From 1b32fbe085d447caa8145c4c62729462932beafe Mon Sep 17 00:00:00 2001 From: Tartalo Date: Sun, 6 Jun 2010 22:33:06 +0200 Subject: Better behaviour for .instance open/close commands For Dungeons: .instance open|close [mapid] normal|heroic|all For Raids: .instance open|close [mapid] normal|heroic|10man|25man|all|10normal|10heroic|25normal|25heroic normal|heroic options will open|close instance in both 10man & 25man at once for selected difficulty 10man|25man options will open|close instance in both normal & heroic modes at once for selected num of players --HG-- branch : trunk --- src/server/game/Chat/Level3.cpp | 60 ++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 9 deletions(-) (limited to 'src/server') diff --git a/src/server/game/Chat/Level3.cpp b/src/server/game/Chat/Level3.cpp index f7ced44922b..8ac26cc5e8f 100644 --- a/src/server/game/Chat/Level3.cpp +++ b/src/server/game/Chat/Level3.cpp @@ -7062,20 +7062,62 @@ bool ChatHandler::HandleInstanceOpenCloseCommand(const char *args,bool open) uint8 status = objmgr.GetAccessRequirement(instance->access_id)->status; uint8 flag = 0; - if (strcmp(instanceModeStr,"normal") || strcmp(instanceModeStr,"10normal")) - flag = DUNGEON_STATUSFLAG_NORMAL; - else if (strcmp(instanceModeStr,"heroic") || strcmp(instanceModeStr,"25normal")) - flag = DUNGEON_STATUSFLAG_HEROIC; - else if (strcmp(instanceModeStr,"10heroic")) - flag = RAID_STATUSFLAG_10MAN_HEROIC; - else if (strcmp(instanceModeStr,"25heroic")) - flag = RAID_STATUSFLAG_25MAN_HEROIC; + const MapEntry *entry = sMapStore.LookupEntry(mapid); + if (!entry) + return false; + + if (entry->IsDungeon()) + { + if (strcmp(instanceModeStr,"normal")) + flag = DUNGEON_STATUSFLAG_NORMAL; + else if (strcmp(instanceModeStr,"heroic")) + flag = DUNGEON_STATUSFLAG_HEROIC; + else if (strcmp(instanceModeStr,"all")) + flag = DUNGEON_STATUSFLAG_NORMAL & DUNGEON_STATUSFLAG_HEROIC; + else + { + PSendSysMessage("Unrecognized difficulty string"); + SetSentErrorMessage(true); + return false; + } + } + + else if (entry->IsRaid()) + { + if (strcmp(instanceModeStr,"normal")) + flag = RAID_STATUSFLAG_10MAN_NORMAL & RAID_STATUSFLAG_25MAN_NORMAL; + else if (strcmp(instanceModeStr,"heroic")) + flag = RAID_STATUSFLAG_10MAN_HEROIC & RAID_STATUSFLAG_25MAN_HEROIC; + else if (strcmp(instanceModeStr,"10man")) + flag = RAID_STATUSFLAG_10MAN_NORMAL & RAID_STATUSFLAG_10MAN_HEROIC; + else if (strcmp(instanceModeStr,"25man")) + flag = RAID_STATUSFLAG_25MAN_NORMAL & RAID_STATUSFLAG_25MAN_HEROIC; + else if (strcmp(instanceModeStr,"heroic")) + flag = RAID_STATUSFLAG_10MAN_HEROIC & RAID_STATUSFLAG_25MAN_HEROIC; + else if (strcmp(instanceModeStr,"10normal")) + flag = DUNGEON_STATUSFLAG_NORMAL; + else if (strcmp(instanceModeStr,"25normal")) + flag = DUNGEON_STATUSFLAG_HEROIC; + else if (strcmp(instanceModeStr,"10heroic")) + flag = RAID_STATUSFLAG_10MAN_HEROIC; + else if (strcmp(instanceModeStr,"25heroic")) + flag = RAID_STATUSFLAG_25MAN_HEROIC; + else if (strcmp(instanceModeStr,"all")) + flag = RAID_STATUSFLAG_10MAN_NORMAL & RAID_STATUSFLAG_10MAN_HEROIC & RAID_STATUSFLAG_25MAN_NORMAL & RAID_STATUSFLAG_25MAN_HEROIC; + else + { + PSendSysMessage("Unrecognized difficulty string"); + SetSentErrorMessage(true); + return false; + } + } else { - PSendSysMessage("Unrecognized difficulty string"); + PSendSysMessage("Map is not a dungeon/raid"); SetSentErrorMessage(true); return false; } + if (open) status |= flag; else -- cgit v1.2.3 From 62200e8d022479ff057b6898380e1dd8374d2ec2 Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 22:55:56 +0200 Subject: * Even more restructuring of the game library. --HG-- branch : trunk --- .../game/AI/AuctionHouseBot/AuctionHouseBot.cpp | 1860 ----- .../game/AI/AuctionHouseBot/AuctionHouseBot.h | 1225 --- src/server/game/AI/CombatAI.cpp | 370 - src/server/game/AI/CombatAI.h | 129 - src/server/game/AI/CoreAI/CombatAI.cpp | 370 + src/server/game/AI/CoreAI/CombatAI.h | 129 + src/server/game/AI/CoreAI/GuardAI.cpp | 137 + src/server/game/AI/CoreAI/GuardAI.h | 55 + src/server/game/AI/CoreAI/PassiveAI.cpp | 81 + src/server/game/AI/CoreAI/PassiveAI.h | 86 + src/server/game/AI/CoreAI/PetAI.cpp | 471 ++ src/server/game/AI/CoreAI/PetAI.h | 64 + src/server/game/AI/CoreAI/ReactorAI.cpp | 59 + src/server/game/AI/CoreAI/ReactorAI.h | 40 + src/server/game/AI/CoreAI/TotemAI.cpp | 116 + src/server/game/AI/CoreAI/TotemAI.h | 47 + src/server/game/AI/CoreAI/UnitAI.cpp | 327 + src/server/game/AI/CoreAI/UnitAI.h | 161 + src/server/game/AI/GuardAI.cpp | 137 - src/server/game/AI/GuardAI.h | 55 - src/server/game/AI/PassiveAI.cpp | 81 - src/server/game/AI/PassiveAI.h | 86 - src/server/game/AI/PetAI.cpp | 471 -- src/server/game/AI/PetAI.h | 64 - src/server/game/AI/ReactorAI.cpp | 59 - src/server/game/AI/ReactorAI.h | 40 - src/server/game/AI/TotemAI.cpp | 116 - src/server/game/AI/TotemAI.h | 47 - src/server/game/AI/UnitAI.cpp | 327 - src/server/game/AI/UnitAI.h | 161 - src/server/game/Account/AccountMgr.cpp | 246 - src/server/game/Account/AccountMgr.h | 64 - src/server/game/Accounts/AccountMgr.cpp | 246 + src/server/game/Accounts/AccountMgr.h | 64 + src/server/game/Addons/AddonHandler.cpp | 234 - src/server/game/Addons/AddonHandler.h | 41 - .../AuctionHouseBot/AuctionHouseBot.cpp | 1860 +++++ .../AuctionHouse/AuctionHouseBot/AuctionHouseBot.h | 1225 +++ .../game/AuctionHouse/AuctionHouseHandler.cpp | 664 -- src/server/game/BattleGrounds/ArenaTeamHandler.cpp | 391 - src/server/game/BattleGrounds/BattleGroundAA.cpp | 84 - src/server/game/BattleGrounds/BattleGroundAA.h | 53 - src/server/game/BattleGrounds/BattleGroundAB.cpp | 715 -- src/server/game/BattleGrounds/BattleGroundAB.h | 301 - src/server/game/BattleGrounds/BattleGroundAV.cpp | 1490 ---- src/server/game/BattleGrounds/BattleGroundAV.h | 1614 ---- src/server/game/BattleGrounds/BattleGroundBE.cpp | 201 - src/server/game/BattleGrounds/BattleGroundBE.h | 78 - src/server/game/BattleGrounds/BattleGroundDS.cpp | 182 - src/server/game/BattleGrounds/BattleGroundDS.h | 89 - src/server/game/BattleGrounds/BattleGroundEY.cpp | 938 --- src/server/game/BattleGrounds/BattleGroundEY.h | 410 - .../game/BattleGrounds/BattleGroundHandler.cpp | 803 -- src/server/game/BattleGrounds/BattleGroundIC.cpp | 132 - src/server/game/BattleGrounds/BattleGroundIC.h | 64 - src/server/game/BattleGrounds/BattleGroundNA.cpp | 177 - src/server/game/BattleGrounds/BattleGroundNA.h | 76 - src/server/game/BattleGrounds/BattleGroundRB.cpp | 81 - src/server/game/BattleGrounds/BattleGroundRB.h | 54 - src/server/game/BattleGrounds/BattleGroundRL.cpp | 176 - src/server/game/BattleGrounds/BattleGroundRL.h | 72 - src/server/game/BattleGrounds/BattleGroundRV.cpp | 234 - src/server/game/BattleGrounds/BattleGroundRV.h | 140 - src/server/game/BattleGrounds/BattleGroundSA.cpp | 822 -- src/server/game/BattleGrounds/BattleGroundSA.h | 384 - src/server/game/BattleGrounds/BattleGroundWS.cpp | 841 -- src/server/game/BattleGrounds/BattleGroundWS.h | 223 - .../game/BattleGrounds/Zones/BattleGroundAA.cpp | 84 + .../game/BattleGrounds/Zones/BattleGroundAA.h | 53 + .../game/BattleGrounds/Zones/BattleGroundAB.cpp | 715 ++ .../game/BattleGrounds/Zones/BattleGroundAB.h | 301 + .../game/BattleGrounds/Zones/BattleGroundAV.cpp | 1490 ++++ .../game/BattleGrounds/Zones/BattleGroundAV.h | 1614 ++++ .../game/BattleGrounds/Zones/BattleGroundBE.cpp | 201 + .../game/BattleGrounds/Zones/BattleGroundBE.h | 78 + .../game/BattleGrounds/Zones/BattleGroundDS.cpp | 182 + .../game/BattleGrounds/Zones/BattleGroundDS.h | 89 + .../game/BattleGrounds/Zones/BattleGroundEY.cpp | 938 +++ .../game/BattleGrounds/Zones/BattleGroundEY.h | 410 + .../game/BattleGrounds/Zones/BattleGroundIC.cpp | 132 + .../game/BattleGrounds/Zones/BattleGroundIC.h | 64 + .../game/BattleGrounds/Zones/BattleGroundNA.cpp | 177 + .../game/BattleGrounds/Zones/BattleGroundNA.h | 76 + .../game/BattleGrounds/Zones/BattleGroundRB.cpp | 81 + .../game/BattleGrounds/Zones/BattleGroundRB.h | 54 + .../game/BattleGrounds/Zones/BattleGroundRL.cpp | 176 + .../game/BattleGrounds/Zones/BattleGroundRL.h | 72 + .../game/BattleGrounds/Zones/BattleGroundRV.cpp | 234 + .../game/BattleGrounds/Zones/BattleGroundRV.h | 140 + .../game/BattleGrounds/Zones/BattleGroundSA.cpp | 822 ++ .../game/BattleGrounds/Zones/BattleGroundSA.h | 384 + .../game/BattleGrounds/Zones/BattleGroundWS.cpp | 841 ++ .../game/BattleGrounds/Zones/BattleGroundWS.h | 223 + src/server/game/Calendar/CalendarHandler.cpp | 318 - src/server/game/Chat/Channel.cpp | 1102 --- src/server/game/Chat/Channel.h | 292 - src/server/game/Chat/ChannelHandler.cpp | 323 - src/server/game/Chat/ChannelMgr.cpp | 110 - src/server/game/Chat/ChannelMgr.h | 57 - src/server/game/Chat/Channels/Channel.cpp | 1102 +++ src/server/game/Chat/Channels/Channel.h | 292 + src/server/game/Chat/Channels/ChannelMgr.cpp | 110 + src/server/game/Chat/Channels/ChannelMgr.h | 57 + src/server/game/Chat/ChatHandler.cpp | 756 -- src/server/game/Chat/Commands/Debugcmds.cpp | 1127 +++ src/server/game/Chat/Commands/Level0.cpp | 295 + src/server/game/Chat/Commands/Level1.cpp | 2960 +++++++ src/server/game/Chat/Commands/Level2.cpp | 4526 ++++++++++ src/server/game/Chat/Commands/Level3.cpp | 7743 +++++++++++++++++ src/server/game/Chat/Debugcmds.cpp | 1127 --- src/server/game/Chat/Level0.cpp | 295 - src/server/game/Chat/Level1.cpp | 2960 ------- src/server/game/Chat/Level2.cpp | 4526 ---------- src/server/game/Chat/Level3.cpp | 7743 ----------------- src/server/game/Combat/CombatHandler.cpp | 91 - src/server/game/Combat/UnitEvents.h | 139 + src/server/game/ConditionMgr/ConditionMgr.cpp | 1145 --- src/server/game/ConditionMgr/ConditionMgr.h | 167 - src/server/game/Conditions/ConditionMgr.cpp | 1145 +++ src/server/game/Conditions/ConditionMgr.h | 167 + src/server/game/DungeonFinding/LFG.h | 72 + src/server/game/DungeonFinding/LFGMgr.cpp | 1100 +++ src/server/game/DungeonFinding/LFGMgr.h | 279 + src/server/game/Entities/Corpse/Corpse.cpp | 243 + src/server/game/Entities/Corpse/Corpse.h | 97 + src/server/game/Entities/Creature/NPCHandler.cpp | 869 -- src/server/game/Entities/Creature/NPCHandler.h | 79 - .../game/Entities/DynamicObject/DynamicObject.cpp | 189 + .../game/Entities/DynamicObject/DynamicObject.h | 61 + src/server/game/Entities/Item/Bag.cpp | 235 - src/server/game/Entities/Item/Bag.h | 75 - src/server/game/Entities/Item/Container/Bag.cpp | 235 + src/server/game/Entities/Item/Container/Bag.h | 75 + src/server/game/Entities/Item/ItemHandler.cpp | 1430 ---- src/server/game/Entities/Object/Corpse.cpp | 243 - src/server/game/Entities/Object/Corpse.h | 97 - src/server/game/Entities/Object/DynamicObject.cpp | 189 - src/server/game/Entities/Object/DynamicObject.h | 61 - src/server/game/Entities/Object/ObjectAccessor.cpp | 375 - src/server/game/Entities/Object/ObjectAccessor.h | 257 - src/server/game/Entities/Object/ObjectMgr.cpp | 8724 -------------------- src/server/game/Entities/Object/ObjectMgr.h | 1085 --- .../game/Entities/Object/ObjectPosSelector.cpp | 157 + .../game/Entities/Object/ObjectPosSelector.h | 155 + src/server/game/Entities/Object/UpdateData.cpp | 157 - src/server/game/Entities/Object/UpdateData.h | 74 - src/server/game/Entities/Object/UpdateFields.h | 435 - src/server/game/Entities/Object/UpdateMask.h | 127 - .../game/Entities/Object/Updates/UpdateData.cpp | 157 + .../game/Entities/Object/Updates/UpdateData.h | 74 + .../game/Entities/Object/Updates/UpdateFields.h | 435 + .../game/Entities/Object/Updates/UpdateMask.h | 127 + src/server/game/Entities/Pet/PetHandler.cpp | 813 -- .../game/Entities/Player/CharacterHandler.cpp | 1406 ---- src/server/game/Entities/Player/DuelHandler.cpp | 84 - src/server/game/Entities/Player/MiscHandler.cpp | 1721 ---- .../game/Entities/Player/PetitionsHandler.cpp | 938 --- src/server/game/Entities/Player/TicketHandler.cpp | 161 - src/server/game/Entities/Player/TradeHandler.cpp | 656 -- .../game/Entities/Player/VoiceChatHandler.cpp | 50 - src/server/game/Entities/Transport/Transports.cpp | 589 ++ src/server/game/Entities/Transport/Transports.h | 108 + src/server/game/Events/GlobalEvents.cpp | 87 - src/server/game/Events/GlobalEvents.h | 32 - src/server/game/Events/UnitEvents.h | 139 - src/server/game/Globals/Formulas.h | 164 - src/server/game/Globals/GlobalEvents.cpp | 87 + src/server/game/Globals/GlobalEvents.h | 32 + src/server/game/Globals/Language.h | 1007 --- src/server/game/Globals/ObjectAccessor.cpp | 375 + src/server/game/Globals/ObjectAccessor.h | 257 + src/server/game/Globals/ObjectMgr.cpp | 8724 ++++++++++++++++++++ src/server/game/Globals/ObjectMgr.h | 1085 +++ src/server/game/Globals/SharedDefines.h | 2772 ------- src/server/game/Groups/GroupHandler.cpp | 940 --- src/server/game/Guilds/GuildHandler.cpp | 1225 --- src/server/game/LookingForGroup/LFG.h | 72 - src/server/game/LookingForGroup/LFGHandler.cpp | 251 - src/server/game/LookingForGroup/LFGMgr.cpp | 1100 --- src/server/game/LookingForGroup/LFGMgr.h | 279 - src/server/game/Loot/LootHandler.cpp | 549 -- src/server/game/Map/Cell/Cell.h | 177 - src/server/game/Map/Cell/CellImpl.h | 297 - src/server/game/Map/Grid/GridDefines.h | 193 - src/server/game/Map/Grid/GridNotifiers.cpp | 353 - src/server/game/Map/Grid/GridNotifiers.h | 1232 --- src/server/game/Map/Grid/GridNotifiersImpl.h | 453 - src/server/game/Map/Grid/GridStates.cpp | 76 - src/server/game/Map/Grid/GridStates.h | 76 - src/server/game/Map/Grid/ObjectGridLoader.cpp | 325 - src/server/game/Map/Grid/ObjectGridLoader.h | 134 - src/server/game/Map/Map.cpp | 3936 --------- src/server/game/Map/Map.h | 689 -- src/server/game/Map/MapInstanced.cpp | 268 - src/server/game/Map/MapInstanced.h | 80 - src/server/game/Map/MapManager.cpp | 395 - src/server/game/Map/MapManager.h | 158 - src/server/game/Map/MapRefManager.h | 45 - src/server/game/Map/MapReference.h | 53 - src/server/game/Map/MapUpdater.cpp | 129 - src/server/game/Map/MapUpdater.h | 40 - src/server/game/Map/ObjectPosSelector.cpp | 157 - src/server/game/Map/ObjectPosSelector.h | 155 - src/server/game/Map/ZoneScript.h | 51 - src/server/game/Maps/Cell/Cell.h | 177 + src/server/game/Maps/Cell/CellImpl.h | 297 + src/server/game/Maps/Grid/GridDefines.h | 193 + src/server/game/Maps/Grid/GridNotifiers.cpp | 353 + src/server/game/Maps/Grid/GridNotifiers.h | 1232 +++ src/server/game/Maps/Grid/GridNotifiersImpl.h | 453 + src/server/game/Maps/Grid/GridStates.cpp | 76 + src/server/game/Maps/Grid/GridStates.h | 76 + src/server/game/Maps/Grid/ObjectGridLoader.cpp | 325 + src/server/game/Maps/Grid/ObjectGridLoader.h | 134 + src/server/game/Maps/Map.cpp | 3936 +++++++++ src/server/game/Maps/Map.h | 689 ++ src/server/game/Maps/MapInstanced.cpp | 268 + src/server/game/Maps/MapInstanced.h | 80 + src/server/game/Maps/MapManager.cpp | 395 + src/server/game/Maps/MapManager.h | 158 + src/server/game/Maps/MapRefManager.h | 45 + src/server/game/Maps/MapReference.h | 53 + src/server/game/Maps/MapUpdater.cpp | 129 + src/server/game/Maps/MapUpdater.h | 40 + src/server/game/Maps/ZoneScript.h | 51 + src/server/game/Miscellaneous/Formulas.h | 164 + src/server/game/Miscellaneous/Language.h | 1007 +++ src/server/game/Miscellaneous/SharedDefines.h | 2772 +++++++ src/server/game/Movement/MovementGenerator.cpp | 27 + src/server/game/Movement/MovementGenerator.h | 102 + src/server/game/Movement/MovementGeneratorImpl.h | 34 + .../MovementGenerators/MovementGenerator.cpp | 27 - .../MovementGenerators/MovementGenerator.h | 102 - .../MovementGenerators/MovementGeneratorImpl.h | 34 - src/server/game/Movement/MovementHandler.cpp | 746 -- src/server/game/Movement/Path.h | 88 - src/server/game/Movement/TaxiHandler.cpp | 287 - src/server/game/Movement/Transports.cpp | 589 -- src/server/game/Movement/Transports.h | 108 - src/server/game/Movement/WaypointManager.cpp | 152 - src/server/game/Movement/WaypointManager.h | 68 - src/server/game/Movement/Waypoints/Path.h | 88 + .../game/Movement/Waypoints/WaypointManager.cpp | 152 + .../game/Movement/Waypoints/WaypointManager.h | 68 + src/server/game/Opcodes/Opcodes.cpp | 1338 --- src/server/game/Opcodes/Opcodes.h | 1378 ---- src/server/game/OutdoorPvP/OutdoorPvPEP.cpp | 765 -- src/server/game/OutdoorPvP/OutdoorPvPEP.h | 280 - src/server/game/OutdoorPvP/OutdoorPvPHP.cpp | 332 - src/server/game/OutdoorPvP/OutdoorPvPHP.h | 118 - src/server/game/OutdoorPvP/OutdoorPvPNA.cpp | 664 -- src/server/game/OutdoorPvP/OutdoorPvPNA.h | 297 - src/server/game/OutdoorPvP/OutdoorPvPSI.cpp | 227 - src/server/game/OutdoorPvP/OutdoorPvPSI.h | 75 - src/server/game/OutdoorPvP/OutdoorPvPTF.cpp | 310 - src/server/game/OutdoorPvP/OutdoorPvPTF.h | 117 - src/server/game/OutdoorPvP/OutdoorPvPZM.cpp | 423 - src/server/game/OutdoorPvP/OutdoorPvPZM.h | 219 - src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.cpp | 765 ++ src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.h | 280 + src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.cpp | 332 + src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.h | 118 + src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.cpp | 664 ++ src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.h | 297 + src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.cpp | 227 + src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.h | 75 + src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.cpp | 310 + src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.h | 117 + src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.cpp | 423 + src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.h | 219 + src/server/game/PrecompiledHeaders/ScriptedPch.cpp | 6 + src/server/game/PrecompiledHeaders/ScriptedPch.h | 32 + src/server/game/Quests/QueryHandler.cpp | 539 -- src/server/game/Quests/QuestHandler.cpp | 721 -- src/server/game/ScriptMgr/ScriptLoader.cpp | 1023 --- src/server/game/ScriptMgr/ScriptLoader.h | 10 - src/server/game/ScriptMgr/ScriptMgr.cpp | 549 -- src/server/game/ScriptMgr/ScriptMgr.h | 163 - src/server/game/ScriptMgr/ScriptSystem.cpp | 248 - src/server/game/ScriptMgr/ScriptSystem.h | 100 - src/server/game/ScriptMgr/ScriptedPch.cpp | 6 - src/server/game/ScriptMgr/ScriptedPch.h | 32 - src/server/game/Scripting/ScriptLoader.cpp | 1023 +++ src/server/game/Scripting/ScriptLoader.h | 10 + src/server/game/Scripting/ScriptMgr.cpp | 549 ++ src/server/game/Scripting/ScriptMgr.h | 163 + src/server/game/Scripting/ScriptSystem.cpp | 248 + src/server/game/Scripting/ScriptSystem.h | 100 + .../game/Server/Protocol/Handlers/AddonHandler.cpp | 234 + .../game/Server/Protocol/Handlers/AddonHandler.h | 41 + .../Server/Protocol/Handlers/ArenaTeamHandler.cpp | 391 + .../Protocol/Handlers/AuctionHouseHandler.cpp | 664 ++ .../Protocol/Handlers/BattleGroundHandler.cpp | 803 ++ .../Server/Protocol/Handlers/CalendarHandler.cpp | 318 + .../Server/Protocol/Handlers/ChannelHandler.cpp | 323 + .../Server/Protocol/Handlers/CharacterHandler.cpp | 1406 ++++ .../game/Server/Protocol/Handlers/ChatHandler.cpp | 756 ++ .../Server/Protocol/Handlers/CombatHandler.cpp | 91 + .../game/Server/Protocol/Handlers/DuelHandler.cpp | 84 + .../game/Server/Protocol/Handlers/GroupHandler.cpp | 940 +++ .../game/Server/Protocol/Handlers/GuildHandler.cpp | 1225 +++ .../game/Server/Protocol/Handlers/ItemHandler.cpp | 1430 ++++ .../game/Server/Protocol/Handlers/LFGHandler.cpp | 251 + .../game/Server/Protocol/Handlers/LootHandler.cpp | 549 ++ .../game/Server/Protocol/Handlers/MiscHandler.cpp | 1721 ++++ .../Server/Protocol/Handlers/MovementHandler.cpp | 746 ++ .../game/Server/Protocol/Handlers/NPCHandler.cpp | 869 ++ .../game/Server/Protocol/Handlers/NPCHandler.h | 79 + .../game/Server/Protocol/Handlers/PetHandler.cpp | 813 ++ .../Server/Protocol/Handlers/PetitionsHandler.cpp | 938 +++ .../game/Server/Protocol/Handlers/QueryHandler.cpp | 539 ++ .../game/Server/Protocol/Handlers/QuestHandler.cpp | 721 ++ .../game/Server/Protocol/Handlers/SkillHandler.cpp | 95 + .../game/Server/Protocol/Handlers/SpellHandler.cpp | 649 ++ .../game/Server/Protocol/Handlers/TaxiHandler.cpp | 287 + .../Server/Protocol/Handlers/TicketHandler.cpp | 161 + .../game/Server/Protocol/Handlers/TradeHandler.cpp | 656 ++ .../Server/Protocol/Handlers/VoiceChatHandler.cpp | 50 + src/server/game/Server/Protocol/Opcodes.cpp | 1338 +++ src/server/game/Server/Protocol/Opcodes.h | 1378 ++++ src/server/game/Server/Protocol/WorldLog.cpp | 122 + src/server/game/Server/Protocol/WorldLog.h | 63 + src/server/game/Server/WorldSession.cpp | 959 +++ src/server/game/Server/WorldSession.h | 829 ++ src/server/game/Server/WorldSocket.cpp | 1064 +++ src/server/game/Server/WorldSocket.h | 223 + src/server/game/Server/WorldSocketMgr.cpp | 369 + src/server/game/Server/WorldSocketMgr.h | 80 + src/server/game/Skills/SkillHandler.cpp | 95 - src/server/game/Spells/SpellHandler.cpp | 649 -- src/server/game/World/WorldLog.cpp | 122 - src/server/game/World/WorldLog.h | 63 - src/server/game/World/WorldSession.cpp | 959 --- src/server/game/World/WorldSession.h | 829 -- src/server/game/World/WorldSocket.cpp | 1064 --- src/server/game/World/WorldSocket.h | 223 - src/server/game/World/WorldSocketMgr.cpp | 369 - src/server/game/World/WorldSocketMgr.h | 80 - 338 files changed, 93332 insertions(+), 93332 deletions(-) delete mode 100644 src/server/game/AI/AuctionHouseBot/AuctionHouseBot.cpp delete mode 100644 src/server/game/AI/AuctionHouseBot/AuctionHouseBot.h delete mode 100644 src/server/game/AI/CombatAI.cpp delete mode 100644 src/server/game/AI/CombatAI.h create mode 100644 src/server/game/AI/CoreAI/CombatAI.cpp create mode 100644 src/server/game/AI/CoreAI/CombatAI.h create mode 100644 src/server/game/AI/CoreAI/GuardAI.cpp create mode 100644 src/server/game/AI/CoreAI/GuardAI.h create mode 100644 src/server/game/AI/CoreAI/PassiveAI.cpp create mode 100644 src/server/game/AI/CoreAI/PassiveAI.h create mode 100644 src/server/game/AI/CoreAI/PetAI.cpp create mode 100644 src/server/game/AI/CoreAI/PetAI.h create mode 100644 src/server/game/AI/CoreAI/ReactorAI.cpp create mode 100644 src/server/game/AI/CoreAI/ReactorAI.h create mode 100644 src/server/game/AI/CoreAI/TotemAI.cpp create mode 100644 src/server/game/AI/CoreAI/TotemAI.h create mode 100644 src/server/game/AI/CoreAI/UnitAI.cpp create mode 100644 src/server/game/AI/CoreAI/UnitAI.h delete mode 100644 src/server/game/AI/GuardAI.cpp delete mode 100644 src/server/game/AI/GuardAI.h delete mode 100644 src/server/game/AI/PassiveAI.cpp delete mode 100644 src/server/game/AI/PassiveAI.h delete mode 100644 src/server/game/AI/PetAI.cpp delete mode 100644 src/server/game/AI/PetAI.h delete mode 100644 src/server/game/AI/ReactorAI.cpp delete mode 100644 src/server/game/AI/ReactorAI.h delete mode 100644 src/server/game/AI/TotemAI.cpp delete mode 100644 src/server/game/AI/TotemAI.h delete mode 100644 src/server/game/AI/UnitAI.cpp delete mode 100644 src/server/game/AI/UnitAI.h delete mode 100644 src/server/game/Account/AccountMgr.cpp delete mode 100644 src/server/game/Account/AccountMgr.h create mode 100644 src/server/game/Accounts/AccountMgr.cpp create mode 100644 src/server/game/Accounts/AccountMgr.h delete mode 100644 src/server/game/Addons/AddonHandler.cpp delete mode 100644 src/server/game/Addons/AddonHandler.h create mode 100644 src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.cpp create mode 100644 src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.h delete mode 100644 src/server/game/AuctionHouse/AuctionHouseHandler.cpp delete mode 100644 src/server/game/BattleGrounds/ArenaTeamHandler.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundAA.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundAA.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundAB.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundAB.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundAV.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundAV.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundBE.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundBE.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundDS.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundDS.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundEY.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundEY.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundHandler.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundIC.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundIC.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundNA.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundNA.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundRB.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundRB.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundRL.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundRL.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundRV.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundRV.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundSA.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundSA.h delete mode 100644 src/server/game/BattleGrounds/BattleGroundWS.cpp delete mode 100644 src/server/game/BattleGrounds/BattleGroundWS.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundAA.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundAA.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundAB.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundAB.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundAV.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundAV.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundBE.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundBE.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundDS.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundDS.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundEY.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundEY.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundIC.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundIC.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundNA.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundNA.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundRB.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundRB.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundRL.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundRL.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundRV.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundRV.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundSA.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundSA.h create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundWS.cpp create mode 100644 src/server/game/BattleGrounds/Zones/BattleGroundWS.h delete mode 100644 src/server/game/Calendar/CalendarHandler.cpp delete mode 100644 src/server/game/Chat/Channel.cpp delete mode 100644 src/server/game/Chat/Channel.h delete mode 100644 src/server/game/Chat/ChannelHandler.cpp delete mode 100644 src/server/game/Chat/ChannelMgr.cpp delete mode 100644 src/server/game/Chat/ChannelMgr.h create mode 100644 src/server/game/Chat/Channels/Channel.cpp create mode 100644 src/server/game/Chat/Channels/Channel.h create mode 100644 src/server/game/Chat/Channels/ChannelMgr.cpp create mode 100644 src/server/game/Chat/Channels/ChannelMgr.h delete mode 100644 src/server/game/Chat/ChatHandler.cpp create mode 100644 src/server/game/Chat/Commands/Debugcmds.cpp create mode 100644 src/server/game/Chat/Commands/Level0.cpp create mode 100644 src/server/game/Chat/Commands/Level1.cpp create mode 100644 src/server/game/Chat/Commands/Level2.cpp create mode 100644 src/server/game/Chat/Commands/Level3.cpp delete mode 100644 src/server/game/Chat/Debugcmds.cpp delete mode 100644 src/server/game/Chat/Level0.cpp delete mode 100644 src/server/game/Chat/Level1.cpp delete mode 100644 src/server/game/Chat/Level2.cpp delete mode 100644 src/server/game/Chat/Level3.cpp delete mode 100644 src/server/game/Combat/CombatHandler.cpp create mode 100644 src/server/game/Combat/UnitEvents.h delete mode 100644 src/server/game/ConditionMgr/ConditionMgr.cpp delete mode 100644 src/server/game/ConditionMgr/ConditionMgr.h create mode 100644 src/server/game/Conditions/ConditionMgr.cpp create mode 100644 src/server/game/Conditions/ConditionMgr.h create mode 100644 src/server/game/DungeonFinding/LFG.h create mode 100644 src/server/game/DungeonFinding/LFGMgr.cpp create mode 100644 src/server/game/DungeonFinding/LFGMgr.h create mode 100644 src/server/game/Entities/Corpse/Corpse.cpp create mode 100644 src/server/game/Entities/Corpse/Corpse.h delete mode 100644 src/server/game/Entities/Creature/NPCHandler.cpp delete mode 100644 src/server/game/Entities/Creature/NPCHandler.h create mode 100644 src/server/game/Entities/DynamicObject/DynamicObject.cpp create mode 100644 src/server/game/Entities/DynamicObject/DynamicObject.h delete mode 100644 src/server/game/Entities/Item/Bag.cpp delete mode 100644 src/server/game/Entities/Item/Bag.h create mode 100644 src/server/game/Entities/Item/Container/Bag.cpp create mode 100644 src/server/game/Entities/Item/Container/Bag.h delete mode 100644 src/server/game/Entities/Item/ItemHandler.cpp delete mode 100644 src/server/game/Entities/Object/Corpse.cpp delete mode 100644 src/server/game/Entities/Object/Corpse.h delete mode 100644 src/server/game/Entities/Object/DynamicObject.cpp delete mode 100644 src/server/game/Entities/Object/DynamicObject.h delete mode 100644 src/server/game/Entities/Object/ObjectAccessor.cpp delete mode 100644 src/server/game/Entities/Object/ObjectAccessor.h delete mode 100644 src/server/game/Entities/Object/ObjectMgr.cpp delete mode 100644 src/server/game/Entities/Object/ObjectMgr.h create mode 100644 src/server/game/Entities/Object/ObjectPosSelector.cpp create mode 100644 src/server/game/Entities/Object/ObjectPosSelector.h delete mode 100644 src/server/game/Entities/Object/UpdateData.cpp delete mode 100644 src/server/game/Entities/Object/UpdateData.h delete mode 100644 src/server/game/Entities/Object/UpdateFields.h delete mode 100644 src/server/game/Entities/Object/UpdateMask.h create mode 100644 src/server/game/Entities/Object/Updates/UpdateData.cpp create mode 100644 src/server/game/Entities/Object/Updates/UpdateData.h create mode 100644 src/server/game/Entities/Object/Updates/UpdateFields.h create mode 100644 src/server/game/Entities/Object/Updates/UpdateMask.h delete mode 100644 src/server/game/Entities/Pet/PetHandler.cpp delete mode 100644 src/server/game/Entities/Player/CharacterHandler.cpp delete mode 100644 src/server/game/Entities/Player/DuelHandler.cpp delete mode 100644 src/server/game/Entities/Player/MiscHandler.cpp delete mode 100644 src/server/game/Entities/Player/PetitionsHandler.cpp delete mode 100644 src/server/game/Entities/Player/TicketHandler.cpp delete mode 100644 src/server/game/Entities/Player/TradeHandler.cpp delete mode 100644 src/server/game/Entities/Player/VoiceChatHandler.cpp create mode 100644 src/server/game/Entities/Transport/Transports.cpp create mode 100644 src/server/game/Entities/Transport/Transports.h delete mode 100644 src/server/game/Events/GlobalEvents.cpp delete mode 100644 src/server/game/Events/GlobalEvents.h delete mode 100644 src/server/game/Events/UnitEvents.h delete mode 100644 src/server/game/Globals/Formulas.h create mode 100644 src/server/game/Globals/GlobalEvents.cpp create mode 100644 src/server/game/Globals/GlobalEvents.h delete mode 100644 src/server/game/Globals/Language.h create mode 100644 src/server/game/Globals/ObjectAccessor.cpp create mode 100644 src/server/game/Globals/ObjectAccessor.h create mode 100644 src/server/game/Globals/ObjectMgr.cpp create mode 100644 src/server/game/Globals/ObjectMgr.h delete mode 100644 src/server/game/Globals/SharedDefines.h delete mode 100644 src/server/game/Groups/GroupHandler.cpp delete mode 100644 src/server/game/Guilds/GuildHandler.cpp delete mode 100644 src/server/game/LookingForGroup/LFG.h delete mode 100644 src/server/game/LookingForGroup/LFGHandler.cpp delete mode 100644 src/server/game/LookingForGroup/LFGMgr.cpp delete mode 100644 src/server/game/LookingForGroup/LFGMgr.h delete mode 100644 src/server/game/Loot/LootHandler.cpp delete mode 100644 src/server/game/Map/Cell/Cell.h delete mode 100644 src/server/game/Map/Cell/CellImpl.h delete mode 100644 src/server/game/Map/Grid/GridDefines.h delete mode 100644 src/server/game/Map/Grid/GridNotifiers.cpp delete mode 100644 src/server/game/Map/Grid/GridNotifiers.h delete mode 100644 src/server/game/Map/Grid/GridNotifiersImpl.h delete mode 100644 src/server/game/Map/Grid/GridStates.cpp delete mode 100644 src/server/game/Map/Grid/GridStates.h delete mode 100644 src/server/game/Map/Grid/ObjectGridLoader.cpp delete mode 100644 src/server/game/Map/Grid/ObjectGridLoader.h delete mode 100644 src/server/game/Map/Map.cpp delete mode 100644 src/server/game/Map/Map.h delete mode 100644 src/server/game/Map/MapInstanced.cpp delete mode 100644 src/server/game/Map/MapInstanced.h delete mode 100644 src/server/game/Map/MapManager.cpp delete mode 100644 src/server/game/Map/MapManager.h delete mode 100644 src/server/game/Map/MapRefManager.h delete mode 100644 src/server/game/Map/MapReference.h delete mode 100644 src/server/game/Map/MapUpdater.cpp delete mode 100644 src/server/game/Map/MapUpdater.h delete mode 100644 src/server/game/Map/ObjectPosSelector.cpp delete mode 100644 src/server/game/Map/ObjectPosSelector.h delete mode 100644 src/server/game/Map/ZoneScript.h create mode 100644 src/server/game/Maps/Cell/Cell.h create mode 100644 src/server/game/Maps/Cell/CellImpl.h create mode 100644 src/server/game/Maps/Grid/GridDefines.h create mode 100644 src/server/game/Maps/Grid/GridNotifiers.cpp create mode 100644 src/server/game/Maps/Grid/GridNotifiers.h create mode 100644 src/server/game/Maps/Grid/GridNotifiersImpl.h create mode 100644 src/server/game/Maps/Grid/GridStates.cpp create mode 100644 src/server/game/Maps/Grid/GridStates.h create mode 100644 src/server/game/Maps/Grid/ObjectGridLoader.cpp create mode 100644 src/server/game/Maps/Grid/ObjectGridLoader.h create mode 100644 src/server/game/Maps/Map.cpp create mode 100644 src/server/game/Maps/Map.h create mode 100644 src/server/game/Maps/MapInstanced.cpp create mode 100644 src/server/game/Maps/MapInstanced.h create mode 100644 src/server/game/Maps/MapManager.cpp create mode 100644 src/server/game/Maps/MapManager.h create mode 100644 src/server/game/Maps/MapRefManager.h create mode 100644 src/server/game/Maps/MapReference.h create mode 100644 src/server/game/Maps/MapUpdater.cpp create mode 100644 src/server/game/Maps/MapUpdater.h create mode 100644 src/server/game/Maps/ZoneScript.h create mode 100644 src/server/game/Miscellaneous/Formulas.h create mode 100644 src/server/game/Miscellaneous/Language.h create mode 100644 src/server/game/Miscellaneous/SharedDefines.h create mode 100644 src/server/game/Movement/MovementGenerator.cpp create mode 100644 src/server/game/Movement/MovementGenerator.h create mode 100644 src/server/game/Movement/MovementGeneratorImpl.h delete mode 100644 src/server/game/Movement/MovementGenerators/MovementGenerator.cpp delete mode 100644 src/server/game/Movement/MovementGenerators/MovementGenerator.h delete mode 100644 src/server/game/Movement/MovementGenerators/MovementGeneratorImpl.h delete mode 100644 src/server/game/Movement/MovementHandler.cpp delete mode 100644 src/server/game/Movement/Path.h delete mode 100644 src/server/game/Movement/TaxiHandler.cpp delete mode 100644 src/server/game/Movement/Transports.cpp delete mode 100644 src/server/game/Movement/Transports.h delete mode 100644 src/server/game/Movement/WaypointManager.cpp delete mode 100644 src/server/game/Movement/WaypointManager.h create mode 100644 src/server/game/Movement/Waypoints/Path.h create mode 100644 src/server/game/Movement/Waypoints/WaypointManager.cpp create mode 100644 src/server/game/Movement/Waypoints/WaypointManager.h delete mode 100644 src/server/game/Opcodes/Opcodes.cpp delete mode 100644 src/server/game/Opcodes/Opcodes.h delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPEP.cpp delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPEP.h delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPHP.cpp delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPHP.h delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPNA.cpp delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPNA.h delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPSI.cpp delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPSI.h delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPTF.cpp delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPTF.h delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPZM.cpp delete mode 100644 src/server/game/OutdoorPvP/OutdoorPvPZM.h create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.cpp create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.h create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.cpp create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.h create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.cpp create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.h create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.cpp create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.h create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.cpp create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.h create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.cpp create mode 100644 src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.h create mode 100644 src/server/game/PrecompiledHeaders/ScriptedPch.cpp create mode 100644 src/server/game/PrecompiledHeaders/ScriptedPch.h delete mode 100644 src/server/game/Quests/QueryHandler.cpp delete mode 100644 src/server/game/Quests/QuestHandler.cpp delete mode 100644 src/server/game/ScriptMgr/ScriptLoader.cpp delete mode 100644 src/server/game/ScriptMgr/ScriptLoader.h delete mode 100644 src/server/game/ScriptMgr/ScriptMgr.cpp delete mode 100644 src/server/game/ScriptMgr/ScriptMgr.h delete mode 100644 src/server/game/ScriptMgr/ScriptSystem.cpp delete mode 100644 src/server/game/ScriptMgr/ScriptSystem.h delete mode 100644 src/server/game/ScriptMgr/ScriptedPch.cpp delete mode 100644 src/server/game/ScriptMgr/ScriptedPch.h create mode 100644 src/server/game/Scripting/ScriptLoader.cpp create mode 100644 src/server/game/Scripting/ScriptLoader.h create mode 100644 src/server/game/Scripting/ScriptMgr.cpp create mode 100644 src/server/game/Scripting/ScriptMgr.h create mode 100644 src/server/game/Scripting/ScriptSystem.cpp create mode 100644 src/server/game/Scripting/ScriptSystem.h create mode 100644 src/server/game/Server/Protocol/Handlers/AddonHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/AddonHandler.h create mode 100644 src/server/game/Server/Protocol/Handlers/ArenaTeamHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/CalendarHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/ChatHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/CombatHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/DuelHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/GroupHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/GuildHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/ItemHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/LFGHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/LootHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/MiscHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/MovementHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/NPCHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/NPCHandler.h create mode 100644 src/server/game/Server/Protocol/Handlers/PetHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/QueryHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/QuestHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/SkillHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/SpellHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/TicketHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/TradeHandler.cpp create mode 100644 src/server/game/Server/Protocol/Handlers/VoiceChatHandler.cpp create mode 100644 src/server/game/Server/Protocol/Opcodes.cpp create mode 100644 src/server/game/Server/Protocol/Opcodes.h create mode 100644 src/server/game/Server/Protocol/WorldLog.cpp create mode 100644 src/server/game/Server/Protocol/WorldLog.h create mode 100644 src/server/game/Server/WorldSession.cpp create mode 100644 src/server/game/Server/WorldSession.h create mode 100644 src/server/game/Server/WorldSocket.cpp create mode 100644 src/server/game/Server/WorldSocket.h create mode 100644 src/server/game/Server/WorldSocketMgr.cpp create mode 100644 src/server/game/Server/WorldSocketMgr.h delete mode 100644 src/server/game/Skills/SkillHandler.cpp delete mode 100644 src/server/game/Spells/SpellHandler.cpp delete mode 100644 src/server/game/World/WorldLog.cpp delete mode 100644 src/server/game/World/WorldLog.h delete mode 100644 src/server/game/World/WorldSession.cpp delete mode 100644 src/server/game/World/WorldSession.h delete mode 100644 src/server/game/World/WorldSocket.cpp delete mode 100644 src/server/game/World/WorldSocket.h delete mode 100644 src/server/game/World/WorldSocketMgr.cpp delete mode 100644 src/server/game/World/WorldSocketMgr.h (limited to 'src/server') diff --git a/src/server/game/AI/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AI/AuctionHouseBot/AuctionHouseBot.cpp deleted file mode 100644 index ebbf48e6476..00000000000 --- a/src/server/game/AI/AuctionHouseBot/AuctionHouseBot.cpp +++ /dev/null @@ -1,1860 +0,0 @@ -#include "ObjectMgr.h" -#include "AuctionHouseMgr.h" -#include "AuctionHouseBot.h" -#include - -#include "Policies/SingletonImp.h" -INSTANTIATE_SINGLETON_1(AuctionHouseBot); - -using namespace std; -vector npcItems; -vector lootItems; -vector greyTradeGoodsBin; -vector whiteTradeGoodsBin; -vector greenTradeGoodsBin; -vector blueTradeGoodsBin; -vector purpleTradeGoodsBin; -vector orangeTradeGoodsBin; -vector yellowTradeGoodsBin; -vector greyItemsBin; -vector whiteItemsBin; -vector greenItemsBin; -vector blueItemsBin; -vector purpleItemsBin; -vector orangeItemsBin; -vector yellowItemsBin; -AuctionHouseBot::AuctionHouseBot() -{ - debug_Out = false; - debug_Out_Filters = false; - AHBSeller = false; - AHBBuyer = false; - - //Begin Filters - - Vendor_Items = false; - Loot_Items = false; - Other_Items = false; - Vendor_TGs = false; - Loot_TGs = false; - Other_TGs = false; - - No_Bind = false; - Bind_When_Picked_Up = false; - Bind_When_Equipped = false; - Bind_When_Use = false; - Bind_Quest_Item = false; - - DisableBeta_PTR_Unused = false; - DisablePermEnchant = false; - DisableConjured = false; - DisableGems = false; - DisableMoney = false; - DisableMoneyLoot = false; - DisableLootable = false; - DisableKeys = false; - DisableDuration = false; - DisableBOP_Or_Quest_NoReqLevel = false; - - DisableWarriorItems = false; - DisablePaladinItems = false; - DisableHunterItems = false; - DisableRogueItems = false; - DisablePriestItems = false; - DisableDKItems = false; - DisableShamanItems = false; - DisableMageItems = false; - DisableWarlockItems = false; - DisableUnusedClassItems = false; - DisableDruidItems = false; - - DisableItemsBelowLevel = 0; - DisableItemsAboveLevel = 0; - DisableTGsBelowLevel = 0; - DisableTGsAboveLevel = 0; - DisableItemsBelowGUID = 0; - DisableItemsAboveGUID = 0; - DisableTGsBelowGUID = 0; - DisableTGsAboveGUID = 0; - DisableItemsBelowReqLevel = 0; - DisableItemsAboveReqLevel = 0; - DisableTGsBelowReqLevel = 0; - DisableTGsAboveReqLevel = 0; - DisableItemsBelowReqSkillRank = 0; - DisableItemsAboveReqSkillRank = 0; - DisableTGsBelowReqSkillRank = 0; - DisableTGsAboveReqSkillRank = 0; - - //End Filters - - _lastrun_a = time(NULL); - _lastrun_h = time(NULL); - _lastrun_n = time(NULL); - - AllianceConfig = AHBConfig(2); - HordeConfig = AHBConfig(6); - NeutralConfig = AHBConfig(7); -} - -AuctionHouseBot::~AuctionHouseBot() -{ -} - -void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) -{ - if (!AHBSeller) - { - if (debug_Out) sLog.outError("AHSeller: Disabled"); - return; - } - - uint32 minItems = config->GetMinItems(); - uint32 maxItems = config->GetMaxItems(); - - if (maxItems == 0) - { - //if (debug_Out) sLog.outString("AHSeller: Auctions disabled"); - return; - } - - AuctionHouseEntry const* ahEntry = auctionmgr.GetAuctionHouseEntry(config->GetAHFID()); - if (!ahEntry) - { - return; - } - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(config->GetAHFID()); - if (!auctionHouse) - { - return; - } - - uint32 auctions = auctionHouse->Getcount(); - - if (auctions >= minItems) - { - //if (debug_Out) sLog.outString("AHSeller: Auctions above minimum"); - return; - } - - if (auctions >= maxItems) - { - //if (debug_Out) sLog.outString("AHSeller: Auctions at or above maximum"); - return; - } - - uint32 items = 0; - if ((maxItems - auctions) >= ItemsPerCycle) - items = ItemsPerCycle; - else - items = (maxItems - auctions); - - if (debug_Out) sLog.outString("AHSeller: Adding %u Auctions", items); - - uint32 AuctioneerGUID = 0; - - switch (config->GetAHID()) - { - case 2: - AuctioneerGUID = 79707; //Human in stormwind. - break; - case 6: - AuctioneerGUID = 4656; //orc in Orgrimmar - break; - case 7: - AuctioneerGUID = 23442; //goblin in GZ - break; - default: - if (debug_Out) sLog.outError("AHSeller: GetAHID() - Default switch reached"); - AuctioneerGUID = 23442; //default to neutral 7 - break; - } - - if (debug_Out) sLog.outString("AHSeller: Current Auctineer GUID is %u", AuctioneerGUID); - - uint32 greyTGcount = config->GetPercents(AHB_GREY_TG); - uint32 whiteTGcount = config->GetPercents(AHB_WHITE_TG); - uint32 greenTGcount = config->GetPercents(AHB_GREEN_TG); - uint32 blueTGcount = config->GetPercents(AHB_BLUE_TG); - uint32 purpleTGcount = config->GetPercents(AHB_PURPLE_TG); - uint32 orangeTGcount = config->GetPercents(AHB_ORANGE_TG); - uint32 yellowTGcount = config->GetPercents(AHB_YELLOW_TG); - uint32 greyIcount = config->GetPercents(AHB_GREY_I); - uint32 whiteIcount = config->GetPercents(AHB_WHITE_I); - uint32 greenIcount = config->GetPercents(AHB_GREEN_I); - uint32 blueIcount = config->GetPercents(AHB_BLUE_I); - uint32 purpleIcount = config->GetPercents(AHB_PURPLE_I); - uint32 orangeIcount = config->GetPercents(AHB_ORANGE_I); - uint32 yellowIcount = config->GetPercents(AHB_YELLOW_I); -/* uint32 total = greyTGcount + whiteTGcount + greenTGcount + blueTGcount - + purpleTGcount + orangeTGcount + yellowTGcount - + whiteIcount + greenIcount + blueIcount + purpleIcount - + orangeIcount + yellowIcount; -*/ - uint32 greyTGoods = config->GetItemCounts(AHB_GREY_TG); - uint32 whiteTGoods = config->GetItemCounts(AHB_WHITE_TG); - uint32 greenTGoods = config->GetItemCounts(AHB_GREEN_TG); - uint32 blueTGoods = config->GetItemCounts(AHB_BLUE_TG); - uint32 purpleTGoods = config->GetItemCounts(AHB_PURPLE_TG); - uint32 orangeTGoods = config->GetItemCounts(AHB_ORANGE_TG); - uint32 yellowTGoods = config->GetItemCounts(AHB_YELLOW_TG); - - uint32 greyItems = config->GetItemCounts(AHB_GREY_I); - uint32 whiteItems = config->GetItemCounts(AHB_WHITE_I); - uint32 greenItems = config->GetItemCounts(AHB_GREEN_I); - uint32 blueItems = config->GetItemCounts(AHB_BLUE_I); - uint32 purpleItems = config->GetItemCounts(AHB_PURPLE_I); - uint32 orangeItems = config->GetItemCounts(AHB_ORANGE_I); - uint32 yellowItems = config->GetItemCounts(AHB_YELLOW_I); - if (debug_Out) sLog.outString("AHSeller: %u items", items); - - // only insert a few at a time, so as not to peg the processor - for (uint32 cnt = 1; cnt <= items; cnt++) - { - if (debug_Out) sLog.outString("AHSeller: %u count", cnt); - uint32 itemID = 0; - uint32 itemColor = 99; - uint32 loopbreaker = 0; - while (itemID == 0 && loopbreaker <= 50) - { - ++loopbreaker; - uint32 choice = urand(0, 13); - itemColor = choice; - switch (choice) - { - case 0: - { - if ((greyItemsBin.size() > 0) && (greyItems < greyIcount)) - itemID = greyItemsBin[urand(0, greyItemsBin.size() - 1)]; - else continue; - break; - } - case 1: - { - if ((whiteItemsBin.size() > 0) && (whiteItems < whiteIcount)) - itemID = whiteItemsBin[urand(0, whiteItemsBin.size() - 1)]; - else continue; - break; - } - case 2: - { - if ((greenItemsBin.size() > 0) && (greenItems < greenIcount)) - itemID = greenItemsBin[urand(0, greenItemsBin.size() - 1)]; - else continue; - break; - } - case 3: - { - if ((blueItemsBin.size() > 0) && (blueItems < blueIcount)) - itemID = blueItemsBin[urand(0, blueItemsBin.size() - 1)]; - else continue; - break; - } - case 4: - { - if ((purpleItemsBin.size() > 0) && (purpleItems < purpleIcount)) - itemID = purpleItemsBin[urand(0, purpleItemsBin.size() - 1)]; - else continue; - break; - } - case 5: - { - if ((orangeItemsBin.size() > 0) && (orangeItems < orangeIcount)) - itemID = orangeItemsBin[urand(0, orangeItemsBin.size() - 1)]; - else continue; - break; - } - case 6: - { - if ((yellowItemsBin.size() > 0) && (yellowItems < yellowIcount)) - itemID = yellowItemsBin[urand(0, yellowItemsBin.size() - 1)]; - else continue; - break; - } - case 7: - { - if ((greyTradeGoodsBin.size() > 0) && (greyTGoods < greyTGcount)) - itemID = greyTradeGoodsBin[urand(0, greyTradeGoodsBin.size() - 1)]; - else continue; - break; - } - case 8: - { - if ((whiteTradeGoodsBin.size() > 0) && (whiteTGoods < whiteTGcount)) - itemID = whiteTradeGoodsBin[urand(0, whiteTradeGoodsBin.size() - 1)]; - else continue; - break; - } - case 9: - { - if ((greenTradeGoodsBin.size() > 0) && (greenTGoods < greenTGcount)) - itemID = greenTradeGoodsBin[urand(0, greenTradeGoodsBin.size() - 1)]; - else continue; - break; - } - case 10: - { - if ((blueTradeGoodsBin.size() > 0) && (blueTGoods < blueTGcount)) - itemID = blueTradeGoodsBin[urand(0, blueTradeGoodsBin.size() - 1)]; - else continue; - break; - } - case 11: - { - if ((purpleTradeGoodsBin.size() > 0) && (purpleTGoods < purpleTGcount)) - itemID = purpleTradeGoodsBin[urand(0, purpleTradeGoodsBin.size() - 1)]; - else continue; - break; - } - case 12: - { - if ((orangeTradeGoodsBin.size() > 0) && (orangeTGoods < orangeTGcount)) - itemID = orangeTradeGoodsBin[urand(0, orangeTradeGoodsBin.size() - 1)]; - else continue; - break; - } - case 13: - { - if ((yellowTradeGoodsBin.size() > 0) && (yellowTGoods < yellowTGcount)) - itemID = yellowTradeGoodsBin[urand(0, yellowTradeGoodsBin.size() - 1)]; - else continue; - break; - } - default: - { - if (debug_Out) sLog.outError("AHSeller: itemID Switch - Default Reached"); - break; - } - } - - if (itemID == 0) - { - if (debug_Out) sLog.outError("AHSeller: Item::CreateItem() - ItemID is 0"); - continue; - } - - ItemPrototype const* prototype = objmgr.GetItemPrototype(itemID); - if (prototype == NULL) - { - if (debug_Out) sLog.outError("AHSeller: Huh?!?! prototype == NULL"); - continue; - } - - Item* item = Item::CreateItem(itemID, 1, AHBplayer); - if (item == NULL) - { - if (debug_Out) sLog.outError("AHSeller: Item::CreateItem() returned NULL"); - break; - } - item->AddToUpdateQueueOf(AHBplayer); - - uint32 randomPropertyId = Item::GenerateItemRandomPropertyId(itemID); - if (randomPropertyId != 0) - item->SetItemRandomProperties(randomPropertyId); - - uint64 buyoutPrice = 0; - uint64 bidPrice = 0; - uint32 stackCount = 1; - - switch (SellMethod) - { - case 0: - buyoutPrice = prototype->SellPrice; - break; - case 1: - buyoutPrice = prototype->BuyPrice; - break; - } - - if ((prototype->Quality >= 0) && (prototype->Quality <= AHB_MAX_QUALITY)) - { - if (config->GetMaxStack(prototype->Quality) > 1 && item->GetMaxStackCount() > 1) - stackCount = urand(1, minValue(item->GetMaxStackCount(), config->GetMaxStack(prototype->Quality))); - else if (config->GetMaxStack(prototype->Quality) == 0 && item->GetMaxStackCount() > 1) - stackCount = urand(1, item->GetMaxStackCount()); - else - stackCount = 1; - buyoutPrice *= urand(config->GetMinPrice(prototype->Quality), config->GetMaxPrice(prototype->Quality)); - buyoutPrice /= 100; - bidPrice = buyoutPrice * urand(config->GetMinBidPrice(prototype->Quality), config->GetMaxBidPrice(prototype->Quality)); - bidPrice /= 100; - } - else - { - // quality is something it shouldn't be, let's get out of here - if (debug_Out) sLog.outError("AHBuyer: Quality %u not Supported", prototype->Quality); - item->RemoveFromUpdateQueueOf(AHBplayer); - continue; - } - - uint32 etime = urand(1,3); - switch(etime) - { - case 1: - etime = 43200; - break; - case 2: - etime = 86400; - break; - case 3: - etime = 172800; - break; - default: - etime = 86400; - break; - } - item->SetCount(stackCount); - - uint32 dep = auctionmgr.GetAuctionDeposit(ahEntry, etime, item); - - AuctionEntry* auctionEntry = new AuctionEntry; - auctionEntry->Id = objmgr.GenerateAuctionID(); - auctionEntry->auctioneer = AuctioneerGUID; - auctionEntry->item_guidlow = item->GetGUIDLow(); - auctionEntry->item_template = item->GetEntry(); - auctionEntry->owner = AHBplayer->GetGUIDLow(); - auctionEntry->startbid = bidPrice * stackCount; - auctionEntry->buyout = buyoutPrice * stackCount; - auctionEntry->bidder = 0; - auctionEntry->bid = 0; - auctionEntry->deposit = dep; - auctionEntry->expire_time = (time_t) etime + time(NULL); - auctionEntry->auctionHouseEntry = ahEntry; - item->SaveToDB(); - item->RemoveFromUpdateQueueOf(AHBplayer); - auctionmgr.AddAItem(item); - auctionHouse->AddAuction(auctionEntry); - auctionEntry->SaveToDB(); - - switch(itemColor) - { - case 0: - ++greyItems; - break; - case 1: - ++whiteItems; - break; - case 2: - ++greenItems; - break; - case 3: - ++blueItems; - break; - case 4: - ++purpleItems; - break; - case 5: - ++orangeItems; - break; - case 6: - ++yellowItems; - break; - case 7: - ++greyTGoods; - break; - case 8: - ++whiteTGoods; - break; - case 9: - ++greenTGoods; - break; - case 10: - ++blueTGoods; - break; - case 11: - ++purpleTGoods; - break; - case 12: - ++orangeTGoods; - break; - case 13: - ++yellowTGoods; - break; - default: - break; - } - } - } -} -void AuctionHouseBot::addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session) -{ - if (!AHBBuyer) - { - if (debug_Out) sLog.outError("AHBuyer: Disabled"); - return; - } - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT id FROM auctionhouse WHERE itemowner<>%u AND buyguid<>%u", AHBplayerGUID, AHBplayerGUID); - - if (!result) - return; - - if (result->GetRowCount() == 0) - return; - - // Fetches content of selected AH - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(config->GetAHFID()); - vector possibleBids; - - do - { - uint32 tmpdata = result->Fetch()->GetUInt32(); - possibleBids.push_back(tmpdata); - }while (result->NextRow()); - - for (uint32 count = 1; count <= config->GetBidsPerInterval(); ++count) - { - // Do we have anything to bid? If not, stop here. - if (possibleBids.empty()) - { - //if (debug_Out) sLog.outString("AHBuyer: I have no items to bid on."); - count = config->GetBidsPerInterval(); - continue; - } - - // Choose random auction from possible auctions - uint32 vectorPos = urand(0, possibleBids.size() - 1); - vector::iterator iter = possibleBids.begin(); - advance(iter, vectorPos); - - // from auctionhousehandler.cpp, creates auction pointer & player pointer - AuctionEntry* auction = auctionHouse->GetAuction(*iter); - - // Erase the auction from the vector to prevent bidding on item in next iteration. - possibleBids.erase(iter); - - if (!auction) - continue; - - // get exact item information - Item *pItem = auctionmgr.GetAItem(auction->item_guidlow); - if (!pItem) - { - if (debug_Out) sLog.outError("AHBuyer: Item %u doesn't exist, perhaps bought already?", auction->item_guidlow); - continue; - } - - // get item prototype - ItemPrototype const* prototype = objmgr.GetItemPrototype(auction->item_template); - - // check which price we have to use, startbid or if it is bidded already - uint32 currentprice; - if (auction->bid) - currentprice = auction->bid; - else - currentprice = auction->startbid; - - // Prepare portion from maximum bid - double bidrate = static_cast(urand(1, 100)) / 100; - long double bidMax = 0; - - // check that bid has acceptable value and take bid based on vendorprice, stacksize and quality - switch (BuyMethod) - { - case 0: - { - if ((prototype->Quality >= 0) && (prototype->Quality <= AHB_MAX_QUALITY)) - { - if (currentprice < prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality)) - bidMax = prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality); - } - else - { - // quality is something it shouldn't be, let's get out of here - if (debug_Out) sLog.outError("AHBuyer: Quality %u not Supported", prototype->Quality); - continue; - } - break; - } - case 1: - { - if ((prototype->Quality >= 0) && (prototype->Quality <= AHB_MAX_QUALITY)) - { - if (currentprice < prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality)) - bidMax = prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality); - } - else - { - // quality is something it shouldn't be, let's get out of here - if (debug_Out) sLog.outError("AHBuyer: Quality %u not Supported", prototype->Quality); - continue; - } - break; - } - } - - // check some special items, and do recalculating to their prices - switch (prototype->Class) - { - // ammo - case 6: - bidMax = 0; - break; - default: - break; - } - - if (bidMax == 0) - { - // quality check failed to get bidmax, let's get out of here - continue; - } - - // Calculate our bid - long double bidvalue = currentprice + ((bidMax - currentprice) * bidrate); - // Convert to uint32 - uint32 bidprice = static_cast(bidvalue); - - // Check our bid is high enough to be valid. If not, correct it to minimum. - if ((currentprice + auction->GetAuctionOutBid()) > bidprice) - bidprice = currentprice + auction->GetAuctionOutBid(); - - if (debug_Out) - { - sLog.outString("-------------------------------------------------"); - sLog.outString("AHBuyer: Info for Auction #%u:", auction->Id); - sLog.outString("AHBuyer: AuctionHouse: %u", auction->GetHouseId()); - sLog.outString("AHBuyer: Auctioneer: %u", auction->auctioneer); - sLog.outString("AHBuyer: Owner: %u", auction->owner); - sLog.outString("AHBuyer: Bidder: %u", auction->bidder); - sLog.outString("AHBuyer: Starting Bid: %u", auction->startbid); - sLog.outString("AHBuyer: Current Bid: %u", currentprice); - sLog.outString("AHBuyer: Buyout: %u", auction->buyout); - sLog.outString("AHBuyer: Deposit: %u", auction->deposit); - sLog.outString("AHBuyer: Expire Time: %u", auction->expire_time); - sLog.outString("AHBuyer: Bid Rate: %f", bidrate); - sLog.outString("AHBuyer: Bid Max: %f", bidMax); - sLog.outString("AHBuyer: Bid Value: %f", bidvalue); - sLog.outString("AHBuyer: Bid Price: %u", bidprice); - sLog.outString("AHBuyer: Item GUID: %u", auction->item_guidlow); - sLog.outString("AHBuyer: Item Template: %u", auction->item_template); - sLog.outString("AHBuyer: Item Info:"); - sLog.outString("AHBuyer: Item ID: %u", prototype->ItemId); - sLog.outString("AHBuyer: Buy Price: %u", prototype->BuyPrice); - sLog.outString("AHBuyer: Sell Price: %u", prototype->SellPrice); - sLog.outString("AHBuyer: Bonding: %u", prototype->Bonding); - sLog.outString("AHBuyer: Quality: %u", prototype->Quality); - sLog.outString("AHBuyer: Item Level: %u", prototype->ItemLevel); - sLog.outString("AHBuyer: Ammo Type: %u", prototype->AmmoType); - sLog.outString("-------------------------------------------------"); - } - - // Check whether we do normal bid, or buyout - if ((bidprice < auction->buyout) || (auction->buyout == 0)) - { - - if (auction->bidder > 0) - { - if (auction->bidder == AHBplayer->GetGUIDLow()) - { - //pl->ModifyMoney(-int32(price - auction->bid)); - } - else - { - // mail to last bidder and return money - session->SendAuctionOutbiddedMail(auction , bidprice); - //pl->ModifyMoney(-int32(price)); - } - } - - auction->bidder = AHBplayer->GetGUIDLow(); - auction->bid = bidprice; - - // Saving auction into database - CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); - } - else - { - //buyout - if ((auction->bidder) && (AHBplayer->GetGUIDLow() != auction->bidder)) - { - session->SendAuctionOutbiddedMail(auction, auction->buyout); - } - auction->bidder = AHBplayer->GetGUIDLow(); - auction->bid = auction->buyout; - - // Send mails to buyer & seller - auctionmgr.SendAuctionSalePendingMail(auction); - auctionmgr.SendAuctionSuccessfulMail(auction); - auctionmgr.SendAuctionWonMail(auction); - auction->DeleteFromDB(); - uint32 item_template = auction->item_template; - auctionmgr.RemoveAItem(auction->item_guidlow); - auctionHouse->RemoveAuction(auction, item_template); - } - } -} - -void AuctionHouseBot::Update() -{ - time_t _newrun = time(NULL); - if ((!AHBSeller) && (!AHBBuyer)) - return; - - WorldSession _session(AHBplayerAccount, NULL, SEC_PLAYER, true, 0, LOCALE_enUS); - Player _AHBplayer(&_session); - _AHBplayer.Initialize(AHBplayerGUID); - ObjectAccessor::Instance().AddObject(&_AHBplayer); - - // Add New Bids - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) - { - addNewAuctions(&_AHBplayer, &AllianceConfig); - if (((_newrun - _lastrun_a) >= (AllianceConfig.GetBiddingInterval() * MINUTE)) && (AllianceConfig.GetBidsPerInterval() > 0)) - { - //if (debug_Out) sLog.outString("AHBuyer: %u seconds have passed since last bid", (_newrun - _lastrun_a)); - //if (debug_Out) sLog.outString("AHBuyer: Bidding on Alliance Auctions"); - addNewAuctionBuyerBotBid(&_AHBplayer, &AllianceConfig, &_session); - _lastrun_a = _newrun; - } - - addNewAuctions(&_AHBplayer, &HordeConfig); - if (((_newrun - _lastrun_h) >= (HordeConfig.GetBiddingInterval() * MINUTE)) && (HordeConfig.GetBidsPerInterval() > 0)) - { - //if (debug_Out) sLog.outString("AHBuyer: %u seconds have passed since last bid", (_newrun - _lastrun_h)); - //if (debug_Out) sLog.outString("AHBuyer: Bidding on Horde Auctions"); - addNewAuctionBuyerBotBid(&_AHBplayer, &HordeConfig, &_session); - _lastrun_h = _newrun; - } - } - - addNewAuctions(&_AHBplayer, &NeutralConfig); - if (((_newrun - _lastrun_n) >= (NeutralConfig.GetBiddingInterval() * MINUTE)) && (NeutralConfig.GetBidsPerInterval() > 0)) - { - //if (debug_Out) sLog.outString("AHBuyer: %u seconds have passed since last bid", (_newrun - _lastrun_n)); - //if (debug_Out) sLog.outString("AHBuyer: Bidding on Neutral Auctions"); - addNewAuctionBuyerBotBid(&_AHBplayer, &NeutralConfig, &_session); - _lastrun_n = _newrun; - } - ObjectAccessor::Instance().RemoveObject(&_AHBplayer); -} - -void AuctionHouseBot::Initialize() -{ - debug_Out = sConfig.GetBoolDefault("AuctionHouseBot.DEBUG", false); - debug_Out_Filters = sConfig.GetBoolDefault("AuctionHouseBot.DEBUG_FILTERS", false); - - AHBSeller = sConfig.GetBoolDefault("AuctionHouseBot.EnableSeller", false); - AHBBuyer = sConfig.GetBoolDefault("AuctionHouseBot.EnableBuyer", false); - SellMethod = sConfig.GetBoolDefault("AuctionHouseBot.UseBuyPriceForSeller", false); - BuyMethod = sConfig.GetBoolDefault("AuctionHouseBot.UseBuyPriceForBuyer", false); - - AHBplayerAccount = sConfig.GetIntDefault("AuctionHouseBot.Account", 0); - AHBplayerGUID = sConfig.GetIntDefault("AuctionHouseBot.GUID", 0); - ItemsPerCycle = sConfig.GetIntDefault("AuctionHouseBot.ItemsPerCycle", 200); - - //Begin Filters - - Vendor_Items = sConfig.GetBoolDefault("AuctionHouseBot.VendorItems", false); - Loot_Items = sConfig.GetBoolDefault("AuctionHouseBot.LootItems", true); - Other_Items = sConfig.GetBoolDefault("AuctionHouseBot.OtherItems", false); - Vendor_TGs = sConfig.GetBoolDefault("AuctionHouseBot.VendorTradeGoods", false); - Loot_TGs = sConfig.GetBoolDefault("AuctionHouseBot.LootTradeGoods", true); - Other_TGs = sConfig.GetBoolDefault("AuctionHouseBot.OtherTradeGoods", false); - - No_Bind = sConfig.GetBoolDefault("AuctionHouseBot.No_Bind", true); - Bind_When_Picked_Up = sConfig.GetBoolDefault("AuctionHouseBot.Bind_When_Picked_Up", false); - Bind_When_Equipped = sConfig.GetBoolDefault("AuctionHouseBot.Bind_When_Equipped", true); - Bind_When_Use = sConfig.GetBoolDefault("AuctionHouseBot.Bind_When_Use", true); - Bind_Quest_Item = sConfig.GetBoolDefault("AuctionHouseBot.Bind_Quest_Item", false); - - DisableBeta_PTR_Unused = sConfig.GetBoolDefault("AuctionHouseBot.DisableBeta_PTR_Unused", false); - DisablePermEnchant = sConfig.GetBoolDefault("AuctionHouseBot.DisablePermEnchant", false); - DisableConjured = sConfig.GetBoolDefault("AuctionHouseBot.DisableConjured", false); - DisableGems = sConfig.GetBoolDefault("AuctionHouseBot.DisableGems", false); - DisableMoney = sConfig.GetBoolDefault("AuctionHouseBot.DisableMoney", false); - DisableMoneyLoot = sConfig.GetBoolDefault("AuctionHouseBot.DisableMoneyLoot", false); - DisableLootable = sConfig.GetBoolDefault("AuctionHouseBot.DisableLootable", false); - DisableKeys = sConfig.GetBoolDefault("AuctionHouseBot.DisableKeys", false); - DisableDuration = sConfig.GetBoolDefault("AuctionHouseBot.DisableDuration", false); - DisableBOP_Or_Quest_NoReqLevel = sConfig.GetBoolDefault("AuctionHouseBot.DisableBOP_Or_Quest_NoReqLevel", false); - - DisableWarriorItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableWarriorItems", false); - DisablePaladinItems = sConfig.GetBoolDefault("AuctionHouseBot.DisablePaladinItems", false); - DisableHunterItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableHunterItems", false); - DisableRogueItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableRogueItems", false); - DisablePriestItems = sConfig.GetBoolDefault("AuctionHouseBot.DisablePriestItems", false); - DisableDKItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableDKItems", false); - DisableShamanItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableShamanItems", false); - DisableMageItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableMageItems", false); - DisableWarlockItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableWarlockItems", false); - DisableUnusedClassItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableUnusedClassItems", false); - DisableDruidItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableDruidItems", false); - - DisableItemsBelowLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsBelowLevel", 0); - DisableItemsAboveLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsAboveLevel", 0); - DisableTGsBelowLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsBelowLevel", 0); - DisableTGsAboveLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsAboveLevel", 0); - DisableItemsBelowGUID = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsBelowGUID", 0); - DisableItemsAboveGUID = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsAboveGUID", 0); - DisableTGsBelowGUID = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsBelowGUID", 0); - DisableTGsAboveGUID = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsAboveGUID", 0); - DisableItemsBelowReqLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsBelowReqLevel", 0); - DisableItemsAboveReqLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsAboveReqLevel", 0); - DisableTGsBelowReqLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsBelowReqLevel", 0); - DisableTGsAboveReqLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsAboveReqLevel", 0); - DisableItemsBelowReqSkillRank = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsBelowReqSkillRank", 0); - DisableItemsAboveReqSkillRank = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsAboveReqSkillRank", 0); - DisableTGsBelowReqSkillRank = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsBelowReqSkillRank", 0); - DisableTGsAboveReqSkillRank = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsAboveReqSkillRank", 0); - - //End Filters - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) - { - LoadValues(&AllianceConfig); - LoadValues(&HordeConfig); - } - LoadValues(&NeutralConfig); - - // - // check if the AHBot account/GUID in the config actually exists - // - - if ((AHBplayerAccount != 0) || (AHBplayerGUID != 0)) - { - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE account = %u AND guid = %u", AHBplayerAccount, AHBplayerGUID); - if (!result) - { - sLog.outError("AuctionHouseBot: The account/GUID-information set for your AHBot is incorrect (account: %u guid: %u)", AHBplayerAccount, AHBplayerGUID); - return; - } - } - - if (AHBSeller) - { - QueryResult_AutoPtr results = QueryResult_AutoPtr(NULL); - char npcQuery[] = "SELECT distinct item FROM npc_vendor"; - results = WorldDatabase.Query(npcQuery); - if (results != NULL) - { - do - { - Field* fields = results->Fetch(); - npcItems.push_back(fields[0].GetUInt32()); - - } while (results->NextRow()); - } - else - { - if (debug_Out) sLog.outString("AuctionHouseBot: \"%s\" failed", npcQuery); - } - - char lootQuery[] = "SELECT item FROM creature_loot_template UNION " - "SELECT item FROM reference_loot_template UNION " - "SELECT item FROM disenchant_loot_template UNION " - "SELECT item FROM fishing_loot_template UNION " - "SELECT item FROM gameobject_loot_template UNION " - "SELECT item FROM item_loot_template UNION " - "SELECT item FROM milling_loot_template UNION " - "SELECT item FROM pickpocketing_loot_template UNION " - "SELECT item FROM prospecting_loot_template UNION " - "SELECT item FROM skinning_loot_template"; - - results = WorldDatabase.Query(lootQuery); - if (results != NULL) - { - do - { - Field* fields = results->Fetch(); - lootItems.push_back(fields[0].GetUInt32()); - - } while (results->NextRow()); - } - else - { - if (debug_Out) sLog.outString("AuctionHouseBot: \"%s\" failed", lootQuery); - } - - for (uint32 itemID = 0; itemID < sItemStorage.MaxEntry; itemID++) - { - ItemPrototype const* prototype = objmgr.GetItemPrototype(itemID); - - if (prototype == NULL) - continue; - - switch (prototype->Bonding) - { - case NO_BIND: - if (!No_Bind) - continue; - break; - case BIND_WHEN_PICKED_UP: - if (!Bind_When_Picked_Up) - continue; - break; - case BIND_WHEN_EQUIPED: - if (!Bind_When_Equipped) - continue; - break; - case BIND_WHEN_USE: - if (!Bind_When_Use) - continue; - break; - case BIND_QUEST_ITEM: - if (!Bind_Quest_Item) - continue; - break; - default: - continue; - break; - } - - switch (SellMethod) - { - case 0: - if (prototype->SellPrice == 0) - continue; - break; - case 1: - if (prototype->BuyPrice == 0) - continue; - break; - } - - if ((prototype->Quality < 0) || (prototype->Quality > 6)) - continue; - - if ((Vendor_Items == 0) && !(prototype->Class == ITEM_CLASS_TRADE_GOODS)) - { - bool isVendorItem = false; - - for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorItem); i++) - { - if (itemID == npcItems[i]) - isVendorItem = true; - } - - if (isVendorItem) - continue; - } - - if ((Vendor_TGs == 0) && (prototype->Class == ITEM_CLASS_TRADE_GOODS)) - { - bool isVendorTG = false; - - for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorTG); i++) - { - if (itemID == npcItems[i]) - isVendorTG = true; - } - - if (isVendorTG) - continue; - } - - if ((Loot_Items == 0) && !(prototype->Class == ITEM_CLASS_TRADE_GOODS)) - { - bool isLootItem = false; - - for (unsigned int i = 0; (i < lootItems.size()) && (!isLootItem); i++) - { - if (itemID == lootItems[i]) - isLootItem = true; - } - - if (isLootItem) - continue; - } - - if ((Loot_TGs == 0) && (prototype->Class == ITEM_CLASS_TRADE_GOODS)) - { - bool isLootTG = false; - - for (unsigned int i = 0; (i < lootItems.size()) && (!isLootTG); i++) - { - if (itemID == lootItems[i]) - isLootTG = true; - } - - if (isLootTG) - continue; - } - - if ((Other_Items == 0) && !(prototype->Class == ITEM_CLASS_TRADE_GOODS)) - { - bool isVendorItem = false; - bool isLootItem = false; - - for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorItem); i++) - { - if (itemID == npcItems[i]) - isVendorItem = true; - } - for (unsigned int i = 0; (i < lootItems.size()) && (!isLootItem); i++) - { - if (itemID == lootItems[i]) - isLootItem = true; - } - if ((!isLootItem) && (!isVendorItem)) - continue; - } - - if ((Other_TGs == 0) && (prototype->Class == ITEM_CLASS_TRADE_GOODS)) - { - bool isVendorTG = false; - bool isLootTG = false; - - for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorTG); i++) - { - if (itemID == npcItems[i]) - isVendorTG = true; - } - for (unsigned int i = 0; (i < lootItems.size()) && (!isLootTG); i++) - { - if (itemID == lootItems[i]) - isLootTG = true; - } - if ((!isLootTG) && (!isVendorTG)) - continue; - } - - //TODO:Make list of items and create a vector - // Disable PTR/Beta/Unused items - if ((DisableBeta_PTR_Unused) && ((prototype->ItemId == 21878) || (prototype->ItemId == 27774) || (prototype->ItemId == 27811) || (prototype->ItemId == 28117) || (prototype->ItemId == 28112))) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (PTR/Beta/Unused Item)", prototype->ItemId); - continue; - } - - // Disable permanent enchants items - if ((DisablePermEnchant) && (prototype->Class == ITEM_CLASS_PERMANENT)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Permanent Enchant Item)", prototype->ItemId); - continue; - } - - // Disable conjured items - if ((DisableConjured) && (prototype->IsConjuredConsumable())) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Conjured Consumable)", prototype->ItemId); - continue; - } - - // Disable gems - if ((DisableGems) && (prototype->Class == ITEM_CLASS_GEM)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Gem)", prototype->ItemId); - continue; - } - - // Disable money - if ((DisableMoney) && (prototype->Class == ITEM_CLASS_MONEY)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Money)", prototype->ItemId); - continue; - } - - // Disable moneyloot - if ((DisableMoneyLoot) && (prototype->MinMoneyLoot > 0)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (MoneyLoot)", prototype->ItemId); - continue; - } - - // Disable lootable items - if ((DisableLootable) && (prototype->Flags & 4)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Lootable Item)", prototype->ItemId); - continue; - } - - // Disable Keys - if ((DisableKeys) && (prototype->Class == ITEM_CLASS_KEY)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Quest Item)", prototype->ItemId); - continue; - } - - // Disable items with duration - if ((DisableDuration) && (prototype->Duration > 0)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Has a Duration)", prototype->ItemId); - continue; - } - - // Disable items which are BOP or Quest Items and have a required level lower than the item level - if ((DisableBOP_Or_Quest_NoReqLevel) && ((prototype->Bonding == BIND_WHEN_PICKED_UP || prototype->Bonding == BIND_QUEST_ITEM) && (prototype->RequiredLevel < prototype->ItemLevel))) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (BOP or BQI and Required Level is less than Item Level)", prototype->ItemId); - continue; - } - - // Disable items specifically for Warrior - if ((DisableWarriorItems) && (prototype->AllowableClass == 1)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Warrior Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Paladin - if ((DisablePaladinItems) && (prototype->AllowableClass == 2)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Paladin Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Hunter - if ((DisableHunterItems) && (prototype->AllowableClass == 4)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Hunter Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Rogue - if ((DisableRogueItems) && (prototype->AllowableClass == 8)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Rogue Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Priest - if ((DisablePriestItems) && (prototype->AllowableClass == 16)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Priest Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for DK - if ((DisableDKItems) && (prototype->AllowableClass == 32)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (DK Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Shaman - if ((DisableShamanItems) && (prototype->AllowableClass == 64)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Shaman Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Mage - if ((DisableMageItems) && (prototype->AllowableClass == 128)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Mage Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Warlock - if ((DisableWarlockItems) && (prototype->AllowableClass == 256)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Warlock Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Unused Class - if ((DisableUnusedClassItems) && (prototype->AllowableClass == 512)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Unused Item)", prototype->ItemId); - continue; - } - - // Disable items specifically for Druid - if ((DisableDruidItems) && (prototype->AllowableClass == 1024)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Druid Item)", prototype->ItemId); - continue; - } - - // Disable Items below level X - if ((DisableItemsBelowLevel) && (prototype->Class != ITEM_CLASS_TRADE_GOODS) && (prototype->ItemLevel < DisableItemsBelowLevel)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Item Level = %u)", prototype->ItemId, prototype->ItemLevel); - continue; - } - - // Disable Items above level X - if ((DisableItemsAboveLevel) && (prototype->Class != ITEM_CLASS_TRADE_GOODS) && (prototype->ItemLevel > DisableItemsAboveLevel)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Item Level = %u)", prototype->ItemId, prototype->ItemLevel); - continue; - } - - // Disable Trade Goods below level X - if ((DisableTGsBelowLevel) && (prototype->Class == ITEM_CLASS_TRADE_GOODS) && (prototype->ItemLevel < DisableTGsBelowLevel)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Trade Good %u disabled (Trade Good Level = %u)", prototype->ItemId, prototype->ItemLevel); - continue; - } - - // Disable Trade Goods above level X - if ((DisableTGsAboveLevel) && (prototype->Class == ITEM_CLASS_TRADE_GOODS) && (prototype->ItemLevel > DisableTGsAboveLevel)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Trade Good %u disabled (Trade Good Level = %u)", prototype->ItemId, prototype->ItemLevel); - continue; - } - - // Disable Items below GUID X - if ((DisableItemsBelowGUID) && (prototype->Class != ITEM_CLASS_TRADE_GOODS) && (prototype->ItemId < DisableItemsBelowGUID)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Item Level = %u)", prototype->ItemId, prototype->ItemLevel); - continue; - } - - // Disable Items above GUID X - if ((DisableItemsAboveGUID) && (prototype->Class != ITEM_CLASS_TRADE_GOODS) && (prototype->ItemId > DisableItemsAboveGUID)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Item Level = %u)", prototype->ItemId, prototype->ItemLevel); - continue; - } - - // Disable Trade Goods below GUID X - if ((DisableTGsBelowGUID) && (prototype->Class == ITEM_CLASS_TRADE_GOODS) && (prototype->ItemId < DisableTGsBelowGUID)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Trade Good Level = %u)", prototype->ItemId, prototype->ItemLevel); - continue; - } - - // Disable Trade Goods above GUID X - if ((DisableTGsAboveGUID) && (prototype->Class == ITEM_CLASS_TRADE_GOODS) && (prototype->ItemId > DisableTGsAboveGUID)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Trade Good Level = %u)", prototype->ItemId, prototype->ItemLevel); - continue; - } - - // Disable Items for level lower than X - if ((DisableItemsBelowReqLevel) && (prototype->RequiredLevel < DisableItemsBelowReqLevel)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredLevel = %u)", prototype->ItemId, prototype->RequiredLevel); - continue; - } - - // Disable Items for level higher than X - if ((DisableItemsAboveReqLevel) && (prototype->RequiredLevel > DisableItemsAboveReqLevel)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredLevel = %u)", prototype->ItemId, prototype->RequiredLevel); - continue; - } - - // Disable Trade Goods for level lower than X - if ((DisableTGsBelowReqLevel) && (prototype->RequiredLevel < DisableTGsBelowReqLevel)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Trade Good %u disabled (RequiredLevel = %u)", prototype->ItemId, prototype->RequiredLevel); - continue; - } - - // Disable Trade Goods for level higher than X - if ((DisableTGsAboveReqLevel) && (prototype->RequiredLevel > DisableTGsAboveReqLevel)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Trade Good %u disabled (RequiredLevel = %u)", prototype->ItemId, prototype->RequiredLevel); - continue; - } - - // Disable Items that require skill lower than X - if ((DisableItemsBelowReqSkillRank) && (prototype->RequiredSkillRank < DisableItemsBelowReqSkillRank)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredSkillRank = %u)", prototype->ItemId, prototype->RequiredSkillRank); - continue; - } - - // Disable Items that require skill higher than X - if ((DisableItemsAboveReqSkillRank) && (prototype->RequiredSkillRank > DisableItemsAboveReqSkillRank)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredSkillRank = %u)", prototype->ItemId, prototype->RequiredSkillRank); - continue; - } - - // Disable Trade Goods that require skill lower than X - if ((DisableTGsBelowReqSkillRank) && (prototype->RequiredSkillRank < DisableTGsBelowReqSkillRank)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredSkillRank = %u)", prototype->ItemId, prototype->RequiredSkillRank); - continue; - } - - // Disable Trade Goods that require skill higher than X - if ((DisableTGsAboveReqSkillRank) && (prototype->RequiredSkillRank > DisableTGsAboveReqSkillRank)) - { - if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredSkillRank = %u)", prototype->ItemId, prototype->RequiredSkillRank); - continue; - } - - switch (prototype->Quality) - { - case AHB_GREY: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - greyTradeGoodsBin.push_back(itemID); - else - greyItemsBin.push_back(itemID); - break; - - case AHB_WHITE: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - whiteTradeGoodsBin.push_back(itemID); - else - whiteItemsBin.push_back(itemID); - break; - - case AHB_GREEN: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - greenTradeGoodsBin.push_back(itemID); - else - greenItemsBin.push_back(itemID); - break; - - case AHB_BLUE: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - blueTradeGoodsBin.push_back(itemID); - else - blueItemsBin.push_back(itemID); - break; - - case AHB_PURPLE: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - purpleTradeGoodsBin.push_back(itemID); - else - purpleItemsBin.push_back(itemID); - break; - - case AHB_ORANGE: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - orangeTradeGoodsBin.push_back(itemID); - else - orangeItemsBin.push_back(itemID); - break; - - case AHB_YELLOW: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - yellowTradeGoodsBin.push_back(itemID); - else - yellowItemsBin.push_back(itemID); - break; - } - } - - if ((greyTradeGoodsBin.size() == 0) && - (whiteTradeGoodsBin.size() == 0) && - (greenTradeGoodsBin.size() == 0) && - (blueTradeGoodsBin.size() == 0) && - (purpleTradeGoodsBin.size() == 0) && - (orangeTradeGoodsBin.size() == 0) && - (yellowTradeGoodsBin.size() == 0) && - (greyItemsBin.size() == 0) && - (whiteItemsBin.size() == 0) && - (greenItemsBin.size() == 0) && - (blueItemsBin.size() == 0) && - (purpleItemsBin.size() == 0) && - (orangeItemsBin.size() == 0) && - (yellowItemsBin.size() == 0)) - { - sLog.outError("AuctionHouseBot: No items"); - AHBSeller = 0; - } - - sLog.outString("AuctionHouseBot:"); - sLog.outString("loaded %u grey trade goods", greyTradeGoodsBin.size()); - sLog.outString("loaded %u white trade goods", whiteTradeGoodsBin.size()); - sLog.outString("loaded %u green trade goods", greenTradeGoodsBin.size()); - sLog.outString("loaded %u blue trade goods", blueTradeGoodsBin.size()); - sLog.outString("loaded %u purple trade goods", purpleTradeGoodsBin.size()); - sLog.outString("loaded %u orange trade goods", orangeTradeGoodsBin.size()); - sLog.outString("loaded %u yellow trade goods", yellowTradeGoodsBin.size()); - sLog.outString("loaded %u grey items", greyItemsBin.size()); - sLog.outString("loaded %u white items", whiteItemsBin.size()); - sLog.outString("loaded %u green items", greenItemsBin.size()); - sLog.outString("loaded %u blue items", blueItemsBin.size()); - sLog.outString("loaded %u purple items", purpleItemsBin.size()); - sLog.outString("loaded %u orange items", orangeItemsBin.size()); - sLog.outString("loaded %u yellow items", yellowItemsBin.size()); - } - sLog.outString("AuctionHouseBot and AuctionHouseBuyer have been loaded."); -} - -void AuctionHouseBot::IncrementItemCounts(AuctionEntry* ah) -{ - // from auctionhousehandler.cpp, creates auction pointer & player pointer - - // get exact item information - Item *pItem = auctionmgr.GetAItem(ah->item_guidlow); - if (!pItem) - { - if (debug_Out) sLog.outError("AHBot: Item %u doesn't exist, perhaps bought already?", ah->item_guidlow); - return; - } - - // get item prototype - ItemPrototype const* prototype = objmgr.GetItemPrototype(ah->item_template); - - AHBConfig *config; - - FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(ah->GetHouseFaction()); - if (!u_entry) - { - if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Neutral", ah->GetHouseFaction()); - config = &NeutralConfig; - } - else if (u_entry->ourMask & FACTION_MASK_ALLIANCE) - { - if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Alliance", ah->GetHouseFaction()); - config = &AllianceConfig; - } - else if (u_entry->ourMask & FACTION_MASK_HORDE) - { - if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Horde", ah->GetHouseFaction()); - config = &HordeConfig; - } - else - { - if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Neutral", ah->GetHouseFaction()); - config = &NeutralConfig; - } - - config->IncItemCounts(prototype->Class, prototype->Quality); -} - -void AuctionHouseBot::DecrementItemCounts(AuctionEntry* ah, uint32 item_template) -{ - // get item prototype - ItemPrototype const* prototype = objmgr.GetItemPrototype(item_template); - - AHBConfig *config; - - FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(ah->GetHouseFaction()); - if (!u_entry) - { - if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Neutral", ah->GetHouseFaction()); - config = &NeutralConfig; - } - else if (u_entry->ourMask & FACTION_MASK_ALLIANCE) - { - if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Alliance", ah->GetHouseFaction()); - config = &AllianceConfig; - } - else if (u_entry->ourMask & FACTION_MASK_HORDE) - { - if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Horde", ah->GetHouseFaction()); - config = &HordeConfig; - } - else - { - if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Neutral", ah->GetHouseFaction()); - config = &NeutralConfig; - } - - config->DecItemCounts(prototype->Class, prototype->Quality); -} - -void AuctionHouseBot::Commands(uint32 command, uint32 ahMapID, uint32 col, char* args) -{ - AHBConfig *config = NULL; - switch (ahMapID) - { - case 2: - config = &AllianceConfig; - break; - case 6: - config = &HordeConfig; - break; - case 7: - config = &NeutralConfig; - break; - } - std::string color; - switch (col) - { - case AHB_GREY: - color = "grey"; - break; - case AHB_WHITE: - color = "white"; - break; - case AHB_GREEN: - color = "green"; - break; - case AHB_BLUE: - color = "blue"; - break; - case AHB_PURPLE: - color = "purple"; - break; - case AHB_ORANGE: - color = "orange"; - break; - case AHB_YELLOW: - color = "yellow"; - break; - default: - break; - } - switch (command) - { - case 0: //ahexpire - { - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(config->GetAHFID()); - - AuctionHouseObject::AuctionEntryMap::iterator itr; - itr = auctionHouse->GetAuctionsBegin(); - - while (itr != auctionHouse->GetAuctionsEnd()) - { - if (itr->second->owner == AHBplayerGUID) - { - itr->second->expire_time = sWorld.GetGameTime(); - uint32 id = itr->second->Id; - uint32 expire_time = itr->second->expire_time; - CharacterDatabase.PExecute("UPDATE auctionhouse SET time = '%u' WHERE id = '%u'", expire_time, id); - } - ++itr; - } - } - break; - case 1: //min items - { - char * param1 = strtok(args, " "); - uint32 minItems = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET minitems = '%u' WHERE auctionhouse = '%u'", minItems, ahMapID); - config->SetMinItems(minItems); - } - break; - case 2: //max items - { - char * param1 = strtok(args, " "); - uint32 maxItems = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET maxitems = '%u' WHERE auctionhouse = '%u'", maxItems, ahMapID); - config->SetMaxItems(maxItems); - } - break; - case 3: //min time Deprecated (Place holder for future commands) - break; - case 4: //max time Deprecated (Place holder for future commands) - break; - case 5: //percentages - { - char * param1 = strtok(args, " "); - char * param2 = strtok(NULL, " "); - char * param3 = strtok(NULL, " "); - char * param4 = strtok(NULL, " "); - char * param5 = strtok(NULL, " "); - char * param6 = strtok(NULL, " "); - char * param7 = strtok(NULL, " "); - char * param8 = strtok(NULL, " "); - char * param9 = strtok(NULL, " "); - char * param10 = strtok(NULL, " "); - char * param11 = strtok(NULL, " "); - char * param12 = strtok(NULL, " "); - char * param13 = strtok(NULL, " "); - char * param14 = strtok(NULL, " "); - uint32 greytg = (uint32) strtoul(param1, NULL, 0); - uint32 whitetg = (uint32) strtoul(param2, NULL, 0); - uint32 greentg = (uint32) strtoul(param3, NULL, 0); - uint32 bluetg = (uint32) strtoul(param4, NULL, 0); - uint32 purpletg = (uint32) strtoul(param5, NULL, 0); - uint32 orangetg = (uint32) strtoul(param6, NULL, 0); - uint32 yellowtg = (uint32) strtoul(param7, NULL, 0); - uint32 greyi = (uint32) strtoul(param8, NULL, 0); - uint32 whitei = (uint32) strtoul(param9, NULL, 0); - uint32 greeni = (uint32) strtoul(param10, NULL, 0); - uint32 bluei = (uint32) strtoul(param11, NULL, 0); - uint32 purplei = (uint32) strtoul(param12, NULL, 0); - uint32 orangei = (uint32) strtoul(param13, NULL, 0); - uint32 yellowi = (uint32) strtoul(param14, NULL, 0); - - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentgreytradegoods = '%u' WHERE auctionhouse = '%u'", greytg, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentwhitetradegoods = '%u' WHERE auctionhouse = '%u'", whitetg, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentgreentradegoods = '%u' WHERE auctionhouse = '%u'", greentg, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentbluetradegoods = '%u' WHERE auctionhouse = '%u'", bluetg, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentpurpletradegoods = '%u' WHERE auctionhouse = '%u'", purpletg, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentorangetradegoods = '%u' WHERE auctionhouse = '%u'", orangetg, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentyellowtradegoods = '%u' WHERE auctionhouse = '%u'", yellowtg, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentgreyitems = '%u' WHERE auctionhouse = '%u'", greyi, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentwhiteitems = '%u' WHERE auctionhouse = '%u'", whitei, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentgreenitems = '%u' WHERE auctionhouse = '%u'", greeni, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentblueitems = '%u' WHERE auctionhouse = '%u'", bluei, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentpurpleitems = '%u' WHERE auctionhouse = '%u'", purplei, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentorangeitems = '%u' WHERE auctionhouse = '%u'", orangei, ahMapID); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentyellowitems = '%u' WHERE auctionhouse = '%u'", yellowi, ahMapID); - CharacterDatabase.CommitTransaction(); - config->SetPercentages(greytg, whitetg, greentg, bluetg, purpletg, orangetg, yellowtg, greyi, whitei, greeni, bluei, purplei, orangei, yellowi); - } - break; - case 6: //min prices - { - char * param1 = strtok(args, " "); - uint32 minPrice = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET minprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), minPrice, ahMapID); - config->SetMinPrice(col, minPrice); - } - break; - case 7: //max prices - { - char * param1 = strtok(args, " "); - uint32 maxPrice = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET maxprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), maxPrice, ahMapID); - config->SetMaxPrice(col, maxPrice); - } - break; - case 8: //min bid price - { - char * param1 = strtok(args, " "); - uint32 minBidPrice = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET minbidprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), minBidPrice, ahMapID); - config->SetMinBidPrice(col, minBidPrice); - } - break; - case 9: //max bid price - { - char * param1 = strtok(args, " "); - uint32 maxBidPrice = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET maxbidprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), maxBidPrice, ahMapID); - config->SetMaxBidPrice(col, maxBidPrice); - } - break; - case 10: //max stacks - { - char * param1 = strtok(args, " "); - uint32 maxStack = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET maxstack%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), maxStack, ahMapID); - config->SetMaxStack(col, maxStack); - } - break; - case 11: //buyer bid prices - { - char * param1 = strtok(args, " "); - uint32 buyerPrice = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET buyerprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), buyerPrice, ahMapID); - config->SetBuyerPrice(col, buyerPrice); - } - break; - case 12: //buyer bidding interval - { - char * param1 = strtok(args, " "); - uint32 bidInterval = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET buyerbiddinginterval = '%u' WHERE auctionhouse = '%u'", bidInterval, ahMapID); - config->SetBiddingInterval(bidInterval); - } - break; - case 13: //buyer bids per interval - { - char * param1 = strtok(args, " "); - uint32 bidsPerInterval = (uint32) strtoul(param1, NULL, 0); - CharacterDatabase.PExecute("UPDATE auctionhousebot SET buyerbidsperinterval = '%u' WHERE auctionhouse = '%u'", bidsPerInterval, ahMapID); - config->SetBidsPerInterval(bidsPerInterval); - } - break; - default: - break; - } -} - -void AuctionHouseBot::LoadValues(AHBConfig *config) -{ - if (debug_Out) sLog.outString("Start Settings for %s Auctionhouses:", CharacterDatabase.PQuery("SELECT name FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetString()); - if (AHBSeller) - { - //load min and max items - config->SetMinItems(CharacterDatabase.PQuery("SELECT minitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxItems(CharacterDatabase.PQuery("SELECT maxitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - //load percentages - uint32 greytg = CharacterDatabase.PQuery("SELECT percentgreytradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 whitetg = CharacterDatabase.PQuery("SELECT percentwhitetradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 greentg = CharacterDatabase.PQuery("SELECT percentgreentradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 bluetg = CharacterDatabase.PQuery("SELECT percentbluetradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 purpletg = CharacterDatabase.PQuery("SELECT percentpurpletradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 orangetg = CharacterDatabase.PQuery("SELECT percentorangetradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 yellowtg = CharacterDatabase.PQuery("SELECT percentyellowtradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 greyi = CharacterDatabase.PQuery("SELECT percentgreyitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 whitei = CharacterDatabase.PQuery("SELECT percentwhiteitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 greeni = CharacterDatabase.PQuery("SELECT percentgreenitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 bluei = CharacterDatabase.PQuery("SELECT percentblueitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 purplei = CharacterDatabase.PQuery("SELECT percentpurpleitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 orangei = CharacterDatabase.PQuery("SELECT percentorangeitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - uint32 yellowi = CharacterDatabase.PQuery("SELECT percentyellowitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); - config->SetPercentages(greytg, whitetg, greentg, bluetg, purpletg, orangetg, yellowtg, greyi, whitei, greeni, bluei, purplei, orangei, yellowi); - //load min and max prices - config->SetMinPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT minpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT maxpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT minpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT maxpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT minpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT maxpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT minpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT maxpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT minpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT maxpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT minpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT maxpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT minpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT maxpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - //load min and max bid prices - config->SetMinBidPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT minbidpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxBidPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT maxbidpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinBidPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT minbidpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxBidPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT maxbidpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinBidPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT minbidpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxBidPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT maxbidpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinBidPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT minbidpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxBidPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT maxbidpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinBidPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT minbidpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxBidPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT maxbidpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinBidPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT minbidpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxBidPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT maxbidpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMinBidPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT minbidpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxBidPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT maxbidpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - //load max stacks - config->SetMaxStack(AHB_GREY, CharacterDatabase.PQuery("SELECT maxstackgrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxStack(AHB_WHITE, CharacterDatabase.PQuery("SELECT maxstackwhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxStack(AHB_GREEN, CharacterDatabase.PQuery("SELECT maxstackgreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxStack(AHB_BLUE, CharacterDatabase.PQuery("SELECT maxstackblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxStack(AHB_PURPLE, CharacterDatabase.PQuery("SELECT maxstackpurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxStack(AHB_ORANGE, CharacterDatabase.PQuery("SELECT maxstackorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetMaxStack(AHB_YELLOW, CharacterDatabase.PQuery("SELECT maxstackyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - if (debug_Out) - { - sLog.outString("minItems = %u", config->GetMinItems()); - sLog.outString("maxItems = %u", config->GetMaxItems()); - sLog.outString("percentGreyTradeGoods = %u", config->GetPercentages(AHB_GREY_TG)); - sLog.outString("percentWhiteTradeGoods = %u", config->GetPercentages(AHB_WHITE_TG)); - sLog.outString("percentGreenTradeGoods = %u", config->GetPercentages(AHB_GREEN_TG)); - sLog.outString("percentBlueTradeGoods = %u", config->GetPercentages(AHB_BLUE_TG)); - sLog.outString("percentPurpleTradeGoods = %u", config->GetPercentages(AHB_PURPLE_TG)); - sLog.outString("percentOrangeTradeGoods = %u", config->GetPercentages(AHB_ORANGE_TG)); - sLog.outString("percentYellowTradeGoods = %u", config->GetPercentages(AHB_YELLOW_TG)); - sLog.outString("percentGreyItems = %u", config->GetPercentages(AHB_GREY_I)); - sLog.outString("percentWhiteItems = %u", config->GetPercentages(AHB_WHITE_I)); - sLog.outString("percentGreenItems = %u", config->GetPercentages(AHB_GREEN_I)); - sLog.outString("percentBlueItems = %u", config->GetPercentages(AHB_BLUE_I)); - sLog.outString("percentPurpleItems = %u", config->GetPercentages(AHB_PURPLE_I)); - sLog.outString("percentOrangeItems = %u", config->GetPercentages(AHB_ORANGE_I)); - sLog.outString("percentYellowItems = %u", config->GetPercentages(AHB_YELLOW_I)); - sLog.outString("minPriceGrey = %u", config->GetMinPrice(AHB_GREY)); - sLog.outString("maxPriceGrey = %u", config->GetMaxPrice(AHB_GREY)); - sLog.outString("minPriceWhite = %u", config->GetMinPrice(AHB_WHITE)); - sLog.outString("maxPriceWhite = %u", config->GetMaxPrice(AHB_WHITE)); - sLog.outString("minPriceGreen = %u", config->GetMinPrice(AHB_GREEN)); - sLog.outString("maxPriceGreen = %u", config->GetMaxPrice(AHB_GREEN)); - sLog.outString("minPriceBlue = %u", config->GetMinPrice(AHB_BLUE)); - sLog.outString("maxPriceBlue = %u", config->GetMaxPrice(AHB_BLUE)); - sLog.outString("minPricePurple = %u", config->GetMinPrice(AHB_PURPLE)); - sLog.outString("maxPricePurple = %u", config->GetMaxPrice(AHB_PURPLE)); - sLog.outString("minPriceOrange = %u", config->GetMinPrice(AHB_ORANGE)); - sLog.outString("maxPriceOrange = %u", config->GetMaxPrice(AHB_ORANGE)); - sLog.outString("minPriceYellow = %u", config->GetMinPrice(AHB_YELLOW)); - sLog.outString("maxPriceYellow = %u", config->GetMaxPrice(AHB_YELLOW)); - sLog.outString("minBidPriceGrey = %u", config->GetMinBidPrice(AHB_GREY)); - sLog.outString("maxBidPriceGrey = %u", config->GetMaxBidPrice(AHB_GREY)); - sLog.outString("minBidPriceWhite = %u", config->GetMinBidPrice(AHB_WHITE)); - sLog.outString("maxBidPriceWhite = %u", config->GetMaxBidPrice(AHB_WHITE)); - sLog.outString("minBidPriceGreen = %u", config->GetMinBidPrice(AHB_GREEN)); - sLog.outString("maxBidPriceGreen = %u", config->GetMaxBidPrice(AHB_GREEN)); - sLog.outString("minBidPriceBlue = %u", config->GetMinBidPrice(AHB_BLUE)); - sLog.outString("maxBidPriceBlue = %u", config->GetMinBidPrice(AHB_BLUE)); - sLog.outString("minBidPricePurple = %u", config->GetMinBidPrice(AHB_PURPLE)); - sLog.outString("maxBidPricePurple = %u", config->GetMaxBidPrice(AHB_PURPLE)); - sLog.outString("minBidPriceOrange = %u", config->GetMinBidPrice(AHB_ORANGE)); - sLog.outString("maxBidPriceOrange = %u", config->GetMaxBidPrice(AHB_ORANGE)); - sLog.outString("minBidPriceYellow = %u", config->GetMinBidPrice(AHB_YELLOW)); - sLog.outString("maxBidPriceYellow = %u", config->GetMaxBidPrice(AHB_YELLOW)); - sLog.outString("maxStackGrey = %u", config->GetMaxStack(AHB_GREY)); - sLog.outString("maxStackWhite = %u", config->GetMaxStack(AHB_WHITE)); - sLog.outString("maxStackGreen = %u", config->GetMaxStack(AHB_GREEN)); - sLog.outString("maxStackBlue = %u", config->GetMaxStack(AHB_BLUE)); - sLog.outString("maxStackPurple = %u", config->GetMaxStack(AHB_PURPLE)); - sLog.outString("maxStackOrange = %u", config->GetMaxStack(AHB_ORANGE)); - sLog.outString("maxStackYellow = %u", config->GetMaxStack(AHB_YELLOW)); - } - //AuctionHouseEntry const* ahEntry = auctionmgr.GetAuctionHouseEntry(config->GetAHFID()); - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(config->GetAHFID()); - - config->ResetItemCounts(); - uint32 auctions = auctionHouse->Getcount(); - - if (auctions) - { - for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = auctionHouse->GetAuctionsBegin(); itr != auctionHouse->GetAuctionsEnd(); ++itr) - { - AuctionEntry *Aentry = itr->second; - Item *item = auctionmgr.GetAItem(Aentry->item_guidlow); - if (item) - { - ItemPrototype const *prototype = item->GetProto(); - if (prototype) - { - switch (prototype->Quality) - { - case 0: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - config->IncItemCounts(AHB_GREY_TG); - else - config->IncItemCounts(AHB_GREY_I); - break; - case 1: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - config->IncItemCounts(AHB_WHITE_TG); - else - config->IncItemCounts(AHB_WHITE_I); - break; - case 2: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - config->IncItemCounts(AHB_GREEN_TG); - else - config->IncItemCounts(AHB_GREEN_I); - break; - case 3: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - config->IncItemCounts(AHB_BLUE_TG); - else - config->IncItemCounts(AHB_BLUE_I); - break; - case 4: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - config->IncItemCounts(AHB_PURPLE_TG); - else - config->IncItemCounts(AHB_PURPLE_I); - break; - case 5: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - config->IncItemCounts(AHB_ORANGE_TG); - else - config->IncItemCounts(AHB_ORANGE_I); - break; - case 6: - if (prototype->Class == ITEM_CLASS_TRADE_GOODS) - config->IncItemCounts(AHB_YELLOW_TG); - else - config->IncItemCounts(AHB_YELLOW_I); - break; - } - } - } - } - } - if (debug_Out) - { - sLog.outString("Current Items in %s Auctionhouses:", CharacterDatabase.PQuery("SELECT name FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetString()); - sLog.outString("Grey Trade Goods\t%u\tGrey Items\t%u", config->GetItemCounts(AHB_GREY_TG), config->GetItemCounts(AHB_GREY_I)); - sLog.outString("White Trade Goods\t%u\tWhite Items\t%u", config->GetItemCounts(AHB_WHITE_TG), config->GetItemCounts(AHB_WHITE_I)); - sLog.outString("Green Trade Goods\t%u\tGreen Items\t%u", config->GetItemCounts(AHB_GREEN_TG), config->GetItemCounts(AHB_GREEN_I)); - sLog.outString("Blue Trade Goods\t%u\tBlue Items\t%u", config->GetItemCounts(AHB_BLUE_TG), config->GetItemCounts(AHB_BLUE_I)); - sLog.outString("Purple Trade Goods\t%u\tPurple Items\t%u", config->GetItemCounts(AHB_PURPLE_TG), config->GetItemCounts(AHB_PURPLE_I)); - sLog.outString("Orange Trade Goods\t%u\tOrange Items\t%u", config->GetItemCounts(AHB_ORANGE_TG), config->GetItemCounts(AHB_ORANGE_I)); - sLog.outString("Yellow Trade Goods\t%u\tYellow Items\t%u", config->GetItemCounts(AHB_YELLOW_TG), config->GetItemCounts(AHB_YELLOW_I)); - } - } - if (AHBBuyer) - { - //load buyer bid prices - config->SetBuyerPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT buyerpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetBuyerPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT buyerpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetBuyerPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT buyerpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetBuyerPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT buyerpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetBuyerPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT buyerpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetBuyerPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT buyerpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - config->SetBuyerPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT buyerpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - //load bidding interval - config->SetBiddingInterval(CharacterDatabase.PQuery("SELECT buyerbiddinginterval FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - //load bids per interval - config->SetBidsPerInterval(CharacterDatabase.PQuery("SELECT buyerbidsperinterval FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); - if (debug_Out) - { - sLog.outString("buyerPriceGrey = %u", config->GetBuyerPrice(AHB_GREY)); - sLog.outString("buyerPriceWhite = %u", config->GetBuyerPrice(AHB_WHITE)); - sLog.outString("buyerPriceGreen = %u", config->GetBuyerPrice(AHB_GREEN)); - sLog.outString("buyerPriceBlue = %u", config->GetBuyerPrice(AHB_BLUE)); - sLog.outString("buyerPricePurple = %u", config->GetBuyerPrice(AHB_PURPLE)); - sLog.outString("buyerPriceOrange = %u", config->GetBuyerPrice(AHB_ORANGE)); - sLog.outString("buyerPriceYellow = %u", config->GetBuyerPrice(AHB_YELLOW)); - sLog.outString("buyerBiddingInterval = %u", config->GetBiddingInterval()); - sLog.outString("buyerBidsPerInterval = %u", config->GetBidsPerInterval()); - } - } - if (debug_Out) sLog.outString("End Settings for %s Auctionhouses:", CharacterDatabase.PQuery("SELECT name FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetString()); -} diff --git a/src/server/game/AI/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AI/AuctionHouseBot/AuctionHouseBot.h deleted file mode 100644 index 208a09aa0b2..00000000000 --- a/src/server/game/AI/AuctionHouseBot/AuctionHouseBot.h +++ /dev/null @@ -1,1225 +0,0 @@ -#ifndef AUCTION_HOUSE_BOT_H -#define AUCTION_HOUSE_BOT_H - -#include "World.h" -#include "Config/ConfigEnv.h" -#include "ItemPrototype.h" - -#define AHB_GREY 0 -#define AHB_WHITE 1 -#define AHB_GREEN 2 -#define AHB_BLUE 3 -#define AHB_PURPLE 4 -#define AHB_ORANGE 5 -#define AHB_YELLOW 6 -#define AHB_MAX_QUALITY 6 -#define AHB_GREY_TG 0 -#define AHB_WHITE_TG 1 -#define AHB_GREEN_TG 2 -#define AHB_BLUE_TG 3 -#define AHB_PURPLE_TG 4 -#define AHB_ORANGE_TG 5 -#define AHB_YELLOW_TG 6 -#define AHB_GREY_I 7 -#define AHB_WHITE_I 8 -#define AHB_GREEN_I 9 -#define AHB_BLUE_I 10 -#define AHB_PURPLE_I 11 -#define AHB_ORANGE_I 12 -#define AHB_YELLOW_I 13 - -class AHBConfig -{ -private: - uint32 AHID; - uint32 AHFID; - uint32 minItems; - uint32 maxItems; - uint32 percentGreyTradeGoods; - uint32 percentWhiteTradeGoods; - uint32 percentGreenTradeGoods; - uint32 percentBlueTradeGoods; - uint32 percentPurpleTradeGoods; - uint32 percentOrangeTradeGoods; - uint32 percentYellowTradeGoods; - uint32 percentGreyItems; - uint32 percentWhiteItems; - uint32 percentGreenItems; - uint32 percentBlueItems; - uint32 percentPurpleItems; - uint32 percentOrangeItems; - uint32 percentYellowItems; - uint32 minPriceGrey; - uint32 maxPriceGrey; - uint32 minBidPriceGrey; - uint32 maxBidPriceGrey; - uint32 maxStackGrey; - uint32 minPriceWhite; - uint32 maxPriceWhite; - uint32 minBidPriceWhite; - uint32 maxBidPriceWhite; - uint32 maxStackWhite; - uint32 minPriceGreen; - uint32 maxPriceGreen; - uint32 minBidPriceGreen; - uint32 maxBidPriceGreen; - uint32 maxStackGreen; - uint32 minPriceBlue; - uint32 maxPriceBlue; - uint32 minBidPriceBlue; - uint32 maxBidPriceBlue; - uint32 maxStackBlue; - uint32 minPricePurple; - uint32 maxPricePurple; - uint32 minBidPricePurple; - uint32 maxBidPricePurple; - uint32 maxStackPurple; - uint32 minPriceOrange; - uint32 maxPriceOrange; - uint32 minBidPriceOrange; - uint32 maxBidPriceOrange; - uint32 maxStackOrange; - uint32 minPriceYellow; - uint32 maxPriceYellow; - uint32 minBidPriceYellow; - uint32 maxBidPriceYellow; - uint32 maxStackYellow; - - uint32 buyerPriceGrey; - uint32 buyerPriceWhite; - uint32 buyerPriceGreen; - uint32 buyerPriceBlue; - uint32 buyerPricePurple; - uint32 buyerPriceOrange; - uint32 buyerPriceYellow; - uint32 buyerBiddingInterval; - uint32 buyerBidsPerInterval; - - uint32 greytgp; - uint32 whitetgp; - uint32 greentgp; - uint32 bluetgp; - uint32 purpletgp; - uint32 orangetgp; - uint32 yellowtgp; - uint32 greyip; - uint32 whiteip; - uint32 greenip; - uint32 blueip; - uint32 purpleip; - uint32 orangeip; - uint32 yellowip; - - uint32 greyTGoods; - uint32 whiteTGoods; - uint32 greenTGoods; - uint32 blueTGoods; - uint32 purpleTGoods; - uint32 orangeTGoods; - uint32 yellowTGoods; - - uint32 greyItems; - uint32 whiteItems; - uint32 greenItems; - uint32 blueItems; - uint32 purpleItems; - uint32 orangeItems; - uint32 yellowItems; - -public: - AHBConfig(uint32 ahid) - { - AHID = ahid; - switch(ahid) - { - case 2: - AHFID = 55; - break; - case 6: - AHFID = 29; - break; - case 7: - AHFID = 120; - break; - default: - AHFID = 120; - break; - } - } - AHBConfig() - { - } - uint32 GetAHID() - { - return AHID; - } - uint32 GetAHFID() - { - return AHFID; - } - void SetMinItems(uint32 value) - { - minItems = value; - } - uint32 GetMinItems() - { - if ((minItems == 0) && (maxItems)) - return maxItems; - else if ((maxItems) && (minItems > maxItems)) - return maxItems; - else - return minItems; - } - void SetMaxItems(uint32 value) - { - maxItems = value; - CalculatePercents(); - } - uint32 GetMaxItems() - { - return maxItems; - } - void SetPercentages(uint32 greytg, uint32 whitetg, uint32 greentg, uint32 bluetg, uint32 purpletg, uint32 orangetg, uint32 yellowtg, uint32 greyi, uint32 whitei, uint32 greeni, uint32 bluei, uint32 purplei, uint32 orangei, uint32 yellowi) - { - uint32 totalPercent = greytg + whitetg + greentg + bluetg + purpletg + orangetg + yellowtg + greyi + whitei + greeni + bluei + purplei + orangei + yellowi; - - if (totalPercent == 0) - { - maxItems = 0; - } - else if (totalPercent != 100) - { - greytg = 0; - whitetg = 27; - greentg = 12; - bluetg = 10; - purpletg = 1; - orangetg = 0; - yellowtg = 0; - greyi = 0; - whitei = 10; - greeni = 30; - bluei = 8; - purplei = 2; - orangei = 0; - yellowi = 0; - } - percentGreyTradeGoods = greytg; - percentWhiteTradeGoods = whitetg; - percentGreenTradeGoods = greentg; - percentBlueTradeGoods = bluetg; - percentPurpleTradeGoods = purpletg; - percentOrangeTradeGoods = orangetg; - percentYellowTradeGoods = yellowtg; - percentGreyItems = greyi; - percentWhiteItems = whitei; - percentGreenItems = greeni; - percentBlueItems = bluei; - percentPurpleItems = purplei; - percentOrangeItems = orangei; - percentYellowItems = yellowi; - CalculatePercents(); - } - uint32 GetPercentages(uint32 color) - { - switch(color) - { - case AHB_GREY_TG: - return percentGreyTradeGoods; - break; - case AHB_WHITE_TG: - return percentWhiteTradeGoods; - break; - case AHB_GREEN_TG: - return percentGreenTradeGoods; - break; - case AHB_BLUE_TG: - return percentBlueTradeGoods; - break; - case AHB_PURPLE_TG: - return percentPurpleTradeGoods; - break; - case AHB_ORANGE_TG: - return percentOrangeTradeGoods; - break; - case AHB_YELLOW_TG: - return percentYellowTradeGoods; - break; - case AHB_GREY_I: - return percentGreyItems; - break; - case AHB_WHITE_I: - return percentWhiteItems; - break; - case AHB_GREEN_I: - return percentGreenItems; - break; - case AHB_BLUE_I: - return percentBlueItems; - break; - case AHB_PURPLE_I: - return percentPurpleItems; - break; - case AHB_ORANGE_I: - return percentOrangeItems; - break; - case AHB_YELLOW_I: - return percentYellowItems; - break; - default: - return 0; - break; - } - } - void SetMinPrice(uint32 color, uint32 value) - { - switch(color) - { - case AHB_GREY: - minPriceGrey = value; - break; - case AHB_WHITE: - minPriceWhite = value; - break; - case AHB_GREEN: - minPriceGreen = value; - break; - case AHB_BLUE: - minPriceBlue = value; - break; - case AHB_PURPLE: - minPricePurple = value; - break; - case AHB_ORANGE: - minPriceOrange = value; - break; - case AHB_YELLOW: - minPriceYellow = value; - break; - default: - break; - } - } - uint32 GetMinPrice(uint32 color) - { - switch(color) - { - case AHB_GREY: - { - if (minPriceGrey == 0) - return 100; - else if (minPriceGrey > maxPriceGrey) - return maxPriceGrey; - else - return minPriceGrey; - break; - } - case AHB_WHITE: - { - if (minPriceWhite == 0) - return 150; - else if (minPriceWhite > maxPriceWhite) - return maxPriceWhite; - else - return minPriceWhite; - break; - } - case AHB_GREEN: - { - if (minPriceGreen == 0) - return 200; - else if (minPriceGreen > maxPriceGreen) - return maxPriceGreen; - else - return minPriceGreen; - break; - } - case AHB_BLUE: - { - if (minPriceBlue == 0) - return 250; - else if (minPriceBlue > maxPriceBlue) - return maxPriceBlue; - else - return minPriceBlue; - break; - } - case AHB_PURPLE: - { - if (minPricePurple == 0) - return 300; - else if (minPricePurple > maxPricePurple) - return maxPricePurple; - else - return minPricePurple; - break; - } - case AHB_ORANGE: - { - if (minPriceOrange == 0) - return 400; - else if (minPriceOrange > maxPriceOrange) - return maxPriceOrange; - else - return minPriceOrange; - break; - } - case AHB_YELLOW: - { - if (minPriceYellow == 0) - return 500; - else if (minPriceYellow > maxPriceYellow) - return maxPriceYellow; - else - return minPriceYellow; - break; - } - default: - { - return 0; - break; - } - } - } - void SetMaxPrice(uint32 color, uint32 value) - { - switch(color) - { - case AHB_GREY: - maxPriceGrey = value; - break; - case AHB_WHITE: - maxPriceWhite = value; - break; - case AHB_GREEN: - maxPriceGreen = value; - break; - case AHB_BLUE: - maxPriceBlue = value; - break; - case AHB_PURPLE: - maxPricePurple = value; - break; - case AHB_ORANGE: - maxPriceOrange = value; - break; - case AHB_YELLOW: - maxPriceYellow = value; - break; - default: - break; - } - } - uint32 GetMaxPrice(uint32 color) - { - switch(color) - { - case AHB_GREY: - { - if (maxPriceGrey == 0) - return 150; - else - return maxPriceGrey; - break; - } - case AHB_WHITE: - { - if (maxPriceWhite == 0) - return 250; - else - return maxPriceWhite; - break; - } - case AHB_GREEN: - { - if (maxPriceGreen == 0) - return 300; - else - return maxPriceGreen; - break; - } - case AHB_BLUE: - { - if (maxPriceBlue == 0) - return 350; - else - return maxPriceBlue; - break; - } - case AHB_PURPLE: - { - if (maxPricePurple == 0) - return 450; - else - return maxPricePurple; - break; - } - case AHB_ORANGE: - { - if (maxPriceOrange == 0) - return 550; - else - return maxPriceOrange; - break; - } - case AHB_YELLOW: - { - if (maxPriceYellow == 0) - return 650; - else - return maxPriceYellow; - break; - } - default: - { - return 0; - break; - } - } - } - void SetMinBidPrice(uint32 color, uint32 value) - { - switch(color) - { - case AHB_GREY: - minBidPriceGrey = value; - break; - case AHB_WHITE: - minBidPriceWhite = value; - break; - case AHB_GREEN: - minBidPriceGreen = value; - break; - case AHB_BLUE: - minBidPriceBlue = value; - break; - case AHB_PURPLE: - minBidPricePurple = value; - break; - case AHB_ORANGE: - minBidPriceOrange = value; - break; - case AHB_YELLOW: - minBidPriceYellow = value; - break; - default: - break; - } - } - uint32 GetMinBidPrice(uint32 color) - { - switch(color) - { - case AHB_GREY: - { - if (minBidPriceGrey > 100) - return 100; - else - return minBidPriceGrey; - break; - } - case AHB_WHITE: - { - if (minBidPriceWhite > 100) - return 100; - else - return minBidPriceWhite; - break; - } - case AHB_GREEN: - { - if (minBidPriceGreen > 100) - return 100; - else - return minBidPriceGreen; - break; - } - case AHB_BLUE: - { - if (minBidPriceBlue > 100) - return 100; - else - return minBidPriceBlue; - break; - } - case AHB_PURPLE: - { - if (minBidPricePurple > 100) - return 100; - else - return minBidPricePurple; - break; - } - case AHB_ORANGE: - { - if (minBidPriceOrange > 100) - return 100; - else - return minBidPriceOrange; - break; - } - case AHB_YELLOW: - { - if (minBidPriceYellow > 100) - return 100; - else - return minBidPriceYellow; - break; - } - default: - { - return 0; - break; - } - } - } - void SetMaxBidPrice(uint32 color, uint32 value) - { - switch(color) - { - case AHB_GREY: - maxBidPriceGrey = value; - break; - case AHB_WHITE: - maxBidPriceWhite = value; - break; - case AHB_GREEN: - maxBidPriceGreen = value; - break; - case AHB_BLUE: - maxBidPriceBlue = value; - break; - case AHB_PURPLE: - maxBidPricePurple = value; - break; - case AHB_ORANGE: - maxBidPriceOrange = value; - break; - case AHB_YELLOW: - maxBidPriceYellow = value; - break; - default: - break; - } - } - uint32 GetMaxBidPrice(uint32 color) - { - switch(color) - { - case AHB_GREY: - { - if (maxBidPriceGrey > 100) - return 100; - else - return maxBidPriceGrey; - break; - } - case AHB_WHITE: - { - if (maxBidPriceWhite > 100) - return 100; - else - return maxBidPriceWhite; - break; - } - case AHB_GREEN: - { - if (maxBidPriceGreen > 100) - return 100; - else - return maxBidPriceGreen; - break; - } - case AHB_BLUE: - { - if (maxBidPriceBlue > 100) - return 100; - else - return maxBidPriceBlue; - break; - } - case AHB_PURPLE: - { - if (maxBidPricePurple > 100) - return 100; - else - return maxBidPricePurple; - break; - } - case AHB_ORANGE: - { - if (maxBidPriceOrange > 100) - return 100; - else - return maxBidPriceOrange; - break; - } - case AHB_YELLOW: - { - if (maxBidPriceYellow > 100) - return 100; - else - return maxBidPriceYellow; - break; - } - default: - { - return 0; - break; - } - } - } - void SetMaxStack(uint32 color, uint32 value) - { - switch(color) - { - case AHB_GREY: - maxStackGrey = value; - break; - case AHB_WHITE: - maxStackWhite = value; - break; - case AHB_GREEN: - maxStackGreen = value; - break; - case AHB_BLUE: - maxStackBlue = value; - break; - case AHB_PURPLE: - maxStackPurple = value; - break; - case AHB_ORANGE: - maxStackOrange = value; - break; - case AHB_YELLOW: - maxStackYellow = value; - break; - default: - break; - } - } - uint32 GetMaxStack(uint32 color) - { - switch(color) - { - case AHB_GREY: - { - return maxStackGrey; - break; - } - case AHB_WHITE: - { - return maxStackWhite; - break; - } - case AHB_GREEN: - { - return maxStackGreen; - break; - } - case AHB_BLUE: - { - return maxStackBlue; - break; - } - case AHB_PURPLE: - { - return maxStackPurple; - break; - } - case AHB_ORANGE: - { - return maxStackOrange; - break; - } - case AHB_YELLOW: - { - return maxStackYellow; - break; - } - default: - { - return 0; - break; - } - } - } - void SetBuyerPrice(uint32 color, uint32 value) - { - switch(color) - { - case AHB_GREY: - buyerPriceGrey = value; - break; - case AHB_WHITE: - buyerPriceWhite = value; - break; - case AHB_GREEN: - buyerPriceGreen = value; - break; - case AHB_BLUE: - buyerPriceBlue = value; - break; - case AHB_PURPLE: - buyerPricePurple = value; - break; - case AHB_ORANGE: - buyerPriceOrange = value; - break; - case AHB_YELLOW: - buyerPriceYellow = value; - break; - default: - break; - } - } - uint32 GetBuyerPrice(uint32 color) - { - switch(color) - { - case AHB_GREY: - return buyerPriceGrey; - break; - case AHB_WHITE: - return buyerPriceWhite; - break; - case AHB_GREEN: - return buyerPriceGreen; - break; - case AHB_BLUE: - return buyerPriceBlue; - break; - case AHB_PURPLE: - return buyerPricePurple; - break; - case AHB_ORANGE: - return buyerPriceOrange; - break; - case AHB_YELLOW: - return buyerPriceYellow; - break; - default: - return 0; - break; - } - } - void SetBiddingInterval(uint32 value) - { - buyerBiddingInterval = value; - } - uint32 GetBiddingInterval() - { - return buyerBiddingInterval; - } - void CalculatePercents() - { - greytgp = (uint32) (((double)percentGreyTradeGoods / 100.0) * maxItems); - whitetgp = (uint32) (((double)percentWhiteTradeGoods / 100.0) * maxItems); - greentgp = (uint32) (((double)percentGreenTradeGoods / 100.0) * maxItems); - bluetgp = (uint32) (((double)percentBlueTradeGoods / 100.0) * maxItems); - purpletgp = (uint32) (((double)percentPurpleTradeGoods / 100.0) * maxItems); - orangetgp = (uint32) (((double)percentOrangeTradeGoods / 100.0) * maxItems); - yellowtgp = (uint32) (((double)percentYellowTradeGoods / 100.0) * maxItems); - greyip = (uint32) (((double)percentGreyItems / 100.0) * maxItems); - whiteip = (uint32) (((double)percentWhiteItems / 100.0) * maxItems); - greenip = (uint32) (((double)percentGreenItems / 100.0) * maxItems); - blueip = (uint32) (((double)percentBlueItems / 100.0) * maxItems); - purpleip = (uint32) (((double)percentPurpleItems / 100.0) * maxItems); - orangeip = (uint32) (((double)percentOrangeItems / 100.0) * maxItems); - yellowip = (uint32) (((double)percentYellowItems / 100.0) * maxItems); - uint32 total = greytgp + whitetgp + greentgp + bluetgp + purpletgp + orangetgp + yellowtgp + greyip + whiteip + greenip + blueip + purpleip + orangeip + yellowip; - int32 diff = (maxItems - total); - if (diff < 0) - { - if ((whiteip - diff) > 0) - whiteip -= diff; - else if ((greenip - diff) > 0) - greenip -= diff; - } - else if (diff < 0) - { - whiteip += diff; - } - } - uint32 GetPercents(uint32 color) - { - switch(color) - { - case AHB_GREY_TG: - return greytgp; - break; - case AHB_WHITE_TG: - return whitetgp; - break; - case AHB_GREEN_TG: - return greentgp; - break; - case AHB_BLUE_TG: - return bluetgp; - break; - case AHB_PURPLE_TG: - return purpletgp; - break; - case AHB_ORANGE_TG: - return orangetgp; - break; - case AHB_YELLOW_TG: - return yellowtgp; - break; - case AHB_GREY_I: - return greyip; - break; - case AHB_WHITE_I: - return whiteip; - break; - case AHB_GREEN_I: - return greenip; - break; - case AHB_BLUE_I: - return blueip; - break; - case AHB_PURPLE_I: - return purpleip; - break; - case AHB_ORANGE_I: - return orangeip; - break; - case AHB_YELLOW_I: - return yellowip; - break; - default: - return 0; - break; - } - } - - void DecItemCounts(uint32 Class, uint32 Quality) - { - switch(Class) - { - case ITEM_CLASS_TRADE_GOODS: - DecItemCounts(Quality); - break; - default: - DecItemCounts(Quality + 7); - break; - } - } - - void DecItemCounts(uint32 color) - { - switch(color) - { - case AHB_GREY_TG: - --greyTGoods; - break; - case AHB_WHITE_TG: - --whiteTGoods; - break; - case AHB_GREEN_TG: - --greenTGoods; - break; - case AHB_BLUE_TG: - --blueTGoods; - break; - case AHB_PURPLE_TG: - --purpleTGoods; - break; - case AHB_ORANGE_TG: - --orangeTGoods; - break; - case AHB_YELLOW_TG: - --yellowTGoods; - break; - case AHB_GREY_I: - --greyItems; - break; - case AHB_WHITE_I: - --whiteItems; - break; - case AHB_GREEN_I: - --greenItems; - break; - case AHB_BLUE_I: - --blueItems; - break; - case AHB_PURPLE_I: - --purpleItems; - break; - case AHB_ORANGE_I: - --orangeItems; - break; - case AHB_YELLOW_I: - --yellowItems; - break; - default: - break; - } - } - - void IncItemCounts(uint32 Class, uint32 Quality) - { - switch(Class) - { - case ITEM_CLASS_TRADE_GOODS: - IncItemCounts(Quality); - break; - default: - IncItemCounts(Quality + 7); - break; - } - } - - void IncItemCounts(uint32 color) - { - switch(color) - { - case AHB_GREY_TG: - ++greyTGoods; - break; - case AHB_WHITE_TG: - ++whiteTGoods; - break; - case AHB_GREEN_TG: - ++greenTGoods; - break; - case AHB_BLUE_TG: - ++blueTGoods; - break; - case AHB_PURPLE_TG: - ++purpleTGoods; - break; - case AHB_ORANGE_TG: - ++orangeTGoods; - break; - case AHB_YELLOW_TG: - ++yellowTGoods; - break; - case AHB_GREY_I: - ++greyItems; - break; - case AHB_WHITE_I: - ++whiteItems; - break; - case AHB_GREEN_I: - ++greenItems; - break; - case AHB_BLUE_I: - ++blueItems; - break; - case AHB_PURPLE_I: - ++purpleItems; - break; - case AHB_ORANGE_I: - ++orangeItems; - break; - case AHB_YELLOW_I: - ++yellowItems; - break; - default: - break; - } - } - - void ResetItemCounts() - { - greyTGoods = 0; - whiteTGoods = 0; - greenTGoods = 0; - blueTGoods = 0; - purpleTGoods = 0; - orangeTGoods = 0; - yellowTGoods = 0; - - greyItems = 0; - whiteItems = 0; - greenItems = 0; - blueItems = 0; - purpleItems = 0; - orangeItems = 0; - yellowItems = 0; - } - - uint32 TotalItemCounts() - { - return( - greyTGoods + - whiteTGoods + - greenTGoods + - blueTGoods + - purpleTGoods + - orangeTGoods + - yellowTGoods + - - greyItems + - whiteItems + - greenItems + - blueItems + - purpleItems + - orangeItems + - yellowItems); - } - - uint32 GetItemCounts(uint32 color) - { - switch(color) - { - case AHB_GREY_TG: - return greyTGoods; - break; - case AHB_WHITE_TG: - return whiteTGoods; - break; - case AHB_GREEN_TG: - return greenTGoods; - break; - case AHB_BLUE_TG: - return blueTGoods; - break; - case AHB_PURPLE_TG: - return purpleTGoods; - break; - case AHB_ORANGE_TG: - return orangeTGoods; - break; - case AHB_YELLOW_TG: - return yellowTGoods; - break; - case AHB_GREY_I: - return greyItems; - break; - case AHB_WHITE_I: - return whiteItems; - break; - case AHB_GREEN_I: - return greenItems; - break; - case AHB_BLUE_I: - return blueItems; - break; - case AHB_PURPLE_I: - return purpleItems; - break; - case AHB_ORANGE_I: - return orangeItems; - break; - case AHB_YELLOW_I: - return yellowItems; - break; - default: - return 0; - break; - } - } - void SetBidsPerInterval(uint32 value) - { - buyerBidsPerInterval = value; - } - uint32 GetBidsPerInterval() - { - return buyerBidsPerInterval; - } - ~AHBConfig() - { - } -}; -class AuctionHouseBot -{ -private: - - bool debug_Out; - bool debug_Out_Filters; - - bool AHBSeller; - bool AHBBuyer; - bool BuyMethod; - bool SellMethod; - - uint32 AHBplayerAccount; - uint32 AHBplayerGUID; - uint32 ItemsPerCycle; - - //Begin Filters - - bool Vendor_Items; - bool Loot_Items; - bool Other_Items; - bool Vendor_TGs; - bool Loot_TGs; - bool Other_TGs; - - bool No_Bind; - bool Bind_When_Picked_Up; - bool Bind_When_Equipped; - bool Bind_When_Use; - bool Bind_Quest_Item; - - bool DisableBeta_PTR_Unused; - bool DisablePermEnchant; - bool DisableConjured; - bool DisableGems; - bool DisableMoney; - bool DisableMoneyLoot; - bool DisableLootable; - bool DisableKeys; - bool DisableDuration; - bool DisableBOP_Or_Quest_NoReqLevel; - - bool DisableWarriorItems; - bool DisablePaladinItems; - bool DisableHunterItems; - bool DisableRogueItems; - bool DisablePriestItems; - bool DisableDKItems; - bool DisableShamanItems; - bool DisableMageItems; - bool DisableWarlockItems; - bool DisableUnusedClassItems; - bool DisableDruidItems; - - uint32 DisableItemsBelowLevel; - uint32 DisableItemsAboveLevel; - uint32 DisableTGsBelowLevel; - uint32 DisableTGsAboveLevel; - uint32 DisableItemsBelowGUID; - uint32 DisableItemsAboveGUID; - uint32 DisableTGsBelowGUID; - uint32 DisableTGsAboveGUID; - uint32 DisableItemsBelowReqLevel; - uint32 DisableItemsAboveReqLevel; - uint32 DisableTGsBelowReqLevel; - uint32 DisableTGsAboveReqLevel; - uint32 DisableItemsBelowReqSkillRank; - uint32 DisableItemsAboveReqSkillRank; - uint32 DisableTGsBelowReqSkillRank; - uint32 DisableTGsAboveReqSkillRank; - - //End Filters - - AHBConfig AllianceConfig; - AHBConfig HordeConfig; - AHBConfig NeutralConfig; - - time_t _lastrun_a; - time_t _lastrun_h; - time_t _lastrun_n; - - inline uint32 minValue(uint32 a, uint32 b) { return a <= b ? a : b; }; - void addNewAuctions(Player *AHBplayer, AHBConfig *config); - void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session); - -public: - AuctionHouseBot(); - ~AuctionHouseBot(); - void Update(); - void Initialize(); - void LoadValues(AHBConfig*); - void DecrementItemCounts(AuctionEntry* ah, uint32 item_template); - void IncrementItemCounts(AuctionEntry* ah); - void Commands(uint32, uint32, uint32, char*); - uint32 GetAHBplayerGUID() { return AHBplayerGUID; }; -}; - -#define auctionbot Trinity::Singleton::Instance() - -#endif diff --git a/src/server/game/AI/CombatAI.cpp b/src/server/game/AI/CombatAI.cpp deleted file mode 100644 index 0d0ff17ffd7..00000000000 --- a/src/server/game/AI/CombatAI.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "CombatAI.h" -#include "SpellMgr.h" -#include "Vehicle.h" - -int AggressorAI::Permissible(const Creature *creature) -{ - // have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight - if (!creature->isCivilian() && !creature->IsNeutralToAll()) - return PERMIT_BASE_PROACTIVE; - - return PERMIT_BASE_NO; -} - -void AggressorAI::UpdateAI(const uint32 /*diff*/) -{ - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); -} - -// some day we will delete these useless things -int CombatAI::Permissible(const Creature * /*creature*/) -{ - return PERMIT_BASE_NO; -} - -int ArchorAI::Permissible(const Creature * /*creature*/) -{ - return PERMIT_BASE_NO; -} - -int TurretAI::Permissible(const Creature * /*creature*/) -{ - return PERMIT_BASE_NO; -} - -int AOEAI::Permissible(const Creature * /*creature*/) -{ - return PERMIT_BASE_NO; -} - -int VehicleAI::Permissible(const Creature * /*creature*/) -{ - return PERMIT_BASE_NO; -} - -void CombatAI::InitializeAI() -{ - for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) - if (me->m_spells[i] && GetSpellStore()->LookupEntry(me->m_spells[i])) - spells.push_back(me->m_spells[i]); - - CreatureAI::InitializeAI(); -} - -void CombatAI::Reset() -{ - events.Reset(); -} - -void CombatAI::JustDied(Unit *killer) -{ - for (SpellVct::iterator i = spells.begin(); i != spells.end(); ++i) - if (AISpellInfo[*i].condition == AICOND_DIE) - me->CastSpell(killer, *i, true); -} - -void CombatAI::EnterCombat(Unit *who) -{ - for (SpellVct::iterator i = spells.begin(); i != spells.end(); ++i) - { - if (AISpellInfo[*i].condition == AICOND_AGGRO) - me->CastSpell(who, *i, false); - else if (AISpellInfo[*i].condition == AICOND_COMBAT) - events.ScheduleEvent(*i, AISpellInfo[*i].cooldown + rand()%AISpellInfo[*i].cooldown); - } -} - -void CombatAI::UpdateAI(const uint32 diff) -{ - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (uint32 spellId = events.ExecuteEvent()) - { - DoCast(spellId); - events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + rand()%AISpellInfo[spellId].cooldown); - } - else - DoMeleeAttackIfReady(); -} - -///////////////// -//CasterAI -///////////////// - -void CasterAI::InitializeAI() -{ - CombatAI::InitializeAI(); - - float m_attackDist = 30.0f; - for (SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr) - if (AISpellInfo[*itr].condition == AICOND_COMBAT && m_attackDist > GetAISpellInfo(*itr)->maxRange) - m_attackDist = GetAISpellInfo(*itr)->maxRange; - if (m_attackDist == 30.0f) - m_attackDist = MELEE_RANGE; -} - -void CasterAI::EnterCombat(Unit *who) -{ - if (spells.empty()) - return; - - uint32 spell = rand()%spells.size(); - uint32 count = 0; - for (SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr, ++count) - { - if (AISpellInfo[*itr].condition == AICOND_AGGRO) - me->CastSpell(who, *itr, false); - else if (AISpellInfo[*itr].condition == AICOND_COMBAT) - { - uint32 cooldown = GetAISpellInfo(*itr)->realCooldown; - if (count == spell) - { - DoCast(spells[spell]); - cooldown += me->GetCurrentSpellCastTime(*itr); - } - events.ScheduleEvent(*itr, cooldown); - } - } -} - -void CasterAI::UpdateAI(const uint32 diff) -{ - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (uint32 spellId = events.ExecuteEvent()) - { - DoCast(spellId); - uint32 casttime = me->GetCurrentSpellCastTime(spellId); - events.ScheduleEvent(spellId, (casttime ? casttime : 500) + GetAISpellInfo(spellId)->realCooldown); - } -} - -////////////// -//ArchorAI -////////////// - -ArchorAI::ArchorAI(Creature *c) : CreatureAI(c) -{ - if (!me->m_spells[0]) - sLog.outError("ArchorAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry()); - - m_minRange = GetSpellMinRange(me->m_spells[0], false); - if (!m_minRange) - m_minRange = MELEE_RANGE; - me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false); - me->m_SightDistance = me->m_CombatDistance; -} - -void ArchorAI::AttackStart(Unit *who) -{ - if (!who) - return; - - if (me->IsWithinCombatRange(who, m_minRange)) - { - if (me->Attack(who, true) && !who->IsFlying()) - me->GetMotionMaster()->MoveChase(who); - } - else - { - if (me->Attack(who, false) && !who->IsFlying()) - me->GetMotionMaster()->MoveChase(who, me->m_CombatDistance); - } - - if (who->IsFlying()) - me->GetMotionMaster()->MoveIdle(); -} - -void ArchorAI::UpdateAI(const uint32 /*diff*/) -{ - if (!UpdateVictim()) - return; - - if (!me->IsWithinCombatRange(me->getVictim(), m_minRange)) - DoSpellAttackIfReady(me->m_spells[0]); - else - DoMeleeAttackIfReady(); -} - -////////////// -//TurretAI -////////////// - -TurretAI::TurretAI(Creature *c) : CreatureAI(c) -{ - if (!me->m_spells[0]) - sLog.outError("TurretAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry()); - - m_minRange = GetSpellMinRange(me->m_spells[0], false); - me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false); - me->m_SightDistance = me->m_CombatDistance; -} - -bool TurretAI::CanAIAttack(const Unit * /*who*/) const -{ - // TODO: use one function to replace it - if (!me->IsWithinCombatRange(me->getVictim(), me->m_CombatDistance) - || m_minRange && me->IsWithinCombatRange(me->getVictim(), m_minRange)) - return false; - return true; -} - -void TurretAI::AttackStart(Unit *who) -{ - if (who) - me->Attack(who, false); -} - -void TurretAI::UpdateAI(const uint32 /*diff*/) -{ - if (!UpdateVictim()) - return; - - DoSpellAttackIfReady(me->m_spells[0]); -} - -////////////// -//AOEAI -////////////// - -AOEAI::AOEAI(Creature *c) : CreatureAI(c) -{ - if (!me->m_spells[0]) - sLog.outError("AOEAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry()); - - me->SetVisibility(VISIBILITY_ON);//visible to see all spell anims - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);//can't be targeted - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_1);//can't be damaged - me->SetDisplayId(11686);//invisible model,around a size of a player -} - -bool AOEAI::CanAIAttack(const Unit * /*who*/) const -{ - return false; -} - -void AOEAI::AttackStart(Unit * /*who*/) -{ -} - -void AOEAI::UpdateAI(const uint32 /*diff*/) -{ - if (!me->HasAura(me->m_spells[0])) - me->CastSpell(me, me->m_spells[0],false); -} - -////////////// -//VehicleAI -////////////// - -VehicleAI::VehicleAI(Creature *c) : CreatureAI(c), m_vehicle(c->GetVehicleKit()), m_IsVehicleInUse(false), m_ConditionsTimer(VEHICLE_CONDITION_CHECK_TIME) -{ - LoadConditions(); - m_DoDismiss = false; - m_DismissTimer = VEHICLE_DISMISS_TIME; -} - - -//NOTE: VehicleAI::UpdateAI runs even while the vehicle is mounted -void VehicleAI::UpdateAI(const uint32 diff) -{ - CheckConditions(diff); - - if (m_DoDismiss) - { - if (m_DismissTimer < diff) - { - m_DoDismiss = false; - me->SetVisibility(VISIBILITY_OFF); - me->ForcedDespawn(); - }else m_DismissTimer -= diff; - } -} - -void VehicleAI::Reset() -{ - me->SetVisibility(VISIBILITY_ON); - - m_vehicle->Reset(); -} - -void VehicleAI::OnCharmed(bool apply) -{ - if (m_IsVehicleInUse && !apply && !conditions.empty())//was used and has conditions - { - m_DoDismiss = true;//needs reset - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - } - else if (apply) - m_DoDismiss = false;//in use again - m_DismissTimer = VEHICLE_DISMISS_TIME;//reset timer - m_IsVehicleInUse = apply; -} - -void VehicleAI::LoadConditions() -{ - conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, me->GetEntry()); - if (!conditions.empty()) - { - sLog.outDebug("VehicleAI::LoadConditions: loaded %u conditions", uint32(conditions.size())); - } -} - -void VehicleAI::CheckConditions(const uint32 diff) -{ - if(m_ConditionsTimer < diff) - { - if (!conditions.empty()) - { - for (SeatMap::iterator itr = m_vehicle->m_Seats.begin(); itr != m_vehicle->m_Seats.end(); ++itr) - if (Unit *passenger = itr->second.passenger) - { - if (Player* plr = passenger->ToPlayer()) - { - if (!sConditionMgr.IsPlayerMeetToConditions(plr, conditions)) - { - plr->ExitVehicle(); - return;//check other pessanger in next tick - } - } - } - } - m_ConditionsTimer = VEHICLE_CONDITION_CHECK_TIME; - } else m_ConditionsTimer -= diff; -} \ No newline at end of file diff --git a/src/server/game/AI/CombatAI.h b/src/server/game/AI/CombatAI.h deleted file mode 100644 index 8626b38dd37..00000000000 --- a/src/server/game/AI/CombatAI.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_COMBATAI_H -#define TRINITY_COMBATAI_H - -#include "CreatureAI.h" -#include "CreatureAIImpl.h" -#include "ConditionMgr.h" - -class Creature; - -class AggressorAI : public CreatureAI -{ - public: - explicit AggressorAI(Creature *c) : CreatureAI(c) {} - - void UpdateAI(const uint32); - static int Permissible(const Creature *); -}; - -typedef std::vector SpellVct; - -class CombatAI : public CreatureAI -{ - public: - explicit CombatAI(Creature *c) : CreatureAI(c) {} - - void InitializeAI(); - void Reset(); - void EnterCombat(Unit* who); - void JustDied(Unit *killer); - void UpdateAI(const uint32 diff); - static int Permissible(const Creature *); - protected: - EventMap events; - SpellVct spells; -}; - -class CasterAI : public CombatAI -{ - public: - explicit CasterAI(Creature *c) : CombatAI(c) { m_attackDist = MELEE_RANGE; } - void InitializeAI(); - void AttackStart(Unit * victim) { AttackStartCaster(victim, m_attackDist); } - void UpdateAI(const uint32 diff); - void EnterCombat(Unit * /*who*/); - private: - float m_attackDist; -}; - -struct ArchorAI : public CreatureAI -{ - public: - explicit ArchorAI(Creature *c); - void AttackStart(Unit *who); - void UpdateAI(const uint32 diff); - - static int Permissible(const Creature *); - protected: - float m_minRange; -}; - -struct TurretAI : public CreatureAI -{ - public: - explicit TurretAI(Creature *c); - bool CanAIAttack(const Unit *who) const; - void AttackStart(Unit *who); - void UpdateAI(const uint32 diff); - - static int Permissible(const Creature *); - protected: - float m_minRange; -}; - -struct AOEAI : public CreatureAI -{ - public: - explicit AOEAI(Creature *c); - bool CanAIAttack(const Unit *who) const; - void AttackStart(Unit *who); - void UpdateAI(const uint32 diff); - - static int Permissible(const Creature *); -}; -#define VEHICLE_CONDITION_CHECK_TIME 1000 -#define VEHICLE_DISMISS_TIME 5000 -struct VehicleAI : public CreatureAI -{ - public: - explicit VehicleAI(Creature *c); - - void UpdateAI(const uint32 diff); - static int Permissible(const Creature *); - void Reset(); - void MoveInLineOfSight(Unit *) {} - void AttackStart(Unit *) {} - void OnCharmed(bool apply); - - private: - Vehicle* m_vehicle; - bool m_IsVehicleInUse; - void LoadConditions(); - void CheckConditions(const uint32 diff); - ConditionList conditions; - uint32 m_ConditionsTimer; - bool m_DoDismiss; - uint32 m_DismissTimer; -}; - -#endif diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp new file mode 100644 index 00000000000..0d0ff17ffd7 --- /dev/null +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "CombatAI.h" +#include "SpellMgr.h" +#include "Vehicle.h" + +int AggressorAI::Permissible(const Creature *creature) +{ + // have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight + if (!creature->isCivilian() && !creature->IsNeutralToAll()) + return PERMIT_BASE_PROACTIVE; + + return PERMIT_BASE_NO; +} + +void AggressorAI::UpdateAI(const uint32 /*diff*/) +{ + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); +} + +// some day we will delete these useless things +int CombatAI::Permissible(const Creature * /*creature*/) +{ + return PERMIT_BASE_NO; +} + +int ArchorAI::Permissible(const Creature * /*creature*/) +{ + return PERMIT_BASE_NO; +} + +int TurretAI::Permissible(const Creature * /*creature*/) +{ + return PERMIT_BASE_NO; +} + +int AOEAI::Permissible(const Creature * /*creature*/) +{ + return PERMIT_BASE_NO; +} + +int VehicleAI::Permissible(const Creature * /*creature*/) +{ + return PERMIT_BASE_NO; +} + +void CombatAI::InitializeAI() +{ + for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) + if (me->m_spells[i] && GetSpellStore()->LookupEntry(me->m_spells[i])) + spells.push_back(me->m_spells[i]); + + CreatureAI::InitializeAI(); +} + +void CombatAI::Reset() +{ + events.Reset(); +} + +void CombatAI::JustDied(Unit *killer) +{ + for (SpellVct::iterator i = spells.begin(); i != spells.end(); ++i) + if (AISpellInfo[*i].condition == AICOND_DIE) + me->CastSpell(killer, *i, true); +} + +void CombatAI::EnterCombat(Unit *who) +{ + for (SpellVct::iterator i = spells.begin(); i != spells.end(); ++i) + { + if (AISpellInfo[*i].condition == AICOND_AGGRO) + me->CastSpell(who, *i, false); + else if (AISpellInfo[*i].condition == AICOND_COMBAT) + events.ScheduleEvent(*i, AISpellInfo[*i].cooldown + rand()%AISpellInfo[*i].cooldown); + } +} + +void CombatAI::UpdateAI(const uint32 diff) +{ + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (uint32 spellId = events.ExecuteEvent()) + { + DoCast(spellId); + events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + rand()%AISpellInfo[spellId].cooldown); + } + else + DoMeleeAttackIfReady(); +} + +///////////////// +//CasterAI +///////////////// + +void CasterAI::InitializeAI() +{ + CombatAI::InitializeAI(); + + float m_attackDist = 30.0f; + for (SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr) + if (AISpellInfo[*itr].condition == AICOND_COMBAT && m_attackDist > GetAISpellInfo(*itr)->maxRange) + m_attackDist = GetAISpellInfo(*itr)->maxRange; + if (m_attackDist == 30.0f) + m_attackDist = MELEE_RANGE; +} + +void CasterAI::EnterCombat(Unit *who) +{ + if (spells.empty()) + return; + + uint32 spell = rand()%spells.size(); + uint32 count = 0; + for (SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr, ++count) + { + if (AISpellInfo[*itr].condition == AICOND_AGGRO) + me->CastSpell(who, *itr, false); + else if (AISpellInfo[*itr].condition == AICOND_COMBAT) + { + uint32 cooldown = GetAISpellInfo(*itr)->realCooldown; + if (count == spell) + { + DoCast(spells[spell]); + cooldown += me->GetCurrentSpellCastTime(*itr); + } + events.ScheduleEvent(*itr, cooldown); + } + } +} + +void CasterAI::UpdateAI(const uint32 diff) +{ + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (uint32 spellId = events.ExecuteEvent()) + { + DoCast(spellId); + uint32 casttime = me->GetCurrentSpellCastTime(spellId); + events.ScheduleEvent(spellId, (casttime ? casttime : 500) + GetAISpellInfo(spellId)->realCooldown); + } +} + +////////////// +//ArchorAI +////////////// + +ArchorAI::ArchorAI(Creature *c) : CreatureAI(c) +{ + if (!me->m_spells[0]) + sLog.outError("ArchorAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry()); + + m_minRange = GetSpellMinRange(me->m_spells[0], false); + if (!m_minRange) + m_minRange = MELEE_RANGE; + me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false); + me->m_SightDistance = me->m_CombatDistance; +} + +void ArchorAI::AttackStart(Unit *who) +{ + if (!who) + return; + + if (me->IsWithinCombatRange(who, m_minRange)) + { + if (me->Attack(who, true) && !who->IsFlying()) + me->GetMotionMaster()->MoveChase(who); + } + else + { + if (me->Attack(who, false) && !who->IsFlying()) + me->GetMotionMaster()->MoveChase(who, me->m_CombatDistance); + } + + if (who->IsFlying()) + me->GetMotionMaster()->MoveIdle(); +} + +void ArchorAI::UpdateAI(const uint32 /*diff*/) +{ + if (!UpdateVictim()) + return; + + if (!me->IsWithinCombatRange(me->getVictim(), m_minRange)) + DoSpellAttackIfReady(me->m_spells[0]); + else + DoMeleeAttackIfReady(); +} + +////////////// +//TurretAI +////////////// + +TurretAI::TurretAI(Creature *c) : CreatureAI(c) +{ + if (!me->m_spells[0]) + sLog.outError("TurretAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry()); + + m_minRange = GetSpellMinRange(me->m_spells[0], false); + me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false); + me->m_SightDistance = me->m_CombatDistance; +} + +bool TurretAI::CanAIAttack(const Unit * /*who*/) const +{ + // TODO: use one function to replace it + if (!me->IsWithinCombatRange(me->getVictim(), me->m_CombatDistance) + || m_minRange && me->IsWithinCombatRange(me->getVictim(), m_minRange)) + return false; + return true; +} + +void TurretAI::AttackStart(Unit *who) +{ + if (who) + me->Attack(who, false); +} + +void TurretAI::UpdateAI(const uint32 /*diff*/) +{ + if (!UpdateVictim()) + return; + + DoSpellAttackIfReady(me->m_spells[0]); +} + +////////////// +//AOEAI +////////////// + +AOEAI::AOEAI(Creature *c) : CreatureAI(c) +{ + if (!me->m_spells[0]) + sLog.outError("AOEAI set for creature (entry = %u) with spell1=0. AI will do nothing", me->GetEntry()); + + me->SetVisibility(VISIBILITY_ON);//visible to see all spell anims + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);//can't be targeted + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_1);//can't be damaged + me->SetDisplayId(11686);//invisible model,around a size of a player +} + +bool AOEAI::CanAIAttack(const Unit * /*who*/) const +{ + return false; +} + +void AOEAI::AttackStart(Unit * /*who*/) +{ +} + +void AOEAI::UpdateAI(const uint32 /*diff*/) +{ + if (!me->HasAura(me->m_spells[0])) + me->CastSpell(me, me->m_spells[0],false); +} + +////////////// +//VehicleAI +////////////// + +VehicleAI::VehicleAI(Creature *c) : CreatureAI(c), m_vehicle(c->GetVehicleKit()), m_IsVehicleInUse(false), m_ConditionsTimer(VEHICLE_CONDITION_CHECK_TIME) +{ + LoadConditions(); + m_DoDismiss = false; + m_DismissTimer = VEHICLE_DISMISS_TIME; +} + + +//NOTE: VehicleAI::UpdateAI runs even while the vehicle is mounted +void VehicleAI::UpdateAI(const uint32 diff) +{ + CheckConditions(diff); + + if (m_DoDismiss) + { + if (m_DismissTimer < diff) + { + m_DoDismiss = false; + me->SetVisibility(VISIBILITY_OFF); + me->ForcedDespawn(); + }else m_DismissTimer -= diff; + } +} + +void VehicleAI::Reset() +{ + me->SetVisibility(VISIBILITY_ON); + + m_vehicle->Reset(); +} + +void VehicleAI::OnCharmed(bool apply) +{ + if (m_IsVehicleInUse && !apply && !conditions.empty())//was used and has conditions + { + m_DoDismiss = true;//needs reset + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } + else if (apply) + m_DoDismiss = false;//in use again + m_DismissTimer = VEHICLE_DISMISS_TIME;//reset timer + m_IsVehicleInUse = apply; +} + +void VehicleAI::LoadConditions() +{ + conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, me->GetEntry()); + if (!conditions.empty()) + { + sLog.outDebug("VehicleAI::LoadConditions: loaded %u conditions", uint32(conditions.size())); + } +} + +void VehicleAI::CheckConditions(const uint32 diff) +{ + if(m_ConditionsTimer < diff) + { + if (!conditions.empty()) + { + for (SeatMap::iterator itr = m_vehicle->m_Seats.begin(); itr != m_vehicle->m_Seats.end(); ++itr) + if (Unit *passenger = itr->second.passenger) + { + if (Player* plr = passenger->ToPlayer()) + { + if (!sConditionMgr.IsPlayerMeetToConditions(plr, conditions)) + { + plr->ExitVehicle(); + return;//check other pessanger in next tick + } + } + } + } + m_ConditionsTimer = VEHICLE_CONDITION_CHECK_TIME; + } else m_ConditionsTimer -= diff; +} \ No newline at end of file diff --git a/src/server/game/AI/CoreAI/CombatAI.h b/src/server/game/AI/CoreAI/CombatAI.h new file mode 100644 index 00000000000..8626b38dd37 --- /dev/null +++ b/src/server/game/AI/CoreAI/CombatAI.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_COMBATAI_H +#define TRINITY_COMBATAI_H + +#include "CreatureAI.h" +#include "CreatureAIImpl.h" +#include "ConditionMgr.h" + +class Creature; + +class AggressorAI : public CreatureAI +{ + public: + explicit AggressorAI(Creature *c) : CreatureAI(c) {} + + void UpdateAI(const uint32); + static int Permissible(const Creature *); +}; + +typedef std::vector SpellVct; + +class CombatAI : public CreatureAI +{ + public: + explicit CombatAI(Creature *c) : CreatureAI(c) {} + + void InitializeAI(); + void Reset(); + void EnterCombat(Unit* who); + void JustDied(Unit *killer); + void UpdateAI(const uint32 diff); + static int Permissible(const Creature *); + protected: + EventMap events; + SpellVct spells; +}; + +class CasterAI : public CombatAI +{ + public: + explicit CasterAI(Creature *c) : CombatAI(c) { m_attackDist = MELEE_RANGE; } + void InitializeAI(); + void AttackStart(Unit * victim) { AttackStartCaster(victim, m_attackDist); } + void UpdateAI(const uint32 diff); + void EnterCombat(Unit * /*who*/); + private: + float m_attackDist; +}; + +struct ArchorAI : public CreatureAI +{ + public: + explicit ArchorAI(Creature *c); + void AttackStart(Unit *who); + void UpdateAI(const uint32 diff); + + static int Permissible(const Creature *); + protected: + float m_minRange; +}; + +struct TurretAI : public CreatureAI +{ + public: + explicit TurretAI(Creature *c); + bool CanAIAttack(const Unit *who) const; + void AttackStart(Unit *who); + void UpdateAI(const uint32 diff); + + static int Permissible(const Creature *); + protected: + float m_minRange; +}; + +struct AOEAI : public CreatureAI +{ + public: + explicit AOEAI(Creature *c); + bool CanAIAttack(const Unit *who) const; + void AttackStart(Unit *who); + void UpdateAI(const uint32 diff); + + static int Permissible(const Creature *); +}; +#define VEHICLE_CONDITION_CHECK_TIME 1000 +#define VEHICLE_DISMISS_TIME 5000 +struct VehicleAI : public CreatureAI +{ + public: + explicit VehicleAI(Creature *c); + + void UpdateAI(const uint32 diff); + static int Permissible(const Creature *); + void Reset(); + void MoveInLineOfSight(Unit *) {} + void AttackStart(Unit *) {} + void OnCharmed(bool apply); + + private: + Vehicle* m_vehicle; + bool m_IsVehicleInUse; + void LoadConditions(); + void CheckConditions(const uint32 diff); + ConditionList conditions; + uint32 m_ConditionsTimer; + bool m_DoDismiss; + uint32 m_DismissTimer; +}; + +#endif diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp new file mode 100644 index 00000000000..19d5b5d8354 --- /dev/null +++ b/src/server/game/AI/CoreAI/GuardAI.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GuardAI.h" +#include "Errors.h" +#include "Player.h" +#include "ObjectAccessor.h" +#include "World.h" +#include "CreatureAIImpl.h" + +int GuardAI::Permissible(const Creature *creature) +{ + if (creature->isGuard()) + return PERMIT_BASE_SPECIAL; + + return PERMIT_BASE_NO; +} + +GuardAI::GuardAI(Creature *c) : CreatureAI(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +{ +} + +void GuardAI::MoveInLineOfSight(Unit *u) +{ + // Ignore Z for flying creatures + if (!me->canFly() && me->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE) + return; + + if (!me->getVictim() && me->canAttack(u) && + (u->IsHostileToPlayers() || me->IsHostileTo(u) /*|| u->getVictim() && me->IsFriendlyTo(u->getVictim())*/) && + u->isInAccessiblePlaceFor(me)) + { + float attackRadius = me->GetAttackDistance(u); + if (me->IsWithinDistInMap(u,attackRadius)) + { + //Need add code to let guard support player + AttackStart(u); + //u->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); + } + } +} + +void GuardAI::EnterEvadeMode() +{ + if (!me->isAlive()) + { + DEBUG_LOG("Creature stopped attacking because he is dead [guid=%u]", me->GetGUIDLow()); + me->GetMotionMaster()->MoveIdle(); + + i_state = STATE_NORMAL; + + i_victimGuid = 0; + me->CombatStop(true); + me->DeleteThreatList(); + return; + } + + Unit* victim = ObjectAccessor::GetUnit(*me, i_victimGuid); + + if (!victim) + { + DEBUG_LOG("Creature stopped attacking because victim does not exist [guid=%u]", me->GetGUIDLow()); + } + else if (!victim ->isAlive()) + { + DEBUG_LOG("Creature stopped attacking because victim is dead [guid=%u]", me->GetGUIDLow()); + } + else if (victim ->HasStealthAura()) + { + DEBUG_LOG("Creature stopped attacking because victim is using stealth [guid=%u]", me->GetGUIDLow()); + } + else if (victim ->isInFlight()) + { + DEBUG_LOG("Creature stopped attacking because victim is flying away [guid=%u]", me->GetGUIDLow()); + } + else + { + DEBUG_LOG("Creature stopped attacking because victim outran him [guid=%u]", me->GetGUIDLow()); + } + + me->RemoveAllAuras(); + me->DeleteThreatList(); + i_victimGuid = 0; + me->CombatStop(true); + i_state = STATE_NORMAL; + + // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + me->GetMotionMaster()->MoveTargetedHome(); +} + +void GuardAI::UpdateAI(const uint32 /*diff*/) +{ + // update i_victimGuid if me->getVictim() !=0 and changed + if (!UpdateVictim()) + return; + + i_victimGuid = me->getVictim()->GetGUID(); + + if (me->isAttackReady()) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } +} + +bool GuardAI::IsVisible(Unit *pl) const +{ + return me->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_GUARDER)) + && pl->isVisibleForOrDetect(me,true); +} + +void GuardAI::JustDied(Unit *killer) +{ + if (Player* pkiller = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) + me->SendZoneUnderAttackMessage(pkiller); +} diff --git a/src/server/game/AI/CoreAI/GuardAI.h b/src/server/game/AI/CoreAI/GuardAI.h new file mode 100644 index 00000000000..73e3692a770 --- /dev/null +++ b/src/server/game/AI/CoreAI/GuardAI.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GUARDAI_H +#define TRINITY_GUARDAI_H + +#include "CreatureAI.h" +#include "Timer.h" + +class Creature; + +class GuardAI : public CreatureAI +{ + enum GuardState + { + STATE_NORMAL = 1, + STATE_LOOK_AT_VICTIM = 2 + }; + + public: + + explicit GuardAI(Creature *c); + + void MoveInLineOfSight(Unit *); + void EnterEvadeMode(); + void JustDied(Unit *); + bool IsVisible(Unit *) const; + + void UpdateAI(const uint32); + static int Permissible(const Creature *); + + private: + uint64 i_victimGuid; + GuardState i_state; + TimeTracker i_tracker; +}; +#endif + diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp new file mode 100644 index 00000000000..c6c92f6df04 --- /dev/null +++ b/src/server/game/AI/CoreAI/PassiveAI.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PassiveAI.h" +#include "Creature.h" +#include "TemporarySummon.h" + +PassiveAI::PassiveAI(Creature *c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); } +PossessedAI::PossessedAI(Creature *c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); } +NullCreatureAI::NullCreatureAI(Creature *c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); } + +void PassiveAI::UpdateAI(const uint32) +{ + if (me->isInCombat() && me->getAttackers().empty()) + EnterEvadeMode(); +} + +void PossessedAI::AttackStart(Unit *target) +{ + me->Attack(target, true); +} + +void PossessedAI::UpdateAI(const uint32 /*diff*/) +{ + if (me->getVictim()) + { + if (!me->canAttack(me->getVictim())) + me->AttackStop(); + else + DoMeleeAttackIfReady(); + } +} + +void PossessedAI::JustDied(Unit * /*u*/) +{ + // We died while possessed, disable our loot + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); +} + +void PossessedAI::KilledUnit(Unit* victim) +{ + // We killed a creature, disable victim's loot + if (victim->GetTypeId() == TYPEID_UNIT) + victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); +} + +void CritterAI::DamageTaken(Unit * /*done_by*/, uint32 &) +{ + if (!me->hasUnitState(UNIT_STAT_FLEEING)) + me->SetControlled(true, UNIT_STAT_FLEEING); +} + +void CritterAI::EnterEvadeMode() +{ + if (me->hasUnitState(UNIT_STAT_FLEEING)) + me->SetControlled(false, UNIT_STAT_FLEEING); + CreatureAI::EnterEvadeMode(); +} + +void TriggerAI::IsSummonedBy(Unit *summoner) +{ + if (me->m_spells[0]) + me->CastSpell(me, me->m_spells[0], false, 0, 0, summoner->GetGUID()); +} diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h new file mode 100644 index 00000000000..c13e2d1a63c --- /dev/null +++ b/src/server/game/AI/CoreAI/PassiveAI.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_PASSIVEAI_H +#define TRINITY_PASSIVEAI_H + +#include "CreatureAI.h" +//#include "CreatureAIImpl.h" + +class PassiveAI : public CreatureAI +{ + public: + explicit PassiveAI(Creature *c); + + void MoveInLineOfSight(Unit *) {} + void AttackStart(Unit *) {} + void UpdateAI(const uint32); + + static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } +}; + +class PossessedAI : public CreatureAI +{ + public: + explicit PossessedAI(Creature *c); + + void MoveInLineOfSight(Unit *) {} + void AttackStart(Unit *target); + void UpdateAI(const uint32); + void EnterEvadeMode() {} + + void JustDied(Unit*); + void KilledUnit(Unit* victim); + + static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } +}; + +class NullCreatureAI : public CreatureAI +{ + public: + explicit NullCreatureAI(Creature *c); + + void MoveInLineOfSight(Unit *) {} + void AttackStart(Unit *) {} + void UpdateAI(const uint32) {} + void EnterEvadeMode() {} + void OnCharmed(bool /*apply*/) {} + + static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } +}; + +class CritterAI : public PassiveAI +{ + public: + explicit CritterAI(Creature *c) : PassiveAI(c) {} + + void DamageTaken(Unit *done_by, uint32 & /*damage*/); + void EnterEvadeMode(); +}; + +class TriggerAI : public NullCreatureAI +{ + public: + explicit TriggerAI(Creature *c) : NullCreatureAI(c) {} + void IsSummonedBy(Unit *summoner); +}; + +#endif + diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp new file mode 100644 index 00000000000..09ec8fae53f --- /dev/null +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PetAI.h" +#include "Errors.h" +#include "Pet.h" +#include "Player.h" +#include "DBCStores.h" +#include "Spell.h" +#include "ObjectAccessor.h" +#include "SpellMgr.h" +#include "Creature.h" +#include "World.h" +#include "Util.h" + +int PetAI::Permissible(const Creature *creature) +{ + if (creature->isPet()) + return PERMIT_BASE_SPECIAL; + + return PERMIT_BASE_NO; +} + +PetAI::PetAI(Creature *c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK) +{ + m_AllySet.clear(); + UpdateAllies(); +} + +void PetAI::EnterEvadeMode() +{ +} + +bool PetAI::_needToStop() const +{ + // This is needed for charmed creatures, as once their target was reset other effects can trigger threat + if (me->isCharmed() && me->getVictim() == me->GetCharmer()) + return true; + + return !me->canAttack(me->getVictim()); +} + +void PetAI::_stopAttack() +{ + if (!me->isAlive()) + { + DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", me->GetGUIDLow()); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->CombatStop(); + me->getHostileRefManager().deleteReferences(); + + return; + } + + me->AttackStop(); + me->GetCharmInfo()->SetIsCommandAttack(false); + HandleReturnMovement(); +} + +void PetAI::UpdateAI(const uint32 diff) +{ + if (!me->isAlive()) + return; + + Unit* owner = me->GetCharmerOrOwner(); + + if (m_updateAlliesTimer <= diff) + // UpdateAllies self set update timer + UpdateAllies(); + else + m_updateAlliesTimer -= diff; + + // me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc. + if (me->getVictim()) + { + if (_needToStop()) + { + DEBUG_LOG("Pet AI stoped attacking [guid=%u]", me->GetGUIDLow()); + _stopAttack(); + return; + } + + DoMeleeAttackIfReady(); + } + else if (owner && me->GetCharmInfo()) //no victim + { + Unit *nextTarget = SelectNextTarget(); + + if (nextTarget) + AttackStart(nextTarget); + else + HandleReturnMovement(); + } + else if (owner && !me->hasUnitState(UNIT_STAT_FOLLOW)) // no charm info and no victim + me->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST, me->GetFollowAngle()); + + if (!me->GetCharmInfo()) + return; + + // Autocast (casted only in combat or persistent spells in any state) + if (me->GetGlobalCooldown() == 0 && !me->hasUnitState(UNIT_STAT_CASTING)) + { + typedef std::vector > TargetSpellList; + TargetSpellList targetSpellStore; + + for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i) + { + uint32 spellID = me->GetPetAutoSpellOnPos(i); + if (!spellID) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); + if (!spellInfo) + continue; + + // ignore some combinations of combat state and combat/noncombat spells + if (!me->getVictim()) + { + // ignore attacking spells, and allow only self/around spells + if (!IsPositiveSpell(spellInfo->Id)) + continue; + + // non combat spells allowed + // only pet spells have IsNonCombatSpell and not fit this reqs: + // Consume Shadows, Lesser Invisibility, so ignore checks for its + if (!IsNonCombatSpell(spellInfo)) + { + // allow only spell without spell cost or with spell cost but not duration limit + int32 duration = GetSpellDuration(spellInfo); + if ((spellInfo->manaCost || spellInfo->ManaCostPercentage || spellInfo->manaPerSecond) && duration > 0) + continue; + + // allow only spell without cooldown > duration + int32 cooldown = GetSpellRecoveryTime(spellInfo); + if (cooldown >= 0 && duration >= 0 && cooldown > duration) + continue; + } + } + else + { + // just ignore non-combat spells + if (IsNonCombatSpell(spellInfo)) + continue; + } + + Spell *spell = new Spell(me, spellInfo, false, 0); + + // Fix to allow pets on STAY to autocast + if (me->getVictim() && _CanAttack(me->getVictim()) && spell->CanAutoCast(me->getVictim())) + { + targetSpellStore.push_back(std::make_pair(me->getVictim(), spell)); + continue; + } + else + { + bool spellUsed = false; + for (std::set::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) + { + Unit* Target = ObjectAccessor::GetUnit(*me,*tar); + + //only buff targets that are in combat, unless the spell can only be cast while out of combat + if (!Target) + continue; + + if (spell->CanAutoCast(Target)) + { + targetSpellStore.push_back(std::make_pair(Target, spell)); + spellUsed = true; + break; + } + } + if (!spellUsed) + delete spell; + } + } + + //found units to cast on to + if (!targetSpellStore.empty()) + { + uint32 index = urand(0, targetSpellStore.size() - 1); + + Spell* spell = targetSpellStore[index].second; + Unit* target = targetSpellStore[index].first; + + targetSpellStore.erase(targetSpellStore.begin() + index); + + SpellCastTargets targets; + targets.setUnitTarget(target); + + if (!me->HasInArc(M_PI, target)) + { + me->SetInFront(target); + if (target && target->GetTypeId() == TYPEID_PLAYER) + me->SendUpdateToPlayer(target->ToPlayer()); + + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + me->SendUpdateToPlayer(owner->ToPlayer()); + } + + me->AddCreatureSpellCooldown(spell->m_spellInfo->Id); + + spell->prepare(&targets); + } + + // deleted cached Spell objects + for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr) + delete itr->second; + } +} + +void PetAI::UpdateAllies() +{ + Unit* owner = me->GetCharmerOrOwner(); + Group *pGroup = NULL; + + m_updateAlliesTimer = 10*IN_MILISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance + + if (!owner) + return; + else if (owner->GetTypeId() == TYPEID_PLAYER) + pGroup = owner->ToPlayer()->GetGroup(); + + //only pet and owner/not in group->ok + if (m_AllySet.size() == 2 && !pGroup) + return; + //owner is in group; group members filled in already (no raid -> subgroupcount = whole count) + if (pGroup && !pGroup->isRaidGroup() && m_AllySet.size() == (pGroup->GetMembersCount() + 2)) + return; + + m_AllySet.clear(); + m_AllySet.insert(me->GetGUID()); + if (pGroup) //add group + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + if (!Target || !pGroup->SameSubGroup((Player*)owner, Target)) + continue; + + if (Target->GetGUID() == owner->GetGUID()) + continue; + + m_AllySet.insert(Target->GetGUID()); + } + } + else //remove group + m_AllySet.insert(owner->GetGUID()); +} + +void PetAI::KilledUnit(Unit *victim) +{ + // Called from Unit::Kill() in case where pet or owner kills something + // if owner killed this victim, pet may still be attacking something else + if (me->getVictim() && me->getVictim() != victim) + return; + + // Clear target just in case. May help problem where health / focus / mana + // regen gets stuck. Also resets attack command. + // Can't use _stopAttack() because that activates movement handlers and ignores + // next target selection + me->AttackStop(); + me->GetCharmInfo()->SetIsCommandAttack(false); + + Unit *nextTarget = SelectNextTarget(); + + if (nextTarget) + AttackStart(nextTarget); + else + HandleReturnMovement(); // Return +} + +void PetAI::AttackStart(Unit *target) +{ + // Overrides Unit::AttackStart to correctly evaluate Pet states + + // Check all pet states to decide if we can attack this target + if (!_CanAttack(target)) + return; + + // We can attack, should we chase or not? + if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) + DoAttack(target,true); // FOLLOW, attack with chase + else + { + if (me->GetCharmInfo()->IsCommandAttack()) + DoAttack(target,true); // STAY or FOLLOW, player clicked "attack" so attack with chase + else + DoAttack(target,false); // STAY, target in range, attack not clicked so attack without chase + } +} + +Unit *PetAI::SelectNextTarget() +{ + // Provides next target selection after current target death + + // Passive pets don't do next target selection + if (me->HasReactState(REACT_PASSIVE)) + return NULL; + + // Check pet's attackers first to prevent dragging mobs back + // to owner + if (me->getAttackerForHelper()) + return me->getAttackerForHelper(); + + // Check owner's attackers if pet didn't have any + if (me->GetCharmerOrOwner()->getAttackerForHelper()) + return me->GetCharmerOrOwner()->getAttackerForHelper(); + + // 3.0.2 - Pets now start attacking their owners target in defensive mode as soon as the hunter does + if (me->GetCharmerOrOwner()->getVictim()) + return me->GetCharmerOrOwner()->getVictim(); + + // Default + return NULL; +} + +void PetAI::HandleReturnMovement() +{ + // Handles moving the pet back to stay or owner + + if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY)) + { + if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning()) + { + // Return to previous position where stay was clicked + if (!me->GetCharmInfo()->IsCommandAttack()) + { + float x,y,z; + + me->GetCharmInfo()->GetStayPosition(x, y, z); + me->GetCharmInfo()->SetIsReturning(true); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(me->GetGUIDLow(),x,y,z); + } + } + } + else // COMMAND_FOLLOW + { + if (!me->GetCharmInfo()->IsFollowing() && !me->GetCharmInfo()->IsReturning()) + { + if (!me->GetCharmInfo()->IsCommandAttack()) + { + me->GetCharmInfo()->SetIsReturning(true); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(me->GetCharmerOrOwner(), PET_FOLLOW_DIST, me->GetFollowAngle()); + } + } + } + +} + +void PetAI::DoAttack(Unit *target, bool chase) +{ + // Handles attack with or without chase and also resets all + // PetAI flags for next update / creature kill + + // me->GetCharmInfo()->SetIsCommandAttack(false); + + // The following conditions are true if chase == true + // (Follow && (Aggressive || Defensive)) + // ((Stay || Follow) && (Passive && player clicked attack)) + + if (chase) + { + if (me->Attack(target,true)) + { + me->GetCharmInfo()->SetIsAtStay(false); + me->GetCharmInfo()->SetIsFollowing(false); + me->GetCharmInfo()->SetIsReturning(false); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(target); + } + } + else // (Stay && ((Aggressive || Defensive) && In Melee Range))) + { + me->GetCharmInfo()->SetIsAtStay(true); + me->GetCharmInfo()->SetIsFollowing(false); + me->GetCharmInfo()->SetIsReturning(false); + me->Attack(target,true); + } +} + +void PetAI::MovementInform(uint32 moveType, uint32 data) +{ + // Receives notification when pet reaches stay or follow owner + switch (moveType) + { + case POINT_MOTION_TYPE: + { + // Pet is returning to where stay was clicked. data should be + // pet's GUIDLow since we set that as the waypoint ID + if (data == me->GetGUIDLow() && me->GetCharmInfo()->IsReturning()) + { + me->GetCharmInfo()->SetIsAtStay(true); + me->GetCharmInfo()->SetIsReturning(false); + me->GetCharmInfo()->SetIsFollowing(false); + me->GetCharmInfo()->SetIsCommandAttack(false); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + } + } + break; + + case TARGETED_MOTION_TYPE: + { + // If data is owner's GUIDLow then we've reached follow point, + // otherwise we're probably chasing a creature + if (me->GetCharmerOrOwner() && me->GetCharmInfo() && data == me->GetCharmerOrOwner()->GetGUIDLow() && me->GetCharmInfo()->IsReturning()) + { + me->GetCharmInfo()->SetIsAtStay(false); + me->GetCharmInfo()->SetIsReturning(false); + me->GetCharmInfo()->SetIsFollowing(true); + me->GetCharmInfo()->SetIsCommandAttack(false); + me->addUnitState(UNIT_STAT_FOLLOW); + } + } + break; + + default: + break; + } +} + +bool PetAI::_CanAttack(Unit *target) +{ + // Evaluates wether a pet can attack a specific + // target based on CommandState, ReactState and other flags + + // Returning - check first since pets returning ignore attacks + if (me->GetCharmInfo()->IsReturning()) + return false; + + // Passive - check now so we don't have to worry about passive in later checks + if (me->HasReactState(REACT_PASSIVE)) + return me->GetCharmInfo()->IsCommandAttack(); + + // Pets commanded to attack should not stop their approach if attacked by another creature + if (me->getVictim() && (me->getVictim() != target)) + return !me->GetCharmInfo()->IsCommandAttack(); + + // From this point on, pet will always be either aggressive or defensive + + // Stay - can attack if target is within range or commanded to + if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY)) + return (me->IsWithinMeleeRange(target, MIN_MELEE_REACH) || me->GetCharmInfo()->IsCommandAttack()); + + // Follow + if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) + return true; + + // default, though we shouldn't ever get here + return false; +} diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h new file mode 100644 index 00000000000..f6087a129ae --- /dev/null +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_PETAI_H +#define TRINITY_PETAI_H + +#include "CreatureAI.h" +#include "Timer.h" + +class Creature; +class Spell; + +class PetAI : public CreatureAI +{ + public: + + explicit PetAI(Creature *c); + + void EnterEvadeMode(); + void JustDied(Unit * /*who*/) { _stopAttack(); } + + void UpdateAI(const uint32); + static int Permissible(const Creature *); + + void KilledUnit(Unit * /*victim*/); + void AttackStart(Unit *target); + void MovementInform(uint32 moveType, uint32 data); + + private: + bool _isVisible(Unit *) const; + bool _needToStop(void) const; + void _stopAttack(void); + + void UpdateAllies(); + + TimeTracker i_tracker; + bool inCombat; + std::set m_AllySet; + uint32 m_updateAlliesTimer; + + Unit *SelectNextTarget(); + void HandleReturnMovement(); + void DoAttack(Unit *target, bool chase); + bool _CanAttack(Unit *target); +}; +#endif + diff --git a/src/server/game/AI/CoreAI/ReactorAI.cpp b/src/server/game/AI/CoreAI/ReactorAI.cpp new file mode 100644 index 00000000000..fdca6314747 --- /dev/null +++ b/src/server/game/AI/CoreAI/ReactorAI.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ByteBuffer.h" +#include "ReactorAI.h" +#include "Errors.h" +#include "Log.h" +#include "ObjectAccessor.h" +#include "CreatureAIImpl.h" + +#define REACTOR_VISIBLE_RANGE (26.46f) + +int +ReactorAI::Permissible(const Creature *creature) +{ + if (creature->isCivilian() || creature->IsNeutralToAll()) + return PERMIT_BASE_REACTIVE; + + return PERMIT_BASE_NO; +} + +void +ReactorAI::MoveInLineOfSight(Unit *) +{ +} + +void +ReactorAI::UpdateAI(const uint32 /*time_diff*/) +{ + // update i_victimGuid if me->getVictim() !=0 and changed + if (!UpdateVictim()) + return; + + if (me->isAttackReady()) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } +} diff --git a/src/server/game/AI/CoreAI/ReactorAI.h b/src/server/game/AI/CoreAI/ReactorAI.h new file mode 100644 index 00000000000..ae4e6403962 --- /dev/null +++ b/src/server/game/AI/CoreAI/ReactorAI.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_REACTORAI_H +#define TRINITY_REACTORAI_H + +#include "CreatureAI.h" + +class Unit; + +class ReactorAI : public CreatureAI +{ + public: + + explicit ReactorAI(Creature *c) : CreatureAI(c) {} + + void MoveInLineOfSight(Unit *); + + void UpdateAI(const uint32); + static int Permissible(const Creature *); +}; +#endif + diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp new file mode 100644 index 00000000000..a6464f189e8 --- /dev/null +++ b/src/server/game/AI/CoreAI/TotemAI.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "TotemAI.h" +#include "Totem.h" +#include "Creature.h" +#include "DBCStores.h" +#include "ObjectAccessor.h" +#include "SpellMgr.h" + +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +int +TotemAI::Permissible(const Creature *creature) +{ + if (creature->isTotem()) + return PERMIT_BASE_PROACTIVE; + + return PERMIT_BASE_NO; +} + +TotemAI::TotemAI(Creature *c) : CreatureAI(c), i_victimGuid(0) +{ + assert(c->isTotem()); +} + +void +TotemAI::MoveInLineOfSight(Unit *) +{ +} + +void TotemAI::EnterEvadeMode() +{ + me->CombatStop(true); +} + +void +TotemAI::UpdateAI(const uint32 /*diff*/) +{ + if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE) + return; + + if (!me->isAlive() || me->IsNonMeleeSpellCasted(false)) + return; + + // Search spell + SpellEntry const *spellInfo = sSpellStore.LookupEntry(me->ToTotem()->GetSpell()); + if (!spellInfo) + return; + + // Get spell range + SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); + float max_range = GetSpellMaxRangeForHostile(srange); + + // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems + + // pointer to appropriate target if found any + Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL; + + // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) + if (!victim || + !victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) || + me->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(me,false)) + { + victim = NULL; + Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me, max_range); + Trinity::UnitLastSearcher checker(me, victim, u_check); + me->VisitNearbyObject(max_range, checker); + } + + // If have target + if (victim) + { + // remember + i_victimGuid = victim->GetGUID(); + + // attack + me->SetInFront(victim); // client change orientation by self + me->CastSpell(victim, me->ToTotem()->GetSpell(), false); + } + else + i_victimGuid = 0; +} + +void +TotemAI::AttackStart(Unit *) +{ + // Sentry totem sends ping on attack + if (me->GetEntry() == SENTRY_TOTEM_ENTRY && me->GetOwner()->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(MSG_MINIMAP_PING, (8+4+4)); + data << me->GetGUID(); + data << me->GetPositionX(); + data << me->GetPositionY(); + ((Player*)me->GetOwner())->GetSession()->SendPacket(&data); + } +} diff --git a/src/server/game/AI/CoreAI/TotemAI.h b/src/server/game/AI/CoreAI/TotemAI.h new file mode 100644 index 00000000000..34f4dfa9945 --- /dev/null +++ b/src/server/game/AI/CoreAI/TotemAI.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_TOTEMAI_H +#define TRINITY_TOTEMAI_H + +#include "CreatureAI.h" +#include "Timer.h" + +class Creature; +class Totem; + +class TotemAI : public CreatureAI +{ + public: + + explicit TotemAI(Creature *c); + + void MoveInLineOfSight(Unit *); + void AttackStart(Unit *); + void EnterEvadeMode(); + + void UpdateAI(const uint32); + static int Permissible(const Creature *); + + private: + uint64 i_victimGuid; +}; +#endif + diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp new file mode 100644 index 00000000000..a156ec573d9 --- /dev/null +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "UnitAI.h" +#include "Player.h" +#include "Creature.h" +#include "SpellAuras.h" +#include "SpellAuraEffects.h" +#include "SpellMgr.h" +#include "CreatureAIImpl.h" + +void UnitAI::AttackStart(Unit *victim) +{ + if (victim && me->Attack(victim, true)) + me->GetMotionMaster()->MoveChase(victim); +} + +void UnitAI::AttackStartCaster(Unit *victim, float dist) +{ + if (victim && me->Attack(victim, false)) + me->GetMotionMaster()->MoveChase(victim, dist); +} + +void UnitAI::DoMeleeAttackIfReady() +{ + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + //Make sure our attack is ready and we aren't currently casting before checking distance + if (me->isAttackReady()) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK)) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK); + me->resetAttackTimer(OFF_ATTACK); + } + } +} + +bool UnitAI::DoSpellAttackIfReady(uint32 spell) +{ + if (me->hasUnitState(UNIT_STAT_CASTING)) + return true; + + if (me->isAttackReady()) + { + if (me->IsWithinCombatRange(me->getVictim(), GetSpellMaxRange(spell, false))) + { + me->CastSpell(me->getVictim(), spell, false); + me->resetAttackTimer(); + } + else + return false; + } + return true; +} + +// default predicate function to select target based on distance, player and/or aura criteria +struct DefaultTargetSelector : public std::unary_function +{ + const Unit *me; + float m_dist; + bool m_playerOnly; + int32 m_aura; + + // pUnit: the reference unit + // dist: if 0: ignored, if > 0: maximum distance to the reference unit, if < 0: minimum distance to the reference unit + // playerOnly: self explaining + // aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura + DefaultTargetSelector(const Unit *pUnit, float dist, bool playerOnly, int32 aura) : me(pUnit), m_dist(dist), m_playerOnly(playerOnly), m_aura(aura) {} + + bool operator() (const Unit *pTarget) + { + if (!me) + return false; + + if (!pTarget) + return false; + + if (m_playerOnly && (pTarget->GetTypeId() != TYPEID_PLAYER)) + return false; + + if (m_dist > 0.0f && !me->IsWithinCombatRange(pTarget, m_dist)) + return false; + + if (m_dist < 0.0f && me->IsWithinCombatRange(pTarget, -m_dist)) + return false; + + if (m_aura) + { + if (m_aura > 0) + { + if (!pTarget->HasAura(m_aura)) + return false; + } + else + { + if (pTarget->HasAura(m_aura)) + return false; + } + } + + return true; + } +}; + +Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, int32 aura) +{ + return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, aura)); +} + +void UnitAI::SelectTargetList(std::list &targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly, int32 aura) +{ + const std::list &threatlist = me->getThreatManager().getThreatList(); + + if (threatlist.empty()) + return; + + DefaultTargetSelector targetSelector(me, dist,playerOnly, aura); + for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + if (targetSelector((*itr)->getTarget())) + targetList.push_back((*itr)->getTarget()); + + if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) + targetList.sort(Trinity::ObjectDistanceOrderPred(me)); + + if (targetType == SELECT_TARGET_FARTHEST || targetType == SELECT_TARGET_BOTTOMAGGRO) + targetList.reverse(); + + if (targetList.size() < num) + return; + + if (targetType == SELECT_TARGET_RANDOM) + { + while (num < targetList.size()) { + std::list::iterator itr = targetList.begin(); + advance(itr, urand(0, targetList.size()-1)); + targetList.erase(itr); + } + } + else + targetList.resize(num); +} + +float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive) +{ + return GetSpellMaxRange(spellId, positive); +} + +void UnitAI::DoAddAuraToAllHostilePlayers(uint32 spellid) +{ + if (me->isInCombat()) + { + std::list& threatlist = me->getThreatManager().getThreatList(); + for (std::list::iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + if (Unit *pTemp = Unit::GetUnit(*me,(*itr)->getUnitGuid())) + if (pTemp->GetTypeId() == TYPEID_PLAYER) + me->AddAura(spellid, pTemp); + } + }else + return; +} + +void UnitAI::DoCastToAllHostilePlayers(uint32 spellid, bool triggered) +{ + if (me->isInCombat()) + { + std::list& threatlist = me->getThreatManager().getThreatList(); + for (std::list::iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + if (Unit *pTemp = Unit::GetUnit(*me,(*itr)->getUnitGuid())) + if (pTemp->GetTypeId() == TYPEID_PLAYER) + me->CastSpell(pTemp, spellid, triggered); + } + }else + return; +} + +void UnitAI::DoCast(uint32 spellId) +{ + Unit *target = NULL; + //sLog.outError("aggre %u %u", spellId, (uint32)AISpellInfo[spellId].target); + switch(AISpellInfo[spellId].target) + { + default: + case AITARGET_SELF: target = me; break; + case AITARGET_VICTIM: target = me->getVictim(); break; + case AITARGET_ENEMY: + { + const SpellEntry * spellInfo = GetSpellStore()->LookupEntry(spellId); + bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY; + //float range = GetSpellMaxRange(spellInfo, false); + target = SelectTarget(SELECT_TARGET_RANDOM, 0, GetSpellMaxRange(spellInfo, false), playerOnly); + break; + } + case AITARGET_ALLY: target = me; break; + case AITARGET_BUFF: target = me; break; + case AITARGET_DEBUFF: + { + const SpellEntry * spellInfo = GetSpellStore()->LookupEntry(spellId); + bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY; + float range = GetSpellMaxRange(spellInfo, false); + + DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId); + if (!(spellInfo->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) + && !(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM) + && targetSelector(me->getVictim())) + target = me->getVictim(); + else + target = SelectTarget(SELECT_TARGET_RANDOM, 0, targetSelector); + break; + } + } + + if (target) + me->CastSpell(target, spellId, false); +} + +#define UPDATE_TARGET(a) {if (AIInfo->targettarget=a;} + +void UnitAI::FillAISpellInfo() +{ + AISpellInfo = new AISpellInfoType[GetSpellStore()->GetNumRows()]; + + AISpellInfoType *AIInfo = AISpellInfo; + const SpellEntry * spellInfo; + + for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i, ++AIInfo) + { + spellInfo = GetSpellStore()->LookupEntry(i); + if (!spellInfo) + continue; + + if (spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_DEAD) + AIInfo->condition = AICOND_DIE; + else if (IsPassiveSpell(i) || GetSpellDuration(spellInfo) == -1) + AIInfo->condition = AICOND_AGGRO; + else + AIInfo->condition = AICOND_COMBAT; + + if (AIInfo->cooldown < spellInfo->RecoveryTime) + AIInfo->cooldown = spellInfo->RecoveryTime; + + if (!GetSpellMaxRange(spellInfo, false)) + UPDATE_TARGET(AITARGET_SELF) + else + { + for (uint32 j = 0; j < 3; ++j) + { + uint32 targetType = spellInfo->EffectImplicitTargetA[j]; + + if (targetType == TARGET_UNIT_TARGET_ENEMY + || targetType == TARGET_DST_TARGET_ENEMY) + UPDATE_TARGET(AITARGET_VICTIM) + else if (targetType == TARGET_UNIT_AREA_ENEMY_DST) + UPDATE_TARGET(AITARGET_ENEMY) + + if (spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AURA) + { + if (targetType == TARGET_UNIT_TARGET_ENEMY) + UPDATE_TARGET(AITARGET_DEBUFF) + else if (IsPositiveSpell(i)) + UPDATE_TARGET(AITARGET_BUFF) + } + } + } + AIInfo->realCooldown = spellInfo->RecoveryTime + spellInfo->StartRecoveryTime; + SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); + if (srange) + AIInfo->maxRange = srange->maxRangeHostile * 3 / 4; + } +} + +//Enable PlayerAI when charmed +void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; } + +void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) +{ + Creature *charmer = me->GetCharmer()->ToCreature(); + + //kill self if charm aura has infinite duration + if (charmer->IsInEvadeMode()) + { + Unit::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM); + for (Unit::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) + if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent()) + { + charmer->Kill(me); + return; + } + } + + if (!charmer->isInCombat()) + me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, me->GetFollowAngle()); + + Unit *target = me->getVictim(); + if (!target || !charmer->canAttack(target)) + AttackStart(charmer->SelectNearestTargetInAttackDistance()); +} diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h new file mode 100644 index 00000000000..62b7090a2d0 --- /dev/null +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_UNITAI_H +#define TRINITY_UNITAI_H + +#include "Platform/Define.h" +#include +#include "Unit.h" + +class Unit; +class Player; +struct AISpellInfoType; + +//Selection method used by SelectTarget +enum SelectAggroTarget +{ + SELECT_TARGET_RANDOM = 0, //Just selects a random target + SELECT_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom + SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top + SELECT_TARGET_NEAREST, + SELECT_TARGET_FARTHEST, +}; + +class UnitAI +{ + protected: + Unit * const me; + public: + explicit UnitAI(Unit *u) : me(u) {} + virtual ~UnitAI() {} + + virtual bool CanAIAttack(const Unit * /*who*/) const { return true; } + virtual void AttackStart(Unit *); + virtual void UpdateAI(const uint32 diff) = 0; + + virtual void InitializeAI() { if (!me->isDead()) Reset(); } + + virtual void Reset() {}; + + // Called when unit is charmed + virtual void OnCharmed(bool apply) = 0; + + // Pass parameters between AI + virtual void DoAction(const int32 /*param*/ = 0) {} + virtual uint32 GetData(uint32 /*id = 0*/) { return 0; } + virtual void SetData(uint32 /*id*/, uint32 /*value*/) {} + virtual void SetGUID(const uint64 &/*guid*/, int32 /*id*/ = 0) {} + virtual uint64 GetGUID(int32 /*id*/ = 0) { return 0; } + + Unit* SelectTarget(SelectAggroTarget targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, int32 aura = 0); + void SelectTargetList(std::list &targetList, uint32 num, SelectAggroTarget targetType, float dist = 0.0f, bool playerOnly = false, int32 aura = 0); + + // Select the targets satifying the predicate. + // predicate shall extend std::unary_function + template Unit* SelectTarget(SelectAggroTarget targetType, uint32 position, PREDICATE predicate) + { + const std::list &threatlist = me->getThreatManager().getThreatList(); + std::list targetList; + + if (position >= threatlist.size()) + return NULL; + + for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + HostileReference* ref = (*itr); + if (predicate(ref->getTarget())) + targetList.push_back(ref->getTarget()); + } + + if (position >= targetList.size()) + return NULL; + + if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) + targetList.sort(Trinity::ObjectDistanceOrderPred(me)); + + switch(targetType) + { + case SELECT_TARGET_NEAREST: + case SELECT_TARGET_TOPAGGRO: + { + std::list::iterator itr = targetList.begin(); + advance(itr, position); + return *itr; + } + break; + + case SELECT_TARGET_FARTHEST: + case SELECT_TARGET_BOTTOMAGGRO: + { + std::list::reverse_iterator ritr = targetList.rbegin(); + advance(ritr, position); + return *ritr; + } + break; + + case SELECT_TARGET_RANDOM: + { + std::list::iterator itr = targetList.begin(); + advance(itr, urand(position, targetList.size()-1)); + return *itr; + } + break; + } + + return NULL; + } + + void AttackStartCaster(Unit *victim, float dist); + + void DoAddAuraToAllHostilePlayers(uint32 spellid); + void DoCast(uint32 spellId); + void DoCast(Unit* victim, uint32 spellId, bool triggered = false); + void DoCastToAllHostilePlayers(uint32 spellid, bool triggered = false); + void DoCastVictim(uint32 spellId, bool triggered = false); + void DoCastAOE(uint32 spellId, bool triggered = false); + + float DoGetSpellMaxRange(uint32 spellId, bool positive = false); + + void DoMeleeAttackIfReady(); + bool DoSpellAttackIfReady(uint32 spell); + + static AISpellInfoType *AISpellInfo; + static void FillAISpellInfo(); +}; + +class PlayerAI : public UnitAI +{ + protected: + Player* const me; + public: + explicit PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {} + + void OnCharmed(bool apply); +}; + +class SimpleCharmedAI : public PlayerAI +{ + public: + void UpdateAI(const uint32 diff); + SimpleCharmedAI(Player *p): PlayerAI(p) {} +}; + +#endif diff --git a/src/server/game/AI/GuardAI.cpp b/src/server/game/AI/GuardAI.cpp deleted file mode 100644 index 19d5b5d8354..00000000000 --- a/src/server/game/AI/GuardAI.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "GuardAI.h" -#include "Errors.h" -#include "Player.h" -#include "ObjectAccessor.h" -#include "World.h" -#include "CreatureAIImpl.h" - -int GuardAI::Permissible(const Creature *creature) -{ - if (creature->isGuard()) - return PERMIT_BASE_SPECIAL; - - return PERMIT_BASE_NO; -} - -GuardAI::GuardAI(Creature *c) : CreatureAI(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) -{ -} - -void GuardAI::MoveInLineOfSight(Unit *u) -{ - // Ignore Z for flying creatures - if (!me->canFly() && me->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE) - return; - - if (!me->getVictim() && me->canAttack(u) && - (u->IsHostileToPlayers() || me->IsHostileTo(u) /*|| u->getVictim() && me->IsFriendlyTo(u->getVictim())*/) && - u->isInAccessiblePlaceFor(me)) - { - float attackRadius = me->GetAttackDistance(u); - if (me->IsWithinDistInMap(u,attackRadius)) - { - //Need add code to let guard support player - AttackStart(u); - //u->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); - } - } -} - -void GuardAI::EnterEvadeMode() -{ - if (!me->isAlive()) - { - DEBUG_LOG("Creature stopped attacking because he is dead [guid=%u]", me->GetGUIDLow()); - me->GetMotionMaster()->MoveIdle(); - - i_state = STATE_NORMAL; - - i_victimGuid = 0; - me->CombatStop(true); - me->DeleteThreatList(); - return; - } - - Unit* victim = ObjectAccessor::GetUnit(*me, i_victimGuid); - - if (!victim) - { - DEBUG_LOG("Creature stopped attacking because victim does not exist [guid=%u]", me->GetGUIDLow()); - } - else if (!victim ->isAlive()) - { - DEBUG_LOG("Creature stopped attacking because victim is dead [guid=%u]", me->GetGUIDLow()); - } - else if (victim ->HasStealthAura()) - { - DEBUG_LOG("Creature stopped attacking because victim is using stealth [guid=%u]", me->GetGUIDLow()); - } - else if (victim ->isInFlight()) - { - DEBUG_LOG("Creature stopped attacking because victim is flying away [guid=%u]", me->GetGUIDLow()); - } - else - { - DEBUG_LOG("Creature stopped attacking because victim outran him [guid=%u]", me->GetGUIDLow()); - } - - me->RemoveAllAuras(); - me->DeleteThreatList(); - i_victimGuid = 0; - me->CombatStop(true); - i_state = STATE_NORMAL; - - // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - me->GetMotionMaster()->MoveTargetedHome(); -} - -void GuardAI::UpdateAI(const uint32 /*diff*/) -{ - // update i_victimGuid if me->getVictim() !=0 and changed - if (!UpdateVictim()) - return; - - i_victimGuid = me->getVictim()->GetGUID(); - - if (me->isAttackReady()) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } -} - -bool GuardAI::IsVisible(Unit *pl) const -{ - return me->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_GUARDER)) - && pl->isVisibleForOrDetect(me,true); -} - -void GuardAI::JustDied(Unit *killer) -{ - if (Player* pkiller = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) - me->SendZoneUnderAttackMessage(pkiller); -} diff --git a/src/server/game/AI/GuardAI.h b/src/server/game/AI/GuardAI.h deleted file mode 100644 index 73e3692a770..00000000000 --- a/src/server/game/AI/GuardAI.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GUARDAI_H -#define TRINITY_GUARDAI_H - -#include "CreatureAI.h" -#include "Timer.h" - -class Creature; - -class GuardAI : public CreatureAI -{ - enum GuardState - { - STATE_NORMAL = 1, - STATE_LOOK_AT_VICTIM = 2 - }; - - public: - - explicit GuardAI(Creature *c); - - void MoveInLineOfSight(Unit *); - void EnterEvadeMode(); - void JustDied(Unit *); - bool IsVisible(Unit *) const; - - void UpdateAI(const uint32); - static int Permissible(const Creature *); - - private: - uint64 i_victimGuid; - GuardState i_state; - TimeTracker i_tracker; -}; -#endif - diff --git a/src/server/game/AI/PassiveAI.cpp b/src/server/game/AI/PassiveAI.cpp deleted file mode 100644 index c6c92f6df04..00000000000 --- a/src/server/game/AI/PassiveAI.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "PassiveAI.h" -#include "Creature.h" -#include "TemporarySummon.h" - -PassiveAI::PassiveAI(Creature *c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); } -PossessedAI::PossessedAI(Creature *c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); } -NullCreatureAI::NullCreatureAI(Creature *c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); } - -void PassiveAI::UpdateAI(const uint32) -{ - if (me->isInCombat() && me->getAttackers().empty()) - EnterEvadeMode(); -} - -void PossessedAI::AttackStart(Unit *target) -{ - me->Attack(target, true); -} - -void PossessedAI::UpdateAI(const uint32 /*diff*/) -{ - if (me->getVictim()) - { - if (!me->canAttack(me->getVictim())) - me->AttackStop(); - else - DoMeleeAttackIfReady(); - } -} - -void PossessedAI::JustDied(Unit * /*u*/) -{ - // We died while possessed, disable our loot - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); -} - -void PossessedAI::KilledUnit(Unit* victim) -{ - // We killed a creature, disable victim's loot - if (victim->GetTypeId() == TYPEID_UNIT) - victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); -} - -void CritterAI::DamageTaken(Unit * /*done_by*/, uint32 &) -{ - if (!me->hasUnitState(UNIT_STAT_FLEEING)) - me->SetControlled(true, UNIT_STAT_FLEEING); -} - -void CritterAI::EnterEvadeMode() -{ - if (me->hasUnitState(UNIT_STAT_FLEEING)) - me->SetControlled(false, UNIT_STAT_FLEEING); - CreatureAI::EnterEvadeMode(); -} - -void TriggerAI::IsSummonedBy(Unit *summoner) -{ - if (me->m_spells[0]) - me->CastSpell(me, me->m_spells[0], false, 0, 0, summoner->GetGUID()); -} diff --git a/src/server/game/AI/PassiveAI.h b/src/server/game/AI/PassiveAI.h deleted file mode 100644 index c13e2d1a63c..00000000000 --- a/src/server/game/AI/PassiveAI.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_PASSIVEAI_H -#define TRINITY_PASSIVEAI_H - -#include "CreatureAI.h" -//#include "CreatureAIImpl.h" - -class PassiveAI : public CreatureAI -{ - public: - explicit PassiveAI(Creature *c); - - void MoveInLineOfSight(Unit *) {} - void AttackStart(Unit *) {} - void UpdateAI(const uint32); - - static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } -}; - -class PossessedAI : public CreatureAI -{ - public: - explicit PossessedAI(Creature *c); - - void MoveInLineOfSight(Unit *) {} - void AttackStart(Unit *target); - void UpdateAI(const uint32); - void EnterEvadeMode() {} - - void JustDied(Unit*); - void KilledUnit(Unit* victim); - - static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } -}; - -class NullCreatureAI : public CreatureAI -{ - public: - explicit NullCreatureAI(Creature *c); - - void MoveInLineOfSight(Unit *) {} - void AttackStart(Unit *) {} - void UpdateAI(const uint32) {} - void EnterEvadeMode() {} - void OnCharmed(bool /*apply*/) {} - - static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } -}; - -class CritterAI : public PassiveAI -{ - public: - explicit CritterAI(Creature *c) : PassiveAI(c) {} - - void DamageTaken(Unit *done_by, uint32 & /*damage*/); - void EnterEvadeMode(); -}; - -class TriggerAI : public NullCreatureAI -{ - public: - explicit TriggerAI(Creature *c) : NullCreatureAI(c) {} - void IsSummonedBy(Unit *summoner); -}; - -#endif - diff --git a/src/server/game/AI/PetAI.cpp b/src/server/game/AI/PetAI.cpp deleted file mode 100644 index 09ec8fae53f..00000000000 --- a/src/server/game/AI/PetAI.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "PetAI.h" -#include "Errors.h" -#include "Pet.h" -#include "Player.h" -#include "DBCStores.h" -#include "Spell.h" -#include "ObjectAccessor.h" -#include "SpellMgr.h" -#include "Creature.h" -#include "World.h" -#include "Util.h" - -int PetAI::Permissible(const Creature *creature) -{ - if (creature->isPet()) - return PERMIT_BASE_SPECIAL; - - return PERMIT_BASE_NO; -} - -PetAI::PetAI(Creature *c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK) -{ - m_AllySet.clear(); - UpdateAllies(); -} - -void PetAI::EnterEvadeMode() -{ -} - -bool PetAI::_needToStop() const -{ - // This is needed for charmed creatures, as once their target was reset other effects can trigger threat - if (me->isCharmed() && me->getVictim() == me->GetCharmer()) - return true; - - return !me->canAttack(me->getVictim()); -} - -void PetAI::_stopAttack() -{ - if (!me->isAlive()) - { - DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", me->GetGUIDLow()); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->CombatStop(); - me->getHostileRefManager().deleteReferences(); - - return; - } - - me->AttackStop(); - me->GetCharmInfo()->SetIsCommandAttack(false); - HandleReturnMovement(); -} - -void PetAI::UpdateAI(const uint32 diff) -{ - if (!me->isAlive()) - return; - - Unit* owner = me->GetCharmerOrOwner(); - - if (m_updateAlliesTimer <= diff) - // UpdateAllies self set update timer - UpdateAllies(); - else - m_updateAlliesTimer -= diff; - - // me->getVictim() can't be used for check in case stop fighting, me->getVictim() clear at Unit death etc. - if (me->getVictim()) - { - if (_needToStop()) - { - DEBUG_LOG("Pet AI stoped attacking [guid=%u]", me->GetGUIDLow()); - _stopAttack(); - return; - } - - DoMeleeAttackIfReady(); - } - else if (owner && me->GetCharmInfo()) //no victim - { - Unit *nextTarget = SelectNextTarget(); - - if (nextTarget) - AttackStart(nextTarget); - else - HandleReturnMovement(); - } - else if (owner && !me->hasUnitState(UNIT_STAT_FOLLOW)) // no charm info and no victim - me->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST, me->GetFollowAngle()); - - if (!me->GetCharmInfo()) - return; - - // Autocast (casted only in combat or persistent spells in any state) - if (me->GetGlobalCooldown() == 0 && !me->hasUnitState(UNIT_STAT_CASTING)) - { - typedef std::vector > TargetSpellList; - TargetSpellList targetSpellStore; - - for (uint8 i = 0; i < me->GetPetAutoSpellSize(); ++i) - { - uint32 spellID = me->GetPetAutoSpellOnPos(i); - if (!spellID) - continue; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); - if (!spellInfo) - continue; - - // ignore some combinations of combat state and combat/noncombat spells - if (!me->getVictim()) - { - // ignore attacking spells, and allow only self/around spells - if (!IsPositiveSpell(spellInfo->Id)) - continue; - - // non combat spells allowed - // only pet spells have IsNonCombatSpell and not fit this reqs: - // Consume Shadows, Lesser Invisibility, so ignore checks for its - if (!IsNonCombatSpell(spellInfo)) - { - // allow only spell without spell cost or with spell cost but not duration limit - int32 duration = GetSpellDuration(spellInfo); - if ((spellInfo->manaCost || spellInfo->ManaCostPercentage || spellInfo->manaPerSecond) && duration > 0) - continue; - - // allow only spell without cooldown > duration - int32 cooldown = GetSpellRecoveryTime(spellInfo); - if (cooldown >= 0 && duration >= 0 && cooldown > duration) - continue; - } - } - else - { - // just ignore non-combat spells - if (IsNonCombatSpell(spellInfo)) - continue; - } - - Spell *spell = new Spell(me, spellInfo, false, 0); - - // Fix to allow pets on STAY to autocast - if (me->getVictim() && _CanAttack(me->getVictim()) && spell->CanAutoCast(me->getVictim())) - { - targetSpellStore.push_back(std::make_pair(me->getVictim(), spell)); - continue; - } - else - { - bool spellUsed = false; - for (std::set::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) - { - Unit* Target = ObjectAccessor::GetUnit(*me,*tar); - - //only buff targets that are in combat, unless the spell can only be cast while out of combat - if (!Target) - continue; - - if (spell->CanAutoCast(Target)) - { - targetSpellStore.push_back(std::make_pair(Target, spell)); - spellUsed = true; - break; - } - } - if (!spellUsed) - delete spell; - } - } - - //found units to cast on to - if (!targetSpellStore.empty()) - { - uint32 index = urand(0, targetSpellStore.size() - 1); - - Spell* spell = targetSpellStore[index].second; - Unit* target = targetSpellStore[index].first; - - targetSpellStore.erase(targetSpellStore.begin() + index); - - SpellCastTargets targets; - targets.setUnitTarget(target); - - if (!me->HasInArc(M_PI, target)) - { - me->SetInFront(target); - if (target && target->GetTypeId() == TYPEID_PLAYER) - me->SendUpdateToPlayer(target->ToPlayer()); - - if (owner && owner->GetTypeId() == TYPEID_PLAYER) - me->SendUpdateToPlayer(owner->ToPlayer()); - } - - me->AddCreatureSpellCooldown(spell->m_spellInfo->Id); - - spell->prepare(&targets); - } - - // deleted cached Spell objects - for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr) - delete itr->second; - } -} - -void PetAI::UpdateAllies() -{ - Unit* owner = me->GetCharmerOrOwner(); - Group *pGroup = NULL; - - m_updateAlliesTimer = 10*IN_MILISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance - - if (!owner) - return; - else if (owner->GetTypeId() == TYPEID_PLAYER) - pGroup = owner->ToPlayer()->GetGroup(); - - //only pet and owner/not in group->ok - if (m_AllySet.size() == 2 && !pGroup) - return; - //owner is in group; group members filled in already (no raid -> subgroupcount = whole count) - if (pGroup && !pGroup->isRaidGroup() && m_AllySet.size() == (pGroup->GetMembersCount() + 2)) - return; - - m_AllySet.clear(); - m_AllySet.insert(me->GetGUID()); - if (pGroup) //add group - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* Target = itr->getSource(); - if (!Target || !pGroup->SameSubGroup((Player*)owner, Target)) - continue; - - if (Target->GetGUID() == owner->GetGUID()) - continue; - - m_AllySet.insert(Target->GetGUID()); - } - } - else //remove group - m_AllySet.insert(owner->GetGUID()); -} - -void PetAI::KilledUnit(Unit *victim) -{ - // Called from Unit::Kill() in case where pet or owner kills something - // if owner killed this victim, pet may still be attacking something else - if (me->getVictim() && me->getVictim() != victim) - return; - - // Clear target just in case. May help problem where health / focus / mana - // regen gets stuck. Also resets attack command. - // Can't use _stopAttack() because that activates movement handlers and ignores - // next target selection - me->AttackStop(); - me->GetCharmInfo()->SetIsCommandAttack(false); - - Unit *nextTarget = SelectNextTarget(); - - if (nextTarget) - AttackStart(nextTarget); - else - HandleReturnMovement(); // Return -} - -void PetAI::AttackStart(Unit *target) -{ - // Overrides Unit::AttackStart to correctly evaluate Pet states - - // Check all pet states to decide if we can attack this target - if (!_CanAttack(target)) - return; - - // We can attack, should we chase or not? - if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) - DoAttack(target,true); // FOLLOW, attack with chase - else - { - if (me->GetCharmInfo()->IsCommandAttack()) - DoAttack(target,true); // STAY or FOLLOW, player clicked "attack" so attack with chase - else - DoAttack(target,false); // STAY, target in range, attack not clicked so attack without chase - } -} - -Unit *PetAI::SelectNextTarget() -{ - // Provides next target selection after current target death - - // Passive pets don't do next target selection - if (me->HasReactState(REACT_PASSIVE)) - return NULL; - - // Check pet's attackers first to prevent dragging mobs back - // to owner - if (me->getAttackerForHelper()) - return me->getAttackerForHelper(); - - // Check owner's attackers if pet didn't have any - if (me->GetCharmerOrOwner()->getAttackerForHelper()) - return me->GetCharmerOrOwner()->getAttackerForHelper(); - - // 3.0.2 - Pets now start attacking their owners target in defensive mode as soon as the hunter does - if (me->GetCharmerOrOwner()->getVictim()) - return me->GetCharmerOrOwner()->getVictim(); - - // Default - return NULL; -} - -void PetAI::HandleReturnMovement() -{ - // Handles moving the pet back to stay or owner - - if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY)) - { - if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning()) - { - // Return to previous position where stay was clicked - if (!me->GetCharmInfo()->IsCommandAttack()) - { - float x,y,z; - - me->GetCharmInfo()->GetStayPosition(x, y, z); - me->GetCharmInfo()->SetIsReturning(true); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(me->GetGUIDLow(),x,y,z); - } - } - } - else // COMMAND_FOLLOW - { - if (!me->GetCharmInfo()->IsFollowing() && !me->GetCharmInfo()->IsReturning()) - { - if (!me->GetCharmInfo()->IsCommandAttack()) - { - me->GetCharmInfo()->SetIsReturning(true); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveFollow(me->GetCharmerOrOwner(), PET_FOLLOW_DIST, me->GetFollowAngle()); - } - } - } - -} - -void PetAI::DoAttack(Unit *target, bool chase) -{ - // Handles attack with or without chase and also resets all - // PetAI flags for next update / creature kill - - // me->GetCharmInfo()->SetIsCommandAttack(false); - - // The following conditions are true if chase == true - // (Follow && (Aggressive || Defensive)) - // ((Stay || Follow) && (Passive && player clicked attack)) - - if (chase) - { - if (me->Attack(target,true)) - { - me->GetCharmInfo()->SetIsAtStay(false); - me->GetCharmInfo()->SetIsFollowing(false); - me->GetCharmInfo()->SetIsReturning(false); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(target); - } - } - else // (Stay && ((Aggressive || Defensive) && In Melee Range))) - { - me->GetCharmInfo()->SetIsAtStay(true); - me->GetCharmInfo()->SetIsFollowing(false); - me->GetCharmInfo()->SetIsReturning(false); - me->Attack(target,true); - } -} - -void PetAI::MovementInform(uint32 moveType, uint32 data) -{ - // Receives notification when pet reaches stay or follow owner - switch (moveType) - { - case POINT_MOTION_TYPE: - { - // Pet is returning to where stay was clicked. data should be - // pet's GUIDLow since we set that as the waypoint ID - if (data == me->GetGUIDLow() && me->GetCharmInfo()->IsReturning()) - { - me->GetCharmInfo()->SetIsAtStay(true); - me->GetCharmInfo()->SetIsReturning(false); - me->GetCharmInfo()->SetIsFollowing(false); - me->GetCharmInfo()->SetIsCommandAttack(false); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - } - } - break; - - case TARGETED_MOTION_TYPE: - { - // If data is owner's GUIDLow then we've reached follow point, - // otherwise we're probably chasing a creature - if (me->GetCharmerOrOwner() && me->GetCharmInfo() && data == me->GetCharmerOrOwner()->GetGUIDLow() && me->GetCharmInfo()->IsReturning()) - { - me->GetCharmInfo()->SetIsAtStay(false); - me->GetCharmInfo()->SetIsReturning(false); - me->GetCharmInfo()->SetIsFollowing(true); - me->GetCharmInfo()->SetIsCommandAttack(false); - me->addUnitState(UNIT_STAT_FOLLOW); - } - } - break; - - default: - break; - } -} - -bool PetAI::_CanAttack(Unit *target) -{ - // Evaluates wether a pet can attack a specific - // target based on CommandState, ReactState and other flags - - // Returning - check first since pets returning ignore attacks - if (me->GetCharmInfo()->IsReturning()) - return false; - - // Passive - check now so we don't have to worry about passive in later checks - if (me->HasReactState(REACT_PASSIVE)) - return me->GetCharmInfo()->IsCommandAttack(); - - // Pets commanded to attack should not stop their approach if attacked by another creature - if (me->getVictim() && (me->getVictim() != target)) - return !me->GetCharmInfo()->IsCommandAttack(); - - // From this point on, pet will always be either aggressive or defensive - - // Stay - can attack if target is within range or commanded to - if (me->GetCharmInfo()->HasCommandState(COMMAND_STAY)) - return (me->IsWithinMeleeRange(target, MIN_MELEE_REACH) || me->GetCharmInfo()->IsCommandAttack()); - - // Follow - if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) - return true; - - // default, though we shouldn't ever get here - return false; -} diff --git a/src/server/game/AI/PetAI.h b/src/server/game/AI/PetAI.h deleted file mode 100644 index f6087a129ae..00000000000 --- a/src/server/game/AI/PetAI.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_PETAI_H -#define TRINITY_PETAI_H - -#include "CreatureAI.h" -#include "Timer.h" - -class Creature; -class Spell; - -class PetAI : public CreatureAI -{ - public: - - explicit PetAI(Creature *c); - - void EnterEvadeMode(); - void JustDied(Unit * /*who*/) { _stopAttack(); } - - void UpdateAI(const uint32); - static int Permissible(const Creature *); - - void KilledUnit(Unit * /*victim*/); - void AttackStart(Unit *target); - void MovementInform(uint32 moveType, uint32 data); - - private: - bool _isVisible(Unit *) const; - bool _needToStop(void) const; - void _stopAttack(void); - - void UpdateAllies(); - - TimeTracker i_tracker; - bool inCombat; - std::set m_AllySet; - uint32 m_updateAlliesTimer; - - Unit *SelectNextTarget(); - void HandleReturnMovement(); - void DoAttack(Unit *target, bool chase); - bool _CanAttack(Unit *target); -}; -#endif - diff --git a/src/server/game/AI/ReactorAI.cpp b/src/server/game/AI/ReactorAI.cpp deleted file mode 100644 index fdca6314747..00000000000 --- a/src/server/game/AI/ReactorAI.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ByteBuffer.h" -#include "ReactorAI.h" -#include "Errors.h" -#include "Log.h" -#include "ObjectAccessor.h" -#include "CreatureAIImpl.h" - -#define REACTOR_VISIBLE_RANGE (26.46f) - -int -ReactorAI::Permissible(const Creature *creature) -{ - if (creature->isCivilian() || creature->IsNeutralToAll()) - return PERMIT_BASE_REACTIVE; - - return PERMIT_BASE_NO; -} - -void -ReactorAI::MoveInLineOfSight(Unit *) -{ -} - -void -ReactorAI::UpdateAI(const uint32 /*time_diff*/) -{ - // update i_victimGuid if me->getVictim() !=0 and changed - if (!UpdateVictim()) - return; - - if (me->isAttackReady()) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } -} diff --git a/src/server/game/AI/ReactorAI.h b/src/server/game/AI/ReactorAI.h deleted file mode 100644 index ae4e6403962..00000000000 --- a/src/server/game/AI/ReactorAI.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_REACTORAI_H -#define TRINITY_REACTORAI_H - -#include "CreatureAI.h" - -class Unit; - -class ReactorAI : public CreatureAI -{ - public: - - explicit ReactorAI(Creature *c) : CreatureAI(c) {} - - void MoveInLineOfSight(Unit *); - - void UpdateAI(const uint32); - static int Permissible(const Creature *); -}; -#endif - diff --git a/src/server/game/AI/TotemAI.cpp b/src/server/game/AI/TotemAI.cpp deleted file mode 100644 index a6464f189e8..00000000000 --- a/src/server/game/AI/TotemAI.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "TotemAI.h" -#include "Totem.h" -#include "Creature.h" -#include "DBCStores.h" -#include "ObjectAccessor.h" -#include "SpellMgr.h" - -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "CellImpl.h" - -int -TotemAI::Permissible(const Creature *creature) -{ - if (creature->isTotem()) - return PERMIT_BASE_PROACTIVE; - - return PERMIT_BASE_NO; -} - -TotemAI::TotemAI(Creature *c) : CreatureAI(c), i_victimGuid(0) -{ - assert(c->isTotem()); -} - -void -TotemAI::MoveInLineOfSight(Unit *) -{ -} - -void TotemAI::EnterEvadeMode() -{ - me->CombatStop(true); -} - -void -TotemAI::UpdateAI(const uint32 /*diff*/) -{ - if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE) - return; - - if (!me->isAlive() || me->IsNonMeleeSpellCasted(false)) - return; - - // Search spell - SpellEntry const *spellInfo = sSpellStore.LookupEntry(me->ToTotem()->GetSpell()); - if (!spellInfo) - return; - - // Get spell range - SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); - float max_range = GetSpellMaxRangeForHostile(srange); - - // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems - - // pointer to appropriate target if found any - Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL; - - // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) - if (!victim || - !victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) || - me->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(me,false)) - { - victim = NULL; - Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me, max_range); - Trinity::UnitLastSearcher checker(me, victim, u_check); - me->VisitNearbyObject(max_range, checker); - } - - // If have target - if (victim) - { - // remember - i_victimGuid = victim->GetGUID(); - - // attack - me->SetInFront(victim); // client change orientation by self - me->CastSpell(victim, me->ToTotem()->GetSpell(), false); - } - else - i_victimGuid = 0; -} - -void -TotemAI::AttackStart(Unit *) -{ - // Sentry totem sends ping on attack - if (me->GetEntry() == SENTRY_TOTEM_ENTRY && me->GetOwner()->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(MSG_MINIMAP_PING, (8+4+4)); - data << me->GetGUID(); - data << me->GetPositionX(); - data << me->GetPositionY(); - ((Player*)me->GetOwner())->GetSession()->SendPacket(&data); - } -} diff --git a/src/server/game/AI/TotemAI.h b/src/server/game/AI/TotemAI.h deleted file mode 100644 index 34f4dfa9945..00000000000 --- a/src/server/game/AI/TotemAI.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_TOTEMAI_H -#define TRINITY_TOTEMAI_H - -#include "CreatureAI.h" -#include "Timer.h" - -class Creature; -class Totem; - -class TotemAI : public CreatureAI -{ - public: - - explicit TotemAI(Creature *c); - - void MoveInLineOfSight(Unit *); - void AttackStart(Unit *); - void EnterEvadeMode(); - - void UpdateAI(const uint32); - static int Permissible(const Creature *); - - private: - uint64 i_victimGuid; -}; -#endif - diff --git a/src/server/game/AI/UnitAI.cpp b/src/server/game/AI/UnitAI.cpp deleted file mode 100644 index a156ec573d9..00000000000 --- a/src/server/game/AI/UnitAI.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "UnitAI.h" -#include "Player.h" -#include "Creature.h" -#include "SpellAuras.h" -#include "SpellAuraEffects.h" -#include "SpellMgr.h" -#include "CreatureAIImpl.h" - -void UnitAI::AttackStart(Unit *victim) -{ - if (victim && me->Attack(victim, true)) - me->GetMotionMaster()->MoveChase(victim); -} - -void UnitAI::AttackStartCaster(Unit *victim, float dist) -{ - if (victim && me->Attack(victim, false)) - me->GetMotionMaster()->MoveChase(victim, dist); -} - -void UnitAI::DoMeleeAttackIfReady() -{ - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - //Make sure our attack is ready and we aren't currently casting before checking distance - if (me->isAttackReady()) - { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK)) - { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK); - me->resetAttackTimer(OFF_ATTACK); - } - } -} - -bool UnitAI::DoSpellAttackIfReady(uint32 spell) -{ - if (me->hasUnitState(UNIT_STAT_CASTING)) - return true; - - if (me->isAttackReady()) - { - if (me->IsWithinCombatRange(me->getVictim(), GetSpellMaxRange(spell, false))) - { - me->CastSpell(me->getVictim(), spell, false); - me->resetAttackTimer(); - } - else - return false; - } - return true; -} - -// default predicate function to select target based on distance, player and/or aura criteria -struct DefaultTargetSelector : public std::unary_function -{ - const Unit *me; - float m_dist; - bool m_playerOnly; - int32 m_aura; - - // pUnit: the reference unit - // dist: if 0: ignored, if > 0: maximum distance to the reference unit, if < 0: minimum distance to the reference unit - // playerOnly: self explaining - // aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura - DefaultTargetSelector(const Unit *pUnit, float dist, bool playerOnly, int32 aura) : me(pUnit), m_dist(dist), m_playerOnly(playerOnly), m_aura(aura) {} - - bool operator() (const Unit *pTarget) - { - if (!me) - return false; - - if (!pTarget) - return false; - - if (m_playerOnly && (pTarget->GetTypeId() != TYPEID_PLAYER)) - return false; - - if (m_dist > 0.0f && !me->IsWithinCombatRange(pTarget, m_dist)) - return false; - - if (m_dist < 0.0f && me->IsWithinCombatRange(pTarget, -m_dist)) - return false; - - if (m_aura) - { - if (m_aura > 0) - { - if (!pTarget->HasAura(m_aura)) - return false; - } - else - { - if (pTarget->HasAura(m_aura)) - return false; - } - } - - return true; - } -}; - -Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, int32 aura) -{ - return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, aura)); -} - -void UnitAI::SelectTargetList(std::list &targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly, int32 aura) -{ - const std::list &threatlist = me->getThreatManager().getThreatList(); - - if (threatlist.empty()) - return; - - DefaultTargetSelector targetSelector(me, dist,playerOnly, aura); - for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - if (targetSelector((*itr)->getTarget())) - targetList.push_back((*itr)->getTarget()); - - if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) - targetList.sort(Trinity::ObjectDistanceOrderPred(me)); - - if (targetType == SELECT_TARGET_FARTHEST || targetType == SELECT_TARGET_BOTTOMAGGRO) - targetList.reverse(); - - if (targetList.size() < num) - return; - - if (targetType == SELECT_TARGET_RANDOM) - { - while (num < targetList.size()) { - std::list::iterator itr = targetList.begin(); - advance(itr, urand(0, targetList.size()-1)); - targetList.erase(itr); - } - } - else - targetList.resize(num); -} - -float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive) -{ - return GetSpellMaxRange(spellId, positive); -} - -void UnitAI::DoAddAuraToAllHostilePlayers(uint32 spellid) -{ - if (me->isInCombat()) - { - std::list& threatlist = me->getThreatManager().getThreatList(); - for (std::list::iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - if (Unit *pTemp = Unit::GetUnit(*me,(*itr)->getUnitGuid())) - if (pTemp->GetTypeId() == TYPEID_PLAYER) - me->AddAura(spellid, pTemp); - } - }else - return; -} - -void UnitAI::DoCastToAllHostilePlayers(uint32 spellid, bool triggered) -{ - if (me->isInCombat()) - { - std::list& threatlist = me->getThreatManager().getThreatList(); - for (std::list::iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - if (Unit *pTemp = Unit::GetUnit(*me,(*itr)->getUnitGuid())) - if (pTemp->GetTypeId() == TYPEID_PLAYER) - me->CastSpell(pTemp, spellid, triggered); - } - }else - return; -} - -void UnitAI::DoCast(uint32 spellId) -{ - Unit *target = NULL; - //sLog.outError("aggre %u %u", spellId, (uint32)AISpellInfo[spellId].target); - switch(AISpellInfo[spellId].target) - { - default: - case AITARGET_SELF: target = me; break; - case AITARGET_VICTIM: target = me->getVictim(); break; - case AITARGET_ENEMY: - { - const SpellEntry * spellInfo = GetSpellStore()->LookupEntry(spellId); - bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY; - //float range = GetSpellMaxRange(spellInfo, false); - target = SelectTarget(SELECT_TARGET_RANDOM, 0, GetSpellMaxRange(spellInfo, false), playerOnly); - break; - } - case AITARGET_ALLY: target = me; break; - case AITARGET_BUFF: target = me; break; - case AITARGET_DEBUFF: - { - const SpellEntry * spellInfo = GetSpellStore()->LookupEntry(spellId); - bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY; - float range = GetSpellMaxRange(spellInfo, false); - - DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId); - if (!(spellInfo->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) - && !(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM) - && targetSelector(me->getVictim())) - target = me->getVictim(); - else - target = SelectTarget(SELECT_TARGET_RANDOM, 0, targetSelector); - break; - } - } - - if (target) - me->CastSpell(target, spellId, false); -} - -#define UPDATE_TARGET(a) {if (AIInfo->targettarget=a;} - -void UnitAI::FillAISpellInfo() -{ - AISpellInfo = new AISpellInfoType[GetSpellStore()->GetNumRows()]; - - AISpellInfoType *AIInfo = AISpellInfo; - const SpellEntry * spellInfo; - - for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i, ++AIInfo) - { - spellInfo = GetSpellStore()->LookupEntry(i); - if (!spellInfo) - continue; - - if (spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_DEAD) - AIInfo->condition = AICOND_DIE; - else if (IsPassiveSpell(i) || GetSpellDuration(spellInfo) == -1) - AIInfo->condition = AICOND_AGGRO; - else - AIInfo->condition = AICOND_COMBAT; - - if (AIInfo->cooldown < spellInfo->RecoveryTime) - AIInfo->cooldown = spellInfo->RecoveryTime; - - if (!GetSpellMaxRange(spellInfo, false)) - UPDATE_TARGET(AITARGET_SELF) - else - { - for (uint32 j = 0; j < 3; ++j) - { - uint32 targetType = spellInfo->EffectImplicitTargetA[j]; - - if (targetType == TARGET_UNIT_TARGET_ENEMY - || targetType == TARGET_DST_TARGET_ENEMY) - UPDATE_TARGET(AITARGET_VICTIM) - else if (targetType == TARGET_UNIT_AREA_ENEMY_DST) - UPDATE_TARGET(AITARGET_ENEMY) - - if (spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AURA) - { - if (targetType == TARGET_UNIT_TARGET_ENEMY) - UPDATE_TARGET(AITARGET_DEBUFF) - else if (IsPositiveSpell(i)) - UPDATE_TARGET(AITARGET_BUFF) - } - } - } - AIInfo->realCooldown = spellInfo->RecoveryTime + spellInfo->StartRecoveryTime; - SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); - if (srange) - AIInfo->maxRange = srange->maxRangeHostile * 3 / 4; - } -} - -//Enable PlayerAI when charmed -void PlayerAI::OnCharmed(bool apply) { me->IsAIEnabled = apply; } - -void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) -{ - Creature *charmer = me->GetCharmer()->ToCreature(); - - //kill self if charm aura has infinite duration - if (charmer->IsInEvadeMode()) - { - Unit::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM); - for (Unit::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) - if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent()) - { - charmer->Kill(me); - return; - } - } - - if (!charmer->isInCombat()) - me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, me->GetFollowAngle()); - - Unit *target = me->getVictim(); - if (!target || !charmer->canAttack(target)) - AttackStart(charmer->SelectNearestTargetInAttackDistance()); -} diff --git a/src/server/game/AI/UnitAI.h b/src/server/game/AI/UnitAI.h deleted file mode 100644 index 62b7090a2d0..00000000000 --- a/src/server/game/AI/UnitAI.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_UNITAI_H -#define TRINITY_UNITAI_H - -#include "Platform/Define.h" -#include -#include "Unit.h" - -class Unit; -class Player; -struct AISpellInfoType; - -//Selection method used by SelectTarget -enum SelectAggroTarget -{ - SELECT_TARGET_RANDOM = 0, //Just selects a random target - SELECT_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom - SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top - SELECT_TARGET_NEAREST, - SELECT_TARGET_FARTHEST, -}; - -class UnitAI -{ - protected: - Unit * const me; - public: - explicit UnitAI(Unit *u) : me(u) {} - virtual ~UnitAI() {} - - virtual bool CanAIAttack(const Unit * /*who*/) const { return true; } - virtual void AttackStart(Unit *); - virtual void UpdateAI(const uint32 diff) = 0; - - virtual void InitializeAI() { if (!me->isDead()) Reset(); } - - virtual void Reset() {}; - - // Called when unit is charmed - virtual void OnCharmed(bool apply) = 0; - - // Pass parameters between AI - virtual void DoAction(const int32 /*param*/ = 0) {} - virtual uint32 GetData(uint32 /*id = 0*/) { return 0; } - virtual void SetData(uint32 /*id*/, uint32 /*value*/) {} - virtual void SetGUID(const uint64 &/*guid*/, int32 /*id*/ = 0) {} - virtual uint64 GetGUID(int32 /*id*/ = 0) { return 0; } - - Unit* SelectTarget(SelectAggroTarget targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, int32 aura = 0); - void SelectTargetList(std::list &targetList, uint32 num, SelectAggroTarget targetType, float dist = 0.0f, bool playerOnly = false, int32 aura = 0); - - // Select the targets satifying the predicate. - // predicate shall extend std::unary_function - template Unit* SelectTarget(SelectAggroTarget targetType, uint32 position, PREDICATE predicate) - { - const std::list &threatlist = me->getThreatManager().getThreatList(); - std::list targetList; - - if (position >= threatlist.size()) - return NULL; - - for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - HostileReference* ref = (*itr); - if (predicate(ref->getTarget())) - targetList.push_back(ref->getTarget()); - } - - if (position >= targetList.size()) - return NULL; - - if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) - targetList.sort(Trinity::ObjectDistanceOrderPred(me)); - - switch(targetType) - { - case SELECT_TARGET_NEAREST: - case SELECT_TARGET_TOPAGGRO: - { - std::list::iterator itr = targetList.begin(); - advance(itr, position); - return *itr; - } - break; - - case SELECT_TARGET_FARTHEST: - case SELECT_TARGET_BOTTOMAGGRO: - { - std::list::reverse_iterator ritr = targetList.rbegin(); - advance(ritr, position); - return *ritr; - } - break; - - case SELECT_TARGET_RANDOM: - { - std::list::iterator itr = targetList.begin(); - advance(itr, urand(position, targetList.size()-1)); - return *itr; - } - break; - } - - return NULL; - } - - void AttackStartCaster(Unit *victim, float dist); - - void DoAddAuraToAllHostilePlayers(uint32 spellid); - void DoCast(uint32 spellId); - void DoCast(Unit* victim, uint32 spellId, bool triggered = false); - void DoCastToAllHostilePlayers(uint32 spellid, bool triggered = false); - void DoCastVictim(uint32 spellId, bool triggered = false); - void DoCastAOE(uint32 spellId, bool triggered = false); - - float DoGetSpellMaxRange(uint32 spellId, bool positive = false); - - void DoMeleeAttackIfReady(); - bool DoSpellAttackIfReady(uint32 spell); - - static AISpellInfoType *AISpellInfo; - static void FillAISpellInfo(); -}; - -class PlayerAI : public UnitAI -{ - protected: - Player* const me; - public: - explicit PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {} - - void OnCharmed(bool apply); -}; - -class SimpleCharmedAI : public PlayerAI -{ - public: - void UpdateAI(const uint32 diff); - SimpleCharmedAI(Player *p): PlayerAI(p) {} -}; - -#endif diff --git a/src/server/game/Account/AccountMgr.cpp b/src/server/game/Account/AccountMgr.cpp deleted file mode 100644 index 52906fb5454..00000000000 --- a/src/server/game/Account/AccountMgr.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Database/DatabaseEnv.h" -#include "Policies/SingletonImp.h" - -#include "AccountMgr.h" -#include "ObjectAccessor.h" -#include "Player.h" -#include "Util.h" -#include "Auth/Sha1.h" - -extern DatabaseType LoginDatabase; - -INSTANTIATE_SINGLETON_1(AccountMgr); - -AccountMgr::AccountMgr() -{} - -AccountMgr::~AccountMgr() -{} - -AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password) -{ - if (utf8length(username) > MAX_ACCOUNT_STR) - return AOR_NAME_TOO_LONG; // username's too long - - normalizeString(username); - normalizeString(password); - - if (GetId(username)) - { - return AOR_NAME_ALREDY_EXIST; // username does already exist - } - - if (!LoginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s','%s',NOW())", username.c_str(), CalculateShaPassHash(username, password).c_str())) - return AOR_DB_INTERNAL_ERROR; // unexpected error - LoginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL"); - - return AOR_OK; // everything's fine -} - -AccountOpResult AccountMgr::DeleteAccount(uint32 accid) -{ - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); - if (!result) - return AOR_NAME_NOT_EXIST; // account doesn't exist - - result = CharacterDatabase.PQuery("SELECT guid FROM characters WHERE account='%d'",accid); - if (result) - { - do - { - Field *fields = result->Fetch(); - uint32 guidlo = fields[0].GetUInt32(); - uint64 guid = MAKE_NEW_GUID(guidlo, 0, HIGHGUID_PLAYER); - - // kick if player currently - if (Player* p = ObjectAccessor::GetObjectInWorld(guid, (Player*)NULL)) - { - WorldSession* s = p->GetSession(); - s->KickPlayer(); // mark session to remove at next session list update - s->LogoutPlayer(false); // logout player without waiting next session list update - } - - Player::DeleteFromDB(guid, accid, false); // no need to update realm characters - } while (result->NextRow()); - } - - // table realm specific but common for all characters of account for realm - CharacterDatabase.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid); - CharacterDatabase.PExecute("DELETE FROM account_data WHERE account = '%u'",accid); - - LoginDatabase.BeginTransaction(); - - bool res = - LoginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) && - LoginDatabase.PExecute("DELETE FROM account_access WHERE id ='%d'", accid) && - LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid); - - LoginDatabase.CommitTransaction(); - - if (!res) - return AOR_DB_INTERNAL_ERROR; // unexpected error; - - return AOR_OK; -} - -AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd) -{ - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); - if (!result) - return AOR_NAME_NOT_EXIST; // account doesn't exist - - if (utf8length(new_uname) > MAX_ACCOUNT_STR) - return AOR_NAME_TOO_LONG; - - if (utf8length(new_passwd) > MAX_ACCOUNT_STR) - return AOR_PASS_TOO_LONG; - - normalizeString(new_uname); - normalizeString(new_passwd); - - std::string safe_new_uname = new_uname; - LoginDatabase.escape_string(safe_new_uname); - - if (!LoginDatabase.PExecute("UPDATE account SET v='0',s='0',username='%s',sha_pass_hash='%s' WHERE id='%d'", safe_new_uname.c_str(), - CalculateShaPassHash(new_uname, new_passwd).c_str(), accid)) - return AOR_DB_INTERNAL_ERROR; // unexpected error - - return AOR_OK; -} - -AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd) -{ - std::string username; - - if (!GetName(accid, username)) - return AOR_NAME_NOT_EXIST; // account doesn't exist - - if (utf8length(new_passwd) > MAX_ACCOUNT_STR) - return AOR_PASS_TOO_LONG; - - normalizeString(username); - normalizeString(new_passwd); - - // also reset s and v to force update at next realmd login - if (!LoginDatabase.PExecute("UPDATE account SET v='0', s='0', sha_pass_hash='%s' WHERE id='%d'", - CalculateShaPassHash(username, new_passwd).c_str(), accid)) - return AOR_DB_INTERNAL_ERROR; // unexpected error - - return AOR_OK; -} - -uint32 AccountMgr::GetId(std::string username) -{ - LoginDatabase.escape_string(username); - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str()); - if (!result) - return 0; - else - { - uint32 id = (*result)[0].GetUInt32(); - return id; - } -} - -uint32 AccountMgr::GetSecurity(uint32 acc_id) -{ - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT gmlevel FROM account_access WHERE id = '%u'", acc_id); - if (result) - { - uint32 sec = (*result)[0].GetUInt32(); - return sec; - } - - return 0; -} - -uint32 AccountMgr::GetSecurity(uint32 acc_id, int32 realm_id) -{ - QueryResult_AutoPtr result = (realm_id == -1) - ? LoginDatabase.PQuery("SELECT gmlevel FROM account_access WHERE id = '%u' AND RealmID = '%d'", acc_id, realm_id) - : LoginDatabase.PQuery("SELECT gmlevel FROM account_access WHERE id = '%u' AND (RealmID = '%d' OR RealmID = '-1')", acc_id, realm_id); - if (result) - { - uint32 sec = (*result)[0].GetUInt32(); - return sec; - } - - return 0; -} - -bool AccountMgr::GetName(uint32 acc_id, std::string &name) -{ - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id); - if (result) - { - name = (*result)[0].GetCppString(); - return true; - } - - return false; -} - -bool AccountMgr::CheckPassword(uint32 accid, std::string passwd) -{ - std::string username; - if (!GetName(accid, username)) - return false; - - normalizeString(username); - normalizeString(passwd); - - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash='%s'", accid, CalculateShaPassHash(username, passwd).c_str()); - if (result) - return true; - - return false; -} - -bool AccountMgr::normalizeString(std::string& utf8str) -{ - wchar_t wstr_buf[MAX_ACCOUNT_STR+1]; - - size_t wstr_len = MAX_ACCOUNT_STR; - if (!Utf8toWStr(utf8str,wstr_buf,wstr_len)) - return false; - - std::transform(&wstr_buf[0], wstr_buf+wstr_len, &wstr_buf[0], wcharToUpperOnlyLatin); - - return WStrToUtf8(wstr_buf,wstr_len,utf8str); -} - -std::string AccountMgr::CalculateShaPassHash(std::string& name, std::string& password) -{ - Sha1Hash sha; - sha.Initialize(); - sha.UpdateData(name); - sha.UpdateData(":"); - sha.UpdateData(password); - sha.Finalize(); - - std::string encoded; - hexEncodeByteArray(sha.GetDigest(), sha.GetLength(), encoded); - - return encoded; -} - diff --git a/src/server/game/Account/AccountMgr.h b/src/server/game/Account/AccountMgr.h deleted file mode 100644 index b017bf1836a..00000000000 --- a/src/server/game/Account/AccountMgr.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ACCMGR_H -#define _ACCMGR_H - -#include - -#include "Common.h" -#include "Policies/Singleton.h" - -enum AccountOpResult -{ - AOR_OK, - AOR_NAME_TOO_LONG, - AOR_PASS_TOO_LONG, - AOR_NAME_ALREDY_EXIST, - AOR_NAME_NOT_EXIST, - AOR_DB_INTERNAL_ERROR -}; - -#define MAX_ACCOUNT_STR 16 - -class AccountMgr -{ - public: - AccountMgr(); - ~AccountMgr(); - - AccountOpResult CreateAccount(std::string username, std::string password); - AccountOpResult DeleteAccount(uint32 accid); - AccountOpResult ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd); - AccountOpResult ChangePassword(uint32 accid, std::string new_passwd); - bool CheckPassword(uint32 accid, std::string passwd); - - uint32 GetId(std::string username); - uint32 GetSecurity(uint32 acc_id); - uint32 GetSecurity(uint32 acc_id, int32 realm_id); - bool GetName(uint32 acc_id, std::string &name); - std::string CalculateShaPassHash(std::string& name, std::string& password); - - static bool normalizeString(std::string& utf8str); -}; - -#define accmgr Trinity::Singleton::Instance() -#endif - diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp new file mode 100644 index 00000000000..52906fb5454 --- /dev/null +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Database/DatabaseEnv.h" +#include "Policies/SingletonImp.h" + +#include "AccountMgr.h" +#include "ObjectAccessor.h" +#include "Player.h" +#include "Util.h" +#include "Auth/Sha1.h" + +extern DatabaseType LoginDatabase; + +INSTANTIATE_SINGLETON_1(AccountMgr); + +AccountMgr::AccountMgr() +{} + +AccountMgr::~AccountMgr() +{} + +AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password) +{ + if (utf8length(username) > MAX_ACCOUNT_STR) + return AOR_NAME_TOO_LONG; // username's too long + + normalizeString(username); + normalizeString(password); + + if (GetId(username)) + { + return AOR_NAME_ALREDY_EXIST; // username does already exist + } + + if (!LoginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s','%s',NOW())", username.c_str(), CalculateShaPassHash(username, password).c_str())) + return AOR_DB_INTERNAL_ERROR; // unexpected error + LoginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL"); + + return AOR_OK; // everything's fine +} + +AccountOpResult AccountMgr::DeleteAccount(uint32 accid) +{ + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); + if (!result) + return AOR_NAME_NOT_EXIST; // account doesn't exist + + result = CharacterDatabase.PQuery("SELECT guid FROM characters WHERE account='%d'",accid); + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guidlo = fields[0].GetUInt32(); + uint64 guid = MAKE_NEW_GUID(guidlo, 0, HIGHGUID_PLAYER); + + // kick if player currently + if (Player* p = ObjectAccessor::GetObjectInWorld(guid, (Player*)NULL)) + { + WorldSession* s = p->GetSession(); + s->KickPlayer(); // mark session to remove at next session list update + s->LogoutPlayer(false); // logout player without waiting next session list update + } + + Player::DeleteFromDB(guid, accid, false); // no need to update realm characters + } while (result->NextRow()); + } + + // table realm specific but common for all characters of account for realm + CharacterDatabase.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid); + CharacterDatabase.PExecute("DELETE FROM account_data WHERE account = '%u'",accid); + + LoginDatabase.BeginTransaction(); + + bool res = + LoginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) && + LoginDatabase.PExecute("DELETE FROM account_access WHERE id ='%d'", accid) && + LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid); + + LoginDatabase.CommitTransaction(); + + if (!res) + return AOR_DB_INTERNAL_ERROR; // unexpected error; + + return AOR_OK; +} + +AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd) +{ + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); + if (!result) + return AOR_NAME_NOT_EXIST; // account doesn't exist + + if (utf8length(new_uname) > MAX_ACCOUNT_STR) + return AOR_NAME_TOO_LONG; + + if (utf8length(new_passwd) > MAX_ACCOUNT_STR) + return AOR_PASS_TOO_LONG; + + normalizeString(new_uname); + normalizeString(new_passwd); + + std::string safe_new_uname = new_uname; + LoginDatabase.escape_string(safe_new_uname); + + if (!LoginDatabase.PExecute("UPDATE account SET v='0',s='0',username='%s',sha_pass_hash='%s' WHERE id='%d'", safe_new_uname.c_str(), + CalculateShaPassHash(new_uname, new_passwd).c_str(), accid)) + return AOR_DB_INTERNAL_ERROR; // unexpected error + + return AOR_OK; +} + +AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd) +{ + std::string username; + + if (!GetName(accid, username)) + return AOR_NAME_NOT_EXIST; // account doesn't exist + + if (utf8length(new_passwd) > MAX_ACCOUNT_STR) + return AOR_PASS_TOO_LONG; + + normalizeString(username); + normalizeString(new_passwd); + + // also reset s and v to force update at next realmd login + if (!LoginDatabase.PExecute("UPDATE account SET v='0', s='0', sha_pass_hash='%s' WHERE id='%d'", + CalculateShaPassHash(username, new_passwd).c_str(), accid)) + return AOR_DB_INTERNAL_ERROR; // unexpected error + + return AOR_OK; +} + +uint32 AccountMgr::GetId(std::string username) +{ + LoginDatabase.escape_string(username); + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str()); + if (!result) + return 0; + else + { + uint32 id = (*result)[0].GetUInt32(); + return id; + } +} + +uint32 AccountMgr::GetSecurity(uint32 acc_id) +{ + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT gmlevel FROM account_access WHERE id = '%u'", acc_id); + if (result) + { + uint32 sec = (*result)[0].GetUInt32(); + return sec; + } + + return 0; +} + +uint32 AccountMgr::GetSecurity(uint32 acc_id, int32 realm_id) +{ + QueryResult_AutoPtr result = (realm_id == -1) + ? LoginDatabase.PQuery("SELECT gmlevel FROM account_access WHERE id = '%u' AND RealmID = '%d'", acc_id, realm_id) + : LoginDatabase.PQuery("SELECT gmlevel FROM account_access WHERE id = '%u' AND (RealmID = '%d' OR RealmID = '-1')", acc_id, realm_id); + if (result) + { + uint32 sec = (*result)[0].GetUInt32(); + return sec; + } + + return 0; +} + +bool AccountMgr::GetName(uint32 acc_id, std::string &name) +{ + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id); + if (result) + { + name = (*result)[0].GetCppString(); + return true; + } + + return false; +} + +bool AccountMgr::CheckPassword(uint32 accid, std::string passwd) +{ + std::string username; + if (!GetName(accid, username)) + return false; + + normalizeString(username); + normalizeString(passwd); + + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash='%s'", accid, CalculateShaPassHash(username, passwd).c_str()); + if (result) + return true; + + return false; +} + +bool AccountMgr::normalizeString(std::string& utf8str) +{ + wchar_t wstr_buf[MAX_ACCOUNT_STR+1]; + + size_t wstr_len = MAX_ACCOUNT_STR; + if (!Utf8toWStr(utf8str,wstr_buf,wstr_len)) + return false; + + std::transform(&wstr_buf[0], wstr_buf+wstr_len, &wstr_buf[0], wcharToUpperOnlyLatin); + + return WStrToUtf8(wstr_buf,wstr_len,utf8str); +} + +std::string AccountMgr::CalculateShaPassHash(std::string& name, std::string& password) +{ + Sha1Hash sha; + sha.Initialize(); + sha.UpdateData(name); + sha.UpdateData(":"); + sha.UpdateData(password); + sha.Finalize(); + + std::string encoded; + hexEncodeByteArray(sha.GetDigest(), sha.GetLength(), encoded); + + return encoded; +} + diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h new file mode 100644 index 00000000000..b017bf1836a --- /dev/null +++ b/src/server/game/Accounts/AccountMgr.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ACCMGR_H +#define _ACCMGR_H + +#include + +#include "Common.h" +#include "Policies/Singleton.h" + +enum AccountOpResult +{ + AOR_OK, + AOR_NAME_TOO_LONG, + AOR_PASS_TOO_LONG, + AOR_NAME_ALREDY_EXIST, + AOR_NAME_NOT_EXIST, + AOR_DB_INTERNAL_ERROR +}; + +#define MAX_ACCOUNT_STR 16 + +class AccountMgr +{ + public: + AccountMgr(); + ~AccountMgr(); + + AccountOpResult CreateAccount(std::string username, std::string password); + AccountOpResult DeleteAccount(uint32 accid); + AccountOpResult ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd); + AccountOpResult ChangePassword(uint32 accid, std::string new_passwd); + bool CheckPassword(uint32 accid, std::string passwd); + + uint32 GetId(std::string username); + uint32 GetSecurity(uint32 acc_id); + uint32 GetSecurity(uint32 acc_id, int32 realm_id); + bool GetName(uint32 acc_id, std::string &name); + std::string CalculateShaPassHash(std::string& name, std::string& password); + + static bool normalizeString(std::string& utf8str); +}; + +#define accmgr Trinity::Singleton::Instance() +#endif + diff --git a/src/server/game/Addons/AddonHandler.cpp b/src/server/game/Addons/AddonHandler.cpp deleted file mode 100644 index a9c8101d7b1..00000000000 --- a/src/server/game/Addons/AddonHandler.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "zlib/zlib.h" - -#include "AddonHandler.h" -#include "Database/DatabaseEnv.h" -#include "Policies/SingletonImp.h" -#include "Opcodes.h" - -#include "Log.h" - -INSTANTIATE_SINGLETON_1( AddonHandler ); - -AddonHandler::AddonHandler() -{ -} - -AddonHandler::~AddonHandler() -{ -} - -bool AddonHandler::BuildAddonPacket(WorldPacket *Source, WorldPacket *Target) -{ - ByteBuffer AddOnPacked; - uLongf AddonRealSize; - uint32 CurrentPosition; - uint32 TempValue; - - unsigned char tdata[256] = - { - 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, - 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, - 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, - 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, - 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, - 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, - 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, - 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, - 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, - 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, - 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, - 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, - 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, - 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, - 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, - 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 - }; - - // broken addon packet, can't be received from real client - if (Source->rpos() + 4 > Source->size()) - return false; - - *Source >> TempValue; // get real size of the packed structure - - // empty addon packet, nothing process, can't be received from real client - if(!TempValue) - return false; - - AddonRealSize = TempValue; // temp value because ZLIB only excepts uLongf - - CurrentPosition = Source->rpos(); // get the position of the pointer in the structure - - AddOnPacked.resize(AddonRealSize); // resize target for zlib action - - if (!uncompress(const_cast(AddOnPacked.contents()), &AddonRealSize, const_cast((*Source).contents() + CurrentPosition), (*Source).size() - CurrentPosition)!= Z_OK) - { - Target->Initialize(SMSG_ADDON_INFO); - - uint32 addonsCount; - AddOnPacked >> addonsCount; // addons count? - - for(uint32 i = 0; i < addonsCount; ++i) - { - std::string addonName; - uint8 enabled; - uint32 crc, unk2; - - // check next addon data format correctness - if(AddOnPacked.rpos()+1 > AddOnPacked.size()) - return false; - - AddOnPacked >> addonName; - - // recheck next addon data format correctness - if(AddOnPacked.rpos()+1+4+4 > AddOnPacked.size()) - return false; - - AddOnPacked >> enabled >> crc >> unk2; - - sLog.outDebug("ADDON: Name: %s, Enabled: 0x%x, CRC: 0x%x, Unknown2: 0x%x", addonName.c_str(), enabled, crc, unk2); - - uint8 state = (enabled ? 2 : 1); - *Target << uint8(state); - - uint8 unk1 = (enabled ? 1 : 0); - *Target << uint8(unk1); - if (unk1) - { - uint8 unk2 = (crc != 0x4c1c776d); // If addon is Standard addon CRC - *Target << uint8(unk2); - if (unk2) - Target->append(tdata, sizeof(tdata)); - - *Target << uint32(0); - } - - uint8 unk3 = (enabled ? 0 : 1); - *Target << uint8(unk3); - if (unk3) - { - // String, 256 (null terminated?) - *Target << uint8(0); - } - } - - uint32 unk4; - AddOnPacked >> unk4; - - uint32 count = 0; - *Target << uint32(count); - /*for(uint32 i = 0; i < count; ++i) - { - uint32 - string (16 bytes) - string (16 bytes) - uint32 - }*/ - - if(AddOnPacked.rpos() != AddOnPacked.size()) - sLog.outDebug("packet under read!"); - } - else - { - sLog.outError("Addon packet uncompress error :("); - return false; - } - return true; -} - -/* Code use in 1.10.2 when client not ignore ban state sended for addons. Saved for reference if client switch to use server ban state information -void AddonHandler::BuildAddonPacket(WorldPacket* Source, WorldPacket* Target, uint32 Packetoffset) -{ - ByteBuffer AddOnPacked; - uLongf AddonRealSize; - uint32 CurrentPosition; - uint32 TempValue; - - *Source >> TempValue; //get real size of the packed structure - - AddonRealSize = TempValue; //temp value becouse ZLIB only excepts uLongf - - CurrentPosition = Source->rpos(); //get the position of the pointer in the structure - - AddOnPacked.resize(AddonRealSize); //resize target for zlib action - - if (!uncompress((uint8*)AddOnPacked.contents(), &AddonRealSize, (uint8*)(*Source).contents() + CurrentPosition, (*Source).size() - CurrentPosition)!= Z_OK) - { - bool* AddonAllowed = new bool; //handle addon check and enable-ing - - uint32 Unknown1; - uint8 Unknown0; - - AddOnPacked >> Unknown0; - AddOnPacked >> Unknown1; - - Target->Initialize(SMSG_ADDON_INFO); - - uint32 i = 5; //offset for addon extraction - while(i != AddOnPacked.size()) - { - std::string AddonNames; - AddOns* Addonstr = new AddOns; - uint8 unk6; - uint64 CRCCHECK; - AddOnPacked >> AddonNames >> CRCCHECK >> unk6; - - //sLog.outDebug("ADDON: Name:%s CRC:%x Unknown:%x",AddonNames.c_str(), CRCCHECK,unk6); - - Addonstr->Name = AddonNames; - Addonstr->CRC = CRCCHECK; - - //if not allowed but unknown added to list - if (GetAddonStatus(Addonstr, AddonAllowed)) // If addon is new - { - Addonstr->Enabled = m_Addon_Default; // by default new addons are set from Config file - *AddonAllowed = m_Addon_Default; // Set addon allowed on default value - _AddAddon(Addonstr); - sLog.outDetail("Found new Addon, Name:%s CRC:%x Unknown:%x",AddonNames.c_str(), CRCCHECK, unk6); - } - - if (CRCCHECK == 0x4C1C776D01LL) //If addon is Standard addon CRC - { - //value's standard Addons - *Target << uint8(0) << uint8(2) << uint8(1) << uint8(0) << uint32(0); - } - else if (*AddonAllowed) //if addon is Custom addons - //value's enable addon - *Target << uint8(0x00) << uint8(0x01) << uint8(0x00) << uint8(0x01); - else - //value's disable addom - *Target << uint8(0x00) << uint8(0x0) << uint8(0x00) << uint8(0x0); - - i += AddonNames.size() + 10; - } - *Target << uint8(0x0); - - //delete mem allocation - delete AddonAllowed; - } - else - { - //handle uncompress error - } -} -*/ - diff --git a/src/server/game/Addons/AddonHandler.h b/src/server/game/Addons/AddonHandler.h deleted file mode 100644 index 999785339bc..00000000000 --- a/src/server/game/Addons/AddonHandler.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __ADDONHANDLER_H -#define __ADDONHANDLER_H - -#include "Common.h" -#include "Config/ConfigEnv.h" -#include "Policies/Singleton.h" - -#include "WorldPacket.h" - -class AddonHandler -{ - public: - /* Construction */ - AddonHandler(); - ~AddonHandler(); - //built addon packet - bool BuildAddonPacket(WorldPacket* Source, WorldPacket* Target); -}; -#define sAddOnHandler Trinity::Singleton::Instance() -#endif - diff --git a/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.cpp new file mode 100644 index 00000000000..ebbf48e6476 --- /dev/null +++ b/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.cpp @@ -0,0 +1,1860 @@ +#include "ObjectMgr.h" +#include "AuctionHouseMgr.h" +#include "AuctionHouseBot.h" +#include + +#include "Policies/SingletonImp.h" +INSTANTIATE_SINGLETON_1(AuctionHouseBot); + +using namespace std; +vector npcItems; +vector lootItems; +vector greyTradeGoodsBin; +vector whiteTradeGoodsBin; +vector greenTradeGoodsBin; +vector blueTradeGoodsBin; +vector purpleTradeGoodsBin; +vector orangeTradeGoodsBin; +vector yellowTradeGoodsBin; +vector greyItemsBin; +vector whiteItemsBin; +vector greenItemsBin; +vector blueItemsBin; +vector purpleItemsBin; +vector orangeItemsBin; +vector yellowItemsBin; +AuctionHouseBot::AuctionHouseBot() +{ + debug_Out = false; + debug_Out_Filters = false; + AHBSeller = false; + AHBBuyer = false; + + //Begin Filters + + Vendor_Items = false; + Loot_Items = false; + Other_Items = false; + Vendor_TGs = false; + Loot_TGs = false; + Other_TGs = false; + + No_Bind = false; + Bind_When_Picked_Up = false; + Bind_When_Equipped = false; + Bind_When_Use = false; + Bind_Quest_Item = false; + + DisableBeta_PTR_Unused = false; + DisablePermEnchant = false; + DisableConjured = false; + DisableGems = false; + DisableMoney = false; + DisableMoneyLoot = false; + DisableLootable = false; + DisableKeys = false; + DisableDuration = false; + DisableBOP_Or_Quest_NoReqLevel = false; + + DisableWarriorItems = false; + DisablePaladinItems = false; + DisableHunterItems = false; + DisableRogueItems = false; + DisablePriestItems = false; + DisableDKItems = false; + DisableShamanItems = false; + DisableMageItems = false; + DisableWarlockItems = false; + DisableUnusedClassItems = false; + DisableDruidItems = false; + + DisableItemsBelowLevel = 0; + DisableItemsAboveLevel = 0; + DisableTGsBelowLevel = 0; + DisableTGsAboveLevel = 0; + DisableItemsBelowGUID = 0; + DisableItemsAboveGUID = 0; + DisableTGsBelowGUID = 0; + DisableTGsAboveGUID = 0; + DisableItemsBelowReqLevel = 0; + DisableItemsAboveReqLevel = 0; + DisableTGsBelowReqLevel = 0; + DisableTGsAboveReqLevel = 0; + DisableItemsBelowReqSkillRank = 0; + DisableItemsAboveReqSkillRank = 0; + DisableTGsBelowReqSkillRank = 0; + DisableTGsAboveReqSkillRank = 0; + + //End Filters + + _lastrun_a = time(NULL); + _lastrun_h = time(NULL); + _lastrun_n = time(NULL); + + AllianceConfig = AHBConfig(2); + HordeConfig = AHBConfig(6); + NeutralConfig = AHBConfig(7); +} + +AuctionHouseBot::~AuctionHouseBot() +{ +} + +void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) +{ + if (!AHBSeller) + { + if (debug_Out) sLog.outError("AHSeller: Disabled"); + return; + } + + uint32 minItems = config->GetMinItems(); + uint32 maxItems = config->GetMaxItems(); + + if (maxItems == 0) + { + //if (debug_Out) sLog.outString("AHSeller: Auctions disabled"); + return; + } + + AuctionHouseEntry const* ahEntry = auctionmgr.GetAuctionHouseEntry(config->GetAHFID()); + if (!ahEntry) + { + return; + } + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(config->GetAHFID()); + if (!auctionHouse) + { + return; + } + + uint32 auctions = auctionHouse->Getcount(); + + if (auctions >= minItems) + { + //if (debug_Out) sLog.outString("AHSeller: Auctions above minimum"); + return; + } + + if (auctions >= maxItems) + { + //if (debug_Out) sLog.outString("AHSeller: Auctions at or above maximum"); + return; + } + + uint32 items = 0; + if ((maxItems - auctions) >= ItemsPerCycle) + items = ItemsPerCycle; + else + items = (maxItems - auctions); + + if (debug_Out) sLog.outString("AHSeller: Adding %u Auctions", items); + + uint32 AuctioneerGUID = 0; + + switch (config->GetAHID()) + { + case 2: + AuctioneerGUID = 79707; //Human in stormwind. + break; + case 6: + AuctioneerGUID = 4656; //orc in Orgrimmar + break; + case 7: + AuctioneerGUID = 23442; //goblin in GZ + break; + default: + if (debug_Out) sLog.outError("AHSeller: GetAHID() - Default switch reached"); + AuctioneerGUID = 23442; //default to neutral 7 + break; + } + + if (debug_Out) sLog.outString("AHSeller: Current Auctineer GUID is %u", AuctioneerGUID); + + uint32 greyTGcount = config->GetPercents(AHB_GREY_TG); + uint32 whiteTGcount = config->GetPercents(AHB_WHITE_TG); + uint32 greenTGcount = config->GetPercents(AHB_GREEN_TG); + uint32 blueTGcount = config->GetPercents(AHB_BLUE_TG); + uint32 purpleTGcount = config->GetPercents(AHB_PURPLE_TG); + uint32 orangeTGcount = config->GetPercents(AHB_ORANGE_TG); + uint32 yellowTGcount = config->GetPercents(AHB_YELLOW_TG); + uint32 greyIcount = config->GetPercents(AHB_GREY_I); + uint32 whiteIcount = config->GetPercents(AHB_WHITE_I); + uint32 greenIcount = config->GetPercents(AHB_GREEN_I); + uint32 blueIcount = config->GetPercents(AHB_BLUE_I); + uint32 purpleIcount = config->GetPercents(AHB_PURPLE_I); + uint32 orangeIcount = config->GetPercents(AHB_ORANGE_I); + uint32 yellowIcount = config->GetPercents(AHB_YELLOW_I); +/* uint32 total = greyTGcount + whiteTGcount + greenTGcount + blueTGcount + + purpleTGcount + orangeTGcount + yellowTGcount + + whiteIcount + greenIcount + blueIcount + purpleIcount + + orangeIcount + yellowIcount; +*/ + uint32 greyTGoods = config->GetItemCounts(AHB_GREY_TG); + uint32 whiteTGoods = config->GetItemCounts(AHB_WHITE_TG); + uint32 greenTGoods = config->GetItemCounts(AHB_GREEN_TG); + uint32 blueTGoods = config->GetItemCounts(AHB_BLUE_TG); + uint32 purpleTGoods = config->GetItemCounts(AHB_PURPLE_TG); + uint32 orangeTGoods = config->GetItemCounts(AHB_ORANGE_TG); + uint32 yellowTGoods = config->GetItemCounts(AHB_YELLOW_TG); + + uint32 greyItems = config->GetItemCounts(AHB_GREY_I); + uint32 whiteItems = config->GetItemCounts(AHB_WHITE_I); + uint32 greenItems = config->GetItemCounts(AHB_GREEN_I); + uint32 blueItems = config->GetItemCounts(AHB_BLUE_I); + uint32 purpleItems = config->GetItemCounts(AHB_PURPLE_I); + uint32 orangeItems = config->GetItemCounts(AHB_ORANGE_I); + uint32 yellowItems = config->GetItemCounts(AHB_YELLOW_I); + if (debug_Out) sLog.outString("AHSeller: %u items", items); + + // only insert a few at a time, so as not to peg the processor + for (uint32 cnt = 1; cnt <= items; cnt++) + { + if (debug_Out) sLog.outString("AHSeller: %u count", cnt); + uint32 itemID = 0; + uint32 itemColor = 99; + uint32 loopbreaker = 0; + while (itemID == 0 && loopbreaker <= 50) + { + ++loopbreaker; + uint32 choice = urand(0, 13); + itemColor = choice; + switch (choice) + { + case 0: + { + if ((greyItemsBin.size() > 0) && (greyItems < greyIcount)) + itemID = greyItemsBin[urand(0, greyItemsBin.size() - 1)]; + else continue; + break; + } + case 1: + { + if ((whiteItemsBin.size() > 0) && (whiteItems < whiteIcount)) + itemID = whiteItemsBin[urand(0, whiteItemsBin.size() - 1)]; + else continue; + break; + } + case 2: + { + if ((greenItemsBin.size() > 0) && (greenItems < greenIcount)) + itemID = greenItemsBin[urand(0, greenItemsBin.size() - 1)]; + else continue; + break; + } + case 3: + { + if ((blueItemsBin.size() > 0) && (blueItems < blueIcount)) + itemID = blueItemsBin[urand(0, blueItemsBin.size() - 1)]; + else continue; + break; + } + case 4: + { + if ((purpleItemsBin.size() > 0) && (purpleItems < purpleIcount)) + itemID = purpleItemsBin[urand(0, purpleItemsBin.size() - 1)]; + else continue; + break; + } + case 5: + { + if ((orangeItemsBin.size() > 0) && (orangeItems < orangeIcount)) + itemID = orangeItemsBin[urand(0, orangeItemsBin.size() - 1)]; + else continue; + break; + } + case 6: + { + if ((yellowItemsBin.size() > 0) && (yellowItems < yellowIcount)) + itemID = yellowItemsBin[urand(0, yellowItemsBin.size() - 1)]; + else continue; + break; + } + case 7: + { + if ((greyTradeGoodsBin.size() > 0) && (greyTGoods < greyTGcount)) + itemID = greyTradeGoodsBin[urand(0, greyTradeGoodsBin.size() - 1)]; + else continue; + break; + } + case 8: + { + if ((whiteTradeGoodsBin.size() > 0) && (whiteTGoods < whiteTGcount)) + itemID = whiteTradeGoodsBin[urand(0, whiteTradeGoodsBin.size() - 1)]; + else continue; + break; + } + case 9: + { + if ((greenTradeGoodsBin.size() > 0) && (greenTGoods < greenTGcount)) + itemID = greenTradeGoodsBin[urand(0, greenTradeGoodsBin.size() - 1)]; + else continue; + break; + } + case 10: + { + if ((blueTradeGoodsBin.size() > 0) && (blueTGoods < blueTGcount)) + itemID = blueTradeGoodsBin[urand(0, blueTradeGoodsBin.size() - 1)]; + else continue; + break; + } + case 11: + { + if ((purpleTradeGoodsBin.size() > 0) && (purpleTGoods < purpleTGcount)) + itemID = purpleTradeGoodsBin[urand(0, purpleTradeGoodsBin.size() - 1)]; + else continue; + break; + } + case 12: + { + if ((orangeTradeGoodsBin.size() > 0) && (orangeTGoods < orangeTGcount)) + itemID = orangeTradeGoodsBin[urand(0, orangeTradeGoodsBin.size() - 1)]; + else continue; + break; + } + case 13: + { + if ((yellowTradeGoodsBin.size() > 0) && (yellowTGoods < yellowTGcount)) + itemID = yellowTradeGoodsBin[urand(0, yellowTradeGoodsBin.size() - 1)]; + else continue; + break; + } + default: + { + if (debug_Out) sLog.outError("AHSeller: itemID Switch - Default Reached"); + break; + } + } + + if (itemID == 0) + { + if (debug_Out) sLog.outError("AHSeller: Item::CreateItem() - ItemID is 0"); + continue; + } + + ItemPrototype const* prototype = objmgr.GetItemPrototype(itemID); + if (prototype == NULL) + { + if (debug_Out) sLog.outError("AHSeller: Huh?!?! prototype == NULL"); + continue; + } + + Item* item = Item::CreateItem(itemID, 1, AHBplayer); + if (item == NULL) + { + if (debug_Out) sLog.outError("AHSeller: Item::CreateItem() returned NULL"); + break; + } + item->AddToUpdateQueueOf(AHBplayer); + + uint32 randomPropertyId = Item::GenerateItemRandomPropertyId(itemID); + if (randomPropertyId != 0) + item->SetItemRandomProperties(randomPropertyId); + + uint64 buyoutPrice = 0; + uint64 bidPrice = 0; + uint32 stackCount = 1; + + switch (SellMethod) + { + case 0: + buyoutPrice = prototype->SellPrice; + break; + case 1: + buyoutPrice = prototype->BuyPrice; + break; + } + + if ((prototype->Quality >= 0) && (prototype->Quality <= AHB_MAX_QUALITY)) + { + if (config->GetMaxStack(prototype->Quality) > 1 && item->GetMaxStackCount() > 1) + stackCount = urand(1, minValue(item->GetMaxStackCount(), config->GetMaxStack(prototype->Quality))); + else if (config->GetMaxStack(prototype->Quality) == 0 && item->GetMaxStackCount() > 1) + stackCount = urand(1, item->GetMaxStackCount()); + else + stackCount = 1; + buyoutPrice *= urand(config->GetMinPrice(prototype->Quality), config->GetMaxPrice(prototype->Quality)); + buyoutPrice /= 100; + bidPrice = buyoutPrice * urand(config->GetMinBidPrice(prototype->Quality), config->GetMaxBidPrice(prototype->Quality)); + bidPrice /= 100; + } + else + { + // quality is something it shouldn't be, let's get out of here + if (debug_Out) sLog.outError("AHBuyer: Quality %u not Supported", prototype->Quality); + item->RemoveFromUpdateQueueOf(AHBplayer); + continue; + } + + uint32 etime = urand(1,3); + switch(etime) + { + case 1: + etime = 43200; + break; + case 2: + etime = 86400; + break; + case 3: + etime = 172800; + break; + default: + etime = 86400; + break; + } + item->SetCount(stackCount); + + uint32 dep = auctionmgr.GetAuctionDeposit(ahEntry, etime, item); + + AuctionEntry* auctionEntry = new AuctionEntry; + auctionEntry->Id = objmgr.GenerateAuctionID(); + auctionEntry->auctioneer = AuctioneerGUID; + auctionEntry->item_guidlow = item->GetGUIDLow(); + auctionEntry->item_template = item->GetEntry(); + auctionEntry->owner = AHBplayer->GetGUIDLow(); + auctionEntry->startbid = bidPrice * stackCount; + auctionEntry->buyout = buyoutPrice * stackCount; + auctionEntry->bidder = 0; + auctionEntry->bid = 0; + auctionEntry->deposit = dep; + auctionEntry->expire_time = (time_t) etime + time(NULL); + auctionEntry->auctionHouseEntry = ahEntry; + item->SaveToDB(); + item->RemoveFromUpdateQueueOf(AHBplayer); + auctionmgr.AddAItem(item); + auctionHouse->AddAuction(auctionEntry); + auctionEntry->SaveToDB(); + + switch(itemColor) + { + case 0: + ++greyItems; + break; + case 1: + ++whiteItems; + break; + case 2: + ++greenItems; + break; + case 3: + ++blueItems; + break; + case 4: + ++purpleItems; + break; + case 5: + ++orangeItems; + break; + case 6: + ++yellowItems; + break; + case 7: + ++greyTGoods; + break; + case 8: + ++whiteTGoods; + break; + case 9: + ++greenTGoods; + break; + case 10: + ++blueTGoods; + break; + case 11: + ++purpleTGoods; + break; + case 12: + ++orangeTGoods; + break; + case 13: + ++yellowTGoods; + break; + default: + break; + } + } + } +} +void AuctionHouseBot::addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session) +{ + if (!AHBBuyer) + { + if (debug_Out) sLog.outError("AHBuyer: Disabled"); + return; + } + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT id FROM auctionhouse WHERE itemowner<>%u AND buyguid<>%u", AHBplayerGUID, AHBplayerGUID); + + if (!result) + return; + + if (result->GetRowCount() == 0) + return; + + // Fetches content of selected AH + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(config->GetAHFID()); + vector possibleBids; + + do + { + uint32 tmpdata = result->Fetch()->GetUInt32(); + possibleBids.push_back(tmpdata); + }while (result->NextRow()); + + for (uint32 count = 1; count <= config->GetBidsPerInterval(); ++count) + { + // Do we have anything to bid? If not, stop here. + if (possibleBids.empty()) + { + //if (debug_Out) sLog.outString("AHBuyer: I have no items to bid on."); + count = config->GetBidsPerInterval(); + continue; + } + + // Choose random auction from possible auctions + uint32 vectorPos = urand(0, possibleBids.size() - 1); + vector::iterator iter = possibleBids.begin(); + advance(iter, vectorPos); + + // from auctionhousehandler.cpp, creates auction pointer & player pointer + AuctionEntry* auction = auctionHouse->GetAuction(*iter); + + // Erase the auction from the vector to prevent bidding on item in next iteration. + possibleBids.erase(iter); + + if (!auction) + continue; + + // get exact item information + Item *pItem = auctionmgr.GetAItem(auction->item_guidlow); + if (!pItem) + { + if (debug_Out) sLog.outError("AHBuyer: Item %u doesn't exist, perhaps bought already?", auction->item_guidlow); + continue; + } + + // get item prototype + ItemPrototype const* prototype = objmgr.GetItemPrototype(auction->item_template); + + // check which price we have to use, startbid or if it is bidded already + uint32 currentprice; + if (auction->bid) + currentprice = auction->bid; + else + currentprice = auction->startbid; + + // Prepare portion from maximum bid + double bidrate = static_cast(urand(1, 100)) / 100; + long double bidMax = 0; + + // check that bid has acceptable value and take bid based on vendorprice, stacksize and quality + switch (BuyMethod) + { + case 0: + { + if ((prototype->Quality >= 0) && (prototype->Quality <= AHB_MAX_QUALITY)) + { + if (currentprice < prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality)) + bidMax = prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality); + } + else + { + // quality is something it shouldn't be, let's get out of here + if (debug_Out) sLog.outError("AHBuyer: Quality %u not Supported", prototype->Quality); + continue; + } + break; + } + case 1: + { + if ((prototype->Quality >= 0) && (prototype->Quality <= AHB_MAX_QUALITY)) + { + if (currentprice < prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality)) + bidMax = prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(prototype->Quality); + } + else + { + // quality is something it shouldn't be, let's get out of here + if (debug_Out) sLog.outError("AHBuyer: Quality %u not Supported", prototype->Quality); + continue; + } + break; + } + } + + // check some special items, and do recalculating to their prices + switch (prototype->Class) + { + // ammo + case 6: + bidMax = 0; + break; + default: + break; + } + + if (bidMax == 0) + { + // quality check failed to get bidmax, let's get out of here + continue; + } + + // Calculate our bid + long double bidvalue = currentprice + ((bidMax - currentprice) * bidrate); + // Convert to uint32 + uint32 bidprice = static_cast(bidvalue); + + // Check our bid is high enough to be valid. If not, correct it to minimum. + if ((currentprice + auction->GetAuctionOutBid()) > bidprice) + bidprice = currentprice + auction->GetAuctionOutBid(); + + if (debug_Out) + { + sLog.outString("-------------------------------------------------"); + sLog.outString("AHBuyer: Info for Auction #%u:", auction->Id); + sLog.outString("AHBuyer: AuctionHouse: %u", auction->GetHouseId()); + sLog.outString("AHBuyer: Auctioneer: %u", auction->auctioneer); + sLog.outString("AHBuyer: Owner: %u", auction->owner); + sLog.outString("AHBuyer: Bidder: %u", auction->bidder); + sLog.outString("AHBuyer: Starting Bid: %u", auction->startbid); + sLog.outString("AHBuyer: Current Bid: %u", currentprice); + sLog.outString("AHBuyer: Buyout: %u", auction->buyout); + sLog.outString("AHBuyer: Deposit: %u", auction->deposit); + sLog.outString("AHBuyer: Expire Time: %u", auction->expire_time); + sLog.outString("AHBuyer: Bid Rate: %f", bidrate); + sLog.outString("AHBuyer: Bid Max: %f", bidMax); + sLog.outString("AHBuyer: Bid Value: %f", bidvalue); + sLog.outString("AHBuyer: Bid Price: %u", bidprice); + sLog.outString("AHBuyer: Item GUID: %u", auction->item_guidlow); + sLog.outString("AHBuyer: Item Template: %u", auction->item_template); + sLog.outString("AHBuyer: Item Info:"); + sLog.outString("AHBuyer: Item ID: %u", prototype->ItemId); + sLog.outString("AHBuyer: Buy Price: %u", prototype->BuyPrice); + sLog.outString("AHBuyer: Sell Price: %u", prototype->SellPrice); + sLog.outString("AHBuyer: Bonding: %u", prototype->Bonding); + sLog.outString("AHBuyer: Quality: %u", prototype->Quality); + sLog.outString("AHBuyer: Item Level: %u", prototype->ItemLevel); + sLog.outString("AHBuyer: Ammo Type: %u", prototype->AmmoType); + sLog.outString("-------------------------------------------------"); + } + + // Check whether we do normal bid, or buyout + if ((bidprice < auction->buyout) || (auction->buyout == 0)) + { + + if (auction->bidder > 0) + { + if (auction->bidder == AHBplayer->GetGUIDLow()) + { + //pl->ModifyMoney(-int32(price - auction->bid)); + } + else + { + // mail to last bidder and return money + session->SendAuctionOutbiddedMail(auction , bidprice); + //pl->ModifyMoney(-int32(price)); + } + } + + auction->bidder = AHBplayer->GetGUIDLow(); + auction->bid = bidprice; + + // Saving auction into database + CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); + } + else + { + //buyout + if ((auction->bidder) && (AHBplayer->GetGUIDLow() != auction->bidder)) + { + session->SendAuctionOutbiddedMail(auction, auction->buyout); + } + auction->bidder = AHBplayer->GetGUIDLow(); + auction->bid = auction->buyout; + + // Send mails to buyer & seller + auctionmgr.SendAuctionSalePendingMail(auction); + auctionmgr.SendAuctionSuccessfulMail(auction); + auctionmgr.SendAuctionWonMail(auction); + auction->DeleteFromDB(); + uint32 item_template = auction->item_template; + auctionmgr.RemoveAItem(auction->item_guidlow); + auctionHouse->RemoveAuction(auction, item_template); + } + } +} + +void AuctionHouseBot::Update() +{ + time_t _newrun = time(NULL); + if ((!AHBSeller) && (!AHBBuyer)) + return; + + WorldSession _session(AHBplayerAccount, NULL, SEC_PLAYER, true, 0, LOCALE_enUS); + Player _AHBplayer(&_session); + _AHBplayer.Initialize(AHBplayerGUID); + ObjectAccessor::Instance().AddObject(&_AHBplayer); + + // Add New Bids + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + { + addNewAuctions(&_AHBplayer, &AllianceConfig); + if (((_newrun - _lastrun_a) >= (AllianceConfig.GetBiddingInterval() * MINUTE)) && (AllianceConfig.GetBidsPerInterval() > 0)) + { + //if (debug_Out) sLog.outString("AHBuyer: %u seconds have passed since last bid", (_newrun - _lastrun_a)); + //if (debug_Out) sLog.outString("AHBuyer: Bidding on Alliance Auctions"); + addNewAuctionBuyerBotBid(&_AHBplayer, &AllianceConfig, &_session); + _lastrun_a = _newrun; + } + + addNewAuctions(&_AHBplayer, &HordeConfig); + if (((_newrun - _lastrun_h) >= (HordeConfig.GetBiddingInterval() * MINUTE)) && (HordeConfig.GetBidsPerInterval() > 0)) + { + //if (debug_Out) sLog.outString("AHBuyer: %u seconds have passed since last bid", (_newrun - _lastrun_h)); + //if (debug_Out) sLog.outString("AHBuyer: Bidding on Horde Auctions"); + addNewAuctionBuyerBotBid(&_AHBplayer, &HordeConfig, &_session); + _lastrun_h = _newrun; + } + } + + addNewAuctions(&_AHBplayer, &NeutralConfig); + if (((_newrun - _lastrun_n) >= (NeutralConfig.GetBiddingInterval() * MINUTE)) && (NeutralConfig.GetBidsPerInterval() > 0)) + { + //if (debug_Out) sLog.outString("AHBuyer: %u seconds have passed since last bid", (_newrun - _lastrun_n)); + //if (debug_Out) sLog.outString("AHBuyer: Bidding on Neutral Auctions"); + addNewAuctionBuyerBotBid(&_AHBplayer, &NeutralConfig, &_session); + _lastrun_n = _newrun; + } + ObjectAccessor::Instance().RemoveObject(&_AHBplayer); +} + +void AuctionHouseBot::Initialize() +{ + debug_Out = sConfig.GetBoolDefault("AuctionHouseBot.DEBUG", false); + debug_Out_Filters = sConfig.GetBoolDefault("AuctionHouseBot.DEBUG_FILTERS", false); + + AHBSeller = sConfig.GetBoolDefault("AuctionHouseBot.EnableSeller", false); + AHBBuyer = sConfig.GetBoolDefault("AuctionHouseBot.EnableBuyer", false); + SellMethod = sConfig.GetBoolDefault("AuctionHouseBot.UseBuyPriceForSeller", false); + BuyMethod = sConfig.GetBoolDefault("AuctionHouseBot.UseBuyPriceForBuyer", false); + + AHBplayerAccount = sConfig.GetIntDefault("AuctionHouseBot.Account", 0); + AHBplayerGUID = sConfig.GetIntDefault("AuctionHouseBot.GUID", 0); + ItemsPerCycle = sConfig.GetIntDefault("AuctionHouseBot.ItemsPerCycle", 200); + + //Begin Filters + + Vendor_Items = sConfig.GetBoolDefault("AuctionHouseBot.VendorItems", false); + Loot_Items = sConfig.GetBoolDefault("AuctionHouseBot.LootItems", true); + Other_Items = sConfig.GetBoolDefault("AuctionHouseBot.OtherItems", false); + Vendor_TGs = sConfig.GetBoolDefault("AuctionHouseBot.VendorTradeGoods", false); + Loot_TGs = sConfig.GetBoolDefault("AuctionHouseBot.LootTradeGoods", true); + Other_TGs = sConfig.GetBoolDefault("AuctionHouseBot.OtherTradeGoods", false); + + No_Bind = sConfig.GetBoolDefault("AuctionHouseBot.No_Bind", true); + Bind_When_Picked_Up = sConfig.GetBoolDefault("AuctionHouseBot.Bind_When_Picked_Up", false); + Bind_When_Equipped = sConfig.GetBoolDefault("AuctionHouseBot.Bind_When_Equipped", true); + Bind_When_Use = sConfig.GetBoolDefault("AuctionHouseBot.Bind_When_Use", true); + Bind_Quest_Item = sConfig.GetBoolDefault("AuctionHouseBot.Bind_Quest_Item", false); + + DisableBeta_PTR_Unused = sConfig.GetBoolDefault("AuctionHouseBot.DisableBeta_PTR_Unused", false); + DisablePermEnchant = sConfig.GetBoolDefault("AuctionHouseBot.DisablePermEnchant", false); + DisableConjured = sConfig.GetBoolDefault("AuctionHouseBot.DisableConjured", false); + DisableGems = sConfig.GetBoolDefault("AuctionHouseBot.DisableGems", false); + DisableMoney = sConfig.GetBoolDefault("AuctionHouseBot.DisableMoney", false); + DisableMoneyLoot = sConfig.GetBoolDefault("AuctionHouseBot.DisableMoneyLoot", false); + DisableLootable = sConfig.GetBoolDefault("AuctionHouseBot.DisableLootable", false); + DisableKeys = sConfig.GetBoolDefault("AuctionHouseBot.DisableKeys", false); + DisableDuration = sConfig.GetBoolDefault("AuctionHouseBot.DisableDuration", false); + DisableBOP_Or_Quest_NoReqLevel = sConfig.GetBoolDefault("AuctionHouseBot.DisableBOP_Or_Quest_NoReqLevel", false); + + DisableWarriorItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableWarriorItems", false); + DisablePaladinItems = sConfig.GetBoolDefault("AuctionHouseBot.DisablePaladinItems", false); + DisableHunterItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableHunterItems", false); + DisableRogueItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableRogueItems", false); + DisablePriestItems = sConfig.GetBoolDefault("AuctionHouseBot.DisablePriestItems", false); + DisableDKItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableDKItems", false); + DisableShamanItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableShamanItems", false); + DisableMageItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableMageItems", false); + DisableWarlockItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableWarlockItems", false); + DisableUnusedClassItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableUnusedClassItems", false); + DisableDruidItems = sConfig.GetBoolDefault("AuctionHouseBot.DisableDruidItems", false); + + DisableItemsBelowLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsBelowLevel", 0); + DisableItemsAboveLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsAboveLevel", 0); + DisableTGsBelowLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsBelowLevel", 0); + DisableTGsAboveLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsAboveLevel", 0); + DisableItemsBelowGUID = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsBelowGUID", 0); + DisableItemsAboveGUID = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsAboveGUID", 0); + DisableTGsBelowGUID = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsBelowGUID", 0); + DisableTGsAboveGUID = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsAboveGUID", 0); + DisableItemsBelowReqLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsBelowReqLevel", 0); + DisableItemsAboveReqLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsAboveReqLevel", 0); + DisableTGsBelowReqLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsBelowReqLevel", 0); + DisableTGsAboveReqLevel = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsAboveReqLevel", 0); + DisableItemsBelowReqSkillRank = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsBelowReqSkillRank", 0); + DisableItemsAboveReqSkillRank = sConfig.GetIntDefault("AuctionHouseBot.DisableItemsAboveReqSkillRank", 0); + DisableTGsBelowReqSkillRank = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsBelowReqSkillRank", 0); + DisableTGsAboveReqSkillRank = sConfig.GetIntDefault("AuctionHouseBot.DisableTGsAboveReqSkillRank", 0); + + //End Filters + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + { + LoadValues(&AllianceConfig); + LoadValues(&HordeConfig); + } + LoadValues(&NeutralConfig); + + // + // check if the AHBot account/GUID in the config actually exists + // + + if ((AHBplayerAccount != 0) || (AHBplayerGUID != 0)) + { + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE account = %u AND guid = %u", AHBplayerAccount, AHBplayerGUID); + if (!result) + { + sLog.outError("AuctionHouseBot: The account/GUID-information set for your AHBot is incorrect (account: %u guid: %u)", AHBplayerAccount, AHBplayerGUID); + return; + } + } + + if (AHBSeller) + { + QueryResult_AutoPtr results = QueryResult_AutoPtr(NULL); + char npcQuery[] = "SELECT distinct item FROM npc_vendor"; + results = WorldDatabase.Query(npcQuery); + if (results != NULL) + { + do + { + Field* fields = results->Fetch(); + npcItems.push_back(fields[0].GetUInt32()); + + } while (results->NextRow()); + } + else + { + if (debug_Out) sLog.outString("AuctionHouseBot: \"%s\" failed", npcQuery); + } + + char lootQuery[] = "SELECT item FROM creature_loot_template UNION " + "SELECT item FROM reference_loot_template UNION " + "SELECT item FROM disenchant_loot_template UNION " + "SELECT item FROM fishing_loot_template UNION " + "SELECT item FROM gameobject_loot_template UNION " + "SELECT item FROM item_loot_template UNION " + "SELECT item FROM milling_loot_template UNION " + "SELECT item FROM pickpocketing_loot_template UNION " + "SELECT item FROM prospecting_loot_template UNION " + "SELECT item FROM skinning_loot_template"; + + results = WorldDatabase.Query(lootQuery); + if (results != NULL) + { + do + { + Field* fields = results->Fetch(); + lootItems.push_back(fields[0].GetUInt32()); + + } while (results->NextRow()); + } + else + { + if (debug_Out) sLog.outString("AuctionHouseBot: \"%s\" failed", lootQuery); + } + + for (uint32 itemID = 0; itemID < sItemStorage.MaxEntry; itemID++) + { + ItemPrototype const* prototype = objmgr.GetItemPrototype(itemID); + + if (prototype == NULL) + continue; + + switch (prototype->Bonding) + { + case NO_BIND: + if (!No_Bind) + continue; + break; + case BIND_WHEN_PICKED_UP: + if (!Bind_When_Picked_Up) + continue; + break; + case BIND_WHEN_EQUIPED: + if (!Bind_When_Equipped) + continue; + break; + case BIND_WHEN_USE: + if (!Bind_When_Use) + continue; + break; + case BIND_QUEST_ITEM: + if (!Bind_Quest_Item) + continue; + break; + default: + continue; + break; + } + + switch (SellMethod) + { + case 0: + if (prototype->SellPrice == 0) + continue; + break; + case 1: + if (prototype->BuyPrice == 0) + continue; + break; + } + + if ((prototype->Quality < 0) || (prototype->Quality > 6)) + continue; + + if ((Vendor_Items == 0) && !(prototype->Class == ITEM_CLASS_TRADE_GOODS)) + { + bool isVendorItem = false; + + for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorItem); i++) + { + if (itemID == npcItems[i]) + isVendorItem = true; + } + + if (isVendorItem) + continue; + } + + if ((Vendor_TGs == 0) && (prototype->Class == ITEM_CLASS_TRADE_GOODS)) + { + bool isVendorTG = false; + + for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorTG); i++) + { + if (itemID == npcItems[i]) + isVendorTG = true; + } + + if (isVendorTG) + continue; + } + + if ((Loot_Items == 0) && !(prototype->Class == ITEM_CLASS_TRADE_GOODS)) + { + bool isLootItem = false; + + for (unsigned int i = 0; (i < lootItems.size()) && (!isLootItem); i++) + { + if (itemID == lootItems[i]) + isLootItem = true; + } + + if (isLootItem) + continue; + } + + if ((Loot_TGs == 0) && (prototype->Class == ITEM_CLASS_TRADE_GOODS)) + { + bool isLootTG = false; + + for (unsigned int i = 0; (i < lootItems.size()) && (!isLootTG); i++) + { + if (itemID == lootItems[i]) + isLootTG = true; + } + + if (isLootTG) + continue; + } + + if ((Other_Items == 0) && !(prototype->Class == ITEM_CLASS_TRADE_GOODS)) + { + bool isVendorItem = false; + bool isLootItem = false; + + for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorItem); i++) + { + if (itemID == npcItems[i]) + isVendorItem = true; + } + for (unsigned int i = 0; (i < lootItems.size()) && (!isLootItem); i++) + { + if (itemID == lootItems[i]) + isLootItem = true; + } + if ((!isLootItem) && (!isVendorItem)) + continue; + } + + if ((Other_TGs == 0) && (prototype->Class == ITEM_CLASS_TRADE_GOODS)) + { + bool isVendorTG = false; + bool isLootTG = false; + + for (unsigned int i = 0; (i < npcItems.size()) && (!isVendorTG); i++) + { + if (itemID == npcItems[i]) + isVendorTG = true; + } + for (unsigned int i = 0; (i < lootItems.size()) && (!isLootTG); i++) + { + if (itemID == lootItems[i]) + isLootTG = true; + } + if ((!isLootTG) && (!isVendorTG)) + continue; + } + + //TODO:Make list of items and create a vector + // Disable PTR/Beta/Unused items + if ((DisableBeta_PTR_Unused) && ((prototype->ItemId == 21878) || (prototype->ItemId == 27774) || (prototype->ItemId == 27811) || (prototype->ItemId == 28117) || (prototype->ItemId == 28112))) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (PTR/Beta/Unused Item)", prototype->ItemId); + continue; + } + + // Disable permanent enchants items + if ((DisablePermEnchant) && (prototype->Class == ITEM_CLASS_PERMANENT)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Permanent Enchant Item)", prototype->ItemId); + continue; + } + + // Disable conjured items + if ((DisableConjured) && (prototype->IsConjuredConsumable())) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Conjured Consumable)", prototype->ItemId); + continue; + } + + // Disable gems + if ((DisableGems) && (prototype->Class == ITEM_CLASS_GEM)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Gem)", prototype->ItemId); + continue; + } + + // Disable money + if ((DisableMoney) && (prototype->Class == ITEM_CLASS_MONEY)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Money)", prototype->ItemId); + continue; + } + + // Disable moneyloot + if ((DisableMoneyLoot) && (prototype->MinMoneyLoot > 0)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (MoneyLoot)", prototype->ItemId); + continue; + } + + // Disable lootable items + if ((DisableLootable) && (prototype->Flags & 4)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Lootable Item)", prototype->ItemId); + continue; + } + + // Disable Keys + if ((DisableKeys) && (prototype->Class == ITEM_CLASS_KEY)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Quest Item)", prototype->ItemId); + continue; + } + + // Disable items with duration + if ((DisableDuration) && (prototype->Duration > 0)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Has a Duration)", prototype->ItemId); + continue; + } + + // Disable items which are BOP or Quest Items and have a required level lower than the item level + if ((DisableBOP_Or_Quest_NoReqLevel) && ((prototype->Bonding == BIND_WHEN_PICKED_UP || prototype->Bonding == BIND_QUEST_ITEM) && (prototype->RequiredLevel < prototype->ItemLevel))) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (BOP or BQI and Required Level is less than Item Level)", prototype->ItemId); + continue; + } + + // Disable items specifically for Warrior + if ((DisableWarriorItems) && (prototype->AllowableClass == 1)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Warrior Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Paladin + if ((DisablePaladinItems) && (prototype->AllowableClass == 2)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Paladin Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Hunter + if ((DisableHunterItems) && (prototype->AllowableClass == 4)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Hunter Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Rogue + if ((DisableRogueItems) && (prototype->AllowableClass == 8)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Rogue Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Priest + if ((DisablePriestItems) && (prototype->AllowableClass == 16)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Priest Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for DK + if ((DisableDKItems) && (prototype->AllowableClass == 32)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (DK Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Shaman + if ((DisableShamanItems) && (prototype->AllowableClass == 64)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Shaman Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Mage + if ((DisableMageItems) && (prototype->AllowableClass == 128)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Mage Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Warlock + if ((DisableWarlockItems) && (prototype->AllowableClass == 256)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Warlock Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Unused Class + if ((DisableUnusedClassItems) && (prototype->AllowableClass == 512)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Unused Item)", prototype->ItemId); + continue; + } + + // Disable items specifically for Druid + if ((DisableDruidItems) && (prototype->AllowableClass == 1024)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Druid Item)", prototype->ItemId); + continue; + } + + // Disable Items below level X + if ((DisableItemsBelowLevel) && (prototype->Class != ITEM_CLASS_TRADE_GOODS) && (prototype->ItemLevel < DisableItemsBelowLevel)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Item Level = %u)", prototype->ItemId, prototype->ItemLevel); + continue; + } + + // Disable Items above level X + if ((DisableItemsAboveLevel) && (prototype->Class != ITEM_CLASS_TRADE_GOODS) && (prototype->ItemLevel > DisableItemsAboveLevel)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Item Level = %u)", prototype->ItemId, prototype->ItemLevel); + continue; + } + + // Disable Trade Goods below level X + if ((DisableTGsBelowLevel) && (prototype->Class == ITEM_CLASS_TRADE_GOODS) && (prototype->ItemLevel < DisableTGsBelowLevel)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Trade Good %u disabled (Trade Good Level = %u)", prototype->ItemId, prototype->ItemLevel); + continue; + } + + // Disable Trade Goods above level X + if ((DisableTGsAboveLevel) && (prototype->Class == ITEM_CLASS_TRADE_GOODS) && (prototype->ItemLevel > DisableTGsAboveLevel)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Trade Good %u disabled (Trade Good Level = %u)", prototype->ItemId, prototype->ItemLevel); + continue; + } + + // Disable Items below GUID X + if ((DisableItemsBelowGUID) && (prototype->Class != ITEM_CLASS_TRADE_GOODS) && (prototype->ItemId < DisableItemsBelowGUID)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Item Level = %u)", prototype->ItemId, prototype->ItemLevel); + continue; + } + + // Disable Items above GUID X + if ((DisableItemsAboveGUID) && (prototype->Class != ITEM_CLASS_TRADE_GOODS) && (prototype->ItemId > DisableItemsAboveGUID)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Item Level = %u)", prototype->ItemId, prototype->ItemLevel); + continue; + } + + // Disable Trade Goods below GUID X + if ((DisableTGsBelowGUID) && (prototype->Class == ITEM_CLASS_TRADE_GOODS) && (prototype->ItemId < DisableTGsBelowGUID)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Trade Good Level = %u)", prototype->ItemId, prototype->ItemLevel); + continue; + } + + // Disable Trade Goods above GUID X + if ((DisableTGsAboveGUID) && (prototype->Class == ITEM_CLASS_TRADE_GOODS) && (prototype->ItemId > DisableTGsAboveGUID)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (Trade Good Level = %u)", prototype->ItemId, prototype->ItemLevel); + continue; + } + + // Disable Items for level lower than X + if ((DisableItemsBelowReqLevel) && (prototype->RequiredLevel < DisableItemsBelowReqLevel)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredLevel = %u)", prototype->ItemId, prototype->RequiredLevel); + continue; + } + + // Disable Items for level higher than X + if ((DisableItemsAboveReqLevel) && (prototype->RequiredLevel > DisableItemsAboveReqLevel)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredLevel = %u)", prototype->ItemId, prototype->RequiredLevel); + continue; + } + + // Disable Trade Goods for level lower than X + if ((DisableTGsBelowReqLevel) && (prototype->RequiredLevel < DisableTGsBelowReqLevel)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Trade Good %u disabled (RequiredLevel = %u)", prototype->ItemId, prototype->RequiredLevel); + continue; + } + + // Disable Trade Goods for level higher than X + if ((DisableTGsAboveReqLevel) && (prototype->RequiredLevel > DisableTGsAboveReqLevel)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Trade Good %u disabled (RequiredLevel = %u)", prototype->ItemId, prototype->RequiredLevel); + continue; + } + + // Disable Items that require skill lower than X + if ((DisableItemsBelowReqSkillRank) && (prototype->RequiredSkillRank < DisableItemsBelowReqSkillRank)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredSkillRank = %u)", prototype->ItemId, prototype->RequiredSkillRank); + continue; + } + + // Disable Items that require skill higher than X + if ((DisableItemsAboveReqSkillRank) && (prototype->RequiredSkillRank > DisableItemsAboveReqSkillRank)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredSkillRank = %u)", prototype->ItemId, prototype->RequiredSkillRank); + continue; + } + + // Disable Trade Goods that require skill lower than X + if ((DisableTGsBelowReqSkillRank) && (prototype->RequiredSkillRank < DisableTGsBelowReqSkillRank)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredSkillRank = %u)", prototype->ItemId, prototype->RequiredSkillRank); + continue; + } + + // Disable Trade Goods that require skill higher than X + if ((DisableTGsAboveReqSkillRank) && (prototype->RequiredSkillRank > DisableTGsAboveReqSkillRank)) + { + if (debug_Out_Filters) sLog.outString("AuctionHouseBot: Item %u disabled (RequiredSkillRank = %u)", prototype->ItemId, prototype->RequiredSkillRank); + continue; + } + + switch (prototype->Quality) + { + case AHB_GREY: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + greyTradeGoodsBin.push_back(itemID); + else + greyItemsBin.push_back(itemID); + break; + + case AHB_WHITE: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + whiteTradeGoodsBin.push_back(itemID); + else + whiteItemsBin.push_back(itemID); + break; + + case AHB_GREEN: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + greenTradeGoodsBin.push_back(itemID); + else + greenItemsBin.push_back(itemID); + break; + + case AHB_BLUE: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + blueTradeGoodsBin.push_back(itemID); + else + blueItemsBin.push_back(itemID); + break; + + case AHB_PURPLE: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + purpleTradeGoodsBin.push_back(itemID); + else + purpleItemsBin.push_back(itemID); + break; + + case AHB_ORANGE: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + orangeTradeGoodsBin.push_back(itemID); + else + orangeItemsBin.push_back(itemID); + break; + + case AHB_YELLOW: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + yellowTradeGoodsBin.push_back(itemID); + else + yellowItemsBin.push_back(itemID); + break; + } + } + + if ((greyTradeGoodsBin.size() == 0) && + (whiteTradeGoodsBin.size() == 0) && + (greenTradeGoodsBin.size() == 0) && + (blueTradeGoodsBin.size() == 0) && + (purpleTradeGoodsBin.size() == 0) && + (orangeTradeGoodsBin.size() == 0) && + (yellowTradeGoodsBin.size() == 0) && + (greyItemsBin.size() == 0) && + (whiteItemsBin.size() == 0) && + (greenItemsBin.size() == 0) && + (blueItemsBin.size() == 0) && + (purpleItemsBin.size() == 0) && + (orangeItemsBin.size() == 0) && + (yellowItemsBin.size() == 0)) + { + sLog.outError("AuctionHouseBot: No items"); + AHBSeller = 0; + } + + sLog.outString("AuctionHouseBot:"); + sLog.outString("loaded %u grey trade goods", greyTradeGoodsBin.size()); + sLog.outString("loaded %u white trade goods", whiteTradeGoodsBin.size()); + sLog.outString("loaded %u green trade goods", greenTradeGoodsBin.size()); + sLog.outString("loaded %u blue trade goods", blueTradeGoodsBin.size()); + sLog.outString("loaded %u purple trade goods", purpleTradeGoodsBin.size()); + sLog.outString("loaded %u orange trade goods", orangeTradeGoodsBin.size()); + sLog.outString("loaded %u yellow trade goods", yellowTradeGoodsBin.size()); + sLog.outString("loaded %u grey items", greyItemsBin.size()); + sLog.outString("loaded %u white items", whiteItemsBin.size()); + sLog.outString("loaded %u green items", greenItemsBin.size()); + sLog.outString("loaded %u blue items", blueItemsBin.size()); + sLog.outString("loaded %u purple items", purpleItemsBin.size()); + sLog.outString("loaded %u orange items", orangeItemsBin.size()); + sLog.outString("loaded %u yellow items", yellowItemsBin.size()); + } + sLog.outString("AuctionHouseBot and AuctionHouseBuyer have been loaded."); +} + +void AuctionHouseBot::IncrementItemCounts(AuctionEntry* ah) +{ + // from auctionhousehandler.cpp, creates auction pointer & player pointer + + // get exact item information + Item *pItem = auctionmgr.GetAItem(ah->item_guidlow); + if (!pItem) + { + if (debug_Out) sLog.outError("AHBot: Item %u doesn't exist, perhaps bought already?", ah->item_guidlow); + return; + } + + // get item prototype + ItemPrototype const* prototype = objmgr.GetItemPrototype(ah->item_template); + + AHBConfig *config; + + FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(ah->GetHouseFaction()); + if (!u_entry) + { + if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Neutral", ah->GetHouseFaction()); + config = &NeutralConfig; + } + else if (u_entry->ourMask & FACTION_MASK_ALLIANCE) + { + if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Alliance", ah->GetHouseFaction()); + config = &AllianceConfig; + } + else if (u_entry->ourMask & FACTION_MASK_HORDE) + { + if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Horde", ah->GetHouseFaction()); + config = &HordeConfig; + } + else + { + if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Neutral", ah->GetHouseFaction()); + config = &NeutralConfig; + } + + config->IncItemCounts(prototype->Class, prototype->Quality); +} + +void AuctionHouseBot::DecrementItemCounts(AuctionEntry* ah, uint32 item_template) +{ + // get item prototype + ItemPrototype const* prototype = objmgr.GetItemPrototype(item_template); + + AHBConfig *config; + + FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(ah->GetHouseFaction()); + if (!u_entry) + { + if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Neutral", ah->GetHouseFaction()); + config = &NeutralConfig; + } + else if (u_entry->ourMask & FACTION_MASK_ALLIANCE) + { + if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Alliance", ah->GetHouseFaction()); + config = &AllianceConfig; + } + else if (u_entry->ourMask & FACTION_MASK_HORDE) + { + if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Horde", ah->GetHouseFaction()); + config = &HordeConfig; + } + else + { + if (debug_Out) sLog.outError("AHBot: %u returned as House Faction. Neutral", ah->GetHouseFaction()); + config = &NeutralConfig; + } + + config->DecItemCounts(prototype->Class, prototype->Quality); +} + +void AuctionHouseBot::Commands(uint32 command, uint32 ahMapID, uint32 col, char* args) +{ + AHBConfig *config = NULL; + switch (ahMapID) + { + case 2: + config = &AllianceConfig; + break; + case 6: + config = &HordeConfig; + break; + case 7: + config = &NeutralConfig; + break; + } + std::string color; + switch (col) + { + case AHB_GREY: + color = "grey"; + break; + case AHB_WHITE: + color = "white"; + break; + case AHB_GREEN: + color = "green"; + break; + case AHB_BLUE: + color = "blue"; + break; + case AHB_PURPLE: + color = "purple"; + break; + case AHB_ORANGE: + color = "orange"; + break; + case AHB_YELLOW: + color = "yellow"; + break; + default: + break; + } + switch (command) + { + case 0: //ahexpire + { + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(config->GetAHFID()); + + AuctionHouseObject::AuctionEntryMap::iterator itr; + itr = auctionHouse->GetAuctionsBegin(); + + while (itr != auctionHouse->GetAuctionsEnd()) + { + if (itr->second->owner == AHBplayerGUID) + { + itr->second->expire_time = sWorld.GetGameTime(); + uint32 id = itr->second->Id; + uint32 expire_time = itr->second->expire_time; + CharacterDatabase.PExecute("UPDATE auctionhouse SET time = '%u' WHERE id = '%u'", expire_time, id); + } + ++itr; + } + } + break; + case 1: //min items + { + char * param1 = strtok(args, " "); + uint32 minItems = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET minitems = '%u' WHERE auctionhouse = '%u'", minItems, ahMapID); + config->SetMinItems(minItems); + } + break; + case 2: //max items + { + char * param1 = strtok(args, " "); + uint32 maxItems = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET maxitems = '%u' WHERE auctionhouse = '%u'", maxItems, ahMapID); + config->SetMaxItems(maxItems); + } + break; + case 3: //min time Deprecated (Place holder for future commands) + break; + case 4: //max time Deprecated (Place holder for future commands) + break; + case 5: //percentages + { + char * param1 = strtok(args, " "); + char * param2 = strtok(NULL, " "); + char * param3 = strtok(NULL, " "); + char * param4 = strtok(NULL, " "); + char * param5 = strtok(NULL, " "); + char * param6 = strtok(NULL, " "); + char * param7 = strtok(NULL, " "); + char * param8 = strtok(NULL, " "); + char * param9 = strtok(NULL, " "); + char * param10 = strtok(NULL, " "); + char * param11 = strtok(NULL, " "); + char * param12 = strtok(NULL, " "); + char * param13 = strtok(NULL, " "); + char * param14 = strtok(NULL, " "); + uint32 greytg = (uint32) strtoul(param1, NULL, 0); + uint32 whitetg = (uint32) strtoul(param2, NULL, 0); + uint32 greentg = (uint32) strtoul(param3, NULL, 0); + uint32 bluetg = (uint32) strtoul(param4, NULL, 0); + uint32 purpletg = (uint32) strtoul(param5, NULL, 0); + uint32 orangetg = (uint32) strtoul(param6, NULL, 0); + uint32 yellowtg = (uint32) strtoul(param7, NULL, 0); + uint32 greyi = (uint32) strtoul(param8, NULL, 0); + uint32 whitei = (uint32) strtoul(param9, NULL, 0); + uint32 greeni = (uint32) strtoul(param10, NULL, 0); + uint32 bluei = (uint32) strtoul(param11, NULL, 0); + uint32 purplei = (uint32) strtoul(param12, NULL, 0); + uint32 orangei = (uint32) strtoul(param13, NULL, 0); + uint32 yellowi = (uint32) strtoul(param14, NULL, 0); + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentgreytradegoods = '%u' WHERE auctionhouse = '%u'", greytg, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentwhitetradegoods = '%u' WHERE auctionhouse = '%u'", whitetg, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentgreentradegoods = '%u' WHERE auctionhouse = '%u'", greentg, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentbluetradegoods = '%u' WHERE auctionhouse = '%u'", bluetg, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentpurpletradegoods = '%u' WHERE auctionhouse = '%u'", purpletg, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentorangetradegoods = '%u' WHERE auctionhouse = '%u'", orangetg, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentyellowtradegoods = '%u' WHERE auctionhouse = '%u'", yellowtg, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentgreyitems = '%u' WHERE auctionhouse = '%u'", greyi, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentwhiteitems = '%u' WHERE auctionhouse = '%u'", whitei, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentgreenitems = '%u' WHERE auctionhouse = '%u'", greeni, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentblueitems = '%u' WHERE auctionhouse = '%u'", bluei, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentpurpleitems = '%u' WHERE auctionhouse = '%u'", purplei, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentorangeitems = '%u' WHERE auctionhouse = '%u'", orangei, ahMapID); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET percentyellowitems = '%u' WHERE auctionhouse = '%u'", yellowi, ahMapID); + CharacterDatabase.CommitTransaction(); + config->SetPercentages(greytg, whitetg, greentg, bluetg, purpletg, orangetg, yellowtg, greyi, whitei, greeni, bluei, purplei, orangei, yellowi); + } + break; + case 6: //min prices + { + char * param1 = strtok(args, " "); + uint32 minPrice = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET minprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), minPrice, ahMapID); + config->SetMinPrice(col, minPrice); + } + break; + case 7: //max prices + { + char * param1 = strtok(args, " "); + uint32 maxPrice = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET maxprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), maxPrice, ahMapID); + config->SetMaxPrice(col, maxPrice); + } + break; + case 8: //min bid price + { + char * param1 = strtok(args, " "); + uint32 minBidPrice = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET minbidprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), minBidPrice, ahMapID); + config->SetMinBidPrice(col, minBidPrice); + } + break; + case 9: //max bid price + { + char * param1 = strtok(args, " "); + uint32 maxBidPrice = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET maxbidprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), maxBidPrice, ahMapID); + config->SetMaxBidPrice(col, maxBidPrice); + } + break; + case 10: //max stacks + { + char * param1 = strtok(args, " "); + uint32 maxStack = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET maxstack%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), maxStack, ahMapID); + config->SetMaxStack(col, maxStack); + } + break; + case 11: //buyer bid prices + { + char * param1 = strtok(args, " "); + uint32 buyerPrice = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET buyerprice%s = '%u' WHERE auctionhouse = '%u'",color.c_str(), buyerPrice, ahMapID); + config->SetBuyerPrice(col, buyerPrice); + } + break; + case 12: //buyer bidding interval + { + char * param1 = strtok(args, " "); + uint32 bidInterval = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET buyerbiddinginterval = '%u' WHERE auctionhouse = '%u'", bidInterval, ahMapID); + config->SetBiddingInterval(bidInterval); + } + break; + case 13: //buyer bids per interval + { + char * param1 = strtok(args, " "); + uint32 bidsPerInterval = (uint32) strtoul(param1, NULL, 0); + CharacterDatabase.PExecute("UPDATE auctionhousebot SET buyerbidsperinterval = '%u' WHERE auctionhouse = '%u'", bidsPerInterval, ahMapID); + config->SetBidsPerInterval(bidsPerInterval); + } + break; + default: + break; + } +} + +void AuctionHouseBot::LoadValues(AHBConfig *config) +{ + if (debug_Out) sLog.outString("Start Settings for %s Auctionhouses:", CharacterDatabase.PQuery("SELECT name FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetString()); + if (AHBSeller) + { + //load min and max items + config->SetMinItems(CharacterDatabase.PQuery("SELECT minitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxItems(CharacterDatabase.PQuery("SELECT maxitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + //load percentages + uint32 greytg = CharacterDatabase.PQuery("SELECT percentgreytradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 whitetg = CharacterDatabase.PQuery("SELECT percentwhitetradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 greentg = CharacterDatabase.PQuery("SELECT percentgreentradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 bluetg = CharacterDatabase.PQuery("SELECT percentbluetradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 purpletg = CharacterDatabase.PQuery("SELECT percentpurpletradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 orangetg = CharacterDatabase.PQuery("SELECT percentorangetradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 yellowtg = CharacterDatabase.PQuery("SELECT percentyellowtradegoods FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 greyi = CharacterDatabase.PQuery("SELECT percentgreyitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 whitei = CharacterDatabase.PQuery("SELECT percentwhiteitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 greeni = CharacterDatabase.PQuery("SELECT percentgreenitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 bluei = CharacterDatabase.PQuery("SELECT percentblueitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 purplei = CharacterDatabase.PQuery("SELECT percentpurpleitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 orangei = CharacterDatabase.PQuery("SELECT percentorangeitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + uint32 yellowi = CharacterDatabase.PQuery("SELECT percentyellowitems FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32(); + config->SetPercentages(greytg, whitetg, greentg, bluetg, purpletg, orangetg, yellowtg, greyi, whitei, greeni, bluei, purplei, orangei, yellowi); + //load min and max prices + config->SetMinPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT minpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT maxpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT minpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT maxpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT minpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT maxpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT minpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT maxpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT minpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT maxpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT minpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT maxpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT minpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT maxpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + //load min and max bid prices + config->SetMinBidPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT minbidpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxBidPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT maxbidpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinBidPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT minbidpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxBidPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT maxbidpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinBidPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT minbidpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxBidPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT maxbidpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinBidPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT minbidpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxBidPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT maxbidpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinBidPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT minbidpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxBidPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT maxbidpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinBidPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT minbidpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxBidPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT maxbidpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMinBidPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT minbidpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxBidPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT maxbidpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + //load max stacks + config->SetMaxStack(AHB_GREY, CharacterDatabase.PQuery("SELECT maxstackgrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxStack(AHB_WHITE, CharacterDatabase.PQuery("SELECT maxstackwhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxStack(AHB_GREEN, CharacterDatabase.PQuery("SELECT maxstackgreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxStack(AHB_BLUE, CharacterDatabase.PQuery("SELECT maxstackblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxStack(AHB_PURPLE, CharacterDatabase.PQuery("SELECT maxstackpurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxStack(AHB_ORANGE, CharacterDatabase.PQuery("SELECT maxstackorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetMaxStack(AHB_YELLOW, CharacterDatabase.PQuery("SELECT maxstackyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + if (debug_Out) + { + sLog.outString("minItems = %u", config->GetMinItems()); + sLog.outString("maxItems = %u", config->GetMaxItems()); + sLog.outString("percentGreyTradeGoods = %u", config->GetPercentages(AHB_GREY_TG)); + sLog.outString("percentWhiteTradeGoods = %u", config->GetPercentages(AHB_WHITE_TG)); + sLog.outString("percentGreenTradeGoods = %u", config->GetPercentages(AHB_GREEN_TG)); + sLog.outString("percentBlueTradeGoods = %u", config->GetPercentages(AHB_BLUE_TG)); + sLog.outString("percentPurpleTradeGoods = %u", config->GetPercentages(AHB_PURPLE_TG)); + sLog.outString("percentOrangeTradeGoods = %u", config->GetPercentages(AHB_ORANGE_TG)); + sLog.outString("percentYellowTradeGoods = %u", config->GetPercentages(AHB_YELLOW_TG)); + sLog.outString("percentGreyItems = %u", config->GetPercentages(AHB_GREY_I)); + sLog.outString("percentWhiteItems = %u", config->GetPercentages(AHB_WHITE_I)); + sLog.outString("percentGreenItems = %u", config->GetPercentages(AHB_GREEN_I)); + sLog.outString("percentBlueItems = %u", config->GetPercentages(AHB_BLUE_I)); + sLog.outString("percentPurpleItems = %u", config->GetPercentages(AHB_PURPLE_I)); + sLog.outString("percentOrangeItems = %u", config->GetPercentages(AHB_ORANGE_I)); + sLog.outString("percentYellowItems = %u", config->GetPercentages(AHB_YELLOW_I)); + sLog.outString("minPriceGrey = %u", config->GetMinPrice(AHB_GREY)); + sLog.outString("maxPriceGrey = %u", config->GetMaxPrice(AHB_GREY)); + sLog.outString("minPriceWhite = %u", config->GetMinPrice(AHB_WHITE)); + sLog.outString("maxPriceWhite = %u", config->GetMaxPrice(AHB_WHITE)); + sLog.outString("minPriceGreen = %u", config->GetMinPrice(AHB_GREEN)); + sLog.outString("maxPriceGreen = %u", config->GetMaxPrice(AHB_GREEN)); + sLog.outString("minPriceBlue = %u", config->GetMinPrice(AHB_BLUE)); + sLog.outString("maxPriceBlue = %u", config->GetMaxPrice(AHB_BLUE)); + sLog.outString("minPricePurple = %u", config->GetMinPrice(AHB_PURPLE)); + sLog.outString("maxPricePurple = %u", config->GetMaxPrice(AHB_PURPLE)); + sLog.outString("minPriceOrange = %u", config->GetMinPrice(AHB_ORANGE)); + sLog.outString("maxPriceOrange = %u", config->GetMaxPrice(AHB_ORANGE)); + sLog.outString("minPriceYellow = %u", config->GetMinPrice(AHB_YELLOW)); + sLog.outString("maxPriceYellow = %u", config->GetMaxPrice(AHB_YELLOW)); + sLog.outString("minBidPriceGrey = %u", config->GetMinBidPrice(AHB_GREY)); + sLog.outString("maxBidPriceGrey = %u", config->GetMaxBidPrice(AHB_GREY)); + sLog.outString("minBidPriceWhite = %u", config->GetMinBidPrice(AHB_WHITE)); + sLog.outString("maxBidPriceWhite = %u", config->GetMaxBidPrice(AHB_WHITE)); + sLog.outString("minBidPriceGreen = %u", config->GetMinBidPrice(AHB_GREEN)); + sLog.outString("maxBidPriceGreen = %u", config->GetMaxBidPrice(AHB_GREEN)); + sLog.outString("minBidPriceBlue = %u", config->GetMinBidPrice(AHB_BLUE)); + sLog.outString("maxBidPriceBlue = %u", config->GetMinBidPrice(AHB_BLUE)); + sLog.outString("minBidPricePurple = %u", config->GetMinBidPrice(AHB_PURPLE)); + sLog.outString("maxBidPricePurple = %u", config->GetMaxBidPrice(AHB_PURPLE)); + sLog.outString("minBidPriceOrange = %u", config->GetMinBidPrice(AHB_ORANGE)); + sLog.outString("maxBidPriceOrange = %u", config->GetMaxBidPrice(AHB_ORANGE)); + sLog.outString("minBidPriceYellow = %u", config->GetMinBidPrice(AHB_YELLOW)); + sLog.outString("maxBidPriceYellow = %u", config->GetMaxBidPrice(AHB_YELLOW)); + sLog.outString("maxStackGrey = %u", config->GetMaxStack(AHB_GREY)); + sLog.outString("maxStackWhite = %u", config->GetMaxStack(AHB_WHITE)); + sLog.outString("maxStackGreen = %u", config->GetMaxStack(AHB_GREEN)); + sLog.outString("maxStackBlue = %u", config->GetMaxStack(AHB_BLUE)); + sLog.outString("maxStackPurple = %u", config->GetMaxStack(AHB_PURPLE)); + sLog.outString("maxStackOrange = %u", config->GetMaxStack(AHB_ORANGE)); + sLog.outString("maxStackYellow = %u", config->GetMaxStack(AHB_YELLOW)); + } + //AuctionHouseEntry const* ahEntry = auctionmgr.GetAuctionHouseEntry(config->GetAHFID()); + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(config->GetAHFID()); + + config->ResetItemCounts(); + uint32 auctions = auctionHouse->Getcount(); + + if (auctions) + { + for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = auctionHouse->GetAuctionsBegin(); itr != auctionHouse->GetAuctionsEnd(); ++itr) + { + AuctionEntry *Aentry = itr->second; + Item *item = auctionmgr.GetAItem(Aentry->item_guidlow); + if (item) + { + ItemPrototype const *prototype = item->GetProto(); + if (prototype) + { + switch (prototype->Quality) + { + case 0: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + config->IncItemCounts(AHB_GREY_TG); + else + config->IncItemCounts(AHB_GREY_I); + break; + case 1: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + config->IncItemCounts(AHB_WHITE_TG); + else + config->IncItemCounts(AHB_WHITE_I); + break; + case 2: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + config->IncItemCounts(AHB_GREEN_TG); + else + config->IncItemCounts(AHB_GREEN_I); + break; + case 3: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + config->IncItemCounts(AHB_BLUE_TG); + else + config->IncItemCounts(AHB_BLUE_I); + break; + case 4: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + config->IncItemCounts(AHB_PURPLE_TG); + else + config->IncItemCounts(AHB_PURPLE_I); + break; + case 5: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + config->IncItemCounts(AHB_ORANGE_TG); + else + config->IncItemCounts(AHB_ORANGE_I); + break; + case 6: + if (prototype->Class == ITEM_CLASS_TRADE_GOODS) + config->IncItemCounts(AHB_YELLOW_TG); + else + config->IncItemCounts(AHB_YELLOW_I); + break; + } + } + } + } + } + if (debug_Out) + { + sLog.outString("Current Items in %s Auctionhouses:", CharacterDatabase.PQuery("SELECT name FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetString()); + sLog.outString("Grey Trade Goods\t%u\tGrey Items\t%u", config->GetItemCounts(AHB_GREY_TG), config->GetItemCounts(AHB_GREY_I)); + sLog.outString("White Trade Goods\t%u\tWhite Items\t%u", config->GetItemCounts(AHB_WHITE_TG), config->GetItemCounts(AHB_WHITE_I)); + sLog.outString("Green Trade Goods\t%u\tGreen Items\t%u", config->GetItemCounts(AHB_GREEN_TG), config->GetItemCounts(AHB_GREEN_I)); + sLog.outString("Blue Trade Goods\t%u\tBlue Items\t%u", config->GetItemCounts(AHB_BLUE_TG), config->GetItemCounts(AHB_BLUE_I)); + sLog.outString("Purple Trade Goods\t%u\tPurple Items\t%u", config->GetItemCounts(AHB_PURPLE_TG), config->GetItemCounts(AHB_PURPLE_I)); + sLog.outString("Orange Trade Goods\t%u\tOrange Items\t%u", config->GetItemCounts(AHB_ORANGE_TG), config->GetItemCounts(AHB_ORANGE_I)); + sLog.outString("Yellow Trade Goods\t%u\tYellow Items\t%u", config->GetItemCounts(AHB_YELLOW_TG), config->GetItemCounts(AHB_YELLOW_I)); + } + } + if (AHBBuyer) + { + //load buyer bid prices + config->SetBuyerPrice(AHB_GREY, CharacterDatabase.PQuery("SELECT buyerpricegrey FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetBuyerPrice(AHB_WHITE, CharacterDatabase.PQuery("SELECT buyerpricewhite FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetBuyerPrice(AHB_GREEN, CharacterDatabase.PQuery("SELECT buyerpricegreen FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetBuyerPrice(AHB_BLUE, CharacterDatabase.PQuery("SELECT buyerpriceblue FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetBuyerPrice(AHB_PURPLE, CharacterDatabase.PQuery("SELECT buyerpricepurple FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetBuyerPrice(AHB_ORANGE, CharacterDatabase.PQuery("SELECT buyerpriceorange FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + config->SetBuyerPrice(AHB_YELLOW, CharacterDatabase.PQuery("SELECT buyerpriceyellow FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + //load bidding interval + config->SetBiddingInterval(CharacterDatabase.PQuery("SELECT buyerbiddinginterval FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + //load bids per interval + config->SetBidsPerInterval(CharacterDatabase.PQuery("SELECT buyerbidsperinterval FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetUInt32()); + if (debug_Out) + { + sLog.outString("buyerPriceGrey = %u", config->GetBuyerPrice(AHB_GREY)); + sLog.outString("buyerPriceWhite = %u", config->GetBuyerPrice(AHB_WHITE)); + sLog.outString("buyerPriceGreen = %u", config->GetBuyerPrice(AHB_GREEN)); + sLog.outString("buyerPriceBlue = %u", config->GetBuyerPrice(AHB_BLUE)); + sLog.outString("buyerPricePurple = %u", config->GetBuyerPrice(AHB_PURPLE)); + sLog.outString("buyerPriceOrange = %u", config->GetBuyerPrice(AHB_ORANGE)); + sLog.outString("buyerPriceYellow = %u", config->GetBuyerPrice(AHB_YELLOW)); + sLog.outString("buyerBiddingInterval = %u", config->GetBiddingInterval()); + sLog.outString("buyerBidsPerInterval = %u", config->GetBidsPerInterval()); + } + } + if (debug_Out) sLog.outString("End Settings for %s Auctionhouses:", CharacterDatabase.PQuery("SELECT name FROM auctionhousebot WHERE auctionhouse = %u",config->GetAHID())->Fetch()->GetString()); +} diff --git a/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.h new file mode 100644 index 00000000000..208a09aa0b2 --- /dev/null +++ b/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.h @@ -0,0 +1,1225 @@ +#ifndef AUCTION_HOUSE_BOT_H +#define AUCTION_HOUSE_BOT_H + +#include "World.h" +#include "Config/ConfigEnv.h" +#include "ItemPrototype.h" + +#define AHB_GREY 0 +#define AHB_WHITE 1 +#define AHB_GREEN 2 +#define AHB_BLUE 3 +#define AHB_PURPLE 4 +#define AHB_ORANGE 5 +#define AHB_YELLOW 6 +#define AHB_MAX_QUALITY 6 +#define AHB_GREY_TG 0 +#define AHB_WHITE_TG 1 +#define AHB_GREEN_TG 2 +#define AHB_BLUE_TG 3 +#define AHB_PURPLE_TG 4 +#define AHB_ORANGE_TG 5 +#define AHB_YELLOW_TG 6 +#define AHB_GREY_I 7 +#define AHB_WHITE_I 8 +#define AHB_GREEN_I 9 +#define AHB_BLUE_I 10 +#define AHB_PURPLE_I 11 +#define AHB_ORANGE_I 12 +#define AHB_YELLOW_I 13 + +class AHBConfig +{ +private: + uint32 AHID; + uint32 AHFID; + uint32 minItems; + uint32 maxItems; + uint32 percentGreyTradeGoods; + uint32 percentWhiteTradeGoods; + uint32 percentGreenTradeGoods; + uint32 percentBlueTradeGoods; + uint32 percentPurpleTradeGoods; + uint32 percentOrangeTradeGoods; + uint32 percentYellowTradeGoods; + uint32 percentGreyItems; + uint32 percentWhiteItems; + uint32 percentGreenItems; + uint32 percentBlueItems; + uint32 percentPurpleItems; + uint32 percentOrangeItems; + uint32 percentYellowItems; + uint32 minPriceGrey; + uint32 maxPriceGrey; + uint32 minBidPriceGrey; + uint32 maxBidPriceGrey; + uint32 maxStackGrey; + uint32 minPriceWhite; + uint32 maxPriceWhite; + uint32 minBidPriceWhite; + uint32 maxBidPriceWhite; + uint32 maxStackWhite; + uint32 minPriceGreen; + uint32 maxPriceGreen; + uint32 minBidPriceGreen; + uint32 maxBidPriceGreen; + uint32 maxStackGreen; + uint32 minPriceBlue; + uint32 maxPriceBlue; + uint32 minBidPriceBlue; + uint32 maxBidPriceBlue; + uint32 maxStackBlue; + uint32 minPricePurple; + uint32 maxPricePurple; + uint32 minBidPricePurple; + uint32 maxBidPricePurple; + uint32 maxStackPurple; + uint32 minPriceOrange; + uint32 maxPriceOrange; + uint32 minBidPriceOrange; + uint32 maxBidPriceOrange; + uint32 maxStackOrange; + uint32 minPriceYellow; + uint32 maxPriceYellow; + uint32 minBidPriceYellow; + uint32 maxBidPriceYellow; + uint32 maxStackYellow; + + uint32 buyerPriceGrey; + uint32 buyerPriceWhite; + uint32 buyerPriceGreen; + uint32 buyerPriceBlue; + uint32 buyerPricePurple; + uint32 buyerPriceOrange; + uint32 buyerPriceYellow; + uint32 buyerBiddingInterval; + uint32 buyerBidsPerInterval; + + uint32 greytgp; + uint32 whitetgp; + uint32 greentgp; + uint32 bluetgp; + uint32 purpletgp; + uint32 orangetgp; + uint32 yellowtgp; + uint32 greyip; + uint32 whiteip; + uint32 greenip; + uint32 blueip; + uint32 purpleip; + uint32 orangeip; + uint32 yellowip; + + uint32 greyTGoods; + uint32 whiteTGoods; + uint32 greenTGoods; + uint32 blueTGoods; + uint32 purpleTGoods; + uint32 orangeTGoods; + uint32 yellowTGoods; + + uint32 greyItems; + uint32 whiteItems; + uint32 greenItems; + uint32 blueItems; + uint32 purpleItems; + uint32 orangeItems; + uint32 yellowItems; + +public: + AHBConfig(uint32 ahid) + { + AHID = ahid; + switch(ahid) + { + case 2: + AHFID = 55; + break; + case 6: + AHFID = 29; + break; + case 7: + AHFID = 120; + break; + default: + AHFID = 120; + break; + } + } + AHBConfig() + { + } + uint32 GetAHID() + { + return AHID; + } + uint32 GetAHFID() + { + return AHFID; + } + void SetMinItems(uint32 value) + { + minItems = value; + } + uint32 GetMinItems() + { + if ((minItems == 0) && (maxItems)) + return maxItems; + else if ((maxItems) && (minItems > maxItems)) + return maxItems; + else + return minItems; + } + void SetMaxItems(uint32 value) + { + maxItems = value; + CalculatePercents(); + } + uint32 GetMaxItems() + { + return maxItems; + } + void SetPercentages(uint32 greytg, uint32 whitetg, uint32 greentg, uint32 bluetg, uint32 purpletg, uint32 orangetg, uint32 yellowtg, uint32 greyi, uint32 whitei, uint32 greeni, uint32 bluei, uint32 purplei, uint32 orangei, uint32 yellowi) + { + uint32 totalPercent = greytg + whitetg + greentg + bluetg + purpletg + orangetg + yellowtg + greyi + whitei + greeni + bluei + purplei + orangei + yellowi; + + if (totalPercent == 0) + { + maxItems = 0; + } + else if (totalPercent != 100) + { + greytg = 0; + whitetg = 27; + greentg = 12; + bluetg = 10; + purpletg = 1; + orangetg = 0; + yellowtg = 0; + greyi = 0; + whitei = 10; + greeni = 30; + bluei = 8; + purplei = 2; + orangei = 0; + yellowi = 0; + } + percentGreyTradeGoods = greytg; + percentWhiteTradeGoods = whitetg; + percentGreenTradeGoods = greentg; + percentBlueTradeGoods = bluetg; + percentPurpleTradeGoods = purpletg; + percentOrangeTradeGoods = orangetg; + percentYellowTradeGoods = yellowtg; + percentGreyItems = greyi; + percentWhiteItems = whitei; + percentGreenItems = greeni; + percentBlueItems = bluei; + percentPurpleItems = purplei; + percentOrangeItems = orangei; + percentYellowItems = yellowi; + CalculatePercents(); + } + uint32 GetPercentages(uint32 color) + { + switch(color) + { + case AHB_GREY_TG: + return percentGreyTradeGoods; + break; + case AHB_WHITE_TG: + return percentWhiteTradeGoods; + break; + case AHB_GREEN_TG: + return percentGreenTradeGoods; + break; + case AHB_BLUE_TG: + return percentBlueTradeGoods; + break; + case AHB_PURPLE_TG: + return percentPurpleTradeGoods; + break; + case AHB_ORANGE_TG: + return percentOrangeTradeGoods; + break; + case AHB_YELLOW_TG: + return percentYellowTradeGoods; + break; + case AHB_GREY_I: + return percentGreyItems; + break; + case AHB_WHITE_I: + return percentWhiteItems; + break; + case AHB_GREEN_I: + return percentGreenItems; + break; + case AHB_BLUE_I: + return percentBlueItems; + break; + case AHB_PURPLE_I: + return percentPurpleItems; + break; + case AHB_ORANGE_I: + return percentOrangeItems; + break; + case AHB_YELLOW_I: + return percentYellowItems; + break; + default: + return 0; + break; + } + } + void SetMinPrice(uint32 color, uint32 value) + { + switch(color) + { + case AHB_GREY: + minPriceGrey = value; + break; + case AHB_WHITE: + minPriceWhite = value; + break; + case AHB_GREEN: + minPriceGreen = value; + break; + case AHB_BLUE: + minPriceBlue = value; + break; + case AHB_PURPLE: + minPricePurple = value; + break; + case AHB_ORANGE: + minPriceOrange = value; + break; + case AHB_YELLOW: + minPriceYellow = value; + break; + default: + break; + } + } + uint32 GetMinPrice(uint32 color) + { + switch(color) + { + case AHB_GREY: + { + if (minPriceGrey == 0) + return 100; + else if (minPriceGrey > maxPriceGrey) + return maxPriceGrey; + else + return minPriceGrey; + break; + } + case AHB_WHITE: + { + if (minPriceWhite == 0) + return 150; + else if (minPriceWhite > maxPriceWhite) + return maxPriceWhite; + else + return minPriceWhite; + break; + } + case AHB_GREEN: + { + if (minPriceGreen == 0) + return 200; + else if (minPriceGreen > maxPriceGreen) + return maxPriceGreen; + else + return minPriceGreen; + break; + } + case AHB_BLUE: + { + if (minPriceBlue == 0) + return 250; + else if (minPriceBlue > maxPriceBlue) + return maxPriceBlue; + else + return minPriceBlue; + break; + } + case AHB_PURPLE: + { + if (minPricePurple == 0) + return 300; + else if (minPricePurple > maxPricePurple) + return maxPricePurple; + else + return minPricePurple; + break; + } + case AHB_ORANGE: + { + if (minPriceOrange == 0) + return 400; + else if (minPriceOrange > maxPriceOrange) + return maxPriceOrange; + else + return minPriceOrange; + break; + } + case AHB_YELLOW: + { + if (minPriceYellow == 0) + return 500; + else if (minPriceYellow > maxPriceYellow) + return maxPriceYellow; + else + return minPriceYellow; + break; + } + default: + { + return 0; + break; + } + } + } + void SetMaxPrice(uint32 color, uint32 value) + { + switch(color) + { + case AHB_GREY: + maxPriceGrey = value; + break; + case AHB_WHITE: + maxPriceWhite = value; + break; + case AHB_GREEN: + maxPriceGreen = value; + break; + case AHB_BLUE: + maxPriceBlue = value; + break; + case AHB_PURPLE: + maxPricePurple = value; + break; + case AHB_ORANGE: + maxPriceOrange = value; + break; + case AHB_YELLOW: + maxPriceYellow = value; + break; + default: + break; + } + } + uint32 GetMaxPrice(uint32 color) + { + switch(color) + { + case AHB_GREY: + { + if (maxPriceGrey == 0) + return 150; + else + return maxPriceGrey; + break; + } + case AHB_WHITE: + { + if (maxPriceWhite == 0) + return 250; + else + return maxPriceWhite; + break; + } + case AHB_GREEN: + { + if (maxPriceGreen == 0) + return 300; + else + return maxPriceGreen; + break; + } + case AHB_BLUE: + { + if (maxPriceBlue == 0) + return 350; + else + return maxPriceBlue; + break; + } + case AHB_PURPLE: + { + if (maxPricePurple == 0) + return 450; + else + return maxPricePurple; + break; + } + case AHB_ORANGE: + { + if (maxPriceOrange == 0) + return 550; + else + return maxPriceOrange; + break; + } + case AHB_YELLOW: + { + if (maxPriceYellow == 0) + return 650; + else + return maxPriceYellow; + break; + } + default: + { + return 0; + break; + } + } + } + void SetMinBidPrice(uint32 color, uint32 value) + { + switch(color) + { + case AHB_GREY: + minBidPriceGrey = value; + break; + case AHB_WHITE: + minBidPriceWhite = value; + break; + case AHB_GREEN: + minBidPriceGreen = value; + break; + case AHB_BLUE: + minBidPriceBlue = value; + break; + case AHB_PURPLE: + minBidPricePurple = value; + break; + case AHB_ORANGE: + minBidPriceOrange = value; + break; + case AHB_YELLOW: + minBidPriceYellow = value; + break; + default: + break; + } + } + uint32 GetMinBidPrice(uint32 color) + { + switch(color) + { + case AHB_GREY: + { + if (minBidPriceGrey > 100) + return 100; + else + return minBidPriceGrey; + break; + } + case AHB_WHITE: + { + if (minBidPriceWhite > 100) + return 100; + else + return minBidPriceWhite; + break; + } + case AHB_GREEN: + { + if (minBidPriceGreen > 100) + return 100; + else + return minBidPriceGreen; + break; + } + case AHB_BLUE: + { + if (minBidPriceBlue > 100) + return 100; + else + return minBidPriceBlue; + break; + } + case AHB_PURPLE: + { + if (minBidPricePurple > 100) + return 100; + else + return minBidPricePurple; + break; + } + case AHB_ORANGE: + { + if (minBidPriceOrange > 100) + return 100; + else + return minBidPriceOrange; + break; + } + case AHB_YELLOW: + { + if (minBidPriceYellow > 100) + return 100; + else + return minBidPriceYellow; + break; + } + default: + { + return 0; + break; + } + } + } + void SetMaxBidPrice(uint32 color, uint32 value) + { + switch(color) + { + case AHB_GREY: + maxBidPriceGrey = value; + break; + case AHB_WHITE: + maxBidPriceWhite = value; + break; + case AHB_GREEN: + maxBidPriceGreen = value; + break; + case AHB_BLUE: + maxBidPriceBlue = value; + break; + case AHB_PURPLE: + maxBidPricePurple = value; + break; + case AHB_ORANGE: + maxBidPriceOrange = value; + break; + case AHB_YELLOW: + maxBidPriceYellow = value; + break; + default: + break; + } + } + uint32 GetMaxBidPrice(uint32 color) + { + switch(color) + { + case AHB_GREY: + { + if (maxBidPriceGrey > 100) + return 100; + else + return maxBidPriceGrey; + break; + } + case AHB_WHITE: + { + if (maxBidPriceWhite > 100) + return 100; + else + return maxBidPriceWhite; + break; + } + case AHB_GREEN: + { + if (maxBidPriceGreen > 100) + return 100; + else + return maxBidPriceGreen; + break; + } + case AHB_BLUE: + { + if (maxBidPriceBlue > 100) + return 100; + else + return maxBidPriceBlue; + break; + } + case AHB_PURPLE: + { + if (maxBidPricePurple > 100) + return 100; + else + return maxBidPricePurple; + break; + } + case AHB_ORANGE: + { + if (maxBidPriceOrange > 100) + return 100; + else + return maxBidPriceOrange; + break; + } + case AHB_YELLOW: + { + if (maxBidPriceYellow > 100) + return 100; + else + return maxBidPriceYellow; + break; + } + default: + { + return 0; + break; + } + } + } + void SetMaxStack(uint32 color, uint32 value) + { + switch(color) + { + case AHB_GREY: + maxStackGrey = value; + break; + case AHB_WHITE: + maxStackWhite = value; + break; + case AHB_GREEN: + maxStackGreen = value; + break; + case AHB_BLUE: + maxStackBlue = value; + break; + case AHB_PURPLE: + maxStackPurple = value; + break; + case AHB_ORANGE: + maxStackOrange = value; + break; + case AHB_YELLOW: + maxStackYellow = value; + break; + default: + break; + } + } + uint32 GetMaxStack(uint32 color) + { + switch(color) + { + case AHB_GREY: + { + return maxStackGrey; + break; + } + case AHB_WHITE: + { + return maxStackWhite; + break; + } + case AHB_GREEN: + { + return maxStackGreen; + break; + } + case AHB_BLUE: + { + return maxStackBlue; + break; + } + case AHB_PURPLE: + { + return maxStackPurple; + break; + } + case AHB_ORANGE: + { + return maxStackOrange; + break; + } + case AHB_YELLOW: + { + return maxStackYellow; + break; + } + default: + { + return 0; + break; + } + } + } + void SetBuyerPrice(uint32 color, uint32 value) + { + switch(color) + { + case AHB_GREY: + buyerPriceGrey = value; + break; + case AHB_WHITE: + buyerPriceWhite = value; + break; + case AHB_GREEN: + buyerPriceGreen = value; + break; + case AHB_BLUE: + buyerPriceBlue = value; + break; + case AHB_PURPLE: + buyerPricePurple = value; + break; + case AHB_ORANGE: + buyerPriceOrange = value; + break; + case AHB_YELLOW: + buyerPriceYellow = value; + break; + default: + break; + } + } + uint32 GetBuyerPrice(uint32 color) + { + switch(color) + { + case AHB_GREY: + return buyerPriceGrey; + break; + case AHB_WHITE: + return buyerPriceWhite; + break; + case AHB_GREEN: + return buyerPriceGreen; + break; + case AHB_BLUE: + return buyerPriceBlue; + break; + case AHB_PURPLE: + return buyerPricePurple; + break; + case AHB_ORANGE: + return buyerPriceOrange; + break; + case AHB_YELLOW: + return buyerPriceYellow; + break; + default: + return 0; + break; + } + } + void SetBiddingInterval(uint32 value) + { + buyerBiddingInterval = value; + } + uint32 GetBiddingInterval() + { + return buyerBiddingInterval; + } + void CalculatePercents() + { + greytgp = (uint32) (((double)percentGreyTradeGoods / 100.0) * maxItems); + whitetgp = (uint32) (((double)percentWhiteTradeGoods / 100.0) * maxItems); + greentgp = (uint32) (((double)percentGreenTradeGoods / 100.0) * maxItems); + bluetgp = (uint32) (((double)percentBlueTradeGoods / 100.0) * maxItems); + purpletgp = (uint32) (((double)percentPurpleTradeGoods / 100.0) * maxItems); + orangetgp = (uint32) (((double)percentOrangeTradeGoods / 100.0) * maxItems); + yellowtgp = (uint32) (((double)percentYellowTradeGoods / 100.0) * maxItems); + greyip = (uint32) (((double)percentGreyItems / 100.0) * maxItems); + whiteip = (uint32) (((double)percentWhiteItems / 100.0) * maxItems); + greenip = (uint32) (((double)percentGreenItems / 100.0) * maxItems); + blueip = (uint32) (((double)percentBlueItems / 100.0) * maxItems); + purpleip = (uint32) (((double)percentPurpleItems / 100.0) * maxItems); + orangeip = (uint32) (((double)percentOrangeItems / 100.0) * maxItems); + yellowip = (uint32) (((double)percentYellowItems / 100.0) * maxItems); + uint32 total = greytgp + whitetgp + greentgp + bluetgp + purpletgp + orangetgp + yellowtgp + greyip + whiteip + greenip + blueip + purpleip + orangeip + yellowip; + int32 diff = (maxItems - total); + if (diff < 0) + { + if ((whiteip - diff) > 0) + whiteip -= diff; + else if ((greenip - diff) > 0) + greenip -= diff; + } + else if (diff < 0) + { + whiteip += diff; + } + } + uint32 GetPercents(uint32 color) + { + switch(color) + { + case AHB_GREY_TG: + return greytgp; + break; + case AHB_WHITE_TG: + return whitetgp; + break; + case AHB_GREEN_TG: + return greentgp; + break; + case AHB_BLUE_TG: + return bluetgp; + break; + case AHB_PURPLE_TG: + return purpletgp; + break; + case AHB_ORANGE_TG: + return orangetgp; + break; + case AHB_YELLOW_TG: + return yellowtgp; + break; + case AHB_GREY_I: + return greyip; + break; + case AHB_WHITE_I: + return whiteip; + break; + case AHB_GREEN_I: + return greenip; + break; + case AHB_BLUE_I: + return blueip; + break; + case AHB_PURPLE_I: + return purpleip; + break; + case AHB_ORANGE_I: + return orangeip; + break; + case AHB_YELLOW_I: + return yellowip; + break; + default: + return 0; + break; + } + } + + void DecItemCounts(uint32 Class, uint32 Quality) + { + switch(Class) + { + case ITEM_CLASS_TRADE_GOODS: + DecItemCounts(Quality); + break; + default: + DecItemCounts(Quality + 7); + break; + } + } + + void DecItemCounts(uint32 color) + { + switch(color) + { + case AHB_GREY_TG: + --greyTGoods; + break; + case AHB_WHITE_TG: + --whiteTGoods; + break; + case AHB_GREEN_TG: + --greenTGoods; + break; + case AHB_BLUE_TG: + --blueTGoods; + break; + case AHB_PURPLE_TG: + --purpleTGoods; + break; + case AHB_ORANGE_TG: + --orangeTGoods; + break; + case AHB_YELLOW_TG: + --yellowTGoods; + break; + case AHB_GREY_I: + --greyItems; + break; + case AHB_WHITE_I: + --whiteItems; + break; + case AHB_GREEN_I: + --greenItems; + break; + case AHB_BLUE_I: + --blueItems; + break; + case AHB_PURPLE_I: + --purpleItems; + break; + case AHB_ORANGE_I: + --orangeItems; + break; + case AHB_YELLOW_I: + --yellowItems; + break; + default: + break; + } + } + + void IncItemCounts(uint32 Class, uint32 Quality) + { + switch(Class) + { + case ITEM_CLASS_TRADE_GOODS: + IncItemCounts(Quality); + break; + default: + IncItemCounts(Quality + 7); + break; + } + } + + void IncItemCounts(uint32 color) + { + switch(color) + { + case AHB_GREY_TG: + ++greyTGoods; + break; + case AHB_WHITE_TG: + ++whiteTGoods; + break; + case AHB_GREEN_TG: + ++greenTGoods; + break; + case AHB_BLUE_TG: + ++blueTGoods; + break; + case AHB_PURPLE_TG: + ++purpleTGoods; + break; + case AHB_ORANGE_TG: + ++orangeTGoods; + break; + case AHB_YELLOW_TG: + ++yellowTGoods; + break; + case AHB_GREY_I: + ++greyItems; + break; + case AHB_WHITE_I: + ++whiteItems; + break; + case AHB_GREEN_I: + ++greenItems; + break; + case AHB_BLUE_I: + ++blueItems; + break; + case AHB_PURPLE_I: + ++purpleItems; + break; + case AHB_ORANGE_I: + ++orangeItems; + break; + case AHB_YELLOW_I: + ++yellowItems; + break; + default: + break; + } + } + + void ResetItemCounts() + { + greyTGoods = 0; + whiteTGoods = 0; + greenTGoods = 0; + blueTGoods = 0; + purpleTGoods = 0; + orangeTGoods = 0; + yellowTGoods = 0; + + greyItems = 0; + whiteItems = 0; + greenItems = 0; + blueItems = 0; + purpleItems = 0; + orangeItems = 0; + yellowItems = 0; + } + + uint32 TotalItemCounts() + { + return( + greyTGoods + + whiteTGoods + + greenTGoods + + blueTGoods + + purpleTGoods + + orangeTGoods + + yellowTGoods + + + greyItems + + whiteItems + + greenItems + + blueItems + + purpleItems + + orangeItems + + yellowItems); + } + + uint32 GetItemCounts(uint32 color) + { + switch(color) + { + case AHB_GREY_TG: + return greyTGoods; + break; + case AHB_WHITE_TG: + return whiteTGoods; + break; + case AHB_GREEN_TG: + return greenTGoods; + break; + case AHB_BLUE_TG: + return blueTGoods; + break; + case AHB_PURPLE_TG: + return purpleTGoods; + break; + case AHB_ORANGE_TG: + return orangeTGoods; + break; + case AHB_YELLOW_TG: + return yellowTGoods; + break; + case AHB_GREY_I: + return greyItems; + break; + case AHB_WHITE_I: + return whiteItems; + break; + case AHB_GREEN_I: + return greenItems; + break; + case AHB_BLUE_I: + return blueItems; + break; + case AHB_PURPLE_I: + return purpleItems; + break; + case AHB_ORANGE_I: + return orangeItems; + break; + case AHB_YELLOW_I: + return yellowItems; + break; + default: + return 0; + break; + } + } + void SetBidsPerInterval(uint32 value) + { + buyerBidsPerInterval = value; + } + uint32 GetBidsPerInterval() + { + return buyerBidsPerInterval; + } + ~AHBConfig() + { + } +}; +class AuctionHouseBot +{ +private: + + bool debug_Out; + bool debug_Out_Filters; + + bool AHBSeller; + bool AHBBuyer; + bool BuyMethod; + bool SellMethod; + + uint32 AHBplayerAccount; + uint32 AHBplayerGUID; + uint32 ItemsPerCycle; + + //Begin Filters + + bool Vendor_Items; + bool Loot_Items; + bool Other_Items; + bool Vendor_TGs; + bool Loot_TGs; + bool Other_TGs; + + bool No_Bind; + bool Bind_When_Picked_Up; + bool Bind_When_Equipped; + bool Bind_When_Use; + bool Bind_Quest_Item; + + bool DisableBeta_PTR_Unused; + bool DisablePermEnchant; + bool DisableConjured; + bool DisableGems; + bool DisableMoney; + bool DisableMoneyLoot; + bool DisableLootable; + bool DisableKeys; + bool DisableDuration; + bool DisableBOP_Or_Quest_NoReqLevel; + + bool DisableWarriorItems; + bool DisablePaladinItems; + bool DisableHunterItems; + bool DisableRogueItems; + bool DisablePriestItems; + bool DisableDKItems; + bool DisableShamanItems; + bool DisableMageItems; + bool DisableWarlockItems; + bool DisableUnusedClassItems; + bool DisableDruidItems; + + uint32 DisableItemsBelowLevel; + uint32 DisableItemsAboveLevel; + uint32 DisableTGsBelowLevel; + uint32 DisableTGsAboveLevel; + uint32 DisableItemsBelowGUID; + uint32 DisableItemsAboveGUID; + uint32 DisableTGsBelowGUID; + uint32 DisableTGsAboveGUID; + uint32 DisableItemsBelowReqLevel; + uint32 DisableItemsAboveReqLevel; + uint32 DisableTGsBelowReqLevel; + uint32 DisableTGsAboveReqLevel; + uint32 DisableItemsBelowReqSkillRank; + uint32 DisableItemsAboveReqSkillRank; + uint32 DisableTGsBelowReqSkillRank; + uint32 DisableTGsAboveReqSkillRank; + + //End Filters + + AHBConfig AllianceConfig; + AHBConfig HordeConfig; + AHBConfig NeutralConfig; + + time_t _lastrun_a; + time_t _lastrun_h; + time_t _lastrun_n; + + inline uint32 minValue(uint32 a, uint32 b) { return a <= b ? a : b; }; + void addNewAuctions(Player *AHBplayer, AHBConfig *config); + void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session); + +public: + AuctionHouseBot(); + ~AuctionHouseBot(); + void Update(); + void Initialize(); + void LoadValues(AHBConfig*); + void DecrementItemCounts(AuctionEntry* ah, uint32 item_template); + void IncrementItemCounts(AuctionEntry* ah); + void Commands(uint32, uint32, uint32, char*); + uint32 GetAHBplayerGUID() { return AHBplayerGUID; }; +}; + +#define auctionbot Trinity::Singleton::Instance() + +#endif diff --git a/src/server/game/AuctionHouse/AuctionHouseHandler.cpp b/src/server/game/AuctionHouse/AuctionHouseHandler.cpp deleted file mode 100644 index 8fec3b7df1d..00000000000 --- a/src/server/game/AuctionHouse/AuctionHouseHandler.cpp +++ /dev/null @@ -1,664 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ObjectMgr.h" -#include "Player.h" -#include "World.h" -#include "WorldPacket.h" -#include "WorldSession.h" - -#include "AuctionHouseBot.h" -#include "AuctionHouseMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "UpdateMask.h" -#include "Util.h" - -//please DO NOT use iterator++, because it is slower than ++iterator!!! -//post-incrementation is always slower than pre-incrementation ! - -//void called when player click on auctioneer npc -void WorldSession::HandleAuctionHelloOpcode(WorldPacket & recv_data) -{ - uint64 guid; //NPC guid - recv_data >> guid; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); - if (!unit) - { - sLog.outDebug("WORLD: HandleAuctionHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendAuctionHello(guid, unit); -} - -//this void causes that auction window is opened -void WorldSession::SendAuctionHello(uint64 guid, Creature* unit) -{ - if (GetPlayer()->getLevel() < sWorld.getConfig(CONFIG_AUCTION_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_AUCTION_REQ), sWorld.getConfig(CONFIG_AUCTION_LEVEL_REQ)); - return; - } - - AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->getFaction()); - if (!ahEntry) - return; - - WorldPacket data(MSG_AUCTION_HELLO, 12); - data << uint64(guid); - data << uint32(ahEntry->houseId); - data << uint8(1); // 3.3.3: 1 - AH enabled, 0 - AH disabled - SendPacket(&data); -} - -//call this method when player bids, creates, or deletes auction -void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError) -{ - WorldPacket data(SMSG_AUCTION_COMMAND_RESULT, 16); - data << auctionId; - data << Action; - data << ErrorCode; - if (!ErrorCode && Action) - data << bidError; //when bid, then send 0, once... - SendPacket(&data); -} - -//this function sends notification, if bidder is online -void WorldSession::SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template) -{ - WorldPacket data(SMSG_AUCTION_BIDDER_NOTIFICATION, (8*4)); - data << uint32(location); - data << uint32(auctionId); - data << uint64(bidder); - data << uint32(bidSum); - data << uint32(diff); - data << uint32(item_template); - data << uint32(0); - SendPacket(&data); -} - -//this void causes on client to display: "Your auction sold" -void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction) -{ - WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, (7*4)); - data << auction->Id; - data << auction->bid; - data << (uint32) 0; //unk - data << (uint32) 0; //unk - data << (uint32) 0; //unk - data << auction->item_template; - data << (uint32) 0; //unk - SendPacket(&data); -} - -//this function sends mail to old bidder -void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPrice) -{ - uint64 oldBidder_guid = MAKE_NEW_GUID(auction->bidder,0, HIGHGUID_PLAYER); - Player *oldBidder = objmgr.GetPlayer(oldBidder_guid); - - uint32 oldBidder_accId = 0; - if (!oldBidder) - oldBidder_accId = objmgr.GetPlayerAccountIdByGUID(oldBidder_guid); - - // old bidder exist - if (oldBidder || oldBidder_accId) - { - std::ostringstream msgAuctionOutbiddedSubject; - msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED << ":0:0"; - - if (oldBidder && !_player) - oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, auctionbot.GetAHBplayerGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); - - if (oldBidder && _player) - oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, _player->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); - - MailDraft(msgAuctionOutbiddedSubject.str(), "") // TODO: fix body - .AddMoney(auction->bid) - .SendMailTo(MailReceiver(oldBidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED); - } -} - -//this function sends mail, when auction is cancelled to old bidder -void WorldSession::SendAuctionCancelledToBidderMail(AuctionEntry* auction) -{ - uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER); - Player *bidder = objmgr.GetPlayer(bidder_guid); - - uint32 bidder_accId = 0; - if (!bidder) - bidder_accId = objmgr.GetPlayerAccountIdByGUID(bidder_guid); - - // bidder exist - if (bidder || bidder_accId) - { - std::ostringstream msgAuctionCancelledSubject; - msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER << ":0:0"; - - MailDraft(msgAuctionCancelledSubject.str(), "") // TODO: fix body - .AddMoney(auction->bid) - .SendMailTo(MailReceiver(bidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED); - } -} - -//this void creates new auction and adds auction to some auctionhouse -void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) -{ - uint64 auctioneer, item; - uint32 etime, bid, buyout; - recv_data >> auctioneer; - recv_data.read_skip(); // const 1? - recv_data >> item; - recv_data.read_skip(); // unk 3.2.2, const 1? - recv_data >> bid; - recv_data >> buyout; - recv_data >> etime; - - Player *pl = GetPlayer(); - - if (!item || !bid || !etime) - return; //check for cheaters - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); - return; - } - - AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(pCreature->getFaction()); - if (!auctionHouseEntry) - { - sLog.outDebug("WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", uint32(GUID_LOPART(auctioneer))); - return; - } - - sLog.outDebug("WORLD: HandleAuctionSellItem - ETIME: %u", etime); - - // client send time in minutes, convert to common used sec time - etime *= MINUTE; - - sLog.outDebug("WORLD: HandleAuctionSellItem - ETIME: %u", etime); - - // client understand only 3 auction time - switch(etime) - { - case 1*MIN_AUCTION_TIME: - case 2*MIN_AUCTION_TIME: - case 4*MIN_AUCTION_TIME: - break; - default: - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Item *it = pl->GetItemByGuid(item); - //do not allow to sell already auctioned items - if (auctionmgr.GetAItem(GUID_LOPART(item))) - { - sLog.outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", pl->GetName(), GUID_LOPART(item)); - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) - if (!it) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); - return; - } - - if (!it->CanBeTraded()) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - - if (it->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION)) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); - return; - } - - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); - - //we have to take deposit : - uint32 deposit = auctionmgr.GetAuctionDeposit(auctionHouseEntry, etime, it); - if (pl->GetMoney() < deposit) - { - SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); - return; - } - - if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) - { - sLog.outCommand(GetAccountId(),"GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", - GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount()); - } - - pl->ModifyMoney(-int32(deposit)); - - uint32 auction_time = uint32(etime * sWorld.getRate(RATE_AUCTION_TIME)); - - AuctionEntry *AH = new AuctionEntry; - AH->Id = objmgr.GenerateAuctionID(); - if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) - AH->auctioneer = 23442; - else - AH->auctioneer = GUID_LOPART(auctioneer); - AH->item_guidlow = GUID_LOPART(item); - AH->item_template = it->GetEntry(); - AH->owner = pl->GetGUIDLow(); - AH->startbid = bid; - AH->bidder = 0; - AH->bid = 0; - AH->buyout = buyout; - AH->expire_time = time(NULL) + auction_time; - AH->deposit = deposit; - AH->auctionHouseEntry = auctionHouseEntry; - - sLog.outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), AH->auctioneer, bid, buyout, auction_time, AH->GetHouseId()); - auctionmgr.AddAItem(it); - auctionHouse->AddAuction(AH); - - pl->MoveItemFromInventory(it->GetBagSlot(), it->GetSlot(), true); - - CharacterDatabase.BeginTransaction(); - it->DeleteFromInventoryDB(); - it->SaveToDB(); // recursive and not have transaction guard into self, not in inventiory and can be save standalone - AH->SaveToDB(); - pl->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); - - SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); - - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); -} - -//this function is called when client bids or buys out auction -void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) -{ - uint64 auctioneer; - uint32 auctionId; - uint32 price; - recv_data >> auctioneer; - recv_data >> auctionId >> price; - - if (!auctionId || !price) - return; //check for cheaters - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject *auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); - - AuctionEntry *auction = auctionHouse->GetAuction(auctionId); - Player *pl = GetPlayer(); - - if (!auction || auction->owner == pl->GetGUIDLow()) - { - //you cannot bid your own auction: - SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); - return; - } - - // impossible have online own another character (use this for speedup check in case online owner) - Player* auction_owner = objmgr.GetPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); - if (!auction_owner && objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == pl->GetSession()->GetAccountId()) - { - //you cannot bid your another character auction: - SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); - return; - } - - // cheating - if (price <= auction->bid || price < auction->startbid) - return; - - // price too low for next bid if not buyout - if ((price < auction->buyout || auction->buyout == 0) && - price < auction->bid + auction->GetAuctionOutBid()) - { - //auction has already higher bid, client tests it! - return; - } - - if (price > pl->GetMoney()) - { - //you don't have enought money!, client tests! - //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); - return; - } - - if (price < auction->buyout || auction->buyout == 0) - { - if (auction->bidder > 0) - { - if (auction->bidder == pl->GetGUIDLow()) - pl->ModifyMoney(-int32(price - auction->bid)); - else - { - // mail to last bidder and return money - SendAuctionOutbiddedMail(auction, price); - pl->ModifyMoney(-int32(price)); - } - } - else - pl->ModifyMoney(-int32(price)); - - auction->bidder = pl->GetGUIDLow(); - auction->bid = price; - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); - - // after this update we should save player's money ... - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); - - SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK, 0); - } - else - { - //buyout: - if (pl->GetGUIDLow() == auction->bidder) - pl->ModifyMoney(-int32(auction->buyout - auction->bid)); - else - { - pl->ModifyMoney(-int32(auction->buyout)); - if (auction->bidder) //buyout for bidded auction .. - SendAuctionOutbiddedMail(auction, auction->buyout); - } - auction->bidder = pl->GetGUIDLow(); - auction->bid = auction->buyout; - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); - - auctionmgr.SendAuctionSalePendingMail(auction); - auctionmgr.SendAuctionSuccessfulMail(auction); - auctionmgr.SendAuctionWonMail(auction); - - SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); - - CharacterDatabase.BeginTransaction(); - auction->DeleteFromDB(); - uint32 item_template = auction->item_template; - auctionmgr.RemoveAItem(auction->item_guidlow); - auctionHouse->RemoveAuction(auction, item_template); - } - pl->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); -} - -//this void is called when auction_owner cancels his auction -void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) -{ - uint64 auctioneer; - uint32 auctionId; - recv_data >> auctioneer; - recv_data >> auctionId; - //sLog.outDebug("Cancel AUCTION AuctionID: %u", auctionId); - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); - - AuctionEntry *auction = auctionHouse->GetAuction(auctionId); - Player *pl = GetPlayer(); - - if (auction && auction->owner == pl->GetGUIDLow()) - { - Item *pItem = auctionmgr.GetAItem(auction->item_guidlow); - if (pItem) - { - if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid - { - uint32 auctionCut = auction->GetAuctionCut(); - if (pl->GetMoney() < auctionCut) //player doesn't have enough money, maybe message needed - return; - //some auctionBidderNotification would be needed, but don't know that parts.. - SendAuctionCancelledToBidderMail(auction); - pl->ModifyMoney(-int32(auctionCut)); - } - // Return the item by mail - std::ostringstream msgAuctionCanceledOwner; - msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED << ":0:0"; - - // item will deleted or added to received mail list - MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body - .AddItem(pItem) - .SendMailTo(pl, auction, MAIL_CHECK_MASK_COPIED); - } - else - { - sLog.outError("Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->item_guidlow); - SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); - return; - } - } - else - { - SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); - //this code isn't possible ... maybe there should be assert - sLog.outError("CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", pl->GetGUIDLow(), auctionId); - return; - } - - //inform player, that auction is removed - SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, AUCTION_OK); - - // Now remove the auction - CharacterDatabase.BeginTransaction(); - pl->SaveInventoryAndGoldToDB(); - auction->DeleteFromDB(); - uint32 item_template = auction->item_template; - auctionmgr.RemoveAItem(auction->item_guidlow); - auctionHouse->RemoveAuction(auction, item_template); - CharacterDatabase.CommitTransaction(); -} - -//called when player lists his bids -void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data) -{ - uint64 guid; //NPC guid - uint32 listfrom; //page of auctions - uint32 outbiddedCount; //count of outbidded auctions - - recv_data >> guid; - recv_data >> listfrom; // not used in fact (this list not have page control in client) - recv_data >> outbiddedCount; - if (recv_data.size() != (16 + outbiddedCount * 4)) - { - sLog.outError("Client sent bad opcode!!! with count: %u and size : %lu (must be: %u)", outbiddedCount, (unsigned long)recv_data.size(),(16 + outbiddedCount * 4)); - outbiddedCount = 0; - } - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); - - WorldPacket data(SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4)); - Player *pl = GetPlayer(); - data << (uint32) 0; //add 0 as count - uint32 count = 0; - uint32 totalcount = 0; - while (outbiddedCount > 0) //add all data, which client requires - { - --outbiddedCount; - uint32 outbiddedAuctionId; - recv_data >> outbiddedAuctionId; - AuctionEntry * auction = auctionHouse->GetAuction(outbiddedAuctionId); - if (auction && auction->BuildAuctionInfo(data)) - { - ++totalcount; - ++count; - } - } - - auctionHouse->BuildListBidderItems(data,pl,count,totalcount); - data.put(0, count); // add count to placeholder - data << totalcount; - data << (uint32)300; //unk 2.3.0 - SendPacket(&data); -} - -//this void sends player info about his auctions -void WorldSession::HandleAuctionListOwnerItems(WorldPacket & recv_data) -{ - uint32 listfrom; - uint64 guid; - - recv_data >> guid; - recv_data >> listfrom; // not used in fact (this list not have page control in client) - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleAuctionListOwnerItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); - - WorldPacket data(SMSG_AUCTION_OWNER_LIST_RESULT, (4+4+4)); - data << (uint32) 0; // amount place holder - - uint32 count = 0; - uint32 totalcount = 0; - - auctionHouse->BuildListOwnerItems(data,_player,count,totalcount); - data.put(0, count); - data << (uint32) totalcount; - data << (uint32) 0; - SendPacket(&data); -} - -//this void is called when player clicks on search button -void WorldSession::HandleAuctionListItems(WorldPacket & recv_data) -{ - std::string searchedname; - uint8 levelmin, levelmax, usable; - uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality; - uint64 guid; - - recv_data >> guid; - recv_data >> listfrom; // start, used for page control listing by 50 elements - recv_data >> searchedname; - - recv_data >> levelmin >> levelmax; - recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; - recv_data >> quality >> usable; - - recv_data.read_skip(16); // unknown 16 bytes: 00 07 01 00 00 01 05 00 06 00 09 01 08 00 03 00 - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleAuctionListItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); - - //sLog.outDebug("Auctionhouse search (GUID: %u TypeId: %u)", , list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u", - // GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid)), listfrom, searchedname.c_str(), levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable); - - WorldPacket data(SMSG_AUCTION_LIST_RESULT, (4+4+4)); - uint32 count = 0; - uint32 totalcount = 0; - data << (uint32) 0; - - // converting string that we try to find to lower case - std::wstring wsearchedname; - if (!Utf8toWStr(searchedname,wsearchedname)) - return; - - wstrToLower(wsearchedname); - - auctionHouse->BuildListAuctionItems(data,_player, - wsearchedname, listfrom, levelmin, levelmax, usable, - auctionSlotID, auctionMainCategory, auctionSubCategory, quality, - count,totalcount); - - data.put(0, count); - data << (uint32) totalcount; - data << (uint32) 300; // unk 2.3.0 const? - SendPacket(&data); -} - -void WorldSession::HandleAuctionListPendingSales(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES"); - - recv_data.read_skip(); - - uint32 count = 0; - - WorldPacket data(SMSG_AUCTION_LIST_PENDING_SALES, 4); - data << uint32(count); // count - /*for (uint32 i = 0; i < count; ++i) - { - data << ""; // string - data << ""; // string - data << uint32(0); - data << uint32(0); - data << float(0); - }*/ - SendPacket(&data); -} diff --git a/src/server/game/BattleGrounds/ArenaTeamHandler.cpp b/src/server/game/BattleGrounds/ArenaTeamHandler.cpp deleted file mode 100644 index 3a9a14524f9..00000000000 --- a/src/server/game/BattleGrounds/ArenaTeamHandler.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Player.h" -#include "World.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Database/DatabaseEnv.h" - -#include "ArenaTeam.h" -#include "Log.h" -#include "ObjectMgr.h" -#include "SocialMgr.h" - -void WorldSession::HandleInspectArenaTeamsOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("MSG_INSPECT_ARENA_TEAMS"); - - uint64 guid; - recv_data >> guid; - sLog.outDebug("Inspect Arena stats (GUID: %u TypeId: %u)", GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); - - if (Player *plr = objmgr.GetPlayer(guid)) - { - for (uint8 i = 0; i < MAX_ARENA_SLOT; ++i) - { - if (uint32 a_id = plr->GetArenaTeamId(i)) - { - if (ArenaTeam *at = objmgr.GetArenaTeamById(a_id)) - at->InspectStats(this, plr->GetGUID()); - } - } - } -} - -void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_ARENA_TEAM_QUERY"); - - uint32 ArenaTeamId; - recv_data >> ArenaTeamId; - - if (ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId)) - { - arenateam->Query(this); - arenateam->Stats(this); - } -} - -void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_ARENA_TEAM_ROSTER"); - - uint32 ArenaTeamId; // arena team id - recv_data >> ArenaTeamId; - - if (ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId)) - arenateam->Roster(this); -} - -void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_ARENA_TEAM_INVITE"); - - uint32 ArenaTeamId; // arena team id - std::string Invitedname; - - Player * player = NULL; - - recv_data >> ArenaTeamId >> Invitedname; - - if (!Invitedname.empty()) - { - if (!normalizePlayerName(Invitedname)) - return; - - player = ObjectAccessor::Instance().FindPlayerByName(Invitedname.c_str()); - } - - if (!player) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); - return; - } - - if (player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); - return; - } - - ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId); - if (!arenateam) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM); - return; - } - - // OK result but not send invite - if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) - return; - - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); - return; - } - - if (player->GetArenaTeamId(arenateam->GetSlot())) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); - return; - } - - if (player->GetArenaTeamIdInvited()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); - return; - } - - if (arenateam->GetMembersSize() >= arenateam->GetType() * 2) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, arenateam->GetName(), "", ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S); - return; - } - - sLog.outDebug("Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName(), Invitedname.c_str()); - - player->SetArenaTeamIdInvited(arenateam->GetId()); - - WorldPacket data(SMSG_ARENA_TEAM_INVITE, (8+10)); - data << GetPlayer()->GetName(); - data << arenateam->GetName(); - player->GetSession()->SendPacket(&data); - - sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_INVITE"); -} - -void WorldSession::HandleArenaTeamAcceptOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("CMSG_ARENA_TEAM_ACCEPT"); // empty opcode - - ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited()); - if (!at) - return; - - if (_player->GetArenaTeamId(at->GetSlot())) - { - // already in arena team that size - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ALREADY_IN_ARENA_TEAM); - return; - } - - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain())) - { - // not let enemies sign petition - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_NOT_ALLIED); - return; - } - - if (!at->AddMember(_player->GetGUID())) - { - // arena team not found - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_INTERNAL); - return; - } - - // event - at->BroadcastEvent(ERR_ARENA_TEAM_JOIN_SS, _player->GetGUID(), 2, _player->GetName(), at->GetName(), ""); -} - -void WorldSession::HandleArenaTeamDeclineOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("CMSG_ARENA_TEAM_DECLINE"); // empty opcode - - _player->SetArenaTeamIdInvited(0); // no more invited -} - -void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_ARENA_TEAM_LEAVE"); - - uint32 ArenaTeamId; // arena team id - recv_data >> ArenaTeamId; - - ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); - if (!at) - return; - - if (_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1) - { - // check for correctness - SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); - return; - } - - // arena team has only one member (=captain) - if (_player->GetGUID() == at->GetCaptain()) - { - at->Disband(this); - delete at; - return; - } - - at->DelMember(_player->GetGUID()); - - // event - at->BroadcastEvent(ERR_ARENA_TEAM_LEAVE_SS, _player->GetGUID(), 2, _player->GetName(), at->GetName(), ""); - - // send you are no longer member of team - SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0); -} - -void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_ARENA_TEAM_DISBAND"); - - uint32 ArenaTeamId; // arena team id - recv_data >> ArenaTeamId; - - if (ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId)) - { - if (at->GetCaptain() != _player->GetGUID()) - return; - - if (at->IsFighting()) - return; - - at->Disband(this); - delete at; - } -} - -void WorldSession::HandleArenaTeamRemoveOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_ARENA_TEAM_REMOVE"); - - uint32 ArenaTeamId; - std::string name; - - recv_data >> ArenaTeamId; - recv_data >> name; - - ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); - if (!at) // arena team not found - return; - - if (at->GetCaptain() != _player->GetGUID()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); - return; - } - - if (!normalizePlayerName(name)) - return; - - ArenaTeamMember* member = at->GetMember(name); - if (!member) // member not found - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); - return; - } - - if (at->GetCaptain() == member->guid) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); - return; - } - - at->DelMember(member->guid); - - // event - at->BroadcastEvent(ERR_ARENA_TEAM_REMOVE_SSS, 0, 3, name, at->GetName(), _player->GetName()); -} - -void WorldSession::HandleArenaTeamLeaderOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_ARENA_TEAM_LEADER"); - - uint32 ArenaTeamId; - std::string name; - - recv_data >> ArenaTeamId; - recv_data >> name; - - ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); - if (!at) // arena team not found - return; - - if (at->GetCaptain() != _player->GetGUID()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); - return; - } - - if (!normalizePlayerName(name)) - return; - - ArenaTeamMember* member = at->GetMember(name); - if (!member) // member not found - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); - return; - } - - if (at->GetCaptain() == member->guid) // target player already captain - return; - - at->SetCaptain(member->guid); - - // event - at->BroadcastEvent(ERR_ARENA_TEAM_LEADER_CHANGED_SSS, 0, 3, _player->GetName(), name, at->GetName()); -} - -void WorldSession::SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id) -{ - WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4); - data << uint32(team_action); - data << team; - data << player; - data << uint32(error_id); - SendPacket(&data); -} - -void WorldSession::SendNotInArenaTeamPacket(uint8 type) -{ - WorldPacket data(SMSG_ARENA_ERROR, 4+1); // 886 - You are not in a %uv%u arena team - uint32 unk = 0; - data << uint32(unk); // unk(0) - if (!unk) - data << uint8(type); // team type (2=2v2,3=3v3,5=5v5), can be used for custom types... - SendPacket(&data); -} - -/* -+ERR_ARENA_NO_TEAM_II "You are not in a %dv%d arena team" - -+ERR_ARENA_TEAM_CREATE_S "%s created. To disband, use /teamdisband [2v2, 3v3, 5v5]." -+ERR_ARENA_TEAM_INVITE_SS "You have invited %s to join %s" -+ERR_ARENA_TEAM_QUIT_S "You are no longer a member of %s" -ERR_ARENA_TEAM_FOUNDER_S "Congratulations, you are a founding member of %s! To leave, use /teamquit [2v2, 3v3, 5v5]." - -+ERR_ARENA_TEAM_INTERNAL "Internal arena team error" -+ERR_ALREADY_IN_ARENA_TEAM "You are already in an arena team of that size" -+ERR_ALREADY_IN_ARENA_TEAM_S "%s is already in an arena team of that size" -+ERR_INVITED_TO_ARENA_TEAM "You have already been invited into an arena team" -+ERR_ALREADY_INVITED_TO_ARENA_TEAM_S "%s has already been invited to an arena team" -+ERR_ARENA_TEAM_NAME_INVALID "That name contains invalid characters, please enter a new name" -+ERR_ARENA_TEAM_NAME_EXISTS_S "There is already an arena team named \"%s\"" -+ERR_ARENA_TEAM_LEADER_LEAVE_S "You must promote a new team captain using /teamcaptain before leaving the team" -+ERR_ARENA_TEAM_PERMISSIONS "You don't have permission to do that" -+ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM "You are not in an arena team of that size" -+ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS "%s is not in %s" -+ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S "\"%s\" not found" -+ERR_ARENA_TEAM_NOT_ALLIED "You cannot invite players from the opposing alliance" - -+ERR_ARENA_TEAM_JOIN_SS "%s has joined %s" -+ERR_ARENA_TEAM_YOU_JOIN_S "You have joined %s. To leave, use /teamquit [2v2, 3v3, 5v5]." - -+ERR_ARENA_TEAM_LEAVE_SS "%s has left %s" - -+ERR_ARENA_TEAM_LEADER_IS_SS "%s is the captain of %s" -+ERR_ARENA_TEAM_LEADER_CHANGED_SSS "%s has made %s the new captain of %s" - -+ERR_ARENA_TEAM_REMOVE_SSS "%s has been kicked out of %s by %s" - -+ERR_ARENA_TEAM_DISBANDED_S "%s has disbanded %s" - -ERR_ARENA_TEAM_TARGET_TOO_LOW_S "%s is not high enough level to join your team" - -ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S "%s is full" - -ERR_ARENA_TEAM_LEVEL_TOO_LOW_I "You must be level %d to form an arena team" -*/ diff --git a/src/server/game/BattleGrounds/BattleGroundAA.cpp b/src/server/game/BattleGrounds/BattleGroundAA.cpp deleted file mode 100644 index 56cf3ebed15..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundAA.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BattleGround.h" -#include "BattleGroundAA.h" -#include "Language.h" -#include "Player.h" - -BattleGroundAA::BattleGroundAA() -{ - - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; - //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; -} - -BattleGroundAA::~BattleGroundAA() -{ - -} - -void BattleGroundAA::Update(uint32 diff) -{ - BattleGround::Update(diff); -} - -void BattleGroundAA::StartingEventCloseDoors() -{ -} - -void BattleGroundAA::StartingEventOpenDoors() -{ -} - -void BattleGroundAA::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundAAScore* sc = new BattleGroundAAScore; - - m_PlayerScores[plr->GetGUID()] = sc; -} - -void BattleGroundAA::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) -{ -} - -void BattleGroundAA::HandleKillPlayer(Player* player, Player* killer) -{ - BattleGround::HandleKillPlayer(player, killer); -} - -void BattleGroundAA::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) -{ -} - -bool BattleGroundAA::SetupBattleGround() -{ - return true; -} - diff --git a/src/server/game/BattleGrounds/BattleGroundAA.h b/src/server/game/BattleGrounds/BattleGroundAA.h deleted file mode 100644 index a13833697cf..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundAA.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __BATTLEGROUNDAA_H -#define __BATTLEGROUNDAA_H - -class BattleGround; - -class BattleGroundAAScore : public BattleGroundScore -{ - public: - BattleGroundAAScore() {}; - virtual ~BattleGroundAAScore() {}; - //TODO fix me -}; - -class BattleGroundAA : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundAA(); - ~BattleGroundAA(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - void RemovePlayer(Player *plr, uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - bool SetupBattleGround(); - void HandleKillPlayer(Player* player, Player *killer); -}; -#endif - diff --git a/src/server/game/BattleGrounds/BattleGroundAB.cpp b/src/server/game/BattleGrounds/BattleGroundAB.cpp deleted file mode 100644 index 38671e85597..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundAB.cpp +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "World.h" -#include "WorldPacket.h" -#include "ObjectMgr.h" -#include "BattleGroundMgr.h" -#include "BattleGround.h" -#include "BattleGroundAB.h" -#include "Creature.h" -#include "Language.h" -#include "Object.h" -#include "Player.h" -#include "Util.h" - -// these variables aren't used outside of this file, so declare them only here -uint32 BG_AB_HonorScoreTicks[BG_HONOR_MODE_NUM] = { - 330, // normal honor - 200 // holiday -}; - -uint32 BG_AB_ReputationScoreTicks[BG_HONOR_MODE_NUM] = { - 200, // normal honor - 150 // holiday -}; - -BattleGroundAB::BattleGroundAB() -{ - m_BuffChange = true; - m_BgObjects.resize(BG_AB_OBJECT_MAX); - m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT + 5);//+5 for aura triggers - - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN; -} - -BattleGroundAB::~BattleGroundAB() -{ -} - -void BattleGroundAB::Update(uint32 diff) -{ - BattleGround::Update(diff); - - if (GetStatus() == STATUS_IN_PROGRESS) - { - int team_points[BG_TEAMS_COUNT] = { 0, 0 }; - - for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) - { - // 3 sec delay to spawn new banner instead previous despawned one - if (m_BannerTimers[node].timer) - { - if (m_BannerTimers[node].timer > diff) - m_BannerTimers[node].timer -= diff; - else - { - m_BannerTimers[node].timer = 0; - _CreateBanner(node, m_BannerTimers[node].type, m_BannerTimers[node].teamIndex, false); - } - } - - // 1-minute to occupy a node from contested state - if (m_NodeTimers[node]) - { - if (m_NodeTimers[node] > diff) - m_NodeTimers[node] -= diff; - else - { - m_NodeTimers[node] = 0; - // Change from contested to occupied ! - uint8 teamIndex = m_Nodes[node]-1; - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] += 2; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex); - // create new occupied banner - _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); - _SendNodeUpdate(node); - _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); - // Message to chatlog - - if (teamIndex == 0) - { - // FIXME: team and node names not localized - SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node)); - PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); - } - else - { - // FIXME: team and node names not localized - SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL,LANG_BG_AB_HORDE,_GetNodeNameId(node)); - PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); - } - } - } - - for (int team = 0; team < BG_TEAMS_COUNT; ++team) - if (m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED) - ++team_points[team]; - } - - // Accumulate points - for (int team = 0; team < BG_TEAMS_COUNT; ++team) - { - int points = team_points[team]; - if (!points) - continue; - m_lastTick[team] += diff; - if (m_lastTick[team] > BG_AB_TickIntervals[points]) - { - m_lastTick[team] -= BG_AB_TickIntervals[points]; - m_TeamScores[team] += BG_AB_TickPoints[points]; - m_HonorScoreTics[team] += BG_AB_TickPoints[points]; - m_ReputationScoreTics[team] += BG_AB_TickPoints[points]; - if (m_ReputationScoreTics[team] >= m_ReputationTics) - { - (team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE); - m_ReputationScoreTics[team] -= m_ReputationTics; - } - if (m_HonorScoreTics[team] >= m_HonorTics) - { - RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE); - m_HonorScoreTics[team] -= m_HonorTics; - } - if (!m_IsInformedNearVictory && m_TeamScores[team] > BG_AB_WARNING_NEAR_VICTORY_SCORE) - { - if (team == BG_TEAM_ALLIANCE) - SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); - else - SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); - PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY); - m_IsInformedNearVictory = true; - } - - if (m_TeamScores[team] > BG_AB_MAX_TEAM_SCORE) - m_TeamScores[team] = BG_AB_MAX_TEAM_SCORE; - if (team == BG_TEAM_ALLIANCE) - UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]); - if (team == BG_TEAM_HORDE) - UpdateWorldState(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[team]); - // update achievement flags - // we increased m_TeamScores[team] so we just need to check if it is 500 more than other teams resources - uint8 otherTeam = (team + 1) % BG_TEAMS_COUNT; - if (m_TeamScores[team] > m_TeamScores[otherTeam] + 500) - m_TeamScores500Disadvantage[otherTeam] = true; - } - } - - // Test win condition - if (m_TeamScores[BG_TEAM_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE) - EndBattleGround(ALLIANCE); - if (m_TeamScores[BG_TEAM_HORDE] >= BG_AB_MAX_TEAM_SCORE) - EndBattleGround(HORDE); - } -} - -void BattleGroundAB::StartingEventCloseDoors() -{ - // despawn banners, auras and buffs - for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj) - SpawnBGObject(obj, RESPAWN_ONE_DAY); - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i) - SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY); - - // Starting doors - DoorClose(BG_AB_OBJECT_GATE_A); - DoorClose(BG_AB_OBJECT_GATE_H); - SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY); - - // Starting base spirit guides - _NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE); - _NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE); -} - -void BattleGroundAB::StartingEventOpenDoors() -{ - // spawn neutral banners - for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i) - SpawnBGObject(banner, RESPAWN_IMMEDIATELY); - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - //randomly select buff to spawn - uint8 buff = urand(0, 2); - SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY); - } - DoorOpen(BG_AB_OBJECT_GATE_A); - DoorOpen(BG_AB_OBJECT_GATE_H); -} - -void BattleGroundAB::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in the constructor - BattleGroundABScore* sc = new BattleGroundABScore; - - m_PlayerScores[plr->GetGUID()] = sc; -} - -void BattleGroundAB::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) -{ - -} - -void BattleGroundAB::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - switch(Trigger) - { - case 3948: // Arathi Basin Alliance Exit. - if (Source->GetTeam() != ALLIANCE) - Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal"); - else - Source->LeaveBattleground(); - break; - case 3949: // Arathi Basin Horde Exit. - if (Source->GetTeam() != HORDE) - Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal"); - else - Source->LeaveBattleground(); - break; - case 3866: // Stables - case 3869: // Gold Mine - case 3867: // Farm - case 3868: // Lumber Mill - case 3870: // Black Smith - case 4020: // Unk1 - case 4021: // Unk2 - //break; - default: - //sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - //Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } -} - -/* type: 0-neutral, 1-contested, 3-occupied - teamIndex: 0-ally, 1-horde */ -void BattleGroundAB::_CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay) -{ - // Just put it into the queue - if (delay) - { - m_BannerTimers[node].timer = 2000; - m_BannerTimers[node].type = type; - m_BannerTimers[node].teamIndex = teamIndex; - return; - } - - uint8 obj = node*8 + type + teamIndex; - - SpawnBGObject(obj, RESPAWN_IMMEDIATELY); - - // handle aura with banner - if (!type) - return; - obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); - SpawnBGObject(obj, RESPAWN_IMMEDIATELY); -} - -void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex) -{ - uint8 obj = node*8 + type + teamIndex; - SpawnBGObject(obj, RESPAWN_ONE_DAY); - - // handle aura with banner - if (!type) - return; - obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); - SpawnBGObject(obj, RESPAWN_ONE_DAY); -} - -int32 BattleGroundAB::_GetNodeNameId(uint8 node) -{ - switch (node) - { - case BG_AB_NODE_STABLES: return LANG_BG_AB_NODE_STABLES; - case BG_AB_NODE_BLACKSMITH: return LANG_BG_AB_NODE_BLACKSMITH; - case BG_AB_NODE_FARM: return LANG_BG_AB_NODE_FARM; - case BG_AB_NODE_LUMBER_MILL:return LANG_BG_AB_NODE_LUMBER_MILL; - case BG_AB_NODE_GOLD_MINE: return LANG_BG_AB_NODE_GOLD_MINE; - default: - ASSERT(0); - } - return 0; -} - -void BattleGroundAB::FillInitialWorldStates(WorldPacket& data) -{ - const uint8 plusArray[] = {0, 2, 3, 0, 1}; - - // Node icons - for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) - data << uint32(BG_AB_OP_NODEICONS[node]) << uint32((m_Nodes[node] == 0)?1:0); - - // Node occupied states - for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) - for (uint8 i = 1; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - data << uint32(BG_AB_OP_NODESTATES[node] + plusArray[i]) << uint32((m_Nodes[node] == i)?1:0); - - // How many bases each team owns - uint8 ally = 0, horde = 0; - for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) - if (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) - ++ally; - else if (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) - ++horde; - - data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(ally); - data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(horde); - - // Team scores - data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE); - data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE); - data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[BG_TEAM_ALLIANCE]); - data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[BG_TEAM_HORDE]); - - // other unknown - data << uint32(0x745) << uint32(0x2); // 37 1861 unk -} - -void BattleGroundAB::_SendNodeUpdate(uint8 node) -{ - // Send node owner state update to refresh map icons on client - const uint8 plusArray[] = {0, 2, 3, 0, 1}; - - if (m_prevNodes[node]) - UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_prevNodes[node]], 0); - else - UpdateWorldState(BG_AB_OP_NODEICONS[node], 0); - - UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_Nodes[node]], 1); - - // How many bases each team owns - uint8 ally = 0, horde = 0; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - if (m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) - ++ally; - else if (m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) - ++horde; - - UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY, ally); - UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_HORDE, horde); -} - -void BattleGroundAB::_NodeOccupied(uint8 node,Team team) -{ - if (!AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team)) - sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team); - - uint8 capturedNodes = 0; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - if (m_Nodes[node] == GetTeamIndexByTeamId(team) + BG_AB_NODE_TYPE_OCCUPIED && !m_NodeTimers[i]) - ++capturedNodes; - } - if (capturedNodes >= 5) - CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES, team); - if (capturedNodes >= 4) - CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, team); - - if(node >= BG_AB_DYNAMIC_NODES_COUNT)//only dynamic nodes, no start points - return; - Creature* trigger = GetBGCreature(node+7);//0-6 spirit guides - if (!trigger) - trigger = AddCreature(WORLD_TRIGGER,node+7,team,BG_AB_NodePositions[node][0],BG_AB_NodePositions[node][1],BG_AB_NodePositions[node][2],BG_AB_NodePositions[node][3]); - - //add bonus honor aura trigger creature when node is accupied - //cast bonus aura (+50% honor in 25yards) - //aura should only apply to players who have accupied the node, set correct faction for trigger - if (trigger) - { - trigger->setFaction(team == ALLIANCE ? 84 : 83); - trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); - } -} - -void BattleGroundAB::_NodeDeOccupied(uint8 node) -{ - if (node >= BG_AB_DYNAMIC_NODES_COUNT) - return; - - //remove bonus honor aura trigger creature when node is lost - if(node < BG_AB_DYNAMIC_NODES_COUNT)//only dynamic nodes, no start points - DelCreature(node+7);//NULL checks are in DelCreature! 0-6 spirit guides - - // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard - std::vector ghost_list = m_ReviveQueue[m_BgCreatures[node]]; - if (!ghost_list.empty()) - { - WorldSafeLocsEntry const *ClosestGrave = NULL; - for (std::vector::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) - { - Player* plr = objmgr.GetPlayer(*itr); - if (!plr) - continue; - - if (!ClosestGrave) // cache - ClosestGrave = GetClosestGraveYard(plr); - - if (ClosestGrave) - plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); - } - } - - if (m_BgCreatures[node]) - DelCreature(node); - - // buff object isn't despawned -} - -/* Invoked if a player used a banner as a gameobject */ -void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*target_obj*/) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - uint8 node = BG_AB_NODE_STABLES; - GameObject* obj=GetBgMap()->GetGameObject(m_BgObjects[node*8+7]); - while ((node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj,10)))) - { - ++node; - obj=GetBgMap()->GetGameObject(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]); - } - - if (node == BG_AB_DYNAMIC_NODES_COUNT) - { - // this means our player isn't close to any of banners - maybe cheater ?? - return; - } - - BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(source->GetTeam()); - - // Check if player really could use this banner, not cheated - if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2)) - return; - - source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); - uint32 sound = 0; - // If node is neutral, change to contested - if (m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL) - { - UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = teamIndex + 1; - // burn current neutral banner - _DelBanner(node, BG_AB_NODE_TYPE_NEUTRAL, 0); - // create new contested banner - _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - - // FIXME: team and node names not localized - if (teamIndex == 0) - SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node), LANG_BG_AB_ALLY); - else - SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node), LANG_BG_AB_HORDE); - - sound = BG_AB_SOUND_NODE_CLAIMED; - } - // If node is contested - else if ((m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED)) - { - // If last state is NOT occupied, change node to enemy-contested - if (m_prevNodes[node] < BG_AB_NODE_TYPE_OCCUPIED) - { - UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); - // create new contested banner - _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - - // FIXME: node names not localized - if (teamIndex == BG_TEAM_ALLIANCE) - SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); - else - SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); - } - // If contested, change back to occupied - else - { - UpdatePlayerScore(source, SCORE_BASES_DEFENDED, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_OCCUPIED; - // burn current contested banner - _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); - // create new occupied banner - _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); - _SendNodeUpdate(node); - m_NodeTimers[node] = 0; - _NodeOccupied(node,(teamIndex == BG_TEAM_ALLIANCE) ? ALLIANCE:HORDE); - - // FIXME: node names not localized - if (teamIndex == BG_TEAM_ALLIANCE) - SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); - else - SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); - } - sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; - } - // If node is occupied, change to enemy-contested - else - { - UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); - m_prevNodes[node] = m_Nodes[node]; - m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED; - // burn current occupied banner - _DelBanner(node, BG_AB_NODE_TYPE_OCCUPIED, !teamIndex); - // create new contested banner - _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); - _SendNodeUpdate(node); - _NodeDeOccupied(node); - m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; - - // FIXME: node names not localized - if (teamIndex == BG_TEAM_ALLIANCE) - SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); - else - SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); - - sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; - } - - // If node is occupied again, send "X has taken the Y" msg. - if (m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED) - { - // FIXME: team and node names not localized - if (teamIndex == BG_TEAM_ALLIANCE) - SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_AB_ALLY, _GetNodeNameId(node)); - else - SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, LANG_BG_AB_HORDE, _GetNodeNameId(node)); - } - PlaySoundToAll(sound); -} - -bool BattleGroundAB::SetupBattleGround() -{ - for (int i = 0 ; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - if (!AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + 8*i,BG_AB_OBJECTID_NODE_BANNER_0 + i,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_CONT_A + 8*i,BG_AB_OBJECTID_BANNER_CONT_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_CONT_H + 8*i,BG_AB_OBJECTID_BANNER_CONT_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_ALLY + 8*i,BG_AB_OBJECTID_BANNER_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_BANNER_HORDE + 8*i,BG_AB_OBJECTID_BANNER_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_ALLY + 8*i,BG_AB_OBJECTID_AURA_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_HORDE + 8*i,BG_AB_OBJECTID_AURA_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_AURA_CONTESTED + 8*i,BG_AB_OBJECTID_AURA_C,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) -) - { - sLog.outErrorDb("BatteGroundAB: Failed to spawn some object BattleGround not created!"); - return false; - } - } - if (!AddObject(BG_AB_OBJECT_GATE_A,BG_AB_OBJECTID_GATE_A,BG_AB_DoorPositions[0][0],BG_AB_DoorPositions[0][1],BG_AB_DoorPositions[0][2],BG_AB_DoorPositions[0][3],BG_AB_DoorPositions[0][4],BG_AB_DoorPositions[0][5],BG_AB_DoorPositions[0][6],BG_AB_DoorPositions[0][7],RESPAWN_IMMEDIATELY) - || !AddObject(BG_AB_OBJECT_GATE_H,BG_AB_OBJECTID_GATE_H,BG_AB_DoorPositions[1][0],BG_AB_DoorPositions[1][1],BG_AB_DoorPositions[1][2],BG_AB_DoorPositions[1][3],BG_AB_DoorPositions[1][4],BG_AB_DoorPositions[1][5],BG_AB_DoorPositions[1][6],BG_AB_DoorPositions[1][7],RESPAWN_IMMEDIATELY) -) - { - sLog.outErrorDb("BatteGroundAB: Failed to spawn door object BattleGround not created!"); - return false; - } - //buffs - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - if (!AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 1, Buff_Entries[1], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 2, Buff_Entries[2], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) -) - sLog.outErrorDb("BatteGroundAB: Failed to spawn buff object!"); - } - - return true; -} - -void BattleGroundAB::Reset() -{ - //call parent's class reset - BattleGround::Reset(); - - m_TeamScores[BG_TEAM_ALLIANCE] = 0; - m_TeamScores[BG_TEAM_HORDE] = 0; - m_lastTick[BG_TEAM_ALLIANCE] = 0; - m_lastTick[BG_TEAM_HORDE] = 0; - m_HonorScoreTics[BG_TEAM_ALLIANCE] = 0; - m_HonorScoreTics[BG_TEAM_HORDE] = 0; - m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0; - m_ReputationScoreTics[BG_TEAM_HORDE] = 0; - m_IsInformedNearVictory = false; - bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); - m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; - m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; - m_TeamScores500Disadvantage[BG_TEAM_ALLIANCE] = false; - m_TeamScores500Disadvantage[BG_TEAM_HORDE] = false; - - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - { - m_Nodes[i] = 0; - m_prevNodes[i] = 0; - m_NodeTimers[i] = 0; - m_BannerTimers[i].timer = 0; - } - - for (uint8 i = 0; i < BG_AB_ALL_NODES_COUNT + 5; ++i)//+5 for aura triggers - if (m_BgCreatures[i]) - DelCreature(i); -} - -void BattleGroundAB::EndBattleGround(uint32 winner) -{ - //win reward - if (winner == ALLIANCE) - RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); - if (winner == HORDE) - RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); - //complete map_end rewards (even if no team wins) - RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); - RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); - - BattleGround::EndBattleGround(winner); -} - -WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player) -{ - BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(player->GetTeam()); - - // Is there any occupied node for this team? - std::vector nodes; - for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - if (m_Nodes[i] == teamIndex + 3) - nodes.push_back(i); - - WorldSafeLocsEntry const* good_entry = NULL; - // If so, select the closest node to place ghost on - if (!nodes.empty()) - { - float plr_x = player->GetPositionX(); - float plr_y = player->GetPositionY(); - - float mindist = 999999.0f; - for (uint8 i = 0; i < nodes.size(); ++i) - { - WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry(BG_AB_GraveyardIds[nodes[i]]); - if (!entry) - continue; - float dist = (entry->x - plr_x)*(entry->x - plr_x)+(entry->y - plr_y)*(entry->y - plr_y); - if (mindist > dist) - { - mindist = dist; - good_entry = entry; - } - } - nodes.clear(); - } - // If not, place ghost on starting location - if (!good_entry) - good_entry = sWorldSafeLocsStore.LookupEntry(BG_AB_GraveyardIds[teamIndex+5]); - - return good_entry; -} - -void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor) -{ - BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... - return; - - switch(type) - { - case SCORE_BASES_ASSAULTED: - ((BattleGroundABScore*)itr->second)->BasesAssaulted += value; - break; - case SCORE_BASES_DEFENDED: - ((BattleGroundABScore*)itr->second)->BasesDefended += value; - break; - default: - BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); - break; - } -} - -bool BattleGroundAB::IsAllNodesConrolledByTeam(uint32 team) const -{ - uint32 count = 0; - for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) - if ((team == ALLIANCE && m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) || - (team == HORDE && m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED)) - ++count; - - return count == BG_AB_DYNAMIC_NODES_COUNT; -} diff --git a/src/server/game/BattleGrounds/BattleGroundAB.h b/src/server/game/BattleGrounds/BattleGroundAB.h deleted file mode 100644 index 3072f8beafd..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundAB.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __BATTLEGROUNDAB_H -#define __BATTLEGROUNDAB_H - -class BattleGround; - -enum BG_AB_WorldStates -{ - BG_AB_OP_OCCUPIED_BASES_HORDE = 1778, - BG_AB_OP_OCCUPIED_BASES_ALLY = 1779, - BG_AB_OP_RESOURCES_ALLY = 1776, - BG_AB_OP_RESOURCES_HORDE = 1777, - BG_AB_OP_RESOURCES_MAX = 1780, - BG_AB_OP_RESOURCES_WARNING = 1955 -/* - BG_AB_OP_STABLE_ICON = 1842, //Stable map icon (NONE) - BG_AB_OP_STABLE_STATE_ALIENCE = 1767, //Stable map state (ALIENCE) - BG_AB_OP_STABLE_STATE_HORDE = 1768, //Stable map state (HORDE) - BG_AB_OP_STABLE_STATE_CON_ALI = 1769, //Stable map state (CON ALIENCE) - BG_AB_OP_STABLE_STATE_CON_HOR = 1770, //Stable map state (CON HORDE) - BG_AB_OP_FARM_ICON = 1845, //Farm map icon (NONE) - BG_AB_OP_FARM_STATE_ALIENCE = 1772, //Farm state (ALIENCE) - BG_AB_OP_FARM_STATE_HORDE = 1773, //Farm state (HORDE) - BG_AB_OP_FARM_STATE_CON_ALI = 1774, //Farm state (CON ALIENCE) - BG_AB_OP_FARM_STATE_CON_HOR = 1775, //Farm state (CON HORDE) - - BG_AB_OP_BLACKSMITH_ICON = 1846, //Blacksmith map icon (NONE) - BG_AB_OP_BLACKSMITH_STATE_ALIENCE = 1782, //Blacksmith map state (ALIENCE) - BG_AB_OP_BLACKSMITH_STATE_HORDE = 1783, //Blacksmith map state (HORDE) - BG_AB_OP_BLACKSMITH_STATE_CON_ALI = 1784, //Blacksmith map state (CON ALIENCE) - BG_AB_OP_BLACKSMITH_STATE_CON_HOR = 1785, //Blacksmith map state (CON HORDE) - BG_AB_OP_LUMBERMILL_ICON = 1844, //Lumber Mill map icon (NONE) - BG_AB_OP_LUMBERMILL_STATE_ALIENCE = 1792, //Lumber Mill map state (ALIENCE) - BG_AB_OP_LUMBERMILL_STATE_HORDE = 1793, //Lumber Mill map state (HORDE) - BG_AB_OP_LUMBERMILL_STATE_CON_ALI = 1794, //Lumber Mill map state (CON ALIENCE) - BG_AB_OP_LUMBERMILL_STATE_CON_HOR = 1795, //Lumber Mill map state (CON HORDE) - BG_AB_OP_GOLDMINE_ICON = 1843, //Gold Mine map icon (NONE) - BG_AB_OP_GOLDMINE_STATE_ALIENCE = 1787, //Gold Mine map state (ALIENCE) - BG_AB_OP_GOLDMINE_STATE_HORDE = 1788, //Gold Mine map state (HORDE) - BG_AB_OP_GOLDMINE_STATE_CON_ALI = 1789, //Gold Mine map state (CON ALIENCE - BG_AB_OP_GOLDMINE_STATE_CON_HOR = 1790, //Gold Mine map state (CON HORDE) -*/ -}; - -const uint32 BG_AB_OP_NODESTATES[5] = {1767, 1782, 1772, 1792, 1787}; - -const uint32 BG_AB_OP_NODEICONS[5] = {1842, 1846, 1845, 1844, 1843}; - -/* Note: code uses that these IDs follow each other */ -enum BG_AB_NodeObjectId -{ - BG_AB_OBJECTID_NODE_BANNER_0 = 180087, // Stables banner - BG_AB_OBJECTID_NODE_BANNER_1 = 180088, // Blacksmith banner - BG_AB_OBJECTID_NODE_BANNER_2 = 180089, // Farm banner - BG_AB_OBJECTID_NODE_BANNER_3 = 180090, // Lumber mill banner - BG_AB_OBJECTID_NODE_BANNER_4 = 180091 // Gold mine banner -}; - -enum BG_AB_ObjectType -{ - // for all 5 node points 8*5=40 objects - BG_AB_OBJECT_BANNER_NEUTRAL = 0, - BG_AB_OBJECT_BANNER_CONT_A = 1, - BG_AB_OBJECT_BANNER_CONT_H = 2, - BG_AB_OBJECT_BANNER_ALLY = 3, - BG_AB_OBJECT_BANNER_HORDE = 4, - BG_AB_OBJECT_AURA_ALLY = 5, - BG_AB_OBJECT_AURA_HORDE = 6, - BG_AB_OBJECT_AURA_CONTESTED = 7, - //gates - BG_AB_OBJECT_GATE_A = 40, - BG_AB_OBJECT_GATE_H = 41, - //buffs - BG_AB_OBJECT_SPEEDBUFF_STABLES = 42, - BG_AB_OBJECT_REGENBUFF_STABLES = 43, - BG_AB_OBJECT_BERSERKBUFF_STABLES = 44, - BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH = 45, - BG_AB_OBJECT_REGENBUFF_BLACKSMITH = 46, - BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH = 47, - BG_AB_OBJECT_SPEEDBUFF_FARM = 48, - BG_AB_OBJECT_REGENBUFF_FARM = 49, - BG_AB_OBJECT_BERSERKBUFF_FARM = 50, - BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL = 51, - BG_AB_OBJECT_REGENBUFF_LUMBER_MILL = 52, - BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 53, - BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE = 54, - BG_AB_OBJECT_REGENBUFF_GOLD_MINE = 55, - BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE = 56, - BG_AB_OBJECT_MAX = 57, -}; - -/* Object id templates from DB */ -enum BG_AB_ObjectTypes -{ - BG_AB_OBJECTID_BANNER_A = 180058, - BG_AB_OBJECTID_BANNER_CONT_A = 180059, - BG_AB_OBJECTID_BANNER_H = 180060, - BG_AB_OBJECTID_BANNER_CONT_H = 180061, - - BG_AB_OBJECTID_AURA_A = 180100, - BG_AB_OBJECTID_AURA_H = 180101, - BG_AB_OBJECTID_AURA_C = 180102, - - BG_AB_OBJECTID_GATE_A = 180255, - BG_AB_OBJECTID_GATE_H = 180256 -}; - -enum BG_AB_Timers -{ - BG_AB_FLAG_CAPTURING_TIME = 60000, -}; - -enum BG_AB_Score -{ - BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400, - BG_AB_MAX_TEAM_SCORE = 1600 -}; - -/* do NOT change the order, else wrong behaviour */ -enum BG_AB_BattleGroundNodes -{ - BG_AB_NODE_STABLES = 0, - BG_AB_NODE_BLACKSMITH = 1, - BG_AB_NODE_FARM = 2, - BG_AB_NODE_LUMBER_MILL = 3, - BG_AB_NODE_GOLD_MINE = 4, - - BG_AB_DYNAMIC_NODES_COUNT = 5, // dynamic nodes that can be captured - - BG_AB_SPIRIT_ALIANCE = 5, - BG_AB_SPIRIT_HORDE = 6, - - BG_AB_ALL_NODES_COUNT = 7, // all nodes (dynamic and static) -}; - -enum BG_AB_NodeStatus -{ - BG_AB_NODE_TYPE_NEUTRAL = 0, - BG_AB_NODE_TYPE_CONTESTED = 1, - BG_AB_NODE_STATUS_ALLY_CONTESTED = 1, - BG_AB_NODE_STATUS_HORDE_CONTESTED = 2, - BG_AB_NODE_TYPE_OCCUPIED = 3, - BG_AB_NODE_STATUS_ALLY_OCCUPIED = 3, - BG_AB_NODE_STATUS_HORDE_OCCUPIED = 4 -}; - -enum BG_AB_Sounds -{ - BG_AB_SOUND_NODE_CLAIMED = 8192, - BG_AB_SOUND_NODE_CAPTURED_ALLIANCE = 8173, - BG_AB_SOUND_NODE_CAPTURED_HORDE = 8213, - BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE = 8212, - BG_AB_SOUND_NODE_ASSAULTED_HORDE = 8174, - BG_AB_SOUND_NEAR_VICTORY = 8456 -}; - -#define BG_AB_NotABBGWeekendHonorTicks 330 -#define BG_AB_ABBGWeekendHonorTicks 200 -#define BG_AB_NotABBGWeekendReputationTicks 200 -#define BG_AB_ABBGWeekendReputationTicks 150 - -// x, y, z, o -const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { - {1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables - {977.0156f, 1046.616f, -44.80923f, -2.600541f}, // blacksmith - {806.1821f, 874.2723f, -55.99371f, -2.303835f}, // farm - {856.1419f, 1148.902f, 11.18469f, -2.303835f}, // lumber mill - {1146.923f, 848.1782f, -110.917f, -0.7330382f} // gold mine -}; - -// x, y, z, o, rot0, rot1, rot2, rot3 -const float BG_AB_DoorPositions[2][8] = { - {1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f, 0.93659f}, - {708.0903f, 708.4479f, -17.8342f, -2.391099f, 0.050291f, 0.015127f, 0.929217f, -0.365784f} -}; - -// Tick intervals and given points: case 0,1,2,3,4,5 captured nodes -const uint32 BG_AB_TickIntervals[6] = {0, 12000, 9000, 6000, 3000, 1000}; -const uint32 BG_AB_TickPoints[6] = {0, 10, 10, 10, 10, 30}; - -// WorldSafeLocs ids for 5 nodes, and for ally, and horde starting location -const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 896, 898, 899}; - -// x, y, z, o -const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { - {1185.71f, 1185.24f, -56.36f, 2.56f}, // stables - {990.75f, 1008.18f, -42.60f, 2.43f}, // blacksmith - {817.66f, 843.34f, -56.54f, 3.01f}, // farm - {807.46f, 1189.16f, 11.92f, 5.44f}, // lumber mill - {1146.62f, 816.94f, -98.49f, 6.14f} // gold mine -}; - -// x, y, z, o -const float BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT][4] = { - {1200.03f, 1171.09f, -56.47f, 5.15f}, // stables - {1017.43f, 960.61f, -42.95f, 4.88f}, // blacksmith - {833.00f, 793.00f, -57.25f, 5.27f}, // farm - {775.17f, 1206.40f, 15.79f, 1.90f}, // lumber mill - {1207.48f, 787.00f, -83.36f, 5.51f}, // gold mine - {1354.05f, 1275.48f, -11.30f, 4.77f}, // alliance starting base - {714.61f, 646.15f, -10.87f, 4.34f} // horde starting base -}; - -struct BG_AB_BannerTimer -{ - uint32 timer; - uint8 type; - uint8 teamIndex; -}; - -class BattleGroundABScore : public BattleGroundScore -{ - public: - BattleGroundABScore(): BasesAssaulted(0), BasesDefended(0) {}; - virtual ~BattleGroundABScore() {}; - uint32 BasesAssaulted; - uint32 BasesDefended; -}; - -class BattleGroundAB : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundAB(); - ~BattleGroundAB(); - - void Update(uint32 diff); - void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - void RemovePlayer(Player *plr,uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - virtual bool SetupBattleGround(); - virtual void Reset(); - void EndBattleGround(uint32 winner); - virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); - - /* Scorekeeping */ - virtual void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); - - virtual void FillInitialWorldStates(WorldPacket& data); - - /* Nodes occupying */ - virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj); - - /* achievement req. */ - bool IsAllNodesConrolledByTeam(uint32 team) const; // overwrited - bool IsTeamScores500Disadvantage(uint32 team) const { return m_TeamScores500Disadvantage[GetTeamIndexByTeamId(team)]; } - private: - /* Gameobject spawning/despawning */ - void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay); - void _DelBanner(uint8 node, uint8 type, uint8 teamIndex); - void _SendNodeUpdate(uint8 node); - - /* Creature spawning/despawning */ - // TODO: working, scripted peons spawning - void _NodeOccupied(uint8 node,Team team); - void _NodeDeOccupied(uint8 node); - - int32 _GetNodeNameId(uint8 node); - - /* Nodes info: - 0: neutral - 1: ally contested - 2: horde contested - 3: ally occupied - 4: horde occupied */ - uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; - uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; - BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; - uint32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; - uint32 m_lastTick[BG_TEAMS_COUNT]; - uint32 m_HonorScoreTics[BG_TEAMS_COUNT]; - uint32 m_ReputationScoreTics[BG_TEAMS_COUNT]; - bool m_IsInformedNearVictory; - uint32 m_HonorTics; - uint32 m_ReputationTics; - // need for achievements - bool m_TeamScores500Disadvantage[BG_TEAMS_COUNT]; -}; -#endif - diff --git a/src/server/game/BattleGrounds/BattleGroundAV.cpp b/src/server/game/BattleGrounds/BattleGroundAV.cpp deleted file mode 100644 index 7f5482cbf16..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundAV.cpp +++ /dev/null @@ -1,1490 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ObjectMgr.h" -#include "WorldPacket.h" - -#include "BattleGround.h" -#include "BattleGroundAV.h" -#include "Formulas.h" -#include "GameObject.h" -#include "Language.h" -#include "Player.h" -#include "SpellAuras.h" - -BattleGroundAV::BattleGroundAV() -{ - m_BgObjects.resize(BG_AV_OBJECT_MAX); - m_BgCreatures.resize(AV_CPLACE_MAX+AV_STATICCPLACE_MAX); - - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AV_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AV_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AV_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AV_HAS_BEGUN; -} - -BattleGroundAV::~BattleGroundAV() -{ -} - -const uint16 BattleGroundAV::GetBonusHonor(uint8 kills) //TODO: move this function to Battleground.cpp (needs to find a way to get m_MaxLevel) -{ - return Trinity::Honor::hk_honor_at_level(m_MaxLevel, kills); -} - -void BattleGroundAV::HandleKillPlayer(Player *player, Player *killer) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - BattleGround::HandleKillPlayer(player, killer); - UpdateScore(player->GetTeam(),-1); -} - -void BattleGroundAV::HandleKillUnit(Creature *unit, Player *killer) -{ - sLog.outDebug("bg_av HandleKillUnit %i",unit->GetEntry()); - if (GetStatus() != STATUS_IN_PROGRESS) - return; - uint32 entry = unit->GetEntry(); - /* - uint32 triggerSpawnID = 0; - if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0]) - triggerSpawnID = AV_CPLACE_TRIGGER16; - else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_BOSS][0]) - triggerSpawnID = AV_CPLACE_TRIGGER17; - else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN][0]) - triggerSpawnID = AV_CPLACE_TRIGGER18; - else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_BOSS][0]) - triggerSpawnID = AV_CPLACE_TRIGGER19; - */ - if (entry == BG_AV_CreatureInfo[AV_NPC_A_BOSS][0]) - { - CastSpellOnTeam(23658,HORDE); //this is a spell which finishes a quest where a player has to kill the boss - RewardReputationToTeam(729,BG_AV_REP_BOSS,HORDE); - RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_BOSS),HORDE); - EndBattleGround(HORDE); - DelCreature(AV_CPLACE_TRIGGER17); - } - else if (entry == BG_AV_CreatureInfo[AV_NPC_H_BOSS][0]) - { - CastSpellOnTeam(23658,ALLIANCE); //this is a spell which finishes a quest where a player has to kill the boss - RewardReputationToTeam(730,BG_AV_REP_BOSS,ALLIANCE); - RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_BOSS),ALLIANCE); - EndBattleGround(ALLIANCE); - DelCreature(AV_CPLACE_TRIGGER19); - } - else if (entry == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0]) - { - if (!m_CaptainAlive[0]) - { - sLog.outError("Killed a Captain twice, please report this bug, if you haven't done \".respawn\""); - return; - } - m_CaptainAlive[0]=false; - RewardReputationToTeam(729,BG_AV_REP_CAPTAIN,HORDE); - RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_CAPTAIN),HORDE); - UpdateScore(ALLIANCE,(-1)*BG_AV_RES_CAPTAIN); - //spawn destroyed aura - for (uint8 i=0; i <= 9; i++) - SpawnBGObject(BG_AV_OBJECT_BURN_BUILDING_ALLIANCE+i,RESPAWN_IMMEDIATELY); - Creature* creature = GetBGCreature(AV_CPLACE_HERALD); - if (creature) - YellToAll(creature,GetTrinityString(LANG_BG_AV_A_CAPTAIN_DEAD),LANG_UNIVERSAL); - DelCreature(AV_CPLACE_TRIGGER16); - } - else if (entry == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN][0]) - { - if (!m_CaptainAlive[1]) - { - sLog.outError("Killed a Captain twice, please report this bug, if you haven't done \".respawn\""); - return; - } - m_CaptainAlive[1]=false; - RewardReputationToTeam(730,BG_AV_REP_CAPTAIN,ALLIANCE); - RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_CAPTAIN),ALLIANCE); - UpdateScore(HORDE,(-1)*BG_AV_RES_CAPTAIN); - //spawn destroyed aura - for (uint8 i=0; i <= 9; i++) - SpawnBGObject(BG_AV_OBJECT_BURN_BUILDING_HORDE+i,RESPAWN_IMMEDIATELY); - Creature* creature = GetBGCreature(AV_CPLACE_HERALD); - if (creature) - YellToAll(creature,GetTrinityString(LANG_BG_AV_H_CAPTAIN_DEAD),LANG_UNIVERSAL); - DelCreature(AV_CPLACE_TRIGGER18); - } - else if (entry == BG_AV_CreatureInfo[AV_NPC_N_MINE_N_4][0] || entry == BG_AV_CreatureInfo[AV_NPC_N_MINE_A_4][0] || entry == BG_AV_CreatureInfo[AV_NPC_N_MINE_H_4][0]) - ChangeMineOwner(AV_NORTH_MINE,killer->GetTeam()); - else if (entry == BG_AV_CreatureInfo[AV_NPC_S_MINE_N_4][0] || entry == BG_AV_CreatureInfo[AV_NPC_S_MINE_A_4][0] || entry == BG_AV_CreatureInfo[AV_NPC_S_MINE_H_4][0]) - ChangeMineOwner(AV_SOUTH_MINE,killer->GetTeam()); -} - -void BattleGroundAV::HandleQuestComplete(uint32 questid, Player *player) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return;//maybe we should log this, cause this must be a cheater or a big bug - uint8 team = GetTeamIndexByTeamId(player->GetTeam()); - //TODO add reputation, events (including quest not available anymore, next quest availabe, go/npc de/spawning)and maybe honor - sLog.outDebug("BG_AV Quest %i completed",questid); - switch(questid) - { - case AV_QUEST_A_SCRAPS1: - case AV_QUEST_A_SCRAPS2: - case AV_QUEST_H_SCRAPS1: - case AV_QUEST_H_SCRAPS2: - m_Team_QuestStatus[team][0]+=20; - if (m_Team_QuestStatus[team][0] == 500 || m_Team_QuestStatus[team][0] == 1000 || m_Team_QuestStatus[team][0] == 1500) //25,50,75 turn ins - { - sLog.outDebug("BG_AV Quest %i completed starting with unit upgrading..",questid); - for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) - if (m_Nodes[i].Owner == player->GetTeam() && m_Nodes[i].State == POINT_CONTROLED) - { - DePopulateNode(i); - PopulateNode(i); - //maybe this is bad, because it will instantly respawn all creatures on every grave.. - } - } - break; - case AV_QUEST_A_COMMANDER1: - case AV_QUEST_H_COMMANDER1: - m_Team_QuestStatus[team][1]++; - RewardReputationToTeam(team,1,player->GetTeam()); - if (m_Team_QuestStatus[team][1] == 30) - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); - break; - case AV_QUEST_A_COMMANDER2: - case AV_QUEST_H_COMMANDER2: - m_Team_QuestStatus[team][2]++; - RewardReputationToTeam(team,1,player->GetTeam()); - if (m_Team_QuestStatus[team][2] == 60) - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); - break; - case AV_QUEST_A_COMMANDER3: - case AV_QUEST_H_COMMANDER3: - m_Team_QuestStatus[team][3]++; - RewardReputationToTeam(team,1,player->GetTeam()); - if (m_Team_QuestStatus[team][1] == 120) - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); - break; - case AV_QUEST_A_BOSS1: - case AV_QUEST_H_BOSS1: - m_Team_QuestStatus[team][4] += 9; //you can turn in 10 or 1 item.. - case AV_QUEST_A_BOSS2: - case AV_QUEST_H_BOSS2: - m_Team_QuestStatus[team][4]++; - if (m_Team_QuestStatus[team][4] >= 200) - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); - break; - case AV_QUEST_A_NEAR_MINE: - case AV_QUEST_H_NEAR_MINE: - m_Team_QuestStatus[team][5]++; - if (m_Team_QuestStatus[team][5] == 28) - { - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); - if (m_Team_QuestStatus[team][6] == 7) - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here - ground assault ready",questid); - } - break; - case AV_QUEST_A_OTHER_MINE: - case AV_QUEST_H_OTHER_MINE: - m_Team_QuestStatus[team][6]++; - if (m_Team_QuestStatus[team][6] == 7) - { - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); - if (m_Team_QuestStatus[team][5] == 20) - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here - ground assault ready",questid); - } - break; - case AV_QUEST_A_RIDER_HIDE: - case AV_QUEST_H_RIDER_HIDE: - m_Team_QuestStatus[team][7]++; - if (m_Team_QuestStatus[team][7] == 25) - { - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); - if (m_Team_QuestStatus[team][8] == 25) - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here - rider assault ready",questid); - } - break; - case AV_QUEST_A_RIDER_TAME: - case AV_QUEST_H_RIDER_TAME: - m_Team_QuestStatus[team][8]++; - if (m_Team_QuestStatus[team][8] == 25) - { - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); - if (m_Team_QuestStatus[team][7] == 25) - sLog.outDebug("BG_AV Quest %i completed (need to implement some events here - rider assault ready",questid); - } - break; - default: - sLog.outDebug("BG_AV Quest %i completed but is not interesting at all",questid); - return; //was no interesting quest at all - break; - } -} - -void BattleGroundAV::UpdateScore(uint16 team, int16 points) -{ //note: to remove reinforcementpoints points must be negative, for adding reinforcements points must be positive - assert(team == ALLIANCE || team == HORDE); - uint8 teamindex = GetTeamIndexByTeamId(team); //0=ally 1=horde - m_Team_Scores[teamindex] += points; - - UpdateWorldState(((teamindex == BG_TEAM_HORDE)?AV_Horde_Score:AV_Alliance_Score), m_Team_Scores[teamindex]); - if (points < 0) - { - if (m_Team_Scores[teamindex] < 1) - { - m_Team_Scores[teamindex]=0; - EndBattleGround(((teamindex == BG_TEAM_HORDE)?ALLIANCE:HORDE)); - } - else if (!m_IsInformedNearVictory[teamindex] && m_Team_Scores[teamindex] < SEND_MSG_NEAR_LOSE) - { - SendMessageToAll(teamindex == BG_TEAM_HORDE?LANG_BG_AV_H_NEAR_LOSE:LANG_BG_AV_A_NEAR_LOSE, teamindex == BG_TEAM_HORDE ? CHAT_MSG_BG_SYSTEM_HORDE : CHAT_MSG_BG_SYSTEM_ALLIANCE); - PlaySoundToAll(AV_SOUND_NEAR_VICTORY); - m_IsInformedNearVictory[teamindex] = true; - } - } -} - -Creature* BattleGroundAV::AddAVCreature(uint16 cinfoid, uint16 type) -{ - uint8 level; - bool isStatic = false; - Creature* creature = NULL; - assert(type <= AV_CPLACE_MAX + AV_STATICCPLACE_MAX); - if (type >= AV_CPLACE_MAX) //static - { - type -= AV_CPLACE_MAX; - cinfoid=uint16(BG_AV_StaticCreaturePos[type][4]); - creature = AddCreature(BG_AV_StaticCreatureInfo[cinfoid][0],(type+AV_CPLACE_MAX),BG_AV_StaticCreatureInfo[cinfoid][1],BG_AV_StaticCreaturePos[type][0],BG_AV_StaticCreaturePos[type][1],BG_AV_StaticCreaturePos[type][2],BG_AV_StaticCreaturePos[type][3]); - level = (BG_AV_StaticCreatureInfo[cinfoid][2] == BG_AV_StaticCreatureInfo[cinfoid][3]) ? BG_AV_StaticCreatureInfo[cinfoid][2] : urand(BG_AV_StaticCreatureInfo[cinfoid][2],BG_AV_StaticCreatureInfo[cinfoid][3]); - isStatic = true; - } - else - { - creature = AddCreature(BG_AV_CreatureInfo[cinfoid][0],type,BG_AV_CreatureInfo[cinfoid][1],BG_AV_CreaturePos[type][0],BG_AV_CreaturePos[type][1],BG_AV_CreaturePos[type][2],BG_AV_CreaturePos[type][3]); - level = (BG_AV_CreatureInfo[cinfoid][2] == BG_AV_CreatureInfo[cinfoid][3]) ? BG_AV_CreatureInfo[cinfoid][2] : urand(BG_AV_CreatureInfo[cinfoid][2],BG_AV_CreatureInfo[cinfoid][3]); - } - if (!creature) - return NULL; - if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0] || creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN][0]) - creature->SetRespawnDelay(RESPAWN_ONE_DAY); // TODO: look if this can be done by database + also add this for the wingcommanders - - if ((isStatic && cinfoid >= 10 && cinfoid <= 14) || (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3) || - (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3)))) - { - if (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3) - || (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3))) - { - CreatureData &data = objmgr.NewOrExistCreatureData(creature->GetDBTableGUIDLow()); - data.spawndist = 5; - } - //else spawndist will be 15, so creatures move maximum=10 - //creature->SetDefaultMovementType(RANDOM_MOTION_TYPE); - creature->GetMotionMaster()->Initialize(); - creature->setDeathState(JUST_DIED); - creature->Respawn(); - //TODO: find a way to add a motionmaster without killing the creature (i - //just copied this code from a gm-command - } - - if (level != 0) - level += m_MaxLevel - 60; //maybe we can do this more generic for custom level-range.. actually it's blizzlike - creature->SetLevel(level); - - uint32 triggerSpawnID = 0; - uint32 newFaction = 0; - if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0]) - { - triggerSpawnID = AV_CPLACE_TRIGGER16; - newFaction = 84; - } - else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_BOSS][0]) - { - triggerSpawnID = AV_CPLACE_TRIGGER17; - newFaction = 84; - } - else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN][0]) - { - triggerSpawnID = AV_CPLACE_TRIGGER18; - newFaction = 83; - } - else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_BOSS][0]) - { - triggerSpawnID = AV_CPLACE_TRIGGER19; - newFaction = 83; - } - if (triggerSpawnID && newFaction) - { - if (Creature* trigger = AddCreature(WORLD_TRIGGER,triggerSpawnID,BG_AV_CreatureInfo[creature->GetEntry()][1],BG_AV_CreaturePos[triggerSpawnID][0],BG_AV_CreaturePos[triggerSpawnID][1],BG_AV_CreaturePos[triggerSpawnID][2],BG_AV_CreaturePos[triggerSpawnID][3])) - { - trigger->setFaction(newFaction); - trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); - } - } - - return creature; -} - -void BattleGroundAV::Update(uint32 diff) -{ - BattleGround::Update(diff); - - if (GetStatus() == STATUS_IN_PROGRESS) - { - for (uint8 i=0; i <= 1; i++)//0=alliance, 1=horde - { - if (!m_CaptainAlive[i]) - continue; - if (m_CaptainBuffTimer[i] > diff) - m_CaptainBuffTimer[i] -= diff; - else - { - if (i == 0) - { - CastSpellOnTeam(AV_BUFF_A_CAPTAIN,ALLIANCE); - Creature* creature = GetBGCreature(AV_CPLACE_MAX + 61); - if (creature) - YellToAll(creature,LANG_BG_AV_A_CAPTAIN_BUFF,LANG_COMMON); - } - else - { - CastSpellOnTeam(AV_BUFF_H_CAPTAIN,HORDE); - Creature* creature = GetBGCreature(AV_CPLACE_MAX + 59); //TODO: make the captains a dynamic creature - if (creature) - YellToAll(creature,LANG_BG_AV_H_CAPTAIN_BUFF,LANG_ORCISH); - } - m_CaptainBuffTimer[i] = 120000 + urand(0,4)* 60000; //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes TODO get the right times - } - } - //add points from mine owning, and look if he neutral team wanrts to reclaim the mine - m_Mine_Timer -=diff; - for (uint8 mine=0; mine <2; mine++) - { - if (m_Mine_Owner[mine] == ALLIANCE || m_Mine_Owner[mine] == HORDE) - { - if (m_Mine_Timer <= 0) - UpdateScore(m_Mine_Owner[mine],1); - - if (m_Mine_Reclaim_Timer[mine] > diff) - m_Mine_Reclaim_Timer[mine] -= diff; - else{ //we don't need to set this timer to 0 cause this codepart wont get called when this thing is 0 - ChangeMineOwner(mine,AV_NEUTRAL_TEAM); - } - } - } - if (m_Mine_Timer <= 0) - m_Mine_Timer=AV_MINE_TICK_TIMER; //this is at the end, cause we need to update both mines - - //looks for all timers of the nodes and destroy the building (for graveyards the building wont get destroyed, it goes just to the other team - for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i) - if (m_Nodes[i].State == POINT_ASSAULTED) //maybe remove this - { - if (m_Nodes[i].Timer > diff) - m_Nodes[i].Timer -= diff; - else - EventPlayerDestroyedPoint(i); - } - } -} - -void BattleGroundAV::StartingEventCloseDoors() -{ - DoorClose(BG_AV_OBJECT_DOOR_A); - DoorClose(BG_AV_OBJECT_DOOR_H); -} - -void BattleGroundAV::StartingEventOpenDoors() -{ - sLog.outDebug("BG_AV: start spawning mine stuff"); - for (uint16 i= BG_AV_OBJECT_MINE_SUPPLY_N_MIN; i <= BG_AV_OBJECT_MINE_SUPPLY_N_MAX; i++) - SpawnBGObject(i,RESPAWN_IMMEDIATELY); - for (uint16 i= BG_AV_OBJECT_MINE_SUPPLY_S_MIN; i <= BG_AV_OBJECT_MINE_SUPPLY_S_MAX; i++) - SpawnBGObject(i,RESPAWN_IMMEDIATELY); - for (uint8 mine = AV_NORTH_MINE; mine <= AV_SOUTH_MINE; mine++) //mine population - ChangeMineOwner(mine, AV_NEUTRAL_TEAM,true); - - UpdateWorldState(AV_SHOW_H_SCORE, 1); - UpdateWorldState(AV_SHOW_A_SCORE, 1); - - DoorOpen(BG_AV_OBJECT_DOOR_H); - DoorOpen(BG_AV_OBJECT_DOOR_A); -} - -void BattleGroundAV::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundAVScore* sc = new BattleGroundAVScore; - m_PlayerScores[plr->GetGUID()] = sc; - if (m_MaxLevel == 0) - m_MaxLevel=(plr->getLevel()%10 == 0)? plr->getLevel() : (plr->getLevel()-(plr->getLevel()%10))+10; //TODO: just look at the code \^_^/ --but queue-info should provide this information.. - -} - -void BattleGroundAV::EndBattleGround(uint32 winner) -{ - //calculate bonuskills for both teams: - //first towers: - uint8 kills[2]={0,0}; //0=ally 1=horde - uint8 rep[2]={0,0}; //0=ally 1=horde - for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) - { - if (m_Nodes[i].State == POINT_CONTROLED) - { - if (m_Nodes[i].Owner == ALLIANCE) - { - rep[0] += BG_AV_REP_SURVIVING_TOWER; - kills[0] += BG_AV_KILL_SURVIVING_TOWER; - } - else - { - rep[0] += BG_AV_KILL_SURVIVING_TOWER; - kills[1] += BG_AV_KILL_SURVIVING_TOWER; - } - } - } - - for (int i=0; i <= 1; i++) //0=ally 1=horde - { - if (m_CaptainAlive[i]) - { - kills[i] += BG_AV_KILL_SURVIVING_CAPTAIN; - rep[i] += BG_AV_REP_SURVIVING_CAPTAIN; - } - if (rep[i] != 0) - RewardReputationToTeam((i == 0)?730:729,rep[i],(i == 0)?ALLIANCE:HORDE); - if (kills[i] != 0) - RewardHonorToTeam(GetBonusHonor(kills[i]),(i == 0)?ALLIANCE:HORDE); - } - - //TODO add enterevademode for all attacking creatures - BattleGround::EndBattleGround(winner); -} - -void BattleGroundAV::RemovePlayer(Player* plr,uint64 /*guid*/) -{ - if (!plr) - { - sLog.outError("bg_AV no player at remove"); - return; - } - //TODO search more buffs - plr->RemoveAurasDueToSpell(AV_BUFF_ARMOR); - plr->RemoveAurasDueToSpell(AV_BUFF_A_CAPTAIN); - plr->RemoveAurasDueToSpell(AV_BUFF_H_CAPTAIN); -} - -void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - uint32 SpellId = 0; - switch(Trigger) - { - case 95: - case 2608: - if (Source->GetTeam() != ALLIANCE) - Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal"); - else - Source->LeaveBattleground(); - break; - case 2606: - if (Source->GetTeam() != HORDE) - Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal"); - else - Source->LeaveBattleground(); - break; - case 3326: - case 3327: - case 3328: - case 3329: - case 3330: - case 3331: - //Source->Unmount(); - break; - default: - sLog.outDebug("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); -// Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } - - if (SpellId) - Source->CastSpell(Source, SpellId, true); -} - -void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) -{ - - BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... - return; - - switch(type) - { - case SCORE_GRAVEYARDS_ASSAULTED: - ((BattleGroundAVScore*)itr->second)->GraveyardsAssaulted += value; - break; - case SCORE_GRAVEYARDS_DEFENDED: - ((BattleGroundAVScore*)itr->second)->GraveyardsDefended += value; - break; - case SCORE_TOWERS_ASSAULTED: - ((BattleGroundAVScore*)itr->second)->TowersAssaulted += value; - break; - case SCORE_TOWERS_DEFENDED: - ((BattleGroundAVScore*)itr->second)->TowersDefended += value; - break; - case SCORE_MINES_CAPTURED: - ((BattleGroundAVScore*)itr->second)->MinesCaptured += value; - break; - case SCORE_LEADERS_KILLED: - ((BattleGroundAVScore*)itr->second)->LeadersKilled += value; - break; - case SCORE_SECONDARY_OBJECTIVES: - ((BattleGroundAVScore*)itr->second)->SecondaryObjectives += value; - break; - default: - BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); - break; - } -} - -void BattleGroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node) -{ - - uint32 object = GetObjectThroughNode(node); - sLog.outDebug("bg_av: player destroyed point node %i object %i",node,object); - - //despawn banner - SpawnBGObject(object, RESPAWN_ONE_DAY); - DestroyNode(node); - UpdateNodeWorldState(node); - - uint32 owner = m_Nodes[node].Owner; - if (IsTower(node)) - { - uint8 tmp = node-BG_AV_NODES_DUNBALDAR_SOUTH; - //despawn marshal - if (m_BgCreatures[AV_CPLACE_A_MARSHAL_SOUTH + tmp]) - DelCreature(AV_CPLACE_A_MARSHAL_SOUTH + tmp); - else - sLog.outError("BG_AV: playerdestroyedpoint: marshal %i doesn't exist",AV_CPLACE_A_MARSHAL_SOUTH + tmp); - //spawn destroyed aura - for (uint8 i=0; i <= 9; i++) - SpawnBGObject(BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH + i + (tmp * 10),RESPAWN_IMMEDIATELY); - - UpdateScore((owner == ALLIANCE) ? HORDE : ALLIANCE, (-1)*BG_AV_RES_TOWER); - RewardReputationToTeam((owner == ALLIANCE)?730:729,BG_AV_REP_TOWER,owner); - RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_TOWER),owner); - - SpawnBGObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+GetTeamIndexByTeamId(owner)+(2*tmp),RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+GetTeamIndexByTeamId(owner)+(2*tmp),RESPAWN_ONE_DAY); - } - else - { - if (owner == ALLIANCE) - SpawnBGObject(object-11, RESPAWN_IMMEDIATELY); - else - SpawnBGObject(object+11, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node,RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+GetTeamIndexByTeamId(owner)+3*node,RESPAWN_IMMEDIATELY); - PopulateNode(node); - if (node == BG_AV_NODES_SNOWFALL_GRAVE) //snowfall eyecandy - { - for (uint8 i = 0; i < 4; i++) - { - SpawnBGObject(((owner == ALLIANCE)?BG_AV_OBJECT_SNOW_EYECANDY_PA : BG_AV_OBJECT_SNOW_EYECANDY_PH)+i,RESPAWN_ONE_DAY); - SpawnBGObject(((owner == ALLIANCE)?BG_AV_OBJECT_SNOW_EYECANDY_A : BG_AV_OBJECT_SNOW_EYECANDY_H)+i,RESPAWN_IMMEDIATELY); - } - } - } - //send a nice message to all :) - char buf[256]; - if (IsTower(node)) - sprintf(buf, GetTrinityString(LANG_BG_AV_TOWER_TAKEN) , GetNodeName(node),(owner == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) : GetTrinityString(LANG_BG_AV_HORDE)); - else - sprintf(buf, GetTrinityString(LANG_BG_AV_GRAVE_TAKEN) , GetNodeName(node),(owner == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) :GetTrinityString(LANG_BG_AV_HORDE)); - - Creature* creature = GetBGCreature(AV_CPLACE_HERALD); - if (creature) - YellToAll(creature,buf,LANG_UNIVERSAL); -} - -void BattleGroundAV::ChangeMineOwner(uint8 mine, uint32 team, bool initial) -{ //mine=0 northmine mine=1 southmin -//changing the owner results in setting respawntim to infinite for current creatures, spawning new mine owners creatures and changing the chest-objects so that the current owning team can use them - assert(mine == AV_NORTH_MINE || mine == AV_SOUTH_MINE); - if (team != ALLIANCE && team != HORDE) - team = AV_NEUTRAL_TEAM; - else - PlaySoundToAll((team == ALLIANCE)?AV_SOUND_ALLIANCE_GOOD:AV_SOUND_HORDE_GOOD); - - if (m_Mine_Owner[mine] == team && !initial) - return; - m_Mine_PrevOwner[mine] = m_Mine_Owner[mine]; - m_Mine_Owner[mine] = team; - - if (!initial) - { - sLog.outDebug("bg_av depopulating mine %i (0=north,1=south)",mine); - if (mine == AV_SOUTH_MINE) - for (uint16 i=AV_CPLACE_MINE_S_S_MIN; i <= AV_CPLACE_MINE_S_S_MAX; i++) - if (m_BgCreatures[i]) - DelCreature(i); //TODO just set the respawntime to 999999 - for (uint16 i=((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_1_MIN:AV_CPLACE_MINE_S_1_MIN); i <= ((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_3:AV_CPLACE_MINE_S_3); i++) - if (m_BgCreatures[i]) - DelCreature(i); //TODO here also - } - SendMineWorldStates(mine); - - sLog.outDebug("bg_av populating mine %i (0=north,1=south)",mine); - uint16 miner; - //also neutral team exists.. after a big time, the neutral team tries to conquer the mine - if (mine == AV_NORTH_MINE) - { - if (team == ALLIANCE) - miner = AV_NPC_N_MINE_A_1; - else if (team == HORDE) - miner = AV_NPC_N_MINE_H_1; - else - miner = AV_NPC_N_MINE_N_1; - } - else - { - uint16 cinfo; - if (team == ALLIANCE) - miner = AV_NPC_S_MINE_A_1; - else if (team == HORDE) - miner = AV_NPC_S_MINE_H_1; - else - miner = AV_NPC_S_MINE_N_1; - //vermin - sLog.outDebug("spawning vermin"); - if (team == ALLIANCE) - cinfo = AV_NPC_S_MINE_A_3; - else if (team == HORDE) - cinfo = AV_NPC_S_MINE_H_3; - else - cinfo = AV_NPC_S_MINE_N_S; - for (uint16 i=AV_CPLACE_MINE_S_S_MIN; i <= AV_CPLACE_MINE_S_S_MAX; i++) - AddAVCreature(cinfo,i); - } - for (uint16 i=((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_1_MIN:AV_CPLACE_MINE_S_1_MIN); i <= ((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_1_MAX:AV_CPLACE_MINE_S_1_MAX); i++) - AddAVCreature(miner,i); - //the next chooses randomly between 2 cretures - for (uint16 i=((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_2_MIN:AV_CPLACE_MINE_S_2_MIN); i <= ((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_2_MAX:AV_CPLACE_MINE_S_2_MAX); i++) - AddAVCreature(miner+(urand(1,2)),i); - AddAVCreature(miner+3,(mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_3:AV_CPLACE_MINE_S_3); - //because the gameobjects in this mine have changed, update all surrounding players: -// for (uint16 i = ((mine == AV_NORTH_MINE)?BG_AV_OBJECT_MINE_SUPPLY_N_MIN:BG_AV_OBJECT_MINE_SUPPLY_N_MIN); i <= ((mine == AV_NORTH_MINE)?BG_AV_OBJECT_MINE_SUPPLY_N_MAX:BG_AV_OBJECT_MINE_SUPPLY_N_MAX); i++) -// { - //TODO: add gameobject-update code -// } - if (team == ALLIANCE || team == HORDE) - { - m_Mine_Reclaim_Timer[mine]=AV_MINE_RECLAIM_TIMER; - char buf[256]; - sprintf(buf, GetTrinityString(LANG_BG_AV_MINE_TAKEN), GetTrinityString((mine == AV_NORTH_MINE) ? LANG_BG_AV_MINE_NORTH : LANG_BG_AV_MINE_SOUTH), (team == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) : GetTrinityString(LANG_BG_AV_HORDE)); - Creature* creature = GetBGCreature(AV_CPLACE_HERALD); - if (creature) - YellToAll(creature,buf,LANG_UNIVERSAL); - } - else - { - if (mine == AV_SOUTH_MINE) //i think this gets called all the time - { - Creature* creature = GetBGCreature(AV_CPLACE_MINE_S_3); - YellToAll(creature,LANG_BG_AV_S_MINE_BOSS_CLAIMS,LANG_UNIVERSAL); - } - } - return; -} - -bool BattleGroundAV::PlayerCanDoMineQuest(int32 GOId,uint32 team) -{ - if (GOId == BG_AV_OBJECTID_MINE_N) - return (m_Mine_Owner[AV_NORTH_MINE] == team); - if (GOId == BG_AV_OBJECTID_MINE_S) - return (m_Mine_Owner[AV_SOUTH_MINE] == team); - return true; //cause it's no mine'object it is ok if this is true -} - -void BattleGroundAV::PopulateNode(BG_AV_Nodes node) -{ - uint32 owner = m_Nodes[node].Owner; - assert(owner); - - uint32 c_place = AV_CPLACE_DEFENSE_STORM_AID + (4 * node); - uint32 creatureid; - if (IsTower(node)) - creatureid=(owner == ALLIANCE)?AV_NPC_A_TOWERDEFENSE:AV_NPC_H_TOWERDEFENSE; - else - { - uint8 team2 = GetTeamIndexByTeamId(owner); - if (m_Team_QuestStatus[team2][0] < 500) - creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE0 : AV_NPC_H_GRAVEDEFENSE0; - else if (m_Team_QuestStatus[team2][0] < 1000) - creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE1 : AV_NPC_H_GRAVEDEFENSE1; - else if (m_Team_QuestStatus[team2][0] < 1500) - creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE2 : AV_NPC_H_GRAVEDEFENSE2; - else - creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE3 : AV_NPC_H_GRAVEDEFENSE3; - //spiritguide - if (m_BgCreatures[node]) - DelCreature(node); - if (!AddSpiritGuide(node, BG_AV_CreaturePos[node][0], BG_AV_CreaturePos[node][1], BG_AV_CreaturePos[node][2], BG_AV_CreaturePos[node][3], owner)) - sLog.outError("AV: couldn't spawn spiritguide at node %i",node); - - } - for (uint8 i=0; i<4; i++) - AddAVCreature(creatureid,c_place+i); - - if (node >= BG_AV_NODES_MAX)//fail safe - return; - Creature* trigger = GetBGCreature(node + 302);//0-302 other creatures - if (!trigger) - trigger = AddCreature(WORLD_TRIGGER,node + 302,owner,BG_AV_CreaturePos[node + 302][0],BG_AV_CreaturePos[node + 302][1],BG_AV_CreaturePos[node + 302][2],BG_AV_CreaturePos[node + 302][3]); - - //add bonus honor aura trigger creature when node is accupied - //cast bonus aura (+50% honor in 25yards) - //aura should only apply to players who have accupied the node, set correct faction for trigger - if (trigger) - { - if (owner != ALLIANCE && owner != HORDE)//node can be neutral, remove trigger - { - DelCreature(node + 302); - return; - } - trigger->setFaction(owner == ALLIANCE ? 84 : 83); - trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); - } -} -void BattleGroundAV::DePopulateNode(BG_AV_Nodes node) -{ - uint32 c_place = AV_CPLACE_DEFENSE_STORM_AID + (4 * node); - for (uint8 i=0; i<4; i++) - if (m_BgCreatures[c_place+i]) - DelCreature(c_place+i); - //spiritguide - if (!IsTower(node) && m_BgCreatures[node]) - DelCreature(node); - - //remove bonus honor aura trigger creature when node is lost - if(node < BG_AV_NODES_MAX)//fail safe - DelCreature(node + 302);//NULL checks are in DelCreature! 0-302 spirit guides -} - -const BG_AV_Nodes BattleGroundAV::GetNodeThroughObject(uint32 object) -{ - sLog.outDebug("bg_AV getnodethroughobject %i",object); - if (object <= BG_AV_OBJECT_FLAG_A_STONEHEART_BUNKER) - return BG_AV_Nodes(object); - if (object <= BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_HUT) - return BG_AV_Nodes(object - 11); - if (object <= BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_WTOWER) - return BG_AV_Nodes(object - 7); - if (object <= BG_AV_OBJECT_FLAG_C_H_STONEHEART_BUNKER) - return BG_AV_Nodes(object -22); - if (object <= BG_AV_OBJECT_FLAG_H_FROSTWOLF_HUT) - return BG_AV_Nodes(object - 33); - if (object <= BG_AV_OBJECT_FLAG_H_FROSTWOLF_WTOWER) - return BG_AV_Nodes(object - 29); - if (object == BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE) - return BG_AV_NODES_SNOWFALL_GRAVE; - sLog.outError("BattleGroundAV: ERROR! GetPlace got a wrong object :("); - assert(false); - return BG_AV_Nodes(0); -} - -const uint32 BattleGroundAV::GetObjectThroughNode(BG_AV_Nodes node) -{ //this function is the counterpart to GetNodeThroughObject() - sLog.outDebug("bg_AV GetObjectThroughNode %i",node); - if (m_Nodes[node].Owner == ALLIANCE) - { - if (m_Nodes[node].State == POINT_ASSAULTED) - { - if (node <= BG_AV_NODES_FROSTWOLF_HUT) - return node+11; - if (node >= BG_AV_NODES_ICEBLOOD_TOWER && node <= BG_AV_NODES_FROSTWOLF_WTOWER) - return node+7; - } - else if (m_Nodes[node].State == POINT_CONTROLED) - if (node <= BG_AV_NODES_STONEHEART_BUNKER) - return node; - } - else if (m_Nodes[node].Owner == HORDE) - { - if (m_Nodes[node].State == POINT_ASSAULTED) - if (node <= BG_AV_NODES_STONEHEART_BUNKER) - return node+22; - else if (m_Nodes[node].State == POINT_CONTROLED) - { - if (node <= BG_AV_NODES_FROSTWOLF_HUT) - return node+33; - if (node >= BG_AV_NODES_ICEBLOOD_TOWER && node <= BG_AV_NODES_FROSTWOLF_WTOWER) - return node+29; - } - } - else if (m_Nodes[node].Owner == AV_NEUTRAL_TEAM) - return BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE; - sLog.outError("BattleGroundAV: Error! GetPlaceNode couldn't resolve node %i",node); - assert(false); - return 0; -} - -//called when using banner - -void BattleGroundAV::EventPlayerClickedOnFlag(Player *source, GameObject* target_obj) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - int32 object = GetObjectType(target_obj->GetGUID()); - sLog.outDebug("BG_AV using gameobject %i with type %i",target_obj->GetEntry(),object); - if (object < 0) - return; - switch(target_obj->GetEntry()) - { - case BG_AV_OBJECTID_BANNER_A: - case BG_AV_OBJECTID_BANNER_A_B: - case BG_AV_OBJECTID_BANNER_H: - case BG_AV_OBJECTID_BANNER_H_B: - case BG_AV_OBJECTID_BANNER_SNOWFALL_N: - EventPlayerAssaultsPoint(source, object); - break; - case BG_AV_OBJECTID_BANNER_CONT_A: - case BG_AV_OBJECTID_BANNER_CONT_A_B: - case BG_AV_OBJECTID_BANNER_CONT_H: - case BG_AV_OBJECTID_BANNER_CONT_H_B: - EventPlayerDefendsPoint(source, object); - break; - default: - break; - } -} - -void BattleGroundAV::EventPlayerDefendsPoint(Player* player, uint32 object) -{ - assert(GetStatus() == STATUS_IN_PROGRESS); - BG_AV_Nodes node = GetNodeThroughObject(object); - - uint32 owner = m_Nodes[node].Owner; //maybe should name it prevowner - uint32 team = player->GetTeam(); - - if (owner == player->GetTeam() || m_Nodes[node].State != POINT_ASSAULTED) - return; - if (m_Nodes[node].TotalOwner == AV_NEUTRAL_TEAM) - { //until snowfall doesn't belong to anyone it is better handled in assault-code - assert(node == BG_AV_NODES_SNOWFALL_GRAVE); //currently the only neutral grave - EventPlayerAssaultsPoint(player,object); - return; - } - sLog.outDebug("player defends point object: %i node: %i",object,node); - if (m_Nodes[node].PrevOwner != team) - { - sLog.outError("BG_AV: player defends point which doesn't belong to his team %i",node); - return; - } - - //spawn new go :) - if (m_Nodes[node].Owner == ALLIANCE) - SpawnBGObject(object+22, RESPAWN_IMMEDIATELY); //spawn horde banner - else - SpawnBGObject(object-22, RESPAWN_IMMEDIATELY); //spawn alliance banner - - if (!IsTower(node)) - { - SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node,RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+GetTeamIndexByTeamId(team)+3*node,RESPAWN_IMMEDIATELY); - } - // despawn old go - SpawnBGObject(object, RESPAWN_ONE_DAY); - - DefendNode(node,team); - PopulateNode(node); - UpdateNodeWorldState(node); - - if (IsTower(node)) - { - //spawn big flag+aura on top of tower - SpawnBGObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == ALLIANCE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == HORDE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == ALLIANCE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == HORDE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - } - else if (node == BG_AV_NODES_SNOWFALL_GRAVE) //snowfall eyecandy - { - for (uint8 i = 0; i < 4; i++) - { - SpawnBGObject(((owner == ALLIANCE)?BG_AV_OBJECT_SNOW_EYECANDY_PA : BG_AV_OBJECT_SNOW_EYECANDY_PH)+i,RESPAWN_ONE_DAY); - SpawnBGObject(((team == ALLIANCE)?BG_AV_OBJECT_SNOW_EYECANDY_A : BG_AV_OBJECT_SNOW_EYECANDY_H)+i,RESPAWN_IMMEDIATELY); - } - } - //send a nice message to all :) - char buf[256]; - sprintf(buf, GetTrinityString((IsTower(node)) ? LANG_BG_AV_TOWER_DEFENDED : LANG_BG_AV_GRAVE_DEFENDED), GetNodeName(node),(team == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) : GetTrinityString(LANG_BG_AV_HORDE)); - Creature* creature = GetBGCreature(AV_CPLACE_HERALD); - if (creature) - YellToAll(creature,buf,LANG_UNIVERSAL); - //update the statistic for the defending player - UpdatePlayerScore(player, (IsTower(node)) ? SCORE_TOWERS_DEFENDED : SCORE_GRAVEYARDS_DEFENDED, 1); - if (IsTower(node)) - PlaySoundToAll(AV_SOUND_BOTH_TOWER_DEFEND); - else - PlaySoundToAll((team == ALLIANCE)?AV_SOUND_ALLIANCE_GOOD:AV_SOUND_HORDE_GOOD); -} - -void BattleGroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object) -{ - assert(GetStatus() == STATUS_IN_PROGRESS); - - BG_AV_Nodes node = GetNodeThroughObject(object); - uint32 owner = m_Nodes[node].Owner; //maybe name it prevowner - uint32 team = player->GetTeam(); - sLog.outDebug("bg_av: player assaults point object %i node %i",object,node); - if (owner == team || team == m_Nodes[node].TotalOwner) - return; //surely a gm used this object - - if (node == BG_AV_NODES_SNOWFALL_GRAVE) //snowfall is a bit special in capping + it gets eyecandy stuff - { - if (object == BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE) //initial capping - { - assert(owner == AV_NEUTRAL_TEAM && m_Nodes[node].TotalOwner == AV_NEUTRAL_TEAM); - if (team == ALLIANCE) - SpawnBGObject(BG_AV_OBJECT_FLAG_C_A_SNOWFALL_GRAVE, RESPAWN_IMMEDIATELY); - else - SpawnBGObject(BG_AV_OBJECT_FLAG_C_H_SNOWFALL_GRAVE, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node,RESPAWN_IMMEDIATELY); //neutral aura spawn - } - else if (m_Nodes[node].TotalOwner == AV_NEUTRAL_TEAM) //recapping, when no team owns this node realy - { - assert(m_Nodes[node].State != POINT_CONTROLED); - if (team == ALLIANCE) - SpawnBGObject(object-11, RESPAWN_IMMEDIATELY); - else - SpawnBGObject(object+11, RESPAWN_IMMEDIATELY); - } - //eyecandy - uint32 spawn,despawn; - if (team == ALLIANCE) - { - despawn = (m_Nodes[node].State == POINT_ASSAULTED)?BG_AV_OBJECT_SNOW_EYECANDY_PH : BG_AV_OBJECT_SNOW_EYECANDY_H; - spawn = BG_AV_OBJECT_SNOW_EYECANDY_PA; - } - else - { - despawn = (m_Nodes[node].State == POINT_ASSAULTED)?BG_AV_OBJECT_SNOW_EYECANDY_PA : BG_AV_OBJECT_SNOW_EYECANDY_A; - spawn = BG_AV_OBJECT_SNOW_EYECANDY_PH; - } - for (uint8 i = 0; i < 4; i++) - { - SpawnBGObject(despawn+i,RESPAWN_ONE_DAY); - SpawnBGObject(spawn+i,RESPAWN_IMMEDIATELY); - } - } - - //if snowfall gots capped it can be handled like all other graveyards - if (m_Nodes[node].TotalOwner != AV_NEUTRAL_TEAM) - { - assert(m_Nodes[node].Owner != AV_NEUTRAL_TEAM); - if (team == ALLIANCE) - SpawnBGObject(object-22, RESPAWN_IMMEDIATELY); - else - SpawnBGObject(object+22, RESPAWN_IMMEDIATELY); - if (IsTower(node)) - { //spawning/despawning of bigflag+aura - SpawnBGObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == ALLIANCE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == HORDE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == ALLIANCE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - SpawnBGObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == HORDE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); - } - else - { - //spawning/despawning of aura - SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node,RESPAWN_IMMEDIATELY); //neutral aura spawn - SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+GetTeamIndexByTeamId(owner)+3*node,RESPAWN_ONE_DAY); //teeamaura despawn - // Those who are waiting to resurrect at this object are taken to the closest own object's graveyard - std::vector ghost_list = m_ReviveQueue[m_BgCreatures[node]]; - if (!ghost_list.empty()) - { - Player *plr; - WorldSafeLocsEntry const *ClosestGrave = NULL; - for (std::vector::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) - { - plr = objmgr.GetPlayer(*ghost_list.begin()); - if (!plr) - continue; - if (!ClosestGrave) - ClosestGrave = GetClosestGraveYard(plr); - else - plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); - } - m_ReviveQueue[m_BgCreatures[node]].clear(); - } - } - DePopulateNode(node); - } - - SpawnBGObject(object, RESPAWN_ONE_DAY); //delete old banner - AssaultNode(node,team); - UpdateNodeWorldState(node); - - //send a nice message to all :) - char buf[256]; - sprintf(buf, (IsTower(node)) ? GetTrinityString(LANG_BG_AV_TOWER_ASSAULTED) : GetTrinityString(LANG_BG_AV_GRAVE_ASSAULTED), GetNodeName(node), (team == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) : GetTrinityString(LANG_BG_AV_HORDE)); - Creature* creature = GetBGCreature(AV_CPLACE_HERALD); - if (creature) - YellToAll(creature,buf,LANG_UNIVERSAL); - //update the statistic for the assaulting player - UpdatePlayerScore(player, (IsTower(node)) ? SCORE_TOWERS_ASSAULTED : SCORE_GRAVEYARDS_ASSAULTED, 1); - PlaySoundToAll((team == ALLIANCE)?AV_SOUND_ALLIANCE_ASSAULTS:AV_SOUND_HORDE_ASSAULTS); -} - -void BattleGroundAV::FillInitialWorldStates(WorldPacket& data) -{ - bool stateok; - //graveyards - for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; i++) - { - for (uint8 j =1; j <= 3; j+=2) - {//j=1=assaulted j=3=controled - stateok = (m_Nodes[i].State == j); - data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j,ALLIANCE)]) << uint32((m_Nodes[i].Owner == ALLIANCE && stateok)?1:0); - data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j,HORDE)]) << uint32((m_Nodes[i].Owner == HORDE && stateok)?1:0); - } - } - - //towers - for (uint8 i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_MAX; i++) - for (uint8 j =1; j <= 3; j+=2) - {//j=1=assaulted j=3=controled //i dont have j=2=destroyed cause destroyed is the same like enemy-team controll - stateok = (m_Nodes[i].State == j || (m_Nodes[i].State == POINT_DESTROYED && j == 3)); - data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j,ALLIANCE)]) << uint32((m_Nodes[i].Owner == ALLIANCE && stateok)?1:0); - data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j,HORDE)]) << uint32((m_Nodes[i].Owner == HORDE && stateok)?1:0); - } - if (m_Nodes[BG_AV_NODES_SNOWFALL_GRAVE].Owner == AV_NEUTRAL_TEAM) //cause neutral teams aren't handled generic - data << uint32(AV_SNOWFALL_N) << uint32(1); - data << uint32(AV_Alliance_Score) << uint32(m_Team_Scores[0]); - data << uint32(AV_Horde_Score) << uint32(m_Team_Scores[1]); - if (GetStatus() == STATUS_IN_PROGRESS){ //only if game started the teamscores are displayed - data << uint32(AV_SHOW_A_SCORE) << uint32(1); - data << uint32(AV_SHOW_H_SCORE) << uint32(1); - } - else - { - data << uint32(AV_SHOW_A_SCORE) << uint32(0); - data << uint32(AV_SHOW_H_SCORE) << uint32(0); - } - SendMineWorldStates(AV_NORTH_MINE); - SendMineWorldStates(AV_SOUTH_MINE); -} - -const uint8 BattleGroundAV::GetWorldStateType(uint8 state, uint16 team) //this is used for node worldstates and returns values which fit good into the worldstatesarray -{ - //neutral stuff cant get handled (currently its only snowfall) - assert(team != AV_NEUTRAL_TEAM); - //a_c a_a h_c h_a the positions in worldstate-array - if (team == ALLIANCE) - { - if (state == POINT_CONTROLED || state == POINT_DESTROYED) - return 0; - if (state == POINT_ASSAULTED) - return 1; - } - if (team == HORDE) - { - if (state == POINT_DESTROYED || state == POINT_CONTROLED) - return 2; - if (state == POINT_ASSAULTED) - return 3; - } - sLog.outError("BG_AV: should update a strange worldstate state:%i team:%i",state,team); - return 5; //this will crash the game, but i want to know if something is wrong here -} - -void BattleGroundAV::UpdateNodeWorldState(BG_AV_Nodes node) -{ - UpdateWorldState(BG_AV_NodeWorldStates[node][GetWorldStateType(m_Nodes[node].State,m_Nodes[node].Owner)],1); - if (m_Nodes[node].PrevOwner == AV_NEUTRAL_TEAM) //currently only snowfall is supported as neutral node (i don't want to make an extra row (neutral states) in worldstatesarray just for one node - UpdateWorldState(AV_SNOWFALL_N,0); - else - UpdateWorldState(BG_AV_NodeWorldStates[node][GetWorldStateType(m_Nodes[node].PrevState,m_Nodes[node].PrevOwner)],0); -} - -void BattleGroundAV::SendMineWorldStates(uint32 mine) -{ - assert(mine == AV_NORTH_MINE || mine == AV_SOUTH_MINE); -// currently i'm sure, that this works (: -// assert(m_Mine_PrevOwner[mine] == ALLIANCE || m_Mine_PrevOwner[mine] == HORDE || m_Mine_PrevOwner[mine] == AV_NEUTRAL_TEAM); -// assert(m_Mine_Owner[mine] == ALLIANCE || m_Mine_Owner[mine] == HORDE || m_Mine_Owner[mine] == AV_NEUTRAL_TEAM); - - uint8 owner,prevowner,mine2; //those variables are needed to access the right worldstate in the BG_AV_MineWorldStates array - mine2 = (mine == AV_NORTH_MINE)?0:1; - if (m_Mine_PrevOwner[mine] == ALLIANCE) - prevowner = 0; - else if (m_Mine_PrevOwner[mine] == HORDE) - prevowner = 2; - else - prevowner = 1; - if (m_Mine_Owner[mine] == ALLIANCE) - owner = 0; - else if (m_Mine_Owner[mine] == HORDE) - owner = 2; - else - owner = 1; - - UpdateWorldState(BG_AV_MineWorldStates[mine2][owner],1); - if (prevowner != owner) - UpdateWorldState(BG_AV_MineWorldStates[mine2][prevowner],0); -} - -WorldSafeLocsEntry const* BattleGroundAV::GetClosestGraveYard(Player* player) -{ - WorldSafeLocsEntry const* pGraveyard = NULL; - WorldSafeLocsEntry const* entry = NULL; - float dist = 0; - float minDist = 0; - float x, y; - - player->GetPosition(x, y); - - pGraveyard = sWorldSafeLocsStore.LookupEntry(BG_AV_GraveyardIds[GetTeamIndexByTeamId(player->GetTeam())+7]); - minDist = (pGraveyard->x - x)*(pGraveyard->x - x)+(pGraveyard->y - y)*(pGraveyard->y - y); - - for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) - if (m_Nodes[i].Owner == player->GetTeam() && m_Nodes[i].State == POINT_CONTROLED) - { - entry = sWorldSafeLocsStore.LookupEntry(BG_AV_GraveyardIds[i]); - if (entry) - { - dist = (entry->x - x)*(entry->x - x)+(entry->y - y)*(entry->y - y); - if (dist < minDist) - { - minDist = dist; - pGraveyard = entry; - } - } - } - return pGraveyard; -} - -bool BattleGroundAV::SetupBattleGround() -{ - // Create starting objects - if ( - // alliance gates - !AddObject(BG_AV_OBJECT_DOOR_A, BG_AV_OBJECTID_GATE_A, BG_AV_DoorPositons[0][0],BG_AV_DoorPositons[0][1],BG_AV_DoorPositons[0][2],BG_AV_DoorPositons[0][3],0,0,sin(BG_AV_DoorPositons[0][3]/2),cos(BG_AV_DoorPositons[0][3]/2),RESPAWN_IMMEDIATELY) - // horde gates - || !AddObject(BG_AV_OBJECT_DOOR_H, BG_AV_OBJECTID_GATE_H, BG_AV_DoorPositons[1][0],BG_AV_DoorPositons[1][1],BG_AV_DoorPositons[1][2],BG_AV_DoorPositons[1][3],0,0,sin(BG_AV_DoorPositons[1][3]/2),cos(BG_AV_DoorPositons[1][3]/2),RESPAWN_IMMEDIATELY)) - { - sLog.outErrorDb("BatteGroundAV: Failed to spawn some object BattleGround not created!1"); - return false; - } - - //spawn node-objects - for (uint8 i = BG_AV_NODES_FIRSTAID_STATION ; i < BG_AV_NODES_MAX; ++i) - { - if (i <= BG_AV_NODES_FROSTWOLF_HUT) - { - if (!AddObject(i,BG_AV_OBJECTID_BANNER_A_B,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(i+11,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(i+33,BG_AV_OBJECTID_BANNER_H_B,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(i+22,BG_AV_OBJECTID_BANNER_CONT_H_B,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - //aura - || !AddObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+i*3,BG_AV_OBJECTID_AURA_N,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+i*3,BG_AV_OBJECTID_AURA_A,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_AURA_H_FIRSTAID_STATION+i*3,BG_AV_OBJECTID_AURA_H,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!2"); - return false; - } - } - else //towers - { - if (i <= BG_AV_NODES_STONEHEART_BUNKER) //alliance towers - { - if (!AddObject(i,BG_AV_OBJECTID_BANNER_A,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(i+22,BG_AV_OBJECTID_BANNER_CONT_H,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_AURA_A,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_AURA_N,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_TOWER_BANNER_A,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_TOWER_BANNER_PH,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!3"); - return false; - } - } - else //horde towers - { - if (!AddObject(i+7,BG_AV_OBJECTID_BANNER_CONT_A,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(i+29,BG_AV_OBJECTID_BANNER_H,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_AURA_N,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_AURA_H,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_TOWER_BANNER_PA,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_TOWER_BANNER_H,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!4"); - return false; - } - } - for (uint8 j=0; j <= 9; j++) //burning aura - { - if (!AddObject(BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j,BG_AV_OBJECTID_FIRE,BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][0],BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][1],BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][2],BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3]/2),RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!5.%i",i); - return false; - } - } - } - } - for (uint8 i=0; i<2; i++) //burning aura for buildings - { - for (uint8 j=0; j <= 9; j++) - { - if (j<5) - { - if (!AddObject(BG_AV_OBJECT_BURN_BUILDING_ALLIANCE+(i*10)+j,BG_AV_OBJECTID_SMOKE,BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][0],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][1],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][2],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2),RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!6.%i",i); - return false; - } - } - else - { - if (!AddObject(BG_AV_OBJECT_BURN_BUILDING_ALLIANCE+(i*10)+j,BG_AV_OBJECTID_FIRE,BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][0],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][1],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][2],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2),RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!7.%i",i); - return false; - } - } - } - } - for (uint16 i= 0; i <= (BG_AV_OBJECT_MINE_SUPPLY_N_MAX-BG_AV_OBJECT_MINE_SUPPLY_N_MIN); i++) - { - if (!AddObject(BG_AV_OBJECT_MINE_SUPPLY_N_MIN+i,BG_AV_OBJECTID_MINE_N,BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][0],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][1],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][2],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3]/2),RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some mine supplies BattleGround not created!7.5.%i",i); - return false; - } - } - for (uint16 i= 0 ; i <= (BG_AV_OBJECT_MINE_SUPPLY_S_MAX-BG_AV_OBJECT_MINE_SUPPLY_S_MIN); i++) - { - if (!AddObject(BG_AV_OBJECT_MINE_SUPPLY_S_MIN+i,BG_AV_OBJECTID_MINE_S,BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][0],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][1],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][2],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3]/2),RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some mine supplies BattleGround not created!7.6.%i",i); - return false; - } - } - - if (!AddObject(BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE, BG_AV_OBJECTID_BANNER_SNOWFALL_N ,BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][0],BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][1],BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][2],BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3],0,0,sin(BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3]/2), cos(BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3]/2), RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!8"); - return false; - } - for (uint8 i = 0; i < 4; i++) - { - if (!AddObject(BG_AV_OBJECT_SNOW_EYECANDY_A+i, BG_AV_OBJECTID_SNOWFALL_CANDY_A ,BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],0,0,sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_PA+i, BG_AV_OBJECTID_SNOWFALL_CANDY_PA ,BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],0,0,sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_H+i, BG_AV_OBJECTID_SNOWFALL_CANDY_H ,BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],0,0,sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY) - || !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_PH+i, BG_AV_OBJECTID_SNOWFALL_CANDY_PH ,BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],0,0,sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY)) - { - sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!9.%i",i); - return false; - } - } - - uint16 i; - sLog.outDebug("Alterac Valley: entering state STATUS_WAIT_JOIN ..."); - // Initial Nodes - for (i = 0; i < BG_AV_OBJECT_MAX; i++) - SpawnBGObject(i, RESPAWN_ONE_DAY); - for (i = BG_AV_OBJECT_FLAG_A_FIRSTAID_STATION; i <= BG_AV_OBJECT_FLAG_A_STONEHEART_GRAVE ; i++){ - SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+3*i,RESPAWN_IMMEDIATELY); - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - } - for (i = BG_AV_OBJECT_FLAG_A_DUNBALDAR_SOUTH; i <= BG_AV_OBJECT_FLAG_A_STONEHEART_BUNKER ; i++) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - for (i = BG_AV_OBJECT_FLAG_H_ICEBLOOD_GRAVE; i <= BG_AV_OBJECT_FLAG_H_FROSTWOLF_WTOWER ; i++){ - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - if (i <= BG_AV_OBJECT_FLAG_H_FROSTWOLF_HUT) - SpawnBGObject(BG_AV_OBJECT_AURA_H_FIRSTAID_STATION+3*GetNodeThroughObject(i),RESPAWN_IMMEDIATELY); - } - for (i = BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH; i <= BG_AV_OBJECT_TFLAG_A_STONEHEART_BUNKER; i+=2) - { - SpawnBGObject(i, RESPAWN_IMMEDIATELY); //flag - SpawnBGObject(i+16, RESPAWN_IMMEDIATELY); //aura - } - for (i = BG_AV_OBJECT_TFLAG_H_ICEBLOOD_TOWER; i <= BG_AV_OBJECT_TFLAG_H_FROSTWOLF_WTOWER; i+=2) - { - SpawnBGObject(i, RESPAWN_IMMEDIATELY); //flag - SpawnBGObject(i+16, RESPAWN_IMMEDIATELY); //aura - } - //snowfall and the doors - for (i = BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE; i <= BG_AV_OBJECT_DOOR_A; i++) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_AV_OBJECT_AURA_N_SNOWFALL_GRAVE,RESPAWN_IMMEDIATELY); - - //creatures - sLog.outDebug("BG_AV start poputlating nodes"); - for (BG_AV_Nodes i= BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i) - { - if (m_Nodes[i].Owner) - PopulateNode(i); - } - //all creatures which don't get despawned through the script are static - sLog.outDebug("BG_AV: start spawning static creatures"); - for (i=0; i < AV_STATICCPLACE_MAX; i++) - AddAVCreature(0,i+AV_CPLACE_MAX); - //mainspiritguides: - sLog.outDebug("BG_AV: start spawning spiritguides creatures"); - AddSpiritGuide(7, BG_AV_CreaturePos[7][0], BG_AV_CreaturePos[7][1], BG_AV_CreaturePos[7][2], BG_AV_CreaturePos[7][3], ALLIANCE); - AddSpiritGuide(8, BG_AV_CreaturePos[8][0], BG_AV_CreaturePos[8][1], BG_AV_CreaturePos[8][2], BG_AV_CreaturePos[8][3], HORDE); - //spawn the marshals (those who get deleted, if a tower gets destroyed) - sLog.outDebug("BG_AV: start spawning marshal creatures"); - for (i=AV_NPC_A_MARSHAL_SOUTH; i <= AV_NPC_H_MARSHAL_WTOWER; i++) - AddAVCreature(i,AV_CPLACE_A_MARSHAL_SOUTH+(i-AV_NPC_A_MARSHAL_SOUTH)); - AddAVCreature(AV_NPC_HERALD,AV_CPLACE_HERALD); - return true; -} - -const char* BattleGroundAV::GetNodeName(BG_AV_Nodes node) -{ - switch (node) - { - case BG_AV_NODES_FIRSTAID_STATION: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_STORM_AID); - case BG_AV_NODES_DUNBALDAR_SOUTH: return GetTrinityString(LANG_BG_AV_NODE_TOWER_DUN_S); - case BG_AV_NODES_DUNBALDAR_NORTH: return GetTrinityString(LANG_BG_AV_NODE_TOWER_DUN_N); - case BG_AV_NODES_STORMPIKE_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_STORMPIKE); - case BG_AV_NODES_ICEWING_BUNKER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_ICEWING); - case BG_AV_NODES_STONEHEART_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_STONE); - case BG_AV_NODES_STONEHEART_BUNKER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_STONE); - case BG_AV_NODES_SNOWFALL_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_SNOW); - case BG_AV_NODES_ICEBLOOD_TOWER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_ICE); - case BG_AV_NODES_ICEBLOOD_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_ICE); - case BG_AV_NODES_TOWER_POINT: return GetTrinityString(LANG_BG_AV_NODE_TOWER_POINT); - case BG_AV_NODES_FROSTWOLF_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_FROST); - case BG_AV_NODES_FROSTWOLF_ETOWER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_FROST_E); - case BG_AV_NODES_FROSTWOLF_WTOWER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_FROST_W); - case BG_AV_NODES_FROSTWOLF_HUT: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_FROST_HUT); - default: - { - sLog.outError("tried to get name for node %u%",node); - return "Unknown"; - break; - } - } -} - -void BattleGroundAV::AssaultNode(BG_AV_Nodes node, uint16 team) -{ - if (m_Nodes[node].TotalOwner == team) - { - sLog.outCrash("Assaulting team is TotalOwner of node"); - assert (false); - } - if (m_Nodes[node].Owner == team) - { - sLog.outCrash("Assaulting team is owner of node"); - assert (false); - } - if (m_Nodes[node].State == POINT_DESTROYED) - { - sLog.outCrash("Destroyed node is being assaulted"); - assert (false); - } - if (m_Nodes[node].State == POINT_ASSAULTED && m_Nodes[node].TotalOwner) //only assault an assaulted node if no totalowner exists - { - sLog.outCrash("Assault on an not assaulted node with total owner"); - assert (false); - } - //the timer gets another time, if the previous owner was 0 == Neutral - m_Nodes[node].Timer = (m_Nodes[node].PrevOwner)? BG_AV_CAPTIME : BG_AV_SNOWFALL_FIRSTCAP; - m_Nodes[node].PrevOwner = m_Nodes[node].Owner; - m_Nodes[node].Owner = team; - m_Nodes[node].PrevState = m_Nodes[node].State; - m_Nodes[node].State = POINT_ASSAULTED; -} - -void BattleGroundAV::DestroyNode(BG_AV_Nodes node) -{ - assert(m_Nodes[node].State == POINT_ASSAULTED); - - m_Nodes[node].TotalOwner = m_Nodes[node].Owner; - m_Nodes[node].PrevOwner = m_Nodes[node].Owner; - m_Nodes[node].PrevState = m_Nodes[node].State; - m_Nodes[node].State = (m_Nodes[node].Tower)? POINT_DESTROYED : POINT_CONTROLED; - m_Nodes[node].Timer = 0; -} - -void BattleGroundAV::InitNode(BG_AV_Nodes node, uint16 team, bool tower) -{ - m_Nodes[node].TotalOwner = team; - m_Nodes[node].Owner = team; - m_Nodes[node].PrevOwner = 0; - m_Nodes[node].State = POINT_CONTROLED; - m_Nodes[node].PrevState = m_Nodes[node].State; - m_Nodes[node].State = POINT_CONTROLED; - m_Nodes[node].Timer = 0; - m_Nodes[node].Tower = tower; -} - -void BattleGroundAV::DefendNode(BG_AV_Nodes node, uint16 team) -{ - assert(m_Nodes[node].TotalOwner == team); - assert(m_Nodes[node].Owner != team); - assert(m_Nodes[node].State != POINT_CONTROLED && m_Nodes[node].State != POINT_DESTROYED); - m_Nodes[node].PrevOwner = m_Nodes[node].Owner; - m_Nodes[node].Owner = team; - m_Nodes[node].PrevState = m_Nodes[node].State; - m_Nodes[node].State = POINT_CONTROLED; - m_Nodes[node].Timer = 0; -} - -void BattleGroundAV::ResetBGSubclass() -{ - m_MaxLevel=0; - for (uint8 i=0; i<2; i++) //forloop for both teams (it just make 0 == alliance and 1 == horde also for both mines 0=north 1=south - { - for (uint8 j=0; j<9; j++) - m_Team_QuestStatus[i][j]=0; - m_Team_Scores[i]=BG_AV_SCORE_INITIAL_POINTS; - m_IsInformedNearVictory[i]=false; - m_CaptainAlive[i] = true; - m_CaptainBuffTimer[i] = 120000 + urand(0,4)* 60; //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes TODO get the right times - m_Mine_Owner[i] = AV_NEUTRAL_TEAM; - m_Mine_PrevOwner[i] = m_Mine_Owner[i]; - } - for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_STONEHEART_GRAVE; ++i) //alliance graves - InitNode(i,ALLIANCE,false); - for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) //alliance towers - InitNode(i,ALLIANCE,true); - for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_GRAVE; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) //horde graves - InitNode(i,HORDE,false); - for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) //horde towers - InitNode(i,HORDE,true); - InitNode(BG_AV_NODES_SNOWFALL_GRAVE,AV_NEUTRAL_TEAM,false); //give snowfall neutral owner - - m_Mine_Timer=AV_MINE_TICK_TIMER; - for (uint16 i = 0; i < AV_CPLACE_MAX+AV_STATICCPLACE_MAX; i++) - if (m_BgCreatures[i]) - DelCreature(i); - -} - - diff --git a/src/server/game/BattleGrounds/BattleGroundAV.h b/src/server/game/BattleGrounds/BattleGroundAV.h deleted file mode 100644 index 6d95c7bbc5d..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundAV.h +++ /dev/null @@ -1,1614 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __BATTLEGROUNDAV_H -#define __BATTLEGROUNDAV_H - -class BattleGround; - -#define LANG_BG_AV_A_CAPTAIN_BUFF "Begone. Uncouth scum! The Alliance shall prevail in Alterac Valley!" -#define LANG_BG_AV_H_CAPTAIN_BUFF "Now is the time to attack! For the Horde!" -#define LANG_BG_AV_S_MINE_BOSS_CLAIMS "Snivvle is here! Snivvle claims the Coldtooth Mine!" - -#define BG_AV_CAPTIME 240000 //4:00 -#define BG_AV_SNOWFALL_FIRSTCAP 300000 //5:00 but i also have seen 4:05 - -#define BG_AV_SCORE_INITIAL_POINTS 600 -#define SEND_MSG_NEAR_LOSE 120 - -#define BG_AV_KILL_BOSS 4 -#define BG_AV_REP_BOSS 350 - -#define BG_AV_KILL_CAPTAIN 3 -#define BG_AV_REP_CAPTAIN 125 -#define BG_AV_RES_CAPTAIN 100 - -#define BG_AV_KILL_TOWER 3 -#define BG_AV_REP_TOWER 12 -#define BG_AV_RES_TOWER 75 - -#define BG_AV_GET_COMMANDER 1 //for a safely returned wingcommander -//bonushonor at the end -#define BG_AV_KILL_SURVIVING_TOWER 2 -#define BG_AV_REP_SURVIVING_TOWER 12 - -#define BG_AV_KILL_SURVIVING_CAPTAIN 2 -#define BG_AV_REP_SURVIVING_CAPTAIN 125 - -enum BG_AV_Sounds -{ //TODO: get out if there comes a sound when neutral team captures mine - -/* -8212: - alliance grave assault - alliance tower assault - drek "mlanzenabschaum! In meiner Burg?! Toetet sie all" - nicht immer der sound -8333: - galv "sterbt fuer euch ist kein platz hier" - -8332: - bal "Verschwinde, dreckiger Abschaum! Die Allianz wird im Alteractal " -8174: - horde tower assault - horde grave assault - van "es Sturmlanzenklans, euer General wird angegriffen! Ich fordere Unterst" -8173: - ally grave capture/defend - tower destroy - mine capture - ally wins -8192: - ally tower destroy(only iceblood - found a bug^^) - ally tower defend - horde tower defend -8213 -horde: - grave defend/capture - tower destroy - mine capture - horde wins - */ - - AV_SOUND_NEAR_VICTORY = 8456, //not confirmed yet - - AV_SOUND_ALLIANCE_ASSAULTS = 8212, //tower,grave + enemy boss if someone tries to attack him - AV_SOUND_HORDE_ASSAULTS = 8174, - AV_SOUND_ALLIANCE_GOOD = 8173, //if something good happens for the team: wins(maybe only through killing the boss), captures mine or grave, destroys tower and defends grave - AV_SOUND_HORDE_GOOD = 8213, - AV_SOUND_BOTH_TOWER_DEFEND = 8192, - - AV_SOUND_ALLIANCE_CAPTAIN = 8232, //gets called when someone attacks them and at the beginning after 3min+rand(x)*10sec (maybe buff) - AV_SOUND_HORDE_CAPTAIN = 8333, - -}; - -enum BG_AV_OTHER_VALUES -{ - AV_STATICCPLACE_MAX = 123, - 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_NEUTRAL_TEAM = 0 //this is the neutral owner of snowfall -}; -enum BG_AV_ObjectIds -{ - //cause the mangos-system is a bit different, we don't use the right go-ids for every node.. if we want to be 100% like another big server, we must take one object for every node - //snowfall 4flags as eyecandy 179424 (alliance neutral) - //Banners - stolen from battleground_AB.h ;-) - BG_AV_OBJECTID_BANNER_A = 178925, // can only be used by horde - BG_AV_OBJECTID_BANNER_H = 178943, // can only be used by alliance - BG_AV_OBJECTID_BANNER_CONT_A = 178940, // can only be used by horde - BG_AV_OBJECTID_BANNER_CONT_H = 179435, // can only be used by alliance - - BG_AV_OBJECTID_BANNER_A_B = 178365, - BG_AV_OBJECTID_BANNER_H_B = 178364, - BG_AV_OBJECTID_BANNER_CONT_A_B = 179286, - BG_AV_OBJECTID_BANNER_CONT_H_B = 179287, - BG_AV_OBJECTID_BANNER_SNOWFALL_N = 180418, - - //snowfall eyecandy banner: - BG_AV_OBJECTID_SNOWFALL_CANDY_A = 179044, - BG_AV_OBJECTID_SNOWFALL_CANDY_PA = 179424, - BG_AV_OBJECTID_SNOWFALL_CANDY_H = 179064, - BG_AV_OBJECTID_SNOWFALL_CANDY_PH = 179425, - - //banners on top of towers: - BG_AV_OBJECTID_TOWER_BANNER_A = 178927, //[PH] Alliance A1 Tower Banner BIG - BG_AV_OBJECTID_TOWER_BANNER_H = 178955, //[PH] Horde H1 Tower Banner BIG - BG_AV_OBJECTID_TOWER_BANNER_PA = 179446, //[PH] Alliance H1 Tower Pre-Banner BIG - BG_AV_OBJECTID_TOWER_BANNER_PH = 179436, //[PH] Horde A1 Tower Pre-Banner BIG - - //Auras - BG_AV_OBJECTID_AURA_A = 180421, - BG_AV_OBJECTID_AURA_H = 180422, - BG_AV_OBJECTID_AURA_N = 180423, - BG_AV_OBJECTID_AURA_A_S = 180100, - BG_AV_OBJECTID_AURA_H_S = 180101, - BG_AV_OBJECTID_AURA_N_S = 180102, - - BG_AV_OBJECTID_GATE_A = 180424, - BG_AV_OBJECTID_GATE_H = 180424, - - //mine supplies - BG_AV_OBJECTID_MINE_N = 178785, - BG_AV_OBJECTID_MINE_S = 178784, - - BG_AV_OBJECTID_FIRE = 179065, - BG_AV_OBJECTID_SMOKE = 179066 -}; - -enum BG_AV_Nodes -{ - BG_AV_NODES_FIRSTAID_STATION = 0, - BG_AV_NODES_STORMPIKE_GRAVE = 1, - BG_AV_NODES_STONEHEART_GRAVE = 2, - BG_AV_NODES_SNOWFALL_GRAVE = 3, - BG_AV_NODES_ICEBLOOD_GRAVE = 4, - BG_AV_NODES_FROSTWOLF_GRAVE = 5, - BG_AV_NODES_FROSTWOLF_HUT = 6, - BG_AV_NODES_DUNBALDAR_SOUTH = 7, - BG_AV_NODES_DUNBALDAR_NORTH = 8, - BG_AV_NODES_ICEWING_BUNKER = 9, - BG_AV_NODES_STONEHEART_BUNKER = 10, - BG_AV_NODES_ICEBLOOD_TOWER = 11, - BG_AV_NODES_TOWER_POINT = 12, - BG_AV_NODES_FROSTWOLF_ETOWER = 13, - BG_AV_NODES_FROSTWOLF_WTOWER = 14, - - BG_AV_NODES_MAX = 15 -}; - -enum BG_AV_ObjectTypes -{ - BG_AV_OBJECT_FLAG_A_FIRSTAID_STATION = 0, - BG_AV_OBJECT_FLAG_A_STORMPIKE_GRAVE = 1, - BG_AV_OBJECT_FLAG_A_STONEHEART_GRAVE = 2, - BG_AV_OBJECT_FLAG_A_SNOWFALL_GRAVE = 3, - BG_AV_OBJECT_FLAG_A_ICEBLOOD_GRAVE = 4, - BG_AV_OBJECT_FLAG_A_FROSTWOLF_GRAVE = 5, - BG_AV_OBJECT_FLAG_A_FROSTWOLF_HUT = 6, - BG_AV_OBJECT_FLAG_A_DUNBALDAR_SOUTH = 7, - BG_AV_OBJECT_FLAG_A_DUNBALDAR_NORTH = 8, - BG_AV_OBJECT_FLAG_A_ICEWING_BUNKER = 9, - BG_AV_OBJECT_FLAG_A_STONEHEART_BUNKER = 10, - - BG_AV_OBJECT_FLAG_C_A_FIRSTAID_STATION = 11, - BG_AV_OBJECT_FLAG_C_A_STORMPIKE_GRAVE = 12, - BG_AV_OBJECT_FLAG_C_A_STONEHEART_GRAVE = 13, - BG_AV_OBJECT_FLAG_C_A_SNOWFALL_GRAVE = 14, - BG_AV_OBJECT_FLAG_C_A_ICEBLOOD_GRAVE = 15, - BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_GRAVE = 16, - BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_HUT = 17, - BG_AV_OBJECT_FLAG_C_A_ICEBLOOD_TOWER = 18, - BG_AV_OBJECT_FLAG_C_A_TOWER_POINT = 19, - BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_ETOWER = 20, - BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_WTOWER = 21, - - BG_AV_OBJECT_FLAG_C_H_FIRSTAID_STATION = 22, - BG_AV_OBJECT_FLAG_C_H_STORMPIKE_GRAVE = 23, - BG_AV_OBJECT_FLAG_C_H_STONEHEART_GRAVE = 24, - BG_AV_OBJECT_FLAG_C_H_SNOWFALL_GRAVE = 25, - BG_AV_OBJECT_FLAG_C_H_ICEBLOOD_GRAVE = 26, - BG_AV_OBJECT_FLAG_C_H_FROSTWOLF_GRAVE = 27, - BG_AV_OBJECT_FLAG_C_H_FROSTWOLF_HUT = 28, - BG_AV_OBJECT_FLAG_C_H_DUNBALDAR_SOUTH = 29, - BG_AV_OBJECT_FLAG_C_H_DUNBALDAR_NORTH = 30, - BG_AV_OBJECT_FLAG_C_H_ICEWING_BUNKER = 31, - BG_AV_OBJECT_FLAG_C_H_STONEHEART_BUNKER = 32, - - BG_AV_OBJECT_FLAG_H_FIRSTAID_STATION = 33, - BG_AV_OBJECT_FLAG_H_STORMPIKE_GRAVE = 34, - BG_AV_OBJECT_FLAG_H_STONEHEART_GRAVE = 35, - BG_AV_OBJECT_FLAG_H_SNOWFALL_GRAVE = 36, - BG_AV_OBJECT_FLAG_H_ICEBLOOD_GRAVE = 37, - BG_AV_OBJECT_FLAG_H_FROSTWOLF_GRAVE = 38, - BG_AV_OBJECT_FLAG_H_FROSTWOLF_HUT = 39, - BG_AV_OBJECT_FLAG_H_ICEBLOOD_TOWER = 40, - BG_AV_OBJECT_FLAG_H_TOWER_POINT = 41, - BG_AV_OBJECT_FLAG_H_FROSTWOLF_ETOWER = 42, - BG_AV_OBJECT_FLAG_H_FROSTWOLF_WTOWER = 43, - - BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE = 44, - - BG_AV_OBJECT_DOOR_H = 45, - BG_AV_OBJECT_DOOR_A = 46, -//auras for graveyards (3auras per graveyard neutral,alliance,horde) - BG_AV_OBJECT_AURA_N_FIRSTAID_STATION = 47, - BG_AV_OBJECT_AURA_A_FIRSTAID_STATION = 48, - BG_AV_OBJECT_AURA_H_FIRSTAID_STATION = 49, - BG_AV_OBJECT_AURA_N_STORMPIKE_GRAVE = 50, - BG_AV_OBJECT_AURA_A_STORMPIKE_GRAVE = 51, - BG_AV_OBJECT_AURA_H_STORMPIKE_GRAVE = 52, - BG_AV_OBJECT_AURA_N_STONEHEART_GRAVE = 53, - BG_AV_OBJECT_AURA_A_STONEHEART_GRAVE = 54, - BG_AV_OBJECT_AURA_H_STONEHEART_GRAVE = 55, - BG_AV_OBJECT_AURA_N_SNOWFALL_GRAVE = 56, - BG_AV_OBJECT_AURA_A_SNOWFALL_GRAVE = 57, - BG_AV_OBJECT_AURA_H_SNOWFALL_GRAVE = 58, - BG_AV_OBJECT_AURA_N_ICEBLOOD_GRAVE = 59, - BG_AV_OBJECT_AURA_A_ICEBLOOD_GRAVE = 60, - BG_AV_OBJECT_AURA_H_ICEBLOOD_GRAVE = 61, - BG_AV_OBJECT_AURA_N_FROSTWOLF_GRAVE = 62, - BG_AV_OBJECT_AURA_A_FROSTWOLF_GRAVE = 63, - BG_AV_OBJECT_AURA_H_FROSTWOLF_GRAVE = 64, - BG_AV_OBJECT_AURA_N_FROSTWOLF_HUT = 65, - BG_AV_OBJECT_AURA_A_FROSTWOLF_HUT = 66, - BG_AV_OBJECT_AURA_H_FROSTWOLF_HUT = 67, - - //big flags on top of towers 2 flags on each (contested,(alliance | horde)) + 2 auras - BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH = 67, - BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH = 68, - BG_AV_OBJECT_TFLAG_A_DUNBALDAR_NORTH = 69, - BG_AV_OBJECT_TFLAG_H_DUNBALDAR_NORTH = 70, - BG_AV_OBJECT_TFLAG_A_ICEWING_BUNKER = 71, - BG_AV_OBJECT_TFLAG_H_ICEWING_BUNKER = 72, - BG_AV_OBJECT_TFLAG_A_STONEHEART_BUNKER = 73, - BG_AV_OBJECT_TFLAG_H_STONEHEART_BUNKER = 74, - BG_AV_OBJECT_TFLAG_A_ICEBLOOD_TOWER = 75, - BG_AV_OBJECT_TFLAG_H_ICEBLOOD_TOWER = 76, - BG_AV_OBJECT_TFLAG_A_TOWER_POINT = 77, - BG_AV_OBJECT_TFLAG_H_TOWER_POINT = 78, - BG_AV_OBJECT_TFLAG_A_FROSTWOLF_ETOWER = 79, - BG_AV_OBJECT_TFLAG_H_FROSTWOLF_ETOWER = 80, - BG_AV_OBJECT_TFLAG_A_FROSTWOLF_WTOWER = 81, - BG_AV_OBJECT_TFLAG_H_FROSTWOLF_WTOWER = 82, - BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH = 83, - BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH = 84, - BG_AV_OBJECT_TAURA_A_DUNBALDAR_NORTH = 85, - BG_AV_OBJECT_TAURA_H_DUNBALDAR_NORTH = 86, - BG_AV_OBJECT_TAURA_A_ICEWING_BUNKER = 87, - BG_AV_OBJECT_TAURA_H_ICEWING_BUNKER = 88, - BG_AV_OBJECT_TAURA_A_STONEHEART_BUNKER = 89, - BG_AV_OBJECT_TAURA_H_STONEHEART_BUNKER = 90, - BG_AV_OBJECT_TAURA_A_ICEBLOOD_TOWER = 91, - BG_AV_OBJECT_TAURA_H_ICEBLOOD_TOWER = 92, - BG_AV_OBJECT_TAURA_A_TOWER_POINT = 93, - BG_AV_OBJECT_TAURA_H_TOWER_POINT = 94, - BG_AV_OBJECT_TAURA_A_FROSTWOLF_ETOWER = 95, - BG_AV_OBJECT_TAURA_H_FROSTWOLF_ETOWER = 96, - BG_AV_OBJECT_TAURA_A_FROSTWOLF_WTOWER = 97, - BG_AV_OBJECT_TAURA_H_FROSTWOLF_WTOWER = 98, - - BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH = 99, - BG_AV_OBJECT_BURN_DUNBALDAR_NORTH = 109, - BG_AV_OBJECT_BURN_ICEWING_BUNKER = 119, - BG_AV_OBJECT_BURN_STONEHEART_BUNKER = 129, - BG_AV_OBJECT_BURN_ICEBLOOD_TOWER = 139, - BG_AV_OBJECT_BURN_TOWER_POINT = 149, - BG_AV_OBJECT_BURN_FROSTWOLF_ETWOER = 159, - BG_AV_OBJECT_BURN_FROSTWOLF_WTOWER = 169, - BG_AV_OBJECT_BURN_BUILDING_ALLIANCE = 179, - BG_AV_OBJECT_BURN_BUILDING_HORDE = 189, - BG_AV_OBJECT_SNOW_EYECANDY_A = 199, - BG_AV_OBJECT_SNOW_EYECANDY_PA = 203, - BG_AV_OBJECT_SNOW_EYECANDY_H = 207, - BG_AV_OBJECT_SNOW_EYECANDY_PH = 211, - BG_AV_OBJECT_MINE_SUPPLY_N_MIN = 215, - BG_AV_OBJECT_MINE_SUPPLY_N_MAX = 224, - BG_AV_OBJECT_MINE_SUPPLY_S_MIN = 225, - BG_AV_OBJECT_MINE_SUPPLY_S_MAX = 236, - - BG_AV_OBJECT_MAX = 237 -}; - -enum BG_AV_OBJECTS -{ - AV_OPLACE_FIRSTAID_STATION = 0, - AV_OPLACE_STORMPIKE_GRAVE = 1, - AV_OPLACE_STONEHEART_GRAVE = 2, - AV_OPLACE_SNOWFALL_GRAVE = 3, - AV_OPLACE_ICEBLOOD_GRAVE = 4, - AV_OPLACE_FROSTWOLF_GRAVE = 5, - AV_OPLACE_FROSTWOLF_HUT = 6, - AV_OPLACE_DUNBALDAR_SOUTH = 7, - AV_OPLACE_DUNBALDAR_NORTH = 8, - AV_OPLACE_ICEWING_BUNKER = 9, - AV_OPLACE_STONEHEART_BUNKER = 10, - AV_OPLACE_ICEBLOOD_TOWER = 11, - AV_OPLACE_TOWER_POINT = 12, - AV_OPLACE_FROSTWOLF_ETOWER = 13, - AV_OPLACE_FROSTWOLF_WTOWER = 14, - AV_OPLACE_BIGBANNER_DUNBALDAR_SOUTH = 15, - AV_OPLACE_BIGBANNER_DUNBALDAR_NORTH = 16, - AV_OPLACE_BIGBANNER_ICEWING_BUNKER = 17, - AV_OPLACE_BIGBANNER_STONEHEART_BUNKER = 18, - AV_OPLACE_BIGBANNER_ICEBLOOD_TOWER = 19, - AV_OPLACE_BIGBANNER_TOWER_POINT = 20, - AV_OPLACE_BIGBANNER_FROSTWOLF_ETOWER = 21, - AV_OPLACE_BIGBANNER_FROSTWOLF_WTOWER = 22, - - AV_OPLACE_BURN_DUNBALDAR_SOUTH = 23, - AV_OPLACE_BURN_DUNBALDAR_NORTH = 33, - AV_OPLACE_BURN_ICEWING_BUNKER = 43, - AV_OPLACE_BURN_STONEHEART_BUNKER = 53, - AV_OPLACE_BURN_ICEBLOOD_TOWER = 63, - AV_OPLACE_BURN_TOWER_POINT = 73, - AV_OPLACE_BURN_FROSTWOLF_ETOWER = 83, - AV_OPLACE_BURN_FROSTWOLF_WTOWER = 93, - AV_OPLACE_BURN_BUILDING_A = 103, - AV_OPLACE_BURN_BUILDING_H = 113, - AV_OPLACE_SNOW_1 = 123, - AV_OPLACE_SNOW_2 = 124, - AV_OPLACE_SNOW_3 = 125, - AV_OPLACE_SNOW_4 = 126, - AV_OPLACE_MINE_SUPPLY_N_MIN = 127, - AV_OPLACE_MINE_SUPPLY_N_MAX = 136, - AV_OPLACE_MINE_SUPPLY_S_MIN = 137, - AV_OPLACE_MINE_SUPPLY_S_MAX = 148, - - AV_OPLACE_MAX = 149 -}; -const float BG_AV_ObjectPos[AV_OPLACE_MAX][4] = { - {638.592f,-32.422f,46.0608f,-1.62316f },//firstaid station - {669.007f,-294.078f,30.2909f,2.77507f },//stormpike - {77.8013f,-404.7f,46.7549f,-0.872665f },//stone grave - {-202.581f,-112.73f,78.4876f,-0.715585f },//snowfall - {-611.962f,-396.17f,60.8351f,2.53682f}, //iceblood grave - {-1082.45f,-346.823f,54.9219f,-1.53589f },//frostwolf grave - {-1402.21f,-307.431f,89.4424f,0.191986f },//frostwolf hut - {553.779f,-78.6566f,51.9378f,-1.22173f }, //dunnbaldar south - {674.001f,-143.125f,63.6615f,0.994838f }, //dunbaldar north - {203.281f,-360.366f,56.3869f,-0.925024f }, //icew - {-152.437f,-441.758f,40.3982f,-1.95477f }, //stone - {-571.88f,-262.777f,75.0087f,-0.802851f }, //ice tower - {-768.907f,-363.71f,90.8949f,1.07991f}, //tower point - {-1302.9f,-316.981f,113.867f,2.00713f }, //frostwolf etower - {-1297.5f,-266.767f,114.15f,3.31044f}, //frostwolf wtower - //bigbanner: - {555.848f,-84.4151f,64.4397f,3.12414f }, //duns - {679.339f,-136.468f,73.9626f,-2.16421f }, //dunn - {208.973f,-365.971f,66.7409f,-0.244346f }, //icew - {-155.832f,-449.401f,52.7306f,0.610865f }, //stone - {-572.329f,-262.476f,88.6496f,-0.575959f }, //icetower - {-768.199f,-363.105f,104.537f,0.10472f }, //towerp - {-1302.84f,-316.582f,127.516f,0.122173f }, //etower - {-1297.87f,-266.762f,127.796f,0.0698132f }, //wtower - //burning auras towers have 9*179065 captain-buildings have 5*179066+5*179065 - //dunns - {562.632f,-88.1815f,61.993f,0.383972f }, - {562.523f,-74.5028f,37.9474f,-0.0523599f }, - {558.097f,-70.9842f,52.4876f,0.820305f }, - {578.167f,-71.8191f,38.1514f,2.72271f }, - {556.028f,-94.9242f,44.8191f,3.05433f }, - {572.451f,-94.3655f,37.9443f,-1.72788f }, - {549.263f,-79.3645f,44.8191f,0.436332f }, - {543.513f,-94.4006f,52.4819f,0.0349066f }, - {572.149f,-93.7862f,52.5726f,0.541052f }, - {582.162f,-81.2375f,37.9216f,0.0872665f }, - //dunn - {664.797f,-143.65f,64.1784f,-0.453786f}, - {664.505f,-139.452f,49.6696f,-0.0349067f}, - {676.067f,-124.319f,49.6726f,-1.01229f}, - {693.004f,-144.025f,64.1755f,2.44346f}, - {661.175f,-117.691f,49.645f,1.91986f}, - {684.423f,-146.582f,63.6662f,0.994838f}, - {682.791f,-127.769f,62.4155f,1.09956f}, - {674.576f,-147.101f,56.5425f,-1.6057f}, - {655.719f,-126.673f,49.8138f,2.80998f}, - {0,0,0,0}, - //icew - {231.503f,-356.688f,42.3704f,0.296706f}, - {224.989f,-348.175f,42.5607f,1.50098f}, - {205.782f,-351.335f,56.8998f,1.01229f}, - {196.605f,-369.187f,56.3914f,2.46091f}, - {210.619f,-376.938f,49.2677f,2.86234f}, - {209.647f,-352.632f,42.3959f,-0.698132f}, - {220.65f,-368.132f,42.3978f,-0.2618f}, - {224.682f,-374.031f,57.0679f,0.541052f}, - {200.26f,-359.968f,49.2677f,-2.89725f}, - {196.619f,-378.016f,56.9131f,1.01229f}, - //stone - {-155.488f,-437.356f,33.2796f,2.60054f}, - {-163.441f,-454.188f,33.2796f,1.93732f}, - {-143.977f,-445.148f,26.4097f,-1.8675f}, - {-135.764f,-464.708f,26.3823f,2.25147f}, - {-154.076f,-466.929f,41.0636f,-1.8675f}, - {-149.908f,-460.332f,26.4083f,-2.09439f}, - {-151.638f,-439.521f,40.3797f,0.436332f}, - {-131.301f,-454.905f,26.5771f,2.93215f}, - {-171.291f,-444.684f,40.9211f,2.30383f}, - {-143.591f,-439.75f,40.9275f,-1.72788f}, - //iceblood - {-572.667f,-267.923f,56.8542f,2.35619f}, - {-561.021f,-262.689f,68.4589f,1.37881f}, - {-572.538f,-262.649f,88.6197f,1.8326f}, - {-574.77f,-251.45f,74.9422f,-1.18682f}, - {-578.625f,-267.571f,68.4696f,0.506145f}, - {-571.476f,-257.234f,63.3223f,3.10669f}, - {-566.035f,-273.907f,52.9582f,-0.890118f}, - {-580.948f,-259.77f,68.4696f,1.46608f}, - {-568.318f,-267.1f,75.0008f,1.01229f}, - {-559.621f,-268.597f,52.8986f,0.0523599f}, - //towerp - {-776.072f,-368.046f,84.3558f,2.63545f}, - {-777.564f,-368.521f,90.6701f,1.72788f}, - {-765.461f,-357.711f,90.888f,0.314159f}, - {-768.763f,-362.735f,104.612f,1.81514f}, - {-760.356f,-358.896f,84.3558f,2.1293f}, - {-771.967f,-352.838f,84.3484f,1.74533f}, - {-773.333f,-364.653f,79.2351f,-1.64061f}, - {-764.109f,-366.069f,70.0934f,0.383972f}, - {-767.103f,-350.737f,68.7933f,2.80998f}, - {-760.115f,-353.845f,68.8633f,1.79769f}, - //froste - {-1304.87f,-304.525f,91.8366f,-0.680679f}, - {-1301.77f,-310.974f,95.8252f,0.907571f}, - {-1305.58f,-320.625f,102.166f,-0.558505f}, - {-1294.27f,-323.468f,113.893f,-1.67552f}, - {-1302.65f,-317.192f,127.487f,2.30383f}, - {-1293.89f,-313.478f,107.328f,1.6057f}, - {-1312.41f,-312.999f,107.328f,1.5708f}, - {-1311.57f,-308.08f,91.7666f,-1.85005f}, - {-1314.7f,-322.131f,107.36f,0.645772f}, - {-1304.6f,-310.754f,113.859f,-0.401426f}, - //frostw - {-1308.24f,-273.26f,92.0514f,-0.139626f}, - {-1302.26f,-262.858f,95.9269f,0.418879f}, - {-1297.28f,-267.773f,126.756f,2.23402f}, - {-1299.08f,-256.89f,114.108f,-2.44346f}, - {-1303.41f,-268.237f,114.151f,-1.23918f}, - {-1304.43f,-273.682f,107.612f,0.244346f}, - {-1309.53f,-265.951f,92.1418f,-2.49582f}, - {-1295.55f,-263.865f,105.033f,0.925024f}, - {-1294.71f,-281.466f,107.664f,-1.50098f}, - {-1289.69f,-259.521f,107.612f,-2.19912f}, - - //the two buildings of the captains - //alliance - {-64.4987f,-289.33f,33.4616f,-2.82743f}, - {-5.98025f,-326.144f,38.8538f,0}, - {-2.67893f,-306.998f,33.4165f,0}, - {-60.25f,-309.232f,50.2408f,-1.46608f}, - {-48.7941f,-266.533f,47.7916f,2.44346f}, - {-3.40929f,-306.288f,33.34f,0}, - {-48.619f,-266.917f,47.8168f,0}, - {-62.9474f,-286.212f,66.7288f,0}, - {-5.05132f,-325.323f,38.8536f,0}, - {-64.2677f,-289.412f,33.469f,0}, -//horde - {-524.276f,-199.6f,82.8733f,-1.46608f}, - {-518.196f,-173.085f,102.43f,0}, - {-500.732f,-145.358f,88.5337f,2.44346f}, - {-501.084f,-150.784f,80.8506f,0}, - {-518.309f,-163.963f,102.521f,2.96706f}, - {-517.053f,-200.429f,80.759f,0}, - {-514.361f,-163.864f,104.163f,0}, - {-568.04f,-188.707f,81.55f,0}, - {-501.775f,-151.581f,81.2027f,0}, - {-509.975f,-191.652f,83.2978f,0}, - -//snowfall eyecandy - {-191.153f,-129.868f,78.5595f,-1.25664f }, - {-201.282f,-134.319f,78.6753f,-0.942478f }, - {-215.981f,-91.4101f,80.8702f,-1.74533f }, - {-200.465f,-96.418f,79.7587f,1.36136f }, - //mine supplies - //irondeep - {870.899f,-388.434f,61.6406f,-1.22173f}, - {825.214f,-320.174f,63.712f,-2.82743f}, - {837.117f,-452.556f,47.2331f,-3.12414f}, - {869.755f,-448.867f,52.5448f,-0.855212f}, - {949.877f,-458.198f,56.4874f,0.314159f}, - {900.35f,-479.024f,58.3553f,0.122173f}, - {854.449f,-442.255f,50.6589f,0.401426f}, - {886.685f,-442.358f,54.6962f,-1.22173f}, - {817.509f,-457.331f,48.4666f,2.07694f}, - {793.411f,-326.281f,63.1117f,-2.79253f}, - //coldtooth - {-934.212f,-57.3517f,80.277f,-0.0174535f}, - {-916.281f,-36.8579f,77.0227f,0.122173f}, - {-902.73f,-103.868f,75.4378f,-1.58825f}, - {-900.514f,-143.527f,75.9686f,1.8675f}, - {-862.882f,-0.353299f,72.1526f,-2.51327f}, - {-854.932f,-85.9184f,68.6056f,-2.04204f}, - {-851.833f,-118.959f,63.8672f,-0.0698131f}, - {-849.832f,-20.8421f,70.4672f,-1.81514f}, - {-844.25f,-60.0374f,72.1031f,-2.19912f}, - {-820.644f,-136.043f,63.1977f,2.40855f}, - {-947.642f,-208.807f,77.0101f,1.36136f}, - {-951.394f,-193.695f,67.634f,0.802851f} -}; - -const float BG_AV_DoorPositons[2][4] = { - {780.487f, -493.024f, 99.9553f, 3.0976f}, //alliance - {-1375.193f, -538.981f, 55.2824f, 0.72178f} //horde -}; - -//creaturestuff starts here -//is related to BG_AV_CreaturePos -enum BG_AV_CreaturePlace -{ - AV_CPLACE_SPIRIT_STORM_AID = 0, - AV_CPLACE_SPIRIT_STORM_GRAVE = 1, - AV_CPLACE_SPIRIT_STONE_GRAVE = 2, - AV_CPLACE_SPIRIT_SNOWFALL = 3, - AV_CPLACE_SPIRIT_ICE_GRAVE = 4, - AV_CPLACE_SPIRIT_FROSTWOLF = 5, - 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 - AV_CPLACE_DEFENSE_STORM_AID = 9, - AV_CPLACE_DEFEMSE_STORM_GRAVE = 13, - AV_CPLACE_DEFENSE_STONE_GRAVE = 17, - AV_CPLACE_DEFENSE_SNOWFALL = 21, - AV_CPLACE_DEFENSE_FROSTWOLF = 25, - AV_CPLACE_DEFENSE_ICE_GRAVE = 29, - AV_CPLACE_DEFENSE_FROST_HUT = 33, - - AV_CPLACE_DEFENSE_DUN_S = 37, - AV_CPLACE_DEFENSE_DUN_N = 41, - AV_CPLACE_DEFENSE_ICEWING = 45, - AV_CPLACE_DEFENSE_STONE_TOWER = 49, - AV_CPLACE_DEFENSE_ICE_TOWER = 53, - AV_CPLACE_DEFENSE_TOWERPOINT = 57, - AV_CPLACE_DEFENSE_FROST_E = 61, - AV_CPLACE_DEFENSE_FROST_t = 65, - - AV_CPLACE_A_MARSHAL_SOUTH = 69, - AV_CPLACE_A_MARSHAL_NORTH = 70, - AV_CPLACE_A_MARSHAL_ICE = 71, - AV_CPLACE_A_MARSHAL_STONE = 72, - AV_CPLACE_H_MARSHAL_ICE = 73, - AV_CPLACE_H_MARSHAL_TOWER = 74, - AV_CPLACE_H_MARSHAL_ETOWER = 75, - AV_CPLACE_H_MARSHAL_WTOWER = 76, - //irondeep - //miner: - AV_CPLACE_MINE_N_1_MIN = 77, - AV_CPLACE_MINE_N_1_MAX = 136, - //special types - AV_CPLACE_MINE_N_2_MIN = 137, - AV_CPLACE_MINE_N_2_MAX = 192, - //boss - AV_CPLACE_MINE_N_3 = 193, - //coldtooth - //miner: - AV_CPLACE_MINE_S_1_MIN = 194, - AV_CPLACE_MINE_S_1_MAX = 250, - //special types - AV_CPLACE_MINE_S_2_MIN = 251, - AV_CPLACE_MINE_S_2_MAX = 289, - //vermin - AV_CPLACE_MINE_S_S_MIN = 290, - AV_CPLACE_MINE_S_S_MAX = 299, - //boss - AV_CPLACE_MINE_S_3 = 300, - - //herald - AV_CPLACE_HERALD = 301, - - //node aura triggers - AV_CPLACE_TRIGGER01 = 302, - AV_CPLACE_TRIGGER02 = 303, - AV_CPLACE_TRIGGER03 = 304, - AV_CPLACE_TRIGGER04 = 305, - AV_CPLACE_TRIGGER05 = 306, - AV_CPLACE_TRIGGER06 = 307, - AV_CPLACE_TRIGGER07 = 308, - AV_CPLACE_TRIGGER08 = 309, - AV_CPLACE_TRIGGER09 = 310, - AV_CPLACE_TRIGGER10 = 311, - AV_CPLACE_TRIGGER11 = 312, - AV_CPLACE_TRIGGER12 = 313, - AV_CPLACE_TRIGGER13 = 314, - AV_CPLACE_TRIGGER14 = 315, - AV_CPLACE_TRIGGER15 = 316, - - //boss,captain triggers - AV_CPLACE_TRIGGER16 = 317, - AV_CPLACE_TRIGGER17 = 318, - AV_CPLACE_TRIGGER18 = 319, - AV_CPLACE_TRIGGER19 = 320, - - AV_CPLACE_MAX = 321 -}; - -//x, y, z, o -const float BG_AV_CreaturePos[AV_CPLACE_MAX][4] = { - //spiritguides - {643.000000f,44.000000f,69.740196f,-0.001854f}, - {676.000000f,-374.000000f,30.000000f,-0.001854f}, - {73.417755f,-496.433105f,48.731918f,-0.001854f}, - {-157.409195f,31.206272f,77.050598f,-0.001854f}, - {-531.217834f,-405.231384f,49.551376f,-0.001854f}, - {-1090.476807f,-253.308670f,57.672371f,-0.001854f}, - {-1496.065063f,-333.338409f,101.134804f,-0.001854f}, - {873.001770f,-491.283630f,96.541931f,-0.001854f}, - {-1437.670044f,-610.088989f,51.161900f,-0.001854f}, - //grave - //firstaid - {635.17f,-29.5594f,46.5056f,4.81711f}, - {642.488f,-32.9437f,46.365f,4.67748f}, - {642.326f,-27.9442f,46.9211f,4.59022f}, - {635.945f,-33.6171f,45.7164f,4.97419f}, - //stormpike - {669.272f,-297.304f,30.291f,4.66604f}, - {674.08f,-292.328f,30.4817f,0.0918785f}, - {667.01f,-288.532f,29.8809f,1.81583f}, - {664.153f,-294.042f,30.2851f,3.28531f}, - //stone - {81.7027f,-406.135f,47.7843f,0.598464f}, - {78.1431f,-409.215f,48.0401f,5.05953f}, - {73.4135f,-407.035f,46.7527f,3.34736f}, - {78.2258f,-401.859f,46.4202f,2.05852f}, - //snowfall - {-207.412f,-110.616f,78.7959f,2.43251f}, - {-197.95f,-112.205f,78.5686f,6.22441f}, - {-202.709f,-116.829f,78.4358f,5.13742f}, - {-202.059f,-108.314f,78.5783f,5.91968f}, - //ice - {-615.501f,-393.802f,60.4299f,3.06147f}, - {-608.513f,-392.717f,62.5724f,2.06323f}, - {-609.769f,-400.072f,60.7174f,5.22367f}, - {-616.093f,-398.293f,60.5628f,3.73613f}, - //frost - {-1077.7f,-340.21f,55.4682f,6.25569f}, - {-1082.74f,-333.821f,54.7962f,2.05459f}, - {-1090.66f,-341.267f,54.6768f,3.27746f}, - {-1081.58f,-344.63f,55.256f,4.75636f}, - //frost hut - {-1408.95f,-311.69f,89.2536f,4.49954f}, - {-1407.15f,-305.323f,89.1993f,2.86827f}, - {-1400.64f,-304.3f,89.7008f,1.0595f}, - {-1400.4f,-311.35f,89.3028f,4.99434f}, - //towers - //dun south - OK - {569.395f,-101.064f,52.8296f,2.34974f}, - {574.85f,-92.9842f,52.5869f,3.09325f}, - {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 - {662.253f,-129.105f,64.1794f,2.77507f}, - {661.209f,-138.877f,64.2251f,3.38594f}, - {665.481f,-146.857f,64.1271f,3.75246f}, - //icewing - OK - {225.228f,-368.909f,56.9983f,6.23806f}, - {191.36f,-369.899f,57.1524f,3.24631f}, - {215.518f,-384.019f,56.9889f,5.09636f}, - {199.625f,-382.177f,56.8691f,4.08407f}, - //stone - {-172.851f,-452.366f,40.8725f,3.31829f}, - {-147.147f,-435.053f,40.8022f,0.599238f}, - {-169.456f,-440.325f,40.985f,2.59101f}, - {-163.494f,-434.904f,41.0725f,1.84174f}, - //ice - OK - {-573.522f,-271.854f,75.0078f,3.9619f}, - {-565.616f,-269.051f,74.9952f,5.02655f}, - {-562.825f,-261.087f,74.9898f,5.95157f}, - {-569.176f,-254.446f,74.8771f,0.820305f}, - //towerpoint - {-763.04f,-371.032f,90.7933f,5.25979f}, - {-759.764f,-358.264f,90.8681f,0.289795f}, - {-768.808f,-353.056f,90.8811f,1.52601f}, - {-775.944f,-362.639f,90.8949f,2.59573f}, - //frost etower - {-1294.13f,-313.045f,107.328f,0.270162f}, - {-1306.5f,-308.105f,113.767f,1.78755f}, - {-1294.78f,-319.966f,113.79f,5.94545f}, - {-1294.83f,-312.241f,113.799f,0.295293f}, - //frost wtower - {-1300.96f,-275.111f,114.058f,4.12804f}, - {-1302.41f,-259.256f,114.065f,1.67602f}, - {-1287.97f,-262.087f,114.165f,6.18264f}, - {-1291.59f,-271.166f,114.151f,5.28257f}, - - //alliance marshall - {721.104f,-7.64155f,50.7046f,3.45575f},// south - {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) - {-1363.99f,-221.99f,98.4053f,4.93012f}, - {-1370.96f,-223.532f,98.4266f,4.93012f}, - {-1378.37f,-228.614f,99.3546f,5.38565f}, - {-1358.02f,-228.998f,98.868f,3.87768f}, - - //irondeep mine - //Irondeep Trogg - {971.671f,-442.657f,57.6951f,3.1765f}, - {969.979f,-457.148f,58.1119f,4.5204f}, - {958.692f,-333.477f,63.2276f,5.77704f}, - {957.113f,-325.92f,61.7589f,1.13446f}, - {948.25f,-448.268f,56.9009f,5.60251f}, - {934.727f,-385.802f,63.0344f,3.75246f}, - {931.751f,-403.458f,59.6737f,5.63741f}, - {931.146f,-359.666f,66.0294f,3.9619f}, - {929.702f,-412.401f,56.8776f,5.89921f}, - {926.849f,-379.074f,63.5286f,2.0944f}, - {921.972f,-358.597f,66.4313f,2.93215f}, - {921.449f,-341.981f,67.1264f,3.4383f}, - {921.1f,-395.812f,60.4615f,2.71695f}, - {919.274f,-394.986f,60.3478f,2.71696f}, - {916.852f,-393.891f,60.1726f,2.71695f}, - {914.568f,-326.21f,66.1733f,2.25147f}, - {913.064f,-395.773f,60.1364f,4.41568f}, - {909.246f,-474.576f,58.2067f,0.226893f}, - {909.246f,-474.576f,58.2901f,0.226893f}, - {907.209f,-428.267f,59.8065f,1.8675f}, - {905.973f,-459.528f,58.7594f,1.37189f}, - {905.067f,-396.074f,60.2085f,5.07891f}, - {901.809f,-457.709f,59.0116f,3.52557f}, - {900.962f,-427.44f,59.0842f,1.50098f}, - {897.929f,-471.742f,59.7729f,2.54818f}, - {893.376f,-343.171f,68.1499f,5.35816f}, - {890.584f,-406.049f,61.1925f,5.67232f}, - {888.208f,-332.564f,68.148f,1.93732f}, - {887.647f,-391.537f,61.8734f,1.37881f}, - {885.109f,-343.338f,67.0867f,3.78979f}, - {881.618f,-419.948f,53.5228f,0.593412f}, - {878.675f,-345.36f,66.1052f,3.45651f}, - {877.127f,-351.8f,66.5296f,5.74213f}, - {876.778f,-345.97f,65.7724f,3.45262f}, - {874.577f,-414.786f,52.7817f,1.67552f}, - {868.247f,-343.136f,64.9894f,1.6057f}, - {859.03f,-367.231f,47.4655f,0.0174533f}, - {857.513f,-351.817f,65.1867f,4.39823f}, - {852.632f,-372.416f,48.1657f,3.66519f}, - {849.86f,-340.944f,66.2447f,0.401426f}, - {847.99f,-386.287f,60.9277f,2.32374f}, - {847.601f,-423.072f,50.0852f,4.57276f}, - {847.135f,-411.307f,50.2106f,1.5708f}, - {835.077f,-379.418f,48.2755f,5.93412f}, - {834.87f,-453.304f,47.9075f,0.226893f}, - {834.634f,-365.981f,62.8801f,1.32645f}, - {834.354f,-355.526f,48.1491f,6.07375f}, - {833.702f,-327.506f,65.0439f,0.331613f}, - {833.151f,-374.228f,63.0938f,3.66519f}, - {831.711f,-346.785f,47.2975f,0.226893f}, - {827.874f,-413.624f,48.5818f,1.49241f}, - {827.728f,-415.483f,48.5593f,1.49238f}, - {827.016f,-424.543f,48.2856f,1.49236f}, - {823.222f,-334.283f,65.6306f,4.88692f}, - {821.892f,-464.723f,48.9451f,4.66003f}, - {821.006f,-387.635f,49.0728f,3.15905f}, - {817.26f,-447.432f,49.4308f,2.18166f}, - {805.399f,-320.146f,52.7712f,0.296706f}, - {801.405f,-328.055f,53.0195f,4.31096f}, - //irondeep skullthumber irondeep shaman - {955.812f,-440.302f,55.3411f,3.19395f}, - {937.378f,-377.816f,65.3919f,3.56047f}, - {925.059f,-331.347f,65.7564f,3.66519f}, - {922.918f,-396.634f,60.3942f,2.71695f}, - {909.99f,-462.154f,59.0811f,3.7001f}, - {907.893f,-388.787f,61.7923f,5.74213f}, - {898.801f,-437.105f,58.5266f,0.959931f}, - {884.237f,-407.597f,61.566f,0.820305f}, - {880.744f,-344.683f,66.4086f,3.4644f}, - {876.047f,-341.857f,65.8743f,4.45059f}, - {874.674f,-402.077f,61.7573f,0.26341f}, - {871.914f,-404.209f,62.1269f,6.06163f}, - {871.606f,-403.665f,62.0795f,0.765774f}, - {871.561f,-404.114f,62.1297f,0.00981727f}, - {871.528f,-404.248f,62.1455f,0.498032f}, - {871.493f,-404.122f,62.1331f,5.65727f}, - {871.282f,-403.843f,62.1108f,0.788382f}, - {868.294f,-392.395f,61.4772f,4.38685f}, - {868.256f,-392.363f,61.4803f,0.732738f}, - {867.804f,-392.51f,61.5089f,2.30167f}, - {867.612f,-392.371f,61.524f,2.86149f}, - {858.593f,-439.614f,50.2184f,0.872665f}, - {851.471f,-362.52f,47.314f,4.06662f}, - {846.939f,-347.279f,66.2876f,0.942478f}, - {842.08f,-421.775f,48.2659f,1.0821f}, - {838.358f,-371.212f,63.3299f,4.04916f}, - {827.57f,-417.483f,48.4538f,1.49237f}, - {827.012f,-457.397f,48.9331f,2.35619f}, - {825.535f,-322.373f,63.9357f,4.76475f}, - {867.635f,-443.605f,51.3347f,1.38626f}, - {957.293f,-455.039f,56.7395f,5.79449f}, - {950.077f,-326.672f,61.6552f,5.48033f}, - {936.692f,-356.78f,65.9835f,2.75762f}, - {926.475f,-419.345f,56.1833f,2.0944f}, - {924.729f,-397.453f,60.213f,2.71695f}, - {902.195f,-475.891f,58.312f,1.39626f}, - {897.464f,-338.758f,68.1715f,2.94961f}, - {884.237f,-407.597f,61.566f,0.820305f}, - {882.517f,-344.111f,66.7887f,3.46962f}, - {881.437f,-400.254f,61.2028f,0.263427f}, - {880.156f,-400.678f,61.3113f,3.41373f}, - {877.989f,-418.051f,52.9753f,4.46804f}, - {871.212f,-404.12f,62.1433f,3.6554f}, - {871.036f,-404.119f,62.2237f,4.50295f}, - {857.396f,-395.766f,61.263f,4.78684f}, - {857.276f,-395.395f,61.2418f,0.0845553f}, - {857.231f,-394.577f,61.2174f,1.96817f}, - {857.108f,-395.682f,61.2317f,4.87022f}, - {856.709f,-395.28f,61.1814f,2.54913f}, - {850.922f,-390.399f,60.8771f,2.85405f}, - {847.556f,-388.228f,60.9438f,2.56872f}, - {842.031f,-384.663f,61.6028f,2.56871f}, - {832.035f,-389.301f,47.5567f,2.11185f}, - {827.415f,-419.468f,48.3322f,1.49232f}, - {826.402f,-349.454f,47.2722f,1.51844f}, - {817.83f,-455.715f,48.4207f,0.925025f}, - {808.953f,-325.964f,52.4043f,3.01942f}, - // Morloch - {865.554f,-438.735f,50.7333f,2.12431f}, - //coldtooth mine - //miner/digger - {-917.648f,-46.8922f,77.0872f,5.27089f}, - {-912.689f,-45.4494f,76.2277f,4.60767f}, - {-905.455f,-84.5179f,75.3642f,3.29867f}, - {-904.332f,-111.509f,75.5925f,2.47837f}, - {-904.27f,-160.419f,61.9876f,3.61192f}, - {-904.023f,-90.4558f,75.3706f,3.40339f}, - {-978.678f,-37.3136f,75.8364f,2.84489f}, - {-973.076f,-36.5013f,77.5047f,1.0821f}, - {-963.951f,-87.734f,81.5555f,0.575959f}, - {-961.941f,-90.7252f,81.6629f,0.820305f}, - {-957.623f,-186.582f,66.6021f,1.95477f}, - {-952.476f,-179.778f,78.6771f,4.5204f}, - {-950.427f,-115.007f,79.6127f,3.68264f}, - {-950.25f,-151.95f,79.4598f,-1.81423f}, - {-950.169f,-188.099f,66.6184f,5.55015f}, - {-949.944f,-142.977f,80.5382f,2.70526f}, - {-947.854f,-170.5f,79.7618f,0.942478f}, - {-946.738f,-139.567f,80.0904f,2.3911f}, - {-945.503f,-65.0654f,79.7907f,5.02655f}, - {-943.678f,-110.986f,80.2557f,0.959931f}, - {-942.993f,-56.9881f,79.8915f,5.65487f}, - {-938.197f,-155.838f,61.3111f,1.65806f}, - {-930.488f,-214.524f,72.1431f,2.1236f}, - {-929.947f,-154.449f,61.5084f,1.67552f}, - {-927.412f,-135.313f,61.1987f,3.29867f}, - {-920.677f,-156.859f,62.8033f,3.15306f}, - {-916.75f,-136.094f,62.2357f,0.0698132f}, - {-915.319f,-132.718f,62.562f,1.16984f}, - {-913.589f,-146.794f,76.9366f,1.8675f}, - {-907.572f,-148.937f,76.6898f,4.76475f}, - {-902.02f,-64.6174f,73.9707f,1.19169f}, - {-899.489f,-61.7252f,73.2498f,5.09636f}, - {-894.792f,-127.141f,75.3834f,6.14356f}, - {-892.408f,-162.525f,64.1212f,2.69884f}, - {-892.326f,-123.158f,76.0318f,5.5676f}, - {-888.468f,-148.462f,61.8012f,1.65806f}, - {-883.268f,-159.738f,63.5311f,5.20108f}, - {-877.76f,-118.07f,65.215f,2.94961f}, - {-876.792f,-128.646f,64.1045f,3.40339f}, - {-874.901f,-36.6579f,69.4246f,2.00713f}, - {-874.856f,-151.351f,62.7537f,3.57875f}, - {-872.135f,-150.08f,62.7513f,3.57201f}, - {-870.288f,-149.217f,62.5413f,3.56624f}, - {-870.03f,-6.27443f,70.3867f,2.3911f}, - {-869.023f,-82.2118f,69.5848f,3.22886f}, - {-866.354f,-40.2455f,70.842f,0.0698132f}, - {-865.305f,-152.302f,63.5044f,4.86947f}, - {-861.926f,-79.0519f,71.4178f,0.20944f}, - {-857.292f,-152.277f,63.2114f,4.18879f}, - {-853.357f,-0.696194f,72.0655f,0.994838f}, - {-850.685f,-14.2596f,70.2298f,0.20944f}, - {-839.987f,-67.7695f,72.7916f,4.93928f}, - {-839.199f,-57.0558f,73.4891f,1.67552f}, - {-836.963f,-153.224f,63.3821f,4.46804f}, - {-832.721f,-67.7555f,72.9062f,4.99164f}, - {-821.496f,-143.095f,63.1292f,0.541052f}, - {-818.829f,-153.004f,62.1757f,6.12611f}, - //special - {-954.622f,-110.958f,80.7911f,6.24828f}, - {-951.477f,-53.9647f,80.0235f,5.32325f}, - {-946.812f,-126.04f,78.8601f,5.15265f}, - {-940.689f,-140.707f,79.9225f,2.79253f}, - {-933.954f,-159.632f,60.778f,2.56563f}, - {-922.537f,-130.291f,61.3756f,4.95674f}, - {-915.862f,-151.74f,76.9427f,0.942478f}, - {-888.321f,-159.831f,62.5303f,1.20428f}, - {-874.361f,-42.4751f,69.4316f,0.785398f}, - {-873.19f,-50.4899f,70.0568f,-2.41288f}, - {-868.511f,-148.386f,62.3547f,3.57875f}, - {-868.44f,-121.649f,64.5056f,3.33358f}, - {-868.324f,-77.7196f,71.4768f,5.41052f}, - {-859.846f,-19.6549f,70.7304f,1.97222f}, - {-828.05f,-150.508f,62.2019f,2.14675f}, - {-826.254f,-58.6911f,72.0041f,3.68264f}, - {-976.086f,-44.1775f,76.029f,1.46608f}, - {-971.864f,-87.4223f,81.4954f,5.8294f}, - {-966.551f,-74.1111f,80.0243f,4.2129f}, - {-958.509f,-173.652f,77.9013f,6.24828f}, - {-951.511f,-181.242f,65.529f,4.39823f}, - {-940.967f,-186.243f,77.698f,1.28164f}, - {-930.004f,-65.0898f,79.077f,0.0581657f}, - {-920.864f,-40.2009f,78.256f,5.16617f}, - {-919.089f,-148.021f,62.0317f,2.59327f}, - {-901.516f,-116.329f,75.6876f,0.471239f}, - {-897.864f,-84.4348f,74.083f,3.00197f}, - {-897.617f,-52.0457f,71.9503f,4.36332f}, - {-894.891f,-153.951f,61.6827f,3.23569f}, - {-893.933f,-111.625f,75.6591f,4.22536f}, - {-883.265f,-152.854f,61.8384f,0.0941087f}, - {-868.293f,-147.243f,62.1097f,3.2056f}, - {-867.501f,-11.8709f,70.018f,6.14356f}, - {-866.699f,-147.54f,62.1646f,3.57878f}, - {-866.566f,-91.1916f,67.4414f,4.56707f}, - {-857.272f,-141.142f,61.7356f,4.17134f}, - {-847.446f,-98.0061f,68.5131f,3.24631f}, - {-837.026f,-140.729f,62.5141f,5.51524f}, - {-824.204f,-65.053f,72.3381f,3.01942f}, - //vermin (s.th special for this mine) - {-951.955f,-197.5f,77.212f,5.63741f}, - {-944.837f,-199.608f,77.0737f,4.97419f}, - {-933.494f,-209.063f,73.7803f,5.88176f}, - {-929.666f,-201.308f,73.7032f,5.02655f}, - {-978.997f,-249.356f,65.4345f,5.05464f}, - {-974.565f,-224.828f,69.5858f,4.88846f}, - {-946.514f,-259.239f,66.0874f,3.78132f}, - {-918.402f,-250.439f,69.5271f,2.21352f}, - {-910.14f,-229.959f,72.9279f,0.27677f}, - {-851.563f,-88.6527f,68.5983f,3.61896f}, - //boss - {-848.902f,-92.931f,68.6325f,3.33350}, - //herald - {-48.459f,-288.802f,55.47f,1.0}, - //triggers - {637.083,-32.6603,45.9715,1.14353}, //firstaid_station - {669.007f,-294.078f,30.2909f,2.77507f}, //stormpike_grave - {77.8013f,-404.7f,46.7549f,-0.872665f}, //stoneheart_grave - {-202.581f,-112.73f,78.4876f,-0.715585f}, //snowfall_grave - {-611.962f,-396.17f,60.8351f,2.53682f}, //iceblood_grave - {-1082.45f,-346.823f,54.9219f,-1.53589f}, //frostwolf_grave - {-1402.21f,-307.431f,89.4424f,0.191986f}, //frostwolf_hut - {553.779f,-78.6566f,51.9378f,-1.22173f}, //dunbaldar_south - {674.001f,-143.125f,63.6615f,0.994838f}, //dunbaldar_north - {203.281f,-360.366f,56.3869f,-0.925024}, //icewing_bunker - {-152.437f,-441.758f,40.3982f,-1.95477f}, //stoneheart_bunker - {-571.88f,-262.777f,75.0087f,-0.802851f}, //iceblood_tower - {-768.907f,-363.71f,90.8949f,1.07991f}, //tower_point - {-1302.9f,-316.981f,113.867f,2.00713f}, //frostwolf_etower - {-1297.5f,-266.767f,114.15f,3.31044f}, //frostwolf_wtower - {-57.7891f,-286.597f,15.6479f,6.02139f}, //AV_NPC_A_CAPTAIN balinda - {722.43f,-10.9982f,50.7046f,3.42085f}, //AV_NPC_A_BOSS vanndar - {-545.23f,-165.35f,57.7886f,3.01145f}, //AV_NPC_H_CAPTAIN galvangar - {-1370.9f,-219.793f,98.4258f,5.04381f} //AV_NPC_H_BOSS drek thar -}; - -enum BG_AV_CreatureIds -{ - - AV_NPC_A_GRAVEDEFENSE0 = 0, // stormpike Defender - AV_NPC_A_GRAVEDEFENSE1 = 1, // seasoned defender - AV_NPC_A_GRAVEDEFENSE2 = 2, // veteran defender - AV_NPC_A_GRAVEDEFENSE3 = 3, // champion defender - AV_NPC_A_TOWERDEFENSE = 4, // stormpike bowman - AV_NPC_A_CAPTAIN = 5, // balinda - AV_NPC_A_BOSS = 6, // vanndar - - AV_NPC_H_GRAVEDEFENSE0 = 7, // frostwolf guardian - AV_NPC_H_GRAVEDEFENSE1 = 8, // seasoned guardian - AV_NPC_H_GRAVEDEFENSE2 = 9, // veteran guardian - AV_NPC_H_GRAVEDEFENSE3 = 10, // champion guardian - AV_NPC_H_TOWERDEFENSE = 11, // frostwolf bowman - AV_NPC_H_CAPTAIN = 12, // galvangar - AV_NPC_H_BOSS = 13, // drek thar - - AV_NPC_A_MARSHAL_SOUTH = 14, - AV_NPC_MARSHAL_NORTH = 15, - AV_NPC_A_MARSHAL_ICE = 16, - AV_NPC_A_MARSHAL_STONE = 17, - AV_NPC_H_MARSHAL_ICE = 18, - AV_NPC_H_MARSHAL_TOWER = 19, - AV_NPC_MARSHAL_ETOWER = 20, - AV_NPC_H_MARSHAL_WTOWER= 21, - AV_NPC_N_MINE_N_1 = 22, - AV_NPC_N_MINE_N_2 = 23, - AV_NPC_N_MINE_N_3 = 24, - AV_NPC_N_MINE_N_4 = 25, - AV_NPC_N_MINE_A_1 = 26, - AV_NPC_N_MINE_A_2 = 27, - AV_NPC_N_MINE_A_3 = 28, - AV_NPC_N_MINE_A_4 = 29, - AV_NPC_N_MINE_H_1 = 30, - AV_NPC_N_MINE_H_2 = 31, - AV_NPC_N_MINE_H_3 = 32, - AV_NPC_N_MINE_H_4 = 33, - AV_NPC_S_MINE_N_1 = 34, - AV_NPC_S_MINE_N_2 = 35, - AV_NPC_S_MINE_N_3 = 36, - AV_NPC_S_MINE_N_4 = 37, - AV_NPC_S_MINE_N_S = 38, - AV_NPC_S_MINE_A_1 = 39, - AV_NPC_S_MINE_A_2 = 40, - AV_NPC_S_MINE_A_3 = 41, - AV_NPC_S_MINE_A_4 = 42, - AV_NPC_S_MINE_H_1 = 43, - AV_NPC_S_MINE_H_2 = 44, - AV_NPC_S_MINE_H_3 = 45, - AV_NPC_S_MINE_H_4 = 46, - AV_NPC_HERALD = 47, - AV_NPC_INFO_MAX = 48 - -}; - -//entry, team, minlevel, maxlevel -//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 - { 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 - { 13328, 1214, 59, 59 }, //Seasoned Guardian - { 13332, 1214, 60, 60 }, //Veteran Guardian - { 13421, 1214, 61, 61 }, //Champion Guardian - { 13359, 1214, 59, 60 }, //Frostwolf Bowman - { 11947,67,0,0}, //not spawned with this data, but used for handlekillunit - { 11946,67,0,0}, //not spawned with this data, but used for handlekillunit - { 14763, 1534, 60, 60 }, //Dun Baldar South Marshal - { 14762, 1534, 60, 60 }, //Dun Baldar North Marshal - { 14764, 1534, 60, 60 }, //Icewing Marshal - { 14765, 1534, 60, 60 }, //Stonehearth Marshal - - { 14773, 1214, 60, 60 }, //Iceblood Warmaster - { 14776, 1214, 60, 60 }, //Tower Point Warmaster - { 14772, 1214, 60, 60 }, //East Frostwolf Warmaster - { 14777, 1214, 60, 60 }, //West Frostwolf Warmaster - - { 10987, 59, 52, 53 }, //Irondeep Trogg - { 11600, 59, 53, 54 }, //Irondeep Shaman - { 11602, 59, 54, 55 }, //Irondeep Skullthumper - { 11657, 59, 58, 58 }, //Morloch - - {13396,469,52,53}, //irondeep alliance TODO: get the right ids - {13080,469,53,54}, - {13098,469,54,55}, - {13078,469,58,58}, - - {13397,67,52,53}, //irondeep horde - {13099,67,53,54}, - {13081,67,54,55}, - {13079,67,58,58}, - - { 11603, 59, 52, 53 }, //south mine neutral - { 11604, 59, 53, 54 }, - { 11605, 59, 54, 55 }, - { 11677, 59, 58, 58 }, - { 10982, 59, 52, 53 }, //vermin - - {13317,469,52,53}, //alliance - {13096,469,54,55}, //explorer - {13087,469,54,55}, //invader - {13086,469,58,58}, - - {13316,67,52,53}, //horde - {13097,67,54,55}, //surveypr - {13089,67,54,55}, //guard - {13088,67,58,58}, - {14848,67,58,58} //Herald - -}; - -//x,y,z,o,static_creature_info-id -const float BG_AV_StaticCreaturePos[AV_STATICCPLACE_MAX][5] = { //static creatures - {-1235.31f,-340.777f,60.5088f,3.31613f,0 },//2225 - Zora Guthrek - {-1244.02f,-323.795f,61.0485f,5.21853f,1 },//3343 - Grelkor - {-1235.16f,-332.302f,60.2985f,2.96706f,2 },//3625 - Rarck - {587.303f,-42.8257f,37.5615f,5.23599f,3 },//4255 - Brogus Thunderbrew - {643.635f,-58.3987f,41.7405f,4.72984f,4 },//4257 - Lana Thunderbrew - {591.464f,-44.452f,37.6166f,5.65487f,5 },//5134 - Jonivera Farmountain - {608.515f,-33.3935f,42.0003f,5.41052f,6 },//5135 - Svalbrad Farmountain - {617.656f,-32.0701f,42.7168f,4.06662f,7 },//5139 - Kurdrum Barleybeard - {-1183.76f,-268.295f,72.8233f,3.28122f,8 },//10364 - Yaelika Farclaw - {-1187.86f,-275.31f,73.0481f,3.63028f,9 },//10367 - Shrye Ragefist - {-1008.42f,-368.006f,55.3426f,5.95647f,10 },//10981 - Frostwolf - {-1091.92f,-424.28f,53.0139f,2.93958f,10 },//10981 - Frostwolf - {-558.455f,-198.768f,58.1755f,4.97946f,10 },//10981 - Frostwolf - {-861.247f,-312.51f,55.1427f,3.35382f,10 },//10981 - Frostwolf - {-1003.81f,-395.913f,50.4736f,2.85631f,10 },//10981 - Frostwolf - {-904.5f,-289.815f,65.1222f,5.7847f,10 },//10981 - Frostwolf - {-1064.41f,-438.839f,51.3614f,1.88857f,10 },//10981 - Frostwolf - {258.814f,76.2017f,18.6468f,6.19052f,11 },//10986 - Snowblind Harpy - {265.838f,-315.846f,-16.5429f,3.15917f,11 },//10986 - Snowblind Harpy - {426.485f,-51.1927f,-5.66286f,1.60347f,11 },//10986 - Snowblind Harpy - {452.044f,-33.9594f,-0.044651f,2.72815f,11 },//10986 - Snowblind Harpy - {266.032f,-315.639f,-16.5429f,4.67962f,11 },//10986 - Snowblind Harpy - {532.64f,-54.5863f,20.7024f,2.93215f,11 },//10986 - Snowblind Harpy - {295.183f,-299.908f,-34.6123f,0.135851f,12 },//10990 - Alterac Ram - {421.08f,-225.006f,-23.73f,0.166754f,12 },//10990 - Alterac Ram - {-55.7766f,-192.498f,20.4352f,6.12221f,12 },//10990 - Alterac Ram - {527.887f,-477.223f,62.3559f,0.170935f,12 },//10990 - Alterac Ram - {389.144f,-346.508f,-30.334f,4.14117f,12 },//10990 - Alterac Ram - {108.121f,-322.248f,37.5655f,4.46788f,12 },//10990 - Alterac Ram - {507.479f,-67.9403f,10.3571f,3.26304f,12 },//10990 - Alterac Ram - {329.071f,-185.016f,-29.1542f,0.356943f,12 },//10990 - Alterac Ram - {252.449f,-422.313f,35.1404f,4.53771f,12 },//10990 - Alterac Ram - {358.882f,-118.061f,-24.9119f,2.29257f,12 },//10990 - Alterac Ram - {487.151f,-174.229f,14.7558f,4.73192f,12 },//10990 - Alterac Ram - {449.652f,-123.561f,6.14273f,6.12029f,12 },//10990 - Alterac Ram - {272.419f,-261.802f,-41.8835f,3.66559f,12 },//10990 - Alterac Ram - {359.021f,-210.954f,-29.3483f,4.31339f,12 },//10990 - Alterac Ram - {450.598f,-318.048f,-37.7548f,0.655219f,12 },//10990 - Alterac Ram - {509.333f,-218.2f,3.05439f,3.66292f,12 },//10990 - Alterac Ram - {485.771f,-223.613f,-1.53f,2.04862f,12 },//10990 - Alterac Ram - {486.636f,-452.172f,39.6592f,2.3341f,12 },//10990 - Alterac Ram - {702.783f,-257.494f,25.9777f,1.68329f,12 },//10990 - Alterac Ram - {460.942f,-199.263f,-6.0149f,0.380506f,12 },//10990 - Alterac Ram - {483.108f,-115.307f,10.1056f,3.69701f,12 },//10990 - Alterac Ram - {471.601f,-154.174f,14.0702f,5.5807f,12 },//10990 - Alterac Ram - {213.938f,-420.793f,41.2549f,5.71394f,12 },//10990 - Alterac Ram - {289.387f,-294.685f,-33.9073f,0.555494f,12 },//10990 - Alterac Ram - {155.649f,-402.891f,43.3915f,5.94838f,12 },//10990 - Alterac Ram - {517.184f,-295.105f,-9.78195f,6.05668f,12 },//10990 - Alterac Ram - {102.334f,-332.165f,38.9812f,3.31445f,12 },//10990 - Alterac Ram - {320.244f,-107.793f,-42.6357f,-1.00311f,12 },//10990 - Alterac Ram - {217.976f,110.774f,15.7603f,4.56793f,13 },//11675 - Snowblind Windcaller - {269.872f,6.66684f,20.7592f,0.381212f,13 },//11675 - Snowblind Windcaller - {313.528f,-319.041f,-27.2373f,0.554098f,13 },//11675 - Snowblind Windcaller - {435.441f,-39.9289f,-0.169651f,0.549454f,13 },//11675 - Snowblind Windcaller - {315.115f,-317.62f,-29.1123f,0.90111f,13 },//11675 - Snowblind Windcaller - {428.091f,-122.731f,3.40332f,6.05901f,14 },//11678 - Snowblind Ambusher - {235.05f,85.5705f,18.3079f,-0.914255f,14 },//11678 - Snowblind Ambusher - {-1553.04f,-344.342f,64.4163f,6.09933f,15 },//11839 - Wildpaw Brute - {-545.23f,-165.35f,57.7886f,3.01145f,16 },//11947 - Captain Galvangar - {722.43f,-10.9982f,50.7046f,3.42085f,17 },//11948 - Vanndar Stormpike - {-57.7891f,-286.597f,15.6479f,6.02139f,18 },//11949 - Captain Balinda Stonehearth - {930.498f,-520.755f,93.7334f,1.8326f,19 },//11997 - Stormpike Herald - {-776.092f,-345.161f,67.4092f,1.89257f,20 },//12051 - Frostwolf Legionnaire - {-1224.63f,-308.144f,65.0087f,4.01139f,20 },//12051 - Frostwolf Legionnaire - {-713.039f,-442.515f,82.8638f,0.68724f,20 },//12051 - Frostwolf Legionnaire - {-711.783f,-444.061f,82.7039f,0.683494f,20 },//12051 - Frostwolf Legionnaire - {587.633f,-45.9816f,37.5438f,5.81195f,21 },//12096 - Stormpike Quartermaster - {-1293.79f,-194.407f,72.4398f,5.84685f,22 },//12097 - Frostwolf Quartermaster - {446.163f,-377.119f,-1.12725f,0.209526f,23 },//12127 - Stormpike Guardsman - {549.348f,-399.254f,53.3537f,3.24729f,23 },//12127 - Stormpike Guardsman - {549.801f,-401.217f,53.8305f,3.24729f,23 },//12127 - Stormpike Guardsman - {192.704f,-406.874f,42.9183f,6.10696f,23 },//12127 - Stormpike Guardsman - {441.305f,-435.765f,28.2385f,2.14472f,23 },//12127 - Stormpike Guardsman - {192.982f,-404.891f,43.0132f,6.1061f,23 },//12127 - Stormpike Guardsman - {355.342f,-391.989f,-0.486707f,3.00643f,23 },//12127 - Stormpike Guardsman - {446.035f,-375.104f,-1.12725f,0.21033f,23 },//12127 - Stormpike Guardsman - {697.864f,-433.238f,62.7914f,1.65776f,23 },//12127 - Stormpike Guardsman - {610.74f,-331.585f,30.8021f,5.14253f,23 },//12127 - Stormpike Guardsman - {609.815f,-329.775f,30.9271f,-2.38829f,23 },//12127 - Stormpike Guardsman - {695.874f,-433.434f,62.8543f,1.65776f,23 },//12127 - Stormpike Guardsman - {443.337f,-435.283f,28.6842f,2.13768f,23 },//12127 - Stormpike Guardsman - {-1251.5f,-316.327f,62.6565f,5.02655f,24 },//13176 - Smith Regzar - {-1332.0f,-331.243f,91.2631f,1.50098f,25 },//13179 - Wing Commander Guse - {569.983f,-94.9992f,38.0325f,1.39626f,26 },//13216 - Gaelden Hammersmith - {-1244.92f,-308.916f,63.2525f,1.62316f,27 },//13218 - Grunnda Wolfheart - {-1319.56f,-342.675f,60.3404f,1.20428f,28 },//13236 - Primalist Thurloga - {647.61f,-61.1548f,41.7405f,4.24115f,29 },//13257 - Murgot Deepforge - {-1321.64f,-343.73f,60.4833f,1.01229f,30 },//13284 - Frostwolf Shaman - {-1317.61f,-342.853f,60.3726f,2.47837f,30 },//13284 - Frostwolf Shaman - {-1319.31f,-344.475f,60.3825f,1.72788f,30 },//13284 - Frostwolf Shaman - {569.963f,-42.0218f,37.7581f,4.27606f,31 },//13438 - Wing Commander Slidore - {729.2f,-78.812f,51.6335f,3.97935f,32 },//13442 - Arch Druid Renferal - {729.118f,-82.8713f,51.6335f,2.53073f,33 },//13443 - Druid of the Grove - {725.554f,-79.4973f,51.6335f,5.27089f,33 },//13443 - Druid of the Grove - {724.768f,-84.1642f,51.6335f,0.733038f,33 },//13443 - Druid of the Grove - {596.68f,-83.0633f,39.0051f,6.24828f,34 },//13447 - Corporal Noreg Stormpike - {600.032f,-2.92475f,42.0788f,5.00909f,35 },//13577 - Stormpike Ram Rider Commander - {610.239f,-21.8454f,43.272f,4.90438f,36 },//13617 - Stormpike Stable Master - {613.422f,-150.764f,33.4517f,5.55015f,37 },//13797 - Mountaineer Boombellow - {-1213.91f,-370.619f,56.4455f,0.837758f,38 },//13798 - Jotek - {704.35f,-22.9071f,50.2187f,0.785398f,39 },//13816 - Prospector Stonehewer - {-1271.24f,-335.766f,62.3971f,5.75959f,40 },//14185 - Najak Hexxen - {-1268.64f,-332.688f,62.6171f,5.28835f,41 },//14186 - Ravak Grimtotem - {648.363f,-65.2233f,41.7405f,3.12414f,42 },//14187 - Athramanis - {648.238f,-67.8931f,41.7405f,2.60054f,43 },//14188 - Dirk Swindle - {-1223.44f,-309.833f,64.9331f,4.0131f,44 },//14282 - Frostwolf Bloodhound - {-1226.4f,-307.136f,64.9706f,4.0145f,44 },//14282 - Frostwolf Bloodhound - {356.001f,-389.969f,-0.438796f,3.0334f,45 },//14283 - Stormpike Owl - {355.835f,-394.005f,-0.60149f,3.02498f,45 },//14283 - Stormpike Owl - {882.266f,-496.378f,96.7707f,4.83248f,45 },//14283 - Stormpike Owl - {878.649f,-495.917f,96.6171f,4.67693f,45 },//14283 - Stormpike Owl - {932.851f,-511.017f,93.6748f,3.61004f,45 },//14283 - Stormpike Owl - {935.806f,-513.983f,93.7436f,3.61788f,45 },//14283 - Stormpike Owl - {947.412f,-509.982f,95.1098f,2.82743f,46 },//14284 - Stormpike Battleguard - {934.557f,-512.395f,93.662f,3.61004f,46 },//14284 - Stormpike Battleguard - {939.42f,-502.777f,94.5887f,5.14872f,46 },//14284 - Stormpike Battleguard - {854.276f,-494.241f,96.8017f,5.44543f,46 },//14284 - Stormpike Battleguard - {776.621f,-487.775f,99.4049f,3.50811f,46 },//14284 - Stormpike Battleguard - {880.169f,-495.699f,96.6204f,4.8325f,46 },//14284 - Stormpike Battleguard - {773.651f,-497.482f,99.0408f,2.11185f,46 },//14284 - Stormpike Battleguard - {949.1f,-506.913f,95.4237f,3.31613f,46 },//14284 - Stormpike Battleguard - {-1370.9f,-219.793f,98.4258f,5.04381f,47}, //drek thar - -}; - -const uint32 BG_AV_StaticCreatureInfo[51][4] = { - { 2225, 1215, 55, 55 }, //Zora Guthrek - { 3343, 1215, 55, 55 }, //Grelkor - { 3625, 1215, 55, 55 }, //Rarck - { 4255, 1217, 55, 55 }, //Brogus Thunderbrew - { 4257, 1217, 55, 55 }, //Lana Thunderbrew - { 5134, 1217, 55, 55 }, //Jonivera Farmountain - { 5135, 1217, 55, 55 }, //Svalbrad Farmountain - { 5139, 1217, 55, 55 }, //Kurdrum Barleybeard - { 10364, 1215, 55, 55 }, //Yaelika Farclaw - { 10367, 1215, 55, 55 }, //Shrye Ragefist - { 10981, 38, 50, 51 }, //Frostwolf - { 10986, 514, 52, 53 }, //Snowblind Harpy - { 10990, 1274, 50, 51 }, //Alterac Ram - { 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 - { 11948, 1216, 63, 63 }, //Vanndar Stormpike - { 11949, 1216, 61, 61 }, //Captain Balinda Stonehearth - { 11997, 1334, 60, 60 }, //Stormpike Herald - { 12051, 1214, 57, 57 }, //Frostwolf Legionnaire - { 12096, 1217, 55, 55 }, //Stormpike Quartermaster - { 12097, 1215, 55, 55 }, //Frostwolf Quartermaster - { 12127, 1216, 57, 57 }, //Stormpike Guardsman - { 13176, 1215, 60, 60 }, //Smith Regzar - { 13179, 1215, 59, 59 }, //Wing Commander Guse - { 13216, 1217, 58, 58 }, //Gaelden Hammersmith - { 13218, 1215, 58, 58 }, //Grunnda Wolfheart - { 13236, 1214, 60, 60 }, //Primalist Thurloga - { 13257, 1216, 60, 60 }, //Murgot Deepforge - { 13284, 1214, 58, 58 }, //Frostwolf Shaman - { 13438, 1217, 58, 58 }, //Wing Commander Slidore - { 13442, 1216, 60, 60 }, //Arch Druid Renferal - { 13443, 1216, 60, 60 }, //Druid of the Grove - { 13447, 1216, 58, 58 }, //Corporal Noreg Stormpike - { 13577, 1216, 60, 60 }, //Stormpike Ram Rider Commander - { 13617, 1216, 60, 60 }, //Stormpike Stable Master - { 13797, 32, 60, 61 }, //Mountaineer Boombellow - { 13798, 1214, 60, 61 }, //Jotek - { 13816, 1216, 61, 61 }, //Prospector Stonehewer - { 14185, 877, 59, 59 }, //Najak Hexxen - { 14186, 105, 60, 60 }, //Ravak Grimtotem - { 14187, 1594, 60, 60 }, //Athramanis - { 14188, 57, 59, 59 }, //Dirk Swindle - { 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) - { 11948, 1216, 63, 63 }, //Vanndar Stormpike - { 11947, 1214, 61, 61 }, //Captain Galvangar - { 11949, 1216, 61, 61 } //Captain Balinda Stonehearth -}; - -enum BG_AV_Graveyards -{ - AV_GRAVE_STORM_AID = 751, - AV_GRAVE_STORM_GRAVE = 689, - AV_GRAVE_STONE_GRAVE = 729, - AV_GRAVE_SNOWFALL = 169, - AV_GRAVE_ICE_GRAVE = 749, - AV_GRAVE_FROSTWOLF = 690, - AV_GRAVE_FROST_HUT = 750, - AV_GRAVE_MAIN_ALLIANCE = 611, - AV_GRAVE_MAIN_HORDE = 610 -}; - -const uint32 BG_AV_GraveyardIds[9]= { - AV_GRAVE_STORM_AID, - AV_GRAVE_STORM_GRAVE, - AV_GRAVE_STONE_GRAVE, - AV_GRAVE_SNOWFALL, - AV_GRAVE_ICE_GRAVE, - AV_GRAVE_FROSTWOLF, - AV_GRAVE_FROST_HUT, - AV_GRAVE_MAIN_ALLIANCE, - AV_GRAVE_MAIN_HORDE -}; - -enum BG_AV_BUFF -{ //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 -}; -enum BG_AV_States -{ - POINT_NEUTRAL = 0, - POINT_ASSAULTED = 1, - POINT_DESTROYED = 2, - POINT_CONTROLED = 3 -}; - -enum BG_AV_WorldStates -{ - AV_Alliance_Score = 3127, - AV_Horde_Score = 3128, - AV_SHOW_H_SCORE = 3133, - AV_SHOW_A_SCORE = 3134, - -/* - //the comments behind the state shows which icon overlaps the other.. but is, until now, unused and maybe not a good solution (but give few performance (:) - -// Graves - - // Alliance - //Stormpike first aid station - AV_AID_A_C = 1325, - AV_AID_A_A = 1326, - AV_AID_H_C = 1327, - AV_AID_H_A = 1328, - //Stormpike Graveyard - AV_PIKEGRAVE_A_C = 1333, - AV_PIKEGRAVE_A_A = 1335, - AV_PIKEGRAVE_H_C = 1334, - AV_PIKEGRAVE_H_A = 1336, - //Stoneheart Grave - AV_STONEHEART_A_C = 1302, - AV_STONEHEART_A_A = 1304, //over hc - AV_STONEHEART_H_C = 1301, //over ac - AV_STONEHEART_H_A = 1303, //over aa - //Neutral - //Snowfall Grave -*/ - AV_SNOWFALL_N = 1966, //over aa -/* - AV_SNOWFALL_A_C = 1341, //over hc - AV_SNOWFALL_A_A = 1343, //over ha - AV_SNOWFALL_H_C = 1342, - AV_SNOWFALL_H_A = 1344, //over ac - //Horde - //Iceblood grave - AV_ICEBLOOD_A_C = 1346, //over hc - AV_ICEBLOOD_A_A = 1348, //over ac - AV_ICEBLOOD_H_C = 1347, - AV_ICEBLOOD_H_A = 1349, //over aa - //Frostwolf Grave - AV_FROSTWOLF_A_C = 1337, //over hc - AV_FROSTWOLF_A_A = 1339, //over ac - AV_FROSTWOLF_H_C = 1338, - AV_FROSTWOLF_H_A = 1340, //over aa - //Frostwolf Hut - AV_FROSTWOLFHUT_A_C = 1329, //over hc - AV_FROSTWOLFHUT_A_A = 1331, //over ha - AV_FROSTWOLFHUT_H_C = 1330, - AV_FROSTWOLFHUT_H_A = 1332, //over ac - -//Towers - //Alliance - //Dunbaldar South Bunker - AV_DUNS_CONTROLLED = 1361, - AV_DUNS_DESTROYED = 1370, - AV_DUNS_ASSAULTED = 1378, - //Dunbaldar North Bunker - AV_DUNN_CONTROLLED = 1362, - AV_DUNN_DESTROYED = 1371, - AV_DUNN_ASSAULTED = 1379, - //Icewing Bunker - AV_ICEWING_CONTROLLED = 1363, - AV_ICEWING_DESTROYED = 1372, - AV_ICEWING_ASSAULTED = 1380, - //Stoneheart Bunker - AV_STONEH_CONTROLLED = 1364, - AV_STONEH_DESTROYED = 1373, - AV_STONEH_ASSAULTED = 1381, - //Horde - //Iceblood Tower - AV_ICEBLOOD_CONTROLLED = 1385, - AV_ICEBLOOD_DESTROYED = 1368, - AV_ICEBLOOD_ASSAULTED = 1390, - //Tower Point - AV_TOWERPOINT_CONTROLLED = 1384, - AV_TOWERPOINT_DESTROYED = 1367, //goes over controlled - AV_TOWERPOINT_ASSAULTED = 1389, //goes over destroyed - //Frostwolf West - AV_FROSTWOLFW_CONTROLLED = 1382, - AV_FROSTWOLFW_DESTROYED = 1365, //over controlled - AV_FROSTWOLFW_ASSAULTED = 1387, //over destroyed - //Frostwolf East - AV_FROSTWOLFE_CONTROLLED = 1383, - AV_FROSTWOLFE_DESTROYED = 1366, - AV_FROSTWOLFE_ASSAULTED = 1388, - -//mines - - AV_N_MINE_N = 1360, - AV_N_MINE_A = 1358, - AV_N_MINE_H = 1359, - - AV_S_MINE_N = 1357, - AV_S_MINE_A = 1355, - AV_S_MINE_H = 1356, - -//towers assaulted by own team (unused) - AV_STONEH_UNUSED = 1377, - AV_ICEWING_UNUSED = 1376, - AV_DUNS_UNUSED = 1375, - AV_DUNN_UNUSED = 1374, - - AV_ICEBLOOD_UNUSED = 1395, - AV_TOWERPOINT_UNUSED = 1394, - AV_FROSTWOLFE_UNUSED = 1393, - AV_FROSTWOLFW_UNUSED = 1392 -*/ - -}; - -//alliance_control neutral_control horde_control -const uint32 BG_AV_MineWorldStates[2][3] = { - {1358, 1360,1359}, - {1355, 1357,1356} -}; - -//alliance_control alliance_assault h_control h_assault -const uint32 BG_AV_NodeWorldStates[16][4] = { - //Stormpike first aid station - {1325, 1326,1327,1328}, - //Stormpike Graveyard - {1333,1335,1334,1336}, - //Stoneheart Grave - {1302,1304,1301,1303}, - //Snowfall Grave - {1341,1343,1342,1344}, - //Iceblood grave - {1346,1348,1347,1349}, - //Frostwolf Grave - {1337,1339,1338,1340}, - //Frostwolf Hut - {1329,1331,1330,1332}, - //Dunbaldar South Bunker - {1361,1375,1370,1378}, - //Dunbaldar North Bunker - {1362,1374,1371,1379}, - //Icewing Bunker - {1363,1376,1372,1380}, - //Stoneheart Bunker - {1364,1377,1373,1381}, - //Iceblood Tower - {1368,1390,1385,1395}, - //Tower Point - {1367,1389,1384,1394}, - //Frostwolf East - {1366,1388,1383,1393}, - //Frostwolf West - {1365,1387,1382,1392}, -}; - -enum BG_AV_QuestIds -{ - AV_QUEST_A_SCRAPS1 = 7223, - AV_QUEST_A_SCRAPS2 = 6781, - AV_QUEST_H_SCRAPS1 = 7224, - AV_QUEST_H_SCRAPS2 = 6741, - AV_QUEST_A_COMMANDER1 = 6942, //soldier - AV_QUEST_H_COMMANDER1 = 6825, - AV_QUEST_A_COMMANDER2 = 6941, //leutnant - AV_QUEST_H_COMMANDER2 = 6826, - AV_QUEST_A_COMMANDER3 = 6943, //commander - AV_QUEST_H_COMMANDER3 = 6827, - AV_QUEST_A_BOSS1 = 7386, // 5 cristal/blood - AV_QUEST_H_BOSS1 = 7385, - AV_QUEST_A_BOSS2 = 6881, // 1 - AV_QUEST_H_BOSS2 = 6801, - AV_QUEST_A_NEAR_MINE = 5892, //the mine near start location of team - AV_QUEST_H_NEAR_MINE = 5893, - AV_QUEST_A_OTHER_MINE = 6982, //the other mine ;) - AV_QUEST_H_OTHER_MINE = 6985, - AV_QUEST_A_RIDER_HIDE = 7026, - AV_QUEST_H_RIDER_HIDE = 7002, - AV_QUEST_A_RIDER_TAME = 7027, - AV_QUEST_H_RIDER_TAME = 7001 -}; - -struct BG_AV_NodeInfo -{ - uint16 TotalOwner; - uint16 Owner; - uint16 PrevOwner; - BG_AV_States State; - BG_AV_States PrevState; - int Timer; - bool Tower; -}; - -inline BG_AV_Nodes &operator++(BG_AV_Nodes &i){ return i = BG_AV_Nodes(i + 1); } - -class BattleGroundAVScore : public BattleGroundScore -{ - public: - BattleGroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0), LeadersKilled(0), SecondaryObjectives(0) {}; - virtual ~BattleGroundAVScore() {}; - uint32 GraveyardsAssaulted; - uint32 GraveyardsDefended; - uint32 TowersAssaulted; - uint32 TowersDefended; - uint32 MinesCaptured; - uint32 LeadersKilled; - uint32 SecondaryObjectives; -}; - -class BattleGroundAV : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundAV(); - ~BattleGroundAV(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - void RemovePlayer(Player *plr,uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - bool SetupBattleGround(); - virtual void ResetBGSubclass(); - - /*general stuff*/ - void UpdateScore(uint16 team, int16 points); - void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); - - /*handlestuff*/ //these are functions which get called from extern - virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj); - void HandleKillPlayer(Player* player, Player *killer); - void HandleKillUnit(Creature *unit, Player *killer); - void HandleQuestComplete(uint32 questid, Player *player); - bool PlayerCanDoMineQuest(int32 GOId,uint32 team); - - void EndBattleGround(uint32 winner); - - virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); - - private: - /* Nodes occupying */ - void EventPlayerAssaultsPoint(Player* player, uint32 object); - void EventPlayerDefendsPoint(Player* player, uint32 object); - void EventPlayerDestroyedPoint(BG_AV_Nodes node); - - void AssaultNode(BG_AV_Nodes node,uint16 team); - void DestroyNode(BG_AV_Nodes node); - void InitNode(BG_AV_Nodes node, uint16 team, bool tower); - void DefendNode(BG_AV_Nodes node, uint16 team); - - void PopulateNode(BG_AV_Nodes node); - void DePopulateNode(BG_AV_Nodes node); - - const BG_AV_Nodes GetNodeThroughObject(uint32 object); - const uint32 GetObjectThroughNode(BG_AV_Nodes node); - const char* GetNodeName(BG_AV_Nodes node); - const bool IsTower(BG_AV_Nodes node) { return m_Nodes[node].Tower; } - - /*mine*/ - void ChangeMineOwner(uint8 mine, uint32 team, bool initial=false); - - /*worldstates*/ - void FillInitialWorldStates(WorldPacket& data); - const uint8 GetWorldStateType(uint8 state, uint16 team); - void SendMineWorldStates(uint32 mine); - void UpdateNodeWorldState(BG_AV_Nodes node); - - /*general */ - Creature* AddAVCreature(uint16 cinfoid, uint16 type); - const uint16 GetBonusHonor(uint8 kills); //TODO remove this when the core handles this right - - /*variables */ - int32 m_Team_Scores[2]; - uint32 m_Team_QuestStatus[2][9]; //[x][y] x=team y=questcounter - - BG_AV_NodeInfo m_Nodes[BG_AV_NODES_MAX]; - - uint32 m_Mine_Owner[2]; - uint32 m_Mine_PrevOwner[2]; //only for worldstates needed - int32 m_Mine_Timer; //ticks for both teams - uint32 m_Mine_Reclaim_Timer[2]; - uint32 m_CaptainBuffTimer[2]; - bool m_CaptainAlive[2]; - - uint8 m_MaxLevel; //TODO remove this when battleground-getmaxlevel() returns something usefull - bool m_IsInformedNearVictory[2]; - -}; - -#endif - diff --git a/src/server/game/BattleGrounds/BattleGroundBE.cpp b/src/server/game/BattleGrounds/BattleGroundBE.cpp deleted file mode 100644 index d6debe45ae3..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundBE.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BattleGround.h" -#include "BattleGroundBE.h" -#include "Language.h" -#include "Object.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "WorldPacket.h" - -BattleGroundBE::BattleGroundBE() -{ - m_BgObjects.resize(BG_BE_OBJECT_MAX); - - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; - //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; -} - -BattleGroundBE::~BattleGroundBE() -{ - -} - -void BattleGroundBE::Update(uint32 diff) -{ - BattleGround::Update(diff); - - /*if (GetStatus() == STATUS_IN_PROGRESS) - { - // update something - }*/ -} - -void BattleGroundBE::StartingEventCloseDoors() -{ - for (uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - - for (uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, RESPAWN_ONE_DAY); -} - -void BattleGroundBE::StartingEventOpenDoors() -{ - for (uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; ++i) - DoorOpen(i); - - for (uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, 60); -} - -void BattleGroundBE::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundBEScore* sc = new BattleGroundBEScore; - - m_PlayerScores[plr->GetGUID()] = sc; - - UpdateArenaWorldState(); -} - -void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) -{ - if (GetStatus() == STATUS_WAIT_LEAVE) - return; - - UpdateArenaWorldState(); - CheckArenaWinConditions(); -} - -void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - if (!killer) - { - sLog.outError("Killer player not found"); - return; - } - - BattleGround::HandleKillPlayer(player,killer); - - UpdateArenaWorldState(); - CheckArenaWinConditions(); -} - -bool BattleGroundBE::HandlePlayerUnderMap(Player *player) -{ - player->TeleportTo(GetMapId(),6238.930176,262.963470,0.889519,player->GetOrientation(),false); - return true; -} - -void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - //uint32 SpellId = 0; - //uint64 buff_guid = 0; - switch(Trigger) - { - case 4538: // buff trigger? - //buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_1]; - break; - case 4539: // buff trigger? - //buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_2]; - break; - default: - sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } - - //if (buff_guid) - // HandleTriggerBuff(buff_guid,Source); -} - -void BattleGroundBE::FillInitialWorldStates(WorldPacket &data) -{ - data << uint32(0x9f3) << uint32(1); // 9 - UpdateArenaWorldState(); -} - -void BattleGroundBE::Reset() -{ - //call parent's class reset - BattleGround::Reset(); -} - -bool BattleGroundBE::SetupBattleGround() -{ - // gates - if (!AddObject(BG_BE_OBJECT_DOOR_1, BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_BE_OBJECT_DOOR_2, BG_BE_OBJECT_TYPE_DOOR_2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_BE_OBJECT_DOOR_3, BG_BE_OBJECT_TYPE_DOOR_3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_BE_OBJECT_DOOR_4, BG_BE_OBJECT_TYPE_DOOR_4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY) - // buffs - || !AddObject(BG_BE_OBJECT_BUFF_1, BG_BE_OBJECT_TYPE_BUFF_1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120) - || !AddObject(BG_BE_OBJECT_BUFF_2, BG_BE_OBJECT_TYPE_BUFF_2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)) - { - sLog.outErrorDb("BatteGroundBE: Failed to spawn some object!"); - return false; - } - - return true; -} - -void BattleGroundBE::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) -{ - - BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... - return; - - //there is nothing special in this score - BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); - -} - -/* -21:45:46 id:231310 [S2C] SMSG_INIT_WORLD_STATES (706 = 0x02C2) len: 86 -0000: 32 02 00 00 76 0e 00 00 00 00 00 00 09 00 f3 09 | 2...v........... -0010: 00 00 01 00 00 00 f1 09 00 00 01 00 00 00 f0 09 | ................ -0020: 00 00 02 00 00 00 d4 08 00 00 00 00 00 00 d8 08 | ................ -0030: 00 00 00 00 00 00 d7 08 00 00 00 00 00 00 d6 08 | ................ -0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................ -0050: 00 00 00 00 00 00 | ...... - -spell 32724 - Gold Team -spell 32725 - Green Team -35774 Gold Team -35775 Green Team -*/ diff --git a/src/server/game/BattleGrounds/BattleGroundBE.h b/src/server/game/BattleGrounds/BattleGroundBE.h deleted file mode 100644 index 760d4d278c9..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundBE.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __BATTLEGROUNDBE_H -#define __BATTLEGROUNDBE_H - -class BattleGround; - -enum BattleGroundBEObjectTypes -{ - BG_BE_OBJECT_DOOR_1 = 0, - BG_BE_OBJECT_DOOR_2 = 1, - BG_BE_OBJECT_DOOR_3 = 2, - BG_BE_OBJECT_DOOR_4 = 3, - BG_BE_OBJECT_BUFF_1 = 4, - BG_BE_OBJECT_BUFF_2 = 5, - BG_BE_OBJECT_MAX = 6 -}; - -enum BattleGroundBEObjects -{ - BG_BE_OBJECT_TYPE_DOOR_1 = 183971, - BG_BE_OBJECT_TYPE_DOOR_2 = 183973, - BG_BE_OBJECT_TYPE_DOOR_3 = 183970, - BG_BE_OBJECT_TYPE_DOOR_4 = 183972, - BG_BE_OBJECT_TYPE_BUFF_1 = 184663, - BG_BE_OBJECT_TYPE_BUFF_2 = 184664 -}; - -class BattleGroundBEScore : public BattleGroundScore -{ - public: - BattleGroundBEScore() {}; - virtual ~BattleGroundBEScore() {}; -}; - -class BattleGroundBE : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundBE(); - ~BattleGroundBE(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - void RemovePlayer(Player *plr, uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - bool SetupBattleGround(); - virtual void Reset(); - virtual void FillInitialWorldStates(WorldPacket &d); - void HandleKillPlayer(Player* player, Player *killer); - bool HandlePlayerUnderMap(Player * plr); - - /* Scorekeeping */ - void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); -}; -#endif diff --git a/src/server/game/BattleGrounds/BattleGroundDS.cpp b/src/server/game/BattleGrounds/BattleGroundDS.cpp deleted file mode 100644 index 9036ef83f93..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundDS.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BattleGround.h" -#include "BattleGroundDS.h" -#include "Language.h" -#include "Player.h" -#include "Object.h" -#include "ObjectMgr.h" -#include "WorldPacket.h" - -BattleGroundDS::BattleGroundDS() -{ - m_BgObjects.resize(BG_DS_OBJECT_MAX); - - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; - //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; -} - -BattleGroundDS::~BattleGroundDS() -{ - -} - -void BattleGroundDS::Update(uint32 diff) -{ - BattleGround::Update(diff); - if (getWaterFallTimer() < diff) - { - if (isWaterFallActive()) - { - setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); - for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) - SpawnBGObject(i, getWaterFallTimer()); - setWaterFallActive(false); - } - else - { - setWaterFallTimer(BG_DS_WATERFALL_DURATION); - for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - setWaterFallActive(true); - } - } - else - setWaterFallTimer(getWaterFallTimer() - diff); -} - -void BattleGroundDS::StartingEventCloseDoors() -{ - for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); -} - -void BattleGroundDS::StartingEventOpenDoors() -{ - for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i) - DoorOpen(i); - - for (uint32 i = BG_DS_OBJECT_BUFF_1; i <= BG_DS_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, 60); - - setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); - setWaterFallActive(false); - - for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) - SpawnBGObject(i, getWaterFallTimer()); -} - -void BattleGroundDS::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundDSScore* sc = new BattleGroundDSScore; - - m_PlayerScores[plr->GetGUID()] = sc; - - UpdateArenaWorldState(); -} - -void BattleGroundDS::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) -{ - if (GetStatus() == STATUS_WAIT_LEAVE) - return; - - UpdateArenaWorldState(); - CheckArenaWinConditions(); -} - -void BattleGroundDS::HandleKillPlayer(Player* player, Player* killer) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - if (!killer) - { - sLog.outError("BattleGroundDS: Killer player not found"); - return; - } - - BattleGround::HandleKillPlayer(player,killer); - - UpdateArenaWorldState(); - CheckArenaWinConditions(); -} - -void BattleGroundDS::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - switch(Trigger) - { - case 5347: - case 5348: - break; - default: - sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } -} - -bool BattleGroundDS::HandlePlayerUnderMap(Player *player) -{ - player->TeleportTo(GetMapId(), 1299.046, 784.825, 9.338, 2.422, false); - return true; -} - -void BattleGroundDS::FillInitialWorldStates(WorldPacket &data) -{ - data << uint32(3610) << uint32(1); // 9 show - UpdateArenaWorldState(); -} - -void BattleGroundDS::Reset() -{ - //call parent's class reset - BattleGround::Reset(); -} - - -bool BattleGroundDS::SetupBattleGround() -{ - // gates - if (!AddObject(BG_DS_OBJECT_DOOR_1, BG_DS_OBJECT_TYPE_DOOR_1, 1350.95, 817.2, 20.8096, 3.15, 0, 0, 0.99627, 0.0862864, RESPAWN_IMMEDIATELY) - || !AddObject(BG_DS_OBJECT_DOOR_2, BG_DS_OBJECT_TYPE_DOOR_2, 1232.65, 764.913, 20.0729, 6.3, 0, 0, 0.0310211, -0.999519, RESPAWN_IMMEDIATELY) - // water - || !AddObject(BG_DS_OBJECT_WATER_1, BG_DS_OBJECT_TYPE_WATER_1, 1291.56, 790.837, 7.1, 3.14238, 0, 0, 0.694215, -0.719768, 120) - || !AddObject(BG_DS_OBJECT_WATER_2, BG_DS_OBJECT_TYPE_WATER_2, 1291.56, 790.837, 7.1, 3.14238, 0, 0, 0.694215, -0.719768, 120) - // buffs - || !AddObject(BG_DS_OBJECT_BUFF_1, BG_DS_OBJECT_TYPE_BUFF_1, 1291.7, 813.424, 7.11472, 4.64562, 0, 0, 0.730314, -0.683111, 120) - || !AddObject(BG_DS_OBJECT_BUFF_2, BG_DS_OBJECT_TYPE_BUFF_2, 1291.7, 768.911, 7.11472, 1.55194, 0, 0, 0.700409, 0.713742, 120)) - { - sLog.outErrorDb("BatteGroundDS: Failed to spawn some object!"); - return false; - } - - return true; -} diff --git a/src/server/game/BattleGrounds/BattleGroundDS.h b/src/server/game/BattleGrounds/BattleGroundDS.h deleted file mode 100644 index 2ced5c88fd1..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundDS.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __BATTLEGROUNDDS_H -#define __BATTLEGROUNDDS_H - -class BattleGround; - -enum BattleGroundDSObjectTypes -{ - BG_DS_OBJECT_DOOR_1 = 0, - BG_DS_OBJECT_DOOR_2 = 1, - BG_DS_OBJECT_WATER_1 = 2, - BG_DS_OBJECT_WATER_2 = 3, - BG_DS_OBJECT_BUFF_1 = 4, - BG_DS_OBJECT_BUFF_2 = 5, - BG_DS_OBJECT_MAX = 6 -}; - -enum BattleGroundDSObjects -{ - BG_DS_OBJECT_TYPE_DOOR_1 = 192642, - BG_DS_OBJECT_TYPE_DOOR_2 = 192643, - BG_DS_OBJECT_TYPE_WATER_1 = 194395, - BG_DS_OBJECT_TYPE_WATER_2 = 191877, - BG_DS_OBJECT_TYPE_BUFF_1 = 184663, - BG_DS_OBJECT_TYPE_BUFF_2 = 184664 -}; - -enum BattleGroundDSData -{ // These values are NOT blizzlike... need the correct data! - BG_DS_WATERFALL_TIMER_MIN = 30000, - BG_DS_WATERFALL_TIMER_MAX = 60000, - BG_DS_WATERFALL_DURATION = 10000, -}; - -class BattleGroundDSScore : public BattleGroundScore -{ - public: - BattleGroundDSScore() {}; - virtual ~BattleGroundDSScore() {}; - //TODO fix me -}; - -class BattleGroundDS : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundDS(); - ~BattleGroundDS(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - void RemovePlayer(Player *plr, uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - bool SetupBattleGround(); - virtual void Reset(); - virtual void FillInitialWorldStates(WorldPacket &d); - void HandleKillPlayer(Player* player, Player *killer); - bool HandlePlayerUnderMap(Player * plr); - private: - uint32 m_waterTimer; - bool m_waterfallActive; - protected: - bool isWaterFallActive() { return m_waterfallActive; }; - void setWaterFallActive(bool active) { m_waterfallActive = active; }; - void setWaterFallTimer(uint32 timer) { m_waterTimer = timer; }; - uint32 getWaterFallTimer() { return m_waterTimer; }; -}; -#endif diff --git a/src/server/game/BattleGrounds/BattleGroundEY.cpp b/src/server/game/BattleGrounds/BattleGroundEY.cpp deleted file mode 100644 index 20f023e4c2a..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundEY.cpp +++ /dev/null @@ -1,938 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ObjectMgr.h" -#include "World.h" -#include "WorldPacket.h" -#include "BattleGroundMgr.h" -#include "BattleGround.h" -#include "BattleGroundEY.h" -#include "Creature.h" -#include "Language.h" -#include "Object.h" -#include "Player.h" -#include "Util.h" - -// these variables aren't used outside of this file, so declare them only here -uint32 BG_EY_HonorScoreTicks[BG_HONOR_MODE_NUM] = { - 330, // normal honor - 200 // holiday -}; - -BattleGroundEY::BattleGroundEY() -{ - m_BuffChange = true; - m_BgObjects.resize(BG_EY_OBJECT_MAX); - m_BgCreatures.resize(BG_EY_CREATURES_MAX); - m_Points_Trigger[FEL_REALVER] = TR_FEL_REALVER_BUFF; - m_Points_Trigger[BLOOD_ELF] = TR_BLOOD_ELF_BUFF; - m_Points_Trigger[DRAENEI_RUINS] = TR_DRAENEI_RUINS_BUFF; - m_Points_Trigger[MAGE_TOWER] = TR_MAGE_TOWER_BUFF; - - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN; -} - -BattleGroundEY::~BattleGroundEY() -{ -} - -void BattleGroundEY::Update(uint32 diff) -{ - BattleGround::Update(diff); - - if (GetStatus() == STATUS_IN_PROGRESS) - { - m_PointAddingTimer -= diff; - if (m_PointAddingTimer <= 0) - { - m_PointAddingTimer = BG_EY_FPOINTS_TICK_TIME; - if (m_TeamPointsCount[BG_TEAM_ALLIANCE] > 0) - AddPoints(ALLIANCE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_ALLIANCE] - 1]); - if (m_TeamPointsCount[BG_TEAM_HORDE] > 0) - AddPoints(HORDE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_HORDE] - 1]); - } - - if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN || m_FlagState == BG_EY_FLAG_STATE_ON_GROUND) - { - m_FlagsTimer -= diff; - - if (m_FlagsTimer < 0) - { - m_FlagsTimer = 0; - if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN) - RespawnFlag(true); - else - RespawnFlagAfterDrop(); - } - } - - m_TowerCapCheckTimer -= diff; - if (m_TowerCapCheckTimer <= 0) - { - //check if player joined point - /*I used this order of calls, because although we will check if one player is in gameobject's distance 2 times - but we can count of players on current point in CheckSomeoneLeftPoint - */ - this->CheckSomeoneJoinedPoint(); - //check if player left point - this->CheckSomeoneLeftPoint(); - this->UpdatePointStatuses(); - m_TowerCapCheckTimer = BG_EY_FPOINTS_TICK_TIME; - } - } -} - -void BattleGroundEY::StartingEventCloseDoors() -{ - SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY); - - for (uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i) - SpawnBGObject(i, RESPAWN_ONE_DAY); -} - -void BattleGroundEY::StartingEventOpenDoors() -{ - SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY); - SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY); - - for (uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - for (uint32 i = 0; i < EY_POINTS_MAX; ++i) - { - //randomly spawn buff - uint8 buff = urand(0, 2); - SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY); - } -} - -void BattleGroundEY::AddPoints(uint32 Team, uint32 Points) -{ - BattleGroundTeamId team_index = GetTeamIndexByTeamId(Team); - m_TeamScores[team_index] += Points; - m_HonorScoreTics[team_index] += Points; - if (m_HonorScoreTics[team_index] >= m_HonorTics) - { - RewardHonorToTeam(GetBonusHonorFromKill(1), Team); - m_HonorScoreTics[team_index] -= m_HonorTics; - } - UpdateTeamScore(Team); -} - -void BattleGroundEY::CheckSomeoneJoinedPoint() -{ - GameObject *obj = NULL; - for (uint8 i = 0; i < EY_POINTS_MAX; ++i) - { - obj = HashMapHolder::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]); - if (obj) - { - uint8 j = 0; - while (j < m_PlayersNearPoint[EY_POINTS_MAX].size()) - { - Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[EY_POINTS_MAX][j]); - if (!plr) - { - sLog.outError("BattleGroundEY:CheckSomeoneJoinedPoint: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[EY_POINTS_MAX][j])); - ++j; - continue; - } - if (plr->CanCaptureTowerPoint() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) - { - //player joined point! - //show progress bar - UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, plr); - UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[i], plr); - UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, plr); - //add player to point - m_PlayersNearPoint[i].push_back(m_PlayersNearPoint[EY_POINTS_MAX][j]); - //remove player from "free space" - m_PlayersNearPoint[EY_POINTS_MAX].erase(m_PlayersNearPoint[EY_POINTS_MAX].begin() + j); - } - else - ++j; - } - } - } -} - -void BattleGroundEY::CheckSomeoneLeftPoint() -{ - //reset current point counts - for (uint8 i = 0; i < 2*EY_POINTS_MAX; ++i) - m_CurrentPointPlayersCount[i] = 0; - GameObject *obj = NULL; - for (uint8 i = 0; i < EY_POINTS_MAX; ++i) - { - obj = HashMapHolder::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]); - if (obj) - { - uint8 j = 0; - while (j < m_PlayersNearPoint[i].size()) - { - Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[i][j]); - if (!plr) - { - sLog.outError("BattleGroundEY:CheckSomeoneLeftPoint Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[i][j])); - //move not existed player to "free space" - this will cause many error showing in log, but it is a very important bug - m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); - m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); - ++j; - continue; - } - if (!plr->CanCaptureTowerPoint() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) - //move player out of point (add him to players that are out of points - { - m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); - m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); - this->UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, plr); - } - else - { - //player is neat flag, so update count: - m_CurrentPointPlayersCount[2 * i + GetTeamIndexByTeamId(plr->GetTeam())]++; - ++j; - } - } - } - } -} - -void BattleGroundEY::UpdatePointStatuses() -{ - for (uint8 point = 0; point < EY_POINTS_MAX; ++point) - { - if (m_PlayersNearPoint[point].empty()) - continue; - //count new point bar status: - m_PointBarStatus[point] += (m_CurrentPointPlayersCount[2 * point] - m_CurrentPointPlayersCount[2 * point + 1] < BG_EY_POINT_MAX_CAPTURERS_COUNT) ? m_CurrentPointPlayersCount[2 * point] - m_CurrentPointPlayersCount[2 * point + 1] : BG_EY_POINT_MAX_CAPTURERS_COUNT; - - if (m_PointBarStatus[point] > BG_EY_PROGRESS_BAR_ALI_CONTROLLED) - //point is fully alliance's - m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_ALI_CONTROLLED; - if (m_PointBarStatus[point] < BG_EY_PROGRESS_BAR_HORDE_CONTROLLED) - //point is fully horde's - m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_HORDE_CONTROLLED; - - uint32 pointOwnerTeamId = 0; - //find which team should own this point - if (m_PointBarStatus[point] <= BG_EY_PROGRESS_BAR_NEUTRAL_LOW) - pointOwnerTeamId = HORDE; - else if (m_PointBarStatus[point] >= BG_EY_PROGRESS_BAR_NEUTRAL_HIGH) - pointOwnerTeamId = ALLIANCE; - else - pointOwnerTeamId = EY_POINT_NO_OWNER; - - for (uint8 i = 0; i < m_PlayersNearPoint[point].size(); ++i) - { - Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[point][i]); - if (plr) - { - this->UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[point], plr); - //if point owner changed we must evoke event! - if (pointOwnerTeamId != m_PointOwnedByTeam[point]) - { - //point was uncontrolled and player is from team which captured point - if (m_PointState[point] == EY_POINT_STATE_UNCONTROLLED && plr->GetTeam() == pointOwnerTeamId) - this->EventTeamCapturedPoint(plr, point); - - //point was under control and player isn't from team which controlled it - if (m_PointState[point] == EY_POINT_UNDER_CONTROL && plr->GetTeam() != m_PointOwnedByTeam[point]) - this->EventTeamLostPoint(plr, point); - } - } - } - } -} - -void BattleGroundEY::UpdateTeamScore(uint32 Team) -{ - uint32 score = GetTeamScore(Team); - //TODO there should be some sound played when one team is near victory!! - and define variables - /*if (!m_IsInformedNearVictory && score >= BG_EY_WARNING_NEAR_VICTORY_SCORE) - { - if (Team == ALLIANCE) - SendMessageToAll(LANG_BG_EY_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); - else - SendMessageToAll(LANG_BG_EY_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); - PlaySoundToAll(BG_EY_SOUND_NEAR_VICTORY); - m_IsInformedNearVictory = true; - }*/ - - if (score >= BG_EY_MAX_TEAM_SCORE) - { - score = BG_EY_MAX_TEAM_SCORE; - EndBattleGround(Team); - } - - if (Team == ALLIANCE) - UpdateWorldState(EY_ALLIANCE_RESOURCES, score); - else - UpdateWorldState(EY_HORDE_RESOURCES, score); -} - -void BattleGroundEY::EndBattleGround(uint32 winner) -{ - //win reward - if (winner == ALLIANCE) - RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); - if (winner == HORDE) - RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); - //complete map reward - RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); - RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); - - BattleGround::EndBattleGround(winner); -} - -void BattleGroundEY::UpdatePointsCount(uint32 Team) -{ - if (Team == ALLIANCE) - UpdateWorldState(EY_ALLIANCE_BASE, m_TeamPointsCount[BG_TEAM_ALLIANCE]); - else - UpdateWorldState(EY_HORDE_BASE, m_TeamPointsCount[BG_TEAM_HORDE]); -} - -void BattleGroundEY::UpdatePointsIcons(uint32 Team, uint32 Point) -{ - //we MUST firstly send 0, after that we can send 1!!! - if (m_PointState[Point] == EY_POINT_UNDER_CONTROL) - { - UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 0); - if (Team == ALLIANCE) - UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 1); - else - UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 1); - } - else - { - if (Team == ALLIANCE) - UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 0); - else - UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 0); - UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 1); - } -} - -void BattleGroundEY::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map - BattleGroundEYScore* sc = new BattleGroundEYScore; - - m_PlayersNearPoint[EY_POINTS_MAX].push_back(plr->GetGUID()); - - m_PlayerScores[plr->GetGUID()] = sc; -} - -void BattleGroundEY::RemovePlayer(Player *plr, uint64 guid) -{ - // sometimes flag aura not removed :( - for (int j = EY_POINTS_MAX; j >= 0; --j) - { - for (size_t i = 0; i < m_PlayersNearPoint[j].size(); ++i) - if (m_PlayersNearPoint[j][i] == guid) - m_PlayersNearPoint[j].erase(m_PlayersNearPoint[j].begin() + i); - } - if (IsFlagPickedup()) - { - if (m_FlagKeeper == guid) - { - if (plr) - EventPlayerDroppedFlag(plr); - else - { - SetFlagPicker(0); - RespawnFlag(true); - } - } - } -} - -void BattleGroundEY::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - if (!Source->isAlive()) //hack code, must be removed later - return; - - switch(Trigger) - { - case TR_BLOOD_ELF_POINT: - if (m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[BLOOD_ELF] == Source->GetTeam()) - if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_BLOOD_ELF); - break; - case TR_FEL_REALVER_POINT: - if (m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[FEL_REALVER] == Source->GetTeam()) - if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_FEL_REALVER); - break; - case TR_MAGE_TOWER_POINT: - if (m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[MAGE_TOWER] == Source->GetTeam()) - if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_MAGE_TOWER); - break; - case TR_DRAENEI_RUINS_POINT: - if (m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[DRAENEI_RUINS] == Source->GetTeam()) - if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_DRAENEI_RUINS); - break; - case 4512: - case 4515: - case 4517: - case 4519: - case 4530: - case 4531: - case 4568: - case 4569: - case 4570: - case 4571: - case 5866: - break; - default: - sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } -} - -bool BattleGroundEY::SetupBattleGround() -{ - // doors - if (!AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_EY_OBJECT_DOOR_H, BG_OBJECT_H_DOOR_EY_ENTRY, 1803.21f, 1539.49f, 1261.09f, 3.14159f, 0.173648f, 0, 0.984808f, 0, RESPAWN_IMMEDIATELY) - // banners (alliance) - || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) - // banners (horde) - || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) - // banners (natural) - || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) - // flags - || !AddObject(BG_EY_OBJECT_FLAG_NETHERSTORM, BG_OBJECT_FLAG2_EY_ENTRY, 2174.782227f, 1569.054688f, 1160.361938f, -1.448624f, 0, 0, 0.662620f, -0.748956f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_FLAG_FEL_REALVER, BG_OBJECT_FLAG1_EY_ENTRY, 2044.28f, 1729.68f, 1189.96f, -0.017453f, 0, 0, 0.008727f, -0.999962f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_FLAG_BLOOD_ELF, BG_OBJECT_FLAG1_EY_ENTRY, 2048.83f, 1393.65f, 1194.49f, 0.20944f, 0, 0, 0.104528f, 0.994522f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_FLAG_DRAENEI_RUINS, BG_OBJECT_FLAG1_EY_ENTRY, 2286.56f, 1402.36f, 1197.11f, 3.72381f, 0, 0, 0.957926f, -0.287016f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_FLAG_MAGE_TOWER, BG_OBJECT_FLAG1_EY_ENTRY, 2284.48f, 1731.23f, 1189.99f, 2.89725f, 0, 0, 0.992546f, 0.121869f, RESPAWN_ONE_DAY) - // tower cap - || !AddObject(BG_EY_OBJECT_TOWER_CAP_FEL_REALVER, BG_OBJECT_FR_TOWER_CAP_EY_ENTRY, 2024.600708f, 1742.819580f, 1195.157715f, 2.443461f, 0, 0, 0.939693f, 0.342020f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF, BG_OBJECT_BE_TOWER_CAP_EY_ENTRY, 2050.493164f, 1372.235962f, 1194.563477f, 1.710423f, 0, 0, 0.754710f, 0.656059f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS, BG_OBJECT_DR_TOWER_CAP_EY_ENTRY, 2301.010498f, 1386.931641f, 1197.183472f, 1.570796f, 0, 0, 0.707107f, 0.707107f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER, BG_OBJECT_HU_TOWER_CAP_EY_ENTRY, 2282.121582f, 1760.006958f, 1189.707153f, 1.919862f, 0, 0, 0.819152f, 0.573576f, RESPAWN_ONE_DAY) -) - { - sLog.outErrorDb("BatteGroundEY: Failed to spawn some object BattleGround not created!"); - return false; - } - - //buffs - for (int i = 0; i < EY_POINTS_MAX; ++i) - { - AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(m_Points_Trigger[i]); - if (!at) - { - sLog.outError("BattleGroundEY: Unknown trigger: %u", m_Points_Trigger[i]); - continue; - } - if (!AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3, Buff_Entries[0], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3 + 1, Buff_Entries[1], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) - || !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3 + 2, Buff_Entries[2], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) -) - sLog.outError("BattleGroundEY: Cannot spawn buff"); - } - - WorldSafeLocsEntry const *sg = NULL; - sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_ALLIANCE); - if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE)) - { - sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!"); - return false; - } - - sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_HORDE); - if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE)) - { - sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!"); - return false; - } - - return true; -} - -void BattleGroundEY::Reset() -{ - //call parent's class reset - BattleGround::Reset(); - - m_TeamScores[BG_TEAM_ALLIANCE] = 0; - m_TeamScores[BG_TEAM_HORDE] = 0; - m_TeamPointsCount[BG_TEAM_ALLIANCE] = 0; - m_TeamPointsCount[BG_TEAM_HORDE] = 0; - m_HonorScoreTics[BG_TEAM_ALLIANCE] = 0; - m_HonorScoreTics[BG_TEAM_HORDE] = 0; - m_FlagState = BG_EY_FLAG_STATE_ON_BASE; - m_FlagCapturedBgObjectType = 0; - m_FlagKeeper = 0; - m_DroppedFlagGUID = 0; - m_PointAddingTimer = 0; - m_TowerCapCheckTimer = 0; - bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); - m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks; - - for (uint8 i = 0; i < EY_POINTS_MAX; ++i) - { - m_PointOwnedByTeam[i] = EY_POINT_NO_OWNER; - m_PointState[i] = EY_POINT_STATE_UNCONTROLLED; - m_PointBarStatus[i] = BG_EY_PROGRESS_BAR_STATE_MIDDLE; - m_PlayersNearPoint[i].clear(); - m_PlayersNearPoint[i].reserve(15); //tip size - } - m_PlayersNearPoint[EY_PLAYERS_OUT_OF_POINTS].clear(); - m_PlayersNearPoint[EY_PLAYERS_OUT_OF_POINTS].reserve(30); -} - -void BattleGroundEY::RespawnFlag(bool send_message) -{ - if (m_FlagCapturedBgObjectType > 0) - SpawnBGObject(m_FlagCapturedBgObjectType, RESPAWN_ONE_DAY); - - m_FlagCapturedBgObjectType = 0; - m_FlagState = BG_EY_FLAG_STATE_ON_BASE; - SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY); - - if (send_message) - { - SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL); - PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound... - } - - UpdateWorldState(NETHERSTORM_FLAG, 1); -} - -void BattleGroundEY::RespawnFlagAfterDrop() -{ - RespawnFlag(true); - - GameObject *obj = HashMapHolder::Find(GetDroppedFlagGUID()); - if (obj) - obj->Delete(); - else - sLog.outError("BattleGroundEY: Unknown dropped flag guid: %u",GUID_LOPART(GetDroppedFlagGUID())); - - SetDroppedFlagGUID(0); -} - -void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - BattleGround::HandleKillPlayer(player, killer); - EventPlayerDroppedFlag(player); -} - -void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - { - // if not running, do not cast things at the dropper player, neither send unnecessary messages - // just take off the aura - if (IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID()) - { - SetFlagPicker(0); - Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); - } - return; - } - - if (!IsFlagPickedup()) - return; - - if (GetFlagPickerGUID() != Source->GetGUID()) - return; - - SetFlagPicker(0); - Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); - m_FlagState = BG_EY_FLAG_STATE_ON_GROUND; - m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; - Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); - Source->CastSpell(Source, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true); - //this does not work correctly :((it should remove flag carrier name) - UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_WAIT_RESPAWN); - UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN); - - if (Source->GetTeam() == ALLIANCE) - SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL); - else - SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL); -} - -void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) -{ - if (GetStatus() != STATUS_IN_PROGRESS || IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10)) - return; - - if (Source->GetTeam() == ALLIANCE) - { - UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_PLAYER); - PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE); - } - else - { - UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_PLAYER); - PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_HORDE); - } - - if (m_FlagState == BG_EY_FLAG_STATE_ON_BASE) - UpdateWorldState(NETHERSTORM_FLAG, 0); - m_FlagState = BG_EY_FLAG_STATE_ON_PLAYER; - - SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_ONE_DAY); - SetFlagPicker(Source->GetGUID()); - //get flag aura on player - Source->CastSpell(Source, BG_EY_NETHERSTORM_FLAG_SPELL, true); - Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); - - if (Source->GetTeam() == ALLIANCE) - PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, Source->GetName()); - else - PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL, Source->GetName()); -} - -void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - //Natural point - uint32 Team = m_PointOwnedByTeam[Point]; - - if (!Team) - return; - - if (Team == ALLIANCE) - { - m_TeamPointsCount[BG_TEAM_ALLIANCE]--; - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY); - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY); - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY); - } - else - { - m_TeamPointsCount[BG_TEAM_HORDE]--; - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY); - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY); - SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY); - } - - SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType + 1, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType + 2, RESPAWN_IMMEDIATELY); - - //buff isn't despawned - - m_PointOwnedByTeam[Point] = EY_POINT_NO_OWNER; - m_PointState[Point] = EY_POINT_NO_OWNER; - - if (Team == ALLIANCE) - SendMessageToAll(m_LoosingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); - else - SendMessageToAll(m_LoosingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); - - UpdatePointsIcons(Team, Point); - UpdatePointsCount(Team); - - //remove bonus honor aura trigger creature when node is lost - if (Point < EY_POINTS_MAX) - DelCreature(Point + 6);//NULL checks are in DelCreature! 0-5 spirit guides -} - -void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - uint32 Team = Source->GetTeam(); - - SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType, RESPAWN_ONE_DAY); - SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType + 1, RESPAWN_ONE_DAY); - SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType + 2, RESPAWN_ONE_DAY); - - if (Team == ALLIANCE) - { - m_TeamPointsCount[BG_TEAM_ALLIANCE]++; - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY); - } - else - { - m_TeamPointsCount[BG_TEAM_HORDE]++; - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY); - SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY); - } - - //buff isn't respawned - - m_PointOwnedByTeam[Point] = Team; - m_PointState[Point] = EY_POINT_UNDER_CONTROL; - - if (Team == ALLIANCE) - SendMessageToAll(m_CapturingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); - else - SendMessageToAll(m_CapturingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); - - if (m_BgCreatures[Point]) - DelCreature(Point); - - WorldSafeLocsEntry const *sg = NULL; - sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveYardId); - if (!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, Team)) - sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u", - Point, Team, m_CapturingPointTypes[Point].GraveYardId); - -// SpawnBGCreature(Point,RESPAWN_IMMEDIATELY); - - UpdatePointsIcons(Team, Point); - UpdatePointsCount(Team); - - if (Point >= EY_POINTS_MAX) - return; - - Creature* trigger = GetBGCreature(Point + 6);//0-5 spirit guides - if (!trigger) - trigger = AddCreature(WORLD_TRIGGER,Point+6,Team,BG_EY_TriggerPositions[Point][0],BG_EY_TriggerPositions[Point][1],BG_EY_TriggerPositions[Point][2],BG_EY_TriggerPositions[Point][3]); - - //add bonus honor aura trigger creature when node is accupied - //cast bonus aura (+50% honor in 25yards) - //aura should only apply to players who have accupied the node, set correct faction for trigger - if (trigger) - { - trigger->setFaction(Team == ALLIANCE ? 84 : 83); - trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); - } -} - -void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType) -{ - if (GetStatus() != STATUS_IN_PROGRESS || GetFlagPickerGUID() != Source->GetGUID()) - return; - - SetFlagPicker(0); - m_FlagState = BG_EY_FLAG_STATE_WAIT_RESPAWN; - Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); - - Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); - - if (Source->GetTeam() == ALLIANCE) - PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE); - else - PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE); - - SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY); - - m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; - m_FlagCapturedBgObjectType = BgObjectType; - - uint8 team_id = 0; - if (Source->GetTeam() == ALLIANCE) - { - team_id = BG_TEAM_ALLIANCE; - SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); - } - else - { - team_id = BG_TEAM_HORDE; - SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, Source); - } - - if (m_TeamPointsCount[team_id] > 0) - AddPoints(Source->GetTeam(), BG_EY_FlagPoints[m_TeamPointsCount[team_id] - 1]); - - UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); -} - -void BattleGroundEY::UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor) -{ - BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found - return; - - switch(type) - { - case SCORE_FLAG_CAPTURES: // flags captured - ((BattleGroundEYScore*)itr->second)->FlagCaptures += value; - break; - default: - BattleGround::UpdatePlayerScore(Source, type, value, doAddHonor); - break; - } -} - -void BattleGroundEY::FillInitialWorldStates(WorldPacket& data) -{ - data << uint32(EY_HORDE_BASE) << uint32(m_TeamPointsCount[BG_TEAM_HORDE]); - data << uint32(EY_ALLIANCE_BASE) << uint32(m_TeamPointsCount[BG_TEAM_ALLIANCE]); - data << uint32(0xab6) << uint32(0x0); - data << uint32(0xab5) << uint32(0x0); - data << uint32(0xab4) << uint32(0x0); - data << uint32(0xab3) << uint32(0x0); - data << uint32(0xab2) << uint32(0x0); - data << uint32(0xab1) << uint32(0x0); - data << uint32(0xab0) << uint32(0x0); - data << uint32(0xaaf) << uint32(0x0); - - data << uint32(DRAENEI_RUINS_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[DRAENEI_RUINS] == HORDE && m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL); - - data << uint32(DRAENEI_RUINS_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[DRAENEI_RUINS] == ALLIANCE && m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL); - - data << uint32(DRAENEI_RUINS_UNCONTROL) << uint32(m_PointState[DRAENEI_RUINS] != EY_POINT_UNDER_CONTROL); - - data << uint32(MAGE_TOWER_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[MAGE_TOWER] == ALLIANCE && m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL); - - data << uint32(MAGE_TOWER_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[MAGE_TOWER] == HORDE && m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL); - - data << uint32(MAGE_TOWER_UNCONTROL) << uint32(m_PointState[MAGE_TOWER] != EY_POINT_UNDER_CONTROL); - - data << uint32(FEL_REAVER_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[FEL_REALVER] == HORDE && m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL); - - data << uint32(FEL_REAVER_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[FEL_REALVER] == ALLIANCE && m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL); - - data << uint32(FEL_REAVER_UNCONTROL) << uint32(m_PointState[FEL_REALVER] != EY_POINT_UNDER_CONTROL); - - data << uint32(BLOOD_ELF_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[BLOOD_ELF] == HORDE && m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL); - - data << uint32(BLOOD_ELF_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[BLOOD_ELF] == ALLIANCE && m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL); - - data << uint32(BLOOD_ELF_UNCONTROL) << uint32(m_PointState[BLOOD_ELF] != EY_POINT_UNDER_CONTROL); - - data << uint32(NETHERSTORM_FLAG) << uint32(m_FlagState == BG_EY_FLAG_STATE_ON_BASE); - - data << uint32(0xad2) << uint32(0x1); - data << uint32(0xad1) << uint32(0x1); - data << uint32(0xabe) << uint32(GetTeamScore(HORDE)); - data << uint32(0xabd) << uint32(GetTeamScore(ALLIANCE)); - data << uint32(0xa05) << uint32(0x8e); - data << uint32(0xaa0) << uint32(0x0); - data << uint32(0xa9f) << uint32(0x0); - data << uint32(0xa9e) << uint32(0x0); - data << uint32(0xc0d) << uint32(0x17b); -} - -WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player) -{ - uint32 g_id = 0; - - switch(player->GetTeam()) - { - case ALLIANCE: g_id = EY_GRAVEYARD_MAIN_ALLIANCE; break; - case HORDE: g_id = EY_GRAVEYARD_MAIN_HORDE; break; - default: return NULL; - } - - float distance, nearestDistance; - - WorldSafeLocsEntry const* entry = NULL; - WorldSafeLocsEntry const* nearestEntry = NULL; - entry = sWorldSafeLocsStore.LookupEntry(g_id); - nearestEntry = entry; - - if (!entry) - { - sLog.outError("BattleGroundEY: Not found the main team graveyard. Graveyard system isn't working!"); - return NULL; - } - - float plr_x = player->GetPositionX(); - float plr_y = player->GetPositionY(); - float plr_z = player->GetPositionZ(); - - distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z); - nearestDistance = distance; - - for (uint8 i = 0; i < EY_POINTS_MAX; ++i) - { - if (m_PointOwnedByTeam[i] == player->GetTeam() && m_PointState[i] == EY_POINT_UNDER_CONTROL) - { - entry = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[i].GraveYardId); - if (!entry) - sLog.outError("BattleGroundEY: Not found graveyard: %u",m_CapturingPointTypes[i].GraveYardId); - else - { - distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z); - if (distance < nearestDistance) - { - nearestDistance = distance; - nearestEntry = entry; - } - } - } - } - - return nearestEntry; -} - -bool BattleGroundEY::IsAllNodesConrolledByTeam(uint32 team) const -{ - uint32 count = 0; - for (int i = 0; i < EY_POINTS_MAX; ++i) - if (m_PointOwnedByTeam[i] == team && m_PointState[i] == EY_POINT_UNDER_CONTROL) - ++count; - - return count == EY_POINTS_MAX; -} diff --git a/src/server/game/BattleGrounds/BattleGroundEY.h b/src/server/game/BattleGrounds/BattleGroundEY.h deleted file mode 100644 index 4fe23c4c821..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundEY.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __BATTLEGROUNDEY_H -#define __BATTLEGROUNDEY_H - -#include "Language.h" - -class BattleGround; - -#define BG_EY_FLAG_RESPAWN_TIME (8*IN_MILISECONDS) //8 seconds -#define BG_EY_FPOINTS_TICK_TIME (2*IN_MILISECONDS) //2 seconds - -enum BG_EY_WorldStates -{ - EY_ALLIANCE_RESOURCES = 2749, - EY_HORDE_RESOURCES = 2750, - EY_ALLIANCE_BASE = 2752, - EY_HORDE_BASE = 2753, - DRAENEI_RUINS_HORDE_CONTROL = 2733, - DRAENEI_RUINS_ALLIANCE_CONTROL = 2732, - DRAENEI_RUINS_UNCONTROL = 2731, - MAGE_TOWER_ALLIANCE_CONTROL = 2730, - MAGE_TOWER_HORDE_CONTROL = 2729, - MAGE_TOWER_UNCONTROL = 2728, - FEL_REAVER_HORDE_CONTROL = 2727, - FEL_REAVER_ALLIANCE_CONTROL = 2726, - FEL_REAVER_UNCONTROL = 2725, - BLOOD_ELF_HORDE_CONTROL = 2724, - BLOOD_ELF_ALLIANCE_CONTROL = 2723, - BLOOD_ELF_UNCONTROL = 2722, - PROGRESS_BAR_PERCENT_GREY = 2720, //100 = empty (only grey), 0 = blue|red (no grey) - PROGRESS_BAR_STATUS = 2719, //50 init!, 48 ... hordak bere .. 33 .. 0 = full 100% hordacky , 100 = full alliance - PROGRESS_BAR_SHOW = 2718, //1 init, 0 druhy send - bez messagu, 1 = controlled aliance - NETHERSTORM_FLAG = 2757, - //set to 2 when flag is picked up, and to 1 if it is dropped - NETHERSTORM_FLAG_STATE_ALLIANCE = 2769, - NETHERSTORM_FLAG_STATE_HORDE = 2770 -}; - -enum BG_EY_ProgressBarConsts -{ - BG_EY_POINT_MAX_CAPTURERS_COUNT = 5, - BG_EY_POINT_RADIUS = 70, - BG_EY_PROGRESS_BAR_DONT_SHOW = 0, - BG_EY_PROGRESS_BAR_SHOW = 1, - BG_EY_PROGRESS_BAR_PERCENT_GREY = 40, - BG_EY_PROGRESS_BAR_STATE_MIDDLE = 50, - BG_EY_PROGRESS_BAR_HORDE_CONTROLLED = 0, - BG_EY_PROGRESS_BAR_NEUTRAL_LOW = 30, - BG_EY_PROGRESS_BAR_NEUTRAL_HIGH = 70, - BG_EY_PROGRESS_BAR_ALI_CONTROLLED = 100 -}; - -enum BG_EY_Sounds -{ - //strange ids, but sure about them - BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE = 8212, - BG_EY_SOUND_FLAG_CAPTURED_HORDE = 8213, - BG_EY_SOUND_FLAG_PICKED_UP_HORDE = 8174, - BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, - BG_EY_SOUND_FLAG_RESET = 8192 -}; - -enum BG_EY_Spells -{ - BG_EY_NETHERSTORM_FLAG_SPELL = 34976, - BG_EY_PLAYER_DROPPED_FLAG_SPELL = 34991 -}; - -enum EYBattleGroundObjectEntry -{ - BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door - BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door - BG_OBJECT_FLAG1_EY_ENTRY = 184493, //Netherstorm flag (generic) - BG_OBJECT_FLAG2_EY_ENTRY = 184141, //Netherstorm flag (flagstand) - BG_OBJECT_FLAG3_EY_ENTRY = 184142, //Netherstorm flag (flagdrop) - BG_OBJECT_A_BANNER_EY_ENTRY = 184381, //Visual Banner (Alliance) - BG_OBJECT_H_BANNER_EY_ENTRY = 184380, //Visual Banner (Horde) - BG_OBJECT_N_BANNER_EY_ENTRY = 184382, //Visual Banner (Neutral) - BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt - BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt - BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt - BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083 //Draenei Tower Cap Pt -}; - -enum EYBattleGroundPointsTrigger -{ - TR_BLOOD_ELF_POINT = 4476, - TR_FEL_REALVER_POINT = 4514, - TR_MAGE_TOWER_POINT = 4516, - TR_DRAENEI_RUINS_POINT = 4518, - TR_BLOOD_ELF_BUFF = 4568, - TR_FEL_REALVER_BUFF = 4569, - TR_MAGE_TOWER_BUFF = 4570, - TR_DRAENEI_RUINS_BUFF = 4571 -}; - -enum EYBattleGroundGaveyards -{ - EY_GRAVEYARD_MAIN_ALLIANCE = 1103, - EY_GRAVEYARD_MAIN_HORDE = 1104, - EY_GRAVEYARD_FEL_REALVER = 1105, - EY_GRAVEYARD_BLOOD_ELF = 1106, - EY_GRAVEYARD_DRAENEI_RUINS = 1107, - EY_GRAVEYARD_MAGE_TOWER = 1108 -}; - -enum EYBattleGroundPoints -{ - FEL_REALVER = 0, - BLOOD_ELF = 1, - DRAENEI_RUINS = 2, - MAGE_TOWER = 3, - - EY_PLAYERS_OUT_OF_POINTS = 4, - EY_POINTS_MAX = 4 -}; - -enum EYBattleGroundCreaturesTypes -{ - EY_SPIRIT_FEL_REALVER = 0, - EY_SPIRIT_BLOOD_ELF = 1, - EY_SPIRIT_DRAENEI_RUINS = 2, - EY_SPIRIT_MAGE_TOWER = 3, - EY_SPIRIT_MAIN_ALLIANCE = 4, - EY_SPIRIT_MAIN_HORDE = 5, - - EY_TRIGGER_FEL_REALVER = 6, - EY_TRIGGER_BLOOD_ELF = 7, - EY_TRIGGER_DRAENEI_RUINS = 8, - EY_TRIGGER_MAGE_TOWER = 9, - - BG_EY_CREATURES_MAX = 10 -}; - -enum EYBattleGroundObjectTypes -{ - BG_EY_OBJECT_DOOR_A = 0, - BG_EY_OBJECT_DOOR_H = 1, - BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER = 2, - BG_EY_OBJECT_A_BANNER_FEL_REALVER_LEFT = 3, - BG_EY_OBJECT_A_BANNER_FEL_REALVER_RIGHT = 4, - BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER = 5, - BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT = 6, - BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT = 7, - BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER = 8, - BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT = 9, - BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT = 10, - BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER = 11, - BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT = 12, - BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT = 13, - BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER = 14, - BG_EY_OBJECT_H_BANNER_FEL_REALVER_LEFT = 15, - BG_EY_OBJECT_H_BANNER_FEL_REALVER_RIGHT = 16, - BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER = 17, - BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT = 18, - BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT = 19, - BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER = 20, - BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT = 21, - BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT = 22, - BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER = 23, - BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT = 24, - BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT = 25, - BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER = 26, - BG_EY_OBJECT_N_BANNER_FEL_REALVER_LEFT = 27, - BG_EY_OBJECT_N_BANNER_FEL_REALVER_RIGHT = 28, - BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER = 29, - BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT = 30, - BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT = 31, - BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER = 32, - BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT = 33, - BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT = 34, - BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER = 35, - BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT = 36, - BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT = 37, - BG_EY_OBJECT_TOWER_CAP_FEL_REALVER = 38, - BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF = 39, - BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS = 40, - BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER = 41, - BG_EY_OBJECT_FLAG_NETHERSTORM = 42, - BG_EY_OBJECT_FLAG_FEL_REALVER = 43, - BG_EY_OBJECT_FLAG_BLOOD_ELF = 44, - BG_EY_OBJECT_FLAG_DRAENEI_RUINS = 45, - BG_EY_OBJECT_FLAG_MAGE_TOWER = 46, - //buffs - BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER = 47, - BG_EY_OBJECT_REGENBUFF_FEL_REALVER = 48, - BG_EY_OBJECT_BERSERKBUFF_FEL_REALVER = 49, - BG_EY_OBJECT_SPEEDBUFF_BLOOD_ELF = 50, - BG_EY_OBJECT_REGENBUFF_BLOOD_ELF = 51, - BG_EY_OBJECT_BERSERKBUFF_BLOOD_ELF = 52, - BG_EY_OBJECT_SPEEDBUFF_DRAENEI_RUINS = 53, - BG_EY_OBJECT_REGENBUFF_DRAENEI_RUINS = 54, - BG_EY_OBJECT_BERSERKBUFF_DRAENEI_RUINS = 55, - BG_EY_OBJECT_SPEEDBUFF_MAGE_TOWER = 56, - BG_EY_OBJECT_REGENBUFF_MAGE_TOWER = 57, - BG_EY_OBJECT_BERSERKBUFF_MAGE_TOWER = 58, - BG_EY_OBJECT_MAX = 59 -}; - -#define BG_EY_NotEYWeekendHonorTicks 330 -#define BG_EY_EYWeekendHonorTicks 200 - -enum BG_EY_Score -{ - BG_EY_WARNING_NEAR_VICTORY_SCORE = 1400, - BG_EY_MAX_TEAM_SCORE = 1600 -}; - -enum BG_EY_FlagState -{ - BG_EY_FLAG_STATE_ON_BASE = 0, - BG_EY_FLAG_STATE_WAIT_RESPAWN = 1, - BG_EY_FLAG_STATE_ON_PLAYER = 2, - BG_EY_FLAG_STATE_ON_GROUND = 3 -}; - -enum EYBattleGroundPointState -{ - EY_POINT_NO_OWNER = 0, - EY_POINT_STATE_UNCONTROLLED = 0, - EY_POINT_UNDER_CONTROL = 3 -}; - -struct BattleGroundEYPointIconsStruct -{ - BattleGroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex) - : WorldStateControlIndex(_WorldStateControlIndex), WorldStateAllianceControlledIndex(_WorldStateAllianceControlledIndex), WorldStateHordeControlledIndex(_WorldStateHordeControlledIndex) {} - uint32 WorldStateControlIndex; - uint32 WorldStateAllianceControlledIndex; - uint32 WorldStateHordeControlledIndex; -}; - -// x, y, z, o -const float BG_EY_TriggerPositions[EY_POINTS_MAX][4] = { - {2044.28f, 1729.68f, 1189.96f, -0.017453f}, // FEL_REALVER center - {2048.83f, 1393.65f, 1194.49f, 0.20944f}, // BLOOD_ELF center - {2286.56f, 1402.36f, 1197.11f, 3.72381f}, // DRAENEI_RUINS center - {2284.48f, 1731.23f, 1189.99f, 2.89725f} // MAGE_TOWER center -}; - -struct BattleGroundEYLoosingPointStruct -{ - BattleGroundEYLoosingPointStruct(uint32 _SpawnNeutralObjectType, uint32 _DespawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _DespawnObjectTypeHorde, uint32 _MessageIdHorde) - : SpawnNeutralObjectType(_SpawnNeutralObjectType), - DespawnObjectTypeAlliance(_DespawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), - DespawnObjectTypeHorde(_DespawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde) - {} - - uint32 SpawnNeutralObjectType; - uint32 DespawnObjectTypeAlliance; - uint32 MessageIdAlliance; - uint32 DespawnObjectTypeHorde; - uint32 MessageIdHorde; -}; - -struct BattleGroundEYCapturingPointStruct -{ - BattleGroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId) - : DespawnNeutralObjectType(_DespawnNeutralObjectType), - SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), - SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde), - GraveYardId(_GraveYardId) - {} - - uint32 DespawnNeutralObjectType; - uint32 SpawnObjectTypeAlliance; - uint32 MessageIdAlliance; - uint32 SpawnObjectTypeHorde; - uint32 MessageIdHorde; - uint32 GraveYardId; -}; - -const uint8 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10}; -const uint32 BG_EY_FlagPoints[EY_POINTS_MAX] = {75, 85, 100, 500}; - -//constant arrays: -const BattleGroundEYPointIconsStruct m_PointsIconStruct[EY_POINTS_MAX] = -{ - BattleGroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL), - BattleGroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL), - BattleGroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL), - BattleGroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL) -}; -const BattleGroundEYLoosingPointStruct m_LoosingPointTypes[EY_POINTS_MAX] = -{ - BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_LOST_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_LOST_H_F_RUINS), - BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_H_B_TOWER), - BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_H_D_RUINS), - BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_H_M_TOWER) -}; -const BattleGroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] = -{ - BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_TAKEN_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_TAKEN_H_F_RUINS, EY_GRAVEYARD_FEL_REALVER), - BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_H_B_TOWER, EY_GRAVEYARD_BLOOD_ELF), - BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_H_D_RUINS, EY_GRAVEYARD_DRAENEI_RUINS), - BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, EY_GRAVEYARD_MAGE_TOWER) -}; - -class BattleGroundEYScore : public BattleGroundScore -{ - public: - BattleGroundEYScore () : FlagCaptures(0) {}; - virtual ~BattleGroundEYScore() {}; - uint32 FlagCaptures; -}; - -class BattleGroundEY : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundEY(); - ~BattleGroundEY(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - /* BG Flags */ - uint64 GetFlagPickerGUID() const { return m_FlagKeeper; } - void SetFlagPicker(uint64 guid) { m_FlagKeeper = guid; } - bool IsFlagPickedup() const { return m_FlagKeeper != 0; } - uint8 GetFlagState() const { return m_FlagState; } - void RespawnFlag(bool send_message); - void RespawnFlagAfterDrop(); - - void RemovePlayer(Player *plr,uint64 guid); - void HandleBuffUse(uint64 const& buff_guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - void HandleKillPlayer(Player *player, Player *killer); - virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); - virtual bool SetupBattleGround(); - virtual void Reset(); - void UpdateTeamScore(uint32 Team); - void EndBattleGround(uint32 winner); - void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); - virtual void FillInitialWorldStates(WorldPacket& data); - void SetDroppedFlagGUID(uint64 guid) { m_DroppedFlagGUID = guid;} - uint64 GetDroppedFlagGUID() const { return m_DroppedFlagGUID;} - - /* Battleground Events */ - virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); - virtual void EventPlayerDroppedFlag(Player *Source); - - /* achievement req. */ - bool IsAllNodesConrolledByTeam(uint32 team) const; - private: - void EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType); - void EventTeamCapturedPoint(Player *Source, uint32 Point); - void EventTeamLostPoint(Player *Source, uint32 Point); - void UpdatePointsCount(uint32 Team); - void UpdatePointsIcons(uint32 Team, uint32 Point); - - /* Point status updating procedures */ - void CheckSomeoneLeftPoint(); - void CheckSomeoneJoinedPoint(); - void UpdatePointStatuses(); - - /* Scorekeeping */ - uint32 GetTeamScore(uint32 Team) const { return m_TeamScores[GetTeamIndexByTeamId(Team)]; } - void AddPoints(uint32 Team, uint32 Points); - - void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } - void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } - - uint32 m_HonorScoreTics[2]; - uint32 m_TeamPointsCount[2]; - - uint32 m_Points_Trigger[EY_POINTS_MAX]; - - uint64 m_FlagKeeper; // keepers guid - uint64 m_DroppedFlagGUID; - uint32 m_FlagCapturedBgObjectType; // type that should be despawned when flag is captured - uint8 m_FlagState; // for checking flag state - int32 m_FlagsTimer; - int32 m_TowerCapCheckTimer; - - uint32 m_PointOwnedByTeam[EY_POINTS_MAX]; - uint8 m_PointState[EY_POINTS_MAX]; - int32 m_PointBarStatus[EY_POINTS_MAX]; - typedef std::vector PlayersNearPointType; - PlayersNearPointType m_PlayersNearPoint[EY_POINTS_MAX + 1]; - uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX]; - - int32 m_PointAddingTimer; - uint32 m_HonorTics; -}; -#endif - diff --git a/src/server/game/BattleGrounds/BattleGroundHandler.cpp b/src/server/game/BattleGrounds/BattleGroundHandler.cpp deleted file mode 100644 index e779f2a8ab1..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundHandler.cpp +++ /dev/null @@ -1,803 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "ObjectAccessor.h" -#include "ObjectMgr.h" -#include "WorldPacket.h" -#include "WorldSession.h" - -#include "ArenaTeam.h" -#include "BattleGroundMgr.h" -#include "BattleGroundWS.h" -#include "BattleGround.h" -#include "Chat.h" -#include "Language.h" -#include "Log.h" -#include "Player.h" -#include "Object.h" -#include "Opcodes.h" - -void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - sLog.outDebug("WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); - - Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); - if (!unit) - return; - - if (!unit->isBattleMaster()) // it's not battlemaster - return; - - // Stop the npc if moving - unit->StopMoving(); - - BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(unit->GetEntry()); - - if (!_player->GetBGAccessByLevel(bgTypeId)) - { - // temp, must be gossip message... - SendNotification(LANG_YOUR_BG_LEVEL_REQ_ERROR); - return; - } - - SendBattlegGroundList(guid, bgTypeId); -} - -void WorldSession::SendBattlegGroundList(uint64 guid, BattleGroundTypeId bgTypeId) -{ - WorldPacket data; - sBattleGroundMgr.BuildBattleGroundListPacket(&data, guid, _player, bgTypeId, 0); - SendPacket(&data); -} - -void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recv_data) -{ - uint64 guid; - uint32 bgTypeId_; - uint32 instanceId; - uint8 joinAsGroup; - bool isPremade = false; - Group * grp = NULL; - - recv_data >> guid; // battlemaster guid - recv_data >> bgTypeId_; // battleground type id (DBC id) - recv_data >> instanceId; // instance id, 0 if First Available selected - recv_data >> joinAsGroup; // join as group - - if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) - { - sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow()); - return; - } - - BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); - - sLog.outDebug("WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid))); - - // can do this, since it's battleground, not arena - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); - BattleGroundQueueTypeId bgQueueTypeIdRandom = BattleGroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); - - // ignore if player is already in BG - if (_player->InBattleGround()) - return; - - // get bg instance or bg template if instance not found - BattleGround *bg = NULL; - if (instanceId) - bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId); - - if (!bg) - bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - if (!bg) - return; - - // expected bracket entry - PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); - if (!bracketEntry) - return; - - GroupJoinBattlegroundResult err; - - // check queue conditions - if (!joinAsGroup) - { - // check Deserter debuff - if (!_player->CanJoinToBattleground()) - { - WorldPacket data; - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); - _player->GetSession()->SendPacket(&data); - return; - } - - if (_player->GetBattleGroundQueueIndex(bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES) - { - //player is already in random queue - WorldPacket data; - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_RANDOM_BG); - _player->GetSession()->SendPacket(&data); - return; - } - - if (_player->InBattleGroundQueue() && bgTypeId == BATTLEGROUND_RB) - { - //player is already in queue, can't start random queue - WorldPacket data; - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_NON_RANDOM_BG); - _player->GetSession()->SendPacket(&data); - return; - } - - // check if already in queue - if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) - //player is already in this queue - return; - - // check if has free queue slots - if (!_player->HasFreeBattleGroundQueueId()) - { - WorldPacket data; - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES); - _player->GetSession()->SendPacket(&data); - return; - } - - BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - - GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0); - uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); - // already checked if queueSlot is valid, now just get it - uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); - - WorldPacket data; - // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); - SendPacket(&data); - sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); - } - else - { - grp = _player->GetGroup(); - // no group found, error - if (!grp) - return; - if (grp->GetLeaderGUID() != _player->GetGUID()) - return; - err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); - isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); - - BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - GroupQueueInfo * ginfo = NULL; - uint32 avgTime = 0; - - if (err > 0) - { - sLog.outDebug("Battleground: the following players are joining as group:"); - ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0); - avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); - } - - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player *member = itr->getSource(); - if (!member) continue; // this should never happen - - WorldPacket data; - - if (err <= 0) - { - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); - member->GetSession()->SendPacket(&data); - continue; - } - - // add to queue - uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); - - // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); - member->GetSession()->SendPacket(&data); - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); - member->GetSession()->SendPacket(&data); - sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); - } - sLog.outDebug("Battleground: group end"); - - } - sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); -} - -void WorldSession::HandleBattleGroundPlayerPositionsOpcode(WorldPacket & /*recv_data*/) -{ - // empty opcode - sLog.outDebug("WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message"); - - BattleGround *bg = _player->GetBattleGround(); - if (!bg) // can't be received if player not in battleground - return; - - switch(bg->GetTypeID(true)) - { - case BATTLEGROUND_WS: - { - uint32 count1 = 0; //always constant zero? - uint32 count2 = 0; //count of next fields - - Player *ali_plr = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetAllianceFlagPickerGUID()); - if (ali_plr) - ++count2; - - Player *horde_plr = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetHordeFlagPickerGUID()); - if (horde_plr) - ++count2; - - WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4+16*count1+16*count2)); - data << count1; // alliance flag holders count - obsolete, now always 0 - /*for (uint8 i = 0; i < count1; ++i) - { - data << uint64(0); // guid - data << (float)0; // x - data << (float)0; // y - }*/ - data << count2; // horde flag holders count - obsolete, now count of next fields - if (ali_plr) - { - data << (uint64)ali_plr->GetGUID(); - data << (float)ali_plr->GetPositionX(); - data << (float)ali_plr->GetPositionY(); - } - if (horde_plr) - { - data << (uint64)horde_plr->GetGUID(); - data << (float)horde_plr->GetPositionX(); - data << (float)horde_plr->GetPositionY(); - } - - SendPacket(&data); - } - break; - case BATTLEGROUND_EY: - //TODO : fix me! - break; - case BATTLEGROUND_AB: - case BATTLEGROUND_AV: - { - //for other BG types - send default - WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4)); - data << uint32(0); - data << uint32(0); - SendPacket(&data); - } - break; - default: - //maybe it is sent also in arena - do nothing - break; - } -} - -void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: Recvd MSG_PVP_LOG_DATA Message"); - - BattleGround *bg = _player->GetBattleGround(); - if (!bg) - return; - - WorldPacket data; - sBattleGroundMgr.BuildPvpLogDataPacket(&data, bg); - SendPacket(&data); - - sLog.outDebug("WORLD: Sent MSG_PVP_LOG_DATA Message"); -} - -void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_BATTLEFIELD_LIST Message"); - - uint32 bgTypeId; - recv_data >> bgTypeId; // id from DBC - - uint8 fromWhere; - recv_data >> fromWhere; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo) - - uint8 unk1; - recv_data >> unk1; // Unknown 3.2.2 - - BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); - if (!bl) - { - sLog.outError("Battleground: invalid bgtype received."); - return; - } - - WorldPacket data; - sBattleGroundMgr.BuildBattleGroundListPacket(&data, 0, _player, BattleGroundTypeId(bgTypeId), fromWhere); - SendPacket(&data); -} - -void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); - - uint8 type; // arenatype if arena - uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 - uint32 bgTypeId_; // type id from dbc - uint16 unk; // 0x1F90 constant? - uint8 action; // enter battle 0x1, leave queue 0x0 - - recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action; - - if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) - { - sLog.outError("BattlegroundHandler: invalid bgtype (%u) received.", bgTypeId_); - return; - } - if (!_player->InBattleGroundQueue()) - { - sLog.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player->GetGUIDLow()); - return; - } - - //get GroupQueueInfo from BattleGroundQueue - BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, type); - BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function - GroupQueueInfo ginfo; - if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) - { - sLog.outError("BattlegroundHandler: itrplayerstatus not found."); - return; - } - // if action == 1, then instanceId is required - if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) - { - sLog.outError("BattlegroundHandler: instance not found."); - return; - } - - BattleGround *bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); - - // bg template might and must be used in case of leaving queue, when instance is not created yet - if (!bg && action == 0) - bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - if (!bg) - { - sLog.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId); - return; - } - - // expected bracket entry - PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); - if (!bracketEntry) - return; - - //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it - if (action == 1 && ginfo.ArenaType == 0) - { - //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue - if (!_player->CanJoinToBattleground()) - { - //send bg command result to show nice message - WorldPacket data2; - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); - _player->GetSession()->SendPacket(&data2); - action = 0; - sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); - } - //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue - if (_player->getLevel() > bg->GetMaxLevel()) - { - sLog.outError("Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!", - _player->GetName(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID()); - action = 0; - } - } - uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); - WorldPacket data; - switch(action) - { - case 1: // port to battleground - if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) - return; // cheating? - - if (!_player->InBattleGround()) - _player->SetBattleGroundEntryPoint(); - - // resurrect the player - if (!_player->isAlive()) - { - _player->ResurrectPlayer(1.0f); - _player->SpawnCorpseBones(); - } - // stop taxi flight at port - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType()); - _player->GetSession()->SendPacket(&data); - // remove battleground queue status from BGmgr - bgQueue.RemovePlayer(_player->GetGUID(), false); - // this is still needed here if battleground "jumping" shouldn't add deserter debuff - // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new - if (BattleGround *currentBg = _player->GetBattleGround()) - currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); - - // set the destination instance id - _player->SetBattleGroundId(bg->GetInstanceID(), bgTypeId); - // set the destination team - _player->SetBGTeam(ginfo.Team); - // bg->HandleBeforeTeleportToBattleGround(_player); - sBattleGroundMgr.SendToBattleGround(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); - // add only in HandleMoveWorldPortAck() - // bg->AddPlayer(_player,team); - sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId); - break; - case 0: // leave queue - // if player leaves rated arena match before match start, it is counted as he played but he lost - if (ginfo.IsRated) - { - ArenaTeam * at = objmgr.GetArenaTeamById(ginfo.Team); - if (at) - { - sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), ginfo.OpponentsTeamRating); - at->MemberLost(_player, ginfo.OpponentsTeamRating); - at->SaveToDB(); - } - } - _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0); - bgQueue.RemovePlayer(_player->GetGUID(), true); - // player left queue, we should update it - do not update Arena Queue - if (!ginfo.ArenaType) - sBattleGroundMgr.ScheduleQueueUpdate(ginfo.ArenaTeamRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); - SendPacket(&data); - sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId); - break; - default: - sLog.outError("Battleground port: unknown action %u", action); - break; - } -} - -void WorldSession::HandleLeaveBattlefieldOpcode(WorldPacket& recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message"); - - recv_data.read_skip(); // unk1 - recv_data.read_skip(); // unk2 - recv_data.read_skip(); // BattleGroundTypeId - recv_data.read_skip(); // unk3 - - // not allow leave battleground in combat - if (_player->isInCombat()) - if (BattleGround* bg = _player->GetBattleGround()) - if (bg->GetStatus() != STATUS_WAIT_LEAVE) - return; - - _player->LeaveBattleground(); -} - -void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recv_data*/) -{ - // empty opcode - sLog.outDebug("WORLD: Battleground status"); - - WorldPacket data; - // we must update all queues here - BattleGround *bg = NULL; - for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) - { - BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); - if (!bgQueueTypeId) - continue; - BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); - uint8 arenaType = BattleGroundMgr::BGArenaType(bgQueueTypeId); - if (bgTypeId == _player->GetBattleGroundTypeId()) - { - bg = _player->GetBattleGround(); - //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena - //so i must use bg pointer to get that information - if (bg && bg->GetArenaType() == arenaType) - { - // this line is checked, i only don't know if GetStartTime is changing itself after bg end! - // send status in BattleGround - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType); - SendPacket(&data); - continue; - } - } - //we are sending update to player about queue - he can be invited there! - //get GroupQueueInfo for queue status - BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - GroupQueueInfo ginfo; - if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) - continue; - if (ginfo.IsInvitedToBGInstanceGUID) - { - bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); - if (!bg) - continue; - uint32 remainingTime = getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime); - // send status invited to BattleGround - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType); - SendPacket(&data); - } - else - { - bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - if (!bg) - continue; - - // expected bracket entry - PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); - if (!bracketEntry) - continue; - - uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId()); - // send status in BattleGround Queue - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(ginfo.JoinTime, getMSTime()), arenaType); - SendPacket(&data); - } - } -} - -void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY"); - - BattleGround *bg = _player->GetBattleGround(); - - uint64 guid; - recv_data >> guid; - - Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); - if (!unit) - return; - - if (!unit->isSpiritService()) // it's not spirit service - return; - - if (bg) - sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, guid); -} - - -void WorldSession::HandleAreaSpiritHealerQueueOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE"); - - BattleGround *bg = _player->GetBattleGround(); - - uint64 guid; - recv_data >> guid; - - Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); - if (!unit) - return; - - if (!unit->isSpiritService()) // it's not spirit service - return; - - if (bg) - bg->AddPlayerToResurrectQueue(guid, _player->GetGUID()); -} - - -void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); - //recv_data.hexlike(); - - uint64 guid; // arena Battlemaster guid - uint8 arenaslot; // 2v2, 3v3 or 5v5 - uint8 asGroup; // asGroup - uint8 isRated; // isRated - Group * grp = NULL; - - recv_data >> guid >> arenaslot >> asGroup >> isRated; - - // ignore if we already in BG or BG queue - if (_player->InBattleGround()) - return; - - Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); - if (!unit) - return; - - if (!unit->isBattleMaster()) // it's not battle master - return; - - uint8 arenatype = 0; - uint32 arenaRating = 0; - - switch(arenaslot) - { - case 0: - arenatype = ARENA_TYPE_2v2; - break; - case 1: - arenatype = ARENA_TYPE_3v3; - break; - case 2: - arenatype = ARENA_TYPE_5v5; - break; - default: - sLog.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot); - return; - } - - //check existance - BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA); - if (!bg) - { - sLog.outError("Battleground: template bg (all arenas) not found"); - return; - } - - BattleGroundTypeId bgTypeId = bg->GetTypeID(); - BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); - PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); - if (!bracketEntry) - return; - - GroupJoinBattlegroundResult err = ERR_GROUP_JOIN_BATTLEGROUND_FAIL; - - if (!asGroup) - { - // check if already in queue - if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) - //player is already in this queue - return; - // check if has free queue slots - if (!_player->HasFreeBattleGroundQueueId()) - return; - } - else - { - grp = _player->GetGroup(); - // no group found, error - if (!grp) - return; - if (grp->GetLeaderGUID() != _player->GetGUID()) - return; - err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); - } - - uint32 ateamId = 0; - - if (isRated) - { - ateamId = _player->GetArenaTeamId(arenaslot); - // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) - ArenaTeam * at = objmgr.GetArenaTeamById(ateamId); - if (!at) - { - _player->GetSession()->SendNotInArenaTeamPacket(arenatype); - return; - } - // get the team rating for queueing - arenaRating = at->GetRating(); - // the arenateam id must match for everyone in the group - // get the personal ratings for queueing - uint32 avg_pers_rating = 0; - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player *member = itr->getSource(); - - // calc avg personal rating - avg_pers_rating += member->GetArenaPersonalRating(arenaslot); - } - - if (arenatype) - avg_pers_rating /= arenatype; - - // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating - if (avg_pers_rating + 150 < arenaRating) - arenaRating = avg_pers_rating; - - if (arenaRating <= 0) - arenaRating = 1; - } - - BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; - if (asGroup) - { - uint32 avgTime = 0; - - if (err > 0) - { - sLog.outDebug("Battleground: arena join as group start"); - if (isRated) - { - sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype); - bg->SetRated(true); - } - else - bg->SetRated(false); - - GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); - avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); - } - - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player *member = itr->getSource(); - if (!member) - continue; - - WorldPacket data; - - if (err <= 0) - { - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); - member->GetSession()->SendPacket(&data); - continue; - } - - // add to queue - uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); - - // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); - member->GetSession()->SendPacket(&data); - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); - member->GetSession()->SendPacket(&data); - sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); - } - } - else - { - GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); - uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); - uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); - - WorldPacket data; - // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); - SendPacket(&data); - sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); - } - sBattleGroundMgr.ScheduleQueueUpdate(arenaRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); -} - -void WorldSession::HandleReportPvPAFK(WorldPacket & recv_data) -{ - uint64 playerGuid; - recv_data >> playerGuid; - Player *reportedPlayer = objmgr.GetPlayer(playerGuid); - - if (!reportedPlayer) - { - sLog.outDebug("WorldSession::HandleReportPvPAFK: player not found"); - return; - } - - sLog.outDebug("WorldSession::HandleReportPvPAFK: %s reported %s", _player->GetName(), reportedPlayer->GetName()); - - reportedPlayer->ReportedAfkBy(_player); -} diff --git a/src/server/game/BattleGrounds/BattleGroundIC.cpp b/src/server/game/BattleGrounds/BattleGroundIC.cpp deleted file mode 100644 index 8dbcc81e5c6..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundIC.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Player.h" -#include "BattleGround.h" -#include "BattleGroundIC.h" -#include "Language.h" - -BattleGroundIC::BattleGroundIC() -{ - m_BgCreatures.resize(2); - m_BgObjects.resize(5); - //TODO FIX ME! - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; -} - -BattleGroundIC::~BattleGroundIC() -{ - -} - -void BattleGroundIC::Update(uint32 diff) -{ - BattleGround::Update(diff); -} - -void BattleGroundIC::StartingEventCloseDoors() -{ -} - -void BattleGroundIC::StartingEventOpenDoors() -{ -} - -void BattleGroundIC::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundICScore* sc = new BattleGroundICScore; - - m_PlayerScores[plr->GetGUID()] = sc; -} - -void BattleGroundIC::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) -{ - -} - -void BattleGroundIC::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) -{ - // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; -} - -void BattleGroundIC::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) -{ - - std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); - - if (itr == m_PlayerScores.end()) // player not found... - return; - - BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); -} - -bool BattleGroundIC::SetupBattleGround() -{ - AddObject(0, 195157, 459.72f, -419.93f, 42.55f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); - AddObject(1, 195158, 797.72f, -1009.48f, 138.52f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); - AddObject(2, 195338, 418.98f, -838.33f, 51.09f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); - AddObject(3, 195343, 1267.45f, -390.88f, 24.23f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); - AddObject(4, 195333, 769.27f, -833.53f, 9.57f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); - SpawnLeader(ALLIANCE); - SpawnLeader(HORDE); - return true; -} - -void BattleGroundIC::SpawnLeader(uint32 teamid) -{ - if (teamid == ALLIANCE) - AddCreature(34924, 0, ALLIANCE, 307.03f, -833.04f, 48.91f, 6.23f, 10*MINUTE); - else - AddCreature(34922, 1, HORDE, 1264.42f, -766.80f, 48.91f, 3.28f, 10*MINUTE); -} - -void BattleGroundIC::HandleKillUnit(Creature *unit, Player * /*killer*/) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - uint32 entry = unit->GetEntry(); - if (entry == 34924) - { - RewardHonorToTeam(500,HORDE); - EndBattleGround(HORDE); - } - else if (entry == 34922) - { - RewardHonorToTeam(500,ALLIANCE); - EndBattleGround(ALLIANCE); - } -} - -void BattleGroundIC::EndBattleGround(uint32 winner) -{ - BattleGround::EndBattleGround(winner); -} - -void BattleGroundIC::EventPlayerClickedOnFlag(Player * /*source*/, GameObject* /*target_obj*/) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; -} diff --git a/src/server/game/BattleGrounds/BattleGroundIC.h b/src/server/game/BattleGrounds/BattleGroundIC.h deleted file mode 100644 index e49ea01e850..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundIC.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __BATTLEGROUNDIC_H -#define __BATTLEGROUNDIC_H - -class BattleGround; - -enum Buffs -{ - OIL_REFINERY = 68719, - QUARRY = 68720 -}; - -class BattleGroundICScore : public BattleGroundScore -{ - public: - BattleGroundICScore() {}; - virtual ~BattleGroundICScore() {}; -}; - -class BattleGroundIC : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundIC(); - ~BattleGroundIC(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - void RemovePlayer(Player *plr,uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - bool SetupBattleGround(); - void SpawnLeader(uint32 teamid); - void HandleKillUnit(Creature *unit, Player *killer); - void EndBattleGround(uint32 winner); - void EventPlayerClickedOnFlag(Player *source, GameObject* /*target_obj*/); - - /* Scorekeeping */ - void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); - - private: -}; -#endif diff --git a/src/server/game/BattleGrounds/BattleGroundNA.cpp b/src/server/game/BattleGrounds/BattleGroundNA.cpp deleted file mode 100644 index 793cf13b3cb..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundNA.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BattleGround.h" -#include "BattleGroundNA.h" -#include "Language.h" -#include "Object.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "WorldPacket.h" - -BattleGroundNA::BattleGroundNA() -{ - m_BgObjects.resize(BG_NA_OBJECT_MAX); - - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; - //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; -} - -BattleGroundNA::~BattleGroundNA() -{ - -} - -void BattleGroundNA::Update(uint32 diff) -{ - BattleGround::Update(diff); - - /*if (GetStatus() == STATUS_IN_PROGRESS) - { - // update something - }*/ -} - -void BattleGroundNA::StartingEventCloseDoors() -{ - for (uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); -} - -void BattleGroundNA::StartingEventOpenDoors() -{ - for (uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; ++i) - DoorOpen(i); - - for (uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, 60); -} - -void BattleGroundNA::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundNAScore* sc = new BattleGroundNAScore; - - m_PlayerScores[plr->GetGUID()] = sc; - - UpdateArenaWorldState(); -} - -void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) -{ - if (GetStatus() == STATUS_WAIT_LEAVE) - return; - - UpdateArenaWorldState(); - CheckArenaWinConditions(); -} - -void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - if (!killer) - { - sLog.outError("BattleGroundNA: Killer player not found"); - return; - } - - BattleGround::HandleKillPlayer(player,killer); - - UpdateArenaWorldState(); - CheckArenaWinConditions(); -} - -bool BattleGroundNA::HandlePlayerUnderMap(Player *player) -{ - player->TeleportTo(GetMapId(),4055.504395,2919.660645,13.611241,player->GetOrientation(),false); - return true; -} - -void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - //uint32 SpellId = 0; - //uint64 buff_guid = 0; - switch(Trigger) - { - case 4536: // buff trigger? - case 4537: // buff trigger? - break; - default: - sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } - - //if (buff_guid) - // HandleTriggerBuff(buff_guid,Source); -} - -void BattleGroundNA::FillInitialWorldStates(WorldPacket &data) -{ - data << uint32(0xa11) << uint32(1); // 9 - UpdateArenaWorldState(); -} - -void BattleGroundNA::Reset() -{ - //call parent's class reset - BattleGround::Reset(); -} - -bool BattleGroundNA::SetupBattleGround() -{ - // gates - if (!AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) - // buffs - || !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) - || !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) - { - sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!"); - return false; - } - - return true; -} - -/* -20:12:14 id:036668 [S2C] SMSG_INIT_WORLD_STATES (706 = 0x02C2) len: 86 -0000: 2f 02 00 00 72 0e 00 00 00 00 00 00 09 00 11 0a | /...r........... -0010: 00 00 01 00 00 00 0f 0a 00 00 00 00 00 00 10 0a | ................ -0020: 00 00 00 00 00 00 d4 08 00 00 00 00 00 00 d8 08 | ................ -0030: 00 00 00 00 00 00 d7 08 00 00 00 00 00 00 d6 08 | ................ -0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................ -0050: 00 00 00 00 00 00 | ...... -*/ diff --git a/src/server/game/BattleGrounds/BattleGroundNA.h b/src/server/game/BattleGrounds/BattleGroundNA.h deleted file mode 100644 index a11d311515d..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundNA.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __BATTLEGROUNDNA_H -#define __BATTLEGROUNDNA_H - -class BattleGround; - -enum BattleGroundNAObjectTypes -{ - BG_NA_OBJECT_DOOR_1 = 0, - BG_NA_OBJECT_DOOR_2 = 1, - BG_NA_OBJECT_DOOR_3 = 2, - BG_NA_OBJECT_DOOR_4 = 3, - BG_NA_OBJECT_BUFF_1 = 4, - BG_NA_OBJECT_BUFF_2 = 5, - BG_NA_OBJECT_MAX = 6 -}; - -enum BattleGroundNAObjects -{ - BG_NA_OBJECT_TYPE_DOOR_1 = 183978, - BG_NA_OBJECT_TYPE_DOOR_2 = 183980, - BG_NA_OBJECT_TYPE_DOOR_3 = 183977, - BG_NA_OBJECT_TYPE_DOOR_4 = 183979, - BG_NA_OBJECT_TYPE_BUFF_1 = 184663, - BG_NA_OBJECT_TYPE_BUFF_2 = 184664 -}; - -class BattleGroundNAScore : public BattleGroundScore -{ - public: - BattleGroundNAScore() {}; - virtual ~BattleGroundNAScore() {}; - //TODO fix me -}; - -class BattleGroundNA : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundNA(); - ~BattleGroundNA(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - void RemovePlayer(Player *plr, uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - bool SetupBattleGround(); - virtual void Reset(); - virtual void FillInitialWorldStates(WorldPacket &d); - void HandleKillPlayer(Player* player, Player *killer); - bool HandlePlayerUnderMap(Player * plr); -}; -#endif diff --git a/src/server/game/BattleGrounds/BattleGroundRB.cpp b/src/server/game/BattleGrounds/BattleGroundRB.cpp deleted file mode 100644 index cf22154ed11..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundRB.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Player.h" -#include "BattleGround.h" -#include "BattleGroundRB.h" -#include "Language.h" - -BattleGroundRB::BattleGroundRB() -{ - //TODO FIX ME! - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = 0; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; -} - -BattleGroundRB::~BattleGroundRB() -{ - -} - -void BattleGroundRB::Update(uint32 diff) -{ - BattleGround::Update(diff); -} - -void BattleGroundRB::StartingEventCloseDoors() -{ -} - -void BattleGroundRB::StartingEventOpenDoors() -{ -} - -void BattleGroundRB::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundRBScore* sc = new BattleGroundRBScore; - - m_PlayerScores[plr->GetGUID()] = sc; -} - -void BattleGroundRB::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) -{ -} - -void BattleGroundRB::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) -{ - // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; -} - -void BattleGroundRB::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) -{ - std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); - - if (itr == m_PlayerScores.end()) // player not found... - return; - - BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); -} diff --git a/src/server/game/BattleGrounds/BattleGroundRB.h b/src/server/game/BattleGrounds/BattleGroundRB.h deleted file mode 100644 index a40ade5adfe..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundRB.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __BATTLEGROUNDRB_H -#define __BATTLEGROUNDRB_H - -class BattleGround; - -class BattleGroundRBScore : public BattleGroundScore -{ - public: - BattleGroundRBScore() {}; - virtual ~BattleGroundRBScore() {}; -}; - -class BattleGroundRB : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundRB(); - ~BattleGroundRB(); - void Update(uint32 diff); - - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - void RemovePlayer(Player *plr,uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - - /* Scorekeeping */ - void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); - - private: -}; -#endif diff --git a/src/server/game/BattleGrounds/BattleGroundRL.cpp b/src/server/game/BattleGrounds/BattleGroundRL.cpp deleted file mode 100644 index ef2ec3cfa94..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundRL.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BattleGround.h" -#include "BattleGroundRL.h" -#include "Language.h" -#include "Object.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "WorldPacket.h" - -BattleGroundRL::BattleGroundRL() -{ - m_BgObjects.resize(BG_RL_OBJECT_MAX); - - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; - //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; -} - -BattleGroundRL::~BattleGroundRL() -{ - -} - -void BattleGroundRL::Update(uint32 diff) -{ - BattleGround::Update(diff); - - /*if (GetStatus() == STATUS_IN_PROGRESS) - { - // update something - }*/ -} - -void BattleGroundRL::StartingEventCloseDoors() -{ - for (uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); -} - -void BattleGroundRL::StartingEventOpenDoors() -{ - for (uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i) - DoorOpen(i); - - for (uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; ++i) - SpawnBGObject(i, 60); -} - -void BattleGroundRL::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundRLScore* sc = new BattleGroundRLScore; - - m_PlayerScores[plr->GetGUID()] = sc; - - UpdateArenaWorldState(); -} - -void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) -{ - if (GetStatus() == STATUS_WAIT_LEAVE) - return; - - UpdateArenaWorldState(); - CheckArenaWinConditions(); -} - -void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - if (!killer) - { - sLog.outError("Killer player not found"); - return; - } - - BattleGround::HandleKillPlayer(player,killer); - - UpdateArenaWorldState(); - CheckArenaWinConditions(); -} - -bool BattleGroundRL::HandlePlayerUnderMap(Player *player) -{ - player->TeleportTo(GetMapId(),1285.810547,1667.896851,39.957642,player->GetOrientation(),false); - return true; -} - -void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - //uint32 SpellId = 0; - //uint64 buff_guid = 0; - switch(Trigger) - { - case 4696: // buff trigger? - case 4697: // buff trigger? - break; - default: - sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } - - //if (buff_guid) - // HandleTriggerBuff(buff_guid,Source); -} - -void BattleGroundRL::FillInitialWorldStates(WorldPacket &data) -{ - data << uint32(0xbba) << uint32(1); // 9 - UpdateArenaWorldState(); -} - -void BattleGroundRL::Reset() -{ - //call parent's reset - BattleGround::Reset(); -} - -bool BattleGroundRL::SetupBattleGround() -{ - // gates - if (!AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY) - // buffs - || !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) - || !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) - { - sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!"); - return false; - } - - return true; -} - -/* -Packet S->C, id 600, SMSG_INIT_WORLD_STATES (706), len 86 -0000: 3C 02 00 00 80 0F 00 00 00 00 00 00 09 00 BA 0B | <............... -0010: 00 00 01 00 00 00 B9 0B 00 00 02 00 00 00 B8 0B | ................ -0020: 00 00 00 00 00 00 D8 08 00 00 00 00 00 00 D7 08 | ................ -0030: 00 00 00 00 00 00 D6 08 00 00 00 00 00 00 D5 08 | ................ -0040: 00 00 00 00 00 00 D3 08 00 00 00 00 00 00 D4 08 | ................ -0050: 00 00 00 00 00 00 | ...... -*/ diff --git a/src/server/game/BattleGrounds/BattleGroundRL.h b/src/server/game/BattleGrounds/BattleGroundRL.h deleted file mode 100644 index 3b4c10a7c9a..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundRL.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __BATTLEGROUNDRL_H -#define __BATTLEGROUNDRL_H - -class BattleGround; - -enum BattleGroundRLObjectTypes -{ - BG_RL_OBJECT_DOOR_1 = 0, - BG_RL_OBJECT_DOOR_2 = 1, - BG_RL_OBJECT_BUFF_1 = 2, - BG_RL_OBJECT_BUFF_2 = 3, - BG_RL_OBJECT_MAX = 4 -}; - -enum BattleGroundRLObjects -{ - BG_RL_OBJECT_TYPE_DOOR_1 = 185918, - BG_RL_OBJECT_TYPE_DOOR_2 = 185917, - BG_RL_OBJECT_TYPE_BUFF_1 = 184663, - BG_RL_OBJECT_TYPE_BUFF_2 = 184664 -}; - -class BattleGroundRLScore : public BattleGroundScore -{ - public: - BattleGroundRLScore() {}; - virtual ~BattleGroundRLScore() {}; - //TODO fix me -}; - -class BattleGroundRL : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundRL(); - ~BattleGroundRL(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void Reset(); - virtual void FillInitialWorldStates(WorldPacket &d); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - void RemovePlayer(Player *plr, uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - bool SetupBattleGround(); - void HandleKillPlayer(Player* player, Player *killer); - bool HandlePlayerUnderMap(Player * plr); -}; -#endif diff --git a/src/server/game/BattleGrounds/BattleGroundRV.cpp b/src/server/game/BattleGrounds/BattleGroundRV.cpp deleted file mode 100644 index fcc53dbbcf9..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundRV.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BattleGround.h" -#include "BattleGroundRV.h" -#include "ObjectAccessor.h" -#include "Language.h" -#include "Player.h" -#include "WorldPacket.h" -#include "GameObject.h" - -BattleGroundRV::BattleGroundRV() -{ - m_BgObjects.resize(BG_RV_OBJECT_MAX); - - m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; - m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; - m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; - m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; - //we must set messageIds - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; -} - -BattleGroundRV::~BattleGroundRV() -{ - -} - -void BattleGroundRV::Update(uint32 diff) -{ - BattleGround::Update(diff); - - if (getTimer() < diff) - { - uint32 i; - switch(getState()) - { - case BG_RV_STATE_OPEN_FENCES: - { - setTimer(BG_RV_PILAR_TO_FIRE_TIMER); - setState(BG_RV_STATE_CLOSE_FIRE); - break; - } - case BG_RV_STATE_CLOSE_FIRE: - for (i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i) - DoorClose(i); - setTimer(BG_RV_FIRE_TO_PILAR_TIMER); - setState(BG_RV_STATE_OPEN_PILARS); - break; - case BG_RV_STATE_OPEN_PILARS: - for (i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PULLEY_2; ++i) - DoorOpen(i); - setTimer(BG_RV_PILAR_TO_FIRE_TIMER); - setState(BG_RV_STATE_OPEN_FIRE); - break; - case BG_RV_STATE_OPEN_FIRE: - for (i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i) - DoorOpen(i); - setTimer(BG_RV_FIRE_TO_PILAR_TIMER); - setState(BG_RV_STATE_CLOSE_PILARS); - break; - case BG_RV_STATE_CLOSE_PILARS: - uint32 i; - for (i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PULLEY_2; ++i) - DoorOpen(i); - setTimer(BG_RV_PILAR_TO_FIRE_TIMER); - setState(BG_RV_STATE_CLOSE_FIRE); - break; - } - } - else - setTimer(getTimer() - diff); -} - -void BattleGroundRV::StartingEventCloseDoors() -{ -} - -void BattleGroundRV::StartingEventOpenDoors() -{ - // Buff respawn - SpawnBGObject(BG_RV_OBJECT_BUFF_1, 90); - SpawnBGObject(BG_RV_OBJECT_BUFF_2, 90); - // Open fences - DoorOpen(BG_RV_OBJECT_FENCE_1); - DoorOpen(BG_RV_OBJECT_FENCE_2); - // Elevators - DoorOpen(BG_RV_OBJECT_ELEVATOR_1); - DoorOpen(BG_RV_OBJECT_ELEVATOR_2); - - setState(BG_RV_STATE_OPEN_FENCES); - setTimer(BG_RV_FIRST_TIMER); -} - -void BattleGroundRV::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundRVScore* sc = new BattleGroundRVScore; - - m_PlayerScores[plr->GetGUID()] = sc; - - UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE)); - UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE)); -} - -void BattleGroundRV::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) -{ - if (GetStatus() == STATUS_WAIT_LEAVE) - return; - - UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE)); - UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE)); - - CheckArenaWinConditions(); -} - -void BattleGroundRV::HandleKillPlayer(Player *player, Player *killer) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - if (!killer) - { - sLog.outError("BattleGroundRV: Killer player not found"); - return; - } - - BattleGround::HandleKillPlayer(player, killer); - - UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE)); - UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE)); - - CheckArenaWinConditions(); -} - -bool BattleGroundRV::HandlePlayerUnderMap(Player *player) -{ - player->TeleportTo(GetMapId(), 763.5, -284, 28.276, 2.422, false); - return true; -} - - -void BattleGroundRV::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - switch(Trigger) - { - case 5224: - case 5226: - break; - default: - sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } -} - -void BattleGroundRV::FillInitialWorldStates(WorldPacket &data) -{ - data << uint32(BG_RV_WORLD_STATE_A) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); - data << uint32(BG_RV_WORLD_STATE_H) << uint32(GetAlivePlayersCountByTeam(HORDE)); - data << uint32(BG_RV_WORLD_STATE) << uint32(1); -} - -void BattleGroundRV::Reset() -{ - //call parent's class reset - BattleGround::Reset(); -} - -bool BattleGroundRV::SetupBattleGround() -{ - // Fence - if (!AddObject(BG_RV_OBJECT_FENCE_1, BG_RV_OBJECT_TYPE_FENCE_1, 763.432373, -274.058197, 28.276695, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_FENCE_2, BG_RV_OBJECT_TYPE_FENCE_2, 763.432373, -294.419464, 28.276684, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - // elevators - || !AddObject(BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_TYPE_ELEVATOR_1, 763.536377, -294.535767, 0.505383, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_ELEVATOR_2, BG_RV_OBJECT_TYPE_ELEVATOR_2, 763.506348, -273.873352, 0.505383, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) - // buffs - || !AddObject(BG_RV_OBJECT_BUFF_1, BG_RV_OBJECT_TYPE_BUFF_1, 735.551819, -284.794678, 28.276682, 0.034906, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_BUFF_2, BG_RV_OBJECT_TYPE_BUFF_2, 791.224487, -284.794464, 28.276682, 2.600535, 0, 0, 0, RESPAWN_IMMEDIATELY) - // fire - || !AddObject(BG_RV_OBJECT_FIRE_1, BG_RV_OBJECT_TYPE_FIRE_1, 743.543457, -283.799469, 28.286655, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_FIRE_2, BG_RV_OBJECT_TYPE_FIRE_2, 782.971802, -283.799469, 28.286655, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_FIREDOOR_1, BG_RV_OBJECT_TYPE_FIREDOOR_1, 743.711060, -284.099609, 27.542587, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_FIREDOOR_2, BG_RV_OBJECT_TYPE_FIREDOOR_2, 783.221252, -284.133362, 27.535686, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) - // Gear - || !AddObject(BG_RV_OBJECT_GEAR_1, BG_RV_OBJECT_TYPE_GEAR_1, 763.664551, -261.872986, 26.686588, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_GEAR_2, BG_RV_OBJECT_TYPE_GEAR_2, 763.578979, -306.146149, 26.665222, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - // Pulley - || !AddObject(BG_RV_OBJECT_PULLEY_1, BG_RV_OBJECT_TYPE_PULLEY_1, 700.722290, -283.990662, 39.517582, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_PULLEY_2, BG_RV_OBJECT_TYPE_PULLEY_2, 826.303833, -283.996429, 39.517582, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) - // Pilars - || !AddObject(BG_RV_OBJECT_PILAR_1, BG_RV_OBJECT_TYPE_PILAR_1, 763.632385, -306.162384, 25.909504, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_PILAR_2, BG_RV_OBJECT_TYPE_PILAR_2, 723.644287, -284.493256, 24.648525, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_PILAR_3, BG_RV_OBJECT_TYPE_PILAR_3, 763.611145, -261.856750, 25.909504, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_PILAR_4, BG_RV_OBJECT_TYPE_PILAR_4, 802.211609, -284.493256, 24.648525, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) -/* - // Pilars Collision - Fixme: Use the collision pilars - should make u break LoS - || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_1, BG_RV_OBJECT_TYPE_PILAR_COLLISION_1, 763.632385, -306.162384, 30.639660, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_2, BG_RV_OBJECT_TYPE_PILAR_COLLISION_2, 723.644287, -284.493256, 32.382710, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_3, BG_RV_OBJECT_TYPE_PILAR_COLLISION_3, 763.611145, -261.856750, 30.639660, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_4, BG_RV_OBJECT_TYPE_PILAR_COLLISION_4, 802.211609, -284.493256, 32.382710, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) -*/ -) - { - sLog.outErrorDb("BatteGroundRV: Failed to spawn some object!"); - return false; - } - return true; -} diff --git a/src/server/game/BattleGrounds/BattleGroundRV.h b/src/server/game/BattleGrounds/BattleGroundRV.h deleted file mode 100644 index bf06478d364..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundRV.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __BATTLEGROUNDRV_H -#define __BATTLEGROUNDRV_H - -class BattleGround; - -enum BattleGroundRVObjectTypes -{ - BG_RV_OBJECT_BUFF_1, - BG_RV_OBJECT_BUFF_2, - BG_RV_OBJECT_FIRE_1, - BG_RV_OBJECT_FIRE_2, - BG_RV_OBJECT_FIREDOOR_1, - BG_RV_OBJECT_FIREDOOR_2, - - BG_RV_OBJECT_PILAR_1, - BG_RV_OBJECT_PILAR_3, - BG_RV_OBJECT_GEAR_1, - BG_RV_OBJECT_GEAR_2, - - BG_RV_OBJECT_PILAR_2, - BG_RV_OBJECT_PILAR_4, - BG_RV_OBJECT_PULLEY_1, - BG_RV_OBJECT_PULLEY_2, -/* - BG_RV_OBJECT_PILAR_COLLISION_1, - BG_RV_OBJECT_PILAR_COLLISION_2, - BG_RV_OBJECT_PILAR_COLLISION_3, - BG_RV_OBJECT_PILAR_COLLISION_4, -*/ - BG_RV_OBJECT_ELEVATOR_1, - BG_RV_OBJECT_ELEVATOR_2, - BG_RV_OBJECT_FENCE_1, - BG_RV_OBJECT_FENCE_2, - BG_RV_OBJECT_MAX, -}; - -enum BattleGroundRVObjects -{ - BG_RV_OBJECT_TYPE_BUFF_1 = 184663, - BG_RV_OBJECT_TYPE_BUFF_2 = 184664, - BG_RV_OBJECT_TYPE_FIRE_1 = 192704, - BG_RV_OBJECT_TYPE_FIRE_2 = 192705, - - BG_RV_OBJECT_TYPE_FIREDOOR_2 = 192387, - BG_RV_OBJECT_TYPE_FIREDOOR_1 = 192388, - BG_RV_OBJECT_TYPE_PULLEY_1 = 192389, - BG_RV_OBJECT_TYPE_PULLEY_2 = 192390, - BG_RV_OBJECT_TYPE_FENCE_1 = 192391, - BG_RV_OBJECT_TYPE_FENCE_2 = 192392, - BG_RV_OBJECT_TYPE_GEAR_1 = 192393, - BG_RV_OBJECT_TYPE_GEAR_2 = 192394, - BG_RV_OBJECT_TYPE_ELEVATOR_1 = 194582, - BG_RV_OBJECT_TYPE_ELEVATOR_2 = 194586, -/* - BG_RV_OBJECT_TYPE_PILAR_COLLISION_1 = 194580, // axe - BG_RV_OBJECT_TYPE_PILAR_COLLISION_2 = 194579, // arena - BG_RV_OBJECT_TYPE_PILAR_COLLISION_3 = 194581, // lightning - BG_RV_OBJECT_TYPE_PILAR_COLLISION_4 = 194578, // ivory -*/ - BG_RV_OBJECT_TYPE_PILAR_1 = 194583, // axe - BG_RV_OBJECT_TYPE_PILAR_2 = 194584, // arena - BG_RV_OBJECT_TYPE_PILAR_3 = 194585, // lightning - BG_RV_OBJECT_TYPE_PILAR_4 = 194587, // ivory -}; - -enum BattleGroundRVData -{ - BG_RV_STATE_OPEN_FENCES, - BG_RV_STATE_OPEN_PILARS, - BG_RV_STATE_CLOSE_PILARS, - BG_RV_STATE_OPEN_FIRE, - BG_RV_STATE_CLOSE_FIRE, - BG_RV_FIRE_TO_PILAR_TIMER = 20000, - BG_RV_PILAR_TO_FIRE_TIMER = 5000, - BG_RV_FIRST_TIMER = 20133, - BG_RV_WORLD_STATE_A = 0xe10, - BG_RV_WORLD_STATE_H = 0xe11, - BG_RV_WORLD_STATE = 0xe1a, -}; - -class BattleGroundRVScore : public BattleGroundScore -{ - public: - BattleGroundRVScore() {}; - virtual ~BattleGroundRVScore() {}; -}; - -class BattleGroundRV : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundRV(); - ~BattleGroundRV(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - virtual void Reset(); - virtual void FillInitialWorldStates(WorldPacket &d); - - void RemovePlayer(Player *plr, uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - bool SetupBattleGround(); - void HandleKillPlayer(Player* player, Player *killer); - bool HandlePlayerUnderMap(Player * plr); - - private: - uint32 Timer; - uint32 State; - - protected: - uint32 getTimer() { return Timer; }; - void setTimer(uint32 timer) { Timer = timer; }; - - uint32 getState() { return State; }; - void setState(uint32 state) { State = state; }; -}; -#endif diff --git a/src/server/game/BattleGrounds/BattleGroundSA.cpp b/src/server/game/BattleGrounds/BattleGroundSA.cpp deleted file mode 100644 index ccde43ce948..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundSA.cpp +++ /dev/null @@ -1,822 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BattleGround.h" -#include "BattleGroundSA.h" -#include "Language.h" -#include "Player.h" -#include "GameObject.h" -#include "ObjectMgr.h" -#include "WorldPacket.h" - - -BattleGroundSA::BattleGroundSA() -{ - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_SA_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_SA_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_SA_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_SA_HAS_BEGUN; - m_BgObjects.resize(BG_SA_MAXOBJ); - m_BgCreatures.resize(BG_SA_MAXNPC + BG_SA_MAX_GY); - TimerEnabled = false; - UpdateWaitTimer = 0; - SignaledRoundTwo = false; - SignaledRoundTwoHalfMin = false; - InitSecondRound = false; -} - -BattleGroundSA::~BattleGroundSA() -{ -} - -void BattleGroundSA::Reset() -{ - TotalTime = 0; - attackers = ((urand(0,1)) ? TEAM_ALLIANCE : TEAM_HORDE); - for (uint8 i = 0; i <= 5; i++) - GateStatus[i] = BG_SA_GATE_OK; - ShipsStarted = false; - status = BG_SA_WARMUP; -} - -bool BattleGroundSA::SetupBattleGround() -{ - return ResetObjs(); -} - -bool BattleGroundSA::ResetObjs() -{ - uint32 atF = BG_SA_Factions[attackers]; - uint32 defF = BG_SA_Factions[attackers ? TEAM_ALLIANCE : TEAM_HORDE]; - - - for (uint8 i = 0; i SetUInt32Value(GAMEOBJECT_FACTION, defF); - } - - GetBGObject(BG_SA_TITAN_RELIC)->SetUInt32Value(GAMEOBJECT_FACTION, atF); - GetBGObject(BG_SA_TITAN_RELIC)->Refresh(); - - for (uint8 i = 0; i <= 5; i++) - GateStatus[i] = BG_SA_GATE_OK; - - // MAD props for Kiper for discovering those values - 4 hours of his work. - GetBGObject(BG_SA_BOAT_ONE)->UpdateRotationFields(1.0f, 0.0002f); - GetBGObject(BG_SA_BOAT_TWO)->UpdateRotationFields(1.0f, 0.00001f); - SpawnBGObject(BG_SA_BOAT_ONE, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_SA_BOAT_TWO, RESPAWN_IMMEDIATELY); - - TotalTime = 0; - ShipsStarted = false; - - //Graveyards! - for (uint8 i = 0;i < BG_SA_MAX_GY; i++) - { - WorldSafeLocsEntry const *sg = NULL; - sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); - - if (!sg) - { - sLog.outError("SOTA: Can't find GY entry %u",BG_SA_GYEntries[i]); - return false; - } - - if (i == BG_SA_BEACH_GY) - { - GraveyardStatus[i] = attackers; - AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], ((attackers == TEAM_HORDE)? HORDE : ALLIANCE)); - } - else - { - GraveyardStatus[i] = ((attackers == TEAM_HORDE)? TEAM_ALLIANCE : TEAM_HORDE); - if (!AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], ((attackers == TEAM_HORDE)? ALLIANCE : HORDE))) - sLog.outError("SOTA: couldn't spawn GY: %u",i); - } - } - - //GY capture points - for (uint8 i = BG_SA_CENTRAL_FLAG; i < BG_SA_MAXOBJ; i++) - { - AddObject(i, BG_SA_ObjEntries[(i + (attackers == TEAM_ALLIANCE ? 3:0))], - BG_SA_ObjSpawnlocs[i][0], BG_SA_ObjSpawnlocs[i][1], - BG_SA_ObjSpawnlocs[i][2], BG_SA_ObjSpawnlocs[i][3], - 0,0,0,0,RESPAWN_ONE_DAY); - GetBGObject(i)->SetUInt32Value(GAMEOBJECT_FACTION, atF); - } - - //Player may enter BEFORE we set up bG - lets update his worldstates anyway... - UpdateWorldState(BG_SA_RIGHT_GY_HORDE , GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE?1:0); - UpdateWorldState(BG_SA_LEFT_GY_HORDE , GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE?1:0); - UpdateWorldState(BG_SA_CENTER_GY_HORDE , GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE?1:0); - - UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE , GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE , GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE , GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - - if (attackers == TEAM_ALLIANCE) - { - UpdateWorldState(BG_SA_ALLY_ATTACKS, 1); - UpdateWorldState(BG_SA_HORDE_ATTACKS, 0); - - UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_ALL, 1); - UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_ALL, 1); - UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_HRD, 0); - UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_HRD, 0); - - UpdateWorldState(BG_SA_HORDE_DEFENCE_TOKEN,1); - UpdateWorldState(BG_SA_ALLIANCE_DEFENCE_TOKEN,0); - } - else - { - UpdateWorldState(BG_SA_HORDE_ATTACKS, 1); - UpdateWorldState(BG_SA_ALLY_ATTACKS, 0); - - UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_ALL, 0); - UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_ALL, 0); - UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_HRD, 1); - UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_HRD, 1); - - UpdateWorldState(BG_SA_HORDE_DEFENCE_TOKEN,0); - UpdateWorldState(BG_SA_ALLIANCE_DEFENCE_TOKEN,1); - } - - UpdateWorldState(BG_SA_PURPLE_GATEWS, 1); - UpdateWorldState(BG_SA_RED_GATEWS, 1); - UpdateWorldState(BG_SA_BLUE_GATEWS, 1); - UpdateWorldState(BG_SA_GREEN_GATEWS, 1); - UpdateWorldState(BG_SA_YELLOW_GATEWS, 1); - UpdateWorldState(BG_SA_ANCIENT_GATEWS, 1); - - TeleportPlayers(); - return true; -} - -void BattleGroundSA::StartShips() -{ - if (ShipsStarted) - return; - - DoorOpen(BG_SA_BOAT_ONE); - DoorOpen(BG_SA_BOAT_TWO); - - for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++) - { - for (BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end();itr++) - { - if (Player* p = objmgr.GetPlayer(itr->first)) - { - if (p->GetTeamId() != attackers) - continue; - - UpdateData data; - WorldPacket pkt; - GetBGObject(i)->BuildValuesUpdateBlockForPlayer(&data, p); - data.BuildPacket(&pkt); - p->GetSession()->SendPacket(&pkt); - } - } - } - ShipsStarted = true; -} - -void BattleGroundSA::Update(uint32 diff) -{ - if (InitSecondRound) - { - if (UpdateWaitTimer < diff) - { - if (!SignaledRoundTwo) - { - SignaledRoundTwo = true; - InitSecondRound = false; - SendMessageToAll(LANG_BG_SA_ROUND_TWO_ONE_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL); - } - }else - { - UpdateWaitTimer -= diff; - return; - } - } - BattleGround::Update(diff); - TotalTime += diff; - - if (status == BG_SA_WARMUP ) - { - BG_SA_ENDROUNDTIME = BG_SA_ROUNDLENGTH; - if (TotalTime >= BG_SA_WARMUPLENGTH) - { - TotalTime = 0; - ToggleTimer(); - DemolisherStartState(false); - status = BG_SA_ROUND_ONE; - } - if (TotalTime >= BG_SA_BOAT_START) - StartShips(); - return; - } - else if (status == BG_SA_SECOND_WARMUP) - { - if (RoundScores[0].time= 60000) - { - SendWarningToAll(LANG_BG_SA_HAS_BEGUN); - TotalTime = 0; - ToggleTimer(); - DemolisherStartState(false); - status = BG_SA_ROUND_TWO; - } - if (TotalTime >= 30000) - { - if (!SignaledRoundTwoHalfMin) - { - SignaledRoundTwoHalfMin = true; - SendMessageToAll(LANG_BG_SA_ROUND_TWO_START_HALF_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL); - } - } - StartShips(); - return; - } - else if (GetStatus() == STATUS_IN_PROGRESS) - { - if (status == BG_SA_ROUND_ONE) - { - if (TotalTime >= BG_SA_ROUNDLENGTH) - { - RoundScores[0].winner = attackers; - RoundScores[0].time = BG_SA_ROUNDLENGTH; - TotalTime = 0; - status = BG_SA_SECOND_WARMUP; - attackers = (attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE; - status = BG_SA_SECOND_WARMUP; - ToggleTimer(); - ResetObjs(); - return; - } - } - else if (status == BG_SA_ROUND_TWO) - { - if (TotalTime >= BG_SA_ENDROUNDTIME) - { - RoundScores[1].time = BG_SA_ROUNDLENGTH; - RoundScores[1].winner = (attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE; - - if (RoundScores[0].time == RoundScores[1].time) - EndBattleGround(NULL); - else if (RoundScores[0].time < RoundScores[1].time) - EndBattleGround(RoundScores[0].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE); - else - EndBattleGround(RoundScores[1].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE); - return; - } - } - if (status == BG_SA_ROUND_ONE || status == BG_SA_ROUND_TWO) - { - SendTime(); - UpdateDemolisherSpawns(); - } - } -} - -void BattleGroundSA::StartingEventCloseDoors() -{ -} - -void BattleGroundSA::StartingEventOpenDoors() -{ -} - -void BattleGroundSA::FillInitialWorldStates(WorldPacket& data) -{ - uint32 ally_attacks = uint32(attackers == TEAM_ALLIANCE ? 1 : 0); - uint32 horde_attacks = uint32(attackers == TEAM_HORDE ? 1 : 0); - - data << uint32(BG_SA_ANCIENT_GATEWS) << uint32(GateStatus[BG_SA_ANCIENT_GATE]); - data << uint32(BG_SA_YELLOW_GATEWS) << uint32(GateStatus[BG_SA_YELLOW_GATE]); - data << uint32(BG_SA_GREEN_GATEWS) << uint32(GateStatus[BG_SA_GREEN_GATE]); - data << uint32(BG_SA_BLUE_GATEWS) << uint32(GateStatus[BG_SA_BLUE_GATE]); - data << uint32(BG_SA_RED_GATEWS) << uint32(GateStatus[BG_SA_RED_GATE]); - data << uint32(BG_SA_PURPLE_GATEWS) << uint32(GateStatus[BG_SA_PURPLE_GATE]); - - data << uint32(BG_SA_BONUS_TIMER) << uint32(0); - - data << uint32(BG_SA_HORDE_ATTACKS)<< horde_attacks; - data << uint32(BG_SA_ALLY_ATTACKS) << ally_attacks; - - //Time will be sent on first update... - data << uint32(BG_SA_ENABLE_TIMER) << ((TimerEnabled) ? uint32(1) : uint32(0)); - data << uint32(BG_SA_TIMER_MINS) << uint32(0); - data << uint32(BG_SA_TIMER_SEC_TENS) << uint32(0); - data << uint32(BG_SA_TIMER_SEC_DECS) << uint32(0); - - data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE?1:0); - data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE?1:0); - data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE?1:0); - - data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); - - data << uint32(BG_SA_HORDE_DEFENCE_TOKEN) << ally_attacks; - data << uint32(BG_SA_ALLIANCE_DEFENCE_TOKEN) << horde_attacks; - - data << uint32(BG_SA_LEFT_ATT_TOKEN_HRD) << horde_attacks; - data << uint32(BG_SA_RIGHT_ATT_TOKEN_HRD) << horde_attacks; - data << uint32(BG_SA_RIGHT_ATT_TOKEN_ALL) << ally_attacks; - data << uint32(BG_SA_LEFT_ATT_TOKEN_ALL) << ally_attacks; -} - -void BattleGroundSA::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundSAScore* sc = new BattleGroundSAScore; - - if (!ShipsStarted) - { - if (plr->GetTeamId() == attackers) - { - plr->CastSpell(plr,12438,true);//Without this player falls before boat loads... - - if (urand(0,1)) - plr->TeleportTo(607, 2682.936f, -830.368f, 50.0f, 2.895f, 0); - else - plr->TeleportTo(607, 2577.003f, 980.261f, 50.0f, 0.807f, 0); - - } - else - plr->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0); - } - else - { - if (plr->GetTeamId() == attackers) - plr->TeleportTo(607, 1600.381f, -106.263f, 8.8745f, 3.78f, 0); - else - plr->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0); - } - - m_PlayerScores[plr->GetGUID()] = sc; -} - -void BattleGroundSA::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) -{ -} - -void BattleGroundSA::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) -{ - // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; -} - -void BattleGroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) -{ - BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found... - return; - - if (type == SCORE_DESTROYED_DEMOLISHER) - ((BattleGroundSAScore*)itr->second)->demolishers_destroyed += value; - else if (type == SCORE_DESTROYED_WALL) - ((BattleGroundSAScore*)itr->second)->gates_destroyed += value; - else - BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); -} - -void BattleGroundSA::TeleportPlayers() -{ - for (BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - { - if (Player *plr = objmgr.GetPlayer(itr->first)) - { - // should remove spirit of redemption - if (plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) - plr->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT); - - if (!plr->isAlive()) - { - plr->ResurrectPlayer(1.0f); - plr->SpawnCorpseBones(); - } - - plr->SetHealth(plr->GetMaxHealth()); - plr->SetPower(POWER_MANA, plr->GetMaxPower(POWER_MANA)); - plr->CombatStopWithPets(true); - - if (plr->GetTeamId() == attackers) - { - plr->CastSpell(plr,12438,true); //Without this player falls before boat loads... - - if (urand(0,1)) - plr->TeleportTo(607, 2682.936f, -830.368f, 50.0f, 2.895f, 0); - else - plr->TeleportTo(607, 2577.003f, 980.261f, 50.0f, 0.807f, 0); - } - else - plr->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0); - } - } -} - -void BattleGroundSA::EventPlayerDamagedGO(Player* plr, GameObject* go, uint8 hitType, uint32 destroyedEvent) -{ - if (!go || !go->GetGOInfo()) - return; - - switch(hitType) - { - case BG_OBJECT_DMG_HIT_TYPE_JUST_DAMAGED://under attack - SendWarningToAll(LANG_BG_SA_IS_UNDER_ATTACK, go->GetGOInfo()->name); - break; - case BG_OBJECT_DMG_HIT_TYPE_DAMAGED: - break; - case BG_OBJECT_DMG_HIT_TYPE_JUST_HIGH_DAMAGED: - { - uint32 i = GetGateIDFromDestroyEventID(destroyedEvent); - GateStatus[i] = BG_SA_GATE_DAMAGED; - uint32 uws = GetWorldStateFromGateID(i); - if (uws) - UpdateWorldState(uws, GateStatus[i]); - break; - } - case BG_OBJECT_DMG_HIT_TYPE_HIGH_DAMAGED: - break; - case BG_OBJECT_DMG_HIT_TYPE_JUST_DESTROYED://handled at DestroyGate() - if (destroyedEvent == 19837) - SendWarningToAll(LANG_BG_SA_CHAMBER_BREACHED); - else - SendWarningToAll(LANG_BG_SA_WAS_DESTROYED, go->GetGOInfo()->name); - break; - } -} - -void BattleGroundSA::HandleKillUnit(Creature* unit, Player* killer) -{ - if (!unit) - return; - - if (unit->GetEntry() == 28781) //Demolisher - UpdatePlayerScore(killer, SCORE_DESTROYED_DEMOLISHER, 1); -} - -/* - You may ask what the fuck does it do? - Prevents owner overwriting guns faction with own. - */ -void BattleGroundSA::OverrideGunFaction() -{ - if (!m_BgCreatures[0]) - return; - - for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10;i++) - { - if (Creature* gun = GetBGCreature(i)) - gun->setFaction(BG_SA_Factions[attackers? TEAM_ALLIANCE : TEAM_HORDE]); - } - - for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4;i++) - { - if (Creature* dem = GetBGCreature(i)) - dem->setFaction(BG_SA_Factions[attackers]); - } -} - -void BattleGroundSA::DemolisherStartState(bool start) -{ - if (!m_BgCreatures[0]) - return; - - for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) - { - if (Creature* dem = GetBGCreature(i)) - { - if (start) - dem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - else - dem->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - } - } -} - -void BattleGroundSA::DestroyGate(Player* pl, GameObject* /*go*/, uint32 destroyedEvent) -{ - uint32 i = GetGateIDFromDestroyEventID(destroyedEvent); - if (!GateStatus[i]) - return; - - if (GameObject* g = GetBGObject(i)) - { - if (g->GetGOValue()->building.health == 0) - { - GateStatus[i] = BG_SA_GATE_DESTROYED; - uint32 uws = GetWorldStateFromGateID(i); - if (uws) - UpdateWorldState(uws, GateStatus[i]); - bool rewardHonor = true; - switch(i) - { - case BG_SA_GREEN_GATE: - if (GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) - rewardHonor = false; - break; - case BG_SA_BLUE_GATE: - if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED) - rewardHonor = false; - break; - case BG_SA_RED_GATE: - if (GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED) - rewardHonor = false; - break; - case BG_SA_PURPLE_GATE: - if (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) - rewardHonor = false; - break; - } - - if (i < 5) - DelObject(i+9); - UpdatePlayerScore(pl,SCORE_DESTROYED_WALL, 1); - if (rewardHonor) - UpdatePlayerScore(pl,SCORE_BONUS_HONOR,(GetBonusHonorFromKill(1))); - } - } -} - -WorldSafeLocsEntry const* BattleGroundSA::GetClosestGraveYard(Player* player) -{ - uint32 safeloc = 0; - WorldSafeLocsEntry const* ret; - WorldSafeLocsEntry const* closest; - float dist, nearest; - float x,y,z; - - player->GetPosition(x,y,z); - - if (player->GetTeamId() == attackers) - safeloc = BG_SA_GYEntries[BG_SA_BEACH_GY]; - else - safeloc = BG_SA_GYEntries[BG_SA_DEFENDER_LAST_GY]; - - closest = sWorldSafeLocsStore.LookupEntry(safeloc); - nearest = sqrt((closest->x - x)*(closest->x - x) + (closest->y - y)*(closest->y - y)+(closest->z - z)*(closest->z - z)); - - for (uint8 i = BG_SA_RIGHT_CAPTURABLE_GY; i < BG_SA_MAX_GY; i++) - { - if (GraveyardStatus[i] != player->GetTeamId()) - continue; - - ret = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); - dist = sqrt((ret->x - x)*(ret->x - x) + (ret->y - y)*(ret->y - y)+(ret->z - z)*(ret->z - z)); - if (dist < nearest) - { - closest = ret; - nearest = dist; - } - } - - return closest; -} - -void BattleGroundSA::SendTime() -{ - uint32 end_of_round = (BG_SA_ENDROUNDTIME - TotalTime); - UpdateWorldState(BG_SA_TIMER_MINS, end_of_round/60000); - UpdateWorldState(BG_SA_TIMER_SEC_TENS, (end_of_round%60000)/10000); - UpdateWorldState(BG_SA_TIMER_SEC_DECS, ((end_of_round%60000)%10000)/1000); -} - -void BattleGroundSA::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) -{ - switch(target_obj->GetEntry()) - { - case 191307: - case 191308: - if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) - CaptureGraveyard(BG_SA_LEFT_CAPTURABLE_GY, Source); - break; - case 191305: - case 191306: - if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) - CaptureGraveyard(BG_SA_RIGHT_CAPTURABLE_GY, Source); - break; - case 191310: - case 191309: - if ((GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) && (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED)) - CaptureGraveyard(BG_SA_CENTRAL_CAPTURABLE_GY, Source); - break; - default: - return; - }; -} - -void BattleGroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player *Source) -{ - DelCreature(BG_SA_MAXNPC + i); - GraveyardStatus[i] = Source->GetTeamId(); - WorldSafeLocsEntry const *sg = NULL; - sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); - AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], (GraveyardStatus[i] == TEAM_ALLIANCE? ALLIANCE : HORDE)); - uint32 npc = 0; - uint32 flag = 0; - - switch(i) - { - case BG_SA_LEFT_CAPTURABLE_GY: - flag = BG_SA_LEFT_FLAG; - DelObject(flag); - AddObject(flag,BG_SA_ObjEntries[(flag + (Source->GetTeamId() == TEAM_ALLIANCE ? 0:3))], - BG_SA_ObjSpawnlocs[flag][0],BG_SA_ObjSpawnlocs[flag][1], - BG_SA_ObjSpawnlocs[flag][2],BG_SA_ObjSpawnlocs[flag][3],0,0,0,0,RESPAWN_ONE_DAY); - - npc = BG_SA_NPC_RIGSPARK; - AddCreature(BG_SA_NpcEntries[npc], npc, attackers, - BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1], - BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]); - - UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); - UpdateWorldState(BG_SA_LEFT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); - if (Source->GetTeamId() == TEAM_ALLIANCE) - SendWarningToAll(LANG_BG_SA_A_GY_WEST); - else - SendWarningToAll(LANG_BG_SA_H_GY_WEST); - break; - case BG_SA_RIGHT_CAPTURABLE_GY: - flag = BG_SA_RIGHT_FLAG; - DelObject(flag); - AddObject(flag,BG_SA_ObjEntries[(flag + (Source->GetTeamId() == TEAM_ALLIANCE ? 0:3))], - BG_SA_ObjSpawnlocs[flag][0],BG_SA_ObjSpawnlocs[flag][1], - BG_SA_ObjSpawnlocs[flag][2],BG_SA_ObjSpawnlocs[flag][3],0,0,0,0,RESPAWN_ONE_DAY); - - npc = BG_SA_NPC_SPARKLIGHT; - AddCreature(BG_SA_NpcEntries[npc], npc, attackers, - BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1], - BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]); - - UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); - UpdateWorldState(BG_SA_RIGHT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); - if (Source->GetTeamId() == TEAM_ALLIANCE) - SendWarningToAll(LANG_BG_SA_A_GY_EAST); - else - SendWarningToAll(LANG_BG_SA_H_GY_EAST); - break; - case BG_SA_CENTRAL_CAPTURABLE_GY: - flag = BG_SA_CENTRAL_FLAG; - DelObject(flag); - AddObject(flag,BG_SA_ObjEntries[(flag + (Source->GetTeamId() == TEAM_ALLIANCE ? 0:3))], - BG_SA_ObjSpawnlocs[flag][0],BG_SA_ObjSpawnlocs[flag][1], - BG_SA_ObjSpawnlocs[flag][2],BG_SA_ObjSpawnlocs[flag][3],0,0,0,0,RESPAWN_ONE_DAY); - - UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); - UpdateWorldState(BG_SA_CENTER_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); - if (Source->GetTeamId() == TEAM_ALLIANCE) - SendWarningToAll(LANG_BG_SA_A_GY_SOUTH); - else - SendWarningToAll(LANG_BG_SA_H_GY_SOUTH); - break; - default: - ASSERT(0); - break; - }; -} - -void BattleGroundSA::EventPlayerUsedGO(Player* Source, GameObject* object) -{ - if (object->GetEntry() == BG_SA_ObjEntries[BG_SA_TITAN_RELIC] && GateStatus[BG_SA_ANCIENT_GATE] == BG_SA_GATE_DESTROYED) - { - if (Source->GetTeamId() == attackers) - { - if (Source->GetTeamId() == ALLIANCE) - SendMessageToAll(LANG_BG_SA_ALLIANCE_CAPTURED_RELIC, CHAT_MSG_BG_SYSTEM_NEUTRAL); - else SendMessageToAll(LANG_BG_SA_HORDE_CAPTURED_RELIC, CHAT_MSG_BG_SYSTEM_NEUTRAL); - - if (status == BG_SA_ROUND_ONE) - { - RoundScores[0].winner = attackers; - RoundScores[0].time = TotalTime; - attackers = (attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE; - status = BG_SA_SECOND_WARMUP; - TotalTime = 0; - ToggleTimer(); - SendWarningToAll(LANG_BG_SA_ROUND_ONE_END); - UpdateWaitTimer = 5000; - SignaledRoundTwo = false; - SignaledRoundTwoHalfMin = false; - InitSecondRound = true; - ResetObjs(); - } - else if (status == BG_SA_ROUND_TWO) - { - RoundScores[1].winner = attackers; - RoundScores[1].time = TotalTime;ToggleTimer(); - if (RoundScores[0].time == RoundScores[1].time) - EndBattleGround(NULL); - else if (RoundScores[0].time < RoundScores[1].time) - EndBattleGround(RoundScores[0].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE); - else - EndBattleGround(RoundScores[1].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE); - } - } - } -} - -void BattleGroundSA::ToggleTimer() -{ - TimerEnabled = !TimerEnabled; - UpdateWorldState(BG_SA_ENABLE_TIMER, (TimerEnabled) ? 1 : 0); -} - -void BattleGroundSA::EndBattleGround(uint32 winner) -{ - //honor reward for winning - if (winner == ALLIANCE) - RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); - else if (winner == HORDE) - RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); - - //complete map_end rewards (even if no team wins) - RewardHonorToTeam(GetBonusHonorFromKill(2), ALLIANCE); - RewardHonorToTeam(GetBonusHonorFromKill(2), HORDE); - - BattleGround::EndBattleGround(winner); -} - -void BattleGroundSA::UpdateDemolisherSpawns() -{ - for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) - { - if (m_BgCreatures[i]) - { - if (Creature *Demolisher = GetBGCreature(i)) - { - if (Demolisher->isDead()) - { - uint8 gy = (i >= BG_SA_DEMOLISHER_3 ? 3 : 2); - if (GraveyardStatus[gy] == attackers) - Demolisher->Relocate(BG_SA_NpcSpawnlocs[i + 6][0], BG_SA_NpcSpawnlocs[i + 6][1], - BG_SA_NpcSpawnlocs[i + 6][2], BG_SA_NpcSpawnlocs[i + 6][3]); - else - Demolisher->Relocate(BG_SA_NpcSpawnlocs[i][0], BG_SA_NpcSpawnlocs[i][1], - BG_SA_NpcSpawnlocs[i][2], BG_SA_NpcSpawnlocs[i][3]); - - Demolisher->Respawn(); - } - } - } - } -} - - diff --git a/src/server/game/BattleGrounds/BattleGroundSA.h b/src/server/game/BattleGrounds/BattleGroundSA.h deleted file mode 100644 index 760be3ca02e..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundSA.h +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __BATTLEGROUNDSA_H -#define __BATTLEGROUNDSA_H - -class BattleGround; - -class BattleGroundSAScore : public BattleGroundScore -{ - public: - BattleGroundSAScore(): demolishers_destroyed(0), gates_destroyed(0) {}; - virtual ~BattleGroundSAScore() {}; - uint8 demolishers_destroyed; - uint8 gates_destroyed; -}; - -#define BG_SA_FLAG_AMOUNT 3 -#define BG_SA_DEMOLISHER_AMOUNT 4 - -enum BG_SA_Status - { - BG_SA_NOTSTARTED = 0, - BG_SA_WARMUP, - BG_SA_ROUND_ONE, - BG_SA_SECOND_WARMUP, - BG_SA_ROUND_TWO, - BG_SA_BONUS_ROUND - }; - -enum BG_SA_GateState - { - BG_SA_GATE_OK = 1, - BG_SA_GATE_DAMAGED = 2, - BG_SA_GATE_DESTROYED = 3 - }; - -enum BG_SA_Timers - { - BG_SA_BOAT_START = 60000, - BG_SA_WARMUPLENGTH = 120000, - BG_SA_ROUNDLENGTH = 600000 - }; - -enum BG_SA_WorldStates - { - BG_SA_TIMER_MINS = 3559, - BG_SA_TIMER_SEC_TENS = 3560, - BG_SA_TIMER_SEC_DECS = 3561, - BG_SA_ALLY_ATTACKS = 4352, - BG_SA_HORDE_ATTACKS = 4353, - - BG_SA_PURPLE_GATEWS = 3614, - BG_SA_RED_GATEWS = 3617, - BG_SA_BLUE_GATEWS = 3620, - BG_SA_GREEN_GATEWS = 3623, - BG_SA_YELLOW_GATEWS = 3638, - BG_SA_ANCIENT_GATEWS = 3849, - - - BG_SA_LEFT_GY_ALLIANCE = 3635, - BG_SA_RIGHT_GY_ALLIANCE = 3636, - BG_SA_CENTER_GY_ALLIANCE = 3637, - - BG_SA_RIGHT_ATT_TOKEN_ALL = 3627, - BG_SA_LEFT_ATT_TOKEN_ALL = 3626, - - BG_SA_LEFT_ATT_TOKEN_HRD = 3629, - BG_SA_RIGHT_ATT_TOKEN_HRD = 3628, - - BG_SA_HORDE_DEFENCE_TOKEN = 3631, - BG_SA_ALLIANCE_DEFENCE_TOKEN = 3630, - - BG_SA_RIGHT_GY_HORDE = 3632, - BG_SA_LEFT_GY_HORDE = 3633, - BG_SA_CENTER_GY_HORDE = 3634, - - BG_SA_BONUS_TIMER = 0xdf3, - BG_SA_ENABLE_TIMER = 3564, - }; - -enum BG_SA_NPCs - { - BG_SA_GUN_1 = 0, - BG_SA_GUN_2, - BG_SA_GUN_3, - BG_SA_GUN_4, - BG_SA_GUN_5, - BG_SA_GUN_6, - BG_SA_GUN_7, - BG_SA_GUN_8, - BG_SA_GUN_9, - BG_SA_GUN_10, - BG_SA_DEMOLISHER_1, - BG_SA_DEMOLISHER_2, - BG_SA_DEMOLISHER_3, - BG_SA_DEMOLISHER_4, - BG_SA_NPC_SPARKLIGHT, - BG_SA_NPC_RIGSPARK, - BG_SA_MAXNPC - }; - -const uint32 BG_SA_NpcEntries[BG_SA_MAXNPC] = - { - 27894, - 27894, - 27894, - 27894, - 27894, - 27894, - 27894, - 27894, - 27894, - 27894, - //4 beach demolishers - 28781, - 28781, - 28781, - 28781, - //Fizzle Sparklight, or whatever his name was - 29260, - 29262, - }; - -const float BG_SA_NpcSpawnlocs[BG_SA_MAXNPC + BG_SA_DEMOLISHER_AMOUNT][4] = - { - //Cannons - { 1436.429f, 110.05f, 41.407f, 5.4f }, - { 1404.9023f, 84.758f, 41.183f, 5.46f }, - { 1068.693f, -86.951f, 93.81f, 0.02f }, - { 1068.83f, -127.56f, 96.45f, 0.0912f }, - { 1422.115f, -196.433f, 42.1825f, 1.0222f }, - { 1454.887f, -220.454f, 41.956f, 0.9627f }, - { 1232.345f, -187.517f, 66.945f, 0.45f }, - { 1249.634f, -224.189f, 66.72f, 0.635f }, - { 1236.213f, 92.287f, 64.965f, 5.751f }, - { 1215.11f, 57.772f, 64.739f, 5.78f } , - //Demolishers - { 1611.597656,-117.270073,8.719355,2.513274}, - { 1575.562500,-158.421875,5.024450,2.129302}, - { 1618.047729,61.424641,7.248210,3.979351}, - { 1575.103149,98.873344,2.830360,3.752458}, - //Npcs - { 1348.644165, -298.786469, 31.080130, 1.710423}, - { 1358.191040, 195.527786, 31.018187, 4.171337}, - //Demolishers2 - { 1371.055786, -317.071136, 35.007359, 1.947460}, - { 1424.034912, -260.195190, 31.084425, 2.820013}, - { 1353.139893, 223.745438, 35.265411, 4.343684}, - { 1404.809570, 197.027237, 32.046032, 3.605401}, - }; - -enum BG_SA_Objects - { - BG_SA_GREEN_GATE = 0, - BG_SA_YELLOW_GATE, - BG_SA_BLUE_GATE, - BG_SA_RED_GATE, - BG_SA_PURPLE_GATE, - BG_SA_ANCIENT_GATE, - BG_SA_TITAN_RELIC, - BG_SA_BOAT_ONE, - BG_SA_BOAT_TWO, - BG_SA_SIGIL_1, - BG_SA_SIGIL_2, - BG_SA_SIGIL_3, - BG_SA_SIGIL_4, - BG_SA_SIGIL_5, - BG_SA_CENTRAL_FLAGPOLE, - BG_SA_RIGHT_FLAGPOLE, - BG_SA_LEFT_FLAGPOLE, - BG_SA_CENTRAL_FLAG, - BG_SA_RIGHT_FLAG, - BG_SA_LEFT_FLAG, - BG_SA_MAXOBJ - }; - -const float BG_SA_ObjSpawnlocs[BG_SA_MAXOBJ][4] = - { - { 1411.57f, 108.163f, 28.692f, 5.441f }, - { 1055.452f, -108.1f, 82.134f, 0.034f }, - { 1431.3413f, -219.437f, 30.893f, 0.9736f }, - { 1227.667f, -212.555f, 55.372f, 0.5023f }, - { 1214.681f, 81.21f, 53.413f, 5.745f }, - { 878.555f, -108.989f, 119.835f, 0.0565f }, - { 836.5f, -108.8f, 120.219f, 0.0f }, - //Ships - { 2679.696777, -826.891235, 3.712860, 5.78367f}, //rot2 1 rot3 0.0002 - { 2574.003662, 981.261475, 2.603424, 0.807696}, - //Sigils - { 1414.054f, 106.72f, 41.442f, 5.441f }, - { 1060.63f, -107.8f, 94.7f, 0.034f }, - { 1433.383f, -216.4f, 43.642f, 0.9736f }, - { 1230.75f, -210.724f, 67.611f, 0.5023f }, - { 1217.8f, 79.532f, 66.58f, 5.745f }, - //Flagpoles - { 1215.114258,-65.711861,70.084267,-3.124123}, - {1338.863892,-153.336533,30.895121,-2.530723}, - {1309.124268,9.410645,30.893402,-1.623156}, - //Flags - { 1215.108032,-65.715767,70.084267,-3.124123}, - { 1338.859253,-153.327316,30.895077,-2.530723}, - { 1309.192017,9.416233,30.893402,1.518436}, - }; - -/* Ships: - * 193182 - ally - * 193183 - horde - * 193184 - horde - * 193185 - ally - * Banners: - * 191308 - left one, - * 191306 - right one, - * 191310 - central, - * Ally ones, substract 1 - * to get horde ones. - */ - -const uint32 BG_SA_ObjEntries[BG_SA_MAXOBJ + BG_SA_FLAG_AMOUNT] = - { - 190722, - 190727, - 190724, - 190726, - 190723, - 192549, - 192834, - 193182, - 193185, - 192687, - 192685, - 192689, - 192690, - 192691, - 191311, - 191311, - 191311, - 191310, - 191306, - 191308, - 191309, - 191305, - 191307, - }; - -const uint32 BG_SA_Factions[2] = - { - 1732, - 1735, - }; - -enum BG_SA_Graveyards - { - BG_SA_BEACH_GY = 0, - BG_SA_DEFENDER_LAST_GY, - BG_SA_RIGHT_CAPTURABLE_GY, - BG_SA_LEFT_CAPTURABLE_GY, - BG_SA_CENTRAL_CAPTURABLE_GY, - BG_SA_MAX_GY - }; - -const uint32 BG_SA_GYEntries[BG_SA_MAX_GY] = - { - 1350, - 1349, - 1347, - 1346, - 1348, - }; - -const float BG_SA_GYOrientation[BG_SA_MAX_GY] = - { - 6.202f, - 1.926f, //right capturable GY - 3.917f, //left capturable GY - 3.104f, //center, capturable - 6.148f, //defender last GY - }; - -struct BG_SA_RoundScore -{ - TeamId winner; - uint32 time; -}; - -class BattleGroundSA : public BattleGround -{ - friend class BattleGroundMgr; - - public: - BattleGroundSA(); - ~BattleGroundSA(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - virtual bool SetupBattleGround(); - virtual void Reset(); - virtual void FillInitialWorldStates(WorldPacket& data); - virtual void EventPlayerDamagedGO(Player* plr, GameObject* go, uint8 hitType, uint32 destroyedEvent); - virtual void HandleKillUnit(Creature* unit, Player* killer); - virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); - virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); - virtual void EventPlayerUsedGO(Player* Source, GameObject* object); - uint32 GetGateIDFromDestroyEventID(uint32 id) - { - uint32 i = 0; - switch(id) - { - case 19046: i = BG_SA_GREEN_GATE; break; //Green gate destroyed - case 19045: i = BG_SA_BLUE_GATE; break; //blue gate - case 19047: i = BG_SA_RED_GATE; break; //red gate - case 19048: i = BG_SA_PURPLE_GATE; break; //purple gate - case 19049: i = BG_SA_YELLOW_GATE; break; //yellow gate - case 19837: i = BG_SA_ANCIENT_GATE; break; //ancient gate - } - return i; - } - uint32 GetWorldStateFromGateID(uint32 id) - { - uint32 uws = 0; - switch(id) - { - case BG_SA_GREEN_GATE: uws = BG_SA_GREEN_GATEWS; break; - case BG_SA_YELLOW_GATE: uws = BG_SA_YELLOW_GATEWS; break; - case BG_SA_BLUE_GATE: uws = BG_SA_BLUE_GATEWS; break; - case BG_SA_RED_GATE: uws = BG_SA_RED_GATEWS; break; - case BG_SA_PURPLE_GATE: uws = BG_SA_PURPLE_GATEWS; break; - case BG_SA_ANCIENT_GATE: uws = BG_SA_ANCIENT_GATEWS; break; - } - return uws; - } - void EndBattleGround(uint32 winner); - - void RemovePlayer(Player *plr,uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - - - /* Scorekeeping */ - void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); - - private: - bool ResetObjs(); - void StartShips(); - void TeleportPlayers(); - void OverrideGunFaction(); - void DemolisherStartState(bool start); - void DestroyGate(Player* pl, GameObject* /*go*/, uint32 destroyedEvent); - void SendTime(); - void CaptureGraveyard(BG_SA_Graveyards i, Player *Source); - void ToggleTimer(); - void UpdateDemolisherSpawns(); - TeamId attackers; - uint32 TotalTime; - uint32 BG_SA_ENDROUNDTIME; - bool ShipsStarted; - BG_SA_GateState GateStatus[6]; - BG_SA_Status status; - TeamId GraveyardStatus[BG_SA_MAX_GY]; - BG_SA_RoundScore RoundScores[2]; - bool TimerEnabled; - uint32 UpdateWaitTimer;//5secs before starting the 1min countdown for second round - bool SignaledRoundTwo; - bool SignaledRoundTwoHalfMin; - bool InitSecondRound; -}; -#endif diff --git a/src/server/game/BattleGrounds/BattleGroundWS.cpp b/src/server/game/BattleGrounds/BattleGroundWS.cpp deleted file mode 100644 index 71872511274..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundWS.cpp +++ /dev/null @@ -1,841 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BattleGround.h" -#include "BattleGroundWS.h" -#include "Creature.h" -#include "GameObject.h" -#include "Language.h" -#include "Object.h" -#include "ObjectMgr.h" -#include "BattleGroundMgr.h" -#include "Player.h" -#include "World.h" -#include "WorldPacket.h" - -// these variables aren't used outside of this file, so declare them only here -enum BG_WSG_Rewards -{ - BG_WSG_WIN = 0, - BG_WSG_FLAG_CAP, - BG_WSG_MAP_COMPLETE, - BG_WSG_REWARD_NUM -}; - -uint32 BG_WSG_Honor[BG_HONOR_MODE_NUM][BG_WSG_REWARD_NUM] = { - {20,40,40}, // normal honor - {60,40,80} // holiday -}; - -uint32 BG_WSG_Reputation[BG_HONOR_MODE_NUM][BG_WSG_REWARD_NUM] = { - {0,35,0}, // normal honor - {0,45,0} // holiday -}; - -BattleGroundWS::BattleGroundWS() -{ - m_BgObjects.resize(BG_WS_OBJECT_MAX); - m_BgCreatures.resize(BG_CREATURES_MAX_WS); - - m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; - m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; - m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; -} - -BattleGroundWS::~BattleGroundWS() -{ -} - -void BattleGroundWS::Update(uint32 diff) -{ - BattleGround::Update(diff); - - if (GetStatus() == STATUS_IN_PROGRESS) - { - if (GetStartTime() >= 25*MINUTE*IN_MILISECONDS) // Òàéìåð òèêàòü íà÷èíàåò ïîñëå 25 ìèíóò - { - if (GetTeamScore(ALLIANCE) == 0) - { - if (GetTeamScore(HORDE) == 0) // No one scored - result is tie - EndBattleGround(NULL); - else // Horde has more points and thus wins - EndBattleGround(HORDE); - } - - else if (GetTeamScore(HORDE) == 0) - EndBattleGround(ALLIANCE); // Alliance has > 0, Horde has 0, alliance wins - - else if (GetTeamScore(HORDE) == GetTeamScore(ALLIANCE)) // Team score equal, winner is team that scored the first flag - EndBattleGround(m_FirstFlagCaptureTeam); - - else if (GetTeamScore(HORDE) > GetTeamScore(ALLIANCE)) // Last but not least, check who has the higher score - EndBattleGround(HORDE); - else - EndBattleGround(ALLIANCE); - } - else if (GetStartTime() > m_minutesElapsed*MINUTE*IN_MILISECONDS) - { - ++m_minutesElapsed; - UpdateWorldState(BG_WS_STATE_TIMER, 25-m_minutesElapsed); - } - - if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) - { - m_FlagsTimer[BG_TEAM_ALLIANCE] -= diff; - - if (m_FlagsTimer[BG_TEAM_ALLIANCE] < 0) - { - m_FlagsTimer[BG_TEAM_ALLIANCE] = 0; - RespawnFlag(ALLIANCE, true); - } - } - if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) - { - m_FlagsDropTimer[BG_TEAM_ALLIANCE] -= diff; - - if (m_FlagsDropTimer[BG_TEAM_ALLIANCE] < 0) - { - m_FlagsDropTimer[BG_TEAM_ALLIANCE] = 0; - RespawnFlagAfterDrop(ALLIANCE); - m_BothFlagsKept = false; - } - } - if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) - { - m_FlagsTimer[BG_TEAM_HORDE] -= diff; - - if (m_FlagsTimer[BG_TEAM_HORDE] < 0) - { - m_FlagsTimer[BG_TEAM_HORDE] = 0; - RespawnFlag(HORDE, true); - } - } - if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) - { - m_FlagsDropTimer[BG_TEAM_HORDE] -= diff; - - if (m_FlagsDropTimer[BG_TEAM_HORDE] < 0) - { - m_FlagsDropTimer[BG_TEAM_HORDE] = 0; - RespawnFlagAfterDrop(HORDE); - m_BothFlagsKept = false; - } - } - if (m_BothFlagsKept) - { - m_FlagSpellForceTimer += diff; - if (m_FlagDebuffState == 0 && m_FlagSpellForceTimer >= 600000) //10 minutes - { - if (Player * plr = objmgr.GetPlayer(m_FlagKeepers[0])) - plr->CastSpell(plr,WS_SPELL_FOCUSED_ASSAULT,true); - if (Player * plr = objmgr.GetPlayer(m_FlagKeepers[1])) - plr->CastSpell(plr,WS_SPELL_FOCUSED_ASSAULT,true); - m_FlagDebuffState = 1; - } - else if (m_FlagDebuffState == 1 && m_FlagSpellForceTimer >= 900000) //15 minutes - { - if (Player * plr = objmgr.GetPlayer(m_FlagKeepers[0])) - { - plr->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - plr->CastSpell(plr,WS_SPELL_BRUTAL_ASSAULT,true); - } - if (Player * plr = objmgr.GetPlayer(m_FlagKeepers[1])) - { - plr->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - plr->CastSpell(plr,WS_SPELL_BRUTAL_ASSAULT,true); - } - m_FlagDebuffState = 2; - } - } - else - { - m_FlagSpellForceTimer = 0; //reset timer. - m_FlagDebuffState = 0; - } - } -} - -void BattleGroundWS::StartingEventCloseDoors() -{ - for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; ++i) - { - DoorClose(i); - SpawnBGObject(i, RESPAWN_IMMEDIATELY); - } - for (uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i) - SpawnBGObject(i, RESPAWN_ONE_DAY); - - UpdateWorldState(BG_WS_STATE_TIMER_ACTIVE, 1); - UpdateWorldState(BG_WS_STATE_TIMER, 25); -} - -void BattleGroundWS::StartingEventOpenDoors() -{ - for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; ++i) - DoorOpen(i); - for (uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; ++i) - DoorOpen(i); - - SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY); - SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY); - - for (uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i) - SpawnBGObject(i, RESPAWN_IMMEDIATELY); -} - -void BattleGroundWS::AddPlayer(Player *plr) -{ - BattleGround::AddPlayer(plr); - //create score and add it to map, default values are set in constructor - BattleGroundWGScore* sc = new BattleGroundWGScore; - - m_PlayerScores[plr->GetGUID()] = sc; -} - -void BattleGroundWS::RespawnFlag(uint32 Team, bool captured) -{ - if (Team == ALLIANCE) - { - sLog.outDebug("Respawn Alliance flag"); - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; - } - else - { - sLog.outDebug("Respawn Horde flag"); - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; - } - - if (captured) - { - //when map_update will be allowed for battlegrounds this code will be useless - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL); - PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound... - } - m_BothFlagsKept = false; -} - -void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - RespawnFlag(team,false); - if (team == ALLIANCE) - { - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); - } - else - { - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); - SendMessageToAll(LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); - } - - PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); - - GameObject *obj = GetBgMap()->GetGameObject(GetDroppedFlagGUID(team)); - if (obj) - obj->Delete(); - else - sLog.outError("unknown droped flag bg, guid: %u",GUID_LOPART(GetDroppedFlagGUID(team))); - - SetDroppedFlagGUID(0,team); - m_BothFlagsKept = false; -} - -void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - uint32 winner = 0; - - Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); - if (Source->GetTeam() == ALLIANCE) - { - if (!this->IsHordeFlagPickedup()) - return; - SetHordeFlagPicker(0); // must be before aura remove to prevent 2 events (drop+capture) at the same time - // horde flag in base (but not respawned yet) - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; - // Drop Horde Flag from Player - Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); - if (m_FlagDebuffState == 1) - Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - if (m_FlagDebuffState == 2) - Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); - if (GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE) - AddPoint(ALLIANCE, 1); - PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE); - RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE); - } - else - { - if (!this->IsAllianceFlagPickedup()) - return; - SetAllianceFlagPicker(0); // must be before aura remove to prevent 2 events (drop+capture) at the same time - // alliance flag in base (but not respawned yet) - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; - // Drop Alliance Flag from Player - Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); - if (m_FlagDebuffState == 1) - Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - if (m_FlagDebuffState == 2) - Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); - if (GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE) - AddPoint(HORDE, 1); - PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE); - RewardReputationToTeam(889, m_ReputationCapture, HORDE); - } - //for flag capture is reward 2 honorable kills - RewardHonorToTeam(GetBonusHonorFromKill(2), Source->GetTeam()); - - SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME); - - if (Source->GetTeam() == ALLIANCE) - SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); - else - SendMessageToAll(LANG_BG_WS_CAPTURED_AF, CHAT_MSG_BG_SYSTEM_HORDE, Source); - - UpdateFlagState(Source->GetTeam(), 1); // flag state none - UpdateTeamScore(Source->GetTeam()); - // only flag capture should be updated - UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures - - if (!m_FirstFlagCaptureTeam) - SetFirstFlagCapture(Source->GetTeam()); - - if (GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE) - winner = ALLIANCE; - - if (GetTeamScore(HORDE) == BG_WS_MAX_TEAM_SCORE) - winner = HORDE; - - if (winner) - { - UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 0); - UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 0); - UpdateWorldState(BG_WS_FLAG_STATE_ALLIANCE, 1); - UpdateWorldState(BG_WS_FLAG_STATE_HORDE, 1); - UpdateWorldState(BG_WS_STATE_TIMER_ACTIVE, 0); - - RewardHonorToTeam(BG_WSG_Honor[m_HonorMode][BG_WSG_WIN], winner); - EndBattleGround(winner); - } - else - { - m_FlagsTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_RESPAWN_TIME; - } -} - -void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - { - // if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages - // just take off the aura - if (Source->GetTeam() == ALLIANCE) - { - if (!this->IsHordeFlagPickedup()) - return; - if (GetHordeFlagPickerGUID() == Source->GetGUID()) - { - SetHordeFlagPicker(0); - Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); - } - } - else - { - if (!this->IsAllianceFlagPickedup()) - return; - if (GetAllianceFlagPickerGUID() == Source->GetGUID()) - { - SetAllianceFlagPicker(0); - Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); - } - } - return; - } - - bool set = false; - - if (Source->GetTeam() == ALLIANCE) - { - if (!IsHordeFlagPickedup()) - return; - if (GetHordeFlagPickerGUID() == Source->GetGUID()) - { - SetHordeFlagPicker(0); - Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); - if (m_FlagDebuffState == 1) - Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - if (m_FlagDebuffState == 2) - Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND; - Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true); - set = true; - } - } - else - { - if (!IsAllianceFlagPickedup()) - return; - if (GetAllianceFlagPickerGUID() == Source->GetGUID()) - { - SetAllianceFlagPicker(0); - Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); - if (m_FlagDebuffState == 1) - Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); - if (m_FlagDebuffState == 2) - Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND; - Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true); - set = true; - } - } - - if (set) - { - Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); - UpdateFlagState(Source->GetTeam(), 1); - - if (Source->GetTeam() == ALLIANCE) - { - SendMessageToAll(LANG_BG_WS_DROPPED_HF, CHAT_MSG_BG_SYSTEM_HORDE, Source); - UpdateWorldState(BG_WS_FLAG_UNK_HORDE, uint32(-1)); - } - else - { - SendMessageToAll(LANG_BG_WS_DROPPED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); - UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, uint32(-1)); - } - - m_FlagsDropTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_DROP_TIME; - } -} - -void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - int32 message_id = 0; - ChatMsg type = CHAT_MSG_BG_SYSTEM_NEUTRAL; - - //alliance flag picked up from base - if (Source->GetTeam() == HORDE && this->GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE - && this->m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) - { - message_id = LANG_BG_WS_PICKEDUP_AF; - type = CHAT_MSG_BG_SYSTEM_HORDE; - PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); - SetAllianceFlagPicker(Source->GetGUID()); - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; - //update world state to show correct flag carrier - UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER); - UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1); - Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); - if (m_FlagState[1] == BG_WS_FLAG_STATE_ON_PLAYER) - m_BothFlagsKept = true; - } - - //horde flag picked up from base - if (Source->GetTeam() == ALLIANCE && this->GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE - && this->m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) - { - message_id = LANG_BG_WS_PICKEDUP_HF; - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); - SetHordeFlagPicker(Source->GetGUID()); - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; - //update world state to show correct flag carrier - UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER); - UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1); - Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); - if (m_FlagState[0] == BG_WS_FLAG_STATE_ON_PLAYER) - m_BothFlagsKept = true; - } - - //Alliance flag on ground(not in base) (returned or picked up again from ground!) - if (GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10)) - { - if (Source->GetTeam() == ALLIANCE) - { - message_id = LANG_BG_WS_RETURNED_AF; - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - UpdateFlagState(HORDE, BG_WS_FLAG_STATE_WAIT_RESPAWN); - RespawnFlag(ALLIANCE, false); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); - PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); - UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); - m_BothFlagsKept = false; - } - else - { - message_id = LANG_BG_WS_PICKEDUP_AF; - type = CHAT_MSG_BG_SYSTEM_HORDE; - PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); - SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); - SetAllianceFlagPicker(Source->GetGUID()); - Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; - UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER); - if (m_FlagDebuffState == 1) - Source->CastSpell(Source,WS_SPELL_FOCUSED_ASSAULT,true); - if (m_FlagDebuffState == 2) - Source->CastSpell(Source,WS_SPELL_BRUTAL_ASSAULT,true); - UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1); - } - //called in HandleGameObjectUseOpcode: - //target_obj->Delete(); - } - - //Horde flag on ground(not in base) (returned or picked up again) - if (GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10)) - { - if (Source->GetTeam() == HORDE) - { - message_id = LANG_BG_WS_RETURNED_HF; - type = CHAT_MSG_BG_SYSTEM_HORDE; - UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_WAIT_RESPAWN); - RespawnFlag(HORDE, false); - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); - PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); - UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); - m_BothFlagsKept = false; - } - else - { - message_id = LANG_BG_WS_PICKEDUP_HF; - type = CHAT_MSG_BG_SYSTEM_ALLIANCE; - PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); - SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); - SetHordeFlagPicker(Source->GetGUID()); - Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; - UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER); - if (m_FlagDebuffState == 1) - Source->CastSpell(Source,WS_SPELL_FOCUSED_ASSAULT,true); - if (m_FlagDebuffState == 2) - Source->CastSpell(Source,WS_SPELL_BRUTAL_ASSAULT,true); - UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1); - } - //called in HandleGameObjectUseOpcode: - //target_obj->Delete(); - } - - if (!message_id) - return; - - SendMessageToAll(message_id, type, Source); - Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); -} - -void BattleGroundWS::RemovePlayer(Player *plr, uint64 guid) -{ - // sometimes flag aura not removed :( - if (IsAllianceFlagPickedup() && m_FlagKeepers[BG_TEAM_ALLIANCE] == guid) - { - if (!plr) - { - sLog.outError("BattleGroundWS: Removing offline player who has the FLAG!!"); - this->SetAllianceFlagPicker(0); - this->RespawnFlag(ALLIANCE, false); - } - else - this->EventPlayerDroppedFlag(plr); - } - if (IsHordeFlagPickedup() && m_FlagKeepers[BG_TEAM_HORDE] == guid) - { - if (!plr) - { - sLog.outError("BattleGroundWS: Removing offline player who has the FLAG!!"); - this->SetHordeFlagPicker(0); - this->RespawnFlag(HORDE, false); - } - else - this->EventPlayerDroppedFlag(plr); - } -} - -void BattleGroundWS::UpdateFlagState(uint32 team, uint32 value) -{ - if (team == ALLIANCE) - UpdateWorldState(BG_WS_FLAG_STATE_ALLIANCE, value); - else - UpdateWorldState(BG_WS_FLAG_STATE_HORDE, value); -} - -void BattleGroundWS::UpdateTeamScore(uint32 team) -{ - if (team == ALLIANCE) - UpdateWorldState(BG_WS_FLAG_CAPTURES_ALLIANCE, GetTeamScore(team)); - else - UpdateWorldState(BG_WS_FLAG_CAPTURES_HORDE, GetTeamScore(team)); -} - -void BattleGroundWS::HandleAreaTrigger(Player *Source, uint32 Trigger) -{ - // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - //uint32 SpellId = 0; - //uint64 buff_guid = 0; - switch(Trigger) - { - case 3686: // Alliance elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update(). - //buff_guid = m_BgObjects[BG_WS_OBJECT_SPEEDBUFF_1]; - break; - case 3687: // Horde elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update(). - //buff_guid = m_BgObjects[BG_WS_OBJECT_SPEEDBUFF_2]; - break; - case 3706: // Alliance elixir of regeneration spawn - //buff_guid = m_BgObjects[BG_WS_OBJECT_REGENBUFF_1]; - break; - case 3708: // Horde elixir of regeneration spawn - //buff_guid = m_BgObjects[BG_WS_OBJECT_REGENBUFF_2]; - break; - case 3707: // Alliance elixir of berserk spawn - //buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_1]; - break; - case 3709: // Horde elixir of berserk spawn - //buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_2]; - break; - case 3646: // Alliance Flag spawn - if (m_FlagState[BG_TEAM_HORDE] && !m_FlagState[BG_TEAM_ALLIANCE]) - if (GetHordeFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source); - break; - case 3647: // Horde Flag spawn - if (m_FlagState[BG_TEAM_ALLIANCE] && !m_FlagState[BG_TEAM_HORDE]) - if (GetAllianceFlagPickerGUID() == Source->GetGUID()) - EventPlayerCapturedFlag(Source); - break; - case 3649: // unk1 - case 3688: // unk2 - case 4628: // unk3 - case 4629: // unk4 - break; - default: - sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); - Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); - break; - } - - //if (buff_guid) - // HandleTriggerBuff(buff_guid,Source); -} - -bool BattleGroundWS::SetupBattleGround() -{ - // flags - if (!AddObject(BG_WS_OBJECT_A_FLAG, BG_OBJECT_A_FLAG_WS_ENTRY, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, BG_WS_FLAG_RESPAWN_TIME/1000) - || !AddObject(BG_WS_OBJECT_H_FLAG, BG_OBJECT_H_FLAG_WS_ENTRY, 916.0226f, 1434.405f, 345.413f, 0.01745329f, 0, 0, 0.008726535f, 0.9999619f, BG_WS_FLAG_RESPAWN_TIME/1000) - // buffs - || !AddObject(BG_WS_OBJECT_SPEEDBUFF_1, BG_OBJECTID_SPEEDBUFF_ENTRY, 1449.93f, 1470.71f, 342.6346f, -1.64061f, 0, 0, 0.7313537f, -0.6819983f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_SPEEDBUFF_2, BG_OBJECTID_SPEEDBUFF_ENTRY, 1005.171f, 1447.946f, 335.9032f, 1.64061f, 0, 0, 0.7313537f, 0.6819984f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_REGENBUFF_1, BG_OBJECTID_REGENBUFF_ENTRY, 1317.506f, 1550.851f, 313.2344f, -0.2617996f, 0, 0, 0.1305263f, -0.9914448f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_REGENBUFF_2, BG_OBJECTID_REGENBUFF_ENTRY, 1110.451f, 1353.656f, 316.5181f, -0.6806787f, 0, 0, 0.333807f, -0.9426414f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_BERSERKBUFF_1, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1320.09f, 1378.79f, 314.7532f, 1.186824f, 0, 0, 0.5591929f, 0.8290376f, BUFF_RESPAWN_TIME) - || !AddObject(BG_WS_OBJECT_BERSERKBUFF_2, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1139.688f, 1560.288f, 306.8432f, -2.443461f, 0, 0, 0.9396926f, -0.3420201f, BUFF_RESPAWN_TIME) - // alliance gates - || !AddObject(BG_WS_OBJECT_DOOR_A_1, BG_OBJECT_DOOR_A_1_WS_ENTRY, 1503.335f, 1493.466f, 352.1888f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_2, BG_OBJECT_DOOR_A_2_WS_ENTRY, 1492.478f, 1457.912f, 342.9689f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_3, BG_OBJECT_DOOR_A_3_WS_ENTRY, 1468.503f, 1494.357f, 351.8618f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_4, BG_OBJECT_DOOR_A_4_WS_ENTRY, 1471.555f, 1458.778f, 362.6332f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_5, BG_OBJECT_DOOR_A_5_WS_ENTRY, 1492.347f, 1458.34f, 342.3712f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_A_6, BG_OBJECT_DOOR_A_6_WS_ENTRY, 1503.466f, 1493.367f, 351.7352f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY) - // horde gates - || !AddObject(BG_WS_OBJECT_DOOR_H_1, BG_OBJECT_DOOR_H_1_WS_ENTRY, 949.1663f, 1423.772f, 345.6241f, -0.5756807f, -0.01673368f, -0.004956111f, -0.2839723f, 0.9586737f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_H_2, BG_OBJECT_DOOR_H_2_WS_ENTRY, 953.0507f, 1459.842f, 340.6526f, -1.99662f, -0.1971825f, 0.1575096f, -0.8239487f, 0.5073641f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_H_3, BG_OBJECT_DOOR_H_3_WS_ENTRY, 949.9523f, 1422.751f, 344.9273f, 0.0f, 0, 0, 0, 1, RESPAWN_IMMEDIATELY) - || !AddObject(BG_WS_OBJECT_DOOR_H_4, BG_OBJECT_DOOR_H_4_WS_ENTRY, 950.7952f, 1459.583f, 342.1523f, 0.05235988f, 0, 0, 0.02617695f, 0.9996573f, RESPAWN_IMMEDIATELY) -) - { - sLog.outErrorDb("BatteGroundWS: Failed to spawn some object BattleGround not created!"); - return false; - } - - WorldSafeLocsEntry const *sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE); - if (!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE)) - { - sLog.outErrorDb("BatteGroundWS: Failed to spawn Alliance spirit guide! BattleGround not created!"); - return false; - } - - sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE); - if (!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE)) - { - sLog.outErrorDb("BatteGroundWS: Failed to spawn Horde spirit guide! BattleGround not created!"); - return false; - } - - sLog.outDebug("BatteGroundWS: BG objects and spirit guides spawned"); - - return true; -} - -void BattleGroundWS::Reset() -{ - //call parent's class reset - BattleGround::Reset(); - - m_FlagKeepers[BG_TEAM_ALLIANCE] = 0; - m_FlagKeepers[BG_TEAM_HORDE] = 0; - m_DroppedFlagGUID[BG_TEAM_ALLIANCE] = 0; - m_DroppedFlagGUID[BG_TEAM_HORDE] = 0; - m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; - m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; - m_TeamScores[BG_TEAM_ALLIANCE] = 0; - m_TeamScores[BG_TEAM_HORDE] = 0; - bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); - m_ReputationCapture = (isBGWeekend) ? 45 : 35; - m_HonorWinKills = (isBGWeekend) ? 3 : 1; - m_HonorEndKills = (isBGWeekend) ? 4 : 2; - // For WorldState - m_minutesElapsed = 0; - m_FirstFlagCaptureTeam = 0; - - /* Spirit nodes is static at this BG and then not required deleting at BG reset. - if (m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE]) - DelCreature(WS_SPIRIT_MAIN_ALLIANCE); - if (m_BgCreatures[WS_SPIRIT_MAIN_HORDE]) - DelCreature(WS_SPIRIT_MAIN_HORDE); - */ -} - -void BattleGroundWS::EndBattleGround(uint32 winner) -{ - //win reward - if (winner == ALLIANCE) - RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), ALLIANCE); - if (winner == HORDE) - RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), HORDE); - //complete map_end rewards (even if no team wins) - RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), ALLIANCE); - RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), HORDE); - - BattleGround::EndBattleGround(winner); -} - -void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer) -{ - if (GetStatus() != STATUS_IN_PROGRESS) - return; - - EventPlayerDroppedFlag(player); - - BattleGround::HandleKillPlayer(player, killer); -} - -void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor) -{ - - BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); - if (itr == m_PlayerScores.end()) // player not found - return; - - switch(type) - { - case SCORE_FLAG_CAPTURES: // flags captured - ((BattleGroundWGScore*)itr->second)->FlagCaptures += value; - break; - case SCORE_FLAG_RETURNS: // flags returned - ((BattleGroundWGScore*)itr->second)->FlagReturns += value; - break; - default: - BattleGround::UpdatePlayerScore(Source, type, value, doAddHonor); - break; - } -} - -WorldSafeLocsEntry const* BattleGroundWS::GetClosestGraveYard(Player* player) -{ - //if status in progress, it returns main graveyards with spiritguides - //else it will return the graveyard in the flagroom - this is especially good - //if a player dies in preparation phase - then the player can't cheat - //and teleport to the graveyard outside the flagroom - //and start running around, while the doors are still closed - if (player->GetTeam() == ALLIANCE) - { - if (GetStatus() == STATUS_IN_PROGRESS) - return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE); - else - return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_ALLIANCE); - } - else - { - if (GetStatus() == STATUS_IN_PROGRESS) - return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE); - else - return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_HORDE); - } -} - -void BattleGroundWS::FillInitialWorldStates(WorldPacket& data) -{ - data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(ALLIANCE)); - data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(HORDE)); - - if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) - data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(-1); - else if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) - data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(1); - else - data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(0); - - if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) - data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(-1); - else if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) - data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(1); - else - data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(0); - - data << uint32(BG_WS_FLAG_CAPTURES_MAX) << uint32(BG_WS_MAX_TEAM_SCORE); - - if (GetStatus() == STATUS_IN_PROGRESS) - { - data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(1); - data << uint32(BG_WS_STATE_TIMER) << uint32(25-m_minutesElapsed); - } - else - data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(0); - - if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) - data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(2); - else - data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(1); - - if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) - data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(2); - else - data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(1); - -} - diff --git a/src/server/game/BattleGrounds/BattleGroundWS.h b/src/server/game/BattleGrounds/BattleGroundWS.h deleted file mode 100644 index 1a733c14570..00000000000 --- a/src/server/game/BattleGrounds/BattleGroundWS.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __BATTLEGROUNDWS_H -#define __BATTLEGROUNDWS_H - -#include "BattleGround.h" - -enum BG_WS_TimerOrScore -{ - BG_WS_MAX_TEAM_SCORE = 3, - BG_WS_FLAG_RESPAWN_TIME = 23000, - BG_WS_FLAG_DROP_TIME = 10000, - BG_WS_SPELL_FORCE_TIME = 600000, - BG_WS_SPELL_BRUTAL_TIME = 900000 -}; - -enum BG_WS_Sound -{ - BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, - BG_WS_SOUND_FLAG_CAPTURED_HORDE = 8213, - BG_WS_SOUND_FLAG_PLACED = 8232, - BG_WS_SOUND_FLAG_RETURNED = 8192, - BG_WS_SOUND_HORDE_FLAG_PICKED_UP = 8212, - BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP = 8174, - BG_WS_SOUND_FLAGS_RESPAWNED = 8232 -}; - -enum BG_WS_SpellId -{ - BG_WS_SPELL_WARSONG_FLAG = 23333, - BG_WS_SPELL_WARSONG_FLAG_DROPPED = 23334, - BG_WS_SPELL_SILVERWING_FLAG = 23335, - BG_WS_SPELL_SILVERWING_FLAG_DROPPED = 23336, - BG_WS_SPELL_FOCUSED_ASSAULT = 46392, - BG_WS_SPELL_BRUTAL_ASSAULT = 46393 -}; - -enum BG_WS_WorldStates -{ - BG_WS_FLAG_UNK_ALLIANCE = 1545, - BG_WS_FLAG_UNK_HORDE = 1546, -// FLAG_UNK = 1547, - BG_WS_FLAG_CAPTURES_ALLIANCE = 1581, - BG_WS_FLAG_CAPTURES_HORDE = 1582, - BG_WS_FLAG_CAPTURES_MAX = 1601, - BG_WS_FLAG_STATE_HORDE = 2338, - BG_WS_FLAG_STATE_ALLIANCE = 2339, - BG_WS_STATE_TIMER = 4248, - BG_WS_STATE_TIMER_ACTIVE = 4247 -}; - -enum BG_WS_ObjectTypes -{ - BG_WS_OBJECT_DOOR_A_1 = 0, - BG_WS_OBJECT_DOOR_A_2 = 1, - BG_WS_OBJECT_DOOR_A_3 = 2, - BG_WS_OBJECT_DOOR_A_4 = 3, - BG_WS_OBJECT_DOOR_A_5 = 4, - BG_WS_OBJECT_DOOR_A_6 = 5, - BG_WS_OBJECT_DOOR_H_1 = 6, - BG_WS_OBJECT_DOOR_H_2 = 7, - BG_WS_OBJECT_DOOR_H_3 = 8, - BG_WS_OBJECT_DOOR_H_4 = 9, - BG_WS_OBJECT_A_FLAG = 10, - BG_WS_OBJECT_H_FLAG = 11, - BG_WS_OBJECT_SPEEDBUFF_1 = 12, - BG_WS_OBJECT_SPEEDBUFF_2 = 13, - BG_WS_OBJECT_REGENBUFF_1 = 14, - BG_WS_OBJECT_REGENBUFF_2 = 15, - BG_WS_OBJECT_BERSERKBUFF_1 = 16, - BG_WS_OBJECT_BERSERKBUFF_2 = 17, - BG_WS_OBJECT_MAX = 18 -}; - -enum BG_WS_ObjectEntry -{ - BG_OBJECT_DOOR_A_1_WS_ENTRY = 179918, - BG_OBJECT_DOOR_A_2_WS_ENTRY = 179919, - BG_OBJECT_DOOR_A_3_WS_ENTRY = 179920, - BG_OBJECT_DOOR_A_4_WS_ENTRY = 179921, - BG_OBJECT_DOOR_A_5_WS_ENTRY = 180322, - BG_OBJECT_DOOR_A_6_WS_ENTRY = 180322, - BG_OBJECT_DOOR_H_1_WS_ENTRY = 179916, - BG_OBJECT_DOOR_H_2_WS_ENTRY = 179917, - BG_OBJECT_DOOR_H_3_WS_ENTRY = 180322, - BG_OBJECT_DOOR_H_4_WS_ENTRY = 180322, - BG_OBJECT_A_FLAG_WS_ENTRY = 179830, - BG_OBJECT_H_FLAG_WS_ENTRY = 179831, - BG_OBJECT_A_FLAG_GROUND_WS_ENTRY = 179785, - BG_OBJECT_H_FLAG_GROUND_WS_ENTRY = 179786 -}; - -enum BG_WS_FlagState -{ - BG_WS_FLAG_STATE_ON_BASE = 0, - BG_WS_FLAG_STATE_WAIT_RESPAWN = 1, - BG_WS_FLAG_STATE_ON_PLAYER = 2, - BG_WS_FLAG_STATE_ON_GROUND = 3 -}; - -enum BG_WS_Graveyards -{ - WS_GRAVEYARD_FLAGROOM_ALLIANCE = 769, - WS_GRAVEYARD_FLAGROOM_HORDE = 770, - WS_GRAVEYARD_MAIN_ALLIANCE = 771, - WS_GRAVEYARD_MAIN_HORDE = 772 -}; - -enum BG_WS_CreatureTypes -{ - WS_SPIRIT_MAIN_ALLIANCE = 0, - WS_SPIRIT_MAIN_HORDE = 1, - - BG_CREATURES_MAX_WS = 2 -}; - -enum BG_WS_CarrierDebuffs -{ - WS_SPELL_FOCUSED_ASSAULT = 46392, - WS_SPELL_BRUTAL_ASSAULT = 46393 -}; - -class BattleGroundWGScore : public BattleGroundScore -{ - public: - BattleGroundWGScore() : FlagCaptures(0), FlagReturns(0) {}; - virtual ~BattleGroundWGScore() {}; - uint32 FlagCaptures; - uint32 FlagReturns; -}; - -class BattleGroundWS : public BattleGround -{ - friend class BattleGroundMgr; - - public: - /* Construction */ - BattleGroundWS(); - ~BattleGroundWS(); - void Update(uint32 diff); - - /* inherited from BattlegroundClass */ - virtual void AddPlayer(Player *plr); - virtual void StartingEventCloseDoors(); - virtual void StartingEventOpenDoors(); - - /* BG Flags */ - uint64 GetAllianceFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_ALLIANCE]; } - uint64 GetHordeFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_HORDE]; } - void SetAllianceFlagPicker(uint64 guid) { m_FlagKeepers[BG_TEAM_ALLIANCE] = guid; } - void SetHordeFlagPicker(uint64 guid) { m_FlagKeepers[BG_TEAM_HORDE] = guid; } - bool IsAllianceFlagPickedup() const { return m_FlagKeepers[BG_TEAM_ALLIANCE] != 0; } - bool IsHordeFlagPickedup() const { return m_FlagKeepers[BG_TEAM_HORDE] != 0; } - void RespawnFlag(uint32 Team, bool captured); - void RespawnFlagAfterDrop(uint32 Team); - uint8 GetFlagState(uint32 team) { return m_FlagState[GetTeamIndexByTeamId(team)]; } - void AddTimedAura(uint32 aura); - void RemoveTimedAura(uint32 aura); - bool IsBrutalTimerDone; - bool IsForceTimerDone; - - /* Battleground Events */ - virtual void EventPlayerDroppedFlag(Player *Source); - virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); - virtual void EventPlayerCapturedFlag(Player *Source); - - void RemovePlayer(Player *plr, uint64 guid); - void HandleAreaTrigger(Player *Source, uint32 Trigger); - void HandleKillPlayer(Player *player, Player *killer); - bool SetupBattleGround(); - virtual void Reset(); - void EndBattleGround(uint32 winner); - virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); - - void UpdateFlagState(uint32 team, uint32 value); - void SetFirstFlagCapture(uint32 team) { m_FirstFlagCaptureTeam = team; } - void UpdateTeamScore(uint32 team); - void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); - void SetDroppedFlagGUID(uint64 guid, uint32 TeamID) { m_DroppedFlagGUID[GetTeamIndexByTeamId(TeamID)] = guid;} - uint64 GetDroppedFlagGUID(uint32 TeamID) { return m_DroppedFlagGUID[GetTeamIndexByTeamId(TeamID)];} - virtual void FillInitialWorldStates(WorldPacket& data); - - /* Scorekeeping */ - uint32 GetTeamScore(uint32 TeamID) const { return m_TeamScores[GetTeamIndexByTeamId(TeamID)]; } - void AddPoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] += Points; } - void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } - void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } - private: - uint64 m_FlagKeepers[2]; // 0 - alliance, 1 - horde - uint64 m_DroppedFlagGUID[2]; - uint8 m_FlagState[2]; // for checking flag state - int32 m_FlagsTimer[2]; - int32 m_FlagsDropTimer[2]; - uint32 m_FirstFlagCaptureTeam; // Winner is based on this if score is equal - - uint32 m_ReputationCapture; - uint32 m_HonorWinKills; - uint32 m_HonorEndKills; - int32 m_FlagSpellForceTimer; - bool m_BothFlagsKept; - uint8 m_FlagDebuffState; // 0 - no debuffs, 1 - focused assault, 2 - brutal assault - uint8 m_minutesElapsed; -}; -#endif - diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundAA.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundAA.cpp new file mode 100644 index 00000000000..56cf3ebed15 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundAA.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundAA.h" +#include "Language.h" +#include "Player.h" + +BattleGroundAA::BattleGroundAA() +{ + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; +} + +BattleGroundAA::~BattleGroundAA() +{ + +} + +void BattleGroundAA::Update(uint32 diff) +{ + BattleGround::Update(diff); +} + +void BattleGroundAA::StartingEventCloseDoors() +{ +} + +void BattleGroundAA::StartingEventOpenDoors() +{ +} + +void BattleGroundAA::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundAAScore* sc = new BattleGroundAAScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundAA::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) +{ +} + +void BattleGroundAA::HandleKillPlayer(Player* player, Player* killer) +{ + BattleGround::HandleKillPlayer(player, killer); +} + +void BattleGroundAA::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) +{ +} + +bool BattleGroundAA::SetupBattleGround() +{ + return true; +} + diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundAA.h b/src/server/game/BattleGrounds/Zones/BattleGroundAA.h new file mode 100644 index 00000000000..a13833697cf --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundAA.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDAA_H +#define __BATTLEGROUNDAA_H + +class BattleGround; + +class BattleGroundAAScore : public BattleGroundScore +{ + public: + BattleGroundAAScore() {}; + virtual ~BattleGroundAAScore() {}; + //TODO fix me +}; + +class BattleGroundAA : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundAA(); + ~BattleGroundAA(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + void HandleKillPlayer(Player* player, Player *killer); +}; +#endif + diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundAB.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundAB.cpp new file mode 100644 index 00000000000..38671e85597 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundAB.cpp @@ -0,0 +1,715 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "World.h" +#include "WorldPacket.h" +#include "ObjectMgr.h" +#include "BattleGroundMgr.h" +#include "BattleGround.h" +#include "BattleGroundAB.h" +#include "Creature.h" +#include "Language.h" +#include "Object.h" +#include "Player.h" +#include "Util.h" + +// these variables aren't used outside of this file, so declare them only here +uint32 BG_AB_HonorScoreTicks[BG_HONOR_MODE_NUM] = { + 330, // normal honor + 200 // holiday +}; + +uint32 BG_AB_ReputationScoreTicks[BG_HONOR_MODE_NUM] = { + 200, // normal honor + 150 // holiday +}; + +BattleGroundAB::BattleGroundAB() +{ + m_BuffChange = true; + m_BgObjects.resize(BG_AB_OBJECT_MAX); + m_BgCreatures.resize(BG_AB_ALL_NODES_COUNT + 5);//+5 for aura triggers + + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AB_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AB_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AB_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AB_HAS_BEGUN; +} + +BattleGroundAB::~BattleGroundAB() +{ +} + +void BattleGroundAB::Update(uint32 diff) +{ + BattleGround::Update(diff); + + if (GetStatus() == STATUS_IN_PROGRESS) + { + int team_points[BG_TEAMS_COUNT] = { 0, 0 }; + + for (int node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + { + // 3 sec delay to spawn new banner instead previous despawned one + if (m_BannerTimers[node].timer) + { + if (m_BannerTimers[node].timer > diff) + m_BannerTimers[node].timer -= diff; + else + { + m_BannerTimers[node].timer = 0; + _CreateBanner(node, m_BannerTimers[node].type, m_BannerTimers[node].teamIndex, false); + } + } + + // 1-minute to occupy a node from contested state + if (m_NodeTimers[node]) + { + if (m_NodeTimers[node] > diff) + m_NodeTimers[node] -= diff; + else + { + m_NodeTimers[node] = 0; + // Change from contested to occupied ! + uint8 teamIndex = m_Nodes[node]-1; + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] += 2; + // burn current contested banner + _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex); + // create new occupied banner + _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); + _SendNodeUpdate(node); + _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); + // Message to chatlog + + if (teamIndex == 0) + { + // FIXME: team and node names not localized + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE,NULL,LANG_BG_AB_ALLY,_GetNodeNameId(node)); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_ALLIANCE); + } + else + { + // FIXME: team and node names not localized + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE,NULL,LANG_BG_AB_HORDE,_GetNodeNameId(node)); + PlaySoundToAll(BG_AB_SOUND_NODE_CAPTURED_HORDE); + } + } + } + + for (int team = 0; team < BG_TEAMS_COUNT; ++team) + if (m_Nodes[node] == team + BG_AB_NODE_TYPE_OCCUPIED) + ++team_points[team]; + } + + // Accumulate points + for (int team = 0; team < BG_TEAMS_COUNT; ++team) + { + int points = team_points[team]; + if (!points) + continue; + m_lastTick[team] += diff; + if (m_lastTick[team] > BG_AB_TickIntervals[points]) + { + m_lastTick[team] -= BG_AB_TickIntervals[points]; + m_TeamScores[team] += BG_AB_TickPoints[points]; + m_HonorScoreTics[team] += BG_AB_TickPoints[points]; + m_ReputationScoreTics[team] += BG_AB_TickPoints[points]; + if (m_ReputationScoreTics[team] >= m_ReputationTics) + { + (team == BG_TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE); + m_ReputationScoreTics[team] -= m_ReputationTics; + } + if (m_HonorScoreTics[team] >= m_HonorTics) + { + RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BG_TEAM_ALLIANCE) ? ALLIANCE : HORDE); + m_HonorScoreTics[team] -= m_HonorTics; + } + if (!m_IsInformedNearVictory && m_TeamScores[team] > BG_AB_WARNING_NEAR_VICTORY_SCORE) + { + if (team == BG_TEAM_ALLIANCE) + SendMessageToAll(LANG_BG_AB_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); + else + SendMessageToAll(LANG_BG_AB_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); + PlaySoundToAll(BG_AB_SOUND_NEAR_VICTORY); + m_IsInformedNearVictory = true; + } + + if (m_TeamScores[team] > BG_AB_MAX_TEAM_SCORE) + m_TeamScores[team] = BG_AB_MAX_TEAM_SCORE; + if (team == BG_TEAM_ALLIANCE) + UpdateWorldState(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[team]); + if (team == BG_TEAM_HORDE) + UpdateWorldState(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[team]); + // update achievement flags + // we increased m_TeamScores[team] so we just need to check if it is 500 more than other teams resources + uint8 otherTeam = (team + 1) % BG_TEAMS_COUNT; + if (m_TeamScores[team] > m_TeamScores[otherTeam] + 500) + m_TeamScores500Disadvantage[otherTeam] = true; + } + } + + // Test win condition + if (m_TeamScores[BG_TEAM_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE) + EndBattleGround(ALLIANCE); + if (m_TeamScores[BG_TEAM_HORDE] >= BG_AB_MAX_TEAM_SCORE) + EndBattleGround(HORDE); + } +} + +void BattleGroundAB::StartingEventCloseDoors() +{ + // despawn banners, auras and buffs + for (int obj = BG_AB_OBJECT_BANNER_NEUTRAL; obj < BG_AB_DYNAMIC_NODES_COUNT * 8; ++obj) + SpawnBGObject(obj, RESPAWN_ONE_DAY); + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT * 3; ++i) + SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + i, RESPAWN_ONE_DAY); + + // Starting doors + DoorClose(BG_AB_OBJECT_GATE_A); + DoorClose(BG_AB_OBJECT_GATE_H); + SpawnBGObject(BG_AB_OBJECT_GATE_A, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_AB_OBJECT_GATE_H, RESPAWN_IMMEDIATELY); + + // Starting base spirit guides + _NodeOccupied(BG_AB_SPIRIT_ALIANCE,ALLIANCE); + _NodeOccupied(BG_AB_SPIRIT_HORDE,HORDE); +} + +void BattleGroundAB::StartingEventOpenDoors() +{ + // spawn neutral banners + for (int banner = BG_AB_OBJECT_BANNER_NEUTRAL, i = 0; i < 5; banner += 8, ++i) + SpawnBGObject(banner, RESPAWN_IMMEDIATELY); + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + //randomly select buff to spawn + uint8 buff = urand(0, 2); + SpawnBGObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + buff + i * 3, RESPAWN_IMMEDIATELY); + } + DoorOpen(BG_AB_OBJECT_GATE_A); + DoorOpen(BG_AB_OBJECT_GATE_H); +} + +void BattleGroundAB::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in the constructor + BattleGroundABScore* sc = new BattleGroundABScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundAB::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) +{ + +} + +void BattleGroundAB::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + switch(Trigger) + { + case 3948: // Arathi Basin Alliance Exit. + if (Source->GetTeam() != ALLIANCE) + Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal"); + else + Source->LeaveBattleground(); + break; + case 3949: // Arathi Basin Horde Exit. + if (Source->GetTeam() != HORDE) + Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal"); + else + Source->LeaveBattleground(); + break; + case 3866: // Stables + case 3869: // Gold Mine + case 3867: // Farm + case 3868: // Lumber Mill + case 3870: // Black Smith + case 4020: // Unk1 + case 4021: // Unk2 + //break; + default: + //sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + //Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } +} + +/* type: 0-neutral, 1-contested, 3-occupied + teamIndex: 0-ally, 1-horde */ +void BattleGroundAB::_CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay) +{ + // Just put it into the queue + if (delay) + { + m_BannerTimers[node].timer = 2000; + m_BannerTimers[node].type = type; + m_BannerTimers[node].teamIndex = teamIndex; + return; + } + + uint8 obj = node*8 + type + teamIndex; + + SpawnBGObject(obj, RESPAWN_IMMEDIATELY); + + // handle aura with banner + if (!type) + return; + obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); + SpawnBGObject(obj, RESPAWN_IMMEDIATELY); +} + +void BattleGroundAB::_DelBanner(uint8 node, uint8 type, uint8 teamIndex) +{ + uint8 obj = node*8 + type + teamIndex; + SpawnBGObject(obj, RESPAWN_ONE_DAY); + + // handle aura with banner + if (!type) + return; + obj = node * 8 + ((type == BG_AB_NODE_TYPE_OCCUPIED) ? (5 + teamIndex) : 7); + SpawnBGObject(obj, RESPAWN_ONE_DAY); +} + +int32 BattleGroundAB::_GetNodeNameId(uint8 node) +{ + switch (node) + { + case BG_AB_NODE_STABLES: return LANG_BG_AB_NODE_STABLES; + case BG_AB_NODE_BLACKSMITH: return LANG_BG_AB_NODE_BLACKSMITH; + case BG_AB_NODE_FARM: return LANG_BG_AB_NODE_FARM; + case BG_AB_NODE_LUMBER_MILL:return LANG_BG_AB_NODE_LUMBER_MILL; + case BG_AB_NODE_GOLD_MINE: return LANG_BG_AB_NODE_GOLD_MINE; + default: + ASSERT(0); + } + return 0; +} + +void BattleGroundAB::FillInitialWorldStates(WorldPacket& data) +{ + const uint8 plusArray[] = {0, 2, 3, 0, 1}; + + // Node icons + for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + data << uint32(BG_AB_OP_NODEICONS[node]) << uint32((m_Nodes[node] == 0)?1:0); + + // Node occupied states + for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + for (uint8 i = 1; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + data << uint32(BG_AB_OP_NODESTATES[node] + plusArray[i]) << uint32((m_Nodes[node] == i)?1:0); + + // How many bases each team owns + uint8 ally = 0, horde = 0; + for (uint8 node = 0; node < BG_AB_DYNAMIC_NODES_COUNT; ++node) + if (m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) + ++ally; + else if (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) + ++horde; + + data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(ally); + data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(horde); + + // Team scores + data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE); + data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE); + data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[BG_TEAM_ALLIANCE]); + data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[BG_TEAM_HORDE]); + + // other unknown + data << uint32(0x745) << uint32(0x2); // 37 1861 unk +} + +void BattleGroundAB::_SendNodeUpdate(uint8 node) +{ + // Send node owner state update to refresh map icons on client + const uint8 plusArray[] = {0, 2, 3, 0, 1}; + + if (m_prevNodes[node]) + UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_prevNodes[node]], 0); + else + UpdateWorldState(BG_AB_OP_NODEICONS[node], 0); + + UpdateWorldState(BG_AB_OP_NODESTATES[node] + plusArray[m_Nodes[node]], 1); + + // How many bases each team owns + uint8 ally = 0, horde = 0; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + if (m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) + ++ally; + else if (m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) + ++horde; + + UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_ALLY, ally); + UpdateWorldState(BG_AB_OP_OCCUPIED_BASES_HORDE, horde); +} + +void BattleGroundAB::_NodeOccupied(uint8 node,Team team) +{ + if (!AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team)) + sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team); + + uint8 capturedNodes = 0; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + if (m_Nodes[node] == GetTeamIndexByTeamId(team) + BG_AB_NODE_TYPE_OCCUPIED && !m_NodeTimers[i]) + ++capturedNodes; + } + if (capturedNodes >= 5) + CastSpellOnTeam(SPELL_AB_QUEST_REWARD_5_BASES, team); + if (capturedNodes >= 4) + CastSpellOnTeam(SPELL_AB_QUEST_REWARD_4_BASES, team); + + if(node >= BG_AB_DYNAMIC_NODES_COUNT)//only dynamic nodes, no start points + return; + Creature* trigger = GetBGCreature(node+7);//0-6 spirit guides + if (!trigger) + trigger = AddCreature(WORLD_TRIGGER,node+7,team,BG_AB_NodePositions[node][0],BG_AB_NodePositions[node][1],BG_AB_NodePositions[node][2],BG_AB_NodePositions[node][3]); + + //add bonus honor aura trigger creature when node is accupied + //cast bonus aura (+50% honor in 25yards) + //aura should only apply to players who have accupied the node, set correct faction for trigger + if (trigger) + { + trigger->setFaction(team == ALLIANCE ? 84 : 83); + trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); + } +} + +void BattleGroundAB::_NodeDeOccupied(uint8 node) +{ + if (node >= BG_AB_DYNAMIC_NODES_COUNT) + return; + + //remove bonus honor aura trigger creature when node is lost + if(node < BG_AB_DYNAMIC_NODES_COUNT)//only dynamic nodes, no start points + DelCreature(node+7);//NULL checks are in DelCreature! 0-6 spirit guides + + // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard + std::vector ghost_list = m_ReviveQueue[m_BgCreatures[node]]; + if (!ghost_list.empty()) + { + WorldSafeLocsEntry const *ClosestGrave = NULL; + for (std::vector::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) + { + Player* plr = objmgr.GetPlayer(*itr); + if (!plr) + continue; + + if (!ClosestGrave) // cache + ClosestGrave = GetClosestGraveYard(plr); + + if (ClosestGrave) + plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); + } + } + + if (m_BgCreatures[node]) + DelCreature(node); + + // buff object isn't despawned +} + +/* Invoked if a player used a banner as a gameobject */ +void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*target_obj*/) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + uint8 node = BG_AB_NODE_STABLES; + GameObject* obj=GetBgMap()->GetGameObject(m_BgObjects[node*8+7]); + while ((node < BG_AB_DYNAMIC_NODES_COUNT) && ((!obj) || (!source->IsWithinDistInMap(obj,10)))) + { + ++node; + obj=GetBgMap()->GetGameObject(m_BgObjects[node*8+BG_AB_OBJECT_AURA_CONTESTED]); + } + + if (node == BG_AB_DYNAMIC_NODES_COUNT) + { + // this means our player isn't close to any of banners - maybe cheater ?? + return; + } + + BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(source->GetTeam()); + + // Check if player really could use this banner, not cheated + if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2)) + return; + + source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + uint32 sound = 0; + // If node is neutral, change to contested + if (m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL) + { + UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] = teamIndex + 1; + // burn current neutral banner + _DelBanner(node, BG_AB_NODE_TYPE_NEUTRAL, 0); + // create new contested banner + _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); + _SendNodeUpdate(node); + m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; + + // FIXME: team and node names not localized + if (teamIndex == 0) + SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node), LANG_BG_AB_ALLY); + else + SendMessage2ToAll(LANG_BG_AB_NODE_CLAIMED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node), LANG_BG_AB_HORDE); + + sound = BG_AB_SOUND_NODE_CLAIMED; + } + // If node is contested + else if ((m_Nodes[node] == BG_AB_NODE_STATUS_ALLY_CONTESTED) || (m_Nodes[node] == BG_AB_NODE_STATUS_HORDE_CONTESTED)) + { + // If last state is NOT occupied, change node to enemy-contested + if (m_prevNodes[node] < BG_AB_NODE_TYPE_OCCUPIED) + { + UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED; + // burn current contested banner + _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); + // create new contested banner + _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); + _SendNodeUpdate(node); + m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; + + // FIXME: node names not localized + if (teamIndex == BG_TEAM_ALLIANCE) + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); + else + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); + } + // If contested, change back to occupied + else + { + UpdatePlayerScore(source, SCORE_BASES_DEFENDED, 1); + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_OCCUPIED; + // burn current contested banner + _DelBanner(node, BG_AB_NODE_TYPE_CONTESTED, !teamIndex); + // create new occupied banner + _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); + _SendNodeUpdate(node); + m_NodeTimers[node] = 0; + _NodeOccupied(node,(teamIndex == BG_TEAM_ALLIANCE) ? ALLIANCE:HORDE); + + // FIXME: node names not localized + if (teamIndex == BG_TEAM_ALLIANCE) + SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); + else + SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); + } + sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; + } + // If node is occupied, change to enemy-contested + else + { + UpdatePlayerScore(source, SCORE_BASES_ASSAULTED, 1); + m_prevNodes[node] = m_Nodes[node]; + m_Nodes[node] = teamIndex + BG_AB_NODE_TYPE_CONTESTED; + // burn current occupied banner + _DelBanner(node, BG_AB_NODE_TYPE_OCCUPIED, !teamIndex); + // create new contested banner + _CreateBanner(node, BG_AB_NODE_TYPE_CONTESTED, teamIndex, true); + _SendNodeUpdate(node); + _NodeDeOccupied(node); + m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; + + // FIXME: node names not localized + if (teamIndex == BG_TEAM_ALLIANCE) + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); + else + SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); + + sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; + } + + // If node is occupied again, send "X has taken the Y" msg. + if (m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED) + { + // FIXME: team and node names not localized + if (teamIndex == BG_TEAM_ALLIANCE) + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_AB_ALLY, _GetNodeNameId(node)); + else + SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, LANG_BG_AB_HORDE, _GetNodeNameId(node)); + } + PlaySoundToAll(sound); +} + +bool BattleGroundAB::SetupBattleGround() +{ + for (int i = 0 ; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + if (!AddObject(BG_AB_OBJECT_BANNER_NEUTRAL + 8*i,BG_AB_OBJECTID_NODE_BANNER_0 + i,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_BANNER_CONT_A + 8*i,BG_AB_OBJECTID_BANNER_CONT_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_BANNER_CONT_H + 8*i,BG_AB_OBJECTID_BANNER_CONT_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_BANNER_ALLY + 8*i,BG_AB_OBJECTID_BANNER_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_BANNER_HORDE + 8*i,BG_AB_OBJECTID_BANNER_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_AURA_ALLY + 8*i,BG_AB_OBJECTID_AURA_A,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_AURA_HORDE + 8*i,BG_AB_OBJECTID_AURA_H,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_AURA_CONTESTED + 8*i,BG_AB_OBJECTID_AURA_C,BG_AB_NodePositions[i][0],BG_AB_NodePositions[i][1],BG_AB_NodePositions[i][2],BG_AB_NodePositions[i][3], 0, 0, sin(BG_AB_NodePositions[i][3]/2), cos(BG_AB_NodePositions[i][3]/2),RESPAWN_ONE_DAY) +) + { + sLog.outErrorDb("BatteGroundAB: Failed to spawn some object BattleGround not created!"); + return false; + } + } + if (!AddObject(BG_AB_OBJECT_GATE_A,BG_AB_OBJECTID_GATE_A,BG_AB_DoorPositions[0][0],BG_AB_DoorPositions[0][1],BG_AB_DoorPositions[0][2],BG_AB_DoorPositions[0][3],BG_AB_DoorPositions[0][4],BG_AB_DoorPositions[0][5],BG_AB_DoorPositions[0][6],BG_AB_DoorPositions[0][7],RESPAWN_IMMEDIATELY) + || !AddObject(BG_AB_OBJECT_GATE_H,BG_AB_OBJECTID_GATE_H,BG_AB_DoorPositions[1][0],BG_AB_DoorPositions[1][1],BG_AB_DoorPositions[1][2],BG_AB_DoorPositions[1][3],BG_AB_DoorPositions[1][4],BG_AB_DoorPositions[1][5],BG_AB_DoorPositions[1][6],BG_AB_DoorPositions[1][7],RESPAWN_IMMEDIATELY) +) + { + sLog.outErrorDb("BatteGroundAB: Failed to spawn door object BattleGround not created!"); + return false; + } + //buffs + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + if (!AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i, Buff_Entries[0], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 1, Buff_Entries[1], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) + || !AddObject(BG_AB_OBJECT_SPEEDBUFF_STABLES + 3 * i + 2, Buff_Entries[2], BG_AB_BuffPositions[i][0], BG_AB_BuffPositions[i][1], BG_AB_BuffPositions[i][2], BG_AB_BuffPositions[i][3], 0, 0, sin(BG_AB_BuffPositions[i][3]/2), cos(BG_AB_BuffPositions[i][3]/2), RESPAWN_ONE_DAY) +) + sLog.outErrorDb("BatteGroundAB: Failed to spawn buff object!"); + } + + return true; +} + +void BattleGroundAB::Reset() +{ + //call parent's class reset + BattleGround::Reset(); + + m_TeamScores[BG_TEAM_ALLIANCE] = 0; + m_TeamScores[BG_TEAM_HORDE] = 0; + m_lastTick[BG_TEAM_ALLIANCE] = 0; + m_lastTick[BG_TEAM_HORDE] = 0; + m_HonorScoreTics[BG_TEAM_ALLIANCE] = 0; + m_HonorScoreTics[BG_TEAM_HORDE] = 0; + m_ReputationScoreTics[BG_TEAM_ALLIANCE] = 0; + m_ReputationScoreTics[BG_TEAM_HORDE] = 0; + m_IsInformedNearVictory = false; + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); + m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; + m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; + m_TeamScores500Disadvantage[BG_TEAM_ALLIANCE] = false; + m_TeamScores500Disadvantage[BG_TEAM_HORDE] = false; + + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + { + m_Nodes[i] = 0; + m_prevNodes[i] = 0; + m_NodeTimers[i] = 0; + m_BannerTimers[i].timer = 0; + } + + for (uint8 i = 0; i < BG_AB_ALL_NODES_COUNT + 5; ++i)//+5 for aura triggers + if (m_BgCreatures[i]) + DelCreature(i); +} + +void BattleGroundAB::EndBattleGround(uint32 winner) +{ + //win reward + if (winner == ALLIANCE) + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + if (winner == HORDE) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + //complete map_end rewards (even if no team wins) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + + BattleGround::EndBattleGround(winner); +} + +WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player) +{ + BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(player->GetTeam()); + + // Is there any occupied node for this team? + std::vector nodes; + for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + if (m_Nodes[i] == teamIndex + 3) + nodes.push_back(i); + + WorldSafeLocsEntry const* good_entry = NULL; + // If so, select the closest node to place ghost on + if (!nodes.empty()) + { + float plr_x = player->GetPositionX(); + float plr_y = player->GetPositionY(); + + float mindist = 999999.0f; + for (uint8 i = 0; i < nodes.size(); ++i) + { + WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry(BG_AB_GraveyardIds[nodes[i]]); + if (!entry) + continue; + float dist = (entry->x - plr_x)*(entry->x - plr_x)+(entry->y - plr_y)*(entry->y - plr_y); + if (mindist > dist) + { + mindist = dist; + good_entry = entry; + } + } + nodes.clear(); + } + // If not, place ghost on starting location + if (!good_entry) + good_entry = sWorldSafeLocsStore.LookupEntry(BG_AB_GraveyardIds[teamIndex+5]); + + return good_entry; +} + +void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor) +{ + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); + if (itr == m_PlayerScores.end()) // player not found... + return; + + switch(type) + { + case SCORE_BASES_ASSAULTED: + ((BattleGroundABScore*)itr->second)->BasesAssaulted += value; + break; + case SCORE_BASES_DEFENDED: + ((BattleGroundABScore*)itr->second)->BasesDefended += value; + break; + default: + BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); + break; + } +} + +bool BattleGroundAB::IsAllNodesConrolledByTeam(uint32 team) const +{ + uint32 count = 0; + for (int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + if ((team == ALLIANCE && m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED) || + (team == HORDE && m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED)) + ++count; + + return count == BG_AB_DYNAMIC_NODES_COUNT; +} diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundAB.h b/src/server/game/BattleGrounds/Zones/BattleGroundAB.h new file mode 100644 index 00000000000..3072f8beafd --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundAB.h @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDAB_H +#define __BATTLEGROUNDAB_H + +class BattleGround; + +enum BG_AB_WorldStates +{ + BG_AB_OP_OCCUPIED_BASES_HORDE = 1778, + BG_AB_OP_OCCUPIED_BASES_ALLY = 1779, + BG_AB_OP_RESOURCES_ALLY = 1776, + BG_AB_OP_RESOURCES_HORDE = 1777, + BG_AB_OP_RESOURCES_MAX = 1780, + BG_AB_OP_RESOURCES_WARNING = 1955 +/* + BG_AB_OP_STABLE_ICON = 1842, //Stable map icon (NONE) + BG_AB_OP_STABLE_STATE_ALIENCE = 1767, //Stable map state (ALIENCE) + BG_AB_OP_STABLE_STATE_HORDE = 1768, //Stable map state (HORDE) + BG_AB_OP_STABLE_STATE_CON_ALI = 1769, //Stable map state (CON ALIENCE) + BG_AB_OP_STABLE_STATE_CON_HOR = 1770, //Stable map state (CON HORDE) + BG_AB_OP_FARM_ICON = 1845, //Farm map icon (NONE) + BG_AB_OP_FARM_STATE_ALIENCE = 1772, //Farm state (ALIENCE) + BG_AB_OP_FARM_STATE_HORDE = 1773, //Farm state (HORDE) + BG_AB_OP_FARM_STATE_CON_ALI = 1774, //Farm state (CON ALIENCE) + BG_AB_OP_FARM_STATE_CON_HOR = 1775, //Farm state (CON HORDE) + + BG_AB_OP_BLACKSMITH_ICON = 1846, //Blacksmith map icon (NONE) + BG_AB_OP_BLACKSMITH_STATE_ALIENCE = 1782, //Blacksmith map state (ALIENCE) + BG_AB_OP_BLACKSMITH_STATE_HORDE = 1783, //Blacksmith map state (HORDE) + BG_AB_OP_BLACKSMITH_STATE_CON_ALI = 1784, //Blacksmith map state (CON ALIENCE) + BG_AB_OP_BLACKSMITH_STATE_CON_HOR = 1785, //Blacksmith map state (CON HORDE) + BG_AB_OP_LUMBERMILL_ICON = 1844, //Lumber Mill map icon (NONE) + BG_AB_OP_LUMBERMILL_STATE_ALIENCE = 1792, //Lumber Mill map state (ALIENCE) + BG_AB_OP_LUMBERMILL_STATE_HORDE = 1793, //Lumber Mill map state (HORDE) + BG_AB_OP_LUMBERMILL_STATE_CON_ALI = 1794, //Lumber Mill map state (CON ALIENCE) + BG_AB_OP_LUMBERMILL_STATE_CON_HOR = 1795, //Lumber Mill map state (CON HORDE) + BG_AB_OP_GOLDMINE_ICON = 1843, //Gold Mine map icon (NONE) + BG_AB_OP_GOLDMINE_STATE_ALIENCE = 1787, //Gold Mine map state (ALIENCE) + BG_AB_OP_GOLDMINE_STATE_HORDE = 1788, //Gold Mine map state (HORDE) + BG_AB_OP_GOLDMINE_STATE_CON_ALI = 1789, //Gold Mine map state (CON ALIENCE + BG_AB_OP_GOLDMINE_STATE_CON_HOR = 1790, //Gold Mine map state (CON HORDE) +*/ +}; + +const uint32 BG_AB_OP_NODESTATES[5] = {1767, 1782, 1772, 1792, 1787}; + +const uint32 BG_AB_OP_NODEICONS[5] = {1842, 1846, 1845, 1844, 1843}; + +/* Note: code uses that these IDs follow each other */ +enum BG_AB_NodeObjectId +{ + BG_AB_OBJECTID_NODE_BANNER_0 = 180087, // Stables banner + BG_AB_OBJECTID_NODE_BANNER_1 = 180088, // Blacksmith banner + BG_AB_OBJECTID_NODE_BANNER_2 = 180089, // Farm banner + BG_AB_OBJECTID_NODE_BANNER_3 = 180090, // Lumber mill banner + BG_AB_OBJECTID_NODE_BANNER_4 = 180091 // Gold mine banner +}; + +enum BG_AB_ObjectType +{ + // for all 5 node points 8*5=40 objects + BG_AB_OBJECT_BANNER_NEUTRAL = 0, + BG_AB_OBJECT_BANNER_CONT_A = 1, + BG_AB_OBJECT_BANNER_CONT_H = 2, + BG_AB_OBJECT_BANNER_ALLY = 3, + BG_AB_OBJECT_BANNER_HORDE = 4, + BG_AB_OBJECT_AURA_ALLY = 5, + BG_AB_OBJECT_AURA_HORDE = 6, + BG_AB_OBJECT_AURA_CONTESTED = 7, + //gates + BG_AB_OBJECT_GATE_A = 40, + BG_AB_OBJECT_GATE_H = 41, + //buffs + BG_AB_OBJECT_SPEEDBUFF_STABLES = 42, + BG_AB_OBJECT_REGENBUFF_STABLES = 43, + BG_AB_OBJECT_BERSERKBUFF_STABLES = 44, + BG_AB_OBJECT_SPEEDBUFF_BLACKSMITH = 45, + BG_AB_OBJECT_REGENBUFF_BLACKSMITH = 46, + BG_AB_OBJECT_BERSERKBUFF_BLACKSMITH = 47, + BG_AB_OBJECT_SPEEDBUFF_FARM = 48, + BG_AB_OBJECT_REGENBUFF_FARM = 49, + BG_AB_OBJECT_BERSERKBUFF_FARM = 50, + BG_AB_OBJECT_SPEEDBUFF_LUMBER_MILL = 51, + BG_AB_OBJECT_REGENBUFF_LUMBER_MILL = 52, + BG_AB_OBJECT_BERSERKBUFF_LUMBER_MILL = 53, + BG_AB_OBJECT_SPEEDBUFF_GOLD_MINE = 54, + BG_AB_OBJECT_REGENBUFF_GOLD_MINE = 55, + BG_AB_OBJECT_BERSERKBUFF_GOLD_MINE = 56, + BG_AB_OBJECT_MAX = 57, +}; + +/* Object id templates from DB */ +enum BG_AB_ObjectTypes +{ + BG_AB_OBJECTID_BANNER_A = 180058, + BG_AB_OBJECTID_BANNER_CONT_A = 180059, + BG_AB_OBJECTID_BANNER_H = 180060, + BG_AB_OBJECTID_BANNER_CONT_H = 180061, + + BG_AB_OBJECTID_AURA_A = 180100, + BG_AB_OBJECTID_AURA_H = 180101, + BG_AB_OBJECTID_AURA_C = 180102, + + BG_AB_OBJECTID_GATE_A = 180255, + BG_AB_OBJECTID_GATE_H = 180256 +}; + +enum BG_AB_Timers +{ + BG_AB_FLAG_CAPTURING_TIME = 60000, +}; + +enum BG_AB_Score +{ + BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400, + BG_AB_MAX_TEAM_SCORE = 1600 +}; + +/* do NOT change the order, else wrong behaviour */ +enum BG_AB_BattleGroundNodes +{ + BG_AB_NODE_STABLES = 0, + BG_AB_NODE_BLACKSMITH = 1, + BG_AB_NODE_FARM = 2, + BG_AB_NODE_LUMBER_MILL = 3, + BG_AB_NODE_GOLD_MINE = 4, + + BG_AB_DYNAMIC_NODES_COUNT = 5, // dynamic nodes that can be captured + + BG_AB_SPIRIT_ALIANCE = 5, + BG_AB_SPIRIT_HORDE = 6, + + BG_AB_ALL_NODES_COUNT = 7, // all nodes (dynamic and static) +}; + +enum BG_AB_NodeStatus +{ + BG_AB_NODE_TYPE_NEUTRAL = 0, + BG_AB_NODE_TYPE_CONTESTED = 1, + BG_AB_NODE_STATUS_ALLY_CONTESTED = 1, + BG_AB_NODE_STATUS_HORDE_CONTESTED = 2, + BG_AB_NODE_TYPE_OCCUPIED = 3, + BG_AB_NODE_STATUS_ALLY_OCCUPIED = 3, + BG_AB_NODE_STATUS_HORDE_OCCUPIED = 4 +}; + +enum BG_AB_Sounds +{ + BG_AB_SOUND_NODE_CLAIMED = 8192, + BG_AB_SOUND_NODE_CAPTURED_ALLIANCE = 8173, + BG_AB_SOUND_NODE_CAPTURED_HORDE = 8213, + BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE = 8212, + BG_AB_SOUND_NODE_ASSAULTED_HORDE = 8174, + BG_AB_SOUND_NEAR_VICTORY = 8456 +}; + +#define BG_AB_NotABBGWeekendHonorTicks 330 +#define BG_AB_ABBGWeekendHonorTicks 200 +#define BG_AB_NotABBGWeekendReputationTicks 200 +#define BG_AB_ABBGWeekendReputationTicks 150 + +// x, y, z, o +const float BG_AB_NodePositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { + {1166.785f, 1200.132f, -56.70859f, 0.9075713f}, // stables + {977.0156f, 1046.616f, -44.80923f, -2.600541f}, // blacksmith + {806.1821f, 874.2723f, -55.99371f, -2.303835f}, // farm + {856.1419f, 1148.902f, 11.18469f, -2.303835f}, // lumber mill + {1146.923f, 848.1782f, -110.917f, -0.7330382f} // gold mine +}; + +// x, y, z, o, rot0, rot1, rot2, rot3 +const float BG_AB_DoorPositions[2][8] = { + {1284.597f, 1281.167f, -15.97792f, 0.7068594f, 0.012957f, -0.060288f, 0.344959f, 0.93659f}, + {708.0903f, 708.4479f, -17.8342f, -2.391099f, 0.050291f, 0.015127f, 0.929217f, -0.365784f} +}; + +// Tick intervals and given points: case 0,1,2,3,4,5 captured nodes +const uint32 BG_AB_TickIntervals[6] = {0, 12000, 9000, 6000, 3000, 1000}; +const uint32 BG_AB_TickPoints[6] = {0, 10, 10, 10, 10, 30}; + +// WorldSafeLocs ids for 5 nodes, and for ally, and horde starting location +const uint32 BG_AB_GraveyardIds[BG_AB_ALL_NODES_COUNT] = {895, 894, 893, 897, 896, 898, 899}; + +// x, y, z, o +const float BG_AB_BuffPositions[BG_AB_DYNAMIC_NODES_COUNT][4] = { + {1185.71f, 1185.24f, -56.36f, 2.56f}, // stables + {990.75f, 1008.18f, -42.60f, 2.43f}, // blacksmith + {817.66f, 843.34f, -56.54f, 3.01f}, // farm + {807.46f, 1189.16f, 11.92f, 5.44f}, // lumber mill + {1146.62f, 816.94f, -98.49f, 6.14f} // gold mine +}; + +// x, y, z, o +const float BG_AB_SpiritGuidePos[BG_AB_ALL_NODES_COUNT][4] = { + {1200.03f, 1171.09f, -56.47f, 5.15f}, // stables + {1017.43f, 960.61f, -42.95f, 4.88f}, // blacksmith + {833.00f, 793.00f, -57.25f, 5.27f}, // farm + {775.17f, 1206.40f, 15.79f, 1.90f}, // lumber mill + {1207.48f, 787.00f, -83.36f, 5.51f}, // gold mine + {1354.05f, 1275.48f, -11.30f, 4.77f}, // alliance starting base + {714.61f, 646.15f, -10.87f, 4.34f} // horde starting base +}; + +struct BG_AB_BannerTimer +{ + uint32 timer; + uint8 type; + uint8 teamIndex; +}; + +class BattleGroundABScore : public BattleGroundScore +{ + public: + BattleGroundABScore(): BasesAssaulted(0), BasesDefended(0) {}; + virtual ~BattleGroundABScore() {}; + uint32 BasesAssaulted; + uint32 BasesDefended; +}; + +class BattleGroundAB : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundAB(); + ~BattleGroundAB(); + + void Update(uint32 diff); + void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + void RemovePlayer(Player *plr,uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + virtual bool SetupBattleGround(); + virtual void Reset(); + void EndBattleGround(uint32 winner); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); + + /* Scorekeeping */ + virtual void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); + + virtual void FillInitialWorldStates(WorldPacket& data); + + /* Nodes occupying */ + virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj); + + /* achievement req. */ + bool IsAllNodesConrolledByTeam(uint32 team) const; // overwrited + bool IsTeamScores500Disadvantage(uint32 team) const { return m_TeamScores500Disadvantage[GetTeamIndexByTeamId(team)]; } + private: + /* Gameobject spawning/despawning */ + void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay); + void _DelBanner(uint8 node, uint8 type, uint8 teamIndex); + void _SendNodeUpdate(uint8 node); + + /* Creature spawning/despawning */ + // TODO: working, scripted peons spawning + void _NodeOccupied(uint8 node,Team team); + void _NodeDeOccupied(uint8 node); + + int32 _GetNodeNameId(uint8 node); + + /* Nodes info: + 0: neutral + 1: ally contested + 2: horde contested + 3: ally occupied + 4: horde occupied */ + uint8 m_Nodes[BG_AB_DYNAMIC_NODES_COUNT]; + uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; + BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; + uint32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; + uint32 m_lastTick[BG_TEAMS_COUNT]; + uint32 m_HonorScoreTics[BG_TEAMS_COUNT]; + uint32 m_ReputationScoreTics[BG_TEAMS_COUNT]; + bool m_IsInformedNearVictory; + uint32 m_HonorTics; + uint32 m_ReputationTics; + // need for achievements + bool m_TeamScores500Disadvantage[BG_TEAMS_COUNT]; +}; +#endif + diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundAV.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundAV.cpp new file mode 100644 index 00000000000..7f5482cbf16 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundAV.cpp @@ -0,0 +1,1490 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectMgr.h" +#include "WorldPacket.h" + +#include "BattleGround.h" +#include "BattleGroundAV.h" +#include "Formulas.h" +#include "GameObject.h" +#include "Language.h" +#include "Player.h" +#include "SpellAuras.h" + +BattleGroundAV::BattleGroundAV() +{ + m_BgObjects.resize(BG_AV_OBJECT_MAX); + m_BgCreatures.resize(AV_CPLACE_MAX+AV_STATICCPLACE_MAX); + + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_AV_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_AV_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_AV_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_AV_HAS_BEGUN; +} + +BattleGroundAV::~BattleGroundAV() +{ +} + +const uint16 BattleGroundAV::GetBonusHonor(uint8 kills) //TODO: move this function to Battleground.cpp (needs to find a way to get m_MaxLevel) +{ + return Trinity::Honor::hk_honor_at_level(m_MaxLevel, kills); +} + +void BattleGroundAV::HandleKillPlayer(Player *player, Player *killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + BattleGround::HandleKillPlayer(player, killer); + UpdateScore(player->GetTeam(),-1); +} + +void BattleGroundAV::HandleKillUnit(Creature *unit, Player *killer) +{ + sLog.outDebug("bg_av HandleKillUnit %i",unit->GetEntry()); + if (GetStatus() != STATUS_IN_PROGRESS) + return; + uint32 entry = unit->GetEntry(); + /* + uint32 triggerSpawnID = 0; + if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0]) + triggerSpawnID = AV_CPLACE_TRIGGER16; + else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_BOSS][0]) + triggerSpawnID = AV_CPLACE_TRIGGER17; + else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN][0]) + triggerSpawnID = AV_CPLACE_TRIGGER18; + else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_BOSS][0]) + triggerSpawnID = AV_CPLACE_TRIGGER19; + */ + if (entry == BG_AV_CreatureInfo[AV_NPC_A_BOSS][0]) + { + CastSpellOnTeam(23658,HORDE); //this is a spell which finishes a quest where a player has to kill the boss + RewardReputationToTeam(729,BG_AV_REP_BOSS,HORDE); + RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_BOSS),HORDE); + EndBattleGround(HORDE); + DelCreature(AV_CPLACE_TRIGGER17); + } + else if (entry == BG_AV_CreatureInfo[AV_NPC_H_BOSS][0]) + { + CastSpellOnTeam(23658,ALLIANCE); //this is a spell which finishes a quest where a player has to kill the boss + RewardReputationToTeam(730,BG_AV_REP_BOSS,ALLIANCE); + RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_BOSS),ALLIANCE); + EndBattleGround(ALLIANCE); + DelCreature(AV_CPLACE_TRIGGER19); + } + else if (entry == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0]) + { + if (!m_CaptainAlive[0]) + { + sLog.outError("Killed a Captain twice, please report this bug, if you haven't done \".respawn\""); + return; + } + m_CaptainAlive[0]=false; + RewardReputationToTeam(729,BG_AV_REP_CAPTAIN,HORDE); + RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_CAPTAIN),HORDE); + UpdateScore(ALLIANCE,(-1)*BG_AV_RES_CAPTAIN); + //spawn destroyed aura + for (uint8 i=0; i <= 9; i++) + SpawnBGObject(BG_AV_OBJECT_BURN_BUILDING_ALLIANCE+i,RESPAWN_IMMEDIATELY); + Creature* creature = GetBGCreature(AV_CPLACE_HERALD); + if (creature) + YellToAll(creature,GetTrinityString(LANG_BG_AV_A_CAPTAIN_DEAD),LANG_UNIVERSAL); + DelCreature(AV_CPLACE_TRIGGER16); + } + else if (entry == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN][0]) + { + if (!m_CaptainAlive[1]) + { + sLog.outError("Killed a Captain twice, please report this bug, if you haven't done \".respawn\""); + return; + } + m_CaptainAlive[1]=false; + RewardReputationToTeam(730,BG_AV_REP_CAPTAIN,ALLIANCE); + RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_CAPTAIN),ALLIANCE); + UpdateScore(HORDE,(-1)*BG_AV_RES_CAPTAIN); + //spawn destroyed aura + for (uint8 i=0; i <= 9; i++) + SpawnBGObject(BG_AV_OBJECT_BURN_BUILDING_HORDE+i,RESPAWN_IMMEDIATELY); + Creature* creature = GetBGCreature(AV_CPLACE_HERALD); + if (creature) + YellToAll(creature,GetTrinityString(LANG_BG_AV_H_CAPTAIN_DEAD),LANG_UNIVERSAL); + DelCreature(AV_CPLACE_TRIGGER18); + } + else if (entry == BG_AV_CreatureInfo[AV_NPC_N_MINE_N_4][0] || entry == BG_AV_CreatureInfo[AV_NPC_N_MINE_A_4][0] || entry == BG_AV_CreatureInfo[AV_NPC_N_MINE_H_4][0]) + ChangeMineOwner(AV_NORTH_MINE,killer->GetTeam()); + else if (entry == BG_AV_CreatureInfo[AV_NPC_S_MINE_N_4][0] || entry == BG_AV_CreatureInfo[AV_NPC_S_MINE_A_4][0] || entry == BG_AV_CreatureInfo[AV_NPC_S_MINE_H_4][0]) + ChangeMineOwner(AV_SOUTH_MINE,killer->GetTeam()); +} + +void BattleGroundAV::HandleQuestComplete(uint32 questid, Player *player) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return;//maybe we should log this, cause this must be a cheater or a big bug + uint8 team = GetTeamIndexByTeamId(player->GetTeam()); + //TODO add reputation, events (including quest not available anymore, next quest availabe, go/npc de/spawning)and maybe honor + sLog.outDebug("BG_AV Quest %i completed",questid); + switch(questid) + { + case AV_QUEST_A_SCRAPS1: + case AV_QUEST_A_SCRAPS2: + case AV_QUEST_H_SCRAPS1: + case AV_QUEST_H_SCRAPS2: + m_Team_QuestStatus[team][0]+=20; + if (m_Team_QuestStatus[team][0] == 500 || m_Team_QuestStatus[team][0] == 1000 || m_Team_QuestStatus[team][0] == 1500) //25,50,75 turn ins + { + sLog.outDebug("BG_AV Quest %i completed starting with unit upgrading..",questid); + for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) + if (m_Nodes[i].Owner == player->GetTeam() && m_Nodes[i].State == POINT_CONTROLED) + { + DePopulateNode(i); + PopulateNode(i); + //maybe this is bad, because it will instantly respawn all creatures on every grave.. + } + } + break; + case AV_QUEST_A_COMMANDER1: + case AV_QUEST_H_COMMANDER1: + m_Team_QuestStatus[team][1]++; + RewardReputationToTeam(team,1,player->GetTeam()); + if (m_Team_QuestStatus[team][1] == 30) + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); + break; + case AV_QUEST_A_COMMANDER2: + case AV_QUEST_H_COMMANDER2: + m_Team_QuestStatus[team][2]++; + RewardReputationToTeam(team,1,player->GetTeam()); + if (m_Team_QuestStatus[team][2] == 60) + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); + break; + case AV_QUEST_A_COMMANDER3: + case AV_QUEST_H_COMMANDER3: + m_Team_QuestStatus[team][3]++; + RewardReputationToTeam(team,1,player->GetTeam()); + if (m_Team_QuestStatus[team][1] == 120) + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); + break; + case AV_QUEST_A_BOSS1: + case AV_QUEST_H_BOSS1: + m_Team_QuestStatus[team][4] += 9; //you can turn in 10 or 1 item.. + case AV_QUEST_A_BOSS2: + case AV_QUEST_H_BOSS2: + m_Team_QuestStatus[team][4]++; + if (m_Team_QuestStatus[team][4] >= 200) + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); + break; + case AV_QUEST_A_NEAR_MINE: + case AV_QUEST_H_NEAR_MINE: + m_Team_QuestStatus[team][5]++; + if (m_Team_QuestStatus[team][5] == 28) + { + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); + if (m_Team_QuestStatus[team][6] == 7) + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here - ground assault ready",questid); + } + break; + case AV_QUEST_A_OTHER_MINE: + case AV_QUEST_H_OTHER_MINE: + m_Team_QuestStatus[team][6]++; + if (m_Team_QuestStatus[team][6] == 7) + { + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); + if (m_Team_QuestStatus[team][5] == 20) + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here - ground assault ready",questid); + } + break; + case AV_QUEST_A_RIDER_HIDE: + case AV_QUEST_H_RIDER_HIDE: + m_Team_QuestStatus[team][7]++; + if (m_Team_QuestStatus[team][7] == 25) + { + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); + if (m_Team_QuestStatus[team][8] == 25) + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here - rider assault ready",questid); + } + break; + case AV_QUEST_A_RIDER_TAME: + case AV_QUEST_H_RIDER_TAME: + m_Team_QuestStatus[team][8]++; + if (m_Team_QuestStatus[team][8] == 25) + { + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here",questid); + if (m_Team_QuestStatus[team][7] == 25) + sLog.outDebug("BG_AV Quest %i completed (need to implement some events here - rider assault ready",questid); + } + break; + default: + sLog.outDebug("BG_AV Quest %i completed but is not interesting at all",questid); + return; //was no interesting quest at all + break; + } +} + +void BattleGroundAV::UpdateScore(uint16 team, int16 points) +{ //note: to remove reinforcementpoints points must be negative, for adding reinforcements points must be positive + assert(team == ALLIANCE || team == HORDE); + uint8 teamindex = GetTeamIndexByTeamId(team); //0=ally 1=horde + m_Team_Scores[teamindex] += points; + + UpdateWorldState(((teamindex == BG_TEAM_HORDE)?AV_Horde_Score:AV_Alliance_Score), m_Team_Scores[teamindex]); + if (points < 0) + { + if (m_Team_Scores[teamindex] < 1) + { + m_Team_Scores[teamindex]=0; + EndBattleGround(((teamindex == BG_TEAM_HORDE)?ALLIANCE:HORDE)); + } + else if (!m_IsInformedNearVictory[teamindex] && m_Team_Scores[teamindex] < SEND_MSG_NEAR_LOSE) + { + SendMessageToAll(teamindex == BG_TEAM_HORDE?LANG_BG_AV_H_NEAR_LOSE:LANG_BG_AV_A_NEAR_LOSE, teamindex == BG_TEAM_HORDE ? CHAT_MSG_BG_SYSTEM_HORDE : CHAT_MSG_BG_SYSTEM_ALLIANCE); + PlaySoundToAll(AV_SOUND_NEAR_VICTORY); + m_IsInformedNearVictory[teamindex] = true; + } + } +} + +Creature* BattleGroundAV::AddAVCreature(uint16 cinfoid, uint16 type) +{ + uint8 level; + bool isStatic = false; + Creature* creature = NULL; + assert(type <= AV_CPLACE_MAX + AV_STATICCPLACE_MAX); + if (type >= AV_CPLACE_MAX) //static + { + type -= AV_CPLACE_MAX; + cinfoid=uint16(BG_AV_StaticCreaturePos[type][4]); + creature = AddCreature(BG_AV_StaticCreatureInfo[cinfoid][0],(type+AV_CPLACE_MAX),BG_AV_StaticCreatureInfo[cinfoid][1],BG_AV_StaticCreaturePos[type][0],BG_AV_StaticCreaturePos[type][1],BG_AV_StaticCreaturePos[type][2],BG_AV_StaticCreaturePos[type][3]); + level = (BG_AV_StaticCreatureInfo[cinfoid][2] == BG_AV_StaticCreatureInfo[cinfoid][3]) ? BG_AV_StaticCreatureInfo[cinfoid][2] : urand(BG_AV_StaticCreatureInfo[cinfoid][2],BG_AV_StaticCreatureInfo[cinfoid][3]); + isStatic = true; + } + else + { + creature = AddCreature(BG_AV_CreatureInfo[cinfoid][0],type,BG_AV_CreatureInfo[cinfoid][1],BG_AV_CreaturePos[type][0],BG_AV_CreaturePos[type][1],BG_AV_CreaturePos[type][2],BG_AV_CreaturePos[type][3]); + level = (BG_AV_CreatureInfo[cinfoid][2] == BG_AV_CreatureInfo[cinfoid][3]) ? BG_AV_CreatureInfo[cinfoid][2] : urand(BG_AV_CreatureInfo[cinfoid][2],BG_AV_CreatureInfo[cinfoid][3]); + } + if (!creature) + return NULL; + if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0] || creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN][0]) + creature->SetRespawnDelay(RESPAWN_ONE_DAY); // TODO: look if this can be done by database + also add this for the wingcommanders + + if ((isStatic && cinfoid >= 10 && cinfoid <= 14) || (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3) || + (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3)))) + { + if (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3) + || (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3))) + { + CreatureData &data = objmgr.NewOrExistCreatureData(creature->GetDBTableGUIDLow()); + data.spawndist = 5; + } + //else spawndist will be 15, so creatures move maximum=10 + //creature->SetDefaultMovementType(RANDOM_MOTION_TYPE); + creature->GetMotionMaster()->Initialize(); + creature->setDeathState(JUST_DIED); + creature->Respawn(); + //TODO: find a way to add a motionmaster without killing the creature (i + //just copied this code from a gm-command + } + + if (level != 0) + level += m_MaxLevel - 60; //maybe we can do this more generic for custom level-range.. actually it's blizzlike + creature->SetLevel(level); + + uint32 triggerSpawnID = 0; + uint32 newFaction = 0; + if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN][0]) + { + triggerSpawnID = AV_CPLACE_TRIGGER16; + newFaction = 84; + } + else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_BOSS][0]) + { + triggerSpawnID = AV_CPLACE_TRIGGER17; + newFaction = 84; + } + else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN][0]) + { + triggerSpawnID = AV_CPLACE_TRIGGER18; + newFaction = 83; + } + else if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_BOSS][0]) + { + triggerSpawnID = AV_CPLACE_TRIGGER19; + newFaction = 83; + } + if (triggerSpawnID && newFaction) + { + if (Creature* trigger = AddCreature(WORLD_TRIGGER,triggerSpawnID,BG_AV_CreatureInfo[creature->GetEntry()][1],BG_AV_CreaturePos[triggerSpawnID][0],BG_AV_CreaturePos[triggerSpawnID][1],BG_AV_CreaturePos[triggerSpawnID][2],BG_AV_CreaturePos[triggerSpawnID][3])) + { + trigger->setFaction(newFaction); + trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); + } + } + + return creature; +} + +void BattleGroundAV::Update(uint32 diff) +{ + BattleGround::Update(diff); + + if (GetStatus() == STATUS_IN_PROGRESS) + { + for (uint8 i=0; i <= 1; i++)//0=alliance, 1=horde + { + if (!m_CaptainAlive[i]) + continue; + if (m_CaptainBuffTimer[i] > diff) + m_CaptainBuffTimer[i] -= diff; + else + { + if (i == 0) + { + CastSpellOnTeam(AV_BUFF_A_CAPTAIN,ALLIANCE); + Creature* creature = GetBGCreature(AV_CPLACE_MAX + 61); + if (creature) + YellToAll(creature,LANG_BG_AV_A_CAPTAIN_BUFF,LANG_COMMON); + } + else + { + CastSpellOnTeam(AV_BUFF_H_CAPTAIN,HORDE); + Creature* creature = GetBGCreature(AV_CPLACE_MAX + 59); //TODO: make the captains a dynamic creature + if (creature) + YellToAll(creature,LANG_BG_AV_H_CAPTAIN_BUFF,LANG_ORCISH); + } + m_CaptainBuffTimer[i] = 120000 + urand(0,4)* 60000; //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes TODO get the right times + } + } + //add points from mine owning, and look if he neutral team wanrts to reclaim the mine + m_Mine_Timer -=diff; + for (uint8 mine=0; mine <2; mine++) + { + if (m_Mine_Owner[mine] == ALLIANCE || m_Mine_Owner[mine] == HORDE) + { + if (m_Mine_Timer <= 0) + UpdateScore(m_Mine_Owner[mine],1); + + if (m_Mine_Reclaim_Timer[mine] > diff) + m_Mine_Reclaim_Timer[mine] -= diff; + else{ //we don't need to set this timer to 0 cause this codepart wont get called when this thing is 0 + ChangeMineOwner(mine,AV_NEUTRAL_TEAM); + } + } + } + if (m_Mine_Timer <= 0) + m_Mine_Timer=AV_MINE_TICK_TIMER; //this is at the end, cause we need to update both mines + + //looks for all timers of the nodes and destroy the building (for graveyards the building wont get destroyed, it goes just to the other team + for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i) + if (m_Nodes[i].State == POINT_ASSAULTED) //maybe remove this + { + if (m_Nodes[i].Timer > diff) + m_Nodes[i].Timer -= diff; + else + EventPlayerDestroyedPoint(i); + } + } +} + +void BattleGroundAV::StartingEventCloseDoors() +{ + DoorClose(BG_AV_OBJECT_DOOR_A); + DoorClose(BG_AV_OBJECT_DOOR_H); +} + +void BattleGroundAV::StartingEventOpenDoors() +{ + sLog.outDebug("BG_AV: start spawning mine stuff"); + for (uint16 i= BG_AV_OBJECT_MINE_SUPPLY_N_MIN; i <= BG_AV_OBJECT_MINE_SUPPLY_N_MAX; i++) + SpawnBGObject(i,RESPAWN_IMMEDIATELY); + for (uint16 i= BG_AV_OBJECT_MINE_SUPPLY_S_MIN; i <= BG_AV_OBJECT_MINE_SUPPLY_S_MAX; i++) + SpawnBGObject(i,RESPAWN_IMMEDIATELY); + for (uint8 mine = AV_NORTH_MINE; mine <= AV_SOUTH_MINE; mine++) //mine population + ChangeMineOwner(mine, AV_NEUTRAL_TEAM,true); + + UpdateWorldState(AV_SHOW_H_SCORE, 1); + UpdateWorldState(AV_SHOW_A_SCORE, 1); + + DoorOpen(BG_AV_OBJECT_DOOR_H); + DoorOpen(BG_AV_OBJECT_DOOR_A); +} + +void BattleGroundAV::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundAVScore* sc = new BattleGroundAVScore; + m_PlayerScores[plr->GetGUID()] = sc; + if (m_MaxLevel == 0) + m_MaxLevel=(plr->getLevel()%10 == 0)? plr->getLevel() : (plr->getLevel()-(plr->getLevel()%10))+10; //TODO: just look at the code \^_^/ --but queue-info should provide this information.. + +} + +void BattleGroundAV::EndBattleGround(uint32 winner) +{ + //calculate bonuskills for both teams: + //first towers: + uint8 kills[2]={0,0}; //0=ally 1=horde + uint8 rep[2]={0,0}; //0=ally 1=horde + for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) + { + if (m_Nodes[i].State == POINT_CONTROLED) + { + if (m_Nodes[i].Owner == ALLIANCE) + { + rep[0] += BG_AV_REP_SURVIVING_TOWER; + kills[0] += BG_AV_KILL_SURVIVING_TOWER; + } + else + { + rep[0] += BG_AV_KILL_SURVIVING_TOWER; + kills[1] += BG_AV_KILL_SURVIVING_TOWER; + } + } + } + + for (int i=0; i <= 1; i++) //0=ally 1=horde + { + if (m_CaptainAlive[i]) + { + kills[i] += BG_AV_KILL_SURVIVING_CAPTAIN; + rep[i] += BG_AV_REP_SURVIVING_CAPTAIN; + } + if (rep[i] != 0) + RewardReputationToTeam((i == 0)?730:729,rep[i],(i == 0)?ALLIANCE:HORDE); + if (kills[i] != 0) + RewardHonorToTeam(GetBonusHonor(kills[i]),(i == 0)?ALLIANCE:HORDE); + } + + //TODO add enterevademode for all attacking creatures + BattleGround::EndBattleGround(winner); +} + +void BattleGroundAV::RemovePlayer(Player* plr,uint64 /*guid*/) +{ + if (!plr) + { + sLog.outError("bg_AV no player at remove"); + return; + } + //TODO search more buffs + plr->RemoveAurasDueToSpell(AV_BUFF_ARMOR); + plr->RemoveAurasDueToSpell(AV_BUFF_A_CAPTAIN); + plr->RemoveAurasDueToSpell(AV_BUFF_H_CAPTAIN); +} + +void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + uint32 SpellId = 0; + switch(Trigger) + { + case 95: + case 2608: + if (Source->GetTeam() != ALLIANCE) + Source->GetSession()->SendAreaTriggerMessage("Only The Alliance can use that portal"); + else + Source->LeaveBattleground(); + break; + case 2606: + if (Source->GetTeam() != HORDE) + Source->GetSession()->SendAreaTriggerMessage("Only The Horde can use that portal"); + else + Source->LeaveBattleground(); + break; + case 3326: + case 3327: + case 3328: + case 3329: + case 3330: + case 3331: + //Source->Unmount(); + break; + default: + sLog.outDebug("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); +// Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + if (SpellId) + Source->CastSpell(Source, SpellId, true); +} + +void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) +{ + + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); + if (itr == m_PlayerScores.end()) // player not found... + return; + + switch(type) + { + case SCORE_GRAVEYARDS_ASSAULTED: + ((BattleGroundAVScore*)itr->second)->GraveyardsAssaulted += value; + break; + case SCORE_GRAVEYARDS_DEFENDED: + ((BattleGroundAVScore*)itr->second)->GraveyardsDefended += value; + break; + case SCORE_TOWERS_ASSAULTED: + ((BattleGroundAVScore*)itr->second)->TowersAssaulted += value; + break; + case SCORE_TOWERS_DEFENDED: + ((BattleGroundAVScore*)itr->second)->TowersDefended += value; + break; + case SCORE_MINES_CAPTURED: + ((BattleGroundAVScore*)itr->second)->MinesCaptured += value; + break; + case SCORE_LEADERS_KILLED: + ((BattleGroundAVScore*)itr->second)->LeadersKilled += value; + break; + case SCORE_SECONDARY_OBJECTIVES: + ((BattleGroundAVScore*)itr->second)->SecondaryObjectives += value; + break; + default: + BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); + break; + } +} + +void BattleGroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node) +{ + + uint32 object = GetObjectThroughNode(node); + sLog.outDebug("bg_av: player destroyed point node %i object %i",node,object); + + //despawn banner + SpawnBGObject(object, RESPAWN_ONE_DAY); + DestroyNode(node); + UpdateNodeWorldState(node); + + uint32 owner = m_Nodes[node].Owner; + if (IsTower(node)) + { + uint8 tmp = node-BG_AV_NODES_DUNBALDAR_SOUTH; + //despawn marshal + if (m_BgCreatures[AV_CPLACE_A_MARSHAL_SOUTH + tmp]) + DelCreature(AV_CPLACE_A_MARSHAL_SOUTH + tmp); + else + sLog.outError("BG_AV: playerdestroyedpoint: marshal %i doesn't exist",AV_CPLACE_A_MARSHAL_SOUTH + tmp); + //spawn destroyed aura + for (uint8 i=0; i <= 9; i++) + SpawnBGObject(BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH + i + (tmp * 10),RESPAWN_IMMEDIATELY); + + UpdateScore((owner == ALLIANCE) ? HORDE : ALLIANCE, (-1)*BG_AV_RES_TOWER); + RewardReputationToTeam((owner == ALLIANCE)?730:729,BG_AV_REP_TOWER,owner); + RewardHonorToTeam(GetBonusHonor(BG_AV_KILL_TOWER),owner); + + SpawnBGObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+GetTeamIndexByTeamId(owner)+(2*tmp),RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+GetTeamIndexByTeamId(owner)+(2*tmp),RESPAWN_ONE_DAY); + } + else + { + if (owner == ALLIANCE) + SpawnBGObject(object-11, RESPAWN_IMMEDIATELY); + else + SpawnBGObject(object+11, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node,RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+GetTeamIndexByTeamId(owner)+3*node,RESPAWN_IMMEDIATELY); + PopulateNode(node); + if (node == BG_AV_NODES_SNOWFALL_GRAVE) //snowfall eyecandy + { + for (uint8 i = 0; i < 4; i++) + { + SpawnBGObject(((owner == ALLIANCE)?BG_AV_OBJECT_SNOW_EYECANDY_PA : BG_AV_OBJECT_SNOW_EYECANDY_PH)+i,RESPAWN_ONE_DAY); + SpawnBGObject(((owner == ALLIANCE)?BG_AV_OBJECT_SNOW_EYECANDY_A : BG_AV_OBJECT_SNOW_EYECANDY_H)+i,RESPAWN_IMMEDIATELY); + } + } + } + //send a nice message to all :) + char buf[256]; + if (IsTower(node)) + sprintf(buf, GetTrinityString(LANG_BG_AV_TOWER_TAKEN) , GetNodeName(node),(owner == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) : GetTrinityString(LANG_BG_AV_HORDE)); + else + sprintf(buf, GetTrinityString(LANG_BG_AV_GRAVE_TAKEN) , GetNodeName(node),(owner == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) :GetTrinityString(LANG_BG_AV_HORDE)); + + Creature* creature = GetBGCreature(AV_CPLACE_HERALD); + if (creature) + YellToAll(creature,buf,LANG_UNIVERSAL); +} + +void BattleGroundAV::ChangeMineOwner(uint8 mine, uint32 team, bool initial) +{ //mine=0 northmine mine=1 southmin +//changing the owner results in setting respawntim to infinite for current creatures, spawning new mine owners creatures and changing the chest-objects so that the current owning team can use them + assert(mine == AV_NORTH_MINE || mine == AV_SOUTH_MINE); + if (team != ALLIANCE && team != HORDE) + team = AV_NEUTRAL_TEAM; + else + PlaySoundToAll((team == ALLIANCE)?AV_SOUND_ALLIANCE_GOOD:AV_SOUND_HORDE_GOOD); + + if (m_Mine_Owner[mine] == team && !initial) + return; + m_Mine_PrevOwner[mine] = m_Mine_Owner[mine]; + m_Mine_Owner[mine] = team; + + if (!initial) + { + sLog.outDebug("bg_av depopulating mine %i (0=north,1=south)",mine); + if (mine == AV_SOUTH_MINE) + for (uint16 i=AV_CPLACE_MINE_S_S_MIN; i <= AV_CPLACE_MINE_S_S_MAX; i++) + if (m_BgCreatures[i]) + DelCreature(i); //TODO just set the respawntime to 999999 + for (uint16 i=((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_1_MIN:AV_CPLACE_MINE_S_1_MIN); i <= ((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_3:AV_CPLACE_MINE_S_3); i++) + if (m_BgCreatures[i]) + DelCreature(i); //TODO here also + } + SendMineWorldStates(mine); + + sLog.outDebug("bg_av populating mine %i (0=north,1=south)",mine); + uint16 miner; + //also neutral team exists.. after a big time, the neutral team tries to conquer the mine + if (mine == AV_NORTH_MINE) + { + if (team == ALLIANCE) + miner = AV_NPC_N_MINE_A_1; + else if (team == HORDE) + miner = AV_NPC_N_MINE_H_1; + else + miner = AV_NPC_N_MINE_N_1; + } + else + { + uint16 cinfo; + if (team == ALLIANCE) + miner = AV_NPC_S_MINE_A_1; + else if (team == HORDE) + miner = AV_NPC_S_MINE_H_1; + else + miner = AV_NPC_S_MINE_N_1; + //vermin + sLog.outDebug("spawning vermin"); + if (team == ALLIANCE) + cinfo = AV_NPC_S_MINE_A_3; + else if (team == HORDE) + cinfo = AV_NPC_S_MINE_H_3; + else + cinfo = AV_NPC_S_MINE_N_S; + for (uint16 i=AV_CPLACE_MINE_S_S_MIN; i <= AV_CPLACE_MINE_S_S_MAX; i++) + AddAVCreature(cinfo,i); + } + for (uint16 i=((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_1_MIN:AV_CPLACE_MINE_S_1_MIN); i <= ((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_1_MAX:AV_CPLACE_MINE_S_1_MAX); i++) + AddAVCreature(miner,i); + //the next chooses randomly between 2 cretures + for (uint16 i=((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_2_MIN:AV_CPLACE_MINE_S_2_MIN); i <= ((mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_2_MAX:AV_CPLACE_MINE_S_2_MAX); i++) + AddAVCreature(miner+(urand(1,2)),i); + AddAVCreature(miner+3,(mine == AV_NORTH_MINE)?AV_CPLACE_MINE_N_3:AV_CPLACE_MINE_S_3); + //because the gameobjects in this mine have changed, update all surrounding players: +// for (uint16 i = ((mine == AV_NORTH_MINE)?BG_AV_OBJECT_MINE_SUPPLY_N_MIN:BG_AV_OBJECT_MINE_SUPPLY_N_MIN); i <= ((mine == AV_NORTH_MINE)?BG_AV_OBJECT_MINE_SUPPLY_N_MAX:BG_AV_OBJECT_MINE_SUPPLY_N_MAX); i++) +// { + //TODO: add gameobject-update code +// } + if (team == ALLIANCE || team == HORDE) + { + m_Mine_Reclaim_Timer[mine]=AV_MINE_RECLAIM_TIMER; + char buf[256]; + sprintf(buf, GetTrinityString(LANG_BG_AV_MINE_TAKEN), GetTrinityString((mine == AV_NORTH_MINE) ? LANG_BG_AV_MINE_NORTH : LANG_BG_AV_MINE_SOUTH), (team == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) : GetTrinityString(LANG_BG_AV_HORDE)); + Creature* creature = GetBGCreature(AV_CPLACE_HERALD); + if (creature) + YellToAll(creature,buf,LANG_UNIVERSAL); + } + else + { + if (mine == AV_SOUTH_MINE) //i think this gets called all the time + { + Creature* creature = GetBGCreature(AV_CPLACE_MINE_S_3); + YellToAll(creature,LANG_BG_AV_S_MINE_BOSS_CLAIMS,LANG_UNIVERSAL); + } + } + return; +} + +bool BattleGroundAV::PlayerCanDoMineQuest(int32 GOId,uint32 team) +{ + if (GOId == BG_AV_OBJECTID_MINE_N) + return (m_Mine_Owner[AV_NORTH_MINE] == team); + if (GOId == BG_AV_OBJECTID_MINE_S) + return (m_Mine_Owner[AV_SOUTH_MINE] == team); + return true; //cause it's no mine'object it is ok if this is true +} + +void BattleGroundAV::PopulateNode(BG_AV_Nodes node) +{ + uint32 owner = m_Nodes[node].Owner; + assert(owner); + + uint32 c_place = AV_CPLACE_DEFENSE_STORM_AID + (4 * node); + uint32 creatureid; + if (IsTower(node)) + creatureid=(owner == ALLIANCE)?AV_NPC_A_TOWERDEFENSE:AV_NPC_H_TOWERDEFENSE; + else + { + uint8 team2 = GetTeamIndexByTeamId(owner); + if (m_Team_QuestStatus[team2][0] < 500) + creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE0 : AV_NPC_H_GRAVEDEFENSE0; + else if (m_Team_QuestStatus[team2][0] < 1000) + creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE1 : AV_NPC_H_GRAVEDEFENSE1; + else if (m_Team_QuestStatus[team2][0] < 1500) + creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE2 : AV_NPC_H_GRAVEDEFENSE2; + else + creatureid = (owner == ALLIANCE)? AV_NPC_A_GRAVEDEFENSE3 : AV_NPC_H_GRAVEDEFENSE3; + //spiritguide + if (m_BgCreatures[node]) + DelCreature(node); + if (!AddSpiritGuide(node, BG_AV_CreaturePos[node][0], BG_AV_CreaturePos[node][1], BG_AV_CreaturePos[node][2], BG_AV_CreaturePos[node][3], owner)) + sLog.outError("AV: couldn't spawn spiritguide at node %i",node); + + } + for (uint8 i=0; i<4; i++) + AddAVCreature(creatureid,c_place+i); + + if (node >= BG_AV_NODES_MAX)//fail safe + return; + Creature* trigger = GetBGCreature(node + 302);//0-302 other creatures + if (!trigger) + trigger = AddCreature(WORLD_TRIGGER,node + 302,owner,BG_AV_CreaturePos[node + 302][0],BG_AV_CreaturePos[node + 302][1],BG_AV_CreaturePos[node + 302][2],BG_AV_CreaturePos[node + 302][3]); + + //add bonus honor aura trigger creature when node is accupied + //cast bonus aura (+50% honor in 25yards) + //aura should only apply to players who have accupied the node, set correct faction for trigger + if (trigger) + { + if (owner != ALLIANCE && owner != HORDE)//node can be neutral, remove trigger + { + DelCreature(node + 302); + return; + } + trigger->setFaction(owner == ALLIANCE ? 84 : 83); + trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); + } +} +void BattleGroundAV::DePopulateNode(BG_AV_Nodes node) +{ + uint32 c_place = AV_CPLACE_DEFENSE_STORM_AID + (4 * node); + for (uint8 i=0; i<4; i++) + if (m_BgCreatures[c_place+i]) + DelCreature(c_place+i); + //spiritguide + if (!IsTower(node) && m_BgCreatures[node]) + DelCreature(node); + + //remove bonus honor aura trigger creature when node is lost + if(node < BG_AV_NODES_MAX)//fail safe + DelCreature(node + 302);//NULL checks are in DelCreature! 0-302 spirit guides +} + +const BG_AV_Nodes BattleGroundAV::GetNodeThroughObject(uint32 object) +{ + sLog.outDebug("bg_AV getnodethroughobject %i",object); + if (object <= BG_AV_OBJECT_FLAG_A_STONEHEART_BUNKER) + return BG_AV_Nodes(object); + if (object <= BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_HUT) + return BG_AV_Nodes(object - 11); + if (object <= BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_WTOWER) + return BG_AV_Nodes(object - 7); + if (object <= BG_AV_OBJECT_FLAG_C_H_STONEHEART_BUNKER) + return BG_AV_Nodes(object -22); + if (object <= BG_AV_OBJECT_FLAG_H_FROSTWOLF_HUT) + return BG_AV_Nodes(object - 33); + if (object <= BG_AV_OBJECT_FLAG_H_FROSTWOLF_WTOWER) + return BG_AV_Nodes(object - 29); + if (object == BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE) + return BG_AV_NODES_SNOWFALL_GRAVE; + sLog.outError("BattleGroundAV: ERROR! GetPlace got a wrong object :("); + assert(false); + return BG_AV_Nodes(0); +} + +const uint32 BattleGroundAV::GetObjectThroughNode(BG_AV_Nodes node) +{ //this function is the counterpart to GetNodeThroughObject() + sLog.outDebug("bg_AV GetObjectThroughNode %i",node); + if (m_Nodes[node].Owner == ALLIANCE) + { + if (m_Nodes[node].State == POINT_ASSAULTED) + { + if (node <= BG_AV_NODES_FROSTWOLF_HUT) + return node+11; + if (node >= BG_AV_NODES_ICEBLOOD_TOWER && node <= BG_AV_NODES_FROSTWOLF_WTOWER) + return node+7; + } + else if (m_Nodes[node].State == POINT_CONTROLED) + if (node <= BG_AV_NODES_STONEHEART_BUNKER) + return node; + } + else if (m_Nodes[node].Owner == HORDE) + { + if (m_Nodes[node].State == POINT_ASSAULTED) + if (node <= BG_AV_NODES_STONEHEART_BUNKER) + return node+22; + else if (m_Nodes[node].State == POINT_CONTROLED) + { + if (node <= BG_AV_NODES_FROSTWOLF_HUT) + return node+33; + if (node >= BG_AV_NODES_ICEBLOOD_TOWER && node <= BG_AV_NODES_FROSTWOLF_WTOWER) + return node+29; + } + } + else if (m_Nodes[node].Owner == AV_NEUTRAL_TEAM) + return BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE; + sLog.outError("BattleGroundAV: Error! GetPlaceNode couldn't resolve node %i",node); + assert(false); + return 0; +} + +//called when using banner + +void BattleGroundAV::EventPlayerClickedOnFlag(Player *source, GameObject* target_obj) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + int32 object = GetObjectType(target_obj->GetGUID()); + sLog.outDebug("BG_AV using gameobject %i with type %i",target_obj->GetEntry(),object); + if (object < 0) + return; + switch(target_obj->GetEntry()) + { + case BG_AV_OBJECTID_BANNER_A: + case BG_AV_OBJECTID_BANNER_A_B: + case BG_AV_OBJECTID_BANNER_H: + case BG_AV_OBJECTID_BANNER_H_B: + case BG_AV_OBJECTID_BANNER_SNOWFALL_N: + EventPlayerAssaultsPoint(source, object); + break; + case BG_AV_OBJECTID_BANNER_CONT_A: + case BG_AV_OBJECTID_BANNER_CONT_A_B: + case BG_AV_OBJECTID_BANNER_CONT_H: + case BG_AV_OBJECTID_BANNER_CONT_H_B: + EventPlayerDefendsPoint(source, object); + break; + default: + break; + } +} + +void BattleGroundAV::EventPlayerDefendsPoint(Player* player, uint32 object) +{ + assert(GetStatus() == STATUS_IN_PROGRESS); + BG_AV_Nodes node = GetNodeThroughObject(object); + + uint32 owner = m_Nodes[node].Owner; //maybe should name it prevowner + uint32 team = player->GetTeam(); + + if (owner == player->GetTeam() || m_Nodes[node].State != POINT_ASSAULTED) + return; + if (m_Nodes[node].TotalOwner == AV_NEUTRAL_TEAM) + { //until snowfall doesn't belong to anyone it is better handled in assault-code + assert(node == BG_AV_NODES_SNOWFALL_GRAVE); //currently the only neutral grave + EventPlayerAssaultsPoint(player,object); + return; + } + sLog.outDebug("player defends point object: %i node: %i",object,node); + if (m_Nodes[node].PrevOwner != team) + { + sLog.outError("BG_AV: player defends point which doesn't belong to his team %i",node); + return; + } + + //spawn new go :) + if (m_Nodes[node].Owner == ALLIANCE) + SpawnBGObject(object+22, RESPAWN_IMMEDIATELY); //spawn horde banner + else + SpawnBGObject(object-22, RESPAWN_IMMEDIATELY); //spawn alliance banner + + if (!IsTower(node)) + { + SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node,RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+GetTeamIndexByTeamId(team)+3*node,RESPAWN_IMMEDIATELY); + } + // despawn old go + SpawnBGObject(object, RESPAWN_ONE_DAY); + + DefendNode(node,team); + PopulateNode(node); + UpdateNodeWorldState(node); + + if (IsTower(node)) + { + //spawn big flag+aura on top of tower + SpawnBGObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == ALLIANCE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == HORDE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == ALLIANCE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == HORDE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + } + else if (node == BG_AV_NODES_SNOWFALL_GRAVE) //snowfall eyecandy + { + for (uint8 i = 0; i < 4; i++) + { + SpawnBGObject(((owner == ALLIANCE)?BG_AV_OBJECT_SNOW_EYECANDY_PA : BG_AV_OBJECT_SNOW_EYECANDY_PH)+i,RESPAWN_ONE_DAY); + SpawnBGObject(((team == ALLIANCE)?BG_AV_OBJECT_SNOW_EYECANDY_A : BG_AV_OBJECT_SNOW_EYECANDY_H)+i,RESPAWN_IMMEDIATELY); + } + } + //send a nice message to all :) + char buf[256]; + sprintf(buf, GetTrinityString((IsTower(node)) ? LANG_BG_AV_TOWER_DEFENDED : LANG_BG_AV_GRAVE_DEFENDED), GetNodeName(node),(team == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) : GetTrinityString(LANG_BG_AV_HORDE)); + Creature* creature = GetBGCreature(AV_CPLACE_HERALD); + if (creature) + YellToAll(creature,buf,LANG_UNIVERSAL); + //update the statistic for the defending player + UpdatePlayerScore(player, (IsTower(node)) ? SCORE_TOWERS_DEFENDED : SCORE_GRAVEYARDS_DEFENDED, 1); + if (IsTower(node)) + PlaySoundToAll(AV_SOUND_BOTH_TOWER_DEFEND); + else + PlaySoundToAll((team == ALLIANCE)?AV_SOUND_ALLIANCE_GOOD:AV_SOUND_HORDE_GOOD); +} + +void BattleGroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object) +{ + assert(GetStatus() == STATUS_IN_PROGRESS); + + BG_AV_Nodes node = GetNodeThroughObject(object); + uint32 owner = m_Nodes[node].Owner; //maybe name it prevowner + uint32 team = player->GetTeam(); + sLog.outDebug("bg_av: player assaults point object %i node %i",object,node); + if (owner == team || team == m_Nodes[node].TotalOwner) + return; //surely a gm used this object + + if (node == BG_AV_NODES_SNOWFALL_GRAVE) //snowfall is a bit special in capping + it gets eyecandy stuff + { + if (object == BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE) //initial capping + { + assert(owner == AV_NEUTRAL_TEAM && m_Nodes[node].TotalOwner == AV_NEUTRAL_TEAM); + if (team == ALLIANCE) + SpawnBGObject(BG_AV_OBJECT_FLAG_C_A_SNOWFALL_GRAVE, RESPAWN_IMMEDIATELY); + else + SpawnBGObject(BG_AV_OBJECT_FLAG_C_H_SNOWFALL_GRAVE, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node,RESPAWN_IMMEDIATELY); //neutral aura spawn + } + else if (m_Nodes[node].TotalOwner == AV_NEUTRAL_TEAM) //recapping, when no team owns this node realy + { + assert(m_Nodes[node].State != POINT_CONTROLED); + if (team == ALLIANCE) + SpawnBGObject(object-11, RESPAWN_IMMEDIATELY); + else + SpawnBGObject(object+11, RESPAWN_IMMEDIATELY); + } + //eyecandy + uint32 spawn,despawn; + if (team == ALLIANCE) + { + despawn = (m_Nodes[node].State == POINT_ASSAULTED)?BG_AV_OBJECT_SNOW_EYECANDY_PH : BG_AV_OBJECT_SNOW_EYECANDY_H; + spawn = BG_AV_OBJECT_SNOW_EYECANDY_PA; + } + else + { + despawn = (m_Nodes[node].State == POINT_ASSAULTED)?BG_AV_OBJECT_SNOW_EYECANDY_PA : BG_AV_OBJECT_SNOW_EYECANDY_A; + spawn = BG_AV_OBJECT_SNOW_EYECANDY_PH; + } + for (uint8 i = 0; i < 4; i++) + { + SpawnBGObject(despawn+i,RESPAWN_ONE_DAY); + SpawnBGObject(spawn+i,RESPAWN_IMMEDIATELY); + } + } + + //if snowfall gots capped it can be handled like all other graveyards + if (m_Nodes[node].TotalOwner != AV_NEUTRAL_TEAM) + { + assert(m_Nodes[node].Owner != AV_NEUTRAL_TEAM); + if (team == ALLIANCE) + SpawnBGObject(object-22, RESPAWN_IMMEDIATELY); + else + SpawnBGObject(object+22, RESPAWN_IMMEDIATELY); + if (IsTower(node)) + { //spawning/despawning of bigflag+aura + SpawnBGObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == ALLIANCE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == HORDE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == ALLIANCE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + SpawnBGObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(node-BG_AV_NODES_DUNBALDAR_SOUTH)),(team == HORDE)? RESPAWN_IMMEDIATELY : RESPAWN_ONE_DAY); + } + else + { + //spawning/despawning of aura + SpawnBGObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+3*node,RESPAWN_IMMEDIATELY); //neutral aura spawn + SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+GetTeamIndexByTeamId(owner)+3*node,RESPAWN_ONE_DAY); //teeamaura despawn + // Those who are waiting to resurrect at this object are taken to the closest own object's graveyard + std::vector ghost_list = m_ReviveQueue[m_BgCreatures[node]]; + if (!ghost_list.empty()) + { + Player *plr; + WorldSafeLocsEntry const *ClosestGrave = NULL; + for (std::vector::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) + { + plr = objmgr.GetPlayer(*ghost_list.begin()); + if (!plr) + continue; + if (!ClosestGrave) + ClosestGrave = GetClosestGraveYard(plr); + else + plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); + } + m_ReviveQueue[m_BgCreatures[node]].clear(); + } + } + DePopulateNode(node); + } + + SpawnBGObject(object, RESPAWN_ONE_DAY); //delete old banner + AssaultNode(node,team); + UpdateNodeWorldState(node); + + //send a nice message to all :) + char buf[256]; + sprintf(buf, (IsTower(node)) ? GetTrinityString(LANG_BG_AV_TOWER_ASSAULTED) : GetTrinityString(LANG_BG_AV_GRAVE_ASSAULTED), GetNodeName(node), (team == ALLIANCE) ? GetTrinityString(LANG_BG_AV_ALLY) : GetTrinityString(LANG_BG_AV_HORDE)); + Creature* creature = GetBGCreature(AV_CPLACE_HERALD); + if (creature) + YellToAll(creature,buf,LANG_UNIVERSAL); + //update the statistic for the assaulting player + UpdatePlayerScore(player, (IsTower(node)) ? SCORE_TOWERS_ASSAULTED : SCORE_GRAVEYARDS_ASSAULTED, 1); + PlaySoundToAll((team == ALLIANCE)?AV_SOUND_ALLIANCE_ASSAULTS:AV_SOUND_HORDE_ASSAULTS); +} + +void BattleGroundAV::FillInitialWorldStates(WorldPacket& data) +{ + bool stateok; + //graveyards + for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; i++) + { + for (uint8 j =1; j <= 3; j+=2) + {//j=1=assaulted j=3=controled + stateok = (m_Nodes[i].State == j); + data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j,ALLIANCE)]) << uint32((m_Nodes[i].Owner == ALLIANCE && stateok)?1:0); + data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j,HORDE)]) << uint32((m_Nodes[i].Owner == HORDE && stateok)?1:0); + } + } + + //towers + for (uint8 i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_MAX; i++) + for (uint8 j =1; j <= 3; j+=2) + {//j=1=assaulted j=3=controled //i dont have j=2=destroyed cause destroyed is the same like enemy-team controll + stateok = (m_Nodes[i].State == j || (m_Nodes[i].State == POINT_DESTROYED && j == 3)); + data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j,ALLIANCE)]) << uint32((m_Nodes[i].Owner == ALLIANCE && stateok)?1:0); + data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j,HORDE)]) << uint32((m_Nodes[i].Owner == HORDE && stateok)?1:0); + } + if (m_Nodes[BG_AV_NODES_SNOWFALL_GRAVE].Owner == AV_NEUTRAL_TEAM) //cause neutral teams aren't handled generic + data << uint32(AV_SNOWFALL_N) << uint32(1); + data << uint32(AV_Alliance_Score) << uint32(m_Team_Scores[0]); + data << uint32(AV_Horde_Score) << uint32(m_Team_Scores[1]); + if (GetStatus() == STATUS_IN_PROGRESS){ //only if game started the teamscores are displayed + data << uint32(AV_SHOW_A_SCORE) << uint32(1); + data << uint32(AV_SHOW_H_SCORE) << uint32(1); + } + else + { + data << uint32(AV_SHOW_A_SCORE) << uint32(0); + data << uint32(AV_SHOW_H_SCORE) << uint32(0); + } + SendMineWorldStates(AV_NORTH_MINE); + SendMineWorldStates(AV_SOUTH_MINE); +} + +const uint8 BattleGroundAV::GetWorldStateType(uint8 state, uint16 team) //this is used for node worldstates and returns values which fit good into the worldstatesarray +{ + //neutral stuff cant get handled (currently its only snowfall) + assert(team != AV_NEUTRAL_TEAM); + //a_c a_a h_c h_a the positions in worldstate-array + if (team == ALLIANCE) + { + if (state == POINT_CONTROLED || state == POINT_DESTROYED) + return 0; + if (state == POINT_ASSAULTED) + return 1; + } + if (team == HORDE) + { + if (state == POINT_DESTROYED || state == POINT_CONTROLED) + return 2; + if (state == POINT_ASSAULTED) + return 3; + } + sLog.outError("BG_AV: should update a strange worldstate state:%i team:%i",state,team); + return 5; //this will crash the game, but i want to know if something is wrong here +} + +void BattleGroundAV::UpdateNodeWorldState(BG_AV_Nodes node) +{ + UpdateWorldState(BG_AV_NodeWorldStates[node][GetWorldStateType(m_Nodes[node].State,m_Nodes[node].Owner)],1); + if (m_Nodes[node].PrevOwner == AV_NEUTRAL_TEAM) //currently only snowfall is supported as neutral node (i don't want to make an extra row (neutral states) in worldstatesarray just for one node + UpdateWorldState(AV_SNOWFALL_N,0); + else + UpdateWorldState(BG_AV_NodeWorldStates[node][GetWorldStateType(m_Nodes[node].PrevState,m_Nodes[node].PrevOwner)],0); +} + +void BattleGroundAV::SendMineWorldStates(uint32 mine) +{ + assert(mine == AV_NORTH_MINE || mine == AV_SOUTH_MINE); +// currently i'm sure, that this works (: +// assert(m_Mine_PrevOwner[mine] == ALLIANCE || m_Mine_PrevOwner[mine] == HORDE || m_Mine_PrevOwner[mine] == AV_NEUTRAL_TEAM); +// assert(m_Mine_Owner[mine] == ALLIANCE || m_Mine_Owner[mine] == HORDE || m_Mine_Owner[mine] == AV_NEUTRAL_TEAM); + + uint8 owner,prevowner,mine2; //those variables are needed to access the right worldstate in the BG_AV_MineWorldStates array + mine2 = (mine == AV_NORTH_MINE)?0:1; + if (m_Mine_PrevOwner[mine] == ALLIANCE) + prevowner = 0; + else if (m_Mine_PrevOwner[mine] == HORDE) + prevowner = 2; + else + prevowner = 1; + if (m_Mine_Owner[mine] == ALLIANCE) + owner = 0; + else if (m_Mine_Owner[mine] == HORDE) + owner = 2; + else + owner = 1; + + UpdateWorldState(BG_AV_MineWorldStates[mine2][owner],1); + if (prevowner != owner) + UpdateWorldState(BG_AV_MineWorldStates[mine2][prevowner],0); +} + +WorldSafeLocsEntry const* BattleGroundAV::GetClosestGraveYard(Player* player) +{ + WorldSafeLocsEntry const* pGraveyard = NULL; + WorldSafeLocsEntry const* entry = NULL; + float dist = 0; + float minDist = 0; + float x, y; + + player->GetPosition(x, y); + + pGraveyard = sWorldSafeLocsStore.LookupEntry(BG_AV_GraveyardIds[GetTeamIndexByTeamId(player->GetTeam())+7]); + minDist = (pGraveyard->x - x)*(pGraveyard->x - x)+(pGraveyard->y - y)*(pGraveyard->y - y); + + for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) + if (m_Nodes[i].Owner == player->GetTeam() && m_Nodes[i].State == POINT_CONTROLED) + { + entry = sWorldSafeLocsStore.LookupEntry(BG_AV_GraveyardIds[i]); + if (entry) + { + dist = (entry->x - x)*(entry->x - x)+(entry->y - y)*(entry->y - y); + if (dist < minDist) + { + minDist = dist; + pGraveyard = entry; + } + } + } + return pGraveyard; +} + +bool BattleGroundAV::SetupBattleGround() +{ + // Create starting objects + if ( + // alliance gates + !AddObject(BG_AV_OBJECT_DOOR_A, BG_AV_OBJECTID_GATE_A, BG_AV_DoorPositons[0][0],BG_AV_DoorPositons[0][1],BG_AV_DoorPositons[0][2],BG_AV_DoorPositons[0][3],0,0,sin(BG_AV_DoorPositons[0][3]/2),cos(BG_AV_DoorPositons[0][3]/2),RESPAWN_IMMEDIATELY) + // horde gates + || !AddObject(BG_AV_OBJECT_DOOR_H, BG_AV_OBJECTID_GATE_H, BG_AV_DoorPositons[1][0],BG_AV_DoorPositons[1][1],BG_AV_DoorPositons[1][2],BG_AV_DoorPositons[1][3],0,0,sin(BG_AV_DoorPositons[1][3]/2),cos(BG_AV_DoorPositons[1][3]/2),RESPAWN_IMMEDIATELY)) + { + sLog.outErrorDb("BatteGroundAV: Failed to spawn some object BattleGround not created!1"); + return false; + } + + //spawn node-objects + for (uint8 i = BG_AV_NODES_FIRSTAID_STATION ; i < BG_AV_NODES_MAX; ++i) + { + if (i <= BG_AV_NODES_FROSTWOLF_HUT) + { + if (!AddObject(i,BG_AV_OBJECTID_BANNER_A_B,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(i+11,BG_AV_OBJECTID_BANNER_CONT_A_B,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(i+33,BG_AV_OBJECTID_BANNER_H_B,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(i+22,BG_AV_OBJECTID_BANNER_CONT_H_B,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + //aura + || !AddObject(BG_AV_OBJECT_AURA_N_FIRSTAID_STATION+i*3,BG_AV_OBJECTID_AURA_N,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+i*3,BG_AV_OBJECTID_AURA_A,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_AURA_H_FIRSTAID_STATION+i*3,BG_AV_OBJECTID_AURA_H,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!2"); + return false; + } + } + else //towers + { + if (i <= BG_AV_NODES_STONEHEART_BUNKER) //alliance towers + { + if (!AddObject(i,BG_AV_OBJECTID_BANNER_A,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(i+22,BG_AV_OBJECTID_BANNER_CONT_H,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_AURA_A,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_AURA_N,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_TOWER_BANNER_A,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_TOWER_BANNER_PH,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!3"); + return false; + } + } + else //horde towers + { + if (!AddObject(i+7,BG_AV_OBJECTID_BANNER_CONT_A,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(i+29,BG_AV_OBJECTID_BANNER_H,BG_AV_ObjectPos[i][0],BG_AV_ObjectPos[i][1],BG_AV_ObjectPos[i][2],BG_AV_ObjectPos[i][3], 0, 0, sin(BG_AV_ObjectPos[i][3]/2), cos(BG_AV_ObjectPos[i][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_AURA_N,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_AURA_H,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_TOWER_BANNER_PA,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH+(2*(i-BG_AV_NODES_DUNBALDAR_SOUTH)),BG_AV_OBJECTID_TOWER_BANNER_H,BG_AV_ObjectPos[i+8][0],BG_AV_ObjectPos[i+8][1],BG_AV_ObjectPos[i+8][2],BG_AV_ObjectPos[i+8][3], 0, 0, sin(BG_AV_ObjectPos[i+8][3]/2), cos(BG_AV_ObjectPos[i+8][3]/2),RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!4"); + return false; + } + } + for (uint8 j=0; j <= 9; j++) //burning aura + { + if (!AddObject(BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j,BG_AV_OBJECTID_FIRE,BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][0],BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][1],BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][2],BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_BURN_DUNBALDAR_SOUTH+((i-BG_AV_NODES_DUNBALDAR_SOUTH)*10)+j][3]/2),RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!5.%i",i); + return false; + } + } + } + } + for (uint8 i=0; i<2; i++) //burning aura for buildings + { + for (uint8 j=0; j <= 9; j++) + { + if (j<5) + { + if (!AddObject(BG_AV_OBJECT_BURN_BUILDING_ALLIANCE+(i*10)+j,BG_AV_OBJECTID_SMOKE,BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][0],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][1],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][2],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2),RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!6.%i",i); + return false; + } + } + else + { + if (!AddObject(BG_AV_OBJECT_BURN_BUILDING_ALLIANCE+(i*10)+j,BG_AV_OBJECTID_FIRE,BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][0],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][1],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][2],BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_BURN_BUILDING_A+(i*10)+j][3]/2),RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!7.%i",i); + return false; + } + } + } + } + for (uint16 i= 0; i <= (BG_AV_OBJECT_MINE_SUPPLY_N_MAX-BG_AV_OBJECT_MINE_SUPPLY_N_MIN); i++) + { + if (!AddObject(BG_AV_OBJECT_MINE_SUPPLY_N_MIN+i,BG_AV_OBJECTID_MINE_N,BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][0],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][1],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][2],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_N_MIN+i][3]/2),RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some mine supplies BattleGround not created!7.5.%i",i); + return false; + } + } + for (uint16 i= 0 ; i <= (BG_AV_OBJECT_MINE_SUPPLY_S_MAX-BG_AV_OBJECT_MINE_SUPPLY_S_MIN); i++) + { + if (!AddObject(BG_AV_OBJECT_MINE_SUPPLY_S_MIN+i,BG_AV_OBJECTID_MINE_S,BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][0],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][1],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][2],BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3], 0, 0, sin(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_MINE_SUPPLY_S_MIN+i][3]/2),RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some mine supplies BattleGround not created!7.6.%i",i); + return false; + } + } + + if (!AddObject(BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE, BG_AV_OBJECTID_BANNER_SNOWFALL_N ,BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][0],BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][1],BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][2],BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3],0,0,sin(BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3]/2), cos(BG_AV_ObjectPos[BG_AV_NODES_SNOWFALL_GRAVE][3]/2), RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!8"); + return false; + } + for (uint8 i = 0; i < 4; i++) + { + if (!AddObject(BG_AV_OBJECT_SNOW_EYECANDY_A+i, BG_AV_OBJECTID_SNOWFALL_CANDY_A ,BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],0,0,sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_PA+i, BG_AV_OBJECTID_SNOWFALL_CANDY_PA ,BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],0,0,sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_H+i, BG_AV_OBJECTID_SNOWFALL_CANDY_H ,BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],0,0,sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY) + || !AddObject(BG_AV_OBJECT_SNOW_EYECANDY_PH+i, BG_AV_OBJECTID_SNOWFALL_CANDY_PH ,BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][0],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][1],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][2],BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3],0,0,sin(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), cos(BG_AV_ObjectPos[AV_OPLACE_SNOW_1+i][3]/2), RESPAWN_ONE_DAY)) + { + sLog.outError("BatteGroundAV: Failed to spawn some object BattleGround not created!9.%i",i); + return false; + } + } + + uint16 i; + sLog.outDebug("Alterac Valley: entering state STATUS_WAIT_JOIN ..."); + // Initial Nodes + for (i = 0; i < BG_AV_OBJECT_MAX; i++) + SpawnBGObject(i, RESPAWN_ONE_DAY); + for (i = BG_AV_OBJECT_FLAG_A_FIRSTAID_STATION; i <= BG_AV_OBJECT_FLAG_A_STONEHEART_GRAVE ; i++){ + SpawnBGObject(BG_AV_OBJECT_AURA_A_FIRSTAID_STATION+3*i,RESPAWN_IMMEDIATELY); + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + } + for (i = BG_AV_OBJECT_FLAG_A_DUNBALDAR_SOUTH; i <= BG_AV_OBJECT_FLAG_A_STONEHEART_BUNKER ; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + for (i = BG_AV_OBJECT_FLAG_H_ICEBLOOD_GRAVE; i <= BG_AV_OBJECT_FLAG_H_FROSTWOLF_WTOWER ; i++){ + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + if (i <= BG_AV_OBJECT_FLAG_H_FROSTWOLF_HUT) + SpawnBGObject(BG_AV_OBJECT_AURA_H_FIRSTAID_STATION+3*GetNodeThroughObject(i),RESPAWN_IMMEDIATELY); + } + for (i = BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH; i <= BG_AV_OBJECT_TFLAG_A_STONEHEART_BUNKER; i+=2) + { + SpawnBGObject(i, RESPAWN_IMMEDIATELY); //flag + SpawnBGObject(i+16, RESPAWN_IMMEDIATELY); //aura + } + for (i = BG_AV_OBJECT_TFLAG_H_ICEBLOOD_TOWER; i <= BG_AV_OBJECT_TFLAG_H_FROSTWOLF_WTOWER; i+=2) + { + SpawnBGObject(i, RESPAWN_IMMEDIATELY); //flag + SpawnBGObject(i+16, RESPAWN_IMMEDIATELY); //aura + } + //snowfall and the doors + for (i = BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE; i <= BG_AV_OBJECT_DOOR_A; i++) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_AV_OBJECT_AURA_N_SNOWFALL_GRAVE,RESPAWN_IMMEDIATELY); + + //creatures + sLog.outDebug("BG_AV start poputlating nodes"); + for (BG_AV_Nodes i= BG_AV_NODES_FIRSTAID_STATION; i < BG_AV_NODES_MAX; ++i) + { + if (m_Nodes[i].Owner) + PopulateNode(i); + } + //all creatures which don't get despawned through the script are static + sLog.outDebug("BG_AV: start spawning static creatures"); + for (i=0; i < AV_STATICCPLACE_MAX; i++) + AddAVCreature(0,i+AV_CPLACE_MAX); + //mainspiritguides: + sLog.outDebug("BG_AV: start spawning spiritguides creatures"); + AddSpiritGuide(7, BG_AV_CreaturePos[7][0], BG_AV_CreaturePos[7][1], BG_AV_CreaturePos[7][2], BG_AV_CreaturePos[7][3], ALLIANCE); + AddSpiritGuide(8, BG_AV_CreaturePos[8][0], BG_AV_CreaturePos[8][1], BG_AV_CreaturePos[8][2], BG_AV_CreaturePos[8][3], HORDE); + //spawn the marshals (those who get deleted, if a tower gets destroyed) + sLog.outDebug("BG_AV: start spawning marshal creatures"); + for (i=AV_NPC_A_MARSHAL_SOUTH; i <= AV_NPC_H_MARSHAL_WTOWER; i++) + AddAVCreature(i,AV_CPLACE_A_MARSHAL_SOUTH+(i-AV_NPC_A_MARSHAL_SOUTH)); + AddAVCreature(AV_NPC_HERALD,AV_CPLACE_HERALD); + return true; +} + +const char* BattleGroundAV::GetNodeName(BG_AV_Nodes node) +{ + switch (node) + { + case BG_AV_NODES_FIRSTAID_STATION: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_STORM_AID); + case BG_AV_NODES_DUNBALDAR_SOUTH: return GetTrinityString(LANG_BG_AV_NODE_TOWER_DUN_S); + case BG_AV_NODES_DUNBALDAR_NORTH: return GetTrinityString(LANG_BG_AV_NODE_TOWER_DUN_N); + case BG_AV_NODES_STORMPIKE_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_STORMPIKE); + case BG_AV_NODES_ICEWING_BUNKER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_ICEWING); + case BG_AV_NODES_STONEHEART_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_STONE); + case BG_AV_NODES_STONEHEART_BUNKER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_STONE); + case BG_AV_NODES_SNOWFALL_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_SNOW); + case BG_AV_NODES_ICEBLOOD_TOWER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_ICE); + case BG_AV_NODES_ICEBLOOD_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_ICE); + case BG_AV_NODES_TOWER_POINT: return GetTrinityString(LANG_BG_AV_NODE_TOWER_POINT); + case BG_AV_NODES_FROSTWOLF_GRAVE: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_FROST); + case BG_AV_NODES_FROSTWOLF_ETOWER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_FROST_E); + case BG_AV_NODES_FROSTWOLF_WTOWER: return GetTrinityString(LANG_BG_AV_NODE_TOWER_FROST_W); + case BG_AV_NODES_FROSTWOLF_HUT: return GetTrinityString(LANG_BG_AV_NODE_GRAVE_FROST_HUT); + default: + { + sLog.outError("tried to get name for node %u%",node); + return "Unknown"; + break; + } + } +} + +void BattleGroundAV::AssaultNode(BG_AV_Nodes node, uint16 team) +{ + if (m_Nodes[node].TotalOwner == team) + { + sLog.outCrash("Assaulting team is TotalOwner of node"); + assert (false); + } + if (m_Nodes[node].Owner == team) + { + sLog.outCrash("Assaulting team is owner of node"); + assert (false); + } + if (m_Nodes[node].State == POINT_DESTROYED) + { + sLog.outCrash("Destroyed node is being assaulted"); + assert (false); + } + if (m_Nodes[node].State == POINT_ASSAULTED && m_Nodes[node].TotalOwner) //only assault an assaulted node if no totalowner exists + { + sLog.outCrash("Assault on an not assaulted node with total owner"); + assert (false); + } + //the timer gets another time, if the previous owner was 0 == Neutral + m_Nodes[node].Timer = (m_Nodes[node].PrevOwner)? BG_AV_CAPTIME : BG_AV_SNOWFALL_FIRSTCAP; + m_Nodes[node].PrevOwner = m_Nodes[node].Owner; + m_Nodes[node].Owner = team; + m_Nodes[node].PrevState = m_Nodes[node].State; + m_Nodes[node].State = POINT_ASSAULTED; +} + +void BattleGroundAV::DestroyNode(BG_AV_Nodes node) +{ + assert(m_Nodes[node].State == POINT_ASSAULTED); + + m_Nodes[node].TotalOwner = m_Nodes[node].Owner; + m_Nodes[node].PrevOwner = m_Nodes[node].Owner; + m_Nodes[node].PrevState = m_Nodes[node].State; + m_Nodes[node].State = (m_Nodes[node].Tower)? POINT_DESTROYED : POINT_CONTROLED; + m_Nodes[node].Timer = 0; +} + +void BattleGroundAV::InitNode(BG_AV_Nodes node, uint16 team, bool tower) +{ + m_Nodes[node].TotalOwner = team; + m_Nodes[node].Owner = team; + m_Nodes[node].PrevOwner = 0; + m_Nodes[node].State = POINT_CONTROLED; + m_Nodes[node].PrevState = m_Nodes[node].State; + m_Nodes[node].State = POINT_CONTROLED; + m_Nodes[node].Timer = 0; + m_Nodes[node].Tower = tower; +} + +void BattleGroundAV::DefendNode(BG_AV_Nodes node, uint16 team) +{ + assert(m_Nodes[node].TotalOwner == team); + assert(m_Nodes[node].Owner != team); + assert(m_Nodes[node].State != POINT_CONTROLED && m_Nodes[node].State != POINT_DESTROYED); + m_Nodes[node].PrevOwner = m_Nodes[node].Owner; + m_Nodes[node].Owner = team; + m_Nodes[node].PrevState = m_Nodes[node].State; + m_Nodes[node].State = POINT_CONTROLED; + m_Nodes[node].Timer = 0; +} + +void BattleGroundAV::ResetBGSubclass() +{ + m_MaxLevel=0; + for (uint8 i=0; i<2; i++) //forloop for both teams (it just make 0 == alliance and 1 == horde also for both mines 0=north 1=south + { + for (uint8 j=0; j<9; j++) + m_Team_QuestStatus[i][j]=0; + m_Team_Scores[i]=BG_AV_SCORE_INITIAL_POINTS; + m_IsInformedNearVictory[i]=false; + m_CaptainAlive[i] = true; + m_CaptainBuffTimer[i] = 120000 + urand(0,4)* 60; //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes TODO get the right times + m_Mine_Owner[i] = AV_NEUTRAL_TEAM; + m_Mine_PrevOwner[i] = m_Mine_Owner[i]; + } + for (BG_AV_Nodes i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_STONEHEART_GRAVE; ++i) //alliance graves + InitNode(i,ALLIANCE,false); + for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) //alliance towers + InitNode(i,ALLIANCE,true); + for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_GRAVE; i <= BG_AV_NODES_FROSTWOLF_HUT; ++i) //horde graves + InitNode(i,HORDE,false); + for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) //horde towers + InitNode(i,HORDE,true); + InitNode(BG_AV_NODES_SNOWFALL_GRAVE,AV_NEUTRAL_TEAM,false); //give snowfall neutral owner + + m_Mine_Timer=AV_MINE_TICK_TIMER; + for (uint16 i = 0; i < AV_CPLACE_MAX+AV_STATICCPLACE_MAX; i++) + if (m_BgCreatures[i]) + DelCreature(i); + +} + + diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundAV.h b/src/server/game/BattleGrounds/Zones/BattleGroundAV.h new file mode 100644 index 00000000000..6d95c7bbc5d --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundAV.h @@ -0,0 +1,1614 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDAV_H +#define __BATTLEGROUNDAV_H + +class BattleGround; + +#define LANG_BG_AV_A_CAPTAIN_BUFF "Begone. Uncouth scum! The Alliance shall prevail in Alterac Valley!" +#define LANG_BG_AV_H_CAPTAIN_BUFF "Now is the time to attack! For the Horde!" +#define LANG_BG_AV_S_MINE_BOSS_CLAIMS "Snivvle is here! Snivvle claims the Coldtooth Mine!" + +#define BG_AV_CAPTIME 240000 //4:00 +#define BG_AV_SNOWFALL_FIRSTCAP 300000 //5:00 but i also have seen 4:05 + +#define BG_AV_SCORE_INITIAL_POINTS 600 +#define SEND_MSG_NEAR_LOSE 120 + +#define BG_AV_KILL_BOSS 4 +#define BG_AV_REP_BOSS 350 + +#define BG_AV_KILL_CAPTAIN 3 +#define BG_AV_REP_CAPTAIN 125 +#define BG_AV_RES_CAPTAIN 100 + +#define BG_AV_KILL_TOWER 3 +#define BG_AV_REP_TOWER 12 +#define BG_AV_RES_TOWER 75 + +#define BG_AV_GET_COMMANDER 1 //for a safely returned wingcommander +//bonushonor at the end +#define BG_AV_KILL_SURVIVING_TOWER 2 +#define BG_AV_REP_SURVIVING_TOWER 12 + +#define BG_AV_KILL_SURVIVING_CAPTAIN 2 +#define BG_AV_REP_SURVIVING_CAPTAIN 125 + +enum BG_AV_Sounds +{ //TODO: get out if there comes a sound when neutral team captures mine + +/* +8212: + alliance grave assault + alliance tower assault + drek "mlanzenabschaum! In meiner Burg?! Toetet sie all" - nicht immer der sound +8333: + galv "sterbt fuer euch ist kein platz hier" + +8332: + bal "Verschwinde, dreckiger Abschaum! Die Allianz wird im Alteractal " +8174: + horde tower assault + horde grave assault + van "es Sturmlanzenklans, euer General wird angegriffen! Ich fordere Unterst" +8173: + ally grave capture/defend + tower destroy + mine capture + ally wins +8192: + ally tower destroy(only iceblood - found a bug^^) + ally tower defend + horde tower defend +8213 +horde: + grave defend/capture + tower destroy + mine capture + horde wins + */ + + AV_SOUND_NEAR_VICTORY = 8456, //not confirmed yet + + AV_SOUND_ALLIANCE_ASSAULTS = 8212, //tower,grave + enemy boss if someone tries to attack him + AV_SOUND_HORDE_ASSAULTS = 8174, + AV_SOUND_ALLIANCE_GOOD = 8173, //if something good happens for the team: wins(maybe only through killing the boss), captures mine or grave, destroys tower and defends grave + AV_SOUND_HORDE_GOOD = 8213, + AV_SOUND_BOTH_TOWER_DEFEND = 8192, + + AV_SOUND_ALLIANCE_CAPTAIN = 8232, //gets called when someone attacks them and at the beginning after 3min+rand(x)*10sec (maybe buff) + AV_SOUND_HORDE_CAPTAIN = 8333, + +}; + +enum BG_AV_OTHER_VALUES +{ + AV_STATICCPLACE_MAX = 123, + 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_NEUTRAL_TEAM = 0 //this is the neutral owner of snowfall +}; +enum BG_AV_ObjectIds +{ + //cause the mangos-system is a bit different, we don't use the right go-ids for every node.. if we want to be 100% like another big server, we must take one object for every node + //snowfall 4flags as eyecandy 179424 (alliance neutral) + //Banners - stolen from battleground_AB.h ;-) + BG_AV_OBJECTID_BANNER_A = 178925, // can only be used by horde + BG_AV_OBJECTID_BANNER_H = 178943, // can only be used by alliance + BG_AV_OBJECTID_BANNER_CONT_A = 178940, // can only be used by horde + BG_AV_OBJECTID_BANNER_CONT_H = 179435, // can only be used by alliance + + BG_AV_OBJECTID_BANNER_A_B = 178365, + BG_AV_OBJECTID_BANNER_H_B = 178364, + BG_AV_OBJECTID_BANNER_CONT_A_B = 179286, + BG_AV_OBJECTID_BANNER_CONT_H_B = 179287, + BG_AV_OBJECTID_BANNER_SNOWFALL_N = 180418, + + //snowfall eyecandy banner: + BG_AV_OBJECTID_SNOWFALL_CANDY_A = 179044, + BG_AV_OBJECTID_SNOWFALL_CANDY_PA = 179424, + BG_AV_OBJECTID_SNOWFALL_CANDY_H = 179064, + BG_AV_OBJECTID_SNOWFALL_CANDY_PH = 179425, + + //banners on top of towers: + BG_AV_OBJECTID_TOWER_BANNER_A = 178927, //[PH] Alliance A1 Tower Banner BIG + BG_AV_OBJECTID_TOWER_BANNER_H = 178955, //[PH] Horde H1 Tower Banner BIG + BG_AV_OBJECTID_TOWER_BANNER_PA = 179446, //[PH] Alliance H1 Tower Pre-Banner BIG + BG_AV_OBJECTID_TOWER_BANNER_PH = 179436, //[PH] Horde A1 Tower Pre-Banner BIG + + //Auras + BG_AV_OBJECTID_AURA_A = 180421, + BG_AV_OBJECTID_AURA_H = 180422, + BG_AV_OBJECTID_AURA_N = 180423, + BG_AV_OBJECTID_AURA_A_S = 180100, + BG_AV_OBJECTID_AURA_H_S = 180101, + BG_AV_OBJECTID_AURA_N_S = 180102, + + BG_AV_OBJECTID_GATE_A = 180424, + BG_AV_OBJECTID_GATE_H = 180424, + + //mine supplies + BG_AV_OBJECTID_MINE_N = 178785, + BG_AV_OBJECTID_MINE_S = 178784, + + BG_AV_OBJECTID_FIRE = 179065, + BG_AV_OBJECTID_SMOKE = 179066 +}; + +enum BG_AV_Nodes +{ + BG_AV_NODES_FIRSTAID_STATION = 0, + BG_AV_NODES_STORMPIKE_GRAVE = 1, + BG_AV_NODES_STONEHEART_GRAVE = 2, + BG_AV_NODES_SNOWFALL_GRAVE = 3, + BG_AV_NODES_ICEBLOOD_GRAVE = 4, + BG_AV_NODES_FROSTWOLF_GRAVE = 5, + BG_AV_NODES_FROSTWOLF_HUT = 6, + BG_AV_NODES_DUNBALDAR_SOUTH = 7, + BG_AV_NODES_DUNBALDAR_NORTH = 8, + BG_AV_NODES_ICEWING_BUNKER = 9, + BG_AV_NODES_STONEHEART_BUNKER = 10, + BG_AV_NODES_ICEBLOOD_TOWER = 11, + BG_AV_NODES_TOWER_POINT = 12, + BG_AV_NODES_FROSTWOLF_ETOWER = 13, + BG_AV_NODES_FROSTWOLF_WTOWER = 14, + + BG_AV_NODES_MAX = 15 +}; + +enum BG_AV_ObjectTypes +{ + BG_AV_OBJECT_FLAG_A_FIRSTAID_STATION = 0, + BG_AV_OBJECT_FLAG_A_STORMPIKE_GRAVE = 1, + BG_AV_OBJECT_FLAG_A_STONEHEART_GRAVE = 2, + BG_AV_OBJECT_FLAG_A_SNOWFALL_GRAVE = 3, + BG_AV_OBJECT_FLAG_A_ICEBLOOD_GRAVE = 4, + BG_AV_OBJECT_FLAG_A_FROSTWOLF_GRAVE = 5, + BG_AV_OBJECT_FLAG_A_FROSTWOLF_HUT = 6, + BG_AV_OBJECT_FLAG_A_DUNBALDAR_SOUTH = 7, + BG_AV_OBJECT_FLAG_A_DUNBALDAR_NORTH = 8, + BG_AV_OBJECT_FLAG_A_ICEWING_BUNKER = 9, + BG_AV_OBJECT_FLAG_A_STONEHEART_BUNKER = 10, + + BG_AV_OBJECT_FLAG_C_A_FIRSTAID_STATION = 11, + BG_AV_OBJECT_FLAG_C_A_STORMPIKE_GRAVE = 12, + BG_AV_OBJECT_FLAG_C_A_STONEHEART_GRAVE = 13, + BG_AV_OBJECT_FLAG_C_A_SNOWFALL_GRAVE = 14, + BG_AV_OBJECT_FLAG_C_A_ICEBLOOD_GRAVE = 15, + BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_GRAVE = 16, + BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_HUT = 17, + BG_AV_OBJECT_FLAG_C_A_ICEBLOOD_TOWER = 18, + BG_AV_OBJECT_FLAG_C_A_TOWER_POINT = 19, + BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_ETOWER = 20, + BG_AV_OBJECT_FLAG_C_A_FROSTWOLF_WTOWER = 21, + + BG_AV_OBJECT_FLAG_C_H_FIRSTAID_STATION = 22, + BG_AV_OBJECT_FLAG_C_H_STORMPIKE_GRAVE = 23, + BG_AV_OBJECT_FLAG_C_H_STONEHEART_GRAVE = 24, + BG_AV_OBJECT_FLAG_C_H_SNOWFALL_GRAVE = 25, + BG_AV_OBJECT_FLAG_C_H_ICEBLOOD_GRAVE = 26, + BG_AV_OBJECT_FLAG_C_H_FROSTWOLF_GRAVE = 27, + BG_AV_OBJECT_FLAG_C_H_FROSTWOLF_HUT = 28, + BG_AV_OBJECT_FLAG_C_H_DUNBALDAR_SOUTH = 29, + BG_AV_OBJECT_FLAG_C_H_DUNBALDAR_NORTH = 30, + BG_AV_OBJECT_FLAG_C_H_ICEWING_BUNKER = 31, + BG_AV_OBJECT_FLAG_C_H_STONEHEART_BUNKER = 32, + + BG_AV_OBJECT_FLAG_H_FIRSTAID_STATION = 33, + BG_AV_OBJECT_FLAG_H_STORMPIKE_GRAVE = 34, + BG_AV_OBJECT_FLAG_H_STONEHEART_GRAVE = 35, + BG_AV_OBJECT_FLAG_H_SNOWFALL_GRAVE = 36, + BG_AV_OBJECT_FLAG_H_ICEBLOOD_GRAVE = 37, + BG_AV_OBJECT_FLAG_H_FROSTWOLF_GRAVE = 38, + BG_AV_OBJECT_FLAG_H_FROSTWOLF_HUT = 39, + BG_AV_OBJECT_FLAG_H_ICEBLOOD_TOWER = 40, + BG_AV_OBJECT_FLAG_H_TOWER_POINT = 41, + BG_AV_OBJECT_FLAG_H_FROSTWOLF_ETOWER = 42, + BG_AV_OBJECT_FLAG_H_FROSTWOLF_WTOWER = 43, + + BG_AV_OBJECT_FLAG_N_SNOWFALL_GRAVE = 44, + + BG_AV_OBJECT_DOOR_H = 45, + BG_AV_OBJECT_DOOR_A = 46, +//auras for graveyards (3auras per graveyard neutral,alliance,horde) + BG_AV_OBJECT_AURA_N_FIRSTAID_STATION = 47, + BG_AV_OBJECT_AURA_A_FIRSTAID_STATION = 48, + BG_AV_OBJECT_AURA_H_FIRSTAID_STATION = 49, + BG_AV_OBJECT_AURA_N_STORMPIKE_GRAVE = 50, + BG_AV_OBJECT_AURA_A_STORMPIKE_GRAVE = 51, + BG_AV_OBJECT_AURA_H_STORMPIKE_GRAVE = 52, + BG_AV_OBJECT_AURA_N_STONEHEART_GRAVE = 53, + BG_AV_OBJECT_AURA_A_STONEHEART_GRAVE = 54, + BG_AV_OBJECT_AURA_H_STONEHEART_GRAVE = 55, + BG_AV_OBJECT_AURA_N_SNOWFALL_GRAVE = 56, + BG_AV_OBJECT_AURA_A_SNOWFALL_GRAVE = 57, + BG_AV_OBJECT_AURA_H_SNOWFALL_GRAVE = 58, + BG_AV_OBJECT_AURA_N_ICEBLOOD_GRAVE = 59, + BG_AV_OBJECT_AURA_A_ICEBLOOD_GRAVE = 60, + BG_AV_OBJECT_AURA_H_ICEBLOOD_GRAVE = 61, + BG_AV_OBJECT_AURA_N_FROSTWOLF_GRAVE = 62, + BG_AV_OBJECT_AURA_A_FROSTWOLF_GRAVE = 63, + BG_AV_OBJECT_AURA_H_FROSTWOLF_GRAVE = 64, + BG_AV_OBJECT_AURA_N_FROSTWOLF_HUT = 65, + BG_AV_OBJECT_AURA_A_FROSTWOLF_HUT = 66, + BG_AV_OBJECT_AURA_H_FROSTWOLF_HUT = 67, + + //big flags on top of towers 2 flags on each (contested,(alliance | horde)) + 2 auras + BG_AV_OBJECT_TFLAG_A_DUNBALDAR_SOUTH = 67, + BG_AV_OBJECT_TFLAG_H_DUNBALDAR_SOUTH = 68, + BG_AV_OBJECT_TFLAG_A_DUNBALDAR_NORTH = 69, + BG_AV_OBJECT_TFLAG_H_DUNBALDAR_NORTH = 70, + BG_AV_OBJECT_TFLAG_A_ICEWING_BUNKER = 71, + BG_AV_OBJECT_TFLAG_H_ICEWING_BUNKER = 72, + BG_AV_OBJECT_TFLAG_A_STONEHEART_BUNKER = 73, + BG_AV_OBJECT_TFLAG_H_STONEHEART_BUNKER = 74, + BG_AV_OBJECT_TFLAG_A_ICEBLOOD_TOWER = 75, + BG_AV_OBJECT_TFLAG_H_ICEBLOOD_TOWER = 76, + BG_AV_OBJECT_TFLAG_A_TOWER_POINT = 77, + BG_AV_OBJECT_TFLAG_H_TOWER_POINT = 78, + BG_AV_OBJECT_TFLAG_A_FROSTWOLF_ETOWER = 79, + BG_AV_OBJECT_TFLAG_H_FROSTWOLF_ETOWER = 80, + BG_AV_OBJECT_TFLAG_A_FROSTWOLF_WTOWER = 81, + BG_AV_OBJECT_TFLAG_H_FROSTWOLF_WTOWER = 82, + BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH = 83, + BG_AV_OBJECT_TAURA_H_DUNBALDAR_SOUTH = 84, + BG_AV_OBJECT_TAURA_A_DUNBALDAR_NORTH = 85, + BG_AV_OBJECT_TAURA_H_DUNBALDAR_NORTH = 86, + BG_AV_OBJECT_TAURA_A_ICEWING_BUNKER = 87, + BG_AV_OBJECT_TAURA_H_ICEWING_BUNKER = 88, + BG_AV_OBJECT_TAURA_A_STONEHEART_BUNKER = 89, + BG_AV_OBJECT_TAURA_H_STONEHEART_BUNKER = 90, + BG_AV_OBJECT_TAURA_A_ICEBLOOD_TOWER = 91, + BG_AV_OBJECT_TAURA_H_ICEBLOOD_TOWER = 92, + BG_AV_OBJECT_TAURA_A_TOWER_POINT = 93, + BG_AV_OBJECT_TAURA_H_TOWER_POINT = 94, + BG_AV_OBJECT_TAURA_A_FROSTWOLF_ETOWER = 95, + BG_AV_OBJECT_TAURA_H_FROSTWOLF_ETOWER = 96, + BG_AV_OBJECT_TAURA_A_FROSTWOLF_WTOWER = 97, + BG_AV_OBJECT_TAURA_H_FROSTWOLF_WTOWER = 98, + + BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH = 99, + BG_AV_OBJECT_BURN_DUNBALDAR_NORTH = 109, + BG_AV_OBJECT_BURN_ICEWING_BUNKER = 119, + BG_AV_OBJECT_BURN_STONEHEART_BUNKER = 129, + BG_AV_OBJECT_BURN_ICEBLOOD_TOWER = 139, + BG_AV_OBJECT_BURN_TOWER_POINT = 149, + BG_AV_OBJECT_BURN_FROSTWOLF_ETWOER = 159, + BG_AV_OBJECT_BURN_FROSTWOLF_WTOWER = 169, + BG_AV_OBJECT_BURN_BUILDING_ALLIANCE = 179, + BG_AV_OBJECT_BURN_BUILDING_HORDE = 189, + BG_AV_OBJECT_SNOW_EYECANDY_A = 199, + BG_AV_OBJECT_SNOW_EYECANDY_PA = 203, + BG_AV_OBJECT_SNOW_EYECANDY_H = 207, + BG_AV_OBJECT_SNOW_EYECANDY_PH = 211, + BG_AV_OBJECT_MINE_SUPPLY_N_MIN = 215, + BG_AV_OBJECT_MINE_SUPPLY_N_MAX = 224, + BG_AV_OBJECT_MINE_SUPPLY_S_MIN = 225, + BG_AV_OBJECT_MINE_SUPPLY_S_MAX = 236, + + BG_AV_OBJECT_MAX = 237 +}; + +enum BG_AV_OBJECTS +{ + AV_OPLACE_FIRSTAID_STATION = 0, + AV_OPLACE_STORMPIKE_GRAVE = 1, + AV_OPLACE_STONEHEART_GRAVE = 2, + AV_OPLACE_SNOWFALL_GRAVE = 3, + AV_OPLACE_ICEBLOOD_GRAVE = 4, + AV_OPLACE_FROSTWOLF_GRAVE = 5, + AV_OPLACE_FROSTWOLF_HUT = 6, + AV_OPLACE_DUNBALDAR_SOUTH = 7, + AV_OPLACE_DUNBALDAR_NORTH = 8, + AV_OPLACE_ICEWING_BUNKER = 9, + AV_OPLACE_STONEHEART_BUNKER = 10, + AV_OPLACE_ICEBLOOD_TOWER = 11, + AV_OPLACE_TOWER_POINT = 12, + AV_OPLACE_FROSTWOLF_ETOWER = 13, + AV_OPLACE_FROSTWOLF_WTOWER = 14, + AV_OPLACE_BIGBANNER_DUNBALDAR_SOUTH = 15, + AV_OPLACE_BIGBANNER_DUNBALDAR_NORTH = 16, + AV_OPLACE_BIGBANNER_ICEWING_BUNKER = 17, + AV_OPLACE_BIGBANNER_STONEHEART_BUNKER = 18, + AV_OPLACE_BIGBANNER_ICEBLOOD_TOWER = 19, + AV_OPLACE_BIGBANNER_TOWER_POINT = 20, + AV_OPLACE_BIGBANNER_FROSTWOLF_ETOWER = 21, + AV_OPLACE_BIGBANNER_FROSTWOLF_WTOWER = 22, + + AV_OPLACE_BURN_DUNBALDAR_SOUTH = 23, + AV_OPLACE_BURN_DUNBALDAR_NORTH = 33, + AV_OPLACE_BURN_ICEWING_BUNKER = 43, + AV_OPLACE_BURN_STONEHEART_BUNKER = 53, + AV_OPLACE_BURN_ICEBLOOD_TOWER = 63, + AV_OPLACE_BURN_TOWER_POINT = 73, + AV_OPLACE_BURN_FROSTWOLF_ETOWER = 83, + AV_OPLACE_BURN_FROSTWOLF_WTOWER = 93, + AV_OPLACE_BURN_BUILDING_A = 103, + AV_OPLACE_BURN_BUILDING_H = 113, + AV_OPLACE_SNOW_1 = 123, + AV_OPLACE_SNOW_2 = 124, + AV_OPLACE_SNOW_3 = 125, + AV_OPLACE_SNOW_4 = 126, + AV_OPLACE_MINE_SUPPLY_N_MIN = 127, + AV_OPLACE_MINE_SUPPLY_N_MAX = 136, + AV_OPLACE_MINE_SUPPLY_S_MIN = 137, + AV_OPLACE_MINE_SUPPLY_S_MAX = 148, + + AV_OPLACE_MAX = 149 +}; +const float BG_AV_ObjectPos[AV_OPLACE_MAX][4] = { + {638.592f,-32.422f,46.0608f,-1.62316f },//firstaid station + {669.007f,-294.078f,30.2909f,2.77507f },//stormpike + {77.8013f,-404.7f,46.7549f,-0.872665f },//stone grave + {-202.581f,-112.73f,78.4876f,-0.715585f },//snowfall + {-611.962f,-396.17f,60.8351f,2.53682f}, //iceblood grave + {-1082.45f,-346.823f,54.9219f,-1.53589f },//frostwolf grave + {-1402.21f,-307.431f,89.4424f,0.191986f },//frostwolf hut + {553.779f,-78.6566f,51.9378f,-1.22173f }, //dunnbaldar south + {674.001f,-143.125f,63.6615f,0.994838f }, //dunbaldar north + {203.281f,-360.366f,56.3869f,-0.925024f }, //icew + {-152.437f,-441.758f,40.3982f,-1.95477f }, //stone + {-571.88f,-262.777f,75.0087f,-0.802851f }, //ice tower + {-768.907f,-363.71f,90.8949f,1.07991f}, //tower point + {-1302.9f,-316.981f,113.867f,2.00713f }, //frostwolf etower + {-1297.5f,-266.767f,114.15f,3.31044f}, //frostwolf wtower + //bigbanner: + {555.848f,-84.4151f,64.4397f,3.12414f }, //duns + {679.339f,-136.468f,73.9626f,-2.16421f }, //dunn + {208.973f,-365.971f,66.7409f,-0.244346f }, //icew + {-155.832f,-449.401f,52.7306f,0.610865f }, //stone + {-572.329f,-262.476f,88.6496f,-0.575959f }, //icetower + {-768.199f,-363.105f,104.537f,0.10472f }, //towerp + {-1302.84f,-316.582f,127.516f,0.122173f }, //etower + {-1297.87f,-266.762f,127.796f,0.0698132f }, //wtower + //burning auras towers have 9*179065 captain-buildings have 5*179066+5*179065 + //dunns + {562.632f,-88.1815f,61.993f,0.383972f }, + {562.523f,-74.5028f,37.9474f,-0.0523599f }, + {558.097f,-70.9842f,52.4876f,0.820305f }, + {578.167f,-71.8191f,38.1514f,2.72271f }, + {556.028f,-94.9242f,44.8191f,3.05433f }, + {572.451f,-94.3655f,37.9443f,-1.72788f }, + {549.263f,-79.3645f,44.8191f,0.436332f }, + {543.513f,-94.4006f,52.4819f,0.0349066f }, + {572.149f,-93.7862f,52.5726f,0.541052f }, + {582.162f,-81.2375f,37.9216f,0.0872665f }, + //dunn + {664.797f,-143.65f,64.1784f,-0.453786f}, + {664.505f,-139.452f,49.6696f,-0.0349067f}, + {676.067f,-124.319f,49.6726f,-1.01229f}, + {693.004f,-144.025f,64.1755f,2.44346f}, + {661.175f,-117.691f,49.645f,1.91986f}, + {684.423f,-146.582f,63.6662f,0.994838f}, + {682.791f,-127.769f,62.4155f,1.09956f}, + {674.576f,-147.101f,56.5425f,-1.6057f}, + {655.719f,-126.673f,49.8138f,2.80998f}, + {0,0,0,0}, + //icew + {231.503f,-356.688f,42.3704f,0.296706f}, + {224.989f,-348.175f,42.5607f,1.50098f}, + {205.782f,-351.335f,56.8998f,1.01229f}, + {196.605f,-369.187f,56.3914f,2.46091f}, + {210.619f,-376.938f,49.2677f,2.86234f}, + {209.647f,-352.632f,42.3959f,-0.698132f}, + {220.65f,-368.132f,42.3978f,-0.2618f}, + {224.682f,-374.031f,57.0679f,0.541052f}, + {200.26f,-359.968f,49.2677f,-2.89725f}, + {196.619f,-378.016f,56.9131f,1.01229f}, + //stone + {-155.488f,-437.356f,33.2796f,2.60054f}, + {-163.441f,-454.188f,33.2796f,1.93732f}, + {-143.977f,-445.148f,26.4097f,-1.8675f}, + {-135.764f,-464.708f,26.3823f,2.25147f}, + {-154.076f,-466.929f,41.0636f,-1.8675f}, + {-149.908f,-460.332f,26.4083f,-2.09439f}, + {-151.638f,-439.521f,40.3797f,0.436332f}, + {-131.301f,-454.905f,26.5771f,2.93215f}, + {-171.291f,-444.684f,40.9211f,2.30383f}, + {-143.591f,-439.75f,40.9275f,-1.72788f}, + //iceblood + {-572.667f,-267.923f,56.8542f,2.35619f}, + {-561.021f,-262.689f,68.4589f,1.37881f}, + {-572.538f,-262.649f,88.6197f,1.8326f}, + {-574.77f,-251.45f,74.9422f,-1.18682f}, + {-578.625f,-267.571f,68.4696f,0.506145f}, + {-571.476f,-257.234f,63.3223f,3.10669f}, + {-566.035f,-273.907f,52.9582f,-0.890118f}, + {-580.948f,-259.77f,68.4696f,1.46608f}, + {-568.318f,-267.1f,75.0008f,1.01229f}, + {-559.621f,-268.597f,52.8986f,0.0523599f}, + //towerp + {-776.072f,-368.046f,84.3558f,2.63545f}, + {-777.564f,-368.521f,90.6701f,1.72788f}, + {-765.461f,-357.711f,90.888f,0.314159f}, + {-768.763f,-362.735f,104.612f,1.81514f}, + {-760.356f,-358.896f,84.3558f,2.1293f}, + {-771.967f,-352.838f,84.3484f,1.74533f}, + {-773.333f,-364.653f,79.2351f,-1.64061f}, + {-764.109f,-366.069f,70.0934f,0.383972f}, + {-767.103f,-350.737f,68.7933f,2.80998f}, + {-760.115f,-353.845f,68.8633f,1.79769f}, + //froste + {-1304.87f,-304.525f,91.8366f,-0.680679f}, + {-1301.77f,-310.974f,95.8252f,0.907571f}, + {-1305.58f,-320.625f,102.166f,-0.558505f}, + {-1294.27f,-323.468f,113.893f,-1.67552f}, + {-1302.65f,-317.192f,127.487f,2.30383f}, + {-1293.89f,-313.478f,107.328f,1.6057f}, + {-1312.41f,-312.999f,107.328f,1.5708f}, + {-1311.57f,-308.08f,91.7666f,-1.85005f}, + {-1314.7f,-322.131f,107.36f,0.645772f}, + {-1304.6f,-310.754f,113.859f,-0.401426f}, + //frostw + {-1308.24f,-273.26f,92.0514f,-0.139626f}, + {-1302.26f,-262.858f,95.9269f,0.418879f}, + {-1297.28f,-267.773f,126.756f,2.23402f}, + {-1299.08f,-256.89f,114.108f,-2.44346f}, + {-1303.41f,-268.237f,114.151f,-1.23918f}, + {-1304.43f,-273.682f,107.612f,0.244346f}, + {-1309.53f,-265.951f,92.1418f,-2.49582f}, + {-1295.55f,-263.865f,105.033f,0.925024f}, + {-1294.71f,-281.466f,107.664f,-1.50098f}, + {-1289.69f,-259.521f,107.612f,-2.19912f}, + + //the two buildings of the captains + //alliance + {-64.4987f,-289.33f,33.4616f,-2.82743f}, + {-5.98025f,-326.144f,38.8538f,0}, + {-2.67893f,-306.998f,33.4165f,0}, + {-60.25f,-309.232f,50.2408f,-1.46608f}, + {-48.7941f,-266.533f,47.7916f,2.44346f}, + {-3.40929f,-306.288f,33.34f,0}, + {-48.619f,-266.917f,47.8168f,0}, + {-62.9474f,-286.212f,66.7288f,0}, + {-5.05132f,-325.323f,38.8536f,0}, + {-64.2677f,-289.412f,33.469f,0}, +//horde + {-524.276f,-199.6f,82.8733f,-1.46608f}, + {-518.196f,-173.085f,102.43f,0}, + {-500.732f,-145.358f,88.5337f,2.44346f}, + {-501.084f,-150.784f,80.8506f,0}, + {-518.309f,-163.963f,102.521f,2.96706f}, + {-517.053f,-200.429f,80.759f,0}, + {-514.361f,-163.864f,104.163f,0}, + {-568.04f,-188.707f,81.55f,0}, + {-501.775f,-151.581f,81.2027f,0}, + {-509.975f,-191.652f,83.2978f,0}, + +//snowfall eyecandy + {-191.153f,-129.868f,78.5595f,-1.25664f }, + {-201.282f,-134.319f,78.6753f,-0.942478f }, + {-215.981f,-91.4101f,80.8702f,-1.74533f }, + {-200.465f,-96.418f,79.7587f,1.36136f }, + //mine supplies + //irondeep + {870.899f,-388.434f,61.6406f,-1.22173f}, + {825.214f,-320.174f,63.712f,-2.82743f}, + {837.117f,-452.556f,47.2331f,-3.12414f}, + {869.755f,-448.867f,52.5448f,-0.855212f}, + {949.877f,-458.198f,56.4874f,0.314159f}, + {900.35f,-479.024f,58.3553f,0.122173f}, + {854.449f,-442.255f,50.6589f,0.401426f}, + {886.685f,-442.358f,54.6962f,-1.22173f}, + {817.509f,-457.331f,48.4666f,2.07694f}, + {793.411f,-326.281f,63.1117f,-2.79253f}, + //coldtooth + {-934.212f,-57.3517f,80.277f,-0.0174535f}, + {-916.281f,-36.8579f,77.0227f,0.122173f}, + {-902.73f,-103.868f,75.4378f,-1.58825f}, + {-900.514f,-143.527f,75.9686f,1.8675f}, + {-862.882f,-0.353299f,72.1526f,-2.51327f}, + {-854.932f,-85.9184f,68.6056f,-2.04204f}, + {-851.833f,-118.959f,63.8672f,-0.0698131f}, + {-849.832f,-20.8421f,70.4672f,-1.81514f}, + {-844.25f,-60.0374f,72.1031f,-2.19912f}, + {-820.644f,-136.043f,63.1977f,2.40855f}, + {-947.642f,-208.807f,77.0101f,1.36136f}, + {-951.394f,-193.695f,67.634f,0.802851f} +}; + +const float BG_AV_DoorPositons[2][4] = { + {780.487f, -493.024f, 99.9553f, 3.0976f}, //alliance + {-1375.193f, -538.981f, 55.2824f, 0.72178f} //horde +}; + +//creaturestuff starts here +//is related to BG_AV_CreaturePos +enum BG_AV_CreaturePlace +{ + AV_CPLACE_SPIRIT_STORM_AID = 0, + AV_CPLACE_SPIRIT_STORM_GRAVE = 1, + AV_CPLACE_SPIRIT_STONE_GRAVE = 2, + AV_CPLACE_SPIRIT_SNOWFALL = 3, + AV_CPLACE_SPIRIT_ICE_GRAVE = 4, + AV_CPLACE_SPIRIT_FROSTWOLF = 5, + 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 + AV_CPLACE_DEFENSE_STORM_AID = 9, + AV_CPLACE_DEFEMSE_STORM_GRAVE = 13, + AV_CPLACE_DEFENSE_STONE_GRAVE = 17, + AV_CPLACE_DEFENSE_SNOWFALL = 21, + AV_CPLACE_DEFENSE_FROSTWOLF = 25, + AV_CPLACE_DEFENSE_ICE_GRAVE = 29, + AV_CPLACE_DEFENSE_FROST_HUT = 33, + + AV_CPLACE_DEFENSE_DUN_S = 37, + AV_CPLACE_DEFENSE_DUN_N = 41, + AV_CPLACE_DEFENSE_ICEWING = 45, + AV_CPLACE_DEFENSE_STONE_TOWER = 49, + AV_CPLACE_DEFENSE_ICE_TOWER = 53, + AV_CPLACE_DEFENSE_TOWERPOINT = 57, + AV_CPLACE_DEFENSE_FROST_E = 61, + AV_CPLACE_DEFENSE_FROST_t = 65, + + AV_CPLACE_A_MARSHAL_SOUTH = 69, + AV_CPLACE_A_MARSHAL_NORTH = 70, + AV_CPLACE_A_MARSHAL_ICE = 71, + AV_CPLACE_A_MARSHAL_STONE = 72, + AV_CPLACE_H_MARSHAL_ICE = 73, + AV_CPLACE_H_MARSHAL_TOWER = 74, + AV_CPLACE_H_MARSHAL_ETOWER = 75, + AV_CPLACE_H_MARSHAL_WTOWER = 76, + //irondeep + //miner: + AV_CPLACE_MINE_N_1_MIN = 77, + AV_CPLACE_MINE_N_1_MAX = 136, + //special types + AV_CPLACE_MINE_N_2_MIN = 137, + AV_CPLACE_MINE_N_2_MAX = 192, + //boss + AV_CPLACE_MINE_N_3 = 193, + //coldtooth + //miner: + AV_CPLACE_MINE_S_1_MIN = 194, + AV_CPLACE_MINE_S_1_MAX = 250, + //special types + AV_CPLACE_MINE_S_2_MIN = 251, + AV_CPLACE_MINE_S_2_MAX = 289, + //vermin + AV_CPLACE_MINE_S_S_MIN = 290, + AV_CPLACE_MINE_S_S_MAX = 299, + //boss + AV_CPLACE_MINE_S_3 = 300, + + //herald + AV_CPLACE_HERALD = 301, + + //node aura triggers + AV_CPLACE_TRIGGER01 = 302, + AV_CPLACE_TRIGGER02 = 303, + AV_CPLACE_TRIGGER03 = 304, + AV_CPLACE_TRIGGER04 = 305, + AV_CPLACE_TRIGGER05 = 306, + AV_CPLACE_TRIGGER06 = 307, + AV_CPLACE_TRIGGER07 = 308, + AV_CPLACE_TRIGGER08 = 309, + AV_CPLACE_TRIGGER09 = 310, + AV_CPLACE_TRIGGER10 = 311, + AV_CPLACE_TRIGGER11 = 312, + AV_CPLACE_TRIGGER12 = 313, + AV_CPLACE_TRIGGER13 = 314, + AV_CPLACE_TRIGGER14 = 315, + AV_CPLACE_TRIGGER15 = 316, + + //boss,captain triggers + AV_CPLACE_TRIGGER16 = 317, + AV_CPLACE_TRIGGER17 = 318, + AV_CPLACE_TRIGGER18 = 319, + AV_CPLACE_TRIGGER19 = 320, + + AV_CPLACE_MAX = 321 +}; + +//x, y, z, o +const float BG_AV_CreaturePos[AV_CPLACE_MAX][4] = { + //spiritguides + {643.000000f,44.000000f,69.740196f,-0.001854f}, + {676.000000f,-374.000000f,30.000000f,-0.001854f}, + {73.417755f,-496.433105f,48.731918f,-0.001854f}, + {-157.409195f,31.206272f,77.050598f,-0.001854f}, + {-531.217834f,-405.231384f,49.551376f,-0.001854f}, + {-1090.476807f,-253.308670f,57.672371f,-0.001854f}, + {-1496.065063f,-333.338409f,101.134804f,-0.001854f}, + {873.001770f,-491.283630f,96.541931f,-0.001854f}, + {-1437.670044f,-610.088989f,51.161900f,-0.001854f}, + //grave + //firstaid + {635.17f,-29.5594f,46.5056f,4.81711f}, + {642.488f,-32.9437f,46.365f,4.67748f}, + {642.326f,-27.9442f,46.9211f,4.59022f}, + {635.945f,-33.6171f,45.7164f,4.97419f}, + //stormpike + {669.272f,-297.304f,30.291f,4.66604f}, + {674.08f,-292.328f,30.4817f,0.0918785f}, + {667.01f,-288.532f,29.8809f,1.81583f}, + {664.153f,-294.042f,30.2851f,3.28531f}, + //stone + {81.7027f,-406.135f,47.7843f,0.598464f}, + {78.1431f,-409.215f,48.0401f,5.05953f}, + {73.4135f,-407.035f,46.7527f,3.34736f}, + {78.2258f,-401.859f,46.4202f,2.05852f}, + //snowfall + {-207.412f,-110.616f,78.7959f,2.43251f}, + {-197.95f,-112.205f,78.5686f,6.22441f}, + {-202.709f,-116.829f,78.4358f,5.13742f}, + {-202.059f,-108.314f,78.5783f,5.91968f}, + //ice + {-615.501f,-393.802f,60.4299f,3.06147f}, + {-608.513f,-392.717f,62.5724f,2.06323f}, + {-609.769f,-400.072f,60.7174f,5.22367f}, + {-616.093f,-398.293f,60.5628f,3.73613f}, + //frost + {-1077.7f,-340.21f,55.4682f,6.25569f}, + {-1082.74f,-333.821f,54.7962f,2.05459f}, + {-1090.66f,-341.267f,54.6768f,3.27746f}, + {-1081.58f,-344.63f,55.256f,4.75636f}, + //frost hut + {-1408.95f,-311.69f,89.2536f,4.49954f}, + {-1407.15f,-305.323f,89.1993f,2.86827f}, + {-1400.64f,-304.3f,89.7008f,1.0595f}, + {-1400.4f,-311.35f,89.3028f,4.99434f}, + //towers + //dun south - OK + {569.395f,-101.064f,52.8296f,2.34974f}, + {574.85f,-92.9842f,52.5869f,3.09325f}, + {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 + {662.253f,-129.105f,64.1794f,2.77507f}, + {661.209f,-138.877f,64.2251f,3.38594f}, + {665.481f,-146.857f,64.1271f,3.75246f}, + //icewing - OK + {225.228f,-368.909f,56.9983f,6.23806f}, + {191.36f,-369.899f,57.1524f,3.24631f}, + {215.518f,-384.019f,56.9889f,5.09636f}, + {199.625f,-382.177f,56.8691f,4.08407f}, + //stone + {-172.851f,-452.366f,40.8725f,3.31829f}, + {-147.147f,-435.053f,40.8022f,0.599238f}, + {-169.456f,-440.325f,40.985f,2.59101f}, + {-163.494f,-434.904f,41.0725f,1.84174f}, + //ice - OK + {-573.522f,-271.854f,75.0078f,3.9619f}, + {-565.616f,-269.051f,74.9952f,5.02655f}, + {-562.825f,-261.087f,74.9898f,5.95157f}, + {-569.176f,-254.446f,74.8771f,0.820305f}, + //towerpoint + {-763.04f,-371.032f,90.7933f,5.25979f}, + {-759.764f,-358.264f,90.8681f,0.289795f}, + {-768.808f,-353.056f,90.8811f,1.52601f}, + {-775.944f,-362.639f,90.8949f,2.59573f}, + //frost etower + {-1294.13f,-313.045f,107.328f,0.270162f}, + {-1306.5f,-308.105f,113.767f,1.78755f}, + {-1294.78f,-319.966f,113.79f,5.94545f}, + {-1294.83f,-312.241f,113.799f,0.295293f}, + //frost wtower + {-1300.96f,-275.111f,114.058f,4.12804f}, + {-1302.41f,-259.256f,114.065f,1.67602f}, + {-1287.97f,-262.087f,114.165f,6.18264f}, + {-1291.59f,-271.166f,114.151f,5.28257f}, + + //alliance marshall + {721.104f,-7.64155f,50.7046f,3.45575f},// south + {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) + {-1363.99f,-221.99f,98.4053f,4.93012f}, + {-1370.96f,-223.532f,98.4266f,4.93012f}, + {-1378.37f,-228.614f,99.3546f,5.38565f}, + {-1358.02f,-228.998f,98.868f,3.87768f}, + + //irondeep mine + //Irondeep Trogg + {971.671f,-442.657f,57.6951f,3.1765f}, + {969.979f,-457.148f,58.1119f,4.5204f}, + {958.692f,-333.477f,63.2276f,5.77704f}, + {957.113f,-325.92f,61.7589f,1.13446f}, + {948.25f,-448.268f,56.9009f,5.60251f}, + {934.727f,-385.802f,63.0344f,3.75246f}, + {931.751f,-403.458f,59.6737f,5.63741f}, + {931.146f,-359.666f,66.0294f,3.9619f}, + {929.702f,-412.401f,56.8776f,5.89921f}, + {926.849f,-379.074f,63.5286f,2.0944f}, + {921.972f,-358.597f,66.4313f,2.93215f}, + {921.449f,-341.981f,67.1264f,3.4383f}, + {921.1f,-395.812f,60.4615f,2.71695f}, + {919.274f,-394.986f,60.3478f,2.71696f}, + {916.852f,-393.891f,60.1726f,2.71695f}, + {914.568f,-326.21f,66.1733f,2.25147f}, + {913.064f,-395.773f,60.1364f,4.41568f}, + {909.246f,-474.576f,58.2067f,0.226893f}, + {909.246f,-474.576f,58.2901f,0.226893f}, + {907.209f,-428.267f,59.8065f,1.8675f}, + {905.973f,-459.528f,58.7594f,1.37189f}, + {905.067f,-396.074f,60.2085f,5.07891f}, + {901.809f,-457.709f,59.0116f,3.52557f}, + {900.962f,-427.44f,59.0842f,1.50098f}, + {897.929f,-471.742f,59.7729f,2.54818f}, + {893.376f,-343.171f,68.1499f,5.35816f}, + {890.584f,-406.049f,61.1925f,5.67232f}, + {888.208f,-332.564f,68.148f,1.93732f}, + {887.647f,-391.537f,61.8734f,1.37881f}, + {885.109f,-343.338f,67.0867f,3.78979f}, + {881.618f,-419.948f,53.5228f,0.593412f}, + {878.675f,-345.36f,66.1052f,3.45651f}, + {877.127f,-351.8f,66.5296f,5.74213f}, + {876.778f,-345.97f,65.7724f,3.45262f}, + {874.577f,-414.786f,52.7817f,1.67552f}, + {868.247f,-343.136f,64.9894f,1.6057f}, + {859.03f,-367.231f,47.4655f,0.0174533f}, + {857.513f,-351.817f,65.1867f,4.39823f}, + {852.632f,-372.416f,48.1657f,3.66519f}, + {849.86f,-340.944f,66.2447f,0.401426f}, + {847.99f,-386.287f,60.9277f,2.32374f}, + {847.601f,-423.072f,50.0852f,4.57276f}, + {847.135f,-411.307f,50.2106f,1.5708f}, + {835.077f,-379.418f,48.2755f,5.93412f}, + {834.87f,-453.304f,47.9075f,0.226893f}, + {834.634f,-365.981f,62.8801f,1.32645f}, + {834.354f,-355.526f,48.1491f,6.07375f}, + {833.702f,-327.506f,65.0439f,0.331613f}, + {833.151f,-374.228f,63.0938f,3.66519f}, + {831.711f,-346.785f,47.2975f,0.226893f}, + {827.874f,-413.624f,48.5818f,1.49241f}, + {827.728f,-415.483f,48.5593f,1.49238f}, + {827.016f,-424.543f,48.2856f,1.49236f}, + {823.222f,-334.283f,65.6306f,4.88692f}, + {821.892f,-464.723f,48.9451f,4.66003f}, + {821.006f,-387.635f,49.0728f,3.15905f}, + {817.26f,-447.432f,49.4308f,2.18166f}, + {805.399f,-320.146f,52.7712f,0.296706f}, + {801.405f,-328.055f,53.0195f,4.31096f}, + //irondeep skullthumber irondeep shaman + {955.812f,-440.302f,55.3411f,3.19395f}, + {937.378f,-377.816f,65.3919f,3.56047f}, + {925.059f,-331.347f,65.7564f,3.66519f}, + {922.918f,-396.634f,60.3942f,2.71695f}, + {909.99f,-462.154f,59.0811f,3.7001f}, + {907.893f,-388.787f,61.7923f,5.74213f}, + {898.801f,-437.105f,58.5266f,0.959931f}, + {884.237f,-407.597f,61.566f,0.820305f}, + {880.744f,-344.683f,66.4086f,3.4644f}, + {876.047f,-341.857f,65.8743f,4.45059f}, + {874.674f,-402.077f,61.7573f,0.26341f}, + {871.914f,-404.209f,62.1269f,6.06163f}, + {871.606f,-403.665f,62.0795f,0.765774f}, + {871.561f,-404.114f,62.1297f,0.00981727f}, + {871.528f,-404.248f,62.1455f,0.498032f}, + {871.493f,-404.122f,62.1331f,5.65727f}, + {871.282f,-403.843f,62.1108f,0.788382f}, + {868.294f,-392.395f,61.4772f,4.38685f}, + {868.256f,-392.363f,61.4803f,0.732738f}, + {867.804f,-392.51f,61.5089f,2.30167f}, + {867.612f,-392.371f,61.524f,2.86149f}, + {858.593f,-439.614f,50.2184f,0.872665f}, + {851.471f,-362.52f,47.314f,4.06662f}, + {846.939f,-347.279f,66.2876f,0.942478f}, + {842.08f,-421.775f,48.2659f,1.0821f}, + {838.358f,-371.212f,63.3299f,4.04916f}, + {827.57f,-417.483f,48.4538f,1.49237f}, + {827.012f,-457.397f,48.9331f,2.35619f}, + {825.535f,-322.373f,63.9357f,4.76475f}, + {867.635f,-443.605f,51.3347f,1.38626f}, + {957.293f,-455.039f,56.7395f,5.79449f}, + {950.077f,-326.672f,61.6552f,5.48033f}, + {936.692f,-356.78f,65.9835f,2.75762f}, + {926.475f,-419.345f,56.1833f,2.0944f}, + {924.729f,-397.453f,60.213f,2.71695f}, + {902.195f,-475.891f,58.312f,1.39626f}, + {897.464f,-338.758f,68.1715f,2.94961f}, + {884.237f,-407.597f,61.566f,0.820305f}, + {882.517f,-344.111f,66.7887f,3.46962f}, + {881.437f,-400.254f,61.2028f,0.263427f}, + {880.156f,-400.678f,61.3113f,3.41373f}, + {877.989f,-418.051f,52.9753f,4.46804f}, + {871.212f,-404.12f,62.1433f,3.6554f}, + {871.036f,-404.119f,62.2237f,4.50295f}, + {857.396f,-395.766f,61.263f,4.78684f}, + {857.276f,-395.395f,61.2418f,0.0845553f}, + {857.231f,-394.577f,61.2174f,1.96817f}, + {857.108f,-395.682f,61.2317f,4.87022f}, + {856.709f,-395.28f,61.1814f,2.54913f}, + {850.922f,-390.399f,60.8771f,2.85405f}, + {847.556f,-388.228f,60.9438f,2.56872f}, + {842.031f,-384.663f,61.6028f,2.56871f}, + {832.035f,-389.301f,47.5567f,2.11185f}, + {827.415f,-419.468f,48.3322f,1.49232f}, + {826.402f,-349.454f,47.2722f,1.51844f}, + {817.83f,-455.715f,48.4207f,0.925025f}, + {808.953f,-325.964f,52.4043f,3.01942f}, + // Morloch + {865.554f,-438.735f,50.7333f,2.12431f}, + //coldtooth mine + //miner/digger + {-917.648f,-46.8922f,77.0872f,5.27089f}, + {-912.689f,-45.4494f,76.2277f,4.60767f}, + {-905.455f,-84.5179f,75.3642f,3.29867f}, + {-904.332f,-111.509f,75.5925f,2.47837f}, + {-904.27f,-160.419f,61.9876f,3.61192f}, + {-904.023f,-90.4558f,75.3706f,3.40339f}, + {-978.678f,-37.3136f,75.8364f,2.84489f}, + {-973.076f,-36.5013f,77.5047f,1.0821f}, + {-963.951f,-87.734f,81.5555f,0.575959f}, + {-961.941f,-90.7252f,81.6629f,0.820305f}, + {-957.623f,-186.582f,66.6021f,1.95477f}, + {-952.476f,-179.778f,78.6771f,4.5204f}, + {-950.427f,-115.007f,79.6127f,3.68264f}, + {-950.25f,-151.95f,79.4598f,-1.81423f}, + {-950.169f,-188.099f,66.6184f,5.55015f}, + {-949.944f,-142.977f,80.5382f,2.70526f}, + {-947.854f,-170.5f,79.7618f,0.942478f}, + {-946.738f,-139.567f,80.0904f,2.3911f}, + {-945.503f,-65.0654f,79.7907f,5.02655f}, + {-943.678f,-110.986f,80.2557f,0.959931f}, + {-942.993f,-56.9881f,79.8915f,5.65487f}, + {-938.197f,-155.838f,61.3111f,1.65806f}, + {-930.488f,-214.524f,72.1431f,2.1236f}, + {-929.947f,-154.449f,61.5084f,1.67552f}, + {-927.412f,-135.313f,61.1987f,3.29867f}, + {-920.677f,-156.859f,62.8033f,3.15306f}, + {-916.75f,-136.094f,62.2357f,0.0698132f}, + {-915.319f,-132.718f,62.562f,1.16984f}, + {-913.589f,-146.794f,76.9366f,1.8675f}, + {-907.572f,-148.937f,76.6898f,4.76475f}, + {-902.02f,-64.6174f,73.9707f,1.19169f}, + {-899.489f,-61.7252f,73.2498f,5.09636f}, + {-894.792f,-127.141f,75.3834f,6.14356f}, + {-892.408f,-162.525f,64.1212f,2.69884f}, + {-892.326f,-123.158f,76.0318f,5.5676f}, + {-888.468f,-148.462f,61.8012f,1.65806f}, + {-883.268f,-159.738f,63.5311f,5.20108f}, + {-877.76f,-118.07f,65.215f,2.94961f}, + {-876.792f,-128.646f,64.1045f,3.40339f}, + {-874.901f,-36.6579f,69.4246f,2.00713f}, + {-874.856f,-151.351f,62.7537f,3.57875f}, + {-872.135f,-150.08f,62.7513f,3.57201f}, + {-870.288f,-149.217f,62.5413f,3.56624f}, + {-870.03f,-6.27443f,70.3867f,2.3911f}, + {-869.023f,-82.2118f,69.5848f,3.22886f}, + {-866.354f,-40.2455f,70.842f,0.0698132f}, + {-865.305f,-152.302f,63.5044f,4.86947f}, + {-861.926f,-79.0519f,71.4178f,0.20944f}, + {-857.292f,-152.277f,63.2114f,4.18879f}, + {-853.357f,-0.696194f,72.0655f,0.994838f}, + {-850.685f,-14.2596f,70.2298f,0.20944f}, + {-839.987f,-67.7695f,72.7916f,4.93928f}, + {-839.199f,-57.0558f,73.4891f,1.67552f}, + {-836.963f,-153.224f,63.3821f,4.46804f}, + {-832.721f,-67.7555f,72.9062f,4.99164f}, + {-821.496f,-143.095f,63.1292f,0.541052f}, + {-818.829f,-153.004f,62.1757f,6.12611f}, + //special + {-954.622f,-110.958f,80.7911f,6.24828f}, + {-951.477f,-53.9647f,80.0235f,5.32325f}, + {-946.812f,-126.04f,78.8601f,5.15265f}, + {-940.689f,-140.707f,79.9225f,2.79253f}, + {-933.954f,-159.632f,60.778f,2.56563f}, + {-922.537f,-130.291f,61.3756f,4.95674f}, + {-915.862f,-151.74f,76.9427f,0.942478f}, + {-888.321f,-159.831f,62.5303f,1.20428f}, + {-874.361f,-42.4751f,69.4316f,0.785398f}, + {-873.19f,-50.4899f,70.0568f,-2.41288f}, + {-868.511f,-148.386f,62.3547f,3.57875f}, + {-868.44f,-121.649f,64.5056f,3.33358f}, + {-868.324f,-77.7196f,71.4768f,5.41052f}, + {-859.846f,-19.6549f,70.7304f,1.97222f}, + {-828.05f,-150.508f,62.2019f,2.14675f}, + {-826.254f,-58.6911f,72.0041f,3.68264f}, + {-976.086f,-44.1775f,76.029f,1.46608f}, + {-971.864f,-87.4223f,81.4954f,5.8294f}, + {-966.551f,-74.1111f,80.0243f,4.2129f}, + {-958.509f,-173.652f,77.9013f,6.24828f}, + {-951.511f,-181.242f,65.529f,4.39823f}, + {-940.967f,-186.243f,77.698f,1.28164f}, + {-930.004f,-65.0898f,79.077f,0.0581657f}, + {-920.864f,-40.2009f,78.256f,5.16617f}, + {-919.089f,-148.021f,62.0317f,2.59327f}, + {-901.516f,-116.329f,75.6876f,0.471239f}, + {-897.864f,-84.4348f,74.083f,3.00197f}, + {-897.617f,-52.0457f,71.9503f,4.36332f}, + {-894.891f,-153.951f,61.6827f,3.23569f}, + {-893.933f,-111.625f,75.6591f,4.22536f}, + {-883.265f,-152.854f,61.8384f,0.0941087f}, + {-868.293f,-147.243f,62.1097f,3.2056f}, + {-867.501f,-11.8709f,70.018f,6.14356f}, + {-866.699f,-147.54f,62.1646f,3.57878f}, + {-866.566f,-91.1916f,67.4414f,4.56707f}, + {-857.272f,-141.142f,61.7356f,4.17134f}, + {-847.446f,-98.0061f,68.5131f,3.24631f}, + {-837.026f,-140.729f,62.5141f,5.51524f}, + {-824.204f,-65.053f,72.3381f,3.01942f}, + //vermin (s.th special for this mine) + {-951.955f,-197.5f,77.212f,5.63741f}, + {-944.837f,-199.608f,77.0737f,4.97419f}, + {-933.494f,-209.063f,73.7803f,5.88176f}, + {-929.666f,-201.308f,73.7032f,5.02655f}, + {-978.997f,-249.356f,65.4345f,5.05464f}, + {-974.565f,-224.828f,69.5858f,4.88846f}, + {-946.514f,-259.239f,66.0874f,3.78132f}, + {-918.402f,-250.439f,69.5271f,2.21352f}, + {-910.14f,-229.959f,72.9279f,0.27677f}, + {-851.563f,-88.6527f,68.5983f,3.61896f}, + //boss + {-848.902f,-92.931f,68.6325f,3.33350}, + //herald + {-48.459f,-288.802f,55.47f,1.0}, + //triggers + {637.083,-32.6603,45.9715,1.14353}, //firstaid_station + {669.007f,-294.078f,30.2909f,2.77507f}, //stormpike_grave + {77.8013f,-404.7f,46.7549f,-0.872665f}, //stoneheart_grave + {-202.581f,-112.73f,78.4876f,-0.715585f}, //snowfall_grave + {-611.962f,-396.17f,60.8351f,2.53682f}, //iceblood_grave + {-1082.45f,-346.823f,54.9219f,-1.53589f}, //frostwolf_grave + {-1402.21f,-307.431f,89.4424f,0.191986f}, //frostwolf_hut + {553.779f,-78.6566f,51.9378f,-1.22173f}, //dunbaldar_south + {674.001f,-143.125f,63.6615f,0.994838f}, //dunbaldar_north + {203.281f,-360.366f,56.3869f,-0.925024}, //icewing_bunker + {-152.437f,-441.758f,40.3982f,-1.95477f}, //stoneheart_bunker + {-571.88f,-262.777f,75.0087f,-0.802851f}, //iceblood_tower + {-768.907f,-363.71f,90.8949f,1.07991f}, //tower_point + {-1302.9f,-316.981f,113.867f,2.00713f}, //frostwolf_etower + {-1297.5f,-266.767f,114.15f,3.31044f}, //frostwolf_wtower + {-57.7891f,-286.597f,15.6479f,6.02139f}, //AV_NPC_A_CAPTAIN balinda + {722.43f,-10.9982f,50.7046f,3.42085f}, //AV_NPC_A_BOSS vanndar + {-545.23f,-165.35f,57.7886f,3.01145f}, //AV_NPC_H_CAPTAIN galvangar + {-1370.9f,-219.793f,98.4258f,5.04381f} //AV_NPC_H_BOSS drek thar +}; + +enum BG_AV_CreatureIds +{ + + AV_NPC_A_GRAVEDEFENSE0 = 0, // stormpike Defender + AV_NPC_A_GRAVEDEFENSE1 = 1, // seasoned defender + AV_NPC_A_GRAVEDEFENSE2 = 2, // veteran defender + AV_NPC_A_GRAVEDEFENSE3 = 3, // champion defender + AV_NPC_A_TOWERDEFENSE = 4, // stormpike bowman + AV_NPC_A_CAPTAIN = 5, // balinda + AV_NPC_A_BOSS = 6, // vanndar + + AV_NPC_H_GRAVEDEFENSE0 = 7, // frostwolf guardian + AV_NPC_H_GRAVEDEFENSE1 = 8, // seasoned guardian + AV_NPC_H_GRAVEDEFENSE2 = 9, // veteran guardian + AV_NPC_H_GRAVEDEFENSE3 = 10, // champion guardian + AV_NPC_H_TOWERDEFENSE = 11, // frostwolf bowman + AV_NPC_H_CAPTAIN = 12, // galvangar + AV_NPC_H_BOSS = 13, // drek thar + + AV_NPC_A_MARSHAL_SOUTH = 14, + AV_NPC_MARSHAL_NORTH = 15, + AV_NPC_A_MARSHAL_ICE = 16, + AV_NPC_A_MARSHAL_STONE = 17, + AV_NPC_H_MARSHAL_ICE = 18, + AV_NPC_H_MARSHAL_TOWER = 19, + AV_NPC_MARSHAL_ETOWER = 20, + AV_NPC_H_MARSHAL_WTOWER= 21, + AV_NPC_N_MINE_N_1 = 22, + AV_NPC_N_MINE_N_2 = 23, + AV_NPC_N_MINE_N_3 = 24, + AV_NPC_N_MINE_N_4 = 25, + AV_NPC_N_MINE_A_1 = 26, + AV_NPC_N_MINE_A_2 = 27, + AV_NPC_N_MINE_A_3 = 28, + AV_NPC_N_MINE_A_4 = 29, + AV_NPC_N_MINE_H_1 = 30, + AV_NPC_N_MINE_H_2 = 31, + AV_NPC_N_MINE_H_3 = 32, + AV_NPC_N_MINE_H_4 = 33, + AV_NPC_S_MINE_N_1 = 34, + AV_NPC_S_MINE_N_2 = 35, + AV_NPC_S_MINE_N_3 = 36, + AV_NPC_S_MINE_N_4 = 37, + AV_NPC_S_MINE_N_S = 38, + AV_NPC_S_MINE_A_1 = 39, + AV_NPC_S_MINE_A_2 = 40, + AV_NPC_S_MINE_A_3 = 41, + AV_NPC_S_MINE_A_4 = 42, + AV_NPC_S_MINE_H_1 = 43, + AV_NPC_S_MINE_H_2 = 44, + AV_NPC_S_MINE_H_3 = 45, + AV_NPC_S_MINE_H_4 = 46, + AV_NPC_HERALD = 47, + AV_NPC_INFO_MAX = 48 + +}; + +//entry, team, minlevel, maxlevel +//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 + { 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 + { 13328, 1214, 59, 59 }, //Seasoned Guardian + { 13332, 1214, 60, 60 }, //Veteran Guardian + { 13421, 1214, 61, 61 }, //Champion Guardian + { 13359, 1214, 59, 60 }, //Frostwolf Bowman + { 11947,67,0,0}, //not spawned with this data, but used for handlekillunit + { 11946,67,0,0}, //not spawned with this data, but used for handlekillunit + { 14763, 1534, 60, 60 }, //Dun Baldar South Marshal + { 14762, 1534, 60, 60 }, //Dun Baldar North Marshal + { 14764, 1534, 60, 60 }, //Icewing Marshal + { 14765, 1534, 60, 60 }, //Stonehearth Marshal + + { 14773, 1214, 60, 60 }, //Iceblood Warmaster + { 14776, 1214, 60, 60 }, //Tower Point Warmaster + { 14772, 1214, 60, 60 }, //East Frostwolf Warmaster + { 14777, 1214, 60, 60 }, //West Frostwolf Warmaster + + { 10987, 59, 52, 53 }, //Irondeep Trogg + { 11600, 59, 53, 54 }, //Irondeep Shaman + { 11602, 59, 54, 55 }, //Irondeep Skullthumper + { 11657, 59, 58, 58 }, //Morloch + + {13396,469,52,53}, //irondeep alliance TODO: get the right ids + {13080,469,53,54}, + {13098,469,54,55}, + {13078,469,58,58}, + + {13397,67,52,53}, //irondeep horde + {13099,67,53,54}, + {13081,67,54,55}, + {13079,67,58,58}, + + { 11603, 59, 52, 53 }, //south mine neutral + { 11604, 59, 53, 54 }, + { 11605, 59, 54, 55 }, + { 11677, 59, 58, 58 }, + { 10982, 59, 52, 53 }, //vermin + + {13317,469,52,53}, //alliance + {13096,469,54,55}, //explorer + {13087,469,54,55}, //invader + {13086,469,58,58}, + + {13316,67,52,53}, //horde + {13097,67,54,55}, //surveypr + {13089,67,54,55}, //guard + {13088,67,58,58}, + {14848,67,58,58} //Herald + +}; + +//x,y,z,o,static_creature_info-id +const float BG_AV_StaticCreaturePos[AV_STATICCPLACE_MAX][5] = { //static creatures + {-1235.31f,-340.777f,60.5088f,3.31613f,0 },//2225 - Zora Guthrek + {-1244.02f,-323.795f,61.0485f,5.21853f,1 },//3343 - Grelkor + {-1235.16f,-332.302f,60.2985f,2.96706f,2 },//3625 - Rarck + {587.303f,-42.8257f,37.5615f,5.23599f,3 },//4255 - Brogus Thunderbrew + {643.635f,-58.3987f,41.7405f,4.72984f,4 },//4257 - Lana Thunderbrew + {591.464f,-44.452f,37.6166f,5.65487f,5 },//5134 - Jonivera Farmountain + {608.515f,-33.3935f,42.0003f,5.41052f,6 },//5135 - Svalbrad Farmountain + {617.656f,-32.0701f,42.7168f,4.06662f,7 },//5139 - Kurdrum Barleybeard + {-1183.76f,-268.295f,72.8233f,3.28122f,8 },//10364 - Yaelika Farclaw + {-1187.86f,-275.31f,73.0481f,3.63028f,9 },//10367 - Shrye Ragefist + {-1008.42f,-368.006f,55.3426f,5.95647f,10 },//10981 - Frostwolf + {-1091.92f,-424.28f,53.0139f,2.93958f,10 },//10981 - Frostwolf + {-558.455f,-198.768f,58.1755f,4.97946f,10 },//10981 - Frostwolf + {-861.247f,-312.51f,55.1427f,3.35382f,10 },//10981 - Frostwolf + {-1003.81f,-395.913f,50.4736f,2.85631f,10 },//10981 - Frostwolf + {-904.5f,-289.815f,65.1222f,5.7847f,10 },//10981 - Frostwolf + {-1064.41f,-438.839f,51.3614f,1.88857f,10 },//10981 - Frostwolf + {258.814f,76.2017f,18.6468f,6.19052f,11 },//10986 - Snowblind Harpy + {265.838f,-315.846f,-16.5429f,3.15917f,11 },//10986 - Snowblind Harpy + {426.485f,-51.1927f,-5.66286f,1.60347f,11 },//10986 - Snowblind Harpy + {452.044f,-33.9594f,-0.044651f,2.72815f,11 },//10986 - Snowblind Harpy + {266.032f,-315.639f,-16.5429f,4.67962f,11 },//10986 - Snowblind Harpy + {532.64f,-54.5863f,20.7024f,2.93215f,11 },//10986 - Snowblind Harpy + {295.183f,-299.908f,-34.6123f,0.135851f,12 },//10990 - Alterac Ram + {421.08f,-225.006f,-23.73f,0.166754f,12 },//10990 - Alterac Ram + {-55.7766f,-192.498f,20.4352f,6.12221f,12 },//10990 - Alterac Ram + {527.887f,-477.223f,62.3559f,0.170935f,12 },//10990 - Alterac Ram + {389.144f,-346.508f,-30.334f,4.14117f,12 },//10990 - Alterac Ram + {108.121f,-322.248f,37.5655f,4.46788f,12 },//10990 - Alterac Ram + {507.479f,-67.9403f,10.3571f,3.26304f,12 },//10990 - Alterac Ram + {329.071f,-185.016f,-29.1542f,0.356943f,12 },//10990 - Alterac Ram + {252.449f,-422.313f,35.1404f,4.53771f,12 },//10990 - Alterac Ram + {358.882f,-118.061f,-24.9119f,2.29257f,12 },//10990 - Alterac Ram + {487.151f,-174.229f,14.7558f,4.73192f,12 },//10990 - Alterac Ram + {449.652f,-123.561f,6.14273f,6.12029f,12 },//10990 - Alterac Ram + {272.419f,-261.802f,-41.8835f,3.66559f,12 },//10990 - Alterac Ram + {359.021f,-210.954f,-29.3483f,4.31339f,12 },//10990 - Alterac Ram + {450.598f,-318.048f,-37.7548f,0.655219f,12 },//10990 - Alterac Ram + {509.333f,-218.2f,3.05439f,3.66292f,12 },//10990 - Alterac Ram + {485.771f,-223.613f,-1.53f,2.04862f,12 },//10990 - Alterac Ram + {486.636f,-452.172f,39.6592f,2.3341f,12 },//10990 - Alterac Ram + {702.783f,-257.494f,25.9777f,1.68329f,12 },//10990 - Alterac Ram + {460.942f,-199.263f,-6.0149f,0.380506f,12 },//10990 - Alterac Ram + {483.108f,-115.307f,10.1056f,3.69701f,12 },//10990 - Alterac Ram + {471.601f,-154.174f,14.0702f,5.5807f,12 },//10990 - Alterac Ram + {213.938f,-420.793f,41.2549f,5.71394f,12 },//10990 - Alterac Ram + {289.387f,-294.685f,-33.9073f,0.555494f,12 },//10990 - Alterac Ram + {155.649f,-402.891f,43.3915f,5.94838f,12 },//10990 - Alterac Ram + {517.184f,-295.105f,-9.78195f,6.05668f,12 },//10990 - Alterac Ram + {102.334f,-332.165f,38.9812f,3.31445f,12 },//10990 - Alterac Ram + {320.244f,-107.793f,-42.6357f,-1.00311f,12 },//10990 - Alterac Ram + {217.976f,110.774f,15.7603f,4.56793f,13 },//11675 - Snowblind Windcaller + {269.872f,6.66684f,20.7592f,0.381212f,13 },//11675 - Snowblind Windcaller + {313.528f,-319.041f,-27.2373f,0.554098f,13 },//11675 - Snowblind Windcaller + {435.441f,-39.9289f,-0.169651f,0.549454f,13 },//11675 - Snowblind Windcaller + {315.115f,-317.62f,-29.1123f,0.90111f,13 },//11675 - Snowblind Windcaller + {428.091f,-122.731f,3.40332f,6.05901f,14 },//11678 - Snowblind Ambusher + {235.05f,85.5705f,18.3079f,-0.914255f,14 },//11678 - Snowblind Ambusher + {-1553.04f,-344.342f,64.4163f,6.09933f,15 },//11839 - Wildpaw Brute + {-545.23f,-165.35f,57.7886f,3.01145f,16 },//11947 - Captain Galvangar + {722.43f,-10.9982f,50.7046f,3.42085f,17 },//11948 - Vanndar Stormpike + {-57.7891f,-286.597f,15.6479f,6.02139f,18 },//11949 - Captain Balinda Stonehearth + {930.498f,-520.755f,93.7334f,1.8326f,19 },//11997 - Stormpike Herald + {-776.092f,-345.161f,67.4092f,1.89257f,20 },//12051 - Frostwolf Legionnaire + {-1224.63f,-308.144f,65.0087f,4.01139f,20 },//12051 - Frostwolf Legionnaire + {-713.039f,-442.515f,82.8638f,0.68724f,20 },//12051 - Frostwolf Legionnaire + {-711.783f,-444.061f,82.7039f,0.683494f,20 },//12051 - Frostwolf Legionnaire + {587.633f,-45.9816f,37.5438f,5.81195f,21 },//12096 - Stormpike Quartermaster + {-1293.79f,-194.407f,72.4398f,5.84685f,22 },//12097 - Frostwolf Quartermaster + {446.163f,-377.119f,-1.12725f,0.209526f,23 },//12127 - Stormpike Guardsman + {549.348f,-399.254f,53.3537f,3.24729f,23 },//12127 - Stormpike Guardsman + {549.801f,-401.217f,53.8305f,3.24729f,23 },//12127 - Stormpike Guardsman + {192.704f,-406.874f,42.9183f,6.10696f,23 },//12127 - Stormpike Guardsman + {441.305f,-435.765f,28.2385f,2.14472f,23 },//12127 - Stormpike Guardsman + {192.982f,-404.891f,43.0132f,6.1061f,23 },//12127 - Stormpike Guardsman + {355.342f,-391.989f,-0.486707f,3.00643f,23 },//12127 - Stormpike Guardsman + {446.035f,-375.104f,-1.12725f,0.21033f,23 },//12127 - Stormpike Guardsman + {697.864f,-433.238f,62.7914f,1.65776f,23 },//12127 - Stormpike Guardsman + {610.74f,-331.585f,30.8021f,5.14253f,23 },//12127 - Stormpike Guardsman + {609.815f,-329.775f,30.9271f,-2.38829f,23 },//12127 - Stormpike Guardsman + {695.874f,-433.434f,62.8543f,1.65776f,23 },//12127 - Stormpike Guardsman + {443.337f,-435.283f,28.6842f,2.13768f,23 },//12127 - Stormpike Guardsman + {-1251.5f,-316.327f,62.6565f,5.02655f,24 },//13176 - Smith Regzar + {-1332.0f,-331.243f,91.2631f,1.50098f,25 },//13179 - Wing Commander Guse + {569.983f,-94.9992f,38.0325f,1.39626f,26 },//13216 - Gaelden Hammersmith + {-1244.92f,-308.916f,63.2525f,1.62316f,27 },//13218 - Grunnda Wolfheart + {-1319.56f,-342.675f,60.3404f,1.20428f,28 },//13236 - Primalist Thurloga + {647.61f,-61.1548f,41.7405f,4.24115f,29 },//13257 - Murgot Deepforge + {-1321.64f,-343.73f,60.4833f,1.01229f,30 },//13284 - Frostwolf Shaman + {-1317.61f,-342.853f,60.3726f,2.47837f,30 },//13284 - Frostwolf Shaman + {-1319.31f,-344.475f,60.3825f,1.72788f,30 },//13284 - Frostwolf Shaman + {569.963f,-42.0218f,37.7581f,4.27606f,31 },//13438 - Wing Commander Slidore + {729.2f,-78.812f,51.6335f,3.97935f,32 },//13442 - Arch Druid Renferal + {729.118f,-82.8713f,51.6335f,2.53073f,33 },//13443 - Druid of the Grove + {725.554f,-79.4973f,51.6335f,5.27089f,33 },//13443 - Druid of the Grove + {724.768f,-84.1642f,51.6335f,0.733038f,33 },//13443 - Druid of the Grove + {596.68f,-83.0633f,39.0051f,6.24828f,34 },//13447 - Corporal Noreg Stormpike + {600.032f,-2.92475f,42.0788f,5.00909f,35 },//13577 - Stormpike Ram Rider Commander + {610.239f,-21.8454f,43.272f,4.90438f,36 },//13617 - Stormpike Stable Master + {613.422f,-150.764f,33.4517f,5.55015f,37 },//13797 - Mountaineer Boombellow + {-1213.91f,-370.619f,56.4455f,0.837758f,38 },//13798 - Jotek + {704.35f,-22.9071f,50.2187f,0.785398f,39 },//13816 - Prospector Stonehewer + {-1271.24f,-335.766f,62.3971f,5.75959f,40 },//14185 - Najak Hexxen + {-1268.64f,-332.688f,62.6171f,5.28835f,41 },//14186 - Ravak Grimtotem + {648.363f,-65.2233f,41.7405f,3.12414f,42 },//14187 - Athramanis + {648.238f,-67.8931f,41.7405f,2.60054f,43 },//14188 - Dirk Swindle + {-1223.44f,-309.833f,64.9331f,4.0131f,44 },//14282 - Frostwolf Bloodhound + {-1226.4f,-307.136f,64.9706f,4.0145f,44 },//14282 - Frostwolf Bloodhound + {356.001f,-389.969f,-0.438796f,3.0334f,45 },//14283 - Stormpike Owl + {355.835f,-394.005f,-0.60149f,3.02498f,45 },//14283 - Stormpike Owl + {882.266f,-496.378f,96.7707f,4.83248f,45 },//14283 - Stormpike Owl + {878.649f,-495.917f,96.6171f,4.67693f,45 },//14283 - Stormpike Owl + {932.851f,-511.017f,93.6748f,3.61004f,45 },//14283 - Stormpike Owl + {935.806f,-513.983f,93.7436f,3.61788f,45 },//14283 - Stormpike Owl + {947.412f,-509.982f,95.1098f,2.82743f,46 },//14284 - Stormpike Battleguard + {934.557f,-512.395f,93.662f,3.61004f,46 },//14284 - Stormpike Battleguard + {939.42f,-502.777f,94.5887f,5.14872f,46 },//14284 - Stormpike Battleguard + {854.276f,-494.241f,96.8017f,5.44543f,46 },//14284 - Stormpike Battleguard + {776.621f,-487.775f,99.4049f,3.50811f,46 },//14284 - Stormpike Battleguard + {880.169f,-495.699f,96.6204f,4.8325f,46 },//14284 - Stormpike Battleguard + {773.651f,-497.482f,99.0408f,2.11185f,46 },//14284 - Stormpike Battleguard + {949.1f,-506.913f,95.4237f,3.31613f,46 },//14284 - Stormpike Battleguard + {-1370.9f,-219.793f,98.4258f,5.04381f,47}, //drek thar + +}; + +const uint32 BG_AV_StaticCreatureInfo[51][4] = { + { 2225, 1215, 55, 55 }, //Zora Guthrek + { 3343, 1215, 55, 55 }, //Grelkor + { 3625, 1215, 55, 55 }, //Rarck + { 4255, 1217, 55, 55 }, //Brogus Thunderbrew + { 4257, 1217, 55, 55 }, //Lana Thunderbrew + { 5134, 1217, 55, 55 }, //Jonivera Farmountain + { 5135, 1217, 55, 55 }, //Svalbrad Farmountain + { 5139, 1217, 55, 55 }, //Kurdrum Barleybeard + { 10364, 1215, 55, 55 }, //Yaelika Farclaw + { 10367, 1215, 55, 55 }, //Shrye Ragefist + { 10981, 38, 50, 51 }, //Frostwolf + { 10986, 514, 52, 53 }, //Snowblind Harpy + { 10990, 1274, 50, 51 }, //Alterac Ram + { 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 + { 11948, 1216, 63, 63 }, //Vanndar Stormpike + { 11949, 1216, 61, 61 }, //Captain Balinda Stonehearth + { 11997, 1334, 60, 60 }, //Stormpike Herald + { 12051, 1214, 57, 57 }, //Frostwolf Legionnaire + { 12096, 1217, 55, 55 }, //Stormpike Quartermaster + { 12097, 1215, 55, 55 }, //Frostwolf Quartermaster + { 12127, 1216, 57, 57 }, //Stormpike Guardsman + { 13176, 1215, 60, 60 }, //Smith Regzar + { 13179, 1215, 59, 59 }, //Wing Commander Guse + { 13216, 1217, 58, 58 }, //Gaelden Hammersmith + { 13218, 1215, 58, 58 }, //Grunnda Wolfheart + { 13236, 1214, 60, 60 }, //Primalist Thurloga + { 13257, 1216, 60, 60 }, //Murgot Deepforge + { 13284, 1214, 58, 58 }, //Frostwolf Shaman + { 13438, 1217, 58, 58 }, //Wing Commander Slidore + { 13442, 1216, 60, 60 }, //Arch Druid Renferal + { 13443, 1216, 60, 60 }, //Druid of the Grove + { 13447, 1216, 58, 58 }, //Corporal Noreg Stormpike + { 13577, 1216, 60, 60 }, //Stormpike Ram Rider Commander + { 13617, 1216, 60, 60 }, //Stormpike Stable Master + { 13797, 32, 60, 61 }, //Mountaineer Boombellow + { 13798, 1214, 60, 61 }, //Jotek + { 13816, 1216, 61, 61 }, //Prospector Stonehewer + { 14185, 877, 59, 59 }, //Najak Hexxen + { 14186, 105, 60, 60 }, //Ravak Grimtotem + { 14187, 1594, 60, 60 }, //Athramanis + { 14188, 57, 59, 59 }, //Dirk Swindle + { 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) + { 11948, 1216, 63, 63 }, //Vanndar Stormpike + { 11947, 1214, 61, 61 }, //Captain Galvangar + { 11949, 1216, 61, 61 } //Captain Balinda Stonehearth +}; + +enum BG_AV_Graveyards +{ + AV_GRAVE_STORM_AID = 751, + AV_GRAVE_STORM_GRAVE = 689, + AV_GRAVE_STONE_GRAVE = 729, + AV_GRAVE_SNOWFALL = 169, + AV_GRAVE_ICE_GRAVE = 749, + AV_GRAVE_FROSTWOLF = 690, + AV_GRAVE_FROST_HUT = 750, + AV_GRAVE_MAIN_ALLIANCE = 611, + AV_GRAVE_MAIN_HORDE = 610 +}; + +const uint32 BG_AV_GraveyardIds[9]= { + AV_GRAVE_STORM_AID, + AV_GRAVE_STORM_GRAVE, + AV_GRAVE_STONE_GRAVE, + AV_GRAVE_SNOWFALL, + AV_GRAVE_ICE_GRAVE, + AV_GRAVE_FROSTWOLF, + AV_GRAVE_FROST_HUT, + AV_GRAVE_MAIN_ALLIANCE, + AV_GRAVE_MAIN_HORDE +}; + +enum BG_AV_BUFF +{ //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 +}; +enum BG_AV_States +{ + POINT_NEUTRAL = 0, + POINT_ASSAULTED = 1, + POINT_DESTROYED = 2, + POINT_CONTROLED = 3 +}; + +enum BG_AV_WorldStates +{ + AV_Alliance_Score = 3127, + AV_Horde_Score = 3128, + AV_SHOW_H_SCORE = 3133, + AV_SHOW_A_SCORE = 3134, + +/* + //the comments behind the state shows which icon overlaps the other.. but is, until now, unused and maybe not a good solution (but give few performance (:) + +// Graves + + // Alliance + //Stormpike first aid station + AV_AID_A_C = 1325, + AV_AID_A_A = 1326, + AV_AID_H_C = 1327, + AV_AID_H_A = 1328, + //Stormpike Graveyard + AV_PIKEGRAVE_A_C = 1333, + AV_PIKEGRAVE_A_A = 1335, + AV_PIKEGRAVE_H_C = 1334, + AV_PIKEGRAVE_H_A = 1336, + //Stoneheart Grave + AV_STONEHEART_A_C = 1302, + AV_STONEHEART_A_A = 1304, //over hc + AV_STONEHEART_H_C = 1301, //over ac + AV_STONEHEART_H_A = 1303, //over aa + //Neutral + //Snowfall Grave +*/ + AV_SNOWFALL_N = 1966, //over aa +/* + AV_SNOWFALL_A_C = 1341, //over hc + AV_SNOWFALL_A_A = 1343, //over ha + AV_SNOWFALL_H_C = 1342, + AV_SNOWFALL_H_A = 1344, //over ac + //Horde + //Iceblood grave + AV_ICEBLOOD_A_C = 1346, //over hc + AV_ICEBLOOD_A_A = 1348, //over ac + AV_ICEBLOOD_H_C = 1347, + AV_ICEBLOOD_H_A = 1349, //over aa + //Frostwolf Grave + AV_FROSTWOLF_A_C = 1337, //over hc + AV_FROSTWOLF_A_A = 1339, //over ac + AV_FROSTWOLF_H_C = 1338, + AV_FROSTWOLF_H_A = 1340, //over aa + //Frostwolf Hut + AV_FROSTWOLFHUT_A_C = 1329, //over hc + AV_FROSTWOLFHUT_A_A = 1331, //over ha + AV_FROSTWOLFHUT_H_C = 1330, + AV_FROSTWOLFHUT_H_A = 1332, //over ac + +//Towers + //Alliance + //Dunbaldar South Bunker + AV_DUNS_CONTROLLED = 1361, + AV_DUNS_DESTROYED = 1370, + AV_DUNS_ASSAULTED = 1378, + //Dunbaldar North Bunker + AV_DUNN_CONTROLLED = 1362, + AV_DUNN_DESTROYED = 1371, + AV_DUNN_ASSAULTED = 1379, + //Icewing Bunker + AV_ICEWING_CONTROLLED = 1363, + AV_ICEWING_DESTROYED = 1372, + AV_ICEWING_ASSAULTED = 1380, + //Stoneheart Bunker + AV_STONEH_CONTROLLED = 1364, + AV_STONEH_DESTROYED = 1373, + AV_STONEH_ASSAULTED = 1381, + //Horde + //Iceblood Tower + AV_ICEBLOOD_CONTROLLED = 1385, + AV_ICEBLOOD_DESTROYED = 1368, + AV_ICEBLOOD_ASSAULTED = 1390, + //Tower Point + AV_TOWERPOINT_CONTROLLED = 1384, + AV_TOWERPOINT_DESTROYED = 1367, //goes over controlled + AV_TOWERPOINT_ASSAULTED = 1389, //goes over destroyed + //Frostwolf West + AV_FROSTWOLFW_CONTROLLED = 1382, + AV_FROSTWOLFW_DESTROYED = 1365, //over controlled + AV_FROSTWOLFW_ASSAULTED = 1387, //over destroyed + //Frostwolf East + AV_FROSTWOLFE_CONTROLLED = 1383, + AV_FROSTWOLFE_DESTROYED = 1366, + AV_FROSTWOLFE_ASSAULTED = 1388, + +//mines + + AV_N_MINE_N = 1360, + AV_N_MINE_A = 1358, + AV_N_MINE_H = 1359, + + AV_S_MINE_N = 1357, + AV_S_MINE_A = 1355, + AV_S_MINE_H = 1356, + +//towers assaulted by own team (unused) + AV_STONEH_UNUSED = 1377, + AV_ICEWING_UNUSED = 1376, + AV_DUNS_UNUSED = 1375, + AV_DUNN_UNUSED = 1374, + + AV_ICEBLOOD_UNUSED = 1395, + AV_TOWERPOINT_UNUSED = 1394, + AV_FROSTWOLFE_UNUSED = 1393, + AV_FROSTWOLFW_UNUSED = 1392 +*/ + +}; + +//alliance_control neutral_control horde_control +const uint32 BG_AV_MineWorldStates[2][3] = { + {1358, 1360,1359}, + {1355, 1357,1356} +}; + +//alliance_control alliance_assault h_control h_assault +const uint32 BG_AV_NodeWorldStates[16][4] = { + //Stormpike first aid station + {1325, 1326,1327,1328}, + //Stormpike Graveyard + {1333,1335,1334,1336}, + //Stoneheart Grave + {1302,1304,1301,1303}, + //Snowfall Grave + {1341,1343,1342,1344}, + //Iceblood grave + {1346,1348,1347,1349}, + //Frostwolf Grave + {1337,1339,1338,1340}, + //Frostwolf Hut + {1329,1331,1330,1332}, + //Dunbaldar South Bunker + {1361,1375,1370,1378}, + //Dunbaldar North Bunker + {1362,1374,1371,1379}, + //Icewing Bunker + {1363,1376,1372,1380}, + //Stoneheart Bunker + {1364,1377,1373,1381}, + //Iceblood Tower + {1368,1390,1385,1395}, + //Tower Point + {1367,1389,1384,1394}, + //Frostwolf East + {1366,1388,1383,1393}, + //Frostwolf West + {1365,1387,1382,1392}, +}; + +enum BG_AV_QuestIds +{ + AV_QUEST_A_SCRAPS1 = 7223, + AV_QUEST_A_SCRAPS2 = 6781, + AV_QUEST_H_SCRAPS1 = 7224, + AV_QUEST_H_SCRAPS2 = 6741, + AV_QUEST_A_COMMANDER1 = 6942, //soldier + AV_QUEST_H_COMMANDER1 = 6825, + AV_QUEST_A_COMMANDER2 = 6941, //leutnant + AV_QUEST_H_COMMANDER2 = 6826, + AV_QUEST_A_COMMANDER3 = 6943, //commander + AV_QUEST_H_COMMANDER3 = 6827, + AV_QUEST_A_BOSS1 = 7386, // 5 cristal/blood + AV_QUEST_H_BOSS1 = 7385, + AV_QUEST_A_BOSS2 = 6881, // 1 + AV_QUEST_H_BOSS2 = 6801, + AV_QUEST_A_NEAR_MINE = 5892, //the mine near start location of team + AV_QUEST_H_NEAR_MINE = 5893, + AV_QUEST_A_OTHER_MINE = 6982, //the other mine ;) + AV_QUEST_H_OTHER_MINE = 6985, + AV_QUEST_A_RIDER_HIDE = 7026, + AV_QUEST_H_RIDER_HIDE = 7002, + AV_QUEST_A_RIDER_TAME = 7027, + AV_QUEST_H_RIDER_TAME = 7001 +}; + +struct BG_AV_NodeInfo +{ + uint16 TotalOwner; + uint16 Owner; + uint16 PrevOwner; + BG_AV_States State; + BG_AV_States PrevState; + int Timer; + bool Tower; +}; + +inline BG_AV_Nodes &operator++(BG_AV_Nodes &i){ return i = BG_AV_Nodes(i + 1); } + +class BattleGroundAVScore : public BattleGroundScore +{ + public: + BattleGroundAVScore() : GraveyardsAssaulted(0), GraveyardsDefended(0), TowersAssaulted(0), TowersDefended(0), MinesCaptured(0), LeadersKilled(0), SecondaryObjectives(0) {}; + virtual ~BattleGroundAVScore() {}; + uint32 GraveyardsAssaulted; + uint32 GraveyardsDefended; + uint32 TowersAssaulted; + uint32 TowersDefended; + uint32 MinesCaptured; + uint32 LeadersKilled; + uint32 SecondaryObjectives; +}; + +class BattleGroundAV : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundAV(); + ~BattleGroundAV(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + void RemovePlayer(Player *plr,uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + virtual void ResetBGSubclass(); + + /*general stuff*/ + void UpdateScore(uint16 team, int16 points); + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); + + /*handlestuff*/ //these are functions which get called from extern + virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj); + void HandleKillPlayer(Player* player, Player *killer); + void HandleKillUnit(Creature *unit, Player *killer); + void HandleQuestComplete(uint32 questid, Player *player); + bool PlayerCanDoMineQuest(int32 GOId,uint32 team); + + void EndBattleGround(uint32 winner); + + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); + + private: + /* Nodes occupying */ + void EventPlayerAssaultsPoint(Player* player, uint32 object); + void EventPlayerDefendsPoint(Player* player, uint32 object); + void EventPlayerDestroyedPoint(BG_AV_Nodes node); + + void AssaultNode(BG_AV_Nodes node,uint16 team); + void DestroyNode(BG_AV_Nodes node); + void InitNode(BG_AV_Nodes node, uint16 team, bool tower); + void DefendNode(BG_AV_Nodes node, uint16 team); + + void PopulateNode(BG_AV_Nodes node); + void DePopulateNode(BG_AV_Nodes node); + + const BG_AV_Nodes GetNodeThroughObject(uint32 object); + const uint32 GetObjectThroughNode(BG_AV_Nodes node); + const char* GetNodeName(BG_AV_Nodes node); + const bool IsTower(BG_AV_Nodes node) { return m_Nodes[node].Tower; } + + /*mine*/ + void ChangeMineOwner(uint8 mine, uint32 team, bool initial=false); + + /*worldstates*/ + void FillInitialWorldStates(WorldPacket& data); + const uint8 GetWorldStateType(uint8 state, uint16 team); + void SendMineWorldStates(uint32 mine); + void UpdateNodeWorldState(BG_AV_Nodes node); + + /*general */ + Creature* AddAVCreature(uint16 cinfoid, uint16 type); + const uint16 GetBonusHonor(uint8 kills); //TODO remove this when the core handles this right + + /*variables */ + int32 m_Team_Scores[2]; + uint32 m_Team_QuestStatus[2][9]; //[x][y] x=team y=questcounter + + BG_AV_NodeInfo m_Nodes[BG_AV_NODES_MAX]; + + uint32 m_Mine_Owner[2]; + uint32 m_Mine_PrevOwner[2]; //only for worldstates needed + int32 m_Mine_Timer; //ticks for both teams + uint32 m_Mine_Reclaim_Timer[2]; + uint32 m_CaptainBuffTimer[2]; + bool m_CaptainAlive[2]; + + uint8 m_MaxLevel; //TODO remove this when battleground-getmaxlevel() returns something usefull + bool m_IsInformedNearVictory[2]; + +}; + +#endif + diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundBE.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundBE.cpp new file mode 100644 index 00000000000..d6debe45ae3 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundBE.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundBE.h" +#include "Language.h" +#include "Object.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "WorldPacket.h" + +BattleGroundBE::BattleGroundBE() +{ + m_BgObjects.resize(BG_BE_OBJECT_MAX); + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; +} + +BattleGroundBE::~BattleGroundBE() +{ + +} + +void BattleGroundBE::Update(uint32 diff) +{ + BattleGround::Update(diff); + + /*if (GetStatus() == STATUS_IN_PROGRESS) + { + // update something + }*/ +} + +void BattleGroundBE::StartingEventCloseDoors() +{ + for (uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + + for (uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i) + SpawnBGObject(i, RESPAWN_ONE_DAY); +} + +void BattleGroundBE::StartingEventOpenDoors() +{ + for (uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_2; ++i) + DoorOpen(i); + + for (uint32 i = BG_BE_OBJECT_BUFF_1; i <= BG_BE_OBJECT_BUFF_2; ++i) + SpawnBGObject(i, 60); +} + +void BattleGroundBE::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundBEScore* sc = new BattleGroundBEScore; + + m_PlayerScores[plr->GetGUID()] = sc; + + UpdateArenaWorldState(); +} + +void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) +{ + if (GetStatus() == STATUS_WAIT_LEAVE) + return; + + UpdateArenaWorldState(); + CheckArenaWinConditions(); +} + +void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + if (!killer) + { + sLog.outError("Killer player not found"); + return; + } + + BattleGround::HandleKillPlayer(player,killer); + + UpdateArenaWorldState(); + CheckArenaWinConditions(); +} + +bool BattleGroundBE::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),6238.930176,262.963470,0.889519,player->GetOrientation(),false); + return true; +} + +void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + //uint32 SpellId = 0; + //uint64 buff_guid = 0; + switch(Trigger) + { + case 4538: // buff trigger? + //buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_1]; + break; + case 4539: // buff trigger? + //buff_guid = m_BgObjects[BG_BE_OBJECT_BUFF_2]; + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + //if (buff_guid) + // HandleTriggerBuff(buff_guid,Source); +} + +void BattleGroundBE::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0x9f3) << uint32(1); // 9 + UpdateArenaWorldState(); +} + +void BattleGroundBE::Reset() +{ + //call parent's class reset + BattleGround::Reset(); +} + +bool BattleGroundBE::SetupBattleGround() +{ + // gates + if (!AddObject(BG_BE_OBJECT_DOOR_1, BG_BE_OBJECT_TYPE_DOOR_1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_BE_OBJECT_DOOR_2, BG_BE_OBJECT_TYPE_DOOR_2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_BE_OBJECT_DOOR_3, BG_BE_OBJECT_TYPE_DOOR_3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_BE_OBJECT_DOOR_4, BG_BE_OBJECT_TYPE_DOOR_4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_BE_OBJECT_BUFF_1, BG_BE_OBJECT_TYPE_BUFF_1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120) + || !AddObject(BG_BE_OBJECT_BUFF_2, BG_BE_OBJECT_TYPE_BUFF_2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120)) + { + sLog.outErrorDb("BatteGroundBE: Failed to spawn some object!"); + return false; + } + + return true; +} + +void BattleGroundBE::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) +{ + + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); + if (itr == m_PlayerScores.end()) // player not found... + return; + + //there is nothing special in this score + BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); + +} + +/* +21:45:46 id:231310 [S2C] SMSG_INIT_WORLD_STATES (706 = 0x02C2) len: 86 +0000: 32 02 00 00 76 0e 00 00 00 00 00 00 09 00 f3 09 | 2...v........... +0010: 00 00 01 00 00 00 f1 09 00 00 01 00 00 00 f0 09 | ................ +0020: 00 00 02 00 00 00 d4 08 00 00 00 00 00 00 d8 08 | ................ +0030: 00 00 00 00 00 00 d7 08 00 00 00 00 00 00 d6 08 | ................ +0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................ +0050: 00 00 00 00 00 00 | ...... + +spell 32724 - Gold Team +spell 32725 - Green Team +35774 Gold Team +35775 Green Team +*/ diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundBE.h b/src/server/game/BattleGrounds/Zones/BattleGroundBE.h new file mode 100644 index 00000000000..760d4d278c9 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundBE.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDBE_H +#define __BATTLEGROUNDBE_H + +class BattleGround; + +enum BattleGroundBEObjectTypes +{ + BG_BE_OBJECT_DOOR_1 = 0, + BG_BE_OBJECT_DOOR_2 = 1, + BG_BE_OBJECT_DOOR_3 = 2, + BG_BE_OBJECT_DOOR_4 = 3, + BG_BE_OBJECT_BUFF_1 = 4, + BG_BE_OBJECT_BUFF_2 = 5, + BG_BE_OBJECT_MAX = 6 +}; + +enum BattleGroundBEObjects +{ + BG_BE_OBJECT_TYPE_DOOR_1 = 183971, + BG_BE_OBJECT_TYPE_DOOR_2 = 183973, + BG_BE_OBJECT_TYPE_DOOR_3 = 183970, + BG_BE_OBJECT_TYPE_DOOR_4 = 183972, + BG_BE_OBJECT_TYPE_BUFF_1 = 184663, + BG_BE_OBJECT_TYPE_BUFF_2 = 184664 +}; + +class BattleGroundBEScore : public BattleGroundScore +{ + public: + BattleGroundBEScore() {}; + virtual ~BattleGroundBEScore() {}; +}; + +class BattleGroundBE : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundBE(); + ~BattleGroundBE(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + virtual void Reset(); + virtual void FillInitialWorldStates(WorldPacket &d); + void HandleKillPlayer(Player* player, Player *killer); + bool HandlePlayerUnderMap(Player * plr); + + /* Scorekeeping */ + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); +}; +#endif diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundDS.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundDS.cpp new file mode 100644 index 00000000000..9036ef83f93 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundDS.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundDS.h" +#include "Language.h" +#include "Player.h" +#include "Object.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" + +BattleGroundDS::BattleGroundDS() +{ + m_BgObjects.resize(BG_DS_OBJECT_MAX); + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; +} + +BattleGroundDS::~BattleGroundDS() +{ + +} + +void BattleGroundDS::Update(uint32 diff) +{ + BattleGround::Update(diff); + if (getWaterFallTimer() < diff) + { + if (isWaterFallActive()) + { + setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); + for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) + SpawnBGObject(i, getWaterFallTimer()); + setWaterFallActive(false); + } + else + { + setWaterFallTimer(BG_DS_WATERFALL_DURATION); + for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + setWaterFallActive(true); + } + } + else + setWaterFallTimer(getWaterFallTimer() - diff); +} + +void BattleGroundDS::StartingEventCloseDoors() +{ + for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); +} + +void BattleGroundDS::StartingEventOpenDoors() +{ + for (uint32 i = BG_DS_OBJECT_DOOR_1; i <= BG_DS_OBJECT_DOOR_2; ++i) + DoorOpen(i); + + for (uint32 i = BG_DS_OBJECT_BUFF_1; i <= BG_DS_OBJECT_BUFF_2; ++i) + SpawnBGObject(i, 60); + + setWaterFallTimer(urand(BG_DS_WATERFALL_TIMER_MIN, BG_DS_WATERFALL_TIMER_MAX)); + setWaterFallActive(false); + + for (uint32 i = BG_DS_OBJECT_WATER_1; i <= BG_DS_OBJECT_WATER_2; ++i) + SpawnBGObject(i, getWaterFallTimer()); +} + +void BattleGroundDS::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundDSScore* sc = new BattleGroundDSScore; + + m_PlayerScores[plr->GetGUID()] = sc; + + UpdateArenaWorldState(); +} + +void BattleGroundDS::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) +{ + if (GetStatus() == STATUS_WAIT_LEAVE) + return; + + UpdateArenaWorldState(); + CheckArenaWinConditions(); +} + +void BattleGroundDS::HandleKillPlayer(Player* player, Player* killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + if (!killer) + { + sLog.outError("BattleGroundDS: Killer player not found"); + return; + } + + BattleGround::HandleKillPlayer(player,killer); + + UpdateArenaWorldState(); + CheckArenaWinConditions(); +} + +void BattleGroundDS::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + switch(Trigger) + { + case 5347: + case 5348: + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } +} + +bool BattleGroundDS::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(), 1299.046, 784.825, 9.338, 2.422, false); + return true; +} + +void BattleGroundDS::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(3610) << uint32(1); // 9 show + UpdateArenaWorldState(); +} + +void BattleGroundDS::Reset() +{ + //call parent's class reset + BattleGround::Reset(); +} + + +bool BattleGroundDS::SetupBattleGround() +{ + // gates + if (!AddObject(BG_DS_OBJECT_DOOR_1, BG_DS_OBJECT_TYPE_DOOR_1, 1350.95, 817.2, 20.8096, 3.15, 0, 0, 0.99627, 0.0862864, RESPAWN_IMMEDIATELY) + || !AddObject(BG_DS_OBJECT_DOOR_2, BG_DS_OBJECT_TYPE_DOOR_2, 1232.65, 764.913, 20.0729, 6.3, 0, 0, 0.0310211, -0.999519, RESPAWN_IMMEDIATELY) + // water + || !AddObject(BG_DS_OBJECT_WATER_1, BG_DS_OBJECT_TYPE_WATER_1, 1291.56, 790.837, 7.1, 3.14238, 0, 0, 0.694215, -0.719768, 120) + || !AddObject(BG_DS_OBJECT_WATER_2, BG_DS_OBJECT_TYPE_WATER_2, 1291.56, 790.837, 7.1, 3.14238, 0, 0, 0.694215, -0.719768, 120) + // buffs + || !AddObject(BG_DS_OBJECT_BUFF_1, BG_DS_OBJECT_TYPE_BUFF_1, 1291.7, 813.424, 7.11472, 4.64562, 0, 0, 0.730314, -0.683111, 120) + || !AddObject(BG_DS_OBJECT_BUFF_2, BG_DS_OBJECT_TYPE_BUFF_2, 1291.7, 768.911, 7.11472, 1.55194, 0, 0, 0.700409, 0.713742, 120)) + { + sLog.outErrorDb("BatteGroundDS: Failed to spawn some object!"); + return false; + } + + return true; +} diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundDS.h b/src/server/game/BattleGrounds/Zones/BattleGroundDS.h new file mode 100644 index 00000000000..2ced5c88fd1 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundDS.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDDS_H +#define __BATTLEGROUNDDS_H + +class BattleGround; + +enum BattleGroundDSObjectTypes +{ + BG_DS_OBJECT_DOOR_1 = 0, + BG_DS_OBJECT_DOOR_2 = 1, + BG_DS_OBJECT_WATER_1 = 2, + BG_DS_OBJECT_WATER_2 = 3, + BG_DS_OBJECT_BUFF_1 = 4, + BG_DS_OBJECT_BUFF_2 = 5, + BG_DS_OBJECT_MAX = 6 +}; + +enum BattleGroundDSObjects +{ + BG_DS_OBJECT_TYPE_DOOR_1 = 192642, + BG_DS_OBJECT_TYPE_DOOR_2 = 192643, + BG_DS_OBJECT_TYPE_WATER_1 = 194395, + BG_DS_OBJECT_TYPE_WATER_2 = 191877, + BG_DS_OBJECT_TYPE_BUFF_1 = 184663, + BG_DS_OBJECT_TYPE_BUFF_2 = 184664 +}; + +enum BattleGroundDSData +{ // These values are NOT blizzlike... need the correct data! + BG_DS_WATERFALL_TIMER_MIN = 30000, + BG_DS_WATERFALL_TIMER_MAX = 60000, + BG_DS_WATERFALL_DURATION = 10000, +}; + +class BattleGroundDSScore : public BattleGroundScore +{ + public: + BattleGroundDSScore() {}; + virtual ~BattleGroundDSScore() {}; + //TODO fix me +}; + +class BattleGroundDS : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundDS(); + ~BattleGroundDS(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + virtual void Reset(); + virtual void FillInitialWorldStates(WorldPacket &d); + void HandleKillPlayer(Player* player, Player *killer); + bool HandlePlayerUnderMap(Player * plr); + private: + uint32 m_waterTimer; + bool m_waterfallActive; + protected: + bool isWaterFallActive() { return m_waterfallActive; }; + void setWaterFallActive(bool active) { m_waterfallActive = active; }; + void setWaterFallTimer(uint32 timer) { m_waterTimer = timer; }; + uint32 getWaterFallTimer() { return m_waterTimer; }; +}; +#endif diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundEY.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundEY.cpp new file mode 100644 index 00000000000..20f023e4c2a --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundEY.cpp @@ -0,0 +1,938 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectMgr.h" +#include "World.h" +#include "WorldPacket.h" +#include "BattleGroundMgr.h" +#include "BattleGround.h" +#include "BattleGroundEY.h" +#include "Creature.h" +#include "Language.h" +#include "Object.h" +#include "Player.h" +#include "Util.h" + +// these variables aren't used outside of this file, so declare them only here +uint32 BG_EY_HonorScoreTicks[BG_HONOR_MODE_NUM] = { + 330, // normal honor + 200 // holiday +}; + +BattleGroundEY::BattleGroundEY() +{ + m_BuffChange = true; + m_BgObjects.resize(BG_EY_OBJECT_MAX); + m_BgCreatures.resize(BG_EY_CREATURES_MAX); + m_Points_Trigger[FEL_REALVER] = TR_FEL_REALVER_BUFF; + m_Points_Trigger[BLOOD_ELF] = TR_BLOOD_ELF_BUFF; + m_Points_Trigger[DRAENEI_RUINS] = TR_DRAENEI_RUINS_BUFF; + m_Points_Trigger[MAGE_TOWER] = TR_MAGE_TOWER_BUFF; + + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_EY_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_EY_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_EY_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_EY_HAS_BEGUN; +} + +BattleGroundEY::~BattleGroundEY() +{ +} + +void BattleGroundEY::Update(uint32 diff) +{ + BattleGround::Update(diff); + + if (GetStatus() == STATUS_IN_PROGRESS) + { + m_PointAddingTimer -= diff; + if (m_PointAddingTimer <= 0) + { + m_PointAddingTimer = BG_EY_FPOINTS_TICK_TIME; + if (m_TeamPointsCount[BG_TEAM_ALLIANCE] > 0) + AddPoints(ALLIANCE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_ALLIANCE] - 1]); + if (m_TeamPointsCount[BG_TEAM_HORDE] > 0) + AddPoints(HORDE, BG_EY_TickPoints[m_TeamPointsCount[BG_TEAM_HORDE] - 1]); + } + + if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN || m_FlagState == BG_EY_FLAG_STATE_ON_GROUND) + { + m_FlagsTimer -= diff; + + if (m_FlagsTimer < 0) + { + m_FlagsTimer = 0; + if (m_FlagState == BG_EY_FLAG_STATE_WAIT_RESPAWN) + RespawnFlag(true); + else + RespawnFlagAfterDrop(); + } + } + + m_TowerCapCheckTimer -= diff; + if (m_TowerCapCheckTimer <= 0) + { + //check if player joined point + /*I used this order of calls, because although we will check if one player is in gameobject's distance 2 times + but we can count of players on current point in CheckSomeoneLeftPoint + */ + this->CheckSomeoneJoinedPoint(); + //check if player left point + this->CheckSomeoneLeftPoint(); + this->UpdatePointStatuses(); + m_TowerCapCheckTimer = BG_EY_FPOINTS_TICK_TIME; + } + } +} + +void BattleGroundEY::StartingEventCloseDoors() +{ + SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY); + + for (uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i) + SpawnBGObject(i, RESPAWN_ONE_DAY); +} + +void BattleGroundEY::StartingEventOpenDoors() +{ + SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_ONE_DAY); + SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_ONE_DAY); + + for (uint32 i = BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER; i <= BG_EY_OBJECT_FLAG_NETHERSTORM; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + for (uint32 i = 0; i < EY_POINTS_MAX; ++i) + { + //randomly spawn buff + uint8 buff = urand(0, 2); + SpawnBGObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + buff + i * 3, RESPAWN_IMMEDIATELY); + } +} + +void BattleGroundEY::AddPoints(uint32 Team, uint32 Points) +{ + BattleGroundTeamId team_index = GetTeamIndexByTeamId(Team); + m_TeamScores[team_index] += Points; + m_HonorScoreTics[team_index] += Points; + if (m_HonorScoreTics[team_index] >= m_HonorTics) + { + RewardHonorToTeam(GetBonusHonorFromKill(1), Team); + m_HonorScoreTics[team_index] -= m_HonorTics; + } + UpdateTeamScore(Team); +} + +void BattleGroundEY::CheckSomeoneJoinedPoint() +{ + GameObject *obj = NULL; + for (uint8 i = 0; i < EY_POINTS_MAX; ++i) + { + obj = HashMapHolder::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]); + if (obj) + { + uint8 j = 0; + while (j < m_PlayersNearPoint[EY_POINTS_MAX].size()) + { + Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[EY_POINTS_MAX][j]); + if (!plr) + { + sLog.outError("BattleGroundEY:CheckSomeoneJoinedPoint: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[EY_POINTS_MAX][j])); + ++j; + continue; + } + if (plr->CanCaptureTowerPoint() && plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) + { + //player joined point! + //show progress bar + UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, plr); + UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[i], plr); + UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, plr); + //add player to point + m_PlayersNearPoint[i].push_back(m_PlayersNearPoint[EY_POINTS_MAX][j]); + //remove player from "free space" + m_PlayersNearPoint[EY_POINTS_MAX].erase(m_PlayersNearPoint[EY_POINTS_MAX].begin() + j); + } + else + ++j; + } + } + } +} + +void BattleGroundEY::CheckSomeoneLeftPoint() +{ + //reset current point counts + for (uint8 i = 0; i < 2*EY_POINTS_MAX; ++i) + m_CurrentPointPlayersCount[i] = 0; + GameObject *obj = NULL; + for (uint8 i = 0; i < EY_POINTS_MAX; ++i) + { + obj = HashMapHolder::Find(m_BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REALVER + i]); + if (obj) + { + uint8 j = 0; + while (j < m_PlayersNearPoint[i].size()) + { + Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[i][j]); + if (!plr) + { + sLog.outError("BattleGroundEY:CheckSomeoneLeftPoint Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[i][j])); + //move not existed player to "free space" - this will cause many error showing in log, but it is a very important bug + m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); + m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); + ++j; + continue; + } + if (!plr->CanCaptureTowerPoint() || !plr->IsWithinDistInMap(obj, BG_EY_POINT_RADIUS)) + //move player out of point (add him to players that are out of points + { + m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); + m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); + this->UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, plr); + } + else + { + //player is neat flag, so update count: + m_CurrentPointPlayersCount[2 * i + GetTeamIndexByTeamId(plr->GetTeam())]++; + ++j; + } + } + } + } +} + +void BattleGroundEY::UpdatePointStatuses() +{ + for (uint8 point = 0; point < EY_POINTS_MAX; ++point) + { + if (m_PlayersNearPoint[point].empty()) + continue; + //count new point bar status: + m_PointBarStatus[point] += (m_CurrentPointPlayersCount[2 * point] - m_CurrentPointPlayersCount[2 * point + 1] < BG_EY_POINT_MAX_CAPTURERS_COUNT) ? m_CurrentPointPlayersCount[2 * point] - m_CurrentPointPlayersCount[2 * point + 1] : BG_EY_POINT_MAX_CAPTURERS_COUNT; + + if (m_PointBarStatus[point] > BG_EY_PROGRESS_BAR_ALI_CONTROLLED) + //point is fully alliance's + m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_ALI_CONTROLLED; + if (m_PointBarStatus[point] < BG_EY_PROGRESS_BAR_HORDE_CONTROLLED) + //point is fully horde's + m_PointBarStatus[point] = BG_EY_PROGRESS_BAR_HORDE_CONTROLLED; + + uint32 pointOwnerTeamId = 0; + //find which team should own this point + if (m_PointBarStatus[point] <= BG_EY_PROGRESS_BAR_NEUTRAL_LOW) + pointOwnerTeamId = HORDE; + else if (m_PointBarStatus[point] >= BG_EY_PROGRESS_BAR_NEUTRAL_HIGH) + pointOwnerTeamId = ALLIANCE; + else + pointOwnerTeamId = EY_POINT_NO_OWNER; + + for (uint8 i = 0; i < m_PlayersNearPoint[point].size(); ++i) + { + Player *plr = objmgr.GetPlayer(m_PlayersNearPoint[point][i]); + if (plr) + { + this->UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[point], plr); + //if point owner changed we must evoke event! + if (pointOwnerTeamId != m_PointOwnedByTeam[point]) + { + //point was uncontrolled and player is from team which captured point + if (m_PointState[point] == EY_POINT_STATE_UNCONTROLLED && plr->GetTeam() == pointOwnerTeamId) + this->EventTeamCapturedPoint(plr, point); + + //point was under control and player isn't from team which controlled it + if (m_PointState[point] == EY_POINT_UNDER_CONTROL && plr->GetTeam() != m_PointOwnedByTeam[point]) + this->EventTeamLostPoint(plr, point); + } + } + } + } +} + +void BattleGroundEY::UpdateTeamScore(uint32 Team) +{ + uint32 score = GetTeamScore(Team); + //TODO there should be some sound played when one team is near victory!! - and define variables + /*if (!m_IsInformedNearVictory && score >= BG_EY_WARNING_NEAR_VICTORY_SCORE) + { + if (Team == ALLIANCE) + SendMessageToAll(LANG_BG_EY_A_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); + else + SendMessageToAll(LANG_BG_EY_H_NEAR_VICTORY, CHAT_MSG_BG_SYSTEM_NEUTRAL); + PlaySoundToAll(BG_EY_SOUND_NEAR_VICTORY); + m_IsInformedNearVictory = true; + }*/ + + if (score >= BG_EY_MAX_TEAM_SCORE) + { + score = BG_EY_MAX_TEAM_SCORE; + EndBattleGround(Team); + } + + if (Team == ALLIANCE) + UpdateWorldState(EY_ALLIANCE_RESOURCES, score); + else + UpdateWorldState(EY_HORDE_RESOURCES, score); +} + +void BattleGroundEY::EndBattleGround(uint32 winner) +{ + //win reward + if (winner == ALLIANCE) + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + if (winner == HORDE) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + //complete map reward + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + + BattleGround::EndBattleGround(winner); +} + +void BattleGroundEY::UpdatePointsCount(uint32 Team) +{ + if (Team == ALLIANCE) + UpdateWorldState(EY_ALLIANCE_BASE, m_TeamPointsCount[BG_TEAM_ALLIANCE]); + else + UpdateWorldState(EY_HORDE_BASE, m_TeamPointsCount[BG_TEAM_HORDE]); +} + +void BattleGroundEY::UpdatePointsIcons(uint32 Team, uint32 Point) +{ + //we MUST firstly send 0, after that we can send 1!!! + if (m_PointState[Point] == EY_POINT_UNDER_CONTROL) + { + UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 0); + if (Team == ALLIANCE) + UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 1); + else + UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 1); + } + else + { + if (Team == ALLIANCE) + UpdateWorldState(m_PointsIconStruct[Point].WorldStateAllianceControlledIndex, 0); + else + UpdateWorldState(m_PointsIconStruct[Point].WorldStateHordeControlledIndex, 0); + UpdateWorldState(m_PointsIconStruct[Point].WorldStateControlIndex, 1); + } +} + +void BattleGroundEY::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map + BattleGroundEYScore* sc = new BattleGroundEYScore; + + m_PlayersNearPoint[EY_POINTS_MAX].push_back(plr->GetGUID()); + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundEY::RemovePlayer(Player *plr, uint64 guid) +{ + // sometimes flag aura not removed :( + for (int j = EY_POINTS_MAX; j >= 0; --j) + { + for (size_t i = 0; i < m_PlayersNearPoint[j].size(); ++i) + if (m_PlayersNearPoint[j][i] == guid) + m_PlayersNearPoint[j].erase(m_PlayersNearPoint[j].begin() + i); + } + if (IsFlagPickedup()) + { + if (m_FlagKeeper == guid) + { + if (plr) + EventPlayerDroppedFlag(plr); + else + { + SetFlagPicker(0); + RespawnFlag(true); + } + } + } +} + +void BattleGroundEY::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + if (!Source->isAlive()) //hack code, must be removed later + return; + + switch(Trigger) + { + case TR_BLOOD_ELF_POINT: + if (m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[BLOOD_ELF] == Source->GetTeam()) + if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_BLOOD_ELF); + break; + case TR_FEL_REALVER_POINT: + if (m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[FEL_REALVER] == Source->GetTeam()) + if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_FEL_REALVER); + break; + case TR_MAGE_TOWER_POINT: + if (m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[MAGE_TOWER] == Source->GetTeam()) + if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_MAGE_TOWER); + break; + case TR_DRAENEI_RUINS_POINT: + if (m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[DRAENEI_RUINS] == Source->GetTeam()) + if (m_FlagState && GetFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source, BG_EY_OBJECT_FLAG_DRAENEI_RUINS); + break; + case 4512: + case 4515: + case 4517: + case 4519: + case 4530: + case 4531: + case 4568: + case 4569: + case 4570: + case 4571: + case 5866: + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } +} + +bool BattleGroundEY::SetupBattleGround() +{ + // doors + if (!AddObject(BG_EY_OBJECT_DOOR_A, BG_OBJECT_A_DOOR_EY_ENTRY, 2527.6f, 1596.91f, 1262.13f, -3.12414f, -0.173642f, -0.001515f, 0.98477f, -0.008594f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_EY_OBJECT_DOOR_H, BG_OBJECT_H_DOOR_EY_ENTRY, 1803.21f, 1539.49f, 1261.09f, 3.14159f, 0.173648f, 0, 0.984808f, 0, RESPAWN_IMMEDIATELY) + // banners (alliance) + || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_A_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_A_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_A_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) + // banners (horde) + || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_H_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_H_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_H_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) + // banners (natural) + || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2057.46f, 1735.07f, 1187.91f, -0.925024f, 0, 0, 0.446198f, -0.894934f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2032.25f, 1729.53f, 1190.33f, 1.8675f, 0, 0, 0.803857f, 0.594823f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_FEL_REALVER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2092.35f, 1775.46f, 1187.08f, -0.401426f, 0, 0, 0.199368f, -0.979925f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2047.19f, 1349.19f, 1189.0f, -1.62316f, 0, 0, 0.725374f, -0.688354f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2074.32f, 1385.78f, 1194.72f, 0.488692f, 0, 0, 0.241922f, 0.970296f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2025.13f, 1386.12f, 1192.74f, 2.3911f, 0, 0, 0.930418f, 0.366501f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2276.8f, 1400.41f, 1196.33f, 2.44346f, 0, 0, 0.939693f, 0.34202f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2305.78f, 1404.56f, 1199.38f, 1.74533f, 0, 0, 0.766044f, 0.642788f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2245.4f, 1366.41f, 1195.28f, 2.21657f, 0, 0, 0.894934f, 0.446198f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_OBJECT_N_BANNER_EY_ENTRY, 2270.84f, 1784.08f, 1186.76f, 2.42601f, 0, 0, 0.936672f, 0.350207f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT, BG_OBJECT_N_BANNER_EY_ENTRY, 2269.13f, 1737.7f, 1186.66f, 0.994838f, 0, 0, 0.477159f, 0.878817f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT, BG_OBJECT_N_BANNER_EY_ENTRY, 2300.86f, 1741.25f, 1187.7f, -0.785398f, 0, 0, 0.382683f, -0.92388f, RESPAWN_ONE_DAY) + // flags + || !AddObject(BG_EY_OBJECT_FLAG_NETHERSTORM, BG_OBJECT_FLAG2_EY_ENTRY, 2174.782227f, 1569.054688f, 1160.361938f, -1.448624f, 0, 0, 0.662620f, -0.748956f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_FLAG_FEL_REALVER, BG_OBJECT_FLAG1_EY_ENTRY, 2044.28f, 1729.68f, 1189.96f, -0.017453f, 0, 0, 0.008727f, -0.999962f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_FLAG_BLOOD_ELF, BG_OBJECT_FLAG1_EY_ENTRY, 2048.83f, 1393.65f, 1194.49f, 0.20944f, 0, 0, 0.104528f, 0.994522f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_FLAG_DRAENEI_RUINS, BG_OBJECT_FLAG1_EY_ENTRY, 2286.56f, 1402.36f, 1197.11f, 3.72381f, 0, 0, 0.957926f, -0.287016f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_FLAG_MAGE_TOWER, BG_OBJECT_FLAG1_EY_ENTRY, 2284.48f, 1731.23f, 1189.99f, 2.89725f, 0, 0, 0.992546f, 0.121869f, RESPAWN_ONE_DAY) + // tower cap + || !AddObject(BG_EY_OBJECT_TOWER_CAP_FEL_REALVER, BG_OBJECT_FR_TOWER_CAP_EY_ENTRY, 2024.600708f, 1742.819580f, 1195.157715f, 2.443461f, 0, 0, 0.939693f, 0.342020f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF, BG_OBJECT_BE_TOWER_CAP_EY_ENTRY, 2050.493164f, 1372.235962f, 1194.563477f, 1.710423f, 0, 0, 0.754710f, 0.656059f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS, BG_OBJECT_DR_TOWER_CAP_EY_ENTRY, 2301.010498f, 1386.931641f, 1197.183472f, 1.570796f, 0, 0, 0.707107f, 0.707107f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER, BG_OBJECT_HU_TOWER_CAP_EY_ENTRY, 2282.121582f, 1760.006958f, 1189.707153f, 1.919862f, 0, 0, 0.819152f, 0.573576f, RESPAWN_ONE_DAY) +) + { + sLog.outErrorDb("BatteGroundEY: Failed to spawn some object BattleGround not created!"); + return false; + } + + //buffs + for (int i = 0; i < EY_POINTS_MAX; ++i) + { + AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(m_Points_Trigger[i]); + if (!at) + { + sLog.outError("BattleGroundEY: Unknown trigger: %u", m_Points_Trigger[i]); + continue; + } + if (!AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3, Buff_Entries[0], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3 + 1, Buff_Entries[1], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) + || !AddObject(BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER + i * 3 + 2, Buff_Entries[2], at->x, at->y, at->z, 0.907571f, 0, 0, 0.438371f, 0.898794f, RESPAWN_ONE_DAY) +) + sLog.outError("BattleGroundEY: Cannot spawn buff"); + } + + WorldSafeLocsEntry const *sg = NULL; + sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_ALLIANCE); + if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE)) + { + sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!"); + return false; + } + + sg = sWorldSafeLocsStore.LookupEntry(EY_GRAVEYARD_MAIN_HORDE); + if (!sg || !AddSpiritGuide(EY_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE)) + { + sLog.outErrorDb("BatteGroundEY: Failed to spawn spirit guide! BattleGround not created!"); + return false; + } + + return true; +} + +void BattleGroundEY::Reset() +{ + //call parent's class reset + BattleGround::Reset(); + + m_TeamScores[BG_TEAM_ALLIANCE] = 0; + m_TeamScores[BG_TEAM_HORDE] = 0; + m_TeamPointsCount[BG_TEAM_ALLIANCE] = 0; + m_TeamPointsCount[BG_TEAM_HORDE] = 0; + m_HonorScoreTics[BG_TEAM_ALLIANCE] = 0; + m_HonorScoreTics[BG_TEAM_HORDE] = 0; + m_FlagState = BG_EY_FLAG_STATE_ON_BASE; + m_FlagCapturedBgObjectType = 0; + m_FlagKeeper = 0; + m_DroppedFlagGUID = 0; + m_PointAddingTimer = 0; + m_TowerCapCheckTimer = 0; + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); + m_HonorTics = (isBGWeekend) ? BG_EY_EYWeekendHonorTicks : BG_EY_NotEYWeekendHonorTicks; + + for (uint8 i = 0; i < EY_POINTS_MAX; ++i) + { + m_PointOwnedByTeam[i] = EY_POINT_NO_OWNER; + m_PointState[i] = EY_POINT_STATE_UNCONTROLLED; + m_PointBarStatus[i] = BG_EY_PROGRESS_BAR_STATE_MIDDLE; + m_PlayersNearPoint[i].clear(); + m_PlayersNearPoint[i].reserve(15); //tip size + } + m_PlayersNearPoint[EY_PLAYERS_OUT_OF_POINTS].clear(); + m_PlayersNearPoint[EY_PLAYERS_OUT_OF_POINTS].reserve(30); +} + +void BattleGroundEY::RespawnFlag(bool send_message) +{ + if (m_FlagCapturedBgObjectType > 0) + SpawnBGObject(m_FlagCapturedBgObjectType, RESPAWN_ONE_DAY); + + m_FlagCapturedBgObjectType = 0; + m_FlagState = BG_EY_FLAG_STATE_ON_BASE; + SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_IMMEDIATELY); + + if (send_message) + { + SendMessageToAll(LANG_BG_EY_RESETED_FLAG, CHAT_MSG_BG_SYSTEM_NEUTRAL); + PlaySoundToAll(BG_EY_SOUND_FLAG_RESET); // flags respawned sound... + } + + UpdateWorldState(NETHERSTORM_FLAG, 1); +} + +void BattleGroundEY::RespawnFlagAfterDrop() +{ + RespawnFlag(true); + + GameObject *obj = HashMapHolder::Find(GetDroppedFlagGUID()); + if (obj) + obj->Delete(); + else + sLog.outError("BattleGroundEY: Unknown dropped flag guid: %u",GUID_LOPART(GetDroppedFlagGUID())); + + SetDroppedFlagGUID(0); +} + +void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + BattleGround::HandleKillPlayer(player, killer); + EventPlayerDroppedFlag(player); +} + +void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + { + // if not running, do not cast things at the dropper player, neither send unnecessary messages + // just take off the aura + if (IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID()) + { + SetFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); + } + return; + } + + if (!IsFlagPickedup()) + return; + + if (GetFlagPickerGUID() != Source->GetGUID()) + return; + + SetFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); + m_FlagState = BG_EY_FLAG_STATE_ON_GROUND; + m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; + Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); + Source->CastSpell(Source, BG_EY_PLAYER_DROPPED_FLAG_SPELL, true); + //this does not work correctly :((it should remove flag carrier name) + UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_WAIT_RESPAWN); + UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_WAIT_RESPAWN); + + if (Source->GetTeam() == ALLIANCE) + SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL); + else + SendMessageToAll(LANG_BG_EY_DROPPED_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL); +} + +void BattleGroundEY::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) +{ + if (GetStatus() != STATUS_IN_PROGRESS || IsFlagPickedup() || !Source->IsWithinDistInMap(target_obj, 10)) + return; + + if (Source->GetTeam() == ALLIANCE) + { + UpdateWorldState(NETHERSTORM_FLAG_STATE_ALLIANCE, BG_EY_FLAG_STATE_ON_PLAYER); + PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE); + } + else + { + UpdateWorldState(NETHERSTORM_FLAG_STATE_HORDE, BG_EY_FLAG_STATE_ON_PLAYER); + PlaySoundToAll(BG_EY_SOUND_FLAG_PICKED_UP_HORDE); + } + + if (m_FlagState == BG_EY_FLAG_STATE_ON_BASE) + UpdateWorldState(NETHERSTORM_FLAG, 0); + m_FlagState = BG_EY_FLAG_STATE_ON_PLAYER; + + SpawnBGObject(BG_EY_OBJECT_FLAG_NETHERSTORM, RESPAWN_ONE_DAY); + SetFlagPicker(Source->GetGUID()); + //get flag aura on player + Source->CastSpell(Source, BG_EY_NETHERSTORM_FLAG_SPELL, true); + Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + + if (Source->GetTeam() == ALLIANCE) + PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, Source->GetName()); + else + PSendMessageToAll(LANG_BG_EY_HAS_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_HORDE, NULL, Source->GetName()); +} + +void BattleGroundEY::EventTeamLostPoint(Player *Source, uint32 Point) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + //Natural point + uint32 Team = m_PointOwnedByTeam[Point]; + + if (!Team) + return; + + if (Team == ALLIANCE) + { + m_TeamPointsCount[BG_TEAM_ALLIANCE]--; + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance, RESPAWN_ONE_DAY); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 1, RESPAWN_ONE_DAY); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeAlliance + 2, RESPAWN_ONE_DAY); + } + else + { + m_TeamPointsCount[BG_TEAM_HORDE]--; + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde, RESPAWN_ONE_DAY); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 1, RESPAWN_ONE_DAY); + SpawnBGObject(m_LoosingPointTypes[Point].DespawnObjectTypeHorde + 2, RESPAWN_ONE_DAY); + } + + SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType + 1, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_LoosingPointTypes[Point].SpawnNeutralObjectType + 2, RESPAWN_IMMEDIATELY); + + //buff isn't despawned + + m_PointOwnedByTeam[Point] = EY_POINT_NO_OWNER; + m_PointState[Point] = EY_POINT_NO_OWNER; + + if (Team == ALLIANCE) + SendMessageToAll(m_LoosingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(m_LoosingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); + + UpdatePointsIcons(Team, Point); + UpdatePointsCount(Team); + + //remove bonus honor aura trigger creature when node is lost + if (Point < EY_POINTS_MAX) + DelCreature(Point + 6);//NULL checks are in DelCreature! 0-5 spirit guides +} + +void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + uint32 Team = Source->GetTeam(); + + SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType, RESPAWN_ONE_DAY); + SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType + 1, RESPAWN_ONE_DAY); + SpawnBGObject(m_CapturingPointTypes[Point].DespawnNeutralObjectType + 2, RESPAWN_ONE_DAY); + + if (Team == ALLIANCE) + { + m_TeamPointsCount[BG_TEAM_ALLIANCE]++; + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 1, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeAlliance + 2, RESPAWN_IMMEDIATELY); + } + else + { + m_TeamPointsCount[BG_TEAM_HORDE]++; + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 1, RESPAWN_IMMEDIATELY); + SpawnBGObject(m_CapturingPointTypes[Point].SpawnObjectTypeHorde + 2, RESPAWN_IMMEDIATELY); + } + + //buff isn't respawned + + m_PointOwnedByTeam[Point] = Team; + m_PointState[Point] = EY_POINT_UNDER_CONTROL; + + if (Team == ALLIANCE) + SendMessageToAll(m_CapturingPointTypes[Point].MessageIdAlliance,CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(m_CapturingPointTypes[Point].MessageIdHorde,CHAT_MSG_BG_SYSTEM_HORDE, Source); + + if (m_BgCreatures[Point]) + DelCreature(Point); + + WorldSafeLocsEntry const *sg = NULL; + sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveYardId); + if (!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, Team)) + sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u", + Point, Team, m_CapturingPointTypes[Point].GraveYardId); + +// SpawnBGCreature(Point,RESPAWN_IMMEDIATELY); + + UpdatePointsIcons(Team, Point); + UpdatePointsCount(Team); + + if (Point >= EY_POINTS_MAX) + return; + + Creature* trigger = GetBGCreature(Point + 6);//0-5 spirit guides + if (!trigger) + trigger = AddCreature(WORLD_TRIGGER,Point+6,Team,BG_EY_TriggerPositions[Point][0],BG_EY_TriggerPositions[Point][1],BG_EY_TriggerPositions[Point][2],BG_EY_TriggerPositions[Point][3]); + + //add bonus honor aura trigger creature when node is accupied + //cast bonus aura (+50% honor in 25yards) + //aura should only apply to players who have accupied the node, set correct faction for trigger + if (trigger) + { + trigger->setFaction(Team == ALLIANCE ? 84 : 83); + trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); + } +} + +void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType) +{ + if (GetStatus() != STATUS_IN_PROGRESS || GetFlagPickerGUID() != Source->GetGUID()) + return; + + SetFlagPicker(0); + m_FlagState = BG_EY_FLAG_STATE_WAIT_RESPAWN; + Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); + + Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + + if (Source->GetTeam() == ALLIANCE) + PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE); + else + PlaySoundToAll(BG_EY_SOUND_FLAG_CAPTURED_HORDE); + + SpawnBGObject(BgObjectType, RESPAWN_IMMEDIATELY); + + m_FlagsTimer = BG_EY_FLAG_RESPAWN_TIME; + m_FlagCapturedBgObjectType = BgObjectType; + + uint8 team_id = 0; + if (Source->GetTeam() == ALLIANCE) + { + team_id = BG_TEAM_ALLIANCE; + SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_A, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + } + else + { + team_id = BG_TEAM_HORDE; + SendMessageToAll(LANG_BG_EY_CAPTURED_FLAG_H, CHAT_MSG_BG_SYSTEM_HORDE, Source); + } + + if (m_TeamPointsCount[team_id] > 0) + AddPoints(Source->GetTeam(), BG_EY_FlagPoints[m_TeamPointsCount[team_id] - 1]); + + UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); +} + +void BattleGroundEY::UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor) +{ + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); + if (itr == m_PlayerScores.end()) // player not found + return; + + switch(type) + { + case SCORE_FLAG_CAPTURES: // flags captured + ((BattleGroundEYScore*)itr->second)->FlagCaptures += value; + break; + default: + BattleGround::UpdatePlayerScore(Source, type, value, doAddHonor); + break; + } +} + +void BattleGroundEY::FillInitialWorldStates(WorldPacket& data) +{ + data << uint32(EY_HORDE_BASE) << uint32(m_TeamPointsCount[BG_TEAM_HORDE]); + data << uint32(EY_ALLIANCE_BASE) << uint32(m_TeamPointsCount[BG_TEAM_ALLIANCE]); + data << uint32(0xab6) << uint32(0x0); + data << uint32(0xab5) << uint32(0x0); + data << uint32(0xab4) << uint32(0x0); + data << uint32(0xab3) << uint32(0x0); + data << uint32(0xab2) << uint32(0x0); + data << uint32(0xab1) << uint32(0x0); + data << uint32(0xab0) << uint32(0x0); + data << uint32(0xaaf) << uint32(0x0); + + data << uint32(DRAENEI_RUINS_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[DRAENEI_RUINS] == HORDE && m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL); + + data << uint32(DRAENEI_RUINS_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[DRAENEI_RUINS] == ALLIANCE && m_PointState[DRAENEI_RUINS] == EY_POINT_UNDER_CONTROL); + + data << uint32(DRAENEI_RUINS_UNCONTROL) << uint32(m_PointState[DRAENEI_RUINS] != EY_POINT_UNDER_CONTROL); + + data << uint32(MAGE_TOWER_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[MAGE_TOWER] == ALLIANCE && m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL); + + data << uint32(MAGE_TOWER_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[MAGE_TOWER] == HORDE && m_PointState[MAGE_TOWER] == EY_POINT_UNDER_CONTROL); + + data << uint32(MAGE_TOWER_UNCONTROL) << uint32(m_PointState[MAGE_TOWER] != EY_POINT_UNDER_CONTROL); + + data << uint32(FEL_REAVER_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[FEL_REALVER] == HORDE && m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL); + + data << uint32(FEL_REAVER_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[FEL_REALVER] == ALLIANCE && m_PointState[FEL_REALVER] == EY_POINT_UNDER_CONTROL); + + data << uint32(FEL_REAVER_UNCONTROL) << uint32(m_PointState[FEL_REALVER] != EY_POINT_UNDER_CONTROL); + + data << uint32(BLOOD_ELF_HORDE_CONTROL) << uint32(m_PointOwnedByTeam[BLOOD_ELF] == HORDE && m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL); + + data << uint32(BLOOD_ELF_ALLIANCE_CONTROL) << uint32(m_PointOwnedByTeam[BLOOD_ELF] == ALLIANCE && m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL); + + data << uint32(BLOOD_ELF_UNCONTROL) << uint32(m_PointState[BLOOD_ELF] != EY_POINT_UNDER_CONTROL); + + data << uint32(NETHERSTORM_FLAG) << uint32(m_FlagState == BG_EY_FLAG_STATE_ON_BASE); + + data << uint32(0xad2) << uint32(0x1); + data << uint32(0xad1) << uint32(0x1); + data << uint32(0xabe) << uint32(GetTeamScore(HORDE)); + data << uint32(0xabd) << uint32(GetTeamScore(ALLIANCE)); + data << uint32(0xa05) << uint32(0x8e); + data << uint32(0xaa0) << uint32(0x0); + data << uint32(0xa9f) << uint32(0x0); + data << uint32(0xa9e) << uint32(0x0); + data << uint32(0xc0d) << uint32(0x17b); +} + +WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player) +{ + uint32 g_id = 0; + + switch(player->GetTeam()) + { + case ALLIANCE: g_id = EY_GRAVEYARD_MAIN_ALLIANCE; break; + case HORDE: g_id = EY_GRAVEYARD_MAIN_HORDE; break; + default: return NULL; + } + + float distance, nearestDistance; + + WorldSafeLocsEntry const* entry = NULL; + WorldSafeLocsEntry const* nearestEntry = NULL; + entry = sWorldSafeLocsStore.LookupEntry(g_id); + nearestEntry = entry; + + if (!entry) + { + sLog.outError("BattleGroundEY: Not found the main team graveyard. Graveyard system isn't working!"); + return NULL; + } + + float plr_x = player->GetPositionX(); + float plr_y = player->GetPositionY(); + float plr_z = player->GetPositionZ(); + + distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z); + nearestDistance = distance; + + for (uint8 i = 0; i < EY_POINTS_MAX; ++i) + { + if (m_PointOwnedByTeam[i] == player->GetTeam() && m_PointState[i] == EY_POINT_UNDER_CONTROL) + { + entry = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[i].GraveYardId); + if (!entry) + sLog.outError("BattleGroundEY: Not found graveyard: %u",m_CapturingPointTypes[i].GraveYardId); + else + { + distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z); + if (distance < nearestDistance) + { + nearestDistance = distance; + nearestEntry = entry; + } + } + } + } + + return nearestEntry; +} + +bool BattleGroundEY::IsAllNodesConrolledByTeam(uint32 team) const +{ + uint32 count = 0; + for (int i = 0; i < EY_POINTS_MAX; ++i) + if (m_PointOwnedByTeam[i] == team && m_PointState[i] == EY_POINT_UNDER_CONTROL) + ++count; + + return count == EY_POINTS_MAX; +} diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundEY.h b/src/server/game/BattleGrounds/Zones/BattleGroundEY.h new file mode 100644 index 00000000000..4fe23c4c821 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundEY.h @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDEY_H +#define __BATTLEGROUNDEY_H + +#include "Language.h" + +class BattleGround; + +#define BG_EY_FLAG_RESPAWN_TIME (8*IN_MILISECONDS) //8 seconds +#define BG_EY_FPOINTS_TICK_TIME (2*IN_MILISECONDS) //2 seconds + +enum BG_EY_WorldStates +{ + EY_ALLIANCE_RESOURCES = 2749, + EY_HORDE_RESOURCES = 2750, + EY_ALLIANCE_BASE = 2752, + EY_HORDE_BASE = 2753, + DRAENEI_RUINS_HORDE_CONTROL = 2733, + DRAENEI_RUINS_ALLIANCE_CONTROL = 2732, + DRAENEI_RUINS_UNCONTROL = 2731, + MAGE_TOWER_ALLIANCE_CONTROL = 2730, + MAGE_TOWER_HORDE_CONTROL = 2729, + MAGE_TOWER_UNCONTROL = 2728, + FEL_REAVER_HORDE_CONTROL = 2727, + FEL_REAVER_ALLIANCE_CONTROL = 2726, + FEL_REAVER_UNCONTROL = 2725, + BLOOD_ELF_HORDE_CONTROL = 2724, + BLOOD_ELF_ALLIANCE_CONTROL = 2723, + BLOOD_ELF_UNCONTROL = 2722, + PROGRESS_BAR_PERCENT_GREY = 2720, //100 = empty (only grey), 0 = blue|red (no grey) + PROGRESS_BAR_STATUS = 2719, //50 init!, 48 ... hordak bere .. 33 .. 0 = full 100% hordacky , 100 = full alliance + PROGRESS_BAR_SHOW = 2718, //1 init, 0 druhy send - bez messagu, 1 = controlled aliance + NETHERSTORM_FLAG = 2757, + //set to 2 when flag is picked up, and to 1 if it is dropped + NETHERSTORM_FLAG_STATE_ALLIANCE = 2769, + NETHERSTORM_FLAG_STATE_HORDE = 2770 +}; + +enum BG_EY_ProgressBarConsts +{ + BG_EY_POINT_MAX_CAPTURERS_COUNT = 5, + BG_EY_POINT_RADIUS = 70, + BG_EY_PROGRESS_BAR_DONT_SHOW = 0, + BG_EY_PROGRESS_BAR_SHOW = 1, + BG_EY_PROGRESS_BAR_PERCENT_GREY = 40, + BG_EY_PROGRESS_BAR_STATE_MIDDLE = 50, + BG_EY_PROGRESS_BAR_HORDE_CONTROLLED = 0, + BG_EY_PROGRESS_BAR_NEUTRAL_LOW = 30, + BG_EY_PROGRESS_BAR_NEUTRAL_HIGH = 70, + BG_EY_PROGRESS_BAR_ALI_CONTROLLED = 100 +}; + +enum BG_EY_Sounds +{ + //strange ids, but sure about them + BG_EY_SOUND_FLAG_PICKED_UP_ALLIANCE = 8212, + BG_EY_SOUND_FLAG_CAPTURED_HORDE = 8213, + BG_EY_SOUND_FLAG_PICKED_UP_HORDE = 8174, + BG_EY_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, + BG_EY_SOUND_FLAG_RESET = 8192 +}; + +enum BG_EY_Spells +{ + BG_EY_NETHERSTORM_FLAG_SPELL = 34976, + BG_EY_PLAYER_DROPPED_FLAG_SPELL = 34991 +}; + +enum EYBattleGroundObjectEntry +{ + BG_OBJECT_A_DOOR_EY_ENTRY = 184719, //Alliance door + BG_OBJECT_H_DOOR_EY_ENTRY = 184720, //Horde door + BG_OBJECT_FLAG1_EY_ENTRY = 184493, //Netherstorm flag (generic) + BG_OBJECT_FLAG2_EY_ENTRY = 184141, //Netherstorm flag (flagstand) + BG_OBJECT_FLAG3_EY_ENTRY = 184142, //Netherstorm flag (flagdrop) + BG_OBJECT_A_BANNER_EY_ENTRY = 184381, //Visual Banner (Alliance) + BG_OBJECT_H_BANNER_EY_ENTRY = 184380, //Visual Banner (Horde) + BG_OBJECT_N_BANNER_EY_ENTRY = 184382, //Visual Banner (Neutral) + BG_OBJECT_BE_TOWER_CAP_EY_ENTRY = 184080, //BE Tower Cap Pt + BG_OBJECT_FR_TOWER_CAP_EY_ENTRY = 184081, //Fel Reaver Cap Pt + BG_OBJECT_HU_TOWER_CAP_EY_ENTRY = 184082, //Human Tower Cap Pt + BG_OBJECT_DR_TOWER_CAP_EY_ENTRY = 184083 //Draenei Tower Cap Pt +}; + +enum EYBattleGroundPointsTrigger +{ + TR_BLOOD_ELF_POINT = 4476, + TR_FEL_REALVER_POINT = 4514, + TR_MAGE_TOWER_POINT = 4516, + TR_DRAENEI_RUINS_POINT = 4518, + TR_BLOOD_ELF_BUFF = 4568, + TR_FEL_REALVER_BUFF = 4569, + TR_MAGE_TOWER_BUFF = 4570, + TR_DRAENEI_RUINS_BUFF = 4571 +}; + +enum EYBattleGroundGaveyards +{ + EY_GRAVEYARD_MAIN_ALLIANCE = 1103, + EY_GRAVEYARD_MAIN_HORDE = 1104, + EY_GRAVEYARD_FEL_REALVER = 1105, + EY_GRAVEYARD_BLOOD_ELF = 1106, + EY_GRAVEYARD_DRAENEI_RUINS = 1107, + EY_GRAVEYARD_MAGE_TOWER = 1108 +}; + +enum EYBattleGroundPoints +{ + FEL_REALVER = 0, + BLOOD_ELF = 1, + DRAENEI_RUINS = 2, + MAGE_TOWER = 3, + + EY_PLAYERS_OUT_OF_POINTS = 4, + EY_POINTS_MAX = 4 +}; + +enum EYBattleGroundCreaturesTypes +{ + EY_SPIRIT_FEL_REALVER = 0, + EY_SPIRIT_BLOOD_ELF = 1, + EY_SPIRIT_DRAENEI_RUINS = 2, + EY_SPIRIT_MAGE_TOWER = 3, + EY_SPIRIT_MAIN_ALLIANCE = 4, + EY_SPIRIT_MAIN_HORDE = 5, + + EY_TRIGGER_FEL_REALVER = 6, + EY_TRIGGER_BLOOD_ELF = 7, + EY_TRIGGER_DRAENEI_RUINS = 8, + EY_TRIGGER_MAGE_TOWER = 9, + + BG_EY_CREATURES_MAX = 10 +}; + +enum EYBattleGroundObjectTypes +{ + BG_EY_OBJECT_DOOR_A = 0, + BG_EY_OBJECT_DOOR_H = 1, + BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER = 2, + BG_EY_OBJECT_A_BANNER_FEL_REALVER_LEFT = 3, + BG_EY_OBJECT_A_BANNER_FEL_REALVER_RIGHT = 4, + BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER = 5, + BG_EY_OBJECT_A_BANNER_BLOOD_ELF_LEFT = 6, + BG_EY_OBJECT_A_BANNER_BLOOD_ELF_RIGHT = 7, + BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER = 8, + BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_LEFT = 9, + BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_RIGHT = 10, + BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER = 11, + BG_EY_OBJECT_A_BANNER_MAGE_TOWER_LEFT = 12, + BG_EY_OBJECT_A_BANNER_MAGE_TOWER_RIGHT = 13, + BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER = 14, + BG_EY_OBJECT_H_BANNER_FEL_REALVER_LEFT = 15, + BG_EY_OBJECT_H_BANNER_FEL_REALVER_RIGHT = 16, + BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER = 17, + BG_EY_OBJECT_H_BANNER_BLOOD_ELF_LEFT = 18, + BG_EY_OBJECT_H_BANNER_BLOOD_ELF_RIGHT = 19, + BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER = 20, + BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_LEFT = 21, + BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_RIGHT = 22, + BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER = 23, + BG_EY_OBJECT_H_BANNER_MAGE_TOWER_LEFT = 24, + BG_EY_OBJECT_H_BANNER_MAGE_TOWER_RIGHT = 25, + BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER = 26, + BG_EY_OBJECT_N_BANNER_FEL_REALVER_LEFT = 27, + BG_EY_OBJECT_N_BANNER_FEL_REALVER_RIGHT = 28, + BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER = 29, + BG_EY_OBJECT_N_BANNER_BLOOD_ELF_LEFT = 30, + BG_EY_OBJECT_N_BANNER_BLOOD_ELF_RIGHT = 31, + BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER = 32, + BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_LEFT = 33, + BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_RIGHT = 34, + BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER = 35, + BG_EY_OBJECT_N_BANNER_MAGE_TOWER_LEFT = 36, + BG_EY_OBJECT_N_BANNER_MAGE_TOWER_RIGHT = 37, + BG_EY_OBJECT_TOWER_CAP_FEL_REALVER = 38, + BG_EY_OBJECT_TOWER_CAP_BLOOD_ELF = 39, + BG_EY_OBJECT_TOWER_CAP_DRAENEI_RUINS = 40, + BG_EY_OBJECT_TOWER_CAP_MAGE_TOWER = 41, + BG_EY_OBJECT_FLAG_NETHERSTORM = 42, + BG_EY_OBJECT_FLAG_FEL_REALVER = 43, + BG_EY_OBJECT_FLAG_BLOOD_ELF = 44, + BG_EY_OBJECT_FLAG_DRAENEI_RUINS = 45, + BG_EY_OBJECT_FLAG_MAGE_TOWER = 46, + //buffs + BG_EY_OBJECT_SPEEDBUFF_FEL_REALVER = 47, + BG_EY_OBJECT_REGENBUFF_FEL_REALVER = 48, + BG_EY_OBJECT_BERSERKBUFF_FEL_REALVER = 49, + BG_EY_OBJECT_SPEEDBUFF_BLOOD_ELF = 50, + BG_EY_OBJECT_REGENBUFF_BLOOD_ELF = 51, + BG_EY_OBJECT_BERSERKBUFF_BLOOD_ELF = 52, + BG_EY_OBJECT_SPEEDBUFF_DRAENEI_RUINS = 53, + BG_EY_OBJECT_REGENBUFF_DRAENEI_RUINS = 54, + BG_EY_OBJECT_BERSERKBUFF_DRAENEI_RUINS = 55, + BG_EY_OBJECT_SPEEDBUFF_MAGE_TOWER = 56, + BG_EY_OBJECT_REGENBUFF_MAGE_TOWER = 57, + BG_EY_OBJECT_BERSERKBUFF_MAGE_TOWER = 58, + BG_EY_OBJECT_MAX = 59 +}; + +#define BG_EY_NotEYWeekendHonorTicks 330 +#define BG_EY_EYWeekendHonorTicks 200 + +enum BG_EY_Score +{ + BG_EY_WARNING_NEAR_VICTORY_SCORE = 1400, + BG_EY_MAX_TEAM_SCORE = 1600 +}; + +enum BG_EY_FlagState +{ + BG_EY_FLAG_STATE_ON_BASE = 0, + BG_EY_FLAG_STATE_WAIT_RESPAWN = 1, + BG_EY_FLAG_STATE_ON_PLAYER = 2, + BG_EY_FLAG_STATE_ON_GROUND = 3 +}; + +enum EYBattleGroundPointState +{ + EY_POINT_NO_OWNER = 0, + EY_POINT_STATE_UNCONTROLLED = 0, + EY_POINT_UNDER_CONTROL = 3 +}; + +struct BattleGroundEYPointIconsStruct +{ + BattleGroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex) + : WorldStateControlIndex(_WorldStateControlIndex), WorldStateAllianceControlledIndex(_WorldStateAllianceControlledIndex), WorldStateHordeControlledIndex(_WorldStateHordeControlledIndex) {} + uint32 WorldStateControlIndex; + uint32 WorldStateAllianceControlledIndex; + uint32 WorldStateHordeControlledIndex; +}; + +// x, y, z, o +const float BG_EY_TriggerPositions[EY_POINTS_MAX][4] = { + {2044.28f, 1729.68f, 1189.96f, -0.017453f}, // FEL_REALVER center + {2048.83f, 1393.65f, 1194.49f, 0.20944f}, // BLOOD_ELF center + {2286.56f, 1402.36f, 1197.11f, 3.72381f}, // DRAENEI_RUINS center + {2284.48f, 1731.23f, 1189.99f, 2.89725f} // MAGE_TOWER center +}; + +struct BattleGroundEYLoosingPointStruct +{ + BattleGroundEYLoosingPointStruct(uint32 _SpawnNeutralObjectType, uint32 _DespawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _DespawnObjectTypeHorde, uint32 _MessageIdHorde) + : SpawnNeutralObjectType(_SpawnNeutralObjectType), + DespawnObjectTypeAlliance(_DespawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), + DespawnObjectTypeHorde(_DespawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde) + {} + + uint32 SpawnNeutralObjectType; + uint32 DespawnObjectTypeAlliance; + uint32 MessageIdAlliance; + uint32 DespawnObjectTypeHorde; + uint32 MessageIdHorde; +}; + +struct BattleGroundEYCapturingPointStruct +{ + BattleGroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId) + : DespawnNeutralObjectType(_DespawnNeutralObjectType), + SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), + SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde), + GraveYardId(_GraveYardId) + {} + + uint32 DespawnNeutralObjectType; + uint32 SpawnObjectTypeAlliance; + uint32 MessageIdAlliance; + uint32 SpawnObjectTypeHorde; + uint32 MessageIdHorde; + uint32 GraveYardId; +}; + +const uint8 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10}; +const uint32 BG_EY_FlagPoints[EY_POINTS_MAX] = {75, 85, 100, 500}; + +//constant arrays: +const BattleGroundEYPointIconsStruct m_PointsIconStruct[EY_POINTS_MAX] = +{ + BattleGroundEYPointIconsStruct(FEL_REAVER_UNCONTROL, FEL_REAVER_ALLIANCE_CONTROL, FEL_REAVER_HORDE_CONTROL), + BattleGroundEYPointIconsStruct(BLOOD_ELF_UNCONTROL, BLOOD_ELF_ALLIANCE_CONTROL, BLOOD_ELF_HORDE_CONTROL), + BattleGroundEYPointIconsStruct(DRAENEI_RUINS_UNCONTROL, DRAENEI_RUINS_ALLIANCE_CONTROL, DRAENEI_RUINS_HORDE_CONTROL), + BattleGroundEYPointIconsStruct(MAGE_TOWER_UNCONTROL, MAGE_TOWER_ALLIANCE_CONTROL, MAGE_TOWER_HORDE_CONTROL) +}; +const BattleGroundEYLoosingPointStruct m_LoosingPointTypes[EY_POINTS_MAX] = +{ + BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_LOST_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_LOST_H_F_RUINS), + BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_LOST_H_B_TOWER), + BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_LOST_H_D_RUINS), + BattleGroundEYLoosingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_LOST_H_M_TOWER) +}; +const BattleGroundEYCapturingPointStruct m_CapturingPointTypes[EY_POINTS_MAX] = +{ + BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_FEL_REALVER_CENTER, BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_TAKEN_A_F_RUINS, BG_EY_OBJECT_H_BANNER_FEL_REALVER_CENTER, LANG_BG_EY_HAS_TAKEN_H_F_RUINS, EY_GRAVEYARD_FEL_REALVER), + BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_BLOOD_ELF_CENTER, BG_EY_OBJECT_A_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_A_B_TOWER, BG_EY_OBJECT_H_BANNER_BLOOD_ELF_CENTER, LANG_BG_EY_HAS_TAKEN_H_B_TOWER, EY_GRAVEYARD_BLOOD_ELF), + BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_DRAENEI_RUINS_CENTER, BG_EY_OBJECT_A_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_A_D_RUINS, BG_EY_OBJECT_H_BANNER_DRAENEI_RUINS_CENTER, LANG_BG_EY_HAS_TAKEN_H_D_RUINS, EY_GRAVEYARD_DRAENEI_RUINS), + BattleGroundEYCapturingPointStruct(BG_EY_OBJECT_N_BANNER_MAGE_TOWER_CENTER, BG_EY_OBJECT_A_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_A_M_TOWER, BG_EY_OBJECT_H_BANNER_MAGE_TOWER_CENTER, LANG_BG_EY_HAS_TAKEN_H_M_TOWER, EY_GRAVEYARD_MAGE_TOWER) +}; + +class BattleGroundEYScore : public BattleGroundScore +{ + public: + BattleGroundEYScore () : FlagCaptures(0) {}; + virtual ~BattleGroundEYScore() {}; + uint32 FlagCaptures; +}; + +class BattleGroundEY : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundEY(); + ~BattleGroundEY(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + /* BG Flags */ + uint64 GetFlagPickerGUID() const { return m_FlagKeeper; } + void SetFlagPicker(uint64 guid) { m_FlagKeeper = guid; } + bool IsFlagPickedup() const { return m_FlagKeeper != 0; } + uint8 GetFlagState() const { return m_FlagState; } + void RespawnFlag(bool send_message); + void RespawnFlagAfterDrop(); + + void RemovePlayer(Player *plr,uint64 guid); + void HandleBuffUse(uint64 const& buff_guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + void HandleKillPlayer(Player *player, Player *killer); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); + virtual bool SetupBattleGround(); + virtual void Reset(); + void UpdateTeamScore(uint32 Team); + void EndBattleGround(uint32 winner); + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); + virtual void FillInitialWorldStates(WorldPacket& data); + void SetDroppedFlagGUID(uint64 guid) { m_DroppedFlagGUID = guid;} + uint64 GetDroppedFlagGUID() const { return m_DroppedFlagGUID;} + + /* Battleground Events */ + virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); + virtual void EventPlayerDroppedFlag(Player *Source); + + /* achievement req. */ + bool IsAllNodesConrolledByTeam(uint32 team) const; + private: + void EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType); + void EventTeamCapturedPoint(Player *Source, uint32 Point); + void EventTeamLostPoint(Player *Source, uint32 Point); + void UpdatePointsCount(uint32 Team); + void UpdatePointsIcons(uint32 Team, uint32 Point); + + /* Point status updating procedures */ + void CheckSomeoneLeftPoint(); + void CheckSomeoneJoinedPoint(); + void UpdatePointStatuses(); + + /* Scorekeeping */ + uint32 GetTeamScore(uint32 Team) const { return m_TeamScores[GetTeamIndexByTeamId(Team)]; } + void AddPoints(uint32 Team, uint32 Points); + + void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } + void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } + + uint32 m_HonorScoreTics[2]; + uint32 m_TeamPointsCount[2]; + + uint32 m_Points_Trigger[EY_POINTS_MAX]; + + uint64 m_FlagKeeper; // keepers guid + uint64 m_DroppedFlagGUID; + uint32 m_FlagCapturedBgObjectType; // type that should be despawned when flag is captured + uint8 m_FlagState; // for checking flag state + int32 m_FlagsTimer; + int32 m_TowerCapCheckTimer; + + uint32 m_PointOwnedByTeam[EY_POINTS_MAX]; + uint8 m_PointState[EY_POINTS_MAX]; + int32 m_PointBarStatus[EY_POINTS_MAX]; + typedef std::vector PlayersNearPointType; + PlayersNearPointType m_PlayersNearPoint[EY_POINTS_MAX + 1]; + uint8 m_CurrentPointPlayersCount[2*EY_POINTS_MAX]; + + int32 m_PointAddingTimer; + uint32 m_HonorTics; +}; +#endif + diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundIC.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundIC.cpp new file mode 100644 index 00000000000..8dbcc81e5c6 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundIC.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundIC.h" +#include "Language.h" + +BattleGroundIC::BattleGroundIC() +{ + m_BgCreatures.resize(2); + m_BgObjects.resize(5); + //TODO FIX ME! + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; +} + +BattleGroundIC::~BattleGroundIC() +{ + +} + +void BattleGroundIC::Update(uint32 diff) +{ + BattleGround::Update(diff); +} + +void BattleGroundIC::StartingEventCloseDoors() +{ +} + +void BattleGroundIC::StartingEventOpenDoors() +{ +} + +void BattleGroundIC::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundICScore* sc = new BattleGroundICScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundIC::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) +{ + +} + +void BattleGroundIC::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if (GetStatus() != STATUS_IN_PROGRESS) + return; +} + +void BattleGroundIC::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) +{ + + std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if (itr == m_PlayerScores.end()) // player not found... + return; + + BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); +} + +bool BattleGroundIC::SetupBattleGround() +{ + AddObject(0, 195157, 459.72f, -419.93f, 42.55f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); + AddObject(1, 195158, 797.72f, -1009.48f, 138.52f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); + AddObject(2, 195338, 418.98f, -838.33f, 51.09f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); + AddObject(3, 195343, 1267.45f, -390.88f, 24.23f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); + AddObject(4, 195333, 769.27f, -833.53f, 9.57f, 0, 0, 0, 0.9996573f, 0.02617699f, 10*MINUTE); + SpawnLeader(ALLIANCE); + SpawnLeader(HORDE); + return true; +} + +void BattleGroundIC::SpawnLeader(uint32 teamid) +{ + if (teamid == ALLIANCE) + AddCreature(34924, 0, ALLIANCE, 307.03f, -833.04f, 48.91f, 6.23f, 10*MINUTE); + else + AddCreature(34922, 1, HORDE, 1264.42f, -766.80f, 48.91f, 3.28f, 10*MINUTE); +} + +void BattleGroundIC::HandleKillUnit(Creature *unit, Player * /*killer*/) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + uint32 entry = unit->GetEntry(); + if (entry == 34924) + { + RewardHonorToTeam(500,HORDE); + EndBattleGround(HORDE); + } + else if (entry == 34922) + { + RewardHonorToTeam(500,ALLIANCE); + EndBattleGround(ALLIANCE); + } +} + +void BattleGroundIC::EndBattleGround(uint32 winner) +{ + BattleGround::EndBattleGround(winner); +} + +void BattleGroundIC::EventPlayerClickedOnFlag(Player * /*source*/, GameObject* /*target_obj*/) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; +} diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundIC.h b/src/server/game/BattleGrounds/Zones/BattleGroundIC.h new file mode 100644 index 00000000000..e49ea01e850 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundIC.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDIC_H +#define __BATTLEGROUNDIC_H + +class BattleGround; + +enum Buffs +{ + OIL_REFINERY = 68719, + QUARRY = 68720 +}; + +class BattleGroundICScore : public BattleGroundScore +{ + public: + BattleGroundICScore() {}; + virtual ~BattleGroundICScore() {}; +}; + +class BattleGroundIC : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundIC(); + ~BattleGroundIC(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + void RemovePlayer(Player *plr,uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + void SpawnLeader(uint32 teamid); + void HandleKillUnit(Creature *unit, Player *killer); + void EndBattleGround(uint32 winner); + void EventPlayerClickedOnFlag(Player *source, GameObject* /*target_obj*/); + + /* Scorekeeping */ + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); + + private: +}; +#endif diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundNA.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundNA.cpp new file mode 100644 index 00000000000..793cf13b3cb --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundNA.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundNA.h" +#include "Language.h" +#include "Object.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "WorldPacket.h" + +BattleGroundNA::BattleGroundNA() +{ + m_BgObjects.resize(BG_NA_OBJECT_MAX); + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; +} + +BattleGroundNA::~BattleGroundNA() +{ + +} + +void BattleGroundNA::Update(uint32 diff) +{ + BattleGround::Update(diff); + + /*if (GetStatus() == STATUS_IN_PROGRESS) + { + // update something + }*/ +} + +void BattleGroundNA::StartingEventCloseDoors() +{ + for (uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); +} + +void BattleGroundNA::StartingEventOpenDoors() +{ + for (uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; ++i) + DoorOpen(i); + + for (uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; ++i) + SpawnBGObject(i, 60); +} + +void BattleGroundNA::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundNAScore* sc = new BattleGroundNAScore; + + m_PlayerScores[plr->GetGUID()] = sc; + + UpdateArenaWorldState(); +} + +void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) +{ + if (GetStatus() == STATUS_WAIT_LEAVE) + return; + + UpdateArenaWorldState(); + CheckArenaWinConditions(); +} + +void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + if (!killer) + { + sLog.outError("BattleGroundNA: Killer player not found"); + return; + } + + BattleGround::HandleKillPlayer(player,killer); + + UpdateArenaWorldState(); + CheckArenaWinConditions(); +} + +bool BattleGroundNA::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),4055.504395,2919.660645,13.611241,player->GetOrientation(),false); + return true; +} + +void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + //uint32 SpellId = 0; + //uint64 buff_guid = 0; + switch(Trigger) + { + case 4536: // buff trigger? + case 4537: // buff trigger? + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + //if (buff_guid) + // HandleTriggerBuff(buff_guid,Source); +} + +void BattleGroundNA::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0xa11) << uint32(1); // 9 + UpdateArenaWorldState(); +} + +void BattleGroundNA::Reset() +{ + //call parent's class reset + BattleGround::Reset(); +} + +bool BattleGroundNA::SetupBattleGround() +{ + // gates + if (!AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) + || !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) + { + sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!"); + return false; + } + + return true; +} + +/* +20:12:14 id:036668 [S2C] SMSG_INIT_WORLD_STATES (706 = 0x02C2) len: 86 +0000: 2f 02 00 00 72 0e 00 00 00 00 00 00 09 00 11 0a | /...r........... +0010: 00 00 01 00 00 00 0f 0a 00 00 00 00 00 00 10 0a | ................ +0020: 00 00 00 00 00 00 d4 08 00 00 00 00 00 00 d8 08 | ................ +0030: 00 00 00 00 00 00 d7 08 00 00 00 00 00 00 d6 08 | ................ +0040: 00 00 00 00 00 00 d5 08 00 00 00 00 00 00 d3 08 | ................ +0050: 00 00 00 00 00 00 | ...... +*/ diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundNA.h b/src/server/game/BattleGrounds/Zones/BattleGroundNA.h new file mode 100644 index 00000000000..a11d311515d --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundNA.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDNA_H +#define __BATTLEGROUNDNA_H + +class BattleGround; + +enum BattleGroundNAObjectTypes +{ + BG_NA_OBJECT_DOOR_1 = 0, + BG_NA_OBJECT_DOOR_2 = 1, + BG_NA_OBJECT_DOOR_3 = 2, + BG_NA_OBJECT_DOOR_4 = 3, + BG_NA_OBJECT_BUFF_1 = 4, + BG_NA_OBJECT_BUFF_2 = 5, + BG_NA_OBJECT_MAX = 6 +}; + +enum BattleGroundNAObjects +{ + BG_NA_OBJECT_TYPE_DOOR_1 = 183978, + BG_NA_OBJECT_TYPE_DOOR_2 = 183980, + BG_NA_OBJECT_TYPE_DOOR_3 = 183977, + BG_NA_OBJECT_TYPE_DOOR_4 = 183979, + BG_NA_OBJECT_TYPE_BUFF_1 = 184663, + BG_NA_OBJECT_TYPE_BUFF_2 = 184664 +}; + +class BattleGroundNAScore : public BattleGroundScore +{ + public: + BattleGroundNAScore() {}; + virtual ~BattleGroundNAScore() {}; + //TODO fix me +}; + +class BattleGroundNA : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundNA(); + ~BattleGroundNA(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + virtual void Reset(); + virtual void FillInitialWorldStates(WorldPacket &d); + void HandleKillPlayer(Player* player, Player *killer); + bool HandlePlayerUnderMap(Player * plr); +}; +#endif diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundRB.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundRB.cpp new file mode 100644 index 00000000000..cf22154ed11 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundRB.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundRB.h" +#include "Language.h" + +BattleGroundRB::BattleGroundRB() +{ + //TODO FIX ME! + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = 0; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; +} + +BattleGroundRB::~BattleGroundRB() +{ + +} + +void BattleGroundRB::Update(uint32 diff) +{ + BattleGround::Update(diff); +} + +void BattleGroundRB::StartingEventCloseDoors() +{ +} + +void BattleGroundRB::StartingEventOpenDoors() +{ +} + +void BattleGroundRB::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundRBScore* sc = new BattleGroundRBScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundRB::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) +{ +} + +void BattleGroundRB::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if (GetStatus() != STATUS_IN_PROGRESS) + return; +} + +void BattleGroundRB::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) +{ + std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if (itr == m_PlayerScores.end()) // player not found... + return; + + BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); +} diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundRB.h b/src/server/game/BattleGrounds/Zones/BattleGroundRB.h new file mode 100644 index 00000000000..a40ade5adfe --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundRB.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDRB_H +#define __BATTLEGROUNDRB_H + +class BattleGround; + +class BattleGroundRBScore : public BattleGroundScore +{ + public: + BattleGroundRBScore() {}; + virtual ~BattleGroundRBScore() {}; +}; + +class BattleGroundRB : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundRB(); + ~BattleGroundRB(); + void Update(uint32 diff); + + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + void RemovePlayer(Player *plr,uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + + /* Scorekeeping */ + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); + + private: +}; +#endif diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundRL.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundRL.cpp new file mode 100644 index 00000000000..ef2ec3cfa94 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundRL.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundRL.h" +#include "Language.h" +#include "Object.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "WorldPacket.h" + +BattleGroundRL::BattleGroundRL() +{ + m_BgObjects.resize(BG_RL_OBJECT_MAX); + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; +} + +BattleGroundRL::~BattleGroundRL() +{ + +} + +void BattleGroundRL::Update(uint32 diff) +{ + BattleGround::Update(diff); + + /*if (GetStatus() == STATUS_IN_PROGRESS) + { + // update something + }*/ +} + +void BattleGroundRL::StartingEventCloseDoors() +{ + for (uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); +} + +void BattleGroundRL::StartingEventOpenDoors() +{ + for (uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; ++i) + DoorOpen(i); + + for (uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; ++i) + SpawnBGObject(i, 60); +} + +void BattleGroundRL::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundRLScore* sc = new BattleGroundRLScore; + + m_PlayerScores[plr->GetGUID()] = sc; + + UpdateArenaWorldState(); +} + +void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) +{ + if (GetStatus() == STATUS_WAIT_LEAVE) + return; + + UpdateArenaWorldState(); + CheckArenaWinConditions(); +} + +void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + if (!killer) + { + sLog.outError("Killer player not found"); + return; + } + + BattleGround::HandleKillPlayer(player,killer); + + UpdateArenaWorldState(); + CheckArenaWinConditions(); +} + +bool BattleGroundRL::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),1285.810547,1667.896851,39.957642,player->GetOrientation(),false); + return true; +} + +void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + //uint32 SpellId = 0; + //uint64 buff_guid = 0; + switch(Trigger) + { + case 4696: // buff trigger? + case 4697: // buff trigger? + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + //if (buff_guid) + // HandleTriggerBuff(buff_guid,Source); +} + +void BattleGroundRL::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0xbba) << uint32(1); // 9 + UpdateArenaWorldState(); +} + +void BattleGroundRL::Reset() +{ + //call parent's reset + BattleGround::Reset(); +} + +bool BattleGroundRL::SetupBattleGround() +{ + // gates + if (!AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) + || !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) + { + sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!"); + return false; + } + + return true; +} + +/* +Packet S->C, id 600, SMSG_INIT_WORLD_STATES (706), len 86 +0000: 3C 02 00 00 80 0F 00 00 00 00 00 00 09 00 BA 0B | <............... +0010: 00 00 01 00 00 00 B9 0B 00 00 02 00 00 00 B8 0B | ................ +0020: 00 00 00 00 00 00 D8 08 00 00 00 00 00 00 D7 08 | ................ +0030: 00 00 00 00 00 00 D6 08 00 00 00 00 00 00 D5 08 | ................ +0040: 00 00 00 00 00 00 D3 08 00 00 00 00 00 00 D4 08 | ................ +0050: 00 00 00 00 00 00 | ...... +*/ diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundRL.h b/src/server/game/BattleGrounds/Zones/BattleGroundRL.h new file mode 100644 index 00000000000..3b4c10a7c9a --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundRL.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDRL_H +#define __BATTLEGROUNDRL_H + +class BattleGround; + +enum BattleGroundRLObjectTypes +{ + BG_RL_OBJECT_DOOR_1 = 0, + BG_RL_OBJECT_DOOR_2 = 1, + BG_RL_OBJECT_BUFF_1 = 2, + BG_RL_OBJECT_BUFF_2 = 3, + BG_RL_OBJECT_MAX = 4 +}; + +enum BattleGroundRLObjects +{ + BG_RL_OBJECT_TYPE_DOOR_1 = 185918, + BG_RL_OBJECT_TYPE_DOOR_2 = 185917, + BG_RL_OBJECT_TYPE_BUFF_1 = 184663, + BG_RL_OBJECT_TYPE_BUFF_2 = 184664 +}; + +class BattleGroundRLScore : public BattleGroundScore +{ + public: + BattleGroundRLScore() {}; + virtual ~BattleGroundRLScore() {}; + //TODO fix me +}; + +class BattleGroundRL : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundRL(); + ~BattleGroundRL(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void Reset(); + virtual void FillInitialWorldStates(WorldPacket &d); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + void HandleKillPlayer(Player* player, Player *killer); + bool HandlePlayerUnderMap(Player * plr); +}; +#endif diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundRV.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundRV.cpp new file mode 100644 index 00000000000..fcc53dbbcf9 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundRV.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundRV.h" +#include "ObjectAccessor.h" +#include "Language.h" +#include "Player.h" +#include "WorldPacket.h" +#include "GameObject.h" + +BattleGroundRV::BattleGroundRV() +{ + m_BgObjects.resize(BG_RV_OBJECT_MAX); + + m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_1M; + m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_30S; + m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_15S; + m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE; + //we must set messageIds + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_ARENA_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_ARENA_THIRTY_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_ARENA_FIFTEEN_SECONDS; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_ARENA_HAS_BEGUN; +} + +BattleGroundRV::~BattleGroundRV() +{ + +} + +void BattleGroundRV::Update(uint32 diff) +{ + BattleGround::Update(diff); + + if (getTimer() < diff) + { + uint32 i; + switch(getState()) + { + case BG_RV_STATE_OPEN_FENCES: + { + setTimer(BG_RV_PILAR_TO_FIRE_TIMER); + setState(BG_RV_STATE_CLOSE_FIRE); + break; + } + case BG_RV_STATE_CLOSE_FIRE: + for (i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i) + DoorClose(i); + setTimer(BG_RV_FIRE_TO_PILAR_TIMER); + setState(BG_RV_STATE_OPEN_PILARS); + break; + case BG_RV_STATE_OPEN_PILARS: + for (i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PULLEY_2; ++i) + DoorOpen(i); + setTimer(BG_RV_PILAR_TO_FIRE_TIMER); + setState(BG_RV_STATE_OPEN_FIRE); + break; + case BG_RV_STATE_OPEN_FIRE: + for (i = BG_RV_OBJECT_FIRE_1; i <= BG_RV_OBJECT_FIREDOOR_2; ++i) + DoorOpen(i); + setTimer(BG_RV_FIRE_TO_PILAR_TIMER); + setState(BG_RV_STATE_CLOSE_PILARS); + break; + case BG_RV_STATE_CLOSE_PILARS: + uint32 i; + for (i = BG_RV_OBJECT_PILAR_1; i <= BG_RV_OBJECT_PULLEY_2; ++i) + DoorOpen(i); + setTimer(BG_RV_PILAR_TO_FIRE_TIMER); + setState(BG_RV_STATE_CLOSE_FIRE); + break; + } + } + else + setTimer(getTimer() - diff); +} + +void BattleGroundRV::StartingEventCloseDoors() +{ +} + +void BattleGroundRV::StartingEventOpenDoors() +{ + // Buff respawn + SpawnBGObject(BG_RV_OBJECT_BUFF_1, 90); + SpawnBGObject(BG_RV_OBJECT_BUFF_2, 90); + // Open fences + DoorOpen(BG_RV_OBJECT_FENCE_1); + DoorOpen(BG_RV_OBJECT_FENCE_2); + // Elevators + DoorOpen(BG_RV_OBJECT_ELEVATOR_1); + DoorOpen(BG_RV_OBJECT_ELEVATOR_2); + + setState(BG_RV_STATE_OPEN_FENCES); + setTimer(BG_RV_FIRST_TIMER); +} + +void BattleGroundRV::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundRVScore* sc = new BattleGroundRVScore; + + m_PlayerScores[plr->GetGUID()] = sc; + + UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE)); +} + +void BattleGroundRV::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) +{ + if (GetStatus() == STATUS_WAIT_LEAVE) + return; + + UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE)); + + CheckArenaWinConditions(); +} + +void BattleGroundRV::HandleKillPlayer(Player *player, Player *killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + if (!killer) + { + sLog.outError("BattleGroundRV: Killer player not found"); + return; + } + + BattleGround::HandleKillPlayer(player, killer); + + UpdateWorldState(BG_RV_WORLD_STATE_A, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(BG_RV_WORLD_STATE_H, GetAlivePlayersCountByTeam(HORDE)); + + CheckArenaWinConditions(); +} + +bool BattleGroundRV::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(), 763.5, -284, 28.276, 2.422, false); + return true; +} + + +void BattleGroundRV::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + switch(Trigger) + { + case 5224: + case 5226: + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } +} + +void BattleGroundRV::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(BG_RV_WORLD_STATE_A) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); + data << uint32(BG_RV_WORLD_STATE_H) << uint32(GetAlivePlayersCountByTeam(HORDE)); + data << uint32(BG_RV_WORLD_STATE) << uint32(1); +} + +void BattleGroundRV::Reset() +{ + //call parent's class reset + BattleGround::Reset(); +} + +bool BattleGroundRV::SetupBattleGround() +{ + // Fence + if (!AddObject(BG_RV_OBJECT_FENCE_1, BG_RV_OBJECT_TYPE_FENCE_1, 763.432373, -274.058197, 28.276695, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_FENCE_2, BG_RV_OBJECT_TYPE_FENCE_2, 763.432373, -294.419464, 28.276684, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + // elevators + || !AddObject(BG_RV_OBJECT_ELEVATOR_1, BG_RV_OBJECT_TYPE_ELEVATOR_1, 763.536377, -294.535767, 0.505383, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_ELEVATOR_2, BG_RV_OBJECT_TYPE_ELEVATOR_2, 763.506348, -273.873352, 0.505383, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_RV_OBJECT_BUFF_1, BG_RV_OBJECT_TYPE_BUFF_1, 735.551819, -284.794678, 28.276682, 0.034906, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_BUFF_2, BG_RV_OBJECT_TYPE_BUFF_2, 791.224487, -284.794464, 28.276682, 2.600535, 0, 0, 0, RESPAWN_IMMEDIATELY) + // fire + || !AddObject(BG_RV_OBJECT_FIRE_1, BG_RV_OBJECT_TYPE_FIRE_1, 743.543457, -283.799469, 28.286655, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_FIRE_2, BG_RV_OBJECT_TYPE_FIRE_2, 782.971802, -283.799469, 28.286655, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_FIREDOOR_1, BG_RV_OBJECT_TYPE_FIREDOOR_1, 743.711060, -284.099609, 27.542587, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_FIREDOOR_2, BG_RV_OBJECT_TYPE_FIREDOOR_2, 783.221252, -284.133362, 27.535686, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) + // Gear + || !AddObject(BG_RV_OBJECT_GEAR_1, BG_RV_OBJECT_TYPE_GEAR_1, 763.664551, -261.872986, 26.686588, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_GEAR_2, BG_RV_OBJECT_TYPE_GEAR_2, 763.578979, -306.146149, 26.665222, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + // Pulley + || !AddObject(BG_RV_OBJECT_PULLEY_1, BG_RV_OBJECT_TYPE_PULLEY_1, 700.722290, -283.990662, 39.517582, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_PULLEY_2, BG_RV_OBJECT_TYPE_PULLEY_2, 826.303833, -283.996429, 39.517582, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) + // Pilars + || !AddObject(BG_RV_OBJECT_PILAR_1, BG_RV_OBJECT_TYPE_PILAR_1, 763.632385, -306.162384, 25.909504, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_PILAR_2, BG_RV_OBJECT_TYPE_PILAR_2, 723.644287, -284.493256, 24.648525, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_PILAR_3, BG_RV_OBJECT_TYPE_PILAR_3, 763.611145, -261.856750, 25.909504, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_PILAR_4, BG_RV_OBJECT_TYPE_PILAR_4, 802.211609, -284.493256, 24.648525, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) +/* + // Pilars Collision - Fixme: Use the collision pilars - should make u break LoS + || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_1, BG_RV_OBJECT_TYPE_PILAR_COLLISION_1, 763.632385, -306.162384, 30.639660, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_2, BG_RV_OBJECT_TYPE_PILAR_COLLISION_2, 723.644287, -284.493256, 32.382710, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_3, BG_RV_OBJECT_TYPE_PILAR_COLLISION_3, 763.611145, -261.856750, 30.639660, 0.000000, 0, 0, 0, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RV_OBJECT_PILAR_COLLISION_4, BG_RV_OBJECT_TYPE_PILAR_COLLISION_4, 802.211609, -284.493256, 32.382710, 3.141593, 0, 0, 0, RESPAWN_IMMEDIATELY) +*/ +) + { + sLog.outErrorDb("BatteGroundRV: Failed to spawn some object!"); + return false; + } + return true; +} diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundRV.h b/src/server/game/BattleGrounds/Zones/BattleGroundRV.h new file mode 100644 index 00000000000..bf06478d364 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundRV.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDRV_H +#define __BATTLEGROUNDRV_H + +class BattleGround; + +enum BattleGroundRVObjectTypes +{ + BG_RV_OBJECT_BUFF_1, + BG_RV_OBJECT_BUFF_2, + BG_RV_OBJECT_FIRE_1, + BG_RV_OBJECT_FIRE_2, + BG_RV_OBJECT_FIREDOOR_1, + BG_RV_OBJECT_FIREDOOR_2, + + BG_RV_OBJECT_PILAR_1, + BG_RV_OBJECT_PILAR_3, + BG_RV_OBJECT_GEAR_1, + BG_RV_OBJECT_GEAR_2, + + BG_RV_OBJECT_PILAR_2, + BG_RV_OBJECT_PILAR_4, + BG_RV_OBJECT_PULLEY_1, + BG_RV_OBJECT_PULLEY_2, +/* + BG_RV_OBJECT_PILAR_COLLISION_1, + BG_RV_OBJECT_PILAR_COLLISION_2, + BG_RV_OBJECT_PILAR_COLLISION_3, + BG_RV_OBJECT_PILAR_COLLISION_4, +*/ + BG_RV_OBJECT_ELEVATOR_1, + BG_RV_OBJECT_ELEVATOR_2, + BG_RV_OBJECT_FENCE_1, + BG_RV_OBJECT_FENCE_2, + BG_RV_OBJECT_MAX, +}; + +enum BattleGroundRVObjects +{ + BG_RV_OBJECT_TYPE_BUFF_1 = 184663, + BG_RV_OBJECT_TYPE_BUFF_2 = 184664, + BG_RV_OBJECT_TYPE_FIRE_1 = 192704, + BG_RV_OBJECT_TYPE_FIRE_2 = 192705, + + BG_RV_OBJECT_TYPE_FIREDOOR_2 = 192387, + BG_RV_OBJECT_TYPE_FIREDOOR_1 = 192388, + BG_RV_OBJECT_TYPE_PULLEY_1 = 192389, + BG_RV_OBJECT_TYPE_PULLEY_2 = 192390, + BG_RV_OBJECT_TYPE_FENCE_1 = 192391, + BG_RV_OBJECT_TYPE_FENCE_2 = 192392, + BG_RV_OBJECT_TYPE_GEAR_1 = 192393, + BG_RV_OBJECT_TYPE_GEAR_2 = 192394, + BG_RV_OBJECT_TYPE_ELEVATOR_1 = 194582, + BG_RV_OBJECT_TYPE_ELEVATOR_2 = 194586, +/* + BG_RV_OBJECT_TYPE_PILAR_COLLISION_1 = 194580, // axe + BG_RV_OBJECT_TYPE_PILAR_COLLISION_2 = 194579, // arena + BG_RV_OBJECT_TYPE_PILAR_COLLISION_3 = 194581, // lightning + BG_RV_OBJECT_TYPE_PILAR_COLLISION_4 = 194578, // ivory +*/ + BG_RV_OBJECT_TYPE_PILAR_1 = 194583, // axe + BG_RV_OBJECT_TYPE_PILAR_2 = 194584, // arena + BG_RV_OBJECT_TYPE_PILAR_3 = 194585, // lightning + BG_RV_OBJECT_TYPE_PILAR_4 = 194587, // ivory +}; + +enum BattleGroundRVData +{ + BG_RV_STATE_OPEN_FENCES, + BG_RV_STATE_OPEN_PILARS, + BG_RV_STATE_CLOSE_PILARS, + BG_RV_STATE_OPEN_FIRE, + BG_RV_STATE_CLOSE_FIRE, + BG_RV_FIRE_TO_PILAR_TIMER = 20000, + BG_RV_PILAR_TO_FIRE_TIMER = 5000, + BG_RV_FIRST_TIMER = 20133, + BG_RV_WORLD_STATE_A = 0xe10, + BG_RV_WORLD_STATE_H = 0xe11, + BG_RV_WORLD_STATE = 0xe1a, +}; + +class BattleGroundRVScore : public BattleGroundScore +{ + public: + BattleGroundRVScore() {}; + virtual ~BattleGroundRVScore() {}; +}; + +class BattleGroundRV : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundRV(); + ~BattleGroundRV(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + virtual void Reset(); + virtual void FillInitialWorldStates(WorldPacket &d); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + void HandleKillPlayer(Player* player, Player *killer); + bool HandlePlayerUnderMap(Player * plr); + + private: + uint32 Timer; + uint32 State; + + protected: + uint32 getTimer() { return Timer; }; + void setTimer(uint32 timer) { Timer = timer; }; + + uint32 getState() { return State; }; + void setState(uint32 state) { State = state; }; +}; +#endif diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundSA.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundSA.cpp new file mode 100644 index 00000000000..ccde43ce948 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundSA.cpp @@ -0,0 +1,822 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundSA.h" +#include "Language.h" +#include "Player.h" +#include "GameObject.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" + + +BattleGroundSA::BattleGroundSA() +{ + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_SA_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_SA_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_SA_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_SA_HAS_BEGUN; + m_BgObjects.resize(BG_SA_MAXOBJ); + m_BgCreatures.resize(BG_SA_MAXNPC + BG_SA_MAX_GY); + TimerEnabled = false; + UpdateWaitTimer = 0; + SignaledRoundTwo = false; + SignaledRoundTwoHalfMin = false; + InitSecondRound = false; +} + +BattleGroundSA::~BattleGroundSA() +{ +} + +void BattleGroundSA::Reset() +{ + TotalTime = 0; + attackers = ((urand(0,1)) ? TEAM_ALLIANCE : TEAM_HORDE); + for (uint8 i = 0; i <= 5; i++) + GateStatus[i] = BG_SA_GATE_OK; + ShipsStarted = false; + status = BG_SA_WARMUP; +} + +bool BattleGroundSA::SetupBattleGround() +{ + return ResetObjs(); +} + +bool BattleGroundSA::ResetObjs() +{ + uint32 atF = BG_SA_Factions[attackers]; + uint32 defF = BG_SA_Factions[attackers ? TEAM_ALLIANCE : TEAM_HORDE]; + + + for (uint8 i = 0; i SetUInt32Value(GAMEOBJECT_FACTION, defF); + } + + GetBGObject(BG_SA_TITAN_RELIC)->SetUInt32Value(GAMEOBJECT_FACTION, atF); + GetBGObject(BG_SA_TITAN_RELIC)->Refresh(); + + for (uint8 i = 0; i <= 5; i++) + GateStatus[i] = BG_SA_GATE_OK; + + // MAD props for Kiper for discovering those values - 4 hours of his work. + GetBGObject(BG_SA_BOAT_ONE)->UpdateRotationFields(1.0f, 0.0002f); + GetBGObject(BG_SA_BOAT_TWO)->UpdateRotationFields(1.0f, 0.00001f); + SpawnBGObject(BG_SA_BOAT_ONE, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_SA_BOAT_TWO, RESPAWN_IMMEDIATELY); + + TotalTime = 0; + ShipsStarted = false; + + //Graveyards! + for (uint8 i = 0;i < BG_SA_MAX_GY; i++) + { + WorldSafeLocsEntry const *sg = NULL; + sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); + + if (!sg) + { + sLog.outError("SOTA: Can't find GY entry %u",BG_SA_GYEntries[i]); + return false; + } + + if (i == BG_SA_BEACH_GY) + { + GraveyardStatus[i] = attackers; + AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], ((attackers == TEAM_HORDE)? HORDE : ALLIANCE)); + } + else + { + GraveyardStatus[i] = ((attackers == TEAM_HORDE)? TEAM_ALLIANCE : TEAM_HORDE); + if (!AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], ((attackers == TEAM_HORDE)? ALLIANCE : HORDE))) + sLog.outError("SOTA: couldn't spawn GY: %u",i); + } + } + + //GY capture points + for (uint8 i = BG_SA_CENTRAL_FLAG; i < BG_SA_MAXOBJ; i++) + { + AddObject(i, BG_SA_ObjEntries[(i + (attackers == TEAM_ALLIANCE ? 3:0))], + BG_SA_ObjSpawnlocs[i][0], BG_SA_ObjSpawnlocs[i][1], + BG_SA_ObjSpawnlocs[i][2], BG_SA_ObjSpawnlocs[i][3], + 0,0,0,0,RESPAWN_ONE_DAY); + GetBGObject(i)->SetUInt32Value(GAMEOBJECT_FACTION, atF); + } + + //Player may enter BEFORE we set up bG - lets update his worldstates anyway... + UpdateWorldState(BG_SA_RIGHT_GY_HORDE , GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE?1:0); + UpdateWorldState(BG_SA_LEFT_GY_HORDE , GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE?1:0); + UpdateWorldState(BG_SA_CENTER_GY_HORDE , GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE?1:0); + + UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE , GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); + UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE , GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); + UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE , GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); + + if (attackers == TEAM_ALLIANCE) + { + UpdateWorldState(BG_SA_ALLY_ATTACKS, 1); + UpdateWorldState(BG_SA_HORDE_ATTACKS, 0); + + UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_ALL, 1); + UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_ALL, 1); + UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_HRD, 0); + UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_HRD, 0); + + UpdateWorldState(BG_SA_HORDE_DEFENCE_TOKEN,1); + UpdateWorldState(BG_SA_ALLIANCE_DEFENCE_TOKEN,0); + } + else + { + UpdateWorldState(BG_SA_HORDE_ATTACKS, 1); + UpdateWorldState(BG_SA_ALLY_ATTACKS, 0); + + UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_ALL, 0); + UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_ALL, 0); + UpdateWorldState(BG_SA_RIGHT_ATT_TOKEN_HRD, 1); + UpdateWorldState(BG_SA_LEFT_ATT_TOKEN_HRD, 1); + + UpdateWorldState(BG_SA_HORDE_DEFENCE_TOKEN,0); + UpdateWorldState(BG_SA_ALLIANCE_DEFENCE_TOKEN,1); + } + + UpdateWorldState(BG_SA_PURPLE_GATEWS, 1); + UpdateWorldState(BG_SA_RED_GATEWS, 1); + UpdateWorldState(BG_SA_BLUE_GATEWS, 1); + UpdateWorldState(BG_SA_GREEN_GATEWS, 1); + UpdateWorldState(BG_SA_YELLOW_GATEWS, 1); + UpdateWorldState(BG_SA_ANCIENT_GATEWS, 1); + + TeleportPlayers(); + return true; +} + +void BattleGroundSA::StartShips() +{ + if (ShipsStarted) + return; + + DoorOpen(BG_SA_BOAT_ONE); + DoorOpen(BG_SA_BOAT_TWO); + + for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++) + { + for (BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end();itr++) + { + if (Player* p = objmgr.GetPlayer(itr->first)) + { + if (p->GetTeamId() != attackers) + continue; + + UpdateData data; + WorldPacket pkt; + GetBGObject(i)->BuildValuesUpdateBlockForPlayer(&data, p); + data.BuildPacket(&pkt); + p->GetSession()->SendPacket(&pkt); + } + } + } + ShipsStarted = true; +} + +void BattleGroundSA::Update(uint32 diff) +{ + if (InitSecondRound) + { + if (UpdateWaitTimer < diff) + { + if (!SignaledRoundTwo) + { + SignaledRoundTwo = true; + InitSecondRound = false; + SendMessageToAll(LANG_BG_SA_ROUND_TWO_ONE_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL); + } + }else + { + UpdateWaitTimer -= diff; + return; + } + } + BattleGround::Update(diff); + TotalTime += diff; + + if (status == BG_SA_WARMUP ) + { + BG_SA_ENDROUNDTIME = BG_SA_ROUNDLENGTH; + if (TotalTime >= BG_SA_WARMUPLENGTH) + { + TotalTime = 0; + ToggleTimer(); + DemolisherStartState(false); + status = BG_SA_ROUND_ONE; + } + if (TotalTime >= BG_SA_BOAT_START) + StartShips(); + return; + } + else if (status == BG_SA_SECOND_WARMUP) + { + if (RoundScores[0].time= 60000) + { + SendWarningToAll(LANG_BG_SA_HAS_BEGUN); + TotalTime = 0; + ToggleTimer(); + DemolisherStartState(false); + status = BG_SA_ROUND_TWO; + } + if (TotalTime >= 30000) + { + if (!SignaledRoundTwoHalfMin) + { + SignaledRoundTwoHalfMin = true; + SendMessageToAll(LANG_BG_SA_ROUND_TWO_START_HALF_MINUTE, CHAT_MSG_BG_SYSTEM_NEUTRAL); + } + } + StartShips(); + return; + } + else if (GetStatus() == STATUS_IN_PROGRESS) + { + if (status == BG_SA_ROUND_ONE) + { + if (TotalTime >= BG_SA_ROUNDLENGTH) + { + RoundScores[0].winner = attackers; + RoundScores[0].time = BG_SA_ROUNDLENGTH; + TotalTime = 0; + status = BG_SA_SECOND_WARMUP; + attackers = (attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE; + status = BG_SA_SECOND_WARMUP; + ToggleTimer(); + ResetObjs(); + return; + } + } + else if (status == BG_SA_ROUND_TWO) + { + if (TotalTime >= BG_SA_ENDROUNDTIME) + { + RoundScores[1].time = BG_SA_ROUNDLENGTH; + RoundScores[1].winner = (attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE; + + if (RoundScores[0].time == RoundScores[1].time) + EndBattleGround(NULL); + else if (RoundScores[0].time < RoundScores[1].time) + EndBattleGround(RoundScores[0].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE); + else + EndBattleGround(RoundScores[1].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE); + return; + } + } + if (status == BG_SA_ROUND_ONE || status == BG_SA_ROUND_TWO) + { + SendTime(); + UpdateDemolisherSpawns(); + } + } +} + +void BattleGroundSA::StartingEventCloseDoors() +{ +} + +void BattleGroundSA::StartingEventOpenDoors() +{ +} + +void BattleGroundSA::FillInitialWorldStates(WorldPacket& data) +{ + uint32 ally_attacks = uint32(attackers == TEAM_ALLIANCE ? 1 : 0); + uint32 horde_attacks = uint32(attackers == TEAM_HORDE ? 1 : 0); + + data << uint32(BG_SA_ANCIENT_GATEWS) << uint32(GateStatus[BG_SA_ANCIENT_GATE]); + data << uint32(BG_SA_YELLOW_GATEWS) << uint32(GateStatus[BG_SA_YELLOW_GATE]); + data << uint32(BG_SA_GREEN_GATEWS) << uint32(GateStatus[BG_SA_GREEN_GATE]); + data << uint32(BG_SA_BLUE_GATEWS) << uint32(GateStatus[BG_SA_BLUE_GATE]); + data << uint32(BG_SA_RED_GATEWS) << uint32(GateStatus[BG_SA_RED_GATE]); + data << uint32(BG_SA_PURPLE_GATEWS) << uint32(GateStatus[BG_SA_PURPLE_GATE]); + + data << uint32(BG_SA_BONUS_TIMER) << uint32(0); + + data << uint32(BG_SA_HORDE_ATTACKS)<< horde_attacks; + data << uint32(BG_SA_ALLY_ATTACKS) << ally_attacks; + + //Time will be sent on first update... + data << uint32(BG_SA_ENABLE_TIMER) << ((TimerEnabled) ? uint32(1) : uint32(0)); + data << uint32(BG_SA_TIMER_MINS) << uint32(0); + data << uint32(BG_SA_TIMER_SEC_TENS) << uint32(0); + data << uint32(BG_SA_TIMER_SEC_DECS) << uint32(0); + + data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE?1:0); + data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE?1:0); + data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE?1:0); + + data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); + data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); + data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE?1:0); + + data << uint32(BG_SA_HORDE_DEFENCE_TOKEN) << ally_attacks; + data << uint32(BG_SA_ALLIANCE_DEFENCE_TOKEN) << horde_attacks; + + data << uint32(BG_SA_LEFT_ATT_TOKEN_HRD) << horde_attacks; + data << uint32(BG_SA_RIGHT_ATT_TOKEN_HRD) << horde_attacks; + data << uint32(BG_SA_RIGHT_ATT_TOKEN_ALL) << ally_attacks; + data << uint32(BG_SA_LEFT_ATT_TOKEN_ALL) << ally_attacks; +} + +void BattleGroundSA::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundSAScore* sc = new BattleGroundSAScore; + + if (!ShipsStarted) + { + if (plr->GetTeamId() == attackers) + { + plr->CastSpell(plr,12438,true);//Without this player falls before boat loads... + + if (urand(0,1)) + plr->TeleportTo(607, 2682.936f, -830.368f, 50.0f, 2.895f, 0); + else + plr->TeleportTo(607, 2577.003f, 980.261f, 50.0f, 0.807f, 0); + + } + else + plr->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0); + } + else + { + if (plr->GetTeamId() == attackers) + plr->TeleportTo(607, 1600.381f, -106.263f, 8.8745f, 3.78f, 0); + else + plr->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0); + } + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundSA::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) +{ +} + +void BattleGroundSA::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if (GetStatus() != STATUS_IN_PROGRESS) + return; +} + +void BattleGroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor) +{ + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); + if (itr == m_PlayerScores.end()) // player not found... + return; + + if (type == SCORE_DESTROYED_DEMOLISHER) + ((BattleGroundSAScore*)itr->second)->demolishers_destroyed += value; + else if (type == SCORE_DESTROYED_WALL) + ((BattleGroundSAScore*)itr->second)->gates_destroyed += value; + else + BattleGround::UpdatePlayerScore(Source,type,value, doAddHonor); +} + +void BattleGroundSA::TeleportPlayers() +{ + for (BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + { + if (Player *plr = objmgr.GetPlayer(itr->first)) + { + // should remove spirit of redemption + if (plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) + plr->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT); + + if (!plr->isAlive()) + { + plr->ResurrectPlayer(1.0f); + plr->SpawnCorpseBones(); + } + + plr->SetHealth(plr->GetMaxHealth()); + plr->SetPower(POWER_MANA, plr->GetMaxPower(POWER_MANA)); + plr->CombatStopWithPets(true); + + if (plr->GetTeamId() == attackers) + { + plr->CastSpell(plr,12438,true); //Without this player falls before boat loads... + + if (urand(0,1)) + plr->TeleportTo(607, 2682.936f, -830.368f, 50.0f, 2.895f, 0); + else + plr->TeleportTo(607, 2577.003f, 980.261f, 50.0f, 0.807f, 0); + } + else + plr->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0); + } + } +} + +void BattleGroundSA::EventPlayerDamagedGO(Player* plr, GameObject* go, uint8 hitType, uint32 destroyedEvent) +{ + if (!go || !go->GetGOInfo()) + return; + + switch(hitType) + { + case BG_OBJECT_DMG_HIT_TYPE_JUST_DAMAGED://under attack + SendWarningToAll(LANG_BG_SA_IS_UNDER_ATTACK, go->GetGOInfo()->name); + break; + case BG_OBJECT_DMG_HIT_TYPE_DAMAGED: + break; + case BG_OBJECT_DMG_HIT_TYPE_JUST_HIGH_DAMAGED: + { + uint32 i = GetGateIDFromDestroyEventID(destroyedEvent); + GateStatus[i] = BG_SA_GATE_DAMAGED; + uint32 uws = GetWorldStateFromGateID(i); + if (uws) + UpdateWorldState(uws, GateStatus[i]); + break; + } + case BG_OBJECT_DMG_HIT_TYPE_HIGH_DAMAGED: + break; + case BG_OBJECT_DMG_HIT_TYPE_JUST_DESTROYED://handled at DestroyGate() + if (destroyedEvent == 19837) + SendWarningToAll(LANG_BG_SA_CHAMBER_BREACHED); + else + SendWarningToAll(LANG_BG_SA_WAS_DESTROYED, go->GetGOInfo()->name); + break; + } +} + +void BattleGroundSA::HandleKillUnit(Creature* unit, Player* killer) +{ + if (!unit) + return; + + if (unit->GetEntry() == 28781) //Demolisher + UpdatePlayerScore(killer, SCORE_DESTROYED_DEMOLISHER, 1); +} + +/* + You may ask what the fuck does it do? + Prevents owner overwriting guns faction with own. + */ +void BattleGroundSA::OverrideGunFaction() +{ + if (!m_BgCreatures[0]) + return; + + for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10;i++) + { + if (Creature* gun = GetBGCreature(i)) + gun->setFaction(BG_SA_Factions[attackers? TEAM_ALLIANCE : TEAM_HORDE]); + } + + for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4;i++) + { + if (Creature* dem = GetBGCreature(i)) + dem->setFaction(BG_SA_Factions[attackers]); + } +} + +void BattleGroundSA::DemolisherStartState(bool start) +{ + if (!m_BgCreatures[0]) + return; + + for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) + { + if (Creature* dem = GetBGCreature(i)) + { + if (start) + dem->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + else + dem->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + } + } +} + +void BattleGroundSA::DestroyGate(Player* pl, GameObject* /*go*/, uint32 destroyedEvent) +{ + uint32 i = GetGateIDFromDestroyEventID(destroyedEvent); + if (!GateStatus[i]) + return; + + if (GameObject* g = GetBGObject(i)) + { + if (g->GetGOValue()->building.health == 0) + { + GateStatus[i] = BG_SA_GATE_DESTROYED; + uint32 uws = GetWorldStateFromGateID(i); + if (uws) + UpdateWorldState(uws, GateStatus[i]); + bool rewardHonor = true; + switch(i) + { + case BG_SA_GREEN_GATE: + if (GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) + rewardHonor = false; + break; + case BG_SA_BLUE_GATE: + if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED) + rewardHonor = false; + break; + case BG_SA_RED_GATE: + if (GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED) + rewardHonor = false; + break; + case BG_SA_PURPLE_GATE: + if (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) + rewardHonor = false; + break; + } + + if (i < 5) + DelObject(i+9); + UpdatePlayerScore(pl,SCORE_DESTROYED_WALL, 1); + if (rewardHonor) + UpdatePlayerScore(pl,SCORE_BONUS_HONOR,(GetBonusHonorFromKill(1))); + } + } +} + +WorldSafeLocsEntry const* BattleGroundSA::GetClosestGraveYard(Player* player) +{ + uint32 safeloc = 0; + WorldSafeLocsEntry const* ret; + WorldSafeLocsEntry const* closest; + float dist, nearest; + float x,y,z; + + player->GetPosition(x,y,z); + + if (player->GetTeamId() == attackers) + safeloc = BG_SA_GYEntries[BG_SA_BEACH_GY]; + else + safeloc = BG_SA_GYEntries[BG_SA_DEFENDER_LAST_GY]; + + closest = sWorldSafeLocsStore.LookupEntry(safeloc); + nearest = sqrt((closest->x - x)*(closest->x - x) + (closest->y - y)*(closest->y - y)+(closest->z - z)*(closest->z - z)); + + for (uint8 i = BG_SA_RIGHT_CAPTURABLE_GY; i < BG_SA_MAX_GY; i++) + { + if (GraveyardStatus[i] != player->GetTeamId()) + continue; + + ret = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); + dist = sqrt((ret->x - x)*(ret->x - x) + (ret->y - y)*(ret->y - y)+(ret->z - z)*(ret->z - z)); + if (dist < nearest) + { + closest = ret; + nearest = dist; + } + } + + return closest; +} + +void BattleGroundSA::SendTime() +{ + uint32 end_of_round = (BG_SA_ENDROUNDTIME - TotalTime); + UpdateWorldState(BG_SA_TIMER_MINS, end_of_round/60000); + UpdateWorldState(BG_SA_TIMER_SEC_TENS, (end_of_round%60000)/10000); + UpdateWorldState(BG_SA_TIMER_SEC_DECS, ((end_of_round%60000)%10000)/1000); +} + +void BattleGroundSA::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) +{ + switch(target_obj->GetEntry()) + { + case 191307: + case 191308: + if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) + CaptureGraveyard(BG_SA_LEFT_CAPTURABLE_GY, Source); + break; + case 191305: + case 191306: + if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) + CaptureGraveyard(BG_SA_RIGHT_CAPTURABLE_GY, Source); + break; + case 191310: + case 191309: + if ((GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) && (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED)) + CaptureGraveyard(BG_SA_CENTRAL_CAPTURABLE_GY, Source); + break; + default: + return; + }; +} + +void BattleGroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player *Source) +{ + DelCreature(BG_SA_MAXNPC + i); + GraveyardStatus[i] = Source->GetTeamId(); + WorldSafeLocsEntry const *sg = NULL; + sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); + AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], (GraveyardStatus[i] == TEAM_ALLIANCE? ALLIANCE : HORDE)); + uint32 npc = 0; + uint32 flag = 0; + + switch(i) + { + case BG_SA_LEFT_CAPTURABLE_GY: + flag = BG_SA_LEFT_FLAG; + DelObject(flag); + AddObject(flag,BG_SA_ObjEntries[(flag + (Source->GetTeamId() == TEAM_ALLIANCE ? 0:3))], + BG_SA_ObjSpawnlocs[flag][0],BG_SA_ObjSpawnlocs[flag][1], + BG_SA_ObjSpawnlocs[flag][2],BG_SA_ObjSpawnlocs[flag][3],0,0,0,0,RESPAWN_ONE_DAY); + + npc = BG_SA_NPC_RIGSPARK; + AddCreature(BG_SA_NpcEntries[npc], npc, attackers, + BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1], + BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]); + + UpdateWorldState(BG_SA_LEFT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); + UpdateWorldState(BG_SA_LEFT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); + if (Source->GetTeamId() == TEAM_ALLIANCE) + SendWarningToAll(LANG_BG_SA_A_GY_WEST); + else + SendWarningToAll(LANG_BG_SA_H_GY_WEST); + break; + case BG_SA_RIGHT_CAPTURABLE_GY: + flag = BG_SA_RIGHT_FLAG; + DelObject(flag); + AddObject(flag,BG_SA_ObjEntries[(flag + (Source->GetTeamId() == TEAM_ALLIANCE ? 0:3))], + BG_SA_ObjSpawnlocs[flag][0],BG_SA_ObjSpawnlocs[flag][1], + BG_SA_ObjSpawnlocs[flag][2],BG_SA_ObjSpawnlocs[flag][3],0,0,0,0,RESPAWN_ONE_DAY); + + npc = BG_SA_NPC_SPARKLIGHT; + AddCreature(BG_SA_NpcEntries[npc], npc, attackers, + BG_SA_NpcSpawnlocs[npc][0], BG_SA_NpcSpawnlocs[npc][1], + BG_SA_NpcSpawnlocs[npc][2], BG_SA_NpcSpawnlocs[npc][3]); + + UpdateWorldState(BG_SA_RIGHT_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); + UpdateWorldState(BG_SA_RIGHT_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); + if (Source->GetTeamId() == TEAM_ALLIANCE) + SendWarningToAll(LANG_BG_SA_A_GY_EAST); + else + SendWarningToAll(LANG_BG_SA_H_GY_EAST); + break; + case BG_SA_CENTRAL_CAPTURABLE_GY: + flag = BG_SA_CENTRAL_FLAG; + DelObject(flag); + AddObject(flag,BG_SA_ObjEntries[(flag + (Source->GetTeamId() == TEAM_ALLIANCE ? 0:3))], + BG_SA_ObjSpawnlocs[flag][0],BG_SA_ObjSpawnlocs[flag][1], + BG_SA_ObjSpawnlocs[flag][2],BG_SA_ObjSpawnlocs[flag][3],0,0,0,0,RESPAWN_ONE_DAY); + + UpdateWorldState(BG_SA_CENTER_GY_ALLIANCE, (GraveyardStatus[i] == TEAM_ALLIANCE? 1:0)); + UpdateWorldState(BG_SA_CENTER_GY_HORDE, (GraveyardStatus[i] == TEAM_ALLIANCE? 0:1)); + if (Source->GetTeamId() == TEAM_ALLIANCE) + SendWarningToAll(LANG_BG_SA_A_GY_SOUTH); + else + SendWarningToAll(LANG_BG_SA_H_GY_SOUTH); + break; + default: + ASSERT(0); + break; + }; +} + +void BattleGroundSA::EventPlayerUsedGO(Player* Source, GameObject* object) +{ + if (object->GetEntry() == BG_SA_ObjEntries[BG_SA_TITAN_RELIC] && GateStatus[BG_SA_ANCIENT_GATE] == BG_SA_GATE_DESTROYED) + { + if (Source->GetTeamId() == attackers) + { + if (Source->GetTeamId() == ALLIANCE) + SendMessageToAll(LANG_BG_SA_ALLIANCE_CAPTURED_RELIC, CHAT_MSG_BG_SYSTEM_NEUTRAL); + else SendMessageToAll(LANG_BG_SA_HORDE_CAPTURED_RELIC, CHAT_MSG_BG_SYSTEM_NEUTRAL); + + if (status == BG_SA_ROUND_ONE) + { + RoundScores[0].winner = attackers; + RoundScores[0].time = TotalTime; + attackers = (attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE; + status = BG_SA_SECOND_WARMUP; + TotalTime = 0; + ToggleTimer(); + SendWarningToAll(LANG_BG_SA_ROUND_ONE_END); + UpdateWaitTimer = 5000; + SignaledRoundTwo = false; + SignaledRoundTwoHalfMin = false; + InitSecondRound = true; + ResetObjs(); + } + else if (status == BG_SA_ROUND_TWO) + { + RoundScores[1].winner = attackers; + RoundScores[1].time = TotalTime;ToggleTimer(); + if (RoundScores[0].time == RoundScores[1].time) + EndBattleGround(NULL); + else if (RoundScores[0].time < RoundScores[1].time) + EndBattleGround(RoundScores[0].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE); + else + EndBattleGround(RoundScores[1].winner == TEAM_ALLIANCE ? ALLIANCE : HORDE); + } + } + } +} + +void BattleGroundSA::ToggleTimer() +{ + TimerEnabled = !TimerEnabled; + UpdateWorldState(BG_SA_ENABLE_TIMER, (TimerEnabled) ? 1 : 0); +} + +void BattleGroundSA::EndBattleGround(uint32 winner) +{ + //honor reward for winning + if (winner == ALLIANCE) + RewardHonorToTeam(GetBonusHonorFromKill(1), ALLIANCE); + else if (winner == HORDE) + RewardHonorToTeam(GetBonusHonorFromKill(1), HORDE); + + //complete map_end rewards (even if no team wins) + RewardHonorToTeam(GetBonusHonorFromKill(2), ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(2), HORDE); + + BattleGround::EndBattleGround(winner); +} + +void BattleGroundSA::UpdateDemolisherSpawns() +{ + for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++) + { + if (m_BgCreatures[i]) + { + if (Creature *Demolisher = GetBGCreature(i)) + { + if (Demolisher->isDead()) + { + uint8 gy = (i >= BG_SA_DEMOLISHER_3 ? 3 : 2); + if (GraveyardStatus[gy] == attackers) + Demolisher->Relocate(BG_SA_NpcSpawnlocs[i + 6][0], BG_SA_NpcSpawnlocs[i + 6][1], + BG_SA_NpcSpawnlocs[i + 6][2], BG_SA_NpcSpawnlocs[i + 6][3]); + else + Demolisher->Relocate(BG_SA_NpcSpawnlocs[i][0], BG_SA_NpcSpawnlocs[i][1], + BG_SA_NpcSpawnlocs[i][2], BG_SA_NpcSpawnlocs[i][3]); + + Demolisher->Respawn(); + } + } + } + } +} + + diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundSA.h b/src/server/game/BattleGrounds/Zones/BattleGroundSA.h new file mode 100644 index 00000000000..760be3ca02e --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundSA.h @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDSA_H +#define __BATTLEGROUNDSA_H + +class BattleGround; + +class BattleGroundSAScore : public BattleGroundScore +{ + public: + BattleGroundSAScore(): demolishers_destroyed(0), gates_destroyed(0) {}; + virtual ~BattleGroundSAScore() {}; + uint8 demolishers_destroyed; + uint8 gates_destroyed; +}; + +#define BG_SA_FLAG_AMOUNT 3 +#define BG_SA_DEMOLISHER_AMOUNT 4 + +enum BG_SA_Status + { + BG_SA_NOTSTARTED = 0, + BG_SA_WARMUP, + BG_SA_ROUND_ONE, + BG_SA_SECOND_WARMUP, + BG_SA_ROUND_TWO, + BG_SA_BONUS_ROUND + }; + +enum BG_SA_GateState + { + BG_SA_GATE_OK = 1, + BG_SA_GATE_DAMAGED = 2, + BG_SA_GATE_DESTROYED = 3 + }; + +enum BG_SA_Timers + { + BG_SA_BOAT_START = 60000, + BG_SA_WARMUPLENGTH = 120000, + BG_SA_ROUNDLENGTH = 600000 + }; + +enum BG_SA_WorldStates + { + BG_SA_TIMER_MINS = 3559, + BG_SA_TIMER_SEC_TENS = 3560, + BG_SA_TIMER_SEC_DECS = 3561, + BG_SA_ALLY_ATTACKS = 4352, + BG_SA_HORDE_ATTACKS = 4353, + + BG_SA_PURPLE_GATEWS = 3614, + BG_SA_RED_GATEWS = 3617, + BG_SA_BLUE_GATEWS = 3620, + BG_SA_GREEN_GATEWS = 3623, + BG_SA_YELLOW_GATEWS = 3638, + BG_SA_ANCIENT_GATEWS = 3849, + + + BG_SA_LEFT_GY_ALLIANCE = 3635, + BG_SA_RIGHT_GY_ALLIANCE = 3636, + BG_SA_CENTER_GY_ALLIANCE = 3637, + + BG_SA_RIGHT_ATT_TOKEN_ALL = 3627, + BG_SA_LEFT_ATT_TOKEN_ALL = 3626, + + BG_SA_LEFT_ATT_TOKEN_HRD = 3629, + BG_SA_RIGHT_ATT_TOKEN_HRD = 3628, + + BG_SA_HORDE_DEFENCE_TOKEN = 3631, + BG_SA_ALLIANCE_DEFENCE_TOKEN = 3630, + + BG_SA_RIGHT_GY_HORDE = 3632, + BG_SA_LEFT_GY_HORDE = 3633, + BG_SA_CENTER_GY_HORDE = 3634, + + BG_SA_BONUS_TIMER = 0xdf3, + BG_SA_ENABLE_TIMER = 3564, + }; + +enum BG_SA_NPCs + { + BG_SA_GUN_1 = 0, + BG_SA_GUN_2, + BG_SA_GUN_3, + BG_SA_GUN_4, + BG_SA_GUN_5, + BG_SA_GUN_6, + BG_SA_GUN_7, + BG_SA_GUN_8, + BG_SA_GUN_9, + BG_SA_GUN_10, + BG_SA_DEMOLISHER_1, + BG_SA_DEMOLISHER_2, + BG_SA_DEMOLISHER_3, + BG_SA_DEMOLISHER_4, + BG_SA_NPC_SPARKLIGHT, + BG_SA_NPC_RIGSPARK, + BG_SA_MAXNPC + }; + +const uint32 BG_SA_NpcEntries[BG_SA_MAXNPC] = + { + 27894, + 27894, + 27894, + 27894, + 27894, + 27894, + 27894, + 27894, + 27894, + 27894, + //4 beach demolishers + 28781, + 28781, + 28781, + 28781, + //Fizzle Sparklight, or whatever his name was + 29260, + 29262, + }; + +const float BG_SA_NpcSpawnlocs[BG_SA_MAXNPC + BG_SA_DEMOLISHER_AMOUNT][4] = + { + //Cannons + { 1436.429f, 110.05f, 41.407f, 5.4f }, + { 1404.9023f, 84.758f, 41.183f, 5.46f }, + { 1068.693f, -86.951f, 93.81f, 0.02f }, + { 1068.83f, -127.56f, 96.45f, 0.0912f }, + { 1422.115f, -196.433f, 42.1825f, 1.0222f }, + { 1454.887f, -220.454f, 41.956f, 0.9627f }, + { 1232.345f, -187.517f, 66.945f, 0.45f }, + { 1249.634f, -224.189f, 66.72f, 0.635f }, + { 1236.213f, 92.287f, 64.965f, 5.751f }, + { 1215.11f, 57.772f, 64.739f, 5.78f } , + //Demolishers + { 1611.597656,-117.270073,8.719355,2.513274}, + { 1575.562500,-158.421875,5.024450,2.129302}, + { 1618.047729,61.424641,7.248210,3.979351}, + { 1575.103149,98.873344,2.830360,3.752458}, + //Npcs + { 1348.644165, -298.786469, 31.080130, 1.710423}, + { 1358.191040, 195.527786, 31.018187, 4.171337}, + //Demolishers2 + { 1371.055786, -317.071136, 35.007359, 1.947460}, + { 1424.034912, -260.195190, 31.084425, 2.820013}, + { 1353.139893, 223.745438, 35.265411, 4.343684}, + { 1404.809570, 197.027237, 32.046032, 3.605401}, + }; + +enum BG_SA_Objects + { + BG_SA_GREEN_GATE = 0, + BG_SA_YELLOW_GATE, + BG_SA_BLUE_GATE, + BG_SA_RED_GATE, + BG_SA_PURPLE_GATE, + BG_SA_ANCIENT_GATE, + BG_SA_TITAN_RELIC, + BG_SA_BOAT_ONE, + BG_SA_BOAT_TWO, + BG_SA_SIGIL_1, + BG_SA_SIGIL_2, + BG_SA_SIGIL_3, + BG_SA_SIGIL_4, + BG_SA_SIGIL_5, + BG_SA_CENTRAL_FLAGPOLE, + BG_SA_RIGHT_FLAGPOLE, + BG_SA_LEFT_FLAGPOLE, + BG_SA_CENTRAL_FLAG, + BG_SA_RIGHT_FLAG, + BG_SA_LEFT_FLAG, + BG_SA_MAXOBJ + }; + +const float BG_SA_ObjSpawnlocs[BG_SA_MAXOBJ][4] = + { + { 1411.57f, 108.163f, 28.692f, 5.441f }, + { 1055.452f, -108.1f, 82.134f, 0.034f }, + { 1431.3413f, -219.437f, 30.893f, 0.9736f }, + { 1227.667f, -212.555f, 55.372f, 0.5023f }, + { 1214.681f, 81.21f, 53.413f, 5.745f }, + { 878.555f, -108.989f, 119.835f, 0.0565f }, + { 836.5f, -108.8f, 120.219f, 0.0f }, + //Ships + { 2679.696777, -826.891235, 3.712860, 5.78367f}, //rot2 1 rot3 0.0002 + { 2574.003662, 981.261475, 2.603424, 0.807696}, + //Sigils + { 1414.054f, 106.72f, 41.442f, 5.441f }, + { 1060.63f, -107.8f, 94.7f, 0.034f }, + { 1433.383f, -216.4f, 43.642f, 0.9736f }, + { 1230.75f, -210.724f, 67.611f, 0.5023f }, + { 1217.8f, 79.532f, 66.58f, 5.745f }, + //Flagpoles + { 1215.114258,-65.711861,70.084267,-3.124123}, + {1338.863892,-153.336533,30.895121,-2.530723}, + {1309.124268,9.410645,30.893402,-1.623156}, + //Flags + { 1215.108032,-65.715767,70.084267,-3.124123}, + { 1338.859253,-153.327316,30.895077,-2.530723}, + { 1309.192017,9.416233,30.893402,1.518436}, + }; + +/* Ships: + * 193182 - ally + * 193183 - horde + * 193184 - horde + * 193185 - ally + * Banners: + * 191308 - left one, + * 191306 - right one, + * 191310 - central, + * Ally ones, substract 1 + * to get horde ones. + */ + +const uint32 BG_SA_ObjEntries[BG_SA_MAXOBJ + BG_SA_FLAG_AMOUNT] = + { + 190722, + 190727, + 190724, + 190726, + 190723, + 192549, + 192834, + 193182, + 193185, + 192687, + 192685, + 192689, + 192690, + 192691, + 191311, + 191311, + 191311, + 191310, + 191306, + 191308, + 191309, + 191305, + 191307, + }; + +const uint32 BG_SA_Factions[2] = + { + 1732, + 1735, + }; + +enum BG_SA_Graveyards + { + BG_SA_BEACH_GY = 0, + BG_SA_DEFENDER_LAST_GY, + BG_SA_RIGHT_CAPTURABLE_GY, + BG_SA_LEFT_CAPTURABLE_GY, + BG_SA_CENTRAL_CAPTURABLE_GY, + BG_SA_MAX_GY + }; + +const uint32 BG_SA_GYEntries[BG_SA_MAX_GY] = + { + 1350, + 1349, + 1347, + 1346, + 1348, + }; + +const float BG_SA_GYOrientation[BG_SA_MAX_GY] = + { + 6.202f, + 1.926f, //right capturable GY + 3.917f, //left capturable GY + 3.104f, //center, capturable + 6.148f, //defender last GY + }; + +struct BG_SA_RoundScore +{ + TeamId winner; + uint32 time; +}; + +class BattleGroundSA : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundSA(); + ~BattleGroundSA(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + virtual bool SetupBattleGround(); + virtual void Reset(); + virtual void FillInitialWorldStates(WorldPacket& data); + virtual void EventPlayerDamagedGO(Player* plr, GameObject* go, uint8 hitType, uint32 destroyedEvent); + virtual void HandleKillUnit(Creature* unit, Player* killer); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); + virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); + virtual void EventPlayerUsedGO(Player* Source, GameObject* object); + uint32 GetGateIDFromDestroyEventID(uint32 id) + { + uint32 i = 0; + switch(id) + { + case 19046: i = BG_SA_GREEN_GATE; break; //Green gate destroyed + case 19045: i = BG_SA_BLUE_GATE; break; //blue gate + case 19047: i = BG_SA_RED_GATE; break; //red gate + case 19048: i = BG_SA_PURPLE_GATE; break; //purple gate + case 19049: i = BG_SA_YELLOW_GATE; break; //yellow gate + case 19837: i = BG_SA_ANCIENT_GATE; break; //ancient gate + } + return i; + } + uint32 GetWorldStateFromGateID(uint32 id) + { + uint32 uws = 0; + switch(id) + { + case BG_SA_GREEN_GATE: uws = BG_SA_GREEN_GATEWS; break; + case BG_SA_YELLOW_GATE: uws = BG_SA_YELLOW_GATEWS; break; + case BG_SA_BLUE_GATE: uws = BG_SA_BLUE_GATEWS; break; + case BG_SA_RED_GATE: uws = BG_SA_RED_GATEWS; break; + case BG_SA_PURPLE_GATE: uws = BG_SA_PURPLE_GATEWS; break; + case BG_SA_ANCIENT_GATE: uws = BG_SA_ANCIENT_GATEWS; break; + } + return uws; + } + void EndBattleGround(uint32 winner); + + void RemovePlayer(Player *plr,uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + + + /* Scorekeeping */ + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); + + private: + bool ResetObjs(); + void StartShips(); + void TeleportPlayers(); + void OverrideGunFaction(); + void DemolisherStartState(bool start); + void DestroyGate(Player* pl, GameObject* /*go*/, uint32 destroyedEvent); + void SendTime(); + void CaptureGraveyard(BG_SA_Graveyards i, Player *Source); + void ToggleTimer(); + void UpdateDemolisherSpawns(); + TeamId attackers; + uint32 TotalTime; + uint32 BG_SA_ENDROUNDTIME; + bool ShipsStarted; + BG_SA_GateState GateStatus[6]; + BG_SA_Status status; + TeamId GraveyardStatus[BG_SA_MAX_GY]; + BG_SA_RoundScore RoundScores[2]; + bool TimerEnabled; + uint32 UpdateWaitTimer;//5secs before starting the 1min countdown for second round + bool SignaledRoundTwo; + bool SignaledRoundTwoHalfMin; + bool InitSecondRound; +}; +#endif diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundWS.cpp b/src/server/game/BattleGrounds/Zones/BattleGroundWS.cpp new file mode 100644 index 00000000000..71872511274 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundWS.cpp @@ -0,0 +1,841 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundWS.h" +#include "Creature.h" +#include "GameObject.h" +#include "Language.h" +#include "Object.h" +#include "ObjectMgr.h" +#include "BattleGroundMgr.h" +#include "Player.h" +#include "World.h" +#include "WorldPacket.h" + +// these variables aren't used outside of this file, so declare them only here +enum BG_WSG_Rewards +{ + BG_WSG_WIN = 0, + BG_WSG_FLAG_CAP, + BG_WSG_MAP_COMPLETE, + BG_WSG_REWARD_NUM +}; + +uint32 BG_WSG_Honor[BG_HONOR_MODE_NUM][BG_WSG_REWARD_NUM] = { + {20,40,40}, // normal honor + {60,40,80} // holiday +}; + +uint32 BG_WSG_Reputation[BG_HONOR_MODE_NUM][BG_WSG_REWARD_NUM] = { + {0,35,0}, // normal honor + {0,45,0} // holiday +}; + +BattleGroundWS::BattleGroundWS() +{ + m_BgObjects.resize(BG_WS_OBJECT_MAX); + m_BgCreatures.resize(BG_CREATURES_MAX_WS); + + m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES; + m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE; + m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN; +} + +BattleGroundWS::~BattleGroundWS() +{ +} + +void BattleGroundWS::Update(uint32 diff) +{ + BattleGround::Update(diff); + + if (GetStatus() == STATUS_IN_PROGRESS) + { + if (GetStartTime() >= 25*MINUTE*IN_MILISECONDS) // Òàéìåð òèêàòü íà÷èíàåò ïîñëå 25 ìèíóò + { + if (GetTeamScore(ALLIANCE) == 0) + { + if (GetTeamScore(HORDE) == 0) // No one scored - result is tie + EndBattleGround(NULL); + else // Horde has more points and thus wins + EndBattleGround(HORDE); + } + + else if (GetTeamScore(HORDE) == 0) + EndBattleGround(ALLIANCE); // Alliance has > 0, Horde has 0, alliance wins + + else if (GetTeamScore(HORDE) == GetTeamScore(ALLIANCE)) // Team score equal, winner is team that scored the first flag + EndBattleGround(m_FirstFlagCaptureTeam); + + else if (GetTeamScore(HORDE) > GetTeamScore(ALLIANCE)) // Last but not least, check who has the higher score + EndBattleGround(HORDE); + else + EndBattleGround(ALLIANCE); + } + else if (GetStartTime() > m_minutesElapsed*MINUTE*IN_MILISECONDS) + { + ++m_minutesElapsed; + UpdateWorldState(BG_WS_STATE_TIMER, 25-m_minutesElapsed); + } + + if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) + { + m_FlagsTimer[BG_TEAM_ALLIANCE] -= diff; + + if (m_FlagsTimer[BG_TEAM_ALLIANCE] < 0) + { + m_FlagsTimer[BG_TEAM_ALLIANCE] = 0; + RespawnFlag(ALLIANCE, true); + } + } + if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) + { + m_FlagsDropTimer[BG_TEAM_ALLIANCE] -= diff; + + if (m_FlagsDropTimer[BG_TEAM_ALLIANCE] < 0) + { + m_FlagsDropTimer[BG_TEAM_ALLIANCE] = 0; + RespawnFlagAfterDrop(ALLIANCE); + m_BothFlagsKept = false; + } + } + if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_WAIT_RESPAWN) + { + m_FlagsTimer[BG_TEAM_HORDE] -= diff; + + if (m_FlagsTimer[BG_TEAM_HORDE] < 0) + { + m_FlagsTimer[BG_TEAM_HORDE] = 0; + RespawnFlag(HORDE, true); + } + } + if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) + { + m_FlagsDropTimer[BG_TEAM_HORDE] -= diff; + + if (m_FlagsDropTimer[BG_TEAM_HORDE] < 0) + { + m_FlagsDropTimer[BG_TEAM_HORDE] = 0; + RespawnFlagAfterDrop(HORDE); + m_BothFlagsKept = false; + } + } + if (m_BothFlagsKept) + { + m_FlagSpellForceTimer += diff; + if (m_FlagDebuffState == 0 && m_FlagSpellForceTimer >= 600000) //10 minutes + { + if (Player * plr = objmgr.GetPlayer(m_FlagKeepers[0])) + plr->CastSpell(plr,WS_SPELL_FOCUSED_ASSAULT,true); + if (Player * plr = objmgr.GetPlayer(m_FlagKeepers[1])) + plr->CastSpell(plr,WS_SPELL_FOCUSED_ASSAULT,true); + m_FlagDebuffState = 1; + } + else if (m_FlagDebuffState == 1 && m_FlagSpellForceTimer >= 900000) //15 minutes + { + if (Player * plr = objmgr.GetPlayer(m_FlagKeepers[0])) + { + plr->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); + plr->CastSpell(plr,WS_SPELL_BRUTAL_ASSAULT,true); + } + if (Player * plr = objmgr.GetPlayer(m_FlagKeepers[1])) + { + plr->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); + plr->CastSpell(plr,WS_SPELL_BRUTAL_ASSAULT,true); + } + m_FlagDebuffState = 2; + } + } + else + { + m_FlagSpellForceTimer = 0; //reset timer. + m_FlagDebuffState = 0; + } + } +} + +void BattleGroundWS::StartingEventCloseDoors() +{ + for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; ++i) + { + DoorClose(i); + SpawnBGObject(i, RESPAWN_IMMEDIATELY); + } + for (uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i) + SpawnBGObject(i, RESPAWN_ONE_DAY); + + UpdateWorldState(BG_WS_STATE_TIMER_ACTIVE, 1); + UpdateWorldState(BG_WS_STATE_TIMER, 25); +} + +void BattleGroundWS::StartingEventOpenDoors() +{ + for (uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_A_4; ++i) + DoorOpen(i); + for (uint32 i = BG_WS_OBJECT_DOOR_H_1; i <= BG_WS_OBJECT_DOOR_H_2; ++i) + DoorOpen(i); + + SpawnBGObject(BG_WS_OBJECT_DOOR_A_5, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_A_6, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_H_3, RESPAWN_ONE_DAY); + SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY); + + for (uint32 i = BG_WS_OBJECT_A_FLAG; i <= BG_WS_OBJECT_BERSERKBUFF_2; ++i) + SpawnBGObject(i, RESPAWN_IMMEDIATELY); +} + +void BattleGroundWS::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundWGScore* sc = new BattleGroundWGScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundWS::RespawnFlag(uint32 Team, bool captured) +{ + if (Team == ALLIANCE) + { + sLog.outDebug("Respawn Alliance flag"); + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; + } + else + { + sLog.outDebug("Respawn Horde flag"); + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; + } + + if (captured) + { + //when map_update will be allowed for battlegrounds this code will be useless + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); + SendMessageToAll(LANG_BG_WS_F_PLACED, CHAT_MSG_BG_SYSTEM_NEUTRAL); + PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); // flag respawned sound... + } + m_BothFlagsKept = false; +} + +void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + RespawnFlag(team,false); + if (team == ALLIANCE) + { + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); + SendMessageToAll(LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); + } + else + { + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); + SendMessageToAll(LANG_BG_WS_HORDE_FLAG_RESPAWNED, CHAT_MSG_BG_SYSTEM_NEUTRAL); + } + + PlaySoundToAll(BG_WS_SOUND_FLAGS_RESPAWNED); + + GameObject *obj = GetBgMap()->GetGameObject(GetDroppedFlagGUID(team)); + if (obj) + obj->Delete(); + else + sLog.outError("unknown droped flag bg, guid: %u",GUID_LOPART(GetDroppedFlagGUID(team))); + + SetDroppedFlagGUID(0,team); + m_BothFlagsKept = false; +} + +void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + uint32 winner = 0; + + Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + if (Source->GetTeam() == ALLIANCE) + { + if (!this->IsHordeFlagPickedup()) + return; + SetHordeFlagPicker(0); // must be before aura remove to prevent 2 events (drop+capture) at the same time + // horde flag in base (but not respawned yet) + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; + // Drop Horde Flag from Player + Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); + if (m_FlagDebuffState == 1) + Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); + if (m_FlagDebuffState == 2) + Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); + if (GetTeamScore(ALLIANCE) < BG_WS_MAX_TEAM_SCORE) + AddPoint(ALLIANCE, 1); + PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE); + RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE); + } + else + { + if (!this->IsAllianceFlagPickedup()) + return; + SetAllianceFlagPicker(0); // must be before aura remove to prevent 2 events (drop+capture) at the same time + // alliance flag in base (but not respawned yet) + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_WAIT_RESPAWN; + // Drop Alliance Flag from Player + Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); + if (m_FlagDebuffState == 1) + Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); + if (m_FlagDebuffState == 2) + Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); + if (GetTeamScore(HORDE) < BG_WS_MAX_TEAM_SCORE) + AddPoint(HORDE, 1); + PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE); + RewardReputationToTeam(889, m_ReputationCapture, HORDE); + } + //for flag capture is reward 2 honorable kills + RewardHonorToTeam(GetBonusHonorFromKill(2), Source->GetTeam()); + + SpawnBGObject(BG_WS_OBJECT_H_FLAG, BG_WS_FLAG_RESPAWN_TIME); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, BG_WS_FLAG_RESPAWN_TIME); + + if (Source->GetTeam() == ALLIANCE) + SendMessageToAll(LANG_BG_WS_CAPTURED_HF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + else + SendMessageToAll(LANG_BG_WS_CAPTURED_AF, CHAT_MSG_BG_SYSTEM_HORDE, Source); + + UpdateFlagState(Source->GetTeam(), 1); // flag state none + UpdateTeamScore(Source->GetTeam()); + // only flag capture should be updated + UpdatePlayerScore(Source, SCORE_FLAG_CAPTURES, 1); // +1 flag captures + + if (!m_FirstFlagCaptureTeam) + SetFirstFlagCapture(Source->GetTeam()); + + if (GetTeamScore(ALLIANCE) == BG_WS_MAX_TEAM_SCORE) + winner = ALLIANCE; + + if (GetTeamScore(HORDE) == BG_WS_MAX_TEAM_SCORE) + winner = HORDE; + + if (winner) + { + UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 0); + UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 0); + UpdateWorldState(BG_WS_FLAG_STATE_ALLIANCE, 1); + UpdateWorldState(BG_WS_FLAG_STATE_HORDE, 1); + UpdateWorldState(BG_WS_STATE_TIMER_ACTIVE, 0); + + RewardHonorToTeam(BG_WSG_Honor[m_HonorMode][BG_WSG_WIN], winner); + EndBattleGround(winner); + } + else + { + m_FlagsTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_RESPAWN_TIME; + } +} + +void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + { + // if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages + // just take off the aura + if (Source->GetTeam() == ALLIANCE) + { + if (!this->IsHordeFlagPickedup()) + return; + if (GetHordeFlagPickerGUID() == Source->GetGUID()) + { + SetHordeFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); + } + } + else + { + if (!this->IsAllianceFlagPickedup()) + return; + if (GetAllianceFlagPickerGUID() == Source->GetGUID()) + { + SetAllianceFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); + } + } + return; + } + + bool set = false; + + if (Source->GetTeam() == ALLIANCE) + { + if (!IsHordeFlagPickedup()) + return; + if (GetHordeFlagPickerGUID() == Source->GetGUID()) + { + SetHordeFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); + if (m_FlagDebuffState == 1) + Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); + if (m_FlagDebuffState == 2) + Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_GROUND; + Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG_DROPPED, true); + set = true; + } + } + else + { + if (!IsAllianceFlagPickedup()) + return; + if (GetAllianceFlagPickerGUID() == Source->GetGUID()) + { + SetAllianceFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); + if (m_FlagDebuffState == 1) + Source->RemoveAurasDueToSpell(WS_SPELL_FOCUSED_ASSAULT); + if (m_FlagDebuffState == 2) + Source->RemoveAurasDueToSpell(WS_SPELL_BRUTAL_ASSAULT); + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_GROUND; + Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG_DROPPED, true); + set = true; + } + } + + if (set) + { + Source->CastSpell(Source, SPELL_RECENTLY_DROPPED_FLAG, true); + UpdateFlagState(Source->GetTeam(), 1); + + if (Source->GetTeam() == ALLIANCE) + { + SendMessageToAll(LANG_BG_WS_DROPPED_HF, CHAT_MSG_BG_SYSTEM_HORDE, Source); + UpdateWorldState(BG_WS_FLAG_UNK_HORDE, uint32(-1)); + } + else + { + SendMessageToAll(LANG_BG_WS_DROPPED_AF, CHAT_MSG_BG_SYSTEM_ALLIANCE, Source); + UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, uint32(-1)); + } + + m_FlagsDropTimer[GetTeamIndexByTeamId(Source->GetTeam()) ? 0 : 1] = BG_WS_FLAG_DROP_TIME; + } +} + +void BattleGroundWS::EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + int32 message_id = 0; + ChatMsg type = CHAT_MSG_BG_SYSTEM_NEUTRAL; + + //alliance flag picked up from base + if (Source->GetTeam() == HORDE && this->GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE + && this->m_BgObjects[BG_WS_OBJECT_A_FLAG] == target_obj->GetGUID()) + { + message_id = LANG_BG_WS_PICKEDUP_AF; + type = CHAT_MSG_BG_SYSTEM_HORDE; + PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); + SetAllianceFlagPicker(Source->GetGUID()); + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; + //update world state to show correct flag carrier + UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER); + UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1); + Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); + if (m_FlagState[1] == BG_WS_FLAG_STATE_ON_PLAYER) + m_BothFlagsKept = true; + } + + //horde flag picked up from base + if (Source->GetTeam() == ALLIANCE && this->GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_BASE + && this->m_BgObjects[BG_WS_OBJECT_H_FLAG] == target_obj->GetGUID()) + { + message_id = LANG_BG_WS_PICKEDUP_HF; + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); + SetHordeFlagPicker(Source->GetGUID()); + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; + //update world state to show correct flag carrier + UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER); + UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1); + Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); + if (m_FlagState[0] == BG_WS_FLAG_STATE_ON_PLAYER) + m_BothFlagsKept = true; + } + + //Alliance flag on ground(not in base) (returned or picked up again from ground!) + if (GetFlagState(ALLIANCE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10)) + { + if (Source->GetTeam() == ALLIANCE) + { + message_id = LANG_BG_WS_RETURNED_AF; + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + UpdateFlagState(HORDE, BG_WS_FLAG_STATE_WAIT_RESPAWN); + RespawnFlag(ALLIANCE, false); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_IMMEDIATELY); + PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); + UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); + m_BothFlagsKept = false; + } + else + { + message_id = LANG_BG_WS_PICKEDUP_AF; + type = CHAT_MSG_BG_SYSTEM_HORDE; + PlaySoundToAll(BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP); + SpawnBGObject(BG_WS_OBJECT_A_FLAG, RESPAWN_ONE_DAY); + SetAllianceFlagPicker(Source->GetGUID()); + Source->CastSpell(Source, BG_WS_SPELL_SILVERWING_FLAG, true); + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_PLAYER; + UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER); + if (m_FlagDebuffState == 1) + Source->CastSpell(Source,WS_SPELL_FOCUSED_ASSAULT,true); + if (m_FlagDebuffState == 2) + Source->CastSpell(Source,WS_SPELL_BRUTAL_ASSAULT,true); + UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1); + } + //called in HandleGameObjectUseOpcode: + //target_obj->Delete(); + } + + //Horde flag on ground(not in base) (returned or picked up again) + if (GetFlagState(HORDE) == BG_WS_FLAG_STATE_ON_GROUND && Source->IsWithinDistInMap(target_obj, 10)) + { + if (Source->GetTeam() == HORDE) + { + message_id = LANG_BG_WS_RETURNED_HF; + type = CHAT_MSG_BG_SYSTEM_HORDE; + UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_WAIT_RESPAWN); + RespawnFlag(HORDE, false); + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_IMMEDIATELY); + PlaySoundToAll(BG_WS_SOUND_FLAG_RETURNED); + UpdatePlayerScore(Source, SCORE_FLAG_RETURNS, 1); + m_BothFlagsKept = false; + } + else + { + message_id = LANG_BG_WS_PICKEDUP_HF; + type = CHAT_MSG_BG_SYSTEM_ALLIANCE; + PlaySoundToAll(BG_WS_SOUND_HORDE_FLAG_PICKED_UP); + SpawnBGObject(BG_WS_OBJECT_H_FLAG, RESPAWN_ONE_DAY); + SetHordeFlagPicker(Source->GetGUID()); + Source->CastSpell(Source, BG_WS_SPELL_WARSONG_FLAG, true); + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_PLAYER; + UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER); + if (m_FlagDebuffState == 1) + Source->CastSpell(Source,WS_SPELL_FOCUSED_ASSAULT,true); + if (m_FlagDebuffState == 2) + Source->CastSpell(Source,WS_SPELL_BRUTAL_ASSAULT,true); + UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1); + } + //called in HandleGameObjectUseOpcode: + //target_obj->Delete(); + } + + if (!message_id) + return; + + SendMessageToAll(message_id, type, Source); + Source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); +} + +void BattleGroundWS::RemovePlayer(Player *plr, uint64 guid) +{ + // sometimes flag aura not removed :( + if (IsAllianceFlagPickedup() && m_FlagKeepers[BG_TEAM_ALLIANCE] == guid) + { + if (!plr) + { + sLog.outError("BattleGroundWS: Removing offline player who has the FLAG!!"); + this->SetAllianceFlagPicker(0); + this->RespawnFlag(ALLIANCE, false); + } + else + this->EventPlayerDroppedFlag(plr); + } + if (IsHordeFlagPickedup() && m_FlagKeepers[BG_TEAM_HORDE] == guid) + { + if (!plr) + { + sLog.outError("BattleGroundWS: Removing offline player who has the FLAG!!"); + this->SetHordeFlagPicker(0); + this->RespawnFlag(HORDE, false); + } + else + this->EventPlayerDroppedFlag(plr); + } +} + +void BattleGroundWS::UpdateFlagState(uint32 team, uint32 value) +{ + if (team == ALLIANCE) + UpdateWorldState(BG_WS_FLAG_STATE_ALLIANCE, value); + else + UpdateWorldState(BG_WS_FLAG_STATE_HORDE, value); +} + +void BattleGroundWS::UpdateTeamScore(uint32 team) +{ + if (team == ALLIANCE) + UpdateWorldState(BG_WS_FLAG_CAPTURES_ALLIANCE, GetTeamScore(team)); + else + UpdateWorldState(BG_WS_FLAG_CAPTURES_HORDE, GetTeamScore(team)); +} + +void BattleGroundWS::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + //uint32 SpellId = 0; + //uint64 buff_guid = 0; + switch(Trigger) + { + case 3686: // Alliance elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update(). + //buff_guid = m_BgObjects[BG_WS_OBJECT_SPEEDBUFF_1]; + break; + case 3687: // Horde elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in BattleGround::Update(). + //buff_guid = m_BgObjects[BG_WS_OBJECT_SPEEDBUFF_2]; + break; + case 3706: // Alliance elixir of regeneration spawn + //buff_guid = m_BgObjects[BG_WS_OBJECT_REGENBUFF_1]; + break; + case 3708: // Horde elixir of regeneration spawn + //buff_guid = m_BgObjects[BG_WS_OBJECT_REGENBUFF_2]; + break; + case 3707: // Alliance elixir of berserk spawn + //buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_1]; + break; + case 3709: // Horde elixir of berserk spawn + //buff_guid = m_BgObjects[BG_WS_OBJECT_BERSERKBUFF_2]; + break; + case 3646: // Alliance Flag spawn + if (m_FlagState[BG_TEAM_HORDE] && !m_FlagState[BG_TEAM_ALLIANCE]) + if (GetHordeFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source); + break; + case 3647: // Horde Flag spawn + if (m_FlagState[BG_TEAM_ALLIANCE] && !m_FlagState[BG_TEAM_HORDE]) + if (GetAllianceFlagPickerGUID() == Source->GetGUID()) + EventPlayerCapturedFlag(Source); + break; + case 3649: // unk1 + case 3688: // unk2 + case 4628: // unk3 + case 4629: // unk4 + break; + default: + sLog.outError("WARNING: Unhandled AreaTrigger in Battleground: %u", Trigger); + Source->GetSession()->SendAreaTriggerMessage("Warning: Unhandled AreaTrigger in Battleground: %u", Trigger); + break; + } + + //if (buff_guid) + // HandleTriggerBuff(buff_guid,Source); +} + +bool BattleGroundWS::SetupBattleGround() +{ + // flags + if (!AddObject(BG_WS_OBJECT_A_FLAG, BG_OBJECT_A_FLAG_WS_ENTRY, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, BG_WS_FLAG_RESPAWN_TIME/1000) + || !AddObject(BG_WS_OBJECT_H_FLAG, BG_OBJECT_H_FLAG_WS_ENTRY, 916.0226f, 1434.405f, 345.413f, 0.01745329f, 0, 0, 0.008726535f, 0.9999619f, BG_WS_FLAG_RESPAWN_TIME/1000) + // buffs + || !AddObject(BG_WS_OBJECT_SPEEDBUFF_1, BG_OBJECTID_SPEEDBUFF_ENTRY, 1449.93f, 1470.71f, 342.6346f, -1.64061f, 0, 0, 0.7313537f, -0.6819983f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_SPEEDBUFF_2, BG_OBJECTID_SPEEDBUFF_ENTRY, 1005.171f, 1447.946f, 335.9032f, 1.64061f, 0, 0, 0.7313537f, 0.6819984f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_REGENBUFF_1, BG_OBJECTID_REGENBUFF_ENTRY, 1317.506f, 1550.851f, 313.2344f, -0.2617996f, 0, 0, 0.1305263f, -0.9914448f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_REGENBUFF_2, BG_OBJECTID_REGENBUFF_ENTRY, 1110.451f, 1353.656f, 316.5181f, -0.6806787f, 0, 0, 0.333807f, -0.9426414f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_BERSERKBUFF_1, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1320.09f, 1378.79f, 314.7532f, 1.186824f, 0, 0, 0.5591929f, 0.8290376f, BUFF_RESPAWN_TIME) + || !AddObject(BG_WS_OBJECT_BERSERKBUFF_2, BG_OBJECTID_BERSERKERBUFF_ENTRY, 1139.688f, 1560.288f, 306.8432f, -2.443461f, 0, 0, 0.9396926f, -0.3420201f, BUFF_RESPAWN_TIME) + // alliance gates + || !AddObject(BG_WS_OBJECT_DOOR_A_1, BG_OBJECT_DOOR_A_1_WS_ENTRY, 1503.335f, 1493.466f, 352.1888f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_2, BG_OBJECT_DOOR_A_2_WS_ENTRY, 1492.478f, 1457.912f, 342.9689f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_3, BG_OBJECT_DOOR_A_3_WS_ENTRY, 1468.503f, 1494.357f, 351.8618f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_4, BG_OBJECT_DOOR_A_4_WS_ENTRY, 1471.555f, 1458.778f, 362.6332f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_5, BG_OBJECT_DOOR_A_5_WS_ENTRY, 1492.347f, 1458.34f, 342.3712f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_A_6, BG_OBJECT_DOOR_A_6_WS_ENTRY, 1503.466f, 1493.367f, 351.7352f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, RESPAWN_IMMEDIATELY) + // horde gates + || !AddObject(BG_WS_OBJECT_DOOR_H_1, BG_OBJECT_DOOR_H_1_WS_ENTRY, 949.1663f, 1423.772f, 345.6241f, -0.5756807f, -0.01673368f, -0.004956111f, -0.2839723f, 0.9586737f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_H_2, BG_OBJECT_DOOR_H_2_WS_ENTRY, 953.0507f, 1459.842f, 340.6526f, -1.99662f, -0.1971825f, 0.1575096f, -0.8239487f, 0.5073641f, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_H_3, BG_OBJECT_DOOR_H_3_WS_ENTRY, 949.9523f, 1422.751f, 344.9273f, 0.0f, 0, 0, 0, 1, RESPAWN_IMMEDIATELY) + || !AddObject(BG_WS_OBJECT_DOOR_H_4, BG_OBJECT_DOOR_H_4_WS_ENTRY, 950.7952f, 1459.583f, 342.1523f, 0.05235988f, 0, 0, 0.02617695f, 0.9996573f, RESPAWN_IMMEDIATELY) +) + { + sLog.outErrorDb("BatteGroundWS: Failed to spawn some object BattleGround not created!"); + return false; + } + + WorldSafeLocsEntry const *sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE); + if (!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_ALLIANCE, sg->x, sg->y, sg->z, 3.124139f, ALLIANCE)) + { + sLog.outErrorDb("BatteGroundWS: Failed to spawn Alliance spirit guide! BattleGround not created!"); + return false; + } + + sg = sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE); + if (!sg || !AddSpiritGuide(WS_SPIRIT_MAIN_HORDE, sg->x, sg->y, sg->z, 3.193953f, HORDE)) + { + sLog.outErrorDb("BatteGroundWS: Failed to spawn Horde spirit guide! BattleGround not created!"); + return false; + } + + sLog.outDebug("BatteGroundWS: BG objects and spirit guides spawned"); + + return true; +} + +void BattleGroundWS::Reset() +{ + //call parent's class reset + BattleGround::Reset(); + + m_FlagKeepers[BG_TEAM_ALLIANCE] = 0; + m_FlagKeepers[BG_TEAM_HORDE] = 0; + m_DroppedFlagGUID[BG_TEAM_ALLIANCE] = 0; + m_DroppedFlagGUID[BG_TEAM_HORDE] = 0; + m_FlagState[BG_TEAM_ALLIANCE] = BG_WS_FLAG_STATE_ON_BASE; + m_FlagState[BG_TEAM_HORDE] = BG_WS_FLAG_STATE_ON_BASE; + m_TeamScores[BG_TEAM_ALLIANCE] = 0; + m_TeamScores[BG_TEAM_HORDE] = 0; + bool isBGWeekend = sBattleGroundMgr.IsBGWeekend(GetTypeID()); + m_ReputationCapture = (isBGWeekend) ? 45 : 35; + m_HonorWinKills = (isBGWeekend) ? 3 : 1; + m_HonorEndKills = (isBGWeekend) ? 4 : 2; + // For WorldState + m_minutesElapsed = 0; + m_FirstFlagCaptureTeam = 0; + + /* Spirit nodes is static at this BG and then not required deleting at BG reset. + if (m_BgCreatures[WS_SPIRIT_MAIN_ALLIANCE]) + DelCreature(WS_SPIRIT_MAIN_ALLIANCE); + if (m_BgCreatures[WS_SPIRIT_MAIN_HORDE]) + DelCreature(WS_SPIRIT_MAIN_HORDE); + */ +} + +void BattleGroundWS::EndBattleGround(uint32 winner) +{ + //win reward + if (winner == ALLIANCE) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), ALLIANCE); + if (winner == HORDE) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), HORDE); + //complete map_end rewards (even if no team wins) + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), ALLIANCE); + RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), HORDE); + + BattleGround::EndBattleGround(winner); +} + +void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer) +{ + if (GetStatus() != STATUS_IN_PROGRESS) + return; + + EventPlayerDroppedFlag(player); + + BattleGround::HandleKillPlayer(player, killer); +} + +void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor) +{ + + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); + if (itr == m_PlayerScores.end()) // player not found + return; + + switch(type) + { + case SCORE_FLAG_CAPTURES: // flags captured + ((BattleGroundWGScore*)itr->second)->FlagCaptures += value; + break; + case SCORE_FLAG_RETURNS: // flags returned + ((BattleGroundWGScore*)itr->second)->FlagReturns += value; + break; + default: + BattleGround::UpdatePlayerScore(Source, type, value, doAddHonor); + break; + } +} + +WorldSafeLocsEntry const* BattleGroundWS::GetClosestGraveYard(Player* player) +{ + //if status in progress, it returns main graveyards with spiritguides + //else it will return the graveyard in the flagroom - this is especially good + //if a player dies in preparation phase - then the player can't cheat + //and teleport to the graveyard outside the flagroom + //and start running around, while the doors are still closed + if (player->GetTeam() == ALLIANCE) + { + if (GetStatus() == STATUS_IN_PROGRESS) + return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_ALLIANCE); + else + return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_ALLIANCE); + } + else + { + if (GetStatus() == STATUS_IN_PROGRESS) + return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_MAIN_HORDE); + else + return sWorldSafeLocsStore.LookupEntry(WS_GRAVEYARD_FLAGROOM_HORDE); + } +} + +void BattleGroundWS::FillInitialWorldStates(WorldPacket& data) +{ + data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(ALLIANCE)); + data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(HORDE)); + + if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_GROUND) + data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(-1); + else if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) + data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(1); + else + data << uint32(BG_WS_FLAG_UNK_ALLIANCE) << uint32(0); + + if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_GROUND) + data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(-1); + else if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) + data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(1); + else + data << uint32(BG_WS_FLAG_UNK_HORDE) << uint32(0); + + data << uint32(BG_WS_FLAG_CAPTURES_MAX) << uint32(BG_WS_MAX_TEAM_SCORE); + + if (GetStatus() == STATUS_IN_PROGRESS) + { + data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(1); + data << uint32(BG_WS_STATE_TIMER) << uint32(25-m_minutesElapsed); + } + else + data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(0); + + if (m_FlagState[BG_TEAM_HORDE] == BG_WS_FLAG_STATE_ON_PLAYER) + data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(2); + else + data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(1); + + if (m_FlagState[BG_TEAM_ALLIANCE] == BG_WS_FLAG_STATE_ON_PLAYER) + data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(2); + else + data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(1); + +} + diff --git a/src/server/game/BattleGrounds/Zones/BattleGroundWS.h b/src/server/game/BattleGrounds/Zones/BattleGroundWS.h new file mode 100644 index 00000000000..1a733c14570 --- /dev/null +++ b/src/server/game/BattleGrounds/Zones/BattleGroundWS.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDWS_H +#define __BATTLEGROUNDWS_H + +#include "BattleGround.h" + +enum BG_WS_TimerOrScore +{ + BG_WS_MAX_TEAM_SCORE = 3, + BG_WS_FLAG_RESPAWN_TIME = 23000, + BG_WS_FLAG_DROP_TIME = 10000, + BG_WS_SPELL_FORCE_TIME = 600000, + BG_WS_SPELL_BRUTAL_TIME = 900000 +}; + +enum BG_WS_Sound +{ + BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE = 8173, + BG_WS_SOUND_FLAG_CAPTURED_HORDE = 8213, + BG_WS_SOUND_FLAG_PLACED = 8232, + BG_WS_SOUND_FLAG_RETURNED = 8192, + BG_WS_SOUND_HORDE_FLAG_PICKED_UP = 8212, + BG_WS_SOUND_ALLIANCE_FLAG_PICKED_UP = 8174, + BG_WS_SOUND_FLAGS_RESPAWNED = 8232 +}; + +enum BG_WS_SpellId +{ + BG_WS_SPELL_WARSONG_FLAG = 23333, + BG_WS_SPELL_WARSONG_FLAG_DROPPED = 23334, + BG_WS_SPELL_SILVERWING_FLAG = 23335, + BG_WS_SPELL_SILVERWING_FLAG_DROPPED = 23336, + BG_WS_SPELL_FOCUSED_ASSAULT = 46392, + BG_WS_SPELL_BRUTAL_ASSAULT = 46393 +}; + +enum BG_WS_WorldStates +{ + BG_WS_FLAG_UNK_ALLIANCE = 1545, + BG_WS_FLAG_UNK_HORDE = 1546, +// FLAG_UNK = 1547, + BG_WS_FLAG_CAPTURES_ALLIANCE = 1581, + BG_WS_FLAG_CAPTURES_HORDE = 1582, + BG_WS_FLAG_CAPTURES_MAX = 1601, + BG_WS_FLAG_STATE_HORDE = 2338, + BG_WS_FLAG_STATE_ALLIANCE = 2339, + BG_WS_STATE_TIMER = 4248, + BG_WS_STATE_TIMER_ACTIVE = 4247 +}; + +enum BG_WS_ObjectTypes +{ + BG_WS_OBJECT_DOOR_A_1 = 0, + BG_WS_OBJECT_DOOR_A_2 = 1, + BG_WS_OBJECT_DOOR_A_3 = 2, + BG_WS_OBJECT_DOOR_A_4 = 3, + BG_WS_OBJECT_DOOR_A_5 = 4, + BG_WS_OBJECT_DOOR_A_6 = 5, + BG_WS_OBJECT_DOOR_H_1 = 6, + BG_WS_OBJECT_DOOR_H_2 = 7, + BG_WS_OBJECT_DOOR_H_3 = 8, + BG_WS_OBJECT_DOOR_H_4 = 9, + BG_WS_OBJECT_A_FLAG = 10, + BG_WS_OBJECT_H_FLAG = 11, + BG_WS_OBJECT_SPEEDBUFF_1 = 12, + BG_WS_OBJECT_SPEEDBUFF_2 = 13, + BG_WS_OBJECT_REGENBUFF_1 = 14, + BG_WS_OBJECT_REGENBUFF_2 = 15, + BG_WS_OBJECT_BERSERKBUFF_1 = 16, + BG_WS_OBJECT_BERSERKBUFF_2 = 17, + BG_WS_OBJECT_MAX = 18 +}; + +enum BG_WS_ObjectEntry +{ + BG_OBJECT_DOOR_A_1_WS_ENTRY = 179918, + BG_OBJECT_DOOR_A_2_WS_ENTRY = 179919, + BG_OBJECT_DOOR_A_3_WS_ENTRY = 179920, + BG_OBJECT_DOOR_A_4_WS_ENTRY = 179921, + BG_OBJECT_DOOR_A_5_WS_ENTRY = 180322, + BG_OBJECT_DOOR_A_6_WS_ENTRY = 180322, + BG_OBJECT_DOOR_H_1_WS_ENTRY = 179916, + BG_OBJECT_DOOR_H_2_WS_ENTRY = 179917, + BG_OBJECT_DOOR_H_3_WS_ENTRY = 180322, + BG_OBJECT_DOOR_H_4_WS_ENTRY = 180322, + BG_OBJECT_A_FLAG_WS_ENTRY = 179830, + BG_OBJECT_H_FLAG_WS_ENTRY = 179831, + BG_OBJECT_A_FLAG_GROUND_WS_ENTRY = 179785, + BG_OBJECT_H_FLAG_GROUND_WS_ENTRY = 179786 +}; + +enum BG_WS_FlagState +{ + BG_WS_FLAG_STATE_ON_BASE = 0, + BG_WS_FLAG_STATE_WAIT_RESPAWN = 1, + BG_WS_FLAG_STATE_ON_PLAYER = 2, + BG_WS_FLAG_STATE_ON_GROUND = 3 +}; + +enum BG_WS_Graveyards +{ + WS_GRAVEYARD_FLAGROOM_ALLIANCE = 769, + WS_GRAVEYARD_FLAGROOM_HORDE = 770, + WS_GRAVEYARD_MAIN_ALLIANCE = 771, + WS_GRAVEYARD_MAIN_HORDE = 772 +}; + +enum BG_WS_CreatureTypes +{ + WS_SPIRIT_MAIN_ALLIANCE = 0, + WS_SPIRIT_MAIN_HORDE = 1, + + BG_CREATURES_MAX_WS = 2 +}; + +enum BG_WS_CarrierDebuffs +{ + WS_SPELL_FOCUSED_ASSAULT = 46392, + WS_SPELL_BRUTAL_ASSAULT = 46393 +}; + +class BattleGroundWGScore : public BattleGroundScore +{ + public: + BattleGroundWGScore() : FlagCaptures(0), FlagReturns(0) {}; + virtual ~BattleGroundWGScore() {}; + uint32 FlagCaptures; + uint32 FlagReturns; +}; + +class BattleGroundWS : public BattleGround +{ + friend class BattleGroundMgr; + + public: + /* Construction */ + BattleGroundWS(); + ~BattleGroundWS(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + virtual void StartingEventCloseDoors(); + virtual void StartingEventOpenDoors(); + + /* BG Flags */ + uint64 GetAllianceFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_ALLIANCE]; } + uint64 GetHordeFlagPickerGUID() const { return m_FlagKeepers[BG_TEAM_HORDE]; } + void SetAllianceFlagPicker(uint64 guid) { m_FlagKeepers[BG_TEAM_ALLIANCE] = guid; } + void SetHordeFlagPicker(uint64 guid) { m_FlagKeepers[BG_TEAM_HORDE] = guid; } + bool IsAllianceFlagPickedup() const { return m_FlagKeepers[BG_TEAM_ALLIANCE] != 0; } + bool IsHordeFlagPickedup() const { return m_FlagKeepers[BG_TEAM_HORDE] != 0; } + void RespawnFlag(uint32 Team, bool captured); + void RespawnFlagAfterDrop(uint32 Team); + uint8 GetFlagState(uint32 team) { return m_FlagState[GetTeamIndexByTeamId(team)]; } + void AddTimedAura(uint32 aura); + void RemoveTimedAura(uint32 aura); + bool IsBrutalTimerDone; + bool IsForceTimerDone; + + /* Battleground Events */ + virtual void EventPlayerDroppedFlag(Player *Source); + virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); + virtual void EventPlayerCapturedFlag(Player *Source); + + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + void HandleKillPlayer(Player *player, Player *killer); + bool SetupBattleGround(); + virtual void Reset(); + void EndBattleGround(uint32 winner); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); + + void UpdateFlagState(uint32 team, uint32 value); + void SetFirstFlagCapture(uint32 team) { m_FirstFlagCaptureTeam = team; } + void UpdateTeamScore(uint32 team); + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value, bool doAddHonor = true); + void SetDroppedFlagGUID(uint64 guid, uint32 TeamID) { m_DroppedFlagGUID[GetTeamIndexByTeamId(TeamID)] = guid;} + uint64 GetDroppedFlagGUID(uint32 TeamID) { return m_DroppedFlagGUID[GetTeamIndexByTeamId(TeamID)];} + virtual void FillInitialWorldStates(WorldPacket& data); + + /* Scorekeeping */ + uint32 GetTeamScore(uint32 TeamID) const { return m_TeamScores[GetTeamIndexByTeamId(TeamID)]; } + void AddPoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] += Points; } + void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } + void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } + private: + uint64 m_FlagKeepers[2]; // 0 - alliance, 1 - horde + uint64 m_DroppedFlagGUID[2]; + uint8 m_FlagState[2]; // for checking flag state + int32 m_FlagsTimer[2]; + int32 m_FlagsDropTimer[2]; + uint32 m_FirstFlagCaptureTeam; // Winner is based on this if score is equal + + uint32 m_ReputationCapture; + uint32 m_HonorWinKills; + uint32 m_HonorEndKills; + int32 m_FlagSpellForceTimer; + bool m_BothFlagsKept; + uint8 m_FlagDebuffState; // 0 - no debuffs, 1 - focused assault, 2 - brutal assault + uint8 m_minutesElapsed; +}; +#endif + diff --git a/src/server/game/Calendar/CalendarHandler.cpp b/src/server/game/Calendar/CalendarHandler.cpp deleted file mode 100644 index f6679c5d5ac..00000000000 --- a/src/server/game/Calendar/CalendarHandler.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" - -#include "InstanceSaveMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Player.h" - -void WorldSession::HandleCalendarGetCalendar(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_GET_CALENDAR"); // empty - - time_t cur_time = time(NULL); - - WorldPacket data(SMSG_CALENDAR_SEND_CALENDAR,4+4*0+4+4*0+4+4); - - data << uint32(0); // invite count - /* - for (;;) - { - uint64 inviteId; - uint64 unkGuid0; - uint8 unk1, unk2, unk3; - uint64 creatorGuid; - } - */ - - data << uint32(0); // event count - /* - for (;;) - { - uint64 eventId; - std::string title; // 128 chars - uint32 type; - uint32 occurrenceTime; - uint32 flags; - uint32 unk4; -- possibly mapid for dungeon/raid - uint64 creatorGuid; - } - */ - - data << uint32(0); // unk - data << uint32(secsToTimeBitFields(cur_time)); // current time - - uint32 counter = 0; - size_t p_counter = data.wpos(); - data << uint32(counter); // instance save count - - for (int i = 0; i < MAX_DIFFICULTY; ++i) - { - for (Player::BoundInstancesMap::const_iterator itr = _player->m_boundInstances[i].begin(); itr != _player->m_boundInstances[i].end(); ++itr) - { - if (itr->second.perm) - { - InstanceSave *save = itr->second.save; - data << uint32(save->GetMapId()); - data << uint32(save->GetDifficulty()); - data << uint32(save->GetResetTime() - cur_time); - data << uint64(save->GetInstanceId()); // instance save id as unique instance copy id - ++counter; - } - } - } - - data.put(p_counter, counter); - - data << uint32(1135753200); // unk (28.12.2005 12:00) - - counter = 0; - p_counter = data.wpos(); - data << uint32(counter); // raid reset count - - ResetTimeByMapDifficultyMap const& resets = sInstanceSaveManager.GetResetTimeMap(); - for (ResetTimeByMapDifficultyMap::const_iterator itr = resets.begin(); itr != resets.end(); ++itr) - { - uint32 mapid = PAIR32_LOPART(itr->first); - MapEntry const* mapEnt = sMapStore.LookupEntry(mapid); - if (!mapEnt || !mapEnt->IsRaid()) - continue; - - data << uint32(mapid); - data << uint32(itr->second - cur_time); - data << uint32(mapEnt->unk_time); - ++counter; - } - - data.put(p_counter, counter); - - data << uint32(0); // holiday count? - /* - for (;;) - { - uint32 unk5, unk6, unk7, unk8, unk9; - for (uint32 j = 0; j < 26; ++j) - { - uint32 unk10; - } - for (uint32 j = 0; j < 10; ++j) - { - uint32 unk11; - } - for (uint32 j = 0; j < 10; ++j) - { - uint32 unk12; - } - std::string holidayName; // 64 chars - } - */ - - sLog.outDebug("Sending calendar"); - data.hexlike(); - SendPacket(&data); -} - -void WorldSession::HandleCalendarGetEvent(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_GET_EVENT"); - recv_data.hexlike(); - recv_data.read_skip(); // unk -} - -void WorldSession::HandleCalendarGuildFilter(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_GUILD_FILTER"); - recv_data.hexlike(); - recv_data.read_skip(); // unk1 - recv_data.read_skip(); // unk2 - recv_data.read_skip(); // unk3 -} - -void WorldSession::HandleCalendarArenaTeam(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_ARENA_TEAM"); - recv_data.hexlike(); - recv_data.read_skip(); // unk -} - -void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //std::string unk1, unk2; - //recv_data >> (std::string)unk1; - //recv_data >> (std::string)unk2; - - //uint8 unk3, unk4; - //uint32 unk5, unk6, unk7, unk8, unk9, count = 0; - //recv_data >> (uint8)unk3; - //recv_data >> (uint8)unk4; - //recv_data >> (uint32)unk5; - //recv_data >> (uint32)unk6; - //recv_data >> (uint32)unk7; - //recv_data >> (uint32)unk8; - //recv_data >> (uint32)unk9; - //if (!((unk9 >> 6) & 1)) - //{ - // recv_data >> (uint32)count; - // if (count) - // { - // uint8 unk12,unk13; - // uint64 guid; - // for (int i=0; i> (uint8)unk12; - // recv_data >> (uint8)unk13; - // } - // } - //} -} - -void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> std::string - //recv_data >> std::string - //recv_data >> uint8 - //recv_data >> uint8 - //recv_data >> uint32 - //recv_data >> uint32 - //recv_data >> uint32 - //recv_data >> uint32 - //recv_data >> uint32 -} - -void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 - -} - -void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 - -} - -void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> std::string - //recv_data >> uint8 - //recv_data >> uint8 - -} - -void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 - -} - -void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data.readPackGUID(guid) - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint64 -} - -void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data.readPackGUID(guid) - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 -} - -void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data.readPackGUID(guid) - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint32 -} - -void WorldSession::HandleCalendarComplain(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN"); - recv_data.hexlike(); - recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam - - //recv_data >> uint64 - //recv_data >> uint64 - //recv_data >> uint64 -} - -void WorldSession::HandleCalendarGetNumPending(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: CMSG_CALENDAR_GET_NUM_PENDING"); // empty - - WorldPacket data(SMSG_CALENDAR_SEND_NUM_PENDING, 4); - data << uint32(0); // 0 - no pending invites, 1 - some pending invites - SendPacket(&data); -} diff --git a/src/server/game/Chat/Channel.cpp b/src/server/game/Chat/Channel.cpp deleted file mode 100644 index 0047892972b..00000000000 --- a/src/server/game/Chat/Channel.cpp +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Channel.h" -#include "Chat.h" -#include "ObjectMgr.h" -#include "SocialMgr.h" -#include "World.h" - -Channel::Channel(const std::string& name, uint32 channel_id, uint32 Team) - : m_name(name), m_announce(true), m_moderate(false), m_channelId(channel_id), m_ownerGUID(0), m_password(""), m_flags(0), m_Team(Team) -{ - // set special flags if built-in channel - ChatChannelsEntry const* ch = GetChannelEntryFor(channel_id); - if (ch) // it's built-in channel - { - channel_id = ch->ChannelID; // built-in channel - m_announce = false; // no join/leave announces - - m_flags |= CHANNEL_FLAG_GENERAL; // for all built-in channels - - if (ch->flags & CHANNEL_DBC_FLAG_TRADE) // for trade channel - m_flags |= CHANNEL_FLAG_TRADE; - - if (ch->flags & CHANNEL_DBC_FLAG_CITY_ONLY2) // for city only channels - m_flags |= CHANNEL_FLAG_CITY; - - if (ch->flags & CHANNEL_DBC_FLAG_LFG) // for LFG channel - m_flags |= CHANNEL_FLAG_LFG; - else // for all other channels - m_flags |= CHANNEL_FLAG_NOT_LFG; - m_IsSaved = false; - } - else // it's custom channel - { - m_flags |= CHANNEL_FLAG_CUSTOM; - //load not built in channel if saved - std::string _name(name); - CharacterDatabase.escape_string(_name); - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT m_announce, m_moderate, m_public, m_password, BannedList FROM channels WHERE m_name = '%s' AND m_team = '%u'", _name.c_str(), m_Team); - if (result)//load - { - Field *fields = result->Fetch(); - m_announce = fields[0].GetBool(); - m_moderate = fields[1].GetBool(); - m_public = fields[2].GetBool(); - m_password = fields[3].GetString(); - const char* db_BannedList = fields[4].GetString(); - - m_IsSaved = true; - - if (db_BannedList) - { - Tokens tokens = StrSplit(db_BannedList, " "); - Tokens::iterator iter; - for (iter = tokens.begin(); iter != tokens.end(); ++iter) - { - uint64 banned_guid = atol((*iter).c_str()); - if (banned_guid) - { - sLog.outDebug("Channel(%s) loaded banned guid: %u",name.c_str(), banned_guid); - banned.insert(banned_guid); - } - } - } - } - else // save - { - // _name is already escaped at this point. - if (CharacterDatabase.PExecute("INSERT INTO channels (m_name, m_team, m_announce, m_moderate, m_public, m_password) " - "VALUES ('%s', '%u', '1', '0', '1', '')", _name.c_str(), m_Team)) - { - sLog.outDebug("New Channel(%s) saved", name.c_str()); - m_IsSaved = true; - } - } - } -} - -bool Channel::_UpdateStringInDB(const std::string& colName, const std::string& colValue) const -{ - // Prevent SQL-injection - std::string _name(m_name); - std::string _colValue(colValue); - CharacterDatabase.escape_string(_colValue); - CharacterDatabase.escape_string(_name); - return CharacterDatabase.PExecute("UPDATE channels SET %s = '%s' WHERE m_name = '%s' AND m_team = '%u'", - colName.c_str(), _colValue.c_str(), _name.c_str(), m_Team); -} - -bool Channel::_UpdateIntInDB(const std::string& colName, int colValue) const -{ - // Prevent SQL-injection - std::string _name(m_name); - CharacterDatabase.escape_string(_name); - return CharacterDatabase.PExecute("UPDATE channels SET %s = '%u' WHERE m_name = '%s' AND m_team = '%u'", - colName.c_str(), colValue, _name.c_str(), m_Team); -} - -void Channel::_UpdateBanListInDB() const -{ - // save banlist - if (m_IsSaved) - { - std::ostringstream banlist; - BannedList::const_iterator iter; - for (iter = banned.begin(); iter != banned.end(); ++iter) - banlist << (*iter) << " "; - std::string banListStr = banlist.str(); - if (_UpdateStringInDB("BannedList", banListStr)) - sLog.outDebug("Channel(%s) BannedList saved", m_name.c_str()); - } -} - -void Channel::Join(uint64 p, const char *pass) -{ - WorldPacket data; - if (IsOn(p)) - { - if (!IsConstant()) // non send error message for built-in channels - { - MakePlayerAlreadyMember(&data, p); - SendToOne(&data, p); - } - return; - } - - if (IsBanned(p)) - { - MakeBanned(&data); - SendToOne(&data, p); - return; - } - - if (m_password.length() > 0 && strcmp(pass, m_password.c_str())) - { - MakeWrongPassword(&data); - SendToOne(&data, p); - return; - } - - Player *plr = objmgr.GetPlayer(p); - - if (plr) - { - if (HasFlag(CHANNEL_FLAG_LFG) && - sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER && plr->GetGroup()) - { - MakeNotInLfg(&data); - SendToOne(&data, p); - return; - } - - if (plr->GetGuildId() && (GetFlags() == 0x38)) - return; - - plr->JoinedChannel(this); - } - - if (m_announce && (!plr || plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || !sWorld.getConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL))) - { - MakeJoined(&data, p); - SendToAll(&data); - } - - data.clear(); - - PlayerInfo pinfo; - pinfo.player = p; - pinfo.flags = MEMBER_FLAG_NONE; - players[p] = pinfo; - - MakeYouJoined(&data); - SendToOne(&data, p); - - JoinNotify(p); - - // if no owner first logged will become - if (!IsConstant() && !m_ownerGUID) - { - SetOwner(p, (players.size() > 1 ? true : false)); - players[p].SetModerator(true); - } - /* - else if (!IsConstant() && m_ownerGUID && plr && m_ownerGUID == plr->GetGUID())) - { - SetOwner(p, (players.size() > 1 ? true : false)); - players[p].SetModerator(true); - }*/ -} - -void Channel::Leave(uint64 p, bool send) -{ - if (!IsOn(p)) - { - if (send) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - } - } - else - { - Player *plr = objmgr.GetPlayer(p); - - if (send) - { - WorldPacket data; - MakeYouLeft(&data); - SendToOne(&data, p); - if (plr) - plr->LeftChannel(this); - data.clear(); - } - - bool changeowner = players[p].IsOwner(); - - players.erase(p); - if (m_announce && (!plr || plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || !sWorld.getConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL))) - { - WorldPacket data; - MakeLeft(&data, p); - SendToAll(&data); - } - - LeaveNotify(p); - - if (changeowner) - { - uint64 newowner = !players.empty() ? players.begin()->second.player : 0; - players[newowner].SetModerator(true); - SetOwner(newowner); - } - } -} - -void Channel::KickOrBan(uint64 good, const char *badname, bool ban) -{ - AccountTypes sec = SEC_PLAYER; - Player *gplr = objmgr.GetPlayer(good); - if (gplr) - sec = gplr->GetSession()->GetSecurity(); - - if (!IsOn(good)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, good); - } - else if (!players[good].IsModerator() && sec < SEC_GAMEMASTER) - { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, good); - } - else - { - Player *bad = objmgr.GetPlayer(badname); - if (bad == NULL || !IsOn(bad->GetGUID())) - { - WorldPacket data; - MakePlayerNotFound(&data, badname); - SendToOne(&data, good); - } - else if (sec < SEC_GAMEMASTER && bad->GetGUID() == m_ownerGUID && good != m_ownerGUID) - { - WorldPacket data; - MakeNotOwner(&data); - SendToOne(&data, good); - } - else - { - bool changeowner = (m_ownerGUID == bad->GetGUID()); - - WorldPacket data; - - if (ban && !IsBanned(bad->GetGUID())) - { - banned.insert(bad->GetGUID()); - MakePlayerBanned(&data, bad->GetGUID(), good); - _UpdateBanListInDB(); - - } - else - MakePlayerKicked(&data, bad->GetGUID(), good); - - SendToAll(&data); - players.erase(bad->GetGUID()); - bad->LeftChannel(this); - - if (changeowner) - { - uint64 newowner = !players.empty() ? good : false; - players[newowner].SetModerator(true); - SetOwner(newowner); - } - } - } -} - -void Channel::UnBan(uint64 good, const char *badname) -{ - uint32 sec = 0; - Player *gplr = objmgr.GetPlayer(good); - if (gplr) - sec = gplr->GetSession()->GetSecurity(); - - if (!IsOn(good)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, good); - } - else if (!players[good].IsModerator() && sec < SEC_GAMEMASTER) - { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, good); - } - else - { - Player *bad = objmgr.GetPlayer(badname); - if (bad == NULL || !IsBanned(bad->GetGUID())) - { - WorldPacket data; - MakePlayerNotFound(&data, badname); - SendToOne(&data, good); - } - else - { - banned.erase(bad->GetGUID()); - - WorldPacket data; - MakePlayerUnbanned(&data, bad->GetGUID(), good); - SendToAll(&data); - //save banlist - _UpdateBanListInDB(); - } - } -} - -void Channel::Password(uint64 p, const char *pass) -{ - std::string plName; - uint32 sec = 0; - Player *plr = objmgr.GetPlayer(p); - if (plr) - sec = plr->GetSession()->GetSecurity(); - - ChatHandler chat(plr); - - if (!m_public && sec <= SEC_MODERATOR) - { - chat.PSendSysMessage(LANG_CHANNEL_NOT_PUBLIC); - return; - } - - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - } - else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) - { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, p); - } - else - { - m_password = pass; - - WorldPacket data; - MakePasswordChanged(&data, p); - SendToAll(&data); - if (m_IsSaved && _UpdateStringInDB("m_password", m_password)) - sLog.outDebug("Channel(%s) password saved", m_name.c_str()); - } -} - -void Channel::SetMode(uint64 p, const char *p2n, bool mod, bool set) -{ - Player *plr = objmgr.GetPlayer(p); - if (!plr) - return; - - uint32 sec = plr->GetSession()->GetSecurity(); - - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - } - else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) - { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, p); - } - else - { - Player *newp = objmgr.GetPlayer(p2n); - if (!newp) - { - WorldPacket data; - MakePlayerNotFound(&data, p2n); - SendToOne(&data, p); - return; - } - - if (p == m_ownerGUID && newp->GetGUID() == m_ownerGUID && mod) - return; - - if (!IsOn(newp->GetGUID())) - { - WorldPacket data; - MakePlayerNotFound(&data, p2n); - SendToOne(&data, p); - return; - } - - // allow make moderator from another team only if both is GMs - // at this moment this only way to show channel post for GM from another team - if ((plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || newp->GetSession()->GetSecurity() < SEC_GAMEMASTER) && - plr->GetTeam() != newp->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) - { - WorldPacket data; - MakePlayerNotFound(&data, p2n); - SendToOne(&data, p); - return; - } - - if (m_ownerGUID == newp->GetGUID() && m_ownerGUID != p) - { - WorldPacket data; - MakeNotOwner(&data); - SendToOne(&data, p); - return; - } - - if (mod) - SetModerator(newp->GetGUID(), set); - else - SetMute(newp->GetGUID(), set); - } -} - -void Channel::SetOwner(uint64 p, const char *newname) -{ - Player *plr = objmgr.GetPlayer(p); - if (!plr) - return; - - uint32 sec = plr->GetSession()->GetSecurity(); - - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - return; - } - - if (sec < SEC_GAMEMASTER && p != m_ownerGUID) - { - WorldPacket data; - MakeNotOwner(&data); - SendToOne(&data, p); - return; - } - - Player *newp = objmgr.GetPlayer(newname); - if (newp == NULL || !IsOn(newp->GetGUID())) - { - WorldPacket data; - MakePlayerNotFound(&data, newname); - SendToOne(&data, p); - return; - } - - if (newp->GetTeam() != plr->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) - { - WorldPacket data; - MakePlayerNotFound(&data, newname); - SendToOne(&data, p); - return; - } - - players[newp->GetGUID()].SetModerator(true); - SetOwner(newp->GetGUID()); -} - -void Channel::SendWhoOwner(uint64 p) -{ - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - } - else - { - WorldPacket data; - MakeChannelOwner(&data); - SendToOne(&data, p); - } -} - -void Channel::List(Player* player) -{ - uint64 p = player->GetGUID(); - - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - } - else - { - WorldPacket data(SMSG_CHANNEL_LIST, 1+(GetName().size()+1)+1+4+players.size()*(8+1)); - data << uint8(1); // channel type? - data << GetName(); // channel name - data << uint8(GetFlags()); // channel flags? - - size_t pos = data.wpos(); - data << uint32(0); // size of list, placeholder - - uint32 gmLevelInWhoList = sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); - - uint32 count = 0; - for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player *plr = objmgr.GetPlayer(i->first); - - // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters - // MODERATOR, GAME MASTER, ADMINISTRATOR can see all - if (plr && (player->GetSession()->GetSecurity() > SEC_PLAYER || plr->GetSession()->GetSecurity() <= gmLevelInWhoList) && - plr->IsVisibleGloballyFor(player)) - { - data << uint64(i->first); - data << uint8(i->second.flags); // flags seems to be changed... - ++count; - } - } - - data.put(pos,count); - - SendToOne(&data, p); - } -} - -void Channel::Announce(uint64 p) -{ - uint32 sec = 0; - Player *plr = objmgr.GetPlayer(p); - if (plr) - sec = plr->GetSession()->GetSecurity(); - - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - } - else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) - { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, p); - } - else - { - m_announce = !m_announce; - - WorldPacket data; - if (m_announce) - MakeAnnouncementsOn(&data, p); - else - MakeAnnouncementsOff(&data, p); - SendToAll(&data); - if (m_IsSaved && _UpdateIntInDB("m_announce", m_announce ? 1 : 0)) - sLog.outDebug("Channel(%s) announce saved", m_name.c_str()); - - } -} - -void Channel::Moderate(uint64 p) -{ - uint32 sec = 0; - Player *plr = objmgr.GetPlayer(p); - if (plr) - sec = plr->GetSession()->GetSecurity(); - - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - } - else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) - { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, p); - } - else - { - m_moderate = !m_moderate; - - WorldPacket data; - if (m_moderate) - MakeModerationOn(&data, p); - else - MakeModerationOff(&data, p); - SendToAll(&data); - if (m_IsSaved && _UpdateIntInDB("m_announce", m_announce ? 1 : 0)) - sLog.outDebug("Channel(%s) announce saved", m_name.c_str()); - } -} - -void Channel::Say(uint64 p, const char *what, uint32 lang) -{ - if (!what) - return; - if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) - lang = LANG_UNIVERSAL; - - uint32 sec = 0; - Player *plr = objmgr.GetPlayer(p); - if (plr) - sec = plr->GetSession()->GetSecurity(); - - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - } - else if (players[p].IsMuted()) - { - WorldPacket data; - MakeMuted(&data); - SendToOne(&data, p); - } - else if (m_moderate && !players[p].IsModerator() && sec < SEC_GAMEMASTER) - { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, p); - } - else - { - uint32 messageLength = strlen(what) + 1; - - WorldPacket data(SMSG_MESSAGECHAT, 1+4+8+4+m_name.size()+1+8+4+messageLength+1); - data << (uint8)CHAT_MSG_CHANNEL; - data << (uint32)lang; - data << p; // 2.1.0 - data << uint32(0); // 2.1.0 - data << m_name; - data << p; - data << messageLength; - data << what; - data << uint8(plr ? plr->chatTag() : 0); - - SendToAll(&data, !players[p].IsModerator() ? p : false); - } -} - -void Channel::Invite(uint64 p, const char *newname) -{ - if (!IsOn(p)) - { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, p); - return; - } - - Player *newp = objmgr.GetPlayer(newname); - if (!newp) - { - WorldPacket data; - MakePlayerNotFound(&data, newname); - SendToOne(&data, p); - return; - } - - Player *plr = objmgr.GetPlayer(p); - if (!plr) - return; - - if (newp->GetTeam() != plr->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) - { - WorldPacket data; - MakeInviteWrongFaction(&data); - SendToOne(&data, p); - return; - } - - if (IsOn(newp->GetGUID())) - { - WorldPacket data; - MakePlayerAlreadyMember(&data, newp->GetGUID()); - SendToOne(&data, p); - return; - } - - WorldPacket data; - if (!newp->GetSocial()->HasIgnore(GUID_LOPART(p))) - { - MakeInvite(&data, p); - SendToOne(&data, newp->GetGUID()); - data.clear(); - } - MakePlayerInvited(&data, newp->GetName()); - SendToOne(&data, p); -} - -void Channel::SetOwner(uint64 guid, bool exclaim) -{ - if (m_ownerGUID) - { - // [] will re-add player after it possible removed - PlayerList::iterator p_itr = players.find(m_ownerGUID); - if (p_itr != players.end()) - p_itr->second.SetOwner(false); - } - - m_ownerGUID = guid; - if (m_ownerGUID) - { - uint8 oldFlag = GetPlayerFlags(m_ownerGUID); - players[m_ownerGUID].SetModerator(true); - players[m_ownerGUID].SetOwner(true); - - WorldPacket data; - MakeModeChange(&data, m_ownerGUID, oldFlag); - SendToAll(&data); - - if (exclaim) - { - MakeOwnerChanged(&data, m_ownerGUID); - SendToAll(&data); - } - if (m_IsSaved && _UpdateIntInDB("m_moderate", m_moderate ? 1 : 0)) - sLog.outDebug("Channel(%s) moderate saved", m_name.c_str()); - - } -} - -void Channel::SendToAll(WorldPacket *data, uint64 p) -{ - for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player *plr = objmgr.GetPlayer(i->first); - if (plr) - { - if (!p || !plr->GetSocial()->HasIgnore(GUID_LOPART(p))) - plr->GetSession()->SendPacket(data); - } - } -} - -void Channel::SendToAllButOne(WorldPacket *data, uint64 who) -{ - for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - if (i->first != who) - { - Player *plr = objmgr.GetPlayer(i->first); - if (plr) - plr->GetSession()->SendPacket(data); - } - } -} - -void Channel::SendToOne(WorldPacket *data, uint64 who) -{ - Player *plr = objmgr.GetPlayer(who); - if (plr) - plr->GetSession()->SendPacket(data); -} - -void Channel::Voice(uint64 /*guid1*/, uint64 /*guid2*/) -{ - -} - -void Channel::DeVoice(uint64 /*guid1*/, uint64 /*guid2*/) -{ - -} - -// done -void Channel::MakeNotifyPacket(WorldPacket *data, uint8 notify_type) -{ - data->Initialize(SMSG_CHANNEL_NOTIFY, 1+m_name.size()+1); - *data << uint8(notify_type); - *data << m_name; -} - -// done 0x00 -void Channel::MakeJoined(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_JOINED_NOTICE); - *data << uint64(guid); -} - -// done 0x01 -void Channel::MakeLeft(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_LEFT_NOTICE); - *data << uint64(guid); -} - -// done 0x02 -void Channel::MakeYouJoined(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_YOU_JOINED_NOTICE); - *data << uint8(GetFlags()); - *data << uint32(GetChannelId()); - *data << uint32(0); -} - -// done 0x03 -void Channel::MakeYouLeft(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); - *data << uint32(GetChannelId()); - *data << uint8(0); // can be 0x00 and 0x01 -} - -// done 0x04 -void Channel::MakeWrongPassword(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_WRONG_PASSWORD_NOTICE); -} - -// done 0x05 -void Channel::MakeNotMember(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_NOT_MEMBER_NOTICE); -} - -// done 0x06 -void Channel::MakeNotModerator(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_NOT_MODERATOR_NOTICE); -} - -// done 0x07 -void Channel::MakePasswordChanged(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_PASSWORD_CHANGED_NOTICE); - *data << uint64(guid); -} - -// done 0x08 -void Channel::MakeOwnerChanged(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_OWNER_CHANGED_NOTICE); - *data << uint64(guid); -} - -// done 0x09 -void Channel::MakePlayerNotFound(WorldPacket *data, const std::string& name) -{ - MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE); - *data << name; -} - -// done 0x0A -void Channel::MakeNotOwner(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_NOT_OWNER_NOTICE); -} - -// done 0x0B -void Channel::MakeChannelOwner(WorldPacket *data) -{ - std::string name = ""; - - if (!objmgr.GetPlayerNameByGUID(m_ownerGUID, name) || name.empty()) - name = "PLAYER_NOT_FOUND"; - - MakeNotifyPacket(data, CHAT_CHANNEL_OWNER_NOTICE); - *data << ((IsConstant() || !m_ownerGUID) ? "Nobody" : name); -} - -// done 0x0C -void Channel::MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags) -{ - MakeNotifyPacket(data, CHAT_MODE_CHANGE_NOTICE); - *data << uint64(guid); - *data << uint8(oldflags); - *data << uint8(GetPlayerFlags(guid)); -} - -// done 0x0D -void Channel::MakeAnnouncementsOn(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_ON_NOTICE); - *data << uint64(guid); -} - -// done 0x0E -void Channel::MakeAnnouncementsOff(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_OFF_NOTICE); - *data << uint64(guid); -} - -// done 0x0F -void Channel::MakeModerationOn(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_MODERATION_ON_NOTICE); - *data << uint64(guid); -} - -// done 0x10 -void Channel::MakeModerationOff(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_MODERATION_OFF_NOTICE); - *data << uint64(guid); -} - -// done 0x11 -void Channel::MakeMuted(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_MUTED_NOTICE); -} - -// done 0x12 -void Channel::MakePlayerKicked(WorldPacket *data, uint64 bad, uint64 good) -{ - MakeNotifyPacket(data, CHAT_PLAYER_KICKED_NOTICE); - *data << uint64(bad); - *data << uint64(good); -} - -// done 0x13 -void Channel::MakeBanned(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_BANNED_NOTICE); -} - -// done 0x14 -void Channel::MakePlayerBanned(WorldPacket *data, uint64 bad, uint64 good) -{ - MakeNotifyPacket(data, CHAT_PLAYER_BANNED_NOTICE); - *data << uint64(bad); - *data << uint64(good); -} - -// done 0x15 -void Channel::MakePlayerUnbanned(WorldPacket *data, uint64 bad, uint64 good) -{ - MakeNotifyPacket(data, CHAT_PLAYER_UNBANNED_NOTICE); - *data << uint64(bad); - *data << uint64(good); -} - -// done 0x16 -void Channel::MakePlayerNotBanned(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_PLAYER_NOT_BANNED_NOTICE); - *data << uint64(guid); -} - -// done 0x17 -void Channel::MakePlayerAlreadyMember(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_PLAYER_ALREADY_MEMBER_NOTICE); - *data << uint64(guid); -} - -// done 0x18 -void Channel::MakeInvite(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_INVITE_NOTICE); - *data << uint64(guid); -} - -// done 0x19 -void Channel::MakeInviteWrongFaction(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_INVITE_WRONG_FACTION_NOTICE); -} - -// done 0x1A -void Channel::MakeWrongFaction(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_WRONG_FACTION_NOTICE); -} - -// done 0x1B -void Channel::MakeInvalidName(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_INVALID_NAME_NOTICE); -} - -// done 0x1C -void Channel::MakeNotModerated(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_NOT_MODERATED_NOTICE); -} - -// done 0x1D -void Channel::MakePlayerInvited(WorldPacket *data, const std::string& name) -{ - MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE); - *data << name; -} - -// done 0x1E -void Channel::MakePlayerInviteBanned(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_PLAYER_INVITE_BANNED_NOTICE); - *data << uint64(guid); -} - -// done 0x1F -void Channel::MakeThrottled(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_THROTTLED_NOTICE); -} - -// done 0x20 -void Channel::MakeNotInArea(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_NOT_IN_AREA_NOTICE); -} - -// done 0x21 -void Channel::MakeNotInLfg(WorldPacket *data) -{ - MakeNotifyPacket(data, CHAT_NOT_IN_LFG_NOTICE); -} - -// done 0x22 -void Channel::MakeVoiceOn(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_VOICE_ON_NOTICE); - *data << uint64(guid); -} - -// done 0x23 -void Channel::MakeVoiceOff(WorldPacket *data, uint64 guid) -{ - MakeNotifyPacket(data, CHAT_VOICE_OFF_NOTICE); - *data << uint64(guid); -} - -void Channel::JoinNotify(uint64 guid) -{ - WorldPacket data; - - if (IsConstant()) - data.Initialize(SMSG_USERLIST_ADD, 8+1+1+4+GetName().size()+1); - else - data.Initialize(SMSG_USERLIST_UPDATE, 8+1+1+4+GetName().size()+1); - - data << uint64(guid); - data << uint8(GetPlayerFlags(guid)); - data << uint8(GetFlags()); - data << uint32(GetNumPlayers()); - data << GetName(); - SendToAll(&data); -} - -void Channel::LeaveNotify(uint64 guid) -{ - WorldPacket data(SMSG_USERLIST_REMOVE, 8+1+4+GetName().size()+1); - data << uint64(guid); - data << uint8(GetFlags()); - data << uint32(GetNumPlayers()); - data << GetName(); - SendToAll(&data); -} - diff --git a/src/server/game/Chat/Channel.h b/src/server/game/Chat/Channel.h deleted file mode 100644 index d0b5923e30e..00000000000 --- a/src/server/game/Chat/Channel.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _CHANNEL_H -#define _CHANNEL_H - -#include -#include -#include - -#include "Common.h" - -#include "Opcodes.h" -#include "Player.h" -#include "WorldPacket.h" - -enum ChatNotify -{ - CHAT_JOINED_NOTICE = 0x00, //+ "%s joined channel."; - CHAT_LEFT_NOTICE = 0x01, //+ "%s left channel."; - //CHAT_SUSPENDED_NOTICE = 0x01, // "%s left channel."; - CHAT_YOU_JOINED_NOTICE = 0x02, //+ "Joined Channel: [%s]"; -- You joined - //CHAT_YOU_CHANGED_NOTICE = 0x02, // "Changed Channel: [%s]"; - CHAT_YOU_LEFT_NOTICE = 0x03, //+ "Left Channel: [%s]"; -- You left - CHAT_WRONG_PASSWORD_NOTICE = 0x04, //+ "Wrong password for %s."; - CHAT_NOT_MEMBER_NOTICE = 0x05, //+ "Not on channel %s."; - CHAT_NOT_MODERATOR_NOTICE = 0x06, //+ "Not a moderator of %s."; - CHAT_PASSWORD_CHANGED_NOTICE = 0x07, //+ "[%s] Password changed by %s."; - CHAT_OWNER_CHANGED_NOTICE = 0x08, //+ "[%s] Owner changed to %s."; - CHAT_PLAYER_NOT_FOUND_NOTICE = 0x09, //+ "[%s] Player %s was not found."; - CHAT_NOT_OWNER_NOTICE = 0x0A, //+ "[%s] You are not the channel owner."; - CHAT_CHANNEL_OWNER_NOTICE = 0x0B, //+ "[%s] Channel owner is %s."; - CHAT_MODE_CHANGE_NOTICE = 0x0C, //? - CHAT_ANNOUNCEMENTS_ON_NOTICE = 0x0D, //+ "[%s] Channel announcements enabled by %s."; - CHAT_ANNOUNCEMENTS_OFF_NOTICE = 0x0E, //+ "[%s] Channel announcements disabled by %s."; - CHAT_MODERATION_ON_NOTICE = 0x0F, //+ "[%s] Channel moderation enabled by %s."; - CHAT_MODERATION_OFF_NOTICE = 0x10, //+ "[%s] Channel moderation disabled by %s."; - CHAT_MUTED_NOTICE = 0x11, //+ "[%s] You do not have permission to speak."; - CHAT_PLAYER_KICKED_NOTICE = 0x12, //? "[%s] Player %s kicked by %s."; - CHAT_BANNED_NOTICE = 0x13, //+ "[%s] You are banned from that channel."; - CHAT_PLAYER_BANNED_NOTICE = 0x14, //? "[%s] Player %s banned by %s."; - CHAT_PLAYER_UNBANNED_NOTICE = 0x15, //? "[%s] Player %s unbanned by %s."; - CHAT_PLAYER_NOT_BANNED_NOTICE = 0x16, //+ "[%s] Player %s is not banned."; - CHAT_PLAYER_ALREADY_MEMBER_NOTICE = 0x17, //+ "[%s] Player %s is already on the channel."; - CHAT_INVITE_NOTICE = 0x18, //+ "%2$s has invited you to join the channel '%1$s'."; - CHAT_INVITE_WRONG_FACTION_NOTICE = 0x19, //+ "Target is in the wrong alliance for %s."; - CHAT_WRONG_FACTION_NOTICE = 0x1A, //+ "Wrong alliance for %s."; - CHAT_INVALID_NAME_NOTICE = 0x1B, //+ "Invalid channel name"; - CHAT_NOT_MODERATED_NOTICE = 0x1C, //+ "%s is not moderated"; - CHAT_PLAYER_INVITED_NOTICE = 0x1D, //+ "[%s] You invited %s to join the channel"; - CHAT_PLAYER_INVITE_BANNED_NOTICE = 0x1E, //+ "[%s] %s has been banned."; - CHAT_THROTTLED_NOTICE = 0x1F, //+ "[%s] The number of messages that can be sent to this channel is limited, please wait to send another message."; - CHAT_NOT_IN_AREA_NOTICE = 0x20, //+ "[%s] You are not in the correct area for this channel."; -- The user is trying to send a chat to a zone specific channel, and they're not physically in that zone. - CHAT_NOT_IN_LFG_NOTICE = 0x21, //+ "[%s] You must be queued in looking for group before joining this channel."; -- The user must be in the looking for group system to join LFG chat channels. - CHAT_VOICE_ON_NOTICE = 0x22, //+ "[%s] Channel voice enabled by %s."; - CHAT_VOICE_OFF_NOTICE = 0x23, //+ "[%s] Channel voice disabled by %s."; -}; - -enum ChannelFlags -{ - CHANNEL_FLAG_NONE = 0x00, - CHANNEL_FLAG_CUSTOM = 0x01, - // 0x02 - CHANNEL_FLAG_TRADE = 0x04, - CHANNEL_FLAG_NOT_LFG = 0x08, - CHANNEL_FLAG_GENERAL = 0x10, - CHANNEL_FLAG_CITY = 0x20, - CHANNEL_FLAG_LFG = 0x40, - CHANNEL_FLAG_VOICE = 0x80 - // General 0x18 = 0x10 | 0x08 - // Trade 0x3C = 0x20 | 0x10 | 0x08 | 0x04 - // LocalDefence 0x18 = 0x10 | 0x08 - // GuildRecruitment 0x38 = 0x20 | 0x10 | 0x08 - // LookingForGroup 0x50 = 0x40 | 0x10 -}; - -enum ChannelDBCFlags -{ - CHANNEL_DBC_FLAG_NONE = 0x00000, - CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG - CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment - CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense - CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade - CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment - CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment - CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense - CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment - CHANNEL_DBC_FLAG_LFG = 0x40000 // LookingForGroup -}; - -enum ChannelMemberFlags -{ - MEMBER_FLAG_NONE = 0x00, - MEMBER_FLAG_OWNER = 0x01, - MEMBER_FLAG_MODERATOR = 0x02, - MEMBER_FLAG_VOICED = 0x04, - MEMBER_FLAG_MUTED = 0x08, - MEMBER_FLAG_CUSTOM = 0x10, - MEMBER_FLAG_MIC_MUTED = 0x20, - // 0x40 - // 0x80 -}; - -class Channel -{ - struct PlayerInfo - { - uint64 player; - uint8 flags; - - bool HasFlag(uint8 flag) { return flags & flag; } - void SetFlag(uint8 flag) { if (!HasFlag(flag)) flags |= flag; } - bool IsOwner() { return flags & MEMBER_FLAG_OWNER; } - void SetOwner(bool state) - { - if (state) flags |= MEMBER_FLAG_OWNER; - else flags &= ~MEMBER_FLAG_OWNER; - } - bool IsModerator() { return flags & MEMBER_FLAG_MODERATOR; } - void SetModerator(bool state) - { - if (state) flags |= MEMBER_FLAG_MODERATOR; - else flags &= ~MEMBER_FLAG_MODERATOR; - } - bool IsMuted() { return flags & MEMBER_FLAG_MUTED; } - void SetMuted(bool state) - { - if (state) flags |= MEMBER_FLAG_MUTED; - else flags &= ~MEMBER_FLAG_MUTED; - } - }; - - typedef std::map PlayerList; - PlayerList players; - typedef std::set BannedList; - BannedList banned; - bool m_announce; - bool m_moderate; - bool m_public; - std::string m_name; - std::string m_password; - uint8 m_flags; - uint32 m_channelId; - uint64 m_ownerGUID; - bool m_IsSaved; - - private: - // initial packet data (notify type and channel name) - void MakeNotifyPacket(WorldPacket *data, uint8 notify_type); - // type specific packet data - void MakeJoined(WorldPacket *data, uint64 guid); //+ 0x00 - void MakeLeft(WorldPacket *data, uint64 guid); //+ 0x01 - void MakeYouJoined(WorldPacket *data); //+ 0x02 - void MakeYouLeft(WorldPacket *data); //+ 0x03 - void MakeWrongPassword(WorldPacket *data); //? 0x04 - void MakeNotMember(WorldPacket *data); //? 0x05 - void MakeNotModerator(WorldPacket *data); //? 0x06 - void MakePasswordChanged(WorldPacket *data, uint64 guid); //+ 0x07 - void MakeOwnerChanged(WorldPacket *data, uint64 guid); //? 0x08 - void MakePlayerNotFound(WorldPacket *data, const std::string& name); //+ 0x09 - void MakeNotOwner(WorldPacket *data); //? 0x0A - void MakeChannelOwner(WorldPacket *data); //? 0x0B - void MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags); //+ 0x0C - void MakeAnnouncementsOn(WorldPacket *data, uint64 guid); //+ 0x0D - void MakeAnnouncementsOff(WorldPacket *data, uint64 guid); //+ 0x0E - void MakeModerationOn(WorldPacket *data, uint64 guid); //+ 0x0F - void MakeModerationOff(WorldPacket *data, uint64 guid); //+ 0x10 - void MakeMuted(WorldPacket *data); //? 0x11 - void MakePlayerKicked(WorldPacket *data, uint64 bad, uint64 good); //? 0x12 - void MakeBanned(WorldPacket *data); //? 0x13 - void MakePlayerBanned(WorldPacket *data, uint64 bad, uint64 good); //? 0x14 - void MakePlayerUnbanned(WorldPacket *data, uint64 bad, uint64 good); //? 0x15 - void MakePlayerNotBanned(WorldPacket *data, uint64 guid); //? 0x16 - void MakePlayerAlreadyMember(WorldPacket *data, uint64 guid); //+ 0x17 - void MakeInvite(WorldPacket *data, uint64 guid); //? 0x18 - void MakeInviteWrongFaction(WorldPacket *data); //? 0x19 - void MakeWrongFaction(WorldPacket *data); //? 0x1A - void MakeInvalidName(WorldPacket *data); //? 0x1B - void MakeNotModerated(WorldPacket *data); //? 0x1C - void MakePlayerInvited(WorldPacket *data, const std::string& name); //+ 0x1D - void MakePlayerInviteBanned(WorldPacket *data, uint64 guid); //? 0x1E - void MakeThrottled(WorldPacket *data); //? 0x1F - void MakeNotInArea(WorldPacket *data); //? 0x20 - void MakeNotInLfg(WorldPacket *data); //? 0x21 - void MakeVoiceOn(WorldPacket *data, uint64 guid); //+ 0x22 - void MakeVoiceOff(WorldPacket *data, uint64 guid); //+ 0x23 - - void SendToAll(WorldPacket *data, uint64 p = 0); - void SendToAllButOne(WorldPacket *data, uint64 who); - void SendToOne(WorldPacket *data, uint64 who); - - bool IsOn(uint64 who) const { return players.find(who) != players.end(); } - bool IsBanned(uint64 guid) const { return banned.find(guid) != banned.end(); } - - bool _UpdateStringInDB(const std::string& colName, const std::string& colValue) const; - bool _UpdateIntInDB(const std::string& colName, int colValue) const; - void _UpdateBanListInDB() const; - - uint8 GetPlayerFlags(uint64 p) const - { - PlayerList::const_iterator p_itr = players.find(p); - if (p_itr == players.end()) - return 0; - - return p_itr->second.flags; - } - - void SetModerator(uint64 p, bool set) - { - if (players[p].IsModerator() != set) - { - uint8 oldFlag = GetPlayerFlags(p); - players[p].SetModerator(set); - - WorldPacket data; - MakeModeChange(&data, p, oldFlag); - SendToAll(&data); - } - } - - void SetMute(uint64 p, bool set) - { - if (players[p].IsMuted() != set) - { - uint8 oldFlag = GetPlayerFlags(p); - players[p].SetMuted(set); - - WorldPacket data; - MakeModeChange(&data, p, oldFlag); - SendToAll(&data); - } - } - - public: - uint32 m_Team; - Channel(const std::string& name, uint32 channel_id, uint32 Team = 0); - std::string GetName() const { return m_name; } - uint32 GetChannelId() const { return m_channelId; } - bool IsConstant() const { return m_channelId != 0; } - bool IsAnnounce() const { return m_announce; } - bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; } - std::string GetPassword() const { return m_password; } - void SetPassword(const std::string& npassword) { m_password = npassword; } - void SetAnnounce(bool nannounce) { m_announce = nannounce; } - uint32 GetNumPlayers() const { return players.size(); } - uint8 GetFlags() const { return m_flags; } - bool HasFlag(uint8 flag) { return m_flags & flag; } - - void Join(uint64 p, const char *pass); - void Leave(uint64 p, bool send = true); - void KickOrBan(uint64 good, const char *badname, bool ban); - void Kick(uint64 good, const char *badname) { KickOrBan(good, badname, false); } - void Ban(uint64 good, const char *badname) { KickOrBan(good, badname, true); } - void UnBan(uint64 good, const char *badname); - void Password(uint64 p, const char *pass); - void SetMode(uint64 p, const char *p2n, bool mod, bool set); - void SetOwner(uint64 p, bool exclaim = true); - void SetOwner(uint64 p, const char *newname); - void SendWhoOwner(uint64 p); - void SetModerator(uint64 p, const char *newname) { SetMode(p, newname, true, true); } - void UnsetModerator(uint64 p, const char *newname) { SetMode(p, newname, true, false); } - void SetMute(uint64 p, const char *newname) { SetMode(p, newname, false, true); } - void UnsetMute(uint64 p, const char *newname) { SetMode(p, newname, false, false); } - void List(Player* p); - void Announce(uint64 p); - void Moderate(uint64 p); - void Say(uint64 p, const char *what, uint32 lang); - void Invite(uint64 p, const char *newp); - void Voice(uint64 guid1, uint64 guid2); - void DeVoice(uint64 guid1, uint64 guid2); - void JoinNotify(uint64 guid); // invisible notify - void LeaveNotify(uint64 guid); // invisible notify -}; -#endif - diff --git a/src/server/game/Chat/ChannelHandler.cpp b/src/server/game/Chat/ChannelHandler.cpp deleted file mode 100644 index 0f615579cb6..00000000000 --- a/src/server/game/Chat/ChannelHandler.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Policies/SingletonImp.h" - -#include "ObjectMgr.h" // for normalizePlayerName -#include "ChannelMgr.h" - -void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - - uint32 channel_id; - uint8 unknown1, unknown2; - std::string channelname, pass; - - recvPacket >> channel_id >> unknown1 >> unknown2; - recvPacket >> channelname; - - if (channelname.empty()) - return; - - recvPacket >> pass; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - { - cMgr->team = _player->GetTeam(); - if (Channel *chn = cMgr->GetJoinChannel(channelname, channel_id)) - chn->Join(_player->GetGUID(), pass.c_str()); - } -} - -void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - - uint32 unk; - std::string channelname; - recvPacket >> unk; // channel id? - recvPacket >> channelname; - - if (channelname.empty()) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - { - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->Leave(_player->GetGUID(), true); - cMgr->LeftChannel(channelname); - } -} - -void WorldSession::HandleChannelList(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname; - recvPacket >> channelname; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->List(_player); -} - -void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname, pass; - recvPacket >> channelname; - - recvPacket >> pass; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->Password(_player->GetGUID(), pass.c_str()); -} - -void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname, newp; - recvPacket >> channelname; - - recvPacket >> newp; - - if (!normalizePlayerName(newp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->SetOwner(_player->GetGUID(), newp.c_str()); -} - -void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname; - recvPacket >> channelname; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->SendWhoOwner(_player->GetGUID()); -} - -void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->SetModerator(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->UnsetModerator(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelMute(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->SetMute(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->UnsetMute(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->Invite(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelKick(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->Kick(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelBan(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->Ban(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - - std::string channelname, otp; - recvPacket >> channelname; - - recvPacket >> otp; - - if (!normalizePlayerName(otp)) - return; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->UnBan(_player->GetGUID(), otp.c_str()); -} - -void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname; - recvPacket >> channelname; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->Announce(_player->GetGUID()); -} - -void WorldSession::HandleChannelModerate(WorldPacket& recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname; - recvPacket >> channelname; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->Moderate(_player->GetGUID()); -} - -void WorldSession::HandleChannelDisplayListQuery(WorldPacket &recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname; - recvPacket >> channelname; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->List(_player); -} - -void WorldSession::HandleGetChannelMemberCount(WorldPacket &recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname; - recvPacket >> channelname; - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - { - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - { - WorldPacket data(SMSG_CHANNEL_MEMBER_COUNT, chn->GetName().size()+1+1+4); - data << chn->GetName(); - data << uint8(chn->GetFlags()); - data << uint32(chn->GetNumPlayers()); - SendPacket(&data); - } - } -} - -void WorldSession::HandleSetChannelWatch(WorldPacket &recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); - //recvPacket.hexlike(); - std::string channelname; - recvPacket >> channelname; - /*if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - if (Channel *chn = cMgr->GetChannel(channelname, _player)) - chn->JoinNotify(_player->GetGUID());*/ -} - diff --git a/src/server/game/Chat/ChannelMgr.cpp b/src/server/game/Chat/ChannelMgr.cpp deleted file mode 100644 index f31d3ffde50..00000000000 --- a/src/server/game/Chat/ChannelMgr.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ChannelMgr.h" -#include "Policies/SingletonImp.h" -#include "World.h" - -INSTANTIATE_SINGLETON_1(AllianceChannelMgr); -INSTANTIATE_SINGLETON_1(HordeChannelMgr); - -ChannelMgr* channelMgr(uint32 team) -{ - if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) - return &Trinity::Singleton::Instance(); // cross-faction - - if (team == ALLIANCE) - return &Trinity::Singleton::Instance(); - if (team == HORDE) - return &Trinity::Singleton::Instance(); - - return NULL; -} - -ChannelMgr::~ChannelMgr() -{ - for (ChannelMap::iterator itr = channels.begin(); itr != channels.end(); ++itr) - delete itr->second; - - channels.clear(); -} - -Channel *ChannelMgr::GetJoinChannel(std::string name, uint32 channel_id) -{ - std::wstring wname; - Utf8toWStr(name,wname); - wstrToLower(wname); - - if (channels.find(wname) == channels.end()) - { - Channel *nchan = new Channel(name,channel_id, team); - channels[wname] = nchan; - return nchan; - } - - return channels[wname]; -} - -Channel *ChannelMgr::GetChannel(std::string name, Player *p, bool pkt) -{ - std::wstring wname; - Utf8toWStr(name,wname); - wstrToLower(wname); - - ChannelMap::const_iterator i = channels.find(wname); - - if (i == channels.end()) - { - if (pkt) - { - WorldPacket data; - MakeNotOnPacket(&data,name); - p->GetSession()->SendPacket(&data); - } - - return NULL; - } - else - return i->second; -} - -void ChannelMgr::LeftChannel(std::string name) -{ - std::wstring wname; - Utf8toWStr(name,wname); - wstrToLower(wname); - - ChannelMap::const_iterator i = channels.find(wname); - - if (i == channels.end()) - return; - - Channel* channel = i->second; - - if (channel->GetNumPlayers() == 0 && !channel->IsConstant()) - { - channels.erase(wname); - delete channel; - } -} - -void ChannelMgr::MakeNotOnPacket(WorldPacket *data, std::string name) -{ - data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size - (*data) << (uint8)0x05 << name; -} diff --git a/src/server/game/Chat/ChannelMgr.h b/src/server/game/Chat/ChannelMgr.h deleted file mode 100644 index 6f3b7c415ae..00000000000 --- a/src/server/game/Chat/ChannelMgr.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __TRINITY_CHANNELMGR_H -#define __TRINITY_CHANNELMGR_H - -#include "Common.h" -#include "Channel.h" -#include "Policies/Singleton.h" - -#include -#include - -#include "Policies/Singleton.h" - -#include "Channel.h" -#include "World.h" - -class ChannelMgr -{ - public: - uint32 team; - typedef std::map ChannelMap; - ChannelMgr() {team = 0;} - ~ChannelMgr(); - - Channel *GetJoinChannel(std::string name, uint32 channel_id); - Channel *GetChannel(std::string name, Player *p, bool pkt = true); - void LeftChannel(std::string name); - private: - ChannelMap channels; - void MakeNotOnPacket(WorldPacket *data, std::string name); -}; - -class AllianceChannelMgr : public ChannelMgr {}; -class HordeChannelMgr : public ChannelMgr {}; - -ChannelMgr* channelMgr(uint32 team); - -#endif - diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp new file mode 100644 index 00000000000..0047892972b --- /dev/null +++ b/src/server/game/Chat/Channels/Channel.cpp @@ -0,0 +1,1102 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Channel.h" +#include "Chat.h" +#include "ObjectMgr.h" +#include "SocialMgr.h" +#include "World.h" + +Channel::Channel(const std::string& name, uint32 channel_id, uint32 Team) + : m_name(name), m_announce(true), m_moderate(false), m_channelId(channel_id), m_ownerGUID(0), m_password(""), m_flags(0), m_Team(Team) +{ + // set special flags if built-in channel + ChatChannelsEntry const* ch = GetChannelEntryFor(channel_id); + if (ch) // it's built-in channel + { + channel_id = ch->ChannelID; // built-in channel + m_announce = false; // no join/leave announces + + m_flags |= CHANNEL_FLAG_GENERAL; // for all built-in channels + + if (ch->flags & CHANNEL_DBC_FLAG_TRADE) // for trade channel + m_flags |= CHANNEL_FLAG_TRADE; + + if (ch->flags & CHANNEL_DBC_FLAG_CITY_ONLY2) // for city only channels + m_flags |= CHANNEL_FLAG_CITY; + + if (ch->flags & CHANNEL_DBC_FLAG_LFG) // for LFG channel + m_flags |= CHANNEL_FLAG_LFG; + else // for all other channels + m_flags |= CHANNEL_FLAG_NOT_LFG; + m_IsSaved = false; + } + else // it's custom channel + { + m_flags |= CHANNEL_FLAG_CUSTOM; + //load not built in channel if saved + std::string _name(name); + CharacterDatabase.escape_string(_name); + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT m_announce, m_moderate, m_public, m_password, BannedList FROM channels WHERE m_name = '%s' AND m_team = '%u'", _name.c_str(), m_Team); + if (result)//load + { + Field *fields = result->Fetch(); + m_announce = fields[0].GetBool(); + m_moderate = fields[1].GetBool(); + m_public = fields[2].GetBool(); + m_password = fields[3].GetString(); + const char* db_BannedList = fields[4].GetString(); + + m_IsSaved = true; + + if (db_BannedList) + { + Tokens tokens = StrSplit(db_BannedList, " "); + Tokens::iterator iter; + for (iter = tokens.begin(); iter != tokens.end(); ++iter) + { + uint64 banned_guid = atol((*iter).c_str()); + if (banned_guid) + { + sLog.outDebug("Channel(%s) loaded banned guid: %u",name.c_str(), banned_guid); + banned.insert(banned_guid); + } + } + } + } + else // save + { + // _name is already escaped at this point. + if (CharacterDatabase.PExecute("INSERT INTO channels (m_name, m_team, m_announce, m_moderate, m_public, m_password) " + "VALUES ('%s', '%u', '1', '0', '1', '')", _name.c_str(), m_Team)) + { + sLog.outDebug("New Channel(%s) saved", name.c_str()); + m_IsSaved = true; + } + } + } +} + +bool Channel::_UpdateStringInDB(const std::string& colName, const std::string& colValue) const +{ + // Prevent SQL-injection + std::string _name(m_name); + std::string _colValue(colValue); + CharacterDatabase.escape_string(_colValue); + CharacterDatabase.escape_string(_name); + return CharacterDatabase.PExecute("UPDATE channels SET %s = '%s' WHERE m_name = '%s' AND m_team = '%u'", + colName.c_str(), _colValue.c_str(), _name.c_str(), m_Team); +} + +bool Channel::_UpdateIntInDB(const std::string& colName, int colValue) const +{ + // Prevent SQL-injection + std::string _name(m_name); + CharacterDatabase.escape_string(_name); + return CharacterDatabase.PExecute("UPDATE channels SET %s = '%u' WHERE m_name = '%s' AND m_team = '%u'", + colName.c_str(), colValue, _name.c_str(), m_Team); +} + +void Channel::_UpdateBanListInDB() const +{ + // save banlist + if (m_IsSaved) + { + std::ostringstream banlist; + BannedList::const_iterator iter; + for (iter = banned.begin(); iter != banned.end(); ++iter) + banlist << (*iter) << " "; + std::string banListStr = banlist.str(); + if (_UpdateStringInDB("BannedList", banListStr)) + sLog.outDebug("Channel(%s) BannedList saved", m_name.c_str()); + } +} + +void Channel::Join(uint64 p, const char *pass) +{ + WorldPacket data; + if (IsOn(p)) + { + if (!IsConstant()) // non send error message for built-in channels + { + MakePlayerAlreadyMember(&data, p); + SendToOne(&data, p); + } + return; + } + + if (IsBanned(p)) + { + MakeBanned(&data); + SendToOne(&data, p); + return; + } + + if (m_password.length() > 0 && strcmp(pass, m_password.c_str())) + { + MakeWrongPassword(&data); + SendToOne(&data, p); + return; + } + + Player *plr = objmgr.GetPlayer(p); + + if (plr) + { + if (HasFlag(CHANNEL_FLAG_LFG) && + sWorld.getConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER && plr->GetGroup()) + { + MakeNotInLfg(&data); + SendToOne(&data, p); + return; + } + + if (plr->GetGuildId() && (GetFlags() == 0x38)) + return; + + plr->JoinedChannel(this); + } + + if (m_announce && (!plr || plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || !sWorld.getConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL))) + { + MakeJoined(&data, p); + SendToAll(&data); + } + + data.clear(); + + PlayerInfo pinfo; + pinfo.player = p; + pinfo.flags = MEMBER_FLAG_NONE; + players[p] = pinfo; + + MakeYouJoined(&data); + SendToOne(&data, p); + + JoinNotify(p); + + // if no owner first logged will become + if (!IsConstant() && !m_ownerGUID) + { + SetOwner(p, (players.size() > 1 ? true : false)); + players[p].SetModerator(true); + } + /* + else if (!IsConstant() && m_ownerGUID && plr && m_ownerGUID == plr->GetGUID())) + { + SetOwner(p, (players.size() > 1 ? true : false)); + players[p].SetModerator(true); + }*/ +} + +void Channel::Leave(uint64 p, bool send) +{ + if (!IsOn(p)) + { + if (send) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + } + else + { + Player *plr = objmgr.GetPlayer(p); + + if (send) + { + WorldPacket data; + MakeYouLeft(&data); + SendToOne(&data, p); + if (plr) + plr->LeftChannel(this); + data.clear(); + } + + bool changeowner = players[p].IsOwner(); + + players.erase(p); + if (m_announce && (!plr || plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || !sWorld.getConfig(CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL))) + { + WorldPacket data; + MakeLeft(&data, p); + SendToAll(&data); + } + + LeaveNotify(p); + + if (changeowner) + { + uint64 newowner = !players.empty() ? players.begin()->second.player : 0; + players[newowner].SetModerator(true); + SetOwner(newowner); + } + } +} + +void Channel::KickOrBan(uint64 good, const char *badname, bool ban) +{ + AccountTypes sec = SEC_PLAYER; + Player *gplr = objmgr.GetPlayer(good); + if (gplr) + sec = gplr->GetSession()->GetSecurity(); + + if (!IsOn(good)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, good); + } + else if (!players[good].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, good); + } + else + { + Player *bad = objmgr.GetPlayer(badname); + if (bad == NULL || !IsOn(bad->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, badname); + SendToOne(&data, good); + } + else if (sec < SEC_GAMEMASTER && bad->GetGUID() == m_ownerGUID && good != m_ownerGUID) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, good); + } + else + { + bool changeowner = (m_ownerGUID == bad->GetGUID()); + + WorldPacket data; + + if (ban && !IsBanned(bad->GetGUID())) + { + banned.insert(bad->GetGUID()); + MakePlayerBanned(&data, bad->GetGUID(), good); + _UpdateBanListInDB(); + + } + else + MakePlayerKicked(&data, bad->GetGUID(), good); + + SendToAll(&data); + players.erase(bad->GetGUID()); + bad->LeftChannel(this); + + if (changeowner) + { + uint64 newowner = !players.empty() ? good : false; + players[newowner].SetModerator(true); + SetOwner(newowner); + } + } + } +} + +void Channel::UnBan(uint64 good, const char *badname) +{ + uint32 sec = 0; + Player *gplr = objmgr.GetPlayer(good); + if (gplr) + sec = gplr->GetSession()->GetSecurity(); + + if (!IsOn(good)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, good); + } + else if (!players[good].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, good); + } + else + { + Player *bad = objmgr.GetPlayer(badname); + if (bad == NULL || !IsBanned(bad->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, badname); + SendToOne(&data, good); + } + else + { + banned.erase(bad->GetGUID()); + + WorldPacket data; + MakePlayerUnbanned(&data, bad->GetGUID(), good); + SendToAll(&data); + //save banlist + _UpdateBanListInDB(); + } + } +} + +void Channel::Password(uint64 p, const char *pass) +{ + std::string plName; + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if (plr) + sec = plr->GetSession()->GetSecurity(); + + ChatHandler chat(plr); + + if (!m_public && sec <= SEC_MODERATOR) + { + chat.PSendSysMessage(LANG_CHANNEL_NOT_PUBLIC); + return; + } + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_password = pass; + + WorldPacket data; + MakePasswordChanged(&data, p); + SendToAll(&data); + if (m_IsSaved && _UpdateStringInDB("m_password", m_password)) + sLog.outDebug("Channel(%s) password saved", m_name.c_str()); + } +} + +void Channel::SetMode(uint64 p, const char *p2n, bool mod, bool set) +{ + Player *plr = objmgr.GetPlayer(p); + if (!plr) + return; + + uint32 sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + Player *newp = objmgr.GetPlayer(p2n); + if (!newp) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + if (p == m_ownerGUID && newp->GetGUID() == m_ownerGUID && mod) + return; + + if (!IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + // allow make moderator from another team only if both is GMs + // at this moment this only way to show channel post for GM from another team + if ((plr->GetSession()->GetSecurity() < SEC_GAMEMASTER || newp->GetSession()->GetSecurity() < SEC_GAMEMASTER) && + plr->GetTeam() != newp->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + { + WorldPacket data; + MakePlayerNotFound(&data, p2n); + SendToOne(&data, p); + return; + } + + if (m_ownerGUID == newp->GetGUID() && m_ownerGUID != p) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, p); + return; + } + + if (mod) + SetModerator(newp->GetGUID(), set); + else + SetMute(newp->GetGUID(), set); + } +} + +void Channel::SetOwner(uint64 p, const char *newname) +{ + Player *plr = objmgr.GetPlayer(p); + if (!plr) + return; + + uint32 sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + return; + } + + if (sec < SEC_GAMEMASTER && p != m_ownerGUID) + { + WorldPacket data; + MakeNotOwner(&data); + SendToOne(&data, p); + return; + } + + Player *newp = objmgr.GetPlayer(newname); + if (newp == NULL || !IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + if (newp->GetTeam() != plr->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + players[newp->GetGUID()].SetModerator(true); + SetOwner(newp->GetGUID()); +} + +void Channel::SendWhoOwner(uint64 p) +{ + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else + { + WorldPacket data; + MakeChannelOwner(&data); + SendToOne(&data, p); + } +} + +void Channel::List(Player* player) +{ + uint64 p = player->GetGUID(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else + { + WorldPacket data(SMSG_CHANNEL_LIST, 1+(GetName().size()+1)+1+4+players.size()*(8+1)); + data << uint8(1); // channel type? + data << GetName(); // channel name + data << uint8(GetFlags()); // channel flags? + + size_t pos = data.wpos(); + data << uint32(0); // size of list, placeholder + + uint32 gmLevelInWhoList = sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); + + uint32 count = 0; + for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player *plr = objmgr.GetPlayer(i->first); + + // PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters + // MODERATOR, GAME MASTER, ADMINISTRATOR can see all + if (plr && (player->GetSession()->GetSecurity() > SEC_PLAYER || plr->GetSession()->GetSecurity() <= gmLevelInWhoList) && + plr->IsVisibleGloballyFor(player)) + { + data << uint64(i->first); + data << uint8(i->second.flags); // flags seems to be changed... + ++count; + } + } + + data.put(pos,count); + + SendToOne(&data, p); + } +} + +void Channel::Announce(uint64 p) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if (plr) + sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_announce = !m_announce; + + WorldPacket data; + if (m_announce) + MakeAnnouncementsOn(&data, p); + else + MakeAnnouncementsOff(&data, p); + SendToAll(&data); + if (m_IsSaved && _UpdateIntInDB("m_announce", m_announce ? 1 : 0)) + sLog.outDebug("Channel(%s) announce saved", m_name.c_str()); + + } +} + +void Channel::Moderate(uint64 p) +{ + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if (plr) + sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (!players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + m_moderate = !m_moderate; + + WorldPacket data; + if (m_moderate) + MakeModerationOn(&data, p); + else + MakeModerationOff(&data, p); + SendToAll(&data); + if (m_IsSaved && _UpdateIntInDB("m_announce", m_announce ? 1 : 0)) + sLog.outDebug("Channel(%s) announce saved", m_name.c_str()); + } +} + +void Channel::Say(uint64 p, const char *what, uint32 lang) +{ + if (!what) + return; + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + lang = LANG_UNIVERSAL; + + uint32 sec = 0; + Player *plr = objmgr.GetPlayer(p); + if (plr) + sec = plr->GetSession()->GetSecurity(); + + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + } + else if (players[p].IsMuted()) + { + WorldPacket data; + MakeMuted(&data); + SendToOne(&data, p); + } + else if (m_moderate && !players[p].IsModerator() && sec < SEC_GAMEMASTER) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, p); + } + else + { + uint32 messageLength = strlen(what) + 1; + + WorldPacket data(SMSG_MESSAGECHAT, 1+4+8+4+m_name.size()+1+8+4+messageLength+1); + data << (uint8)CHAT_MSG_CHANNEL; + data << (uint32)lang; + data << p; // 2.1.0 + data << uint32(0); // 2.1.0 + data << m_name; + data << p; + data << messageLength; + data << what; + data << uint8(plr ? plr->chatTag() : 0); + + SendToAll(&data, !players[p].IsModerator() ? p : false); + } +} + +void Channel::Invite(uint64 p, const char *newname) +{ + if (!IsOn(p)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, p); + return; + } + + Player *newp = objmgr.GetPlayer(newname); + if (!newp) + { + WorldPacket data; + MakePlayerNotFound(&data, newname); + SendToOne(&data, p); + return; + } + + Player *plr = objmgr.GetPlayer(p); + if (!plr) + return; + + if (newp->GetTeam() != plr->GetTeam() && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + { + WorldPacket data; + MakeInviteWrongFaction(&data); + SendToOne(&data, p); + return; + } + + if (IsOn(newp->GetGUID())) + { + WorldPacket data; + MakePlayerAlreadyMember(&data, newp->GetGUID()); + SendToOne(&data, p); + return; + } + + WorldPacket data; + if (!newp->GetSocial()->HasIgnore(GUID_LOPART(p))) + { + MakeInvite(&data, p); + SendToOne(&data, newp->GetGUID()); + data.clear(); + } + MakePlayerInvited(&data, newp->GetName()); + SendToOne(&data, p); +} + +void Channel::SetOwner(uint64 guid, bool exclaim) +{ + if (m_ownerGUID) + { + // [] will re-add player after it possible removed + PlayerList::iterator p_itr = players.find(m_ownerGUID); + if (p_itr != players.end()) + p_itr->second.SetOwner(false); + } + + m_ownerGUID = guid; + if (m_ownerGUID) + { + uint8 oldFlag = GetPlayerFlags(m_ownerGUID); + players[m_ownerGUID].SetModerator(true); + players[m_ownerGUID].SetOwner(true); + + WorldPacket data; + MakeModeChange(&data, m_ownerGUID, oldFlag); + SendToAll(&data); + + if (exclaim) + { + MakeOwnerChanged(&data, m_ownerGUID); + SendToAll(&data); + } + if (m_IsSaved && _UpdateIntInDB("m_moderate", m_moderate ? 1 : 0)) + sLog.outDebug("Channel(%s) moderate saved", m_name.c_str()); + + } +} + +void Channel::SendToAll(WorldPacket *data, uint64 p) +{ + for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player *plr = objmgr.GetPlayer(i->first); + if (plr) + { + if (!p || !plr->GetSocial()->HasIgnore(GUID_LOPART(p))) + plr->GetSession()->SendPacket(data); + } + } +} + +void Channel::SendToAllButOne(WorldPacket *data, uint64 who) +{ + for (PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + if (i->first != who) + { + Player *plr = objmgr.GetPlayer(i->first); + if (plr) + plr->GetSession()->SendPacket(data); + } + } +} + +void Channel::SendToOne(WorldPacket *data, uint64 who) +{ + Player *plr = objmgr.GetPlayer(who); + if (plr) + plr->GetSession()->SendPacket(data); +} + +void Channel::Voice(uint64 /*guid1*/, uint64 /*guid2*/) +{ + +} + +void Channel::DeVoice(uint64 /*guid1*/, uint64 /*guid2*/) +{ + +} + +// done +void Channel::MakeNotifyPacket(WorldPacket *data, uint8 notify_type) +{ + data->Initialize(SMSG_CHANNEL_NOTIFY, 1+m_name.size()+1); + *data << uint8(notify_type); + *data << m_name; +} + +// done 0x00 +void Channel::MakeJoined(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_JOINED_NOTICE); + *data << uint64(guid); +} + +// done 0x01 +void Channel::MakeLeft(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_LEFT_NOTICE); + *data << uint64(guid); +} + +// done 0x02 +void Channel::MakeYouJoined(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_YOU_JOINED_NOTICE); + *data << uint8(GetFlags()); + *data << uint32(GetChannelId()); + *data << uint32(0); +} + +// done 0x03 +void Channel::MakeYouLeft(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); + *data << uint32(GetChannelId()); + *data << uint8(0); // can be 0x00 and 0x01 +} + +// done 0x04 +void Channel::MakeWrongPassword(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_WRONG_PASSWORD_NOTICE); +} + +// done 0x05 +void Channel::MakeNotMember(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MEMBER_NOTICE); +} + +// done 0x06 +void Channel::MakeNotModerator(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MODERATOR_NOTICE); +} + +// done 0x07 +void Channel::MakePasswordChanged(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PASSWORD_CHANGED_NOTICE); + *data << uint64(guid); +} + +// done 0x08 +void Channel::MakeOwnerChanged(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_OWNER_CHANGED_NOTICE); + *data << uint64(guid); +} + +// done 0x09 +void Channel::MakePlayerNotFound(WorldPacket *data, const std::string& name) +{ + MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE); + *data << name; +} + +// done 0x0A +void Channel::MakeNotOwner(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_OWNER_NOTICE); +} + +// done 0x0B +void Channel::MakeChannelOwner(WorldPacket *data) +{ + std::string name = ""; + + if (!objmgr.GetPlayerNameByGUID(m_ownerGUID, name) || name.empty()) + name = "PLAYER_NOT_FOUND"; + + MakeNotifyPacket(data, CHAT_CHANNEL_OWNER_NOTICE); + *data << ((IsConstant() || !m_ownerGUID) ? "Nobody" : name); +} + +// done 0x0C +void Channel::MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags) +{ + MakeNotifyPacket(data, CHAT_MODE_CHANGE_NOTICE); + *data << uint64(guid); + *data << uint8(oldflags); + *data << uint8(GetPlayerFlags(guid)); +} + +// done 0x0D +void Channel::MakeAnnouncementsOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x0E +void Channel::MakeAnnouncementsOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_OFF_NOTICE); + *data << uint64(guid); +} + +// done 0x0F +void Channel::MakeModerationOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_MODERATION_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x10 +void Channel::MakeModerationOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_MODERATION_OFF_NOTICE); + *data << uint64(guid); +} + +// done 0x11 +void Channel::MakeMuted(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_MUTED_NOTICE); +} + +// done 0x12 +void Channel::MakePlayerKicked(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_KICKED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x13 +void Channel::MakeBanned(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_BANNED_NOTICE); +} + +// done 0x14 +void Channel::MakePlayerBanned(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_BANNED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x15 +void Channel::MakePlayerUnbanned(WorldPacket *data, uint64 bad, uint64 good) +{ + MakeNotifyPacket(data, CHAT_PLAYER_UNBANNED_NOTICE); + *data << uint64(bad); + *data << uint64(good); +} + +// done 0x16 +void Channel::MakePlayerNotBanned(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_NOT_BANNED_NOTICE); + *data << uint64(guid); +} + +// done 0x17 +void Channel::MakePlayerAlreadyMember(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_ALREADY_MEMBER_NOTICE); + *data << uint64(guid); +} + +// done 0x18 +void Channel::MakeInvite(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_INVITE_NOTICE); + *data << uint64(guid); +} + +// done 0x19 +void Channel::MakeInviteWrongFaction(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_INVITE_WRONG_FACTION_NOTICE); +} + +// done 0x1A +void Channel::MakeWrongFaction(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_WRONG_FACTION_NOTICE); +} + +// done 0x1B +void Channel::MakeInvalidName(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_INVALID_NAME_NOTICE); +} + +// done 0x1C +void Channel::MakeNotModerated(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_MODERATED_NOTICE); +} + +// done 0x1D +void Channel::MakePlayerInvited(WorldPacket *data, const std::string& name) +{ + MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE); + *data << name; +} + +// done 0x1E +void Channel::MakePlayerInviteBanned(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_PLAYER_INVITE_BANNED_NOTICE); + *data << uint64(guid); +} + +// done 0x1F +void Channel::MakeThrottled(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_THROTTLED_NOTICE); +} + +// done 0x20 +void Channel::MakeNotInArea(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_IN_AREA_NOTICE); +} + +// done 0x21 +void Channel::MakeNotInLfg(WorldPacket *data) +{ + MakeNotifyPacket(data, CHAT_NOT_IN_LFG_NOTICE); +} + +// done 0x22 +void Channel::MakeVoiceOn(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_VOICE_ON_NOTICE); + *data << uint64(guid); +} + +// done 0x23 +void Channel::MakeVoiceOff(WorldPacket *data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_VOICE_OFF_NOTICE); + *data << uint64(guid); +} + +void Channel::JoinNotify(uint64 guid) +{ + WorldPacket data; + + if (IsConstant()) + data.Initialize(SMSG_USERLIST_ADD, 8+1+1+4+GetName().size()+1); + else + data.Initialize(SMSG_USERLIST_UPDATE, 8+1+1+4+GetName().size()+1); + + data << uint64(guid); + data << uint8(GetPlayerFlags(guid)); + data << uint8(GetFlags()); + data << uint32(GetNumPlayers()); + data << GetName(); + SendToAll(&data); +} + +void Channel::LeaveNotify(uint64 guid) +{ + WorldPacket data(SMSG_USERLIST_REMOVE, 8+1+4+GetName().size()+1); + data << uint64(guid); + data << uint8(GetFlags()); + data << uint32(GetNumPlayers()); + data << GetName(); + SendToAll(&data); +} + diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h new file mode 100644 index 00000000000..d0b5923e30e --- /dev/null +++ b/src/server/game/Chat/Channels/Channel.h @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CHANNEL_H +#define _CHANNEL_H + +#include +#include +#include + +#include "Common.h" + +#include "Opcodes.h" +#include "Player.h" +#include "WorldPacket.h" + +enum ChatNotify +{ + CHAT_JOINED_NOTICE = 0x00, //+ "%s joined channel."; + CHAT_LEFT_NOTICE = 0x01, //+ "%s left channel."; + //CHAT_SUSPENDED_NOTICE = 0x01, // "%s left channel."; + CHAT_YOU_JOINED_NOTICE = 0x02, //+ "Joined Channel: [%s]"; -- You joined + //CHAT_YOU_CHANGED_NOTICE = 0x02, // "Changed Channel: [%s]"; + CHAT_YOU_LEFT_NOTICE = 0x03, //+ "Left Channel: [%s]"; -- You left + CHAT_WRONG_PASSWORD_NOTICE = 0x04, //+ "Wrong password for %s."; + CHAT_NOT_MEMBER_NOTICE = 0x05, //+ "Not on channel %s."; + CHAT_NOT_MODERATOR_NOTICE = 0x06, //+ "Not a moderator of %s."; + CHAT_PASSWORD_CHANGED_NOTICE = 0x07, //+ "[%s] Password changed by %s."; + CHAT_OWNER_CHANGED_NOTICE = 0x08, //+ "[%s] Owner changed to %s."; + CHAT_PLAYER_NOT_FOUND_NOTICE = 0x09, //+ "[%s] Player %s was not found."; + CHAT_NOT_OWNER_NOTICE = 0x0A, //+ "[%s] You are not the channel owner."; + CHAT_CHANNEL_OWNER_NOTICE = 0x0B, //+ "[%s] Channel owner is %s."; + CHAT_MODE_CHANGE_NOTICE = 0x0C, //? + CHAT_ANNOUNCEMENTS_ON_NOTICE = 0x0D, //+ "[%s] Channel announcements enabled by %s."; + CHAT_ANNOUNCEMENTS_OFF_NOTICE = 0x0E, //+ "[%s] Channel announcements disabled by %s."; + CHAT_MODERATION_ON_NOTICE = 0x0F, //+ "[%s] Channel moderation enabled by %s."; + CHAT_MODERATION_OFF_NOTICE = 0x10, //+ "[%s] Channel moderation disabled by %s."; + CHAT_MUTED_NOTICE = 0x11, //+ "[%s] You do not have permission to speak."; + CHAT_PLAYER_KICKED_NOTICE = 0x12, //? "[%s] Player %s kicked by %s."; + CHAT_BANNED_NOTICE = 0x13, //+ "[%s] You are banned from that channel."; + CHAT_PLAYER_BANNED_NOTICE = 0x14, //? "[%s] Player %s banned by %s."; + CHAT_PLAYER_UNBANNED_NOTICE = 0x15, //? "[%s] Player %s unbanned by %s."; + CHAT_PLAYER_NOT_BANNED_NOTICE = 0x16, //+ "[%s] Player %s is not banned."; + CHAT_PLAYER_ALREADY_MEMBER_NOTICE = 0x17, //+ "[%s] Player %s is already on the channel."; + CHAT_INVITE_NOTICE = 0x18, //+ "%2$s has invited you to join the channel '%1$s'."; + CHAT_INVITE_WRONG_FACTION_NOTICE = 0x19, //+ "Target is in the wrong alliance for %s."; + CHAT_WRONG_FACTION_NOTICE = 0x1A, //+ "Wrong alliance for %s."; + CHAT_INVALID_NAME_NOTICE = 0x1B, //+ "Invalid channel name"; + CHAT_NOT_MODERATED_NOTICE = 0x1C, //+ "%s is not moderated"; + CHAT_PLAYER_INVITED_NOTICE = 0x1D, //+ "[%s] You invited %s to join the channel"; + CHAT_PLAYER_INVITE_BANNED_NOTICE = 0x1E, //+ "[%s] %s has been banned."; + CHAT_THROTTLED_NOTICE = 0x1F, //+ "[%s] The number of messages that can be sent to this channel is limited, please wait to send another message."; + CHAT_NOT_IN_AREA_NOTICE = 0x20, //+ "[%s] You are not in the correct area for this channel."; -- The user is trying to send a chat to a zone specific channel, and they're not physically in that zone. + CHAT_NOT_IN_LFG_NOTICE = 0x21, //+ "[%s] You must be queued in looking for group before joining this channel."; -- The user must be in the looking for group system to join LFG chat channels. + CHAT_VOICE_ON_NOTICE = 0x22, //+ "[%s] Channel voice enabled by %s."; + CHAT_VOICE_OFF_NOTICE = 0x23, //+ "[%s] Channel voice disabled by %s."; +}; + +enum ChannelFlags +{ + CHANNEL_FLAG_NONE = 0x00, + CHANNEL_FLAG_CUSTOM = 0x01, + // 0x02 + CHANNEL_FLAG_TRADE = 0x04, + CHANNEL_FLAG_NOT_LFG = 0x08, + CHANNEL_FLAG_GENERAL = 0x10, + CHANNEL_FLAG_CITY = 0x20, + CHANNEL_FLAG_LFG = 0x40, + CHANNEL_FLAG_VOICE = 0x80 + // General 0x18 = 0x10 | 0x08 + // Trade 0x3C = 0x20 | 0x10 | 0x08 | 0x04 + // LocalDefence 0x18 = 0x10 | 0x08 + // GuildRecruitment 0x38 = 0x20 | 0x10 | 0x08 + // LookingForGroup 0x50 = 0x40 | 0x10 +}; + +enum ChannelDBCFlags +{ + CHANNEL_DBC_FLAG_NONE = 0x00000, + CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG + CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment + CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense + CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade + CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment + CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment + CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense + CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment + CHANNEL_DBC_FLAG_LFG = 0x40000 // LookingForGroup +}; + +enum ChannelMemberFlags +{ + MEMBER_FLAG_NONE = 0x00, + MEMBER_FLAG_OWNER = 0x01, + MEMBER_FLAG_MODERATOR = 0x02, + MEMBER_FLAG_VOICED = 0x04, + MEMBER_FLAG_MUTED = 0x08, + MEMBER_FLAG_CUSTOM = 0x10, + MEMBER_FLAG_MIC_MUTED = 0x20, + // 0x40 + // 0x80 +}; + +class Channel +{ + struct PlayerInfo + { + uint64 player; + uint8 flags; + + bool HasFlag(uint8 flag) { return flags & flag; } + void SetFlag(uint8 flag) { if (!HasFlag(flag)) flags |= flag; } + bool IsOwner() { return flags & MEMBER_FLAG_OWNER; } + void SetOwner(bool state) + { + if (state) flags |= MEMBER_FLAG_OWNER; + else flags &= ~MEMBER_FLAG_OWNER; + } + bool IsModerator() { return flags & MEMBER_FLAG_MODERATOR; } + void SetModerator(bool state) + { + if (state) flags |= MEMBER_FLAG_MODERATOR; + else flags &= ~MEMBER_FLAG_MODERATOR; + } + bool IsMuted() { return flags & MEMBER_FLAG_MUTED; } + void SetMuted(bool state) + { + if (state) flags |= MEMBER_FLAG_MUTED; + else flags &= ~MEMBER_FLAG_MUTED; + } + }; + + typedef std::map PlayerList; + PlayerList players; + typedef std::set BannedList; + BannedList banned; + bool m_announce; + bool m_moderate; + bool m_public; + std::string m_name; + std::string m_password; + uint8 m_flags; + uint32 m_channelId; + uint64 m_ownerGUID; + bool m_IsSaved; + + private: + // initial packet data (notify type and channel name) + void MakeNotifyPacket(WorldPacket *data, uint8 notify_type); + // type specific packet data + void MakeJoined(WorldPacket *data, uint64 guid); //+ 0x00 + void MakeLeft(WorldPacket *data, uint64 guid); //+ 0x01 + void MakeYouJoined(WorldPacket *data); //+ 0x02 + void MakeYouLeft(WorldPacket *data); //+ 0x03 + void MakeWrongPassword(WorldPacket *data); //? 0x04 + void MakeNotMember(WorldPacket *data); //? 0x05 + void MakeNotModerator(WorldPacket *data); //? 0x06 + void MakePasswordChanged(WorldPacket *data, uint64 guid); //+ 0x07 + void MakeOwnerChanged(WorldPacket *data, uint64 guid); //? 0x08 + void MakePlayerNotFound(WorldPacket *data, const std::string& name); //+ 0x09 + void MakeNotOwner(WorldPacket *data); //? 0x0A + void MakeChannelOwner(WorldPacket *data); //? 0x0B + void MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags); //+ 0x0C + void MakeAnnouncementsOn(WorldPacket *data, uint64 guid); //+ 0x0D + void MakeAnnouncementsOff(WorldPacket *data, uint64 guid); //+ 0x0E + void MakeModerationOn(WorldPacket *data, uint64 guid); //+ 0x0F + void MakeModerationOff(WorldPacket *data, uint64 guid); //+ 0x10 + void MakeMuted(WorldPacket *data); //? 0x11 + void MakePlayerKicked(WorldPacket *data, uint64 bad, uint64 good); //? 0x12 + void MakeBanned(WorldPacket *data); //? 0x13 + void MakePlayerBanned(WorldPacket *data, uint64 bad, uint64 good); //? 0x14 + void MakePlayerUnbanned(WorldPacket *data, uint64 bad, uint64 good); //? 0x15 + void MakePlayerNotBanned(WorldPacket *data, uint64 guid); //? 0x16 + void MakePlayerAlreadyMember(WorldPacket *data, uint64 guid); //+ 0x17 + void MakeInvite(WorldPacket *data, uint64 guid); //? 0x18 + void MakeInviteWrongFaction(WorldPacket *data); //? 0x19 + void MakeWrongFaction(WorldPacket *data); //? 0x1A + void MakeInvalidName(WorldPacket *data); //? 0x1B + void MakeNotModerated(WorldPacket *data); //? 0x1C + void MakePlayerInvited(WorldPacket *data, const std::string& name); //+ 0x1D + void MakePlayerInviteBanned(WorldPacket *data, uint64 guid); //? 0x1E + void MakeThrottled(WorldPacket *data); //? 0x1F + void MakeNotInArea(WorldPacket *data); //? 0x20 + void MakeNotInLfg(WorldPacket *data); //? 0x21 + void MakeVoiceOn(WorldPacket *data, uint64 guid); //+ 0x22 + void MakeVoiceOff(WorldPacket *data, uint64 guid); //+ 0x23 + + void SendToAll(WorldPacket *data, uint64 p = 0); + void SendToAllButOne(WorldPacket *data, uint64 who); + void SendToOne(WorldPacket *data, uint64 who); + + bool IsOn(uint64 who) const { return players.find(who) != players.end(); } + bool IsBanned(uint64 guid) const { return banned.find(guid) != banned.end(); } + + bool _UpdateStringInDB(const std::string& colName, const std::string& colValue) const; + bool _UpdateIntInDB(const std::string& colName, int colValue) const; + void _UpdateBanListInDB() const; + + uint8 GetPlayerFlags(uint64 p) const + { + PlayerList::const_iterator p_itr = players.find(p); + if (p_itr == players.end()) + return 0; + + return p_itr->second.flags; + } + + void SetModerator(uint64 p, bool set) + { + if (players[p].IsModerator() != set) + { + uint8 oldFlag = GetPlayerFlags(p); + players[p].SetModerator(set); + + WorldPacket data; + MakeModeChange(&data, p, oldFlag); + SendToAll(&data); + } + } + + void SetMute(uint64 p, bool set) + { + if (players[p].IsMuted() != set) + { + uint8 oldFlag = GetPlayerFlags(p); + players[p].SetMuted(set); + + WorldPacket data; + MakeModeChange(&data, p, oldFlag); + SendToAll(&data); + } + } + + public: + uint32 m_Team; + Channel(const std::string& name, uint32 channel_id, uint32 Team = 0); + std::string GetName() const { return m_name; } + uint32 GetChannelId() const { return m_channelId; } + bool IsConstant() const { return m_channelId != 0; } + bool IsAnnounce() const { return m_announce; } + bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; } + std::string GetPassword() const { return m_password; } + void SetPassword(const std::string& npassword) { m_password = npassword; } + void SetAnnounce(bool nannounce) { m_announce = nannounce; } + uint32 GetNumPlayers() const { return players.size(); } + uint8 GetFlags() const { return m_flags; } + bool HasFlag(uint8 flag) { return m_flags & flag; } + + void Join(uint64 p, const char *pass); + void Leave(uint64 p, bool send = true); + void KickOrBan(uint64 good, const char *badname, bool ban); + void Kick(uint64 good, const char *badname) { KickOrBan(good, badname, false); } + void Ban(uint64 good, const char *badname) { KickOrBan(good, badname, true); } + void UnBan(uint64 good, const char *badname); + void Password(uint64 p, const char *pass); + void SetMode(uint64 p, const char *p2n, bool mod, bool set); + void SetOwner(uint64 p, bool exclaim = true); + void SetOwner(uint64 p, const char *newname); + void SendWhoOwner(uint64 p); + void SetModerator(uint64 p, const char *newname) { SetMode(p, newname, true, true); } + void UnsetModerator(uint64 p, const char *newname) { SetMode(p, newname, true, false); } + void SetMute(uint64 p, const char *newname) { SetMode(p, newname, false, true); } + void UnsetMute(uint64 p, const char *newname) { SetMode(p, newname, false, false); } + void List(Player* p); + void Announce(uint64 p); + void Moderate(uint64 p); + void Say(uint64 p, const char *what, uint32 lang); + void Invite(uint64 p, const char *newp); + void Voice(uint64 guid1, uint64 guid2); + void DeVoice(uint64 guid1, uint64 guid2); + void JoinNotify(uint64 guid); // invisible notify + void LeaveNotify(uint64 guid); // invisible notify +}; +#endif + diff --git a/src/server/game/Chat/Channels/ChannelMgr.cpp b/src/server/game/Chat/Channels/ChannelMgr.cpp new file mode 100644 index 00000000000..f31d3ffde50 --- /dev/null +++ b/src/server/game/Chat/Channels/ChannelMgr.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ChannelMgr.h" +#include "Policies/SingletonImp.h" +#include "World.h" + +INSTANTIATE_SINGLETON_1(AllianceChannelMgr); +INSTANTIATE_SINGLETON_1(HordeChannelMgr); + +ChannelMgr* channelMgr(uint32 team) +{ + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + return &Trinity::Singleton::Instance(); // cross-faction + + if (team == ALLIANCE) + return &Trinity::Singleton::Instance(); + if (team == HORDE) + return &Trinity::Singleton::Instance(); + + return NULL; +} + +ChannelMgr::~ChannelMgr() +{ + for (ChannelMap::iterator itr = channels.begin(); itr != channels.end(); ++itr) + delete itr->second; + + channels.clear(); +} + +Channel *ChannelMgr::GetJoinChannel(std::string name, uint32 channel_id) +{ + std::wstring wname; + Utf8toWStr(name,wname); + wstrToLower(wname); + + if (channels.find(wname) == channels.end()) + { + Channel *nchan = new Channel(name,channel_id, team); + channels[wname] = nchan; + return nchan; + } + + return channels[wname]; +} + +Channel *ChannelMgr::GetChannel(std::string name, Player *p, bool pkt) +{ + std::wstring wname; + Utf8toWStr(name,wname); + wstrToLower(wname); + + ChannelMap::const_iterator i = channels.find(wname); + + if (i == channels.end()) + { + if (pkt) + { + WorldPacket data; + MakeNotOnPacket(&data,name); + p->GetSession()->SendPacket(&data); + } + + return NULL; + } + else + return i->second; +} + +void ChannelMgr::LeftChannel(std::string name) +{ + std::wstring wname; + Utf8toWStr(name,wname); + wstrToLower(wname); + + ChannelMap::const_iterator i = channels.find(wname); + + if (i == channels.end()) + return; + + Channel* channel = i->second; + + if (channel->GetNumPlayers() == 0 && !channel->IsConstant()) + { + channels.erase(wname); + delete channel; + } +} + +void ChannelMgr::MakeNotOnPacket(WorldPacket *data, std::string name) +{ + data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size + (*data) << (uint8)0x05 << name; +} diff --git a/src/server/game/Chat/Channels/ChannelMgr.h b/src/server/game/Chat/Channels/ChannelMgr.h new file mode 100644 index 00000000000..6f3b7c415ae --- /dev/null +++ b/src/server/game/Chat/Channels/ChannelMgr.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __TRINITY_CHANNELMGR_H +#define __TRINITY_CHANNELMGR_H + +#include "Common.h" +#include "Channel.h" +#include "Policies/Singleton.h" + +#include +#include + +#include "Policies/Singleton.h" + +#include "Channel.h" +#include "World.h" + +class ChannelMgr +{ + public: + uint32 team; + typedef std::map ChannelMap; + ChannelMgr() {team = 0;} + ~ChannelMgr(); + + Channel *GetJoinChannel(std::string name, uint32 channel_id); + Channel *GetChannel(std::string name, Player *p, bool pkt = true); + void LeftChannel(std::string name); + private: + ChannelMap channels; + void MakeNotOnPacket(WorldPacket *data, std::string name); +}; + +class AllianceChannelMgr : public ChannelMgr {}; +class HordeChannelMgr : public ChannelMgr {}; + +ChannelMgr* channelMgr(uint32 team); + +#endif + diff --git a/src/server/game/Chat/ChatHandler.cpp b/src/server/game/Chat/ChatHandler.cpp deleted file mode 100644 index 88e2b5473a5..00000000000 --- a/src/server/game/Chat/ChatHandler.cpp +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "ObjectAccessor.h" -#include "ObjectMgr.h" -#include "World.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Database/DatabaseEnv.h" - -#include "CellImpl.h" -#include "Chat.h" -#include "ChannelMgr.h" -#include "GridNotifiersImpl.h" -#include "Group.h" -#include "Guild.h" -#include "Language.h" -#include "Log.h" -#include "Opcodes.h" -#include "Player.h" -#include "SpellAuras.h" -#include "SpellAuraEffects.h" -#include "Util.h" - -bool WorldSession::processChatmessageFurtherAfterSecurityChecks(std::string& msg, uint32 lang) -{ - if (lang != LANG_ADDON) - { - // strip invisible characters for non-addon messages - if (sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) - stripLineInvisibleChars(msg); - - if (sWorld.getConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY) && GetSecurity() < SEC_MODERATOR - && !ChatHandler(this).isValidChatMessage(msg.c_str())) - { - sLog.outError("Player %s (GUID: %u) sent a chatmessage with an invalid link: %s", GetPlayer()->GetName(), - GetPlayer()->GetGUIDLow(), msg.c_str()); - if (sWorld.getConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK)) - KickPlayer(); - return false; - } - } - - return true; -} - -void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) -{ - uint32 type; - uint32 lang; - - recv_data >> type; - recv_data >> lang; - - if (type >= MAX_CHAT_MSG_TYPE) - { - sLog.outError("CHAT: Wrong message type received: %u", type); - return; - } - - //sLog.outDebug("CHAT: packet received. type %u, lang %u", type, lang); - - // prevent talking at unknown language (cheating) - LanguageDesc const* langDesc = GetLanguageDescByID(lang); - if (!langDesc) - { - SendNotification(LANG_UNKNOWN_LANGUAGE); - return; - } - if (langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) - { - // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) - Unit::AuraEffectList const& langAuras = _player->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE); - bool foundAura = false; - for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i) - { - if ((*i)->GetMiscValue() == int32(lang)) - { - foundAura = true; - break; - } - } - if (!foundAura) - { - SendNotification(LANG_NOT_LEARNED_LANGUAGE); - return; - } - } - - if (lang == LANG_ADDON) - { - if (sWorld.getConfig(CONFIG_CHATLOG_ADDON)) - { - std::string msg = ""; - recv_data >> msg; - - if (msg.empty()) - { - sLog.outDebug("Player %s send empty addon msg", GetPlayer()->GetName()); - return; - } - - sLog.outChat("[ADDON] Player %s sends: %s", - GetPlayer()->GetName(), msg.c_str()); - } - - // Disabled addon channel? - if (!sWorld.getConfig(CONFIG_ADDON_CHANNEL)) - return; - } - // LANG_ADDON should not be changed nor be affected by flood control - else - { - // send in universal language if player in .gmon mode (ignore spell effects) - if (_player->isGameMaster()) - lang = LANG_UNIVERSAL; - else - { - // send in universal language in two side iteration allowed mode - if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT)) - lang = LANG_UNIVERSAL; - else - { - switch(type) - { - case CHAT_MSG_PARTY: - case CHAT_MSG_RAID: - case CHAT_MSG_RAID_LEADER: - case CHAT_MSG_RAID_WARNING: - // allow two side chat at group channel if two side group allowed - if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) - lang = LANG_UNIVERSAL; - break; - case CHAT_MSG_GUILD: - case CHAT_MSG_OFFICER: - // allow two side chat at guild channel if two side guild allowed - if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) - lang = LANG_UNIVERSAL; - break; - } - } - - // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) - Unit::AuraEffectList const& ModLangAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE); - if (!ModLangAuras.empty()) - lang = ModLangAuras.front()->GetMiscValue(); - } - - if (!_player->CanSpeak()) - { - std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); - SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); - return; - } - - if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) - GetPlayer()->UpdateSpeakTime(); - } - - if (GetPlayer()->HasAura(1852) && type != CHAT_MSG_WHISPER) - { - std::string msg=""; - recv_data >> msg; - - SendNotification(GetTrinityString(LANG_GM_SILENCE), GetPlayer()->GetName()); - return; - } - - switch(type) - { - case CHAT_MSG_SAY: - case CHAT_MSG_EMOTE: - case CHAT_MSG_YELL: - { - std::string msg; - recv_data >> msg; - - if (msg.empty()) - break; - - if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) - break; - - if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_SAY_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_SAY_REQ), sWorld.getConfig(CONFIG_CHAT_SAY_LEVEL_REQ)); - return; - } - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - if (type == CHAT_MSG_SAY) - GetPlayer()->Say(msg, lang); - else if (type == CHAT_MSG_EMOTE) - GetPlayer()->TextEmote(msg); - else if (type == CHAT_MSG_YELL) - GetPlayer()->Yell(msg, lang); - } break; - - case CHAT_MSG_WHISPER: - { - std::string to, msg; - recv_data >> to; - recv_data >> msg; - - if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_WHISPER_REQ), sWorld.getConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)); - return; - } - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - if (!normalizePlayerName(to)) - { - SendPlayerNotFoundNotice(to); - break; - } - - Player *player = objmgr.GetPlayer(to.c_str()); - uint32 tSecurity = GetSecurity(); - uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; - if (!player || (tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())) - { - SendPlayerNotFoundNotice(to); - return; - } - - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) && tSecurity == SEC_PLAYER && pSecurity == SEC_PLAYER) - { - uint32 sidea = GetPlayer()->GetTeam(); - uint32 sideb = player->GetTeam(); - if (sidea != sideb) - { - SendWrongFactionNotice(); - return; - } - } - - if (GetPlayer()->HasAura(1852) && !player->isGameMaster()) - { - SendNotification(GetTrinityString(LANG_GM_SILENCE), GetPlayer()->GetName()); - return; - } - - GetPlayer()->Whisper(msg, lang, player->GetGUID()); - } break; - - case CHAT_MSG_PARTY: - case CHAT_MSG_PARTY_LEADER: - { - std::string msg; - recv_data >> msg; - - if (msg.empty()) - break; - - if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) - break; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - // if player is in battleground, he cannot say to battleground members by /p - Group *group = GetPlayer()->GetOriginalGroup(); - if (!group) - { - group = _player->GetGroup(); - if (!group || group->isBGGroup()) - return; - } - - if ((type == CHAT_MSG_PARTY_LEADER) && !group->IsLeader(_player->GetGUID())) - return; - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, type, lang, NULL, 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID())); - - if (sWorld.getConfig(CONFIG_CHATLOG_PARTY)) - sLog.outChat("[PARTY] Player %s tells group with leader %s: %s", - GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); - } break; - - case CHAT_MSG_GUILD: - { - std::string msg; - recv_data >> msg; - - if (msg.empty()) - break; - - if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) - break; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - if (GetPlayer()->GetGuildId()) - { - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - - if (guild) - guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); - - if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHATLOG_GUILD)) - { - sLog.outChat("[GUILD] Player %s tells guild %s: %s", - GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); - } - else if (lang == LANG_ADDON && sWorld.getConfig(CONFIG_CHATLOG_ADDON)) - { - sLog.outChat("[ADDON] Player %s sends to guild %s: %s", - GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); - } - } - - break; - } - case CHAT_MSG_OFFICER: - { - std::string msg; - recv_data >> msg; - - if (msg.empty()) - break; - - if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) - break; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - if (GetPlayer()->GetGuildId()) - { - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - - if (guild) - guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); - - if (sWorld.getConfig(CONFIG_CHATLOG_GUILD)) - sLog.outChat("[OFFICER] Player %s tells guild %s officers: %s", - GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); - } - break; - } - case CHAT_MSG_RAID: - { - std::string msg; - recv_data >> msg; - - if (msg.empty()) - break; - - if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) - break; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - // if player is in battleground, he cannot say to battleground members by /ra - Group *group = GetPlayer()->GetOriginalGroup(); - if (!group) - { - group = GetPlayer()->GetGroup(); - if (!group || group->isBGGroup() || !group->isRaidGroup()) - return; - } - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - - if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) - sLog.outChat("[RAID] Player %s tells raid with leader %s: %s", - GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); - } break; - case CHAT_MSG_RAID_LEADER: - { - std::string msg; - recv_data >> msg; - - if (msg.empty()) - break; - - if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) - break; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - // if player is in battleground, he cannot say to battleground members by /ra - Group *group = GetPlayer()->GetOriginalGroup(); - if (!group) - { - group = GetPlayer()->GetGroup(); - if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetGUID())) - return; - } - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - - if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) - sLog.outChat("[RAID] Leader player %s tells raid: %s", - GetPlayer()->GetName(), msg.c_str()); - } break; - case CHAT_MSG_RAID_WARNING: - { - std::string msg; - recv_data >> msg; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - Group *group = GetPlayer()->GetGroup(); - if (!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID())) || group->isBGGroup()) - return; - - WorldPacket data; - //in battleground, raid warning is sent only to players in battleground - code is ok - ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - - if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) - sLog.outChat("[RAID] Leader player %s warns raid with: %s", - GetPlayer()->GetName(), msg.c_str()); - } break; - - case CHAT_MSG_BATTLEGROUND: - { - std::string msg; - recv_data >> msg; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - //battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() - Group *group = GetPlayer()->GetGroup(); - if (!group || !group->isBGGroup()) - return; - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - - if (sWorld.getConfig(CONFIG_CHATLOG_BGROUND)) - sLog.outChat("[BATTLEGROUND] Player %s tells battleground with leader %s: %s", - GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); - } break; - - case CHAT_MSG_BATTLEGROUND_LEADER: - { - std::string msg; - recv_data >> msg; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (msg.empty()) - break; - - // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() - Group *group = GetPlayer()->GetGroup(); - if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID())) - return; - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(), NULL); - group->BroadcastPacket(&data, false); - - if (sWorld.getConfig(CONFIG_CHATLOG_BGROUND)) - sLog.outChat("[RAID] Leader player %s tells battleground: %s", - GetPlayer()->GetName(), msg.c_str()); - } break; - - case CHAT_MSG_CHANNEL: - { - std::string channel, msg; - recv_data >> channel; - recv_data >> msg; - - if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) - return; - - if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_CHANNEL_REQ), sWorld.getConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)); - return; - } - - if (msg.empty()) - break; - - if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) - { - - if (Channel *chn = cMgr->GetChannel(channel, _player)) - { - chn->Say(_player->GetGUID(), msg.c_str(), lang); - - if ((chn->HasFlag(CHANNEL_FLAG_TRADE) || - chn->HasFlag(CHANNEL_FLAG_GENERAL) || - chn->HasFlag(CHANNEL_FLAG_CITY) || - chn->HasFlag(CHANNEL_FLAG_LFG)) && - sWorld.getConfig(CONFIG_CHATLOG_SYSCHAN)) - sLog.outChat("[SYSCHAN] Player %s tells channel %s: %s", - GetPlayer()->GetName(), chn->GetName().c_str(), msg.c_str()); - else if (sWorld.getConfig(CONFIG_CHATLOG_CHANNEL)) - sLog.outChat("[CHANNEL] Player %s tells channel %s: %s", - GetPlayer()->GetName(), chn->GetName().c_str(), msg.c_str()); - } - } - } break; - - case CHAT_MSG_AFK: - { - std::string msg; - recv_data >> msg; - - if ((msg.empty() || !_player->isAFK()) && !_player->isInCombat()) - { - if (!_player->isAFK()) - { - if (msg.empty()) - msg = GetTrinityString(LANG_PLAYER_AFK_DEFAULT); - _player->afkMsg = msg; - } - _player->ToggleAFK(); - if (_player->isAFK() && _player->isDND()) - _player->ToggleDND(); - } - } break; - - case CHAT_MSG_DND: - { - std::string msg; - recv_data >> msg; - - if (msg.empty() || !_player->isDND()) - { - if (!_player->isDND()) - { - if (msg.empty()) - msg = GetTrinityString(LANG_PLAYER_DND_DEFAULT); - _player->dndMsg = msg; - } - _player->ToggleDND(); - if (_player->isDND() && _player->isAFK()) - _player->ToggleAFK(); - } - } break; - - default: - sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang); - break; - } -} - -void WorldSession::HandleEmoteOpcode(WorldPacket & recv_data) -{ - if (!GetPlayer()->isAlive()) - return; - - uint32 emote; - recv_data >> emote; - GetPlayer()->HandleEmoteCommand(emote); -} - -namespace Trinity -{ - class EmoteChatBuilder - { - public: - EmoteChatBuilder(Player const& pl, uint32 text_emote, uint32 emote_num, Unit const* target) - : i_player(pl), i_text_emote(text_emote), i_emote_num(emote_num), i_target(target) {} - - void operator()(WorldPacket& data, int32 loc_idx) - { - char const* nam = i_target ? i_target->GetNameForLocaleIdx(loc_idx) : NULL; - uint32 namlen = (nam ? strlen(nam) : 0) + 1; - - data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); - data << i_player.GetGUID(); - data << (uint32)i_text_emote; - data << i_emote_num; - data << (uint32)namlen; - if (namlen > 1) - data.append(nam, namlen); - else - data << (uint8)0x00; - } - - private: - Player const& i_player; - uint32 i_text_emote; - uint32 i_emote_num; - Unit const* i_target; - }; -} // namespace Trinity - -void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data) -{ - if (!GetPlayer()->isAlive()) - return; - - if (!GetPlayer()->CanSpeak()) - { - std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); - SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); - return; - } - - uint32 text_emote, emoteNum; - uint64 guid; - - recv_data >> text_emote; - recv_data >> emoteNum; - recv_data >> guid; - - EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); - if (!em) - return; - - uint32 emote_anim = em->textid; - - switch(emote_anim) - { - case EMOTE_STATE_SLEEP: - case EMOTE_STATE_SIT: - case EMOTE_STATE_KNEEL: - case EMOTE_ONESHOT_NONE: - break; - default: - GetPlayer()->HandleEmoteCommand(emote_anim); - break; - } - - Unit* unit = ObjectAccessor::GetUnit(*_player, guid); - - CellPair p = Trinity::ComputeCellPair(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); - - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit); - Trinity::LocalizedPacketDo emote_do(emote_builder); - Trinity::PlayerDistWorker > emote_worker(GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), emote_do); - TypeContainerVisitor >, WorldTypeMapContainer> message(emote_worker); - cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); - - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); - - //Send scripted event call - if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI()) - ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote); -} - -void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data) -{ - uint64 iguid; - uint8 unk; - //sLog.outDebug("WORLD: Received CMSG_CHAT_IGNORED"); - - recv_data >> iguid; - recv_data >> unk; // probably related to spam reporting - - Player *player = objmgr.GetPlayer(iguid); - if (!player || !player->GetSession()) - return; - - WorldPacket data; - ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), GetPlayer()->GetName(), NULL); - player->GetSession()->SendPacket(&data); -} - -void WorldSession::HandleChannelDeclineInvite(WorldPacket &recvPacket) -{ - sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); -} - -void WorldSession::SendPlayerNotFoundNotice(std::string name) -{ - WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, name.size()+1); - data << name; - SendPacket(&data); -} - -void WorldSession::SendPlayerAmbiguousNotice(std::string name) -{ - WorldPacket data(SMSG_CHAT_PLAYER_AMBIGUOUS, name.size()+1); - data << name; - SendPacket(&data); -} - -void WorldSession::SendWrongFactionNotice() -{ - WorldPacket data(SMSG_CHAT_WRONG_FACTION, 0); - SendPacket(&data); -} - -void WorldSession::SendChatRestrictedNotice(ChatRestrictionType restriction) -{ - WorldPacket data(SMSG_CHAT_RESTRICTED, 1); - data << uint8(restriction); - SendPacket(&data); -} diff --git a/src/server/game/Chat/Commands/Debugcmds.cpp b/src/server/game/Chat/Commands/Debugcmds.cpp new file mode 100644 index 00000000000..ee8c623c3d0 --- /dev/null +++ b/src/server/game/Chat/Commands/Debugcmds.cpp @@ -0,0 +1,1127 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "Vehicle.h" +#include "Player.h" +#include "Opcodes.h" +#include "Chat.h" +#include "Log.h" +#include "Unit.h" +#include "GossipDef.h" +#include "Language.h" +#include "BattleGroundMgr.h" +#include +#include "ObjectMgr.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "SpellMgr.h" +#include "ScriptMgr.h" + +bool ChatHandler::HandleDebugSendSpellFailCommand(const char* args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + if (!px) + return false; + + uint8 failnum = (uint8)atoi(px); + if (failnum == 0 && *px != '0') + return false; + + char* p1 = strtok(NULL, " "); + uint8 failarg1 = p1 ? (uint8)atoi(p1) : 0; + + char* p2 = strtok(NULL, " "); + uint8 failarg2 = p2 ? (uint8)atoi(p2) : 0; + + WorldPacket data(SMSG_CAST_FAILED, 5); + data << uint8(0); + data << uint32(133); + data << uint8(failnum); + if (p1 || p2) + data << uint32(failarg1); + if (p2) + data << uint32(failarg2); + + m_session->SendPacket(&data); + + return true; +} + +bool ChatHandler::HandleDebugSendPoiCommand(const char* args) +{ + if (!*args) + return false; + + Player *pPlayer = m_session->GetPlayer(); + Unit* target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + return true; + } + + char* icon_text = strtok((char*)args, " "); + char* flags_text = strtok(NULL, " "); + if (!icon_text || !flags_text) + return false; + + uint32 icon = atol(icon_text); + uint32 flags = atol(flags_text); + + sLog.outDetail("Command : POI, NPC = %u, icon = %u flags = %u", target->GetGUIDLow(), icon,flags); + pPlayer->PlayerTalkClass->SendPointOfInterest(target->GetPositionX(), target->GetPositionY(), Poi_Icon(icon), flags, 30, "Test POI"); + return true; +} + +bool ChatHandler::HandleDebugSendEquipErrorCommand(const char* args) +{ + if (!*args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendEquipError(msg, 0, 0); + return true; +} + +bool ChatHandler::HandleDebugSendSellErrorCommand(const char* args) +{ + if (!*args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendSellError(msg, 0, 0, 0); + return true; +} + +bool ChatHandler::HandleDebugSendBuyErrorCommand(const char* args) +{ + if (!*args) + return false; + + uint8 msg = atoi(args); + m_session->GetPlayer()->SendBuyError(msg, 0, 0, 0); + return true; +} + +bool ChatHandler::HandleDebugSendOpcodeCommand(const char* /*args*/) +{ + Unit *unit = getSelectedUnit(); + Player *player = NULL; + if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) + player = m_session->GetPlayer(); + else + player = (Player*)unit; + if (!unit) unit = player; + + std::ifstream ifs("opcode.txt"); + if (ifs.bad()) + return false; + + uint32 opcode; + ifs >> opcode; + + WorldPacket data(opcode, 0); + + while (!ifs.eof()) + { + std::string type; + ifs >> type; + + if (type == "") + break; + + if (type == "uint8") + { + uint16 val1; + ifs >> val1; + data << uint8(val1); + } + else if (type == "uint16") + { + uint16 val2; + ifs >> val2; + data << val2; + } + else if (type == "uint32") + { + uint32 val3; + ifs >> val3; + data << val3; + } + else if (type == "uint64") + { + uint64 val4; + ifs >> val4; + data << val4; + } + else if (type == "float") + { + float val5; + ifs >> val5; + data << val5; + } + else if (type == "string") + { + std::string val6; + ifs >> val6; + data << val6; + } + else if (type == "appitsguid") + { + data.append(unit->GetPackGUID()); + } + else if (type == "appmyguid") + { + data.append(player->GetPackGUID()); + } + else if (type == "appgoguid") + { + GameObject *obj = GetNearbyGameObject(); + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, 0); + SetSentErrorMessage(true); + ifs.close(); + return false; + } + data.append(obj->GetPackGUID()); + } + else if (type == "goguid") + { + GameObject *obj = GetNearbyGameObject(); + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, 0); + SetSentErrorMessage(true); + ifs.close(); + return false; + } + data << uint64(obj->GetGUID()); + } + else if (type == "myguid") + { + data << uint64(player->GetGUID()); + } + else if (type == "itsguid") + { + data << uint64(unit->GetGUID()); + } + else if (type == "pos") + { + data << unit->GetPositionX(); + data << unit->GetPositionY(); + data << unit->GetPositionZ(); + } + else if (type == "mypos") + { + data << player->GetPositionX(); + data << player->GetPositionY(); + data << player->GetPositionZ(); + } + else + { + sLog.outDebug("Sending opcode: unknown type '%s'", type.c_str()); + break; + } + } + ifs.close(); + sLog.outDebug("Sending opcode %u", data.GetOpcode()); + data.hexlike(); + player->GetSession()->SendPacket(&data); + PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName()); + return true; +} + +bool ChatHandler::HandleDebugUpdateWorldStateCommand(const char* args) +{ + char* w = strtok((char*)args, " "); + char* s = strtok(NULL, " "); + + if (!w || !s) + return false; + + uint32 world = (uint32)atoi(w); + uint32 state = (uint32)atoi(s); + m_session->GetPlayer()->SendUpdateWorldState(world, state); + return true; +} + +bool ChatHandler::HandleDebugPlayCinematicCommand(const char* args) +{ + // USAGE: .debug play cinematic #cinematicid + // #cinematicid - ID decimal number from CinemaicSequences.dbc (1st column) + if (!*args) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 dwId = atoi((char*)args); + + if (!sCinematicSequencesStore.LookupEntry(dwId)) + { + PSendSysMessage(LANG_CINEMATIC_NOT_EXIST, dwId); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->SendCinematicStart(dwId); + return true; +} + +bool ChatHandler::HandleDebugPlayMovieCommand(const char* args) +{ + // USAGE: .debug play movie #movieid + // #movieid - ID decimal number from Movie.dbc (1st column) + if (!*args) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 dwId = atoi((char*)args); + + if (!sMovieStore.LookupEntry(dwId)) + { + PSendSysMessage(LANG_MOVIE_NOT_EXIST, dwId); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->SendMovieStart(dwId); + return true; +} + +//Play sound +bool ChatHandler::HandleDebugPlaySoundCommand(const char* args) +{ + // USAGE: .debug playsound #soundid + // #soundid - ID decimal number from SoundEntries.dbc (1st column) + if (!*args) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 dwSoundId = atoi((char*)args); + + if (!sSoundEntriesStore.LookupEntry(dwSoundId)) + { + PSendSysMessage(LANG_SOUND_NOT_EXIST, dwSoundId); + SetSentErrorMessage(true); + return false; + } + + Unit* unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (m_session->GetPlayer()->GetSelection()) + unit->PlayDistanceSound(dwSoundId,m_session->GetPlayer()); + else + unit->PlayDirectSound(dwSoundId,m_session->GetPlayer()); + + PSendSysMessage(LANG_YOU_HEAR_SOUND, dwSoundId); + return true; +} + +//Send notification in channel +bool ChatHandler::HandleDebugSendChannelNotifyCommand(const char* args) +{ + if (!*args) + return false; + + const char *name = "test"; + uint8 code = atoi(args); + + WorldPacket data(SMSG_CHANNEL_NOTIFY, (1+10)); + data << code; // notify type + data << name; // channel name + data << uint32(0); + data << uint32(0); + m_session->SendPacket(&data); + return true; +} + +//Send notification in chat +bool ChatHandler::HandleDebugSendChatMsgCommand(const char* args) +{ + if (!*args) + return false; + + const char *msg = "testtest"; + uint8 type = atoi(args); + WorldPacket data; + ChatHandler::FillMessageData(&data, m_session, type, 0, "chan", m_session->GetPlayer()->GetGUID(), msg, m_session->GetPlayer()); + m_session->SendPacket(&data); + return true; +} + +bool ChatHandler::HandleDebugSendQuestPartyMsgCommand(const char* args) +{ + uint32 msg = atol((char*)args); + m_session->GetPlayer()->SendPushToPartyResponse(m_session->GetPlayer(), msg); + return true; +} + +bool ChatHandler::HandleDebugGetLootRecipientCommand(const char* /*args*/) +{ + Creature* target = getSelectedCreature(); + if (!target) + return false; + + PSendSysMessage("loot recipient: %s", target->hasLootRecipient()?(target->GetLootRecipient()?target->GetLootRecipient()->GetName():"offline"):"no loot recipient"); + return true; +} + +bool ChatHandler::HandleDebugSendQuestInvalidMsgCommand(const char* args) +{ + uint32 msg = atol((char*)args); + m_session->GetPlayer()->SendCanTakeQuestResponse(msg); + return true; +} + +bool ChatHandler::HandleDebugGetItemStateCommand(const char* args) +{ + if (!*args) + return false; + + std::string state_str = args; + + ItemUpdateState state = ITEM_UNCHANGED; + bool list_queue = false, check_all = false; + if (state_str == "unchanged") state = ITEM_UNCHANGED; + else if (state_str == "changed") state = ITEM_CHANGED; + else if (state_str == "new") state = ITEM_NEW; + else if (state_str == "removed") state = ITEM_REMOVED; + else if (state_str == "queue") list_queue = true; + else if (state_str == "check_all") check_all = true; + else return false; + + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + + if (!list_queue && !check_all) + { + state_str = "The player has the following " + state_str + " items: "; + SendSysMessage(state_str.c_str()); + for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i) + { + if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) + continue; + + Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + if (!item) continue; + if (!item->IsBag()) + { + if (item->GetState() == state) + PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID())); + } + else + { + Bag *bag = (Bag*)item; + for (uint8 j = 0; j < bag->GetBagSize(); ++j) + { + Item* item2 = bag->GetItemByPos(j); + if (item2 && item2->GetState() == state) + PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item2->GetSlot(), item2->GetGUIDLow(), GUID_LOPART(item2->GetOwnerGUID())); + } + } + } + } + + if (list_queue) + { + std::vector &updateQueue = player->GetItemUpdateQueue(); + for (size_t i = 0; i < updateQueue.size(); ++i) + { + Item *item = updateQueue[i]; + if (!item) continue; + + Bag *container = item->GetContainer(); + uint8 bag_slot = container ? container->GetSlot() : uint8(INVENTORY_SLOT_BAG_0); + + std::string st; + switch(item->GetState()) + { + case ITEM_UNCHANGED: st = "unchanged"; break; + case ITEM_CHANGED: st = "changed"; break; + case ITEM_NEW: st = "new"; break; + case ITEM_REMOVED: st = "removed"; break; + } + + PSendSysMessage("bag: %d slot: %d guid: %d - state: %s", bag_slot, item->GetSlot(), item->GetGUIDLow(), st.c_str()); + } + if (updateQueue.empty()) + PSendSysMessage("updatequeue empty"); + } + + if (check_all) + { + bool error = false; + std::vector &updateQueue = player->GetItemUpdateQueue(); + for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i) + { + if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) + continue; + + Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + if (!item) continue; + + if (item->GetSlot() != i) + { + PSendSysMessage("item at slot %d, guid %d has an incorrect slot value: %d", i, item->GetGUIDLow(), item->GetSlot()); + error = true; continue; + } + + if (item->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("for the item at slot %d and itemguid %d, owner's guid (%d) and player's guid (%d) don't match!", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + if (Bag *container = item->GetContainer()) + { + PSendSysMessage("item at slot: %d guid: %d has a container (slot: %d, guid: %d) but shouldnt!", item->GetSlot(), item->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); + error = true; continue; + } + + if (item->IsInUpdateQueue()) + { + uint16 qp = item->GetQueuePos(); + if (qp > updateQueue.size()) + { + PSendSysMessage("item at slot: %d guid: %d has a queuepos (%d) larger than the update queue size! ", item->GetSlot(), item->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] == NULL) + { + PSendSysMessage("item at slot: %d guid: %d has a queuepos (%d) that points to NULL in the queue!", item->GetSlot(), item->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] != item) + { + PSendSysMessage("item at slot: %d guid: %d has has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", item->GetSlot(), item->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); + error = true; continue; + } + } + else if (item->GetState() != ITEM_UNCHANGED) + { + PSendSysMessage("item at slot: %d guid: %d is not in queue but should be (state: %d)!", item->GetSlot(), item->GetGUIDLow(), item->GetState()); + error = true; continue; + } + + if (item->IsBag()) + { + Bag *bag = (Bag*)item; + for (uint8 j = 0; j < bag->GetBagSize(); ++j) + { + Item* item2 = bag->GetItemByPos(j); + if (!item2) continue; + + if (item2->GetSlot() != j) + { + PSendSysMessage("the item in bag %d slot %d, guid %d has an incorrect slot value: %d", bag->GetSlot(), j, item2->GetGUIDLow(), item2->GetSlot()); + error = true; continue; + } + + if (item2->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("for the item in bag %d at slot %d and itemguid %d, owner's guid (%d) and player's guid (%d) don't match!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), GUID_LOPART(item2->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + Bag *container = item2->GetContainer(); + if (!container) + { + PSendSysMessage("the item in bag %d at slot %d with guid %d has no container!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow()); + error = true; continue; + } + + if (container != bag) + { + PSendSysMessage("the item in bag %d at slot %d with guid %d has a different container(slot %d guid %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); + error = true; continue; + } + + if (item2->IsInUpdateQueue()) + { + uint16 qp = item2->GetQueuePos(); + if (qp > updateQueue.size()) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has a queuepos (%d) larger than the update queue size! ", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] == NULL) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has a queuepos (%d) that points to NULL in the queue!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp); + error = true; continue; + } + + if (updateQueue[qp] != item2) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d has has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); + error = true; continue; + } + } + else if (item2->GetState() != ITEM_UNCHANGED) + { + PSendSysMessage("item in bag: %d at slot: %d guid: %d is not in queue but should be (state: %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), item2->GetState()); + error = true; continue; + } + } + } + } + + for (size_t i = 0; i < updateQueue.size(); ++i) + { + Item *item = updateQueue[i]; + if (!item) continue; + + if (item->GetOwnerGUID() != player->GetGUID()) + { + PSendSysMessage("queue(" SIZEFMTD "): for the an item (guid %d), the owner's guid (%d) and player's guid (%d) don't match!", i, item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); + error = true; continue; + } + + if (item->GetQueuePos() != i) + { + PSendSysMessage("queue(" SIZEFMTD "): for the an item (guid %d), the queuepos doesn't match it's position in the queue!", i, item->GetGUIDLow()); + error = true; continue; + } + + if (item->GetState() == ITEM_REMOVED) continue; + Item *test = player->GetItemByPos(item->GetBagSlot(), item->GetSlot()); + + if (test == NULL) + { + PSendSysMessage("queue(" SIZEFMTD "): the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the player doesn't have an item at that position!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow()); + error = true; continue; + } + + if (test != item) + { + PSendSysMessage("queue(" SIZEFMTD "): the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the item with guid %d is there instead!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow()); + error = true; continue; + } + } + if (!error) + SendSysMessage("All OK!"); + } + + return true; +} + +bool ChatHandler::HandleDebugBattlegroundCommand(const char * /*args*/) +{ + sBattleGroundMgr.ToggleTesting(); + return true; +} + +bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/) +{ + sBattleGroundMgr.ToggleArenaTesting(); + return true; +} + +bool ChatHandler::HandleDebugThreatList(const char * /*args*/) +{ + Creature* target = getSelectedCreature(); + if (!target || target->isTotem() || target->isPet()) + return false; + + std::list& tlist = target->getThreatManager().getThreatList(); + std::list::iterator itr; + uint32 cnt = 0; + PSendSysMessage("Threat list of %s (guid %u)",target->GetName(), target->GetGUIDLow()); + for (itr = tlist.begin(); itr != tlist.end(); ++itr) + { + Unit* unit = (*itr)->getTarget(); + if (!unit) + continue; + ++cnt; + PSendSysMessage(" %u. %s (guid %u) - threat %f",cnt,unit->GetName(), unit->GetGUIDLow(), (*itr)->getThreat()); + } + SendSysMessage("End of threat list."); + return true; +} + +bool ChatHandler::HandleDebugHostileRefList(const char * /*args*/) +{ + Unit* target = getSelectedUnit(); + if (!target) + target = m_session->GetPlayer(); + HostileReference* ref = target->getHostileRefManager().getFirst(); + uint32 cnt = 0; + PSendSysMessage("Hostil reference list of %s (guid %u)",target->GetName(), target->GetGUIDLow()); + while (ref) + { + if (Unit * unit = ref->getSource()->getOwner()) + { + ++cnt; + PSendSysMessage(" %u. %s (guid %u) - threat %f",cnt,unit->GetName(), unit->GetGUIDLow(), ref->getThreat()); + } + ref = ref->next(); + } + SendSysMessage("End of hostil reference list."); + return true; +} + +bool ChatHandler::HandleDebugSetVehicleId(const char *args) +{ + Unit* target = getSelectedUnit(); + if (!target || target->IsVehicle()) + return false; + + if (!args) + return false; + + char* i = strtok((char*)args, " "); + if (!i) + return false; + + uint32 id = (uint32)atoi(i); + //target->SetVehicleId(id); + PSendSysMessage("Vehicle id set to %u", id); + return true; +} + +bool ChatHandler::HandleDebugEnterVehicle(const char * args) +{ + Unit* target = getSelectedUnit(); + if (!target || !target->IsVehicle()) + return false; + + if (!args) + return false; + + char* i = strtok((char*)args, " "); + if (!i) + return false; + + char* j = strtok(NULL, " "); + + uint32 entry = (uint32)atoi(i); + int8 seatId = j ? (int8)atoi(j) : -1; + + if (!entry) + m_session->GetPlayer()->EnterVehicle(target, seatId); + else + { + Creature *passenger = NULL; + Trinity::AllCreaturesOfEntryInRange check(m_session->GetPlayer(), entry, 20.0f); + Trinity::CreatureSearcher searcher(m_session->GetPlayer(), passenger, check); + m_session->GetPlayer()->VisitNearbyObject(30.0f, searcher); + if (!passenger || passenger == target) + return false; + passenger->EnterVehicle(target, seatId); + } + + PSendSysMessage("Unit %u entered vehicle %d", entry, (int32)seatId); + return true; +} + +bool ChatHandler::HandleDebugSpawnVehicle(const char* args) +{ + if (!*args) + return false; + + char* e = strtok((char*)args, " "); + char* i = strtok(NULL, " "); + + if (!e) + return false; + + uint32 entry = (uint32)atoi(e); + + float x, y, z, o = m_session->GetPlayer()->GetOrientation(); + m_session->GetPlayer()->GetClosePoint(x, y, z, m_session->GetPlayer()->GetObjectSize()); + + if (!i) + return m_session->GetPlayer()->SummonCreature(entry, x, y, z, o); + + uint32 id = (uint32)atoi(i); + + CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); + + if (!ci) + return false; + + VehicleEntry const *ve = sVehicleStore.LookupEntry(id); + + if (!ve) + return false; + + Creature *v = new Creature; + + Map *map = m_session->GetPlayer()->GetMap(); + + if (!v->Create(objmgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, m_session->GetPlayer()->GetPhaseMask(), entry, id, m_session->GetPlayer()->GetTeam(), x, y, z, o)) + { + delete v; + return false; + } + + map->Add(v->ToCreature()); + + return true; +} + +bool ChatHandler::HandleDebugSendLargePacketCommand(const char* /*args*/) +{ + const char* stuffingString = "This is a dummy string to push the packet's size beyond 128000 bytes. "; + std::ostringstream ss; + while (ss.str().size() < 128000) + ss << stuffingString; + SendSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleDebugSendSetPhaseShiftCommand(const char* args) +{ + if (!*args) + return false; + + uint32 PhaseShift = atoi(args); + m_session->SendSetPhaseShift(PhaseShift); + return true; +} + +bool ChatHandler::HandleDebugGetItemValueCommand(const char* args) +{ + if (!*args) + return false; + + char* e = strtok((char*)args, " "); + char* f = strtok(NULL, " "); + + if (!e || !f) + return false; + + uint32 guid = (uint32)atoi(e); + uint32 index = (uint32)atoi(f); + + Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); + + if (!i) + return false; + + if (index >= i->GetValuesCount()) + return false; + + uint32 value = i->GetUInt32Value(index); + + PSendSysMessage("Item %u: value at %u is %u", guid, index, value); + + return true; +} + +bool ChatHandler::HandleDebugSetItemValueCommand(const char* args) +{ + if (!*args) + return false; + + char* e = strtok((char*)args, " "); + char* f = strtok(NULL, " "); + char* g = strtok(NULL, " "); + + if (!e || !f || !g) + return false; + + uint32 guid = (uint32)atoi(e); + uint32 index = (uint32)atoi(f); + uint32 value = (uint32)atoi(g); + + Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); + + if (!i) + return false; + + if (index >= i->GetValuesCount()) + return false; + + i->SetUInt32Value(index, value); + + return true; +} + +bool ChatHandler::HandleDebugItemExpireCommand(const char* args) +{ + if (!*args) + return false; + + char* e = strtok((char*)args, " "); + if (!e) + return false; + + uint32 guid = (uint32)atoi(e); + + Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); + + if (!i) + return false; + + m_session->GetPlayer()->DestroyItem(i->GetBagSlot(),i->GetSlot(), true); + sScriptMgr.ItemExpire(m_session->GetPlayer(),i->GetProto()); + + return true; +} + +//show animation +bool ChatHandler::HandleDebugAnimCommand(const char* args) +{ + if (!*args) + return false; + + uint32 anim_id = atoi((char*)args); + m_session->GetPlayer()->HandleEmoteCommand(anim_id); + return true; +} + +bool ChatHandler::HandleDebugSetAuraStateCommand(const char* args) +{ + if (!*args) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Unit* unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + int32 state = atoi((char*)args); + if (!state) + { + // reset all states + for (int i = 1; i <= 32; ++i) + unit->ModifyAuraState(AuraState(i),false); + return true; + } + + unit->ModifyAuraState(AuraState(abs(state)),state > 0); + return true; +} + +bool ChatHandler::HandleDebugSetValueCommand(const char* args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px || !py) + return false; + + WorldObject* target = getSelectedObject(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = target->GetGUID(); + + uint32 Opcode = (uint32)atoi(px); + if (Opcode >= target->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); + return false; + } + uint32 iValue; + float fValue; + bool isint32 = true; + if (pz) + isint32 = (bool)atoi(pz); + if (isint32) + { + iValue = (uint32)atoi(py); + sLog.outDebug(GetTrinityString(LANG_SET_UINT), GUID_LOPART(guid), Opcode, iValue); + target->SetUInt32Value(Opcode , iValue); + PSendSysMessage(LANG_SET_UINT_FIELD, GUID_LOPART(guid), Opcode,iValue); + } + else + { + fValue = (float)atof(py); + sLog.outDebug(GetTrinityString(LANG_SET_FLOAT), GUID_LOPART(guid), Opcode, fValue); + target->SetFloatValue(Opcode , fValue); + PSendSysMessage(LANG_SET_FLOAT_FIELD, GUID_LOPART(guid), Opcode,fValue); + } + + return true; +} + +bool ChatHandler::HandleDebugGetValueCommand(const char* args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + char* pz = strtok(NULL, " "); + + if (!px) + return false; + + Unit* target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = target->GetGUID(); + + uint32 Opcode = (uint32)atoi(px); + if (Opcode >= target->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); + return false; + } + uint32 iValue; + float fValue; + bool isint32 = true; + if (pz) + isint32 = (bool)atoi(pz); + + if (isint32) + { + iValue = target->GetUInt32Value(Opcode); + sLog.outDebug(GetTrinityString(LANG_GET_UINT), GUID_LOPART(guid), Opcode, iValue); + PSendSysMessage(LANG_GET_UINT_FIELD, GUID_LOPART(guid), Opcode, iValue); + } + else + { + fValue = target->GetFloatValue(Opcode); + sLog.outDebug(GetTrinityString(LANG_GET_FLOAT), GUID_LOPART(guid), Opcode, fValue); + PSendSysMessage(LANG_GET_FLOAT_FIELD, GUID_LOPART(guid), Opcode, fValue); + } + + return true; +} + +bool ChatHandler::HandleDebugMod32ValueCommand(const char* args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 Opcode = (uint32)atoi(px); + int Value = atoi(py); + + if (Opcode >= m_session->GetPlayer()->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, m_session->GetPlayer()->GetGUIDLow(), m_session->GetPlayer()->GetValuesCount()); + return false; + } + + sLog.outDebug(GetTrinityString(LANG_CHANGE_32BIT), Opcode, Value); + + int CurrentValue = (int)m_session->GetPlayer()->GetUInt32Value(Opcode); + + CurrentValue += Value; + m_session->GetPlayer()->SetUInt32Value(Opcode , (uint32)CurrentValue); + + PSendSysMessage(LANG_CHANGE_32BIT_FIELD, Opcode,CurrentValue); + + return true; +} + +bool ChatHandler::HandleDebugUpdateCommand(const char* args) +{ + if (!*args) + return false; + + uint32 updateIndex; + uint32 value; + + char* pUpdateIndex = strtok((char*)args, " "); + + Unit* chr = getSelectedUnit(); + if (chr == NULL) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!pUpdateIndex) + { + return true; + } + updateIndex = atoi(pUpdateIndex); + //check updateIndex + if (chr->GetTypeId() == TYPEID_PLAYER) + { + if (updateIndex >= PLAYER_END) return true; + } + else + { + if (updateIndex >= UNIT_END) return true; + } + + char* pvalue = strtok(NULL, " "); + if (!pvalue) + { + value=chr->GetUInt32Value(updateIndex); + + PSendSysMessage(LANG_UPDATE, chr->GetGUIDLow(),updateIndex,value); + return true; + } + + value=atoi(pvalue); + + PSendSysMessage(LANG_UPDATE_CHANGE, chr->GetGUIDLow(),updateIndex,value); + + chr->SetUInt32Value(updateIndex,value); + + return true; +} diff --git a/src/server/game/Chat/Commands/Level0.cpp b/src/server/game/Chat/Commands/Level0.cpp new file mode 100644 index 00000000000..ed021ac00d4 --- /dev/null +++ b/src/server/game/Chat/Commands/Level0.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "World.h" +#include "Player.h" +#include "Opcodes.h" +#include "Chat.h" +#include "ObjectAccessor.h" +#include "Language.h" +#include "AccountMgr.h" +#include "SystemConfig.h" +#include "revision.h" +#include "Util.h" + +bool ChatHandler::HandleHelpCommand(const char* args) +{ + char* cmd = strtok((char*)args, " "); + if (!cmd) + { + ShowHelpForCommand(getCommandTable(), "help"); + ShowHelpForCommand(getCommandTable(), ""); + } + else + { + if (!ShowHelpForCommand(getCommandTable(), cmd)) + SendSysMessage(LANG_NO_HELP_CMD); + } + + return true; +} + +bool ChatHandler::HandleCommandsCommand(const char* /*args*/) +{ + ShowHelpForCommand(getCommandTable(), ""); + return true; +} + +bool ChatHandler::HandleAccountCommand(const char* /*args*/) +{ + AccountTypes gmlevel = m_session->GetSecurity(); + PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmlevel)); + return true; +} + +bool ChatHandler::HandleStartCommand(const char* /*args*/) +{ + Player *chr = m_session->GetPlayer(); + + if (chr->isInFlight()) + { + SendSysMessage(LANG_YOU_IN_FLIGHT); + SetSentErrorMessage(true); + return false; + } + + if (chr->isInCombat()) + { + SendSysMessage(LANG_YOU_IN_COMBAT); + SetSentErrorMessage(true); + return false; + } + + if ((chr->isDead()) || (chr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))) + { + // if player is dead and stuck, send ghost to graveyard + chr->RepopAtGraveyard(); + return true; + } + + // cast spell Stuck + chr->CastSpell(chr,7355,false); + return true; +} + +bool ChatHandler::HandleServerInfoCommand(const char* /*args*/) +{ + uint32 PlayersNum = sWorld.GetPlayerCount(); + uint32 MaxPlayersNum = sWorld.GetMaxPlayerCount(); + uint32 activeClientsNum = sWorld.GetActiveSessionCount(); + uint32 queuedClientsNum = sWorld.GetQueuedSessionCount(); + uint32 maxActiveClientsNum = sWorld.GetMaxActiveSessionCount(); + uint32 maxQueuedClientsNum = sWorld.GetMaxQueuedSessionCount(); + std::string uptime = secsToTimeString(sWorld.GetUptime()); + uint32 updateTime = sWorld.GetUpdateTime(); + + PSendSysMessage(_FULLVERSION); + //if (m_session) + // full = _FULLVERSION(REVISION_DATE,REVISION_TIME,"|cffffffff|Hurl:" REVISION_ID "|h" REVISION_ID "|h|r"); + //else + // full = _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_ID); + + //SendSysMessage(full); + //PSendSysMessage(LANG_USING_WORLD_DB,sWorld.GetDBVersion()); + //PSendSysMessage(LANG_USING_EVENT_AI,sWorld.GetCreatureEventAIVersion()); + PSendSysMessage(LANG_CONNECTED_PLAYERS, PlayersNum, MaxPlayersNum); + PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); + PSendSysMessage(LANG_UPTIME, uptime.c_str()); + PSendSysMessage("Update time diff: %u.", updateTime); + + return true; +} + +bool ChatHandler::HandleDismountCommand(const char* /*args*/) +{ + //If player is not mounted, so go out :) + if (!m_session->GetPlayer()->IsMounted()) + { + SendSysMessage(LANG_CHAR_NON_MOUNTED); + SetSentErrorMessage(true); + return false; + } + + if (m_session->GetPlayer()->isInFlight()) + { + SendSysMessage(LANG_YOU_IN_FLIGHT); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->Unmount(); + m_session->GetPlayer()->RemoveAurasByType(SPELL_AURA_MOUNTED); + return true; +} + +bool ChatHandler::HandleSaveCommand(const char* /*args*/) +{ + Player *player=m_session->GetPlayer(); + + // save GM account without delay and output message (testing, etc) + if (m_session->GetSecurity() > SEC_PLAYER) + { + player->SaveToDB(); + SendSysMessage(LANG_PLAYER_SAVED); + return true; + } + + // save or plan save after 20 sec (logout delay) if current next save time more this value and _not_ output any messages to prevent cheat planning + uint32 save_interval = sWorld.getConfig(CONFIG_INTERVAL_SAVE); + if ((save_interval == 0 || save_interval > 20*IN_MILISECONDS && player->GetSaveTimer() <= save_interval - 20*IN_MILISECONDS)) + player->SaveToDB(); + + return true; +} + +bool ChatHandler::HandleGMListIngameCommand(const char* /*args*/) +{ + bool first = true; + + ObjectAccessor::Guard guard(*HashMapHolder::GetLock()); + HashMapHolder::MapType &m = ObjectAccessor::Instance().GetPlayers(); + for (HashMapHolder::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) + { + AccountTypes itr_sec = itr->second->GetSession()->GetSecurity(); + if ((itr->second->isGameMaster() || (itr_sec > SEC_PLAYER && itr_sec <= sWorld.getConfig(CONFIG_GM_LEVEL_IN_GM_LIST))) && + (!m_session || itr->second->IsVisibleGloballyFor(m_session->GetPlayer()))) + { + if (first) + { + SendSysMessage(LANG_GMS_ON_SRV); + first = false; + } + + SendSysMessage(GetNameLink(itr->second).c_str()); + } + } + + if (first) + SendSysMessage(LANG_GMS_NOT_LOGGED); + + return true; +} + +bool ChatHandler::HandleAccountPasswordCommand(const char* args) +{ + if (!*args) + return false; + + char *old_pass = strtok ((char*)args, " "); + char *new_pass = strtok (NULL, " "); + char *new_pass_c = strtok (NULL, " "); + + if (!old_pass || !new_pass || !new_pass_c) + return false; + + std::string password_old = old_pass; + std::string password_new = new_pass; + std::string password_new_c = new_pass_c; + + if (strcmp(new_pass, new_pass_c) != 0) + { + SendSysMessage (LANG_NEW_PASSWORDS_NOT_MATCH); + SetSentErrorMessage (true); + return false; + } + + if (!accmgr.CheckPassword (m_session->GetAccountId(), password_old)) + { + SendSysMessage (LANG_COMMAND_WRONGOLDPASSWORD); + SetSentErrorMessage (true); + return false; + } + + AccountOpResult result = accmgr.ChangePassword(m_session->GetAccountId(), password_new); + + switch(result) + { + case AOR_OK: + SendSysMessage(LANG_COMMAND_PASSWORD); + break; + case AOR_PASS_TOO_LONG: + SendSysMessage(LANG_PASSWORD_TOO_LONG); + SetSentErrorMessage(true); + return false; + case AOR_NAME_NOT_EXIST: // not possible case, don't want get account name for output + default: + SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleAccountAddonCommand(const char* args) +{ + if (!*args) + return false; + + char *szExp = strtok((char*)args," "); + + uint32 account_id = m_session->GetAccountId(); + + int expansion=atoi(szExp); //get int anyway (0 if error) + if (expansion < 0 || expansion > sWorld.getConfig(CONFIG_EXPANSION)) + return false; + + // No SQL injection + LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'", expansion, account_id); + PSendSysMessage(LANG_ACCOUNT_ADDON, expansion); + return true; +} + +bool ChatHandler::HandleAccountLockCommand(const char* args) +{ + if (!*args) + { + SendSysMessage(LANG_USE_BOL); + return true; + } + + std::string argstr = (char*)args; + if (argstr == "on") + { + LoginDatabase.PExecute("UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId()); + PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); + return true; + } + + if (argstr == "off") + { + LoginDatabase.PExecute("UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId()); + PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); + return true; + } + + SendSysMessage(LANG_USE_BOL); + return true; +} + +/// Display the 'Message of the day' for the realm +bool ChatHandler::HandleServerMotdCommand(const char* /*args*/) +{ + PSendSysMessage(LANG_MOTD_CURRENT, sWorld.GetMotd()); + return true; +} + diff --git a/src/server/game/Chat/Commands/Level1.cpp b/src/server/game/Chat/Commands/Level1.cpp new file mode 100644 index 00000000000..11189d519a0 --- /dev/null +++ b/src/server/game/Chat/Commands/Level1.cpp @@ -0,0 +1,2960 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "AccountMgr.h" +#include "Opcodes.h" +#include "Chat.h" +#include "Log.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "Language.h" +#include "CellImpl.h" +#include "InstanceSaveMgr.h" +#include "Util.h" + +#ifdef _DEBUG_VMAPS +#include "VMapFactory.h" +#endif + +//-----------------------Npc Commands----------------------- +bool ChatHandler::HandleNpcSayCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterSay(args, LANG_UNIVERSAL, 0); + + // make some emotes + char lastchar = args[strlen(args) - 1]; + switch(lastchar) + { + case '?': pCreature->HandleEmoteCommand(EMOTE_ONESHOT_QUESTION); break; + case '!': pCreature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); break; + default: pCreature->HandleEmoteCommand(EMOTE_ONESHOT_TALK); break; + } + + return true; +} + +bool ChatHandler::HandleNpcYellCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterYell(args, LANG_UNIVERSAL, 0); + + // make an emote + pCreature->HandleEmoteCommand(EMOTE_ONESHOT_SHOUT); + + return true; +} + +//show text emote by creature in chat +bool ChatHandler::HandleNpcTextEmoteCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->MonsterTextEmote(args, 0); + + return true; +} + +// make npc whisper to player +bool ChatHandler::HandleNpcWhisperCommand(const char* args) +{ + if (!*args) + return false; + + char* receiver_str = strtok((char*)args, " "); + char* text = strtok(NULL, ""); + + uint64 guid = m_session->GetPlayer()->GetSelection(); + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(guid); + + if (!pCreature || !receiver_str || !text) + { + return false; + } + + uint64 receiver_guid= atol(receiver_str); + + // check online security + if (HasLowerSecurity(objmgr.GetPlayer(receiver_guid), 0)) + return false; + + pCreature->MonsterWhisper(text,receiver_guid); + + return true; +} +//---------------------------------------------------------- + +bool ChatHandler::HandleNameAnnounceCommand(const char* args) +{ + WorldPacket data; + if (!*args) + return false; + + sWorld.SendWorldText(LANG_ANNOUNCE_COLOR, m_session->GetPlayer()->GetName(), args); + return true; +} + +bool ChatHandler::HandleGMNameAnnounceCommand(const char* args) +{ + WorldPacket data; + if (!*args) + return false; + + sWorld.SendGMText(LANG_GM_ANNOUNCE_COLOR, m_session->GetPlayer()->GetName(), args); + return true; +} + +// global announce +bool ChatHandler::HandleAnnounceCommand(const char* args) +{ + if (!*args) + return false; + + sWorld.SendWorldText(LANG_SYSTEMMESSAGE,args); + return true; +} + +// announce to logged in GMs +bool ChatHandler::HandleGMAnnounceCommand(const char* args) +{ + if (!*args) + return false; + + sWorld.SendGMText(LANG_GM_BROADCAST,args); + return true; +} + +//notification player at the screen +bool ChatHandler::HandleNotifyCommand(const char* args) +{ + if (!*args) + return false; + + std::string str = GetTrinityString(LANG_GLOBAL_NOTIFY); + str += args; + + WorldPacket data(SMSG_NOTIFICATION, (str.size()+1)); + data << str; + sWorld.SendGlobalMessage(&data); + + return true; +} + +//notification GM at the screen +bool ChatHandler::HandleGMNotifyCommand(const char* args) +{ + if (!*args) + return false; + + std::string str = GetTrinityString(LANG_GM_NOTIFY); + str += args; + + WorldPacket data(SMSG_NOTIFICATION, (str.size()+1)); + data << str; + sWorld.SendGlobalGMMessage(&data); + + return true; +} + +//Enable\Dissable GM Mode +bool ChatHandler::HandleGMCommand(const char* args) +{ + if (!*args) + { + if (m_session->GetPlayer()->isGameMaster()) + m_session->SendNotification(LANG_GM_ON); + else + m_session->SendNotification(LANG_GM_OFF); + return true; + } + + std::string argstr = (char*)args; + + if (argstr == "on") + { + m_session->GetPlayer()->SetGameMaster(true); + m_session->SendNotification(LANG_GM_ON); + m_session->GetPlayer()->UpdateTriggerVisibility(); + #ifdef _DEBUG_VMAPS + VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); + vMapManager->processCommand("stoplog"); + #endif + return true; + } + + if (argstr == "off") + { + m_session->GetPlayer()->SetGameMaster(false); + m_session->SendNotification(LANG_GM_OFF); + m_session->GetPlayer()->UpdateTriggerVisibility(); + #ifdef _DEBUG_VMAPS + VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); + vMapManager->processCommand("startlog"); + #endif + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +// Enables or disables hiding of the staff badge +bool ChatHandler::HandleGMChatCommand(const char* args) +{ + if (!*args) + { + if (m_session->GetPlayer()->isGMChat()) + m_session->SendNotification(LANG_GM_CHAT_ON); + else + m_session->SendNotification(LANG_GM_CHAT_OFF); + return true; + } + + std::string argstr = (char*)args; + + if (argstr == "on") + { + m_session->GetPlayer()->SetGMChat(true); + m_session->SendNotification(LANG_GM_CHAT_ON); + return true; + } + + if (argstr == "off") + { + m_session->GetPlayer()->SetGMChat(false); + m_session->SendNotification(LANG_GM_CHAT_OFF); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +std::string ChatHandler::PGetParseString(int32 entry, ...) +{ + const char *format = GetTrinityString(entry); + va_list ap; + char str [1024]; + va_start(ap, entry); + vsnprintf(str,1024,format, ap); + va_end(ap); + return (std::string)str; +} + +bool ChatHandler::HandleGMTicketListCommand(const char* /*args*/) +{ + SendSysMessage(LANG_COMMAND_TICKETSHOWLIST); + for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) + { + if ((*itr)->closed != 0) + continue; + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + SendSysMessage(ss.str().c_str()); + } + return true; +} + +bool ChatHandler::HandleGMTicketListOnlineCommand(const char* /*args*/) +{ + SendSysMessage(LANG_COMMAND_TICKETSHOWONLINELIST); + for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) + { + if ((*itr)->closed != 0 || !objmgr.GetPlayer((*itr)->playerGuid)) + continue; + + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + SendSysMessage(ss.str().c_str()); + } + return true; +} + +bool ChatHandler::HandleGMTicketListClosedCommand(const char* /*args*/) +{ + SendSysMessage(LANG_COMMAND_TICKETSHOWCLOSEDLIST); + for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) + { + if ((*itr)->closed == 0) + continue; + + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + SendSysMessage(ss.str().c_str()); + } + return true; +} + +bool ChatHandler::HandleGMTicketGetByIdCommand(const char* args) +{ + if (!*args) + return false; + + uint64 tguid = atoi(args); + GM_Ticket *ticket = objmgr.GetGMTicket(tguid); + if (!ticket || ticket->closed != 0) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + ss << PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, ticket->message.c_str()); + if (ticket->comment != "") + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, ticket->comment.c_str()); + } + SendSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleGMTicketGetByNameCommand(const char* args) +{ + if (!*args) + return false; + + std::string name = (char*)args; + normalizePlayerName(name); + + Player *plr = objmgr.GetPlayer(name.c_str()); + if (!plr) + { + SendSysMessage(LANG_NO_PLAYERS_FOUND); + return true; + } + + GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(plr->GetGUID()); + if (!ticket) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + std::string gmname; + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str()); + if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + ss << PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, ticket->message.c_str()); + if (ticket->comment != "") + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, ticket->comment.c_str()); + } + SendSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleGMTicketCloseByIdCommand(const char* args) +{ + if (!*args) + return false; + + uint64 tguid = atoi(args); + GM_Ticket *ticket = objmgr.GetGMTicket(tguid); + if (!ticket || ticket->closed != 0) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + if (ticket && ticket->assignedToGM != 0 && ticket->assignedToGM != m_session->GetPlayer()->GetGUID()) + { + PSendSysMessage(LANG_COMMAND_TICKETCANNOTCLOSE, ticket->guid); + return true; + } + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETCLOSED, m_session->GetPlayer()->GetName()); + SendGlobalGMSysMessage(ss.str().c_str()); + Player *plr = objmgr.GetPlayer(ticket->playerGuid); + objmgr.RemoveGMTicket(ticket, m_session->GetPlayer()->GetGUID()); + + if (!plr || !plr->IsInWorld()) + return true; + + // send abandon ticket + WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); + data << uint32(9); + plr->GetSession()->SendPacket(&data); + return true; +} + +bool ChatHandler::HandleGMTicketAssignToCommand(const char* args) +{ + if (!*args) + return false; + + char* tguid = strtok((char*)args, " "); + uint64 ticketGuid = atoi(tguid); + char* targetgm = strtok(NULL, " "); + + if (!targetgm) + return false; + + std::string targm = targetgm; + if (!normalizePlayerName(targm)) + return false; + + Player *cplr = m_session->GetPlayer(); + GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); + + if (!ticket || ticket->closed != 0) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + uint64 tarGUID = objmgr.GetPlayerGUIDByName(targm.c_str()); + uint64 accid = objmgr.GetPlayerAccountIdByGUID(tarGUID); + uint32 gmlevel = accmgr.GetSecurity(accid, realmID); + + if (!tarGUID || gmlevel == SEC_PLAYER) + { + SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); + return true; + } + + if (ticket->assignedToGM == tarGUID) + { + PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->guid); + return true; + } + + std::string gmname; + objmgr.GetPlayerNameByGUID(tarGUID, gmname); + if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID()) + { + PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid, gmname.c_str()); + return true; + } + + ticket->assignedToGM = tarGUID; + objmgr.AddOrUpdateGMTicket(*ticket); + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + SendGlobalGMSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args) +{ + if (!*args) + return false; + + uint64 ticketGuid = atoi(args); + Player *cplr = m_session->GetPlayer(); + GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); + + if (!ticket|| ticket->closed != 0) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + if (ticket->assignedToGM == 0) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTASSIGNED, ticket->guid); + return true; + } + + std::string gmname; + objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname); + Player *plr = objmgr.GetPlayer(ticket->assignedToGM); + if (plr && plr->IsInWorld() && plr->GetSession()->GetSecurity() > cplr->GetSession()->GetSecurity()) + { + SendSysMessage(LANG_COMMAND_TICKETUNASSIGNSECURITY); + return true; + } + + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETLISTUNASSIGNED, cplr->GetName()); + SendGlobalGMSysMessage(ss.str().c_str()); + ticket->assignedToGM = 0; + objmgr.AddOrUpdateGMTicket(*ticket); + return true; +} + +bool ChatHandler::HandleGMTicketCommentCommand(const char* args) +{ + if (!*args) + return false; + + char* tguid = strtok((char*)args, " "); + uint64 ticketGuid = atoi(tguid); + char* comment = strtok(NULL, "\n"); + + if (!comment) + return false; + + Player *cplr = m_session->GetPlayer(); + GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); + + if (!ticket || ticket->closed != 0) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID()) + { + PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid); + return true; + } + + std::string gmname; + objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname); + ticket->comment = comment; + objmgr.AddOrUpdateGMTicket(*ticket); + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) + { + ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); + } + ss << PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, cplr->GetName(), ticket->comment.c_str()); + SendGlobalGMSysMessage(ss.str().c_str()); + return true; +} + +bool ChatHandler::HandleGMTicketDeleteByIdCommand(const char* args) +{ + if (!*args) + return false; + uint64 ticketGuid = atoi(args); + GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); + + if (!ticket) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + if (ticket->closed == 0) + { + SendSysMessage(LANG_COMMAND_TICKETCLOSEFIRST); + return true; + } + + std::stringstream ss; + ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); + ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); + ss << PGetParseString(LANG_COMMAND_TICKETDELETED, m_session->GetPlayer()->GetName()); + SendGlobalGMSysMessage(ss.str().c_str()); + Player *plr = objmgr.GetPlayer(ticket->playerGuid); + objmgr.RemoveGMTicket(ticket, -1, true); + if (plr && plr->IsInWorld()) + { + // Force abandon ticket + WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); + data << uint32(9); + plr->GetSession()->SendPacket(&data); + } + + ticket = NULL; + return true; +} + +bool ChatHandler::HandleGMTicketReloadCommand(const char*) +{ + objmgr.LoadGMTickets(); + return true; +} + +//Enable\Dissable Invisible mode +bool ChatHandler::HandleGMVisibleCommand(const char* args) +{ + if (!*args) + { + PSendSysMessage(LANG_YOU_ARE, m_session->GetPlayer()->isGMVisible() ? GetTrinityString(LANG_VISIBLE) : GetTrinityString(LANG_INVISIBLE)); + return true; + } + + std::string argstr = (char*)args; + + if (argstr == "on") + { + m_session->GetPlayer()->SetGMVisible(true); + m_session->SendNotification(LANG_INVISIBLE_VISIBLE); + return true; + } + + if (argstr == "off") + { + m_session->SendNotification(LANG_INVISIBLE_INVISIBLE); + m_session->GetPlayer()->SetGMVisible(false); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +bool ChatHandler::HandleGPSCommand(const char* args) +{ + WorldObject *obj = NULL; + if (*args) + { + uint64 guid = extractGuidFromLink((char*)args); + if (guid) + obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + + if (!obj) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + obj = getSelectedUnit(); + + if (!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + } + CellPair cell_val = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + Cell cell(cell_val); + + uint32 zone_id, area_id; + obj->GetZoneAndAreaId(zone_id,area_id); + + MapEntry const* mapEntry = sMapStore.LookupEntry(obj->GetMapId()); + AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zone_id); + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(area_id); + + float zone_x = obj->GetPositionX(); + float zone_y = obj->GetPositionY(); + + Map2ZoneCoordinates(zone_x,zone_y,zone_id); + + Map const *map = obj->GetMap(); + float ground_z = map->GetHeight(obj->GetPositionX(), obj->GetPositionY(), MAX_HEIGHT); + float floor_z = map->GetHeight(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ()); + + GridPair p = Trinity::ComputeGridPair(obj->GetPositionX(), obj->GetPositionY()); + + int gx=63-p.x_coord; + int gy=63-p.y_coord; + + uint32 have_map = Map::ExistMap(obj->GetMapId(),gx,gy) ? 1 : 0; + uint32 have_vmap = Map::ExistVMap(obj->GetMapId(),gx,gy) ? 1 : 0; + + if(have_vmap) + { + if(map->IsOutdoors(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ())) + PSendSysMessage("You are outdoors"); + else + PSendSysMessage("You are indoor"); + } + else PSendSysMessage("no VMAP available for area info"); + + PSendSysMessage(LANG_MAP_POSITION, + obj->GetMapId(), (mapEntry ? mapEntry->name[GetSessionDbcLocale()] : ""), + zone_id, (zoneEntry ? zoneEntry->area_name[GetSessionDbcLocale()] : ""), + area_id, (areaEntry ? areaEntry->area_name[GetSessionDbcLocale()] : ""), + obj->GetPhaseMask(), + obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), + cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), + zone_x, zone_y, ground_z, floor_z, have_map, have_vmap); + + sLog.outDebug("Player %s GPS call for %s '%s' (%s: %u):", + m_session ? GetNameLink().c_str() : GetTrinityString(LANG_CONSOLE_COMMAND), + (obj->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), obj->GetName(), + (obj->GetTypeId() == TYPEID_PLAYER ? "GUID" : "Entry"), (obj->GetTypeId() == TYPEID_PLAYER ? obj->GetGUIDLow(): obj->GetEntry())); + sLog.outDebug(GetTrinityString(LANG_MAP_POSITION), + obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : ""), + zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : ""), + area_id, (areaEntry ? areaEntry->area_name[sWorld.GetDefaultDbcLocale()] : ""), + obj->GetPhaseMask(), + obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), + cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), + zone_x, zone_y, ground_z, floor_z, have_map, have_vmap); + + LiquidData liquid_status; + ZLiquidStatus res = map->getLiquidStatus(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), MAP_ALL_LIQUIDS, &liquid_status); + if (res) + { + PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.type, res); + } + return true; +} + +//Summon Player +bool ChatHandler::HandleNamegoCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + Player* _player = m_session->GetPlayer(); + if (target == _player || target_guid == _player->GetGUID()) + { + PSendSysMessage(LANG_CANT_TELEPORT_SELF); + SetSentErrorMessage(true); + return false; + } + + if (target) + { + std::string nameLink = playerLink(target_name); + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + if (target->IsBeingTeleported()) + { + PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + Map* pMap = m_session->GetPlayer()->GetMap(); + + if (pMap->IsBattleGroundOrArena()) + { + // only allow if gm mode is on + if (!target->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + // if both players are in different bgs + else if (target->GetBattleGroundId() && m_session->GetPlayer()->GetBattleGroundId() != target->GetBattleGroundId()) + { + target->LeaveBattleground(false); // Note: should be changed so target gets no Deserter debuff + //PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,nameLink.c_str()); + //SetSentErrorMessage(true); + //return false; + } + // all's well, set bg id + // when porting out from the bg, it will be reset to 0 + target->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId(), m_session->GetPlayer()->GetBattleGroundTypeId()); + // remember current position as entry point for return at bg end teleportation + if (!target->GetMap()->IsBattleGroundOrArena()) + target->SetBattleGroundEntryPoint(); + } + else if (pMap->IsDungeon()) + { + Map* cMap = target->GetMap(); + if (cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId()) + { + target->UnbindInstance(pMap->GetInstanceId(), target->GetDungeonDifficulty(), true); + // cannot summon from instance to instance + //PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); + //SetSentErrorMessage(true); + //return false; + } + + // we are in instance, and can summon only player in our group with us as lead + if (!m_session->GetPlayer()->GetGroup() || !target->GetGroup() || + (target->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || + (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID())) + // the last check is a bit excessive, but let it be, just in case + { + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),""); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(_player->GetName()).c_str()); + + // stop flight if need + if (target->isInFlight()) + { + target->GetMotionMaster()->MovementExpired(); + target->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + target->SaveRecallPosition(); + + // before GM + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,target->GetObjectSize()); + target->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,target->GetOrientation()); + target->SetPhaseMask(m_session->GetPlayer()->GetPhaseMask(), true); + } + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),GetTrinityString(LANG_OFFLINE)); + + // in point where GM stay + Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(), + m_session->GetPlayer()->GetPositionX(), + m_session->GetPlayer()->GetPositionY(), + m_session->GetPlayer()->GetPositionZ(), + m_session->GetPlayer()->GetOrientation(), + m_session->GetPlayer()->GetZoneId(), + target_guid); + } + + return true; +} + +//Teleport to Player +bool ChatHandler::HandleGonameCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + Player* _player = m_session->GetPlayer(); + if (target == _player || target_guid == _player->GetGUID()) + { + SendSysMessage(LANG_CANT_TELEPORT_SELF); + SetSentErrorMessage(true); + return false; + } + + if (target) + { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + std::string chrNameLink = playerLink(target_name); + + Map* cMap = target->GetMap(); + if (cMap->IsBattleGroundOrArena()) + { + // only allow if gm mode is on + if (!_player->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + // if both players are in different bgs + else if (_player->GetBattleGroundId() && _player->GetBattleGroundId() != target->GetBattleGroundId()) + { + _player->LeaveBattleground(false); // Note: should be changed so _player gets no Deserter debuff + //PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chrNameLink.c_str()); + //SetSentErrorMessage(true); + //return false; + } + // all's well, set bg id + // when porting out from the bg, it will be reset to 0 + _player->SetBattleGroundId(target->GetBattleGroundId(), target->GetBattleGroundTypeId()); + // remember current position as entry point for return at bg end teleportation + if (!_player->GetMap()->IsBattleGroundOrArena()) + _player->SetBattleGroundEntryPoint(); + } + else if (cMap->IsDungeon()) + { + //Map* pMap = _player->GetMap(); + + // we have to go to instance, and can go to player only if: + // 1) we are in his group (either as leader or as member) + // 2) we are not bound to any group and have GM mode on + if (_player->GetGroup()) + { + // we are in group, we can go only if we are in the player group + if (_player->GetGroup() != target->GetGroup()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + } + else + { + // we are not in group, let's verify our GM mode + if (!_player->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + // if the player or the player's group is bound to another instance + // the player will not be bound to another one + InstancePlayerBind *pBind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty(cMap->IsRaid())); + if (!pBind) + { + Group *group = _player->GetGroup(); + // if no bind exists, create a solo bind + InstanceGroupBind *gBind = group ? group->GetBoundInstance(target) : NULL; // if no bind exists, create a solo bind + if (!gBind) + if (InstanceSave *save = sInstanceSaveManager.GetInstanceSave(target->GetInstanceId())) + _player->BindToInstance(save, !save->CanReset()); + } + + if (cMap->IsRaid()) + _player->SetRaidDifficulty(target->GetRaidDifficulty()); + else + _player->SetDungeonDifficulty(target->GetDungeonDifficulty()); + } + + PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); + //if (needReportToTarget(target)) + // ChatHandler(target).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str()); + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + // to point to see at target with same orientation + float x,y,z; + target->GetContactPoint(_player,x,y,z); + + _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); + _player->SetPhaseMask(target->GetPhaseMask(), true); + } + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); + + // to point where player stay (if loaded) + float x,y,z,o; + uint32 map; + bool in_flight; + if (!Player::LoadPositionFromDB(map,x,y,z,o,in_flight,target_guid)) + return false; + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(map, x, y, z,_player->GetOrientation()); + } + + return true; +} + +// Teleport player to last position +bool ChatHandler::HandleRecallCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + if (target->IsBeingTeleported()) + { + PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(target).c_str()); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (target->isInFlight()) + { + target->GetMotionMaster()->MovementExpired(); + target->CleanupAfterTaxiFlight(); + } + + target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO); + return true; +} + +//Edit Player HP +bool ChatHandler::HandleModifyHPCommand(const char* args) +{ + if (!*args) + return false; + + int32 hp = atoi((char*)args); + int32 hpm = atoi((char*)args); + + if (hp < 1 || hpm < 1 || hpm < hp) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_HP, GetNameLink(chr).c_str(), hp, hpm); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetNameLink().c_str(), hp, hpm); + + chr->SetMaxHealth(hpm); + chr->SetHealth(hp); + + return true; +} + +//Edit Player Mana +bool ChatHandler::HandleModifyManaCommand(const char* args) +{ + if (!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + int32 mana = atoi((char*)args); + int32 manam = atoi((char*)args); + + if (mana <= 0 || manam <= 0 || manam < mana) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_MANA, GetNameLink(chr).c_str(), mana, manam); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetNameLink().c_str(), mana, manam); + + chr->SetMaxPower(POWER_MANA,manam); + chr->SetPower(POWER_MANA, mana); + + return true; +} + +//Edit Player Energy +bool ChatHandler::HandleModifyEnergyCommand(const char* args) +{ + if (!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + + int32 energy = atoi((char*)args)*10; + int32 energym = atoi((char*)args)*10; + + if (energy <= 0 || energym <= 0 || energym < energy) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (!chr) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_ENERGY, GetNameLink(chr).c_str(), energy/10, energym/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetNameLink().c_str(), energy/10, energym/10); + + chr->SetMaxPower(POWER_ENERGY,energym); + chr->SetPower(POWER_ENERGY, energy); + + sLog.outDetail(GetTrinityString(LANG_CURRENT_ENERGY),chr->GetMaxPower(POWER_ENERGY)); + + return true; +} + +//Edit Player Rage +bool ChatHandler::HandleModifyRageCommand(const char* args) +{ + if (!*args) + return false; + + // char* pmana = strtok((char*)args, " "); + // if (!pmana) + // return false; + + // char* pmanaMax = strtok(NULL, " "); + // if (!pmanaMax) + // return false; + + // int32 manam = atoi(pmanaMax); + // int32 mana = atoi(pmana); + + int32 rage = atoi((char*)args)*10; + int32 ragem = atoi((char*)args)*10; + + if (rage <= 0 || ragem <= 0 || ragem < rage) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_RAGE, GetNameLink(chr).c_str(), rage/10, ragem/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetNameLink().c_str(), rage/10, ragem/10); + + chr->SetMaxPower(POWER_RAGE,ragem); + chr->SetPower(POWER_RAGE, rage); + + return true; +} + +// Edit Player Runic Power +bool ChatHandler::HandleModifyRunicPowerCommand(const char* args) +{ + if (!*args) + return false; + + int32 rune = atoi((char*)args)*10; + int32 runem = atoi((char*)args)*10; + + if (rune <= 0 || runem <= 0 || runem < rune) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_RUNIC_POWER, GetNameLink(chr).c_str(), rune/10, runem/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_RUNIC_POWER_CHANGED, GetNameLink().c_str(), rune/10, runem/10); + + chr->SetMaxPower(POWER_RUNIC_POWER,runem); + chr->SetPower(POWER_RUNIC_POWER, rune); + + return true; +} + +//Edit Player Faction +bool ChatHandler::HandleModifyFactionCommand(const char* args) +{ + if (!*args) + return false; + + char* pfactionid = extractKeyFromLink((char*)args,"Hfaction"); + + Creature* chr = getSelectedCreature(); + if (!chr) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!pfactionid) + { + if (chr) + { + uint32 factionid = chr->getFaction(); + uint32 flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS); + uint32 npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS); + uint32 dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS); + PSendSysMessage(LANG_CURRENT_FACTION,chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); + } + return true; + } + + if (!chr) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + uint32 factionid = atoi(pfactionid); + uint32 flag; + + char *pflag = strtok(NULL, " "); + if (!pflag) + flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS); + else + flag = atoi(pflag); + + char* pnpcflag = strtok(NULL, " "); + + uint32 npcflag; + if (!pnpcflag) + npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS); + else + npcflag = atoi(pnpcflag); + + char* pdyflag = strtok(NULL, " "); + + uint32 dyflag; + if (!pdyflag) + dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS); + else + dyflag = atoi(pdyflag); + + if (!sFactionTemplateStore.LookupEntry(factionid)) + { + PSendSysMessage(LANG_WRONG_FACTION, factionid); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_FACTION, chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); + + chr->setFaction(factionid); + chr->SetUInt32Value(UNIT_FIELD_FLAGS,flag); + chr->SetUInt32Value(UNIT_NPC_FLAGS,npcflag); + chr->SetUInt32Value(UNIT_DYNAMIC_FLAGS,dyflag); + + return true; +} + +//Edit Player Spell +bool ChatHandler::HandleModifySpellCommand(const char* args) +{ + if (!*args) return false; + char* pspellflatid = strtok((char*)args, " "); + if (!pspellflatid) + return false; + + char* pop = strtok(NULL, " "); + if (!pop) + return false; + + char* pval = strtok(NULL, " "); + if (!pval) + return false; + + uint16 mark; + + char* pmark = strtok(NULL, " "); + + uint8 spellflatid = atoi(pspellflatid); + uint8 op = atoi(pop); + uint16 val = atoi(pval); + if (!pmark) + mark = 65535; + else + mark = atoi(pmark); + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetNameLink().c_str(), spellflatid, val, mark); + + WorldPacket data(SMSG_SET_FLAT_SPELL_MODIFIER, (1+1+2+2)); + data << uint8(spellflatid); + data << uint8(op); + data << uint16(val); + data << uint16(mark); + chr->GetSession()->SendPacket(&data); + + return true; +} + +//Edit Player TP +bool ChatHandler::HandleModifyTalentCommand (const char* args) +{ + if (!*args) + return false; + + int tp = atoi((char*)args); + if (tp < 0) + return false; + + Unit* target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (target->GetTypeId() == TYPEID_PLAYER) + { + // check online security + if (HasLowerSecurity((Player*)target, 0)) + return false; + target->ToPlayer()->SetFreeTalentPoints(tp); + target->ToPlayer()->SendTalentsInfoData(false); + return true; + } + else if (target->ToCreature()->isPet()) + { + Unit *owner = target->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet *)target)->IsPermanentPetFor(owner->ToPlayer())) + { + // check online security + if (HasLowerSecurity((Player*)owner, 0)) + return false; + ((Pet *)target)->SetFreeTalentPoints(tp); + owner->ToPlayer()->SendTalentsInfoData(true); + return true; + } + } + + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; +} + +//Enable On\OFF all taxi paths +bool ChatHandler::HandleTaxiCheatCommand(const char* args) +{ + if (!*args) + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + std::string argstr = (char*)args; + + Player *chr = getSelectedPlayer(); + if (!chr) + { + chr=m_session->GetPlayer(); + } + + // check online security + else if (HasLowerSecurity(chr, 0)) + return false; + + if (argstr == "on") + { + chr->SetTaxiCheater(true); + PSendSysMessage(LANG_YOU_GIVE_TAXIS, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetNameLink().c_str()); + return true; + } + + if (argstr == "off") + { + chr->SetTaxiCheater(false); + PSendSysMessage(LANG_YOU_REMOVE_TAXIS, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetNameLink().c_str()); + + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +//Edit Player Aspeed +bool ChatHandler::HandleModifyASpeedCommand(const char* args) +{ + if (!*args) + return false; + + float ASpeed = (float)atof((char*)args); + + if (ASpeed > 50.0f || ASpeed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + + if (chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetNameLink().c_str(), ASpeed); + + chr->SetSpeed(MOVE_WALK, ASpeed,true); + chr->SetSpeed(MOVE_RUN, ASpeed,true); + chr->SetSpeed(MOVE_SWIM, ASpeed,true); + //chr->SetSpeed(MOVE_TURN, ASpeed,true); + chr->SetSpeed(MOVE_FLIGHT, ASpeed,true); + return true; +} + +//Edit Player Speed +bool ChatHandler::HandleModifySpeedCommand(const char* args) +{ + if (!*args) + return false; + + float Speed = (float)atof((char*)args); + + if (Speed > 50.0f || Speed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + + if (chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetNameLink().c_str(), Speed); + + chr->SetSpeed(MOVE_RUN,Speed,true); + + return true; +} + +//Edit Player Swim Speed +bool ChatHandler::HandleModifySwimCommand(const char* args) +{ + if (!*args) + return false; + + float Swim = (float)atof((char*)args); + + if (Swim > 50.0f || Swim < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + + if (chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chrNameLink.c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetNameLink().c_str(), Swim); + + chr->SetSpeed(MOVE_SWIM,Swim,true); + + return true; +} + +//Edit Player Walk Speed +bool ChatHandler::HandleModifyBWalkCommand(const char* args) +{ + if (!*args) + return false; + + float BSpeed = (float)atof((char*)args); + + if (BSpeed > 50.0f || BSpeed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + + if (chr->isInFlight()) + { + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chrNameLink.c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetNameLink().c_str(), BSpeed); + + chr->SetSpeed(MOVE_RUN_BACK,BSpeed,true); + + return true; +} + +//Edit Player Fly +bool ChatHandler::HandleModifyFlyCommand(const char* args) +{ + if (!*args) + return false; + + float FSpeed = (float)atof((char*)args); + + if (FSpeed > 50.0f || FSpeed < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetNameLink().c_str(), FSpeed); + + chr->SetSpeed(MOVE_FLIGHT,FSpeed,true); + + return true; +} + +//Edit Player Scale +bool ChatHandler::HandleModifyScaleCommand(const char* args) +{ + if (!*args) + return false; + + float Scale = (float)atof((char*)args); + if (Scale > 10.0f || Scale < 0.1f) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetNameLink().c_str(), Scale); + + chr->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale); + + return true; +} + +//Enable Player mount +bool ChatHandler::HandleModifyMountCommand(const char* args) +{ + if (!*args) + return false; + + uint16 mId = 1147; + float speed = (float)15; + uint32 num = 0; + + num = atoi((char*)args); + switch(num) + { + case 1: + mId=14340; + break; + case 2: + mId=4806; + break; + case 3: + mId=6471; + break; + case 4: + mId=12345; + break; + case 5: + mId=6472; + break; + case 6: + mId=6473; + break; + case 7: + mId=10670; + break; + case 8: + mId=10719; + break; + case 9: + mId=10671; + break; + case 10: + mId=10672; + break; + case 11: + mId=10720; + break; + case 12: + mId=14349; + break; + case 13: + mId=11641; + break; + case 14: + mId=12244; + break; + case 15: + mId=12242; + break; + case 16: + mId=14578; + break; + case 17: + mId=14579; + break; + case 18: + mId=14349; + break; + case 19: + mId=12245; + break; + case 20: + mId=14335; + break; + case 21: + mId=207; + break; + case 22: + mId=2328; + break; + case 23: + mId=2327; + break; + case 24: + mId=2326; + break; + case 25: + mId=14573; + break; + case 26: + mId=14574; + break; + case 27: + mId=14575; + break; + case 28: + mId=604; + break; + case 29: + mId=1166; + break; + case 30: + mId=2402; + break; + case 31: + mId=2410; + break; + case 32: + mId=2409; + break; + case 33: + mId=2408; + break; + case 34: + mId=2405; + break; + case 35: + mId=14337; + break; + case 36: + mId=6569; + break; + case 37: + mId=10661; + break; + case 38: + mId=10666; + break; + case 39: + mId=9473; + break; + case 40: + mId=9476; + break; + case 41: + mId=9474; + break; + case 42: + mId=14374; + break; + case 43: + mId=14376; + break; + case 44: + mId=14377; + break; + case 45: + mId=2404; + break; + case 46: + mId=2784; + break; + case 47: + mId=2787; + break; + case 48: + mId=2785; + break; + case 49: + mId=2736; + break; + case 50: + mId=2786; + break; + case 51: + mId=14347; + break; + case 52: + mId=14346; + break; + case 53: + mId=14576; + break; + case 54: + mId=9695; + break; + case 55: + mId=9991; + break; + case 56: + mId=6448; + break; + case 57: + mId=6444; + break; + case 58: + mId=6080; + break; + case 59: + mId=6447; + break; + case 60: + mId=4805; + break; + case 61: + mId=9714; + break; + case 62: + mId=6448; + break; + case 63: + mId=6442; + break; + case 64: + mId=14632; + break; + case 65: + mId=14332; + break; + case 66: + mId=14331; + break; + case 67: + mId=8469; + break; + case 68: + mId=2830; + break; + case 69: + mId=2346; + break; + default: + SendSysMessage(LANG_NO_MOUNT); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_GIVE_MOUNT, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetNameLink().c_str()); + + chr->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); + chr->Mount(mId); + + WorldPacket data(SMSG_FORCE_RUN_SPEED_CHANGE, (8+4+1+4)); + data.append(chr->GetPackGUID()); + data << (uint32)0; + data << (uint8)0; //new 2.1.0 + data << float(speed); + chr->SendMessageToSet(&data, true); + + data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, (8+4+4)); + data.append(chr->GetPackGUID()); + data << (uint32)0; + data << float(speed); + chr->SendMessageToSet(&data, true); + + return true; +} + +//Edit Player money +bool ChatHandler::HandleModifyMoneyCommand(const char* args) +{ + if (!*args) + return false; + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + int32 addmoney = atoi((char*)args); + + uint32 moneyuser = chr->GetMoney(); + + if (addmoney < 0) + { + int32 newmoney = int32(moneyuser) + addmoney; + + sLog.outDetail(GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney); + if (newmoney <= 0) + { + PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetNameLink().c_str()); + + chr->SetMoney(0); + } + else + { + if (newmoney > MAX_MONEY_AMOUNT) + newmoney = MAX_MONEY_AMOUNT; + + PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetNameLink().c_str(), abs(addmoney)); + chr->SetMoney(newmoney); + } + } + else + { + PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetNameLink().c_str(), addmoney); + + if (addmoney >=MAX_MONEY_AMOUNT) + chr->SetMoney(MAX_MONEY_AMOUNT); + else + chr->ModifyMoney(addmoney); + } + + sLog.outDetail(GetTrinityString(LANG_NEW_MONEY), moneyuser, addmoney, chr->GetMoney()); + + return true; +} + +//Edit Unit field +bool ChatHandler::HandleModifyBitCommand(const char* args) +{ + if (!*args) + return false; + + Unit *unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (unit->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity(unit->ToPlayer(), 0)) + return false; + + char* pField = strtok((char*)args, " "); + if (!pField) + return false; + + char* pBit = strtok(NULL, " "); + if (!pBit) + return false; + + uint16 field = atoi(pField); + uint32 bit = atoi(pBit); + + if (field < OBJECT_END || field >= unit->GetValuesCount()) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + if (bit < 1 || bit > 32) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + if (unit->HasFlag(field, (1<<(bit-1)))) + { + unit->RemoveFlag(field, (1<<(bit-1))); + PSendSysMessage(LANG_REMOVE_BIT, bit, field); + } + else + { + unit->SetFlag(field, (1<<(bit-1))); + PSendSysMessage(LANG_SET_BIT, bit, field); + } + return true; +} + +bool ChatHandler::HandleModifyHonorCommand (const char* args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + int32 amount = (uint32)atoi(args); + + target->ModifyHonorPoints(amount); + + PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, GetNameLink(target).c_str(), target->GetHonorPoints()); + + return true; +} + +bool ChatHandler::HandleTeleCommand(const char * args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = extractGameTeleFromLink((char*)args); + + if (!tele) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + + if (_player->isInCombat()) + { + SendSysMessage(LANG_YOU_IN_COMBAT); + SetSentErrorMessage(true); + return false; + } + + MapEntry const * me = sMapStore.LookupEntry(tele->mapId); + if (!me || me->IsBattleGroundOrArena()) + { + SendSysMessage(LANG_CANNOT_TELE_TO_BG); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); + return true; +} + +bool ChatHandler::HandleLookupAreaCommand(const char* args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr (namepart,wnamepart)) + return false; + + bool found = false; + + // converting string that we try to find to lower case + wstrToLower (wnamepart); + + // Search in AreaTable.dbc + for (uint32 areaflag = 0; areaflag < sAreaStore.GetNumRows (); ++areaflag) + { + AreaTableEntry const *areaEntry = sAreaStore.LookupEntry (areaflag); + if (areaEntry) + { + int loc = GetSessionDbcLocale (); + std::string name = areaEntry->area_name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo (name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale ()) + continue; + + name = areaEntry->area_name[loc]; + if (name.empty ()) + continue; + + if (Utf8FitTo (name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send area in "id - [name]" format + std::ostringstream ss; + if (m_session) + ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << " " << localeNames[loc]<< "]|h|r"; + else + ss << areaEntry->ID << " - " << name << " " << localeNames[loc]; + + SendSysMessage (ss.str ().c_str()); + + if (!found) + found = true; + } + } + } + + if (!found) + SendSysMessage (LANG_COMMAND_NOAREAFOUND); + + return true; +} + +//Find tele in game_tele order by name +bool ChatHandler::HandleLookupTeleCommand(const char * args) +{ + if (!*args) + { + SendSysMessage(LANG_COMMAND_TELE_PARAMETER); + SetSentErrorMessage(true); + return false; + } + + char const* str = strtok((char*)args, " "); + if (!str) + return false; + + std::string namepart = str; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + std::ostringstream reply; + + GameTeleMap const & teleMap = objmgr.GetGameTeleMap(); + for (GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr) + { + GameTele const* tele = &itr->second; + + if (tele->wnameLow.find(wnamepart) == std::wstring::npos) + continue; + + if (m_session) + reply << " |cffffffff|Htele:" << itr->first << "|h[" << tele->name << "]|h|r\n"; + else + reply << " " << itr->first << " " << tele->name << "\n"; + } + + if (reply.str().empty()) + SendSysMessage(LANG_COMMAND_TELE_NOLOCATION); + else + PSendSysMessage(LANG_COMMAND_TELE_LOCATION,reply.str().c_str()); + + return true; +} + +//Enable\Dissable accept whispers (for GM) +bool ChatHandler::HandleWhispersCommand(const char* args) +{ + if (!*args) + { + PSendSysMessage(LANG_COMMAND_WHISPERACCEPTING, m_session->GetPlayer()->isAcceptWhispers() ? GetTrinityString(LANG_ON) : GetTrinityString(LANG_OFF)); + return true; + } + + std::string argstr = (char*)args; + // whisper on + if (argstr == "on") + { + m_session->GetPlayer()->SetAcceptWhispers(true); + SendSysMessage(LANG_COMMAND_WHISPERON); + return true; + } + + // whisper off + if (argstr == "off") + { + m_session->GetPlayer()->SetAcceptWhispers(false); + SendSysMessage(LANG_COMMAND_WHISPEROFF); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +//Save all players in the world +bool ChatHandler::HandleSaveAllCommand(const char* /*args*/) +{ + ObjectAccessor::Instance().SaveAllPlayers(); + SendSysMessage(LANG_PLAYERS_SAVED); + return true; +} + +//Send mail by command +bool ChatHandler::HandleSendMailCommand(const char* args) +{ + // format: name "subject text" "mail text" + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char* msgSubject = extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char* msgText = extractQuotedArg(tail2); + if (!msgText) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // from console show not existed sender + MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + MailDraft(subject, text) + .SendMailTo(MailReceiver(target,GUID_LOPART(target_guid)),sender); + + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +// teleport player to given game_tele.entry +bool ChatHandler::HandleTeleNameCommand(const char * args) +{ + char* nameStr; + char* teleStr; + extractOptFirstArg((char*)args,&nameStr,&teleStr); + if (!teleStr) + return false; + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = extractGameTeleFromLink(teleStr); + if (!tele) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + +/* MapEntry const * me = sMapStore.LookupEntry(tele->mapId); + if (!me || me->IsBattleGroundOrArena()) + { + SendSysMessage(LANG_CANNOT_TELE_TO_BG); + SetSentErrorMessage(true); + return false; + } + + Player *chr = objmgr.GetPlayer(name.c_str());*/ + + if (target) + { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + std::string chrNameLink = playerLink(target_name); + + if (target->IsBeingTeleported() == true) + { + PSendSysMessage(LANG_IS_TELEPORTED, chrNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_TELEPORTING_TO, chrNameLink.c_str(),"", tele->name.c_str()); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str()); + + // stop flight if need + if (target->isInFlight()) + { + target->GetMotionMaster()->MovementExpired(); + target->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + target->SaveRecallPosition(); + + target->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation); + } + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_TELEPORTING_TO, nameLink.c_str(), GetTrinityString(LANG_OFFLINE), tele->name.c_str()); + Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation, + MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y,tele->position_z),target_guid); + } + + return true; +} + +//Teleport group to given game_tele.entry +bool ChatHandler::HandleTeleGroupCommand(const char * args) +{ + if (!*args) + return false; + + Player *player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(player, 0)) + return false; + + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = extractGameTeleFromLink((char*)args); + if (!tele) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + + MapEntry const * me = sMapStore.LookupEntry(tele->mapId); + if (!me || me->IsBattleGroundOrArena()) + { + SendSysMessage(LANG_CANNOT_TELE_TO_BG); + SetSentErrorMessage(true); + return false; + } + + std::string nameLink = GetNameLink(player); + + Group *grp = player->GetGroup(); + if (!grp) + { + PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pl = itr->getSource(); + + if (!pl || !pl->GetSession()) + continue; + + // check online security + if (HasLowerSecurity(pl, 0)) + return false; + + std::string plNameLink = GetNameLink(pl); + + if (pl->IsBeingTeleported()) + { + PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); + continue; + } + + PSendSysMessage(LANG_TELEPORTING_TO, plNameLink.c_str(),"", tele->name.c_str()); + if (needReportToTarget(pl)) + ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, nameLink.c_str()); + + // stop flight if need + if (pl->isInFlight()) + { + pl->GetMotionMaster()->MovementExpired(); + pl->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + pl->SaveRecallPosition(); + + pl->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); + } + + return true; +} + +//Summon group of player +bool ChatHandler::HandleGroupgoCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + Group *grp = target->GetGroup(); + + std::string nameLink = GetNameLink(target); + + if (!grp) + { + PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + Map* gmMap = m_session->GetPlayer()->GetMap(); + bool to_instance = gmMap->Instanceable(); + + // we are in instance, and can summon only player in our group with us as lead + if (to_instance && ( + !m_session->GetPlayer()->GetGroup() || (grp->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || + (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()))) + // the last check is a bit excessive, but let it be, just in case + { + SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); + SetSentErrorMessage(true); + return false; + } + + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pl = itr->getSource(); + + if (!pl || pl == m_session->GetPlayer() || !pl->GetSession()) + continue; + + // check online security + if (HasLowerSecurity(pl, 0)) + return false; + + std::string plNameLink = GetNameLink(pl); + + if (pl->IsBeingTeleported() == true) + { + PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + if (to_instance) + { + Map* plMap = pl->GetMap(); + + if (plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId()) + { + // cannot summon from instance to instance + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,plNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(),""); + if (needReportToTarget(pl)) + ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetNameLink().c_str()); + + // stop flight if need + if (pl->isInFlight()) + { + pl->GetMotionMaster()->MovementExpired(); + pl->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + pl->SaveRecallPosition(); + + // before GM + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,pl->GetObjectSize()); + pl->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,pl->GetOrientation()); + } + + return true; +} + +bool ChatHandler::HandleGoTaxinodeCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char* cNodeId = extractKeyFromLink((char*)args,"Htaxinode"); + if (!cNodeId) + return false; + + int32 i_nodeId = atoi(cNodeId); + if (!i_nodeId) + return false; + + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i_nodeId); + if (!node) + { + PSendSysMessage(LANG_COMMAND_GOTAXINODENOTFOUND,i_nodeId); + SetSentErrorMessage(true); + return false; + } + + if ((node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) || + !MapManager::IsValidMapCoord(node->map_id,node->x,node->y,node->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(node->map_id, node->x, node->y, node->z, _player->GetOrientation()); + return true; +} + +//teleport at coordinates +bool ChatHandler::HandleGoXYCommand(const char* args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else mapid = _player->GetMapId(); + + if (!MapManager::IsValidMapCoord(mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + Map const *map = MapManager::Instance().CreateBaseMap(mapid); + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport at coordinates, including Z +bool ChatHandler::HandleGoXYZCommand(const char* args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py || !pz) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + float z = (float)atof(pz); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else + mapid = _player->GetMapId(); + + if (!MapManager::IsValidMapCoord(mapid,x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport at coordinates +bool ChatHandler::HandleGoZoneXYCommand(const char* args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* tail = strtok(NULL,""); + + char* cAreaId = extractKeyFromLink(tail,"Harea"); // string or [name] Shift-click form |color|Harea:area_id|h[name]|h|r + + if (!px || !py) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + + // prevent accept wrong numeric args + if ((x == 0.0f && *px != '0') || (y == 0.0f && *py != '0')) + return false; + + uint32 areaid = cAreaId ? (uint32)atoi(cAreaId) : _player->GetZoneId(); + + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaid); + + if (x<0 || x>100 || y<0 || y>100 || !areaEntry) + { + PSendSysMessage(LANG_INVALID_ZONE_COORD,x,y,areaid); + SetSentErrorMessage(true); + return false; + } + + // update to parent zone if exist (client map show only zones without parents) + AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; + + Map const *map = MapManager::Instance().CreateBaseMap(zoneEntry->mapid); + + if (map->Instanceable()) + { + PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[GetSessionDbcLocale()],map->GetId(),map->GetMapName()); + SetSentErrorMessage(true); + return false; + } + + Zone2MapCoordinates(x,y,zoneEntry->ID); + + if (!MapManager::IsValidMapCoord(zoneEntry->mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,zoneEntry->mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + _player->TeleportTo(zoneEntry->mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +//teleport to grid +bool ChatHandler::HandleGoGridCommand(const char* args) +{ + if (!*args) return false; + Player* _player = m_session->GetPlayer(); + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py) + return false; + + float grid_x = (float)atof(px); + float grid_y = (float)atof(py); + uint32 mapid; + if (pmapid) + mapid = (uint32)atoi(pmapid); + else mapid = _player->GetMapId(); + + // center of grid + float x = (grid_x-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; + float y = (grid_y-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; + + if (!MapManager::IsValidMapCoord(mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + Map const *map = MapManager::Instance().CreateBaseMap(mapid); + float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); + + return true; +} + +bool ChatHandler::HandleModifyDrunkCommand(const char* args) +{ + if (!*args) return false; + + uint32 drunklevel = (uint32)atoi(args); + if (drunklevel > 100) + drunklevel = 100; + + uint16 drunkMod = drunklevel * 0xFFFF / 100; + + m_session->GetPlayer()->SetDrunkValue(drunkMod); + + return true; +} + diff --git a/src/server/game/Chat/Commands/Level2.cpp b/src/server/game/Chat/Commands/Level2.cpp new file mode 100644 index 00000000000..4f299c932e8 --- /dev/null +++ b/src/server/game/Chat/Commands/Level2.cpp @@ -0,0 +1,4526 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "DBCStores.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Item.h" +#include "GameObject.h" +#include "Opcodes.h" +#include "Chat.h" +#include "MapManager.h" +#include "Language.h" +#include "World.h" +#include "GameEventMgr.h" +#include "SpellMgr.h" +#include "PoolHandler.h" +#include "AccountMgr.h" +#include "WaypointManager.h" +#include "Util.h" +#include +#include +#include +#include +#include "GlobalEvents.h" +#include "OutdoorPvPMgr.h" + +#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand +#include "CreatureGroups.h" + +//mute player for some times +bool ChatHandler::HandleMuteCommand(const char* args) +{ + char* nameStr; + char* delayStr; + extractOptFirstArg((char*)args,&nameStr,&delayStr); + if (!delayStr) + return false; + + char *mutereason = strtok(NULL, "\r"); + std::string mutereasonstr = "No reason"; + if (mutereason != NULL) + mutereasonstr = mutereason; + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); + + // find only player from same account if any + if (!target) + if (WorldSession* session = sWorld.FindSession(account_id)) + target = session->GetPlayer(); + + uint32 notspeaktime = (uint32) atoi(delayStr); + + // must have strong lesser security level + if (HasLowerSecurity (target,target_guid,true)) + return false; + + time_t mutetime = time(NULL) + notspeaktime*60; + + if (target) + target->GetSession()->m_muteTime = mutetime; + + LoginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id); + + if (target) + ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime, mutereasonstr.c_str()); + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime, mutereasonstr.c_str()); + + return true; +} + +//unmute player +bool ChatHandler::HandleUnmuteCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); + + // find only player from same account if any + if (!target) + if (WorldSession* session = sWorld.FindSession(account_id)) + target = session->GetPlayer(); + + // must have strong lesser security level + if (HasLowerSecurity (target,target_guid,true)) + return false; + + if (target) + { + if (target->CanSpeak()) + { + SendSysMessage(LANG_CHAT_ALREADY_ENABLED); + SetSentErrorMessage(true); + return false; + } + + target->GetSession()->m_muteTime = 0; + } + + LoginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id); + + if (target) + ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str()); + return true; +} + +bool ChatHandler::HandleGoTicketCommand(const char * args) +{ + if (!*args) + return false; + + char *cstrticket_id = strtok((char*)args, " "); + + if (!cstrticket_id) + return false; + + uint64 ticket_id = atoi(cstrticket_id); + if (!ticket_id) + return false; + + GM_Ticket *ticket = objmgr.GetGMTicket(ticket_id); + if (!ticket) + { + SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); + return true; + } + + float x, y, z; + int mapid; + + x = ticket->pos_x; + y = ticket->pos_y; + z = ticket->pos_z; + mapid = ticket->map; + + Player* _player = m_session->GetPlayer(); + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, 1, 0); + return true; +} + +bool ChatHandler::HandleGoTriggerCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char *atId = strtok((char*)args, " "); + if (!atId) + return false; + + int32 i_atId = atoi(atId); + + if (!i_atId) + return false; + + AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId); + if (!at) + { + PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId); + SetSentErrorMessage(true); + return false; + } + + if (!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation()); + return true; +} + +bool ChatHandler::HandleGoGraveyardCommand(const char* args) +{ + Player* _player = m_session->GetPlayer(); + + if (!*args) + return false; + + char *gyId = strtok((char*)args, " "); + if (!gyId) + return false; + + int32 i_gyId = atoi(gyId); + + if (!i_gyId) + return false; + + WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId); + if (!gy) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId); + SetSentErrorMessage(true); + return false; + } + + if (!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation()); + return true; +} + +/** \brief Teleport the GM to the specified creature +* +* .gocreature --> TP using creature.guid +* .gocreature azuregos --> TP player to the mob with this name +* Warning: If there is more than one mob with this name +* you will be teleported to the first one that is found. +* .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry +* Warning: If there is more than one mob with this "id" +* you will be teleported to the first one that is found. +*/ +//teleport to creature +bool ChatHandler::HandleGoCreatureCommand(const char* args) +{ + if (!*args) + return false; + Player* _player = m_session->GetPlayer(); + + // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* pParam1 = extractKeyFromLink((char*)args,"Hcreature"); + if (!pParam1) + return false; + + std::ostringstream whereClause; + + // User wants to teleport to the NPC's template entry + if (strcmp(pParam1, "id") == 0) + { + //sLog.outError("DEBUG: ID found"); + + // Get the "creature_template.entry" + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* tail = strtok(NULL,""); + if (!tail) + return false; + char* cId = extractKeyFromLink(tail,"Hcreature_entry"); + if (!cId) + return false; + + int32 tEntry = atoi(cId); + //sLog.outError("DEBUG: ID value: %d", tEntry); + if (!tEntry) + return false; + + whereClause << "WHERE id = '" << tEntry << "'"; + } + else + { + //sLog.outError("DEBUG: ID *not found*"); + + int32 guid = atoi(pParam1); + + // Number is invalid - maybe the user specified the mob's name + if (!guid) + { + std::string name = pParam1; + WorldDatabase.escape_string(name); + whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'"; + } + else + { + whereClause << "WHERE guid = '" << guid << "'"; + } + } + //sLog.outError("DEBUG: %s", whereClause.c_str()); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + if (result->GetRowCount() > 1) + SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE); + + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + float ort = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + if (!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, ort); + return true; +} + +//teleport to gameobject +bool ChatHandler::HandleGoObjectCommand(const char* args) +{ + if (!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + int32 guid = atoi(cId); + if (!guid) + return false; + + float x, y, z, ort; + int mapid; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(guid)) + { + x = go_data->posX; + y = go_data->posY; + z = go_data->posZ; + ort = go_data->orientation; + mapid = go_data->mapid; + } + else + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + if (!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + _player->SaveRecallPosition(); + + _player->TeleportTo(mapid, x, y, z, ort); + return true; +} + +bool ChatHandler::HandleGameObjectTargetCommand(const char* args) +{ + Player* pl = m_session->GetPlayer(); + QueryResult_AutoPtr result; + GameEventMgr::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList(); + if (*args) + { + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); + if (!cId) + return false; + + uint32 id = atol(cId); + + if (id) + result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id); + else + { + std::string name = cId; + WorldDatabase.escape_string(name); + result = WorldDatabase.PQuery( + "SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ " + "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str()); + } + } + else + { + std::ostringstream eventFilter; + eventFilter << " AND (event IS NULL "; + bool initString = true; + + for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr) + { + if (initString) + { + eventFilter << "OR event IN (" <<*itr; + initString =false; + } + else + eventFilter << "," << *itr; + } + + if (!initString) + eventFilter << "))"; + else + eventFilter << ")"; + + result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, phaseMask, " + "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject " + "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10", + m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str()); + } + + if (!result) + { + SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND); + return true; + } + + bool found = false; + float x, y, z, o; + uint32 lowguid, id; + uint16 mapid, pool_id, phase; + + do + { + Field *fields = result->Fetch(); + lowguid = fields[0].GetUInt32(); + id = fields[1].GetUInt32(); + x = fields[2].GetFloat(); + y = fields[3].GetFloat(); + z = fields[4].GetFloat(); + o = fields[5].GetFloat(); + mapid = fields[6].GetUInt16(); + phase = fields[7].GetUInt16(); + pool_id = poolhandler.IsPartOfAPool(lowguid); + if (!pool_id || poolhandler.IsSpawnedObject(lowguid)) + found = true; + } while (result->NextRow() && (!found)); + + if (!found) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); + return false; + } + + GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id); + + if (!goI) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); + return false; + } + + GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT)); + + PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o, phase); + + if (target) + { + int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); + if (curRespawnDelay < 0) + curRespawnDelay = 0; + + std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true); + std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true); + + PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str()); + } + return true; +} + +//delete object by selection or guid +bool ChatHandler::HandleGameObjectDeleteCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint64 owner_guid = obj->GetOwnerGUID(); + if (owner_guid) + { + Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid); + if (!owner || !IS_PLAYER_GUID(owner_guid)) + { + PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow()); + SetSentErrorMessage(true); + return false; + } + + owner->RemoveGameObject(obj,false); + } + + obj->SetRespawnTime(0); // not save respawn time + obj->Delete(); + obj->DeleteFromDB(); + + PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow()); + + return true; +} + +//turn selected object +bool ChatHandler::HandleGameObjectTurnCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* po = strtok(NULL, " "); + float o; + + if (po) + { + o = (float)atof(po); + } + else + { + Player *chr = m_session->GetPlayer(); + o = chr->GetOrientation(); + } + + obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); + obj->UpdateRotationFields(); + obj->DestroyForNearbyPlayers(); + obj->UpdateObjectVisibility(); + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow(), o); + + return true; +} + +//move selected object +bool ChatHandler::HandleGameObjectMoveCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* px = strtok(NULL, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px) + { + Player *chr = m_session->GetPlayer(); + obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); + obj->DestroyForNearbyPlayers(); + obj->UpdateObjectVisibility(); + } + else + { + if (!py || !pz) + return false; + + float x = (float)atof(px); + float y = (float)atof(py); + float z = (float)atof(pz); + + if (!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId()); + SetSentErrorMessage(true); + return false; + } + + obj->Relocate(x, y, z, obj->GetOrientation()); + obj->DestroyForNearbyPlayers(); + obj->UpdateObjectVisibility(); + } + + obj->SaveToDB(); + obj->Refresh(); + + PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow()); + + return true; +} + +//spawn go +bool ChatHandler::HandleGameObjectAddCommand(const char* args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); + if (!cId) + return false; + + uint32 id = atol(cId); + if (!id) + return false; + + char* spawntimeSecs = strtok(NULL, " "); + + const GameObjectInfo *gInfo = objmgr.GetGameObjectInfo(id); + + if (!gInfo) + { + PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); + SetSentErrorMessage(true); + return false; + } + + if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId)) + { + // report to DB errors log as in loading case + sLog.outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.",id, gInfo->type, gInfo->displayId); + PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA,id); + SetSentErrorMessage(true); + return false; + } + + Player *chr = m_session->GetPlayer(); + float x = float(chr->GetPositionX()); + float y = float(chr->GetPositionY()); + float z = float(chr->GetPositionZ()); + float o = float(chr->GetOrientation()); + Map *map = chr->GetMap(); + + GameObject* pGameObj = new GameObject; + uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); + + if (!pGameObj->Create(db_lowGUID, gInfo->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) + { + delete pGameObj; + return false; + } + + if (spawntimeSecs) + { + uint32 value = atoi((char*)spawntimeSecs); + pGameObj->SetRespawnTime(value); + //sLog.outDebug("*** spawntimeSecs: %d", value); + } + + // fill the gameobject data and save to the db + pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn()); + + // this will generate a new guid if the object is in an instance + if (!pGameObj->LoadFromDB(db_lowGUID, map)) + { + delete pGameObj; + return false; + } + + sLog.outDebug(GetTrinityString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o); + + map->Add(pGameObj); + + // TODO: is it really necessary to add both the real and DB table guid here ? + objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID)); + + PSendSysMessage(LANG_GAMEOBJECT_ADD,id,gInfo->name,db_lowGUID,x,y,z); + return true; +} + +//set pahsemask for selected object +bool ChatHandler::HandleGameObjectPhaseCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* phaseStr = strtok (NULL, " "); + uint32 phasemask = phaseStr? atoi(phaseStr) : 0; + if (phasemask == 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + obj->SetPhaseMask(phasemask,true); + obj->SaveToDB(); + return true; +} + +bool ChatHandler::HandleGameObjectNearCommand(const char* args) +{ + float distance = (!*args) ? 10 : atol(args); + uint32 count = 0; + + Player* pl = m_session->GetPlayer(); + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, map, " + "(POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ " + "FROM gameobject WHERE map='%u' AND (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) <= '%f' ORDER BY order_", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), + pl->GetMapId(),pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),distance*distance); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + uint32 entry = fields[1].GetUInt32(); + float x = fields[2].GetFloat(); + float y = fields[3].GetFloat(); + float z = fields[4].GetFloat(); + int mapid = fields[5].GetUInt16(); + + GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(entry); + + if (!gInfo) + continue; + + PSendSysMessage(LANG_GO_LIST_CHAT, guid, guid, gInfo->name, x, y, z, mapid); + + ++count; + } while (result->NextRow()); + } + + PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE,distance,count); + return true; +} + +bool ChatHandler::HandleGUIDCommand(const char* /*args*/) +{ + uint64 guid = m_session->GetPlayer()->GetSelection(); + + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid)); + return true; +} + +bool ChatHandler::HandleModifyRepCommand(const char * args) +{ + if (!*args) return false; + + Player* target = NULL; + target = getSelectedPlayer(); + + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + char* factionTxt = extractKeyFromLink((char*)args,"Hfaction"); + if (!factionTxt) + return false; + + uint32 factionId = atoi(factionTxt); + + int32 amount = 0; + char *rankTxt = strtok(NULL, " "); + if (!factionTxt || !rankTxt) + return false; + + amount = atoi(rankTxt); + if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0])) + { + std::string rankStr = rankTxt; + std::wstring wrankStr; + if (!Utf8toWStr(rankStr,wrankStr)) + return false; + wstrToLower(wrankStr); + + int r = 0; + amount = -42000; + for (; r < MAX_REPUTATION_RANK; ++r) + { + std::string rank = GetTrinityString(ReputationRankStrIndex[r]); + if (rank.empty()) + continue; + + std::wstring wrank; + if (!Utf8toWStr(rank,wrank)) + continue; + + wstrToLower(wrank); + + if (wrank.substr(0,wrankStr.size()) == wrankStr) + { + char *deltaTxt = strtok(NULL, " "); + if (deltaTxt) + { + int32 delta = atoi(deltaTxt); + if ((delta < 0) || (delta > ReputationMgr::PointsInRank[r] -1)) + { + PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (ReputationMgr::PointsInRank[r]-1)); + SetSentErrorMessage(true); + return false; + } + amount += delta; + } + break; + } + amount += ReputationMgr::PointsInRank[r]; + } + if (r >= MAX_REPUTATION_RANK) + { + PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt); + SetSentErrorMessage(true); + return false; + } + } + + FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId); + + if (!factionEntry) + { + PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId); + SetSentErrorMessage(true); + return false; + } + + if (factionEntry->reputationListID < 0) + { + PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[GetSessionDbcLocale()], factionId); + SetSentErrorMessage(true); + return false; + } + + target->GetReputationMgr().SetReputation(factionEntry,amount); + PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[GetSessionDbcLocale()], factionId, + GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry)); + return true; +} + +//-----------------------Npc Commands----------------------- +//add spawn of creature +bool ChatHandler::HandleNpcAddCommand(const char* args) +{ + if (!*args) + return false; + char* charID = extractKeyFromLink((char*)args,"Hcreature_entry"); + if (!charID) + return false; + + char* team = strtok(NULL, " "); + int32 teamval = 0; + if (team) { teamval = atoi(team); } + if (teamval < 0) { teamval = 0; } + + uint32 id = atoi(charID); + + Player *chr = m_session->GetPlayer(); + float x = chr->GetPositionX(); + float y = chr->GetPositionY(); + float z = chr->GetPositionZ(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o)) + { + delete pCreature; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + + uint32 db_guid = pCreature->GetDBTableGUIDLow(); + + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + pCreature->LoadFromDB(db_guid, map); + + map->Add(pCreature); + objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid)); + return true; +} + +//add item in vendorlist +bool ChatHandler::HandleNpcAddVendorItemCommand(const char* args) +{ + if (!*args) + return false; + + char* pitem = extractKeyFromLink((char*)args,"Hitem"); + if (!pitem) + { + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; + } + + uint32 itemId = atol(pitem); + + char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 + uint32 maxcount = 0; + if (fmaxcount) + maxcount = atol(fmaxcount); + + char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 + uint32 incrtime = 0; + if (fincrtime) + incrtime = atol(fincrtime); + + char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 + uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0; + + Creature* vendor = getSelectedCreature(); + + uint32 vendor_entry = vendor ? vendor->GetEntry() : 0; + + if (!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer())) + { + SetSentErrorMessage(true); + return false; + } + + objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost); + + ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); + + PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost); + return true; +} + +//del item from vendor list +bool ChatHandler::HandleNpcDelVendorItemCommand(const char* args) +{ + if (!*args) + return false; + + Creature* vendor = getSelectedCreature(); + if (!vendor || !vendor->isVendor()) + { + SendSysMessage(LANG_COMMAND_VENDORSELECTION); + SetSentErrorMessage(true); + return false; + } + + char* pitem = extractKeyFromLink((char*)args,"Hitem"); + if (!pitem) + { + SendSysMessage(LANG_COMMAND_NEEDITEMSEND); + SetSentErrorMessage(true); + return false; + } + uint32 itemId = atol(pitem); + + if (!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId)) + { + PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId); + SetSentErrorMessage(true); + return false; + } + + ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); + + PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1); + return true; +} + +//add move for creature +bool ChatHandler::HandleNpcAddMoveCommand(const char* args) +{ + if (!*args) + return false; + + char* guid_str = strtok((char*)args, " "); + char* wait_str = strtok((char*)NULL, " "); + + uint32 lowguid = atoi((char*)guid_str); + + Creature* pCreature = NULL; + + /* FIXME: impossible without entry + if (lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // attempt check creature existence by DB data + if (!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if (!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + // obtain real GUID for DB operations + lowguid = pCreature->GetDBTableGUIDLow(); + } + + int wait = wait_str ? atoi(wait_str) : 0; + + if (wait < 0) + wait = 0; + + //Player* player = m_session->GetPlayer(); + + //WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0); + + // update movement type + WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid); + if (pCreature && pCreature->GetWaypointPath()) + { + pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + pCreature->GetMotionMaster()->Initialize(); + if (pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(true); + } + pCreature->SaveToDB(); + } + + SendSysMessage(LANG_WAYPOINT_ADDED); + + return true; +} + +//change level of creature or pet +bool ChatHandler::HandleNpcChangeLevelCommand(const char* args) +{ + if (!*args) + return false; + + uint8 lvl = (uint8) atoi((char*)args); + if (lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (pCreature->isPet()) + { + if (((Pet*)pCreature)->getPetType() == HUNTER_PET) + { + pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(lvl)/4); + pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); + } + ((Pet*)pCreature)->GivePetLevel(lvl); + } + else + { + pCreature->SetMaxHealth(100 + 30*lvl); + pCreature->SetHealth(100 + 30*lvl); + pCreature->SetLevel(lvl); + pCreature->SaveToDB(); + } + + return true; +} + +//set npcflag of creature +bool ChatHandler::HandleNpcFlagCommand(const char* args) +{ + if (!*args) + return false; + + uint32 npcFlags = (uint32) atoi((char*)args); + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); + + WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry()); + + SendSysMessage(LANG_VALUE_SAVED_REJOIN); + + return true; +} + +bool ChatHandler::HandleNpcDeleteCommand(const char* args) +{ + Creature* unit = NULL; + + if (*args) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) + unit = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); + } + else + unit = getSelectedCreature(); + + if (!unit || unit->isPet() || unit->isTotem()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // Delete the creature + unit->CombatStop(); + unit->DeleteFromDB(); + unit->AddObjectToRemoveList(); + + SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); + + return true; +} + +//move selected creature +bool ChatHandler::HandleNpcMoveCommand(const char* args) +{ + uint32 lowguid = 0; + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature"); + if (!cId) + return false; + + lowguid = atoi(cId); + + /* FIXME: impossibel without entry + if (lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // Attempting creature load from DB data + if (!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if (!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + uint32 map_id = data->mapid; + + if (m_session->GetPlayer()->GetMapId() != map_id) + { + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + + float x = m_session->GetPlayer()->GetPositionX(); + float y = m_session->GetPlayer()->GetPositionY(); + float z = m_session->GetPlayer()->GetPositionZ(); + float o = m_session->GetPlayer()->GetOrientation(); + + if (pCreature) + { + if (CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow())) + { + const_cast(data)->posX = x; + const_cast(data)->posY = y; + const_cast(data)->posZ = z; + const_cast(data)->orientation = o; + } + pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o); + pCreature->GetMotionMaster()->Initialize(); + if (pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + } + + WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); + PSendSysMessage(LANG_COMMAND_CREATUREMOVED); + return true; +} + +/**HandleNpcSetMoveTypeCommand + * Set the movement type for an NPC.
+ *
+ * Valid movement types are: + *
    + *
  • stay - NPC wont move
  • + *
  • random - NPC will move randomly according to the spawndist
  • + *
  • way - NPC will move with given waypoints set
  • + *
+ * additional parameter: NODEL - so no waypoints are deleted, if you + * change the movement type + */ +bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args) +{ + if (!*args) + return false; + + // 3 arguments: + // GUID (optional - you can also select the creature) + // stay|random|way (determines the kind of movement) + // NODEL (optional - tells the system NOT to delete any waypoints) + // this is very handy if you want to do waypoints, that are + // later switched on/off according to special events (like escort + // quests, etc) + char* guid_str = strtok((char*)args, " "); + char* type_str = strtok((char*)NULL, " "); + char* dontdel_str = strtok((char*)NULL, " "); + + bool doNotDelete = false; + + if (!guid_str) + return false; + + uint32 lowguid = 0; + Creature* pCreature = NULL; + + if (dontdel_str) + { + //sLog.outError("DEBUG: All 3 params are set"); + + // All 3 params are set + // GUID + // type + // doNotDEL + if (stricmp(dontdel_str, "NODEL") == 0) + { + //sLog.outError("DEBUG: doNotDelete = true;"); + doNotDelete = true; + } + } + else + { + // Only 2 params - but maybe NODEL is set + if (type_str) + { + sLog.outError("DEBUG: Only 2 params "); + if (stricmp(type_str, "NODEL") == 0) + { + //sLog.outError("DEBUG: type_str, NODEL "); + doNotDelete = true; + type_str = NULL; + } + } + } + + if (!type_str) // case .setmovetype $move_type (with selected creature) + { + type_str = guid_str; + pCreature = getSelectedCreature(); + if (!pCreature || pCreature->isPet()) + return false; + lowguid = pCreature->GetDBTableGUIDLow(); + } + else // case .setmovetype #creature_guid $move_type (with selected creature) + { + lowguid = atoi((char*)guid_str); + + /* impossible without entry + if (lowguid) + pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); + */ + + // attempt check creature existence by DB data + if (!pCreature) + { + CreatureData const* data = objmgr.GetCreatureData(lowguid); + if (!data) + { + PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + } + else + { + lowguid = pCreature->GetDBTableGUIDLow(); + } + } + + // now lowguid is low guid really existed creature + // and pCreature point (maybe) to this creature or NULL + + MovementGeneratorType move_type; + + std::string type = type_str; + + if (type == "stay") + move_type = IDLE_MOTION_TYPE; + else if (type == "random") + move_type = RANDOM_MOTION_TYPE; + else if (type == "way") + move_type = WAYPOINT_MOTION_TYPE; + else + return false; + + // update movement type + //if (doNotDelete == false) + // WaypointMgr.DeletePath(lowguid); + + if (pCreature) + { + // update movement type + if (doNotDelete == false) + pCreature->LoadPath(0); + + pCreature->SetDefaultMovementType(move_type); + pCreature->GetMotionMaster()->Initialize(); + if (pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + pCreature->SaveToDB(); + } + if (doNotDelete == false) + { + PSendSysMessage(LANG_MOVE_TYPE_SET,type_str); + } + else + { + PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str); + } + + return true; +} + +//set model of creature +bool ChatHandler::HandleNpcSetModelCommand(const char* args) +{ + if (!*args) + return false; + + uint32 displayId = (uint32) atoi((char*)args); + + Creature *pCreature = getSelectedCreature(); + + if (!pCreature || pCreature->isPet()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetDisplayId(displayId); + pCreature->SetNativeDisplayId(displayId); + + pCreature->SaveToDB(); + + return true; +} +//set faction of creature +bool ChatHandler::HandleNpcFactionIdCommand(const char* args) +{ + if (!*args) + return false; + + uint32 factionId = (uint32) atoi((char*)args); + + if (!sFactionTemplateStore.LookupEntry(factionId)) + { + PSendSysMessage(LANG_WRONG_FACTION, factionId); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->setFaction(factionId); + + // faction is set in creature_template - not inside creature + + // update in memory + if (CreatureInfo const *cinfo = pCreature->GetCreatureInfo()) + { + const_cast(cinfo)->faction_A = factionId; + const_cast(cinfo)->faction_H = factionId; + } + + // and DB + WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry()); + + return true; +} +//set spawn dist of creature +bool ChatHandler::HandleNpcSpawnDistCommand(const char* args) +{ + if (!*args) + return false; + + float option = atof((char*)args); + if (option < 0.0f) + { + SendSysMessage(LANG_BAD_VALUE); + return false; + } + + MovementGeneratorType mtype = IDLE_MOTION_TYPE; + if (option >0.0f) + mtype = RANDOM_MOTION_TYPE; + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + pCreature->SetRespawnRadius((float)option); + pCreature->SetDefaultMovementType(mtype); + pCreature->GetMotionMaster()->Initialize(); + if (pCreature->isAlive()) // dead creature will reset movement generator at respawn + { + pCreature->setDeathState(JUST_DIED); + pCreature->Respawn(); + } + + WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow); + PSendSysMessage(LANG_COMMAND_SPAWNDIST,option); + return true; +} +//spawn time handling +bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args) +{ + if (!*args) + return false; + + char* stime = strtok((char*)args, " "); + + if (!stime) + return false; + + int i_stime = atoi((char*)stime); + + if (i_stime < 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature *pCreature = getSelectedCreature(); + uint32 u_guidlow = 0; + + if (pCreature) + u_guidlow = pCreature->GetDBTableGUIDLow(); + else + return false; + + WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow); + pCreature->SetRespawnDelay((uint32)i_stime); + PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime); + + return true; +} +//npc follow handling +bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creature = getSelectedCreature(); + + if (!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // Follow player - Using pet's default dist and angle + creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, creature->GetFollowAngle()); + + PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +//npc unfollow handling +bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creature = getSelectedCreature(); + + if (!creature) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (/*creature->GetMotionMaster()->empty() ||*/ + creature->GetMotionMaster()->GetCurrentMovementGeneratorType () != TARGETED_MOTION_TYPE) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + SetSentErrorMessage(true); + return false; + } + + TargetedMovementGenerator const* mgen + = static_cast const*>((creature->GetMotionMaster()->top())); + + if (mgen->GetTarget() != player) + { + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + SetSentErrorMessage(true); + return false; + } + + // reset movement + creature->GetMotionMaster()->MovementExpired(true); + + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); + return true; +} +//npc tame handling +bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) +{ + Creature *creatureTarget = getSelectedCreature (); + if (!creatureTarget || creatureTarget->isPet ()) + { + PSendSysMessage (LANG_SELECT_CREATURE); + SetSentErrorMessage (true); + return false; + } + + Player *player = m_session->GetPlayer (); + + if (player->GetPetGUID ()) + { + SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); + SetSentErrorMessage (true); + return false; + } + + CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo(); + + if (!cInfo->isTameable (player->CanTameExoticPets())) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // Everything looks OK, create new pet + Pet* pet = player->CreateTamedPetFrom (creatureTarget); + if (!pet) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // place pet before player + float x,y,z; + player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); + pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); + + // set pet to defensive mode by default (some classes can't control controlled pets in fact). + pet->SetReactState(REACT_DEFENSIVE); + + // calculate proper level + uint8 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); + + // add to world + pet->GetMap()->Add(pet->ToCreature()); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); + + // caster have pet now + player->SetMinion(pet, true); + + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + player->PetSpellInitialize(); + + return true; +} +//npc phasemask handling +//change phasemask of creature or pet +bool ChatHandler::HandleNpcSetPhaseCommand(const char* args) +{ + if (!*args) + return false; + + uint32 phasemask = (uint32) atoi((char*)args); + if (phasemask == 0) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetPhaseMask(phasemask,true); + + if (!pCreature->isPet()) + pCreature->SaveToDB(); + + return true; +} +//npc deathstate handling +bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args) +{ + if (!*args) + return false; + + Creature* pCreature = getSelectedCreature(); + if (!pCreature || pCreature->isPet()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (strncmp(args, "on", 3) == 0) + pCreature->SetDeadByDefault(true); + else if (strncmp(args, "off", 4) == 0) + pCreature->SetDeadByDefault(false); + else + { + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; + } + + pCreature->SaveToDB(); + pCreature->Respawn(); + + return true; +} + +//TODO: NpcCommands that need to be fixed : + +bool ChatHandler::HandleNpcNameCommand(const char* /*args*/) +{ + /* Temp. disabled + if (!*args) + return false; + + if (strlen((char*)args)>75) + { + PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); ++i) + { + if (!isalpha(args[i]) && args[i] != ' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + pCreature->SetName(args); + uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName()); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + + return true; +} + +bool ChatHandler::HandleNpcSubNameCommand(const char* /*args*/) +{ + /* Temp. disabled + + if (!*args) + args = ""; + + if (strlen((char*)args)>75) + { + + PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); + return true; + } + + for (uint8 i = 0; i < strlen(args); i++) + { + if (!isalpha(args[i]) && args[i] != ' ') + { + SendSysMessage(LANG_CHARS_ONLY); + return false; + } + } + uint64 guid; + guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); + pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); + + pCreature->SaveToDB(); + */ + return true; +} + +//move item to other slot +bool ChatHandler::HandleItemMoveCommand(const char* args) +{ + if (!*args) + return false; + uint8 srcslot, dstslot; + + char* pParam1 = strtok((char*)args, " "); + if (!pParam1) + return false; + + char* pParam2 = strtok(NULL, " "); + if (!pParam2) + return false; + + srcslot = (uint8)atoi(pParam1); + dstslot = (uint8)atoi(pParam2); + + if (srcslot == dstslot) + return true; + + if (!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + return false; + + if (!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + return false; + + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + + m_session->GetPlayer()->SwapItem(src, dst); + + return true; +} + +//demorph player or unit +bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) +{ + Unit *target = getSelectedUnit(); + if (!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->DeMorph(); + + return true; +} + +//morph creature or player +bool ChatHandler::HandleModifyMorphCommand(const char* args) +{ + if (!*args) + return false; + + uint16 display_id = (uint16)atoi((char*)args); + + Unit *target = getSelectedUnit(); + if (!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->SetDisplayId(display_id); + + return true; +} + +//kick player +bool ChatHandler::HandleKickPlayerCommand(const char *args) +{ +/* const char* kickName = strtok((char*)args, " "); + char* kickReason = strtok(NULL, "\n"); + std::string reason = "No Reason"; + std::string kicker = "Console"; + if (kickReason) + reason = kickReason; + if (m_session) + kicker = m_session->GetPlayer()->GetName(); + + if (!kickName) + { + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (player == m_session->GetPlayer()) + { + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(player, 0)) + return false; + + if (sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1) + { + sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str()); + } + else + { + PSendSysMessage(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str()); + } + + player->GetSession()->KickPlayer(); + } + else + { + std::string name = extractPlayerNameFromLink((char*)kickName); + if (name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if (m_session && name == m_session->GetPlayer()->GetName()) + { + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; + } + + Player* player = objmgr.GetPlayer(kickName); + if (!player) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if (HasLowerSecurity(player, 0)) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); //maybe replacement string for this later on + SetSentErrorMessage(true); + return false; + } + + std::string nameLink = playerLink(name); + + if (sWorld.KickPlayer(name)) + { + if (sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1) + { + sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, nameLink.c_str(), kicker.c_str(), reason.c_str()); + } + else + { + PSendSysMessage(LANG_COMMAND_KICKMESSAGE,nameLink.c_str()); + } + } + else + { + PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,nameLink.c_str()); + return false; + } + }*/ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + if (m_session && target == m_session->GetPlayer()) + { + SendSysMessage(LANG_COMMAND_KICKSELF); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + // send before target pointer invalidate + PSendSysMessage(LANG_COMMAND_KICKMESSAGE,GetNameLink(target).c_str()); + target->GetSession()->KickPlayer(); + return true; +} + +//set temporary phase mask for player +bool ChatHandler::HandleModifyPhaseCommand(const char* args) +{ + if (!*args) + return false; + + uint32 phasemask = (uint32)atoi((char*)args); + + Unit *target = getSelectedUnit(); + if (!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->SetPhaseMask(phasemask,true); + + return true; +} +//show info of gameobject +bool ChatHandler::HandleGOInfoCommand(const char* args) +{ + uint32 entry = 0; + uint32 type = 0; + uint32 displayid = 0; + std::string name; + + if (!*args) + { + if (WorldObject * obj = getSelectedObject()) + entry = obj->GetEntry(); + } + else + entry = atoi((char*)args); + + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); + + if (!goinfo) + return false; + + type = goinfo->type; + displayid = goinfo->displayId; + name = goinfo->name; + + PSendSysMessage(LANG_GOINFO_ENTRY, entry); + PSendSysMessage(LANG_GOINFO_TYPE, type); + PSendSysMessage(LANG_GOINFO_DISPLAYID, displayid); + PSendSysMessage(LANG_GOINFO_NAME, name.c_str()); + + return true; +} + +//show info of player +bool ChatHandler::HandlePInfoCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + uint32 accId = 0; + uint32 money = 0; + uint32 total_player_time = 0; + uint8 level = 0; + uint32 latency = 0; + uint8 race; + uint8 Class; + + // get additional information from Player object + if (target) + { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + accId = target->GetSession()->GetAccountId(); + money = target->GetMoney(); + total_player_time = target->GetTotalPlayedTime(); + level = target->getLevel(); + latency = target->GetSession()->GetLatency(); + race = target->getRace(); + Class = target->getClass(); + } + // get additional information from DB + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + // 0 1 2 3 4 5 + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT totaltime, level, money, account, race, class FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid)); + if (!result) + return false; + + Field *fields = result->Fetch(); + total_player_time = fields[0].GetUInt32(); + level = fields[1].GetUInt32(); + money = fields[2].GetUInt32(); + accId = fields[3].GetUInt32(); + race = fields[4].GetUInt8(); + Class = fields[5].GetUInt8(); + } + + std::string username = GetTrinityString(LANG_ERROR); + std::string email = GetTrinityString(LANG_ERROR); + std::string last_ip = GetTrinityString(LANG_ERROR); + uint32 security = 0; + std::string last_login = GetTrinityString(LANG_ERROR); + + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT a.username,aa.gmlevel,a.email,a.last_ip,a.last_login " + "FROM account a " + "LEFT JOIN account_access aa " + "ON (a.id = aa.id) " + "WHERE a.id = '%u'",accId); + if (result) + { + Field* fields = result->Fetch(); + username = fields[0].GetCppString(); + security = fields[1].GetUInt32(); + email = fields[2].GetCppString(); + + if (email.empty()) + email = "-"; + + if (!m_session || m_session->GetSecurity() >= security) + { + last_ip = fields[3].GetCppString(); + last_login = fields[4].GetCppString(); + } + else + { + last_ip = "-"; + last_login = "-"; + } + } + + std::string nameLink = playerLink(target_name); + + PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(target_guid), username.c_str(), accId, email.c_str(), security, last_ip.c_str(), last_login.c_str(), latency); + + std::string race_s, Class_s; + switch(race) + { + case RACE_HUMAN: race_s = "Human"; break; + case RACE_ORC: race_s = "Orc"; break; + case RACE_DWARF: race_s = "Dwarf"; break; + case RACE_NIGHTELF: race_s = "Night Elf"; break; + case RACE_UNDEAD_PLAYER: race_s = "Undead"; break; + case RACE_TAUREN: race_s = "Tauren"; break; + case RACE_GNOME: race_s = "Gnome"; break; + case RACE_TROLL: race_s = "Troll"; break; + case RACE_BLOODELF: race_s = "Blood Elf"; break; + case RACE_DRAENEI: race_s = "Draenei"; break; + } + switch(Class) + { + case CLASS_WARRIOR: Class_s = "Warrior"; break; + case CLASS_PALADIN: Class_s = "Paladin"; break; + case CLASS_HUNTER: Class_s = "Hunter"; break; + case CLASS_ROGUE: Class_s = "Rogue"; break; + case CLASS_PRIEST: Class_s = "Priest"; break; + case CLASS_DEATH_KNIGHT: Class_s = "Death Knight"; break; + case CLASS_SHAMAN: Class_s = "Shaman"; break; + case CLASS_MAGE: Class_s = "Mage"; break; + case CLASS_WARLOCK: Class_s = "Warlock"; break; + case CLASS_DRUID: Class_s = "Druid"; break; + } + + std::string timeStr = secsToTimeString(total_player_time,true,true); + uint32 gold = money /GOLD; + uint32 silv = (money % GOLD) / SILVER; + uint32 copp = (money % GOLD) % SILVER; + PSendSysMessage(LANG_PINFO_LEVEL, race_s.c_str(), Class_s.c_str(), timeStr.c_str(), level, gold, silv, copp); + + return true; +} + +/////WAYPOINT COMMANDS + +/** + * Add a waypoint to a creature. + * + * The user can either select an npc or provide its GUID. + * + * The user can even select a visual waypoint - then the new waypoint + * is placed *after* the selected one - this makes insertion of new + * waypoints possible. + * + * eg: + * .wp add 12345 + * -> adds a waypoint to the npc with the GUID 12345 + * + * .wp add + * -> adds a waypoint to the currently selected creature + * + * + * @param args if the user did not provide a GUID, it is NULL + * + * @return true - command did succeed, false - something went wrong + */ +bool ChatHandler::HandleWpAddCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpAddCommand"); + + // optional + char* path_number = NULL; + uint32 pathid = 0; + + if (*args) + path_number = strtok((char*)args, " "); + + uint32 point = 0; + Creature* target = getSelectedCreature(); + + if (!path_number) + { + if (target) + pathid = target->GetWaypointPath(); + else + { + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT MAX(id) FROM waypoint_data"); + uint32 maxpathid = result->Fetch()->GetInt32(); + pathid = maxpathid+1; + sLog.outDebug("DEBUG: HandleWpAddCommand - New path started."); + PSendSysMessage("%s%s|r", "|cff00ff00", "New path started."); + } + } + else + pathid = atoi(path_number); + + // path_id -> ID of the Path + // point -> number of the waypoint (if not 0) + + if (!pathid) + { + sLog.outDebug("DEBUG: HandleWpAddCommand - Current creature haven't loaded path."); + PSendSysMessage("%s%s|r", "|cffff33ff", "Current creature haven't loaded path."); + return true; + } + + sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0"); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid); + + if (result) + point = (*result)[0].GetUInt32(); + + Player* player = m_session->GetPlayer(); + //Map *map = player->GetMap(); + + WorldDatabase.PExecuteLog("INSERT INTO waypoint_data (id, point, position_x, position_y, position_z) VALUES ('%u','%u','%f', '%f', '%f')", + pathid, point+1, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); + + PSendSysMessage("%s%s%u%s%u%s|r", "|cff00ff00", "PathID: |r|cff00ffff", pathid, "|r|cff00ff00: Waypoint |r|cff00ffff", point+1,"|r|cff00ff00 created. "); + return true; +} // HandleWpAddCommand + +bool ChatHandler::HandleWpLoadPathCommand(const char *args) +{ + if (!*args) + return false; + + // optional + char* path_number = NULL; + + if (*args) + path_number = strtok((char*)args, " "); + + uint32 pathid = 0; + uint32 guidlow = 0; + Creature* target = getSelectedCreature(); + + // Did player provide a path_id? + if (!path_number) + sLog.outDebug("DEBUG: HandleWpLoadPathCommand - No path number provided"); + + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->GetEntry() == 1) + { + PSendSysMessage("%s%s|r", "|cffff33ff", "You want to load path to a waypoint? Aren't you?"); + SetSentErrorMessage(true); + return false; + } + + pathid = atoi(path_number); + + if (!pathid) + { + PSendSysMessage("%s%s|r", "|cffff33ff", "No vallid path number provided."); + return true; + } + + guidlow = target->GetDBTableGUIDLow(); + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM creature_addon WHERE guid = '%u'",guidlow); + + if (result) + WorldDatabase.PExecute("UPDATE creature_addon SET path_id = '%u' WHERE guid = '%u'", pathid, guidlow); + else + WorldDatabase.PExecute("INSERT INTO creature_addon(guid,path_id) VALUES ('%u','%u')", guidlow, pathid); + + WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE, guidlow); + + target->LoadPath(pathid); + target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); + target->GetMotionMaster()->Initialize(); + target->MonsterSay("Path loaded.",0,0); + + return true; +} + +bool ChatHandler::HandleReloadAllPaths(const char* args) +{ + if (!*args) + return false; + + uint32 id = atoi(args); + + if (!id) + return false; + + PSendSysMessage("%s%s|r|cff00ffff%u|r", "|cff00ff00", "Loading Path: ", id); + sWaypointMgr->UpdatePath(id); + return true; +} + +bool ChatHandler::HandleWpUnLoadPathCommand(const char * /*args*/) +{ + uint32 guidlow = 0; + Creature* target = getSelectedCreature(); + + if (!target) + { + PSendSysMessage("%s%s|r", "|cff33ffff", "You must select target."); + return true; + } + + if (target->GetCreatureAddon()) + { + if (target->GetCreatureAddon()->path_id != 0) + { + WorldDatabase.PExecute("DELETE FROM creature_addon WHERE guid = %u", target->GetGUIDLow()); + target->UpdateWaypointID(0); + WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", IDLE_MOTION_TYPE, guidlow); + target->LoadPath(0); + target->SetDefaultMovementType(IDLE_MOTION_TYPE); + target->GetMotionMaster()->MoveTargetedHome(); + target->GetMotionMaster()->Initialize(); + target->MonsterSay("Path unloaded.",0,0); + return true; + } + PSendSysMessage("%s%s|r", "|cffff33ff", "Target have no loaded path."); + } + return true; +} + +bool ChatHandler::HandleWpEventCommand(const char* args) +{ + if (!*args) + return false; + + char* show_str = strtok((char*)args, " "); + std::string show = show_str; + + // Check + if ((show != "add") && (show != "mod") && (show != "del") && (show != "listid")) return false; + + char* arg_id = strtok(NULL, " "); + uint32 id = 0; + + if (show == "add") + { + if (arg_id) + id = atoi(arg_id); + + if (id) + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid = %u", id); + + if (!result) + { + WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id); + PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: New waypoint event added: ", id); + } + else + PSendSysMessage("|cff00ff00Wp Event: You have choosed an existing waypoint script guid: %u|r", id); + } + else + { + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT MAX(guid) FROM waypoint_scripts"); + id = result->Fetch()->GetUInt32(); + WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id+1); + PSendSysMessage("%s%s%u|r", "|cff00ff00","Wp Event: New waypoint event added: |r|cff00ffff", id+1); + } + + return true; + } + + if (show == "listid") + { + if (!arg_id) + { + PSendSysMessage("%s%s|r", "|cff33ffff","Wp Event: You must provide waypoint script id."); + return true; + } + + id = atoi(arg_id); + + uint32 a2, a3, a4, a5, a6; + float a8, a9, a10, a11; + char const* a7; + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = %u", id); + + if (!result) + { + PSendSysMessage("%s%s%u|r", "|cff33ffff", "Wp Event: No waypoint scripts found on id: ", id); + return true; + } + + Field *fields; + + do + { + fields = result->Fetch(); + a2 = fields[0].GetUInt32(); + a3 = fields[1].GetUInt32(); + a4 = fields[2].GetUInt32(); + a5 = fields[3].GetUInt32(); + a6 = fields[4].GetUInt32(); + a7 = fields[5].GetString(); + a8 = fields[6].GetFloat(); + a9 = fields[7].GetFloat(); + a10 = fields[8].GetFloat(); + a11 = fields[9].GetFloat(); + + PSendSysMessage("|cffff33ffid:|r|cff00ffff %u|r|cff00ff00, guid: |r|cff00ffff%u|r|cff00ff00, delay: |r|cff00ffff%u|r|cff00ff00, command: |r|cff00ffff%u|r|cff00ff00, datalong: |r|cff00ffff%u|r|cff00ff00, datalong2: |r|cff00ffff%u|r|cff00ff00, datatext: |r|cff00ffff%s|r|cff00ff00, posx: |r|cff00ffff%f|r|cff00ff00, posy: |r|cff00ffff%f|r|cff00ff00, posz: |r|cff00ffff%f|r|cff00ff00, orientation: |r|cff00ffff%f|r", id, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + while (result->NextRow()); + } + + if (show == "del") + { + id = atoi(arg_id); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM waypoint_scripts WHERE guid = %u", id); + + if (result) + { + WorldDatabase.PExecuteLog("DELETE FROM waypoint_scripts WHERE guid = %u", id); + PSendSysMessage("%s%s%u|r","|cff00ff00","Wp Event: Waypoint script removed: ", id); + } + else + PSendSysMessage("|cffff33ffWp Event: ERROR: you have selected a non existing script: %u|r", id); + + return true; + } + + if (show == "mod") + { + if (!arg_id) + { + SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r"); + return true; + } + + id = atoi(arg_id); + + if (!id) + { + SendSysMessage("|cffff33ffERROR: No vallid waypoint script id not present.|r"); + return true; + } + + char* arg_2 = strtok(NULL," "); + + if (!arg_2) + { + SendSysMessage("|cffff33ffERROR: No argument present.|r"); + return true; + } + + std::string arg_string = arg_2; + + if ((arg_string != "setid") && (arg_string != "delay") && (arg_string != "command") + && (arg_string != "datalong") && (arg_string != "datalong2") && (arg_string != "dataint") && (arg_string != "posx") + && (arg_string != "posy") && (arg_string != "posz") && (arg_string != "orientation")) + { + SendSysMessage("|cffff33ffERROR: No valid argument present.|r"); + return true; + } + + char* arg_3; + std::string arg_str_2 = arg_2; + arg_3 = strtok(NULL," "); + + if (!arg_3) + { + SendSysMessage("|cffff33ffERROR: No additional argument present.|r"); + return true; + } + + float coord; + + if (arg_str_2 == "setid") + { + uint32 newid = atoi(arg_3); + PSendSysMessage("%s%s|r|cff00ffff%u|r|cff00ff00%s|r|cff00ffff%u|r","|cff00ff00","Wp Event: Wypoint scipt guid: ", newid," id changed: ", id); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET id='%u' WHERE guid='%u'", + newid, id); return true; + } + else + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid='%u'",id); + + if (!result) + { + SendSysMessage("|cffff33ffERROR: You have selected an non existing waypoint script guid.|r"); + return true; + } + + if (arg_str_2 == "posx") + { + coord = atof(arg_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET x='%f' WHERE guid='%u'", + coord, id); + PSendSysMessage("|cff00ff00Waypoint script:|r|cff00ffff %u|r|cff00ff00 position_x updated.|r", id); + return true; + } + else if (arg_str_2 == "posy") + { + coord = atof(arg_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET y='%f' WHERE guid='%u'", + coord, id); + PSendSysMessage("|cff00ff00Waypoint script: %u position_y updated.|r", id); + return true; + } + else if (arg_str_2 == "posz") + { + coord = atof(arg_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET z='%f' WHERE guid='%u'", + coord, id); + PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 position_z updated.|r", id); + return true; + } + else if (arg_str_2 == "orientation") + { + coord = atof(arg_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET o='%f' WHERE guid='%u'", + coord, id); + PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 orientation updated.|r", id); + return true; + } + else if (arg_str_2 == "dataint") + { + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%u' WHERE guid='%u'", + arg_2, atoi(arg_3), id); + PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 dataint updated.|r", id); + return true; + } + else + { + std::string arg_str_3 = arg_3; + WorldDatabase.escape_string(arg_str_3); + WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'", + arg_2, arg_str_3.c_str(), id); + } + } + PSendSysMessage("%s%s|r|cff00ffff%u:|r|cff00ff00 %s %s|r","|cff00ff00","Waypoint script:", id, arg_2,"updated."); + } + return true; +} + +bool ChatHandler::HandleWpModifyCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpModifyCommand"); + + if (!*args) + return false; + + // first arg: add del text emote spell waittime move + char* show_str = strtok((char*)args, " "); + if (!show_str) + { + return false; + } + + std::string show = show_str; + // Check + // Remember: "show" must also be the name of a column! + if ((show != "delay") && (show != "action") && (show != "action_chance") + && (show != "move_flag") && (show != "del") && (show != "move") && (show != "wpadd") +) + { + return false; + } + + // Next arg is: + char* arg_str = NULL; + + // Did user provide a GUID + // or did the user select a creature? + // -> variable lowguid is filled with the GUID of the NPC + uint32 pathid = 0; + uint32 point = 0; + uint32 wpGuid = 0; + Creature* target = getSelectedCreature(); + + if (!target || target->GetEntry() != VISUAL_WAYPOINT) + { + SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r"); + return false; + } + + sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC"); + // The visual waypoint + Creature* wpCreature = NULL; + wpGuid = target->GetGUIDLow(); + + // Did the user select a visual spawnpoint? + if (wpGuid) + wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + // attempt check creature existence by DB data + else + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, wpGuid); + return false; + } + // User did select a visual waypoint? + // Check the creature + if (wpCreature->GetEntry() == VISUAL_WAYPOINT) + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE wpguid = %u", wpGuid); + + if (!result) + { + sLog.outDebug("DEBUG: HandleWpModifyCommand - No waypoint found - used 'wpguid'"); + + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow()); + // Select waypoint number from database + // Since we compare float values, we have to deal with + // some difficulties. + // Here we search for all waypoints that only differ in one from 1 thousand + // (0.001) - There is no other way to compare C++ floats with mySQL floats + // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html + const char* maxDIFF = "0.01"; + result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE (abs(position_x - %f) <= %s) and (abs(position_y - %f) <= %s) and (abs(position_z - %f) <= %s)", + wpCreature->GetPositionX(), maxDIFF, wpCreature->GetPositionY(), maxDIFF, wpCreature->GetPositionZ(), maxDIFF); + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid); + return true; + } + } + sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid"); + + do + { + Field *fields = result->Fetch(); + pathid = fields[0].GetUInt32(); + point = fields[1].GetUInt32(); + } + while (result->NextRow()); + + // We have the waypoint number and the GUID of the "master npc" + // Text is enclosed in "<>", all other arguments not + arg_str = strtok((char*)NULL, " "); + } + + sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command"); + + // Check for argument + if (show != "del" && show != "move" && arg_str == NULL) + { + PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str); + return false; + } + + if (show == "del" && target) + { + PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); + + // wpCreature + Creature* wpCreature = NULL; + + if (wpGuid != 0) + { + wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + wpCreature->CombatStop(); + wpCreature->DeleteFromDB(); + wpCreature->AddObjectToRemoveList(); + } + + WorldDatabase.PExecuteLog("DELETE FROM waypoint_data WHERE id='%u' AND point='%u'", + pathid, point); + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET point=point-1 WHERE id='%u' AND point>'%u'", + pathid, point); + + PSendSysMessage(LANG_WAYPOINT_REMOVED); + return true; + } // del + + if (show == "move" && target) + { + PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid); + + Player *chr = m_session->GetPlayer(); + Map *map = chr->GetMap(); + { + // wpCreature + Creature* wpCreature = NULL; + // What to do: + // Move the visual spawnpoint + // Respawn the owner of the waypoints + if (wpGuid != 0) + { + wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + wpCreature->CombatStop(); + wpCreature->DeleteFromDB(); + wpCreature->AddObjectToRemoveList(); + // re-create + Creature* wpCreature2 = new Creature; + if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + delete wpCreature2; + return false; + } + + wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map); + map->Add(wpCreature2); + //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2); + } + + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'", + chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), pathid, point); + + PSendSysMessage(LANG_WAYPOINT_CHANGED); + } + return true; + } // move + + const char *text = arg_str; + + if (text == 0) + { + // show_str check for present in list of correct values, no sql injection possible + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'", + show_str, pathid, point); + } + else + { + // show_str check for present in list of correct values, no sql injection possible + std::string text2 = text; + WorldDatabase.escape_string(text2); + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'", + show_str, text2.c_str(), pathid, point); + } + + PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str); + return true; +} + +bool ChatHandler::HandleWpShowCommand(const char* args) +{ + sLog.outDebug("DEBUG: HandleWpShowCommand"); + + if (!*args) + return false; + + // first arg: on, off, first, last + char* show_str = strtok((char*)args, " "); + if (!show_str) + return false; + + // second arg: GUID (optional, if a creature is selected) + char* guid_str = strtok((char*)NULL, " "); + sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str); + + uint32 pathid = 0; + Creature* target = getSelectedCreature(); + + // Did player provide a PathID? + + if (!guid_str) + { + sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str"); + // No PathID provided + // -> Player must have selected a creature + + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pathid = target->GetWaypointPath(); + } + else + { + sLog.outDebug("|cff00ff00DEBUG: HandleWpShowCommand: PathID provided|r"); + // PathID provided + // Warn if player also selected a creature + // -> Creature selection is ignored <- + if (target) + SendSysMessage(LANG_WAYPOINT_CREATSELECTED); + + pathid = atoi((char*)guid_str); + } + + sLog.outDebug("DEBUG: HandleWpShowCommand: danach"); + + std::string show = show_str; + uint32 Maxpoint; + + sLog.outDebug("DEBUG: HandleWpShowCommand: PathID: %u", pathid); + + //PSendSysMessage("wpshow - show: %s", show); + + // Show info for the selected waypoint + if (show == "info") + { + // Check if the user did specify a visual waypoint + if (target->GetEntry() != VISUAL_WAYPOINT) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id, point, delay, move_flag, action, action_chance FROM waypoint_data WHERE wpguid = %u", target->GetGUIDLow()); + + if (!result) + { + SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM); + return true; + } + + SendSysMessage("|cff00ffffDEBUG: wp show info:|r"); + do + { + Field *fields = result->Fetch(); + pathid = fields[0].GetUInt32(); + uint32 point = fields[1].GetUInt32(); + uint32 delay = fields[2].GetUInt32(); + uint32 flag = fields[3].GetUInt32(); + uint32 ev_id = fields[4].GetUInt32(); + uint32 ev_chance = fields[5].GetUInt32(); + + PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff%u|r|cff00ff00, Path ID: |r|cff00ffff%u|r", point, pathid); + PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff%u|r", delay); + PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff%u|r", flag); + PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff%u|r", ev_id); + PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff%u|r", ev_chance); + } + while (result->NextRow()); + + return true; + } + + if (show == "on") + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT point, position_x,position_y,position_z FROM waypoint_data WHERE id = '%u'", pathid); + + if (!result) + { + SendSysMessage("|cffff33ffPath no found.|r"); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff%u|r", pathid); + + // Delete all visuals for this NPC + QueryResult_AutoPtr result2 = WorldDatabase.PQuery("SELECT wpguid FROM waypoint_data WHERE id = '%u' and wpguid <> 0", pathid); + + if (result2) + { + bool hasError = false; + do + { + Field *fields = result2->Fetch(); + uint32 wpguid = fields[0].GetUInt32(); + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + + if (!pCreature) + { + PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid); + hasError = true; + WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid); + } + else + { + pCreature->CombatStop(); + pCreature->DeleteFromDB(); + pCreature->AddObjectToRemoveList(); + } + + } + while (result2->NextRow()); + + if (hasError) + { + PSendSysMessage(LANG_WAYPOINT_TOOFAR1); + PSendSysMessage(LANG_WAYPOINT_TOOFAR2); + PSendSysMessage(LANG_WAYPOINT_TOOFAR3); + } + } + + do + { + Field *fields = result->Fetch(); + uint32 point = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + Map *map = chr->GetMap(); + float o = chr->GetOrientation(); + + Creature* wpCreature = new Creature; + if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); + delete wpCreature; + return false; + } + + sLog.outDebug("DEBUG: UPDATE waypoint_data SET wpguid = '%u"); + // set "wpguid" column to the visual waypoint + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point); + + wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map); + map->Add(wpCreature); + + if (target) + { + wpCreature->SetDisplayId(target->GetDisplayId()); + wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); + wpCreature->SetLevel(point > MAX_LEVEL ? MAX_LEVEL : point); + } + } + while (result->NextRow()); + + SendSysMessage("|cff00ff00Showing the current creature's path.|r"); + return true; + } + + if (show == "first") + { + PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: %u|r", pathid); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z FROM waypoint_data WHERE point='1' AND id = '%u'",pathid); + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid); + SetSentErrorMessage(true); + return false; + } + + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); + delete pCreature; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); + map->Add(pCreature); + + if (target) + { + pCreature->SetDisplayId(target->GetDisplayId()); + pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); + } + + return true; + } + + if (show == "last") + { + PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff%u|r", pathid); + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid); + if (result) + Maxpoint = (*result)[0].GetUInt32(); + else + Maxpoint = 0; + + result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z FROM waypoint_data WHERE point ='%u' AND id = '%u'",Maxpoint, pathid); + if (!result) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid); + SetSentErrorMessage(true); + return false; + } + Field *fields = result->Fetch(); + float x = fields[0].GetFloat(); + float y = fields[1].GetFloat(); + float z = fields[2].GetFloat(); + uint32 id = VISUAL_WAYPOINT; + + Player *chr = m_session->GetPlayer(); + float o = chr->GetOrientation(); + Map *map = chr->GetMap(); + + Creature* pCreature = new Creature; + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) + { + PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); + delete pCreature; + return false; + } + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); + map->Add(pCreature); + + if (target) + { + pCreature->SetDisplayId(target->GetDisplayId()); + pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); + } + + return true; + } + + if (show == "off") + { + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%u'", 1); + if (!result) + { + SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + bool hasError = false; + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + if (!pCreature) + { + PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); + hasError = true; + WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid); + } + else + { + pCreature->CombatStop(); + pCreature->DeleteFromDB(); + pCreature->AddObjectToRemoveList(); + } + } + while (result->NextRow()); + // set "wpguid" column to "empty" - no visual waypoint spawned + WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '0'"); + //WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'"); + + if (hasError) + { + PSendSysMessage(LANG_WAYPOINT_TOOFAR1); + PSendSysMessage(LANG_WAYPOINT_TOOFAR2); + PSendSysMessage(LANG_WAYPOINT_TOOFAR3); + } + + SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); + return true; + } + + PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r"); + return true; +} + +//////////// WAYPOINT COMMANDS // + +//rename characters +bool ChatHandler::HandleCharacterRenameCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + if (target) + { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_RENAME); + } + else + { + // check offline security + if (HasLowerSecurity(NULL, target_guid)) + return false; + + std::string oldNameLink = playerLink(target_name); + + PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(target_guid)); + } + + return true; +} + +// customize characters +bool ChatHandler::HandleCharacterCustomizeCommand(const char* args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + if (target) + { + PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow()); + } + else + { + std::string oldNameLink = playerLink(target_name); + + PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(target_guid)); + } + + return true; +} + +bool ChatHandler::HandleCharacterReputationCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + LocaleConstant loc = GetSessionDbcLocale(); + + FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList(); + for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID); + char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#"; + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); + std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]); + std::ostringstream ss; + if (m_session) + ss << itr->second.ID << " - |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << " " << localeNames[loc] << "]|h|r"; + else + ss << itr->second.ID << " - " << factionName << " " << localeNames[loc]; + + ss << " " << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; + + if (itr->second.Flags & FACTION_FLAG_VISIBLE) + ss << GetTrinityString(LANG_FACTION_VISIBLE); + if (itr->second.Flags & FACTION_FLAG_AT_WAR) + ss << GetTrinityString(LANG_FACTION_ATWAR); + if (itr->second.Flags & FACTION_FLAG_PEACE_FORCED) + ss << GetTrinityString(LANG_FACTION_PEACE_FORCED); + if (itr->second.Flags & FACTION_FLAG_HIDDEN) + ss << GetTrinityString(LANG_FACTION_HIDDEN); + if (itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED) + ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED); + if (itr->second.Flags & FACTION_FLAG_INACTIVE) + ss << GetTrinityString(LANG_FACTION_INACTIVE); + + SendSysMessage(ss.str().c_str()); + } + return true; +} + +//change standstate +bool ChatHandler::HandleModifyStandStateCommand(const char* args) +{ + if (!*args) + return false; + + uint32 anim_id = atoi((char*)args); + m_session->GetPlayer()->SetUInt32Value(UNIT_NPC_EMOTESTATE , anim_id); + + return true; +} + +bool ChatHandler::HandleHonorAddCommand(const char* args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + uint32 amount = (uint32)atoi(args); + target->RewardHonor(NULL, 1, amount); + return true; +} + +bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/) +{ + Unit *target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + m_session->GetPlayer()->RewardHonor(target, 1); + return true; +} + +bool ChatHandler::HandleHonorUpdateCommand(const char* /*args*/) +{ + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + target->UpdateHonorFields(); + return true; +} + +bool ChatHandler::HandleLookupEventCommand(const char* args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + for (uint32 id = 0; id < events.size(); ++id) + { + GameEventData const& eventData = events[id]; + + std::string descr = eventData.description; + if (descr.empty()) + continue; + + if (Utf8FitTo(descr, wnamepart)) + { + char const* active = activeEvents.find(id) != activeEvents.end() ? GetTrinityString(LANG_ACTIVE) : ""; + + if (m_session) + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active); + else + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage(LANG_NOEVENTFOUND); + + return true; +} + +bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/) +{ + uint32 counter = 0; + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + char const* active = GetTrinityString(LANG_ACTIVE); + + for (GameEventMgr::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr) + { + uint32 event_id = *itr; + GameEventData const& eventData = events[event_id]; + + if (m_session) + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active); + else + PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active); + + ++counter; + } + + if (counter == 0) + SendSysMessage(LANG_NOEVENTFOUND); + + return true; +} + +bool ChatHandler::HandleEventInfoCommand(const char* args) +{ + if (!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if (!cId) + return false; + + uint32 event_id = atoi(cId); + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if (event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if (!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + bool active = activeEvents.find(event_id) != activeEvents.end(); + char const* activeStr = active ? GetTrinityString(LANG_ACTIVE) : ""; + + std::string startTimeStr = TimeToTimestampStr(eventData.start); + std::string endTimeStr = TimeToTimestampStr(eventData.end); + + uint32 delay = gameeventmgr.NextCheck(event_id); + time_t nextTime = time(NULL)+delay; + std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-"; + + std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE); + std::string lengthStr = secsToTimeString(eventData.length * MINUTE); + + PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr, + startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(), + nextStr.c_str()); + return true; +} + +bool ChatHandler::HandleEventStartCommand(const char* args) +{ + if (!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if (!cId) + return false; + + int32 event_id = atoi(cId); + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if (event_id < 1 || event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if (!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + if (activeEvents.find(event_id) != activeEvents.end()) + { + PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id); + SetSentErrorMessage(true); + return false; + } + + gameeventmgr.StartEvent(event_id,true); + return true; +} + +bool ChatHandler::HandleEventStopCommand(const char* args) +{ + if (!*args) + return false; + + // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameevent"); + if (!cId) + return false; + + int32 event_id = atoi(cId); + + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + + if (event_id < 1 || event_id >=events.size()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventData const& eventData = events[event_id]; + if (!eventData.isValid()) + { + SendSysMessage(LANG_EVENT_NOT_EXIST); + SetSentErrorMessage(true); + return false; + } + + GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); + + if (activeEvents.find(event_id) == activeEvents.end()) + { + PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id); + SetSentErrorMessage(true); + return false; + } + + gameeventmgr.StopEvent(event_id,true); + return true; +} + +bool ChatHandler::HandleCombatStopCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + target->CombatStop(); + target->getHostileRefManager().deleteReferences(); + return true; +} + +void ChatHandler::HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id) +{ + uint32 classmask = player->getClassMask(); + + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) + { + SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); + if (!skillLine) + continue; + + // wrong skill + if (skillLine->skillId != skill_id) + continue; + + // not high rank + if (skillLine->forward_spellid) + continue; + + // skip racial skills + if (skillLine->racemask != 0) + continue; + + // skip wrong class skills + if (skillLine->classmask && (skillLine->classmask & classmask) == 0) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,player,false)) + continue; + + player->learnSpell(skillLine->spellId, false); + } +} + +bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/) +{ + + for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i); + if (!skillInfo) + continue; + + if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) && + skillInfo->canLink) // only prof. with recipes have + { + HandleLearnSkillRecipesHelper(m_session->GetPlayer(),skillInfo->id); + } + } + + SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT); + return true; +} + +bool ChatHandler::HandleLearnAllRecipesCommand(const char* args) +{ + // Learns all recipes of specified profession and sets skill to max + // Example: .learn all_recipes enchanting + + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + return false; + } + + if (!*args) + return false; + + std::wstring wnamepart; + + if (!Utf8toWStr(args,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + std::string name; + + SkillLineEntry const *targetSkillInfo = NULL; + for (uint32 i = 1; i < sSkillLineStore.GetNumRows(); ++i) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i); + if (!skillInfo) + continue; + + if ((skillInfo->categoryId != SKILL_CATEGORY_PROFESSION && + skillInfo->categoryId != SKILL_CATEGORY_SECONDARY) || + !skillInfo->canLink) // only prof with recipes have set + continue; + + int loc = GetSessionDbcLocale(); + name = skillInfo->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = skillInfo->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + targetSkillInfo = skillInfo; + break; + } + } + + if (!targetSkillInfo) + return false; + + HandleLearnSkillRecipesHelper(target,targetSkillInfo->id); + + uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id); + target->SetSkill(targetSkillInfo->id, target->GetSkillStep(targetSkillInfo->id), maxLevel, maxLevel); + PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str()); + return true; +} + +bool ChatHandler::HandleLookupPlayerIpCommand(const char* args) +{ + + if (!*args) + return false; + + std::string ip = strtok ((char*)args, " "); + char* limit_str = strtok (NULL, " "); + int32 limit = limit_str ? atoi (limit_str) : -1; + + LoginDatabase.escape_string (ip); + + QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ()); + + return LookupPlayerSearchCommand (result,limit); +} + +bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args) +{ + if (!*args) + return false; + + std::string account = strtok ((char*)args, " "); + char* limit_str = strtok (NULL, " "); + int32 limit = limit_str ? atoi (limit_str) : -1; + + if (!AccountMgr::normalizeString (account)) + return false; + + LoginDatabase.escape_string (account); + + QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ()); + + return LookupPlayerSearchCommand (result,limit); +} + +bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args) +{ + + if (!*args) + return false; + + std::string email = strtok ((char*)args, " "); + char* limit_str = strtok (NULL, " "); + int32 limit = limit_str ? atoi (limit_str) : -1; + + LoginDatabase.escape_string (email); + + QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ()); + + return LookupPlayerSearchCommand (result,limit); +} + +bool ChatHandler::LookupPlayerSearchCommand(QueryResult_AutoPtr result, int32 limit) +{ + if (!result) + { + PSendSysMessage(LANG_NO_PLAYERS_FOUND); + SetSentErrorMessage(true); + return false; + } + + int i =0; + do + { + Field* fields = result->Fetch(); + uint32 acc_id = fields[0].GetUInt32(); + std::string acc_name = fields[1].GetCppString(); + + QueryResult_AutoPtr chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id); + if (chars) + { + PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id); + + uint64 guid = 0; + std::string name; + + do + { + Field* charfields = chars->Fetch(); + guid = charfields[0].GetUInt64(); + name = charfields[1].GetCppString(); + + PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid); + ++i; + + } while (chars->NextRow() && (limit == -1 || i < limit)); + } + } while (result->NextRow()); + + if (i == 0) // empty accounts only + { + PSendSysMessage(LANG_NO_PLAYERS_FOUND); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +/// Triggering corpses expire check in world +bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/) +{ + CorpsesErase(); + return true; +} + +bool ChatHandler::HandleRepairitemsCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + // Repair items + target->DurabilityRepairAll(false, 0, false); + + PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str()); + if (needReportToTarget(target)) + ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str()); + return true; +} + +bool ChatHandler::HandleWaterwalkCommand(const char* args) +{ + if (!*args) + return false; + + Player *player = getSelectedPlayer(); + + if (!player) + { + PSendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(player, 0)) + return false; + + if (strncmp(args, "on", 3) == 0) + player->SetMovement(MOVE_WATER_WALK); // ON + else if (strncmp(args, "off", 4) == 0) + player->SetMovement(MOVE_LAND_WALK); // OFF + else + { + SendSysMessage(LANG_USE_BOL); + return false; + } + + PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str()); + if (needReportToTarget(player)) + ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str()); + return true; +} + +bool ChatHandler::HandleCreatePetCommand(const char* /*args*/) +{ + Player *player = m_session->GetPlayer(); + Creature *creatureTarget = getSelectedCreature(); + + if (!creatureTarget || creatureTarget->isPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) + { + PSendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(creatureTarget->GetEntry()); + // Creatures with family 0 crashes the server + if (cInfo->family == 0) + { + PSendSysMessage("This creature cannot be tamed. (family id: 0)."); + SetSentErrorMessage(true); + return false; + } + + if (player->GetPetGUID()) + { + PSendSysMessage("You already have a pet"); + SetSentErrorMessage(true); + return false; + } + + // Everything looks OK, create new pet + Pet* pet = new Pet(player, HUNTER_PET); + + if (!pet) + return false; + + if (!pet->CreateBaseAtCreature(creatureTarget)) + { + delete pet; + PSendSysMessage("Error 1"); + return false; + } + + creatureTarget->setDeathState(JUST_DIED); + creatureTarget->RemoveCorpse(); + creatureTarget->SetHealth(0); // just for nice GM-mode view + + pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); + pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); + + if (!pet->InitStatsForLevel(creatureTarget->getLevel())) + { + sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); + PSendSysMessage("Error 2"); + delete pet; + return false; + } + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); + + pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true); + // this enables pet details window (Shift+P) + pet->InitPetCreateSpells(); + pet->SetHealth(pet->GetMaxHealth()); + + pet->GetMap()->Add(pet->ToCreature()); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); + + player->SetMinion(pet, true); + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + player->PetSpellInitialize(); + + return true; +} + +bool ChatHandler::HandlePetLearnCommand(const char* args) +{ + if (!*args) + return false; + + Player *plr = m_session->GetPlayer(); + Pet *pet = plr->GetPet(); + + if (!pet) + { + PSendSysMessage("You have no pet"); + SetSentErrorMessage(true); + return false; + } + + uint32 spellId = extractSpellIdFromLink((char*)args); + + if (!spellId || !sSpellStore.LookupEntry(spellId)) + return false; + + // Check if pet already has it + if (pet->HasSpell(spellId)) + { + PSendSysMessage("Pet already has spell: %u", spellId); + SetSentErrorMessage(true); + return false; + } + + // Check if spell is valid + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spellId); + SetSentErrorMessage(true); + return false; + } + + pet->learnSpell(spellId); + + PSendSysMessage("Pet has learned spell %u", spellId); + return true; +} + +bool ChatHandler::HandlePetUnlearnCommand(const char *args) +{ + if (!*args) + return false; + + Player *plr = m_session->GetPlayer(); + Pet *pet = plr->GetPet(); + + if (!pet) + { + PSendSysMessage("You have no pet"); + SetSentErrorMessage(true); + return false; + } + + uint32 spellId = extractSpellIdFromLink((char*)args); + + if (pet->HasSpell(spellId)) + pet->removeSpell(spellId, false); + else + PSendSysMessage("Pet doesn't have that spell"); + + return true; +} + +bool ChatHandler::HandlePetTpCommand(const char *args) +{ + if (!*args) + return false; + + Player *plr = m_session->GetPlayer(); + Pet *pet = plr->GetPet(); + + if (!pet) + { + PSendSysMessage("You have no pet"); + SetSentErrorMessage(true); + return false; + } + + uint32 tp = atol(args); + + //pet->SetTP(tp); + + PSendSysMessage("Pet's tp changed to %u", tp); + return true; +} + +bool ChatHandler::HandleActivateObjectCommand(const char *args) +{ + if (!*args) + return false; + + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* obj = NULL; + + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if (!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + // Activate + obj->SetLootState(GO_READY); + obj->UseDoorOrButton(10000); + + PSendSysMessage("Object activated!"); + + return true; +} + +// add creature, temp only +bool ChatHandler::HandleTempAddSpwCommand(const char* args) +{ + if (!*args) + return false; + char* charID = strtok((char*)args, " "); + if (!charID) + return false; + + Player *chr = m_session->GetPlayer(); + + uint32 id = atoi(charID); + if (!id) + return false; + + chr->SummonCreature(id, *chr, TEMPSUMMON_CORPSE_DESPAWN, 120); + + return true; +} + +// add go, temp only +bool ChatHandler::HandleTempGameObjectCommand(const char* args) +{ + if (!*args) + return false; + char* charID = strtok((char*)args, " "); + if (!charID) + return false; + + Player *chr = m_session->GetPlayer(); + + char* spawntime = strtok(NULL, " "); + uint32 spawntm = 300; + + if (spawntime) + spawntm = atoi((char*)spawntime); + + float x = chr->GetPositionX(); + float y = chr->GetPositionY(); + float z = chr->GetPositionZ(); + float ang = chr->GetOrientation(); + + float rot2 = sin(ang/2); + float rot3 = cos(ang/2); + + uint32 id = atoi(charID); + + chr->SummonGameObject(id,x,y,z,ang,0,0,rot2,rot3,spawntm); + + return true; +} + +bool ChatHandler::HandleNpcAddFormationCommand(const char* args) +{ + if (!*args) + return false; + + uint32 leaderGUID = (uint32) atoi((char*)args); + Creature *pCreature = getSelectedCreature(); + + if (!pCreature || !pCreature->GetDBTableGUIDLow()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint32 lowguid = pCreature->GetDBTableGUIDLow(); + if (pCreature->GetFormation()) + { + PSendSysMessage("Selected creature is already member of group %u", pCreature->GetFormation()->GetId()); + return false; + } + + if (!lowguid) + return false; + + Player *chr = m_session->GetPlayer(); + FormationInfo *group_member; + + group_member = new FormationInfo; + group_member->follow_angle = (pCreature->GetAngle(chr) - chr->GetOrientation()) * 180 / M_PI; + group_member->follow_dist = sqrtf(pow(chr->GetPositionX() - pCreature->GetPositionX(),int(2))+pow(chr->GetPositionY()-pCreature->GetPositionY(),int(2))); + group_member->leaderGUID = leaderGUID; + group_member->groupAI = 0; + + CreatureGroupMap[lowguid] = group_member; + pCreature->SearchFormation(); + + WorldDatabase.PExecuteLog("INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES ('%u','%u','%f', '%f', '%u')", + leaderGUID, lowguid, group_member->follow_dist, group_member->follow_angle, group_member->groupAI); + + PSendSysMessage("Creature %u added to formation with leader %u", lowguid, leaderGUID); + + return true; + } + +bool ChatHandler::HandleNpcSetLinkCommand(const char* args) +{ + if (!*args) + return false; + + uint32 linkguid = (uint32) atoi((char*)args); + + Creature* pCreature = getSelectedCreature(); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!pCreature->GetDBTableGUIDLow()) + { + PSendSysMessage("Selected creature isn't in creature table", pCreature->GetGUIDLow()); + SetSentErrorMessage(true); + return false; + } + + if (!objmgr.SetCreatureLinkedRespawn(pCreature->GetDBTableGUIDLow(), linkguid)) + { + PSendSysMessage("Selected creature can't link with guid '%u'", linkguid); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage("LinkGUID '%u' added to creature with DBTableGUID: '%u'", linkguid, pCreature->GetDBTableGUIDLow()); + return true; +} + +bool ChatHandler::HandleLookupTitleCommand(const char* args) +{ + if (!*args) + return false; + + // can be NULL in console call + Player* target = getSelectedPlayer(); + + // title name have single string arg for player name + char const* targetName = target ? target->GetName() : "NAME"; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + uint32 counter = 0; // Counter for figure out that we found smth. + + // Search in CharTitles.dbc + for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) + { + CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id); + if (titleInfo) + { + int loc = GetSessionDbcLocale(); + std::string name = titleInfo->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = titleInfo->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + char const* knownStr = target && target->HasTitle(titleInfo) ? GetTrinityString(LANG_KNOWN) : ""; + + char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index + ? GetTrinityString(LANG_ACTIVE) + : ""; + + char titleNameStr[80]; + snprintf(titleNameStr,80,name.c_str(),targetName); + + // send title in "id (idx:idx) - [namedlink locale]" format + if (m_session) + PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr); + else + PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,titleNameStr,localeNames[loc],knownStr,activeStr); + + ++counter; + } + } + } + if (counter == 0) // if counter == 0 then we found nth + SendSysMessage(LANG_COMMAND_NOTITLEFOUND); + return true; +} + +bool ChatHandler::HandleTitlesAddCommand(const char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + char* id_p = extractKeyFromLink((char*)args,"Htitle"); + if (!id_p) + return false; + + int32 id = atoi(id_p); + if (id <= 0) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + Player * target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (!titleInfo) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + std::string tNameLink = GetNameLink(target); + + char const* targetName = target->GetName(); + char titleNameStr[80]; + snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName); + + target->SetTitle(titleInfo); + PSendSysMessage(LANG_TITLE_ADD_RES, id, titleNameStr, tNameLink.c_str()); + + return true; +} + +bool ChatHandler::HandleTitlesRemoveCommand(const char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + char* id_p = extractKeyFromLink((char*)args,"Htitle"); + if (!id_p) + return false; + + int32 id = atoi(id_p); + if (id <= 0) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + Player * target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (!titleInfo) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + target->SetTitle(titleInfo,true); + + std::string tNameLink = GetNameLink(target); + + char const* targetName = target->GetName(); + char titleNameStr[80]; + snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName); + + PSendSysMessage(LANG_TITLE_REMOVE_RES, id, titleNameStr, tNameLink.c_str()); + + if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE))) + { + target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0); + PSendSysMessage(LANG_CURRENT_TITLE_RESET, tNameLink.c_str()); + } + + return true; +} + +//Edit Player KnownTitles +bool ChatHandler::HandleTitlesSetMaskCommand(const char* args) +{ + if (!*args) + return false; + + uint64 titles = 0; + + sscanf((char*)args, UI64FMTD, &titles); + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + uint64 titles2 = titles; + + for (uint32 i = 1; i < sCharTitlesStore.GetNumRows(); ++i) + if (CharTitlesEntry const* tEntry = sCharTitlesStore.LookupEntry(i)) + titles2 &= ~(uint64(1) << tEntry->bit_index); + + titles &= ~titles2; // remove not existed titles + + target->SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES, titles); + SendSysMessage(LANG_DONE); + + if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE))) + { + target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0); + PSendSysMessage(LANG_CURRENT_TITLE_RESET,GetNameLink(target).c_str()); + } + + return true; +} + +bool ChatHandler::HandleCharacterTitlesCommand(const char* args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + LocaleConstant loc = GetSessionDbcLocale(); + char const* targetName = target->GetName(); + char const* knownStr = GetTrinityString(LANG_KNOWN); + + // Search in CharTitles.dbc + for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) + { + CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id); + if (titleInfo && target->HasTitle(titleInfo)) + { + std::string name = titleInfo->name[loc]; + if (name.empty()) + continue; + + char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index + ? GetTrinityString(LANG_ACTIVE) + : ""; + + char titleNameStr[80]; + snprintf(titleNameStr,80,name.c_str(),targetName); + + // send title in "id (idx:idx) - [namedlink locale]" format + if (m_session) + PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr); + else + PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,name.c_str(),localeNames[loc],knownStr,activeStr); + } + } + return true; +} + +bool ChatHandler::HandleTitlesCurrentCommand(const char* args) +{ + // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r + char* id_p = extractKeyFromLink((char*)args,"Htitle"); + if (!id_p) + return false; + + int32 id = atoi(id_p); + if (id <= 0) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + Player * target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + if (!titleInfo) + { + PSendSysMessage(LANG_INVALID_TITLE_ID, id); + SetSentErrorMessage(true); + return false; + } + + std::string tNameLink = GetNameLink(target); + + target->SetTitle(titleInfo); // to be sure that title now known + target->SetUInt32Value(PLAYER_CHOSEN_TITLE,titleInfo->bit_index); + + PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name[GetSessionDbcLocale()], tNameLink.c_str()); + + return true; +} diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp new file mode 100644 index 00000000000..f7ced44922b --- /dev/null +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -0,0 +1,7743 @@ +/* +* Copyright (C) 2005-2009 MaNGOS +* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "AuctionHouseMgr.h" +#include "AccountMgr.h" +#include "PlayerDump.h" +#include "SpellMgr.h" +#include "Player.h" +#include "Opcodes.h" +#include "GameObject.h" +#include "Chat.h" +#include "Log.h" +#include "Guild.h" +#include "ObjectAccessor.h" +#include "MapManager.h" +#include "Language.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" +#include "Weather.h" +#include "PointMovementGenerator.h" +#include "TargetedMovementGenerator.h" +#include "SkillDiscovery.h" +#include "SkillExtraItems.h" +#include "SystemConfig.h" +#include "Config/ConfigEnv.h" +#include "Util.h" +#include "ItemEnchantmentMgr.h" +#include "BattleGroundMgr.h" +#include "InstanceSaveMgr.h" +#include "InstanceData.h" +#include "AuctionHouseBot.h" +#include "CreatureEventAIMgr.h" +#include "SpellAuraEffects.h" +#include "DBCEnums.h" +#include "ConditionMgr.h" + +bool ChatHandler::HandleAHBotOptionsCommand(const char *args) +{ + uint32 ahMapID = 0; + char * opt = strtok((char*)args, " "); + char * ahMapIdStr = strtok(NULL, " "); + if (ahMapIdStr) + { + ahMapID = (uint32) strtoul(ahMapIdStr, NULL, 0); + switch (ahMapID) + { + case 2: + case 6: + case 7: + break; + default: + opt = NULL; + break; + } + } + if (!opt) + { + PSendSysMessage("Syntax is: ahbotoptions $option $ahMapID (2, 6 or 7) $parameter"); + PSendSysMessage("Try ahbotoptions help to see a list of options."); + return false; + } + int l = strlen(opt); + + if (strncmp(opt,"help",l) == 0) + { + PSendSysMessage("AHBot commands:"); + PSendSysMessage("ahexpire"); + PSendSysMessage("minitems"); + PSendSysMessage("maxitems"); + //PSendSysMessage(""); + //PSendSysMessage(""); + PSendSysMessage("percentages"); + PSendSysMessage("minprice"); + PSendSysMessage("maxprice"); + PSendSysMessage("minbidprice"); + PSendSysMessage("maxbidprice"); + PSendSysMessage("maxstack"); + PSendSysMessage("buyerprice"); + PSendSysMessage("bidinterval"); + PSendSysMessage("bidsperinterval"); + return true; + } + else if (strncmp(opt,"ahexpire",l) == 0) + { + if (!ahMapIdStr) + { + PSendSysMessage("Syntax is: ahbotoptions ahexpire $ahMapID (2, 6 or 7)"); + return false; + } + auctionbot.Commands(0, ahMapID, NULL, NULL); + } + else if (strncmp(opt,"minitems",l) == 0) + { + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions minitems $ahMapID (2, 6 or 7) $minItems"); + return false; + } + auctionbot.Commands(1, ahMapID, NULL, param1); + } + else if (strncmp(opt,"maxitems",l) == 0) + { + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions maxitems $ahMapID (2, 6 or 7) $maxItems"); + return false; + } + auctionbot.Commands(2, ahMapID, NULL, param1); + } + else if (strncmp(opt,"mintime",l) == 0) + { + PSendSysMessage("ahbotoptions mintime has been deprecated"); + return false; + /* + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions mintime $ahMapID (2, 6 or 7) $mintime"); + return false; + } + auctionbot.Commands(3, ahMapID, NULL, param1); + */ + } + else if (strncmp(opt,"maxtime",l) == 0) + { + PSendSysMessage("ahbotoptions maxtime has been deprecated"); + return false; + /* + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions maxtime $ahMapID (2, 6 or 7) $maxtime"); + return false; + } + auctionbot.Commands(4, ahMapID, NULL, param1); + */ + } + else if (strncmp(opt,"percentages",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + char * param3 = strtok(NULL, " "); + char * param4 = strtok(NULL, " "); + char * param5 = strtok(NULL, " "); + char * param6 = strtok(NULL, " "); + char * param7 = strtok(NULL, " "); + char * param8 = strtok(NULL, " "); + char * param9 = strtok(NULL, " "); + char * param10 = strtok(NULL, " "); + char * param11 = strtok(NULL, " "); + char * param12 = strtok(NULL, " "); + char * param13 = strtok(NULL, " "); + char * param14 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param14)) + { + PSendSysMessage("Syntax is: ahbotoptions percentages $ahMapID (2, 6 or 7) $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14"); + PSendSysMessage("1 GreyTradeGoods 2 WhiteTradeGoods 3 GreenTradeGoods 4 BlueTradeGoods 5 PurpleTradeGoods"); + PSendSysMessage("6 OrangeTradeGoods 7 YellowTradeGoods 8 GreyItems 9 WhiteItems 10 GreenItems 11 BlueItems"); + PSendSysMessage("12 PurpleItems 13 OrangeItems 14 YellowItems"); + PSendSysMessage("The total must add up to 100%"); + return false; + } + uint32 greytg = (uint32) strtoul(param1, NULL, 0); + uint32 whitetg = (uint32) strtoul(param2, NULL, 0); + uint32 greentg = (uint32) strtoul(param3, NULL, 0); + uint32 bluetg = (uint32) strtoul(param3, NULL, 0); + uint32 purpletg = (uint32) strtoul(param5, NULL, 0); + uint32 orangetg = (uint32) strtoul(param6, NULL, 0); + uint32 yellowtg = (uint32) strtoul(param7, NULL, 0); + uint32 greyi = (uint32) strtoul(param8, NULL, 0); + uint32 whitei = (uint32) strtoul(param9, NULL, 0); + uint32 greeni = (uint32) strtoul(param10, NULL, 0); + uint32 bluei = (uint32) strtoul(param11, NULL, 0); + uint32 purplei = (uint32) strtoul(param12, NULL, 0); + uint32 orangei = (uint32) strtoul(param13, NULL, 0); + uint32 yellowi = (uint32) strtoul(param14, NULL, 0); + uint32 totalPercent = greytg + whitetg + greentg + bluetg + purpletg + orangetg + yellowtg + greyi + whitei + greeni + bluei + purplei + orangei + yellowi; + if ((totalPercent == 0) || (totalPercent != 100)) + { + PSendSysMessage("Syntax is: ahbotoptions percentages $ahMapID (2, 6 or 7) $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14"); + PSendSysMessage("1 GreyTradeGoods 2 WhiteTradeGoods 3 GreenTradeGoods 4 BlueTradeGoods 5 PurpleTradeGoods"); + PSendSysMessage("6 OrangeTradeGoods 7 YellowTradeGoods 8 GreyItems 9 WhiteItems 10 GreenItems 11 BlueItems"); + PSendSysMessage("12 PurpleItems 13 OrangeItems 14 YellowItems"); + PSendSysMessage("The total must add up to 100%"); + return false; + } + char param[100]; + param[0] = '\0'; + strcat(param, param1); + strcat(param, " "); + strcat(param, param2); + strcat(param, " "); + strcat(param, param3); + strcat(param, " "); + strcat(param, param4); + strcat(param, " "); + strcat(param, param5); + strcat(param, " "); + strcat(param, param6); + strcat(param, " "); + strcat(param, param7); + strcat(param, " "); + strcat(param, param8); + strcat(param, " "); + strcat(param, param9); + strcat(param, " "); + strcat(param, param10); + strcat(param, " "); + strcat(param, param11); + strcat(param, " "); + strcat(param, param12); + strcat(param, " "); + strcat(param, param13); + strcat(param, " "); + strcat(param, param14); + auctionbot.Commands(5, ahMapID, NULL, param); + } + else if (strncmp(opt,"minprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions minprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(6, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions minprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + } + else if (strncmp(opt,"maxprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions maxprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(7, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions maxprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + } + else if (strncmp(opt,"minbidprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions minbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + uint32 minBidPrice = (uint32) strtoul(param2, NULL, 0); + if ((minBidPrice < 1) || (minBidPrice > 100)) + { + PSendSysMessage("The min bid price multiplier must be between 1 and 100"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(8, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions minbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + } + else if (strncmp(opt,"maxbidprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions maxbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + uint32 maxBidPrice = (uint32) strtoul(param2, NULL, 0); + if ((maxBidPrice < 1) || (maxBidPrice > 100)) + { + PSendSysMessage("The max bid price multiplier must be between 1 and 100"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(9, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions max bidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); + return false; + } + } + else if (strncmp(opt,"maxstack",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions maxstack $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $value"); + return false; + } + uint32 maxStack = (uint32) strtoul(param2, NULL, 0); + if (maxStack < 0) + { + PSendSysMessage("maxstack can't be a negative number."); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(10, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions maxstack $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $value"); + return false; + } + } + else if (strncmp(opt,"buyerprice",l) == 0) + { + char * param1 = strtok(NULL, " "); + char * param2 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1) || (!param2)) + { + PSendSysMessage("Syntax is: ahbotoptions buyerprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue or purple) $price"); + return false; + } + if (strncmp(param1,"grey",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_GREY, param2); + } + else if (strncmp(param1,"white",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_WHITE, param2); + } + else if (strncmp(param1,"green",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_GREEN, param2); + } + else if (strncmp(param1,"blue",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_BLUE, param2); + } + else if (strncmp(param1,"purple",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_PURPLE, param2); + } + else if (strncmp(param1,"orange",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_ORANGE, param2); + } + else if (strncmp(param1,"yellow",l) == 0) + { + auctionbot.Commands(11, ahMapID, AHB_YELLOW, param2); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions buyerprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue or purple) $price"); + return false; + } + } + else if (strncmp(opt,"bidinterval",l) == 0) + { + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions bidinterval $ahMapID (2, 6 or 7) $interval(in minutes)"); + return false; + } + auctionbot.Commands(12, ahMapID, NULL, param1); + } + else if (strncmp(opt,"bidsperinterval",l) == 0) + { + char * param1 = strtok(NULL, " "); + if ((!ahMapIdStr) || (!param1)) + { + PSendSysMessage("Syntax is: ahbotoptions bidsperinterval $ahMapID (2, 6 or 7) $bids"); + return false; + } + auctionbot.Commands(13, ahMapID, NULL, param1); + } + else + { + PSendSysMessage("Syntax is: ahbotoptions $option $ahMapID (2, 6 or 7) $parameter"); + PSendSysMessage("Try ahbotoptions help to see a list of options."); + return false; + } + return true; +} + +//reload commands +bool ChatHandler::HandleReloadAllCommand(const char*) +{ + HandleReloadSkillFishingBaseLevelCommand(""); + + HandleReloadAllAchievementCommand(""); + HandleReloadAllAreaCommand(""); + HandleReloadAllEventAICommand(""); + HandleReloadAllLootCommand(""); + HandleReloadAllNpcCommand(""); + HandleReloadAllQuestCommand(""); + HandleReloadAllSpellCommand(""); + HandleReloadAllItemCommand(""); + HandleReloadAllLocalesCommand(""); + + HandleReloadAccessRequirementCommand(""); + HandleReloadMailLevelRewardCommand(""); + HandleReloadCommandCommand(""); + HandleReloadReservedNameCommand(""); + HandleReloadTrinityStringCommand(""); + HandleReloadGameTeleCommand(""); + + HandleReloadAutobroadcastCommand(""); + return true; +} + +bool ChatHandler::HandleReloadAllAchievementCommand(const char*) +{ + HandleReloadAchievementCriteriaDataCommand(""); + HandleReloadAchievementRewardCommand(""); + return true; +} + +bool ChatHandler::HandleReloadAllAreaCommand(const char*) +{ + //HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand + HandleReloadAreaTriggerTeleportCommand(""); + HandleReloadAreaTriggerTavernCommand(""); + HandleReloadGameGraveyardZoneCommand(""); + return true; +} + +bool ChatHandler::HandleReloadAllLootCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables..."); + LoadLootTables(); + SendGlobalGMSysMessage("DB tables `*_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/) +{ + HandleReloadNpcGossipCommand("a"); + HandleReloadNpcTrainerCommand("a"); + HandleReloadNpcVendorCommand("a"); + HandleReloadPointsOfInterestCommand("a"); + HandleReloadSpellClickSpellsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllQuestCommand(const char* /*args*/) +{ + HandleReloadQuestAreaTriggersCommand("a"); + HandleReloadQuestTemplateCommand("a"); + + sLog.outString("Re-Loading Quests Relations..."); + objmgr.LoadQuestRelations(); + SendGlobalGMSysMessage("DB tables `*_questrelation` and `*_involvedrelation` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAllScriptsCommand(const char*) +{ + if (sWorld.IsScriptScheduled()) + { + PSendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + sLog.outString("Re-Loading Scripts..."); + HandleReloadGameObjectScriptsCommand("a"); + HandleReloadEventScriptsCommand("a"); + HandleReloadQuestEndScriptsCommand("a"); + HandleReloadQuestStartScriptsCommand("a"); + HandleReloadSpellScriptsCommand("a"); + SendGlobalGMSysMessage("DB tables `*_scripts` reloaded."); + HandleReloadDbScriptStringCommand("a"); + HandleReloadWpScriptsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllEventAICommand(const char*) +{ + HandleReloadEventAITextsCommand("a"); + HandleReloadEventAISummonsCommand("a"); + HandleReloadEventAIScriptsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllSpellCommand(const char*) +{ + HandleReloadSkillDiscoveryTemplateCommand("a"); + HandleReloadSkillExtraItemTemplateCommand("a"); + HandleReloadSpellRequiredCommand("a"); + HandleReloadSpellAreaCommand("a"); + HandleReloadSpellGroupsCommand("a"); + HandleReloadSpellLearnSpellCommand("a"); + HandleReloadSpellLinkedSpellCommand("a"); + HandleReloadSpellProcEventCommand("a"); + HandleReloadSpellBonusesCommand("a"); + HandleReloadSpellTargetPositionCommand("a"); + HandleReloadSpellThreatsCommand("a"); + HandleReloadSpellGroupStackRulesCommand("a"); + HandleReloadSpellPetAurasCommand("a"); + HandleReloadSpellDisabledCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllItemCommand(const char*) +{ + HandleReloadPageTextsCommand("a"); + HandleReloadItemEnchantementsCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadAllLocalesCommand(const char* /*args*/) +{ + HandleReloadLocalesAchievementRewardCommand("a"); + HandleReloadLocalesCreatureCommand("a"); + HandleReloadLocalesGameobjectCommand("a"); + HandleReloadLocalesItemCommand("a"); + HandleReloadLocalesNpcTextCommand("a"); + HandleReloadLocalesPageTextCommand("a"); + HandleReloadLocalesPointsOfInterestCommand("a"); + HandleReloadLocalesQuestCommand("a"); + return true; +} + +bool ChatHandler::HandleReloadConfigCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading config settings..."); + sWorld.LoadConfigSettings(true); + MapManager::Instance().InitializeVisibilityDistanceInfo(); + SendGlobalGMSysMessage("World config settings reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAccessRequirementCommand(const char*) +{ + sLog.outString("Re-Loading Access Requirement definitions..."); + objmgr.LoadAccessRequirements(); + SendGlobalGMSysMessage("DB table `access_requirement` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAchievementCriteriaDataCommand(const char*) +{ + sLog.outString("Re-Loading Additional Achievement Criteria Data..."); + achievementmgr.LoadAchievementCriteriaData(); + SendGlobalGMSysMessage("DB table `achievement_criteria_data` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAchievementRewardCommand(const char*) +{ + sLog.outString("Re-Loading Achievement Reward Data..."); + achievementmgr.LoadRewards(); + SendGlobalGMSysMessage("DB table `achievement_reward` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAreaTriggerTavernCommand(const char*) +{ + sLog.outString("Re-Loading Tavern Area Triggers..."); + objmgr.LoadTavernAreaTriggers(); + SendGlobalGMSysMessage("DB table `areatrigger_tavern` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAreaTriggerTeleportCommand(const char*) +{ + sLog.outString("Re-Loading AreaTrigger teleport definitions..."); + objmgr.LoadAreaTriggerTeleports(); + SendGlobalGMSysMessage("DB table `areatrigger_teleport` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAutobroadcastCommand(const char*) +{ + sLog.outString("Re-Loading Autobroadcast..."); + sWorld.LoadAutobroadcasts(); + SendGlobalGMSysMessage("DB table `autobroadcast` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCommandCommand(const char*) +{ + load_command_table = true; + SendGlobalGMSysMessage("DB table `command` will be reloaded at next chat command use."); + return true; +} + +bool ChatHandler::HandleReloadCreatureTemplateCommand(const char* args) +{ + if (!*args) + return false; + + uint32 entry = (uint32) atoi((char*)args); + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT difficulty_entry_1,difficulty_entry_2,difficulty_entry_3,KillCredit1,KillCredit2,modelid1,modelid2,modelid3,modelid4,name,subname,IconName,gossip_menu_id,minlevel,maxlevel,exp,faction_A,faction_H,npcflag,speed_walk,speed_run,scale,rank,mindmg,maxdmg,dmgschool,attackpower,dmg_multiplier,baseattacktime,rangeattacktime,unit_class,unit_flags,dynamicflags,family,trainer_type,trainer_spell,trainer_class,trainer_race,minrangedmg,maxrangedmg,rangedattackpower,type,type_flags,lootid,pickpocketloot,skinloot,resistance1,resistance2,resistance3,resistance4,resistance5,resistance6,spell1,spell2,spell3,spell4,spell5,spell6,spell7,spell8,PetSpellDataId,VehicleId,mingold,maxgold,AIName,MovementType,InhabitType,Health_mod,Mana_mod,Armor_mod,RacialLeader,questItem1,questItem2,questItem3,questItem4,questItem5,questItem6,movementId,RegenHealth,equipment_id,mechanic_immune_mask,flags_extra,ScriptName FROM creature_template WHERE entry = %u", entry); + if (!result) + { + PSendSysMessage(LANG_COMMAND_CREATURETEMPLATE_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); + if (!cInfo) + { + PSendSysMessage(LANG_COMMAND_CREATURESTORAGE_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + sLog.outString("Reloading creature template entry %u", entry); + + Field *fields = result->Fetch(); + + const_cast(cInfo)->DifficultyEntry[0] = fields[0].GetUInt32(); + const_cast(cInfo)->DifficultyEntry[1] = fields[1].GetUInt32(); + const_cast(cInfo)->DifficultyEntry[2] = fields[2].GetUInt32(); + const_cast(cInfo)->KillCredit[0] = fields[3].GetUInt32(); + const_cast(cInfo)->KillCredit[1] = fields[4].GetUInt32(); + const_cast(cInfo)->Modelid1 = fields[5].GetUInt32(); + const_cast(cInfo)->Modelid2 = fields[6].GetUInt32(); + const_cast(cInfo)->Modelid3 = fields[7].GetUInt32(); + const_cast(cInfo)->Modelid4 = fields[8].GetUInt32(); + size_t len = 0; + if (const char* temp = fields[9].GetString()) + { + if (cInfo->Name) + delete cInfo->Name; + len = strlen(temp)+1; + const_cast(cInfo)->Name = new char[len]; + strncpy(cInfo->Name, temp, len); + } + if (const char* temp = fields[10].GetString()) + { + if (cInfo->SubName) + delete cInfo->SubName; + len = strlen(temp)+1; + const_cast(cInfo)->SubName = new char[len]; + strncpy(cInfo->SubName, temp, len); + } + if (const char* temp = fields[11].GetString()) + { + if (cInfo->IconName) + delete cInfo->IconName; + len = strlen(temp)+1; + const_cast(cInfo)->IconName = new char[len]; + strncpy(cInfo->IconName, temp, len); + } + const_cast(cInfo)->GossipMenuId = fields[12].GetUInt32(); + const_cast(cInfo)->minlevel = fields[13].GetUInt32(); + const_cast(cInfo)->maxlevel = fields[14].GetUInt32(); + const_cast(cInfo)->expansion = fields[15].GetUInt32(); + const_cast(cInfo)->faction_A = fields[16].GetUInt32(); + const_cast(cInfo)->faction_H = fields[17].GetUInt32(); + const_cast(cInfo)->npcflag = fields[18].GetUInt32(); + const_cast(cInfo)->speed_walk = fields[19].GetFloat(); + const_cast(cInfo)->speed_run = fields[20].GetFloat(); + const_cast(cInfo)->scale = fields[21].GetFloat(); + const_cast(cInfo)->rank = fields[22].GetUInt32(); + const_cast(cInfo)->mindmg = fields[23].GetFloat(); + const_cast(cInfo)->maxdmg = fields[24].GetFloat(); + const_cast(cInfo)->dmgschool = fields[25].GetUInt32(); + const_cast(cInfo)->attackpower = fields[26].GetUInt32(); + const_cast(cInfo)->dmg_multiplier = fields[27].GetFloat(); + const_cast(cInfo)->baseattacktime = fields[28].GetUInt32(); + const_cast(cInfo)->rangeattacktime = fields[29].GetUInt32(); + const_cast(cInfo)->unit_class = fields[30].GetUInt32(); + const_cast(cInfo)->unit_flags = fields[31].GetUInt32(); + const_cast(cInfo)->dynamicflags = fields[32].GetUInt32(); + const_cast(cInfo)->family = fields[33].GetUInt32(); + const_cast(cInfo)->trainer_type = fields[34].GetUInt32(); + const_cast(cInfo)->trainer_spell = fields[35].GetUInt32(); + const_cast(cInfo)->trainer_class = fields[36].GetUInt32(); + const_cast(cInfo)->trainer_race = fields[37].GetUInt32(); + const_cast(cInfo)->minrangedmg = fields[38].GetFloat(); + const_cast(cInfo)->maxrangedmg = fields[39].GetFloat(); + const_cast(cInfo)->rangedattackpower = fields[40].GetUInt32(); + const_cast(cInfo)->type = fields[41].GetUInt32(); + const_cast(cInfo)->type_flags = fields[42].GetUInt32(); + const_cast(cInfo)->lootid = fields[43].GetUInt32(); + const_cast(cInfo)->pickpocketLootId = fields[44].GetUInt32(); + const_cast(cInfo)->SkinLootId = fields[45].GetUInt32(); + const_cast(cInfo)->resistance1 = fields[46].GetUInt32(); + const_cast(cInfo)->resistance2 = fields[47].GetUInt32(); + const_cast(cInfo)->resistance3 = fields[48].GetUInt32(); + const_cast(cInfo)->resistance4 = fields[49].GetUInt32(); + const_cast(cInfo)->resistance5 = fields[50].GetUInt32(); + const_cast(cInfo)->resistance6 = fields[51].GetUInt32(); + const_cast(cInfo)->spells[0] = fields[52].GetUInt32(); + const_cast(cInfo)->spells[1] = fields[53].GetUInt32(); + const_cast(cInfo)->spells[2] = fields[54].GetUInt32(); + const_cast(cInfo)->spells[3] = fields[55].GetUInt32(); + const_cast(cInfo)->spells[4] = fields[56].GetUInt32(); + const_cast(cInfo)->spells[5] = fields[57].GetUInt32(); + const_cast(cInfo)->spells[6] = fields[58].GetUInt32(); + const_cast(cInfo)->spells[7] = fields[59].GetUInt32(); + const_cast(cInfo)->PetSpellDataId = fields[60].GetUInt32(); + const_cast(cInfo)->VehicleId = fields[61].GetUInt32(); + const_cast(cInfo)->mingold = fields[62].GetUInt32(); + const_cast(cInfo)->maxgold = fields[63].GetUInt32(); + if (const char* temp = fields[64].GetString()) + { + if (cInfo->AIName) + delete cInfo->AIName; + len = strlen(temp)+1; + const_cast(cInfo)->AIName = new char[len]; + strncpy(const_cast(cInfo->AIName), temp, len); + } + const_cast(cInfo)->MovementType = fields[65].GetUInt32(); + const_cast(cInfo)->InhabitType = fields[66].GetUInt32(); + const_cast(cInfo)->ModHealth = fields[67].GetFloat(); + const_cast(cInfo)->ModMana = fields[68].GetFloat(); + const_cast(cInfo)->ModArmor = fields[69].GetFloat(); + const_cast(cInfo)->RacialLeader = fields[70].GetBool(); + const_cast(cInfo)->questItems[0] = fields[71].GetUInt32(); + const_cast(cInfo)->questItems[1] = fields[72].GetUInt32(); + const_cast(cInfo)->questItems[2] = fields[73].GetUInt32(); + const_cast(cInfo)->questItems[3] = fields[74].GetUInt32(); + const_cast(cInfo)->questItems[4] = fields[75].GetUInt32(); + const_cast(cInfo)->questItems[5] = fields[76].GetUInt32(); + const_cast(cInfo)->movementId = fields[77].GetUInt32(); + const_cast(cInfo)->RegenHealth = fields[78].GetBool(); + const_cast(cInfo)->equipmentId = fields[79].GetUInt32(); + const_cast(cInfo)->MechanicImmuneMask = fields[80].GetUInt32(); + const_cast(cInfo)->flags_extra = fields[81].GetUInt32(); + const_cast(cInfo)->ScriptID = objmgr.GetScriptId(fields[82].GetString()); + + objmgr.CheckCreatureTemplate(cInfo); + + SendGlobalGMSysMessage("Creature template reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCreatureQuestRelationsCommand(const char*) +{ + sLog.outString("Loading Quests Relations... (`creature_questrelation`)"); + objmgr.LoadCreatureQuestRelations(); + SendGlobalGMSysMessage("DB table `creature_questrelation` (creature quest givers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCreatureLinkedRespawnCommand(const char * /*args*/) +{ + sLog.outString("Loading Linked Respawns... (`creature_linked_respawn`)"); + objmgr.LoadCreatureLinkedRespawn(); + SendGlobalGMSysMessage("DB table `creature_linked_respawn` (creature linked respawns) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadCreatureQuestInvRelationsCommand(const char*) +{ + sLog.outString("Loading Quests Relations... (`creature_involvedrelation`)"); + objmgr.LoadCreatureInvolvedRelations(); + SendGlobalGMSysMessage("DB table `creature_involvedrelation` (creature quest takers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGossipMenuCommand(const char*) +{ + sLog.outString("Re-Loading `gossip_menu` Table!"); + objmgr.LoadGossipMenu(); + SendGlobalGMSysMessage("DB table `gossip_menu` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadGossipMenuOptionCommand(const char*) +{ + sLog.outString("Re-Loading `gossip_menu_option` Table!"); + objmgr.LoadGossipMenuItems(); + SendGlobalGMSysMessage("DB table `gossip_menu_option` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadGOQuestRelationsCommand(const char*) +{ + sLog.outString("Loading Quests Relations... (`gameobject_questrelation`)"); + objmgr.LoadGameobjectQuestRelations(); + SendGlobalGMSysMessage("DB table `gameobject_questrelation` (gameobject quest givers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGOQuestInvRelationsCommand(const char*) +{ + sLog.outString("Loading Quests Relations... (`gameobject_involvedrelation`)"); + objmgr.LoadGameobjectInvolvedRelations(); + SendGlobalGMSysMessage("DB table `gameobject_involvedrelation` (gameobject quest takers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadQuestAreaTriggersCommand(const char*) +{ + sLog.outString("Re-Loading Quest Area Triggers..."); + objmgr.LoadQuestAreaTriggers(); + SendGlobalGMSysMessage("DB table `areatrigger_involvedrelation` (quest area triggers) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadQuestTemplateCommand(const char*) +{ + sLog.outString("Re-Loading Quest Templates..."); + objmgr.LoadQuests(); + SendGlobalGMSysMessage("DB table `quest_template` (quest definitions) reloaded."); + + /// dependent also from `gameobject` but this table not reloaded anyway + sLog.outString("Re-Loading GameObjects for quests..."); + objmgr.LoadGameObjectForQuests(); + SendGlobalGMSysMessage("Data GameObjects for quests reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesCreatureCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`creature_loot_template`)"); + LoadLootTemplates_Creature(); + LootTemplates_Creature.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `creature_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesDisenchantCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`disenchant_loot_template`)"); + LoadLootTemplates_Disenchant(); + LootTemplates_Disenchant.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `disenchant_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesFishingCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`fishing_loot_template`)"); + LoadLootTemplates_Fishing(); + LootTemplates_Fishing.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `fishing_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesGameobjectCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`gameobject_loot_template`)"); + LoadLootTemplates_Gameobject(); + LootTemplates_Gameobject.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `gameobject_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`item_loot_template`)"); + LoadLootTemplates_Item(); + LootTemplates_Item.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `item_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesMillingCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`milling_loot_template`)"); + LoadLootTemplates_Milling(); + LootTemplates_Milling.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `milling_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`pickpocketing_loot_template`)"); + LoadLootTemplates_Pickpocketing(); + LootTemplates_Pickpocketing.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `pickpocketing_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesProspectingCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`prospecting_loot_template`)"); + LoadLootTemplates_Prospecting(); + LootTemplates_Prospecting.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `prospecting_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesMailCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`mail_loot_template`)"); + LoadLootTemplates_Mail(); + LootTemplates_Mail.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `mail_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesReferenceCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`reference_loot_template`)"); + LoadLootTemplates_Reference(); + SendGlobalGMSysMessage("DB table `reference_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`skinning_loot_template`)"); + LoadLootTemplates_Skinning(); + LootTemplates_Skinning.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `skinning_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadLootTemplatesSpellCommand(const char*) +{ + sLog.outString("Re-Loading Loot Tables... (`spell_loot_template`)"); + LoadLootTemplates_Spell(); + LootTemplates_Spell.CheckLootRefs(); + SendGlobalGMSysMessage("DB table `spell_loot_template` reloaded."); + sConditionMgr.LoadConditions(true); + return true; +} + +bool ChatHandler::HandleReloadTrinityStringCommand(const char*) +{ + sLog.outString("Re-Loading trinity_string Table!"); + objmgr.LoadTrinityStrings(); + SendGlobalGMSysMessage("DB table `trinity_string` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadNpcGossipCommand(const char*) +{ + sLog.outString("Re-Loading `npc_gossip` Table!"); + objmgr.LoadNpcTextId(); + SendGlobalGMSysMessage("DB table `npc_gossip` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadNpcTrainerCommand(const char*) +{ + sLog.outString("Re-Loading `npc_trainer` Table!"); + objmgr.LoadTrainerSpell(); + SendGlobalGMSysMessage("DB table `npc_trainer` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadNpcVendorCommand(const char*) +{ + sLog.outString("Re-Loading `npc_vendor` Table!"); + objmgr.LoadVendors(); + SendGlobalGMSysMessage("DB table `npc_vendor` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadPointsOfInterestCommand(const char*) +{ + sLog.outString("Re-Loading `points_of_interest` Table!"); + objmgr.LoadPointsOfInterest(); + SendGlobalGMSysMessage("DB table `points_of_interest` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellClickSpellsCommand(const char*) +{ + sLog.outString("Re-Loading `npc_spellclick_spells` Table!"); + objmgr.LoadNPCSpellClickSpells(); + SendGlobalGMSysMessage("DB table `npc_spellclick_spells` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadReservedNameCommand(const char*) +{ + sLog.outString("Loading ReservedNames... (`reserved_name`)"); + objmgr.LoadReservedPlayersNames(); + SendGlobalGMSysMessage("DB table `reserved_name` (player reserved names) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillDiscoveryTemplateCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Skill Discovery Table..."); + LoadSkillDiscoveryTable(); + SendGlobalGMSysMessage("DB table `skill_discovery_template` (recipes discovered at crafting) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillExtraItemTemplateCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Skill Extra Item Table..."); + LoadSkillExtraItemTable(); + SendGlobalGMSysMessage("DB table `skill_extra_item_template` (extra item creation when crafting) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSkillFishingBaseLevelCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Skill Fishing base level requirements..."); + objmgr.LoadFishingBaseSkillLevel(); + SendGlobalGMSysMessage("DB table `skill_fishing_base_level` (fishing base level for zone/subzone) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellAreaCommand(const char*) +{ + sLog.outString("Re-Loading SpellArea Data..."); + spellmgr.LoadSpellAreas(); + SendGlobalGMSysMessage("DB table `spell_area` (spell dependences from area/quest/auras state) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellRequiredCommand(const char*) +{ + sLog.outString("Re-Loading Spell Required Data... "); + spellmgr.LoadSpellRequired(); + SendGlobalGMSysMessage("DB table `spell_required` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellGroupsCommand(const char*) +{ + sLog.outString("Re-Loading Spell Groups..."); + spellmgr.LoadSpellGroups(); + SendGlobalGMSysMessage("DB table `spell_group` (spell groups) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellLearnSpellCommand(const char*) +{ + sLog.outString("Re-Loading Spell Learn Spells..."); + spellmgr.LoadSpellLearnSpells(); + SendGlobalGMSysMessage("DB table `spell_learn_spell` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellLinkedSpellCommand(const char*) +{ + sLog.outString("Re-Loading Spell Linked Spells..."); + spellmgr.LoadSpellLinked(); + SendGlobalGMSysMessage("DB table `spell_linked_spell` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellProcEventCommand(const char*) +{ + sLog.outString("Re-Loading Spell Proc Event conditions..."); + spellmgr.LoadSpellProcEvents(); + SendGlobalGMSysMessage("DB table `spell_proc_event` (spell proc trigger requirements) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellBonusesCommand(const char*) +{ + sLog.outString("Re-Loading Spell Bonus Data..."); + spellmgr.LoadSpellBonusess(); + SendGlobalGMSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellTargetPositionCommand(const char*) +{ + sLog.outString("Re-Loading Spell target coordinates..."); + spellmgr.LoadSpellTargetPositions(); + SendGlobalGMSysMessage("DB table `spell_target_position` (destination coordinates for spell targets) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellThreatsCommand(const char*) +{ + sLog.outString("Re-Loading Aggro Spells Definitions..."); + spellmgr.LoadSpellThreats(); + SendGlobalGMSysMessage("DB table `spell_threat` (spell aggro definitions) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellGroupStackRulesCommand(const char*) +{ + sLog.outString("Re-Loading Spell Group Stack Rules..."); + spellmgr.LoadSpellGroupStackRules(); + SendGlobalGMSysMessage("DB table `spell_group_stack_rules` (spell stacking definitions) reloaded."); + return true; +} + +bool ChatHandler::HandleReloadSpellPetAurasCommand(const char*) +{ + sLog.outString("Re-Loading Spell pet auras..."); + spellmgr.LoadSpellPetAuras(); + SendGlobalGMSysMessage("DB table `spell_pet_auras` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadPageTextsCommand(const char*) +{ + sLog.outString("Re-Loading Page Texts..."); + objmgr.LoadPageTexts(); + SendGlobalGMSysMessage("DB table `page_texts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadItemEnchantementsCommand(const char*) +{ + sLog.outString("Re-Loading Item Random Enchantments Table..."); + LoadRandomEnchantmentsTable(); + SendGlobalGMSysMessage("DB table `item_enchantment_template` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGameObjectScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `gameobject_scripts`..."); + + objmgr.LoadGameObjectScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `gameobject_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadEventScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `event_scripts`..."); + + objmgr.LoadEventScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `event_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadWpScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `waypoint_scripts`..."); + + objmgr.LoadWaypointScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `waypoint_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadEventAITextsCommand(const char* /*args*/) +{ + + sLog.outString("Re-Loading Texts from `creature_ai_texts`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Texts(); + SendGlobalGMSysMessage("DB table `creature_ai_texts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadEventAISummonsCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Summons from `creature_ai_summons`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Summons(); + SendGlobalGMSysMessage("DB table `creature_ai_summons` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadEventAIScriptsCommand(const char* /*args*/) +{ + sLog.outString("Re-Loading Scripts from `creature_ai_scripts`..."); + CreatureEAI_Mgr.LoadCreatureEventAI_Scripts(); + SendGlobalGMSysMessage("DB table `creature_ai_scripts` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadQuestEndScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `quest_end_scripts`..."); + + objmgr.LoadQuestEndScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `quest_end_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadQuestStartScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `quest_start_scripts`..."); + + objmgr.LoadQuestStartScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `quest_start_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadSpellScriptsCommand(const char* arg) +{ + if (sWorld.IsScriptScheduled()) + { + SendSysMessage("DB scripts used currently, please attempt reload later."); + SetSentErrorMessage(true); + return false; + } + + if (*arg != 'a') + sLog.outString("Re-Loading Scripts from `spell_scripts`..."); + + objmgr.LoadSpellScripts(); + + if (*arg != 'a') + SendGlobalGMSysMessage("DB table `spell_scripts` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadDbScriptStringCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Script strings from `db_script_string`..."); + objmgr.LoadDbScriptStrings(); + SendGlobalGMSysMessage("DB table `db_script_string` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadGameGraveyardZoneCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Graveyard-zone links..."); + + objmgr.LoadGraveyardZones(); + + SendGlobalGMSysMessage("DB table `game_graveyard_zone` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadGameTeleCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Game Tele coordinates..."); + + objmgr.LoadGameTele(); + + SendGlobalGMSysMessage("DB table `game_tele` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadSpellDisabledCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading spell disabled table..."); + + objmgr.LoadSpellDisabledEntrys(); + + SendGlobalGMSysMessage("DB table `spell_disabled` reloaded."); + + return true; +} + +bool ChatHandler::HandleReloadLocalesAchievementRewardCommand(const char*) +{ + sLog.outString("Re-Loading Locales Achievement Reward Data..."); + achievementmgr.LoadRewardLocales(); + SendGlobalGMSysMessage("DB table `locales_achievement_reward` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesCreatureCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Creature ..."); + objmgr.LoadCreatureLocales(); + SendGlobalGMSysMessage("DB table `locales_creature` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesGameobjectCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Gameobject ... "); + objmgr.LoadGameObjectLocales(); + SendGlobalGMSysMessage("DB table `locales_gameobject` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesItemCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Item ... "); + objmgr.LoadItemLocales(); + SendGlobalGMSysMessage("DB table `locales_item` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesNpcTextCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales NPC Text ... "); + objmgr.LoadNpcTextLocales(); + SendGlobalGMSysMessage("DB table `locales_npc_text` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesPageTextCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Page Text ... "); + objmgr.LoadPageTextLocales(); + SendGlobalGMSysMessage("DB table `locales_page_text` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesPointsOfInterestCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Points Of Interest ... "); + objmgr.LoadPointOfInterestLocales(); + SendGlobalGMSysMessage("DB table `locales_points_of_interest` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadLocalesQuestCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Locales Quest ... "); + objmgr.LoadQuestLocales(); + SendGlobalGMSysMessage("DB table `locales_quest` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadMailLevelRewardCommand(const char* /*arg*/) +{ + sLog.outString("Re-Loading Player level dependent mail rewards..."); + objmgr.LoadMailLevelRewards(); + SendGlobalGMSysMessage("DB table `mail_level_reward` reloaded."); + return true; +} + +bool ChatHandler::HandleReloadAuctionsCommand(const char * /*args*/) +{ + ///- Reload dynamic data tables from the database + sLog.outString("Re-Loading Auctions..."); + auctionmgr.LoadAuctionItems(); + auctionmgr.LoadAuctions(); + SendGlobalGMSysMessage("Auctions reloaded."); + return true; +} + +bool ChatHandler::HandleReloadConditions(const char* args) +{ + sLog.outString("Re-Loading Conditions..."); + sConditionMgr.LoadConditions(true); + SendGlobalGMSysMessage("Conditions reloaded."); + return true; +} + +bool ChatHandler::HandleAccountSetGmLevelCommand(const char *args) +{ + if (!*args) + return false; + + std::string targetAccountName; + uint32 targetAccountId = 0; + uint32 targetSecurity = 0; + uint32 gm = 0; + char* arg1 = strtok((char*)args, " "); + char* arg2 = strtok(NULL, " "); + char* arg3 = strtok(NULL, " "); + bool isAccountNameGiven = true; + + if (arg1 && !arg3) + { + if (!getSelectedPlayer()) + return false; + isAccountNameGiven = false; + } + + // Check for second parameter + if (!isAccountNameGiven && !arg2) + return false; + + // Check for account + if (isAccountNameGiven) + { + targetAccountName = arg1; + if (!AccountMgr::normalizeString(targetAccountName)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,targetAccountName.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + // Check for invalid specified GM level. + gm = (isAccountNameGiven) ? atoi(arg2) : atoi(arg1); + if (gm < SEC_PLAYER) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + // m_session == NULL only for console + targetAccountId = (isAccountNameGiven) ? accmgr.GetId(targetAccountName) : getSelectedPlayer()->GetSession()->GetAccountId(); + int32 gmRealmID = (isAccountNameGiven) ? atoi(arg3) : atoi(arg2); + uint32 plSecurity = m_session ? accmgr.GetSecurity(m_session->GetAccountId(), gmRealmID) : SEC_CONSOLE; + + // can set security level only for target with less security and to less security that we have + // This is also reject self apply in fact + targetSecurity = accmgr.GetSecurity(targetAccountId, gmRealmID); + if (targetSecurity >= plSecurity || gm >= plSecurity) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return false; + } + + // Check and abort if the target gm has a higher rank on one of the realms and the new realm is -1 + if (gmRealmID == -1) + { + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT * FROM account_access WHERE id = '%u' AND gmlevel > '%d'", targetAccountId, gm); + if (result) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return false; + } + } + + // Check if provided realmID has a negative value other than -1 + if (gmRealmID < -1) + { + SendSysMessage(LANG_INVALID_REALMID); + SetSentErrorMessage(true); + return false; + } + + // If gmRealmID is -1, delete all values for the account id, else, insert values for the specific realmID + if (gmRealmID == -1) + LoginDatabase.PExecute("DELETE FROM account_access WHERE id = '%u'", targetAccountId); + else + LoginDatabase.PExecute("DELETE FROM account_access WHERE id = '%u' AND (RealmID = '%d' OR RealmID = '-1')", targetAccountId, realmID); + + if (gm != 0) + LoginDatabase.PExecute("INSERT INTO account_access VALUES ('%u','%d','%d')", targetAccountId, gm, realmID); + PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); + return true; +} + +/// Set password for account +bool ChatHandler::HandleAccountSetPasswordCommand(const char *args) +{ + if (!*args) + return false; + + ///- Get the command line arguments + char *szAccount = strtok ((char*)args," "); + char *szPassword1 = strtok (NULL," "); + char *szPassword2 = strtok (NULL," "); + + if (!szAccount||!szPassword1 || !szPassword2) + return false; + + std::string account_name = szAccount; + if (!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + uint32 targetAccountId = accmgr.GetId(account_name); + if (!targetAccountId) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + /// can set password only for target with less security + /// This is also reject self apply in fact + if (HasLowerSecurityAccount (NULL,targetAccountId,true)) + return false; + + if (strcmp(szPassword1,szPassword2)) + { + SendSysMessage (LANG_NEW_PASSWORDS_NOT_MATCH); + SetSentErrorMessage (true); + return false; + } + + AccountOpResult result = accmgr.ChangePassword(targetAccountId, szPassword1); + + switch (result) + { + case AOR_OK: + SendSysMessage(LANG_COMMAND_PASSWORD); + break; + case AOR_NAME_NOT_EXIST: + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + case AOR_PASS_TOO_LONG: + SendSysMessage(LANG_PASSWORD_TOO_LONG); + SetSentErrorMessage(true); + return false; + default: + SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleMaxSkillCommand(const char* /*args*/) +{ + Player* SelectedPlayer = getSelectedPlayer(); + if (!SelectedPlayer) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // each skills that have max skill value dependent from level seted to current level max skill value + SelectedPlayer->UpdateSkillsToMaxSkillsForLevel(); + return true; +} + +bool ChatHandler::HandleSetSkillCommand(const char *args) +{ + // number or [name] Shift-click form |color|Hskill:skill_id|h[name]|h|r + char* skill_p = extractKeyFromLink((char*)args,"Hskill"); + if (!skill_p) + return false; + + char *level_p = strtok (NULL, " "); + + if (!level_p) + return false; + + char *max_p = strtok (NULL, " "); + + int32 skill = atoi(skill_p); + if (skill <= 0) + { + PSendSysMessage(LANG_INVALID_SKILL_ID, skill); + SetSentErrorMessage(true); + return false; + } + + int32 level = atol (level_p); + + Player * target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + SkillLineEntry const* sl = sSkillLineStore.LookupEntry(skill); + if (!sl) + { + PSendSysMessage(LANG_INVALID_SKILL_ID, skill); + SetSentErrorMessage(true); + return false; + } + + std::string tNameLink = GetNameLink(target); + + if (!target->GetSkillValue(skill)) + { + PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, sl->name[GetSessionDbcLocale()]); + SetSentErrorMessage(true); + return false; + } + + int32 max = max_p ? atol (max_p) : target->GetPureMaxSkillValue(skill); + + if (level <= 0 || level > max || max <= 0) + return false; + + target->SetSkill(skill, target->GetSkillStep(skill), level, max); + PSendSysMessage(LANG_SET_SKILL, skill, sl->name[GetSessionDbcLocale()], tNameLink.c_str(), level, max); + + return true; +} + +bool ChatHandler::HandleUnLearnCommand(const char *args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + uint32 spell_id = extractSpellIdFromLink((char*)args); + if (!spell_id) + return false; + + char const* allStr = strtok(NULL," "); + bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; + + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (allRanks) + spell_id = spellmgr.GetFirstSpellInChain (spell_id); + + if (target->HasSpell(spell_id)) + target->removeSpell(spell_id,false,!allRanks); + else + SendSysMessage(LANG_FORGET_SPELL); + + if (GetTalentSpellCost(spell_id)) + target->SendTalentsInfoData(false); + + return true; +} + +bool ChatHandler::HandleCooldownCommand(const char *args) +{ + Player* target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + std::string tNameLink = GetNameLink(target); + + if (!*args) + { + target->RemoveAllSpellCooldown(); + PSendSysMessage(LANG_REMOVEALL_COOLDOWN, tNameLink.c_str()); + } + else + { + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell_id = extractSpellIdFromLink((char*)args); + if (!spell_id) + return false; + + if (!sSpellStore.LookupEntry(spell_id)) + { + PSendSysMessage(LANG_UNKNOWN_SPELL, target == m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : tNameLink.c_str()); + SetSentErrorMessage(true); + return false; + } + + target->RemoveSpellCooldown(spell_id,true); + PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target == m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : tNameLink.c_str()); + } + return true; +} + +bool ChatHandler::HandleLearnAllCommand(const char* /*args*/) +{ + static const char *allSpellList[] = + { + "3365", + "6233", + "6247", + "6246", + "6477", + "6478", + "22810", + "8386", + "21651", + "21652", + "522", + "7266", + "8597", + "2479", + "22027", + "6603", + "5019", + "133", + "168", + "227", + "5009", + "9078", + "668", + "203", + "20599", + "20600", + "81", + "20597", + "20598", + "20864", + "1459", + "5504", + "587", + "5143", + "118", + "5505", + "597", + "604", + "1449", + "1460", + "2855", + "1008", + "475", + "5506", + "1463", + "12824", + "8437", + "990", + "5145", + "8450", + "1461", + "759", + "8494", + "8455", + "8438", + "6127", + "8416", + "6129", + "8451", + "8495", + "8439", + "3552", + "8417", + "10138", + "12825", + "10169", + "10156", + "10144", + "10191", + "10201", + "10211", + "10053", + "10173", + "10139", + "10145", + "10192", + "10170", + "10202", + "10054", + "10174", + "10193", + "12826", + "2136", + "143", + "145", + "2137", + "2120", + "3140", + "543", + "2138", + "2948", + "8400", + "2121", + "8444", + "8412", + "8457", + "8401", + "8422", + "8445", + "8402", + "8413", + "8458", + "8423", + "8446", + "10148", + "10197", + "10205", + "10149", + "10215", + "10223", + "10206", + "10199", + "10150", + "10216", + "10207", + "10225", + "10151", + "116", + "205", + "7300", + "122", + "837", + "10", + "7301", + "7322", + "6143", + "120", + "865", + "8406", + "6141", + "7302", + "8461", + "8407", + "8492", + "8427", + "8408", + "6131", + "7320", + "10159", + "8462", + "10185", + "10179", + "10160", + "10180", + "10219", + "10186", + "10177", + "10230", + "10181", + "10161", + "10187", + "10220", + "2018", + "2663", + "12260", + "2660", + "3115", + "3326", + "2665", + "3116", + "2738", + "3293", + "2661", + "3319", + "2662", + "9983", + "8880", + "2737", + "2739", + "7408", + "3320", + "2666", + "3323", + "3324", + "3294", + "22723", + "23219", + "23220", + "23221", + "23228", + "23338", + "10788", + "10790", + "5611", + "5016", + "5609", + "2060", + "10963", + "10964", + "10965", + "22593", + "22594", + "596", + "996", + "499", + "768", + "17002", + "1448", + "1082", + "16979", + "1079", + "5215", + "20484", + "5221", + "15590", + "17007", + "6795", + "6807", + "5487", + "1446", + "1066", + "5421", + "3139", + "779", + "6811", + "6808", + "1445", + "5216", + "1737", + "5222", + "5217", + "1432", + "6812", + "9492", + "5210", + "3030", + "1441", + "783", + "6801", + "20739", + "8944", + "9491", + "22569", + "5226", + "6786", + "1433", + "8973", + "1828", + "9495", + "9006", + "6794", + "8993", + "5203", + "16914", + "6784", + "9635", + "22830", + "20722", + "9748", + "6790", + "9753", + "9493", + "9752", + "9831", + "9825", + "9822", + "5204", + "5401", + "22831", + "6793", + "9845", + "17401", + "9882", + "9868", + "20749", + "9893", + "9899", + "9895", + "9832", + "9902", + "9909", + "22832", + "9828", + "9851", + "9883", + "9869", + "17406", + "17402", + "9914", + "20750", + "9897", + "9848", + "3127", + "107", + "204", + "9116", + "2457", + "78", + "18848", + "331", + "403", + "2098", + "1752", + "11278", + "11288", + "11284", + "6461", + "2344", + "2345", + "6463", + "2346", + "2352", + "775", + "1434", + "1612", + "71", + "2468", + "2458", + "2467", + "7164", + "7178", + "7367", + "7376", + "7381", + "21156", + "5209", + "3029", + "5201", + "9849", + "9850", + "20719", + "22568", + "22827", + "22828", + "22829", + "6809", + "8972", + "9005", + "9823", + "9827", + "6783", + "9913", + "6785", + "6787", + "9866", + "9867", + "9894", + "9896", + "6800", + "8992", + "9829", + "9830", + "780", + "769", + "6749", + "6750", + "9755", + "9754", + "9908", + "20745", + "20742", + "20747", + "20748", + "9746", + "9745", + "9880", + "9881", + "5391", + "842", + "3025", + "3031", + "3287", + "3329", + "1945", + "3559", + "4933", + "4934", + "4935", + "4936", + "5142", + "5390", + "5392", + "5404", + "5420", + "6405", + "7293", + "7965", + "8041", + "8153", + "9033", + "9034", + //"9036", problems with ghost state + "16421", + "21653", + "22660", + "5225", + "9846", + "2426", + "5916", + "6634", + //"6718", phasing stealth, annoying for learn all case. + "6719", + "8822", + "9591", + "9590", + "10032", + "17746", + "17747", + "8203", + "11392", + "12495", + "16380", + "23452", + "4079", + "4996", + "4997", + "4998", + "4999", + "5000", + "6348", + "6349", + "6481", + "6482", + "6483", + "6484", + "11362", + "11410", + "11409", + "12510", + "12509", + "12885", + "13142", + "21463", + "23460", + "11421", + "11416", + "11418", + "1851", + "10059", + "11423", + "11417", + "11422", + "11419", + "11424", + "11420", + "27", + "31", + "33", + "34", + "35", + "15125", + "21127", + "22950", + "1180", + "201", + "12593", + "16770", + "6057", + "12051", + "18468", + "12606", + "12605", + "18466", + "12502", + "12043", + "15060", + "12042", + "12341", + "12848", + "12344", + "12353", + "18460", + "11366", + "12350", + "12352", + "13043", + "11368", + "11113", + "12400", + "11129", + "16766", + "12573", + "12580", + "12472", + "12953", + "12488", + "11189", + "12985", + "12519", + "16758", + "11958", + "12490", + "11426", + "3565", + "3562", + "18960", + "3567", + "3561", + "3566", + "3563", + "1953", + "2139", + "12505", + "13018", + "12522", + "12523", + "5146", + "5144", + "5148", + "8419", + "8418", + "10213", + "10212", + "10157", + "12524", + "13019", + "12525", + "13020", + "12526", + "13021", + "18809", + "13031", + "13032", + "13033", + "4036", + "3920", + "3919", + "3918", + "7430", + "3922", + "3923", + "7411", + "7418", + "7421", + "13262", + "7412", + "7415", + "7413", + "7416", + "13920", + "13921", + "7745", + "7779", + "7428", + "7457", + "7857", + "7748", + "7426", + "13421", + "7454", + "13378", + "7788", + "14807", + "14293", + "7795", + "6296", + "20608", + "755", + "444", + "427", + "428", + "442", + "447", + "3578", + "3581", + "19027", + "3580", + "665", + "3579", + "3577", + "6755", + "3576", + "2575", + "2577", + "2578", + "2579", + "2580", + "2656", + "2657", + "2576", + "3564", + "10248", + "8388", + "2659", + "14891", + "3308", + "3307", + "10097", + "2658", + "3569", + "16153", + "3304", + "10098", + "4037", + "3929", + "3931", + "3926", + "3924", + "3930", + "3977", + "3925", + "136", + "228", + "5487", + "43", + "202", + "0" + }; + + int loop = 0; + while (strcmp(allSpellList[loop], "0")) + { + uint32 spell = atol((char*)allSpellList[loop++]); + + if (m_session->GetPlayer()->HasSpell(spell)) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + continue; + } + + m_session->GetPlayer()->learnSpell(spell, false); + } + + SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS); + + return true; +} + +bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/) +{ + static const char *gmSpellList[] = + { + "24347", // Become A Fish, No Breath Bar + "35132", // Visual Boom + "38488", // Attack 4000-8000 AOE + "38795", // Attack 2000 AOE + Slow Down 90% + "15712", // Attack 200 + "1852", // GM Spell Silence + "31899", // Kill + "31924", // Kill + "29878", // Kill My Self + "26644", // More Kill + + "28550", //Invisible 24 + "23452", //Invisible + Target + "0" + }; + + uint16 gmSpellIter = 0; + while (strcmp(gmSpellList[gmSpellIter], "0")) + { + uint32 spell = atol((char*)gmSpellList[gmSpellIter++]); + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + continue; + } + + m_session->GetPlayer()->learnSpell(spell, false); + } + + SendSysMessage(LANG_LEARNING_GM_SKILLS); + return true; +} + +bool ChatHandler::HandleLearnAllMyClassCommand(const char* /*args*/) +{ + HandleLearnAllMySpellsCommand(""); + HandleLearnAllMyTalentsCommand(""); + return true; +} + +bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) +{ + ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(m_session->GetPlayer()->getClass()); + if (!clsEntry) + return true; + uint32 family = clsEntry->spellfamily; + + for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(i); + if (!spellInfo) + continue; + + // skip server-side/triggered spells + if (spellInfo->spellLevel == 0) + continue; + + // skip wrong class/race skills + if (!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id)) + continue; + + // skip other spell families + if (spellInfo->SpellFamilyName != family) + continue; + + // skip spells with first rank learned as talent (and all talents then also) + uint32 first_rank = spellmgr.GetFirstSpellInChain(spellInfo->Id); + if (GetTalentSpellCost(first_rank) > 0) + continue; + + // skip broken spells + if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + m_session->GetPlayer()->learnSpell(i, false); + } + + SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); + return true; +} + +bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + uint32 classMask = player->getClassMask(); + + for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + if (!talentInfo) + continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); + if (!talentTabInfo) + continue; + + if ((classMask & talentTabInfo->ClassMask) == 0) + continue; + + // search highest talent rank + uint32 spellId = 0; + for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) + { + if (talentInfo->RankID[rank] != 0) + { + spellId = talentInfo->RankID[rank]; + break; + } + } + + if (!spellId) // ??? none spells in talent + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) + player->learnSpellHighRank(spellId); + player->AddTalent(spellId, player->GetActiveSpec(), true); + } + + player->SetFreeTalentPoints(0); + + SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); + return true; +} + +bool ChatHandler::HandleLearnAllMyPetTalentsCommand(const char* /*args*/) +{ + Player* player = m_session->GetPlayer(); + + Pet* pet = player->GetPet(); + if (!pet) + { + SendSysMessage(LANG_NO_PET_FOUND); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const *ci = pet->GetCreatureInfo(); + if (!ci) + { + SendSysMessage(LANG_WRONG_PET_TYPE); + SetSentErrorMessage(true); + return false; + } + + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); + if (!pet_family) + { + SendSysMessage(LANG_WRONG_PET_TYPE); + SetSentErrorMessage(true); + return false; + } + + if (pet_family->petTalentType < 0) // not hunter pet + { + SendSysMessage(LANG_WRONG_PET_TYPE); + SetSentErrorMessage(true); + return false; + } + + for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + if (!talentInfo) + continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); + if (!talentTabInfo) + continue; + + // prevent learn talent for different family (cheating) + if (((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask) == 0) + continue; + + // search highest talent rank + uint32 spellid = 0; + + for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) + { + if (talentInfo->RankID[rank] != 0) + { + spellid = talentInfo->RankID[rank]; + break; + } + } + + if (!spellid) // ??? none spells in talent + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) + continue; + + // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) + pet->learnSpellHighRank(spellid); + } + + pet->SetFreeTalentPoints(0); + + SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS); + return true; +} + +bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) +{ + // skipping UNIVERSAL language (0) + for (uint8 i = 1; i < LANGUAGES_COUNT; ++i) + m_session->GetPlayer()->learnSpell(lang_description[i].spell_id, false); + + SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); + return true; +} + +bool ChatHandler::HandleLearnAllDefaultCommand(const char *args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + target->learnDefaultSpells(); + target->learnQuestRewardedSpells(); + + PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,GetNameLink(target).c_str()); + return true; +} + +bool ChatHandler::HandleLearnCommand(const char *args) +{ + Player* targetPlayer = getSelectedPlayer(); + + if (!targetPlayer) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell || !sSpellStore.LookupEntry(spell)) + return false; + + char const* allStr = strtok(NULL," "); + bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + if (!allRanks && targetPlayer->HasSpell(spell)) + { + if (targetPlayer == m_session->GetPlayer()) + SendSysMessage(LANG_YOU_KNOWN_SPELL); + else + PSendSysMessage(LANG_TARGET_KNOWN_SPELL,GetNameLink(targetPlayer).c_str()); + SetSentErrorMessage(true); + return false; + } + + if (allRanks) + targetPlayer->learnSpellHighRank(spell); + else + targetPlayer->learnSpell(spell, false); + + uint32 first_spell = spellmgr.GetFirstSpellInChain(spell); + if (GetTalentSpellCost(first_spell)) + targetPlayer->SendTalentsInfoData(false); + + return true; +} + +bool ChatHandler::HandleAddItemCommand(const char *args) +{ + if (!*args) + return false; + + uint32 itemId = 0; + + if (args[0] == '[') // [name] manual form + { + char* citemName = strtok((char*)args, "]"); + + if (citemName && citemName[0]) + { + std::string itemName = citemName+1; + WorldDatabase.escape_string(itemName); + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE name = '%s'", itemName.c_str()); + if (!result) + { + PSendSysMessage(LANG_COMMAND_COULDNOTFIND, citemName+1); + SetSentErrorMessage(true); + return false; + } + itemId = result->Fetch()->GetUInt16(); + } + else + return false; + } + else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r + { + char* cId = extractKeyFromLink((char*)args,"Hitem"); + if (!cId) + return false; + itemId = atol(cId); + } + + char* ccount = strtok(NULL, " "); + + int32 count = 1; + + if (ccount) + count = strtol(ccount, NULL, 10); + + if (count == 0) + count = 1; + + Player* pl = m_session->GetPlayer(); + Player* plTarget = getSelectedPlayer(); + if (!plTarget) + plTarget = pl; + + sLog.outDetail(GetTrinityString(LANG_ADDITEM), itemId, count); + + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId); + if (!pProto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); + SetSentErrorMessage(true); + return false; + } + + //Subtract + if (count < 0) + { + plTarget->DestroyItemCount(itemId, -count, true, false); + PSendSysMessage(LANG_REMOVEITEM, itemId, -count, GetNameLink(plTarget).c_str()); + return true; + } + + //Adding items + uint32 noSpaceForCount = 0; + + // check space and find places + ItemPosCountVec dest; + uint8 msg = plTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount); + if (msg != EQUIP_ERR_OK) // convert to possible store amount + count -= noSpaceForCount; + + if (count == 0 || dest.empty()) // can't add any + { + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); + SetSentErrorMessage(true); + return false; + } + + Item* item = plTarget->StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); + + // remove binding (let GM give it to another player later) + if (pl == plTarget) + for (ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ++itr) + if (Item* item1 = pl->GetItemByPos(itr->pos)) + item1->SetBinding(false); + + if (count > 0 && item) + { + pl->SendNewItem(item,count,false,true); + if (pl != plTarget) + plTarget->SendNewItem(item,count,true,false); + } + + if (noSpaceForCount > 0) + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); + + return true; +} + +bool ChatHandler::HandleAddItemSetCommand(const char *args) +{ + if (!*args) + return false; + + char* cId = extractKeyFromLink((char*)args,"Hitemset"); // number or [name] Shift-click form |color|Hitemset:itemset_id|h[name]|h|r + if (!cId) + return false; + + uint32 itemsetId = atol(cId); + + // prevent generation all items with itemset field value '0' + if (itemsetId == 0) + { + PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); + SetSentErrorMessage(true); + return false; + } + + Player* pl = m_session->GetPlayer(); + Player* plTarget = getSelectedPlayer(); + if (!plTarget) + plTarget = pl; + + sLog.outDetail(GetTrinityString(LANG_ADDITEMSET), itemsetId); + + bool found = false; + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry(id); + if (!pProto) + continue; + + if (pProto->ItemSet == itemsetId) + { + found = true; + ItemPosCountVec dest; + uint8 msg = plTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, pProto->ItemId, 1); + if (msg == EQUIP_ERR_OK) + { + Item* item = plTarget->StoreNewItem(dest, pProto->ItemId, true); + + // remove binding (let GM give it to another player later) + if (pl == plTarget) + item->SetBinding(false); + + pl->SendNewItem(item,1,false,true); + if (pl != plTarget) + plTarget->SendNewItem(item,1,true,false); + } + else + { + pl->SendEquipError(msg, NULL, NULL); + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, pProto->ItemId, 1); + } + } + } + + if (!found) + { + PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); + + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleListItemCommand(const char *args) +{ + if (!*args) + return false; + + char* cId = extractKeyFromLink((char*)args,"Hitem"); + if (!cId) + return false; + + uint32 item_id = atol(cId); + if (!item_id) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + ItemPrototype const* itemProto = objmgr.GetItemPrototype(item_id); + if (!itemProto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if (count < 0) + return false; + + QueryResult_AutoPtr result; + + // inventory case + uint32 inv_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM character_inventory WHERE item_template='%u'",item_id); + if (result) + inv_count = (*result)[0].GetUInt32(); + + result=CharacterDatabase.PQuery( + // 0 1 2 3 4 5 + "SELECT ci.item, cibag.slot AS bag, ci.slot, ci.guid, characters.account,characters.name " + "FROM character_inventory AS ci LEFT JOIN character_inventory AS cibag ON (cibag.item=ci.bag),characters " + "WHERE ci.item_template='%u' AND ci.guid = characters.guid LIMIT %u ", + item_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 item_bag = fields[1].GetUInt32(); + uint32 item_slot = fields[2].GetUInt32(); + uint32 owner_guid = fields[3].GetUInt32(); + uint32 owner_acc = fields[4].GetUInt32(); + std::string owner_name = fields[5].GetCppString(); + + char const* item_pos = 0; + if (Player::IsEquipmentPos(item_bag,item_slot)) + item_pos = "[equipped]"; + else if (Player::IsInventoryPos(item_bag,item_slot)) + item_pos = "[in inventory]"; + else if (Player::IsBankPos(item_bag,item_slot)) + item_pos = "[in bank]"; + else + item_pos = ""; + + PSendSysMessage(LANG_ITEMLIST_SLOT, + item_guid,owner_name.c_str(),owner_guid,owner_acc,item_pos); + } while (result->NextRow()); + + int64 res_count = result->GetRowCount(); + + if (count > res_count) + count-=res_count; + else if (count) + count = 0; + } + + // mail case + uint32 mail_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM mail_items WHERE item_template='%u'", item_id); + if (result) + mail_count = (*result)[0].GetUInt32(); + + if (count > 0) + { + result=CharacterDatabase.PQuery( + // 0 1 2 3 4 5 6 + "SELECT mail_items.item_guid, mail.sender, mail.receiver, char_s.account, char_s.name, char_r.account, char_r.name " + "FROM mail,mail_items,characters as char_s,characters as char_r " + "WHERE mail_items.item_template='%u' AND char_s.guid = mail.sender AND char_r.guid = mail.receiver AND mail.id=mail_items.mail_id LIMIT %u", + item_id,uint32(count)); + } + else + result = QueryResult_AutoPtr(NULL); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 item_s = fields[1].GetUInt32(); + uint32 item_r = fields[2].GetUInt32(); + uint32 item_s_acc = fields[3].GetUInt32(); + std::string item_s_name = fields[4].GetCppString(); + uint32 item_r_acc = fields[5].GetUInt32(); + std::string item_r_name = fields[6].GetCppString(); + + char const* item_pos = "[in mail]"; + + PSendSysMessage(LANG_ITEMLIST_MAIL, + item_guid,item_s_name.c_str(),item_s,item_s_acc,item_r_name.c_str(),item_r,item_r_acc,item_pos); + } while (result->NextRow()); + + int64 res_count = result->GetRowCount(); + + if (count > res_count) + count-=res_count; + else if (count) + count = 0; + } + + // auction case + uint32 auc_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM auctionhouse WHERE item_template='%u'",item_id); + if (result) + auc_count = (*result)[0].GetUInt32(); + + if (count > 0) + { + result=CharacterDatabase.PQuery( + // 0 1 2 3 + "SELECT auctionhouse.itemguid, auctionhouse.itemowner, characters.account, characters.name " + "FROM auctionhouse,characters WHERE auctionhouse.item_template='%u' AND characters.guid = auctionhouse.itemowner LIMIT %u", + item_id,uint32(count)); + } + else + result = QueryResult_AutoPtr(NULL); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 owner = fields[1].GetUInt32(); + uint32 owner_acc = fields[2].GetUInt32(); + std::string owner_name = fields[3].GetCppString(); + + char const* item_pos = "[in auction]"; + + PSendSysMessage(LANG_ITEMLIST_AUCTION, item_guid, owner_name.c_str(), owner, owner_acc,item_pos); + } while (result->NextRow()); + } + + // guild bank case + uint32 guild_count = 0; + result=CharacterDatabase.PQuery("SELECT COUNT(item_entry) FROM guild_bank_item WHERE item_entry='%u'",item_id); + if (result) + guild_count = (*result)[0].GetUInt32(); + + result=CharacterDatabase.PQuery( + // 0 1 2 + "SELECT gi.item_guid, gi.guildid, guild.name " + "FROM guild_bank_item AS gi, guild WHERE gi.item_entry='%u' AND gi.guildid = guild.guildid LIMIT %u ", + item_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 item_guid = fields[0].GetUInt32(); + uint32 guild_guid = fields[1].GetUInt32(); + std::string guild_name = fields[2].GetCppString(); + + char const* item_pos = "[in guild bank]"; + + PSendSysMessage(LANG_ITEMLIST_GUILD,item_guid,guild_name.c_str(),guild_guid,item_pos); + } while (result->NextRow()); + + int64 res_count = result->GetRowCount(); + + if (count > res_count) + count-=res_count; + else if (count) + count = 0; + } + + if (inv_count+mail_count+auc_count+guild_count == 0) + { + SendSysMessage(LANG_COMMAND_NOITEMFOUND); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_COMMAND_LISTITEMMESSAGE,item_id,inv_count+mail_count+auc_count+guild_count,inv_count,mail_count,auc_count,guild_count); + + return true; +} + +bool ChatHandler::HandleListObjectCommand(const char *args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); + if (!cId) + return false; + + uint32 go_id = atol(cId); + if (!go_id) + { + PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); + SetSentErrorMessage(true); + return false; + } + + GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(go_id); + if (!gInfo) + { + PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if (count < 0) + return false; + + QueryResult_AutoPtr result; + + uint32 obj_count = 0; + result=WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'",go_id); + if (result) + obj_count = (*result)[0].GetUInt32(); + + if (m_session) + { + Player* pl = m_session->GetPlayer(); + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),go_id,uint32(count)); + } + else + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM gameobject WHERE id = '%u' LIMIT %u", + go_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + if (m_session) + PSendSysMessage(LANG_GO_LIST_CHAT, guid, guid, gInfo->name, x, y, z, mapid); + else + PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name, x, y, z, mapid); + } while (result->NextRow()); + } + + PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE,go_id,obj_count); + return true; +} + +bool ChatHandler::HandleGameObjectStateCommand(const char *args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args, "Hgameobject"); + if (!cId) + return false; + + uint32 lowguid = atoi(cId); + if (!lowguid) + return false; + + GameObject* gobj = NULL; + + if (GameObjectData const* goData = objmgr.GetGOData(lowguid)) + gobj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid, goData->id); + + if (!gobj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* ctype = strtok(NULL, " "); + if (!ctype) + return false; + + int32 type = atoi(ctype); + if (type < 0) + { + if (type == -1) + gobj->SendObjectDeSpawnAnim(gobj->GetGUID()); + else if (type == -2) + { + return false; + } + return true; + } + + char* cstate = strtok(NULL, " "); + if (!cstate) + return false; + + int32 state = atoi(cstate); + + if (type < 4) + gobj->SetByteValue(GAMEOBJECT_BYTES_1, type, state); + else if (type == 4) + { + WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM,8+4); + data << gobj->GetGUID(); + data << (uint32)(state); + gobj->SendMessageToSet(&data, true); + } + PSendSysMessage("Set gobject type %d state %d", type, state); + + return true; +} + +bool ChatHandler::HandleListCreatureCommand(const char *args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hcreature_entry"); + if (!cId) + return false; + + uint32 cr_id = atol(cId); + if (!cr_id) + { + PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); + SetSentErrorMessage(true); + return false; + } + + CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(cr_id); + if (!cInfo) + { + PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); + SetSentErrorMessage(true); + return false; + } + + char* c_count = strtok(NULL, " "); + int count = c_count ? atol(c_count) : 10; + + if (count < 0) + return false; + + QueryResult_AutoPtr result; + + uint32 cr_count = 0; + result=WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'",cr_id); + if (result) + cr_count = (*result)[0].GetUInt32(); + + if (m_session) + { + Player* pl = m_session->GetPlayer(); + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM creature WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), cr_id,uint32(count)); + } + else + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM creature WHERE id = '%u' LIMIT %u", + cr_id,uint32(count)); + + if (result) + { + do + { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + int mapid = fields[4].GetUInt16(); + + if (m_session) + PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name, x, y, z, mapid); + else + PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name, x, y, z, mapid); + } while (result->NextRow()); + } + + PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE,cr_id,cr_count); + return true; +} + +bool ChatHandler::HandleLookupItemCommand(const char *args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + // Search in `item_template` + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry(id); + if (!pProto) + continue; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); + if (il) + { + if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty()) + { + std::string name = il->Name[loc_idx]; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage(LANG_ITEM_LIST_CHAT, id, id, name.c_str()); + else + PSendSysMessage(LANG_ITEM_LIST_CONSOLE, id, name.c_str()); + + if (!found) + found = true; + + continue; + } + } + } + } + + std::string name = pProto->Name1; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage(LANG_ITEM_LIST_CHAT, id, id, name.c_str()); + else + PSendSysMessage(LANG_ITEM_LIST_CONSOLE, id, name.c_str()); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_NOITEMFOUND); + + return true; +} + +bool ChatHandler::HandleLookupItemSetCommand(const char *args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + bool found = false; + + // Search in ItemSet.dbc + for (uint32 id = 0; id < sItemSetStore.GetNumRows(); id++) + { + ItemSetEntry const *set = sItemSetStore.LookupEntry(id); + if (set) + { + int loc = GetSessionDbcLocale(); + std::string name = set->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = set->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send item set in "id - [namedlink locale]" format + if (m_session) + PSendSysMessage(LANG_ITEMSET_LIST_CHAT,id,id,name.c_str(),localeNames[loc]); + else + PSendSysMessage(LANG_ITEMSET_LIST_CONSOLE,id,name.c_str(),localeNames[loc]); + + if (!found) + found = true; + } + } + } + if (!found) + SendSysMessage(LANG_COMMAND_NOITEMSETFOUND); + return true; +} + +bool ChatHandler::HandleLookupSkillCommand(const char *args) +{ + if (!*args) + return false; + + // can be NULL in console call + Player* target = getSelectedPlayer(); + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + bool found = false; + + // Search in SkillLine.dbc + for (uint32 id = 0; id < sSkillLineStore.GetNumRows(); id++) + { + SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(id); + if (skillInfo) + { + int loc = GetSessionDbcLocale(); + std::string name = skillInfo->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = skillInfo->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + char valStr[50] = ""; + char const* knownStr = ""; + if (target && target->HasSkill(id)) + { + knownStr = GetTrinityString(LANG_KNOWN); + uint32 curValue = target->GetPureSkillValue(id); + uint32 maxValue = target->GetPureMaxSkillValue(id); + uint32 permValue = target->GetSkillPermBonusValue(id); + uint32 tempValue = target->GetSkillTempBonusValue(id); + + char const* valFormat = GetTrinityString(LANG_SKILL_VALUES); + snprintf(valStr,50,valFormat,curValue,maxValue,permValue,tempValue); + } + + // send skill in "id - [namedlink locale]" format + if (m_session) + PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr,valStr); + else + PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr,valStr); + + if (!found) + found = true; + } + } + } + if (!found) + SendSysMessage(LANG_COMMAND_NOSKILLFOUND); + return true; +} + +bool ChatHandler::HandleLookupSpellCommand(const char *args) +{ + if (!*args) + return false; + + // can be NULL at console call + Player* target = getSelectedPlayer(); + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + bool found = false; + + // Search in Spell.dbc + for (uint32 id = 0; id < sSpellStore.GetNumRows(); id++) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(id); + if (spellInfo) + { + int loc = GetSessionDbcLocale(); + std::string name = spellInfo->SpellName[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = spellInfo->SpellName[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + bool known = target && target->HasSpell(id); + bool learn = (spellInfo->Effect[0] == SPELL_EFFECT_LEARN_SPELL); + + uint32 talentCost = GetTalentSpellCost(id); + + bool talent = (talentCost > 0); + bool passive = IsPassiveSpell(id); + bool active = target && target->HasAura(id); + + // unit32 used to prevent interpreting uint8 as char at output + // find rank of learned spell for learning spell, or talent rank + uint32 rank = talentCost ? talentCost : spellmgr.GetSpellRank(learn ? spellInfo->EffectTriggerSpell[0] : id); + + // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format + std::ostringstream ss; + if (m_session) + ss << id << " - |cffffffff|Hspell:" << id << "|h[" << name; + else + ss << id << " - " << name; + + // include rank in link name + if (rank) + ss << GetTrinityString(LANG_SPELL_RANK) << rank; + + if (m_session) + ss << " " << localeNames[loc] << "]|h|r"; + else + ss << " " << localeNames[loc]; + + if (talent) + ss << GetTrinityString(LANG_TALENT); + if (passive) + ss << GetTrinityString(LANG_PASSIVE); + if (learn) + ss << GetTrinityString(LANG_LEARN); + if (known) + ss << GetTrinityString(LANG_KNOWN); + if (active) + ss << GetTrinityString(LANG_ACTIVE); + + SendSysMessage(ss.str().c_str()); + + if (!found) + found = true; + } + } + } + if (!found) + SendSysMessage(LANG_COMMAND_NOSPELLFOUND); + return true; +} + +bool ChatHandler::HandleLookupQuestCommand(const char *args) +{ + if (!*args) + return false; + + // can be NULL at console call + Player* target = getSelectedPlayer(); + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + ObjectMgr::QuestMap const& qTemplates = objmgr.GetQuestTemplates(); + for (ObjectMgr::QuestMap::const_iterator iter = qTemplates.begin(); iter != qTemplates.end(); ++iter) + { + Quest * qinfo = iter->second; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + QuestLocale const *il = objmgr.GetQuestLocale(qinfo->GetQuestId()); + if (il) + { + if (il->Title.size() > loc_idx && !il->Title[loc_idx].empty()) + { + std::string title = il->Title[loc_idx]; + + if (Utf8FitTo(title, wnamepart)) + { + char const* statusStr = ""; + + if (target) + { + QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); + + if (status == QUEST_STATUS_COMPLETE) + { + if (target->GetQuestRewardStatus(qinfo->GetQuestId())) + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + else + statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + } + else if (status == QUEST_STATUS_INCOMPLETE) + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + } + + if (m_session) + PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),qinfo->GetQuestLevel(),title.c_str(),statusStr); + else + PSendSysMessage(LANG_QUEST_LIST_CONSOLE,qinfo->GetQuestId(),title.c_str(),statusStr); + + if (!found) + found = true; + + continue; + } + } + } + } + + std::string title = qinfo->GetTitle(); + if (title.empty()) + continue; + + if (Utf8FitTo(title, wnamepart)) + { + char const* statusStr = ""; + + if (target) + { + QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); + + if (status == QUEST_STATUS_COMPLETE) + { + if (target->GetQuestRewardStatus(qinfo->GetQuestId())) + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + else + statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + } + else if (status == QUEST_STATUS_INCOMPLETE) + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + } + + if (m_session) + PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),qinfo->GetQuestLevel(),title.c_str(),statusStr); + else + PSendSysMessage(LANG_QUEST_LIST_CONSOLE,qinfo->GetQuestId(),title.c_str(),statusStr); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_NOQUESTFOUND); + + return true; +} + +bool ChatHandler::HandleLookupCreatureCommand(const char *args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr (namepart,wnamepart)) + return false; + + wstrToLower (wnamepart); + + bool found = false; + + for (uint32 id = 0; id< sCreatureStorage.MaxEntry; ++id) + { + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry (id); + if (!cInfo) + continue; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + CreatureLocale const *cl = objmgr.GetCreatureLocale (id); + if (cl) + { + if (cl->Name.size() > loc_idx && !cl->Name[loc_idx].empty ()) + { + std::string name = cl->Name[loc_idx]; + + if (Utf8FitTo (name, wnamepart)) + { + if (m_session) + PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name.c_str ()); + else + PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name.c_str ()); + + if (!found) + found = true; + + continue; + } + } + } + } + + std::string name = cInfo->Name; + if (name.empty ()) + continue; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name.c_str ()); + else + PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name.c_str ()); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage (LANG_COMMAND_NOCREATUREFOUND); + + return true; +} + +bool ChatHandler::HandleLookupObjectCommand(const char *args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + for (uint32 id = 0; id< sGOStorage.MaxEntry; id++) + { + GameObjectInfo const* gInfo = sGOStorage.LookupEntry(id); + if (!gInfo) + continue; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + GameObjectLocale const *gl = objmgr.GetGameObjectLocale(id); + if (gl) + { + if (gl->Name.size() > loc_idx && !gl->Name[loc_idx].empty()) + { + std::string name = gl->Name[loc_idx]; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, id, id, name.c_str()); + else + PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, id, name.c_str()); + + if (!found) + found = true; + + continue; + } + } + } + } + + std::string name = gInfo->name; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + { + if (m_session) + PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, id, id, name.c_str()); + else + PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, id, name.c_str()); + + if (!found) + found = true; + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_NOGAMEOBJECTFOUND); + + return true; +} + +bool ChatHandler::HandleLookupFactionCommand(const char *args) +{ + if (!*args) + return false; + + // Can be NULL at console call + Player *target = getSelectedPlayer (); + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr (namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower (wnamepart); + + bool found = false; + + for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id) + { + FactionEntry const *factionEntry = sFactionStore.LookupEntry (id); + if (factionEntry) + { + FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL; + + int loc = GetSessionDbcLocale(); + std::string name = factionEntry->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = factionEntry->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format + // or "id - [faction] [no reputation]" format + std::ostringstream ss; + if (m_session) + ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r"; + else + ss << id << " - " << name << " " << localeNames[loc]; + + if (repState) // and then target != NULL also + { + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); + std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]); + + ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; + + if (repState->Flags & FACTION_FLAG_VISIBLE) + ss << GetTrinityString(LANG_FACTION_VISIBLE); + if (repState->Flags & FACTION_FLAG_AT_WAR) + ss << GetTrinityString(LANG_FACTION_ATWAR); + if (repState->Flags & FACTION_FLAG_PEACE_FORCED) + ss << GetTrinityString(LANG_FACTION_PEACE_FORCED); + if (repState->Flags & FACTION_FLAG_HIDDEN) + ss << GetTrinityString(LANG_FACTION_HIDDEN); + if (repState->Flags & FACTION_FLAG_INVISIBLE_FORCED) + ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED); + if (repState->Flags & FACTION_FLAG_INACTIVE) + ss << GetTrinityString(LANG_FACTION_INACTIVE); + } + else + ss << GetTrinityString(LANG_FACTION_NOREPUTATION); + + SendSysMessage(ss.str().c_str()); + + if (!found) + found = true; + } + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND); + return true; +} + +bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) +{ + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart,wnamepart)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wnamepart); + + bool found = false; + + // Search in TaxiNodes.dbc + for (uint32 id = 0; id < sTaxiNodesStore.GetNumRows(); id++) + { + TaxiNodesEntry const *nodeEntry = sTaxiNodesStore.LookupEntry(id); + if (nodeEntry) + { + int loc = GetSessionDbcLocale(); + std::string name = nodeEntry->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = 0; + for (; loc < MAX_LOCALE; ++loc) + { + if (loc == GetSessionDbcLocale()) + continue; + + name = nodeEntry->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send taxinode in "id - [name] (Map:m X:x Y:y Z:z)" format + if (m_session) + PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CHAT, id, id, name.c_str(),localeNames[loc], + nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z); + else + PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CONSOLE, id, name.c_str(), localeNames[loc], + nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z); + + if (!found) + found = true; + } + } + } + if (!found) + SendSysMessage(LANG_COMMAND_NOTAXINODEFOUND); + return true; +} + +bool ChatHandler::HandleLookupMapCommand(const char *args) +{ + if (!*args) + return false; + + /*std::string namepart = args; + std::wstring wnamepart; + + // converting string that we try to find to lower case + if (!Utf8toWStr(namepart, wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + + // search in Map.dbc + for (uint32 id = 0; id < sMapStore.GetNumRows(); id++) + { + MapEntry const* MapInfo = sMapStore.LookupEntry(id); + if (MapInfo) + { + uint8 loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); + + std::string name = MapInfo->name[loc]; + if (name.empty()) + continue; + + if (!Utf8FitTo(name, wnamepart)) + { + loc = LOCALE_enUS; + for (; loc < MAX_LOCALE; loc++) + { + if (m_session && loc == m_session->GetSessionDbcLocale()) + continue; + + name = MapInfo->name[loc]; + if (name.empty()) + continue; + + if (Utf8FitTo(name, wnamepart)) + break; + } + } + + if (loc < MAX_LOCALE) + { + // send map in "id - [name][Continent][Instance/Battleground/Arena][Raid reset time:][Heroic reset time:][Mountable]" format + std::ostringstream ss; + + if (m_session) + ss << id << " - |cffffffff|Hmap:" << id << "|h[" << name << "]"; + else // console + ss << id << " - [" << name << "]"; + + if (MapInfo->IsContinent()) + ss << GetTrinityString(LANG_CONTINENT); + + switch(MapInfo->map_type) + { + case MAP_INSTANCE: ss << GetTrinityString(LANG_INSTANCE); break; + case MAP_BATTLEGROUND: ss << GetTrinityString(LANG_BATTLEGROUND); break; + case MAP_ARENA: ss << GetTrinityString(LANG_ARENA); break; + } + + if (MapInfo->IsRaid()) + ss << GetTrinityString(LANG_RAID); + + if (MapInfo->SupportsHeroicMode()) + ss << GetTrinityString(LANG_HEROIC); + + uint32 ResetTimeRaid = MapInfo->resetTimeRaid; + + std::string ResetTimeRaidStr; + if (ResetTimeRaid) + ResetTimeRaidStr = secsToTimeString(ResetTimeRaid, true, false); + + uint32 ResetTimeHeroic = MapInfo->resetTimeHeroic; + std::string ResetTimeHeroicStr; + if (ResetTimeHeroic) + ResetTimeHeroicStr = secsToTimeString(ResetTimeHeroic, true, false); + + if (MapInfo->IsMountAllowed()) + ss << GetTrinityString(LANG_MOUNTABLE); + + if (ResetTimeRaid && !ResetTimeHeroic) + PSendSysMessage(ss.str().c_str(), ResetTimeRaidStr.c_str()); + else if (!ResetTimeRaid && ResetTimeHeroic) + PSendSysMessage(ss.str().c_str(), ResetTimeHeroicStr.c_str()); + else if (ResetTimeRaid && ResetTimeHeroic) + PSendSysMessage(ss.str().c_str(), ResetTimeRaidStr.c_str(), ResetTimeHeroicStr.c_str()); + else + SendSysMessage(ss.str().c_str()); + + if (!found) + found = true; + } + } + } + + if (!found) + SendSysMessage(LANG_COMMAND_NOMAPFOUND); + */ + return true; +} + +/** \brief GM command level 3 - Create a guild. + * + * This command allows a GM (level 3) to create a guild. + * + * The "args" parameter contains the name of the guild leader + * and then the name of the guild. + * + */ +bool ChatHandler::HandleGuildCreateCommand(const char *args) +{ + if (!*args) + return false; + + // if not guild name only (in "") then player name + Player* target; + if (!extractPlayerTarget(*args != '"' ? (char*)args : NULL, &target)) + return false; + + char* tailStr = *args != '"' ? strtok(NULL, "") : (char*)args; + if (!tailStr) + return false; + + char* guildStr = extractQuotedArg(tailStr); + if (!guildStr) + return false; + + std::string guildname = guildStr; + + if (target->GetGuildId()) + { + SendSysMessage (LANG_PLAYER_IN_GUILD); + return true; + } + + Guild *guild = new Guild; + if (!guild->Create (target,guildname)) + { + delete guild; + SendSysMessage (LANG_GUILD_NOT_CREATED); + SetSentErrorMessage (true); + return false; + } + + objmgr.AddGuild (guild); + return true; +} + +bool ChatHandler::HandleGuildInviteCommand(const char *args) +{ + if (!*args) + return false; + + // if not guild name only (in "") then player name + uint64 target_guid; + if (!extractPlayerTarget(*args != '"' ? (char*)args : NULL, NULL, &target_guid)) + return false; + + char* tailStr = *args != '"' ? strtok(NULL, "") : (char*)args; + if (!tailStr) + return false; + + char* guildStr = extractQuotedArg(tailStr); + if (!guildStr) + return false; + + std::string glName = guildStr; + Guild* targetGuild = objmgr.GetGuildByName (glName); + if (!targetGuild) + return false; + + // player's guild membership checked in AddMember before add + if (!targetGuild->AddMember (target_guid,targetGuild->GetLowestRank ())) + return false; + + return true; +} + +bool ChatHandler::HandleGuildUninviteCommand(const char *args) +{ + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; + + uint32 glId = target ? target->GetGuildId () : Player::GetGuildIdFromDB (target_guid); + if (!glId) + return false; + + Guild* targetGuild = objmgr.GetGuildById (glId); + if (!targetGuild) + return false; + + targetGuild->DelMember (target_guid); + return true; +} + +bool ChatHandler::HandleGuildRankCommand(const char *args) +{ + char* nameStr; + char* rankStr; + extractOptFirstArg((char*)args,&nameStr,&rankStr); + if (!rankStr) + return false; + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + uint32 glId = target ? target->GetGuildId () : Player::GetGuildIdFromDB (target_guid); + if (!glId) + return false; + + Guild* targetGuild = objmgr.GetGuildById (glId); + if (!targetGuild) + return false; + + uint32 newrank = uint32 (atoi (rankStr)); + if (newrank > targetGuild->GetLowestRank ()) + return false; + + targetGuild->ChangeRank (target_guid,newrank); + return true; +} + +bool ChatHandler::HandleGuildDeleteCommand(const char *args) +{ + if (!*args) + return false; + + char* guildStr = extractQuotedArg((char*)args); + if (!guildStr) + return false; + + std::string gld = guildStr; + + Guild* targetGuild = objmgr.GetGuildByName (gld); + if (!targetGuild) + return false; + + targetGuild->Disband (); + + return true; +} + +bool ChatHandler::HandleGetDistanceCommand(const char *args) +{ + WorldObject* obj = NULL; + + if (*args) + { + uint64 guid = extractGuidFromLink((char*)args); + if (guid) + obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + + if (!obj) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + obj = getSelectedUnit(); + + if (!obj) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_DISTANCE, m_session->GetPlayer()->GetDistance(obj), m_session->GetPlayer()->GetDistance2d(obj), m_session->GetPlayer()->GetExactDist(obj), m_session->GetPlayer()->GetExactDist2d(obj)); + return true; +} + +bool ChatHandler::HandleDieCommand(const char* /*args*/) +{ + Unit* target = getSelectedUnit(); + + if (!target || !m_session->GetPlayer()->GetSelection()) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->GetTypeId() == TYPEID_PLAYER) + { + if (HasLowerSecurity((Player*)target,0,false)) + return false; + } + + if (target->isAlive()) + { + if (sWorld.getConfig(CONFIG_DIE_COMMAND_MODE)) + m_session->GetPlayer()->Kill(target); + else + m_session->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + return true; +} + +bool ChatHandler::HandleDamageCommand(const char * args) +{ + if (!*args) + return false; + + Unit* target = getSelectedUnit(); + + if (!target || !m_session->GetPlayer()->GetSelection()) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!target->isAlive()) + return true; + + char* damageStr = strtok((char*)args, " "); + if (!damageStr) + return false; + + int32 damage_int = atoi((char*)damageStr); + if (damage_int <= 0) + return true; + + uint32 damage = damage_int; + + char* schoolStr = strtok((char*)NULL, " "); + + // flat melee damage without resistence/etc reduction + if (!schoolStr) + { + m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if (target != m_session->GetPlayer()) + m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); + return true; + } + + uint32 school = schoolStr ? atoi((char*)schoolStr) : SPELL_SCHOOL_NORMAL; + if (school >= MAX_SPELL_SCHOOL) + return false; + + SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); + + if (schoolmask & SPELL_SCHOOL_MASK_NORMAL) + damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage, NULL, BASE_ATTACK); + + char* spellStr = strtok((char*)NULL, " "); + + // melee damage by specific school + if (!spellStr) + { + uint32 absorb = 0; + uint32 resist = 0; + + m_session->GetPlayer()->CalcAbsorbResist(target,schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + + if (damage <= absorb + resist) + return true; + + damage -= absorb + resist; + + m_session->GetPlayer()->DealDamageMods(target,damage,&absorb); + m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); + m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); + return true; + } + + // non-melee damage + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellid = extractSpellIdFromLink((char*)args); + if (!spellid || !sSpellStore.LookupEntry(spellid)) + return false; + + m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage); + return true; +} + +bool ChatHandler::HandleModifyArenaCommand(const char * args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + int32 amount = (uint32)atoi(args); + + target->ModifyArenaPoints(amount); + + PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, GetNameLink(target).c_str(), target->GetArenaPoints()); + + return true; +} + +bool ChatHandler::HandleReviveCommand(const char *args) +{ + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; + + if (target) + { + target->ResurrectPlayer(target->GetSession()->GetSecurity() > SEC_PLAYER ? 1.0f : 0.5f); + target->SpawnCorpseBones(); + target->SaveToDB(); + } + else + // will resurrected at login without corpse + ObjectAccessor::Instance().ConvertCorpseForPlayer(target_guid); + + return true; +} + +bool ChatHandler::HandleAuraCommand(const char *args) +{ + Unit *target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellID = extractSpellIdFromLink((char*)args); + + if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID)) + Aura::TryCreate(spellInfo, target, target); + + return true; +} + +bool ChatHandler::HandleUnAuraCommand(const char *args) +{ + Unit *target = getSelectedUnit(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + std::string argstr = args; + if (argstr == "all") + { + target->RemoveAllAuras(); + return true; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellID = extractSpellIdFromLink((char*)args); + if (!spellID) + return false; + + target->RemoveAurasDueToSpell(spellID); + + return true; +} + +bool ChatHandler::HandleLinkGraveCommand(const char *args) +{ + if (!*args) + return false; + + char* px = strtok((char*)args, " "); + if (!px) + return false; + + uint32 g_id = (uint32)atoi(px); + + uint32 g_team; + + char* px2 = strtok(NULL, " "); + + if (!px2) + g_team = 0; + else if (strncmp(px2,"horde",6) == 0) + g_team = HORDE; + else if (strncmp(px2,"alliance",9) == 0) + g_team = ALLIANCE; + else + return false; + + WorldSafeLocsEntry const* graveyard = sWorldSafeLocsStore.LookupEntry(g_id); + + if (!graveyard) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST, g_id); + SetSentErrorMessage(true); + return false; + } + + Player* player = m_session->GetPlayer(); + + uint32 zoneId = player->GetZoneId(); + + AreaTableEntry const *areaEntry = GetAreaEntryByAreaID(zoneId); + if (!areaEntry || areaEntry->zone !=0) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDWRONGZONE, g_id,zoneId); + SetSentErrorMessage(true); + return false; + } + + if (objmgr.AddGraveYardLink(g_id,zoneId,g_team)) + PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, g_id,zoneId); + else + PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, g_id,zoneId); + + return true; +} + +bool ChatHandler::HandleNearGraveCommand(const char *args) +{ + uint32 g_team; + + size_t argslen = strlen(args); + + if (!*args) + g_team = 0; + else if (strncmp((char*)args,"horde",argslen) == 0) + g_team = HORDE; + else if (strncmp((char*)args,"alliance",argslen) == 0) + g_team = ALLIANCE; + else + return false; + + Player* player = m_session->GetPlayer(); + uint32 zone_id = player->GetZoneId(); + + WorldSafeLocsEntry const* graveyard = objmgr.GetClosestGraveYard( + player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(),player->GetMapId(),g_team); + + if (graveyard) + { + uint32 g_id = graveyard->ID; + + GraveYardData const* data = objmgr.FindGraveYardData(g_id,zone_id); + if (!data) + { + PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR,g_id); + SetSentErrorMessage(true); + return false; + } + + g_team = data->team; + + std::string team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_NOTEAM); + + if (g_team == 0) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ANY); + else if (g_team == HORDE) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_HORDE); + else if (g_team == ALLIANCE) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ALLIANCE); + + PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),zone_id); + } + else + { + std::string team_name; + + if (g_team == 0) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ANY); + else if (g_team == HORDE) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_HORDE); + else if (g_team == ALLIANCE) + team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ALLIANCE); + + if (g_team == ~uint32(0)) + PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id); + else + PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id,team_name.c_str()); + } + + return true; +} + +//-----------------------Npc Commands----------------------- +bool ChatHandler::HandleNpcAllowMovementCommand(const char* /*args*/) +{ + if (sWorld.getAllowMovement()) + { + sWorld.SetAllowMovement(false); + SendSysMessage(LANG_CREATURE_MOVE_DISABLED); + } + else + { + sWorld.SetAllowMovement(true); + SendSysMessage(LANG_CREATURE_MOVE_ENABLED); + } + return true; +} + +bool ChatHandler::HandleNpcChangeEntryCommand(const char *args) +{ + if (!*args) + return false; + + uint32 newEntryNum = atoi(args); + if (!newEntryNum) + return false; + + Unit* unit = getSelectedUnit(); + if (!unit || unit->GetTypeId() != TYPEID_UNIT) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + Creature* creature = unit->ToCreature(); + if (creature->UpdateEntry(newEntryNum)) + SendSysMessage(LANG_DONE); + else + SendSysMessage(LANG_ERROR); + return true; +} + +bool ChatHandler::HandleNpcInfoCommand(const char* /*args*/) +{ + Creature* target = getSelectedCreature(); + + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint32 faction = target->getFaction(); + uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS); + uint32 displayid = target->GetDisplayId(); + uint32 nativeid = target->GetNativeDisplayId(); + uint32 Entry = target->GetEntry(); + CreatureInfo const* cInfo = target->GetCreatureInfo(); + + int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); + if (curRespawnDelay < 0) + curRespawnDelay = 0; + std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true); + std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true); + + PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), faction, npcflags, Entry, displayid, nativeid); + PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); + PSendSysMessage(LANG_NPCINFO_HEALTH,target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); + PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction()); + PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str()); + PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->lootid,cInfo->pickpocketLootId,cInfo->SkinLootId); + PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId()); + PSendSysMessage(LANG_NPCINFO_PHASEMASK, target->GetPhaseMask()); + PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); + PSendSysMessage(LANG_NPCINFO_POSITION,float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); + if (const CreatureData* const linked = target->GetLinkedRespawnCreatureData()) + if (CreatureInfo const *master = GetCreatureInfo(linked->id)) + PSendSysMessage(LANG_NPCINFO_LINKGUID, objmgr.GetLinkedRespawnGuid(target->GetDBTableGUIDLow()), linked->id, master->Name); + + if ((npcflags & UNIT_NPC_FLAG_VENDOR)) + { + SendSysMessage(LANG_NPCINFO_VENDOR); + } + if ((npcflags & UNIT_NPC_FLAG_TRAINER)) + { + SendSysMessage(LANG_NPCINFO_TRAINER); + } + + return true; +} + +//play npc emote +bool ChatHandler::HandleNpcPlayEmoteCommand(const char *args) +{ + uint32 emote = atoi((char*)args); + + Creature* target = getSelectedCreature(); + if (!target) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote); + + return true; +} + +//TODO: NpcCommands that needs to be fixed : + +bool ChatHandler::HandleNpcAddWeaponCommand(const char* /*args*/) +{ + /*if (!*args) + return false; + + uint64 guid = m_session->GetPlayer()->GetSelection(); + if (guid == 0) + { + SendSysMessage(LANG_NO_SELECTION); + return true; + } + + Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + + if (!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + return true; + } + + char* pSlotID = strtok((char*)args, " "); + if (!pSlotID) + return false; + + char* pItemID = strtok(NULL, " "); + if (!pItemID) + return false; + + uint32 ItemID = atoi(pItemID); + uint32 SlotID = atoi(pSlotID); + + ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID); + + bool added = false; + if (tmpItem) + { + switch(SlotID) + { + case 1: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID); + added = true; + break; + case 2: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID); + added = true; + break; + case 3: + pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID); + added = true; + break; + default: + PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID); + added = false; + break; + } + + if (added) + PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID); + } + else + { + PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID); + return true; + } + */ + return true; +} +//---------------------------------------------------------- + +bool ChatHandler::HandleExploreCheatCommand(const char *args) +{ + if (!*args) + return false; + + int flag = atoi((char*)args); + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (flag != 0) + { + PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetNameLink().c_str()); + } + else + { + PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, GetNameLink(chr).c_str()); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetNameLink().c_str()); + } + + for (uint8 i=0; iGetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0xFFFFFFFF); + } + else + { + m_session->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0); + } + } + + return true; +} + +bool ChatHandler::HandleHoverCommand(const char *args) +{ + char* px = strtok((char*)args, " "); + uint32 flag; + if (!px) + flag = 1; + else + flag = atoi(px); + + m_session->GetPlayer()->SetHover(flag); + + if (flag) + SendSysMessage(LANG_HOVER_ENABLED); + else + SendSysMessage(LANG_HOVER_DISABLED); + + return true; +} + +void ChatHandler::HandleCharacterLevel(Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel) +{ + if (player) + { + player->GiveLevel(newlevel); + player->InitTalentForLevel(); + player->SetUInt32Value(PLAYER_XP,0); + + if (needReportToTarget(player)) + { + if (oldlevel == newlevel) + ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET,GetNameLink().c_str()); + else if (oldlevel < newlevel) + ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_UP,GetNameLink().c_str(),newlevel); + else // if (oldlevel > newlevel) + ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_DOWN,GetNameLink().c_str(),newlevel); + } + } + else + { + // update level and XP at level, all other will be updated at loading + CharacterDatabase.PExecute("UPDATE characters SET level = '%u', xp = 0 WHERE guid = '%u'", newlevel, GUID_LOPART(player_guid)); + } +} + +bool ChatHandler::HandleCharacterLevelCommand(const char *args) +{ + char* nameStr; + char* levelStr; + extractOptFirstArg((char*)args,&nameStr,&levelStr); + if (!levelStr) + return false; + + // exception opt second arg: .character level $name + if (isalpha(levelStr[0])) + { + nameStr = levelStr; + levelStr = NULL; // current level will used + } + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid); + int32 newlevel = levelStr ? atoi(levelStr) : oldlevel; + + if (newlevel < 1) + return false; // invalid level + + if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level + newlevel = STRONG_MAX_LEVEL; + + HandleCharacterLevel(target,target_guid,oldlevel,newlevel); + + if (!m_session || m_session->GetPlayer() != target) // including player == NULL + { + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); + } + + return true; +} + +bool ChatHandler::HandleLevelUpCommand(const char *args) +{ + char* nameStr; + char* levelStr; + extractOptFirstArg((char*)args,&nameStr,&levelStr); + + // exception opt second arg: .character level $name + if (levelStr && isalpha(levelStr[0])) + { + nameStr = levelStr; + levelStr = NULL; // current level will used + } + + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) + return false; + + int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid); + int32 addlevel = levelStr ? atoi(levelStr) : 1; + int32 newlevel = oldlevel + addlevel; + + if (newlevel < 1) + newlevel = 1; + + if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level + newlevel = STRONG_MAX_LEVEL; + + HandleCharacterLevel(target,target_guid,oldlevel,newlevel); + + if (!m_session || m_session->GetPlayer() != target) // including chr == NULL + { + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); + } + + return true; +} + +bool ChatHandler::HandleShowAreaCommand(const char *args) +{ + if (!*args) + return false; + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + int area = GetAreaFlagByAreaID(atoi((char*)args)); + int offset = area / 32; + uint32 val = (uint32)(1 << (area % 32)); + + if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 currFields = chr->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); + chr->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val)); + + SendSysMessage(LANG_EXPLORE_AREA); + return true; +} + +bool ChatHandler::HandleHideAreaCommand(const char *args) +{ + if (!*args) + return false; + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + int area = GetAreaFlagByAreaID(atoi((char*)args)); + int offset = area / 32; + uint32 val = (uint32)(1 << (area % 32)); + + if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + uint32 currFields = chr->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); + chr->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields ^ val)); + + SendSysMessage(LANG_UNEXPLORE_AREA); + return true; +} + +bool ChatHandler::HandleBankCommand(const char* /*args*/) +{ + m_session->SendShowBank(m_session->GetPlayer()->GetGUID()); + + return true; +} + +bool ChatHandler::HandleChangeWeather(const char *args) +{ + if (!*args) + return false; + + //Weather is OFF + if (!sWorld.getConfig(CONFIG_WEATHER)) + { + SendSysMessage(LANG_WEATHER_DISABLED); + SetSentErrorMessage(true); + return false; + } + + //*Change the weather of a cell + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 type = (uint32)atoi(px); //0 to 3, 0: fine, 1: rain, 2: snow, 3: sand + float grade = (float)atof(py); //0 to 1, sending -1 is instand good weather + + Player *player = m_session->GetPlayer(); + uint32 zoneid = player->GetZoneId(); + + Weather* wth = sWorld.FindWeather(zoneid); + + if (!wth) + wth = sWorld.AddWeather(zoneid); + if (!wth) + { + SendSysMessage(LANG_NO_WEATHER); + SetSentErrorMessage(true); + return false; + } + + wth->SetWeather(WeatherType(type), grade); + + return true; +} + +bool ChatHandler::HandleDebugSet32Bit(const char *args) +{ + if (!*args) + return false; + + WorldObject* target = getSelectedObject(); + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 Opcode = (uint32)atoi(px); + uint32 Value = (uint32)atoi(py); + if (Value > 32) //uint32 = 32 bits + return false; + + sLog.outDebug(GetTrinityString(LANG_SET_32BIT), Opcode, Value); + + uint32 iValue = Value ? 1 << (Value - 1) : 0; + target->SetUInt32Value(Opcode , iValue); + + PSendSysMessage(LANG_SET_32BIT_FIELD, Opcode, iValue); + return true; +} + +bool ChatHandler::HandleTeleAddCommand(const char * args) +{ + if (!*args) + return false; + + Player *player=m_session->GetPlayer(); + if (!player) + return false; + + std::string name = args; + + if (objmgr.GetGameTele(name)) + { + SendSysMessage(LANG_COMMAND_TP_ALREADYEXIST); + SetSentErrorMessage(true); + return false; + } + + GameTele tele; + tele.position_x = player->GetPositionX(); + tele.position_y = player->GetPositionY(); + tele.position_z = player->GetPositionZ(); + tele.orientation = player->GetOrientation(); + tele.mapId = player->GetMapId(); + tele.name = name; + + if (objmgr.AddGameTele(tele)) + { + SendSysMessage(LANG_COMMAND_TP_ADDED); + } + else + { + SendSysMessage(LANG_COMMAND_TP_ADDEDERR); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleTeleDelCommand(const char * args) +{ + if (!*args) + return false; + + std::string name = args; + + if (!objmgr.DeleteGameTele(name)) + { + SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); + SetSentErrorMessage(true); + return false; + } + + SendSysMessage(LANG_COMMAND_TP_DELETED); + return true; +} + +bool ChatHandler::HandleListAurasCommand (const char * /*args*/) +{ + Unit *unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + char const* talentStr = GetTrinityString(LANG_TALENT); + char const* passiveStr = GetTrinityString(LANG_PASSIVE); + + Unit::AuraApplicationMap const& uAuras = unit->GetAppliedAuras(); + PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size()); + for (Unit::AuraApplicationMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) + { + bool talent = GetTalentSpellCost(itr->second->GetBase()->GetId()) > 0; + + AuraApplication const * aurApp = itr->second; + Aura const * aura = aurApp->GetBase(); + char const* name = aura->GetSpellProto()->SpellName[GetSessionDbcLocale()]; + + if (m_session) + { + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r"; + + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), aurApp->GetEffectMask(), + aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), + aura->GetDuration(), aura->GetMaxDuration(), + ss_name.str().c_str(), + (aura->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(aura->GetCasterGUID())); + } + else + { + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), aurApp->GetEffectMask(), + aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), + aura->GetDuration(), aura->GetMaxDuration(), + name, + (aura->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(aura->GetCasterGUID())); + } + } + for (uint16 i = 0; i < TOTAL_AURAS; ++i) + { + Unit::AuraEffectList const& uAuraList = unit->GetAuraEffectsByType(AuraType(i)); + if (uAuraList.empty()) continue; + PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, uAuraList.size(), i); + for (Unit::AuraEffectList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) + { + //bool talent = GetTalentSpellCost((*itr)->GetId()) > 0; + + char const* name = (*itr)->GetSpellProto()->SpellName[GetSessionDbcLocale()]; + + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << (*itr)->GetId() << "|h[" << name << "]|h|r"; + + PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), + (*itr)->GetAmount()); + } + } + return true; +} + +bool ChatHandler::HandleResetAchievementsCommand (const char * args) +{ + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; + + if (target) + target->GetAchievementMgr().Reset(); + else + AchievementMgr::DeleteFromDB(GUID_LOPART(target_guid)); + + return true; +} + +bool ChatHandler::HandleResetHonorCommand (const char * args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, 0); + target->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); + target->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); + target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); + + return true; +} + +static bool HandleResetStatsOrLevelHelper(Player* player) +{ + ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(player->getClass()); + if (!cEntry) + { + sLog.outError("Class %u not found in DBC (Wrong DBC files?)",player->getClass()); + return false; + } + + uint8 powertype = cEntry->powerType; + + // reset m_form if no aura + if (!player->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT)) + player->m_form = FORM_NONE; + + player->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + player->SetFloatValue(UNIT_FIELD_COMBATREACH, DEFAULT_COMBAT_REACH); + + player->setFactionForRace(player->getRace()); + + player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powertype << 24))); + + // reset only if player not in some form; + if (player->m_form == FORM_NONE) + player->InitDisplayIds(); + + player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); + player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form); + + player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + //-1 is default value + player->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); + + //player->SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000); + return true; +} + +bool ChatHandler::HandleResetLevelCommand(const char * args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + if (!HandleResetStatsOrLevelHelper(target)) + return false; + + // set starting level + uint32 start_level = target->getClass() != CLASS_DEATH_KNIGHT + ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) + : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); + + target->_ApplyAllLevelScaleItemMods(false); + + target->SetLevel(start_level); + target->InitRunes(); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitGlyphsForLevel(); + target->InitTalentForLevel(); + target->SetUInt32Value(PLAYER_XP,0); + + target->_ApplyAllLevelScaleItemMods(true); + + // reset level for pet + if (Pet* pet = target->GetPet()) + pet->SynchronizeLevelWithOwner(); + + return true; +} + +bool ChatHandler::HandleResetStatsCommand(const char * args) +{ + Player* target; + if (!extractPlayerTarget((char*)args,&target)) + return false; + + if (!HandleResetStatsOrLevelHelper(target)) + return false; + + target->InitRunes(); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitGlyphsForLevel(); + target->InitTalentForLevel(); + + return true; +} + +bool ChatHandler::HandleResetSpellsCommand(const char * args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + return false; + + if (target) + { + target->resetSpells(/* bool myClassOnly */); + + ChatHandler(target).SendSysMessage(LANG_RESET_SPELLS); + if (!m_session || m_session->GetPlayer() != target) + PSendSysMessage(LANG_RESET_SPELLS_ONLINE,GetNameLink(target).c_str()); + } + else + { + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_SPELLS), GUID_LOPART(target_guid)); + PSendSysMessage(LANG_RESET_SPELLS_OFFLINE,target_name.c_str()); + } + + return true; +} + +bool ChatHandler::HandleResetTalentsCommand(const char * args) +{ + Player* target; + uint64 target_guid; + std::string target_name; + if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) + { + // Try reset talents as Hunter Pet + Creature* creature = getSelectedCreature(); + if (!*args && creature && creature->isPet()) + { + Unit *owner = creature->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet *)creature)->IsPermanentPetFor(owner->ToPlayer())) + { + ((Pet *)creature)->resetTalents(true); + owner->ToPlayer()->SendTalentsInfoData(true); + + ChatHandler(owner->ToPlayer()).SendSysMessage(LANG_RESET_PET_TALENTS); + if (!m_session || m_session->GetPlayer() != owner->ToPlayer()) + PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE,GetNameLink(owner->ToPlayer()).c_str()); + } + return true; + } + + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + if (target) + { + target->resetTalents(true); + target->SendTalentsInfoData(false); + ChatHandler(target).SendSysMessage(LANG_RESET_TALENTS); + if (!m_session || m_session->GetPlayer() != target) + PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(target).c_str()); + + Pet* pet = target->GetPet(); + Pet::resetTalentsForAllPetsOf(target,pet); + if (pet) + target->SendTalentsInfoData(true); + return true; + } + else if (target_guid) + { + uint32 at_flags = AT_LOGIN_NONE | AT_LOGIN_RESET_PET_TALENTS; + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",at_flags, GUID_LOPART(target_guid)); + std::string nameLink = playerLink(target_name); + PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,nameLink.c_str()); + return true; + } + + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; +} + +bool ChatHandler::HandleResetAllCommand(const char * args) +{ + if (!*args) + return false; + + std::string casename = args; + + AtLoginFlags atLogin; + + // Command specially created as single command to prevent using short case names + if (casename == "spells") + { + atLogin = AT_LOGIN_RESET_SPELLS; + sWorld.SendWorldText(LANG_RESETALL_SPELLS); + if (!m_session) + SendSysMessage(LANG_RESETALL_SPELLS); + } + else if (casename == "talents") + { + atLogin = AtLoginFlags(AT_LOGIN_RESET_TALENTS | AT_LOGIN_RESET_PET_TALENTS); + sWorld.SendWorldText(LANG_RESETALL_TALENTS); + if (!m_session) + SendSysMessage(LANG_RESETALL_TALENTS); + } + else + { + PSendSysMessage(LANG_RESETALL_UNKNOWN_CASE,args); + SetSentErrorMessage(true); + return false; + } + + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE (at_login & '%u') = '0'",atLogin,atLogin); + + ObjectAccessor::Guard guard(*HashMapHolder::GetLock()); + HashMapHolder::MapType const& plist = ObjectAccessor::Instance().GetPlayers(); + for (HashMapHolder::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) + itr->second->SetAtLoginFlag(atLogin); + + return true; +} + +bool ChatHandler::HandleServerShutDownCancelCommand(const char* /*args*/) +{ + sWorld.ShutdownCancel(); + return true; +} + +bool ChatHandler::HandleServerShutDownCommand(const char *args) +{ + if (!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0')) || time < 0) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, 0, exitcode); + } + else + sWorld.ShutdownServ(time,0,SHUTDOWN_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleServerRestartCommand(const char *args) +{ + if (!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0)) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART, exitcode); + } + else + sWorld.ShutdownServ(time, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleServerIdleRestartCommand(const char *args) +{ + if (!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0)) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE, exitcode); + } + else + sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE,RESTART_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleServerIdleShutDownCommand(const char *args) +{ + if (!*args) + return false; + + char* time_str = strtok ((char*) args, " "); + char* exitcode_str = strtok (NULL, ""); + + int32 time = atoi (time_str); + + ///- Prevent interpret wrong arg value as 0 secs shutdown time + if (time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0) + return false; + + if (exitcode_str) + { + int32 exitcode = atoi (exitcode_str); + + // Handle atoi() errors + if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitcode < 0 || exitcode > 125) + return false; + + sWorld.ShutdownServ (time, SHUTDOWN_MASK_IDLE, exitcode); + } + else + sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE,SHUTDOWN_EXIT_CODE); + return true; +} + +bool ChatHandler::HandleQuestAdd(const char *args) +{ + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .addquest #entry' + // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if (!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + if (!pQuest) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND,entry); + SetSentErrorMessage(true); + return false; + } + + // check item starting quest (it can work incorrectly if added without item in inventory) + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry(id); + if (!pProto) + continue; + + if (pProto->StartQuest == entry) + { + PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, pProto->ItemId); + SetSentErrorMessage(true); + return false; + } + } + + // ok, normal (creature/GO starting) quest + if (player->CanAddQuest(pQuest, true)) + { + player->AddQuest(pQuest, NULL); + + if (player->CanCompleteQuest(entry)) + player->CompleteQuest(entry); + } + + return true; +} + +bool ChatHandler::HandleQuestRemove(const char *args) +{ + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .removequest #entry' + // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if (!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + if (!pQuest) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + // remove all quest entries for 'entry' from quest log + for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) + { + uint32 quest = player->GetQuestSlotQuestId(slot); + if (quest == entry) + { + player->SetQuestSlot(slot,0); + + // we ignore unequippable quest items in this case, its' still be equipped + player->TakeQuestSourceItem(quest, false); + } + } + + // set quest status to not started (will updated in DB at next save) + player->SetQuestStatus(entry, QUEST_STATUS_NONE); + + // reset rewarded for restart repeatable quest + player->getQuestStatusMap()[entry].m_rewarded = false; + + SendSysMessage(LANG_COMMAND_QUEST_REMOVED); + return true; +} + +bool ChatHandler::HandleQuestComplete(const char *args) +{ + Player* player = getSelectedPlayer(); + if (!player) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // .quest complete #entry + // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hquest"); + if (!cId) + return false; + + uint32 entry = atol(cId); + + Quest const* pQuest = objmgr.GetQuestTemplate(entry); + + // If player doesn't have the quest + if (!pQuest || player->GetQuestStatus(entry) == QUEST_STATUS_NONE) + { + PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); + SetSentErrorMessage(true); + return false; + } + + // Add quest items for quests that require items + for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x) + { + uint32 id = pQuest->ReqItemId[x]; + uint32 count = pQuest->ReqItemCount[x]; + if (!id || !count) + continue; + + uint32 curItemCount = player->GetItemCount(id,true); + + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count-curItemCount); + if (msg == EQUIP_ERR_OK) + { + Item* item = player->StoreNewItem(dest, id, true); + player->SendNewItem(item,count-curItemCount,true,false); + } + } + + // All creature/GO slain/casted (not required, but otherwise it will display "Creature slain 0/10") + for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + { + uint32 creature = pQuest->ReqCreatureOrGOId[i]; + uint32 creaturecount = pQuest->ReqCreatureOrGOCount[i]; + + if (uint32 spell_id = pQuest->ReqSpell[i]) + { + for (uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(creature,0,spell_id); + } + else if (creature > 0) + { + if (CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(creature)) + for (uint16 z = 0; z < creaturecount; ++z) + player->KilledMonster(cInfo,0); + } + else if (creature < 0) + { + for (uint16 z = 0; z < creaturecount; ++z) + player->CastedCreatureOrGO(creature,0,0); + } + } + + // If the quest requires reputation to complete + if (uint32 repFaction = pQuest->GetRepObjectiveFaction()) + { + uint32 repValue = pQuest->GetRepObjectiveValue(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue) + if (FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry,repValue); + } + + // If the quest requires a SECOND reputation to complete + if (uint32 repFaction = pQuest->GetRepObjectiveFaction2()) + { + uint32 repValue2 = pQuest->GetRepObjectiveValue2(); + uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); + if (curRep < repValue2) + if (FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction)) + player->GetReputationMgr().SetReputation(factionEntry,repValue2); + } + + // If the quest requires money + int32 ReqOrRewMoney = pQuest->GetRewOrReqMoney(); + if (ReqOrRewMoney < 0) + player->ModifyMoney(-ReqOrRewMoney); + + player->CompleteQuest(entry); + return true; +} + +bool ChatHandler::HandleBanAccountCommand(const char *args) +{ + return HandleBanHelper(BAN_ACCOUNT,args); +} + +bool ChatHandler::HandleBanCharacterCommand(const char *args) +{ + return HandleBanHelper(BAN_CHARACTER,args); +} + +bool ChatHandler::HandleBanIPCommand(const char *args) +{ + return HandleBanHelper(BAN_IP,args); +} + +bool ChatHandler::HandleBanHelper(BanMode mode, const char *args) +{ + if (!*args) + return false; + + char* cnameOrIP = strtok ((char*)args, " "); + if (!cnameOrIP) + return false; + + std::string nameOrIP = cnameOrIP; + + char* duration = strtok (NULL," "); + if (!duration || !atoi(duration)) + return false; + + char* reason = strtok (NULL,""); + if (!reason) + return false; + + switch(mode) + { + case BAN_ACCOUNT: + if (!AccountMgr::normalizeString(nameOrIP)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,nameOrIP.c_str()); + SetSentErrorMessage(true); + return false; + } + break; + case BAN_CHARACTER: + if (!normalizePlayerName(nameOrIP)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + break; + case BAN_IP: + if (!IsIPAddress(nameOrIP.c_str())) + return false; + break; + } + + switch(sWorld.BanAccount(mode, nameOrIP, duration, reason,m_session ? m_session->GetPlayerName() : "")) + { + case BAN_SUCCESS: + if (atoi(duration)>0) + PSendSysMessage(LANG_BAN_YOUBANNED,nameOrIP.c_str(),secsToTimeString(TimeStringToSecs(duration),true).c_str(),reason); + else + PSendSysMessage(LANG_BAN_YOUPERMBANNED,nameOrIP.c_str(),reason); + break; + case BAN_SYNTAX_ERROR: + return false; + case BAN_NOTFOUND: + switch(mode) + { + default: + PSendSysMessage(LANG_BAN_NOTFOUND,"account",nameOrIP.c_str()); + break; + case BAN_CHARACTER: + PSendSysMessage(LANG_BAN_NOTFOUND,"character",nameOrIP.c_str()); + break; + case BAN_IP: + PSendSysMessage(LANG_BAN_NOTFOUND,"ip",nameOrIP.c_str()); + break; + } + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleUnBanAccountCommand(const char *args) +{ + return HandleUnBanHelper(BAN_ACCOUNT,args); +} + +bool ChatHandler::HandleUnBanCharacterCommand(const char *args) +{ + return HandleUnBanHelper(BAN_CHARACTER,args); +} + +bool ChatHandler::HandleUnBanIPCommand(const char *args) +{ + return HandleUnBanHelper(BAN_IP,args); +} + +bool ChatHandler::HandleUnBanHelper(BanMode mode, const char *args) +{ + if (!*args) + return false; + + char* cnameOrIP = strtok ((char*)args, " "); + if (!cnameOrIP) + return false; + + std::string nameOrIP = cnameOrIP; + + switch(mode) + { + case BAN_ACCOUNT: + if (!AccountMgr::normalizeString(nameOrIP)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,nameOrIP.c_str()); + SetSentErrorMessage(true); + return false; + } + break; + case BAN_CHARACTER: + if (!normalizePlayerName(nameOrIP)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + break; + case BAN_IP: + if (!IsIPAddress(nameOrIP.c_str())) + return false; + break; + } + + if (sWorld.RemoveBanAccount(mode,nameOrIP)) + PSendSysMessage(LANG_UNBAN_UNBANNED,nameOrIP.c_str()); + else + PSendSysMessage(LANG_UNBAN_ERROR,nameOrIP.c_str()); + + return true; +} + +bool ChatHandler::HandleBanInfoAccountCommand(const char *args) +{ + if (!*args) + return false; + + char* cname = strtok((char*)args, ""); + if (!cname) + return false; + + std::string account_name = cname; + if (!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + uint32 accountid = accmgr.GetId(account_name); + if (!accountid) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + return true; + } + + return HandleBanInfoHelper(accountid,account_name.c_str()); +} + +bool ChatHandler::HandleBanInfoCharacterCommand(const char *args) +{ + Player* target; + uint64 target_guid; + if (!extractPlayerTarget((char*)args,&target,&target_guid)) + return false; + + uint32 accountid = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); + + std::string accountname; + if (!accmgr.GetName(accountid,accountname)) + { + PSendSysMessage(LANG_BANINFO_NOCHARACTER); + return true; + } + + return HandleBanInfoHelper(accountid,accountname.c_str()); +} + +bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) +{ + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid); + if (!result) + { + PSendSysMessage(LANG_BANINFO_NOACCOUNTBAN, accountname); + return true; + } + + PSendSysMessage(LANG_BANINFO_BANHISTORY,accountname); + do + { + Field* fields = result->Fetch(); + + time_t unbandate = time_t(fields[3].GetUInt64()); + bool active = false; + if (fields[2].GetBool() && (fields[1].GetUInt64() == (uint64)0 ||unbandate >= time(NULL))) + active = true; + bool permanent = (fields[1].GetUInt64() == (uint64)0); + std::string bantime = permanent?GetTrinityString(LANG_BANINFO_INFINITE):secsToTimeString(fields[1].GetUInt64(), true); + PSendSysMessage(LANG_BANINFO_HISTORYENTRY, + fields[0].GetString(), bantime.c_str(), active ? GetTrinityString(LANG_BANINFO_YES):GetTrinityString(LANG_BANINFO_NO), fields[4].GetString(), fields[5].GetString()); + }while (result->NextRow()); + + return true; +} + +bool ChatHandler::HandleBanInfoIPCommand(const char *args) +{ + if (!*args) + return false; + + char* cIP = strtok ((char*)args, ""); + if (!cIP) + return false; + + if (!IsIPAddress(cIP)) + return false; + + std::string IP = cIP; + + LoginDatabase.escape_string(IP); + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str()); + if (!result) + { + PSendSysMessage(LANG_BANINFO_NOIP); + return true; + } + + Field *fields = result->Fetch(); + bool permanent = !fields[6].GetUInt64(); + PSendSysMessage(LANG_BANINFO_IPENTRY, + fields[0].GetString(), fields[1].GetString(), permanent ? GetTrinityString(LANG_BANINFO_NEVER):fields[2].GetString(), + permanent ? GetTrinityString(LANG_BANINFO_INFINITE):secsToTimeString(fields[3].GetUInt64(), true).c_str(), fields[4].GetString(), fields[5].GetString()); + + return true; +} + +bool ChatHandler::HandleBanListCharacterCommand(const char *args) +{ + LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); + + char* cFilter = strtok ((char*)args, " "); + if (!cFilter) + return false; + + std::string filter = cFilter; + LoginDatabase.escape_string(filter); + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),filter.c_str()); + if (!result) + { + PSendSysMessage(LANG_BANLIST_NOCHARACTER); + return true; + } + + return HandleBanListHelper(result); +} + +bool ChatHandler::HandleBanListAccountCommand(const char *args) +{ + LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); + + char* cFilter = strtok((char*)args, " "); + std::string filter = cFilter ? cFilter : ""; + LoginDatabase.escape_string(filter); + + QueryResult_AutoPtr result; + + if (filter.empty()) + { + result = LoginDatabase.Query("SELECT account.id, username FROM account, account_banned" + " WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id"); + } + else + { + result = LoginDatabase.PQuery("SELECT account.id, username FROM account, account_banned" + " WHERE account.id = account_banned.id AND active = 1 AND username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" GROUP BY account.id", + filter.c_str()); + } + + if (!result) + { + PSendSysMessage(LANG_BANLIST_NOACCOUNT); + return true; + } + + return HandleBanListHelper(result); +} + +bool ChatHandler::HandleBanListHelper(QueryResult_AutoPtr result) +{ + PSendSysMessage(LANG_BANLIST_MATCHINGACCOUNT); + + // Chat short output + if (m_session) + { + do + { + Field* fields = result->Fetch(); + uint32 accountid = fields[0].GetUInt32(); + + QueryResult_AutoPtr banresult = LoginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid); + if (banresult) + { + Field* fields2 = banresult->Fetch(); + PSendSysMessage("%s",fields2[0].GetString()); + } + } while (result->NextRow()); + } + // Console wide output + else + { + SendSysMessage(LANG_BANLIST_ACCOUNTS); + SendSysMessage(" ==============================================================================="); + SendSysMessage(LANG_BANLIST_ACCOUNTS_HEADER); + do + { + SendSysMessage("-------------------------------------------------------------------------------"); + Field *fields = result->Fetch(); + uint32 account_id = fields[0].GetUInt32 (); + + std::string account_name; + + // "account" case, name can be get in same query + if (result->GetFieldCount() > 1) + account_name = fields[1].GetCppString(); + // "character" case, name need extract from another DB + else + accmgr.GetName (account_id,account_name); + + // No SQL injection. id is uint32. + QueryResult_AutoPtr banInfo = LoginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id); + if (banInfo) + { + Field *fields2 = banInfo->Fetch(); + do + { + time_t t_ban = fields2[0].GetUInt64(); + tm* aTm_ban = localtime(&t_ban); + + if (fields2[0].GetUInt64() == fields2[1].GetUInt64()) + { + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", + account_name.c_str(),aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + fields2[2].GetString(),fields2[3].GetString()); + } + else + { + time_t t_unban = fields2[1].GetUInt64(); + tm* aTm_unban = localtime(&t_unban); + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", + account_name.c_str(),aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min, + fields2[2].GetString(),fields2[3].GetString()); + } + }while (banInfo->NextRow()); + } + }while (result->NextRow()); + SendSysMessage(" ==============================================================================="); + } + return true; +} + +bool ChatHandler::HandleBanListIPCommand(const char *args) +{ + LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); + + char* cFilter = strtok((char*)args, " "); + std::string filter = cFilter ? cFilter : ""; + LoginDatabase.escape_string(filter); + + QueryResult_AutoPtr result; + + if (filter.empty()) + { + result = LoginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" + " WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP())" + " ORDER BY unbandate"); + } + else + { + result = LoginDatabase.PQuery("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" + " WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP()) AND ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'") + " ORDER BY unbandate",filter.c_str()); + } + + if (!result) + { + PSendSysMessage(LANG_BANLIST_NOIP); + return true; + } + + PSendSysMessage(LANG_BANLIST_MATCHINGIP); + // Chat short output + if (m_session) + { + do + { + Field* fields = result->Fetch(); + PSendSysMessage("%s",fields[0].GetString()); + } while (result->NextRow()); + } + // Console wide output + else + { + SendSysMessage(LANG_BANLIST_IPS); + SendSysMessage(" ==============================================================================="); + SendSysMessage(LANG_BANLIST_IPS_HEADER); + do + { + SendSysMessage("-------------------------------------------------------------------------------"); + Field *fields = result->Fetch(); + time_t t_ban = fields[1].GetUInt64(); + tm* aTm_ban = localtime(&t_ban); + if (fields[1].GetUInt64() == fields[2].GetUInt64()) + { + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", + fields[0].GetString(), aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + fields[3].GetString(), fields[4].GetString()); + } + else + { + time_t t_unban = fields[2].GetUInt64(); + tm* aTm_unban = localtime(&t_unban); + PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", + fields[0].GetString(), aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, + aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min, + fields[3].GetString(), fields[4].GetString()); + } + }while (result->NextRow()); + SendSysMessage(" ==============================================================================="); + } + + return true; +} + +bool ChatHandler::HandleRespawnCommand(const char* /*args*/) +{ + Player* pl = m_session->GetPlayer(); + + // accept only explicitly selected target (not implicitly self targeting case) + Unit* target = getSelectedUnit(); + if (pl->GetSelection() && target) + { + if (target->GetTypeId() != TYPEID_UNIT || target->isPet()) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (target->isDead()) + target->ToCreature()->Respawn(); + return true; + } + + CellPair p(Trinity::ComputeCellPair(pl->GetPositionX(), pl->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::RespawnDo u_do; + Trinity::WorldObjectWorker worker(pl,u_do); + + TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); + cell.Visit(p, obj_worker, *pl->GetMap()); + + return true; +} + +bool ChatHandler::HandleGMFlyCommand(const char *args) +{ + if (!*args) + return false; + + Player *target = getSelectedPlayer(); + if (!target) + target = m_session->GetPlayer(); + + WorldPacket data(12); + if (strncmp(args, "on", 3) == 0) + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + else if (strncmp(args, "off", 4) == 0) + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + else + { + SendSysMessage(LANG_USE_BOL); + return false; + } + data.append(target->GetPackGUID()); + data << uint32(0); // unknown + target->SendMessageToSet(&data, true); + PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, GetNameLink(target).c_str(), args); + return true; +} + +bool ChatHandler::HandlePDumpLoadCommand(const char *args) +{ + if (!*args) + return false; + + char * file = strtok((char*)args, " "); + if (!file) + return false; + + char * account = strtok(NULL, " "); + if (!account) + return false; + + std::string account_name = account; + if (!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + uint32 account_id = accmgr.GetId(account_name); + if (!account_id) + { + account_id = atoi(account); // use original string + if (!account_id) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + } + + if (!accmgr.GetName(account_id,account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + char* guid_str = NULL; + char* name_str = strtok(NULL, " "); + + std::string name; + if (name_str) + { + name = name_str; + // normalize the name if specified and check if it exists + if (!normalizePlayerName(name)) + { + PSendSysMessage(LANG_INVALID_CHARACTER_NAME); + SetSentErrorMessage(true); + return false; + } + + if (ObjectMgr::CheckPlayerName(name,true) != CHAR_NAME_SUCCESS) + { + PSendSysMessage(LANG_INVALID_CHARACTER_NAME); + SetSentErrorMessage(true); + return false; + } + + guid_str = strtok(NULL, " "); + } + + uint32 guid = 0; + + if (guid_str) + { + guid = atoi(guid_str); + if (!guid) + { + PSendSysMessage(LANG_INVALID_CHARACTER_GUID); + SetSentErrorMessage(true); + return false; + } + + if (objmgr.GetPlayerAccountIdByGUID(guid)) + { + PSendSysMessage(LANG_CHARACTER_GUID_IN_USE,guid); + SetSentErrorMessage(true); + return false; + } + } + + switch(PlayerDumpReader().LoadDump(file, account_id, name, guid)) + { + case DUMP_SUCCESS: + PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS); + break; + case DUMP_FILE_OPEN_ERROR: + PSendSysMessage(LANG_FILE_OPEN_FAIL,file); + SetSentErrorMessage(true); + return false; + case DUMP_FILE_BROKEN: + PSendSysMessage(LANG_DUMP_BROKEN,file); + SetSentErrorMessage(true); + return false; + case DUMP_TOO_MANY_CHARS: + PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL,account_name.c_str(),account_id); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_COMMAND_IMPORT_FAILED); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandlePDumpWriteCommand(const char *args) +{ + if (!*args) + return false; + + char* file = strtok((char*)args, " "); + char* p2 = strtok(NULL, " "); + + if (!file || !p2) + return false; + + uint32 guid; + // character name can't start from number + if (isNumeric(p2[0])) + guid = atoi(p2); + else + { + std::string name = extractPlayerNameFromLink(p2); + if (name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + guid = objmgr.GetPlayerGUIDByName(name); + } + + if (!objmgr.GetPlayerAccountIdByGUID(guid)) + { + PSendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + switch(PlayerDumpWriter().WriteDump(file, guid)) + { + case DUMP_SUCCESS: + PSendSysMessage(LANG_COMMAND_EXPORT_SUCCESS); + break; + case DUMP_FILE_OPEN_ERROR: + PSendSysMessage(LANG_FILE_OPEN_FAIL,file); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_COMMAND_EXPORT_FAILED); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleMovegensCommand(const char* /*args*/) +{ + Unit* unit = getSelectedUnit(); + if (!unit) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_MOVEGENS_LIST,(unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"),unit->GetGUIDLow()); + + MotionMaster* mm = unit->GetMotionMaster(); + for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) + { + MovementGenerator* mg = mm->GetMotionSlot(i); + if (!mg) + { + SendSysMessage("Empty"); + continue; + } + switch(mg->GetMovementGeneratorType()) + { + case IDLE_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_IDLE); break; + case RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_RANDOM); break; + case WAYPOINT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_WAYPOINT); break; + case ANIMAL_RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_ANIMAL_RANDOM); break; + case CONFUSED_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_CONFUSED); break; + case TARGETED_MOTION_TYPE: + { + if (unit->GetTypeId() == TYPEID_PLAYER) + { + TargetedMovementGenerator const* mgen = static_cast const*>(mg); + Unit* target = mgen->GetTarget(); + if (target) + PSendSysMessage(LANG_MOVEGENS_TARGETED_PLAYER,target->GetName(),target->GetGUIDLow()); + else + SendSysMessage(LANG_MOVEGENS_TARGETED_NULL); + } + else + { + TargetedMovementGenerator const* mgen = static_cast const*>(mg); + Unit* target = mgen->GetTarget(); + if (target) + PSendSysMessage(LANG_MOVEGENS_TARGETED_CREATURE,target->GetName(),target->GetGUIDLow()); + else + SendSysMessage(LANG_MOVEGENS_TARGETED_NULL); + } + break; + } + case HOME_MOTION_TYPE: + if (unit->GetTypeId() == TYPEID_UNIT) + { + float x,y,z; + mg->GetDestination(x,y,z); + PSendSysMessage(LANG_MOVEGENS_HOME_CREATURE,x,y,z); + } + else + SendSysMessage(LANG_MOVEGENS_HOME_PLAYER); + break; + case FLIGHT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FLIGHT); break; + case POINT_MOTION_TYPE: + { + float x,y,z; + mg->GetDestination(x,y,z); + PSendSysMessage(LANG_MOVEGENS_POINT,x,y,z); + break; + } + case FLEEING_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FEAR); break; + case DISTRACT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_DISTRACT); break; + default: + PSendSysMessage(LANG_MOVEGENS_UNKNOWN,mg->GetMovementGeneratorType()); + break; + } + } + return true; +} + +bool ChatHandler::HandleServerPLimitCommand(const char *args) +{ + if (*args) + { + char* param = strtok((char*)args, " "); + if (!param) + return false; + + int l = strlen(param); + + if (strncmp(param,"player",l) == 0) + sWorld.SetPlayerSecurityLimit(SEC_PLAYER); + else if (strncmp(param,"moderator",l) == 0) + sWorld.SetPlayerSecurityLimit(SEC_MODERATOR); + else if (strncmp(param,"gamemaster",l) == 0) + sWorld.SetPlayerSecurityLimit(SEC_GAMEMASTER); + else if (strncmp(param,"administrator",l) == 0) + sWorld.SetPlayerSecurityLimit(SEC_ADMINISTRATOR); + else if (strncmp(param,"reset",l) == 0) + sWorld.SetPlayerLimit(sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT)); + else + { + int val = atoi(param); + if (val < 0) + sWorld.SetPlayerSecurityLimit(AccountTypes(uint32(-val))); + else + sWorld.SetPlayerLimit(val); + } + + // kick all low security level players + if (sWorld.GetPlayerSecurityLimit() > SEC_PLAYER) + sWorld.KickAllLess(sWorld.GetPlayerSecurityLimit()); + } + + uint32 pLimit = sWorld.GetPlayerAmountLimit(); + AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); + char const* secName = ""; + switch(allowedAccountType) + { + case SEC_PLAYER: secName = "Player"; break; + case SEC_MODERATOR: secName = "Moderator"; break; + case SEC_GAMEMASTER: secName = "Gamemaster"; break; + case SEC_ADMINISTRATOR: secName = "Administrator"; break; + default: secName = ""; break; + } + + PSendSysMessage("Player limits: amount %u, min. security level %s.",pLimit,secName); + + return true; +} + +bool ChatHandler::HandleCastCommand(const char *args) +{ + if (!*args) + return false; + + Unit* target = getSelectedUnit(); + + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo) + { + PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SetSentErrorMessage(true); + return false; + } + + if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + char* trig_str = strtok(NULL, " "); + if (trig_str) + { + int l = strlen(trig_str); + if (strncmp(trig_str,"triggered",l) != 0) + return false; + } + + bool triggered = (trig_str != NULL); + + m_session->GetPlayer()->CastSpell(target,spell,triggered); + + return true; +} + +bool ChatHandler::HandleCastBackCommand(const char *args) +{ + Creature* caster = getSelectedCreature(); + + if (!caster) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell || !sSpellStore.LookupEntry(spell)) + { + PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SetSentErrorMessage(true); + return false; + } + + char* trig_str = strtok(NULL, " "); + if (trig_str) + { + int l = strlen(trig_str); + if (strncmp(trig_str,"triggered",l) != 0) + return false; + } + + bool triggered = (trig_str != NULL); + + caster->SetFacingToObject(m_session->GetPlayer()); + + caster->CastSpell(m_session->GetPlayer(),spell,triggered); + + return true; +} + +bool ChatHandler::HandleCastDistCommand(const char *args) +{ + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo) + { + PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SetSentErrorMessage(true); + return false; + } + + if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + char *distStr = strtok(NULL, " "); + + float dist = 0; + + if (distStr) + sscanf(distStr, "%f", &dist); + + char* trig_str = strtok(NULL, " "); + if (trig_str) + { + int l = strlen(trig_str); + if (strncmp(trig_str,"triggered",l) != 0) + return false; + } + + bool triggered = (trig_str != NULL); + + float x,y,z; + m_session->GetPlayer()->GetClosePoint(x,y,z,dist); + + m_session->GetPlayer()->CastSpell(x,y,z,spell,triggered); + return true; +} + +bool ChatHandler::HandleCastTargetCommand(const char *args) +{ + Creature* caster = getSelectedCreature(); + + if (!caster) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if (!caster->getVictim()) + { + SendSysMessage(LANG_SELECTED_TARGET_NOT_HAVE_VICTIM); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell || !sSpellStore.LookupEntry(spell)) + { + PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SetSentErrorMessage(true); + return false; + } + + char* trig_str = strtok(NULL, " "); + if (trig_str) + { + int l = strlen(trig_str); + if (strncmp(trig_str,"triggered",l) != 0) + return false; + } + + bool triggered = (trig_str != NULL); + + caster->SetFacingToObject(m_session->GetPlayer()); + + caster->CastSpell(caster->getVictim(),spell,triggered); + + return true; +} + +/* +ComeToMe command REQUIRED for 3rd party scripting library to have access to PointMovementGenerator +Without this function 3rd party scripting library will get linking errors (unresolved external) +when attempting to use the PointMovementGenerator +*/ +bool ChatHandler::HandleComeToMeCommand(const char *args) +{ + char* newFlagStr = strtok((char*)args, " "); + + if (!newFlagStr) + return false; + + uint32 newFlags = (uint32)strtoul(newFlagStr, NULL, 0); + + Creature* caster = getSelectedCreature(); + if (!caster) + { + m_session->GetPlayer()->SetUnitMovementFlags(newFlags); + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + caster->SetUnitMovementFlags(newFlags); + + Player* pl = m_session->GetPlayer(); + + caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ()); + return true; +} + +bool ChatHandler::HandleCastSelfCommand(const char *args) +{ + if (!*args) + return false; + + Unit* target = getSelectedUnit(); + + if (!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spell = extractSpellIdFromLink((char*)args); + if (!spell) + return false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo) + return false; + + if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + { + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + SetSentErrorMessage(true); + return false; + } + + target->CastSpell(target,spell,false); + + return true; +} + +std::string GetTimeString(uint32 time) +{ + uint16 days = time / DAY, hours = (time % DAY) / HOUR, minute = (time % HOUR) / MINUTE; + std::ostringstream ss; + if (days) ss << days << "d "; + if (hours) ss << hours << "h "; + ss << minute << "m"; + return ss.str(); +} + +bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/) +{ + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + uint32 counter = 0; + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); + counter++; + } + } + PSendSysMessage("player binds: %d", counter); + counter = 0; + Group *group = player->GetGroup(); + if (group) + { + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Group::BoundInstancesMap &binds = group->GetBoundInstances(Difficulty(i)); + for (Group::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); counter++; + } + } + } + PSendSysMessage("group binds: %d", counter); + + return true; +} + +bool ChatHandler::HandleInstanceUnbindCommand(const char *args) +{ + if (!*args) + return false; + + std::string cmd = args; + if (cmd == "all") + { + Player* player = getSelectedPlayer(); + if (!player) player = m_session->GetPlayer(); + uint32 counter = 0; + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + if (itr->first != player->GetMapId()) + { + InstanceSave *save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); + player->UnbindInstance(itr, Difficulty(i)); + counter++; + } + else + ++itr; + } + } + PSendSysMessage("instances unbound: %d", counter); + } + return true; +} + +bool ChatHandler::HandleInstanceStatsCommand(const char* /*args*/) +{ + PSendSysMessage("instances loaded: %d", MapManager::Instance().GetNumInstances()); + PSendSysMessage("players in instances: %d", MapManager::Instance().GetNumPlayersInInstances()); + PSendSysMessage("instance saves: %d", sInstanceSaveManager.GetNumInstanceSaves()); + PSendSysMessage("players bound: %d", sInstanceSaveManager.GetNumBoundPlayersTotal()); + PSendSysMessage("groups bound: %d", sInstanceSaveManager.GetNumBoundGroupsTotal()); + return true; +} + +bool ChatHandler::HandleInstanceSaveDataCommand(const char * /*args*/) +{ + Player* pl = m_session->GetPlayer(); + + Map* map = pl->GetMap(); + if (!map->IsDungeon()) + { + PSendSysMessage("Map is not a dungeon."); + SetSentErrorMessage(true); + return false; + } + + if (!((InstanceMap*)map)->GetInstanceData()) + { + PSendSysMessage("Map has no instance data."); + SetSentErrorMessage(true); + return false; + } + + ((InstanceMap*)map)->GetInstanceData()->SaveToDB(); + return true; +} + +bool ChatHandler::HandleInstanceOpenCommand(const char *args) +{ + return HandleInstanceOpenCloseCommand(args,true); +} + +bool ChatHandler::HandleInstanceCloseCommand(const char *args) +{ + return HandleInstanceOpenCloseCommand(args,false); +} + +bool ChatHandler::HandleInstanceOpenCloseCommand(const char *args,bool open) +{ + char *mapIdStr; + char *instanceModeStr; + extractOptFirstArg((char*)args,&mapIdStr,&instanceModeStr); + if (!mapIdStr || !instanceModeStr) + return false; + + uint32 mapid = atoi(mapIdStr); + + InstanceTemplate const* instance = objmgr.GetInstanceTemplate(mapid); + if (!instance) + { + PSendSysMessage("Invalid map id"); + SetSentErrorMessage(true); + return false; + } + + uint8 status = objmgr.GetAccessRequirement(instance->access_id)->status; + uint8 flag = 0; + + if (strcmp(instanceModeStr,"normal") || strcmp(instanceModeStr,"10normal")) + flag = DUNGEON_STATUSFLAG_NORMAL; + else if (strcmp(instanceModeStr,"heroic") || strcmp(instanceModeStr,"25normal")) + flag = DUNGEON_STATUSFLAG_HEROIC; + else if (strcmp(instanceModeStr,"10heroic")) + flag = RAID_STATUSFLAG_10MAN_HEROIC; + else if (strcmp(instanceModeStr,"25heroic")) + flag = RAID_STATUSFLAG_25MAN_HEROIC; + else + { + PSendSysMessage("Unrecognized difficulty string"); + SetSentErrorMessage(true); + return false; + } + if (open) + status |= flag; + else + status &= ~flag; + + WorldDatabase.PExecute("UPDATE access_requirement SET status = '%u' WHERE id = '%u'", status, instance->access_id); + PSendSysMessage("Instance status changed. Don't forget to reload access_requirement table"); + return true; +} + +/// Display the list of GMs +bool ChatHandler::HandleGMListFullCommand(const char* /*args*/) +{ + ///- Get the accounts with GM Level >0 + QueryResult_AutoPtr result = LoginDatabase.Query("SELECT a.username,aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel > 0"); + if (result) + { + SendSysMessage(LANG_GMLIST); + SendSysMessage(" ======================== "); + SendSysMessage(LANG_GMLIST_HEADER); + SendSysMessage(" ======================== "); + + ///- Circle through them. Display username and GM level + do + { + Field *fields = result->Fetch(); + PSendSysMessage("|%15s|%6s|", fields[0].GetString(),fields[1].GetString()); + }while (result->NextRow()); + + PSendSysMessage(" ======================== "); + } + else + PSendSysMessage(LANG_GMLIST_EMPTY); + return true; +} + +/// Define the 'Message of the day' for the realm +bool ChatHandler::HandleServerSetMotdCommand(const char *args) +{ + sWorld.SetMotd(args); + PSendSysMessage(LANG_MOTD_NEW, args); + return true; +} + +/// Set whether we accept new clients +bool ChatHandler::HandleServerSetClosedCommand(const char *args) +{ + std::string arg = args; + + if (strncmp(args, "on", 3) == 0) + { + SendSysMessage(LANG_WORLD_CLOSED); + sWorld.SetClosed(true); + return true; + } + else if (strncmp(args, "off", 4) == 0) + { + SendSysMessage(LANG_WORLD_OPENED); + sWorld.SetClosed(false); + return true; + } + + SendSysMessage(LANG_USE_BOL); + SetSentErrorMessage(true); + return false; +} + +/// Set/Unset the expansion level for an account +bool ChatHandler::HandleAccountSetAddonCommand(const char *args) +{ + ///- Get the command line arguments + char *szAcc = strtok((char*)args," "); + char *szExp = strtok(NULL," "); + + if (!szAcc) + return false; + + std::string account_name; + uint32 account_id; + + if (!szExp) + { + Player* player = getSelectedPlayer(); + if (!player) + return false; + + account_id = player->GetSession()->GetAccountId(); + accmgr.GetName(account_id,account_name); + szExp = szAcc; + } + else + { + ///- Convert Account name to Upper Format + account_name = szAcc; + if (!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + account_id = accmgr.GetId(account_name); + if (!account_id) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + } + + // Let set addon state only for lesser (strong) security level + // or to self account + if (m_session && m_session->GetAccountId () != account_id && + HasLowerSecurityAccount (NULL,account_id,true)) + return false; + + int expansion = atoi(szExp); //get int anyway (0 if error) + if (expansion < 0 || expansion > sWorld.getConfig(CONFIG_EXPANSION)) + return false; + + // No SQL injection + LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",expansion,account_id); + PSendSysMessage(LANG_ACCOUNT_SETADDON,account_name.c_str(),account_id,expansion); + return true; +} + +//Send items by mail +bool ChatHandler::HandleSendItemsCommand(const char *args) +{ + // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] + Player* receiver; + uint64 receiver_guid; + std::string receiver_name; + if (!extractPlayerTarget((char*)args,&receiver,&receiver_guid,&receiver_name)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char* msgSubject = extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char* msgText = extractQuotedArg(tail2); + if (!msgText) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // extract items + typedef std::pair ItemPair; + typedef std::list< ItemPair > ItemPairs; + ItemPairs items; + + // get all tail string + char* tail = strtok(NULL, ""); + + // get from tail next item str + while (char* itemStr = strtok(tail, " ")) + { + // and get new tail + tail = strtok(NULL, ""); + + // parse item str + char* itemIdStr = strtok(itemStr, ":"); + char* itemCountStr = strtok(NULL, " "); + + uint32 item_id = atoi(itemIdStr); + if (!item_id) + return false; + + ItemPrototype const* item_proto = objmgr.GetItemPrototype(item_id); + if (!item_proto) + { + PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); + SetSentErrorMessage(true); + return false; + } + + uint32 item_count = itemCountStr ? atoi(itemCountStr) : 1; + if (item_count < 1 || (item_proto->MaxCount > 0 && item_count > uint32(item_proto->MaxCount))) + { + PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, item_count,item_id); + SetSentErrorMessage(true); + return false; + } + + while (item_count > item_proto->GetMaxStackSize()) + { + items.push_back(ItemPair(item_id,item_proto->GetMaxStackSize())); + item_count -= item_proto->GetMaxStackSize(); + } + + items.push_back(ItemPair(item_id,item_count)); + + if (items.size() > MAX_MAIL_ITEMS) + { + PSendSysMessage(LANG_COMMAND_MAIL_ITEMS_LIMIT, MAX_MAIL_ITEMS); + SetSentErrorMessage(true); + return false; + } + } + + // from console show not existed sender + MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + // fill mail + MailDraft draft(subject, text); + + for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr) + { + if (Item* item = Item::CreateItem(itr->first,itr->second,m_session ? m_session->GetPlayer() : 0)) + { + item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + draft.AddItem(item); + } + } + + draft.SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)), sender); + + std::string nameLink = playerLink(receiver_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +///Send money by mail +bool ChatHandler::HandleSendMoneyCommand(const char *args) +{ + /// format: name "subject text" "mail text" money + + Player* receiver; + uint64 receiver_guid; + std::string receiver_name; + if (!extractPlayerTarget((char*)args,&receiver,&receiver_guid,&receiver_name)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char* msgSubject = extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char* msgText = extractQuotedArg(tail2); + if (!msgText) + return false; + + char* money_str = strtok(NULL, ""); + int32 money = money_str ? atoi(money_str) : 0; + if (money <= 0) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // from console show not existed sender + MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + MailDraft(subject, text) + .AddMoney(money) + .SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)),sender); + + std::string nameLink = playerLink(receiver_name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; +} + +/// Send a message to a player in game +bool ChatHandler::HandleSendMessageCommand(const char *args) +{ + ///- Find the player + Player *rPlayer; + if (!extractPlayerTarget((char*)args, &rPlayer)) + return false; + + char* msg_str = strtok(NULL, ""); + if (!msg_str) + return false; + + ///- Check that he is not logging out. + if (rPlayer->GetSession()->isLogingOut()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + ///- Send the message + //Use SendAreaTriggerMessage for fastest delivery. + rPlayer->GetSession()->SendAreaTriggerMessage("%s", msg_str); + rPlayer->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); + + //Confirmation message + std::string nameLink = GetNameLink(rPlayer); + PSendSysMessage(LANG_SENDMESSAGE,nameLink.c_str(),msg_str); + return true; +} + +bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/) +{ + sBattleGroundMgr.DistributeArenaPoints(); + return true; +} + +bool ChatHandler::HandleModifyGenderCommand(const char *args) +{ + if (!*args) + return false; + + Player *player = getSelectedPlayer(); + + if (!player) + { + PSendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + PlayerInfo const* info = objmgr.GetPlayerInfo(player->getRace(), player->getClass()); + if (!info) + return false; + + char const* gender_str = (char*)args; + int gender_len = strlen(gender_str); + + Gender gender; + + if (!strncmp(gender_str, "male", gender_len)) // MALE + { + if (player->getGender() == GENDER_MALE) + return true; + + gender = GENDER_MALE; + } + else if (!strncmp(gender_str, "female", gender_len)) // FEMALE + { + if (player->getGender() == GENDER_FEMALE) + return true; + + gender = GENDER_FEMALE; + } + else + { + SendSysMessage(LANG_MUST_MALE_OR_FEMALE); + SetSentErrorMessage(true); + return false; + } + + // Set gender + player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); + player->SetByteValue(PLAYER_BYTES_3, 0, gender); + + // Change display ID + player->InitDisplayIds(); + + char const* gender_full = gender ? "female" : "male"; + + PSendSysMessage(LANG_YOU_CHANGE_GENDER, GetNameLink(player).c_str(), gender_full); + + if (needReportToTarget(player)) + ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetNameLink().c_str()); + + return true; +} + +bool ChatHandler::HandleChannelSetPublic(const char *args) +{ + if (!*args) + return false; + std::string channel = strtok((char*)args, " "); + uint32 val = atoi((char*)args); + + if (val) + { + CharacterDatabase.PExecute("UPDATE channels SET m_public = 1 WHERE m_name LIKE '%s'", channel.c_str()); + val = 1; + } + else + { + CharacterDatabase.PExecute("UPDATE channels SET m_public = 0 WHERE m_name LIKE '%s'", channel.c_str()); + val = 0; + } + + PSendSysMessage(LANG_CHANNEL_PUBLIC_CHANGED, channel.c_str(), val); + + return true; +} + + +/*------------------------------------------ + *-------------TRINITY---------------------- + *-------------------------------------*/ + +bool ChatHandler::HandlePlayAllCommand(const char *args) +{ + if (!*args) + return false; + + uint32 soundId = atoi((char*)args); + + if (!sSoundEntriesStore.LookupEntry(soundId)) + { + PSendSysMessage(LANG_SOUND_NOT_EXIST, soundId); + SetSentErrorMessage(true); + return false; + } + + WorldPacket data(SMSG_PLAY_SOUND, 4); + data << uint32(soundId) << m_session->GetPlayer()->GetGUID(); + sWorld.SendGlobalMessage(&data); + + PSendSysMessage(LANG_COMMAND_PLAYED_TO_ALL, soundId); + return true; +} + +bool ChatHandler::HandleFreezeCommand(const char *args) +{ + std::string name; + Player *player; + char *TargetName = strtok((char*)args, " "); //get entered name + if (!TargetName) //if no name entered use target + { + player = getSelectedPlayer(); + if (player) //prevent crash with creature as target + { + name = player->GetName(); + normalizePlayerName(name); + } + } + else // if name entered + { + name = TargetName; + normalizePlayerName(name); + player = objmgr.GetPlayer(name.c_str()); //get player by name + } + + if (!player) + { + SendSysMessage(LANG_COMMAND_FREEZE_WRONG); + return true; + } + + if (player == m_session->GetPlayer()) + { + SendSysMessage(LANG_COMMAND_FREEZE_ERROR); + return true; + } + + //effect + if (player && player != m_session->GetPlayer()) + { + PSendSysMessage(LANG_COMMAND_FREEZE,name.c_str()); + + //stop combat + make player unattackable + duel stop + stop some spells + player->setFaction(35); + player->CombatStop(); + if (player->IsNonMeleeSpellCasted(true)) + player->InterruptNonMeleeSpells(true); + player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + player->SetUInt32Value(PLAYER_DUEL_TEAM, 1); + + //if player class = hunter || warlock remove pet if alive + if ((player->getClass() == CLASS_HUNTER) || (player->getClass() == CLASS_WARLOCK)) + { + if (Pet *pet = player->GetPet()) + { + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + // not let dismiss dead pet + if (pet && pet->isAlive()) + player->RemovePet(pet,PET_SAVE_NOT_IN_SLOT); + } + } + + //m_session->GetPlayer()->CastSpell(player,spellID,false); + if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(9454)) + Aura::TryCreate(spellInfo, player, player); + + //save player + player->SaveToDB(); + } + return true; +} + +bool ChatHandler::HandleUnFreezeCommand(const char *args) +{ + std::string name; + Player *player; + char *TargetName = strtok((char*)args, " "); //get entered name + if (!TargetName) //if no name entered use target + { + player = getSelectedPlayer(); + if (player) //prevent crash with creature as target + name = player->GetName(); + } + + else // if name entered + { + name = TargetName; + normalizePlayerName(name); + player = objmgr.GetPlayer(name.c_str()); //get player by name + } + + //effect + if (player) + { + PSendSysMessage(LANG_COMMAND_UNFREEZE,name.c_str()); + + //Reset player faction + allow combat + allow duels + player->setFactionForRace(player->getRace()); + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + //allow movement and spells + player->RemoveAurasDueToSpell(9454); + + //save player + player->SaveToDB(); + } + + if (!player) + { + if (TargetName) + { + //check for offline players + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT characters.guid FROM characters WHERE characters.name = '%s'",name.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_FREEZE_WRONG); + return true; + } + //if player found: delete his freeze aura + Field *fields=result->Fetch(); + uint64 pguid = fields[0].GetUInt64(); + + CharacterDatabase.PQuery("DELETE FROM character_aura WHERE character_aura.spell = 9454 AND character_aura.guid = '%u'",pguid); + PSendSysMessage(LANG_COMMAND_UNFREEZE,name.c_str()); + return true; + } + else + { + SendSysMessage(LANG_COMMAND_FREEZE_WRONG); + return true; + } + } + + return true; +} + +bool ChatHandler::HandleListFreezeCommand(const char * /*args*/) +{ + //Get names from DB + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT characters.name FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454"); + if (!result) + { + SendSysMessage(LANG_COMMAND_NO_FROZEN_PLAYERS); + return true; + } + //Header of the names + PSendSysMessage(LANG_COMMAND_LIST_FREEZE); + + //Output of the results + do + { + Field *fields = result->Fetch(); + std::string fplayers = fields[0].GetCppString(); + PSendSysMessage(LANG_COMMAND_FROZEN_PLAYERS,fplayers.c_str()); + } while (result->NextRow()); + + return true; +} + +bool ChatHandler::HandleGroupLeaderCommand(const char *args) +{ + Player* plr = NULL; + Group* group = NULL; + uint64 guid = 0; + char* cname = strtok((char*)args, " "); + + if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid)) + if (group && group->GetLeaderGUID() != guid) + group->ChangeLeader(guid); + + return true; +} + +bool ChatHandler::HandleGroupDisbandCommand(const char *args) +{ + Player* plr = NULL; + Group* group = NULL; + uint64 guid = 0; + char* cname = strtok((char*)args, " "); + + if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid)) + if (group) + group->Disband(); + + return true; +} + +bool ChatHandler::HandleGroupRemoveCommand(const char *args) +{ + Player* plr = NULL; + Group* group = NULL; + uint64 guid = 0; + char* cname = strtok((char*)args, " "); + + if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid, true)) + if (group) + group->RemoveMember(guid, 0); + + return true; +} + +bool ChatHandler::HandlePossessCommand(const char * /*args*/) +{ + Unit *pUnit = getSelectedUnit(); + if (!pUnit) + return false; + + m_session->GetPlayer()->CastSpell(pUnit, 530, true); + return true; +} + +bool ChatHandler::HandleUnPossessCommand(const char * /*args*/) +{ + Unit *pUnit = getSelectedUnit(); + if (!pUnit) + pUnit = m_session->GetPlayer(); + + pUnit->RemoveCharmAuras(); + + return true; +} + +bool ChatHandler::HandleBindSightCommand(const char * /*args*/) +{ + Unit *pUnit = getSelectedUnit(); + if (!pUnit) + return false; + + m_session->GetPlayer()->CastSpell(pUnit, 6277, true); + return true; +} + +bool ChatHandler::HandleUnbindSightCommand(const char * /*args*/) +{ + if (m_session->GetPlayer()->isPossessing()) + return false; + + m_session->GetPlayer()->StopCastingBindSight(); + return true; +} diff --git a/src/server/game/Chat/Debugcmds.cpp b/src/server/game/Chat/Debugcmds.cpp deleted file mode 100644 index ee8c623c3d0..00000000000 --- a/src/server/game/Chat/Debugcmds.cpp +++ /dev/null @@ -1,1127 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "WorldPacket.h" -#include "Vehicle.h" -#include "Player.h" -#include "Opcodes.h" -#include "Chat.h" -#include "Log.h" -#include "Unit.h" -#include "GossipDef.h" -#include "Language.h" -#include "BattleGroundMgr.h" -#include -#include "ObjectMgr.h" -#include "Cell.h" -#include "CellImpl.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "SpellMgr.h" -#include "ScriptMgr.h" - -bool ChatHandler::HandleDebugSendSpellFailCommand(const char* args) -{ - if (!*args) - return false; - - char* px = strtok((char*)args, " "); - if (!px) - return false; - - uint8 failnum = (uint8)atoi(px); - if (failnum == 0 && *px != '0') - return false; - - char* p1 = strtok(NULL, " "); - uint8 failarg1 = p1 ? (uint8)atoi(p1) : 0; - - char* p2 = strtok(NULL, " "); - uint8 failarg2 = p2 ? (uint8)atoi(p2) : 0; - - WorldPacket data(SMSG_CAST_FAILED, 5); - data << uint8(0); - data << uint32(133); - data << uint8(failnum); - if (p1 || p2) - data << uint32(failarg1); - if (p2) - data << uint32(failarg2); - - m_session->SendPacket(&data); - - return true; -} - -bool ChatHandler::HandleDebugSendPoiCommand(const char* args) -{ - if (!*args) - return false; - - Player *pPlayer = m_session->GetPlayer(); - Unit* target = getSelectedUnit(); - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - return true; - } - - char* icon_text = strtok((char*)args, " "); - char* flags_text = strtok(NULL, " "); - if (!icon_text || !flags_text) - return false; - - uint32 icon = atol(icon_text); - uint32 flags = atol(flags_text); - - sLog.outDetail("Command : POI, NPC = %u, icon = %u flags = %u", target->GetGUIDLow(), icon,flags); - pPlayer->PlayerTalkClass->SendPointOfInterest(target->GetPositionX(), target->GetPositionY(), Poi_Icon(icon), flags, 30, "Test POI"); - return true; -} - -bool ChatHandler::HandleDebugSendEquipErrorCommand(const char* args) -{ - if (!*args) - return false; - - uint8 msg = atoi(args); - m_session->GetPlayer()->SendEquipError(msg, 0, 0); - return true; -} - -bool ChatHandler::HandleDebugSendSellErrorCommand(const char* args) -{ - if (!*args) - return false; - - uint8 msg = atoi(args); - m_session->GetPlayer()->SendSellError(msg, 0, 0, 0); - return true; -} - -bool ChatHandler::HandleDebugSendBuyErrorCommand(const char* args) -{ - if (!*args) - return false; - - uint8 msg = atoi(args); - m_session->GetPlayer()->SendBuyError(msg, 0, 0, 0); - return true; -} - -bool ChatHandler::HandleDebugSendOpcodeCommand(const char* /*args*/) -{ - Unit *unit = getSelectedUnit(); - Player *player = NULL; - if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) - player = m_session->GetPlayer(); - else - player = (Player*)unit; - if (!unit) unit = player; - - std::ifstream ifs("opcode.txt"); - if (ifs.bad()) - return false; - - uint32 opcode; - ifs >> opcode; - - WorldPacket data(opcode, 0); - - while (!ifs.eof()) - { - std::string type; - ifs >> type; - - if (type == "") - break; - - if (type == "uint8") - { - uint16 val1; - ifs >> val1; - data << uint8(val1); - } - else if (type == "uint16") - { - uint16 val2; - ifs >> val2; - data << val2; - } - else if (type == "uint32") - { - uint32 val3; - ifs >> val3; - data << val3; - } - else if (type == "uint64") - { - uint64 val4; - ifs >> val4; - data << val4; - } - else if (type == "float") - { - float val5; - ifs >> val5; - data << val5; - } - else if (type == "string") - { - std::string val6; - ifs >> val6; - data << val6; - } - else if (type == "appitsguid") - { - data.append(unit->GetPackGUID()); - } - else if (type == "appmyguid") - { - data.append(player->GetPackGUID()); - } - else if (type == "appgoguid") - { - GameObject *obj = GetNearbyGameObject(); - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, 0); - SetSentErrorMessage(true); - ifs.close(); - return false; - } - data.append(obj->GetPackGUID()); - } - else if (type == "goguid") - { - GameObject *obj = GetNearbyGameObject(); - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, 0); - SetSentErrorMessage(true); - ifs.close(); - return false; - } - data << uint64(obj->GetGUID()); - } - else if (type == "myguid") - { - data << uint64(player->GetGUID()); - } - else if (type == "itsguid") - { - data << uint64(unit->GetGUID()); - } - else if (type == "pos") - { - data << unit->GetPositionX(); - data << unit->GetPositionY(); - data << unit->GetPositionZ(); - } - else if (type == "mypos") - { - data << player->GetPositionX(); - data << player->GetPositionY(); - data << player->GetPositionZ(); - } - else - { - sLog.outDebug("Sending opcode: unknown type '%s'", type.c_str()); - break; - } - } - ifs.close(); - sLog.outDebug("Sending opcode %u", data.GetOpcode()); - data.hexlike(); - player->GetSession()->SendPacket(&data); - PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName()); - return true; -} - -bool ChatHandler::HandleDebugUpdateWorldStateCommand(const char* args) -{ - char* w = strtok((char*)args, " "); - char* s = strtok(NULL, " "); - - if (!w || !s) - return false; - - uint32 world = (uint32)atoi(w); - uint32 state = (uint32)atoi(s); - m_session->GetPlayer()->SendUpdateWorldState(world, state); - return true; -} - -bool ChatHandler::HandleDebugPlayCinematicCommand(const char* args) -{ - // USAGE: .debug play cinematic #cinematicid - // #cinematicid - ID decimal number from CinemaicSequences.dbc (1st column) - if (!*args) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - uint32 dwId = atoi((char*)args); - - if (!sCinematicSequencesStore.LookupEntry(dwId)) - { - PSendSysMessage(LANG_CINEMATIC_NOT_EXIST, dwId); - SetSentErrorMessage(true); - return false; - } - - m_session->GetPlayer()->SendCinematicStart(dwId); - return true; -} - -bool ChatHandler::HandleDebugPlayMovieCommand(const char* args) -{ - // USAGE: .debug play movie #movieid - // #movieid - ID decimal number from Movie.dbc (1st column) - if (!*args) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - uint32 dwId = atoi((char*)args); - - if (!sMovieStore.LookupEntry(dwId)) - { - PSendSysMessage(LANG_MOVIE_NOT_EXIST, dwId); - SetSentErrorMessage(true); - return false; - } - - m_session->GetPlayer()->SendMovieStart(dwId); - return true; -} - -//Play sound -bool ChatHandler::HandleDebugPlaySoundCommand(const char* args) -{ - // USAGE: .debug playsound #soundid - // #soundid - ID decimal number from SoundEntries.dbc (1st column) - if (!*args) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - uint32 dwSoundId = atoi((char*)args); - - if (!sSoundEntriesStore.LookupEntry(dwSoundId)) - { - PSendSysMessage(LANG_SOUND_NOT_EXIST, dwSoundId); - SetSentErrorMessage(true); - return false; - } - - Unit* unit = getSelectedUnit(); - if (!unit) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (m_session->GetPlayer()->GetSelection()) - unit->PlayDistanceSound(dwSoundId,m_session->GetPlayer()); - else - unit->PlayDirectSound(dwSoundId,m_session->GetPlayer()); - - PSendSysMessage(LANG_YOU_HEAR_SOUND, dwSoundId); - return true; -} - -//Send notification in channel -bool ChatHandler::HandleDebugSendChannelNotifyCommand(const char* args) -{ - if (!*args) - return false; - - const char *name = "test"; - uint8 code = atoi(args); - - WorldPacket data(SMSG_CHANNEL_NOTIFY, (1+10)); - data << code; // notify type - data << name; // channel name - data << uint32(0); - data << uint32(0); - m_session->SendPacket(&data); - return true; -} - -//Send notification in chat -bool ChatHandler::HandleDebugSendChatMsgCommand(const char* args) -{ - if (!*args) - return false; - - const char *msg = "testtest"; - uint8 type = atoi(args); - WorldPacket data; - ChatHandler::FillMessageData(&data, m_session, type, 0, "chan", m_session->GetPlayer()->GetGUID(), msg, m_session->GetPlayer()); - m_session->SendPacket(&data); - return true; -} - -bool ChatHandler::HandleDebugSendQuestPartyMsgCommand(const char* args) -{ - uint32 msg = atol((char*)args); - m_session->GetPlayer()->SendPushToPartyResponse(m_session->GetPlayer(), msg); - return true; -} - -bool ChatHandler::HandleDebugGetLootRecipientCommand(const char* /*args*/) -{ - Creature* target = getSelectedCreature(); - if (!target) - return false; - - PSendSysMessage("loot recipient: %s", target->hasLootRecipient()?(target->GetLootRecipient()?target->GetLootRecipient()->GetName():"offline"):"no loot recipient"); - return true; -} - -bool ChatHandler::HandleDebugSendQuestInvalidMsgCommand(const char* args) -{ - uint32 msg = atol((char*)args); - m_session->GetPlayer()->SendCanTakeQuestResponse(msg); - return true; -} - -bool ChatHandler::HandleDebugGetItemStateCommand(const char* args) -{ - if (!*args) - return false; - - std::string state_str = args; - - ItemUpdateState state = ITEM_UNCHANGED; - bool list_queue = false, check_all = false; - if (state_str == "unchanged") state = ITEM_UNCHANGED; - else if (state_str == "changed") state = ITEM_CHANGED; - else if (state_str == "new") state = ITEM_NEW; - else if (state_str == "removed") state = ITEM_REMOVED; - else if (state_str == "queue") list_queue = true; - else if (state_str == "check_all") check_all = true; - else return false; - - Player* player = getSelectedPlayer(); - if (!player) player = m_session->GetPlayer(); - - if (!list_queue && !check_all) - { - state_str = "The player has the following " + state_str + " items: "; - SendSysMessage(state_str.c_str()); - for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i) - { - if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) - continue; - - Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); - if (!item) continue; - if (!item->IsBag()) - { - if (item->GetState() == state) - PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID())); - } - else - { - Bag *bag = (Bag*)item; - for (uint8 j = 0; j < bag->GetBagSize(); ++j) - { - Item* item2 = bag->GetItemByPos(j); - if (item2 && item2->GetState() == state) - PSendSysMessage("bag: 255 slot: %d guid: %d owner: %d", item2->GetSlot(), item2->GetGUIDLow(), GUID_LOPART(item2->GetOwnerGUID())); - } - } - } - } - - if (list_queue) - { - std::vector &updateQueue = player->GetItemUpdateQueue(); - for (size_t i = 0; i < updateQueue.size(); ++i) - { - Item *item = updateQueue[i]; - if (!item) continue; - - Bag *container = item->GetContainer(); - uint8 bag_slot = container ? container->GetSlot() : uint8(INVENTORY_SLOT_BAG_0); - - std::string st; - switch(item->GetState()) - { - case ITEM_UNCHANGED: st = "unchanged"; break; - case ITEM_CHANGED: st = "changed"; break; - case ITEM_NEW: st = "new"; break; - case ITEM_REMOVED: st = "removed"; break; - } - - PSendSysMessage("bag: %d slot: %d guid: %d - state: %s", bag_slot, item->GetSlot(), item->GetGUIDLow(), st.c_str()); - } - if (updateQueue.empty()) - PSendSysMessage("updatequeue empty"); - } - - if (check_all) - { - bool error = false; - std::vector &updateQueue = player->GetItemUpdateQueue(); - for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i) - { - if (i >= BUYBACK_SLOT_START && i < BUYBACK_SLOT_END) - continue; - - Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); - if (!item) continue; - - if (item->GetSlot() != i) - { - PSendSysMessage("item at slot %d, guid %d has an incorrect slot value: %d", i, item->GetGUIDLow(), item->GetSlot()); - error = true; continue; - } - - if (item->GetOwnerGUID() != player->GetGUID()) - { - PSendSysMessage("for the item at slot %d and itemguid %d, owner's guid (%d) and player's guid (%d) don't match!", item->GetSlot(), item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); - error = true; continue; - } - - if (Bag *container = item->GetContainer()) - { - PSendSysMessage("item at slot: %d guid: %d has a container (slot: %d, guid: %d) but shouldnt!", item->GetSlot(), item->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); - error = true; continue; - } - - if (item->IsInUpdateQueue()) - { - uint16 qp = item->GetQueuePos(); - if (qp > updateQueue.size()) - { - PSendSysMessage("item at slot: %d guid: %d has a queuepos (%d) larger than the update queue size! ", item->GetSlot(), item->GetGUIDLow(), qp); - error = true; continue; - } - - if (updateQueue[qp] == NULL) - { - PSendSysMessage("item at slot: %d guid: %d has a queuepos (%d) that points to NULL in the queue!", item->GetSlot(), item->GetGUIDLow(), qp); - error = true; continue; - } - - if (updateQueue[qp] != item) - { - PSendSysMessage("item at slot: %d guid: %d has has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", item->GetSlot(), item->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); - error = true; continue; - } - } - else if (item->GetState() != ITEM_UNCHANGED) - { - PSendSysMessage("item at slot: %d guid: %d is not in queue but should be (state: %d)!", item->GetSlot(), item->GetGUIDLow(), item->GetState()); - error = true; continue; - } - - if (item->IsBag()) - { - Bag *bag = (Bag*)item; - for (uint8 j = 0; j < bag->GetBagSize(); ++j) - { - Item* item2 = bag->GetItemByPos(j); - if (!item2) continue; - - if (item2->GetSlot() != j) - { - PSendSysMessage("the item in bag %d slot %d, guid %d has an incorrect slot value: %d", bag->GetSlot(), j, item2->GetGUIDLow(), item2->GetSlot()); - error = true; continue; - } - - if (item2->GetOwnerGUID() != player->GetGUID()) - { - PSendSysMessage("for the item in bag %d at slot %d and itemguid %d, owner's guid (%d) and player's guid (%d) don't match!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), GUID_LOPART(item2->GetOwnerGUID()), player->GetGUIDLow()); - error = true; continue; - } - - Bag *container = item2->GetContainer(); - if (!container) - { - PSendSysMessage("the item in bag %d at slot %d with guid %d has no container!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow()); - error = true; continue; - } - - if (container != bag) - { - PSendSysMessage("the item in bag %d at slot %d with guid %d has a different container(slot %d guid %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), container->GetSlot(), container->GetGUIDLow()); - error = true; continue; - } - - if (item2->IsInUpdateQueue()) - { - uint16 qp = item2->GetQueuePos(); - if (qp > updateQueue.size()) - { - PSendSysMessage("item in bag: %d at slot: %d guid: %d has a queuepos (%d) larger than the update queue size! ", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp); - error = true; continue; - } - - if (updateQueue[qp] == NULL) - { - PSendSysMessage("item in bag: %d at slot: %d guid: %d has a queuepos (%d) that points to NULL in the queue!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp); - error = true; continue; - } - - if (updateQueue[qp] != item2) - { - PSendSysMessage("item in bag: %d at slot: %d guid: %d has has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); - error = true; continue; - } - } - else if (item2->GetState() != ITEM_UNCHANGED) - { - PSendSysMessage("item in bag: %d at slot: %d guid: %d is not in queue but should be (state: %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), item2->GetState()); - error = true; continue; - } - } - } - } - - for (size_t i = 0; i < updateQueue.size(); ++i) - { - Item *item = updateQueue[i]; - if (!item) continue; - - if (item->GetOwnerGUID() != player->GetGUID()) - { - PSendSysMessage("queue(" SIZEFMTD "): for the an item (guid %d), the owner's guid (%d) and player's guid (%d) don't match!", i, item->GetGUIDLow(), GUID_LOPART(item->GetOwnerGUID()), player->GetGUIDLow()); - error = true; continue; - } - - if (item->GetQueuePos() != i) - { - PSendSysMessage("queue(" SIZEFMTD "): for the an item (guid %d), the queuepos doesn't match it's position in the queue!", i, item->GetGUIDLow()); - error = true; continue; - } - - if (item->GetState() == ITEM_REMOVED) continue; - Item *test = player->GetItemByPos(item->GetBagSlot(), item->GetSlot()); - - if (test == NULL) - { - PSendSysMessage("queue(" SIZEFMTD "): the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the player doesn't have an item at that position!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow()); - error = true; continue; - } - - if (test != item) - { - PSendSysMessage("queue(" SIZEFMTD "): the bag(%d) and slot(%d) values for the item with guid %d are incorrect, the item with guid %d is there instead!", i, item->GetBagSlot(), item->GetSlot(), item->GetGUIDLow(), test->GetGUIDLow()); - error = true; continue; - } - } - if (!error) - SendSysMessage("All OK!"); - } - - return true; -} - -bool ChatHandler::HandleDebugBattlegroundCommand(const char * /*args*/) -{ - sBattleGroundMgr.ToggleTesting(); - return true; -} - -bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/) -{ - sBattleGroundMgr.ToggleArenaTesting(); - return true; -} - -bool ChatHandler::HandleDebugThreatList(const char * /*args*/) -{ - Creature* target = getSelectedCreature(); - if (!target || target->isTotem() || target->isPet()) - return false; - - std::list& tlist = target->getThreatManager().getThreatList(); - std::list::iterator itr; - uint32 cnt = 0; - PSendSysMessage("Threat list of %s (guid %u)",target->GetName(), target->GetGUIDLow()); - for (itr = tlist.begin(); itr != tlist.end(); ++itr) - { - Unit* unit = (*itr)->getTarget(); - if (!unit) - continue; - ++cnt; - PSendSysMessage(" %u. %s (guid %u) - threat %f",cnt,unit->GetName(), unit->GetGUIDLow(), (*itr)->getThreat()); - } - SendSysMessage("End of threat list."); - return true; -} - -bool ChatHandler::HandleDebugHostileRefList(const char * /*args*/) -{ - Unit* target = getSelectedUnit(); - if (!target) - target = m_session->GetPlayer(); - HostileReference* ref = target->getHostileRefManager().getFirst(); - uint32 cnt = 0; - PSendSysMessage("Hostil reference list of %s (guid %u)",target->GetName(), target->GetGUIDLow()); - while (ref) - { - if (Unit * unit = ref->getSource()->getOwner()) - { - ++cnt; - PSendSysMessage(" %u. %s (guid %u) - threat %f",cnt,unit->GetName(), unit->GetGUIDLow(), ref->getThreat()); - } - ref = ref->next(); - } - SendSysMessage("End of hostil reference list."); - return true; -} - -bool ChatHandler::HandleDebugSetVehicleId(const char *args) -{ - Unit* target = getSelectedUnit(); - if (!target || target->IsVehicle()) - return false; - - if (!args) - return false; - - char* i = strtok((char*)args, " "); - if (!i) - return false; - - uint32 id = (uint32)atoi(i); - //target->SetVehicleId(id); - PSendSysMessage("Vehicle id set to %u", id); - return true; -} - -bool ChatHandler::HandleDebugEnterVehicle(const char * args) -{ - Unit* target = getSelectedUnit(); - if (!target || !target->IsVehicle()) - return false; - - if (!args) - return false; - - char* i = strtok((char*)args, " "); - if (!i) - return false; - - char* j = strtok(NULL, " "); - - uint32 entry = (uint32)atoi(i); - int8 seatId = j ? (int8)atoi(j) : -1; - - if (!entry) - m_session->GetPlayer()->EnterVehicle(target, seatId); - else - { - Creature *passenger = NULL; - Trinity::AllCreaturesOfEntryInRange check(m_session->GetPlayer(), entry, 20.0f); - Trinity::CreatureSearcher searcher(m_session->GetPlayer(), passenger, check); - m_session->GetPlayer()->VisitNearbyObject(30.0f, searcher); - if (!passenger || passenger == target) - return false; - passenger->EnterVehicle(target, seatId); - } - - PSendSysMessage("Unit %u entered vehicle %d", entry, (int32)seatId); - return true; -} - -bool ChatHandler::HandleDebugSpawnVehicle(const char* args) -{ - if (!*args) - return false; - - char* e = strtok((char*)args, " "); - char* i = strtok(NULL, " "); - - if (!e) - return false; - - uint32 entry = (uint32)atoi(e); - - float x, y, z, o = m_session->GetPlayer()->GetOrientation(); - m_session->GetPlayer()->GetClosePoint(x, y, z, m_session->GetPlayer()->GetObjectSize()); - - if (!i) - return m_session->GetPlayer()->SummonCreature(entry, x, y, z, o); - - uint32 id = (uint32)atoi(i); - - CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); - - if (!ci) - return false; - - VehicleEntry const *ve = sVehicleStore.LookupEntry(id); - - if (!ve) - return false; - - Creature *v = new Creature; - - Map *map = m_session->GetPlayer()->GetMap(); - - if (!v->Create(objmgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, m_session->GetPlayer()->GetPhaseMask(), entry, id, m_session->GetPlayer()->GetTeam(), x, y, z, o)) - { - delete v; - return false; - } - - map->Add(v->ToCreature()); - - return true; -} - -bool ChatHandler::HandleDebugSendLargePacketCommand(const char* /*args*/) -{ - const char* stuffingString = "This is a dummy string to push the packet's size beyond 128000 bytes. "; - std::ostringstream ss; - while (ss.str().size() < 128000) - ss << stuffingString; - SendSysMessage(ss.str().c_str()); - return true; -} - -bool ChatHandler::HandleDebugSendSetPhaseShiftCommand(const char* args) -{ - if (!*args) - return false; - - uint32 PhaseShift = atoi(args); - m_session->SendSetPhaseShift(PhaseShift); - return true; -} - -bool ChatHandler::HandleDebugGetItemValueCommand(const char* args) -{ - if (!*args) - return false; - - char* e = strtok((char*)args, " "); - char* f = strtok(NULL, " "); - - if (!e || !f) - return false; - - uint32 guid = (uint32)atoi(e); - uint32 index = (uint32)atoi(f); - - Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); - - if (!i) - return false; - - if (index >= i->GetValuesCount()) - return false; - - uint32 value = i->GetUInt32Value(index); - - PSendSysMessage("Item %u: value at %u is %u", guid, index, value); - - return true; -} - -bool ChatHandler::HandleDebugSetItemValueCommand(const char* args) -{ - if (!*args) - return false; - - char* e = strtok((char*)args, " "); - char* f = strtok(NULL, " "); - char* g = strtok(NULL, " "); - - if (!e || !f || !g) - return false; - - uint32 guid = (uint32)atoi(e); - uint32 index = (uint32)atoi(f); - uint32 value = (uint32)atoi(g); - - Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); - - if (!i) - return false; - - if (index >= i->GetValuesCount()) - return false; - - i->SetUInt32Value(index, value); - - return true; -} - -bool ChatHandler::HandleDebugItemExpireCommand(const char* args) -{ - if (!*args) - return false; - - char* e = strtok((char*)args, " "); - if (!e) - return false; - - uint32 guid = (uint32)atoi(e); - - Item *i = m_session->GetPlayer()->GetItemByGuid(MAKE_NEW_GUID(guid, 0, HIGHGUID_ITEM)); - - if (!i) - return false; - - m_session->GetPlayer()->DestroyItem(i->GetBagSlot(),i->GetSlot(), true); - sScriptMgr.ItemExpire(m_session->GetPlayer(),i->GetProto()); - - return true; -} - -//show animation -bool ChatHandler::HandleDebugAnimCommand(const char* args) -{ - if (!*args) - return false; - - uint32 anim_id = atoi((char*)args); - m_session->GetPlayer()->HandleEmoteCommand(anim_id); - return true; -} - -bool ChatHandler::HandleDebugSetAuraStateCommand(const char* args) -{ - if (!*args) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Unit* unit = getSelectedUnit(); - if (!unit) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - int32 state = atoi((char*)args); - if (!state) - { - // reset all states - for (int i = 1; i <= 32; ++i) - unit->ModifyAuraState(AuraState(i),false); - return true; - } - - unit->ModifyAuraState(AuraState(abs(state)),state > 0); - return true; -} - -bool ChatHandler::HandleDebugSetValueCommand(const char* args) -{ - if (!*args) - return false; - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - char* pz = strtok(NULL, " "); - - if (!px || !py) - return false; - - WorldObject* target = getSelectedObject(); - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = target->GetGUID(); - - uint32 Opcode = (uint32)atoi(px); - if (Opcode >= target->GetValuesCount()) - { - PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); - return false; - } - uint32 iValue; - float fValue; - bool isint32 = true; - if (pz) - isint32 = (bool)atoi(pz); - if (isint32) - { - iValue = (uint32)atoi(py); - sLog.outDebug(GetTrinityString(LANG_SET_UINT), GUID_LOPART(guid), Opcode, iValue); - target->SetUInt32Value(Opcode , iValue); - PSendSysMessage(LANG_SET_UINT_FIELD, GUID_LOPART(guid), Opcode,iValue); - } - else - { - fValue = (float)atof(py); - sLog.outDebug(GetTrinityString(LANG_SET_FLOAT), GUID_LOPART(guid), Opcode, fValue); - target->SetFloatValue(Opcode , fValue); - PSendSysMessage(LANG_SET_FLOAT_FIELD, GUID_LOPART(guid), Opcode,fValue); - } - - return true; -} - -bool ChatHandler::HandleDebugGetValueCommand(const char* args) -{ - if (!*args) - return false; - - char* px = strtok((char*)args, " "); - char* pz = strtok(NULL, " "); - - if (!px) - return false; - - Unit* target = getSelectedUnit(); - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = target->GetGUID(); - - uint32 Opcode = (uint32)atoi(px); - if (Opcode >= target->GetValuesCount()) - { - PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); - return false; - } - uint32 iValue; - float fValue; - bool isint32 = true; - if (pz) - isint32 = (bool)atoi(pz); - - if (isint32) - { - iValue = target->GetUInt32Value(Opcode); - sLog.outDebug(GetTrinityString(LANG_GET_UINT), GUID_LOPART(guid), Opcode, iValue); - PSendSysMessage(LANG_GET_UINT_FIELD, GUID_LOPART(guid), Opcode, iValue); - } - else - { - fValue = target->GetFloatValue(Opcode); - sLog.outDebug(GetTrinityString(LANG_GET_FLOAT), GUID_LOPART(guid), Opcode, fValue); - PSendSysMessage(LANG_GET_FLOAT_FIELD, GUID_LOPART(guid), Opcode, fValue); - } - - return true; -} - -bool ChatHandler::HandleDebugMod32ValueCommand(const char* args) -{ - if (!*args) - return false; - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - - if (!px || !py) - return false; - - uint32 Opcode = (uint32)atoi(px); - int Value = atoi(py); - - if (Opcode >= m_session->GetPlayer()->GetValuesCount()) - { - PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, m_session->GetPlayer()->GetGUIDLow(), m_session->GetPlayer()->GetValuesCount()); - return false; - } - - sLog.outDebug(GetTrinityString(LANG_CHANGE_32BIT), Opcode, Value); - - int CurrentValue = (int)m_session->GetPlayer()->GetUInt32Value(Opcode); - - CurrentValue += Value; - m_session->GetPlayer()->SetUInt32Value(Opcode , (uint32)CurrentValue); - - PSendSysMessage(LANG_CHANGE_32BIT_FIELD, Opcode,CurrentValue); - - return true; -} - -bool ChatHandler::HandleDebugUpdateCommand(const char* args) -{ - if (!*args) - return false; - - uint32 updateIndex; - uint32 value; - - char* pUpdateIndex = strtok((char*)args, " "); - - Unit* chr = getSelectedUnit(); - if (chr == NULL) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (!pUpdateIndex) - { - return true; - } - updateIndex = atoi(pUpdateIndex); - //check updateIndex - if (chr->GetTypeId() == TYPEID_PLAYER) - { - if (updateIndex >= PLAYER_END) return true; - } - else - { - if (updateIndex >= UNIT_END) return true; - } - - char* pvalue = strtok(NULL, " "); - if (!pvalue) - { - value=chr->GetUInt32Value(updateIndex); - - PSendSysMessage(LANG_UPDATE, chr->GetGUIDLow(),updateIndex,value); - return true; - } - - value=atoi(pvalue); - - PSendSysMessage(LANG_UPDATE_CHANGE, chr->GetGUIDLow(),updateIndex,value); - - chr->SetUInt32Value(updateIndex,value); - - return true; -} diff --git a/src/server/game/Chat/Level0.cpp b/src/server/game/Chat/Level0.cpp deleted file mode 100644 index ed021ac00d4..00000000000 --- a/src/server/game/Chat/Level0.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "World.h" -#include "Player.h" -#include "Opcodes.h" -#include "Chat.h" -#include "ObjectAccessor.h" -#include "Language.h" -#include "AccountMgr.h" -#include "SystemConfig.h" -#include "revision.h" -#include "Util.h" - -bool ChatHandler::HandleHelpCommand(const char* args) -{ - char* cmd = strtok((char*)args, " "); - if (!cmd) - { - ShowHelpForCommand(getCommandTable(), "help"); - ShowHelpForCommand(getCommandTable(), ""); - } - else - { - if (!ShowHelpForCommand(getCommandTable(), cmd)) - SendSysMessage(LANG_NO_HELP_CMD); - } - - return true; -} - -bool ChatHandler::HandleCommandsCommand(const char* /*args*/) -{ - ShowHelpForCommand(getCommandTable(), ""); - return true; -} - -bool ChatHandler::HandleAccountCommand(const char* /*args*/) -{ - AccountTypes gmlevel = m_session->GetSecurity(); - PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmlevel)); - return true; -} - -bool ChatHandler::HandleStartCommand(const char* /*args*/) -{ - Player *chr = m_session->GetPlayer(); - - if (chr->isInFlight()) - { - SendSysMessage(LANG_YOU_IN_FLIGHT); - SetSentErrorMessage(true); - return false; - } - - if (chr->isInCombat()) - { - SendSysMessage(LANG_YOU_IN_COMBAT); - SetSentErrorMessage(true); - return false; - } - - if ((chr->isDead()) || (chr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))) - { - // if player is dead and stuck, send ghost to graveyard - chr->RepopAtGraveyard(); - return true; - } - - // cast spell Stuck - chr->CastSpell(chr,7355,false); - return true; -} - -bool ChatHandler::HandleServerInfoCommand(const char* /*args*/) -{ - uint32 PlayersNum = sWorld.GetPlayerCount(); - uint32 MaxPlayersNum = sWorld.GetMaxPlayerCount(); - uint32 activeClientsNum = sWorld.GetActiveSessionCount(); - uint32 queuedClientsNum = sWorld.GetQueuedSessionCount(); - uint32 maxActiveClientsNum = sWorld.GetMaxActiveSessionCount(); - uint32 maxQueuedClientsNum = sWorld.GetMaxQueuedSessionCount(); - std::string uptime = secsToTimeString(sWorld.GetUptime()); - uint32 updateTime = sWorld.GetUpdateTime(); - - PSendSysMessage(_FULLVERSION); - //if (m_session) - // full = _FULLVERSION(REVISION_DATE,REVISION_TIME,"|cffffffff|Hurl:" REVISION_ID "|h" REVISION_ID "|h|r"); - //else - // full = _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_ID); - - //SendSysMessage(full); - //PSendSysMessage(LANG_USING_WORLD_DB,sWorld.GetDBVersion()); - //PSendSysMessage(LANG_USING_EVENT_AI,sWorld.GetCreatureEventAIVersion()); - PSendSysMessage(LANG_CONNECTED_PLAYERS, PlayersNum, MaxPlayersNum); - PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); - PSendSysMessage(LANG_UPTIME, uptime.c_str()); - PSendSysMessage("Update time diff: %u.", updateTime); - - return true; -} - -bool ChatHandler::HandleDismountCommand(const char* /*args*/) -{ - //If player is not mounted, so go out :) - if (!m_session->GetPlayer()->IsMounted()) - { - SendSysMessage(LANG_CHAR_NON_MOUNTED); - SetSentErrorMessage(true); - return false; - } - - if (m_session->GetPlayer()->isInFlight()) - { - SendSysMessage(LANG_YOU_IN_FLIGHT); - SetSentErrorMessage(true); - return false; - } - - m_session->GetPlayer()->Unmount(); - m_session->GetPlayer()->RemoveAurasByType(SPELL_AURA_MOUNTED); - return true; -} - -bool ChatHandler::HandleSaveCommand(const char* /*args*/) -{ - Player *player=m_session->GetPlayer(); - - // save GM account without delay and output message (testing, etc) - if (m_session->GetSecurity() > SEC_PLAYER) - { - player->SaveToDB(); - SendSysMessage(LANG_PLAYER_SAVED); - return true; - } - - // save or plan save after 20 sec (logout delay) if current next save time more this value and _not_ output any messages to prevent cheat planning - uint32 save_interval = sWorld.getConfig(CONFIG_INTERVAL_SAVE); - if ((save_interval == 0 || save_interval > 20*IN_MILISECONDS && player->GetSaveTimer() <= save_interval - 20*IN_MILISECONDS)) - player->SaveToDB(); - - return true; -} - -bool ChatHandler::HandleGMListIngameCommand(const char* /*args*/) -{ - bool first = true; - - ObjectAccessor::Guard guard(*HashMapHolder::GetLock()); - HashMapHolder::MapType &m = ObjectAccessor::Instance().GetPlayers(); - for (HashMapHolder::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) - { - AccountTypes itr_sec = itr->second->GetSession()->GetSecurity(); - if ((itr->second->isGameMaster() || (itr_sec > SEC_PLAYER && itr_sec <= sWorld.getConfig(CONFIG_GM_LEVEL_IN_GM_LIST))) && - (!m_session || itr->second->IsVisibleGloballyFor(m_session->GetPlayer()))) - { - if (first) - { - SendSysMessage(LANG_GMS_ON_SRV); - first = false; - } - - SendSysMessage(GetNameLink(itr->second).c_str()); - } - } - - if (first) - SendSysMessage(LANG_GMS_NOT_LOGGED); - - return true; -} - -bool ChatHandler::HandleAccountPasswordCommand(const char* args) -{ - if (!*args) - return false; - - char *old_pass = strtok ((char*)args, " "); - char *new_pass = strtok (NULL, " "); - char *new_pass_c = strtok (NULL, " "); - - if (!old_pass || !new_pass || !new_pass_c) - return false; - - std::string password_old = old_pass; - std::string password_new = new_pass; - std::string password_new_c = new_pass_c; - - if (strcmp(new_pass, new_pass_c) != 0) - { - SendSysMessage (LANG_NEW_PASSWORDS_NOT_MATCH); - SetSentErrorMessage (true); - return false; - } - - if (!accmgr.CheckPassword (m_session->GetAccountId(), password_old)) - { - SendSysMessage (LANG_COMMAND_WRONGOLDPASSWORD); - SetSentErrorMessage (true); - return false; - } - - AccountOpResult result = accmgr.ChangePassword(m_session->GetAccountId(), password_new); - - switch(result) - { - case AOR_OK: - SendSysMessage(LANG_COMMAND_PASSWORD); - break; - case AOR_PASS_TOO_LONG: - SendSysMessage(LANG_PASSWORD_TOO_LONG); - SetSentErrorMessage(true); - return false; - case AOR_NAME_NOT_EXIST: // not possible case, don't want get account name for output - default: - SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandleAccountAddonCommand(const char* args) -{ - if (!*args) - return false; - - char *szExp = strtok((char*)args," "); - - uint32 account_id = m_session->GetAccountId(); - - int expansion=atoi(szExp); //get int anyway (0 if error) - if (expansion < 0 || expansion > sWorld.getConfig(CONFIG_EXPANSION)) - return false; - - // No SQL injection - LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'", expansion, account_id); - PSendSysMessage(LANG_ACCOUNT_ADDON, expansion); - return true; -} - -bool ChatHandler::HandleAccountLockCommand(const char* args) -{ - if (!*args) - { - SendSysMessage(LANG_USE_BOL); - return true; - } - - std::string argstr = (char*)args; - if (argstr == "on") - { - LoginDatabase.PExecute("UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId()); - PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); - return true; - } - - if (argstr == "off") - { - LoginDatabase.PExecute("UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId()); - PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); - return true; - } - - SendSysMessage(LANG_USE_BOL); - return true; -} - -/// Display the 'Message of the day' for the realm -bool ChatHandler::HandleServerMotdCommand(const char* /*args*/) -{ - PSendSysMessage(LANG_MOTD_CURRENT, sWorld.GetMotd()); - return true; -} - diff --git a/src/server/game/Chat/Level1.cpp b/src/server/game/Chat/Level1.cpp deleted file mode 100644 index 11189d519a0..00000000000 --- a/src/server/game/Chat/Level1.cpp +++ /dev/null @@ -1,2960 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "AccountMgr.h" -#include "Opcodes.h" -#include "Chat.h" -#include "Log.h" -#include "MapManager.h" -#include "ObjectAccessor.h" -#include "Language.h" -#include "CellImpl.h" -#include "InstanceSaveMgr.h" -#include "Util.h" - -#ifdef _DEBUG_VMAPS -#include "VMapFactory.h" -#endif - -//-----------------------Npc Commands----------------------- -bool ChatHandler::HandleNpcSayCommand(const char* args) -{ - if (!*args) - return false; - - Creature* pCreature = getSelectedCreature(); - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->MonsterSay(args, LANG_UNIVERSAL, 0); - - // make some emotes - char lastchar = args[strlen(args) - 1]; - switch(lastchar) - { - case '?': pCreature->HandleEmoteCommand(EMOTE_ONESHOT_QUESTION); break; - case '!': pCreature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); break; - default: pCreature->HandleEmoteCommand(EMOTE_ONESHOT_TALK); break; - } - - return true; -} - -bool ChatHandler::HandleNpcYellCommand(const char* args) -{ - if (!*args) - return false; - - Creature* pCreature = getSelectedCreature(); - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->MonsterYell(args, LANG_UNIVERSAL, 0); - - // make an emote - pCreature->HandleEmoteCommand(EMOTE_ONESHOT_SHOUT); - - return true; -} - -//show text emote by creature in chat -bool ChatHandler::HandleNpcTextEmoteCommand(const char* args) -{ - if (!*args) - return false; - - Creature* pCreature = getSelectedCreature(); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->MonsterTextEmote(args, 0); - - return true; -} - -// make npc whisper to player -bool ChatHandler::HandleNpcWhisperCommand(const char* args) -{ - if (!*args) - return false; - - char* receiver_str = strtok((char*)args, " "); - char* text = strtok(NULL, ""); - - uint64 guid = m_session->GetPlayer()->GetSelection(); - Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(guid); - - if (!pCreature || !receiver_str || !text) - { - return false; - } - - uint64 receiver_guid= atol(receiver_str); - - // check online security - if (HasLowerSecurity(objmgr.GetPlayer(receiver_guid), 0)) - return false; - - pCreature->MonsterWhisper(text,receiver_guid); - - return true; -} -//---------------------------------------------------------- - -bool ChatHandler::HandleNameAnnounceCommand(const char* args) -{ - WorldPacket data; - if (!*args) - return false; - - sWorld.SendWorldText(LANG_ANNOUNCE_COLOR, m_session->GetPlayer()->GetName(), args); - return true; -} - -bool ChatHandler::HandleGMNameAnnounceCommand(const char* args) -{ - WorldPacket data; - if (!*args) - return false; - - sWorld.SendGMText(LANG_GM_ANNOUNCE_COLOR, m_session->GetPlayer()->GetName(), args); - return true; -} - -// global announce -bool ChatHandler::HandleAnnounceCommand(const char* args) -{ - if (!*args) - return false; - - sWorld.SendWorldText(LANG_SYSTEMMESSAGE,args); - return true; -} - -// announce to logged in GMs -bool ChatHandler::HandleGMAnnounceCommand(const char* args) -{ - if (!*args) - return false; - - sWorld.SendGMText(LANG_GM_BROADCAST,args); - return true; -} - -//notification player at the screen -bool ChatHandler::HandleNotifyCommand(const char* args) -{ - if (!*args) - return false; - - std::string str = GetTrinityString(LANG_GLOBAL_NOTIFY); - str += args; - - WorldPacket data(SMSG_NOTIFICATION, (str.size()+1)); - data << str; - sWorld.SendGlobalMessage(&data); - - return true; -} - -//notification GM at the screen -bool ChatHandler::HandleGMNotifyCommand(const char* args) -{ - if (!*args) - return false; - - std::string str = GetTrinityString(LANG_GM_NOTIFY); - str += args; - - WorldPacket data(SMSG_NOTIFICATION, (str.size()+1)); - data << str; - sWorld.SendGlobalGMMessage(&data); - - return true; -} - -//Enable\Dissable GM Mode -bool ChatHandler::HandleGMCommand(const char* args) -{ - if (!*args) - { - if (m_session->GetPlayer()->isGameMaster()) - m_session->SendNotification(LANG_GM_ON); - else - m_session->SendNotification(LANG_GM_OFF); - return true; - } - - std::string argstr = (char*)args; - - if (argstr == "on") - { - m_session->GetPlayer()->SetGameMaster(true); - m_session->SendNotification(LANG_GM_ON); - m_session->GetPlayer()->UpdateTriggerVisibility(); - #ifdef _DEBUG_VMAPS - VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); - vMapManager->processCommand("stoplog"); - #endif - return true; - } - - if (argstr == "off") - { - m_session->GetPlayer()->SetGameMaster(false); - m_session->SendNotification(LANG_GM_OFF); - m_session->GetPlayer()->UpdateTriggerVisibility(); - #ifdef _DEBUG_VMAPS - VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); - vMapManager->processCommand("startlog"); - #endif - return true; - } - - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; -} - -// Enables or disables hiding of the staff badge -bool ChatHandler::HandleGMChatCommand(const char* args) -{ - if (!*args) - { - if (m_session->GetPlayer()->isGMChat()) - m_session->SendNotification(LANG_GM_CHAT_ON); - else - m_session->SendNotification(LANG_GM_CHAT_OFF); - return true; - } - - std::string argstr = (char*)args; - - if (argstr == "on") - { - m_session->GetPlayer()->SetGMChat(true); - m_session->SendNotification(LANG_GM_CHAT_ON); - return true; - } - - if (argstr == "off") - { - m_session->GetPlayer()->SetGMChat(false); - m_session->SendNotification(LANG_GM_CHAT_OFF); - return true; - } - - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; -} - -std::string ChatHandler::PGetParseString(int32 entry, ...) -{ - const char *format = GetTrinityString(entry); - va_list ap; - char str [1024]; - va_start(ap, entry); - vsnprintf(str,1024,format, ap); - va_end(ap); - return (std::string)str; -} - -bool ChatHandler::HandleGMTicketListCommand(const char* /*args*/) -{ - SendSysMessage(LANG_COMMAND_TICKETSHOWLIST); - for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) - { - if ((*itr)->closed != 0) - continue; - std::string gmname; - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); - if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) - { - ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); - } - SendSysMessage(ss.str().c_str()); - } - return true; -} - -bool ChatHandler::HandleGMTicketListOnlineCommand(const char* /*args*/) -{ - SendSysMessage(LANG_COMMAND_TICKETSHOWONLINELIST); - for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) - { - if ((*itr)->closed != 0 || !objmgr.GetPlayer((*itr)->playerGuid)) - continue; - - std::string gmname; - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); - if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) - { - ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); - } - SendSysMessage(ss.str().c_str()); - } - return true; -} - -bool ChatHandler::HandleGMTicketListClosedCommand(const char* /*args*/) -{ - SendSysMessage(LANG_COMMAND_TICKETSHOWCLOSEDLIST); - for (GmTicketList::iterator itr = objmgr.m_GMTicketList.begin(); itr != objmgr.m_GMTicketList.end(); ++itr) - { - if ((*itr)->closed == 0) - continue; - - std::string gmname; - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, (*itr)->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, (*itr)->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - (*itr)->createtime, true, false)).c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - (*itr)->timestamp, true, false)).c_str()); - if (objmgr.GetPlayerNameByGUID((*itr)->assignedToGM, gmname)) - { - ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); - } - SendSysMessage(ss.str().c_str()); - } - return true; -} - -bool ChatHandler::HandleGMTicketGetByIdCommand(const char* args) -{ - if (!*args) - return false; - - uint64 tguid = atoi(args); - GM_Ticket *ticket = objmgr.GetGMTicket(tguid); - if (!ticket || ticket->closed != 0) - { - SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); - return true; - } - - std::string gmname; - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str()); - if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) - { - ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); - } - ss << PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, ticket->message.c_str()); - if (ticket->comment != "") - { - ss << PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, ticket->comment.c_str()); - } - SendSysMessage(ss.str().c_str()); - return true; -} - -bool ChatHandler::HandleGMTicketGetByNameCommand(const char* args) -{ - if (!*args) - return false; - - std::string name = (char*)args; - normalizePlayerName(name); - - Player *plr = objmgr.GetPlayer(name.c_str()); - if (!plr) - { - SendSysMessage(LANG_NO_PLAYERS_FOUND); - return true; - } - - GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(plr->GetGUID()); - if (!ticket) - { - SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); - return true; - } - - std::string gmname; - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(time(NULL) - ticket->createtime, true, false)).c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(time(NULL) - ticket->timestamp, true, false)).c_str()); - if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) - { - ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); - } - ss << PGetParseString(LANG_COMMAND_TICKETLISTMESSAGE, ticket->message.c_str()); - if (ticket->comment != "") - { - ss << PGetParseString(LANG_COMMAND_TICKETLISTCOMMENT, ticket->comment.c_str()); - } - SendSysMessage(ss.str().c_str()); - return true; -} - -bool ChatHandler::HandleGMTicketCloseByIdCommand(const char* args) -{ - if (!*args) - return false; - - uint64 tguid = atoi(args); - GM_Ticket *ticket = objmgr.GetGMTicket(tguid); - if (!ticket || ticket->closed != 0) - { - SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); - return true; - } - if (ticket && ticket->assignedToGM != 0 && ticket->assignedToGM != m_session->GetPlayer()->GetGUID()) - { - PSendSysMessage(LANG_COMMAND_TICKETCANNOTCLOSE, ticket->guid); - return true; - } - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETCLOSED, m_session->GetPlayer()->GetName()); - SendGlobalGMSysMessage(ss.str().c_str()); - Player *plr = objmgr.GetPlayer(ticket->playerGuid); - objmgr.RemoveGMTicket(ticket, m_session->GetPlayer()->GetGUID()); - - if (!plr || !plr->IsInWorld()) - return true; - - // send abandon ticket - WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); - data << uint32(9); - plr->GetSession()->SendPacket(&data); - return true; -} - -bool ChatHandler::HandleGMTicketAssignToCommand(const char* args) -{ - if (!*args) - return false; - - char* tguid = strtok((char*)args, " "); - uint64 ticketGuid = atoi(tguid); - char* targetgm = strtok(NULL, " "); - - if (!targetgm) - return false; - - std::string targm = targetgm; - if (!normalizePlayerName(targm)) - return false; - - Player *cplr = m_session->GetPlayer(); - GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); - - if (!ticket || ticket->closed != 0) - { - SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); - return true; - } - - uint64 tarGUID = objmgr.GetPlayerGUIDByName(targm.c_str()); - uint64 accid = objmgr.GetPlayerAccountIdByGUID(tarGUID); - uint32 gmlevel = accmgr.GetSecurity(accid, realmID); - - if (!tarGUID || gmlevel == SEC_PLAYER) - { - SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); - return true; - } - - if (ticket->assignedToGM == tarGUID) - { - PSendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_B, ticket->guid); - return true; - } - - std::string gmname; - objmgr.GetPlayerNameByGUID(tarGUID, gmname); - if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID()) - { - PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid, gmname.c_str()); - return true; - } - - ticket->assignedToGM = tarGUID; - objmgr.AddOrUpdateGMTicket(*ticket); - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); - SendGlobalGMSysMessage(ss.str().c_str()); - return true; -} - -bool ChatHandler::HandleGMTicketUnAssignCommand(const char* args) -{ - if (!*args) - return false; - - uint64 ticketGuid = atoi(args); - Player *cplr = m_session->GetPlayer(); - GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); - - if (!ticket|| ticket->closed != 0) - { - SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); - return true; - } - if (ticket->assignedToGM == 0) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTASSIGNED, ticket->guid); - return true; - } - - std::string gmname; - objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname); - Player *plr = objmgr.GetPlayer(ticket->assignedToGM); - if (plr && plr->IsInWorld() && plr->GetSession()->GetSecurity() > cplr->GetSession()->GetSecurity()) - { - SendSysMessage(LANG_COMMAND_TICKETUNASSIGNSECURITY); - return true; - } - - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETLISTUNASSIGNED, cplr->GetName()); - SendGlobalGMSysMessage(ss.str().c_str()); - ticket->assignedToGM = 0; - objmgr.AddOrUpdateGMTicket(*ticket); - return true; -} - -bool ChatHandler::HandleGMTicketCommentCommand(const char* args) -{ - if (!*args) - return false; - - char* tguid = strtok((char*)args, " "); - uint64 ticketGuid = atoi(tguid); - char* comment = strtok(NULL, "\n"); - - if (!comment) - return false; - - Player *cplr = m_session->GetPlayer(); - GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); - - if (!ticket || ticket->closed != 0) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST); - return true; - } - if (ticket->assignedToGM != 0 && ticket->assignedToGM != cplr->GetGUID()) - { - PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->guid); - return true; - } - - std::string gmname; - objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname); - ticket->comment = comment; - objmgr.AddOrUpdateGMTicket(*ticket); - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); - if (objmgr.GetPlayerNameByGUID(ticket->assignedToGM, gmname)) - { - ss << PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, gmname.c_str()); - } - ss << PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, cplr->GetName(), ticket->comment.c_str()); - SendGlobalGMSysMessage(ss.str().c_str()); - return true; -} - -bool ChatHandler::HandleGMTicketDeleteByIdCommand(const char* args) -{ - if (!*args) - return false; - uint64 ticketGuid = atoi(args); - GM_Ticket *ticket = objmgr.GetGMTicket(ticketGuid); - - if (!ticket) - { - SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); - return true; - } - if (ticket->closed == 0) - { - SendSysMessage(LANG_COMMAND_TICKETCLOSEFIRST); - return true; - } - - std::stringstream ss; - ss << PGetParseString(LANG_COMMAND_TICKETLISTGUID, ticket->guid); - ss << PGetParseString(LANG_COMMAND_TICKETLISTNAME, ticket->name.c_str()); - ss << PGetParseString(LANG_COMMAND_TICKETDELETED, m_session->GetPlayer()->GetName()); - SendGlobalGMSysMessage(ss.str().c_str()); - Player *plr = objmgr.GetPlayer(ticket->playerGuid); - objmgr.RemoveGMTicket(ticket, -1, true); - if (plr && plr->IsInWorld()) - { - // Force abandon ticket - WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); - data << uint32(9); - plr->GetSession()->SendPacket(&data); - } - - ticket = NULL; - return true; -} - -bool ChatHandler::HandleGMTicketReloadCommand(const char*) -{ - objmgr.LoadGMTickets(); - return true; -} - -//Enable\Dissable Invisible mode -bool ChatHandler::HandleGMVisibleCommand(const char* args) -{ - if (!*args) - { - PSendSysMessage(LANG_YOU_ARE, m_session->GetPlayer()->isGMVisible() ? GetTrinityString(LANG_VISIBLE) : GetTrinityString(LANG_INVISIBLE)); - return true; - } - - std::string argstr = (char*)args; - - if (argstr == "on") - { - m_session->GetPlayer()->SetGMVisible(true); - m_session->SendNotification(LANG_INVISIBLE_VISIBLE); - return true; - } - - if (argstr == "off") - { - m_session->SendNotification(LANG_INVISIBLE_INVISIBLE); - m_session->GetPlayer()->SetGMVisible(false); - return true; - } - - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; -} - -bool ChatHandler::HandleGPSCommand(const char* args) -{ - WorldObject *obj = NULL; - if (*args) - { - uint64 guid = extractGuidFromLink((char*)args); - if (guid) - obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - - if (!obj) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - } - else - { - obj = getSelectedUnit(); - - if (!obj) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - } - CellPair cell_val = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - Cell cell(cell_val); - - uint32 zone_id, area_id; - obj->GetZoneAndAreaId(zone_id,area_id); - - MapEntry const* mapEntry = sMapStore.LookupEntry(obj->GetMapId()); - AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zone_id); - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(area_id); - - float zone_x = obj->GetPositionX(); - float zone_y = obj->GetPositionY(); - - Map2ZoneCoordinates(zone_x,zone_y,zone_id); - - Map const *map = obj->GetMap(); - float ground_z = map->GetHeight(obj->GetPositionX(), obj->GetPositionY(), MAX_HEIGHT); - float floor_z = map->GetHeight(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ()); - - GridPair p = Trinity::ComputeGridPair(obj->GetPositionX(), obj->GetPositionY()); - - int gx=63-p.x_coord; - int gy=63-p.y_coord; - - uint32 have_map = Map::ExistMap(obj->GetMapId(),gx,gy) ? 1 : 0; - uint32 have_vmap = Map::ExistVMap(obj->GetMapId(),gx,gy) ? 1 : 0; - - if(have_vmap) - { - if(map->IsOutdoors(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ())) - PSendSysMessage("You are outdoors"); - else - PSendSysMessage("You are indoor"); - } - else PSendSysMessage("no VMAP available for area info"); - - PSendSysMessage(LANG_MAP_POSITION, - obj->GetMapId(), (mapEntry ? mapEntry->name[GetSessionDbcLocale()] : ""), - zone_id, (zoneEntry ? zoneEntry->area_name[GetSessionDbcLocale()] : ""), - area_id, (areaEntry ? areaEntry->area_name[GetSessionDbcLocale()] : ""), - obj->GetPhaseMask(), - obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), - cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), - zone_x, zone_y, ground_z, floor_z, have_map, have_vmap); - - sLog.outDebug("Player %s GPS call for %s '%s' (%s: %u):", - m_session ? GetNameLink().c_str() : GetTrinityString(LANG_CONSOLE_COMMAND), - (obj->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), obj->GetName(), - (obj->GetTypeId() == TYPEID_PLAYER ? "GUID" : "Entry"), (obj->GetTypeId() == TYPEID_PLAYER ? obj->GetGUIDLow(): obj->GetEntry())); - sLog.outDebug(GetTrinityString(LANG_MAP_POSITION), - obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : ""), - zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : ""), - area_id, (areaEntry ? areaEntry->area_name[sWorld.GetDefaultDbcLocale()] : ""), - obj->GetPhaseMask(), - obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), - cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), - zone_x, zone_y, ground_z, floor_z, have_map, have_vmap); - - LiquidData liquid_status; - ZLiquidStatus res = map->getLiquidStatus(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), MAP_ALL_LIQUIDS, &liquid_status); - if (res) - { - PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.type, res); - } - return true; -} - -//Summon Player -bool ChatHandler::HandleNamegoCommand(const char* args) -{ - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - return false; - - Player* _player = m_session->GetPlayer(); - if (target == _player || target_guid == _player->GetGUID()) - { - PSendSysMessage(LANG_CANT_TELEPORT_SELF); - SetSentErrorMessage(true); - return false; - } - - if (target) - { - std::string nameLink = playerLink(target_name); - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - if (target->IsBeingTeleported()) - { - PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - Map* pMap = m_session->GetPlayer()->GetMap(); - - if (pMap->IsBattleGroundOrArena()) - { - // only allow if gm mode is on - if (!target->isGameMaster()) - { - PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,nameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - // if both players are in different bgs - else if (target->GetBattleGroundId() && m_session->GetPlayer()->GetBattleGroundId() != target->GetBattleGroundId()) - { - target->LeaveBattleground(false); // Note: should be changed so target gets no Deserter debuff - //PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,nameLink.c_str()); - //SetSentErrorMessage(true); - //return false; - } - // all's well, set bg id - // when porting out from the bg, it will be reset to 0 - target->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId(), m_session->GetPlayer()->GetBattleGroundTypeId()); - // remember current position as entry point for return at bg end teleportation - if (!target->GetMap()->IsBattleGroundOrArena()) - target->SetBattleGroundEntryPoint(); - } - else if (pMap->IsDungeon()) - { - Map* cMap = target->GetMap(); - if (cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId()) - { - target->UnbindInstance(pMap->GetInstanceId(), target->GetDungeonDifficulty(), true); - // cannot summon from instance to instance - //PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); - //SetSentErrorMessage(true); - //return false; - } - - // we are in instance, and can summon only player in our group with us as lead - if (!m_session->GetPlayer()->GetGroup() || !target->GetGroup() || - (target->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || - (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID())) - // the last check is a bit excessive, but let it be, just in case - { - PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - } - - PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),""); - if (needReportToTarget(target)) - ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(_player->GetName()).c_str()); - - // stop flight if need - if (target->isInFlight()) - { - target->GetMotionMaster()->MovementExpired(); - target->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - target->SaveRecallPosition(); - - // before GM - float x,y,z; - m_session->GetPlayer()->GetClosePoint(x,y,z,target->GetObjectSize()); - target->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,target->GetOrientation()); - target->SetPhaseMask(m_session->GetPlayer()->GetPhaseMask(), true); - } - else - { - // check offline security - if (HasLowerSecurity(NULL, target_guid)) - return false; - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),GetTrinityString(LANG_OFFLINE)); - - // in point where GM stay - Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(), - m_session->GetPlayer()->GetPositionX(), - m_session->GetPlayer()->GetPositionY(), - m_session->GetPlayer()->GetPositionZ(), - m_session->GetPlayer()->GetOrientation(), - m_session->GetPlayer()->GetZoneId(), - target_guid); - } - - return true; -} - -//Teleport to Player -bool ChatHandler::HandleGonameCommand(const char* args) -{ - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - return false; - - Player* _player = m_session->GetPlayer(); - if (target == _player || target_guid == _player->GetGUID()) - { - SendSysMessage(LANG_CANT_TELEPORT_SELF); - SetSentErrorMessage(true); - return false; - } - - if (target) - { - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - std::string chrNameLink = playerLink(target_name); - - Map* cMap = target->GetMap(); - if (cMap->IsBattleGroundOrArena()) - { - // only allow if gm mode is on - if (!_player->isGameMaster()) - { - PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - // if both players are in different bgs - else if (_player->GetBattleGroundId() && _player->GetBattleGroundId() != target->GetBattleGroundId()) - { - _player->LeaveBattleground(false); // Note: should be changed so _player gets no Deserter debuff - //PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chrNameLink.c_str()); - //SetSentErrorMessage(true); - //return false; - } - // all's well, set bg id - // when porting out from the bg, it will be reset to 0 - _player->SetBattleGroundId(target->GetBattleGroundId(), target->GetBattleGroundTypeId()); - // remember current position as entry point for return at bg end teleportation - if (!_player->GetMap()->IsBattleGroundOrArena()) - _player->SetBattleGroundEntryPoint(); - } - else if (cMap->IsDungeon()) - { - //Map* pMap = _player->GetMap(); - - // we have to go to instance, and can go to player only if: - // 1) we are in his group (either as leader or as member) - // 2) we are not bound to any group and have GM mode on - if (_player->GetGroup()) - { - // we are in group, we can go only if we are in the player group - if (_player->GetGroup() != target->GetGroup()) - { - PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - } - else - { - // we are not in group, let's verify our GM mode - if (!_player->isGameMaster()) - { - PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM,chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - } - - // if the player or the player's group is bound to another instance - // the player will not be bound to another one - InstancePlayerBind *pBind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty(cMap->IsRaid())); - if (!pBind) - { - Group *group = _player->GetGroup(); - // if no bind exists, create a solo bind - InstanceGroupBind *gBind = group ? group->GetBoundInstance(target) : NULL; // if no bind exists, create a solo bind - if (!gBind) - if (InstanceSave *save = sInstanceSaveManager.GetInstanceSave(target->GetInstanceId())) - _player->BindToInstance(save, !save->CanReset()); - } - - if (cMap->IsRaid()) - _player->SetRaidDifficulty(target->GetRaidDifficulty()); - else - _player->SetDungeonDifficulty(target->GetDungeonDifficulty()); - } - - PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); - //if (needReportToTarget(target)) - // ChatHandler(target).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str()); - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - // to point to see at target with same orientation - float x,y,z; - target->GetContactPoint(_player,x,y,z); - - _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); - _player->SetPhaseMask(target->GetPhaseMask(), true); - } - else - { - // check offline security - if (HasLowerSecurity(NULL, target_guid)) - return false; - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); - - // to point where player stay (if loaded) - float x,y,z,o; - uint32 map; - bool in_flight; - if (!Player::LoadPositionFromDB(map,x,y,z,o,in_flight,target_guid)) - return false; - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(map, x, y, z,_player->GetOrientation()); - } - - return true; -} - -// Teleport player to last position -bool ChatHandler::HandleRecallCommand(const char* args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - if (target->IsBeingTeleported()) - { - PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(target).c_str()); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (target->isInFlight()) - { - target->GetMotionMaster()->MovementExpired(); - target->CleanupAfterTaxiFlight(); - } - - target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO); - return true; -} - -//Edit Player HP -bool ChatHandler::HandleModifyHPCommand(const char* args) -{ - if (!*args) - return false; - - int32 hp = atoi((char*)args); - int32 hpm = atoi((char*)args); - - if (hp < 1 || hpm < 1 || hpm < hp) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (HasLowerSecurity(chr, 0)) - return false; - - PSendSysMessage(LANG_YOU_CHANGE_HP, GetNameLink(chr).c_str(), hp, hpm); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetNameLink().c_str(), hp, hpm); - - chr->SetMaxHealth(hpm); - chr->SetHealth(hp); - - return true; -} - -//Edit Player Mana -bool ChatHandler::HandleModifyManaCommand(const char* args) -{ - if (!*args) - return false; - - // char* pmana = strtok((char*)args, " "); - // if (!pmana) - // return false; - - // char* pmanaMax = strtok(NULL, " "); - // if (!pmanaMax) - // return false; - - // int32 manam = atoi(pmanaMax); - // int32 mana = atoi(pmana); - int32 mana = atoi((char*)args); - int32 manam = atoi((char*)args); - - if (mana <= 0 || manam <= 0 || manam < mana) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - PSendSysMessage(LANG_YOU_CHANGE_MANA, GetNameLink(chr).c_str(), mana, manam); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetNameLink().c_str(), mana, manam); - - chr->SetMaxPower(POWER_MANA,manam); - chr->SetPower(POWER_MANA, mana); - - return true; -} - -//Edit Player Energy -bool ChatHandler::HandleModifyEnergyCommand(const char* args) -{ - if (!*args) - return false; - - // char* pmana = strtok((char*)args, " "); - // if (!pmana) - // return false; - - // char* pmanaMax = strtok(NULL, " "); - // if (!pmanaMax) - // return false; - - // int32 manam = atoi(pmanaMax); - // int32 mana = atoi(pmana); - - int32 energy = atoi((char*)args)*10; - int32 energym = atoi((char*)args)*10; - - if (energy <= 0 || energym <= 0 || energym < energy) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (!chr) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - PSendSysMessage(LANG_YOU_CHANGE_ENERGY, GetNameLink(chr).c_str(), energy/10, energym/10); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetNameLink().c_str(), energy/10, energym/10); - - chr->SetMaxPower(POWER_ENERGY,energym); - chr->SetPower(POWER_ENERGY, energy); - - sLog.outDetail(GetTrinityString(LANG_CURRENT_ENERGY),chr->GetMaxPower(POWER_ENERGY)); - - return true; -} - -//Edit Player Rage -bool ChatHandler::HandleModifyRageCommand(const char* args) -{ - if (!*args) - return false; - - // char* pmana = strtok((char*)args, " "); - // if (!pmana) - // return false; - - // char* pmanaMax = strtok(NULL, " "); - // if (!pmanaMax) - // return false; - - // int32 manam = atoi(pmanaMax); - // int32 mana = atoi(pmana); - - int32 rage = atoi((char*)args)*10; - int32 ragem = atoi((char*)args)*10; - - if (rage <= 0 || ragem <= 0 || ragem < rage) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - PSendSysMessage(LANG_YOU_CHANGE_RAGE, GetNameLink(chr).c_str(), rage/10, ragem/10); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetNameLink().c_str(), rage/10, ragem/10); - - chr->SetMaxPower(POWER_RAGE,ragem); - chr->SetPower(POWER_RAGE, rage); - - return true; -} - -// Edit Player Runic Power -bool ChatHandler::HandleModifyRunicPowerCommand(const char* args) -{ - if (!*args) - return false; - - int32 rune = atoi((char*)args)*10; - int32 runem = atoi((char*)args)*10; - - if (rune <= 0 || runem <= 0 || runem < rune) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_RUNIC_POWER, GetNameLink(chr).c_str(), rune/10, runem/10); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_RUNIC_POWER_CHANGED, GetNameLink().c_str(), rune/10, runem/10); - - chr->SetMaxPower(POWER_RUNIC_POWER,runem); - chr->SetPower(POWER_RUNIC_POWER, rune); - - return true; -} - -//Edit Player Faction -bool ChatHandler::HandleModifyFactionCommand(const char* args) -{ - if (!*args) - return false; - - char* pfactionid = extractKeyFromLink((char*)args,"Hfaction"); - - Creature* chr = getSelectedCreature(); - if (!chr) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (!pfactionid) - { - if (chr) - { - uint32 factionid = chr->getFaction(); - uint32 flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS); - uint32 npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS); - uint32 dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS); - PSendSysMessage(LANG_CURRENT_FACTION,chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); - } - return true; - } - - if (!chr) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - uint32 factionid = atoi(pfactionid); - uint32 flag; - - char *pflag = strtok(NULL, " "); - if (!pflag) - flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS); - else - flag = atoi(pflag); - - char* pnpcflag = strtok(NULL, " "); - - uint32 npcflag; - if (!pnpcflag) - npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS); - else - npcflag = atoi(pnpcflag); - - char* pdyflag = strtok(NULL, " "); - - uint32 dyflag; - if (!pdyflag) - dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS); - else - dyflag = atoi(pdyflag); - - if (!sFactionTemplateStore.LookupEntry(factionid)) - { - PSendSysMessage(LANG_WRONG_FACTION, factionid); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_FACTION, chr->GetGUIDLow(),factionid,flag,npcflag,dyflag); - - chr->setFaction(factionid); - chr->SetUInt32Value(UNIT_FIELD_FLAGS,flag); - chr->SetUInt32Value(UNIT_NPC_FLAGS,npcflag); - chr->SetUInt32Value(UNIT_DYNAMIC_FLAGS,dyflag); - - return true; -} - -//Edit Player Spell -bool ChatHandler::HandleModifySpellCommand(const char* args) -{ - if (!*args) return false; - char* pspellflatid = strtok((char*)args, " "); - if (!pspellflatid) - return false; - - char* pop = strtok(NULL, " "); - if (!pop) - return false; - - char* pval = strtok(NULL, " "); - if (!pval) - return false; - - uint16 mark; - - char* pmark = strtok(NULL, " "); - - uint8 spellflatid = atoi(pspellflatid); - uint8 op = atoi(pop); - uint16 val = atoi(pval); - if (!pmark) - mark = 65535; - else - mark = atoi(pmark); - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetNameLink().c_str(), spellflatid, val, mark); - - WorldPacket data(SMSG_SET_FLAT_SPELL_MODIFIER, (1+1+2+2)); - data << uint8(spellflatid); - data << uint8(op); - data << uint16(val); - data << uint16(mark); - chr->GetSession()->SendPacket(&data); - - return true; -} - -//Edit Player TP -bool ChatHandler::HandleModifyTalentCommand (const char* args) -{ - if (!*args) - return false; - - int tp = atoi((char*)args); - if (tp < 0) - return false; - - Unit* target = getSelectedUnit(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (target->GetTypeId() == TYPEID_PLAYER) - { - // check online security - if (HasLowerSecurity((Player*)target, 0)) - return false; - target->ToPlayer()->SetFreeTalentPoints(tp); - target->ToPlayer()->SendTalentsInfoData(false); - return true; - } - else if (target->ToCreature()->isPet()) - { - Unit *owner = target->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet *)target)->IsPermanentPetFor(owner->ToPlayer())) - { - // check online security - if (HasLowerSecurity((Player*)owner, 0)) - return false; - ((Pet *)target)->SetFreeTalentPoints(tp); - owner->ToPlayer()->SendTalentsInfoData(true); - return true; - } - } - - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; -} - -//Enable On\OFF all taxi paths -bool ChatHandler::HandleTaxiCheatCommand(const char* args) -{ - if (!*args) - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - std::string argstr = (char*)args; - - Player *chr = getSelectedPlayer(); - if (!chr) - { - chr=m_session->GetPlayer(); - } - - // check online security - else if (HasLowerSecurity(chr, 0)) - return false; - - if (argstr == "on") - { - chr->SetTaxiCheater(true); - PSendSysMessage(LANG_YOU_GIVE_TAXIS, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetNameLink().c_str()); - return true; - } - - if (argstr == "off") - { - chr->SetTaxiCheater(false); - PSendSysMessage(LANG_YOU_REMOVE_TAXIS, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetNameLink().c_str()); - - return true; - } - - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; -} - -//Edit Player Aspeed -bool ChatHandler::HandleModifyASpeedCommand(const char* args) -{ - if (!*args) - return false; - - float ASpeed = (float)atof((char*)args); - - if (ASpeed > 50.0f || ASpeed < 0.1f) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - std::string chrNameLink = GetNameLink(chr); - - if (chr->isInFlight()) - { - PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chrNameLink.c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetNameLink().c_str(), ASpeed); - - chr->SetSpeed(MOVE_WALK, ASpeed,true); - chr->SetSpeed(MOVE_RUN, ASpeed,true); - chr->SetSpeed(MOVE_SWIM, ASpeed,true); - //chr->SetSpeed(MOVE_TURN, ASpeed,true); - chr->SetSpeed(MOVE_FLIGHT, ASpeed,true); - return true; -} - -//Edit Player Speed -bool ChatHandler::HandleModifySpeedCommand(const char* args) -{ - if (!*args) - return false; - - float Speed = (float)atof((char*)args); - - if (Speed > 50.0f || Speed < 0.1f) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - std::string chrNameLink = GetNameLink(chr); - - if (chr->isInFlight()) - { - PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chrNameLink.c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetNameLink().c_str(), Speed); - - chr->SetSpeed(MOVE_RUN,Speed,true); - - return true; -} - -//Edit Player Swim Speed -bool ChatHandler::HandleModifySwimCommand(const char* args) -{ - if (!*args) - return false; - - float Swim = (float)atof((char*)args); - - if (Swim > 50.0f || Swim < 0.1f) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - std::string chrNameLink = GetNameLink(chr); - - if (chr->isInFlight()) - { - PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chrNameLink.c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetNameLink().c_str(), Swim); - - chr->SetSpeed(MOVE_SWIM,Swim,true); - - return true; -} - -//Edit Player Walk Speed -bool ChatHandler::HandleModifyBWalkCommand(const char* args) -{ - if (!*args) - return false; - - float BSpeed = (float)atof((char*)args); - - if (BSpeed > 50.0f || BSpeed < 0.1f) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - std::string chrNameLink = GetNameLink(chr); - - if (chr->isInFlight()) - { - PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chrNameLink.c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetNameLink().c_str(), BSpeed); - - chr->SetSpeed(MOVE_RUN_BACK,BSpeed,true); - - return true; -} - -//Edit Player Fly -bool ChatHandler::HandleModifyFlyCommand(const char* args) -{ - if (!*args) - return false; - - float FSpeed = (float)atof((char*)args); - - if (FSpeed > 50.0f || FSpeed < 0.1f) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetNameLink().c_str(), FSpeed); - - chr->SetSpeed(MOVE_FLIGHT,FSpeed,true); - - return true; -} - -//Edit Player Scale -bool ChatHandler::HandleModifyScaleCommand(const char* args) -{ - if (!*args) - return false; - - float Scale = (float)atof((char*)args); - if (Scale > 10.0f || Scale < 0.1f) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetNameLink().c_str(), Scale); - - chr->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale); - - return true; -} - -//Enable Player mount -bool ChatHandler::HandleModifyMountCommand(const char* args) -{ - if (!*args) - return false; - - uint16 mId = 1147; - float speed = (float)15; - uint32 num = 0; - - num = atoi((char*)args); - switch(num) - { - case 1: - mId=14340; - break; - case 2: - mId=4806; - break; - case 3: - mId=6471; - break; - case 4: - mId=12345; - break; - case 5: - mId=6472; - break; - case 6: - mId=6473; - break; - case 7: - mId=10670; - break; - case 8: - mId=10719; - break; - case 9: - mId=10671; - break; - case 10: - mId=10672; - break; - case 11: - mId=10720; - break; - case 12: - mId=14349; - break; - case 13: - mId=11641; - break; - case 14: - mId=12244; - break; - case 15: - mId=12242; - break; - case 16: - mId=14578; - break; - case 17: - mId=14579; - break; - case 18: - mId=14349; - break; - case 19: - mId=12245; - break; - case 20: - mId=14335; - break; - case 21: - mId=207; - break; - case 22: - mId=2328; - break; - case 23: - mId=2327; - break; - case 24: - mId=2326; - break; - case 25: - mId=14573; - break; - case 26: - mId=14574; - break; - case 27: - mId=14575; - break; - case 28: - mId=604; - break; - case 29: - mId=1166; - break; - case 30: - mId=2402; - break; - case 31: - mId=2410; - break; - case 32: - mId=2409; - break; - case 33: - mId=2408; - break; - case 34: - mId=2405; - break; - case 35: - mId=14337; - break; - case 36: - mId=6569; - break; - case 37: - mId=10661; - break; - case 38: - mId=10666; - break; - case 39: - mId=9473; - break; - case 40: - mId=9476; - break; - case 41: - mId=9474; - break; - case 42: - mId=14374; - break; - case 43: - mId=14376; - break; - case 44: - mId=14377; - break; - case 45: - mId=2404; - break; - case 46: - mId=2784; - break; - case 47: - mId=2787; - break; - case 48: - mId=2785; - break; - case 49: - mId=2736; - break; - case 50: - mId=2786; - break; - case 51: - mId=14347; - break; - case 52: - mId=14346; - break; - case 53: - mId=14576; - break; - case 54: - mId=9695; - break; - case 55: - mId=9991; - break; - case 56: - mId=6448; - break; - case 57: - mId=6444; - break; - case 58: - mId=6080; - break; - case 59: - mId=6447; - break; - case 60: - mId=4805; - break; - case 61: - mId=9714; - break; - case 62: - mId=6448; - break; - case 63: - mId=6442; - break; - case 64: - mId=14632; - break; - case 65: - mId=14332; - break; - case 66: - mId=14331; - break; - case 67: - mId=8469; - break; - case 68: - mId=2830; - break; - case 69: - mId=2346; - break; - default: - SendSysMessage(LANG_NO_MOUNT); - SetSentErrorMessage(true); - return false; - } - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - PSendSysMessage(LANG_YOU_GIVE_MOUNT, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetNameLink().c_str()); - - chr->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); - chr->Mount(mId); - - WorldPacket data(SMSG_FORCE_RUN_SPEED_CHANGE, (8+4+1+4)); - data.append(chr->GetPackGUID()); - data << (uint32)0; - data << (uint8)0; //new 2.1.0 - data << float(speed); - chr->SendMessageToSet(&data, true); - - data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, (8+4+4)); - data.append(chr->GetPackGUID()); - data << (uint32)0; - data << float(speed); - chr->SendMessageToSet(&data, true); - - return true; -} - -//Edit Player money -bool ChatHandler::HandleModifyMoneyCommand(const char* args) -{ - if (!*args) - return false; - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(chr, 0)) - return false; - - int32 addmoney = atoi((char*)args); - - uint32 moneyuser = chr->GetMoney(); - - if (addmoney < 0) - { - int32 newmoney = int32(moneyuser) + addmoney; - - sLog.outDetail(GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney); - if (newmoney <= 0) - { - PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetNameLink().c_str()); - - chr->SetMoney(0); - } - else - { - if (newmoney > MAX_MONEY_AMOUNT) - newmoney = MAX_MONEY_AMOUNT; - - PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetNameLink().c_str(), abs(addmoney)); - chr->SetMoney(newmoney); - } - } - else - { - PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetNameLink().c_str(), addmoney); - - if (addmoney >=MAX_MONEY_AMOUNT) - chr->SetMoney(MAX_MONEY_AMOUNT); - else - chr->ModifyMoney(addmoney); - } - - sLog.outDetail(GetTrinityString(LANG_NEW_MONEY), moneyuser, addmoney, chr->GetMoney()); - - return true; -} - -//Edit Unit field -bool ChatHandler::HandleModifyBitCommand(const char* args) -{ - if (!*args) - return false; - - Unit *unit = getSelectedUnit(); - if (!unit) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (unit->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity(unit->ToPlayer(), 0)) - return false; - - char* pField = strtok((char*)args, " "); - if (!pField) - return false; - - char* pBit = strtok(NULL, " "); - if (!pBit) - return false; - - uint16 field = atoi(pField); - uint32 bit = atoi(pBit); - - if (field < OBJECT_END || field >= unit->GetValuesCount()) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - if (bit < 1 || bit > 32) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - if (unit->HasFlag(field, (1<<(bit-1)))) - { - unit->RemoveFlag(field, (1<<(bit-1))); - PSendSysMessage(LANG_REMOVE_BIT, bit, field); - } - else - { - unit->SetFlag(field, (1<<(bit-1))); - PSendSysMessage(LANG_SET_BIT, bit, field); - } - return true; -} - -bool ChatHandler::HandleModifyHonorCommand (const char* args) -{ - if (!*args) - return false; - - Player *target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - int32 amount = (uint32)atoi(args); - - target->ModifyHonorPoints(amount); - - PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, GetNameLink(target).c_str(), target->GetHonorPoints()); - - return true; -} - -bool ChatHandler::HandleTeleCommand(const char * args) -{ - if (!*args) - return false; - - Player* _player = m_session->GetPlayer(); - - // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r - GameTele const* tele = extractGameTeleFromLink((char*)args); - - if (!tele) - { - SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); - SetSentErrorMessage(true); - return false; - } - - if (_player->isInCombat()) - { - SendSysMessage(LANG_YOU_IN_COMBAT); - SetSentErrorMessage(true); - return false; - } - - MapEntry const * me = sMapStore.LookupEntry(tele->mapId); - if (!me || me->IsBattleGroundOrArena()) - { - SendSysMessage(LANG_CANNOT_TELE_TO_BG); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); - return true; -} - -bool ChatHandler::HandleLookupAreaCommand(const char* args) -{ - if (!*args) - return false; - - std::string namepart = args; - std::wstring wnamepart; - - if (!Utf8toWStr (namepart,wnamepart)) - return false; - - bool found = false; - - // converting string that we try to find to lower case - wstrToLower (wnamepart); - - // Search in AreaTable.dbc - for (uint32 areaflag = 0; areaflag < sAreaStore.GetNumRows (); ++areaflag) - { - AreaTableEntry const *areaEntry = sAreaStore.LookupEntry (areaflag); - if (areaEntry) - { - int loc = GetSessionDbcLocale (); - std::string name = areaEntry->area_name[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo (name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale ()) - continue; - - name = areaEntry->area_name[loc]; - if (name.empty ()) - continue; - - if (Utf8FitTo (name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - // send area in "id - [name]" format - std::ostringstream ss; - if (m_session) - ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << " " << localeNames[loc]<< "]|h|r"; - else - ss << areaEntry->ID << " - " << name << " " << localeNames[loc]; - - SendSysMessage (ss.str ().c_str()); - - if (!found) - found = true; - } - } - } - - if (!found) - SendSysMessage (LANG_COMMAND_NOAREAFOUND); - - return true; -} - -//Find tele in game_tele order by name -bool ChatHandler::HandleLookupTeleCommand(const char * args) -{ - if (!*args) - { - SendSysMessage(LANG_COMMAND_TELE_PARAMETER); - SetSentErrorMessage(true); - return false; - } - - char const* str = strtok((char*)args, " "); - if (!str) - return false; - - std::string namepart = str; - std::wstring wnamepart; - - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wnamepart); - - std::ostringstream reply; - - GameTeleMap const & teleMap = objmgr.GetGameTeleMap(); - for (GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr) - { - GameTele const* tele = &itr->second; - - if (tele->wnameLow.find(wnamepart) == std::wstring::npos) - continue; - - if (m_session) - reply << " |cffffffff|Htele:" << itr->first << "|h[" << tele->name << "]|h|r\n"; - else - reply << " " << itr->first << " " << tele->name << "\n"; - } - - if (reply.str().empty()) - SendSysMessage(LANG_COMMAND_TELE_NOLOCATION); - else - PSendSysMessage(LANG_COMMAND_TELE_LOCATION,reply.str().c_str()); - - return true; -} - -//Enable\Dissable accept whispers (for GM) -bool ChatHandler::HandleWhispersCommand(const char* args) -{ - if (!*args) - { - PSendSysMessage(LANG_COMMAND_WHISPERACCEPTING, m_session->GetPlayer()->isAcceptWhispers() ? GetTrinityString(LANG_ON) : GetTrinityString(LANG_OFF)); - return true; - } - - std::string argstr = (char*)args; - // whisper on - if (argstr == "on") - { - m_session->GetPlayer()->SetAcceptWhispers(true); - SendSysMessage(LANG_COMMAND_WHISPERON); - return true; - } - - // whisper off - if (argstr == "off") - { - m_session->GetPlayer()->SetAcceptWhispers(false); - SendSysMessage(LANG_COMMAND_WHISPEROFF); - return true; - } - - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; -} - -//Save all players in the world -bool ChatHandler::HandleSaveAllCommand(const char* /*args*/) -{ - ObjectAccessor::Instance().SaveAllPlayers(); - SendSysMessage(LANG_PLAYERS_SAVED); - return true; -} - -//Send mail by command -bool ChatHandler::HandleSendMailCommand(const char* args) -{ - // format: name "subject text" "mail text" - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - return false; - - char* tail1 = strtok(NULL, ""); - if (!tail1) - return false; - - char* msgSubject = extractQuotedArg(tail1); - if (!msgSubject) - return false; - - char* tail2 = strtok(NULL, ""); - if (!tail2) - return false; - - char* msgText = extractQuotedArg(tail2); - if (!msgText) - return false; - - // msgSubject, msgText isn't NUL after prev. check - std::string subject = msgSubject; - std::string text = msgText; - - // from console show not existed sender - MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - - MailDraft(subject, text) - .SendMailTo(MailReceiver(target,GUID_LOPART(target_guid)),sender); - - std::string nameLink = playerLink(target_name); - PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; -} - -// teleport player to given game_tele.entry -bool ChatHandler::HandleTeleNameCommand(const char * args) -{ - char* nameStr; - char* teleStr; - extractOptFirstArg((char*)args,&nameStr,&teleStr); - if (!teleStr) - return false; - - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) - return false; - - // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r - GameTele const* tele = extractGameTeleFromLink(teleStr); - if (!tele) - { - SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); - SetSentErrorMessage(true); - return false; - } - -/* MapEntry const * me = sMapStore.LookupEntry(tele->mapId); - if (!me || me->IsBattleGroundOrArena()) - { - SendSysMessage(LANG_CANNOT_TELE_TO_BG); - SetSentErrorMessage(true); - return false; - } - - Player *chr = objmgr.GetPlayer(name.c_str());*/ - - if (target) - { - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - std::string chrNameLink = playerLink(target_name); - - if (target->IsBeingTeleported() == true) - { - PSendSysMessage(LANG_IS_TELEPORTED, chrNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_TELEPORTING_TO, chrNameLink.c_str(),"", tele->name.c_str()); - if (needReportToTarget(target)) - ChatHandler(target).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str()); - - // stop flight if need - if (target->isInFlight()) - { - target->GetMotionMaster()->MovementExpired(); - target->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - target->SaveRecallPosition(); - - target->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation); - } - else - { - // check offline security - if (HasLowerSecurity(NULL, target_guid)) - return false; - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_TELEPORTING_TO, nameLink.c_str(), GetTrinityString(LANG_OFFLINE), tele->name.c_str()); - Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation, - MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y,tele->position_z),target_guid); - } - - return true; -} - -//Teleport group to given game_tele.entry -bool ChatHandler::HandleTeleGroupCommand(const char * args) -{ - if (!*args) - return false; - - Player *player = getSelectedPlayer(); - if (!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(player, 0)) - return false; - - // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r - GameTele const* tele = extractGameTeleFromLink((char*)args); - if (!tele) - { - SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); - SetSentErrorMessage(true); - return false; - } - - MapEntry const * me = sMapStore.LookupEntry(tele->mapId); - if (!me || me->IsBattleGroundOrArena()) - { - SendSysMessage(LANG_CANNOT_TELE_TO_BG); - SetSentErrorMessage(true); - return false; - } - - std::string nameLink = GetNameLink(player); - - Group *grp = player->GetGroup(); - if (!grp) - { - PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player *pl = itr->getSource(); - - if (!pl || !pl->GetSession()) - continue; - - // check online security - if (HasLowerSecurity(pl, 0)) - return false; - - std::string plNameLink = GetNameLink(pl); - - if (pl->IsBeingTeleported()) - { - PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); - continue; - } - - PSendSysMessage(LANG_TELEPORTING_TO, plNameLink.c_str(),"", tele->name.c_str()); - if (needReportToTarget(pl)) - ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, nameLink.c_str()); - - // stop flight if need - if (pl->isInFlight()) - { - pl->GetMotionMaster()->MovementExpired(); - pl->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - pl->SaveRecallPosition(); - - pl->TeleportTo(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); - } - - return true; -} - -//Summon group of player -bool ChatHandler::HandleGroupgoCommand(const char* args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - Group *grp = target->GetGroup(); - - std::string nameLink = GetNameLink(target); - - if (!grp) - { - PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - Map* gmMap = m_session->GetPlayer()->GetMap(); - bool to_instance = gmMap->Instanceable(); - - // we are in instance, and can summon only player in our group with us as lead - if (to_instance && ( - !m_session->GetPlayer()->GetGroup() || (grp->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || - (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()))) - // the last check is a bit excessive, but let it be, just in case - { - SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); - SetSentErrorMessage(true); - return false; - } - - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player *pl = itr->getSource(); - - if (!pl || pl == m_session->GetPlayer() || !pl->GetSession()) - continue; - - // check online security - if (HasLowerSecurity(pl, 0)) - return false; - - std::string plNameLink = GetNameLink(pl); - - if (pl->IsBeingTeleported() == true) - { - PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - if (to_instance) - { - Map* plMap = pl->GetMap(); - - if (plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId()) - { - // cannot summon from instance to instance - PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,plNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - } - - PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(),""); - if (needReportToTarget(pl)) - ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetNameLink().c_str()); - - // stop flight if need - if (pl->isInFlight()) - { - pl->GetMotionMaster()->MovementExpired(); - pl->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - pl->SaveRecallPosition(); - - // before GM - float x,y,z; - m_session->GetPlayer()->GetClosePoint(x,y,z,pl->GetObjectSize()); - pl->TeleportTo(m_session->GetPlayer()->GetMapId(),x,y,z,pl->GetOrientation()); - } - - return true; -} - -bool ChatHandler::HandleGoTaxinodeCommand(const char* args) -{ - Player* _player = m_session->GetPlayer(); - - if (!*args) - return false; - - char* cNodeId = extractKeyFromLink((char*)args,"Htaxinode"); - if (!cNodeId) - return false; - - int32 i_nodeId = atoi(cNodeId); - if (!i_nodeId) - return false; - - TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i_nodeId); - if (!node) - { - PSendSysMessage(LANG_COMMAND_GOTAXINODENOTFOUND,i_nodeId); - SetSentErrorMessage(true); - return false; - } - - if ((node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) || - !MapManager::IsValidMapCoord(node->map_id,node->x,node->y,node->z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(node->map_id, node->x, node->y, node->z, _player->GetOrientation()); - return true; -} - -//teleport at coordinates -bool ChatHandler::HandleGoXYCommand(const char* args) -{ - if (!*args) - return false; - - Player* _player = m_session->GetPlayer(); - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - char* pmapid = strtok(NULL, " "); - - if (!px || !py) - return false; - - float x = (float)atof(px); - float y = (float)atof(py); - uint32 mapid; - if (pmapid) - mapid = (uint32)atoi(pmapid); - else mapid = _player->GetMapId(); - - if (!MapManager::IsValidMapCoord(mapid,x,y)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - Map const *map = MapManager::Instance().CreateBaseMap(mapid); - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); - - _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); - - return true; -} - -//teleport at coordinates, including Z -bool ChatHandler::HandleGoXYZCommand(const char* args) -{ - if (!*args) - return false; - - Player* _player = m_session->GetPlayer(); - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - char* pz = strtok(NULL, " "); - char* pmapid = strtok(NULL, " "); - - if (!px || !py || !pz) - return false; - - float x = (float)atof(px); - float y = (float)atof(py); - float z = (float)atof(pz); - uint32 mapid; - if (pmapid) - mapid = (uint32)atoi(pmapid); - else - mapid = _player->GetMapId(); - - if (!MapManager::IsValidMapCoord(mapid,x,y,z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); - - return true; -} - -//teleport at coordinates -bool ChatHandler::HandleGoZoneXYCommand(const char* args) -{ - if (!*args) - return false; - - Player* _player = m_session->GetPlayer(); - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - char* tail = strtok(NULL,""); - - char* cAreaId = extractKeyFromLink(tail,"Harea"); // string or [name] Shift-click form |color|Harea:area_id|h[name]|h|r - - if (!px || !py) - return false; - - float x = (float)atof(px); - float y = (float)atof(py); - - // prevent accept wrong numeric args - if ((x == 0.0f && *px != '0') || (y == 0.0f && *py != '0')) - return false; - - uint32 areaid = cAreaId ? (uint32)atoi(cAreaId) : _player->GetZoneId(); - - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaid); - - if (x<0 || x>100 || y<0 || y>100 || !areaEntry) - { - PSendSysMessage(LANG_INVALID_ZONE_COORD,x,y,areaid); - SetSentErrorMessage(true); - return false; - } - - // update to parent zone if exist (client map show only zones without parents) - AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; - - Map const *map = MapManager::Instance().CreateBaseMap(zoneEntry->mapid); - - if (map->Instanceable()) - { - PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[GetSessionDbcLocale()],map->GetId(),map->GetMapName()); - SetSentErrorMessage(true); - return false; - } - - Zone2MapCoordinates(x,y,zoneEntry->ID); - - if (!MapManager::IsValidMapCoord(zoneEntry->mapid,x,y)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,zoneEntry->mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); - _player->TeleportTo(zoneEntry->mapid, x, y, z, _player->GetOrientation()); - - return true; -} - -//teleport to grid -bool ChatHandler::HandleGoGridCommand(const char* args) -{ - if (!*args) return false; - Player* _player = m_session->GetPlayer(); - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - char* pmapid = strtok(NULL, " "); - - if (!px || !py) - return false; - - float grid_x = (float)atof(px); - float grid_y = (float)atof(py); - uint32 mapid; - if (pmapid) - mapid = (uint32)atoi(pmapid); - else mapid = _player->GetMapId(); - - // center of grid - float x = (grid_x-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; - float y = (grid_y-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; - - if (!MapManager::IsValidMapCoord(mapid,x,y)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - Map const *map = MapManager::Instance().CreateBaseMap(mapid); - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); - _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); - - return true; -} - -bool ChatHandler::HandleModifyDrunkCommand(const char* args) -{ - if (!*args) return false; - - uint32 drunklevel = (uint32)atoi(args); - if (drunklevel > 100) - drunklevel = 100; - - uint16 drunkMod = drunklevel * 0xFFFF / 100; - - m_session->GetPlayer()->SetDrunkValue(drunkMod); - - return true; -} - diff --git a/src/server/game/Chat/Level2.cpp b/src/server/game/Chat/Level2.cpp deleted file mode 100644 index 4f299c932e8..00000000000 --- a/src/server/game/Chat/Level2.cpp +++ /dev/null @@ -1,4526 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "DBCStores.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "Item.h" -#include "GameObject.h" -#include "Opcodes.h" -#include "Chat.h" -#include "MapManager.h" -#include "Language.h" -#include "World.h" -#include "GameEventMgr.h" -#include "SpellMgr.h" -#include "PoolHandler.h" -#include "AccountMgr.h" -#include "WaypointManager.h" -#include "Util.h" -#include -#include -#include -#include -#include "GlobalEvents.h" -#include "OutdoorPvPMgr.h" - -#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand -#include "CreatureGroups.h" - -//mute player for some times -bool ChatHandler::HandleMuteCommand(const char* args) -{ - char* nameStr; - char* delayStr; - extractOptFirstArg((char*)args,&nameStr,&delayStr); - if (!delayStr) - return false; - - char *mutereason = strtok(NULL, "\r"); - std::string mutereasonstr = "No reason"; - if (mutereason != NULL) - mutereasonstr = mutereason; - - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) - return false; - - uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); - - // find only player from same account if any - if (!target) - if (WorldSession* session = sWorld.FindSession(account_id)) - target = session->GetPlayer(); - - uint32 notspeaktime = (uint32) atoi(delayStr); - - // must have strong lesser security level - if (HasLowerSecurity (target,target_guid,true)) - return false; - - time_t mutetime = time(NULL) + notspeaktime*60; - - if (target) - target->GetSession()->m_muteTime = mutetime; - - LoginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id); - - if (target) - ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime, mutereasonstr.c_str()); - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime, mutereasonstr.c_str()); - - return true; -} - -//unmute player -bool ChatHandler::HandleUnmuteCommand(const char* args) -{ - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - return false; - - uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); - - // find only player from same account if any - if (!target) - if (WorldSession* session = sWorld.FindSession(account_id)) - target = session->GetPlayer(); - - // must have strong lesser security level - if (HasLowerSecurity (target,target_guid,true)) - return false; - - if (target) - { - if (target->CanSpeak()) - { - SendSysMessage(LANG_CHAT_ALREADY_ENABLED); - SetSentErrorMessage(true); - return false; - } - - target->GetSession()->m_muteTime = 0; - } - - LoginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id); - - if (target) - ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str()); - return true; -} - -bool ChatHandler::HandleGoTicketCommand(const char * args) -{ - if (!*args) - return false; - - char *cstrticket_id = strtok((char*)args, " "); - - if (!cstrticket_id) - return false; - - uint64 ticket_id = atoi(cstrticket_id); - if (!ticket_id) - return false; - - GM_Ticket *ticket = objmgr.GetGMTicket(ticket_id); - if (!ticket) - { - SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); - return true; - } - - float x, y, z; - int mapid; - - x = ticket->pos_x; - y = ticket->pos_y; - z = ticket->pos_z; - mapid = ticket->map; - - Player* _player = m_session->GetPlayer(); - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - else - _player->SaveRecallPosition(); - - _player->TeleportTo(mapid, x, y, z, 1, 0); - return true; -} - -bool ChatHandler::HandleGoTriggerCommand(const char* args) -{ - Player* _player = m_session->GetPlayer(); - - if (!*args) - return false; - - char *atId = strtok((char*)args, " "); - if (!atId) - return false; - - int32 i_atId = atoi(atId); - - if (!i_atId) - return false; - - AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId); - if (!at) - { - PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId); - SetSentErrorMessage(true); - return false; - } - - if (!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation()); - return true; -} - -bool ChatHandler::HandleGoGraveyardCommand(const char* args) -{ - Player* _player = m_session->GetPlayer(); - - if (!*args) - return false; - - char *gyId = strtok((char*)args, " "); - if (!gyId) - return false; - - int32 i_gyId = atoi(gyId); - - if (!i_gyId) - return false; - - WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId); - if (!gy) - { - PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId); - SetSentErrorMessage(true); - return false; - } - - if (!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation()); - return true; -} - -/** \brief Teleport the GM to the specified creature -* -* .gocreature --> TP using creature.guid -* .gocreature azuregos --> TP player to the mob with this name -* Warning: If there is more than one mob with this name -* you will be teleported to the first one that is found. -* .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry -* Warning: If there is more than one mob with this "id" -* you will be teleported to the first one that is found. -*/ -//teleport to creature -bool ChatHandler::HandleGoCreatureCommand(const char* args) -{ - if (!*args) - return false; - Player* _player = m_session->GetPlayer(); - - // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r - char* pParam1 = extractKeyFromLink((char*)args,"Hcreature"); - if (!pParam1) - return false; - - std::ostringstream whereClause; - - // User wants to teleport to the NPC's template entry - if (strcmp(pParam1, "id") == 0) - { - //sLog.outError("DEBUG: ID found"); - - // Get the "creature_template.entry" - // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r - char* tail = strtok(NULL,""); - if (!tail) - return false; - char* cId = extractKeyFromLink(tail,"Hcreature_entry"); - if (!cId) - return false; - - int32 tEntry = atoi(cId); - //sLog.outError("DEBUG: ID value: %d", tEntry); - if (!tEntry) - return false; - - whereClause << "WHERE id = '" << tEntry << "'"; - } - else - { - //sLog.outError("DEBUG: ID *not found*"); - - int32 guid = atoi(pParam1); - - // Number is invalid - maybe the user specified the mob's name - if (!guid) - { - std::string name = pParam1; - WorldDatabase.escape_string(name); - whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'"; - } - else - { - whereClause << "WHERE guid = '" << guid << "'"; - } - } - //sLog.outError("DEBUG: %s", whereClause.c_str()); - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str()); - if (!result) - { - SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); - SetSentErrorMessage(true); - return false; - } - if (result->GetRowCount() > 1) - SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE); - - Field *fields = result->Fetch(); - float x = fields[0].GetFloat(); - float y = fields[1].GetFloat(); - float z = fields[2].GetFloat(); - float ort = fields[3].GetFloat(); - int mapid = fields[4].GetUInt16(); - - if (!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(mapid, x, y, z, ort); - return true; -} - -//teleport to gameobject -bool ChatHandler::HandleGoObjectCommand(const char* args) -{ - if (!*args) - return false; - - Player* _player = m_session->GetPlayer(); - - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if (!cId) - return false; - - int32 guid = atoi(cId); - if (!guid) - return false; - - float x, y, z, ort; - int mapid; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(guid)) - { - x = go_data->posX; - y = go_data->posY; - z = go_data->posZ; - ort = go_data->orientation; - mapid = go_data->mapid; - } - else - { - SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - if (!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(mapid, x, y, z, ort); - return true; -} - -bool ChatHandler::HandleGameObjectTargetCommand(const char* args) -{ - Player* pl = m_session->GetPlayer(); - QueryResult_AutoPtr result; - GameEventMgr::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList(); - if (*args) - { - // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); - if (!cId) - return false; - - uint32 id = atol(cId); - - if (id) - result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1", - pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id); - else - { - std::string name = cId; - WorldDatabase.escape_string(name); - result = WorldDatabase.PQuery( - "SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ " - "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1", - pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str()); - } - } - else - { - std::ostringstream eventFilter; - eventFilter << " AND (event IS NULL "; - bool initString = true; - - for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr) - { - if (initString) - { - eventFilter << "OR event IN (" <<*itr; - initString =false; - } - else - eventFilter << "," << *itr; - } - - if (!initString) - eventFilter << "))"; - else - eventFilter << ")"; - - result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, phaseMask, " - "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject " - "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10", - m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str()); - } - - if (!result) - { - SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND); - return true; - } - - bool found = false; - float x, y, z, o; - uint32 lowguid, id; - uint16 mapid, pool_id, phase; - - do - { - Field *fields = result->Fetch(); - lowguid = fields[0].GetUInt32(); - id = fields[1].GetUInt32(); - x = fields[2].GetFloat(); - y = fields[3].GetFloat(); - z = fields[4].GetFloat(); - o = fields[5].GetFloat(); - mapid = fields[6].GetUInt16(); - phase = fields[7].GetUInt16(); - pool_id = poolhandler.IsPartOfAPool(lowguid); - if (!pool_id || poolhandler.IsSpawnedObject(lowguid)) - found = true; - } while (result->NextRow() && (!found)); - - if (!found) - { - PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); - return false; - } - - GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id); - - if (!goI) - { - PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); - return false; - } - - GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT)); - - PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o, phase); - - if (target) - { - int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); - if (curRespawnDelay < 0) - curRespawnDelay = 0; - - std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true); - std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true); - - PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str()); - } - return true; -} - -//delete object by selection or guid -bool ChatHandler::HandleGameObjectDeleteCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if (!cId) - return false; - - uint32 lowguid = atoi(cId); - if (!lowguid) - return false; - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - uint64 owner_guid = obj->GetOwnerGUID(); - if (owner_guid) - { - Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid); - if (!owner || !IS_PLAYER_GUID(owner_guid)) - { - PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow()); - SetSentErrorMessage(true); - return false; - } - - owner->RemoveGameObject(obj,false); - } - - obj->SetRespawnTime(0); // not save respawn time - obj->Delete(); - obj->DeleteFromDB(); - - PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow()); - - return true; -} - -//turn selected object -bool ChatHandler::HandleGameObjectTurnCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if (!cId) - return false; - - uint32 lowguid = atoi(cId); - if (!lowguid) - return false; - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - char* po = strtok(NULL, " "); - float o; - - if (po) - { - o = (float)atof(po); - } - else - { - Player *chr = m_session->GetPlayer(); - o = chr->GetOrientation(); - } - - obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); - obj->UpdateRotationFields(); - obj->DestroyForNearbyPlayers(); - obj->UpdateObjectVisibility(); - - obj->SaveToDB(); - obj->Refresh(); - - PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow(), o); - - return true; -} - -//move selected object -bool ChatHandler::HandleGameObjectMoveCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if (!cId) - return false; - - uint32 lowguid = atoi(cId); - if (!lowguid) - return false; - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - char* px = strtok(NULL, " "); - char* py = strtok(NULL, " "); - char* pz = strtok(NULL, " "); - - if (!px) - { - Player *chr = m_session->GetPlayer(); - obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); - obj->DestroyForNearbyPlayers(); - obj->UpdateObjectVisibility(); - } - else - { - if (!py || !pz) - return false; - - float x = (float)atof(px); - float y = (float)atof(py); - float z = (float)atof(pz); - - if (!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId()); - SetSentErrorMessage(true); - return false; - } - - obj->Relocate(x, y, z, obj->GetOrientation()); - obj->DestroyForNearbyPlayers(); - obj->UpdateObjectVisibility(); - } - - obj->SaveToDB(); - obj->Refresh(); - - PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow()); - - return true; -} - -//spawn go -bool ChatHandler::HandleGameObjectAddCommand(const char* args) -{ - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); - if (!cId) - return false; - - uint32 id = atol(cId); - if (!id) - return false; - - char* spawntimeSecs = strtok(NULL, " "); - - const GameObjectInfo *gInfo = objmgr.GetGameObjectInfo(id); - - if (!gInfo) - { - PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); - SetSentErrorMessage(true); - return false; - } - - if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId)) - { - // report to DB errors log as in loading case - sLog.outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.",id, gInfo->type, gInfo->displayId); - PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA,id); - SetSentErrorMessage(true); - return false; - } - - Player *chr = m_session->GetPlayer(); - float x = float(chr->GetPositionX()); - float y = float(chr->GetPositionY()); - float z = float(chr->GetPositionZ()); - float o = float(chr->GetOrientation()); - Map *map = chr->GetMap(); - - GameObject* pGameObj = new GameObject; - uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - - if (!pGameObj->Create(db_lowGUID, gInfo->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) - { - delete pGameObj; - return false; - } - - if (spawntimeSecs) - { - uint32 value = atoi((char*)spawntimeSecs); - pGameObj->SetRespawnTime(value); - //sLog.outDebug("*** spawntimeSecs: %d", value); - } - - // fill the gameobject data and save to the db - pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn()); - - // this will generate a new guid if the object is in an instance - if (!pGameObj->LoadFromDB(db_lowGUID, map)) - { - delete pGameObj; - return false; - } - - sLog.outDebug(GetTrinityString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o); - - map->Add(pGameObj); - - // TODO: is it really necessary to add both the real and DB table guid here ? - objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID)); - - PSendSysMessage(LANG_GAMEOBJECT_ADD,id,gInfo->name,db_lowGUID,x,y,z); - return true; -} - -//set pahsemask for selected object -bool ChatHandler::HandleGameObjectPhaseCommand(const char* args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if (!cId) - return false; - - uint32 lowguid = atoi(cId); - if (!lowguid) - return false; - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - char* phaseStr = strtok (NULL, " "); - uint32 phasemask = phaseStr? atoi(phaseStr) : 0; - if (phasemask == 0) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - obj->SetPhaseMask(phasemask,true); - obj->SaveToDB(); - return true; -} - -bool ChatHandler::HandleGameObjectNearCommand(const char* args) -{ - float distance = (!*args) ? 10 : atol(args); - uint32 count = 0; - - Player* pl = m_session->GetPlayer(); - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, map, " - "(POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ " - "FROM gameobject WHERE map='%u' AND (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) <= '%f' ORDER BY order_", - pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), - pl->GetMapId(),pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),distance*distance); - - if (result) - { - do - { - Field *fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - uint32 entry = fields[1].GetUInt32(); - float x = fields[2].GetFloat(); - float y = fields[3].GetFloat(); - float z = fields[4].GetFloat(); - int mapid = fields[5].GetUInt16(); - - GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(entry); - - if (!gInfo) - continue; - - PSendSysMessage(LANG_GO_LIST_CHAT, guid, guid, gInfo->name, x, y, z, mapid); - - ++count; - } while (result->NextRow()); - } - - PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE,distance,count); - return true; -} - -bool ChatHandler::HandleGUIDCommand(const char* /*args*/) -{ - uint64 guid = m_session->GetPlayer()->GetSelection(); - - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid)); - return true; -} - -bool ChatHandler::HandleModifyRepCommand(const char * args) -{ - if (!*args) return false; - - Player* target = NULL; - target = getSelectedPlayer(); - - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - char* factionTxt = extractKeyFromLink((char*)args,"Hfaction"); - if (!factionTxt) - return false; - - uint32 factionId = atoi(factionTxt); - - int32 amount = 0; - char *rankTxt = strtok(NULL, " "); - if (!factionTxt || !rankTxt) - return false; - - amount = atoi(rankTxt); - if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0])) - { - std::string rankStr = rankTxt; - std::wstring wrankStr; - if (!Utf8toWStr(rankStr,wrankStr)) - return false; - wstrToLower(wrankStr); - - int r = 0; - amount = -42000; - for (; r < MAX_REPUTATION_RANK; ++r) - { - std::string rank = GetTrinityString(ReputationRankStrIndex[r]); - if (rank.empty()) - continue; - - std::wstring wrank; - if (!Utf8toWStr(rank,wrank)) - continue; - - wstrToLower(wrank); - - if (wrank.substr(0,wrankStr.size()) == wrankStr) - { - char *deltaTxt = strtok(NULL, " "); - if (deltaTxt) - { - int32 delta = atoi(deltaTxt); - if ((delta < 0) || (delta > ReputationMgr::PointsInRank[r] -1)) - { - PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (ReputationMgr::PointsInRank[r]-1)); - SetSentErrorMessage(true); - return false; - } - amount += delta; - } - break; - } - amount += ReputationMgr::PointsInRank[r]; - } - if (r >= MAX_REPUTATION_RANK) - { - PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt); - SetSentErrorMessage(true); - return false; - } - } - - FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId); - - if (!factionEntry) - { - PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId); - SetSentErrorMessage(true); - return false; - } - - if (factionEntry->reputationListID < 0) - { - PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[GetSessionDbcLocale()], factionId); - SetSentErrorMessage(true); - return false; - } - - target->GetReputationMgr().SetReputation(factionEntry,amount); - PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[GetSessionDbcLocale()], factionId, - GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry)); - return true; -} - -//-----------------------Npc Commands----------------------- -//add spawn of creature -bool ChatHandler::HandleNpcAddCommand(const char* args) -{ - if (!*args) - return false; - char* charID = extractKeyFromLink((char*)args,"Hcreature_entry"); - if (!charID) - return false; - - char* team = strtok(NULL, " "); - int32 teamval = 0; - if (team) { teamval = atoi(team); } - if (teamval < 0) { teamval = 0; } - - uint32 id = atoi(charID); - - Player *chr = m_session->GetPlayer(); - float x = chr->GetPositionX(); - float y = chr->GetPositionY(); - float z = chr->GetPositionZ(); - float o = chr->GetOrientation(); - Map *map = chr->GetMap(); - - Creature* pCreature = new Creature; - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o)) - { - delete pCreature; - return false; - } - - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - - uint32 db_guid = pCreature->GetDBTableGUIDLow(); - - // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - pCreature->LoadFromDB(db_guid, map); - - map->Add(pCreature); - objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid)); - return true; -} - -//add item in vendorlist -bool ChatHandler::HandleNpcAddVendorItemCommand(const char* args) -{ - if (!*args) - return false; - - char* pitem = extractKeyFromLink((char*)args,"Hitem"); - if (!pitem) - { - SendSysMessage(LANG_COMMAND_NEEDITEMSEND); - SetSentErrorMessage(true); - return false; - } - - uint32 itemId = atol(pitem); - - char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 - uint32 maxcount = 0; - if (fmaxcount) - maxcount = atol(fmaxcount); - - char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 - uint32 incrtime = 0; - if (fincrtime) - incrtime = atol(fincrtime); - - char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 - uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0; - - Creature* vendor = getSelectedCreature(); - - uint32 vendor_entry = vendor ? vendor->GetEntry() : 0; - - if (!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer())) - { - SetSentErrorMessage(true); - return false; - } - - objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost); - - ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); - - PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost); - return true; -} - -//del item from vendor list -bool ChatHandler::HandleNpcDelVendorItemCommand(const char* args) -{ - if (!*args) - return false; - - Creature* vendor = getSelectedCreature(); - if (!vendor || !vendor->isVendor()) - { - SendSysMessage(LANG_COMMAND_VENDORSELECTION); - SetSentErrorMessage(true); - return false; - } - - char* pitem = extractKeyFromLink((char*)args,"Hitem"); - if (!pitem) - { - SendSysMessage(LANG_COMMAND_NEEDITEMSEND); - SetSentErrorMessage(true); - return false; - } - uint32 itemId = atol(pitem); - - if (!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId)) - { - PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId); - SetSentErrorMessage(true); - return false; - } - - ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId); - - PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1); - return true; -} - -//add move for creature -bool ChatHandler::HandleNpcAddMoveCommand(const char* args) -{ - if (!*args) - return false; - - char* guid_str = strtok((char*)args, " "); - char* wait_str = strtok((char*)NULL, " "); - - uint32 lowguid = atoi((char*)guid_str); - - Creature* pCreature = NULL; - - /* FIXME: impossible without entry - if (lowguid) - pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); - */ - - // attempt check creature existence by DB data - if (!pCreature) - { - CreatureData const* data = objmgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - } - else - { - // obtain real GUID for DB operations - lowguid = pCreature->GetDBTableGUIDLow(); - } - - int wait = wait_str ? atoi(wait_str) : 0; - - if (wait < 0) - wait = 0; - - //Player* player = m_session->GetPlayer(); - - //WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0); - - // update movement type - WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid); - if (pCreature && pCreature->GetWaypointPath()) - { - pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); - pCreature->GetMotionMaster()->Initialize(); - if (pCreature->isAlive()) // dead creature will reset movement generator at respawn - { - pCreature->setDeathState(JUST_DIED); - pCreature->Respawn(true); - } - pCreature->SaveToDB(); - } - - SendSysMessage(LANG_WAYPOINT_ADDED); - - return true; -} - -//change level of creature or pet -bool ChatHandler::HandleNpcChangeLevelCommand(const char* args) -{ - if (!*args) - return false; - - uint8 lvl = (uint8) atoi((char*)args); - if (lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Creature* pCreature = getSelectedCreature(); - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (pCreature->isPet()) - { - if (((Pet*)pCreature)->getPetType() == HUNTER_PET) - { - pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(lvl)/4); - pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); - } - ((Pet*)pCreature)->GivePetLevel(lvl); - } - else - { - pCreature->SetMaxHealth(100 + 30*lvl); - pCreature->SetHealth(100 + 30*lvl); - pCreature->SetLevel(lvl); - pCreature->SaveToDB(); - } - - return true; -} - -//set npcflag of creature -bool ChatHandler::HandleNpcFlagCommand(const char* args) -{ - if (!*args) - return false; - - uint32 npcFlags = (uint32) atoi((char*)args); - - Creature* pCreature = getSelectedCreature(); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); - - WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry()); - - SendSysMessage(LANG_VALUE_SAVED_REJOIN); - - return true; -} - -bool ChatHandler::HandleNpcDeleteCommand(const char* args) -{ - Creature* unit = NULL; - - if (*args) - { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hcreature"); - if (!cId) - return false; - - uint32 lowguid = atoi(cId); - if (!lowguid) - return false; - - if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) - unit = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); - } - else - unit = getSelectedCreature(); - - if (!unit || unit->isPet() || unit->isTotem()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // Delete the creature - unit->CombatStop(); - unit->DeleteFromDB(); - unit->AddObjectToRemoveList(); - - SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); - - return true; -} - -//move selected creature -bool ChatHandler::HandleNpcMoveCommand(const char* args) -{ - uint32 lowguid = 0; - - Creature* pCreature = getSelectedCreature(); - - if (!pCreature) - { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hcreature"); - if (!cId) - return false; - - lowguid = atoi(cId); - - /* FIXME: impossibel without entry - if (lowguid) - pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); - */ - - // Attempting creature load from DB data - if (!pCreature) - { - CreatureData const* data = objmgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - uint32 map_id = data->mapid; - - if (m_session->GetPlayer()->GetMapId() != map_id) - { - PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); - SetSentErrorMessage(true); - return false; - } - } - else - { - lowguid = pCreature->GetDBTableGUIDLow(); - } - } - else - { - lowguid = pCreature->GetDBTableGUIDLow(); - } - - float x = m_session->GetPlayer()->GetPositionX(); - float y = m_session->GetPlayer()->GetPositionY(); - float z = m_session->GetPlayer()->GetPositionZ(); - float o = m_session->GetPlayer()->GetOrientation(); - - if (pCreature) - { - if (CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow())) - { - const_cast(data)->posX = x; - const_cast(data)->posY = y; - const_cast(data)->posZ = z; - const_cast(data)->orientation = o; - } - pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o); - pCreature->GetMotionMaster()->Initialize(); - if (pCreature->isAlive()) // dead creature will reset movement generator at respawn - { - pCreature->setDeathState(JUST_DIED); - pCreature->Respawn(); - } - } - - WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid); - PSendSysMessage(LANG_COMMAND_CREATUREMOVED); - return true; -} - -/**HandleNpcSetMoveTypeCommand - * Set the movement type for an NPC.
- *
- * Valid movement types are: - *
    - *
  • stay - NPC wont move
  • - *
  • random - NPC will move randomly according to the spawndist
  • - *
  • way - NPC will move with given waypoints set
  • - *
- * additional parameter: NODEL - so no waypoints are deleted, if you - * change the movement type - */ -bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args) -{ - if (!*args) - return false; - - // 3 arguments: - // GUID (optional - you can also select the creature) - // stay|random|way (determines the kind of movement) - // NODEL (optional - tells the system NOT to delete any waypoints) - // this is very handy if you want to do waypoints, that are - // later switched on/off according to special events (like escort - // quests, etc) - char* guid_str = strtok((char*)args, " "); - char* type_str = strtok((char*)NULL, " "); - char* dontdel_str = strtok((char*)NULL, " "); - - bool doNotDelete = false; - - if (!guid_str) - return false; - - uint32 lowguid = 0; - Creature* pCreature = NULL; - - if (dontdel_str) - { - //sLog.outError("DEBUG: All 3 params are set"); - - // All 3 params are set - // GUID - // type - // doNotDEL - if (stricmp(dontdel_str, "NODEL") == 0) - { - //sLog.outError("DEBUG: doNotDelete = true;"); - doNotDelete = true; - } - } - else - { - // Only 2 params - but maybe NODEL is set - if (type_str) - { - sLog.outError("DEBUG: Only 2 params "); - if (stricmp(type_str, "NODEL") == 0) - { - //sLog.outError("DEBUG: type_str, NODEL "); - doNotDelete = true; - type_str = NULL; - } - } - } - - if (!type_str) // case .setmovetype $move_type (with selected creature) - { - type_str = guid_str; - pCreature = getSelectedCreature(); - if (!pCreature || pCreature->isPet()) - return false; - lowguid = pCreature->GetDBTableGUIDLow(); - } - else // case .setmovetype #creature_guid $move_type (with selected creature) - { - lowguid = atoi((char*)guid_str); - - /* impossible without entry - if (lowguid) - pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT)); - */ - - // attempt check creature existence by DB data - if (!pCreature) - { - CreatureData const* data = objmgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - } - else - { - lowguid = pCreature->GetDBTableGUIDLow(); - } - } - - // now lowguid is low guid really existed creature - // and pCreature point (maybe) to this creature or NULL - - MovementGeneratorType move_type; - - std::string type = type_str; - - if (type == "stay") - move_type = IDLE_MOTION_TYPE; - else if (type == "random") - move_type = RANDOM_MOTION_TYPE; - else if (type == "way") - move_type = WAYPOINT_MOTION_TYPE; - else - return false; - - // update movement type - //if (doNotDelete == false) - // WaypointMgr.DeletePath(lowguid); - - if (pCreature) - { - // update movement type - if (doNotDelete == false) - pCreature->LoadPath(0); - - pCreature->SetDefaultMovementType(move_type); - pCreature->GetMotionMaster()->Initialize(); - if (pCreature->isAlive()) // dead creature will reset movement generator at respawn - { - pCreature->setDeathState(JUST_DIED); - pCreature->Respawn(); - } - pCreature->SaveToDB(); - } - if (doNotDelete == false) - { - PSendSysMessage(LANG_MOVE_TYPE_SET,type_str); - } - else - { - PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str); - } - - return true; -} - -//set model of creature -bool ChatHandler::HandleNpcSetModelCommand(const char* args) -{ - if (!*args) - return false; - - uint32 displayId = (uint32) atoi((char*)args); - - Creature *pCreature = getSelectedCreature(); - - if (!pCreature || pCreature->isPet()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->SetDisplayId(displayId); - pCreature->SetNativeDisplayId(displayId); - - pCreature->SaveToDB(); - - return true; -} -//set faction of creature -bool ChatHandler::HandleNpcFactionIdCommand(const char* args) -{ - if (!*args) - return false; - - uint32 factionId = (uint32) atoi((char*)args); - - if (!sFactionTemplateStore.LookupEntry(factionId)) - { - PSendSysMessage(LANG_WRONG_FACTION, factionId); - SetSentErrorMessage(true); - return false; - } - - Creature* pCreature = getSelectedCreature(); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->setFaction(factionId); - - // faction is set in creature_template - not inside creature - - // update in memory - if (CreatureInfo const *cinfo = pCreature->GetCreatureInfo()) - { - const_cast(cinfo)->faction_A = factionId; - const_cast(cinfo)->faction_H = factionId; - } - - // and DB - WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry()); - - return true; -} -//set spawn dist of creature -bool ChatHandler::HandleNpcSpawnDistCommand(const char* args) -{ - if (!*args) - return false; - - float option = atof((char*)args); - if (option < 0.0f) - { - SendSysMessage(LANG_BAD_VALUE); - return false; - } - - MovementGeneratorType mtype = IDLE_MOTION_TYPE; - if (option >0.0f) - mtype = RANDOM_MOTION_TYPE; - - Creature *pCreature = getSelectedCreature(); - uint32 u_guidlow = 0; - - if (pCreature) - u_guidlow = pCreature->GetDBTableGUIDLow(); - else - return false; - - pCreature->SetRespawnRadius((float)option); - pCreature->SetDefaultMovementType(mtype); - pCreature->GetMotionMaster()->Initialize(); - if (pCreature->isAlive()) // dead creature will reset movement generator at respawn - { - pCreature->setDeathState(JUST_DIED); - pCreature->Respawn(); - } - - WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow); - PSendSysMessage(LANG_COMMAND_SPAWNDIST,option); - return true; -} -//spawn time handling -bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args) -{ - if (!*args) - return false; - - char* stime = strtok((char*)args, " "); - - if (!stime) - return false; - - int i_stime = atoi((char*)stime); - - if (i_stime < 0) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Creature *pCreature = getSelectedCreature(); - uint32 u_guidlow = 0; - - if (pCreature) - u_guidlow = pCreature->GetDBTableGUIDLow(); - else - return false; - - WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow); - pCreature->SetRespawnDelay((uint32)i_stime); - PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime); - - return true; -} -//npc follow handling -bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/) -{ - Player *player = m_session->GetPlayer(); - Creature *creature = getSelectedCreature(); - - if (!creature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // Follow player - Using pet's default dist and angle - creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, creature->GetFollowAngle()); - - PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); - return true; -} -//npc unfollow handling -bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) -{ - Player *player = m_session->GetPlayer(); - Creature *creature = getSelectedCreature(); - - if (!creature) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (/*creature->GetMotionMaster()->empty() ||*/ - creature->GetMotionMaster()->GetCurrentMovementGeneratorType () != TARGETED_MOTION_TYPE) - { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); - SetSentErrorMessage(true); - return false; - } - - TargetedMovementGenerator const* mgen - = static_cast const*>((creature->GetMotionMaster()->top())); - - if (mgen->GetTarget() != player) - { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); - SetSentErrorMessage(true); - return false; - } - - // reset movement - creature->GetMotionMaster()->MovementExpired(true); - - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); - return true; -} -//npc tame handling -bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) -{ - Creature *creatureTarget = getSelectedCreature (); - if (!creatureTarget || creatureTarget->isPet ()) - { - PSendSysMessage (LANG_SELECT_CREATURE); - SetSentErrorMessage (true); - return false; - } - - Player *player = m_session->GetPlayer (); - - if (player->GetPetGUID ()) - { - SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); - SetSentErrorMessage (true); - return false; - } - - CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo(); - - if (!cInfo->isTameable (player->CanTameExoticPets())) - { - PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); - SetSentErrorMessage (true); - return false; - } - - // Everything looks OK, create new pet - Pet* pet = player->CreateTamedPetFrom (creatureTarget); - if (!pet) - { - PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); - SetSentErrorMessage (true); - return false; - } - - // place pet before player - float x,y,z; - player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); - pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); - - // set pet to defensive mode by default (some classes can't control controlled pets in fact). - pet->SetReactState(REACT_DEFENSIVE); - - // calculate proper level - uint8 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); - - // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); - - // add to world - pet->GetMap()->Add(pet->ToCreature()); - - // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); - - // caster have pet now - player->SetMinion(pet, true); - - pet->SavePetToDB(PET_SAVE_AS_CURRENT); - player->PetSpellInitialize(); - - return true; -} -//npc phasemask handling -//change phasemask of creature or pet -bool ChatHandler::HandleNpcSetPhaseCommand(const char* args) -{ - if (!*args) - return false; - - uint32 phasemask = (uint32) atoi((char*)args); - if (phasemask == 0) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - Creature* pCreature = getSelectedCreature(); - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pCreature->SetPhaseMask(phasemask,true); - - if (!pCreature->isPet()) - pCreature->SaveToDB(); - - return true; -} -//npc deathstate handling -bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args) -{ - if (!*args) - return false; - - Creature* pCreature = getSelectedCreature(); - if (!pCreature || pCreature->isPet()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (strncmp(args, "on", 3) == 0) - pCreature->SetDeadByDefault(true); - else if (strncmp(args, "off", 4) == 0) - pCreature->SetDeadByDefault(false); - else - { - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; - } - - pCreature->SaveToDB(); - pCreature->Respawn(); - - return true; -} - -//TODO: NpcCommands that need to be fixed : - -bool ChatHandler::HandleNpcNameCommand(const char* /*args*/) -{ - /* Temp. disabled - if (!*args) - return false; - - if (strlen((char*)args)>75) - { - PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); - return true; - } - - for (uint8 i = 0; i < strlen(args); ++i) - { - if (!isalpha(args[i]) && args[i] != ' ') - { - SendSysMessage(LANG_CHARS_ONLY); - return false; - } - } - - uint64 guid; - guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - pCreature->SetName(args); - uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName()); - pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - pCreature->SaveToDB(); - */ - - return true; -} - -bool ChatHandler::HandleNpcSubNameCommand(const char* /*args*/) -{ - /* Temp. disabled - - if (!*args) - args = ""; - - if (strlen((char*)args)>75) - { - - PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); - return true; - } - - for (uint8 i = 0; i < strlen(args); i++) - { - if (!isalpha(args[i]) && args[i] != ' ') - { - SendSysMessage(LANG_CHARS_ONLY); - return false; - } - } - uint64 guid; - guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); - pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - pCreature->SaveToDB(); - */ - return true; -} - -//move item to other slot -bool ChatHandler::HandleItemMoveCommand(const char* args) -{ - if (!*args) - return false; - uint8 srcslot, dstslot; - - char* pParam1 = strtok((char*)args, " "); - if (!pParam1) - return false; - - char* pParam2 = strtok(NULL, " "); - if (!pParam2) - return false; - - srcslot = (uint8)atoi(pParam1); - dstslot = (uint8)atoi(pParam2); - - if (srcslot == dstslot) - return true; - - if (!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) - return false; - - if (!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) - return false; - - uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); - uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - - m_session->GetPlayer()->SwapItem(src, dst); - - return true; -} - -//demorph player or unit -bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) -{ - Unit *target = getSelectedUnit(); - if (!target) - target = m_session->GetPlayer(); - - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) - return false; - - target->DeMorph(); - - return true; -} - -//morph creature or player -bool ChatHandler::HandleModifyMorphCommand(const char* args) -{ - if (!*args) - return false; - - uint16 display_id = (uint16)atoi((char*)args); - - Unit *target = getSelectedUnit(); - if (!target) - target = m_session->GetPlayer(); - - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) - return false; - - target->SetDisplayId(display_id); - - return true; -} - -//kick player -bool ChatHandler::HandleKickPlayerCommand(const char *args) -{ -/* const char* kickName = strtok((char*)args, " "); - char* kickReason = strtok(NULL, "\n"); - std::string reason = "No Reason"; - std::string kicker = "Console"; - if (kickReason) - reason = kickReason; - if (m_session) - kicker = m_session->GetPlayer()->GetName(); - - if (!kickName) - { - Player* player = getSelectedPlayer(); - if (!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (player == m_session->GetPlayer()) - { - SendSysMessage(LANG_COMMAND_KICKSELF); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(player, 0)) - return false; - - if (sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1) - { - sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str()); - } - else - { - PSendSysMessage(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str()); - } - - player->GetSession()->KickPlayer(); - } - else - { - std::string name = extractPlayerNameFromLink((char*)kickName); - if (name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - if (m_session && name == m_session->GetPlayer()->GetName()) - { - SendSysMessage(LANG_COMMAND_KICKSELF); - SetSentErrorMessage(true); - return false; - } - - Player* player = objmgr.GetPlayer(kickName); - if (!player) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - if (HasLowerSecurity(player, 0)) - { - SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); //maybe replacement string for this later on - SetSentErrorMessage(true); - return false; - } - - std::string nameLink = playerLink(name); - - if (sWorld.KickPlayer(name)) - { - if (sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1) - { - sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, nameLink.c_str(), kicker.c_str(), reason.c_str()); - } - else - { - PSendSysMessage(LANG_COMMAND_KICKMESSAGE,nameLink.c_str()); - } - } - else - { - PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,nameLink.c_str()); - return false; - } - }*/ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - if (m_session && target == m_session->GetPlayer()) - { - SendSysMessage(LANG_COMMAND_KICKSELF); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - // send before target pointer invalidate - PSendSysMessage(LANG_COMMAND_KICKMESSAGE,GetNameLink(target).c_str()); - target->GetSession()->KickPlayer(); - return true; -} - -//set temporary phase mask for player -bool ChatHandler::HandleModifyPhaseCommand(const char* args) -{ - if (!*args) - return false; - - uint32 phasemask = (uint32)atoi((char*)args); - - Unit *target = getSelectedUnit(); - if (!target) - target = m_session->GetPlayer(); - - // check online security - else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) - return false; - - target->SetPhaseMask(phasemask,true); - - return true; -} -//show info of gameobject -bool ChatHandler::HandleGOInfoCommand(const char* args) -{ - uint32 entry = 0; - uint32 type = 0; - uint32 displayid = 0; - std::string name; - - if (!*args) - { - if (WorldObject * obj = getSelectedObject()) - entry = obj->GetEntry(); - } - else - entry = atoi((char*)args); - - GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); - - if (!goinfo) - return false; - - type = goinfo->type; - displayid = goinfo->displayId; - name = goinfo->name; - - PSendSysMessage(LANG_GOINFO_ENTRY, entry); - PSendSysMessage(LANG_GOINFO_TYPE, type); - PSendSysMessage(LANG_GOINFO_DISPLAYID, displayid); - PSendSysMessage(LANG_GOINFO_NAME, name.c_str()); - - return true; -} - -//show info of player -bool ChatHandler::HandlePInfoCommand(const char* args) -{ - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - return false; - - uint32 accId = 0; - uint32 money = 0; - uint32 total_player_time = 0; - uint8 level = 0; - uint32 latency = 0; - uint8 race; - uint8 Class; - - // get additional information from Player object - if (target) - { - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - accId = target->GetSession()->GetAccountId(); - money = target->GetMoney(); - total_player_time = target->GetTotalPlayedTime(); - level = target->getLevel(); - latency = target->GetSession()->GetLatency(); - race = target->getRace(); - Class = target->getClass(); - } - // get additional information from DB - else - { - // check offline security - if (HasLowerSecurity(NULL, target_guid)) - return false; - - // 0 1 2 3 4 5 - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT totaltime, level, money, account, race, class FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid)); - if (!result) - return false; - - Field *fields = result->Fetch(); - total_player_time = fields[0].GetUInt32(); - level = fields[1].GetUInt32(); - money = fields[2].GetUInt32(); - accId = fields[3].GetUInt32(); - race = fields[4].GetUInt8(); - Class = fields[5].GetUInt8(); - } - - std::string username = GetTrinityString(LANG_ERROR); - std::string email = GetTrinityString(LANG_ERROR); - std::string last_ip = GetTrinityString(LANG_ERROR); - uint32 security = 0; - std::string last_login = GetTrinityString(LANG_ERROR); - - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT a.username,aa.gmlevel,a.email,a.last_ip,a.last_login " - "FROM account a " - "LEFT JOIN account_access aa " - "ON (a.id = aa.id) " - "WHERE a.id = '%u'",accId); - if (result) - { - Field* fields = result->Fetch(); - username = fields[0].GetCppString(); - security = fields[1].GetUInt32(); - email = fields[2].GetCppString(); - - if (email.empty()) - email = "-"; - - if (!m_session || m_session->GetSecurity() >= security) - { - last_ip = fields[3].GetCppString(); - last_login = fields[4].GetCppString(); - } - else - { - last_ip = "-"; - last_login = "-"; - } - } - - std::string nameLink = playerLink(target_name); - - PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(target_guid), username.c_str(), accId, email.c_str(), security, last_ip.c_str(), last_login.c_str(), latency); - - std::string race_s, Class_s; - switch(race) - { - case RACE_HUMAN: race_s = "Human"; break; - case RACE_ORC: race_s = "Orc"; break; - case RACE_DWARF: race_s = "Dwarf"; break; - case RACE_NIGHTELF: race_s = "Night Elf"; break; - case RACE_UNDEAD_PLAYER: race_s = "Undead"; break; - case RACE_TAUREN: race_s = "Tauren"; break; - case RACE_GNOME: race_s = "Gnome"; break; - case RACE_TROLL: race_s = "Troll"; break; - case RACE_BLOODELF: race_s = "Blood Elf"; break; - case RACE_DRAENEI: race_s = "Draenei"; break; - } - switch(Class) - { - case CLASS_WARRIOR: Class_s = "Warrior"; break; - case CLASS_PALADIN: Class_s = "Paladin"; break; - case CLASS_HUNTER: Class_s = "Hunter"; break; - case CLASS_ROGUE: Class_s = "Rogue"; break; - case CLASS_PRIEST: Class_s = "Priest"; break; - case CLASS_DEATH_KNIGHT: Class_s = "Death Knight"; break; - case CLASS_SHAMAN: Class_s = "Shaman"; break; - case CLASS_MAGE: Class_s = "Mage"; break; - case CLASS_WARLOCK: Class_s = "Warlock"; break; - case CLASS_DRUID: Class_s = "Druid"; break; - } - - std::string timeStr = secsToTimeString(total_player_time,true,true); - uint32 gold = money /GOLD; - uint32 silv = (money % GOLD) / SILVER; - uint32 copp = (money % GOLD) % SILVER; - PSendSysMessage(LANG_PINFO_LEVEL, race_s.c_str(), Class_s.c_str(), timeStr.c_str(), level, gold, silv, copp); - - return true; -} - -/////WAYPOINT COMMANDS - -/** - * Add a waypoint to a creature. - * - * The user can either select an npc or provide its GUID. - * - * The user can even select a visual waypoint - then the new waypoint - * is placed *after* the selected one - this makes insertion of new - * waypoints possible. - * - * eg: - * .wp add 12345 - * -> adds a waypoint to the npc with the GUID 12345 - * - * .wp add - * -> adds a waypoint to the currently selected creature - * - * - * @param args if the user did not provide a GUID, it is NULL - * - * @return true - command did succeed, false - something went wrong - */ -bool ChatHandler::HandleWpAddCommand(const char* args) -{ - sLog.outDebug("DEBUG: HandleWpAddCommand"); - - // optional - char* path_number = NULL; - uint32 pathid = 0; - - if (*args) - path_number = strtok((char*)args, " "); - - uint32 point = 0; - Creature* target = getSelectedCreature(); - - if (!path_number) - { - if (target) - pathid = target->GetWaypointPath(); - else - { - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT MAX(id) FROM waypoint_data"); - uint32 maxpathid = result->Fetch()->GetInt32(); - pathid = maxpathid+1; - sLog.outDebug("DEBUG: HandleWpAddCommand - New path started."); - PSendSysMessage("%s%s|r", "|cff00ff00", "New path started."); - } - } - else - pathid = atoi(path_number); - - // path_id -> ID of the Path - // point -> number of the waypoint (if not 0) - - if (!pathid) - { - sLog.outDebug("DEBUG: HandleWpAddCommand - Current creature haven't loaded path."); - PSendSysMessage("%s%s|r", "|cffff33ff", "Current creature haven't loaded path."); - return true; - } - - sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0"); - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid); - - if (result) - point = (*result)[0].GetUInt32(); - - Player* player = m_session->GetPlayer(); - //Map *map = player->GetMap(); - - WorldDatabase.PExecuteLog("INSERT INTO waypoint_data (id, point, position_x, position_y, position_z) VALUES ('%u','%u','%f', '%f', '%f')", - pathid, point+1, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); - - PSendSysMessage("%s%s%u%s%u%s|r", "|cff00ff00", "PathID: |r|cff00ffff", pathid, "|r|cff00ff00: Waypoint |r|cff00ffff", point+1,"|r|cff00ff00 created. "); - return true; -} // HandleWpAddCommand - -bool ChatHandler::HandleWpLoadPathCommand(const char *args) -{ - if (!*args) - return false; - - // optional - char* path_number = NULL; - - if (*args) - path_number = strtok((char*)args, " "); - - uint32 pathid = 0; - uint32 guidlow = 0; - Creature* target = getSelectedCreature(); - - // Did player provide a path_id? - if (!path_number) - sLog.outDebug("DEBUG: HandleWpLoadPathCommand - No path number provided"); - - if (!target) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (target->GetEntry() == 1) - { - PSendSysMessage("%s%s|r", "|cffff33ff", "You want to load path to a waypoint? Aren't you?"); - SetSentErrorMessage(true); - return false; - } - - pathid = atoi(path_number); - - if (!pathid) - { - PSendSysMessage("%s%s|r", "|cffff33ff", "No vallid path number provided."); - return true; - } - - guidlow = target->GetDBTableGUIDLow(); - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM creature_addon WHERE guid = '%u'",guidlow); - - if (result) - WorldDatabase.PExecute("UPDATE creature_addon SET path_id = '%u' WHERE guid = '%u'", pathid, guidlow); - else - WorldDatabase.PExecute("INSERT INTO creature_addon(guid,path_id) VALUES ('%u','%u')", guidlow, pathid); - - WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE, guidlow); - - target->LoadPath(pathid); - target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); - target->GetMotionMaster()->Initialize(); - target->MonsterSay("Path loaded.",0,0); - - return true; -} - -bool ChatHandler::HandleReloadAllPaths(const char* args) -{ - if (!*args) - return false; - - uint32 id = atoi(args); - - if (!id) - return false; - - PSendSysMessage("%s%s|r|cff00ffff%u|r", "|cff00ff00", "Loading Path: ", id); - sWaypointMgr->UpdatePath(id); - return true; -} - -bool ChatHandler::HandleWpUnLoadPathCommand(const char * /*args*/) -{ - uint32 guidlow = 0; - Creature* target = getSelectedCreature(); - - if (!target) - { - PSendSysMessage("%s%s|r", "|cff33ffff", "You must select target."); - return true; - } - - if (target->GetCreatureAddon()) - { - if (target->GetCreatureAddon()->path_id != 0) - { - WorldDatabase.PExecute("DELETE FROM creature_addon WHERE guid = %u", target->GetGUIDLow()); - target->UpdateWaypointID(0); - WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", IDLE_MOTION_TYPE, guidlow); - target->LoadPath(0); - target->SetDefaultMovementType(IDLE_MOTION_TYPE); - target->GetMotionMaster()->MoveTargetedHome(); - target->GetMotionMaster()->Initialize(); - target->MonsterSay("Path unloaded.",0,0); - return true; - } - PSendSysMessage("%s%s|r", "|cffff33ff", "Target have no loaded path."); - } - return true; -} - -bool ChatHandler::HandleWpEventCommand(const char* args) -{ - if (!*args) - return false; - - char* show_str = strtok((char*)args, " "); - std::string show = show_str; - - // Check - if ((show != "add") && (show != "mod") && (show != "del") && (show != "listid")) return false; - - char* arg_id = strtok(NULL, " "); - uint32 id = 0; - - if (show == "add") - { - if (arg_id) - id = atoi(arg_id); - - if (id) - { - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid = %u", id); - - if (!result) - { - WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id); - PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: New waypoint event added: ", id); - } - else - PSendSysMessage("|cff00ff00Wp Event: You have choosed an existing waypoint script guid: %u|r", id); - } - else - { - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT MAX(guid) FROM waypoint_scripts"); - id = result->Fetch()->GetUInt32(); - WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id+1); - PSendSysMessage("%s%s%u|r", "|cff00ff00","Wp Event: New waypoint event added: |r|cff00ffff", id+1); - } - - return true; - } - - if (show == "listid") - { - if (!arg_id) - { - PSendSysMessage("%s%s|r", "|cff33ffff","Wp Event: You must provide waypoint script id."); - return true; - } - - id = atoi(arg_id); - - uint32 a2, a3, a4, a5, a6; - float a8, a9, a10, a11; - char const* a7; - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = %u", id); - - if (!result) - { - PSendSysMessage("%s%s%u|r", "|cff33ffff", "Wp Event: No waypoint scripts found on id: ", id); - return true; - } - - Field *fields; - - do - { - fields = result->Fetch(); - a2 = fields[0].GetUInt32(); - a3 = fields[1].GetUInt32(); - a4 = fields[2].GetUInt32(); - a5 = fields[3].GetUInt32(); - a6 = fields[4].GetUInt32(); - a7 = fields[5].GetString(); - a8 = fields[6].GetFloat(); - a9 = fields[7].GetFloat(); - a10 = fields[8].GetFloat(); - a11 = fields[9].GetFloat(); - - PSendSysMessage("|cffff33ffid:|r|cff00ffff %u|r|cff00ff00, guid: |r|cff00ffff%u|r|cff00ff00, delay: |r|cff00ffff%u|r|cff00ff00, command: |r|cff00ffff%u|r|cff00ff00, datalong: |r|cff00ffff%u|r|cff00ff00, datalong2: |r|cff00ffff%u|r|cff00ff00, datatext: |r|cff00ffff%s|r|cff00ff00, posx: |r|cff00ffff%f|r|cff00ff00, posy: |r|cff00ffff%f|r|cff00ff00, posz: |r|cff00ffff%f|r|cff00ff00, orientation: |r|cff00ffff%f|r", id, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); - } - while (result->NextRow()); - } - - if (show == "del") - { - id = atoi(arg_id); - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM waypoint_scripts WHERE guid = %u", id); - - if (result) - { - WorldDatabase.PExecuteLog("DELETE FROM waypoint_scripts WHERE guid = %u", id); - PSendSysMessage("%s%s%u|r","|cff00ff00","Wp Event: Waypoint script removed: ", id); - } - else - PSendSysMessage("|cffff33ffWp Event: ERROR: you have selected a non existing script: %u|r", id); - - return true; - } - - if (show == "mod") - { - if (!arg_id) - { - SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r"); - return true; - } - - id = atoi(arg_id); - - if (!id) - { - SendSysMessage("|cffff33ffERROR: No vallid waypoint script id not present.|r"); - return true; - } - - char* arg_2 = strtok(NULL," "); - - if (!arg_2) - { - SendSysMessage("|cffff33ffERROR: No argument present.|r"); - return true; - } - - std::string arg_string = arg_2; - - if ((arg_string != "setid") && (arg_string != "delay") && (arg_string != "command") - && (arg_string != "datalong") && (arg_string != "datalong2") && (arg_string != "dataint") && (arg_string != "posx") - && (arg_string != "posy") && (arg_string != "posz") && (arg_string != "orientation")) - { - SendSysMessage("|cffff33ffERROR: No valid argument present.|r"); - return true; - } - - char* arg_3; - std::string arg_str_2 = arg_2; - arg_3 = strtok(NULL," "); - - if (!arg_3) - { - SendSysMessage("|cffff33ffERROR: No additional argument present.|r"); - return true; - } - - float coord; - - if (arg_str_2 == "setid") - { - uint32 newid = atoi(arg_3); - PSendSysMessage("%s%s|r|cff00ffff%u|r|cff00ff00%s|r|cff00ffff%u|r","|cff00ff00","Wp Event: Wypoint scipt guid: ", newid," id changed: ", id); - WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET id='%u' WHERE guid='%u'", - newid, id); return true; - } - else - { - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid='%u'",id); - - if (!result) - { - SendSysMessage("|cffff33ffERROR: You have selected an non existing waypoint script guid.|r"); - return true; - } - - if (arg_str_2 == "posx") - { - coord = atof(arg_3); - WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET x='%f' WHERE guid='%u'", - coord, id); - PSendSysMessage("|cff00ff00Waypoint script:|r|cff00ffff %u|r|cff00ff00 position_x updated.|r", id); - return true; - } - else if (arg_str_2 == "posy") - { - coord = atof(arg_3); - WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET y='%f' WHERE guid='%u'", - coord, id); - PSendSysMessage("|cff00ff00Waypoint script: %u position_y updated.|r", id); - return true; - } - else if (arg_str_2 == "posz") - { - coord = atof(arg_3); - WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET z='%f' WHERE guid='%u'", - coord, id); - PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 position_z updated.|r", id); - return true; - } - else if (arg_str_2 == "orientation") - { - coord = atof(arg_3); - WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET o='%f' WHERE guid='%u'", - coord, id); - PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 orientation updated.|r", id); - return true; - } - else if (arg_str_2 == "dataint") - { - WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%u' WHERE guid='%u'", - arg_2, atoi(arg_3), id); - PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 dataint updated.|r", id); - return true; - } - else - { - std::string arg_str_3 = arg_3; - WorldDatabase.escape_string(arg_str_3); - WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'", - arg_2, arg_str_3.c_str(), id); - } - } - PSendSysMessage("%s%s|r|cff00ffff%u:|r|cff00ff00 %s %s|r","|cff00ff00","Waypoint script:", id, arg_2,"updated."); - } - return true; -} - -bool ChatHandler::HandleWpModifyCommand(const char* args) -{ - sLog.outDebug("DEBUG: HandleWpModifyCommand"); - - if (!*args) - return false; - - // first arg: add del text emote spell waittime move - char* show_str = strtok((char*)args, " "); - if (!show_str) - { - return false; - } - - std::string show = show_str; - // Check - // Remember: "show" must also be the name of a column! - if ((show != "delay") && (show != "action") && (show != "action_chance") - && (show != "move_flag") && (show != "del") && (show != "move") && (show != "wpadd") -) - { - return false; - } - - // Next arg is: - char* arg_str = NULL; - - // Did user provide a GUID - // or did the user select a creature? - // -> variable lowguid is filled with the GUID of the NPC - uint32 pathid = 0; - uint32 point = 0; - uint32 wpGuid = 0; - Creature* target = getSelectedCreature(); - - if (!target || target->GetEntry() != VISUAL_WAYPOINT) - { - SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r"); - return false; - } - - sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC"); - // The visual waypoint - Creature* wpCreature = NULL; - wpGuid = target->GetGUIDLow(); - - // Did the user select a visual spawnpoint? - if (wpGuid) - wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); - // attempt check creature existence by DB data - else - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, wpGuid); - return false; - } - // User did select a visual waypoint? - // Check the creature - if (wpCreature->GetEntry() == VISUAL_WAYPOINT) - { - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE wpguid = %u", wpGuid); - - if (!result) - { - sLog.outDebug("DEBUG: HandleWpModifyCommand - No waypoint found - used 'wpguid'"); - - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow()); - // Select waypoint number from database - // Since we compare float values, we have to deal with - // some difficulties. - // Here we search for all waypoints that only differ in one from 1 thousand - // (0.001) - There is no other way to compare C++ floats with mySQL floats - // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html - const char* maxDIFF = "0.01"; - result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE (abs(position_x - %f) <= %s) and (abs(position_y - %f) <= %s) and (abs(position_z - %f) <= %s)", - wpCreature->GetPositionX(), maxDIFF, wpCreature->GetPositionY(), maxDIFF, wpCreature->GetPositionZ(), maxDIFF); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid); - return true; - } - } - sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid"); - - do - { - Field *fields = result->Fetch(); - pathid = fields[0].GetUInt32(); - point = fields[1].GetUInt32(); - } - while (result->NextRow()); - - // We have the waypoint number and the GUID of the "master npc" - // Text is enclosed in "<>", all other arguments not - arg_str = strtok((char*)NULL, " "); - } - - sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command"); - - // Check for argument - if (show != "del" && show != "move" && arg_str == NULL) - { - PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str); - return false; - } - - if (show == "del" && target) - { - PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); - - // wpCreature - Creature* wpCreature = NULL; - - if (wpGuid != 0) - { - wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); - wpCreature->CombatStop(); - wpCreature->DeleteFromDB(); - wpCreature->AddObjectToRemoveList(); - } - - WorldDatabase.PExecuteLog("DELETE FROM waypoint_data WHERE id='%u' AND point='%u'", - pathid, point); - WorldDatabase.PExecuteLog("UPDATE waypoint_data SET point=point-1 WHERE id='%u' AND point>'%u'", - pathid, point); - - PSendSysMessage(LANG_WAYPOINT_REMOVED); - return true; - } // del - - if (show == "move" && target) - { - PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid); - - Player *chr = m_session->GetPlayer(); - Map *map = chr->GetMap(); - { - // wpCreature - Creature* wpCreature = NULL; - // What to do: - // Move the visual spawnpoint - // Respawn the owner of the waypoints - if (wpGuid != 0) - { - wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); - wpCreature->CombatStop(); - wpCreature->DeleteFromDB(); - wpCreature->AddObjectToRemoveList(); - // re-create - Creature* wpCreature2 = new Creature; - if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - delete wpCreature2; - return false; - } - - wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map); - map->Add(wpCreature2); - //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2); - } - - WorldDatabase.PExecuteLog("UPDATE waypoint_data SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'", - chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), pathid, point); - - PSendSysMessage(LANG_WAYPOINT_CHANGED); - } - return true; - } // move - - const char *text = arg_str; - - if (text == 0) - { - // show_str check for present in list of correct values, no sql injection possible - WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'", - show_str, pathid, point); - } - else - { - // show_str check for present in list of correct values, no sql injection possible - std::string text2 = text; - WorldDatabase.escape_string(text2); - WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'", - show_str, text2.c_str(), pathid, point); - } - - PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str); - return true; -} - -bool ChatHandler::HandleWpShowCommand(const char* args) -{ - sLog.outDebug("DEBUG: HandleWpShowCommand"); - - if (!*args) - return false; - - // first arg: on, off, first, last - char* show_str = strtok((char*)args, " "); - if (!show_str) - return false; - - // second arg: GUID (optional, if a creature is selected) - char* guid_str = strtok((char*)NULL, " "); - sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str); - - uint32 pathid = 0; - Creature* target = getSelectedCreature(); - - // Did player provide a PathID? - - if (!guid_str) - { - sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str"); - // No PathID provided - // -> Player must have selected a creature - - if (!target) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - pathid = target->GetWaypointPath(); - } - else - { - sLog.outDebug("|cff00ff00DEBUG: HandleWpShowCommand: PathID provided|r"); - // PathID provided - // Warn if player also selected a creature - // -> Creature selection is ignored <- - if (target) - SendSysMessage(LANG_WAYPOINT_CREATSELECTED); - - pathid = atoi((char*)guid_str); - } - - sLog.outDebug("DEBUG: HandleWpShowCommand: danach"); - - std::string show = show_str; - uint32 Maxpoint; - - sLog.outDebug("DEBUG: HandleWpShowCommand: PathID: %u", pathid); - - //PSendSysMessage("wpshow - show: %s", show); - - // Show info for the selected waypoint - if (show == "info") - { - // Check if the user did specify a visual waypoint - if (target->GetEntry() != VISUAL_WAYPOINT) - { - PSendSysMessage(LANG_WAYPOINT_VP_SELECT); - SetSentErrorMessage(true); - return false; - } - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id, point, delay, move_flag, action, action_chance FROM waypoint_data WHERE wpguid = %u", target->GetGUIDLow()); - - if (!result) - { - SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM); - return true; - } - - SendSysMessage("|cff00ffffDEBUG: wp show info:|r"); - do - { - Field *fields = result->Fetch(); - pathid = fields[0].GetUInt32(); - uint32 point = fields[1].GetUInt32(); - uint32 delay = fields[2].GetUInt32(); - uint32 flag = fields[3].GetUInt32(); - uint32 ev_id = fields[4].GetUInt32(); - uint32 ev_chance = fields[5].GetUInt32(); - - PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff%u|r|cff00ff00, Path ID: |r|cff00ffff%u|r", point, pathid); - PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff%u|r", delay); - PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff%u|r", flag); - PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff%u|r", ev_id); - PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff%u|r", ev_chance); - } - while (result->NextRow()); - - return true; - } - - if (show == "on") - { - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT point, position_x,position_y,position_z FROM waypoint_data WHERE id = '%u'", pathid); - - if (!result) - { - SendSysMessage("|cffff33ffPath no found.|r"); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff%u|r", pathid); - - // Delete all visuals for this NPC - QueryResult_AutoPtr result2 = WorldDatabase.PQuery("SELECT wpguid FROM waypoint_data WHERE id = '%u' and wpguid <> 0", pathid); - - if (result2) - { - bool hasError = false; - do - { - Field *fields = result2->Fetch(); - uint32 wpguid = fields[0].GetUInt32(); - Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); - - if (!pCreature) - { - PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid); - hasError = true; - WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid); - } - else - { - pCreature->CombatStop(); - pCreature->DeleteFromDB(); - pCreature->AddObjectToRemoveList(); - } - - } - while (result2->NextRow()); - - if (hasError) - { - PSendSysMessage(LANG_WAYPOINT_TOOFAR1); - PSendSysMessage(LANG_WAYPOINT_TOOFAR2); - PSendSysMessage(LANG_WAYPOINT_TOOFAR3); - } - } - - do - { - Field *fields = result->Fetch(); - uint32 point = fields[0].GetUInt32(); - float x = fields[1].GetFloat(); - float y = fields[2].GetFloat(); - float z = fields[3].GetFloat(); - - uint32 id = VISUAL_WAYPOINT; - - Player *chr = m_session->GetPlayer(); - Map *map = chr->GetMap(); - float o = chr->GetOrientation(); - - Creature* wpCreature = new Creature; - if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); - delete wpCreature; - return false; - } - - sLog.outDebug("DEBUG: UPDATE waypoint_data SET wpguid = '%u"); - // set "wpguid" column to the visual waypoint - WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point); - - wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map); - map->Add(wpCreature); - - if (target) - { - wpCreature->SetDisplayId(target->GetDisplayId()); - wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); - wpCreature->SetLevel(point > MAX_LEVEL ? MAX_LEVEL : point); - } - } - while (result->NextRow()); - - SendSysMessage("|cff00ff00Showing the current creature's path.|r"); - return true; - } - - if (show == "first") - { - PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: %u|r", pathid); - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z FROM waypoint_data WHERE point='1' AND id = '%u'",pathid); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid); - SetSentErrorMessage(true); - return false; - } - - Field *fields = result->Fetch(); - float x = fields[0].GetFloat(); - float y = fields[1].GetFloat(); - float z = fields[2].GetFloat(); - uint32 id = VISUAL_WAYPOINT; - - Player *chr = m_session->GetPlayer(); - float o = chr->GetOrientation(); - Map *map = chr->GetMap(); - - Creature* pCreature = new Creature; - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); - delete pCreature; - return false; - } - - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); - map->Add(pCreature); - - if (target) - { - pCreature->SetDisplayId(target->GetDisplayId()); - pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); - } - - return true; - } - - if (show == "last") - { - PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff%u|r", pathid); - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid); - if (result) - Maxpoint = (*result)[0].GetUInt32(); - else - Maxpoint = 0; - - result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z FROM waypoint_data WHERE point ='%u' AND id = '%u'",Maxpoint, pathid); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid); - SetSentErrorMessage(true); - return false; - } - Field *fields = result->Fetch(); - float x = fields[0].GetFloat(); - float y = fields[1].GetFloat(); - float z = fields[2].GetFloat(); - uint32 id = VISUAL_WAYPOINT; - - Player *chr = m_session->GetPlayer(); - float o = chr->GetOrientation(); - Map *map = chr->GetMap(); - - Creature* pCreature = new Creature; - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) - { - PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); - delete pCreature; - return false; - } - - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); - map->Add(pCreature); - - if (target) - { - pCreature->SetDisplayId(target->GetDisplayId()); - pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5); - } - - return true; - } - - if (show == "off") - { - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%u'", 1); - if (!result) - { - SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND); - SetSentErrorMessage(true); - return false; - } - bool hasError = false; - do - { - Field *fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); - if (!pCreature) - { - PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); - hasError = true; - WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid); - } - else - { - pCreature->CombatStop(); - pCreature->DeleteFromDB(); - pCreature->AddObjectToRemoveList(); - } - } - while (result->NextRow()); - // set "wpguid" column to "empty" - no visual waypoint spawned - WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '0'"); - //WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'"); - - if (hasError) - { - PSendSysMessage(LANG_WAYPOINT_TOOFAR1); - PSendSysMessage(LANG_WAYPOINT_TOOFAR2); - PSendSysMessage(LANG_WAYPOINT_TOOFAR3); - } - - SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); - return true; - } - - PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r"); - return true; -} - -//////////// WAYPOINT COMMANDS // - -//rename characters -bool ChatHandler::HandleCharacterRenameCommand(const char* args) -{ - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - return false; - - if (target) - { - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_RENAME); - } - else - { - // check offline security - if (HasLowerSecurity(NULL, target_guid)) - return false; - - std::string oldNameLink = playerLink(target_name); - - PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid)); - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(target_guid)); - } - - return true; -} - -// customize characters -bool ChatHandler::HandleCharacterCustomizeCommand(const char* args) -{ - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - return false; - - if (target) - { - PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow()); - } - else - { - std::string oldNameLink = playerLink(target_name); - - PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid)); - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(target_guid)); - } - - return true; -} - -bool ChatHandler::HandleCharacterReputationCommand(const char* args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - LocaleConstant loc = GetSessionDbcLocale(); - - FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList(); - for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr) - { - FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID); - char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#"; - ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); - std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]); - std::ostringstream ss; - if (m_session) - ss << itr->second.ID << " - |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << " " << localeNames[loc] << "]|h|r"; - else - ss << itr->second.ID << " - " << factionName << " " << localeNames[loc]; - - ss << " " << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; - - if (itr->second.Flags & FACTION_FLAG_VISIBLE) - ss << GetTrinityString(LANG_FACTION_VISIBLE); - if (itr->second.Flags & FACTION_FLAG_AT_WAR) - ss << GetTrinityString(LANG_FACTION_ATWAR); - if (itr->second.Flags & FACTION_FLAG_PEACE_FORCED) - ss << GetTrinityString(LANG_FACTION_PEACE_FORCED); - if (itr->second.Flags & FACTION_FLAG_HIDDEN) - ss << GetTrinityString(LANG_FACTION_HIDDEN); - if (itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED) - ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED); - if (itr->second.Flags & FACTION_FLAG_INACTIVE) - ss << GetTrinityString(LANG_FACTION_INACTIVE); - - SendSysMessage(ss.str().c_str()); - } - return true; -} - -//change standstate -bool ChatHandler::HandleModifyStandStateCommand(const char* args) -{ - if (!*args) - return false; - - uint32 anim_id = atoi((char*)args); - m_session->GetPlayer()->SetUInt32Value(UNIT_NPC_EMOTESTATE , anim_id); - - return true; -} - -bool ChatHandler::HandleHonorAddCommand(const char* args) -{ - if (!*args) - return false; - - Player *target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - uint32 amount = (uint32)atoi(args); - target->RewardHonor(NULL, 1, amount); - return true; -} - -bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/) -{ - Unit *target = getSelectedUnit(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) - return false; - - m_session->GetPlayer()->RewardHonor(target, 1); - return true; -} - -bool ChatHandler::HandleHonorUpdateCommand(const char* /*args*/) -{ - Player *target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - target->UpdateHonorFields(); - return true; -} - -bool ChatHandler::HandleLookupEventCommand(const char* args) -{ - if (!*args) - return false; - - std::string namepart = args; - std::wstring wnamepart; - - // converting string that we try to find to lower case - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - wstrToLower(wnamepart); - - bool found = false; - - GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); - GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); - - for (uint32 id = 0; id < events.size(); ++id) - { - GameEventData const& eventData = events[id]; - - std::string descr = eventData.description; - if (descr.empty()) - continue; - - if (Utf8FitTo(descr, wnamepart)) - { - char const* active = activeEvents.find(id) != activeEvents.end() ? GetTrinityString(LANG_ACTIVE) : ""; - - if (m_session) - PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active); - else - PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active); - - if (!found) - found = true; - } - } - - if (!found) - SendSysMessage(LANG_NOEVENTFOUND); - - return true; -} - -bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/) -{ - uint32 counter = 0; - - GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); - GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); - - char const* active = GetTrinityString(LANG_ACTIVE); - - for (GameEventMgr::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr) - { - uint32 event_id = *itr; - GameEventData const& eventData = events[event_id]; - - if (m_session) - PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active); - else - PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active); - - ++counter; - } - - if (counter == 0) - SendSysMessage(LANG_NOEVENTFOUND); - - return true; -} - -bool ChatHandler::HandleEventInfoCommand(const char* args) -{ - if (!*args) - return false; - - // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameevent"); - if (!cId) - return false; - - uint32 event_id = atoi(cId); - - GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); - - if (event_id >=events.size()) - { - SendSysMessage(LANG_EVENT_NOT_EXIST); - SetSentErrorMessage(true); - return false; - } - - GameEventData const& eventData = events[event_id]; - if (!eventData.isValid()) - { - SendSysMessage(LANG_EVENT_NOT_EXIST); - SetSentErrorMessage(true); - return false; - } - - GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); - bool active = activeEvents.find(event_id) != activeEvents.end(); - char const* activeStr = active ? GetTrinityString(LANG_ACTIVE) : ""; - - std::string startTimeStr = TimeToTimestampStr(eventData.start); - std::string endTimeStr = TimeToTimestampStr(eventData.end); - - uint32 delay = gameeventmgr.NextCheck(event_id); - time_t nextTime = time(NULL)+delay; - std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-"; - - std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE); - std::string lengthStr = secsToTimeString(eventData.length * MINUTE); - - PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr, - startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(), - nextStr.c_str()); - return true; -} - -bool ChatHandler::HandleEventStartCommand(const char* args) -{ - if (!*args) - return false; - - // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameevent"); - if (!cId) - return false; - - int32 event_id = atoi(cId); - - GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); - - if (event_id < 1 || event_id >=events.size()) - { - SendSysMessage(LANG_EVENT_NOT_EXIST); - SetSentErrorMessage(true); - return false; - } - - GameEventData const& eventData = events[event_id]; - if (!eventData.isValid()) - { - SendSysMessage(LANG_EVENT_NOT_EXIST); - SetSentErrorMessage(true); - return false; - } - - GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); - if (activeEvents.find(event_id) != activeEvents.end()) - { - PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id); - SetSentErrorMessage(true); - return false; - } - - gameeventmgr.StartEvent(event_id,true); - return true; -} - -bool ChatHandler::HandleEventStopCommand(const char* args) -{ - if (!*args) - return false; - - // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameevent"); - if (!cId) - return false; - - int32 event_id = atoi(cId); - - GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); - - if (event_id < 1 || event_id >=events.size()) - { - SendSysMessage(LANG_EVENT_NOT_EXIST); - SetSentErrorMessage(true); - return false; - } - - GameEventData const& eventData = events[event_id]; - if (!eventData.isValid()) - { - SendSysMessage(LANG_EVENT_NOT_EXIST); - SetSentErrorMessage(true); - return false; - } - - GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList(); - - if (activeEvents.find(event_id) == activeEvents.end()) - { - PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id); - SetSentErrorMessage(true); - return false; - } - - gameeventmgr.StopEvent(event_id,true); - return true; -} - -bool ChatHandler::HandleCombatStopCommand(const char* args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - target->CombatStop(); - target->getHostileRefManager().deleteReferences(); - return true; -} - -void ChatHandler::HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id) -{ - uint32 classmask = player->getClassMask(); - - for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) - { - SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); - if (!skillLine) - continue; - - // wrong skill - if (skillLine->skillId != skill_id) - continue; - - // not high rank - if (skillLine->forward_spellid) - continue; - - // skip racial skills - if (skillLine->racemask != 0) - continue; - - // skip wrong class skills - if (skillLine->classmask && (skillLine->classmask & classmask) == 0) - continue; - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,player,false)) - continue; - - player->learnSpell(skillLine->spellId, false); - } -} - -bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/) -{ - - for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) - { - SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i); - if (!skillInfo) - continue; - - if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) && - skillInfo->canLink) // only prof. with recipes have - { - HandleLearnSkillRecipesHelper(m_session->GetPlayer(),skillInfo->id); - } - } - - SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT); - return true; -} - -bool ChatHandler::HandleLearnAllRecipesCommand(const char* args) -{ - // Learns all recipes of specified profession and sets skill to max - // Example: .learn all_recipes enchanting - - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - return false; - } - - if (!*args) - return false; - - std::wstring wnamepart; - - if (!Utf8toWStr(args,wnamepart)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wnamepart); - - std::string name; - - SkillLineEntry const *targetSkillInfo = NULL; - for (uint32 i = 1; i < sSkillLineStore.GetNumRows(); ++i) - { - SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i); - if (!skillInfo) - continue; - - if ((skillInfo->categoryId != SKILL_CATEGORY_PROFESSION && - skillInfo->categoryId != SKILL_CATEGORY_SECONDARY) || - !skillInfo->canLink) // only prof with recipes have set - continue; - - int loc = GetSessionDbcLocale(); - name = skillInfo->name[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo(name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale()) - continue; - - name = skillInfo->name[loc]; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - targetSkillInfo = skillInfo; - break; - } - } - - if (!targetSkillInfo) - return false; - - HandleLearnSkillRecipesHelper(target,targetSkillInfo->id); - - uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id); - target->SetSkill(targetSkillInfo->id, target->GetSkillStep(targetSkillInfo->id), maxLevel, maxLevel); - PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str()); - return true; -} - -bool ChatHandler::HandleLookupPlayerIpCommand(const char* args) -{ - - if (!*args) - return false; - - std::string ip = strtok ((char*)args, " "); - char* limit_str = strtok (NULL, " "); - int32 limit = limit_str ? atoi (limit_str) : -1; - - LoginDatabase.escape_string (ip); - - QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ()); - - return LookupPlayerSearchCommand (result,limit); -} - -bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args) -{ - if (!*args) - return false; - - std::string account = strtok ((char*)args, " "); - char* limit_str = strtok (NULL, " "); - int32 limit = limit_str ? atoi (limit_str) : -1; - - if (!AccountMgr::normalizeString (account)) - return false; - - LoginDatabase.escape_string (account); - - QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ()); - - return LookupPlayerSearchCommand (result,limit); -} - -bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args) -{ - - if (!*args) - return false; - - std::string email = strtok ((char*)args, " "); - char* limit_str = strtok (NULL, " "); - int32 limit = limit_str ? atoi (limit_str) : -1; - - LoginDatabase.escape_string (email); - - QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ()); - - return LookupPlayerSearchCommand (result,limit); -} - -bool ChatHandler::LookupPlayerSearchCommand(QueryResult_AutoPtr result, int32 limit) -{ - if (!result) - { - PSendSysMessage(LANG_NO_PLAYERS_FOUND); - SetSentErrorMessage(true); - return false; - } - - int i =0; - do - { - Field* fields = result->Fetch(); - uint32 acc_id = fields[0].GetUInt32(); - std::string acc_name = fields[1].GetCppString(); - - QueryResult_AutoPtr chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id); - if (chars) - { - PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id); - - uint64 guid = 0; - std::string name; - - do - { - Field* charfields = chars->Fetch(); - guid = charfields[0].GetUInt64(); - name = charfields[1].GetCppString(); - - PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid); - ++i; - - } while (chars->NextRow() && (limit == -1 || i < limit)); - } - } while (result->NextRow()); - - if (i == 0) // empty accounts only - { - PSendSysMessage(LANG_NO_PLAYERS_FOUND); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -/// Triggering corpses expire check in world -bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/) -{ - CorpsesErase(); - return true; -} - -bool ChatHandler::HandleRepairitemsCommand(const char* args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - // Repair items - target->DurabilityRepairAll(false, 0, false); - - PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str()); - if (needReportToTarget(target)) - ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str()); - return true; -} - -bool ChatHandler::HandleWaterwalkCommand(const char* args) -{ - if (!*args) - return false; - - Player *player = getSelectedPlayer(); - - if (!player) - { - PSendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(player, 0)) - return false; - - if (strncmp(args, "on", 3) == 0) - player->SetMovement(MOVE_WATER_WALK); // ON - else if (strncmp(args, "off", 4) == 0) - player->SetMovement(MOVE_LAND_WALK); // OFF - else - { - SendSysMessage(LANG_USE_BOL); - return false; - } - - PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str()); - if (needReportToTarget(player)) - ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str()); - return true; -} - -bool ChatHandler::HandleCreatePetCommand(const char* /*args*/) -{ - Player *player = m_session->GetPlayer(); - Creature *creatureTarget = getSelectedCreature(); - - if (!creatureTarget || creatureTarget->isPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) - { - PSendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(creatureTarget->GetEntry()); - // Creatures with family 0 crashes the server - if (cInfo->family == 0) - { - PSendSysMessage("This creature cannot be tamed. (family id: 0)."); - SetSentErrorMessage(true); - return false; - } - - if (player->GetPetGUID()) - { - PSendSysMessage("You already have a pet"); - SetSentErrorMessage(true); - return false; - } - - // Everything looks OK, create new pet - Pet* pet = new Pet(player, HUNTER_PET); - - if (!pet) - return false; - - if (!pet->CreateBaseAtCreature(creatureTarget)) - { - delete pet; - PSendSysMessage("Error 1"); - return false; - } - - creatureTarget->setDeathState(JUST_DIED); - creatureTarget->RemoveCorpse(); - creatureTarget->SetHealth(0); // just for nice GM-mode view - - pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); - pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); - - if (!pet->InitStatsForLevel(creatureTarget->getLevel())) - { - sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); - PSendSysMessage("Error 2"); - delete pet; - return false; - } - - // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); - - pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true); - // this enables pet details window (Shift+P) - pet->InitPetCreateSpells(); - pet->SetHealth(pet->GetMaxHealth()); - - pet->GetMap()->Add(pet->ToCreature()); - - // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); - - player->SetMinion(pet, true); - pet->SavePetToDB(PET_SAVE_AS_CURRENT); - player->PetSpellInitialize(); - - return true; -} - -bool ChatHandler::HandlePetLearnCommand(const char* args) -{ - if (!*args) - return false; - - Player *plr = m_session->GetPlayer(); - Pet *pet = plr->GetPet(); - - if (!pet) - { - PSendSysMessage("You have no pet"); - SetSentErrorMessage(true); - return false; - } - - uint32 spellId = extractSpellIdFromLink((char*)args); - - if (!spellId || !sSpellStore.LookupEntry(spellId)) - return false; - - // Check if pet already has it - if (pet->HasSpell(spellId)) - { - PSendSysMessage("Pet already has spell: %u", spellId); - SetSentErrorMessage(true); - return false; - } - - // Check if spell is valid - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spellId); - SetSentErrorMessage(true); - return false; - } - - pet->learnSpell(spellId); - - PSendSysMessage("Pet has learned spell %u", spellId); - return true; -} - -bool ChatHandler::HandlePetUnlearnCommand(const char *args) -{ - if (!*args) - return false; - - Player *plr = m_session->GetPlayer(); - Pet *pet = plr->GetPet(); - - if (!pet) - { - PSendSysMessage("You have no pet"); - SetSentErrorMessage(true); - return false; - } - - uint32 spellId = extractSpellIdFromLink((char*)args); - - if (pet->HasSpell(spellId)) - pet->removeSpell(spellId, false); - else - PSendSysMessage("Pet doesn't have that spell"); - - return true; -} - -bool ChatHandler::HandlePetTpCommand(const char *args) -{ - if (!*args) - return false; - - Player *plr = m_session->GetPlayer(); - Pet *pet = plr->GetPet(); - - if (!pet) - { - PSendSysMessage("You have no pet"); - SetSentErrorMessage(true); - return false; - } - - uint32 tp = atol(args); - - //pet->SetTP(tp); - - PSendSysMessage("Pet's tp changed to %u", tp); - return true; -} - -bool ChatHandler::HandleActivateObjectCommand(const char *args) -{ - if (!*args) - return false; - - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if (!cId) - return false; - - uint32 lowguid = atoi(cId); - if (!lowguid) - return false; - - GameObject* obj = NULL; - - // by DB guid - if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) - obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); - - if (!obj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - // Activate - obj->SetLootState(GO_READY); - obj->UseDoorOrButton(10000); - - PSendSysMessage("Object activated!"); - - return true; -} - -// add creature, temp only -bool ChatHandler::HandleTempAddSpwCommand(const char* args) -{ - if (!*args) - return false; - char* charID = strtok((char*)args, " "); - if (!charID) - return false; - - Player *chr = m_session->GetPlayer(); - - uint32 id = atoi(charID); - if (!id) - return false; - - chr->SummonCreature(id, *chr, TEMPSUMMON_CORPSE_DESPAWN, 120); - - return true; -} - -// add go, temp only -bool ChatHandler::HandleTempGameObjectCommand(const char* args) -{ - if (!*args) - return false; - char* charID = strtok((char*)args, " "); - if (!charID) - return false; - - Player *chr = m_session->GetPlayer(); - - char* spawntime = strtok(NULL, " "); - uint32 spawntm = 300; - - if (spawntime) - spawntm = atoi((char*)spawntime); - - float x = chr->GetPositionX(); - float y = chr->GetPositionY(); - float z = chr->GetPositionZ(); - float ang = chr->GetOrientation(); - - float rot2 = sin(ang/2); - float rot3 = cos(ang/2); - - uint32 id = atoi(charID); - - chr->SummonGameObject(id,x,y,z,ang,0,0,rot2,rot3,spawntm); - - return true; -} - -bool ChatHandler::HandleNpcAddFormationCommand(const char* args) -{ - if (!*args) - return false; - - uint32 leaderGUID = (uint32) atoi((char*)args); - Creature *pCreature = getSelectedCreature(); - - if (!pCreature || !pCreature->GetDBTableGUIDLow()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - uint32 lowguid = pCreature->GetDBTableGUIDLow(); - if (pCreature->GetFormation()) - { - PSendSysMessage("Selected creature is already member of group %u", pCreature->GetFormation()->GetId()); - return false; - } - - if (!lowguid) - return false; - - Player *chr = m_session->GetPlayer(); - FormationInfo *group_member; - - group_member = new FormationInfo; - group_member->follow_angle = (pCreature->GetAngle(chr) - chr->GetOrientation()) * 180 / M_PI; - group_member->follow_dist = sqrtf(pow(chr->GetPositionX() - pCreature->GetPositionX(),int(2))+pow(chr->GetPositionY()-pCreature->GetPositionY(),int(2))); - group_member->leaderGUID = leaderGUID; - group_member->groupAI = 0; - - CreatureGroupMap[lowguid] = group_member; - pCreature->SearchFormation(); - - WorldDatabase.PExecuteLog("INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES ('%u','%u','%f', '%f', '%u')", - leaderGUID, lowguid, group_member->follow_dist, group_member->follow_angle, group_member->groupAI); - - PSendSysMessage("Creature %u added to formation with leader %u", lowguid, leaderGUID); - - return true; - } - -bool ChatHandler::HandleNpcSetLinkCommand(const char* args) -{ - if (!*args) - return false; - - uint32 linkguid = (uint32) atoi((char*)args); - - Creature* pCreature = getSelectedCreature(); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (!pCreature->GetDBTableGUIDLow()) - { - PSendSysMessage("Selected creature isn't in creature table", pCreature->GetGUIDLow()); - SetSentErrorMessage(true); - return false; - } - - if (!objmgr.SetCreatureLinkedRespawn(pCreature->GetDBTableGUIDLow(), linkguid)) - { - PSendSysMessage("Selected creature can't link with guid '%u'", linkguid); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage("LinkGUID '%u' added to creature with DBTableGUID: '%u'", linkguid, pCreature->GetDBTableGUIDLow()); - return true; -} - -bool ChatHandler::HandleLookupTitleCommand(const char* args) -{ - if (!*args) - return false; - - // can be NULL in console call - Player* target = getSelectedPlayer(); - - // title name have single string arg for player name - char const* targetName = target ? target->GetName() : "NAME"; - - std::string namepart = args; - std::wstring wnamepart; - - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wnamepart); - - uint32 counter = 0; // Counter for figure out that we found smth. - - // Search in CharTitles.dbc - for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) - { - CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id); - if (titleInfo) - { - int loc = GetSessionDbcLocale(); - std::string name = titleInfo->name[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo(name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale()) - continue; - - name = titleInfo->name[loc]; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - char const* knownStr = target && target->HasTitle(titleInfo) ? GetTrinityString(LANG_KNOWN) : ""; - - char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index - ? GetTrinityString(LANG_ACTIVE) - : ""; - - char titleNameStr[80]; - snprintf(titleNameStr,80,name.c_str(),targetName); - - // send title in "id (idx:idx) - [namedlink locale]" format - if (m_session) - PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr); - else - PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,titleNameStr,localeNames[loc],knownStr,activeStr); - - ++counter; - } - } - } - if (counter == 0) // if counter == 0 then we found nth - SendSysMessage(LANG_COMMAND_NOTITLEFOUND); - return true; -} - -bool ChatHandler::HandleTitlesAddCommand(const char* args) -{ - // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r - char* id_p = extractKeyFromLink((char*)args,"Htitle"); - if (!id_p) - return false; - - int32 id = atoi(id_p); - if (id <= 0) - { - PSendSysMessage(LANG_INVALID_TITLE_ID, id); - SetSentErrorMessage(true); - return false; - } - - Player * target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); - if (!titleInfo) - { - PSendSysMessage(LANG_INVALID_TITLE_ID, id); - SetSentErrorMessage(true); - return false; - } - - std::string tNameLink = GetNameLink(target); - - char const* targetName = target->GetName(); - char titleNameStr[80]; - snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName); - - target->SetTitle(titleInfo); - PSendSysMessage(LANG_TITLE_ADD_RES, id, titleNameStr, tNameLink.c_str()); - - return true; -} - -bool ChatHandler::HandleTitlesRemoveCommand(const char* args) -{ - // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r - char* id_p = extractKeyFromLink((char*)args,"Htitle"); - if (!id_p) - return false; - - int32 id = atoi(id_p); - if (id <= 0) - { - PSendSysMessage(LANG_INVALID_TITLE_ID, id); - SetSentErrorMessage(true); - return false; - } - - Player * target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); - if (!titleInfo) - { - PSendSysMessage(LANG_INVALID_TITLE_ID, id); - SetSentErrorMessage(true); - return false; - } - - target->SetTitle(titleInfo,true); - - std::string tNameLink = GetNameLink(target); - - char const* targetName = target->GetName(); - char titleNameStr[80]; - snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName); - - PSendSysMessage(LANG_TITLE_REMOVE_RES, id, titleNameStr, tNameLink.c_str()); - - if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE))) - { - target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0); - PSendSysMessage(LANG_CURRENT_TITLE_RESET, tNameLink.c_str()); - } - - return true; -} - -//Edit Player KnownTitles -bool ChatHandler::HandleTitlesSetMaskCommand(const char* args) -{ - if (!*args) - return false; - - uint64 titles = 0; - - sscanf((char*)args, UI64FMTD, &titles); - - Player *target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - uint64 titles2 = titles; - - for (uint32 i = 1; i < sCharTitlesStore.GetNumRows(); ++i) - if (CharTitlesEntry const* tEntry = sCharTitlesStore.LookupEntry(i)) - titles2 &= ~(uint64(1) << tEntry->bit_index); - - titles &= ~titles2; // remove not existed titles - - target->SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES, titles); - SendSysMessage(LANG_DONE); - - if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE))) - { - target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0); - PSendSysMessage(LANG_CURRENT_TITLE_RESET,GetNameLink(target).c_str()); - } - - return true; -} - -bool ChatHandler::HandleCharacterTitlesCommand(const char* args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - LocaleConstant loc = GetSessionDbcLocale(); - char const* targetName = target->GetName(); - char const* knownStr = GetTrinityString(LANG_KNOWN); - - // Search in CharTitles.dbc - for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) - { - CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id); - if (titleInfo && target->HasTitle(titleInfo)) - { - std::string name = titleInfo->name[loc]; - if (name.empty()) - continue; - - char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index - ? GetTrinityString(LANG_ACTIVE) - : ""; - - char titleNameStr[80]; - snprintf(titleNameStr,80,name.c_str(),targetName); - - // send title in "id (idx:idx) - [namedlink locale]" format - if (m_session) - PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr); - else - PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,name.c_str(),localeNames[loc],knownStr,activeStr); - } - } - return true; -} - -bool ChatHandler::HandleTitlesCurrentCommand(const char* args) -{ - // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r - char* id_p = extractKeyFromLink((char*)args,"Htitle"); - if (!id_p) - return false; - - int32 id = atoi(id_p); - if (id <= 0) - { - PSendSysMessage(LANG_INVALID_TITLE_ID, id); - SetSentErrorMessage(true); - return false; - } - - Player * target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); - if (!titleInfo) - { - PSendSysMessage(LANG_INVALID_TITLE_ID, id); - SetSentErrorMessage(true); - return false; - } - - std::string tNameLink = GetNameLink(target); - - target->SetTitle(titleInfo); // to be sure that title now known - target->SetUInt32Value(PLAYER_CHOSEN_TITLE,titleInfo->bit_index); - - PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name[GetSessionDbcLocale()], tNameLink.c_str()); - - return true; -} diff --git a/src/server/game/Chat/Level3.cpp b/src/server/game/Chat/Level3.cpp deleted file mode 100644 index f7ced44922b..00000000000 --- a/src/server/game/Chat/Level3.cpp +++ /dev/null @@ -1,7743 +0,0 @@ -/* -* Copyright (C) 2005-2009 MaNGOS -* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "AuctionHouseMgr.h" -#include "AccountMgr.h" -#include "PlayerDump.h" -#include "SpellMgr.h" -#include "Player.h" -#include "Opcodes.h" -#include "GameObject.h" -#include "Chat.h" -#include "Log.h" -#include "Guild.h" -#include "ObjectAccessor.h" -#include "MapManager.h" -#include "Language.h" -#include "GridNotifiersImpl.h" -#include "CellImpl.h" -#include "Weather.h" -#include "PointMovementGenerator.h" -#include "TargetedMovementGenerator.h" -#include "SkillDiscovery.h" -#include "SkillExtraItems.h" -#include "SystemConfig.h" -#include "Config/ConfigEnv.h" -#include "Util.h" -#include "ItemEnchantmentMgr.h" -#include "BattleGroundMgr.h" -#include "InstanceSaveMgr.h" -#include "InstanceData.h" -#include "AuctionHouseBot.h" -#include "CreatureEventAIMgr.h" -#include "SpellAuraEffects.h" -#include "DBCEnums.h" -#include "ConditionMgr.h" - -bool ChatHandler::HandleAHBotOptionsCommand(const char *args) -{ - uint32 ahMapID = 0; - char * opt = strtok((char*)args, " "); - char * ahMapIdStr = strtok(NULL, " "); - if (ahMapIdStr) - { - ahMapID = (uint32) strtoul(ahMapIdStr, NULL, 0); - switch (ahMapID) - { - case 2: - case 6: - case 7: - break; - default: - opt = NULL; - break; - } - } - if (!opt) - { - PSendSysMessage("Syntax is: ahbotoptions $option $ahMapID (2, 6 or 7) $parameter"); - PSendSysMessage("Try ahbotoptions help to see a list of options."); - return false; - } - int l = strlen(opt); - - if (strncmp(opt,"help",l) == 0) - { - PSendSysMessage("AHBot commands:"); - PSendSysMessage("ahexpire"); - PSendSysMessage("minitems"); - PSendSysMessage("maxitems"); - //PSendSysMessage(""); - //PSendSysMessage(""); - PSendSysMessage("percentages"); - PSendSysMessage("minprice"); - PSendSysMessage("maxprice"); - PSendSysMessage("minbidprice"); - PSendSysMessage("maxbidprice"); - PSendSysMessage("maxstack"); - PSendSysMessage("buyerprice"); - PSendSysMessage("bidinterval"); - PSendSysMessage("bidsperinterval"); - return true; - } - else if (strncmp(opt,"ahexpire",l) == 0) - { - if (!ahMapIdStr) - { - PSendSysMessage("Syntax is: ahbotoptions ahexpire $ahMapID (2, 6 or 7)"); - return false; - } - auctionbot.Commands(0, ahMapID, NULL, NULL); - } - else if (strncmp(opt,"minitems",l) == 0) - { - char * param1 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1)) - { - PSendSysMessage("Syntax is: ahbotoptions minitems $ahMapID (2, 6 or 7) $minItems"); - return false; - } - auctionbot.Commands(1, ahMapID, NULL, param1); - } - else if (strncmp(opt,"maxitems",l) == 0) - { - char * param1 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1)) - { - PSendSysMessage("Syntax is: ahbotoptions maxitems $ahMapID (2, 6 or 7) $maxItems"); - return false; - } - auctionbot.Commands(2, ahMapID, NULL, param1); - } - else if (strncmp(opt,"mintime",l) == 0) - { - PSendSysMessage("ahbotoptions mintime has been deprecated"); - return false; - /* - char * param1 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1)) - { - PSendSysMessage("Syntax is: ahbotoptions mintime $ahMapID (2, 6 or 7) $mintime"); - return false; - } - auctionbot.Commands(3, ahMapID, NULL, param1); - */ - } - else if (strncmp(opt,"maxtime",l) == 0) - { - PSendSysMessage("ahbotoptions maxtime has been deprecated"); - return false; - /* - char * param1 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1)) - { - PSendSysMessage("Syntax is: ahbotoptions maxtime $ahMapID (2, 6 or 7) $maxtime"); - return false; - } - auctionbot.Commands(4, ahMapID, NULL, param1); - */ - } - else if (strncmp(opt,"percentages",l) == 0) - { - char * param1 = strtok(NULL, " "); - char * param2 = strtok(NULL, " "); - char * param3 = strtok(NULL, " "); - char * param4 = strtok(NULL, " "); - char * param5 = strtok(NULL, " "); - char * param6 = strtok(NULL, " "); - char * param7 = strtok(NULL, " "); - char * param8 = strtok(NULL, " "); - char * param9 = strtok(NULL, " "); - char * param10 = strtok(NULL, " "); - char * param11 = strtok(NULL, " "); - char * param12 = strtok(NULL, " "); - char * param13 = strtok(NULL, " "); - char * param14 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param14)) - { - PSendSysMessage("Syntax is: ahbotoptions percentages $ahMapID (2, 6 or 7) $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14"); - PSendSysMessage("1 GreyTradeGoods 2 WhiteTradeGoods 3 GreenTradeGoods 4 BlueTradeGoods 5 PurpleTradeGoods"); - PSendSysMessage("6 OrangeTradeGoods 7 YellowTradeGoods 8 GreyItems 9 WhiteItems 10 GreenItems 11 BlueItems"); - PSendSysMessage("12 PurpleItems 13 OrangeItems 14 YellowItems"); - PSendSysMessage("The total must add up to 100%"); - return false; - } - uint32 greytg = (uint32) strtoul(param1, NULL, 0); - uint32 whitetg = (uint32) strtoul(param2, NULL, 0); - uint32 greentg = (uint32) strtoul(param3, NULL, 0); - uint32 bluetg = (uint32) strtoul(param3, NULL, 0); - uint32 purpletg = (uint32) strtoul(param5, NULL, 0); - uint32 orangetg = (uint32) strtoul(param6, NULL, 0); - uint32 yellowtg = (uint32) strtoul(param7, NULL, 0); - uint32 greyi = (uint32) strtoul(param8, NULL, 0); - uint32 whitei = (uint32) strtoul(param9, NULL, 0); - uint32 greeni = (uint32) strtoul(param10, NULL, 0); - uint32 bluei = (uint32) strtoul(param11, NULL, 0); - uint32 purplei = (uint32) strtoul(param12, NULL, 0); - uint32 orangei = (uint32) strtoul(param13, NULL, 0); - uint32 yellowi = (uint32) strtoul(param14, NULL, 0); - uint32 totalPercent = greytg + whitetg + greentg + bluetg + purpletg + orangetg + yellowtg + greyi + whitei + greeni + bluei + purplei + orangei + yellowi; - if ((totalPercent == 0) || (totalPercent != 100)) - { - PSendSysMessage("Syntax is: ahbotoptions percentages $ahMapID (2, 6 or 7) $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14"); - PSendSysMessage("1 GreyTradeGoods 2 WhiteTradeGoods 3 GreenTradeGoods 4 BlueTradeGoods 5 PurpleTradeGoods"); - PSendSysMessage("6 OrangeTradeGoods 7 YellowTradeGoods 8 GreyItems 9 WhiteItems 10 GreenItems 11 BlueItems"); - PSendSysMessage("12 PurpleItems 13 OrangeItems 14 YellowItems"); - PSendSysMessage("The total must add up to 100%"); - return false; - } - char param[100]; - param[0] = '\0'; - strcat(param, param1); - strcat(param, " "); - strcat(param, param2); - strcat(param, " "); - strcat(param, param3); - strcat(param, " "); - strcat(param, param4); - strcat(param, " "); - strcat(param, param5); - strcat(param, " "); - strcat(param, param6); - strcat(param, " "); - strcat(param, param7); - strcat(param, " "); - strcat(param, param8); - strcat(param, " "); - strcat(param, param9); - strcat(param, " "); - strcat(param, param10); - strcat(param, " "); - strcat(param, param11); - strcat(param, " "); - strcat(param, param12); - strcat(param, " "); - strcat(param, param13); - strcat(param, " "); - strcat(param, param14); - auctionbot.Commands(5, ahMapID, NULL, param); - } - else if (strncmp(opt,"minprice",l) == 0) - { - char * param1 = strtok(NULL, " "); - char * param2 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1) || (!param2)) - { - PSendSysMessage("Syntax is: ahbotoptions minprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); - return false; - } - if (strncmp(param1,"grey",l) == 0) - { - auctionbot.Commands(6, ahMapID, AHB_GREY, param2); - } - else if (strncmp(param1,"white",l) == 0) - { - auctionbot.Commands(6, ahMapID, AHB_WHITE, param2); - } - else if (strncmp(param1,"green",l) == 0) - { - auctionbot.Commands(6, ahMapID, AHB_GREEN, param2); - } - else if (strncmp(param1,"blue",l) == 0) - { - auctionbot.Commands(6, ahMapID, AHB_BLUE, param2); - } - else if (strncmp(param1,"purple",l) == 0) - { - auctionbot.Commands(6, ahMapID, AHB_PURPLE, param2); - } - else if (strncmp(param1,"orange",l) == 0) - { - auctionbot.Commands(6, ahMapID, AHB_ORANGE, param2); - } - else if (strncmp(param1,"yellow",l) == 0) - { - auctionbot.Commands(6, ahMapID, AHB_YELLOW, param2); - } - else - { - PSendSysMessage("Syntax is: ahbotoptions minprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); - return false; - } - } - else if (strncmp(opt,"maxprice",l) == 0) - { - char * param1 = strtok(NULL, " "); - char * param2 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1) || (!param2)) - { - PSendSysMessage("Syntax is: ahbotoptions maxprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); - return false; - } - if (strncmp(param1,"grey",l) == 0) - { - auctionbot.Commands(7, ahMapID, AHB_GREY, param2); - } - else if (strncmp(param1,"white",l) == 0) - { - auctionbot.Commands(7, ahMapID, AHB_WHITE, param2); - } - else if (strncmp(param1,"green",l) == 0) - { - auctionbot.Commands(7, ahMapID, AHB_GREEN, param2); - } - else if (strncmp(param1,"blue",l) == 0) - { - auctionbot.Commands(7, ahMapID, AHB_BLUE, param2); - } - else if (strncmp(param1,"purple",l) == 0) - { - auctionbot.Commands(7, ahMapID, AHB_PURPLE, param2); - } - else if (strncmp(param1,"orange",l) == 0) - { - auctionbot.Commands(7, ahMapID, AHB_ORANGE, param2); - } - else if (strncmp(param1,"yellow",l) == 0) - { - auctionbot.Commands(7, ahMapID, AHB_YELLOW, param2); - } - else - { - PSendSysMessage("Syntax is: ahbotoptions maxprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); - return false; - } - } - else if (strncmp(opt,"minbidprice",l) == 0) - { - char * param1 = strtok(NULL, " "); - char * param2 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1) || (!param2)) - { - PSendSysMessage("Syntax is: ahbotoptions minbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); - return false; - } - uint32 minBidPrice = (uint32) strtoul(param2, NULL, 0); - if ((minBidPrice < 1) || (minBidPrice > 100)) - { - PSendSysMessage("The min bid price multiplier must be between 1 and 100"); - return false; - } - if (strncmp(param1,"grey",l) == 0) - { - auctionbot.Commands(8, ahMapID, AHB_GREY, param2); - } - else if (strncmp(param1,"white",l) == 0) - { - auctionbot.Commands(8, ahMapID, AHB_WHITE, param2); - } - else if (strncmp(param1,"green",l) == 0) - { - auctionbot.Commands(8, ahMapID, AHB_GREEN, param2); - } - else if (strncmp(param1,"blue",l) == 0) - { - auctionbot.Commands(8, ahMapID, AHB_BLUE, param2); - } - else if (strncmp(param1,"purple",l) == 0) - { - auctionbot.Commands(8, ahMapID, AHB_PURPLE, param2); - } - else if (strncmp(param1,"orange",l) == 0) - { - auctionbot.Commands(8, ahMapID, AHB_ORANGE, param2); - } - else if (strncmp(param1,"yellow",l) == 0) - { - auctionbot.Commands(8, ahMapID, AHB_YELLOW, param2); - } - else - { - PSendSysMessage("Syntax is: ahbotoptions minbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); - return false; - } - } - else if (strncmp(opt,"maxbidprice",l) == 0) - { - char * param1 = strtok(NULL, " "); - char * param2 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1) || (!param2)) - { - PSendSysMessage("Syntax is: ahbotoptions maxbidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); - return false; - } - uint32 maxBidPrice = (uint32) strtoul(param2, NULL, 0); - if ((maxBidPrice < 1) || (maxBidPrice > 100)) - { - PSendSysMessage("The max bid price multiplier must be between 1 and 100"); - return false; - } - if (strncmp(param1,"grey",l) == 0) - { - auctionbot.Commands(9, ahMapID, AHB_GREY, param2); - } - else if (strncmp(param1,"white",l) == 0) - { - auctionbot.Commands(9, ahMapID, AHB_WHITE, param2); - } - else if (strncmp(param1,"green",l) == 0) - { - auctionbot.Commands(9, ahMapID, AHB_GREEN, param2); - } - else if (strncmp(param1,"blue",l) == 0) - { - auctionbot.Commands(9, ahMapID, AHB_BLUE, param2); - } - else if (strncmp(param1,"purple",l) == 0) - { - auctionbot.Commands(9, ahMapID, AHB_PURPLE, param2); - } - else if (strncmp(param1,"orange",l) == 0) - { - auctionbot.Commands(9, ahMapID, AHB_ORANGE, param2); - } - else if (strncmp(param1,"yellow",l) == 0) - { - auctionbot.Commands(9, ahMapID, AHB_YELLOW, param2); - } - else - { - PSendSysMessage("Syntax is: ahbotoptions max bidprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $price"); - return false; - } - } - else if (strncmp(opt,"maxstack",l) == 0) - { - char * param1 = strtok(NULL, " "); - char * param2 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1) || (!param2)) - { - PSendSysMessage("Syntax is: ahbotoptions maxstack $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $value"); - return false; - } - uint32 maxStack = (uint32) strtoul(param2, NULL, 0); - if (maxStack < 0) - { - PSendSysMessage("maxstack can't be a negative number."); - return false; - } - if (strncmp(param1,"grey",l) == 0) - { - auctionbot.Commands(10, ahMapID, AHB_GREY, param2); - } - else if (strncmp(param1,"white",l) == 0) - { - auctionbot.Commands(10, ahMapID, AHB_WHITE, param2); - } - else if (strncmp(param1,"green",l) == 0) - { - auctionbot.Commands(10, ahMapID, AHB_GREEN, param2); - } - else if (strncmp(param1,"blue",l) == 0) - { - auctionbot.Commands(10, ahMapID, AHB_BLUE, param2); - } - else if (strncmp(param1,"purple",l) == 0) - { - auctionbot.Commands(10, ahMapID, AHB_PURPLE, param2); - } - else if (strncmp(param1,"orange",l) == 0) - { - auctionbot.Commands(10, ahMapID, AHB_ORANGE, param2); - } - else if (strncmp(param1,"yellow",l) == 0) - { - auctionbot.Commands(10, ahMapID, AHB_YELLOW, param2); - } - else - { - PSendSysMessage("Syntax is: ahbotoptions maxstack $ahMapID (2, 6 or 7) $color (grey, white, green, blue, purple, orange or yellow) $value"); - return false; - } - } - else if (strncmp(opt,"buyerprice",l) == 0) - { - char * param1 = strtok(NULL, " "); - char * param2 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1) || (!param2)) - { - PSendSysMessage("Syntax is: ahbotoptions buyerprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue or purple) $price"); - return false; - } - if (strncmp(param1,"grey",l) == 0) - { - auctionbot.Commands(11, ahMapID, AHB_GREY, param2); - } - else if (strncmp(param1,"white",l) == 0) - { - auctionbot.Commands(11, ahMapID, AHB_WHITE, param2); - } - else if (strncmp(param1,"green",l) == 0) - { - auctionbot.Commands(11, ahMapID, AHB_GREEN, param2); - } - else if (strncmp(param1,"blue",l) == 0) - { - auctionbot.Commands(11, ahMapID, AHB_BLUE, param2); - } - else if (strncmp(param1,"purple",l) == 0) - { - auctionbot.Commands(11, ahMapID, AHB_PURPLE, param2); - } - else if (strncmp(param1,"orange",l) == 0) - { - auctionbot.Commands(11, ahMapID, AHB_ORANGE, param2); - } - else if (strncmp(param1,"yellow",l) == 0) - { - auctionbot.Commands(11, ahMapID, AHB_YELLOW, param2); - } - else - { - PSendSysMessage("Syntax is: ahbotoptions buyerprice $ahMapID (2, 6 or 7) $color (grey, white, green, blue or purple) $price"); - return false; - } - } - else if (strncmp(opt,"bidinterval",l) == 0) - { - char * param1 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1)) - { - PSendSysMessage("Syntax is: ahbotoptions bidinterval $ahMapID (2, 6 or 7) $interval(in minutes)"); - return false; - } - auctionbot.Commands(12, ahMapID, NULL, param1); - } - else if (strncmp(opt,"bidsperinterval",l) == 0) - { - char * param1 = strtok(NULL, " "); - if ((!ahMapIdStr) || (!param1)) - { - PSendSysMessage("Syntax is: ahbotoptions bidsperinterval $ahMapID (2, 6 or 7) $bids"); - return false; - } - auctionbot.Commands(13, ahMapID, NULL, param1); - } - else - { - PSendSysMessage("Syntax is: ahbotoptions $option $ahMapID (2, 6 or 7) $parameter"); - PSendSysMessage("Try ahbotoptions help to see a list of options."); - return false; - } - return true; -} - -//reload commands -bool ChatHandler::HandleReloadAllCommand(const char*) -{ - HandleReloadSkillFishingBaseLevelCommand(""); - - HandleReloadAllAchievementCommand(""); - HandleReloadAllAreaCommand(""); - HandleReloadAllEventAICommand(""); - HandleReloadAllLootCommand(""); - HandleReloadAllNpcCommand(""); - HandleReloadAllQuestCommand(""); - HandleReloadAllSpellCommand(""); - HandleReloadAllItemCommand(""); - HandleReloadAllLocalesCommand(""); - - HandleReloadAccessRequirementCommand(""); - HandleReloadMailLevelRewardCommand(""); - HandleReloadCommandCommand(""); - HandleReloadReservedNameCommand(""); - HandleReloadTrinityStringCommand(""); - HandleReloadGameTeleCommand(""); - - HandleReloadAutobroadcastCommand(""); - return true; -} - -bool ChatHandler::HandleReloadAllAchievementCommand(const char*) -{ - HandleReloadAchievementCriteriaDataCommand(""); - HandleReloadAchievementRewardCommand(""); - return true; -} - -bool ChatHandler::HandleReloadAllAreaCommand(const char*) -{ - //HandleReloadQuestAreaTriggersCommand(""); -- reloaded in HandleReloadAllQuestCommand - HandleReloadAreaTriggerTeleportCommand(""); - HandleReloadAreaTriggerTavernCommand(""); - HandleReloadGameGraveyardZoneCommand(""); - return true; -} - -bool ChatHandler::HandleReloadAllLootCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables..."); - LoadLootTables(); - SendGlobalGMSysMessage("DB tables `*_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/) -{ - HandleReloadNpcGossipCommand("a"); - HandleReloadNpcTrainerCommand("a"); - HandleReloadNpcVendorCommand("a"); - HandleReloadPointsOfInterestCommand("a"); - HandleReloadSpellClickSpellsCommand("a"); - return true; -} - -bool ChatHandler::HandleReloadAllQuestCommand(const char* /*args*/) -{ - HandleReloadQuestAreaTriggersCommand("a"); - HandleReloadQuestTemplateCommand("a"); - - sLog.outString("Re-Loading Quests Relations..."); - objmgr.LoadQuestRelations(); - SendGlobalGMSysMessage("DB tables `*_questrelation` and `*_involvedrelation` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadAllScriptsCommand(const char*) -{ - if (sWorld.IsScriptScheduled()) - { - PSendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - sLog.outString("Re-Loading Scripts..."); - HandleReloadGameObjectScriptsCommand("a"); - HandleReloadEventScriptsCommand("a"); - HandleReloadQuestEndScriptsCommand("a"); - HandleReloadQuestStartScriptsCommand("a"); - HandleReloadSpellScriptsCommand("a"); - SendGlobalGMSysMessage("DB tables `*_scripts` reloaded."); - HandleReloadDbScriptStringCommand("a"); - HandleReloadWpScriptsCommand("a"); - return true; -} - -bool ChatHandler::HandleReloadAllEventAICommand(const char*) -{ - HandleReloadEventAITextsCommand("a"); - HandleReloadEventAISummonsCommand("a"); - HandleReloadEventAIScriptsCommand("a"); - return true; -} - -bool ChatHandler::HandleReloadAllSpellCommand(const char*) -{ - HandleReloadSkillDiscoveryTemplateCommand("a"); - HandleReloadSkillExtraItemTemplateCommand("a"); - HandleReloadSpellRequiredCommand("a"); - HandleReloadSpellAreaCommand("a"); - HandleReloadSpellGroupsCommand("a"); - HandleReloadSpellLearnSpellCommand("a"); - HandleReloadSpellLinkedSpellCommand("a"); - HandleReloadSpellProcEventCommand("a"); - HandleReloadSpellBonusesCommand("a"); - HandleReloadSpellTargetPositionCommand("a"); - HandleReloadSpellThreatsCommand("a"); - HandleReloadSpellGroupStackRulesCommand("a"); - HandleReloadSpellPetAurasCommand("a"); - HandleReloadSpellDisabledCommand("a"); - return true; -} - -bool ChatHandler::HandleReloadAllItemCommand(const char*) -{ - HandleReloadPageTextsCommand("a"); - HandleReloadItemEnchantementsCommand("a"); - return true; -} - -bool ChatHandler::HandleReloadAllLocalesCommand(const char* /*args*/) -{ - HandleReloadLocalesAchievementRewardCommand("a"); - HandleReloadLocalesCreatureCommand("a"); - HandleReloadLocalesGameobjectCommand("a"); - HandleReloadLocalesItemCommand("a"); - HandleReloadLocalesNpcTextCommand("a"); - HandleReloadLocalesPageTextCommand("a"); - HandleReloadLocalesPointsOfInterestCommand("a"); - HandleReloadLocalesQuestCommand("a"); - return true; -} - -bool ChatHandler::HandleReloadConfigCommand(const char* /*args*/) -{ - sLog.outString("Re-Loading config settings..."); - sWorld.LoadConfigSettings(true); - MapManager::Instance().InitializeVisibilityDistanceInfo(); - SendGlobalGMSysMessage("World config settings reloaded."); - return true; -} - -bool ChatHandler::HandleReloadAccessRequirementCommand(const char*) -{ - sLog.outString("Re-Loading Access Requirement definitions..."); - objmgr.LoadAccessRequirements(); - SendGlobalGMSysMessage("DB table `access_requirement` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadAchievementCriteriaDataCommand(const char*) -{ - sLog.outString("Re-Loading Additional Achievement Criteria Data..."); - achievementmgr.LoadAchievementCriteriaData(); - SendGlobalGMSysMessage("DB table `achievement_criteria_data` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadAchievementRewardCommand(const char*) -{ - sLog.outString("Re-Loading Achievement Reward Data..."); - achievementmgr.LoadRewards(); - SendGlobalGMSysMessage("DB table `achievement_reward` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadAreaTriggerTavernCommand(const char*) -{ - sLog.outString("Re-Loading Tavern Area Triggers..."); - objmgr.LoadTavernAreaTriggers(); - SendGlobalGMSysMessage("DB table `areatrigger_tavern` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadAreaTriggerTeleportCommand(const char*) -{ - sLog.outString("Re-Loading AreaTrigger teleport definitions..."); - objmgr.LoadAreaTriggerTeleports(); - SendGlobalGMSysMessage("DB table `areatrigger_teleport` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadAutobroadcastCommand(const char*) -{ - sLog.outString("Re-Loading Autobroadcast..."); - sWorld.LoadAutobroadcasts(); - SendGlobalGMSysMessage("DB table `autobroadcast` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadCommandCommand(const char*) -{ - load_command_table = true; - SendGlobalGMSysMessage("DB table `command` will be reloaded at next chat command use."); - return true; -} - -bool ChatHandler::HandleReloadCreatureTemplateCommand(const char* args) -{ - if (!*args) - return false; - - uint32 entry = (uint32) atoi((char*)args); - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT difficulty_entry_1,difficulty_entry_2,difficulty_entry_3,KillCredit1,KillCredit2,modelid1,modelid2,modelid3,modelid4,name,subname,IconName,gossip_menu_id,minlevel,maxlevel,exp,faction_A,faction_H,npcflag,speed_walk,speed_run,scale,rank,mindmg,maxdmg,dmgschool,attackpower,dmg_multiplier,baseattacktime,rangeattacktime,unit_class,unit_flags,dynamicflags,family,trainer_type,trainer_spell,trainer_class,trainer_race,minrangedmg,maxrangedmg,rangedattackpower,type,type_flags,lootid,pickpocketloot,skinloot,resistance1,resistance2,resistance3,resistance4,resistance5,resistance6,spell1,spell2,spell3,spell4,spell5,spell6,spell7,spell8,PetSpellDataId,VehicleId,mingold,maxgold,AIName,MovementType,InhabitType,Health_mod,Mana_mod,Armor_mod,RacialLeader,questItem1,questItem2,questItem3,questItem4,questItem5,questItem6,movementId,RegenHealth,equipment_id,mechanic_immune_mask,flags_extra,ScriptName FROM creature_template WHERE entry = %u", entry); - if (!result) - { - PSendSysMessage(LANG_COMMAND_CREATURETEMPLATE_NOTFOUND, entry); - SetSentErrorMessage(true); - return false; - } - - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); - if (!cInfo) - { - PSendSysMessage(LANG_COMMAND_CREATURESTORAGE_NOTFOUND, entry); - SetSentErrorMessage(true); - return false; - } - - sLog.outString("Reloading creature template entry %u", entry); - - Field *fields = result->Fetch(); - - const_cast(cInfo)->DifficultyEntry[0] = fields[0].GetUInt32(); - const_cast(cInfo)->DifficultyEntry[1] = fields[1].GetUInt32(); - const_cast(cInfo)->DifficultyEntry[2] = fields[2].GetUInt32(); - const_cast(cInfo)->KillCredit[0] = fields[3].GetUInt32(); - const_cast(cInfo)->KillCredit[1] = fields[4].GetUInt32(); - const_cast(cInfo)->Modelid1 = fields[5].GetUInt32(); - const_cast(cInfo)->Modelid2 = fields[6].GetUInt32(); - const_cast(cInfo)->Modelid3 = fields[7].GetUInt32(); - const_cast(cInfo)->Modelid4 = fields[8].GetUInt32(); - size_t len = 0; - if (const char* temp = fields[9].GetString()) - { - if (cInfo->Name) - delete cInfo->Name; - len = strlen(temp)+1; - const_cast(cInfo)->Name = new char[len]; - strncpy(cInfo->Name, temp, len); - } - if (const char* temp = fields[10].GetString()) - { - if (cInfo->SubName) - delete cInfo->SubName; - len = strlen(temp)+1; - const_cast(cInfo)->SubName = new char[len]; - strncpy(cInfo->SubName, temp, len); - } - if (const char* temp = fields[11].GetString()) - { - if (cInfo->IconName) - delete cInfo->IconName; - len = strlen(temp)+1; - const_cast(cInfo)->IconName = new char[len]; - strncpy(cInfo->IconName, temp, len); - } - const_cast(cInfo)->GossipMenuId = fields[12].GetUInt32(); - const_cast(cInfo)->minlevel = fields[13].GetUInt32(); - const_cast(cInfo)->maxlevel = fields[14].GetUInt32(); - const_cast(cInfo)->expansion = fields[15].GetUInt32(); - const_cast(cInfo)->faction_A = fields[16].GetUInt32(); - const_cast(cInfo)->faction_H = fields[17].GetUInt32(); - const_cast(cInfo)->npcflag = fields[18].GetUInt32(); - const_cast(cInfo)->speed_walk = fields[19].GetFloat(); - const_cast(cInfo)->speed_run = fields[20].GetFloat(); - const_cast(cInfo)->scale = fields[21].GetFloat(); - const_cast(cInfo)->rank = fields[22].GetUInt32(); - const_cast(cInfo)->mindmg = fields[23].GetFloat(); - const_cast(cInfo)->maxdmg = fields[24].GetFloat(); - const_cast(cInfo)->dmgschool = fields[25].GetUInt32(); - const_cast(cInfo)->attackpower = fields[26].GetUInt32(); - const_cast(cInfo)->dmg_multiplier = fields[27].GetFloat(); - const_cast(cInfo)->baseattacktime = fields[28].GetUInt32(); - const_cast(cInfo)->rangeattacktime = fields[29].GetUInt32(); - const_cast(cInfo)->unit_class = fields[30].GetUInt32(); - const_cast(cInfo)->unit_flags = fields[31].GetUInt32(); - const_cast(cInfo)->dynamicflags = fields[32].GetUInt32(); - const_cast(cInfo)->family = fields[33].GetUInt32(); - const_cast(cInfo)->trainer_type = fields[34].GetUInt32(); - const_cast(cInfo)->trainer_spell = fields[35].GetUInt32(); - const_cast(cInfo)->trainer_class = fields[36].GetUInt32(); - const_cast(cInfo)->trainer_race = fields[37].GetUInt32(); - const_cast(cInfo)->minrangedmg = fields[38].GetFloat(); - const_cast(cInfo)->maxrangedmg = fields[39].GetFloat(); - const_cast(cInfo)->rangedattackpower = fields[40].GetUInt32(); - const_cast(cInfo)->type = fields[41].GetUInt32(); - const_cast(cInfo)->type_flags = fields[42].GetUInt32(); - const_cast(cInfo)->lootid = fields[43].GetUInt32(); - const_cast(cInfo)->pickpocketLootId = fields[44].GetUInt32(); - const_cast(cInfo)->SkinLootId = fields[45].GetUInt32(); - const_cast(cInfo)->resistance1 = fields[46].GetUInt32(); - const_cast(cInfo)->resistance2 = fields[47].GetUInt32(); - const_cast(cInfo)->resistance3 = fields[48].GetUInt32(); - const_cast(cInfo)->resistance4 = fields[49].GetUInt32(); - const_cast(cInfo)->resistance5 = fields[50].GetUInt32(); - const_cast(cInfo)->resistance6 = fields[51].GetUInt32(); - const_cast(cInfo)->spells[0] = fields[52].GetUInt32(); - const_cast(cInfo)->spells[1] = fields[53].GetUInt32(); - const_cast(cInfo)->spells[2] = fields[54].GetUInt32(); - const_cast(cInfo)->spells[3] = fields[55].GetUInt32(); - const_cast(cInfo)->spells[4] = fields[56].GetUInt32(); - const_cast(cInfo)->spells[5] = fields[57].GetUInt32(); - const_cast(cInfo)->spells[6] = fields[58].GetUInt32(); - const_cast(cInfo)->spells[7] = fields[59].GetUInt32(); - const_cast(cInfo)->PetSpellDataId = fields[60].GetUInt32(); - const_cast(cInfo)->VehicleId = fields[61].GetUInt32(); - const_cast(cInfo)->mingold = fields[62].GetUInt32(); - const_cast(cInfo)->maxgold = fields[63].GetUInt32(); - if (const char* temp = fields[64].GetString()) - { - if (cInfo->AIName) - delete cInfo->AIName; - len = strlen(temp)+1; - const_cast(cInfo)->AIName = new char[len]; - strncpy(const_cast(cInfo->AIName), temp, len); - } - const_cast(cInfo)->MovementType = fields[65].GetUInt32(); - const_cast(cInfo)->InhabitType = fields[66].GetUInt32(); - const_cast(cInfo)->ModHealth = fields[67].GetFloat(); - const_cast(cInfo)->ModMana = fields[68].GetFloat(); - const_cast(cInfo)->ModArmor = fields[69].GetFloat(); - const_cast(cInfo)->RacialLeader = fields[70].GetBool(); - const_cast(cInfo)->questItems[0] = fields[71].GetUInt32(); - const_cast(cInfo)->questItems[1] = fields[72].GetUInt32(); - const_cast(cInfo)->questItems[2] = fields[73].GetUInt32(); - const_cast(cInfo)->questItems[3] = fields[74].GetUInt32(); - const_cast(cInfo)->questItems[4] = fields[75].GetUInt32(); - const_cast(cInfo)->questItems[5] = fields[76].GetUInt32(); - const_cast(cInfo)->movementId = fields[77].GetUInt32(); - const_cast(cInfo)->RegenHealth = fields[78].GetBool(); - const_cast(cInfo)->equipmentId = fields[79].GetUInt32(); - const_cast(cInfo)->MechanicImmuneMask = fields[80].GetUInt32(); - const_cast(cInfo)->flags_extra = fields[81].GetUInt32(); - const_cast(cInfo)->ScriptID = objmgr.GetScriptId(fields[82].GetString()); - - objmgr.CheckCreatureTemplate(cInfo); - - SendGlobalGMSysMessage("Creature template reloaded."); - return true; -} - -bool ChatHandler::HandleReloadCreatureQuestRelationsCommand(const char*) -{ - sLog.outString("Loading Quests Relations... (`creature_questrelation`)"); - objmgr.LoadCreatureQuestRelations(); - SendGlobalGMSysMessage("DB table `creature_questrelation` (creature quest givers) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadCreatureLinkedRespawnCommand(const char * /*args*/) -{ - sLog.outString("Loading Linked Respawns... (`creature_linked_respawn`)"); - objmgr.LoadCreatureLinkedRespawn(); - SendGlobalGMSysMessage("DB table `creature_linked_respawn` (creature linked respawns) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadCreatureQuestInvRelationsCommand(const char*) -{ - sLog.outString("Loading Quests Relations... (`creature_involvedrelation`)"); - objmgr.LoadCreatureInvolvedRelations(); - SendGlobalGMSysMessage("DB table `creature_involvedrelation` (creature quest takers) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadGossipMenuCommand(const char*) -{ - sLog.outString("Re-Loading `gossip_menu` Table!"); - objmgr.LoadGossipMenu(); - SendGlobalGMSysMessage("DB table `gossip_menu` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadGossipMenuOptionCommand(const char*) -{ - sLog.outString("Re-Loading `gossip_menu_option` Table!"); - objmgr.LoadGossipMenuItems(); - SendGlobalGMSysMessage("DB table `gossip_menu_option` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadGOQuestRelationsCommand(const char*) -{ - sLog.outString("Loading Quests Relations... (`gameobject_questrelation`)"); - objmgr.LoadGameobjectQuestRelations(); - SendGlobalGMSysMessage("DB table `gameobject_questrelation` (gameobject quest givers) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadGOQuestInvRelationsCommand(const char*) -{ - sLog.outString("Loading Quests Relations... (`gameobject_involvedrelation`)"); - objmgr.LoadGameobjectInvolvedRelations(); - SendGlobalGMSysMessage("DB table `gameobject_involvedrelation` (gameobject quest takers) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadQuestAreaTriggersCommand(const char*) -{ - sLog.outString("Re-Loading Quest Area Triggers..."); - objmgr.LoadQuestAreaTriggers(); - SendGlobalGMSysMessage("DB table `areatrigger_involvedrelation` (quest area triggers) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadQuestTemplateCommand(const char*) -{ - sLog.outString("Re-Loading Quest Templates..."); - objmgr.LoadQuests(); - SendGlobalGMSysMessage("DB table `quest_template` (quest definitions) reloaded."); - - /// dependent also from `gameobject` but this table not reloaded anyway - sLog.outString("Re-Loading GameObjects for quests..."); - objmgr.LoadGameObjectForQuests(); - SendGlobalGMSysMessage("Data GameObjects for quests reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesCreatureCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`creature_loot_template`)"); - LoadLootTemplates_Creature(); - LootTemplates_Creature.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `creature_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesDisenchantCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`disenchant_loot_template`)"); - LoadLootTemplates_Disenchant(); - LootTemplates_Disenchant.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `disenchant_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesFishingCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`fishing_loot_template`)"); - LoadLootTemplates_Fishing(); - LootTemplates_Fishing.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `fishing_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesGameobjectCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`gameobject_loot_template`)"); - LoadLootTemplates_Gameobject(); - LootTemplates_Gameobject.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `gameobject_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`item_loot_template`)"); - LoadLootTemplates_Item(); - LootTemplates_Item.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `item_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesMillingCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`milling_loot_template`)"); - LoadLootTemplates_Milling(); - LootTemplates_Milling.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `milling_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`pickpocketing_loot_template`)"); - LoadLootTemplates_Pickpocketing(); - LootTemplates_Pickpocketing.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `pickpocketing_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesProspectingCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`prospecting_loot_template`)"); - LoadLootTemplates_Prospecting(); - LootTemplates_Prospecting.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `prospecting_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesMailCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`mail_loot_template`)"); - LoadLootTemplates_Mail(); - LootTemplates_Mail.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `mail_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesReferenceCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`reference_loot_template`)"); - LoadLootTemplates_Reference(); - SendGlobalGMSysMessage("DB table `reference_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`skinning_loot_template`)"); - LoadLootTemplates_Skinning(); - LootTemplates_Skinning.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `skinning_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadLootTemplatesSpellCommand(const char*) -{ - sLog.outString("Re-Loading Loot Tables... (`spell_loot_template`)"); - LoadLootTemplates_Spell(); - LootTemplates_Spell.CheckLootRefs(); - SendGlobalGMSysMessage("DB table `spell_loot_template` reloaded."); - sConditionMgr.LoadConditions(true); - return true; -} - -bool ChatHandler::HandleReloadTrinityStringCommand(const char*) -{ - sLog.outString("Re-Loading trinity_string Table!"); - objmgr.LoadTrinityStrings(); - SendGlobalGMSysMessage("DB table `trinity_string` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadNpcGossipCommand(const char*) -{ - sLog.outString("Re-Loading `npc_gossip` Table!"); - objmgr.LoadNpcTextId(); - SendGlobalGMSysMessage("DB table `npc_gossip` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadNpcTrainerCommand(const char*) -{ - sLog.outString("Re-Loading `npc_trainer` Table!"); - objmgr.LoadTrainerSpell(); - SendGlobalGMSysMessage("DB table `npc_trainer` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadNpcVendorCommand(const char*) -{ - sLog.outString("Re-Loading `npc_vendor` Table!"); - objmgr.LoadVendors(); - SendGlobalGMSysMessage("DB table `npc_vendor` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadPointsOfInterestCommand(const char*) -{ - sLog.outString("Re-Loading `points_of_interest` Table!"); - objmgr.LoadPointsOfInterest(); - SendGlobalGMSysMessage("DB table `points_of_interest` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellClickSpellsCommand(const char*) -{ - sLog.outString("Re-Loading `npc_spellclick_spells` Table!"); - objmgr.LoadNPCSpellClickSpells(); - SendGlobalGMSysMessage("DB table `npc_spellclick_spells` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadReservedNameCommand(const char*) -{ - sLog.outString("Loading ReservedNames... (`reserved_name`)"); - objmgr.LoadReservedPlayersNames(); - SendGlobalGMSysMessage("DB table `reserved_name` (player reserved names) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSkillDiscoveryTemplateCommand(const char* /*args*/) -{ - sLog.outString("Re-Loading Skill Discovery Table..."); - LoadSkillDiscoveryTable(); - SendGlobalGMSysMessage("DB table `skill_discovery_template` (recipes discovered at crafting) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSkillExtraItemTemplateCommand(const char* /*args*/) -{ - sLog.outString("Re-Loading Skill Extra Item Table..."); - LoadSkillExtraItemTable(); - SendGlobalGMSysMessage("DB table `skill_extra_item_template` (extra item creation when crafting) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSkillFishingBaseLevelCommand(const char* /*args*/) -{ - sLog.outString("Re-Loading Skill Fishing base level requirements..."); - objmgr.LoadFishingBaseSkillLevel(); - SendGlobalGMSysMessage("DB table `skill_fishing_base_level` (fishing base level for zone/subzone) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellAreaCommand(const char*) -{ - sLog.outString("Re-Loading SpellArea Data..."); - spellmgr.LoadSpellAreas(); - SendGlobalGMSysMessage("DB table `spell_area` (spell dependences from area/quest/auras state) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellRequiredCommand(const char*) -{ - sLog.outString("Re-Loading Spell Required Data... "); - spellmgr.LoadSpellRequired(); - SendGlobalGMSysMessage("DB table `spell_required` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellGroupsCommand(const char*) -{ - sLog.outString("Re-Loading Spell Groups..."); - spellmgr.LoadSpellGroups(); - SendGlobalGMSysMessage("DB table `spell_group` (spell groups) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellLearnSpellCommand(const char*) -{ - sLog.outString("Re-Loading Spell Learn Spells..."); - spellmgr.LoadSpellLearnSpells(); - SendGlobalGMSysMessage("DB table `spell_learn_spell` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellLinkedSpellCommand(const char*) -{ - sLog.outString("Re-Loading Spell Linked Spells..."); - spellmgr.LoadSpellLinked(); - SendGlobalGMSysMessage("DB table `spell_linked_spell` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellProcEventCommand(const char*) -{ - sLog.outString("Re-Loading Spell Proc Event conditions..."); - spellmgr.LoadSpellProcEvents(); - SendGlobalGMSysMessage("DB table `spell_proc_event` (spell proc trigger requirements) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellBonusesCommand(const char*) -{ - sLog.outString("Re-Loading Spell Bonus Data..."); - spellmgr.LoadSpellBonusess(); - SendGlobalGMSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellTargetPositionCommand(const char*) -{ - sLog.outString("Re-Loading Spell target coordinates..."); - spellmgr.LoadSpellTargetPositions(); - SendGlobalGMSysMessage("DB table `spell_target_position` (destination coordinates for spell targets) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellThreatsCommand(const char*) -{ - sLog.outString("Re-Loading Aggro Spells Definitions..."); - spellmgr.LoadSpellThreats(); - SendGlobalGMSysMessage("DB table `spell_threat` (spell aggro definitions) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellGroupStackRulesCommand(const char*) -{ - sLog.outString("Re-Loading Spell Group Stack Rules..."); - spellmgr.LoadSpellGroupStackRules(); - SendGlobalGMSysMessage("DB table `spell_group_stack_rules` (spell stacking definitions) reloaded."); - return true; -} - -bool ChatHandler::HandleReloadSpellPetAurasCommand(const char*) -{ - sLog.outString("Re-Loading Spell pet auras..."); - spellmgr.LoadSpellPetAuras(); - SendGlobalGMSysMessage("DB table `spell_pet_auras` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadPageTextsCommand(const char*) -{ - sLog.outString("Re-Loading Page Texts..."); - objmgr.LoadPageTexts(); - SendGlobalGMSysMessage("DB table `page_texts` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadItemEnchantementsCommand(const char*) -{ - sLog.outString("Re-Loading Item Random Enchantments Table..."); - LoadRandomEnchantmentsTable(); - SendGlobalGMSysMessage("DB table `item_enchantment_template` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadGameObjectScriptsCommand(const char* arg) -{ - if (sWorld.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*arg != 'a') - sLog.outString("Re-Loading Scripts from `gameobject_scripts`..."); - - objmgr.LoadGameObjectScripts(); - - if (*arg != 'a') - SendGlobalGMSysMessage("DB table `gameobject_scripts` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadEventScriptsCommand(const char* arg) -{ - if (sWorld.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*arg != 'a') - sLog.outString("Re-Loading Scripts from `event_scripts`..."); - - objmgr.LoadEventScripts(); - - if (*arg != 'a') - SendGlobalGMSysMessage("DB table `event_scripts` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadWpScriptsCommand(const char* arg) -{ - if (sWorld.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*arg != 'a') - sLog.outString("Re-Loading Scripts from `waypoint_scripts`..."); - - objmgr.LoadWaypointScripts(); - - if (*arg != 'a') - SendGlobalGMSysMessage("DB table `waypoint_scripts` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadEventAITextsCommand(const char* /*args*/) -{ - - sLog.outString("Re-Loading Texts from `creature_ai_texts`..."); - CreatureEAI_Mgr.LoadCreatureEventAI_Texts(); - SendGlobalGMSysMessage("DB table `creature_ai_texts` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadEventAISummonsCommand(const char* /*args*/) -{ - sLog.outString("Re-Loading Summons from `creature_ai_summons`..."); - CreatureEAI_Mgr.LoadCreatureEventAI_Summons(); - SendGlobalGMSysMessage("DB table `creature_ai_summons` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadEventAIScriptsCommand(const char* /*args*/) -{ - sLog.outString("Re-Loading Scripts from `creature_ai_scripts`..."); - CreatureEAI_Mgr.LoadCreatureEventAI_Scripts(); - SendGlobalGMSysMessage("DB table `creature_ai_scripts` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadQuestEndScriptsCommand(const char* arg) -{ - if (sWorld.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*arg != 'a') - sLog.outString("Re-Loading Scripts from `quest_end_scripts`..."); - - objmgr.LoadQuestEndScripts(); - - if (*arg != 'a') - SendGlobalGMSysMessage("DB table `quest_end_scripts` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadQuestStartScriptsCommand(const char* arg) -{ - if (sWorld.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*arg != 'a') - sLog.outString("Re-Loading Scripts from `quest_start_scripts`..."); - - objmgr.LoadQuestStartScripts(); - - if (*arg != 'a') - SendGlobalGMSysMessage("DB table `quest_start_scripts` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadSpellScriptsCommand(const char* arg) -{ - if (sWorld.IsScriptScheduled()) - { - SendSysMessage("DB scripts used currently, please attempt reload later."); - SetSentErrorMessage(true); - return false; - } - - if (*arg != 'a') - sLog.outString("Re-Loading Scripts from `spell_scripts`..."); - - objmgr.LoadSpellScripts(); - - if (*arg != 'a') - SendGlobalGMSysMessage("DB table `spell_scripts` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadDbScriptStringCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Script strings from `db_script_string`..."); - objmgr.LoadDbScriptStrings(); - SendGlobalGMSysMessage("DB table `db_script_string` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadGameGraveyardZoneCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Graveyard-zone links..."); - - objmgr.LoadGraveyardZones(); - - SendGlobalGMSysMessage("DB table `game_graveyard_zone` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadGameTeleCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Game Tele coordinates..."); - - objmgr.LoadGameTele(); - - SendGlobalGMSysMessage("DB table `game_tele` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadSpellDisabledCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading spell disabled table..."); - - objmgr.LoadSpellDisabledEntrys(); - - SendGlobalGMSysMessage("DB table `spell_disabled` reloaded."); - - return true; -} - -bool ChatHandler::HandleReloadLocalesAchievementRewardCommand(const char*) -{ - sLog.outString("Re-Loading Locales Achievement Reward Data..."); - achievementmgr.LoadRewardLocales(); - SendGlobalGMSysMessage("DB table `locales_achievement_reward` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLocalesCreatureCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Locales Creature ..."); - objmgr.LoadCreatureLocales(); - SendGlobalGMSysMessage("DB table `locales_creature` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLocalesGameobjectCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Locales Gameobject ... "); - objmgr.LoadGameObjectLocales(); - SendGlobalGMSysMessage("DB table `locales_gameobject` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLocalesItemCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Locales Item ... "); - objmgr.LoadItemLocales(); - SendGlobalGMSysMessage("DB table `locales_item` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLocalesNpcTextCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Locales NPC Text ... "); - objmgr.LoadNpcTextLocales(); - SendGlobalGMSysMessage("DB table `locales_npc_text` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLocalesPageTextCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Locales Page Text ... "); - objmgr.LoadPageTextLocales(); - SendGlobalGMSysMessage("DB table `locales_page_text` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLocalesPointsOfInterestCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Locales Points Of Interest ... "); - objmgr.LoadPointOfInterestLocales(); - SendGlobalGMSysMessage("DB table `locales_points_of_interest` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadLocalesQuestCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Locales Quest ... "); - objmgr.LoadQuestLocales(); - SendGlobalGMSysMessage("DB table `locales_quest` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadMailLevelRewardCommand(const char* /*arg*/) -{ - sLog.outString("Re-Loading Player level dependent mail rewards..."); - objmgr.LoadMailLevelRewards(); - SendGlobalGMSysMessage("DB table `mail_level_reward` reloaded."); - return true; -} - -bool ChatHandler::HandleReloadAuctionsCommand(const char * /*args*/) -{ - ///- Reload dynamic data tables from the database - sLog.outString("Re-Loading Auctions..."); - auctionmgr.LoadAuctionItems(); - auctionmgr.LoadAuctions(); - SendGlobalGMSysMessage("Auctions reloaded."); - return true; -} - -bool ChatHandler::HandleReloadConditions(const char* args) -{ - sLog.outString("Re-Loading Conditions..."); - sConditionMgr.LoadConditions(true); - SendGlobalGMSysMessage("Conditions reloaded."); - return true; -} - -bool ChatHandler::HandleAccountSetGmLevelCommand(const char *args) -{ - if (!*args) - return false; - - std::string targetAccountName; - uint32 targetAccountId = 0; - uint32 targetSecurity = 0; - uint32 gm = 0; - char* arg1 = strtok((char*)args, " "); - char* arg2 = strtok(NULL, " "); - char* arg3 = strtok(NULL, " "); - bool isAccountNameGiven = true; - - if (arg1 && !arg3) - { - if (!getSelectedPlayer()) - return false; - isAccountNameGiven = false; - } - - // Check for second parameter - if (!isAccountNameGiven && !arg2) - return false; - - // Check for account - if (isAccountNameGiven) - { - targetAccountName = arg1; - if (!AccountMgr::normalizeString(targetAccountName)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,targetAccountName.c_str()); - SetSentErrorMessage(true); - return false; - } - } - - // Check for invalid specified GM level. - gm = (isAccountNameGiven) ? atoi(arg2) : atoi(arg1); - if (gm < SEC_PLAYER) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - // m_session == NULL only for console - targetAccountId = (isAccountNameGiven) ? accmgr.GetId(targetAccountName) : getSelectedPlayer()->GetSession()->GetAccountId(); - int32 gmRealmID = (isAccountNameGiven) ? atoi(arg3) : atoi(arg2); - uint32 plSecurity = m_session ? accmgr.GetSecurity(m_session->GetAccountId(), gmRealmID) : SEC_CONSOLE; - - // can set security level only for target with less security and to less security that we have - // This is also reject self apply in fact - targetSecurity = accmgr.GetSecurity(targetAccountId, gmRealmID); - if (targetSecurity >= plSecurity || gm >= plSecurity) - { - SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); - SetSentErrorMessage(true); - return false; - } - - // Check and abort if the target gm has a higher rank on one of the realms and the new realm is -1 - if (gmRealmID == -1) - { - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT * FROM account_access WHERE id = '%u' AND gmlevel > '%d'", targetAccountId, gm); - if (result) - { - SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); - SetSentErrorMessage(true); - return false; - } - } - - // Check if provided realmID has a negative value other than -1 - if (gmRealmID < -1) - { - SendSysMessage(LANG_INVALID_REALMID); - SetSentErrorMessage(true); - return false; - } - - // If gmRealmID is -1, delete all values for the account id, else, insert values for the specific realmID - if (gmRealmID == -1) - LoginDatabase.PExecute("DELETE FROM account_access WHERE id = '%u'", targetAccountId); - else - LoginDatabase.PExecute("DELETE FROM account_access WHERE id = '%u' AND (RealmID = '%d' OR RealmID = '-1')", targetAccountId, realmID); - - if (gm != 0) - LoginDatabase.PExecute("INSERT INTO account_access VALUES ('%u','%d','%d')", targetAccountId, gm, realmID); - PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); - return true; -} - -/// Set password for account -bool ChatHandler::HandleAccountSetPasswordCommand(const char *args) -{ - if (!*args) - return false; - - ///- Get the command line arguments - char *szAccount = strtok ((char*)args," "); - char *szPassword1 = strtok (NULL," "); - char *szPassword2 = strtok (NULL," "); - - if (!szAccount||!szPassword1 || !szPassword2) - return false; - - std::string account_name = szAccount; - if (!AccountMgr::normalizeString(account_name)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - uint32 targetAccountId = accmgr.GetId(account_name); - if (!targetAccountId) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - /// can set password only for target with less security - /// This is also reject self apply in fact - if (HasLowerSecurityAccount (NULL,targetAccountId,true)) - return false; - - if (strcmp(szPassword1,szPassword2)) - { - SendSysMessage (LANG_NEW_PASSWORDS_NOT_MATCH); - SetSentErrorMessage (true); - return false; - } - - AccountOpResult result = accmgr.ChangePassword(targetAccountId, szPassword1); - - switch (result) - { - case AOR_OK: - SendSysMessage(LANG_COMMAND_PASSWORD); - break; - case AOR_NAME_NOT_EXIST: - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - case AOR_PASS_TOO_LONG: - SendSysMessage(LANG_PASSWORD_TOO_LONG); - SetSentErrorMessage(true); - return false; - default: - SendSysMessage(LANG_COMMAND_NOTCHANGEPASSWORD); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandleMaxSkillCommand(const char* /*args*/) -{ - Player* SelectedPlayer = getSelectedPlayer(); - if (!SelectedPlayer) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // each skills that have max skill value dependent from level seted to current level max skill value - SelectedPlayer->UpdateSkillsToMaxSkillsForLevel(); - return true; -} - -bool ChatHandler::HandleSetSkillCommand(const char *args) -{ - // number or [name] Shift-click form |color|Hskill:skill_id|h[name]|h|r - char* skill_p = extractKeyFromLink((char*)args,"Hskill"); - if (!skill_p) - return false; - - char *level_p = strtok (NULL, " "); - - if (!level_p) - return false; - - char *max_p = strtok (NULL, " "); - - int32 skill = atoi(skill_p); - if (skill <= 0) - { - PSendSysMessage(LANG_INVALID_SKILL_ID, skill); - SetSentErrorMessage(true); - return false; - } - - int32 level = atol (level_p); - - Player * target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - SkillLineEntry const* sl = sSkillLineStore.LookupEntry(skill); - if (!sl) - { - PSendSysMessage(LANG_INVALID_SKILL_ID, skill); - SetSentErrorMessage(true); - return false; - } - - std::string tNameLink = GetNameLink(target); - - if (!target->GetSkillValue(skill)) - { - PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, sl->name[GetSessionDbcLocale()]); - SetSentErrorMessage(true); - return false; - } - - int32 max = max_p ? atol (max_p) : target->GetPureMaxSkillValue(skill); - - if (level <= 0 || level > max || max <= 0) - return false; - - target->SetSkill(skill, target->GetSkillStep(skill), level, max); - PSendSysMessage(LANG_SET_SKILL, skill, sl->name[GetSessionDbcLocale()], tNameLink.c_str(), level, max); - - return true; -} - -bool ChatHandler::HandleUnLearnCommand(const char *args) -{ - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r - uint32 spell_id = extractSpellIdFromLink((char*)args); - if (!spell_id) - return false; - - char const* allStr = strtok(NULL," "); - bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; - - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (allRanks) - spell_id = spellmgr.GetFirstSpellInChain (spell_id); - - if (target->HasSpell(spell_id)) - target->removeSpell(spell_id,false,!allRanks); - else - SendSysMessage(LANG_FORGET_SPELL); - - if (GetTalentSpellCost(spell_id)) - target->SendTalentsInfoData(false); - - return true; -} - -bool ChatHandler::HandleCooldownCommand(const char *args) -{ - Player* target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - std::string tNameLink = GetNameLink(target); - - if (!*args) - { - target->RemoveAllSpellCooldown(); - PSendSysMessage(LANG_REMOVEALL_COOLDOWN, tNameLink.c_str()); - } - else - { - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell_id = extractSpellIdFromLink((char*)args); - if (!spell_id) - return false; - - if (!sSpellStore.LookupEntry(spell_id)) - { - PSendSysMessage(LANG_UNKNOWN_SPELL, target == m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : tNameLink.c_str()); - SetSentErrorMessage(true); - return false; - } - - target->RemoveSpellCooldown(spell_id,true); - PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target == m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : tNameLink.c_str()); - } - return true; -} - -bool ChatHandler::HandleLearnAllCommand(const char* /*args*/) -{ - static const char *allSpellList[] = - { - "3365", - "6233", - "6247", - "6246", - "6477", - "6478", - "22810", - "8386", - "21651", - "21652", - "522", - "7266", - "8597", - "2479", - "22027", - "6603", - "5019", - "133", - "168", - "227", - "5009", - "9078", - "668", - "203", - "20599", - "20600", - "81", - "20597", - "20598", - "20864", - "1459", - "5504", - "587", - "5143", - "118", - "5505", - "597", - "604", - "1449", - "1460", - "2855", - "1008", - "475", - "5506", - "1463", - "12824", - "8437", - "990", - "5145", - "8450", - "1461", - "759", - "8494", - "8455", - "8438", - "6127", - "8416", - "6129", - "8451", - "8495", - "8439", - "3552", - "8417", - "10138", - "12825", - "10169", - "10156", - "10144", - "10191", - "10201", - "10211", - "10053", - "10173", - "10139", - "10145", - "10192", - "10170", - "10202", - "10054", - "10174", - "10193", - "12826", - "2136", - "143", - "145", - "2137", - "2120", - "3140", - "543", - "2138", - "2948", - "8400", - "2121", - "8444", - "8412", - "8457", - "8401", - "8422", - "8445", - "8402", - "8413", - "8458", - "8423", - "8446", - "10148", - "10197", - "10205", - "10149", - "10215", - "10223", - "10206", - "10199", - "10150", - "10216", - "10207", - "10225", - "10151", - "116", - "205", - "7300", - "122", - "837", - "10", - "7301", - "7322", - "6143", - "120", - "865", - "8406", - "6141", - "7302", - "8461", - "8407", - "8492", - "8427", - "8408", - "6131", - "7320", - "10159", - "8462", - "10185", - "10179", - "10160", - "10180", - "10219", - "10186", - "10177", - "10230", - "10181", - "10161", - "10187", - "10220", - "2018", - "2663", - "12260", - "2660", - "3115", - "3326", - "2665", - "3116", - "2738", - "3293", - "2661", - "3319", - "2662", - "9983", - "8880", - "2737", - "2739", - "7408", - "3320", - "2666", - "3323", - "3324", - "3294", - "22723", - "23219", - "23220", - "23221", - "23228", - "23338", - "10788", - "10790", - "5611", - "5016", - "5609", - "2060", - "10963", - "10964", - "10965", - "22593", - "22594", - "596", - "996", - "499", - "768", - "17002", - "1448", - "1082", - "16979", - "1079", - "5215", - "20484", - "5221", - "15590", - "17007", - "6795", - "6807", - "5487", - "1446", - "1066", - "5421", - "3139", - "779", - "6811", - "6808", - "1445", - "5216", - "1737", - "5222", - "5217", - "1432", - "6812", - "9492", - "5210", - "3030", - "1441", - "783", - "6801", - "20739", - "8944", - "9491", - "22569", - "5226", - "6786", - "1433", - "8973", - "1828", - "9495", - "9006", - "6794", - "8993", - "5203", - "16914", - "6784", - "9635", - "22830", - "20722", - "9748", - "6790", - "9753", - "9493", - "9752", - "9831", - "9825", - "9822", - "5204", - "5401", - "22831", - "6793", - "9845", - "17401", - "9882", - "9868", - "20749", - "9893", - "9899", - "9895", - "9832", - "9902", - "9909", - "22832", - "9828", - "9851", - "9883", - "9869", - "17406", - "17402", - "9914", - "20750", - "9897", - "9848", - "3127", - "107", - "204", - "9116", - "2457", - "78", - "18848", - "331", - "403", - "2098", - "1752", - "11278", - "11288", - "11284", - "6461", - "2344", - "2345", - "6463", - "2346", - "2352", - "775", - "1434", - "1612", - "71", - "2468", - "2458", - "2467", - "7164", - "7178", - "7367", - "7376", - "7381", - "21156", - "5209", - "3029", - "5201", - "9849", - "9850", - "20719", - "22568", - "22827", - "22828", - "22829", - "6809", - "8972", - "9005", - "9823", - "9827", - "6783", - "9913", - "6785", - "6787", - "9866", - "9867", - "9894", - "9896", - "6800", - "8992", - "9829", - "9830", - "780", - "769", - "6749", - "6750", - "9755", - "9754", - "9908", - "20745", - "20742", - "20747", - "20748", - "9746", - "9745", - "9880", - "9881", - "5391", - "842", - "3025", - "3031", - "3287", - "3329", - "1945", - "3559", - "4933", - "4934", - "4935", - "4936", - "5142", - "5390", - "5392", - "5404", - "5420", - "6405", - "7293", - "7965", - "8041", - "8153", - "9033", - "9034", - //"9036", problems with ghost state - "16421", - "21653", - "22660", - "5225", - "9846", - "2426", - "5916", - "6634", - //"6718", phasing stealth, annoying for learn all case. - "6719", - "8822", - "9591", - "9590", - "10032", - "17746", - "17747", - "8203", - "11392", - "12495", - "16380", - "23452", - "4079", - "4996", - "4997", - "4998", - "4999", - "5000", - "6348", - "6349", - "6481", - "6482", - "6483", - "6484", - "11362", - "11410", - "11409", - "12510", - "12509", - "12885", - "13142", - "21463", - "23460", - "11421", - "11416", - "11418", - "1851", - "10059", - "11423", - "11417", - "11422", - "11419", - "11424", - "11420", - "27", - "31", - "33", - "34", - "35", - "15125", - "21127", - "22950", - "1180", - "201", - "12593", - "16770", - "6057", - "12051", - "18468", - "12606", - "12605", - "18466", - "12502", - "12043", - "15060", - "12042", - "12341", - "12848", - "12344", - "12353", - "18460", - "11366", - "12350", - "12352", - "13043", - "11368", - "11113", - "12400", - "11129", - "16766", - "12573", - "12580", - "12472", - "12953", - "12488", - "11189", - "12985", - "12519", - "16758", - "11958", - "12490", - "11426", - "3565", - "3562", - "18960", - "3567", - "3561", - "3566", - "3563", - "1953", - "2139", - "12505", - "13018", - "12522", - "12523", - "5146", - "5144", - "5148", - "8419", - "8418", - "10213", - "10212", - "10157", - "12524", - "13019", - "12525", - "13020", - "12526", - "13021", - "18809", - "13031", - "13032", - "13033", - "4036", - "3920", - "3919", - "3918", - "7430", - "3922", - "3923", - "7411", - "7418", - "7421", - "13262", - "7412", - "7415", - "7413", - "7416", - "13920", - "13921", - "7745", - "7779", - "7428", - "7457", - "7857", - "7748", - "7426", - "13421", - "7454", - "13378", - "7788", - "14807", - "14293", - "7795", - "6296", - "20608", - "755", - "444", - "427", - "428", - "442", - "447", - "3578", - "3581", - "19027", - "3580", - "665", - "3579", - "3577", - "6755", - "3576", - "2575", - "2577", - "2578", - "2579", - "2580", - "2656", - "2657", - "2576", - "3564", - "10248", - "8388", - "2659", - "14891", - "3308", - "3307", - "10097", - "2658", - "3569", - "16153", - "3304", - "10098", - "4037", - "3929", - "3931", - "3926", - "3924", - "3930", - "3977", - "3925", - "136", - "228", - "5487", - "43", - "202", - "0" - }; - - int loop = 0; - while (strcmp(allSpellList[loop], "0")) - { - uint32 spell = atol((char*)allSpellList[loop++]); - - if (m_session->GetPlayer()->HasSpell(spell)) - continue; - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); - continue; - } - - m_session->GetPlayer()->learnSpell(spell, false); - } - - SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS); - - return true; -} - -bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/) -{ - static const char *gmSpellList[] = - { - "24347", // Become A Fish, No Breath Bar - "35132", // Visual Boom - "38488", // Attack 4000-8000 AOE - "38795", // Attack 2000 AOE + Slow Down 90% - "15712", // Attack 200 - "1852", // GM Spell Silence - "31899", // Kill - "31924", // Kill - "29878", // Kill My Self - "26644", // More Kill - - "28550", //Invisible 24 - "23452", //Invisible + Target - "0" - }; - - uint16 gmSpellIter = 0; - while (strcmp(gmSpellList[gmSpellIter], "0")) - { - uint32 spell = atol((char*)gmSpellList[gmSpellIter++]); - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); - continue; - } - - m_session->GetPlayer()->learnSpell(spell, false); - } - - SendSysMessage(LANG_LEARNING_GM_SKILLS); - return true; -} - -bool ChatHandler::HandleLearnAllMyClassCommand(const char* /*args*/) -{ - HandleLearnAllMySpellsCommand(""); - HandleLearnAllMyTalentsCommand(""); - return true; -} - -bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) -{ - ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(m_session->GetPlayer()->getClass()); - if (!clsEntry) - return true; - uint32 family = clsEntry->spellfamily; - - for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(i); - if (!spellInfo) - continue; - - // skip server-side/triggered spells - if (spellInfo->spellLevel == 0) - continue; - - // skip wrong class/race skills - if (!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id)) - continue; - - // skip other spell families - if (spellInfo->SpellFamilyName != family) - continue; - - // skip spells with first rank learned as talent (and all talents then also) - uint32 first_rank = spellmgr.GetFirstSpellInChain(spellInfo->Id); - if (GetTalentSpellCost(first_rank) > 0) - continue; - - // skip broken spells - if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) - continue; - - m_session->GetPlayer()->learnSpell(i, false); - } - - SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); - return true; -} - -bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - uint32 classMask = player->getClassMask(); - - for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) - { - TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); - if (!talentInfo) - continue; - - TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - if (!talentTabInfo) - continue; - - if ((classMask & talentTabInfo->ClassMask) == 0) - continue; - - // search highest talent rank - uint32 spellId = 0; - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) - { - if (talentInfo->RankID[rank] != 0) - { - spellId = talentInfo->RankID[rank]; - break; - } - } - - if (!spellId) // ??? none spells in talent - continue; - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) - continue; - - // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) - player->learnSpellHighRank(spellId); - player->AddTalent(spellId, player->GetActiveSpec(), true); - } - - player->SetFreeTalentPoints(0); - - SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); - return true; -} - -bool ChatHandler::HandleLearnAllMyPetTalentsCommand(const char* /*args*/) -{ - Player* player = m_session->GetPlayer(); - - Pet* pet = player->GetPet(); - if (!pet) - { - SendSysMessage(LANG_NO_PET_FOUND); - SetSentErrorMessage(true); - return false; - } - - CreatureInfo const *ci = pet->GetCreatureInfo(); - if (!ci) - { - SendSysMessage(LANG_WRONG_PET_TYPE); - SetSentErrorMessage(true); - return false; - } - - CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); - if (!pet_family) - { - SendSysMessage(LANG_WRONG_PET_TYPE); - SetSentErrorMessage(true); - return false; - } - - if (pet_family->petTalentType < 0) // not hunter pet - { - SendSysMessage(LANG_WRONG_PET_TYPE); - SetSentErrorMessage(true); - return false; - } - - for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) - { - TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); - if (!talentInfo) - continue; - - TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - if (!talentTabInfo) - continue; - - // prevent learn talent for different family (cheating) - if (((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask) == 0) - continue; - - // search highest talent rank - uint32 spellid = 0; - - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) - { - if (talentInfo->RankID[rank] != 0) - { - spellid = talentInfo->RankID[rank]; - break; - } - } - - if (!spellid) // ??? none spells in talent - continue; - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) - continue; - - // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) - pet->learnSpellHighRank(spellid); - } - - pet->SetFreeTalentPoints(0); - - SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS); - return true; -} - -bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) -{ - // skipping UNIVERSAL language (0) - for (uint8 i = 1; i < LANGUAGES_COUNT; ++i) - m_session->GetPlayer()->learnSpell(lang_description[i].spell_id, false); - - SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); - return true; -} - -bool ChatHandler::HandleLearnAllDefaultCommand(const char *args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - target->learnDefaultSpells(); - target->learnQuestRewardedSpells(); - - PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,GetNameLink(target).c_str()); - return true; -} - -bool ChatHandler::HandleLearnCommand(const char *args) -{ - Player* targetPlayer = getSelectedPlayer(); - - if (!targetPlayer) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell || !sSpellStore.LookupEntry(spell)) - return false; - - char const* allStr = strtok(NULL," "); - bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); - SetSentErrorMessage(true); - return false; - } - - if (!allRanks && targetPlayer->HasSpell(spell)) - { - if (targetPlayer == m_session->GetPlayer()) - SendSysMessage(LANG_YOU_KNOWN_SPELL); - else - PSendSysMessage(LANG_TARGET_KNOWN_SPELL,GetNameLink(targetPlayer).c_str()); - SetSentErrorMessage(true); - return false; - } - - if (allRanks) - targetPlayer->learnSpellHighRank(spell); - else - targetPlayer->learnSpell(spell, false); - - uint32 first_spell = spellmgr.GetFirstSpellInChain(spell); - if (GetTalentSpellCost(first_spell)) - targetPlayer->SendTalentsInfoData(false); - - return true; -} - -bool ChatHandler::HandleAddItemCommand(const char *args) -{ - if (!*args) - return false; - - uint32 itemId = 0; - - if (args[0] == '[') // [name] manual form - { - char* citemName = strtok((char*)args, "]"); - - if (citemName && citemName[0]) - { - std::string itemName = citemName+1; - WorldDatabase.escape_string(itemName); - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE name = '%s'", itemName.c_str()); - if (!result) - { - PSendSysMessage(LANG_COMMAND_COULDNOTFIND, citemName+1); - SetSentErrorMessage(true); - return false; - } - itemId = result->Fetch()->GetUInt16(); - } - else - return false; - } - else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r - { - char* cId = extractKeyFromLink((char*)args,"Hitem"); - if (!cId) - return false; - itemId = atol(cId); - } - - char* ccount = strtok(NULL, " "); - - int32 count = 1; - - if (ccount) - count = strtol(ccount, NULL, 10); - - if (count == 0) - count = 1; - - Player* pl = m_session->GetPlayer(); - Player* plTarget = getSelectedPlayer(); - if (!plTarget) - plTarget = pl; - - sLog.outDetail(GetTrinityString(LANG_ADDITEM), itemId, count); - - ItemPrototype const *pProto = objmgr.GetItemPrototype(itemId); - if (!pProto) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); - SetSentErrorMessage(true); - return false; - } - - //Subtract - if (count < 0) - { - plTarget->DestroyItemCount(itemId, -count, true, false); - PSendSysMessage(LANG_REMOVEITEM, itemId, -count, GetNameLink(plTarget).c_str()); - return true; - } - - //Adding items - uint32 noSpaceForCount = 0; - - // check space and find places - ItemPosCountVec dest; - uint8 msg = plTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount); - if (msg != EQUIP_ERR_OK) // convert to possible store amount - count -= noSpaceForCount; - - if (count == 0 || dest.empty()) // can't add any - { - PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); - SetSentErrorMessage(true); - return false; - } - - Item* item = plTarget->StoreNewItem(dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); - - // remove binding (let GM give it to another player later) - if (pl == plTarget) - for (ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); ++itr) - if (Item* item1 = pl->GetItemByPos(itr->pos)) - item1->SetBinding(false); - - if (count > 0 && item) - { - pl->SendNewItem(item,count,false,true); - if (pl != plTarget) - plTarget->SendNewItem(item,count,true,false); - } - - if (noSpaceForCount > 0) - PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, noSpaceForCount); - - return true; -} - -bool ChatHandler::HandleAddItemSetCommand(const char *args) -{ - if (!*args) - return false; - - char* cId = extractKeyFromLink((char*)args,"Hitemset"); // number or [name] Shift-click form |color|Hitemset:itemset_id|h[name]|h|r - if (!cId) - return false; - - uint32 itemsetId = atol(cId); - - // prevent generation all items with itemset field value '0' - if (itemsetId == 0) - { - PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); - SetSentErrorMessage(true); - return false; - } - - Player* pl = m_session->GetPlayer(); - Player* plTarget = getSelectedPlayer(); - if (!plTarget) - plTarget = pl; - - sLog.outDetail(GetTrinityString(LANG_ADDITEMSET), itemsetId); - - bool found = false; - for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) - { - ItemPrototype const *pProto = sItemStorage.LookupEntry(id); - if (!pProto) - continue; - - if (pProto->ItemSet == itemsetId) - { - found = true; - ItemPosCountVec dest; - uint8 msg = plTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, pProto->ItemId, 1); - if (msg == EQUIP_ERR_OK) - { - Item* item = plTarget->StoreNewItem(dest, pProto->ItemId, true); - - // remove binding (let GM give it to another player later) - if (pl == plTarget) - item->SetBinding(false); - - pl->SendNewItem(item,1,false,true); - if (pl != plTarget) - plTarget->SendNewItem(item,1,true,false); - } - else - { - pl->SendEquipError(msg, NULL, NULL); - PSendSysMessage(LANG_ITEM_CANNOT_CREATE, pProto->ItemId, 1); - } - } - } - - if (!found) - { - PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); - - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandleListItemCommand(const char *args) -{ - if (!*args) - return false; - - char* cId = extractKeyFromLink((char*)args,"Hitem"); - if (!cId) - return false; - - uint32 item_id = atol(cId); - if (!item_id) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - ItemPrototype const* itemProto = objmgr.GetItemPrototype(item_id); - if (!itemProto) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - char* c_count = strtok(NULL, " "); - int count = c_count ? atol(c_count) : 10; - - if (count < 0) - return false; - - QueryResult_AutoPtr result; - - // inventory case - uint32 inv_count = 0; - result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM character_inventory WHERE item_template='%u'",item_id); - if (result) - inv_count = (*result)[0].GetUInt32(); - - result=CharacterDatabase.PQuery( - // 0 1 2 3 4 5 - "SELECT ci.item, cibag.slot AS bag, ci.slot, ci.guid, characters.account,characters.name " - "FROM character_inventory AS ci LEFT JOIN character_inventory AS cibag ON (cibag.item=ci.bag),characters " - "WHERE ci.item_template='%u' AND ci.guid = characters.guid LIMIT %u ", - item_id,uint32(count)); - - if (result) - { - do - { - Field *fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 item_bag = fields[1].GetUInt32(); - uint32 item_slot = fields[2].GetUInt32(); - uint32 owner_guid = fields[3].GetUInt32(); - uint32 owner_acc = fields[4].GetUInt32(); - std::string owner_name = fields[5].GetCppString(); - - char const* item_pos = 0; - if (Player::IsEquipmentPos(item_bag,item_slot)) - item_pos = "[equipped]"; - else if (Player::IsInventoryPos(item_bag,item_slot)) - item_pos = "[in inventory]"; - else if (Player::IsBankPos(item_bag,item_slot)) - item_pos = "[in bank]"; - else - item_pos = ""; - - PSendSysMessage(LANG_ITEMLIST_SLOT, - item_guid,owner_name.c_str(),owner_guid,owner_acc,item_pos); - } while (result->NextRow()); - - int64 res_count = result->GetRowCount(); - - if (count > res_count) - count-=res_count; - else if (count) - count = 0; - } - - // mail case - uint32 mail_count = 0; - result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM mail_items WHERE item_template='%u'", item_id); - if (result) - mail_count = (*result)[0].GetUInt32(); - - if (count > 0) - { - result=CharacterDatabase.PQuery( - // 0 1 2 3 4 5 6 - "SELECT mail_items.item_guid, mail.sender, mail.receiver, char_s.account, char_s.name, char_r.account, char_r.name " - "FROM mail,mail_items,characters as char_s,characters as char_r " - "WHERE mail_items.item_template='%u' AND char_s.guid = mail.sender AND char_r.guid = mail.receiver AND mail.id=mail_items.mail_id LIMIT %u", - item_id,uint32(count)); - } - else - result = QueryResult_AutoPtr(NULL); - - if (result) - { - do - { - Field *fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 item_s = fields[1].GetUInt32(); - uint32 item_r = fields[2].GetUInt32(); - uint32 item_s_acc = fields[3].GetUInt32(); - std::string item_s_name = fields[4].GetCppString(); - uint32 item_r_acc = fields[5].GetUInt32(); - std::string item_r_name = fields[6].GetCppString(); - - char const* item_pos = "[in mail]"; - - PSendSysMessage(LANG_ITEMLIST_MAIL, - item_guid,item_s_name.c_str(),item_s,item_s_acc,item_r_name.c_str(),item_r,item_r_acc,item_pos); - } while (result->NextRow()); - - int64 res_count = result->GetRowCount(); - - if (count > res_count) - count-=res_count; - else if (count) - count = 0; - } - - // auction case - uint32 auc_count = 0; - result=CharacterDatabase.PQuery("SELECT COUNT(item_template) FROM auctionhouse WHERE item_template='%u'",item_id); - if (result) - auc_count = (*result)[0].GetUInt32(); - - if (count > 0) - { - result=CharacterDatabase.PQuery( - // 0 1 2 3 - "SELECT auctionhouse.itemguid, auctionhouse.itemowner, characters.account, characters.name " - "FROM auctionhouse,characters WHERE auctionhouse.item_template='%u' AND characters.guid = auctionhouse.itemowner LIMIT %u", - item_id,uint32(count)); - } - else - result = QueryResult_AutoPtr(NULL); - - if (result) - { - do - { - Field *fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 owner = fields[1].GetUInt32(); - uint32 owner_acc = fields[2].GetUInt32(); - std::string owner_name = fields[3].GetCppString(); - - char const* item_pos = "[in auction]"; - - PSendSysMessage(LANG_ITEMLIST_AUCTION, item_guid, owner_name.c_str(), owner, owner_acc,item_pos); - } while (result->NextRow()); - } - - // guild bank case - uint32 guild_count = 0; - result=CharacterDatabase.PQuery("SELECT COUNT(item_entry) FROM guild_bank_item WHERE item_entry='%u'",item_id); - if (result) - guild_count = (*result)[0].GetUInt32(); - - result=CharacterDatabase.PQuery( - // 0 1 2 - "SELECT gi.item_guid, gi.guildid, guild.name " - "FROM guild_bank_item AS gi, guild WHERE gi.item_entry='%u' AND gi.guildid = guild.guildid LIMIT %u ", - item_id,uint32(count)); - - if (result) - { - do - { - Field *fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 guild_guid = fields[1].GetUInt32(); - std::string guild_name = fields[2].GetCppString(); - - char const* item_pos = "[in guild bank]"; - - PSendSysMessage(LANG_ITEMLIST_GUILD,item_guid,guild_name.c_str(),guild_guid,item_pos); - } while (result->NextRow()); - - int64 res_count = result->GetRowCount(); - - if (count > res_count) - count-=res_count; - else if (count) - count = 0; - } - - if (inv_count+mail_count+auc_count+guild_count == 0) - { - SendSysMessage(LANG_COMMAND_NOITEMFOUND); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_COMMAND_LISTITEMMESSAGE,item_id,inv_count+mail_count+auc_count+guild_count,inv_count,mail_count,auc_count,guild_count); - - return true; -} - -bool ChatHandler::HandleListObjectCommand(const char *args) -{ - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry"); - if (!cId) - return false; - - uint32 go_id = atol(cId); - if (!go_id) - { - PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); - SetSentErrorMessage(true); - return false; - } - - GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(go_id); - if (!gInfo) - { - PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); - SetSentErrorMessage(true); - return false; - } - - char* c_count = strtok(NULL, " "); - int count = c_count ? atol(c_count) : 10; - - if (count < 0) - return false; - - QueryResult_AutoPtr result; - - uint32 obj_count = 0; - result=WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'",go_id); - if (result) - obj_count = (*result)[0].GetUInt32(); - - if (m_session) - { - Player* pl = m_session->GetPlayer(); - result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", - pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),go_id,uint32(count)); - } - else - result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM gameobject WHERE id = '%u' LIMIT %u", - go_id,uint32(count)); - - if (result) - { - do - { - Field *fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - float x = fields[1].GetFloat(); - float y = fields[2].GetFloat(); - float z = fields[3].GetFloat(); - int mapid = fields[4].GetUInt16(); - - if (m_session) - PSendSysMessage(LANG_GO_LIST_CHAT, guid, guid, gInfo->name, x, y, z, mapid); - else - PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name, x, y, z, mapid); - } while (result->NextRow()); - } - - PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE,go_id,obj_count); - return true; -} - -bool ChatHandler::HandleGameObjectStateCommand(const char *args) -{ - // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args, "Hgameobject"); - if (!cId) - return false; - - uint32 lowguid = atoi(cId); - if (!lowguid) - return false; - - GameObject* gobj = NULL; - - if (GameObjectData const* goData = objmgr.GetGOData(lowguid)) - gobj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid, goData->id); - - if (!gobj) - { - PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - char* ctype = strtok(NULL, " "); - if (!ctype) - return false; - - int32 type = atoi(ctype); - if (type < 0) - { - if (type == -1) - gobj->SendObjectDeSpawnAnim(gobj->GetGUID()); - else if (type == -2) - { - return false; - } - return true; - } - - char* cstate = strtok(NULL, " "); - if (!cstate) - return false; - - int32 state = atoi(cstate); - - if (type < 4) - gobj->SetByteValue(GAMEOBJECT_BYTES_1, type, state); - else if (type == 4) - { - WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM,8+4); - data << gobj->GetGUID(); - data << (uint32)(state); - gobj->SendMessageToSet(&data, true); - } - PSendSysMessage("Set gobject type %d state %d", type, state); - - return true; -} - -bool ChatHandler::HandleListCreatureCommand(const char *args) -{ - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hcreature_entry"); - if (!cId) - return false; - - uint32 cr_id = atol(cId); - if (!cr_id) - { - PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); - SetSentErrorMessage(true); - return false; - } - - CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(cr_id); - if (!cInfo) - { - PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); - SetSentErrorMessage(true); - return false; - } - - char* c_count = strtok(NULL, " "); - int count = c_count ? atol(c_count) : 10; - - if (count < 0) - return false; - - QueryResult_AutoPtr result; - - uint32 cr_count = 0; - result=WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'",cr_id); - if (result) - cr_count = (*result)[0].GetUInt32(); - - if (m_session) - { - Player* pl = m_session->GetPlayer(); - result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM creature WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", - pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), cr_id,uint32(count)); - } - else - result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM creature WHERE id = '%u' LIMIT %u", - cr_id,uint32(count)); - - if (result) - { - do - { - Field *fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - float x = fields[1].GetFloat(); - float y = fields[2].GetFloat(); - float z = fields[3].GetFloat(); - int mapid = fields[4].GetUInt16(); - - if (m_session) - PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name, x, y, z, mapid); - else - PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name, x, y, z, mapid); - } while (result->NextRow()); - } - - PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE,cr_id,cr_count); - return true; -} - -bool ChatHandler::HandleLookupItemCommand(const char *args) -{ - if (!*args) - return false; - - std::string namepart = args; - std::wstring wnamepart; - - // converting string that we try to find to lower case - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - wstrToLower(wnamepart); - - bool found = false; - - // Search in `item_template` - for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) - { - ItemPrototype const *pProto = sItemStorage.LookupEntry(id); - if (!pProto) - continue; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); - if (il) - { - if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty()) - { - std::string name = il->Name[loc_idx]; - - if (Utf8FitTo(name, wnamepart)) - { - if (m_session) - PSendSysMessage(LANG_ITEM_LIST_CHAT, id, id, name.c_str()); - else - PSendSysMessage(LANG_ITEM_LIST_CONSOLE, id, name.c_str()); - - if (!found) - found = true; - - continue; - } - } - } - } - - std::string name = pProto->Name1; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - { - if (m_session) - PSendSysMessage(LANG_ITEM_LIST_CHAT, id, id, name.c_str()); - else - PSendSysMessage(LANG_ITEM_LIST_CONSOLE, id, name.c_str()); - - if (!found) - found = true; - } - } - - if (!found) - SendSysMessage(LANG_COMMAND_NOITEMFOUND); - - return true; -} - -bool ChatHandler::HandleLookupItemSetCommand(const char *args) -{ - if (!*args) - return false; - - std::string namepart = args; - std::wstring wnamepart; - - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wnamepart); - - bool found = false; - - // Search in ItemSet.dbc - for (uint32 id = 0; id < sItemSetStore.GetNumRows(); id++) - { - ItemSetEntry const *set = sItemSetStore.LookupEntry(id); - if (set) - { - int loc = GetSessionDbcLocale(); - std::string name = set->name[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo(name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale()) - continue; - - name = set->name[loc]; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - // send item set in "id - [namedlink locale]" format - if (m_session) - PSendSysMessage(LANG_ITEMSET_LIST_CHAT,id,id,name.c_str(),localeNames[loc]); - else - PSendSysMessage(LANG_ITEMSET_LIST_CONSOLE,id,name.c_str(),localeNames[loc]); - - if (!found) - found = true; - } - } - } - if (!found) - SendSysMessage(LANG_COMMAND_NOITEMSETFOUND); - return true; -} - -bool ChatHandler::HandleLookupSkillCommand(const char *args) -{ - if (!*args) - return false; - - // can be NULL in console call - Player* target = getSelectedPlayer(); - - std::string namepart = args; - std::wstring wnamepart; - - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wnamepart); - - bool found = false; - - // Search in SkillLine.dbc - for (uint32 id = 0; id < sSkillLineStore.GetNumRows(); id++) - { - SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(id); - if (skillInfo) - { - int loc = GetSessionDbcLocale(); - std::string name = skillInfo->name[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo(name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale()) - continue; - - name = skillInfo->name[loc]; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - char valStr[50] = ""; - char const* knownStr = ""; - if (target && target->HasSkill(id)) - { - knownStr = GetTrinityString(LANG_KNOWN); - uint32 curValue = target->GetPureSkillValue(id); - uint32 maxValue = target->GetPureMaxSkillValue(id); - uint32 permValue = target->GetSkillPermBonusValue(id); - uint32 tempValue = target->GetSkillTempBonusValue(id); - - char const* valFormat = GetTrinityString(LANG_SKILL_VALUES); - snprintf(valStr,50,valFormat,curValue,maxValue,permValue,tempValue); - } - - // send skill in "id - [namedlink locale]" format - if (m_session) - PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr,valStr); - else - PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr,valStr); - - if (!found) - found = true; - } - } - } - if (!found) - SendSysMessage(LANG_COMMAND_NOSKILLFOUND); - return true; -} - -bool ChatHandler::HandleLookupSpellCommand(const char *args) -{ - if (!*args) - return false; - - // can be NULL at console call - Player* target = getSelectedPlayer(); - - std::string namepart = args; - std::wstring wnamepart; - - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wnamepart); - - bool found = false; - - // Search in Spell.dbc - for (uint32 id = 0; id < sSpellStore.GetNumRows(); id++) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(id); - if (spellInfo) - { - int loc = GetSessionDbcLocale(); - std::string name = spellInfo->SpellName[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo(name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale()) - continue; - - name = spellInfo->SpellName[loc]; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - bool known = target && target->HasSpell(id); - bool learn = (spellInfo->Effect[0] == SPELL_EFFECT_LEARN_SPELL); - - uint32 talentCost = GetTalentSpellCost(id); - - bool talent = (talentCost > 0); - bool passive = IsPassiveSpell(id); - bool active = target && target->HasAura(id); - - // unit32 used to prevent interpreting uint8 as char at output - // find rank of learned spell for learning spell, or talent rank - uint32 rank = talentCost ? talentCost : spellmgr.GetSpellRank(learn ? spellInfo->EffectTriggerSpell[0] : id); - - // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format - std::ostringstream ss; - if (m_session) - ss << id << " - |cffffffff|Hspell:" << id << "|h[" << name; - else - ss << id << " - " << name; - - // include rank in link name - if (rank) - ss << GetTrinityString(LANG_SPELL_RANK) << rank; - - if (m_session) - ss << " " << localeNames[loc] << "]|h|r"; - else - ss << " " << localeNames[loc]; - - if (talent) - ss << GetTrinityString(LANG_TALENT); - if (passive) - ss << GetTrinityString(LANG_PASSIVE); - if (learn) - ss << GetTrinityString(LANG_LEARN); - if (known) - ss << GetTrinityString(LANG_KNOWN); - if (active) - ss << GetTrinityString(LANG_ACTIVE); - - SendSysMessage(ss.str().c_str()); - - if (!found) - found = true; - } - } - } - if (!found) - SendSysMessage(LANG_COMMAND_NOSPELLFOUND); - return true; -} - -bool ChatHandler::HandleLookupQuestCommand(const char *args) -{ - if (!*args) - return false; - - // can be NULL at console call - Player* target = getSelectedPlayer(); - - std::string namepart = args; - std::wstring wnamepart; - - // converting string that we try to find to lower case - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - wstrToLower(wnamepart); - - bool found = false; - - ObjectMgr::QuestMap const& qTemplates = objmgr.GetQuestTemplates(); - for (ObjectMgr::QuestMap::const_iterator iter = qTemplates.begin(); iter != qTemplates.end(); ++iter) - { - Quest * qinfo = iter->second; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - QuestLocale const *il = objmgr.GetQuestLocale(qinfo->GetQuestId()); - if (il) - { - if (il->Title.size() > loc_idx && !il->Title[loc_idx].empty()) - { - std::string title = il->Title[loc_idx]; - - if (Utf8FitTo(title, wnamepart)) - { - char const* statusStr = ""; - - if (target) - { - QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - - if (status == QUEST_STATUS_COMPLETE) - { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); - else - statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); - } - else if (status == QUEST_STATUS_INCOMPLETE) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); - } - - if (m_session) - PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),qinfo->GetQuestLevel(),title.c_str(),statusStr); - else - PSendSysMessage(LANG_QUEST_LIST_CONSOLE,qinfo->GetQuestId(),title.c_str(),statusStr); - - if (!found) - found = true; - - continue; - } - } - } - } - - std::string title = qinfo->GetTitle(); - if (title.empty()) - continue; - - if (Utf8FitTo(title, wnamepart)) - { - char const* statusStr = ""; - - if (target) - { - QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - - if (status == QUEST_STATUS_COMPLETE) - { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); - else - statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); - } - else if (status == QUEST_STATUS_INCOMPLETE) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); - } - - if (m_session) - PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),qinfo->GetQuestLevel(),title.c_str(),statusStr); - else - PSendSysMessage(LANG_QUEST_LIST_CONSOLE,qinfo->GetQuestId(),title.c_str(),statusStr); - - if (!found) - found = true; - } - } - - if (!found) - SendSysMessage(LANG_COMMAND_NOQUESTFOUND); - - return true; -} - -bool ChatHandler::HandleLookupCreatureCommand(const char *args) -{ - if (!*args) - return false; - - std::string namepart = args; - std::wstring wnamepart; - - // converting string that we try to find to lower case - if (!Utf8toWStr (namepart,wnamepart)) - return false; - - wstrToLower (wnamepart); - - bool found = false; - - for (uint32 id = 0; id< sCreatureStorage.MaxEntry; ++id) - { - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry (id); - if (!cInfo) - continue; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - CreatureLocale const *cl = objmgr.GetCreatureLocale (id); - if (cl) - { - if (cl->Name.size() > loc_idx && !cl->Name[loc_idx].empty ()) - { - std::string name = cl->Name[loc_idx]; - - if (Utf8FitTo (name, wnamepart)) - { - if (m_session) - PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name.c_str ()); - else - PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name.c_str ()); - - if (!found) - found = true; - - continue; - } - } - } - } - - std::string name = cInfo->Name; - if (name.empty ()) - continue; - - if (Utf8FitTo(name, wnamepart)) - { - if (m_session) - PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CHAT, id, id, name.c_str ()); - else - PSendSysMessage (LANG_CREATURE_ENTRY_LIST_CONSOLE, id, name.c_str ()); - - if (!found) - found = true; - } - } - - if (!found) - SendSysMessage (LANG_COMMAND_NOCREATUREFOUND); - - return true; -} - -bool ChatHandler::HandleLookupObjectCommand(const char *args) -{ - if (!*args) - return false; - - std::string namepart = args; - std::wstring wnamepart; - - // converting string that we try to find to lower case - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - wstrToLower(wnamepart); - - bool found = false; - - for (uint32 id = 0; id< sGOStorage.MaxEntry; id++) - { - GameObjectInfo const* gInfo = sGOStorage.LookupEntry(id); - if (!gInfo) - continue; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - GameObjectLocale const *gl = objmgr.GetGameObjectLocale(id); - if (gl) - { - if (gl->Name.size() > loc_idx && !gl->Name[loc_idx].empty()) - { - std::string name = gl->Name[loc_idx]; - - if (Utf8FitTo(name, wnamepart)) - { - if (m_session) - PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, id, id, name.c_str()); - else - PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, id, name.c_str()); - - if (!found) - found = true; - - continue; - } - } - } - } - - std::string name = gInfo->name; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - { - if (m_session) - PSendSysMessage(LANG_GO_ENTRY_LIST_CHAT, id, id, name.c_str()); - else - PSendSysMessage(LANG_GO_ENTRY_LIST_CONSOLE, id, name.c_str()); - - if (!found) - found = true; - } - } - - if (!found) - SendSysMessage(LANG_COMMAND_NOGAMEOBJECTFOUND); - - return true; -} - -bool ChatHandler::HandleLookupFactionCommand(const char *args) -{ - if (!*args) - return false; - - // Can be NULL at console call - Player *target = getSelectedPlayer (); - - std::string namepart = args; - std::wstring wnamepart; - - if (!Utf8toWStr (namepart,wnamepart)) - return false; - - // converting string that we try to find to lower case - wstrToLower (wnamepart); - - bool found = false; - - for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id) - { - FactionEntry const *factionEntry = sFactionStore.LookupEntry (id); - if (factionEntry) - { - FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL; - - int loc = GetSessionDbcLocale(); - std::string name = factionEntry->name[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo(name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale()) - continue; - - name = factionEntry->name[loc]; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format - // or "id - [faction] [no reputation]" format - std::ostringstream ss; - if (m_session) - ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r"; - else - ss << id << " - " << name << " " << localeNames[loc]; - - if (repState) // and then target != NULL also - { - ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); - std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]); - - ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")"; - - if (repState->Flags & FACTION_FLAG_VISIBLE) - ss << GetTrinityString(LANG_FACTION_VISIBLE); - if (repState->Flags & FACTION_FLAG_AT_WAR) - ss << GetTrinityString(LANG_FACTION_ATWAR); - if (repState->Flags & FACTION_FLAG_PEACE_FORCED) - ss << GetTrinityString(LANG_FACTION_PEACE_FORCED); - if (repState->Flags & FACTION_FLAG_HIDDEN) - ss << GetTrinityString(LANG_FACTION_HIDDEN); - if (repState->Flags & FACTION_FLAG_INVISIBLE_FORCED) - ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED); - if (repState->Flags & FACTION_FLAG_INACTIVE) - ss << GetTrinityString(LANG_FACTION_INACTIVE); - } - else - ss << GetTrinityString(LANG_FACTION_NOREPUTATION); - - SendSysMessage(ss.str().c_str()); - - if (!found) - found = true; - } - } - } - - if (!found) - SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND); - return true; -} - -bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) -{ - if (!*args) - return false; - - std::string namepart = args; - std::wstring wnamepart; - - if (!Utf8toWStr(namepart,wnamepart)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wnamepart); - - bool found = false; - - // Search in TaxiNodes.dbc - for (uint32 id = 0; id < sTaxiNodesStore.GetNumRows(); id++) - { - TaxiNodesEntry const *nodeEntry = sTaxiNodesStore.LookupEntry(id); - if (nodeEntry) - { - int loc = GetSessionDbcLocale(); - std::string name = nodeEntry->name[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo(name, wnamepart)) - { - loc = 0; - for (; loc < MAX_LOCALE; ++loc) - { - if (loc == GetSessionDbcLocale()) - continue; - - name = nodeEntry->name[loc]; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - // send taxinode in "id - [name] (Map:m X:x Y:y Z:z)" format - if (m_session) - PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CHAT, id, id, name.c_str(),localeNames[loc], - nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z); - else - PSendSysMessage (LANG_TAXINODE_ENTRY_LIST_CONSOLE, id, name.c_str(), localeNames[loc], - nodeEntry->map_id,nodeEntry->x,nodeEntry->y,nodeEntry->z); - - if (!found) - found = true; - } - } - } - if (!found) - SendSysMessage(LANG_COMMAND_NOTAXINODEFOUND); - return true; -} - -bool ChatHandler::HandleLookupMapCommand(const char *args) -{ - if (!*args) - return false; - - /*std::string namepart = args; - std::wstring wnamepart; - - // converting string that we try to find to lower case - if (!Utf8toWStr(namepart, wnamepart)) - return false; - - wstrToLower(wnamepart); - - bool found = false; - - // search in Map.dbc - for (uint32 id = 0; id < sMapStore.GetNumRows(); id++) - { - MapEntry const* MapInfo = sMapStore.LookupEntry(id); - if (MapInfo) - { - uint8 loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); - - std::string name = MapInfo->name[loc]; - if (name.empty()) - continue; - - if (!Utf8FitTo(name, wnamepart)) - { - loc = LOCALE_enUS; - for (; loc < MAX_LOCALE; loc++) - { - if (m_session && loc == m_session->GetSessionDbcLocale()) - continue; - - name = MapInfo->name[loc]; - if (name.empty()) - continue; - - if (Utf8FitTo(name, wnamepart)) - break; - } - } - - if (loc < MAX_LOCALE) - { - // send map in "id - [name][Continent][Instance/Battleground/Arena][Raid reset time:][Heroic reset time:][Mountable]" format - std::ostringstream ss; - - if (m_session) - ss << id << " - |cffffffff|Hmap:" << id << "|h[" << name << "]"; - else // console - ss << id << " - [" << name << "]"; - - if (MapInfo->IsContinent()) - ss << GetTrinityString(LANG_CONTINENT); - - switch(MapInfo->map_type) - { - case MAP_INSTANCE: ss << GetTrinityString(LANG_INSTANCE); break; - case MAP_BATTLEGROUND: ss << GetTrinityString(LANG_BATTLEGROUND); break; - case MAP_ARENA: ss << GetTrinityString(LANG_ARENA); break; - } - - if (MapInfo->IsRaid()) - ss << GetTrinityString(LANG_RAID); - - if (MapInfo->SupportsHeroicMode()) - ss << GetTrinityString(LANG_HEROIC); - - uint32 ResetTimeRaid = MapInfo->resetTimeRaid; - - std::string ResetTimeRaidStr; - if (ResetTimeRaid) - ResetTimeRaidStr = secsToTimeString(ResetTimeRaid, true, false); - - uint32 ResetTimeHeroic = MapInfo->resetTimeHeroic; - std::string ResetTimeHeroicStr; - if (ResetTimeHeroic) - ResetTimeHeroicStr = secsToTimeString(ResetTimeHeroic, true, false); - - if (MapInfo->IsMountAllowed()) - ss << GetTrinityString(LANG_MOUNTABLE); - - if (ResetTimeRaid && !ResetTimeHeroic) - PSendSysMessage(ss.str().c_str(), ResetTimeRaidStr.c_str()); - else if (!ResetTimeRaid && ResetTimeHeroic) - PSendSysMessage(ss.str().c_str(), ResetTimeHeroicStr.c_str()); - else if (ResetTimeRaid && ResetTimeHeroic) - PSendSysMessage(ss.str().c_str(), ResetTimeRaidStr.c_str(), ResetTimeHeroicStr.c_str()); - else - SendSysMessage(ss.str().c_str()); - - if (!found) - found = true; - } - } - } - - if (!found) - SendSysMessage(LANG_COMMAND_NOMAPFOUND); - */ - return true; -} - -/** \brief GM command level 3 - Create a guild. - * - * This command allows a GM (level 3) to create a guild. - * - * The "args" parameter contains the name of the guild leader - * and then the name of the guild. - * - */ -bool ChatHandler::HandleGuildCreateCommand(const char *args) -{ - if (!*args) - return false; - - // if not guild name only (in "") then player name - Player* target; - if (!extractPlayerTarget(*args != '"' ? (char*)args : NULL, &target)) - return false; - - char* tailStr = *args != '"' ? strtok(NULL, "") : (char*)args; - if (!tailStr) - return false; - - char* guildStr = extractQuotedArg(tailStr); - if (!guildStr) - return false; - - std::string guildname = guildStr; - - if (target->GetGuildId()) - { - SendSysMessage (LANG_PLAYER_IN_GUILD); - return true; - } - - Guild *guild = new Guild; - if (!guild->Create (target,guildname)) - { - delete guild; - SendSysMessage (LANG_GUILD_NOT_CREATED); - SetSentErrorMessage (true); - return false; - } - - objmgr.AddGuild (guild); - return true; -} - -bool ChatHandler::HandleGuildInviteCommand(const char *args) -{ - if (!*args) - return false; - - // if not guild name only (in "") then player name - uint64 target_guid; - if (!extractPlayerTarget(*args != '"' ? (char*)args : NULL, NULL, &target_guid)) - return false; - - char* tailStr = *args != '"' ? strtok(NULL, "") : (char*)args; - if (!tailStr) - return false; - - char* guildStr = extractQuotedArg(tailStr); - if (!guildStr) - return false; - - std::string glName = guildStr; - Guild* targetGuild = objmgr.GetGuildByName (glName); - if (!targetGuild) - return false; - - // player's guild membership checked in AddMember before add - if (!targetGuild->AddMember (target_guid,targetGuild->GetLowestRank ())) - return false; - - return true; -} - -bool ChatHandler::HandleGuildUninviteCommand(const char *args) -{ - Player* target; - uint64 target_guid; - if (!extractPlayerTarget((char*)args,&target,&target_guid)) - return false; - - uint32 glId = target ? target->GetGuildId () : Player::GetGuildIdFromDB (target_guid); - if (!glId) - return false; - - Guild* targetGuild = objmgr.GetGuildById (glId); - if (!targetGuild) - return false; - - targetGuild->DelMember (target_guid); - return true; -} - -bool ChatHandler::HandleGuildRankCommand(const char *args) -{ - char* nameStr; - char* rankStr; - extractOptFirstArg((char*)args,&nameStr,&rankStr); - if (!rankStr) - return false; - - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) - return false; - - uint32 glId = target ? target->GetGuildId () : Player::GetGuildIdFromDB (target_guid); - if (!glId) - return false; - - Guild* targetGuild = objmgr.GetGuildById (glId); - if (!targetGuild) - return false; - - uint32 newrank = uint32 (atoi (rankStr)); - if (newrank > targetGuild->GetLowestRank ()) - return false; - - targetGuild->ChangeRank (target_guid,newrank); - return true; -} - -bool ChatHandler::HandleGuildDeleteCommand(const char *args) -{ - if (!*args) - return false; - - char* guildStr = extractQuotedArg((char*)args); - if (!guildStr) - return false; - - std::string gld = guildStr; - - Guild* targetGuild = objmgr.GetGuildByName (gld); - if (!targetGuild) - return false; - - targetGuild->Disband (); - - return true; -} - -bool ChatHandler::HandleGetDistanceCommand(const char *args) -{ - WorldObject* obj = NULL; - - if (*args) - { - uint64 guid = extractGuidFromLink((char*)args); - if (guid) - obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - - if (!obj) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - } - else - { - obj = getSelectedUnit(); - - if (!obj) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - } - - PSendSysMessage(LANG_DISTANCE, m_session->GetPlayer()->GetDistance(obj), m_session->GetPlayer()->GetDistance2d(obj), m_session->GetPlayer()->GetExactDist(obj), m_session->GetPlayer()->GetExactDist2d(obj)); - return true; -} - -bool ChatHandler::HandleDieCommand(const char* /*args*/) -{ - Unit* target = getSelectedUnit(); - - if (!target || !m_session->GetPlayer()->GetSelection()) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (target->GetTypeId() == TYPEID_PLAYER) - { - if (HasLowerSecurity((Player*)target,0,false)) - return false; - } - - if (target->isAlive()) - { - if (sWorld.getConfig(CONFIG_DIE_COMMAND_MODE)) - m_session->GetPlayer()->Kill(target); - else - m_session->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - return true; -} - -bool ChatHandler::HandleDamageCommand(const char * args) -{ - if (!*args) - return false; - - Unit* target = getSelectedUnit(); - - if (!target || !m_session->GetPlayer()->GetSelection()) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (!target->isAlive()) - return true; - - char* damageStr = strtok((char*)args, " "); - if (!damageStr) - return false; - - int32 damage_int = atoi((char*)damageStr); - if (damage_int <= 0) - return true; - - uint32 damage = damage_int; - - char* schoolStr = strtok((char*)NULL, " "); - - // flat melee damage without resistence/etc reduction - if (!schoolStr) - { - m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - if (target != m_session->GetPlayer()) - m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); - return true; - } - - uint32 school = schoolStr ? atoi((char*)schoolStr) : SPELL_SCHOOL_NORMAL; - if (school >= MAX_SPELL_SCHOOL) - return false; - - SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); - - if (schoolmask & SPELL_SCHOOL_MASK_NORMAL) - damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage, NULL, BASE_ATTACK); - - char* spellStr = strtok((char*)NULL, " "); - - // melee damage by specific school - if (!spellStr) - { - uint32 absorb = 0; - uint32 resist = 0; - - m_session->GetPlayer()->CalcAbsorbResist(target,schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); - - if (damage <= absorb + resist) - return true; - - damage -= absorb + resist; - - m_session->GetPlayer()->DealDamageMods(target,damage,&absorb); - m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); - m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); - return true; - } - - // non-melee damage - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spellid = extractSpellIdFromLink((char*)args); - if (!spellid || !sSpellStore.LookupEntry(spellid)) - return false; - - m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage); - return true; -} - -bool ChatHandler::HandleModifyArenaCommand(const char * args) -{ - if (!*args) - return false; - - Player *target = getSelectedPlayer(); - if (!target) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - int32 amount = (uint32)atoi(args); - - target->ModifyArenaPoints(amount); - - PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, GetNameLink(target).c_str(), target->GetArenaPoints()); - - return true; -} - -bool ChatHandler::HandleReviveCommand(const char *args) -{ - Player* target; - uint64 target_guid; - if (!extractPlayerTarget((char*)args,&target,&target_guid)) - return false; - - if (target) - { - target->ResurrectPlayer(target->GetSession()->GetSecurity() > SEC_PLAYER ? 1.0f : 0.5f); - target->SpawnCorpseBones(); - target->SaveToDB(); - } - else - // will resurrected at login without corpse - ObjectAccessor::Instance().ConvertCorpseForPlayer(target_guid); - - return true; -} - -bool ChatHandler::HandleAuraCommand(const char *args) -{ - Unit *target = getSelectedUnit(); - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spellID = extractSpellIdFromLink((char*)args); - - if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID)) - Aura::TryCreate(spellInfo, target, target); - - return true; -} - -bool ChatHandler::HandleUnAuraCommand(const char *args) -{ - Unit *target = getSelectedUnit(); - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - std::string argstr = args; - if (argstr == "all") - { - target->RemoveAllAuras(); - return true; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spellID = extractSpellIdFromLink((char*)args); - if (!spellID) - return false; - - target->RemoveAurasDueToSpell(spellID); - - return true; -} - -bool ChatHandler::HandleLinkGraveCommand(const char *args) -{ - if (!*args) - return false; - - char* px = strtok((char*)args, " "); - if (!px) - return false; - - uint32 g_id = (uint32)atoi(px); - - uint32 g_team; - - char* px2 = strtok(NULL, " "); - - if (!px2) - g_team = 0; - else if (strncmp(px2,"horde",6) == 0) - g_team = HORDE; - else if (strncmp(px2,"alliance",9) == 0) - g_team = ALLIANCE; - else - return false; - - WorldSafeLocsEntry const* graveyard = sWorldSafeLocsStore.LookupEntry(g_id); - - if (!graveyard) - { - PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST, g_id); - SetSentErrorMessage(true); - return false; - } - - Player* player = m_session->GetPlayer(); - - uint32 zoneId = player->GetZoneId(); - - AreaTableEntry const *areaEntry = GetAreaEntryByAreaID(zoneId); - if (!areaEntry || areaEntry->zone !=0) - { - PSendSysMessage(LANG_COMMAND_GRAVEYARDWRONGZONE, g_id,zoneId); - SetSentErrorMessage(true); - return false; - } - - if (objmgr.AddGraveYardLink(g_id,zoneId,g_team)) - PSendSysMessage(LANG_COMMAND_GRAVEYARDLINKED, g_id,zoneId); - else - PSendSysMessage(LANG_COMMAND_GRAVEYARDALRLINKED, g_id,zoneId); - - return true; -} - -bool ChatHandler::HandleNearGraveCommand(const char *args) -{ - uint32 g_team; - - size_t argslen = strlen(args); - - if (!*args) - g_team = 0; - else if (strncmp((char*)args,"horde",argslen) == 0) - g_team = HORDE; - else if (strncmp((char*)args,"alliance",argslen) == 0) - g_team = ALLIANCE; - else - return false; - - Player* player = m_session->GetPlayer(); - uint32 zone_id = player->GetZoneId(); - - WorldSafeLocsEntry const* graveyard = objmgr.GetClosestGraveYard( - player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(),player->GetMapId(),g_team); - - if (graveyard) - { - uint32 g_id = graveyard->ID; - - GraveYardData const* data = objmgr.FindGraveYardData(g_id,zone_id); - if (!data) - { - PSendSysMessage(LANG_COMMAND_GRAVEYARDERROR,g_id); - SetSentErrorMessage(true); - return false; - } - - g_team = data->team; - - std::string team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_NOTEAM); - - if (g_team == 0) - team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ANY); - else if (g_team == HORDE) - team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_HORDE); - else if (g_team == ALLIANCE) - team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ALLIANCE); - - PSendSysMessage(LANG_COMMAND_GRAVEYARDNEAREST, g_id,team_name.c_str(),zone_id); - } - else - { - std::string team_name; - - if (g_team == 0) - team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ANY); - else if (g_team == HORDE) - team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_HORDE); - else if (g_team == ALLIANCE) - team_name = GetTrinityString(LANG_COMMAND_GRAVEYARD_ALLIANCE); - - if (g_team == ~uint32(0)) - PSendSysMessage(LANG_COMMAND_ZONENOGRAVEYARDS, zone_id); - else - PSendSysMessage(LANG_COMMAND_ZONENOGRAFACTION, zone_id,team_name.c_str()); - } - - return true; -} - -//-----------------------Npc Commands----------------------- -bool ChatHandler::HandleNpcAllowMovementCommand(const char* /*args*/) -{ - if (sWorld.getAllowMovement()) - { - sWorld.SetAllowMovement(false); - SendSysMessage(LANG_CREATURE_MOVE_DISABLED); - } - else - { - sWorld.SetAllowMovement(true); - SendSysMessage(LANG_CREATURE_MOVE_ENABLED); - } - return true; -} - -bool ChatHandler::HandleNpcChangeEntryCommand(const char *args) -{ - if (!*args) - return false; - - uint32 newEntryNum = atoi(args); - if (!newEntryNum) - return false; - - Unit* unit = getSelectedUnit(); - if (!unit || unit->GetTypeId() != TYPEID_UNIT) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - Creature* creature = unit->ToCreature(); - if (creature->UpdateEntry(newEntryNum)) - SendSysMessage(LANG_DONE); - else - SendSysMessage(LANG_ERROR); - return true; -} - -bool ChatHandler::HandleNpcInfoCommand(const char* /*args*/) -{ - Creature* target = getSelectedCreature(); - - if (!target) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - uint32 faction = target->getFaction(); - uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS); - uint32 displayid = target->GetDisplayId(); - uint32 nativeid = target->GetNativeDisplayId(); - uint32 Entry = target->GetEntry(); - CreatureInfo const* cInfo = target->GetCreatureInfo(); - - int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); - if (curRespawnDelay < 0) - curRespawnDelay = 0; - std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true); - std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true); - - PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), faction, npcflags, Entry, displayid, nativeid); - PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); - PSendSysMessage(LANG_NPCINFO_HEALTH,target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); - PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction()); - PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str()); - PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->lootid,cInfo->pickpocketLootId,cInfo->SkinLootId); - PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId()); - PSendSysMessage(LANG_NPCINFO_PHASEMASK, target->GetPhaseMask()); - PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); - PSendSysMessage(LANG_NPCINFO_POSITION,float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); - if (const CreatureData* const linked = target->GetLinkedRespawnCreatureData()) - if (CreatureInfo const *master = GetCreatureInfo(linked->id)) - PSendSysMessage(LANG_NPCINFO_LINKGUID, objmgr.GetLinkedRespawnGuid(target->GetDBTableGUIDLow()), linked->id, master->Name); - - if ((npcflags & UNIT_NPC_FLAG_VENDOR)) - { - SendSysMessage(LANG_NPCINFO_VENDOR); - } - if ((npcflags & UNIT_NPC_FLAG_TRAINER)) - { - SendSysMessage(LANG_NPCINFO_TRAINER); - } - - return true; -} - -//play npc emote -bool ChatHandler::HandleNpcPlayEmoteCommand(const char *args) -{ - uint32 emote = atoi((char*)args); - - Creature* target = getSelectedCreature(); - if (!target) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote); - - return true; -} - -//TODO: NpcCommands that needs to be fixed : - -bool ChatHandler::HandleNpcAddWeaponCommand(const char* /*args*/) -{ - /*if (!*args) - return false; - - uint64 guid = m_session->GetPlayer()->GetSelection(); - if (guid == 0) - { - SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature *pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - - if (!pCreature) - { - SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - char* pSlotID = strtok((char*)args, " "); - if (!pSlotID) - return false; - - char* pItemID = strtok(NULL, " "); - if (!pItemID) - return false; - - uint32 ItemID = atoi(pItemID); - uint32 SlotID = atoi(pSlotID); - - ItemPrototype* tmpItem = objmgr.GetItemPrototype(ItemID); - - bool added = false; - if (tmpItem) - { - switch(SlotID) - { - case 1: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, ItemID); - added = true; - break; - case 2: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_01, ItemID); - added = true; - break; - case 3: - pCreature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY_02, ItemID); - added = true; - break; - default: - PSendSysMessage(LANG_ITEM_SLOT_NOT_EXIST,SlotID); - added = false; - break; - } - - if (added) - PSendSysMessage(LANG_ITEM_ADDED_TO_SLOT,ItemID,tmpItem->Name1,SlotID); - } - else - { - PSendSysMessage(LANG_ITEM_NOT_FOUND,ItemID); - return true; - } - */ - return true; -} -//---------------------------------------------------------- - -bool ChatHandler::HandleExploreCheatCommand(const char *args) -{ - if (!*args) - return false; - - int flag = atoi((char*)args); - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (flag != 0) - { - PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetNameLink().c_str()); - } - else - { - PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, GetNameLink(chr).c_str()); - if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetNameLink().c_str()); - } - - for (uint8 i=0; iGetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0xFFFFFFFF); - } - else - { - m_session->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i,0); - } - } - - return true; -} - -bool ChatHandler::HandleHoverCommand(const char *args) -{ - char* px = strtok((char*)args, " "); - uint32 flag; - if (!px) - flag = 1; - else - flag = atoi(px); - - m_session->GetPlayer()->SetHover(flag); - - if (flag) - SendSysMessage(LANG_HOVER_ENABLED); - else - SendSysMessage(LANG_HOVER_DISABLED); - - return true; -} - -void ChatHandler::HandleCharacterLevel(Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel) -{ - if (player) - { - player->GiveLevel(newlevel); - player->InitTalentForLevel(); - player->SetUInt32Value(PLAYER_XP,0); - - if (needReportToTarget(player)) - { - if (oldlevel == newlevel) - ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_PROGRESS_RESET,GetNameLink().c_str()); - else if (oldlevel < newlevel) - ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_UP,GetNameLink().c_str(),newlevel); - else // if (oldlevel > newlevel) - ChatHandler(player).PSendSysMessage(LANG_YOURS_LEVEL_DOWN,GetNameLink().c_str(),newlevel); - } - } - else - { - // update level and XP at level, all other will be updated at loading - CharacterDatabase.PExecute("UPDATE characters SET level = '%u', xp = 0 WHERE guid = '%u'", newlevel, GUID_LOPART(player_guid)); - } -} - -bool ChatHandler::HandleCharacterLevelCommand(const char *args) -{ - char* nameStr; - char* levelStr; - extractOptFirstArg((char*)args,&nameStr,&levelStr); - if (!levelStr) - return false; - - // exception opt second arg: .character level $name - if (isalpha(levelStr[0])) - { - nameStr = levelStr; - levelStr = NULL; // current level will used - } - - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) - return false; - - int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid); - int32 newlevel = levelStr ? atoi(levelStr) : oldlevel; - - if (newlevel < 1) - return false; // invalid level - - if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level - newlevel = STRONG_MAX_LEVEL; - - HandleCharacterLevel(target,target_guid,oldlevel,newlevel); - - if (!m_session || m_session->GetPlayer() != target) // including player == NULL - { - std::string nameLink = playerLink(target_name); - PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); - } - - return true; -} - -bool ChatHandler::HandleLevelUpCommand(const char *args) -{ - char* nameStr; - char* levelStr; - extractOptFirstArg((char*)args,&nameStr,&levelStr); - - // exception opt second arg: .character level $name - if (levelStr && isalpha(levelStr[0])) - { - nameStr = levelStr; - levelStr = NULL; // current level will used - } - - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget(nameStr,&target,&target_guid,&target_name)) - return false; - - int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid); - int32 addlevel = levelStr ? atoi(levelStr) : 1; - int32 newlevel = oldlevel + addlevel; - - if (newlevel < 1) - newlevel = 1; - - if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level - newlevel = STRONG_MAX_LEVEL; - - HandleCharacterLevel(target,target_guid,oldlevel,newlevel); - - if (!m_session || m_session->GetPlayer() != target) // including chr == NULL - { - std::string nameLink = playerLink(target_name); - PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); - } - - return true; -} - -bool ChatHandler::HandleShowAreaCommand(const char *args) -{ - if (!*args) - return false; - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - int area = GetAreaFlagByAreaID(atoi((char*)args)); - int offset = area / 32; - uint32 val = (uint32)(1 << (area % 32)); - - if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - uint32 currFields = chr->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); - chr->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val)); - - SendSysMessage(LANG_EXPLORE_AREA); - return true; -} - -bool ChatHandler::HandleHideAreaCommand(const char *args) -{ - if (!*args) - return false; - - Player *chr = getSelectedPlayer(); - if (chr == NULL) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - int area = GetAreaFlagByAreaID(atoi((char*)args)); - int offset = area / 32; - uint32 val = (uint32)(1 << (area % 32)); - - if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) - { - SendSysMessage(LANG_BAD_VALUE); - SetSentErrorMessage(true); - return false; - } - - uint32 currFields = chr->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); - chr->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields ^ val)); - - SendSysMessage(LANG_UNEXPLORE_AREA); - return true; -} - -bool ChatHandler::HandleBankCommand(const char* /*args*/) -{ - m_session->SendShowBank(m_session->GetPlayer()->GetGUID()); - - return true; -} - -bool ChatHandler::HandleChangeWeather(const char *args) -{ - if (!*args) - return false; - - //Weather is OFF - if (!sWorld.getConfig(CONFIG_WEATHER)) - { - SendSysMessage(LANG_WEATHER_DISABLED); - SetSentErrorMessage(true); - return false; - } - - //*Change the weather of a cell - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - - if (!px || !py) - return false; - - uint32 type = (uint32)atoi(px); //0 to 3, 0: fine, 1: rain, 2: snow, 3: sand - float grade = (float)atof(py); //0 to 1, sending -1 is instand good weather - - Player *player = m_session->GetPlayer(); - uint32 zoneid = player->GetZoneId(); - - Weather* wth = sWorld.FindWeather(zoneid); - - if (!wth) - wth = sWorld.AddWeather(zoneid); - if (!wth) - { - SendSysMessage(LANG_NO_WEATHER); - SetSentErrorMessage(true); - return false; - } - - wth->SetWeather(WeatherType(type), grade); - - return true; -} - -bool ChatHandler::HandleDebugSet32Bit(const char *args) -{ - if (!*args) - return false; - - WorldObject* target = getSelectedObject(); - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - - if (!px || !py) - return false; - - uint32 Opcode = (uint32)atoi(px); - uint32 Value = (uint32)atoi(py); - if (Value > 32) //uint32 = 32 bits - return false; - - sLog.outDebug(GetTrinityString(LANG_SET_32BIT), Opcode, Value); - - uint32 iValue = Value ? 1 << (Value - 1) : 0; - target->SetUInt32Value(Opcode , iValue); - - PSendSysMessage(LANG_SET_32BIT_FIELD, Opcode, iValue); - return true; -} - -bool ChatHandler::HandleTeleAddCommand(const char * args) -{ - if (!*args) - return false; - - Player *player=m_session->GetPlayer(); - if (!player) - return false; - - std::string name = args; - - if (objmgr.GetGameTele(name)) - { - SendSysMessage(LANG_COMMAND_TP_ALREADYEXIST); - SetSentErrorMessage(true); - return false; - } - - GameTele tele; - tele.position_x = player->GetPositionX(); - tele.position_y = player->GetPositionY(); - tele.position_z = player->GetPositionZ(); - tele.orientation = player->GetOrientation(); - tele.mapId = player->GetMapId(); - tele.name = name; - - if (objmgr.AddGameTele(tele)) - { - SendSysMessage(LANG_COMMAND_TP_ADDED); - } - else - { - SendSysMessage(LANG_COMMAND_TP_ADDEDERR); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandleTeleDelCommand(const char * args) -{ - if (!*args) - return false; - - std::string name = args; - - if (!objmgr.DeleteGameTele(name)) - { - SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); - SetSentErrorMessage(true); - return false; - } - - SendSysMessage(LANG_COMMAND_TP_DELETED); - return true; -} - -bool ChatHandler::HandleListAurasCommand (const char * /*args*/) -{ - Unit *unit = getSelectedUnit(); - if (!unit) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - char const* talentStr = GetTrinityString(LANG_TALENT); - char const* passiveStr = GetTrinityString(LANG_PASSIVE); - - Unit::AuraApplicationMap const& uAuras = unit->GetAppliedAuras(); - PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size()); - for (Unit::AuraApplicationMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) - { - bool talent = GetTalentSpellCost(itr->second->GetBase()->GetId()) > 0; - - AuraApplication const * aurApp = itr->second; - Aura const * aura = aurApp->GetBase(); - char const* name = aura->GetSpellProto()->SpellName[GetSessionDbcLocale()]; - - if (m_session) - { - std::ostringstream ss_name; - ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r"; - - PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), aurApp->GetEffectMask(), - aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), - aura->GetDuration(), aura->GetMaxDuration(), - ss_name.str().c_str(), - (aura->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), - IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(aura->GetCasterGUID())); - } - else - { - PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), aurApp->GetEffectMask(), - aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), - aura->GetDuration(), aura->GetMaxDuration(), - name, - (aura->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), - IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(aura->GetCasterGUID())); - } - } - for (uint16 i = 0; i < TOTAL_AURAS; ++i) - { - Unit::AuraEffectList const& uAuraList = unit->GetAuraEffectsByType(AuraType(i)); - if (uAuraList.empty()) continue; - PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, uAuraList.size(), i); - for (Unit::AuraEffectList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) - { - //bool talent = GetTalentSpellCost((*itr)->GetId()) > 0; - - char const* name = (*itr)->GetSpellProto()->SpellName[GetSessionDbcLocale()]; - - std::ostringstream ss_name; - ss_name << "|cffffffff|Hspell:" << (*itr)->GetId() << "|h[" << name << "]|h|r"; - - PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), - (*itr)->GetAmount()); - } - } - return true; -} - -bool ChatHandler::HandleResetAchievementsCommand (const char * args) -{ - Player* target; - uint64 target_guid; - if (!extractPlayerTarget((char*)args,&target,&target_guid)) - return false; - - if (target) - target->GetAchievementMgr().Reset(); - else - AchievementMgr::DeleteFromDB(GUID_LOPART(target_guid)); - - return true; -} - -bool ChatHandler::HandleResetHonorCommand (const char * args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); - target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); - target->SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, 0); - target->SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); - target->SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); - target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); - - return true; -} - -static bool HandleResetStatsOrLevelHelper(Player* player) -{ - ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(player->getClass()); - if (!cEntry) - { - sLog.outError("Class %u not found in DBC (Wrong DBC files?)",player->getClass()); - return false; - } - - uint8 powertype = cEntry->powerType; - - // reset m_form if no aura - if (!player->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT)) - player->m_form = FORM_NONE; - - player->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); - player->SetFloatValue(UNIT_FIELD_COMBATREACH, DEFAULT_COMBAT_REACH); - - player->setFactionForRace(player->getRace()); - - player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powertype << 24))); - - // reset only if player not in some form; - if (player->m_form == FORM_NONE) - player->InitDisplayIds(); - - player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); - player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form); - - player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); - - //-1 is default value - player->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); - - //player->SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000); - return true; -} - -bool ChatHandler::HandleResetLevelCommand(const char * args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - if (!HandleResetStatsOrLevelHelper(target)) - return false; - - // set starting level - uint32 start_level = target->getClass() != CLASS_DEATH_KNIGHT - ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) - : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); - - target->_ApplyAllLevelScaleItemMods(false); - - target->SetLevel(start_level); - target->InitRunes(); - target->InitStatsForLevel(true); - target->InitTaxiNodesForLevel(); - target->InitGlyphsForLevel(); - target->InitTalentForLevel(); - target->SetUInt32Value(PLAYER_XP,0); - - target->_ApplyAllLevelScaleItemMods(true); - - // reset level for pet - if (Pet* pet = target->GetPet()) - pet->SynchronizeLevelWithOwner(); - - return true; -} - -bool ChatHandler::HandleResetStatsCommand(const char * args) -{ - Player* target; - if (!extractPlayerTarget((char*)args,&target)) - return false; - - if (!HandleResetStatsOrLevelHelper(target)) - return false; - - target->InitRunes(); - target->InitStatsForLevel(true); - target->InitTaxiNodesForLevel(); - target->InitGlyphsForLevel(); - target->InitTalentForLevel(); - - return true; -} - -bool ChatHandler::HandleResetSpellsCommand(const char * args) -{ - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - return false; - - if (target) - { - target->resetSpells(/* bool myClassOnly */); - - ChatHandler(target).SendSysMessage(LANG_RESET_SPELLS); - if (!m_session || m_session->GetPlayer() != target) - PSendSysMessage(LANG_RESET_SPELLS_ONLINE,GetNameLink(target).c_str()); - } - else - { - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_SPELLS), GUID_LOPART(target_guid)); - PSendSysMessage(LANG_RESET_SPELLS_OFFLINE,target_name.c_str()); - } - - return true; -} - -bool ChatHandler::HandleResetTalentsCommand(const char * args) -{ - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget((char*)args,&target,&target_guid,&target_name)) - { - // Try reset talents as Hunter Pet - Creature* creature = getSelectedCreature(); - if (!*args && creature && creature->isPet()) - { - Unit *owner = creature->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet *)creature)->IsPermanentPetFor(owner->ToPlayer())) - { - ((Pet *)creature)->resetTalents(true); - owner->ToPlayer()->SendTalentsInfoData(true); - - ChatHandler(owner->ToPlayer()).SendSysMessage(LANG_RESET_PET_TALENTS); - if (!m_session || m_session->GetPlayer() != owner->ToPlayer()) - PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE,GetNameLink(owner->ToPlayer()).c_str()); - } - return true; - } - - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (target) - { - target->resetTalents(true); - target->SendTalentsInfoData(false); - ChatHandler(target).SendSysMessage(LANG_RESET_TALENTS); - if (!m_session || m_session->GetPlayer() != target) - PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(target).c_str()); - - Pet* pet = target->GetPet(); - Pet::resetTalentsForAllPetsOf(target,pet); - if (pet) - target->SendTalentsInfoData(true); - return true; - } - else if (target_guid) - { - uint32 at_flags = AT_LOGIN_NONE | AT_LOGIN_RESET_PET_TALENTS; - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",at_flags, GUID_LOPART(target_guid)); - std::string nameLink = playerLink(target_name); - PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,nameLink.c_str()); - return true; - } - - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; -} - -bool ChatHandler::HandleResetAllCommand(const char * args) -{ - if (!*args) - return false; - - std::string casename = args; - - AtLoginFlags atLogin; - - // Command specially created as single command to prevent using short case names - if (casename == "spells") - { - atLogin = AT_LOGIN_RESET_SPELLS; - sWorld.SendWorldText(LANG_RESETALL_SPELLS); - if (!m_session) - SendSysMessage(LANG_RESETALL_SPELLS); - } - else if (casename == "talents") - { - atLogin = AtLoginFlags(AT_LOGIN_RESET_TALENTS | AT_LOGIN_RESET_PET_TALENTS); - sWorld.SendWorldText(LANG_RESETALL_TALENTS); - if (!m_session) - SendSysMessage(LANG_RESETALL_TALENTS); - } - else - { - PSendSysMessage(LANG_RESETALL_UNKNOWN_CASE,args); - SetSentErrorMessage(true); - return false; - } - - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE (at_login & '%u') = '0'",atLogin,atLogin); - - ObjectAccessor::Guard guard(*HashMapHolder::GetLock()); - HashMapHolder::MapType const& plist = ObjectAccessor::Instance().GetPlayers(); - for (HashMapHolder::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) - itr->second->SetAtLoginFlag(atLogin); - - return true; -} - -bool ChatHandler::HandleServerShutDownCancelCommand(const char* /*args*/) -{ - sWorld.ShutdownCancel(); - return true; -} - -bool ChatHandler::HandleServerShutDownCommand(const char *args) -{ - if (!*args) - return false; - - char* time_str = strtok ((char*) args, " "); - char* exitcode_str = strtok (NULL, ""); - - int32 time = atoi (time_str); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0')) || time < 0) - return false; - - if (exitcode_str) - { - int32 exitcode = atoi (exitcode_str); - - // Handle atoi() errors - if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) - return false; - - // Exit code should be in range of 0-125, 126-255 is used - // in many shells for their own return codes and code > 255 - // is not supported in many others - if (exitcode < 0 || exitcode > 125) - return false; - - sWorld.ShutdownServ (time, 0, exitcode); - } - else - sWorld.ShutdownServ(time,0,SHUTDOWN_EXIT_CODE); - return true; -} - -bool ChatHandler::HandleServerRestartCommand(const char *args) -{ - if (!*args) - return false; - - char* time_str = strtok ((char*) args, " "); - char* exitcode_str = strtok (NULL, ""); - - int32 time = atoi (time_str); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0)) - return false; - - if (exitcode_str) - { - int32 exitcode = atoi (exitcode_str); - - // Handle atoi() errors - if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) - return false; - - // Exit code should be in range of 0-125, 126-255 is used - // in many shells for their own return codes and code > 255 - // is not supported in many others - if (exitcode < 0 || exitcode > 125) - return false; - - sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART, exitcode); - } - else - sWorld.ShutdownServ(time, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); - return true; -} - -bool ChatHandler::HandleServerIdleRestartCommand(const char *args) -{ - if (!*args) - return false; - - char* time_str = strtok ((char*) args, " "); - char* exitcode_str = strtok (NULL, ""); - - int32 time = atoi (time_str); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0)) - return false; - - if (exitcode_str) - { - int32 exitcode = atoi (exitcode_str); - - // Handle atoi() errors - if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) - return false; - - // Exit code should be in range of 0-125, 126-255 is used - // in many shells for their own return codes and code > 255 - // is not supported in many others - if (exitcode < 0 || exitcode > 125) - return false; - - sWorld.ShutdownServ (time, SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE, exitcode); - } - else - sWorld.ShutdownServ(time,SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE,RESTART_EXIT_CODE); - return true; -} - -bool ChatHandler::HandleServerIdleShutDownCommand(const char *args) -{ - if (!*args) - return false; - - char* time_str = strtok ((char*) args, " "); - char* exitcode_str = strtok (NULL, ""); - - int32 time = atoi (time_str); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if (time == 0 && (time_str[0] != '0' || time_str[1] != '\0') || time < 0) - return false; - - if (exitcode_str) - { - int32 exitcode = atoi (exitcode_str); - - // Handle atoi() errors - if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) - return false; - - // Exit code should be in range of 0-125, 126-255 is used - // in many shells for their own return codes and code > 255 - // is not supported in many others - if (exitcode < 0 || exitcode > 125) - return false; - - sWorld.ShutdownServ (time, SHUTDOWN_MASK_IDLE, exitcode); - } - else - sWorld.ShutdownServ(time,SHUTDOWN_MASK_IDLE,SHUTDOWN_EXIT_CODE); - return true; -} - -bool ChatHandler::HandleQuestAdd(const char *args) -{ - Player* player = getSelectedPlayer(); - if (!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // .addquest #entry' - // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hquest"); - if (!cId) - return false; - - uint32 entry = atol(cId); - - Quest const* pQuest = objmgr.GetQuestTemplate(entry); - - if (!pQuest) - { - PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND,entry); - SetSentErrorMessage(true); - return false; - } - - // check item starting quest (it can work incorrectly if added without item in inventory) - for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) - { - ItemPrototype const *pProto = sItemStorage.LookupEntry(id); - if (!pProto) - continue; - - if (pProto->StartQuest == entry) - { - PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, pProto->ItemId); - SetSentErrorMessage(true); - return false; - } - } - - // ok, normal (creature/GO starting) quest - if (player->CanAddQuest(pQuest, true)) - { - player->AddQuest(pQuest, NULL); - - if (player->CanCompleteQuest(entry)) - player->CompleteQuest(entry); - } - - return true; -} - -bool ChatHandler::HandleQuestRemove(const char *args) -{ - Player* player = getSelectedPlayer(); - if (!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // .removequest #entry' - // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hquest"); - if (!cId) - return false; - - uint32 entry = atol(cId); - - Quest const* pQuest = objmgr.GetQuestTemplate(entry); - - if (!pQuest) - { - PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); - SetSentErrorMessage(true); - return false; - } - - // remove all quest entries for 'entry' from quest log - for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot) - { - uint32 quest = player->GetQuestSlotQuestId(slot); - if (quest == entry) - { - player->SetQuestSlot(slot,0); - - // we ignore unequippable quest items in this case, its' still be equipped - player->TakeQuestSourceItem(quest, false); - } - } - - // set quest status to not started (will updated in DB at next save) - player->SetQuestStatus(entry, QUEST_STATUS_NONE); - - // reset rewarded for restart repeatable quest - player->getQuestStatusMap()[entry].m_rewarded = false; - - SendSysMessage(LANG_COMMAND_QUEST_REMOVED); - return true; -} - -bool ChatHandler::HandleQuestComplete(const char *args) -{ - Player* player = getSelectedPlayer(); - if (!player) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - // .quest complete #entry - // number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hquest"); - if (!cId) - return false; - - uint32 entry = atol(cId); - - Quest const* pQuest = objmgr.GetQuestTemplate(entry); - - // If player doesn't have the quest - if (!pQuest || player->GetQuestStatus(entry) == QUEST_STATUS_NONE) - { - PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); - SetSentErrorMessage(true); - return false; - } - - // Add quest items for quests that require items - for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x) - { - uint32 id = pQuest->ReqItemId[x]; - uint32 count = pQuest->ReqItemCount[x]; - if (!id || !count) - continue; - - uint32 curItemCount = player->GetItemCount(id,true); - - ItemPosCountVec dest; - uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count-curItemCount); - if (msg == EQUIP_ERR_OK) - { - Item* item = player->StoreNewItem(dest, id, true); - player->SendNewItem(item,count-curItemCount,true,false); - } - } - - // All creature/GO slain/casted (not required, but otherwise it will display "Creature slain 0/10") - for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - { - uint32 creature = pQuest->ReqCreatureOrGOId[i]; - uint32 creaturecount = pQuest->ReqCreatureOrGOCount[i]; - - if (uint32 spell_id = pQuest->ReqSpell[i]) - { - for (uint16 z = 0; z < creaturecount; ++z) - player->CastedCreatureOrGO(creature,0,spell_id); - } - else if (creature > 0) - { - if (CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(creature)) - for (uint16 z = 0; z < creaturecount; ++z) - player->KilledMonster(cInfo,0); - } - else if (creature < 0) - { - for (uint16 z = 0; z < creaturecount; ++z) - player->CastedCreatureOrGO(creature,0,0); - } - } - - // If the quest requires reputation to complete - if (uint32 repFaction = pQuest->GetRepObjectiveFaction()) - { - uint32 repValue = pQuest->GetRepObjectiveValue(); - uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); - if (curRep < repValue) - if (FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction)) - player->GetReputationMgr().SetReputation(factionEntry,repValue); - } - - // If the quest requires a SECOND reputation to complete - if (uint32 repFaction = pQuest->GetRepObjectiveFaction2()) - { - uint32 repValue2 = pQuest->GetRepObjectiveValue2(); - uint32 curRep = player->GetReputationMgr().GetReputation(repFaction); - if (curRep < repValue2) - if (FactionEntry const *factionEntry = sFactionStore.LookupEntry(repFaction)) - player->GetReputationMgr().SetReputation(factionEntry,repValue2); - } - - // If the quest requires money - int32 ReqOrRewMoney = pQuest->GetRewOrReqMoney(); - if (ReqOrRewMoney < 0) - player->ModifyMoney(-ReqOrRewMoney); - - player->CompleteQuest(entry); - return true; -} - -bool ChatHandler::HandleBanAccountCommand(const char *args) -{ - return HandleBanHelper(BAN_ACCOUNT,args); -} - -bool ChatHandler::HandleBanCharacterCommand(const char *args) -{ - return HandleBanHelper(BAN_CHARACTER,args); -} - -bool ChatHandler::HandleBanIPCommand(const char *args) -{ - return HandleBanHelper(BAN_IP,args); -} - -bool ChatHandler::HandleBanHelper(BanMode mode, const char *args) -{ - if (!*args) - return false; - - char* cnameOrIP = strtok ((char*)args, " "); - if (!cnameOrIP) - return false; - - std::string nameOrIP = cnameOrIP; - - char* duration = strtok (NULL," "); - if (!duration || !atoi(duration)) - return false; - - char* reason = strtok (NULL,""); - if (!reason) - return false; - - switch(mode) - { - case BAN_ACCOUNT: - if (!AccountMgr::normalizeString(nameOrIP)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,nameOrIP.c_str()); - SetSentErrorMessage(true); - return false; - } - break; - case BAN_CHARACTER: - if (!normalizePlayerName(nameOrIP)) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - break; - case BAN_IP: - if (!IsIPAddress(nameOrIP.c_str())) - return false; - break; - } - - switch(sWorld.BanAccount(mode, nameOrIP, duration, reason,m_session ? m_session->GetPlayerName() : "")) - { - case BAN_SUCCESS: - if (atoi(duration)>0) - PSendSysMessage(LANG_BAN_YOUBANNED,nameOrIP.c_str(),secsToTimeString(TimeStringToSecs(duration),true).c_str(),reason); - else - PSendSysMessage(LANG_BAN_YOUPERMBANNED,nameOrIP.c_str(),reason); - break; - case BAN_SYNTAX_ERROR: - return false; - case BAN_NOTFOUND: - switch(mode) - { - default: - PSendSysMessage(LANG_BAN_NOTFOUND,"account",nameOrIP.c_str()); - break; - case BAN_CHARACTER: - PSendSysMessage(LANG_BAN_NOTFOUND,"character",nameOrIP.c_str()); - break; - case BAN_IP: - PSendSysMessage(LANG_BAN_NOTFOUND,"ip",nameOrIP.c_str()); - break; - } - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandleUnBanAccountCommand(const char *args) -{ - return HandleUnBanHelper(BAN_ACCOUNT,args); -} - -bool ChatHandler::HandleUnBanCharacterCommand(const char *args) -{ - return HandleUnBanHelper(BAN_CHARACTER,args); -} - -bool ChatHandler::HandleUnBanIPCommand(const char *args) -{ - return HandleUnBanHelper(BAN_IP,args); -} - -bool ChatHandler::HandleUnBanHelper(BanMode mode, const char *args) -{ - if (!*args) - return false; - - char* cnameOrIP = strtok ((char*)args, " "); - if (!cnameOrIP) - return false; - - std::string nameOrIP = cnameOrIP; - - switch(mode) - { - case BAN_ACCOUNT: - if (!AccountMgr::normalizeString(nameOrIP)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,nameOrIP.c_str()); - SetSentErrorMessage(true); - return false; - } - break; - case BAN_CHARACTER: - if (!normalizePlayerName(nameOrIP)) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - break; - case BAN_IP: - if (!IsIPAddress(nameOrIP.c_str())) - return false; - break; - } - - if (sWorld.RemoveBanAccount(mode,nameOrIP)) - PSendSysMessage(LANG_UNBAN_UNBANNED,nameOrIP.c_str()); - else - PSendSysMessage(LANG_UNBAN_ERROR,nameOrIP.c_str()); - - return true; -} - -bool ChatHandler::HandleBanInfoAccountCommand(const char *args) -{ - if (!*args) - return false; - - char* cname = strtok((char*)args, ""); - if (!cname) - return false; - - std::string account_name = cname; - if (!AccountMgr::normalizeString(account_name)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - uint32 accountid = accmgr.GetId(account_name); - if (!accountid) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - return true; - } - - return HandleBanInfoHelper(accountid,account_name.c_str()); -} - -bool ChatHandler::HandleBanInfoCharacterCommand(const char *args) -{ - Player* target; - uint64 target_guid; - if (!extractPlayerTarget((char*)args,&target,&target_guid)) - return false; - - uint32 accountid = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid); - - std::string accountname; - if (!accmgr.GetName(accountid,accountname)) - { - PSendSysMessage(LANG_BANINFO_NOCHARACTER); - return true; - } - - return HandleBanInfoHelper(accountid,accountname.c_str()); -} - -bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) -{ - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid); - if (!result) - { - PSendSysMessage(LANG_BANINFO_NOACCOUNTBAN, accountname); - return true; - } - - PSendSysMessage(LANG_BANINFO_BANHISTORY,accountname); - do - { - Field* fields = result->Fetch(); - - time_t unbandate = time_t(fields[3].GetUInt64()); - bool active = false; - if (fields[2].GetBool() && (fields[1].GetUInt64() == (uint64)0 ||unbandate >= time(NULL))) - active = true; - bool permanent = (fields[1].GetUInt64() == (uint64)0); - std::string bantime = permanent?GetTrinityString(LANG_BANINFO_INFINITE):secsToTimeString(fields[1].GetUInt64(), true); - PSendSysMessage(LANG_BANINFO_HISTORYENTRY, - fields[0].GetString(), bantime.c_str(), active ? GetTrinityString(LANG_BANINFO_YES):GetTrinityString(LANG_BANINFO_NO), fields[4].GetString(), fields[5].GetString()); - }while (result->NextRow()); - - return true; -} - -bool ChatHandler::HandleBanInfoIPCommand(const char *args) -{ - if (!*args) - return false; - - char* cIP = strtok ((char*)args, ""); - if (!cIP) - return false; - - if (!IsIPAddress(cIP)) - return false; - - std::string IP = cIP; - - LoginDatabase.escape_string(IP); - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str()); - if (!result) - { - PSendSysMessage(LANG_BANINFO_NOIP); - return true; - } - - Field *fields = result->Fetch(); - bool permanent = !fields[6].GetUInt64(); - PSendSysMessage(LANG_BANINFO_IPENTRY, - fields[0].GetString(), fields[1].GetString(), permanent ? GetTrinityString(LANG_BANINFO_NEVER):fields[2].GetString(), - permanent ? GetTrinityString(LANG_BANINFO_INFINITE):secsToTimeString(fields[3].GetUInt64(), true).c_str(), fields[4].GetString(), fields[5].GetString()); - - return true; -} - -bool ChatHandler::HandleBanListCharacterCommand(const char *args) -{ - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); - - char* cFilter = strtok ((char*)args, " "); - if (!cFilter) - return false; - - std::string filter = cFilter; - LoginDatabase.escape_string(filter); - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),filter.c_str()); - if (!result) - { - PSendSysMessage(LANG_BANLIST_NOCHARACTER); - return true; - } - - return HandleBanListHelper(result); -} - -bool ChatHandler::HandleBanListAccountCommand(const char *args) -{ - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); - - char* cFilter = strtok((char*)args, " "); - std::string filter = cFilter ? cFilter : ""; - LoginDatabase.escape_string(filter); - - QueryResult_AutoPtr result; - - if (filter.empty()) - { - result = LoginDatabase.Query("SELECT account.id, username FROM account, account_banned" - " WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id"); - } - else - { - result = LoginDatabase.PQuery("SELECT account.id, username FROM account, account_banned" - " WHERE account.id = account_banned.id AND active = 1 AND username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" GROUP BY account.id", - filter.c_str()); - } - - if (!result) - { - PSendSysMessage(LANG_BANLIST_NOACCOUNT); - return true; - } - - return HandleBanListHelper(result); -} - -bool ChatHandler::HandleBanListHelper(QueryResult_AutoPtr result) -{ - PSendSysMessage(LANG_BANLIST_MATCHINGACCOUNT); - - // Chat short output - if (m_session) - { - do - { - Field* fields = result->Fetch(); - uint32 accountid = fields[0].GetUInt32(); - - QueryResult_AutoPtr banresult = LoginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid); - if (banresult) - { - Field* fields2 = banresult->Fetch(); - PSendSysMessage("%s",fields2[0].GetString()); - } - } while (result->NextRow()); - } - // Console wide output - else - { - SendSysMessage(LANG_BANLIST_ACCOUNTS); - SendSysMessage(" ==============================================================================="); - SendSysMessage(LANG_BANLIST_ACCOUNTS_HEADER); - do - { - SendSysMessage("-------------------------------------------------------------------------------"); - Field *fields = result->Fetch(); - uint32 account_id = fields[0].GetUInt32 (); - - std::string account_name; - - // "account" case, name can be get in same query - if (result->GetFieldCount() > 1) - account_name = fields[1].GetCppString(); - // "character" case, name need extract from another DB - else - accmgr.GetName (account_id,account_name); - - // No SQL injection. id is uint32. - QueryResult_AutoPtr banInfo = LoginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id); - if (banInfo) - { - Field *fields2 = banInfo->Fetch(); - do - { - time_t t_ban = fields2[0].GetUInt64(); - tm* aTm_ban = localtime(&t_ban); - - if (fields2[0].GetUInt64() == fields2[1].GetUInt64()) - { - PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", - account_name.c_str(),aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, - fields2[2].GetString(),fields2[3].GetString()); - } - else - { - time_t t_unban = fields2[1].GetUInt64(); - tm* aTm_unban = localtime(&t_unban); - PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", - account_name.c_str(),aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, - aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min, - fields2[2].GetString(),fields2[3].GetString()); - } - }while (banInfo->NextRow()); - } - }while (result->NextRow()); - SendSysMessage(" ==============================================================================="); - } - return true; -} - -bool ChatHandler::HandleBanListIPCommand(const char *args) -{ - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); - - char* cFilter = strtok((char*)args, " "); - std::string filter = cFilter ? cFilter : ""; - LoginDatabase.escape_string(filter); - - QueryResult_AutoPtr result; - - if (filter.empty()) - { - result = LoginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" - " WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP())" - " ORDER BY unbandate"); - } - else - { - result = LoginDatabase.PQuery("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" - " WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP()) AND ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'") - " ORDER BY unbandate",filter.c_str()); - } - - if (!result) - { - PSendSysMessage(LANG_BANLIST_NOIP); - return true; - } - - PSendSysMessage(LANG_BANLIST_MATCHINGIP); - // Chat short output - if (m_session) - { - do - { - Field* fields = result->Fetch(); - PSendSysMessage("%s",fields[0].GetString()); - } while (result->NextRow()); - } - // Console wide output - else - { - SendSysMessage(LANG_BANLIST_IPS); - SendSysMessage(" ==============================================================================="); - SendSysMessage(LANG_BANLIST_IPS_HEADER); - do - { - SendSysMessage("-------------------------------------------------------------------------------"); - Field *fields = result->Fetch(); - time_t t_ban = fields[1].GetUInt64(); - tm* aTm_ban = localtime(&t_ban); - if (fields[1].GetUInt64() == fields[2].GetUInt64()) - { - PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", - fields[0].GetString(), aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, - fields[3].GetString(), fields[4].GetString()); - } - else - { - time_t t_unban = fields[2].GetUInt64(); - tm* aTm_unban = localtime(&t_unban); - PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", - fields[0].GetString(), aTm_ban->tm_year%100, aTm_ban->tm_mon+1, aTm_ban->tm_mday, aTm_ban->tm_hour, aTm_ban->tm_min, - aTm_unban->tm_year%100, aTm_unban->tm_mon+1, aTm_unban->tm_mday, aTm_unban->tm_hour, aTm_unban->tm_min, - fields[3].GetString(), fields[4].GetString()); - } - }while (result->NextRow()); - SendSysMessage(" ==============================================================================="); - } - - return true; -} - -bool ChatHandler::HandleRespawnCommand(const char* /*args*/) -{ - Player* pl = m_session->GetPlayer(); - - // accept only explicitly selected target (not implicitly self targeting case) - Unit* target = getSelectedUnit(); - if (pl->GetSelection() && target) - { - if (target->GetTypeId() != TYPEID_UNIT || target->isPet()) - { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (target->isDead()) - target->ToCreature()->Respawn(); - return true; - } - - CellPair p(Trinity::ComputeCellPair(pl->GetPositionX(), pl->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::RespawnDo u_do; - Trinity::WorldObjectWorker worker(pl,u_do); - - TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); - cell.Visit(p, obj_worker, *pl->GetMap()); - - return true; -} - -bool ChatHandler::HandleGMFlyCommand(const char *args) -{ - if (!*args) - return false; - - Player *target = getSelectedPlayer(); - if (!target) - target = m_session->GetPlayer(); - - WorldPacket data(12); - if (strncmp(args, "on", 3) == 0) - data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); - else if (strncmp(args, "off", 4) == 0) - data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); - else - { - SendSysMessage(LANG_USE_BOL); - return false; - } - data.append(target->GetPackGUID()); - data << uint32(0); // unknown - target->SendMessageToSet(&data, true); - PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, GetNameLink(target).c_str(), args); - return true; -} - -bool ChatHandler::HandlePDumpLoadCommand(const char *args) -{ - if (!*args) - return false; - - char * file = strtok((char*)args, " "); - if (!file) - return false; - - char * account = strtok(NULL, " "); - if (!account) - return false; - - std::string account_name = account; - if (!AccountMgr::normalizeString(account_name)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - uint32 account_id = accmgr.GetId(account_name); - if (!account_id) - { - account_id = atoi(account); // use original string - if (!account_id) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - } - - if (!accmgr.GetName(account_id,account_name)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - char* guid_str = NULL; - char* name_str = strtok(NULL, " "); - - std::string name; - if (name_str) - { - name = name_str; - // normalize the name if specified and check if it exists - if (!normalizePlayerName(name)) - { - PSendSysMessage(LANG_INVALID_CHARACTER_NAME); - SetSentErrorMessage(true); - return false; - } - - if (ObjectMgr::CheckPlayerName(name,true) != CHAR_NAME_SUCCESS) - { - PSendSysMessage(LANG_INVALID_CHARACTER_NAME); - SetSentErrorMessage(true); - return false; - } - - guid_str = strtok(NULL, " "); - } - - uint32 guid = 0; - - if (guid_str) - { - guid = atoi(guid_str); - if (!guid) - { - PSendSysMessage(LANG_INVALID_CHARACTER_GUID); - SetSentErrorMessage(true); - return false; - } - - if (objmgr.GetPlayerAccountIdByGUID(guid)) - { - PSendSysMessage(LANG_CHARACTER_GUID_IN_USE,guid); - SetSentErrorMessage(true); - return false; - } - } - - switch(PlayerDumpReader().LoadDump(file, account_id, name, guid)) - { - case DUMP_SUCCESS: - PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS); - break; - case DUMP_FILE_OPEN_ERROR: - PSendSysMessage(LANG_FILE_OPEN_FAIL,file); - SetSentErrorMessage(true); - return false; - case DUMP_FILE_BROKEN: - PSendSysMessage(LANG_DUMP_BROKEN,file); - SetSentErrorMessage(true); - return false; - case DUMP_TOO_MANY_CHARS: - PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL,account_name.c_str(),account_id); - SetSentErrorMessage(true); - return false; - default: - PSendSysMessage(LANG_COMMAND_IMPORT_FAILED); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandlePDumpWriteCommand(const char *args) -{ - if (!*args) - return false; - - char* file = strtok((char*)args, " "); - char* p2 = strtok(NULL, " "); - - if (!file || !p2) - return false; - - uint32 guid; - // character name can't start from number - if (isNumeric(p2[0])) - guid = atoi(p2); - else - { - std::string name = extractPlayerNameFromLink(p2); - if (name.empty()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - guid = objmgr.GetPlayerGUIDByName(name); - } - - if (!objmgr.GetPlayerAccountIdByGUID(guid)) - { - PSendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - switch(PlayerDumpWriter().WriteDump(file, guid)) - { - case DUMP_SUCCESS: - PSendSysMessage(LANG_COMMAND_EXPORT_SUCCESS); - break; - case DUMP_FILE_OPEN_ERROR: - PSendSysMessage(LANG_FILE_OPEN_FAIL,file); - SetSentErrorMessage(true); - return false; - default: - PSendSysMessage(LANG_COMMAND_EXPORT_FAILED); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandleMovegensCommand(const char* /*args*/) -{ - Unit* unit = getSelectedUnit(); - if (!unit) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_MOVEGENS_LIST,(unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"),unit->GetGUIDLow()); - - MotionMaster* mm = unit->GetMotionMaster(); - for (uint8 i = 0; i < MAX_MOTION_SLOT; ++i) - { - MovementGenerator* mg = mm->GetMotionSlot(i); - if (!mg) - { - SendSysMessage("Empty"); - continue; - } - switch(mg->GetMovementGeneratorType()) - { - case IDLE_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_IDLE); break; - case RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_RANDOM); break; - case WAYPOINT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_WAYPOINT); break; - case ANIMAL_RANDOM_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_ANIMAL_RANDOM); break; - case CONFUSED_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_CONFUSED); break; - case TARGETED_MOTION_TYPE: - { - if (unit->GetTypeId() == TYPEID_PLAYER) - { - TargetedMovementGenerator const* mgen = static_cast const*>(mg); - Unit* target = mgen->GetTarget(); - if (target) - PSendSysMessage(LANG_MOVEGENS_TARGETED_PLAYER,target->GetName(),target->GetGUIDLow()); - else - SendSysMessage(LANG_MOVEGENS_TARGETED_NULL); - } - else - { - TargetedMovementGenerator const* mgen = static_cast const*>(mg); - Unit* target = mgen->GetTarget(); - if (target) - PSendSysMessage(LANG_MOVEGENS_TARGETED_CREATURE,target->GetName(),target->GetGUIDLow()); - else - SendSysMessage(LANG_MOVEGENS_TARGETED_NULL); - } - break; - } - case HOME_MOTION_TYPE: - if (unit->GetTypeId() == TYPEID_UNIT) - { - float x,y,z; - mg->GetDestination(x,y,z); - PSendSysMessage(LANG_MOVEGENS_HOME_CREATURE,x,y,z); - } - else - SendSysMessage(LANG_MOVEGENS_HOME_PLAYER); - break; - case FLIGHT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FLIGHT); break; - case POINT_MOTION_TYPE: - { - float x,y,z; - mg->GetDestination(x,y,z); - PSendSysMessage(LANG_MOVEGENS_POINT,x,y,z); - break; - } - case FLEEING_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_FEAR); break; - case DISTRACT_MOTION_TYPE: SendSysMessage(LANG_MOVEGENS_DISTRACT); break; - default: - PSendSysMessage(LANG_MOVEGENS_UNKNOWN,mg->GetMovementGeneratorType()); - break; - } - } - return true; -} - -bool ChatHandler::HandleServerPLimitCommand(const char *args) -{ - if (*args) - { - char* param = strtok((char*)args, " "); - if (!param) - return false; - - int l = strlen(param); - - if (strncmp(param,"player",l) == 0) - sWorld.SetPlayerSecurityLimit(SEC_PLAYER); - else if (strncmp(param,"moderator",l) == 0) - sWorld.SetPlayerSecurityLimit(SEC_MODERATOR); - else if (strncmp(param,"gamemaster",l) == 0) - sWorld.SetPlayerSecurityLimit(SEC_GAMEMASTER); - else if (strncmp(param,"administrator",l) == 0) - sWorld.SetPlayerSecurityLimit(SEC_ADMINISTRATOR); - else if (strncmp(param,"reset",l) == 0) - sWorld.SetPlayerLimit(sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT)); - else - { - int val = atoi(param); - if (val < 0) - sWorld.SetPlayerSecurityLimit(AccountTypes(uint32(-val))); - else - sWorld.SetPlayerLimit(val); - } - - // kick all low security level players - if (sWorld.GetPlayerSecurityLimit() > SEC_PLAYER) - sWorld.KickAllLess(sWorld.GetPlayerSecurityLimit()); - } - - uint32 pLimit = sWorld.GetPlayerAmountLimit(); - AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); - char const* secName = ""; - switch(allowedAccountType) - { - case SEC_PLAYER: secName = "Player"; break; - case SEC_MODERATOR: secName = "Moderator"; break; - case SEC_GAMEMASTER: secName = "Gamemaster"; break; - case SEC_ADMINISTRATOR: secName = "Administrator"; break; - default: secName = ""; break; - } - - PSendSysMessage("Player limits: amount %u, min. security level %s.",pLimit,secName); - - return true; -} - -bool ChatHandler::HandleCastCommand(const char *args) -{ - if (!*args) - return false; - - Unit* target = getSelectedUnit(); - - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell) - return false; - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if (!spellInfo) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); - SetSentErrorMessage(true); - return false; - } - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str,"triggered",l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - m_session->GetPlayer()->CastSpell(target,spell,triggered); - - return true; -} - -bool ChatHandler::HandleCastBackCommand(const char *args) -{ - Creature* caster = getSelectedCreature(); - - if (!caster) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell || !sSpellStore.LookupEntry(spell)) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str,"triggered",l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - caster->SetFacingToObject(m_session->GetPlayer()); - - caster->CastSpell(m_session->GetPlayer(),spell,triggered); - - return true; -} - -bool ChatHandler::HandleCastDistCommand(const char *args) -{ - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell) - return false; - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if (!spellInfo) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); - SetSentErrorMessage(true); - return false; - } - - char *distStr = strtok(NULL, " "); - - float dist = 0; - - if (distStr) - sscanf(distStr, "%f", &dist); - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str,"triggered",l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - float x,y,z; - m_session->GetPlayer()->GetClosePoint(x,y,z,dist); - - m_session->GetPlayer()->CastSpell(x,y,z,spell,triggered); - return true; -} - -bool ChatHandler::HandleCastTargetCommand(const char *args) -{ - Creature* caster = getSelectedCreature(); - - if (!caster) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (!caster->getVictim()) - { - SendSysMessage(LANG_SELECTED_TARGET_NOT_HAVE_VICTIM); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell || !sSpellStore.LookupEntry(spell)) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str,"triggered",l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - caster->SetFacingToObject(m_session->GetPlayer()); - - caster->CastSpell(caster->getVictim(),spell,triggered); - - return true; -} - -/* -ComeToMe command REQUIRED for 3rd party scripting library to have access to PointMovementGenerator -Without this function 3rd party scripting library will get linking errors (unresolved external) -when attempting to use the PointMovementGenerator -*/ -bool ChatHandler::HandleComeToMeCommand(const char *args) -{ - char* newFlagStr = strtok((char*)args, " "); - - if (!newFlagStr) - return false; - - uint32 newFlags = (uint32)strtoul(newFlagStr, NULL, 0); - - Creature* caster = getSelectedCreature(); - if (!caster) - { - m_session->GetPlayer()->SetUnitMovementFlags(newFlags); - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); - return false; - } - - caster->SetUnitMovementFlags(newFlags); - - Player* pl = m_session->GetPlayer(); - - caster->GetMotionMaster()->MovePoint(0, pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ()); - return true; -} - -bool ChatHandler::HandleCastSelfCommand(const char *args) -{ - if (!*args) - return false; - - Unit* target = getSelectedUnit(); - - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell) - return false; - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if (!spellInfo) - return false; - - if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); - SetSentErrorMessage(true); - return false; - } - - target->CastSpell(target,spell,false); - - return true; -} - -std::string GetTimeString(uint32 time) -{ - uint16 days = time / DAY, hours = (time % DAY) / HOUR, minute = (time % HOUR) / MINUTE; - std::ostringstream ss; - if (days) ss << days << "d "; - if (hours) ss << hours << "h "; - ss << minute << "m"; - return ss.str(); -} - -bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/) -{ - Player* player = getSelectedPlayer(); - if (!player) player = m_session->GetPlayer(); - uint32 counter = 0; - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); - for (Player::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) - { - InstanceSave *save = itr->second.save; - std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); - counter++; - } - } - PSendSysMessage("player binds: %d", counter); - counter = 0; - Group *group = player->GetGroup(); - if (group) - { - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - Group::BoundInstancesMap &binds = group->GetBoundInstances(Difficulty(i)); - for (Group::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) - { - InstanceSave *save = itr->second.save; - std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); counter++; - } - } - } - PSendSysMessage("group binds: %d", counter); - - return true; -} - -bool ChatHandler::HandleInstanceUnbindCommand(const char *args) -{ - if (!*args) - return false; - - std::string cmd = args; - if (cmd == "all") - { - Player* player = getSelectedPlayer(); - if (!player) player = m_session->GetPlayer(); - uint32 counter = 0; - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); - for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) - { - if (itr->first != player->GetMapId()) - { - InstanceSave *save = itr->second.save; - std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); - player->UnbindInstance(itr, Difficulty(i)); - counter++; - } - else - ++itr; - } - } - PSendSysMessage("instances unbound: %d", counter); - } - return true; -} - -bool ChatHandler::HandleInstanceStatsCommand(const char* /*args*/) -{ - PSendSysMessage("instances loaded: %d", MapManager::Instance().GetNumInstances()); - PSendSysMessage("players in instances: %d", MapManager::Instance().GetNumPlayersInInstances()); - PSendSysMessage("instance saves: %d", sInstanceSaveManager.GetNumInstanceSaves()); - PSendSysMessage("players bound: %d", sInstanceSaveManager.GetNumBoundPlayersTotal()); - PSendSysMessage("groups bound: %d", sInstanceSaveManager.GetNumBoundGroupsTotal()); - return true; -} - -bool ChatHandler::HandleInstanceSaveDataCommand(const char * /*args*/) -{ - Player* pl = m_session->GetPlayer(); - - Map* map = pl->GetMap(); - if (!map->IsDungeon()) - { - PSendSysMessage("Map is not a dungeon."); - SetSentErrorMessage(true); - return false; - } - - if (!((InstanceMap*)map)->GetInstanceData()) - { - PSendSysMessage("Map has no instance data."); - SetSentErrorMessage(true); - return false; - } - - ((InstanceMap*)map)->GetInstanceData()->SaveToDB(); - return true; -} - -bool ChatHandler::HandleInstanceOpenCommand(const char *args) -{ - return HandleInstanceOpenCloseCommand(args,true); -} - -bool ChatHandler::HandleInstanceCloseCommand(const char *args) -{ - return HandleInstanceOpenCloseCommand(args,false); -} - -bool ChatHandler::HandleInstanceOpenCloseCommand(const char *args,bool open) -{ - char *mapIdStr; - char *instanceModeStr; - extractOptFirstArg((char*)args,&mapIdStr,&instanceModeStr); - if (!mapIdStr || !instanceModeStr) - return false; - - uint32 mapid = atoi(mapIdStr); - - InstanceTemplate const* instance = objmgr.GetInstanceTemplate(mapid); - if (!instance) - { - PSendSysMessage("Invalid map id"); - SetSentErrorMessage(true); - return false; - } - - uint8 status = objmgr.GetAccessRequirement(instance->access_id)->status; - uint8 flag = 0; - - if (strcmp(instanceModeStr,"normal") || strcmp(instanceModeStr,"10normal")) - flag = DUNGEON_STATUSFLAG_NORMAL; - else if (strcmp(instanceModeStr,"heroic") || strcmp(instanceModeStr,"25normal")) - flag = DUNGEON_STATUSFLAG_HEROIC; - else if (strcmp(instanceModeStr,"10heroic")) - flag = RAID_STATUSFLAG_10MAN_HEROIC; - else if (strcmp(instanceModeStr,"25heroic")) - flag = RAID_STATUSFLAG_25MAN_HEROIC; - else - { - PSendSysMessage("Unrecognized difficulty string"); - SetSentErrorMessage(true); - return false; - } - if (open) - status |= flag; - else - status &= ~flag; - - WorldDatabase.PExecute("UPDATE access_requirement SET status = '%u' WHERE id = '%u'", status, instance->access_id); - PSendSysMessage("Instance status changed. Don't forget to reload access_requirement table"); - return true; -} - -/// Display the list of GMs -bool ChatHandler::HandleGMListFullCommand(const char* /*args*/) -{ - ///- Get the accounts with GM Level >0 - QueryResult_AutoPtr result = LoginDatabase.Query("SELECT a.username,aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel > 0"); - if (result) - { - SendSysMessage(LANG_GMLIST); - SendSysMessage(" ======================== "); - SendSysMessage(LANG_GMLIST_HEADER); - SendSysMessage(" ======================== "); - - ///- Circle through them. Display username and GM level - do - { - Field *fields = result->Fetch(); - PSendSysMessage("|%15s|%6s|", fields[0].GetString(),fields[1].GetString()); - }while (result->NextRow()); - - PSendSysMessage(" ======================== "); - } - else - PSendSysMessage(LANG_GMLIST_EMPTY); - return true; -} - -/// Define the 'Message of the day' for the realm -bool ChatHandler::HandleServerSetMotdCommand(const char *args) -{ - sWorld.SetMotd(args); - PSendSysMessage(LANG_MOTD_NEW, args); - return true; -} - -/// Set whether we accept new clients -bool ChatHandler::HandleServerSetClosedCommand(const char *args) -{ - std::string arg = args; - - if (strncmp(args, "on", 3) == 0) - { - SendSysMessage(LANG_WORLD_CLOSED); - sWorld.SetClosed(true); - return true; - } - else if (strncmp(args, "off", 4) == 0) - { - SendSysMessage(LANG_WORLD_OPENED); - sWorld.SetClosed(false); - return true; - } - - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; -} - -/// Set/Unset the expansion level for an account -bool ChatHandler::HandleAccountSetAddonCommand(const char *args) -{ - ///- Get the command line arguments - char *szAcc = strtok((char*)args," "); - char *szExp = strtok(NULL," "); - - if (!szAcc) - return false; - - std::string account_name; - uint32 account_id; - - if (!szExp) - { - Player* player = getSelectedPlayer(); - if (!player) - return false; - - account_id = player->GetSession()->GetAccountId(); - accmgr.GetName(account_id,account_name); - szExp = szAcc; - } - else - { - ///- Convert Account name to Upper Format - account_name = szAcc; - if (!AccountMgr::normalizeString(account_name)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - account_id = accmgr.GetId(account_name); - if (!account_id) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - } - - // Let set addon state only for lesser (strong) security level - // or to self account - if (m_session && m_session->GetAccountId () != account_id && - HasLowerSecurityAccount (NULL,account_id,true)) - return false; - - int expansion = atoi(szExp); //get int anyway (0 if error) - if (expansion < 0 || expansion > sWorld.getConfig(CONFIG_EXPANSION)) - return false; - - // No SQL injection - LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",expansion,account_id); - PSendSysMessage(LANG_ACCOUNT_SETADDON,account_name.c_str(),account_id,expansion); - return true; -} - -//Send items by mail -bool ChatHandler::HandleSendItemsCommand(const char *args) -{ - // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] - Player* receiver; - uint64 receiver_guid; - std::string receiver_name; - if (!extractPlayerTarget((char*)args,&receiver,&receiver_guid,&receiver_name)) - return false; - - char* tail1 = strtok(NULL, ""); - if (!tail1) - return false; - - char* msgSubject = extractQuotedArg(tail1); - if (!msgSubject) - return false; - - char* tail2 = strtok(NULL, ""); - if (!tail2) - return false; - - char* msgText = extractQuotedArg(tail2); - if (!msgText) - return false; - - // msgSubject, msgText isn't NUL after prev. check - std::string subject = msgSubject; - std::string text = msgText; - - // extract items - typedef std::pair ItemPair; - typedef std::list< ItemPair > ItemPairs; - ItemPairs items; - - // get all tail string - char* tail = strtok(NULL, ""); - - // get from tail next item str - while (char* itemStr = strtok(tail, " ")) - { - // and get new tail - tail = strtok(NULL, ""); - - // parse item str - char* itemIdStr = strtok(itemStr, ":"); - char* itemCountStr = strtok(NULL, " "); - - uint32 item_id = atoi(itemIdStr); - if (!item_id) - return false; - - ItemPrototype const* item_proto = objmgr.GetItemPrototype(item_id); - if (!item_proto) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - uint32 item_count = itemCountStr ? atoi(itemCountStr) : 1; - if (item_count < 1 || (item_proto->MaxCount > 0 && item_count > uint32(item_proto->MaxCount))) - { - PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, item_count,item_id); - SetSentErrorMessage(true); - return false; - } - - while (item_count > item_proto->GetMaxStackSize()) - { - items.push_back(ItemPair(item_id,item_proto->GetMaxStackSize())); - item_count -= item_proto->GetMaxStackSize(); - } - - items.push_back(ItemPair(item_id,item_count)); - - if (items.size() > MAX_MAIL_ITEMS) - { - PSendSysMessage(LANG_COMMAND_MAIL_ITEMS_LIMIT, MAX_MAIL_ITEMS); - SetSentErrorMessage(true); - return false; - } - } - - // from console show not existed sender - MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - - // fill mail - MailDraft draft(subject, text); - - for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr) - { - if (Item* item = Item::CreateItem(itr->first,itr->second,m_session ? m_session->GetPlayer() : 0)) - { - item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted - draft.AddItem(item); - } - } - - draft.SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)), sender); - - std::string nameLink = playerLink(receiver_name); - PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; -} - -///Send money by mail -bool ChatHandler::HandleSendMoneyCommand(const char *args) -{ - /// format: name "subject text" "mail text" money - - Player* receiver; - uint64 receiver_guid; - std::string receiver_name; - if (!extractPlayerTarget((char*)args,&receiver,&receiver_guid,&receiver_name)) - return false; - - char* tail1 = strtok(NULL, ""); - if (!tail1) - return false; - - char* msgSubject = extractQuotedArg(tail1); - if (!msgSubject) - return false; - - char* tail2 = strtok(NULL, ""); - if (!tail2) - return false; - - char* msgText = extractQuotedArg(tail2); - if (!msgText) - return false; - - char* money_str = strtok(NULL, ""); - int32 money = money_str ? atoi(money_str) : 0; - if (money <= 0) - return false; - - // msgSubject, msgText isn't NUL after prev. check - std::string subject = msgSubject; - std::string text = msgText; - - // from console show not existed sender - MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - - MailDraft(subject, text) - .AddMoney(money) - .SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)),sender); - - std::string nameLink = playerLink(receiver_name); - PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; -} - -/// Send a message to a player in game -bool ChatHandler::HandleSendMessageCommand(const char *args) -{ - ///- Find the player - Player *rPlayer; - if (!extractPlayerTarget((char*)args, &rPlayer)) - return false; - - char* msg_str = strtok(NULL, ""); - if (!msg_str) - return false; - - ///- Check that he is not logging out. - if (rPlayer->GetSession()->isLogingOut()) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - ///- Send the message - //Use SendAreaTriggerMessage for fastest delivery. - rPlayer->GetSession()->SendAreaTriggerMessage("%s", msg_str); - rPlayer->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); - - //Confirmation message - std::string nameLink = GetNameLink(rPlayer); - PSendSysMessage(LANG_SENDMESSAGE,nameLink.c_str(),msg_str); - return true; -} - -bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/) -{ - sBattleGroundMgr.DistributeArenaPoints(); - return true; -} - -bool ChatHandler::HandleModifyGenderCommand(const char *args) -{ - if (!*args) - return false; - - Player *player = getSelectedPlayer(); - - if (!player) - { - PSendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - PlayerInfo const* info = objmgr.GetPlayerInfo(player->getRace(), player->getClass()); - if (!info) - return false; - - char const* gender_str = (char*)args; - int gender_len = strlen(gender_str); - - Gender gender; - - if (!strncmp(gender_str, "male", gender_len)) // MALE - { - if (player->getGender() == GENDER_MALE) - return true; - - gender = GENDER_MALE; - } - else if (!strncmp(gender_str, "female", gender_len)) // FEMALE - { - if (player->getGender() == GENDER_FEMALE) - return true; - - gender = GENDER_FEMALE; - } - else - { - SendSysMessage(LANG_MUST_MALE_OR_FEMALE); - SetSentErrorMessage(true); - return false; - } - - // Set gender - player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); - player->SetByteValue(PLAYER_BYTES_3, 0, gender); - - // Change display ID - player->InitDisplayIds(); - - char const* gender_full = gender ? "female" : "male"; - - PSendSysMessage(LANG_YOU_CHANGE_GENDER, GetNameLink(player).c_str(), gender_full); - - if (needReportToTarget(player)) - ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetNameLink().c_str()); - - return true; -} - -bool ChatHandler::HandleChannelSetPublic(const char *args) -{ - if (!*args) - return false; - std::string channel = strtok((char*)args, " "); - uint32 val = atoi((char*)args); - - if (val) - { - CharacterDatabase.PExecute("UPDATE channels SET m_public = 1 WHERE m_name LIKE '%s'", channel.c_str()); - val = 1; - } - else - { - CharacterDatabase.PExecute("UPDATE channels SET m_public = 0 WHERE m_name LIKE '%s'", channel.c_str()); - val = 0; - } - - PSendSysMessage(LANG_CHANNEL_PUBLIC_CHANGED, channel.c_str(), val); - - return true; -} - - -/*------------------------------------------ - *-------------TRINITY---------------------- - *-------------------------------------*/ - -bool ChatHandler::HandlePlayAllCommand(const char *args) -{ - if (!*args) - return false; - - uint32 soundId = atoi((char*)args); - - if (!sSoundEntriesStore.LookupEntry(soundId)) - { - PSendSysMessage(LANG_SOUND_NOT_EXIST, soundId); - SetSentErrorMessage(true); - return false; - } - - WorldPacket data(SMSG_PLAY_SOUND, 4); - data << uint32(soundId) << m_session->GetPlayer()->GetGUID(); - sWorld.SendGlobalMessage(&data); - - PSendSysMessage(LANG_COMMAND_PLAYED_TO_ALL, soundId); - return true; -} - -bool ChatHandler::HandleFreezeCommand(const char *args) -{ - std::string name; - Player *player; - char *TargetName = strtok((char*)args, " "); //get entered name - if (!TargetName) //if no name entered use target - { - player = getSelectedPlayer(); - if (player) //prevent crash with creature as target - { - name = player->GetName(); - normalizePlayerName(name); - } - } - else // if name entered - { - name = TargetName; - normalizePlayerName(name); - player = objmgr.GetPlayer(name.c_str()); //get player by name - } - - if (!player) - { - SendSysMessage(LANG_COMMAND_FREEZE_WRONG); - return true; - } - - if (player == m_session->GetPlayer()) - { - SendSysMessage(LANG_COMMAND_FREEZE_ERROR); - return true; - } - - //effect - if (player && player != m_session->GetPlayer()) - { - PSendSysMessage(LANG_COMMAND_FREEZE,name.c_str()); - - //stop combat + make player unattackable + duel stop + stop some spells - player->setFaction(35); - player->CombatStop(); - if (player->IsNonMeleeSpellCasted(true)) - player->InterruptNonMeleeSpells(true); - player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - player->SetUInt32Value(PLAYER_DUEL_TEAM, 1); - - //if player class = hunter || warlock remove pet if alive - if ((player->getClass() == CLASS_HUNTER) || (player->getClass() == CLASS_WARLOCK)) - { - if (Pet *pet = player->GetPet()) - { - pet->SavePetToDB(PET_SAVE_AS_CURRENT); - // not let dismiss dead pet - if (pet && pet->isAlive()) - player->RemovePet(pet,PET_SAVE_NOT_IN_SLOT); - } - } - - //m_session->GetPlayer()->CastSpell(player,spellID,false); - if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(9454)) - Aura::TryCreate(spellInfo, player, player); - - //save player - player->SaveToDB(); - } - return true; -} - -bool ChatHandler::HandleUnFreezeCommand(const char *args) -{ - std::string name; - Player *player; - char *TargetName = strtok((char*)args, " "); //get entered name - if (!TargetName) //if no name entered use target - { - player = getSelectedPlayer(); - if (player) //prevent crash with creature as target - name = player->GetName(); - } - - else // if name entered - { - name = TargetName; - normalizePlayerName(name); - player = objmgr.GetPlayer(name.c_str()); //get player by name - } - - //effect - if (player) - { - PSendSysMessage(LANG_COMMAND_UNFREEZE,name.c_str()); - - //Reset player faction + allow combat + allow duels - player->setFactionForRace(player->getRace()); - player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - //allow movement and spells - player->RemoveAurasDueToSpell(9454); - - //save player - player->SaveToDB(); - } - - if (!player) - { - if (TargetName) - { - //check for offline players - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT characters.guid FROM characters WHERE characters.name = '%s'",name.c_str()); - if (!result) - { - SendSysMessage(LANG_COMMAND_FREEZE_WRONG); - return true; - } - //if player found: delete his freeze aura - Field *fields=result->Fetch(); - uint64 pguid = fields[0].GetUInt64(); - - CharacterDatabase.PQuery("DELETE FROM character_aura WHERE character_aura.spell = 9454 AND character_aura.guid = '%u'",pguid); - PSendSysMessage(LANG_COMMAND_UNFREEZE,name.c_str()); - return true; - } - else - { - SendSysMessage(LANG_COMMAND_FREEZE_WRONG); - return true; - } - } - - return true; -} - -bool ChatHandler::HandleListFreezeCommand(const char * /*args*/) -{ - //Get names from DB - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT characters.name FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454"); - if (!result) - { - SendSysMessage(LANG_COMMAND_NO_FROZEN_PLAYERS); - return true; - } - //Header of the names - PSendSysMessage(LANG_COMMAND_LIST_FREEZE); - - //Output of the results - do - { - Field *fields = result->Fetch(); - std::string fplayers = fields[0].GetCppString(); - PSendSysMessage(LANG_COMMAND_FROZEN_PLAYERS,fplayers.c_str()); - } while (result->NextRow()); - - return true; -} - -bool ChatHandler::HandleGroupLeaderCommand(const char *args) -{ - Player* plr = NULL; - Group* group = NULL; - uint64 guid = 0; - char* cname = strtok((char*)args, " "); - - if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid)) - if (group && group->GetLeaderGUID() != guid) - group->ChangeLeader(guid); - - return true; -} - -bool ChatHandler::HandleGroupDisbandCommand(const char *args) -{ - Player* plr = NULL; - Group* group = NULL; - uint64 guid = 0; - char* cname = strtok((char*)args, " "); - - if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid)) - if (group) - group->Disband(); - - return true; -} - -bool ChatHandler::HandleGroupRemoveCommand(const char *args) -{ - Player* plr = NULL; - Group* group = NULL; - uint64 guid = 0; - char* cname = strtok((char*)args, " "); - - if (GetPlayerGroupAndGUIDByName(cname, plr, group, guid, true)) - if (group) - group->RemoveMember(guid, 0); - - return true; -} - -bool ChatHandler::HandlePossessCommand(const char * /*args*/) -{ - Unit *pUnit = getSelectedUnit(); - if (!pUnit) - return false; - - m_session->GetPlayer()->CastSpell(pUnit, 530, true); - return true; -} - -bool ChatHandler::HandleUnPossessCommand(const char * /*args*/) -{ - Unit *pUnit = getSelectedUnit(); - if (!pUnit) - pUnit = m_session->GetPlayer(); - - pUnit->RemoveCharmAuras(); - - return true; -} - -bool ChatHandler::HandleBindSightCommand(const char * /*args*/) -{ - Unit *pUnit = getSelectedUnit(); - if (!pUnit) - return false; - - m_session->GetPlayer()->CastSpell(pUnit, 6277, true); - return true; -} - -bool ChatHandler::HandleUnbindSightCommand(const char * /*args*/) -{ - if (m_session->GetPlayer()->isPossessing()) - return false; - - m_session->GetPlayer()->StopCastingBindSight(); - return true; -} diff --git a/src/server/game/Combat/CombatHandler.cpp b/src/server/game/Combat/CombatHandler.cpp deleted file mode 100644 index 404b70c1c84..00000000000 --- a/src/server/game/Combat/CombatHandler.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Log.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "ObjectAccessor.h" -#include "CreatureAI.h" -#include "ObjectDefines.h" - -void WorldSession::HandleAttackSwingOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - DEBUG_LOG("WORLD: Recvd CMSG_ATTACKSWING Message guidlow:%u guidhigh:%u", GUID_LOPART(guid), GUID_HIPART(guid)); - - Unit *pEnemy = ObjectAccessor::GetUnit(*_player, guid); - - if (!pEnemy) - { - if (!IS_UNIT_GUID(guid)) - sLog.outError("WORLD: Object %u (TypeID: %u) isn't player, pet or creature",GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); - else - sLog.outError("WORLD: Enemy %s %u not found",GetLogNameForGuid(guid),GUID_LOPART(guid)); - - // stop attack state at client - SendAttackStop(NULL); - return; - } - - if (!_player->canAttack(pEnemy)) - { - sLog.outError("WORLD: Enemy %s %u is friendly",(IS_PLAYER_GUID(guid) ? "player" : "creature"),GUID_LOPART(guid)); - - // stop attack state at client - SendAttackStop(pEnemy); - return; - } - - _player->Attack(pEnemy,true); -} - -void WorldSession::HandleAttackStopOpcode(WorldPacket & /*recv_data*/) -{ - GetPlayer()->AttackStop(); -} - -void WorldSession::HandleSetSheathedOpcode(WorldPacket & recv_data) -{ - uint32 sheathed; - recv_data >> sheathed; - - //sLog.outDebug("WORLD: Recvd CMSG_SETSHEATHED Message guidlow:%u value1:%u", GetPlayer()->GetGUIDLow(), sheathed); - - if (sheathed >= MAX_SHEATH_STATE) - { - sLog.outError("Unknown sheath state %u ??",sheathed); - return; - } - - GetPlayer()->SetSheath(SheathState(sheathed)); -} - -void WorldSession::SendAttackStop(Unit const* enemy) -{ - WorldPacket data(SMSG_ATTACKSTOP, (4+20)); // we guess size - data.append(GetPlayer()->GetPackGUID()); - data.append(enemy ? enemy->GetPackGUID() : 0); // must be packed guid - data << uint32(0); // unk, can be 1 also - SendPacket(&data); -} - diff --git a/src/server/game/Combat/UnitEvents.h b/src/server/game/Combat/UnitEvents.h new file mode 100644 index 00000000000..a218e0dd34d --- /dev/null +++ b/src/server/game/Combat/UnitEvents.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _UNITEVENTS +#define _UNITEVENTS + +#include "Common.h" + +class ThreatContainer; +class ThreatManager; +class HostileReference; + +//============================================================== +//============================================================== + +enum UNIT_EVENT_TYPE +{ + // Player/Pet changed on/offline status + UEV_THREAT_REF_ONLINE_STATUS = 1<<0, + + // Threat for Player/Pet changed + UEV_THREAT_REF_THREAT_CHANGE = 1<<1, + + // Player/Pet will be removed from list (dead) [for internal use] + UEV_THREAT_REF_REMOVE_FROM_LIST = 1<<2, + + // Player/Pet entered/left water or some other place where it is/was not accessible for the creature + UEV_THREAT_REF_ASSECCIBLE_STATUS = 1<<3, + + // Threat list is going to be sorted (if dirty flag is set) + UEV_THREAT_SORT_LIST = 1<<4, + + // New target should be fetched, could tbe the current target as well + UEV_THREAT_SET_NEXT_TARGET = 1<<5, + + // A new victim (target) was set. Could be NULL + UEV_THREAT_VICTIM_CHANGED = 1<<6, + + // Future use + //UEV_UNIT_KILLED = 1<<7, + + //Future use + //UEV_UNIT_HEALTH_CHANGE = 1<<8, +}; + +#define UEV_THREAT_REF_EVENT_MASK (UEV_THREAT_REF_ONLINE_STATUS | UEV_THREAT_REF_THREAT_CHANGE | UEV_THREAT_REF_REMOVE_FROM_LIST | UEV_THREAT_REF_ASSECCIBLE_STATUS) +#define UEV_THREAT_MANAGER_EVENT_MASK (UEV_THREAT_SORT_LIST | UEV_THREAT_SET_NEXT_TARGET | UEV_THREAT_VICTIM_CHANGED) +#define UEV_ALL_EVENT_MASK (0xffffffff) + +// Future use +//#define UEV_UNIT_EVENT_MASK (UEV_UNIT_KILLED | UEV_UNIT_HEALTH_CHANGE) + +//============================================================== + +class UnitBaseEvent +{ + private: + uint32 iType; + public: + UnitBaseEvent(uint32 pType) { iType = pType; } + uint32 getType() const { return iType; } + bool matchesTypeMask(uint32 pMask) const { return iType & pMask; } + + void setType(uint32 pType) { iType = pType; } + +}; + +//============================================================== + +class ThreatRefStatusChangeEvent : public UnitBaseEvent +{ + private: + HostileReference* iHostileReference; + union + { + float iFValue; + int32 iIValue; + bool iBValue; + }; + ThreatManager* iThreatManager; + public: + ThreatRefStatusChangeEvent(uint32 pType) : UnitBaseEvent(pType) { iHostileReference = NULL; } + + ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; } + + ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, float pValue) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; iFValue = pValue; } + + ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, bool pValue) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; iBValue = pValue; } + + int32 getIValue() const { return iIValue; } + + float getFValue() const { return iFValue; } + + bool getBValue() const { return iBValue; } + + void setBValue(bool pValue) { iBValue = pValue; } + + HostileReference* getReference() const { return iHostileReference; } + + void setThreatManager(ThreatManager* pThreatManager) { iThreatManager = pThreatManager; } + + ThreatManager* getThreatManager() const { return iThreatManager; } +}; + +//============================================================== + +class ThreatManagerEvent : public ThreatRefStatusChangeEvent +{ + private: + ThreatContainer* iThreatContainer; + public: + ThreatManagerEvent(uint32 pType) : ThreatRefStatusChangeEvent(pType) {} + ThreatManagerEvent(uint32 pType, HostileReference* pHostileReference) : ThreatRefStatusChangeEvent(pType, pHostileReference) {} + + void setThreatContainer(ThreatContainer* pThreatContainer) { iThreatContainer = pThreatContainer; } + + ThreatContainer* getThreatContainer() const { return iThreatContainer; } +}; + +//============================================================== +#endif + diff --git a/src/server/game/ConditionMgr/ConditionMgr.cpp b/src/server/game/ConditionMgr/ConditionMgr.cpp deleted file mode 100644 index 8e5a7e5677e..00000000000 --- a/src/server/game/ConditionMgr/ConditionMgr.cpp +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "Policies/SingletonImp.h" -#include "Player.h" -#include "SpellAuras.h" -#include "SpellMgr.h" -#include "GameEventMgr.h" -#include "ObjectMgr.h" -#include "ProgressBar.h" -#include "InstanceData.h" -#include "ConditionMgr.h" - -INSTANTIATE_SINGLETON_1(ConditionMgr); - -// Checks if player meets the condition -// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI) -bool Condition::Meets(Player * player, Unit* targetOverride) -{ - if (!player) - { - sLog.outDebug("Condition player not found"); - return false; // player not present, return false - } - uint32 refId = 0; - bool condMeets = false; - bool sendErrorMsg = false; - refId = mConditionValue3;//value 3 can be a 'quick' reference - switch (mConditionType) - { - case CONDITION_NONE: - condMeets = true; // empty condition, always met - break; - case CONDITION_AURA: - condMeets = player->HasAuraEffect(mConditionValue1, mConditionValue2); - break; - case CONDITION_ITEM: - condMeets = player->HasItemCount(mConditionValue1, mConditionValue2); - break; - case CONDITION_ITEM_EQUIPPED: - condMeets = player->HasItemOrGemWithIdEquipped(mConditionValue1,1); - break; - case CONDITION_ZONEID: - condMeets = player->GetZoneId() == mConditionValue1; - break; - case CONDITION_REPUTATION_RANK: - { - FactionEntry const* faction = sFactionStore.LookupEntry(mConditionValue1); - condMeets = faction && uint32(player->GetReputationMgr().GetRank(faction)) >= int32(mConditionValue2); - break; - } - case CONDITION_ACHIEVEMENT: - { - AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(mConditionValue1); - condMeets = player->GetAchievementMgr().HasAchieved(achievement); - break; - } - case CONDITION_TEAM: - condMeets = player->GetTeam() == mConditionValue1; - break; - case CONDITION_CLASS: - condMeets = player->getClass() == mConditionValue1; - break; - case CONDITION_RACE: - condMeets = player->getRace() == mConditionValue1; - break; - case CONDITION_SKILL: - condMeets = player->HasSkill(mConditionValue1) && player->GetBaseSkillValue(mConditionValue1) >= mConditionValue2; - break; - case CONDITION_QUESTREWARDED: - condMeets = player->GetQuestRewardStatus(mConditionValue1); - break; - case CONDITION_QUESTTAKEN: - { - QuestStatus status = player->GetQuestStatus(mConditionValue1); - condMeets = (status == QUEST_STATUS_INCOMPLETE); - break; - } - case CONDITION_QUEST_NONE: - { - QuestStatus status = player->GetQuestStatus(mConditionValue1); - condMeets = (status == QUEST_STATUS_NONE); - break; - } - case CONDITION_AD_COMMISSION_AURA: - { - Unit::AuraApplicationMap const& auras = player->GetAppliedAuras(); - for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - if ((itr->second->GetBase()->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetBase()->GetSpellProto()->SpellVisual[0] == 3580) - { - condMeets = true; - break; - } - condMeets = false; - break; - } - case CONDITION_NO_AURA: - condMeets = !player->HasAuraEffect(mConditionValue1, mConditionValue2); - break; - case CONDITION_ACTIVE_EVENT: - condMeets = gameeventmgr.IsActiveEvent(mConditionValue1); - break; - case CONDITION_INSTANCE_DATA: - { - Map *map = player->GetMap(); - if (map && map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData()) - condMeets = ((InstanceMap*)map)->GetInstanceData()->GetData(mConditionValue1) == mConditionValue2; - break; - } - case CONDITION_SPELL_SCRIPT_TARGET: - condMeets = true;//spell target condition is handled in spellsystem, here it is always true - refId = 0;//cant have references! use CONDITION_SOURCE_TYPE_SPELL for it - break; - case CONDITION_CREATURE_TARGET: - { - Unit* target = player->GetSelectedUnit(); - if (targetOverride) - target = targetOverride; - if (target) - if (Creature* cTarget = target->ToCreature()) - if (cTarget->GetEntry() == mConditionValue1) - condMeets = true; - break; - } - case CONDITION_TARGET_HEALTH_BELOW_PCT: - { - Unit* target = player->GetSelectedUnit(); - if (targetOverride) - target = targetOverride; - if (target) - if ((target->GetHealth()*100 / target->GetMaxHealth()) <= mConditionValue1) - condMeets = true; - break; - } - case CONDITION_TARGET_RANGE: - { - if (Unit* target = player->GetSelectedUnit()) - if (player->GetDistance(target) >= mConditionValue1 && (!mConditionValue2 || player->GetDistance(target) <= mConditionValue2)) - condMeets = true; - break; - } - case CONDITION_MAPID: - condMeets = player->GetMapId() == mConditionValue1; - break; - case CONDITION_AREAID: - condMeets = player->GetAreaId() == mConditionValue1; - break; - case CONDITION_ITEM_TARGET: - { - condMeets = true;//handled in Item::IsTargetValidForItemUse - refId = 0;//cant have references for now - break; - } - default: - condMeets = false; - refId = 0; - break; - } - switch (mSourceType) - { - case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET: - case CONDITION_SOURCE_TYPE_SPELL: - sendErrorMsg = true; - break; - } - - bool refMeets = false; - if (condMeets && refId)//only have to check references if 'this' is met - { - ConditionList ref = sConditionMgr.GetConditionReferences(refId); - refMeets = sConditionMgr.IsPlayerMeetToConditions(player, ref); - }else refMeets = true; - - if (sendErrorMsg && ErrorTextd && (!condMeets || !refMeets))//send special error from DB - player->m_ConditionErrorMsgId = ErrorTextd; - - return condMeets && refMeets; -} - -ConditionMgr::ConditionMgr() -{ -} - -ConditionMgr::~ConditionMgr() -{ -} - -ConditionList ConditionMgr::GetConditionReferences(uint32 refId) -{ - ConditionList conditions; - ConditionReferenceMap::const_iterator ref = m_ConditionReferenceMap.find(refId); - if (ref != m_ConditionReferenceMap.end()) - conditions = (*ref).second; - return conditions; -} - -bool ConditionMgr::IsPlayerMeetToConditionList(Player* player,const ConditionList& conditions, Unit* targetOverride) -{ - std::mapElseGroupMap; - for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i) - { - sLog.outDebug("ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u",(*i)->mConditionType,(*i)->mConditionValue1); - if ((*i)->isLoaded()) - { - std::map::const_iterator itr = ElseGroupMap.find((*i)->mElseGroup); - if (itr == ElseGroupMap.end()) - ElseGroupMap[(*i)->mElseGroup] = true; - else if (!(*itr).second) - continue; - - if ((*i)->mReferenceId)//handle reference - { - ConditionReferenceMap::const_iterator ref = m_ConditionReferenceMap.find((*i)->mReferenceId); - if (ref != m_ConditionReferenceMap.end()) - { - if(!IsPlayerMeetToConditionList(player, (*ref).second, targetOverride)) - ElseGroupMap[(*i)->mElseGroup] = false; - }else{ - sLog.outDebug("IsPlayerMeetToConditionList: Reference template -%u not found", (*i)->mReferenceId);//checked at loading, should never happen - } - - } else//handle normal condition - { - if (!(*i)->Meets(player, targetOverride)) - ElseGroupMap[(*i)->mElseGroup] = false; - } - } - } - for (std::map::const_iterator i = ElseGroupMap.begin(); i != ElseGroupMap.end(); ++i) - if (i->second) - return true; - return false; -} - -bool ConditionMgr::IsPlayerMeetToConditions(Player* player, ConditionList conditions, Unit* targetOverride) -{ - if (conditions.empty()) - return true; - if(player) - player->m_ConditionErrorMsgId = 0; - - sLog.outDebug("ConditionMgr::IsPlayerMeetToConditions"); - bool result = IsPlayerMeetToConditionList(player, conditions, targetOverride); - - if (player && player->m_ConditionErrorMsgId && player->GetSession()) - player->GetSession()->SendNotification(player->m_ConditionErrorMsgId);//m_ConditionErrorMsgId is set only if a condition was not met - - return result; -} - -ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType sType, uint32 uEntry) -{ - ConditionList spellCond; - if (sType > CONDITION_SOURCE_TYPE_NONE && sType < MAX_CONDITIONSOURCETYPE) - { - ConditionMap::const_iterator itr = m_ConditionMap.find(sType); - if (itr != m_ConditionMap.end()) - { - ConditionTypeMap::const_iterator i = (*itr).second.find(uEntry); - if (i != (*itr).second.end()) - { - spellCond = (*i).second; - sLog.outDebug("GetConditionsForNotGroupedEntry: found conditions for type %u and entry %u", uint32(sType), uEntry); - } - } - } - return spellCond; -} - -void ConditionMgr::LoadConditions(bool isReload) -{ - m_ConditionMap.clear(); // for reload case - m_ConditionReferenceMap.clear(); // for reload case - //must clear all custom handled cases (groupped types) before reload - if (isReload) - { - sLog.outString("Reseting Loot Conditions..."); - LootTemplates_Creature.ResetConditions(); - LootTemplates_Fishing.ResetConditions(); - LootTemplates_Gameobject.ResetConditions(); - LootTemplates_Item.ResetConditions(); - LootTemplates_Mail.ResetConditions(); - LootTemplates_Milling.ResetConditions(); - LootTemplates_Pickpocketing.ResetConditions(); - LootTemplates_Reference.ResetConditions(); - LootTemplates_Skinning.ResetConditions(); - LootTemplates_Disenchant.ResetConditions(); - LootTemplates_Prospecting.ResetConditions(); - LootTemplates_Spell.ResetConditions(); - - sLog.outString("Re-Loading `gossip_menu` Table for Conditions!"); - objmgr.LoadGossipMenu(); - - sLog.outString("Re-Loading `gossip_menu_option` Table for Conditions!"); - objmgr.LoadGossipMenuItems(); - } - - uint32 count = 0; - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, ElseGroup, ConditionTypeOrReference, ConditionValue1, ConditionValue2, ConditionValue3, ErrorTextId FROM conditions"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded `conditions`, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Field *fields = result->Fetch(); - - Condition* cond = new Condition(); - int32 iSourceTypeOrReferenceId = fields[0].GetInt32(); - cond->mSourceGroup = fields[1].GetUInt32(); - cond->mSourceEntry = fields[2].GetUInt32(); - cond->mElseGroup = fields[3].GetUInt32(); - int32 iConditionTypeOrReference = fields[4].GetInt32(); - cond->mConditionValue1 = fields[5].GetUInt32(); - cond->mConditionValue2 = fields[6].GetUInt32(); - cond->mConditionValue3 = fields[7].GetUInt32(); - cond->ErrorTextd = fields[8].GetUInt32(); - - if (iConditionTypeOrReference >= 0) - cond->mConditionType = ConditionType(iConditionTypeOrReference); - - if (iConditionTypeOrReference < 0)//it has a reference - { - if (iConditionTypeOrReference == iSourceTypeOrReferenceId)//self referencing, skipp - { - sLog.outErrorDb("Condition reference %i is referencing self, skipped", iSourceTypeOrReferenceId); - continue; - } - cond->mReferenceId = uint32(abs(iConditionTypeOrReference)); - - const char* rowType = "reference template"; - if (iSourceTypeOrReferenceId >= 0) - rowType = "reference"; - //check for useless data - if (cond->mConditionValue1) - sLog.outErrorDb("Condition %s %i has useless data in value1 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue1); - if (cond->mConditionValue2) - sLog.outErrorDb("Condition %s %i has useless data in value2 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue2); - if (cond->mConditionValue3) - sLog.outErrorDb("Condition %s %i has useless data in value3 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue3); - if (cond->mSourceGroup && iSourceTypeOrReferenceId < 0) - sLog.outErrorDb("Condition %s %i has useless data in SourceGroup (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceGroup); - if (cond->mSourceEntry && iSourceTypeOrReferenceId < 0) - sLog.outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceEntry); - }else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType - continue; - - - if (iSourceTypeOrReferenceId < 0)//it is a reference template - { - uint32 uRefId = abs(iSourceTypeOrReferenceId); - if (m_ConditionReferenceMap.find(uRefId) == m_ConditionReferenceMap.end())//make sure we have a list for our conditions, based on reference id - { - ConditionList mCondList; - m_ConditionReferenceMap[uRefId] = mCondList; - } - m_ConditionReferenceMap[uRefId].push_back(cond);//add to reference storage - count++; - continue; - }//end of reference templates - - cond->mSourceType = ConditionSourceType(iSourceTypeOrReferenceId); - - //if not a reference and SourceType is invalid, skip - if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond)) - continue; - - //Grouping is only allowed for some types (loot templates, gossip menus, gossip items) - if (cond->mSourceGroup && !isGroupable(cond->mSourceType)) - { - sLog.outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->mSourceType), cond->mSourceGroup); - continue; - }else if (cond->mSourceGroup) - { - bool bIsDone = false; - //handle grouped conditions - switch (cond->mSourceType) - { - case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Creature.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Disenchant.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Fishing.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Gameobject.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Item.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Mail.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Milling.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Pickpocketing.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Prospecting.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Reference.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Skinning.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE: - bIsDone = addToLootTemplate(cond, LootTemplates_Spell.GetLootForConditionFill(cond->mSourceGroup)); - break; - case CONDITION_SOURCE_TYPE_GOSSIP_MENU: - bIsDone = addToGossipMenus(cond); - break; - case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: - bIsDone = addToGossipMenuItems(cond); - break; - } - if (!bIsDone) - sLog.outErrorDb("Not handled grouped condition, SourceGroup %u", cond->mSourceGroup); - else - ++count; - continue; - } - - //handle not grouped conditions - //make sure we have a storage list for our SourceType - if (m_ConditionMap.find(cond->mSourceType) == m_ConditionMap.end()) - { - ConditionTypeMap mTypeMap; - m_ConditionMap[cond->mSourceType] = mTypeMap;//add new empty list for SourceType - } - - //make sure we have a condition list for our SourceType's entry - if (m_ConditionMap[cond->mSourceType].find(cond->mSourceEntry) == m_ConditionMap[cond->mSourceType].end()) - { - ConditionList mCondList; - m_ConditionMap[cond->mSourceType][cond->mSourceEntry] = mCondList; - } - - //add new Condition to storage based on Type/Entry - m_ConditionMap[cond->mSourceType][cond->mSourceEntry].push_back(cond); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u conditions", count); -} - -bool ConditionMgr::addToLootTemplate(Condition* cond, LootTemplate* loot) -{ - if (!loot) - { - sLog.outErrorDb("ConditionMgr: LootTemplate %u not found", cond->mSourceGroup); - return false; - } - if (loot->addConditionItem(cond)) - return true; - sLog.outErrorDb("ConditionMgr: Item %u not found in LootTemplate %u", cond->mSourceEntry, cond->mSourceGroup); - return false; -} - -bool ConditionMgr::addToGossipMenus(Condition* cond) -{ - GossipMenusMapBoundsNonConst pMenuBounds = objmgr.GetGossipMenusMapBoundsNonConst(cond->mSourceGroup); - - if (pMenuBounds.first != pMenuBounds.second) - { - for (GossipMenusMap::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr) - { - if ((*itr).second.entry == cond->mSourceGroup && (*itr).second.text_id == cond->mSourceEntry) - { - (*itr).second.conditions.push_back(cond); - sLog.outDebug("addToGossipMenus: entry %u textId %u", cond->mSourceGroup, cond->mSourceEntry); - return true; - } - } - } - sLog.outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->mSourceGroup); - return false; -} - -bool ConditionMgr::addToGossipMenuItems(Condition* cond) -{ - GossipMenuItemsMapBoundsNonConst pMenuItemBounds = objmgr.GetGossipMenuItemsMapBoundsNonConst(cond->mSourceGroup); - if (pMenuItemBounds.first != pMenuItemBounds.second) - { - for (GossipMenuItemsMap::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr) - { - if ((*itr).second.menu_id == cond->mSourceGroup && (*itr).second.id == cond->mSourceEntry) - { - (*itr).second.conditions.push_back(cond); - //sLog.outDebug("addToGossipMenuItems: menuId %u id %u", cond->mSourceGroup, cond->mSourceEntry); - return true; - } - } - } - sLog.outErrorDb("addToGossipMenuItems: GossipMenuIt %u Item %u not found", cond->mSourceGroup, cond->mSourceEntry); - return false; -} - -bool ConditionMgr::isSourceTypeValid(Condition* cond) -{ - if (cond->mSourceType == CONDITION_SOURCE_TYPE_NONE || cond->mSourceType >= MAX_CONDITIONSOURCETYPE) - { - sLog.outErrorDb("Invalid ConditionSourceType %u in `condition` table, ignoring.", uint32(cond->mSourceType)); - return false; - } - switch (cond->mSourceType) - { - case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE: - { - if (!LootTemplates_Creature.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Creature.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE: - { - if (!LootTemplates_Disenchant.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Disenchant.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE: - { - if (!LootTemplates_Fishing.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Fishing.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE: - { - if (!LootTemplates_Gameobject.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Gameobject.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE: - { - if (!LootTemplates_Item.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Item.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE: - { - if (!LootTemplates_Mail.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Mail.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE: - { - if (!LootTemplates_Milling.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Milling.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE: - { - if (!LootTemplates_Pickpocketing.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Pickpocketing.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE: - { - if (!LootTemplates_Prospecting.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Prospecting.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE: - { - if (!LootTemplates_Reference.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Reference.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE: - { - if (!LootTemplates_Skinning.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Skinning.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE: - { - if (!LootTemplates_Spell.HaveLootFor(cond->mSourceGroup)) - { - sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->mSourceGroup); - return false; - } - LootTemplate* loot = LootTemplates_Spell.GetLootForConditionFill(cond->mSourceGroup); - ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); - if (!pItemProto && !loot->isReference(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET: - { - if (cond->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) - { - sLog.outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_SPELL_SCRIPT_TARGET(18) is valid for CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET(14), ignoring.", cond->mSourceEntry, uint32(cond->mConditionType)); - return false; - } - SpellEntry const* spellProto = sSpellStore.LookupEntry(cond->mSourceEntry); - - if (!spellProto) - { - sLog.outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); - return false; - } - - bool targetfound = false; - for (uint8 i = 0; i < 3; ++i) - { - if (spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENTRY_SRC || - spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_AREA_ENTRY_SRC || - spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENTRY_DST || - spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_AREA_ENTRY_DST || - spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_NEARBY_ENTRY || - spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_NEARBY_ENTRY || - spellProto->EffectImplicitTargetA[i] == TARGET_GAMEOBJECT_NEARBY_ENTRY || - spellProto->EffectImplicitTargetB[i] == TARGET_GAMEOBJECT_NEARBY_ENTRY || - spellProto->EffectImplicitTargetA[i] == TARGET_DST_NEARBY_ENTRY || - spellProto->EffectImplicitTargetB[i] == TARGET_DST_NEARBY_ENTRY || - spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_CONE_ENTRY || - spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_CONE_ENTRY) - { - targetfound = true; - break; - } - } - if (!targetfound) - { - sLog.outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DST_NEARBY_ENTRY (46)\ - ,TARGET_UNIT_AREA_ENTRY_SRC(7), TARGET_UNIT_AREA_ENTRY_DST(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)",cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE: - { - if (!sCreatureStorage.LookupEntry(cond->mSourceEntry)) - { - sLog.outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_SPELL: - { - SpellEntry const* spellProto = sSpellStore.LookupEntry(cond->mSourceEntry); - if (!spellProto) - { - sLog.outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); - return false; - } - break; - } - case CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET: - { - if (cond->mConditionType != CONDITION_ITEM_TARGET) - { - sLog.outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_ITEM_TARGET(24) is valid for CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET(18), ignoring.", cond->mSourceEntry, uint32(cond->mConditionType)); - return false; - } - ItemPrototype const *pItemProto = objmgr.GetItemPrototype(cond->mSourceEntry); - if (!pItemProto) - { - sLog.outErrorDb("SourceEntry %u in `condition` table, does not exist in `item_tamplate`, ignoring.", cond->mSourceEntry); - return false; - } - bool bIsItemSpellValid = false; - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - if (SpellEntry const* pSpellInfo = sSpellStore.LookupEntry(pItemProto->Spells[i].SpellId)) - { - if (pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE || - pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) - { - ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, pSpellInfo->Id);//script loading is done before item target loading - if (!conditions.empty()) - break; - - for (int j = 0; j < 3; ++j) - { - if (pSpellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ENEMY || - pSpellInfo->EffectImplicitTargetB[i] == TARGET_UNIT_TARGET_ENEMY || - pSpellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ANY || - pSpellInfo->EffectImplicitTargetB[i] == TARGET_UNIT_TARGET_ANY) - { - bIsItemSpellValid = true; - break; - } - } - if (bIsItemSpellValid) - break; - } - } - } - - if (!bIsItemSpellValid) - { - sLog.outErrorDb("Conditions:ITEM_REQUIRED_TARGET used by item %u does not have implicit target TARGET_CHAIN_DAMAGE(6), TARGET_DUELVSPLAYER(25), already listed in scriptTargets or doesn't have item spelltrigger.", cond->mSourceEntry); - break; - } - break; - } - case CONDITION_SOURCE_TYPE_GOSSIP_MENU: - case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: - case CONDITION_SOURCE_TYPE_NONE: - break; - } - return true; -} -bool ConditionMgr::isConditionTypeValid(Condition* cond) -{ - if (cond->mConditionType == CONDITION_NONE || cond->mConditionType >= MAX_CONDITION) - { - sLog.outErrorDb("Invalid ConditionType %u at SourceEntry %u in `condition` table, ignoring.", uint32(cond->mConditionType),cond->mSourceEntry); - return false; - } - switch (cond->mConditionType) - { - case CONDITION_AURA: - { - if (!sSpellStore.LookupEntry(cond->mConditionValue1)) - { - sLog.outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2 > 2) - { - sLog.outErrorDb("Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->mConditionValue2); - return false; - } - break; - } - case CONDITION_ITEM: - { - ItemPrototype const *proto = objmgr.GetItemPrototype(cond->mConditionValue1); - if (!proto) - { - sLog.outErrorDb("Item condition has non existing item (%u), skipped", cond->mConditionValue1); - return false; - } - if (!cond->mConditionValue2) - { - sLog.outErrorDb("Item condition has 0 set for item count in value2 (%u), skipped", cond->mConditionValue2); - return false; - } - break; - } - case CONDITION_ITEM_EQUIPPED: - { - ItemPrototype const *proto = objmgr.GetItemPrototype(cond->mConditionValue1); - if (!proto) - { - sLog.outErrorDb("ItemEquipped condition has non existing item (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("ItemEquipped condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_ZONEID: - { - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->mConditionValue1); - if (!areaEntry) - { - sLog.outErrorDb("Zone condition has non existing area (%u), skipped", cond->mConditionValue1); - return false; - } - if (areaEntry->zone != 0) - { - sLog.outErrorDb("Zone condition requires to be in area (%u) which is a subzone but zone expected, skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("Zone condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_REPUTATION_RANK: - { - FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->mConditionValue1); - if (!factionEntry) - { - sLog.outErrorDb("Reputation condition has non existing faction (%u), skipped", cond->mConditionValue1); - return false; - } - break; - } - case CONDITION_TEAM: - { - if (cond->mConditionValue1 != ALLIANCE && cond->mConditionValue1 != HORDE) - { - sLog.outErrorDb("Team condition specifies unknown team (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("Team condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_SKILL: - { - SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(cond->mConditionValue1); - if (!pSkill) - { - sLog.outErrorDb("Skill condition specifies non-existing skill (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2 < 1 || cond->mConditionValue2 > sWorld.GetConfigMaxSkillValue()) - { - sLog.outErrorDb("Skill condition specifies invalid skill value (%u), skipped", cond->mConditionValue2); - return false; - } - break; - } - case CONDITION_QUESTREWARDED: - case CONDITION_QUESTTAKEN: - case CONDITION_QUEST_NONE: - { - Quest const *Quest = objmgr.GetQuestTemplate(cond->mConditionValue1); - if (!Quest) - { - sLog.outErrorDb("Quest condition specifies non-existing quest (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_AD_COMMISSION_AURA: - { - if (cond->mConditionValue1) - sLog.outErrorDb("Quest condition has useless data in value1 (%u)!", cond->mConditionValue1); - if (cond->mConditionValue2) - sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_NO_AURA: - { - if (!sSpellStore.LookupEntry(cond->mConditionValue1)) - { - sLog.outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2 > 2) - { - sLog.outErrorDb("Aura condition has non existing effect index (%u) in value2 (must be 0..2), skipped", cond->mConditionValue2); - return false; - } - break; - } - case CONDITION_ACTIVE_EVENT: - { - GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); - if (cond->mConditionValue1 >=events.size() || !events[cond->mConditionValue1].isValid()) - { - sLog.outErrorDb("Active event condition has non existing event id (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("Active event condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_ACHIEVEMENT: - { - AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(cond->mConditionValue1); - if (!achievement) - { - sLog.outErrorDb("Achivemen condition has non existing achivement id (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("Achivemen condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_CLASS: - { - if (cond->mConditionValue1 >= MAX_CLASSES) - { - sLog.outErrorDb("Class condition has non existing class (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("Class condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_RACE: - { - if (cond->mConditionValue1 >= MAX_RACES) - { - sLog.outErrorDb("Race condition has non existing race (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("Race condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_SPELL_SCRIPT_TARGET: - { - if (cond->mConditionValue1 >= MAX_SPELL_TARGET_TYPE) - { - sLog.outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->mConditionValue1); - return false; - } - switch(cond->mConditionValue1) - { - case SPELL_TARGET_TYPE_GAMEOBJECT: - { - if (cond->mConditionValue2 && !sGOStorage.LookupEntry(cond->mConditionValue2)) - { - sLog.outErrorDb("SpellTarget condition has non existing gameobject (%u) as target, skipped", cond->mConditionValue2); - return false; - } - break; - } - case SPELL_TARGET_TYPE_CONTROLLED: - case SPELL_TARGET_TYPE_CREATURE: - case SPELL_TARGET_TYPE_DEAD: - { - if (cond->mConditionValue2 && !sCreatureStorage.LookupEntry(cond->mConditionValue2)) - { - sLog.outErrorDb("SpellTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue2); - return false; - } - const CreatureInfo* cInfo = sCreatureStorage.LookupEntry(cond->mConditionValue2); - - if (cond->mSourceEntry == 30427 && !cInfo->SkinLootId) - { - sLog.outErrorDb("SpellTarget condition has creature entry %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!, skipped", cond->mConditionValue2); - return false; - } - break; - } - } - if (cond->mConditionValue3) - sLog.outErrorDb("SpellTarget condition has useless data in value3 (%u)!", cond->mConditionValue3); - break; - } - case CONDITION_CREATURE_TARGET: - { - if (!cond->mConditionValue1 && !sCreatureStorage.LookupEntry(cond->mConditionValue1)) - { - sLog.outErrorDb("CreatureTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("CreatureTarget condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_TARGET_HEALTH_BELOW_PCT: - { - if (cond->mConditionValue1 > 100) - { - sLog.outErrorDb("TargetHealthBelowPct condition has invalid data in value1 (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("TargetHealthBelowPct condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_TARGET_RANGE: - { - if (cond->mConditionValue2 && cond->mConditionValue2 < cond->mConditionValue1)//maxDist can be 0 for infinit max range - { - sLog.outErrorDb("TargetRange condition has max distance closer then min distance, skipped"); - return false; - } - break; - } - case CONDITION_MAPID: - { - MapEntry const * me = sMapStore.LookupEntry(cond->mConditionValue1); - if (!me) - { - sLog.outErrorDb("Map condition has non existing map (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue2) - sLog.outErrorDb("Map condition has useless data in value2 (%u)!", cond->mConditionValue2); - break; - } - case CONDITION_ITEM_TARGET: - { - if (!cond->mConditionValue1 || cond->mConditionValue1 > MAX_ITEM_REQ_TARGET_TYPE) - { - sLog.outErrorDb("ItemTarget condition has incorrect target type (%u), skipped", cond->mConditionValue1); - return false; - } - if (!cond->mConditionValue2 && !sCreatureStorage.LookupEntry(cond->mConditionValue2)) - { - sLog.outErrorDb("ItemTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue2); - return false; - } - if (cond->mConditionValue3) - sLog.outErrorDb("ItemTarget condition has useless data in value3 (%u)!", cond->mConditionValue3); - break; - } - case CONDITION_AREAID: - case CONDITION_INSTANCE_DATA: - break; - } - return true; -} diff --git a/src/server/game/ConditionMgr/ConditionMgr.h b/src/server/game/ConditionMgr/ConditionMgr.h deleted file mode 100644 index bc2ce8d01a2..00000000000 --- a/src/server/game/ConditionMgr/ConditionMgr.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CONDITIONMGR_H -#define TRINITY_CONDITIONMGR_H - -#include "LootMgr.h" - -class Player; -class Unit; -class LootTemplate; - -enum ConditionType -{ // value1 value2 value3 - CONDITION_NONE = 0, // 0 0 0 always true - CONDITION_AURA = 1, // spell_id effindex +referenceID true if has aura of spell_id with effect effindex - CONDITION_ITEM = 2, // item_id count +referenceID true if has #count of item_ids - CONDITION_ITEM_EQUIPPED = 3, // item_id 0 +referenceID true if has item_id equipped - CONDITION_ZONEID = 4, // zone_id 0 +referenceID true if in zone_id - CONDITION_REPUTATION_RANK = 5, // faction_id min_rank +referenceID true if has min_rank for faction_id - CONDITION_TEAM = 6, // player_team 0, +referenceID 469 - Alliance, 67 - Horde) - CONDITION_SKILL = 7, // skill_id skill_value +referenceID true if has skill_value for skill_id - CONDITION_QUESTREWARDED = 8, // quest_id 0 +referenceID true if quest_id was rewarded before - CONDITION_QUESTTAKEN = 9, // quest_id 0, +referenceID true while quest active - CONDITION_AD_COMMISSION_AURA = 10, // 0 0, +referenceID true while one from AD commission aura active - CONDITION_NO_AURA = 11, // spell_id effindex +referenceID true if does not have aura of spell_id with effect effindex - CONDITION_ACTIVE_EVENT = 12, // event_id 0 +referenceID true if event is active - CONDITION_INSTANCE_DATA = 13, // entry data +referenceID true if data is set in current instance - CONDITION_QUEST_NONE = 14, // quest_id 0 +referenceID true if doesn't have quest saved - CONDITION_CLASS = 15, // class 0 +referenceID true if player's class is equal to class - CONDITION_RACE = 16, // race 0 +referenceID true if player's race is equal to race - CONDITION_ACHIEVEMENT = 17, // achievement_id 0 +referenceID true if achievement is complete - CONDITION_SPELL_SCRIPT_TARGET = 18, // SpellScriptTargetType, TargetEntry, 0 - CONDITION_CREATURE_TARGET = 19, // creature entry 0 +referenceID true if current target is creature with value1 entry - CONDITION_TARGET_HEALTH_BELOW_PCT = 20, // 0-100 0 +referenceID true if target's health is below value1 percent, false if over or no target - CONDITION_TARGET_RANGE = 21, // minDistance maxDist +referenceID true if target is closer then minDist and further then maxDist or if max is 0 then max dist is infinit - CONDITION_MAPID = 22, // map_id 0 +referenceID true if in map_id - CONDITION_AREAID = 23, // area_id 0 +referenceID true if in area_id - CONDITION_ITEM_TARGET = 24 // ItemRequiredTargetType, TargetEntry, 0 -}; - -#define MAX_CONDITION 25 // maximum value in ConditionType enum - -enum ConditionSourceType -{ - CONDITION_SOURCE_TYPE_NONE = 0,//DONE - CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE = 1,//DONE - CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE = 2,//DONE - CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE = 3,//DONE - CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE = 4,//DONE - CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE = 5,//DONE - CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE = 6,//DONE - CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE = 7,//DONE - CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE = 8,//DONE - CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE = 9,//DONE - CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10,//DONE - CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11,//DONE - CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12,//DONE - CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET = 13,//DONE - CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14,//DONE - CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15,//DONE - CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16,//DONE - CONDITION_SOURCE_TYPE_SPELL = 17,//DONE - CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET = 18//DONE -}; - -#define MAX_CONDITIONSOURCETYPE 19 - -struct Condition -{ - ConditionSourceType mSourceType; //SourceTypeOrReferenceId - uint32 mSourceGroup; - uint32 mSourceEntry; - uint32 mElseGroup; - ConditionType mConditionType; //ConditionTypeOrReference - uint32 mConditionValue1; - uint32 mConditionValue2; - uint32 mConditionValue3; - uint32 ErrorTextd; - uint32 mReferenceId; - - Condition() - { - mSourceType = CONDITION_SOURCE_TYPE_NONE; - mSourceGroup = 0; - mSourceEntry = 0; - mElseGroup = 0; - mConditionType = CONDITION_NONE; - mConditionValue1 = 0; - mConditionValue2 = 0; - mConditionValue3 = 0; - mReferenceId = 0; - ErrorTextd = 0; - } - bool Meets(Player * player, Unit* targetOverride = NULL); - bool isLoaded() { return mConditionType > CONDITION_NONE || mReferenceId; } -}; - -typedef std::list ConditionList; -typedef std::map ConditionTypeMap; -typedef std::map ConditionMap;//used for all conditions, except references - -typedef std::map ConditionReferenceMap;//only used for references - -class ConditionMgr -{ - public: - ConditionMgr(); - ~ConditionMgr(); - - void LoadConditions(bool isReload = false); - bool isConditionTypeValid(Condition* cond); - ConditionList GetConditionReferences(uint32 refId); - - bool IsPlayerMeetToConditions(Player* player, ConditionList conditions, Unit* targetOverride = NULL); - ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sType, uint32 uEntry); - - protected: - ConditionMap m_ConditionMap; - ConditionReferenceMap m_ConditionReferenceMap; - - private: - bool isSourceTypeValid(Condition* cond); - bool addToLootTemplate(Condition* cond, LootTemplate* loot); - bool addToGossipMenus(Condition* cond); - bool addToGossipMenuItems(Condition* cond); - bool IsPlayerMeetToConditionList(Player* player,const ConditionList& conditions, Unit* targetOverride = NULL); - - bool isGroupable(ConditionSourceType sourceType) - { - return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE || - sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU || - sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION); - } -}; - -#define sConditionMgr Trinity::Singleton::Instance() - -#endif diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp new file mode 100644 index 00000000000..8e5a7e5677e --- /dev/null +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -0,0 +1,1145 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Policies/SingletonImp.h" +#include "Player.h" +#include "SpellAuras.h" +#include "SpellMgr.h" +#include "GameEventMgr.h" +#include "ObjectMgr.h" +#include "ProgressBar.h" +#include "InstanceData.h" +#include "ConditionMgr.h" + +INSTANTIATE_SINGLETON_1(ConditionMgr); + +// Checks if player meets the condition +// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI) +bool Condition::Meets(Player * player, Unit* targetOverride) +{ + if (!player) + { + sLog.outDebug("Condition player not found"); + return false; // player not present, return false + } + uint32 refId = 0; + bool condMeets = false; + bool sendErrorMsg = false; + refId = mConditionValue3;//value 3 can be a 'quick' reference + switch (mConditionType) + { + case CONDITION_NONE: + condMeets = true; // empty condition, always met + break; + case CONDITION_AURA: + condMeets = player->HasAuraEffect(mConditionValue1, mConditionValue2); + break; + case CONDITION_ITEM: + condMeets = player->HasItemCount(mConditionValue1, mConditionValue2); + break; + case CONDITION_ITEM_EQUIPPED: + condMeets = player->HasItemOrGemWithIdEquipped(mConditionValue1,1); + break; + case CONDITION_ZONEID: + condMeets = player->GetZoneId() == mConditionValue1; + break; + case CONDITION_REPUTATION_RANK: + { + FactionEntry const* faction = sFactionStore.LookupEntry(mConditionValue1); + condMeets = faction && uint32(player->GetReputationMgr().GetRank(faction)) >= int32(mConditionValue2); + break; + } + case CONDITION_ACHIEVEMENT: + { + AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(mConditionValue1); + condMeets = player->GetAchievementMgr().HasAchieved(achievement); + break; + } + case CONDITION_TEAM: + condMeets = player->GetTeam() == mConditionValue1; + break; + case CONDITION_CLASS: + condMeets = player->getClass() == mConditionValue1; + break; + case CONDITION_RACE: + condMeets = player->getRace() == mConditionValue1; + break; + case CONDITION_SKILL: + condMeets = player->HasSkill(mConditionValue1) && player->GetBaseSkillValue(mConditionValue1) >= mConditionValue2; + break; + case CONDITION_QUESTREWARDED: + condMeets = player->GetQuestRewardStatus(mConditionValue1); + break; + case CONDITION_QUESTTAKEN: + { + QuestStatus status = player->GetQuestStatus(mConditionValue1); + condMeets = (status == QUEST_STATUS_INCOMPLETE); + break; + } + case CONDITION_QUEST_NONE: + { + QuestStatus status = player->GetQuestStatus(mConditionValue1); + condMeets = (status == QUEST_STATUS_NONE); + break; + } + case CONDITION_AD_COMMISSION_AURA: + { + Unit::AuraApplicationMap const& auras = player->GetAppliedAuras(); + for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + if ((itr->second->GetBase()->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetBase()->GetSpellProto()->SpellVisual[0] == 3580) + { + condMeets = true; + break; + } + condMeets = false; + break; + } + case CONDITION_NO_AURA: + condMeets = !player->HasAuraEffect(mConditionValue1, mConditionValue2); + break; + case CONDITION_ACTIVE_EVENT: + condMeets = gameeventmgr.IsActiveEvent(mConditionValue1); + break; + case CONDITION_INSTANCE_DATA: + { + Map *map = player->GetMap(); + if (map && map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData()) + condMeets = ((InstanceMap*)map)->GetInstanceData()->GetData(mConditionValue1) == mConditionValue2; + break; + } + case CONDITION_SPELL_SCRIPT_TARGET: + condMeets = true;//spell target condition is handled in spellsystem, here it is always true + refId = 0;//cant have references! use CONDITION_SOURCE_TYPE_SPELL for it + break; + case CONDITION_CREATURE_TARGET: + { + Unit* target = player->GetSelectedUnit(); + if (targetOverride) + target = targetOverride; + if (target) + if (Creature* cTarget = target->ToCreature()) + if (cTarget->GetEntry() == mConditionValue1) + condMeets = true; + break; + } + case CONDITION_TARGET_HEALTH_BELOW_PCT: + { + Unit* target = player->GetSelectedUnit(); + if (targetOverride) + target = targetOverride; + if (target) + if ((target->GetHealth()*100 / target->GetMaxHealth()) <= mConditionValue1) + condMeets = true; + break; + } + case CONDITION_TARGET_RANGE: + { + if (Unit* target = player->GetSelectedUnit()) + if (player->GetDistance(target) >= mConditionValue1 && (!mConditionValue2 || player->GetDistance(target) <= mConditionValue2)) + condMeets = true; + break; + } + case CONDITION_MAPID: + condMeets = player->GetMapId() == mConditionValue1; + break; + case CONDITION_AREAID: + condMeets = player->GetAreaId() == mConditionValue1; + break; + case CONDITION_ITEM_TARGET: + { + condMeets = true;//handled in Item::IsTargetValidForItemUse + refId = 0;//cant have references for now + break; + } + default: + condMeets = false; + refId = 0; + break; + } + switch (mSourceType) + { + case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET: + case CONDITION_SOURCE_TYPE_SPELL: + sendErrorMsg = true; + break; + } + + bool refMeets = false; + if (condMeets && refId)//only have to check references if 'this' is met + { + ConditionList ref = sConditionMgr.GetConditionReferences(refId); + refMeets = sConditionMgr.IsPlayerMeetToConditions(player, ref); + }else refMeets = true; + + if (sendErrorMsg && ErrorTextd && (!condMeets || !refMeets))//send special error from DB + player->m_ConditionErrorMsgId = ErrorTextd; + + return condMeets && refMeets; +} + +ConditionMgr::ConditionMgr() +{ +} + +ConditionMgr::~ConditionMgr() +{ +} + +ConditionList ConditionMgr::GetConditionReferences(uint32 refId) +{ + ConditionList conditions; + ConditionReferenceMap::const_iterator ref = m_ConditionReferenceMap.find(refId); + if (ref != m_ConditionReferenceMap.end()) + conditions = (*ref).second; + return conditions; +} + +bool ConditionMgr::IsPlayerMeetToConditionList(Player* player,const ConditionList& conditions, Unit* targetOverride) +{ + std::mapElseGroupMap; + for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i) + { + sLog.outDebug("ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u",(*i)->mConditionType,(*i)->mConditionValue1); + if ((*i)->isLoaded()) + { + std::map::const_iterator itr = ElseGroupMap.find((*i)->mElseGroup); + if (itr == ElseGroupMap.end()) + ElseGroupMap[(*i)->mElseGroup] = true; + else if (!(*itr).second) + continue; + + if ((*i)->mReferenceId)//handle reference + { + ConditionReferenceMap::const_iterator ref = m_ConditionReferenceMap.find((*i)->mReferenceId); + if (ref != m_ConditionReferenceMap.end()) + { + if(!IsPlayerMeetToConditionList(player, (*ref).second, targetOverride)) + ElseGroupMap[(*i)->mElseGroup] = false; + }else{ + sLog.outDebug("IsPlayerMeetToConditionList: Reference template -%u not found", (*i)->mReferenceId);//checked at loading, should never happen + } + + } else//handle normal condition + { + if (!(*i)->Meets(player, targetOverride)) + ElseGroupMap[(*i)->mElseGroup] = false; + } + } + } + for (std::map::const_iterator i = ElseGroupMap.begin(); i != ElseGroupMap.end(); ++i) + if (i->second) + return true; + return false; +} + +bool ConditionMgr::IsPlayerMeetToConditions(Player* player, ConditionList conditions, Unit* targetOverride) +{ + if (conditions.empty()) + return true; + if(player) + player->m_ConditionErrorMsgId = 0; + + sLog.outDebug("ConditionMgr::IsPlayerMeetToConditions"); + bool result = IsPlayerMeetToConditionList(player, conditions, targetOverride); + + if (player && player->m_ConditionErrorMsgId && player->GetSession()) + player->GetSession()->SendNotification(player->m_ConditionErrorMsgId);//m_ConditionErrorMsgId is set only if a condition was not met + + return result; +} + +ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType sType, uint32 uEntry) +{ + ConditionList spellCond; + if (sType > CONDITION_SOURCE_TYPE_NONE && sType < MAX_CONDITIONSOURCETYPE) + { + ConditionMap::const_iterator itr = m_ConditionMap.find(sType); + if (itr != m_ConditionMap.end()) + { + ConditionTypeMap::const_iterator i = (*itr).second.find(uEntry); + if (i != (*itr).second.end()) + { + spellCond = (*i).second; + sLog.outDebug("GetConditionsForNotGroupedEntry: found conditions for type %u and entry %u", uint32(sType), uEntry); + } + } + } + return spellCond; +} + +void ConditionMgr::LoadConditions(bool isReload) +{ + m_ConditionMap.clear(); // for reload case + m_ConditionReferenceMap.clear(); // for reload case + //must clear all custom handled cases (groupped types) before reload + if (isReload) + { + sLog.outString("Reseting Loot Conditions..."); + LootTemplates_Creature.ResetConditions(); + LootTemplates_Fishing.ResetConditions(); + LootTemplates_Gameobject.ResetConditions(); + LootTemplates_Item.ResetConditions(); + LootTemplates_Mail.ResetConditions(); + LootTemplates_Milling.ResetConditions(); + LootTemplates_Pickpocketing.ResetConditions(); + LootTemplates_Reference.ResetConditions(); + LootTemplates_Skinning.ResetConditions(); + LootTemplates_Disenchant.ResetConditions(); + LootTemplates_Prospecting.ResetConditions(); + LootTemplates_Spell.ResetConditions(); + + sLog.outString("Re-Loading `gossip_menu` Table for Conditions!"); + objmgr.LoadGossipMenu(); + + sLog.outString("Re-Loading `gossip_menu_option` Table for Conditions!"); + objmgr.LoadGossipMenuItems(); + } + + uint32 count = 0; + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, ElseGroup, ConditionTypeOrReference, ConditionValue1, ConditionValue2, ConditionValue3, ErrorTextId FROM conditions"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `conditions`, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + + Condition* cond = new Condition(); + int32 iSourceTypeOrReferenceId = fields[0].GetInt32(); + cond->mSourceGroup = fields[1].GetUInt32(); + cond->mSourceEntry = fields[2].GetUInt32(); + cond->mElseGroup = fields[3].GetUInt32(); + int32 iConditionTypeOrReference = fields[4].GetInt32(); + cond->mConditionValue1 = fields[5].GetUInt32(); + cond->mConditionValue2 = fields[6].GetUInt32(); + cond->mConditionValue3 = fields[7].GetUInt32(); + cond->ErrorTextd = fields[8].GetUInt32(); + + if (iConditionTypeOrReference >= 0) + cond->mConditionType = ConditionType(iConditionTypeOrReference); + + if (iConditionTypeOrReference < 0)//it has a reference + { + if (iConditionTypeOrReference == iSourceTypeOrReferenceId)//self referencing, skipp + { + sLog.outErrorDb("Condition reference %i is referencing self, skipped", iSourceTypeOrReferenceId); + continue; + } + cond->mReferenceId = uint32(abs(iConditionTypeOrReference)); + + const char* rowType = "reference template"; + if (iSourceTypeOrReferenceId >= 0) + rowType = "reference"; + //check for useless data + if (cond->mConditionValue1) + sLog.outErrorDb("Condition %s %i has useless data in value1 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue1); + if (cond->mConditionValue2) + sLog.outErrorDb("Condition %s %i has useless data in value2 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue2); + if (cond->mConditionValue3) + sLog.outErrorDb("Condition %s %i has useless data in value3 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue3); + if (cond->mSourceGroup && iSourceTypeOrReferenceId < 0) + sLog.outErrorDb("Condition %s %i has useless data in SourceGroup (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceGroup); + if (cond->mSourceEntry && iSourceTypeOrReferenceId < 0) + sLog.outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceEntry); + }else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType + continue; + + + if (iSourceTypeOrReferenceId < 0)//it is a reference template + { + uint32 uRefId = abs(iSourceTypeOrReferenceId); + if (m_ConditionReferenceMap.find(uRefId) == m_ConditionReferenceMap.end())//make sure we have a list for our conditions, based on reference id + { + ConditionList mCondList; + m_ConditionReferenceMap[uRefId] = mCondList; + } + m_ConditionReferenceMap[uRefId].push_back(cond);//add to reference storage + count++; + continue; + }//end of reference templates + + cond->mSourceType = ConditionSourceType(iSourceTypeOrReferenceId); + + //if not a reference and SourceType is invalid, skip + if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond)) + continue; + + //Grouping is only allowed for some types (loot templates, gossip menus, gossip items) + if (cond->mSourceGroup && !isGroupable(cond->mSourceType)) + { + sLog.outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->mSourceType), cond->mSourceGroup); + continue; + }else if (cond->mSourceGroup) + { + bool bIsDone = false; + //handle grouped conditions + switch (cond->mSourceType) + { + case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Creature.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Disenchant.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Fishing.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Gameobject.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Item.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Mail.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Milling.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Pickpocketing.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Prospecting.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Reference.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Skinning.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE: + bIsDone = addToLootTemplate(cond, LootTemplates_Spell.GetLootForConditionFill(cond->mSourceGroup)); + break; + case CONDITION_SOURCE_TYPE_GOSSIP_MENU: + bIsDone = addToGossipMenus(cond); + break; + case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: + bIsDone = addToGossipMenuItems(cond); + break; + } + if (!bIsDone) + sLog.outErrorDb("Not handled grouped condition, SourceGroup %u", cond->mSourceGroup); + else + ++count; + continue; + } + + //handle not grouped conditions + //make sure we have a storage list for our SourceType + if (m_ConditionMap.find(cond->mSourceType) == m_ConditionMap.end()) + { + ConditionTypeMap mTypeMap; + m_ConditionMap[cond->mSourceType] = mTypeMap;//add new empty list for SourceType + } + + //make sure we have a condition list for our SourceType's entry + if (m_ConditionMap[cond->mSourceType].find(cond->mSourceEntry) == m_ConditionMap[cond->mSourceType].end()) + { + ConditionList mCondList; + m_ConditionMap[cond->mSourceType][cond->mSourceEntry] = mCondList; + } + + //add new Condition to storage based on Type/Entry + m_ConditionMap[cond->mSourceType][cond->mSourceEntry].push_back(cond); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u conditions", count); +} + +bool ConditionMgr::addToLootTemplate(Condition* cond, LootTemplate* loot) +{ + if (!loot) + { + sLog.outErrorDb("ConditionMgr: LootTemplate %u not found", cond->mSourceGroup); + return false; + } + if (loot->addConditionItem(cond)) + return true; + sLog.outErrorDb("ConditionMgr: Item %u not found in LootTemplate %u", cond->mSourceEntry, cond->mSourceGroup); + return false; +} + +bool ConditionMgr::addToGossipMenus(Condition* cond) +{ + GossipMenusMapBoundsNonConst pMenuBounds = objmgr.GetGossipMenusMapBoundsNonConst(cond->mSourceGroup); + + if (pMenuBounds.first != pMenuBounds.second) + { + for (GossipMenusMap::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr) + { + if ((*itr).second.entry == cond->mSourceGroup && (*itr).second.text_id == cond->mSourceEntry) + { + (*itr).second.conditions.push_back(cond); + sLog.outDebug("addToGossipMenus: entry %u textId %u", cond->mSourceGroup, cond->mSourceEntry); + return true; + } + } + } + sLog.outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->mSourceGroup); + return false; +} + +bool ConditionMgr::addToGossipMenuItems(Condition* cond) +{ + GossipMenuItemsMapBoundsNonConst pMenuItemBounds = objmgr.GetGossipMenuItemsMapBoundsNonConst(cond->mSourceGroup); + if (pMenuItemBounds.first != pMenuItemBounds.second) + { + for (GossipMenuItemsMap::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr) + { + if ((*itr).second.menu_id == cond->mSourceGroup && (*itr).second.id == cond->mSourceEntry) + { + (*itr).second.conditions.push_back(cond); + //sLog.outDebug("addToGossipMenuItems: menuId %u id %u", cond->mSourceGroup, cond->mSourceEntry); + return true; + } + } + } + sLog.outErrorDb("addToGossipMenuItems: GossipMenuIt %u Item %u not found", cond->mSourceGroup, cond->mSourceEntry); + return false; +} + +bool ConditionMgr::isSourceTypeValid(Condition* cond) +{ + if (cond->mSourceType == CONDITION_SOURCE_TYPE_NONE || cond->mSourceType >= MAX_CONDITIONSOURCETYPE) + { + sLog.outErrorDb("Invalid ConditionSourceType %u in `condition` table, ignoring.", uint32(cond->mSourceType)); + return false; + } + switch (cond->mSourceType) + { + case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE: + { + if (!LootTemplates_Creature.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Creature.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE: + { + if (!LootTemplates_Disenchant.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Disenchant.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE: + { + if (!LootTemplates_Fishing.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Fishing.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE: + { + if (!LootTemplates_Gameobject.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Gameobject.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE: + { + if (!LootTemplates_Item.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Item.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE: + { + if (!LootTemplates_Mail.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Mail.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE: + { + if (!LootTemplates_Milling.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Milling.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE: + { + if (!LootTemplates_Pickpocketing.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Pickpocketing.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE: + { + if (!LootTemplates_Prospecting.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Prospecting.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE: + { + if (!LootTemplates_Reference.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Reference.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE: + { + if (!LootTemplates_Skinning.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Skinning.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE: + { + if (!LootTemplates_Spell.HaveLootFor(cond->mSourceGroup)) + { + sLog.outErrorDb("SourceGroup %u in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->mSourceGroup); + return false; + } + LootTemplate* loot = LootTemplates_Spell.GetLootForConditionFill(cond->mSourceGroup); + ItemPrototype const* pItemProto = sItemStorage.LookupEntry(cond->mSourceEntry); + if (!pItemProto && !loot->isReference(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET: + { + if (cond->mConditionType != CONDITION_SPELL_SCRIPT_TARGET) + { + sLog.outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_SPELL_SCRIPT_TARGET(18) is valid for CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET(14), ignoring.", cond->mSourceEntry, uint32(cond->mConditionType)); + return false; + } + SpellEntry const* spellProto = sSpellStore.LookupEntry(cond->mSourceEntry); + + if (!spellProto) + { + sLog.outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); + return false; + } + + bool targetfound = false; + for (uint8 i = 0; i < 3; ++i) + { + if (spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENTRY_SRC || + spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_AREA_ENTRY_SRC || + spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENTRY_DST || + spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_AREA_ENTRY_DST || + spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_NEARBY_ENTRY || + spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_NEARBY_ENTRY || + spellProto->EffectImplicitTargetA[i] == TARGET_GAMEOBJECT_NEARBY_ENTRY || + spellProto->EffectImplicitTargetB[i] == TARGET_GAMEOBJECT_NEARBY_ENTRY || + spellProto->EffectImplicitTargetA[i] == TARGET_DST_NEARBY_ENTRY || + spellProto->EffectImplicitTargetB[i] == TARGET_DST_NEARBY_ENTRY || + spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_CONE_ENTRY || + spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_CONE_ENTRY) + { + targetfound = true; + break; + } + } + if (!targetfound) + { + sLog.outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DST_NEARBY_ENTRY (46)\ + ,TARGET_UNIT_AREA_ENTRY_SRC(7), TARGET_UNIT_AREA_ENTRY_DST(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)",cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE: + { + if (!sCreatureStorage.LookupEntry(cond->mSourceEntry)) + { + sLog.outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_SPELL: + { + SpellEntry const* spellProto = sSpellStore.LookupEntry(cond->mSourceEntry); + if (!spellProto) + { + sLog.outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); + return false; + } + break; + } + case CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET: + { + if (cond->mConditionType != CONDITION_ITEM_TARGET) + { + sLog.outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_ITEM_TARGET(24) is valid for CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET(18), ignoring.", cond->mSourceEntry, uint32(cond->mConditionType)); + return false; + } + ItemPrototype const *pItemProto = objmgr.GetItemPrototype(cond->mSourceEntry); + if (!pItemProto) + { + sLog.outErrorDb("SourceEntry %u in `condition` table, does not exist in `item_tamplate`, ignoring.", cond->mSourceEntry); + return false; + } + bool bIsItemSpellValid = false; + for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + { + if (SpellEntry const* pSpellInfo = sSpellStore.LookupEntry(pItemProto->Spells[i].SpellId)) + { + if (pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE || + pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) + { + ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, pSpellInfo->Id);//script loading is done before item target loading + if (!conditions.empty()) + break; + + for (int j = 0; j < 3; ++j) + { + if (pSpellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ENEMY || + pSpellInfo->EffectImplicitTargetB[i] == TARGET_UNIT_TARGET_ENEMY || + pSpellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ANY || + pSpellInfo->EffectImplicitTargetB[i] == TARGET_UNIT_TARGET_ANY) + { + bIsItemSpellValid = true; + break; + } + } + if (bIsItemSpellValid) + break; + } + } + } + + if (!bIsItemSpellValid) + { + sLog.outErrorDb("Conditions:ITEM_REQUIRED_TARGET used by item %u does not have implicit target TARGET_CHAIN_DAMAGE(6), TARGET_DUELVSPLAYER(25), already listed in scriptTargets or doesn't have item spelltrigger.", cond->mSourceEntry); + break; + } + break; + } + case CONDITION_SOURCE_TYPE_GOSSIP_MENU: + case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: + case CONDITION_SOURCE_TYPE_NONE: + break; + } + return true; +} +bool ConditionMgr::isConditionTypeValid(Condition* cond) +{ + if (cond->mConditionType == CONDITION_NONE || cond->mConditionType >= MAX_CONDITION) + { + sLog.outErrorDb("Invalid ConditionType %u at SourceEntry %u in `condition` table, ignoring.", uint32(cond->mConditionType),cond->mSourceEntry); + return false; + } + switch (cond->mConditionType) + { + case CONDITION_AURA: + { + if (!sSpellStore.LookupEntry(cond->mConditionValue1)) + { + sLog.outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2 > 2) + { + sLog.outErrorDb("Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->mConditionValue2); + return false; + } + break; + } + case CONDITION_ITEM: + { + ItemPrototype const *proto = objmgr.GetItemPrototype(cond->mConditionValue1); + if (!proto) + { + sLog.outErrorDb("Item condition has non existing item (%u), skipped", cond->mConditionValue1); + return false; + } + if (!cond->mConditionValue2) + { + sLog.outErrorDb("Item condition has 0 set for item count in value2 (%u), skipped", cond->mConditionValue2); + return false; + } + break; + } + case CONDITION_ITEM_EQUIPPED: + { + ItemPrototype const *proto = objmgr.GetItemPrototype(cond->mConditionValue1); + if (!proto) + { + sLog.outErrorDb("ItemEquipped condition has non existing item (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("ItemEquipped condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_ZONEID: + { + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->mConditionValue1); + if (!areaEntry) + { + sLog.outErrorDb("Zone condition has non existing area (%u), skipped", cond->mConditionValue1); + return false; + } + if (areaEntry->zone != 0) + { + sLog.outErrorDb("Zone condition requires to be in area (%u) which is a subzone but zone expected, skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("Zone condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_REPUTATION_RANK: + { + FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->mConditionValue1); + if (!factionEntry) + { + sLog.outErrorDb("Reputation condition has non existing faction (%u), skipped", cond->mConditionValue1); + return false; + } + break; + } + case CONDITION_TEAM: + { + if (cond->mConditionValue1 != ALLIANCE && cond->mConditionValue1 != HORDE) + { + sLog.outErrorDb("Team condition specifies unknown team (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("Team condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_SKILL: + { + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(cond->mConditionValue1); + if (!pSkill) + { + sLog.outErrorDb("Skill condition specifies non-existing skill (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2 < 1 || cond->mConditionValue2 > sWorld.GetConfigMaxSkillValue()) + { + sLog.outErrorDb("Skill condition specifies invalid skill value (%u), skipped", cond->mConditionValue2); + return false; + } + break; + } + case CONDITION_QUESTREWARDED: + case CONDITION_QUESTTAKEN: + case CONDITION_QUEST_NONE: + { + Quest const *Quest = objmgr.GetQuestTemplate(cond->mConditionValue1); + if (!Quest) + { + sLog.outErrorDb("Quest condition specifies non-existing quest (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_AD_COMMISSION_AURA: + { + if (cond->mConditionValue1) + sLog.outErrorDb("Quest condition has useless data in value1 (%u)!", cond->mConditionValue1); + if (cond->mConditionValue2) + sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_NO_AURA: + { + if (!sSpellStore.LookupEntry(cond->mConditionValue1)) + { + sLog.outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2 > 2) + { + sLog.outErrorDb("Aura condition has non existing effect index (%u) in value2 (must be 0..2), skipped", cond->mConditionValue2); + return false; + } + break; + } + case CONDITION_ACTIVE_EVENT: + { + GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap(); + if (cond->mConditionValue1 >=events.size() || !events[cond->mConditionValue1].isValid()) + { + sLog.outErrorDb("Active event condition has non existing event id (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("Active event condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_ACHIEVEMENT: + { + AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(cond->mConditionValue1); + if (!achievement) + { + sLog.outErrorDb("Achivemen condition has non existing achivement id (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("Achivemen condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_CLASS: + { + if (cond->mConditionValue1 >= MAX_CLASSES) + { + sLog.outErrorDb("Class condition has non existing class (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("Class condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_RACE: + { + if (cond->mConditionValue1 >= MAX_RACES) + { + sLog.outErrorDb("Race condition has non existing race (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("Race condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_SPELL_SCRIPT_TARGET: + { + if (cond->mConditionValue1 >= MAX_SPELL_TARGET_TYPE) + { + sLog.outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->mConditionValue1); + return false; + } + switch(cond->mConditionValue1) + { + case SPELL_TARGET_TYPE_GAMEOBJECT: + { + if (cond->mConditionValue2 && !sGOStorage.LookupEntry(cond->mConditionValue2)) + { + sLog.outErrorDb("SpellTarget condition has non existing gameobject (%u) as target, skipped", cond->mConditionValue2); + return false; + } + break; + } + case SPELL_TARGET_TYPE_CONTROLLED: + case SPELL_TARGET_TYPE_CREATURE: + case SPELL_TARGET_TYPE_DEAD: + { + if (cond->mConditionValue2 && !sCreatureStorage.LookupEntry(cond->mConditionValue2)) + { + sLog.outErrorDb("SpellTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue2); + return false; + } + const CreatureInfo* cInfo = sCreatureStorage.LookupEntry(cond->mConditionValue2); + + if (cond->mSourceEntry == 30427 && !cInfo->SkinLootId) + { + sLog.outErrorDb("SpellTarget condition has creature entry %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!, skipped", cond->mConditionValue2); + return false; + } + break; + } + } + if (cond->mConditionValue3) + sLog.outErrorDb("SpellTarget condition has useless data in value3 (%u)!", cond->mConditionValue3); + break; + } + case CONDITION_CREATURE_TARGET: + { + if (!cond->mConditionValue1 && !sCreatureStorage.LookupEntry(cond->mConditionValue1)) + { + sLog.outErrorDb("CreatureTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("CreatureTarget condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_TARGET_HEALTH_BELOW_PCT: + { + if (cond->mConditionValue1 > 100) + { + sLog.outErrorDb("TargetHealthBelowPct condition has invalid data in value1 (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("TargetHealthBelowPct condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_TARGET_RANGE: + { + if (cond->mConditionValue2 && cond->mConditionValue2 < cond->mConditionValue1)//maxDist can be 0 for infinit max range + { + sLog.outErrorDb("TargetRange condition has max distance closer then min distance, skipped"); + return false; + } + break; + } + case CONDITION_MAPID: + { + MapEntry const * me = sMapStore.LookupEntry(cond->mConditionValue1); + if (!me) + { + sLog.outErrorDb("Map condition has non existing map (%u), skipped", cond->mConditionValue1); + return false; + } + if (cond->mConditionValue2) + sLog.outErrorDb("Map condition has useless data in value2 (%u)!", cond->mConditionValue2); + break; + } + case CONDITION_ITEM_TARGET: + { + if (!cond->mConditionValue1 || cond->mConditionValue1 > MAX_ITEM_REQ_TARGET_TYPE) + { + sLog.outErrorDb("ItemTarget condition has incorrect target type (%u), skipped", cond->mConditionValue1); + return false; + } + if (!cond->mConditionValue2 && !sCreatureStorage.LookupEntry(cond->mConditionValue2)) + { + sLog.outErrorDb("ItemTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue2); + return false; + } + if (cond->mConditionValue3) + sLog.outErrorDb("ItemTarget condition has useless data in value3 (%u)!", cond->mConditionValue3); + break; + } + case CONDITION_AREAID: + case CONDITION_INSTANCE_DATA: + break; + } + return true; +} diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h new file mode 100644 index 00000000000..bc2ce8d01a2 --- /dev/null +++ b/src/server/game/Conditions/ConditionMgr.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CONDITIONMGR_H +#define TRINITY_CONDITIONMGR_H + +#include "LootMgr.h" + +class Player; +class Unit; +class LootTemplate; + +enum ConditionType +{ // value1 value2 value3 + CONDITION_NONE = 0, // 0 0 0 always true + CONDITION_AURA = 1, // spell_id effindex +referenceID true if has aura of spell_id with effect effindex + CONDITION_ITEM = 2, // item_id count +referenceID true if has #count of item_ids + CONDITION_ITEM_EQUIPPED = 3, // item_id 0 +referenceID true if has item_id equipped + CONDITION_ZONEID = 4, // zone_id 0 +referenceID true if in zone_id + CONDITION_REPUTATION_RANK = 5, // faction_id min_rank +referenceID true if has min_rank for faction_id + CONDITION_TEAM = 6, // player_team 0, +referenceID 469 - Alliance, 67 - Horde) + CONDITION_SKILL = 7, // skill_id skill_value +referenceID true if has skill_value for skill_id + CONDITION_QUESTREWARDED = 8, // quest_id 0 +referenceID true if quest_id was rewarded before + CONDITION_QUESTTAKEN = 9, // quest_id 0, +referenceID true while quest active + CONDITION_AD_COMMISSION_AURA = 10, // 0 0, +referenceID true while one from AD commission aura active + CONDITION_NO_AURA = 11, // spell_id effindex +referenceID true if does not have aura of spell_id with effect effindex + CONDITION_ACTIVE_EVENT = 12, // event_id 0 +referenceID true if event is active + CONDITION_INSTANCE_DATA = 13, // entry data +referenceID true if data is set in current instance + CONDITION_QUEST_NONE = 14, // quest_id 0 +referenceID true if doesn't have quest saved + CONDITION_CLASS = 15, // class 0 +referenceID true if player's class is equal to class + CONDITION_RACE = 16, // race 0 +referenceID true if player's race is equal to race + CONDITION_ACHIEVEMENT = 17, // achievement_id 0 +referenceID true if achievement is complete + CONDITION_SPELL_SCRIPT_TARGET = 18, // SpellScriptTargetType, TargetEntry, 0 + CONDITION_CREATURE_TARGET = 19, // creature entry 0 +referenceID true if current target is creature with value1 entry + CONDITION_TARGET_HEALTH_BELOW_PCT = 20, // 0-100 0 +referenceID true if target's health is below value1 percent, false if over or no target + CONDITION_TARGET_RANGE = 21, // minDistance maxDist +referenceID true if target is closer then minDist and further then maxDist or if max is 0 then max dist is infinit + CONDITION_MAPID = 22, // map_id 0 +referenceID true if in map_id + CONDITION_AREAID = 23, // area_id 0 +referenceID true if in area_id + CONDITION_ITEM_TARGET = 24 // ItemRequiredTargetType, TargetEntry, 0 +}; + +#define MAX_CONDITION 25 // maximum value in ConditionType enum + +enum ConditionSourceType +{ + CONDITION_SOURCE_TYPE_NONE = 0,//DONE + CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE = 1,//DONE + CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE = 2,//DONE + CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE = 3,//DONE + CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE = 4,//DONE + CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE = 5,//DONE + CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE = 6,//DONE + CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE = 7,//DONE + CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE = 8,//DONE + CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE = 9,//DONE + CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10,//DONE + CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11,//DONE + CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12,//DONE + CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET = 13,//DONE + CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14,//DONE + CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15,//DONE + CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16,//DONE + CONDITION_SOURCE_TYPE_SPELL = 17,//DONE + CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET = 18//DONE +}; + +#define MAX_CONDITIONSOURCETYPE 19 + +struct Condition +{ + ConditionSourceType mSourceType; //SourceTypeOrReferenceId + uint32 mSourceGroup; + uint32 mSourceEntry; + uint32 mElseGroup; + ConditionType mConditionType; //ConditionTypeOrReference + uint32 mConditionValue1; + uint32 mConditionValue2; + uint32 mConditionValue3; + uint32 ErrorTextd; + uint32 mReferenceId; + + Condition() + { + mSourceType = CONDITION_SOURCE_TYPE_NONE; + mSourceGroup = 0; + mSourceEntry = 0; + mElseGroup = 0; + mConditionType = CONDITION_NONE; + mConditionValue1 = 0; + mConditionValue2 = 0; + mConditionValue3 = 0; + mReferenceId = 0; + ErrorTextd = 0; + } + bool Meets(Player * player, Unit* targetOverride = NULL); + bool isLoaded() { return mConditionType > CONDITION_NONE || mReferenceId; } +}; + +typedef std::list ConditionList; +typedef std::map ConditionTypeMap; +typedef std::map ConditionMap;//used for all conditions, except references + +typedef std::map ConditionReferenceMap;//only used for references + +class ConditionMgr +{ + public: + ConditionMgr(); + ~ConditionMgr(); + + void LoadConditions(bool isReload = false); + bool isConditionTypeValid(Condition* cond); + ConditionList GetConditionReferences(uint32 refId); + + bool IsPlayerMeetToConditions(Player* player, ConditionList conditions, Unit* targetOverride = NULL); + ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sType, uint32 uEntry); + + protected: + ConditionMap m_ConditionMap; + ConditionReferenceMap m_ConditionReferenceMap; + + private: + bool isSourceTypeValid(Condition* cond); + bool addToLootTemplate(Condition* cond, LootTemplate* loot); + bool addToGossipMenus(Condition* cond); + bool addToGossipMenuItems(Condition* cond); + bool IsPlayerMeetToConditionList(Player* player,const ConditionList& conditions, Unit* targetOverride = NULL); + + bool isGroupable(ConditionSourceType sourceType) + { + return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE || + sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU || + sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION); + } +}; + +#define sConditionMgr Trinity::Singleton::Instance() + +#endif diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h new file mode 100644 index 00000000000..c1b55443852 --- /dev/null +++ b/src/server/game/DungeonFinding/LFG.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LFG_H +#define _LFG_H + +#include "Platform/Define.h" +#include "Object.h" + +enum LfgRoles +{ + ROLE_NONE = 0x00, + ROLE_LEADER = 0x01, + ROLE_TANK = 0x02, + ROLE_HEALER = 0x04, + ROLE_DAMAGE = 0x08, +}; + +enum LfgUpdateType +{ + LFG_UPDATETYPE_LEADER = 1, + LFG_UPDATETYPE_ROLECHECK_ABORTED = 4, + LFG_UPDATETYPE_JOIN_PROPOSAL = 5, + LFG_UPDATETYPE_ROLECHECK_FAILED = 6, + LFG_UPDATETYPE_REMOVED_FROM_QUEUE = 7, + LFG_UPDATETYPE_PROPOSAL_FAILED = 8, + LFG_UPDATETYPE_PROPOSAL_DECLINED = 9, + LFG_UPDATETYPE_GROUP_FOUND = 10, + LFG_UPDATETYPE_ADDED_TO_QUEUE = 12, + LFG_UPDATETYPE_PROPOSAL_FOUND = 13, + LFG_UPDATETYPE_CLEAR_LOCK_LIST = 14, + LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 15, + LFG_UPDATETYPE_GROUP_DISBAND = 16, +}; + +typedef std::set LfgDungeonSet; + +struct LookingForGroup +{ + LookingForGroup(): roles(0) + { + donerandomDungeons.clear(); + applyDungeons.clear(); + } + std::string comment; + int8 roles; + + bool isDungeonDone(const uint32 entry) + { + return donerandomDungeons.find(entry) != donerandomDungeons.end(); + } + + LfgDungeonSet applyDungeons; // Dungeons the player have applied for + LfgDungeonSet donerandomDungeons; // Finished random Dungeons (to calculate the bonus); +}; + +#endif diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp new file mode 100644 index 00000000000..ba418cdb191 --- /dev/null +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -0,0 +1,1100 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "Policies/SingletonImp.h" +#include "Common.h" +#include "SharedDefines.h" +#include "Group.h" +#include "Player.h" +#include "LFGMgr.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" + +INSTANTIATE_SINGLETON_1(LFGMgr); + +/*********************************************************/ +/*** LFG QUEUES ***/ +/*********************************************************/ + +LFGQueue::LFGQueue() +{ + m_LfgQueue.clear(); + avgWaitTime = -1; + waitTimeTanks = -1; + waitTimeHealer = -1; + waitTimeDps = -1; +} + +LFGQueue::~LFGQueue() +{ + m_LfgQueue.clear(); +} + +void LFGQueue::AddToQueue(uint64 guid, LfgQueueInfo* pqInfo) +{ + if (LfgQueueInfo* qInfo = m_LfgQueue[guid]) + delete qInfo; + m_LfgQueue[guid] = pqInfo; + // ATM will only add it to the queue... No find group implementation... yet (on purpose) +} + +bool LFGQueue::RemoveFromQueue(uint64 guid) +{ + if (m_LfgQueue.empty()) + return false; + + LfgQueueInfoMap::iterator itr = m_LfgQueue.find(guid); + if (itr == m_LfgQueue.end()) + return false; + + delete itr->second; + m_LfgQueue.erase(itr); + return true; +} + +LfgQueueInfo* LFGQueue::GetQueueInfo(uint64 guid) +{ + return m_LfgQueue[guid]; +} + +void LFGQueue::Update() +{ + if (m_LfgQueue.empty()) + return; + + Player *plr; + LfgQueueInfo *queue; + time_t currTime = time(NULL); + uint32 queuedTime; + uint8 role = 0; + int32 waitTime = -1; + for (LfgQueueInfoMap::const_iterator itQueue = m_LfgQueue.begin(); itQueue != m_LfgQueue.end(); ++itQueue) + { + queue = itQueue->second; + // Update queue status + queuedTime = uint32(currTime - queue->joinTime); + for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) + { + plr = objmgr.GetPlayer(itPlayer->first); + if (!plr) + continue; + role = itPlayer->second; + if (role & ROLE_TANK) + { + if (role & ROLE_HEALER || role & ROLE_DAMAGE) + waitTime = avgWaitTime; + else + waitTime = waitTimeTanks; + } + else if (role & ROLE_HEALER) + { + if (role & ROLE_DAMAGE) + waitTime = avgWaitTime; + else + waitTime = waitTimeDps; + } + plr->GetSession()->SendLfgQueueStatus(queue->dungeonId, waitTime, avgWaitTime, waitTimeTanks, waitTimeHealer, waitTimeDps, queuedTime, queue->tanks, queue->healers, queue->dps); + } + } +} + +LFGMgr::LFGMgr() +{ + m_QueueTimer = 0; + m_update = true; +} + +LFGMgr::~LFGMgr() +{ + // RewardList to be removed -> query quest system + for (LfgRewardList::iterator it = m_RewardList.begin(); it != m_RewardList.end(); ++it) + delete *it; + m_RewardList.clear(); + + // RewardDoneList to be removed -> query quest system + for (LfgRewardList::iterator it = m_RewardDoneList.begin(); it != m_RewardDoneList.end(); ++it) + delete *it; + m_RewardDoneList.clear(); + + for(LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it) + delete it->second; + m_Queues.clear(); + + for (LfgDungeonMap::iterator it = m_DungeonsMap.begin(); it != m_DungeonsMap.end(); ++it) + { + it->second->clear(); + delete it->second; + } + m_DungeonsMap.clear(); + + for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end(); ++it) + delete it->second; + m_RoleChecks.clear(); +} + +void LFGMgr::Update(uint32 diff) +{ + if (!m_update) + return; + + // Update all players status queue info + if (m_QueueTimer > LFG_QUEUEUPDATE_INTERVAL) + { + m_QueueTimer = 0; + for (LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it) + it->second->Update(); + } + else + m_QueueTimer += diff; + + time_t currTime = time(NULL); + + // Remove obsolete role checks + LfgRoleCheckMap::iterator itRoleCheck; + LfgRoleCheck *pRoleCheck; + for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end();) + { + itRoleCheck = it++; + pRoleCheck = itRoleCheck->second; + if (currTime < pRoleCheck->cancelTime) + continue; + pRoleCheck->result = LFG_ROLECHECK_MISSING_ROLE; + + WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + pRoleCheck->dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1)); + sLog.outDebug("SMSG_LFG_ROLE_CHECK_UPDATE"); + BuildLfgRoleCheck(data, pRoleCheck); + Player *plr = NULL; + for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end(); ++itRoles) + { + plr = objmgr.GetPlayer(itRoles->first); + if (!plr) + continue; + plr->GetSession()->SendPacket(&data); + plr->m_lookingForGroup.applyDungeons.clear(); + plr->m_lookingForGroup.roles = 0; + + if (itRoles->first == pRoleCheck->leader) + plr->GetSession()->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result); + } + delete pRoleCheck; + m_RoleChecks.erase(itRoleCheck); + } +} + +/// +/// Initialize Looking For Group +/// +void LFGMgr::InitLFG() +{ + // Fill reward data (to be removed -> query quest system) + LfgReward *reward; + for (uint8 i = 0; i <= LFG_REWARD_DATA_SIZE; ++i) + { + reward = new LfgReward(); + reward->strangers = 0; + reward->baseXP = RewardDungeonData[i][0]; + reward->baseMoney = RewardDungeonData[i][1]; + reward->variableMoney = 0; + reward->variableXP = 0; + reward->itemId = RewardDungeonData[i][2]; + reward->displayId = RewardDungeonData[i][3]; + reward->stackCount = RewardDungeonData[i][4]; + m_RewardList.push_back(reward); + } + + for (uint8 i = 0; i < LFG_REWARD_DATA_SIZE; ++i) + { + reward = new LfgReward(); + reward->strangers = 0; + reward->baseXP = RewardDungeonDoneData[i][0]; + reward->baseMoney = RewardDungeonDoneData[i][1]; + reward->variableMoney = 0; + reward->variableXP = 0; + reward->itemId = RewardDungeonDoneData[i][2]; + reward->displayId = RewardDungeonDoneData[i][3]; + reward->stackCount = RewardDungeonDoneData[i][4]; + m_RewardDoneList.push_back(reward); + } + // Initialize dungeonMap + m_DungeonsMap[LFG_ALL_DUNGEONS] = GetAllDungeons(); + m_DungeonsMap[LFG_RANDOM_CLASSIC] = GetDungeonsByRandom(LFG_RANDOM_CLASSIC); + m_DungeonsMap[LFG_RANDOM_BC_NORMAL] = GetDungeonsByRandom(LFG_RANDOM_BC_NORMAL); + m_DungeonsMap[LFG_RANDOM_BC_HEROIC] = GetDungeonsByRandom(LFG_RANDOM_BC_HEROIC); + m_DungeonsMap[LFG_RANDOM_LK_NORMAL] = GetDungeonsByRandom(LFG_RANDOM_LK_NORMAL); + m_DungeonsMap[LFG_RANDOM_LK_HEROIC] = GetDungeonsByRandom(LFG_RANDOM_LK_HEROIC); +} + +/// +/// Adds the player to lfg queue +/// +/// Player +void LFGMgr::Join(Player *plr) +{ + Group *grp = plr->GetGroup(); + + // TODO - 2010-05-27 Anyone can init rolecheck when already in a LFD Group? + if (grp && grp->GetLeaderGUID() != plr->GetGUID()) + return; + + // Previous checks before joining + LfgJoinResult result = LFG_JOIN_OK; + if (plr->InBattleGround() || plr->InArena()) + result = LFG_JOIN_USING_BG_SYSTEM; + else if (plr->HasAura(LFG_SPELL_DESERTER)) + result = LFG_JOIN_DESERTER; + else if (plr->HasAura(LFG_SPELL_COOLDOWN)) + result = LFG_JOIN_RANDOM_COOLDOWN; + else + { + // Check if all dungeons are valid + for (LfgDungeonSet::const_iterator it = plr->m_lookingForGroup.applyDungeons.begin(); it != plr->m_lookingForGroup.applyDungeons.end(); ++it) + { + if ((m_DungeonsMap[LFG_ALL_DUNGEONS])->find(*it) == (m_DungeonsMap[LFG_ALL_DUNGEONS])->end()) + { + result = LFG_JOIN_DUNGEON_INVALID; + break; + } + } + } + + if (grp && result == LFG_JOIN_OK) + { + if (grp->GetMembersCount() > MAXGROUPSIZE) + result = LFG_JOIN_TOO_MUCH_MEMBERS; + else if(grp->isRaidGroup()) + result = LFG_JOIN_MIXED_RAID_DUNGEON; + else + { + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL && result == LFG_JOIN_OK; itr = itr->next()) + { + if (Player *plrg = itr->getSource()) + { + if (plrg->HasAura(LFG_SPELL_DESERTER)) + result = LFG_JOIN_PARTY_DESERTER; + else if (plrg->HasAura(LFG_SPELL_COOLDOWN)) + result = LFG_JOIN_PARTY_RANDOM_COOLDOWN; + } + else + result = LFG_JOIN_DISCONNECTED; + } + } + } + + if (result != LFG_JOIN_OK) + { + plr->m_lookingForGroup.applyDungeons.clear(); + plr->m_lookingForGroup.roles = 0; + plr->GetSession()->SendLfgJoinResult(result, 0); + return; + } + + if (grp) + { + Player *plrg = NULL; + for (GroupReference *itr = plr->GetGroup()->GetFirstMember(); itr != NULL; itr = itr->next()) + { + plrg = itr->getSource(); // Not null, checked earlier + plrg->m_lookingForGroup.applyDungeons = plr->m_lookingForGroup.applyDungeons; + plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_JOIN_PROPOSAL); + } + UpdateRoleCheck(grp, plr); + } + else + { + plr->GetSession()->SendLfgJoinResult(LFG_JOIN_OK, 0); + plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_JOIN_PROPOSAL); + + // Add player to queue + LfgQueueInfo *pqInfo; + uint8 groupType = 0; + uint8 tanks = LFG_TANKS_NEEDED; + uint8 healers = LFG_HEALERS_NEEDED; + uint8 dps = LFG_DPS_NEEDED; + if (plr->m_lookingForGroup.roles & ROLE_TANK) + --tanks; + else if (plr->m_lookingForGroup.roles & ROLE_HEALER) + --healers; + else + --dps; + m_update = false; + for (LfgDungeonSet::const_iterator it = plr->m_lookingForGroup.applyDungeons.begin(); it != plr->m_lookingForGroup.applyDungeons.end(); ++it) + { + groupType = GetDungeonGroupType(*it); + pqInfo = m_Queues[groupType] ? m_Queues[groupType]->GetQueueInfo(plr->GetGUID()) : NULL; + // if exist we have already added the player with another dungeon sharing same GroupType + if (pqInfo) + continue; + pqInfo = new LfgQueueInfo(); + pqInfo->dungeonId = *it; + pqInfo->joinTime = time_t(time(NULL)); + pqInfo->tanks = tanks; + pqInfo->healers = healers; + pqInfo->dps = dps; + pqInfo->roles[plr->GetGUID()] = plr->m_lookingForGroup.roles; + if (!m_Queues[groupType]) + m_Queues[groupType] = new LFGQueue(); + m_Queues[groupType]->AddToQueue(plr->GetGUID(), pqInfo); + } + m_update = true; + } +} + +/// +/// Leave the lfg queue +/// +/// Player (could be NULL) +/// Group (could be NULL) +void LFGMgr::Leave(Player *plr, Group *grp /* = NULL*/) +{ + uint64 guid = grp ? grp->GetGUID() : plr ? plr->GetGUID() : 0; + assert(guid); + + // Check if player was in a rolecheck + if (grp) + { + LfgRoleCheckMap::iterator itRoleCheck = m_RoleChecks.find(GUID_LOPART(grp->GetGUID())); + if (itRoleCheck != m_RoleChecks.end()) + { + UpdateRoleCheck(grp); // No player to update role = LFG_ROLECHECK_ABORTED + return; + } + } + + // Check if player/group was in the queue + bool inQueue = false; + for (LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it) + inQueue |= it->second->RemoveFromQueue(guid); + + // Not in queue + if (!inQueue) + return; + + if (grp) + { + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + if (Player *plrg = itr->getSource()) + { + plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); + plrg->m_lookingForGroup.applyDungeons.clear(); + plrg->m_lookingForGroup.roles = 0; + } + } + else + { + plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); + plr->m_lookingForGroup.applyDungeons.clear(); + plr->m_lookingForGroup.roles = 0; + } +} + +/// +/// Update the Role check info with the player selected role. +/// +/// Group +/// Player +void LFGMgr::UpdateRoleCheck(Group *grp, Player *plr /* = NULL*/) +{ + assert(grp); + + uint32 rolecheckId = GUID_LOPART(grp->GetGUID()); + LfgRoleCheck *pRoleCheck = NULL; + LfgRolesMap check_roles; + LfgRoleCheckMap::iterator itRoleCheck = m_RoleChecks.find(rolecheckId); + bool newRoleCheck = itRoleCheck == m_RoleChecks.end(); + if (newRoleCheck) + { + if (!grp->IsLeader(plr->GetGUID())) + return; + + pRoleCheck = new LfgRoleCheck(); + pRoleCheck->cancelTime = time_t(time(NULL)) + LFG_TIME_ROLECHECK; + pRoleCheck->result = LFG_ROLECHECK_INITIALITING; + pRoleCheck->leader = plr->GetGUID(); + + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + if (Player *plrg = itr->getSource()) + pRoleCheck->roles[plrg->GetGUID()] = 0; + + pRoleCheck->dungeons = plr->m_lookingForGroup.applyDungeons; + } + else + pRoleCheck = itRoleCheck->second; + + LfgLockStatusMap *playersLockMap = NULL; + if (plr) + { + // Player selected no role. + if (plr->m_lookingForGroup.roles < ROLE_TANK) + pRoleCheck->result = LFG_ROLECHECK_NO_ROLE; + else + { + // Check if all players have selected a role + pRoleCheck->roles[plr->GetGUID()] = plr->m_lookingForGroup.roles; + uint8 size = 0; + for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end() && itRoles->second != ROLE_NONE; ++itRoles) + ++size; + + if (pRoleCheck->roles.size() == size) + { + // use temporal var to check roles, CheckGroupRoles modifies the roles + for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end(); ++itRoles) + check_roles[itRoles->first] = itRoles->second; + + if (!CheckGroupRoles(check_roles)) // Group is not posible + pRoleCheck->result = LFG_ROLECHECK_WRONG_ROLES; + else + { + // Check if we can find a dungeon for that group + pRoleCheck->result = LFG_ROLECHECK_FINISHED; + if (pRoleCheck->dungeons.size() > 1) + playersLockMap = GetPartyLockStatusDungeons(plr, &pRoleCheck->dungeons); + else + { + LfgDungeonSet::const_iterator it = pRoleCheck->dungeons.begin(); + LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(*it); + if (dungeon && dungeon->type == LFG_TYPE_RANDOM) + playersLockMap = GetPartyLockStatusDungeons(plr, m_DungeonsMap[*it]); + else + playersLockMap = GetPartyLockStatusDungeons(plr, &pRoleCheck->dungeons); + } + } + } + } + } + else + pRoleCheck->result = LFG_ROLECHECK_ABORTED; + + WorldSession *session; + WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + pRoleCheck->dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1)); + sLog.outDebug("SMSG_LFG_ROLE_CHECK_UPDATE"); + BuildLfgRoleCheck(data, pRoleCheck); + + Player *plrg = NULL; + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + plrg = itr->getSource(); + if (!plrg) + continue; + + session = plrg->GetSession(); + if (!newRoleCheck && plr) + session->SendLfgRoleChosen(plr->GetGUID(), plr->m_lookingForGroup.roles); + session->SendPacket(&data); + + switch(pRoleCheck->result) + { + case LFG_ROLECHECK_INITIALITING: + continue; + case LFG_ROLECHECK_FINISHED: + if (!playersLockMap) + { + session->SendLfgUpdateParty(LFG_UPDATETYPE_ADDED_TO_QUEUE); + } + else + { + if (grp->IsLeader(plrg->GetGUID())) + { + uint32 size = 0; + for (LfgLockStatusMap::const_iterator it = playersLockMap->begin(); it != playersLockMap->end(); ++it) + size += 8 + 4 + it->second->size() * (4 + 4); + WorldPacket data(SMSG_LFG_JOIN_RESULT, 4 + 4 + size); + sLog.outDebug("SMSG_LFG_JOIN_RESULT"); + data << uint32(LFG_JOIN_PARTY_NOT_MEET_REQS); // Check Result + data << uint32(0); // Check Value (always 0 when PartyNotMeetReqs + BuildPartyLockDungeonBlock(data, playersLockMap); + session->SendPacket(&data); + } + session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED); + plrg->m_lookingForGroup.applyDungeons.clear(); + plrg->m_lookingForGroup.roles = 0; + } + break; + default: + if (grp->IsLeader(plrg->GetGUID())) + session->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result); + session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED); + plrg->m_lookingForGroup.applyDungeons.clear(); + plrg->m_lookingForGroup.roles = 0; + break; + } + } + + if (pRoleCheck->result == LFG_ROLECHECK_FINISHED) + { + // Add qroup to queue + LfgQueueInfo *pqInfo; + uint8 groupType = 0; + uint8 tanks = LFG_TANKS_NEEDED; + uint8 healers = LFG_HEALERS_NEEDED; + uint8 dps = LFG_DPS_NEEDED; + for (LfgRolesMap::const_iterator it = check_roles.begin(); it != check_roles.end(); ++it) + { + if (it->second & ROLE_TANK) + --tanks; + else if (it->second & ROLE_HEALER) + --healers; + else + --dps; + } + uint64 guid = grp->GetGUID(); + m_update = false; + for (LfgDungeonSet::const_iterator it = pRoleCheck->dungeons.begin(); it != pRoleCheck->dungeons.end(); ++it) + { + groupType = GetDungeonGroupType(*it); + pqInfo = m_Queues[groupType] ? m_Queues[groupType]->GetQueueInfo(guid) : NULL; + // if exist we have already added the player with another dungeon sharing same GroupType + if (pqInfo) + continue; + pqInfo = new LfgQueueInfo(); + pqInfo->dungeonId = *it; + pqInfo->joinTime = time_t(time(NULL)); + pqInfo->tanks = tanks; + pqInfo->healers = healers; + pqInfo->dps = dps; + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + if (Player *plrg = itr->getSource()) + pqInfo->roles[plrg->GetGUID()] = plrg->m_lookingForGroup.roles; + } + if (!m_Queues[groupType]) + m_Queues[groupType] = new LFGQueue(); + m_Queues[groupType]->AddToQueue(guid, pqInfo); + } + m_update = true; + } + + if (pRoleCheck->result != LFG_ROLECHECK_INITIALITING) + { + delete pRoleCheck; + if (!newRoleCheck) + m_RoleChecks.erase(itRoleCheck); + } + else if (newRoleCheck) + m_RoleChecks[rolecheckId] = pRoleCheck; +} + +/// +/// Check if a group can be formed with the given group +/// +/// Map of roles +/// bool, will be used to remove ROLE_LEADER +/// bool +bool LFGMgr::CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag /*= true*/) +{ + if (!groles.size()) + return false; + + uint8 damage = 0; + uint8 tank = 0; + uint8 healer = 0; + uint64 tguid = 0; + uint64 hguid = 0; + uint64 dguid = 0; + uint64 guid = 0; + uint8 role = 0; + + if (removeLeaderFlag) + for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it) + it->second &= ~ROLE_LEADER; + + for (LfgRolesMap::const_iterator it = groles.begin(); it != groles.end(); ++it) + { + guid = it->first; + role = it->second; + + if (role == ROLE_NONE) + return false; + + if (role & ROLE_TANK) + { + if (!tank) + { + tguid = guid; + ++tank; + } + else + { + if (groles[tguid] == ROLE_TANK) + tguid = guid; + groles[tguid] -= ROLE_TANK; + return CheckGroupRoles(groles, false); + } + } + + if (role & ROLE_HEALER) + { + if (!healer) + { + hguid = guid; + ++healer; + } + else + { + if (groles[hguid] == ROLE_HEALER) + hguid = guid; + groles[hguid] -= ROLE_HEALER; + return CheckGroupRoles(groles, false); + } + } + + if (role & ROLE_DAMAGE) + { + if (damage < 3) + { + if (!damage) + dguid = guid; + ++damage; + } + else + { + if (groles[dguid] == ROLE_DAMAGE) + dguid = guid; + groles[dguid] -= ROLE_DAMAGE; + if (!CheckGroupRoles(groles, false)) + groles[dguid] += ROLE_DAMAGE; + else + return true; + } + } + } + return true; +} + + + +// --------------------------------------------------------------------------// +// Packet Functions +// --------------------------------------------------------------------------// + +/// +/// Build lfgRolecheck packet +/// +/// WorldPacket +/// Player +/// Player status in LFG system +void LFGMgr::BuildLfgRoleCheck(WorldPacket &data, LfgRoleCheck *pRoleCheck) +{ + assert(pRoleCheck); + + Player *plr; + uint8 roles; + + data << uint32(pRoleCheck->result); // Check result + data << uint8(pRoleCheck->result == LFG_ROLECHECK_INITIALITING); + data << uint8(pRoleCheck->dungeons.size()); // Number of dungeons + LFGDungeonEntry const *dungeon; + for (LfgDungeonSet::iterator it = pRoleCheck->dungeons.begin(); it != pRoleCheck->dungeons.end(); ++it) + { + dungeon = sLFGDungeonStore.LookupEntry(*it); // not null - been checked at join time + data << uint32(dungeon->Entry()); // Dungeon + } + + data << uint8(pRoleCheck->roles.size()); // Players in group + // Leader info MUST be sent 1st :S + roles = pRoleCheck->roles[pRoleCheck->leader]; + data << uint64(pRoleCheck->leader); // Guid + data << uint8(roles > 0); // Ready + data << uint32(roles); // Roles + plr = objmgr.GetPlayer(pRoleCheck->leader); + if (plr) + data << uint8(plr->getLevel()); // Level + else + data << uint8(0); + + for (LfgRolesMap::const_iterator itPlayers = pRoleCheck->roles.begin(); itPlayers != pRoleCheck->roles.end(); ++itPlayers) + { + if (itPlayers->first == pRoleCheck->leader) + continue; + + roles = itPlayers->second; + data << uint64(itPlayers->first); // Guid + data << uint8(roles > 0); // Ready + data << uint32(roles); // Roles + plr = objmgr.GetPlayer(pRoleCheck->leader); + if (plr) + data << uint8(plr->getLevel()); // Level + else + data << uint8(0); + } +} + +/// +/// Build and Send LFG lock player info and reward +/// +/// Player +void LFGMgr::SendLfgPlayerInfo(Player *plr) +{ + uint32 rsize = 0; + uint32 lsize = 0; + LfgDungeonSet *randomlist = GetRandomDungeons(plr->getLevel(), plr->GetSession()->Expansion()); + LfgLockStatusSet *lockSet = GetPlayerLockStatusDungeons(plr, m_DungeonsMap[LFG_ALL_DUNGEONS]); + if (randomlist) + rsize = randomlist->size(); + if (lockSet) + lsize = lockSet->size(); + + sLog.outDebug("SMSG_LFG_PLAYER_INFO"); + WorldPacket data(SMSG_LFG_PLAYER_INFO, 1 + rsize * (4 + 1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4) + 4 + lsize * (4 + 4)); + if (!randomlist) + data << uint8(0); + else + { + data << uint8(randomlist->size()); // Random Dungeon count + for (LfgDungeonSet::iterator it = randomlist->begin(); it != randomlist->end(); ++it) + { + data << uint32(*it); // Entry + BuildRewardBlock(data, *it, plr); + } + randomlist->clear(); + delete randomlist; + } + BuildPlayerLockDungeonBlock(data, lockSet); + plr->GetSession()->SendPacket(&data); +} + +/// +/// Build and Send LFG lock party info and reward +/// +/// Player +void LFGMgr::SendLfgPartyInfo(Player *plr) +{ + if (LfgLockStatusMap *lockMap = GetPartyLockStatusDungeons(plr, m_DungeonsMap[LFG_ALL_DUNGEONS])) + { + uint32 size = 0; + for (LfgLockStatusMap::const_iterator it = lockMap->begin(); it != lockMap->end(); ++it) + size += 8 + 4 + it->second->size() * (4 + 4); + sLog.outDebug("SMSG_LFG_PARTY_INFO"); + WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size); + BuildPartyLockDungeonBlock(data, lockMap); + plr->GetSession()->SendPacket(&data); + } +} + +/// +/// Build Reward packet structure for a given dungeon +/// +/// WorldPacket +/// Dungeon entry +/// Player +void LFGMgr::BuildRewardBlock(WorldPacket &data, uint32 dungeon, Player *plr) +{ + bool done = plr->m_lookingForGroup.isDungeonDone(dungeon); + LfgReward *reward = GetRandomDungeonReward(dungeon, done, plr->getLevel()); + + if (!reward) + return; + + data << uint8(done); + if (data.GetOpcode() == SMSG_LFG_PLAYER_REWARD) + data << uint32(reward->strangers); + data << uint32(reward->baseMoney); + data << uint32(reward->baseXP); + data << uint32(reward->variableMoney); + data << uint32(reward->variableXP); + data << uint8(reward->itemId != 0); + if (reward->itemId) + { + data << uint32(reward->itemId); + data << uint32(reward->displayId); + data << uint32(reward->stackCount); + } +} + +/// +/// Build Party Dungeon lock status packet +/// +/// WorldPacket +/// lock status map +void LFGMgr::BuildPartyLockDungeonBlock(WorldPacket &data, LfgLockStatusMap *lockMap) +{ + assert(lockMap); + + data << uint8(lockMap->size()); + + LfgLockStatusSet *lockSet; + uint64 guid; + for (LfgLockStatusMap::const_iterator it = lockMap->begin(); it != lockMap->end(); ++it) + { + guid = it->first; + lockSet = it->second; + if (!lockSet) + continue; + + data << uint64(guid); // Player guid + BuildPlayerLockDungeonBlock(data, lockSet); + } + lockMap->clear(); + delete lockMap; +} + +/// +/// Build Player Dungeon lock status packet +/// +/// WorldPacket +/// lock status list +void LFGMgr::BuildPlayerLockDungeonBlock(WorldPacket &data, LfgLockStatusSet *lockSet) +{ + assert(lockSet); + data << uint32(lockSet->size()); // Size of lock dungeons + for (LfgLockStatusSet::iterator it = lockSet->begin(); it != lockSet->end(); ++it) + { + data << uint32((*it)->dungeon); // Dungeon entry + type + data << uint32((*it)->lockstatus); // Lock status + delete (*it); + } + lockSet->clear(); + delete lockSet; +} + + + + +// --------------------------------------------------------------------------// +// Auxiliar Functions +// --------------------------------------------------------------------------// + +/// +/// Get all Group members list of dungeons that can't be done and reason +/// leader excluded as the list given is he list he can do +/// +/// Group +/// Dungeons to check +/// LfgLockStatusMap* +LfgLockStatusMap* LFGMgr::GetPartyLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons) +{ + assert(plr); + assert(dungeons); + Group *grp = plr->GetGroup(); + if (!grp) + return NULL; + + Player *plrg; + LfgLockStatusSet *dungeonSet = NULL; + LfgLockStatusMap *dungeonMap = new LfgLockStatusMap(); + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + plrg = itr->getSource(); + if (!plrg || plrg == plr) + continue; + + dungeonSet = GetPlayerLockStatusDungeons(plrg, dungeons); + if (dungeonSet) + (*dungeonMap)[plrg->GetGUID()] = dungeonSet; + } + + if (!dungeonMap->size()) + { + delete dungeonMap; + dungeonMap = NULL; + } + return dungeonMap; +} + +/// +/// Get list of dungeons player can't do and reasons +/// +/// Player +/// Dungeons to check +/// LfgLockStatusSet* +LfgLockStatusSet* LFGMgr::GetPlayerLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons) +{ + LfgLockStatusSet *list = new LfgLockStatusSet(); + LfgLockStatus *lockstatus = NULL; + LFGDungeonEntry const *dungeon; + LfgLockStatusType locktype; + uint8 level = plr->getLevel(); + uint8 expansion = plr->GetSession()->Expansion(); + + for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it) + { + dungeon = sLFGDungeonStore.LookupEntry(*it); + assert(dungeon); // Will never happen - We provide a list from sLFGDungeonStore + + locktype = LFG_LOCKSTATUS_OK; + if (dungeon->expansion > expansion) + locktype = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; + else if (dungeon->minlevel > level) + locktype = LFG_LOCKSTATUS_TOO_LOW_LEVEL; + else if (dungeon->maxlevel < level) + locktype = LFG_LOCKSTATUS_TOO_HIGH_LEVEL; + /* TODO - Use these types when needed... + else if () + locktype = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; + else if () + locktype = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; + else if () // Locked due to WG, closed by GM, done daily, etc + locktype = LFG_LOCKSTATUS_RAID_LOCKED; + else if () + locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; + else if () + locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; + else if () // Need list of instances and needed quest to enter + locktype = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; + else if () // Need list of instances and needed key to enter + locktype = LFG_LOCKSTATUS_MISSING_ITEM; + else if () // Need list of instances and needed season to open + locktype = LFG_LOCKSTATUS_NOT_IN_SEASON; + */ + + if (locktype != LFG_LOCKSTATUS_OK) + { + lockstatus = new LfgLockStatus(); + lockstatus->dungeon = dungeon->Entry(); + lockstatus->lockstatus = locktype; + list->insert(lockstatus); + } + } + if (!list->size()) + { + delete list; + list = NULL; + } + return list; +} + +/// +/// Get the dungeon list that can be done. +/// +/// LfgDungeonSet* +LfgDungeonSet* LFGMgr::GetAllDungeons() +{ + LfgDungeonSet *dungeons = new LfgDungeonSet(); + LFGDungeonEntry const *dungeon; + for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) + { + dungeon = sLFGDungeonStore.LookupEntry(i); + if (!dungeon || dungeon->type == LFG_TYPE_ZONE) + continue; + dungeons->insert(dungeon->ID); + } + if (!dungeons->size()) + { + delete dungeons; + return NULL; + } + else + return dungeons; +} + +/// +/// Get the dungeon list that can be done given a random dungeon entry. +/// +/// Random dungeon entry +/// LfgDungeonSet* +LfgDungeonSet* LFGMgr::GetDungeonsByRandom(uint32 randomdungeon) +{ + LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(randomdungeon); + if (!dungeon) + return NULL; + + uint32 grouptype = dungeon->grouptype; + LfgDungeonSet *random = new LfgDungeonSet(); + for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) + { + dungeon = sLFGDungeonStore.LookupEntry(i); + if (!dungeon || dungeon->type == LFG_TYPE_RANDOM || dungeon->grouptype != grouptype) + continue; + random->insert(dungeon->ID); + } + if (!random->size()) + { + delete random; + return NULL; + } + else + return random; +} + +/// +/// Get the random dungeon list that can be done at a certain level and expansion. +/// +/// Player level +/// Player account expansion +/// LfgDungeonSet* +LfgDungeonSet* LFGMgr::GetRandomDungeons(uint8 level, uint8 expansion) +{ + LfgDungeonSet *list = new LfgDungeonSet(); + LFGDungeonEntry const *dungeon; + for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) + { + dungeon = sLFGDungeonStore.LookupEntry(i); + if (dungeon && dungeon->expansion <= expansion && dungeon->type == LFG_TYPE_RANDOM && + dungeon->minlevel <= level && level <= dungeon->maxlevel) + list->insert(dungeon->Entry()); + } + return list; +} + +/// +/// Get the reward of a given random dungeon +/// +/// random dungeon id +/// Dungeon previously done +/// +LfgReward* LFGMgr::GetRandomDungeonReward(uint32 dungeon, bool done, uint8 level) +{ + uint8 index = 0; + switch((dungeon & 0x00FFFFFF)) // Get dungeon id from dungeon entry + { + case LFG_RANDOM_CLASSIC: + if (level < 15) + index = LFG_REWARD_LEVEL0; + else if (level < 24) + index = LFG_REWARD_LEVEL1; + else if (level < 35) + index = LFG_REWARD_LEVEL2; + else if (level < 46) + index = LFG_REWARD_LEVEL3; + else if (level < 56) + index = LFG_REWARD_LEVEL4; + else + index = LFG_REWARD_LEVEL5; + break; + case LFG_RANDOM_BC_NORMAL: + index = LFG_REWARD_BC_NORMAL; + break; + case LFG_RANDOM_BC_HEROIC: + index = LFG_REWARD_BC_HEROIC; + break; + case LFG_RANDOM_LK_NORMAL: + index = level == 80 ? LFG_REWARD_LK_NORMAL80 : LFG_REWARD_LK_NORMAL; + break; + case LFG_RANDOM_LK_HEROIC: + index = LFG_REWARD_LK_HEROIC; + break; + default: // This should never happen! + done = false; + index = LFG_REWARD_LEVEL0; + sLog.outError("LFGMgr::GetRandomDungeonReward: Dungeon %u is not random dungeon!", dungeon); + break; + } + return done ? m_RewardDoneList.at(index) : m_RewardList.at(index); +} + +/// +/// Given a Dungeon id returns the dungeon Group Type +/// +/// Dungeon id +/// uint8: GroupType +uint8 LFGMgr::GetDungeonGroupType(uint32 dungeonId) +{ + LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(dungeonId); + if (!dungeon) + return 0; + + return dungeon->grouptype; +} diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h new file mode 100644 index 00000000000..b19da4e3d00 --- /dev/null +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LFGMGR_H +#define _LFGMGR_H + +#include "Common.h" +#include "Policies/Singleton.h" +#include "Group.h" +#include "LFG.h" + +enum LFGenum +{ + LFG_TIME_ROLECHECK = 2*MINUTE, + LFG_TANKS_NEEDED = 1, + LFG_HEALERS_NEEDED = 1, + LFG_DPS_NEEDED = 3, + LFG_QUEUEUPDATE_INTERVAL = 15000, + LFG_SPELL_COOLDOWN = 71328, + LFG_SPELL_DESERTER = 71041, +}; + +enum LfgType +{ + LFG_TYPE_DUNGEON = 1, + LFG_TYPE_RAID = 2, + LFG_TYPE_QUEST = 3, + LFG_TYPE_ZONE = 4, + LFG_TYPE_HEROIC = 5, + LFG_TYPE_RANDOM = 6, +}; + +enum LfgGroupType +{ + LFG_GROUPTYPE_CLASSIC = 1, + LFG_GROUPTYPE_BC_NORMAL = 2, + LFG_GROUPTYPE_BC_HEROIC = 3, + LFG_GROUPTYPE_WTLK_NORMAL = 4, + LFG_GROUPTYPE_WTLK_HEROIC = 5, + LFG_GROUPTYPE_CLASSIC_RAID = 6, + LFG_GROUPTYPE_BC_RAID = 7, + LFG_GROUPTYPE_WTLK_RAID_10 = 8, + LFG_GROUPTYPE_WTLK_RAID_25 = 9, +}; + +enum LfgLockStatusType +{ + LFG_LOCKSTATUS_OK = 0, // Internal use only + LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION = 1, + LFG_LOCKSTATUS_TOO_LOW_LEVEL = 2, + LFG_LOCKSTATUS_TOO_HIGH_LEVEL = 3, + LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE = 4, + LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE = 5, + LFG_LOCKSTATUS_RAID_LOCKED = 6, + LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL = 1001, + LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL = 1002, + LFG_LOCKSTATUS_QUEST_NOT_COMPLETED = 1022, + LFG_LOCKSTATUS_MISSING_ITEM = 1025, + LFG_LOCKSTATUS_NOT_IN_SEASON = 1031, +}; + +enum LfgJoinResult +{ + LFG_JOIN_OK = 0, // Joined (no client msg) + LFG_JOIN_FAILED = 1, // RoleCheck Failed + LFG_JOIN_GROUPFULL = 2, // Your group is full + LFG_JOIN_UNK3 = 3, // No client reaction + LFG_JOIN_INTERNAL_ERROR = 4, // Internal LFG Error + LFG_JOIN_NOT_MEET_REQS = 5, // You do not meet the requirements for the chosen dungeons + LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons + LFG_JOIN_MIXED_RAID_DUNGEON = 7, // You cannot mix dungeons, raids, and random when picking dungeons + LFG_JOIN_MULTI_REALM = 8, // The dungeon you chose does not support players from multiple realms + LFG_JOIN_DISCONNECTED = 9, // One or more party members are pending invites or disconnected + LFG_JOIN_PARTY_INFO_FAILED = 10, // Could not retrieve information about some party members + LFG_JOIN_DUNGEON_INVALID = 11, // One or more dungeons was not valid + LFG_JOIN_DESERTER = 12, // You can not queue for dungeons until your deserter debuff wears off + LFG_JOIN_PARTY_DESERTER = 13, // One or more party members has a deserter debuff + LFG_JOIN_RANDOM_COOLDOWN = 14, // You can not queue for random dungeons while on random dungeon cooldown + LFG_JOIN_PARTY_RANDOM_COOLDOWN = 15, // One or more party members are on random dungeon cooldown + LFG_JOIN_TOO_MUCH_MEMBERS = 16, // You can not enter dungeons with more that 5 party members + LFG_JOIN_USING_BG_SYSTEM = 17, // You can not use the dungeon system while in BG or arenas + LFG_JOIN_FAILED2 = 18, // RoleCheck Failed +}; + +enum LfgRoleCheckResult +{ + LFG_ROLECHECK_FINISHED = 1, // Role check finished + LFG_ROLECHECK_INITIALITING = 2, // Role check begins + LFG_ROLECHECK_MISSING_ROLE = 3, // Someone didn't selected a role after 2 mins + LFG_ROLECHECK_WRONG_ROLES = 4, // Can't form a group with that role selection + LFG_ROLECHECK_ABORTED = 5, // Someone leave the group + LFG_ROLECHECK_NO_ROLE = 6, // Someone selected no role +}; + +enum LfgRandomDungeonEntries +{ + LFG_ALL_DUNGEONS = 0, + LFG_RANDOM_CLASSIC = 258, + LFG_RANDOM_BC_NORMAL = 259, + LFG_RANDOM_BC_HEROIC = 260, + LFG_RANDOM_LK_NORMAL = 261, + LFG_RANDOM_LK_HEROIC = 262, +}; + +enum LfgRewardEnums +{ + LFG_REWARD_LEVEL0 = 10, + LFG_REWARD_LEVEL1 = 0, + LFG_REWARD_LEVEL2 = 1, + LFG_REWARD_LEVEL3 = 2, + LFG_REWARD_LEVEL4 = 3, + LFG_REWARD_LEVEL5 = 4, + LFG_REWARD_BC_NORMAL = 5, + LFG_REWARD_BC_HEROIC = 6, + LFG_REWARD_LK_NORMAL = 7, + LFG_REWARD_LK_NORMAL80 = 7, + LFG_REWARD_LK_HEROIC = 8, + LFG_REWARD_DATA_SIZE = 10, +}; + +const uint32 RewardDungeonData[LFG_REWARD_DATA_SIZE+1][5] = +{ // XP, money, item, item display, count + {310, 3500, 51999, 56915, 1}, // Classic 15-23 + {470, 7000, 52000, 56915, 1}, // Classic 24-34 + {825, 13000, 52001, 56915, 1}, // Classic 35-45 + {12250, 16500, 52002, 56915, 1}, // Classic 46-55 + {14300, 18000, 52003, 56915, 1}, // Classic 56-60 + {1600, 62000, 52004, 56915, 1}, // BC Normal + {1900, 88000, 52005, 56915, 1}, // BC Heroic + {33100, 148000, 47241, 62232, 2}, // LK Normal + {0, 198600, 47241, 62232, 2}, // LK Normal - Level 80 + {0, 264600, 49426, 64062, 2}, // LK Heroic + {0, 0, 0, 0, 0}, // Classic - No level +}; + +const uint32 RewardDungeonDoneData[LFG_REWARD_DATA_SIZE][5] = +{ // XP, money, item, item display, count + {200, 1800, 51999, 56915, 1}, // Classic 15-23 + {310, 3500, 52000, 56915, 1}, // Classic 24-34 + {550, 6500, 52001, 56915, 1}, // Classic 35-45 + {8150, 8500, 52002, 56915, 1}, // Classic 46-55 + {9550, 9000, 52003, 56915, 1}, // Classic 56-60 + {1100, 31000, 52004, 56915, 1}, // BC Normal + {12650, 44000, 52005, 56915, 1}, // BC Heroic + {16550, 74000, 0, 0, 0}, // LK Normal + {0, 99300, 0, 0, 0}, // LK Normal - Level 80 + {0, 132300, 47241, 62232, 2}, // LK Heroic +}; + +// Dungeon and reason why player can't join +struct LfgLockStatus +{ + uint32 dungeon; + LfgLockStatusType lockstatus; +}; + +// Reward info +struct LfgReward +{ + uint32 strangers; + uint32 baseMoney; + uint32 baseXP; + uint32 variableMoney; + uint32 variableXP; + uint32 itemId; + uint32 displayId; + uint32 stackCount; +}; + +typedef std::set LfgLockStatusSet; +typedef std::vector LfgRewardList; +typedef std::map LfgLockStatusMap; +typedef std::map LfgDungeonMap; + +typedef std::map LfgAnswerMap; +typedef std::map LfgRolesMap; +typedef std::set LfgGuidSet; + +// Stores player or group queue info +struct LfgQueueInfo +{ + time_t joinTime; // Player queue join time (to calculate wait times) + uint32 dungeonId; // Selected Player/Group Dungeon + LfgRolesMap roles; // Selected Player Role/s + uint8 tanks; // Tanks needed + uint8 healers; // Healers needed + uint8 dps; // Dps needed +}; + +// Stores all rolecheck info of a group that wants to join LFG +struct LfgRoleCheck +{ + time_t cancelTime; + LfgRolesMap roles; + LfgRoleCheckResult result; + LfgDungeonSet dungeons; + uint64 leader; +}; + +typedef std::map LfgQueueInfoMap; +typedef std::map LfgRoleCheckMap; + +class LFGQueue +{ + public: + LFGQueue(); + ~LFGQueue(); + + void Update(); + void AddToQueue(uint64 guid, LfgQueueInfo *pqInfo); + bool RemoveFromQueue(uint64 guid); + LfgQueueInfo* GetQueueInfo(uint64 guid); + private: + LfgQueueInfoMap m_LfgQueue; + int32 avgWaitTime; + int32 waitTimeTanks; + int32 waitTimeHealer; + int32 waitTimeDps; +}; + +typedef std::map LFGQueueMap; + +class LFGMgr +{ +public: + LFGMgr(); + ~LFGMgr(); + + void InitLFG(); + void SendLfgPlayerInfo(Player *plr); + void SendLfgPartyInfo(Player *plr); + void Join(Player *plr); + void Leave(Player *plr, Group *grp = NULL); + void UpdateRoleCheck(Group *grp, Player *plr = NULL); + void Update(uint32 diff); + +private: + void BuildLfgRoleCheck(WorldPacket &data, LfgRoleCheck *pRoleCheck); + void BuildAvailableRandomDungeonList(WorldPacket &data, Player *plr); + void BuildRewardBlock(WorldPacket &data, uint32 dungeon, Player *plr); + void BuildPlayerLockDungeonBlock(WorldPacket &data, LfgLockStatusSet *lockSet); + void BuildPartyLockDungeonBlock(WorldPacket &data, LfgLockStatusMap *lockMap); + bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true); + + LfgLockStatusMap* GetPartyLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons); + LfgLockStatusSet* GetPlayerLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons); + LfgDungeonSet* GetRandomDungeons(uint8 level, uint8 expansion); + LfgDungeonSet* GetDungeonsByRandom(uint32 randomdungeon); + LfgDungeonSet* GetAllDungeons(); + LfgReward* GetRandomDungeonReward(uint32 dungeon, bool done, uint8 level); + uint8 GetDungeonGroupType(uint32 dungeon); + + LfgRewardList m_RewardList; + LfgRewardList m_RewardDoneList; + LfgDungeonMap m_DungeonsMap; + + LFGQueueMap m_Queues; + LfgRoleCheckMap m_RoleChecks; + uint32 m_QueueTimer; + bool m_update; +}; + +#define sLFGMgr Trinity::Singleton::Instance() +#endif diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp new file mode 100644 index 00000000000..510ea13e78b --- /dev/null +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Corpse.h" +#include "Player.h" +#include "UpdateMask.h" +#include "ObjectAccessor.h" +#include "Database/DatabaseEnv.h" +#include "Opcodes.h" +#include "GossipDef.h" +#include "World.h" + +Corpse::Corpse(CorpseType type) : WorldObject() +, m_type(type) +{ + m_objectType |= TYPEMASK_CORPSE; + m_objectTypeId = TYPEID_CORPSE; + + m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION); + + m_valuesCount = CORPSE_END; + + m_time = time(NULL); + + lootForBody = false; + + if (type != CORPSE_BONES) + m_isWorldObject = true; +} + +Corpse::~Corpse() +{ +} + +void Corpse::AddToWorld() +{ + ///- Register the corpse for guid lookup + if (!IsInWorld()) + ObjectAccessor::Instance().AddObject(this); + + Object::AddToWorld(); +} + +void Corpse::RemoveFromWorld() +{ + ///- Remove the corpse from the accessor + if (IsInWorld()) + ObjectAccessor::Instance().RemoveObject(this); + + Object::RemoveFromWorld(); +} + +bool Corpse::Create(uint32 guidlow, Map *map) +{ + SetMap(map); + Object::_Create(guidlow, 0, HIGHGUID_CORPSE); + return true; +} + +bool Corpse::Create(uint32 guidlow, Player *owner) +{ + ASSERT(owner); + + Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation()); + + if (!IsPositionValid()) + { + sLog.outError("Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + guidlow, owner->GetName(), owner->GetPositionX(), owner->GetPositionY()); + return false; + } + + //we need to assign owner's map for corpse + //in other way we will get a crash in Corpse::SaveToDB() + SetMap(owner->GetMap()); + + WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask()); + + SetFloatValue(OBJECT_FIELD_SCALE_X, 1); + SetUInt64Value(CORPSE_FIELD_OWNER, owner->GetGUID()); + + m_grid = Trinity::ComputeGridPair(GetPositionX(), GetPositionY()); + + return true; +} + +void Corpse::SaveToDB() +{ + // prevent DB data inconsistence problems and duplicates + CharacterDatabase.BeginTransaction(); + DeleteFromDB(); + + std::ostringstream ss; + ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance,phaseMask) VALUES (" + << GetGUIDLow() << ", " + << GUID_LOPART(GetOwnerGUID()) << ", " + << GetPositionX() << ", " + << GetPositionY() << ", " + << GetPositionZ() << ", " + << GetOrientation() << ", " + << GetZoneId() << ", " + << GetMapId() << ", '"; + for (uint16 i = 0; i < m_valuesCount; ++i) + ss << GetUInt32Value(i) << " "; + ss << "'," + << uint64(m_time) <<", " + << uint32(GetType()) << ", " + << int(GetInstanceId()) << ", " + << uint16(GetPhaseMask()) << ")"; // prevent out of range error + CharacterDatabase.Execute(ss.str().c_str()); + CharacterDatabase.CommitTransaction(); +} + +void Corpse::DeleteBonesFromWorld() +{ + assert(GetType() == CORPSE_BONES); + Corpse* corpse = ObjectAccessor::GetCorpse(*this, GetGUID()); + + if (!corpse) + { + sLog.outError("Bones %u not found in world.", GetGUIDLow()); + return; + } + + AddObjectToRemoveList(); +} + +void Corpse::DeleteFromDB() +{ + if (GetType() == CORPSE_BONES) + // only specific bones + CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%d'", GetGUIDLow()); + else + // all corpses (not bones) + CharacterDatabase.PExecute("DELETE FROM corpse WHERE player = '%d' AND corpse_type <> '0'", GUID_LOPART(GetOwnerGUID())); +} + +/* +bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId) +{ + bool external = (result != NULL); + if (!external) + // 0 1 2 3 4 5 6 7 8 9 + result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid); + + if (!result) + { + sLog.outError("Corpse (GUID: %u) not found in table `corpse`, can't load. ",guid); + return false; + } + + Field *fields = result->Fetch(); + + if (!LoadFromDB(guid, fields)) + { + if (!external) + delete result; + + return false; + } + + if (!external) + delete result; + + return true; +}*/ + +bool Corpse::LoadFromDB(uint32 guid, Field *fields) +{ + float positionX = fields[0].GetFloat(); + float positionY = fields[1].GetFloat(); + float positionZ = fields[2].GetFloat(); + float ort = fields[3].GetFloat(); + uint32 mapid = fields[4].GetUInt32(); + + Object::_Create(guid, 0, HIGHGUID_CORPSE); + + if (!LoadValues(fields[5].GetString())) + { + sLog.outError("Corpse #%d have broken data in `data` field. Can't be loaded.",guid); + return false; + } + + m_time = time_t(fields[6].GetUInt64()); + m_type = CorpseType(fields[7].GetUInt32()); + + if (m_type >= MAX_CORPSE_TYPE) + { + sLog.outError("Corpse (guidlow %d, owner %d) have wrong corpse type, not load.",GetGUIDLow(),GUID_LOPART(GetOwnerGUID())); + return false; + } + + if (m_type != CORPSE_BONES) + m_isWorldObject = true; + + uint32 instanceid = fields[8].GetUInt32(); + + uint32 phaseMask = fields[9].GetUInt32(); + + // overwrite possible wrong/corrupted guid + SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE)); + + // place + SetLocationInstanceId(instanceid); + SetLocationMapId(mapid); + SetPhaseMask(phaseMask, false); + Relocate(positionX, positionY, positionZ, ort); + + if (!IsPositionValid()) + { + sLog.outError("Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + GetGUIDLow(), GUID_LOPART(GetOwnerGUID()), GetPositionX(), GetPositionY()); + return false; + } + + m_grid = Trinity::ComputeGridPair(GetPositionX(), GetPositionY()); + + return true; +} + +bool Corpse::isVisibleForInState(Player const* u, bool inVisibleList) const +{ + return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u->m_seer, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false); +} + diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h new file mode 100644 index 00000000000..bab95e99d14 --- /dev/null +++ b/src/server/game/Entities/Corpse/Corpse.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_CORPSE_H +#define TRINITYCORE_CORPSE_H + +#include "Object.h" +#include "Database/DatabaseEnv.h" +#include "GridDefines.h" +#include "LootMgr.h" + +enum CorpseType +{ + CORPSE_BONES = 0, + CORPSE_RESURRECTABLE_PVE = 1, + CORPSE_RESURRECTABLE_PVP = 2 +}; +#define MAX_CORPSE_TYPE 3 + +// Value equal client resurrection dialog show radius. +#define CORPSE_RECLAIM_RADIUS 39 + +enum CorpseFlags +{ + CORPSE_FLAG_NONE = 0x00, + CORPSE_FLAG_BONES = 0x01, + CORPSE_FLAG_UNK1 = 0x02, + CORPSE_FLAG_UNK2 = 0x04, + CORPSE_FLAG_HIDE_HELM = 0x08, + CORPSE_FLAG_HIDE_CLOAK = 0x10, + CORPSE_FLAG_LOOTABLE = 0x20 +}; + +class Corpse : public WorldObject, public GridObject +{ + public: + explicit Corpse(CorpseType type = CORPSE_BONES); + ~Corpse(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create(uint32 guidlow, Map *map); + bool Create(uint32 guidlow, Player *owner); + + void SaveToDB(); + //bool LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId); + bool LoadFromDB(uint32 guid, Field *fields); + + void DeleteBonesFromWorld(); + void DeleteFromDB(); + + uint64 const& GetOwnerGUID() const { return GetUInt64Value(CORPSE_FIELD_OWNER); } + + time_t const& GetGhostTime() const { return m_time; } + void ResetGhostTime() { m_time = time(NULL); } + CorpseType GetType() const { return m_type; } + + GridPair const& GetGrid() const { return m_grid; } + void SetGrid(GridPair const& grid) { m_grid = grid; } + + bool isVisibleForInState(Player const* u, bool inVisibleList) const; + + Loot loot; // remove insignia ONLY at BG + Player* lootRecipient; + bool lootForBody; + + void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } + void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } + void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); } + void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); } + void YellToZone(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYellToZone(textId,language,TargetGuid); } + + private: + CorpseType m_type; + time_t m_time; + GridPair m_grid; // gride for corpse position for fast search +}; +#endif + diff --git a/src/server/game/Entities/Creature/NPCHandler.cpp b/src/server/game/Entities/Creature/NPCHandler.cpp deleted file mode 100644 index 4e73fb381af..00000000000 --- a/src/server/game/Entities/Creature/NPCHandler.cpp +++ /dev/null @@ -1,869 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Language.h" -#include "Database/DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "Player.h" -#include "GossipDef.h" -#include "UpdateMask.h" -#include "ObjectAccessor.h" -#include "Creature.h" -#include "Pet.h" -#include "BattleGroundMgr.h" -#include "BattleGround.h" -#include "Guild.h" -#include "ScriptMgr.h" - -void WorldSession::HandleTabardVendorActivateOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TABARDDESIGNER); - if (!unit) - { - sLog.outDebug("WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendTabardVendorActivate(guid); -} - -void WorldSession::SendTabardVendorActivate(uint64 guid) -{ - WorldPacket data(MSG_TABARDVENDOR_ACTIVATE, 8); - data << guid; - SendPacket(&data); -} - -void WorldSession::HandleBankerActivateOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - sLog.outDebug("WORLD: Received CMSG_BANKER_ACTIVATE"); - - recv_data >> guid; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_BANKER); - if (!unit) - { - sLog.outDebug("WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendShowBank(guid); -} - -void WorldSession::SendShowBank(uint64 guid) -{ - WorldPacket data(SMSG_SHOW_BANK, 8); - data << guid; - SendPacket(&data); -} - -void WorldSession::HandleTrainerListOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - recv_data >> guid; - SendTrainerList(guid); -} - -void WorldSession::SendTrainerList(uint64 guid) -{ - std::string str = GetTrinityString(LANG_NPC_TAINER_HELLO); - SendTrainerList(guid, str); -} - -void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle) -{ - sLog.outDebug("WORLD: SendTrainerList"); - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TRAINER); - if (!unit) - { - sLog.outDebug("WORLD: SendTrainerList - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // trainer list loaded at check; - if (!unit->isCanTrainingOf(_player,true)) - return; - - CreatureInfo const *ci = unit->GetCreatureInfo(); - - if (!ci) - { - sLog.outDebug("WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!",GUID_LOPART(guid)); - return; - } - - TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); - if (!trainer_spells) - { - sLog.outDebug("WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", - GUID_LOPART(guid), unit->GetEntry()); - return; - } - - WorldPacket data(SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1); - data << guid; - data << uint32(trainer_spells->trainerType); - - size_t count_pos = data.wpos(); - data << uint32(trainer_spells->spellList.size()); - - // reputation discount - float fDiscountMod = _player->GetReputationPriceDiscount(unit); - bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; - - uint32 count = 0; - for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) - { - TrainerSpell const* tSpell = &itr->second; - - bool valid = true; - bool primary_prof_first_rank = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS ; ++i) - { - if (!tSpell->learnedSpell[i]) - continue; - if (!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell[i])) - { - valid = false; - break; - } - if (spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell[i])) - primary_prof_first_rank = true; - } - if (!valid) - continue; - - TrainerSpellState state = _player->GetTrainerSpellState(tSpell); - - data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) - data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); - data << uint32(floor(tSpell->spellCost * fDiscountMod)); - - data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0); - // primary prof. learn confirmation dialog - data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state - data << uint8(tSpell->reqLevel); - data << uint32(tSpell->reqSkill); - data << uint32(tSpell->reqSkillValue); - //prev + req or req + 0 - uint8 maxReq = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS ; ++i) - { - if (!tSpell->learnedSpell[i]) - continue; - if (SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learnedSpell[i])) - { - if (chain_node->prev) - { - data << uint32(chain_node->prev); - ++maxReq; - } - } - if (maxReq == 3) - break; - SpellsRequiringSpellMapBounds spellsRequired = spellmgr.GetSpellsRequiredForSpellBounds(tSpell->learnedSpell[i]); - for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2) - { - data << uint32(itr2->second); - ++maxReq; - } - if (maxReq == 3) - break; - } - while (maxReq < 3) - { - data << uint32(0); - ++maxReq; - } - - ++count; - } - - data << strTitle; - - data.put(count_pos,count); - SendPacket(&data); -} - -void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recv_data) -{ - uint64 guid; - uint32 spellId = 0; - - recv_data >> guid >> spellId; - sLog.outDebug("WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId); - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); - if (!unit) - { - sLog.outDebug("WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (!unit->isCanTrainingOf(_player,true)) - return; - - // check present spell in trainer spell list - TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); - if (!trainer_spells) - return; - - // not found, cheat? - TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); - if (!trainer_spell) - return; - - // can't be learn, cheat? Or double learn with lags... - if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN) - return; - - // apply reputation discount - uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); - - // check money requirement - if (_player->GetMoney() < nSpellCost) - return; - - _player->ModifyMoney(-int32(nSpellCost)); - - WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer - data << uint64(guid); - data << uint32(0xB3); // index from SpellVisualKit.dbc - SendPacket(&data); - - data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player - data << uint64(_player->GetGUID()); - data << uint32(0x016A); // index from SpellVisualKit.dbc - SendPacket(&data); - - // learn explicitly or cast explicitly - if (trainer_spell->IsCastable()) - _player->CastSpell(_player,trainer_spell->spell,true); - else - _player->learnSpell(spellId, false); - - data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); - data << uint64(guid); - data << uint32(spellId); // should be same as in packet from client - SendPacket(&data); -} - -void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_GOSSIP_HELLO"); - - uint64 guid; - recv_data >> guid; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) - { - sLog.outDebug("WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); - // remove fake death - //if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - // GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider()) - { - unit->StopMoving(); - } - - // If spiritguide, no need for gossip menu, just put player into resurrect queue - if (unit->isSpiritGuide()) - { - BattleGround *bg = _player->GetBattleGround(); - if (bg) - { - bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID()); - sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID()); - return; - } - } - - if (!sScriptMgr.GossipHello(_player, unit)) - { -// _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID()); - _player->PrepareGossipMenu(unit, unit->GetCreatureInfo()->GossipMenuId, true); - _player->SendPreparedGossip(unit); - } -} - -/*void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION"); - - uint32 option; - uint32 unk; - uint64 guid; - std::string code = ""; - - recv_data >> guid >> unk >> option; - - if (_player->PlayerTalkClass->GossipOptionCoded(option)) - { - sLog.outDebug("reading string"); - recv_data >> code; - sLog.outDebug("string read: %s", code.c_str()); - } - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) - { - sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (!code.empty()) - { - if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str())) - unit->OnGossipSelect (_player, option); - } - else - { - if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option))) - unit->OnGossipSelect (_player, option); - } -}*/ - -void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE"); - - uint64 guid; - - recv_data >> guid; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_SPIRITHEALER); - if (!unit) - { - sLog.outDebug("WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendSpiritResurrect(); -} - -void WorldSession::SendSpiritResurrect() -{ - _player->ResurrectPlayer(0.5f, true); - - _player->DurabilityLossAll(0.25f,true); - - // get corpse nearest graveyard - WorldSafeLocsEntry const *corpseGrave = NULL; - Corpse *corpse = _player->GetCorpse(); - if (corpse) - corpseGrave = objmgr.GetClosestGraveYard( - corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam()); - - // now can spawn bones - _player->SpawnCorpseBones(); - - // teleport to nearest from corpse graveyard, if different from nearest to player ghost - if (corpseGrave) - { - WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard( - _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam()); - - if (corpseGrave != ghostGrave) - _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation()); - // or update at original position - else - _player->UpdateObjectVisibility(); - } - // or update at original position - else - _player->UpdateObjectVisibility(); -} - -void WorldSession::HandleBinderActivateOpcode(WorldPacket & recv_data) -{ - uint64 npcGUID; - recv_data >> npcGUID; - - if (!GetPlayer()->IsInWorld() || !GetPlayer()->isAlive()) - return; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID,UNIT_NPC_FLAG_INNKEEPER); - if (!unit) - { - sLog.outDebug("WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - SendBindPoint(unit); -} - -void WorldSession::SendBindPoint(Creature *npc) -{ - // prevent set homebind to instances in any case - if (GetPlayer()->GetMap()->Instanceable()) - return; - - uint32 bindspell = 3286; - - // update sql homebind - CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", - _player->GetMapId(), _player->GetAreaId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow()); - _player->m_homebindMapId = _player->GetMapId(); - _player->m_homebindAreaId = _player->GetAreaId(); - _player->m_homebindX = _player->GetPositionX(); - _player->m_homebindY = _player->GetPositionY(); - _player->m_homebindZ = _player->GetPositionZ(); - - // send spell for homebinding (3286) - npc->CastSpell(_player, bindspell, true); - - WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, (8+4)); - data << uint64(npc->GetGUID()); - data << uint32(bindspell); - SendPacket(&data); - - _player->PlayerTalkClass->CloseGossip(); -} - -void WorldSession::HandleListStabledPetsOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS"); - uint64 npcGUID; - - recv_data >> npcGUID; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); - if (!unit) - { - sLog.outDebug("WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // remove mounts this fix bug where getting pet from stable while mounted deletes pet. - if (GetPlayer()->IsMounted()) - GetPlayer()->RemoveAurasByType(SPELL_AURA_MOUNTED); - - SendStablePet(npcGUID); -} - -void WorldSession::SendStablePet(uint64 guid) -{ - sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send."); - - WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size - data << uint64 (guid); - - Pet *pet = _player->GetPet(); - - size_t wpos = data.wpos(); - data << uint8(0); // place holder for slot show number - - data << uint8(GetPlayer()->m_stableSlots); - - uint8 num = 0; // counter for place holder - - // not let move dead pet in slot - if (pet && pet->isAlive() && pet->getPetType() == HUNTER_PET) - { - data << uint32(pet->GetCharmInfo()->GetPetNumber()); - data << uint32(pet->GetEntry()); - data << uint32(pet->getLevel()); - data << pet->GetName(); // petname - data << uint8(1); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show) - ++num; - } - - // 0 1 2 3 4 - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT owner, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot", - _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); - - if (result) - { - do - { - Field *fields = result->Fetch(); - - data << uint32(fields[1].GetUInt32()); // petnumber - data << uint32(fields[2].GetUInt32()); // creature entry - data << uint32(fields[3].GetUInt32()); // level - data << fields[4].GetString(); // name - data << uint8(2); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show) - - ++num; - }while (result->NextRow()); - } - - data.put(wpos, num); // set real data to placeholder - SendPacket(&data); -} - -void WorldSession::HandleStablePet(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Recv CMSG_STABLE_PET"); - uint64 npcGUID; - - recv_data >> npcGUID; - - if (!GetPlayer()->isAlive()) - return; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); - if (!unit) - { - sLog.outDebug("WORLD: HandleStablePet - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Pet *pet = _player->GetPet(); - - // can't place in stable dead pet - if (!pet||!pet->isAlive()||pet->getPetType() != HUNTER_PET) - { - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(0x06); - SendPacket(&data); - return; - } - - uint32 free_slot = 1; - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot ", - _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); - if (result) - { - do - { - Field *fields = result->Fetch(); - - uint32 slot = fields[1].GetUInt32(); - - // slots ordered in query, and if not equal then free - if (slot != free_slot) - break; - - // this slot not free, skip - ++free_slot; - }while (result->NextRow()); - } - - WorldPacket data(SMSG_STABLE_RESULT, 1); - if (free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots) - { - _player->RemovePet(pet,PetSaveMode(free_slot)); - data << uint8(0x08); - } - else - data << uint8(0x06); - - SendPacket(&data); -} - -void WorldSession::HandleUnstablePet(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET."); - uint64 npcGUID; - uint32 petnumber; - - recv_data >> npcGUID >> petnumber; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); - if (!unit) - { - sLog.outDebug("WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - uint32 creature_id = 0; - - { - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot >='%u' AND slot <= '%u'", - _player->GetGUIDLow(),petnumber,PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); - if (result) - { - Field *fields = result->Fetch(); - creature_id = fields[0].GetUInt32(); - } - } - - if (!creature_id) - { - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(0x06); - SendPacket(&data); - return; - } - - CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(creature_id); - if (!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets())) - { - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(0x06); - SendPacket(&data); - return; - } - - Pet* pet = _player->GetPet(); - if (pet && pet->isAlive()) - { - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(0x06); - SendPacket(&data); - return; - } - - // delete dead pet - if (pet) - _player->RemovePet(pet,PET_SAVE_AS_DELETED); - - Pet *newpet = new Pet(_player, HUNTER_PET); - if (!newpet->LoadPetFromDB(_player,creature_id,petnumber)) - { - delete newpet; - newpet = NULL; - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(0x06); - SendPacket(&data); - return; - } - - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(0x09); - SendPacket(&data); -} - -void WorldSession::HandleBuyStableSlot(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT."); - uint64 npcGUID; - - recv_data >> npcGUID; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); - if (!unit) - { - sLog.outDebug("WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - WorldPacket data(SMSG_STABLE_RESULT, 200); - - if (GetPlayer()->m_stableSlots < MAX_PET_STABLES) - { - StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1); - if (_player->GetMoney() >= SlotPrice->Price) - { - ++GetPlayer()->m_stableSlots; - _player->ModifyMoney(-int32(SlotPrice->Price)); - data << uint8(0x0A); // success buy - } - else - data << uint8(0x06); - } - else - data << uint8(0x06); - - SendPacket(&data); -} - -void WorldSession::HandleStableRevivePet(WorldPacket &/* recv_data */) -{ - sLog.outDebug("HandleStableRevivePet: Not implemented"); -} - -void WorldSession::HandleStableSwapPet(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET."); - uint64 npcGUID; - uint32 pet_number; - - recv_data >> npcGUID >> pet_number; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); - if (!unit) - { - sLog.outDebug("WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size - - Pet* pet = _player->GetPet(); - - if (!pet || pet->getPetType() != HUNTER_PET) - return; - - // find swapped pet slot in stable - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'", - _player->GetGUIDLow(),pet_number); - if (!result) - return; - - Field *fields = result->Fetch(); - - uint32 slot = fields[0].GetUInt32(); - uint32 creature_id = fields[1].GetUInt32(); - - if (!creature_id) - { - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(0x06); - SendPacket(&data); - return; - } - - CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(creature_id); - if (!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets())) - { - WorldPacket data(SMSG_STABLE_RESULT, 1); - data << uint8(0x06); - SendPacket(&data); - return; - } - - // move alive pet to slot or delete dead pet - _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED); - - // summon unstabled pet - Pet *newpet = new Pet(_player); - if (!newpet->LoadPetFromDB(_player,creature_id,pet_number)) - { - delete newpet; - data << uint8(0x06); - } - else - data << uint8(0x09); - - SendPacket(&data); -} - -void WorldSession::HandleRepairItemOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_REPAIR_ITEM"); - - uint64 npcGUID, itemGUID; - uint8 guildBank; // new in 2.3.2, bool that means from guild bank money - - recv_data >> npcGUID >> itemGUID >> guildBank; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_REPAIR); - if (!unit) - { - sLog.outDebug("WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // reputation discount - float discountMod = _player->GetReputationPriceDiscount(unit); - - uint32 TotalCost = 0; - if (itemGUID) - { - sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID)); - - Item* item = _player->GetItemByGuid(itemGUID); - - if (item) - TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false); - } - else - { - sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID)); - - TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false); - } - if (guildBank) - { - uint32 GuildId = _player->GetGuildId(); - if (!GuildId) - return; - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost); - pGuild->SendMoneyInfo(this, _player->GetGUIDLow()); - } -} - diff --git a/src/server/game/Entities/Creature/NPCHandler.h b/src/server/game/Entities/Creature/NPCHandler.h deleted file mode 100644 index 98e2fd218d3..00000000000 --- a/src/server/game/Entities/Creature/NPCHandler.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __NPCHANDLER_H -#define __NPCHANDLER_H - -// 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 -#if defined(__GNUC__) -#pragma pack(1) -#else -#pragma pack(push,1) -#endif - -struct PageText -{ - uint32 Page_ID; - char * Text; - - uint32 Next_Page; -}; - -// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform -#if defined(__GNUC__) -#pragma pack() -#else -#pragma pack(pop) -#endif - -struct QEmote -{ - uint32 _Emote; - uint32 _Delay; -}; - -struct GossipTextOption -{ - std::string Text_0; - std::string Text_1; - uint32 Language; - float Probability; - QEmote Emotes[3]; -}; - -struct GossipText -{ - GossipTextOption Options[8]; -}; - -struct PageTextLocale -{ - std::vector Text; -}; - -struct NpcTextLocale -{ - NpcTextLocale() { Text_0.resize(8); Text_1.resize(8); } - - std::vector > Text_0; - std::vector > Text_1; -}; -#endif - diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp new file mode 100644 index 00000000000..48179190a6e --- /dev/null +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "UpdateMask.h" +#include "Opcodes.h" +#include "World.h" +#include "ObjectAccessor.h" +#include "Database/DatabaseEnv.h" +#include "GridNotifiers.h" +#include "CellImpl.h" +#include "GridNotifiersImpl.h" + +DynamicObject::DynamicObject() : WorldObject() +{ + m_objectType |= TYPEMASK_DYNAMICOBJECT; + m_objectTypeId = TYPEID_DYNAMICOBJECT; + + m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION); + + m_valuesCount = DYNAMICOBJECT_END; + + m_aura = 0; + m_duration = 0; +} + +void DynamicObject::AddToWorld() +{ + ///- Register the dynamicObject for guid lookup + if (!IsInWorld()) + { + ObjectAccessor::Instance().AddObject(this); + WorldObject::AddToWorld(); + } +} + +void DynamicObject::RemoveFromWorld() +{ + ///- Remove the dynamicObject from the accessor + if (IsInWorld()) + { + if (m_isWorldObject) + { + if (Unit *caster = GetCaster()) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + caster->ToPlayer()->SetViewpoint(this, false); + } + else + { + sLog.outCrash("DynamicObject::RemoveFromWorld cannot find viewpoint owner"); + } + } + WorldObject::RemoveFromWorld(); + ObjectAccessor::Instance().RemoveObject(this); + } +} + +bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, const Position &pos, float radius, bool active) +{ + SetMap(caster->GetMap()); + Relocate(pos); + if (!IsPositionValid()) + { + sLog.outError("DynamicObject (spell %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",spellId,GetPositionX(),GetPositionY()); + return false; + } + + WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask()); + + SetEntry(spellId); + SetFloatValue(OBJECT_FIELD_SCALE_X, 1); + SetUInt64Value(DYNAMICOBJECT_CASTER, caster->GetGUID()); + + // The lower word of DYNAMICOBJECT_BYTES must be 0x0001. This value means that the visual radius will be overriden + // by client for most of the "ground patch" visual effect spells and a few "skyfall" ones like Hurricane. + // If any other value is used, the client will _always_ use the radius provided in DYNAMICOBJECT_RADIUS, but + // precompensation is necessary (eg radius *= 2) for many spells. Anyway, blizz sends 0x0001 for all the spells + // I saw sniffed... + SetUInt32Value(DYNAMICOBJECT_BYTES, 0x00000001); + SetUInt32Value(DYNAMICOBJECT_SPELLID, spellId); + SetFloatValue(DYNAMICOBJECT_RADIUS, radius); + SetUInt32Value(DYNAMICOBJECT_CASTTIME, getMSTime()); + + m_isWorldObject = active; + return true; +} + +Unit* DynamicObject::GetCaster() const +{ + // can be not found in some cases + return ObjectAccessor::GetUnit(*this, GetCasterGUID()); +} + +void DynamicObject::Update(uint32 p_time) +{ + // caster can be not in world at time dynamic object update, but dynamic object not yet deleted in Unit destructor + Unit* caster = GetCaster(); + if (!caster) + { + Delete(); + return; + } + + bool expired = false; + + if (m_aura) + { + if (!m_aura->IsRemoved()) + m_aura->UpdateOwner(p_time, this); + + // m_aura may be set to null in Unit::RemoveGameObject call + if (m_aura && (m_aura->IsRemoved() || m_aura->IsExpired())) + expired = true; + } + else + { + if (GetDuration() > int32(p_time)) + m_duration -= p_time; + else + expired = true; + } + + if (expired) + { + caster->RemoveDynObjectWithGUID(GetGUID()); + Delete(); + } +} + +void DynamicObject::Delete() +{ + if (m_aura) + { + // dynObj may be removed in Aura::Remove - we cannot delete there + // so recheck aura here + if (!m_aura->IsRemoved()) + m_aura->_Remove(AURA_REMOVE_BY_DEFAULT); + delete m_aura; + m_aura = NULL; + } + SendObjectDeSpawnAnim(GetGUID()); + RemoveFromWorld(); + AddObjectToRemoveList(); +} + +int32 DynamicObject::GetDuration() const +{ + if (!m_aura) + return m_duration; + else + return m_aura->GetDuration(); +} + +void DynamicObject::SetDuration(int32 newDuration) +{ + if (!m_aura) + m_duration = newDuration; + else + m_aura->SetDuration(newDuration); +} + +void DynamicObject::Delay(int32 delaytime) +{ + SetDuration(GetDuration() - delaytime); +} + +bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const +{ + return IsInWorld() && u->IsInWorld() + && (IsWithinDistInMap(u->m_seer,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false)); +} diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h new file mode 100644 index 00000000000..9a70407fd2d --- /dev/null +++ b/src/server/game/Entities/DynamicObject/DynamicObject.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_DYNAMICOBJECT_H +#define TRINITYCORE_DYNAMICOBJECT_H + +#include "Object.h" + +class Unit; +class Aura; +struct SpellEntry; + +class DynamicObject : public WorldObject, public GridObject +{ + public: + explicit DynamicObject(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create(uint32 guidlow, Unit *caster, uint32 spellId, const Position &pos, float radius, bool active); + void Update(uint32 p_time); + void Delete(); + void SetDuration(int32 newDuration); + int32 GetDuration() const; + void SetAura(Aura * aura) {assert (!m_aura && aura); m_aura = aura;} + void Delay(int32 delaytime); + uint32 GetSpellId() const { return GetUInt32Value(DYNAMICOBJECT_SPELLID); } + uint64 GetCasterGUID() const { return GetUInt64Value(DYNAMICOBJECT_CASTER); } + float GetRadius() const { return GetFloatValue(DYNAMICOBJECT_RADIUS); } + Unit* GetCaster() const; + bool isVisibleForInState(Player const* u, bool inVisibleList) const; + + void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } + void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } + void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); } + void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); } + void YellToZone(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYellToZone(textId,language,TargetGuid); } + + protected: + int32 m_duration; // for non-aura dynobjects + Aura * m_aura; +}; +#endif diff --git a/src/server/game/Entities/Item/Bag.cpp b/src/server/game/Entities/Item/Bag.cpp deleted file mode 100644 index aa78126b198..00000000000 --- a/src/server/game/Entities/Item/Bag.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "ObjectMgr.h" -#include "Database/DatabaseEnv.h" - -#include "Bag.h" -#include "Log.h" -#include "UpdateData.h" - -Bag::Bag(): Item() -{ - m_objectType |= TYPEMASK_CONTAINER; - m_objectTypeId = TYPEID_CONTAINER; - - m_valuesCount = CONTAINER_END; - - memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); -} - -Bag::~Bag() -{ - for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) - if (Item *item = m_bagslot[i]) - { - if (item->IsInWorld()) - { - sLog.outCrash("Item %u (slot %u, bag slot %u) in bag %u (slot %u, bag slot %u, m_bagslot %u) is to be deleted but is still in world.", - item->GetEntry(), (uint32)item->GetSlot(), (uint32)item->GetBagSlot(), - GetEntry(), (uint32)GetSlot(), (uint32)GetBagSlot(), (uint32)i); - item->RemoveFromWorld(); - } - delete m_bagslot[i]; - } -} - -void Bag::AddToWorld() -{ - Item::AddToWorld(); - - for (uint32 i = 0; i < GetBagSize(); ++i) - if (m_bagslot[i]) - m_bagslot[i]->AddToWorld(); -} - -void Bag::RemoveFromWorld() -{ - for (uint32 i = 0; i < GetBagSize(); ++i) - if (m_bagslot[i]) - m_bagslot[i]->RemoveFromWorld(); - - Item::RemoveFromWorld(); -} - -bool Bag::Create(uint32 guidlow, uint32 itemid, Player const* owner) -{ - ItemPrototype const * itemProto = objmgr.GetItemPrototype(itemid); - - if (!itemProto || itemProto->ContainerSlots > MAX_BAG_SIZE) - return false; - - Object::_Create(guidlow, 0, HIGHGUID_CONTAINER); - - SetEntry(itemid); - SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); - - SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0); - SetUInt64Value(ITEM_FIELD_CONTAINED, owner ? owner->GetGUID() : 0); - - SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability); - SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability); - SetUInt32Value(ITEM_FIELD_FLAGS, itemProto->Flags); - SetUInt32Value(ITEM_FIELD_STACK_COUNT, 1); - - // Setting the number of Slots the Container has - SetUInt32Value(CONTAINER_FIELD_NUM_SLOTS, itemProto->ContainerSlots); - - // Cleaning 20 slots - for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) - { - SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0); - m_bagslot[i] = NULL; - } - - return true; -} - -void Bag::SaveToDB() -{ - Item::SaveToDB(); -} - -bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result) -{ - if (!Item::LoadFromDB(guid, owner_guid, result)) - return false; - - // cleanup bag content related item value fields (its will be filled correctly from `character_inventory`) - for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) - { - SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0); - if (m_bagslot[i]) - { - delete m_bagslot[i]; - m_bagslot[i] = NULL; - } - } - - return true; -} - -void Bag::DeleteFromDB() -{ - for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) - if (m_bagslot[i]) - m_bagslot[i]->DeleteFromDB(); - - Item::DeleteFromDB(); -} - -uint32 Bag::GetFreeSlots() const -{ - uint32 slots = 0; - for (uint32 i=0; i < GetBagSize(); ++i) - if (!m_bagslot[i]) - ++slots; - - return slots; -} - -void Bag::RemoveItem(uint8 slot, bool /*update*/) -{ - assert(slot < MAX_BAG_SIZE); - - if (m_bagslot[slot]) - m_bagslot[slot]->SetContainer(NULL); - - m_bagslot[slot] = NULL; - SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (slot * 2), 0); -} - -void Bag::StoreItem(uint8 slot, Item *pItem, bool /*update*/) -{ - assert(slot < MAX_BAG_SIZE); - - if (pItem && pItem->GetGUID() != this->GetGUID()) - { - m_bagslot[slot] = pItem; - SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (slot * 2), pItem->GetGUID()); - pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, GetGUID()); - pItem->SetUInt64Value(ITEM_FIELD_OWNER, GetOwnerGUID()); - pItem->SetContainer(this); - pItem->SetSlot(slot); - } -} - -void Bag::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const -{ - Item::BuildCreateUpdateBlockForPlayer(data, target); - - for (uint32 i = 0; i < GetBagSize(); ++i) - if (m_bagslot[i]) - m_bagslot[i]->BuildCreateUpdateBlockForPlayer(data, target); -} - -// If the bag is empty returns true -bool Bag::IsEmpty() const -{ - for (uint32 i = 0; i < GetBagSize(); ++i) - if (m_bagslot[i]) - return false; - - return true; -} - -uint32 Bag::GetItemCount(uint32 item, Item* eItem) const -{ - Item *pItem; - uint32 count = 0; - for (uint32 i=0; i < GetBagSize(); ++i) - { - pItem = m_bagslot[i]; - if (pItem && pItem != eItem && pItem->GetEntry() == item) - count += pItem->GetCount(); - } - - if (eItem && eItem->GetProto()->GemProperties) - { - for (uint32 i=0; i < GetBagSize(); ++i) - { - pItem = m_bagslot[i]; - if (pItem && pItem != eItem && pItem->GetProto()->Socket[0].Color) - count += pItem->GetGemCountWithID(item); - } - } - - return count; -} - -uint8 Bag::GetSlotByItemGUID(uint64 guid) const -{ - for (uint32 i = 0; i < GetBagSize(); ++i) - if (m_bagslot[i] != 0) - if (m_bagslot[i]->GetGUID() == guid) - return i; - - return NULL_SLOT; -} - -Item* Bag::GetItemByPos(uint8 slot) const -{ - if (slot < GetBagSize()) - return m_bagslot[slot]; - - return NULL; -} - diff --git a/src/server/game/Entities/Item/Bag.h b/src/server/game/Entities/Item/Bag.h deleted file mode 100644 index 5bc2480fc47..00000000000 --- a/src/server/game/Entities/Item/Bag.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_BAG_H -#define TRINITY_BAG_H - -// Maximum 36 Slots ((CONTAINER_END - CONTAINER_FIELD_SLOT_1)/2 -#define MAX_BAG_SIZE 36 // 2.0.12 - -#include "Item.h" -#include "ItemPrototype.h" - -class Bag : public Item -{ - public: - - Bag(); - ~Bag(); - - void AddToWorld(); - void RemoveFromWorld(); - - bool Create(uint32 guidlow, uint32 itemid, Player const* owner); - - void Clear(); - void StoreItem(uint8 slot, Item *pItem, bool update); - void RemoveItem(uint8 slot, bool update); - - Item* GetItemByPos(uint8 slot) const; - uint32 GetItemCount(uint32 item, Item* eItem = NULL) const; - - uint8 GetSlotByItemGUID(uint64 guid) const; - bool IsEmpty() const; - uint32 GetFreeSlots() const; - uint32 GetBagSize() const { return GetUInt32Value(CONTAINER_FIELD_NUM_SLOTS); } - - // DB operations - // overwrite virtual Item::SaveToDB - void SaveToDB(); - // overwrite virtual Item::LoadFromDB - bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result); - // overwrite virtual Item::DeleteFromDB - void DeleteFromDB(); - - void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const; - - protected: - - // Bag Storage space - Item* m_bagslot[MAX_BAG_SIZE]; -}; - -inline Item* NewItemOrBag(ItemPrototype const * proto) -{ - return (proto->InventoryType == INVTYPE_BAG) ? new Bag : new Item; -} -#endif - diff --git a/src/server/game/Entities/Item/Container/Bag.cpp b/src/server/game/Entities/Item/Container/Bag.cpp new file mode 100644 index 00000000000..aa78126b198 --- /dev/null +++ b/src/server/game/Entities/Item/Container/Bag.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "ObjectMgr.h" +#include "Database/DatabaseEnv.h" + +#include "Bag.h" +#include "Log.h" +#include "UpdateData.h" + +Bag::Bag(): Item() +{ + m_objectType |= TYPEMASK_CONTAINER; + m_objectTypeId = TYPEID_CONTAINER; + + m_valuesCount = CONTAINER_END; + + memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); +} + +Bag::~Bag() +{ + for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) + if (Item *item = m_bagslot[i]) + { + if (item->IsInWorld()) + { + sLog.outCrash("Item %u (slot %u, bag slot %u) in bag %u (slot %u, bag slot %u, m_bagslot %u) is to be deleted but is still in world.", + item->GetEntry(), (uint32)item->GetSlot(), (uint32)item->GetBagSlot(), + GetEntry(), (uint32)GetSlot(), (uint32)GetBagSlot(), (uint32)i); + item->RemoveFromWorld(); + } + delete m_bagslot[i]; + } +} + +void Bag::AddToWorld() +{ + Item::AddToWorld(); + + for (uint32 i = 0; i < GetBagSize(); ++i) + if (m_bagslot[i]) + m_bagslot[i]->AddToWorld(); +} + +void Bag::RemoveFromWorld() +{ + for (uint32 i = 0; i < GetBagSize(); ++i) + if (m_bagslot[i]) + m_bagslot[i]->RemoveFromWorld(); + + Item::RemoveFromWorld(); +} + +bool Bag::Create(uint32 guidlow, uint32 itemid, Player const* owner) +{ + ItemPrototype const * itemProto = objmgr.GetItemPrototype(itemid); + + if (!itemProto || itemProto->ContainerSlots > MAX_BAG_SIZE) + return false; + + Object::_Create(guidlow, 0, HIGHGUID_CONTAINER); + + SetEntry(itemid); + SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + + SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0); + SetUInt64Value(ITEM_FIELD_CONTAINED, owner ? owner->GetGUID() : 0); + + SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability); + SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability); + SetUInt32Value(ITEM_FIELD_FLAGS, itemProto->Flags); + SetUInt32Value(ITEM_FIELD_STACK_COUNT, 1); + + // Setting the number of Slots the Container has + SetUInt32Value(CONTAINER_FIELD_NUM_SLOTS, itemProto->ContainerSlots); + + // Cleaning 20 slots + for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) + { + SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0); + m_bagslot[i] = NULL; + } + + return true; +} + +void Bag::SaveToDB() +{ + Item::SaveToDB(); +} + +bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result) +{ + if (!Item::LoadFromDB(guid, owner_guid, result)) + return false; + + // cleanup bag content related item value fields (its will be filled correctly from `character_inventory`) + for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) + { + SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0); + if (m_bagslot[i]) + { + delete m_bagslot[i]; + m_bagslot[i] = NULL; + } + } + + return true; +} + +void Bag::DeleteFromDB() +{ + for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) + if (m_bagslot[i]) + m_bagslot[i]->DeleteFromDB(); + + Item::DeleteFromDB(); +} + +uint32 Bag::GetFreeSlots() const +{ + uint32 slots = 0; + for (uint32 i=0; i < GetBagSize(); ++i) + if (!m_bagslot[i]) + ++slots; + + return slots; +} + +void Bag::RemoveItem(uint8 slot, bool /*update*/) +{ + assert(slot < MAX_BAG_SIZE); + + if (m_bagslot[slot]) + m_bagslot[slot]->SetContainer(NULL); + + m_bagslot[slot] = NULL; + SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (slot * 2), 0); +} + +void Bag::StoreItem(uint8 slot, Item *pItem, bool /*update*/) +{ + assert(slot < MAX_BAG_SIZE); + + if (pItem && pItem->GetGUID() != this->GetGUID()) + { + m_bagslot[slot] = pItem; + SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (slot * 2), pItem->GetGUID()); + pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, GetGUID()); + pItem->SetUInt64Value(ITEM_FIELD_OWNER, GetOwnerGUID()); + pItem->SetContainer(this); + pItem->SetSlot(slot); + } +} + +void Bag::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const +{ + Item::BuildCreateUpdateBlockForPlayer(data, target); + + for (uint32 i = 0; i < GetBagSize(); ++i) + if (m_bagslot[i]) + m_bagslot[i]->BuildCreateUpdateBlockForPlayer(data, target); +} + +// If the bag is empty returns true +bool Bag::IsEmpty() const +{ + for (uint32 i = 0; i < GetBagSize(); ++i) + if (m_bagslot[i]) + return false; + + return true; +} + +uint32 Bag::GetItemCount(uint32 item, Item* eItem) const +{ + Item *pItem; + uint32 count = 0; + for (uint32 i=0; i < GetBagSize(); ++i) + { + pItem = m_bagslot[i]; + if (pItem && pItem != eItem && pItem->GetEntry() == item) + count += pItem->GetCount(); + } + + if (eItem && eItem->GetProto()->GemProperties) + { + for (uint32 i=0; i < GetBagSize(); ++i) + { + pItem = m_bagslot[i]; + if (pItem && pItem != eItem && pItem->GetProto()->Socket[0].Color) + count += pItem->GetGemCountWithID(item); + } + } + + return count; +} + +uint8 Bag::GetSlotByItemGUID(uint64 guid) const +{ + for (uint32 i = 0; i < GetBagSize(); ++i) + if (m_bagslot[i] != 0) + if (m_bagslot[i]->GetGUID() == guid) + return i; + + return NULL_SLOT; +} + +Item* Bag::GetItemByPos(uint8 slot) const +{ + if (slot < GetBagSize()) + return m_bagslot[slot]; + + return NULL; +} + diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h new file mode 100644 index 00000000000..5bc2480fc47 --- /dev/null +++ b/src/server/game/Entities/Item/Container/Bag.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_BAG_H +#define TRINITY_BAG_H + +// Maximum 36 Slots ((CONTAINER_END - CONTAINER_FIELD_SLOT_1)/2 +#define MAX_BAG_SIZE 36 // 2.0.12 + +#include "Item.h" +#include "ItemPrototype.h" + +class Bag : public Item +{ + public: + + Bag(); + ~Bag(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create(uint32 guidlow, uint32 itemid, Player const* owner); + + void Clear(); + void StoreItem(uint8 slot, Item *pItem, bool update); + void RemoveItem(uint8 slot, bool update); + + Item* GetItemByPos(uint8 slot) const; + uint32 GetItemCount(uint32 item, Item* eItem = NULL) const; + + uint8 GetSlotByItemGUID(uint64 guid) const; + bool IsEmpty() const; + uint32 GetFreeSlots() const; + uint32 GetBagSize() const { return GetUInt32Value(CONTAINER_FIELD_NUM_SLOTS); } + + // DB operations + // overwrite virtual Item::SaveToDB + void SaveToDB(); + // overwrite virtual Item::LoadFromDB + bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result); + // overwrite virtual Item::DeleteFromDB + void DeleteFromDB(); + + void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const; + + protected: + + // Bag Storage space + Item* m_bagslot[MAX_BAG_SIZE]; +}; + +inline Item* NewItemOrBag(ItemPrototype const * proto) +{ + return (proto->InventoryType == INVTYPE_BAG) ? new Bag : new Item; +} +#endif + diff --git a/src/server/game/Entities/Item/ItemHandler.cpp b/src/server/game/Entities/Item/ItemHandler.cpp deleted file mode 100644 index 53aede43492..00000000000 --- a/src/server/game/Entities/Item/ItemHandler.cpp +++ /dev/null @@ -1,1430 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "Item.h" -#include "UpdateData.h" -#include "ObjectAccessor.h" - -void WorldSession::HandleSplitItemOpcode(WorldPacket & recv_data) -{ - //sLog.outDebug("WORLD: CMSG_SPLIT_ITEM"); - uint8 srcbag, srcslot, dstbag, dstslot; - uint32 count; - - recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count; - //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count); - - uint16 src = ((srcbag << 8) | srcslot); - uint16 dst = ((dstbag << 8) | dstslot); - - if (src == dst) - return; - - if (count == 0) - return; //check count - if zero it's fake packet - - if (!_player->IsValidPos(srcbag,srcslot)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (!_player->IsValidPos(dstbag,dstslot)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); - return; - } - - _player->SplitItem(src, dst, count); -} - -void WorldSession::HandleSwapInvItemOpcode(WorldPacket & recv_data) -{ - //sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM"); - uint8 srcslot, dstslot; - - recv_data >> dstslot >> srcslot; - //sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot); - - // prevent attempt swap same item to current position generated by client at special checting sequence - if (srcslot == dstslot) - return; - - if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); - return; - } - - uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); - uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - - _player->SwapItem(src, dst); -} - -void WorldSession::HandleAutoEquipItemSlotOpcode(WorldPacket & recv_data) -{ - uint64 itemguid; - uint8 dstslot; - recv_data >> itemguid >> dstslot; - - // cheating attempt, client should never send opcode in that case - if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, dstslot)) - return; - - Item* item = _player->GetItemByGuid(itemguid); - uint16 dstpos = dstslot | (INVENTORY_SLOT_BAG_0 << 8); - - if (!item || item->GetPos() == dstpos) - return; - - _player->SwapItem(item->GetPos(), dstpos); -} - -void WorldSession::HandleSwapItem(WorldPacket & recv_data) -{ - //sLog.outDebug("WORLD: CMSG_SWAP_ITEM"); - uint8 dstbag, dstslot, srcbag, srcslot; - - recv_data >> dstbag >> dstslot >> srcbag >> srcslot ; - //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot); - - uint16 src = ((srcbag << 8) | srcslot); - uint16 dst = ((dstbag << 8) | dstslot); - - // prevent attempt swap same item to current position generated by client at special checting sequence - if (src == dst) - return; - - if (!_player->IsValidPos(srcbag,srcslot)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (!_player->IsValidPos(dstbag,dstslot)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); - return; - } - - _player->SwapItem(src, dst); -} - -void WorldSession::HandleAutoEquipItemOpcode(WorldPacket & recv_data) -{ - //sLog.outDebug("WORLD: CMSG_AUTOEQUIP_ITEM"); - uint8 srcbag, srcslot; - - recv_data >> srcbag >> srcslot; - //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); - - Item *pSrcItem = _player->GetItemByPos(srcbag, srcslot); - if (!pSrcItem) - return; // only at cheat - - uint16 dest; - uint8 msg = _player->CanEquipItem(NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag()); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pSrcItem, NULL); - return; - } - - uint16 src = pSrcItem->GetPos(); - if (dest == src) // prevent equip in same slot, only at cheat - return; - - Item *pDstItem = _player->GetItemByPos(dest); - if (!pDstItem) // empty slot, simple case - { - _player->RemoveItem(srcbag, srcslot, true); - _player->EquipItem(dest, pSrcItem, true); - _player->AutoUnequipOffhandIfNeed(); - } - else // have currently equipped item, not simple case - { - uint8 dstbag = pDstItem->GetBagSlot(); - uint8 dstslot = pDstItem->GetSlot(); - - msg = _player->CanUnequipItem(dest, !pSrcItem->IsBag()); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pDstItem, NULL); - return; - } - - // check dest->src move possibility - ItemPosCountVec sSrc; - uint16 eSrc = 0; - if (_player->IsInventoryPos(src)) - { - msg = _player->CanStoreItem(srcbag, srcslot, sSrc, pDstItem, true); - if (msg != EQUIP_ERR_OK) - msg = _player->CanStoreItem(srcbag, NULL_SLOT, sSrc, pDstItem, true); - if (msg != EQUIP_ERR_OK) - msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true); - } - else if (_player->IsBankPos(src)) - { - msg = _player->CanBankItem(srcbag, srcslot, sSrc, pDstItem, true); - if (msg != EQUIP_ERR_OK) - msg = _player->CanBankItem(srcbag, NULL_SLOT, sSrc, pDstItem, true); - if (msg != EQUIP_ERR_OK) - msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true); - } - else if (_player->IsEquipmentPos(src)) - { - msg = _player->CanEquipItem(srcslot, eSrc, pDstItem, true); - if (msg == EQUIP_ERR_OK) - msg = _player->CanUnequipItem(eSrc, true); - } - - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pDstItem, pSrcItem); - return; - } - - // now do moves, remove... - _player->RemoveItem(dstbag, dstslot, false); - _player->RemoveItem(srcbag, srcslot, false); - - // add to dest - _player->EquipItem(dest, pSrcItem, true); - - // add to src - if (_player->IsInventoryPos(src)) - _player->StoreItem(sSrc, pDstItem, true); - else if (_player->IsBankPos(src)) - _player->BankItem(sSrc, pDstItem, true); - else if (_player->IsEquipmentPos(src)) - _player->EquipItem(eSrc, pDstItem, true); - - _player->AutoUnequipOffhandIfNeed(); - } -} - -void WorldSession::HandleDestroyItemOpcode(WorldPacket & recv_data) -{ - //sLog.outDebug("WORLD: CMSG_DESTROYITEM"); - uint8 bag, slot, count, data1, data2, data3; - - recv_data >> bag >> slot >> count >> data1 >> data2 >> data3; - //sLog.outDebug("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count); - - uint16 pos = (bag << 8) | slot; - - // prevent drop unequipable items (in combat, for example) and non-empty bags - if (_player->IsEquipmentPos(pos) || _player->IsBagPos(pos)) - { - uint8 msg = _player->CanUnequipItem(pos, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, _player->GetItemByPos(pos), NULL); - return; - } - } - - Item *pItem = _player->GetItemByPos(bag, slot); - if (!pItem) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (count) - { - uint32 i_count = count; - _player->DestroyItemCount(pItem, i_count, true); - } - else - _player->DestroyItem(bag, slot, true); -} - -// Only _static_ data send in this packet !!! -void WorldSession::HandleItemQuerySingleOpcode(WorldPacket & recv_data) -{ - //sLog.outDebug("WORLD: CMSG_ITEM_QUERY_SINGLE"); - uint32 item; - recv_data >> item; - - sLog.outDetail("STORAGE: Item Query = %u", item); - - ItemPrototype const *pProto = objmgr.GetItemPrototype(item); - if (pProto) - { - std::string Name = pProto->Name1; - std::string Description = pProto->Description; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); - if (il) - { - if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty()) - Name = il->Name[loc_idx]; - if (il->Description.size() > size_t(loc_idx) && !il->Description[loc_idx].empty()) - Description = il->Description[loc_idx]; - } - } - // guess size - WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600); - data << pProto->ItemId; - data << pProto->Class; - data << pProto->SubClass; - data << int32(pProto->Unk0); // new 2.0.3, not exist in wdb cache? - data << Name; - data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name... - data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00); - data << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00); - data << pProto->DisplayInfoID; - data << pProto->Quality; - data << pProto->Flags; - data << pProto->Flags2; - data << pProto->BuyPrice; - data << pProto->SellPrice; - data << pProto->InventoryType; - data << pProto->AllowableClass; - data << pProto->AllowableRace; - data << pProto->ItemLevel; - data << pProto->RequiredLevel; - data << pProto->RequiredSkill; - data << pProto->RequiredSkillRank; - data << pProto->RequiredSpell; - data << pProto->RequiredHonorRank; - data << pProto->RequiredCityRank; - data << pProto->RequiredReputationFaction; - data << pProto->RequiredReputationRank; - data << int32(pProto->MaxCount); - data << int32(pProto->Stackable); - data << pProto->ContainerSlots; - data << pProto->StatsCount; // item stats count - for (uint32 i = 0; i < pProto->StatsCount; ++i) - { - data << pProto->ItemStat[i].ItemStatType; - data << pProto->ItemStat[i].ItemStatValue; - } - data << pProto->ScalingStatDistribution; // scaling stats distribution - data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column - for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i) - { - data << pProto->Damage[i].DamageMin; - data << pProto->Damage[i].DamageMax; - data << pProto->Damage[i].DamageType; - } - - // resistances (7) - data << pProto->Armor; - data << pProto->HolyRes; - data << pProto->FireRes; - data << pProto->NatureRes; - data << pProto->FrostRes; - data << pProto->ShadowRes; - data << pProto->ArcaneRes; - - data << pProto->Delay; - data << pProto->AmmoType; - data << pProto->RangedModRange; - - for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s) - { - // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown - // use `item_template` or if not set then only use spell cooldowns - SpellEntry const* spell = sSpellStore.LookupEntry(pProto->Spells[s].SpellId); - if (spell) - { - bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0; - - data << pProto->Spells[s].SpellId; - data << pProto->Spells[s].SpellTrigger; - data << uint32(-abs(pProto->Spells[s].SpellCharges)); - - if (db_data) - { - data << uint32(pProto->Spells[s].SpellCooldown); - data << uint32(pProto->Spells[s].SpellCategory); - data << uint32(pProto->Spells[s].SpellCategoryCooldown); - } - else - { - data << uint32(spell->RecoveryTime); - data << uint32(spell->Category); - data << uint32(spell->CategoryRecoveryTime); - } - } - else - { - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(-1); - data << uint32(0); - data << uint32(-1); - } - } - data << pProto->Bonding; - data << Description; - data << pProto->PageText; - data << pProto->LanguageID; - data << pProto->PageMaterial; - data << pProto->StartQuest; - data << pProto->LockID; - data << int32(pProto->Material); - data << pProto->Sheath; - data << pProto->RandomProperty; - data << pProto->RandomSuffix; - data << pProto->Block; - data << pProto->ItemSet; - data << pProto->MaxDurability; - data << pProto->Area; - data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch - data << pProto->BagFamily; - data << pProto->TotemCategory; - for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s) - { - data << pProto->Socket[s].Color; - data << pProto->Socket[s].Content; - } - data << pProto->socketBonus; - data << pProto->GemProperties; - data << pProto->RequiredDisenchantSkill; - data << pProto->ArmorDamageModifier; - data << abs(pProto->Duration); // added in 2.4.2.8209, duration (seconds) - data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory - data << pProto->HolidayId; // Holiday.dbc? - SendPacket(&data); - } - else - { - sLog.outDebug("WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item); - WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4); - data << uint32(item | 0x80000000); - SendPacket(&data); - } -} - -void WorldSession::HandleReadItem(WorldPacket & recv_data) -{ - //sLog.outDebug("WORLD: CMSG_READ_ITEM"); - - uint8 bag, slot; - recv_data >> bag >> slot; - - //sLog.outDetail("STORAGE: Read bag = %u, slot = %u", bag, slot); - Item *pItem = _player->GetItemByPos(bag, slot); - - if (pItem && pItem->GetProto()->PageText) - { - WorldPacket data; - - uint8 msg = _player->CanUseItem(pItem); - if (msg == EQUIP_ERR_OK) - { - data.Initialize (SMSG_READ_ITEM_OK, 8); - sLog.outDetail("STORAGE: Item page sent"); - } - else - { - data.Initialize(SMSG_READ_ITEM_FAILED, 8); - sLog.outDetail("STORAGE: Unable to read item"); - _player->SendEquipError(msg, pItem, NULL); - } - data << pItem->GetGUID(); - SendPacket(&data); - } - else - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); -} - -void WorldSession::HandlePageQuerySkippedOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_PAGE_TEXT_QUERY"); - - uint32 itemid; - uint64 guid; - - recv_data >> itemid >> guid; - - sLog.outDetail("Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u", - itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid)); -} - -void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_SELL_ITEM"); - uint64 vendorguid, itemguid; - uint32 count; - - recv_data >> vendorguid >> itemguid >> count; - - if (!itemguid) - return; - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); - _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Item *pItem = _player->GetItemByGuid(itemguid); - if (pItem) - { - // prevent sell not owner item - if (_player->GetGUID() != pItem->GetOwnerGUID()) - { - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); - return; - } - - // prevent sell non empty bag by drag-and-drop at vendor's item list - if (pItem->IsBag() && !((Bag*)pItem)->IsEmpty()) - { - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); - return; - } - - // prevent sell currently looted item - if (_player->GetLootGUID() == pItem->GetGUID()) - { - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); - return; - } - - // special case at auto sell (sell all) - if (count == 0) - { - count = pItem->GetCount(); - } - else - { - // prevent sell more items that exist in stack (possible only not from client) - if (count > pItem->GetCount()) - { - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); - return; - } - } - - ItemPrototype const *pProto = pItem->GetProto(); - if (pProto) - { - if (pProto->SellPrice > 0) - { - if (count < pItem->GetCount()) // need split items - { - Item *pNewItem = pItem->CloneItem(count, _player); - if (!pNewItem) - { - sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count); - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); - return; - } - - pItem->SetCount(pItem->GetCount() - count); - _player->ItemRemovedQuestCheck(pItem->GetEntry(), count); - if (_player->IsInWorld()) - pItem->SendUpdateToPlayer(_player); - pItem->SetState(ITEM_CHANGED, _player); - - _player->AddItemToBuyBackSlot(pNewItem); - if (_player->IsInWorld()) - pNewItem->SendUpdateToPlayer(_player); - } - else - { - _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); - _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true); - pItem->RemoveFromUpdateQueueOf(_player); - _player->AddItemToBuyBackSlot(pItem); - } - - uint32 money = pProto->SellPrice * count; - _player->ModifyMoney(money); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money); - } - else - _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); - return; - } - } - _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0); - return; -} - -void WorldSession::HandleBuybackItem(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_BUYBACK_ITEM"); - uint64 vendorguid; - uint32 slot; - - recv_data >> vendorguid >> slot; - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); - _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Item *pItem = _player->GetItemFromBuyBackSlot(slot); - if (pItem) - { - uint32 price = _player->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START); - if (_player->GetMoney() < price) - { - _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, pItem->GetEntry(), 0); - return; - } - - ItemPosCountVec dest; - uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false); - if (msg == EQUIP_ERR_OK) - { - _player->ModifyMoney(-(int32)price); - _player->RemoveItemFromBuyBackSlot(slot, false); - _player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount()); - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount()); - _player->StoreItem(dest, pItem, true); - } - else - _player->SendEquipError(msg, pItem, NULL); - return; - } - else - _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, pCreature, 0, 0); -} - -void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_BUY_ITEM_IN_SLOT"); - uint64 vendorguid, bagguid; - uint32 item, slot, count; - uint8 bagslot; - - recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count; - - // client expects count starting at 1, and we send vendorslot+1 to client already - if (slot > 0) - --slot; - else - return; // cheating - - uint8 bag = NULL_BAG; // init for case invalid bagGUID - - // find bag slot by bag guid - if (bagguid == _player->GetGUID()) - bag = INVENTORY_SLOT_BAG_0; - else - { - for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) - { - if (Bag *pBag = (Bag*)_player->GetItemByPos(INVENTORY_SLOT_BAG_0,i)) - { - if (bagguid == pBag->GetGUID()) - { - bag = i; - break; - } - } - } - } - - // bag not found, cheating? - if (bag == NULL_BAG) - return; - - GetPlayer()->BuyItemFromVendorSlot(vendorguid,slot,item,count,bag,bagslot); -} - -void WorldSession::HandleBuyItemOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_BUY_ITEM"); - uint64 vendorguid; - uint32 item, slot, count; - uint8 unk1; - - recv_data >> vendorguid >> item >> slot >> count >> unk1; - - // client expects count starting at 1, and we send vendorslot+1 to client already - if (slot > 0) - --slot; - else - return; // cheating - - GetPlayer()->BuyItemFromVendorSlot(vendorguid,slot,item,count,NULL_BAG,NULL_SLOT); -} - -void WorldSession::HandleListInventoryOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - recv_data >> guid; - - if (!GetPlayer()->isAlive()) - return; - - sLog.outDebug("WORLD: Recvd CMSG_LIST_INVENTORY"); - - SendListInventory(guid); -} - -void WorldSession::SendListInventory(uint64 vendorguid) -{ - sLog.outDebug("WORLD: Sent SMSG_LIST_INVENTORY"); - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); - if (!pCreature) - { - sLog.outDebug("WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); - _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // Stop the npc if moving - pCreature->StopMoving(); - - VendorItemData const* vItems = pCreature->GetVendorItems(); - if (!vItems) - { - _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); - return; - } - - uint8 numitems = vItems->GetItemCount(); - uint8 count = 0; - - WorldPacket data(SMSG_LIST_INVENTORY, (8+1+numitems*8*4)); - data << uint64(vendorguid); - - size_t count_pos = data.wpos(); - data << uint8(count); - - float discountMod = _player->GetReputationPriceDiscount(pCreature); - - for (uint8 vendorslot = 0; vendorslot < numitems; ++vendorslot ) - { - if (VendorItem const* crItem = vItems->GetItem(vendorslot)) - { - if (ItemPrototype const *pProto = objmgr.GetItemPrototype(crItem->item)) - { - if ((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster()) - continue; - // Only display items in vendor lists for the team the - // player is on. If GM on, display all items. - // `item_template`.`Faction` is actually `Team`. - // 1 == Horde / 2 == Alliance. Field will be renamed in later - // patch. - if (pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE || pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE && !_player->isGameMaster()) - continue; - ++count; - - // reputation discount - int32 price = uint32(floor(pProto->BuyPrice * discountMod)); - - data << uint32(vendorslot+1); // client expects counting to start at 1 - data << uint32(crItem->item); - data << uint32(pProto->DisplayInfoID); - data << int32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem)); - data << uint32(price); - data << uint32(pProto->MaxDurability); - data << uint32(pProto->BuyCount); - data << uint32(crItem->ExtendedCost); - } - } - } - - if (count == 0 || data.size() != 8 + 1 + size_t(count) * 8 * 4) - return; - - data.put(count_pos, count); - SendPacket(&data); -} - -void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket & recv_data) -{ - //sLog.outDebug("WORLD: CMSG_AUTOSTORE_BAG_ITEM"); - uint8 srcbag, srcslot, dstbag; - - recv_data >> srcbag >> srcslot >> dstbag; - //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag); - - Item *pItem = _player->GetItemByPos(srcbag, srcslot); - if (!pItem) - return; - - if (!_player->IsValidPos(dstbag,NULL_SLOT)) - { - _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); - return; - } - - uint16 src = pItem->GetPos(); - - // check unequip potability for equipped items and bank bags - if (_player->IsEquipmentPos (src) || _player->IsBagPos (src)) - { - uint8 msg = _player->CanUnequipItem(src, !_player->IsBagPos (src)); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - } - - ItemPosCountVec dest; - uint8 msg = _player->CanStoreItem(dstbag, NULL_SLOT, dest, pItem, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - - // no-op: placed in same slot - if (dest.size() == 1 && dest[0].pos == src) - { - // just remove grey item state - _player->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); - return; - } - - _player->RemoveItem(srcbag, srcslot, true); - _player->StoreItem(dest, pItem, true); -} - -void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: CMSG_BUY_BANK_SLOT"); - - uint64 guid; - recvPacket >> guid; - - // cheating protection - /* not critical if "cheated", and check skip allow by slots in bank windows open by .bank command. - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - */ - - uint32 slot = _player->GetBankBagSlotCount(); - - // next slot - ++slot; - - sLog.outDetail("PLAYER: Buy bank bag slot, slot number = %u", slot); - - BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot); - - WorldPacket data(SMSG_BUY_BANK_SLOT_RESULT, 4); - - if (!slotEntry) - { - data << uint32(ERR_BANKSLOT_FAILED_TOO_MANY); - SendPacket(&data); - return; - } - - uint32 price = slotEntry->price; - - if (_player->GetMoney() < price) - { - data << uint32(ERR_BANKSLOT_INSUFFICIENT_FUNDS); - SendPacket(&data); - return; - } - - _player->SetBankBagSlotCount(slot); - _player->ModifyMoney(-int32(price)); - - data << uint32(ERR_BANKSLOT_OK); - SendPacket(&data); - - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT); -} - -void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: CMSG_AUTOBANK_ITEM"); - uint8 srcbag, srcslot; - - recvPacket >> srcbag >> srcslot; - sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); - - Item *pItem = _player->GetItemByPos(srcbag, srcslot); - if (!pItem) - return; - - ItemPosCountVec dest; - uint8 msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, dest, pItem, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - - _player->RemoveItem(srcbag, srcslot, true); - _player->BankItem(dest, pItem, true); -} - -void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: CMSG_AUTOSTORE_BANK_ITEM"); - uint8 srcbag, srcslot; - - recvPacket >> srcbag >> srcslot; - sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); - - Item *pItem = _player->GetItemByPos(srcbag, srcslot); - if (!pItem) - return; - - if (_player->IsBankPos(srcbag, srcslot)) // moving from bank to inventory - { - ItemPosCountVec dest; - uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - - _player->RemoveItem(srcbag, srcslot, true); - _player->StoreItem(dest, pItem, true); - } - else // moving from inventory to bank - { - ItemPosCountVec dest; - uint8 msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, dest, pItem, false); - if (msg != EQUIP_ERR_OK) - { - _player->SendEquipError(msg, pItem, NULL); - return; - } - - _player->RemoveItem(srcbag, srcslot, true); - _player->BankItem(dest, pItem, true); - } -} - -void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data) -{ - if (!GetPlayer()->isAlive()) - { - GetPlayer()->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL); - return; - } - - sLog.outDebug("WORLD: CMSG_SET_AMMO"); - uint32 item; - - recv_data >> item; - - if (!item) - GetPlayer()->RemoveAmmo(); - else - GetPlayer()->SetAmmo(item); -} - -void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID) -{ - WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10 - data << uint64(Target); - data << uint64(Caster); - data << uint32(ItemID); - data << uint32(SpellID); - data << uint8(0); - SendPacket(&data); -} - -void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration) -{ - // last check 2.0.10 - WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8)); - data << uint64(Itemguid); - data << uint32(slot); - data << uint32(Duration); - data << uint64(Playerguid); - SendPacket(&data); -} - -void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data) -{ - uint32 itemid; - recv_data >> itemid; - recv_data.read_skip(); // guid - - sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid); - ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid); - if (pProto) - { - std::string Name; - Name = pProto->Name1; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); - if (il) - { - if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty()) - Name = il->Name[loc_idx]; - } - } - // guess size - WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+10)); - data << uint32(pProto->ItemId); - data << Name; - data << uint32(pProto->InventoryType); - SendPacket(&data); - return; - } -// This is a BS check, there are lots of items listed in Item.dbc that do not even exist on official -- so we can NEVER get the data for them. -// If you *really* want to spam your error log -- uncomment this. -/* else - { - // listed in dbc or not expected to exist unknown item - if (sItemStore.LookupEntry(itemid)) - sLog.outErrorDb("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (item listed in Item.dbc but not exist in DB)", itemid); - else - sLog.outError("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (unknown item, not listed in Item.dbc)", itemid); - } */ -} - -void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data) -{ - sLog.outDebug("Received opcode CMSG_WRAP_ITEM"); - - uint8 gift_bag, gift_slot, item_bag, item_slot; - //recv_data.hexlike(); - - recv_data >> gift_bag >> gift_slot; // paper - recv_data >> item_bag >> item_slot; // item - - sLog.outDebug("WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot); - - Item *gift = _player->GetItemByPos(gift_bag, gift_slot); - if (!gift) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); - return; - } - - if (!gift->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPER))// cheating: non-wrapper wrapper - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); - return; - } - - Item *item = _player->GetItemByPos(item_bag, item_slot); - - if (!item) - { - _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL); - return; - } - - if (item == gift) // not possable with pacjket from real client - { - _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->IsEquipped()) - { - _player->SendEquipError(EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR)) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); - { - _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->IsBag()) - { - _player->SendEquipError(EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->IsSoulBound()) - { - _player->SendEquipError(EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL); - return; - } - - if (item->GetMaxStackCount() != 1) - { - _player->SendEquipError(EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL); - return; - } - - // maybe not correct check (it is better than nothing) - if (item->GetProto()->MaxCount>0) - { - _player->SendEquipError(EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL); - return; - } - - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS)); - item->SetEntry(gift->GetEntry()); - - switch (item->GetEntry()) - { - case 5042: item->SetEntry(5043); break; - case 5048: item->SetEntry(5044); break; - case 17303: item->SetEntry(17302); break; - case 17304: item->SetEntry(17305); break; - case 17307: item->SetEntry(17308); break; - case 21830: item->SetEntry(21831); break; - } - item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID()); - item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); - item->SetState(ITEM_CHANGED, _player); - - if (item->GetState() == ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance` - { - // after save it will be impossible to remove the item from the queue - item->RemoveFromUpdateQueueOf(_player); - item->SaveToDB(); // item gave inventory record unchanged and can be save standalone - } - CharacterDatabase.CommitTransaction(); - - uint32 count = 1; - _player->DestroyItemCount(gift, count, true); -} - -void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) -{ - sLog.outDebug("WORLD: CMSG_SOCKET_GEMS"); - - uint64 item_guid; - uint64 gem_guids[MAX_GEM_SOCKETS]; - - recv_data >> item_guid; - if (!item_guid) - return; - - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - recv_data >> gem_guids[i]; - - //cheat -> tried to socket same gem multiple times - if ((gem_guids[0] && (gem_guids[0] == gem_guids[1] || gem_guids[0] == gem_guids[2])) || - (gem_guids[1] && (gem_guids[1] == gem_guids[2]))) - return; - - Item *itemTarget = _player->GetItemByGuid(item_guid); - if (!itemTarget) //missing item to socket - return; - - ItemPrototype const* itemProto = itemTarget->GetProto(); - if (!itemProto) - return; - - //this slot is excepted when applying / removing meta gem bonus - uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT); - - Item *Gems[MAX_GEM_SOCKETS]; - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - Gems[i] = gem_guids[i] ? _player->GetItemByGuid(gem_guids[i]) : NULL; - - GemPropertiesEntry const *GemProps[MAX_GEM_SOCKETS]; - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get geminfo from dbc storage - GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL; - - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //check for hack maybe - { - if (!GemProps[i]) - continue; - - // tried to put gem in socket where no socket exists (take care about prismatic sockets) - if (!itemProto->Socket[i].Color) - { - // no prismatic socket - if (!itemTarget->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) - return; - - // not first not-colored (not normaly used) socket - if (i != 0 && !itemProto->Socket[i-1].Color && (i+1 >= MAX_GEM_SOCKETS || itemProto->Socket[i+1].Color)) - return; - - // ok, this is first not colored socket for item with prismatic socket - } - - // tried to put normal gem in meta socket - if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META) - return; - - // tried to put meta gem in normal socket - if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META) - return; - } - - uint32 GemEnchants[MAX_GEM_SOCKETS]; - uint32 OldEnchants[MAX_GEM_SOCKETS]; - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get new and old enchantments - { - GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0; - OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i)); - } - - // check unique-equipped conditions - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - { - if (!Gems[i]) - continue; - - // continue check for case when attempt add 2 similar unique equipped gems in one item. - ItemPrototype const* iGemProto = Gems[i]->GetProto(); - - // unique item (for new and already placed bit removed enchantments - if (iGemProto->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED) - { - for (int j = 0; j < MAX_GEM_SOCKETS; ++j) - { - if (i == j) // skip self - continue; - - if (Gems[j]) - { - if (iGemProto->ItemId == Gems[j]->GetEntry()) - { - _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); - return; - } - } - else if (OldEnchants[j]) - { - if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) - { - if (iGemProto->ItemId == enchantEntry->GemID) - { - _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); - return; - } - } - } - - } - } - - // unique limit type item - int32 limit_newcount = 0; - if (iGemProto->ItemLimitCategory) - { - if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->ItemLimitCategory)) - { - for (int j = 0; j < MAX_GEM_SOCKETS; ++j) - { - if (Gems[j]) - { - // destroyed gem - if (OldEnchants[j]) - { - if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) - if (ItemPrototype const* jProto = ObjectMgr::GetItemPrototype(enchantEntry->GemID)) - if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory) - --limit_newcount; - } - - // new gem - if (iGemProto->ItemLimitCategory == Gems[j]->GetProto()->ItemLimitCategory) - ++limit_newcount; - } - // existed gem - else if (OldEnchants[j]) - { - if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) - if (ItemPrototype const* jProto = ObjectMgr::GetItemPrototype(enchantEntry->GemID)) - if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory) - ++limit_newcount; - } - } - - if (limit_newcount > 0 && uint32(limit_newcount) > limitEntry->maxCount) - { - _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); - return; - } - } - } - - // for equipped item check all equipment for duplicate equipped gems - if (itemTarget->IsEquipped()) - { - if (uint8 res = _player->CanEquipUniqueItem(Gems[i],slot,limit_newcount >= 0 ? limit_newcount : 0)) - { - _player->SendEquipError(res, itemTarget, NULL); - return; - } - } - } - - bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus - _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item) - - //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met - - //remove ALL enchants - for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) - _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),false); - - for (int i = 0; i < MAX_GEM_SOCKETS; ++i) - { - if (GemEnchants[i]) - { - itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i],0,0); - if (Item* guidItem = _player->GetItemByGuid(gem_guids[i])) - _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true); - } - } - - for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) - _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true); - - bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state - if (SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change... - { - _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false); - itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0); - _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,true); - //it is not displayed, client has an inbuilt system to determine if the bonus is activated - } - - _player->ToggleMetaGemsActive(slot, true); //turn on all metagems (except for target item) -} - -void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data) -{ - sLog.outDebug("WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT"); - - uint32 eslot; - - recv_data >> eslot; - - // apply only to equipped item - if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0,eslot)) - return; - - Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot); - - if (!item) - return; - - if (!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)) - return; - - GetPlayer()->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); - item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT); -} - -void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recv_data) -{ - sLog.outDebug("WORLD: CMSG_ITEM_REFUND_INFO"); - - uint64 guid; - recv_data >> guid; // item guid - - Item *item = _player->GetItemByGuid(guid); - if (!item) - { - sLog.outDebug("Item refund: item not found!"); - return; - } - - GetPlayer()->SendRefundInfo(item); -} - -void WorldSession::HandleItemRefund(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: CMSG_ITEM_REFUND"); - uint64 guid; - recv_data >> guid; // item guid - - Item *item = _player->GetItemByGuid(guid); - if (!item) - { - sLog.outDebug("Item refund: item not found!"); - return; - } - - GetPlayer()->RefundItem(item); -} - -/** - * Handles the packet sent by the client when requesting information about item text. - * - * This function is called when player clicks on item which has some flag set - */ -void WorldSession::HandleItemTextQuery(WorldPacket & recv_data ) -{ - uint64 itemGuid; - recv_data >> itemGuid; - - sLog.outDebug("CMSG_ITEM_TEXT_QUERY item guid: %u", GUID_LOPART(itemGuid)); - - WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, (4+10)); // guess size - - if (Item *item = _player->GetItemByGuid(itemGuid)) - { - data << uint8(0); // has text - data << uint64(itemGuid); // item guid - data << item->GetText(); - } - else - { - data << uint8(1); // no text - } - - SendPacket(&data); -} diff --git a/src/server/game/Entities/Object/Corpse.cpp b/src/server/game/Entities/Object/Corpse.cpp deleted file mode 100644 index 510ea13e78b..00000000000 --- a/src/server/game/Entities/Object/Corpse.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Corpse.h" -#include "Player.h" -#include "UpdateMask.h" -#include "ObjectAccessor.h" -#include "Database/DatabaseEnv.h" -#include "Opcodes.h" -#include "GossipDef.h" -#include "World.h" - -Corpse::Corpse(CorpseType type) : WorldObject() -, m_type(type) -{ - m_objectType |= TYPEMASK_CORPSE; - m_objectTypeId = TYPEID_CORPSE; - - m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION); - - m_valuesCount = CORPSE_END; - - m_time = time(NULL); - - lootForBody = false; - - if (type != CORPSE_BONES) - m_isWorldObject = true; -} - -Corpse::~Corpse() -{ -} - -void Corpse::AddToWorld() -{ - ///- Register the corpse for guid lookup - if (!IsInWorld()) - ObjectAccessor::Instance().AddObject(this); - - Object::AddToWorld(); -} - -void Corpse::RemoveFromWorld() -{ - ///- Remove the corpse from the accessor - if (IsInWorld()) - ObjectAccessor::Instance().RemoveObject(this); - - Object::RemoveFromWorld(); -} - -bool Corpse::Create(uint32 guidlow, Map *map) -{ - SetMap(map); - Object::_Create(guidlow, 0, HIGHGUID_CORPSE); - return true; -} - -bool Corpse::Create(uint32 guidlow, Player *owner) -{ - ASSERT(owner); - - Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation()); - - if (!IsPositionValid()) - { - sLog.outError("Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)", - guidlow, owner->GetName(), owner->GetPositionX(), owner->GetPositionY()); - return false; - } - - //we need to assign owner's map for corpse - //in other way we will get a crash in Corpse::SaveToDB() - SetMap(owner->GetMap()); - - WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask()); - - SetFloatValue(OBJECT_FIELD_SCALE_X, 1); - SetUInt64Value(CORPSE_FIELD_OWNER, owner->GetGUID()); - - m_grid = Trinity::ComputeGridPair(GetPositionX(), GetPositionY()); - - return true; -} - -void Corpse::SaveToDB() -{ - // prevent DB data inconsistence problems and duplicates - CharacterDatabase.BeginTransaction(); - DeleteFromDB(); - - std::ostringstream ss; - ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance,phaseMask) VALUES (" - << GetGUIDLow() << ", " - << GUID_LOPART(GetOwnerGUID()) << ", " - << GetPositionX() << ", " - << GetPositionY() << ", " - << GetPositionZ() << ", " - << GetOrientation() << ", " - << GetZoneId() << ", " - << GetMapId() << ", '"; - for (uint16 i = 0; i < m_valuesCount; ++i) - ss << GetUInt32Value(i) << " "; - ss << "'," - << uint64(m_time) <<", " - << uint32(GetType()) << ", " - << int(GetInstanceId()) << ", " - << uint16(GetPhaseMask()) << ")"; // prevent out of range error - CharacterDatabase.Execute(ss.str().c_str()); - CharacterDatabase.CommitTransaction(); -} - -void Corpse::DeleteBonesFromWorld() -{ - assert(GetType() == CORPSE_BONES); - Corpse* corpse = ObjectAccessor::GetCorpse(*this, GetGUID()); - - if (!corpse) - { - sLog.outError("Bones %u not found in world.", GetGUIDLow()); - return; - } - - AddObjectToRemoveList(); -} - -void Corpse::DeleteFromDB() -{ - if (GetType() == CORPSE_BONES) - // only specific bones - CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%d'", GetGUIDLow()); - else - // all corpses (not bones) - CharacterDatabase.PExecute("DELETE FROM corpse WHERE player = '%d' AND corpse_type <> '0'", GUID_LOPART(GetOwnerGUID())); -} - -/* -bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId) -{ - bool external = (result != NULL); - if (!external) - // 0 1 2 3 4 5 6 7 8 9 - result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid); - - if (!result) - { - sLog.outError("Corpse (GUID: %u) not found in table `corpse`, can't load. ",guid); - return false; - } - - Field *fields = result->Fetch(); - - if (!LoadFromDB(guid, fields)) - { - if (!external) - delete result; - - return false; - } - - if (!external) - delete result; - - return true; -}*/ - -bool Corpse::LoadFromDB(uint32 guid, Field *fields) -{ - float positionX = fields[0].GetFloat(); - float positionY = fields[1].GetFloat(); - float positionZ = fields[2].GetFloat(); - float ort = fields[3].GetFloat(); - uint32 mapid = fields[4].GetUInt32(); - - Object::_Create(guid, 0, HIGHGUID_CORPSE); - - if (!LoadValues(fields[5].GetString())) - { - sLog.outError("Corpse #%d have broken data in `data` field. Can't be loaded.",guid); - return false; - } - - m_time = time_t(fields[6].GetUInt64()); - m_type = CorpseType(fields[7].GetUInt32()); - - if (m_type >= MAX_CORPSE_TYPE) - { - sLog.outError("Corpse (guidlow %d, owner %d) have wrong corpse type, not load.",GetGUIDLow(),GUID_LOPART(GetOwnerGUID())); - return false; - } - - if (m_type != CORPSE_BONES) - m_isWorldObject = true; - - uint32 instanceid = fields[8].GetUInt32(); - - uint32 phaseMask = fields[9].GetUInt32(); - - // overwrite possible wrong/corrupted guid - SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE)); - - // place - SetLocationInstanceId(instanceid); - SetLocationMapId(mapid); - SetPhaseMask(phaseMask, false); - Relocate(positionX, positionY, positionZ, ort); - - if (!IsPositionValid()) - { - sLog.outError("Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", - GetGUIDLow(), GUID_LOPART(GetOwnerGUID()), GetPositionX(), GetPositionY()); - return false; - } - - m_grid = Trinity::ComputeGridPair(GetPositionX(), GetPositionY()); - - return true; -} - -bool Corpse::isVisibleForInState(Player const* u, bool inVisibleList) const -{ - return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u->m_seer, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false); -} - diff --git a/src/server/game/Entities/Object/Corpse.h b/src/server/game/Entities/Object/Corpse.h deleted file mode 100644 index bab95e99d14..00000000000 --- a/src/server/game/Entities/Object/Corpse.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_CORPSE_H -#define TRINITYCORE_CORPSE_H - -#include "Object.h" -#include "Database/DatabaseEnv.h" -#include "GridDefines.h" -#include "LootMgr.h" - -enum CorpseType -{ - CORPSE_BONES = 0, - CORPSE_RESURRECTABLE_PVE = 1, - CORPSE_RESURRECTABLE_PVP = 2 -}; -#define MAX_CORPSE_TYPE 3 - -// Value equal client resurrection dialog show radius. -#define CORPSE_RECLAIM_RADIUS 39 - -enum CorpseFlags -{ - CORPSE_FLAG_NONE = 0x00, - CORPSE_FLAG_BONES = 0x01, - CORPSE_FLAG_UNK1 = 0x02, - CORPSE_FLAG_UNK2 = 0x04, - CORPSE_FLAG_HIDE_HELM = 0x08, - CORPSE_FLAG_HIDE_CLOAK = 0x10, - CORPSE_FLAG_LOOTABLE = 0x20 -}; - -class Corpse : public WorldObject, public GridObject -{ - public: - explicit Corpse(CorpseType type = CORPSE_BONES); - ~Corpse(); - - void AddToWorld(); - void RemoveFromWorld(); - - bool Create(uint32 guidlow, Map *map); - bool Create(uint32 guidlow, Player *owner); - - void SaveToDB(); - //bool LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId); - bool LoadFromDB(uint32 guid, Field *fields); - - void DeleteBonesFromWorld(); - void DeleteFromDB(); - - uint64 const& GetOwnerGUID() const { return GetUInt64Value(CORPSE_FIELD_OWNER); } - - time_t const& GetGhostTime() const { return m_time; } - void ResetGhostTime() { m_time = time(NULL); } - CorpseType GetType() const { return m_type; } - - GridPair const& GetGrid() const { return m_grid; } - void SetGrid(GridPair const& grid) { m_grid = grid; } - - bool isVisibleForInState(Player const* u, bool inVisibleList) const; - - Loot loot; // remove insignia ONLY at BG - Player* lootRecipient; - bool lootForBody; - - void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } - void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } - void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); } - void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); } - void YellToZone(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYellToZone(textId,language,TargetGuid); } - - private: - CorpseType m_type; - time_t m_time; - GridPair m_grid; // gride for corpse position for fast search -}; -#endif - diff --git a/src/server/game/Entities/Object/DynamicObject.cpp b/src/server/game/Entities/Object/DynamicObject.cpp deleted file mode 100644 index 48179190a6e..00000000000 --- a/src/server/game/Entities/Object/DynamicObject.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "UpdateMask.h" -#include "Opcodes.h" -#include "World.h" -#include "ObjectAccessor.h" -#include "Database/DatabaseEnv.h" -#include "GridNotifiers.h" -#include "CellImpl.h" -#include "GridNotifiersImpl.h" - -DynamicObject::DynamicObject() : WorldObject() -{ - m_objectType |= TYPEMASK_DYNAMICOBJECT; - m_objectTypeId = TYPEID_DYNAMICOBJECT; - - m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION); - - m_valuesCount = DYNAMICOBJECT_END; - - m_aura = 0; - m_duration = 0; -} - -void DynamicObject::AddToWorld() -{ - ///- Register the dynamicObject for guid lookup - if (!IsInWorld()) - { - ObjectAccessor::Instance().AddObject(this); - WorldObject::AddToWorld(); - } -} - -void DynamicObject::RemoveFromWorld() -{ - ///- Remove the dynamicObject from the accessor - if (IsInWorld()) - { - if (m_isWorldObject) - { - if (Unit *caster = GetCaster()) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - caster->ToPlayer()->SetViewpoint(this, false); - } - else - { - sLog.outCrash("DynamicObject::RemoveFromWorld cannot find viewpoint owner"); - } - } - WorldObject::RemoveFromWorld(); - ObjectAccessor::Instance().RemoveObject(this); - } -} - -bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, const Position &pos, float radius, bool active) -{ - SetMap(caster->GetMap()); - Relocate(pos); - if (!IsPositionValid()) - { - sLog.outError("DynamicObject (spell %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",spellId,GetPositionX(),GetPositionY()); - return false; - } - - WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask()); - - SetEntry(spellId); - SetFloatValue(OBJECT_FIELD_SCALE_X, 1); - SetUInt64Value(DYNAMICOBJECT_CASTER, caster->GetGUID()); - - // The lower word of DYNAMICOBJECT_BYTES must be 0x0001. This value means that the visual radius will be overriden - // by client for most of the "ground patch" visual effect spells and a few "skyfall" ones like Hurricane. - // If any other value is used, the client will _always_ use the radius provided in DYNAMICOBJECT_RADIUS, but - // precompensation is necessary (eg radius *= 2) for many spells. Anyway, blizz sends 0x0001 for all the spells - // I saw sniffed... - SetUInt32Value(DYNAMICOBJECT_BYTES, 0x00000001); - SetUInt32Value(DYNAMICOBJECT_SPELLID, spellId); - SetFloatValue(DYNAMICOBJECT_RADIUS, radius); - SetUInt32Value(DYNAMICOBJECT_CASTTIME, getMSTime()); - - m_isWorldObject = active; - return true; -} - -Unit* DynamicObject::GetCaster() const -{ - // can be not found in some cases - return ObjectAccessor::GetUnit(*this, GetCasterGUID()); -} - -void DynamicObject::Update(uint32 p_time) -{ - // caster can be not in world at time dynamic object update, but dynamic object not yet deleted in Unit destructor - Unit* caster = GetCaster(); - if (!caster) - { - Delete(); - return; - } - - bool expired = false; - - if (m_aura) - { - if (!m_aura->IsRemoved()) - m_aura->UpdateOwner(p_time, this); - - // m_aura may be set to null in Unit::RemoveGameObject call - if (m_aura && (m_aura->IsRemoved() || m_aura->IsExpired())) - expired = true; - } - else - { - if (GetDuration() > int32(p_time)) - m_duration -= p_time; - else - expired = true; - } - - if (expired) - { - caster->RemoveDynObjectWithGUID(GetGUID()); - Delete(); - } -} - -void DynamicObject::Delete() -{ - if (m_aura) - { - // dynObj may be removed in Aura::Remove - we cannot delete there - // so recheck aura here - if (!m_aura->IsRemoved()) - m_aura->_Remove(AURA_REMOVE_BY_DEFAULT); - delete m_aura; - m_aura = NULL; - } - SendObjectDeSpawnAnim(GetGUID()); - RemoveFromWorld(); - AddObjectToRemoveList(); -} - -int32 DynamicObject::GetDuration() const -{ - if (!m_aura) - return m_duration; - else - return m_aura->GetDuration(); -} - -void DynamicObject::SetDuration(int32 newDuration) -{ - if (!m_aura) - m_duration = newDuration; - else - m_aura->SetDuration(newDuration); -} - -void DynamicObject::Delay(int32 delaytime) -{ - SetDuration(GetDuration() - delaytime); -} - -bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const -{ - return IsInWorld() && u->IsInWorld() - && (IsWithinDistInMap(u->m_seer,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false)); -} diff --git a/src/server/game/Entities/Object/DynamicObject.h b/src/server/game/Entities/Object/DynamicObject.h deleted file mode 100644 index 9a70407fd2d..00000000000 --- a/src/server/game/Entities/Object/DynamicObject.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_DYNAMICOBJECT_H -#define TRINITYCORE_DYNAMICOBJECT_H - -#include "Object.h" - -class Unit; -class Aura; -struct SpellEntry; - -class DynamicObject : public WorldObject, public GridObject -{ - public: - explicit DynamicObject(); - - void AddToWorld(); - void RemoveFromWorld(); - - bool Create(uint32 guidlow, Unit *caster, uint32 spellId, const Position &pos, float radius, bool active); - void Update(uint32 p_time); - void Delete(); - void SetDuration(int32 newDuration); - int32 GetDuration() const; - void SetAura(Aura * aura) {assert (!m_aura && aura); m_aura = aura;} - void Delay(int32 delaytime); - uint32 GetSpellId() const { return GetUInt32Value(DYNAMICOBJECT_SPELLID); } - uint64 GetCasterGUID() const { return GetUInt64Value(DYNAMICOBJECT_CASTER); } - float GetRadius() const { return GetFloatValue(DYNAMICOBJECT_RADIUS); } - Unit* GetCaster() const; - bool isVisibleForInState(Player const* u, bool inVisibleList) const; - - void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } - void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } - void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); } - void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); } - void YellToZone(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYellToZone(textId,language,TargetGuid); } - - protected: - int32 m_duration; // for non-aura dynobjects - Aura * m_aura; -}; -#endif diff --git a/src/server/game/Entities/Object/ObjectAccessor.cpp b/src/server/game/Entities/Object/ObjectAccessor.cpp deleted file mode 100644 index cf5bc728c6e..00000000000 --- a/src/server/game/Entities/Object/ObjectAccessor.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ObjectAccessor.h" -#include "ObjectMgr.h" -#include "Policies/SingletonImp.h" -#include "Player.h" -#include "Creature.h" -#include "GameObject.h" -#include "DynamicObject.h" -#include "Vehicle.h" -#include "WorldPacket.h" -#include "Item.h" -#include "Corpse.h" -#include "GridNotifiers.h" -#include "MapManager.h" -#include "Map.h" -#include "CellImpl.h" -#include "GridNotifiersImpl.h" -#include "Opcodes.h" -#include "ObjectDefines.h" -#include "MapInstanced.h" -#include "World.h" - -#include - -#define CLASS_LOCK Trinity::ClassLevelLockable -INSTANTIATE_SINGLETON_2(ObjectAccessor, CLASS_LOCK); -INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ACE_Thread_Mutex); - -ObjectAccessor::ObjectAccessor() -{ -} - -ObjectAccessor::~ObjectAccessor() -{ - for (Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr) - { - itr->second->RemoveFromWorld(); - delete itr->second; - } -} - -Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, uint64 guid) -{ - if (IS_PLAYER_GUID(guid)) - return NULL; - - if (IS_PET_GUID(guid)) - return GetPet(guid); - - return u.IsInWorld() ? u.GetMap()->GetCreature(guid) : NULL; -} - -Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, uint64 guid) -{ - Corpse* ret = GetObjectInWorld(guid, (Corpse*)NULL); - - if (!ret) - return NULL; - - if (ret->GetMapId() != u.GetMapId()) - return NULL; - - if (ret->GetInstanceId() != u.GetInstanceId()) - return NULL; - - return ret; -} - -WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, uint64 guid) -{ - switch (GUID_HIPART(guid)) - { - case HIGHGUID_PLAYER: return FindPlayer(guid); - case HIGHGUID_GAMEOBJECT: return p.GetMap()->GetGameObject(guid); - case HIGHGUID_VEHICLE: - case HIGHGUID_UNIT: return p.GetMap()->GetCreature(guid); - case HIGHGUID_PET: return GetPet(guid); - case HIGHGUID_DYNAMICOBJECT: return p.GetMap()->GetDynamicObject(guid); - case HIGHGUID_TRANSPORT: return NULL; - case HIGHGUID_CORPSE: return GetCorpse(p,guid); - case HIGHGUID_MO_TRANSPORT: return NULL; - default: return NULL; - } -} - -Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, uint64 guid, uint32 typemask) -{ - switch (GUID_HIPART(guid)) - { - case HIGHGUID_ITEM: - if (typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER) - return ((Player const&)p).GetItemByGuid(guid); - break; - case HIGHGUID_PLAYER: - if (typemask & TYPEMASK_PLAYER) - return FindPlayer(guid); - break; - case HIGHGUID_GAMEOBJECT: - if (typemask & TYPEMASK_GAMEOBJECT) - return p.GetMap()->GetGameObject(guid); - break; - case HIGHGUID_UNIT: - case HIGHGUID_VEHICLE: - if (typemask & TYPEMASK_UNIT) - return p.GetMap()->GetCreature(guid); - break; - case HIGHGUID_PET: - if (typemask & TYPEMASK_UNIT) - return GetPet(guid); - break; - case HIGHGUID_DYNAMICOBJECT: - if (typemask & TYPEMASK_DYNAMICOBJECT) - return p.GetMap()->GetDynamicObject(guid); - break; - case HIGHGUID_TRANSPORT: - case HIGHGUID_CORPSE: - case HIGHGUID_MO_TRANSPORT: - break; - } - - return NULL; -} - -Player* ObjectAccessor::FindPlayer(uint64 guid) -{ - Player* plr = GetObjectInWorld(guid, (Player*)NULL); - if (!plr || !plr->IsInWorld()) - return NULL; - - return plr; -} - -Player* ObjectAccessor::FindPlayerByName(const char* name) -{ - Guard guard(*HashMapHolder::GetLock()); - HashMapHolder::MapType& m = HashMapHolder::GetContainer(); - for (HashMapHolder::MapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (iter->second->IsInWorld() && strcmp(name, iter->second->GetName()) == 0) - return iter->second; - - return NULL; -} - -void ObjectAccessor::SaveAllPlayers() -{ - Guard guard(*HashMapHolder::GetLock()); - HashMapHolder::MapType& m = HashMapHolder::GetContainer(); - for (HashMapHolder::MapType::iterator itr = m.begin(); itr != m.end(); ++itr) - itr->second->SaveToDB(); -} - -Pet* ObjectAccessor::GetPet(uint64 guid) -{ - return GetObjectInWorld(guid, (Pet*)NULL); -} - -Corpse* ObjectAccessor::GetCorpseForPlayerGUID(uint64 guid) -{ - Guard guard(i_corpseGuard); - - Player2CorpsesMapType::iterator iter = i_player2corpse.find(guid); - if (iter == i_player2corpse.end()) - return NULL; - - assert(iter->second->GetType() != CORPSE_BONES); - - return iter->second; -} - -void ObjectAccessor::RemoveCorpse(Corpse* corpse) -{ - assert(corpse && corpse->GetType() != CORPSE_BONES); - - if (corpse->FindMap()) - corpse->FindMap()->Remove(corpse, false); - else - corpse->RemoveFromWorld(); - - // Critical section - { - Guard guard(i_corpseGuard); - - Player2CorpsesMapType::iterator iter = i_player2corpse.find(corpse->GetOwnerGUID()); - if (iter == i_player2corpse.end()) // TODO: Fix this - return; - - // build mapid*cellid -> guid_set map - CellPair cell_pair = Trinity::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY()); - uint32 cell_id = (cell_pair.y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - objmgr.DeleteCorpseCellData(corpse->GetMapId(), cell_id, corpse->GetOwnerGUID()); - - i_player2corpse.erase(iter); - } -} - -void ObjectAccessor::AddCorpse(Corpse* corpse) -{ - assert(corpse && corpse->GetType() != CORPSE_BONES); - - // Critical section - { - Guard guard(i_corpseGuard); - - assert(i_player2corpse.find(corpse->GetOwnerGUID()) == i_player2corpse.end()); - i_player2corpse[corpse->GetOwnerGUID()] = corpse; - - // build mapid*cellid -> guid_set map - CellPair cell_pair = Trinity::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY()); - uint32 cell_id = (cell_pair.y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - objmgr.AddCorpseCellData(corpse->GetMapId(), cell_id, corpse->GetOwnerGUID(), corpse->GetInstanceId()); - } -} - -void ObjectAccessor::AddCorpsesToGrid(GridPair const& gridpair, GridType& grid, Map* map) -{ - Guard guard(i_corpseGuard); - - for (Player2CorpsesMapType::iterator iter = i_player2corpse.begin(); iter != i_player2corpse.end(); ++iter) - { - if (iter->second->GetGrid() == gridpair) - { - // verify, if the corpse in our instance (add only corpses which are) - if (map->Instanceable()) - { - if (iter->second->GetInstanceId() == map->GetInstanceId()) - grid.AddWorldObject(iter->second); - } - else - grid.AddWorldObject(iter->second); - } - } -} - -Corpse* ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool /*insignia*/) -{ - Corpse* corpse = GetCorpseForPlayerGUID(player_guid); - if (!corpse) - { - //in fact this function is called from several places - //even when player doesn't have a corpse, not an error - // TODO: really, now... - //sLog.outError("Try remove corpse that not in map for GUID %ul", player_guid); - return NULL; - } - - DEBUG_LOG("Deleting Corpse and spawned bones."); - - //Map* map = corpse->FindMap(); - - // remove corpse from player_guid -> corpse map - RemoveCorpse(corpse); - - // done in removecorpse - // remove resurrectable corpse from grid object registry (loaded state checked into call) - // do not load the map if it's not loaded - //Map *map = MapManager::Instance().FindMap(corpse->GetMapId(), corpse->GetInstanceId()); - //if (map) - // map->Remove(corpse, false); - - // remove corpse from DB - corpse->DeleteFromDB(); - - // we don't want bones to save some cpu.. :) - delete corpse; - return NULL; - - /* - Corpse* bones = NULL; - // create the bones only if the map and the grid is loaded at the corpse's location - // ignore bones creating option in case insignia - if (map && (insignia || - (map->IsBattleGroundOrArena() ? sWorld.getConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld.getConfig(CONFIG_DEATH_BONES_WORLD))) && - !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) - { - // Create bones, don't change Corpse - bones = new Corpse; - bones->Create(corpse->GetGUIDLow(), map); - - for (int i = 3; i < CORPSE_END; ++i) // don't overwrite guid and object type - bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); - - bones->SetGrid(corpse->GetGrid()); - // bones->m_time = m_time; // don't overwrite time - // bones->m_inWorld = m_inWorld; // don't overwrite in-world state - // bones->m_type = m_type; // don't overwrite type - bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); - bones->SetPhaseMask(corpse->GetPhaseMask(), false); - - bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); - bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0); - - for (int i = 0; i < EQUIPMENT_SLOT_END; ++i) - { - if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) - bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); - } - - // add bones in grid store if grid loaded where corpse placed - map->Add(bones); - } - - // all references to the corpse should be removed at this point - delete corpse; - - return bones; - */ -} - -void ObjectAccessor::Update(uint32 /*diff*/) -{ - UpdateDataMapType update_players; - - // Critical section - { - Guard guard(i_updateGuard); - - while (!i_objects.empty()) - { - Object* obj = *i_objects.begin(); - assert(obj && obj->IsInWorld()); - i_objects.erase(i_objects.begin()); - obj->BuildUpdate(update_players); - } - } - - WorldPacket packet; // here we allocate a std::vector with a size of 0x10000 - for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) - { - iter->second.BuildPacket(&packet); - iter->first->GetSession()->SendPacket(&packet); - packet.clear(); // clean the string - } -} - -/// Define the static members of HashMapHolder - -template UNORDERED_MAP< uint64, T* > HashMapHolder::m_objectMap; -template ACE_Thread_Mutex HashMapHolder::i_lock; - -/// Global definitions for the hashmap storage - -template class HashMapHolder; -template class HashMapHolder; -template class HashMapHolder; -template class HashMapHolder; -template class HashMapHolder; -template class HashMapHolder; - -template Player* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/); -template Pet* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/); -template Creature* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/); -template Corpse* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/); -template GameObject* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/); -template DynamicObject* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, DynamicObject* /*fake*/); diff --git a/src/server/game/Entities/Object/ObjectAccessor.h b/src/server/game/Entities/Object/ObjectAccessor.h deleted file mode 100644 index 8e64eb48fa0..00000000000 --- a/src/server/game/Entities/Object/ObjectAccessor.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_OBJECTACCESSOR_H -#define TRINITY_OBJECTACCESSOR_H - -#include "Platform/Define.h" -#include "Policies/Singleton.h" -#include -#include "Utilities/UnorderedMap.h" -#include "Policies/ThreadingModel.h" - -#include "UpdateData.h" - -#include "GridDefines.h" -#include "Object.h" -#include "Player.h" - -#include - -class Creature; -class Corpse; -class Unit; -class GameObject; -class DynamicObject; -class WorldObject; -class Map; - -template -class HashMapHolder -{ - public: - - typedef UNORDERED_MAP MapType; - typedef ACE_Thread_Mutex LockType; - typedef Trinity::GeneralLock Guard; - - static void Insert(T* o) - { - Guard guard(i_lock); - m_objectMap[o->GetGUID()] = o; - } - - static void Remove(T* o) - { - Guard guard(i_lock); - m_objectMap.erase(o->GetGUID()); - } - - static T* Find(uint64 guid) - { - Guard guard(i_lock); - typename MapType::iterator itr = m_objectMap.find(guid); - return (itr != m_objectMap.end()) ? itr->second : NULL; - } - - static MapType& GetContainer() { return m_objectMap; } - - static LockType* GetLock() { return &i_lock; } - - private: - - //Non instanceable only static - HashMapHolder() {} - - static LockType i_lock; - static MapType m_objectMap; -}; - -class ObjectAccessor : public Trinity::Singleton > -{ - friend class Trinity::OperatorNew; - ObjectAccessor(); - ~ObjectAccessor(); - ObjectAccessor(const ObjectAccessor&); - ObjectAccessor& operator=(const ObjectAccessor&); - - public: - - typedef UNORDERED_MAP Player2CorpsesMapType; - typedef UNORDERED_MAP::value_type UpdateDataValueType; - - template static T* GetObjectInWorld(uint64 guid, T* /*fake*/) - { - return HashMapHolder::Find(guid); - } - - static Unit* GetObjectInWorld(uint64 guid, Unit* /*fake*/) - { - if (!guid) - return NULL; - - if (IS_PLAYER_GUID(guid)) - { - Unit* u = (Unit*)HashMapHolder::Find(guid); - if (!u || !u->IsInWorld()) - return NULL; - - return u; - } - - if (IS_PET_GUID(guid)) - return (Unit*)HashMapHolder::Find(guid); - - return (Unit*)HashMapHolder::Find(guid); - } - - static Unit* GetUnitInOrOutOfWorld(uint64 guid, Unit* /*fake*/) - { - if (!guid) - return NULL; - - if (IS_PLAYER_GUID(guid)) - { - Unit* u = (Unit*)HashMapHolder::Find(guid); - if (!u) - return NULL; - - return u; - } - - // Other object types than player are unloaded while out of world - return GetObjectInWorld(guid, (Unit*)NULL); - } - - template static T* GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, T* /*fake*/) - { - T* obj = HashMapHolder::Find(guid); - if (!obj || obj->GetMapId() != mapid) - return NULL; - - CellPair p = Trinity::ComputeCellPair(x, y); - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("ObjectAccessor::GetObjectInWorld: invalid coordinates supplied X:%f Y:%f grid cell [%u:%u]", x, y, p.x_coord, p.y_coord); - return NULL; - } - - CellPair q = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - if (q.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || q.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("ObjectAccessor::GetObjecInWorld: object (GUID: %u TypeId: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), q.x_coord, q.y_coord); - return NULL; - } - - int32 dx = int32(p.x_coord) - int32(q.x_coord); - int32 dy = int32(p.y_coord) - int32(q.y_coord); - - if (dx > -2 && dx < 2 && dy > -2 && dy < 2) - return obj; - else - return NULL; - } - - static WorldObject* GetWorldObject(WorldObject const&, uint64); - static Object* GetObjectByTypeMask(WorldObject const&, uint64, uint32 typemask); - static Creature* GetCreatureOrPetOrVehicle(WorldObject const&, uint64); - static Unit* GetUnit(WorldObject const&, uint64 guid) { return GetObjectInWorld(guid, (Unit*)NULL); } - static Unit* GetUnitInOrOutOfWorld(WorldObject const&, uint64 guid) { return GetUnitInOrOutOfWorld(guid, (Unit*)NULL); } - static Pet* GetPet(Unit const&, uint64 guid) { return GetPet(guid); } - static Player* GetPlayer(Unit const&, uint64 guid) { return FindPlayer(guid); } - static Corpse* GetCorpse(WorldObject const& u, uint64 guid); - static Pet* GetPet(uint64 guid); - static Player* FindPlayer(uint64); - - Player* FindPlayerByName(const char* name) ; - - // when using this, you must use the hashmapholder's lock - HashMapHolder::MapType& GetPlayers() - { - return HashMapHolder::GetContainer(); - } - - // when using this, you must use the hashmapholder's lock - HashMapHolder::MapType& GetCreatures() - { - return HashMapHolder::GetContainer(); - } - - // when using this, you must use the hashmapholder's lock - HashMapHolder::MapType& GetGameObjects() - { - return HashMapHolder::GetContainer(); - } - - template void AddObject(T* object) - { - HashMapHolder::Insert(object); - } - - template void RemoveObject(T* object) - { - HashMapHolder::Remove(object); - } - - void RemoveObject(Player* pl) - { - HashMapHolder::Remove(pl); - RemoveUpdateObject((Object*)pl); - } - - void SaveAllPlayers(); - - void AddUpdateObject(Object* obj) - { - Guard guard(i_updateGuard); - i_objects.insert(obj); - } - - void RemoveUpdateObject(Object* obj) - { - Guard guard(i_updateGuard); - i_objects.erase(obj); - } - - void Update(uint32 diff); - - Corpse* GetCorpseForPlayerGUID(uint64 guid); - void RemoveCorpse(Corpse* corpse); - void AddCorpse(Corpse* corpse); - void AddCorpsesToGrid(GridPair const& gridpair, GridType& grid, Map* map); - Corpse* ConvertCorpseForPlayer(uint64 player_guid, bool insignia = false); - - typedef ACE_Thread_Mutex LockType; - typedef Trinity::GeneralLock Guard; - - private: - - Player2CorpsesMapType i_player2corpse; - - static void _buildChangeObjectForPlayer(WorldObject*, UpdateDataMapType&); - static void _buildPacket(Player*, Object*, UpdateDataMapType&); - void _update(); - - std::set i_objects; - - LockType i_updateGuard; - LockType i_corpseGuard; -}; -#endif diff --git a/src/server/game/Entities/Object/ObjectMgr.cpp b/src/server/game/Entities/Object/ObjectMgr.cpp deleted file mode 100644 index ce86c2a4e77..00000000000 --- a/src/server/game/Entities/Object/ObjectMgr.cpp +++ /dev/null @@ -1,8724 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "Database/SQLStorage.h" -#include "Database/SQLStorageImpl.h" -#include "Policies/SingletonImp.h" - -#include "Log.h" -#include "MapManager.h" -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "UpdateMask.h" -#include "World.h" -#include "Group.h" -#include "Guild.h" -#include "ArenaTeam.h" -#include "Transports.h" -#include "ProgressBar.h" -#include "Language.h" -#include "GameEventMgr.h" -#include "Spell.h" -#include "Chat.h" -#include "AccountMgr.h" -#include "InstanceSaveMgr.h" -#include "SpellAuras.h" -#include "Util.h" -#include "WaypointManager.h" -#include "GossipDef.h" -#include "Vehicle.h" -#include "AchievementMgr.h" - -INSTANTIATE_SINGLETON_1(ObjectMgr); - -ScriptMapMap sQuestEndScripts; -ScriptMapMap sQuestStartScripts; -ScriptMapMap sSpellScripts; -ScriptMapMap sGameObjectScripts; -ScriptMapMap sEventScripts; -ScriptMapMap sGossipScripts; -ScriptMapMap sWaypointScripts; - -bool normalizePlayerName(std::string& name) -{ - if (name.empty()) - return false; - - wchar_t wstr_buf[MAX_INTERNAL_PLAYER_NAME+1]; - size_t wstr_len = MAX_INTERNAL_PLAYER_NAME; - - if (!Utf8toWStr(name,&wstr_buf[0],wstr_len)) - return false; - - wstr_buf[0] = wcharToUpper(wstr_buf[0]); - for (size_t i = 1; i < wstr_len; ++i) - wstr_buf[i] = wcharToLower(wstr_buf[i]); - - if (!WStrToUtf8(wstr_buf,wstr_len,name)) - return false; - - return true; -} - -LanguageDesc lang_description[LANGUAGES_COUNT] = -{ - { LANG_ADDON, 0, 0 }, - { LANG_UNIVERSAL, 0, 0 }, - { LANG_ORCISH, 669, SKILL_LANG_ORCISH }, - { LANG_DARNASSIAN, 671, SKILL_LANG_DARNASSIAN }, - { LANG_TAURAHE, 670, SKILL_LANG_TAURAHE }, - { LANG_DWARVISH, 672, SKILL_LANG_DWARVEN }, - { LANG_COMMON, 668, SKILL_LANG_COMMON }, - { LANG_DEMONIC, 815, SKILL_LANG_DEMON_TONGUE }, - { LANG_TITAN, 816, SKILL_LANG_TITAN }, - { LANG_THALASSIAN, 813, SKILL_LANG_THALASSIAN }, - { LANG_DRACONIC, 814, SKILL_LANG_DRACONIC }, - { LANG_KALIMAG, 817, SKILL_LANG_OLD_TONGUE }, - { LANG_GNOMISH, 7340, SKILL_LANG_GNOMISH }, - { LANG_TROLL, 7341, SKILL_LANG_TROLL }, - { LANG_GUTTERSPEAK, 17737, SKILL_LANG_GUTTERSPEAK }, - { LANG_DRAENEI, 29932, SKILL_LANG_DRAENEI }, - { LANG_ZOMBIE, 0, 0 }, - { LANG_GNOMISH_BINARY, 0, 0 }, - { LANG_GOBLIN_BINARY, 0, 0 } -}; - -LanguageDesc const* GetLanguageDescByID(uint32 lang) -{ - for (uint8 i = 0; i < LANGUAGES_COUNT; ++i) - { - if (uint32(lang_description[i].lang_id) == lang) - return &lang_description[i]; - } - - return NULL; -} - -bool SpellClickInfo::IsFitToRequirements(Player const* player, Creature const * clickNpc) const -{ - if (questStart) - { - // not in expected required quest state - if (!player || ((!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart))) - return false; - } - - if (questEnd) - { - // not in expected forbidden quest state - if (!player || player->GetQuestRewardStatus(questEnd)) - return false; - } - - if (auraRequired) - if (!player->HasAura(auraRequired)) - return false; - - if (auraForbidden) - if (player->HasAura(auraForbidden)) - return false; - - Unit const * summoner = NULL; - // Check summoners for party - if (clickNpc->isSummon()) - summoner = clickNpc->ToTempSummon()->GetSummoner(); - if (!summoner) - summoner = clickNpc; - - switch (userType) - { - case SPELL_CLICK_USER_FRIEND: - if (!player->IsFriendlyTo(summoner)) - return false; - break; - case SPELL_CLICK_USER_RAID: - if (!player->IsInRaidWith(summoner)) - return false; - break; - case SPELL_CLICK_USER_PARTY: - if (!player->IsInPartyWith(summoner)) - return false; - break; - } - - return true; -} - -ObjectMgr::ObjectMgr() -{ - m_hiCharGuid = 1; - m_hiCreatureGuid = 1; - m_hiPetGuid = 1; - m_hiVehicleGuid = 1; - m_hiItemGuid = 1; - m_hiGoGuid = 1; - m_hiDoGuid = 1; - m_hiCorpseGuid = 1; - m_hiPetNumber = 1; - m_hiGroupGuid = 1; - m_ItemTextId = 1; - m_mailid = 1; - m_equipmentSetGuid = 1; - m_guildId = 1; - m_arenaTeamId = 1; - m_auctionid = 1; -} - -ObjectMgr::~ObjectMgr() -{ - for (QuestMap::iterator i = mQuestTemplates.begin(); i != mQuestTemplates.end(); ++i) - delete i->second; - - for (PetLevelInfoMap::iterator i = petInfo.begin(); i != petInfo.end(); ++i) - delete[] i->second; - - // free only if loaded - for (int class_ = 0; class_ < MAX_CLASSES; ++class_) - delete[] playerClassInfo[class_].levelInfo; - - for (int race = 0; race < MAX_RACES; ++race) - for (int class_ = 0; class_ < MAX_CLASSES; ++class_) - delete[] playerInfo[race][class_].levelInfo; - - // free group and guild objects - for (GroupSet::iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr) - delete (*itr); - - for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr) - delete itr->second; - - for (ArenaTeamMap::iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) - delete itr->second; - - for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) - itr->second.Clear(); - - for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr) - itr->second.Clear(); -} - -Group * ObjectMgr::GetGroupByGUID(const uint64 &guid) const -{ - for (GroupSet::const_iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr) - if ((*itr)->GetGUID() == guid) - return *itr; - - return NULL; -} - -Guild * ObjectMgr::GetGuildById(uint32 GuildId) const -{ - GuildMap::const_iterator itr = mGuildMap.find(GuildId); - if (itr != mGuildMap.end()) - return itr->second; - - return NULL; -} - -Guild * ObjectMgr::GetGuildByName(const std::string& guildname) const -{ - std::string search = guildname; - std::transform(search.begin(), search.end(), search.begin(), ::toupper); - for (GuildMap::const_iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr) - { - std::string gname = itr->second->GetName(); - std::transform(gname.begin(), gname.end(), gname.begin(), ::toupper); - if (search == gname) - return itr->second; - } - return NULL; -} - -std::string ObjectMgr::GetGuildNameById(uint32 GuildId) const -{ - GuildMap::const_iterator itr = mGuildMap.find(GuildId); - if (itr != mGuildMap.end()) - return itr->second->GetName(); - - return ""; -} - -Guild* ObjectMgr::GetGuildByLeader(const uint64 &guid) const -{ - for (GuildMap::const_iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr) - if (itr->second->GetLeader() == guid) - return itr->second; - - return NULL; -} - -void ObjectMgr::AddGuild(Guild* guild) -{ - mGuildMap[guild->GetId()] = guild; -} - -void ObjectMgr::RemoveGuild(uint32 Id) -{ - mGuildMap.erase(Id); -} - -ArenaTeam* ObjectMgr::GetArenaTeamById(uint32 arenateamid) const -{ - ArenaTeamMap::const_iterator itr = mArenaTeamMap.find(arenateamid); - if (itr != mArenaTeamMap.end()) - return itr->second; - - return NULL; -} - -ArenaTeam* ObjectMgr::GetArenaTeamByName(const std::string& arenateamname) const -{ - std::string search = arenateamname; - std::transform(search.begin(), search.end(), search.begin(), ::toupper); - for (ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) - { - std::string teamname = itr->second->GetName(); - std::transform(teamname.begin(), teamname.end(), teamname.begin(), ::toupper); - if (search == teamname) - return itr->second; - } - return NULL; -} - -ArenaTeam* ObjectMgr::GetArenaTeamByCaptain(uint64 const& guid) const -{ - for (ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) - if (itr->second->GetCaptain() == guid) - return itr->second; - - return NULL; -} - -void ObjectMgr::AddArenaTeam(ArenaTeam* arenaTeam) -{ - mArenaTeamMap[arenaTeam->GetId()] = arenaTeam; -} - -void ObjectMgr::RemoveArenaTeam(uint32 Id) -{ - mArenaTeamMap.erase(Id); -} - -CreatureInfo const* ObjectMgr::GetCreatureTemplate(uint32 id) -{ - return sCreatureStorage.LookupEntry(id); -} - -void ObjectMgr::LoadCreatureLocales() -{ - mCreatureLocaleMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,name_loc1,subname_loc1,name_loc2,subname_loc2,name_loc3,subname_loc3,name_loc4,subname_loc4,name_loc5,subname_loc5,name_loc6,subname_loc6,name_loc7,subname_loc7,name_loc8,subname_loc8 FROM locales_creature"); - - if (!result) - return; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 entry = fields[0].GetUInt32(); - - CreatureLocale& data = mCreatureLocaleMap[entry]; - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[1+2*(i-1)].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Name.size() <= idx) - data.Name.resize(idx+1); - - data.Name[idx] = str; - } - } - str = fields[1+2*(i-1)+1].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.SubName.size() <= idx) - data.SubName.resize(idx+1); - - data.SubName[idx] = str; - } - } - } - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu creature locale strings", (unsigned long)mCreatureLocaleMap.size()); -} - -void ObjectMgr::LoadGossipMenuItemsLocales() -{ - mGossipMenuItemsLocaleMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT menu_id,id," - "option_text_loc1,box_text_loc1,option_text_loc2,box_text_loc2," - "option_text_loc3,box_text_loc3,option_text_loc4,box_text_loc4," - "option_text_loc5,box_text_loc5,option_text_loc6,box_text_loc6," - "option_text_loc7,box_text_loc7,option_text_loc8,box_text_loc8 " - "FROM locales_gossip_menu_option"); - - if (!result) - return; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint16 menuId = fields[0].GetUInt16(); - uint16 id = fields[1].GetUInt16(); - - GossipMenuItemsLocale& data = mGossipMenuItemsLocaleMap[MAKE_PAIR32(menuId,id)]; - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[2+2*(i-1)].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.OptionText.size() <= idx) - data.OptionText.resize(idx+1); - - data.OptionText[idx] = str; - } - } - str = fields[2+2*(i-1)+1].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.BoxText.size() <= idx) - data.BoxText.resize(idx+1); - - data.BoxText[idx] = str; - } - } - } - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu gossip_menu_option locale strings", (unsigned long)mGossipMenuItemsLocaleMap.size()); -} - -void ObjectMgr::LoadPointOfInterestLocales() -{ - mPointOfInterestLocaleMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,icon_name_loc1,icon_name_loc2,icon_name_loc3,icon_name_loc4,icon_name_loc5,icon_name_loc6,icon_name_loc7,icon_name_loc8 FROM locales_points_of_interest"); - - if (!result) - return; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 entry = fields[0].GetUInt32(); - - PointOfInterestLocale& data = mPointOfInterestLocaleMap[entry]; - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[i].GetCppString(); - if (str.empty()) - continue; - - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.IconName.size() <= idx) - data.IconName.resize(idx+1); - - data.IconName[idx] = str; - } - } - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu points_of_interest locale strings", (unsigned long)mPointOfInterestLocaleMap.size()); -} - -struct SQLCreatureLoader : public SQLStorageLoaderBase -{ - template - void convert_from_str(uint32 /*field_pos*/, char *src, D &dst) - { - dst = D(objmgr.GetScriptId(src)); - } -}; - -void ObjectMgr::LoadCreatureTemplates() -{ - SQLCreatureLoader loader; - loader.Load(sCreatureStorage); - - sLog.outString(">> Loaded %u creature definitions", sCreatureStorage.RecordCount); - sLog.outString(); - - // check data correctness - for (uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i) - { - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i); - CheckCreatureTemplate(cInfo); - } -} - -void ObjectMgr::CheckCreatureTemplate(CreatureInfo const* cInfo) -{ - if (!cInfo) - return; - - bool ok = true; // bool to allow continue outside this loop - for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) - { - if (!cInfo->DifficultyEntry[diff]) - continue; - ok = false; // will be set to true at the end of this loop again - - CreatureInfo const* difficultyInfo = GetCreatureTemplate(cInfo->DifficultyEntry[diff]); - if (!difficultyInfo) - { - sLog.outErrorDb("Creature (Entry: %u) have `difficulty_entry_%u`=%u but creature entry %u not exist.", - cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff]); - continue; - } - - if (difficultyEntries[diff].find(cInfo->Entry) != difficultyEntries[diff].end()) - { - sLog.outErrorDb("Creature (Entry: %u) listed as difficulty %u but have value in `difficulty_entry_1`.", cInfo->Entry, diff + 1); - continue; - } - - bool ok2 = true; - for (uint32 diff2 = 0; diff2 < MAX_DIFFICULTY - 1 && ok2; ++diff2) - { - ok2 = false; - if (difficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != difficultyEntries[diff2].end()) - { - sLog.outErrorDb("Creature (Entry: %u) already listed as difficulty %u for another entry.", cInfo->DifficultyEntry[diff], diff2 + 1); - continue; - } - - if (hasDifficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != hasDifficultyEntries[diff2].end()) - { - sLog.outErrorDb("Creature (Entry: %u) have `difficulty_entry_%u`=%u but creature entry %u have difficulty %u entry also.", - cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff], diff2 + 1); - continue; - } - ok2 = true; - } - if (!ok2) - continue; - - if (cInfo->unit_class != difficultyInfo->unit_class) - { - sLog.outErrorDb("Creature (Entry: %u, class %u) has different `unit_class` in difficulty %u mode (Entry: %u, class %u).", - cInfo->Entry, cInfo->unit_class, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->unit_class); - continue; - } - - if (cInfo->npcflag != difficultyInfo->npcflag) - { - sLog.outErrorDb("Creature (Entry: %u) has different `npcflag` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); - continue; - } - - if (cInfo->trainer_class != difficultyInfo->trainer_class) - { - sLog.outErrorDb("Creature (Entry: %u) has different `trainer_class` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); - continue; - } - - if (cInfo->trainer_race != difficultyInfo->trainer_race) - { - sLog.outErrorDb("Creature (Entry: %u) has different `trainer_race` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); - continue; - } - - if (cInfo->trainer_type != difficultyInfo->trainer_type) - { - sLog.outErrorDb("Creature (Entry: %u) has different `trainer_type` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); - continue; - } - - if (cInfo->trainer_spell != difficultyInfo->trainer_spell) - { - sLog.outErrorDb("Creature (Entry: %u) has different `trainer_spell` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); - continue; - } - - if (difficultyInfo->AIName && *difficultyInfo->AIName) - { - sLog.outErrorDb("Difficulty %u mode creature (Entry: %u) has `AIName`, but in any case will used difficulty 0 mode creature (Entry: %u) AIName.", - diff, cInfo->DifficultyEntry[diff], cInfo->Entry); - continue; - } - - if (difficultyInfo->ScriptID) - { - sLog.outErrorDb("Difficulty %u mode creature (Entry: %u) has `ScriptName`, but in any case will used difficulty 0 mode creature (Entry: %u) ScriptName.", - diff, cInfo->DifficultyEntry[diff], cInfo->Entry); - continue; - } - - hasDifficultyEntries[diff].insert(cInfo->Entry); - difficultyEntries[diff].insert(cInfo->DifficultyEntry[diff]); - ok = true; - } - - FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_A); - if (!factionTemplate) - sLog.outErrorDb("Creature (Entry: %u) has non-existing faction_A template (%u)", cInfo->Entry, cInfo->faction_A); - - factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_H); - if (!factionTemplate) - sLog.outErrorDb("Creature (Entry: %u) has non-existing faction_H template (%u)", cInfo->Entry, cInfo->faction_H); - - // used later for scale - CreatureDisplayInfoEntry const* displayScaleEntry = NULL; - - if (cInfo->Modelid1) - { - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid1); - if (!displayEntry) - { - sLog.outErrorDb("Creature (Entry: %u) has non-existing Modelid1 id (%u), can crash client", cInfo->Entry, cInfo->Modelid1); - const_cast(cInfo)->Modelid1 = 0; - } - else if (!displayScaleEntry) - displayScaleEntry = displayEntry; - - CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->Modelid1); - if (!minfo) - sLog.outErrorDb("Creature (Entry: %u) not has model data for Modelid1 (%u)", cInfo->Entry, cInfo->Modelid1); - } - - if (cInfo->Modelid2) - { - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid2); - if (!displayEntry) - { - sLog.outErrorDb("Creature (Entry: %u) has non-existing Modelid2 id (%u), can crash client", cInfo->Entry, cInfo->Modelid2); - const_cast(cInfo)->Modelid2 = 0; - } - else if (!displayScaleEntry) - displayScaleEntry = displayEntry; - - CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->Modelid2); - if (!minfo) - sLog.outErrorDb("Creature (Entry: %u) not has model data for Modelid2 (%u)", cInfo->Entry, cInfo->Modelid2); - } - - if (cInfo->Modelid3) - { - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid3); - if (!displayEntry) - { - sLog.outErrorDb("Creature (Entry: %u) has non-existing Modelid3 id (%u), can crash client", cInfo->Entry, cInfo->Modelid3); - const_cast(cInfo)->Modelid3 = 0; - } - else if (!displayScaleEntry) - displayScaleEntry = displayEntry; - - CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->Modelid3); - if (!minfo) - sLog.outErrorDb("Creature (Entry: %u) not has model data for Modelid3 (%u)", cInfo->Entry, cInfo->Modelid3); - } - - if (cInfo->Modelid4) - { - CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid4); - if (!displayEntry) - { - sLog.outErrorDb("Creature (Entry: %u) has non-existing Modelid4 id (%u), can crash client", cInfo->Entry, cInfo->Modelid4); - const_cast(cInfo)->Modelid4 = 0; - } - else if (!displayScaleEntry) - displayScaleEntry = displayEntry; - - CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->Modelid4); - if (!minfo) - sLog.outErrorDb("Creature (Entry: %u) not has model data for Modelid4 (%u)", cInfo->Entry, cInfo->Modelid4); - } - - if (!displayScaleEntry) - sLog.outErrorDb("Creature (Entry: %u) not has any existed display id in Modelid1/Modelid2/Modelid3/Modelid4", cInfo->Entry); - - for (int k = 0; k < MAX_KILL_CREDIT; ++k) - { - if (cInfo->KillCredit[k]) - { - if (!GetCreatureTemplate(cInfo->KillCredit[k])) - { - sLog.outErrorDb("Creature (Entry: %u) has not existed creature entry in `KillCredit%d` (%u)",cInfo->Entry,k+1,cInfo->KillCredit[k]); - const_cast(cInfo)->KillCredit[k] = 0; - } - } - } - - if (!cInfo->unit_class || ((1 << (cInfo->unit_class-1)) & CLASSMASK_ALL_CREATURES) == 0) - { - sLog.outErrorDb("Creature (Entry: %u) has invalid unit_class(%u) for creature_template. Set to 1 (UNIT_CLASS_WARRIOR).", cInfo->Entry, cInfo->unit_class); - const_cast(cInfo)->unit_class = UNIT_CLASS_WARRIOR; - } - - if (cInfo->dmgschool >= MAX_SPELL_SCHOOL) - { - sLog.outErrorDb("Creature (Entry: %u) has invalid spell school value (%u) in `dmgschool`",cInfo->Entry,cInfo->dmgschool); - const_cast(cInfo)->dmgschool = SPELL_SCHOOL_NORMAL; - } - - if (cInfo->baseattacktime == 0) - const_cast(cInfo)->baseattacktime = BASE_ATTACK_TIME; - - if (cInfo->rangeattacktime == 0) - const_cast(cInfo)->rangeattacktime = BASE_ATTACK_TIME; - - if (cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK) - { - sLog.outErrorDb("Creature (Entry: %u) has dynamic flag UNIT_NPC_FLAG_SPELLCLICK (%u) set, it expect to be set by code base at `npc_spellclick_spells` content.",cInfo->Entry,UNIT_NPC_FLAG_SPELLCLICK); - const_cast(cInfo)->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK; - } - - if ((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE) - sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type); - - if (cInfo->type && !sCreatureTypeStore.LookupEntry(cInfo->type)) - { - sLog.outErrorDb("Creature (Entry: %u) has invalid creature type (%u) in `type`",cInfo->Entry,cInfo->type); - const_cast(cInfo)->type = CREATURE_TYPE_HUMANOID; - } - - // must exist or used hidden but used in data horse case - if (cInfo->family && !sCreatureFamilyStore.LookupEntry(cInfo->family) && cInfo->family != CREATURE_FAMILY_HORSE_CUSTOM) - { - sLog.outErrorDb("Creature (Entry: %u) has invalid creature family (%u) in `family`",cInfo->Entry,cInfo->family); - const_cast(cInfo)->family = 0; - } - - if (cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE) - { - sLog.outErrorDb("Creature (Entry: %u) has wrong value (%u) in `InhabitType`, creature will not correctly walk/swim/fly",cInfo->Entry,cInfo->InhabitType); - const_cast(cInfo)->InhabitType = INHABIT_ANYWHERE; - } - - if (cInfo->VehicleId) - { - VehicleEntry const* vehId = sVehicleStore.LookupEntry(cInfo->VehicleId); - if (!vehId) - sLog.outErrorDb("Creature (Entry: %u) has a non-existing VehicleId (%u). This *WILL* cause the client to freeze!", cInfo->Entry, cInfo->VehicleId); - } - - if (cInfo->PetSpellDataId) - { - CreatureSpellDataEntry const* spellDataId = sCreatureSpellDataStore.LookupEntry(cInfo->PetSpellDataId); - if (!spellDataId) - sLog.outErrorDb("Creature (Entry: %u) has non-existing PetSpellDataId (%u)", cInfo->Entry, cInfo->PetSpellDataId); - } - - for (uint8 j = 0; j < CREATURE_MAX_SPELLS; ++j) - { - if (cInfo->spells[j] && !sSpellStore.LookupEntry(cInfo->spells[j])) - { - sLog.outErrorDb("Creature (Entry: %u) has non-existing Spell%d (%u), set to 0", cInfo->Entry, j+1,cInfo->spells[j]); - const_cast(cInfo)->spells[j] = 0; - } - } - - if (cInfo->MovementType >= MAX_DB_MOTION_TYPE) - { - sLog.outErrorDb("Creature (Entry: %u) has wrong movement generator type (%u), ignore and set to IDLE.",cInfo->Entry,cInfo->MovementType); - const_cast(cInfo)->MovementType = IDLE_MOTION_TYPE; - } - - if (cInfo->equipmentId > 0) // 0 no equipment - { - if (!GetEquipmentInfo(cInfo->equipmentId)) - { - sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", cInfo->Entry, cInfo->equipmentId); - const_cast(cInfo)->equipmentId = 0; - } - } - - /// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc - if (cInfo->scale <= 0.0f) - { - if (displayScaleEntry) - const_cast(cInfo)->scale = displayScaleEntry->scale; - else - const_cast(cInfo)->scale = 1.0f; - } - - if (cInfo->expansion > (MAX_CREATURE_BASE_HP - 1)) - { - sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with expansion %u ignore and set to NULL.", cInfo->expansion); - const_cast(cInfo)->expansion = 0; - } - - const_cast(cInfo)->dmg_multiplier *= Creature::_GetDamageMod(cInfo->rank); -} - -void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr) -{ - // Now add the auras, format "spellid effectindex spellid effectindex..." - char *p,*s; - std::map val; - s=p=(char*)reinterpret_cast(addon->auras); - if (p) - { - uint32 currSpellId = 0; - bool spell = true; - while (p[0] != 0) - { - ++p; - if (p[0] == ' ' || p[0] == 0) - { - if (spell) - currSpellId = atoi(s); - else - { - uint8 eff = atoi(s); - if (eff >=3) - { - sLog.outErrorDb("Creature (%s: %u) has wrong `auras` data in `%s`(too high aura effect: %d for spell: %d)",guidEntryStr,addon->guidOrEntry,table,eff,currSpellId); - } - val[currSpellId] |= 1<(addon->auras); - - // wrong list - if (!spell) - { - addon->auras = NULL; - sLog.outErrorDb("Creature (%s: %u) has wrong `auras` data in `%s`.",guidEntryStr,addon->guidOrEntry,table); - return; - } - } - - // empty list - if (val.empty()) - { - addon->auras = NULL; - return; - } - - // replace by new structures array - const_cast(addon->auras) = new CreatureDataAddonAura[val.size()+1]; - - uint32 i=0; - for (std::map::iterator itr = val.begin(); itr != val.end();++itr) - { - CreatureDataAddonAura& cAura = const_cast(addon->auras[i]); - cAura.spell_id = itr->first; - cAura.effectMask = itr->second; - if (cAura.effectMask > 7 || !cAura.effectMask) - { - sLog.outErrorDb("Creature (%s: %u) has wrong effect for spell %u in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.spell_id,table); - continue; - } - SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(cAura.spell_id); - if (!AdditionalSpellInfo) - { - sLog.outErrorDb("Creature (%s: %u) has wrong spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.spell_id,table); - continue; - } - for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) - { - if ((1<Effect[eff] || !AdditionalSpellInfo->EffectApplyAuraName[eff]) - { - sLog.outErrorDb("Creature (%s: %u) has not aura effect %u of spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,eff,cAura.spell_id,table); - continue; - } - else if (AdditionalSpellInfo->Effect[eff] == SPELL_EFFECT_PERSISTENT_AREA_AURA) - { - sLog.outErrorDb("Creature (%s: %u) has persistent area aura effect %u of spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,eff,cAura.spell_id,table); - continue; - } - } - } - - ++i; - } - - // fill terminator element (after last added) - CreatureDataAddonAura& endAura = const_cast(addon->auras[i]); - endAura.spell_id = 0; - endAura.effectMask = 0; -} - -void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment) -{ - creatureaddons.Load(); - - sLog.outString(">> Loaded %u %s", creatureaddons.RecordCount, comment); - sLog.outString(); - - // check data correctness and convert 'auras' - for (uint32 i = 1; i < creatureaddons.MaxEntry; ++i) - { - CreatureDataAddon const* addon = creatureaddons.LookupEntry(i); - if (!addon) - continue; - - if (addon->mount) - { - if (!sCreatureDisplayInfoStore.LookupEntry(addon->mount)) - { - sLog.outErrorDb("Creature (%s %u) have invalid displayInfoId for mount (%u) defined in `%s`.", entryName, addon->guidOrEntry, addon->mount, creatureaddons.GetTableName()); - const_cast(addon)->mount = 0; - } - } - - if (!sEmotesStore.LookupEntry(addon->emote)) - sLog.outErrorDb("Creature (%s %u) have invalid emote (%u) defined in `%s`.", entryName, addon->guidOrEntry, addon->emote, creatureaddons.GetTableName()); - - /*if (addon->move_flags & (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4)) - { - sLog.outErrorDb("Creature (%s %u) movement flags mask defined in `%s` include forbidden flags (" I32FMT ") that can crash client, cleanup at load.", entryName, addon->guidOrEntry, creatureaddons.GetTableName(), (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4)); - const_cast(addon)->move_flags &= ~(MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4); - }*/ - - ConvertCreatureAddonAuras(const_cast(addon), creatureaddons.GetTableName(), entryName); - } -} - -void ObjectMgr::LoadCreatureAddons() -{ - LoadCreatureAddons(sCreatureInfoAddonStorage,"Entry","creature template addons"); - - // check entry ids - for (uint32 i = 1; i < sCreatureInfoAddonStorage.MaxEntry; ++i) - if (CreatureDataAddon const* addon = sCreatureInfoAddonStorage.LookupEntry(i)) - if (!sCreatureStorage.LookupEntry(addon->guidOrEntry)) - sLog.outErrorDb("Creature (Entry: %u) does not exist but has a record in `%s`",addon->guidOrEntry, sCreatureInfoAddonStorage.GetTableName()); - - sLog.outString("Loading Creature Addon Data..."); - LoadCreatureAddons(sCreatureDataAddonStorage,"GUID","creature addons"); - - // check entry ids - for (uint32 i = 1; i < sCreatureDataAddonStorage.MaxEntry; ++i) - if (CreatureDataAddon const* addon = sCreatureDataAddonStorage.LookupEntry(i)) - if (mCreatureDataMap.find(addon->guidOrEntry) == mCreatureDataMap.end()) - sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`",addon->guidOrEntry); -} - -EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry) -{ - return sEquipmentStorage.LookupEntry(entry); -} - -void ObjectMgr::LoadEquipmentTemplates() -{ - sEquipmentStorage.Load(); - - for (uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i) - { - EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry(i); - - if (!eqInfo) - continue; - - for (uint8 j=0; j<3; j++) - { - if (!eqInfo->equipentry[j]) - continue; - - ItemEntry const *dbcitem = sItemStore.LookupEntry(eqInfo->equipentry[j]); - - if (!dbcitem) - { - sLog.outErrorDb("Unknown item (entry=%u) in creature_equip_template.equipentry%u for entry = %u, forced to 0.", eqInfo->equipentry[j], j+1, i); - const_cast(eqInfo)->equipentry[j] = 0; - continue; - } - - if (dbcitem->InventoryType != INVTYPE_WEAPON && - dbcitem->InventoryType != INVTYPE_SHIELD && - dbcitem->InventoryType != INVTYPE_RANGED && - dbcitem->InventoryType != INVTYPE_2HWEAPON && - dbcitem->InventoryType != INVTYPE_WEAPONMAINHAND && - dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND && - dbcitem->InventoryType != INVTYPE_HOLDABLE && - dbcitem->InventoryType != INVTYPE_THROWN && - dbcitem->InventoryType != INVTYPE_RANGEDRIGHT) - { - sLog.outErrorDb("Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0.", eqInfo->equipentry[j], j+1, i); - const_cast(eqInfo)->equipentry[j] = 0; - } - } - } - sLog.outString(">> Loaded %u equipment template", sEquipmentStorage.RecordCount); - sLog.outString(); -} - -CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelid) -{ - return sCreatureModelStorage.LookupEntry(modelid); -} - -uint32 ObjectMgr::ChooseDisplayId(uint32 /*team*/, const CreatureInfo *cinfo, const CreatureData *data /*= NULL*/) -{ - // Load creature model (display id) - uint32 display_id = 0; - - if (!data || data->displayid == 0) - { - display_id = cinfo->GetRandomValidModelId(); - } - else - return data->displayid; - - /*if (!team) - { - switch(cinfo->Entry) - { - case 28511: // Eye of Acherus - case 33114: // Flame Leviathan Seat (model 24914 chair) - case 33167: // Salvaged Demolisher Mechanic Seat - case 33189: // Liquid Pryite - return cinfo->Modelid1; - case 33218: // Pyrite Safety Container - return cinfo->Modelid2; - case 33143: // Overload Control Device - return cinfo->Modelid3; - default: - return cinfo->GetRandomValidModelId(); - } - }*/ - - return display_id; -} - -CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32 display_id) -{ - CreatureModelInfo const *minfo = GetCreatureModelInfo(display_id); - if (!minfo) - return NULL; - - // If a model for another gender exists, 50% chance to use it - if (minfo->modelid_other_gender != 0 && urand(0,1) == 0) - { - CreatureModelInfo const *minfo_tmp = GetCreatureModelInfo(minfo->modelid_other_gender); - if (!minfo_tmp) - { - sLog.outErrorDb("Model (Entry: %u) has modelid_other_gender %u not found in table `creature_model_info`. ", minfo->modelid, minfo->modelid_other_gender); - return minfo; // not fatal, just use the previous one - } - else - return minfo_tmp; - } - else - return minfo; -} - -void ObjectMgr::LoadCreatureModelInfo() -{ - sCreatureModelStorage.Load(); - - // post processing - for (uint32 i = 1; i < sCreatureModelStorage.MaxEntry; ++i) - { - CreatureModelInfo const *minfo = sCreatureModelStorage.LookupEntry(i); - if (!minfo) - continue; - - if (!sCreatureDisplayInfoStore.LookupEntry(minfo->modelid)) - sLog.outErrorDb("Table `creature_model_info` has model for not existed display id (%u).", minfo->modelid); - - if (minfo->gender > GENDER_NONE) - { - sLog.outErrorDb("Table `creature_model_info` has wrong gender (%u) for display id (%u).", uint32(minfo->gender), minfo->modelid); - const_cast(minfo)->gender = GENDER_MALE; - } - - if (minfo->modelid_other_gender && !sCreatureDisplayInfoStore.LookupEntry(minfo->modelid_other_gender)) - { - sLog.outErrorDb("Table `creature_model_info` has not existed alt.gender model (%u) for existed display id (%u).", minfo->modelid_other_gender, minfo->modelid); - const_cast(minfo)->modelid_other_gender = 0; - } - } - - sLog.outString(">> Loaded %u creature model based info", sCreatureModelStorage.RecordCount); - sLog.outString(); - - // check if combat_reach is valid - for (uint32 i = 1; i < sCreatureModelStorage.MaxEntry; ++i) - { - CreatureModelInfo const* mInfo = sCreatureModelStorage.LookupEntry(i); - if (!mInfo) - continue; - - if (mInfo->combat_reach < 0.1f) - { - //sLog.outErrorDb("Creature model (Entry: %u) has invalid combat reach (%f), setting it to 0.5", mInfo->modelid, mInfo->combat_reach); - const_cast(mInfo)->combat_reach = DEFAULT_COMBAT_REACH; - } - } -} - -bool ObjectMgr::CheckCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) const -{ - const CreatureData* const slave = GetCreatureData(guid); - const CreatureData* const master = GetCreatureData(linkedGuid); - - if (!slave || !master) // they must have a corresponding entry in db - { - sLog.outError("LinkedRespawn: Creature '%u' linking to '%u' which doesn't exist",guid,linkedGuid); - return false; - } - - const MapEntry* const map = sMapStore.LookupEntry(master->mapid); - - if (master->mapid != slave->mapid // link only to same map - && (!map || map->Instanceable())) // or to unistanced world - { - sLog.outError("LinkedRespawn: Creature '%u' linking to '%u' on an unpermitted map",guid,linkedGuid); - return false; - } - - if (!(master->spawnMask & slave->spawnMask) // they must have a possibility to meet (normal/heroic difficulty) - && (!map || map->Instanceable())) - { - sLog.outError("LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask",guid,linkedGuid); - return false; - } - - return true; -} - -void ObjectMgr::LoadCreatureLinkedRespawn() -{ - mCreatureLinkedRespawnMap.clear(); - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT guid, linkedGuid FROM creature_linked_respawn ORDER BY guid ASC"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(""); - sLog.outErrorDb(">> Loaded 0 linked respawns. DB table `creature_linked_respawn` is empty."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 guid = fields[0].GetUInt32(); - uint32 linkedGuid = fields[1].GetUInt32(); - - if (CheckCreatureLinkedRespawn(guid,linkedGuid)) - mCreatureLinkedRespawnMap[guid] = linkedGuid; - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u linked respawns", mCreatureLinkedRespawnMap.size()); -} - -bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) -{ - if (!guid) - return false; - - if (!linkedGuid) // we're removing the linking - { - mCreatureLinkedRespawnMap.erase(guid); - WorldDatabase.DirectPExecute("DELETE FROM creature_linked_respawn WHERE guid = '%u'",guid); - return true; - } - - if (CheckCreatureLinkedRespawn(guid,linkedGuid)) // we add/change linking - { - mCreatureLinkedRespawnMap[guid] = linkedGuid; - WorldDatabase.DirectPExecute("REPLACE INTO creature_linked_respawn (guid,linkedGuid) VALUES ('%u','%u')",guid,linkedGuid); - return true; - } - return false; -} - -void ObjectMgr::LoadCreatures() -{ - uint32 count = 0; - // 0 1 2 3 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid," - // 4 5 6 7 8 9 10 11 - "equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint," - // 12 13 14 15 16 17 18 19 - "curhealth, curmana, DeathState, MovementType, spawnMask, phaseMask, event, pool_entry " - "FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid " - "LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 creature. DB table `creature` is empty."); - return; - } - - // build single time for check creature data - std::set difficultyCreatures[MAX_DIFFICULTY - 1]; - for (uint32 i = 0; i < sCreatureStorage.MaxEntry; ++i) - if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i)) - for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1; ++diff) - if (cInfo->DifficultyEntry[diff]) - difficultyCreatures[diff].insert(cInfo->DifficultyEntry[diff]); - - // build single time for check spawnmask - std::map spawnMasks; - for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) - if (sMapStore.LookupEntry(i)) - for (int k = 0; k < MAX_DIFFICULTY; ++k) - if (GetMapDifficultyData(i,Difficulty(k))) - spawnMasks[i] |= (1 << k); - - //TODO: remove this - //gameeventmgr.mGameEventCreatureGuids.resize(52*2-1); - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 guid = fields[ 0].GetUInt32(); - uint32 entry = fields[ 1].GetUInt32(); - - CreatureInfo const* cInfo = GetCreatureTemplate(entry); - if (!cInfo) - { - sLog.outErrorDb("Table `creature` has creature (GUID: %u) with non existing creature entry %u, skipped.", guid, entry); - continue; - } - - CreatureData& data = mCreatureDataMap[guid]; - - data.id = entry; - data.mapid = fields[ 2].GetUInt32(); - data.displayid = fields[ 3].GetUInt32(); - data.equipmentId = fields[ 4].GetUInt32(); - data.posX = fields[ 5].GetFloat(); - data.posY = fields[ 6].GetFloat(); - data.posZ = fields[ 7].GetFloat(); - data.orientation = fields[ 8].GetFloat(); - data.spawntimesecs = fields[ 9].GetUInt32(); - data.spawndist = fields[10].GetFloat(); - data.currentwaypoint= fields[11].GetUInt32(); - data.curhealth = fields[12].GetUInt32(); - data.curmana = fields[13].GetUInt32(); - data.is_dead = fields[14].GetBool(); - data.movementType = fields[15].GetUInt8(); - data.spawnMask = fields[16].GetUInt8(); - data.phaseMask = fields[17].GetUInt16(); - int16 gameEvent = fields[18].GetInt16(); - int16 PoolId = fields[19].GetInt16(); - - MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); - if (!mapEntry) - { - sLog.outErrorDb("Table `creature` have creature (GUID: %u) that spawned at not existed map (Id: %u), skipped.",guid, data.mapid); - continue; - } - - if (data.spawnMask & ~spawnMasks[data.mapid]) - sLog.outErrorDb("Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).",guid, data.spawnMask, data.mapid); - - bool ok = true; - for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) - { - if (difficultyCreatures[diff].find(data.id) != difficultyCreatures[diff].end()) - { - sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as difficulty %u template (entry: %u) in `creature_template`, skipped.", - guid, diff + 1, data.id); - ok = false; - } - } - if (!ok) - continue; - - // I do not know why but in db most display id are not zero - /*if (data.displayid == 11686 || data.displayid == 24719) - { - (const_cast(cInfo))->flags_extra |= CREATURE_FLAG_EXTRA_TRIGGER; - } - else if (data.displayid == cInfo->DisplayID_A || data.displayid == cInfo->DisplayID_A2 - || data.displayid == cInfo->DisplayID_H || data.displayid == cInfo->DisplayID_H2) - data.displayid = 0; - */ - - if (data.equipmentId > 0) // -1 no equipment, 0 use default - { - if (!GetEquipmentInfo(data.equipmentId)) - { - sLog.outErrorDb("Table `creature` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", data.id, data.equipmentId); - data.equipmentId = -1; - } - } - - if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) - { - if (!mapEntry || !mapEntry->IsDungeon()) - sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance.",guid,data.id); - } - - if (data.spawndist < 0.0f) - { - sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `spawndist`< 0, set to 0.",guid,data.id); - data.spawndist = 0.0f; - } - else if (data.movementType == RANDOM_MOTION_TYPE) - { - if (data.spawndist == 0.0f) - { - sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=1 (random movement) but with `spawndist`=0, replace by idle movement type (0).",guid,data.id); - data.movementType = IDLE_MOTION_TYPE; - } - else if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) - data.movementType = IDLE_MOTION_TYPE; - } - else if (data.movementType == IDLE_MOTION_TYPE) - { - if (data.spawndist != 0.0f) - { - sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=0 (idle) have `spawndist`<>0, set to 0.",guid,data.id); - data.spawndist = 0.0f; - } - } - - if (data.phaseMask == 0) - { - sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id); - data.phaseMask = 1; - } - - //if (entry == 32307 || entry == 32308) - /*if (entry == 30739 || entry == 30740) - { - gameEvent = 51; - uint32 guid2 = objmgr.GenerateLowGuid(HIGHGUID_UNIT); - CreatureData& data2 = mCreatureDataMap[guid2]; - data2 = data; -// data2.id = (entry == 32307 ? 32308 : 32307); - data2.id = (entry == 30739 ? 30740 : 30739); - data2.displayid = 0; - gameeventmgr.mGameEventCreatureGuids[51+51].push_back(guid); - gameeventmgr.mGameEventCreatureGuids[51+50].push_back(guid2); - }*/ - - if (gameEvent == 0 && PoolId == 0) // if not this is to be managed by GameEvent System or Pool system - AddCreatureToGrid(guid, &data); - - ++count; - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu creatures", (unsigned long)mCreatureDataMap.size()); -} - -void ObjectMgr::AddCreatureToGrid(uint32 guid, CreatureData const* data) -{ - uint8 mask = data->spawnMask; - for (uint8 i = 0; mask != 0; i++, mask >>= 1) - { - if (mask & 1) - { - CellPair cell_pair = Trinity::ComputeCellPair(data->posX, data->posY); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; - cell_guids.creatures.insert(guid); - } - } -} - -void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data) -{ - uint8 mask = data->spawnMask; - for (uint8 i = 0; mask != 0; i++, mask >>= 1) - { - if (mask & 1) - { - CellPair cell_pair = Trinity::ComputeCellPair(data->posX, data->posY); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; - cell_guids.creatures.erase(guid); - } - } -} - -uint32 ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay, float rotation0, float rotation1, float rotation2, float rotation3) -{ - GameObjectInfo const* goinfo = GetGameObjectInfo(entry); - if (!goinfo) - return 0; - - Map* map = const_cast(MapManager::Instance().CreateBaseMap(mapId)); - if (!map) - return 0; - - uint32 guid = GenerateLowGuid(HIGHGUID_GAMEOBJECT); - GameObjectData& data = NewGOData(guid); - data.id = entry; - data.mapid = mapId; - data.posX = x; - data.posY = y; - data.posZ = z; - data.orientation = o; - data.rotation0 = rotation0; - data.rotation1 = rotation1; - data.rotation2 = rotation2; - data.rotation3 = rotation3; - data.spawntimesecs = spawntimedelay; - data.animprogress = 100; - data.spawnMask = 1; - data.go_state = GO_STATE_READY; - data.phaseMask = PHASEMASK_NORMAL; - data.artKit = goinfo->type == GAMEOBJECT_TYPE_CAPTURE_POINT ? 21 : 0; - data.dbData = false; - - AddGameobjectToGrid(guid, &data); - - // Spawn if necessary (loaded grids only) - // We use spawn coords to spawn - if (!map->Instanceable() && map->IsLoaded(x, y)) - { - GameObject *go = new GameObject; - if (!go->LoadFromDB(guid, map)) - { - sLog.outError("AddGOData: cannot add gameobject entry %u to map", entry); - delete go; - return 0; - } - map->Add(go); - } - - sLog.outDebug("AddGOData: dbguid %u entry %u map %u x %f y %f z %f o %f", guid, entry, mapId, x, y, z, o); - - return guid; -} - -bool ObjectMgr::MoveCreData(uint32 guid, uint32 mapId, Position pos) -{ - CreatureData& data = NewOrExistCreatureData(guid); - if (!data.id) - return false; - - RemoveCreatureFromGrid(guid, &data); - if (data.posX == pos.GetPositionX() && data.posY == pos.GetPositionY() && data.posZ == pos.GetPositionZ()) - return true; - data.posX = pos.GetPositionX(); - data.posY = pos.GetPositionY(); - data.posZ = pos.GetPositionZ(); - data.orientation = pos.GetOrientation(); - AddCreatureToGrid(guid, &data); - - // Spawn if necessary (loaded grids only) - if (Map* map = const_cast(MapManager::Instance().CreateBaseMap(mapId))) - { - // We use spawn coords to spawn - if (!map->Instanceable() && map->IsLoaded(data.posX, data.posY)) - { - Creature *creature = new Creature; - if (!creature->LoadFromDB(guid, map)) - { - sLog.outError("AddCreature: cannot add creature entry %u to map", guid); - delete creature; - return false; - } - map->Add(creature); - } - } - return true; -} - -uint32 ObjectMgr::AddCreData(uint32 entry, uint32 /*team*/, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay) -{ - CreatureInfo const *cInfo = GetCreatureTemplate(entry); - if (!cInfo) - return 0; - - uint32 level = cInfo->minlevel == cInfo->maxlevel ? cInfo->minlevel : urand(cInfo->minlevel, cInfo->maxlevel); // Only used for extracting creature base stats - CreatureBaseStats const* stats = objmgr.GetCreatureBaseStats(level, cInfo->unit_class); - - uint32 guid = GenerateLowGuid(HIGHGUID_UNIT); - CreatureData& data = NewOrExistCreatureData(guid); - data.id = entry; - data.mapid = mapId; - data.displayid = 0; - data.equipmentId = cInfo->equipmentId; - data.posX = x; - data.posY = y; - data.posZ = z; - data.orientation = o; - data.spawntimesecs = spawntimedelay; - data.spawndist = 0; - data.currentwaypoint = 0; - data.curhealth = stats->GenerateHealth(cInfo); - data.curmana = stats->GenerateMana(cInfo); - data.is_dead = false; - data.movementType = cInfo->MovementType; - data.spawnMask = 1; - data.phaseMask = PHASEMASK_NORMAL; - data.dbData = false; - - AddCreatureToGrid(guid, &data); - - // Spawn if necessary (loaded grids only) - if (Map* map = const_cast(MapManager::Instance().CreateBaseMap(mapId))) - { - // We use spawn coords to spawn - if (!map->Instanceable() && !map->IsRemovalGrid(x, y)) - { - Creature* creature = new Creature; - if (!creature->LoadFromDB(guid, map)) - { - sLog.outError("AddCreature: cannot add creature entry %u to map", entry); - delete creature; - return 0; - } - map->Add(creature); - } - } - - return guid; -} - -void ObjectMgr::LoadGameobjects() -{ - uint32 count = 0; - - // 0 1 2 3 4 5 6 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation," - // 7 8 9 10 11 12 13 14 15 16 17 - "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, event, pool_entry " - "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid " - "LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 gameobjects. DB table `gameobject` is empty."); - return; - } - - // build single time for check spawnmask - std::map spawnMasks; - for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) - if (sMapStore.LookupEntry(i)) - for (int k = 0; k < MAX_DIFFICULTY; ++k) - if (GetMapDifficultyData(i,Difficulty(k))) - spawnMasks[i] |= (1 << k); - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 guid = fields[ 0].GetUInt32(); - uint32 entry = fields[ 1].GetUInt32(); - - GameObjectInfo const* gInfo = GetGameObjectInfo(entry); - if (!gInfo) - { - sLog.outErrorDb("Table `gameobject` has gameobject (GUID: %u) with non existing gameobject entry %u, skipped.", guid, entry); - continue; - } - - if (!gInfo->displayId) - { - switch (gInfo->type) - { - case GAMEOBJECT_TYPE_TRAP: - case GAMEOBJECT_TYPE_SPELL_FOCUS: - break; - default: - sLog.outErrorDb("Gameobject (GUID: %u Entry %u GoType: %u) doesn't have displayId (%u), not loaded.", guid, entry, gInfo->type, gInfo->displayId); - break; - } - } - - if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId)) - { - sLog.outErrorDb("Gameobject (GUID: %u Entry %u GoType: %u) have invalid displayId (%u), not loaded.",guid, entry, gInfo->type, gInfo->displayId); - continue; - } - - GameObjectData& data = mGameObjectDataMap[guid]; - - data.id = entry; - data.mapid = fields[ 2].GetUInt32(); - data.posX = fields[ 3].GetFloat(); - data.posY = fields[ 4].GetFloat(); - data.posZ = fields[ 5].GetFloat(); - data.orientation = fields[ 6].GetFloat(); - data.rotation0 = fields[ 7].GetFloat(); - data.rotation1 = fields[ 8].GetFloat(); - data.rotation2 = fields[ 9].GetFloat(); - data.rotation3 = fields[10].GetFloat(); - data.spawntimesecs = fields[11].GetInt32(); - - MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); - if (!mapEntry) - { - sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) that spawned at not existed map (Id: %u), skip", guid, data.id, data.mapid); - continue; - } - - if (data.spawntimesecs == 0 && gInfo->IsDespawnAtAction()) - { - sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `spawntimesecs` (0) value, but gameobejct marked as despawnable at action.",guid,data.id); - } - - data.animprogress = fields[12].GetUInt32(); - data.artKit = 0; - - uint32 go_state = fields[13].GetUInt32(); - if (go_state >= MAX_GO_STATE) - { - sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid `state` (%u) value, skip",guid,data.id,go_state); - continue; - } - data.go_state = GOState(go_state); - - data.spawnMask = fields[14].GetUInt8(); - - if (data.spawnMask & ~spawnMasks[data.mapid]) - sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid); - - data.phaseMask = fields[15].GetUInt16(); - int16 gameEvent = fields[16].GetInt16(); - int16 PoolId = fields[17].GetInt16(); - - if (data.rotation2 < -1.0f || data.rotation2 > 1.0f) - { - sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation2 (%f) value, skip",guid,data.id,data.rotation2); - continue; - } - - if (data.rotation3 < -1.0f || data.rotation3 > 1.0f) - { - sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation3 (%f) value, skip",guid,data.id,data.rotation3); - continue; - } - - if (!MapManager::IsValidMapCoord(data.mapid,data.posX,data.posY,data.posZ,data.orientation)) - { - sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid coordinates, skip",guid,data.id); - continue; - } - - if (data.phaseMask == 0) - { - sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id); - data.phaseMask = 1; - } - - if (gameEvent == 0 && PoolId == 0) // if not this is to be managed by GameEvent System or Pool system - AddGameobjectToGrid(guid, &data); - ++count; - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu gameobjects", (unsigned long)mGameObjectDataMap.size()); -} - -void ObjectMgr::AddGameobjectToGrid(uint32 guid, GameObjectData const* data) -{ - uint8 mask = data->spawnMask; - for (uint8 i = 0; mask != 0; i++, mask >>= 1) - { - if (mask & 1) - { - CellPair cell_pair = Trinity::ComputeCellPair(data->posX, data->posY); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; - cell_guids.gameobjects.insert(guid); - } - } -} - -void ObjectMgr::RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data) -{ - uint8 mask = data->spawnMask; - for (uint8 i = 0; mask != 0; i++, mask >>= 1) - { - if (mask & 1) - { - CellPair cell_pair = Trinity::ComputeCellPair(data->posX, data->posY); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; - cell_guids.gameobjects.erase(guid); - } - } -} - -void ObjectMgr::LoadCreatureRespawnTimes() -{ - uint32 count = 0; - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT guid,respawntime,instance FROM creature_respawn"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded 0 creature respawn time."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 loguid = fields[0].GetUInt32(); - uint64 respawn_time = fields[1].GetUInt64(); - uint32 instance = fields[2].GetUInt32(); - - mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)] = time_t(respawn_time); - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu creature respawn times", (unsigned long)mCreatureRespawnTimes.size()); -} - -void ObjectMgr::LoadGameobjectRespawnTimes() -{ - // remove outdated data - WorldDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE respawntime <= UNIX_TIMESTAMP(NOW())"); - - uint32 count = 0; - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT guid,respawntime,instance FROM gameobject_respawn"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded 0 gameobject respawn time."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 loguid = fields[0].GetUInt32(); - uint64 respawn_time = fields[1].GetUInt64(); - uint32 instance = fields[2].GetUInt32(); - - mGORespawnTimes[MAKE_PAIR64(loguid,instance)] = time_t(respawn_time); - - ++count; - } while (result->NextRow()); - - sLog.outString(">> Loaded %lu gameobject respawn times", (unsigned long)mGORespawnTimes.size()); - sLog.outString(); -} - -// name must be checked to correctness (if received) before call this function -uint64 ObjectMgr::GetPlayerGUIDByName(std::string name) const -{ - uint64 guid = 0; - - CharacterDatabase.escape_string(name); - - // Player name safe to sending to DB (checked at login) and this function using - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT guid FROM characters WHERE name = '%s'", name.c_str()); - if (result) - guid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); - - return guid; -} - -bool ObjectMgr::GetPlayerNameByGUID(const uint64 &guid, std::string &name) const -{ - // prevent DB access for online player - if (Player* player = GetPlayer(guid)) - { - name = player->GetName(); - return true; - } - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); - - if (result) - { - name = (*result)[0].GetCppString(); - return true; - } - - return false; -} - -uint32 ObjectMgr::GetPlayerTeamByGUID(const uint64 &guid) const -{ - // prevent DB access for online player - if (Player* player = GetPlayer(guid)) - { - return Player::TeamForRace(player->getRace()); - } - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT race FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); - - if (result) - { - uint8 race = (*result)[0].GetUInt8(); - return Player::TeamForRace(race); - } - - return 0; -} - -uint32 ObjectMgr::GetPlayerAccountIdByGUID(const uint64 &guid) const -{ - // prevent DB access for online player - if (Player* player = GetPlayer(guid)) - { - return player->GetSession()->GetAccountId(); - } - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); - if (result) - { - uint32 acc = (*result)[0].GetUInt32(); - return acc; - } - - return 0; -} - -uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(const std::string& name) const -{ - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", name.c_str()); - if (result) - { - uint32 acc = (*result)[0].GetUInt32(); - return acc; - } - - return 0; -} - -void ObjectMgr::LoadItemLocales() -{ - mItemLocaleMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,name_loc1,description_loc1,name_loc2,description_loc2,name_loc3,description_loc3,name_loc4,description_loc4,name_loc5,description_loc5,name_loc6,description_loc6,name_loc7,description_loc7,name_loc8,description_loc8 FROM locales_item"); - - if (!result) - return; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 entry = fields[0].GetUInt32(); - - ItemLocale& data = mItemLocaleMap[entry]; - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[1+2*(i-1)].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Name.size() <= idx) - data.Name.resize(idx+1); - - data.Name[idx] = str; - } - } - - str = fields[1+2*(i-1)+1].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Description.size() <= idx) - data.Description.resize(idx+1); - - data.Description[idx] = str; - } - } - } - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu Item locale strings", (unsigned long)mItemLocaleMap.size()); -} - -struct SQLItemLoader : public SQLStorageLoaderBase -{ - template - void convert_from_str(uint32 /*field_pos*/, char *src, D &dst) - { - dst = D(objmgr.GetScriptId(src)); - } -}; - -void ObjectMgr::LoadItemPrototypes() -{ - SQLItemLoader loader; - loader.Load(sItemStorage); - sLog.outString(">> Loaded %u item prototypes", sItemStorage.RecordCount); - sLog.outString(); - - // check data correctness - for (uint32 i = 1; i < sItemStorage.MaxEntry; ++i) - { - ItemPrototype const* proto = sItemStorage.LookupEntry(i); - ItemEntry const *dbcitem = sItemStore.LookupEntry(i); - if (!proto) - { - /* to many errors, and possible not all items really used in game - if (dbcitem) - sLog.outErrorDb("Item (Entry: %u) doesn't exists in DB, but must exist.",i); - */ - continue; - } - - if (dbcitem) - { - if (proto->Class != dbcitem->Class) - { - sLog.outErrorDb("Item (Entry: %u) not correct class %u, must be %u (still using DB value).",i,proto->Class,dbcitem->Class); - // It safe let use Class from DB - } - /* disabled: have some strange wrong cases for Subclass values. - for enable also uncomment Subclass field in ItemEntry structure and in Itemfmt[] - if (proto->SubClass != dbcitem->SubClass) - { - sLog.outErrorDb("Item (Entry: %u) not correct (Class: %u, Sub: %u) pair, must be (Class: %u, Sub: %u) (still using DB value).",i,proto->Class,proto->SubClass,dbcitem->Class,dbcitem->SubClass); - // It safe let use Subclass from DB - } - */ - - if (proto->Unk0 != dbcitem->Unk0) - { - sLog.outErrorDb("Item (Entry: %u) not correct %i Unk0, must be %i (still using DB value).",i,proto->Unk0,dbcitem->Unk0); - // It safe let use Unk0 from DB - } - - if (proto->Material != dbcitem->Material) - { - sLog.outErrorDb("Item (Entry: %u) not correct %i material, must be %i (still using DB value).",i,proto->Material,dbcitem->Material); - // It safe let use Material from DB - } - - if (proto->InventoryType != dbcitem->InventoryType) - { - sLog.outErrorDb("Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value).",i,proto->InventoryType,dbcitem->InventoryType); - // It safe let use InventoryType from DB - } - - if (proto->DisplayInfoID != dbcitem->DisplayId) - { - sLog.outErrorDb("Item (Entry: %u) not correct %u display id, must be %u (using it).",i,proto->DisplayInfoID,dbcitem->DisplayId); - const_cast(proto)->DisplayInfoID = dbcitem->DisplayId; - } - if (proto->Sheath != dbcitem->Sheath) - { - sLog.outErrorDb("Item (Entry: %u) not correct %u sheath, must be %u (using it).",i,proto->Sheath,dbcitem->Sheath); - const_cast(proto)->Sheath = dbcitem->Sheath; - } - } - else - sLog.outErrorDb("Item (Entry: %u) not correct (not listed in list of existed items).",i); - - if (proto->Class >= MAX_ITEM_CLASS) - { - sLog.outErrorDb("Item (Entry: %u) has wrong Class value (%u)",i,proto->Class); - const_cast(proto)->Class = ITEM_CLASS_MISC; - } - - if (proto->SubClass >= MaxItemSubclassValues[proto->Class]) - { - sLog.outErrorDb("Item (Entry: %u) has wrong Subclass value (%u) for class %u",i,proto->SubClass,proto->Class); - const_cast(proto)->SubClass = 0;// exist for all item classes - } - - if (proto->Quality >= MAX_ITEM_QUALITY) - { - sLog.outErrorDb("Item (Entry: %u) has wrong Quality value (%u)",i,proto->Quality); - const_cast(proto)->Quality = ITEM_QUALITY_NORMAL; - } - - if (proto->BuyCount <= 0) - { - sLog.outErrorDb("Item (Entry: %u) has wrong BuyCount value (%u), set to default(1).",i,proto->BuyCount); - const_cast(proto)->BuyCount = 1; - } - - if (proto->InventoryType >= MAX_INVTYPE) - { - sLog.outErrorDb("Item (Entry: %u) has wrong InventoryType value (%u)",i,proto->InventoryType); - const_cast(proto)->InventoryType = INVTYPE_NON_EQUIP; - } - - if (proto->RequiredSkill >= MAX_SKILL_TYPE) - { - sLog.outErrorDb("Item (Entry: %u) has wrong RequiredSkill value (%u)",i,proto->RequiredSkill); - const_cast(proto)->RequiredSkill = 0; - } - - { - // can be used in equip slot, as page read use in inventory, or spell casting at use - bool req = proto->InventoryType != INVTYPE_NON_EQUIP || proto->PageText; - if (!req) - for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j) - { - if (proto->Spells[j].SpellId) - { - req = true; - break; - } - } - - if (req) - { - if (!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE)) - sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped or use.",i,proto->AllowableClass); - - if (!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE)) - sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped or use.",i,proto->AllowableRace); - } - } - - if (proto->RequiredSpell && !sSpellStore.LookupEntry(proto->RequiredSpell)) - { - sLog.outErrorDb("Item (Entry: %u) have wrong (non-existed) spell in RequiredSpell (%u)",i,proto->RequiredSpell); - const_cast(proto)->RequiredSpell = 0; - } - - if (proto->RequiredReputationRank >= MAX_REPUTATION_RANK) - sLog.outErrorDb("Item (Entry: %u) has wrong reputation rank in RequiredReputationRank (%u), item can't be used.",i,proto->RequiredReputationRank); - - if (proto->RequiredReputationFaction) - { - if (!sFactionStore.LookupEntry(proto->RequiredReputationFaction)) - { - sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) faction in RequiredReputationFaction (%u)",i,proto->RequiredReputationFaction); - const_cast(proto)->RequiredReputationFaction = 0; - } - - if (proto->RequiredReputationRank == MIN_REPUTATION_RANK) - sLog.outErrorDb("Item (Entry: %u) has min. reputation rank in RequiredReputationRank (0) but RequiredReputationFaction > 0, faction setting is useless.",i); - } - - if (proto->MaxCount < -1) - { - sLog.outErrorDb("Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits.",i,proto->MaxCount); - const_cast(proto)->MaxCount = -1; - } - - if (proto->Stackable == 0) - { - sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%i), replace by default 1.",i,proto->Stackable); - const_cast(proto)->Stackable = 1; - } - else if (proto->Stackable < -1) - { - sLog.outErrorDb("Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits.",i,proto->Stackable); - const_cast(proto)->Stackable = -1; - } - - if (proto->ContainerSlots > MAX_BAG_SIZE) - { - sLog.outErrorDb("Item (Entry: %u) has too large value in ContainerSlots (%u), replace by hardcoded limit (%u).",i,proto->ContainerSlots,MAX_BAG_SIZE); - const_cast(proto)->ContainerSlots = MAX_BAG_SIZE; - } - - if (proto->StatsCount > MAX_ITEM_PROTO_STATS) - { - sLog.outErrorDb("Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).",i,proto->StatsCount,MAX_ITEM_PROTO_STATS); - const_cast(proto)->StatsCount = MAX_ITEM_PROTO_STATS; - } - - for (uint8 j = 0; j < MAX_ITEM_PROTO_STATS; ++j) - { - // for ItemStatValue != 0 - if (proto->ItemStat[j].ItemStatValue && proto->ItemStat[j].ItemStatType >= MAX_ITEM_MOD) - { - sLog.outErrorDb("Item (Entry: %u) has wrong stat_type%d (%u)",i,j+1,proto->ItemStat[j].ItemStatType); - const_cast(proto)->ItemStat[j].ItemStatType = 0; - } - - switch (proto->ItemStat[j].ItemStatType) - { - case ITEM_MOD_SPELL_HEALING_DONE: - case ITEM_MOD_SPELL_DAMAGE_DONE: - sLog.outErrorDb("Item (Entry: %u) has deprecated stat_type%d (%u)",i,j+1,proto->ItemStat[j].ItemStatType); - break; - default: - break; - } - } - - for (uint8 j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j) - { - if (proto->Damage[j].DamageType >= MAX_SPELL_SCHOOL) - { - sLog.outErrorDb("Item (Entry: %u) has wrong dmg_type%d (%u)",i,j+1,proto->Damage[j].DamageType); - const_cast(proto)->Damage[j].DamageType = 0; - } - } - - // special format - if ((proto->Spells[0].SpellId == 483) || (proto->Spells[0].SpellId == 55884)) - { - // spell_1 - if (proto->Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) - { - sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format",i,0+1,proto->Spells[0].SpellTrigger); - const_cast(proto)->Spells[0].SpellId = 0; - const_cast(proto)->Spells[0].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; - const_cast(proto)->Spells[1].SpellId = 0; - const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; - } - - // spell_2 have learning spell - if (proto->Spells[1].SpellTrigger != ITEM_SPELLTRIGGER_LEARN_SPELL_ID) - { - sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format.",i,1+1,proto->Spells[1].SpellTrigger); - const_cast(proto)->Spells[0].SpellId = 0; - const_cast(proto)->Spells[1].SpellId = 0; - const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; - } - else if (!proto->Spells[1].SpellId) - { - sLog.outErrorDb("Item (Entry: %u) not has expected spell in spellid_%d in special learning format.",i,1+1); - const_cast(proto)->Spells[0].SpellId = 0; - const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; - } - else if (proto->Spells[1].SpellId != -1) - { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->Spells[1].SpellId); - if (!spellInfo) - { - sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)",i,1+1,proto->Spells[1].SpellId); - const_cast(proto)->Spells[0].SpellId = 0; - const_cast(proto)->Spells[1].SpellId = 0; - const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; - } - // allowed only in special format - else if ((proto->Spells[1].SpellId == 483) || (proto->Spells[1].SpellId == 55884)) - { - sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%d)",i,1+1,proto->Spells[1].SpellId); - const_cast(proto)->Spells[0].SpellId = 0; - const_cast(proto)->Spells[1].SpellId = 0; - const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; - } - } - - // spell_3*,spell_4*,spell_5* is empty - for (uint8 j = 2; j < MAX_ITEM_PROTO_SPELLS; ++j) - { - if (proto->Spells[j].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) - { - sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)",i,j+1,proto->Spells[j].SpellTrigger); - const_cast(proto)->Spells[j].SpellId = 0; - const_cast(proto)->Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; - } - else if (proto->Spells[j].SpellId != 0) - { - sLog.outErrorDb("Item (Entry: %u) has wrong spell in spellid_%d (%d) for learning special format",i,j+1,proto->Spells[j].SpellId); - const_cast(proto)->Spells[j].SpellId = 0; - } - } - } - // normal spell list - else - { - for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j) - { - if (proto->Spells[j].SpellTrigger >= MAX_ITEM_SPELLTRIGGER || proto->Spells[j].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID) - { - sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)",i,j+1,proto->Spells[j].SpellTrigger); - const_cast(proto)->Spells[j].SpellId = 0; - const_cast(proto)->Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; - } - - if (proto->Spells[j].SpellId && proto->Spells[j].SpellId != -1) - { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->Spells[j].SpellId); - if (!spellInfo) - { - sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)",i,j+1,proto->Spells[j].SpellId); - const_cast(proto)->Spells[j].SpellId = 0; - } - // allowed only in special format - else if ((proto->Spells[j].SpellId == 483) || (proto->Spells[j].SpellId == 55884)) - { - sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%d)",i,j+1,proto->Spells[j].SpellId); - const_cast(proto)->Spells[j].SpellId = 0; - } - } - } - } - - if (proto->Bonding >= MAX_BIND_TYPE) - sLog.outErrorDb("Item (Entry: %u) has wrong Bonding value (%u)",i,proto->Bonding); - - if (proto->PageText && !sPageTextStore.LookupEntry(proto->PageText)) - sLog.outErrorDb("Item (Entry: %u) has non existing first page (Id:%u)", i,proto->PageText); - - if (proto->LockID && !sLockStore.LookupEntry(proto->LockID)) - sLog.outErrorDb("Item (Entry: %u) has wrong LockID (%u)",i,proto->LockID); - - if (proto->Sheath >= MAX_SHEATHETYPE) - { - sLog.outErrorDb("Item (Entry: %u) has wrong Sheath (%u)",i,proto->Sheath); - const_cast(proto)->Sheath = SHEATHETYPE_NONE; - } - - if (proto->RandomProperty && !sItemRandomPropertiesStore.LookupEntry(GetItemEnchantMod(proto->RandomProperty))) - { - sLog.outErrorDb("Item (Entry: %u) has unknown (wrong or not listed in `item_enchantment_template`) RandomProperty (%u)",i,proto->RandomProperty); - const_cast(proto)->RandomProperty = 0; - } - - if (proto->RandomSuffix && !sItemRandomSuffixStore.LookupEntry(GetItemEnchantMod(proto->RandomSuffix))) - { - sLog.outErrorDb("Item (Entry: %u) has wrong RandomSuffix (%u)",i,proto->RandomSuffix); - const_cast(proto)->RandomSuffix = 0; - } - - if (proto->ItemSet && !sItemSetStore.LookupEntry(proto->ItemSet)) - { - sLog.outErrorDb("Item (Entry: %u) have wrong ItemSet (%u)",i,proto->ItemSet); - const_cast(proto)->ItemSet = 0; - } - - if (proto->Area && !GetAreaEntryByAreaID(proto->Area)) - sLog.outErrorDb("Item (Entry: %u) has wrong Area (%u)",i,proto->Area); - - if (proto->Map && !sMapStore.LookupEntry(proto->Map)) - sLog.outErrorDb("Item (Entry: %u) has wrong Map (%u)",i,proto->Map); - - if (proto->BagFamily) - { - // check bits - for (uint32 j = 0; j < sizeof(proto->BagFamily)*8; ++j) - { - uint32 mask = 1 << j; - if ((proto->BagFamily & mask) == 0) - continue; - - ItemBagFamilyEntry const* bf = sItemBagFamilyStore.LookupEntry(j+1); - if (!bf) - { - sLog.outErrorDb("Item (Entry: %u) has bag family bit set not listed in ItemBagFamily.dbc, remove bit",i); - const_cast(proto)->BagFamily &= ~mask; - continue; - } - - if (BAG_FAMILY_MASK_CURRENCY_TOKENS & mask) - { - CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(proto->ItemId); - if (!ctEntry) - { - sLog.outErrorDb("Item (Entry: %u) has currency bag family bit set in BagFamily but not listed in CurrencyTypes.dbc, remove bit",i); - const_cast(proto)->BagFamily &= ~mask; - } - } - } - } - - if (proto->TotemCategory && !sTotemCategoryStore.LookupEntry(proto->TotemCategory)) - sLog.outErrorDb("Item (Entry: %u) has wrong TotemCategory (%u)",i,proto->TotemCategory); - - for (uint8 j = 0; j < MAX_ITEM_PROTO_SOCKETS; ++j) - { - if (proto->Socket[j].Color && (proto->Socket[j].Color & SOCKET_COLOR_ALL) != proto->Socket[j].Color) - { - sLog.outErrorDb("Item (Entry: %u) has wrong socketColor_%d (%u)",i,j+1,proto->Socket[j].Color); - const_cast(proto)->Socket[j].Color = 0; - } - } - - if (proto->GemProperties && !sGemPropertiesStore.LookupEntry(proto->GemProperties)) - sLog.outErrorDb("Item (Entry: %u) has wrong GemProperties (%u)",i,proto->GemProperties); - - if (proto->FoodType >= MAX_PET_DIET) - { - sLog.outErrorDb("Item (Entry: %u) has wrong FoodType value (%u)",i,proto->FoodType); - const_cast(proto)->FoodType = 0; - } - - if (proto->ItemLimitCategory && !sItemLimitCategoryStore.LookupEntry(proto->ItemLimitCategory)) - { - sLog.outErrorDb("Item (Entry: %u) has wrong LimitCategory value (%u)",i,proto->ItemLimitCategory); - const_cast(proto)->ItemLimitCategory = 0; - } - - if (proto->HolidayId && !sHolidaysStore.LookupEntry(proto->HolidayId)) - { - sLog.outErrorDb("Item (Entry: %u) has wrong HolidayId value (%u)", i, proto->HolidayId); - const_cast(proto)->HolidayId = 0; - } - } - - // check some dbc referecned items (avoid duplicate reports) - std::set notFoundOutfit; - for (uint32 i = 1; i < sCharStartOutfitStore.GetNumRows(); ++i) - { - CharStartOutfitEntry const* entry = sCharStartOutfitStore.LookupEntry(i); - if (!entry) - continue; - - for (int j = 0; j < MAX_OUTFIT_ITEMS; ++j) - { - if (entry->ItemId[j] <= 0) - continue; - - uint32 item_id = entry->ItemId[j]; - - if (!GetItemPrototype(item_id)) - notFoundOutfit.insert(item_id); - } - } - - for (std::set::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr) - sLog.outErrorDb("Item (Entry: %u) not exist in `item_template` but referenced in `CharStartOutfit.dnc`", *itr); -} - -void ObjectMgr::LoadVehicleAccessories() -{ - m_VehicleAccessoryMap.clear(); // needed for reload case - - uint32 count = 0; - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT `entry`,`accessory_entry`,`seat_id`,`minion` FROM `vehicle_accessory`"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 LoadVehicleAccessor. DB table `vehicle_accessory` is empty."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 uiEntry = fields[0].GetUInt32(); - uint32 uiAccessory = fields[1].GetUInt32(); - int8 uiSeat = int8(fields[2].GetInt16()); - bool bMinion = fields[3].GetBool(); - - if (!sCreatureStorage.LookupEntry(uiEntry)) - { - sLog.outErrorDb("Table `vehicle_accessory`: creature template entry %u does not exist.", uiEntry); - continue; - } - - if (!sCreatureStorage.LookupEntry(uiAccessory)) - { - sLog.outErrorDb("Table `vehicle_accessory`: Accessory %u does not exist.", uiAccessory); - continue; - } - - m_VehicleAccessoryMap[uiEntry].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion)); - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u Vehicle Accessories", count); -} - -void ObjectMgr::LoadPetLevelInfo() -{ - // Loading levels data - { - // 0 1 2 3 4 5 6 7 8 9 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT creature_entry, level, hp, mana, str, agi, sta, inte, spi, armor FROM pet_levelstats"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - - sLog.outString(); - sLog.outString(">> Loaded %u level pet stats definitions", count); - sLog.outErrorDb("Error loading `pet_levelstats` table or empty table."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - uint32 creature_id = fields[0].GetUInt32(); - if (!sCreatureStorage.LookupEntry(creature_id)) - { - sLog.outErrorDb("Wrong creature id %u in `pet_levelstats` table, ignoring.",creature_id); - continue; - } - - uint32 current_level = fields[1].GetUInt32(); - if (current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum - sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); - else - { - sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `pet_levelstats` table, ignoring.",current_level); - ++count; // make result loading percent "expected" correct in case disabled detail mode for example. - } - continue; - } - else if (current_level < 1) - { - sLog.outErrorDb("Wrong (<1) level %u in `pet_levelstats` table, ignoring.",current_level); - continue; - } - - PetLevelInfo*& pInfoMapEntry = petInfo[creature_id]; - - if (pInfoMapEntry == NULL) - pInfoMapEntry = new PetLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; - - // data for level 1 stored in [0] array element, ... - PetLevelInfo* pLevelInfo = &pInfoMapEntry[current_level-1]; - - pLevelInfo->health = fields[2].GetUInt16(); - pLevelInfo->mana = fields[3].GetUInt16(); - pLevelInfo->armor = fields[9].GetUInt16(); - - for (int i = 0; i < MAX_STATS; i++) - { - pLevelInfo->stats[i] = fields[i+4].GetUInt16(); - } - - bar.step(); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u level pet stats definitions", count); - } - - // Fill gaps and check integrity - for (PetLevelInfoMap::iterator itr = petInfo.begin(); itr != petInfo.end(); ++itr) - { - PetLevelInfo* pInfo = itr->second; - - // fatal error if no level 1 data - if (!pInfo || pInfo[0].health == 0) - { - sLog.outErrorDb("Creature %u does not have pet stats data for Level 1!",itr->first); - exit(1); - } - - // fill level gaps - for (uint8 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) - { - if (pInfo[level].health == 0) - { - sLog.outErrorDb("Creature %u has no data for Level %i pet stats data, using data of Level %i.",itr->first,level+1, level); - pInfo[level] = pInfo[level-1]; - } - } - } -} - -PetLevelInfo const* ObjectMgr::GetPetLevelInfo(uint32 creature_id, uint8 level) const -{ - if (level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); - - PetLevelInfoMap::const_iterator itr = petInfo.find(creature_id); - if (itr == petInfo.end()) - return NULL; - - return &itr->second[level-1]; // data for level 1 stored in [0] array element, ... -} - -void ObjectMgr::LoadPlayerInfo() -{ - // Load playercreate - { - // 0 1 2 3 4 5 6 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT race, class, map, zone, position_x, position_y, position_z FROM playercreateinfo"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - - sLog.outString(); - sLog.outString(">> Loaded %u player create definitions", count); - sLog.outErrorDb("Error loading `playercreateinfo` table or empty table."); - exit(1); - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - uint32 current_race = fields[0].GetUInt32(); - uint32 current_class = fields[1].GetUInt32(); - uint32 mapId = fields[2].GetUInt32(); - uint32 areaId = fields[3].GetUInt32(); - float positionX = fields[4].GetFloat(); - float positionY = fields[5].GetFloat(); - float positionZ = fields[6].GetFloat(); - - if (current_race >= MAX_RACES) - { - sLog.outErrorDb("Wrong race %u in `playercreateinfo` table, ignoring.",current_race); - continue; - } - - ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(current_race); - if (!rEntry) - { - sLog.outErrorDb("Wrong race %u in `playercreateinfo` table, ignoring.",current_race); - continue; - } - - if (current_class >= MAX_CLASSES) - { - sLog.outErrorDb("Wrong class %u in `playercreateinfo` table, ignoring.",current_class); - continue; - } - - if (!sChrClassesStore.LookupEntry(current_class)) - { - sLog.outErrorDb("Wrong class %u in `playercreateinfo` table, ignoring.",current_class); - continue; - } - - // accept DB data only for valid position (and non instanceable) - if (!MapManager::IsValidMapCoord(mapId,positionX,positionY,positionZ)) - { - sLog.outErrorDb("Wrong home position for class %u race %u pair in `playercreateinfo` table, ignoring.",current_class,current_race); - continue; - } - - if (sMapStore.LookupEntry(mapId)->Instanceable()) - { - sLog.outErrorDb("Home position in instanceable map for class %u race %u pair in `playercreateinfo` table, ignoring.",current_class,current_race); - continue; - } - - PlayerInfo* pInfo = &playerInfo[current_race][current_class]; - - pInfo->mapId = mapId; - pInfo->areaId = areaId; - pInfo->positionX = positionX; - pInfo->positionY = positionY; - pInfo->positionZ = positionZ; - - pInfo->displayId_m = rEntry->model_m; - pInfo->displayId_f = rEntry->model_f; - - bar.step(); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u player create definitions", count); - } - - // Load playercreate items - sLog.outString("Loading Player Create Items Data..."); - { - // 0 1 2 3 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT race, class, itemid, amount FROM playercreateinfo_item"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u custom player create items", count); - } - else - { - barGoLink bar(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - uint32 current_race = fields[0].GetUInt32(); - if (current_race >= MAX_RACES) - { - sLog.outErrorDb("Wrong race %u in `playercreateinfo_item` table, ignoring.",current_race); - continue; - } - - uint32 current_class = fields[1].GetUInt32(); - if (current_class >= MAX_CLASSES) - { - sLog.outErrorDb("Wrong class %u in `playercreateinfo_item` table, ignoring.",current_class); - continue; - } - - PlayerInfo* pInfo = &playerInfo[current_race][current_class]; - - uint32 item_id = fields[2].GetUInt32(); - - if (!GetItemPrototype(item_id)) - { - sLog.outErrorDb("Item id %u (race %u class %u) in `playercreateinfo_item` table but not listed in `item_template`, ignoring.",item_id,current_race,current_class); - continue; - } - - uint32 amount = fields[3].GetUInt32(); - - if (!amount) - { - sLog.outErrorDb("Item id %u (class %u race %u) have amount == 0 in `playercreateinfo_item` table, ignoring.",item_id,current_race,current_class); - continue; - } - - pInfo->item.push_back(PlayerCreateInfoItem(item_id, amount)); - - bar.step(); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u custom player create items", count); - } - } - - // Load playercreate spells - sLog.outString("Loading Player Create Spell Data..."); - { - - QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); - if (sWorld.getConfig(CONFIG_START_ALL_SPELLS)) - result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell_custom"); - else - result = WorldDatabase.Query("SELECT race, class, Spell FROM playercreateinfo_spell"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - - sLog.outString(); - sLog.outString(">> Loaded %u player create spells", count); - sLog.outErrorDb("Error loading player starting spells or empty table."); - } - else - { - barGoLink bar(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - uint32 current_race = fields[0].GetUInt32(); - if (current_race >= MAX_RACES) - { - sLog.outErrorDb("Wrong race %u in `playercreateinfo_spell` table, ignoring.",current_race); - continue; - } - - uint32 current_class = fields[1].GetUInt32(); - if (current_class >= MAX_CLASSES) - { - sLog.outErrorDb("Wrong class %u in `playercreateinfo_spell` table, ignoring.",current_class); - continue; - } - - if (!current_race || !current_class) - { - uint32 min_race = current_race ? current_race : 1; - uint32 max_race = current_race ? current_race + 1 : MAX_RACES; - uint32 min_class = current_class ? current_class : 1; - uint32 max_class = current_class ? current_class + 1 : MAX_CLASSES; - for (uint32 r = min_race; r < max_race; ++r) - for (uint32 c = min_class; c < max_class; ++c) - playerInfo[r][c].spell.push_back(fields[2].GetUInt32()); - } - else - playerInfo[current_race][current_class].spell.push_back(fields[2].GetUInt32()); - - bar.step(); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u player create spells", count); - } - } - - // Load playercreate actions - sLog.outString("Loading Player Create Action Data..."); - { - // 0 1 2 3 4 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT race, class, button, action, type FROM playercreateinfo_action"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - - sLog.outString(); - sLog.outString(">> Loaded %u player create actions", count); - sLog.outErrorDb("Error loading `playercreateinfo_action` table or empty table."); - } - else - { - barGoLink bar(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - uint32 current_race = fields[0].GetUInt32(); - if (current_race >= MAX_RACES) - { - sLog.outErrorDb("Wrong race %u in `playercreateinfo_action` table, ignoring.",current_race); - continue; - } - - uint32 current_class = fields[1].GetUInt32(); - if (current_class >= MAX_CLASSES) - { - sLog.outErrorDb("Wrong class %u in `playercreateinfo_action` table, ignoring.",current_class); - continue; - } - - PlayerInfo* pInfo = &playerInfo[current_race][current_class]; - pInfo->action.push_back(PlayerCreateInfoAction(fields[2].GetUInt8(),fields[3].GetUInt32(),fields[4].GetUInt8())); - - bar.step(); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u player create actions", count); - } - } - - // Loading levels data (class only dependent) - sLog.outString("Loading Player Create Level HP/Mana Data..."); - { - // 0 1 2 3 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT class, level, basehp, basemana FROM player_classlevelstats"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - - sLog.outString(); - sLog.outString(">> Loaded %u level health/mana definitions", count); - sLog.outErrorDb("Error loading `player_classlevelstats` table or empty table."); - exit(1); - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - uint32 current_class = fields[0].GetUInt32(); - if (current_class >= MAX_CLASSES) - { - sLog.outErrorDb("Wrong class %u in `player_classlevelstats` table, ignoring.",current_class); - continue; - } - - uint8 current_level = fields[1].GetUInt8(); - if (current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum - sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); - else - { - sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level); - ++count; // make result loading percent "expected" correct in case disabled detail mode for example. - } - continue; - } - - PlayerClassInfo* pClassInfo = &playerClassInfo[current_class]; - - if (!pClassInfo->levelInfo) - pClassInfo->levelInfo = new PlayerClassLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; - - PlayerClassLevelInfo* pClassLevelInfo = &pClassInfo->levelInfo[current_level-1]; - - pClassLevelInfo->basehealth = fields[2].GetUInt16(); - pClassLevelInfo->basemana = fields[3].GetUInt16(); - - bar.step(); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u level health/mana definitions", count); - } - - // Fill gaps and check integrity - for (int class_ = 0; class_ < MAX_CLASSES; ++class_) - { - // skip non existed classes - if (!sChrClassesStore.LookupEntry(class_)) - continue; - - PlayerClassInfo* pClassInfo = &playerClassInfo[class_]; - - // fatal error if no level 1 data - if (!pClassInfo->levelInfo || pClassInfo->levelInfo[0].basehealth == 0) - { - sLog.outErrorDb("Class %i Level 1 does not have health/mana data!",class_); - exit(1); - } - - // fill level gaps - for (uint8 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) - { - if (pClassInfo->levelInfo[level].basehealth == 0) - { - sLog.outErrorDb("Class %i Level %i does not have health/mana data. Using stats data of level %i.",class_,level+1, level); - pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level-1]; - } - } - } - - // Loading levels data (class/race dependent) - sLog.outString("Loading Player Create Level Stats Data..."); - { - // 0 1 2 3 4 5 6 7 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT race, class, level, str, agi, sta, inte, spi FROM player_levelstats"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - - sLog.outString(); - sLog.outString(">> Loaded %u level stats definitions", count); - sLog.outErrorDb("Error loading `player_levelstats` table or empty table."); - exit(1); - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - uint32 current_race = fields[0].GetUInt32(); - if (current_race >= MAX_RACES) - { - sLog.outErrorDb("Wrong race %u in `player_levelstats` table, ignoring.",current_race); - continue; - } - - uint32 current_class = fields[1].GetUInt32(); - if (current_class >= MAX_CLASSES) - { - sLog.outErrorDb("Wrong class %u in `player_levelstats` table, ignoring.",current_class); - continue; - } - - uint32 current_level = fields[2].GetUInt32(); - if (current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum - sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); - else - { - sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_levelstats` table, ignoring.",current_level); - ++count; // make result loading percent "expected" correct in case disabled detail mode for example. - } - continue; - } - - PlayerInfo* pInfo = &playerInfo[current_race][current_class]; - - if (!pInfo->levelInfo) - pInfo->levelInfo = new PlayerLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; - - PlayerLevelInfo* pLevelInfo = &pInfo->levelInfo[current_level-1]; - - for (int i = 0; i < MAX_STATS; i++) - { - pLevelInfo->stats[i] = fields[i+3].GetUInt8(); - } - - bar.step(); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u level stats definitions", count); - } - - // Fill gaps and check integrity - for (int race = 0; race < MAX_RACES; ++race) - { - // skip non existed races - if (!sChrRacesStore.LookupEntry(race)) - continue; - - for (int class_ = 0; class_ < MAX_CLASSES; ++class_) - { - // skip non existed classes - if (!sChrClassesStore.LookupEntry(class_)) - continue; - - PlayerInfo* pInfo = &playerInfo[race][class_]; - - // skip non loaded combinations - if (!pInfo->displayId_m || !pInfo->displayId_f) - continue; - - // skip expansion races if not playing with expansion - if (sWorld.getConfig(CONFIG_EXPANSION) < 1 && (race == RACE_BLOODELF || race == RACE_DRAENEI)) - continue; - - // skip expansion classes if not playing with expansion - if (sWorld.getConfig(CONFIG_EXPANSION) < 2 && class_ == CLASS_DEATH_KNIGHT) - continue; - - // fatal error if no level 1 data - if (!pInfo->levelInfo || pInfo->levelInfo[0].stats[0] == 0) - { - sLog.outErrorDb("Race %i Class %i Level 1 does not have stats data!",race,class_); - exit(1); - } - - // fill level gaps - for (uint8 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) - { - if (pInfo->levelInfo[level].stats[0] == 0) - { - sLog.outErrorDb("Race %i Class %i Level %i does not have stats data. Using stats data of level %i.",race,class_,level+1, level); - pInfo->levelInfo[level] = pInfo->levelInfo[level-1]; - } - } - } - } - - // Loading xp per level data - sLog.outString("Loading Player Create XP Data..."); - { - mPlayerXPperLevel.resize(sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - for (uint8 level = 0; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) - mPlayerXPperLevel[level] = 0; - - // 0 1 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - - sLog.outString(); - sLog.outString(">> Loaded %u xp for level definitions", count); - sLog.outErrorDb("Error loading `player_xp_for_level` table or empty table."); - exit(1); - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - uint32 current_level = fields[0].GetUInt32(); - uint32 current_xp = fields[1].GetUInt32(); - - if (current_level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum - sLog.outErrorDb("Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL,current_level); - else - { - sLog.outDetail("Unused (> MaxPlayerLevel in TrinityCore.conf) level %u in `player_xp_for_levels` table, ignoring.",current_level); - ++count; // make result loading percent "expected" correct in case disabled detail mode for example. - } - continue; - } - //PlayerXPperLevel - mPlayerXPperLevel[current_level] = current_xp; - bar.step(); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u xp for level definitions", count); - } - - // fill level gaps - for (uint8 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) - { - if (mPlayerXPperLevel[level] == 0) - { - sLog.outErrorDb("Level %i does not have XP for level data. Using data of level [%i] + 100.",level+1, level); - mPlayerXPperLevel[level] = mPlayerXPperLevel[level-1]+100; - } - } -} - -void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassLevelInfo* info) const -{ - if (level < 1 || class_ >= MAX_CLASSES) - return; - - PlayerClassInfo const* pInfo = &playerClassInfo[class_]; - - if (level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); - - *info = pInfo->levelInfo[level-1]; -} - -void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const -{ - if (level < 1 || race >= MAX_RACES || class_ >= MAX_CLASSES) - return; - - PlayerInfo const* pInfo = &playerInfo[race][class_]; - if (pInfo->displayId_m == 0 || pInfo->displayId_f == 0) - return; - - if (level <= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - *info = pInfo->levelInfo[level-1]; - else - BuildPlayerLevelInfo(race,class_,level,info); -} - -void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, PlayerLevelInfo* info) const -{ - // base data (last known level) - *info = playerInfo[race][_class].levelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)-1]; - - // if conversion from uint32 to uint8 causes unexpected behaviour, change lvl to uint32 - for (uint8 lvl = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)-1; lvl < level; ++lvl) - { - switch(_class) - { - case CLASS_WARRIOR: - info->stats[STAT_STRENGTH] += (lvl > 23 ? 2: (lvl > 1 ? 1: 0)); - info->stats[STAT_STAMINA] += (lvl > 23 ? 2: (lvl > 1 ? 1: 0)); - info->stats[STAT_AGILITY] += (lvl > 36 ? 1: (lvl > 6 && (lvl%2) ? 1: 0)); - info->stats[STAT_INTELLECT] += (lvl > 9 && !(lvl%2) ? 1: 0); - info->stats[STAT_SPIRIT] += (lvl > 9 && !(lvl%2) ? 1: 0); - break; - case CLASS_PALADIN: - info->stats[STAT_STRENGTH] += (lvl > 3 ? 1: 0); - info->stats[STAT_STAMINA] += (lvl > 33 ? 2: (lvl > 1 ? 1: 0)); - info->stats[STAT_AGILITY] += (lvl > 38 ? 1: (lvl > 7 && !(lvl%2) ? 1: 0)); - info->stats[STAT_INTELLECT] += (lvl > 6 && (lvl%2) ? 1: 0); - info->stats[STAT_SPIRIT] += (lvl > 7 ? 1: 0); - break; - case CLASS_HUNTER: - info->stats[STAT_STRENGTH] += (lvl > 4 ? 1: 0); - info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); - info->stats[STAT_AGILITY] += (lvl > 33 ? 2: (lvl > 1 ? 1: 0)); - info->stats[STAT_INTELLECT] += (lvl > 8 && (lvl%2) ? 1: 0); - info->stats[STAT_SPIRIT] += (lvl > 38 ? 1: (lvl > 9 && !(lvl%2) ? 1: 0)); - break; - case CLASS_ROGUE: - info->stats[STAT_STRENGTH] += (lvl > 5 ? 1: 0); - info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); - info->stats[STAT_AGILITY] += (lvl > 16 ? 2: (lvl > 1 ? 1: 0)); - info->stats[STAT_INTELLECT] += (lvl > 8 && !(lvl%2) ? 1: 0); - info->stats[STAT_SPIRIT] += (lvl > 38 ? 1: (lvl > 9 && !(lvl%2) ? 1: 0)); - break; - case CLASS_PRIEST: - info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); - info->stats[STAT_STAMINA] += (lvl > 5 ? 1: 0); - info->stats[STAT_AGILITY] += (lvl > 38 ? 1: (lvl > 8 && (lvl%2) ? 1: 0)); - info->stats[STAT_INTELLECT] += (lvl > 22 ? 2: (lvl > 1 ? 1: 0)); - info->stats[STAT_SPIRIT] += (lvl > 3 ? 1: 0); - break; - case CLASS_SHAMAN: - info->stats[STAT_STRENGTH] += (lvl > 34 ? 1: (lvl > 6 && (lvl%2) ? 1: 0)); - info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); - info->stats[STAT_AGILITY] += (lvl > 7 && !(lvl%2) ? 1: 0); - info->stats[STAT_INTELLECT] += (lvl > 5 ? 1: 0); - info->stats[STAT_SPIRIT] += (lvl > 4 ? 1: 0); - break; - case CLASS_MAGE: - info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); - info->stats[STAT_STAMINA] += (lvl > 5 ? 1: 0); - info->stats[STAT_AGILITY] += (lvl > 9 && !(lvl%2) ? 1: 0); - info->stats[STAT_INTELLECT] += (lvl > 24 ? 2: (lvl > 1 ? 1: 0)); - info->stats[STAT_SPIRIT] += (lvl > 33 ? 2: (lvl > 2 ? 1: 0)); - break; - case CLASS_WARLOCK: - info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); - info->stats[STAT_STAMINA] += (lvl > 38 ? 2: (lvl > 3 ? 1: 0)); - info->stats[STAT_AGILITY] += (lvl > 9 && !(lvl%2) ? 1: 0); - info->stats[STAT_INTELLECT] += (lvl > 33 ? 2: (lvl > 2 ? 1: 0)); - info->stats[STAT_SPIRIT] += (lvl > 38 ? 2: (lvl > 3 ? 1: 0)); - break; - case CLASS_DRUID: - info->stats[STAT_STRENGTH] += (lvl > 38 ? 2: (lvl > 6 && (lvl%2) ? 1: 0)); - info->stats[STAT_STAMINA] += (lvl > 32 ? 2: (lvl > 4 ? 1: 0)); - info->stats[STAT_AGILITY] += (lvl > 38 ? 2: (lvl > 8 && (lvl%2) ? 1: 0)); - info->stats[STAT_INTELLECT] += (lvl > 38 ? 3: (lvl > 4 ? 1: 0)); - info->stats[STAT_SPIRIT] += (lvl > 38 ? 3: (lvl > 5 ? 1: 0)); - } - } -} - -void ObjectMgr::LoadGuilds() -{ - Guild *newGuild; - uint32 count = 0; - - // 0 1 2 3 4 5 6 - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT guild.guildid,guild.name,leaderguid,EmblemStyle,EmblemColor,BorderStyle,BorderColor," - // 7 8 9 10 11 12 - "BackgroundColor,info,motd,createdate,BankMoney,COUNT(guild_bank_tab.guildid) " - "FROM guild LEFT JOIN guild_bank_tab ON guild.guildid = guild_bank_tab.guildid GROUP BY guild.guildid ORDER BY guildid ASC"); - - if (!result) - { - - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u guild definitions", count); - return; - } - - // load guild ranks - // 0 1 2 3 4 - QueryResult_AutoPtr guildRanksResult = CharacterDatabase.Query("SELECT guildid,rid,rname,rights,BankMoneyPerDay FROM guild_rank ORDER BY guildid ASC, rid ASC"); - - // load guild members - // 0 1 2 3 4 5 6 - QueryResult_AutoPtr guildMembersResult = CharacterDatabase.Query("SELECT guildid,guild_member.guid,rank,pnote,offnote,BankResetTimeMoney,BankRemMoney," - // 7 8 9 10 11 12 - "BankResetTimeTab0,BankRemSlotsTab0,BankResetTimeTab1,BankRemSlotsTab1,BankResetTimeTab2,BankRemSlotsTab2," - // 13 14 15 16 17 18 - "BankResetTimeTab3,BankRemSlotsTab3,BankResetTimeTab4,BankRemSlotsTab4,BankResetTimeTab5,BankRemSlotsTab5," - // 19 20 21 22 23 - "characters.name, characters.level, characters.class, characters.zone, characters.logout_time " - "FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid ORDER BY guildid ASC"); - - // load guild bank tab rights - // 0 1 2 3 4 - QueryResult_AutoPtr guildBankTabRightsResult = CharacterDatabase.Query("SELECT guildid,TabId,rid,gbright,SlotPerDay FROM guild_bank_right ORDER BY guildid ASC, TabId ASC"); - - barGoLink bar(result->GetRowCount()); - - do - { - //Field *fields = result->Fetch(); - - bar.step(); - ++count; - - newGuild = new Guild; - if (!newGuild->LoadGuildFromDB(result) || - !newGuild->LoadRanksFromDB(guildRanksResult) || - !newGuild->LoadMembersFromDB(guildMembersResult) || - !newGuild->LoadBankRightsFromDB(guildBankTabRightsResult) || - !newGuild->CheckGuildStructure() -) - { - newGuild->Disband(); - delete newGuild; - continue; - } - newGuild->LoadGuildEventLogFromDB(); - newGuild->LoadGuildBankEventLogFromDB(); - newGuild->LoadGuildBankFromDB(); - AddGuild(newGuild); - - } while (result->NextRow()); - - //delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table - //you can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT - CharacterDatabase.PQuery("DELETE FROM guild_eventlog WHERE LogGuid > '%u'", sWorld.getConfig(CONFIG_GUILD_EVENT_LOG_COUNT)); - CharacterDatabase.PQuery("DELETE FROM guild_bank_eventlog WHERE LogGuid > '%u'", sWorld.getConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT)); - - sLog.outString(); - sLog.outString(">> Loaded %u guild definitions", count); -} - -void ObjectMgr::LoadArenaTeams() -{ - uint32 count = 0; - - // 0 1 2 3 4 5 - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT arena_team.arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle," - // 6 7 8 9 10 11 12 13 14 - "EmblemColor,BorderStyle,BorderColor, rating,games,wins,played,wins2,rank " - "FROM arena_team LEFT JOIN arena_team_stats ON arena_team.arenateamid = arena_team_stats.arenateamid ORDER BY arena_team.arenateamid ASC"); - - if (!result) - { - - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u arenateam definitions", count); - return; - } - - // load arena_team members - QueryResult_AutoPtr arenaTeamMembersResult = CharacterDatabase.Query( - // 0 1 2 3 4 5 6 7 8 - "SELECT arenateamid,member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class " - "FROM arena_team_member member LEFT JOIN characters chars on member.guid = chars.guid ORDER BY member.arenateamid ASC"); - - barGoLink bar(result->GetRowCount()); - - do - { - //Field *fields = result->Fetch(); - - bar.step(); - ++count; - - ArenaTeam *newArenaTeam = new ArenaTeam; - if (!newArenaTeam->LoadArenaTeamFromDB(result) || - !newArenaTeam->LoadMembersFromDB(arenaTeamMembersResult)) - { - newArenaTeam->Disband(NULL); - delete newArenaTeam; - continue; - } - AddArenaTeam(newArenaTeam); - }while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u arenateam definitions", count); -} - -void ObjectMgr::LoadGroups() -{ - Group *group = NULL; - Field *fields = NULL; - uint64 groupGuid = 0; - uint32 count = 0; - - // Consistency cleaning before load to avoid having to do some checks later - // Delete all members that does not exist - CharacterDatabase.PExecute("DELETE FROM group_member WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=memberGuid)"); - // Delete all groups whose leader does not exist - CharacterDatabase.PExecute("DELETE FROM groups WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=leaderGuid)"); - // Delete all groups with less than 2 members - CharacterDatabase.PExecute("DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)"); - // Delete all rows from group_member or group_instance with no group - CharacterDatabase.PExecute("DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)"); - CharacterDatabase.PExecute("DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)"); - - // ----------------------- Load Group definitions - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty, guid FROM groups"); - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded 0 group definitions"); - return; - } - - barGoLink bar(result->GetRowCount()); - do - { - bar.step(); - fields = result->Fetch(); - ++count; - group = new Group; - groupGuid = MAKE_NEW_GUID(fields[15].GetUInt32(),0,HIGHGUID_GROUP); - group->LoadGroupFromDB(groupGuid, result, false); - // group load will never be false (we have run consistency sql's before loading) - AddGroup(group); - }while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u group definitions", count); - - // ----------------------- Load member - // 0 1 2 3 - result = CharacterDatabase.Query("SELECT guid, memberGuid, memberFlags, subgroup FROM group_member ORDER BY guid"); - if (!result) - { - barGoLink bar2(1); - bar2.step(); - sLog.outString(); - sLog.outString(">> Loaded 0 group members"); - return; - } - - barGoLink bar2(result->GetRowCount()); - uint32 groupLowGuid = 0; - count = 0; - do - { - bar2.step(); - fields = result->Fetch(); - - if (groupLowGuid != fields[0].GetUInt32()) - { - groupLowGuid = fields[0].GetUInt32(); - groupGuid = MAKE_NEW_GUID(groupLowGuid, 0, HIGHGUID_GROUP); - group = GetGroupByGUID(groupGuid); - // group will never be NULL (we have run consistency sql's before loading) - } - group->LoadMemberFromDB(fields[1].GetUInt32(), fields[2].GetUInt8(), fields[3].GetUInt8()); - ++count; - }while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u group members", count); - - - // ----------------------- Load instance save - // 0 1 2 3 4 5 - result = CharacterDatabase.Query("SELECT guid, map, instance, permanent, difficulty, resettime, " - // 6 - "(SELECT COUNT(1) FROM groups JOIN character_instance ON leaderGuid = groups.guid WHERE instance = group_instance.instance AND permanent = 1 LIMIT 1) " - "FROM group_instance LEFT JOIN instance ON instance = id ORDER BY guid"); - - if (!result) - { - barGoLink bar2(1); - bar2.step(); - sLog.outString(); - sLog.outString(">> Loaded 0 group-instance saves"); - return; - } - - barGoLink bar3(result->GetRowCount()); - count = 0; - do - { - bar3.step(); - fields = result->Fetch(); - groupGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_GROUP); - group = GetGroupByGUID(groupGuid); - // group will never be NULL (we have run consistency sql's before loading) - - MapEntry const* mapEntry = sMapStore.LookupEntry(fields[1].GetUInt32()); - if (!mapEntry || !mapEntry->IsDungeon()) - { - sLog.outErrorDb("Incorrect entry in group_instance table : no dungeon map %d", fields[1].GetUInt32()); - continue; - } - - uint32 diff = fields[4].GetUInt8(); - if (diff >= (mapEntry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) - { - sLog.outErrorDb("Wrong dungeon difficulty use in group_instance table: %d", diff + 1); - diff = 0; // default for both difficaly types - } - - InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt64()), fields[6].GetBool(), true); - group->BindToInstance(save, fields[3].GetBool(), true); - ++count; - }while (result->NextRow()); - sLog.outString(); - sLog.outString(">> Loaded %u group-instance saves", count); -} - -void ObjectMgr::LoadQuests() -{ - // For reload case - for (QuestMap::const_iterator itr=mQuestTemplates.begin(); itr != mQuestTemplates.end(); ++itr) - delete itr->second; - mQuestTemplates.clear(); - - mExclusiveQuestGroups.clear(); - - // 0 1 2 3 4 5 6 7 8 9 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, Method, ZoneOrSort, SkillOrClassMask, MinLevel, MaxLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue," - // 10 11 12 13 14 15 16 17 18 19 - "RepObjectiveFaction, RepObjectiveValue, RepObjectiveFaction2, RepObjectiveValue2, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime," - // 20 21 22 23 24 25 26 27 28 29 30 31 32 33 - "QuestFlags, SpecialFlags, CharTitleId, PlayersSlain, BonusTalents, RewardArenaPoints, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, RewXPId, SrcItemId, SrcItemCount, SrcSpell," - // 34 35 36 37 38 39 40 41 42 43 44 - "Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, CompletedText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4," - // 45 46 47 48 49 50 51 52 53 54 55 56 - "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemId5, ReqItemId6, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4, ReqItemCount5, ReqItemCount6," - // 57 58 59 60 61 62 63 64 - "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4," - // 65 66 67 68 69 70 71 72 - "ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4," - // 73 74 75 76 - "ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4," - // 77 78 79 80 81 82 - "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6," - // 83 84 85 86 87 88 - "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6," - // 89 90 91 92 93 94 95 96 - "RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4," - // 97 98 99 100 101 102 103 104 105 106 - "RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValueId1, RewRepValueId2, RewRepValueId3, RewRepValueId4, RewRepValueId5," - // 107 108 109 110 111 - "RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5," - // 112 113 114 115 116 117 118 119 120 121 122 123 - "RewHonorAddition, RewHonorMultiplier, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt," - // 124 125 126 127 128 129 130 131 - "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4," - // 132 133 134 135 136 137 - "IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," - // 138 139 140 141 - "OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4," - // 142 143 - "StartScript, CompleteScript" - " FROM quest_template"); - if (result == NULL) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded 0 quests definitions"); - sLog.outErrorDb("`quest_template` table is empty!"); - return; - } - - // create multimap previous quest for each existed quest - // some quests can have many previous maps set by NextQuestId in previous quest - // for example set of race quests can lead to single not race specific quest - barGoLink bar(result->GetRowCount()); - do - { - bar.step(); - Field *fields = result->Fetch(); - - Quest * newQuest = new Quest(fields); - mQuestTemplates[newQuest->GetQuestId()] = newQuest; - } while (result->NextRow()); - - std::map usedMailTemplates; - - // Post processing - for (QuestMap::iterator iter = mQuestTemplates.begin(); iter != mQuestTemplates.end(); ++iter) - { - Quest * qinfo = iter->second; - - // additional quest integrity checks (GO, creature_template and item_template must be loaded already) - - if (qinfo->GetQuestMethod() >= 3) - { - sLog.outErrorDb("Quest %u has `Method` = %u, expected values are 0, 1 or 2.",qinfo->GetQuestId(),qinfo->GetQuestMethod()); - } - - if (qinfo->QuestFlags & ~QUEST_TRINITY_FLAGS_DB_ALLOWED) - { - sLog.outErrorDb("Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u", - qinfo->GetQuestId(),qinfo->QuestFlags >> 20, QUEST_TRINITY_FLAGS_DB_ALLOWED >> 20); - qinfo->QuestFlags &= QUEST_TRINITY_FLAGS_DB_ALLOWED; - } - - if (qinfo->QuestFlags & QUEST_FLAGS_DAILY && qinfo->QuestFlags & QUEST_FLAGS_WEEKLY) - { - sLog.outErrorDb("Weekly Quest %u is marked as daily quest in `QuestFlags`, removed daily flag.",qinfo->GetQuestId()); - qinfo->QuestFlags &= ~QUEST_FLAGS_DAILY; - } - - if (qinfo->QuestFlags & QUEST_FLAGS_DAILY) - { - if (!(qinfo->QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE)) - { - sLog.outErrorDb("Daily Quest %u not marked as repeatable in `SpecialFlags`, added.",qinfo->GetQuestId()); - qinfo->QuestFlags |= QUEST_TRINITY_FLAGS_REPEATABLE; - } - } - - if (qinfo->QuestFlags & QUEST_FLAGS_WEEKLY) - { - if (!(qinfo->QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE)) - { - sLog.outErrorDb("Weekly Quest %u not marked as repeatable in `SpecialFlags`, added.",qinfo->GetQuestId()); - qinfo->QuestFlags |= QUEST_TRINITY_FLAGS_REPEATABLE; - } - } - - if (qinfo->QuestFlags & QUEST_FLAGS_AUTO_REWARDED) - { - // at auto-reward can be rewarded only RewChoiceItemId[0] - for (int j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j ) - { - if (uint32 id = qinfo->RewChoiceItemId[j]) - { - sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but item from `RewChoiceItemId%d` can't be rewarded with quest flag QUEST_FLAGS_AUTO_REWARDED.", - qinfo->GetQuestId(),j+1,id,j+1); - // no changes, quest ignore this data - } - } - } - - // client quest log visual (area case) - if (qinfo->ZoneOrSort > 0) - { - if (!GetAreaEntryByAreaID(qinfo->ZoneOrSort)) - { - sLog.outErrorDb("Quest %u has `ZoneOrSort` = %u (zone case) but zone with this id does not exist.", - qinfo->GetQuestId(),qinfo->ZoneOrSort); - // no changes, quest not dependent from this value but can have problems at client - } - } - // client quest log visual (sort case) - if (qinfo->ZoneOrSort < 0) - { - QuestSortEntry const* qSort = sQuestSortStore.LookupEntry(-int32(qinfo->ZoneOrSort)); - if (!qSort) - { - sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (sort case) but quest sort with this id does not exist.", - qinfo->GetQuestId(),qinfo->ZoneOrSort); - // no changes, quest not dependent from this value but can have problems at client (note some may be 0, we must allow this so no check) - } - //check SkillOrClass value (class case). - if (ClassByQuestSort(-int32(qinfo->ZoneOrSort))) - { - // SkillOrClass should not have class case when class case already set in ZoneOrSort. - if (qinfo->SkillOrClassMask < 0) - { - sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (class sort case) and `SkillOrClassMask` = %i (class case), redundant.", - qinfo->GetQuestId(),qinfo->ZoneOrSort,qinfo->SkillOrClassMask); - } - } - //check for proper SkillOrClass value (skill case) - if (int32 skill_id = SkillByQuestSort(-int32(qinfo->ZoneOrSort))) - { - // skill is positive value in SkillOrClass - if (qinfo->SkillOrClassMask != skill_id) - { - sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (skill sort case) but `SkillOrClassMask` does not have a corresponding value (%i).", - qinfo->GetQuestId(),qinfo->ZoneOrSort,skill_id); - //override, and force proper value here? - } - } - } - - // SkillOrClassMask (class case) - if (qinfo->SkillOrClassMask < 0) - { - if (!(-int32(qinfo->SkillOrClassMask) & CLASSMASK_ALL_PLAYABLE)) - { - sLog.outErrorDb("Quest %u has `SkillOrClassMask` = %i (class case) but classmask does not have valid class", - qinfo->GetQuestId(),qinfo->SkillOrClassMask); - } - } - // SkillOrClassMask (skill case) - if (qinfo->SkillOrClassMask > 0) - { - if (!sSkillLineStore.LookupEntry(qinfo->SkillOrClassMask)) - { - sLog.outErrorDb("Quest %u has `SkillOrClass` = %u (skill case) but skill (%i) does not exist", - qinfo->GetQuestId(),qinfo->SkillOrClassMask,qinfo->SkillOrClassMask); - } - } - - if (qinfo->RequiredSkillValue) - { - if (qinfo->RequiredSkillValue > sWorld.GetConfigMaxSkillValue()) - { - sLog.outErrorDb("Quest %u has `RequiredSkillValue` = %u but max possible skill is %u, quest can't be done.", - qinfo->GetQuestId(),qinfo->RequiredSkillValue,sWorld.GetConfigMaxSkillValue()); - // no changes, quest can't be done for this requirement - } - - if (qinfo->SkillOrClassMask <= 0) - { - sLog.outErrorDb("Quest %u has `RequiredSkillValue` = %u but `SkillOrClass` = %i (class case), value ignored.", - qinfo->GetQuestId(),qinfo->RequiredSkillValue,qinfo->SkillOrClassMask); - // no changes, quest can't be done for this requirement (fail at wrong skill id) - } - } - // else Skill quests can have 0 skill level, this is ok - - if (qinfo->RepObjectiveFaction2 && !sFactionStore.LookupEntry(qinfo->RepObjectiveFaction2)) - { - sLog.outErrorDb("Quest %u has `RepObjectiveFaction2` = %u but faction template %u does not exist, quest can't be done.", - qinfo->GetQuestId(),qinfo->RepObjectiveFaction2,qinfo->RepObjectiveFaction2); - // no changes, quest can't be done for this requirement - } - - if (qinfo->RepObjectiveFaction && !sFactionStore.LookupEntry(qinfo->RepObjectiveFaction)) - { - sLog.outErrorDb("Quest %u has `RepObjectiveFaction` = %u but faction template %u does not exist, quest can't be done.", - qinfo->GetQuestId(),qinfo->RepObjectiveFaction,qinfo->RepObjectiveFaction); - // no changes, quest can't be done for this requirement - } - - if (qinfo->RequiredMinRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMinRepFaction)) - { - sLog.outErrorDb("Quest %u has `RequiredMinRepFaction` = %u but faction template %u does not exist, quest can't be done.", - qinfo->GetQuestId(),qinfo->RequiredMinRepFaction,qinfo->RequiredMinRepFaction); - // no changes, quest can't be done for this requirement - } - - if (qinfo->RequiredMaxRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMaxRepFaction)) - { - sLog.outErrorDb("Quest %u has `RequiredMaxRepFaction` = %u but faction template %u does not exist, quest can't be done.", - qinfo->GetQuestId(),qinfo->RequiredMaxRepFaction,qinfo->RequiredMaxRepFaction); - // no changes, quest can't be done for this requirement - } - - if (qinfo->RequiredMinRepValue && qinfo->RequiredMinRepValue > ReputationMgr::Reputation_Cap) - { - sLog.outErrorDb("Quest %u has `RequiredMinRepValue` = %d but max reputation is %u, quest can't be done.", - qinfo->GetQuestId(),qinfo->RequiredMinRepValue,ReputationMgr::Reputation_Cap); - // no changes, quest can't be done for this requirement - } - - if (qinfo->RequiredMinRepValue && qinfo->RequiredMaxRepValue && qinfo->RequiredMaxRepValue <= qinfo->RequiredMinRepValue) - { - sLog.outErrorDb("Quest %u has `RequiredMaxRepValue` = %d and `RequiredMinRepValue` = %d, quest can't be done.", - qinfo->GetQuestId(),qinfo->RequiredMaxRepValue,qinfo->RequiredMinRepValue); - // no changes, quest can't be done for this requirement - } - - if (!qinfo->RepObjectiveFaction && qinfo->RepObjectiveValue > 0) - { - sLog.outErrorDb("Quest %u has `RepObjectiveValue` = %d but `RepObjectiveFaction` is 0, value has no effect", - qinfo->GetQuestId(),qinfo->RepObjectiveValue); - // warning - } - - if (!qinfo->RepObjectiveFaction2 && qinfo->RepObjectiveValue2 > 0) - { - sLog.outErrorDb("Quest %u has `RepObjectiveValue2` = %d but `RepObjectiveFaction2` is 0, value has no effect", - qinfo->GetQuestId(),qinfo->RepObjectiveValue2); - // warning - } - - if (!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue > 0) - { - sLog.outErrorDb("Quest %u has `RequiredMinRepValue` = %d but `RequiredMinRepFaction` is 0, value has no effect", - qinfo->GetQuestId(),qinfo->RequiredMinRepValue); - // warning - } - - if (!qinfo->RequiredMaxRepFaction && qinfo->RequiredMaxRepValue > 0) - { - sLog.outErrorDb("Quest %u has `RequiredMaxRepValue` = %d but `RequiredMaxRepFaction` is 0, value has no effect", - qinfo->GetQuestId(),qinfo->RequiredMaxRepValue); - // warning - } - - if (qinfo->CharTitleId && !sCharTitlesStore.LookupEntry(qinfo->CharTitleId)) - { - sLog.outErrorDb("Quest %u has `CharTitleId` = %u but CharTitle Id %u does not exist, quest can't be rewarded with title.", - qinfo->GetQuestId(),qinfo->GetCharTitleId(),qinfo->GetCharTitleId()); - qinfo->CharTitleId = 0; - // quest can't reward this title - } - - if (qinfo->SrcItemId) - { - if (!sItemStorage.LookupEntry(qinfo->SrcItemId)) - { - sLog.outErrorDb("Quest %u has `SrcItemId` = %u but item with entry %u does not exist, quest can't be done.", - qinfo->GetQuestId(),qinfo->SrcItemId,qinfo->SrcItemId); - qinfo->SrcItemId = 0; // quest can't be done for this requirement - } - else if (qinfo->SrcItemCount == 0) - { - sLog.outErrorDb("Quest %u has `SrcItemId` = %u but `SrcItemCount` = 0, set to 1 but need fix in DB.", - qinfo->GetQuestId(),qinfo->SrcItemId); - qinfo->SrcItemCount = 1; // update to 1 for allow quest work for backward compatibility with DB - } - } - else if (qinfo->SrcItemCount>0) - { - sLog.outErrorDb("Quest %u has `SrcItemId` = 0 but `SrcItemCount` = %u, useless value.", - qinfo->GetQuestId(),qinfo->SrcItemCount); - qinfo->SrcItemCount=0; // no quest work changes in fact - } - - if (qinfo->SrcSpell) - { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->SrcSpell); - if (!spellInfo) - { - sLog.outErrorDb("Quest %u has `SrcSpell` = %u but spell %u doesn't exist, quest can't be done.", - qinfo->GetQuestId(),qinfo->SrcSpell,qinfo->SrcSpell); - qinfo->SrcSpell = 0; // quest can't be done for this requirement - } - else if (!SpellMgr::IsSpellValid(spellInfo)) - { - sLog.outErrorDb("Quest %u has `SrcSpell` = %u but spell %u is broken, quest can't be done.", - qinfo->GetQuestId(),qinfo->SrcSpell,qinfo->SrcSpell); - qinfo->SrcSpell = 0; // quest can't be done for this requirement - } - } - - for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j) - { - uint32 id = qinfo->ReqItemId[j]; - if (id) - { - if (qinfo->ReqItemCount[j] == 0) - { - sLog.outErrorDb("Quest %u has `ReqItemId%d` = %u but `ReqItemCount%d` = 0, quest can't be done.", - qinfo->GetQuestId(),j+1,id,j+1); - // no changes, quest can't be done for this requirement - } - - qinfo->SetFlag(QUEST_TRINITY_FLAGS_DELIVER); - - if (!sItemStorage.LookupEntry(id)) - { - sLog.outErrorDb("Quest %u has `ReqItemId%d` = %u but item with entry %u does not exist, quest can't be done.", - qinfo->GetQuestId(),j+1,id,id); - qinfo->ReqItemCount[j] = 0; // prevent incorrect work of quest - } - } - else if (qinfo->ReqItemCount[j]>0) - { - sLog.outErrorDb("Quest %u has `ReqItemId%d` = 0 but `ReqItemCount%d` = %u, quest can't be done.", - qinfo->GetQuestId(),j+1,j+1,qinfo->ReqItemCount[j]); - qinfo->ReqItemCount[j] = 0; // prevent incorrect work of quest - } - } - - for (uint8 j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j) - { - uint32 id = qinfo->ReqSourceId[j]; - if (id) - { - if (!sItemStorage.LookupEntry(id)) - { - sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but item with entry %u does not exist, quest can't be done.", - qinfo->GetQuestId(),j+1,id,id); - // no changes, quest can't be done for this requirement - } - } - else - { - if (qinfo->ReqSourceCount[j]>0) - { - sLog.outErrorDb("Quest %u has `ReqSourceId%d` = 0 but `ReqSourceCount%d` = %u.", - qinfo->GetQuestId(),j+1,j+1,qinfo->ReqSourceCount[j]); - // no changes, quest ignore this data - } - } - } - - for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) - { - uint32 id = qinfo->ReqSpell[j]; - if (id) - { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(id); - if (!spellInfo) - { - sLog.outErrorDb("Quest %u has `ReqSpellCast%d` = %u but spell %u does not exist, quest can't be done.", - qinfo->GetQuestId(),j+1,id,id); - continue; - } - - if (!qinfo->ReqCreatureOrGOId[j]) - { - bool found = false; - for (uint8 k = 0; k < 3; ++k) - { - if ((spellInfo->Effect[k] == SPELL_EFFECT_QUEST_COMPLETE && uint32(spellInfo->EffectMiscValue[k]) == qinfo->QuestId) || - spellInfo->Effect[k] == SPELL_EFFECT_SEND_EVENT) - { - found = true; - break; - } - } - - if (found) - { - if (!qinfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) - { - sLog.outErrorDb("Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and ReqCreatureOrGOId%d = 0, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags or ReqCreatureOrGOId%d must be fixed, quest modified to enable objective.",spellInfo->Id,qinfo->QuestId,j+1,j+1); - - // this will prevent quest completing without objective - const_cast(qinfo)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); - } - } - else - { - sLog.outErrorDb("Quest %u has `ReqSpellCast%d` = %u and ReqCreatureOrGOId%d = 0 but spell %u does not have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT effect for this quest, quest can't be done.", - qinfo->GetQuestId(),j+1,id,j+1,id); - // no changes, quest can't be done for this requirement - } - } - } - } - - for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) - { - int32 id = qinfo->ReqCreatureOrGOId[j]; - if (id < 0 && !sGOStorage.LookupEntry(-id)) - { - sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %i but gameobject %u does not exist, quest can't be done.", - qinfo->GetQuestId(),j+1,id,uint32(-id)); - qinfo->ReqCreatureOrGOId[j] = 0; // quest can't be done for this requirement - } - - if (id > 0 && !sCreatureStorage.LookupEntry(id)) - { - sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %i but creature with entry %u does not exist, quest can't be done.", - qinfo->GetQuestId(),j+1,id,uint32(id)); - qinfo->ReqCreatureOrGOId[j] = 0; // quest can't be done for this requirement - } - - if (id) - { - // In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast - - qinfo->SetFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO); - - if (!qinfo->ReqCreatureOrGOCount[j]) - { - sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %u but `ReqCreatureOrGOCount%d` = 0, quest can't be done.", - qinfo->GetQuestId(),j+1,id,j+1); - // no changes, quest can be incorrectly done, but we already report this - } - } - else if (qinfo->ReqCreatureOrGOCount[j]>0) - { - sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = 0 but `ReqCreatureOrGOCount%d` = %u.", - qinfo->GetQuestId(),j+1,j+1,qinfo->ReqCreatureOrGOCount[j]); - // no changes, quest ignore this data - } - } - - for (uint8 j = 0; j < QUEST_REWARD_CHOICES_COUNT; ++j) - { - uint32 id = qinfo->RewChoiceItemId[j]; - if (id) - { - if (!sItemStorage.LookupEntry(id)) - { - sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but item with entry %u does not exist, quest will not reward this item.", - qinfo->GetQuestId(),j+1,id,id); - qinfo->RewChoiceItemId[j] = 0; // no changes, quest will not reward this - } - - if (!qinfo->RewChoiceItemCount[j]) - { - sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but `RewChoiceItemCount%d` = 0, quest can't be done.", - qinfo->GetQuestId(),j+1,id,j+1); - // no changes, quest can't be done - } - } - else if (qinfo->RewChoiceItemCount[j]>0) - { - sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = 0 but `RewChoiceItemCount%d` = %u.", - qinfo->GetQuestId(),j+1,j+1,qinfo->RewChoiceItemCount[j]); - // no changes, quest ignore this data - } - } - - for (uint8 j = 0; j < QUEST_REWARDS_COUNT; ++j) - { - uint32 id = qinfo->RewItemId[j]; - if (id) - { - if (!sItemStorage.LookupEntry(id)) - { - sLog.outErrorDb("Quest %u has `RewItemId%d` = %u but item with entry %u does not exist, quest will not reward this item.", - qinfo->GetQuestId(),j+1,id,id); - qinfo->RewItemId[j] = 0; // no changes, quest will not reward this item - } - - if (!qinfo->RewItemCount[j]) - { - sLog.outErrorDb("Quest %u has `RewItemId%d` = %u but `RewItemCount%d` = 0, quest will not reward this item.", - qinfo->GetQuestId(),j+1,id,j+1); - // no changes - } - } - else if (qinfo->RewItemCount[j]>0) - { - sLog.outErrorDb("Quest %u has `RewItemId%d` = 0 but `RewItemCount%d` = %u.", - qinfo->GetQuestId(),j+1,j+1,qinfo->RewItemCount[j]); - // no changes, quest ignore this data - } - } - - for (uint8 j = 0; j < QUEST_REPUTATIONS_COUNT; ++j) - { - if (qinfo->RewRepFaction[j]) - { - if (abs(qinfo->RewRepValueId[j]) > 9) - { - sLog.outErrorDb("Quest %u has RewRepValueId%d = %i. That is outside the range of valid values (-9 to 9).", qinfo->GetQuestId(), j+1, qinfo->RewRepValueId[j]); - } - if (!sFactionStore.LookupEntry(qinfo->RewRepFaction[j])) - { - sLog.outErrorDb("Quest %u has `RewRepFaction%d` = %u but raw faction (faction.dbc) %u does not exist, quest will not reward reputation for this faction.", qinfo->GetQuestId(),j+1,qinfo->RewRepFaction[j] ,qinfo->RewRepFaction[j]); - qinfo->RewRepFaction[j] = 0; // quest will not reward this - } - } - - - else if (qinfo->RewRepValue[j] != 0) - { - sLog.outErrorDb("Quest %u has `RewRepFaction%d` = 0 but `RewRepValue%d` = %i.", - qinfo->GetQuestId(),j+1,j+1,qinfo->RewRepValue[j]); - // no changes, quest ignore this data - } - } - - - if (qinfo->RewSpell) - { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->RewSpell); - - if (!spellInfo) - { - sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u does not exist, spell removed as display reward.", - qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell); - qinfo->RewSpell = 0; // no spell reward will display for this quest - } - - else if (!SpellMgr::IsSpellValid(spellInfo)) - { - sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is broken, quest will not have a spell reward.", - qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell); - qinfo->RewSpell = 0; // no spell reward will display for this quest - } - - else if (GetTalentSpellCost(qinfo->RewSpell)) - { - sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is talent, quest will not have a spell reward.", - qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell); - qinfo->RewSpell = 0; // no spell reward will display for this quest - } - } - - if (qinfo->RewSpellCast > 0) - { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->RewSpellCast); - - if (!spellInfo) - { - sLog.outErrorDb("Quest %u has `RewSpellCast` = %u but spell %u does not exist, quest will not have a spell reward.", - qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast); - qinfo->RewSpellCast = 0; // no spell will be casted on player - } - - else if (!SpellMgr::IsSpellValid(spellInfo)) - { - sLog.outErrorDb("Quest %u has `RewSpellCast` = %u but spell %u is broken, quest will not have a spell reward.", - qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast); - qinfo->RewSpellCast = 0; // no spell will be casted on player - } - - else if (GetTalentSpellCost(qinfo->RewSpellCast)) - { - sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is talent, quest will not have a spell reward.", - qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast); - qinfo->RewSpellCast = 0; // no spell will be casted on player - } - } - - if (qinfo->RewMailTemplateId) - { - if (!sMailTemplateStore.LookupEntry(qinfo->RewMailTemplateId)) - { - sLog.outErrorDb("Quest %u has `RewMailTemplateId` = %u but mail template %u does not exist, quest will not have a mail reward.", - qinfo->GetQuestId(),qinfo->RewMailTemplateId,qinfo->RewMailTemplateId); - qinfo->RewMailTemplateId = 0; // no mail will send to player - qinfo->RewMailDelaySecs = 0; // no mail will send to player - } - else if (usedMailTemplates.find(qinfo->RewMailTemplateId) != usedMailTemplates.end()) - { - std::map::const_iterator used_mt_itr = usedMailTemplates.find(qinfo->RewMailTemplateId); - sLog.outErrorDb("Quest %u has `RewMailTemplateId` = %u but mail template %u already used for quest %u, quest will not have a mail reward.", - qinfo->GetQuestId(),qinfo->RewMailTemplateId,qinfo->RewMailTemplateId,used_mt_itr->second); - qinfo->RewMailTemplateId = 0; // no mail will send to player - qinfo->RewMailDelaySecs = 0; // no mail will send to player - } - else - usedMailTemplates[qinfo->RewMailTemplateId] = qinfo->GetQuestId(); - } - - if (qinfo->NextQuestInChain) - { - QuestMap::iterator qNextItr = mQuestTemplates.find(qinfo->NextQuestInChain); - if (qNextItr == mQuestTemplates.end()) - { - sLog.outErrorDb("Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.", - qinfo->GetQuestId(),qinfo->NextQuestInChain ,qinfo->NextQuestInChain); - qinfo->NextQuestInChain = 0; - } - else - qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId()); - } - - // fill additional data stores - if (qinfo->PrevQuestId) - { - if (mQuestTemplates.find(abs(qinfo->GetPrevQuestId())) == mQuestTemplates.end()) - { - sLog.outErrorDb("Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId()); - } - else - { - qinfo->prevQuests.push_back(qinfo->PrevQuestId); - } - } - - if (qinfo->NextQuestId) - { - QuestMap::iterator qNextItr = mQuestTemplates.find(abs(qinfo->GetNextQuestId())); - if (qNextItr == mQuestTemplates.end()) - { - sLog.outErrorDb("Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId()); - } - else - { - int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId()); - qNextItr->second->prevQuests.push_back(signedQuestId); - } - } - - if (qinfo->ExclusiveGroup) - mExclusiveQuestGroups.insert(std::pair(qinfo->ExclusiveGroup, qinfo->GetQuestId())); - if (qinfo->LimitTime) - qinfo->SetFlag(QUEST_TRINITY_FLAGS_TIMED); - } - - // check QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE - for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(i); - if (!spellInfo) - continue; - - for (uint8 j = 0; j < 3; ++j) - { - if (spellInfo->Effect[j] != SPELL_EFFECT_QUEST_COMPLETE) - continue; - - uint32 quest_id = spellInfo->EffectMiscValue[j]; - - Quest const* quest = GetQuestTemplate(quest_id); - - // some quest referenced in spells not exist (outdated spells) - if (!quest) - continue; - - if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) - { - sLog.outErrorDb("Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u , but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective.",spellInfo->Id,quest_id); - - // this will prevent quest completing without objective - const_cast(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); - } - } - } - - sLog.outString(); - sLog.outString(">> Loaded %lu quests definitions", (unsigned long)mQuestTemplates.size()); -} - -void ObjectMgr::LoadQuestLocales() -{ - mQuestLocaleMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry," - "Title_loc1,Details_loc1,Objectives_loc1,OfferRewardText_loc1,RequestItemsText_loc1,EndText_loc1,CompletedText_loc1,ObjectiveText1_loc1,ObjectiveText2_loc1,ObjectiveText3_loc1,ObjectiveText4_loc1," - "Title_loc2,Details_loc2,Objectives_loc2,OfferRewardText_loc2,RequestItemsText_loc2,EndText_loc2,CompletedText_loc2,ObjectiveText1_loc2,ObjectiveText2_loc2,ObjectiveText3_loc2,ObjectiveText4_loc2," - "Title_loc3,Details_loc3,Objectives_loc3,OfferRewardText_loc3,RequestItemsText_loc3,EndText_loc3,CompletedText_loc3,ObjectiveText1_loc3,ObjectiveText2_loc3,ObjectiveText3_loc3,ObjectiveText4_loc3," - "Title_loc4,Details_loc4,Objectives_loc4,OfferRewardText_loc4,RequestItemsText_loc4,EndText_loc4,CompletedText_loc4,ObjectiveText1_loc4,ObjectiveText2_loc4,ObjectiveText3_loc4,ObjectiveText4_loc4," - "Title_loc5,Details_loc5,Objectives_loc5,OfferRewardText_loc5,RequestItemsText_loc5,EndText_loc5,CompletedText_loc5,ObjectiveText1_loc5,ObjectiveText2_loc5,ObjectiveText3_loc5,ObjectiveText4_loc5," - "Title_loc6,Details_loc6,Objectives_loc6,OfferRewardText_loc6,RequestItemsText_loc6,EndText_loc6,CompletedText_loc6,ObjectiveText1_loc6,ObjectiveText2_loc6,ObjectiveText3_loc6,ObjectiveText4_loc6," - "Title_loc7,Details_loc7,Objectives_loc7,OfferRewardText_loc7,RequestItemsText_loc7,EndText_loc7,CompletedText_loc7,ObjectiveText1_loc7,ObjectiveText2_loc7,ObjectiveText3_loc7,ObjectiveText4_loc7," - "Title_loc8,Details_loc8,Objectives_loc8,OfferRewardText_loc8,RequestItemsText_loc8,EndText_loc8,CompletedText_loc8,ObjectiveText1_loc8,ObjectiveText2_loc8,ObjectiveText3_loc8,ObjectiveText4_loc8" - " FROM locales_quest" -); - - if (!result) - return; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 entry = fields[0].GetUInt32(); - - QuestLocale& data = mQuestLocaleMap[entry]; - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[1+11*(i-1)].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Title.size() <= idx) - data.Title.resize(idx+1); - - data.Title[idx] = str; - } - } - str = fields[1+11*(i-1)+1].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Details.size() <= idx) - data.Details.resize(idx+1); - - data.Details[idx] = str; - } - } - str = fields[1+11*(i-1)+2].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Objectives.size() <= idx) - data.Objectives.resize(idx+1); - - data.Objectives[idx] = str; - } - } - str = fields[1+11*(i-1)+3].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.OfferRewardText.size() <= idx) - data.OfferRewardText.resize(idx+1); - - data.OfferRewardText[idx] = str; - } - } - str = fields[1+11*(i-1)+4].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.RequestItemsText.size() <= idx) - data.RequestItemsText.resize(idx+1); - - data.RequestItemsText[idx] = str; - } - } - str = fields[1+11*(i-1)+5].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.EndText.size() <= idx) - data.EndText.resize(idx+1); - - data.EndText[idx] = str; - } - } - str = fields[1+11*(i-1)+6].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.CompletedText.size() <= idx) - data.CompletedText.resize(idx+1); - - data.CompletedText[idx] = str; - } - } - - for (uint8 k = 0; k < 4; ++k) - { - str = fields[1+11*(i-1)+7+k].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.ObjectiveText[k].size() <= idx) - data.ObjectiveText[k].resize(idx+1); - - data.ObjectiveText[k][idx] = str; - } - } - } - } - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu Quest locale strings", (unsigned long)mQuestLocaleMap.size()); -} - -void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) -{ - if (sWorld.IsScriptScheduled()) // function don't must be called in time scripts use. - return; - - sLog.outString("%s :", tablename); - - scripts.clear(); // need for reload support - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id,delay,command,datalong,datalong2,dataint, x, y, z, o FROM %s", tablename); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u script definitions", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Field *fields = result->Fetch(); - ScriptInfo tmp; - tmp.id = fields[0].GetUInt32(); - tmp.delay = fields[1].GetUInt32(); - tmp.command = fields[2].GetUInt32(); - tmp.datalong = fields[3].GetUInt32(); - tmp.datalong2 = fields[4].GetUInt32(); - tmp.dataint = fields[5].GetInt32(); - tmp.x = fields[6].GetFloat(); - tmp.y = fields[7].GetFloat(); - tmp.z = fields[8].GetFloat(); - tmp.o = fields[9].GetFloat(); - - // generic command args check - switch (tmp.command) - { - case SCRIPT_COMMAND_TALK: - { - if (tmp.datalong > CHAT_TYPE_WHISPER) - { - sLog.outErrorDb("Table `%s` has invalid talk type (datalong = %u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.datalong,tmp.id); - continue; - } - if (tmp.dataint == 0) - { - sLog.outErrorDb("Table `%s` has invalid talk text id (dataint = %i) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.dataint,tmp.id); - continue; - } - if (tmp.dataint < MIN_DB_SCRIPT_STRING_ID || tmp.dataint >= MAX_DB_SCRIPT_STRING_ID) - { - sLog.outErrorDb("Table `%s` has out of range text id (dataint = %i expected %u-%u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.dataint,MIN_DB_SCRIPT_STRING_ID,MAX_DB_SCRIPT_STRING_ID,tmp.id); - continue; - } - - break; - } - - case SCRIPT_COMMAND_EMOTE: - { - if (!sEmotesStore.LookupEntry(tmp.datalong)) - { - sLog.outErrorDb("Table `%s` has invalid emote id (datalong = %u) in SCRIPT_COMMAND_EMOTE for script id %u",tablename,tmp.datalong,tmp.id); - continue; - } - break; - } - - case SCRIPT_COMMAND_TELEPORT_TO: - { - if (!sMapStore.LookupEntry(tmp.datalong)) - { - sLog.outErrorDb("Table `%s` has invalid map (Id: %u) in SCRIPT_COMMAND_TELEPORT_TO for script id %u",tablename,tmp.datalong,tmp.id); - continue; - } - - if (!Trinity::IsValidMapCoord(tmp.x,tmp.y,tmp.z,tmp.o)) - { - sLog.outErrorDb("Table `%s` has invalid coordinates (X: %f Y: %f) in SCRIPT_COMMAND_TELEPORT_TO for script id %u",tablename,tmp.x,tmp.y,tmp.id); - continue; - } - break; - } - - case SCRIPT_COMMAND_KILL_CREDIT: - { - if (!GetCreatureTemplate(tmp.datalong)) - { - sLog.outErrorDb("Table `%s` has invalid creature (Entry: %u) in SCRIPT_COMMAND_KILL_CREDIT for script id %u",tablename,tmp.datalong,tmp.id); - continue; - } - break; - } - - case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: - { - if (!Trinity::IsValidMapCoord(tmp.x,tmp.y,tmp.z,tmp.o)) - { - sLog.outErrorDb("Table `%s` has invalid coordinates (X: %f Y: %f) in SCRIPT_COMMAND_TEMP_SUMMON_CREATURE for script id %u",tablename,tmp.x,tmp.y,tmp.id); - continue; - } - - if (!GetCreatureTemplate(tmp.datalong)) - { - sLog.outErrorDb("Table `%s` has invalid creature (Entry: %u) in SCRIPT_COMMAND_TEMP_SUMMON_CREATURE for script id %u",tablename,tmp.datalong,tmp.id); - continue; - } - break; - } - - case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: - { - GameObjectData const* data = GetGOData(tmp.datalong); - if (!data) - { - sLog.outErrorDb("Table `%s` has invalid gameobject (GUID: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,tmp.datalong,tmp.id); - continue; - } - - GameObjectInfo const* info = GetGameObjectInfo(data->id); - if (!info) - { - sLog.outErrorDb("Table `%s` has gameobject with invalid entry (GUID: %u Entry: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,tmp.datalong,data->id,tmp.id); - continue; - } - - if (info->type == GAMEOBJECT_TYPE_FISHINGNODE || - info->type == GAMEOBJECT_TYPE_FISHINGHOLE || - info->type == GAMEOBJECT_TYPE_DOOR || - info->type == GAMEOBJECT_TYPE_BUTTON || - info->type == GAMEOBJECT_TYPE_TRAP) - { - sLog.outErrorDb("Table `%s` have gameobject type (%u) unsupported by command SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,info->id,tmp.id); - continue; - } - break; - } - case SCRIPT_COMMAND_OPEN_DOOR: - case SCRIPT_COMMAND_CLOSE_DOOR: - { - GameObjectData const* data = GetGOData(tmp.datalong); - if (!data) - { - sLog.outErrorDb("Table `%s` has invalid gameobject (GUID: %u) in %s for script id %u",tablename,tmp.datalong,(tmp.command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); - continue; - } - - GameObjectInfo const* info = GetGameObjectInfo(data->id); - if (!info) - { - sLog.outErrorDb("Table `%s` has gameobject with invalid entry (GUID: %u Entry: %u) in %s for script id %u",tablename,tmp.datalong,data->id,(tmp.command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); - continue; - } - - if (info->type != GAMEOBJECT_TYPE_DOOR) - { - sLog.outErrorDb("Table `%s` has gameobject type (%u) non supported by command %s for script id %u",tablename,info->id,(tmp.command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); - continue; - } - - break; - } - case SCRIPT_COMMAND_QUEST_EXPLORED: - { - Quest const* quest = GetQuestTemplate(tmp.datalong); - if (!quest) - { - sLog.outErrorDb("Table `%s` has invalid quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u",tablename,tmp.datalong,tmp.id); - continue; - } - - if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) - { - sLog.outErrorDb("Table `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective.",tablename,tmp.datalong,tmp.id); - - // this will prevent quest completing without objective - const_cast(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); - - // continue; - quest objective requirement set and command can be allowed - } - - if (float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) - { - sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u", - tablename,tmp.datalong2,tmp.id); - continue; - } - - if (tmp.datalong2 && float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) - { - sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, max distance is %f or 0 for disable distance check", - tablename,tmp.datalong2,tmp.id,DEFAULT_VISIBILITY_DISTANCE); - continue; - } - - if (tmp.datalong2 && float(tmp.datalong2) < INTERACTION_DISTANCE) - { - sLog.outErrorDb("Table `%s` has too small distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, min distance is %f or 0 for disable distance check", - tablename,tmp.datalong2,tmp.id,INTERACTION_DISTANCE); - continue; - } - - break; - } - - case SCRIPT_COMMAND_REMOVE_AURA: - { - if (!sSpellStore.LookupEntry(tmp.datalong)) - { - sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u", - tablename,tmp.datalong,tmp.id); - continue; - } - if (tmp.datalong2 & ~0x1) // 1 bits (0,1) - { - sLog.outErrorDb("Table `%s` using unknown flags in datalong2 (%u)i n SCRIPT_COMMAND_CAST_SPELL for script id %u", - tablename,tmp.datalong2,tmp.id); - continue; - } - break; - } - case SCRIPT_COMMAND_CAST_SPELL: - { - if (!sSpellStore.LookupEntry(tmp.datalong)) - { - sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u", - tablename,tmp.datalong,tmp.id); - continue; - } - if (tmp.datalong2 & ~0x3) // 2 bits - { - sLog.outErrorDb("Table `%s` using unknown flags in datalong2 (%u)i n SCRIPT_COMMAND_CAST_SPELL for script id %u", - tablename,tmp.datalong2,tmp.id); - continue; - } - break; - } - - case SCRIPT_COMMAND_CREATE_ITEM: - { - if (!GetItemPrototype(tmp.datalong)) - { - sLog.outErrorDb("Table `%s` has nonexistent item (entry: %u) in SCRIPT_COMMAND_CREATE_ITEM for script id %u", - tablename, tmp.datalong, tmp.id); - continue; - } - if (!tmp.datalong2) - { - sLog.outErrorDb("Table `%s` SCRIPT_COMMAND_CREATE_ITEM but amount is %u for script id %u", - tablename, tmp.datalong2, tmp.id); - continue; - } - break; - } - } - - if (scripts.find(tmp.id) == scripts.end()) - { - ScriptMap emptyMap; - scripts[tmp.id] = emptyMap; - } - scripts[tmp.id].insert(std::pair(tmp.delay, tmp)); - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u script definitions", count); -} - -void ObjectMgr::LoadGameObjectScripts() -{ - LoadScripts(sGameObjectScripts, "gameobject_scripts"); - - // check ids - for (ScriptMapMap::const_iterator itr = sGameObjectScripts.begin(); itr != sGameObjectScripts.end(); ++itr) - { - if (!GetGOData(itr->first)) - sLog.outErrorDb("Table `gameobject_scripts` has not existing gameobject (GUID: %u) as script id",itr->first); - } -} - -void ObjectMgr::LoadQuestEndScripts() -{ - LoadScripts(sQuestEndScripts, "quest_end_scripts"); - - // check ids - for (ScriptMapMap::const_iterator itr = sQuestEndScripts.begin(); itr != sQuestEndScripts.end(); ++itr) - { - if (!GetQuestTemplate(itr->first)) - sLog.outErrorDb("Table `quest_end_scripts` has not existing quest (Id: %u) as script id",itr->first); - } -} - -void ObjectMgr::LoadQuestStartScripts() -{ - LoadScripts(sQuestStartScripts,"quest_start_scripts"); - - // check ids - for (ScriptMapMap::const_iterator itr = sQuestStartScripts.begin(); itr != sQuestStartScripts.end(); ++itr) - { - if (!GetQuestTemplate(itr->first)) - sLog.outErrorDb("Table `quest_start_scripts` has not existing quest (Id: %u) as script id",itr->first); - } -} - -void ObjectMgr::LoadSpellScripts() -{ - LoadScripts(sSpellScripts, "spell_scripts"); - - // check ids - for (ScriptMapMap::const_iterator itr = sSpellScripts.begin(); itr != sSpellScripts.end(); ++itr) - { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first); - - if (!spellInfo) - { - sLog.outErrorDb("Table `spell_scripts` has not existing spell (Id: %u) as script id",itr->first); - continue; - } - - //check for correct spellEffect - bool found = false; - for (uint8 i=0; i<3; ++i) - { - // skip empty effects - if (!spellInfo->Effect[i]) - continue; - - if (spellInfo->Effect[i] == SPELL_EFFECT_SCRIPT_EFFECT) - { - found = true; - break; - } - } - - if (!found) - sLog.outErrorDb("Table `spell_scripts` has unsupported spell (Id: %u) without SPELL_EFFECT_SCRIPT_EFFECT (%u) spell effect",itr->first,SPELL_EFFECT_SCRIPT_EFFECT); - } -} - -void ObjectMgr::LoadEventScripts() -{ - LoadScripts(sEventScripts, "event_scripts"); - - std::set evt_scripts; - // Load all possible script entries from gameobjects - for (uint32 i = 1; i < sGOStorage.MaxEntry; ++i) - { - GameObjectInfo const * goInfo = sGOStorage.LookupEntry(i); - if (goInfo) - { - switch(goInfo->type) - { - case GAMEOBJECT_TYPE_GOOBER: - if (goInfo->goober.eventId) - evt_scripts.insert(goInfo->goober.eventId); - break; - case GAMEOBJECT_TYPE_CHEST: - if (goInfo->chest.eventId) - evt_scripts.insert(goInfo->chest.eventId); - break; - case GAMEOBJECT_TYPE_CAMERA: - if (goInfo->camera.eventID) - evt_scripts.insert(goInfo->camera.eventID); - default: - break; - } - } - } - // Load all possible script entries from spells - for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) - { - SpellEntry const * spell = sSpellStore.LookupEntry(i); - if (spell) - { - for (uint8 j=0; j<3; ++j) - { - if (spell->Effect[j] == SPELL_EFFECT_SEND_EVENT) - { - if (spell->EffectMiscValue[j]) - evt_scripts.insert(spell->EffectMiscValue[j]); - } - } - } - } - - // Then check if all scripts are in above list of possible script entries - for (ScriptMapMap::const_iterator itr = sEventScripts.begin(); itr != sEventScripts.end(); ++itr) - { - std::set::const_iterator itr2 = evt_scripts.find(itr->first); - if (itr2 == evt_scripts.end()) - sLog.outErrorDb("Table `event_scripts` has script (Id: %u) not referring to any gameobject_template type 10 data2 field, type 3 data6 field, type 13 data 2 field or any spell effect %u", - itr->first, SPELL_EFFECT_SEND_EVENT); - } -} - -//Load WP Scripts -void ObjectMgr::LoadWaypointScripts() -{ - LoadScripts(sWaypointScripts, "waypoint_scripts"); - - for (ScriptMapMap::const_iterator itr = sWaypointScripts.begin(); itr != sWaypointScripts.end(); ++itr) - { - QueryResult_AutoPtr query = WorldDatabase.PQuery("SELECT * FROM waypoint_scripts WHERE id = %u", itr->first); - if (!query || !query->GetRowCount()) - sLog.outErrorDb("There is no waypoint which links to the waypoint script %u", itr->first); - } -} - -void ObjectMgr::LoadGossipScripts() -{ - LoadScripts(sGossipScripts, "gossip_scripts"); - - // checks are done in LoadGossipMenuItems -} - -void ObjectMgr::LoadPageTexts() -{ - sPageTextStore.Free(); // for reload case - - sPageTextStore.Load(); - sLog.outString(">> Loaded %u page texts", sPageTextStore.RecordCount); - sLog.outString(); - - for (uint32 i = 1; i < sPageTextStore.MaxEntry; ++i) - { - // check data correctness - PageText const* page = sPageTextStore.LookupEntry(i); - if (!page) - continue; - - if (page->Next_Page && !sPageTextStore.LookupEntry(page->Next_Page)) - { - sLog.outErrorDb("Page text (Id: %u) has not existing next page (Id:%u)", i,page->Next_Page); - continue; - } - - // detect circular reference - std::set checkedPages; - for (PageText const* pageItr = page; pageItr; pageItr = sPageTextStore.LookupEntry(pageItr->Next_Page)) - { - if (!pageItr->Next_Page) - break; - checkedPages.insert(pageItr->Page_ID); - if (checkedPages.find(pageItr->Next_Page)!= checkedPages.end()) - { - std::ostringstream ss; - ss << "The text page(s) "; - for (std::set::iterator itr= checkedPages.begin(); itr != checkedPages.end(); ++itr) - ss << *itr << " "; - ss << "create(s) a circular reference, which can cause the server to freeze. Changing Next_Page of page " - << pageItr->Page_ID <<" to 0"; - sLog.outErrorDb(ss.str().c_str()); - const_cast(pageItr)->Next_Page = 0; - break; - } - } - } -} - -void ObjectMgr::LoadPageTextLocales() -{ - mPageTextLocaleMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,text_loc1,text_loc2,text_loc3,text_loc4,text_loc5,text_loc6,text_loc7,text_loc8 FROM locales_page_text"); - - if (!result) - return; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 entry = fields[0].GetUInt32(); - - PageTextLocale& data = mPageTextLocaleMap[entry]; - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[i].GetCppString(); - if (str.empty()) - continue; - - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Text.size() <= idx) - data.Text.resize(idx+1); - - data.Text[idx] = str; - } - } - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu PageText locale strings", (unsigned long)mPageTextLocaleMap.size()); -} - -struct SQLInstanceLoader : public SQLStorageLoaderBase -{ - template - void convert_from_str(uint32 /*field_pos*/, char *src, D &dst) - { - dst = D(objmgr.GetScriptId(src)); - } -}; - -void ObjectMgr::LoadInstanceTemplate() -{ - SQLInstanceLoader loader; - loader.Load(sInstanceTemplate); - - for (uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) - { - InstanceTemplate* temp = (InstanceTemplate*)GetInstanceTemplate(i); - if (!temp) - continue; - - if (!MapManager::IsValidMAP(temp->map)) - sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad mapid %d for template!", temp->map); - - if (!MapManager::IsValidMapCoord(temp->parent,temp->startLocX,temp->startLocY,temp->startLocZ,temp->startLocO)) - { - sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad parent entrance coordinates for map id %d template!", temp->map); - temp->parent = 0; // will have wrong continent 0 parent, at least existed - } - } - - sLog.outString(">> Loaded %u Instance Template definitions", sInstanceTemplate.RecordCount); - sLog.outString(); -} - -GossipText const *ObjectMgr::GetGossipText(uint32 Text_ID) const -{ - GossipTextMap::const_iterator itr = mGossipText.find(Text_ID); - if (itr != mGossipText.end()) - return &itr->second; - return NULL; -} - -void ObjectMgr::LoadGossipText() -{ - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT * FROM npc_text"); - - int count = 0; - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u npc texts", count); - return; - } - - int cic; - - barGoLink bar(result->GetRowCount()); - - do - { - ++count; - cic = 0; - - Field *fields = result->Fetch(); - - bar.step(); - - uint32 Text_ID = fields[cic++].GetUInt32(); - if (!Text_ID) - { - sLog.outErrorDb("Table `npc_text` has record wit reserved id 0, ignore."); - continue; - } - - GossipText& gText = mGossipText[Text_ID]; - - for (int i=0; i< 8; i++) - { - gText.Options[i].Text_0 = fields[cic++].GetCppString(); - gText.Options[i].Text_1 = fields[cic++].GetCppString(); - - gText.Options[i].Language = fields[cic++].GetUInt32(); - gText.Options[i].Probability = fields[cic++].GetFloat(); - - for (uint8 j=0; j < 3; ++j) - { - gText.Options[i].Emotes[j]._Delay = fields[cic++].GetUInt32(); - gText.Options[i].Emotes[j]._Emote = fields[cic++].GetUInt32(); - } - } - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u npc texts", count); -} - -void ObjectMgr::LoadNpcTextLocales() -{ - mNpcTextLocaleMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry," - "Text0_0_loc1,Text0_1_loc1,Text1_0_loc1,Text1_1_loc1,Text2_0_loc1,Text2_1_loc1,Text3_0_loc1,Text3_1_loc1,Text4_0_loc1,Text4_1_loc1,Text5_0_loc1,Text5_1_loc1,Text6_0_loc1,Text6_1_loc1,Text7_0_loc1,Text7_1_loc1," - "Text0_0_loc2,Text0_1_loc2,Text1_0_loc2,Text1_1_loc2,Text2_0_loc2,Text2_1_loc2,Text3_0_loc2,Text3_1_loc1,Text4_0_loc2,Text4_1_loc2,Text5_0_loc2,Text5_1_loc2,Text6_0_loc2,Text6_1_loc2,Text7_0_loc2,Text7_1_loc2," - "Text0_0_loc3,Text0_1_loc3,Text1_0_loc3,Text1_1_loc3,Text2_0_loc3,Text2_1_loc3,Text3_0_loc3,Text3_1_loc1,Text4_0_loc3,Text4_1_loc3,Text5_0_loc3,Text5_1_loc3,Text6_0_loc3,Text6_1_loc3,Text7_0_loc3,Text7_1_loc3," - "Text0_0_loc4,Text0_1_loc4,Text1_0_loc4,Text1_1_loc4,Text2_0_loc4,Text2_1_loc4,Text3_0_loc4,Text3_1_loc1,Text4_0_loc4,Text4_1_loc4,Text5_0_loc4,Text5_1_loc4,Text6_0_loc4,Text6_1_loc4,Text7_0_loc4,Text7_1_loc4," - "Text0_0_loc5,Text0_1_loc5,Text1_0_loc5,Text1_1_loc5,Text2_0_loc5,Text2_1_loc5,Text3_0_loc5,Text3_1_loc1,Text4_0_loc5,Text4_1_loc5,Text5_0_loc5,Text5_1_loc5,Text6_0_loc5,Text6_1_loc5,Text7_0_loc5,Text7_1_loc5," - "Text0_0_loc6,Text0_1_loc6,Text1_0_loc6,Text1_1_loc6,Text2_0_loc6,Text2_1_loc6,Text3_0_loc6,Text3_1_loc1,Text4_0_loc6,Text4_1_loc6,Text5_0_loc6,Text5_1_loc6,Text6_0_loc6,Text6_1_loc6,Text7_0_loc6,Text7_1_loc6," - "Text0_0_loc7,Text0_1_loc7,Text1_0_loc7,Text1_1_loc7,Text2_0_loc7,Text2_1_loc7,Text3_0_loc7,Text3_1_loc1,Text4_0_loc7,Text4_1_loc7,Text5_0_loc7,Text5_1_loc7,Text6_0_loc7,Text6_1_loc7,Text7_0_loc7,Text7_1_loc7, " - "Text0_0_loc8,Text0_1_loc8,Text1_0_loc8,Text1_1_loc8,Text2_0_loc8,Text2_1_loc8,Text3_0_loc8,Text3_1_loc1,Text4_0_loc8,Text4_1_loc8,Text5_0_loc8,Text5_1_loc8,Text6_0_loc8,Text6_1_loc8,Text7_0_loc8,Text7_1_loc8 " - " FROM locales_npc_text"); - - if (!result) - return; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 entry = fields[0].GetUInt32(); - - NpcTextLocale& data = mNpcTextLocaleMap[entry]; - - for (uint8 i=1; i= 0) - { - if (data.Text_0[j].size() <= idx) - data.Text_0[j].resize(idx+1); - - data.Text_0[j][idx] = str0; - } - } - std::string str1 = fields[1+8*2*(i-1)+2*j+1].GetCppString(); - if (!str1.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Text_1[j].size() <= idx) - data.Text_1[j].resize(idx+1); - - data.Text_1[j][idx] = str1; - } - } - } - } - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu NpcText locale strings", (unsigned long)mNpcTextLocaleMap.size()); -} - -//not very fast function but it is called only once a day, or on starting-up -void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) -{ - time_t basetime = time(NULL); - sLog.outDebug("Returning mails current time: hour: %d, minute: %d, second: %d ", localtime(&basetime)->tm_hour, localtime(&basetime)->tm_min, localtime(&basetime)->tm_sec); - //delete all old mails without item and without body immediately, if starting server - if (!serverUp) - CharacterDatabase.PExecute("DELETE FROM mail WHERE expire_time < '" UI64FMTD "' AND has_items = '0' AND body = ''", (uint64)basetime); - // 0 1 2 3 4 5 6 7 8 9 - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" UI64FMTD "'", (uint64)basetime); - if (!result) - { - barGoLink bar(1); - bar.step(); - sLog.outString(); - sLog.outString(">> Only expired mails (need to be return or delete) or DB table `mail` is empty."); - return; // any mails need to be returned or deleted - } - - //std::ostringstream delitems, delmails; //will be here for optimization - //bool deletemail = false, deleteitem = false; - //delitems << "DELETE FROM item_instance WHERE guid IN ("; - //delmails << "DELETE FROM mail WHERE id IN (" - - barGoLink bar(result->GetRowCount()); - uint32 count = 0; - Field *fields; - - do - { - bar.step(); - - fields = result->Fetch(); - Mail *m = new Mail; - m->messageID = fields[0].GetUInt32(); - m->messageType = fields[1].GetUInt8(); - m->sender = fields[2].GetUInt32(); - m->receiver = fields[3].GetUInt32(); - bool has_items = fields[4].GetBool(); - m->expire_time = (time_t)fields[5].GetUInt64(); - m->deliver_time = 0; - m->COD = fields[6].GetUInt32(); - m->checked = fields[7].GetUInt32(); - m->mailTemplateId = fields[8].GetInt16(); - - Player *pl = 0; - if (serverUp) - pl = GetPlayer((uint64)m->receiver); - if (pl && pl->m_mailsLoaded) - { //this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail - //his in mailbox and he has already listed his mails) - delete m; - continue; - } - //delete or return mail: - if (has_items) - { - QueryResult_AutoPtr resultItems = CharacterDatabase.PQuery("SELECT item_guid,item_template FROM mail_items WHERE mail_id='%u'", m->messageID); - if (resultItems) - { - do - { - Field *fields2 = resultItems->Fetch(); - - uint32 item_guid_low = fields2[0].GetUInt32(); - uint32 item_template = fields2[1].GetUInt32(); - - m->AddItem(item_guid_low, item_template); - } - while (resultItems->NextRow()); - } - //if it is mail from AH, it shouldn't be returned, but deleted - if (m->messageType != MAIL_NORMAL || m->messageType == MAIL_AUCTION || (m->checked & (MAIL_CHECK_MASK_COD_PAYMENT | MAIL_CHECK_MASK_RETURNED))) - { - // mail open and then not returned - for (std::vector::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", itr2->item_guid); - } - else - { - //mail will be returned: - CharacterDatabase.PExecute("UPDATE mail SET sender = '%u', receiver = '%u', expire_time = '" UI64FMTD "', deliver_time = '" UI64FMTD "',cod = '0', checked = '%u' WHERE id = '%u'", m->receiver, m->sender, (uint64)(basetime + 30*DAY), (uint64)basetime, MAIL_CHECK_MASK_RETURNED, m->messageID); - delete m; - continue; - } - } - - //deletemail = true; - //delmails << m->messageID << ", "; - CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID); - delete m; - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u mails", count); -} - -void ObjectMgr::LoadQuestAreaTriggers() -{ - mQuestAreaTriggerMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id,quest FROM areatrigger_involvedrelation"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u quest trigger points", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - ++count; - bar.step(); - - Field *fields = result->Fetch(); - - uint32 trigger_ID = fields[0].GetUInt32(); - uint32 quest_ID = fields[1].GetUInt32(); - - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(trigger_ID); - if (!atEntry) - { - sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",trigger_ID); - continue; - } - - Quest const* quest = GetQuestTemplate(quest_ID); - - if (!quest) - { - sLog.outErrorDb("Table `areatrigger_involvedrelation` has record (id: %u) for not existing quest %u",trigger_ID,quest_ID); - continue; - } - - if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) - { - sLog.outErrorDb("Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.",trigger_ID,quest_ID); - - // this will prevent quest completing without objective - const_cast(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); - - // continue; - quest modified to required objective and trigger can be allowed. - } - - mQuestAreaTriggerMap[trigger_ID] = quest_ID; - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u quest trigger points", count); -} - -void ObjectMgr::LoadTavernAreaTriggers() -{ - mTavernAreaTriggerSet.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id FROM areatrigger_tavern"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u tavern triggers", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - ++count; - bar.step(); - - Field *fields = result->Fetch(); - - uint32 Trigger_ID = fields[0].GetUInt32(); - - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); - if (!atEntry) - { - sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); - continue; - } - - mTavernAreaTriggerSet.insert(Trigger_ID); - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u tavern triggers", count); -} - -void ObjectMgr::LoadAreaTriggerScripts() -{ - mAreaTriggerScripts.clear(); // need for reload case - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, ScriptName FROM areatrigger_scripts"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u areatrigger scripts", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - ++count; - bar.step(); - - Field *fields = result->Fetch(); - - uint32 Trigger_ID = fields[0].GetUInt32(); - const char *scriptName = fields[1].GetString(); - - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); - if (!atEntry) - { - sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); - continue; - } - mAreaTriggerScripts[Trigger_ID] = GetScriptId(scriptName); - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u areatrigger scripts", count); -} - -uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team) -{ - bool found = false; - float dist = 10000; - uint32 id = 0; - - for (uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) - { - TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); - - if (!node || node->map_id != mapid || !node->MountCreatureID[team == ALLIANCE ? 1 : 0] && node->MountCreatureID[0] != 32981) // dk flight - continue; - - uint8 field = (uint8)((i - 1) / 32); - uint32 submask = 1<<((i-1)%32); - - // skip not taxi network nodes - if ((sTaxiNodesMask[field] & submask) == 0) - continue; - - float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z); - if (found) - { - if (dist2 < dist) - { - dist = dist2; - id = i; - } - } - else - { - found = true; - dist = dist2; - id = i; - } - } - - return id; -} - -void ObjectMgr::GetTaxiPath(uint32 source, uint32 destination, uint32 &path, uint32 &cost) -{ - TaxiPathSetBySource::iterator src_i = sTaxiPathSetBySource.find(source); - if (src_i == sTaxiPathSetBySource.end()) - { - path = 0; - cost = 0; - return; - } - - TaxiPathSetForSource& pathSet = src_i->second; - - TaxiPathSetForSource::iterator dest_i = pathSet.find(destination); - if (dest_i == pathSet.end()) - { - path = 0; - cost = 0; - return; - } - - cost = dest_i->second.price; - path = dest_i->second.ID; -} - -uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt_team /* = false */) -{ - uint32 mount_entry = 0; - uint32 mount_id = 0; - - // select mount creature id - TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id); - if (node) - { - if (team == ALLIANCE) - mount_entry = node->MountCreatureID[1]; - else - mount_entry = node->MountCreatureID[0]; - - // Fix for Alliance not being able to use Acherus taxi - // only one mount type for both sides - if (mount_entry == 0 && allowed_alt_team) - { - // Simply reverse the selection. At least one team in theory should have a valid mount ID to choose. - mount_entry = team == ALLIANCE ? node->MountCreatureID[0] : node->MountCreatureID[1]; - } - - CreatureInfo const *mount_info = GetCreatureTemplate(mount_entry); - if (mount_info) - { - mount_id = mount_info->GetRandomValidModelId(); - if (!mount_id) - { - sLog.outErrorDb("No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry); - return false; - } - } - } - - CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(mount_id); - if (minfo) - mount_id = minfo->modelid; - - return mount_id; -} - -void ObjectMgr::GetTaxiPathNodes(uint32 path, Path &pathnodes, std::vector& mapIds) -{ - if (path >= sTaxiPathNodesByPath.size()) - return; - - TaxiPathNodeList& nodeList = sTaxiPathNodesByPath[path]; - - pathnodes.Resize(nodeList.size()); - mapIds.resize(nodeList.size()); - - for (size_t i = 0; i < nodeList.size(); ++i) - { - pathnodes[ i ].x = nodeList[i].x; - pathnodes[ i ].y = nodeList[i].y; - pathnodes[ i ].z = nodeList[i].z; - - mapIds[i] = nodeList[i].mapid; - } -} - -void ObjectMgr::GetTransportPathNodes(uint32 path, TransportPath &pathnodes) -{ - if (path >= sTaxiPathNodesByPath.size()) - return; - - TaxiPathNodeList& nodeList = sTaxiPathNodesByPath[path]; - - pathnodes.Resize(nodeList.size()); - - for (size_t i = 0; i < nodeList.size(); ++i) - { - pathnodes[ i ].mapid = nodeList[i].mapid; - pathnodes[ i ].x = nodeList[i].x; - pathnodes[ i ].y = nodeList[i].y; - pathnodes[ i ].z = nodeList[i].z; - pathnodes[ i ].actionFlag = nodeList[i].actionFlag; - pathnodes[ i ].delay = nodeList[i].delay; - } -} - -void ObjectMgr::LoadGraveyardZones() -{ - mGraveYardMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id,ghost_zone,faction FROM game_graveyard_zone"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u graveyard-zone links", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - ++count; - bar.step(); - - Field *fields = result->Fetch(); - - uint32 safeLocId = fields[0].GetUInt32(); - uint32 zoneId = fields[1].GetUInt32(); - uint32 team = fields[2].GetUInt32(); - - WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(safeLocId); - if (!entry) - { - sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.",safeLocId); - continue; - } - - AreaTableEntry const *areaEntry = GetAreaEntryByAreaID(zoneId); - if (!areaEntry) - { - sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing zone id (%u), skipped.",zoneId); - continue; - } - - if (areaEntry->zone != 0) - { - sLog.outErrorDb("Table `game_graveyard_zone` has record subzone id (%u) instead of zone, skipped.",zoneId); - continue; - } - - if (team != 0 && team != HORDE && team != ALLIANCE) - { - sLog.outErrorDb("Table `game_graveyard_zone` has record for non player faction (%u), skipped.",team); - continue; - } - - if (!AddGraveYardLink(safeLocId,zoneId,team,false)) - sLog.outErrorDb("Table `game_graveyard_zone` has a duplicate record for Graveyard (ID: %u) and Zone (ID: %u), skipped.",safeLocId,zoneId); - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u graveyard-zone links", count); -} - -WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team) -{ - // search for zone associated closest graveyard - uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y,z); - - // Simulate std. algorithm: - // found some graveyard associated to (ghost_zone,ghost_map) - // - // if mapId == graveyard.mapId (ghost in plain zone or city or battleground) and search graveyard at same map - // then check faction - // if mapId != graveyard.mapId (ghost in instance) and search any graveyard associated - // then check faction - GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId); - GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId); - MapEntry const* map = sMapStore.LookupEntry(MapId); - // not need to check validity of map object; MapId _MUST_ be valid here - - if (graveLow == graveUp && !map->IsBattleArena()) - { - //sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team); - return NULL; - } - - // at corpse map - bool foundNear = false; - float distNear = 10000; - WorldSafeLocsEntry const* entryNear = NULL; - - // at entrance map for corpse map - bool foundEntr = false; - float distEntr = 10000; - WorldSafeLocsEntry const* entryEntr = NULL; - - // some where other - WorldSafeLocsEntry const* entryFar = NULL; - - MapEntry const* mapEntry = sMapStore.LookupEntry(MapId); - - for (GraveYardMap::const_iterator itr = graveLow; itr != graveUp; ++itr) - { - GraveYardData const& data = itr->second; - - WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(data.safeLocId); - if (!entry) - { - sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.",data.safeLocId); - continue; - } - - // skip enemy faction graveyard - // team == 0 case can be at call from .neargrave - if (data.team != 0 && team != 0 && data.team != team) - continue; - - // find now nearest graveyard at other map - if (MapId != entry->map_id) - { - // if find graveyard at different map from where entrance placed (or no entrance data), use any first - if (!mapEntry || - mapEntry->entrance_map < 0 || - uint32(mapEntry->entrance_map) != entry->map_id || - (mapEntry->entrance_x == 0 && mapEntry->entrance_y == 0)) - { - // not have any corrdinates for check distance anyway - entryFar = entry; - continue; - } - - // at entrance map calculate distance (2D); - float dist2 = (entry->x - mapEntry->entrance_x)*(entry->x - mapEntry->entrance_x) - +(entry->y - mapEntry->entrance_y)*(entry->y - mapEntry->entrance_y); - if (foundEntr) - { - if (dist2 < distEntr) - { - distEntr = dist2; - entryEntr = entry; - } - } - else - { - foundEntr = true; - distEntr = dist2; - entryEntr = entry; - } - } - // find now nearest graveyard at same map - else - { - float dist2 = (entry->x - x)*(entry->x - x)+(entry->y - y)*(entry->y - y)+(entry->z - z)*(entry->z - z); - if (foundNear) - { - if (dist2 < distNear) - { - distNear = dist2; - entryNear = entry; - } - } - else - { - foundNear = true; - distNear = dist2; - entryNear = entry; - } - } - } - - if (entryNear) - return entryNear; - - if (entryEntr) - return entryEntr; - - return entryFar; -} - -GraveYardData const* ObjectMgr::FindGraveYardData(uint32 id, uint32 zoneId) -{ - GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId); - GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId); - - for (GraveYardMap::const_iterator itr = graveLow; itr != graveUp; ++itr) - { - if (itr->second.safeLocId == id) - return &itr->second; - } - - return NULL; -} - -bool ObjectMgr::AddGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool inDB) -{ - if (FindGraveYardData(id,zoneId)) - return false; - - // add link to loaded data - GraveYardData data; - data.safeLocId = id; - data.team = team; - - mGraveYardMap.insert(GraveYardMap::value_type(zoneId,data)); - - // add link to DB - if (inDB) - { - WorldDatabase.PExecuteLog("INSERT INTO game_graveyard_zone (id,ghost_zone,faction) " - "VALUES ('%u', '%u','%u')",id,zoneId,team); - } - - return true; -} - -void ObjectMgr::RemoveGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool inDB) -{ - GraveYardMap::iterator graveLow = mGraveYardMap.lower_bound(zoneId); - GraveYardMap::iterator graveUp = mGraveYardMap.upper_bound(zoneId); - if (graveLow == graveUp) - { - //sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team); - return; - } - - bool found = false; - - GraveYardMap::iterator itr; - - for (itr = graveLow; itr != graveUp; ++itr) - { - GraveYardData & data = itr->second; - - // skip not matching safezone id - if (data.safeLocId != id) - continue; - - // skip enemy faction graveyard at same map (normal area, city, or battleground) - // team == 0 case can be at call from .neargrave - if (data.team != 0 && team != 0 && data.team != team) - continue; - - found = true; - break; - } - - // no match, return - if (!found) - return; - - // remove from links - mGraveYardMap.erase(itr); - - // remove link from DB - if (inDB) - { - WorldDatabase.PExecute("DELETE FROM game_graveyard_zone WHERE id = '%u' AND ghost_zone = '%u' AND faction = '%u'",id,zoneId,team); - } - - return; -} - -void ObjectMgr::LoadAreaTriggerTeleports() -{ - mAreaTriggers.clear(); // need for reload case - - uint32 count = 0; - - // 0 1 2 3 4 5 6 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, access_id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport"); - if (!result) - { - - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u area trigger teleport definitions", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - - bar.step(); - - ++count; - - uint32 Trigger_ID = fields[0].GetUInt32(); - - AreaTrigger at; - - at.access_id = fields[1].GetUInt32(); - at.target_mapId = fields[2].GetUInt32(); - at.target_X = fields[3].GetFloat(); - at.target_Y = fields[4].GetFloat(); - at.target_Z = fields[5].GetFloat(); - at.target_Orientation = fields[6].GetFloat(); - - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); - if (!atEntry) - { - sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); - continue; - } - - MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId); - if (!mapEntry) - { - sLog.outErrorDb("Area trigger (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Trigger_ID,at.target_mapId); - continue; - } - - if (at.target_X == 0 && at.target_Y == 0 && at.target_Z == 0) - { - sLog.outErrorDb("Area trigger (ID:%u) target coordinates not provided.",Trigger_ID); - continue; - } - - mAreaTriggers[Trigger_ID] = at; - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u area trigger teleport definitions", count); -} - -void ObjectMgr::LoadAccessRequirements() -{ - mAccessRequirements.clear(); // need for reload case - - uint32 count = 0; - - // 0 1 2 3 4 5 6 7 8 9 10 11 12 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, level_min, level_max, item, item2, heroic_key, heroic_key2, quest_done, quest_failed_text, heroic_quest_done, heroic_quest_failed_text, heroic_level_min, status FROM access_requirement"); - if (!result) - { - - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u access requirement definitions", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - - bar.step(); - - ++count; - - uint32 requiremt_ID = fields[0].GetUInt32(); - - AccessRequirement ar; - - ar.levelMin = fields[1].GetUInt8(); - ar.levelMax = fields[2].GetUInt8(); - ar.heroicLevelMin = fields[11].GetUInt8(); - ar.item = fields[3].GetUInt32(); - ar.item2 = fields[4].GetUInt32(); - ar.heroicKey = fields[5].GetUInt32(); - ar.heroicKey2 = fields[6].GetUInt32(); - ar.quest = fields[7].GetUInt32(); - ar.questFailedText = fields[8].GetCppString(); - ar.heroicQuest = fields[9].GetUInt32(); - ar.heroicQuestFailedText = fields[10].GetCppString(); - ar.status = fields[12].GetUInt8(); - - if (ar.item) - { - ItemPrototype const *pProto = GetItemPrototype(ar.item); - if (!pProto) - { - sLog.outError("Key item %u does not exist for requirement %u, removing key requirement.", ar.item, requiremt_ID); - ar.item = 0; - } - } - - if (ar.item2) - { - ItemPrototype const *pProto = GetItemPrototype(ar.item2); - if (!pProto) - { - sLog.outError("Second item %u does not exist for requirement %u, removing key requirement.", ar.item2, requiremt_ID); - ar.item2 = 0; - } - } - - if (ar.heroicKey) - { - ItemPrototype const *pProto = GetItemPrototype(ar.heroicKey); - if (!pProto) - { - sLog.outError("Heroic key %u not exist for trigger %u, remove key requirement.", ar.heroicKey, requiremt_ID); - ar.heroicKey = 0; - } - } - - if (ar.heroicKey2) - { - ItemPrototype const *pProto = GetItemPrototype(ar.heroicKey2); - if (!pProto) - { - sLog.outError("Second heroic key %u not exist for trigger %u, remove key requirement.", ar.heroicKey2, requiremt_ID); - ar.heroicKey2 = 0; - } - } - - if (ar.heroicQuest) - { - QuestMap::iterator qReqItr = mQuestTemplates.find(ar.heroicQuest); - if (qReqItr == mQuestTemplates.end()) - { - sLog.outErrorDb("Required Heroic Quest %u not exist for trigger %u, remove heroic quest done requirement.",ar.heroicQuest,requiremt_ID); - ar.heroicQuest = 0; - } - } - - if (ar.quest) - { - QuestMap::iterator qReqItr = mQuestTemplates.find(ar.quest); - if (qReqItr == mQuestTemplates.end()) - { - sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",ar.quest,requiremt_ID); - ar.quest = 0; - } - } - - mAccessRequirements[requiremt_ID] = ar; - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u access requirement definitions", count); -} - -/* - * Searches for the areatrigger which teleports players out of the given map with instance_template.parent field support - */ -AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const -{ - bool useParentDbValue = false; - uint32 parentId = 0; - const MapEntry *mapEntry = sMapStore.LookupEntry(Map); - if (!mapEntry || mapEntry->entrance_map < 0) - return NULL; - - if (mapEntry->IsDungeon()) - { - const InstanceTemplate *iTemplate = objmgr.GetInstanceTemplate(Map); - - if (!iTemplate) - return NULL; - - parentId = iTemplate->parent; - useParentDbValue = true; - } - - uint32 entrance_map = uint32(mapEntry->entrance_map); - for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr) - if ((!useParentDbValue && itr->second.target_mapId == entrance_map) || (useParentDbValue && itr->second.target_mapId == parentId)) - { - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); - if (atEntry && atEntry->mapid == Map) - return &itr->second; - } - return NULL; -} - -/** - * Searches for the areatrigger which teleports players to the given map - */ -AreaTrigger const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const -{ - for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr) - { - if (itr->second.target_mapId == Map) - { - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); - if (atEntry) - return &itr->second; - } - } - return NULL; -} - -void ObjectMgr::SetHighestGuids() -{ - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(guid) FROM characters"); - if (result) - m_hiCharGuid = (*result)[0].GetUInt32()+1; - - result = WorldDatabase.Query("SELECT MAX(guid) FROM creature"); - if (result) - m_hiCreatureGuid = (*result)[0].GetUInt32()+1; - - result = CharacterDatabase.Query("SELECT MAX(guid) FROM item_instance"); - if (result) - m_hiItemGuid = (*result)[0].GetUInt32()+1; - - // Cleanup other tables from not existed guids ( >= m_hiItemGuid) - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", m_hiItemGuid); - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", m_hiItemGuid); - CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", m_hiItemGuid); - CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", m_hiItemGuid); - - result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject"); - if (result) - m_hiGoGuid = (*result)[0].GetUInt32()+1; - - result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse"); - if (result) - m_auctionid = (*result)[0].GetUInt32()+1; - - result = CharacterDatabase.Query("SELECT MAX(id) FROM mail"); - if (result) - m_mailid = (*result)[0].GetUInt32()+1; - - result = CharacterDatabase.Query("SELECT MAX(guid) FROM corpse"); - if (result) - m_hiCorpseGuid = (*result)[0].GetUInt32()+1; - - result = CharacterDatabase.Query("SELECT MAX(arenateamid) FROM arena_team"); - if (result) - m_arenaTeamId = (*result)[0].GetUInt32()+1; - - result = CharacterDatabase.Query("SELECT MAX(setguid) FROM character_equipmentsets"); - if (result) - m_equipmentSetGuid = (*result)[0].GetUInt64()+1; - - result = CharacterDatabase.Query("SELECT MAX(guildid) FROM guild"); - if (result) - m_guildId = (*result)[0].GetUInt32()+1; - - result = CharacterDatabase.Query("SELECT MAX(guid) FROM groups"); - if (result) - m_hiGroupGuid = (*result)[0].GetUInt32()+1; -} - -uint32 ObjectMgr::GenerateArenaTeamId() -{ - if (m_arenaTeamId >= 0xFFFFFFFE) - { - sLog.outError("Arena team ids overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_arenaTeamId++; -} - -uint32 ObjectMgr::GenerateAuctionID() -{ - if (m_auctionid >= 0xFFFFFFFE) - { - sLog.outError("Auctions ids overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_auctionid++; -} - -uint64 ObjectMgr::GenerateEquipmentSetGuid() -{ - if (m_equipmentSetGuid >= 0xFFFFFFFFFFFFFFFEll) - { - sLog.outError("EquipmentSet guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_equipmentSetGuid++; -} - -uint32 ObjectMgr::GenerateGuildId() -{ - if (m_guildId >= 0xFFFFFFFE) - { - sLog.outError("Guild ids overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_guildId++; -} - -uint32 ObjectMgr::GenerateMailID() -{ - if (m_mailid >= 0xFFFFFFFE) - { - sLog.outError("Mail ids overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_mailid++; -} - -uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) -{ - switch(guidhigh) - { - case HIGHGUID_ITEM: - if (m_hiItemGuid >= 0xFFFFFFFE) - { - sLog.outError("Item guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiItemGuid++; - case HIGHGUID_UNIT: - if (m_hiCreatureGuid >= 0x00FFFFFE) - { - sLog.outError("Creature guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiCreatureGuid++; - case HIGHGUID_PET: - if (m_hiPetGuid >= 0x00FFFFFE) - { - sLog.outError("Pet guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiPetGuid++; - case HIGHGUID_VEHICLE: - if (m_hiVehicleGuid >= 0x00FFFFFF) - { - sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiVehicleGuid++; - case HIGHGUID_PLAYER: - if (m_hiCharGuid >= 0xFFFFFFFE) - { - sLog.outError("Players guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiCharGuid++; - case HIGHGUID_GAMEOBJECT: - if (m_hiGoGuid >= 0x00FFFFFE) - { - sLog.outError("Gameobject guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiGoGuid++; - case HIGHGUID_CORPSE: - if (m_hiCorpseGuid >= 0xFFFFFFFE) - { - sLog.outError("Corpse guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiCorpseGuid++; - case HIGHGUID_DYNAMICOBJECT: - if (m_hiDoGuid >= 0xFFFFFFFE) - { - sLog.outError("DynamicObject guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiDoGuid++; - case HIGHGUID_GROUP: - if (m_hiGroupGuid >= 0xFFFFFFFE) - { - sLog.outError("Group guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } - return m_hiGroupGuid++; - default: - ASSERT(0); - } - - ASSERT(0); - return 0; -} - -void ObjectMgr::LoadGameObjectLocales() -{ - mGameObjectLocaleMap.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry," - "name_loc1,name_loc2,name_loc3,name_loc4,name_loc5,name_loc6,name_loc7,name_loc8," - "castbarcaption_loc1,castbarcaption_loc2,castbarcaption_loc3,castbarcaption_loc4," - "castbarcaption_loc5,castbarcaption_loc6,castbarcaption_loc7,castbarcaption_loc8 FROM locales_gameobject"); - - if (!result) - return; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 entry = fields[0].GetUInt32(); - - GameObjectLocale& data = mGameObjectLocaleMap[entry]; - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[i].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.Name.size() <= idx) - data.Name.resize(idx+1); - - data.Name[idx] = str; - } - } - } - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[i+(MAX_LOCALE-1)].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - if (data.CastBarCaption.size() <= idx) - data.CastBarCaption.resize(idx+1); - - data.CastBarCaption[idx] = str; - } - } - } - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %lu gameobject locale strings", (unsigned long)mGameObjectLocaleMap.size()); -} - -struct SQLGameObjectLoader : public SQLStorageLoaderBase -{ - template - void convert_from_str(uint32 /*field_pos*/, char *src, D &dst) - { - dst = D(objmgr.GetScriptId(src)); - } -}; - -inline void CheckGOLockId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) -{ - if (sLockStore.LookupEntry(dataN)) - return; - - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but lock (Id: %u) not found.", - goInfo->id,goInfo->type,N,goInfo->door.lockId,goInfo->door.lockId); -} - -inline void CheckGOLinkedTrapId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) -{ - if (GameObjectInfo const* trapInfo = sGOStorage.LookupEntry(dataN)) - { - if (trapInfo->type != GAMEOBJECT_TYPE_TRAP) - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.", - goInfo->id,goInfo->type,N,dataN,dataN,GAMEOBJECT_TYPE_TRAP); - } - /* disable check for while (too many error reports baout not existed in trap templates - else - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but trap GO (Entry %u) not exist in `gameobject_template`.", - goInfo->id,goInfo->type,N,dataN,dataN); - */ -} - -inline void CheckGOSpellId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) -{ - if (sSpellStore.LookupEntry(dataN)) - return; - - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but Spell (Entry %u) not exist.", - goInfo->id,goInfo->type,N,dataN,dataN); -} - -inline void CheckAndFixGOChairHeightId(GameObjectInfo const* goInfo,uint32 const& dataN,uint32 N) -{ - if (dataN <= (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR)) - return; - - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but correct chair height in range 0..%i.", - goInfo->id,goInfo->type,N,dataN,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR); - - // prevent client and server unexpected work - const_cast(dataN) = 0; -} - -inline void CheckGONoDamageImmuneId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) -{ - // 0/1 correct values - if (dataN <= 1) - return; - - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) noDamageImmune field value.", - goInfo->id,goInfo->type,N,dataN); -} - -inline void CheckGOConsumable(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) -{ - // 0/1 correct values - if (dataN <= 1) - return; - - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) consumable field value.", - goInfo->id,goInfo->type,N,dataN); -} - -void ObjectMgr::LoadGameobjectInfo() -{ - SQLGameObjectLoader loader; - loader.Load(sGOStorage); - - // some checks - for (uint32 id = 1; id < sGOStorage.MaxEntry; id++) - { - GameObjectInfo const* goInfo = sGOStorage.LookupEntry(id); - if (!goInfo) - continue; - - // some GO types have unused go template, check goInfo->displayId at GO spawn data loading or ignore - - switch(goInfo->type) - { - case GAMEOBJECT_TYPE_DOOR: //0 - { - if (goInfo->door.lockId) - CheckGOLockId(goInfo,goInfo->door.lockId,1); - CheckGONoDamageImmuneId(goInfo,goInfo->door.noDamageImmune,3); - break; - } - case GAMEOBJECT_TYPE_BUTTON: //1 - { - if (goInfo->button.lockId) - CheckGOLockId(goInfo,goInfo->button.lockId,1); - CheckGONoDamageImmuneId(goInfo,goInfo->button.noDamageImmune,4); - break; - } - case GAMEOBJECT_TYPE_QUESTGIVER: //2 - { - if (goInfo->questgiver.lockId) - CheckGOLockId(goInfo,goInfo->questgiver.lockId,0); - CheckGONoDamageImmuneId(goInfo,goInfo->questgiver.noDamageImmune,5); - break; - } - case GAMEOBJECT_TYPE_CHEST: //3 - { - if (goInfo->chest.lockId) - CheckGOLockId(goInfo,goInfo->chest.lockId,0); - - CheckGOConsumable(goInfo,goInfo->chest.consumable,3); - - if (goInfo->chest.linkedTrapId) // linked trap - CheckGOLinkedTrapId(goInfo,goInfo->chest.linkedTrapId,7); - break; - } - case GAMEOBJECT_TYPE_TRAP: //6 - { - if (goInfo->trap.lockId) - CheckGOLockId(goInfo,goInfo->trap.lockId,0); - /* disable check for while, too many not existed spells - if (goInfo->trap.spellId) // spell - CheckGOSpellId(goInfo,goInfo->trap.spellId,3); - */ - break; - } - case GAMEOBJECT_TYPE_CHAIR: //7 - CheckAndFixGOChairHeightId(goInfo,goInfo->chair.height,1); - break; - case GAMEOBJECT_TYPE_SPELL_FOCUS: //8 - { - if (goInfo->spellFocus.focusId) - { - if (!sSpellFocusObjectStore.LookupEntry(goInfo->spellFocus.focusId)) - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but SpellFocus (Id: %u) not exist.", - id,goInfo->type,goInfo->spellFocus.focusId,goInfo->spellFocus.focusId); - } - - if (goInfo->spellFocus.linkedTrapId) // linked trap - CheckGOLinkedTrapId(goInfo,goInfo->spellFocus.linkedTrapId,2); - break; - } - case GAMEOBJECT_TYPE_GOOBER: //10 - { - if (goInfo->goober.lockId) - CheckGOLockId(goInfo,goInfo->goober.lockId,0); - - CheckGOConsumable(goInfo,goInfo->goober.consumable,3); - - if (goInfo->goober.pageId) // pageId - { - if (!sPageTextStore.LookupEntry(goInfo->goober.pageId)) - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but PageText (Entry %u) not exist.", - id,goInfo->type,goInfo->goober.pageId,goInfo->goober.pageId); - } - /* disable check for while, too many not existed spells - if (goInfo->goober.spellId) // spell - CheckGOSpellId(goInfo,goInfo->goober.spellId,10); - */ - CheckGONoDamageImmuneId(goInfo,goInfo->goober.noDamageImmune,11); - if (goInfo->goober.linkedTrapId) // linked trap - CheckGOLinkedTrapId(goInfo,goInfo->goober.linkedTrapId,12); - break; - } - case GAMEOBJECT_TYPE_AREADAMAGE: //12 - { - if (goInfo->areadamage.lockId) - CheckGOLockId(goInfo,goInfo->areadamage.lockId,0); - break; - } - case GAMEOBJECT_TYPE_CAMERA: //13 - { - if (goInfo->camera.lockId) - CheckGOLockId(goInfo,goInfo->camera.lockId,0); - break; - } - case GAMEOBJECT_TYPE_MO_TRANSPORT: //15 - { - if (goInfo->moTransport.taxiPathId) - { - if (goInfo->moTransport.taxiPathId >= sTaxiPathNodesByPath.size() || sTaxiPathNodesByPath[goInfo->moTransport.taxiPathId].empty()) - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist.", - id,goInfo->type,goInfo->moTransport.taxiPathId,goInfo->moTransport.taxiPathId); - } - break; - } - case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18 - { - /* disable check for while, too many not existed spells - // always must have spell - CheckGOSpellId(goInfo,goInfo->summoningRitual.spellId,1); - */ - break; - } - case GAMEOBJECT_TYPE_SPELLCASTER: //22 - { - // always must have spell - CheckGOSpellId(goInfo,goInfo->spellcaster.spellId,0); - break; - } - case GAMEOBJECT_TYPE_FLAGSTAND: //24 - { - if (goInfo->flagstand.lockId) - CheckGOLockId(goInfo,goInfo->flagstand.lockId,0); - CheckGONoDamageImmuneId(goInfo,goInfo->flagstand.noDamageImmune,5); - break; - } - case GAMEOBJECT_TYPE_FISHINGHOLE: //25 - { - if (goInfo->fishinghole.lockId) - CheckGOLockId(goInfo,goInfo->fishinghole.lockId,4); - break; - } - case GAMEOBJECT_TYPE_FLAGDROP: //26 - { - if (goInfo->flagdrop.lockId) - CheckGOLockId(goInfo,goInfo->flagdrop.lockId,0); - CheckGONoDamageImmuneId(goInfo,goInfo->flagdrop.noDamageImmune,3); - break; - } - case GAMEOBJECT_TYPE_BARBER_CHAIR: //32 - CheckAndFixGOChairHeightId(goInfo,goInfo->barberChair.chairheight,0); - break; - } - } - - sLog.outString(">> Loaded %u game object templates", sGOStorage.RecordCount); - sLog.outString(); -} - -void ObjectMgr::LoadExplorationBaseXP() -{ - uint32 count = 0; - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT level,basexp FROM exploration_basexp"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u BaseXP definitions", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Field *fields = result->Fetch(); - uint8 level = fields[0].GetUInt8(); - uint32 basexp = fields[1].GetUInt32(); - mBaseXPTable[level] = basexp; - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u BaseXP definitions", count); -} - -uint32 ObjectMgr::GetBaseXP(uint8 level) -{ - return mBaseXPTable[level] ? mBaseXPTable[level] : 0; -} - -uint32 ObjectMgr::GetXPForLevel(uint8 level) -{ - if (level < mPlayerXPperLevel.size()) - return mPlayerXPperLevel[level]; - return 0; -} - -void ObjectMgr::LoadPetNames() -{ - uint32 count = 0; - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT word,entry,half FROM pet_name_generation"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u pet name parts", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Field *fields = result->Fetch(); - std::string word = fields[0].GetString(); - uint32 entry = fields[1].GetUInt32(); - bool half = fields[2].GetBool(); - if (half) - PetHalfName1[entry].push_back(word); - else - PetHalfName0[entry].push_back(word); - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u pet name parts", count); -} - -void ObjectMgr::LoadPetNumber() -{ - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(id) FROM character_pet"); - if (result) - { - Field *fields = result->Fetch(); - m_hiPetNumber = fields[0].GetUInt32()+1; - } - - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded the max pet number: %d", m_hiPetNumber-1); -} - -std::string ObjectMgr::GeneratePetName(uint32 entry) -{ - std::vector & list0 = PetHalfName0[entry]; - std::vector & list1 = PetHalfName1[entry]; - - if (list0.empty() || list1.empty()) - { - CreatureInfo const *cinfo = GetCreatureTemplate(entry); - char* petname = GetPetName(cinfo->family, sWorld.GetDefaultDbcLocale()); - if (!petname) - petname = cinfo->Name; - return std::string(petname); - } - - return *(list0.begin()+urand(0, list0.size()-1)) + *(list1.begin()+urand(0, list1.size()-1)); -} - -uint32 ObjectMgr::GeneratePetNumber() -{ - return ++m_hiPetNumber; -} - -void ObjectMgr::LoadCorpses() -{ - uint32 count = 0; - // 0 1 2 3 4 5 6 7 8 9 10 - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT position_x, position_y, position_z, orientation, map, data, time, corpse_type, instance, phaseMask, guid FROM corpse WHERE corpse_type <> 0"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u corpses", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Field *fields = result->Fetch(); - - uint32 guid = fields[result->GetFieldCount()-1].GetUInt32(); - - Corpse *corpse = new Corpse; - if (!corpse->LoadFromDB(guid,fields)) - { - delete corpse; - continue; - } - - ObjectAccessor::Instance().AddCorpse(corpse); - - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u corpses", count); -} - -void ObjectMgr::LoadReputationOnKill() -{ - uint32 count = 0; - - // 0 1 2 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT creature_id, RewOnKillRepFaction1, RewOnKillRepFaction2," - // 3 4 5 6 7 8 9 - "IsTeamAward1, MaxStanding1, RewOnKillRepValue1, IsTeamAward2, MaxStanding2, RewOnKillRepValue2, TeamDependent " - "FROM creature_onkill_reputation"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 creature_id = fields[0].GetUInt32(); - - ReputationOnKillEntry repOnKill; - repOnKill.repfaction1 = fields[1].GetUInt32(); - repOnKill.repfaction2 = fields[2].GetUInt32(); - repOnKill.is_teamaward1 = fields[3].GetBool(); - repOnKill.reputation_max_cap1 = fields[4].GetUInt32(); - repOnKill.repvalue1 = fields[5].GetInt32(); - repOnKill.is_teamaward2 = fields[6].GetBool(); - repOnKill.reputation_max_cap2 = fields[7].GetUInt32(); - repOnKill.repvalue2 = fields[8].GetInt32(); - repOnKill.team_dependent = fields[9].GetUInt8(); - - if (!GetCreatureTemplate(creature_id)) - { - sLog.outErrorDb("Table `creature_onkill_reputation` have data for not existed creature entry (%u), skipped",creature_id); - continue; - } - - if (repOnKill.repfaction1) - { - FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(repOnKill.repfaction1); - if (!factionEntry1) - { - sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`",repOnKill.repfaction1); - continue; - } - } - - if (repOnKill.repfaction2) - { - FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(repOnKill.repfaction2); - if (!factionEntry2) - { - sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`",repOnKill.repfaction2); - continue; - } - } - - mRepOnKill[creature_id] = repOnKill; - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u creature award reputation definitions", count); -} - -void ObjectMgr::LoadPointsOfInterest() -{ - uint32 count = 0; - - // 0 1 2 3 4 5 6 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, x, y, icon, flags, data, icon_name FROM points_of_interest"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 Points of Interest definitions. DB table `points_of_interest` is empty."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 point_id = fields[0].GetUInt32(); - - PointOfInterest POI; - POI.x = fields[1].GetFloat(); - POI.y = fields[2].GetFloat(); - POI.icon = fields[3].GetUInt32(); - POI.flags = fields[4].GetUInt32(); - POI.data = fields[5].GetUInt32(); - POI.icon_name = fields[6].GetCppString(); - - if (!Trinity::IsValidMapCoord(POI.x,POI.y)) - { - sLog.outErrorDb("Table `points_of_interest` (Entry: %u) have invalid coordinates (X: %f Y: %f), ignored.",point_id,POI.x,POI.y); - continue; - } - - mPointsOfInterest[point_id] = POI; - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u Points of Interest definitions", count); -} - -void ObjectMgr::LoadQuestPOI() -{ - uint32 count = 0; - - // 0 1 2 3 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT questId, id, objIndex, mapid, WorldMapAreaId, FloorId, unk3, unk4 FROM quest_poi order by questId"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 questId = fields[0].GetUInt32(); - uint32 id = fields[1].GetUInt32(); - int32 objIndex = fields[2].GetInt32(); - uint32 mapId = fields[3].GetUInt32(); - uint32 WorldMapAreaId = fields[4].GetUInt32(); - uint32 FloorId = fields[5].GetUInt32(); - uint32 unk3 = fields[6].GetUInt32(); - uint32 unk4 = fields[7].GetUInt32(); - - QuestPOI POI(id, objIndex, mapId, WorldMapAreaId, FloorId, unk3, unk4); - - QueryResult_AutoPtr points = WorldDatabase.PQuery("SELECT x, y FROM quest_poi_points WHERE questId='%u' AND id='%i'", questId, id); - - if (points) - { - do - { - Field *pointFields = points->Fetch(); - int32 x = pointFields[0].GetInt32(); - int32 y = pointFields[1].GetInt32(); - QuestPOIPoint point(x, y); - POI.points.push_back(point); - } while (points->NextRow()); - } - - mQuestPOIMap[questId].push_back(POI); - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u quest POI definitions", count); -} - -void ObjectMgr::LoadNPCSpellClickSpells() -{ - uint32 count = 0; - - mSpellClickInfoMap.clear(); - // 0 1 2 3 4 5 6 7 8 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags, aura_required, aura_forbidden, user_type FROM npc_spellclick_spells"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 npc_entry = fields[0].GetUInt32(); - CreatureInfo const* cInfo = GetCreatureTemplate(npc_entry); - if (!cInfo) - { - sLog.outErrorDb("Table npc_spellclick_spells references unknown creature_template %u. Skipping entry.", npc_entry); - continue; - } - - if (!(cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK)) - const_cast(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK; - - uint32 spellid = fields[1].GetUInt32(); - SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid); - if (!spellinfo) - { - sLog.outErrorDb("Table npc_spellclick_spells references unknown spellid %u. Skipping entry.", spellid); - continue; - } - - uint32 auraRequired = fields[6].GetUInt32(); - if (auraRequired) - { - SpellEntry const *aurReqInfo = sSpellStore.LookupEntry(auraRequired); - if (!aurReqInfo) - { - sLog.outErrorDb("Table npc_spellclick_spells references unknown aura required %u. Skipping entry.", auraRequired); - continue; - } - } - - uint32 auraForbidden = fields[7].GetUInt32(); - if (auraForbidden) - { - SpellEntry const *aurForInfo = sSpellStore.LookupEntry(auraForbidden); - if (!aurForInfo) - { - sLog.outErrorDb("Table npc_spellclick_spells references unknown aura forbidden %u. Skipping entry.", auraForbidden); - continue; - } - } - - uint32 quest_start = fields[2].GetUInt32(); - - // quest might be 0 to enable spellclick independent of any quest - if (quest_start) - { - if (mQuestTemplates.find(quest_start) == mQuestTemplates.end()) - { - sLog.outErrorDb("Table npc_spellclick_spells references unknown start quest %u. Skipping entry.", quest_start); - continue; - } - } - - bool quest_start_active = fields[3].GetBool(); - - uint32 quest_end = fields[4].GetUInt32(); - // quest might be 0 to enable spellclick active infinity after start quest - if (quest_end) - { - if (mQuestTemplates.find(quest_end) == mQuestTemplates.end()) - { - sLog.outErrorDb("Table npc_spellclick_spells references unknown end quest %u. Skipping entry.", quest_end); - continue; - } - } - - uint8 userType = fields[8].GetUInt8(); - if (userType >= SPELL_CLICK_USER_MAX) - sLog.outErrorDb("Table npc_spellclick_spells references unknown user type %u. Skipping entry.", uint32(userType)); - - uint8 castFlags = fields[5].GetUInt8(); - SpellClickInfo info; - info.spellId = spellid; - info.questStart = quest_start; - info.questStartCanActive = quest_start_active; - info.questEnd = quest_end; - info.castFlags = castFlags; - info.auraRequired = auraRequired; - info.auraForbidden = auraForbidden; - info.userType = SpellClickUserTypes(userType); - mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info)); - - // mark creature template as spell clickable - const_cast(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK; - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u spellclick definitions", count); -} - -void ObjectMgr::LoadWeatherZoneChances() -{ - uint32 count = 0; - - // 0 1 2 3 4 5 6 7 8 9 10 11 12 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT zone, spring_rain_chance, spring_snow_chance, spring_storm_chance, summer_rain_chance, summer_snow_chance, summer_storm_chance, fall_rain_chance, fall_snow_chance, fall_storm_chance, winter_rain_chance, winter_snow_chance, winter_storm_chance FROM game_weather"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 weather definitions. DB table `game_weather` is empty."); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 zone_id = fields[0].GetUInt32(); - - WeatherZoneChances& wzc = mWeatherZoneMap[zone_id]; - - for (uint8 season = 0; season < WEATHER_SEASONS; ++season) - { - wzc.data[season].rainChance = fields[season * (MAX_WEATHER_TYPE-1) + 1].GetUInt32(); - wzc.data[season].snowChance = fields[season * (MAX_WEATHER_TYPE-1) + 2].GetUInt32(); - wzc.data[season].stormChance = fields[season * (MAX_WEATHER_TYPE-1) + 3].GetUInt32(); - - if (wzc.data[season].rainChance > 100) - { - wzc.data[season].rainChance = 25; - sLog.outErrorDb("Weather for zone %u season %u has wrong rain chance > 100%%",zone_id,season); - } - - if (wzc.data[season].snowChance > 100) - { - wzc.data[season].snowChance = 25; - sLog.outErrorDb("Weather for zone %u season %u has wrong snow chance > 100%%",zone_id,season); - } - - if (wzc.data[season].stormChance > 100) - { - wzc.data[season].stormChance = 25; - sLog.outErrorDb("Weather for zone %u season %u has wrong storm chance > 100%%",zone_id,season); - } - } - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u weather definitions", count); -} - -void ObjectMgr::SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t) -{ - mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)] = t; - WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE guid = '%u' AND instance = '%u'", loguid, instance); - if (t) - WorldDatabase.PExecute("INSERT INTO creature_respawn VALUES ('%u', '" UI64FMTD "', '%u')", loguid, uint64(t), instance); -} - -void ObjectMgr::DeleteCreatureData(uint32 guid) -{ - // remove mapid*cellid -> guid_set map - CreatureData const* data = GetCreatureData(guid); - if (data) - RemoveCreatureFromGrid(guid, data); - - mCreatureDataMap.erase(guid); -} - -void ObjectMgr::SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t) -{ - mGORespawnTimes[MAKE_PAIR64(loguid,instance)] = t; - WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE guid = '%u' AND instance = '%u'", loguid, instance); - if (t) - WorldDatabase.PExecute("INSERT INTO gameobject_respawn VALUES ('%u', '" UI64FMTD "', '%u')", loguid, uint64(t), instance); -} - -void ObjectMgr::DeleteRespawnTimeForInstance(uint32 instance) -{ - RespawnTimes::iterator next; - - for (RespawnTimes::iterator itr = mGORespawnTimes.begin(); itr != mGORespawnTimes.end(); itr = next) - { - next = itr; - ++next; - - if (GUID_HIPART(itr->first) == instance) - mGORespawnTimes.erase(itr); - } - - for (RespawnTimes::iterator itr = mCreatureRespawnTimes.begin(); itr != mCreatureRespawnTimes.end(); itr = next) - { - next = itr; - ++next; - - if (GUID_HIPART(itr->first) == instance) - mCreatureRespawnTimes.erase(itr); - } - - WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'", instance); - WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'", instance); -} - -void ObjectMgr::DeleteGOData(uint32 guid) -{ - // remove mapid*cellid -> guid_set map - GameObjectData const* data = GetGOData(guid); - if (data) - RemoveGameobjectFromGrid(guid, data); - - mGameObjectDataMap.erase(guid); -} - -void ObjectMgr::AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance) -{ - // corpses are always added to spawn mode 0 and they are spawned by their instance id - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(mapid,0)][cellid]; - cell_guids.corpses[player_guid] = instance; -} - -void ObjectMgr::DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid) -{ - // corpses are always added to spawn mode 0 and they are spawned by their instance id - CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(mapid,0)][cellid]; - cell_guids.corpses.erase(player_guid); -} - -void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map,char const* table) -{ - map.clear(); // need for reload case - - uint32 count = 0; - - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id,quest FROM %s",table); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded 0 quest relations from %s. DB table `%s` is empty.",table,table); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - uint32 id = fields[0].GetUInt32(); - uint32 quest = fields[1].GetUInt32(); - - if (mQuestTemplates.find(quest) == mQuestTemplates.end()) - { - sLog.outErrorDb("Table `%s: Quest %u listed for entry %u does not exist.",table,quest,id); - continue; - } - - map.insert(QuestRelations::value_type(id,quest)); - - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u quest relations from %s", count,table); -} - -void ObjectMgr::LoadGameobjectQuestRelations() -{ - LoadQuestRelationsHelper(mGOQuestRelations,"gameobject_questrelation"); - - for (QuestRelations::iterator itr = mGOQuestRelations.begin(); itr != mGOQuestRelations.end(); ++itr) - { - GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first); - if (!goInfo) - sLog.outErrorDb("Table `gameobject_questrelation` have data for not existed gameobject entry (%u) and existed quest %u",itr->first,itr->second); - else if (goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER) - sLog.outErrorDb("Table `gameobject_questrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER",itr->first,itr->second); - } -} - -void ObjectMgr::LoadGameobjectInvolvedRelations() -{ - LoadQuestRelationsHelper(mGOQuestInvolvedRelations,"gameobject_involvedrelation"); - - for (QuestRelations::iterator itr = mGOQuestInvolvedRelations.begin(); itr != mGOQuestInvolvedRelations.end(); ++itr) - { - GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first); - if (!goInfo) - sLog.outErrorDb("Table `gameobject_involvedrelation` have data for not existed gameobject entry (%u) and existed quest %u",itr->first,itr->second); - else if (goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER) - sLog.outErrorDb("Table `gameobject_involvedrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER",itr->first,itr->second); - } -} - -void ObjectMgr::LoadCreatureQuestRelations() -{ - LoadQuestRelationsHelper(mCreatureQuestRelations,"creature_questrelation"); - - for (QuestRelations::iterator itr = mCreatureQuestRelations.begin(); itr != mCreatureQuestRelations.end(); ++itr) - { - CreatureInfo const* cInfo = GetCreatureTemplate(itr->first); - if (!cInfo) - sLog.outErrorDb("Table `creature_questrelation` have data for not existed creature entry (%u) and existed quest %u",itr->first,itr->second); - else if (!(cInfo->npcflag & UNIT_NPC_FLAG_QUESTGIVER)) - sLog.outErrorDb("Table `creature_questrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER",itr->first,itr->second); - } -} - -void ObjectMgr::LoadCreatureInvolvedRelations() -{ - LoadQuestRelationsHelper(mCreatureQuestInvolvedRelations,"creature_involvedrelation"); - - for (QuestRelations::iterator itr = mCreatureQuestInvolvedRelations.begin(); itr != mCreatureQuestInvolvedRelations.end(); ++itr) - { - CreatureInfo const* cInfo = GetCreatureTemplate(itr->first); - if (!cInfo) - sLog.outErrorDb("Table `creature_involvedrelation` have data for not existed creature entry (%u) and existed quest %u",itr->first,itr->second); - else if (!(cInfo->npcflag & UNIT_NPC_FLAG_QUESTGIVER)) - sLog.outErrorDb("Table `creature_involvedrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER",itr->first,itr->second); - } -} - -void ObjectMgr::LoadReservedPlayersNames() -{ - m_ReservedNames.clear(); // need for reload case - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT name FROM reserved_name"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u reserved player names", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - Field* fields; - do - { - bar.step(); - fields = result->Fetch(); - std::string name= fields[0].GetCppString(); - - std::wstring wstr; - if (!Utf8toWStr (name,wstr)) - { - sLog.outError("Table `reserved_name` have invalid name: %s", name.c_str()); - continue; - } - - wstrToLower(wstr); - - m_ReservedNames.insert(wstr); - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u reserved player names", count); -} - -bool ObjectMgr::IsReservedName(const std::string& name) const -{ - std::wstring wstr; - if (!Utf8toWStr (name,wstr)) - return false; - - wstrToLower(wstr); - - return m_ReservedNames.find(wstr) != m_ReservedNames.end(); -} - -enum LanguageType -{ - LT_BASIC_LATIN = 0x0000, - LT_EXTENDEN_LATIN = 0x0001, - LT_CYRILLIC = 0x0002, - LT_EAST_ASIA = 0x0004, - LT_ANY = 0xFFFF -}; - -static LanguageType GetRealmLanguageType(bool create) -{ - switch(sWorld.getConfig(CONFIG_REALM_ZONE)) - { - case REALM_ZONE_UNKNOWN: // any language - case REALM_ZONE_DEVELOPMENT: - case REALM_ZONE_TEST_SERVER: - case REALM_ZONE_QA_SERVER: - return LT_ANY; - case REALM_ZONE_UNITED_STATES: // extended-Latin - case REALM_ZONE_OCEANIC: - case REALM_ZONE_LATIN_AMERICA: - case REALM_ZONE_ENGLISH: - case REALM_ZONE_GERMAN: - case REALM_ZONE_FRENCH: - case REALM_ZONE_SPANISH: - return LT_EXTENDEN_LATIN; - case REALM_ZONE_KOREA: // East-Asian - case REALM_ZONE_TAIWAN: - case REALM_ZONE_CHINA: - return LT_EAST_ASIA; - case REALM_ZONE_RUSSIAN: // Cyrillic - return LT_CYRILLIC; - default: - return create ? LT_BASIC_LATIN : LT_ANY; // basic-Latin at create, any at login - } -} - -bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bool create = false) -{ - if (strictMask == 0) // any language, ignore realm - { - if (isExtendedLatinString(wstr,numericOrSpace)) - return true; - if (isCyrillicString(wstr,numericOrSpace)) - return true; - if (isEastAsianString(wstr,numericOrSpace)) - return true; - return false; - } - - if (strictMask & 0x2) // realm zone specific - { - LanguageType lt = GetRealmLanguageType(create); - if (lt & LT_EXTENDEN_LATIN) - if (isExtendedLatinString(wstr,numericOrSpace)) - return true; - if (lt & LT_CYRILLIC) - if (isCyrillicString(wstr,numericOrSpace)) - return true; - if (lt & LT_EAST_ASIA) - if (isEastAsianString(wstr,numericOrSpace)) - return true; - } - - if (strictMask & 0x1) // basic Latin - { - if (isBasicLatinString(wstr,numericOrSpace)) - return true; - } - - return false; -} - -uint8 ObjectMgr::CheckPlayerName(const std::string& name, bool create) -{ - std::wstring wname; - if (!Utf8toWStr(name,wname)) - return CHAR_NAME_INVALID_CHARACTER; - - if (wname.size() > MAX_PLAYER_NAME) - return CHAR_NAME_TOO_LONG; - - uint32 minName = sWorld.getConfig(CONFIG_MIN_PLAYER_NAME); - if (wname.size() < minName) - return CHAR_NAME_TOO_SHORT; - - uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PLAYER_NAMES); - if (!isValidString(wname,strictMask,false,create)) - return CHAR_NAME_MIXED_LANGUAGES; - - return CHAR_NAME_SUCCESS; -} - -bool ObjectMgr::IsValidCharterName(const std::string& name) -{ - std::wstring wname; - if (!Utf8toWStr(name,wname)) - return false; - - if (wname.size() > MAX_CHARTER_NAME) - return false; - - uint32 minName = sWorld.getConfig(CONFIG_MIN_CHARTER_NAME); - if (wname.size() < minName) - return false; - - uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_CHARTER_NAMES); - - return isValidString(wname,strictMask,true); -} - -PetNameInvalidReason ObjectMgr::CheckPetName(const std::string& name) -{ - std::wstring wname; - if (!Utf8toWStr(name,wname)) - return PET_NAME_INVALID; - - if (wname.size() > MAX_PET_NAME) - return PET_NAME_TOO_LONG; - - uint32 minName = sWorld.getConfig(CONFIG_MIN_PET_NAME); - if (wname.size() < minName) - return PET_NAME_TOO_SHORT; - - uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PET_NAMES); - if (!isValidString(wname,strictMask,false)) - return PET_NAME_MIXED_LANGUAGES; - - return PET_NAME_SUCCESS; -} - -int ObjectMgr::GetIndexForLocale(LocaleConstant loc) -{ - if (loc == LOCALE_enUS) - return -1; - - for (size_t i=0; i < m_LocalForIndex.size(); ++i) - if (m_LocalForIndex[i] == loc) - return i; - - return -1; -} - -LocaleConstant ObjectMgr::GetLocaleForIndex(int i) -{ - if (i<0 || i >= m_LocalForIndex.size()) - return LOCALE_enUS; - - return m_LocalForIndex[i]; -} - -int ObjectMgr::GetOrNewIndexForLocale(LocaleConstant loc) -{ - if (loc == LOCALE_enUS) - return -1; - - for (size_t i=0; i < m_LocalForIndex.size(); ++i) - if (m_LocalForIndex[i] == loc) - return i; - - m_LocalForIndex.push_back(loc); - return m_LocalForIndex.size()-1; -} - -void ObjectMgr::LoadGameObjectForQuests() -{ - mGameObjectForQuestSet.clear(); // need for reload case - - if (!sGOStorage.MaxEntry) - { - barGoLink bar(1); - bar.step(); - sLog.outString(); - sLog.outString(">> Loaded 0 GameObjects for quests"); - return; - } - - barGoLink bar(sGOStorage.MaxEntry - 1); - uint32 count = 0; - - // collect GO entries for GO that must activated - for (uint32 go_entry = 1; go_entry < sGOStorage.MaxEntry; ++go_entry) - { - bar.step(); - GameObjectInfo const* goInfo = sGOStorage.LookupEntry(go_entry); - if (!goInfo) - continue; - - switch(goInfo->type) - { - // scan GO chest with loot including quest items - case GAMEOBJECT_TYPE_CHEST: - { - uint32 loot_id = goInfo->GetLootId(); - - // find quest loot for GO - if (LootTemplates_Gameobject.HaveQuestLootFor(loot_id)) - { - mGameObjectForQuestSet.insert(go_entry); - ++count; - } - break; - } - case GAMEOBJECT_TYPE_GOOBER: - { - if (goInfo->goober.questId) //quests objects - { - mGameObjectForQuestSet.insert(go_entry); - count++; - } - break; - } - default: - break; - } - } - - sLog.outString(); - sLog.outString(">> Loaded %u GameObjects for quests", count); -} - -bool ObjectMgr::LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value) -{ - int32 start_value = min_value; - int32 end_value = max_value; - // some string can have negative indexes range - if (start_value < 0) - { - if (end_value >= start_value) - { - sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded.",table,min_value,max_value); - return false; - } - - // real range (max+1,min+1) exaple: (-10,-1000) -> -999...-10+1 - std::swap(start_value,end_value); - ++start_value; - ++end_value; - } - else - { - if (start_value >= end_value) - { - sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded.",table,min_value,max_value); - return false; - } - } - - // cleanup affected map part for reloading case - for (TrinityStringLocaleMap::iterator itr = mTrinityStringLocaleMap.begin(); itr != mTrinityStringLocaleMap.end();) - { - if (itr->first >= start_value && itr->first < end_value) - mTrinityStringLocaleMap.erase(itr++); - else - ++itr; - } - - QueryResult_AutoPtr result = db.PQuery("SELECT entry,content_default,content_loc1,content_loc2,content_loc3,content_loc4,content_loc5,content_loc6,content_loc7,content_loc8 FROM %s",table); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - if (min_value == MIN_TRINITY_STRING_ID) // error only in case internal strings - sLog.outErrorDb(">> Loaded 0 trinity strings. DB table `%s` is empty. Cannot continue.",table); - else - sLog.outString(">> Loaded 0 string templates. DB table `%s` is empty.",table); - return false; - } - - uint32 count = 0; - - barGoLink bar(result->GetRowCount()); - - do - { - Field *fields = result->Fetch(); - bar.step(); - - int32 entry = fields[0].GetInt32(); - - if (entry == 0) - { - sLog.outErrorDb("Table `%s` contain reserved entry 0, ignored.",table); - continue; - } - else if (entry < start_value || entry >= end_value) - { - sLog.outErrorDb("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,min_value,max_value); - continue; - } - - TrinityStringLocale& data = mTrinityStringLocaleMap[entry]; - - if (data.Content.size() > 0) - { - sLog.outErrorDb("Table `%s` contain data for already loaded entry %i (from another table?), ignored.",table,entry); - continue; - } - - data.Content.resize(1); - ++count; - - // 0 -> default, idx in to idx+1 - data.Content[0] = fields[1].GetCppString(); - - for (uint8 i = 1; i < MAX_LOCALE; ++i) - { - std::string str = fields[i+1].GetCppString(); - if (!str.empty()) - { - int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if (idx >= 0) - { - // 0 -> default, idx in to idx+1 - if (data.Content.size() <= idx+1) - data.Content.resize(idx+2); - - data.Content[idx+1] = str; - } - } - } - } while (result->NextRow()); - - sLog.outString(); - if (min_value == MIN_TRINITY_STRING_ID) - sLog.outString(">> Loaded %u Trinity strings from table %s", count,table); - else - sLog.outString(">> Loaded %u string templates from %s", count,table); - - return true; -} - -const char *ObjectMgr::GetTrinityString(int32 entry, int locale_idx) const -{ - // locale_idx == -1 -> default, locale_idx >= 0 in to idx+1 - // Content[0] always exist if exist TrinityStringLocale - if (TrinityStringLocale const *msl = GetTrinityStringLocale(entry)) - { - if (msl->Content.size() > locale_idx+1 && !msl->Content[locale_idx+1].empty()) - return msl->Content[locale_idx+1].c_str(); - else - return msl->Content[0].c_str(); - } - - if (entry > 0) - sLog.outErrorDb("Entry %i not found in `trinity_string` table.",entry); - else - sLog.outErrorDb("Trinity string entry %i not found in DB.",entry); - return ""; -} - -void ObjectMgr::LoadSpellDisabledEntrys() -{ - m_DisabledPlayerSpells.clear(); // need for reload case - m_DisabledCreatureSpells.clear(); - m_DisabledPetSpells.clear(); - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, disable_mask FROM spell_disabled"); - - uint32 total_count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u disabled spells", total_count); - return; - } - - barGoLink bar(result->GetRowCount()); - - Field* fields; - do - { - bar.step(); - fields = result->Fetch(); - uint32 spellid = fields[0].GetUInt32(); - if (!sSpellStore.LookupEntry(spellid)) - { - sLog.outErrorDb("Spell entry %u from `spell_disabled` doesn't exist in dbc, ignoring.",spellid); - continue; - } - uint32 disable_mask = fields[1].GetUInt32(); - if (disable_mask & SPELL_DISABLE_PLAYER) - m_DisabledPlayerSpells.insert(spellid); - if (disable_mask & SPELL_DISABLE_CREATURE) - m_DisabledCreatureSpells.insert(spellid); - if (disable_mask & SPELL_DISABLE_PET) - m_DisabledPetSpells.insert(spellid); - ++total_count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u disabled spells from `spell_disabled`", total_count); -} - -void ObjectMgr::LoadFishingBaseSkillLevel() -{ - mFishingBaseForArea.clear(); // for reload case - - uint32 count = 0; - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,skill FROM skill_fishing_base_level"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded `skill_fishing_base_level`, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Field *fields = result->Fetch(); - uint32 entry = fields[0].GetUInt32(); - int32 skill = fields[1].GetInt32(); - - AreaTableEntry const* fArea = GetAreaEntryByAreaID(entry); - if (!fArea) - { - sLog.outErrorDb("AreaId %u defined in `skill_fishing_base_level` does not exist",entry); - continue; - } - - mFishingBaseForArea[entry] = skill; - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u areas for fishing base skill level", count); -} - -bool ObjectMgr::CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names) -{ - for (uint8 i =0; i < MAX_DECLINED_NAME_CASES; ++i) - { - std::wstring wname; - if (!Utf8toWStr(names.name[i],wname)) - return false; - - if (mainpart != GetMainPartOfName(wname,i+1)) - return false; - } - return true; -} - -uint32 ObjectMgr::GetAreaTriggerScriptId(uint32 trigger_id) -{ - AreaTriggerScriptMap::const_iterator i = mAreaTriggerScripts.find(trigger_id); - if (i!= mAreaTriggerScripts.end()) - return i->second; - return 0; -} - -SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial) -{ - switch(pSkill->categoryId) - { - case SKILL_CATEGORY_LANGUAGES: return SKILL_RANGE_LANGUAGE; - case SKILL_CATEGORY_WEAPON: - if (pSkill->id != SKILL_FIST_WEAPONS) - return SKILL_RANGE_LEVEL; - else - return SKILL_RANGE_MONO; - case SKILL_CATEGORY_ARMOR: - case SKILL_CATEGORY_CLASS: - if (pSkill->id != SKILL_LOCKPICKING) - return SKILL_RANGE_MONO; - else - return SKILL_RANGE_LEVEL; - case SKILL_CATEGORY_SECONDARY: - case SKILL_CATEGORY_PROFESSION: - // not set skills for professions and racial abilities - if (IsProfessionSkill(pSkill->id)) - return SKILL_RANGE_RANK; - else if (racial) - return SKILL_RANGE_NONE; - else - return SKILL_RANGE_MONO; - default: - case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc - case SKILL_CATEGORY_GENERIC: //only GENERIC(DND) - return SKILL_RANGE_NONE; - } -} - -void ObjectMgr::LoadGameTele() -{ - m_GameTeleMap.clear(); // for reload case - - uint32 count = 0; - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, map, name FROM game_tele"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded `game_tele`, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Field *fields = result->Fetch(); - - uint32 id = fields[0].GetUInt32(); - - GameTele gt; - - gt.position_x = fields[1].GetFloat(); - gt.position_y = fields[2].GetFloat(); - gt.position_z = fields[3].GetFloat(); - gt.orientation = fields[4].GetFloat(); - gt.mapId = fields[5].GetUInt32(); - gt.name = fields[6].GetCppString(); - - if (!MapManager::IsValidMapCoord(gt.mapId,gt.position_x,gt.position_y,gt.position_z,gt.orientation)) - { - sLog.outErrorDb("Wrong position for id %u (name: %s) in `game_tele` table, ignoring.",id,gt.name.c_str()); - continue; - } - - if (!Utf8toWStr(gt.name,gt.wnameLow)) - { - sLog.outErrorDb("Wrong UTF8 name for id %u in `game_tele` table, ignoring.",id); - continue; - } - - wstrToLower(gt.wnameLow); - - m_GameTeleMap[id] = gt; - - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u GameTeleports", count); -} - -GameTele const* ObjectMgr::GetGameTele(const std::string& name) const -{ - // explicit name case - std::wstring wname; - if (!Utf8toWStr(name,wname)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wname); - - // Alternative first GameTele what contains wnameLow as substring in case no GameTele location found - const GameTele* alt = NULL; - for (GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) - { - if (itr->second.wnameLow == wname) - return &itr->second; - else if (alt == NULL && itr->second.wnameLow.find(wname) != std::wstring::npos) - alt = &itr->second; - } - - return alt; -} - -bool ObjectMgr::AddGameTele(GameTele& tele) -{ - // find max id - uint32 new_id = 0; - for (GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) - if (itr->first > new_id) - new_id = itr->first; - - // use next - ++new_id; - - if (!Utf8toWStr(tele.name,tele.wnameLow)) - return false; - - wstrToLower(tele.wnameLow); - - m_GameTeleMap[new_id] = tele; - - return WorldDatabase.PExecuteLog("INSERT INTO game_tele (id,position_x,position_y,position_z,orientation,map,name) VALUES (%u,%f,%f,%f,%f,%d,'%s')", - new_id,tele.position_x,tele.position_y,tele.position_z,tele.orientation,tele.mapId,tele.name.c_str()); -} - -bool ObjectMgr::DeleteGameTele(const std::string& name) -{ - // explicit name case - std::wstring wname; - if (!Utf8toWStr(name,wname)) - return false; - - // converting string that we try to find to lower case - wstrToLower(wname); - - for (GameTeleMap::iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) - { - if (itr->second.wnameLow == wname) - { - WorldDatabase.PExecuteLog("DELETE FROM game_tele WHERE name = '%s'",itr->second.name.c_str()); - m_GameTeleMap.erase(itr); - return true; - } - } - - return false; -} - -void ObjectMgr::LoadMailLevelRewards() -{ - m_mailLevelRewardMap.clear(); // for reload case - - uint32 count = 0; - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT level, raceMask, mailTemplateId, senderEntry FROM mail_level_reward"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded `mail_level_reward`, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Field *fields = result->Fetch(); - - uint8 level = fields[0].GetUInt8(); - uint32 raceMask = fields[1].GetUInt32(); - uint32 mailTemplateId = fields[2].GetUInt32(); - uint32 senderEntry = fields[3].GetUInt32(); - - if (level > MAX_LEVEL) - { - sLog.outErrorDb("Table `mail_level_reward` have data for level %u that more supported by client (%u), ignoring.",level,MAX_LEVEL); - continue; - } - - if (!(raceMask & RACEMASK_ALL_PLAYABLE)) - { - sLog.outErrorDb("Table `mail_level_reward` have raceMask (%u) for level %u that not include any player races, ignoring.",raceMask,level); - continue; - } - - if (!sMailTemplateStore.LookupEntry(mailTemplateId)) - { - sLog.outErrorDb("Table `mail_level_reward` have invalid mailTemplateId (%u) for level %u that invalid not include any player races, ignoring.",mailTemplateId,level); - continue; - } - - if (!GetCreatureTemplateStore(senderEntry)) - { - sLog.outErrorDb("Table `mail_level_reward` have not existed sender creature entry (%u) for level %u that invalid not include any player races, ignoring.",senderEntry,level); - continue; - } - - m_mailLevelRewardMap[level].push_back(MailLevelReward(raceMask,mailTemplateId,senderEntry)); - - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u level dependent mail rewards,", count); -} - -bool ObjectMgr::AddSpellToTrainer(uint32 entry, uint32 spell, Field *fields, std::set *skip_trainers, std::set *talentIds) -{ - if (entry >= TRINITY_TRAINER_START_REF) - return false; - - CreatureInfo const* cInfo = GetCreatureTemplate(entry); - if (!cInfo) - { - sLog.outErrorDb("Table `npc_trainer` have entry for not existed creature template (Entry: %u), ignore", entry); - return false; - } - - if (!(cInfo->npcflag & UNIT_NPC_FLAG_TRAINER)) - { - if (skip_trainers->find(entry) == skip_trainers->end()) - { - sLog.outErrorDb("Table `npc_trainer` have data for not creature template (Entry: %u) without trainer flag, ignore", entry); - skip_trainers->insert(entry); - } - return false; - } - - SpellEntry const *spellinfo = sSpellStore.LookupEntry(spell); - if (!spellinfo) - { - sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u) has non existing spell %u, ignore", entry,spell); - return false; - } - - if (!SpellMgr::IsSpellValid(spellinfo)) - { - sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u) has broken learning spell %u, ignore", entry, spell); - return false; - } - - if (GetTalentSpellCost(spell)) - { - if (talentIds->count(spell) == 0) - { - sLog.outErrorDb("Table `npc_trainer` has talent as learning spell %u, ignore", spell); - talentIds->insert(spell); - } - return false; - } - - TrainerSpellData& data = m_mCacheTrainerSpellMap[entry]; - - TrainerSpell& trainerSpell = data.spellList[spell]; - trainerSpell.spell = spell; - trainerSpell.spellCost = fields[2].GetUInt32(); - trainerSpell.reqSkill = fields[3].GetUInt32(); - trainerSpell.reqSkillValue = fields[4].GetUInt32(); - trainerSpell.reqLevel = fields[5].GetUInt32(); - - if (!trainerSpell.reqLevel) - trainerSpell.reqLevel = spellinfo->spellLevel; - - // calculate learned spell for profession case when stored cast-spell - trainerSpell.learnedSpell[0] = spell; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (spellinfo->Effect[i] != SPELL_EFFECT_LEARN_SPELL) - continue; - if (trainerSpell.learnedSpell[0] == spell) - trainerSpell.learnedSpell[0] = 0; - // player must be able to cast spell on himself - if (spellinfo->EffectImplicitTargetA[i] != 0 && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_TARGET_ALLY - && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_TARGET_ANY && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_CASTER) - { - sLog.outErrorDb("Table `npc_trainer` has spell %u for trainer entry %u with learn effect which has incorrect target type, ignoring learn effect!", spell, entry); - continue; - } - - trainerSpell.learnedSpell[i] = spellinfo->EffectTriggerSpell[i]; - } - - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (!trainerSpell.learnedSpell[i]) - continue; - if (SpellMgr::IsProfessionSpell(trainerSpell.learnedSpell[i])) - { - data.trainerType = 2; - break; - } - } - return true; -} -int ObjectMgr::LoadReferenceTrainer(uint32 trainer, int32 spell, std::set *skip_trainers, std::set *talentIds) -{ - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer WHERE entry='%d'", spell); - if (!result) - return 0; - - uint32 count = 0; - do - { - - Field* fields = result->Fetch(); - - int32 spell = fields[1].GetInt32(); - if (spell < 0) - count += this->LoadReferenceTrainer(trainer, -spell, skip_trainers, talentIds); - else if (this->AddSpellToTrainer(trainer, uint32(spell), fields, skip_trainers, talentIds)) - ++count; - } while (result->NextRow()); - - return count; -} - -void ObjectMgr::LoadTrainerSpell() -{ - // For reload case - for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr) - itr->second.Clear(); - m_mCacheTrainerSpellMap.clear(); - - std::set skip_trainers; - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded `npc_trainer`, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - std::set talentIds; - - uint32 count = 0; - do - { - bar.step(); - - Field* fields = result->Fetch(); - - uint32 entry = fields[0].GetUInt32(); - int32 spell = fields[1].GetInt32(); - if (spell < 0) - count += this->LoadReferenceTrainer(entry, -spell, &skip_trainers, &talentIds); - else if (this->AddSpellToTrainer(entry, uint32(spell), fields, &skip_trainers, &talentIds)) - ++count; - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %d Trainers", count); -} - -int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set *skip_vendors) -{ - // find all items from the reference vendor - QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry='%d' ORDER BY slot ASC", item); - if (!result) - return 0; - - uint32 count = 0; - do - { - Field* fields = result->Fetch(); - - int32 item_id = fields[0].GetInt32(); - - // if item is a negative, its a reference - if (item_id < 0) - count += LoadReferenceVendor(vendor, -item_id, skip_vendors); - else - { - int32 maxcount = fields[1].GetInt32(); - uint32 incrtime = fields[2].GetUInt32(); - uint32 ExtendedCost = fields[3].GetUInt32(); - - if (!IsVendorItemValid(vendor,item_id,maxcount,incrtime,ExtendedCost,NULL,skip_vendors)) - continue; - - VendorItemData& vList = m_mCacheVendorItemMap[vendor]; - - vList.AddItem(item_id,maxcount,incrtime,ExtendedCost); - ++count; - } - - } while (result->NextRow()); - - return count; -} - -void ObjectMgr::LoadVendors() -{ - // For reload case - for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) - itr->second.Clear(); - m_mCacheVendorItemMap.clear(); - - std::set skip_vendors; - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor ORDER BY entry, slot ASC"); - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded `npc_vendor`, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - uint32 count = 0; - do - { - bar.step(); - Field* fields = result->Fetch(); - - uint32 entry = fields[0].GetUInt32(); - int32 item_id = fields[1].GetInt32(); - - // if item is a negative, its a reference - if (item_id < 0) - count += LoadReferenceVendor(entry, -item_id, &skip_vendors); - else - { - int32 maxcount = fields[2].GetInt32(); - uint32 incrtime = fields[3].GetUInt32(); - uint32 ExtendedCost = fields[4].GetUInt32(); - - if (!IsVendorItemValid(entry,item_id,maxcount,incrtime,ExtendedCost,NULL,&skip_vendors)) - continue; - - VendorItemData& vList = m_mCacheVendorItemMap[entry]; - - vList.AddItem(item_id,maxcount,incrtime,ExtendedCost); - ++count; - } - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %d Vendors ", count); -} - -void ObjectMgr::LoadNpcTextId() -{ - - m_mCacheNpcTextIdMap.clear(); - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT npc_guid, textid FROM npc_gossip"); - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded `npc_gossip`, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - uint32 count = 0; - uint32 guid,textid; - do - { - bar.step(); - - Field* fields = result->Fetch(); - - guid = fields[0].GetUInt32(); - textid = fields[1].GetUInt32(); - - if (!GetCreatureData(guid)) - { - sLog.outErrorDb("Table `npc_gossip` have not existed creature (GUID: %u) entry, ignore. ",guid); - continue; - } - if (!GetGossipText(textid)) - { - sLog.outErrorDb("Table `npc_gossip` for creature (GUID: %u) have wrong Textid (%u), ignore. ", guid, textid); - continue; - } - - m_mCacheNpcTextIdMap[guid] = textid ; - ++count; - - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %d NpcTextId ", count); -} - -void ObjectMgr::LoadGossipMenu() -{ - m_mGossipMenusMap.clear(); - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, text_id FROM gossip_menu"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded `gossip_menu`, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - uint32 count = 0; - - do - { - bar.step(); - - Field* fields = result->Fetch(); - - GossipMenus gMenu; - - gMenu.entry = fields[0].GetUInt32(); - gMenu.text_id = fields[1].GetUInt32(); - - if (!GetGossipText(gMenu.text_id)) - { - sLog.outErrorDb("Table gossip_menu entry %u are using non-existing text_id %u", gMenu.entry, gMenu.text_id); - continue; - } - - m_mGossipMenusMap.insert(GossipMenusMap::value_type(gMenu.entry, gMenu)); - - ++count; - } - while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u gossip_menu entries", count); -} - -void ObjectMgr::LoadGossipMenuItems() -{ - m_mGossipMenuItemsMap.clear(); - - QueryResult_AutoPtr result = WorldDatabase.Query( - "SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, " - "action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text " - "FROM gossip_menu_option"); - - if (!result) - { - barGoLink bar(1); - - bar.step(); - - sLog.outString(); - sLog.outErrorDb(">> Loaded gossip_menu_option, table is empty!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - uint32 count = 0; - - std::set gossipScriptSet; - - for (ScriptMapMap::const_iterator itr = sGossipScripts.begin(); itr != sGossipScripts.end(); ++itr) - gossipScriptSet.insert(itr->first); - - do - { - bar.step(); - - Field* fields = result->Fetch(); - - GossipMenuItems gMenuItem; - - gMenuItem.menu_id = fields[0].GetUInt32(); - gMenuItem.id = fields[1].GetUInt32(); - gMenuItem.option_icon = fields[2].GetUInt8(); - gMenuItem.option_text = fields[3].GetCppString(); - gMenuItem.option_id = fields[4].GetUInt32(); - gMenuItem.npc_option_npcflag = fields[5].GetUInt32(); - gMenuItem.action_menu_id = fields[6].GetUInt32(); - gMenuItem.action_poi_id = fields[7].GetUInt32(); - gMenuItem.action_script_id = fields[8].GetUInt32(); - gMenuItem.box_coded = fields[9].GetUInt8() != 0; - gMenuItem.box_money = fields[10].GetUInt32(); - gMenuItem.box_text = fields[11].GetCppString(); - - if (gMenuItem.option_icon >= GOSSIP_ICON_MAX) - { - sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown icon id %u. Replacing with GOSSIP_ICON_CHAT", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_icon); - gMenuItem.option_icon = GOSSIP_ICON_CHAT; - } - - if (gMenuItem.option_id >= GOSSIP_OPTION_MAX) - sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown option id %u. Option will not be used", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_id); - - if (gMenuItem.action_poi_id && !GetPointOfInterest(gMenuItem.action_poi_id)) - { - sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u use non-existing action_poi_id %u, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_poi_id); - gMenuItem.action_poi_id = 0; - } - - if (gMenuItem.action_script_id) - { - if (gMenuItem.option_id != GOSSIP_OPTION_GOSSIP) - { - sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u but option_id is not GOSSIP_OPTION_GOSSIP, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id); - continue; - } - - if (sGossipScripts.find(gMenuItem.action_script_id) == sGossipScripts.end()) - { - sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u that does not exist in `gossip_scripts`, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id); - continue; - } - - gossipScriptSet.erase(gMenuItem.action_script_id); - } - - m_mGossipMenuItemsMap.insert(GossipMenuItemsMap::value_type(gMenuItem.menu_id, gMenuItem)); - - ++count; - - } - while (result->NextRow()); - - if (!gossipScriptSet.empty()) - { - for (std::set::const_iterator itr = gossipScriptSet.begin(); itr != gossipScriptSet.end(); ++itr) - sLog.outErrorDb("Table `gossip_scripts` contain unused script, id %u.", *itr); - } - - sLog.outString(); - sLog.outString(">> Loaded %u gossip_menu_option entries", count); -} - -void ObjectMgr::AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedcost, bool savetodb) -{ - VendorItemData& vList = m_mCacheVendorItemMap[entry]; - vList.AddItem(item,maxcount,incrtime,extendedcost); - - if (savetodb) WorldDatabase.PExecuteLog("INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')",entry, item, maxcount,incrtime,extendedcost); -} - -bool ObjectMgr::RemoveVendorItem(uint32 entry,uint32 item, bool savetodb) -{ - CacheVendorItemMap::iterator iter = m_mCacheVendorItemMap.find(entry); - if (iter == m_mCacheVendorItemMap.end()) - return false; - - if(!iter->second.RemoveItem(item)) - return false; - - if (savetodb) WorldDatabase.PExecuteLog("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",entry, item); - return true; -} - -bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* pl, std::set* skip_vendors, uint32 ORnpcflag) const -{ - CreatureInfo const* cInfo = GetCreatureTemplate(vendor_entry); - if (!cInfo) - { - if (pl) - ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION); - else - sLog.outErrorDb("Table `(game_event_)npc_vendor` have data for not existed creature template (Entry: %u), ignore", vendor_entry); - return false; - } - - if (!((cInfo->npcflag | ORnpcflag) & UNIT_NPC_FLAG_VENDOR)) - { - if (!skip_vendors || skip_vendors->count(vendor_entry) == 0) - { - if (pl) - ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION); - else - sLog.outErrorDb("Table `(game_event_)npc_vendor` have data for not creature template (Entry: %u) without vendor flag, ignore", vendor_entry); - - if (skip_vendors) - skip_vendors->insert(vendor_entry); - } - return false; - } - - if (!GetItemPrototype(item_id)) - { - if (pl) - ChatHandler(pl).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id); - else - sLog.outErrorDb("Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore",vendor_entry,item_id); - return false; - } - - if (ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost)) - { - if (pl) - ChatHandler(pl).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST,ExtendedCost); - else - sLog.outErrorDb("Table `(game_event_)npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore",item_id,ExtendedCost,vendor_entry); - return false; - } - - if (maxcount > 0 && incrtime == 0) - { - if (pl) - ChatHandler(pl).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount); - else - sLog.outErrorDb("Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", maxcount, item_id, vendor_entry); - return false; - } - else if (maxcount == 0 && incrtime > 0) - { - if (pl) - ChatHandler(pl).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0"); - else - sLog.outErrorDb("Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", item_id, vendor_entry); - return false; - } - - VendorItemData const* vItems = GetNpcVendorItemList(vendor_entry); - if (!vItems) - return true; // later checks for non-empty lists - - if(vItems->FindItemCostPair(item_id,ExtendedCost)) - { - if (pl) - ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost); - else - sLog.outErrorDb( "Table `npc_vendor` has duplicate items %u (with extended cost %u) for vendor (Entry: %u), ignoring", item_id, ExtendedCost, vendor_entry); - return false; - } - - if (vItems->GetItemCount() >= MAX_VENDOR_ITEMS) - { - if (pl) - ChatHandler(pl).SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS); - else - sLog.outErrorDb("Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignore", vItems->GetItemCount(), MAX_VENDOR_ITEMS, vendor_entry); - return false; - } - - return true; -} - -void ObjectMgr::LoadScriptNames() -{ - m_scriptNames.push_back(""); - QueryResult_AutoPtr result = WorldDatabase.Query( - "SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); - - if (!result) - { - barGoLink bar(1); - bar.step(); - sLog.outString(); - sLog.outErrorDb(">> Loaded empty set of Script Names!"); - return; - } - - barGoLink bar(result->GetRowCount()); - - //OnEvent Changes - m_scriptNames.push_back("scripted_on_events"); - uint32 count = 1; - - do - { - bar.step(); - m_scriptNames.push_back((*result)[0].GetString()); - ++count; - } while (result->NextRow()); - - std::sort(m_scriptNames.begin(), m_scriptNames.end()); - sLog.outString(); - sLog.outString(">> Loaded %d Script Names", count); -} - -uint32 ObjectMgr::GetScriptId(const char *name) -{ - // use binary search to find the script name in the sorted vector - // assume "" is the first element - if (!name) return 0; - ScriptNameMap::const_iterator itr = - std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name); - if (itr == m_scriptNames.end() || *itr != name) return 0; - return itr - m_scriptNames.begin(); -} - -void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set& ids) -{ - for (ScriptMapMap::const_iterator itrMM = scripts.begin(); itrMM != scripts.end(); ++itrMM) - { - for (ScriptMap::const_iterator itrM = itrMM->second.begin(); itrM != itrMM->second.end(); ++itrM) - { - switch(itrM->second.command) - { - case SCRIPT_COMMAND_TALK: - { - if (!GetTrinityStringLocale (itrM->second.dataint)) - sLog.outErrorDb("Table `db_script_string` not has string id %u used db script (ID: %u)", itrM->second.dataint, itrMM->first); - - if (ids.find(itrM->second.dataint) != ids.end()) - ids.erase(itrM->second.dataint); - } - } - } - } -} - -void ObjectMgr::LoadDbScriptStrings() -{ - LoadTrinityStrings(WorldDatabase,"db_script_string",MIN_DB_SCRIPT_STRING_ID,MAX_DB_SCRIPT_STRING_ID); - - std::set ids; - - for (int32 i = MIN_DB_SCRIPT_STRING_ID; i < MAX_DB_SCRIPT_STRING_ID; ++i) - if (GetTrinityStringLocale(i)) - ids.insert(i); - - CheckScripts(sQuestEndScripts,ids); - CheckScripts(sQuestStartScripts,ids); - CheckScripts(sSpellScripts,ids); - CheckScripts(sGameObjectScripts,ids); - CheckScripts(sEventScripts,ids); - - CheckScripts(sWaypointScripts,ids); - - for (std::set::const_iterator itr = ids.begin(); itr != ids.end(); ++itr) - sLog.outErrorDb("Table `db_script_string` has unused string id %u", *itr); -} - -// Functions for scripting access -uint32 GetAreaTriggerScriptId(uint32 trigger_id) -{ - return objmgr.GetAreaTriggerScriptId(trigger_id); -} - -bool LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value) -{ - // MAX_DB_SCRIPT_STRING_ID is max allowed negative value for scripts (scrpts can use only more deep negative values - // start/end reversed for negative values - if (start_value > MAX_DB_SCRIPT_STRING_ID || end_value >= start_value) - { - sLog.outErrorDb("Table '%s' load attempted with range (%d - %d) reserved by Trinity, strings not loaded.",table,start_value,end_value+1); - return false; - } - - return objmgr.LoadTrinityStrings(db,table,start_value,end_value); -} - -uint32 GetScriptId(const char *name) -{ - return objmgr.GetScriptId(name); -} - -ObjectMgr::ScriptNameMap & GetScriptNames() -{ - return objmgr.GetScriptNames(); -} - -GameObjectInfo const *GetGameObjectInfo(uint32 id) -{ - return objmgr.GetGameObjectInfo(id); -} - -CreatureInfo const *GetCreatureInfo(uint32 id) -{ - return objmgr.GetCreatureTemplate(id); -} - -void ObjectMgr::LoadTransportEvents() -{ - - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, waypoint_id, event_id FROM transport_events"); - - if (!result) - { - barGoLink bar1(1); - bar1.step(); - sLog.outString("\n>> Transport events table is empty \n"); - return; - } - - barGoLink bar1(result->GetRowCount()); - - do - { - bar1.step(); - - Field *fields = result->Fetch(); - - //Load event values - uint32 entry = fields[0].GetUInt32(); - uint32 waypoint_id = fields[1].GetUInt32(); - uint32 event_id = fields[2].GetUInt32(); - - uint32 event_count = (entry*100)+waypoint_id; - TransportEventMap[event_count] = event_id; - } - while (result->NextRow()); - - sLog.outString("\n>> Loaded %u transport events \n", result->GetRowCount()); -} - -CreatureInfo const* GetCreatureTemplateStore(uint32 entry) -{ - return sCreatureStorage.LookupEntry(entry); -} - -Quest const* GetQuestTemplateStore(uint32 entry) -{ - return objmgr.GetQuestTemplate(entry); -} - -uint64 ObjectMgr::GenerateGMTicketId() -{ - return ++m_GMticketid; -} - -void ObjectMgr::LoadGMTickets() -{ - if (!m_GMTicketList.empty()) - { - for (GmTicketList::const_iterator itr = m_GMTicketList.begin(); itr != m_GMTicketList.end(); ++itr) - delete *itr; - } - m_GMTicketList.clear(); - m_GMticketid = 0; - - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment FROM gm_tickets"); - - if (!result) - { - barGoLink bar(1); - bar.step(); - sLog.outString(); - sLog.outString(">> GM Tickets table is empty, no tickets were loaded."); - return; - } - - uint16 count = 0; - barGoLink bar ((*result).GetRowCount()); - GM_Ticket *ticket; - do - { - Field *fields = result->Fetch(); - ticket = new GM_Ticket; - ticket->guid = fields[0].GetUInt64(); - ticket->playerGuid = fields[1].GetUInt64(); - ticket->name = fields[2].GetCppString(); - ticket->message = fields[3].GetCppString(); - ticket->createtime = fields[4].GetUInt64(); - ticket->map = fields[5].GetUInt32(); - ticket->pos_x = fields[6].GetFloat(); - ticket->pos_y = fields[7].GetFloat(); - ticket->pos_z = fields[8].GetFloat(); - ticket->timestamp = fields[9].GetUInt64(); - ticket->closed = fields[10].GetUInt64(); - ticket->assignedToGM = fields[11].GetUInt64(); - ticket->comment = fields[12].GetCppString(); - ++count; - bar.step(); - - m_GMTicketList.push_back(ticket); - - } while (result->NextRow()); - - result = CharacterDatabase.Query("SELECT MAX(guid) from gm_tickets"); - - if (result) - { - Field *fields = result->Fetch(); - m_GMticketid = fields[0].GetUInt64(); - } - - sLog.outString(">> Loaded %u GM Tickets from the database.", count); -} - -void ObjectMgr::AddOrUpdateGMTicket(GM_Ticket &ticket, bool create) -{ - if (create) - m_GMTicketList.push_back(&ticket); - - _AddOrUpdateGMTicket(ticket); -} - -void ObjectMgr::_AddOrUpdateGMTicket(GM_Ticket &ticket) -{ - std::string msg(ticket.message), name(ticket.name), comment(ticket.comment); - CharacterDatabase.escape_string(msg); - CharacterDatabase.escape_string(name); - CharacterDatabase.escape_string(comment); - std::ostringstream ss; - ss << "REPLACE INTO gm_tickets (guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment) VALUES('"; - ss << ticket.guid << "', '"; - ss << ticket.playerGuid << "', '"; - ss << name << "', '"; - ss << msg << "', '" ; - ss << ticket.createtime << "', '"; - ss << ticket.map << "', '"; - ss << ticket.pos_x << "', '"; - ss << ticket.pos_y << "', '"; - ss << ticket.pos_z << "', '"; - ss << ticket.timestamp << "', '"; - ss << ticket.closed << "', '"; - ss << ticket.assignedToGM << "', '"; - ss << comment << "');"; - CharacterDatabase.BeginTransaction(); - CharacterDatabase.Execute(ss.str().c_str()); - CharacterDatabase.CommitTransaction(); -} - -void ObjectMgr::RemoveGMTicket(GM_Ticket *ticket, int64 source, bool permanently) -{ - for (GmTicketList::iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i) - if ((*i)->guid == ticket->guid) - { - if (permanently) - { - CharacterDatabase.PExecute("DELETE FROM gm_tickets WHERE guid = '%u'", ticket->guid); - i = m_GMTicketList.erase(i); - ticket = NULL; - return; - } - (*i)->closed = source; - _AddOrUpdateGMTicket(*(*i)); - } -} - -void ObjectMgr::RemoveGMTicket(uint64 ticketGuid, int64 source, bool permanently) -{ - GM_Ticket *ticket = GetGMTicket(ticketGuid); - assert(ticket); - RemoveGMTicket(ticket, source, permanently); -} - -CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unitClass) -{ - CreatureBaseStatsMap::const_iterator it = m_creatureBaseStatsMap.find(MAKE_PAIR16(level,unitClass)); - - if (it != m_creatureBaseStatsMap.end()) - return &(it->second); - - struct DefaultCreatureBaseStats : public CreatureBaseStats - { - DefaultCreatureBaseStats() - { - BaseArmor = 1; - for (uint8 j = 0; j < MAX_CREATURE_BASE_HP; ++j) - BaseHealth[j] = 1; - BaseMana = 0; - } - }; - static const DefaultCreatureBaseStats def_stats; - return &def_stats; -} - -void ObjectMgr::LoadCreatureClassLevelStats() -{ - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basemana, basearmor FROM creature_classlevelstats"); - - if (!result) - { - barGoLink bar(1); - bar.step(); - sLog.outString(); - sLog.outString(">> Loaded 0 creature base stats. DB table `creature_classlevelstats` is empty."); - return; - } - - barGoLink bar(result->GetRowCount()); - uint32 counter = 0; - - do - { - Field *fields = result->Fetch(); - - uint8 Level = fields[0].GetUInt32(); - uint8 Class = fields[1].GetUInt8(); - - CreatureBaseStats stats; - for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i) - stats.BaseHealth[i] = fields[i + 2].GetUInt32(); - stats.BaseMana = fields[5].GetUInt32(); - stats.BaseArmor = fields[6].GetUInt32(); - - if (Level > STRONG_MAX_LEVEL) - { - sLog.outErrorDb("Creature base stats for class %u has invalid level %u (max is %u) - set to %u", - Class, Level, STRONG_MAX_LEVEL, STRONG_MAX_LEVEL); - Level = STRONG_MAX_LEVEL; - } - - if (!Class || ((1 << (Class - 1)) & CLASSMASK_ALL_CREATURES) == 0) - sLog.outErrorDb("Creature base stats for level %u has invalid class %u", - Level, Class); - - for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i) - { - if (stats.BaseHealth[i] < 1) - { - sLog.outErrorDb("Creature base stats for class %u, level %u has invalid zero base HP[%u] - set to 1", - Class, Level, i); - stats.BaseHealth[i] = 1; - } - } - - m_creatureBaseStatsMap[MAKE_PAIR16(Level, Class)] = stats; - - bar.step(); - ++counter; - } - while (result->NextRow()); - - for (uint32 i = 0; i < sCreatureStorage.MaxEntry; ++i) - { - CreatureInfo const* info = sCreatureStorage.LookupEntry(i); - if (!info) - continue; - - for (uint16 lvl = info->minlevel; lvl <= info->maxlevel; ++lvl) - { - if (m_creatureBaseStatsMap.find(MAKE_PAIR16(lvl, info->unit_class)) == m_creatureBaseStatsMap.end()) - sLog.outErrorDb("Missing base stats for creature class %u level %u", info->unit_class, lvl); - } - } - - sLog.outString(); - sLog.outString(">> Loaded %u creature base stats.", counter); -} diff --git a/src/server/game/Entities/Object/ObjectMgr.h b/src/server/game/Entities/Object/ObjectMgr.h deleted file mode 100644 index 79b6ffdd0eb..00000000000 --- a/src/server/game/Entities/Object/ObjectMgr.h +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _OBJECTMGR_H -#define _OBJECTMGR_H - -#include "Log.h" -#include "Object.h" -#include "Bag.h" -#include "Creature.h" -#include "Player.h" -#include "DynamicObject.h" -#include "GameObject.h" -#include "Corpse.h" -#include "QuestDef.h" -#include "Path.h" -#include "ItemPrototype.h" -#include "NPCHandler.h" -#include "Database/DatabaseEnv.h" -#include "Mail.h" -#include "Map.h" -#include "ObjectAccessor.h" -#include "ObjectDefines.h" -#include "Policies/Singleton.h" -#include "Database/SQLStorage.h" -#include "Vehicle.h" -#include "ObjectMgr.h" -#include -#include -#include -#include "ConditionMgr.h" - -extern SQLStorage sCreatureStorage; -extern SQLStorage sCreatureDataAddonStorage; -extern SQLStorage sCreatureInfoAddonStorage; -extern SQLStorage sCreatureModelStorage; -extern SQLStorage sEquipmentStorage; -extern SQLStorage sGOStorage; -extern SQLStorage sPageTextStore; -extern SQLStorage sItemStorage; -extern SQLStorage sInstanceTemplate; - -class Group; -class Guild; -class ArenaTeam; -class Path; -class TransportPath; -class Item; - -struct GameTele -{ - float position_x; - float position_y; - float position_z; - float orientation; - uint32 mapId; - std::string name; - std::wstring wnameLow; -}; - -typedef UNORDERED_MAP GameTeleMap; - -struct ScriptInfo -{ - uint32 id; - uint32 delay; - uint32 command; - uint32 datalong; - uint32 datalong2; - int32 dataint; - float x; - float y; - float z; - float o; -}; - -typedef std::multimap ScriptMap; -typedef std::map ScriptMapMap; -extern ScriptMapMap sQuestEndScripts; -extern ScriptMapMap sQuestStartScripts; -extern ScriptMapMap sSpellScripts; -extern ScriptMapMap sGameObjectScripts; -extern ScriptMapMap sEventScripts; -extern ScriptMapMap sGossipScripts; -extern ScriptMapMap sWaypointScripts; - -struct SpellClickInfo -{ - uint32 spellId; - uint32 questStart; // quest start (quest must be active or rewarded for spell apply) - uint32 questEnd; // quest end (quest don't must be rewarded for spell apply) - bool questStartCanActive; // if true then quest start can be active (not only rewarded) - uint8 castFlags; - uint32 auraRequired; - uint32 auraForbidden; - SpellClickUserTypes userType; - - // helpers - bool IsFitToRequirements(Player const* player, Creature const * clickNpc) const; -}; - -typedef std::multimap SpellClickInfoMap; -typedef std::pair SpellClickInfoMapBounds; - -struct AreaTrigger -{ - uint32 access_id; - uint32 target_mapId; - float target_X; - float target_Y; - float target_Z; - float target_Orientation; -}; - -typedef std::set CellGuidSet; -typedef std::map CellCorpseSet; -struct CellObjectGuids -{ - CellGuidSet creatures; - CellGuidSet gameobjects; - CellCorpseSet corpses; -}; -typedef UNORDERED_MAP CellObjectGuidsMap; -typedef UNORDERED_MAP MapObjectGuids; - -typedef UNORDERED_MAP RespawnTimes; - -// Trinity string ranges -#define MIN_TRINITY_STRING_ID 1 // 'trinity_string' -#define MAX_TRINITY_STRING_ID 2000000000 -#define MIN_DB_SCRIPT_STRING_ID MAX_TRINITY_STRING_ID // 'db_script_string' -#define MAX_DB_SCRIPT_STRING_ID 2000010000 -#define MIN_CREATURE_AI_TEXT_STRING_ID (-1) // 'creature_ai_texts' -#define MAX_CREATURE_AI_TEXT_STRING_ID (-1000000) - -// Trinity Trainer Reference start range -#define TRINITY_TRAINER_START_REF 200000 - -struct TrinityStringLocale -{ - std::vector Content; // 0 -> default, i -> i-1 locale index -}; - -typedef std::map CreatureLinkedRespawnMap; -typedef UNORDERED_MAP CreatureDataMap; -typedef UNORDERED_MAP GameObjectDataMap; -typedef UNORDERED_MAP CreatureLocaleMap; -typedef UNORDERED_MAP GameObjectLocaleMap; -typedef UNORDERED_MAP ItemLocaleMap; -typedef UNORDERED_MAP QuestLocaleMap; -typedef UNORDERED_MAP NpcTextLocaleMap; -typedef UNORDERED_MAP PageTextLocaleMap; -typedef UNORDERED_MAP TrinityStringLocaleMap; -typedef UNORDERED_MAP GossipMenuItemsLocaleMap; -typedef UNORDERED_MAP PointOfInterestLocaleMap; - -typedef std::multimap QuestRelations; -typedef std::multimap ItemRequiredTargetMap; -typedef std::pair ItemRequiredTargetMapBounds; - -struct PetLevelInfo -{ - PetLevelInfo() : health(0), mana(0) { for (uint8 i=0; i < MAX_STATS; ++i) stats[i] = 0; } - - uint16 stats[MAX_STATS]; - uint16 health; - uint16 mana; - uint16 armor; -}; - -struct MailLevelReward -{ - MailLevelReward() : raceMask(0), mailTemplateId(0), senderEntry(0) {} - MailLevelReward(uint32 _raceMask, uint32 _mailTemplateId, uint32 _senderEntry) : raceMask(_raceMask), mailTemplateId(_mailTemplateId), senderEntry(_senderEntry) {} - - uint32 raceMask; - uint32 mailTemplateId; - uint32 senderEntry; -}; - -typedef std::list MailLevelRewardList; -typedef UNORDERED_MAP MailLevelRewardMap; - -struct ReputationOnKillEntry -{ - uint32 repfaction1; - uint32 repfaction2; - bool is_teamaward1; - uint32 reputation_max_cap1; - int32 repvalue1; - bool is_teamaward2; - uint32 reputation_max_cap2; - int32 repvalue2; - bool team_dependent; -}; - -struct PointOfInterest -{ - uint32 entry; - float x; - float y; - uint32 icon; - uint32 flags; - uint32 data; - std::string icon_name; -}; - -struct GossipMenuItems -{ - uint32 menu_id; - uint32 id; - uint8 option_icon; - std::string option_text; - uint32 option_id; - uint32 npc_option_npcflag; - uint32 action_menu_id; - uint32 action_poi_id; - uint32 action_script_id; - bool box_coded; - uint32 box_money; - std::string box_text; - ConditionList conditions; -}; - -struct GossipMenus -{ - uint32 entry; - uint32 text_id; - ConditionList conditions; -}; - -typedef std::multimap GossipMenusMap; -typedef std::pair GossipMenusMapBounds; -typedef std::pair GossipMenusMapBoundsNonConst; -typedef std::multimap GossipMenuItemsMap; -typedef std::pair GossipMenuItemsMapBounds; -typedef std::pair GossipMenuItemsMapBoundsNonConst; - -struct QuestPOIPoint -{ - int32 x; - int32 y; - - QuestPOIPoint() : x(0), y(0) {} - QuestPOIPoint(int32 _x, int32 _y) : x(_x), y(_y) {} -}; - -struct QuestPOI -{ - uint32 Id; - int32 ObjectiveIndex; - uint32 MapId; - uint32 AreaId; - uint32 Unk2; - uint32 Unk3; - uint32 Unk4; - std::vector points; - - QuestPOI() : Id(0), ObjectiveIndex(0), MapId(0), AreaId(0), Unk2(0), Unk3(0), Unk4(0) {} - QuestPOI(uint32 id, int32 objIndex, uint32 mapId, uint32 areaId, uint32 unk2, uint32 unk3, uint32 unk4) : Id(id), ObjectiveIndex(objIndex), MapId(mapId), AreaId(areaId), Unk2(unk2), Unk3(unk3), Unk4(unk4) {} -}; - -typedef std::vector QuestPOIVector; -typedef UNORDERED_MAP QuestPOIMap; - -#define WEATHER_SEASONS 4 -struct WeatherSeasonChances -{ - uint32 rainChance; - uint32 snowChance; - uint32 stormChance; -}; - -struct WeatherZoneChances -{ - WeatherSeasonChances data[WEATHER_SEASONS]; -}; - -struct GraveYardData -{ - uint32 safeLocId; - uint32 team; -}; -typedef std::multimap GraveYardMap; - -// NPC gossip text id -typedef UNORDERED_MAP CacheNpcTextIdMap; - -typedef UNORDERED_MAP CacheVendorItemMap; -typedef UNORDERED_MAP CacheTrainerSpellMap; - -enum SkillRangeType -{ - SKILL_RANGE_LANGUAGE, // 300..300 - SKILL_RANGE_LEVEL, // 1..max skill for level - SKILL_RANGE_MONO, // 1..1, grey monolite bar - SKILL_RANGE_RANK, // 1..skill for known rank - SKILL_RANGE_NONE, // 0..0 always -}; - -struct GM_Ticket -{ - uint64 guid; - uint64 playerGuid; - std::string name; - float pos_x; - float pos_y; - float pos_z; - uint32 map; - std::string message; - uint64 createtime; - uint64 timestamp; - int64 closed; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket, other = GM who closed it. - uint64 assignedToGM; - std::string comment; -}; -typedef std::list GmTicketList; -SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial); - -#define MAX_PLAYER_NAME 12 // max allowed by client name length -#define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length (> MAX_PLAYER_NAME for support declined names) -#define MAX_PET_NAME 12 // max allowed by client name length -#define MAX_CHARTER_NAME 24 // max allowed by client name length - -bool normalizePlayerName(std::string& name); - -struct LanguageDesc -{ - Language lang_id; - uint32 spell_id; - uint32 skill_id; -}; - -extern LanguageDesc lang_description[LANGUAGES_COUNT]; - LanguageDesc const* GetLanguageDescByID(uint32 lang); - -class PlayerDumpReader; - -class ObjectMgr -{ - friend class PlayerDumpReader; - - public: - ObjectMgr(); - ~ObjectMgr(); - - typedef UNORDERED_MAP ItemMap; - - typedef std::set< Group * > GroupSet; - - typedef UNORDERED_MAP GuildMap; - - typedef UNORDERED_MAP ArenaTeamMap; - - typedef UNORDERED_MAP QuestMap; - - typedef UNORDERED_MAP AreaTriggerMap; - - typedef UNORDERED_MAP AreaTriggerScriptMap; - - typedef UNORDERED_MAP AccessRequirementMap; - - typedef UNORDERED_MAP RepOnKillMap; - typedef UNORDERED_MAP PointOfInterestMap; - - typedef UNORDERED_MAP WeatherZoneMap; - - typedef std::vector ScriptNameMap; - - UNORDERED_MAP TransportEventMap; - - Player* GetPlayer(const char* name) const { return ObjectAccessor::Instance().FindPlayerByName(name);} - Player* GetPlayer(uint64 guid) const { return ObjectAccessor::FindPlayer(guid); } - - static GameObjectInfo const *GetGameObjectInfo(uint32 id) { return sGOStorage.LookupEntry(id); } - int LoadReferenceVendor(int32 vendor, int32 item_id, std::set *skip_vendors); - - void LoadGameobjectInfo(); - void AddGameobjectInfo(GameObjectInfo *goinfo); - - Group * GetGroupByGUID(const uint64 &guid) const; - void AddGroup(Group* group) { mGroupSet.insert(group); } - void RemoveGroup(Group* group) { mGroupSet.erase(group); } - - Guild* GetGuildByLeader(uint64 const&guid) const; - Guild* GetGuildById(uint32 GuildId) const; - Guild* GetGuildByName(const std::string& guildname) const; - std::string GetGuildNameById(uint32 GuildId) const; - void AddGuild(Guild* guild); - void RemoveGuild(uint32 Id); - - ArenaTeam* GetArenaTeamById(uint32 arenateamid) const; - ArenaTeam* GetArenaTeamByName(const std::string& arenateamname) const; - ArenaTeam* GetArenaTeamByCaptain(uint64 const& guid) const; - void AddArenaTeam(ArenaTeam* arenaTeam); - void RemoveArenaTeam(uint32 Id); - ArenaTeamMap::iterator GetArenaTeamMapBegin() { return mArenaTeamMap.begin(); } - ArenaTeamMap::iterator GetArenaTeamMapEnd() { return mArenaTeamMap.end(); } - - static CreatureInfo const *GetCreatureTemplate(uint32 id); - CreatureModelInfo const *GetCreatureModelInfo(uint32 modelid); - CreatureModelInfo const* GetCreatureModelRandomGender(uint32 display_id); - uint32 ChooseDisplayId(uint32 team, const CreatureInfo *cinfo, const CreatureData *data = NULL); - EquipmentInfo const *GetEquipmentInfo(uint32 entry); - static CreatureDataAddon const *GetCreatureAddon(uint32 lowguid) - { - return sCreatureDataAddonStorage.LookupEntry(lowguid); - } - - static CreatureDataAddon const *GetCreatureTemplateAddon(uint32 entry) - { - return sCreatureInfoAddonStorage.LookupEntry(entry); - } - - static ItemPrototype const* GetItemPrototype(uint32 id) { return sItemStorage.LookupEntry(id); } - - static InstanceTemplate const* GetInstanceTemplate(uint32 map) - { - return sInstanceTemplate.LookupEntry(map); - } - - PetLevelInfo const* GetPetLevelInfo(uint32 creature_id, uint8 level) const; - - PlayerClassInfo const* GetPlayerClassInfo(uint32 class_) const - { - if (class_ >= MAX_CLASSES) return NULL; - return &playerClassInfo[class_]; - } - void GetPlayerClassLevelInfo(uint32 class_,uint8 level, PlayerClassLevelInfo* info) const; - - PlayerInfo const* GetPlayerInfo(uint32 race, uint32 class_) const - { - if (race >= MAX_RACES) return NULL; - if (class_ >= MAX_CLASSES) return NULL; - PlayerInfo const* info = &playerInfo[race][class_]; - if (info->displayId_m == 0 || info->displayId_f == 0) return NULL; - return info; - } - void GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const; - - uint64 GetPlayerGUIDByName(std::string name) const; - bool GetPlayerNameByGUID(const uint64 &guid, std::string &name) const; - uint32 GetPlayerTeamByGUID(const uint64 &guid) const; - uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const; - uint32 GetPlayerAccountIdByPlayerName(const std::string& name) const; - - uint32 GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team); - void GetTaxiPath(uint32 source, uint32 destination, uint32 &path, uint32 &cost); - uint32 GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt_team = false); - void GetTaxiPathNodes(uint32 path, Path &pathnodes, std::vector& mapIds); - void GetTransportPathNodes(uint32 path, TransportPath &pathnodes); - - Quest const* GetQuestTemplate(uint32 quest_id) const - { - QuestMap::const_iterator itr = mQuestTemplates.find(quest_id); - return itr != mQuestTemplates.end() ? itr->second : NULL; - } - QuestMap const& GetQuestTemplates() const { return mQuestTemplates; } - - uint32 GetQuestForAreaTrigger(uint32 Trigger_ID) const - { - QuestAreaTriggerMap::const_iterator itr = mQuestAreaTriggerMap.find(Trigger_ID); - if (itr != mQuestAreaTriggerMap.end()) - return itr->second; - return 0; - } - bool IsTavernAreaTrigger(uint32 Trigger_ID) const - { - return mTavernAreaTriggerSet.find(Trigger_ID) != mTavernAreaTriggerSet.end(); - } - - bool IsGameObjectForQuests(uint32 entry) const - { - return mGameObjectForQuestSet.find(entry) != mGameObjectForQuestSet.end(); - } - - GossipText const* GetGossipText(uint32 Text_ID) const; - - WorldSafeLocsEntry const *GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team); - bool AddGraveYardLink(uint32 id, uint32 zone, uint32 team, bool inDB = true); - void RemoveGraveYardLink(uint32 id, uint32 zone, uint32 team, bool inDB = false); - void LoadGraveyardZones(); - GraveYardData const* FindGraveYardData(uint32 id, uint32 zone); - - AreaTrigger const* GetAreaTrigger(uint32 trigger) const - { - AreaTriggerMap::const_iterator itr = mAreaTriggers.find(trigger); - if (itr != mAreaTriggers.end()) - return &itr->second; - return NULL; - } - - AccessRequirement const* GetAccessRequirement(uint32 requirement) const - { - AccessRequirementMap::const_iterator itr = mAccessRequirements.find(requirement); - if (itr != mAccessRequirements.end()) - return &itr->second; - return NULL; - } - - AreaTrigger const* GetGoBackTrigger(uint32 Map) const; - AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const; - - uint32 GetAreaTriggerScriptId(uint32 trigger_id); - - ReputationOnKillEntry const* GetReputationOnKilEntry(uint32 id) const - { - RepOnKillMap::const_iterator itr = mRepOnKill.find(id); - if (itr != mRepOnKill.end()) - return &itr->second; - return NULL; - } - - PointOfInterest const* GetPointOfInterest(uint32 id) const - { - PointOfInterestMap::const_iterator itr = mPointsOfInterest.find(id); - if (itr != mPointsOfInterest.end()) - return &itr->second; - return NULL; - } - - QuestPOIVector const* GetQuestPOIVector(uint32 questId) - { - QuestPOIMap::const_iterator itr = mQuestPOIMap.find(questId); - if (itr != mQuestPOIMap.end()) - return &itr->second; - return NULL; - } - - VehicleAccessoryList const* GetVehicleAccessoryList(uint32 uiEntry) const - { - VehicleAccessoryMap::const_iterator itr = m_VehicleAccessoryMap.find(uiEntry); - if (itr != m_VehicleAccessoryMap.end()) - return &itr->second; - return NULL; - } - - void LoadGuilds(); - void LoadArenaTeams(); - void LoadGroups(); - void LoadQuests(); - void LoadQuestRelations() - { - sLog.outString("Loading GO Start Quest Data..."); - LoadGameobjectQuestRelations(); - sLog.outString("Loading GO End Quest Data..."); - LoadGameobjectInvolvedRelations(); - sLog.outString("Loading Creature Start Quest Data..."); - LoadCreatureQuestRelations(); - sLog.outString("Loading Creature End Quest Data..."); - LoadCreatureInvolvedRelations(); - } - void LoadGameobjectQuestRelations(); - void LoadGameobjectInvolvedRelations(); - void LoadCreatureQuestRelations(); - void LoadCreatureInvolvedRelations(); - - QuestRelations mGOQuestRelations; - QuestRelations mGOQuestInvolvedRelations; - QuestRelations mCreatureQuestRelations; - QuestRelations mCreatureQuestInvolvedRelations; - - void LoadGameObjectScripts(); - void LoadQuestEndScripts(); - void LoadQuestStartScripts(); - void LoadEventScripts(); - void LoadSpellScripts(); - void LoadGossipScripts(); - void LoadWaypointScripts(); - - void LoadTransportEvents(); - - bool LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value); - bool LoadTrinityStrings() { return LoadTrinityStrings(WorldDatabase,"trinity_string",MIN_TRINITY_STRING_ID,MAX_TRINITY_STRING_ID); } - void LoadDbScriptStrings(); - void LoadCreatureClassLevelStats(); - void LoadCreatureLocales(); - void LoadCreatureTemplates(); - void CheckCreatureTemplate(CreatureInfo const* cInfo); - void LoadCreatures(); - void LoadCreatureLinkedRespawn(); - bool CheckCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) const; - bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid); - void LoadCreatureRespawnTimes(); - void LoadCreatureAddons(); - void LoadCreatureModelInfo(); - void LoadEquipmentTemplates(); - void LoadGameObjectLocales(); - void LoadGameobjects(); - void LoadGameobjectRespawnTimes(); - void LoadItemPrototypes(); - void LoadItemLocales(); - void LoadQuestLocales(); - void LoadNpcTextLocales(); - void LoadPageTextLocales(); - void LoadGossipMenuItemsLocales(); - void LoadPointOfInterestLocales(); - void LoadInstanceTemplate(); - void LoadMailLevelRewards(); - void LoadVehicleAccessories(); - - void LoadGossipText(); - - void LoadAreaTriggerTeleports(); - void LoadAccessRequirements(); - void LoadQuestAreaTriggers(); - void LoadAreaTriggerScripts(); - void LoadTavernAreaTriggers(); - void LoadGameObjectForQuests(); - - void LoadPageTexts(); - - void LoadPlayerInfo(); - void LoadPetLevelInfo(); - void LoadExplorationBaseXP(); - void LoadPetNames(); - void LoadPetNumber(); - void LoadCorpses(); - void LoadFishingBaseSkillLevel(); - - void LoadReputationOnKill(); - void LoadPointsOfInterest(); - void LoadQuestPOI(); - - void LoadNPCSpellClickSpells(); - - void LoadWeatherZoneChances(); - void LoadGameTele(); - - void LoadNpcTextId(); - - void LoadGossipMenu(); - void LoadGossipMenuItems(); - - void LoadVendors(); - void LoadTrainerSpell(); - bool AddSpellToTrainer(uint32 entry, uint32 spell, Field *fields, std::set *skip_trainers, std::set *talentIds); - int LoadReferenceTrainer(uint32 trainer, int32 spell, std::set *skip_trainers, std::set *talentIds); - void LoadGMTickets(); - - std::string GeneratePetName(uint32 entry); - uint32 GetBaseXP(uint8 level); - uint32 GetXPForLevel(uint8 level); - - int32 GetFishingBaseSkillLevel(uint32 entry) const - { - FishingBaseSkillMap::const_iterator itr = mFishingBaseForArea.find(entry); - return itr != mFishingBaseForArea.end() ? itr->second : 0; - } - - void ReturnOrDeleteOldMails(bool serverUp); - - CreatureBaseStats const* GetCreatureBaseStats(uint8 level, uint8 unitClass); - - void SetHighestGuids(); - uint32 GenerateLowGuid(HighGuid guidhigh); - uint32 GenerateArenaTeamId(); - uint32 GenerateAuctionID(); - uint64 GenerateEquipmentSetGuid(); - uint32 GenerateGuildId(); - uint32 GenerateMailID(); - uint32 GeneratePetNumber(); - - typedef std::multimap ExclusiveQuestGroups; - ExclusiveQuestGroups mExclusiveQuestGroups; - - MailLevelReward const* GetMailLevelReward(uint32 level,uint32 raceMask) - { - MailLevelRewardMap::const_iterator map_itr = m_mailLevelRewardMap.find(level); - if (map_itr == m_mailLevelRewardMap.end()) - return NULL; - - for (MailLevelRewardList::const_iterator set_itr = map_itr->second.begin(); set_itr != map_itr->second.end(); ++set_itr) - if (set_itr->raceMask & raceMask) - return &*set_itr; - - return NULL; - } - - WeatherZoneChances const* GetWeatherChances(uint32 zone_id) const - { - WeatherZoneMap::const_iterator itr = mWeatherZoneMap.find(zone_id); - if (itr != mWeatherZoneMap.end()) - return &itr->second; - else - return NULL; - } - - CellObjectGuids const& GetCellObjectGuids(uint16 mapid, uint8 spawnMode, uint32 cell_id) - { - return mMapObjectGuids[MAKE_PAIR32(mapid,spawnMode)][cell_id]; - } - - CreatureData const* GetCreatureData(uint32 guid) const - { - CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid); - if (itr == mCreatureDataMap.end()) return NULL; - return &itr->second; - } - CreatureData& NewOrExistCreatureData(uint32 guid) { return mCreatureDataMap[guid]; } - void DeleteCreatureData(uint32 guid); - uint32 GetLinkedRespawnGuid(uint32 guid) const - { - CreatureLinkedRespawnMap::const_iterator itr = mCreatureLinkedRespawnMap.find(guid); - if (itr == mCreatureLinkedRespawnMap.end()) return 0; - return itr->second; - } - CreatureLocale const* GetCreatureLocale(uint32 entry) const - { - CreatureLocaleMap::const_iterator itr = mCreatureLocaleMap.find(entry); - if (itr == mCreatureLocaleMap.end()) return NULL; - return &itr->second; - } - GameObjectLocale const* GetGameObjectLocale(uint32 entry) const - { - GameObjectLocaleMap::const_iterator itr = mGameObjectLocaleMap.find(entry); - if (itr == mGameObjectLocaleMap.end()) return NULL; - return &itr->second; - } - ItemLocale const* GetItemLocale(uint32 entry) const - { - ItemLocaleMap::const_iterator itr = mItemLocaleMap.find(entry); - if (itr == mItemLocaleMap.end()) return NULL; - return &itr->second; - } - QuestLocale const* GetQuestLocale(uint32 entry) const - { - QuestLocaleMap::const_iterator itr = mQuestLocaleMap.find(entry); - if (itr == mQuestLocaleMap.end()) return NULL; - return &itr->second; - } - NpcTextLocale const* GetNpcTextLocale(uint32 entry) const - { - NpcTextLocaleMap::const_iterator itr = mNpcTextLocaleMap.find(entry); - if (itr == mNpcTextLocaleMap.end()) return NULL; - return &itr->second; - } - PageTextLocale const* GetPageTextLocale(uint32 entry) const - { - PageTextLocaleMap::const_iterator itr = mPageTextLocaleMap.find(entry); - if (itr == mPageTextLocaleMap.end()) return NULL; - return &itr->second; - } - GossipMenuItemsLocale const* GetGossipMenuItemsLocale(uint32 entry) const - { - GossipMenuItemsLocaleMap::const_iterator itr = mGossipMenuItemsLocaleMap.find(entry); - if (itr == mGossipMenuItemsLocaleMap.end()) return NULL; - return &itr->second; - } - PointOfInterestLocale const* GetPointOfInterestLocale(uint32 poi_id) const - { - PointOfInterestLocaleMap::const_iterator itr = mPointOfInterestLocaleMap.find(poi_id); - if (itr == mPointOfInterestLocaleMap.end()) return NULL; - return &itr->second; - } - - bool IsGoOfSpecificEntrySpawned(uint32 entry) const - { - for (GameObjectDataMap::const_iterator it = mGameObjectDataMap.begin(); it != mGameObjectDataMap.end(); ++it) - if (it->second.id == entry) - return true; - - return false; - } - - GameObjectData const* GetGOData(uint32 guid) const - { - GameObjectDataMap::const_iterator itr = mGameObjectDataMap.find(guid); - if (itr == mGameObjectDataMap.end()) return NULL; - return &itr->second; - } - GameObjectData& NewGOData(uint32 guid) { return mGameObjectDataMap[guid]; } - void DeleteGOData(uint32 guid); - - TrinityStringLocale const* GetTrinityStringLocale(int32 entry) const - { - TrinityStringLocaleMap::const_iterator itr = mTrinityStringLocaleMap.find(entry); - if (itr == mTrinityStringLocaleMap.end()) return NULL; - return &itr->second; - } - const char *GetTrinityString(int32 entry, int locale_idx) const; - const char *GetTrinityStringForDBCLocale(int32 entry) const { return GetTrinityString(entry,DBCLocaleIndex); } - int32 GetDBCLocaleIndex() const { return DBCLocaleIndex; } - void SetDBCLocaleIndex(uint32 lang) { DBCLocaleIndex = GetIndexForLocale(LocaleConstant(lang)); } - - void AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance); - void DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid); - - time_t GetCreatureRespawnTime(uint32 loguid, uint32 instance) { return mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)]; } - void SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t); - time_t GetGORespawnTime(uint32 loguid, uint32 instance) { return mGORespawnTimes[MAKE_PAIR64(loguid,instance)]; } - void SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t); - void DeleteRespawnTimeForInstance(uint32 instance); - - // grid objects - void AddCreatureToGrid(uint32 guid, CreatureData const* data); - void RemoveCreatureFromGrid(uint32 guid, CreatureData const* data); - void AddGameobjectToGrid(uint32 guid, GameObjectData const* data); - void RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data); - uint32 AddGOData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0, float rotation0 = 0, float rotation1 = 0, float rotation2 = 0, float rotation3 = 0); - uint32 AddCreData(uint32 entry, uint32 team, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0); - bool MoveCreData(uint32 guid, uint32 map, Position pos); - - // reserved names - void LoadReservedPlayersNames(); - bool IsReservedName(const std::string& name) const; - - // name with valid structure and symbols - static uint8 CheckPlayerName(const std::string& name, bool create = false); - static PetNameInvalidReason CheckPetName(const std::string& name); - static bool IsValidCharterName(const std::string& name); - - static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names); - - void LoadSpellDisabledEntrys(); - bool IsPlayerSpellDisabled(uint32 spellid) { return (m_DisabledPlayerSpells.count(spellid) != 0); } - bool IsCreatureSpellDisabled(uint32 spellid) { return (m_DisabledCreatureSpells.count(spellid) != 0); } - bool IsPetSpellDisabled(uint32 spellid) { return (m_DisabledPetSpells.count(spellid) != 0); } - - int GetIndexForLocale(LocaleConstant loc); - LocaleConstant GetLocaleForIndex(int i); - - GameTele const* GetGameTele(uint32 id) const - { - GameTeleMap::const_iterator itr = m_GameTeleMap.find(id); - if (itr == m_GameTeleMap.end()) return NULL; - return &itr->second; - } - GameTele const* GetGameTele(const std::string& name) const; - GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; } - bool AddGameTele(GameTele& data); - bool DeleteGameTele(const std::string& name); - - uint32 GetNpcGossip(uint32 entry) const - { - CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry); - if (iter == m_mCacheNpcTextIdMap.end()) - return 0; - - return iter->second; - } - - TrainerSpellData const* GetNpcTrainerSpells(uint32 entry) const - { - CacheTrainerSpellMap::const_iterator iter = m_mCacheTrainerSpellMap.find(entry); - if (iter == m_mCacheTrainerSpellMap.end()) - return NULL; - - return &iter->second; - } - - VendorItemData const* GetNpcVendorItemList(uint32 entry) const - { - CacheVendorItemMap::const_iterator iter = m_mCacheVendorItemMap.find(entry); - if (iter == m_mCacheVendorItemMap.end()) - return NULL; - - return &iter->second; - } - void AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, bool savetodb = true); // for event - bool RemoveVendorItem(uint32 entry,uint32 item, bool savetodb = true); // for event - bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set* skip_vendors = NULL, uint32 ORnpcflag = 0) const; - - void LoadScriptNames(); - ScriptNameMap &GetScriptNames() { return m_scriptNames; } - const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; } - uint32 GetScriptId(const char *name); - - int GetOrNewIndexForLocale(LocaleConstant loc); - - SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const - { - return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id),mSpellClickInfoMap.upper_bound(creature_id)); - } - - GM_Ticket *GetGMTicket(uint64 ticketGuid) - { - for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i) - if ((*i) && (*i)->guid == ticketGuid) - return (*i); - - return NULL; - } - GM_Ticket *GetGMTicketByPlayer(uint64 playerGuid) - { - for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i) - if ((*i) && (*i)->playerGuid == playerGuid && (*i)->closed == 0) - return (*i); - - return NULL; - } - - GossipMenusMapBounds GetGossipMenusMapBounds(uint32 uiMenuId) const - { - return GossipMenusMapBounds(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId)); - } - - GossipMenusMapBoundsNonConst GetGossipMenusMapBoundsNonConst(uint32 uiMenuId) - { - return GossipMenusMapBoundsNonConst(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId)); - } - - GossipMenuItemsMapBounds GetGossipMenuItemsMapBounds(uint32 uiMenuId) const - { - return GossipMenuItemsMapBounds(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId)); - } - GossipMenuItemsMapBoundsNonConst GetGossipMenuItemsMapBoundsNonConst(uint32 uiMenuId) - { - return GossipMenuItemsMapBoundsNonConst(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId)); - } - - void AddOrUpdateGMTicket(GM_Ticket &ticket, bool create = false); - void _AddOrUpdateGMTicket(GM_Ticket &ticket); - void RemoveGMTicket(uint64 ticketGuid, int64 source = -1, bool permanently = false); - void RemoveGMTicket(GM_Ticket *ticket, int64 source = -1, bool permanently = false); - GmTicketList m_GMTicketList; - uint64 GenerateGMTicketId(); - - // for wintergrasp only - GraveYardMap mGraveYardMap; - protected: - - // first free id for selected id type - uint32 m_arenaTeamId; - uint32 m_auctionid; - uint64 m_equipmentSetGuid; - uint32 m_guildId; - uint32 m_ItemTextId; - uint32 m_mailid; - uint32 m_hiPetNumber; - uint64 m_GMticketid; - - // first free low guid for seelcted guid type - uint32 m_hiCharGuid; - uint32 m_hiCreatureGuid; - uint32 m_hiPetGuid; - uint32 m_hiVehicleGuid; - uint32 m_hiItemGuid; - uint32 m_hiGoGuid; - uint32 m_hiDoGuid; - uint32 m_hiCorpseGuid; - uint32 m_hiGroupGuid; - - QuestMap mQuestTemplates; - - typedef UNORDERED_MAP GossipTextMap; - typedef UNORDERED_MAP QuestAreaTriggerMap; - typedef std::set TavernAreaTriggerSet; - typedef std::set GameObjectForQuestSet; - - GroupSet mGroupSet; - GuildMap mGuildMap; - ArenaTeamMap mArenaTeamMap; - - QuestAreaTriggerMap mQuestAreaTriggerMap; - TavernAreaTriggerSet mTavernAreaTriggerSet; - GameObjectForQuestSet mGameObjectForQuestSet; - GossipTextMap mGossipText; - AreaTriggerMap mAreaTriggers; - AreaTriggerScriptMap mAreaTriggerScripts; - AccessRequirementMap mAccessRequirements; - - RepOnKillMap mRepOnKill; - - GossipMenusMap m_mGossipMenusMap; - GossipMenuItemsMap m_mGossipMenuItemsMap; - PointOfInterestMap mPointsOfInterest; - - QuestPOIMap mQuestPOIMap; - - WeatherZoneMap mWeatherZoneMap; - - //character reserved names - typedef std::set ReservedNamesMap; - ReservedNamesMap m_ReservedNames; - - std::set m_DisabledPlayerSpells; - std::set m_DisabledCreatureSpells; - std::set m_DisabledPetSpells; - -// GraveYardMap mGraveYardMap; - - GameTeleMap m_GameTeleMap; - - ScriptNameMap m_scriptNames; - - SpellClickInfoMap mSpellClickInfoMap; - - ItemRequiredTargetMap m_ItemRequiredTarget; - - VehicleAccessoryMap m_VehicleAccessoryMap; - - typedef std::vector LocalForIndex; - LocalForIndex m_LocalForIndex; - - int DBCLocaleIndex; - - private: - void LoadScripts(ScriptMapMap& scripts, char const* tablename); - void CheckScripts(ScriptMapMap const& scripts,std::set& ids); - void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment); - void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); - void LoadQuestRelationsHelper(QuestRelations& map,char const* table); - - MailLevelRewardMap m_mailLevelRewardMap; - - CreatureBaseStatsMap m_creatureBaseStatsMap; - - typedef std::map PetLevelInfoMap; - // PetLevelInfoMap[creature_id][level] - PetLevelInfoMap petInfo; // [creature_id][level] - - PlayerClassInfo playerClassInfo[MAX_CLASSES]; - - void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const; - PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES]; - - typedef std::vector PlayerXPperLevel; // [level] - PlayerXPperLevel mPlayerXPperLevel; - - typedef std::map BaseXPMap; // [area level][base xp] - BaseXPMap mBaseXPTable; - - typedef std::map FishingBaseSkillMap; // [areaId][base skill level] - FishingBaseSkillMap mFishingBaseForArea; - - typedef std::map > HalfNameMap; - HalfNameMap PetHalfName0; - HalfNameMap PetHalfName1; - - MapObjectGuids mMapObjectGuids; - CreatureDataMap mCreatureDataMap; - CreatureLinkedRespawnMap mCreatureLinkedRespawnMap; - CreatureLocaleMap mCreatureLocaleMap; - GameObjectDataMap mGameObjectDataMap; - GameObjectLocaleMap mGameObjectLocaleMap; - ItemLocaleMap mItemLocaleMap; - QuestLocaleMap mQuestLocaleMap; - NpcTextLocaleMap mNpcTextLocaleMap; - PageTextLocaleMap mPageTextLocaleMap; - TrinityStringLocaleMap mTrinityStringLocaleMap; - GossipMenuItemsLocaleMap mGossipMenuItemsLocaleMap; - PointOfInterestLocaleMap mPointOfInterestLocaleMap; - RespawnTimes mCreatureRespawnTimes; - RespawnTimes mGORespawnTimes; - - CacheNpcTextIdMap m_mCacheNpcTextIdMap; - CacheVendorItemMap m_mCacheVendorItemMap; - CacheTrainerSpellMap m_mCacheTrainerSpellMap; - - std::set difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate - std::set hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate - -}; - -#define objmgr Trinity::Singleton::Instance() - -// scripting access functions - bool LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value = MAX_CREATURE_AI_TEXT_STRING_ID, int32 end_value = std::numeric_limits::min()); - uint32 GetAreaTriggerScriptId(uint32 trigger_id); - uint32 GetScriptId(const char *name); - ObjectMgr::ScriptNameMap& GetScriptNames(); - GameObjectInfo const *GetGameObjectInfo(uint32 id); - CreatureInfo const *GetCreatureInfo(uint32 id); - CreatureInfo const* GetCreatureTemplateStore(uint32 entry); - Quest const* GetQuestTemplateStore(uint32 entry); - -#endif diff --git a/src/server/game/Entities/Object/ObjectPosSelector.cpp b/src/server/game/Entities/Object/ObjectPosSelector.cpp new file mode 100644 index 00000000000..899dfec3fdb --- /dev/null +++ b/src/server/game/Entities/Object/ObjectPosSelector.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectPosSelector.h" + +ObjectPosSelector::ObjectPosSelector(float x,float y,float size,float dist) +: m_center_x(x),m_center_y(y),m_size(size),m_dist(dist) +{ + m_anglestep = acos(m_dist/(m_dist+2*m_size)); + + m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].end(); + m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].end(); + + m_smallStepAngle[USED_POS_PLUS] = 0; + m_smallStepAngle[USED_POS_MINUS] = 0; + + m_smallStepOk[USED_POS_PLUS] = false; + m_smallStepOk[USED_POS_MINUS] = false; + + m_smallStepNextUsedPos[USED_POS_PLUS] = NULL; + m_smallStepNextUsedPos[USED_POS_MINUS] = NULL; +} + +ObjectPosSelector::UsedPosList::value_type const* ObjectPosSelector::nextUsedPos(UsedPosType uptype) +{ + UsedPosList::const_iterator itr = m_nextUsedPos[uptype]; + if(itr!=m_UsedPosLists[uptype].end()) + ++itr; + + if(itr==m_UsedPosLists[uptype].end()) + { + if(!m_UsedPosLists[~uptype].empty()) + return &*m_UsedPosLists[~uptype].rbegin(); + else + return NULL; + } + else + return &*itr; +} + +void ObjectPosSelector::AddUsedPos(float size,float angle,float dist) +{ + if(angle>=0) + m_UsedPosLists[USED_POS_PLUS].insert(UsedPosList::value_type(angle,UsedPos(1.0,size,dist))); + else + m_UsedPosLists[USED_POS_MINUS].insert(UsedPosList::value_type(-angle,UsedPos(-1.0,size,dist))); +} + +void ObjectPosSelector::InitializeAngle() +{ + m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].begin(); + m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].begin(); + + m_smallStepAngle[USED_POS_PLUS] = 0; + m_smallStepAngle[USED_POS_MINUS] = 0; + + m_smallStepOk[USED_POS_PLUS] = true; + m_smallStepOk[USED_POS_MINUS] = true; +} + +bool ObjectPosSelector::FirstAngle(float& angle) +{ + if(m_UsedPosLists[USED_POS_PLUS].empty() && !m_UsedPosLists[USED_POS_MINUS].empty() ) + return NextAngleFor(*m_UsedPosLists[USED_POS_MINUS].begin(),1.0,USED_POS_PLUS,angle); + else if(m_UsedPosLists[USED_POS_MINUS].empty() && !m_UsedPosLists[USED_POS_PLUS].empty() ) + return NextAngleFor(*m_UsedPosLists[USED_POS_PLUS].begin(),-1.0,USED_POS_MINUS,angle); + + return false; +} + +bool ObjectPosSelector::NextAngle(float& angle) +{ + while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() || + m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() || + m_smallStepOk[USED_POS_PLUS] || m_smallStepOk[USED_POS_MINUS] ) + { + // calculate next possible angle + if(NextPosibleAngle(angle)) + return true; + } + + return false; +} + +bool ObjectPosSelector::NextUsedAngle(float& angle) +{ + while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() || + m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() ) + { + // calculate next possible angle + if(!NextPosibleAngle(angle)) + return true; + } + + return false; +} + +bool ObjectPosSelector::NextPosibleAngle( float& angle ) +{ + // ++ direction less updated + if( m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() && + (m_nextUsedPos[USED_POS_MINUS]==m_UsedPosLists[USED_POS_MINUS].end() || m_nextUsedPos[USED_POS_PLUS]->first <= m_nextUsedPos[USED_POS_MINUS]->first) ) + { + bool ok; + if(m_smallStepOk[USED_POS_PLUS]) + ok = NextSmallStepAngle(1.0,USED_POS_PLUS,angle); + else + ok = NextAngleFor(*m_nextUsedPos[USED_POS_PLUS],1.0,USED_POS_PLUS,angle); + + if(!ok) + ++m_nextUsedPos[USED_POS_PLUS]; // increase. only at fail (original or checked) + return ok; + } + // -- direction less updated + else if( m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end()) + { + bool ok; + if(m_smallStepOk[USED_POS_MINUS]) + ok = NextSmallStepAngle(-1.0,USED_POS_MINUS,angle); + else + ok = NextAngleFor(*m_nextUsedPos[USED_POS_MINUS],-1.0,USED_POS_MINUS,angle); + + if(!ok) + ++m_nextUsedPos[USED_POS_MINUS]; + return ok; + } + else // both list empty + { + if( m_smallStepOk[USED_POS_PLUS] && (!m_smallStepOk[USED_POS_MINUS] || m_smallStepAngle[USED_POS_PLUS] <= m_smallStepAngle[USED_POS_MINUS]) ) + { + return NextSmallStepAngle(1.0,USED_POS_PLUS,angle); + } + // -- direction less updated + else if( m_smallStepOk[USED_POS_MINUS] ) + { + return NextSmallStepAngle(-1.0,USED_POS_MINUS,angle); + } + } + + // no angles + return false; +} diff --git a/src/server/game/Entities/Object/ObjectPosSelector.h b/src/server/game/Entities/Object/ObjectPosSelector.h new file mode 100644 index 00000000000..84050611121 --- /dev/null +++ b/src/server/game/Entities/Object/ObjectPosSelector.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _OBJECT_POS_SELECTOR_H +#define _OBJECT_POS_SELECTOR_H + +#include + +#include + +enum UsedPosType { USED_POS_PLUS, USED_POS_MINUS }; + +inline UsedPosType operator ~(UsedPosType uptype) +{ + return uptype==USED_POS_PLUS ? USED_POS_MINUS : USED_POS_PLUS; +} + +struct ObjectPosSelector +{ + struct UsedPos + { + UsedPos(float sign_, float size_,float dist_) : sign(sign_), size(size_),dist(dist_) {} + + float sign; + + float size; // size of point + float dist; // dist to central point (including central point size) + }; + + typedef std::multimap UsedPosList; // abs(angle)->Node + + ObjectPosSelector(float x,float y,float size,float dist); + + void AddUsedPos(float size,float angle,float dist); + void InitializeAngle(); + + bool FirstAngle(float& angle); + bool NextAngle(float& angle); + bool NextUsedAngle(float& angle); + + bool NextPosibleAngle( float& angle ); + + bool CheckAngle(UsedPosList::value_type const& nextUsedPos, float sign, float angle ) const + { + float angle_step2 = GetAngle(nextUsedPos.second); + + float next_angle = nextUsedPos.first; + if(nextUsedPos.second.sign * sign < 0) // last node from diff. list (-pi+alpha) + next_angle = 2*M_PI-next_angle; // move to positive + + return fabs(angle)+angle_step2 <= next_angle; + } + + bool CheckOriginal() const + { + return (m_UsedPosLists[USED_POS_PLUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_PLUS].begin(),1.0,0)) && + (m_UsedPosLists[USED_POS_MINUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_MINUS].begin(),-1.0,0)); + } + + bool IsNonBalanced() const { return m_UsedPosLists[USED_POS_PLUS].empty() != m_UsedPosLists[USED_POS_MINUS].empty(); } + + bool NextAngleFor( UsedPosList::value_type const& usedPos, float sign, UsedPosType uptype, float &angle ) + { + float angle_step = GetAngle(usedPos.second); + + // next possible angle + angle = usedPos.first * usedPos.second.sign + angle_step * sign; + + UsedPosList::value_type const* nextNode = nextUsedPos(uptype); + if(nextNode) + { + // if next node permit use selected angle, then do it + if(!CheckAngle(*nextNode, sign, angle)) + { + m_smallStepOk[uptype] = false; + return false; + } + } + + // possible more points + m_smallStepOk[uptype] = true; + m_smallStepAngle[uptype] = angle; + m_smallStepNextUsedPos[uptype] = nextNode; + + return true; + } + + bool NextSmallStepAngle( float sign, UsedPosType uptype, float &angle ) + { + // next possible angle + angle = m_smallStepAngle[uptype] + m_anglestep * sign; + + if(fabs(angle) > M_PI) + { + m_smallStepOk[uptype] = false; + return false; + } + + if(m_smallStepNextUsedPos[uptype]) + { + if(fabs(angle) >= m_smallStepNextUsedPos[uptype]->first) + { + m_smallStepOk[uptype] = false; + return false; + } + + // if next node permit use selected angle, then do it + if(!CheckAngle(*m_smallStepNextUsedPos[uptype], sign, angle)) + { + m_smallStepOk[uptype] = false; + return false; + } + } + + // possible more points + m_smallStepAngle[uptype] = angle; + return true; + } + + // next used post for m_nextUsedPos[uptype] + UsedPosList::value_type const* nextUsedPos(UsedPosType uptype); + + // angle from used pos to next possible free pos + float GetAngle(UsedPos const& usedPos) const { return acos(m_dist/(usedPos.dist+usedPos.size+m_size)); } + + float m_center_x; + float m_center_y; + float m_size; // size of object in center + float m_dist; // distance for searching pos (including central object size) + float m_anglestep; + + UsedPosList m_UsedPosLists[2]; + UsedPosList::const_iterator m_nextUsedPos[2]; + + // field for small step from first after next used pos until next pos + float m_smallStepAngle[2]; + bool m_smallStepOk[2]; + UsedPosList::value_type const* m_smallStepNextUsedPos[2]; +}; +#endif diff --git a/src/server/game/Entities/Object/UpdateData.cpp b/src/server/game/Entities/Object/UpdateData.cpp deleted file mode 100644 index 68f0501f304..00000000000 --- a/src/server/game/Entities/Object/UpdateData.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "ByteBuffer.h" -#include "WorldPacket.h" -#include "UpdateData.h" -#include "Log.h" -#include "Opcodes.h" -#include "World.h" -#include - -UpdateData::UpdateData() : m_blockCount(0) -{ -} - -void UpdateData::AddOutOfRangeGUID(std::set& guids) -{ - m_outOfRangeGUIDs.insert(guids.begin(),guids.end()); -} - -void UpdateData::AddOutOfRangeGUID(const uint64 &guid) -{ - m_outOfRangeGUIDs.insert(guid); -} - -void UpdateData::AddUpdateBlock(const ByteBuffer &block) -{ - m_data.append(block); - ++m_blockCount; -} - -void UpdateData::Compress(void* dst, uint32 *dst_size, void* src, int src_size) -{ - z_stream c_stream; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - // default Z_BEST_SPEED (1) - int z_res = deflateInit(&c_stream, sWorld.getConfig(CONFIG_COMPRESSION)); - if (z_res != Z_OK) - { - sLog.outError("Can't compress update packet (zlib: deflateInit) Error code: %i (%s)",z_res,zError(z_res)); - *dst_size = 0; - return; - } - - c_stream.next_out = (Bytef*)dst; - c_stream.avail_out = *dst_size; - c_stream.next_in = (Bytef*)src; - c_stream.avail_in = (uInt)src_size; - - z_res = deflate(&c_stream, Z_NO_FLUSH); - if (z_res != Z_OK) - { - sLog.outError("Can't compress update packet (zlib: deflate) Error code: %i (%s)",z_res,zError(z_res)); - *dst_size = 0; - return; - } - - if (c_stream.avail_in != 0) - { - sLog.outError("Can't compress update packet (zlib: deflate not greedy)"); - *dst_size = 0; - return; - } - - z_res = deflate(&c_stream, Z_FINISH); - if (z_res != Z_STREAM_END) - { - sLog.outError("Can't compress update packet (zlib: deflate should report Z_STREAM_END instead %i (%s)",z_res,zError(z_res)); - *dst_size = 0; - return; - } - - z_res = deflateEnd(&c_stream); - if (z_res != Z_OK) - { - sLog.outError("Can't compress update packet (zlib: deflateEnd) Error code: %i (%s)",z_res,zError(z_res)); - *dst_size = 0; - return; - } - - *dst_size = c_stream.total_out; -} - -bool UpdateData::BuildPacket(WorldPacket *packet) -{ - ASSERT(packet->empty()); // shouldn't happen - - ByteBuffer buf(4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos()); - - buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount); - - if (!m_outOfRangeGUIDs.empty()) - { - buf << (uint8) UPDATETYPE_OUT_OF_RANGE_OBJECTS; - buf << (uint32) m_outOfRangeGUIDs.size(); - - for (std::set::const_iterator i = m_outOfRangeGUIDs.begin(); i != m_outOfRangeGUIDs.end(); ++i) - { - buf.appendPackGUID(*i); - } - } - - buf.append(m_data); - - size_t pSize = buf.wpos(); // use real used data size - - if (pSize > 100) // compress large packets - { - uint32 destsize = compressBound(pSize); - packet->resize(destsize + sizeof(uint32)); - - packet->put(0, pSize); - Compress(const_cast(packet->contents()) + sizeof(uint32), &destsize, (void*)buf.contents(), pSize); - if (destsize == 0) - return false; - - packet->resize(destsize + sizeof(uint32)); - packet->SetOpcode(SMSG_COMPRESSED_UPDATE_OBJECT); - } - else // send small packets without compression - { - packet->append(buf); - packet->SetOpcode(SMSG_UPDATE_OBJECT); - } - - return true; -} - -void UpdateData::Clear() -{ - m_data.clear(); - m_outOfRangeGUIDs.clear(); - m_blockCount = 0; -} - diff --git a/src/server/game/Entities/Object/UpdateData.h b/src/server/game/Entities/Object/UpdateData.h deleted file mode 100644 index e560db842f5..00000000000 --- a/src/server/game/Entities/Object/UpdateData.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __UPDATEDATA_H -#define __UPDATEDATA_H - -#include "ByteBuffer.h" -class WorldPacket; - -enum OBJECT_UPDATE_TYPE -{ - UPDATETYPE_VALUES = 0, - UPDATETYPE_MOVEMENT = 1, - UPDATETYPE_CREATE_OBJECT = 2, - UPDATETYPE_CREATE_OBJECT2 = 3, - UPDATETYPE_OUT_OF_RANGE_OBJECTS = 4, - UPDATETYPE_NEAR_OBJECTS = 5 -}; - -enum OBJECT_UPDATE_FLAGS -{ - UPDATEFLAG_NONE = 0x0000, - UPDATEFLAG_SELF = 0x0001, - UPDATEFLAG_TRANSPORT = 0x0002, - UPDATEFLAG_HAS_TARGET = 0x0004, - UPDATEFLAG_LOWGUID = 0x0008, - UPDATEFLAG_HIGHGUID = 0x0010, - UPDATEFLAG_LIVING = 0x0020, - UPDATEFLAG_HAS_POSITION = 0x0040, - UPDATEFLAG_VEHICLE = 0x0080, - UPDATEFLAG_POSITION = 0x0100, - UPDATEFLAG_ROTATION = 0x0200 -}; - -class UpdateData -{ - public: - UpdateData(); - - void AddOutOfRangeGUID(std::set& guids); - void AddOutOfRangeGUID(const uint64 &guid); - void AddUpdateBlock(const ByteBuffer &block); - bool BuildPacket(WorldPacket *packet); - bool HasData() { return m_blockCount > 0 || !m_outOfRangeGUIDs.empty(); } - void Clear(); - - std::set const& GetOutOfRangeGUIDs() const { return m_outOfRangeGUIDs; } - - protected: - uint32 m_blockCount; - std::set m_outOfRangeGUIDs; - ByteBuffer m_data; - - void Compress(void* dst, uint32 *dst_size, void* src, int src_size); -}; -#endif - diff --git a/src/server/game/Entities/Object/UpdateFields.h b/src/server/game/Entities/Object/UpdateFields.h deleted file mode 100644 index 5f819375677..00000000000 --- a/src/server/game/Entities/Object/UpdateFields.h +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _UPDATEFIELDS_AUTO_H -#define _UPDATEFIELDS_AUTO_H - -// Auto generated for version 3, 3, 3, 11723 - -enum EObjectFields -{ - OBJECT_FIELD_GUID = 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC - OBJECT_FIELD_TYPE = 0x0002, // Size: 1, Type: INT, Flags: PUBLIC - OBJECT_FIELD_ENTRY = 0x0003, // Size: 1, Type: INT, Flags: PUBLIC - OBJECT_FIELD_SCALE_X = 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC - OBJECT_FIELD_PADDING = 0x0005, // Size: 1, Type: INT, Flags: NONE - OBJECT_END = 0x0006, -}; - -enum EItemFields -{ - ITEM_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC - ITEM_FIELD_CONTAINED = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC - ITEM_FIELD_CREATOR = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC - ITEM_FIELD_GIFTCREATOR = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC - ITEM_FIELD_STACK_COUNT = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER - ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER - ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER, ITEM_OWNER - ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_1_1 = OBJECT_END + 0x0010, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_1_3 = OBJECT_END + 0x0012, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_2_1 = OBJECT_END + 0x0013, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_2_3 = OBJECT_END + 0x0015, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_3_1 = OBJECT_END + 0x0016, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_3_3 = OBJECT_END + 0x0018, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_4_1 = OBJECT_END + 0x0019, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_4_3 = OBJECT_END + 0x001B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_5_1 = OBJECT_END + 0x001C, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_5_3 = OBJECT_END + 0x001E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_6_1 = OBJECT_END + 0x001F, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_6_3 = OBJECT_END + 0x0021, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_7_1 = OBJECT_END + 0x0022, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_7_3 = OBJECT_END + 0x0024, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_8_1 = OBJECT_END + 0x0025, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_8_3 = OBJECT_END + 0x0027, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_9_1 = OBJECT_END + 0x0028, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_9_3 = OBJECT_END + 0x002A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_10_1 = OBJECT_END + 0x002B, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_10_3 = OBJECT_END + 0x002D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_11_1 = OBJECT_END + 0x002E, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_11_3 = OBJECT_END + 0x0030, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_12_1 = OBJECT_END + 0x0031, // Size: 2, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT_12_3 = OBJECT_END + 0x0033, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_DURABILITY = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER - ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER - ITEM_FIELD_CREATE_PLAYED_TIME = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE - ITEM_END = OBJECT_END + 0x003A, -}; - -enum EContainerFields -{ - CONTAINER_FIELD_NUM_SLOTS = ITEM_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC - CONTAINER_ALIGN_PAD = ITEM_END + 0x0001, // Size: 1, Type: BYTES, Flags: NONE - CONTAINER_FIELD_SLOT_1 = ITEM_END + 0x0002, // Size: 72, Type: LONG, Flags: PUBLIC - CONTAINER_END = ITEM_END + 0x004A, -}; - -enum EUnitFields -{ - UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE - UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_CHANNEL_SPELL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_HEALTH = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER1 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER2 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER3 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER4 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER5 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER6 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER7 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0021, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0022, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER - UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0029, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER - UNIT_FIELD_LEVEL = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0032, // Size: 3, Type: INT, Flags: PUBLIC - UNIT_FIELD_FLAGS = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_AURASTATE = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0038, // Size: 2, Type: INT, Flags: PUBLIC - UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x003A, // Size: 1, Type: INT, Flags: PRIVATE - UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003C, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003F, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER - UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER - UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER - UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0043, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER - UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0044, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER - UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: OWNER - UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_MOD_CAST_SPEED = OBJECT_END + 0x004A, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_CREATED_BY_SPELL = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_NPC_FLAGS = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_NPC_EMOTESTATE = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_STAT0 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER, PARTY_LEADER - UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_BASE_MANA = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_BYTES_2 = OBJECT_END + 0x0074, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x0075, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER - UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER - UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER - UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER - UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER - UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER - UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER - UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER - UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER - UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x008C, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_FIELD_PADDING = OBJECT_END + 0x008D, // Size: 1, Type: INT, Flags: NONE - UNIT_END = OBJECT_END + 0x008E, - - PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_GUILDID = UNIT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_GUILDRANK = UNIT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_BYTES = UNIT_END + 0x0005, // Size: 1, Type: BYTES, Flags: PUBLIC - PLAYER_BYTES_2 = UNIT_END + 0x0006, // Size: 1, Type: BYTES, Flags: PUBLIC - PLAYER_BYTES_3 = UNIT_END + 0x0007, // Size: 1, Type: BYTES, Flags: PUBLIC - PLAYER_DUEL_TEAM = UNIT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_GUILD_TIMESTAMP = UNIT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_QUEST_LOG_1_1 = UNIT_END + 0x000A, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_1_2 = UNIT_END + 0x000B, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_1_3 = UNIT_END + 0x000C, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_1_4 = UNIT_END + 0x000E, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_2_1 = UNIT_END + 0x000F, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_2_2 = UNIT_END + 0x0010, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_2_3 = UNIT_END + 0x0011, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_2_5 = UNIT_END + 0x0013, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_3_1 = UNIT_END + 0x0014, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_3_2 = UNIT_END + 0x0015, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_3_3 = UNIT_END + 0x0016, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_3_5 = UNIT_END + 0x0018, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_4_1 = UNIT_END + 0x0019, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_4_2 = UNIT_END + 0x001A, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_4_3 = UNIT_END + 0x001B, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_4_5 = UNIT_END + 0x001D, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_5_1 = UNIT_END + 0x001E, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_5_2 = UNIT_END + 0x001F, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_5_3 = UNIT_END + 0x0020, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_5_5 = UNIT_END + 0x0022, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_6_1 = UNIT_END + 0x0023, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_6_2 = UNIT_END + 0x0024, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_6_3 = UNIT_END + 0x0025, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_6_5 = UNIT_END + 0x0027, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_7_1 = UNIT_END + 0x0028, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_7_2 = UNIT_END + 0x0029, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_7_3 = UNIT_END + 0x002A, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_7_5 = UNIT_END + 0x002C, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_8_1 = UNIT_END + 0x002D, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_8_2 = UNIT_END + 0x002E, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_8_3 = UNIT_END + 0x002F, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_8_5 = UNIT_END + 0x0031, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_9_1 = UNIT_END + 0x0032, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_9_2 = UNIT_END + 0x0033, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_9_3 = UNIT_END + 0x0034, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_9_5 = UNIT_END + 0x0036, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_10_1 = UNIT_END + 0x0037, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_10_2 = UNIT_END + 0x0038, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_10_3 = UNIT_END + 0x0039, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_10_5 = UNIT_END + 0x003B, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_11_1 = UNIT_END + 0x003C, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_11_2 = UNIT_END + 0x003D, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_11_3 = UNIT_END + 0x003E, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_11_5 = UNIT_END + 0x0040, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_12_1 = UNIT_END + 0x0041, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_12_2 = UNIT_END + 0x0042, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_12_3 = UNIT_END + 0x0043, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_12_5 = UNIT_END + 0x0045, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_13_1 = UNIT_END + 0x0046, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_13_2 = UNIT_END + 0x0047, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_13_3 = UNIT_END + 0x0048, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_13_5 = UNIT_END + 0x004A, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_14_1 = UNIT_END + 0x004B, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_14_2 = UNIT_END + 0x004C, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_14_3 = UNIT_END + 0x004D, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_14_5 = UNIT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_15_1 = UNIT_END + 0x0050, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_15_2 = UNIT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_15_3 = UNIT_END + 0x0052, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_15_5 = UNIT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_16_1 = UNIT_END + 0x0055, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_16_2 = UNIT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_16_3 = UNIT_END + 0x0057, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_16_5 = UNIT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_17_1 = UNIT_END + 0x005A, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_17_2 = UNIT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_17_3 = UNIT_END + 0x005C, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_17_5 = UNIT_END + 0x005E, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_18_1 = UNIT_END + 0x005F, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_18_2 = UNIT_END + 0x0060, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_18_3 = UNIT_END + 0x0061, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_18_5 = UNIT_END + 0x0063, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_19_1 = UNIT_END + 0x0064, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_19_2 = UNIT_END + 0x0065, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_19_3 = UNIT_END + 0x0066, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_19_5 = UNIT_END + 0x0068, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_20_1 = UNIT_END + 0x0069, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_20_2 = UNIT_END + 0x006A, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_20_3 = UNIT_END + 0x006B, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_20_5 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_21_1 = UNIT_END + 0x006E, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_21_2 = UNIT_END + 0x006F, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_21_3 = UNIT_END + 0x0070, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_21_5 = UNIT_END + 0x0072, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_22_1 = UNIT_END + 0x0073, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_22_2 = UNIT_END + 0x0074, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_22_3 = UNIT_END + 0x0075, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_22_5 = UNIT_END + 0x0077, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_23_1 = UNIT_END + 0x0078, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_23_2 = UNIT_END + 0x0079, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_23_3 = UNIT_END + 0x007A, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_23_5 = UNIT_END + 0x007C, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_24_1 = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_24_2 = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_24_3 = UNIT_END + 0x007F, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_24_5 = UNIT_END + 0x0081, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_25_1 = UNIT_END + 0x0082, // Size: 1, Type: INT, Flags: PARTY_MEMBER - PLAYER_QUEST_LOG_25_2 = UNIT_END + 0x0083, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x0084, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_QUEST_LOG_25_5 = UNIT_END + 0x0086, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_VISIBLE_ITEM_1_ENTRYID = UNIT_END + 0x0087, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_1_ENCHANTMENT = UNIT_END + 0x0088, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_ENTRYID = UNIT_END + 0x0089, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_ENCHANTMENT = UNIT_END + 0x008A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_ENTRYID = UNIT_END + 0x008B, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_ENCHANTMENT = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_ENTRYID = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_ENCHANTMENT = UNIT_END + 0x008E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_ENTRYID = UNIT_END + 0x008F, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_ENCHANTMENT = UNIT_END + 0x0090, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_ENTRYID = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_ENCHANTMENT = UNIT_END + 0x0092, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_ENTRYID = UNIT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_ENCHANTMENT = UNIT_END + 0x0094, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_ENTRYID = UNIT_END + 0x0095, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_ENCHANTMENT = UNIT_END + 0x0096, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_ENTRYID = UNIT_END + 0x0097, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_ENCHANTMENT = UNIT_END + 0x0098, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_ENTRYID = UNIT_END + 0x0099, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_ENCHANTMENT = UNIT_END + 0x009A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_ENTRYID = UNIT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_ENCHANTMENT = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_ENTRYID = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_ENCHANTMENT = UNIT_END + 0x009E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_ENTRYID = UNIT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_ENCHANTMENT = UNIT_END + 0x00A0, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_ENTRYID = UNIT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_ENCHANTMENT = UNIT_END + 0x00A2, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_ENTRYID = UNIT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_ENCHANTMENT = UNIT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_ENTRYID = UNIT_END + 0x00A5, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_ENCHANTMENT = UNIT_END + 0x00A6, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_ENTRYID = UNIT_END + 0x00A7, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_ENCHANTMENT = UNIT_END + 0x00A8, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_ENTRYID = UNIT_END + 0x00A9, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_ENCHANTMENT = UNIT_END + 0x00AA, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_ENTRYID = UNIT_END + 0x00AB, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_ENCHANTMENT = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_CHOSEN_TITLE = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_FAKE_INEBRIATION = UNIT_END + 0x00AE, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_FIELD_PAD_0 = UNIT_END + 0x00AF, // Size: 1, Type: INT, Flags: NONE - PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x00B0, // Size: 46, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x00DE, // Size: 32, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x00FE, // Size: 56, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0136, // Size: 14, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0144, // Size: 24, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x015C, // Size: 64, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_CURRENCYTOKEN_SLOT_1 = UNIT_END + 0x019C, // Size: 64, Type: LONG, Flags: PRIVATE - PLAYER_FARSIGHT = UNIT_END + 0x01DC, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x01DE, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x01E0, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER__FIELD_KNOWN_TITLES2 = UNIT_END + 0x01E2, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_KNOWN_CURRENCIES = UNIT_END + 0x01E4, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER_XP = UNIT_END + 0x01E6, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x01E7, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x01E8, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0368, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0369, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_TRACK_CREATURES = UNIT_END + 0x036A, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_TRACK_RESOURCES = UNIT_END + 0x036B, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x036C, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x036D, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x036E, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_EXPERTISE = UNIT_END + 0x036F, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x0370, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x0371, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0372, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0373, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0374, // Size: 7, Type: FLOAT, Flags: PRIVATE - PLAYER_SHIELD_BLOCK = UNIT_END + 0x037B, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x037C, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x037D, // Size: 128, Type: BYTES, Flags: PRIVATE - PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x03FD, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_COINAGE = UNIT_END + 0x03FE, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x03FF, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x0406, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x040D, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x0414, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_HEALING_PCT = UNIT_END + 0x0415, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_FIELD_MOD_HEALING_DONE_PCT = UNIT_END + 0x0416, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x0417, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x0418, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BYTES = UNIT_END + 0x0419, // Size: 1, Type: BYTES, Flags: PRIVATE - PLAYER_AMMO_ID = UNIT_END + 0x041A, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_SELF_RES_SPELL = UNIT_END + 0x041B, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x041C, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x041D, // Size: 12, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x0429, // Size: 12, Type: INT, Flags: PRIVATE - PLAYER_FIELD_KILLS = UNIT_END + 0x0435, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_LIFETIME_HONORABLE_KILLS = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BYTES2 = UNIT_END + 0x0439, // Size: 1, Type: 6, Flags: PRIVATE - PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x043A, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x043B, // Size: 25, Type: INT, Flags: PRIVATE - PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x0454, // Size: 21, Type: INT, Flags: PRIVATE - PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0469, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x046A, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x046B, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x046C, // Size: 25, Type: INT, Flags: PRIVATE - PLAYER_RUNE_REGEN_1 = UNIT_END + 0x0485, // Size: 4, Type: FLOAT, Flags: PRIVATE - PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x0489, // Size: 3, Type: INT, Flags: PRIVATE - PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x048C, // Size: 6, Type: INT, Flags: PRIVATE - PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0492, // Size: 6, Type: INT, Flags: PRIVATE - PLAYER_GLYPHS_ENABLED = UNIT_END + 0x0498, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_PET_SPELL_POWER = UNIT_END + 0x0499, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_END = UNIT_END + 0x049A, -}; - -enum EGameObjectFields -{ - OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC - GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_PARENTROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_DYNAMIC = OBJECT_END + 0x0008, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC - GAMEOBJECT_FACTION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_LEVEL = OBJECT_END + 0x000A, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_BYTES_1 = OBJECT_END + 0x000B, // Size: 1, Type: BYTES, Flags: PUBLIC - GAMEOBJECT_END = OBJECT_END + 0x000C, -}; - -enum EDynamicObjectFields -{ - DYNAMICOBJECT_CASTER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC - DYNAMICOBJECT_BYTES = OBJECT_END + 0x0002, // Size: 1, Type: BYTES, Flags: PUBLIC - DYNAMICOBJECT_SPELLID = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC - DYNAMICOBJECT_RADIUS = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC - DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC - DYNAMICOBJECT_END = OBJECT_END + 0x0006, -}; - -enum ECorpseFields -{ - CORPSE_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC - CORPSE_FIELD_PARTY = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC - CORPSE_FIELD_DISPLAY_ID = OBJECT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC - CORPSE_FIELD_ITEM = OBJECT_END + 0x0005, // Size: 19, Type: INT, Flags: PUBLIC - CORPSE_FIELD_BYTES_1 = OBJECT_END + 0x0018, // Size: 1, Type: BYTES, Flags: PUBLIC - CORPSE_FIELD_BYTES_2 = OBJECT_END + 0x0019, // Size: 1, Type: BYTES, Flags: PUBLIC - CORPSE_FIELD_GUILD = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC - CORPSE_FIELD_FLAGS = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC - CORPSE_FIELD_DYNAMIC_FLAGS = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: DYNAMIC - CORPSE_FIELD_PAD = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: NONE - CORPSE_END = OBJECT_END + 0x001E, -}; -#endif diff --git a/src/server/game/Entities/Object/UpdateMask.h b/src/server/game/Entities/Object/UpdateMask.h deleted file mode 100644 index 527bec42aa7..00000000000 --- a/src/server/game/Entities/Object/UpdateMask.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __UPDATEMASK_H -#define __UPDATEMASK_H - -#include "UpdateFields.h" -#include "Errors.h" - -class UpdateMask -{ - public: - UpdateMask() : mCount(0), mBlocks(0), mUpdateMask(0) { } - UpdateMask(const UpdateMask& mask) : mUpdateMask(0) { *this = mask; } - - ~UpdateMask() - { - if (mUpdateMask) - delete [] mUpdateMask; - } - - void SetBit (uint32 index) - { - ((uint8 *)mUpdateMask)[ index >> 3 ] |= 1 << (index & 0x7); - } - - void UnsetBit (uint32 index) - { - ((uint8 *)mUpdateMask)[ index >> 3 ] &= (0xff ^ (1 << (index & 0x7))); - } - - bool GetBit (uint32 index) const - { - return (((uint8 *)mUpdateMask)[ index >> 3 ] & (1 << (index & 0x7))) != 0; - } - - uint32 GetBlockCount() const { return mBlocks; } - uint32 GetLength() const { return mBlocks << 2; } - uint32 GetCount() const { return mCount; } - uint8* GetMask() { return (uint8*)mUpdateMask; } - - void SetCount (uint32 valuesCount) - { - if (mUpdateMask) - delete [] mUpdateMask; - - mCount = valuesCount; - mBlocks = (valuesCount + 31) / 32; - - mUpdateMask = new uint32[mBlocks]; - memset(mUpdateMask, 0, mBlocks << 2); - } - - void Clear() - { - if (mUpdateMask) - memset(mUpdateMask, 0, mBlocks << 2); - } - - UpdateMask& operator = (const UpdateMask& mask) - { - SetCount(mask.mCount); - memcpy(mUpdateMask, mask.mUpdateMask, mBlocks << 2); - - return *this; - } - - void operator &= (const UpdateMask& mask) - { - ASSERT(mask.mCount <= mCount); - for (uint32 i = 0; i < mBlocks; ++i) - mUpdateMask[i] &= mask.mUpdateMask[i]; - } - - void operator |= (const UpdateMask& mask) - { - ASSERT(mask.mCount <= mCount); - for (uint32 i = 0; i < mBlocks; ++i) - mUpdateMask[i] |= mask.mUpdateMask[i]; - } - - UpdateMask operator & (const UpdateMask& mask) const - { - ASSERT(mask.mCount <= mCount); - - UpdateMask newmask; - newmask = *this; - newmask &= mask; - - return newmask; - } - - UpdateMask operator | (const UpdateMask& mask) const - { - ASSERT(mask.mCount <= mCount); - - UpdateMask newmask; - newmask = *this; - newmask |= mask; - - return newmask; - } - - private: - uint32 mCount; - uint32 mBlocks; - uint32 *mUpdateMask; -}; -#endif - diff --git a/src/server/game/Entities/Object/Updates/UpdateData.cpp b/src/server/game/Entities/Object/Updates/UpdateData.cpp new file mode 100644 index 00000000000..68f0501f304 --- /dev/null +++ b/src/server/game/Entities/Object/Updates/UpdateData.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "ByteBuffer.h" +#include "WorldPacket.h" +#include "UpdateData.h" +#include "Log.h" +#include "Opcodes.h" +#include "World.h" +#include + +UpdateData::UpdateData() : m_blockCount(0) +{ +} + +void UpdateData::AddOutOfRangeGUID(std::set& guids) +{ + m_outOfRangeGUIDs.insert(guids.begin(),guids.end()); +} + +void UpdateData::AddOutOfRangeGUID(const uint64 &guid) +{ + m_outOfRangeGUIDs.insert(guid); +} + +void UpdateData::AddUpdateBlock(const ByteBuffer &block) +{ + m_data.append(block); + ++m_blockCount; +} + +void UpdateData::Compress(void* dst, uint32 *dst_size, void* src, int src_size) +{ + z_stream c_stream; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + // default Z_BEST_SPEED (1) + int z_res = deflateInit(&c_stream, sWorld.getConfig(CONFIG_COMPRESSION)); + if (z_res != Z_OK) + { + sLog.outError("Can't compress update packet (zlib: deflateInit) Error code: %i (%s)",z_res,zError(z_res)); + *dst_size = 0; + return; + } + + c_stream.next_out = (Bytef*)dst; + c_stream.avail_out = *dst_size; + c_stream.next_in = (Bytef*)src; + c_stream.avail_in = (uInt)src_size; + + z_res = deflate(&c_stream, Z_NO_FLUSH); + if (z_res != Z_OK) + { + sLog.outError("Can't compress update packet (zlib: deflate) Error code: %i (%s)",z_res,zError(z_res)); + *dst_size = 0; + return; + } + + if (c_stream.avail_in != 0) + { + sLog.outError("Can't compress update packet (zlib: deflate not greedy)"); + *dst_size = 0; + return; + } + + z_res = deflate(&c_stream, Z_FINISH); + if (z_res != Z_STREAM_END) + { + sLog.outError("Can't compress update packet (zlib: deflate should report Z_STREAM_END instead %i (%s)",z_res,zError(z_res)); + *dst_size = 0; + return; + } + + z_res = deflateEnd(&c_stream); + if (z_res != Z_OK) + { + sLog.outError("Can't compress update packet (zlib: deflateEnd) Error code: %i (%s)",z_res,zError(z_res)); + *dst_size = 0; + return; + } + + *dst_size = c_stream.total_out; +} + +bool UpdateData::BuildPacket(WorldPacket *packet) +{ + ASSERT(packet->empty()); // shouldn't happen + + ByteBuffer buf(4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos()); + + buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount); + + if (!m_outOfRangeGUIDs.empty()) + { + buf << (uint8) UPDATETYPE_OUT_OF_RANGE_OBJECTS; + buf << (uint32) m_outOfRangeGUIDs.size(); + + for (std::set::const_iterator i = m_outOfRangeGUIDs.begin(); i != m_outOfRangeGUIDs.end(); ++i) + { + buf.appendPackGUID(*i); + } + } + + buf.append(m_data); + + size_t pSize = buf.wpos(); // use real used data size + + if (pSize > 100) // compress large packets + { + uint32 destsize = compressBound(pSize); + packet->resize(destsize + sizeof(uint32)); + + packet->put(0, pSize); + Compress(const_cast(packet->contents()) + sizeof(uint32), &destsize, (void*)buf.contents(), pSize); + if (destsize == 0) + return false; + + packet->resize(destsize + sizeof(uint32)); + packet->SetOpcode(SMSG_COMPRESSED_UPDATE_OBJECT); + } + else // send small packets without compression + { + packet->append(buf); + packet->SetOpcode(SMSG_UPDATE_OBJECT); + } + + return true; +} + +void UpdateData::Clear() +{ + m_data.clear(); + m_outOfRangeGUIDs.clear(); + m_blockCount = 0; +} + diff --git a/src/server/game/Entities/Object/Updates/UpdateData.h b/src/server/game/Entities/Object/Updates/UpdateData.h new file mode 100644 index 00000000000..e560db842f5 --- /dev/null +++ b/src/server/game/Entities/Object/Updates/UpdateData.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __UPDATEDATA_H +#define __UPDATEDATA_H + +#include "ByteBuffer.h" +class WorldPacket; + +enum OBJECT_UPDATE_TYPE +{ + UPDATETYPE_VALUES = 0, + UPDATETYPE_MOVEMENT = 1, + UPDATETYPE_CREATE_OBJECT = 2, + UPDATETYPE_CREATE_OBJECT2 = 3, + UPDATETYPE_OUT_OF_RANGE_OBJECTS = 4, + UPDATETYPE_NEAR_OBJECTS = 5 +}; + +enum OBJECT_UPDATE_FLAGS +{ + UPDATEFLAG_NONE = 0x0000, + UPDATEFLAG_SELF = 0x0001, + UPDATEFLAG_TRANSPORT = 0x0002, + UPDATEFLAG_HAS_TARGET = 0x0004, + UPDATEFLAG_LOWGUID = 0x0008, + UPDATEFLAG_HIGHGUID = 0x0010, + UPDATEFLAG_LIVING = 0x0020, + UPDATEFLAG_HAS_POSITION = 0x0040, + UPDATEFLAG_VEHICLE = 0x0080, + UPDATEFLAG_POSITION = 0x0100, + UPDATEFLAG_ROTATION = 0x0200 +}; + +class UpdateData +{ + public: + UpdateData(); + + void AddOutOfRangeGUID(std::set& guids); + void AddOutOfRangeGUID(const uint64 &guid); + void AddUpdateBlock(const ByteBuffer &block); + bool BuildPacket(WorldPacket *packet); + bool HasData() { return m_blockCount > 0 || !m_outOfRangeGUIDs.empty(); } + void Clear(); + + std::set const& GetOutOfRangeGUIDs() const { return m_outOfRangeGUIDs; } + + protected: + uint32 m_blockCount; + std::set m_outOfRangeGUIDs; + ByteBuffer m_data; + + void Compress(void* dst, uint32 *dst_size, void* src, int src_size); +}; +#endif + diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.h b/src/server/game/Entities/Object/Updates/UpdateFields.h new file mode 100644 index 00000000000..5f819375677 --- /dev/null +++ b/src/server/game/Entities/Object/Updates/UpdateFields.h @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _UPDATEFIELDS_AUTO_H +#define _UPDATEFIELDS_AUTO_H + +// Auto generated for version 3, 3, 3, 11723 + +enum EObjectFields +{ + OBJECT_FIELD_GUID = 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + OBJECT_FIELD_TYPE = 0x0002, // Size: 1, Type: INT, Flags: PUBLIC + OBJECT_FIELD_ENTRY = 0x0003, // Size: 1, Type: INT, Flags: PUBLIC + OBJECT_FIELD_SCALE_X = 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC + OBJECT_FIELD_PADDING = 0x0005, // Size: 1, Type: INT, Flags: NONE + OBJECT_END = 0x0006, +}; + +enum EItemFields +{ + ITEM_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + ITEM_FIELD_CONTAINED = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC + ITEM_FIELD_CREATOR = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC + ITEM_FIELD_GIFTCREATOR = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC + ITEM_FIELD_STACK_COUNT = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER + ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER + ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER, ITEM_OWNER + ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_1_1 = OBJECT_END + 0x0010, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_1_3 = OBJECT_END + 0x0012, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_2_1 = OBJECT_END + 0x0013, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_2_3 = OBJECT_END + 0x0015, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_3_1 = OBJECT_END + 0x0016, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_3_3 = OBJECT_END + 0x0018, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_4_1 = OBJECT_END + 0x0019, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_4_3 = OBJECT_END + 0x001B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_5_1 = OBJECT_END + 0x001C, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_5_3 = OBJECT_END + 0x001E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_6_1 = OBJECT_END + 0x001F, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_6_3 = OBJECT_END + 0x0021, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_7_1 = OBJECT_END + 0x0022, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_7_3 = OBJECT_END + 0x0024, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_8_1 = OBJECT_END + 0x0025, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_8_3 = OBJECT_END + 0x0027, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_9_1 = OBJECT_END + 0x0028, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_9_3 = OBJECT_END + 0x002A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_10_1 = OBJECT_END + 0x002B, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_10_3 = OBJECT_END + 0x002D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_11_1 = OBJECT_END + 0x002E, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_11_3 = OBJECT_END + 0x0030, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_12_1 = OBJECT_END + 0x0031, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_12_3 = OBJECT_END + 0x0033, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_DURABILITY = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER + ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER, ITEM_OWNER + ITEM_FIELD_CREATE_PLAYED_TIME = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE + ITEM_END = OBJECT_END + 0x003A, +}; + +enum EContainerFields +{ + CONTAINER_FIELD_NUM_SLOTS = ITEM_END + 0x0000, // Size: 1, Type: INT, Flags: PUBLIC + CONTAINER_ALIGN_PAD = ITEM_END + 0x0001, // Size: 1, Type: BYTES, Flags: NONE + CONTAINER_FIELD_SLOT_1 = ITEM_END + 0x0002, // Size: 72, Type: LONG, Flags: PUBLIC + CONTAINER_END = ITEM_END + 0x004A, +}; + +enum EUnitFields +{ + UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE + UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_CHANNEL_SPELL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_HEALTH = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER1 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER2 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER3 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER4 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER5 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER6 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER7 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0021, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0022, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER + UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0029, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER + UNIT_FIELD_LEVEL = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0032, // Size: 3, Type: INT, Flags: PUBLIC + UNIT_FIELD_FLAGS = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_AURASTATE = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0038, // Size: 2, Type: INT, Flags: PUBLIC + UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x003A, // Size: 1, Type: INT, Flags: PRIVATE + UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003C, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003F, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER + UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER + UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER + UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0043, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER, PARTY_LEADER + UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0044, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER + UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: OWNER + UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_MOD_CAST_SPEED = OBJECT_END + 0x004A, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_CREATED_BY_SPELL = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_NPC_FLAGS = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_NPC_EMOTESTATE = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_STAT0 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER, PARTY_LEADER + UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_BASE_MANA = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_BYTES_2 = OBJECT_END + 0x0074, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x0075, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER + UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER + UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER + UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER + UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER + UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER + UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER + UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER + UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER + UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x008C, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_PADDING = OBJECT_END + 0x008D, // Size: 1, Type: INT, Flags: NONE + UNIT_END = OBJECT_END + 0x008E, + + PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_GUILDID = UNIT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_GUILDRANK = UNIT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_BYTES = UNIT_END + 0x0005, // Size: 1, Type: BYTES, Flags: PUBLIC + PLAYER_BYTES_2 = UNIT_END + 0x0006, // Size: 1, Type: BYTES, Flags: PUBLIC + PLAYER_BYTES_3 = UNIT_END + 0x0007, // Size: 1, Type: BYTES, Flags: PUBLIC + PLAYER_DUEL_TEAM = UNIT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_GUILD_TIMESTAMP = UNIT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_QUEST_LOG_1_1 = UNIT_END + 0x000A, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_1_2 = UNIT_END + 0x000B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_1_3 = UNIT_END + 0x000C, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_1_4 = UNIT_END + 0x000E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_2_1 = UNIT_END + 0x000F, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_2_2 = UNIT_END + 0x0010, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_2_3 = UNIT_END + 0x0011, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_2_5 = UNIT_END + 0x0013, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_3_1 = UNIT_END + 0x0014, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_3_2 = UNIT_END + 0x0015, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_3_3 = UNIT_END + 0x0016, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_3_5 = UNIT_END + 0x0018, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_4_1 = UNIT_END + 0x0019, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_4_2 = UNIT_END + 0x001A, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_4_3 = UNIT_END + 0x001B, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_4_5 = UNIT_END + 0x001D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_5_1 = UNIT_END + 0x001E, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_5_2 = UNIT_END + 0x001F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_5_3 = UNIT_END + 0x0020, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_5_5 = UNIT_END + 0x0022, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_6_1 = UNIT_END + 0x0023, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_6_2 = UNIT_END + 0x0024, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_6_3 = UNIT_END + 0x0025, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_6_5 = UNIT_END + 0x0027, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_7_1 = UNIT_END + 0x0028, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_7_2 = UNIT_END + 0x0029, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_7_3 = UNIT_END + 0x002A, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_7_5 = UNIT_END + 0x002C, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_8_1 = UNIT_END + 0x002D, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_8_2 = UNIT_END + 0x002E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_8_3 = UNIT_END + 0x002F, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_8_5 = UNIT_END + 0x0031, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_9_1 = UNIT_END + 0x0032, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_9_2 = UNIT_END + 0x0033, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_9_3 = UNIT_END + 0x0034, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_9_5 = UNIT_END + 0x0036, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_10_1 = UNIT_END + 0x0037, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_10_2 = UNIT_END + 0x0038, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_10_3 = UNIT_END + 0x0039, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_10_5 = UNIT_END + 0x003B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_11_1 = UNIT_END + 0x003C, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_11_2 = UNIT_END + 0x003D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_11_3 = UNIT_END + 0x003E, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_11_5 = UNIT_END + 0x0040, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_12_1 = UNIT_END + 0x0041, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_12_2 = UNIT_END + 0x0042, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_12_3 = UNIT_END + 0x0043, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_12_5 = UNIT_END + 0x0045, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_13_1 = UNIT_END + 0x0046, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_13_2 = UNIT_END + 0x0047, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_13_3 = UNIT_END + 0x0048, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_13_5 = UNIT_END + 0x004A, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_14_1 = UNIT_END + 0x004B, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_14_2 = UNIT_END + 0x004C, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_14_3 = UNIT_END + 0x004D, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_14_5 = UNIT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_15_1 = UNIT_END + 0x0050, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_15_2 = UNIT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_15_3 = UNIT_END + 0x0052, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_15_5 = UNIT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_16_1 = UNIT_END + 0x0055, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_16_2 = UNIT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_16_3 = UNIT_END + 0x0057, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_16_5 = UNIT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_17_1 = UNIT_END + 0x005A, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_17_2 = UNIT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_17_3 = UNIT_END + 0x005C, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_17_5 = UNIT_END + 0x005E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_18_1 = UNIT_END + 0x005F, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_18_2 = UNIT_END + 0x0060, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_18_3 = UNIT_END + 0x0061, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_18_5 = UNIT_END + 0x0063, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_19_1 = UNIT_END + 0x0064, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_19_2 = UNIT_END + 0x0065, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_19_3 = UNIT_END + 0x0066, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_19_5 = UNIT_END + 0x0068, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_20_1 = UNIT_END + 0x0069, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_20_2 = UNIT_END + 0x006A, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_20_3 = UNIT_END + 0x006B, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_20_5 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_21_1 = UNIT_END + 0x006E, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_21_2 = UNIT_END + 0x006F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_21_3 = UNIT_END + 0x0070, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_21_5 = UNIT_END + 0x0072, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_22_1 = UNIT_END + 0x0073, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_22_2 = UNIT_END + 0x0074, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_22_3 = UNIT_END + 0x0075, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_22_5 = UNIT_END + 0x0077, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_23_1 = UNIT_END + 0x0078, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_23_2 = UNIT_END + 0x0079, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_23_3 = UNIT_END + 0x007A, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_23_5 = UNIT_END + 0x007C, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_24_1 = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_24_2 = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_24_3 = UNIT_END + 0x007F, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_24_5 = UNIT_END + 0x0081, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_25_1 = UNIT_END + 0x0082, // Size: 1, Type: INT, Flags: PARTY_MEMBER + PLAYER_QUEST_LOG_25_2 = UNIT_END + 0x0083, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x0084, // Size: 2, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_QUEST_LOG_25_5 = UNIT_END + 0x0086, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_VISIBLE_ITEM_1_ENTRYID = UNIT_END + 0x0087, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_ENCHANTMENT = UNIT_END + 0x0088, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_ENTRYID = UNIT_END + 0x0089, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_ENCHANTMENT = UNIT_END + 0x008A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_ENTRYID = UNIT_END + 0x008B, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_ENCHANTMENT = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_ENTRYID = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_ENCHANTMENT = UNIT_END + 0x008E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_ENTRYID = UNIT_END + 0x008F, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_ENCHANTMENT = UNIT_END + 0x0090, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_ENTRYID = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_ENCHANTMENT = UNIT_END + 0x0092, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_ENTRYID = UNIT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_ENCHANTMENT = UNIT_END + 0x0094, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_ENTRYID = UNIT_END + 0x0095, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_ENCHANTMENT = UNIT_END + 0x0096, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_ENTRYID = UNIT_END + 0x0097, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_ENCHANTMENT = UNIT_END + 0x0098, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_ENTRYID = UNIT_END + 0x0099, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_ENCHANTMENT = UNIT_END + 0x009A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_ENTRYID = UNIT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_ENCHANTMENT = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_ENTRYID = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_ENCHANTMENT = UNIT_END + 0x009E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_ENTRYID = UNIT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_ENCHANTMENT = UNIT_END + 0x00A0, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_ENTRYID = UNIT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_ENCHANTMENT = UNIT_END + 0x00A2, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_ENTRYID = UNIT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_ENCHANTMENT = UNIT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_ENTRYID = UNIT_END + 0x00A5, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_ENCHANTMENT = UNIT_END + 0x00A6, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_ENTRYID = UNIT_END + 0x00A7, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_ENCHANTMENT = UNIT_END + 0x00A8, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_ENTRYID = UNIT_END + 0x00A9, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_ENCHANTMENT = UNIT_END + 0x00AA, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_ENTRYID = UNIT_END + 0x00AB, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_ENCHANTMENT = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_CHOSEN_TITLE = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_FAKE_INEBRIATION = UNIT_END + 0x00AE, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_FIELD_PAD_0 = UNIT_END + 0x00AF, // Size: 1, Type: INT, Flags: NONE + PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x00B0, // Size: 46, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x00DE, // Size: 32, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x00FE, // Size: 56, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0136, // Size: 14, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0144, // Size: 24, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x015C, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_CURRENCYTOKEN_SLOT_1 = UNIT_END + 0x019C, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FARSIGHT = UNIT_END + 0x01DC, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x01DE, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x01E0, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER__FIELD_KNOWN_TITLES2 = UNIT_END + 0x01E2, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_KNOWN_CURRENCIES = UNIT_END + 0x01E4, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER_XP = UNIT_END + 0x01E6, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x01E7, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x01E8, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0368, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0369, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_TRACK_CREATURES = UNIT_END + 0x036A, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_TRACK_RESOURCES = UNIT_END + 0x036B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x036C, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x036D, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x036E, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_EXPERTISE = UNIT_END + 0x036F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x0370, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x0371, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0372, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0373, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0374, // Size: 7, Type: FLOAT, Flags: PRIVATE + PLAYER_SHIELD_BLOCK = UNIT_END + 0x037B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x037C, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x037D, // Size: 128, Type: BYTES, Flags: PRIVATE + PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x03FD, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_COINAGE = UNIT_END + 0x03FE, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x03FF, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x0406, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x040D, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x0414, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_HEALING_PCT = UNIT_END + 0x0415, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_FIELD_MOD_HEALING_DONE_PCT = UNIT_END + 0x0416, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x0417, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x0418, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BYTES = UNIT_END + 0x0419, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_AMMO_ID = UNIT_END + 0x041A, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SELF_RES_SPELL = UNIT_END + 0x041B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x041C, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x041D, // Size: 12, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x0429, // Size: 12, Type: INT, Flags: PRIVATE + PLAYER_FIELD_KILLS = UNIT_END + 0x0435, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_LIFETIME_HONORABLE_KILLS = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BYTES2 = UNIT_END + 0x0439, // Size: 1, Type: 6, Flags: PRIVATE + PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x043A, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x043B, // Size: 25, Type: INT, Flags: PRIVATE + PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x0454, // Size: 21, Type: INT, Flags: PRIVATE + PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0469, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x046A, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x046B, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x046C, // Size: 25, Type: INT, Flags: PRIVATE + PLAYER_RUNE_REGEN_1 = UNIT_END + 0x0485, // Size: 4, Type: FLOAT, Flags: PRIVATE + PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x0489, // Size: 3, Type: INT, Flags: PRIVATE + PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x048C, // Size: 6, Type: INT, Flags: PRIVATE + PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0492, // Size: 6, Type: INT, Flags: PRIVATE + PLAYER_GLYPHS_ENABLED = UNIT_END + 0x0498, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_PET_SPELL_POWER = UNIT_END + 0x0499, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_END = UNIT_END + 0x049A, +}; + +enum EGameObjectFields +{ + OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_PARENTROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_DYNAMIC = OBJECT_END + 0x0008, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC + GAMEOBJECT_FACTION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_LEVEL = OBJECT_END + 0x000A, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_BYTES_1 = OBJECT_END + 0x000B, // Size: 1, Type: BYTES, Flags: PUBLIC + GAMEOBJECT_END = OBJECT_END + 0x000C, +}; + +enum EDynamicObjectFields +{ + DYNAMICOBJECT_CASTER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + DYNAMICOBJECT_BYTES = OBJECT_END + 0x0002, // Size: 1, Type: BYTES, Flags: PUBLIC + DYNAMICOBJECT_SPELLID = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC + DYNAMICOBJECT_RADIUS = OBJECT_END + 0x0004, // Size: 1, Type: FLOAT, Flags: PUBLIC + DYNAMICOBJECT_CASTTIME = OBJECT_END + 0x0005, // Size: 1, Type: INT, Flags: PUBLIC + DYNAMICOBJECT_END = OBJECT_END + 0x0006, +}; + +enum ECorpseFields +{ + CORPSE_FIELD_OWNER = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC + CORPSE_FIELD_PARTY = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC + CORPSE_FIELD_DISPLAY_ID = OBJECT_END + 0x0004, // Size: 1, Type: INT, Flags: PUBLIC + CORPSE_FIELD_ITEM = OBJECT_END + 0x0005, // Size: 19, Type: INT, Flags: PUBLIC + CORPSE_FIELD_BYTES_1 = OBJECT_END + 0x0018, // Size: 1, Type: BYTES, Flags: PUBLIC + CORPSE_FIELD_BYTES_2 = OBJECT_END + 0x0019, // Size: 1, Type: BYTES, Flags: PUBLIC + CORPSE_FIELD_GUILD = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC + CORPSE_FIELD_FLAGS = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC + CORPSE_FIELD_DYNAMIC_FLAGS = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: DYNAMIC + CORPSE_FIELD_PAD = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: NONE + CORPSE_END = OBJECT_END + 0x001E, +}; +#endif diff --git a/src/server/game/Entities/Object/Updates/UpdateMask.h b/src/server/game/Entities/Object/Updates/UpdateMask.h new file mode 100644 index 00000000000..527bec42aa7 --- /dev/null +++ b/src/server/game/Entities/Object/Updates/UpdateMask.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __UPDATEMASK_H +#define __UPDATEMASK_H + +#include "UpdateFields.h" +#include "Errors.h" + +class UpdateMask +{ + public: + UpdateMask() : mCount(0), mBlocks(0), mUpdateMask(0) { } + UpdateMask(const UpdateMask& mask) : mUpdateMask(0) { *this = mask; } + + ~UpdateMask() + { + if (mUpdateMask) + delete [] mUpdateMask; + } + + void SetBit (uint32 index) + { + ((uint8 *)mUpdateMask)[ index >> 3 ] |= 1 << (index & 0x7); + } + + void UnsetBit (uint32 index) + { + ((uint8 *)mUpdateMask)[ index >> 3 ] &= (0xff ^ (1 << (index & 0x7))); + } + + bool GetBit (uint32 index) const + { + return (((uint8 *)mUpdateMask)[ index >> 3 ] & (1 << (index & 0x7))) != 0; + } + + uint32 GetBlockCount() const { return mBlocks; } + uint32 GetLength() const { return mBlocks << 2; } + uint32 GetCount() const { return mCount; } + uint8* GetMask() { return (uint8*)mUpdateMask; } + + void SetCount (uint32 valuesCount) + { + if (mUpdateMask) + delete [] mUpdateMask; + + mCount = valuesCount; + mBlocks = (valuesCount + 31) / 32; + + mUpdateMask = new uint32[mBlocks]; + memset(mUpdateMask, 0, mBlocks << 2); + } + + void Clear() + { + if (mUpdateMask) + memset(mUpdateMask, 0, mBlocks << 2); + } + + UpdateMask& operator = (const UpdateMask& mask) + { + SetCount(mask.mCount); + memcpy(mUpdateMask, mask.mUpdateMask, mBlocks << 2); + + return *this; + } + + void operator &= (const UpdateMask& mask) + { + ASSERT(mask.mCount <= mCount); + for (uint32 i = 0; i < mBlocks; ++i) + mUpdateMask[i] &= mask.mUpdateMask[i]; + } + + void operator |= (const UpdateMask& mask) + { + ASSERT(mask.mCount <= mCount); + for (uint32 i = 0; i < mBlocks; ++i) + mUpdateMask[i] |= mask.mUpdateMask[i]; + } + + UpdateMask operator & (const UpdateMask& mask) const + { + ASSERT(mask.mCount <= mCount); + + UpdateMask newmask; + newmask = *this; + newmask &= mask; + + return newmask; + } + + UpdateMask operator | (const UpdateMask& mask) const + { + ASSERT(mask.mCount <= mCount); + + UpdateMask newmask; + newmask = *this; + newmask |= mask; + + return newmask; + } + + private: + uint32 mCount; + uint32 mBlocks; + uint32 *mUpdateMask; +}; +#endif + diff --git a/src/server/game/Entities/Pet/PetHandler.cpp b/src/server/game/Entities/Pet/PetHandler.cpp deleted file mode 100644 index 34e6845762b..00000000000 --- a/src/server/game/Entities/Pet/PetHandler.cpp +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Spell.h" -#include "ObjectAccessor.h" -#include "CreatureAI.h" -#include "Util.h" -#include "Pet.h" -#include "World.h" - -void WorldSession::HandleDismissCritter(WorldPacket &recv_data) -{ - uint64 guid; - recv_data >> guid; - - sLog.outDebug("WORLD: Received CMSG_DISMISS_CRITTER for GUID %u", guid); - - Unit* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - - if (!pet) - { - sLog.outError("Vanitypet %u does not exist", uint32(GUID_LOPART(guid))); - return; - } - - if (_player->GetCritterGUID() == pet->GetGUID()) - { - if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isSummon()) - pet->ToTempSummon()->UnSummon(); - } -} - -void WorldSession::HandlePetAction(WorldPacket & recv_data) -{ - uint64 guid1; - uint32 data; - uint64 guid2; - recv_data >> guid1; //pet guid - recv_data >> data; - recv_data >> guid2; //tag guid - - uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data); - uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); //delete = 0x07 CastSpell = C1 - - // used also for charmed creature - Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); - sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), uint32(flag), spellid, uint32(GUID_LOPART(guid2))); - if (!pet) - { - sLog.outError("Pet %u not exist.", uint32(GUID_LOPART(guid1))); - return; - } - - if (pet != GetPlayer()->GetFirstControlled()) - { - sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName()); - return; - } - - if (!pet->isAlive()) - return; - - //TODO: allow control charmed player? - if (pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) - return; - - if (GetPlayer()->m_Controlled.size() == 1) - HandlePetActionHelper(pet, guid1, spellid, flag, guid2); - else - { - //If a pet is dismissed, m_Controlled will change - std::vector controlled; - for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr) - if ((*itr)->GetEntry() == pet->GetEntry() && (*itr)->isAlive()) - controlled.push_back(*itr); - for (std::vector::iterator itr = controlled.begin(); itr != controlled.end(); ++itr) - HandlePetActionHelper(*itr, guid1, spellid, flag, guid2); - } -} - -void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid, uint16 flag, uint64 guid2) -{ - CharmInfo *charmInfo = pet->GetCharmInfo(); - if (!charmInfo) - { - sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); - return; - } - - switch(flag) - { - case ACT_COMMAND: //0x07 - switch(spellid) - { - case COMMAND_STAY: //flat=1792 //STAY - pet->AttackStop(); - pet->InterruptNonMeleeSpells(false); - pet->GetMotionMaster()->MoveIdle(); - charmInfo->SetCommandState(COMMAND_STAY); - - charmInfo->SetIsCommandAttack(false); - charmInfo->SetIsAtStay(true); - charmInfo->SetIsFollowing(false); - charmInfo->SetIsReturning(false); - charmInfo->SaveStayPosition(); - break; - case COMMAND_FOLLOW: //spellid=1792 //FOLLOW - pet->AttackStop(); - pet->InterruptNonMeleeSpells(false); - pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,pet->GetFollowAngle()); - charmInfo->SetCommandState(COMMAND_FOLLOW); - - charmInfo->SetIsCommandAttack(false); - charmInfo->SetIsAtStay(false); - charmInfo->SetIsReturning(true); - charmInfo->SetIsFollowing(false); - break; - case COMMAND_ATTACK: //spellid=1792 //ATTACK - { - // Can't attack if owner is pacified - if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY)) - { - //pet->SendPetCastFail(spellid, SPELL_FAILED_PACIFIED); - //TODO: Send proper error message to client - return; - } - - // only place where pet can be player - Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, guid2); - if (!TargetUnit) - return; - - if (!pet->canAttack(TargetUnit)) - return; - - // Not let attack through obstructions - if (sWorld.getConfig(CONFIG_PET_LOS)) - { - - if (!pet->IsWithinLOSInMap(TargetUnit)) - return; - - } - - pet->clearUnitState(UNIT_STAT_FOLLOW); - // This is true if pet has no target or has target but targets differs. - if (pet->getVictim() != TargetUnit || (pet->getVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack())) - { - if (pet->getVictim()) - pet->AttackStop(); - - if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature()->IsAIEnabled) - { - charmInfo->SetIsCommandAttack(true); - charmInfo->SetIsAtStay(false); - charmInfo->SetIsFollowing(false); - charmInfo->SetIsReturning(false); - - pet->ToCreature()->AI()->AttackStart(TargetUnit); - - //10% chance to play special pet attack talk, else growl - if (pet->ToCreature()->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_ATTACK); - else - { - // 90% chance for pet and 100% chance for charmed creature - pet->SendPetAIReaction(guid1); - } - } - else // charmed player - { - if (pet->getVictim() && pet->getVictim() != TargetUnit) - pet->AttackStop(); - - charmInfo->SetIsCommandAttack(true); - charmInfo->SetIsAtStay(false); - charmInfo->SetIsFollowing(false); - charmInfo->SetIsReturning(false); - - pet->Attack(TargetUnit,true); - pet->SendPetAIReaction(guid1); - } - } - break; - } - case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) - if (pet->GetCharmerGUID() == GetPlayer()->GetGUID()) - _player->StopCastingCharm(); - else if (pet->GetOwnerGUID() == GetPlayer()->GetGUID()) - { - assert(pet->GetTypeId() == TYPEID_UNIT); - if (pet->isPet()) - { - if (((Pet*)pet)->getPetType() == HUNTER_PET) - GetPlayer()->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); - else - //dismissing a summoned pet is like killing them (this prevents returning a soulshard...) - pet->setDeathState(CORPSE); - } - else if (pet->HasUnitTypeMask(UNIT_MASK_MINION)) - { - ((Minion*)pet)->UnSummon(); - } - } - break; - default: - sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); - } - break; - case ACT_REACTION: // 0x6 - switch(spellid) - { - case REACT_PASSIVE: //passive - pet->AttackStop(); - - case REACT_DEFENSIVE: //recovery - case REACT_AGGRESSIVE: //activete - if (pet->GetTypeId() == TYPEID_UNIT) - pet->ToCreature()->SetReactState(ReactStates(spellid)); - break; - } - break; - case ACT_DISABLED: // 0x81 spell (disabled), ignore - case ACT_PASSIVE: // 0x01 - case ACT_ENABLED: // 0xC1 spell - { - Unit* unit_target = NULL; - - if (guid2) - unit_target = ObjectAccessor::GetUnit(*_player,guid2); - - // do not cast unknown spells - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); - if (!spellInfo) - { - sLog.outError("WORLD: unknown PET spell id %i", spellid); - return; - } - - if (spellInfo->StartRecoveryCategory > 0) - if (pet->ToCreature()->GetGlobalCooldown() > 0) - return; - - for (uint32 i = 0; i < 3; ++i) - { - if (spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_SRC || spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_DST || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) - return; - } - - // do not cast not learned spells - if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) - return; - - // Clear the flags as if owner clicked 'attack'. AI will reset them - // after AttackStart, even if spell failed - if (pet->GetCharmInfo()) - { - pet->GetCharmInfo()->SetIsAtStay(false); - pet->GetCharmInfo()->SetIsCommandAttack(true); - pet->GetCharmInfo()->SetIsReturning(false); - pet->GetCharmInfo()->SetIsFollowing(false); - } - - Spell *spell = new Spell(pet, spellInfo, false); - - SpellCastResult result = spell->CheckPetCast(unit_target); - - //auto turn to target unless possessed - if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed() && !pet->IsVehicle()) - { - if (unit_target) - { - pet->SetInFront(unit_target); - if (unit_target->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer((Player*)unit_target); - } - else if (Unit *unit_target2 = spell->m_targets.getUnitTarget()) - { - pet->SetInFront(unit_target2); - if (unit_target2->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer((Player*)unit_target2); - } - if (Unit* powner = pet->GetCharmerOrOwner()) - if (powner->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer(powner->ToPlayer()); - result = SPELL_CAST_OK; - } - - if (result == SPELL_CAST_OK) - { - pet->ToCreature()->AddCreatureSpellCooldown(spellid); - - unit_target = spell->m_targets.getUnitTarget(); - - //10% chance to play special pet attack talk, else growl - //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (pet->ToCreature()->isPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); - else - { - pet->SendPetAIReaction(guid1); - } - - if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->isPossessed() && !pet->IsVehicle()) - { - // This is true if pet has no target or has target but targets differs. - if (pet->getVictim() != unit_target) - { - if (pet->getVictim()) - pet->AttackStop(); - pet->GetMotionMaster()->Clear(); - if (pet->ToCreature()->IsAIEnabled) - pet->ToCreature()->AI()->AttackStart(unit_target); - } - } - - spell->prepare(&(spell->m_targets)); - } - else - { - if (pet->isPossessed() || pet->IsVehicle()) - Spell::SendCastResult(GetPlayer(),spellInfo,0,result); - else - pet->SendPetCastFail(spellid, result); - - if (!pet->ToCreature()->HasSpellCooldown(spellid)) - GetPlayer()->SendClearCooldown(spellid, pet); - - spell->finish(false); - delete spell; - - // reset specific flags in case of spell fail. AI will reset other flags - if (pet->GetCharmInfo()) - pet->GetCharmInfo()->SetIsCommandAttack(false); - } - break; - } - default: - sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); - } -} - -void WorldSession::HandlePetNameQuery(WorldPacket & recv_data) -{ - sLog.outDetail("HandlePetNameQuery. CMSG_PET_NAME_QUERY"); - - uint32 petnumber; - uint64 petguid; - - recv_data >> petnumber; - recv_data >> petguid; - - SendPetNameQuery(petguid,petnumber); -} - -void WorldSession::SendPetNameQuery(uint64 petguid, uint32 petnumber) -{ - Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); - if (!pet) - { - WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+7+1)); - data << uint32(petnumber); - data << "Unknown"; - data << uint32(0); - data << uint8(0); - _player->GetSession()->SendPacket(&data); - return; - } - - std::string name = pet->GetName(); - - WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+name.size()+1)); - data << uint32(petnumber); - data << name.c_str(); - data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); - - if (pet->isPet() && ((Pet*)pet)->GetDeclinedNames()) - { - data << uint8(1); - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - data << ((Pet*)pet)->GetDeclinedNames()->name[i]; - } - else - data << uint8(0); - - _player->GetSession()->SendPacket(&data); -} - -void WorldSession::HandlePetSetAction(WorldPacket & recv_data) -{ - sLog.outDetail("HandlePetSetAction. CMSG_PET_SET_ACTION"); - - uint64 petguid; - uint8 count; - - recv_data >> petguid; - - Unit* pet = ObjectAccessor::GetUnit(*_player, petguid); - - if (!pet || pet != _player->GetFirstControlled()) - { - sLog.outError("HandlePetSetAction: Unknown pet or pet owner."); - return; - } - - CharmInfo *charmInfo = pet->GetCharmInfo(); - if (!charmInfo) - { - sLog.outError("WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); - return; - } - - count = (recv_data.size() == 24) ? 2 : 1; - - uint32 position[2]; - uint32 data[2]; - bool move_command = false; - - for (uint8 i = 0; i < count; ++i) - { - recv_data >> position[i]; - recv_data >> data[i]; - - uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); - - //ignore invalid position - if (position[i] >= MAX_UNIT_ACTION_BAR_INDEX) - return; - - // in the normal case, command and reaction buttons can only be moved, not removed - // at moving count == 2, at removing count == 1 - // ignore attempt to remove command|reaction buttons (not possible at normal case) - if (act_state == ACT_COMMAND || act_state == ACT_REACTION) - { - if (count == 1) - return; - - move_command = true; - } - } - - // check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness) - if (move_command) - { - uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]); - if (act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION) - { - uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]); - UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]); - if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() || - act_state_0 != actionEntry_1->GetType()) - return; - } - - uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]); - if (act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION) - { - uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]); - UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]); - if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() || - act_state_1 != actionEntry_0->GetType()) - return; - } - } - - for (uint8 i = 0; i < count; ++i) - { - uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]); - uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); - - sLog.outDetail("Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position[i], spell_id, uint32(act_state)); - - //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add - if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) - { - //sign for autocast - if (act_state == ACT_ENABLED && spell_id) - { - if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet()) - ((Pet*)pet)->ToggleAutocast(spell_id, true); - else - charmInfo->ToggleCreatureAutocast(spell_id, true); - } - //sign for no/turn off autocast - else if (act_state == ACT_DISABLED && spell_id) - { - if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet()) - ((Pet*)pet)->ToggleAutocast(spell_id, false); - else - charmInfo->ToggleCreatureAutocast(spell_id, false); - - } - - charmInfo->SetActionBar(position[i],spell_id,ActiveStates(act_state)); - } - } -} - -void WorldSession::HandlePetRename(WorldPacket & recv_data) -{ - sLog.outDetail("HandlePetRename. CMSG_PET_RENAME"); - - uint64 petguid; - uint8 isdeclined; - - std::string name; - DeclinedName declinedname; - - recv_data >> petguid; - recv_data >> name; - recv_data >> isdeclined; - - Pet* pet = ObjectAccessor::GetPet(petguid); - // check it! - if (!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || - !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || - pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) - return; - - PetNameInvalidReason res = ObjectMgr::CheckPetName(name); - if (res != PET_NAME_SUCCESS) - { - SendPetNameInvalid(res, name, NULL); - return; - } - - if (objmgr.IsReservedName(name)) - { - SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); - return; - } - - pet->SetName(name); - - Unit *owner = pet->GetOwner(); - if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) - owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); - - pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); - - if (isdeclined) - { - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - { - recv_data >> declinedname.name[i]; - } - - std::wstring wname; - Utf8toWStr(name, wname); - if (!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname,0),declinedname)) - { - SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); - return; - } - } - - CharacterDatabase.BeginTransaction(); - if (isdeclined) - { - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - CharacterDatabase.escape_string(declinedname.name[i]); - CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); - CharacterDatabase.PExecute("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", - pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); - } - - CharacterDatabase.escape_string(name); - CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); - CharacterDatabase.CommitTransaction(); - - pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); -} - -void WorldSession::HandlePetAbandon(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; //pet guid - sLog.outDetail("HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid)); - - if (!_player->IsInWorld()) - return; - - // pet/charmed - Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - if (pet) - { - if (pet->isPet()) - { - if (pet->GetGUID() == _player->GetPetGUID()) - { - uint32 feelty = pet->GetPower(POWER_HAPPINESS); - pet->SetPower(POWER_HAPPINESS ,(feelty-50000) > 0 ?(feelty-50000) : 0); - } - - _player->RemovePet((Pet*)pet,PET_SAVE_AS_DELETED); - } - else if (pet->GetGUID() == _player->GetCharmGUID()) - _player->StopCastingCharm(); - } -} - -void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) -{ - sLog.outDetail("CMSG_PET_SPELL_AUTOCAST"); - uint64 guid; - uint32 spellid; - uint8 state; //1 for on, 0 for off - recvPacket >> guid >> spellid >> state; - - if (!_player->GetGuardianPet() && !_player->GetCharm()) - return; - - if (ObjectAccessor::FindPlayer(guid)) - return; - - Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); - - if (!pet || (pet != _player->GetGuardianPet() && pet != _player->GetCharm())) - { - sLog.outError("HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName()); - return; - } - - // do not add not learned spells/ passive spells - if (!pet->HasSpell(spellid) || IsAutocastableSpell(spellid)) - return; - - CharmInfo *charmInfo = pet->GetCharmInfo(); - if (!charmInfo) - { - sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); - return; - } - - if (pet->isPet()) - ((Pet*)pet)->ToggleAutocast(spellid, state); - else - pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state); - - charmInfo->SetSpellAutocast(spellid,state); -} - -void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) -{ - sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); - - uint64 guid; - uint32 spellid; - uint8 cast_count; - uint8 unk_flags; // flags (if 0x02 - some additional data are received) - - recvPacket >> guid >> cast_count >> spellid >> unk_flags; - - sLog.outDebug("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags); - - // This opcode is also sent from charmed and possessed units (players and creatures) - if (!_player->GetGuardianPet() && !_player->GetCharm()) - return; - - Unit* caster = ObjectAccessor::GetUnit(*_player, guid); - - if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm())) - { - sLog.outError("HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName()); - return; - } - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); - if (!spellInfo) - { - sLog.outError("WORLD: unknown PET spell id %i", spellid); - return; - } - - if (spellInfo->StartRecoveryCategory > 0) //Check if spell is affected by GCD - if (caster->GetTypeId() == TYPEID_UNIT && caster->ToCreature()->GetGlobalCooldown() > 0) - { - caster->SendPetCastFail(spellid, SPELL_FAILED_NOT_READY); - return; - } - - // do not cast not learned spells - if (!caster->HasSpell(spellid) || IsPassiveSpell(spellid)) - return; - - SpellCastTargets targets; - if (!targets.read(&recvPacket,caster)) - return; - - caster->clearUnitState(UNIT_STAT_FOLLOW); - - Spell *spell = new Spell(caster, spellInfo, spellid == 33395); // water elemental can cast freeze as triggered - spell->m_cast_count = spellid == 33395 ? 0 : cast_count; // probably pending spell cast - spell->m_targets = targets; - - // TODO: need to check victim? - SpellCastResult result; - if (caster->m_movedPlayer) - result = spell->CheckPetCast(caster->m_movedPlayer->GetSelectedUnit()); - else - result = spell->CheckPetCast(NULL); - if (result == SPELL_CAST_OK) - { - if (caster->GetTypeId() == TYPEID_UNIT) - { - Creature* pet = caster->ToCreature(); - pet->AddCreatureSpellCooldown(spellid); - if (pet->isPet()) - { - Pet* p = (Pet*)pet; - // 10% chance to play special pet attack talk, else growl - // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); - else - pet->SendPetAIReaction(guid); - } - } - - spell->prepare(&(spell->m_targets)); - } - else - { - caster->SendPetCastFail(spellid, result); - if (caster->GetTypeId() == TYPEID_PLAYER) - { - if (!caster->ToPlayer()->HasSpellCooldown(spellid)) - GetPlayer()->SendClearCooldown(spellid, caster); - } - else - { - if (!caster->ToCreature()->HasSpellCooldown(spellid)) - GetPlayer()->SendClearCooldown(spellid, caster); - } - - spell->finish(false); - delete spell; - } -} - -void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName) -{ - WorldPacket data(SMSG_PET_NAME_INVALID, 4 + name.size() + 1 + 1); - data << uint32(error); - data << name; - if (declinedName) - { - data << uint8(1); - for (uint32 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - data << declinedName->name[i]; - } - else - data << uint8(0); - SendPacket(&data); -} - -void WorldSession::HandlePetLearnTalent(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_PET_LEARN_TALENT"); - - uint64 guid; - uint32 talent_id, requested_rank; - recv_data >> guid >> talent_id >> requested_rank; - - _player->LearnPetTalent(guid, talent_id, requested_rank); - _player->SendTalentsInfoData(true); -} - -void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_LEARN_PREVIEW_TALENTS_PET"); - - uint64 guid; - recv_data >> guid; - - uint32 talentsCount; - recv_data >> talentsCount; - - uint32 talentId, talentRank; - - for (uint32 i = 0; i < talentsCount; ++i) - { - recv_data >> talentId >> talentRank; - - _player->LearnPetTalent(guid, talentId, talentRank); - } - - _player->SendTalentsInfoData(true); -} diff --git a/src/server/game/Entities/Player/CharacterHandler.cpp b/src/server/game/Entities/Player/CharacterHandler.cpp deleted file mode 100644 index 416827d73ea..00000000000 --- a/src/server/game/Entities/Player/CharacterHandler.cpp +++ /dev/null @@ -1,1406 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "ObjectAccessor.h" -#include "ObjectMgr.h" -#include "SystemConfig.h" -#include "World.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Auth/md5.h" -#include "Database/DatabaseEnv.h" -#include "Database/DatabaseImpl.h" - -#include "ArenaTeam.h" -#include "Chat.h" -#include "Group.h" -#include "Guild.h" -#include "Language.h" -#include "Log.h" -#include "Opcodes.h" -#include "Player.h" -#include "PlayerDump.h" -#include "SharedDefines.h" -#include "SocialMgr.h" -#include "UpdateMask.h" -#include "Util.h" -#include "ScriptMgr.h" - -class LoginQueryHolder : public SqlQueryHolder -{ - private: - uint32 m_accountId; - uint64 m_guid; - public: - LoginQueryHolder(uint32 accountId, uint64 guid) - : m_accountId(accountId), m_guid(guid) { } - uint64 GetGuid() const { return m_guid; } - uint32 GetAccountId() const { return m_accountId; } - bool Initialize(); -}; - -bool LoginQueryHolder::Initialize() -{ - SetSize(MAX_PLAYER_LOGIN_QUERY); - - bool res = true; - - // NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure. - // !!! NOTE: including unused `zone`,`online` - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags," - "position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost," - "resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty," - "arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk," - "health, power1, power2, power3, power4, power5, power6, power7, instance_id, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT guid FROM group_member WHERE memberGuid =%u", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS,"SELECT quest FROM character_queststatus_weekly WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADREPUTATION, "SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADINVENTORY, "SELECT data,text,bag,slot,item,item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag,slot", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACTIONS, "SELECT a.button,a.action,a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activespec AND a.guid = '%u' ORDER BY button", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = '%u' AND (checked & 1)=0 AND deliver_time <= '" UI64FMTD "'", GUID_LOPART(m_guid),(uint64)time(NULL)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = '%u' AND (checked & 1)=0", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSOCIALLIST, "SELECT friend,flags,note FROM character_social WHERE guid = '%u' LIMIT 255", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADHOMEBIND, "SELECT map,zone,position_x,position_y,position_z FROM character_homebind WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS, "SELECT spell,item,time FROM character_spell_cooldown WHERE guid = '%u'", GUID_LOPART(m_guid)); - if (sWorld.getConfig(CONFIG_DECLINED_NAMES_USED)) - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid)); - // in other case still be dummy query - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, wons_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = '%u' ORDER BY setindex", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBGDATA, "SELECT instance_id, team, join_x, join_y, join_z, join_o, join_map, taxi_start, taxi_end, mount_spell FROM character_battleground_data WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGLYPHS, "SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 FROM character_glyphs WHERE guid='%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADTALENTS, "SELECT spell, spec FROM character_talent WHERE guid='%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA, "SELECT type, time, data FROM character_account_data WHERE guid='%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADRANDOMBG, "SELECT guid FROM character_battleground_random WHERE guid = '%u'", GUID_LOPART(m_guid)); - - return res; -} - -// don't call WorldSession directly -// it may get deleted before the query callbacks get executed -// instead pass an account id to this handler -class CharacterHandler -{ - - public: - void HandleCharEnumCallback(QueryResult_AutoPtr result, uint32 account) - { - WorldSession * session = sWorld.FindSession(account); - if (!session) - return; - session->HandleCharEnum(result); - } - void HandlePlayerLoginCallback(QueryResult_AutoPtr /*dummy*/, SqlQueryHolder * holder) - { - if (!holder) return; - WorldSession *session = sWorld.FindSession(((LoginQueryHolder*)holder)->GetAccountId()); - if (!session) - { - delete holder; - return; - } - session->HandlePlayerLogin((LoginQueryHolder*)holder); - } -} chrHandler; - -void WorldSession::HandleCharEnum(QueryResult_AutoPtr result) -{ - WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size - - uint8 num = 0; - - data << num; - - if (result) - { - do - { - uint32 guidlow = (*result)[0].GetUInt32(); - sLog.outDetail("Loading char guid %u from account %u.",guidlow,GetAccountId()); - if (Player::BuildEnumData(result, &data)) - ++num; - } - while (result->NextRow()); - } - - data.put(0, num); - - SendPacket(&data); -} - -void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) -{ - /// get all the data necessary for loading all characters (along with their pets) on the account - CharacterDatabase.AsyncPQuery(&chrHandler, &CharacterHandler::HandleCharEnumCallback, GetAccountId(), - !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? - // ------- Query Without Declined Names -------- - // 0 1 2 3 4 5 6 7 - "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " - // 8 9 10 11 12 13 14 - "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 - "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache " - "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' " - "LEFT JOIN guild_member ON characters.guid = guild_member.guid " - "WHERE characters.account = '%u' ORDER BY characters.guid" - : - // --------- Query With Declined Names --------- - // 0 1 2 3 4 5 6 7 - "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " - // 8 9 10 11 12 13 14 - "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 20 - "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_declinedname.genitive " - "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' " - "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid " - "LEFT JOIN guild_member ON characters.guid = guild_member.guid " - "WHERE characters.account = '%u' ORDER BY characters.guid", - PET_SAVE_AS_CURRENT,GetAccountId()); -} - -void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data) -{ - std::string name; - uint8 race_,class_; - - recv_data >> name; - - recv_data >> race_; - recv_data >> class_; - - WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases - - if (GetSecurity() == SEC_PLAYER) - { - if (uint32 mask = sWorld.getConfig(CONFIG_CHARACTERS_CREATING_DISABLED)) - { - bool disabled = false; - - uint32 team = Player::TeamForRace(race_); - switch(team) - { - case ALLIANCE: disabled = mask & (1<<0); break; - case HORDE: disabled = mask & (1<<1); break; - } - - if (disabled) - { - data << (uint8)CHAR_CREATE_DISABLED; - SendPacket(&data); - return; - } - } - } - - ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); - ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); - - if (!classEntry || !raceEntry) - { - data << (uint8)CHAR_CREATE_FAILED; - SendPacket(&data); - sLog.outError("Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); - return; - } - - // prevent character creating Expansion race without Expansion account - if (raceEntry->expansion > Expansion()) - { - data << (uint8)CHAR_CREATE_EXPANSION; - sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->expansion,race_); - SendPacket(&data); - return; - } - - // prevent character creating Expansion class without Expansion account - if (classEntry->expansion > Expansion()) - { - data << (uint8)CHAR_CREATE_EXPANSION_CLASS; - sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->expansion,class_); - SendPacket(&data); - return; - } - - // prevent character creating with invalid name - if (!normalizePlayerName(name)) - { - data << (uint8)CHAR_NAME_NO_NAME; - SendPacket(&data); - sLog.outError("Account:[%d] but tried to Create character with empty [name] ",GetAccountId()); - return; - } - - // check name limitations - uint8 res = ObjectMgr::CheckPlayerName(name,true); - if (res != CHAR_NAME_SUCCESS) - { - data << uint8(res); - SendPacket(&data); - return; - } - - if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name)) - { - data << (uint8)CHAR_NAME_RESERVED; - SendPacket(&data); - return; - } - - if (objmgr.GetPlayerGUIDByName(name)) - { - data << (uint8)CHAR_CREATE_NAME_IN_USE; - SendPacket(&data); - return; - } - - QueryResult_AutoPtr resultacct = LoginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); - if (resultacct) - { - Field *fields=resultacct->Fetch(); - uint32 acctcharcount = fields[0].GetUInt32(); - - if (acctcharcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) - { - data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; - SendPacket(&data); - return; - } - } - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", GetAccountId()); - uint8 charcount = 0; - if (result) - { - Field *fields=result->Fetch(); - charcount = fields[0].GetUInt8(); - - if (charcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_REALM)) - { - data << (uint8)CHAR_CREATE_SERVER_LIMIT; - SendPacket(&data); - return; - } - } - - // speedup check for heroic class disabled case - uint32 heroic_free_slots = sWorld.getConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM); - if (heroic_free_slots == 0 && GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) - { - data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; - SendPacket(&data); - return; - } - - // speedup check for heroic class disabled case - uint32 req_level_for_heroic = sWorld.getConfig(CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING); - if (GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; - SendPacket(&data); - return; - } - - bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; - uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); - - bool have_same_race = false; - - // if 0 then allowed creating without any characters - bool have_req_level_for_heroic = (req_level_for_heroic == 0); - - if (!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) - { - QueryResult_AutoPtr result2 = CharacterDatabase.PQuery("SELECT level,race,class FROM characters WHERE account = '%u' %s", - GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1"); - if (result2) - { - uint32 team_= Player::TeamForRace(race_); - - Field* field = result2->Fetch(); - uint8 acc_race = field[1].GetUInt32(); - - if (GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) - { - uint8 acc_class = field[2].GetUInt32(); - if (acc_class == CLASS_DEATH_KNIGHT) - { - if (heroic_free_slots > 0) - --heroic_free_slots; - - if (heroic_free_slots == 0) - { - data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; - SendPacket(&data); - return; - } - } - - if (!have_req_level_for_heroic) - { - uint32 acc_level = field[0].GetUInt32(); - if (acc_level >= req_level_for_heroic) - have_req_level_for_heroic = true; - } - } - - // need to check team only for first character - // TODO: what to if account already has characters of both races? - if (!AllowTwoSideAccounts) - { - uint32 acc_team=0; - if (acc_race > 0) - acc_team = Player::TeamForRace(acc_race); - - if (acc_team != team_) - { - data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; - SendPacket(&data); - return; - } - } - - // search same race for cinematic or same class if need - // TODO: check if cinematic already shown? (already logged in?; cinematic field) - while ((skipCinematics == 1 && !have_same_race) || class_ == CLASS_DEATH_KNIGHT) - { - if (!result2->NextRow()) - break; - - field = result2->Fetch(); - acc_race = field[1].GetUInt32(); - - if (!have_same_race) - have_same_race = race_ == acc_race; - - if (GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) - { - uint8 acc_class = field[2].GetUInt32(); - if (acc_class == CLASS_DEATH_KNIGHT) - { - if (heroic_free_slots > 0) - --heroic_free_slots; - - if (heroic_free_slots == 0) - { - data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; - SendPacket(&data); - return; - } - } - - if (!have_req_level_for_heroic) - { - uint32 acc_level = field[0].GetUInt32(); - if (acc_level >= req_level_for_heroic) - have_req_level_for_heroic = true; - } - } - } - } - } - - if (GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && !have_req_level_for_heroic) - { - data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; - SendPacket(&data); - return; - } - - // extract other data required for player creating - uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; - recv_data >> gender >> skin >> face; - recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; - - if (recv_data.rpos() < recv_data.wpos()) - { - uint8 unk; - recv_data >> unk; - sLog.outDebug("Character creation %s (account %u) has unhandled tail data: [%u]", name.c_str(), GetAccountId(), unk); - } - - Player * pNewChar = new Player(this); - if (!pNewChar->Create(objmgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId)) - { - // Player not create (race/class problem?) - pNewChar->CleanupsBeforeDelete(); - delete pNewChar; - - data << (uint8)CHAR_CREATE_ERROR; - SendPacket(&data); - - return; - } - - if ((have_same_race && skipCinematics == 1) || skipCinematics == 2) - pNewChar->setCinematic(1); // not show intro - - pNewChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login - - // Player created, save it now - pNewChar->SaveToDB(); - charcount+=1; - - LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); - LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); - - pNewChar->CleanupsBeforeDelete(); - - data << (uint8)CHAR_CREATE_SUCCESS; - SendPacket(&data); - - std::string IP_str = GetRemoteAddress(); - sLog.outBasic("Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), pNewChar->GetGUIDLow()); - sLog.outChar("Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), pNewChar->GetGUIDLow()); - delete pNewChar; // created only to call SaveToDB() - -} - -void WorldSession::HandleCharDeleteOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - // can't delete loaded character - if (objmgr.GetPlayer(guid)) - return; - - uint32 accountId = 0; - std::string name; - - // is guild leader - if (objmgr.GetGuildByLeader(guid)) - { - WorldPacket data(SMSG_CHAR_DELETE, 1); - data << (uint8)CHAR_DELETE_FAILED_GUILD_LEADER; - SendPacket(&data); - return; - } - - // is arena team captain - if (objmgr.GetArenaTeamByCaptain(guid)) - { - WorldPacket data(SMSG_CHAR_DELETE, 1); - data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN; - SendPacket(&data); - return; - } - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account,name FROM characters WHERE guid='%u'", GUID_LOPART(guid)); - if (result) - { - Field *fields = result->Fetch(); - accountId = fields[0].GetUInt32(); - name = fields[1].GetCppString(); - } - - // prevent deleting other players' characters using cheating tools - if (accountId != GetAccountId()) - return; - - std::string IP_str = GetRemoteAddress(); - sLog.outDetail("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid)); - sLog.outChar("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid)); - - if (sLog.IsOutCharDump()) // optimize GetPlayerDump call - { - std::string dump = PlayerDumpWriter().GetDump(GUID_LOPART(guid)); - sLog.outCharDump(dump.c_str(),GetAccountId(),GUID_LOPART(guid),name.c_str()); - } - - Player::DeleteFromDB(guid, GetAccountId()); - - WorldPacket data(SMSG_CHAR_DELETE, 1); - data << (uint8)CHAR_DELETE_SUCCESS; - SendPacket(&data); -} - -void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data) -{ - if (PlayerLoading() || GetPlayer() != NULL) - { - sLog.outError("Player tryes to login again, AccountId = %d",GetAccountId()); - return; - } - - m_playerLoading = true; - uint64 playerGuid = 0; - - DEBUG_LOG("WORLD: Recvd Player Logon Message"); - - recv_data >> playerGuid; - - LoginQueryHolder *holder = new LoginQueryHolder(GetAccountId(), playerGuid); - if (!holder->Initialize()) - { - delete holder; // delete all unprocessed queries - m_playerLoading = false; - return; - } - - CharacterDatabase.DelayQueryHolder(&chrHandler, &CharacterHandler::HandlePlayerLoginCallback, holder); -} - -void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) -{ - uint64 playerGuid = holder->GetGuid(); - - Player* pCurrChar = new Player(this); - // for send server info and strings (config) - ChatHandler chH = ChatHandler(pCurrChar); - - // "GetAccountId() == db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) - if (!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) - { - KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick - delete pCurrChar; // delete it manually - delete holder; // delete all unprocessed queries - m_playerLoading = false; - return; - } - - pCurrChar->GetMotionMaster()->Initialize(); - - SetPlayer(pCurrChar); - - pCurrChar->SendDungeonDifficulty(false); - - WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20); - data << pCurrChar->GetMapId(); - data << pCurrChar->GetPositionX(); - data << pCurrChar->GetPositionY(); - data << pCurrChar->GetPositionZ(); - data << pCurrChar->GetOrientation(); - SendPacket(&data); - - // load player specific part before send times - LoadAccountData(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA),PER_CHARACTER_CACHE_MASK); - SendAccountDataTimes(PER_CHARACTER_CACHE_MASK); - - data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 - data << uint8(2); // unknown value - data << uint8(0); // enable(1)/disable(0) voice chat interface in client - SendPacket(&data); - - // Send MOTD - { - data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 - data << (uint32)0; - - uint32 linecount=0; - std::string str_motd = sWorld.GetMotd(); - std::string::size_type pos, nextpos; - - pos = 0; - while ((nextpos= str_motd.find('@',pos)) != std::string::npos) - { - if (nextpos != pos) - { - data << str_motd.substr(pos,nextpos-pos); - ++linecount; - } - pos = nextpos+1; - } - - if (posGetGUIDLow()); - QueryResult_AutoPtr resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); - - if (resultGuild) - { - Field *fields = resultGuild->Fetch(); - pCurrChar->SetInGuild(fields[0].GetUInt32()); - pCurrChar->SetRank(fields[1].GetUInt32()); - } - else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership - { - pCurrChar->SetInGuild(0); - pCurrChar->SetRank(0); - } - - if (pCurrChar->GetGuildId() != 0) - { - Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); - if (guild) - { - data.Initialize(SMSG_GUILD_EVENT, (1+1+guild->GetMOTD().size()+1)); - data << uint8(GE_MOTD); - data << uint8(1); - data << guild->GetMOTD(); - SendPacket(&data); - DEBUG_LOG("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)"); - - guild->DisplayGuildBankTabsInfo(this); - - guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetGUID(), 1, pCurrChar->GetName(), "", ""); - } - else - { - // remove wrong guild data - sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); - pCurrChar->SetInGuild(0); - } - } - - data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4); - data << uint32(0); - data << uint32(0); - SendPacket(&data); - - pCurrChar->SendInitialPacketsBeforeAddToMap(); - - //Show cinematic at the first time that player login - if (!pCurrChar->getCinematic()) - { - pCurrChar->setCinematic(1); - - if (ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) - { - if (cEntry->CinematicSequence) - pCurrChar->SendCinematicStart(cEntry->CinematicSequence); - else if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) - pCurrChar->SendCinematicStart(rEntry->CinematicSequence); - - // send new char string if not empty - if (!sWorld.GetNewCharString().empty()) - chH.PSendSysMessage(sWorld.GetNewCharString().c_str()); - } - } - - if (!pCurrChar->GetMap()->Add(pCurrChar) || !pCurrChar->CheckInstanceLoginValid()) - { - AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId()); - if (at) - pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); - else - pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); - } - - ObjectAccessor::Instance().AddObject(pCurrChar); - //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); - - pCurrChar->SendInitialPacketsAfterAddToMap(); - - CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); - LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId()); - pCurrChar->SetInGameTime(getMSTime()); - - // announce group about member online (must be after add to player list to receive announce to self) - if (Group *group = pCurrChar->GetGroup()) - { - //pCurrChar->groupInfo.group->SendInit(this); // useless - group->SendUpdate(); - group->ResetMaxEnchantingLevel(); - } - - // friend status - sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); - - // Place character in world (and load zone) before some object loading - pCurrChar->LoadCorpse(); - - // setting Ghost+speed if dead - if (pCurrChar->m_deathState != ALIVE) - { - // not blizz like, we must correctly save and load player instead... - if (pCurrChar->getRace() == RACE_NIGHTELF) - pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) - pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) - - pCurrChar->SetMovement(MOVE_WATER_WALK); - } - - pCurrChar->ContinueTaxiFlight(); - - // reset for all pets before pet loading - if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) - Pet::resetTalentsForAllPetsOf(pCurrChar); - - // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned) - pCurrChar->LoadPet(); - - // Set FFA PvP for non GM in non-rest mode - if (sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING)) - pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - - if (pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) - pCurrChar->SetContestedPvP(); - - // Apply at_login requests - if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) - { - pCurrChar->resetSpells(); - SendNotification(LANG_RESET_SPELLS); - } - - if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) - { - pCurrChar->resetTalents(true); - pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state - SendNotification(LANG_RESET_TALENTS); - } - - if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST)) - pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST); - - // show time before shutdown if shutdown planned. - if (sWorld.IsShutdowning()) - sWorld.ShutdownMsg(true,pCurrChar); - - if (sWorld.getConfig(CONFIG_ALL_TAXI_PATHS)) - pCurrChar->SetTaxiCheater(true); - - if (pCurrChar->isGameMaster()) - SendNotification(LANG_GM_ON); - - std::string IP_str = GetRemoteAddress(); - sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (GUID: %u)", - GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow()); - - if (!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED)) - pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); - - m_playerLoading = false; - - //Hook for OnLogin Event - sScriptMgr.OnLogin(pCurrChar); - delete holder; -} - -void WorldSession::HandleSetFactionAtWar(WorldPacket & recv_data) -{ - DEBUG_LOG("WORLD: Received CMSG_SET_FACTION_ATWAR"); - - uint32 repListID; - uint8 flag; - - recv_data >> repListID; - recv_data >> flag; - - GetPlayer()->GetReputationMgr().SetAtWar(repListID,flag); -} - -//I think this function is never used :/ I dunno, but i guess this opcode not exists -void WorldSession::HandleSetFactionCheat(WorldPacket & /*recv_data*/) -{ - sLog.outError("WORLD SESSION: HandleSetFactionCheat, not expected call, please report."); - /* - uint32 FactionID; - uint32 Standing; - - recv_data >> FactionID; - recv_data >> Standing; - - std::list::iterator itr; - - for (itr = GetPlayer()->factions.begin(); itr != GetPlayer()->factions.end(); ++itr) - { - if (itr->ReputationListID == FactionID) - { - itr->Standing += Standing; - itr->Flags = (itr->Flags | 1); - break; - } - } - */ - GetPlayer()->GetReputationMgr().SendStates(); -} - -void WorldSession::HandleMeetingStoneInfo(WorldPacket & /*recv_data*/) -{ - DEBUG_LOG("WORLD: Received CMSG_MEETING_STONE_INFO"); - - //SendLfgUpdate(0, 0, 0); -} - -void WorldSession::HandleTutorialFlag(WorldPacket & recv_data) -{ - uint32 iFlag; - recv_data >> iFlag; - - uint32 wInt = (iFlag / 32); - if (wInt >= 8) - { - //sLog.outError("CHEATER? Account:[%d] Guid[%u] tried to send wrong CMSG_TUTORIAL_FLAG", GetAccountId(),GetGUID()); - return; - } - uint32 rInt = (iFlag % 32); - - uint32 tutflag = GetTutorialInt(wInt); - tutflag |= (1 << rInt); - SetTutorialInt(wInt, tutflag); - - //sLog.outDebug("Received Tutorial Flag Set {%u}.", iFlag); -} - -void WorldSession::HandleTutorialClear(WorldPacket & /*recv_data*/) -{ - for (int i = 0; i < 8; ++i) - SetTutorialInt(i, 0xFFFFFFFF); -} - -void WorldSession::HandleTutorialReset(WorldPacket & /*recv_data*/) -{ - for (int i = 0; i < 8; ++i) - SetTutorialInt(i, 0x00000000); -} - -void WorldSession::HandleSetWatchedFactionOpcode(WorldPacket & recv_data) -{ - DEBUG_LOG("WORLD: Received CMSG_SET_WATCHED_FACTION"); - uint32 fact; - recv_data >> fact; - GetPlayer()->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fact); -} - -void WorldSession::HandleSetFactionInactiveOpcode(WorldPacket & recv_data) -{ - DEBUG_LOG("WORLD: Received CMSG_SET_FACTION_INACTIVE"); - uint32 replistid; - uint8 inactive; - recv_data >> replistid >> inactive; - - _player->GetReputationMgr().SetInactive(replistid, inactive); -} - -void WorldSession::HandleShowingHelmOpcode(WorldPacket & /*recv_data*/) -{ - DEBUG_LOG("CMSG_SHOWING_HELM for %s", _player->GetName()); - _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM); -} - -void WorldSession::HandleShowingCloakOpcode(WorldPacket & /*recv_data*/) -{ - DEBUG_LOG("CMSG_SHOWING_CLOAK for %s", _player->GetName()); - _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK); -} - -void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data) -{ - uint64 guid; - std::string newname; - - recv_data >> guid; - recv_data >> newname; - - // prevent character rename to invalid name - if (!normalizePlayerName(newname)) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(CHAR_NAME_NO_NAME); - SendPacket(&data); - return; - } - - uint8 res = ObjectMgr::CheckPlayerName(newname,true); - if (res != CHAR_NAME_SUCCESS) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(res); - SendPacket(&data); - return; - } - - // check name limitations - if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(CHAR_NAME_RESERVED); - SendPacket(&data); - return; - } - - std::string escaped_newname = newname; - CharacterDatabase.escape_string(escaped_newname); - - // make sure that the character belongs to the current account, that rename at login is enabled - // and that there is no character with the desired new name - CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, - GetAccountId(), newname, - "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", - GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str() -); -} - -void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string newname) -{ - WorldSession * session = sWorld.FindSession(accountId); - if (!session) - return; - - if (!result) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << uint8(CHAR_CREATE_ERROR); - session->SendPacket(&data); - return; - } - - uint32 guidLow = result->Fetch()[0].GetUInt32(); - uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); - std::string oldname = result->Fetch()[1].GetCppString(); - - CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow); - CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow); - - sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str()); - - WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1)); - data << uint8(RESPONSE_SUCCESS); - data << uint64(guid); - data << newname; - session->SendPacket(&data); -} - -void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) -{ - uint64 guid; - - recv_data >> guid; - - // not accept declined names for unsupported languages - std::string name; - if (!objmgr.GetPlayerNameByGUID(guid, name)) - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - std::wstring wname; - if (!Utf8toWStr(name, wname)) - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - if (!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - std::string name2; - DeclinedName declinedname; - - recv_data >> name2; - - if (name2 != name) // character have different name - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - { - recv_data >> declinedname.name[i]; - if (!normalizePlayerName(declinedname.name[i])) - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - } - - if (!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname, 0), declinedname)) - { - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(1); - data << uint64(guid); - SendPacket(&data); - return; - } - - for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - CharacterDatabase.escape_string(declinedname.name[i]); - - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid)); - CharacterDatabase.PExecute("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%s','%s','%s','%s','%s')", - GUID_LOPART(guid), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); - CharacterDatabase.CommitTransaction(); - - WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); - data << uint32(0); // OK - data << uint64(guid); - SendPacket(&data); -} - -void WorldSession::HandleAlterAppearance(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_ALTER_APPEARANCE"); - - uint32 Hair, Color, FacialHair, SkinColor; - recv_data >> Hair >> Color >> FacialHair >> SkinColor; - - BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair); - - if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->getGender()) - return; - - BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair); - - if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender()) - return; - - BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(SkinColor); - - if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->getGender())) - return; - - uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id, bs_skinColor); - - // 0 - ok - // 1,3 - not enough money - // 2 - you have to seat on barber chair - if (_player->GetMoney() < Cost) - { - WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); - data << uint32(1); // no money - SendPacket(&data); - return; - } - else - { - WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); - data << uint32(0); // ok - SendPacket(&data); - } - - _player->ModifyMoney(-int32(Cost)); // it isn't free - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, Cost); - - _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id)); - _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color)); - _player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id)); - if (bs_skinColor) - _player->SetByteValue(PLAYER_BYTES, 0, uint8(bs_skinColor->hair_id)); - - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); - - _player->SetStandState(0); // stand up -} - -void WorldSession::HandleRemoveGlyph(WorldPacket & recv_data) -{ - uint32 slot; - recv_data >> slot; - - if (slot >= MAX_GLYPH_SLOT_INDEX) - { - sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot); - return; - } - - if (uint32 glyph = _player->GetGlyph(slot)) - { - if (GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) - { - _player->RemoveAurasDueToSpell(gp->SpellId); - _player->SetGlyph(slot, 0); - _player->SendTalentsInfoData(false); - } - } -} - -void WorldSession::HandleCharCustomize(WorldPacket& recv_data) -{ - uint64 guid; - std::string newname; - - recv_data >> guid; - recv_data >> newname; - - uint8 gender, skin, face, hairStyle, hairColor, facialHair; - recv_data >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face; - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); - if (!result) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - - Field *fields = result->Fetch(); - uint32 at_loginFlags = fields[0].GetUInt32(); - - if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE)) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_CREATE_ERROR); - SendPacket(&data); - return; - } - - // prevent character rename to invalid name - if (!normalizePlayerName(newname)) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_NAME_NO_NAME); - SendPacket(&data); - return; - } - - uint8 res = ObjectMgr::CheckPlayerName(newname,true); - if (res != CHAR_NAME_SUCCESS) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(res); - SendPacket(&data); - return; - } - - // check name limitations - if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_NAME_RESERVED); - SendPacket(&data); - return; - } - - // character with this name already exist - if (uint64 newguid = objmgr.GetPlayerGUIDByName(newname)) - { - if (newguid != guid) - { - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); - data << uint8(CHAR_CREATE_NAME_IN_USE); - SendPacket(&data); - return; - } - } - - CharacterDatabase.escape_string(newname); - if (QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid ='%u'", GUID_LOPART(guid))) - { - std::string oldname = result->Fetch()[0].GetCppString(); - std::string IP_str = GetRemoteAddress(); - sLog.outChar("Account: %d (IP: %s), Character[%s] (guid:%u) Customized to: %s", GetAccountId(), IP_str.c_str(), oldname.c_str(), GUID_LOPART(guid), newname.c_str()); - } - Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); - CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_CUSTOMIZE), GUID_LOPART(guid)); - CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); - - WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newname.size()+1)+6); - data << uint8(RESPONSE_SUCCESS); - data << uint64(guid); - data << newname; - data << uint8(gender); - data << uint8(skin); - data << uint8(face); - data << uint8(hairStyle); - data << uint8(hairColor); - data << uint8(facialHair); - SendPacket(&data); -} - -void WorldSession::HandleEquipmentSetSave(WorldPacket &recv_data) -{ - sLog.outDebug("CMSG_EQUIPMENT_SET_SAVE"); - - uint64 setGuid; - if (!recv_data.readPackGUID(setGuid)) - return; - - uint32 index; - recv_data >> index; - if (index >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount - return; - - std::string name; - recv_data >> name; - - std::string iconName; - recv_data >> iconName; - - EquipmentSet eqSet; - - eqSet.Guid = setGuid; - eqSet.Name = name; - eqSet.IconName = iconName; - eqSet.state = EQUIPMENT_SET_NEW; - - for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) - { - uint64 itemGuid; - if (!recv_data.readPackGUID(itemGuid)) - return; - - Item *item = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); - - if (!item && itemGuid) // cheating check 1 - return; - - if (item && item->GetGUID() != itemGuid) // cheating check 2 - return; - - eqSet.Items[i] = GUID_LOPART(itemGuid); - } - - _player->SetEquipmentSet(index, eqSet); -} - -void WorldSession::HandleEquipmentSetDelete(WorldPacket &recv_data) -{ - sLog.outDebug("CMSG_EQUIPMENT_SET_DELETE"); - - uint64 setGuid; - if (!recv_data.readPackGUID(setGuid)) - return; - - _player->DeleteEquipmentSet(setGuid); -} - -void WorldSession::HandleEquipmentSetUse(WorldPacket &recv_data) -{ - sLog.outDebug("CMSG_EQUIPMENT_SET_USE"); - recv_data.hexlike(); - - for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) - { - uint64 itemGuid; - if (!recv_data.readPackGUID(itemGuid)) - return; - - uint8 srcbag, srcslot; - recv_data >> srcbag >> srcslot; - - sLog.outDebug("Item " UI64FMTD ": srcbag %u, srcslot %u", itemGuid, srcbag, srcslot); - - Item *item = _player->GetItemByGuid(itemGuid); - - uint16 dstpos = i | (INVENTORY_SLOT_BAG_0 << 8); - - if (!item) - { - Item *uItem = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); - if (!uItem) - continue; - - ItemPosCountVec sDest; - uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, uItem, false); - if (msg == EQUIP_ERR_OK) - { - _player->RemoveItem(INVENTORY_SLOT_BAG_0, i, true); - _player->StoreItem(sDest, uItem, true); - } - else - _player->SendEquipError(msg, uItem, NULL); - - continue; - } - - if (item->GetPos() == dstpos) - continue; - - _player->SwapItem(item->GetPos(), dstpos); - } - - WorldPacket data(SMSG_EQUIPMENT_SET_USE_RESULT, 1); - data << uint8(0); // 4 - equipment swap failed - inventory is full - SendPacket(&data); -} - -void WorldSession::HandleOnPVPKill(Player *killed) -{ - sScriptMgr.OnPVPKill(GetPlayer(), killed); -} - -bool WorldSession::HandleOnPlayerChat(const char *text) -{ - return sScriptMgr.OnPlayerChat(GetPlayer(), text); -} - -uint32 WorldSession::HandleOnGetXP(uint32 amount) -{ - return sScriptMgr.OnGetXP(GetPlayer(), amount); -} - -int32 WorldSession::HandleOnGetMoney(int32 amount) -{ - return sScriptMgr.OnGetMoney(GetPlayer(), amount); -} - -void WorldSession::HandleOnAreaChange(AreaTableEntry const *pArea) -{ - sScriptMgr.OnAreaChange(GetPlayer(), pArea); -} - -bool WorldSession::HandleOnItemClick(Item *pItem) -{ - return sScriptMgr.OnItemClick(GetPlayer(), pItem); -} - -bool WorldSession::HandleOnItemOpen(Item *pItem) -{ - return sScriptMgr.OnItemOpen(GetPlayer(), pItem); -} - -bool WorldSession::HandleOnGoClick(GameObject *pGameObject) -{ - return sScriptMgr.OnGoClick(GetPlayer(), pGameObject); -} - -void WorldSession::HandleOnCreatureKill(Creature *pCreature) -{ - sScriptMgr.OnCreatureKill(GetPlayer(), pCreature); -} diff --git a/src/server/game/Entities/Player/DuelHandler.cpp b/src/server/game/Entities/Player/DuelHandler.cpp deleted file mode 100644 index 99c8a774b03..00000000000 --- a/src/server/game/Entities/Player/DuelHandler.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Log.h" -#include "Opcodes.h" -#include "UpdateData.h" -#include "Player.h" - -void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket) -{ - uint64 guid; - Player *pl; - Player *plTarget; - - if (!GetPlayer()->duel) // ignore accept from duel-sender - return; - - recvPacket >> guid; - - pl = GetPlayer(); - plTarget = pl->duel->opponent; - - if (pl == pl->duel->initiator || !plTarget || pl == plTarget || pl->duel->startTime != 0 || plTarget->duel->startTime != 0) - return; - - //sLog.outDebug("WORLD: received CMSG_DUEL_ACCEPTED"); - DEBUG_LOG("Player 1 is: %u (%s)", pl->GetGUIDLow(),pl->GetName()); - DEBUG_LOG("Player 2 is: %u (%s)", plTarget->GetGUIDLow(),plTarget->GetName()); - - time_t now = time(NULL); - pl->duel->startTimer = now; - plTarget->duel->startTimer = now; - - pl->SendDuelCountdown(3000); - plTarget->SendDuelCountdown(3000); -} - -void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket) -{ - //sLog.outDebug("WORLD: received CMSG_DUEL_CANCELLED"); - - // no duel requested - if (!GetPlayer()->duel) - return; - - // player surrendered in a duel using /forfeit - if (GetPlayer()->duel->startTime != 0) - { - GetPlayer()->CombatStopWithPets(true); - if (GetPlayer()->duel->opponent) - GetPlayer()->duel->opponent->CombatStopWithPets(true); - - GetPlayer()->CastSpell(GetPlayer(), 7267, true); // beg - GetPlayer()->DuelComplete(DUEL_WON); - return; - } - - // player either discarded the duel using the "discard button" - // or used "/forfeit" before countdown reached 0 - uint64 guid; - recvPacket >> guid; - - GetPlayer()->DuelComplete(DUEL_INTERUPTED); -} diff --git a/src/server/game/Entities/Player/MiscHandler.cpp b/src/server/game/Entities/Player/MiscHandler.cpp deleted file mode 100644 index ea6f892c126..00000000000 --- a/src/server/game/Entities/Player/MiscHandler.cpp +++ /dev/null @@ -1,1721 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Language.h" -#include "Database/DatabaseEnv.h" -#include "Database/DatabaseImpl.h" -#include "WorldPacket.h" -#include "Opcodes.h" -#include "Log.h" -#include "Player.h" -#include "GossipDef.h" -#include "World.h" -#include "ObjectMgr.h" -#include "WorldSession.h" -#include "Auth/BigNumber.h" -#include "Auth/Sha1.h" -#include "UpdateData.h" -#include "LootMgr.h" -#include "Chat.h" -#include -#include "ObjectAccessor.h" -#include "Object.h" -#include "BattleGround.h" -#include "OutdoorPvP.h" -#include "Pet.h" -#include "SocialMgr.h" -#include "CellImpl.h" -#include "AccountMgr.h" -#include "Vehicle.h" -#include "CreatureAI.h" -#include "DBCEnums.h" -#include "ScriptMgr.h" -#include "MapManager.h" -#include "InstanceData.h" - -void WorldSession::HandleRepopRequestOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_REPOP_REQUEST Message"); - - recv_data.read_skip(); - - if (GetPlayer()->isAlive()||GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) - return; - - // the world update order is sessions, players, creatures - // the netcode runs in parallel with all of these - // creatures can kill players - // so if the server is lagging enough the player can - // release spirit after he's killed but before he is updated - if (GetPlayer()->getDeathState() == JUST_DIED) - { - sLog.outDebug("HandleRepopRequestOpcode: got request after player %s(%d) was killed and before he was updated", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); - GetPlayer()->KillPlayer(); - } - - //this is spirit release confirm? - GetPlayer()->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT, true); - GetPlayer()->BuildPlayerRepop(); - GetPlayer()->RepopAtGraveyard(); -} - -void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION"); - - uint32 gossipListId; - uint32 menuId; - uint64 guid; - std::string code = ""; - - recv_data >> guid >> menuId >> gossipListId; - - if (_player->PlayerTalkClass->GossipOptionCoded(gossipListId)) - { - // recheck - sLog.outBasic("reading string"); - recv_data >> code; - sLog.outBasic("string read: %s", code.c_str()); - } - - Creature *unit = NULL; - GameObject *go = NULL; - if (IS_CRE_OR_VEH_GUID(guid)) - { - unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) - { - sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - } - else if (IS_GAMEOBJECT_GUID(guid)) - { - go = _player->GetMap()->GetGameObject(guid); - if (!go) - { - sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - GameObject (GUID: %u) not found.", uint32(GUID_LOPART(guid))); - return; - } - } - else - { - sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - unsupported GUID type for highguid %u. lowpart %u.", uint32(GUID_HIPART(guid)), uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if ((unit && unit->GetCreatureInfo()->ScriptID != unit->LastUsedScriptID) || (go && go->GetGOInfo()->ScriptId != go->LastUsedScriptID)) - { - sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - Script reloaded while in use, ignoring and set new scipt id"); - if (unit) - unit->LastUsedScriptID = unit->GetCreatureInfo()->ScriptID; - if (go) - go->LastUsedScriptID = go->GetGOInfo()->ScriptId; - _player->PlayerTalkClass->CloseGossip(); - return; - } - if (!code.empty()) - { - if (unit) - { - if (!sScriptMgr.GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId), code.c_str())) - _player->OnGossipSelect(unit, gossipListId, menuId); - } - else - sScriptMgr.GOSelectWithCode(_player, go, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId), code.c_str()); - } - else - { - if (unit) - { - if (!sScriptMgr.GossipSelect(_player, unit, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId))) - _player->OnGossipSelect(unit, gossipListId, menuId); - } - else - sScriptMgr.GOSelect(_player, go, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId)); - } -} - -void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_WHO Message"); - //recv_data.hexlike(); - - uint32 clientcount = 0; - - uint32 level_min, level_max, racemask, classmask, zones_count, str_count; - uint32 zoneids[10]; // 10 is client limit - std::string player_name, guild_name; - - recv_data >> level_min; // maximal player level, default 0 - recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) - recv_data >> player_name; // player name, case sensitive... - - recv_data >> guild_name; // guild name, case sensitive... - - recv_data >> racemask; // race mask - recv_data >> classmask; // class mask - recv_data >> zones_count; // zones count, client limit = 10 (2.0.10) - - if (zones_count > 10) - return; // can't be received from real client or broken packet - - for (uint32 i = 0; i < zones_count; ++i) - { - uint32 temp; - recv_data >> temp; // zone id, 0 if zone is unknown... - zoneids[i] = temp; - sLog.outDebug("Zone %u: %u", i, zoneids[i]); - } - - recv_data >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) - - if (str_count > 4) - return; // can't be received from real client or broken packet - - sLog.outDebug("Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", level_min, level_max, player_name.c_str(), guild_name.c_str(), racemask, classmask, zones_count, str_count); - - std::wstring str[4]; // 4 is client limit - for (uint32 i = 0; i < str_count; ++i) - { - std::string temp; - recv_data >> temp; // user entered string, it used as universal search pattern(guild+player name)? - - if (!Utf8toWStr(temp,str[i])) - continue; - - wstrToLower(str[i]); - - sLog.outDebug("String %u: %s", i, temp.c_str()); - } - - std::wstring wplayer_name; - std::wstring wguild_name; - if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name))) - return; - wstrToLower(wplayer_name); - wstrToLower(wguild_name); - - // client send in case not set max level value 100 but Trinity supports 255 max level, - // update it to show GMs with characters after 100 level - if (level_max >= MAX_LEVEL) - level_max = STRONG_MAX_LEVEL; - - uint32 team = _player->GetTeam(); - uint32 security = GetSecurity(); - bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); - uint32 gmLevelInWhoList = sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); - - WorldPacket data(SMSG_WHO, 50); // guess size - data << uint32(clientcount); // clientcount place holder, listed count - data << uint32(clientcount); // clientcount place holder, online count - - ObjectAccessor::Guard guard(*HashMapHolder::GetLock()); - HashMapHolder::MapType& m = ObjectAccessor::Instance().GetPlayers(); - for (HashMapHolder::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) - { - if (security == SEC_PLAYER) - { - // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST - if (itr->second->GetTeam() != team && !allowTwoSideWhoList) - continue; - - // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST - if ((itr->second->GetSession()->GetSecurity() > gmLevelInWhoList)) - continue; - } - - //do not process players which are not in world - if (!(itr->second->IsInWorld())) - continue; - - // check if target is globally visible for player - if (!(itr->second->IsVisibleGloballyFor(_player))) - continue; - - // check if target's level is in level range - uint8 lvl = itr->second->getLevel(); - if (lvl < level_min || lvl > level_max) - continue; - - // check if class matches classmask - uint32 class_ = itr->second->getClass(); - if (!(classmask & (1 << class_))) - continue; - - // check if race matches racemask - uint32 race = itr->second->getRace(); - if (!(racemask & (1 << race))) - continue; - - uint32 pzoneid = itr->second->GetZoneId(); - - bool z_show = true; - for (uint32 i = 0; i < zones_count; ++i) - { - if (zoneids[i] == pzoneid) - { - z_show = true; - break; - } - - z_show = false; - } - if (!z_show) - continue; - - std::string pname = itr->second->GetName(); - std::wstring wpname; - if (!Utf8toWStr(pname,wpname)) - continue; - wstrToLower(wpname); - - if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos)) - continue; - - std::string gname = objmgr.GetGuildNameById(itr->second->GetGuildId()); - std::wstring wgname; - if (!Utf8toWStr(gname,wgname)) - continue; - wstrToLower(wgname); - - if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos)) - continue; - - std::string aname; - if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(itr->second->GetZoneId())) - aname = areaEntry->area_name[GetSessionDbcLocale()]; - - bool s_show = true; - for (uint32 i = 0; i < str_count; ++i) - { - if (!str[i].empty()) - { - if (wgname.find(str[i]) != std::wstring::npos || - wpname.find(str[i]) != std::wstring::npos || - Utf8FitTo(aname, str[i])) - { - s_show = true; - break; - } - s_show = false; - } - } - if (!s_show) - continue; - - data << pname; // player name - data << gname; // guild name - data << uint32(lvl); // player level - data << uint32(class_); // player class - data << uint32(race); // player race - data << uint8(0); // new 2.4.0 - data << uint32(pzoneid); // player zone id - - // 49 is maximum player count sent to client - can be overridden - // through config, but is unstable - if ((++clientcount) == sWorld.getConfig(CONFIG_MAX_WHO)) - break; - } - - uint32 count = m.size(); - data.put( 0, clientcount ); // insert right count, listed count - data.put( 4, count > 50 ? count : clientcount ); // insert right count, online count - - SendPacket(&data); - sLog.outDebug("WORLD: Send SMSG_WHO Message"); -} - -void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", GetSecurity()); - - if (uint64 lguid = GetPlayer()->GetLootGUID()) - DoLootRelease(lguid); - - uint8 reason = 0; - - if (GetPlayer()->isInCombat()) - reason = 1; - else if (GetPlayer()->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_JUMPING | MOVEMENTFLAG_FALLING)) - reason = 3; // is jumping or falling - else if (GetPlayer()->duel || GetPlayer()->HasAura(9454)) // is dueling or frozen by GM via freeze command - reason = 2; // FIXME - Need the correct value - - if (reason) - { - WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(reason); - data << uint32(0); - SendPacket(&data); - LogoutRequest(0); - return; - } - - //instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in TrinityCore.conf - if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->isInFlight() || - GetSecurity() >= sWorld.getConfig(CONFIG_INSTANT_LOGOUT)) - { - WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(0); - data << uint32(16777216); - SendPacket(&data); - LogoutPlayer(true); - return; - } - - // not set flags if player can't free move to prevent lost state at logout cancel - if (GetPlayer()->CanFreeMove()) - { - GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); - - WorldPacket data(SMSG_FORCE_MOVE_ROOT, (8+4)); // guess size - data.append(GetPlayer()->GetPackGUID()); - data << (uint32)2; - SendPacket(&data); - GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - } - - WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint8(0); - data << uint32(0); - SendPacket(&data); - LogoutRequest(time(NULL)); -} - -void WorldSession::HandlePlayerLogoutOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: Recvd CMSG_PLAYER_LOGOUT Message"); -} - -void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: Recvd CMSG_LOGOUT_CANCEL Message"); - - LogoutRequest(0); - - WorldPacket data(SMSG_LOGOUT_CANCEL_ACK, 0); - SendPacket(&data); - - // not remove flags if can't free move - its not set in Logout request code. - if (GetPlayer()->CanFreeMove()) - { - //!we can move again - data.Initialize(SMSG_FORCE_MOVE_UNROOT, 8); // guess size - data.append(GetPlayer()->GetPackGUID()); - data << uint32(0); - SendPacket(&data); - - //! Stand Up - GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND); - - //! DISABLE_ROTATE - GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - } - - sLog.outDebug("WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message"); -} - -void WorldSession::HandleTogglePvP(WorldPacket & recv_data) -{ - // this opcode can be used in two ways: Either set explicit new status or toggle old status - if (recv_data.size() == 1) - { - bool newPvPStatus; - recv_data >> newPvPStatus; - GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus); - GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus); - } - else - { - GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); - GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER); - } - - if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) - { - if (!GetPlayer()->IsPvP() || GetPlayer()->pvpInfo.endTimer != 0) - GetPlayer()->UpdatePvP(true, true); - } - else - { - if (!GetPlayer()->pvpInfo.inHostileArea && GetPlayer()->IsPvP()) - GetPlayer()->pvpInfo.endTimer = time(NULL); // start toggle-off - } - - //if (OutdoorPvP * pvp = _player->GetOutdoorPvP()) - // pvp->HandlePlayerActivityChanged(_player); -} - -void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recv_data) -{ - uint32 newZone; - recv_data >> newZone; - - sLog.outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); - - // use server size data - uint32 newzone, newarea; - GetPlayer()->GetZoneAndAreaId(newzone,newarea); - GetPlayer()->UpdateZone(newzone,newarea); - //GetPlayer()->SendInitWorldStates(true,newZone); -} - -void WorldSession::HandleSetTargetOpcode(WorldPacket & recv_data) -{ - // When this packet send? - uint64 guid ; - recv_data >> guid; - - _player->SetUInt32Value(UNIT_FIELD_TARGET, guid); - - // update reputation list if need - Unit* unit = ObjectAccessor::GetUnit(*_player, guid); - if (!unit) - return; - - if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction())) - _player->GetReputationMgr().SetVisible(factionTemplateEntry); -} - -void WorldSession::HandleSetSelectionOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - _player->SetSelection(guid); - - // update reputation list if need - Unit* unit = ObjectAccessor::GetUnit(*_player, guid); - if (!unit) - return; - - if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction())) - _player->GetReputationMgr().SetVisible(factionTemplateEntry); -} - -void WorldSession::HandleStandStateChangeOpcode(WorldPacket & recv_data) -{ - // sLog.outDebug("WORLD: Received CMSG_STANDSTATECHANGE"); -- too many spam in log at lags/debug stop - uint32 animstate; - recv_data >> animstate; - - _player->SetStandState(animstate); -} - -void WorldSession::HandleContactListOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_CONTACT_LIST"); - uint32 unk; - recv_data >> unk; - sLog.outDebug("unk value is %u", unk); - _player->GetSocial()->SendSocialList(); -} - -void WorldSession::HandleAddFriendOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_ADD_FRIEND"); - - std::string friendName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN); - std::string friendNote; - - recv_data >> friendName; - - recv_data >> friendNote; - - if (!normalizePlayerName(friendName)) - return; - - CharacterDatabase.escape_string(friendName); // prevent SQL injection - normal name don't must changed by this call - - sLog.outDebug("WORLD: %s asked to add friend : '%s'", - GetPlayer()->GetName(), friendName.c_str()); - - CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddFriendOpcodeCallBack, GetAccountId(), friendNote, "SELECT guid, race, account FROM characters WHERE name = '%s'", friendName.c_str()); -} - -void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string friendNote) -{ - uint64 friendGuid; - uint64 friendAcctid; - uint32 team; - FriendsResult friendResult; - - WorldSession * session = sWorld.FindSession(accountId); - - if (!session || !session->GetPlayer()) - return; - - friendResult = FRIEND_NOT_FOUND; - friendGuid = 0; - - if (result) - { - friendGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); - team = Player::TeamForRace((*result)[1].GetUInt8()); - friendAcctid = (*result)[2].GetUInt32(); - - if (session->GetSecurity() >= SEC_MODERATOR || sWorld.getConfig(CONFIG_ALLOW_GM_FRIEND) || accmgr.GetSecurity(friendAcctid) < SEC_MODERATOR) - { - if (friendGuid) - { - if (friendGuid == session->GetPlayer()->GetGUID()) - friendResult = FRIEND_SELF; - else if (session->GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && session->GetSecurity() < SEC_MODERATOR) - friendResult = FRIEND_ENEMY; - else if (session->GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) - friendResult = FRIEND_ALREADY; - else - { - Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); - if (pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(session->GetPlayer())) - friendResult = FRIEND_ADDED_ONLINE; - else - friendResult = FRIEND_ADDED_OFFLINE; - if (!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) - { - friendResult = FRIEND_LIST_FULL; - sLog.outDebug("WORLD: %s's friend list is full.", session->GetPlayer()->GetName()); - } - } - session->GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); - } - } - } - - sSocialMgr.SendFriendStatus(session->GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); - - sLog.outDebug("WORLD: Sent (SMSG_FRIEND_STATUS)"); -} - -void WorldSession::HandleDelFriendOpcode(WorldPacket & recv_data) -{ - uint64 FriendGUID; - - sLog.outDebug("WORLD: Received CMSG_DEL_FRIEND"); - - recv_data >> FriendGUID; - - _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), false); - - sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), false); - - sLog.outDebug("WORLD: Sent motd (SMSG_FRIEND_STATUS)"); -} - -void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_ADD_IGNORE"); - - std::string IgnoreName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN); - - recv_data >> IgnoreName; - - if (!normalizePlayerName(IgnoreName)) - return; - - CharacterDatabase.escape_string(IgnoreName); // prevent SQL injection - normal name don't must changed by this call - - sLog.outDebug("WORLD: %s asked to Ignore: '%s'", - GetPlayer()->GetName(), IgnoreName.c_str()); - - CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddIgnoreOpcodeCallBack, GetAccountId(), "SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str()); -} - -void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId) -{ - uint64 IgnoreGuid; - FriendsResult ignoreResult; - - WorldSession * session = sWorld.FindSession(accountId); - - if (!session || !session->GetPlayer()) - return; - - ignoreResult = FRIEND_IGNORE_NOT_FOUND; - IgnoreGuid = 0; - - if (result) - { - IgnoreGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); - - if (IgnoreGuid) - { - if (IgnoreGuid == session->GetPlayer()->GetGUID()) //not add yourself - ignoreResult = FRIEND_IGNORE_SELF; - else if (session->GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid))) - ignoreResult = FRIEND_IGNORE_ALREADY; - else - { - ignoreResult = FRIEND_IGNORE_ADDED; - - // ignore list full - if (!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) - ignoreResult = FRIEND_IGNORE_FULL; - } - } - } - - sSocialMgr.SendFriendStatus(session->GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false); - - sLog.outDebug("WORLD: Sent (SMSG_FRIEND_STATUS)"); -} - -void WorldSession::HandleDelIgnoreOpcode(WorldPacket & recv_data) -{ - uint64 IgnoreGUID; - - sLog.outDebug("WORLD: Received CMSG_DEL_IGNORE"); - - recv_data >> IgnoreGUID; - - _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), true); - - sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), false); - - sLog.outDebug("WORLD: Sent motd (SMSG_FRIEND_STATUS)"); -} - -void WorldSession::HandleSetContactNotesOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_SET_CONTACT_NOTES"); - uint64 guid; - std::string note; - recv_data >> guid >> note; - _player->GetSocial()->SetFriendNote(guid, note); -} - -void WorldSession::HandleBugOpcode(WorldPacket & recv_data) -{ - uint32 suggestion, contentlen, typelen; - std::string content, type; - - recv_data >> suggestion >> contentlen >> content; - - recv_data >> typelen >> type; - - if (suggestion == 0) - sLog.outDebug("WORLD: Received CMSG_BUG [Bug Report]"); - else - sLog.outDebug("WORLD: Received CMSG_BUG [Suggestion]"); - - sLog.outDebug("%s", type.c_str()); - sLog.outDebug("%s", content.c_str()); - - CharacterDatabase.escape_string(type); - CharacterDatabase.escape_string(content); - CharacterDatabase.PExecute ("INSERT INTO bugreport (type,content) VALUES('%s', '%s')", type.c_str(), content.c_str()); -} - -void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) -{ - sLog.outDetail("WORLD: Received CMSG_RECLAIM_CORPSE"); - - uint64 guid; - recv_data >> guid; - - if (GetPlayer()->isAlive()) - return; - - // do not allow corpse reclaim in arena - if (GetPlayer()->InArena()) - return; - - // body not released yet - if (!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) - return; - - Corpse *corpse = GetPlayer()->GetCorpse(); - - if (!corpse) - return; - - // prevent resurrect before 30-sec delay after body release not finished - if (corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP) > time(NULL)) - return; - - if (!corpse->IsWithinDistInMap(GetPlayer(), CORPSE_RECLAIM_RADIUS, true)) - return; - - // resurrect - GetPlayer()->ResurrectPlayer(GetPlayer()->InBattleGround() ? 1.0f : 0.5f); - - // spawn bones - GetPlayer()->SpawnCorpseBones(); -} - -void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) -{ - sLog.outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE"); - - uint64 guid; - uint8 status; - recv_data >> guid; - recv_data >> status; - - if (GetPlayer()->isAlive()) - return; - - if (status == 0) - { - GetPlayer()->clearResurrectRequestData(); // reject - return; - } - - if (!GetPlayer()->isRessurectRequestedBy(guid)) - return; - - GetPlayer()->ResurectUsingRequestData(); -} - -void WorldSession::SendAreaTriggerMessage(const char* Text, ...) -{ - va_list ap; - char szStr [1024]; - szStr[0] = '\0'; - - va_start(ap, Text); - vsnprintf(szStr, 1024, Text, ap); - va_end(ap); - - uint32 length = strlen(szStr)+1; - WorldPacket data(SMSG_AREA_TRIGGER_MESSAGE, 4+length); - data << length; - data << szStr; - SendPacket(&data); -} - -void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_AREATRIGGER"); - - uint32 Trigger_ID; - - recv_data >> Trigger_ID; - sLog.outDebug("Trigger ID:%u",Trigger_ID); - - if (GetPlayer()->isInFlight()) - { - sLog.outDebug("Player '%s' (GUID: %u) in flight, ignore Area Trigger ID:%u",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow(), Trigger_ID); - return; - } - - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); - if (!atEntry) - { - sLog.outDebug("Player '%s' (GUID: %u) send unknown (by DBC) Area Trigger ID:%u",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow(), Trigger_ID); - return; - } - - if (GetPlayer()->GetMapId() != atEntry->mapid) - { - sLog.outDebug("Player '%s' (GUID: %u) too far (trigger map: %u player map: %u), ignore Area Trigger ID: %u", GetPlayer()->GetName(), atEntry->mapid, GetPlayer()->GetMapId(), GetPlayer()->GetGUIDLow(), Trigger_ID); - return; - } - - // delta is safe radius - const float delta = 5.0f; - // check if player in the range of areatrigger - Player* pl = GetPlayer(); - - if (atEntry->radius > 0) - { - // if we have radius check it - float dist = pl->GetDistance(atEntry->x,atEntry->y,atEntry->z); - if (dist > atEntry->radius + delta) - { - sLog.outDebug("Player '%s' (GUID: %u) too far (radius: %f distance: %f), ignore Area Trigger ID: %u", - pl->GetName(), pl->GetGUIDLow(), atEntry->radius, dist, Trigger_ID); - return; - } - } - else - { - // we have only extent - - // rotate the players position instead of rotating the whole cube, that way we can make a simplified - // is-in-cube check and we have to calculate only one point instead of 4 - - // 2PI = 360°, keep in mind that ingame orientation is counter-clockwise - double rotation = 2*M_PI-atEntry->box_orientation; - double sinVal = sin(rotation); - double cosVal = cos(rotation); - - float playerBoxDistX = pl->GetPositionX() - atEntry->x; - float playerBoxDistY = pl->GetPositionY() - atEntry->y; - - float rotPlayerX = atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal; - float rotPlayerY = atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal; - - // box edges are parallel to coordiante axis, so we can treat every dimension independently :D - float dz = pl->GetPositionZ() - atEntry->z; - float dx = rotPlayerX - atEntry->x; - float dy = rotPlayerY - atEntry->y; - if ((fabs(dx) > atEntry->box_x/2 + delta) || - (fabs(dy) > atEntry->box_y/2 + delta) || - (fabs(dz) > atEntry->box_z/2 + delta)) - { - sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotatedPlayerX: %f rotatedPlayerY: %f dZ:%f), ignore Area Trigger ID: %u", - pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotPlayerX, rotPlayerY, dz, Trigger_ID); - return; - } - } - - if (sScriptMgr.AreaTrigger(GetPlayer(), atEntry)) - return; - - uint32 quest_id = objmgr.GetQuestForAreaTrigger(Trigger_ID); - if (quest_id && GetPlayer()->isAlive() && GetPlayer()->IsActiveQuest(quest_id)) - { - Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); - if (pQuest) - { - if (GetPlayer()->GetQuestStatus(quest_id) == QUEST_STATUS_INCOMPLETE) - GetPlayer()->AreaExploredOrEventHappens(quest_id); - } - } - - if (objmgr.IsTavernAreaTrigger(Trigger_ID)) - { - // set resting flag we are in the inn - GetPlayer()->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - GetPlayer()->InnEnter(time(NULL), atEntry->mapid, atEntry->x, atEntry->y, atEntry->z); - GetPlayer()->SetRestType(REST_TYPE_IN_TAVERN); - - if (sWorld.IsFFAPvPRealm()) - GetPlayer()->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - - return; - } - - if (GetPlayer()->InBattleGround()) - { - BattleGround* bg = GetPlayer()->GetBattleGround(); - if (bg) - if (bg->GetStatus() == STATUS_IN_PROGRESS) - bg->HandleAreaTrigger(GetPlayer(), Trigger_ID); - - return; - } - - if (OutdoorPvP * pvp = GetPlayer()->GetOutdoorPvP()) - { - if (pvp->HandleAreaTrigger(_player, Trigger_ID)) - return; - } - - // NULL if all values default (non teleport trigger) - AreaTrigger const* at = objmgr.GetAreaTrigger(Trigger_ID); - if (!at) - return; - - if (!GetPlayer()->Satisfy(objmgr.GetAccessRequirement(at->access_id), at->target_mapId, true)) - return; - - // check if player can enter instance : instance not full, and raid instance not in encounter fight - if (!MapManager::Instance().CanPlayerEnter(at->target_mapId, GetPlayer(), false)) - return; - - GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT); -} - -void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) -{ - sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); - - uint32 type, timestamp, decompressedSize; - recv_data >> type >> timestamp >> decompressedSize; - - sLog.outDebug("UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize); - - if (type > NUM_ACCOUNT_DATA_TYPES) - return; - - if (decompressedSize == 0) // erase - { - SetAccountData(AccountDataType(type), 0, ""); - - WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); - data << uint32(type); - data << uint32(0); - SendPacket(&data); - - return; - } - - if (decompressedSize > 0xFFFF) - { - recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case - sLog.outError("UAD: Account data packet too big, size %u", decompressedSize); - return; - } - - ByteBuffer dest; - dest.resize(decompressedSize); - - uLongf realSize = decompressedSize; - if (uncompress(const_cast(dest.contents()), &realSize, const_cast(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) - { - recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case - sLog.outError("UAD: Failed to decompress account data"); - return; - } - - recv_data.rpos(recv_data.wpos()); // uncompress read (recv_data.size() - recv_data.rpos()) - - std::string adata; - dest >> adata; - - SetAccountData(AccountDataType(type), timestamp, adata); - - WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); - data << uint32(type); - data << uint32(0); - SendPacket(&data); -} - -void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) -{ - sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); - - uint32 type; - recv_data >> type; - - sLog.outDebug("RAD: type %u", type); - - if (type > NUM_ACCOUNT_DATA_TYPES) - return; - - AccountData *adata = GetAccountData(AccountDataType(type)); - - uint32 size = adata->Data.size(); - - uLongf destSize = compressBound(size); - - ByteBuffer dest; - dest.resize(destSize); - - if (size && compress(const_cast(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) - { - sLog.outDebug("RAD: Failed to compress account data"); - return; - } - - dest.resize(destSize); - - WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize); - data << uint64(_player ? _player->GetGUID() : 0); // player guid - data << uint32(type); // type (0-7) - data << uint32(adata->Time); // unix time - data << uint32(size); // decompressed length - data.append(dest); // compressed data - SendPacket(&data); -} - -void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_SET_ACTION_BUTTON"); - uint8 button; - uint32 packetData; - recv_data >> button >> packetData; - - uint32 action = ACTION_BUTTON_ACTION(packetData); - uint8 type = ACTION_BUTTON_TYPE(packetData); - - sLog.outDetail("BUTTON: %u ACTION: %u TYPE: %u", button, action, type); - if (!packetData) - { - sLog.outDetail("MISC: Remove action from button %u", button); - GetPlayer()->removeActionButton(button); - } - else - { - switch(type) - { - case ACTION_BUTTON_MACRO: - case ACTION_BUTTON_CMACRO: - sLog.outDetail("MISC: Added Macro %u into button %u", action, button); - break; - case ACTION_BUTTON_EQSET: - sLog.outDetail("MISC: Added EquipmentSet %u into button %u", action, button); - break; - case ACTION_BUTTON_SPELL: - sLog.outDetail("MISC: Added Spell %u into button %u", action, button); - break; - case ACTION_BUTTON_ITEM: - sLog.outDetail("MISC: Added Item %u into button %u", action, button); - break; - default: - sLog.outError("MISC: Unknown action button type %u for action %u into button %u", type, action, button); - return; - } - GetPlayer()->addActionButton(button, action, type); - } -} - -void WorldSession::HandleCompleteCinematic(WorldPacket & /*recv_data*/) -{ - DEBUG_LOG("WORLD: Player is watching cinema"); -} - -void WorldSession::HandleNextCinematicCamera(WorldPacket & /*recv_data*/) -{ - DEBUG_LOG("WORLD: Which movie to play"); -} - -void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) -{ - /* WorldSession::Update(getMSTime());*/ - DEBUG_LOG("WORLD: Time Lag/Synchronization Resent/Update"); - - uint64 guid; - if (!recv_data.readPackGUID(guid)) - { - recv_data.rpos(recv_data.wpos()); - return; - } - recv_data.read_skip(); - /* - uint64 guid; - uint32 time_skipped; - recv_data >> guid; - recv_data >> time_skipped; - sLog.outDebug("WORLD: CMSG_MOVE_TIME_SKIPPED"); - - /// TODO - must be need use in Trinity - We substract server Lags to move time (AntiLags) - for exmaple - GetPlayer()->ModifyLastMoveTime(-int32(time_skipped)); - */ -} - -void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data) -{ - DEBUG_LOG("WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); - - // no used - recv_data.rpos(recv_data.wpos()); // prevent warnings spam -} - -void WorldSession::HandleMoveUnRootAck(WorldPacket& recv_data) -{ - // no used - recv_data.rpos(recv_data.wpos()); // prevent warnings spam -/* - uint64 guid; - recv_data >> guid; - - // now can skip not our packet - if (_player->GetGUID() != guid) - { - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - } - - sLog.outDebug("WORLD: CMSG_FORCE_MOVE_UNROOT_ACK"); - - recv_data.read_skip(); // unk - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); - recv_data.read_skip(); // unk2 -*/ -} - -void WorldSession::HandleMoveRootAck(WorldPacket& recv_data) -{ - // no used - recv_data.rpos(recv_data.wpos()); // prevent warnings spam -/* - uint64 guid; - recv_data >> guid; - - // now can skip not our packet - if (_player->GetGUID() != guid) - { - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - } - - sLog.outDebug("WORLD: CMSG_FORCE_MOVE_ROOT_ACK"); - - recv_data.read_skip(); // unk - - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); -*/ -} - -void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data) -{ - uint8 ActionBar; - - recv_data >> ActionBar; - - if (!GetPlayer()) // ignore until not logged (check needed because STATUS_AUTHED) - { - if (ActionBar != 0) - sLog.outError("WorldSession::HandleSetActionBarToggles in not logged state with value: %u, ignored",uint32(ActionBar)); - return; - } - - GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, ActionBar); -} - -void WorldSession::HandleWardenDataOpcode(WorldPacket& recv_data) -{ - recv_data.read_skip(); - /* - uint8 tmp; - recv_data >> tmp; - sLog.outDebug("Received opcode CMSG_WARDEN_DATA, not resolve.uint8 = %u",tmp); - */ -} - -void WorldSession::HandlePlayedTime(WorldPacket& recv_data) -{ - uint8 unk1; - recv_data >> unk1; // 0 or 1 expected - - WorldPacket data(SMSG_PLAYED_TIME, 4 + 4 + 1); - data << uint32(_player->GetTotalPlayedTime()); - data << uint32(_player->GetLevelPlayedTime()); - data << uint8(unk1); // 0 - will not show in chat frame - SendPacket(&data); -} - -void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) -{ - uint64 guid; - recv_data >> guid; - DEBUG_LOG("Inspected guid is " UI64FMTD, guid); - - _player->SetSelection(guid); - - Player *plr = objmgr.GetPlayer(guid); - if (!plr) // wrong player - return; - - uint32 talent_points = 0x47; - uint32 guid_size = plr->GetPackGUID().wpos(); - WorldPacket data(SMSG_INSPECT_TALENT, guid_size+4+talent_points); - data.append(plr->GetPackGUID()); - - if (sWorld.getConfig(CONFIG_TALENTS_INSPECTING) || _player->isGameMaster()) - { - plr->BuildPlayerTalentsInfoData(&data); - } - else - { - data << uint32(0); // unspentTalentPoints - data << uint8(0); // talentGroupCount - data << uint8(0); // talentGroupIndex - } - - plr->BuildEnchantmentsInfoData(&data); - SendPacket(&data); -} - -void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) -{ - uint64 guid; - recv_data >> guid; - - Player *player = objmgr.GetPlayer(guid); - - if (!player) - { - sLog.outError("InspectHonorStats: WTF, player not found..."); - return; - } - - WorldPacket data(MSG_INSPECT_HONOR_STATS, 8+1+4*4); - data << uint64(player->GetGUID()); - data << uint8(player->GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY)); - data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS)); - data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); - data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); - data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); - SendPacket(&data); -} - -void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) -{ - // write in client console: worldport 469 452 6454 2536 180 or /console worldport 469 452 6454 2536 180 - // Received opcode CMSG_WORLD_TELEPORT - // Time is ***, map=469, x=452.000000, y=6454.000000, z=2536.000000, orient=3.141593 - - uint32 time; - uint32 mapid; - float PositionX; - float PositionY; - float PositionZ; - float Orientation; - - recv_data >> time; // time in m.sec. - recv_data >> mapid; - recv_data >> PositionX; - recv_data >> PositionY; - recv_data >> PositionZ; - recv_data >> Orientation; // o (3.141593 = 180 degrees) - - //sLog.outDebug("Received opcode CMSG_WORLD_TELEPORT"); - if (GetPlayer()->isInFlight()) - { - sLog.outDebug("Player '%s' (GUID: %u) in flight, ignore worldport command.",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow()); - return; - } - - DEBUG_LOG("Time %u sec, map=%u, x=%f, y=%f, z=%f, orient=%f", time/1000, mapid, PositionX, PositionY, PositionZ, Orientation); - - if (GetSecurity() >= SEC_ADMINISTRATOR) - GetPlayer()->TeleportTo(mapid,PositionX,PositionY,PositionZ,Orientation); - else - SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); - sLog.outDebug("Received worldport command from player %s", GetPlayer()->GetName()); -} - -void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) -{ - sLog.outDebug("Received opcode CMSG_WHOIS"); - std::string charname; - recv_data >> charname; - - if (GetSecurity() < SEC_ADMINISTRATOR) - { - SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); - return; - } - - if (charname.empty() || !normalizePlayerName (charname)) - { - SendNotification(LANG_NEED_CHARACTER_NAME); - return; - } - - Player *plr = objmgr.GetPlayer(charname.c_str()); - - if (!plr) - { - SendNotification(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, charname.c_str()); - return; - } - - uint32 accid = plr->GetSession()->GetAccountId(); - - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid); - if (!result) - { - SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, charname.c_str()); - return; - } - - Field *fields = result->Fetch(); - std::string acc = fields[0].GetCppString(); - if (acc.empty()) - acc = "Unknown"; - std::string email = fields[1].GetCppString(); - if (email.empty()) - email = "Unknown"; - std::string lastip = fields[2].GetCppString(); - if (lastip.empty()) - lastip = "Unknown"; - - std::string msg = charname + "'s " + "account is " + acc + ", e-mail: " + email + ", last ip: " + lastip; - - WorldPacket data(SMSG_WHOIS, msg.size()+1); - data << msg; - _player->GetSession()->SendPacket(&data); - - sLog.outDebug("Received whois command from player %s for character %s", GetPlayer()->GetName(), charname.c_str()); -} - -void WorldSession::HandleComplainOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_COMPLAIN"); - recv_data.hexlike(); - - uint8 spam_type; // 0 - mail, 1 - chat - uint64 spammer_guid; - uint32 unk1 = 0; - uint32 unk2 = 0; - uint32 unk3 = 0; - uint32 unk4 = 0; - std::string description = ""; - recv_data >> spam_type; // unk 0x01 const, may be spam type (mail/chat) - recv_data >> spammer_guid; // player guid - switch(spam_type) - { - case 0: - recv_data >> unk1; // const 0 - recv_data >> unk2; // probably mail id - recv_data >> unk3; // const 0 - break; - case 1: - recv_data >> unk1; // probably language - recv_data >> unk2; // message type? - recv_data >> unk3; // probably channel id - recv_data >> unk4; // unk random value - recv_data >> description; // spam description string (messagetype, channel name, player name, message) - break; - } - - // NOTE: all chat messages from this spammer automatically ignored by spam reporter until logout in case chat spam. - // if it's mail spam - ALL mails from this spammer automatically removed by client - - // Complaint Received message - WorldPacket data(SMSG_COMPLAIN_RESULT, 1); - data << uint8(0); - SendPacket(&data); - - sLog.outDebug("REPORT SPAM: type %u, guid %u, unk1 %u, unk2 %u, unk3 %u, unk4 %u, message %s", spam_type, GUID_LOPART(spammer_guid), unk1, unk2, unk3, unk4, description.c_str()); -} - -void WorldSession::HandleRealmSplitOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_REALM_SPLIT"); - - uint32 unk; - std::string split_date = "01/01/01"; - recv_data >> unk; - - WorldPacket data(SMSG_REALM_SPLIT, 4+4+split_date.size()+1); - data << unk; - data << uint32(0x00000000); // realm split state - // split states: - // 0x0 realm normal - // 0x1 realm split - // 0x2 realm split pending - data << split_date; - SendPacket(&data); - //sLog.outDebug("response sent %u", unk); -} - -void WorldSession::HandleFarSightOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_FAR_SIGHT"); - //recv_data.hexlike(); - - uint8 apply; - recv_data >> apply; - - switch(apply) - { - case 0: - sLog.outDebug("Player %u set vision to self", _player->GetGUIDLow()); - _player->SetSeer(_player); - break; - case 1: - sLog.outDebug("Added FarSight " I64FMT " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow()); - if (WorldObject *target = _player->GetViewpoint()) - _player->SetSeer(target); - else - sLog.outError("Player %s requests non-existing seer", _player->GetName()); - break; - default: - sLog.outDebug("Unhandled mode in CMSG_FAR_SIGHT: %u", apply); - return; - } - - GetPlayer()->UpdateVisibilityForPlayer(); -} - -void WorldSession::HandleSetTitleOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_SET_TITLE"); - - int32 title; - recv_data >> title; - - // -1 at none - if (title > 0 && title < MAX_TITLE_INDEX) - { - if (!GetPlayer()->HasTitle(title)) - return; - } - else - title = 0; - - GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title); -} - -void WorldSession::HandleTimeSyncResp(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_TIME_SYNC_RESP"); - - uint32 counter, clientTicks; - recv_data >> counter >> clientTicks; - - if (counter != _player->m_timeSyncCounter - 1) - sLog.outDebug("Wrong time sync counter from player %s (cheater?)", _player->GetName()); - - sLog.outDebug("Time sync received: counter %u, client ticks %u, time since last sync %u", counter, clientTicks, clientTicks - _player->m_timeSyncClient); - - uint32 ourTicks = clientTicks + (getMSTime() - _player->m_timeSyncServer); - - // diff should be small - sLog.outDebug("Our ticks: %u, diff %u, latency %u", ourTicks, ourTicks - clientTicks, GetLatency()); - - _player->m_timeSyncClient = clientTicks; -} - -void WorldSession::HandleResetInstancesOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: CMSG_RESET_INSTANCES"); - Group *pGroup = _player->GetGroup(); - if (pGroup) - { - if (pGroup->IsLeader(_player->GetGUID())) - { - pGroup->ResetInstances(INSTANCE_RESET_ALL, false, _player); - pGroup->ResetInstances(INSTANCE_RESET_ALL, true,_player); - } - } - else - { - _player->ResetInstances(INSTANCE_RESET_ALL, false); - _player->ResetInstances(INSTANCE_RESET_ALL, true); - } -} - -void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("MSG_SET_DUNGEON_DIFFICULTY"); - - uint32 mode; - recv_data >> mode; - - if (mode >= MAX_DUNGEON_DIFFICULTY) - { - sLog.outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode); - return; - } - - if (Difficulty(mode) == _player->GetDungeonDifficulty()) - return; - - // cannot reset while in an instance - Map *map = _player->GetMap(); - if (map && map->IsDungeon()) - { - sLog.outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); - return; - } - - if (_player->getLevel() < LEVELREQUIREMENT_HEROIC) - return; - - Group *pGroup = _player->GetGroup(); - if (pGroup) - { - if (pGroup->IsLeader(_player->GetGUID())) - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* pGroupGuy = itr->getSource(); - if (!pGroupGuy) - continue; - - if (!pGroupGuy->IsInMap(pGroupGuy)) - return; - - map = pGroupGuy->GetMap(); - if (map && map->IsNonRaidDungeon()) - { - sLog.outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); - return; - } - } - // the difficulty is set even if the instances can't be reset - //_player->SendDungeonDifficulty(true); - pGroup->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, _player); - pGroup->SetDungeonDifficulty(Difficulty(mode)); - } - } - else - { - _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false); - _player->SetDungeonDifficulty(Difficulty(mode)); - } -} - -void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("MSG_SET_RAID_DIFFICULTY"); - - uint32 mode; - recv_data >> mode; - - if (mode >= MAX_RAID_DIFFICULTY) - { - sLog.outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode); - return; - } - - // cannot reset while in an instance - Map *map = _player->GetMap(); - if (map && map->IsDungeon()) - { - sLog.outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); - return; - } - - if (Difficulty(mode) == _player->GetRaidDifficulty()) - return; - - if (_player->getLevel() < LEVELREQUIREMENT_HEROIC) - return; - - Group *pGroup = _player->GetGroup(); - if (pGroup) - { - if (pGroup->IsLeader(_player->GetGUID())) - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* pGroupGuy = itr->getSource(); - if (!pGroupGuy) - continue; - - if (!pGroupGuy->IsInMap(pGroupGuy)) - return; - - map = pGroupGuy->GetMap(); - if (map && map->IsRaid()) - { - sLog.outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); - return; - } - } - // the difficulty is set even if the instances can't be reset - //_player->SendDungeonDifficulty(true); - pGroup->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, _player); - pGroup->SetRaidDifficulty(Difficulty(mode)); - } - } - else - { - _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true); - _player->SetRaidDifficulty(Difficulty(mode)); - } -} - -void WorldSession::HandleCancelMountAuraOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: CMSG_CANCEL_MOUNT_AURA"); - - //If player is not mounted, so go out :) - if (!_player->IsMounted()) // not blizz like; no any messages on blizz - { - ChatHandler(this).SendSysMessage(LANG_CHAR_NON_MOUNTED); - return; - } - - if (_player->isInFlight()) // not blizz like; no any messages on blizz - { - ChatHandler(this).SendSysMessage(LANG_YOU_IN_FLIGHT); - return; - } - - _player->Unmount(); - _player->RemoveAurasByType(SPELL_AURA_MOUNTED); -} - -void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket & recv_data) -{ - // fly mode on/off - sLog.outDebug("WORLD: CMSG_MOVE_SET_CAN_FLY_ACK"); - //recv_data.hexlike(); - - uint64 guid; // guid - unused - if (!recv_data.readPackGUID(guid)) - return; - - recv_data.read_skip(); // unk - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip(); // unk2 - - _player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags(); -} - -void WorldSession::HandleRequestPetInfoOpcode(WorldPacket & /*recv_data */) -{ - /* - sLog.outDebug("WORLD: CMSG_REQUEST_PET_INFO"); - recv_data.hexlike(); - */ -} - -void WorldSession::HandleSetTaxiBenchmarkOpcode(WorldPacket & recv_data) -{ - uint8 mode; - recv_data >> mode; - - sLog.outDebug("Client used \"/timetest %d\" command", mode); -} - -void WorldSession::HandleQueryInspectAchievements(WorldPacket & recv_data) -{ - uint64 guid; - if (!recv_data.readPackGUID(guid)) - return; - - Player *player = objmgr.GetPlayer(guid); - if (!player) - return; - - player->GetAchievementMgr().SendRespondInspectAchievements(_player); -} - -void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recv_data*/) -{ - // empty opcode - sLog.outDebug("WORLD: CMSG_WORLD_STATE_UI_TIMER_UPDATE"); - - WorldPacket data(SMSG_WORLD_STATE_UI_TIMER_UPDATE, 4); - data << uint32(time(NULL)); - SendPacket(&data); -} - -void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recv_data*/) -{ - // empty opcode - sLog.outDebug("WORLD: CMSG_READY_FOR_ACCOUNT_DATA_TIMES"); - - SendAccountDataTimes(GLOBAL_CACHE_MASK); -} - -void WorldSession::SendSetPhaseShift(uint32 PhaseShift) -{ - WorldPacket data(SMSG_SET_PHASE_SHIFT, 4); - data << uint32(PhaseShift); - SendPacket(&data); -} diff --git a/src/server/game/Entities/Player/PetitionsHandler.cpp b/src/server/game/Entities/Player/PetitionsHandler.cpp deleted file mode 100644 index 7f578c22656..00000000000 --- a/src/server/game/Entities/Player/PetitionsHandler.cpp +++ /dev/null @@ -1,938 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Language.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Guild.h" -#include "ArenaTeam.h" -#include "GossipDef.h" -#include "SocialMgr.h" - -/*enum PetitionType // dbc data -{ - PETITION_TYPE_GUILD = 1, - PETITION_TYPE_ARENA_TEAM = 3 -};*/ - -// Charters ID in item_template -#define GUILD_CHARTER 5863 -#define GUILD_CHARTER_COST 1000 // 10 S -#define ARENA_TEAM_CHARTER_2v2 23560 -#define ARENA_TEAM_CHARTER_2v2_COST 800000 // 80 G -#define ARENA_TEAM_CHARTER_3v3 23561 -#define ARENA_TEAM_CHARTER_3v3_COST 1200000 // 120 G -#define ARENA_TEAM_CHARTER_5v5 23562 -#define ARENA_TEAM_CHARTER_5v5_COST 2000000 // 200 G - -void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("Received opcode CMSG_PETITION_BUY"); - recv_data.hexlike(); - - uint64 guidNPC; - uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client - std::string name; - - recv_data >> guidNPC; // NPC GUID - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data >> name; // name - recv_data.read_skip(); // some string - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - recv_data.read_skip(); // 0 - - for (int i = 0; i < 10; ++i) - recv_data.read_skip(); - - recv_data >> clientIndex; // index - recv_data.read_skip(); // 0 - - sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str()); - - // prevent cheating - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC,UNIT_NPC_FLAG_PETITIONER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC)); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - uint32 charterid = 0; - uint32 cost = 0; - uint32 type = 0; - if (pCreature->isTabardDesigner()) - { - // if tabard designer, then trying to buy a guild charter. - // do not let if already in guild. - if (_player->GetGuildId()) - return; - - charterid = GUILD_CHARTER; - cost = GUILD_CHARTER_COST; - type = 9; - } - else - { - // TODO: find correct opcode - if (_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - return; - } - - switch(clientIndex) // arenaSlot+1 as received from client (1 from 3 case) - { - case 1: - charterid = ARENA_TEAM_CHARTER_2v2; - cost = ARENA_TEAM_CHARTER_2v2_COST; - type = 2; // 2v2 - break; - case 2: - charterid = ARENA_TEAM_CHARTER_3v3; - cost = ARENA_TEAM_CHARTER_3v3_COST; - type = 3; // 3v3 - break; - case 3: - charterid = ARENA_TEAM_CHARTER_5v5; - cost = ARENA_TEAM_CHARTER_5v5_COST; - type = 5; // 5v5 - break; - default: - sLog.outDebug("unknown selection at buy arena petition: %u", clientIndex); - return; - } - - if (_player->GetArenaTeamId(clientIndex - 1)) // arenaSlot+1 as received from client - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); - return; - } - } - - if (type == 9) - { - if (objmgr.GetGuildByName(name)) - { - SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S); - return; - } - if (objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) - { - SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_INVALID); - return; - } - } - else - { - if (objmgr.GetArenaTeamByName(name)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); - return; - } - if (objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); - return; - } - } - - ItemPrototype const *pProto = objmgr.GetItemPrototype(charterid); - if (!pProto) - { - _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0); - return; - } - - if (_player->GetMoney() < cost) - { //player hasn't got enough money - _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0); - return; - } - - ItemPosCountVec dest; - uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount); - if (msg != EQUIP_ERR_OK) - { - _player->SendBuyError(msg, pCreature, charterid, 0); - return; - } - - _player->ModifyMoney(-(int32)cost); - Item *charter = _player->StoreNewItem(dest, charterid, true); - if (!charter) - return; - - charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow()); - // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id - // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item) - charter->SetState(ITEM_CHANGED, _player); - _player->SendNewItem(charter, 1, true, false); - - // a petition is invalid, if both the owner and the type matches - // we checked above, if this player is in an arenateam, so this must be - // datacorruption - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type); - - std::ostringstream ssInvalidPetitionGUIDs; - - if (result) - { - do - { - Field *fields = result->Fetch(); - ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , "; - } while (result->NextRow()); - } - - // delete petitions with the same guid as this one - ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'"; - - sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); - CharacterDatabase.escape_string(name); - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); - CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); - CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')", - _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type); - CharacterDatabase.CommitTransaction(); -} - -void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) -{ - // ok - sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES"); - //recv_data.hexlike(); - - uint8 signs = 0; - uint64 petitionguid; - recv_data >> petitionguid; // petition guid - - // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?) - uint32 petitionguid_low = GUID_LOPART(petitionguid); - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low); - if (!result) - { - sLog.outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); - return; - } - Field *fields = result->Fetch(); - uint32 type = fields[0].GetUInt32(); - - // if guild petition and has guild => error, return; - if (type == 9 && _player->GetGuildId()) - return; - - result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low); - - // result == NULL also correct in case no sign yet - if (result) - signs = result->GetRowCount(); - - sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low); - - WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12)); - data << uint64(petitionguid); // petition guid - data << uint64(_player->GetGUID()); // owner guid - data << uint32(petitionguid_low); // guild guid (in mangos always same as GUID_LOPART(petitionguid) - data << uint8(signs); // sign's count - - for (uint8 i = 1; i <= signs; ++i) - { - Field *fields2 = result->Fetch(); - uint64 plguid = fields2[0].GetUInt64(); - - data << uint64(plguid); // Player GUID - data << (uint32)0; // there 0 ... - - result->NextRow(); - } - SendPacket(&data); -} - -void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("Received opcode CMSG_PETITION_QUERY"); // ok - //recv_data.hexlike(); - - uint32 guildguid; - uint64 petitionguid; - recv_data >> guildguid; // in Trinity always same as GUID_LOPART(petitionguid) - recv_data >> petitionguid; // petition guid - sLog.outDebug("CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid); - - SendPetitionQueryOpcode(petitionguid); -} - -void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) -{ - uint64 ownerguid = 0; - uint32 type; - std::string name = "NO_NAME_FOR_GUID"; - uint8 signs = 0; - - QueryResult_AutoPtr result = CharacterDatabase.PQuery( - "SELECT ownerguid, name, " - " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " - " type " - "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); - - if (result) - { - Field* fields = result->Fetch(); - ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - name = fields[1].GetCppString(); - signs = fields[2].GetUInt8(); - type = fields[3].GetUInt32(); - } - else - { - sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); - return; - } - - WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*12+2+10)); - data << uint32(GUID_LOPART(petitionguid)); // guild/team guid (in Trinity always same as GUID_LOPART(petition guid) - data << uint64(ownerguid); // charter owner guid - data << name; // name (guild/arena team) - data << uint8(0); // some string - if (type == 9) - { - data << uint32(9); - data << uint32(9); - data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition - } - else - { - data << uint32(type-1); - data << uint32(type-1); - data << uint32(type); // bypass client - side limitation, a different value is needed here for each petition - } - data << uint32(0); // 5 - data << uint32(0); // 6 - data << uint32(0); // 7 - data << uint32(0); // 8 - data << uint16(0); // 9 2 bytes field - data << uint32(0); // 10 - data << uint32(0); // 11 - data << uint32(0); // 13 count of next strings? - - for (int i = 0; i < 10; ++i) - data << uint8(0); // some string - - data << uint32(0); // 14 - - if (type == 9) - data << uint32(0); // 15 0 - guild, 1 - arena team - else - data << uint32(1); - - SendPacket(&data); -} - -void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("Received opcode MSG_PETITION_RENAME"); // ok - //recv_data.hexlike(); - - uint64 petitionguid; - uint32 type; - std::string newname; - - recv_data >> petitionguid; // guid - recv_data >> newname; // new name - - Item *item = _player->GetItemByGuid(petitionguid); - if (!item) - return; - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - - if (result) - { - Field* fields = result->Fetch(); - type = fields[0].GetUInt32(); - } - else - { - sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); - return; - } - - if (type == 9) - { - if (objmgr.GetGuildByName(newname)) - { - SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_GUILD_NAME_EXISTS_S); - return; - } - if (objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) - { - SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_GUILD_NAME_INVALID); - return; - } - } - else - { - if (objmgr.GetArenaTeamByName(newname)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S); - return; - } - if (objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID); - return; - } - } - - std::string db_newname = newname; - CharacterDatabase.escape_string(db_newname); - CharacterDatabase.PExecute("UPDATE petition SET name = '%s' WHERE petitionguid = '%u'", - db_newname.c_str(), GUID_LOPART(petitionguid)); - - sLog.outDebug("Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionguid), newname.c_str()); - WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1)); - data << uint64(petitionguid); - data << newname; - SendPacket(&data); -} - -void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); // ok - //recv_data.hexlike(); - - Field *fields; - uint64 petitionguid; - uint8 unk; - recv_data >> petitionguid; // petition guid - recv_data >> unk; - - QueryResult_AutoPtr result = CharacterDatabase.PQuery( - "SELECT ownerguid, " - " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " - " type " - "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); - - if (!result) - { - sLog.outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); - return; - } - - fields = result->Fetch(); - uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - uint8 signs = fields[1].GetUInt8(); - uint32 type = fields[2].GetUInt32(); - - uint32 plguidlo = _player->GetGUIDLow(); - if (GUID_LOPART(ownerguid) == plguidlo) - return; - - // not let enemies sign guild charter - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid)) - { - if (type != 9) - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); - else - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_NOT_ALLIED); - return; - } - - if (type != 9) - { - if (_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); - return; - } - - uint8 slot = ArenaTeam::GetSlotByType(type); - if (slot >= MAX_ARENA_SLOT) - return; - - if (_player->GetArenaTeamId(slot)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); - return; - } - - if (_player->GetArenaTeamIdInvited()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); - return; - } - } - else - { - if (_player->GetGuildId()) - { - SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_IN_GUILD_S); - return; - } - if (_player->GetGuildIdInvited()) - { - SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S); - return; - } - } - - if (++signs > type) // client signs maximum - return; - - //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account - //not allow sign another player from already sign player account - result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid)); - - if (result) - { - WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); - data << uint64(petitionguid); - data << uint64(_player->GetGUID()); - data << (uint32)PETITION_SIGN_ALREADY_SIGNED; - - // close at signer side - SendPacket(&data); - - // update for owner if online - if (Player *owner = objmgr.GetPlayer(ownerguid)) - owner->GetSession()->SendPacket(&data); - return; - } - - CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId()); - - sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId()); - - WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); - data << uint64(petitionguid); - data << uint64(_player->GetGUID()); - data << uint32(PETITION_SIGN_OK); - - // close at signer side - SendPacket(&data); - - // update signs count on charter, required testing... - //Item *item = _player->GetItemByGuid(petitionguid)); - //if (item) - // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); - - // update for owner if online - if (Player *owner = objmgr.GetPlayer(ownerguid)) - owner->GetSession()->SendPacket(&data); -} - -void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); // ok - //recv_data.hexlike(); - - uint64 petitionguid; - uint64 ownerguid; - recv_data >> petitionguid; // petition guid - sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if (!result) - return; - - Field *fields = result->Fetch(); - ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - - Player *owner = objmgr.GetPlayer(ownerguid); - if (owner) // petition owner online - { - WorldPacket data(MSG_PETITION_DECLINE, 8); - data << uint64(_player->GetGUID()); - owner->GetSession()->SendPacket(&data); - } -} - -void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); // ok - //recv_data.hexlike(); - - uint8 signs = 0; - uint64 petitionguid, plguid; - uint32 type, junk; - Player *player; - recv_data >> junk; // this is not petition type! - recv_data >> petitionguid; // petition guid - recv_data >> plguid; // player guid - - player = ObjectAccessor::FindPlayer(plguid); - if (!player) - return; - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if (!result) - return; - - Field *fields = result->Fetch(); - type = fields[0].GetUInt32(); - - sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); - - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam()) - { - if (type != 9) - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); - else - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_NOT_ALLIED); - return; - } - - if (type != 9) - { - if (player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) - { - // player is too low level to join an arena team - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_TARGET_TOO_LOW_S); - return; - } - - uint8 slot = ArenaTeam::GetSlotByType(type); - if (slot >= MAX_ARENA_SLOT) - return; - - if (player->GetArenaTeamId(slot)) - { - // player is already in an arena team - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S); - return; - } - - if (player->GetArenaTeamIdInvited()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); - return; - } - } - else - { - if (player->GetGuildId()) - { - SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_IN_GUILD_S); - return; - } - - if (player->GetGuildIdInvited()) - { - SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S); - return; - } - } - - result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - // result == NULL also correct charter without signs - if (result) - signs = result->GetRowCount(); - - WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12)); - data << uint64(petitionguid); // petition guid - data << uint64(_player->GetGUID()); // owner guid - data << uint32(GUID_LOPART(petitionguid)); // guild guid (in mangos always same as GUID_LOPART(petition guid) - data << uint8(signs); // sign's count - - for (uint8 i = 1; i <= signs; ++i) - { - Field *fields2 = result->Fetch(); - plguid = fields2[0].GetUInt64(); - - data << uint64(plguid); // Player GUID - data << (uint32)0; // there 0 ... - - result->NextRow(); - } - - player->GetSession()->SendPacket(&data); -} - -void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok - //recv_data.hexlike(); - - WorldPacket data; - uint64 petitionguid; - - uint32 ownerguidlo; - uint32 type; - std::string name; - - recv_data >> petitionguid; - - sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); - - // data - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if (result) - { - Field *fields = result->Fetch(); - ownerguidlo = fields[0].GetUInt32(); - name = fields[1].GetCppString(); - type = fields[2].GetUInt32(); - } - else - { - sLog.outError("petition table has broken data!"); - return; - } - - if (type == 9) - { - if (_player->GetGuildId()) - { - data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); - data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild - _player->GetSession()->SendPacket(&data); - return; - } - } - else - { - uint8 slot = ArenaTeam::GetSlotByType(type); - if (slot >= MAX_ARENA_SLOT) - return; - - if (_player->GetArenaTeamId(slot)) - { - //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); - //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild - //_player->GetSession()->SendPacket(&data); - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); - return; - } - } - - if (_player->GetGUIDLow() != ownerguidlo) - return; - - // signs - uint8 signs; - result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if (result) - signs = result->GetRowCount(); - else - signs = 0; - - uint32 count; - //if (signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS)) - if (type == 9) - count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS); - else - count = type-1; - if (signs < count) - { - data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); - data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures... - SendPacket(&data); - return; - } - - if (type == 9) - { - if (objmgr.GetGuildByName(name)) - { - SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S); - return; - } - } - else - { - if (objmgr.GetArenaTeamByName(name)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); - return; - } - } - - // and at last charter item check - Item *item = _player->GetItemByGuid(petitionguid); - if (!item) - return; - - // OK! - - // delete charter item - _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true); - - if (type == 9) // create guild - { - Guild* guild = new Guild; - if (!guild->Create(_player, name)) - { - delete guild; - return; - } - - // register guild and add guildmaster - objmgr.AddGuild(guild); - - // add members - for (uint8 i = 0; i < signs; ++i) - { - Field* fields = result->Fetch(); - guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank()); - result->NextRow(); - } - } - else // or arena team - { - ArenaTeam* at = new ArenaTeam; - if (!at->Create(_player->GetGUID(), type, name)) - { - sLog.outError("PetitionsHandler: arena team create failed."); - delete at; - return; - } - - uint32 icon, iconcolor, border, bordercolor, backgroud; - recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor; - - at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor); - - // register team and add captain - objmgr.AddArenaTeam(at); - sLog.outDebug("PetitonsHandler: arena team added to objmrg"); - - // add members - for (uint8 i = 0; i < signs; ++i) - { - Field* fields = result->Fetch(); - uint64 memberGUID = fields[0].GetUInt64(); - sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID)); - at->AddMember(memberGUID); - result->NextRow(); - } - } - - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - CharacterDatabase.CommitTransaction(); - - // created - sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid)); - - data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); - data << (uint32)PETITION_TURN_OK; - SendPacket(&data); -} - -void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("Received CMSG_PETITION_SHOWLIST"); // ok - //recv_data.hexlike(); - - uint64 guid; - recv_data >> guid; - - SendPetitionShowList(guid); -} - -void WorldSession::SendPetitionShowList(uint64 guid) -{ - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER); - if (!pCreature) - { - sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - uint8 count = 0; - if (pCreature->isTabardDesigner()) - count = 1; - else - count = 3; - - WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6); - data << guid; // npc guid - data << count; // count - if (count == 1) - { - data << uint32(1); // index - data << uint32(GUILD_CHARTER); // charter entry - data << uint32(16161); // charter display id - data << uint32(GUILD_CHARTER_COST); // charter cost - data << uint32(0); // unknown - data << uint32(9); // required signs? - } - else - { - // 2v2 - data << uint32(1); // index - data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry - data << uint32(16161); // charter display id - data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost - data << uint32(2); // unknown - data << uint32(2); // required signs? - // 3v3 - data << uint32(2); // index - data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry - data << uint32(16161); // charter display id - data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost - data << uint32(3); // unknown - data << uint32(3); // required signs? - // 5v5 - data << uint32(3); // index - data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry - data << uint32(16161); // charter display id - data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost - data << uint32(5); // unknown - data << uint32(5); // required signs? - } - //for (uint8 i = 0; i < count; ++i) - //{ - // data << uint32(i); // index - // data << uint32(GUILD_CHARTER); // charter entry - // data << uint32(16161); // charter display id - // data << uint32(GUILD_CHARTER_COST+i); // charter cost - // data << uint32(0); // unknown - // data << uint32(9); // required signs? - //} - SendPacket(&data); - sLog.outDebug("Sent SMSG_PETITION_SHOWLIST"); -} diff --git a/src/server/game/Entities/Player/TicketHandler.cpp b/src/server/game/Entities/Player/TicketHandler.cpp deleted file mode 100644 index 72ed25adbca..00000000000 --- a/src/server/game/Entities/Player/TicketHandler.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Language.h" -#include "WorldPacket.h" -#include "Common.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "World.h" - -void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) -{ - if (GetPlayer()->getLevel() < sWorld.getConfig(CONFIG_TICKET_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_TICKET_REQ), sWorld.getConfig(CONFIG_TICKET_LEVEL_REQ)); - return; - } - - if (GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(GetPlayer()->GetGUID())) - { - WorldPacket data(SMSG_GMTICKET_CREATE, 4); - data << uint32(1); // 1 - You already have GM ticket - SendPacket(&data); - return; - } - - uint32 map; - float x, y, z; - std::string ticketText, ticketText2; - - SendQueryTimeResponse(); - - WorldPacket data(SMSG_GMTICKET_CREATE, 4); - recv_data >> map; - recv_data >> x; - recv_data >> y; - recv_data >> z; - recv_data >> ticketText; - recv_data >> ticketText2; - - GM_Ticket *ticket = new GM_Ticket; - ticket->name = GetPlayer()->GetName(); - ticket->guid = objmgr.GenerateGMTicketId(); - ticket->playerGuid = GetPlayer()->GetGUID(); - ticket->message = ticketText; - ticket->createtime = time(NULL); - ticket->map = map; - ticket->pos_x = x; - ticket->pos_y = y; - ticket->pos_z = z; - ticket->timestamp = time(NULL); - ticket->closed = 0; - ticket->assignedToGM = 0; - ticket->comment = ""; - - objmgr.AddOrUpdateGMTicket(*ticket, true); - - data << uint32(2); - SendPacket(&data); - - sWorld.SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName(), ticket->guid); - -} - -void WorldSession::HandleGMTicketUpdateOpcode(WorldPacket & recv_data) -{ - WorldPacket data(SMSG_GMTICKET_UPDATETEXT, 4); - - std::string message; - recv_data >> message; - - GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(GetPlayer()->GetGUID()); - if (!ticket) - { - data << uint32(1); - SendPacket(&data); - return; - } - - ticket->message = message; - ticket->timestamp = time(NULL); - - objmgr.AddOrUpdateGMTicket(*ticket); - - data << uint32(2); - SendPacket(&data); - - sWorld.SendGMText(LANG_COMMAND_TICKETUPDATED, GetPlayer()->GetName(), ticket->guid); - -} - -void WorldSession::HandleGMTicketDeleteOpcode(WorldPacket & /*recv_data*/) -{ - GM_Ticket* ticket = objmgr.GetGMTicketByPlayer(GetPlayer()->GetGUID()); - - if (ticket) - { - WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); - data << uint32(9); - SendPacket(&data); - - sWorld.SendGMText(LANG_COMMAND_TICKETPLAYERABANDON, GetPlayer()->GetName(), ticket->guid); - objmgr.RemoveGMTicket(ticket, GetPlayer()->GetGUID(), false); - SendGMTicketGetTicket(0x0A, 0); - } -} - -void WorldSession::HandleGMTicketGetTicketOpcode(WorldPacket & /*recv_data*/) -{ - SendQueryTimeResponse(); - - GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(GetPlayer()->GetGUID()); - if (ticket) - SendGMTicketGetTicket(0x06, ticket->message.c_str()); - else - SendGMTicketGetTicket(0x0A, 0); - -} - -void WorldSession::HandleGMTicketSystemStatusOpcode(WorldPacket & /*recv_data*/) -{ - WorldPacket data(SMSG_GMTICKET_SYSTEMSTATUS, 4); - data << uint32(1); - SendPacket(&data); -} - -void WorldSession::SendGMTicketGetTicket(uint32 status, char const* text) -{ - int len = text ? strlen(text) : 0; - WorldPacket data(SMSG_GMTICKET_GETTICKET, (4+len+1+4+2+4+4)); - data << uint32(status); // standard 0x0A, 0x06 if text present - data << uint32(1); // unk flags, if 0, can't edit the ticket - if (status == 6) - { - data << text; // ticket text - data << uint8(0x7); // ticket category - data << float(0); // tickets in queue? - data << float(0); // if > "tickets in queue" then "We are currently experiencing a high volume of petitions." - data << float(0); // 0 - "Your ticket will be serviced soon", 1 - "Wait time currently unavailable" - data << uint8(0); // if == 2 and next field == 1 then "Your ticket has been escalated" - data << uint8(0); // const - } - SendPacket(&data); -} diff --git a/src/server/game/Entities/Player/TradeHandler.cpp b/src/server/game/Entities/Player/TradeHandler.cpp deleted file mode 100644 index 448a6e0520d..00000000000 --- a/src/server/game/Entities/Player/TradeHandler.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectAccessor.h" -#include "Log.h" -#include "Opcodes.h" -#include "Player.h" -#include "Item.h" -#include "SocialMgr.h" -#include "Language.h" - -enum TradeStatus -{ - TRADE_STATUS_BUSY = 0, - TRADE_STATUS_BEGIN_TRADE = 1, - TRADE_STATUS_OPEN_WINDOW = 2, - TRADE_STATUS_TRADE_CANCELED = 3, - TRADE_STATUS_TRADE_ACCEPT = 4, - TRADE_STATUS_BUSY_2 = 5, - TRADE_STATUS_NO_TARGET = 6, - TRADE_STATUS_BACK_TO_TRADE = 7, - TRADE_STATUS_TRADE_COMPLETE = 8, - // 9? - TRADE_STATUS_TARGET_TO_FAR = 10, - TRADE_STATUS_WRONG_FACTION = 11, - TRADE_STATUS_CLOSE_WINDOW = 12, - // 13? - TRADE_STATUS_IGNORE_YOU = 14, - TRADE_STATUS_YOU_STUNNED = 15, - TRADE_STATUS_TARGET_STUNNED = 16, - TRADE_STATUS_YOU_DEAD = 17, - TRADE_STATUS_TARGET_DEAD = 18, - TRADE_STATUS_YOU_LOGOUT = 19, - TRADE_STATUS_TARGET_LOGOUT = 20, - TRADE_STATUS_TRIAL_ACCOUNT = 21, // Trial accounts can not perform that action - TRADE_STATUS_ONLY_CONJURED = 22 // You can only trade conjured items... (cross realm BG related). -}; - -void WorldSession::SendTradeStatus(uint32 status) -{ - WorldPacket data; - - switch(status) - { - case TRADE_STATUS_BEGIN_TRADE: - data.Initialize(SMSG_TRADE_STATUS, 4+8); - data << uint32(status); - data << uint64(0); - break; - case TRADE_STATUS_OPEN_WINDOW: - data.Initialize(SMSG_TRADE_STATUS, 4+4); - data << uint32(status); - data << uint32(0); // added in 2.4.0 - break; - case TRADE_STATUS_CLOSE_WINDOW: - data.Initialize(SMSG_TRADE_STATUS, 4+4+1+4); - data << uint32(status); - data << uint32(0); - data << uint8(0); - data << uint32(0); - break; - case TRADE_STATUS_ONLY_CONJURED: - data.Initialize(SMSG_TRADE_STATUS, 4+1); - data << uint32(status); - data << uint8(0); - break; - default: - data.Initialize(SMSG_TRADE_STATUS, 4); - data << uint32(status); - break; - } - - SendPacket(&data); -} - -void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Ignore Trade %u",_player->GetGUIDLow()); - // recvPacket.print_storage(); -} - -void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Busy Trade %u",_player->GetGUIDLow()); - // recvPacket.print_storage(); -} - -void WorldSession::SendUpdateTrade() -{ - Item *item = NULL; - - if (!_player || !_player->pTrader) - return; - - // reset trade status - if (_player->acceptTrade) - { - _player->acceptTrade = false; - SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - } - - if (_player->pTrader->acceptTrade) - { - _player->pTrader->acceptTrade = false; - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - } - - WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, (100)); // guess size - data << (uint8) 1; // can be different (only seen 0 and 1) - data << (uint32) 0; // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?) - data << (uint32) TRADE_SLOT_COUNT; // trade slots count/number?, = next field in most cases - data << (uint32) TRADE_SLOT_COUNT; // trade slots count/number?, = prev field in most cases - data << (uint32) _player->pTrader->tradeGold; // trader gold - data << (uint32) 0; // spell casted on lowest slot item - - for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) - { - item = (_player->pTrader->tradeItems[i] != 0 ? _player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]) : NULL); - - data << (uint8) i; // trade slot number, if not specified, then end of packet - - if (item) - { - data << (uint32) item->GetProto()->ItemId; // entry - // display id - data << (uint32) item->GetProto()->DisplayInfoID; - // stack count - data << (uint32) item->GetUInt32Value(ITEM_FIELD_STACK_COUNT); - data << (uint32) 0; // probably gift=1, created_by=0? - // gift creator - data << (uint64) item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR); - data << (uint32) item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT); - for (uint8 j = 0; j < 3; ++j) - data << (uint32) 0; // enchantment id (permanent/gems?) - // creator - data << (uint64) item->GetUInt64Value(ITEM_FIELD_CREATOR); - data << (uint32) item->GetSpellCharges(); // charges - data << (uint32) item->GetItemSuffixFactor(); // SuffixFactor - // random properties id - data << (int32) item->GetItemRandomPropertyId(); - data << (uint32) item->GetProto()->LockID; // lock id - // max durability - data << (uint32) item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); - // durability - data << (uint32) item->GetUInt32Value(ITEM_FIELD_DURABILITY); - } - else - { - for (uint8 j = 0; j < 18; j++) - data << uint32(0); - } - } - SendPacket(&data); -} - -//============================================================== -// transfer the items to the players - -void WorldSession::moveItems(Item* myItems[], Item* hisItems[]) -{ - for (int i=0; ipTrader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, myItems[i], false) == EQUIP_ERR_OK); - bool playerCanTrade = (hisItems[i] == NULL || _player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, hisItems[i], false) == EQUIP_ERR_OK); - if (traderCanTrade && playerCanTrade) - { - // Ok, if trade item exists and can be stored - // If we trade in both directions we had to check, if the trade will work before we actually do it - // A roll back is not possible after we stored it - if (myItems[i]) - { - // logging - sLog.outDebug("partner storing: %u",myItems[i]->GetGUIDLow()); - if (_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) - { - sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", - _player->GetName(),_player->GetSession()->GetAccountId(), - myItems[i]->GetProto()->Name1,myItems[i]->GetEntry(),myItems[i]->GetCount(), - _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId()); - } - - // store - _player->pTrader->MoveItemToInventory(traderDst, myItems[i], true, true); - } - if (hisItems[i]) - { - // logging - sLog.outDebug("player storing: %u",hisItems[i]->GetGUIDLow()); - if (_player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) - { - sLog.outCommand(_player->pTrader->GetSession()->GetAccountId(),"GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", - _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(), - hisItems[i]->GetProto()->Name1,hisItems[i]->GetEntry(),hisItems[i]->GetCount(), - _player->GetName(),_player->GetSession()->GetAccountId()); - } - - // store - _player->MoveItemToInventory(playerDst, hisItems[i], true, true); - } - } - else - { - // in case of fatal error log error message - // return the already removed items to the original owner - if (myItems[i]) - { - if (!traderCanTrade) - sLog.outError("trader can't store item: %u",myItems[i]->GetGUIDLow()); - if (_player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, myItems[i], false) == EQUIP_ERR_OK) - _player->MoveItemToInventory(playerDst, myItems[i], true, true); - else - sLog.outError("player can't take item back: %u",myItems[i]->GetGUIDLow()); - } - // return the already removed items to the original owner - if (hisItems[i]) - { - if (!playerCanTrade) - sLog.outError("player can't store item: %u",hisItems[i]->GetGUIDLow()); - if (_player->pTrader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, hisItems[i], false) == EQUIP_ERR_OK) - _player->pTrader->MoveItemToInventory(traderDst, hisItems[i], true, true); - else - sLog.outError("trader can't take item back: %u",hisItems[i]->GetGUIDLow()); - } - } - } -} - -//============================================================== - -void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) -{ - Item *myItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; - Item *hisItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; - bool myCanCompleteTrade=true,hisCanCompleteTrade=true; - - if (!GetPlayer()->pTrader) - return; - - // not accept case incorrect money amount - if (_player->tradeGold > _player->GetMoney()) - { - SendNotification(LANG_NOT_ENOUGH_GOLD); - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - _player->acceptTrade = false; - return; - } - - // not accept case incorrect money amount - if (_player->pTrader->tradeGold > _player->pTrader->GetMoney()) - { - _player->pTrader->GetSession()->SendNotification(LANG_NOT_ENOUGH_GOLD); - SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - _player->pTrader->acceptTrade = false; - return; - } - - // not accept if some items now can't be trade (cheating) - for (int i=0; itradeItems[i] != 0) - { - if (Item* item =_player->GetItemByGuid(_player->tradeItems[i])) - { - if (!item->CanBeTraded()) - { - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - } - } - if (_player->pTrader->tradeItems[i] != 0) - { - if (Item* item =_player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i])) - { - if (!item->CanBeTraded()) - { - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - } - } - } - - _player->acceptTrade = true; - if (_player->pTrader->acceptTrade) - { - // inform partner client - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); - - // store items in local list and set 'in-trade' flag - for (int i=0; itradeItems[i] != 0) - { - //Can return NULL - myItems[i] = _player->GetItemByGuid(_player->tradeItems[i]); - if (myItems[i]) - { - myItems[i]->SetInTrade(); - sLog.outDebug("Player trade item bag: %u slot: %u", myItems[i]->GetBagSlot(), myItems[i]->GetSlot()); - } - } - if (_player->pTrader->tradeItems[i] != 0) - { - //Can return NULL - hisItems[i]=_player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]); - if (hisItems[i]) - { - hisItems[i]->SetInTrade(); - sLog.outDebug("Player trade item bag: %u slot: %u", hisItems[i]->GetBagSlot(), hisItems[i]->GetSlot()); - } - } - } - - // test if item will fit in each inventory - hisCanCompleteTrade = (_player->pTrader->CanStoreItems(myItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); - myCanCompleteTrade = (_player->CanStoreItems(hisItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); - - // clear 'in-trade' flag - for (int i=0; iSetInTrade(false); - if (hisItems[i]) hisItems[i]->SetInTrade(false); - } - - // in case of missing space report error - if (!myCanCompleteTrade) - { - SendNotification(LANG_NOT_FREE_TRADE_SLOTS); - GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS); - SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - return; - } - else if (!hisCanCompleteTrade) - { - SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS); - GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS); - SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - return; - } - - // execute trade: 1. remove - for (int i=0; iSetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID()); - iPtr = _player->GetItemByGuid(_player->tradeItems[i]); - _player->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true); - } - if (hisItems[i]) - { - hisItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR,_player->pTrader->GetGUID()); - iPtr = _player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]); - _player->pTrader->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true); - } - } - - // execute trade: 2. store - moveItems(myItems, hisItems); - - // logging money - if (sWorld.getConfig(CONFIG_GM_LOG_TRADE)) - { - if (_player->GetSession()->GetSecurity() > SEC_PLAYER && _player->tradeGold > 0) - { - sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", - _player->GetName(),_player->GetSession()->GetAccountId(), - _player->tradeGold, - _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId()); - } - if (_player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && _player->pTrader->tradeGold > 0) - { - sLog.outCommand(_player->pTrader->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", - _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(), - _player->pTrader->tradeGold, - _player->GetName(),_player->GetSession()->GetAccountId()); - } - } - - // update money - _player->ModifyMoney(-int32(_player->tradeGold)); - _player->ModifyMoney(_player->pTrader->tradeGold); - _player->pTrader->ModifyMoney(-int32(_player->pTrader->tradeGold)); - _player->pTrader->ModifyMoney(_player->tradeGold); - - _player->ClearTrade(); - _player->pTrader->ClearTrade(); - - // desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards) - CharacterDatabase.BeginTransaction(); - _player->SaveInventoryAndGoldToDB(); - _player->pTrader->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); - - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); - SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); - - _player->pTrader->pTrader = NULL; - _player->pTrader = NULL; - } - else - { - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); - } -} - -void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/) -{ - if (!GetPlayer()->pTrader) - return; - - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); - _player->acceptTrade = false; -} - -void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/) -{ - if (!_player->pTrader) - return; - - _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW); - _player->pTrader->ClearTrade(); - - SendTradeStatus(TRADE_STATUS_OPEN_WINDOW); - _player->ClearTrade(); -} - -void WorldSession::SendCancelTrade() -{ - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); -} - -void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/) -{ - // sended also after LOGOUT COMPLETE - if (_player) // needed because STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT - _player->TradeCancel(true); -} - -void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) -{ - if (GetPlayer()->pTrader) - return; - - uint64 ID; - - if (!GetPlayer()->isAlive()) - { - SendTradeStatus(TRADE_STATUS_YOU_DEAD); - return; - } - - if (GetPlayer()->hasUnitState(UNIT_STAT_STUNNED)) - { - SendTradeStatus(TRADE_STATUS_YOU_STUNNED); - return; - } - - if (isLogingOut()) - { - SendTradeStatus(TRADE_STATUS_YOU_LOGOUT); - return; - } - - if (GetPlayer()->isInFlight()) - { - SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); - return; - } - - if (GetPlayer()->getLevel() < sWorld.getConfig(CONFIG_TRADE_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_TRADE_REQ), sWorld.getConfig(CONFIG_TRADE_LEVEL_REQ)); - return; - } - - recvPacket >> ID; - - Player* pOther = ObjectAccessor::FindPlayer(ID); - - if (!pOther) - { - SendTradeStatus(TRADE_STATUS_NO_TARGET); - return; - } - - if (pOther == GetPlayer() || pOther->pTrader) - { - SendTradeStatus(TRADE_STATUS_BUSY); - return; - } - - if (!pOther->isAlive()) - { - SendTradeStatus(TRADE_STATUS_TARGET_DEAD); - return; - } - - if (pOther->isInFlight()) - { - SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); - return; - } - - if (pOther->hasUnitState(UNIT_STAT_STUNNED)) - { - SendTradeStatus(TRADE_STATUS_TARGET_STUNNED); - return; - } - - if (pOther->GetSession()->isLogingOut()) - { - SendTradeStatus(TRADE_STATUS_TARGET_LOGOUT); - return; - } - - if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) - { - SendTradeStatus(TRADE_STATUS_IGNORE_YOU); - return; - } - - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && pOther->GetTeam() !=_player->GetTeam()) - { - SendTradeStatus(TRADE_STATUS_WRONG_FACTION); - return; - } - - if (!pOther->IsWithinDistInMap(_player,10.0f,false)) - { - SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); - return; - } - - if (pOther->getLevel() < sWorld.getConfig(CONFIG_TRADE_LEVEL_REQ)) - { - SendNotification(GetTrinityString(LANG_TRADE_OTHER_REQ), sWorld.getConfig(CONFIG_TRADE_LEVEL_REQ)); - return; - } - - // OK start trade - _player->pTrader = pOther; - pOther->pTrader =_player; - - WorldPacket data(SMSG_TRADE_STATUS, 12); - data << (uint32) TRADE_STATUS_BEGIN_TRADE; - data << (uint64)_player->GetGUID(); - _player->pTrader->GetSession()->SendPacket(&data); -} - -void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket) -{ - if (!_player->pTrader) - return; - - uint32 gold; - - recvPacket >> gold; - - // gold can be incorrect, but this is checked at trade finished. - _player->tradeGold = gold; - - _player->pTrader->GetSession()->SendUpdateTrade(); -} - -void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket) -{ - if (!_player->pTrader) - return; - - // send update - uint8 tradeSlot; - uint8 bag; - uint8 slot; - - recvPacket >> tradeSlot; - recvPacket >> bag; - recvPacket >> slot; - - // invalid slot number - if (tradeSlot >= TRADE_SLOT_COUNT) - { - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - - // check cheating, can't fail with correct client operations - Item* item = _player->GetItemByPos(bag,slot); - if (!item || (tradeSlot != TRADE_SLOT_NONTRADED && !item->CanBeTraded())) - { - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - - uint64 iGUID = item->GetGUID(); - - // prevent place single item into many trade slots using cheating and client bugs - for (int i = 0; i < TRADE_SLOT_COUNT; ++i) - { - if (_player->tradeItems[i] == iGUID) - { - // cheating attempt - SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); - return; - } - } - - _player->tradeItems[tradeSlot] = iGUID; - - _player->pTrader->GetSession()->SendUpdateTrade(); -} - -void WorldSession::HandleClearTradeItemOpcode(WorldPacket& recvPacket) -{ - if (!_player->pTrader) - return; - - uint8 tradeSlot; - recvPacket >> tradeSlot; - - // invalid slot number - if (tradeSlot >= TRADE_SLOT_COUNT) - return; - - _player->tradeItems[tradeSlot] = 0; - - _player->pTrader->GetSession()->SendUpdateTrade(); -} - diff --git a/src/server/game/Entities/Player/VoiceChatHandler.cpp b/src/server/game/Entities/Player/VoiceChatHandler.cpp deleted file mode 100644 index 78aafe1999b..00000000000 --- a/src/server/game/Entities/Player/VoiceChatHandler.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" - -void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_VOICE_SESSION_ENABLE"); - // uint8 isVoiceEnabled, uint8 isMicrophoneEnabled - recv_data.read_skip(); - recv_data.read_skip(); - recv_data.hexlike(); -} - -void WorldSession::HandleChannelVoiceOnOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_CHANNEL_VOICE_ON"); - // Enable Voice button in channel context menu - recv_data.hexlike(); -} - -void WorldSession::HandleSetActiveVoiceChannel(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_SET_ACTIVE_VOICE_CHANNEL"); - recv_data.read_skip(); - recv_data.read_skip(); - recv_data.hexlike(); -} - diff --git a/src/server/game/Entities/Transport/Transports.cpp b/src/server/game/Entities/Transport/Transports.cpp new file mode 100644 index 00000000000..444e115f8b9 --- /dev/null +++ b/src/server/game/Entities/Transport/Transports.cpp @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" + +#include "Transports.h" +#include "MapManager.h" +#include "ObjectMgr.h" +#include "Path.h" + +#include "WorldPacket.h" +#include "DBCStores.h" +#include "ProgressBar.h" + +#include "World.h" + +void MapManager::LoadTransports() +{ + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, name, period FROM transports"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u transports", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Transport *t = new Transport; + + Field *fields = result->Fetch(); + + uint32 entry = fields[0].GetUInt32(); + std::string name = fields[1].GetCppString(); + t->m_period = fields[2].GetUInt32(); + + const GameObjectInfo *goinfo = objmgr.GetGameObjectInfo(entry); + + if (!goinfo) + { + sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str()); + delete t; + continue; + } + + if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT) + { + sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str()); + delete t; + continue; + } + + // sLog.outString("Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name); + + std::set mapsUsed; + + if (!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed)) + // skip transports with empty waypoints list + { + sLog.outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.",goinfo->moTransport.taxiPathId); + delete t; + continue; + } + + float x, y, z, o; + uint32 mapid; + x = t->m_WayPoints[0].x; y = t->m_WayPoints[0].y; z = t->m_WayPoints[0].z; mapid = t->m_WayPoints[0].mapid; o = 1; + + // creates the Gameobject + if (!t->Create(entry, mapid, x, y, z, o, 100, 0)) + { + delete t; + continue; + } + + m_Transports.insert(t); + + for (std::set::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i) + m_TransportsByMap[*i].insert(t); + + //If we someday decide to use the grid to track transports, here: + t->SetMap(MapManager::Instance().CreateMap(mapid, t, 0)); + + //t->GetMap()->Add((GameObject *)t); + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u transports", count); + + // check transport data DB integrity + result = WorldDatabase.Query("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); + if (result) // wrong data found + { + do + { + Field *fields = result->Fetch(); + + uint32 guid = fields[0].GetUInt32(); + uint32 entry = fields[1].GetUInt32(); + std::string name = fields[2].GetCppString(); + sLog.outErrorDb("Transport %u '%s' have record (GUID: %u) in `gameobject`. Transports DON'T must have any records in `gameobject` or its behavior will be unpredictable/bugged.",entry,name.c_str(),guid); + } + while (result->NextRow()); + } +} + +Transport::Transport() : GameObject() +{ + m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_ROTATION); +} + +bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) +{ + Relocate(x,y,z,ang); + // instance id and phaseMask isn't set to values different from std. + + if (!IsPositionValid()) + { + sLog.outError("Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + guidlow,x,y); + return false; + } + + Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT); + + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(guidlow); + + if (!goinfo) + { + sLog.outErrorDb("Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f",guidlow, mapid, x, y, z, ang); + return false; + } + + m_goInfo = goinfo; + + SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); + + SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); + //SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); + SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64)); + SetUInt32Value(GAMEOBJECT_LEVEL, m_period); + SetEntry(goinfo->id); + + SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); + + SetGoState(GO_STATE_READY); + SetGoType(GameobjectTypes(goinfo->type)); + + SetGoAnimProgress(animprogress); + if (dynflags) + SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags)); + + SetName(goinfo->name); + + return true; +} + +struct keyFrame +{ + keyFrame(float _x, float _y, float _z, uint32 _mapid, int _actionflag, int _delay) + { + x = _x; y = _y; z = _z; mapid = _mapid; actionflag = _actionflag; delay = _delay; distFromPrev = -1; distSinceStop = -1; distUntilStop = -1; + tFrom = 0; tTo = 0; + } + + float x; + float y; + float z; + uint32 mapid; + int actionflag; + int delay; + float distSinceStop; + float distUntilStop; + float distFromPrev; + float tFrom, tTo; +}; + +bool Transport::GenerateWaypoints(uint32 pathid, std::set &mapids) +{ + TransportPath path; + objmgr.GetTransportPathNodes(pathid, path); + + if (path.Empty()) + return false; + + std::vector keyFrames; + int mapChange = 0; + mapids.clear(); + for (size_t i = 1; i < path.Size() - 1; ++i) + { + if (mapChange == 0) + { + if ((path[i].mapid == path[i+1].mapid)) + { + keyFrame k(path[i].x, path[i].y, path[i].z, path[i].mapid, path[i].actionFlag, path[i].delay); + keyFrames.push_back(k); + mapids.insert(k.mapid); + } + else + { + mapChange = 1; + } + } + else + { + --mapChange; + } + } + + int lastStop = -1; + int firstStop = -1; + + // first cell is arrived at by teleportation :S + keyFrames[0].distFromPrev = 0; + if (keyFrames[0].actionflag == 2) + { + lastStop = 0; + } + + // find the rest of the distances between key points + for (size_t i = 1; i < keyFrames.size(); ++i) + { + if ((keyFrames[i].actionflag == 1) || (keyFrames[i].mapid != keyFrames[i-1].mapid)) + { + keyFrames[i].distFromPrev = 0; + } + else + { + keyFrames[i].distFromPrev = + sqrt(pow(keyFrames[i].x - keyFrames[i - 1].x, 2) + + pow(keyFrames[i].y - keyFrames[i - 1].y, 2) + + pow(keyFrames[i].z - keyFrames[i - 1].z, 2)); + } + if (keyFrames[i].actionflag == 2) + { + // remember first stop frame + if (firstStop == -1) + firstStop = i; + lastStop = i; + } + } + + float tmpDist = 0; + for (size_t i = 0; i < keyFrames.size(); ++i) + { + int j = (i + lastStop) % keyFrames.size(); + if (keyFrames[j].actionflag == 2) + tmpDist = 0; + else + tmpDist += keyFrames[j].distFromPrev; + keyFrames[j].distSinceStop = tmpDist; + } + + for (int i = int(keyFrames.size()) - 1; i >= 0; i--) + { + int j = (i + (firstStop+1)) % keyFrames.size(); + tmpDist += keyFrames[(j + 1) % keyFrames.size()].distFromPrev; + keyFrames[j].distUntilStop = tmpDist; + if (keyFrames[j].actionflag == 2) + tmpDist = 0; + } + + for (size_t i = 0; i < keyFrames.size(); ++i) + { + if (keyFrames[i].distSinceStop < (30 * 30 * 0.5f)) + keyFrames[i].tFrom = sqrt(2 * keyFrames[i].distSinceStop); + else + keyFrames[i].tFrom = ((keyFrames[i].distSinceStop - (30 * 30 * 0.5f)) / 30) + 30; + + if (keyFrames[i].distUntilStop < (30 * 30 * 0.5f)) + keyFrames[i].tTo = sqrt(2 * keyFrames[i].distUntilStop); + else + keyFrames[i].tTo = ((keyFrames[i].distUntilStop - (30 * 30 * 0.5f)) / 30) + 30; + + keyFrames[i].tFrom *= 1000; + keyFrames[i].tTo *= 1000; + } + + // for (int i = 0; i < keyFrames.size(); ++i) { + // sLog.outString("%f, %f, %f, %f, %f, %f, %f", keyFrames[i].x, keyFrames[i].y, keyFrames[i].distUntilStop, keyFrames[i].distSinceStop, keyFrames[i].distFromPrev, keyFrames[i].tFrom, keyFrames[i].tTo); + // } + + // Now we're completely set up; we can move along the length of each waypoint at 100 ms intervals + // speed = max(30, t) (remember x = 0.5s^2, and when accelerating, a = 1 unit/s^2 + int t = 0; + bool teleport = false; + if (keyFrames[keyFrames.size() - 1].mapid != keyFrames[0].mapid) + teleport = true; + + WayPoint pos(keyFrames[0].mapid, keyFrames[0].x, keyFrames[0].y, keyFrames[0].z, teleport, 0); + m_WayPoints[0] = pos; + t += keyFrames[0].delay * 1000; + + uint32 cM = keyFrames[0].mapid; + for (size_t i = 0; i < keyFrames.size() - 1; ++i) + { + float d = 0; + float tFrom = keyFrames[i].tFrom; + float tTo = keyFrames[i].tTo; + + // keep the generation of all these points; we use only a few now, but may need the others later + if (((d < keyFrames[i + 1].distFromPrev) && (tTo > 0))) + { + while ((d < keyFrames[i + 1].distFromPrev) && (tTo > 0)) + { + tFrom += 100; + tTo -= 100; + + if (d > 0) + { + float newX, newY, newZ; + newX = keyFrames[i].x + (keyFrames[i + 1].x - keyFrames[i].x) * d / keyFrames[i + 1].distFromPrev; + newY = keyFrames[i].y + (keyFrames[i + 1].y - keyFrames[i].y) * d / keyFrames[i + 1].distFromPrev; + newZ = keyFrames[i].z + (keyFrames[i + 1].z - keyFrames[i].z) * d / keyFrames[i + 1].distFromPrev; + + bool teleport = false; + if (keyFrames[i].mapid != cM) + { + teleport = true; + cM = keyFrames[i].mapid; + } + + // sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ); + WayPoint pos(keyFrames[i].mapid, newX, newY, newZ, teleport, i); + if (teleport) + m_WayPoints[t] = pos; + } + + if (tFrom < tTo) // caught in tFrom dock's "gravitational pull" + { + if (tFrom <= 30000) + { + d = 0.5f * (tFrom / 1000) * (tFrom / 1000); + } + else + { + d = 0.5f * 30 * 30 + 30 * ((tFrom - 30000) / 1000); + } + d = d - keyFrames[i].distSinceStop; + } + else + { + if (tTo <= 30000) + { + d = 0.5f * (tTo / 1000) * (tTo / 1000); + } + else + { + d = 0.5f * 30 * 30 + 30 * ((tTo - 30000) / 1000); + } + d = keyFrames[i].distUntilStop - d; + } + t += 100; + } + t -= 100; + } + + if (keyFrames[i + 1].tFrom > keyFrames[i + 1].tTo) + t += 100 - ((long)keyFrames[i + 1].tTo % 100); + else + t += (long)keyFrames[i + 1].tTo % 100; + + bool teleport = false; + if ((keyFrames[i + 1].actionflag == 1) || (keyFrames[i + 1].mapid != keyFrames[i].mapid)) + { + teleport = true; + cM = keyFrames[i + 1].mapid; + } + + WayPoint pos(keyFrames[i + 1].mapid, keyFrames[i + 1].x, keyFrames[i + 1].y, keyFrames[i + 1].z, teleport, i); + + // sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport); +/* + if (keyFrames[i+1].delay > 5) + pos.delayed = true; +*/ + //if (teleport) + m_WayPoints[t] = pos; + + t += keyFrames[i + 1].delay * 1000; + // sLog.outString("------"); + } + + uint32 timer = t; + + // sLog.outDetail(" Generated %lu waypoints, total time %u.", (unsigned long)m_WayPoints.size(), timer); + + m_curr = m_WayPoints.begin(); + m_curr = GetNextWayPoint(); + m_next = GetNextWayPoint(); + m_pathTime = timer; + + m_nextNodeTime = m_curr->first; + + return true; +} + +Transport::WayPointMap::const_iterator Transport::GetNextWayPoint() +{ + WayPointMap::const_iterator iter = m_curr; + ++iter; + if (iter == m_WayPoints.end()) + iter = m_WayPoints.begin(); + return iter; +} + +void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) +{ + Map const* oldMap = GetMap(); + Relocate(x, y, z); + + for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) + { + Player *plr = *itr; + ++itr; + + if (plr->isDead() && !plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + { + plr->ResurrectPlayer(1.0); + } + plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT); + + //WorldPacket data(SMSG_811, 4); + //data << uint32(0); + //plr->GetSession()->SendPacket(&data); + } + + //we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference... + //player far teleport would try to create same instance, but we need it NOW for transport... + //correct me if I'm wrong O.o + //yes, you're right + + ResetMap(); + Map * newMap = MapManager::Instance().CreateMap(newMapid, this, 0); + SetMap(newMap); + assert (GetMap()); + + if (oldMap != newMap) + { + UpdateForMap(oldMap); + UpdateForMap(newMap); + } +} + +bool Transport::AddPassenger(Player* passenger) +{ + if (m_passengers.insert(passenger).second) + sLog.outDetail("Player %s boarded transport %s.", passenger->GetName(), GetName()); + return true; +} + +bool Transport::RemovePassenger(Player* passenger) +{ + if (m_passengers.erase(passenger)) + sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), GetName()); + return true; +} + +void Transport::CheckForEvent(uint32 entry, uint32 wp_id) +{ + uint32 key = entry*100+wp_id; + if (objmgr.TransportEventMap.find(key) != objmgr.TransportEventMap.end()) + GetMap()->ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL); +} + +void Transport::Update(uint32 /*p_time*/) +{ + if (m_WayPoints.size() <= 1) + return; + + m_timer = getMSTime() % m_period; + while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime)) + { + m_curr = GetNextWayPoint(); + m_next = GetNextWayPoint(); + + // first check help in case client-server transport coordinates de-synchronization + if (m_curr->second.mapid != GetMapId() || m_curr->second.teleport) + { + TeleportTransport(m_curr->second.mapid, m_curr->second.x, m_curr->second.y, m_curr->second.z); + } + else + { + Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z); + } +/* + if (m_curr->second.delayed) + { + switch (GetEntry()) + { + case 176495: + case 164871: + case 175080: + SendPlaySound(11804, false); break; // ZeppelinDocked + case 20808: + case 181646: + case 176231: + case 176244: + case 176310: + case 177233: + SendPlaySound(5495, false);break; // BoatDockingWarning + default: + SendPlaySound(5154, false); break; // ShipDocked + } + } +*/ + /* + for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) + { + PlayerSet::const_iterator it2 = itr; + ++itr; + //(*it2)->SetPosition(m_curr->second.x + (*it2)->GetTransOffsetX(), m_curr->second.y + (*it2)->GetTransOffsetY(), m_curr->second.z + (*it2)->GetTransOffsetZ(), (*it2)->GetTransOffsetO()); + } + */ + + m_nextNodeTime = m_curr->first; + + if (m_curr == m_WayPoints.begin() && (sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES) == 0) + sLog.outDetail(" ************ BEGIN ************** %s", this->m_name.c_str()); + + if ((sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES) == 0) + sLog.outDetail("%s moved to %d %f %f %f %d", this->m_name.c_str(), m_curr->second.id, m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid); + + //Transport Event System + CheckForEvent(this->GetEntry(), m_curr->second.id); + } +} + +void Transport::UpdateForMap(Map const* targetMap) +{ + Map::PlayerList const& pl = targetMap->GetPlayers(); + if (pl.isEmpty()) + return; + + if (GetMapId() == targetMap->GetId()) + { + for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) + { + if (this != itr->getSource()->GetTransport()) + { + UpdateData transData; + BuildCreateUpdateBlockForPlayer(&transData, itr->getSource()); + WorldPacket packet; + transData.BuildPacket(&packet); + itr->getSource()->SendDirectMessage(&packet); + } + } + } + else + { + UpdateData transData; + BuildOutOfRangeUpdateBlock(&transData); + WorldPacket out_packet; + transData.BuildPacket(&out_packet); + + for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) + if (this != itr->getSource()->GetTransport()) + itr->getSource()->SendDirectMessage(&out_packet); + } +} + diff --git a/src/server/game/Entities/Transport/Transports.h b/src/server/game/Entities/Transport/Transports.h new file mode 100644 index 00000000000..25b9ade1461 --- /dev/null +++ b/src/server/game/Entities/Transport/Transports.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRANSPORTS_H +#define TRANSPORTS_H + +#include "GameObject.h" + +#include +#include +#include + +class TransportPath +{ + public: + struct PathNode + { + uint32 mapid; + float x,y,z; + uint32 actionFlag; + uint32 delay; + }; + + void SetLength(const unsigned int sz) + { + i_nodes.resize(sz); + } + + unsigned int Size(void) const { return i_nodes.size(); } + bool Empty(void) const { return i_nodes.empty(); } + void Resize(unsigned int sz) { i_nodes.resize(sz); } + void Clear(void) { i_nodes.clear(); } + PathNode* GetNodes(void) { return static_cast(&i_nodes[0]); } + + PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } + const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } + + protected: + std::vector i_nodes; +}; + +class Transport : public GameObject +{ + public: + explicit Transport(); + + bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags); + bool GenerateWaypoints(uint32 pathid, std::set &mapids); + void Update(uint32 p_time); + bool AddPassenger(Player* passenger); + bool RemovePassenger(Player* passenger); + void CheckForEvent(uint32 entry, uint32 wp_id); + + typedef std::set PlayerSet; + PlayerSet const& GetPassengers() const { return m_passengers; } + + private: + struct WayPoint + { + WayPoint() : mapid(0), x(0), y(0), z(0), teleport(false), id(0) {} + WayPoint(uint32 _mapid, float _x, float _y, float _z, bool _teleport, uint32 _id) : + mapid(_mapid), x(_x), y(_y), z(_z), teleport(_teleport), id(_id) {} + uint32 mapid; + float x; + float y; + float z; + bool teleport; + uint32 id; + }; + + typedef std::map WayPointMap; + + WayPointMap::const_iterator m_curr; + WayPointMap::const_iterator m_next; + uint32 m_pathTime; + uint32 m_timer; + + PlayerSet m_passengers; + + public: + WayPointMap m_WayPoints; + uint32 m_nextNodeTime; + uint32 m_period; + + private: + void TeleportTransport(uint32 newMapid, float x, float y, float z); + void UpdateForMap(Map const* map); + WayPointMap::const_iterator GetNextWayPoint(); +}; +#endif + diff --git a/src/server/game/Events/GlobalEvents.cpp b/src/server/game/Events/GlobalEvents.cpp deleted file mode 100644 index 300527aad73..00000000000 --- a/src/server/game/Events/GlobalEvents.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup world -*/ - -#include "Log.h" -#include "Database/DatabaseEnv.h" -#include "Database/DatabaseImpl.h" -#include "Platform/Define.h" -#include "MapManager.h" -#include "ObjectAccessor.h" -#include "GlobalEvents.h" -#include "ObjectDefines.h" -#include "Corpse.h" - -static void CorpsesEraseCallBack(QueryResult_AutoPtr result, bool bones) -{ - if (!result) - return; - - do - { - Field *fields = result->Fetch(); - uint32 guidlow = fields[0].GetUInt32(); - float positionX = fields[1].GetFloat(); - float positionY = fields[2].GetFloat(); - uint32 mapid = fields[3].GetUInt32(); - uint64 player_guid = MAKE_NEW_GUID(fields[4].GetUInt32(), 0, HIGHGUID_PLAYER); - - uint64 guid = MAKE_NEW_GUID(guidlow, 0, HIGHGUID_CORPSE); - - sLog.outDebug("[Global event] Removing %s %u (X:%f Y:%f Map:%u).",(bones?"bones":"corpse"),guidlow,positionX,positionY,mapid); - - /// Resurrectable - convert corpses to bones - if (!bones) - { - if (!ObjectAccessor::Instance().ConvertCorpseForPlayer(player_guid)) - { - sLog.outDebug("Corpse %u not found in world or bones creating forbidden. Delete from DB.",guidlow); - CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); - } - } - else - ///- or delete bones - { - MapManager::Instance().RemoveBonesFromMap(mapid, guid, positionX, positionY); - - ///- remove bones from the database - CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); - } - } while (result->NextRow()); -} - -/// Handle periodic erase of corpses and bones -static void CorpsesErase(bool bones,uint32 delay) -{ - ///- Get the list of eligible corpses/bones to be removed - //No SQL injection (uint32 and enum) - CharacterDatabase.AsyncPQuery(&CorpsesEraseCallBack, bones, "SELECT guid,position_x,position_y,map,player FROM corpse WHERE time < (UNIX_TIMESTAMP()+'%u') AND corpse_type %s '0'", delay, (bones ? "=" : "<>")); -} - -/// not thread guarded variant for call from other thread -void CorpsesErase() -{ - CorpsesErase(true, 20*MINUTE); - CorpsesErase(false,3*DAY); -} - diff --git a/src/server/game/Events/GlobalEvents.h b/src/server/game/Events/GlobalEvents.h deleted file mode 100644 index 6af63bf4429..00000000000 --- a/src/server/game/Events/GlobalEvents.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup world -/// @{ -/// \file - -#ifndef __GLOBALEVENTS_H -#define __GLOBALEVENTS_H - -void CorpsesErase(); -void HandleCorpsesErase(void*); -#endif -/// @} - diff --git a/src/server/game/Events/UnitEvents.h b/src/server/game/Events/UnitEvents.h deleted file mode 100644 index a218e0dd34d..00000000000 --- a/src/server/game/Events/UnitEvents.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _UNITEVENTS -#define _UNITEVENTS - -#include "Common.h" - -class ThreatContainer; -class ThreatManager; -class HostileReference; - -//============================================================== -//============================================================== - -enum UNIT_EVENT_TYPE -{ - // Player/Pet changed on/offline status - UEV_THREAT_REF_ONLINE_STATUS = 1<<0, - - // Threat for Player/Pet changed - UEV_THREAT_REF_THREAT_CHANGE = 1<<1, - - // Player/Pet will be removed from list (dead) [for internal use] - UEV_THREAT_REF_REMOVE_FROM_LIST = 1<<2, - - // Player/Pet entered/left water or some other place where it is/was not accessible for the creature - UEV_THREAT_REF_ASSECCIBLE_STATUS = 1<<3, - - // Threat list is going to be sorted (if dirty flag is set) - UEV_THREAT_SORT_LIST = 1<<4, - - // New target should be fetched, could tbe the current target as well - UEV_THREAT_SET_NEXT_TARGET = 1<<5, - - // A new victim (target) was set. Could be NULL - UEV_THREAT_VICTIM_CHANGED = 1<<6, - - // Future use - //UEV_UNIT_KILLED = 1<<7, - - //Future use - //UEV_UNIT_HEALTH_CHANGE = 1<<8, -}; - -#define UEV_THREAT_REF_EVENT_MASK (UEV_THREAT_REF_ONLINE_STATUS | UEV_THREAT_REF_THREAT_CHANGE | UEV_THREAT_REF_REMOVE_FROM_LIST | UEV_THREAT_REF_ASSECCIBLE_STATUS) -#define UEV_THREAT_MANAGER_EVENT_MASK (UEV_THREAT_SORT_LIST | UEV_THREAT_SET_NEXT_TARGET | UEV_THREAT_VICTIM_CHANGED) -#define UEV_ALL_EVENT_MASK (0xffffffff) - -// Future use -//#define UEV_UNIT_EVENT_MASK (UEV_UNIT_KILLED | UEV_UNIT_HEALTH_CHANGE) - -//============================================================== - -class UnitBaseEvent -{ - private: - uint32 iType; - public: - UnitBaseEvent(uint32 pType) { iType = pType; } - uint32 getType() const { return iType; } - bool matchesTypeMask(uint32 pMask) const { return iType & pMask; } - - void setType(uint32 pType) { iType = pType; } - -}; - -//============================================================== - -class ThreatRefStatusChangeEvent : public UnitBaseEvent -{ - private: - HostileReference* iHostileReference; - union - { - float iFValue; - int32 iIValue; - bool iBValue; - }; - ThreatManager* iThreatManager; - public: - ThreatRefStatusChangeEvent(uint32 pType) : UnitBaseEvent(pType) { iHostileReference = NULL; } - - ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; } - - ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, float pValue) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; iFValue = pValue; } - - ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, bool pValue) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; iBValue = pValue; } - - int32 getIValue() const { return iIValue; } - - float getFValue() const { return iFValue; } - - bool getBValue() const { return iBValue; } - - void setBValue(bool pValue) { iBValue = pValue; } - - HostileReference* getReference() const { return iHostileReference; } - - void setThreatManager(ThreatManager* pThreatManager) { iThreatManager = pThreatManager; } - - ThreatManager* getThreatManager() const { return iThreatManager; } -}; - -//============================================================== - -class ThreatManagerEvent : public ThreatRefStatusChangeEvent -{ - private: - ThreatContainer* iThreatContainer; - public: - ThreatManagerEvent(uint32 pType) : ThreatRefStatusChangeEvent(pType) {} - ThreatManagerEvent(uint32 pType, HostileReference* pHostileReference) : ThreatRefStatusChangeEvent(pType, pHostileReference) {} - - void setThreatContainer(ThreatContainer* pThreatContainer) { iThreatContainer = pThreatContainer; } - - ThreatContainer* getThreatContainer() const { return iThreatContainer; } -}; - -//============================================================== -#endif - diff --git a/src/server/game/Globals/Formulas.h b/src/server/game/Globals/Formulas.h deleted file mode 100644 index e5961834a78..00000000000 --- a/src/server/game/Globals/Formulas.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_FORMULAS_H -#define TRINITY_FORMULAS_H - -#include "World.h" - -namespace Trinity -{ - namespace Honor - { - inline uint32 hk_honor_at_level(uint8 level, uint32 count = 1) - { - return uint32(ceil(count * (33.333f * ((float)level) / 21.50537f))); - } - } - namespace XP - { - enum XPColorChar { RED, ORANGE, YELLOW, GREEN, GRAY }; - - inline uint8 GetGrayLevel(uint8 pl_level) - { - if (pl_level <= 5) - return 0; - else if (pl_level <= 39) - return pl_level - 5 - pl_level/10; - else if (pl_level <= 59) - return pl_level - 1 - pl_level/5; - else - return pl_level - 9; - } - - inline XPColorChar GetColorCode(uint8 pl_level, uint8 mob_level) - { - if (mob_level >= pl_level + 5) - return RED; - else if (mob_level >= pl_level + 3) - return ORANGE; - else if (mob_level >= pl_level - 2) - return YELLOW; - else if (mob_level > GetGrayLevel(pl_level)) - return GREEN; - else - return GRAY; - } - - inline uint8 GetZeroDifference(uint8 pl_level) - { - if (pl_level < 8) return 5; - if (pl_level < 10) return 6; - if (pl_level < 12) return 7; - if (pl_level < 16) return 8; - if (pl_level < 20) return 9; - if (pl_level < 30) return 11; - if (pl_level < 40) return 12; - if (pl_level < 45) return 13; - if (pl_level < 50) return 14; - if (pl_level < 55) return 15; - if (pl_level < 60) return 16; - return 17; - } - - inline uint32 BaseGain(uint8 pl_level, uint8 mob_level, ContentLevels content) - { - uint32 nBaseExp; - switch (content) - { - case CONTENT_1_60: nBaseExp = 45; break; - case CONTENT_61_70: nBaseExp = 235; break; - case CONTENT_71_80: nBaseExp = 580; break; - default: - sLog.outError("BaseGain: Unsupported content level %u",content); - nBaseExp = 45; break; - } - - if (mob_level >= pl_level) - { - uint8 nLevelDiff = mob_level - pl_level; - if (nLevelDiff > 4) - nLevelDiff = 4; - return ((pl_level*5 + nBaseExp) * (20 + nLevelDiff)/10 + 1)/2; - } - else - { - uint8 gray_level = GetGrayLevel(pl_level); - if (mob_level > gray_level) - { - uint8 ZD = GetZeroDifference(pl_level); - return (pl_level*5 + nBaseExp) * (ZD + mob_level - pl_level)/ZD; - } - return 0; - } - } - - inline uint32 Gain(Player *pl, Unit *u) - { - if (u->GetTypeId() == TYPEID_UNIT && ( - ((Creature*)u)->isTotem() || ((Creature*)u)->isPet() || - (((Creature*)u)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL))) - return 0; - - uint32 xp_gain = BaseGain(pl->getLevel(), u->getLevel(), GetContentLevelsForMapAndZone(u->GetMapId(),u->GetZoneId())); - if (xp_gain == 0) - return 0; - - //elites in instances have a 2.75x xp bonus instead of the regular 2x world bonus - if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isElite()) - { - if(u->GetMap() && u->GetMap()->IsDungeon()) - xp_gain *= 2.75; - else - xp_gain *= 2; - } - - return uint32(xp_gain*sWorld.getRate(RATE_XP_KILL)); - } - - inline float xp_in_group_rate(uint32 count, bool isRaid) - { - if (isRaid) - { - // FIX ME: must apply decrease modifiers dependent from raid size - return 1.0f; - } - else - { - switch (count) - { - case 0: - case 1: - case 2: - return 1.0f; - case 3: - return 1.166f; - case 4: - return 1.3f; - case 5: - default: - return 1.4f; - } - } - } - } -} -#endif - diff --git a/src/server/game/Globals/GlobalEvents.cpp b/src/server/game/Globals/GlobalEvents.cpp new file mode 100644 index 00000000000..300527aad73 --- /dev/null +++ b/src/server/game/Globals/GlobalEvents.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup world +*/ + +#include "Log.h" +#include "Database/DatabaseEnv.h" +#include "Database/DatabaseImpl.h" +#include "Platform/Define.h" +#include "MapManager.h" +#include "ObjectAccessor.h" +#include "GlobalEvents.h" +#include "ObjectDefines.h" +#include "Corpse.h" + +static void CorpsesEraseCallBack(QueryResult_AutoPtr result, bool bones) +{ + if (!result) + return; + + do + { + Field *fields = result->Fetch(); + uint32 guidlow = fields[0].GetUInt32(); + float positionX = fields[1].GetFloat(); + float positionY = fields[2].GetFloat(); + uint32 mapid = fields[3].GetUInt32(); + uint64 player_guid = MAKE_NEW_GUID(fields[4].GetUInt32(), 0, HIGHGUID_PLAYER); + + uint64 guid = MAKE_NEW_GUID(guidlow, 0, HIGHGUID_CORPSE); + + sLog.outDebug("[Global event] Removing %s %u (X:%f Y:%f Map:%u).",(bones?"bones":"corpse"),guidlow,positionX,positionY,mapid); + + /// Resurrectable - convert corpses to bones + if (!bones) + { + if (!ObjectAccessor::Instance().ConvertCorpseForPlayer(player_guid)) + { + sLog.outDebug("Corpse %u not found in world or bones creating forbidden. Delete from DB.",guidlow); + CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); + } + } + else + ///- or delete bones + { + MapManager::Instance().RemoveBonesFromMap(mapid, guid, positionX, positionY); + + ///- remove bones from the database + CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); + } + } while (result->NextRow()); +} + +/// Handle periodic erase of corpses and bones +static void CorpsesErase(bool bones,uint32 delay) +{ + ///- Get the list of eligible corpses/bones to be removed + //No SQL injection (uint32 and enum) + CharacterDatabase.AsyncPQuery(&CorpsesEraseCallBack, bones, "SELECT guid,position_x,position_y,map,player FROM corpse WHERE time < (UNIX_TIMESTAMP()+'%u') AND corpse_type %s '0'", delay, (bones ? "=" : "<>")); +} + +/// not thread guarded variant for call from other thread +void CorpsesErase() +{ + CorpsesErase(true, 20*MINUTE); + CorpsesErase(false,3*DAY); +} + diff --git a/src/server/game/Globals/GlobalEvents.h b/src/server/game/Globals/GlobalEvents.h new file mode 100644 index 00000000000..6af63bf4429 --- /dev/null +++ b/src/server/game/Globals/GlobalEvents.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup world +/// @{ +/// \file + +#ifndef __GLOBALEVENTS_H +#define __GLOBALEVENTS_H + +void CorpsesErase(); +void HandleCorpsesErase(void*); +#endif +/// @} + diff --git a/src/server/game/Globals/Language.h b/src/server/game/Globals/Language.h deleted file mode 100644 index c0c8fc486f3..00000000000 --- a/src/server/game/Globals/Language.h +++ /dev/null @@ -1,1007 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __TRINITY_LANGUAGE_H -#define __TRINITY_LANGUAGE_H - -enum TrinityStrings -{ - // for chat commands - LANG_SELECT_CHAR_OR_CREATURE = 1, - LANG_SELECT_CREATURE = 2, - - // level 0 chat - LANG_SYSTEMMESSAGE = 3, - LANG_EVENTMESSAGE = 4, - LANG_NO_HELP_CMD = 5, - LANG_NO_CMD = 6, - LANG_NO_SUBCMD = 7, - LANG_SUBCMDS_LIST = 8, - LANG_AVIABLE_CMD = 9, - LANG_CMD_SYNTAX = 10, - LANG_ACCOUNT_LEVEL = 11, - LANG_CONNECTED_USERS = 12, - LANG_UPTIME = 13, - LANG_PLAYER_SAVED = 14, - LANG_PLAYERS_SAVED = 15, - LANG_GMS_ON_SRV = 16, - LANG_GMS_NOT_LOGGED = 17, - LANG_YOU_IN_FLIGHT = 18, - //LANG_YOU_IN_BATTLEGROUND = 19, not used - //LANG_TARGET_IN_FLIGHT = 20, not used - LANG_CHAR_IN_FLIGHT = 21, - LANG_CHAR_NON_MOUNTED = 22, - LANG_YOU_IN_COMBAT = 23, - LANG_YOU_USED_IT_RECENTLY = 24, - LANG_COMMAND_NOTCHANGEPASSWORD = 25, - LANG_COMMAND_PASSWORD = 26, - LANG_COMMAND_WRONGOLDPASSWORD = 27, - LANG_COMMAND_ACCLOCKLOCKED = 28, - LANG_COMMAND_ACCLOCKUNLOCKED = 29, - LANG_SPELL_RANK = 30, - LANG_KNOWN = 31, - LANG_LEARN = 32, - LANG_PASSIVE = 33, - LANG_TALENT = 34, - LANG_ACTIVE = 35, - LANG_COMPLETE = 36, - LANG_OFFLINE = 37, - LANG_ON = 38, - LANG_OFF = 39, - LANG_YOU_ARE = 40, - LANG_VISIBLE = 41, - LANG_INVISIBLE = 42, - LANG_DONE = 43, - LANG_YOU = 44, - LANG_UNKNOWN = 45, - LANG_ERROR = 46, - LANG_NON_EXIST_CHARACTER = 47, - LANG_FRIEND_IGNORE_UNKNOWN = 48, - LANG_LEVEL_MINREQUIRED = 49, - LANG_LEVEL_MINREQUIRED_AND_ITEM = 50, - LANG_NPC_TAINER_HELLO = 51, - LANG_COMMAND_INVALID_ITEM_COUNT = 52, - LANG_COMMAND_MAIL_ITEMS_LIMIT = 53, - LANG_NEW_PASSWORDS_NOT_MATCH = 54, - LANG_PASSWORD_TOO_LONG = 55, - LANG_MOTD_CURRENT = 56, - LANG_USING_WORLD_DB = 57, - LANG_USING_SCRIPT_LIB = 58, - LANG_USING_EVENT_AI = 59, - LANG_CONNECTED_PLAYERS = 60, - LANG_ACCOUNT_ADDON = 61, - // Room for more level 0 62-99 not used - - // level 1 chat - LANG_GLOBAL_NOTIFY = 100, - LANG_MAP_POSITION = 101, - LANG_IS_TELEPORTED = 102, - LANG_CANNOT_SUMMON_TO_INST = 103, - LANG_CANNOT_GO_TO_INST_PARTY = 104, - LANG_CANNOT_GO_TO_INST_GM = 105, - LANG_CANNOT_GO_INST_INST = 106, - LANG_CANNOT_SUMMON_INST_INST = 107, - LANG_SUMMONING = 108, - LANG_SUMMONED_BY = 109, - LANG_TELEPORTING_TO = 110, - LANG_TELEPORTED_TO_BY = 111, - LANG_NO_PLAYER = 112, - LANG_APPEARING_AT = 113, - LANG_APPEARING_TO = 114, - LANG_BAD_VALUE = 115, - LANG_NO_CHAR_SELECTED = 116, - LANG_NOT_IN_GROUP = 117, - - LANG_YOU_CHANGE_HP = 118, - LANG_YOURS_HP_CHANGED = 119, - LANG_YOU_CHANGE_MANA = 120, - LANG_YOURS_MANA_CHANGED = 121, - LANG_YOU_CHANGE_ENERGY = 122, - LANG_YOURS_ENERGY_CHANGED = 123, - - LANG_CURRENT_ENERGY = 124, //log - LANG_YOU_CHANGE_RAGE = 125, - LANG_YOURS_RAGE_CHANGED = 126, - LANG_YOU_CHANGE_LVL = 127, - LANG_CURRENT_FACTION = 128, - LANG_WRONG_FACTION = 129, - LANG_YOU_CHANGE_FACTION = 130, - LANG_YOU_CHANGE_SPELLFLATID = 131, - LANG_YOURS_SPELLFLATID_CHANGED = 132, - LANG_YOU_GIVE_TAXIS = 133, - LANG_YOU_REMOVE_TAXIS = 134, - LANG_YOURS_TAXIS_ADDED = 135, - LANG_YOURS_TAXIS_REMOVED = 136, - - LANG_YOU_CHANGE_ASPEED = 137, - LANG_YOURS_ASPEED_CHANGED = 138, - LANG_YOU_CHANGE_SPEED = 139, - LANG_YOURS_SPEED_CHANGED = 140, - LANG_YOU_CHANGE_SWIM_SPEED = 141, - LANG_YOURS_SWIM_SPEED_CHANGED = 142, - LANG_YOU_CHANGE_BACK_SPEED = 143, - LANG_YOURS_BACK_SPEED_CHANGED = 144, - LANG_YOU_CHANGE_FLY_SPEED = 145, - LANG_YOURS_FLY_SPEED_CHANGED = 146, - - LANG_YOU_CHANGE_SIZE = 147, - LANG_YOURS_SIZE_CHANGED = 148, - LANG_NO_MOUNT = 149, - LANG_YOU_GIVE_MOUNT = 150, - LANG_MOUNT_GIVED = 151, - - LANG_CURRENT_MONEY = 152, - LANG_YOU_TAKE_ALL_MONEY = 153, - LANG_YOURS_ALL_MONEY_GONE = 154, - LANG_YOU_TAKE_MONEY = 155, - LANG_YOURS_MONEY_TAKEN = 156, - LANG_YOU_GIVE_MONEY = 157, - LANG_YOURS_MONEY_GIVEN = 158, - LANG_YOU_HEAR_SOUND = 159, - - LANG_NEW_MONEY = 160, // Log - - LANG_REMOVE_BIT = 161, - LANG_SET_BIT = 162, - LANG_COMMAND_TELE_TABLEEMPTY = 163, - LANG_COMMAND_TELE_NOTFOUND = 164, - LANG_COMMAND_TELE_PARAMETER = 165, - LANG_COMMAND_TELE_NOLOCATION = 166, - // 167 // not used - LANG_COMMAND_TELE_LOCATION = 168, - - LANG_MAIL_SENT = 169, - LANG_SOUND_NOT_EXIST = 170, - LANG_CANT_TELEPORT_SELF = 171, - LANG_CONSOLE_COMMAND = 172, - LANG_YOU_CHANGE_RUNIC_POWER = 173, - LANG_YOURS_RUNIC_POWER_CHANGED = 174, - LANG_LIQUID_STATUS = 175, - // Room for more level 1 176-199 not used - - // level 2 chat - LANG_NO_SELECTION = 200, - LANG_OBJECT_GUID = 201, - LANG_TOO_LONG_NAME = 202, - LANG_CHARS_ONLY = 203, - LANG_TOO_LONG_SUBNAME = 204, - LANG_NOT_IMPLEMENTED = 205, - - LANG_ITEM_ADDED_TO_LIST = 206, - LANG_ITEM_NOT_FOUND = 207, - LANG_ITEM_DELETED_FROM_LIST = 208, - LANG_ITEM_NOT_IN_LIST = 209, - LANG_ITEM_ALREADY_IN_LIST = 210, - - LANG_RESET_SPELLS_ONLINE = 211, - LANG_RESET_SPELLS_OFFLINE = 212, - LANG_RESET_TALENTS_ONLINE = 213, - LANG_RESET_TALENTS_OFFLINE = 214, - LANG_RESET_SPELLS = 215, - LANG_RESET_TALENTS = 216, - - LANG_RESETALL_UNKNOWN_CASE = 217, - LANG_RESETALL_SPELLS = 218, - LANG_RESETALL_TALENTS = 219, - - LANG_WAYPOINT_NOTFOUND = 220, - LANG_WAYPOINT_NOTFOUNDLAST = 221, - LANG_WAYPOINT_NOTFOUNDSEARCH = 222, - LANG_WAYPOINT_NOTFOUNDDBPROBLEM = 223, - LANG_WAYPOINT_CREATSELECTED = 224, - LANG_WAYPOINT_CREATNOTFOUND = 225, - LANG_WAYPOINT_VP_SELECT = 226, - LANG_WAYPOINT_VP_NOTFOUND = 227, - LANG_WAYPOINT_VP_NOTCREATED = 228, - LANG_WAYPOINT_VP_ALLREMOVED = 229, - LANG_WAYPOINT_NOTCREATED = 230, - LANG_WAYPOINT_NOGUID = 231, - LANG_WAYPOINT_NOWAYPOINTGIVEN = 232, - LANG_WAYPOINT_ARGUMENTREQ = 233, - LANG_WAYPOINT_ADDED = 234, - LANG_WAYPOINT_ADDED_NO = 235, - LANG_WAYPOINT_CHANGED = 236, - LANG_WAYPOINT_CHANGED_NO = 237, - LANG_WAYPOINT_EXPORTED = 238, - LANG_WAYPOINT_NOTHINGTOEXPORT = 239, - LANG_WAYPOINT_IMPORTED = 240, - LANG_WAYPOINT_REMOVED = 241, - LANG_WAYPOINT_NOTREMOVED = 242, - LANG_WAYPOINT_TOOFAR1 = 243, - LANG_WAYPOINT_TOOFAR2 = 244, - LANG_WAYPOINT_TOOFAR3 = 245, - LANG_WAYPOINT_INFO_TITLE = 246, - LANG_WAYPOINT_INFO_WAITTIME = 247, - LANG_WAYPOINT_INFO_MODEL = 248, - LANG_WAYPOINT_INFO_EMOTE = 249, - LANG_WAYPOINT_INFO_SPELL = 250, - LANG_WAYPOINT_INFO_TEXT = 251, - LANG_WAYPOINT_INFO_AISCRIPT = 252, - - LANG_RENAME_PLAYER = 253, - LANG_RENAME_PLAYER_GUID = 254, - - LANG_WAYPOINT_WPCREATNOTFOUND = 255, - LANG_WAYPOINT_NPCNOTFOUND = 256, - - LANG_MOVE_TYPE_SET = 257, - LANG_MOVE_TYPE_SET_NODEL = 258, - LANG_USE_BOL = 259, - LANG_VALUE_SAVED = 260, - LANG_VALUE_SAVED_REJOIN = 261, - - LANG_COMMAND_GOAREATRNOTFOUND = 262, - LANG_INVALID_TARGET_COORD = 263, - LANG_INVALID_ZONE_COORD = 264, - LANG_INVALID_ZONE_MAP = 265, - LANG_COMMAND_TARGETOBJNOTFOUND = 266, - LANG_COMMAND_GOOBJNOTFOUND = 267, - LANG_COMMAND_GOCREATNOTFOUND = 268, - LANG_COMMAND_GOCREATMULTIPLE = 269, - LANG_COMMAND_DELCREATMESSAGE = 270, - LANG_COMMAND_CREATUREMOVED = 271, - LANG_COMMAND_CREATUREATSAMEMAP = 272, - LANG_COMMAND_OBJNOTFOUND = 273, - LANG_COMMAND_DELOBJREFERCREATURE = 274, - LANG_COMMAND_DELOBJMESSAGE = 275, - LANG_COMMAND_TURNOBJMESSAGE = 276, - LANG_COMMAND_MOVEOBJMESSAGE = 277, - LANG_COMMAND_VENDORSELECTION = 278, - LANG_COMMAND_NEEDITEMSEND = 279, - LANG_COMMAND_ADDVENDORITEMITEMS = 280, - LANG_COMMAND_KICKSELF = 281, - LANG_COMMAND_KICKMESSAGE = 282, - // 283, not used - LANG_COMMAND_WHISPERACCEPTING = 284, - LANG_COMMAND_WHISPERON = 285, - LANG_COMMAND_WHISPEROFF = 286, - LANG_COMMAND_CREATGUIDNOTFOUND = 287, - // TICKET STRINGS NEED REWRITE // 288-296 FREE - - // END - LANG_COMMAND_SPAWNDIST = 297, - LANG_COMMAND_SPAWNTIME = 298, - LANG_COMMAND_MODIFY_HONOR = 299, - - LANG_YOUR_CHAT_DISABLED = 300, - LANG_YOU_DISABLE_CHAT = 301, - LANG_CHAT_ALREADY_ENABLED = 302, - LANG_YOUR_CHAT_ENABLED = 303, - LANG_YOU_ENABLE_CHAT = 304, - - LANG_COMMAND_MODIFY_REP = 305, - LANG_COMMAND_MODIFY_ARENA = 306, - LANG_COMMAND_FACTION_NOTFOUND = 307, - LANG_COMMAND_FACTION_UNKNOWN = 308, - LANG_COMMAND_FACTION_INVPARAM = 309, - LANG_COMMAND_FACTION_DELTA = 310, - LANG_FACTION_LIST = 311, - LANG_FACTION_VISIBLE = 312, - LANG_FACTION_ATWAR = 313, - LANG_FACTION_PEACE_FORCED = 314, - LANG_FACTION_HIDDEN = 315, - LANG_FACTION_INVISIBLE_FORCED = 316, - LANG_FACTION_INACTIVE = 317, - LANG_REP_HATED = 318, - LANG_REP_HOSTILE = 319, - LANG_REP_UNFRIENDLY = 320, - LANG_REP_NEUTRAL = 321, - LANG_REP_FRIENDLY = 322, - LANG_REP_HONORED = 323, - LANG_REP_REVERED = 324, - LANG_REP_EXALTED = 325, - LANG_COMMAND_FACTION_NOREP_ERROR = 326, - LANG_FACTION_NOREPUTATION = 327, - LANG_LOOKUP_PLAYER_ACCOUNT = 328, - LANG_LOOKUP_PLAYER_CHARACTER = 329, - LANG_NO_PLAYERS_FOUND = 330, - LANG_EXTENDED_COST_NOT_EXIST = 331, - LANG_GM_ON = 332, - LANG_GM_OFF = 333, - LANG_GM_CHAT_ON = 334, - LANG_GM_CHAT_OFF = 335, - LANG_YOU_REPAIR_ITEMS = 336, - LANG_YOUR_ITEMS_REPAIRED = 337, - LANG_YOU_SET_WATERWALK = 338, - LANG_YOUR_WATERWALK_SET = 339, - LANG_CREATURE_FOLLOW_YOU_NOW = 340, - LANG_CREATURE_NOT_FOLLOW_YOU = 341, - LANG_CREATURE_NOT_FOLLOW_YOU_NOW = 342, - LANG_CREATURE_NON_TAMEABLE = 343, - LANG_YOU_ALREADY_HAVE_PET = 344, - LANG_CUSTOMIZE_PLAYER = 345, - LANG_CUSTOMIZE_PLAYER_GUID = 346, - LANG_COMMAND_GOTAXINODENOTFOUND = 347, - LANG_GAMEOBJECT_HAVE_INVALID_DATA = 348, - LANG_TITLE_LIST_CHAT = 349, - LANG_TITLE_LIST_CONSOLE = 350, - LANG_COMMAND_NOTITLEFOUND = 351, - LANG_INVALID_TITLE_ID = 352, - LANG_TITLE_ADD_RES = 353, - LANG_TITLE_REMOVE_RES = 354, - LANG_TITLE_CURRENT_RES = 355, - LANG_CURRENT_TITLE_RESET = 356, - // Room for more level 2 357-399 not used - - // level 3 chat - LANG_SCRIPTS_RELOADED = 400, - LANG_YOU_CHANGE_SECURITY = 401, - LANG_YOURS_SECURITY_CHANGED = 402, - LANG_YOURS_SECURITY_IS_LOW = 403, - LANG_CREATURE_MOVE_DISABLED = 404, - LANG_CREATURE_MOVE_ENABLED = 405, - LANG_NO_WEATHER = 406, - LANG_WEATHER_DISABLED = 407, - - LANG_BAN_YOUBANNED = 408, - LANG_BAN_YOUPERMBANNED = 409, - LANG_BAN_NOTFOUND = 410, - - LANG_UNBAN_UNBANNED = 411, - LANG_UNBAN_ERROR = 412, - - LANG_ACCOUNT_NOT_EXIST = 413, - - LANG_BANINFO_NOCHARACTER = 414, - LANG_BANINFO_NOIP = 415, - LANG_BANINFO_NOACCOUNTBAN = 416, - LANG_BANINFO_BANHISTORY = 417, - LANG_BANINFO_HISTORYENTRY = 418, - LANG_BANINFO_INFINITE = 419, - LANG_BANINFO_NEVER = 420, - LANG_BANINFO_YES = 421, - LANG_BANINFO_NO = 422, - LANG_BANINFO_IPENTRY = 423, - - LANG_BANLIST_NOIP = 424, - LANG_BANLIST_NOACCOUNT = 425, - LANG_BANLIST_NOCHARACTER = 426, - LANG_BANLIST_MATCHINGIP = 427, - LANG_BANLIST_MATCHINGACCOUNT = 428, - - LANG_COMMAND_LEARN_MANY_SPELLS = 429, - LANG_COMMAND_LEARN_CLASS_SPELLS = 430, - LANG_COMMAND_LEARN_CLASS_TALENTS = 431, - LANG_COMMAND_LEARN_ALL_LANG = 432, - LANG_COMMAND_LEARN_ALL_CRAFT = 433, - LANG_COMMAND_COULDNOTFIND = 434, - LANG_COMMAND_ITEMIDINVALID = 435, - LANG_COMMAND_NOITEMFOUND = 436, - LANG_COMMAND_LISTOBJINVALIDID = 437, - LANG_COMMAND_LISTITEMMESSAGE = 438, - LANG_COMMAND_LISTOBJMESSAGE = 439, - LANG_COMMAND_INVALIDCREATUREID = 440, - LANG_COMMAND_LISTCREATUREMESSAGE = 441, - LANG_COMMAND_NOAREAFOUND = 442, - LANG_COMMAND_NOITEMSETFOUND = 443, - LANG_COMMAND_NOSKILLFOUND = 444, - LANG_COMMAND_NOSPELLFOUND = 445, - LANG_COMMAND_NOQUESTFOUND = 446, - LANG_COMMAND_NOCREATUREFOUND = 447, - LANG_COMMAND_NOGAMEOBJECTFOUND = 448, - LANG_COMMAND_GRAVEYARDNOEXIST = 449, - LANG_COMMAND_GRAVEYARDALRLINKED = 450, - LANG_COMMAND_GRAVEYARDLINKED = 451, - LANG_COMMAND_GRAVEYARDWRONGZONE = 452, - // = 453, - LANG_COMMAND_GRAVEYARDERROR = 454, - LANG_COMMAND_GRAVEYARD_NOTEAM = 455, - LANG_COMMAND_GRAVEYARD_ANY = 456, - LANG_COMMAND_GRAVEYARD_ALLIANCE = 457, - LANG_COMMAND_GRAVEYARD_HORDE = 458, - LANG_COMMAND_GRAVEYARDNEAREST = 459, - LANG_COMMAND_ZONENOGRAVEYARDS = 460, - LANG_COMMAND_ZONENOGRAFACTION = 461, - LANG_COMMAND_TP_ALREADYEXIST = 462, - LANG_COMMAND_TP_ADDED = 463, - LANG_COMMAND_TP_ADDEDERR = 464, - LANG_COMMAND_TP_DELETED = 465, - LANG_COMMAND_NOTAXINODEFOUND = 466, - LANG_COMMAND_TARGET_LISTAURAS = 467, - LANG_COMMAND_TARGET_AURADETAIL = 468, - LANG_COMMAND_TARGET_LISTAURATYPE = 469, - LANG_COMMAND_TARGET_AURASIMPLE = 470, - - LANG_COMMAND_QUEST_NOTFOUND = 471, - LANG_COMMAND_QUEST_STARTFROMITEM = 472, - LANG_COMMAND_QUEST_REMOVED = 473, - LANG_COMMAND_QUEST_REWARDED = 474, - LANG_COMMAND_QUEST_COMPLETE = 475, - LANG_COMMAND_QUEST_ACTIVE = 476, - - LANG_COMMAND_FLYMODE_STATUS = 477, - - LANG_COMMAND_OPCODESENT = 478, - - LANG_COMMAND_IMPORT_SUCCESS = 479, - LANG_COMMAND_IMPORT_FAILED = 480, - LANG_COMMAND_EXPORT_SUCCESS = 481, - LANG_COMMAND_EXPORT_FAILED = 482, - - LANG_COMMAND_SPELL_BROKEN = 483, - - LANG_SET_SKILL = 484, - LANG_SET_SKILL_ERROR = 485, - - LANG_INVALID_SKILL_ID = 486, - LANG_LEARNING_GM_SKILLS = 487, - LANG_YOU_KNOWN_SPELL = 488, - LANG_TARGET_KNOWN_SPELL = 489, - LANG_UNKNOWN_SPELL = 490, - LANG_FORGET_SPELL = 491, - LANG_REMOVEALL_COOLDOWN = 492, - LANG_REMOVE_COOLDOWN = 493, - - LANG_ADDITEM = 494, //log - LANG_ADDITEMSET = 495, //log - LANG_REMOVEITEM = 496, - LANG_ITEM_CANNOT_CREATE = 497, - LANG_INSERT_GUILD_NAME = 498, - LANG_PLAYER_NOT_FOUND = 499, - LANG_PLAYER_IN_GUILD = 500, - LANG_GUILD_NOT_CREATED = 501, - LANG_NO_ITEMS_FROM_ITEMSET_FOUND = 502, - - LANG_DISTANCE = 503, - - LANG_ITEM_SLOT = 504, - LANG_ITEM_SLOT_NOT_EXIST = 505, - LANG_ITEM_ADDED_TO_SLOT = 506, - LANG_ITEM_SAVE_FAILED = 507, - LANG_ITEMLIST_SLOT = 508, - LANG_ITEMLIST_MAIL = 509, - LANG_ITEMLIST_AUCTION = 510, - - LANG_WRONG_LINK_TYPE = 511, - LANG_ITEM_LIST_CHAT = 512, - LANG_QUEST_LIST_CHAT = 513, - LANG_CREATURE_ENTRY_LIST_CHAT = 514, - LANG_CREATURE_LIST_CHAT = 515, - LANG_GO_ENTRY_LIST_CHAT = 516, - LANG_GO_LIST_CHAT = 517, - LANG_ITEMSET_LIST_CHAT = 518, - LANG_TELE_LIST = 519, - LANG_SPELL_LIST = 520, - LANG_SKILL_LIST_CHAT = 521, - - LANG_GAMEOBJECT_NOT_EXIST = 522, - - LANG_GAMEOBJECT_CURRENT = 523, //log - LANG_GAMEOBJECT_DETAIL = 524, - LANG_GAMEOBJECT_ADD = 525, - - LANG_MOVEGENS_LIST = 526, - LANG_MOVEGENS_IDLE = 527, - LANG_MOVEGENS_RANDOM = 528, - LANG_MOVEGENS_WAYPOINT = 529, - LANG_MOVEGENS_ANIMAL_RANDOM = 530, - LANG_MOVEGENS_CONFUSED = 531, - LANG_MOVEGENS_TARGETED_PLAYER = 532, - LANG_MOVEGENS_TARGETED_CREATURE = 533, - LANG_MOVEGENS_TARGETED_NULL = 534, - LANG_MOVEGENS_HOME_CREATURE = 535, - LANG_MOVEGENS_HOME_PLAYER = 536, - LANG_MOVEGENS_FLIGHT = 537, - LANG_MOVEGENS_UNKNOWN = 538, - - LANG_NPCINFO_CHAR = 539, - LANG_NPCINFO_LEVEL = 540, - LANG_NPCINFO_HEALTH = 541, - LANG_NPCINFO_FLAGS = 542, - LANG_NPCINFO_LOOT = 543, - LANG_NPCINFO_POSITION = 544, - LANG_NPCINFO_VENDOR = 545, - LANG_NPCINFO_TRAINER = 546, - LANG_NPCINFO_DUNGEON_ID = 547, - - LANG_PINFO_ACCOUNT = 548, - LANG_PINFO_LEVEL = 549, - LANG_PINFO_NO_REP = 550, - - LANG_YOU_SET_EXPLORE_ALL = 551, - LANG_YOU_SET_EXPLORE_NOTHING = 552, - LANG_YOURS_EXPLORE_SET_ALL = 553, - LANG_YOURS_EXPLORE_SET_NOTHING = 554, - - LANG_HOVER_ENABLED = 555, - LANG_HOVER_DISABLED = 556, - LANG_YOURS_LEVEL_UP = 557, - LANG_YOURS_LEVEL_DOWN = 558, - LANG_YOURS_LEVEL_PROGRESS_RESET = 559, - LANG_EXPLORE_AREA = 560, - LANG_UNEXPLORE_AREA = 561, - - LANG_UPDATE = 562, - LANG_UPDATE_CHANGE = 563, - LANG_TOO_BIG_INDEX = 564, - LANG_SET_UINT = 565, //log - LANG_SET_UINT_FIELD = 566, - LANG_SET_FLOAT = 567, //log - LANG_SET_FLOAT_FIELD = 568, - LANG_GET_UINT = 569, //log - LANG_GET_UINT_FIELD = 570, - LANG_GET_FLOAT = 571, //log - LANG_GET_FLOAT_FIELD = 572, - LANG_SET_32BIT = 573, //log - LANG_SET_32BIT_FIELD = 574, - LANG_CHANGE_32BIT = 575, //log - LANG_CHANGE_32BIT_FIELD = 576, - - LANG_INVISIBLE_INVISIBLE = 577, - LANG_INVISIBLE_VISIBLE = 578, - LANG_SELECTED_TARGET_NOT_HAVE_VICTIM = 579, - - LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST = 580, - LANG_COMMAND_NEAROBJMESSAGE = 581, - LANG_COMMAND_RAWPAWNTIMES = 582, - - LANG_EVENT_ENTRY_LIST_CHAT = 583, - LANG_NOEVENTFOUND = 584, - LANG_EVENT_NOT_EXIST = 585, - LANG_EVENT_INFO = 586, - LANG_EVENT_ALREADY_ACTIVE = 587, - LANG_EVENT_NOT_ACTIVE = 588, - - LANG_MOVEGENS_POINT = 589, - LANG_MOVEGENS_FEAR = 590, - LANG_MOVEGENS_DISTRACT = 591, - - LANG_COMMAND_LEARN_ALL_RECIPES = 592, - LANG_BANLIST_ACCOUNTS = 593, - LANG_BANLIST_ACCOUNTS_HEADER = 594, - LANG_BANLIST_IPS = 595, - LANG_BANLIST_IPS_HEADER = 596, - LANG_GMLIST = 597, - LANG_GMLIST_HEADER = 598, - LANG_GMLIST_EMPTY = 599, - // End Level 3 list, continued at 1100 - - // Battleground - LANG_BG_A_WINS = 600, - LANG_BG_H_WINS = 601, - - LANG_BG_WS_START_TWO_MINUTES = 753, - LANG_BG_WS_START_ONE_MINUTE = 602, - LANG_BG_WS_START_HALF_MINUTE = 603, - LANG_BG_WS_HAS_BEGUN = 604, - - LANG_BG_WS_CAPTURED_HF = 605, - LANG_BG_WS_CAPTURED_AF = 606, - LANG_BG_WS_DROPPED_HF = 607, - LANG_BG_WS_DROPPED_AF = 608, - LANG_BG_WS_RETURNED_AF = 609, - LANG_BG_WS_RETURNED_HF = 610, - LANG_BG_WS_PICKEDUP_HF = 611, - LANG_BG_WS_PICKEDUP_AF = 612, - LANG_BG_WS_F_PLACED = 613, - LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED = 614, - LANG_BG_WS_HORDE_FLAG_RESPAWNED = 615, - - LANG_BG_EY_START_TWO_MINUTES = 755, - LANG_BG_EY_START_ONE_MINUTE = 636, - LANG_BG_EY_START_HALF_MINUTE = 637, - LANG_BG_EY_HAS_BEGUN = 638, - - LANG_BG_AB_ALLY = 650, - LANG_BG_AB_HORDE = 651, - LANG_BG_AB_NODE_STABLES = 652, - LANG_BG_AB_NODE_BLACKSMITH = 653, - LANG_BG_AB_NODE_FARM = 654, - LANG_BG_AB_NODE_LUMBER_MILL = 655, - LANG_BG_AB_NODE_GOLD_MINE = 656, - LANG_BG_AB_NODE_TAKEN = 657, - LANG_BG_AB_NODE_DEFENDED = 658, - LANG_BG_AB_NODE_ASSAULTED = 659, - LANG_BG_AB_NODE_CLAIMED = 660, - - LANG_BG_AB_START_TWO_MINUTES = 754, - LANG_BG_AB_START_ONE_MINUTE = 661, - LANG_BG_AB_START_HALF_MINUTE = 662, - LANG_BG_AB_HAS_BEGUN = 663, - LANG_BG_AB_A_NEAR_VICTORY = 664, - LANG_BG_AB_H_NEAR_VICTORY = 665, - LANG_BG_MARK_BY_MAIL = 666, - - LANG_BG_EY_HAS_TAKEN_A_M_TOWER = 667, - LANG_BG_EY_HAS_TAKEN_H_M_TOWER = 668, - LANG_BG_EY_HAS_TAKEN_A_D_RUINS = 669, - LANG_BG_EY_HAS_TAKEN_H_D_RUINS = 670, - LANG_BG_EY_HAS_TAKEN_A_B_TOWER = 671, - LANG_BG_EY_HAS_TAKEN_H_B_TOWER = 672, - LANG_BG_EY_HAS_TAKEN_A_F_RUINS = 673, - LANG_BG_EY_HAS_TAKEN_H_F_RUINS = 674, - LANG_BG_EY_HAS_LOST_A_M_TOWER = 675, - LANG_BG_EY_HAS_LOST_H_M_TOWER = 676, - LANG_BG_EY_HAS_LOST_A_D_RUINS = 677, - LANG_BG_EY_HAS_LOST_H_D_RUINS = 678, - LANG_BG_EY_HAS_LOST_A_B_TOWER = 679, - LANG_BG_EY_HAS_LOST_H_B_TOWER = 680, - LANG_BG_EY_HAS_LOST_A_F_RUINS = 681, - LANG_BG_EY_HAS_LOST_H_F_RUINS = 682, - LANG_BG_EY_HAS_TAKEN_FLAG = 683, - LANG_BG_EY_CAPTURED_FLAG_A = 684, - LANG_BG_EY_CAPTURED_FLAG_H = 685, - LANG_BG_EY_DROPPED_FLAG = 686, - LANG_BG_EY_RESETED_FLAG = 687, - - LANG_ARENA_ONE_TOOLOW = 700, - LANG_ARENA_ONE_MINUTE = 701, - LANG_ARENA_THIRTY_SECONDS = 702, - LANG_ARENA_FIFTEEN_SECONDS = 703, - LANG_ARENA_HAS_BEGUN = 704, - - LANG_WAIT_BEFORE_SPEAKING = 705, - LANG_NOT_EQUIPPED_ITEM = 706, - LANG_PLAYER_DND = 707, - LANG_PLAYER_AFK = 708, - LANG_PLAYER_DND_DEFAULT = 709, - LANG_PLAYER_AFK_DEFAULT = 710, - - LANG_BG_QUEUE_ANNOUNCE_SELF = 711, - LANG_BG_QUEUE_ANNOUNCE_WORLD = 712, - LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713, -// = 714, not used - LANG_YOUR_BG_LEVEL_REQ_ERROR = 715, -// = 716, not used - LANG_BG_STARTED_ANNOUNCE_WORLD = 717, - LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN= 718, - LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT= 719, - - LANG_BG_GROUP_TOO_LARGE = 720, // "Your group is too large for this battleground. Please regroup to join." - LANG_ARENA_GROUP_TOO_LARGE = 721, // "Your group is too large for this arena. Please regroup to join." - LANG_ARENA_YOUR_TEAM_ONLY = 722, // "Your group has members not in your arena team. Please regroup to join." - LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match." - LANG_ARENA_GOLD_WINS = 724, // "The Gold Team wins!" - LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!" -// = 726, not used - LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining." - LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group." - LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group." - LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 730, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group." - LANG_BG_GROUP_MEMBER_DESERTER = 731, // "Someone in your party is Deserter. You can't join as group." - LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 732, // "Someone in your party is already in three battleground queues. You cannot join as group." - - LANG_CANNOT_TELE_TO_BG = 733, // "You cannot teleport to a battleground or arena map." - LANG_CANNOT_SUMMON_TO_BG = 734, // "You cannot summon players to a battleground or arena map." - LANG_CANNOT_GO_TO_BG_GM = 735, // "You must be in GM mode to teleport to a player in a battleground." - LANG_CANNOT_GO_TO_BG_FROM_BG = 736, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first." - LANG_DEBUG_ARENA_ON = 737, - LANG_DEBUG_ARENA_OFF = 738, - LANG_DEBUG_BG_ON = 739, - LANG_DEBUG_BG_OFF = 740, - LANG_DIST_ARENA_POINTS_START = 741, - LANG_DIST_ARENA_POINTS_ONLINE_START = 742, - LANG_DIST_ARENA_POINTS_ONLINE_END = 743, - LANG_DIST_ARENA_POINTS_TEAM_START = 744, - LANG_DIST_ARENA_POINTS_TEAM_END = 745, - LANG_DIST_ARENA_POINTS_END = 746, - LANG_BG_DISABLED = 747, - LANG_ARENA_DISABLED = 748, -// = 749, not used - LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." - LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." -// = 752, not used -// LANG_BG_WS_START_TWO_MINUTES = 753, - defined above -// LANG_BG_AB_START_TWO_MINUTES = 754, - defined above -// LANG_BG_EY_START_TWO_MINUTES = 755, - defined above - - // Room for BG/ARENA = 773-784, 788-799 not used - LANG_ARENA_TESTING = 785, - LANG_AUTO_ANN = 786, - LANG_ANNOUNCE_COLOR = 787, - - // in game strings - LANG_PET_INVALID_NAME = 800, - LANG_NOT_ENOUGH_GOLD = 801, - LANG_NOT_FREE_TRADE_SLOTS = 802, - LANG_NOT_PARTNER_FREE_TRADE_SLOTS = 803, - LANG_YOU_NOT_HAVE_PERMISSION = 804, - LANG_UNKNOWN_LANGUAGE = 805, - LANG_NOT_LEARNED_LANGUAGE = 806, - LANG_NEED_CHARACTER_NAME = 807, - LANG_PLAYER_NOT_EXIST_OR_OFFLINE = 808, - LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND = 809, - LANG_ACHIEVEMENT_EARNED = 810, - LANG_GUILD_MASTER = 811, - LANG_GUILD_OFFICER = 812, - LANG_GUILD_VETERAN = 813, - LANG_GUILD_MEMBER = 814, - LANG_GUILD_INITIATE = 815, - LANG_ZONE_NOFLYZONE = 816, - - LANG_COMMAND_CREATURETEMPLATE_NOTFOUND = 817, - LANG_COMMAND_CREATURESTORAGE_NOTFOUND = 818, - // Room for in-game strings 819-999 not used - - // Level 4 (CLI only commands) - LANG_COMMAND_EXIT = 1000, - LANG_ACCOUNT_DELETED = 1001, - LANG_ACCOUNT_NOT_DELETED_SQL_ERROR = 1002, - LANG_ACCOUNT_NOT_DELETED = 1003, - LANG_ACCOUNT_CREATED = 1004, - LANG_ACCOUNT_TOO_LONG = 1005, - LANG_ACCOUNT_ALREADY_EXIST = 1006, - LANG_ACCOUNT_NOT_CREATED_SQL_ERROR = 1007, - LANG_ACCOUNT_NOT_CREATED = 1008, - LANG_CHARACTER_DELETED = 1009, - LANG_ACCOUNT_LIST_HEADER = 1010, - LANG_ACCOUNT_LIST_ERROR = 1011, - LANG_ACCOUNT_LIST_BAR = 1012, - LANG_ACCOUNT_LIST_LINE = 1013, - LANG_ACCOUNT_LIST_EMPTY = 1014, - LANG_ACCOUNT_LIST_BAR_HEADER = 1015, - // Room for more level 4 1016-1099 not used - - // Level 3 (continue) - LANG_ACCOUNT_SETADDON = 1100, - LANG_MOTD_NEW = 1101, - LANG_SENDMESSAGE = 1102, - LANG_EVENT_ENTRY_LIST_CONSOLE = 1103, - LANG_CREATURE_ENTRY_LIST_CONSOLE = 1104, - LANG_ITEM_LIST_CONSOLE = 1105, - LANG_ITEMSET_LIST_CONSOLE = 1106, - LANG_GO_ENTRY_LIST_CONSOLE = 1107, - LANG_QUEST_LIST_CONSOLE = 1108, - LANG_SKILL_LIST_CONSOLE = 1109, - LANG_CREATURE_LIST_CONSOLE = 1110, - LANG_GO_LIST_CONSOLE = 1111, - LANG_FILE_OPEN_FAIL = 1112, - LANG_ACCOUNT_CHARACTER_LIST_FULL = 1113, - LANG_DUMP_BROKEN = 1114, - LANG_INVALID_CHARACTER_NAME = 1115, - LANG_INVALID_CHARACTER_GUID = 1116, - LANG_CHARACTER_GUID_IN_USE = 1117, - LANG_ITEMLIST_GUILD = 1118, - LANG_MUST_MALE_OR_FEMALE = 1119, - LANG_YOU_CHANGE_GENDER = 1120, - LANG_YOUR_GENDER_CHANGED = 1121, - LANG_SKILL_VALUES = 1122, - LANG_NO_PET_FOUND = 1123, - LANG_WRONG_PET_TYPE = 1124, - LANG_COMMAND_LEARN_PET_TALENTS = 1125, - LANG_RESET_PET_TALENTS = 1126, - LANG_RESET_PET_TALENTS_ONLINE = 1127, - LANG_TAXINODE_ENTRY_LIST_CHAT = 1128, - LANG_TAXINODE_ENTRY_LIST_CONSOLE = 1129, - // Room for more level 3 1130-1199 not used - - // Debug commands - LANG_CINEMATIC_NOT_EXIST = 1200, - LANG_MOVIE_NOT_EXIST = 1201, - // Room for more debug 1202-1299 not used - - // FREE IDS 1300-9999 - - // AV - LANG_BG_AV_ALLY = 1300, - LANG_BG_AV_HORDE = 1301, - LANG_BG_AV_TOWER_TAKEN = 1302, - LANG_BG_AV_TOWER_ASSAULTED = 1303, - LANG_BG_AV_TOWER_DEFENDED = 1304, - LANG_BG_AV_GRAVE_TAKEN = 1305, - LANG_BG_AV_GRAVE_DEFENDED = 1306, - LANG_BG_AV_GRAVE_ASSAULTED = 1307, - - LANG_BG_AV_MINE_TAKEN = 1308, - LANG_BG_AV_MINE_NORTH = 1309, - LANG_BG_AV_MINE_SOUTH = 1310, - - LANG_BG_AV_NODE_GRAVE_STORM_AID = 1311, - LANG_BG_AV_NODE_TOWER_DUN_S = 1312, - LANG_BG_AV_NODE_TOWER_DUN_N = 1313, - LANG_BG_AV_NODE_GRAVE_STORMPIKE = 1314, - LANG_BG_AV_NODE_TOWER_ICEWING = 1315, - LANG_BG_AV_NODE_GRAVE_STONE = 1316, - LANG_BG_AV_NODE_TOWER_STONE = 1317, - LANG_BG_AV_NODE_GRAVE_SNOW = 1318, - LANG_BG_AV_NODE_TOWER_ICE = 1319, - LANG_BG_AV_NODE_GRAVE_ICE = 1320, - LANG_BG_AV_NODE_TOWER_POINT = 1321, - LANG_BG_AV_NODE_GRAVE_FROST = 1322, - LANG_BG_AV_NODE_TOWER_FROST_E = 1323, - LANG_BG_AV_NODE_TOWER_FROST_W = 1324, - LANG_BG_AV_NODE_GRAVE_FROST_HUT = 1325, - - LANG_BG_AV_START_ONE_MINUTE = 1326, - LANG_BG_AV_START_HALF_MINUTE = 1327, - LANG_BG_AV_HAS_BEGUN = 1328, - LANG_BG_AV_A_NEAR_LOSE = 1329, - LANG_BG_AV_H_NEAR_LOSE = 1330, - LANG_BG_AV_H_CAPTAIN_DEAD = 1331, - LANG_BG_AV_A_CAPTAIN_DEAD = 1332, - LANG_BG_AV_START_TWO_MINUTES = 1333, - // FREE IDS 1334-1999 - - // Ticket Strings 2000-2029 - LANG_COMMAND_TICKETNEW = 2000, - LANG_COMMAND_TICKETUPDATED = 2001, - LANG_COMMAND_TICKETPLAYERABANDON = 2002, - LANG_COMMAND_TICKETCLOSED = 2003, - LANG_COMMAND_TICKETDELETED = 2004, - LANG_COMMAND_TICKETNOTEXIST = 2005, - LANG_COMMAND_TICKETCLOSEFIRST = 2006, - LANG_COMMAND_TICKETALREADYASSIGNED = 2007, - LANG_COMMAND_TICKETRELOAD = 2008, - LANG_COMMAND_TICKETSHOWLIST = 2009, - LANG_COMMAND_TICKETSHOWONLINELIST = 2010, - LANG_COMMAND_TICKETSHOWCLOSEDLIST = 2011, - LANG_COMMAND_TICKETASSIGNERROR_A = 2012, - LANG_COMMAND_TICKETASSIGNERROR_B = 2013, - LANG_COMMAND_TICKETNOTASSIGNED = 2014, - LANG_COMMAND_TICKETUNASSIGNSECURITY = 2015, - LANG_COMMAND_TICKETCANNOTCLOSE = 2016, - LANG_COMMAND_TICKETLISTGUID = 2017, - LANG_COMMAND_TICKETLISTNAME = 2018, - LANG_COMMAND_TICKETLISTAGE = 2019, - LANG_COMMAND_TICKETLISTASSIGNEDTO = 2020, - LANG_COMMAND_TICKETLISTUNASSIGNED = 2021, - LANG_COMMAND_TICKETLISTMESSAGE = 2022, - LANG_COMMAND_TICKETLISTCOMMENT = 2023, - LANG_COMMAND_TICKETLISTADDCOMMENT = 2024, - LANG_COMMAND_TICKETLISTAGECREATE = 2025, - - // Trinity strings 5000-9999 - LANG_COMMAND_FREEZE = 5000, - LANG_COMMAND_FREEZE_ERROR = 5001, - LANG_COMMAND_FREEZE_WRONG = 5002, - LANG_COMMAND_UNFREEZE = 5003, - LANG_COMMAND_NO_FROZEN_PLAYERS = 5004, - LANG_COMMAND_LIST_FREEZE = 5005, - LANG_COMMAND_FROZEN_PLAYERS = 5006, - LANG_INSTANCE_RAID_GROUP_ONLY = 5007, - LANG_INSTANCE_CLOSED = 5008, - LANG_COMMAND_PLAYED_TO_ALL = 5009, - LANG_NPCINFO_LINKGUID = 5010, - LANG_TELEPORTED_TO_BY_CONSOLE = 5011, - // for command lookup map - LANG_COMMAND_NOMAPFOUND = 5012, - LANG_CONTINENT = 5013, - LANG_INSTANCE = 5014, - LANG_BATTLEGROUND = 5015, - LANG_ARENA = 5016, - LANG_RAID = 5017, - LANG_HEROIC = 5018, - LANG_MOUNTABLE = 5019, - LANG_NPCINFO_PHASEMASK = 5020, - LANG_NPCINFO_ARMOR = 5021, - LANG_CHANNEL_NOT_PUBLIC = 5022, - LANG_CHANNEL_PUBLIC_CHANGED = 5023, - LANG_GOINFO_ENTRY = 5024, - LANG_GOINFO_TYPE = 5025, - LANG_GOINFO_DISPLAYID = 5026, - LANG_GOINFO_NAME = 5027, - // Room for more Trinity strings 5028-9999 - - // Level requirement notifications - LANG_SAY_REQ = 6604, - LANG_WHISPER_REQ = 6605, - LANG_CHANNEL_REQ = 6606, - LANG_AUCTION_REQ = 6607, - LANG_TICKET_REQ = 6608, - LANG_TRADE_REQ = 6609, - LANG_TRADE_OTHER_REQ = 6610, - LANG_MAIL_SENDER_REQ = 6611, - LANG_MAIL_RECEIVER_REQ = 6612, - - - // Used for GM Announcements - LANG_GM_BROADCAST = 6613, - LANG_GM_NOTIFY = 6614, - LANG_GM_ANNOUNCE_COLOR = 6615, - - LANG_GM_SILENCE = 6616, // "Silence is ON for %s" - Spell 1852 - - LANG_WORLD_CLOSED = 7523, - LANG_WORLD_OPENED = 7524, - - // Use for not-in-offcial-sources patches - // 10000-10999 - // opvp hp - LANG_OPVP_HP_CAPTURE_OVERLOOK_H = 10001, - LANG_OPVP_HP_CAPTURE_OVERLOOK_A = 10002, - LANG_OPVP_HP_CAPTURE_STADIUM_H = 10003, - LANG_OPVP_HP_CAPTURE_STADIUM_A = 10004, - LANG_OPVP_HP_CAPTURE_BROKENHILL_H = 10005, - LANG_OPVP_HP_CAPTURE_BROKENHILL_A = 10006, - LANG_OPVP_HP_LOOSE_OVERLOOK_H = 10007, - LANG_OPVP_HP_LOOSE_OVERLOOK_A = 10008, - LANG_OPVP_HP_LOOSE_STADIUM_H = 10009, - LANG_OPVP_HP_LOOSE_STADIUM_A = 10010, - LANG_OPVP_HP_LOOSE_BROKENHILL_H = 10011, - LANG_OPVP_HP_LOOSE_BROKENHILL_A = 10012, - // opvp zm - LANG_OPVP_ZM_CAPTURE_WEST_H = 10013, - LANG_OPVP_ZM_CAPTURE_WEST_A = 10014, - LANG_OPVP_ZM_CAPTURE_EAST_H = 10015, - LANG_OPVP_ZM_CAPTURE_EAST_A = 10016, - LANG_OPVP_ZM_CAPTURE_GY_H = 10017, - LANG_OPVP_ZM_CAPTURE_GY_A = 10018, - LANG_OPVP_ZM_LOOSE_WEST_H = 10019, - LANG_OPVP_ZM_LOOSE_WEST_A = 10020, - LANG_OPVP_ZM_LOOSE_EAST_H = 10021, - LANG_OPVP_ZM_LOOSE_EAST_A = 10022, - LANG_OPVP_ZM_LOOSE_GY_H = 10023, - LANG_OPVP_ZM_LOOSE_GY_A = 10024, - // opvp na - LANG_OPVP_NA_CAPTURE_H = 10025, - LANG_OPVP_NA_CAPTURE_A = 10026, - LANG_OPVP_NA_LOOSE_H = 10027, - LANG_OPVP_NA_LOOSE_A = 10028, - // opvp tf - LANG_OPVP_TF_CAPTURE_H = 10029, - LANG_OPVP_TF_CAPTURE_A = 10030, - LANG_OPVP_TF_LOOSE_H = 10031, - LANG_OPVP_TF_LOOSE_A = 10032, - // opvp ep - LANG_OPVP_EP_CAPTURE_NPT_H = 10033, - LANG_OPVP_EP_CAPTURE_NPT_A = 10034, - LANG_OPVP_EP_CAPTURE_EWT_H = 10035, - LANG_OPVP_EP_CAPTURE_EWT_A = 10036, - LANG_OPVP_EP_CAPTURE_CGT_H = 10037, - LANG_OPVP_EP_CAPTURE_CGT_A = 10038, - LANG_OPVP_EP_CAPTURE_PWT_H = 10039, - LANG_OPVP_EP_CAPTURE_PWT_A = 10040, - LANG_OPVP_EP_LOOSE_NPT_H = 10041, - LANG_OPVP_EP_LOOSE_NPT_A = 10042, - LANG_OPVP_EP_LOOSE_EWT_H = 10043, - LANG_OPVP_EP_LOOSE_EWT_A = 10044, - LANG_OPVP_EP_LOOSE_CGT_H = 10045, - LANG_OPVP_EP_LOOSE_CGT_A = 10046, - LANG_OPVP_EP_LOOSE_PWT_H = 10047, - LANG_OPVP_EP_LOOSE_PWT_A = 10048, - // opvp si - LANG_OPVP_SI_CAPTURE_H = 10049, - LANG_OPVP_SI_CAPTURE_A = 10050, - // opvp gossips - LANG_OPVP_EP_FLIGHT_NPT = 10051, - LANG_OPVP_EP_FLIGHT_EWT = 10052, - LANG_OPVP_EP_FLIGHT_CGT = 10053, - LANG_OPVP_ZM_GOSSIP_ALLIANCE = 10054, - LANG_OPVP_ZM_GOSSIP_HORDE = 10055, - - LANG_BG_SA_START_TWO_MINUTES = 10056, - LANG_BG_SA_START_ONE_MINUTE = 10057, - LANG_BG_SA_START_HALF_MINUTE = 10058, - LANG_BG_SA_HAS_BEGUN = 10059, - LANG_BG_SA_IS_UNDER_ATTACK = 10060,//The %s is under attack! - LANG_BG_SA_WAS_DESTROYED = 10061,//The %s was destroyed! - LANG_BG_SA_ROUND_ONE_END = 10062,//Round 1 - finished! - LANG_BG_SA_ALLIANCE_CAPTURED_RELIC = 10063,//The Alliance captured the titan portal! - LANG_BG_SA_HORDE_CAPTURED_RELIC = 10064,//The Horde captured the titan portal! - LANG_BG_SA_ROUND_TWO_ONE_MINUTE = 10065,//Round 2 of the Battle for the Strand of the Ancients begins in 1 minute. - LANG_BG_SA_ROUND_TWO_START_HALF_MINUTE = 10066,//Round 2 begins in 30 seconds. Prepare yourselves! - LANG_BG_SA_CHAMBER_BREACHED = 10067,//The chamber has been breached! The titan relic is vulnerable! - LANG_BG_SA_A_GY_SOUTH = 10068,//The Alliance captured the South Graveyard! - LANG_BG_SA_A_GY_WEST = 10069,//The Alliance captured the West Graveyard! - LANG_BG_SA_A_GY_EAST = 10070,//The Alliance captured the East Graveyard! - LANG_BG_SA_H_GY_SOUTH = 10071,//The Horde captured the South Graveyard! - LANG_BG_SA_H_GY_WEST = 10072,//The Horde captured the West Graveyard! - LANG_BG_SA_H_GY_EAST = 10073,//The Horde captured the East Graveyard! - - // Use for custom patches 11000-11999 - LANG_AUTO_BROADCAST = 11000, - LANG_INVALID_REALMID = 11001, - - // NOT RESERVED IDS 12000-1999999999 - // `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID) - // For other tables maybe 2000010000-2147483647 (max index) -}; -#endif - diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp new file mode 100644 index 00000000000..cf5bc728c6e --- /dev/null +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -0,0 +1,375 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "Policies/SingletonImp.h" +#include "Player.h" +#include "Creature.h" +#include "GameObject.h" +#include "DynamicObject.h" +#include "Vehicle.h" +#include "WorldPacket.h" +#include "Item.h" +#include "Corpse.h" +#include "GridNotifiers.h" +#include "MapManager.h" +#include "Map.h" +#include "CellImpl.h" +#include "GridNotifiersImpl.h" +#include "Opcodes.h" +#include "ObjectDefines.h" +#include "MapInstanced.h" +#include "World.h" + +#include + +#define CLASS_LOCK Trinity::ClassLevelLockable +INSTANTIATE_SINGLETON_2(ObjectAccessor, CLASS_LOCK); +INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ACE_Thread_Mutex); + +ObjectAccessor::ObjectAccessor() +{ +} + +ObjectAccessor::~ObjectAccessor() +{ + for (Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr) + { + itr->second->RemoveFromWorld(); + delete itr->second; + } +} + +Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, uint64 guid) +{ + if (IS_PLAYER_GUID(guid)) + return NULL; + + if (IS_PET_GUID(guid)) + return GetPet(guid); + + return u.IsInWorld() ? u.GetMap()->GetCreature(guid) : NULL; +} + +Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, uint64 guid) +{ + Corpse* ret = GetObjectInWorld(guid, (Corpse*)NULL); + + if (!ret) + return NULL; + + if (ret->GetMapId() != u.GetMapId()) + return NULL; + + if (ret->GetInstanceId() != u.GetInstanceId()) + return NULL; + + return ret; +} + +WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, uint64 guid) +{ + switch (GUID_HIPART(guid)) + { + case HIGHGUID_PLAYER: return FindPlayer(guid); + case HIGHGUID_GAMEOBJECT: return p.GetMap()->GetGameObject(guid); + case HIGHGUID_VEHICLE: + case HIGHGUID_UNIT: return p.GetMap()->GetCreature(guid); + case HIGHGUID_PET: return GetPet(guid); + case HIGHGUID_DYNAMICOBJECT: return p.GetMap()->GetDynamicObject(guid); + case HIGHGUID_TRANSPORT: return NULL; + case HIGHGUID_CORPSE: return GetCorpse(p,guid); + case HIGHGUID_MO_TRANSPORT: return NULL; + default: return NULL; + } +} + +Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, uint64 guid, uint32 typemask) +{ + switch (GUID_HIPART(guid)) + { + case HIGHGUID_ITEM: + if (typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER) + return ((Player const&)p).GetItemByGuid(guid); + break; + case HIGHGUID_PLAYER: + if (typemask & TYPEMASK_PLAYER) + return FindPlayer(guid); + break; + case HIGHGUID_GAMEOBJECT: + if (typemask & TYPEMASK_GAMEOBJECT) + return p.GetMap()->GetGameObject(guid); + break; + case HIGHGUID_UNIT: + case HIGHGUID_VEHICLE: + if (typemask & TYPEMASK_UNIT) + return p.GetMap()->GetCreature(guid); + break; + case HIGHGUID_PET: + if (typemask & TYPEMASK_UNIT) + return GetPet(guid); + break; + case HIGHGUID_DYNAMICOBJECT: + if (typemask & TYPEMASK_DYNAMICOBJECT) + return p.GetMap()->GetDynamicObject(guid); + break; + case HIGHGUID_TRANSPORT: + case HIGHGUID_CORPSE: + case HIGHGUID_MO_TRANSPORT: + break; + } + + return NULL; +} + +Player* ObjectAccessor::FindPlayer(uint64 guid) +{ + Player* plr = GetObjectInWorld(guid, (Player*)NULL); + if (!plr || !plr->IsInWorld()) + return NULL; + + return plr; +} + +Player* ObjectAccessor::FindPlayerByName(const char* name) +{ + Guard guard(*HashMapHolder::GetLock()); + HashMapHolder::MapType& m = HashMapHolder::GetContainer(); + for (HashMapHolder::MapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if (iter->second->IsInWorld() && strcmp(name, iter->second->GetName()) == 0) + return iter->second; + + return NULL; +} + +void ObjectAccessor::SaveAllPlayers() +{ + Guard guard(*HashMapHolder::GetLock()); + HashMapHolder::MapType& m = HashMapHolder::GetContainer(); + for (HashMapHolder::MapType::iterator itr = m.begin(); itr != m.end(); ++itr) + itr->second->SaveToDB(); +} + +Pet* ObjectAccessor::GetPet(uint64 guid) +{ + return GetObjectInWorld(guid, (Pet*)NULL); +} + +Corpse* ObjectAccessor::GetCorpseForPlayerGUID(uint64 guid) +{ + Guard guard(i_corpseGuard); + + Player2CorpsesMapType::iterator iter = i_player2corpse.find(guid); + if (iter == i_player2corpse.end()) + return NULL; + + assert(iter->second->GetType() != CORPSE_BONES); + + return iter->second; +} + +void ObjectAccessor::RemoveCorpse(Corpse* corpse) +{ + assert(corpse && corpse->GetType() != CORPSE_BONES); + + if (corpse->FindMap()) + corpse->FindMap()->Remove(corpse, false); + else + corpse->RemoveFromWorld(); + + // Critical section + { + Guard guard(i_corpseGuard); + + Player2CorpsesMapType::iterator iter = i_player2corpse.find(corpse->GetOwnerGUID()); + if (iter == i_player2corpse.end()) // TODO: Fix this + return; + + // build mapid*cellid -> guid_set map + CellPair cell_pair = Trinity::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY()); + uint32 cell_id = (cell_pair.y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + objmgr.DeleteCorpseCellData(corpse->GetMapId(), cell_id, corpse->GetOwnerGUID()); + + i_player2corpse.erase(iter); + } +} + +void ObjectAccessor::AddCorpse(Corpse* corpse) +{ + assert(corpse && corpse->GetType() != CORPSE_BONES); + + // Critical section + { + Guard guard(i_corpseGuard); + + assert(i_player2corpse.find(corpse->GetOwnerGUID()) == i_player2corpse.end()); + i_player2corpse[corpse->GetOwnerGUID()] = corpse; + + // build mapid*cellid -> guid_set map + CellPair cell_pair = Trinity::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY()); + uint32 cell_id = (cell_pair.y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + objmgr.AddCorpseCellData(corpse->GetMapId(), cell_id, corpse->GetOwnerGUID(), corpse->GetInstanceId()); + } +} + +void ObjectAccessor::AddCorpsesToGrid(GridPair const& gridpair, GridType& grid, Map* map) +{ + Guard guard(i_corpseGuard); + + for (Player2CorpsesMapType::iterator iter = i_player2corpse.begin(); iter != i_player2corpse.end(); ++iter) + { + if (iter->second->GetGrid() == gridpair) + { + // verify, if the corpse in our instance (add only corpses which are) + if (map->Instanceable()) + { + if (iter->second->GetInstanceId() == map->GetInstanceId()) + grid.AddWorldObject(iter->second); + } + else + grid.AddWorldObject(iter->second); + } + } +} + +Corpse* ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool /*insignia*/) +{ + Corpse* corpse = GetCorpseForPlayerGUID(player_guid); + if (!corpse) + { + //in fact this function is called from several places + //even when player doesn't have a corpse, not an error + // TODO: really, now... + //sLog.outError("Try remove corpse that not in map for GUID %ul", player_guid); + return NULL; + } + + DEBUG_LOG("Deleting Corpse and spawned bones."); + + //Map* map = corpse->FindMap(); + + // remove corpse from player_guid -> corpse map + RemoveCorpse(corpse); + + // done in removecorpse + // remove resurrectable corpse from grid object registry (loaded state checked into call) + // do not load the map if it's not loaded + //Map *map = MapManager::Instance().FindMap(corpse->GetMapId(), corpse->GetInstanceId()); + //if (map) + // map->Remove(corpse, false); + + // remove corpse from DB + corpse->DeleteFromDB(); + + // we don't want bones to save some cpu.. :) + delete corpse; + return NULL; + + /* + Corpse* bones = NULL; + // create the bones only if the map and the grid is loaded at the corpse's location + // ignore bones creating option in case insignia + if (map && (insignia || + (map->IsBattleGroundOrArena() ? sWorld.getConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld.getConfig(CONFIG_DEATH_BONES_WORLD))) && + !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) + { + // Create bones, don't change Corpse + bones = new Corpse; + bones->Create(corpse->GetGUIDLow(), map); + + for (int i = 3; i < CORPSE_END; ++i) // don't overwrite guid and object type + bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); + + bones->SetGrid(corpse->GetGrid()); + // bones->m_time = m_time; // don't overwrite time + // bones->m_inWorld = m_inWorld; // don't overwrite in-world state + // bones->m_type = m_type; // don't overwrite type + bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); + bones->SetPhaseMask(corpse->GetPhaseMask(), false); + + bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); + bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0); + + for (int i = 0; i < EQUIPMENT_SLOT_END; ++i) + { + if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) + bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); + } + + // add bones in grid store if grid loaded where corpse placed + map->Add(bones); + } + + // all references to the corpse should be removed at this point + delete corpse; + + return bones; + */ +} + +void ObjectAccessor::Update(uint32 /*diff*/) +{ + UpdateDataMapType update_players; + + // Critical section + { + Guard guard(i_updateGuard); + + while (!i_objects.empty()) + { + Object* obj = *i_objects.begin(); + assert(obj && obj->IsInWorld()); + i_objects.erase(i_objects.begin()); + obj->BuildUpdate(update_players); + } + } + + WorldPacket packet; // here we allocate a std::vector with a size of 0x10000 + for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) + { + iter->second.BuildPacket(&packet); + iter->first->GetSession()->SendPacket(&packet); + packet.clear(); // clean the string + } +} + +/// Define the static members of HashMapHolder + +template UNORDERED_MAP< uint64, T* > HashMapHolder::m_objectMap; +template ACE_Thread_Mutex HashMapHolder::i_lock; + +/// Global definitions for the hashmap storage + +template class HashMapHolder; +template class HashMapHolder; +template class HashMapHolder; +template class HashMapHolder; +template class HashMapHolder; +template class HashMapHolder; + +template Player* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/); +template Pet* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/); +template Creature* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/); +template Corpse* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/); +template GameObject* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/); +template DynamicObject* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, DynamicObject* /*fake*/); diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h new file mode 100644 index 00000000000..8e64eb48fa0 --- /dev/null +++ b/src/server/game/Globals/ObjectAccessor.h @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_OBJECTACCESSOR_H +#define TRINITY_OBJECTACCESSOR_H + +#include "Platform/Define.h" +#include "Policies/Singleton.h" +#include +#include "Utilities/UnorderedMap.h" +#include "Policies/ThreadingModel.h" + +#include "UpdateData.h" + +#include "GridDefines.h" +#include "Object.h" +#include "Player.h" + +#include + +class Creature; +class Corpse; +class Unit; +class GameObject; +class DynamicObject; +class WorldObject; +class Map; + +template +class HashMapHolder +{ + public: + + typedef UNORDERED_MAP MapType; + typedef ACE_Thread_Mutex LockType; + typedef Trinity::GeneralLock Guard; + + static void Insert(T* o) + { + Guard guard(i_lock); + m_objectMap[o->GetGUID()] = o; + } + + static void Remove(T* o) + { + Guard guard(i_lock); + m_objectMap.erase(o->GetGUID()); + } + + static T* Find(uint64 guid) + { + Guard guard(i_lock); + typename MapType::iterator itr = m_objectMap.find(guid); + return (itr != m_objectMap.end()) ? itr->second : NULL; + } + + static MapType& GetContainer() { return m_objectMap; } + + static LockType* GetLock() { return &i_lock; } + + private: + + //Non instanceable only static + HashMapHolder() {} + + static LockType i_lock; + static MapType m_objectMap; +}; + +class ObjectAccessor : public Trinity::Singleton > +{ + friend class Trinity::OperatorNew; + ObjectAccessor(); + ~ObjectAccessor(); + ObjectAccessor(const ObjectAccessor&); + ObjectAccessor& operator=(const ObjectAccessor&); + + public: + + typedef UNORDERED_MAP Player2CorpsesMapType; + typedef UNORDERED_MAP::value_type UpdateDataValueType; + + template static T* GetObjectInWorld(uint64 guid, T* /*fake*/) + { + return HashMapHolder::Find(guid); + } + + static Unit* GetObjectInWorld(uint64 guid, Unit* /*fake*/) + { + if (!guid) + return NULL; + + if (IS_PLAYER_GUID(guid)) + { + Unit* u = (Unit*)HashMapHolder::Find(guid); + if (!u || !u->IsInWorld()) + return NULL; + + return u; + } + + if (IS_PET_GUID(guid)) + return (Unit*)HashMapHolder::Find(guid); + + return (Unit*)HashMapHolder::Find(guid); + } + + static Unit* GetUnitInOrOutOfWorld(uint64 guid, Unit* /*fake*/) + { + if (!guid) + return NULL; + + if (IS_PLAYER_GUID(guid)) + { + Unit* u = (Unit*)HashMapHolder::Find(guid); + if (!u) + return NULL; + + return u; + } + + // Other object types than player are unloaded while out of world + return GetObjectInWorld(guid, (Unit*)NULL); + } + + template static T* GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, T* /*fake*/) + { + T* obj = HashMapHolder::Find(guid); + if (!obj || obj->GetMapId() != mapid) + return NULL; + + CellPair p = Trinity::ComputeCellPair(x, y); + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("ObjectAccessor::GetObjectInWorld: invalid coordinates supplied X:%f Y:%f grid cell [%u:%u]", x, y, p.x_coord, p.y_coord); + return NULL; + } + + CellPair q = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + if (q.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || q.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("ObjectAccessor::GetObjecInWorld: object (GUID: %u TypeId: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), q.x_coord, q.y_coord); + return NULL; + } + + int32 dx = int32(p.x_coord) - int32(q.x_coord); + int32 dy = int32(p.y_coord) - int32(q.y_coord); + + if (dx > -2 && dx < 2 && dy > -2 && dy < 2) + return obj; + else + return NULL; + } + + static WorldObject* GetWorldObject(WorldObject const&, uint64); + static Object* GetObjectByTypeMask(WorldObject const&, uint64, uint32 typemask); + static Creature* GetCreatureOrPetOrVehicle(WorldObject const&, uint64); + static Unit* GetUnit(WorldObject const&, uint64 guid) { return GetObjectInWorld(guid, (Unit*)NULL); } + static Unit* GetUnitInOrOutOfWorld(WorldObject const&, uint64 guid) { return GetUnitInOrOutOfWorld(guid, (Unit*)NULL); } + static Pet* GetPet(Unit const&, uint64 guid) { return GetPet(guid); } + static Player* GetPlayer(Unit const&, uint64 guid) { return FindPlayer(guid); } + static Corpse* GetCorpse(WorldObject const& u, uint64 guid); + static Pet* GetPet(uint64 guid); + static Player* FindPlayer(uint64); + + Player* FindPlayerByName(const char* name) ; + + // when using this, you must use the hashmapholder's lock + HashMapHolder::MapType& GetPlayers() + { + return HashMapHolder::GetContainer(); + } + + // when using this, you must use the hashmapholder's lock + HashMapHolder::MapType& GetCreatures() + { + return HashMapHolder::GetContainer(); + } + + // when using this, you must use the hashmapholder's lock + HashMapHolder::MapType& GetGameObjects() + { + return HashMapHolder::GetContainer(); + } + + template void AddObject(T* object) + { + HashMapHolder::Insert(object); + } + + template void RemoveObject(T* object) + { + HashMapHolder::Remove(object); + } + + void RemoveObject(Player* pl) + { + HashMapHolder::Remove(pl); + RemoveUpdateObject((Object*)pl); + } + + void SaveAllPlayers(); + + void AddUpdateObject(Object* obj) + { + Guard guard(i_updateGuard); + i_objects.insert(obj); + } + + void RemoveUpdateObject(Object* obj) + { + Guard guard(i_updateGuard); + i_objects.erase(obj); + } + + void Update(uint32 diff); + + Corpse* GetCorpseForPlayerGUID(uint64 guid); + void RemoveCorpse(Corpse* corpse); + void AddCorpse(Corpse* corpse); + void AddCorpsesToGrid(GridPair const& gridpair, GridType& grid, Map* map); + Corpse* ConvertCorpseForPlayer(uint64 player_guid, bool insignia = false); + + typedef ACE_Thread_Mutex LockType; + typedef Trinity::GeneralLock Guard; + + private: + + Player2CorpsesMapType i_player2corpse; + + static void _buildChangeObjectForPlayer(WorldObject*, UpdateDataMapType&); + static void _buildPacket(Player*, Object*, UpdateDataMapType&); + void _update(); + + std::set i_objects; + + LockType i_updateGuard; + LockType i_corpseGuard; +}; +#endif diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp new file mode 100644 index 00000000000..ce86c2a4e77 --- /dev/null +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -0,0 +1,8724 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Database/SQLStorage.h" +#include "Database/SQLStorageImpl.h" +#include "Policies/SingletonImp.h" + +#include "Log.h" +#include "MapManager.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "UpdateMask.h" +#include "World.h" +#include "Group.h" +#include "Guild.h" +#include "ArenaTeam.h" +#include "Transports.h" +#include "ProgressBar.h" +#include "Language.h" +#include "GameEventMgr.h" +#include "Spell.h" +#include "Chat.h" +#include "AccountMgr.h" +#include "InstanceSaveMgr.h" +#include "SpellAuras.h" +#include "Util.h" +#include "WaypointManager.h" +#include "GossipDef.h" +#include "Vehicle.h" +#include "AchievementMgr.h" + +INSTANTIATE_SINGLETON_1(ObjectMgr); + +ScriptMapMap sQuestEndScripts; +ScriptMapMap sQuestStartScripts; +ScriptMapMap sSpellScripts; +ScriptMapMap sGameObjectScripts; +ScriptMapMap sEventScripts; +ScriptMapMap sGossipScripts; +ScriptMapMap sWaypointScripts; + +bool normalizePlayerName(std::string& name) +{ + if (name.empty()) + return false; + + wchar_t wstr_buf[MAX_INTERNAL_PLAYER_NAME+1]; + size_t wstr_len = MAX_INTERNAL_PLAYER_NAME; + + if (!Utf8toWStr(name,&wstr_buf[0],wstr_len)) + return false; + + wstr_buf[0] = wcharToUpper(wstr_buf[0]); + for (size_t i = 1; i < wstr_len; ++i) + wstr_buf[i] = wcharToLower(wstr_buf[i]); + + if (!WStrToUtf8(wstr_buf,wstr_len,name)) + return false; + + return true; +} + +LanguageDesc lang_description[LANGUAGES_COUNT] = +{ + { LANG_ADDON, 0, 0 }, + { LANG_UNIVERSAL, 0, 0 }, + { LANG_ORCISH, 669, SKILL_LANG_ORCISH }, + { LANG_DARNASSIAN, 671, SKILL_LANG_DARNASSIAN }, + { LANG_TAURAHE, 670, SKILL_LANG_TAURAHE }, + { LANG_DWARVISH, 672, SKILL_LANG_DWARVEN }, + { LANG_COMMON, 668, SKILL_LANG_COMMON }, + { LANG_DEMONIC, 815, SKILL_LANG_DEMON_TONGUE }, + { LANG_TITAN, 816, SKILL_LANG_TITAN }, + { LANG_THALASSIAN, 813, SKILL_LANG_THALASSIAN }, + { LANG_DRACONIC, 814, SKILL_LANG_DRACONIC }, + { LANG_KALIMAG, 817, SKILL_LANG_OLD_TONGUE }, + { LANG_GNOMISH, 7340, SKILL_LANG_GNOMISH }, + { LANG_TROLL, 7341, SKILL_LANG_TROLL }, + { LANG_GUTTERSPEAK, 17737, SKILL_LANG_GUTTERSPEAK }, + { LANG_DRAENEI, 29932, SKILL_LANG_DRAENEI }, + { LANG_ZOMBIE, 0, 0 }, + { LANG_GNOMISH_BINARY, 0, 0 }, + { LANG_GOBLIN_BINARY, 0, 0 } +}; + +LanguageDesc const* GetLanguageDescByID(uint32 lang) +{ + for (uint8 i = 0; i < LANGUAGES_COUNT; ++i) + { + if (uint32(lang_description[i].lang_id) == lang) + return &lang_description[i]; + } + + return NULL; +} + +bool SpellClickInfo::IsFitToRequirements(Player const* player, Creature const * clickNpc) const +{ + if (questStart) + { + // not in expected required quest state + if (!player || ((!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart))) + return false; + } + + if (questEnd) + { + // not in expected forbidden quest state + if (!player || player->GetQuestRewardStatus(questEnd)) + return false; + } + + if (auraRequired) + if (!player->HasAura(auraRequired)) + return false; + + if (auraForbidden) + if (player->HasAura(auraForbidden)) + return false; + + Unit const * summoner = NULL; + // Check summoners for party + if (clickNpc->isSummon()) + summoner = clickNpc->ToTempSummon()->GetSummoner(); + if (!summoner) + summoner = clickNpc; + + switch (userType) + { + case SPELL_CLICK_USER_FRIEND: + if (!player->IsFriendlyTo(summoner)) + return false; + break; + case SPELL_CLICK_USER_RAID: + if (!player->IsInRaidWith(summoner)) + return false; + break; + case SPELL_CLICK_USER_PARTY: + if (!player->IsInPartyWith(summoner)) + return false; + break; + } + + return true; +} + +ObjectMgr::ObjectMgr() +{ + m_hiCharGuid = 1; + m_hiCreatureGuid = 1; + m_hiPetGuid = 1; + m_hiVehicleGuid = 1; + m_hiItemGuid = 1; + m_hiGoGuid = 1; + m_hiDoGuid = 1; + m_hiCorpseGuid = 1; + m_hiPetNumber = 1; + m_hiGroupGuid = 1; + m_ItemTextId = 1; + m_mailid = 1; + m_equipmentSetGuid = 1; + m_guildId = 1; + m_arenaTeamId = 1; + m_auctionid = 1; +} + +ObjectMgr::~ObjectMgr() +{ + for (QuestMap::iterator i = mQuestTemplates.begin(); i != mQuestTemplates.end(); ++i) + delete i->second; + + for (PetLevelInfoMap::iterator i = petInfo.begin(); i != petInfo.end(); ++i) + delete[] i->second; + + // free only if loaded + for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + delete[] playerClassInfo[class_].levelInfo; + + for (int race = 0; race < MAX_RACES; ++race) + for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + delete[] playerInfo[race][class_].levelInfo; + + // free group and guild objects + for (GroupSet::iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr) + delete (*itr); + + for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr) + delete itr->second; + + for (ArenaTeamMap::iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) + delete itr->second; + + for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) + itr->second.Clear(); + + for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr) + itr->second.Clear(); +} + +Group * ObjectMgr::GetGroupByGUID(const uint64 &guid) const +{ + for (GroupSet::const_iterator itr = mGroupSet.begin(); itr != mGroupSet.end(); ++itr) + if ((*itr)->GetGUID() == guid) + return *itr; + + return NULL; +} + +Guild * ObjectMgr::GetGuildById(uint32 GuildId) const +{ + GuildMap::const_iterator itr = mGuildMap.find(GuildId); + if (itr != mGuildMap.end()) + return itr->second; + + return NULL; +} + +Guild * ObjectMgr::GetGuildByName(const std::string& guildname) const +{ + std::string search = guildname; + std::transform(search.begin(), search.end(), search.begin(), ::toupper); + for (GuildMap::const_iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr) + { + std::string gname = itr->second->GetName(); + std::transform(gname.begin(), gname.end(), gname.begin(), ::toupper); + if (search == gname) + return itr->second; + } + return NULL; +} + +std::string ObjectMgr::GetGuildNameById(uint32 GuildId) const +{ + GuildMap::const_iterator itr = mGuildMap.find(GuildId); + if (itr != mGuildMap.end()) + return itr->second->GetName(); + + return ""; +} + +Guild* ObjectMgr::GetGuildByLeader(const uint64 &guid) const +{ + for (GuildMap::const_iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr) + if (itr->second->GetLeader() == guid) + return itr->second; + + return NULL; +} + +void ObjectMgr::AddGuild(Guild* guild) +{ + mGuildMap[guild->GetId()] = guild; +} + +void ObjectMgr::RemoveGuild(uint32 Id) +{ + mGuildMap.erase(Id); +} + +ArenaTeam* ObjectMgr::GetArenaTeamById(uint32 arenateamid) const +{ + ArenaTeamMap::const_iterator itr = mArenaTeamMap.find(arenateamid); + if (itr != mArenaTeamMap.end()) + return itr->second; + + return NULL; +} + +ArenaTeam* ObjectMgr::GetArenaTeamByName(const std::string& arenateamname) const +{ + std::string search = arenateamname; + std::transform(search.begin(), search.end(), search.begin(), ::toupper); + for (ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) + { + std::string teamname = itr->second->GetName(); + std::transform(teamname.begin(), teamname.end(), teamname.begin(), ::toupper); + if (search == teamname) + return itr->second; + } + return NULL; +} + +ArenaTeam* ObjectMgr::GetArenaTeamByCaptain(uint64 const& guid) const +{ + for (ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) + if (itr->second->GetCaptain() == guid) + return itr->second; + + return NULL; +} + +void ObjectMgr::AddArenaTeam(ArenaTeam* arenaTeam) +{ + mArenaTeamMap[arenaTeam->GetId()] = arenaTeam; +} + +void ObjectMgr::RemoveArenaTeam(uint32 Id) +{ + mArenaTeamMap.erase(Id); +} + +CreatureInfo const* ObjectMgr::GetCreatureTemplate(uint32 id) +{ + return sCreatureStorage.LookupEntry(id); +} + +void ObjectMgr::LoadCreatureLocales() +{ + mCreatureLocaleMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,name_loc1,subname_loc1,name_loc2,subname_loc2,name_loc3,subname_loc3,name_loc4,subname_loc4,name_loc5,subname_loc5,name_loc6,subname_loc6,name_loc7,subname_loc7,name_loc8,subname_loc8 FROM locales_creature"); + + if (!result) + return; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + CreatureLocale& data = mCreatureLocaleMap[entry]; + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+2*(i-1)].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Name.size() <= idx) + data.Name.resize(idx+1); + + data.Name[idx] = str; + } + } + str = fields[1+2*(i-1)+1].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.SubName.size() <= idx) + data.SubName.resize(idx+1); + + data.SubName[idx] = str; + } + } + } + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu creature locale strings", (unsigned long)mCreatureLocaleMap.size()); +} + +void ObjectMgr::LoadGossipMenuItemsLocales() +{ + mGossipMenuItemsLocaleMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT menu_id,id," + "option_text_loc1,box_text_loc1,option_text_loc2,box_text_loc2," + "option_text_loc3,box_text_loc3,option_text_loc4,box_text_loc4," + "option_text_loc5,box_text_loc5,option_text_loc6,box_text_loc6," + "option_text_loc7,box_text_loc7,option_text_loc8,box_text_loc8 " + "FROM locales_gossip_menu_option"); + + if (!result) + return; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint16 menuId = fields[0].GetUInt16(); + uint16 id = fields[1].GetUInt16(); + + GossipMenuItemsLocale& data = mGossipMenuItemsLocaleMap[MAKE_PAIR32(menuId,id)]; + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[2+2*(i-1)].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.OptionText.size() <= idx) + data.OptionText.resize(idx+1); + + data.OptionText[idx] = str; + } + } + str = fields[2+2*(i-1)+1].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.BoxText.size() <= idx) + data.BoxText.resize(idx+1); + + data.BoxText[idx] = str; + } + } + } + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu gossip_menu_option locale strings", (unsigned long)mGossipMenuItemsLocaleMap.size()); +} + +void ObjectMgr::LoadPointOfInterestLocales() +{ + mPointOfInterestLocaleMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,icon_name_loc1,icon_name_loc2,icon_name_loc3,icon_name_loc4,icon_name_loc5,icon_name_loc6,icon_name_loc7,icon_name_loc8 FROM locales_points_of_interest"); + + if (!result) + return; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + PointOfInterestLocale& data = mPointOfInterestLocaleMap[entry]; + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[i].GetCppString(); + if (str.empty()) + continue; + + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.IconName.size() <= idx) + data.IconName.resize(idx+1); + + data.IconName[idx] = str; + } + } + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu points_of_interest locale strings", (unsigned long)mPointOfInterestLocaleMap.size()); +} + +struct SQLCreatureLoader : public SQLStorageLoaderBase +{ + template + void convert_from_str(uint32 /*field_pos*/, char *src, D &dst) + { + dst = D(objmgr.GetScriptId(src)); + } +}; + +void ObjectMgr::LoadCreatureTemplates() +{ + SQLCreatureLoader loader; + loader.Load(sCreatureStorage); + + sLog.outString(">> Loaded %u creature definitions", sCreatureStorage.RecordCount); + sLog.outString(); + + // check data correctness + for (uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i) + { + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i); + CheckCreatureTemplate(cInfo); + } +} + +void ObjectMgr::CheckCreatureTemplate(CreatureInfo const* cInfo) +{ + if (!cInfo) + return; + + bool ok = true; // bool to allow continue outside this loop + for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) + { + if (!cInfo->DifficultyEntry[diff]) + continue; + ok = false; // will be set to true at the end of this loop again + + CreatureInfo const* difficultyInfo = GetCreatureTemplate(cInfo->DifficultyEntry[diff]); + if (!difficultyInfo) + { + sLog.outErrorDb("Creature (Entry: %u) have `difficulty_entry_%u`=%u but creature entry %u not exist.", + cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff]); + continue; + } + + if (difficultyEntries[diff].find(cInfo->Entry) != difficultyEntries[diff].end()) + { + sLog.outErrorDb("Creature (Entry: %u) listed as difficulty %u but have value in `difficulty_entry_1`.", cInfo->Entry, diff + 1); + continue; + } + + bool ok2 = true; + for (uint32 diff2 = 0; diff2 < MAX_DIFFICULTY - 1 && ok2; ++diff2) + { + ok2 = false; + if (difficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != difficultyEntries[diff2].end()) + { + sLog.outErrorDb("Creature (Entry: %u) already listed as difficulty %u for another entry.", cInfo->DifficultyEntry[diff], diff2 + 1); + continue; + } + + if (hasDifficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != hasDifficultyEntries[diff2].end()) + { + sLog.outErrorDb("Creature (Entry: %u) have `difficulty_entry_%u`=%u but creature entry %u have difficulty %u entry also.", + cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff], diff2 + 1); + continue; + } + ok2 = true; + } + if (!ok2) + continue; + + if (cInfo->unit_class != difficultyInfo->unit_class) + { + sLog.outErrorDb("Creature (Entry: %u, class %u) has different `unit_class` in difficulty %u mode (Entry: %u, class %u).", + cInfo->Entry, cInfo->unit_class, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->unit_class); + continue; + } + + if (cInfo->npcflag != difficultyInfo->npcflag) + { + sLog.outErrorDb("Creature (Entry: %u) has different `npcflag` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); + continue; + } + + if (cInfo->trainer_class != difficultyInfo->trainer_class) + { + sLog.outErrorDb("Creature (Entry: %u) has different `trainer_class` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); + continue; + } + + if (cInfo->trainer_race != difficultyInfo->trainer_race) + { + sLog.outErrorDb("Creature (Entry: %u) has different `trainer_race` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); + continue; + } + + if (cInfo->trainer_type != difficultyInfo->trainer_type) + { + sLog.outErrorDb("Creature (Entry: %u) has different `trainer_type` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); + continue; + } + + if (cInfo->trainer_spell != difficultyInfo->trainer_spell) + { + sLog.outErrorDb("Creature (Entry: %u) has different `trainer_spell` in difficulty %u mode (Entry: %u).", cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]); + continue; + } + + if (difficultyInfo->AIName && *difficultyInfo->AIName) + { + sLog.outErrorDb("Difficulty %u mode creature (Entry: %u) has `AIName`, but in any case will used difficulty 0 mode creature (Entry: %u) AIName.", + diff, cInfo->DifficultyEntry[diff], cInfo->Entry); + continue; + } + + if (difficultyInfo->ScriptID) + { + sLog.outErrorDb("Difficulty %u mode creature (Entry: %u) has `ScriptName`, but in any case will used difficulty 0 mode creature (Entry: %u) ScriptName.", + diff, cInfo->DifficultyEntry[diff], cInfo->Entry); + continue; + } + + hasDifficultyEntries[diff].insert(cInfo->Entry); + difficultyEntries[diff].insert(cInfo->DifficultyEntry[diff]); + ok = true; + } + + FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_A); + if (!factionTemplate) + sLog.outErrorDb("Creature (Entry: %u) has non-existing faction_A template (%u)", cInfo->Entry, cInfo->faction_A); + + factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_H); + if (!factionTemplate) + sLog.outErrorDb("Creature (Entry: %u) has non-existing faction_H template (%u)", cInfo->Entry, cInfo->faction_H); + + // used later for scale + CreatureDisplayInfoEntry const* displayScaleEntry = NULL; + + if (cInfo->Modelid1) + { + CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid1); + if (!displayEntry) + { + sLog.outErrorDb("Creature (Entry: %u) has non-existing Modelid1 id (%u), can crash client", cInfo->Entry, cInfo->Modelid1); + const_cast(cInfo)->Modelid1 = 0; + } + else if (!displayScaleEntry) + displayScaleEntry = displayEntry; + + CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->Modelid1); + if (!minfo) + sLog.outErrorDb("Creature (Entry: %u) not has model data for Modelid1 (%u)", cInfo->Entry, cInfo->Modelid1); + } + + if (cInfo->Modelid2) + { + CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid2); + if (!displayEntry) + { + sLog.outErrorDb("Creature (Entry: %u) has non-existing Modelid2 id (%u), can crash client", cInfo->Entry, cInfo->Modelid2); + const_cast(cInfo)->Modelid2 = 0; + } + else if (!displayScaleEntry) + displayScaleEntry = displayEntry; + + CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->Modelid2); + if (!minfo) + sLog.outErrorDb("Creature (Entry: %u) not has model data for Modelid2 (%u)", cInfo->Entry, cInfo->Modelid2); + } + + if (cInfo->Modelid3) + { + CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid3); + if (!displayEntry) + { + sLog.outErrorDb("Creature (Entry: %u) has non-existing Modelid3 id (%u), can crash client", cInfo->Entry, cInfo->Modelid3); + const_cast(cInfo)->Modelid3 = 0; + } + else if (!displayScaleEntry) + displayScaleEntry = displayEntry; + + CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->Modelid3); + if (!minfo) + sLog.outErrorDb("Creature (Entry: %u) not has model data for Modelid3 (%u)", cInfo->Entry, cInfo->Modelid3); + } + + if (cInfo->Modelid4) + { + CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid4); + if (!displayEntry) + { + sLog.outErrorDb("Creature (Entry: %u) has non-existing Modelid4 id (%u), can crash client", cInfo->Entry, cInfo->Modelid4); + const_cast(cInfo)->Modelid4 = 0; + } + else if (!displayScaleEntry) + displayScaleEntry = displayEntry; + + CreatureModelInfo const* minfo = sCreatureModelStorage.LookupEntry(cInfo->Modelid4); + if (!minfo) + sLog.outErrorDb("Creature (Entry: %u) not has model data for Modelid4 (%u)", cInfo->Entry, cInfo->Modelid4); + } + + if (!displayScaleEntry) + sLog.outErrorDb("Creature (Entry: %u) not has any existed display id in Modelid1/Modelid2/Modelid3/Modelid4", cInfo->Entry); + + for (int k = 0; k < MAX_KILL_CREDIT; ++k) + { + if (cInfo->KillCredit[k]) + { + if (!GetCreatureTemplate(cInfo->KillCredit[k])) + { + sLog.outErrorDb("Creature (Entry: %u) has not existed creature entry in `KillCredit%d` (%u)",cInfo->Entry,k+1,cInfo->KillCredit[k]); + const_cast(cInfo)->KillCredit[k] = 0; + } + } + } + + if (!cInfo->unit_class || ((1 << (cInfo->unit_class-1)) & CLASSMASK_ALL_CREATURES) == 0) + { + sLog.outErrorDb("Creature (Entry: %u) has invalid unit_class(%u) for creature_template. Set to 1 (UNIT_CLASS_WARRIOR).", cInfo->Entry, cInfo->unit_class); + const_cast(cInfo)->unit_class = UNIT_CLASS_WARRIOR; + } + + if (cInfo->dmgschool >= MAX_SPELL_SCHOOL) + { + sLog.outErrorDb("Creature (Entry: %u) has invalid spell school value (%u) in `dmgschool`",cInfo->Entry,cInfo->dmgschool); + const_cast(cInfo)->dmgschool = SPELL_SCHOOL_NORMAL; + } + + if (cInfo->baseattacktime == 0) + const_cast(cInfo)->baseattacktime = BASE_ATTACK_TIME; + + if (cInfo->rangeattacktime == 0) + const_cast(cInfo)->rangeattacktime = BASE_ATTACK_TIME; + + if (cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK) + { + sLog.outErrorDb("Creature (Entry: %u) has dynamic flag UNIT_NPC_FLAG_SPELLCLICK (%u) set, it expect to be set by code base at `npc_spellclick_spells` content.",cInfo->Entry,UNIT_NPC_FLAG_SPELLCLICK); + const_cast(cInfo)->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK; + } + + if ((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE) + sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type); + + if (cInfo->type && !sCreatureTypeStore.LookupEntry(cInfo->type)) + { + sLog.outErrorDb("Creature (Entry: %u) has invalid creature type (%u) in `type`",cInfo->Entry,cInfo->type); + const_cast(cInfo)->type = CREATURE_TYPE_HUMANOID; + } + + // must exist or used hidden but used in data horse case + if (cInfo->family && !sCreatureFamilyStore.LookupEntry(cInfo->family) && cInfo->family != CREATURE_FAMILY_HORSE_CUSTOM) + { + sLog.outErrorDb("Creature (Entry: %u) has invalid creature family (%u) in `family`",cInfo->Entry,cInfo->family); + const_cast(cInfo)->family = 0; + } + + if (cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE) + { + sLog.outErrorDb("Creature (Entry: %u) has wrong value (%u) in `InhabitType`, creature will not correctly walk/swim/fly",cInfo->Entry,cInfo->InhabitType); + const_cast(cInfo)->InhabitType = INHABIT_ANYWHERE; + } + + if (cInfo->VehicleId) + { + VehicleEntry const* vehId = sVehicleStore.LookupEntry(cInfo->VehicleId); + if (!vehId) + sLog.outErrorDb("Creature (Entry: %u) has a non-existing VehicleId (%u). This *WILL* cause the client to freeze!", cInfo->Entry, cInfo->VehicleId); + } + + if (cInfo->PetSpellDataId) + { + CreatureSpellDataEntry const* spellDataId = sCreatureSpellDataStore.LookupEntry(cInfo->PetSpellDataId); + if (!spellDataId) + sLog.outErrorDb("Creature (Entry: %u) has non-existing PetSpellDataId (%u)", cInfo->Entry, cInfo->PetSpellDataId); + } + + for (uint8 j = 0; j < CREATURE_MAX_SPELLS; ++j) + { + if (cInfo->spells[j] && !sSpellStore.LookupEntry(cInfo->spells[j])) + { + sLog.outErrorDb("Creature (Entry: %u) has non-existing Spell%d (%u), set to 0", cInfo->Entry, j+1,cInfo->spells[j]); + const_cast(cInfo)->spells[j] = 0; + } + } + + if (cInfo->MovementType >= MAX_DB_MOTION_TYPE) + { + sLog.outErrorDb("Creature (Entry: %u) has wrong movement generator type (%u), ignore and set to IDLE.",cInfo->Entry,cInfo->MovementType); + const_cast(cInfo)->MovementType = IDLE_MOTION_TYPE; + } + + if (cInfo->equipmentId > 0) // 0 no equipment + { + if (!GetEquipmentInfo(cInfo->equipmentId)) + { + sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", cInfo->Entry, cInfo->equipmentId); + const_cast(cInfo)->equipmentId = 0; + } + } + + /// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc + if (cInfo->scale <= 0.0f) + { + if (displayScaleEntry) + const_cast(cInfo)->scale = displayScaleEntry->scale; + else + const_cast(cInfo)->scale = 1.0f; + } + + if (cInfo->expansion > (MAX_CREATURE_BASE_HP - 1)) + { + sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with expansion %u ignore and set to NULL.", cInfo->expansion); + const_cast(cInfo)->expansion = 0; + } + + const_cast(cInfo)->dmg_multiplier *= Creature::_GetDamageMod(cInfo->rank); +} + +void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr) +{ + // Now add the auras, format "spellid effectindex spellid effectindex..." + char *p,*s; + std::map val; + s=p=(char*)reinterpret_cast(addon->auras); + if (p) + { + uint32 currSpellId = 0; + bool spell = true; + while (p[0] != 0) + { + ++p; + if (p[0] == ' ' || p[0] == 0) + { + if (spell) + currSpellId = atoi(s); + else + { + uint8 eff = atoi(s); + if (eff >=3) + { + sLog.outErrorDb("Creature (%s: %u) has wrong `auras` data in `%s`(too high aura effect: %d for spell: %d)",guidEntryStr,addon->guidOrEntry,table,eff,currSpellId); + } + val[currSpellId] |= 1<(addon->auras); + + // wrong list + if (!spell) + { + addon->auras = NULL; + sLog.outErrorDb("Creature (%s: %u) has wrong `auras` data in `%s`.",guidEntryStr,addon->guidOrEntry,table); + return; + } + } + + // empty list + if (val.empty()) + { + addon->auras = NULL; + return; + } + + // replace by new structures array + const_cast(addon->auras) = new CreatureDataAddonAura[val.size()+1]; + + uint32 i=0; + for (std::map::iterator itr = val.begin(); itr != val.end();++itr) + { + CreatureDataAddonAura& cAura = const_cast(addon->auras[i]); + cAura.spell_id = itr->first; + cAura.effectMask = itr->second; + if (cAura.effectMask > 7 || !cAura.effectMask) + { + sLog.outErrorDb("Creature (%s: %u) has wrong effect for spell %u in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.spell_id,table); + continue; + } + SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(cAura.spell_id); + if (!AdditionalSpellInfo) + { + sLog.outErrorDb("Creature (%s: %u) has wrong spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.spell_id,table); + continue; + } + for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) + { + if ((1<Effect[eff] || !AdditionalSpellInfo->EffectApplyAuraName[eff]) + { + sLog.outErrorDb("Creature (%s: %u) has not aura effect %u of spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,eff,cAura.spell_id,table); + continue; + } + else if (AdditionalSpellInfo->Effect[eff] == SPELL_EFFECT_PERSISTENT_AREA_AURA) + { + sLog.outErrorDb("Creature (%s: %u) has persistent area aura effect %u of spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,eff,cAura.spell_id,table); + continue; + } + } + } + + ++i; + } + + // fill terminator element (after last added) + CreatureDataAddonAura& endAura = const_cast(addon->auras[i]); + endAura.spell_id = 0; + endAura.effectMask = 0; +} + +void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment) +{ + creatureaddons.Load(); + + sLog.outString(">> Loaded %u %s", creatureaddons.RecordCount, comment); + sLog.outString(); + + // check data correctness and convert 'auras' + for (uint32 i = 1; i < creatureaddons.MaxEntry; ++i) + { + CreatureDataAddon const* addon = creatureaddons.LookupEntry(i); + if (!addon) + continue; + + if (addon->mount) + { + if (!sCreatureDisplayInfoStore.LookupEntry(addon->mount)) + { + sLog.outErrorDb("Creature (%s %u) have invalid displayInfoId for mount (%u) defined in `%s`.", entryName, addon->guidOrEntry, addon->mount, creatureaddons.GetTableName()); + const_cast(addon)->mount = 0; + } + } + + if (!sEmotesStore.LookupEntry(addon->emote)) + sLog.outErrorDb("Creature (%s %u) have invalid emote (%u) defined in `%s`.", entryName, addon->guidOrEntry, addon->emote, creatureaddons.GetTableName()); + + /*if (addon->move_flags & (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4)) + { + sLog.outErrorDb("Creature (%s %u) movement flags mask defined in `%s` include forbidden flags (" I32FMT ") that can crash client, cleanup at load.", entryName, addon->guidOrEntry, creatureaddons.GetTableName(), (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4)); + const_cast(addon)->move_flags &= ~(MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4); + }*/ + + ConvertCreatureAddonAuras(const_cast(addon), creatureaddons.GetTableName(), entryName); + } +} + +void ObjectMgr::LoadCreatureAddons() +{ + LoadCreatureAddons(sCreatureInfoAddonStorage,"Entry","creature template addons"); + + // check entry ids + for (uint32 i = 1; i < sCreatureInfoAddonStorage.MaxEntry; ++i) + if (CreatureDataAddon const* addon = sCreatureInfoAddonStorage.LookupEntry(i)) + if (!sCreatureStorage.LookupEntry(addon->guidOrEntry)) + sLog.outErrorDb("Creature (Entry: %u) does not exist but has a record in `%s`",addon->guidOrEntry, sCreatureInfoAddonStorage.GetTableName()); + + sLog.outString("Loading Creature Addon Data..."); + LoadCreatureAddons(sCreatureDataAddonStorage,"GUID","creature addons"); + + // check entry ids + for (uint32 i = 1; i < sCreatureDataAddonStorage.MaxEntry; ++i) + if (CreatureDataAddon const* addon = sCreatureDataAddonStorage.LookupEntry(i)) + if (mCreatureDataMap.find(addon->guidOrEntry) == mCreatureDataMap.end()) + sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`",addon->guidOrEntry); +} + +EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry) +{ + return sEquipmentStorage.LookupEntry(entry); +} + +void ObjectMgr::LoadEquipmentTemplates() +{ + sEquipmentStorage.Load(); + + for (uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i) + { + EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry(i); + + if (!eqInfo) + continue; + + for (uint8 j=0; j<3; j++) + { + if (!eqInfo->equipentry[j]) + continue; + + ItemEntry const *dbcitem = sItemStore.LookupEntry(eqInfo->equipentry[j]); + + if (!dbcitem) + { + sLog.outErrorDb("Unknown item (entry=%u) in creature_equip_template.equipentry%u for entry = %u, forced to 0.", eqInfo->equipentry[j], j+1, i); + const_cast(eqInfo)->equipentry[j] = 0; + continue; + } + + if (dbcitem->InventoryType != INVTYPE_WEAPON && + dbcitem->InventoryType != INVTYPE_SHIELD && + dbcitem->InventoryType != INVTYPE_RANGED && + dbcitem->InventoryType != INVTYPE_2HWEAPON && + dbcitem->InventoryType != INVTYPE_WEAPONMAINHAND && + dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND && + dbcitem->InventoryType != INVTYPE_HOLDABLE && + dbcitem->InventoryType != INVTYPE_THROWN && + dbcitem->InventoryType != INVTYPE_RANGEDRIGHT) + { + sLog.outErrorDb("Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0.", eqInfo->equipentry[j], j+1, i); + const_cast(eqInfo)->equipentry[j] = 0; + } + } + } + sLog.outString(">> Loaded %u equipment template", sEquipmentStorage.RecordCount); + sLog.outString(); +} + +CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelid) +{ + return sCreatureModelStorage.LookupEntry(modelid); +} + +uint32 ObjectMgr::ChooseDisplayId(uint32 /*team*/, const CreatureInfo *cinfo, const CreatureData *data /*= NULL*/) +{ + // Load creature model (display id) + uint32 display_id = 0; + + if (!data || data->displayid == 0) + { + display_id = cinfo->GetRandomValidModelId(); + } + else + return data->displayid; + + /*if (!team) + { + switch(cinfo->Entry) + { + case 28511: // Eye of Acherus + case 33114: // Flame Leviathan Seat (model 24914 chair) + case 33167: // Salvaged Demolisher Mechanic Seat + case 33189: // Liquid Pryite + return cinfo->Modelid1; + case 33218: // Pyrite Safety Container + return cinfo->Modelid2; + case 33143: // Overload Control Device + return cinfo->Modelid3; + default: + return cinfo->GetRandomValidModelId(); + } + }*/ + + return display_id; +} + +CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32 display_id) +{ + CreatureModelInfo const *minfo = GetCreatureModelInfo(display_id); + if (!minfo) + return NULL; + + // If a model for another gender exists, 50% chance to use it + if (minfo->modelid_other_gender != 0 && urand(0,1) == 0) + { + CreatureModelInfo const *minfo_tmp = GetCreatureModelInfo(minfo->modelid_other_gender); + if (!minfo_tmp) + { + sLog.outErrorDb("Model (Entry: %u) has modelid_other_gender %u not found in table `creature_model_info`. ", minfo->modelid, minfo->modelid_other_gender); + return minfo; // not fatal, just use the previous one + } + else + return minfo_tmp; + } + else + return minfo; +} + +void ObjectMgr::LoadCreatureModelInfo() +{ + sCreatureModelStorage.Load(); + + // post processing + for (uint32 i = 1; i < sCreatureModelStorage.MaxEntry; ++i) + { + CreatureModelInfo const *minfo = sCreatureModelStorage.LookupEntry(i); + if (!minfo) + continue; + + if (!sCreatureDisplayInfoStore.LookupEntry(minfo->modelid)) + sLog.outErrorDb("Table `creature_model_info` has model for not existed display id (%u).", minfo->modelid); + + if (minfo->gender > GENDER_NONE) + { + sLog.outErrorDb("Table `creature_model_info` has wrong gender (%u) for display id (%u).", uint32(minfo->gender), minfo->modelid); + const_cast(minfo)->gender = GENDER_MALE; + } + + if (minfo->modelid_other_gender && !sCreatureDisplayInfoStore.LookupEntry(minfo->modelid_other_gender)) + { + sLog.outErrorDb("Table `creature_model_info` has not existed alt.gender model (%u) for existed display id (%u).", minfo->modelid_other_gender, minfo->modelid); + const_cast(minfo)->modelid_other_gender = 0; + } + } + + sLog.outString(">> Loaded %u creature model based info", sCreatureModelStorage.RecordCount); + sLog.outString(); + + // check if combat_reach is valid + for (uint32 i = 1; i < sCreatureModelStorage.MaxEntry; ++i) + { + CreatureModelInfo const* mInfo = sCreatureModelStorage.LookupEntry(i); + if (!mInfo) + continue; + + if (mInfo->combat_reach < 0.1f) + { + //sLog.outErrorDb("Creature model (Entry: %u) has invalid combat reach (%f), setting it to 0.5", mInfo->modelid, mInfo->combat_reach); + const_cast(mInfo)->combat_reach = DEFAULT_COMBAT_REACH; + } + } +} + +bool ObjectMgr::CheckCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) const +{ + const CreatureData* const slave = GetCreatureData(guid); + const CreatureData* const master = GetCreatureData(linkedGuid); + + if (!slave || !master) // they must have a corresponding entry in db + { + sLog.outError("LinkedRespawn: Creature '%u' linking to '%u' which doesn't exist",guid,linkedGuid); + return false; + } + + const MapEntry* const map = sMapStore.LookupEntry(master->mapid); + + if (master->mapid != slave->mapid // link only to same map + && (!map || map->Instanceable())) // or to unistanced world + { + sLog.outError("LinkedRespawn: Creature '%u' linking to '%u' on an unpermitted map",guid,linkedGuid); + return false; + } + + if (!(master->spawnMask & slave->spawnMask) // they must have a possibility to meet (normal/heroic difficulty) + && (!map || map->Instanceable())) + { + sLog.outError("LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask",guid,linkedGuid); + return false; + } + + return true; +} + +void ObjectMgr::LoadCreatureLinkedRespawn() +{ + mCreatureLinkedRespawnMap.clear(); + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT guid, linkedGuid FROM creature_linked_respawn ORDER BY guid ASC"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outErrorDb(">> Loaded 0 linked respawns. DB table `creature_linked_respawn` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 guid = fields[0].GetUInt32(); + uint32 linkedGuid = fields[1].GetUInt32(); + + if (CheckCreatureLinkedRespawn(guid,linkedGuid)) + mCreatureLinkedRespawnMap[guid] = linkedGuid; + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u linked respawns", mCreatureLinkedRespawnMap.size()); +} + +bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) +{ + if (!guid) + return false; + + if (!linkedGuid) // we're removing the linking + { + mCreatureLinkedRespawnMap.erase(guid); + WorldDatabase.DirectPExecute("DELETE FROM creature_linked_respawn WHERE guid = '%u'",guid); + return true; + } + + if (CheckCreatureLinkedRespawn(guid,linkedGuid)) // we add/change linking + { + mCreatureLinkedRespawnMap[guid] = linkedGuid; + WorldDatabase.DirectPExecute("REPLACE INTO creature_linked_respawn (guid,linkedGuid) VALUES ('%u','%u')",guid,linkedGuid); + return true; + } + return false; +} + +void ObjectMgr::LoadCreatures() +{ + uint32 count = 0; + // 0 1 2 3 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid," + // 4 5 6 7 8 9 10 11 + "equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint," + // 12 13 14 15 16 17 18 19 + "curhealth, curmana, DeathState, MovementType, spawnMask, phaseMask, event, pool_entry " + "FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid " + "LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 creature. DB table `creature` is empty."); + return; + } + + // build single time for check creature data + std::set difficultyCreatures[MAX_DIFFICULTY - 1]; + for (uint32 i = 0; i < sCreatureStorage.MaxEntry; ++i) + if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i)) + for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1; ++diff) + if (cInfo->DifficultyEntry[diff]) + difficultyCreatures[diff].insert(cInfo->DifficultyEntry[diff]); + + // build single time for check spawnmask + std::map spawnMasks; + for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) + if (sMapStore.LookupEntry(i)) + for (int k = 0; k < MAX_DIFFICULTY; ++k) + if (GetMapDifficultyData(i,Difficulty(k))) + spawnMasks[i] |= (1 << k); + + //TODO: remove this + //gameeventmgr.mGameEventCreatureGuids.resize(52*2-1); + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 guid = fields[ 0].GetUInt32(); + uint32 entry = fields[ 1].GetUInt32(); + + CreatureInfo const* cInfo = GetCreatureTemplate(entry); + if (!cInfo) + { + sLog.outErrorDb("Table `creature` has creature (GUID: %u) with non existing creature entry %u, skipped.", guid, entry); + continue; + } + + CreatureData& data = mCreatureDataMap[guid]; + + data.id = entry; + data.mapid = fields[ 2].GetUInt32(); + data.displayid = fields[ 3].GetUInt32(); + data.equipmentId = fields[ 4].GetUInt32(); + data.posX = fields[ 5].GetFloat(); + data.posY = fields[ 6].GetFloat(); + data.posZ = fields[ 7].GetFloat(); + data.orientation = fields[ 8].GetFloat(); + data.spawntimesecs = fields[ 9].GetUInt32(); + data.spawndist = fields[10].GetFloat(); + data.currentwaypoint= fields[11].GetUInt32(); + data.curhealth = fields[12].GetUInt32(); + data.curmana = fields[13].GetUInt32(); + data.is_dead = fields[14].GetBool(); + data.movementType = fields[15].GetUInt8(); + data.spawnMask = fields[16].GetUInt8(); + data.phaseMask = fields[17].GetUInt16(); + int16 gameEvent = fields[18].GetInt16(); + int16 PoolId = fields[19].GetInt16(); + + MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); + if (!mapEntry) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u) that spawned at not existed map (Id: %u), skipped.",guid, data.mapid); + continue; + } + + if (data.spawnMask & ~spawnMasks[data.mapid]) + sLog.outErrorDb("Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).",guid, data.spawnMask, data.mapid); + + bool ok = true; + for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) + { + if (difficultyCreatures[diff].find(data.id) != difficultyCreatures[diff].end()) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as difficulty %u template (entry: %u) in `creature_template`, skipped.", + guid, diff + 1, data.id); + ok = false; + } + } + if (!ok) + continue; + + // I do not know why but in db most display id are not zero + /*if (data.displayid == 11686 || data.displayid == 24719) + { + (const_cast(cInfo))->flags_extra |= CREATURE_FLAG_EXTRA_TRIGGER; + } + else if (data.displayid == cInfo->DisplayID_A || data.displayid == cInfo->DisplayID_A2 + || data.displayid == cInfo->DisplayID_H || data.displayid == cInfo->DisplayID_H2) + data.displayid = 0; + */ + + if (data.equipmentId > 0) // -1 no equipment, 0 use default + { + if (!GetEquipmentInfo(data.equipmentId)) + { + sLog.outErrorDb("Table `creature` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", data.id, data.equipmentId); + data.equipmentId = -1; + } + } + + if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) + { + if (!mapEntry || !mapEntry->IsDungeon()) + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance.",guid,data.id); + } + + if (data.spawndist < 0.0f) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `spawndist`< 0, set to 0.",guid,data.id); + data.spawndist = 0.0f; + } + else if (data.movementType == RANDOM_MOTION_TYPE) + { + if (data.spawndist == 0.0f) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=1 (random movement) but with `spawndist`=0, replace by idle movement type (0).",guid,data.id); + data.movementType = IDLE_MOTION_TYPE; + } + else if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) + data.movementType = IDLE_MOTION_TYPE; + } + else if (data.movementType == IDLE_MOTION_TYPE) + { + if (data.spawndist != 0.0f) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=0 (idle) have `spawndist`<>0, set to 0.",guid,data.id); + data.spawndist = 0.0f; + } + } + + if (data.phaseMask == 0) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id); + data.phaseMask = 1; + } + + //if (entry == 32307 || entry == 32308) + /*if (entry == 30739 || entry == 30740) + { + gameEvent = 51; + uint32 guid2 = objmgr.GenerateLowGuid(HIGHGUID_UNIT); + CreatureData& data2 = mCreatureDataMap[guid2]; + data2 = data; +// data2.id = (entry == 32307 ? 32308 : 32307); + data2.id = (entry == 30739 ? 30740 : 30739); + data2.displayid = 0; + gameeventmgr.mGameEventCreatureGuids[51+51].push_back(guid); + gameeventmgr.mGameEventCreatureGuids[51+50].push_back(guid2); + }*/ + + if (gameEvent == 0 && PoolId == 0) // if not this is to be managed by GameEvent System or Pool system + AddCreatureToGrid(guid, &data); + + ++count; + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu creatures", (unsigned long)mCreatureDataMap.size()); +} + +void ObjectMgr::AddCreatureToGrid(uint32 guid, CreatureData const* data) +{ + uint8 mask = data->spawnMask; + for (uint8 i = 0; mask != 0; i++, mask >>= 1) + { + if (mask & 1) + { + CellPair cell_pair = Trinity::ComputeCellPair(data->posX, data->posY); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; + cell_guids.creatures.insert(guid); + } + } +} + +void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data) +{ + uint8 mask = data->spawnMask; + for (uint8 i = 0; mask != 0; i++, mask >>= 1) + { + if (mask & 1) + { + CellPair cell_pair = Trinity::ComputeCellPair(data->posX, data->posY); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; + cell_guids.creatures.erase(guid); + } + } +} + +uint32 ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay, float rotation0, float rotation1, float rotation2, float rotation3) +{ + GameObjectInfo const* goinfo = GetGameObjectInfo(entry); + if (!goinfo) + return 0; + + Map* map = const_cast(MapManager::Instance().CreateBaseMap(mapId)); + if (!map) + return 0; + + uint32 guid = GenerateLowGuid(HIGHGUID_GAMEOBJECT); + GameObjectData& data = NewGOData(guid); + data.id = entry; + data.mapid = mapId; + data.posX = x; + data.posY = y; + data.posZ = z; + data.orientation = o; + data.rotation0 = rotation0; + data.rotation1 = rotation1; + data.rotation2 = rotation2; + data.rotation3 = rotation3; + data.spawntimesecs = spawntimedelay; + data.animprogress = 100; + data.spawnMask = 1; + data.go_state = GO_STATE_READY; + data.phaseMask = PHASEMASK_NORMAL; + data.artKit = goinfo->type == GAMEOBJECT_TYPE_CAPTURE_POINT ? 21 : 0; + data.dbData = false; + + AddGameobjectToGrid(guid, &data); + + // Spawn if necessary (loaded grids only) + // We use spawn coords to spawn + if (!map->Instanceable() && map->IsLoaded(x, y)) + { + GameObject *go = new GameObject; + if (!go->LoadFromDB(guid, map)) + { + sLog.outError("AddGOData: cannot add gameobject entry %u to map", entry); + delete go; + return 0; + } + map->Add(go); + } + + sLog.outDebug("AddGOData: dbguid %u entry %u map %u x %f y %f z %f o %f", guid, entry, mapId, x, y, z, o); + + return guid; +} + +bool ObjectMgr::MoveCreData(uint32 guid, uint32 mapId, Position pos) +{ + CreatureData& data = NewOrExistCreatureData(guid); + if (!data.id) + return false; + + RemoveCreatureFromGrid(guid, &data); + if (data.posX == pos.GetPositionX() && data.posY == pos.GetPositionY() && data.posZ == pos.GetPositionZ()) + return true; + data.posX = pos.GetPositionX(); + data.posY = pos.GetPositionY(); + data.posZ = pos.GetPositionZ(); + data.orientation = pos.GetOrientation(); + AddCreatureToGrid(guid, &data); + + // Spawn if necessary (loaded grids only) + if (Map* map = const_cast(MapManager::Instance().CreateBaseMap(mapId))) + { + // We use spawn coords to spawn + if (!map->Instanceable() && map->IsLoaded(data.posX, data.posY)) + { + Creature *creature = new Creature; + if (!creature->LoadFromDB(guid, map)) + { + sLog.outError("AddCreature: cannot add creature entry %u to map", guid); + delete creature; + return false; + } + map->Add(creature); + } + } + return true; +} + +uint32 ObjectMgr::AddCreData(uint32 entry, uint32 /*team*/, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay) +{ + CreatureInfo const *cInfo = GetCreatureTemplate(entry); + if (!cInfo) + return 0; + + uint32 level = cInfo->minlevel == cInfo->maxlevel ? cInfo->minlevel : urand(cInfo->minlevel, cInfo->maxlevel); // Only used for extracting creature base stats + CreatureBaseStats const* stats = objmgr.GetCreatureBaseStats(level, cInfo->unit_class); + + uint32 guid = GenerateLowGuid(HIGHGUID_UNIT); + CreatureData& data = NewOrExistCreatureData(guid); + data.id = entry; + data.mapid = mapId; + data.displayid = 0; + data.equipmentId = cInfo->equipmentId; + data.posX = x; + data.posY = y; + data.posZ = z; + data.orientation = o; + data.spawntimesecs = spawntimedelay; + data.spawndist = 0; + data.currentwaypoint = 0; + data.curhealth = stats->GenerateHealth(cInfo); + data.curmana = stats->GenerateMana(cInfo); + data.is_dead = false; + data.movementType = cInfo->MovementType; + data.spawnMask = 1; + data.phaseMask = PHASEMASK_NORMAL; + data.dbData = false; + + AddCreatureToGrid(guid, &data); + + // Spawn if necessary (loaded grids only) + if (Map* map = const_cast(MapManager::Instance().CreateBaseMap(mapId))) + { + // We use spawn coords to spawn + if (!map->Instanceable() && !map->IsRemovalGrid(x, y)) + { + Creature* creature = new Creature; + if (!creature->LoadFromDB(guid, map)) + { + sLog.outError("AddCreature: cannot add creature entry %u to map", entry); + delete creature; + return 0; + } + map->Add(creature); + } + } + + return guid; +} + +void ObjectMgr::LoadGameobjects() +{ + uint32 count = 0; + + // 0 1 2 3 4 5 6 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation," + // 7 8 9 10 11 12 13 14 15 16 17 + "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, event, pool_entry " + "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid " + "LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 gameobjects. DB table `gameobject` is empty."); + return; + } + + // build single time for check spawnmask + std::map spawnMasks; + for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) + if (sMapStore.LookupEntry(i)) + for (int k = 0; k < MAX_DIFFICULTY; ++k) + if (GetMapDifficultyData(i,Difficulty(k))) + spawnMasks[i] |= (1 << k); + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 guid = fields[ 0].GetUInt32(); + uint32 entry = fields[ 1].GetUInt32(); + + GameObjectInfo const* gInfo = GetGameObjectInfo(entry); + if (!gInfo) + { + sLog.outErrorDb("Table `gameobject` has gameobject (GUID: %u) with non existing gameobject entry %u, skipped.", guid, entry); + continue; + } + + if (!gInfo->displayId) + { + switch (gInfo->type) + { + case GAMEOBJECT_TYPE_TRAP: + case GAMEOBJECT_TYPE_SPELL_FOCUS: + break; + default: + sLog.outErrorDb("Gameobject (GUID: %u Entry %u GoType: %u) doesn't have displayId (%u), not loaded.", guid, entry, gInfo->type, gInfo->displayId); + break; + } + } + + if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId)) + { + sLog.outErrorDb("Gameobject (GUID: %u Entry %u GoType: %u) have invalid displayId (%u), not loaded.",guid, entry, gInfo->type, gInfo->displayId); + continue; + } + + GameObjectData& data = mGameObjectDataMap[guid]; + + data.id = entry; + data.mapid = fields[ 2].GetUInt32(); + data.posX = fields[ 3].GetFloat(); + data.posY = fields[ 4].GetFloat(); + data.posZ = fields[ 5].GetFloat(); + data.orientation = fields[ 6].GetFloat(); + data.rotation0 = fields[ 7].GetFloat(); + data.rotation1 = fields[ 8].GetFloat(); + data.rotation2 = fields[ 9].GetFloat(); + data.rotation3 = fields[10].GetFloat(); + data.spawntimesecs = fields[11].GetInt32(); + + MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); + if (!mapEntry) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) that spawned at not existed map (Id: %u), skip", guid, data.id, data.mapid); + continue; + } + + if (data.spawntimesecs == 0 && gInfo->IsDespawnAtAction()) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `spawntimesecs` (0) value, but gameobejct marked as despawnable at action.",guid,data.id); + } + + data.animprogress = fields[12].GetUInt32(); + data.artKit = 0; + + uint32 go_state = fields[13].GetUInt32(); + if (go_state >= MAX_GO_STATE) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid `state` (%u) value, skip",guid,data.id,go_state); + continue; + } + data.go_state = GOState(go_state); + + data.spawnMask = fields[14].GetUInt8(); + + if (data.spawnMask & ~spawnMasks[data.mapid]) + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid); + + data.phaseMask = fields[15].GetUInt16(); + int16 gameEvent = fields[16].GetInt16(); + int16 PoolId = fields[17].GetInt16(); + + if (data.rotation2 < -1.0f || data.rotation2 > 1.0f) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation2 (%f) value, skip",guid,data.id,data.rotation2); + continue; + } + + if (data.rotation3 < -1.0f || data.rotation3 > 1.0f) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation3 (%f) value, skip",guid,data.id,data.rotation3); + continue; + } + + if (!MapManager::IsValidMapCoord(data.mapid,data.posX,data.posY,data.posZ,data.orientation)) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid coordinates, skip",guid,data.id); + continue; + } + + if (data.phaseMask == 0) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id); + data.phaseMask = 1; + } + + if (gameEvent == 0 && PoolId == 0) // if not this is to be managed by GameEvent System or Pool system + AddGameobjectToGrid(guid, &data); + ++count; + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu gameobjects", (unsigned long)mGameObjectDataMap.size()); +} + +void ObjectMgr::AddGameobjectToGrid(uint32 guid, GameObjectData const* data) +{ + uint8 mask = data->spawnMask; + for (uint8 i = 0; mask != 0; i++, mask >>= 1) + { + if (mask & 1) + { + CellPair cell_pair = Trinity::ComputeCellPair(data->posX, data->posY); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; + cell_guids.gameobjects.insert(guid); + } + } +} + +void ObjectMgr::RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data) +{ + uint8 mask = data->spawnMask; + for (uint8 i = 0; mask != 0; i++, mask >>= 1) + { + if (mask & 1) + { + CellPair cell_pair = Trinity::ComputeCellPair(data->posX, data->posY); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(data->mapid,i)][cell_id]; + cell_guids.gameobjects.erase(guid); + } + } +} + +void ObjectMgr::LoadCreatureRespawnTimes() +{ + uint32 count = 0; + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT guid,respawntime,instance FROM creature_respawn"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded 0 creature respawn time."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 loguid = fields[0].GetUInt32(); + uint64 respawn_time = fields[1].GetUInt64(); + uint32 instance = fields[2].GetUInt32(); + + mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)] = time_t(respawn_time); + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu creature respawn times", (unsigned long)mCreatureRespawnTimes.size()); +} + +void ObjectMgr::LoadGameobjectRespawnTimes() +{ + // remove outdated data + WorldDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE respawntime <= UNIX_TIMESTAMP(NOW())"); + + uint32 count = 0; + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT guid,respawntime,instance FROM gameobject_respawn"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded 0 gameobject respawn time."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 loguid = fields[0].GetUInt32(); + uint64 respawn_time = fields[1].GetUInt64(); + uint32 instance = fields[2].GetUInt32(); + + mGORespawnTimes[MAKE_PAIR64(loguid,instance)] = time_t(respawn_time); + + ++count; + } while (result->NextRow()); + + sLog.outString(">> Loaded %lu gameobject respawn times", (unsigned long)mGORespawnTimes.size()); + sLog.outString(); +} + +// name must be checked to correctness (if received) before call this function +uint64 ObjectMgr::GetPlayerGUIDByName(std::string name) const +{ + uint64 guid = 0; + + CharacterDatabase.escape_string(name); + + // Player name safe to sending to DB (checked at login) and this function using + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT guid FROM characters WHERE name = '%s'", name.c_str()); + if (result) + guid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + + return guid; +} + +bool ObjectMgr::GetPlayerNameByGUID(const uint64 &guid, std::string &name) const +{ + // prevent DB access for online player + if (Player* player = GetPlayer(guid)) + { + name = player->GetName(); + return true; + } + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + + if (result) + { + name = (*result)[0].GetCppString(); + return true; + } + + return false; +} + +uint32 ObjectMgr::GetPlayerTeamByGUID(const uint64 &guid) const +{ + // prevent DB access for online player + if (Player* player = GetPlayer(guid)) + { + return Player::TeamForRace(player->getRace()); + } + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT race FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + + if (result) + { + uint8 race = (*result)[0].GetUInt8(); + return Player::TeamForRace(race); + } + + return 0; +} + +uint32 ObjectMgr::GetPlayerAccountIdByGUID(const uint64 &guid) const +{ + // prevent DB access for online player + if (Player* player = GetPlayer(guid)) + { + return player->GetSession()->GetAccountId(); + } + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + if (result) + { + uint32 acc = (*result)[0].GetUInt32(); + return acc; + } + + return 0; +} + +uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(const std::string& name) const +{ + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", name.c_str()); + if (result) + { + uint32 acc = (*result)[0].GetUInt32(); + return acc; + } + + return 0; +} + +void ObjectMgr::LoadItemLocales() +{ + mItemLocaleMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,name_loc1,description_loc1,name_loc2,description_loc2,name_loc3,description_loc3,name_loc4,description_loc4,name_loc5,description_loc5,name_loc6,description_loc6,name_loc7,description_loc7,name_loc8,description_loc8 FROM locales_item"); + + if (!result) + return; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + ItemLocale& data = mItemLocaleMap[entry]; + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+2*(i-1)].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Name.size() <= idx) + data.Name.resize(idx+1); + + data.Name[idx] = str; + } + } + + str = fields[1+2*(i-1)+1].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Description.size() <= idx) + data.Description.resize(idx+1); + + data.Description[idx] = str; + } + } + } + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu Item locale strings", (unsigned long)mItemLocaleMap.size()); +} + +struct SQLItemLoader : public SQLStorageLoaderBase +{ + template + void convert_from_str(uint32 /*field_pos*/, char *src, D &dst) + { + dst = D(objmgr.GetScriptId(src)); + } +}; + +void ObjectMgr::LoadItemPrototypes() +{ + SQLItemLoader loader; + loader.Load(sItemStorage); + sLog.outString(">> Loaded %u item prototypes", sItemStorage.RecordCount); + sLog.outString(); + + // check data correctness + for (uint32 i = 1; i < sItemStorage.MaxEntry; ++i) + { + ItemPrototype const* proto = sItemStorage.LookupEntry(i); + ItemEntry const *dbcitem = sItemStore.LookupEntry(i); + if (!proto) + { + /* to many errors, and possible not all items really used in game + if (dbcitem) + sLog.outErrorDb("Item (Entry: %u) doesn't exists in DB, but must exist.",i); + */ + continue; + } + + if (dbcitem) + { + if (proto->Class != dbcitem->Class) + { + sLog.outErrorDb("Item (Entry: %u) not correct class %u, must be %u (still using DB value).",i,proto->Class,dbcitem->Class); + // It safe let use Class from DB + } + /* disabled: have some strange wrong cases for Subclass values. + for enable also uncomment Subclass field in ItemEntry structure and in Itemfmt[] + if (proto->SubClass != dbcitem->SubClass) + { + sLog.outErrorDb("Item (Entry: %u) not correct (Class: %u, Sub: %u) pair, must be (Class: %u, Sub: %u) (still using DB value).",i,proto->Class,proto->SubClass,dbcitem->Class,dbcitem->SubClass); + // It safe let use Subclass from DB + } + */ + + if (proto->Unk0 != dbcitem->Unk0) + { + sLog.outErrorDb("Item (Entry: %u) not correct %i Unk0, must be %i (still using DB value).",i,proto->Unk0,dbcitem->Unk0); + // It safe let use Unk0 from DB + } + + if (proto->Material != dbcitem->Material) + { + sLog.outErrorDb("Item (Entry: %u) not correct %i material, must be %i (still using DB value).",i,proto->Material,dbcitem->Material); + // It safe let use Material from DB + } + + if (proto->InventoryType != dbcitem->InventoryType) + { + sLog.outErrorDb("Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value).",i,proto->InventoryType,dbcitem->InventoryType); + // It safe let use InventoryType from DB + } + + if (proto->DisplayInfoID != dbcitem->DisplayId) + { + sLog.outErrorDb("Item (Entry: %u) not correct %u display id, must be %u (using it).",i,proto->DisplayInfoID,dbcitem->DisplayId); + const_cast(proto)->DisplayInfoID = dbcitem->DisplayId; + } + if (proto->Sheath != dbcitem->Sheath) + { + sLog.outErrorDb("Item (Entry: %u) not correct %u sheath, must be %u (using it).",i,proto->Sheath,dbcitem->Sheath); + const_cast(proto)->Sheath = dbcitem->Sheath; + } + } + else + sLog.outErrorDb("Item (Entry: %u) not correct (not listed in list of existed items).",i); + + if (proto->Class >= MAX_ITEM_CLASS) + { + sLog.outErrorDb("Item (Entry: %u) has wrong Class value (%u)",i,proto->Class); + const_cast(proto)->Class = ITEM_CLASS_MISC; + } + + if (proto->SubClass >= MaxItemSubclassValues[proto->Class]) + { + sLog.outErrorDb("Item (Entry: %u) has wrong Subclass value (%u) for class %u",i,proto->SubClass,proto->Class); + const_cast(proto)->SubClass = 0;// exist for all item classes + } + + if (proto->Quality >= MAX_ITEM_QUALITY) + { + sLog.outErrorDb("Item (Entry: %u) has wrong Quality value (%u)",i,proto->Quality); + const_cast(proto)->Quality = ITEM_QUALITY_NORMAL; + } + + if (proto->BuyCount <= 0) + { + sLog.outErrorDb("Item (Entry: %u) has wrong BuyCount value (%u), set to default(1).",i,proto->BuyCount); + const_cast(proto)->BuyCount = 1; + } + + if (proto->InventoryType >= MAX_INVTYPE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong InventoryType value (%u)",i,proto->InventoryType); + const_cast(proto)->InventoryType = INVTYPE_NON_EQUIP; + } + + if (proto->RequiredSkill >= MAX_SKILL_TYPE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong RequiredSkill value (%u)",i,proto->RequiredSkill); + const_cast(proto)->RequiredSkill = 0; + } + + { + // can be used in equip slot, as page read use in inventory, or spell casting at use + bool req = proto->InventoryType != INVTYPE_NON_EQUIP || proto->PageText; + if (!req) + for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j) + { + if (proto->Spells[j].SpellId) + { + req = true; + break; + } + } + + if (req) + { + if (!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE)) + sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped or use.",i,proto->AllowableClass); + + if (!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE)) + sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped or use.",i,proto->AllowableRace); + } + } + + if (proto->RequiredSpell && !sSpellStore.LookupEntry(proto->RequiredSpell)) + { + sLog.outErrorDb("Item (Entry: %u) have wrong (non-existed) spell in RequiredSpell (%u)",i,proto->RequiredSpell); + const_cast(proto)->RequiredSpell = 0; + } + + if (proto->RequiredReputationRank >= MAX_REPUTATION_RANK) + sLog.outErrorDb("Item (Entry: %u) has wrong reputation rank in RequiredReputationRank (%u), item can't be used.",i,proto->RequiredReputationRank); + + if (proto->RequiredReputationFaction) + { + if (!sFactionStore.LookupEntry(proto->RequiredReputationFaction)) + { + sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) faction in RequiredReputationFaction (%u)",i,proto->RequiredReputationFaction); + const_cast(proto)->RequiredReputationFaction = 0; + } + + if (proto->RequiredReputationRank == MIN_REPUTATION_RANK) + sLog.outErrorDb("Item (Entry: %u) has min. reputation rank in RequiredReputationRank (0) but RequiredReputationFaction > 0, faction setting is useless.",i); + } + + if (proto->MaxCount < -1) + { + sLog.outErrorDb("Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits.",i,proto->MaxCount); + const_cast(proto)->MaxCount = -1; + } + + if (proto->Stackable == 0) + { + sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%i), replace by default 1.",i,proto->Stackable); + const_cast(proto)->Stackable = 1; + } + else if (proto->Stackable < -1) + { + sLog.outErrorDb("Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits.",i,proto->Stackable); + const_cast(proto)->Stackable = -1; + } + + if (proto->ContainerSlots > MAX_BAG_SIZE) + { + sLog.outErrorDb("Item (Entry: %u) has too large value in ContainerSlots (%u), replace by hardcoded limit (%u).",i,proto->ContainerSlots,MAX_BAG_SIZE); + const_cast(proto)->ContainerSlots = MAX_BAG_SIZE; + } + + if (proto->StatsCount > MAX_ITEM_PROTO_STATS) + { + sLog.outErrorDb("Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).",i,proto->StatsCount,MAX_ITEM_PROTO_STATS); + const_cast(proto)->StatsCount = MAX_ITEM_PROTO_STATS; + } + + for (uint8 j = 0; j < MAX_ITEM_PROTO_STATS; ++j) + { + // for ItemStatValue != 0 + if (proto->ItemStat[j].ItemStatValue && proto->ItemStat[j].ItemStatType >= MAX_ITEM_MOD) + { + sLog.outErrorDb("Item (Entry: %u) has wrong stat_type%d (%u)",i,j+1,proto->ItemStat[j].ItemStatType); + const_cast(proto)->ItemStat[j].ItemStatType = 0; + } + + switch (proto->ItemStat[j].ItemStatType) + { + case ITEM_MOD_SPELL_HEALING_DONE: + case ITEM_MOD_SPELL_DAMAGE_DONE: + sLog.outErrorDb("Item (Entry: %u) has deprecated stat_type%d (%u)",i,j+1,proto->ItemStat[j].ItemStatType); + break; + default: + break; + } + } + + for (uint8 j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j) + { + if (proto->Damage[j].DamageType >= MAX_SPELL_SCHOOL) + { + sLog.outErrorDb("Item (Entry: %u) has wrong dmg_type%d (%u)",i,j+1,proto->Damage[j].DamageType); + const_cast(proto)->Damage[j].DamageType = 0; + } + } + + // special format + if ((proto->Spells[0].SpellId == 483) || (proto->Spells[0].SpellId == 55884)) + { + // spell_1 + if (proto->Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format",i,0+1,proto->Spells[0].SpellTrigger); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[0].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + const_cast(proto)->Spells[1].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + + // spell_2 have learning spell + if (proto->Spells[1].SpellTrigger != ITEM_SPELLTRIGGER_LEARN_SPELL_ID) + { + sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format.",i,1+1,proto->Spells[1].SpellTrigger); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[1].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + else if (!proto->Spells[1].SpellId) + { + sLog.outErrorDb("Item (Entry: %u) not has expected spell in spellid_%d in special learning format.",i,1+1); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + else if (proto->Spells[1].SpellId != -1) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->Spells[1].SpellId); + if (!spellInfo) + { + sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)",i,1+1,proto->Spells[1].SpellId); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[1].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + // allowed only in special format + else if ((proto->Spells[1].SpellId == 483) || (proto->Spells[1].SpellId == 55884)) + { + sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%d)",i,1+1,proto->Spells[1].SpellId); + const_cast(proto)->Spells[0].SpellId = 0; + const_cast(proto)->Spells[1].SpellId = 0; + const_cast(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + } + + // spell_3*,spell_4*,spell_5* is empty + for (uint8 j = 2; j < MAX_ITEM_PROTO_SPELLS; ++j) + { + if (proto->Spells[j].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)",i,j+1,proto->Spells[j].SpellTrigger); + const_cast(proto)->Spells[j].SpellId = 0; + const_cast(proto)->Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + else if (proto->Spells[j].SpellId != 0) + { + sLog.outErrorDb("Item (Entry: %u) has wrong spell in spellid_%d (%d) for learning special format",i,j+1,proto->Spells[j].SpellId); + const_cast(proto)->Spells[j].SpellId = 0; + } + } + } + // normal spell list + else + { + for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j) + { + if (proto->Spells[j].SpellTrigger >= MAX_ITEM_SPELLTRIGGER || proto->Spells[j].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID) + { + sLog.outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)",i,j+1,proto->Spells[j].SpellTrigger); + const_cast(proto)->Spells[j].SpellId = 0; + const_cast(proto)->Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; + } + + if (proto->Spells[j].SpellId && proto->Spells[j].SpellId != -1) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->Spells[j].SpellId); + if (!spellInfo) + { + sLog.outErrorDb("Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)",i,j+1,proto->Spells[j].SpellId); + const_cast(proto)->Spells[j].SpellId = 0; + } + // allowed only in special format + else if ((proto->Spells[j].SpellId == 483) || (proto->Spells[j].SpellId == 55884)) + { + sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%d)",i,j+1,proto->Spells[j].SpellId); + const_cast(proto)->Spells[j].SpellId = 0; + } + } + } + } + + if (proto->Bonding >= MAX_BIND_TYPE) + sLog.outErrorDb("Item (Entry: %u) has wrong Bonding value (%u)",i,proto->Bonding); + + if (proto->PageText && !sPageTextStore.LookupEntry(proto->PageText)) + sLog.outErrorDb("Item (Entry: %u) has non existing first page (Id:%u)", i,proto->PageText); + + if (proto->LockID && !sLockStore.LookupEntry(proto->LockID)) + sLog.outErrorDb("Item (Entry: %u) has wrong LockID (%u)",i,proto->LockID); + + if (proto->Sheath >= MAX_SHEATHETYPE) + { + sLog.outErrorDb("Item (Entry: %u) has wrong Sheath (%u)",i,proto->Sheath); + const_cast(proto)->Sheath = SHEATHETYPE_NONE; + } + + if (proto->RandomProperty && !sItemRandomPropertiesStore.LookupEntry(GetItemEnchantMod(proto->RandomProperty))) + { + sLog.outErrorDb("Item (Entry: %u) has unknown (wrong or not listed in `item_enchantment_template`) RandomProperty (%u)",i,proto->RandomProperty); + const_cast(proto)->RandomProperty = 0; + } + + if (proto->RandomSuffix && !sItemRandomSuffixStore.LookupEntry(GetItemEnchantMod(proto->RandomSuffix))) + { + sLog.outErrorDb("Item (Entry: %u) has wrong RandomSuffix (%u)",i,proto->RandomSuffix); + const_cast(proto)->RandomSuffix = 0; + } + + if (proto->ItemSet && !sItemSetStore.LookupEntry(proto->ItemSet)) + { + sLog.outErrorDb("Item (Entry: %u) have wrong ItemSet (%u)",i,proto->ItemSet); + const_cast(proto)->ItemSet = 0; + } + + if (proto->Area && !GetAreaEntryByAreaID(proto->Area)) + sLog.outErrorDb("Item (Entry: %u) has wrong Area (%u)",i,proto->Area); + + if (proto->Map && !sMapStore.LookupEntry(proto->Map)) + sLog.outErrorDb("Item (Entry: %u) has wrong Map (%u)",i,proto->Map); + + if (proto->BagFamily) + { + // check bits + for (uint32 j = 0; j < sizeof(proto->BagFamily)*8; ++j) + { + uint32 mask = 1 << j; + if ((proto->BagFamily & mask) == 0) + continue; + + ItemBagFamilyEntry const* bf = sItemBagFamilyStore.LookupEntry(j+1); + if (!bf) + { + sLog.outErrorDb("Item (Entry: %u) has bag family bit set not listed in ItemBagFamily.dbc, remove bit",i); + const_cast(proto)->BagFamily &= ~mask; + continue; + } + + if (BAG_FAMILY_MASK_CURRENCY_TOKENS & mask) + { + CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(proto->ItemId); + if (!ctEntry) + { + sLog.outErrorDb("Item (Entry: %u) has currency bag family bit set in BagFamily but not listed in CurrencyTypes.dbc, remove bit",i); + const_cast(proto)->BagFamily &= ~mask; + } + } + } + } + + if (proto->TotemCategory && !sTotemCategoryStore.LookupEntry(proto->TotemCategory)) + sLog.outErrorDb("Item (Entry: %u) has wrong TotemCategory (%u)",i,proto->TotemCategory); + + for (uint8 j = 0; j < MAX_ITEM_PROTO_SOCKETS; ++j) + { + if (proto->Socket[j].Color && (proto->Socket[j].Color & SOCKET_COLOR_ALL) != proto->Socket[j].Color) + { + sLog.outErrorDb("Item (Entry: %u) has wrong socketColor_%d (%u)",i,j+1,proto->Socket[j].Color); + const_cast(proto)->Socket[j].Color = 0; + } + } + + if (proto->GemProperties && !sGemPropertiesStore.LookupEntry(proto->GemProperties)) + sLog.outErrorDb("Item (Entry: %u) has wrong GemProperties (%u)",i,proto->GemProperties); + + if (proto->FoodType >= MAX_PET_DIET) + { + sLog.outErrorDb("Item (Entry: %u) has wrong FoodType value (%u)",i,proto->FoodType); + const_cast(proto)->FoodType = 0; + } + + if (proto->ItemLimitCategory && !sItemLimitCategoryStore.LookupEntry(proto->ItemLimitCategory)) + { + sLog.outErrorDb("Item (Entry: %u) has wrong LimitCategory value (%u)",i,proto->ItemLimitCategory); + const_cast(proto)->ItemLimitCategory = 0; + } + + if (proto->HolidayId && !sHolidaysStore.LookupEntry(proto->HolidayId)) + { + sLog.outErrorDb("Item (Entry: %u) has wrong HolidayId value (%u)", i, proto->HolidayId); + const_cast(proto)->HolidayId = 0; + } + } + + // check some dbc referecned items (avoid duplicate reports) + std::set notFoundOutfit; + for (uint32 i = 1; i < sCharStartOutfitStore.GetNumRows(); ++i) + { + CharStartOutfitEntry const* entry = sCharStartOutfitStore.LookupEntry(i); + if (!entry) + continue; + + for (int j = 0; j < MAX_OUTFIT_ITEMS; ++j) + { + if (entry->ItemId[j] <= 0) + continue; + + uint32 item_id = entry->ItemId[j]; + + if (!GetItemPrototype(item_id)) + notFoundOutfit.insert(item_id); + } + } + + for (std::set::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr) + sLog.outErrorDb("Item (Entry: %u) not exist in `item_template` but referenced in `CharStartOutfit.dnc`", *itr); +} + +void ObjectMgr::LoadVehicleAccessories() +{ + m_VehicleAccessoryMap.clear(); // needed for reload case + + uint32 count = 0; + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT `entry`,`accessory_entry`,`seat_id`,`minion` FROM `vehicle_accessory`"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 LoadVehicleAccessor. DB table `vehicle_accessory` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 uiEntry = fields[0].GetUInt32(); + uint32 uiAccessory = fields[1].GetUInt32(); + int8 uiSeat = int8(fields[2].GetInt16()); + bool bMinion = fields[3].GetBool(); + + if (!sCreatureStorage.LookupEntry(uiEntry)) + { + sLog.outErrorDb("Table `vehicle_accessory`: creature template entry %u does not exist.", uiEntry); + continue; + } + + if (!sCreatureStorage.LookupEntry(uiAccessory)) + { + sLog.outErrorDb("Table `vehicle_accessory`: Accessory %u does not exist.", uiAccessory); + continue; + } + + m_VehicleAccessoryMap[uiEntry].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion)); + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u Vehicle Accessories", count); +} + +void ObjectMgr::LoadPetLevelInfo() +{ + // Loading levels data + { + // 0 1 2 3 4 5 6 7 8 9 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT creature_entry, level, hp, mana, str, agi, sta, inte, spi, armor FROM pet_levelstats"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + + sLog.outString(); + sLog.outString(">> Loaded %u level pet stats definitions", count); + sLog.outErrorDb("Error loading `pet_levelstats` table or empty table."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + uint32 creature_id = fields[0].GetUInt32(); + if (!sCreatureStorage.LookupEntry(creature_id)) + { + sLog.outErrorDb("Wrong creature id %u in `pet_levelstats` table, ignoring.",creature_id); + continue; + } + + uint32 current_level = fields[1].GetUInt32(); + if (current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); + else + { + sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `pet_levelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } + continue; + } + else if (current_level < 1) + { + sLog.outErrorDb("Wrong (<1) level %u in `pet_levelstats` table, ignoring.",current_level); + continue; + } + + PetLevelInfo*& pInfoMapEntry = petInfo[creature_id]; + + if (pInfoMapEntry == NULL) + pInfoMapEntry = new PetLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; + + // data for level 1 stored in [0] array element, ... + PetLevelInfo* pLevelInfo = &pInfoMapEntry[current_level-1]; + + pLevelInfo->health = fields[2].GetUInt16(); + pLevelInfo->mana = fields[3].GetUInt16(); + pLevelInfo->armor = fields[9].GetUInt16(); + + for (int i = 0; i < MAX_STATS; i++) + { + pLevelInfo->stats[i] = fields[i+4].GetUInt16(); + } + + bar.step(); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u level pet stats definitions", count); + } + + // Fill gaps and check integrity + for (PetLevelInfoMap::iterator itr = petInfo.begin(); itr != petInfo.end(); ++itr) + { + PetLevelInfo* pInfo = itr->second; + + // fatal error if no level 1 data + if (!pInfo || pInfo[0].health == 0) + { + sLog.outErrorDb("Creature %u does not have pet stats data for Level 1!",itr->first); + exit(1); + } + + // fill level gaps + for (uint8 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if (pInfo[level].health == 0) + { + sLog.outErrorDb("Creature %u has no data for Level %i pet stats data, using data of Level %i.",itr->first,level+1, level); + pInfo[level] = pInfo[level-1]; + } + } + } +} + +PetLevelInfo const* ObjectMgr::GetPetLevelInfo(uint32 creature_id, uint8 level) const +{ + if (level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); + + PetLevelInfoMap::const_iterator itr = petInfo.find(creature_id); + if (itr == petInfo.end()) + return NULL; + + return &itr->second[level-1]; // data for level 1 stored in [0] array element, ... +} + +void ObjectMgr::LoadPlayerInfo() +{ + // Load playercreate + { + // 0 1 2 3 4 5 6 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT race, class, map, zone, position_x, position_y, position_z FROM playercreateinfo"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + + sLog.outString(); + sLog.outString(">> Loaded %u player create definitions", count); + sLog.outErrorDb("Error loading `playercreateinfo` table or empty table."); + exit(1); + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + uint32 current_class = fields[1].GetUInt32(); + uint32 mapId = fields[2].GetUInt32(); + uint32 areaId = fields[3].GetUInt32(); + float positionX = fields[4].GetFloat(); + float positionY = fields[5].GetFloat(); + float positionZ = fields[6].GetFloat(); + + if (current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo` table, ignoring.",current_race); + continue; + } + + ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(current_race); + if (!rEntry) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo` table, ignoring.",current_race); + continue; + } + + if (current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo` table, ignoring.",current_class); + continue; + } + + if (!sChrClassesStore.LookupEntry(current_class)) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo` table, ignoring.",current_class); + continue; + } + + // accept DB data only for valid position (and non instanceable) + if (!MapManager::IsValidMapCoord(mapId,positionX,positionY,positionZ)) + { + sLog.outErrorDb("Wrong home position for class %u race %u pair in `playercreateinfo` table, ignoring.",current_class,current_race); + continue; + } + + if (sMapStore.LookupEntry(mapId)->Instanceable()) + { + sLog.outErrorDb("Home position in instanceable map for class %u race %u pair in `playercreateinfo` table, ignoring.",current_class,current_race); + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + + pInfo->mapId = mapId; + pInfo->areaId = areaId; + pInfo->positionX = positionX; + pInfo->positionY = positionY; + pInfo->positionZ = positionZ; + + pInfo->displayId_m = rEntry->model_m; + pInfo->displayId_f = rEntry->model_f; + + bar.step(); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u player create definitions", count); + } + + // Load playercreate items + sLog.outString("Loading Player Create Items Data..."); + { + // 0 1 2 3 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT race, class, itemid, amount FROM playercreateinfo_item"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u custom player create items", count); + } + else + { + barGoLink bar(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + if (current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo_item` table, ignoring.",current_race); + continue; + } + + uint32 current_class = fields[1].GetUInt32(); + if (current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo_item` table, ignoring.",current_class); + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + + uint32 item_id = fields[2].GetUInt32(); + + if (!GetItemPrototype(item_id)) + { + sLog.outErrorDb("Item id %u (race %u class %u) in `playercreateinfo_item` table but not listed in `item_template`, ignoring.",item_id,current_race,current_class); + continue; + } + + uint32 amount = fields[3].GetUInt32(); + + if (!amount) + { + sLog.outErrorDb("Item id %u (class %u race %u) have amount == 0 in `playercreateinfo_item` table, ignoring.",item_id,current_race,current_class); + continue; + } + + pInfo->item.push_back(PlayerCreateInfoItem(item_id, amount)); + + bar.step(); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u custom player create items", count); + } + } + + // Load playercreate spells + sLog.outString("Loading Player Create Spell Data..."); + { + + QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); + if (sWorld.getConfig(CONFIG_START_ALL_SPELLS)) + result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell_custom"); + else + result = WorldDatabase.Query("SELECT race, class, Spell FROM playercreateinfo_spell"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + + sLog.outString(); + sLog.outString(">> Loaded %u player create spells", count); + sLog.outErrorDb("Error loading player starting spells or empty table."); + } + else + { + barGoLink bar(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + if (current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo_spell` table, ignoring.",current_race); + continue; + } + + uint32 current_class = fields[1].GetUInt32(); + if (current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo_spell` table, ignoring.",current_class); + continue; + } + + if (!current_race || !current_class) + { + uint32 min_race = current_race ? current_race : 1; + uint32 max_race = current_race ? current_race + 1 : MAX_RACES; + uint32 min_class = current_class ? current_class : 1; + uint32 max_class = current_class ? current_class + 1 : MAX_CLASSES; + for (uint32 r = min_race; r < max_race; ++r) + for (uint32 c = min_class; c < max_class; ++c) + playerInfo[r][c].spell.push_back(fields[2].GetUInt32()); + } + else + playerInfo[current_race][current_class].spell.push_back(fields[2].GetUInt32()); + + bar.step(); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u player create spells", count); + } + } + + // Load playercreate actions + sLog.outString("Loading Player Create Action Data..."); + { + // 0 1 2 3 4 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT race, class, button, action, type FROM playercreateinfo_action"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + + sLog.outString(); + sLog.outString(">> Loaded %u player create actions", count); + sLog.outErrorDb("Error loading `playercreateinfo_action` table or empty table."); + } + else + { + barGoLink bar(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + if (current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `playercreateinfo_action` table, ignoring.",current_race); + continue; + } + + uint32 current_class = fields[1].GetUInt32(); + if (current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `playercreateinfo_action` table, ignoring.",current_class); + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + pInfo->action.push_back(PlayerCreateInfoAction(fields[2].GetUInt8(),fields[3].GetUInt32(),fields[4].GetUInt8())); + + bar.step(); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u player create actions", count); + } + } + + // Loading levels data (class only dependent) + sLog.outString("Loading Player Create Level HP/Mana Data..."); + { + // 0 1 2 3 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT class, level, basehp, basemana FROM player_classlevelstats"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + + sLog.outString(); + sLog.outString(">> Loaded %u level health/mana definitions", count); + sLog.outErrorDb("Error loading `player_classlevelstats` table or empty table."); + exit(1); + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + uint32 current_class = fields[0].GetUInt32(); + if (current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `player_classlevelstats` table, ignoring.",current_class); + continue; + } + + uint8 current_level = fields[1].GetUInt8(); + if (current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); + else + { + sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } + continue; + } + + PlayerClassInfo* pClassInfo = &playerClassInfo[current_class]; + + if (!pClassInfo->levelInfo) + pClassInfo->levelInfo = new PlayerClassLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; + + PlayerClassLevelInfo* pClassLevelInfo = &pClassInfo->levelInfo[current_level-1]; + + pClassLevelInfo->basehealth = fields[2].GetUInt16(); + pClassLevelInfo->basemana = fields[3].GetUInt16(); + + bar.step(); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u level health/mana definitions", count); + } + + // Fill gaps and check integrity + for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + { + // skip non existed classes + if (!sChrClassesStore.LookupEntry(class_)) + continue; + + PlayerClassInfo* pClassInfo = &playerClassInfo[class_]; + + // fatal error if no level 1 data + if (!pClassInfo->levelInfo || pClassInfo->levelInfo[0].basehealth == 0) + { + sLog.outErrorDb("Class %i Level 1 does not have health/mana data!",class_); + exit(1); + } + + // fill level gaps + for (uint8 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if (pClassInfo->levelInfo[level].basehealth == 0) + { + sLog.outErrorDb("Class %i Level %i does not have health/mana data. Using stats data of level %i.",class_,level+1, level); + pClassInfo->levelInfo[level] = pClassInfo->levelInfo[level-1]; + } + } + } + + // Loading levels data (class/race dependent) + sLog.outString("Loading Player Create Level Stats Data..."); + { + // 0 1 2 3 4 5 6 7 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT race, class, level, str, agi, sta, inte, spi FROM player_levelstats"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + + sLog.outString(); + sLog.outString(">> Loaded %u level stats definitions", count); + sLog.outErrorDb("Error loading `player_levelstats` table or empty table."); + exit(1); + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + uint32 current_race = fields[0].GetUInt32(); + if (current_race >= MAX_RACES) + { + sLog.outErrorDb("Wrong race %u in `player_levelstats` table, ignoring.",current_race); + continue; + } + + uint32 current_class = fields[1].GetUInt32(); + if (current_class >= MAX_CLASSES) + { + sLog.outErrorDb("Wrong class %u in `player_levelstats` table, ignoring.",current_class); + continue; + } + + uint32 current_level = fields[2].GetUInt32(); + if (current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); + else + { + sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_levelstats` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } + continue; + } + + PlayerInfo* pInfo = &playerInfo[current_race][current_class]; + + if (!pInfo->levelInfo) + pInfo->levelInfo = new PlayerLevelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)]; + + PlayerLevelInfo* pLevelInfo = &pInfo->levelInfo[current_level-1]; + + for (int i = 0; i < MAX_STATS; i++) + { + pLevelInfo->stats[i] = fields[i+3].GetUInt8(); + } + + bar.step(); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u level stats definitions", count); + } + + // Fill gaps and check integrity + for (int race = 0; race < MAX_RACES; ++race) + { + // skip non existed races + if (!sChrRacesStore.LookupEntry(race)) + continue; + + for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + { + // skip non existed classes + if (!sChrClassesStore.LookupEntry(class_)) + continue; + + PlayerInfo* pInfo = &playerInfo[race][class_]; + + // skip non loaded combinations + if (!pInfo->displayId_m || !pInfo->displayId_f) + continue; + + // skip expansion races if not playing with expansion + if (sWorld.getConfig(CONFIG_EXPANSION) < 1 && (race == RACE_BLOODELF || race == RACE_DRAENEI)) + continue; + + // skip expansion classes if not playing with expansion + if (sWorld.getConfig(CONFIG_EXPANSION) < 2 && class_ == CLASS_DEATH_KNIGHT) + continue; + + // fatal error if no level 1 data + if (!pInfo->levelInfo || pInfo->levelInfo[0].stats[0] == 0) + { + sLog.outErrorDb("Race %i Class %i Level 1 does not have stats data!",race,class_); + exit(1); + } + + // fill level gaps + for (uint8 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if (pInfo->levelInfo[level].stats[0] == 0) + { + sLog.outErrorDb("Race %i Class %i Level %i does not have stats data. Using stats data of level %i.",race,class_,level+1, level); + pInfo->levelInfo[level] = pInfo->levelInfo[level-1]; + } + } + } + } + + // Loading xp per level data + sLog.outString("Loading Player Create XP Data..."); + { + mPlayerXPperLevel.resize(sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + for (uint8 level = 0; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + mPlayerXPperLevel[level] = 0; + + // 0 1 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + + sLog.outString(); + sLog.outString(">> Loaded %u xp for level definitions", count); + sLog.outErrorDb("Error loading `player_xp_for_level` table or empty table."); + exit(1); + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + uint32 current_level = fields[0].GetUInt32(); + uint32 current_xp = fields[1].GetUInt32(); + + if (current_level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if (current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL,current_level); + else + { + sLog.outDetail("Unused (> MaxPlayerLevel in TrinityCore.conf) level %u in `player_xp_for_levels` table, ignoring.",current_level); + ++count; // make result loading percent "expected" correct in case disabled detail mode for example. + } + continue; + } + //PlayerXPperLevel + mPlayerXPperLevel[current_level] = current_xp; + bar.step(); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u xp for level definitions", count); + } + + // fill level gaps + for (uint8 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if (mPlayerXPperLevel[level] == 0) + { + sLog.outErrorDb("Level %i does not have XP for level data. Using data of level [%i] + 100.",level+1, level); + mPlayerXPperLevel[level] = mPlayerXPperLevel[level-1]+100; + } + } +} + +void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassLevelInfo* info) const +{ + if (level < 1 || class_ >= MAX_CLASSES) + return; + + PlayerClassInfo const* pInfo = &playerClassInfo[class_]; + + if (level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); + + *info = pInfo->levelInfo[level-1]; +} + +void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const +{ + if (level < 1 || race >= MAX_RACES || class_ >= MAX_CLASSES) + return; + + PlayerInfo const* pInfo = &playerInfo[race][class_]; + if (pInfo->displayId_m == 0 || pInfo->displayId_f == 0) + return; + + if (level <= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + *info = pInfo->levelInfo[level-1]; + else + BuildPlayerLevelInfo(race,class_,level,info); +} + +void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, PlayerLevelInfo* info) const +{ + // base data (last known level) + *info = playerInfo[race][_class].levelInfo[sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)-1]; + + // if conversion from uint32 to uint8 causes unexpected behaviour, change lvl to uint32 + for (uint8 lvl = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)-1; lvl < level; ++lvl) + { + switch(_class) + { + case CLASS_WARRIOR: + info->stats[STAT_STRENGTH] += (lvl > 23 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_STAMINA] += (lvl > 23 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_AGILITY] += (lvl > 36 ? 1: (lvl > 6 && (lvl%2) ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 9 && !(lvl%2) ? 1: 0); + break; + case CLASS_PALADIN: + info->stats[STAT_STRENGTH] += (lvl > 3 ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 33 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_AGILITY] += (lvl > 38 ? 1: (lvl > 7 && !(lvl%2) ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 6 && (lvl%2) ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 7 ? 1: 0); + break; + case CLASS_HUNTER: + info->stats[STAT_STRENGTH] += (lvl > 4 ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 33 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 8 && (lvl%2) ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 38 ? 1: (lvl > 9 && !(lvl%2) ? 1: 0)); + break; + case CLASS_ROGUE: + info->stats[STAT_STRENGTH] += (lvl > 5 ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 16 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 8 && !(lvl%2) ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 38 ? 1: (lvl > 9 && !(lvl%2) ? 1: 0)); + break; + case CLASS_PRIEST: + info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 5 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 38 ? 1: (lvl > 8 && (lvl%2) ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 22 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_SPIRIT] += (lvl > 3 ? 1: 0); + break; + case CLASS_SHAMAN: + info->stats[STAT_STRENGTH] += (lvl > 34 ? 1: (lvl > 6 && (lvl%2) ? 1: 0)); + info->stats[STAT_STAMINA] += (lvl > 4 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 7 && !(lvl%2) ? 1: 0); + info->stats[STAT_INTELLECT] += (lvl > 5 ? 1: 0); + info->stats[STAT_SPIRIT] += (lvl > 4 ? 1: 0); + break; + case CLASS_MAGE: + info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 5 ? 1: 0); + info->stats[STAT_AGILITY] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_INTELLECT] += (lvl > 24 ? 2: (lvl > 1 ? 1: 0)); + info->stats[STAT_SPIRIT] += (lvl > 33 ? 2: (lvl > 2 ? 1: 0)); + break; + case CLASS_WARLOCK: + info->stats[STAT_STRENGTH] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_STAMINA] += (lvl > 38 ? 2: (lvl > 3 ? 1: 0)); + info->stats[STAT_AGILITY] += (lvl > 9 && !(lvl%2) ? 1: 0); + info->stats[STAT_INTELLECT] += (lvl > 33 ? 2: (lvl > 2 ? 1: 0)); + info->stats[STAT_SPIRIT] += (lvl > 38 ? 2: (lvl > 3 ? 1: 0)); + break; + case CLASS_DRUID: + info->stats[STAT_STRENGTH] += (lvl > 38 ? 2: (lvl > 6 && (lvl%2) ? 1: 0)); + info->stats[STAT_STAMINA] += (lvl > 32 ? 2: (lvl > 4 ? 1: 0)); + info->stats[STAT_AGILITY] += (lvl > 38 ? 2: (lvl > 8 && (lvl%2) ? 1: 0)); + info->stats[STAT_INTELLECT] += (lvl > 38 ? 3: (lvl > 4 ? 1: 0)); + info->stats[STAT_SPIRIT] += (lvl > 38 ? 3: (lvl > 5 ? 1: 0)); + } + } +} + +void ObjectMgr::LoadGuilds() +{ + Guild *newGuild; + uint32 count = 0; + + // 0 1 2 3 4 5 6 + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT guild.guildid,guild.name,leaderguid,EmblemStyle,EmblemColor,BorderStyle,BorderColor," + // 7 8 9 10 11 12 + "BackgroundColor,info,motd,createdate,BankMoney,COUNT(guild_bank_tab.guildid) " + "FROM guild LEFT JOIN guild_bank_tab ON guild.guildid = guild_bank_tab.guildid GROUP BY guild.guildid ORDER BY guildid ASC"); + + if (!result) + { + + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u guild definitions", count); + return; + } + + // load guild ranks + // 0 1 2 3 4 + QueryResult_AutoPtr guildRanksResult = CharacterDatabase.Query("SELECT guildid,rid,rname,rights,BankMoneyPerDay FROM guild_rank ORDER BY guildid ASC, rid ASC"); + + // load guild members + // 0 1 2 3 4 5 6 + QueryResult_AutoPtr guildMembersResult = CharacterDatabase.Query("SELECT guildid,guild_member.guid,rank,pnote,offnote,BankResetTimeMoney,BankRemMoney," + // 7 8 9 10 11 12 + "BankResetTimeTab0,BankRemSlotsTab0,BankResetTimeTab1,BankRemSlotsTab1,BankResetTimeTab2,BankRemSlotsTab2," + // 13 14 15 16 17 18 + "BankResetTimeTab3,BankRemSlotsTab3,BankResetTimeTab4,BankRemSlotsTab4,BankResetTimeTab5,BankRemSlotsTab5," + // 19 20 21 22 23 + "characters.name, characters.level, characters.class, characters.zone, characters.logout_time " + "FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid ORDER BY guildid ASC"); + + // load guild bank tab rights + // 0 1 2 3 4 + QueryResult_AutoPtr guildBankTabRightsResult = CharacterDatabase.Query("SELECT guildid,TabId,rid,gbright,SlotPerDay FROM guild_bank_right ORDER BY guildid ASC, TabId ASC"); + + barGoLink bar(result->GetRowCount()); + + do + { + //Field *fields = result->Fetch(); + + bar.step(); + ++count; + + newGuild = new Guild; + if (!newGuild->LoadGuildFromDB(result) || + !newGuild->LoadRanksFromDB(guildRanksResult) || + !newGuild->LoadMembersFromDB(guildMembersResult) || + !newGuild->LoadBankRightsFromDB(guildBankTabRightsResult) || + !newGuild->CheckGuildStructure() +) + { + newGuild->Disband(); + delete newGuild; + continue; + } + newGuild->LoadGuildEventLogFromDB(); + newGuild->LoadGuildBankEventLogFromDB(); + newGuild->LoadGuildBankFromDB(); + AddGuild(newGuild); + + } while (result->NextRow()); + + //delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table + //you can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT + CharacterDatabase.PQuery("DELETE FROM guild_eventlog WHERE LogGuid > '%u'", sWorld.getConfig(CONFIG_GUILD_EVENT_LOG_COUNT)); + CharacterDatabase.PQuery("DELETE FROM guild_bank_eventlog WHERE LogGuid > '%u'", sWorld.getConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT)); + + sLog.outString(); + sLog.outString(">> Loaded %u guild definitions", count); +} + +void ObjectMgr::LoadArenaTeams() +{ + uint32 count = 0; + + // 0 1 2 3 4 5 + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT arena_team.arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle," + // 6 7 8 9 10 11 12 13 14 + "EmblemColor,BorderStyle,BorderColor, rating,games,wins,played,wins2,rank " + "FROM arena_team LEFT JOIN arena_team_stats ON arena_team.arenateamid = arena_team_stats.arenateamid ORDER BY arena_team.arenateamid ASC"); + + if (!result) + { + + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u arenateam definitions", count); + return; + } + + // load arena_team members + QueryResult_AutoPtr arenaTeamMembersResult = CharacterDatabase.Query( + // 0 1 2 3 4 5 6 7 8 + "SELECT arenateamid,member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class " + "FROM arena_team_member member LEFT JOIN characters chars on member.guid = chars.guid ORDER BY member.arenateamid ASC"); + + barGoLink bar(result->GetRowCount()); + + do + { + //Field *fields = result->Fetch(); + + bar.step(); + ++count; + + ArenaTeam *newArenaTeam = new ArenaTeam; + if (!newArenaTeam->LoadArenaTeamFromDB(result) || + !newArenaTeam->LoadMembersFromDB(arenaTeamMembersResult)) + { + newArenaTeam->Disband(NULL); + delete newArenaTeam; + continue; + } + AddArenaTeam(newArenaTeam); + }while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u arenateam definitions", count); +} + +void ObjectMgr::LoadGroups() +{ + Group *group = NULL; + Field *fields = NULL; + uint64 groupGuid = 0; + uint32 count = 0; + + // Consistency cleaning before load to avoid having to do some checks later + // Delete all members that does not exist + CharacterDatabase.PExecute("DELETE FROM group_member WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=memberGuid)"); + // Delete all groups whose leader does not exist + CharacterDatabase.PExecute("DELETE FROM groups WHERE NOT EXISTS (SELECT guid FROM characters WHERE guid=leaderGuid)"); + // Delete all groups with less than 2 members + CharacterDatabase.PExecute("DELETE FROM groups WHERE guid NOT IN (SELECT guid FROM group_member GROUP BY guid HAVING COUNT(guid) > 1)"); + // Delete all rows from group_member or group_instance with no group + CharacterDatabase.PExecute("DELETE FROM group_member WHERE guid NOT IN (SELECT guid FROM groups)"); + CharacterDatabase.PExecute("DELETE FROM group_instance WHERE guid NOT IN (SELECT guid FROM groups)"); + + // ----------------------- Load Group definitions + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty, guid FROM groups"); + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded 0 group definitions"); + return; + } + + barGoLink bar(result->GetRowCount()); + do + { + bar.step(); + fields = result->Fetch(); + ++count; + group = new Group; + groupGuid = MAKE_NEW_GUID(fields[15].GetUInt32(),0,HIGHGUID_GROUP); + group->LoadGroupFromDB(groupGuid, result, false); + // group load will never be false (we have run consistency sql's before loading) + AddGroup(group); + }while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u group definitions", count); + + // ----------------------- Load member + // 0 1 2 3 + result = CharacterDatabase.Query("SELECT guid, memberGuid, memberFlags, subgroup FROM group_member ORDER BY guid"); + if (!result) + { + barGoLink bar2(1); + bar2.step(); + sLog.outString(); + sLog.outString(">> Loaded 0 group members"); + return; + } + + barGoLink bar2(result->GetRowCount()); + uint32 groupLowGuid = 0; + count = 0; + do + { + bar2.step(); + fields = result->Fetch(); + + if (groupLowGuid != fields[0].GetUInt32()) + { + groupLowGuid = fields[0].GetUInt32(); + groupGuid = MAKE_NEW_GUID(groupLowGuid, 0, HIGHGUID_GROUP); + group = GetGroupByGUID(groupGuid); + // group will never be NULL (we have run consistency sql's before loading) + } + group->LoadMemberFromDB(fields[1].GetUInt32(), fields[2].GetUInt8(), fields[3].GetUInt8()); + ++count; + }while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u group members", count); + + + // ----------------------- Load instance save + // 0 1 2 3 4 5 + result = CharacterDatabase.Query("SELECT guid, map, instance, permanent, difficulty, resettime, " + // 6 + "(SELECT COUNT(1) FROM groups JOIN character_instance ON leaderGuid = groups.guid WHERE instance = group_instance.instance AND permanent = 1 LIMIT 1) " + "FROM group_instance LEFT JOIN instance ON instance = id ORDER BY guid"); + + if (!result) + { + barGoLink bar2(1); + bar2.step(); + sLog.outString(); + sLog.outString(">> Loaded 0 group-instance saves"); + return; + } + + barGoLink bar3(result->GetRowCount()); + count = 0; + do + { + bar3.step(); + fields = result->Fetch(); + groupGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_GROUP); + group = GetGroupByGUID(groupGuid); + // group will never be NULL (we have run consistency sql's before loading) + + MapEntry const* mapEntry = sMapStore.LookupEntry(fields[1].GetUInt32()); + if (!mapEntry || !mapEntry->IsDungeon()) + { + sLog.outErrorDb("Incorrect entry in group_instance table : no dungeon map %d", fields[1].GetUInt32()); + continue; + } + + uint32 diff = fields[4].GetUInt8(); + if (diff >= (mapEntry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) + { + sLog.outErrorDb("Wrong dungeon difficulty use in group_instance table: %d", diff + 1); + diff = 0; // default for both difficaly types + } + + InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt64()), fields[6].GetBool(), true); + group->BindToInstance(save, fields[3].GetBool(), true); + ++count; + }while (result->NextRow()); + sLog.outString(); + sLog.outString(">> Loaded %u group-instance saves", count); +} + +void ObjectMgr::LoadQuests() +{ + // For reload case + for (QuestMap::const_iterator itr=mQuestTemplates.begin(); itr != mQuestTemplates.end(); ++itr) + delete itr->second; + mQuestTemplates.clear(); + + mExclusiveQuestGroups.clear(); + + // 0 1 2 3 4 5 6 7 8 9 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, Method, ZoneOrSort, SkillOrClassMask, MinLevel, MaxLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue," + // 10 11 12 13 14 15 16 17 18 19 + "RepObjectiveFaction, RepObjectiveValue, RepObjectiveFaction2, RepObjectiveValue2, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime," + // 20 21 22 23 24 25 26 27 28 29 30 31 32 33 + "QuestFlags, SpecialFlags, CharTitleId, PlayersSlain, BonusTalents, RewardArenaPoints, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, RewXPId, SrcItemId, SrcItemCount, SrcSpell," + // 34 35 36 37 38 39 40 41 42 43 44 + "Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, CompletedText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4," + // 45 46 47 48 49 50 51 52 53 54 55 56 + "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemId5, ReqItemId6, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4, ReqItemCount5, ReqItemCount6," + // 57 58 59 60 61 62 63 64 + "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4," + // 65 66 67 68 69 70 71 72 + "ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4," + // 73 74 75 76 + "ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4," + // 77 78 79 80 81 82 + "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6," + // 83 84 85 86 87 88 + "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6," + // 89 90 91 92 93 94 95 96 + "RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4," + // 97 98 99 100 101 102 103 104 105 106 + "RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValueId1, RewRepValueId2, RewRepValueId3, RewRepValueId4, RewRepValueId5," + // 107 108 109 110 111 + "RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5," + // 112 113 114 115 116 117 118 119 120 121 122 123 + "RewHonorAddition, RewHonorMultiplier, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt," + // 124 125 126 127 128 129 130 131 + "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4," + // 132 133 134 135 136 137 + "IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," + // 138 139 140 141 + "OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4," + // 142 143 + "StartScript, CompleteScript" + " FROM quest_template"); + if (result == NULL) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded 0 quests definitions"); + sLog.outErrorDb("`quest_template` table is empty!"); + return; + } + + // create multimap previous quest for each existed quest + // some quests can have many previous maps set by NextQuestId in previous quest + // for example set of race quests can lead to single not race specific quest + barGoLink bar(result->GetRowCount()); + do + { + bar.step(); + Field *fields = result->Fetch(); + + Quest * newQuest = new Quest(fields); + mQuestTemplates[newQuest->GetQuestId()] = newQuest; + } while (result->NextRow()); + + std::map usedMailTemplates; + + // Post processing + for (QuestMap::iterator iter = mQuestTemplates.begin(); iter != mQuestTemplates.end(); ++iter) + { + Quest * qinfo = iter->second; + + // additional quest integrity checks (GO, creature_template and item_template must be loaded already) + + if (qinfo->GetQuestMethod() >= 3) + { + sLog.outErrorDb("Quest %u has `Method` = %u, expected values are 0, 1 or 2.",qinfo->GetQuestId(),qinfo->GetQuestMethod()); + } + + if (qinfo->QuestFlags & ~QUEST_TRINITY_FLAGS_DB_ALLOWED) + { + sLog.outErrorDb("Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u", + qinfo->GetQuestId(),qinfo->QuestFlags >> 20, QUEST_TRINITY_FLAGS_DB_ALLOWED >> 20); + qinfo->QuestFlags &= QUEST_TRINITY_FLAGS_DB_ALLOWED; + } + + if (qinfo->QuestFlags & QUEST_FLAGS_DAILY && qinfo->QuestFlags & QUEST_FLAGS_WEEKLY) + { + sLog.outErrorDb("Weekly Quest %u is marked as daily quest in `QuestFlags`, removed daily flag.",qinfo->GetQuestId()); + qinfo->QuestFlags &= ~QUEST_FLAGS_DAILY; + } + + if (qinfo->QuestFlags & QUEST_FLAGS_DAILY) + { + if (!(qinfo->QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE)) + { + sLog.outErrorDb("Daily Quest %u not marked as repeatable in `SpecialFlags`, added.",qinfo->GetQuestId()); + qinfo->QuestFlags |= QUEST_TRINITY_FLAGS_REPEATABLE; + } + } + + if (qinfo->QuestFlags & QUEST_FLAGS_WEEKLY) + { + if (!(qinfo->QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE)) + { + sLog.outErrorDb("Weekly Quest %u not marked as repeatable in `SpecialFlags`, added.",qinfo->GetQuestId()); + qinfo->QuestFlags |= QUEST_TRINITY_FLAGS_REPEATABLE; + } + } + + if (qinfo->QuestFlags & QUEST_FLAGS_AUTO_REWARDED) + { + // at auto-reward can be rewarded only RewChoiceItemId[0] + for (int j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j ) + { + if (uint32 id = qinfo->RewChoiceItemId[j]) + { + sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but item from `RewChoiceItemId%d` can't be rewarded with quest flag QUEST_FLAGS_AUTO_REWARDED.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes, quest ignore this data + } + } + } + + // client quest log visual (area case) + if (qinfo->ZoneOrSort > 0) + { + if (!GetAreaEntryByAreaID(qinfo->ZoneOrSort)) + { + sLog.outErrorDb("Quest %u has `ZoneOrSort` = %u (zone case) but zone with this id does not exist.", + qinfo->GetQuestId(),qinfo->ZoneOrSort); + // no changes, quest not dependent from this value but can have problems at client + } + } + // client quest log visual (sort case) + if (qinfo->ZoneOrSort < 0) + { + QuestSortEntry const* qSort = sQuestSortStore.LookupEntry(-int32(qinfo->ZoneOrSort)); + if (!qSort) + { + sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (sort case) but quest sort with this id does not exist.", + qinfo->GetQuestId(),qinfo->ZoneOrSort); + // no changes, quest not dependent from this value but can have problems at client (note some may be 0, we must allow this so no check) + } + //check SkillOrClass value (class case). + if (ClassByQuestSort(-int32(qinfo->ZoneOrSort))) + { + // SkillOrClass should not have class case when class case already set in ZoneOrSort. + if (qinfo->SkillOrClassMask < 0) + { + sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (class sort case) and `SkillOrClassMask` = %i (class case), redundant.", + qinfo->GetQuestId(),qinfo->ZoneOrSort,qinfo->SkillOrClassMask); + } + } + //check for proper SkillOrClass value (skill case) + if (int32 skill_id = SkillByQuestSort(-int32(qinfo->ZoneOrSort))) + { + // skill is positive value in SkillOrClass + if (qinfo->SkillOrClassMask != skill_id) + { + sLog.outErrorDb("Quest %u has `ZoneOrSort` = %i (skill sort case) but `SkillOrClassMask` does not have a corresponding value (%i).", + qinfo->GetQuestId(),qinfo->ZoneOrSort,skill_id); + //override, and force proper value here? + } + } + } + + // SkillOrClassMask (class case) + if (qinfo->SkillOrClassMask < 0) + { + if (!(-int32(qinfo->SkillOrClassMask) & CLASSMASK_ALL_PLAYABLE)) + { + sLog.outErrorDb("Quest %u has `SkillOrClassMask` = %i (class case) but classmask does not have valid class", + qinfo->GetQuestId(),qinfo->SkillOrClassMask); + } + } + // SkillOrClassMask (skill case) + if (qinfo->SkillOrClassMask > 0) + { + if (!sSkillLineStore.LookupEntry(qinfo->SkillOrClassMask)) + { + sLog.outErrorDb("Quest %u has `SkillOrClass` = %u (skill case) but skill (%i) does not exist", + qinfo->GetQuestId(),qinfo->SkillOrClassMask,qinfo->SkillOrClassMask); + } + } + + if (qinfo->RequiredSkillValue) + { + if (qinfo->RequiredSkillValue > sWorld.GetConfigMaxSkillValue()) + { + sLog.outErrorDb("Quest %u has `RequiredSkillValue` = %u but max possible skill is %u, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredSkillValue,sWorld.GetConfigMaxSkillValue()); + // no changes, quest can't be done for this requirement + } + + if (qinfo->SkillOrClassMask <= 0) + { + sLog.outErrorDb("Quest %u has `RequiredSkillValue` = %u but `SkillOrClass` = %i (class case), value ignored.", + qinfo->GetQuestId(),qinfo->RequiredSkillValue,qinfo->SkillOrClassMask); + // no changes, quest can't be done for this requirement (fail at wrong skill id) + } + } + // else Skill quests can have 0 skill level, this is ok + + if (qinfo->RepObjectiveFaction2 && !sFactionStore.LookupEntry(qinfo->RepObjectiveFaction2)) + { + sLog.outErrorDb("Quest %u has `RepObjectiveFaction2` = %u but faction template %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->RepObjectiveFaction2,qinfo->RepObjectiveFaction2); + // no changes, quest can't be done for this requirement + } + + if (qinfo->RepObjectiveFaction && !sFactionStore.LookupEntry(qinfo->RepObjectiveFaction)) + { + sLog.outErrorDb("Quest %u has `RepObjectiveFaction` = %u but faction template %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->RepObjectiveFaction,qinfo->RepObjectiveFaction); + // no changes, quest can't be done for this requirement + } + + if (qinfo->RequiredMinRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMinRepFaction)) + { + sLog.outErrorDb("Quest %u has `RequiredMinRepFaction` = %u but faction template %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredMinRepFaction,qinfo->RequiredMinRepFaction); + // no changes, quest can't be done for this requirement + } + + if (qinfo->RequiredMaxRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMaxRepFaction)) + { + sLog.outErrorDb("Quest %u has `RequiredMaxRepFaction` = %u but faction template %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredMaxRepFaction,qinfo->RequiredMaxRepFaction); + // no changes, quest can't be done for this requirement + } + + if (qinfo->RequiredMinRepValue && qinfo->RequiredMinRepValue > ReputationMgr::Reputation_Cap) + { + sLog.outErrorDb("Quest %u has `RequiredMinRepValue` = %d but max reputation is %u, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredMinRepValue,ReputationMgr::Reputation_Cap); + // no changes, quest can't be done for this requirement + } + + if (qinfo->RequiredMinRepValue && qinfo->RequiredMaxRepValue && qinfo->RequiredMaxRepValue <= qinfo->RequiredMinRepValue) + { + sLog.outErrorDb("Quest %u has `RequiredMaxRepValue` = %d and `RequiredMinRepValue` = %d, quest can't be done.", + qinfo->GetQuestId(),qinfo->RequiredMaxRepValue,qinfo->RequiredMinRepValue); + // no changes, quest can't be done for this requirement + } + + if (!qinfo->RepObjectiveFaction && qinfo->RepObjectiveValue > 0) + { + sLog.outErrorDb("Quest %u has `RepObjectiveValue` = %d but `RepObjectiveFaction` is 0, value has no effect", + qinfo->GetQuestId(),qinfo->RepObjectiveValue); + // warning + } + + if (!qinfo->RepObjectiveFaction2 && qinfo->RepObjectiveValue2 > 0) + { + sLog.outErrorDb("Quest %u has `RepObjectiveValue2` = %d but `RepObjectiveFaction2` is 0, value has no effect", + qinfo->GetQuestId(),qinfo->RepObjectiveValue2); + // warning + } + + if (!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue > 0) + { + sLog.outErrorDb("Quest %u has `RequiredMinRepValue` = %d but `RequiredMinRepFaction` is 0, value has no effect", + qinfo->GetQuestId(),qinfo->RequiredMinRepValue); + // warning + } + + if (!qinfo->RequiredMaxRepFaction && qinfo->RequiredMaxRepValue > 0) + { + sLog.outErrorDb("Quest %u has `RequiredMaxRepValue` = %d but `RequiredMaxRepFaction` is 0, value has no effect", + qinfo->GetQuestId(),qinfo->RequiredMaxRepValue); + // warning + } + + if (qinfo->CharTitleId && !sCharTitlesStore.LookupEntry(qinfo->CharTitleId)) + { + sLog.outErrorDb("Quest %u has `CharTitleId` = %u but CharTitle Id %u does not exist, quest can't be rewarded with title.", + qinfo->GetQuestId(),qinfo->GetCharTitleId(),qinfo->GetCharTitleId()); + qinfo->CharTitleId = 0; + // quest can't reward this title + } + + if (qinfo->SrcItemId) + { + if (!sItemStorage.LookupEntry(qinfo->SrcItemId)) + { + sLog.outErrorDb("Quest %u has `SrcItemId` = %u but item with entry %u does not exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->SrcItemId,qinfo->SrcItemId); + qinfo->SrcItemId = 0; // quest can't be done for this requirement + } + else if (qinfo->SrcItemCount == 0) + { + sLog.outErrorDb("Quest %u has `SrcItemId` = %u but `SrcItemCount` = 0, set to 1 but need fix in DB.", + qinfo->GetQuestId(),qinfo->SrcItemId); + qinfo->SrcItemCount = 1; // update to 1 for allow quest work for backward compatibility with DB + } + } + else if (qinfo->SrcItemCount>0) + { + sLog.outErrorDb("Quest %u has `SrcItemId` = 0 but `SrcItemCount` = %u, useless value.", + qinfo->GetQuestId(),qinfo->SrcItemCount); + qinfo->SrcItemCount=0; // no quest work changes in fact + } + + if (qinfo->SrcSpell) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->SrcSpell); + if (!spellInfo) + { + sLog.outErrorDb("Quest %u has `SrcSpell` = %u but spell %u doesn't exist, quest can't be done.", + qinfo->GetQuestId(),qinfo->SrcSpell,qinfo->SrcSpell); + qinfo->SrcSpell = 0; // quest can't be done for this requirement + } + else if (!SpellMgr::IsSpellValid(spellInfo)) + { + sLog.outErrorDb("Quest %u has `SrcSpell` = %u but spell %u is broken, quest can't be done.", + qinfo->GetQuestId(),qinfo->SrcSpell,qinfo->SrcSpell); + qinfo->SrcSpell = 0; // quest can't be done for this requirement + } + } + + for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j) + { + uint32 id = qinfo->ReqItemId[j]; + if (id) + { + if (qinfo->ReqItemCount[j] == 0) + { + sLog.outErrorDb("Quest %u has `ReqItemId%d` = %u but `ReqItemCount%d` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes, quest can't be done for this requirement + } + + qinfo->SetFlag(QUEST_TRINITY_FLAGS_DELIVER); + + if (!sItemStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `ReqItemId%d` = %u but item with entry %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,id); + qinfo->ReqItemCount[j] = 0; // prevent incorrect work of quest + } + } + else if (qinfo->ReqItemCount[j]>0) + { + sLog.outErrorDb("Quest %u has `ReqItemId%d` = 0 but `ReqItemCount%d` = %u, quest can't be done.", + qinfo->GetQuestId(),j+1,j+1,qinfo->ReqItemCount[j]); + qinfo->ReqItemCount[j] = 0; // prevent incorrect work of quest + } + } + + for (uint8 j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j) + { + uint32 id = qinfo->ReqSourceId[j]; + if (id) + { + if (!sItemStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but item with entry %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,id); + // no changes, quest can't be done for this requirement + } + } + else + { + if (qinfo->ReqSourceCount[j]>0) + { + sLog.outErrorDb("Quest %u has `ReqSourceId%d` = 0 but `ReqSourceCount%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->ReqSourceCount[j]); + // no changes, quest ignore this data + } + } + } + + for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) + { + uint32 id = qinfo->ReqSpell[j]; + if (id) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(id); + if (!spellInfo) + { + sLog.outErrorDb("Quest %u has `ReqSpellCast%d` = %u but spell %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,id); + continue; + } + + if (!qinfo->ReqCreatureOrGOId[j]) + { + bool found = false; + for (uint8 k = 0; k < 3; ++k) + { + if ((spellInfo->Effect[k] == SPELL_EFFECT_QUEST_COMPLETE && uint32(spellInfo->EffectMiscValue[k]) == qinfo->QuestId) || + spellInfo->Effect[k] == SPELL_EFFECT_SEND_EVENT) + { + found = true; + break; + } + } + + if (found) + { + if (!qinfo->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + { + sLog.outErrorDb("Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and ReqCreatureOrGOId%d = 0, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags or ReqCreatureOrGOId%d must be fixed, quest modified to enable objective.",spellInfo->Id,qinfo->QuestId,j+1,j+1); + + // this will prevent quest completing without objective + const_cast(qinfo)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); + } + } + else + { + sLog.outErrorDb("Quest %u has `ReqSpellCast%d` = %u and ReqCreatureOrGOId%d = 0 but spell %u does not have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT effect for this quest, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1,id); + // no changes, quest can't be done for this requirement + } + } + } + } + + for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) + { + int32 id = qinfo->ReqCreatureOrGOId[j]; + if (id < 0 && !sGOStorage.LookupEntry(-id)) + { + sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %i but gameobject %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,uint32(-id)); + qinfo->ReqCreatureOrGOId[j] = 0; // quest can't be done for this requirement + } + + if (id > 0 && !sCreatureStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %i but creature with entry %u does not exist, quest can't be done.", + qinfo->GetQuestId(),j+1,id,uint32(id)); + qinfo->ReqCreatureOrGOId[j] = 0; // quest can't be done for this requirement + } + + if (id) + { + // In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast + + qinfo->SetFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO); + + if (!qinfo->ReqCreatureOrGOCount[j]) + { + sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = %u but `ReqCreatureOrGOCount%d` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes, quest can be incorrectly done, but we already report this + } + } + else if (qinfo->ReqCreatureOrGOCount[j]>0) + { + sLog.outErrorDb("Quest %u has `ReqCreatureOrGOId%d` = 0 but `ReqCreatureOrGOCount%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->ReqCreatureOrGOCount[j]); + // no changes, quest ignore this data + } + } + + for (uint8 j = 0; j < QUEST_REWARD_CHOICES_COUNT; ++j) + { + uint32 id = qinfo->RewChoiceItemId[j]; + if (id) + { + if (!sItemStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but item with entry %u does not exist, quest will not reward this item.", + qinfo->GetQuestId(),j+1,id,id); + qinfo->RewChoiceItemId[j] = 0; // no changes, quest will not reward this + } + + if (!qinfo->RewChoiceItemCount[j]) + { + sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = %u but `RewChoiceItemCount%d` = 0, quest can't be done.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes, quest can't be done + } + } + else if (qinfo->RewChoiceItemCount[j]>0) + { + sLog.outErrorDb("Quest %u has `RewChoiceItemId%d` = 0 but `RewChoiceItemCount%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->RewChoiceItemCount[j]); + // no changes, quest ignore this data + } + } + + for (uint8 j = 0; j < QUEST_REWARDS_COUNT; ++j) + { + uint32 id = qinfo->RewItemId[j]; + if (id) + { + if (!sItemStorage.LookupEntry(id)) + { + sLog.outErrorDb("Quest %u has `RewItemId%d` = %u but item with entry %u does not exist, quest will not reward this item.", + qinfo->GetQuestId(),j+1,id,id); + qinfo->RewItemId[j] = 0; // no changes, quest will not reward this item + } + + if (!qinfo->RewItemCount[j]) + { + sLog.outErrorDb("Quest %u has `RewItemId%d` = %u but `RewItemCount%d` = 0, quest will not reward this item.", + qinfo->GetQuestId(),j+1,id,j+1); + // no changes + } + } + else if (qinfo->RewItemCount[j]>0) + { + sLog.outErrorDb("Quest %u has `RewItemId%d` = 0 but `RewItemCount%d` = %u.", + qinfo->GetQuestId(),j+1,j+1,qinfo->RewItemCount[j]); + // no changes, quest ignore this data + } + } + + for (uint8 j = 0; j < QUEST_REPUTATIONS_COUNT; ++j) + { + if (qinfo->RewRepFaction[j]) + { + if (abs(qinfo->RewRepValueId[j]) > 9) + { + sLog.outErrorDb("Quest %u has RewRepValueId%d = %i. That is outside the range of valid values (-9 to 9).", qinfo->GetQuestId(), j+1, qinfo->RewRepValueId[j]); + } + if (!sFactionStore.LookupEntry(qinfo->RewRepFaction[j])) + { + sLog.outErrorDb("Quest %u has `RewRepFaction%d` = %u but raw faction (faction.dbc) %u does not exist, quest will not reward reputation for this faction.", qinfo->GetQuestId(),j+1,qinfo->RewRepFaction[j] ,qinfo->RewRepFaction[j]); + qinfo->RewRepFaction[j] = 0; // quest will not reward this + } + } + + + else if (qinfo->RewRepValue[j] != 0) + { + sLog.outErrorDb("Quest %u has `RewRepFaction%d` = 0 but `RewRepValue%d` = %i.", + qinfo->GetQuestId(),j+1,j+1,qinfo->RewRepValue[j]); + // no changes, quest ignore this data + } + } + + + if (qinfo->RewSpell) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->RewSpell); + + if (!spellInfo) + { + sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u does not exist, spell removed as display reward.", + qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell); + qinfo->RewSpell = 0; // no spell reward will display for this quest + } + + else if (!SpellMgr::IsSpellValid(spellInfo)) + { + sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is broken, quest will not have a spell reward.", + qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell); + qinfo->RewSpell = 0; // no spell reward will display for this quest + } + + else if (GetTalentSpellCost(qinfo->RewSpell)) + { + sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is talent, quest will not have a spell reward.", + qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell); + qinfo->RewSpell = 0; // no spell reward will display for this quest + } + } + + if (qinfo->RewSpellCast > 0) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(qinfo->RewSpellCast); + + if (!spellInfo) + { + sLog.outErrorDb("Quest %u has `RewSpellCast` = %u but spell %u does not exist, quest will not have a spell reward.", + qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast); + qinfo->RewSpellCast = 0; // no spell will be casted on player + } + + else if (!SpellMgr::IsSpellValid(spellInfo)) + { + sLog.outErrorDb("Quest %u has `RewSpellCast` = %u but spell %u is broken, quest will not have a spell reward.", + qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast); + qinfo->RewSpellCast = 0; // no spell will be casted on player + } + + else if (GetTalentSpellCost(qinfo->RewSpellCast)) + { + sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is talent, quest will not have a spell reward.", + qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast); + qinfo->RewSpellCast = 0; // no spell will be casted on player + } + } + + if (qinfo->RewMailTemplateId) + { + if (!sMailTemplateStore.LookupEntry(qinfo->RewMailTemplateId)) + { + sLog.outErrorDb("Quest %u has `RewMailTemplateId` = %u but mail template %u does not exist, quest will not have a mail reward.", + qinfo->GetQuestId(),qinfo->RewMailTemplateId,qinfo->RewMailTemplateId); + qinfo->RewMailTemplateId = 0; // no mail will send to player + qinfo->RewMailDelaySecs = 0; // no mail will send to player + } + else if (usedMailTemplates.find(qinfo->RewMailTemplateId) != usedMailTemplates.end()) + { + std::map::const_iterator used_mt_itr = usedMailTemplates.find(qinfo->RewMailTemplateId); + sLog.outErrorDb("Quest %u has `RewMailTemplateId` = %u but mail template %u already used for quest %u, quest will not have a mail reward.", + qinfo->GetQuestId(),qinfo->RewMailTemplateId,qinfo->RewMailTemplateId,used_mt_itr->second); + qinfo->RewMailTemplateId = 0; // no mail will send to player + qinfo->RewMailDelaySecs = 0; // no mail will send to player + } + else + usedMailTemplates[qinfo->RewMailTemplateId] = qinfo->GetQuestId(); + } + + if (qinfo->NextQuestInChain) + { + QuestMap::iterator qNextItr = mQuestTemplates.find(qinfo->NextQuestInChain); + if (qNextItr == mQuestTemplates.end()) + { + sLog.outErrorDb("Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.", + qinfo->GetQuestId(),qinfo->NextQuestInChain ,qinfo->NextQuestInChain); + qinfo->NextQuestInChain = 0; + } + else + qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId()); + } + + // fill additional data stores + if (qinfo->PrevQuestId) + { + if (mQuestTemplates.find(abs(qinfo->GetPrevQuestId())) == mQuestTemplates.end()) + { + sLog.outErrorDb("Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId()); + } + else + { + qinfo->prevQuests.push_back(qinfo->PrevQuestId); + } + } + + if (qinfo->NextQuestId) + { + QuestMap::iterator qNextItr = mQuestTemplates.find(abs(qinfo->GetNextQuestId())); + if (qNextItr == mQuestTemplates.end()) + { + sLog.outErrorDb("Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId()); + } + else + { + int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId()); + qNextItr->second->prevQuests.push_back(signedQuestId); + } + } + + if (qinfo->ExclusiveGroup) + mExclusiveQuestGroups.insert(std::pair(qinfo->ExclusiveGroup, qinfo->GetQuestId())); + if (qinfo->LimitTime) + qinfo->SetFlag(QUEST_TRINITY_FLAGS_TIMED); + } + + // check QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE + for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(i); + if (!spellInfo) + continue; + + for (uint8 j = 0; j < 3; ++j) + { + if (spellInfo->Effect[j] != SPELL_EFFECT_QUEST_COMPLETE) + continue; + + uint32 quest_id = spellInfo->EffectMiscValue[j]; + + Quest const* quest = GetQuestTemplate(quest_id); + + // some quest referenced in spells not exist (outdated spells) + if (!quest) + continue; + + if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + { + sLog.outErrorDb("Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u , but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective.",spellInfo->Id,quest_id); + + // this will prevent quest completing without objective + const_cast(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); + } + } + } + + sLog.outString(); + sLog.outString(">> Loaded %lu quests definitions", (unsigned long)mQuestTemplates.size()); +} + +void ObjectMgr::LoadQuestLocales() +{ + mQuestLocaleMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry," + "Title_loc1,Details_loc1,Objectives_loc1,OfferRewardText_loc1,RequestItemsText_loc1,EndText_loc1,CompletedText_loc1,ObjectiveText1_loc1,ObjectiveText2_loc1,ObjectiveText3_loc1,ObjectiveText4_loc1," + "Title_loc2,Details_loc2,Objectives_loc2,OfferRewardText_loc2,RequestItemsText_loc2,EndText_loc2,CompletedText_loc2,ObjectiveText1_loc2,ObjectiveText2_loc2,ObjectiveText3_loc2,ObjectiveText4_loc2," + "Title_loc3,Details_loc3,Objectives_loc3,OfferRewardText_loc3,RequestItemsText_loc3,EndText_loc3,CompletedText_loc3,ObjectiveText1_loc3,ObjectiveText2_loc3,ObjectiveText3_loc3,ObjectiveText4_loc3," + "Title_loc4,Details_loc4,Objectives_loc4,OfferRewardText_loc4,RequestItemsText_loc4,EndText_loc4,CompletedText_loc4,ObjectiveText1_loc4,ObjectiveText2_loc4,ObjectiveText3_loc4,ObjectiveText4_loc4," + "Title_loc5,Details_loc5,Objectives_loc5,OfferRewardText_loc5,RequestItemsText_loc5,EndText_loc5,CompletedText_loc5,ObjectiveText1_loc5,ObjectiveText2_loc5,ObjectiveText3_loc5,ObjectiveText4_loc5," + "Title_loc6,Details_loc6,Objectives_loc6,OfferRewardText_loc6,RequestItemsText_loc6,EndText_loc6,CompletedText_loc6,ObjectiveText1_loc6,ObjectiveText2_loc6,ObjectiveText3_loc6,ObjectiveText4_loc6," + "Title_loc7,Details_loc7,Objectives_loc7,OfferRewardText_loc7,RequestItemsText_loc7,EndText_loc7,CompletedText_loc7,ObjectiveText1_loc7,ObjectiveText2_loc7,ObjectiveText3_loc7,ObjectiveText4_loc7," + "Title_loc8,Details_loc8,Objectives_loc8,OfferRewardText_loc8,RequestItemsText_loc8,EndText_loc8,CompletedText_loc8,ObjectiveText1_loc8,ObjectiveText2_loc8,ObjectiveText3_loc8,ObjectiveText4_loc8" + " FROM locales_quest" +); + + if (!result) + return; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + QuestLocale& data = mQuestLocaleMap[entry]; + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+11*(i-1)].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Title.size() <= idx) + data.Title.resize(idx+1); + + data.Title[idx] = str; + } + } + str = fields[1+11*(i-1)+1].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Details.size() <= idx) + data.Details.resize(idx+1); + + data.Details[idx] = str; + } + } + str = fields[1+11*(i-1)+2].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Objectives.size() <= idx) + data.Objectives.resize(idx+1); + + data.Objectives[idx] = str; + } + } + str = fields[1+11*(i-1)+3].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.OfferRewardText.size() <= idx) + data.OfferRewardText.resize(idx+1); + + data.OfferRewardText[idx] = str; + } + } + str = fields[1+11*(i-1)+4].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.RequestItemsText.size() <= idx) + data.RequestItemsText.resize(idx+1); + + data.RequestItemsText[idx] = str; + } + } + str = fields[1+11*(i-1)+5].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.EndText.size() <= idx) + data.EndText.resize(idx+1); + + data.EndText[idx] = str; + } + } + str = fields[1+11*(i-1)+6].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.CompletedText.size() <= idx) + data.CompletedText.resize(idx+1); + + data.CompletedText[idx] = str; + } + } + + for (uint8 k = 0; k < 4; ++k) + { + str = fields[1+11*(i-1)+7+k].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.ObjectiveText[k].size() <= idx) + data.ObjectiveText[k].resize(idx+1); + + data.ObjectiveText[k][idx] = str; + } + } + } + } + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu Quest locale strings", (unsigned long)mQuestLocaleMap.size()); +} + +void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) +{ + if (sWorld.IsScriptScheduled()) // function don't must be called in time scripts use. + return; + + sLog.outString("%s :", tablename); + + scripts.clear(); // need for reload support + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id,delay,command,datalong,datalong2,dataint, x, y, z, o FROM %s", tablename); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u script definitions", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + ScriptInfo tmp; + tmp.id = fields[0].GetUInt32(); + tmp.delay = fields[1].GetUInt32(); + tmp.command = fields[2].GetUInt32(); + tmp.datalong = fields[3].GetUInt32(); + tmp.datalong2 = fields[4].GetUInt32(); + tmp.dataint = fields[5].GetInt32(); + tmp.x = fields[6].GetFloat(); + tmp.y = fields[7].GetFloat(); + tmp.z = fields[8].GetFloat(); + tmp.o = fields[9].GetFloat(); + + // generic command args check + switch (tmp.command) + { + case SCRIPT_COMMAND_TALK: + { + if (tmp.datalong > CHAT_TYPE_WHISPER) + { + sLog.outErrorDb("Table `%s` has invalid talk type (datalong = %u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + if (tmp.dataint == 0) + { + sLog.outErrorDb("Table `%s` has invalid talk text id (dataint = %i) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.dataint,tmp.id); + continue; + } + if (tmp.dataint < MIN_DB_SCRIPT_STRING_ID || tmp.dataint >= MAX_DB_SCRIPT_STRING_ID) + { + sLog.outErrorDb("Table `%s` has out of range text id (dataint = %i expected %u-%u) in SCRIPT_COMMAND_TALK for script id %u",tablename,tmp.dataint,MIN_DB_SCRIPT_STRING_ID,MAX_DB_SCRIPT_STRING_ID,tmp.id); + continue; + } + + break; + } + + case SCRIPT_COMMAND_EMOTE: + { + if (!sEmotesStore.LookupEntry(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` has invalid emote id (datalong = %u) in SCRIPT_COMMAND_EMOTE for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + break; + } + + case SCRIPT_COMMAND_TELEPORT_TO: + { + if (!sMapStore.LookupEntry(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` has invalid map (Id: %u) in SCRIPT_COMMAND_TELEPORT_TO for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + + if (!Trinity::IsValidMapCoord(tmp.x,tmp.y,tmp.z,tmp.o)) + { + sLog.outErrorDb("Table `%s` has invalid coordinates (X: %f Y: %f) in SCRIPT_COMMAND_TELEPORT_TO for script id %u",tablename,tmp.x,tmp.y,tmp.id); + continue; + } + break; + } + + case SCRIPT_COMMAND_KILL_CREDIT: + { + if (!GetCreatureTemplate(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` has invalid creature (Entry: %u) in SCRIPT_COMMAND_KILL_CREDIT for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + break; + } + + case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: + { + if (!Trinity::IsValidMapCoord(tmp.x,tmp.y,tmp.z,tmp.o)) + { + sLog.outErrorDb("Table `%s` has invalid coordinates (X: %f Y: %f) in SCRIPT_COMMAND_TEMP_SUMMON_CREATURE for script id %u",tablename,tmp.x,tmp.y,tmp.id); + continue; + } + + if (!GetCreatureTemplate(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` has invalid creature (Entry: %u) in SCRIPT_COMMAND_TEMP_SUMMON_CREATURE for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + break; + } + + case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: + { + GameObjectData const* data = GetGOData(tmp.datalong); + if (!data) + { + sLog.outErrorDb("Table `%s` has invalid gameobject (GUID: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + + GameObjectInfo const* info = GetGameObjectInfo(data->id); + if (!info) + { + sLog.outErrorDb("Table `%s` has gameobject with invalid entry (GUID: %u Entry: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,tmp.datalong,data->id,tmp.id); + continue; + } + + if (info->type == GAMEOBJECT_TYPE_FISHINGNODE || + info->type == GAMEOBJECT_TYPE_FISHINGHOLE || + info->type == GAMEOBJECT_TYPE_DOOR || + info->type == GAMEOBJECT_TYPE_BUTTON || + info->type == GAMEOBJECT_TYPE_TRAP) + { + sLog.outErrorDb("Table `%s` have gameobject type (%u) unsupported by command SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u",tablename,info->id,tmp.id); + continue; + } + break; + } + case SCRIPT_COMMAND_OPEN_DOOR: + case SCRIPT_COMMAND_CLOSE_DOOR: + { + GameObjectData const* data = GetGOData(tmp.datalong); + if (!data) + { + sLog.outErrorDb("Table `%s` has invalid gameobject (GUID: %u) in %s for script id %u",tablename,tmp.datalong,(tmp.command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); + continue; + } + + GameObjectInfo const* info = GetGameObjectInfo(data->id); + if (!info) + { + sLog.outErrorDb("Table `%s` has gameobject with invalid entry (GUID: %u Entry: %u) in %s for script id %u",tablename,tmp.datalong,data->id,(tmp.command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); + continue; + } + + if (info->type != GAMEOBJECT_TYPE_DOOR) + { + sLog.outErrorDb("Table `%s` has gameobject type (%u) non supported by command %s for script id %u",tablename,info->id,(tmp.command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR"),tmp.id); + continue; + } + + break; + } + case SCRIPT_COMMAND_QUEST_EXPLORED: + { + Quest const* quest = GetQuestTemplate(tmp.datalong); + if (!quest) + { + sLog.outErrorDb("Table `%s` has invalid quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + + if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + { + sLog.outErrorDb("Table `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective.",tablename,tmp.datalong,tmp.id); + + // this will prevent quest completing without objective + const_cast(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); + + // continue; - quest objective requirement set and command can be allowed + } + + if (float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) + { + sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u", + tablename,tmp.datalong2,tmp.id); + continue; + } + + if (tmp.datalong2 && float(tmp.datalong2) > DEFAULT_VISIBILITY_DISTANCE) + { + sLog.outErrorDb("Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, max distance is %f or 0 for disable distance check", + tablename,tmp.datalong2,tmp.id,DEFAULT_VISIBILITY_DISTANCE); + continue; + } + + if (tmp.datalong2 && float(tmp.datalong2) < INTERACTION_DISTANCE) + { + sLog.outErrorDb("Table `%s` has too small distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, min distance is %f or 0 for disable distance check", + tablename,tmp.datalong2,tmp.id,INTERACTION_DISTANCE); + continue; + } + + break; + } + + case SCRIPT_COMMAND_REMOVE_AURA: + { + if (!sSpellStore.LookupEntry(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u", + tablename,tmp.datalong,tmp.id); + continue; + } + if (tmp.datalong2 & ~0x1) // 1 bits (0,1) + { + sLog.outErrorDb("Table `%s` using unknown flags in datalong2 (%u)i n SCRIPT_COMMAND_CAST_SPELL for script id %u", + tablename,tmp.datalong2,tmp.id); + continue; + } + break; + } + case SCRIPT_COMMAND_CAST_SPELL: + { + if (!sSpellStore.LookupEntry(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u", + tablename,tmp.datalong,tmp.id); + continue; + } + if (tmp.datalong2 & ~0x3) // 2 bits + { + sLog.outErrorDb("Table `%s` using unknown flags in datalong2 (%u)i n SCRIPT_COMMAND_CAST_SPELL for script id %u", + tablename,tmp.datalong2,tmp.id); + continue; + } + break; + } + + case SCRIPT_COMMAND_CREATE_ITEM: + { + if (!GetItemPrototype(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` has nonexistent item (entry: %u) in SCRIPT_COMMAND_CREATE_ITEM for script id %u", + tablename, tmp.datalong, tmp.id); + continue; + } + if (!tmp.datalong2) + { + sLog.outErrorDb("Table `%s` SCRIPT_COMMAND_CREATE_ITEM but amount is %u for script id %u", + tablename, tmp.datalong2, tmp.id); + continue; + } + break; + } + } + + if (scripts.find(tmp.id) == scripts.end()) + { + ScriptMap emptyMap; + scripts[tmp.id] = emptyMap; + } + scripts[tmp.id].insert(std::pair(tmp.delay, tmp)); + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u script definitions", count); +} + +void ObjectMgr::LoadGameObjectScripts() +{ + LoadScripts(sGameObjectScripts, "gameobject_scripts"); + + // check ids + for (ScriptMapMap::const_iterator itr = sGameObjectScripts.begin(); itr != sGameObjectScripts.end(); ++itr) + { + if (!GetGOData(itr->first)) + sLog.outErrorDb("Table `gameobject_scripts` has not existing gameobject (GUID: %u) as script id",itr->first); + } +} + +void ObjectMgr::LoadQuestEndScripts() +{ + LoadScripts(sQuestEndScripts, "quest_end_scripts"); + + // check ids + for (ScriptMapMap::const_iterator itr = sQuestEndScripts.begin(); itr != sQuestEndScripts.end(); ++itr) + { + if (!GetQuestTemplate(itr->first)) + sLog.outErrorDb("Table `quest_end_scripts` has not existing quest (Id: %u) as script id",itr->first); + } +} + +void ObjectMgr::LoadQuestStartScripts() +{ + LoadScripts(sQuestStartScripts,"quest_start_scripts"); + + // check ids + for (ScriptMapMap::const_iterator itr = sQuestStartScripts.begin(); itr != sQuestStartScripts.end(); ++itr) + { + if (!GetQuestTemplate(itr->first)) + sLog.outErrorDb("Table `quest_start_scripts` has not existing quest (Id: %u) as script id",itr->first); + } +} + +void ObjectMgr::LoadSpellScripts() +{ + LoadScripts(sSpellScripts, "spell_scripts"); + + // check ids + for (ScriptMapMap::const_iterator itr = sSpellScripts.begin(); itr != sSpellScripts.end(); ++itr) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->first); + + if (!spellInfo) + { + sLog.outErrorDb("Table `spell_scripts` has not existing spell (Id: %u) as script id",itr->first); + continue; + } + + //check for correct spellEffect + bool found = false; + for (uint8 i=0; i<3; ++i) + { + // skip empty effects + if (!spellInfo->Effect[i]) + continue; + + if (spellInfo->Effect[i] == SPELL_EFFECT_SCRIPT_EFFECT) + { + found = true; + break; + } + } + + if (!found) + sLog.outErrorDb("Table `spell_scripts` has unsupported spell (Id: %u) without SPELL_EFFECT_SCRIPT_EFFECT (%u) spell effect",itr->first,SPELL_EFFECT_SCRIPT_EFFECT); + } +} + +void ObjectMgr::LoadEventScripts() +{ + LoadScripts(sEventScripts, "event_scripts"); + + std::set evt_scripts; + // Load all possible script entries from gameobjects + for (uint32 i = 1; i < sGOStorage.MaxEntry; ++i) + { + GameObjectInfo const * goInfo = sGOStorage.LookupEntry(i); + if (goInfo) + { + switch(goInfo->type) + { + case GAMEOBJECT_TYPE_GOOBER: + if (goInfo->goober.eventId) + evt_scripts.insert(goInfo->goober.eventId); + break; + case GAMEOBJECT_TYPE_CHEST: + if (goInfo->chest.eventId) + evt_scripts.insert(goInfo->chest.eventId); + break; + case GAMEOBJECT_TYPE_CAMERA: + if (goInfo->camera.eventID) + evt_scripts.insert(goInfo->camera.eventID); + default: + break; + } + } + } + // Load all possible script entries from spells + for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) + { + SpellEntry const * spell = sSpellStore.LookupEntry(i); + if (spell) + { + for (uint8 j=0; j<3; ++j) + { + if (spell->Effect[j] == SPELL_EFFECT_SEND_EVENT) + { + if (spell->EffectMiscValue[j]) + evt_scripts.insert(spell->EffectMiscValue[j]); + } + } + } + } + + // Then check if all scripts are in above list of possible script entries + for (ScriptMapMap::const_iterator itr = sEventScripts.begin(); itr != sEventScripts.end(); ++itr) + { + std::set::const_iterator itr2 = evt_scripts.find(itr->first); + if (itr2 == evt_scripts.end()) + sLog.outErrorDb("Table `event_scripts` has script (Id: %u) not referring to any gameobject_template type 10 data2 field, type 3 data6 field, type 13 data 2 field or any spell effect %u", + itr->first, SPELL_EFFECT_SEND_EVENT); + } +} + +//Load WP Scripts +void ObjectMgr::LoadWaypointScripts() +{ + LoadScripts(sWaypointScripts, "waypoint_scripts"); + + for (ScriptMapMap::const_iterator itr = sWaypointScripts.begin(); itr != sWaypointScripts.end(); ++itr) + { + QueryResult_AutoPtr query = WorldDatabase.PQuery("SELECT * FROM waypoint_scripts WHERE id = %u", itr->first); + if (!query || !query->GetRowCount()) + sLog.outErrorDb("There is no waypoint which links to the waypoint script %u", itr->first); + } +} + +void ObjectMgr::LoadGossipScripts() +{ + LoadScripts(sGossipScripts, "gossip_scripts"); + + // checks are done in LoadGossipMenuItems +} + +void ObjectMgr::LoadPageTexts() +{ + sPageTextStore.Free(); // for reload case + + sPageTextStore.Load(); + sLog.outString(">> Loaded %u page texts", sPageTextStore.RecordCount); + sLog.outString(); + + for (uint32 i = 1; i < sPageTextStore.MaxEntry; ++i) + { + // check data correctness + PageText const* page = sPageTextStore.LookupEntry(i); + if (!page) + continue; + + if (page->Next_Page && !sPageTextStore.LookupEntry(page->Next_Page)) + { + sLog.outErrorDb("Page text (Id: %u) has not existing next page (Id:%u)", i,page->Next_Page); + continue; + } + + // detect circular reference + std::set checkedPages; + for (PageText const* pageItr = page; pageItr; pageItr = sPageTextStore.LookupEntry(pageItr->Next_Page)) + { + if (!pageItr->Next_Page) + break; + checkedPages.insert(pageItr->Page_ID); + if (checkedPages.find(pageItr->Next_Page)!= checkedPages.end()) + { + std::ostringstream ss; + ss << "The text page(s) "; + for (std::set::iterator itr= checkedPages.begin(); itr != checkedPages.end(); ++itr) + ss << *itr << " "; + ss << "create(s) a circular reference, which can cause the server to freeze. Changing Next_Page of page " + << pageItr->Page_ID <<" to 0"; + sLog.outErrorDb(ss.str().c_str()); + const_cast(pageItr)->Next_Page = 0; + break; + } + } + } +} + +void ObjectMgr::LoadPageTextLocales() +{ + mPageTextLocaleMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,text_loc1,text_loc2,text_loc3,text_loc4,text_loc5,text_loc6,text_loc7,text_loc8 FROM locales_page_text"); + + if (!result) + return; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + PageTextLocale& data = mPageTextLocaleMap[entry]; + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[i].GetCppString(); + if (str.empty()) + continue; + + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Text.size() <= idx) + data.Text.resize(idx+1); + + data.Text[idx] = str; + } + } + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu PageText locale strings", (unsigned long)mPageTextLocaleMap.size()); +} + +struct SQLInstanceLoader : public SQLStorageLoaderBase +{ + template + void convert_from_str(uint32 /*field_pos*/, char *src, D &dst) + { + dst = D(objmgr.GetScriptId(src)); + } +}; + +void ObjectMgr::LoadInstanceTemplate() +{ + SQLInstanceLoader loader; + loader.Load(sInstanceTemplate); + + for (uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) + { + InstanceTemplate* temp = (InstanceTemplate*)GetInstanceTemplate(i); + if (!temp) + continue; + + if (!MapManager::IsValidMAP(temp->map)) + sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad mapid %d for template!", temp->map); + + if (!MapManager::IsValidMapCoord(temp->parent,temp->startLocX,temp->startLocY,temp->startLocZ,temp->startLocO)) + { + sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad parent entrance coordinates for map id %d template!", temp->map); + temp->parent = 0; // will have wrong continent 0 parent, at least existed + } + } + + sLog.outString(">> Loaded %u Instance Template definitions", sInstanceTemplate.RecordCount); + sLog.outString(); +} + +GossipText const *ObjectMgr::GetGossipText(uint32 Text_ID) const +{ + GossipTextMap::const_iterator itr = mGossipText.find(Text_ID); + if (itr != mGossipText.end()) + return &itr->second; + return NULL; +} + +void ObjectMgr::LoadGossipText() +{ + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT * FROM npc_text"); + + int count = 0; + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u npc texts", count); + return; + } + + int cic; + + barGoLink bar(result->GetRowCount()); + + do + { + ++count; + cic = 0; + + Field *fields = result->Fetch(); + + bar.step(); + + uint32 Text_ID = fields[cic++].GetUInt32(); + if (!Text_ID) + { + sLog.outErrorDb("Table `npc_text` has record wit reserved id 0, ignore."); + continue; + } + + GossipText& gText = mGossipText[Text_ID]; + + for (int i=0; i< 8; i++) + { + gText.Options[i].Text_0 = fields[cic++].GetCppString(); + gText.Options[i].Text_1 = fields[cic++].GetCppString(); + + gText.Options[i].Language = fields[cic++].GetUInt32(); + gText.Options[i].Probability = fields[cic++].GetFloat(); + + for (uint8 j=0; j < 3; ++j) + { + gText.Options[i].Emotes[j]._Delay = fields[cic++].GetUInt32(); + gText.Options[i].Emotes[j]._Emote = fields[cic++].GetUInt32(); + } + } + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u npc texts", count); +} + +void ObjectMgr::LoadNpcTextLocales() +{ + mNpcTextLocaleMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry," + "Text0_0_loc1,Text0_1_loc1,Text1_0_loc1,Text1_1_loc1,Text2_0_loc1,Text2_1_loc1,Text3_0_loc1,Text3_1_loc1,Text4_0_loc1,Text4_1_loc1,Text5_0_loc1,Text5_1_loc1,Text6_0_loc1,Text6_1_loc1,Text7_0_loc1,Text7_1_loc1," + "Text0_0_loc2,Text0_1_loc2,Text1_0_loc2,Text1_1_loc2,Text2_0_loc2,Text2_1_loc2,Text3_0_loc2,Text3_1_loc1,Text4_0_loc2,Text4_1_loc2,Text5_0_loc2,Text5_1_loc2,Text6_0_loc2,Text6_1_loc2,Text7_0_loc2,Text7_1_loc2," + "Text0_0_loc3,Text0_1_loc3,Text1_0_loc3,Text1_1_loc3,Text2_0_loc3,Text2_1_loc3,Text3_0_loc3,Text3_1_loc1,Text4_0_loc3,Text4_1_loc3,Text5_0_loc3,Text5_1_loc3,Text6_0_loc3,Text6_1_loc3,Text7_0_loc3,Text7_1_loc3," + "Text0_0_loc4,Text0_1_loc4,Text1_0_loc4,Text1_1_loc4,Text2_0_loc4,Text2_1_loc4,Text3_0_loc4,Text3_1_loc1,Text4_0_loc4,Text4_1_loc4,Text5_0_loc4,Text5_1_loc4,Text6_0_loc4,Text6_1_loc4,Text7_0_loc4,Text7_1_loc4," + "Text0_0_loc5,Text0_1_loc5,Text1_0_loc5,Text1_1_loc5,Text2_0_loc5,Text2_1_loc5,Text3_0_loc5,Text3_1_loc1,Text4_0_loc5,Text4_1_loc5,Text5_0_loc5,Text5_1_loc5,Text6_0_loc5,Text6_1_loc5,Text7_0_loc5,Text7_1_loc5," + "Text0_0_loc6,Text0_1_loc6,Text1_0_loc6,Text1_1_loc6,Text2_0_loc6,Text2_1_loc6,Text3_0_loc6,Text3_1_loc1,Text4_0_loc6,Text4_1_loc6,Text5_0_loc6,Text5_1_loc6,Text6_0_loc6,Text6_1_loc6,Text7_0_loc6,Text7_1_loc6," + "Text0_0_loc7,Text0_1_loc7,Text1_0_loc7,Text1_1_loc7,Text2_0_loc7,Text2_1_loc7,Text3_0_loc7,Text3_1_loc1,Text4_0_loc7,Text4_1_loc7,Text5_0_loc7,Text5_1_loc7,Text6_0_loc7,Text6_1_loc7,Text7_0_loc7,Text7_1_loc7, " + "Text0_0_loc8,Text0_1_loc8,Text1_0_loc8,Text1_1_loc8,Text2_0_loc8,Text2_1_loc8,Text3_0_loc8,Text3_1_loc1,Text4_0_loc8,Text4_1_loc8,Text5_0_loc8,Text5_1_loc8,Text6_0_loc8,Text6_1_loc8,Text7_0_loc8,Text7_1_loc8 " + " FROM locales_npc_text"); + + if (!result) + return; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + NpcTextLocale& data = mNpcTextLocaleMap[entry]; + + for (uint8 i=1; i= 0) + { + if (data.Text_0[j].size() <= idx) + data.Text_0[j].resize(idx+1); + + data.Text_0[j][idx] = str0; + } + } + std::string str1 = fields[1+8*2*(i-1)+2*j+1].GetCppString(); + if (!str1.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Text_1[j].size() <= idx) + data.Text_1[j].resize(idx+1); + + data.Text_1[j][idx] = str1; + } + } + } + } + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu NpcText locale strings", (unsigned long)mNpcTextLocaleMap.size()); +} + +//not very fast function but it is called only once a day, or on starting-up +void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) +{ + time_t basetime = time(NULL); + sLog.outDebug("Returning mails current time: hour: %d, minute: %d, second: %d ", localtime(&basetime)->tm_hour, localtime(&basetime)->tm_min, localtime(&basetime)->tm_sec); + //delete all old mails without item and without body immediately, if starting server + if (!serverUp) + CharacterDatabase.PExecute("DELETE FROM mail WHERE expire_time < '" UI64FMTD "' AND has_items = '0' AND body = ''", (uint64)basetime); + // 0 1 2 3 4 5 6 7 8 9 + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" UI64FMTD "'", (uint64)basetime); + if (!result) + { + barGoLink bar(1); + bar.step(); + sLog.outString(); + sLog.outString(">> Only expired mails (need to be return or delete) or DB table `mail` is empty."); + return; // any mails need to be returned or deleted + } + + //std::ostringstream delitems, delmails; //will be here for optimization + //bool deletemail = false, deleteitem = false; + //delitems << "DELETE FROM item_instance WHERE guid IN ("; + //delmails << "DELETE FROM mail WHERE id IN (" + + barGoLink bar(result->GetRowCount()); + uint32 count = 0; + Field *fields; + + do + { + bar.step(); + + fields = result->Fetch(); + Mail *m = new Mail; + m->messageID = fields[0].GetUInt32(); + m->messageType = fields[1].GetUInt8(); + m->sender = fields[2].GetUInt32(); + m->receiver = fields[3].GetUInt32(); + bool has_items = fields[4].GetBool(); + m->expire_time = (time_t)fields[5].GetUInt64(); + m->deliver_time = 0; + m->COD = fields[6].GetUInt32(); + m->checked = fields[7].GetUInt32(); + m->mailTemplateId = fields[8].GetInt16(); + + Player *pl = 0; + if (serverUp) + pl = GetPlayer((uint64)m->receiver); + if (pl && pl->m_mailsLoaded) + { //this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail + //his in mailbox and he has already listed his mails) + delete m; + continue; + } + //delete or return mail: + if (has_items) + { + QueryResult_AutoPtr resultItems = CharacterDatabase.PQuery("SELECT item_guid,item_template FROM mail_items WHERE mail_id='%u'", m->messageID); + if (resultItems) + { + do + { + Field *fields2 = resultItems->Fetch(); + + uint32 item_guid_low = fields2[0].GetUInt32(); + uint32 item_template = fields2[1].GetUInt32(); + + m->AddItem(item_guid_low, item_template); + } + while (resultItems->NextRow()); + } + //if it is mail from AH, it shouldn't be returned, but deleted + if (m->messageType != MAIL_NORMAL || m->messageType == MAIL_AUCTION || (m->checked & (MAIL_CHECK_MASK_COD_PAYMENT | MAIL_CHECK_MASK_RETURNED))) + { + // mail open and then not returned + for (std::vector::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) + CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", itr2->item_guid); + } + else + { + //mail will be returned: + CharacterDatabase.PExecute("UPDATE mail SET sender = '%u', receiver = '%u', expire_time = '" UI64FMTD "', deliver_time = '" UI64FMTD "',cod = '0', checked = '%u' WHERE id = '%u'", m->receiver, m->sender, (uint64)(basetime + 30*DAY), (uint64)basetime, MAIL_CHECK_MASK_RETURNED, m->messageID); + delete m; + continue; + } + } + + //deletemail = true; + //delmails << m->messageID << ", "; + CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID); + delete m; + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u mails", count); +} + +void ObjectMgr::LoadQuestAreaTriggers() +{ + mQuestAreaTriggerMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id,quest FROM areatrigger_involvedrelation"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u quest trigger points", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 trigger_ID = fields[0].GetUInt32(); + uint32 quest_ID = fields[1].GetUInt32(); + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(trigger_ID); + if (!atEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",trigger_ID); + continue; + } + + Quest const* quest = GetQuestTemplate(quest_ID); + + if (!quest) + { + sLog.outErrorDb("Table `areatrigger_involvedrelation` has record (id: %u) for not existing quest %u",trigger_ID,quest_ID); + continue; + } + + if (!quest->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) + { + sLog.outErrorDb("Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.",trigger_ID,quest_ID); + + // this will prevent quest completing without objective + const_cast(quest)->SetFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT); + + // continue; - quest modified to required objective and trigger can be allowed. + } + + mQuestAreaTriggerMap[trigger_ID] = quest_ID; + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u quest trigger points", count); +} + +void ObjectMgr::LoadTavernAreaTriggers() +{ + mTavernAreaTriggerSet.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id FROM areatrigger_tavern"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u tavern triggers", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 Trigger_ID = fields[0].GetUInt32(); + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + if (!atEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); + continue; + } + + mTavernAreaTriggerSet.insert(Trigger_ID); + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u tavern triggers", count); +} + +void ObjectMgr::LoadAreaTriggerScripts() +{ + mAreaTriggerScripts.clear(); // need for reload case + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, ScriptName FROM areatrigger_scripts"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u areatrigger scripts", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 Trigger_ID = fields[0].GetUInt32(); + const char *scriptName = fields[1].GetString(); + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + if (!atEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); + continue; + } + mAreaTriggerScripts[Trigger_ID] = GetScriptId(scriptName); + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u areatrigger scripts", count); +} + +uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team) +{ + bool found = false; + float dist = 10000; + uint32 id = 0; + + for (uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) + { + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); + + if (!node || node->map_id != mapid || !node->MountCreatureID[team == ALLIANCE ? 1 : 0] && node->MountCreatureID[0] != 32981) // dk flight + continue; + + uint8 field = (uint8)((i - 1) / 32); + uint32 submask = 1<<((i-1)%32); + + // skip not taxi network nodes + if ((sTaxiNodesMask[field] & submask) == 0) + continue; + + float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z); + if (found) + { + if (dist2 < dist) + { + dist = dist2; + id = i; + } + } + else + { + found = true; + dist = dist2; + id = i; + } + } + + return id; +} + +void ObjectMgr::GetTaxiPath(uint32 source, uint32 destination, uint32 &path, uint32 &cost) +{ + TaxiPathSetBySource::iterator src_i = sTaxiPathSetBySource.find(source); + if (src_i == sTaxiPathSetBySource.end()) + { + path = 0; + cost = 0; + return; + } + + TaxiPathSetForSource& pathSet = src_i->second; + + TaxiPathSetForSource::iterator dest_i = pathSet.find(destination); + if (dest_i == pathSet.end()) + { + path = 0; + cost = 0; + return; + } + + cost = dest_i->second.price; + path = dest_i->second.ID; +} + +uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt_team /* = false */) +{ + uint32 mount_entry = 0; + uint32 mount_id = 0; + + // select mount creature id + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id); + if (node) + { + if (team == ALLIANCE) + mount_entry = node->MountCreatureID[1]; + else + mount_entry = node->MountCreatureID[0]; + + // Fix for Alliance not being able to use Acherus taxi + // only one mount type for both sides + if (mount_entry == 0 && allowed_alt_team) + { + // Simply reverse the selection. At least one team in theory should have a valid mount ID to choose. + mount_entry = team == ALLIANCE ? node->MountCreatureID[0] : node->MountCreatureID[1]; + } + + CreatureInfo const *mount_info = GetCreatureTemplate(mount_entry); + if (mount_info) + { + mount_id = mount_info->GetRandomValidModelId(); + if (!mount_id) + { + sLog.outErrorDb("No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry); + return false; + } + } + } + + CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(mount_id); + if (minfo) + mount_id = minfo->modelid; + + return mount_id; +} + +void ObjectMgr::GetTaxiPathNodes(uint32 path, Path &pathnodes, std::vector& mapIds) +{ + if (path >= sTaxiPathNodesByPath.size()) + return; + + TaxiPathNodeList& nodeList = sTaxiPathNodesByPath[path]; + + pathnodes.Resize(nodeList.size()); + mapIds.resize(nodeList.size()); + + for (size_t i = 0; i < nodeList.size(); ++i) + { + pathnodes[ i ].x = nodeList[i].x; + pathnodes[ i ].y = nodeList[i].y; + pathnodes[ i ].z = nodeList[i].z; + + mapIds[i] = nodeList[i].mapid; + } +} + +void ObjectMgr::GetTransportPathNodes(uint32 path, TransportPath &pathnodes) +{ + if (path >= sTaxiPathNodesByPath.size()) + return; + + TaxiPathNodeList& nodeList = sTaxiPathNodesByPath[path]; + + pathnodes.Resize(nodeList.size()); + + for (size_t i = 0; i < nodeList.size(); ++i) + { + pathnodes[ i ].mapid = nodeList[i].mapid; + pathnodes[ i ].x = nodeList[i].x; + pathnodes[ i ].y = nodeList[i].y; + pathnodes[ i ].z = nodeList[i].z; + pathnodes[ i ].actionFlag = nodeList[i].actionFlag; + pathnodes[ i ].delay = nodeList[i].delay; + } +} + +void ObjectMgr::LoadGraveyardZones() +{ + mGraveYardMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id,ghost_zone,faction FROM game_graveyard_zone"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u graveyard-zone links", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 safeLocId = fields[0].GetUInt32(); + uint32 zoneId = fields[1].GetUInt32(); + uint32 team = fields[2].GetUInt32(); + + WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(safeLocId); + if (!entry) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.",safeLocId); + continue; + } + + AreaTableEntry const *areaEntry = GetAreaEntryByAreaID(zoneId); + if (!areaEntry) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing zone id (%u), skipped.",zoneId); + continue; + } + + if (areaEntry->zone != 0) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record subzone id (%u) instead of zone, skipped.",zoneId); + continue; + } + + if (team != 0 && team != HORDE && team != ALLIANCE) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for non player faction (%u), skipped.",team); + continue; + } + + if (!AddGraveYardLink(safeLocId,zoneId,team,false)) + sLog.outErrorDb("Table `game_graveyard_zone` has a duplicate record for Graveyard (ID: %u) and Zone (ID: %u), skipped.",safeLocId,zoneId); + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u graveyard-zone links", count); +} + +WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team) +{ + // search for zone associated closest graveyard + uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y,z); + + // Simulate std. algorithm: + // found some graveyard associated to (ghost_zone,ghost_map) + // + // if mapId == graveyard.mapId (ghost in plain zone or city or battleground) and search graveyard at same map + // then check faction + // if mapId != graveyard.mapId (ghost in instance) and search any graveyard associated + // then check faction + GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId); + GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId); + MapEntry const* map = sMapStore.LookupEntry(MapId); + // not need to check validity of map object; MapId _MUST_ be valid here + + if (graveLow == graveUp && !map->IsBattleArena()) + { + //sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team); + return NULL; + } + + // at corpse map + bool foundNear = false; + float distNear = 10000; + WorldSafeLocsEntry const* entryNear = NULL; + + // at entrance map for corpse map + bool foundEntr = false; + float distEntr = 10000; + WorldSafeLocsEntry const* entryEntr = NULL; + + // some where other + WorldSafeLocsEntry const* entryFar = NULL; + + MapEntry const* mapEntry = sMapStore.LookupEntry(MapId); + + for (GraveYardMap::const_iterator itr = graveLow; itr != graveUp; ++itr) + { + GraveYardData const& data = itr->second; + + WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(data.safeLocId); + if (!entry) + { + sLog.outErrorDb("Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.",data.safeLocId); + continue; + } + + // skip enemy faction graveyard + // team == 0 case can be at call from .neargrave + if (data.team != 0 && team != 0 && data.team != team) + continue; + + // find now nearest graveyard at other map + if (MapId != entry->map_id) + { + // if find graveyard at different map from where entrance placed (or no entrance data), use any first + if (!mapEntry || + mapEntry->entrance_map < 0 || + uint32(mapEntry->entrance_map) != entry->map_id || + (mapEntry->entrance_x == 0 && mapEntry->entrance_y == 0)) + { + // not have any corrdinates for check distance anyway + entryFar = entry; + continue; + } + + // at entrance map calculate distance (2D); + float dist2 = (entry->x - mapEntry->entrance_x)*(entry->x - mapEntry->entrance_x) + +(entry->y - mapEntry->entrance_y)*(entry->y - mapEntry->entrance_y); + if (foundEntr) + { + if (dist2 < distEntr) + { + distEntr = dist2; + entryEntr = entry; + } + } + else + { + foundEntr = true; + distEntr = dist2; + entryEntr = entry; + } + } + // find now nearest graveyard at same map + else + { + float dist2 = (entry->x - x)*(entry->x - x)+(entry->y - y)*(entry->y - y)+(entry->z - z)*(entry->z - z); + if (foundNear) + { + if (dist2 < distNear) + { + distNear = dist2; + entryNear = entry; + } + } + else + { + foundNear = true; + distNear = dist2; + entryNear = entry; + } + } + } + + if (entryNear) + return entryNear; + + if (entryEntr) + return entryEntr; + + return entryFar; +} + +GraveYardData const* ObjectMgr::FindGraveYardData(uint32 id, uint32 zoneId) +{ + GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId); + GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId); + + for (GraveYardMap::const_iterator itr = graveLow; itr != graveUp; ++itr) + { + if (itr->second.safeLocId == id) + return &itr->second; + } + + return NULL; +} + +bool ObjectMgr::AddGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool inDB) +{ + if (FindGraveYardData(id,zoneId)) + return false; + + // add link to loaded data + GraveYardData data; + data.safeLocId = id; + data.team = team; + + mGraveYardMap.insert(GraveYardMap::value_type(zoneId,data)); + + // add link to DB + if (inDB) + { + WorldDatabase.PExecuteLog("INSERT INTO game_graveyard_zone (id,ghost_zone,faction) " + "VALUES ('%u', '%u','%u')",id,zoneId,team); + } + + return true; +} + +void ObjectMgr::RemoveGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool inDB) +{ + GraveYardMap::iterator graveLow = mGraveYardMap.lower_bound(zoneId); + GraveYardMap::iterator graveUp = mGraveYardMap.upper_bound(zoneId); + if (graveLow == graveUp) + { + //sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team); + return; + } + + bool found = false; + + GraveYardMap::iterator itr; + + for (itr = graveLow; itr != graveUp; ++itr) + { + GraveYardData & data = itr->second; + + // skip not matching safezone id + if (data.safeLocId != id) + continue; + + // skip enemy faction graveyard at same map (normal area, city, or battleground) + // team == 0 case can be at call from .neargrave + if (data.team != 0 && team != 0 && data.team != team) + continue; + + found = true; + break; + } + + // no match, return + if (!found) + return; + + // remove from links + mGraveYardMap.erase(itr); + + // remove link from DB + if (inDB) + { + WorldDatabase.PExecute("DELETE FROM game_graveyard_zone WHERE id = '%u' AND ghost_zone = '%u' AND faction = '%u'",id,zoneId,team); + } + + return; +} + +void ObjectMgr::LoadAreaTriggerTeleports() +{ + mAreaTriggers.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 3 4 5 6 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, access_id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport"); + if (!result) + { + + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u area trigger teleport definitions", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + ++count; + + uint32 Trigger_ID = fields[0].GetUInt32(); + + AreaTrigger at; + + at.access_id = fields[1].GetUInt32(); + at.target_mapId = fields[2].GetUInt32(); + at.target_X = fields[3].GetFloat(); + at.target_Y = fields[4].GetFloat(); + at.target_Z = fields[5].GetFloat(); + at.target_Orientation = fields[6].GetFloat(); + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + if (!atEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID); + continue; + } + + MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId); + if (!mapEntry) + { + sLog.outErrorDb("Area trigger (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Trigger_ID,at.target_mapId); + continue; + } + + if (at.target_X == 0 && at.target_Y == 0 && at.target_Z == 0) + { + sLog.outErrorDb("Area trigger (ID:%u) target coordinates not provided.",Trigger_ID); + continue; + } + + mAreaTriggers[Trigger_ID] = at; + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u area trigger teleport definitions", count); +} + +void ObjectMgr::LoadAccessRequirements() +{ + mAccessRequirements.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, level_min, level_max, item, item2, heroic_key, heroic_key2, quest_done, quest_failed_text, heroic_quest_done, heroic_quest_failed_text, heroic_level_min, status FROM access_requirement"); + if (!result) + { + + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u access requirement definitions", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + ++count; + + uint32 requiremt_ID = fields[0].GetUInt32(); + + AccessRequirement ar; + + ar.levelMin = fields[1].GetUInt8(); + ar.levelMax = fields[2].GetUInt8(); + ar.heroicLevelMin = fields[11].GetUInt8(); + ar.item = fields[3].GetUInt32(); + ar.item2 = fields[4].GetUInt32(); + ar.heroicKey = fields[5].GetUInt32(); + ar.heroicKey2 = fields[6].GetUInt32(); + ar.quest = fields[7].GetUInt32(); + ar.questFailedText = fields[8].GetCppString(); + ar.heroicQuest = fields[9].GetUInt32(); + ar.heroicQuestFailedText = fields[10].GetCppString(); + ar.status = fields[12].GetUInt8(); + + if (ar.item) + { + ItemPrototype const *pProto = GetItemPrototype(ar.item); + if (!pProto) + { + sLog.outError("Key item %u does not exist for requirement %u, removing key requirement.", ar.item, requiremt_ID); + ar.item = 0; + } + } + + if (ar.item2) + { + ItemPrototype const *pProto = GetItemPrototype(ar.item2); + if (!pProto) + { + sLog.outError("Second item %u does not exist for requirement %u, removing key requirement.", ar.item2, requiremt_ID); + ar.item2 = 0; + } + } + + if (ar.heroicKey) + { + ItemPrototype const *pProto = GetItemPrototype(ar.heroicKey); + if (!pProto) + { + sLog.outError("Heroic key %u not exist for trigger %u, remove key requirement.", ar.heroicKey, requiremt_ID); + ar.heroicKey = 0; + } + } + + if (ar.heroicKey2) + { + ItemPrototype const *pProto = GetItemPrototype(ar.heroicKey2); + if (!pProto) + { + sLog.outError("Second heroic key %u not exist for trigger %u, remove key requirement.", ar.heroicKey2, requiremt_ID); + ar.heroicKey2 = 0; + } + } + + if (ar.heroicQuest) + { + QuestMap::iterator qReqItr = mQuestTemplates.find(ar.heroicQuest); + if (qReqItr == mQuestTemplates.end()) + { + sLog.outErrorDb("Required Heroic Quest %u not exist for trigger %u, remove heroic quest done requirement.",ar.heroicQuest,requiremt_ID); + ar.heroicQuest = 0; + } + } + + if (ar.quest) + { + QuestMap::iterator qReqItr = mQuestTemplates.find(ar.quest); + if (qReqItr == mQuestTemplates.end()) + { + sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",ar.quest,requiremt_ID); + ar.quest = 0; + } + } + + mAccessRequirements[requiremt_ID] = ar; + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u access requirement definitions", count); +} + +/* + * Searches for the areatrigger which teleports players out of the given map with instance_template.parent field support + */ +AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const +{ + bool useParentDbValue = false; + uint32 parentId = 0; + const MapEntry *mapEntry = sMapStore.LookupEntry(Map); + if (!mapEntry || mapEntry->entrance_map < 0) + return NULL; + + if (mapEntry->IsDungeon()) + { + const InstanceTemplate *iTemplate = objmgr.GetInstanceTemplate(Map); + + if (!iTemplate) + return NULL; + + parentId = iTemplate->parent; + useParentDbValue = true; + } + + uint32 entrance_map = uint32(mapEntry->entrance_map); + for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr) + if ((!useParentDbValue && itr->second.target_mapId == entrance_map) || (useParentDbValue && itr->second.target_mapId == parentId)) + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); + if (atEntry && atEntry->mapid == Map) + return &itr->second; + } + return NULL; +} + +/** + * Searches for the areatrigger which teleports players to the given map + */ +AreaTrigger const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const +{ + for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr) + { + if (itr->second.target_mapId == Map) + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); + if (atEntry) + return &itr->second; + } + } + return NULL; +} + +void ObjectMgr::SetHighestGuids() +{ + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(guid) FROM characters"); + if (result) + m_hiCharGuid = (*result)[0].GetUInt32()+1; + + result = WorldDatabase.Query("SELECT MAX(guid) FROM creature"); + if (result) + m_hiCreatureGuid = (*result)[0].GetUInt32()+1; + + result = CharacterDatabase.Query("SELECT MAX(guid) FROM item_instance"); + if (result) + m_hiItemGuid = (*result)[0].GetUInt32()+1; + + // Cleanup other tables from not existed guids ( >= m_hiItemGuid) + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", m_hiItemGuid); + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", m_hiItemGuid); + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", m_hiItemGuid); + CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", m_hiItemGuid); + + result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject"); + if (result) + m_hiGoGuid = (*result)[0].GetUInt32()+1; + + result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse"); + if (result) + m_auctionid = (*result)[0].GetUInt32()+1; + + result = CharacterDatabase.Query("SELECT MAX(id) FROM mail"); + if (result) + m_mailid = (*result)[0].GetUInt32()+1; + + result = CharacterDatabase.Query("SELECT MAX(guid) FROM corpse"); + if (result) + m_hiCorpseGuid = (*result)[0].GetUInt32()+1; + + result = CharacterDatabase.Query("SELECT MAX(arenateamid) FROM arena_team"); + if (result) + m_arenaTeamId = (*result)[0].GetUInt32()+1; + + result = CharacterDatabase.Query("SELECT MAX(setguid) FROM character_equipmentsets"); + if (result) + m_equipmentSetGuid = (*result)[0].GetUInt64()+1; + + result = CharacterDatabase.Query("SELECT MAX(guildid) FROM guild"); + if (result) + m_guildId = (*result)[0].GetUInt32()+1; + + result = CharacterDatabase.Query("SELECT MAX(guid) FROM groups"); + if (result) + m_hiGroupGuid = (*result)[0].GetUInt32()+1; +} + +uint32 ObjectMgr::GenerateArenaTeamId() +{ + if (m_arenaTeamId >= 0xFFFFFFFE) + { + sLog.outError("Arena team ids overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_arenaTeamId++; +} + +uint32 ObjectMgr::GenerateAuctionID() +{ + if (m_auctionid >= 0xFFFFFFFE) + { + sLog.outError("Auctions ids overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_auctionid++; +} + +uint64 ObjectMgr::GenerateEquipmentSetGuid() +{ + if (m_equipmentSetGuid >= 0xFFFFFFFFFFFFFFFEll) + { + sLog.outError("EquipmentSet guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_equipmentSetGuid++; +} + +uint32 ObjectMgr::GenerateGuildId() +{ + if (m_guildId >= 0xFFFFFFFE) + { + sLog.outError("Guild ids overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_guildId++; +} + +uint32 ObjectMgr::GenerateMailID() +{ + if (m_mailid >= 0xFFFFFFFE) + { + sLog.outError("Mail ids overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_mailid++; +} + +uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) +{ + switch(guidhigh) + { + case HIGHGUID_ITEM: + if (m_hiItemGuid >= 0xFFFFFFFE) + { + sLog.outError("Item guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiItemGuid++; + case HIGHGUID_UNIT: + if (m_hiCreatureGuid >= 0x00FFFFFE) + { + sLog.outError("Creature guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiCreatureGuid++; + case HIGHGUID_PET: + if (m_hiPetGuid >= 0x00FFFFFE) + { + sLog.outError("Pet guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiPetGuid++; + case HIGHGUID_VEHICLE: + if (m_hiVehicleGuid >= 0x00FFFFFF) + { + sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiVehicleGuid++; + case HIGHGUID_PLAYER: + if (m_hiCharGuid >= 0xFFFFFFFE) + { + sLog.outError("Players guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiCharGuid++; + case HIGHGUID_GAMEOBJECT: + if (m_hiGoGuid >= 0x00FFFFFE) + { + sLog.outError("Gameobject guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiGoGuid++; + case HIGHGUID_CORPSE: + if (m_hiCorpseGuid >= 0xFFFFFFFE) + { + sLog.outError("Corpse guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiCorpseGuid++; + case HIGHGUID_DYNAMICOBJECT: + if (m_hiDoGuid >= 0xFFFFFFFE) + { + sLog.outError("DynamicObject guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiDoGuid++; + case HIGHGUID_GROUP: + if (m_hiGroupGuid >= 0xFFFFFFFE) + { + sLog.outError("Group guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiGroupGuid++; + default: + ASSERT(0); + } + + ASSERT(0); + return 0; +} + +void ObjectMgr::LoadGameObjectLocales() +{ + mGameObjectLocaleMap.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry," + "name_loc1,name_loc2,name_loc3,name_loc4,name_loc5,name_loc6,name_loc7,name_loc8," + "castbarcaption_loc1,castbarcaption_loc2,castbarcaption_loc3,castbarcaption_loc4," + "castbarcaption_loc5,castbarcaption_loc6,castbarcaption_loc7,castbarcaption_loc8 FROM locales_gameobject"); + + if (!result) + return; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + GameObjectLocale& data = mGameObjectLocaleMap[entry]; + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[i].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.Name.size() <= idx) + data.Name.resize(idx+1); + + data.Name[idx] = str; + } + } + } + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[i+(MAX_LOCALE-1)].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + if (data.CastBarCaption.size() <= idx) + data.CastBarCaption.resize(idx+1); + + data.CastBarCaption[idx] = str; + } + } + } + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %lu gameobject locale strings", (unsigned long)mGameObjectLocaleMap.size()); +} + +struct SQLGameObjectLoader : public SQLStorageLoaderBase +{ + template + void convert_from_str(uint32 /*field_pos*/, char *src, D &dst) + { + dst = D(objmgr.GetScriptId(src)); + } +}; + +inline void CheckGOLockId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) +{ + if (sLockStore.LookupEntry(dataN)) + return; + + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but lock (Id: %u) not found.", + goInfo->id,goInfo->type,N,goInfo->door.lockId,goInfo->door.lockId); +} + +inline void CheckGOLinkedTrapId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) +{ + if (GameObjectInfo const* trapInfo = sGOStorage.LookupEntry(dataN)) + { + if (trapInfo->type != GAMEOBJECT_TYPE_TRAP) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.", + goInfo->id,goInfo->type,N,dataN,dataN,GAMEOBJECT_TYPE_TRAP); + } + /* disable check for while (too many error reports baout not existed in trap templates + else + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but trap GO (Entry %u) not exist in `gameobject_template`.", + goInfo->id,goInfo->type,N,dataN,dataN); + */ +} + +inline void CheckGOSpellId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) +{ + if (sSpellStore.LookupEntry(dataN)) + return; + + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but Spell (Entry %u) not exist.", + goInfo->id,goInfo->type,N,dataN,dataN); +} + +inline void CheckAndFixGOChairHeightId(GameObjectInfo const* goInfo,uint32 const& dataN,uint32 N) +{ + if (dataN <= (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR)) + return; + + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but correct chair height in range 0..%i.", + goInfo->id,goInfo->type,N,dataN,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR); + + // prevent client and server unexpected work + const_cast(dataN) = 0; +} + +inline void CheckGONoDamageImmuneId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) +{ + // 0/1 correct values + if (dataN <= 1) + return; + + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) noDamageImmune field value.", + goInfo->id,goInfo->type,N,dataN); +} + +inline void CheckGOConsumable(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) +{ + // 0/1 correct values + if (dataN <= 1) + return; + + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) consumable field value.", + goInfo->id,goInfo->type,N,dataN); +} + +void ObjectMgr::LoadGameobjectInfo() +{ + SQLGameObjectLoader loader; + loader.Load(sGOStorage); + + // some checks + for (uint32 id = 1; id < sGOStorage.MaxEntry; id++) + { + GameObjectInfo const* goInfo = sGOStorage.LookupEntry(id); + if (!goInfo) + continue; + + // some GO types have unused go template, check goInfo->displayId at GO spawn data loading or ignore + + switch(goInfo->type) + { + case GAMEOBJECT_TYPE_DOOR: //0 + { + if (goInfo->door.lockId) + CheckGOLockId(goInfo,goInfo->door.lockId,1); + CheckGONoDamageImmuneId(goInfo,goInfo->door.noDamageImmune,3); + break; + } + case GAMEOBJECT_TYPE_BUTTON: //1 + { + if (goInfo->button.lockId) + CheckGOLockId(goInfo,goInfo->button.lockId,1); + CheckGONoDamageImmuneId(goInfo,goInfo->button.noDamageImmune,4); + break; + } + case GAMEOBJECT_TYPE_QUESTGIVER: //2 + { + if (goInfo->questgiver.lockId) + CheckGOLockId(goInfo,goInfo->questgiver.lockId,0); + CheckGONoDamageImmuneId(goInfo,goInfo->questgiver.noDamageImmune,5); + break; + } + case GAMEOBJECT_TYPE_CHEST: //3 + { + if (goInfo->chest.lockId) + CheckGOLockId(goInfo,goInfo->chest.lockId,0); + + CheckGOConsumable(goInfo,goInfo->chest.consumable,3); + + if (goInfo->chest.linkedTrapId) // linked trap + CheckGOLinkedTrapId(goInfo,goInfo->chest.linkedTrapId,7); + break; + } + case GAMEOBJECT_TYPE_TRAP: //6 + { + if (goInfo->trap.lockId) + CheckGOLockId(goInfo,goInfo->trap.lockId,0); + /* disable check for while, too many not existed spells + if (goInfo->trap.spellId) // spell + CheckGOSpellId(goInfo,goInfo->trap.spellId,3); + */ + break; + } + case GAMEOBJECT_TYPE_CHAIR: //7 + CheckAndFixGOChairHeightId(goInfo,goInfo->chair.height,1); + break; + case GAMEOBJECT_TYPE_SPELL_FOCUS: //8 + { + if (goInfo->spellFocus.focusId) + { + if (!sSpellFocusObjectStore.LookupEntry(goInfo->spellFocus.focusId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but SpellFocus (Id: %u) not exist.", + id,goInfo->type,goInfo->spellFocus.focusId,goInfo->spellFocus.focusId); + } + + if (goInfo->spellFocus.linkedTrapId) // linked trap + CheckGOLinkedTrapId(goInfo,goInfo->spellFocus.linkedTrapId,2); + break; + } + case GAMEOBJECT_TYPE_GOOBER: //10 + { + if (goInfo->goober.lockId) + CheckGOLockId(goInfo,goInfo->goober.lockId,0); + + CheckGOConsumable(goInfo,goInfo->goober.consumable,3); + + if (goInfo->goober.pageId) // pageId + { + if (!sPageTextStore.LookupEntry(goInfo->goober.pageId)) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but PageText (Entry %u) not exist.", + id,goInfo->type,goInfo->goober.pageId,goInfo->goober.pageId); + } + /* disable check for while, too many not existed spells + if (goInfo->goober.spellId) // spell + CheckGOSpellId(goInfo,goInfo->goober.spellId,10); + */ + CheckGONoDamageImmuneId(goInfo,goInfo->goober.noDamageImmune,11); + if (goInfo->goober.linkedTrapId) // linked trap + CheckGOLinkedTrapId(goInfo,goInfo->goober.linkedTrapId,12); + break; + } + case GAMEOBJECT_TYPE_AREADAMAGE: //12 + { + if (goInfo->areadamage.lockId) + CheckGOLockId(goInfo,goInfo->areadamage.lockId,0); + break; + } + case GAMEOBJECT_TYPE_CAMERA: //13 + { + if (goInfo->camera.lockId) + CheckGOLockId(goInfo,goInfo->camera.lockId,0); + break; + } + case GAMEOBJECT_TYPE_MO_TRANSPORT: //15 + { + if (goInfo->moTransport.taxiPathId) + { + if (goInfo->moTransport.taxiPathId >= sTaxiPathNodesByPath.size() || sTaxiPathNodesByPath[goInfo->moTransport.taxiPathId].empty()) + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist.", + id,goInfo->type,goInfo->moTransport.taxiPathId,goInfo->moTransport.taxiPathId); + } + break; + } + case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18 + { + /* disable check for while, too many not existed spells + // always must have spell + CheckGOSpellId(goInfo,goInfo->summoningRitual.spellId,1); + */ + break; + } + case GAMEOBJECT_TYPE_SPELLCASTER: //22 + { + // always must have spell + CheckGOSpellId(goInfo,goInfo->spellcaster.spellId,0); + break; + } + case GAMEOBJECT_TYPE_FLAGSTAND: //24 + { + if (goInfo->flagstand.lockId) + CheckGOLockId(goInfo,goInfo->flagstand.lockId,0); + CheckGONoDamageImmuneId(goInfo,goInfo->flagstand.noDamageImmune,5); + break; + } + case GAMEOBJECT_TYPE_FISHINGHOLE: //25 + { + if (goInfo->fishinghole.lockId) + CheckGOLockId(goInfo,goInfo->fishinghole.lockId,4); + break; + } + case GAMEOBJECT_TYPE_FLAGDROP: //26 + { + if (goInfo->flagdrop.lockId) + CheckGOLockId(goInfo,goInfo->flagdrop.lockId,0); + CheckGONoDamageImmuneId(goInfo,goInfo->flagdrop.noDamageImmune,3); + break; + } + case GAMEOBJECT_TYPE_BARBER_CHAIR: //32 + CheckAndFixGOChairHeightId(goInfo,goInfo->barberChair.chairheight,0); + break; + } + } + + sLog.outString(">> Loaded %u game object templates", sGOStorage.RecordCount); + sLog.outString(); +} + +void ObjectMgr::LoadExplorationBaseXP() +{ + uint32 count = 0; + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT level,basexp FROM exploration_basexp"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u BaseXP definitions", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + uint8 level = fields[0].GetUInt8(); + uint32 basexp = fields[1].GetUInt32(); + mBaseXPTable[level] = basexp; + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u BaseXP definitions", count); +} + +uint32 ObjectMgr::GetBaseXP(uint8 level) +{ + return mBaseXPTable[level] ? mBaseXPTable[level] : 0; +} + +uint32 ObjectMgr::GetXPForLevel(uint8 level) +{ + if (level < mPlayerXPperLevel.size()) + return mPlayerXPperLevel[level]; + return 0; +} + +void ObjectMgr::LoadPetNames() +{ + uint32 count = 0; + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT word,entry,half FROM pet_name_generation"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u pet name parts", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + std::string word = fields[0].GetString(); + uint32 entry = fields[1].GetUInt32(); + bool half = fields[2].GetBool(); + if (half) + PetHalfName1[entry].push_back(word); + else + PetHalfName0[entry].push_back(word); + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u pet name parts", count); +} + +void ObjectMgr::LoadPetNumber() +{ + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(id) FROM character_pet"); + if (result) + { + Field *fields = result->Fetch(); + m_hiPetNumber = fields[0].GetUInt32()+1; + } + + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded the max pet number: %d", m_hiPetNumber-1); +} + +std::string ObjectMgr::GeneratePetName(uint32 entry) +{ + std::vector & list0 = PetHalfName0[entry]; + std::vector & list1 = PetHalfName1[entry]; + + if (list0.empty() || list1.empty()) + { + CreatureInfo const *cinfo = GetCreatureTemplate(entry); + char* petname = GetPetName(cinfo->family, sWorld.GetDefaultDbcLocale()); + if (!petname) + petname = cinfo->Name; + return std::string(petname); + } + + return *(list0.begin()+urand(0, list0.size()-1)) + *(list1.begin()+urand(0, list1.size()-1)); +} + +uint32 ObjectMgr::GeneratePetNumber() +{ + return ++m_hiPetNumber; +} + +void ObjectMgr::LoadCorpses() +{ + uint32 count = 0; + // 0 1 2 3 4 5 6 7 8 9 10 + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT position_x, position_y, position_z, orientation, map, data, time, corpse_type, instance, phaseMask, guid FROM corpse WHERE corpse_type <> 0"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u corpses", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + + uint32 guid = fields[result->GetFieldCount()-1].GetUInt32(); + + Corpse *corpse = new Corpse; + if (!corpse->LoadFromDB(guid,fields)) + { + delete corpse; + continue; + } + + ObjectAccessor::Instance().AddCorpse(corpse); + + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u corpses", count); +} + +void ObjectMgr::LoadReputationOnKill() +{ + uint32 count = 0; + + // 0 1 2 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT creature_id, RewOnKillRepFaction1, RewOnKillRepFaction2," + // 3 4 5 6 7 8 9 + "IsTeamAward1, MaxStanding1, RewOnKillRepValue1, IsTeamAward2, MaxStanding2, RewOnKillRepValue2, TeamDependent " + "FROM creature_onkill_reputation"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 creature_id = fields[0].GetUInt32(); + + ReputationOnKillEntry repOnKill; + repOnKill.repfaction1 = fields[1].GetUInt32(); + repOnKill.repfaction2 = fields[2].GetUInt32(); + repOnKill.is_teamaward1 = fields[3].GetBool(); + repOnKill.reputation_max_cap1 = fields[4].GetUInt32(); + repOnKill.repvalue1 = fields[5].GetInt32(); + repOnKill.is_teamaward2 = fields[6].GetBool(); + repOnKill.reputation_max_cap2 = fields[7].GetUInt32(); + repOnKill.repvalue2 = fields[8].GetInt32(); + repOnKill.team_dependent = fields[9].GetUInt8(); + + if (!GetCreatureTemplate(creature_id)) + { + sLog.outErrorDb("Table `creature_onkill_reputation` have data for not existed creature entry (%u), skipped",creature_id); + continue; + } + + if (repOnKill.repfaction1) + { + FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(repOnKill.repfaction1); + if (!factionEntry1) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`",repOnKill.repfaction1); + continue; + } + } + + if (repOnKill.repfaction2) + { + FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(repOnKill.repfaction2); + if (!factionEntry2) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`",repOnKill.repfaction2); + continue; + } + } + + mRepOnKill[creature_id] = repOnKill; + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u creature award reputation definitions", count); +} + +void ObjectMgr::LoadPointsOfInterest() +{ + uint32 count = 0; + + // 0 1 2 3 4 5 6 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, x, y, icon, flags, data, icon_name FROM points_of_interest"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 Points of Interest definitions. DB table `points_of_interest` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 point_id = fields[0].GetUInt32(); + + PointOfInterest POI; + POI.x = fields[1].GetFloat(); + POI.y = fields[2].GetFloat(); + POI.icon = fields[3].GetUInt32(); + POI.flags = fields[4].GetUInt32(); + POI.data = fields[5].GetUInt32(); + POI.icon_name = fields[6].GetCppString(); + + if (!Trinity::IsValidMapCoord(POI.x,POI.y)) + { + sLog.outErrorDb("Table `points_of_interest` (Entry: %u) have invalid coordinates (X: %f Y: %f), ignored.",point_id,POI.x,POI.y); + continue; + } + + mPointsOfInterest[point_id] = POI; + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u Points of Interest definitions", count); +} + +void ObjectMgr::LoadQuestPOI() +{ + uint32 count = 0; + + // 0 1 2 3 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT questId, id, objIndex, mapid, WorldMapAreaId, FloorId, unk3, unk4 FROM quest_poi order by questId"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 questId = fields[0].GetUInt32(); + uint32 id = fields[1].GetUInt32(); + int32 objIndex = fields[2].GetInt32(); + uint32 mapId = fields[3].GetUInt32(); + uint32 WorldMapAreaId = fields[4].GetUInt32(); + uint32 FloorId = fields[5].GetUInt32(); + uint32 unk3 = fields[6].GetUInt32(); + uint32 unk4 = fields[7].GetUInt32(); + + QuestPOI POI(id, objIndex, mapId, WorldMapAreaId, FloorId, unk3, unk4); + + QueryResult_AutoPtr points = WorldDatabase.PQuery("SELECT x, y FROM quest_poi_points WHERE questId='%u' AND id='%i'", questId, id); + + if (points) + { + do + { + Field *pointFields = points->Fetch(); + int32 x = pointFields[0].GetInt32(); + int32 y = pointFields[1].GetInt32(); + QuestPOIPoint point(x, y); + POI.points.push_back(point); + } while (points->NextRow()); + } + + mQuestPOIMap[questId].push_back(POI); + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u quest POI definitions", count); +} + +void ObjectMgr::LoadNPCSpellClickSpells() +{ + uint32 count = 0; + + mSpellClickInfoMap.clear(); + // 0 1 2 3 4 5 6 7 8 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags, aura_required, aura_forbidden, user_type FROM npc_spellclick_spells"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 npc_entry = fields[0].GetUInt32(); + CreatureInfo const* cInfo = GetCreatureTemplate(npc_entry); + if (!cInfo) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown creature_template %u. Skipping entry.", npc_entry); + continue; + } + + if (!(cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK)) + const_cast(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK; + + uint32 spellid = fields[1].GetUInt32(); + SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid); + if (!spellinfo) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown spellid %u. Skipping entry.", spellid); + continue; + } + + uint32 auraRequired = fields[6].GetUInt32(); + if (auraRequired) + { + SpellEntry const *aurReqInfo = sSpellStore.LookupEntry(auraRequired); + if (!aurReqInfo) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown aura required %u. Skipping entry.", auraRequired); + continue; + } + } + + uint32 auraForbidden = fields[7].GetUInt32(); + if (auraForbidden) + { + SpellEntry const *aurForInfo = sSpellStore.LookupEntry(auraForbidden); + if (!aurForInfo) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown aura forbidden %u. Skipping entry.", auraForbidden); + continue; + } + } + + uint32 quest_start = fields[2].GetUInt32(); + + // quest might be 0 to enable spellclick independent of any quest + if (quest_start) + { + if (mQuestTemplates.find(quest_start) == mQuestTemplates.end()) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown start quest %u. Skipping entry.", quest_start); + continue; + } + } + + bool quest_start_active = fields[3].GetBool(); + + uint32 quest_end = fields[4].GetUInt32(); + // quest might be 0 to enable spellclick active infinity after start quest + if (quest_end) + { + if (mQuestTemplates.find(quest_end) == mQuestTemplates.end()) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown end quest %u. Skipping entry.", quest_end); + continue; + } + } + + uint8 userType = fields[8].GetUInt8(); + if (userType >= SPELL_CLICK_USER_MAX) + sLog.outErrorDb("Table npc_spellclick_spells references unknown user type %u. Skipping entry.", uint32(userType)); + + uint8 castFlags = fields[5].GetUInt8(); + SpellClickInfo info; + info.spellId = spellid; + info.questStart = quest_start; + info.questStartCanActive = quest_start_active; + info.questEnd = quest_end; + info.castFlags = castFlags; + info.auraRequired = auraRequired; + info.auraForbidden = auraForbidden; + info.userType = SpellClickUserTypes(userType); + mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info)); + + // mark creature template as spell clickable + const_cast(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK; + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u spellclick definitions", count); +} + +void ObjectMgr::LoadWeatherZoneChances() +{ + uint32 count = 0; + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT zone, spring_rain_chance, spring_snow_chance, spring_storm_chance, summer_rain_chance, summer_snow_chance, summer_storm_chance, fall_rain_chance, fall_snow_chance, fall_storm_chance, winter_rain_chance, winter_snow_chance, winter_storm_chance FROM game_weather"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 weather definitions. DB table `game_weather` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 zone_id = fields[0].GetUInt32(); + + WeatherZoneChances& wzc = mWeatherZoneMap[zone_id]; + + for (uint8 season = 0; season < WEATHER_SEASONS; ++season) + { + wzc.data[season].rainChance = fields[season * (MAX_WEATHER_TYPE-1) + 1].GetUInt32(); + wzc.data[season].snowChance = fields[season * (MAX_WEATHER_TYPE-1) + 2].GetUInt32(); + wzc.data[season].stormChance = fields[season * (MAX_WEATHER_TYPE-1) + 3].GetUInt32(); + + if (wzc.data[season].rainChance > 100) + { + wzc.data[season].rainChance = 25; + sLog.outErrorDb("Weather for zone %u season %u has wrong rain chance > 100%%",zone_id,season); + } + + if (wzc.data[season].snowChance > 100) + { + wzc.data[season].snowChance = 25; + sLog.outErrorDb("Weather for zone %u season %u has wrong snow chance > 100%%",zone_id,season); + } + + if (wzc.data[season].stormChance > 100) + { + wzc.data[season].stormChance = 25; + sLog.outErrorDb("Weather for zone %u season %u has wrong storm chance > 100%%",zone_id,season); + } + } + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u weather definitions", count); +} + +void ObjectMgr::SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t) +{ + mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)] = t; + WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE guid = '%u' AND instance = '%u'", loguid, instance); + if (t) + WorldDatabase.PExecute("INSERT INTO creature_respawn VALUES ('%u', '" UI64FMTD "', '%u')", loguid, uint64(t), instance); +} + +void ObjectMgr::DeleteCreatureData(uint32 guid) +{ + // remove mapid*cellid -> guid_set map + CreatureData const* data = GetCreatureData(guid); + if (data) + RemoveCreatureFromGrid(guid, data); + + mCreatureDataMap.erase(guid); +} + +void ObjectMgr::SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t) +{ + mGORespawnTimes[MAKE_PAIR64(loguid,instance)] = t; + WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE guid = '%u' AND instance = '%u'", loguid, instance); + if (t) + WorldDatabase.PExecute("INSERT INTO gameobject_respawn VALUES ('%u', '" UI64FMTD "', '%u')", loguid, uint64(t), instance); +} + +void ObjectMgr::DeleteRespawnTimeForInstance(uint32 instance) +{ + RespawnTimes::iterator next; + + for (RespawnTimes::iterator itr = mGORespawnTimes.begin(); itr != mGORespawnTimes.end(); itr = next) + { + next = itr; + ++next; + + if (GUID_HIPART(itr->first) == instance) + mGORespawnTimes.erase(itr); + } + + for (RespawnTimes::iterator itr = mCreatureRespawnTimes.begin(); itr != mCreatureRespawnTimes.end(); itr = next) + { + next = itr; + ++next; + + if (GUID_HIPART(itr->first) == instance) + mCreatureRespawnTimes.erase(itr); + } + + WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'", instance); + WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'", instance); +} + +void ObjectMgr::DeleteGOData(uint32 guid) +{ + // remove mapid*cellid -> guid_set map + GameObjectData const* data = GetGOData(guid); + if (data) + RemoveGameobjectFromGrid(guid, data); + + mGameObjectDataMap.erase(guid); +} + +void ObjectMgr::AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance) +{ + // corpses are always added to spawn mode 0 and they are spawned by their instance id + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(mapid,0)][cellid]; + cell_guids.corpses[player_guid] = instance; +} + +void ObjectMgr::DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid) +{ + // corpses are always added to spawn mode 0 and they are spawned by their instance id + CellObjectGuids& cell_guids = mMapObjectGuids[MAKE_PAIR32(mapid,0)][cellid]; + cell_guids.corpses.erase(player_guid); +} + +void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map,char const* table) +{ + map.clear(); // need for reload case + + uint32 count = 0; + + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT id,quest FROM %s",table); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 quest relations from %s. DB table `%s` is empty.",table,table); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 id = fields[0].GetUInt32(); + uint32 quest = fields[1].GetUInt32(); + + if (mQuestTemplates.find(quest) == mQuestTemplates.end()) + { + sLog.outErrorDb("Table `%s: Quest %u listed for entry %u does not exist.",table,quest,id); + continue; + } + + map.insert(QuestRelations::value_type(id,quest)); + + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u quest relations from %s", count,table); +} + +void ObjectMgr::LoadGameobjectQuestRelations() +{ + LoadQuestRelationsHelper(mGOQuestRelations,"gameobject_questrelation"); + + for (QuestRelations::iterator itr = mGOQuestRelations.begin(); itr != mGOQuestRelations.end(); ++itr) + { + GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first); + if (!goInfo) + sLog.outErrorDb("Table `gameobject_questrelation` have data for not existed gameobject entry (%u) and existed quest %u",itr->first,itr->second); + else if (goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER) + sLog.outErrorDb("Table `gameobject_questrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER",itr->first,itr->second); + } +} + +void ObjectMgr::LoadGameobjectInvolvedRelations() +{ + LoadQuestRelationsHelper(mGOQuestInvolvedRelations,"gameobject_involvedrelation"); + + for (QuestRelations::iterator itr = mGOQuestInvolvedRelations.begin(); itr != mGOQuestInvolvedRelations.end(); ++itr) + { + GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first); + if (!goInfo) + sLog.outErrorDb("Table `gameobject_involvedrelation` have data for not existed gameobject entry (%u) and existed quest %u",itr->first,itr->second); + else if (goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER) + sLog.outErrorDb("Table `gameobject_involvedrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER",itr->first,itr->second); + } +} + +void ObjectMgr::LoadCreatureQuestRelations() +{ + LoadQuestRelationsHelper(mCreatureQuestRelations,"creature_questrelation"); + + for (QuestRelations::iterator itr = mCreatureQuestRelations.begin(); itr != mCreatureQuestRelations.end(); ++itr) + { + CreatureInfo const* cInfo = GetCreatureTemplate(itr->first); + if (!cInfo) + sLog.outErrorDb("Table `creature_questrelation` have data for not existed creature entry (%u) and existed quest %u",itr->first,itr->second); + else if (!(cInfo->npcflag & UNIT_NPC_FLAG_QUESTGIVER)) + sLog.outErrorDb("Table `creature_questrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER",itr->first,itr->second); + } +} + +void ObjectMgr::LoadCreatureInvolvedRelations() +{ + LoadQuestRelationsHelper(mCreatureQuestInvolvedRelations,"creature_involvedrelation"); + + for (QuestRelations::iterator itr = mCreatureQuestInvolvedRelations.begin(); itr != mCreatureQuestInvolvedRelations.end(); ++itr) + { + CreatureInfo const* cInfo = GetCreatureTemplate(itr->first); + if (!cInfo) + sLog.outErrorDb("Table `creature_involvedrelation` have data for not existed creature entry (%u) and existed quest %u",itr->first,itr->second); + else if (!(cInfo->npcflag & UNIT_NPC_FLAG_QUESTGIVER)) + sLog.outErrorDb("Table `creature_involvedrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER",itr->first,itr->second); + } +} + +void ObjectMgr::LoadReservedPlayersNames() +{ + m_ReservedNames.clear(); // need for reload case + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT name FROM reserved_name"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u reserved player names", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + Field* fields; + do + { + bar.step(); + fields = result->Fetch(); + std::string name= fields[0].GetCppString(); + + std::wstring wstr; + if (!Utf8toWStr (name,wstr)) + { + sLog.outError("Table `reserved_name` have invalid name: %s", name.c_str()); + continue; + } + + wstrToLower(wstr); + + m_ReservedNames.insert(wstr); + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u reserved player names", count); +} + +bool ObjectMgr::IsReservedName(const std::string& name) const +{ + std::wstring wstr; + if (!Utf8toWStr (name,wstr)) + return false; + + wstrToLower(wstr); + + return m_ReservedNames.find(wstr) != m_ReservedNames.end(); +} + +enum LanguageType +{ + LT_BASIC_LATIN = 0x0000, + LT_EXTENDEN_LATIN = 0x0001, + LT_CYRILLIC = 0x0002, + LT_EAST_ASIA = 0x0004, + LT_ANY = 0xFFFF +}; + +static LanguageType GetRealmLanguageType(bool create) +{ + switch(sWorld.getConfig(CONFIG_REALM_ZONE)) + { + case REALM_ZONE_UNKNOWN: // any language + case REALM_ZONE_DEVELOPMENT: + case REALM_ZONE_TEST_SERVER: + case REALM_ZONE_QA_SERVER: + return LT_ANY; + case REALM_ZONE_UNITED_STATES: // extended-Latin + case REALM_ZONE_OCEANIC: + case REALM_ZONE_LATIN_AMERICA: + case REALM_ZONE_ENGLISH: + case REALM_ZONE_GERMAN: + case REALM_ZONE_FRENCH: + case REALM_ZONE_SPANISH: + return LT_EXTENDEN_LATIN; + case REALM_ZONE_KOREA: // East-Asian + case REALM_ZONE_TAIWAN: + case REALM_ZONE_CHINA: + return LT_EAST_ASIA; + case REALM_ZONE_RUSSIAN: // Cyrillic + return LT_CYRILLIC; + default: + return create ? LT_BASIC_LATIN : LT_ANY; // basic-Latin at create, any at login + } +} + +bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bool create = false) +{ + if (strictMask == 0) // any language, ignore realm + { + if (isExtendedLatinString(wstr,numericOrSpace)) + return true; + if (isCyrillicString(wstr,numericOrSpace)) + return true; + if (isEastAsianString(wstr,numericOrSpace)) + return true; + return false; + } + + if (strictMask & 0x2) // realm zone specific + { + LanguageType lt = GetRealmLanguageType(create); + if (lt & LT_EXTENDEN_LATIN) + if (isExtendedLatinString(wstr,numericOrSpace)) + return true; + if (lt & LT_CYRILLIC) + if (isCyrillicString(wstr,numericOrSpace)) + return true; + if (lt & LT_EAST_ASIA) + if (isEastAsianString(wstr,numericOrSpace)) + return true; + } + + if (strictMask & 0x1) // basic Latin + { + if (isBasicLatinString(wstr,numericOrSpace)) + return true; + } + + return false; +} + +uint8 ObjectMgr::CheckPlayerName(const std::string& name, bool create) +{ + std::wstring wname; + if (!Utf8toWStr(name,wname)) + return CHAR_NAME_INVALID_CHARACTER; + + if (wname.size() > MAX_PLAYER_NAME) + return CHAR_NAME_TOO_LONG; + + uint32 minName = sWorld.getConfig(CONFIG_MIN_PLAYER_NAME); + if (wname.size() < minName) + return CHAR_NAME_TOO_SHORT; + + uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PLAYER_NAMES); + if (!isValidString(wname,strictMask,false,create)) + return CHAR_NAME_MIXED_LANGUAGES; + + return CHAR_NAME_SUCCESS; +} + +bool ObjectMgr::IsValidCharterName(const std::string& name) +{ + std::wstring wname; + if (!Utf8toWStr(name,wname)) + return false; + + if (wname.size() > MAX_CHARTER_NAME) + return false; + + uint32 minName = sWorld.getConfig(CONFIG_MIN_CHARTER_NAME); + if (wname.size() < minName) + return false; + + uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_CHARTER_NAMES); + + return isValidString(wname,strictMask,true); +} + +PetNameInvalidReason ObjectMgr::CheckPetName(const std::string& name) +{ + std::wstring wname; + if (!Utf8toWStr(name,wname)) + return PET_NAME_INVALID; + + if (wname.size() > MAX_PET_NAME) + return PET_NAME_TOO_LONG; + + uint32 minName = sWorld.getConfig(CONFIG_MIN_PET_NAME); + if (wname.size() < minName) + return PET_NAME_TOO_SHORT; + + uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PET_NAMES); + if (!isValidString(wname,strictMask,false)) + return PET_NAME_MIXED_LANGUAGES; + + return PET_NAME_SUCCESS; +} + +int ObjectMgr::GetIndexForLocale(LocaleConstant loc) +{ + if (loc == LOCALE_enUS) + return -1; + + for (size_t i=0; i < m_LocalForIndex.size(); ++i) + if (m_LocalForIndex[i] == loc) + return i; + + return -1; +} + +LocaleConstant ObjectMgr::GetLocaleForIndex(int i) +{ + if (i<0 || i >= m_LocalForIndex.size()) + return LOCALE_enUS; + + return m_LocalForIndex[i]; +} + +int ObjectMgr::GetOrNewIndexForLocale(LocaleConstant loc) +{ + if (loc == LOCALE_enUS) + return -1; + + for (size_t i=0; i < m_LocalForIndex.size(); ++i) + if (m_LocalForIndex[i] == loc) + return i; + + m_LocalForIndex.push_back(loc); + return m_LocalForIndex.size()-1; +} + +void ObjectMgr::LoadGameObjectForQuests() +{ + mGameObjectForQuestSet.clear(); // need for reload case + + if (!sGOStorage.MaxEntry) + { + barGoLink bar(1); + bar.step(); + sLog.outString(); + sLog.outString(">> Loaded 0 GameObjects for quests"); + return; + } + + barGoLink bar(sGOStorage.MaxEntry - 1); + uint32 count = 0; + + // collect GO entries for GO that must activated + for (uint32 go_entry = 1; go_entry < sGOStorage.MaxEntry; ++go_entry) + { + bar.step(); + GameObjectInfo const* goInfo = sGOStorage.LookupEntry(go_entry); + if (!goInfo) + continue; + + switch(goInfo->type) + { + // scan GO chest with loot including quest items + case GAMEOBJECT_TYPE_CHEST: + { + uint32 loot_id = goInfo->GetLootId(); + + // find quest loot for GO + if (LootTemplates_Gameobject.HaveQuestLootFor(loot_id)) + { + mGameObjectForQuestSet.insert(go_entry); + ++count; + } + break; + } + case GAMEOBJECT_TYPE_GOOBER: + { + if (goInfo->goober.questId) //quests objects + { + mGameObjectForQuestSet.insert(go_entry); + count++; + } + break; + } + default: + break; + } + } + + sLog.outString(); + sLog.outString(">> Loaded %u GameObjects for quests", count); +} + +bool ObjectMgr::LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value) +{ + int32 start_value = min_value; + int32 end_value = max_value; + // some string can have negative indexes range + if (start_value < 0) + { + if (end_value >= start_value) + { + sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded.",table,min_value,max_value); + return false; + } + + // real range (max+1,min+1) exaple: (-10,-1000) -> -999...-10+1 + std::swap(start_value,end_value); + ++start_value; + ++end_value; + } + else + { + if (start_value >= end_value) + { + sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded.",table,min_value,max_value); + return false; + } + } + + // cleanup affected map part for reloading case + for (TrinityStringLocaleMap::iterator itr = mTrinityStringLocaleMap.begin(); itr != mTrinityStringLocaleMap.end();) + { + if (itr->first >= start_value && itr->first < end_value) + mTrinityStringLocaleMap.erase(itr++); + else + ++itr; + } + + QueryResult_AutoPtr result = db.PQuery("SELECT entry,content_default,content_loc1,content_loc2,content_loc3,content_loc4,content_loc5,content_loc6,content_loc7,content_loc8 FROM %s",table); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + if (min_value == MIN_TRINITY_STRING_ID) // error only in case internal strings + sLog.outErrorDb(">> Loaded 0 trinity strings. DB table `%s` is empty. Cannot continue.",table); + else + sLog.outString(">> Loaded 0 string templates. DB table `%s` is empty.",table); + return false; + } + + uint32 count = 0; + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + int32 entry = fields[0].GetInt32(); + + if (entry == 0) + { + sLog.outErrorDb("Table `%s` contain reserved entry 0, ignored.",table); + continue; + } + else if (entry < start_value || entry >= end_value) + { + sLog.outErrorDb("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,min_value,max_value); + continue; + } + + TrinityStringLocale& data = mTrinityStringLocaleMap[entry]; + + if (data.Content.size() > 0) + { + sLog.outErrorDb("Table `%s` contain data for already loaded entry %i (from another table?), ignored.",table,entry); + continue; + } + + data.Content.resize(1); + ++count; + + // 0 -> default, idx in to idx+1 + data.Content[0] = fields[1].GetCppString(); + + for (uint8 i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[i+1].GetCppString(); + if (!str.empty()) + { + int idx = GetOrNewIndexForLocale(LocaleConstant(i)); + if (idx >= 0) + { + // 0 -> default, idx in to idx+1 + if (data.Content.size() <= idx+1) + data.Content.resize(idx+2); + + data.Content[idx+1] = str; + } + } + } + } while (result->NextRow()); + + sLog.outString(); + if (min_value == MIN_TRINITY_STRING_ID) + sLog.outString(">> Loaded %u Trinity strings from table %s", count,table); + else + sLog.outString(">> Loaded %u string templates from %s", count,table); + + return true; +} + +const char *ObjectMgr::GetTrinityString(int32 entry, int locale_idx) const +{ + // locale_idx == -1 -> default, locale_idx >= 0 in to idx+1 + // Content[0] always exist if exist TrinityStringLocale + if (TrinityStringLocale const *msl = GetTrinityStringLocale(entry)) + { + if (msl->Content.size() > locale_idx+1 && !msl->Content[locale_idx+1].empty()) + return msl->Content[locale_idx+1].c_str(); + else + return msl->Content[0].c_str(); + } + + if (entry > 0) + sLog.outErrorDb("Entry %i not found in `trinity_string` table.",entry); + else + sLog.outErrorDb("Trinity string entry %i not found in DB.",entry); + return ""; +} + +void ObjectMgr::LoadSpellDisabledEntrys() +{ + m_DisabledPlayerSpells.clear(); // need for reload case + m_DisabledCreatureSpells.clear(); + m_DisabledPetSpells.clear(); + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, disable_mask FROM spell_disabled"); + + uint32 total_count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u disabled spells", total_count); + return; + } + + barGoLink bar(result->GetRowCount()); + + Field* fields; + do + { + bar.step(); + fields = result->Fetch(); + uint32 spellid = fields[0].GetUInt32(); + if (!sSpellStore.LookupEntry(spellid)) + { + sLog.outErrorDb("Spell entry %u from `spell_disabled` doesn't exist in dbc, ignoring.",spellid); + continue; + } + uint32 disable_mask = fields[1].GetUInt32(); + if (disable_mask & SPELL_DISABLE_PLAYER) + m_DisabledPlayerSpells.insert(spellid); + if (disable_mask & SPELL_DISABLE_CREATURE) + m_DisabledCreatureSpells.insert(spellid); + if (disable_mask & SPELL_DISABLE_PET) + m_DisabledPetSpells.insert(spellid); + ++total_count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u disabled spells from `spell_disabled`", total_count); +} + +void ObjectMgr::LoadFishingBaseSkillLevel() +{ + mFishingBaseForArea.clear(); // for reload case + + uint32 count = 0; + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,skill FROM skill_fishing_base_level"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `skill_fishing_base_level`, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + uint32 entry = fields[0].GetUInt32(); + int32 skill = fields[1].GetInt32(); + + AreaTableEntry const* fArea = GetAreaEntryByAreaID(entry); + if (!fArea) + { + sLog.outErrorDb("AreaId %u defined in `skill_fishing_base_level` does not exist",entry); + continue; + } + + mFishingBaseForArea[entry] = skill; + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u areas for fishing base skill level", count); +} + +bool ObjectMgr::CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names) +{ + for (uint8 i =0; i < MAX_DECLINED_NAME_CASES; ++i) + { + std::wstring wname; + if (!Utf8toWStr(names.name[i],wname)) + return false; + + if (mainpart != GetMainPartOfName(wname,i+1)) + return false; + } + return true; +} + +uint32 ObjectMgr::GetAreaTriggerScriptId(uint32 trigger_id) +{ + AreaTriggerScriptMap::const_iterator i = mAreaTriggerScripts.find(trigger_id); + if (i!= mAreaTriggerScripts.end()) + return i->second; + return 0; +} + +SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial) +{ + switch(pSkill->categoryId) + { + case SKILL_CATEGORY_LANGUAGES: return SKILL_RANGE_LANGUAGE; + case SKILL_CATEGORY_WEAPON: + if (pSkill->id != SKILL_FIST_WEAPONS) + return SKILL_RANGE_LEVEL; + else + return SKILL_RANGE_MONO; + case SKILL_CATEGORY_ARMOR: + case SKILL_CATEGORY_CLASS: + if (pSkill->id != SKILL_LOCKPICKING) + return SKILL_RANGE_MONO; + else + return SKILL_RANGE_LEVEL; + case SKILL_CATEGORY_SECONDARY: + case SKILL_CATEGORY_PROFESSION: + // not set skills for professions and racial abilities + if (IsProfessionSkill(pSkill->id)) + return SKILL_RANGE_RANK; + else if (racial) + return SKILL_RANGE_NONE; + else + return SKILL_RANGE_MONO; + default: + case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc + case SKILL_CATEGORY_GENERIC: //only GENERIC(DND) + return SKILL_RANGE_NONE; + } +} + +void ObjectMgr::LoadGameTele() +{ + m_GameTeleMap.clear(); // for reload case + + uint32 count = 0; + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, map, name FROM game_tele"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `game_tele`, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + + uint32 id = fields[0].GetUInt32(); + + GameTele gt; + + gt.position_x = fields[1].GetFloat(); + gt.position_y = fields[2].GetFloat(); + gt.position_z = fields[3].GetFloat(); + gt.orientation = fields[4].GetFloat(); + gt.mapId = fields[5].GetUInt32(); + gt.name = fields[6].GetCppString(); + + if (!MapManager::IsValidMapCoord(gt.mapId,gt.position_x,gt.position_y,gt.position_z,gt.orientation)) + { + sLog.outErrorDb("Wrong position for id %u (name: %s) in `game_tele` table, ignoring.",id,gt.name.c_str()); + continue; + } + + if (!Utf8toWStr(gt.name,gt.wnameLow)) + { + sLog.outErrorDb("Wrong UTF8 name for id %u in `game_tele` table, ignoring.",id); + continue; + } + + wstrToLower(gt.wnameLow); + + m_GameTeleMap[id] = gt; + + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u GameTeleports", count); +} + +GameTele const* ObjectMgr::GetGameTele(const std::string& name) const +{ + // explicit name case + std::wstring wname; + if (!Utf8toWStr(name,wname)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wname); + + // Alternative first GameTele what contains wnameLow as substring in case no GameTele location found + const GameTele* alt = NULL; + for (GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) + { + if (itr->second.wnameLow == wname) + return &itr->second; + else if (alt == NULL && itr->second.wnameLow.find(wname) != std::wstring::npos) + alt = &itr->second; + } + + return alt; +} + +bool ObjectMgr::AddGameTele(GameTele& tele) +{ + // find max id + uint32 new_id = 0; + for (GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) + if (itr->first > new_id) + new_id = itr->first; + + // use next + ++new_id; + + if (!Utf8toWStr(tele.name,tele.wnameLow)) + return false; + + wstrToLower(tele.wnameLow); + + m_GameTeleMap[new_id] = tele; + + return WorldDatabase.PExecuteLog("INSERT INTO game_tele (id,position_x,position_y,position_z,orientation,map,name) VALUES (%u,%f,%f,%f,%f,%d,'%s')", + new_id,tele.position_x,tele.position_y,tele.position_z,tele.orientation,tele.mapId,tele.name.c_str()); +} + +bool ObjectMgr::DeleteGameTele(const std::string& name) +{ + // explicit name case + std::wstring wname; + if (!Utf8toWStr(name,wname)) + return false; + + // converting string that we try to find to lower case + wstrToLower(wname); + + for (GameTeleMap::iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) + { + if (itr->second.wnameLow == wname) + { + WorldDatabase.PExecuteLog("DELETE FROM game_tele WHERE name = '%s'",itr->second.name.c_str()); + m_GameTeleMap.erase(itr); + return true; + } + } + + return false; +} + +void ObjectMgr::LoadMailLevelRewards() +{ + m_mailLevelRewardMap.clear(); // for reload case + + uint32 count = 0; + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT level, raceMask, mailTemplateId, senderEntry FROM mail_level_reward"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `mail_level_reward`, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + + uint8 level = fields[0].GetUInt8(); + uint32 raceMask = fields[1].GetUInt32(); + uint32 mailTemplateId = fields[2].GetUInt32(); + uint32 senderEntry = fields[3].GetUInt32(); + + if (level > MAX_LEVEL) + { + sLog.outErrorDb("Table `mail_level_reward` have data for level %u that more supported by client (%u), ignoring.",level,MAX_LEVEL); + continue; + } + + if (!(raceMask & RACEMASK_ALL_PLAYABLE)) + { + sLog.outErrorDb("Table `mail_level_reward` have raceMask (%u) for level %u that not include any player races, ignoring.",raceMask,level); + continue; + } + + if (!sMailTemplateStore.LookupEntry(mailTemplateId)) + { + sLog.outErrorDb("Table `mail_level_reward` have invalid mailTemplateId (%u) for level %u that invalid not include any player races, ignoring.",mailTemplateId,level); + continue; + } + + if (!GetCreatureTemplateStore(senderEntry)) + { + sLog.outErrorDb("Table `mail_level_reward` have not existed sender creature entry (%u) for level %u that invalid not include any player races, ignoring.",senderEntry,level); + continue; + } + + m_mailLevelRewardMap[level].push_back(MailLevelReward(raceMask,mailTemplateId,senderEntry)); + + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u level dependent mail rewards,", count); +} + +bool ObjectMgr::AddSpellToTrainer(uint32 entry, uint32 spell, Field *fields, std::set *skip_trainers, std::set *talentIds) +{ + if (entry >= TRINITY_TRAINER_START_REF) + return false; + + CreatureInfo const* cInfo = GetCreatureTemplate(entry); + if (!cInfo) + { + sLog.outErrorDb("Table `npc_trainer` have entry for not existed creature template (Entry: %u), ignore", entry); + return false; + } + + if (!(cInfo->npcflag & UNIT_NPC_FLAG_TRAINER)) + { + if (skip_trainers->find(entry) == skip_trainers->end()) + { + sLog.outErrorDb("Table `npc_trainer` have data for not creature template (Entry: %u) without trainer flag, ignore", entry); + skip_trainers->insert(entry); + } + return false; + } + + SpellEntry const *spellinfo = sSpellStore.LookupEntry(spell); + if (!spellinfo) + { + sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u) has non existing spell %u, ignore", entry,spell); + return false; + } + + if (!SpellMgr::IsSpellValid(spellinfo)) + { + sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u) has broken learning spell %u, ignore", entry, spell); + return false; + } + + if (GetTalentSpellCost(spell)) + { + if (talentIds->count(spell) == 0) + { + sLog.outErrorDb("Table `npc_trainer` has talent as learning spell %u, ignore", spell); + talentIds->insert(spell); + } + return false; + } + + TrainerSpellData& data = m_mCacheTrainerSpellMap[entry]; + + TrainerSpell& trainerSpell = data.spellList[spell]; + trainerSpell.spell = spell; + trainerSpell.spellCost = fields[2].GetUInt32(); + trainerSpell.reqSkill = fields[3].GetUInt32(); + trainerSpell.reqSkillValue = fields[4].GetUInt32(); + trainerSpell.reqLevel = fields[5].GetUInt32(); + + if (!trainerSpell.reqLevel) + trainerSpell.reqLevel = spellinfo->spellLevel; + + // calculate learned spell for profession case when stored cast-spell + trainerSpell.learnedSpell[0] = spell; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (spellinfo->Effect[i] != SPELL_EFFECT_LEARN_SPELL) + continue; + if (trainerSpell.learnedSpell[0] == spell) + trainerSpell.learnedSpell[0] = 0; + // player must be able to cast spell on himself + if (spellinfo->EffectImplicitTargetA[i] != 0 && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_TARGET_ALLY + && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_TARGET_ANY && spellinfo->EffectImplicitTargetA[i] != TARGET_UNIT_CASTER) + { + sLog.outErrorDb("Table `npc_trainer` has spell %u for trainer entry %u with learn effect which has incorrect target type, ignoring learn effect!", spell, entry); + continue; + } + + trainerSpell.learnedSpell[i] = spellinfo->EffectTriggerSpell[i]; + } + + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (!trainerSpell.learnedSpell[i]) + continue; + if (SpellMgr::IsProfessionSpell(trainerSpell.learnedSpell[i])) + { + data.trainerType = 2; + break; + } + } + return true; +} +int ObjectMgr::LoadReferenceTrainer(uint32 trainer, int32 spell, std::set *skip_trainers, std::set *talentIds) +{ + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer WHERE entry='%d'", spell); + if (!result) + return 0; + + uint32 count = 0; + do + { + + Field* fields = result->Fetch(); + + int32 spell = fields[1].GetInt32(); + if (spell < 0) + count += this->LoadReferenceTrainer(trainer, -spell, skip_trainers, talentIds); + else if (this->AddSpellToTrainer(trainer, uint32(spell), fields, skip_trainers, talentIds)) + ++count; + } while (result->NextRow()); + + return count; +} + +void ObjectMgr::LoadTrainerSpell() +{ + // For reload case + for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr) + itr->second.Clear(); + m_mCacheTrainerSpellMap.clear(); + + std::set skip_trainers; + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `npc_trainer`, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + std::set talentIds; + + uint32 count = 0; + do + { + bar.step(); + + Field* fields = result->Fetch(); + + uint32 entry = fields[0].GetUInt32(); + int32 spell = fields[1].GetInt32(); + if (spell < 0) + count += this->LoadReferenceTrainer(entry, -spell, &skip_trainers, &talentIds); + else if (this->AddSpellToTrainer(entry, uint32(spell), fields, &skip_trainers, &talentIds)) + ++count; + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %d Trainers", count); +} + +int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set *skip_vendors) +{ + // find all items from the reference vendor + QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry='%d' ORDER BY slot ASC", item); + if (!result) + return 0; + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + int32 item_id = fields[0].GetInt32(); + + // if item is a negative, its a reference + if (item_id < 0) + count += LoadReferenceVendor(vendor, -item_id, skip_vendors); + else + { + int32 maxcount = fields[1].GetInt32(); + uint32 incrtime = fields[2].GetUInt32(); + uint32 ExtendedCost = fields[3].GetUInt32(); + + if (!IsVendorItemValid(vendor,item_id,maxcount,incrtime,ExtendedCost,NULL,skip_vendors)) + continue; + + VendorItemData& vList = m_mCacheVendorItemMap[vendor]; + + vList.AddItem(item_id,maxcount,incrtime,ExtendedCost); + ++count; + } + + } while (result->NextRow()); + + return count; +} + +void ObjectMgr::LoadVendors() +{ + // For reload case + for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) + itr->second.Clear(); + m_mCacheVendorItemMap.clear(); + + std::set skip_vendors; + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor ORDER BY entry, slot ASC"); + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `npc_vendor`, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + uint32 count = 0; + do + { + bar.step(); + Field* fields = result->Fetch(); + + uint32 entry = fields[0].GetUInt32(); + int32 item_id = fields[1].GetInt32(); + + // if item is a negative, its a reference + if (item_id < 0) + count += LoadReferenceVendor(entry, -item_id, &skip_vendors); + else + { + int32 maxcount = fields[2].GetInt32(); + uint32 incrtime = fields[3].GetUInt32(); + uint32 ExtendedCost = fields[4].GetUInt32(); + + if (!IsVendorItemValid(entry,item_id,maxcount,incrtime,ExtendedCost,NULL,&skip_vendors)) + continue; + + VendorItemData& vList = m_mCacheVendorItemMap[entry]; + + vList.AddItem(item_id,maxcount,incrtime,ExtendedCost); + ++count; + } + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %d Vendors ", count); +} + +void ObjectMgr::LoadNpcTextId() +{ + + m_mCacheNpcTextIdMap.clear(); + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT npc_guid, textid FROM npc_gossip"); + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `npc_gossip`, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + uint32 count = 0; + uint32 guid,textid; + do + { + bar.step(); + + Field* fields = result->Fetch(); + + guid = fields[0].GetUInt32(); + textid = fields[1].GetUInt32(); + + if (!GetCreatureData(guid)) + { + sLog.outErrorDb("Table `npc_gossip` have not existed creature (GUID: %u) entry, ignore. ",guid); + continue; + } + if (!GetGossipText(textid)) + { + sLog.outErrorDb("Table `npc_gossip` for creature (GUID: %u) have wrong Textid (%u), ignore. ", guid, textid); + continue; + } + + m_mCacheNpcTextIdMap[guid] = textid ; + ++count; + + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %d NpcTextId ", count); +} + +void ObjectMgr::LoadGossipMenu() +{ + m_mGossipMenusMap.clear(); + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, text_id FROM gossip_menu"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `gossip_menu`, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + uint32 count = 0; + + do + { + bar.step(); + + Field* fields = result->Fetch(); + + GossipMenus gMenu; + + gMenu.entry = fields[0].GetUInt32(); + gMenu.text_id = fields[1].GetUInt32(); + + if (!GetGossipText(gMenu.text_id)) + { + sLog.outErrorDb("Table gossip_menu entry %u are using non-existing text_id %u", gMenu.entry, gMenu.text_id); + continue; + } + + m_mGossipMenusMap.insert(GossipMenusMap::value_type(gMenu.entry, gMenu)); + + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u gossip_menu entries", count); +} + +void ObjectMgr::LoadGossipMenuItems() +{ + m_mGossipMenuItemsMap.clear(); + + QueryResult_AutoPtr result = WorldDatabase.Query( + "SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, " + "action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text " + "FROM gossip_menu_option"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded gossip_menu_option, table is empty!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + uint32 count = 0; + + std::set gossipScriptSet; + + for (ScriptMapMap::const_iterator itr = sGossipScripts.begin(); itr != sGossipScripts.end(); ++itr) + gossipScriptSet.insert(itr->first); + + do + { + bar.step(); + + Field* fields = result->Fetch(); + + GossipMenuItems gMenuItem; + + gMenuItem.menu_id = fields[0].GetUInt32(); + gMenuItem.id = fields[1].GetUInt32(); + gMenuItem.option_icon = fields[2].GetUInt8(); + gMenuItem.option_text = fields[3].GetCppString(); + gMenuItem.option_id = fields[4].GetUInt32(); + gMenuItem.npc_option_npcflag = fields[5].GetUInt32(); + gMenuItem.action_menu_id = fields[6].GetUInt32(); + gMenuItem.action_poi_id = fields[7].GetUInt32(); + gMenuItem.action_script_id = fields[8].GetUInt32(); + gMenuItem.box_coded = fields[9].GetUInt8() != 0; + gMenuItem.box_money = fields[10].GetUInt32(); + gMenuItem.box_text = fields[11].GetCppString(); + + if (gMenuItem.option_icon >= GOSSIP_ICON_MAX) + { + sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown icon id %u. Replacing with GOSSIP_ICON_CHAT", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_icon); + gMenuItem.option_icon = GOSSIP_ICON_CHAT; + } + + if (gMenuItem.option_id >= GOSSIP_OPTION_MAX) + sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown option id %u. Option will not be used", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_id); + + if (gMenuItem.action_poi_id && !GetPointOfInterest(gMenuItem.action_poi_id)) + { + sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u use non-existing action_poi_id %u, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_poi_id); + gMenuItem.action_poi_id = 0; + } + + if (gMenuItem.action_script_id) + { + if (gMenuItem.option_id != GOSSIP_OPTION_GOSSIP) + { + sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u but option_id is not GOSSIP_OPTION_GOSSIP, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id); + continue; + } + + if (sGossipScripts.find(gMenuItem.action_script_id) == sGossipScripts.end()) + { + sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u that does not exist in `gossip_scripts`, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id); + continue; + } + + gossipScriptSet.erase(gMenuItem.action_script_id); + } + + m_mGossipMenuItemsMap.insert(GossipMenuItemsMap::value_type(gMenuItem.menu_id, gMenuItem)); + + ++count; + + } + while (result->NextRow()); + + if (!gossipScriptSet.empty()) + { + for (std::set::const_iterator itr = gossipScriptSet.begin(); itr != gossipScriptSet.end(); ++itr) + sLog.outErrorDb("Table `gossip_scripts` contain unused script, id %u.", *itr); + } + + sLog.outString(); + sLog.outString(">> Loaded %u gossip_menu_option entries", count); +} + +void ObjectMgr::AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedcost, bool savetodb) +{ + VendorItemData& vList = m_mCacheVendorItemMap[entry]; + vList.AddItem(item,maxcount,incrtime,extendedcost); + + if (savetodb) WorldDatabase.PExecuteLog("INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')",entry, item, maxcount,incrtime,extendedcost); +} + +bool ObjectMgr::RemoveVendorItem(uint32 entry,uint32 item, bool savetodb) +{ + CacheVendorItemMap::iterator iter = m_mCacheVendorItemMap.find(entry); + if (iter == m_mCacheVendorItemMap.end()) + return false; + + if(!iter->second.RemoveItem(item)) + return false; + + if (savetodb) WorldDatabase.PExecuteLog("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",entry, item); + return true; +} + +bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* pl, std::set* skip_vendors, uint32 ORnpcflag) const +{ + CreatureInfo const* cInfo = GetCreatureTemplate(vendor_entry); + if (!cInfo) + { + if (pl) + ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION); + else + sLog.outErrorDb("Table `(game_event_)npc_vendor` have data for not existed creature template (Entry: %u), ignore", vendor_entry); + return false; + } + + if (!((cInfo->npcflag | ORnpcflag) & UNIT_NPC_FLAG_VENDOR)) + { + if (!skip_vendors || skip_vendors->count(vendor_entry) == 0) + { + if (pl) + ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION); + else + sLog.outErrorDb("Table `(game_event_)npc_vendor` have data for not creature template (Entry: %u) without vendor flag, ignore", vendor_entry); + + if (skip_vendors) + skip_vendors->insert(vendor_entry); + } + return false; + } + + if (!GetItemPrototype(item_id)) + { + if (pl) + ChatHandler(pl).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id); + else + sLog.outErrorDb("Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore",vendor_entry,item_id); + return false; + } + + if (ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost)) + { + if (pl) + ChatHandler(pl).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST,ExtendedCost); + else + sLog.outErrorDb("Table `(game_event_)npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore",item_id,ExtendedCost,vendor_entry); + return false; + } + + if (maxcount > 0 && incrtime == 0) + { + if (pl) + ChatHandler(pl).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount); + else + sLog.outErrorDb("Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", maxcount, item_id, vendor_entry); + return false; + } + else if (maxcount == 0 && incrtime > 0) + { + if (pl) + ChatHandler(pl).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0"); + else + sLog.outErrorDb("Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", item_id, vendor_entry); + return false; + } + + VendorItemData const* vItems = GetNpcVendorItemList(vendor_entry); + if (!vItems) + return true; // later checks for non-empty lists + + if(vItems->FindItemCostPair(item_id,ExtendedCost)) + { + if (pl) + ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost); + else + sLog.outErrorDb( "Table `npc_vendor` has duplicate items %u (with extended cost %u) for vendor (Entry: %u), ignoring", item_id, ExtendedCost, vendor_entry); + return false; + } + + if (vItems->GetItemCount() >= MAX_VENDOR_ITEMS) + { + if (pl) + ChatHandler(pl).SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS); + else + sLog.outErrorDb("Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignore", vItems->GetItemCount(), MAX_VENDOR_ITEMS, vendor_entry); + return false; + } + + return true; +} + +void ObjectMgr::LoadScriptNames() +{ + m_scriptNames.push_back(""); + QueryResult_AutoPtr result = WorldDatabase.Query( + "SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); + + if (!result) + { + barGoLink bar(1); + bar.step(); + sLog.outString(); + sLog.outErrorDb(">> Loaded empty set of Script Names!"); + return; + } + + barGoLink bar(result->GetRowCount()); + + //OnEvent Changes + m_scriptNames.push_back("scripted_on_events"); + uint32 count = 1; + + do + { + bar.step(); + m_scriptNames.push_back((*result)[0].GetString()); + ++count; + } while (result->NextRow()); + + std::sort(m_scriptNames.begin(), m_scriptNames.end()); + sLog.outString(); + sLog.outString(">> Loaded %d Script Names", count); +} + +uint32 ObjectMgr::GetScriptId(const char *name) +{ + // use binary search to find the script name in the sorted vector + // assume "" is the first element + if (!name) return 0; + ScriptNameMap::const_iterator itr = + std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name); + if (itr == m_scriptNames.end() || *itr != name) return 0; + return itr - m_scriptNames.begin(); +} + +void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set& ids) +{ + for (ScriptMapMap::const_iterator itrMM = scripts.begin(); itrMM != scripts.end(); ++itrMM) + { + for (ScriptMap::const_iterator itrM = itrMM->second.begin(); itrM != itrMM->second.end(); ++itrM) + { + switch(itrM->second.command) + { + case SCRIPT_COMMAND_TALK: + { + if (!GetTrinityStringLocale (itrM->second.dataint)) + sLog.outErrorDb("Table `db_script_string` not has string id %u used db script (ID: %u)", itrM->second.dataint, itrMM->first); + + if (ids.find(itrM->second.dataint) != ids.end()) + ids.erase(itrM->second.dataint); + } + } + } + } +} + +void ObjectMgr::LoadDbScriptStrings() +{ + LoadTrinityStrings(WorldDatabase,"db_script_string",MIN_DB_SCRIPT_STRING_ID,MAX_DB_SCRIPT_STRING_ID); + + std::set ids; + + for (int32 i = MIN_DB_SCRIPT_STRING_ID; i < MAX_DB_SCRIPT_STRING_ID; ++i) + if (GetTrinityStringLocale(i)) + ids.insert(i); + + CheckScripts(sQuestEndScripts,ids); + CheckScripts(sQuestStartScripts,ids); + CheckScripts(sSpellScripts,ids); + CheckScripts(sGameObjectScripts,ids); + CheckScripts(sEventScripts,ids); + + CheckScripts(sWaypointScripts,ids); + + for (std::set::const_iterator itr = ids.begin(); itr != ids.end(); ++itr) + sLog.outErrorDb("Table `db_script_string` has unused string id %u", *itr); +} + +// Functions for scripting access +uint32 GetAreaTriggerScriptId(uint32 trigger_id) +{ + return objmgr.GetAreaTriggerScriptId(trigger_id); +} + +bool LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value) +{ + // MAX_DB_SCRIPT_STRING_ID is max allowed negative value for scripts (scrpts can use only more deep negative values + // start/end reversed for negative values + if (start_value > MAX_DB_SCRIPT_STRING_ID || end_value >= start_value) + { + sLog.outErrorDb("Table '%s' load attempted with range (%d - %d) reserved by Trinity, strings not loaded.",table,start_value,end_value+1); + return false; + } + + return objmgr.LoadTrinityStrings(db,table,start_value,end_value); +} + +uint32 GetScriptId(const char *name) +{ + return objmgr.GetScriptId(name); +} + +ObjectMgr::ScriptNameMap & GetScriptNames() +{ + return objmgr.GetScriptNames(); +} + +GameObjectInfo const *GetGameObjectInfo(uint32 id) +{ + return objmgr.GetGameObjectInfo(id); +} + +CreatureInfo const *GetCreatureInfo(uint32 id) +{ + return objmgr.GetCreatureTemplate(id); +} + +void ObjectMgr::LoadTransportEvents() +{ + + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, waypoint_id, event_id FROM transport_events"); + + if (!result) + { + barGoLink bar1(1); + bar1.step(); + sLog.outString("\n>> Transport events table is empty \n"); + return; + } + + barGoLink bar1(result->GetRowCount()); + + do + { + bar1.step(); + + Field *fields = result->Fetch(); + + //Load event values + uint32 entry = fields[0].GetUInt32(); + uint32 waypoint_id = fields[1].GetUInt32(); + uint32 event_id = fields[2].GetUInt32(); + + uint32 event_count = (entry*100)+waypoint_id; + TransportEventMap[event_count] = event_id; + } + while (result->NextRow()); + + sLog.outString("\n>> Loaded %u transport events \n", result->GetRowCount()); +} + +CreatureInfo const* GetCreatureTemplateStore(uint32 entry) +{ + return sCreatureStorage.LookupEntry(entry); +} + +Quest const* GetQuestTemplateStore(uint32 entry) +{ + return objmgr.GetQuestTemplate(entry); +} + +uint64 ObjectMgr::GenerateGMTicketId() +{ + return ++m_GMticketid; +} + +void ObjectMgr::LoadGMTickets() +{ + if (!m_GMTicketList.empty()) + { + for (GmTicketList::const_iterator itr = m_GMTicketList.begin(); itr != m_GMTicketList.end(); ++itr) + delete *itr; + } + m_GMTicketList.clear(); + m_GMticketid = 0; + + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment FROM gm_tickets"); + + if (!result) + { + barGoLink bar(1); + bar.step(); + sLog.outString(); + sLog.outString(">> GM Tickets table is empty, no tickets were loaded."); + return; + } + + uint16 count = 0; + barGoLink bar ((*result).GetRowCount()); + GM_Ticket *ticket; + do + { + Field *fields = result->Fetch(); + ticket = new GM_Ticket; + ticket->guid = fields[0].GetUInt64(); + ticket->playerGuid = fields[1].GetUInt64(); + ticket->name = fields[2].GetCppString(); + ticket->message = fields[3].GetCppString(); + ticket->createtime = fields[4].GetUInt64(); + ticket->map = fields[5].GetUInt32(); + ticket->pos_x = fields[6].GetFloat(); + ticket->pos_y = fields[7].GetFloat(); + ticket->pos_z = fields[8].GetFloat(); + ticket->timestamp = fields[9].GetUInt64(); + ticket->closed = fields[10].GetUInt64(); + ticket->assignedToGM = fields[11].GetUInt64(); + ticket->comment = fields[12].GetCppString(); + ++count; + bar.step(); + + m_GMTicketList.push_back(ticket); + + } while (result->NextRow()); + + result = CharacterDatabase.Query("SELECT MAX(guid) from gm_tickets"); + + if (result) + { + Field *fields = result->Fetch(); + m_GMticketid = fields[0].GetUInt64(); + } + + sLog.outString(">> Loaded %u GM Tickets from the database.", count); +} + +void ObjectMgr::AddOrUpdateGMTicket(GM_Ticket &ticket, bool create) +{ + if (create) + m_GMTicketList.push_back(&ticket); + + _AddOrUpdateGMTicket(ticket); +} + +void ObjectMgr::_AddOrUpdateGMTicket(GM_Ticket &ticket) +{ + std::string msg(ticket.message), name(ticket.name), comment(ticket.comment); + CharacterDatabase.escape_string(msg); + CharacterDatabase.escape_string(name); + CharacterDatabase.escape_string(comment); + std::ostringstream ss; + ss << "REPLACE INTO gm_tickets (guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment) VALUES('"; + ss << ticket.guid << "', '"; + ss << ticket.playerGuid << "', '"; + ss << name << "', '"; + ss << msg << "', '" ; + ss << ticket.createtime << "', '"; + ss << ticket.map << "', '"; + ss << ticket.pos_x << "', '"; + ss << ticket.pos_y << "', '"; + ss << ticket.pos_z << "', '"; + ss << ticket.timestamp << "', '"; + ss << ticket.closed << "', '"; + ss << ticket.assignedToGM << "', '"; + ss << comment << "');"; + CharacterDatabase.BeginTransaction(); + CharacterDatabase.Execute(ss.str().c_str()); + CharacterDatabase.CommitTransaction(); +} + +void ObjectMgr::RemoveGMTicket(GM_Ticket *ticket, int64 source, bool permanently) +{ + for (GmTicketList::iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i) + if ((*i)->guid == ticket->guid) + { + if (permanently) + { + CharacterDatabase.PExecute("DELETE FROM gm_tickets WHERE guid = '%u'", ticket->guid); + i = m_GMTicketList.erase(i); + ticket = NULL; + return; + } + (*i)->closed = source; + _AddOrUpdateGMTicket(*(*i)); + } +} + +void ObjectMgr::RemoveGMTicket(uint64 ticketGuid, int64 source, bool permanently) +{ + GM_Ticket *ticket = GetGMTicket(ticketGuid); + assert(ticket); + RemoveGMTicket(ticket, source, permanently); +} + +CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unitClass) +{ + CreatureBaseStatsMap::const_iterator it = m_creatureBaseStatsMap.find(MAKE_PAIR16(level,unitClass)); + + if (it != m_creatureBaseStatsMap.end()) + return &(it->second); + + struct DefaultCreatureBaseStats : public CreatureBaseStats + { + DefaultCreatureBaseStats() + { + BaseArmor = 1; + for (uint8 j = 0; j < MAX_CREATURE_BASE_HP; ++j) + BaseHealth[j] = 1; + BaseMana = 0; + } + }; + static const DefaultCreatureBaseStats def_stats; + return &def_stats; +} + +void ObjectMgr::LoadCreatureClassLevelStats() +{ + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basemana, basearmor FROM creature_classlevelstats"); + + if (!result) + { + barGoLink bar(1); + bar.step(); + sLog.outString(); + sLog.outString(">> Loaded 0 creature base stats. DB table `creature_classlevelstats` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + uint32 counter = 0; + + do + { + Field *fields = result->Fetch(); + + uint8 Level = fields[0].GetUInt32(); + uint8 Class = fields[1].GetUInt8(); + + CreatureBaseStats stats; + for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i) + stats.BaseHealth[i] = fields[i + 2].GetUInt32(); + stats.BaseMana = fields[5].GetUInt32(); + stats.BaseArmor = fields[6].GetUInt32(); + + if (Level > STRONG_MAX_LEVEL) + { + sLog.outErrorDb("Creature base stats for class %u has invalid level %u (max is %u) - set to %u", + Class, Level, STRONG_MAX_LEVEL, STRONG_MAX_LEVEL); + Level = STRONG_MAX_LEVEL; + } + + if (!Class || ((1 << (Class - 1)) & CLASSMASK_ALL_CREATURES) == 0) + sLog.outErrorDb("Creature base stats for level %u has invalid class %u", + Level, Class); + + for (uint8 i = 0; i < MAX_CREATURE_BASE_HP; ++i) + { + if (stats.BaseHealth[i] < 1) + { + sLog.outErrorDb("Creature base stats for class %u, level %u has invalid zero base HP[%u] - set to 1", + Class, Level, i); + stats.BaseHealth[i] = 1; + } + } + + m_creatureBaseStatsMap[MAKE_PAIR16(Level, Class)] = stats; + + bar.step(); + ++counter; + } + while (result->NextRow()); + + for (uint32 i = 0; i < sCreatureStorage.MaxEntry; ++i) + { + CreatureInfo const* info = sCreatureStorage.LookupEntry(i); + if (!info) + continue; + + for (uint16 lvl = info->minlevel; lvl <= info->maxlevel; ++lvl) + { + if (m_creatureBaseStatsMap.find(MAKE_PAIR16(lvl, info->unit_class)) == m_creatureBaseStatsMap.end()) + sLog.outErrorDb("Missing base stats for creature class %u level %u", info->unit_class, lvl); + } + } + + sLog.outString(); + sLog.outString(">> Loaded %u creature base stats.", counter); +} diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h new file mode 100644 index 00000000000..79b6ffdd0eb --- /dev/null +++ b/src/server/game/Globals/ObjectMgr.h @@ -0,0 +1,1085 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _OBJECTMGR_H +#define _OBJECTMGR_H + +#include "Log.h" +#include "Object.h" +#include "Bag.h" +#include "Creature.h" +#include "Player.h" +#include "DynamicObject.h" +#include "GameObject.h" +#include "Corpse.h" +#include "QuestDef.h" +#include "Path.h" +#include "ItemPrototype.h" +#include "NPCHandler.h" +#include "Database/DatabaseEnv.h" +#include "Mail.h" +#include "Map.h" +#include "ObjectAccessor.h" +#include "ObjectDefines.h" +#include "Policies/Singleton.h" +#include "Database/SQLStorage.h" +#include "Vehicle.h" +#include "ObjectMgr.h" +#include +#include +#include +#include "ConditionMgr.h" + +extern SQLStorage sCreatureStorage; +extern SQLStorage sCreatureDataAddonStorage; +extern SQLStorage sCreatureInfoAddonStorage; +extern SQLStorage sCreatureModelStorage; +extern SQLStorage sEquipmentStorage; +extern SQLStorage sGOStorage; +extern SQLStorage sPageTextStore; +extern SQLStorage sItemStorage; +extern SQLStorage sInstanceTemplate; + +class Group; +class Guild; +class ArenaTeam; +class Path; +class TransportPath; +class Item; + +struct GameTele +{ + float position_x; + float position_y; + float position_z; + float orientation; + uint32 mapId; + std::string name; + std::wstring wnameLow; +}; + +typedef UNORDERED_MAP GameTeleMap; + +struct ScriptInfo +{ + uint32 id; + uint32 delay; + uint32 command; + uint32 datalong; + uint32 datalong2; + int32 dataint; + float x; + float y; + float z; + float o; +}; + +typedef std::multimap ScriptMap; +typedef std::map ScriptMapMap; +extern ScriptMapMap sQuestEndScripts; +extern ScriptMapMap sQuestStartScripts; +extern ScriptMapMap sSpellScripts; +extern ScriptMapMap sGameObjectScripts; +extern ScriptMapMap sEventScripts; +extern ScriptMapMap sGossipScripts; +extern ScriptMapMap sWaypointScripts; + +struct SpellClickInfo +{ + uint32 spellId; + uint32 questStart; // quest start (quest must be active or rewarded for spell apply) + uint32 questEnd; // quest end (quest don't must be rewarded for spell apply) + bool questStartCanActive; // if true then quest start can be active (not only rewarded) + uint8 castFlags; + uint32 auraRequired; + uint32 auraForbidden; + SpellClickUserTypes userType; + + // helpers + bool IsFitToRequirements(Player const* player, Creature const * clickNpc) const; +}; + +typedef std::multimap SpellClickInfoMap; +typedef std::pair SpellClickInfoMapBounds; + +struct AreaTrigger +{ + uint32 access_id; + uint32 target_mapId; + float target_X; + float target_Y; + float target_Z; + float target_Orientation; +}; + +typedef std::set CellGuidSet; +typedef std::map CellCorpseSet; +struct CellObjectGuids +{ + CellGuidSet creatures; + CellGuidSet gameobjects; + CellCorpseSet corpses; +}; +typedef UNORDERED_MAP CellObjectGuidsMap; +typedef UNORDERED_MAP MapObjectGuids; + +typedef UNORDERED_MAP RespawnTimes; + +// Trinity string ranges +#define MIN_TRINITY_STRING_ID 1 // 'trinity_string' +#define MAX_TRINITY_STRING_ID 2000000000 +#define MIN_DB_SCRIPT_STRING_ID MAX_TRINITY_STRING_ID // 'db_script_string' +#define MAX_DB_SCRIPT_STRING_ID 2000010000 +#define MIN_CREATURE_AI_TEXT_STRING_ID (-1) // 'creature_ai_texts' +#define MAX_CREATURE_AI_TEXT_STRING_ID (-1000000) + +// Trinity Trainer Reference start range +#define TRINITY_TRAINER_START_REF 200000 + +struct TrinityStringLocale +{ + std::vector Content; // 0 -> default, i -> i-1 locale index +}; + +typedef std::map CreatureLinkedRespawnMap; +typedef UNORDERED_MAP CreatureDataMap; +typedef UNORDERED_MAP GameObjectDataMap; +typedef UNORDERED_MAP CreatureLocaleMap; +typedef UNORDERED_MAP GameObjectLocaleMap; +typedef UNORDERED_MAP ItemLocaleMap; +typedef UNORDERED_MAP QuestLocaleMap; +typedef UNORDERED_MAP NpcTextLocaleMap; +typedef UNORDERED_MAP PageTextLocaleMap; +typedef UNORDERED_MAP TrinityStringLocaleMap; +typedef UNORDERED_MAP GossipMenuItemsLocaleMap; +typedef UNORDERED_MAP PointOfInterestLocaleMap; + +typedef std::multimap QuestRelations; +typedef std::multimap ItemRequiredTargetMap; +typedef std::pair ItemRequiredTargetMapBounds; + +struct PetLevelInfo +{ + PetLevelInfo() : health(0), mana(0) { for (uint8 i=0; i < MAX_STATS; ++i) stats[i] = 0; } + + uint16 stats[MAX_STATS]; + uint16 health; + uint16 mana; + uint16 armor; +}; + +struct MailLevelReward +{ + MailLevelReward() : raceMask(0), mailTemplateId(0), senderEntry(0) {} + MailLevelReward(uint32 _raceMask, uint32 _mailTemplateId, uint32 _senderEntry) : raceMask(_raceMask), mailTemplateId(_mailTemplateId), senderEntry(_senderEntry) {} + + uint32 raceMask; + uint32 mailTemplateId; + uint32 senderEntry; +}; + +typedef std::list MailLevelRewardList; +typedef UNORDERED_MAP MailLevelRewardMap; + +struct ReputationOnKillEntry +{ + uint32 repfaction1; + uint32 repfaction2; + bool is_teamaward1; + uint32 reputation_max_cap1; + int32 repvalue1; + bool is_teamaward2; + uint32 reputation_max_cap2; + int32 repvalue2; + bool team_dependent; +}; + +struct PointOfInterest +{ + uint32 entry; + float x; + float y; + uint32 icon; + uint32 flags; + uint32 data; + std::string icon_name; +}; + +struct GossipMenuItems +{ + uint32 menu_id; + uint32 id; + uint8 option_icon; + std::string option_text; + uint32 option_id; + uint32 npc_option_npcflag; + uint32 action_menu_id; + uint32 action_poi_id; + uint32 action_script_id; + bool box_coded; + uint32 box_money; + std::string box_text; + ConditionList conditions; +}; + +struct GossipMenus +{ + uint32 entry; + uint32 text_id; + ConditionList conditions; +}; + +typedef std::multimap GossipMenusMap; +typedef std::pair GossipMenusMapBounds; +typedef std::pair GossipMenusMapBoundsNonConst; +typedef std::multimap GossipMenuItemsMap; +typedef std::pair GossipMenuItemsMapBounds; +typedef std::pair GossipMenuItemsMapBoundsNonConst; + +struct QuestPOIPoint +{ + int32 x; + int32 y; + + QuestPOIPoint() : x(0), y(0) {} + QuestPOIPoint(int32 _x, int32 _y) : x(_x), y(_y) {} +}; + +struct QuestPOI +{ + uint32 Id; + int32 ObjectiveIndex; + uint32 MapId; + uint32 AreaId; + uint32 Unk2; + uint32 Unk3; + uint32 Unk4; + std::vector points; + + QuestPOI() : Id(0), ObjectiveIndex(0), MapId(0), AreaId(0), Unk2(0), Unk3(0), Unk4(0) {} + QuestPOI(uint32 id, int32 objIndex, uint32 mapId, uint32 areaId, uint32 unk2, uint32 unk3, uint32 unk4) : Id(id), ObjectiveIndex(objIndex), MapId(mapId), AreaId(areaId), Unk2(unk2), Unk3(unk3), Unk4(unk4) {} +}; + +typedef std::vector QuestPOIVector; +typedef UNORDERED_MAP QuestPOIMap; + +#define WEATHER_SEASONS 4 +struct WeatherSeasonChances +{ + uint32 rainChance; + uint32 snowChance; + uint32 stormChance; +}; + +struct WeatherZoneChances +{ + WeatherSeasonChances data[WEATHER_SEASONS]; +}; + +struct GraveYardData +{ + uint32 safeLocId; + uint32 team; +}; +typedef std::multimap GraveYardMap; + +// NPC gossip text id +typedef UNORDERED_MAP CacheNpcTextIdMap; + +typedef UNORDERED_MAP CacheVendorItemMap; +typedef UNORDERED_MAP CacheTrainerSpellMap; + +enum SkillRangeType +{ + SKILL_RANGE_LANGUAGE, // 300..300 + SKILL_RANGE_LEVEL, // 1..max skill for level + SKILL_RANGE_MONO, // 1..1, grey monolite bar + SKILL_RANGE_RANK, // 1..skill for known rank + SKILL_RANGE_NONE, // 0..0 always +}; + +struct GM_Ticket +{ + uint64 guid; + uint64 playerGuid; + std::string name; + float pos_x; + float pos_y; + float pos_z; + uint32 map; + std::string message; + uint64 createtime; + uint64 timestamp; + int64 closed; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket, other = GM who closed it. + uint64 assignedToGM; + std::string comment; +}; +typedef std::list GmTicketList; +SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial); + +#define MAX_PLAYER_NAME 12 // max allowed by client name length +#define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length (> MAX_PLAYER_NAME for support declined names) +#define MAX_PET_NAME 12 // max allowed by client name length +#define MAX_CHARTER_NAME 24 // max allowed by client name length + +bool normalizePlayerName(std::string& name); + +struct LanguageDesc +{ + Language lang_id; + uint32 spell_id; + uint32 skill_id; +}; + +extern LanguageDesc lang_description[LANGUAGES_COUNT]; + LanguageDesc const* GetLanguageDescByID(uint32 lang); + +class PlayerDumpReader; + +class ObjectMgr +{ + friend class PlayerDumpReader; + + public: + ObjectMgr(); + ~ObjectMgr(); + + typedef UNORDERED_MAP ItemMap; + + typedef std::set< Group * > GroupSet; + + typedef UNORDERED_MAP GuildMap; + + typedef UNORDERED_MAP ArenaTeamMap; + + typedef UNORDERED_MAP QuestMap; + + typedef UNORDERED_MAP AreaTriggerMap; + + typedef UNORDERED_MAP AreaTriggerScriptMap; + + typedef UNORDERED_MAP AccessRequirementMap; + + typedef UNORDERED_MAP RepOnKillMap; + typedef UNORDERED_MAP PointOfInterestMap; + + typedef UNORDERED_MAP WeatherZoneMap; + + typedef std::vector ScriptNameMap; + + UNORDERED_MAP TransportEventMap; + + Player* GetPlayer(const char* name) const { return ObjectAccessor::Instance().FindPlayerByName(name);} + Player* GetPlayer(uint64 guid) const { return ObjectAccessor::FindPlayer(guid); } + + static GameObjectInfo const *GetGameObjectInfo(uint32 id) { return sGOStorage.LookupEntry(id); } + int LoadReferenceVendor(int32 vendor, int32 item_id, std::set *skip_vendors); + + void LoadGameobjectInfo(); + void AddGameobjectInfo(GameObjectInfo *goinfo); + + Group * GetGroupByGUID(const uint64 &guid) const; + void AddGroup(Group* group) { mGroupSet.insert(group); } + void RemoveGroup(Group* group) { mGroupSet.erase(group); } + + Guild* GetGuildByLeader(uint64 const&guid) const; + Guild* GetGuildById(uint32 GuildId) const; + Guild* GetGuildByName(const std::string& guildname) const; + std::string GetGuildNameById(uint32 GuildId) const; + void AddGuild(Guild* guild); + void RemoveGuild(uint32 Id); + + ArenaTeam* GetArenaTeamById(uint32 arenateamid) const; + ArenaTeam* GetArenaTeamByName(const std::string& arenateamname) const; + ArenaTeam* GetArenaTeamByCaptain(uint64 const& guid) const; + void AddArenaTeam(ArenaTeam* arenaTeam); + void RemoveArenaTeam(uint32 Id); + ArenaTeamMap::iterator GetArenaTeamMapBegin() { return mArenaTeamMap.begin(); } + ArenaTeamMap::iterator GetArenaTeamMapEnd() { return mArenaTeamMap.end(); } + + static CreatureInfo const *GetCreatureTemplate(uint32 id); + CreatureModelInfo const *GetCreatureModelInfo(uint32 modelid); + CreatureModelInfo const* GetCreatureModelRandomGender(uint32 display_id); + uint32 ChooseDisplayId(uint32 team, const CreatureInfo *cinfo, const CreatureData *data = NULL); + EquipmentInfo const *GetEquipmentInfo(uint32 entry); + static CreatureDataAddon const *GetCreatureAddon(uint32 lowguid) + { + return sCreatureDataAddonStorage.LookupEntry(lowguid); + } + + static CreatureDataAddon const *GetCreatureTemplateAddon(uint32 entry) + { + return sCreatureInfoAddonStorage.LookupEntry(entry); + } + + static ItemPrototype const* GetItemPrototype(uint32 id) { return sItemStorage.LookupEntry(id); } + + static InstanceTemplate const* GetInstanceTemplate(uint32 map) + { + return sInstanceTemplate.LookupEntry(map); + } + + PetLevelInfo const* GetPetLevelInfo(uint32 creature_id, uint8 level) const; + + PlayerClassInfo const* GetPlayerClassInfo(uint32 class_) const + { + if (class_ >= MAX_CLASSES) return NULL; + return &playerClassInfo[class_]; + } + void GetPlayerClassLevelInfo(uint32 class_,uint8 level, PlayerClassLevelInfo* info) const; + + PlayerInfo const* GetPlayerInfo(uint32 race, uint32 class_) const + { + if (race >= MAX_RACES) return NULL; + if (class_ >= MAX_CLASSES) return NULL; + PlayerInfo const* info = &playerInfo[race][class_]; + if (info->displayId_m == 0 || info->displayId_f == 0) return NULL; + return info; + } + void GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const; + + uint64 GetPlayerGUIDByName(std::string name) const; + bool GetPlayerNameByGUID(const uint64 &guid, std::string &name) const; + uint32 GetPlayerTeamByGUID(const uint64 &guid) const; + uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const; + uint32 GetPlayerAccountIdByPlayerName(const std::string& name) const; + + uint32 GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team); + void GetTaxiPath(uint32 source, uint32 destination, uint32 &path, uint32 &cost); + uint32 GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt_team = false); + void GetTaxiPathNodes(uint32 path, Path &pathnodes, std::vector& mapIds); + void GetTransportPathNodes(uint32 path, TransportPath &pathnodes); + + Quest const* GetQuestTemplate(uint32 quest_id) const + { + QuestMap::const_iterator itr = mQuestTemplates.find(quest_id); + return itr != mQuestTemplates.end() ? itr->second : NULL; + } + QuestMap const& GetQuestTemplates() const { return mQuestTemplates; } + + uint32 GetQuestForAreaTrigger(uint32 Trigger_ID) const + { + QuestAreaTriggerMap::const_iterator itr = mQuestAreaTriggerMap.find(Trigger_ID); + if (itr != mQuestAreaTriggerMap.end()) + return itr->second; + return 0; + } + bool IsTavernAreaTrigger(uint32 Trigger_ID) const + { + return mTavernAreaTriggerSet.find(Trigger_ID) != mTavernAreaTriggerSet.end(); + } + + bool IsGameObjectForQuests(uint32 entry) const + { + return mGameObjectForQuestSet.find(entry) != mGameObjectForQuestSet.end(); + } + + GossipText const* GetGossipText(uint32 Text_ID) const; + + WorldSafeLocsEntry const *GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team); + bool AddGraveYardLink(uint32 id, uint32 zone, uint32 team, bool inDB = true); + void RemoveGraveYardLink(uint32 id, uint32 zone, uint32 team, bool inDB = false); + void LoadGraveyardZones(); + GraveYardData const* FindGraveYardData(uint32 id, uint32 zone); + + AreaTrigger const* GetAreaTrigger(uint32 trigger) const + { + AreaTriggerMap::const_iterator itr = mAreaTriggers.find(trigger); + if (itr != mAreaTriggers.end()) + return &itr->second; + return NULL; + } + + AccessRequirement const* GetAccessRequirement(uint32 requirement) const + { + AccessRequirementMap::const_iterator itr = mAccessRequirements.find(requirement); + if (itr != mAccessRequirements.end()) + return &itr->second; + return NULL; + } + + AreaTrigger const* GetGoBackTrigger(uint32 Map) const; + AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const; + + uint32 GetAreaTriggerScriptId(uint32 trigger_id); + + ReputationOnKillEntry const* GetReputationOnKilEntry(uint32 id) const + { + RepOnKillMap::const_iterator itr = mRepOnKill.find(id); + if (itr != mRepOnKill.end()) + return &itr->second; + return NULL; + } + + PointOfInterest const* GetPointOfInterest(uint32 id) const + { + PointOfInterestMap::const_iterator itr = mPointsOfInterest.find(id); + if (itr != mPointsOfInterest.end()) + return &itr->second; + return NULL; + } + + QuestPOIVector const* GetQuestPOIVector(uint32 questId) + { + QuestPOIMap::const_iterator itr = mQuestPOIMap.find(questId); + if (itr != mQuestPOIMap.end()) + return &itr->second; + return NULL; + } + + VehicleAccessoryList const* GetVehicleAccessoryList(uint32 uiEntry) const + { + VehicleAccessoryMap::const_iterator itr = m_VehicleAccessoryMap.find(uiEntry); + if (itr != m_VehicleAccessoryMap.end()) + return &itr->second; + return NULL; + } + + void LoadGuilds(); + void LoadArenaTeams(); + void LoadGroups(); + void LoadQuests(); + void LoadQuestRelations() + { + sLog.outString("Loading GO Start Quest Data..."); + LoadGameobjectQuestRelations(); + sLog.outString("Loading GO End Quest Data..."); + LoadGameobjectInvolvedRelations(); + sLog.outString("Loading Creature Start Quest Data..."); + LoadCreatureQuestRelations(); + sLog.outString("Loading Creature End Quest Data..."); + LoadCreatureInvolvedRelations(); + } + void LoadGameobjectQuestRelations(); + void LoadGameobjectInvolvedRelations(); + void LoadCreatureQuestRelations(); + void LoadCreatureInvolvedRelations(); + + QuestRelations mGOQuestRelations; + QuestRelations mGOQuestInvolvedRelations; + QuestRelations mCreatureQuestRelations; + QuestRelations mCreatureQuestInvolvedRelations; + + void LoadGameObjectScripts(); + void LoadQuestEndScripts(); + void LoadQuestStartScripts(); + void LoadEventScripts(); + void LoadSpellScripts(); + void LoadGossipScripts(); + void LoadWaypointScripts(); + + void LoadTransportEvents(); + + bool LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value); + bool LoadTrinityStrings() { return LoadTrinityStrings(WorldDatabase,"trinity_string",MIN_TRINITY_STRING_ID,MAX_TRINITY_STRING_ID); } + void LoadDbScriptStrings(); + void LoadCreatureClassLevelStats(); + void LoadCreatureLocales(); + void LoadCreatureTemplates(); + void CheckCreatureTemplate(CreatureInfo const* cInfo); + void LoadCreatures(); + void LoadCreatureLinkedRespawn(); + bool CheckCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) const; + bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid); + void LoadCreatureRespawnTimes(); + void LoadCreatureAddons(); + void LoadCreatureModelInfo(); + void LoadEquipmentTemplates(); + void LoadGameObjectLocales(); + void LoadGameobjects(); + void LoadGameobjectRespawnTimes(); + void LoadItemPrototypes(); + void LoadItemLocales(); + void LoadQuestLocales(); + void LoadNpcTextLocales(); + void LoadPageTextLocales(); + void LoadGossipMenuItemsLocales(); + void LoadPointOfInterestLocales(); + void LoadInstanceTemplate(); + void LoadMailLevelRewards(); + void LoadVehicleAccessories(); + + void LoadGossipText(); + + void LoadAreaTriggerTeleports(); + void LoadAccessRequirements(); + void LoadQuestAreaTriggers(); + void LoadAreaTriggerScripts(); + void LoadTavernAreaTriggers(); + void LoadGameObjectForQuests(); + + void LoadPageTexts(); + + void LoadPlayerInfo(); + void LoadPetLevelInfo(); + void LoadExplorationBaseXP(); + void LoadPetNames(); + void LoadPetNumber(); + void LoadCorpses(); + void LoadFishingBaseSkillLevel(); + + void LoadReputationOnKill(); + void LoadPointsOfInterest(); + void LoadQuestPOI(); + + void LoadNPCSpellClickSpells(); + + void LoadWeatherZoneChances(); + void LoadGameTele(); + + void LoadNpcTextId(); + + void LoadGossipMenu(); + void LoadGossipMenuItems(); + + void LoadVendors(); + void LoadTrainerSpell(); + bool AddSpellToTrainer(uint32 entry, uint32 spell, Field *fields, std::set *skip_trainers, std::set *talentIds); + int LoadReferenceTrainer(uint32 trainer, int32 spell, std::set *skip_trainers, std::set *talentIds); + void LoadGMTickets(); + + std::string GeneratePetName(uint32 entry); + uint32 GetBaseXP(uint8 level); + uint32 GetXPForLevel(uint8 level); + + int32 GetFishingBaseSkillLevel(uint32 entry) const + { + FishingBaseSkillMap::const_iterator itr = mFishingBaseForArea.find(entry); + return itr != mFishingBaseForArea.end() ? itr->second : 0; + } + + void ReturnOrDeleteOldMails(bool serverUp); + + CreatureBaseStats const* GetCreatureBaseStats(uint8 level, uint8 unitClass); + + void SetHighestGuids(); + uint32 GenerateLowGuid(HighGuid guidhigh); + uint32 GenerateArenaTeamId(); + uint32 GenerateAuctionID(); + uint64 GenerateEquipmentSetGuid(); + uint32 GenerateGuildId(); + uint32 GenerateMailID(); + uint32 GeneratePetNumber(); + + typedef std::multimap ExclusiveQuestGroups; + ExclusiveQuestGroups mExclusiveQuestGroups; + + MailLevelReward const* GetMailLevelReward(uint32 level,uint32 raceMask) + { + MailLevelRewardMap::const_iterator map_itr = m_mailLevelRewardMap.find(level); + if (map_itr == m_mailLevelRewardMap.end()) + return NULL; + + for (MailLevelRewardList::const_iterator set_itr = map_itr->second.begin(); set_itr != map_itr->second.end(); ++set_itr) + if (set_itr->raceMask & raceMask) + return &*set_itr; + + return NULL; + } + + WeatherZoneChances const* GetWeatherChances(uint32 zone_id) const + { + WeatherZoneMap::const_iterator itr = mWeatherZoneMap.find(zone_id); + if (itr != mWeatherZoneMap.end()) + return &itr->second; + else + return NULL; + } + + CellObjectGuids const& GetCellObjectGuids(uint16 mapid, uint8 spawnMode, uint32 cell_id) + { + return mMapObjectGuids[MAKE_PAIR32(mapid,spawnMode)][cell_id]; + } + + CreatureData const* GetCreatureData(uint32 guid) const + { + CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid); + if (itr == mCreatureDataMap.end()) return NULL; + return &itr->second; + } + CreatureData& NewOrExistCreatureData(uint32 guid) { return mCreatureDataMap[guid]; } + void DeleteCreatureData(uint32 guid); + uint32 GetLinkedRespawnGuid(uint32 guid) const + { + CreatureLinkedRespawnMap::const_iterator itr = mCreatureLinkedRespawnMap.find(guid); + if (itr == mCreatureLinkedRespawnMap.end()) return 0; + return itr->second; + } + CreatureLocale const* GetCreatureLocale(uint32 entry) const + { + CreatureLocaleMap::const_iterator itr = mCreatureLocaleMap.find(entry); + if (itr == mCreatureLocaleMap.end()) return NULL; + return &itr->second; + } + GameObjectLocale const* GetGameObjectLocale(uint32 entry) const + { + GameObjectLocaleMap::const_iterator itr = mGameObjectLocaleMap.find(entry); + if (itr == mGameObjectLocaleMap.end()) return NULL; + return &itr->second; + } + ItemLocale const* GetItemLocale(uint32 entry) const + { + ItemLocaleMap::const_iterator itr = mItemLocaleMap.find(entry); + if (itr == mItemLocaleMap.end()) return NULL; + return &itr->second; + } + QuestLocale const* GetQuestLocale(uint32 entry) const + { + QuestLocaleMap::const_iterator itr = mQuestLocaleMap.find(entry); + if (itr == mQuestLocaleMap.end()) return NULL; + return &itr->second; + } + NpcTextLocale const* GetNpcTextLocale(uint32 entry) const + { + NpcTextLocaleMap::const_iterator itr = mNpcTextLocaleMap.find(entry); + if (itr == mNpcTextLocaleMap.end()) return NULL; + return &itr->second; + } + PageTextLocale const* GetPageTextLocale(uint32 entry) const + { + PageTextLocaleMap::const_iterator itr = mPageTextLocaleMap.find(entry); + if (itr == mPageTextLocaleMap.end()) return NULL; + return &itr->second; + } + GossipMenuItemsLocale const* GetGossipMenuItemsLocale(uint32 entry) const + { + GossipMenuItemsLocaleMap::const_iterator itr = mGossipMenuItemsLocaleMap.find(entry); + if (itr == mGossipMenuItemsLocaleMap.end()) return NULL; + return &itr->second; + } + PointOfInterestLocale const* GetPointOfInterestLocale(uint32 poi_id) const + { + PointOfInterestLocaleMap::const_iterator itr = mPointOfInterestLocaleMap.find(poi_id); + if (itr == mPointOfInterestLocaleMap.end()) return NULL; + return &itr->second; + } + + bool IsGoOfSpecificEntrySpawned(uint32 entry) const + { + for (GameObjectDataMap::const_iterator it = mGameObjectDataMap.begin(); it != mGameObjectDataMap.end(); ++it) + if (it->second.id == entry) + return true; + + return false; + } + + GameObjectData const* GetGOData(uint32 guid) const + { + GameObjectDataMap::const_iterator itr = mGameObjectDataMap.find(guid); + if (itr == mGameObjectDataMap.end()) return NULL; + return &itr->second; + } + GameObjectData& NewGOData(uint32 guid) { return mGameObjectDataMap[guid]; } + void DeleteGOData(uint32 guid); + + TrinityStringLocale const* GetTrinityStringLocale(int32 entry) const + { + TrinityStringLocaleMap::const_iterator itr = mTrinityStringLocaleMap.find(entry); + if (itr == mTrinityStringLocaleMap.end()) return NULL; + return &itr->second; + } + const char *GetTrinityString(int32 entry, int locale_idx) const; + const char *GetTrinityStringForDBCLocale(int32 entry) const { return GetTrinityString(entry,DBCLocaleIndex); } + int32 GetDBCLocaleIndex() const { return DBCLocaleIndex; } + void SetDBCLocaleIndex(uint32 lang) { DBCLocaleIndex = GetIndexForLocale(LocaleConstant(lang)); } + + void AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance); + void DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid); + + time_t GetCreatureRespawnTime(uint32 loguid, uint32 instance) { return mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)]; } + void SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t); + time_t GetGORespawnTime(uint32 loguid, uint32 instance) { return mGORespawnTimes[MAKE_PAIR64(loguid,instance)]; } + void SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t); + void DeleteRespawnTimeForInstance(uint32 instance); + + // grid objects + void AddCreatureToGrid(uint32 guid, CreatureData const* data); + void RemoveCreatureFromGrid(uint32 guid, CreatureData const* data); + void AddGameobjectToGrid(uint32 guid, GameObjectData const* data); + void RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data); + uint32 AddGOData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0, float rotation0 = 0, float rotation1 = 0, float rotation2 = 0, float rotation3 = 0); + uint32 AddCreData(uint32 entry, uint32 team, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0); + bool MoveCreData(uint32 guid, uint32 map, Position pos); + + // reserved names + void LoadReservedPlayersNames(); + bool IsReservedName(const std::string& name) const; + + // name with valid structure and symbols + static uint8 CheckPlayerName(const std::string& name, bool create = false); + static PetNameInvalidReason CheckPetName(const std::string& name); + static bool IsValidCharterName(const std::string& name); + + static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names); + + void LoadSpellDisabledEntrys(); + bool IsPlayerSpellDisabled(uint32 spellid) { return (m_DisabledPlayerSpells.count(spellid) != 0); } + bool IsCreatureSpellDisabled(uint32 spellid) { return (m_DisabledCreatureSpells.count(spellid) != 0); } + bool IsPetSpellDisabled(uint32 spellid) { return (m_DisabledPetSpells.count(spellid) != 0); } + + int GetIndexForLocale(LocaleConstant loc); + LocaleConstant GetLocaleForIndex(int i); + + GameTele const* GetGameTele(uint32 id) const + { + GameTeleMap::const_iterator itr = m_GameTeleMap.find(id); + if (itr == m_GameTeleMap.end()) return NULL; + return &itr->second; + } + GameTele const* GetGameTele(const std::string& name) const; + GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; } + bool AddGameTele(GameTele& data); + bool DeleteGameTele(const std::string& name); + + uint32 GetNpcGossip(uint32 entry) const + { + CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry); + if (iter == m_mCacheNpcTextIdMap.end()) + return 0; + + return iter->second; + } + + TrainerSpellData const* GetNpcTrainerSpells(uint32 entry) const + { + CacheTrainerSpellMap::const_iterator iter = m_mCacheTrainerSpellMap.find(entry); + if (iter == m_mCacheTrainerSpellMap.end()) + return NULL; + + return &iter->second; + } + + VendorItemData const* GetNpcVendorItemList(uint32 entry) const + { + CacheVendorItemMap::const_iterator iter = m_mCacheVendorItemMap.find(entry); + if (iter == m_mCacheVendorItemMap.end()) + return NULL; + + return &iter->second; + } + void AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, bool savetodb = true); // for event + bool RemoveVendorItem(uint32 entry,uint32 item, bool savetodb = true); // for event + bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set* skip_vendors = NULL, uint32 ORnpcflag = 0) const; + + void LoadScriptNames(); + ScriptNameMap &GetScriptNames() { return m_scriptNames; } + const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; } + uint32 GetScriptId(const char *name); + + int GetOrNewIndexForLocale(LocaleConstant loc); + + SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const + { + return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id),mSpellClickInfoMap.upper_bound(creature_id)); + } + + GM_Ticket *GetGMTicket(uint64 ticketGuid) + { + for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i) + if ((*i) && (*i)->guid == ticketGuid) + return (*i); + + return NULL; + } + GM_Ticket *GetGMTicketByPlayer(uint64 playerGuid) + { + for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i) + if ((*i) && (*i)->playerGuid == playerGuid && (*i)->closed == 0) + return (*i); + + return NULL; + } + + GossipMenusMapBounds GetGossipMenusMapBounds(uint32 uiMenuId) const + { + return GossipMenusMapBounds(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId)); + } + + GossipMenusMapBoundsNonConst GetGossipMenusMapBoundsNonConst(uint32 uiMenuId) + { + return GossipMenusMapBoundsNonConst(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId)); + } + + GossipMenuItemsMapBounds GetGossipMenuItemsMapBounds(uint32 uiMenuId) const + { + return GossipMenuItemsMapBounds(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId)); + } + GossipMenuItemsMapBoundsNonConst GetGossipMenuItemsMapBoundsNonConst(uint32 uiMenuId) + { + return GossipMenuItemsMapBoundsNonConst(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId)); + } + + void AddOrUpdateGMTicket(GM_Ticket &ticket, bool create = false); + void _AddOrUpdateGMTicket(GM_Ticket &ticket); + void RemoveGMTicket(uint64 ticketGuid, int64 source = -1, bool permanently = false); + void RemoveGMTicket(GM_Ticket *ticket, int64 source = -1, bool permanently = false); + GmTicketList m_GMTicketList; + uint64 GenerateGMTicketId(); + + // for wintergrasp only + GraveYardMap mGraveYardMap; + protected: + + // first free id for selected id type + uint32 m_arenaTeamId; + uint32 m_auctionid; + uint64 m_equipmentSetGuid; + uint32 m_guildId; + uint32 m_ItemTextId; + uint32 m_mailid; + uint32 m_hiPetNumber; + uint64 m_GMticketid; + + // first free low guid for seelcted guid type + uint32 m_hiCharGuid; + uint32 m_hiCreatureGuid; + uint32 m_hiPetGuid; + uint32 m_hiVehicleGuid; + uint32 m_hiItemGuid; + uint32 m_hiGoGuid; + uint32 m_hiDoGuid; + uint32 m_hiCorpseGuid; + uint32 m_hiGroupGuid; + + QuestMap mQuestTemplates; + + typedef UNORDERED_MAP GossipTextMap; + typedef UNORDERED_MAP QuestAreaTriggerMap; + typedef std::set TavernAreaTriggerSet; + typedef std::set GameObjectForQuestSet; + + GroupSet mGroupSet; + GuildMap mGuildMap; + ArenaTeamMap mArenaTeamMap; + + QuestAreaTriggerMap mQuestAreaTriggerMap; + TavernAreaTriggerSet mTavernAreaTriggerSet; + GameObjectForQuestSet mGameObjectForQuestSet; + GossipTextMap mGossipText; + AreaTriggerMap mAreaTriggers; + AreaTriggerScriptMap mAreaTriggerScripts; + AccessRequirementMap mAccessRequirements; + + RepOnKillMap mRepOnKill; + + GossipMenusMap m_mGossipMenusMap; + GossipMenuItemsMap m_mGossipMenuItemsMap; + PointOfInterestMap mPointsOfInterest; + + QuestPOIMap mQuestPOIMap; + + WeatherZoneMap mWeatherZoneMap; + + //character reserved names + typedef std::set ReservedNamesMap; + ReservedNamesMap m_ReservedNames; + + std::set m_DisabledPlayerSpells; + std::set m_DisabledCreatureSpells; + std::set m_DisabledPetSpells; + +// GraveYardMap mGraveYardMap; + + GameTeleMap m_GameTeleMap; + + ScriptNameMap m_scriptNames; + + SpellClickInfoMap mSpellClickInfoMap; + + ItemRequiredTargetMap m_ItemRequiredTarget; + + VehicleAccessoryMap m_VehicleAccessoryMap; + + typedef std::vector LocalForIndex; + LocalForIndex m_LocalForIndex; + + int DBCLocaleIndex; + + private: + void LoadScripts(ScriptMapMap& scripts, char const* tablename); + void CheckScripts(ScriptMapMap const& scripts,std::set& ids); + void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment); + void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); + void LoadQuestRelationsHelper(QuestRelations& map,char const* table); + + MailLevelRewardMap m_mailLevelRewardMap; + + CreatureBaseStatsMap m_creatureBaseStatsMap; + + typedef std::map PetLevelInfoMap; + // PetLevelInfoMap[creature_id][level] + PetLevelInfoMap petInfo; // [creature_id][level] + + PlayerClassInfo playerClassInfo[MAX_CLASSES]; + + void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const; + PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES]; + + typedef std::vector PlayerXPperLevel; // [level] + PlayerXPperLevel mPlayerXPperLevel; + + typedef std::map BaseXPMap; // [area level][base xp] + BaseXPMap mBaseXPTable; + + typedef std::map FishingBaseSkillMap; // [areaId][base skill level] + FishingBaseSkillMap mFishingBaseForArea; + + typedef std::map > HalfNameMap; + HalfNameMap PetHalfName0; + HalfNameMap PetHalfName1; + + MapObjectGuids mMapObjectGuids; + CreatureDataMap mCreatureDataMap; + CreatureLinkedRespawnMap mCreatureLinkedRespawnMap; + CreatureLocaleMap mCreatureLocaleMap; + GameObjectDataMap mGameObjectDataMap; + GameObjectLocaleMap mGameObjectLocaleMap; + ItemLocaleMap mItemLocaleMap; + QuestLocaleMap mQuestLocaleMap; + NpcTextLocaleMap mNpcTextLocaleMap; + PageTextLocaleMap mPageTextLocaleMap; + TrinityStringLocaleMap mTrinityStringLocaleMap; + GossipMenuItemsLocaleMap mGossipMenuItemsLocaleMap; + PointOfInterestLocaleMap mPointOfInterestLocaleMap; + RespawnTimes mCreatureRespawnTimes; + RespawnTimes mGORespawnTimes; + + CacheNpcTextIdMap m_mCacheNpcTextIdMap; + CacheVendorItemMap m_mCacheVendorItemMap; + CacheTrainerSpellMap m_mCacheTrainerSpellMap; + + std::set difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate + std::set hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate + +}; + +#define objmgr Trinity::Singleton::Instance() + +// scripting access functions + bool LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value = MAX_CREATURE_AI_TEXT_STRING_ID, int32 end_value = std::numeric_limits::min()); + uint32 GetAreaTriggerScriptId(uint32 trigger_id); + uint32 GetScriptId(const char *name); + ObjectMgr::ScriptNameMap& GetScriptNames(); + GameObjectInfo const *GetGameObjectInfo(uint32 id); + CreatureInfo const *GetCreatureInfo(uint32 id); + CreatureInfo const* GetCreatureTemplateStore(uint32 entry); + Quest const* GetQuestTemplateStore(uint32 entry); + +#endif diff --git a/src/server/game/Globals/SharedDefines.h b/src/server/game/Globals/SharedDefines.h deleted file mode 100644 index 903dd4b09ca..00000000000 --- a/src/server/game/Globals/SharedDefines.h +++ /dev/null @@ -1,2772 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_SHAREDDEFINES_H -#define TRINITY_SHAREDDEFINES_H - -#include "Platform/Define.h" -#include - -// loot modes for creatures and gameobjects, bitmask! -enum LootModes -{ - LOOT_MODE_DEFAULT = 1, - LOOT_MODE_HARD_MODE_1 = 2, - LOOT_MODE_HARD_MODE_2 = 4, - LOOT_MODE_HARD_MODE_3 = 8, - LOOT_MODE_HARD_MODE_4 = 16 -}; - -enum Gender -{ - GENDER_MALE = 0, - GENDER_FEMALE = 1, - GENDER_NONE = 2 -}; - -// Race value is index in ChrRaces.dbc -enum Races -{ - RACE_HUMAN = 1, - RACE_ORC = 2, - RACE_DWARF = 3, - RACE_NIGHTELF = 4, - RACE_UNDEAD_PLAYER = 5, - RACE_TAUREN = 6, - RACE_GNOME = 7, - RACE_TROLL = 8, - //RACE_GOBLIN = 9, - RACE_BLOODELF = 10, - RACE_DRAENEI = 11 - //RACE_FEL_ORC = 12, - //RACE_NAGA = 13, - //RACE_BROKEN = 14, - //RACE_SKELETON = 15, - //RACE_VRYKUL = 16, - //RACE_TUSKARR = 17, - //RACE_FOREST_TROLL = 18, - //RACE_TAUNKA = 19, - //RACE_NORTHREND_SKELETON = 20, - //RACE_ICE_TROLL = 21 -}; - -// max+1 for player race -#define MAX_RACES 12 - -#define RACEMASK_ALL_PLAYABLE \ - ((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \ - (1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \ - (1<<(RACE_GNOME-1)) |(1<<(RACE_TROLL-1)) |(1<<(RACE_BLOODELF-1))| \ - (1<<(RACE_DRAENEI-1))) - -// Class value is index in ChrClasses.dbc -enum Classes -{ - CLASS_WARRIOR = 1, - CLASS_PALADIN = 2, - CLASS_HUNTER = 3, - CLASS_ROGUE = 4, - CLASS_PRIEST = 5, - CLASS_DEATH_KNIGHT = 6, - CLASS_SHAMAN = 7, - CLASS_MAGE = 8, - CLASS_WARLOCK = 9, - //CLASS_UNK = 10, - CLASS_DRUID = 11 -}; - -// max+1 for player class -#define MAX_CLASSES 12 - -#define CLASSMASK_ALL_PLAYABLE \ - ((1<<(CLASS_WARRIOR-1))|(1<<(CLASS_PALADIN-1))|(1<<(CLASS_HUNTER-1))| \ - (1<<(CLASS_ROGUE-1)) |(1<<(CLASS_PRIEST-1)) |(1<<(CLASS_SHAMAN-1))| \ - (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) | \ - (1<<(CLASS_DEATH_KNIGHT-1))) - -// valid classes for creature_template.unit_class -enum UnitClass -{ - UNIT_CLASS_WARRIOR = 1, - UNIT_CLASS_PALADIN = 2, - UNIT_CLASS_ROGUE = 4, - UNIT_CLASS_MAGE = 8, -}; - -#define CLASSMASK_ALL_CREATURES ((1<<(UNIT_CLASS_WARRIOR-1)) | (1<<(UNIT_CLASS_PALADIN-1)) | (1<<(UNIT_CLASS_ROGUE-1)) | (1<<(UNIT_CLASS_MAGE-1))) - -#define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1))) - -#define PLAYER_MAX_BATTLEGROUND_QUEUES 2 - -enum ReputationRank -{ - REP_HATED = 0, - REP_HOSTILE = 1, - REP_UNFRIENDLY = 2, - REP_NEUTRAL = 3, - REP_FRIENDLY = 4, - REP_HONORED = 5, - REP_REVERED = 6, - REP_EXALTED = 7 -}; - -#define MIN_REPUTATION_RANK (REP_HATED) -#define MAX_REPUTATION_RANK 8 - -enum MoneyConstants -{ - COPPER = 1, - SILVER = COPPER*100, - GOLD = SILVER*100 -}; - -enum Stats -{ - STAT_STRENGTH = 0, - STAT_AGILITY = 1, - STAT_STAMINA = 2, - STAT_INTELLECT = 3, - STAT_SPIRIT = 4 -}; - -#define MAX_STATS 5 - -enum Powers -{ - POWER_MANA = 0, - POWER_RAGE = 1, - POWER_FOCUS = 2, - POWER_ENERGY = 3, - POWER_HAPPINESS = 4, - POWER_RUNE = 5, - POWER_RUNIC_POWER = 6, - MAX_POWERS = 7, - POWER_ALL = 127, // default for class? - POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) -}; - -enum SpellSchools -{ - SPELL_SCHOOL_NORMAL = 0, - SPELL_SCHOOL_HOLY = 1, - SPELL_SCHOOL_FIRE = 2, - SPELL_SCHOOL_NATURE = 3, - SPELL_SCHOOL_FROST = 4, - SPELL_SCHOOL_SHADOW = 5, - SPELL_SCHOOL_ARCANE = 6 -}; - -#define MAX_SPELL_SCHOOL 7 - -enum SpellSchoolMask -{ - SPELL_SCHOOL_MASK_NONE = 0x00, // not exist - SPELL_SCHOOL_MASK_NORMAL = (1 << SPELL_SCHOOL_NORMAL), // PHYSICAL (Armor) - SPELL_SCHOOL_MASK_HOLY = (1 << SPELL_SCHOOL_HOLY), - SPELL_SCHOOL_MASK_FIRE = (1 << SPELL_SCHOOL_FIRE), - SPELL_SCHOOL_MASK_NATURE = (1 << SPELL_SCHOOL_NATURE), - SPELL_SCHOOL_MASK_FROST = (1 << SPELL_SCHOOL_FROST), - SPELL_SCHOOL_MASK_SHADOW = (1 << SPELL_SCHOOL_SHADOW), - SPELL_SCHOOL_MASK_ARCANE = (1 << SPELL_SCHOOL_ARCANE), - - // unions - - // 124, not include normal and holy damage - SPELL_SCHOOL_MASK_SPELL = (SPELL_SCHOOL_MASK_FIRE | - SPELL_SCHOOL_MASK_NATURE | SPELL_SCHOOL_MASK_FROST | - SPELL_SCHOOL_MASK_SHADOW | SPELL_SCHOOL_MASK_ARCANE), - // 126 - SPELL_SCHOOL_MASK_MAGIC = (SPELL_SCHOOL_MASK_HOLY | SPELL_SCHOOL_MASK_SPELL), - - // 127 - SPELL_SCHOOL_MASK_ALL = (SPELL_SCHOOL_MASK_NORMAL | SPELL_SCHOOL_MASK_MAGIC) -}; - -inline SpellSchools GetFirstSchoolInMask(SpellSchoolMask mask) -{ - for (int i = 0; i < MAX_SPELL_SCHOOL; ++i) - if (mask & (1 << i)) - return SpellSchools(i); - - return SPELL_SCHOOL_NORMAL; -} - -enum ItemQualities -{ - ITEM_QUALITY_POOR = 0, //GREY - ITEM_QUALITY_NORMAL = 1, //WHITE - ITEM_QUALITY_UNCOMMON = 2, //GREEN - ITEM_QUALITY_RARE = 3, //BLUE - ITEM_QUALITY_EPIC = 4, //PURPLE - ITEM_QUALITY_LEGENDARY = 5, //ORANGE - ITEM_QUALITY_ARTIFACT = 6, //LIGHT YELLOW - ITEM_QUALITY_HEIRLOOM = 7 -}; - -#define MAX_ITEM_QUALITY 8 - -enum SpellCategory -{ - SPELL_CATEGORY_FOOD = 11, - SPELL_CATEGORY_DRINK = 59, -}; - -const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = { - 0xff9d9d9d, //GREY - 0xffffffff, //WHITE - 0xff1eff00, //GREEN - 0xff0070dd, //BLUE - 0xffa335ee, //PURPLE - 0xffff8000, //ORANGE - 0xffe6cc80, //LIGHT YELLOW - 0xffe6cc80 //LIGHT YELLOW -}; - -// *********************************** -// Spell Attributes definitions -// *********************************** - -#define SPELL_ATTR_UNK0 0x00000001 // 0 -#define SPELL_ATTR_REQ_AMMO 0x00000002 // 1 -#define SPELL_ATTR_ON_NEXT_SWING 0x00000004 // 2 on next swing -#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 3.0.3 -#define SPELL_ATTR_UNK4 0x00000010 // 4 -#define SPELL_ATTR_TRADESPELL 0x00000020 // 5 trade spells, will be added by client to a sublist of profession spell -#define SPELL_ATTR_PASSIVE 0x00000040 // 6 Passive spell -#define SPELL_ATTR_UNK7 0x00000080 // 7 visible? -#define SPELL_ATTR_UNK8 0x00000100 // 8 -#define SPELL_ATTR_UNK9 0x00000200 // 9 -#define SPELL_ATTR_UNK10 0x00000400 // 10 on next swing 2 -#define SPELL_ATTR_UNK11 0x00000800 // 11 -#define SPELL_ATTR_DAYTIME_ONLY 0x00001000 // 12 only useable at daytime, not set in 2.4.2 -#define SPELL_ATTR_NIGHT_ONLY 0x00002000 // 13 only useable at night, not set in 2.4.2 -#define SPELL_ATTR_INDOORS_ONLY 0x00004000 // 14 only useable indoors, not set in 2.4.2 -#define SPELL_ATTR_OUTDOORS_ONLY 0x00008000 // 15 Only useable outdoors. -#define SPELL_ATTR_NOT_SHAPESHIFT 0x00010000 // 16 Not while shapeshifted -#define SPELL_ATTR_ONLY_STEALTHED 0x00020000 // 17 Must be in stealth -#define SPELL_ATTR_UNK18 0x00040000 // 18 -#define SPELL_ATTR_LEVEL_DAMAGE_CALCULATION 0x00080000 // 19 spelldamage depends on caster level -#define SPELL_ATTR_STOP_ATTACK_TARGET 0x00100000 // 20 Stop attack after use this spell (and not begin attack if use) -#define SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK 0x00200000 // 21 Cannot be dodged/parried/blocked -#define SPELL_ATTR_UNK22 0x00400000 // 22 shoot spells -#define SPELL_ATTR_CASTABLE_WHILE_DEAD 0x00800000 // 23 castable while dead? -#define SPELL_ATTR_CASTABLE_WHILE_MOUNTED 0x01000000 // 24 castable while mounted -#define SPELL_ATTR_DISABLED_WHILE_ACTIVE 0x02000000 // 25 Activate and start cooldown after aura fade or remove summoned creature or go -#define SPELL_ATTR_NEGATIVE_1 0x04000000 // 26 Many negative spells have this attr -#define SPELL_ATTR_CASTABLE_WHILE_SITTING 0x08000000 // 27 castable while sitting -#define SPELL_ATTR_CANT_USED_IN_COMBAT 0x10000000 // 28 Cannot be used in combat -#define SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY 0x20000000 // 29 unaffected by invulnerability (hmm possible not...) -#define SPELL_ATTR_BREAKABLE_BY_DAMAGE 0x40000000 // 30 -#define SPELL_ATTR_CANT_CANCEL 0x80000000 // 31 positive aura can't be canceled - -#define SPELL_ATTR_EX_DISMISS_PET 0x00000001 // 0 dismiss pet and not allow to summon new one? -#define SPELL_ATTR_EX_DRAIN_ALL_POWER 0x00000002 // 1 use all power (Only paladin Lay of Hands and Bunyanize) -#define SPELL_ATTR_EX_CHANNELED_1 0x00000004 // 2 channeled target -#define SPELL_ATTR_EX_PUT_CASTER_IN_COMBAT 0x00000008 // 3 spells that cause a caster to enter a combat -#define SPELL_ATTR_EX_UNK4 0x00000010 // 4 stealth and whirlwind -#define SPELL_ATTR_EX_NOT_BREAK_STEALTH 0x00000020 // 5 Not break stealth -#define SPELL_ATTR_EX_CHANNELED_2 0x00000040 // 6 channeled self -#define SPELL_ATTR_EX_NEGATIVE 0x00000080 // 7 -#define SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET 0x00000100 // 8 Spell req target not to be in combat state -#define SPELL_ATTR_EX_UNK9 0x00000200 // 9 melee spells -#define SPELL_ATTR_EX_UNK10 0x00000400 // 10 no generates threat on cast 100%? (old NO_INITIAL_AGGRO) -#define SPELL_ATTR_EX_UNK11 0x00000800 // 11 aura -#define SPELL_ATTR_EX_UNK12 0x00001000 // 12 -#define SPELL_ATTR_EX_UNK13 0x00002000 // 13 -#define SPELL_ATTR_EX_STACK_FOR_DIFF_CASTERS 0x00004000 // 14 -#define SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY 0x00008000 // 15 remove auras on immunity -#define SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE 0x00010000 // 16 on immuniy -#define SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET 0x00020000 // 17 -#define SPELL_ATTR_EX_UNK18 0x00040000 // 18 -#define SPELL_ATTR_EX_CANT_TARGET_SELF 0x00080000 // 19 Applies only to unit target - for example Divine Intervention (19752) -#define SPELL_ATTR_EX_REQ_COMBO_POINTS1 0x00100000 // 20 Req combo points on target -#define SPELL_ATTR_EX_UNK21 0x00200000 // 21 -#define SPELL_ATTR_EX_REQ_COMBO_POINTS2 0x00400000 // 22 Req combo points on target -#define SPELL_ATTR_EX_UNK23 0x00800000 // 23 -#define SPELL_ATTR_EX_UNK24 0x01000000 // 24 Req fishing pole?? -#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 -#define SPELL_ATTR_EX_UNK26 0x04000000 // 26 works correctly with [target=focus] and [target=mouseover] macros? -#define SPELL_ATTR_EX_UNK27 0x08000000 // 27 -#define SPELL_ATTR_EX_IGNORE_IMMUNITY 0x10000000 // 28 removed from Chains of Ice 3.3.0 -#define SPELL_ATTR_EX_UNK29 0x20000000 // 29 -#define SPELL_ATTR_EX_ENABLE_AT_DODGE 0x40000000 // 30 Overpower, Wolverine Bite -#define SPELL_ATTR_EX_UNK31 0x80000000 // 31 - -#define SPELL_ATTR_EX2_UNK0 0x00000001 // 0 -#define SPELL_ATTR_EX2_UNK1 0x00000002 // 1 ? many triggered spells have this flag -#define SPELL_ATTR_EX2_CANT_REFLECTED 0x00000004 // 2 ? used for detect can or not spell reflected -#define SPELL_ATTR_EX2_UNK3 0x00000008 // 3 -#define SPELL_ATTR_EX2_UNK4 0x00000010 // 4 -#define SPELL_ATTR_EX2_AUTOREPEAT_FLAG 0x00000020 // 5 -#define SPELL_ATTR_EX2_UNK6 0x00000040 // 6 -#define SPELL_ATTR_EX2_UNK7 0x00000080 // 7 -#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 3.0.3 -#define SPELL_ATTR_EX2_UNK9 0x00000200 // 9 -#define SPELL_ATTR_EX2_UNK10 0x00000400 // 10 -#define SPELL_ATTR_EX2_HEALTH_FUNNEL 0x00000800 // 11 -#define SPELL_ATTR_EX2_UNK12 0x00001000 // 12 -#define SPELL_ATTR_EX2_UNK13 0x00002000 // 13 Items enchanted by spells with this flag preserve the enchant to arenas -#define SPELL_ATTR_EX2_UNK14 0x00004000 // 14 -#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 3.0.3 -#define SPELL_ATTR_EX2_TAME_BEAST 0x00010000 // 16 -#define SPELL_ATTR_EX2_NOT_RESET_AUTOSHOT 0x00020000 // 17 Hunters Shot and Stings only have this flag -#define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet -#define SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT 0x00080000 // 19 does not necessarly need shapeshift -#define SPELL_ATTR_EX2_UNK20 0x00100000 // 20 -#define SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD 0x00200000 // 21 for ice blocks, pala immunity buffs, priest absorb shields, but used also for other spells -> not sure! -#define SPELL_ATTR_EX2_UNK22 0x00400000 // 22 -#define SPELL_ATTR_EX2_UNK23 0x00800000 // 23 Only mage Arcane Concentration have this flag -#define SPELL_ATTR_EX2_UNK24 0x01000000 // 24 -#define SPELL_ATTR_EX2_UNK25 0x02000000 // 25 -#define SPELL_ATTR_EX2_UNK26 0x04000000 // 26 unaffected by school immunity -#define SPELL_ATTR_EX2_UNK27 0x08000000 // 27 -#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 no breaks stealth if it fails?? -#define SPELL_ATTR_EX2_CANT_CRIT 0x20000000 // 29 Spell can't crit -#define SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER 0x40000000 // 30 spell can trigger even if triggered -#define SPELL_ATTR_EX2_FOOD_BUFF 0x80000000 // 31 Food or Drink Buff (like Well Fed) - -#define SPELL_ATTR_EX3_UNK0 0x00000001 // 0 -#define SPELL_ATTR_EX3_UNK1 0x00000002 // 1 -#define SPELL_ATTR_EX3_UNK2 0x00000004 // 2 -#define SPELL_ATTR_EX3_BLOCKABLE_SPELL 0x00000008 // 3 Only dmg class melee in 3.1.3 -#define SPELL_ATTR_EX3_UNK4 0x00000010 // 4 Druid Rebirth only this spell have this flag -#define SPELL_ATTR_EX3_UNK5 0x00000020 // 5 -#define SPELL_ATTR_EX3_UNK6 0x00000040 // 6 -#define SPELL_ATTR_EX3_STACK_FOR_DIFF_CASTERS 0x00000080 // 7 separate stack for every caster -#define SPELL_ATTR_EX3_PLAYERS_ONLY 0x00000100 // 8 Player only? -#define SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2 0x00000200 // 9 triggered from effect? -#define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required -#define SPELL_ATTR_EX3_BATTLEGROUND 0x00000800 // 11 Can casted only on battleground -#define SPELL_ATTR_EX3_UNK12 0x00001000 // 12 -#define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 -#define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag -#define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag -#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 no triggers effects that trigger on casting a spell?? (15290 - 2.2ptr change) -#define SPELL_ATTR_EX3_NO_INITIAL_AGGRO 0x00020000 // 17 Soothe Animal, 39758, Mind Soothe -#define SPELL_ATTR_EX3_UNK18 0x00040000 // 18 added to Explosive Trap Effect 3.3.0, removed from Mutilate 3.3.0 -#define SPELL_ATTR_EX3_DISABLE_PROC 0x00080000 // 19 during aura proc no spells can trigger (20178, 20375) -#define SPELL_ATTR_EX3_DEATH_PERSISTENT 0x00100000 // 20 Death persistent spells -#define SPELL_ATTR_EX3_UNK21 0x00200000 // 21 -#define SPELL_ATTR_EX3_REQ_WAND 0x00400000 // 22 Req wand -#define SPELL_ATTR_EX3_UNK23 0x00800000 // 23 -#define SPELL_ATTR_EX3_REQ_OFFHAND 0x01000000 // 24 Req offhand weapon -#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25 no cause spell pushback ? -#define SPELL_ATTR_EX3_CAN_PROC_TRIGGERED 0x04000000 // 26 -#define SPELL_ATTR_EX3_DRAIN_SOUL 0x08000000 // 27 only drain soul has this flag -#define SPELL_ATTR_EX3_UNK28 0x10000000 // 28 -#define SPELL_ATTR_EX3_NO_DONE_BONUS 0x20000000 // 29 Ignore caster spellpower and done damage mods? -#define SPELL_ATTR_EX3_UNK30 0x40000000 // 30 Shaman's Fire Nova 3.3.0, Sweeping Strikes 3.3.0 -#define SPELL_ATTR_EX3_UNK31 0x80000000 // 31 - -#define SPELL_ATTR_EX4_UNK0 0x00000001 // 0 -#define SPELL_ATTR_EX4_UNK1 0x00000002 // 1 proc on finishing move? -#define SPELL_ATTR_EX4_UNK2 0x00000004 // 2 -#define SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST 0x00000008 // 3 -#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4 This will no longer cause guards to attack on use?? -#define SPELL_ATTR_EX4_UNK5 0x00000020 // 5 -#define SPELL_ATTR_EX4_NOT_STEALABLE 0x00000040 // 6 although such auras might be dispellable, they cannot be stolen -#define SPELL_ATTR_EX4_UNK7 0x00000080 // 7 -#define SPELL_ATTR_EX4_FIXED_DAMAGE 0x00000100 // 8 decimate, share damage? -#define SPELL_ATTR_EX4_UNK9 0x00000200 // 9 -#define SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST 0x00000400 // 10 Rogue Shiv have this flag -#define SPELL_ATTR_EX4_UNK11 0x00000800 // 11 -#define SPELL_ATTR_EX4_UNK12 0x00001000 // 12 -#define SPELL_ATTR_EX4_UNK13 0x00002000 // 13 -#define SPELL_ATTR_EX4_UNK14 0x00004000 // 14 -#define SPELL_ATTR_EX4_UNK15 0x00008000 // 15 -#define SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA 0x00010000 // 16 not usable in arena -#define SPELL_ATTR_EX4_USABLE_IN_ARENA 0x00020000 // 17 usable in arena -#define SPELL_ATTR_EX4_UNK18 0x00040000 // 18 -#define SPELL_ATTR_EX4_UNK19 0x00080000 // 19 -#define SPELL_ATTR_EX4_NOT_CHECK_SELFCAST_POWER 0x00100000 // 20 supersedes message "More powerful spell applied" for self casts. -#define SPELL_ATTR_EX4_UNK21 0x00200000 // 21 -#define SPELL_ATTR_EX4_UNK22 0x00400000 // 22 -#define SPELL_ATTR_EX4_UNK23 0x00800000 // 23 -#define SPELL_ATTR_EX4_UNK24 0x01000000 // 24 -#define SPELL_ATTR_EX4_UNK25 0x02000000 // 25 pet scaling auras -#define SPELL_ATTR_EX4_CAST_ONLY_IN_OUTLAND 0x04000000 // 26 Can only be used in Outland. -#define SPELL_ATTR_EX4_UNK27 0x08000000 // 27 -#define SPELL_ATTR_EX4_UNK28 0x10000000 // 28 -#define SPELL_ATTR_EX4_UNK29 0x20000000 // 29 -#define SPELL_ATTR_EX4_UNK30 0x40000000 // 30 -#define SPELL_ATTR_EX4_UNK31 0x80000000 // 31 - -#define SPELL_ATTR_EX5_UNK0 0x00000001 // 0 -#define SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP 0x00000002 // 1 not need reagents if UNIT_FLAG_PREPARATION -#define SPELL_ATTR_EX5_UNK2 0x00000004 // 2 -#define SPELL_ATTR_EX5_USABLE_WHILE_STUNNED 0x00000008 // 3 usable while stunned -#define SPELL_ATTR_EX5_UNK4 0x00000010 // 4 -#define SPELL_ATTR_EX5_SINGLE_TARGET_SPELL 0x00000020 // 5 Only one target can be apply at a time -#define SPELL_ATTR_EX5_UNK6 0x00000040 // 6 -#define SPELL_ATTR_EX5_UNK7 0x00000080 // 7 -#define SPELL_ATTR_EX5_UNK8 0x00000100 // 8 -#define SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY 0x00000200 // 9 begin periodic tick at aura apply -#define SPELL_ATTR_EX5_UNK10 0x00000400 // 10 -#define SPELL_ATTR_EX5_UNK11 0x00000800 // 11 -#define SPELL_ATTR_EX5_UNK12 0x00001000 // 12 -#define SPELL_ATTR_EX5_UNK13 0x00002000 // 13 -#define SPELL_ATTR_EX5_UNK14 0x00004000 // 14 -#define SPELL_ATTR_EX5_UNK15 0x00008000 // 15 -#define SPELL_ATTR_EX5_UNK16 0x00010000 // 16 -#define SPELL_ATTR_EX5_USABLE_WHILE_FEARED 0x00020000 // 17 usable while feared -#define SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED 0x00040000 // 18 usable while confused -#define SPELL_ATTR_EX5_UNK19 0x00080000 // 19 -#define SPELL_ATTR_EX5_UNK20 0x00100000 // 20 -#define SPELL_ATTR_EX5_UNK21 0x00200000 // 21 -#define SPELL_ATTR_EX5_UNK22 0x00400000 // 22 -#define SPELL_ATTR_EX5_UNK23 0x00800000 // 23 -#define SPELL_ATTR_EX5_UNK24 0x01000000 // 24 -#define SPELL_ATTR_EX5_UNK25 0x02000000 // 25 -#define SPELL_ATTR_EX5_UNK26 0x04000000 // 26 -#define SPELL_ATTR_EX5_UNK27 0x08000000 // 27 -#define SPELL_ATTR_EX5_UNK28 0x10000000 // 28 -#define SPELL_ATTR_EX5_UNK29 0x20000000 // 29 -#define SPELL_ATTR_EX5_UNK30 0x40000000 // 30 -#define SPELL_ATTR_EX5_UNK31 0x80000000 // 31 Forces all nearby enemies to focus attacks caster - -#define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag -#define SPELL_ATTR_EX6_ONLY_IN_ARENA 0x00000002 // 1 only usable in arena -#define SPELL_ATTR_EX6_IGNORE_CASTER_AURAS 0x00000004 // 2 -#define SPELL_ATTR_EX6_UNK3 0x00000008 // 3 -#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 -#define SPELL_ATTR_EX6_UNK5 0x00000020 // 5 -#define SPELL_ATTR_EX6_UNK6 0x00000040 // 6 -#define SPELL_ATTR_EX6_UNK7 0x00000080 // 7 -#define SPELL_ATTR_EX6_UNK8 0x00000100 // 8 -#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 -#define SPELL_ATTR_EX6_UNK10 0x00000400 // 10 -#define SPELL_ATTR_EX6_NOT_IN_RAID_INSTANCE 0x00000800 // 11 not usable in raid instance -#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 -#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 -#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 -#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 -#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 -#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 -#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 -#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 -#define SPELL_ATTR_EX6_CLIENT_UI_TARGET_EFFECTS 0x00200000 // 21 it's only client-side attribute -#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 -#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3 - -#define SPELL_ATTR_EX7_UNK0 0x00000001 // 0 Shaman's new spells (Call of the ...), Feign Death. -#define SPELL_ATTR_EX7_UNK1 0x00000002 // 1 Not set in 3.2.2a. -#define SPELL_ATTR_EX7_REACTIVATE_AT_RESURRECT 0x00000004 // 2 Paladin's auras and 65607 only. -#define SPELL_ATTR_EX7_UNK3 0x00000008 // 3 Only 43574 test spell. -#define SPELL_ATTR_EX7_UNK4 0x00000010 // 4 Only 66109 test spell. -#define SPELL_ATTR_EX7_SUMMON_PLAYER_TOTEM 0x00000020 // 5 Only Shaman player totems. -#define SPELL_ATTR_EX7_UNK6 0x00000040 // 6 Dark Surge, Surge of Light, Burning Breath triggers (boss spells). -#define SPELL_ATTR_EX7_UNK7 0x00000080 // 7 66218 (Launch) spell. -#define SPELL_ATTR_EX7_UNK8 0x00000100 // 8 Teleports, mounts and other spells. -#define SPELL_ATTR_EX7_UNK9 0x00000200 // 9 Teleports, mounts and other spells. -#define SPELL_ATTR_EX7_DISPEL_CHARGES 0x00000400 // 10 Dispel and Spellsteal individual charges instead of whole aura. -#define SPELL_ATTR_EX7_INTERRUPT_ONLY_NONPLAYER 0x00000800 // 11 Only non-player casts interrupt, though Feral Charge - Bear has it. -#define SPELL_ATTR_EX7_UNK12 0x00001000 // 12 Not set in 3.2.2a. -#define SPELL_ATTR_EX7_UNK13 0x00002000 // 13 Not set in 3.2.2a. -#define SPELL_ATTR_EX7_UNK14 0x00004000 // 14 Only 52150 (Raise Dead - Pet) spell. -#define SPELL_ATTR_EX7_UNK15 0x00008000 // 15 Exorcism. Usable on players? 100% crit chance on undead and demons? -#define SPELL_ATTR_EX7_UNK16 0x00010000 // 16 Druid spells (29166, 54833, 64372, 68285). -#define SPELL_ATTR_EX7_UNK17 0x00020000 // 17 Only 27965 (Suicide) spell. -#define SPELL_ATTR_EX7_HAS_CHARGE_EFFECT 0x00040000 // 18 Only spells that have Charge among effects. -#define SPELL_ATTR_EX7_ZONE_TELEPORT 0x00080000 // 19 Teleports to specific zones. - -#define MIN_TALENT_SPEC 0 -#define MAX_TALENT_SPEC 1 -#define MIN_TALENT_SPECS 1 -#define MAX_TALENT_SPECS 2 -#define MAX_GLYPH_SLOT_INDEX 6 - -// Custom values -enum SpellClickUserTypes -{ - SPELL_CLICK_USER_ANY = 0, - SPELL_CLICK_USER_FRIEND = 1, - SPELL_CLICK_USER_RAID = 2, - SPELL_CLICK_USER_PARTY = 3, - SPELL_CLICK_USER_MAX = 4 -}; - -#define NPC_CLICK_CAST_CASTER_PLAYER 0x01 -#define NPC_CLICK_CAST_TARGET_PLAYER 0x02 -#define NPC_CLICK_CAST_ORIG_CASTER_OWNER 0x04 - -enum SheathTypes -{ - SHEATHETYPE_NONE = 0, - SHEATHETYPE_MAINHAND = 1, - SHEATHETYPE_OFFHAND = 2, - SHEATHETYPE_LARGEWEAPONLEFT = 3, - SHEATHETYPE_LARGEWEAPONRIGHT = 4, - SHEATHETYPE_HIPWEAPONLEFT = 5, - SHEATHETYPE_HIPWEAPONRIGHT = 6, - SHEATHETYPE_SHIELD = 7 -}; - -#define MAX_SHEATHETYPE 8 - -enum CharacterSlot -{ - SLOT_HEAD = 0, - SLOT_NECK = 1, - SLOT_SHOULDERS = 2, - SLOT_SHIRT = 3, - SLOT_CHEST = 4, - SLOT_WAIST = 5, - SLOT_LEGS = 6, - SLOT_FEET = 7, - SLOT_WRISTS = 8, - SLOT_HANDS = 9, - SLOT_FINGER1 = 10, - SLOT_FINGER2 = 11, - SLOT_TRINKET1 = 12, - SLOT_TRINKET2 = 13, - SLOT_BACK = 14, - SLOT_MAIN_HAND = 15, - SLOT_OFF_HAND = 16, - SLOT_RANGED = 17, - SLOT_TABARD = 18, - SLOT_EMPTY = 19 -}; - -enum Language -{ - LANG_UNIVERSAL = 0, - LANG_ORCISH = 1, - LANG_DARNASSIAN = 2, - LANG_TAURAHE = 3, - LANG_DWARVISH = 6, - LANG_COMMON = 7, - LANG_DEMONIC = 8, - LANG_TITAN = 9, - LANG_THALASSIAN = 10, - LANG_DRACONIC = 11, - LANG_KALIMAG = 12, - LANG_GNOMISH = 13, - LANG_TROLL = 14, - LANG_GUTTERSPEAK = 33, - LANG_DRAENEI = 35, - LANG_ZOMBIE = 36, - LANG_GNOMISH_BINARY = 37, - LANG_GOBLIN_BINARY = 38, - LANG_ADDON = 0xFFFFFFFF // used by addons, in 2.4.0 not exist, replaced by messagetype? -}; - -#define LANGUAGES_COUNT 19 - -enum TeamId -{ - TEAM_ALLIANCE = 0, - TEAM_HORDE, - TEAM_NEUTRAL, -}; - -enum Team -{ - HORDE = 67, - ALLIANCE = 469, - //TEAM_STEAMWHEEDLE_CARTEL = 169, // not used in code - //TEAM_ALLIANCE_FORCES = 891, - //TEAM_HORDE_FORCES = 892, - //TEAM_SANCTUARY = 936, - //TEAM_OUTLAND = 980, - TEAM_OTHER = 0, // if ReputationListId > 0 && Flags != FACTION_FLAG_TEAM_HEADER -}; - -const Team TeamId2Team[3] = {ALLIANCE, HORDE, TEAM_OTHER}; - -enum SpellEffects -{ - SPELL_EFFECT_INSTAKILL = 1, - SPELL_EFFECT_SCHOOL_DAMAGE = 2, - SPELL_EFFECT_DUMMY = 3, - SPELL_EFFECT_PORTAL_TELEPORT = 4, - SPELL_EFFECT_TELEPORT_UNITS = 5, - SPELL_EFFECT_APPLY_AURA = 6, - SPELL_EFFECT_ENVIRONMENTAL_DAMAGE = 7, - SPELL_EFFECT_POWER_DRAIN = 8, - SPELL_EFFECT_HEALTH_LEECH = 9, - SPELL_EFFECT_HEAL = 10, - SPELL_EFFECT_BIND = 11, - SPELL_EFFECT_PORTAL = 12, - SPELL_EFFECT_RITUAL_BASE = 13, - SPELL_EFFECT_RITUAL_SPECIALIZE = 14, - SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15, - SPELL_EFFECT_QUEST_COMPLETE = 16, - SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17, - SPELL_EFFECT_RESURRECT = 18, - SPELL_EFFECT_ADD_EXTRA_ATTACKS = 19, - SPELL_EFFECT_DODGE = 20, - SPELL_EFFECT_EVADE = 21, - SPELL_EFFECT_PARRY = 22, - SPELL_EFFECT_BLOCK = 23, - SPELL_EFFECT_CREATE_ITEM = 24, - SPELL_EFFECT_WEAPON = 25, - SPELL_EFFECT_DEFENSE = 26, - SPELL_EFFECT_PERSISTENT_AREA_AURA = 27, - SPELL_EFFECT_SUMMON = 28, - SPELL_EFFECT_LEAP = 29, - SPELL_EFFECT_ENERGIZE = 30, - SPELL_EFFECT_WEAPON_PERCENT_DAMAGE = 31, - SPELL_EFFECT_TRIGGER_MISSILE = 32, - SPELL_EFFECT_OPEN_LOCK = 33, - SPELL_EFFECT_SUMMON_CHANGE_ITEM = 34, - SPELL_EFFECT_APPLY_AREA_AURA_PARTY = 35, - SPELL_EFFECT_LEARN_SPELL = 36, - SPELL_EFFECT_SPELL_DEFENSE = 37, - SPELL_EFFECT_DISPEL = 38, - SPELL_EFFECT_LANGUAGE = 39, - SPELL_EFFECT_DUAL_WIELD = 40, - SPELL_EFFECT_JUMP = 41, - SPELL_EFFECT_JUMP2 = 42, - SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER= 43, - SPELL_EFFECT_SKILL_STEP = 44, - SPELL_EFFECT_ADD_HONOR = 45, - SPELL_EFFECT_SPAWN = 46, - SPELL_EFFECT_TRADE_SKILL = 47, - SPELL_EFFECT_STEALTH = 48, - SPELL_EFFECT_DETECT = 49, - SPELL_EFFECT_TRANS_DOOR = 50, - SPELL_EFFECT_FORCE_CRITICAL_HIT = 51, - SPELL_EFFECT_GUARANTEE_HIT = 52, - SPELL_EFFECT_ENCHANT_ITEM = 53, - SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54, - SPELL_EFFECT_TAMECREATURE = 55, - SPELL_EFFECT_SUMMON_PET = 56, - SPELL_EFFECT_LEARN_PET_SPELL = 57, - SPELL_EFFECT_WEAPON_DAMAGE = 58, - SPELL_EFFECT_CREATE_RANDOM_ITEM = 59, - SPELL_EFFECT_PROFICIENCY = 60, - SPELL_EFFECT_SEND_EVENT = 61, - SPELL_EFFECT_POWER_BURN = 62, - SPELL_EFFECT_THREAT = 63, - SPELL_EFFECT_TRIGGER_SPELL = 64, - SPELL_EFFECT_APPLY_AREA_AURA_RAID = 65, - SPELL_EFFECT_CREATE_MANA_GEM = 66, - SPELL_EFFECT_HEAL_MAX_HEALTH = 67, - SPELL_EFFECT_INTERRUPT_CAST = 68, - SPELL_EFFECT_DISTRACT = 69, - SPELL_EFFECT_PULL = 70, - SPELL_EFFECT_PICKPOCKET = 71, - SPELL_EFFECT_ADD_FARSIGHT = 72, - SPELL_EFFECT_UNTRAIN_TALENTS = 73, - SPELL_EFFECT_APPLY_GLYPH = 74, - SPELL_EFFECT_HEAL_MECHANICAL = 75, - SPELL_EFFECT_SUMMON_OBJECT_WILD = 76, - SPELL_EFFECT_SCRIPT_EFFECT = 77, - SPELL_EFFECT_ATTACK = 78, - SPELL_EFFECT_SANCTUARY = 79, - SPELL_EFFECT_ADD_COMBO_POINTS = 80, - SPELL_EFFECT_CREATE_HOUSE = 81, - SPELL_EFFECT_BIND_SIGHT = 82, - SPELL_EFFECT_DUEL = 83, - SPELL_EFFECT_STUCK = 84, - SPELL_EFFECT_SUMMON_PLAYER = 85, - SPELL_EFFECT_ACTIVATE_OBJECT = 86, - SPELL_EFFECT_WMO_DAMAGE = 87, - SPELL_EFFECT_WMO_REPAIR = 88, - SPELL_EFFECT_WMO_CHANGE = 89, - SPELL_EFFECT_KILL_CREDIT = 90, - SPELL_EFFECT_THREAT_ALL = 91, - SPELL_EFFECT_ENCHANT_HELD_ITEM = 92, - SPELL_EFFECT_FORCE_DESELECT = 93, - SPELL_EFFECT_SELF_RESURRECT = 94, - SPELL_EFFECT_SKINNING = 95, - SPELL_EFFECT_CHARGE = 96, - SPELL_EFFECT_CAST_BUTTON = 97, - SPELL_EFFECT_KNOCK_BACK = 98, - SPELL_EFFECT_DISENCHANT = 99, - SPELL_EFFECT_INEBRIATE = 100, - SPELL_EFFECT_FEED_PET = 101, - SPELL_EFFECT_DISMISS_PET = 102, - SPELL_EFFECT_REPUTATION = 103, - SPELL_EFFECT_SUMMON_OBJECT_SLOT1 = 104, - SPELL_EFFECT_SUMMON_OBJECT_SLOT2 = 105, - SPELL_EFFECT_SUMMON_OBJECT_SLOT3 = 106, - SPELL_EFFECT_SUMMON_OBJECT_SLOT4 = 107, - SPELL_EFFECT_DISPEL_MECHANIC = 108, - SPELL_EFFECT_SUMMON_DEAD_PET = 109, - SPELL_EFFECT_DESTROY_ALL_TOTEMS = 110, - SPELL_EFFECT_DURABILITY_DAMAGE = 111, - SPELL_EFFECT_112 = 112, - SPELL_EFFECT_RESURRECT_NEW = 113, - SPELL_EFFECT_ATTACK_ME = 114, - SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115, - SPELL_EFFECT_SKIN_PLAYER_CORPSE = 116, - SPELL_EFFECT_SPIRIT_HEAL = 117, - SPELL_EFFECT_SKILL = 118, - SPELL_EFFECT_APPLY_AREA_AURA_PET = 119, - SPELL_EFFECT_TELEPORT_GRAVEYARD = 120, - SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121, - SPELL_EFFECT_122 = 122, - SPELL_EFFECT_SEND_TAXI = 123, - SPELL_EFFECT_PLAYER_PULL = 124, - SPELL_EFFECT_MODIFY_THREAT_PERCENT = 125, - SPELL_EFFECT_STEAL_BENEFICIAL_BUFF = 126, - SPELL_EFFECT_PROSPECTING = 127, - SPELL_EFFECT_APPLY_AREA_AURA_FRIEND = 128, - SPELL_EFFECT_APPLY_AREA_AURA_ENEMY = 129, - SPELL_EFFECT_REDIRECT_THREAT = 130, - SPELL_EFFECT_131 = 131, - SPELL_EFFECT_PLAY_MUSIC = 132, - SPELL_EFFECT_UNLEARN_SPECIALIZATION = 133, - SPELL_EFFECT_KILL_CREDIT2 = 134, - SPELL_EFFECT_CALL_PET = 135, - SPELL_EFFECT_HEAL_PCT = 136, - SPELL_EFFECT_ENERGIZE_PCT = 137, - SPELL_EFFECT_LEAP_BACK = 138, - SPELL_EFFECT_CLEAR_QUEST = 139, - SPELL_EFFECT_FORCE_CAST = 140, - SPELL_EFFECT_141 = 141, - SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE = 142, - SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143, - SPELL_EFFECT_KNOCK_BACK_2 = 144, - SPELL_EFFECT_145 = 145, - SPELL_EFFECT_ACTIVATE_RUNE = 146, - SPELL_EFFECT_QUEST_FAIL = 147, - SPELL_EFFECT_148 = 148, - SPELL_EFFECT_149 = 149, - SPELL_EFFECT_150 = 150, - SPELL_EFFECT_TRIGGER_SPELL_2 = 151, - SPELL_EFFECT_152 = 152, - SPELL_EFFECT_153 = 153, - SPELL_EFFECT_154 = 154, - SPELL_EFFECT_TITAN_GRIP = 155, - SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC = 156, - SPELL_EFFECT_CREATE_ITEM_2 = 157, - SPELL_EFFECT_MILLING = 158, - SPELL_EFFECT_ALLOW_RENAME_PET = 159, - SPELL_EFFECT_160 = 160, - SPELL_EFFECT_TALENT_SPEC_COUNT = 161, - SPELL_EFFECT_TALENT_SPEC_SELECT = 162, - SPELL_EFFECT_163 = 163, - SPELL_EFFECT_164 = 164, - TOTAL_SPELL_EFFECTS = 165 -}; - -enum SpellCastResult -{ - SPELL_FAILED_SUCCESS = 0, - SPELL_FAILED_AFFECTING_COMBAT = 1, - SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 2, - SPELL_FAILED_ALREADY_AT_FULL_MANA = 3, - SPELL_FAILED_ALREADY_AT_FULL_POWER = 4, - SPELL_FAILED_ALREADY_BEING_TAMED = 5, - SPELL_FAILED_ALREADY_HAVE_CHARM = 6, - SPELL_FAILED_ALREADY_HAVE_SUMMON = 7, - SPELL_FAILED_ALREADY_OPEN = 8, - SPELL_FAILED_AURA_BOUNCED = 9, - SPELL_FAILED_AUTOTRACK_INTERRUPTED = 10, - SPELL_FAILED_BAD_IMPLICIT_TARGETS = 11, - SPELL_FAILED_BAD_TARGETS = 12, - SPELL_FAILED_CANT_BE_CHARMED = 13, - SPELL_FAILED_CANT_BE_DISENCHANTED = 14, - SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 15, - SPELL_FAILED_CANT_BE_MILLED = 16, - SPELL_FAILED_CANT_BE_PROSPECTED = 17, - SPELL_FAILED_CANT_CAST_ON_TAPPED = 18, - SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 19, - SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 20, - SPELL_FAILED_CANT_STEALTH = 21, - SPELL_FAILED_CASTER_AURASTATE = 22, - SPELL_FAILED_CASTER_DEAD = 23, - SPELL_FAILED_CHARMED = 24, - SPELL_FAILED_CHEST_IN_USE = 25, - SPELL_FAILED_CONFUSED = 26, - SPELL_FAILED_DONT_REPORT = 27, - SPELL_FAILED_EQUIPPED_ITEM = 28, - SPELL_FAILED_EQUIPPED_ITEM_CLASS = 29, - SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 30, - SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 31, - SPELL_FAILED_ERROR = 32, - SPELL_FAILED_FIZZLE = 33, - SPELL_FAILED_FLEEING = 34, - SPELL_FAILED_FOOD_LOWLEVEL = 35, - SPELL_FAILED_HIGHLEVEL = 36, - SPELL_FAILED_HUNGER_SATIATED = 37, - SPELL_FAILED_IMMUNE = 38, - SPELL_FAILED_INCORRECT_AREA = 39, - SPELL_FAILED_INTERRUPTED = 40, - SPELL_FAILED_INTERRUPTED_COMBAT = 41, - SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 42, - SPELL_FAILED_ITEM_GONE = 43, - SPELL_FAILED_ITEM_NOT_FOUND = 44, - SPELL_FAILED_ITEM_NOT_READY = 45, - SPELL_FAILED_LEVEL_REQUIREMENT = 46, - SPELL_FAILED_LINE_OF_SIGHT = 47, - SPELL_FAILED_LOWLEVEL = 48, - SPELL_FAILED_LOW_CASTLEVEL = 49, - SPELL_FAILED_MAINHAND_EMPTY = 50, - SPELL_FAILED_MOVING = 51, - SPELL_FAILED_NEED_AMMO = 52, - SPELL_FAILED_NEED_AMMO_POUCH = 53, - SPELL_FAILED_NEED_EXOTIC_AMMO = 54, - SPELL_FAILED_NEED_MORE_ITEMS = 55, - SPELL_FAILED_NOPATH = 56, - SPELL_FAILED_NOT_BEHIND = 57, - SPELL_FAILED_NOT_FISHABLE = 58, - SPELL_FAILED_NOT_FLYING = 59, - SPELL_FAILED_NOT_HERE = 60, - SPELL_FAILED_NOT_INFRONT = 61, - SPELL_FAILED_NOT_IN_CONTROL = 62, - SPELL_FAILED_NOT_KNOWN = 63, - SPELL_FAILED_NOT_MOUNTED = 64, - SPELL_FAILED_NOT_ON_TAXI = 65, - SPELL_FAILED_NOT_ON_TRANSPORT = 66, - SPELL_FAILED_NOT_READY = 67, - SPELL_FAILED_NOT_SHAPESHIFT = 68, - SPELL_FAILED_NOT_STANDING = 69, - SPELL_FAILED_NOT_TRADEABLE = 70, - SPELL_FAILED_NOT_TRADING = 71, - SPELL_FAILED_NOT_UNSHEATHED = 72, - SPELL_FAILED_NOT_WHILE_GHOST = 73, - SPELL_FAILED_NOT_WHILE_LOOTING = 74, - SPELL_FAILED_NO_AMMO = 75, - SPELL_FAILED_NO_CHARGES_REMAIN = 76, - SPELL_FAILED_NO_CHAMPION = 77, - SPELL_FAILED_NO_COMBO_POINTS = 78, - SPELL_FAILED_NO_DUELING = 79, - SPELL_FAILED_NO_ENDURANCE = 80, - SPELL_FAILED_NO_FISH = 81, - SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 82, - SPELL_FAILED_NO_MOUNTS_ALLOWED = 83, - SPELL_FAILED_NO_PET = 84, - SPELL_FAILED_NO_POWER = 85, - SPELL_FAILED_NOTHING_TO_DISPEL = 86, - SPELL_FAILED_NOTHING_TO_STEAL = 87, - SPELL_FAILED_ONLY_ABOVEWATER = 88, - SPELL_FAILED_ONLY_DAYTIME = 89, - SPELL_FAILED_ONLY_INDOORS = 90, - SPELL_FAILED_ONLY_MOUNTED = 91, - SPELL_FAILED_ONLY_NIGHTTIME = 92, - SPELL_FAILED_ONLY_OUTDOORS = 93, - SPELL_FAILED_ONLY_SHAPESHIFT = 94, - SPELL_FAILED_ONLY_STEALTHED = 95, - SPELL_FAILED_ONLY_UNDERWATER = 96, - SPELL_FAILED_OUT_OF_RANGE = 97, - SPELL_FAILED_PACIFIED = 98, - SPELL_FAILED_POSSESSED = 99, - SPELL_FAILED_REAGENTS = 100, - SPELL_FAILED_REQUIRES_AREA = 101, - SPELL_FAILED_REQUIRES_SPELL_FOCUS = 102, - SPELL_FAILED_ROOTED = 103, - SPELL_FAILED_SILENCED = 104, - SPELL_FAILED_SPELL_IN_PROGRESS = 105, - SPELL_FAILED_SPELL_LEARNED = 106, - SPELL_FAILED_SPELL_UNAVAILABLE = 107, - SPELL_FAILED_STUNNED = 108, - SPELL_FAILED_TARGETS_DEAD = 109, - SPELL_FAILED_TARGET_AFFECTING_COMBAT = 110, - SPELL_FAILED_TARGET_AURASTATE = 111, - SPELL_FAILED_TARGET_DUELING = 112, - SPELL_FAILED_TARGET_ENEMY = 113, - SPELL_FAILED_TARGET_ENRAGED = 114, - SPELL_FAILED_TARGET_FRIENDLY = 115, - SPELL_FAILED_TARGET_IN_COMBAT = 116, - SPELL_FAILED_TARGET_IS_PLAYER = 117, - SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 118, - SPELL_FAILED_TARGET_NOT_DEAD = 119, - SPELL_FAILED_TARGET_NOT_IN_PARTY = 120, - SPELL_FAILED_TARGET_NOT_LOOTED = 121, - SPELL_FAILED_TARGET_NOT_PLAYER = 122, - SPELL_FAILED_TARGET_NO_POCKETS = 123, - SPELL_FAILED_TARGET_NO_WEAPONS = 124, - SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 125, - SPELL_FAILED_TARGET_UNSKINNABLE = 126, - SPELL_FAILED_THIRST_SATIATED = 127, - SPELL_FAILED_TOO_CLOSE = 128, - SPELL_FAILED_TOO_MANY_OF_ITEM = 129, - SPELL_FAILED_TOTEM_CATEGORY = 130, - SPELL_FAILED_TOTEMS = 131, - SPELL_FAILED_TRY_AGAIN = 132, - SPELL_FAILED_UNIT_NOT_BEHIND = 133, - SPELL_FAILED_UNIT_NOT_INFRONT = 134, - SPELL_FAILED_WRONG_PET_FOOD = 135, - SPELL_FAILED_NOT_WHILE_FATIGUED = 136, - SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 137, - SPELL_FAILED_NOT_WHILE_TRADING = 138, - SPELL_FAILED_TARGET_NOT_IN_RAID = 139, - SPELL_FAILED_TARGET_FREEFORALL = 140, - SPELL_FAILED_NO_EDIBLE_CORPSES = 141, - SPELL_FAILED_ONLY_BATTLEGROUNDS = 142, - SPELL_FAILED_TARGET_NOT_GHOST = 143, - SPELL_FAILED_TRANSFORM_UNUSABLE = 144, - SPELL_FAILED_WRONG_WEATHER = 145, - SPELL_FAILED_DAMAGE_IMMUNE = 146, - SPELL_FAILED_PREVENTED_BY_MECHANIC = 147, - SPELL_FAILED_PLAY_TIME = 148, - SPELL_FAILED_REPUTATION = 149, - SPELL_FAILED_MIN_SKILL = 150, - SPELL_FAILED_NOT_IN_ARENA = 151, - SPELL_FAILED_NOT_ON_SHAPESHIFT = 152, - SPELL_FAILED_NOT_ON_STEALTHED = 153, - SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 154, - SPELL_FAILED_NOT_ON_MOUNTED = 155, - SPELL_FAILED_TOO_SHALLOW = 156, - SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 157, - SPELL_FAILED_TARGET_IS_TRIVIAL = 158, - SPELL_FAILED_BM_OR_INVISGOD = 159, - SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 160, - SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 161, - SPELL_FAILED_NOT_IDLE = 162, - SPELL_FAILED_NOT_INACTIVE = 163, - SPELL_FAILED_PARTIAL_PLAYTIME = 164, - SPELL_FAILED_NO_PLAYTIME = 165, - SPELL_FAILED_NOT_IN_BATTLEGROUND = 166, - SPELL_FAILED_NOT_IN_RAID_INSTANCE = 167, - SPELL_FAILED_ONLY_IN_ARENA = 168, - SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 169, - SPELL_FAILED_ON_USE_ENCHANT = 170, - SPELL_FAILED_NOT_ON_GROUND = 171, - SPELL_FAILED_CUSTOM_ERROR = 172, - SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 173, - SPELL_FAILED_TOO_MANY_SOCKETS = 174, - SPELL_FAILED_INVALID_GLYPH = 175, - SPELL_FAILED_UNIQUE_GLYPH = 176, - SPELL_FAILED_GLYPH_SOCKET_LOCKED = 177, - SPELL_FAILED_NO_VALID_TARGETS = 178, - SPELL_FAILED_ITEM_AT_MAX_CHARGES = 179, - SPELL_FAILED_NOT_IN_BARBERSHOP = 180, - SPELL_FAILED_FISHING_TOO_LOW = 181, - SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 182, - SPELL_FAILED_SUMMON_PENDING = 183, - SPELL_FAILED_MAX_SOCKETS = 184, - SPELL_FAILED_PET_CAN_RENAME = 185, - SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 186, - SPELL_FAILED_UNKNOWN = 187, // actually doesn't exist in client - - SPELL_CAST_OK = 255 // custom value, don't must be send to client -}; - -// Spell aura states -enum AuraState -{ // (C) used in caster aura state (T) used in target aura state - // (c) used in caster aura state-not (t) used in target aura state-not - AURA_STATE_NONE = 0, // C | - AURA_STATE_DEFENSE = 1, // C | - AURA_STATE_HEALTHLESS_20_PERCENT = 2, // CcT | - AURA_STATE_BERSERKING = 3, // C T | - AURA_STATE_FROZEN = 4, // c t| frozen target - AURA_STATE_JUDGEMENT = 5, // C | - //AURA_STATE_UNKNOWN6 = 6, // | not used - AURA_STATE_HUNTER_PARRY = 7, // C | - //AURA_STATE_UNKNOWN7 = 7, // c | creature cheap shot / focused bursts spells - //AURA_STATE_UNKNOWN8 = 8, // t| test spells - //AURA_STATE_UNKNOWN9 = 9, // | - AURA_STATE_WARRIOR_VICTORY_RUSH = 10, // C | warrior victory rush - //AURA_STATE_UNKNOWN11 = 11, // C t| 60348 - Maelstrom Ready!, test spells - AURA_STATE_FAERIE_FIRE = 12, // c t| - AURA_STATE_HEALTHLESS_35_PERCENT = 13, // C T | - AURA_STATE_CONFLAGRATE = 14, // T | - AURA_STATE_SWIFTMEND = 15, // T | - AURA_STATE_DEADLY_POISON = 16, // T | - AURA_STATE_ENRAGE = 17, // C | - AURA_STATE_BLEEDING = 18, // T| - //AURA_STATE_UNKNOWN19 = 19, // | not used - //AURA_STATE_UNKNOWN20 = 20, // c | only (45317 Suicide) - //AURA_STATE_UNKNOWN21 = 21, // | not used - //AURA_STATE_UNKNOWN22 = 22, // C t| varius spells (63884, 50240) - AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C | -}; - -#define PER_CASTER_AURA_STATE_MASK (\ - (1<<(AURA_STATE_CONFLAGRATE-1))|(1<<(AURA_STATE_DEADLY_POISON-1))) - -// Spell mechanics -enum Mechanics -{ - MECHANIC_NONE = 0, - MECHANIC_CHARM = 1, - MECHANIC_DISORIENTED = 2, - MECHANIC_DISARM = 3, - MECHANIC_DISTRACT = 4, - MECHANIC_FEAR = 5, - MECHANIC_GRIP = 6, - MECHANIC_ROOT = 7, - MECHANIC_PACIFY = 8, //0 spells use this mechanic - MECHANIC_SILENCE = 9, - MECHANIC_SLEEP = 10, - MECHANIC_SNARE = 11, - MECHANIC_STUN = 12, - MECHANIC_FREEZE = 13, - MECHANIC_KNOCKOUT = 14, - MECHANIC_BLEED = 15, - MECHANIC_BANDAGE = 16, - MECHANIC_POLYMORPH = 17, - MECHANIC_BANISH = 18, - MECHANIC_SHIELD = 19, - MECHANIC_SHACKLE = 20, - MECHANIC_MOUNT = 21, - MECHANIC_INFECTED = 22, - MECHANIC_TURN = 23, - MECHANIC_HORROR = 24, - MECHANIC_INVULNERABILITY = 25, - MECHANIC_INTERRUPT = 26, - MECHANIC_DAZE = 27, - MECHANIC_DISCOVERY = 28, - MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block - MECHANIC_SAPPED = 30, - MECHANIC_ENRAGED = 31 -}; - -// Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967da6) -#define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK (\ - (1<(only this effect in the spell) can't cast to it, -//some aura(related to Mechanics or ImmuneToState) can't apply to it. -enum SpellImmunity -{ - IMMUNITY_EFFECT = 0, // enum SpellEffects - IMMUNITY_STATE = 1, // enum AuraType - IMMUNITY_SCHOOL = 2, // enum SpellSchoolMask - IMMUNITY_DAMAGE = 3, // enum SpellSchoolMask - IMMUNITY_DISPEL = 4, // enum DispelType - IMMUNITY_MECHANIC = 5, // enum Mechanics - IMMUNITY_ID = 6 -}; - -#define MAX_SPELL_IMMUNITY 7 - -enum Targets -{ - TARGET_UNIT_CASTER = 1, - TARGET_UNIT_NEARBY_ENEMY = 2, - TARGET_UNIT_NEARBY_ALLY = 3, - TARGET_UNIT_NEARBY_ALLY_UNK = 4, - TARGET_UNIT_PET = 5, - TARGET_UNIT_TARGET_ENEMY = 6, - TARGET_UNIT_AREA_ENTRY_SRC = 7, - TARGET_UNIT_AREA_ENTRY_DST = 8, - TARGET_DST_HOME = 9, // uses in teleport to innkeeper spells - TARGET_UNIT_TARGET_DEST_CASTER = 11, // teleport target to caster - TARGET_UNIT_AREA_ENEMY_SRC = 15, - TARGET_UNIT_AREA_ENEMY_DST = 16, - TARGET_DST_DB = 17, // uses in teleport spells and some other - TARGET_DST_CASTER = 18, - TARGET_UNIT_PARTY_CASTER = 20, - TARGET_UNIT_TARGET_ALLY = 21, - TARGET_SRC_CASTER = 22, - TARGET_GAMEOBJECT = 23, - //TARGET_OBJECT_OPEN - TARGET_UNIT_CONE_ENEMY = 24, - TARGET_UNIT_TARGET_ANY = 25, - TARGET_GAMEOBJECT_ITEM = 26, - //TARGET_OBJECT_ITEM_PICKLOCK - TARGET_UNIT_MASTER = 27, - TARGET_DEST_DYNOBJ_ENEMY = 28, - TARGET_DEST_DYNOBJ_ALLY = 29, // only for effect 27 - TARGET_UNIT_AREA_ALLY_SRC = 30, // in TargetB used only with TARGET_SRC_CASTER and in self casting range in TargetA - TARGET_UNIT_AREA_ALLY_DST = 31, - TARGET_MINION = 32, - //TARGET_DEST_SUMMON - TARGET_UNIT_AREA_PARTY_SRC = 33, - TARGET_UNIT_AREA_PARTY_DST = 34, // used in Tranquility - TARGET_UNIT_TARGET_PARTY = 35, - TARGET_DEST_CASTER_RANDOM_UNKNOWN = 36, //unknown - TARGET_UNIT_PARTY_TARGET = 37, - TARGET_UNIT_NEARBY_ENTRY = 38, - TARGET_UNIT_CASTER_FISHING = 39, - TARGET_GAMEOBJECT_NEARBY_ENTRY = 40, - TARGET_DEST_CASTER_FRONT_LEFT = 41, //earth totem - TARGET_DEST_CASTER_BACK_LEFT = 42, //water totem - TARGET_DEST_CASTER_BACK_RIGHT = 43, //air totem - TARGET_DEST_CASTER_FRONT_RIGHT = 44, //fire totem - TARGET_UNIT_CHAINHEAL = 45, - TARGET_DST_NEARBY_ENTRY = 46, - TARGET_DEST_CASTER_FRONT = 47, - TARGET_DEST_CASTER_BACK = 48, - TARGET_DEST_CASTER_RIGHT = 49, - TARGET_DEST_CASTER_LEFT = 50, - TARGET_OBJECT_AREA_SRC = 51, - TARGET_OBJECT_AREA_DST = 52, - TARGET_DST_TARGET_ENEMY = 53, // set unit coordinates as dest, only 16 target B imlemented - TARGET_UNIT_CONE_ENEMY_UNKNOWN = 54, // 180 degree, or different angle - TARGET_DEST_CASTER_FRONT_LEAP = 55, // for a leap spell - TARGET_UNIT_RAID_CASTER = 56, - TARGET_UNIT_TARGET_RAID = 57, - TARGET_UNIT_NEARBY_RAID = 58, - TARGET_UNIT_CONE_ALLY = 59, - TARGET_UNIT_CONE_ENTRY = 60, - TARGET_UNIT_CLASS_TARGET = 61, - TARGET_TEST = 62, // for a test spell - TARGET_DEST_TARGET_ANY = 63, - TARGET_DEST_TARGET_FRONT = 64, - TARGET_DEST_TARGET_BACK = 65, // uses in teleport behind spells - TARGET_DEST_TARGET_RIGHT = 66, - TARGET_DEST_TARGET_LEFT = 67, - TARGET_DEST_TARGET_FRONT_LEFT = 68, - TARGET_DEST_TARGET_BACK_LEFT = 69, - TARGET_DEST_TARGET_BACK_RIGHT = 70, - TARGET_DEST_TARGET_FRONT_RIGHT = 71, - TARGET_DEST_CASTER_RANDOM = 72, - TARGET_DEST_CASTER_RADIUS = 73, - TARGET_DEST_TARGET_RANDOM = 74, - TARGET_DEST_TARGET_RADIUS = 75, - TARGET_DEST_CHANNEL = 76, - TARGET_UNIT_CHANNEL = 77, - TARGET_DEST_DEST_FRONT = 78, - TARGET_DEST_DEST_BACK = 79, - TARGET_DEST_DEST_RIGHT = 80, - TARGET_DEST_DEST_LEFT = 81, - TARGET_DEST_DEST_FRONT_LEFT = 82, - TARGET_DEST_DEST_BACK_LEFT = 83, - TARGET_DEST_DEST_BACK_RIGHT = 84, - TARGET_DEST_DEST_FRONT_RIGHT = 85, - TARGET_DEST_DEST_RANDOM = 86, - TARGET_DEST_DEST = 87, - TARGET_DEST_DYNOBJ_NONE = 88, - TARGET_DEST_TRAJ = 89, - TARGET_UNIT_MINIPET = 90, - TARGET_DEST_DEST_RANDOM_DIR_DIST = 91, - TARGET_UNIT_UNK_92 = 92, - TARGET_CORPSE_AREA_ENEMY_PLAYER_SRC= 93, - TARGET_UNIT_VEHICLE = 94, - TARGET_UNIT_DRIVER = 95, - TARGET_UNIT_PASSENGER_0 = 96, - TARGET_UNIT_PASSENGER_1 = 97, - TARGET_UNIT_PASSENGER_2 = 98, - TARGET_UNIT_PASSENGER_3 = 99, - TARGET_UNIT_PASSENGER_4 = 100, - TARGET_UNIT_PASSENGER_5 = 101, - TARGET_UNIT_PASSENGER_6 = 102, - TARGET_UNIT_PASSENGER_7 = 103, - TARGET_UNIT_AREA_PATH = 104, - TARGET_UNIT_UNK_105 = 105, // 1 spell - TARGET_DEST_UNK_110 = 110, // some kind of traj? -}; - -#define TOTAL_SPELL_TARGETS 105 - -enum SpellMissInfo -{ - SPELL_MISS_NONE = 0, - SPELL_MISS_MISS = 1, - SPELL_MISS_RESIST = 2, - SPELL_MISS_DODGE = 3, - SPELL_MISS_PARRY = 4, - SPELL_MISS_BLOCK = 5, - SPELL_MISS_EVADE = 6, - SPELL_MISS_IMMUNE = 7, - SPELL_MISS_IMMUNE2 = 8, - SPELL_MISS_DEFLECT = 9, - SPELL_MISS_ABSORB = 10, - SPELL_MISS_REFLECT = 11 -}; - -enum SpellHitType -{ - SPELL_HIT_TYPE_UNK1 = 0x00001, - SPELL_HIT_TYPE_CRIT = 0x00002, - SPELL_HIT_TYPE_UNK3 = 0x00004, - SPELL_HIT_TYPE_UNK4 = 0x00008, - SPELL_HIT_TYPE_UNK5 = 0x00010, // replace caster? - SPELL_HIT_TYPE_UNK6 = 0x00020 -}; - -enum SpellDmgClass -{ - SPELL_DAMAGE_CLASS_NONE = 0, - SPELL_DAMAGE_CLASS_MAGIC = 1, - SPELL_DAMAGE_CLASS_MELEE = 2, - SPELL_DAMAGE_CLASS_RANGED = 3 -}; - -enum SpellPreventionType -{ - SPELL_PREVENTION_TYPE_NONE = 0, - SPELL_PREVENTION_TYPE_SILENCE = 1, - SPELL_PREVENTION_TYPE_PACIFY = 2 -}; - -enum GameobjectTypes -{ - GAMEOBJECT_TYPE_DOOR = 0, - GAMEOBJECT_TYPE_BUTTON = 1, - GAMEOBJECT_TYPE_QUESTGIVER = 2, - GAMEOBJECT_TYPE_CHEST = 3, - GAMEOBJECT_TYPE_BINDER = 4, - GAMEOBJECT_TYPE_GENERIC = 5, - GAMEOBJECT_TYPE_TRAP = 6, - GAMEOBJECT_TYPE_CHAIR = 7, - GAMEOBJECT_TYPE_SPELL_FOCUS = 8, - GAMEOBJECT_TYPE_TEXT = 9, - GAMEOBJECT_TYPE_GOOBER = 10, - GAMEOBJECT_TYPE_TRANSPORT = 11, - GAMEOBJECT_TYPE_AREADAMAGE = 12, - GAMEOBJECT_TYPE_CAMERA = 13, - GAMEOBJECT_TYPE_MAP_OBJECT = 14, - GAMEOBJECT_TYPE_MO_TRANSPORT = 15, - GAMEOBJECT_TYPE_DUEL_ARBITER = 16, - GAMEOBJECT_TYPE_FISHINGNODE = 17, - GAMEOBJECT_TYPE_SUMMONING_RITUAL = 18, - GAMEOBJECT_TYPE_MAILBOX = 19, - GAMEOBJECT_TYPE_DO_NOT_USE = 20, - GAMEOBJECT_TYPE_GUARDPOST = 21, - GAMEOBJECT_TYPE_SPELLCASTER = 22, - GAMEOBJECT_TYPE_MEETINGSTONE = 23, - GAMEOBJECT_TYPE_FLAGSTAND = 24, - GAMEOBJECT_TYPE_FISHINGHOLE = 25, - GAMEOBJECT_TYPE_FLAGDROP = 26, - GAMEOBJECT_TYPE_MINI_GAME = 27, - GAMEOBJECT_TYPE_DO_NOT_USE_2 = 28, - GAMEOBJECT_TYPE_CAPTURE_POINT = 29, - GAMEOBJECT_TYPE_AURA_GENERATOR = 30, - GAMEOBJECT_TYPE_DUNGEON_DIFFICULTY = 31, - GAMEOBJECT_TYPE_BARBER_CHAIR = 32, - GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING = 33, - GAMEOBJECT_TYPE_GUILD_BANK = 34, - GAMEOBJECT_TYPE_TRAPDOOR = 35 -}; - -#define MAX_GAMEOBJECT_TYPE 36 // sending to client this or greater value can crash client. - -#define GAMEOBJECT_FISHINGNODE_ENTRY 35591 // Better to define it somewhere instead of hardcoding everywhere - -enum GameObjectFlags -{ - GO_FLAG_IN_USE = 0x00000001, //disables interaction while animated - GO_FLAG_LOCKED = 0x00000002, //require key, spell, event, etc to be opened. Makes "Locked" appear in tooltip - GO_FLAG_INTERACT_COND = 0x00000004, //cannot interact (condition to interact) - GO_FLAG_TRANSPORT = 0x00000008, //any kind of transport? Object can transport (elevator, boat, car) - GO_FLAG_UNK1 = 0x00000010, // - GO_FLAG_NODESPAWN = 0x00000020, //never despawn, typically for doors, they just change state - GO_FLAG_TRIGGERED = 0x00000040, //typically, summoned objects. Triggered by spell or other events - GO_FLAG_DAMAGED = 0x00000200, - GO_FLAG_DESTROYED = 0x00000400, -}; - -enum TextEmotes -{ - TEXTEMOTE_AGREE = 1, - TEXTEMOTE_AMAZE = 2, - TEXTEMOTE_ANGRY = 3, - TEXTEMOTE_APOLOGIZE = 4, - TEXTEMOTE_APPLAUD = 5, - TEXTEMOTE_BASHFUL = 6, - TEXTEMOTE_BECKON = 7, - TEXTEMOTE_BEG = 8, - TEXTEMOTE_BITE = 9, - TEXTEMOTE_BLEED = 10, - TEXTEMOTE_BLINK = 11, - TEXTEMOTE_BLUSH = 12, - TEXTEMOTE_BONK = 13, - TEXTEMOTE_BORED = 14, - TEXTEMOTE_BOUNCE = 15, - TEXTEMOTE_BRB = 16, - TEXTEMOTE_BOW = 17, - TEXTEMOTE_BURP = 18, - TEXTEMOTE_BYE = 19, - TEXTEMOTE_CACKLE = 20, - TEXTEMOTE_CHEER = 21, - TEXTEMOTE_CHICKEN = 22, - TEXTEMOTE_CHUCKLE = 23, - TEXTEMOTE_CLAP = 24, - TEXTEMOTE_CONFUSED = 25, - TEXTEMOTE_CONGRATULATE = 26, - TEXTEMOTE_COUGH = 27, - TEXTEMOTE_COWER = 28, - TEXTEMOTE_CRACK = 29, - TEXTEMOTE_CRINGE = 30, - TEXTEMOTE_CRY = 31, - TEXTEMOTE_CURIOUS = 32, - TEXTEMOTE_CURTSEY = 33, - TEXTEMOTE_DANCE = 34, - TEXTEMOTE_DRINK = 35, - TEXTEMOTE_DROOL = 36, - TEXTEMOTE_EAT = 37, - TEXTEMOTE_EYE = 38, - TEXTEMOTE_FART = 39, - TEXTEMOTE_FIDGET = 40, - TEXTEMOTE_FLEX = 41, - TEXTEMOTE_FROWN = 42, - TEXTEMOTE_GASP = 43, - TEXTEMOTE_GAZE = 44, - TEXTEMOTE_GIGGLE = 45, - TEXTEMOTE_GLARE = 46, - TEXTEMOTE_GLOAT = 47, - TEXTEMOTE_GREET = 48, - TEXTEMOTE_GRIN = 49, - TEXTEMOTE_GROAN = 50, - TEXTEMOTE_GROVEL = 51, - TEXTEMOTE_GUFFAW = 52, - TEXTEMOTE_HAIL = 53, - TEXTEMOTE_HAPPY = 54, - TEXTEMOTE_HELLO = 55, - TEXTEMOTE_HUG = 56, - TEXTEMOTE_HUNGRY = 57, - TEXTEMOTE_KISS = 58, - TEXTEMOTE_KNEEL = 59, - TEXTEMOTE_LAUGH = 60, - TEXTEMOTE_LAYDOWN = 61, - TEXTEMOTE_MESSAGE = 62, - TEXTEMOTE_MOAN = 63, - TEXTEMOTE_MOON = 64, - TEXTEMOTE_MOURN = 65, - TEXTEMOTE_NO = 66, - TEXTEMOTE_NOD = 67, - TEXTEMOTE_NOSEPICK = 68, - TEXTEMOTE_PANIC = 69, - TEXTEMOTE_PEER = 70, - TEXTEMOTE_PLEAD = 71, - TEXTEMOTE_POINT = 72, - TEXTEMOTE_POKE = 73, - TEXTEMOTE_PRAY = 74, - TEXTEMOTE_ROAR = 75, - TEXTEMOTE_ROFL = 76, - TEXTEMOTE_RUDE = 77, - TEXTEMOTE_SALUTE = 78, - TEXTEMOTE_SCRATCH = 79, - TEXTEMOTE_SEXY = 80, - TEXTEMOTE_SHAKE = 81, - TEXTEMOTE_SHOUT = 82, - TEXTEMOTE_SHRUG = 83, - TEXTEMOTE_SHY = 84, - TEXTEMOTE_SIGH = 85, - TEXTEMOTE_SIT = 86, - TEXTEMOTE_SLEEP = 87, - TEXTEMOTE_SNARL = 88, - TEXTEMOTE_SPIT = 89, - TEXTEMOTE_STARE = 90, - TEXTEMOTE_SURPRISED = 91, - TEXTEMOTE_SURRENDER = 92, - TEXTEMOTE_TALK = 93, - TEXTEMOTE_TALKEX = 94, - TEXTEMOTE_TALKQ = 95, - TEXTEMOTE_TAP = 96, - TEXTEMOTE_THANK = 97, - TEXTEMOTE_THREATEN = 98, - TEXTEMOTE_TIRED = 99, - TEXTEMOTE_VICTORY = 100, - TEXTEMOTE_WAVE = 101, - TEXTEMOTE_WELCOME = 102, - TEXTEMOTE_WHINE = 103, - TEXTEMOTE_WHISTLE = 104, - TEXTEMOTE_WORK = 105, - TEXTEMOTE_YAWN = 106, - TEXTEMOTE_BOGGLE = 107, - TEXTEMOTE_CALM = 108, - TEXTEMOTE_COLD = 109, - TEXTEMOTE_COMFORT = 110, - TEXTEMOTE_CUDDLE = 111, - TEXTEMOTE_DUCK = 112, - TEXTEMOTE_INSULT = 113, - TEXTEMOTE_INTRODUCE = 114, - TEXTEMOTE_JK = 115, - TEXTEMOTE_LICK = 116, - TEXTEMOTE_LISTEN = 117, - TEXTEMOTE_LOST = 118, - TEXTEMOTE_MOCK = 119, - TEXTEMOTE_PONDER = 120, - TEXTEMOTE_POUNCE = 121, - TEXTEMOTE_PRAISE = 122, - TEXTEMOTE_PURR = 123, - TEXTEMOTE_PUZZLE = 124, - TEXTEMOTE_RAISE = 125, - TEXTEMOTE_READY = 126, - TEXTEMOTE_SHIMMY = 127, - TEXTEMOTE_SHIVER = 128, - TEXTEMOTE_SHOO = 129, - TEXTEMOTE_SLAP = 130, - TEXTEMOTE_SMIRK = 131, - TEXTEMOTE_SNIFF = 132, - TEXTEMOTE_SNUB = 133, - TEXTEMOTE_SOOTHE = 134, - TEXTEMOTE_STINK = 135, - TEXTEMOTE_TAUNT = 136, - TEXTEMOTE_TEASE = 137, - TEXTEMOTE_THIRSTY = 138, - TEXTEMOTE_VETO = 139, - TEXTEMOTE_SNICKER = 140, - TEXTEMOTE_STAND = 141, - TEXTEMOTE_TICKLE = 142, - TEXTEMOTE_VIOLIN = 143, - TEXTEMOTE_SMILE = 163, - TEXTEMOTE_RASP = 183, - TEXTEMOTE_PITY = 203, - TEXTEMOTE_GROWL = 204, - TEXTEMOTE_BARK = 205, - TEXTEMOTE_SCARED = 223, - TEXTEMOTE_FLOP = 224, - TEXTEMOTE_LOVE = 225, - TEXTEMOTE_MOO = 226, - TEXTEMOTE_OPENFIRE = 327, - TEXTEMOTE_FLIRT = 328, - TEXTEMOTE_JOKE = 329, - TEXTEMOTE_COMMEND = 243, - TEXTEMOTE_WINK = 363, - TEXTEMOTE_PAT = 364, - TEXTEMOTE_SERIOUS = 365, - TEXTEMOTE_MOUNTSPECIAL = 366, - TEXTEMOTE_GOODLUCK = 367, - TEXTEMOTE_BLAME = 368, - TEXTEMOTE_BLANK = 369, - TEXTEMOTE_BRANDISH = 370, - TEXTEMOTE_BREATH = 371, - TEXTEMOTE_DISAGREE = 372, - TEXTEMOTE_DOUBT = 373, - TEXTEMOTE_EMBARRASS = 374, - TEXTEMOTE_ENCOURAGE = 375, - TEXTEMOTE_ENEMY = 376, - TEXTEMOTE_EYEBROW = 377, - TEXTEMOTE_TOAST = 378 -}; - -enum Emote -{ - EMOTE_ONESHOT_NONE = 0, - EMOTE_ONESHOT_TALK = 1, - EMOTE_ONESHOT_BOW = 2, - EMOTE_ONESHOT_WAVE = 3, - EMOTE_ONESHOT_CHEER = 4, - EMOTE_ONESHOT_EXCLAMATION = 5, - EMOTE_ONESHOT_QUESTION = 6, - EMOTE_ONESHOT_EAT = 7, - EMOTE_STATE_DANCE = 10, - EMOTE_ONESHOT_LAUGH = 11, - EMOTE_STATE_SLEEP = 12, - EMOTE_STATE_SIT = 13, - EMOTE_ONESHOT_RUDE = 14, - EMOTE_ONESHOT_ROAR = 15, - EMOTE_ONESHOT_KNEEL = 16, - EMOTE_ONESHOT_KISS = 17, - EMOTE_ONESHOT_CRY = 18, - EMOTE_ONESHOT_CHICKEN = 19, - EMOTE_ONESHOT_BEG = 20, - EMOTE_ONESHOT_APPLAUD = 21, - EMOTE_ONESHOT_SHOUT = 22, - EMOTE_ONESHOT_FLEX = 23, - EMOTE_ONESHOT_SHY = 24, - EMOTE_ONESHOT_POINT = 25, - EMOTE_STATE_STAND = 26, - EMOTE_STATE_READYUNARMED = 27, - EMOTE_STATE_WORK_SHEATHED = 28, - EMOTE_STATE_POINT = 29, - EMOTE_STATE_NONE = 30, - EMOTE_ONESHOT_WOUND = 33, - EMOTE_ONESHOT_WOUNDCRITICAL = 34, - EMOTE_ONESHOT_ATTACKUNARMED = 35, - EMOTE_ONESHOT_ATTACK1H = 36, - EMOTE_ONESHOT_ATTACK2HTIGHT = 37, - EMOTE_ONESHOT_ATTACK2HLOOSE = 38, - EMOTE_ONESHOT_PARRYUNARMED = 39, - EMOTE_ONESHOT_PARRYSHIELD = 43, - EMOTE_ONESHOT_READYUNARMED = 44, - EMOTE_ONESHOT_READY1H = 45, - EMOTE_ONESHOT_READYBOW = 48, - EMOTE_ONESHOT_SPELLPRECAST = 50, - EMOTE_ONESHOT_SPELLCAST = 51, - EMOTE_ONESHOT_BATTLEROAR = 53, - EMOTE_ONESHOT_SPECIALATTACK1H = 54, - EMOTE_ONESHOT_KICK = 60, - EMOTE_ONESHOT_ATTACKTHROWN = 61, - EMOTE_STATE_STUN = 64, - EMOTE_STATE_DEAD = 65, - EMOTE_ONESHOT_SALUTE = 66, - EMOTE_STATE_KNEEL = 68, - EMOTE_STATE_USESTANDING = 69, - EMOTE_ONESHOT_WAVE_NOSHEATHE = 70, - EMOTE_ONESHOT_CHEER_NOSHEATHE = 71, - EMOTE_ONESHOT_EAT_NOSHEATHE = 92, - EMOTE_STATE_STUN_NOSHEATHE = 93, - EMOTE_ONESHOT_DANCE = 94, - EMOTE_ONESHOT_SALUTE_NOSHEATH = 113, - EMOTE_STATE_USESTANDING_NOSHEATHE = 133, - EMOTE_ONESHOT_LAUGH_NOSHEATHE = 153, - EMOTE_STATE_WORK = 173, - EMOTE_STATE_SPELLPRECAST = 193, - EMOTE_ONESHOT_READYRIFLE = 213, - EMOTE_STATE_READYRIFLE = 214, - EMOTE_STATE_WORK_MINING = 233, - EMOTE_STATE_WORK_CHOPWOOD = 234, - EMOTE_STATE_APPLAUD = 253, - EMOTE_ONESHOT_LIFTOFF = 254, - EMOTE_ONESHOT_YES = 273, - EMOTE_ONESHOT_NO = 274, - EMOTE_ONESHOT_TRAIN = 275, - EMOTE_ONESHOT_LAND = 293, - EMOTE_STATE_AT_EASE = 313, - EMOTE_STATE_READY1H = 333, - EMOTE_STATE_SPELLKNEELSTART = 353, - EMOTE_STATE_SUBMERGED = 373, - EMOTE_ONESHOT_SUBMERGE = 374, - EMOTE_STATE_READY2H = 375, - EMOTE_STATE_READYBOW = 376, - EMOTE_ONESHOT_MOUNTSPECIAL = 377, - EMOTE_STATE_TALK = 378, - EMOTE_STATE_FISHING = 379, - EMOTE_ONESHOT_FISHING = 380, - EMOTE_ONESHOT_LOOT = 381, - EMOTE_STATE_WHIRLWIND = 382, - EMOTE_STATE_DROWNED = 383, - EMOTE_STATE_HOLD_BOW = 384, - EMOTE_STATE_HOLD_RIFLE = 385, - EMOTE_STATE_HOLD_THROWN = 386, - EMOTE_ONESHOT_DROWN = 387, - EMOTE_ONESHOT_STOMP = 388, - EMOTE_ONESHOT_ATTACKOFF = 389, - EMOTE_ONESHOT_ATTACKOFFPIERCE = 390, - EMOTE_STATE_ROAR = 391, - EMOTE_STATE_LAUGH = 392, - EMOTE_ONESHOT_CREATURE_SPECIAL = 393, - EMOTE_ONESHOT_JUMPLANDRUN = 394, - EMOTE_ONESHOT_JUMPEND = 395, - EMOTE_ONESHOT_TALK_NOSHEATHE = 396, - EMOTE_ONESHOT_POINT_NOSHEATHE = 397, - EMOTE_STATE_CANNIBALIZE = 398, - EMOTE_ONESHOT_JUMPSTART = 399, - EMOTE_STATE_DANCESPECIAL = 400, - EMOTE_ONESHOT_DANCESPECIAL = 401, - EMOTE_ONESHOT_CUSTOMSPELL01 = 402, - EMOTE_ONESHOT_CUSTOMSPELL02 = 403, - EMOTE_ONESHOT_CUSTOMSPELL03 = 404, - EMOTE_ONESHOT_CUSTOMSPELL04 = 405, - EMOTE_ONESHOT_CUSTOMSPELL05 = 406, - EMOTE_ONESHOT_CUSTOMSPELL06 = 407, - EMOTE_ONESHOT_CUSTOMSPELL07 = 408, - EMOTE_ONESHOT_CUSTOMSPELL08 = 409, - EMOTE_ONESHOT_CUSTOMSPELL09 = 410, - EMOTE_ONESHOT_CUSTOMSPELL10 = 411, - EMOTE_STATE_EXCLAIM = 412, - EMOTE_STATE_DANCE_CUSTOM = 413, - EMOTE_STATE_SIT_CHAIR_MED = 415, - EMOTE_STATE_CUSTOM_SPELL_01 = 416, - EMOTE_STATE_CUSTOM_SPELL_02 = 417, - EMOTE_STATE_EAT = 418, - EMOTE_STATE_CUSTOM_SPELL_04 = 419, - EMOTE_STATE_CUSTOM_SPELL_03 = 420, - EMOTE_STATE_CUSTOM_SPELL_05 = 421, - EMOTE_STATE_SPELLEFFECT_HOLD = 422, - EMOTE_STATE_EAT_NO_SHEATHE = 423, - EMOTE_STATE_MOUNT = 424, - EMOTE_STATE_READY2HL = 425, - EMOTE_STATE_SIT_CHAIR_HIGH = 426, - EMOTE_STATE_FALL = 427, - EMOTE_STATE_LOOT = 428, - EMOTE_STATE_SUBMERGED_NEW = 429, - EMOTE_ONESHOT_COWER = 430, - EMOTE_STATE_COWER = 431, - EMOTE_ONESHOT_USESTANDING = 432, - EMOTE_STATE_STEALTH_STAND = 433, - EMOTE_ONESHOT_OMNICAST_GHOUL = 434, - EMOTE_ONESHOT_ATTACKBOW = 435, - EMOTE_ONESHOT_ATTACKRIFLE = 436, - EMOTE_STATE_SWIM_IDLE = 437, - EMOTE_STATE_ATTACK_UNARMED = 438, - EMOTE_ONESHOT_SPELLCAST_W_SOUND = 439, - EMOTE_ONESHOT_DODGE = 440, - EMOTE_ONESHOT_PARRY1H = 441, - EMOTE_ONESHOT_PARRY2H = 442, - EMOTE_ONESHOT_PARRY2HL = 443, - EMOTE_STATE_FLYFALL = 444, - EMOTE_ONESHOT_FLYDEATH = 445, - EMOTE_STATE_FLY_FALL = 446, - EMOTE_ONESHOT_FLY_SIT_GROUND_DOWN = 447, - EMOTE_ONESHOT_FLY_SIT_GROUND_UP = 448, - EMOTE_ONESHOT_EMERGE = 449, - EMOTE_ONESHOT_DRAGONSPIT = 450, - EMOTE_STATE_SPECIALUNARMED = 451, - EMOTE_ONESHOT_FLYGRAB = 452, - EMOTE_STATE_FLYGRABCLOSED = 453, - EMOTE_ONESHOT_FLYGRABTHROWN = 454, - EMOTE_STATE_FLY_SIT_GROUND = 455, - EMOTE_STATE_WALKBACKWARDS = 456, - EMOTE_ONESHOT_FLYTALK = 457, - EMOTE_ONESHOT_FLYATTACK1H = 458, - EMOTE_STATE_CUSTOMSPELL08 = 459, - EMOTE_ONESHOT_FLY_DRAGONSPIT = 460, - EMOTE_STATE_SIT_CHAIR_LOW = 461, - EMOTE_ONE_SHOT_STUN = 462, - EMOTE_ONESHOT_SPELLCAST_OMNI = 463, - EMOTE_STATE_READYTHROWN = 464 -}; - -enum Anim -{ - ANIM_STAND = 0x0, - ANIM_DEATH = 0x1, - ANIM_SPELL = 0x2, - ANIM_STOP = 0x3, - ANIM_WALK = 0x4, - ANIM_RUN = 0x5, - ANIM_DEAD = 0x6, - ANIM_RISE = 0x7, - ANIM_STANDWOUND = 0x8, - ANIM_COMBATWOUND = 0x9, - ANIM_COMBATCRITICAL = 0xA, - ANIM_SHUFFLE_LEFT = 0xB, - ANIM_SHUFFLE_RIGHT = 0xC, - ANIM_WALK_BACKWARDS = 0xD, - ANIM_STUN = 0xE, - ANIM_HANDS_CLOSED = 0xF, - ANIM_ATTACKUNARMED = 0x10, - ANIM_ATTACK1H = 0x11, - ANIM_ATTACK2HTIGHT = 0x12, - ANIM_ATTACK2HLOOSE = 0x13, - ANIM_PARRYUNARMED = 0x14, - ANIM_PARRY1H = 0x15, - ANIM_PARRY2HTIGHT = 0x16, - ANIM_PARRY2HLOOSE = 0x17, - ANIM_PARRYSHIELD = 0x18, - ANIM_READYUNARMED = 0x19, - ANIM_READY1H = 0x1A, - ANIM_READY2HTIGHT = 0x1B, - ANIM_READY2HLOOSE = 0x1C, - ANIM_READYBOW = 0x1D, - ANIM_DODGE = 0x1E, - ANIM_SPELLPRECAST = 0x1F, - ANIM_SPELLCAST = 0x20, - ANIM_SPELLCASTAREA = 0x21, - ANIM_NPCWELCOME = 0x22, - ANIM_NPCGOODBYE = 0x23, - ANIM_BLOCK = 0x24, - ANIM_JUMPSTART = 0x25, - ANIM_JUMP = 0x26, - ANIM_JUMPEND = 0x27, - ANIM_FALL = 0x28, - ANIM_SWIMIDLE = 0x29, - ANIM_SWIM = 0x2A, - ANIM_SWIM_LEFT = 0x2B, - ANIM_SWIM_RIGHT = 0x2C, - ANIM_SWIM_BACKWARDS = 0x2D, - ANIM_ATTACKBOW = 0x2E, - ANIM_FIREBOW = 0x2F, - ANIM_READYRIFLE = 0x30, - ANIM_ATTACKRIFLE = 0x31, - ANIM_LOOT = 0x32, - ANIM_SPELL_PRECAST_DIRECTED = 0x33, - ANIM_SPELL_PRECAST_OMNI = 0x34, - ANIM_SPELL_CAST_DIRECTED = 0x35, - ANIM_SPELL_CAST_OMNI = 0x36, - ANIM_SPELL_BATTLEROAR = 0x37, - ANIM_SPELL_READYABILITY = 0x38, - ANIM_SPELL_SPECIAL1H = 0x39, - ANIM_SPELL_SPECIAL2H = 0x3A, - ANIM_SPELL_SHIELDBASH = 0x3B, - ANIM_EMOTE_TALK = 0x3C, - ANIM_EMOTE_EAT = 0x3D, - ANIM_EMOTE_WORK = 0x3E, - ANIM_EMOTE_USE_STANDING = 0x3F, - ANIM_EMOTE_EXCLAMATION = 0x40, - ANIM_EMOTE_QUESTION = 0x41, - ANIM_EMOTE_BOW = 0x42, - ANIM_EMOTE_WAVE = 0x43, - ANIM_EMOTE_CHEER = 0x44, - ANIM_EMOTE_DANCE = 0x45, - ANIM_EMOTE_LAUGH = 0x46, - ANIM_EMOTE_SLEEP = 0x47, - ANIM_EMOTE_SIT_GROUND = 0x48, - ANIM_EMOTE_RUDE = 0x49, - ANIM_EMOTE_ROAR = 0x4A, - ANIM_EMOTE_KNEEL = 0x4B, - ANIM_EMOTE_KISS = 0x4C, - ANIM_EMOTE_CRY = 0x4D, - ANIM_EMOTE_CHICKEN = 0x4E, - ANIM_EMOTE_BEG = 0x4F, - ANIM_EMOTE_APPLAUD = 0x50, - ANIM_EMOTE_SHOUT = 0x51, - ANIM_EMOTE_FLEX = 0x52, - ANIM_EMOTE_SHY = 0x53, - ANIM_EMOTE_POINT = 0x54, - ANIM_ATTACK1HPIERCE = 0x55, - ANIM_ATTACK2HLOOSEPIERCE = 0x56, - ANIM_ATTACKOFF = 0x57, - ANIM_ATTACKOFFPIERCE = 0x58, - ANIM_SHEATHE = 0x59, - ANIM_HIPSHEATHE = 0x5A, - ANIM_MOUNT = 0x5B, - ANIM_RUN_LEANRIGHT = 0x5C, - ANIM_RUN_LEANLEFT = 0x5D, - ANIM_MOUNT_SPECIAL = 0x5E, - ANIM_KICK = 0x5F, - ANIM_SITDOWN = 0x60, - ANIM_SITTING = 0x61, - ANIM_SITUP = 0x62, - ANIM_SLEEPDOWN = 0x63, - ANIM_SLEEPING = 0x64, - ANIM_SLEEPUP = 0x65, - ANIM_SITCHAIRLOW = 0x66, - ANIM_SITCHAIRMEDIUM = 0x67, - ANIM_SITCHAIRHIGH = 0x68, - ANIM_LOADBOW = 0x69, - ANIM_LOADRIFLE = 0x6A, - ANIM_ATTACKTHROWN = 0x6B, - ANIM_READYTHROWN = 0x6C, - ANIM_HOLDBOW = 0x6D, - ANIM_HOLDRIFLE = 0x6E, - ANIM_HOLDTHROWN = 0x6F, - ANIM_LOADTHROWN = 0x70, - ANIM_EMOTE_SALUTE = 0x71, - ANIM_KNEELDOWN = 0x72, - ANIM_KNEELING = 0x73, - ANIM_KNEELUP = 0x74, - ANIM_ATTACKUNARMEDOFF = 0x75, - ANIM_SPECIALUNARMED = 0x76, - ANIM_STEALTHWALK = 0x77, - ANIM_STEALTHSTAND = 0x78, - ANIM_KNOCKDOWN = 0x79, - ANIM_EATING = 0x7A, - ANIM_USESTANDINGLOOP = 0x7B, - ANIM_CHANNELCASTDIRECTED = 0x7C, - ANIM_CHANNELCASTOMNI = 0x7D, - ANIM_WHIRLWIND = 0x7E, - ANIM_BIRTH = 0x7F, - ANIM_USESTANDINGSTART = 0x80, - ANIM_USESTANDINGEND = 0x81, - ANIM_HOWL = 0x82, - ANIM_DROWN = 0x83, - ANIM_DROWNED = 0x84, - ANIM_FISHINGCAST = 0x85, - ANIM_FISHINGLOOP = 0x86, - ANIM_FLY = 0x87, - ANIM_EMOTE_WORK_NO_SHEATHE = 0x88, - ANIM_EMOTE_STUN_NO_SHEATHE = 0x89, - ANIM_EMOTE_USE_STANDING_NO_SHEATHE= 0x8A, - ANIM_SPELL_SLEEP_DOWN = 0x8B, - ANIM_SPELL_KNEEL_START = 0x8C, - ANIM_SPELL_KNEEL_LOOP = 0x8D, - ANIM_SPELL_KNEEL_END = 0x8E, - ANIM_SPRINT = 0x8F, - ANIM_IN_FIGHT = 0x90, - - ANIM_GAMEOBJ_SPAWN = 145, - ANIM_GAMEOBJ_CLOSE = 146, - ANIM_GAMEOBJ_CLOSED = 147, - ANIM_GAMEOBJ_OPEN = 148, - ANIM_GAMEOBJ_OPENED = 149, - ANIM_GAMEOBJ_DESTROY = 150, - ANIM_GAMEOBJ_DESTROYED = 151, - ANIM_GAMEOBJ_REBUILD = 152, - ANIM_GAMEOBJ_CUSTOM0 = 153, - ANIM_GAMEOBJ_CUSTOM1 = 154, - ANIM_GAMEOBJ_CUSTOM2 = 155, - ANIM_GAMEOBJ_CUSTOM3 = 156, - ANIM_GAMEOBJ_DESPAWN = 157, - ANIM_HOLD = 158, - ANIM_DECAY = 159, - ANIM_BOWPULL = 160, - ANIM_BOWRELEASE = 161, - ANIM_SHIPSTART = 162, - ANIM_SHIPMOVEING = 163, - ANIM_SHIPSTOP = 164, - ANIM_GROUPARROW = 165, - ANIM_ARROW = 166, - ANIM_CORPSEARROW = 167, - ANIM_GUIDEARROW = 168, - ANIM_SWAY = 169, - ANIM_DRUIDCATPOUNCE = 170, - ANIM_DRUIDCATRIP = 171, - ANIM_DRUIDCATRAKE = 172, - ANIM_DRUIDCATRAVAGE = 173, - ANIM_DRUIDCATCLAW = 174, - ANIM_DRUIDCATCOWER = 175, - ANIM_DRUIDBEARSWIPE = 176, - ANIM_DRUIDBEARBITE = 177, - ANIM_DRUIDBEARMAUL = 178, - ANIM_DRUIDBEARBASH = 179, - ANIM_DRAGONTAIL = 180, - ANIM_DRAGONSTOMP = 181, - ANIM_DRAGONSPIT = 182, - ANIM_DRAGONSPITHOVER = 183, - ANIM_DRAGONSPITFLY = 184, - ANIM_EMOTEYES = 185, - ANIM_EMOTENO = 186, - ANIM_JUMPLANDRUN = 187, - ANIM_LOOTHOLD = 188, - ANIM_LOOTUP = 189, - ANIM_STANDHIGH = 190, - ANIM_IMPACT = 191, - ANIM_LIFTOFF = 192, - ANIM_HOVER = 193, - ANIM_SUCCUBUSENTICE = 194, - ANIM_EMOTETRAIN = 195, - ANIM_EMOTEDEAD = 196, - ANIM_EMOTEDANCEONCE = 197, - ANIM_DEFLECT = 198, - ANIM_EMOTEEATNOSHEATHE = 199, - ANIM_LAND = 200, - ANIM_SUBMERGE = 201, - ANIM_SUBMERGED = 202, - ANIM_CANNIBALIZE = 203, - ANIM_ARROWBIRTH = 204, - ANIM_GROURARROWBIRTH = 205, - ANIM_CORPSEARROWBIRTH = 206, - ANIM_GUIDEARROWBIRTH = 207, - ANIM_EMOTETALKNOSHEATHE = 208, - ANIM_EMOTEPOINTNOSHEATHE = 209, - ANIM_EMOTESALUTENOSHEATHE = 210, - ANIM_EMOTEDANCESPECIAL = 211, - ANIM_MUTILATE = 212, - ANIM_CUSTOMSPELL01 = 213, - ANIM_CUSTOMSPELL02 = 214, - ANIM_CUSTOMSPELL03 = 215, - ANIM_CUSTOMSPELL04 = 216, - ANIM_CUSTOMSPELL05 = 217, - ANIM_CUSTOMSPELL06 = 218, - ANIM_CUSTOMSPELL07 = 219, - ANIM_CUSTOMSPELL08 = 220, - ANIM_CUSTOMSPELL09 = 221, - ANIM_CUSTOMSPELL10 = 222, - ANIM_StealthRun = 223 -}; - -enum LockKeyType -{ - LOCK_KEY_NONE = 0, - LOCK_KEY_ITEM = 1, - LOCK_KEY_SKILL = 2 -}; - -enum LockType -{ - LOCKTYPE_PICKLOCK = 1, - LOCKTYPE_HERBALISM = 2, - LOCKTYPE_MINING = 3, - LOCKTYPE_DISARM_TRAP = 4, - LOCKTYPE_OPEN = 5, - LOCKTYPE_TREASURE = 6, - LOCKTYPE_CALCIFIED_ELVEN_GEMS = 7, - LOCKTYPE_CLOSE = 8, - LOCKTYPE_ARM_TRAP = 9, - LOCKTYPE_QUICK_OPEN = 10, - LOCKTYPE_QUICK_CLOSE = 11, - LOCKTYPE_OPEN_TINKERING = 12, - LOCKTYPE_OPEN_KNEELING = 13, - LOCKTYPE_OPEN_ATTACKING = 14, - LOCKTYPE_GAHZRIDIAN = 15, - LOCKTYPE_BLASTING = 16, - LOCKTYPE_SLOW_OPEN = 17, - LOCKTYPE_SLOW_CLOSE = 18, - LOCKTYPE_FISHING = 19, - LOCKTYPE_INSCRIPTION = 20, - LOCKTYPE_OPEN_FROM_VEHICLE = 21 -}; - -enum TrainerType // this is important type for npcs! -{ - TRAINER_TYPE_CLASS = 0, - TRAINER_TYPE_MOUNTS = 1, // on blizz it's 2 - TRAINER_TYPE_TRADESKILLS = 2, - TRAINER_TYPE_PETS = 3 -}; - -#define MAX_TRAINER_TYPE 4 - -// CreatureType.dbc -enum CreatureType -{ - CREATURE_TYPE_BEAST = 1, - CREATURE_TYPE_DRAGONKIN = 2, - CREATURE_TYPE_DEMON = 3, - CREATURE_TYPE_ELEMENTAL = 4, - CREATURE_TYPE_GIANT = 5, - CREATURE_TYPE_UNDEAD = 6, - CREATURE_TYPE_HUMANOID = 7, - CREATURE_TYPE_CRITTER = 8, - CREATURE_TYPE_MECHANICAL = 9, - CREATURE_TYPE_NOT_SPECIFIED = 10, - CREATURE_TYPE_TOTEM = 11, - CREATURE_TYPE_NON_COMBAT_PET = 12, - CREATURE_TYPE_GAS_CLOUD = 13 -}; - -uint32 const CREATURE_TYPEMASK_DEMON_OR_UNDEAD = (1 << (CREATURE_TYPE_DEMON-1)) | (1 << (CREATURE_TYPE_UNDEAD-1)); -uint32 const CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD = (1 << (CREATURE_TYPE_HUMANOID-1)) | (1 << (CREATURE_TYPE_UNDEAD-1)); -uint32 const CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL = (1 << (CREATURE_TYPE_MECHANICAL-1)) | (1 << (CREATURE_TYPE_ELEMENTAL-1)); - -// CreatureFamily.dbc -enum CreatureFamily -{ - CREATURE_FAMILY_WOLF = 1, - CREATURE_FAMILY_CAT = 2, - CREATURE_FAMILY_SPIDER = 3, - CREATURE_FAMILY_BEAR = 4, - CREATURE_FAMILY_BOAR = 5, - CREATURE_FAMILY_CROCOLISK = 6, - CREATURE_FAMILY_CARRION_BIRD = 7, - CREATURE_FAMILY_CRAB = 8, - CREATURE_FAMILY_GORILLA = 9, - CREATURE_FAMILY_HORSE_CUSTOM = 10, // not exist in DBC but used for horse like beasts in DB - CREATURE_FAMILY_RAPTOR = 11, - CREATURE_FAMILY_TALLSTRIDER = 12, - CREATURE_FAMILY_FELHUNTER = 15, - CREATURE_FAMILY_VOIDWALKER = 16, - CREATURE_FAMILY_SUCCUBUS = 17, - CREATURE_FAMILY_DOOMGUARD = 19, - CREATURE_FAMILY_SCORPID = 20, - CREATURE_FAMILY_TURTLE = 21, - CREATURE_FAMILY_IMP = 23, - CREATURE_FAMILY_BAT = 24, - CREATURE_FAMILY_HYENA = 25, - CREATURE_FAMILY_BIRD_OF_PREY = 26, - CREATURE_FAMILY_WIND_SERPENT = 27, - CREATURE_FAMILY_REMOTE_CONTROL = 28, - CREATURE_FAMILY_FELGUARD = 29, - CREATURE_FAMILY_DRAGONHAWK = 30, - CREATURE_FAMILY_RAVAGER = 31, - CREATURE_FAMILY_WARP_STALKER = 32, - CREATURE_FAMILY_SPOREBAT = 33, - CREATURE_FAMILY_NETHER_RAY = 34, - CREATURE_FAMILY_SERPENT = 35, - CREATURE_FAMILY_MOTH = 37, - CREATURE_FAMILY_CHIMAERA = 38, - CREATURE_FAMILY_DEVILSAUR = 39, - CREATURE_FAMILY_GHOUL = 40, - CREATURE_FAMILY_SILITHID = 41, - CREATURE_FAMILY_WORM = 42, - CREATURE_FAMILY_RHINO = 43, - CREATURE_FAMILY_WASP = 44, - CREATURE_FAMILY_CORE_HOUND = 45, - CREATURE_FAMILY_SPIRIT_BEAST = 46 -}; - -enum CreatureTypeFlags -{ - CREATURE_TYPEFLAGS_TAMEABLE = 0x000001, // Tameable by any hunter - CREATURE_TYPEFLAGS_GHOST = 0x000002, // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow? - CREATURE_TYPEFLAGS_UNK3 = 0x000004, - CREATURE_TYPEFLAGS_UNK4 = 0x000008, - CREATURE_TYPEFLAGS_UNK5 = 0x000010, - CREATURE_TYPEFLAGS_UNK6 = 0x000020, - CREATURE_TYPEFLAGS_UNK7 = 0x000040, - CREATURE_TYPEFLAGS_UNK8 = 0x000080, - CREATURE_TYPEFLAGS_HERBLOOT = 0x000100, // Can be looted by herbalist - CREATURE_TYPEFLAGS_MININGLOOT = 0x000200, // Can be looted by miner - CREATURE_TYPEFLAGS_UNK11 = 0x000400, - CREATURE_TYPEFLAGS_UNK12 = 0x000800, // ? Related to mounts in some way. If mounted, fight mounted, mount appear as independant when rider dies? - CREATURE_TYPEFLAGS_UNK13 = 0x001000, // ? Can aid any player in combat if in range? - CREATURE_TYPEFLAGS_UNK14 = 0x002000, - CREATURE_TYPEFLAGS_UNK15 = 0x004000, // ? Possibly not in use - CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x008000, // Can be looted by engineer - CREATURE_TYPEFLAGS_EXOTIC = 0x010000, // Can be tamed by hunter as exotic pet - CREATURE_TYPEFLAGS_UNK18 = 0x020000, // ? Related to vehicles/pvp? - CREATURE_TYPEFLAGS_UNK19 = 0x040000, // ? Related to vehicle/siege weapons? - CREATURE_TYPEFLAGS_UNK20 = 0x080000, - CREATURE_TYPEFLAGS_UNK21 = 0x100000, - CREATURE_TYPEFLAGS_UNK22 = 0x200000, - CREATURE_TYPEFLAGS_UNK23 = 0x400000, - CREATURE_TYPEFLAGS_UNK24 = 0x800000 // ? First seen in 3.2.2. Related to banner/backpack of creature/companion? -}; - -enum CreatureEliteType -{ - CREATURE_ELITE_NORMAL = 0, - CREATURE_ELITE_ELITE = 1, - CREATURE_ELITE_RAREELITE = 2, - CREATURE_ELITE_WORLDBOSS = 3, - CREATURE_ELITE_RARE = 4, - CREATURE_UNKNOWN = 5 // found in 2.2.3 for 2 mobs -}; - -// values based at Holidays.dbc -enum HolidayIds -{ - HOLIDAY_NONE = 0, - - HOLIDAY_FIREWORKS_SPECTACULAR = 62, - HOLIDAY_FEAST_OF_WINTER_VEIL = 141, - HOLIDAY_NOBLEGARDEN = 181, - HOLIDAY_CHILDRENS_WEEK = 201, - HOLIDAY_CALL_TO_ARMS_AV = 283, - HOLIDAY_CALL_TO_ARMS_WS = 284, - HOLIDAY_CALL_TO_ARMS_AB = 285, - HOLIDAY_FISHING_EXTRAVAGANZA = 301, - HOLIDAY_HARVEST_FESTIVAL = 321, - HOLIDAY_HALLOWS_END = 324, - HOLIDAY_LUNAR_FESTIVAL = 327, - HOLIDAY_LOVE_IS_IN_THE_AIR = 335, - HOLIDAY_FIRE_FESTIVAL = 341, - HOLIDAY_CALL_TO_ARMS_EY = 353, - HOLIDAY_BREWFEST = 372, - HOLIDAY_DARKMOON_FAIRE_ELWYNN = 374, - HOLIDAY_DARKMOON_FAIRE_THUNDER = 375, - HOLIDAY_DARKMOON_FAIRE_SHATTRATH = 376, - HOLIDAY_PIRATES_DAY = 398, - HOLIDAY_CALL_TO_ARMS_SA = 400, - HOLIDAY_PILGRIMS_BOUNTY = 404, - HOLIDAY_WOTLK_LAUNCH = 406, - HOLIDAY_DAY_OF_DEAD = 409, - HOLIDAY_CALL_TO_ARMS_ISLE_OF_C = 420 -}; - -// values based at QuestInfo.dbc -enum QuestTypes -{ - QUEST_TYPE_ELITE = 1, - QUEST_TYPE_LIFE = 21, - QUEST_TYPE_PVP = 41, - QUEST_TYPE_RAID = 62, - QUEST_TYPE_DUNGEON = 81, - QUEST_TYPE_WORLD_EVENT = 82, - QUEST_TYPE_LEGENDARY = 83, - QUEST_TYPE_ESCORT = 84, - QUEST_TYPE_HEROIC = 85, - QUEST_TYPE_RAID_10 = 88, - QUEST_TYPE_RAID_25 = 89 -}; - -// values based at QuestSort.dbc -enum QuestSort -{ - QUEST_SORT_EPIC = 1, - QUEST_SORT_WAILING_CAVERNS_OLD = 21, - QUEST_SORT_SEASONAL = 22, - QUEST_SORT_UNDERCITY_OLD = 23, - QUEST_SORT_HERBALISM = 24, - QUEST_SORT_BATTLEGROUNDS = 25, - QUEST_SORT_ULDAMN_OLD = 41, - QUEST_SORT_WARLOCK = 61, - QUEST_SORT_WARRIOR = 81, - QUEST_SORT_SHAMAN = 82, - QUEST_SORT_FISHING = 101, - QUEST_SORT_BLACKSMITHING = 121, - QUEST_SORT_PALADIN = 141, - QUEST_SORT_MAGE = 161, - QUEST_SORT_ROGUE = 162, - QUEST_SORT_ALCHEMY = 181, - QUEST_SORT_LEATHERWORKING = 182, - QUEST_SORT_ENGINERING = 201, - QUEST_SORT_TREASURE_MAP = 221, - QUEST_SORT_SUNKEN_TEMPLE_OLD = 241, - QUEST_SORT_HUNTER = 261, - QUEST_SORT_PRIEST = 262, - QUEST_SORT_DRUID = 263, - QUEST_SORT_TAILORING = 264, - QUEST_SORT_SPECIAL = 284, - QUEST_SORT_COOKING = 304, - QUEST_SORT_FIRST_AID = 324, - QUEST_SORT_LEGENDARY = 344, - QUEST_SORT_DARKMOON_FAIRE = 364, - QUEST_SORT_AHN_QIRAJ_WAR = 365, - QUEST_SORT_LUNAR_FESTIVAL = 366, - QUEST_SORT_REPUTATION = 367, - QUEST_SORT_INVASION = 368, - QUEST_SORT_MIDSUMMER = 369, - QUEST_SORT_BREWFEST = 370, - QUEST_SORT_INSCRIPTION = 371, - QUEST_SORT_DEATH_KNIGHT = 372, - QUEST_SORT_JEWELCRAFTING = 373 -}; - -inline uint8 ClassByQuestSort(int32 QuestSort) -{ - switch(QuestSort) - { - case QUEST_SORT_WARLOCK: return CLASS_WARLOCK; - case QUEST_SORT_WARRIOR: return CLASS_WARRIOR; - case QUEST_SORT_SHAMAN: return CLASS_SHAMAN; - case QUEST_SORT_PALADIN: return CLASS_PALADIN; - case QUEST_SORT_MAGE: return CLASS_MAGE; - case QUEST_SORT_ROGUE: return CLASS_ROGUE; - case QUEST_SORT_HUNTER: return CLASS_HUNTER; - case QUEST_SORT_PRIEST: return CLASS_PRIEST; - case QUEST_SORT_DRUID: return CLASS_DRUID; - case QUEST_SORT_DEATH_KNIGHT: return CLASS_DEATH_KNIGHT; - } - return 0; -} - -enum SkillType -{ - SKILL_NONE = 0, - - SKILL_FROST = 6, - SKILL_FIRE = 8, - SKILL_ARMS = 26, - SKILL_COMBAT = 38, - SKILL_SUBTLETY = 39, - SKILL_SWORDS = 43, - SKILL_AXES = 44, - SKILL_BOWS = 45, - SKILL_GUNS = 46, - SKILL_BEAST_MASTERY = 50, - SKILL_SURVIVAL = 51, - SKILL_MACES = 54, - SKILL_2H_SWORDS = 55, - SKILL_HOLY = 56, - SKILL_SHADOW = 78, - SKILL_DEFENSE = 95, - SKILL_LANG_COMMON = 98, - SKILL_RACIAL_DWARVEN = 101, - SKILL_LANG_ORCISH = 109, - SKILL_LANG_DWARVEN = 111, - SKILL_LANG_DARNASSIAN = 113, - SKILL_LANG_TAURAHE = 115, - SKILL_DUAL_WIELD = 118, - SKILL_RACIAL_TAUREN = 124, - SKILL_ORC_RACIAL = 125, - SKILL_RACIAL_NIGHT_ELF = 126, - SKILL_FIRST_AID = 129, - SKILL_FERAL_COMBAT = 134, - SKILL_STAVES = 136, - SKILL_LANG_THALASSIAN = 137, - SKILL_LANG_DRACONIC = 138, - SKILL_LANG_DEMON_TONGUE = 139, - SKILL_LANG_TITAN = 140, - SKILL_LANG_OLD_TONGUE = 141, - SKILL_SURVIVAL2 = 142, - SKILL_RIDING_HORSE = 148, - SKILL_RIDING_WOLF = 149, - SKILL_RIDING_RAM = 152, - SKILL_RIDING_TIGER = 150, - SKILL_SWIMING = 155, - SKILL_2H_MACES = 160, - SKILL_UNARMED = 162, - SKILL_MARKSMANSHIP = 163, - SKILL_BLACKSMITHING = 164, - SKILL_LEATHERWORKING = 165, - SKILL_ALCHEMY = 171, - SKILL_2H_AXES = 172, - SKILL_DAGGERS = 173, - SKILL_THROWN = 176, - SKILL_HERBALISM = 182, - SKILL_GENERIC_DND = 183, - SKILL_RETRIBUTION = 184, - SKILL_COOKING = 185, - SKILL_MINING = 186, - SKILL_PET_IMP = 188, - SKILL_PET_FELHUNTER = 189, - SKILL_TAILORING = 197, - SKILL_ENGINERING = 202, - SKILL_PET_SPIDER = 203, - SKILL_PET_VOIDWALKER = 204, - SKILL_PET_SUCCUBUS = 205, - SKILL_PET_INFERNAL = 206, - SKILL_PET_DOOMGUARD = 207, - SKILL_PET_WOLF = 208, - SKILL_PET_CAT = 209, - SKILL_PET_BEAR = 210, - SKILL_PET_BOAR = 211, - SKILL_PET_CROCILISK = 212, - SKILL_PET_CARRION_BIRD = 213, - SKILL_PET_CRAB = 214, - SKILL_PET_GORILLA = 215, - SKILL_PET_RAPTOR = 217, - SKILL_PET_TALLSTRIDER = 218, - SKILL_RACIAL_UNDED = 220, - SKILL_CROSSBOWS = 226, - SKILL_WANDS = 228, - SKILL_POLEARMS = 229, - SKILL_PET_SCORPID = 236, - SKILL_ARCANE = 237, - SKILL_PET_TURTLE = 251, - SKILL_ASSASSINATION = 253, - SKILL_FURY = 256, - SKILL_PROTECTION = 257, - SKILL_PROTECTION2 = 267, - SKILL_PET_TALENTS = 270, - SKILL_PLATE_MAIL = 293, - SKILL_LANG_GNOMISH = 313, - SKILL_LANG_TROLL = 315, - SKILL_ENCHANTING = 333, - SKILL_DEMONOLOGY = 354, - SKILL_AFFLICTION = 355, - SKILL_FISHING = 356, - SKILL_ENHANCEMENT = 373, - SKILL_RESTORATION = 374, - SKILL_ELEMENTAL_COMBAT = 375, - SKILL_SKINNING = 393, - SKILL_MAIL = 413, - SKILL_LEATHER = 414, - SKILL_CLOTH = 415, - SKILL_SHIELD = 433, - SKILL_FIST_WEAPONS = 473, - SKILL_RIDING_RAPTOR = 533, - SKILL_RIDING_MECHANOSTRIDER = 553, - SKILL_RIDING_UNDEAD_HORSE = 554, - SKILL_RESTORATION2 = 573, - SKILL_BALANCE = 574, - SKILL_DESTRUCTION = 593, - SKILL_HOLY2 = 594, - SKILL_DISCIPLINE = 613, - SKILL_LOCKPICKING = 633, - SKILL_PET_BAT = 653, - SKILL_PET_HYENA = 654, - SKILL_PET_BIRD_OF_PREY = 655, - SKILL_PET_WIND_SERPENT = 656, - SKILL_LANG_GUTTERSPEAK = 673, - SKILL_RIDING_KODO = 713, - SKILL_RACIAL_TROLL = 733, - SKILL_RACIAL_GNOME = 753, - SKILL_RACIAL_HUMAN = 754, - SKILL_JEWELCRAFTING = 755, - SKILL_RACIAL_BLOODELF = 756, - SKILL_PET_EVENT_RC = 758, - SKILL_LANG_DRAENEI = 759, - SKILL_RACIAL_DRAENEI = 760, - SKILL_PET_FELGUARD = 761, - SKILL_RIDING = 762, - SKILL_PET_DRAGONHAWK = 763, - SKILL_PET_NETHER_RAY = 764, - SKILL_PET_SPOREBAT = 765, - SKILL_PET_WARP_STALKER = 766, - SKILL_PET_RAVAGER = 767, - SKILL_PET_SERPENT = 768, - SKILL_INTERNAL = 769, - SKILL_DK_BLOOD = 770, - SKILL_DK_FROST = 771, - SKILL_DK_UNHOLY = 772, - SKILL_INSCRIPTION = 773, - SKILL_PET_MOTH = 775, - SKILL_RUNEFORGING = 776, - SKILL_MOUNTS = 777, - SKILL_COMPANIONS = 778, - SKILL_PET_EXOTIC_CHIMAERA = 780, - SKILL_PET_EXOTIC_DEVILSAUR = 781, - SKILL_PET_GHOUL = 782, - SKILL_PET_EXOTIC_SILITHID = 783, - SKILL_PET_EXOTIC_WORM = 784, - SKILL_PET_WASP = 785, - SKILL_PET_EXOTIC_RHINO = 786, - SKILL_PET_EXOTIC_CORE_HOUND = 787, - SKILL_PET_EXOTIC_SPIRIT_BEAST = 788 -}; - -#define MAX_SKILL_TYPE 789 - -inline SkillType SkillByLockType(LockType locktype) -{ - switch(locktype) - { - case LOCKTYPE_PICKLOCK: return SKILL_LOCKPICKING; - case LOCKTYPE_HERBALISM: return SKILL_HERBALISM; - case LOCKTYPE_MINING: return SKILL_MINING; - case LOCKTYPE_FISHING: return SKILL_FISHING; - case LOCKTYPE_INSCRIPTION: return SKILL_INSCRIPTION; - default: break; - } - return SKILL_NONE; -} - -inline uint32 SkillByQuestSort(int32 QuestSort) -{ - switch(QuestSort) - { - case QUEST_SORT_HERBALISM: return SKILL_HERBALISM; - case QUEST_SORT_FISHING: return SKILL_FISHING; - case QUEST_SORT_BLACKSMITHING: return SKILL_BLACKSMITHING; - case QUEST_SORT_ALCHEMY: return SKILL_ALCHEMY; - case QUEST_SORT_LEATHERWORKING: return SKILL_LEATHERWORKING; - case QUEST_SORT_ENGINERING: return SKILL_ENGINERING; - case QUEST_SORT_TAILORING: return SKILL_TAILORING; - case QUEST_SORT_COOKING: return SKILL_COOKING; - case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID; - case QUEST_SORT_JEWELCRAFTING: return SKILL_JEWELCRAFTING; - case QUEST_SORT_INSCRIPTION: return SKILL_INSCRIPTION; - } - return 0; -} - -enum SkillCategory -{ - SKILL_CATEGORY_ATTRIBUTES = 5, - SKILL_CATEGORY_WEAPON = 6, - SKILL_CATEGORY_CLASS = 7, - SKILL_CATEGORY_ARMOR = 8, - SKILL_CATEGORY_SECONDARY = 9, // secondary professions - SKILL_CATEGORY_LANGUAGES = 10, - SKILL_CATEGORY_PROFESSION = 11, // primary professions - SKILL_CATEGORY_GENERIC = 12 -}; - -enum TotemCategory -{ - TC_SKINNING_SKIFE_OLD = 1, - TC_EARTH_TOTEM = 2, - TC_AIR_TOTEM = 3, - TC_FIRE_TOTEM = 4, - TC_WATER_TOTEM = 5, - TC_COPPER_ROD = 6, - TC_SILVER_ROD = 7, - TC_GOLDEN_ROD = 8, - TC_TRUESILVER_ROD = 9, - TC_ARCANITE_ROD = 10, - TC_MINING_PICK_OLD = 11, - TC_PHILOSOPHERS_STONE = 12, - TC_BLACKSMITH_HAMMER_OLD = 13, - TC_ARCLIGHT_SPANNER = 14, - TC_GYROMATIC_MA = 15, - TC_MASTER_TOTEM = 21, - TC_FEL_IRON_ROD = 41, - TC_ADAMANTITE_ROD = 62, - TC_ETERNIUM_ROD = 63, - TC_HOLLOW_QUILL = 81, - TC_RUNED_AZURITE_ROD = 101, - TC_VIRTUOSO_INKING_SET = 121, - TC_DRUMS = 141, - TC_GNOMISH_ARMY_KNIFE = 161, - TC_BLACKSMITH_HAMMER = 162, - TC_MINING_PICK = 165, - TC_SKINNING_KNIFE = 166, - TC_HAMMER_PICK = 167, - TC_BLADED_PICKAXE = 168, - TC_FLINT_AND_TINDER = 169, - TC_RUNED_COBALT_ROD = 189, - TC_RUNED_TITANIUM_ROD = 190 -}; - -enum UnitDynFlags -{ - UNIT_DYNFLAG_NONE = 0x0000, - UNIT_DYNFLAG_LOOTABLE = 0x0001, - UNIT_DYNFLAG_TRACK_UNIT = 0x0002, - UNIT_DYNFLAG_TAPPED = 0x0004, // Lua_UnitIsTapped - UNIT_DYNFLAG_TAPPED_BY_PLAYER = 0x0008, // Lua_UnitIsTappedByPlayer - UNIT_DYNFLAG_SPECIALINFO = 0x0010, - UNIT_DYNFLAG_DEAD = 0x0020, - UNIT_DYNFLAG_REFER_A_FRIEND = 0x0040, - UNIT_DYNFLAG_TAPPED_BY_ALL_THREAT_LIST = 0x0080 // Lua_UnitIsTappedByAllThreatList -}; - -enum CorpseDynFlags -{ - CORPSE_DYNFLAG_LOOTABLE = 0x0001 -}; - -enum WeatherType -{ - WEATHER_TYPE_FINE = 0, - WEATHER_TYPE_RAIN = 1, - WEATHER_TYPE_SNOW = 2, - WEATHER_TYPE_STORM = 3, - WEATHER_TYPE_THUNDERS = 86, - WEATHER_TYPE_BLACKRAIN = 90 -}; - -#define MAX_WEATHER_TYPE 4 - -enum ChatMsg -{ - CHAT_MSG_ADDON = 0xFFFFFFFF, - CHAT_MSG_SYSTEM = 0x00, - CHAT_MSG_SAY = 0x01, - CHAT_MSG_PARTY = 0x02, - CHAT_MSG_RAID = 0x03, - CHAT_MSG_GUILD = 0x04, - CHAT_MSG_OFFICER = 0x05, - CHAT_MSG_YELL = 0x06, - CHAT_MSG_WHISPER = 0x07, - CHAT_MSG_WHISPER_FOREIGN = 0x08, - CHAT_MSG_WHISPER_INFORM = 0x09, - CHAT_MSG_EMOTE = 0x0A, - CHAT_MSG_TEXT_EMOTE = 0x0B, - CHAT_MSG_MONSTER_SAY = 0x0C, - CHAT_MSG_MONSTER_PARTY = 0x0D, - CHAT_MSG_MONSTER_YELL = 0x0E, - CHAT_MSG_MONSTER_WHISPER = 0x0F, - CHAT_MSG_MONSTER_EMOTE = 0x10, - CHAT_MSG_CHANNEL = 0x11, - CHAT_MSG_CHANNEL_JOIN = 0x12, - CHAT_MSG_CHANNEL_LEAVE = 0x13, - CHAT_MSG_CHANNEL_LIST = 0x14, - CHAT_MSG_CHANNEL_NOTICE = 0x15, - CHAT_MSG_CHANNEL_NOTICE_USER = 0x16, - CHAT_MSG_AFK = 0x17, - CHAT_MSG_DND = 0x18, - CHAT_MSG_IGNORED = 0x19, - CHAT_MSG_SKILL = 0x1A, - CHAT_MSG_LOOT = 0x1B, - CHAT_MSG_MONEY = 0x1C, - CHAT_MSG_OPENING = 0x1D, - CHAT_MSG_TRADESKILLS = 0x1E, - CHAT_MSG_PET_INFO = 0x1F, - CHAT_MSG_COMBAT_MISC_INFO = 0x20, - CHAT_MSG_COMBAT_XP_GAIN = 0x21, - CHAT_MSG_COMBAT_HONOR_GAIN = 0x22, - CHAT_MSG_COMBAT_FACTION_CHANGE = 0x23, - CHAT_MSG_BG_SYSTEM_NEUTRAL = 0x24, - CHAT_MSG_BG_SYSTEM_ALLIANCE = 0x25, - CHAT_MSG_BG_SYSTEM_HORDE = 0x26, - CHAT_MSG_RAID_LEADER = 0x27, - CHAT_MSG_RAID_WARNING = 0x28, - CHAT_MSG_RAID_BOSS_EMOTE = 0x29, - CHAT_MSG_RAID_BOSS_WHISPER = 0x2A, - CHAT_MSG_FILTERED = 0x2B, - CHAT_MSG_BATTLEGROUND = 0x2C, - CHAT_MSG_BATTLEGROUND_LEADER = 0x2D, - CHAT_MSG_RESTRICTED = 0x2E, - CHAT_MSG_BATTLENET = 0x2F, - CHAT_MSG_ACHIEVEMENT = 0x30, - CHAT_MSG_GUILD_ACHIEVEMENT = 0x31, - CHAT_MSG_ARENA_POINTS = 0x32, - CHAT_MSG_PARTY_LEADER = 0x33 -}; - -#define MAX_CHAT_MSG_TYPE 0x34 - -enum ChatLinkColors -{ - CHAT_LINK_COLOR_TRADE = 0xffffd000, // orange - CHAT_LINK_COLOR_TALENT = 0xff4e96f7, // blue - CHAT_LINK_COLOR_SPELL = 0xff71d5ff, // bright blue - CHAT_LINK_COLOR_ENCHANT = 0xffffd000, // orange - CHAT_LINK_COLOR_ACHIEVEMENT = 0xffffff00, - CHAT_LINK_COLOR_GLYPH = 0xff66bbff -}; - -// Values from ItemPetFood (power of (value-1) used for compare with CreatureFamilyEntry.petDietMask -enum PetDiet -{ - PET_DIET_MEAT = 1, - PET_DIET_FISH = 2, - PET_DIET_CHEESE = 3, - PET_DIET_BREAD = 4, - PET_DIET_FUNGAS = 5, - PET_DIET_FRUIT = 6, - PET_DIET_RAW_MEAT = 7, - PET_DIET_RAW_FISH = 8 -}; - -#define MAX_PET_DIET 9 - -#define CHAIN_SPELL_JUMP_RADIUS 10 - -// Max values for Guild & Guild Bank -#define GUILD_BANK_MAX_TABS 6 // send by client for money log also -#define GUILD_BANK_MAX_SLOTS 98 -#define GUILD_BANK_MAX_LOGS 25 -#define GUILD_BANK_MONEY_LOGS_TAB 100 // used for money log in DB -#define GUILD_EVENTLOG_MAX_RECORDS 100 -#define GUILD_RANKS_MIN_COUNT 5 -#define GUILD_RANKS_MAX_COUNT 10 - -enum AiReaction -{ - AI_REACTION_ALERT = 0, // pre-aggro (used in client packet handler) - AI_REACTION_FRIENDLY = 1, // (NOT used in client packet handler) - AI_REACTION_HOSTILE = 2, // sent on every attack, triggers aggro sound (used in client packet handler) - AI_REACTION_AFRAID = 3, // seen for polymorph (when AI not in control of self?) (NOT used in client packet handler) - AI_REACTION_DESTROY = 4, // used on object destroy (NOT used in client packet handler) -}; - -// Diminishing Returns Types -enum DiminishingReturnsType -{ - DRTYPE_NONE = 0, // this spell is not diminished, but may have limited it's duration to 10s - DRTYPE_PLAYER = 1, // this spell is diminished only when applied on players - DRTYPE_ALL = 2 // this spell is diminished in every case -}; - -// Diminishing Return Groups -enum DiminishingGroup -{ - // Common Groups - DIMINISHING_NONE = 0, - DIMINISHING_CONTROL_STUN, // Player Controlled stuns - DIMINISHING_TRIGGER_STUN, // By aura proced stuns, usualy chance on hit talents - DIMINISHING_CONTROL_ROOT, // Immobilizing effects from casted spells - DIMINISHING_TRIGGER_ROOT, // Immobilizing effects from triggered spells like Frostbite - DIMINISHING_CHARM, - DIMINISHING_POLYMORPH, // Also: Gouge, Sap, Repentance, Hungering Cold - DIMINISHING_KNOCKOUT, // Sap, Knockout mechanics - DIMINISHING_FEAR_BLIND, // Intimidating Shout, Howl of Terror, Blind - // Warlock Specific - DIMINISHING_DEATHCOIL, // Death Coil Diminish only with another Death Coil - // Druid Specific - DIMINISHING_CYCLONE, // From 2.3.0 - // Shared Class Specific - DIMINISHING_CHEAPSHOT_POUNCE, - DIMINISHING_DISARM, // From 2.3.0 - DIMINISHING_SILENCE, // From 2.3.0 - DIMINISHING_FREEZE_SLEEP, // Hunter's Freezing Trap - DIMINISHING_BANISH, - DIMINISHING_TAUNT, - DIMINISHING_LIMITONLY // Don't Diminish, but limit duration to 10s -}; - -enum SummonCategory -{ - SUMMON_CATEGORY_WILD = 0, - SUMMON_CATEGORY_ALLY = 1, - SUMMON_CATEGORY_PET = 2, - SUMMON_CATEGORY_PUPPET = 3, - SUMMON_CATEGORY_VEHICLE = 4, -}; - -enum SummonType -{ - SUMMON_TYPE_NONE = 0, - SUMMON_TYPE_PET = 1, - SUMMON_TYPE_GUARDIAN = 2, - SUMMON_TYPE_MINION = 3, - SUMMON_TYPE_TOTEM = 4, - SUMMON_TYPE_MINIPET = 5, - SUMMON_TYPE_GUARDIAN2 = 6, - SUMMON_TYPE_WILD2 = 7, - SUMMON_TYPE_WILD3 = 8, - SUMMON_TYPE_VEHICLE = 9, - SUMMON_TYPE_VEHICLE2 = 10, - SUMMON_TYPE_OBJECT = 11, -}; - -enum EventId -{ - EVENT_SPELLCLICK = 1001, - EVENT_FALL_GROUND = 1002, - EVENT_CHARGE = 1003, -}; - -enum ResponseCodes -{ - RESPONSE_SUCCESS = 0x00, - RESPONSE_FAILURE = 0x01, - RESPONSE_CANCELLED = 0x02, - RESPONSE_DISCONNECTED = 0x03, - RESPONSE_FAILED_TO_CONNECT = 0x04, - RESPONSE_CONNECTED = 0x05, - RESPONSE_VERSION_MISMATCH = 0x06, - - CSTATUS_CONNECTING = 0x07, - CSTATUS_NEGOTIATING_SECURITY = 0x08, - CSTATUS_NEGOTIATION_COMPLETE = 0x09, - CSTATUS_NEGOTIATION_FAILED = 0x0A, - CSTATUS_AUTHENTICATING = 0x0B, - - AUTH_OK = 0x0C, - AUTH_FAILED = 0x0D, - AUTH_REJECT = 0x0E, - AUTH_BAD_SERVER_PROOF = 0x0F, - AUTH_UNAVAILABLE = 0x10, - AUTH_SYSTEM_ERROR = 0x11, - AUTH_BILLING_ERROR = 0x12, - AUTH_BILLING_EXPIRED = 0x13, - AUTH_VERSION_MISMATCH = 0x14, - AUTH_UNKNOWN_ACCOUNT = 0x15, - AUTH_INCORRECT_PASSWORD = 0x16, - AUTH_SESSION_EXPIRED = 0x17, - AUTH_SERVER_SHUTTING_DOWN = 0x18, - AUTH_ALREADY_LOGGING_IN = 0x19, - AUTH_LOGIN_SERVER_NOT_FOUND = 0x1A, - AUTH_WAIT_QUEUE = 0x1B, - AUTH_BANNED = 0x1C, - AUTH_ALREADY_ONLINE = 0x1D, - AUTH_NO_TIME = 0x1E, - AUTH_DB_BUSY = 0x1F, - AUTH_SUSPENDED = 0x20, - AUTH_PARENTAL_CONTROL = 0x21, - AUTH_LOCKED_ENFORCED = 0x22, - - REALM_LIST_IN_PROGRESS = 0x23, - REALM_LIST_SUCCESS = 0x24, - REALM_LIST_FAILED = 0x25, - REALM_LIST_INVALID = 0x26, - REALM_LIST_REALM_NOT_FOUND = 0x27, - - ACCOUNT_CREATE_IN_PROGRESS = 0x28, - ACCOUNT_CREATE_SUCCESS = 0x29, - ACCOUNT_CREATE_FAILED = 0x2A, - - CHAR_LIST_RETRIEVING = 0x2B, - CHAR_LIST_RETRIEVED = 0x2C, - CHAR_LIST_FAILED = 0x2D, - - CHAR_CREATE_IN_PROGRESS = 0x2E, - CHAR_CREATE_SUCCESS = 0x2F, - CHAR_CREATE_ERROR = 0x30, - CHAR_CREATE_FAILED = 0x31, - CHAR_CREATE_NAME_IN_USE = 0x32, - CHAR_CREATE_DISABLED = 0x33, - CHAR_CREATE_PVP_TEAMS_VIOLATION = 0x34, - CHAR_CREATE_SERVER_LIMIT = 0x35, - CHAR_CREATE_ACCOUNT_LIMIT = 0x36, - CHAR_CREATE_SERVER_QUEUE = 0x37, - CHAR_CREATE_ONLY_EXISTING = 0x38, - CHAR_CREATE_EXPANSION = 0x39, - CHAR_CREATE_EXPANSION_CLASS = 0x3A, - CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B, - CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C, - CHAR_CREATE_CHARACTER_IN_GUILD = 0x3D, - CHAR_CREATE_RESTRICTED_RACECLASS = 0x3E, - CHAR_CREATE_CHARACTER_CHOOSE_RACE = 0x3F, - CHAR_CREATE_CHARACTER_ARENA_LEADER = 0x40, - CHAR_CREATE_CHARACTER_DELETE_MAIL = 0x41, - CHAR_CREATE_CHARACTER_SWAP_FACTION = 0x42, - CHAR_CREATE_CHARACTER_RACE_ONLY = 0x43, - - CHAR_CREATE_CHARACTER_GOLD_LIMIT = 0x44, - - CHAR_CREATE_FORCE_LOGIN = 0x45, - - CHAR_DELETE_IN_PROGRESS = 0x46, - CHAR_DELETE_SUCCESS = 0x47, - CHAR_DELETE_FAILED = 0x48, - CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x49, - CHAR_DELETE_FAILED_GUILD_LEADER = 0x4A, - CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x4B, - - CHAR_LOGIN_IN_PROGRESS = 0x4C, - CHAR_LOGIN_SUCCESS = 0x4D, - CHAR_LOGIN_NO_WORLD = 0x4E, - CHAR_LOGIN_DUPLICATE_CHARACTER = 0x4F, - CHAR_LOGIN_NO_INSTANCES = 0x50, - CHAR_LOGIN_FAILED = 0x51, - CHAR_LOGIN_DISABLED = 0x52, - CHAR_LOGIN_NO_CHARACTER = 0x53, - CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x54, - CHAR_LOGIN_LOCKED_BY_BILLING = 0x55, - CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 0x56, - - CHAR_NAME_SUCCESS = 0x57, - CHAR_NAME_FAILURE = 0x58, - CHAR_NAME_NO_NAME = 0x59, - CHAR_NAME_TOO_SHORT = 0x5A, - CHAR_NAME_TOO_LONG = 0x5B, - CHAR_NAME_INVALID_CHARACTER = 0x5C, - CHAR_NAME_MIXED_LANGUAGES = 0x5D, - CHAR_NAME_PROFANE = 0x5E, - CHAR_NAME_RESERVED = 0x5F, - CHAR_NAME_INVALID_APOSTROPHE = 0x60, - CHAR_NAME_MULTIPLE_APOSTROPHES = 0x61, - CHAR_NAME_THREE_CONSECUTIVE = 0x62, - CHAR_NAME_INVALID_SPACE = 0x63, - CHAR_NAME_CONSECUTIVE_SPACES = 0x64, - CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x65, - CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x66, - CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x67 -}; - -/// Ban function modes -enum BanMode -{ - BAN_ACCOUNT, - BAN_CHARACTER, - BAN_IP -}; - -/// Ban function return codes -enum BanReturn -{ - BAN_SUCCESS, - BAN_SYNTAX_ERROR, - BAN_NOTFOUND -}; - -// indexes of BattlemasterList.dbc -enum BattleGroundTypeId -{ - BATTLEGROUND_TYPE_NONE = 0, - BATTLEGROUND_AV = 1, - BATTLEGROUND_WS = 2, - BATTLEGROUND_AB = 3, - BATTLEGROUND_NA = 4, - BATTLEGROUND_BE = 5, - BATTLEGROUND_AA = 6, - BATTLEGROUND_EY = 7, - BATTLEGROUND_RL = 8, - BATTLEGROUND_SA = 9, - BATTLEGROUND_DS = 10, - BATTLEGROUND_RV = 11, - BATTLEGROUND_IC = 30, - BATTLEGROUND_RB = 32 -}; - -#define MAX_BATTLEGROUND_TYPE_ID 33 - -enum MailResponseType -{ - MAIL_SEND = 0, - MAIL_MONEY_TAKEN = 1, - MAIL_ITEM_TAKEN = 2, - MAIL_RETURNED_TO_SENDER = 3, - MAIL_DELETED = 4, - MAIL_MADE_PERMANENT = 5 -}; - -enum MailResponseResult -{ - MAIL_OK = 0, - MAIL_ERR_EQUIP_ERROR = 1, - MAIL_ERR_CANNOT_SEND_TO_SELF = 2, - MAIL_ERR_NOT_ENOUGH_MONEY = 3, - MAIL_ERR_RECIPIENT_NOT_FOUND = 4, - MAIL_ERR_NOT_YOUR_TEAM = 5, - MAIL_ERR_INTERNAL_ERROR = 6, - MAIL_ERR_DISABLED_FOR_TRIAL_ACC = 14, - MAIL_ERR_RECIPIENT_CAP_REACHED = 15, - MAIL_ERR_CANT_SEND_WRAPPED_COD = 16, - MAIL_ERR_MAIL_AND_CHAT_SUSPENDED = 17, - MAIL_ERR_TOO_MANY_ATTACHMENTS = 18, - MAIL_ERR_MAIL_ATTACHMENT_INVALID = 19, - MAIL_ERR_ITEM_HAS_EXPIRED = 21, -}; - -enum SpellFamilyNames -{ - SPELLFAMILY_GENERIC = 0, - SPELLFAMILY_UNK1 = 1, // events, holidays - // 2 - unused - SPELLFAMILY_MAGE = 3, - SPELLFAMILY_WARRIOR = 4, - SPELLFAMILY_WARLOCK = 5, - SPELLFAMILY_PRIEST = 6, - SPELLFAMILY_DRUID = 7, - SPELLFAMILY_ROGUE = 8, - SPELLFAMILY_HUNTER = 9, - SPELLFAMILY_PALADIN = 10, - SPELLFAMILY_SHAMAN = 11, - SPELLFAMILY_UNK2 = 12, // 2 spells (silence resistance) - SPELLFAMILY_POTION = 13, - // 14 - unused - SPELLFAMILY_DEATHKNIGHT = 15, - // 16 - unused - SPELLFAMILY_PET = 17 -}; - -#endif diff --git a/src/server/game/Groups/GroupHandler.cpp b/src/server/game/Groups/GroupHandler.cpp deleted file mode 100644 index f973bc24722..00000000000 --- a/src/server/game/Groups/GroupHandler.cpp +++ /dev/null @@ -1,940 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "Opcodes.h" -#include "Log.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "Group.h" -#include "SocialMgr.h" -#include "Util.h" -#include "SpellAuras.h" -#include "Vehicle.h" -#include "LFG.h" - -class Aura; - -/* differeces from off: - -you can uninvite yourself - is is useful - -you can accept invitation even if leader went offline -*/ -/* todo: - -group_destroyed msg is sent but not shown - -reduce xp gaining when in raid group - -quest sharing has to be corrected - -FIX sending PartyMemberStats -*/ - -void WorldSession::SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res) -{ - WorldPacket data(SMSG_PARTY_COMMAND_RESULT, (4+member.size()+1+4+4)); - data << (uint32)operation; - data << member; - data << (uint32)res; - data << uint32(0); // LFD cooldown related (used with ERR_PARTY_LFG_BOOT_COOLDOWN_S and ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S) - - SendPacket(&data); -} - -void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) -{ - std::string membername; - recv_data >> membername; - - // attempt add selected player - - // cheating - if (!normalizePlayerName(membername)) - { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); - return; - } - - Player *player = objmgr.GetPlayer(membername.c_str()); - - // no player - if (!player) - { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); - return; - } - - // restrict invite to GMs - if (!sWorld.getConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->isGameMaster() && player->isGameMaster()) - return; - - // can't group with - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) - { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION); - return; - } - if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) - { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S); - return; - } - // just ignore us - if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty()) - { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); - return; - } - - if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) - { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); - return; - } - - Group *group = GetPlayer()->GetGroup(); - if (group && group->isBGGroup()) - group = GetPlayer()->GetOriginalGroup(); - - Group *group2 = player->GetGroup(); - if (group2 && group2->isBGGroup()) - group2 = player->GetOriginalGroup(); - // player already in another group or invited - if (group2 || player->GetGroupInvite()) - { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S); - return; - } - - if (group) - { - // not have permissions for invite - if (group->isRaidGroup() && !group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) - { - SendPartyResult(PARTY_OP_INVITE, "", ERR_NOT_LEADER); - return; - } - // not have place - if (group->IsFull()) - { - SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); - return; - } - } - - // ok, but group not exist, start a new group - // but don't create and save the group to the DB until - // at least one person joins - if (!group) - { - group = new Group; - // new group: if can't add then delete - if (!group->AddLeaderInvite(GetPlayer())) - { - delete group; - return; - } - if (!group->AddInvite(player)) - { - delete group; - return; - } - } - else - { - // already existed group: if can't add then just leave - if (!group->AddInvite(player)) - { - return; - } - } - - // ok, we do it - WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size - data << uint8(1); // invited/already in group flag - data << GetPlayer()->GetName(); // max len 48 - data << uint32(0); // unk - data << uint8(0); // count - //for (int i = 0; i < count; ++i) - // data << uint32(0); - data << uint32(0); // unk - player->GetSession()->SendPacket(&data); - - SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK); -} - -void WorldSession::HandleGroupAcceptOpcode(WorldPacket & /*recv_data*/) -{ - Group *group = GetPlayer()->GetGroupInvite(); - if (!group) return; - - if (group->GetLeaderGUID() == GetPlayer()->GetGUID()) - { - sLog.outError("HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); - return; - } - - // remove in from ivites in any case - group->RemoveInvite(GetPlayer()); - - /** error handling **/ - /********************/ - - // not have place - if (group->IsFull()) - { - SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); - return; - } - - Player* leader = objmgr.GetPlayer(group->GetLeaderGUID()); - - // forming a new group, create it - if (!group->IsCreated()) - { - if (leader) - group->RemoveInvite(leader); - group->Create(group->GetLeaderGUID(), group->GetLeaderName()); - objmgr.AddGroup(group); - } - - // everything's fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!! - if (!group->AddMember(GetPlayer()->GetGUID(), GetPlayer()->GetName())) - return; - - SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - if (Player *plrg = itr->getSource()) - { - plrg->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_CLEAR_LOCK_LIST); - plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_CLEAR_LOCK_LIST); - } - - group->BroadcastGroupUpdate(); -} - -void WorldSession::HandleGroupDeclineOpcode(WorldPacket & /*recv_data*/) -{ - Group *group = GetPlayer()->GetGroupInvite(); - if (!group) return; - - // remember leader if online - Player *leader = objmgr.GetPlayer(group->GetLeaderGUID()); - - // uninvite, group can be deleted - GetPlayer()->UninviteFromGroup(); - - if (!leader || !leader->GetSession()) - return; - - // report - WorldPacket data(SMSG_GROUP_DECLINE, 10); // guess size - data << GetPlayer()->GetName(); - leader->GetSession()->SendPacket(&data); -} - -void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - recv_data.read_skip(); // reason - - //can't uninvite yourself - if (guid == GetPlayer()->GetGUID()) - { - sLog.outError("WorldSession::HandleGroupUninviteGuidOpcode: leader %s(%d) tried to uninvite himself from the group.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); - return; - } - - PartyResult res = GetPlayer()->CanUninviteFromGroup(); - if (res != ERR_PARTY_RESULT_OK) - { - SendPartyResult(PARTY_OP_UNINVITE, "", res); - return; - } - - Group* grp = GetPlayer()->GetGroup(); - if (!grp) - return; - - if (grp->IsMember(guid)) - { - Player::RemoveFromGroup(grp,guid); - return; - } - - if (Player* plr = grp->GetInvited(guid)) - { - plr->UninviteFromGroup(); - return; - } - - SendPartyResult(PARTY_OP_UNINVITE, "", ERR_TARGET_NOT_IN_GROUP_S); -} - -void WorldSession::HandleGroupUninviteOpcode(WorldPacket & recv_data) -{ - std::string membername; - recv_data >> membername; - - // player not found - if (!normalizePlayerName(membername)) - return; - - // can't uninvite yourself - if (GetPlayer()->GetName() == membername) - { - sLog.outError("WorldSession::HandleGroupUninviteOpcode: leader %s(%d) tried to uninvite himself from the group.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); - return; - } - - PartyResult res = GetPlayer()->CanUninviteFromGroup(); - if (res != ERR_PARTY_RESULT_OK) - { - SendPartyResult(PARTY_OP_UNINVITE, "", res); - return; - } - - Group* grp = GetPlayer()->GetGroup(); - if (!grp) - return; - - if (uint64 guid = grp->GetMemberGUID(membername)) - { - Player::RemoveFromGroup(grp,guid); - return; - } - - if (Player* plr = grp->GetInvited(membername)) - { - plr->UninviteFromGroup(); - return; - } - - SendPartyResult(PARTY_OP_UNINVITE, membername, ERR_TARGET_NOT_IN_GROUP_S); -} - -void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket & recv_data) -{ - Group *group = GetPlayer()->GetGroup(); - if (!group) - return; - - uint64 guid; - recv_data >> guid; - - Player *player = objmgr.GetPlayer(guid); - - /** error handling **/ - if (!player || !group->IsLeader(GetPlayer()->GetGUID()) || player->GetGroup() != group) - return; - /********************/ - - // everything's fine, do it - group->ChangeLeader(guid); -} - -void WorldSession::HandleGroupDisbandOpcode(WorldPacket & /*recv_data*/) -{ - if (!GetPlayer()->GetGroup()) - return; - - if (_player->InBattleGround()) - { - SendPartyResult(PARTY_OP_INVITE, "", ERR_INVITE_RESTRICTED); - return; - } - - /** error handling **/ - /********************/ - - // everything's fine, do it - SendPartyResult(PARTY_OP_LEAVE, GetPlayer()->GetName(), ERR_PARTY_RESULT_OK); - - GetPlayer()->RemoveFromGroup(); -} - -void WorldSession::HandleLootMethodOpcode(WorldPacket & recv_data) -{ - Group *group = GetPlayer()->GetGroup(); - if (!group) - return; - - uint32 lootMethod; - uint64 lootMaster; - uint32 lootThreshold; - recv_data >> lootMethod >> lootMaster >> lootThreshold; - - /** error handling **/ - if (!group->IsLeader(GetPlayer()->GetGUID())) - return; - /********************/ - - // everything's fine, do it - group->SetLootMethod((LootMethod)lootMethod); - group->SetLooterGuid(lootMaster); - group->SetLootThreshold((ItemQualities)lootThreshold); - group->SendUpdate(); -} - -void WorldSession::HandleLootRoll(WorldPacket &recv_data) -{ - if (!GetPlayer()->GetGroup()) - return; - - uint64 Guid; - uint32 NumberOfPlayers; - uint8 rollType; - recv_data >> Guid; //guid of the item rolled - recv_data >> NumberOfPlayers; - recv_data >> rollType; //0: pass, 1: need, 2: greed - - //sLog.outDebug("WORLD RECIEVE CMSG_LOOT_ROLL, From:%u, Numberofplayers:%u, Choise:%u", (uint32)Guid, NumberOfPlayers, Choise); - - Group* group = GetPlayer()->GetGroup(); - if (!group) - return; - - // everything's fine, do it - group->CountRollVote(GetPlayer()->GetGUID(), Guid, NumberOfPlayers, rollType); - - switch (rollType) - { - case ROLL_NEED: - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1); - break; - case ROLL_GREED: - GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1); - break; - } -} - -void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data) -{ - if (!GetPlayer()->GetGroup()) - return; - - float x, y; - recv_data >> x; - recv_data >> y; - - //sLog.outDebug("Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y); - - /** error handling **/ - /********************/ - - // everything's fine, do it - WorldPacket data(MSG_MINIMAP_PING, (8+4+4)); - data << uint64(GetPlayer()->GetGUID()); - data << float(x); - data << float(y); - GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID()); -} - -void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data) -{ - uint32 minimum, maximum, roll; - recv_data >> minimum; - recv_data >> maximum; - - /** error handling **/ - if (minimum > maximum || maximum > 10000) // < 32768 for urand call - return; - /********************/ - - // everything's fine, do it - roll = urand(minimum, maximum); - - //sLog.outDebug("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll); - - WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8); - data << uint32(minimum); - data << uint32(maximum); - data << uint32(roll); - data << uint64(GetPlayer()->GetGUID()); - if (GetPlayer()->GetGroup()) - GetPlayer()->GetGroup()->BroadcastPacket(&data, false); - else - SendPacket(&data); -} - -void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket & recv_data) -{ - Group *group = GetPlayer()->GetGroup(); - if (!group) - return; - - uint8 x; - recv_data >> x; - - /** error handling **/ - /********************/ - - // everything's fine, do it - if (x == 0xFF) // target icon request - { - group->SendTargetIconList(this); - } - else // target icon update - { - if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) - return; - - uint64 guid; - recv_data >> guid; - group->SetTargetIcon(x, _player->GetGUID(), guid); - } -} - -void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recv_data*/) -{ - Group *group = GetPlayer()->GetGroup(); - if (!group) - return; - - if (_player->InBattleGround()) - return; - - /** error handling **/ - if (!group->IsLeader(GetPlayer()->GetGUID()) || group->GetMembersCount() < 2) - return; - /********************/ - - // everything's fine, do it (is it 0 (PARTY_OP_INVITE) correct code) - SendPartyResult(PARTY_OP_INVITE, "", ERR_PARTY_RESULT_OK); - group->ConvertToRaid(); -} - -void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket & recv_data) -{ - // we will get correct pointer for group here, so we don't have to check if group is BG raid - Group *group = GetPlayer()->GetGroup(); - if (!group) - return; - - std::string name; - uint8 groupNr; - recv_data >> name; - - recv_data >> groupNr; - - /** error handling **/ - uint64 senderGuid = GetPlayer()->GetGUID(); - if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid)) - return; - - if (!group->HasFreeSlotSubGroup(groupNr)) - return; - /********************/ - - Player *movedPlayer=objmgr.GetPlayer(name.c_str()); - if (!movedPlayer) - return; - - //Do not allow leader to change group of player in combat - if (movedPlayer->isInCombat()) - return; - - // everything's fine, do it - group->ChangeMembersGroup(movedPlayer, groupNr); -} - -void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket & recv_data) -{ - Group *group = GetPlayer()->GetGroup(); - if (!group) - return; - - uint64 guid; - uint8 flag; - recv_data >> guid; - recv_data >> flag; - - /** error handling **/ - if (!group->IsLeader(GetPlayer()->GetGUID())) - return; - /********************/ - - // everything's fine, do it - group->SetAssistant(guid, (flag != 0)); -} - -void WorldSession::HandlePartyAssignmentOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("MSG_PARTY_ASSIGNMENT"); - - Group *group = GetPlayer()->GetGroup(); - if (!group) - return; - - uint8 flag, apply; - uint64 guid; - recv_data >> flag >> apply; - recv_data >> guid; - - /** error handling **/ - uint64 senderGuid = GetPlayer()->GetGUID(); - if (!group->IsLeader(senderGuid) && group->IsAssistant(senderGuid)) - return; - /********************/ - - // everything's fine, do it - if (flag == 0) - group->SetMainTank(guid, apply); - - else if (flag == 1) - group->SetMainAssistant(guid, apply); -} - -void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket & recv_data) -{ - Group *group = GetPlayer()->GetGroup(); - if (!group) - return; - - if (recv_data.empty()) // request - { - /** error handling **/ - if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) - return; - /********************/ - - // everything's fine, do it - WorldPacket data(MSG_RAID_READY_CHECK, 8); - data << GetPlayer()->GetGUID(); - group->BroadcastPacket(&data, false, -1); - - group->OfflineReadyCheck(); - } - else // answer - { - uint8 state; - recv_data >> state; - - // everything's fine, do it - WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); - data << uint64(GetPlayer()->GetGUID()); - data << uint8(state); - group->BroadcastReadyCheck(&data); - } -} - -void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket & /*recv_data*/) -{ - //Group* group = GetPlayer()->GetGroup(); - //if (!group) - // return; - - //if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) - // return; - - // Is any reaction need? -} - -void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data) -{ - uint32 mask = player->GetGroupUpdateFlag(); - - if (mask == GROUP_UPDATE_FLAG_NONE) - return; - - if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also - mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); - - if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets - mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); - - uint32 byteCount = 0; - for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) - if (mask & (1 << i)) - byteCount += GroupUpdateLength[i]; - - data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); - data->append(player->GetPackGUID()); - *data << (uint32) mask; - - if (mask & GROUP_UPDATE_FLAG_STATUS) - { - if (player) - { - if (player->IsPvP()) - *data << (uint16) (MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); - else - *data << (uint16) MEMBER_STATUS_ONLINE; - } - else - *data << (uint16) MEMBER_STATUS_OFFLINE; - } - - if (mask & GROUP_UPDATE_FLAG_CUR_HP) - *data << (uint32) player->GetHealth(); - - if (mask & GROUP_UPDATE_FLAG_MAX_HP) - *data << (uint32) player->GetMaxHealth(); - - Powers powerType = player->getPowerType(); - if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) - *data << (uint8) powerType; - - if (mask & GROUP_UPDATE_FLAG_CUR_POWER) - *data << (uint16) player->GetPower(powerType); - - if (mask & GROUP_UPDATE_FLAG_MAX_POWER) - *data << (uint16) player->GetMaxPower(powerType); - - if (mask & GROUP_UPDATE_FLAG_LEVEL) - *data << (uint16) player->getLevel(); - - if (mask & GROUP_UPDATE_FLAG_ZONE) - *data << (uint16) player->GetZoneId(); - - if (mask & GROUP_UPDATE_FLAG_POSITION) - *data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY(); - - if (mask & GROUP_UPDATE_FLAG_AURAS) - { - const uint64& auramask = player->GetAuraUpdateMaskForRaid(); - *data << uint64(auramask); - for (uint32 i = 0; i < MAX_AURAS; ++i) - { - if (auramask & (uint64(1) << i)) - { - AuraApplication const * aurApp = player->GetVisibleAura(i); - *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); - *data << uint8(1); - } - } - } - - Pet *pet = player->GetPet(); - if (mask & GROUP_UPDATE_FLAG_PET_GUID) - { - if (pet) - *data << (uint64) pet->GetGUID(); - else - *data << (uint64) 0; - } - - if (mask & GROUP_UPDATE_FLAG_PET_NAME) - { - if (pet) - *data << pet->GetName(); - else - *data << (uint8) 0; - } - - if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) - { - if (pet) - *data << (uint16) pet->GetDisplayId(); - else - *data << (uint16) 0; - } - - if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) - { - if (pet) - *data << (uint32) pet->GetHealth(); - else - *data << (uint32) 0; - } - - if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) - { - if (pet) - *data << (uint32) pet->GetMaxHealth(); - else - *data << (uint32) 0; - } - - if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) - { - if (pet) - *data << (uint8) pet->getPowerType(); - else - *data << (uint8) 0; - } - - if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) - { - if (pet) - *data << (uint16) pet->GetPower(pet->getPowerType()); - else - *data << (uint16) 0; - } - - if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) - { - if (pet) - *data << (uint16) pet->GetMaxPower(pet->getPowerType()); - else - *data << (uint16) 0; - } - - if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) - { - if (player->GetVehicle()){ - Vehicle* vv=player->GetVehicle(); - *data << (uint32) vv->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]; - } - } - - if (mask & GROUP_UPDATE_FLAG_PET_AURAS) - { - if (pet) - { - const uint64& auramask = pet->GetAuraUpdateMaskForRaid(); - *data << uint64(auramask); - for (uint32 i = 0; i < MAX_AURAS; ++i) - { - if (auramask & (uint64(1) << i)) - { - AuraApplication const * aurApp = player->GetVisibleAura(i); - *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); - *data << uint8(1); - } - } - } - else - *data << (uint64) 0; - } -} - -/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ -void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); - uint64 Guid; - recv_data >> Guid; - - Player *player = objmgr.GetPlayer(Guid); - if (!player) - { - WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); - data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related - data.appendPackGUID(Guid); - data << (uint32) GROUP_UPDATE_FLAG_STATUS; - data << (uint16) MEMBER_STATUS_OFFLINE; - SendPacket(&data); - return; - } - - Pet *pet = player->GetPet(); - - WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); - data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related - data.append(player->GetPackGUID()); - - uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF - if (pet) - mask1 = 0x7FFFFFFF; // for hunters and other classes with pets - - Powers powerType = player->getPowerType(); - data << (uint32) mask1; // group update mask - data << (uint16) MEMBER_STATUS_ONLINE; // member's online status - data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP - data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP - data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE - data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER - data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER - data << (uint16) player->getLevel(); // GROUP_UPDATE_FLAG_LEVEL - data << (uint16) player->GetZoneId(); // GROUP_UPDATE_FLAG_ZONE - data << (uint16) player->GetPositionX(); // GROUP_UPDATE_FLAG_POSITION - data << (uint16) player->GetPositionY(); // GROUP_UPDATE_FLAG_POSITION - - uint64 auramask = 0; - size_t maskPos = data.wpos(); - data << (uint64) auramask; // placeholder - for (uint8 i = 0; i < MAX_AURAS; ++i) - { - if (AuraApplication * aurApp = player->GetVisibleAura(i)) - { - auramask |= (uint64(1) << i); - data << (uint32) aurApp->GetBase()->GetId(); - data << (uint8) 1; - } - } - data.put(maskPos,auramask); // GROUP_UPDATE_FLAG_AURAS - - if (pet) - { - Powers petpowertype = pet->getPowerType(); - data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID - data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME - data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID - data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP - data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP - data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE - data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER - data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER - - uint64 petauramask = 0; - size_t petMaskPos = data.wpos(); - data << (uint64) petauramask; // placeholder - for (uint8 i = 0; i < MAX_AURAS; ++i) - { - if (AuraApplication * auraApp = pet->GetVisibleAura(i)) - { - petauramask |= (uint64(1) << i); - data << (uint32) auraApp->GetBase()->GetId(); - data << (uint8) 1; - } - } - data.put(petMaskPos,petauramask); // GROUP_UPDATE_FLAG_PET_AURAS - } - else - { - data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_NAME - data << (uint64) 0; // GROUP_UPDATE_FLAG_PET_AURAS - } - - SendPacket(&data); -} - -/*!*/void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket & /*recv_data*/) -{ - // every time the player checks the character screen - _player->SendRaidInfo(); -} - -/*void WorldSession::HandleGroupCancelOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: got CMSG_GROUP_CANCEL."); -}*/ - -void WorldSession::HandleOptOutOfLootOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_OPT_OUT_OF_LOOT"); - - uint32 passOnLoot; - recv_data >> passOnLoot; // 1 always pass, 0 do not pass - - // ignore if player not loaded - if (!GetPlayer()) // needed because STATUS_AUTHED - { - if (passOnLoot != 0) - sLog.outError("CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!"); - return; - } - - GetPlayer()->SetPassOnGroupLoot(passOnLoot); -} diff --git a/src/server/game/Guilds/GuildHandler.cpp b/src/server/game/Guilds/GuildHandler.cpp deleted file mode 100644 index 6803fe63a86..00000000000 --- a/src/server/game/Guilds/GuildHandler.cpp +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Guild.h" -#include "GossipDef.h" -#include "SocialMgr.h" - -void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_QUERY"); - - uint32 guildId; - recvPacket >> guildId; - - if (Guild *guild = objmgr.GetGuildById(guildId)) - { - guild->Query(this); - return; - } - - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); -} - -void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_CREATE"); - - std::string gname; - recvPacket >> gname; - - if (GetPlayer()->GetGuildId()) // already in guild - return; - - Guild *guild = new Guild; - if (!guild->Create(GetPlayer(), gname)) - { - delete guild; - return; - } - - objmgr.AddGuild(guild); -} - -void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_INVITE"); - - std::string Invitedname, plname; - - Player * player = NULL; - recvPacket >> Invitedname; - - if (normalizePlayerName(Invitedname)) - player = ObjectAccessor::Instance().FindPlayerByName(Invitedname.c_str()); - - if (!player) - { - SendGuildCommandResult(GUILD_INVITE_S, Invitedname, ERR_GUILD_PLAYER_NOT_FOUND_S); - return; - } - - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - // OK result but not send invite - if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) - return; - - // not let enemies sign guild charter - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) - { - SendGuildCommandResult(GUILD_INVITE_S, Invitedname, ERR_GUILD_NOT_ALLIED); - return; - } - - if (player->GetGuildId()) - { - plname = player->GetName(); - SendGuildCommandResult(GUILD_INVITE_S, plname, ERR_ALREADY_IN_GUILD_S); - return; - } - - if (player->GetGuildIdInvited()) - { - plname = player->GetName(); - SendGuildCommandResult(GUILD_INVITE_S, plname, ERR_ALREADY_INVITED_TO_GUILD_S); - return; - } - - if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_INVITE)) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - sLog.outDebug("Player %s Invited %s to Join his Guild", GetPlayer()->GetName(), Invitedname.c_str()); - - player->SetGuildIdInvited(GetPlayer()->GetGuildId()); - // Put record into guildlog - guild->LogGuildEvent(GUILD_EVENT_LOG_INVITE_PLAYER, GetPlayer()->GetGUIDLow(), player->GetGUIDLow(), 0); - - WorldPacket data(SMSG_GUILD_INVITE, (8+10)); // guess size - data << GetPlayer()->GetName(); - data << guild->GetName(); - player->GetSession()->SendPacket(&data); - - sLog.outDebug("WORLD: Sent (SMSG_GUILD_INVITE)"); -} - -void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_REMOVE"); - - std::string plName; - recvPacket >> plName; - - if (!normalizePlayerName(plName)) - return; - - Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_REMOVE)) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - uint64 plGuid; - MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); - if (!slot) - { - SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); - return; - } - - if (slot->RankId == GR_GUILDMASTER) - { - SendGuildCommandResult(GUILD_QUIT_S, "", ERR_GUILD_LEADER_LEAVE); - return; - } - - //do not allow to kick player with same or higher rights - if (GetPlayer()->GetRank() >= slot->RankId) - { - SendGuildCommandResult(GUILD_QUIT_S, plName, ERR_GUILD_RANK_TOO_HIGH_S); - return; - } - - guild->DelMember(plGuid); - // Put record into guildlog - guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), 0); - - guild->BroadcastEvent(GE_REMOVED, 0, 2, plName, _player->GetName(), ""); -} - -void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/) -{ - Guild *guild; - Player *player = GetPlayer(); - - sLog.outDebug("WORLD: Received CMSG_GUILD_ACCEPT"); - - guild = objmgr.GetGuildById(player->GetGuildIdInvited()); - if (!guild || player->GetGuildId()) - return; - - // not let enemies sign guild charter - if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != objmgr.GetPlayerTeamByGUID(guild->GetLeader())) - return; - - if (!guild->AddMember(GetPlayer()->GetGUID(),guild->GetLowestRank())) - return; - // Put record into guildlog - guild->LogGuildEvent(GUILD_EVENT_LOG_JOIN_GUILD, GetPlayer()->GetGUIDLow(), 0, 0); - - guild->BroadcastEvent(GE_JOINED, player->GetGUID(), 1, player->GetName(), "", ""); - - sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); -} - -void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_DECLINE"); - - GetPlayer()->SetGuildIdInvited(0); - GetPlayer()->SetInGuild(0); -} - -void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/) -{ - Guild *guild; - sLog.outDebug("WORLD: Received CMSG_GUILD_INFO"); - - guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - WorldPacket data(SMSG_GUILD_INFO, (guild->GetName().size() + 4 + 4 + 4)); - data << guild->GetName(); - data << secsToTimeBitFields(guild->GetCreatedDate()); // 3.x (prev. year + month + day) - data << guild->GetMemberSize(); // char amount - data << guild->GetMemberSize(); // acc amount - - SendPacket(&data); -} - -void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_ROSTER"); - - if (Guild* guild = objmgr.GetGuildById(_player->GetGuildId())) - guild->Roster(this); -} - -void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_PROMOTE"); - - std::string plName; - recvPacket >> plName; - - if (!normalizePlayerName(plName)) - return; - - Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_PROMOTE)) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - uint64 plGuid; - MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); - - if (!slot) - { - SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); - return; - } - - if (plGuid == GetPlayer()->GetGUID()) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_NAME_INVALID); - return; - } - - //allow to promote only to lower rank than member's rank - //guildmaster's rank = 0 - //GetPlayer()->GetRank() + 1 is highest rank that current player can promote to - if (GetPlayer()->GetRank() + 1 >= slot->RankId) - { - SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_HIGH_S); - return; - } - - uint32 newRankId = slot->RankId - 1; //when promoting player, rank is decreased - - guild->BroadcastEvent(GE_PROMOTION, 0, 3, _player->GetName(), plName, guild->GetRankName(newRankId)); - - guild->ChangeRank(plGuid, newRankId); - // Put record into guildlog - guild->LogGuildEvent(GUILD_EVENT_LOG_PROMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId); -} - -void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_DEMOTE"); - - std::string plName; - recvPacket >> plName; - - if (!normalizePlayerName(plName)) - return; - - Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_DEMOTE)) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - uint64 plGuid; - MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); - - if (!slot) - { - SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); - return; - } - - if (plGuid == GetPlayer()->GetGUID()) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_NAME_INVALID); - return; - } - - //do not allow to demote same or higher rank - if (GetPlayer()->GetRank() >= slot->RankId) - { - SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_HIGH_S); - return; - } - - //do not allow to demote lowest rank - if (slot->RankId >= guild->GetLowestRank()) - { - SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_LOW_S); - return; - } - - uint32 newRankId = slot->RankId + 1; //when demoting player, rank is increased - - guild->ChangeRank(plGuid, newRankId); - // Put record into guildlog - guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId); - - guild->BroadcastEvent(GE_DEMOTION, 0, 3, _player->GetName(), plName, guild->GetRankName(slot->RankId)); -} - -void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_LEAVE"); - - Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (_player->GetGUID() == guild->GetLeader() && guild->GetMemberSize() > 1) - { - SendGuildCommandResult(GUILD_QUIT_S, "", ERR_GUILD_LEADER_LEAVE); - return; - } - - if (_player->GetGUID() == guild->GetLeader()) - { - guild->Disband(); - return; - } - - guild->DelMember(_player->GetGUID()); - // Put record into guildlog - guild->LogGuildEvent(GUILD_EVENT_LOG_LEAVE_GUILD, _player->GetGUIDLow(), 0, 0); - - guild->BroadcastEvent(GE_LEFT, _player->GetGUID(), 1, _player->GetName(), "", ""); - - SendGuildCommandResult(GUILD_QUIT_S, guild->GetName(), ERR_PLAYER_NO_MORE_IN_GUILD); -} - -void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_DISBAND"); - - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (GetPlayer()->GetGUID() != guild->GetLeader()) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - guild->Disband(); - - sLog.outDebug("WORLD: Guild Successfully Disbanded"); -} - -void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_LEADER"); - - std::string name; - recvPacket >> name; - - Player *oldLeader = GetPlayer(); - - if (!normalizePlayerName(name)) - return; - - Guild *guild = objmgr.GetGuildById(oldLeader->GetGuildId()); - - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (oldLeader->GetGUID() != guild->GetLeader()) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - uint64 newLeaderGUID; - MemberSlot* slot = guild->GetMemberSlot(name, newLeaderGUID); - - if (!slot) - { - SendGuildCommandResult(GUILD_INVITE_S, name, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); - return; - } - - guild->SetLeader(newLeaderGUID); - guild->ChangeRank(oldLeader->GetGUID(), GR_OFFICER); - - guild->BroadcastEvent(GE_LEADER_CHANGED, 0, 2, oldLeader->GetName(), name, ""); -} - -void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_MOTD"); - - std::string MOTD; - - if (!recvPacket.empty()) - recvPacket >> MOTD; - else - MOTD = ""; - - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_SETMOTD)) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - guild->SetMOTD(MOTD); - - guild->BroadcastEvent(GE_MOTD, 0, 1, MOTD, "", ""); -} - -void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_SET_PUBLIC_NOTE"); - - std::string name,PNOTE; - recvPacket >> name; - - if (!normalizePlayerName(name)) - return; - - Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EPNOTE)) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - uint64 plGuid; - MemberSlot* slot = guild->GetMemberSlot(name, plGuid); - - if (!slot) - { - SendGuildCommandResult(GUILD_INVITE_S, name, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); - return; - } - - recvPacket >> PNOTE; - guild->SetPNOTE(plGuid, PNOTE); - - guild->Roster(this); -} - -void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_SET_OFFICER_NOTE"); - - std::string plName, OFFNOTE; - recvPacket >> plName; - - if (!normalizePlayerName(plName)) - return; - - Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EOFFNOTE)) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - uint64 plGuid; - MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); - - if (!slot) - { - SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); - return; - } - - recvPacket >> OFFNOTE; - guild->SetOFFNOTE(plGuid, OFFNOTE); - - guild->Roster(this); -} - -void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) -{ - std::string rankname; - uint32 rankId; - uint32 rights, MoneyPerDay; - - sLog.outDebug("WORLD: Received CMSG_GUILD_RANK"); - - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - else if (GetPlayer()->GetGUID() != guild->GetLeader()) - { - recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - recvPacket >> rankId; - recvPacket >> rights; - recvPacket >> rankname; - recvPacket >> MoneyPerDay; - - for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) - { - uint32 BankRights; - uint32 BankSlotPerDay; - - recvPacket >> BankRights; - recvPacket >> BankSlotPerDay; - guild->SetBankRightsAndSlots(rankId, uint8(i), uint16(BankRights & 0xFF), uint16(BankSlotPerDay), true); - } - - sLog.outDebug("WORLD: Changed RankName to %s , Rights to 0x%.4X", rankname.c_str(), rights); - - guild->SetBankMoneyPerDay(rankId, MoneyPerDay); - guild->SetRankName(rankId, rankname); - - if (rankId == GR_GUILDMASTER) // prevent loss leader rights - rights = GR_RIGHT_ALL; - - guild->SetRankRights(rankId, rights); - - guild->Query(this); - guild->Roster(); // broadcast for tab rights update -} - -void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_ADD_RANK"); - - std::string rankname; - recvPacket >> rankname; - - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (GetPlayer()->GetGUID() != guild->GetLeader()) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - if (guild->GetRanksSize() >= GUILD_RANKS_MAX_COUNT) // client not let create more 10 than ranks - return; - - guild->CreateRank(rankname, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - - guild->Query(this); - guild->Roster(); // broadcast for tab rights update -} - -void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_DEL_RANK"); - - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - else if (GetPlayer()->GetGUID() != guild->GetLeader()) - { - SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - guild->DelRank(); - - guild->Query(this); - guild->Roster(); // broadcast for tab rights update -} - -void WorldSession::SendGuildCommandResult(uint32 typecmd, const std::string& str,uint32 cmdresult) -{ - WorldPacket data(SMSG_GUILD_COMMAND_RESULT, (8+str.size()+1)); - data << typecmd; - data << str; - data << cmdresult; - SendPacket(&data); - - sLog.outDebug("WORLD: Sent (SMSG_GUILD_COMMAND_RESULT)"); -} - -void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received CMSG_GUILD_INFO_TEXT"); - - std::string GINFO; - - recvPacket >> GINFO; - - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); - return; - } - - if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_MODIFY_GUILD_INFO)) - { - SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PERMISSIONS); - return; - } - - guild->SetGINFO(GINFO); -} - -void WorldSession::HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket) -{ - sLog.outDebug("WORLD: Received MSG_SAVE_GUILD_EMBLEM"); - - uint64 vendorGuid; - - uint32 EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor; - - recvPacket >> vendorGuid; - recvPacket >> EmblemStyle >> EmblemColor >> BorderStyle >> BorderColor >> BackgroundColor; - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid,UNIT_NPC_FLAG_TABARDDESIGNER); - if (!pCreature) - { - //"That's not an emblem vendor!" - SendSaveGuildEmblem(ERR_GUILDEMBLEM_INVALIDVENDOR); - sLog.outDebug("WORLD: HandleSaveGuildEmblemOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(vendorGuid)); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); - if (!guild) - { - //"You are not part of a guild!"; - SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOGUILD); - return; - } - - if (guild->GetLeader() != GetPlayer()->GetGUID()) - { - //"Only guild leaders can create emblems." - SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOTGUILDMASTER); - return; - } - - if (GetPlayer()->GetMoney() < 10*GOLD) - { - //"You can't afford to do that." - SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOTENOUGHMONEY); - return; - } - - GetPlayer()->ModifyMoney(-10*GOLD); - guild->SetEmblem(EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor); - - //"Guild Emblem saved." - SendSaveGuildEmblem(ERR_GUILDEMBLEM_SUCCESS); - - guild->Query(this); -} - -void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */) -{ - // empty - sLog.outDebug("WORLD: Received (MSG_GUILD_EVENT_LOG_QUERY)"); - if (uint32 GuildId = GetPlayer()->GetGuildId()) - if (Guild *pGuild = objmgr.GetGuildById(GuildId)) - pGuild->DisplayGuildEventLog(this); -} - -/****** GUILD BANK *******/ - -void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket & /* recv_data */) -{ - sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_MONEY_WITHDRAWN)"); - if (uint32 GuildId = GetPlayer()->GetGuildId()) - if (Guild *pGuild = objmgr.GetGuildById(GuildId)) - pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); -} - -void WorldSession::HandleGuildPermissions(WorldPacket& /* recv_data */) -{ - sLog.outDebug("WORLD: Received (MSG_GUILD_PERMISSIONS)"); - - if (uint32 GuildId = GetPlayer()->GetGuildId()) - { - if (Guild *pGuild = objmgr.GetGuildById(GuildId)) - { - uint32 rankId = GetPlayer()->GetRank(); - - WorldPacket data(MSG_GUILD_PERMISSIONS, 4*15+1); - data << uint32(rankId); // guild rank id - data << uint32(pGuild->GetRankRights(rankId)); // rank rights - // money per day left - data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow())); - data << uint8(pGuild->GetPurchasedTabs()); // tabs count - // why sending all info when not all tabs are purchased??? - for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) - { - data << uint32(pGuild->GetBankRights(rankId, uint8(i))); - data << uint32(pGuild->GetMemberSlotWithdrawRem(GetPlayer()->GetGUIDLow(), uint8(i))); - } - SendPacket(&data); - sLog.outDebug("WORLD: Sent (MSG_GUILD_PERMISSIONS)"); - } - } -} - -/* Called when clicking on Guild bank gameobject */ -void WorldSession::HandleGuildBankerActivate(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received (CMSG_GUILD_BANKER_ACTIVATE)"); - - uint64 GoGuid; - uint8 unk; - recv_data >> GoGuid >> unk; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - return; - - if (uint32 GuildId = GetPlayer()->GetGuildId()) - { - if (Guild *pGuild = objmgr.GetGuildById(GuildId)) - { - pGuild->DisplayGuildBankTabsInfo(this); // this also will load guild bank if not yet - return; - } - } - - SendGuildCommandResult(GUILD_UNK1, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); -} - -/* Called when opening guild bank tab only (first one) */ -void WorldSession::HandleGuildBankQueryTab(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_QUERY_TAB)"); - - uint64 GoGuid; - uint8 TabId, unk1; - recv_data >> GoGuid >> TabId >> unk1; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - return; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (!GuildId) - return; - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - - if (TabId >= pGuild->GetPurchasedTabs()) - return; - - // Let's update the amount of gold the player can withdraw before displaying the content - // This is useful if money withdraw right has changed - pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); - pGuild->DisplayGuildBankContent(this, TabId); -} - -void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_DEPOSIT_MONEY)"); - - uint64 GoGuid; - uint32 money; - recv_data >> GoGuid >> money; - - if (!money) - return; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - return; - - if (GetPlayer()->GetMoney() < money) - return; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (!GuildId) - return; - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - - if (!pGuild->GetPurchasedTabs()) - return; - - CharacterDatabase.BeginTransaction(); - - pGuild->SetBankMoney(pGuild->GetGuildBankMoney()+money); - GetPlayer()->ModifyMoney(-int(money)); - GetPlayer()->SaveGoldToDB(); - - CharacterDatabase.CommitTransaction(); - - // logging money - if (_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) - { - sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit money (Amount: %u) to guild bank (Guild ID %u)", - _player->GetName(),_player->GetSession()->GetAccountId(),money,GuildId); - } - - // log - pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); - - pGuild->DisplayGuildBankTabsInfo(this); - pGuild->DisplayGuildBankContent(this, 0); - pGuild->DisplayGuildBankMoneyUpdate(this); -} - -void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_WITHDRAW_MONEY)"); - - uint64 GoGuid; - uint32 money; - recv_data >> GoGuid >> money; - - if (!money) - return; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - return; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (GuildId == 0) - return; - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - - if (!pGuild->GetPurchasedTabs()) - return; - - if (pGuild->GetGuildBankMoney()HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_WITHDRAW_GOLD)) - return; - - CharacterDatabase.BeginTransaction(); - - if (!pGuild->MemberMoneyWithdraw(money, GetPlayer()->GetGUIDLow())) - { - CharacterDatabase.RollbackTransaction(); - return; - } - - GetPlayer()->ModifyMoney(money); - GetPlayer()->SaveGoldToDB(); - - CharacterDatabase.CommitTransaction(); - - // Log - pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); - - pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); - pGuild->DisplayGuildBankTabsInfo(this); - pGuild->DisplayGuildBankContent(this,0); - pGuild->DisplayGuildBankMoneyUpdate(this); -} - -void WorldSession::HandleGuildBankSwapItems(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_SWAP_ITEMS)"); - - uint64 GoGuid; - uint8 BankToBank; - - uint8 BankTab, BankTabSlot, AutoStore; - uint8 PlayerSlot = NULL_SLOT; - uint8 PlayerBag = NULL_BAG; - uint8 BankTabDst = 0, BankTabSlotDst = 0, unk2; - uint8 ToChar = 1; - uint32 ItemEntry, unk1; - uint32 AutoStoreCount = 0; - uint32 SplitedAmount = 0; - - recv_data >> GoGuid >> BankToBank; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (!GuildId) - { - recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet - return; - } - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - { - recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet - return; - } - - if (BankToBank) - { - recv_data >> BankTabDst; - recv_data >> BankTabSlotDst; - recv_data >> unk1; // always 0 - recv_data >> BankTab; - recv_data >> BankTabSlot; - recv_data >> ItemEntry; - recv_data >> unk2; // always 0 - recv_data >> SplitedAmount; - - if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS || - (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) || - BankTab >= pGuild->GetPurchasedTabs() || - BankTabDst >= pGuild->GetPurchasedTabs()) - { - recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet - return; - } - } - else - { - recv_data >> BankTab; - recv_data >> BankTabSlot; - recv_data >> ItemEntry; - recv_data >> AutoStore; - if (AutoStore) - { - recv_data >> AutoStoreCount; - recv_data.read_skip(); // ToChar (?), always and expected to be 1 (autostore only triggered in guild->ToChar) - recv_data.read_skip(); // unknown, always 0 - } - else - { - recv_data >> PlayerBag; - recv_data >> PlayerSlot; - recv_data >> ToChar; - recv_data >> SplitedAmount; - } - - if (BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF || - BankTab >= pGuild->GetPurchasedTabs()) - { - recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet - return; - } - } - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - return; - - if (BankTab >= pGuild->GetPurchasedTabs()) - return; - - // Bank <-> Bank - if (BankToBank) - { - pGuild->SwapItems(_player, BankTab, BankTabSlot, BankTabDst, BankTabSlotDst, SplitedAmount); - return; - } - - // Player <-> Bank - - // allow work with inventory only - if (!Player::IsInventoryPos(PlayerBag, PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT)) - { - _player->SendEquipError(EQUIP_ERR_NONE, NULL, NULL); - return; - } - - // BankToChar swap or char to bank remaining - if (ToChar) // Bank -> Char cases - pGuild->MoveFromBankToChar(_player, BankTab, BankTabSlot, PlayerBag, PlayerSlot, SplitedAmount); - else // Char -> Bank cases - pGuild->MoveFromCharToBank(_player, PlayerBag, PlayerSlot, BankTab, BankTabSlot, SplitedAmount); -} - -void WorldSession::HandleGuildBankBuyTab(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_BUY_TAB)"); - - uint64 GoGuid; - uint8 TabId; - - recv_data >> GoGuid; - recv_data >> TabId; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - return; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (!GuildId) - return; - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - - // m_PurchasedTabs = 0 when buying Tab 0, that is why this check can be made - if (TabId != pGuild->GetPurchasedTabs()) - return; - - uint32 TabCost = GetGuildBankTabPrice(TabId) * GOLD; - if (!TabCost) - return; - - if (GetPlayer()->GetMoney() < TabCost) // Should not happen, this is checked by client - return; - - // Go on with creating tab - pGuild->CreateNewBankTab(); - GetPlayer()->ModifyMoney(-int(TabCost)); - pGuild->SetBankMoneyPerDay(GetPlayer()->GetRank(), WITHDRAW_MONEY_UNLIMITED); - pGuild->SetBankRightsAndSlots(GetPlayer()->GetRank(), TabId, GUILD_BANK_RIGHT_FULL, WITHDRAW_SLOT_UNLIMITED, true); - pGuild->Roster(); // broadcast for tab rights update - pGuild->DisplayGuildBankTabsInfo(this); -} - -void WorldSession::HandleGuildBankUpdateTab(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_UPDATE_TAB)"); - - uint64 GoGuid; - uint8 TabId; - std::string Name; - std::string IconIndex; - - recv_data >> GoGuid; - recv_data >> TabId; - recv_data >> Name; - recv_data >> IconIndex; - - if (Name.empty()) - return; - - if (IconIndex.empty()) - return; - - if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) - return; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (!GuildId) - return; - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - - if (TabId >= pGuild->GetPurchasedTabs()) - return; - - pGuild->SetGuildBankTabInfo(TabId, Name, IconIndex); - pGuild->DisplayGuildBankTabsInfo(this); - pGuild->DisplayGuildBankContent(this, TabId); -} - -void WorldSession::HandleGuildBankLogQuery(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_LOG_QUERY)"); - - uint8 TabId; - recv_data >> TabId; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (!GuildId) - return; - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - - // GUILD_BANK_MAX_TABS send by client for money log - if (TabId >= pGuild->GetPurchasedTabs() && TabId != GUILD_BANK_MAX_TABS) - return; - - pGuild->DisplayGuildBankLogs(this, TabId); -} - -void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Received MSG_QUERY_GUILD_BANK_TEXT"); - - uint8 TabId; - recv_data >> TabId; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (!GuildId) - return; - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - - if (TabId >= pGuild->GetPurchasedTabs()) - return; - - pGuild->SendGuildBankTabText(this, TabId); -} - -void WorldSession::HandleSetGuildBankTabText(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_SET_GUILD_BANK_TEXT"); - - uint8 TabId; - std::string Text; - recv_data >> TabId; - recv_data >> Text; - - uint32 GuildId = GetPlayer()->GetGuildId(); - if (!GuildId) - return; - - Guild *pGuild = objmgr.GetGuildById(GuildId); - if (!pGuild) - return; - - if (TabId >= pGuild->GetPurchasedTabs()) - return; - - pGuild->SetGuildBankTabText(TabId, Text); -} - -void WorldSession::SendSaveGuildEmblem(uint32 msg) -{ - WorldPacket data(MSG_SAVE_GUILD_EMBLEM, 4); - data << uint32(msg); // not part of guild - SendPacket(&data); -} diff --git a/src/server/game/LookingForGroup/LFG.h b/src/server/game/LookingForGroup/LFG.h deleted file mode 100644 index c1b55443852..00000000000 --- a/src/server/game/LookingForGroup/LFG.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _LFG_H -#define _LFG_H - -#include "Platform/Define.h" -#include "Object.h" - -enum LfgRoles -{ - ROLE_NONE = 0x00, - ROLE_LEADER = 0x01, - ROLE_TANK = 0x02, - ROLE_HEALER = 0x04, - ROLE_DAMAGE = 0x08, -}; - -enum LfgUpdateType -{ - LFG_UPDATETYPE_LEADER = 1, - LFG_UPDATETYPE_ROLECHECK_ABORTED = 4, - LFG_UPDATETYPE_JOIN_PROPOSAL = 5, - LFG_UPDATETYPE_ROLECHECK_FAILED = 6, - LFG_UPDATETYPE_REMOVED_FROM_QUEUE = 7, - LFG_UPDATETYPE_PROPOSAL_FAILED = 8, - LFG_UPDATETYPE_PROPOSAL_DECLINED = 9, - LFG_UPDATETYPE_GROUP_FOUND = 10, - LFG_UPDATETYPE_ADDED_TO_QUEUE = 12, - LFG_UPDATETYPE_PROPOSAL_FOUND = 13, - LFG_UPDATETYPE_CLEAR_LOCK_LIST = 14, - LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 15, - LFG_UPDATETYPE_GROUP_DISBAND = 16, -}; - -typedef std::set LfgDungeonSet; - -struct LookingForGroup -{ - LookingForGroup(): roles(0) - { - donerandomDungeons.clear(); - applyDungeons.clear(); - } - std::string comment; - int8 roles; - - bool isDungeonDone(const uint32 entry) - { - return donerandomDungeons.find(entry) != donerandomDungeons.end(); - } - - LfgDungeonSet applyDungeons; // Dungeons the player have applied for - LfgDungeonSet donerandomDungeons; // Finished random Dungeons (to calculate the bonus); -}; - -#endif diff --git a/src/server/game/LookingForGroup/LFGHandler.cpp b/src/server/game/LookingForGroup/LFGHandler.cpp deleted file mode 100644 index 0746973ff4c..00000000000 --- a/src/server/game/LookingForGroup/LFGHandler.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "LFGMgr.h" -#include "WorldSession.h" -#include "WorldPacket.h" -#include "Player.h" - -void WorldSession::HandleLfgJoinOpcode(WorldPacket &recv_data) -{ - sLog.outDebug("CMSG_LFG_JOIN"); - - uint8 numDungeons; - uint32 dungeon; - uint32 roles; - std::string comment; - - recv_data >> roles; - recv_data.read_skip(); // unk - always 0 - recv_data.read_skip(); // unk - always 0 - recv_data >> numDungeons; - if (!numDungeons) - { - sLog.outError("Invalid CMSG_LFG_JOIN packet sent by %s", GetPlayer()->GetName()); - recv_data.rpos(recv_data.wpos()); - return; - } - - GetPlayer()->m_lookingForGroup.roles = uint8(roles); - for (int8 i = 0 ; i < numDungeons; ++i) - { - recv_data >> dungeon; - // remove the type from the dungeon entry - GetPlayer()->m_lookingForGroup.applyDungeons.insert((dungeon & 0x00FFFFFF)); - } - - recv_data >> numDungeons; // unk - always 3 - for (int8 i = 0 ; i < numDungeons; ++i) - recv_data.read_skip(); // unk - always 0 - - recv_data >> comment; - - GetPlayer()->m_lookingForGroup.comment = comment; - sLFGMgr.Join(GetPlayer()); -} - -void WorldSession::HandleLfgLeaveOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("CMSG_LFG_LEAVE"); - - // Check cheating - only leader can leave the queue - if (Group *grp = GetPlayer()->GetGroup()) - { - if (grp->GetLeaderGUID() != GetPlayer()->GetGUID()) - return; - else - sLFGMgr.Leave(GetPlayer(), grp); - } - else - sLFGMgr.Leave(GetPlayer()); -} - -void WorldSession::HandleLfgSetRolesOpcode(WorldPacket &recv_data) -{ - sLog.outDebug("CMSG_LFG_SET_ROLES"); - - uint8 roles; - recv_data >> roles; // Player Group Roles - - Group *grp = GetPlayer()->GetGroup(); - if (!grp) - return; - GetPlayer()->m_lookingForGroup.roles = roles; - sLFGMgr.UpdateRoleCheck(grp, GetPlayer()); -} - -void WorldSession::HandleSetLfgCommentOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_SET_LFG_COMMENT"); - - std::string comment; - recv_data >> comment; - - GetPlayer()->m_lookingForGroup.comment = comment; -} - -void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket &/*recv_data*/) -{ - sLog.outDebug("CMSG_LFD_PLAYER_LOCK_INFO_REQUEST"); - sLFGMgr.SendLfgPlayerInfo(GetPlayer()); -} - -void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket &/*recv_data*/) -{ - sLog.outDebug("CMSG_LFD_PARTY_LOCK_INFO_REQUEST"); - sLFGMgr.SendLfgPartyInfo(GetPlayer()); -} - -void WorldSession::SendLfgUpdatePlayer(uint8 updateType) -{ - bool queued = false; - bool extrainfo = false; - - switch(updateType) - { - case LFG_UPDATETYPE_JOIN_PROPOSAL: - case LFG_UPDATETYPE_ADDED_TO_QUEUE: - queued = true; - extrainfo = true; - break; - //case LFG_UPDATETYPE_CLEAR_LOCK_LIST: // TODO: Sometimes has extrainfo - Check ocurrences... - case LFG_UPDATETYPE_PROPOSAL_FOUND: - extrainfo = true; - break; - } - sLog.outDebug("SMSG_LFG_UPDATE_PLAYER"); - WorldPacket data(SMSG_LFG_UPDATE_PLAYER, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + GetPlayer()->m_lookingForGroup.applyDungeons.size() * 4 + GetPlayer()->m_lookingForGroup.comment.length())); - data << uint8(updateType); // Lfg Update type - data << uint8(extrainfo); // Extra info - if (extrainfo) - { - data << uint8(queued); // Join the queue - data << uint8(0); // unk - Always 0 - data << uint8(0); // unk - Always 0 - - uint8 size = GetPlayer()->m_lookingForGroup.applyDungeons.size(); - data << uint8(size); - - for (LfgDungeonSet::const_iterator it = GetPlayer()->m_lookingForGroup.applyDungeons.begin(); it != GetPlayer()->m_lookingForGroup.applyDungeons.end(); ++it) - data << uint32(*it); - data << GetPlayer()->m_lookingForGroup.comment; - } - SendPacket(&data); -} - -void WorldSession::SendLfgUpdateParty(uint8 updateType) -{ - bool join = false; - bool extrainfo = false; - bool queued = false; - - switch(updateType) - { - case LFG_UPDATETYPE_JOIN_PROPOSAL: - extrainfo = true; - break; - case LFG_UPDATETYPE_ADDED_TO_QUEUE: - extrainfo = true; - join = true; - queued = true; - break; - case LFG_UPDATETYPE_CLEAR_LOCK_LIST: - // join = true; // TODO: Sometimes queued and extrainfo - Check ocurrences... - queued = true; - break; - case LFG_UPDATETYPE_PROPOSAL_FOUND: - extrainfo = true; - join = true; - break; - } - - sLog.outDebug("SMSG_LFG_UPDATE_PARTY"); - WorldPacket data(SMSG_LFG_UPDATE_PARTY, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + 1 + GetPlayer()->m_lookingForGroup.applyDungeons.size() * 4 + GetPlayer()->m_lookingForGroup.comment.length())); - data << uint8(updateType); // Lfg Update type - data << uint8(extrainfo); // Extra info - if (extrainfo) - { - data << uint8(join); // LFG Join - data << uint8(queued); // Join the queue - data << uint8(0); // unk - Always 0 - data << uint8(0); // unk - Always 0 - for (uint8 i = 0; i < 3; ++i) - data << uint8(0); // unk - Always 0 - - uint8 size = GetPlayer()->m_lookingForGroup.applyDungeons.size(); - data << uint8(size); - - for (LfgDungeonSet::const_iterator it = GetPlayer()->m_lookingForGroup.applyDungeons.begin(); it != GetPlayer()->m_lookingForGroup.applyDungeons.end(); ++it) - data << uint32(*it); - - data << GetPlayer()->m_lookingForGroup.comment; - } - SendPacket(&data); -} - -void WorldSession::SendLfgRoleChosen(uint64 guid, uint8 roles) -{ - sLog.outDebug("SMSG_LFG_ROLE_CHOSEN"); - - WorldPacket data(SMSG_LFG_ROLE_CHOSEN); - data << uint64(guid); // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - SendPacket(&data); -} - -void WorldSession::SendLfgJoinResult(uint8 checkResult, uint8 checkValue) -{ - if (checkResult == LFG_JOIN_PARTY_NOT_MEET_REQS) // Should never happen - its handled in Mgr - return; - - sLog.outDebug("SMSG_LFG_JOIN_RESULT"); - - WorldPacket data(SMSG_LFG_JOIN_RESULT); - data << uint32(checkResult); // Check Result - data << uint32(checkValue); // Check Value - SendPacket(&data); -} - -void WorldSession::SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps) -{ - sLog.outDebug("SMSG_LFG_QUEUE_STATUS"); - WorldPacket data(SMSG_LFG_QUEUE_STATUS); - - data << uint32(dungeon); // Dungeon - data << uint32(avgWaitTime); // Average Wait time - data << uint32(waitTime); // Wait Time - data << uint32(waitTimeTanks); // Wait Tanks - data << uint32(waitTimeHealer); // Wait Healers - data << uint32(waitTimeDps); // Wait Dps - data << uint8(tanks); // Tanks needed - data << uint8(healers); // Healers needed - data << uint8(dps); // Dps needed - data << uint32(queuedTime); // Player wait time in queue - SendPacket(&data); -} - -void WorldSession::SendLfgUpdateSearch(bool update) -{ - sLog.outDebug("SMSG_LFG_UPDATE_SEARCH"); - - WorldPacket data(SMSG_LFG_UPDATE_SEARCH); - data << uint8(update); // In Lfg Queue? - SendPacket(&data); -} diff --git a/src/server/game/LookingForGroup/LFGMgr.cpp b/src/server/game/LookingForGroup/LFGMgr.cpp deleted file mode 100644 index ba418cdb191..00000000000 --- a/src/server/game/LookingForGroup/LFGMgr.cpp +++ /dev/null @@ -1,1100 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "Policies/SingletonImp.h" -#include "Common.h" -#include "SharedDefines.h" -#include "Group.h" -#include "Player.h" -#include "LFGMgr.h" -#include "ObjectMgr.h" -#include "WorldPacket.h" - -INSTANTIATE_SINGLETON_1(LFGMgr); - -/*********************************************************/ -/*** LFG QUEUES ***/ -/*********************************************************/ - -LFGQueue::LFGQueue() -{ - m_LfgQueue.clear(); - avgWaitTime = -1; - waitTimeTanks = -1; - waitTimeHealer = -1; - waitTimeDps = -1; -} - -LFGQueue::~LFGQueue() -{ - m_LfgQueue.clear(); -} - -void LFGQueue::AddToQueue(uint64 guid, LfgQueueInfo* pqInfo) -{ - if (LfgQueueInfo* qInfo = m_LfgQueue[guid]) - delete qInfo; - m_LfgQueue[guid] = pqInfo; - // ATM will only add it to the queue... No find group implementation... yet (on purpose) -} - -bool LFGQueue::RemoveFromQueue(uint64 guid) -{ - if (m_LfgQueue.empty()) - return false; - - LfgQueueInfoMap::iterator itr = m_LfgQueue.find(guid); - if (itr == m_LfgQueue.end()) - return false; - - delete itr->second; - m_LfgQueue.erase(itr); - return true; -} - -LfgQueueInfo* LFGQueue::GetQueueInfo(uint64 guid) -{ - return m_LfgQueue[guid]; -} - -void LFGQueue::Update() -{ - if (m_LfgQueue.empty()) - return; - - Player *plr; - LfgQueueInfo *queue; - time_t currTime = time(NULL); - uint32 queuedTime; - uint8 role = 0; - int32 waitTime = -1; - for (LfgQueueInfoMap::const_iterator itQueue = m_LfgQueue.begin(); itQueue != m_LfgQueue.end(); ++itQueue) - { - queue = itQueue->second; - // Update queue status - queuedTime = uint32(currTime - queue->joinTime); - for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) - { - plr = objmgr.GetPlayer(itPlayer->first); - if (!plr) - continue; - role = itPlayer->second; - if (role & ROLE_TANK) - { - if (role & ROLE_HEALER || role & ROLE_DAMAGE) - waitTime = avgWaitTime; - else - waitTime = waitTimeTanks; - } - else if (role & ROLE_HEALER) - { - if (role & ROLE_DAMAGE) - waitTime = avgWaitTime; - else - waitTime = waitTimeDps; - } - plr->GetSession()->SendLfgQueueStatus(queue->dungeonId, waitTime, avgWaitTime, waitTimeTanks, waitTimeHealer, waitTimeDps, queuedTime, queue->tanks, queue->healers, queue->dps); - } - } -} - -LFGMgr::LFGMgr() -{ - m_QueueTimer = 0; - m_update = true; -} - -LFGMgr::~LFGMgr() -{ - // RewardList to be removed -> query quest system - for (LfgRewardList::iterator it = m_RewardList.begin(); it != m_RewardList.end(); ++it) - delete *it; - m_RewardList.clear(); - - // RewardDoneList to be removed -> query quest system - for (LfgRewardList::iterator it = m_RewardDoneList.begin(); it != m_RewardDoneList.end(); ++it) - delete *it; - m_RewardDoneList.clear(); - - for(LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it) - delete it->second; - m_Queues.clear(); - - for (LfgDungeonMap::iterator it = m_DungeonsMap.begin(); it != m_DungeonsMap.end(); ++it) - { - it->second->clear(); - delete it->second; - } - m_DungeonsMap.clear(); - - for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end(); ++it) - delete it->second; - m_RoleChecks.clear(); -} - -void LFGMgr::Update(uint32 diff) -{ - if (!m_update) - return; - - // Update all players status queue info - if (m_QueueTimer > LFG_QUEUEUPDATE_INTERVAL) - { - m_QueueTimer = 0; - for (LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it) - it->second->Update(); - } - else - m_QueueTimer += diff; - - time_t currTime = time(NULL); - - // Remove obsolete role checks - LfgRoleCheckMap::iterator itRoleCheck; - LfgRoleCheck *pRoleCheck; - for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end();) - { - itRoleCheck = it++; - pRoleCheck = itRoleCheck->second; - if (currTime < pRoleCheck->cancelTime) - continue; - pRoleCheck->result = LFG_ROLECHECK_MISSING_ROLE; - - WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + pRoleCheck->dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1)); - sLog.outDebug("SMSG_LFG_ROLE_CHECK_UPDATE"); - BuildLfgRoleCheck(data, pRoleCheck); - Player *plr = NULL; - for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end(); ++itRoles) - { - plr = objmgr.GetPlayer(itRoles->first); - if (!plr) - continue; - plr->GetSession()->SendPacket(&data); - plr->m_lookingForGroup.applyDungeons.clear(); - plr->m_lookingForGroup.roles = 0; - - if (itRoles->first == pRoleCheck->leader) - plr->GetSession()->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result); - } - delete pRoleCheck; - m_RoleChecks.erase(itRoleCheck); - } -} - -/// -/// Initialize Looking For Group -/// -void LFGMgr::InitLFG() -{ - // Fill reward data (to be removed -> query quest system) - LfgReward *reward; - for (uint8 i = 0; i <= LFG_REWARD_DATA_SIZE; ++i) - { - reward = new LfgReward(); - reward->strangers = 0; - reward->baseXP = RewardDungeonData[i][0]; - reward->baseMoney = RewardDungeonData[i][1]; - reward->variableMoney = 0; - reward->variableXP = 0; - reward->itemId = RewardDungeonData[i][2]; - reward->displayId = RewardDungeonData[i][3]; - reward->stackCount = RewardDungeonData[i][4]; - m_RewardList.push_back(reward); - } - - for (uint8 i = 0; i < LFG_REWARD_DATA_SIZE; ++i) - { - reward = new LfgReward(); - reward->strangers = 0; - reward->baseXP = RewardDungeonDoneData[i][0]; - reward->baseMoney = RewardDungeonDoneData[i][1]; - reward->variableMoney = 0; - reward->variableXP = 0; - reward->itemId = RewardDungeonDoneData[i][2]; - reward->displayId = RewardDungeonDoneData[i][3]; - reward->stackCount = RewardDungeonDoneData[i][4]; - m_RewardDoneList.push_back(reward); - } - // Initialize dungeonMap - m_DungeonsMap[LFG_ALL_DUNGEONS] = GetAllDungeons(); - m_DungeonsMap[LFG_RANDOM_CLASSIC] = GetDungeonsByRandom(LFG_RANDOM_CLASSIC); - m_DungeonsMap[LFG_RANDOM_BC_NORMAL] = GetDungeonsByRandom(LFG_RANDOM_BC_NORMAL); - m_DungeonsMap[LFG_RANDOM_BC_HEROIC] = GetDungeonsByRandom(LFG_RANDOM_BC_HEROIC); - m_DungeonsMap[LFG_RANDOM_LK_NORMAL] = GetDungeonsByRandom(LFG_RANDOM_LK_NORMAL); - m_DungeonsMap[LFG_RANDOM_LK_HEROIC] = GetDungeonsByRandom(LFG_RANDOM_LK_HEROIC); -} - -/// -/// Adds the player to lfg queue -/// -/// Player -void LFGMgr::Join(Player *plr) -{ - Group *grp = plr->GetGroup(); - - // TODO - 2010-05-27 Anyone can init rolecheck when already in a LFD Group? - if (grp && grp->GetLeaderGUID() != plr->GetGUID()) - return; - - // Previous checks before joining - LfgJoinResult result = LFG_JOIN_OK; - if (plr->InBattleGround() || plr->InArena()) - result = LFG_JOIN_USING_BG_SYSTEM; - else if (plr->HasAura(LFG_SPELL_DESERTER)) - result = LFG_JOIN_DESERTER; - else if (plr->HasAura(LFG_SPELL_COOLDOWN)) - result = LFG_JOIN_RANDOM_COOLDOWN; - else - { - // Check if all dungeons are valid - for (LfgDungeonSet::const_iterator it = plr->m_lookingForGroup.applyDungeons.begin(); it != plr->m_lookingForGroup.applyDungeons.end(); ++it) - { - if ((m_DungeonsMap[LFG_ALL_DUNGEONS])->find(*it) == (m_DungeonsMap[LFG_ALL_DUNGEONS])->end()) - { - result = LFG_JOIN_DUNGEON_INVALID; - break; - } - } - } - - if (grp && result == LFG_JOIN_OK) - { - if (grp->GetMembersCount() > MAXGROUPSIZE) - result = LFG_JOIN_TOO_MUCH_MEMBERS; - else if(grp->isRaidGroup()) - result = LFG_JOIN_MIXED_RAID_DUNGEON; - else - { - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL && result == LFG_JOIN_OK; itr = itr->next()) - { - if (Player *plrg = itr->getSource()) - { - if (plrg->HasAura(LFG_SPELL_DESERTER)) - result = LFG_JOIN_PARTY_DESERTER; - else if (plrg->HasAura(LFG_SPELL_COOLDOWN)) - result = LFG_JOIN_PARTY_RANDOM_COOLDOWN; - } - else - result = LFG_JOIN_DISCONNECTED; - } - } - } - - if (result != LFG_JOIN_OK) - { - plr->m_lookingForGroup.applyDungeons.clear(); - plr->m_lookingForGroup.roles = 0; - plr->GetSession()->SendLfgJoinResult(result, 0); - return; - } - - if (grp) - { - Player *plrg = NULL; - for (GroupReference *itr = plr->GetGroup()->GetFirstMember(); itr != NULL; itr = itr->next()) - { - plrg = itr->getSource(); // Not null, checked earlier - plrg->m_lookingForGroup.applyDungeons = plr->m_lookingForGroup.applyDungeons; - plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_JOIN_PROPOSAL); - } - UpdateRoleCheck(grp, plr); - } - else - { - plr->GetSession()->SendLfgJoinResult(LFG_JOIN_OK, 0); - plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_JOIN_PROPOSAL); - - // Add player to queue - LfgQueueInfo *pqInfo; - uint8 groupType = 0; - uint8 tanks = LFG_TANKS_NEEDED; - uint8 healers = LFG_HEALERS_NEEDED; - uint8 dps = LFG_DPS_NEEDED; - if (plr->m_lookingForGroup.roles & ROLE_TANK) - --tanks; - else if (plr->m_lookingForGroup.roles & ROLE_HEALER) - --healers; - else - --dps; - m_update = false; - for (LfgDungeonSet::const_iterator it = plr->m_lookingForGroup.applyDungeons.begin(); it != plr->m_lookingForGroup.applyDungeons.end(); ++it) - { - groupType = GetDungeonGroupType(*it); - pqInfo = m_Queues[groupType] ? m_Queues[groupType]->GetQueueInfo(plr->GetGUID()) : NULL; - // if exist we have already added the player with another dungeon sharing same GroupType - if (pqInfo) - continue; - pqInfo = new LfgQueueInfo(); - pqInfo->dungeonId = *it; - pqInfo->joinTime = time_t(time(NULL)); - pqInfo->tanks = tanks; - pqInfo->healers = healers; - pqInfo->dps = dps; - pqInfo->roles[plr->GetGUID()] = plr->m_lookingForGroup.roles; - if (!m_Queues[groupType]) - m_Queues[groupType] = new LFGQueue(); - m_Queues[groupType]->AddToQueue(plr->GetGUID(), pqInfo); - } - m_update = true; - } -} - -/// -/// Leave the lfg queue -/// -/// Player (could be NULL) -/// Group (could be NULL) -void LFGMgr::Leave(Player *plr, Group *grp /* = NULL*/) -{ - uint64 guid = grp ? grp->GetGUID() : plr ? plr->GetGUID() : 0; - assert(guid); - - // Check if player was in a rolecheck - if (grp) - { - LfgRoleCheckMap::iterator itRoleCheck = m_RoleChecks.find(GUID_LOPART(grp->GetGUID())); - if (itRoleCheck != m_RoleChecks.end()) - { - UpdateRoleCheck(grp); // No player to update role = LFG_ROLECHECK_ABORTED - return; - } - } - - // Check if player/group was in the queue - bool inQueue = false; - for (LFGQueueMap::iterator it = m_Queues.begin(); it != m_Queues.end(); ++it) - inQueue |= it->second->RemoveFromQueue(guid); - - // Not in queue - if (!inQueue) - return; - - if (grp) - { - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - if (Player *plrg = itr->getSource()) - { - plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - plrg->m_lookingForGroup.applyDungeons.clear(); - plrg->m_lookingForGroup.roles = 0; - } - } - else - { - plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - plr->m_lookingForGroup.applyDungeons.clear(); - plr->m_lookingForGroup.roles = 0; - } -} - -/// -/// Update the Role check info with the player selected role. -/// -/// Group -/// Player -void LFGMgr::UpdateRoleCheck(Group *grp, Player *plr /* = NULL*/) -{ - assert(grp); - - uint32 rolecheckId = GUID_LOPART(grp->GetGUID()); - LfgRoleCheck *pRoleCheck = NULL; - LfgRolesMap check_roles; - LfgRoleCheckMap::iterator itRoleCheck = m_RoleChecks.find(rolecheckId); - bool newRoleCheck = itRoleCheck == m_RoleChecks.end(); - if (newRoleCheck) - { - if (!grp->IsLeader(plr->GetGUID())) - return; - - pRoleCheck = new LfgRoleCheck(); - pRoleCheck->cancelTime = time_t(time(NULL)) + LFG_TIME_ROLECHECK; - pRoleCheck->result = LFG_ROLECHECK_INITIALITING; - pRoleCheck->leader = plr->GetGUID(); - - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - if (Player *plrg = itr->getSource()) - pRoleCheck->roles[plrg->GetGUID()] = 0; - - pRoleCheck->dungeons = plr->m_lookingForGroup.applyDungeons; - } - else - pRoleCheck = itRoleCheck->second; - - LfgLockStatusMap *playersLockMap = NULL; - if (plr) - { - // Player selected no role. - if (plr->m_lookingForGroup.roles < ROLE_TANK) - pRoleCheck->result = LFG_ROLECHECK_NO_ROLE; - else - { - // Check if all players have selected a role - pRoleCheck->roles[plr->GetGUID()] = plr->m_lookingForGroup.roles; - uint8 size = 0; - for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end() && itRoles->second != ROLE_NONE; ++itRoles) - ++size; - - if (pRoleCheck->roles.size() == size) - { - // use temporal var to check roles, CheckGroupRoles modifies the roles - for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end(); ++itRoles) - check_roles[itRoles->first] = itRoles->second; - - if (!CheckGroupRoles(check_roles)) // Group is not posible - pRoleCheck->result = LFG_ROLECHECK_WRONG_ROLES; - else - { - // Check if we can find a dungeon for that group - pRoleCheck->result = LFG_ROLECHECK_FINISHED; - if (pRoleCheck->dungeons.size() > 1) - playersLockMap = GetPartyLockStatusDungeons(plr, &pRoleCheck->dungeons); - else - { - LfgDungeonSet::const_iterator it = pRoleCheck->dungeons.begin(); - LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(*it); - if (dungeon && dungeon->type == LFG_TYPE_RANDOM) - playersLockMap = GetPartyLockStatusDungeons(plr, m_DungeonsMap[*it]); - else - playersLockMap = GetPartyLockStatusDungeons(plr, &pRoleCheck->dungeons); - } - } - } - } - } - else - pRoleCheck->result = LFG_ROLECHECK_ABORTED; - - WorldSession *session; - WorldPacket data(SMSG_LFG_ROLE_CHECK_UPDATE, 4 + 1 + 1 + pRoleCheck->dungeons.size() * 4 + 1 + pRoleCheck->roles.size() * (8 + 1 + 4 + 1)); - sLog.outDebug("SMSG_LFG_ROLE_CHECK_UPDATE"); - BuildLfgRoleCheck(data, pRoleCheck); - - Player *plrg = NULL; - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - plrg = itr->getSource(); - if (!plrg) - continue; - - session = plrg->GetSession(); - if (!newRoleCheck && plr) - session->SendLfgRoleChosen(plr->GetGUID(), plr->m_lookingForGroup.roles); - session->SendPacket(&data); - - switch(pRoleCheck->result) - { - case LFG_ROLECHECK_INITIALITING: - continue; - case LFG_ROLECHECK_FINISHED: - if (!playersLockMap) - { - session->SendLfgUpdateParty(LFG_UPDATETYPE_ADDED_TO_QUEUE); - } - else - { - if (grp->IsLeader(plrg->GetGUID())) - { - uint32 size = 0; - for (LfgLockStatusMap::const_iterator it = playersLockMap->begin(); it != playersLockMap->end(); ++it) - size += 8 + 4 + it->second->size() * (4 + 4); - WorldPacket data(SMSG_LFG_JOIN_RESULT, 4 + 4 + size); - sLog.outDebug("SMSG_LFG_JOIN_RESULT"); - data << uint32(LFG_JOIN_PARTY_NOT_MEET_REQS); // Check Result - data << uint32(0); // Check Value (always 0 when PartyNotMeetReqs - BuildPartyLockDungeonBlock(data, playersLockMap); - session->SendPacket(&data); - } - session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED); - plrg->m_lookingForGroup.applyDungeons.clear(); - plrg->m_lookingForGroup.roles = 0; - } - break; - default: - if (grp->IsLeader(plrg->GetGUID())) - session->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result); - session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED); - plrg->m_lookingForGroup.applyDungeons.clear(); - plrg->m_lookingForGroup.roles = 0; - break; - } - } - - if (pRoleCheck->result == LFG_ROLECHECK_FINISHED) - { - // Add qroup to queue - LfgQueueInfo *pqInfo; - uint8 groupType = 0; - uint8 tanks = LFG_TANKS_NEEDED; - uint8 healers = LFG_HEALERS_NEEDED; - uint8 dps = LFG_DPS_NEEDED; - for (LfgRolesMap::const_iterator it = check_roles.begin(); it != check_roles.end(); ++it) - { - if (it->second & ROLE_TANK) - --tanks; - else if (it->second & ROLE_HEALER) - --healers; - else - --dps; - } - uint64 guid = grp->GetGUID(); - m_update = false; - for (LfgDungeonSet::const_iterator it = pRoleCheck->dungeons.begin(); it != pRoleCheck->dungeons.end(); ++it) - { - groupType = GetDungeonGroupType(*it); - pqInfo = m_Queues[groupType] ? m_Queues[groupType]->GetQueueInfo(guid) : NULL; - // if exist we have already added the player with another dungeon sharing same GroupType - if (pqInfo) - continue; - pqInfo = new LfgQueueInfo(); - pqInfo->dungeonId = *it; - pqInfo->joinTime = time_t(time(NULL)); - pqInfo->tanks = tanks; - pqInfo->healers = healers; - pqInfo->dps = dps; - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - if (Player *plrg = itr->getSource()) - pqInfo->roles[plrg->GetGUID()] = plrg->m_lookingForGroup.roles; - } - if (!m_Queues[groupType]) - m_Queues[groupType] = new LFGQueue(); - m_Queues[groupType]->AddToQueue(guid, pqInfo); - } - m_update = true; - } - - if (pRoleCheck->result != LFG_ROLECHECK_INITIALITING) - { - delete pRoleCheck; - if (!newRoleCheck) - m_RoleChecks.erase(itRoleCheck); - } - else if (newRoleCheck) - m_RoleChecks[rolecheckId] = pRoleCheck; -} - -/// -/// Check if a group can be formed with the given group -/// -/// Map of roles -/// bool, will be used to remove ROLE_LEADER -/// bool -bool LFGMgr::CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag /*= true*/) -{ - if (!groles.size()) - return false; - - uint8 damage = 0; - uint8 tank = 0; - uint8 healer = 0; - uint64 tguid = 0; - uint64 hguid = 0; - uint64 dguid = 0; - uint64 guid = 0; - uint8 role = 0; - - if (removeLeaderFlag) - for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it) - it->second &= ~ROLE_LEADER; - - for (LfgRolesMap::const_iterator it = groles.begin(); it != groles.end(); ++it) - { - guid = it->first; - role = it->second; - - if (role == ROLE_NONE) - return false; - - if (role & ROLE_TANK) - { - if (!tank) - { - tguid = guid; - ++tank; - } - else - { - if (groles[tguid] == ROLE_TANK) - tguid = guid; - groles[tguid] -= ROLE_TANK; - return CheckGroupRoles(groles, false); - } - } - - if (role & ROLE_HEALER) - { - if (!healer) - { - hguid = guid; - ++healer; - } - else - { - if (groles[hguid] == ROLE_HEALER) - hguid = guid; - groles[hguid] -= ROLE_HEALER; - return CheckGroupRoles(groles, false); - } - } - - if (role & ROLE_DAMAGE) - { - if (damage < 3) - { - if (!damage) - dguid = guid; - ++damage; - } - else - { - if (groles[dguid] == ROLE_DAMAGE) - dguid = guid; - groles[dguid] -= ROLE_DAMAGE; - if (!CheckGroupRoles(groles, false)) - groles[dguid] += ROLE_DAMAGE; - else - return true; - } - } - } - return true; -} - - - -// --------------------------------------------------------------------------// -// Packet Functions -// --------------------------------------------------------------------------// - -/// -/// Build lfgRolecheck packet -/// -/// WorldPacket -/// Player -/// Player status in LFG system -void LFGMgr::BuildLfgRoleCheck(WorldPacket &data, LfgRoleCheck *pRoleCheck) -{ - assert(pRoleCheck); - - Player *plr; - uint8 roles; - - data << uint32(pRoleCheck->result); // Check result - data << uint8(pRoleCheck->result == LFG_ROLECHECK_INITIALITING); - data << uint8(pRoleCheck->dungeons.size()); // Number of dungeons - LFGDungeonEntry const *dungeon; - for (LfgDungeonSet::iterator it = pRoleCheck->dungeons.begin(); it != pRoleCheck->dungeons.end(); ++it) - { - dungeon = sLFGDungeonStore.LookupEntry(*it); // not null - been checked at join time - data << uint32(dungeon->Entry()); // Dungeon - } - - data << uint8(pRoleCheck->roles.size()); // Players in group - // Leader info MUST be sent 1st :S - roles = pRoleCheck->roles[pRoleCheck->leader]; - data << uint64(pRoleCheck->leader); // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - plr = objmgr.GetPlayer(pRoleCheck->leader); - if (plr) - data << uint8(plr->getLevel()); // Level - else - data << uint8(0); - - for (LfgRolesMap::const_iterator itPlayers = pRoleCheck->roles.begin(); itPlayers != pRoleCheck->roles.end(); ++itPlayers) - { - if (itPlayers->first == pRoleCheck->leader) - continue; - - roles = itPlayers->second; - data << uint64(itPlayers->first); // Guid - data << uint8(roles > 0); // Ready - data << uint32(roles); // Roles - plr = objmgr.GetPlayer(pRoleCheck->leader); - if (plr) - data << uint8(plr->getLevel()); // Level - else - data << uint8(0); - } -} - -/// -/// Build and Send LFG lock player info and reward -/// -/// Player -void LFGMgr::SendLfgPlayerInfo(Player *plr) -{ - uint32 rsize = 0; - uint32 lsize = 0; - LfgDungeonSet *randomlist = GetRandomDungeons(plr->getLevel(), plr->GetSession()->Expansion()); - LfgLockStatusSet *lockSet = GetPlayerLockStatusDungeons(plr, m_DungeonsMap[LFG_ALL_DUNGEONS]); - if (randomlist) - rsize = randomlist->size(); - if (lockSet) - lsize = lockSet->size(); - - sLog.outDebug("SMSG_LFG_PLAYER_INFO"); - WorldPacket data(SMSG_LFG_PLAYER_INFO, 1 + rsize * (4 + 1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4) + 4 + lsize * (4 + 4)); - if (!randomlist) - data << uint8(0); - else - { - data << uint8(randomlist->size()); // Random Dungeon count - for (LfgDungeonSet::iterator it = randomlist->begin(); it != randomlist->end(); ++it) - { - data << uint32(*it); // Entry - BuildRewardBlock(data, *it, plr); - } - randomlist->clear(); - delete randomlist; - } - BuildPlayerLockDungeonBlock(data, lockSet); - plr->GetSession()->SendPacket(&data); -} - -/// -/// Build and Send LFG lock party info and reward -/// -/// Player -void LFGMgr::SendLfgPartyInfo(Player *plr) -{ - if (LfgLockStatusMap *lockMap = GetPartyLockStatusDungeons(plr, m_DungeonsMap[LFG_ALL_DUNGEONS])) - { - uint32 size = 0; - for (LfgLockStatusMap::const_iterator it = lockMap->begin(); it != lockMap->end(); ++it) - size += 8 + 4 + it->second->size() * (4 + 4); - sLog.outDebug("SMSG_LFG_PARTY_INFO"); - WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size); - BuildPartyLockDungeonBlock(data, lockMap); - plr->GetSession()->SendPacket(&data); - } -} - -/// -/// Build Reward packet structure for a given dungeon -/// -/// WorldPacket -/// Dungeon entry -/// Player -void LFGMgr::BuildRewardBlock(WorldPacket &data, uint32 dungeon, Player *plr) -{ - bool done = plr->m_lookingForGroup.isDungeonDone(dungeon); - LfgReward *reward = GetRandomDungeonReward(dungeon, done, plr->getLevel()); - - if (!reward) - return; - - data << uint8(done); - if (data.GetOpcode() == SMSG_LFG_PLAYER_REWARD) - data << uint32(reward->strangers); - data << uint32(reward->baseMoney); - data << uint32(reward->baseXP); - data << uint32(reward->variableMoney); - data << uint32(reward->variableXP); - data << uint8(reward->itemId != 0); - if (reward->itemId) - { - data << uint32(reward->itemId); - data << uint32(reward->displayId); - data << uint32(reward->stackCount); - } -} - -/// -/// Build Party Dungeon lock status packet -/// -/// WorldPacket -/// lock status map -void LFGMgr::BuildPartyLockDungeonBlock(WorldPacket &data, LfgLockStatusMap *lockMap) -{ - assert(lockMap); - - data << uint8(lockMap->size()); - - LfgLockStatusSet *lockSet; - uint64 guid; - for (LfgLockStatusMap::const_iterator it = lockMap->begin(); it != lockMap->end(); ++it) - { - guid = it->first; - lockSet = it->second; - if (!lockSet) - continue; - - data << uint64(guid); // Player guid - BuildPlayerLockDungeonBlock(data, lockSet); - } - lockMap->clear(); - delete lockMap; -} - -/// -/// Build Player Dungeon lock status packet -/// -/// WorldPacket -/// lock status list -void LFGMgr::BuildPlayerLockDungeonBlock(WorldPacket &data, LfgLockStatusSet *lockSet) -{ - assert(lockSet); - data << uint32(lockSet->size()); // Size of lock dungeons - for (LfgLockStatusSet::iterator it = lockSet->begin(); it != lockSet->end(); ++it) - { - data << uint32((*it)->dungeon); // Dungeon entry + type - data << uint32((*it)->lockstatus); // Lock status - delete (*it); - } - lockSet->clear(); - delete lockSet; -} - - - - -// --------------------------------------------------------------------------// -// Auxiliar Functions -// --------------------------------------------------------------------------// - -/// -/// Get all Group members list of dungeons that can't be done and reason -/// leader excluded as the list given is he list he can do -/// -/// Group -/// Dungeons to check -/// LfgLockStatusMap* -LfgLockStatusMap* LFGMgr::GetPartyLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons) -{ - assert(plr); - assert(dungeons); - Group *grp = plr->GetGroup(); - if (!grp) - return NULL; - - Player *plrg; - LfgLockStatusSet *dungeonSet = NULL; - LfgLockStatusMap *dungeonMap = new LfgLockStatusMap(); - for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - plrg = itr->getSource(); - if (!plrg || plrg == plr) - continue; - - dungeonSet = GetPlayerLockStatusDungeons(plrg, dungeons); - if (dungeonSet) - (*dungeonMap)[plrg->GetGUID()] = dungeonSet; - } - - if (!dungeonMap->size()) - { - delete dungeonMap; - dungeonMap = NULL; - } - return dungeonMap; -} - -/// -/// Get list of dungeons player can't do and reasons -/// -/// Player -/// Dungeons to check -/// LfgLockStatusSet* -LfgLockStatusSet* LFGMgr::GetPlayerLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons) -{ - LfgLockStatusSet *list = new LfgLockStatusSet(); - LfgLockStatus *lockstatus = NULL; - LFGDungeonEntry const *dungeon; - LfgLockStatusType locktype; - uint8 level = plr->getLevel(); - uint8 expansion = plr->GetSession()->Expansion(); - - for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it) - { - dungeon = sLFGDungeonStore.LookupEntry(*it); - assert(dungeon); // Will never happen - We provide a list from sLFGDungeonStore - - locktype = LFG_LOCKSTATUS_OK; - if (dungeon->expansion > expansion) - locktype = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; - else if (dungeon->minlevel > level) - locktype = LFG_LOCKSTATUS_TOO_LOW_LEVEL; - else if (dungeon->maxlevel < level) - locktype = LFG_LOCKSTATUS_TOO_HIGH_LEVEL; - /* TODO - Use these types when needed... - else if () - locktype = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE; - else if () - locktype = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE; - else if () // Locked due to WG, closed by GM, done daily, etc - locktype = LFG_LOCKSTATUS_RAID_LOCKED; - else if () - locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL; - else if () - locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL; - else if () // Need list of instances and needed quest to enter - locktype = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED; - else if () // Need list of instances and needed key to enter - locktype = LFG_LOCKSTATUS_MISSING_ITEM; - else if () // Need list of instances and needed season to open - locktype = LFG_LOCKSTATUS_NOT_IN_SEASON; - */ - - if (locktype != LFG_LOCKSTATUS_OK) - { - lockstatus = new LfgLockStatus(); - lockstatus->dungeon = dungeon->Entry(); - lockstatus->lockstatus = locktype; - list->insert(lockstatus); - } - } - if (!list->size()) - { - delete list; - list = NULL; - } - return list; -} - -/// -/// Get the dungeon list that can be done. -/// -/// LfgDungeonSet* -LfgDungeonSet* LFGMgr::GetAllDungeons() -{ - LfgDungeonSet *dungeons = new LfgDungeonSet(); - LFGDungeonEntry const *dungeon; - for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) - { - dungeon = sLFGDungeonStore.LookupEntry(i); - if (!dungeon || dungeon->type == LFG_TYPE_ZONE) - continue; - dungeons->insert(dungeon->ID); - } - if (!dungeons->size()) - { - delete dungeons; - return NULL; - } - else - return dungeons; -} - -/// -/// Get the dungeon list that can be done given a random dungeon entry. -/// -/// Random dungeon entry -/// LfgDungeonSet* -LfgDungeonSet* LFGMgr::GetDungeonsByRandom(uint32 randomdungeon) -{ - LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(randomdungeon); - if (!dungeon) - return NULL; - - uint32 grouptype = dungeon->grouptype; - LfgDungeonSet *random = new LfgDungeonSet(); - for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) - { - dungeon = sLFGDungeonStore.LookupEntry(i); - if (!dungeon || dungeon->type == LFG_TYPE_RANDOM || dungeon->grouptype != grouptype) - continue; - random->insert(dungeon->ID); - } - if (!random->size()) - { - delete random; - return NULL; - } - else - return random; -} - -/// -/// Get the random dungeon list that can be done at a certain level and expansion. -/// -/// Player level -/// Player account expansion -/// LfgDungeonSet* -LfgDungeonSet* LFGMgr::GetRandomDungeons(uint8 level, uint8 expansion) -{ - LfgDungeonSet *list = new LfgDungeonSet(); - LFGDungeonEntry const *dungeon; - for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) - { - dungeon = sLFGDungeonStore.LookupEntry(i); - if (dungeon && dungeon->expansion <= expansion && dungeon->type == LFG_TYPE_RANDOM && - dungeon->minlevel <= level && level <= dungeon->maxlevel) - list->insert(dungeon->Entry()); - } - return list; -} - -/// -/// Get the reward of a given random dungeon -/// -/// random dungeon id -/// Dungeon previously done -/// -LfgReward* LFGMgr::GetRandomDungeonReward(uint32 dungeon, bool done, uint8 level) -{ - uint8 index = 0; - switch((dungeon & 0x00FFFFFF)) // Get dungeon id from dungeon entry - { - case LFG_RANDOM_CLASSIC: - if (level < 15) - index = LFG_REWARD_LEVEL0; - else if (level < 24) - index = LFG_REWARD_LEVEL1; - else if (level < 35) - index = LFG_REWARD_LEVEL2; - else if (level < 46) - index = LFG_REWARD_LEVEL3; - else if (level < 56) - index = LFG_REWARD_LEVEL4; - else - index = LFG_REWARD_LEVEL5; - break; - case LFG_RANDOM_BC_NORMAL: - index = LFG_REWARD_BC_NORMAL; - break; - case LFG_RANDOM_BC_HEROIC: - index = LFG_REWARD_BC_HEROIC; - break; - case LFG_RANDOM_LK_NORMAL: - index = level == 80 ? LFG_REWARD_LK_NORMAL80 : LFG_REWARD_LK_NORMAL; - break; - case LFG_RANDOM_LK_HEROIC: - index = LFG_REWARD_LK_HEROIC; - break; - default: // This should never happen! - done = false; - index = LFG_REWARD_LEVEL0; - sLog.outError("LFGMgr::GetRandomDungeonReward: Dungeon %u is not random dungeon!", dungeon); - break; - } - return done ? m_RewardDoneList.at(index) : m_RewardList.at(index); -} - -/// -/// Given a Dungeon id returns the dungeon Group Type -/// -/// Dungeon id -/// uint8: GroupType -uint8 LFGMgr::GetDungeonGroupType(uint32 dungeonId) -{ - LFGDungeonEntry const *dungeon = sLFGDungeonStore.LookupEntry(dungeonId); - if (!dungeon) - return 0; - - return dungeon->grouptype; -} diff --git a/src/server/game/LookingForGroup/LFGMgr.h b/src/server/game/LookingForGroup/LFGMgr.h deleted file mode 100644 index b19da4e3d00..00000000000 --- a/src/server/game/LookingForGroup/LFGMgr.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _LFGMGR_H -#define _LFGMGR_H - -#include "Common.h" -#include "Policies/Singleton.h" -#include "Group.h" -#include "LFG.h" - -enum LFGenum -{ - LFG_TIME_ROLECHECK = 2*MINUTE, - LFG_TANKS_NEEDED = 1, - LFG_HEALERS_NEEDED = 1, - LFG_DPS_NEEDED = 3, - LFG_QUEUEUPDATE_INTERVAL = 15000, - LFG_SPELL_COOLDOWN = 71328, - LFG_SPELL_DESERTER = 71041, -}; - -enum LfgType -{ - LFG_TYPE_DUNGEON = 1, - LFG_TYPE_RAID = 2, - LFG_TYPE_QUEST = 3, - LFG_TYPE_ZONE = 4, - LFG_TYPE_HEROIC = 5, - LFG_TYPE_RANDOM = 6, -}; - -enum LfgGroupType -{ - LFG_GROUPTYPE_CLASSIC = 1, - LFG_GROUPTYPE_BC_NORMAL = 2, - LFG_GROUPTYPE_BC_HEROIC = 3, - LFG_GROUPTYPE_WTLK_NORMAL = 4, - LFG_GROUPTYPE_WTLK_HEROIC = 5, - LFG_GROUPTYPE_CLASSIC_RAID = 6, - LFG_GROUPTYPE_BC_RAID = 7, - LFG_GROUPTYPE_WTLK_RAID_10 = 8, - LFG_GROUPTYPE_WTLK_RAID_25 = 9, -}; - -enum LfgLockStatusType -{ - LFG_LOCKSTATUS_OK = 0, // Internal use only - LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION = 1, - LFG_LOCKSTATUS_TOO_LOW_LEVEL = 2, - LFG_LOCKSTATUS_TOO_HIGH_LEVEL = 3, - LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE = 4, - LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE = 5, - LFG_LOCKSTATUS_RAID_LOCKED = 6, - LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL = 1001, - LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL = 1002, - LFG_LOCKSTATUS_QUEST_NOT_COMPLETED = 1022, - LFG_LOCKSTATUS_MISSING_ITEM = 1025, - LFG_LOCKSTATUS_NOT_IN_SEASON = 1031, -}; - -enum LfgJoinResult -{ - LFG_JOIN_OK = 0, // Joined (no client msg) - LFG_JOIN_FAILED = 1, // RoleCheck Failed - LFG_JOIN_GROUPFULL = 2, // Your group is full - LFG_JOIN_UNK3 = 3, // No client reaction - LFG_JOIN_INTERNAL_ERROR = 4, // Internal LFG Error - LFG_JOIN_NOT_MEET_REQS = 5, // You do not meet the requirements for the chosen dungeons - LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons - LFG_JOIN_MIXED_RAID_DUNGEON = 7, // You cannot mix dungeons, raids, and random when picking dungeons - LFG_JOIN_MULTI_REALM = 8, // The dungeon you chose does not support players from multiple realms - LFG_JOIN_DISCONNECTED = 9, // One or more party members are pending invites or disconnected - LFG_JOIN_PARTY_INFO_FAILED = 10, // Could not retrieve information about some party members - LFG_JOIN_DUNGEON_INVALID = 11, // One or more dungeons was not valid - LFG_JOIN_DESERTER = 12, // You can not queue for dungeons until your deserter debuff wears off - LFG_JOIN_PARTY_DESERTER = 13, // One or more party members has a deserter debuff - LFG_JOIN_RANDOM_COOLDOWN = 14, // You can not queue for random dungeons while on random dungeon cooldown - LFG_JOIN_PARTY_RANDOM_COOLDOWN = 15, // One or more party members are on random dungeon cooldown - LFG_JOIN_TOO_MUCH_MEMBERS = 16, // You can not enter dungeons with more that 5 party members - LFG_JOIN_USING_BG_SYSTEM = 17, // You can not use the dungeon system while in BG or arenas - LFG_JOIN_FAILED2 = 18, // RoleCheck Failed -}; - -enum LfgRoleCheckResult -{ - LFG_ROLECHECK_FINISHED = 1, // Role check finished - LFG_ROLECHECK_INITIALITING = 2, // Role check begins - LFG_ROLECHECK_MISSING_ROLE = 3, // Someone didn't selected a role after 2 mins - LFG_ROLECHECK_WRONG_ROLES = 4, // Can't form a group with that role selection - LFG_ROLECHECK_ABORTED = 5, // Someone leave the group - LFG_ROLECHECK_NO_ROLE = 6, // Someone selected no role -}; - -enum LfgRandomDungeonEntries -{ - LFG_ALL_DUNGEONS = 0, - LFG_RANDOM_CLASSIC = 258, - LFG_RANDOM_BC_NORMAL = 259, - LFG_RANDOM_BC_HEROIC = 260, - LFG_RANDOM_LK_NORMAL = 261, - LFG_RANDOM_LK_HEROIC = 262, -}; - -enum LfgRewardEnums -{ - LFG_REWARD_LEVEL0 = 10, - LFG_REWARD_LEVEL1 = 0, - LFG_REWARD_LEVEL2 = 1, - LFG_REWARD_LEVEL3 = 2, - LFG_REWARD_LEVEL4 = 3, - LFG_REWARD_LEVEL5 = 4, - LFG_REWARD_BC_NORMAL = 5, - LFG_REWARD_BC_HEROIC = 6, - LFG_REWARD_LK_NORMAL = 7, - LFG_REWARD_LK_NORMAL80 = 7, - LFG_REWARD_LK_HEROIC = 8, - LFG_REWARD_DATA_SIZE = 10, -}; - -const uint32 RewardDungeonData[LFG_REWARD_DATA_SIZE+1][5] = -{ // XP, money, item, item display, count - {310, 3500, 51999, 56915, 1}, // Classic 15-23 - {470, 7000, 52000, 56915, 1}, // Classic 24-34 - {825, 13000, 52001, 56915, 1}, // Classic 35-45 - {12250, 16500, 52002, 56915, 1}, // Classic 46-55 - {14300, 18000, 52003, 56915, 1}, // Classic 56-60 - {1600, 62000, 52004, 56915, 1}, // BC Normal - {1900, 88000, 52005, 56915, 1}, // BC Heroic - {33100, 148000, 47241, 62232, 2}, // LK Normal - {0, 198600, 47241, 62232, 2}, // LK Normal - Level 80 - {0, 264600, 49426, 64062, 2}, // LK Heroic - {0, 0, 0, 0, 0}, // Classic - No level -}; - -const uint32 RewardDungeonDoneData[LFG_REWARD_DATA_SIZE][5] = -{ // XP, money, item, item display, count - {200, 1800, 51999, 56915, 1}, // Classic 15-23 - {310, 3500, 52000, 56915, 1}, // Classic 24-34 - {550, 6500, 52001, 56915, 1}, // Classic 35-45 - {8150, 8500, 52002, 56915, 1}, // Classic 46-55 - {9550, 9000, 52003, 56915, 1}, // Classic 56-60 - {1100, 31000, 52004, 56915, 1}, // BC Normal - {12650, 44000, 52005, 56915, 1}, // BC Heroic - {16550, 74000, 0, 0, 0}, // LK Normal - {0, 99300, 0, 0, 0}, // LK Normal - Level 80 - {0, 132300, 47241, 62232, 2}, // LK Heroic -}; - -// Dungeon and reason why player can't join -struct LfgLockStatus -{ - uint32 dungeon; - LfgLockStatusType lockstatus; -}; - -// Reward info -struct LfgReward -{ - uint32 strangers; - uint32 baseMoney; - uint32 baseXP; - uint32 variableMoney; - uint32 variableXP; - uint32 itemId; - uint32 displayId; - uint32 stackCount; -}; - -typedef std::set LfgLockStatusSet; -typedef std::vector LfgRewardList; -typedef std::map LfgLockStatusMap; -typedef std::map LfgDungeonMap; - -typedef std::map LfgAnswerMap; -typedef std::map LfgRolesMap; -typedef std::set LfgGuidSet; - -// Stores player or group queue info -struct LfgQueueInfo -{ - time_t joinTime; // Player queue join time (to calculate wait times) - uint32 dungeonId; // Selected Player/Group Dungeon - LfgRolesMap roles; // Selected Player Role/s - uint8 tanks; // Tanks needed - uint8 healers; // Healers needed - uint8 dps; // Dps needed -}; - -// Stores all rolecheck info of a group that wants to join LFG -struct LfgRoleCheck -{ - time_t cancelTime; - LfgRolesMap roles; - LfgRoleCheckResult result; - LfgDungeonSet dungeons; - uint64 leader; -}; - -typedef std::map LfgQueueInfoMap; -typedef std::map LfgRoleCheckMap; - -class LFGQueue -{ - public: - LFGQueue(); - ~LFGQueue(); - - void Update(); - void AddToQueue(uint64 guid, LfgQueueInfo *pqInfo); - bool RemoveFromQueue(uint64 guid); - LfgQueueInfo* GetQueueInfo(uint64 guid); - private: - LfgQueueInfoMap m_LfgQueue; - int32 avgWaitTime; - int32 waitTimeTanks; - int32 waitTimeHealer; - int32 waitTimeDps; -}; - -typedef std::map LFGQueueMap; - -class LFGMgr -{ -public: - LFGMgr(); - ~LFGMgr(); - - void InitLFG(); - void SendLfgPlayerInfo(Player *plr); - void SendLfgPartyInfo(Player *plr); - void Join(Player *plr); - void Leave(Player *plr, Group *grp = NULL); - void UpdateRoleCheck(Group *grp, Player *plr = NULL); - void Update(uint32 diff); - -private: - void BuildLfgRoleCheck(WorldPacket &data, LfgRoleCheck *pRoleCheck); - void BuildAvailableRandomDungeonList(WorldPacket &data, Player *plr); - void BuildRewardBlock(WorldPacket &data, uint32 dungeon, Player *plr); - void BuildPlayerLockDungeonBlock(WorldPacket &data, LfgLockStatusSet *lockSet); - void BuildPartyLockDungeonBlock(WorldPacket &data, LfgLockStatusMap *lockMap); - bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true); - - LfgLockStatusMap* GetPartyLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons); - LfgLockStatusSet* GetPlayerLockStatusDungeons(Player *plr, LfgDungeonSet *dungeons); - LfgDungeonSet* GetRandomDungeons(uint8 level, uint8 expansion); - LfgDungeonSet* GetDungeonsByRandom(uint32 randomdungeon); - LfgDungeonSet* GetAllDungeons(); - LfgReward* GetRandomDungeonReward(uint32 dungeon, bool done, uint8 level); - uint8 GetDungeonGroupType(uint32 dungeon); - - LfgRewardList m_RewardList; - LfgRewardList m_RewardDoneList; - LfgDungeonMap m_DungeonsMap; - - LFGQueueMap m_Queues; - LfgRoleCheckMap m_RoleChecks; - uint32 m_QueueTimer; - bool m_update; -}; - -#define sLFGMgr Trinity::Singleton::Instance() -#endif diff --git a/src/server/game/Loot/LootHandler.cpp b/src/server/game/Loot/LootHandler.cpp deleted file mode 100644 index 55aefb3c1f5..00000000000 --- a/src/server/game/Loot/LootHandler.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "Log.h" -#include "Corpse.h" -#include "GameObject.h" -#include "Player.h" -#include "ObjectAccessor.h" -#include "WorldSession.h" -#include "LootMgr.h" -#include "Object.h" -#include "Group.h" -#include "World.h" -#include "Util.h" - -void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); - Player *player = GetPlayer(); - uint64 lguid = player->GetLootGUID(); - Loot *loot; - uint8 lootSlot; - - recv_data >> lootSlot; - - if (IS_GAMEOBJECT_GUID(lguid)) - { - GameObject *go = player->GetMap()->GetGameObject(lguid); - - // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO - if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE))) - { - player->SendLootRelease(lguid); - return; - } - - loot = &go->loot; - } - else if (IS_ITEM_GUID(lguid)) - { - Item *pItem = player->GetItemByGuid(lguid); - - if (!pItem) - { - player->SendLootRelease(lguid); - return; - } - - loot = &pItem->loot; - } - else if (IS_CORPSE_GUID(lguid)) - { - Corpse *bones = ObjectAccessor::GetCorpse(*player, lguid); - if (!bones) - { - player->SendLootRelease(lguid); - return; - } - loot = &bones->loot; - } - else - { - Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); - - bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); - - if (!ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) - { - player->SendLootRelease(lguid); - return; - } - - loot = &pCreature->loot; - } - - QuestItem *qitem = NULL; - QuestItem *ffaitem = NULL; - QuestItem *conditem = NULL; - - LootItem *item = loot->LootItemInSlot(lootSlot,player,&qitem,&ffaitem,&conditem); - - if (!item) - { - player->SendEquipError(EQUIP_ERR_ALREADY_LOOTED, NULL, NULL); - return; - } - - // questitems use the blocked field for other purposes - if (!qitem && item->is_blocked) - { - player->SendLootRelease(lguid); - return; - } - - ItemPosCountVec dest; - uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item->itemid, item->count); - if (msg == EQUIP_ERR_OK) - { - Item * newitem = player->StoreNewItem(dest, item->itemid, true, item->randomPropertyId); - - if (qitem) - { - qitem->is_looted = true; - //freeforall is 1 if everyone's supposed to get the quest item. - if (item->freeforall || loot->GetPlayerQuestItems().size() == 1) - player->SendNotifyLootItemRemoved(lootSlot); - else - loot->NotifyQuestItemRemoved(qitem->index); - } - else - { - if (ffaitem) - { - //freeforall case, notify only one player of the removal - ffaitem->is_looted=true; - player->SendNotifyLootItemRemoved(lootSlot); - } - else - { - //not freeforall, notify everyone - if (conditem) - conditem->is_looted=true; - loot->NotifyItemRemoved(lootSlot); - } - } - - //if only one person is supposed to loot the item, then set it to looted - if (!item->freeforall) - item->is_looted = true; - - --loot->unlootedCount; - - player->SendNewItem(newitem, uint32(item->count), false, false, true); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item->count); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count); - } - else - player->SendEquipError(msg, NULL, NULL); -} - -void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: CMSG_LOOT_MONEY"); - - Player *player = GetPlayer(); - uint64 guid = player->GetLootGUID(); - if (!guid) - return; - - Loot *pLoot = NULL; - - switch(GUID_HIPART(guid)) - { - case HIGHGUID_GAMEOBJECT: - { - GameObject *pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); - - // not check distance for GO in case owned GO (fishing bobber case, for example) - if (pGameObject && ((pGameObject->GetOwnerGUID() == _player->GetGUID() || pGameObject->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))) - pLoot = &pGameObject->loot; - - break; - } - case HIGHGUID_CORPSE: // remove insignia ONLY in BG - { - Corpse *bones = ObjectAccessor::GetCorpse(*GetPlayer(), guid); - - if (bones && bones->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) - pLoot = &bones->loot; - - break; - } - case HIGHGUID_ITEM: - { - if (Item *item = GetPlayer()->GetItemByGuid(guid)) - pLoot = &item->loot; - break; - } - case HIGHGUID_UNIT: - { - Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); - - bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); - - if (ok_loot && pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) - pLoot = &pCreature->loot ; - - break; - } - default: - return; // unlootable type - } - - if (pLoot) - { - if (!IS_ITEM_GUID(guid) && player->GetGroup()) //item can be looted only single player - { - Group *group = player->GetGroup(); - - std::vector playersNear; - for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* playerGroup = itr->getSource(); - if (!playerGroup) - continue; - if (player->IsWithinDistInMap(playerGroup,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) - playersNear.push_back(playerGroup); - } - - uint32 money_per_player = uint32((pLoot->gold)/(playersNear.size())); - - for (std::vector::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) - { - (*i)->ModifyMoney(money_per_player); - (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player); - //Offset surely incorrect, but works - WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); - data << uint32(money_per_player); - (*i)->GetSession()->SendPacket(&data); - } - } - else - { - player->ModifyMoney(pLoot->gold); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold); - } - pLoot->gold = 0; - pLoot->NotifyMoneyRemoved(); - } -} - -void WorldSession::HandleLootOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_LOOT"); - - uint64 guid; - recv_data >> guid; - - // Check possible cheat - if (!_player->isAlive()) - return; - - GetPlayer()->SendLoot(guid, LOOT_CORPSE); -} - -void WorldSession::HandleLootReleaseOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_LOOT_RELEASE"); - - // cheaters can modify lguid to prevent correct apply loot release code and re-loot - // use internal stored guid - recv_data.read_skip(); // guid; - - if (uint64 lguid = GetPlayer()->GetLootGUID()) - DoLootRelease(lguid); -} - -void WorldSession::DoLootRelease(uint64 lguid) -{ - Player *player = GetPlayer(); - Loot *loot; - - player->SetLootGUID(0); - player->SendLootRelease(lguid); - - player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); - - if (!player->IsInWorld()) - return; - - if (IS_GAMEOBJECT_GUID(lguid)) - { - GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid); - - // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO - if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE))) - return; - - loot = &go->loot; - - if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) - { - // locked doors are opened with spelleffect openlock, prevent remove its as looted - go->UseDoorOrButton(); - } - else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) - { - // GO is mineral vein? so it is not removed after its looted - if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) - { - uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; - uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; - - // only vein pass this check - if (go_min != 0 && go_max > go_min) - { - float amount_rate = sWorld.getRate(RATE_MINING_AMOUNT); - float min_amount = go_min*amount_rate; - float max_amount = go_max*amount_rate; - - go->AddUse(); - float uses = float(go->GetUseCount()); - - if (uses < max_amount) - { - if (uses >= min_amount) - { - float chance_rate = sWorld.getRate(RATE_MINING_NEXT); - - int32 ReqValue = 175; - LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); - if (lockInfo) - ReqValue = lockInfo->Skill[0]; - float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); - double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses)); - if (roll_chance_f(100*chance+skill)) - { - go->SetLootState(GO_READY); - } - else // not have more uses - go->SetLootState(GO_JUST_DEACTIVATED); - } - else // 100% chance until min uses - go->SetLootState(GO_READY); - } - else // max uses already - go->SetLootState(GO_JUST_DEACTIVATED); - } - else // not vein - go->SetLootState(GO_JUST_DEACTIVATED); - } - else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) - { // The fishing hole used once more - go->AddUse(); // if the max usage is reached, will be despawned in next tick - if (go->GetUseCount() >= irand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens)) - { - go->SetLootState(GO_JUST_DEACTIVATED); - } - else - go->SetLootState(GO_READY); - } - else // not chest (or vein/herb/etc) - go->SetLootState(GO_JUST_DEACTIVATED); - - loot->clear(); - } - else - { - // not fully looted object - go->SetLootState(GO_ACTIVATED); - - // if the round robin player release, reset it. - if (player->GetGUID() == loot->roundRobinPlayer) - { - if (Group* pGroup = player->GetGroup()) - { - if (pGroup->GetLootMethod() != MASTER_LOOT) - { - loot->roundRobinPlayer = 0; - } - } - else - loot->roundRobinPlayer = 0; - } - } - } - else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG - { - Corpse *corpse = ObjectAccessor::GetCorpse(*player, lguid); - if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) - return; - - loot = &corpse->loot; - - if (loot->isLooted()) - { - loot->clear(); - corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); - } - } - else if (IS_ITEM_GUID(lguid)) - { - Item *pItem = player->GetItemByGuid(lguid); - if (!pItem) - return; - - ItemPrototype const* proto = pItem->GetProto(); - - // destroy only 5 items from stack in case prospecting and milling - if ((proto->BagFamily & (BAG_FAMILY_MASK_MINING_SUPP|BAG_FAMILY_MASK_HERBS)) && - proto->Class == ITEM_CLASS_TRADE_GOODS) - { - pItem->m_lootGenerated = false; - pItem->loot.clear(); - - uint32 count = pItem->GetCount(); - - // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. - if (count > 5) - count = 5; - - player->DestroyItemCount(pItem, count, true); - } - else - // FIXME: item must not be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or cheating possible. - player->DestroyItem(pItem->GetBagSlot(),pItem->GetSlot(), true); - return; // item can be looted only single player - } - else - { - Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); - - bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); - if (!ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) - return; - - loot = &pCreature->loot; - if (loot->isLooted()) - { - // skip pickpocketing loot for speed, skinning timer redunction is no-op in fact - if (!pCreature->isAlive()) - pCreature->AllLootRemovedFromCorpse(); - - pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - pCreature->SetLootRecipient(NULL); - loot->clear(); - } - else - { - // if the round robin player release, reset it. - if (player->GetGUID() == loot->roundRobinPlayer) - { - if (Group* pGroup = player->GetGroup()) - { - if (pGroup->GetLootMethod() != MASTER_LOOT) - { - loot->roundRobinPlayer = 0; - pGroup->SendLooter(pCreature, NULL); - - // force update of dynamic flags, otherwise other group's players still not able to loot. - pCreature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); - } - } - else - loot->roundRobinPlayer = 0; - } - } - } - - //Player is not looking at loot list, he doesn't need to see updates on the loot list - loot->RemoveLooter(player->GetGUID()); -} - -void WorldSession::HandleLootMasterGiveOpcode(WorldPacket & recv_data) -{ - uint8 slotid; - uint64 lootguid, target_playerguid; - - recv_data >> lootguid >> slotid >> target_playerguid; - - if (!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetGUID()) - { - _player->SendLootRelease(GetPlayer()->GetLootGUID()); - return; - } - - Player *target = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(target_playerguid, 0, HIGHGUID_PLAYER)); - if (!target) - return; - - sLog.outDebug("WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = [%s].", target->GetName()); - - if (_player->GetLootGUID() != lootguid) - return; - - Loot *pLoot = NULL; - - if (IS_CRE_OR_VEH_GUID(GetPlayer()->GetLootGUID())) - { - Creature *pCreature = GetPlayer()->GetMap()->GetCreature(lootguid); - if (!pCreature) - return; - - pLoot = &pCreature->loot; - } - else if (IS_GAMEOBJECT_GUID(GetPlayer()->GetLootGUID())) - { - GameObject *pGO = GetPlayer()->GetMap()->GetGameObject(lootguid); - if (!pGO) - return; - - pLoot = &pGO->loot; - } - - if (!pLoot) - return; - - if (slotid > pLoot->items.size()) - { - sLog.outDebug("AutoLootItem: Player %s might be using a hack! (slot %d, size %lu)",GetPlayer()->GetName(), slotid, (unsigned long)pLoot->items.size()); - return; - } - - LootItem& item = pLoot->items[slotid]; - - ItemPosCountVec dest; - uint8 msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count); - if (msg != EQUIP_ERR_OK) - { - target->SendEquipError(msg, NULL, NULL); - _player->SendEquipError(msg, NULL, NULL); // send duplicate of error massage to master looter - return; - } - - // not move item from loot to target inventory - Item * newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId); - target->SendNewItem(newitem, uint32(item.count), false, false, true); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, pLoot->loot_type, item.count); - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count); - - // mark as looted - item.count=0; - item.is_looted=true; - - pLoot->NotifyItemRemoved(slotid); - --pLoot->unlootedCount; -} - diff --git a/src/server/game/Map/Cell/Cell.h b/src/server/game/Map/Cell/Cell.h deleted file mode 100644 index 49e0329ace6..00000000000 --- a/src/server/game/Map/Cell/Cell.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CELL_H -#define TRINITY_CELL_H - -#include - -#include "GameSystem/TypeContainer.h" -#include "GameSystem/TypeContainerVisitor.h" - -#include "GridDefines.h" - -class Map; -class WorldObject; - -enum District -{ - UPPER_DISTRICT = 1, - LOWER_DISTRICT = 1 << 1, - LEFT_DISTRICT = 1 << 2, - RIGHT_DISTRICT = 1 << 3, - CENTER_DISTRICT = 1 << 4, - UPPER_LEFT_DISTRICT = (UPPER_DISTRICT | LEFT_DISTRICT), - UPPER_RIGHT_DISTRICT = (UPPER_DISTRICT | RIGHT_DISTRICT), - LOWER_LEFT_DISTRICT = (LOWER_DISTRICT | LEFT_DISTRICT), - LOWER_RIGHT_DISTRICT = (LOWER_DISTRICT | RIGHT_DISTRICT), - ALL_DISTRICT = (UPPER_DISTRICT | LOWER_DISTRICT | LEFT_DISTRICT | RIGHT_DISTRICT | CENTER_DISTRICT) -}; - -struct CellArea -{ - CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {} - CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {} - bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; } - - void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const - { - begin_cell << left_offset; - begin_cell -= lower_offset; - end_cell >> right_offset; - end_cell += upper_offset; - } - - int right_offset; - int left_offset; - int upper_offset; - int lower_offset; -}; - -struct Cell -{ - Cell() { data.All = 0; } - Cell(const Cell &cell) { data.All = cell.data.All; } - explicit Cell(CellPair const& p); - - void operator|=(Cell &cell) - { - data.Part.reserved = 0; - cell.data.Part.reserved = 0; - uint32 x, y, old_x, old_y; - Compute(x, y); - cell.Compute(old_x, old_y); - - if (std::abs(int(x-old_x)) > 1 || std::abs(int(y-old_y)) > 1) - { - data.Part.reserved = ALL_DISTRICT; - cell.data.Part.reserved = ALL_DISTRICT; - return; - } - - if (x < old_x) - { - data.Part.reserved |= LEFT_DISTRICT; - cell.data.Part.reserved |= RIGHT_DISTRICT; - } - else if (old_x < x) - { - data.Part.reserved |= RIGHT_DISTRICT; - cell.data.Part.reserved |= LEFT_DISTRICT; - } - if (y < old_y) - { - data.Part.reserved |= UPPER_DISTRICT; - cell.data.Part.reserved |= LOWER_DISTRICT; - } - else if (old_y < y) - { - data.Part.reserved |= LOWER_DISTRICT; - cell.data.Part.reserved |= UPPER_DISTRICT; - } - } - - void Compute(uint32 &x, uint32 &y) const - { - x = data.Part.grid_x*MAX_NUMBER_OF_CELLS + data.Part.cell_x; - y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; - } - - bool DiffCell(const Cell &cell) const - { - return(data.Part.cell_x != cell.data.Part.cell_x || - data.Part.cell_y != cell.data.Part.cell_y); - } - - bool DiffGrid(const Cell &cell) const - { - return(data.Part.grid_x != cell.data.Part.grid_x || - data.Part.grid_y != cell.data.Part.grid_y); - } - - uint32 CellX() const { return data.Part.cell_x; } - uint32 CellY() const { return data.Part.cell_y; } - uint32 GridX() const { return data.Part.grid_x; } - uint32 GridY() const { return data.Part.grid_y; } - bool NoCreate() const { return data.Part.nocreate; } - void SetNoCreate() { data.Part.nocreate = 1; } - - CellPair cellPair() const - { - return CellPair( - data.Part.grid_x*MAX_NUMBER_OF_CELLS+data.Part.cell_x, - data.Part.grid_y*MAX_NUMBER_OF_CELLS+data.Part.cell_y); - } - - Cell& operator=(const Cell &cell) - { - this->data.All = cell.data.All; - return *this; - } - - bool operator == (const Cell &cell) const { return (data.All == cell.data.All); } - bool operator != (const Cell &cell) const { return !operator == (cell); } - union - { - struct - { - unsigned grid_x : 6; - unsigned grid_y : 6; - unsigned cell_x : 6; - unsigned cell_y : 6; - unsigned nocreate : 1; - unsigned reserved : 7; - } Part; - uint32 All; - } data; - - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &) const; - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, const WorldObject&, float) const; - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, float, float, float) const; - - static CellArea CalculateCellArea(const WorldObject &obj, float radius); - static CellArea CalculateCellArea(float x, float y, float radius); - -private: - template void VisitCircle(TypeContainerVisitor &, Map &, const CellPair&, const CellPair&) const; -}; - -#endif - diff --git a/src/server/game/Map/Cell/CellImpl.h b/src/server/game/Map/Cell/CellImpl.h deleted file mode 100644 index d906e81a5c9..00000000000 --- a/src/server/game/Map/Cell/CellImpl.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CELLIMPL_H -#define TRINITY_CELLIMPL_H - -#include - -#include "Cell.h" -#include "Map.h" -#include "Object.h" - -inline Cell::Cell(CellPair const& p) -{ - data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS; - data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; - data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; - data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; - data.Part.nocreate = 0; - data.Part.reserved = 0; -} - -template -inline void -Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m) const -{ - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - return; - - uint16 district = (District)this->data.Part.reserved; - if (district == CENTER_DISTRICT) - { - m.Visit(*this, visitor); - return; - } - - // set up the cell range based on the district - // the overloaded operators handle range checking - CellPair begin_cell = standing_cell; - CellPair end_cell = standing_cell; - - switch(district) - { - case ALL_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell >> 1; end_cell += 1; // lower right - break; - } - case UPPER_LEFT_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - break; - } - case UPPER_RIGHT_DISTRICT: - { - begin_cell -= 1; // up - end_cell >> 1; // right - break; - } - case LOWER_LEFT_DISTRICT: - { - begin_cell << 1; // left - end_cell += 1; // down - break; - } - case LOWER_RIGHT_DISTRICT: - { - end_cell >> 1; end_cell += 1; // lower right - break; - } - case LEFT_DISTRICT: - { - begin_cell -= 1; // up - end_cell >> 1; end_cell += 1; // lower right - break; - } - case RIGHT_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell += 1; // down - break; - } - case UPPER_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell >> 1; // right - break; - } - case LOWER_DISTRICT: - { - begin_cell << 1; // left - end_cell >> 1; end_cell += 1; // lower right - break; - } - default: - { - assert(false); - break; - } - } - - // loop the cell range - for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++) - { - CellPair cell_pair(x,y); - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } -} - -inline int CellHelper(const float radius) -{ - if (radius < 1.0f) - return 0; - - return (int)ceilf(radius/SIZE_OF_GRID_CELL); -} - -inline CellArea Cell::CalculateCellArea(const WorldObject &obj, float radius) -{ - return Cell::CalculateCellArea(obj.GetPositionX(), obj.GetPositionY(), radius); -} - -inline CellArea Cell::CalculateCellArea(float x, float y, float radius) -{ - if (radius <= 0.0f) - return CellArea(); - - //lets calculate object coord offsets from cell borders. - //TODO: add more correct/generic method for this task - const float x_offset = (x - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - const float y_offset = (y - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - - const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f); - const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f); - - const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - - const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET; - //lets calculate upper/lower/right/left corners for cell search - int right = CellHelper(tmp_diff + x_off); - int left = CellHelper(tmp_diff - x_off); - int upper = CellHelper(tmp_diff + y_off); - int lower = CellHelper(tmp_diff - y_off); - - return CellArea(right, left, upper, lower); -} - -template -inline void -Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m, float radius, float x_off, float y_off) const -{ - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - return; - - //no jokes here... Actually placing ASSERT() here was good idea, but - //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?) - //maybe it is better to just return when radius <= 0.0f? - if (radius <= 0.0f) - { - m.Visit(*this, visitor); - return; - } - //lets limit the upper value for search radius - if (radius > 333.0f) - radius = 333.0f; - - //lets calculate object coord offsets from cell borders. - CellArea area = Cell::CalculateCellArea(x_off, y_off, radius); - //if radius fits inside standing cell - if (!area) - { - m.Visit(*this, visitor); - return; - } - - CellPair begin_cell = standing_cell; - CellPair end_cell = standing_cell; - - area.ResizeBorders(begin_cell, end_cell); - //visit all cells, found in CalculateCellArea() - //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle - //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values - //there are nothing to optimize because SIZE_OF_GRID_CELL is too big... - if (((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4)) - { - VisitCircle(visitor, m, begin_cell, end_cell); - return; - } - - //ALWAYS visit standing cell first!!! Since we deal with small radiuses - //it is very essential to call visitor for standing cell firstly... - m.Visit(*this, visitor); - - // loop the cell range - for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) - { - CellPair cell_pair(x,y); - //lets skip standing cell since we already visited it - if (cell_pair != standing_cell) - { - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } - } -} - -template -inline void -Cell::Visit(const CellPair& l, TypeContainerVisitor &visitor, Map &m, const WorldObject &obj, float radius) const -{ - //we should increase search radius by object's radius, otherwise - //we could have problems with huge creatures, which won't attack nearest players etc - Visit(l, visitor, m, radius + obj.GetObjectSize(), obj.GetPositionX(), obj.GetPositionY()); -} - -template -inline void -Cell::VisitCircle(TypeContainerVisitor &visitor, Map &m, const CellPair& begin_cell, const CellPair& end_cell) const -{ - //here is an algorithm for 'filling' circum-squared octagon - uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f); - //lets calculate x_start/x_end coords for central strip... - const uint32 x_start = begin_cell.x_coord + x_shift; - const uint32 x_end = end_cell.x_coord - x_shift; - - //visit central strip with constant width... - for (uint32 x = x_start; x <= x_end; ++x) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) - { - CellPair cell_pair(x,y); - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } - - //if x_shift == 0 then we have too small cell area, which were already - //visited at previous step, so just return from procedure... - if (x_shift == 0) - return; - - uint32 y_start = end_cell.y_coord; - uint32 y_end = begin_cell.y_coord; - //now we are visiting borders of an octagon... - for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step) - { - //each step reduces strip height by 2 cells... - y_end += 1; - y_start -= 1; - for (uint32 y = y_start; y >= y_end; --y) - { - //we visit cells symmetrically from both sides, heading from center to sides and from up to bottom - //e.g. filling 2 trapezoids after filling central cell strip... - CellPair cell_pair_left(x_start - step, y); - Cell r_zone_left(cell_pair_left); - r_zone_left.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone_left, visitor); - - //right trapezoid cell visit - CellPair cell_pair_right(x_end + step, y); - Cell r_zone_right(cell_pair_right); - r_zone_right.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone_right, visitor); - } - } -} -#endif - diff --git a/src/server/game/Map/Grid/GridDefines.h b/src/server/game/Map/Grid/GridDefines.h deleted file mode 100644 index 5269d0a094d..00000000000 --- a/src/server/game/Map/Grid/GridDefines.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDDEFINES_H -#define TRINITY_GRIDDEFINES_H - -#include "Common.h" -#include "GameSystem/NGrid.h" -#include - -// Forward class definitions -class Corpse; -class Creature; -class DynamicObject; -class GameObject; -class Pet; -class Player; - -#define MAX_NUMBER_OF_CELLS 8 - -#define MAX_NUMBER_OF_GRIDS 64 - -#define SIZE_OF_GRIDS 533.33333f -#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2) - -#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) - -#define MIN_GRID_DELAY (MINUTE*IN_MILISECONDS) -#define MIN_MAP_UPDATE_DELAY 50 - -#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) - -#define CENTER_GRID_CELL_ID (MAX_NUMBER_OF_CELLS*MAX_NUMBER_OF_GRIDS/2) -#define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2) - -#define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) - -#define MAP_RESOLUTION 128 - -#define MAP_SIZE (SIZE_OF_GRIDS*MAX_NUMBER_OF_GRIDS) -#define MAP_HALFSIZE (MAP_SIZE/2) - -// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case) -typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes; -typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes; - -typedef GridRefManager CorpseMapType; -typedef GridRefManager CreatureMapType; -typedef GridRefManager DynamicObjectMapType; -typedef GridRefManager GameObjectMapType; -typedef GridRefManager PlayerMapType; - -typedef Grid GridType; -typedef NGrid NGridType; - -typedef TypeMapContainer GridTypeMapContainer; -typedef TypeMapContainer WorldTypeMapContainer; - -template -struct CoordPair -{ - CoordPair(uint32 x=0, uint32 y=0) : x_coord(x), y_coord(y) {} - CoordPair(const CoordPair &obj) : x_coord(obj.x_coord), y_coord(obj.y_coord) {} - bool operator == (const CoordPair &obj) const { return (obj.x_coord == x_coord && obj.y_coord == y_coord); } - bool operator != (const CoordPair &obj) const { return !operator == (obj); } - CoordPair& operator=(const CoordPair &obj) - { - x_coord = obj.x_coord; - y_coord = obj.y_coord; - return *this; - } - - void operator<<(const uint32 val) - { - if (x_coord > val) - x_coord -= val; - else - x_coord = 0; - } - - void operator>>(const uint32 val) - { - if (x_coord+val < LIMIT) - x_coord += val; - else - x_coord = LIMIT - 1; - } - - void operator-=(const uint32 val) - { - if (y_coord > val) - y_coord -= val; - else - y_coord = 0; - } - - void operator+=(const uint32 val) - { - if (y_coord+val < LIMIT) - y_coord += val; - else - y_coord = LIMIT - 1; - } - - uint32 x_coord; - uint32 y_coord; -}; - -typedef CoordPair GridPair; -typedef CoordPair CellPair; - -namespace Trinity -{ - template - inline RET_TYPE Compute(float x, float y, float center_offset, float size) - { - // calculate and store temporary values in double format for having same result as same mySQL calculations - double x_offset = (double(x) - center_offset)/size; - double y_offset = (double(y) - center_offset)/size; - - int x_val = int(x_offset+CENTER_VAL + 0.5); - int y_val = int(y_offset+CENTER_VAL + 0.5); - return RET_TYPE(x_val, y_val); - } - - inline GridPair ComputeGridPair(float x, float y) - { - return Compute(x, y, CENTER_GRID_OFFSET, SIZE_OF_GRIDS); - } - - inline CellPair ComputeCellPair(float x, float y) - { - return Compute(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL); - } - - inline CellPair ComputeCellPair(float x, float y, float &x_off, float &y_off) - { - double x_offset = (double(x) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - double y_offset = (double(y) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - - int x_val = int(x_offset + CENTER_GRID_CELL_ID + 0.5); - int y_val = int(y_offset + CENTER_GRID_CELL_ID + 0.5); - x_off = (float(x_offset) - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - y_off = (float(y_offset) - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - return CellPair(x_val, y_val); - } - - inline void NormalizeMapCoord(float &c) - { - if (c > MAP_HALFSIZE - 0.5) - c = MAP_HALFSIZE - 0.5; - else if (c < -(MAP_HALFSIZE - 0.5)) - c = -(MAP_HALFSIZE - 0.5); - } - - inline bool IsValidMapCoord(float c) - { - return finite(c) && (std::fabs(c) <= MAP_HALFSIZE - 0.5); - } - - inline bool IsValidMapCoord(float x, float y) - { - return IsValidMapCoord(x) && IsValidMapCoord(y); - } - - inline bool IsValidMapCoord(float x, float y, float z) - { - return IsValidMapCoord(x,y) && finite(z); - } - - inline bool IsValidMapCoord(float x, float y, float z, float o) - { - return IsValidMapCoord(x,y,z) && finite(o); - } -} -#endif diff --git a/src/server/game/Map/Grid/GridNotifiers.cpp b/src/server/game/Map/Grid/GridNotifiers.cpp deleted file mode 100644 index b10dfa8791e..00000000000 --- a/src/server/game/Map/Grid/GridNotifiers.cpp +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "UpdateData.h" -#include "Item.h" -#include "Map.h" -#include "Transports.h" -#include "ObjectAccessor.h" -#include "CellImpl.h" - -using namespace Trinity; - -void -VisibleNotifier::SendToSelf() -{ - // at this moment i_clientGUIDs have guids that not iterate at grid level checks - // but exist one case when this possible and object not out of range: transports - if (Transport* transport = i_player.GetTransport()) - for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr != transport->GetPassengers().end();++itr) - { - if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end()) - { - vis_guids.erase((*itr)->GetGUID()); - - i_player.UpdateVisibilityOf((*itr), i_data, i_visibleNow); - - if (!(*itr)->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - (*itr)->UpdateVisibilityOf(&i_player); - } - } - - for (Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end(); ++it) - { - i_player.m_clientGUIDs.erase(*it); - i_data.AddOutOfRangeGUID(*it); - - if (IS_PLAYER_GUID(*it)) - { - Player* plr = ObjectAccessor::FindPlayer(*it); - if (plr && plr->IsInWorld() && !plr->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - plr->UpdateVisibilityOf(&i_player); - } - } - - if (!i_data.HasData()) - return; - - WorldPacket packet; - i_data.BuildPacket(&packet); - i_player.GetSession()->SendPacket(&packet); - - for (std::set::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it) - i_player.SendInitialVisiblePackets(*it); -} - -void -VisibleChangesNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - if (iter->getSource() == &i_object) - continue; - - iter->getSource()->UpdateVisibilityOf(&i_object); - - if (!iter->getSource()->GetSharedVisionList().empty()) - for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - (*i)->UpdateVisibilityOf(&i_object); - } -} - -void -VisibleChangesNotifier::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (!iter->getSource()->GetSharedVisionList().empty()) - for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - (*i)->UpdateVisibilityOf(&i_object); -} - -void -VisibleChangesNotifier::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) - if (Player* caster = (Player*)iter->getSource()->GetCaster()) - if (caster->m_seer == iter->getSource()) - caster->UpdateVisibilityOf(&i_object); -} - -inline void CreatureUnitRelocationWorker(Creature* c, Unit* u) -{ - if (!u->isAlive() || !c->isAlive() || c == u || u->isInFlight()) - return; - - if (c->HasReactState(REACT_AGGRESSIVE) && !c->hasUnitState(UNIT_STAT_SIGHTLESS)) - if (c->_IsWithinDist(u, c->m_SightDistance, true) && c->IsAIEnabled) - c->AI()->MoveInLineOfSight_Safe(u); -} - -void PlayerRelocationNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Player* plr = iter->getSource(); - - vis_guids.erase(plr->GetGUID()); - - i_player.UpdateVisibilityOf(plr,i_data,i_visibleNow); - - if (plr->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - plr->UpdateVisibilityOf(&i_player); - } -} - -void PlayerRelocationNotifier::Visit(CreatureMapType &m) -{ - bool relocated_for_ai = (&i_player == i_player.m_seer); - - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Creature * c = iter->getSource(); - - vis_guids.erase(c->GetGUID()); - - i_player.UpdateVisibilityOf(c,i_data,i_visibleNow); - - if (relocated_for_ai && !c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - CreatureUnitRelocationWorker(c, &i_player); - } -} - -void CreatureRelocationNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Player * pl = iter->getSource(); - - if (!pl->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - pl->UpdateVisibilityOf(&i_creature); - - CreatureUnitRelocationWorker(&i_creature, pl); - } -} - -void CreatureRelocationNotifier::Visit(CreatureMapType &m) -{ - if (!i_creature.isAlive()) - return; - - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Creature* c = iter->getSource(); - CreatureUnitRelocationWorker(&i_creature, c); - - if (!c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - CreatureUnitRelocationWorker(c, &i_creature); - } -} - -void DelayedUnitRelocation::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Creature * unit = iter->getSource(); - if (!unit->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - CreatureRelocationNotifier relocate(*unit); - - TypeContainerVisitor c2world_relocation(relocate); - TypeContainerVisitor c2grid_relocation(relocate); - - cell.Visit(p, c2world_relocation, i_map, *unit, i_radius); - cell.Visit(p, c2grid_relocation, i_map, *unit, i_radius); - } -} - -void DelayedUnitRelocation::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Player * player = iter->getSource(); - WorldObject const *viewPoint = player->m_seer; - - if (!viewPoint->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - if (player != viewPoint && !viewPoint->IsPositionValid()) - continue; - - CellPair pair2(Trinity::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY())); - Cell cell2(pair2); - //cell.SetNoCreate(); need load cells around viewPoint or player, that's why its commented - - PlayerRelocationNotifier relocate(*player); - TypeContainerVisitor c2world_relocation(relocate); - TypeContainerVisitor c2grid_relocation(relocate); - - cell2.Visit(pair2, c2world_relocation, i_map, *viewPoint, i_radius); - cell2.Visit(pair2, c2grid_relocation, i_map, *viewPoint, i_radius); - - relocate.SendToSelf(); - } -} - -void AIRelocationNotifier::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Creature *c = iter->getSource(); - CreatureUnitRelocationWorker(c, &i_unit); - if (isCreature) - CreatureUnitRelocationWorker((Creature*)&i_unit, c); - } -} - -void -MessageDistDeliverer::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Player *target = iter->getSource(); - if (!target->InSamePhase(i_phaseMask)) - continue; - - if (target->GetExactDistSq(i_source) > i_distSq) - continue; - - // Send packet to all who are sharing the player's vision - if (!target->GetSharedVisionList().empty()) - { - SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); - for (; i != target->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == target) - SendPacket(*i); - } - - if (target->m_seer == target || target->GetVehicle()) - SendPacket(target); - } -} - -void -MessageDistDeliverer::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (!iter->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) - continue; - - // Send packet to all who are sharing the creature's vision - if (!iter->getSource()->GetSharedVisionList().empty()) - { - SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - for (; i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - SendPacket(*i); - } - } -} - -void -MessageDistDeliverer::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (!iter->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) - continue; - - if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) - { - // Send packet back to the caster if the caster has vision of dynamic object - Player* caster = (Player*)iter->getSource()->GetCaster(); - if (caster && caster->m_seer == iter->getSource()) - SendPacket(caster); - } - } -} - -/* -void -MessageDistDeliverer::VisitObject(Player* plr) -{ - if (!i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam())) - { - SendPacket(plr); - } -} -*/ - -template void -ObjectUpdater::Visit(GridRefManager &m) -{ - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (iter->getSource()->IsInWorld()) - iter->getSource()->Update(i_timeDiff); - } -} - -bool CannibalizeObjectCheck::operator()(Corpse* u) -{ - // ignore bones - if (u->GetType() == CORPSE_BONES) - return false; - - Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); - - if (!owner || i_funit->IsFriendlyTo(owner)) - return false; - - if (i_funit->IsWithinDistInMap(u, i_range)) - return true; - - return false; -} - -template void ObjectUpdater::Visit(GameObjectMapType &); -template void ObjectUpdater::Visit(DynamicObjectMapType &); diff --git a/src/server/game/Map/Grid/GridNotifiers.h b/src/server/game/Map/Grid/GridNotifiers.h deleted file mode 100644 index b0abf0aae79..00000000000 --- a/src/server/game/Map/Grid/GridNotifiers.h +++ /dev/null @@ -1,1232 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDNOTIFIERS_H -#define TRINITY_GRIDNOTIFIERS_H - -#include "ObjectGridLoader.h" -#include "UpdateData.h" -#include - -#include "Corpse.h" -#include "Object.h" -#include "DynamicObject.h" -#include "GameObject.h" -#include "Player.h" -#include "Unit.h" -#include "CreatureAI.h" - -class Player; -//class Map; - -namespace Trinity -{ - struct VisibleNotifier - { - Player &i_player; - UpdateData i_data; - std::set i_visibleNow; - Player::ClientGUIDs vis_guids; - - VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) {} - template void Visit(GridRefManager &m); - void SendToSelf(void); - }; - - struct VisibleChangesNotifier - { - WorldObject &i_object; - - explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {} - template void Visit(GridRefManager &) {} - void Visit(PlayerMapType &); - void Visit(CreatureMapType &); - void Visit(DynamicObjectMapType &); - }; - - struct PlayerRelocationNotifier : public VisibleNotifier - { - PlayerRelocationNotifier(Player &pl) : VisibleNotifier(pl) {} - - template void Visit(GridRefManager &m) { VisibleNotifier::Visit(m); } - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct CreatureRelocationNotifier - { - Creature &i_creature; - CreatureRelocationNotifier(Creature &c) : i_creature(c) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct DelayedUnitRelocation - { - Map &i_map; - Cell &cell; - CellPair &p; - const float i_radius; - DelayedUnitRelocation(Cell &c, CellPair &pair, Map &map, float radius) : - cell(c), p(pair), i_map(map), i_radius(radius) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct AIRelocationNotifier - { - Unit &i_unit; - bool isCreature; - explicit AIRelocationNotifier(Unit &unit) : i_unit(unit), isCreature(unit.GetTypeId() == TYPEID_UNIT) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - }; - - struct GridUpdater - { - GridType &i_grid; - uint32 i_timeDiff; - GridUpdater(GridType &grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) {} - - template void updateObjects(GridRefManager &m) - { - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - iter->getSource()->Update(i_timeDiff); - } - - void Visit(PlayerMapType &m) { updateObjects(m); } - void Visit(CreatureMapType &m){ updateObjects(m); } - void Visit(GameObjectMapType &m) { updateObjects(m); } - void Visit(DynamicObjectMapType &m) { updateObjects(m); } - void Visit(CorpseMapType &m) { updateObjects(m); } - }; - - struct MessageDistDeliverer - { - WorldObject *i_source; - WorldPacket *i_message; - uint32 i_phaseMask; - float i_distSq; - uint32 team; - Player const* skipped_receiver; - MessageDistDeliverer(WorldObject *src, WorldPacket *msg, float dist, bool own_team_only = false, Player const* skipped = NULL) - : i_source(src), i_message(msg), i_distSq(dist * dist), i_phaseMask(src->GetPhaseMask()) - , team((own_team_only && src->GetTypeId() == TYPEID_PLAYER) ? ((Player*)src)->GetTeam() : 0) - , skipped_receiver(skipped) - { - } - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(DynamicObjectMapType &m); - template void Visit(GridRefManager &) {} - - void SendPacket(Player* plr) - { - // never send packet to self - if (plr == i_source || (team && plr->GetTeam() != team) || skipped_receiver == plr) - return; - - plr->GetSession()->SendPacket(i_message); - } - }; - - struct ObjectUpdater - { - uint32 i_timeDiff; - explicit ObjectUpdater(const uint32 &diff) : i_timeDiff(diff) {} - template void Visit(GridRefManager &m); - void Visit(PlayerMapType &) {} - void Visit(CorpseMapType &) {} - void Visit(CreatureMapType &); - }; - - // SEARCHERS & LIST SEARCHERS & WORKERS - - // WorldObject searchers & workers - - template - struct WorldObjectSearcher - { - uint32 i_phaseMask; - WorldObject* &i_object; - Check &i_check; - - WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(GameObjectMapType &m); - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(CorpseMapType &m); - void Visit(DynamicObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct WorldObjectListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - WorldObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(CorpseMapType &m); - void Visit(GameObjectMapType &m); - void Visit(DynamicObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct WorldObjectWorker - { - uint32 i_phaseMask; - Do const& i_do; - - WorldObjectWorker(WorldObject const* searcher, Do const& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(GameObjectMapType &m) - { - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - void Visit(CreatureMapType &m) - { - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(CorpseMapType &m) - { - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(DynamicObjectMapType &m) - { - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // Gameobject searchers - - template - struct GameObjectSearcher - { - uint32 i_phaseMask; - GameObject* &i_object; - Check &i_check; - - GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check GO if any (Check can change requirements at each call) - template - struct GameObjectLastSearcher - { - uint32 i_phaseMask; - GameObject* &i_object; - Check& i_check; - - GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct GameObjectListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - GameObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Unit searchers - - // First accepted by Check Unit if any - template - struct UnitSearcher - { - uint32 i_phaseMask; - Unit* &i_object; - Check & i_check; - - UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check Unit if any (Check can change requirements at each call) - template - struct UnitLastSearcher - { - uint32 i_phaseMask; - Unit* &i_object; - Check & i_check; - - UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // All accepted by Check units if any - template - struct UnitListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - UnitListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Creature searchers - - template - struct CreatureSearcher - { - uint32 i_phaseMask; - Creature* &i_object; - Check & i_check; - - CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check Creature if any (Check can change requirements at each call) - template - struct CreatureLastSearcher - { - uint32 i_phaseMask; - Creature* &i_object; - Check & i_check; - - CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct CreatureListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - CreatureListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct CreatureWorker - { - uint32 i_phaseMask; - Do& i_do; - - CreatureWorker(WorldObject const* searcher, Do& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(CreatureMapType &m) - { - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // Player searchers - - template - struct PlayerSearcher - { - uint32 i_phaseMask; - Player* &i_object; - Check & i_check; - - PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - PlayerListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerWorker - { - uint32 i_phaseMask; - Do& i_do; - - PlayerWorker(WorldObject const* searcher, Do& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerDistWorker - { - WorldObject const* i_searcher; - float i_dist; - Do& i_do; - - PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do) - : i_searcher(searcher), i_dist(_dist), i_do(_do) {} - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // CHECKS && DO classes - - // WorldObject check classes - class RaiseDeadObjectCheck - { - public: - RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Creature* u) - { - if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || - u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() || - (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 || - (u->GetDisplayId() != u->GetNativeDisplayId())) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - class ExplodeCorpseObjectCheck - { - public: - ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (u->getDeathState() != CORPSE || u->isInFlight() || - u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - bool operator()(Creature* u) - { - if (u->getDeathState() != CORPSE || u->isInFlight() || u->isDeadByDefault() || - (u->GetDisplayId() != u->GetNativeDisplayId()) || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - class CannibalizeObjectCheck - { - public: - CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - bool operator()(Corpse* u); - bool operator()(Creature* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - // WorldObject do classes - - class RespawnDo - { - public: - RespawnDo() {} - void operator()(Creature* u) const { u->Respawn(); } - void operator()(GameObject* u) const { u->Respawn(); } - void operator()(WorldObject*) const {} - void operator()(Corpse*) const {} - }; - - // GameObject checks - - class GameObjectFocusCheck - { - public: - GameObjectFocusCheck(Unit const* unit,uint32 focusId) : i_unit(unit), i_focusId(focusId) {} - bool operator()(GameObject* go) const - { - if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS) - return false; - - if (go->GetGOInfo()->spellFocus.focusId != i_focusId) - return false; - - float dist = (go->GetGOInfo()->spellFocus.dist)/2; - - return go->IsWithinDistInMap(i_unit, dist); - } - private: - Unit const* i_unit; - uint32 i_focusId; - }; - - // Find the nearest Fishing hole and return true only if source object is in range of hole - class NearestGameObjectFishingHole - { - public: - NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(GameObject* go) - { - if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, go->GetGOInfo()->fishinghole.radius)) - { - i_range = i_obj.GetDistance(go); - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - float i_range; - - // prevent clone - NearestGameObjectFishingHole(NearestGameObjectFishingHole const&); - }; - - class NearestGameObjectCheck - { - public: - NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) {} - bool operator()(GameObject* go) - { - if (i_obj.IsWithinDistInMap(go, i_range)) - { - i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - float i_range; - - // prevent clone this object - NearestGameObjectCheck(NearestGameObjectCheck const&); - }; - - // Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO) - class NearestGameObjectEntryInObjectRangeCheck - { - public: - NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj,uint32 entry, float range) : i_obj(obj), i_entry(entry), i_range(range) {} - bool operator()(GameObject* go) - { - if (go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range)) - { - i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - uint32 i_entry; - float i_range; - - // prevent clone this object - NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&); - }; - - class GameObjectWithDbGUIDCheck - { - public: - GameObjectWithDbGUIDCheck(WorldObject const& obj,uint32 db_guid) : i_obj(obj), i_db_guid(db_guid) {} - bool operator()(GameObject const* go) const - { - return go->GetDBTableGUIDLow() == i_db_guid; - } - private: - WorldObject const& i_obj; - uint32 i_db_guid; - }; - - // Unit checks - - class MostHPMissingInRange - { - public: - MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp) - { - i_hp = u->GetMaxHealth() - u->GetHealth(); - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - uint32 i_hp; - }; - - class FriendlyCCedInRange - { - public: - FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && - (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED))) - { - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - }; - - class FriendlyMissingBuffInRange - { - public: - FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && - !(u->HasAura(i_spell))) - { - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - uint32 i_spell; - }; - - class AnyUnfriendlyUnitInObjectRangeCheck - { - public: - AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u)) - return true; - else - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnfriendlyNoTotemUnitInObjectRangeCheck - { - public: - AnyUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (!u->isAlive()) - return false; - - if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) - return false; - - return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u); - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnfriendlyVisibleUnitInObjectRangeCheck - { - public: - AnyUnfriendlyVisibleUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) - : i_obj(obj), i_funit(funit), i_range(range) {} - - bool operator()(Unit* u) - { - return u->isAlive() - && i_obj->IsWithinDistInMap(u, i_range) - && !i_funit->IsFriendlyTo(u) - && u->isVisibleForOrDetect(i_funit, false); - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class CreatureWithDbGUIDCheck - { - public: - CreatureWithDbGUIDCheck(WorldObject const* obj, uint32 lowguid) : i_obj(obj), i_lowguid(lowguid) {} - bool operator()(Creature* u) - { - return u->GetDBTableGUIDLow() == i_lowguid; - } - private: - WorldObject const* i_obj; - uint32 i_lowguid; - }; - - class AnyFriendlyUnitInObjectRangeCheck - { - public: - AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) - return true; - else - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnitInObjectRangeCheck - { - public: - AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - WorldObject const* i_obj; - float i_range; - }; - - // Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit) - class NearestAttackableUnitInObjectRangeCheck - { - public: - NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) && - !i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,false)) - { - i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - - // prevent clone this object - NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); - }; - - class AnyAoETargetUnitInObjectRangeCheck - { - public: - AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) - : i_obj(obj), i_funit(funit), i_range(range) - { - Unit const* check = i_funit; - Unit const* owner = i_funit->GetOwner(); - if (owner) - check = owner; - i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER); - } - bool operator()(Unit* u) - { - // Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems - if (!u->isTargetableForAttack()) - return false; - if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) - return false; - - if ((i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u))&& i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - bool i_targetForPlayer; - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - // do attack at call of help to friendly crearture - class CallOfHelpCreatureInRangeDo - { - public: - CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range) - : i_funit(funit), i_enemy(enemy), i_range(range) - {} - void operator()(Creature* u) - { - if (u == i_funit) - return; - - if (!u->CanAssistTo(i_funit, i_enemy, false)) - return; - - // too far - if (!u->IsWithinDistInMap(i_enemy, i_range)) - return; - - // only if see assisted creature's enemy - if (!u->IsWithinLOSInMap(i_enemy)) - return; - - if (u->AI()) - u->AI()->AttackStart(i_enemy); - } - private: - Unit* const i_funit; - Unit* const i_enemy; - float i_range; - }; - - struct AnyDeadUnitCheck - { - bool operator()(Unit* u) { return !u->isAlive(); } - }; - - struct AnyStealthedCheck - { - bool operator()(Unit* u) { return u->GetVisibility() == VISIBILITY_GROUP_STEALTH; } - }; - - // Creature checks - - class NearestHostileUnitCheck - { - public: - explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0) : me(creature) - { - m_range = (dist == 0 ? 9999 : dist); - } - bool operator()(Unit* u) - { - if (!me->IsWithinDistInMap(u, m_range)) - return false; - - if (!me->canAttack(u)) - return false; - - m_range = me->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - - private: - Creature const *me; - float m_range; - NearestHostileUnitCheck(NearestHostileUnitCheck const&); - }; - - class NearestHostileUnitInAttackDistanceCheck - { - public: - explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0) : me(creature) - { - m_range = (dist == 0 ? 9999 : dist); - m_force = (dist == 0 ? false : true); - } - bool operator()(Unit* u) - { - if (!me->IsWithinDistInMap(u, m_range)) - return false; - - if (m_force) - { - if (!me->canAttack(u)) - return false; - } - else - { - if (!me->canStartAttack(u, false)) - return false; - } - - m_range = me->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - float GetLastRange() const { return m_range; } - private: - Creature const *me; - float m_range; - bool m_force; - NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&); - }; - - class AnyAssistCreatureInRangeCheck - { - public: - AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range) - : i_funit(funit), i_enemy(enemy), i_range(range) - { - } - bool operator()(Creature* u) - { - if (u == i_funit) - return false; - - if (!u->CanAssistTo(i_funit, i_enemy)) - return false; - - // too far - if (!i_funit->IsWithinDistInMap(u, i_range)) - return false; - - // only if see assisted creature - if (!i_funit->IsWithinLOSInMap(u)) - return false; - - return true; - } - private: - Unit* const i_funit; - Unit* const i_enemy; - float i_range; - }; - - class NearestAssistCreatureInCreatureRangeCheck - { - public: - NearestAssistCreatureInCreatureRangeCheck(Creature* obj, Unit* enemy, float range) - : i_obj(obj), i_enemy(enemy), i_range(range) {} - - bool operator()(Creature* u) - { - if (u == i_obj) - return false; - if (!u->CanAssistTo(i_obj,i_enemy)) - return false; - - if (!i_obj->IsWithinDistInMap(u, i_range)) - return false; - - if (!i_obj->IsWithinLOSInMap(u)) - return false; - - i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - float GetLastRange() const { return i_range; } - private: - Creature* const i_obj; - Unit* const i_enemy; - float i_range; - - // prevent clone this object - NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&); - }; - - // Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature) - class NearestCreatureEntryWithLiveStateInObjectRangeCheck - { - public: - NearestCreatureEntryWithLiveStateInObjectRangeCheck(WorldObject const& obj, uint32 entry, bool alive, float range) - : i_obj(obj), i_entry(entry), i_alive(alive), i_range(range) {} - - bool operator()(Creature* u) - { - if (u->GetEntry() == i_entry && u->isAlive() == i_alive && i_obj.IsWithinDistInMap(u, i_range)) - { - i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - uint32 i_entry; - bool i_alive; - float i_range; - - // prevent clone this object - NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&); - }; - - class AnyPlayerInObjectRangeCheck - { - public: - AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Player* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - WorldObject const* i_obj; - float i_range; - }; - - class AllFriendlyCreaturesInGrid - { - public: - AllFriendlyCreaturesInGrid(Unit const* obj) : pUnit(obj) {} - bool operator() (Unit* u) - { - if (u->isAlive() && u->GetVisibility() == VISIBILITY_ON && u->IsFriendlyTo(pUnit)) - return true; - - return false; - } - private: - Unit const* pUnit; - }; - - class AllGameObjectsWithEntryInRange - { - public: - AllGameObjectsWithEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} - bool operator() (GameObject* pGo) - { - if (pGo->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pGo,m_fRange,false)) - return true; - - return false; - } - private: - const WorldObject* m_pObject; - uint32 m_uiEntry; - float m_fRange; - }; - - class AllCreaturesOfEntryInRange - { - public: - AllCreaturesOfEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} - bool operator() (Unit* pUnit) - { - if (pUnit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pUnit,m_fRange,false)) - return true; - - return false; - } - - private: - const WorldObject* m_pObject; - uint32 m_uiEntry; - float m_fRange; - }; - - class PlayerAtMinimumRangeAway - { - public: - PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : pUnit(unit), fRange(fMinRange) {} - bool operator() (Player* pPlayer) - { - //No threat list check, must be done explicit if expected to be in combat with creature - if (!pPlayer->isGameMaster() && pPlayer->isAlive() && !pUnit->IsWithinDist(pPlayer,fRange,false)) - return true; - - return false; - } - - private: - Unit const* pUnit; - float fRange; - }; - - class GameObjectInRangeCheck - { - public: - GameObjectInRangeCheck(float _x, float _y, float _z, float _range) : x(_x), y(_y), z(_z), range(_range) {} - bool operator() (GameObject* go) - { - return go->IsInRange(x, y, z, range); - } - private: - float x, y, z, range; - }; - - // Player checks and do - - // Prepare using Builder localized packets with caching and send to player - template - class LocalizedPacketDo - { - public: - explicit LocalizedPacketDo(Builder& builder) : i_builder(builder) {} - - ~LocalizedPacketDo() - { - for (size_t i = 0; i < i_data_cache.size(); ++i) - delete i_data_cache[i]; - } - void operator()(Player* p); - - private: - Builder& i_builder; - std::vector i_data_cache; // 0 = default, i => i-1 locale index - }; - - // Prepare using Builder localized packets with caching and send to player - template - class LocalizedPacketListDo - { - public: - typedef std::vector WorldPacketList; - explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {} - - ~LocalizedPacketListDo() - { - for (size_t i = 0; i < i_data_cache.size(); ++i) - for (size_t j = 0; j < i_data_cache[i].size(); ++j) - delete i_data_cache[i][j]; - } - void operator()(Player* p); - - private: - Builder& i_builder; - std::vector i_data_cache; - // 0 = default, i => i-1 locale index - }; -} -#endif diff --git a/src/server/game/Map/Grid/GridNotifiersImpl.h b/src/server/game/Map/Grid/GridNotifiersImpl.h deleted file mode 100644 index 26a9c0bd328..00000000000 --- a/src/server/game/Map/Grid/GridNotifiersImpl.h +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDNOTIFIERSIMPL_H -#define TRINITY_GRIDNOTIFIERSIMPL_H - -#include "GridNotifiers.h" -#include "WorldPacket.h" -#include "Corpse.h" -#include "Player.h" -#include "UpdateData.h" -#include "CreatureAI.h" -#include "SpellAuras.h" - - -template -inline void -Trinity::VisibleNotifier::Visit(GridRefManager &m) -{ - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - { - vis_guids.erase(iter->getSource()->GetGUID()); - i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow); - } -} - -inline void -Trinity::ObjectUpdater::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - if (iter->getSource()->IsInWorld() && !iter->getSource()->isSpiritService()) - iter->getSource()->Update(i_timeDiff); -} - -// SEARCHERS & LIST SEARCHERS & WORKERS - -// WorldObject searchers & workers - -template -void Trinity::WorldObjectSearcher::Visit(GameObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(CorpseMapType &m) -{ - // already found - if (i_object) - return; - - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(DynamicObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(CorpseMapType &m) -{ - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Gameobject searchers - -template -void Trinity::GameObjectSearcher::Visit(GameObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::GameObjectLastSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::GameObjectListSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Unit searchers - -template -void Trinity::UnitSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::UnitSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::UnitLastSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::UnitLastSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::UnitListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::UnitListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Creature searchers - -template -void Trinity::CreatureSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::CreatureLastSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::CreatureListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::PlayerListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::PlayerSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::LocalizedPacketDo::operator()(Player* p) -{ - int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; - WorldPacket* data; - - // create if not cached yet - if (i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx]) - { - if (i_data_cache.size() < cache_idx+1) - i_data_cache.resize(cache_idx+1); - - data = new WorldPacket(SMSG_MESSAGECHAT, 200); - - i_builder(*data,loc_idx); - - i_data_cache[cache_idx] = data; - } - else - data = i_data_cache[cache_idx]; - - p->SendDirectMessage(data); -} - -template -void Trinity::LocalizedPacketListDo::operator()(Player* p) -{ - int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; - WorldPacketList* data_list; - - // create if not cached yet - if (i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty()) - { - if (i_data_cache.size() < cache_idx+1) - i_data_cache.resize(cache_idx+1); - - data_list = &i_data_cache[cache_idx]; - - i_builder(*data_list,loc_idx); - } - else - data_list = &i_data_cache[cache_idx]; - - for (size_t i = 0; i < data_list->size(); ++i) - p->SendDirectMessage((*data_list)[i]); -} - -#endif // TRINITY_GRIDNOTIFIERSIMPL_H diff --git a/src/server/game/Map/Grid/GridStates.cpp b/src/server/game/Map/Grid/GridStates.cpp deleted file mode 100644 index 9d39531cfad..00000000000 --- a/src/server/game/Map/Grid/GridStates.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "GridStates.h" -#include "GridNotifiers.h" -#include "GameSystem/Grid.h" -#include "Log.h" - -void -InvalidState::Update(Map &, NGridType &, GridInfo &, const uint32 &/*x*/, const uint32 &/*y*/, const uint32 &) const -{ -} - -void -ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const -{ - // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle - info.UpdateTimeTracker(t_diff); - if (info.getTimeTracker().Passed()) - { - if (grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y)) - { - ObjectGridStoper stoper(grid); - stoper.StopN(); - grid.SetGridState(GRID_STATE_IDLE); - sLog.outDebug("Grid[%u,%u] on map %u moved to IDLE state", x, y, m.GetId()); - } - else - { - m.ResetGridExpiry(grid, 0.1f); - } - } -} - -void -IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &) const -{ - m.ResetGridExpiry(grid); - grid.SetGridState(GRID_STATE_REMOVAL); - sLog.outDebug("Grid[%u,%u] on map %u moved to REMOVAL state", x, y, m.GetId()); -} - -void -RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const -{ - if (!info.getUnloadLock()) - { - info.UpdateTimeTracker(t_diff); - if (info.getTimeTracker().Passed()) - { - if (!m.UnloadGrid(x, y, false)) - { - sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players or active objects nearby", x, y, m.GetId()); - m.ResetGridExpiry(grid); - } - } - } -} - diff --git a/src/server/game/Map/Grid/GridStates.h b/src/server/game/Map/Grid/GridStates.h deleted file mode 100644 index c2a75ec45b7..00000000000 --- a/src/server/game/Map/Grid/GridStates.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDSTATES_H -#define TRINITY_GRIDSTATES_H - -#include "Map.h" -#include "Object.h" - -class GridState -{ - public: -#ifdef TRINITY_DEBUG -#define MAGIC_TESTVAL 0xFBE823BA - GridState() { i_Magic = MAGIC_TESTVAL; } - bool checkMagic() - { - if (i_Magic != MAGIC_TESTVAL) - { - sLog.outError("!!! GridState: Magic value gone !!!"); - return false; - } - return true; - } - void setMagic() { i_Magic = MAGIC_TESTVAL; } - unsigned int i_Magic; -#endif - virtual void Update(Map &, NGridType&, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const = 0; -}; - -class InvalidState : public GridState -{ - public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; -}; - -class ActiveState : public GridState -{ - public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; -}; - -class IdleState : public GridState -{ - public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; -}; - -class RemovalState : public GridState -{ - public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; -}; -#endif - diff --git a/src/server/game/Map/Grid/ObjectGridLoader.cpp b/src/server/game/Map/Grid/ObjectGridLoader.cpp deleted file mode 100644 index ab69d9a966b..00000000000 --- a/src/server/game/Map/Grid/ObjectGridLoader.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ObjectGridLoader.h" -#include "ObjectAccessor.h" -#include "ObjectMgr.h" -#include "Creature.h" -#include "Vehicle.h" -#include "GameObject.h" -#include "DynamicObject.h" -#include "Corpse.h" -#include "World.h" -#include "CellImpl.h" -#include "CreatureAI.h" - -class ObjectGridRespawnMover -{ - public: - ObjectGridRespawnMover() {} - - void Move(GridType &grid); - - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &m); -}; - -void -ObjectGridRespawnMover::Move(GridType &grid) -{ - TypeContainerVisitor mover(*this); - grid.Visit(mover); -} - -void -ObjectGridRespawnMover::Visit(CreatureMapType &m) -{ - // creature in unloading grid can have respawn point in another grid - // if it will be unloaded then it will not respawn in original grid until unload/load original grid - // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn. - for (CreatureMapType::iterator iter = m.begin(); iter != m.end();) - { - Creature * c = iter->getSource(); - ++iter; - - assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); - - Cell const& cur_cell = c->GetCurrentCell(); - - float resp_x, resp_y, resp_z; - c->GetRespawnCoord(resp_x, resp_y, resp_z); - CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y); - Cell resp_cell(resp_val); - - if (cur_cell.DiffGrid(resp_cell)) - { - c->GetMap()->CreatureRespawnRelocation(c); - // false result ignored: will be unload with other creatures at grid - } - } -} - -// for loading world object at grid loading (Corpses) -class ObjectWorldLoader -{ - public: - explicit ObjectWorldLoader(ObjectGridLoader& gloader) - : i_cell(gloader.i_cell), i_grid(gloader.i_grid), i_map(gloader.i_map), i_corpses (0) - {} - - void Visit(CorpseMapType &m); - - template void Visit(GridRefManager&) { } - - private: - Cell i_cell; - NGridType &i_grid; - Map* i_map; - public: - uint32 i_corpses; -}; - -template void addUnitState(T* /*obj*/, CellPair const& /*cell_pair*/) -{ -} - -template<> void addUnitState(Creature *obj, CellPair const& cell_pair) -{ - Cell cell(cell_pair); - - obj->SetCurrentCell(cell); - if (obj->isSpiritService()) - obj->setDeathState(DEAD); -} - -template -void AddObjectHelper(CellPair &cell, GridRefManager &m, uint32 &count, Map* map, T *obj) -{ - obj->GetGridRef().link(&m, obj); - addUnitState(obj,cell); - obj->AddToWorld(); - if (obj->isActiveObject()) - map->AddToActive(obj); - - ++count; -} - -template -void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager &m, uint32 &count, Map* map) -{ - for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) - { - T* obj = new T; - uint32 guid = *i_guid; - //sLog.outString("DEBUG: LoadHelper from table: %s for (guid: %u) Loading",table,guid); - if (!obj->LoadFromDB(guid, map)) - { - delete obj; - continue; - } - - AddObjectHelper(cell, m, count, map, obj); - } -} - -void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map) -{ - if (cell_corpses.empty()) - return; - - for (CellCorpseSet::const_iterator itr = cell_corpses.begin(); itr != cell_corpses.end(); ++itr) - { - if (itr->second != map->GetInstanceId()) - continue; - - uint32 player_guid = itr->first; - - Corpse *obj = ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid); - if (!obj) - continue; - - // TODO: this is a hack - // corpse's map should be reset when the map is unloaded - // but it may still exist when the grid is unloaded but map is not - // in that case map == currMap - obj->SetMap(map); - - AddObjectHelper(cell, m, count, map, obj); - } -} - -void -ObjectGridLoader::Visit(GameObjectMapType &m) -{ - uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); - uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); - CellPair cell_pair(x,y); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); - - LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map); -} - -void -ObjectGridLoader::Visit(CreatureMapType &m) -{ - uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); - uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); - CellPair cell_pair(x,y); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); - - LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map); -} - -void -ObjectWorldLoader::Visit(CorpseMapType &m) -{ - uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); - uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); - CellPair cell_pair(x,y); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - // corpses are always added to spawn mode 0 and they are spawned by their instance id - CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id); - LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map); -} - -void -ObjectGridLoader::Load(GridType &grid) -{ - { - TypeContainerVisitor loader(*this); - grid.Visit(loader); - } - - { - ObjectWorldLoader wloader(*this); - TypeContainerVisitor loader(wloader); - grid.Visit(loader); - i_corpses = wloader.i_corpses; - } -} - -void ObjectGridLoader::LoadN(void) -{ - i_gameObjects = 0; i_creatures = 0; i_corpses = 0; - i_cell.data.Part.cell_y = 0; - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - i_cell.data.Part.cell_x = x; - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - i_cell.data.Part.cell_y = y; - GridLoader loader; - loader.Load(i_grid(x, y), *this); - } - } - sLog.outDebug("%u GameObjects, %u Creatures, and %u Corpses/Bones loaded for grid %u on map %u", i_gameObjects, i_creatures, i_corpses,i_grid.GetGridId(), i_map->GetId()); -} - -void ObjectGridUnloader::MoveToRespawnN() -{ - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - ObjectGridRespawnMover mover; - mover.Move(i_grid(x, y)); - } - } -} - -void -ObjectGridUnloader::Unload(GridType &grid) -{ - TypeContainerVisitor unloader(*this); - grid.Visit(unloader); -} - -template -void -ObjectGridUnloader::Visit(GridRefManager &m) -{ - while (!m.isEmpty()) - { - T *obj = m.getFirst()->getSource(); - // if option set then object already saved at this moment - if (!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) - obj->SaveRespawnTime(); - ///- object will get delinked from the manager when deleted - delete obj; - } -} - -void -ObjectGridStoper::Stop(GridType &grid) -{ - TypeContainerVisitor stoper(*this); - grid.Visit(stoper); -} - -void -ObjectGridStoper::Visit(CreatureMapType &m) -{ - // stop any fights at grid de-activation and remove dynobjects created at cast by creatures - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - iter->getSource()->RemoveAllDynObjects(); - if (iter->getSource()->isInCombat()) - { - iter->getSource()->CombatStop(); - iter->getSource()->DeleteThreatList(); - iter->getSource()->AI()->EnterEvadeMode(); - } - } -} - -void -ObjectGridCleaner::Stop(GridType &grid) -{ - TypeContainerVisitor stoper(*this); - grid.Visit(stoper); -} - -void -ObjectGridCleaner::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - iter->getSource()->CleanupsBeforeDelete(); -} - -template -void -ObjectGridCleaner::Visit(GridRefManager &m) -{ - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - iter->getSource()->RemoveFromWorld(); -} - -template void ObjectGridUnloader::Visit(CreatureMapType &); -template void ObjectGridUnloader::Visit(GameObjectMapType &); -template void ObjectGridUnloader::Visit(DynamicObjectMapType &); -template void ObjectGridUnloader::Visit(CorpseMapType &); -template void ObjectGridCleaner::Visit(GameObjectMapType &); -template void ObjectGridCleaner::Visit(DynamicObjectMapType &); -template void ObjectGridCleaner::Visit(CorpseMapType &); diff --git a/src/server/game/Map/Grid/ObjectGridLoader.h b/src/server/game/Map/Grid/ObjectGridLoader.h deleted file mode 100644 index e890bf8d482..00000000000 --- a/src/server/game/Map/Grid/ObjectGridLoader.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_OBJECTGRIDLOADER_H -#define TRINITY_OBJECTGRIDLOADER_H - -#include "Utilities/TypeList.h" -#include "Platform/Define.h" -#include "GameSystem/GridLoader.h" -#include "GridDefines.h" -#include "Cell.h" - -class ObjectWorldLoader; - -class ObjectGridLoader -{ - friend class ObjectWorldLoader; - - public: - ObjectGridLoader(NGridType &grid, Map* map, const Cell &cell) - : i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses (0) - {} - - void Load(GridType &grid); - void Visit(GameObjectMapType &m); - void Visit(CreatureMapType &m); - void Visit(CorpseMapType &) {} - - void Visit(DynamicObjectMapType&) { } - - void LoadN(void); - - private: - Cell i_cell; - NGridType &i_grid; - Map* i_map; - uint32 i_gameObjects; - uint32 i_creatures; - uint32 i_corpses; -}; - -class ObjectGridUnloader -{ - public: - ObjectGridUnloader(NGridType &grid) : i_grid(grid) {} - - void MoveToRespawnN(); - void UnloadN() - { - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - GridLoader loader; - loader.Unload(i_grid(x, y), *this); - } - } - } - - void Unload(GridType &grid); - template void Visit(GridRefManager &m); - private: - NGridType &i_grid; -}; - -class ObjectGridStoper -{ - public: - ObjectGridStoper(NGridType &grid) : i_grid(grid) {} - - void StopN() - { - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - GridLoader loader; - loader.Stop(i_grid(x, y), *this); - } - } - } - - void Stop(GridType &grid); - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - private: - NGridType &i_grid; -}; - -class ObjectGridCleaner -{ - public: - ObjectGridCleaner(NGridType &grid) : i_grid(grid) {} - - void CleanN() - { - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - GridLoader loader; - loader.Stop(i_grid(x, y), *this); - } - } - } - - void Stop(GridType &grid); - void Visit(CreatureMapType &m); - template void Visit(GridRefManager &); - private: - NGridType &i_grid; -}; - -typedef GridLoader GridLoaderType; -#endif - diff --git a/src/server/game/Map/Map.cpp b/src/server/game/Map/Map.cpp deleted file mode 100644 index 11bfdcd6f99..00000000000 --- a/src/server/game/Map/Map.cpp +++ /dev/null @@ -1,3936 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "MapManager.h" -#include "Player.h" -#include "Vehicle.h" -#include "GridNotifiers.h" -#include "Log.h" -#include "GridStates.h" -#include "CellImpl.h" -#include "InstanceData.h" -#include "Map.h" -#include "GridNotifiersImpl.h" -#include "Config/ConfigEnv.h" -#include "Transports.h" -#include "ObjectAccessor.h" -#include "ObjectMgr.h" -#include "World.h" -#include "Group.h" -#include "MapRefManager.h" -#include "Vehicle.h" -#include "WaypointManager.h" -#include "DBCEnums.h" -#include "ScriptMgr.h" -#include "ScriptedCreature.h" -#include "GossipDef.h" - -#include "MapInstanced.h" -#include "InstanceSaveMgr.h" -#include "VMapFactory.h" - -#define DEFAULT_GRID_EXPIRY 300 -#define MAX_GRID_LOAD_TIME 50 -#define MAX_CREATURE_ATTACK_RADIUS (45.0f * sWorld.getRate(RATE_CREATURE_AGGRO)) - -GridState* si_GridStates[MAX_GRID_STATE]; - -struct ScriptAction -{ - uint64 sourceGUID; - uint64 targetGUID; - uint64 ownerGUID; // owner of source if source is item - ScriptInfo const* script; // pointer to static script data -}; - -Map::~Map() -{ - UnloadAll(); - - while (!i_worldObjects.empty()) - { - WorldObject *obj = *i_worldObjects.begin(); - assert(obj->m_isWorldObject); - //assert(obj->GetTypeId() == TYPEID_CORPSE); - obj->RemoveFromWorld(); - obj->ResetMap(); - } - - if (!m_scriptSchedule.empty()) - sWorld.DecreaseScheduledScriptCount(m_scriptSchedule.size()); -} - -bool Map::ExistMap(uint32 mapid,int gx,int gy) -{ - int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; - char* tmp = new char[len]; - snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,gx,gy); - - FILE *pf=fopen(tmp,"rb"); - - if (!pf) - { - sLog.outError("Map file '%s': does not exist!",tmp); - delete[] tmp; - return false; - } - - map_fileheader header; - fread(&header, sizeof(header), 1, pf); - if (header.mapMagic != uint32(MAP_MAGIC) || - header.versionMagic != uint32(MAP_VERSION_MAGIC)) - { - sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); - delete [] tmp; - fclose(pf); //close file before return - return false; - } - - delete [] tmp; - fclose(pf); - return true; -} - -bool Map::ExistVMap(uint32 mapid,int gx,int gy) -{ - if (VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager()) - { - if (vmgr->isMapLoadingEnabled()) - { - // x and y are swapped !! => fixed now - bool exists = vmgr->existsMap((sWorld.GetDataPath()+ "vmaps").c_str(), mapid, gx,gy); - if (!exists) - { - std::string name = vmgr->getDirFileName(mapid,gx,gy); - sLog.outError("VMap file '%s' is missing or points to wrong version of vmap file. Redo vmaps with latest version of vmap_assembler.exe.", (sWorld.GetDataPath()+"vmaps/"+name).c_str()); - return false; - } - } - } - - return true; -} - -void Map::LoadVMap(int gx,int gy) -{ - // x and y are swapped !! - int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath()+ "vmaps").c_str(), GetId(), gx,gy); - switch(vmapLoadResult) - { - case VMAP::VMAP_LOAD_RESULT_OK: - sLog.outDetail("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); - break; - case VMAP::VMAP_LOAD_RESULT_ERROR: - sLog.outDetail("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); - break; - case VMAP::VMAP_LOAD_RESULT_IGNORED: - DEBUG_LOG("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); - break; - } -} - -void Map::LoadMap(int gx,int gy, bool reload) -{ - if (i_InstanceId != 0) - { - if (GridMaps[gx][gy]) - return; - - // load grid map for base map - if (!m_parentMap->GridMaps[gx][gy]) - m_parentMap->EnsureGridCreated(GridPair(63-gx,63-gy)); - - ((MapInstanced*)(m_parentMap))->AddGridMapReference(GridPair(gx,gy)); - GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy]; - return; - } - - if (GridMaps[gx][gy] && !reload) - return; - - //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?) - if (GridMaps[gx][gy]) - { - sLog.outDetail("Unloading previously loaded map %u before reloading.",GetId()); - delete (GridMaps[gx][gy]); - GridMaps[gx][gy]=NULL; - } - - // map file name - char *tmp=NULL; - int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; - tmp = new char[len]; - snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),GetId(),gx,gy); - sLog.outDetail("Loading map %s",tmp); - // loading data - GridMaps[gx][gy] = new GridMap(); - if (!GridMaps[gx][gy]->loadData(tmp)) - { - sLog.outError("Error loading map file: \n %s\n", tmp); - } - delete [] tmp; -} - -void Map::LoadMapAndVMap(int gx,int gy) -{ - LoadMap(gx,gy); - if (i_InstanceId == 0) - LoadVMap(gx, gy); // Only load the data for the base map -} - -void Map::InitStateMachine() -{ - si_GridStates[GRID_STATE_INVALID] = new InvalidState; - si_GridStates[GRID_STATE_ACTIVE] = new ActiveState; - si_GridStates[GRID_STATE_IDLE] = new IdleState; - si_GridStates[GRID_STATE_REMOVAL] = new RemovalState; -} - -void Map::DeleteStateMachine() -{ - delete si_GridStates[GRID_STATE_INVALID]; - delete si_GridStates[GRID_STATE_ACTIVE]; - delete si_GridStates[GRID_STATE_IDLE]; - delete si_GridStates[GRID_STATE_REMOVAL]; -} - -Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent) - : i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId), m_unloadTimer(0), - m_activeNonPlayersIter(m_activeNonPlayers.end()), - i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this), - m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE), - m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD), - i_scriptLock(false) -{ - for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) - { - for (unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j) - { - //z code - GridMaps[idx][j] =NULL; - setNGrid(NULL, idx, j); - } - } - - //lets initialize visibility distance for map - Map::InitVisibilityDistance(); -} - -void Map::InitVisibilityDistance() -{ - //init visibility for continents - m_VisibleDistance = World::GetMaxVisibleDistanceOnContinents(); - m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodOnContinents(); -} - -// Template specialization of utility methods -template -void Map::AddToGrid(T* obj, NGridType *grid, Cell const& cell) -{ - if (obj->m_isWorldObject) - (*grid)(cell.CellX(), cell.CellY()).template AddWorldObject(obj); - else - (*grid)(cell.CellX(), cell.CellY()).template AddGridObject(obj); -} - -template<> -void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell) -{ - if (obj->m_isWorldObject) - (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(obj); - else - (*grid)(cell.CellX(), cell.CellY()).AddGridObject(obj); - - obj->SetCurrentCell(cell); -} - -template -void Map::RemoveFromGrid(T* obj, NGridType *grid, Cell const& cell) -{ - if (obj->m_isWorldObject) - (*grid)(cell.CellX(), cell.CellY()).template RemoveWorldObject(obj); - else - (*grid)(cell.CellX(), cell.CellY()).template RemoveGridObject(obj); -} - -template -void Map::SwitchGridContainers(T* obj, bool on) -{ - CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("Map::SwitchGridContainers: Object " I64FMT " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); - return; - } - - Cell cell(p); - if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) - return; - - DEBUG_LOG("Switch object " I64FMT " from grid[%u,%u] %u", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y, on); - NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY()); - assert(ngrid != NULL); - - GridType &grid = (*ngrid)(cell.CellX(), cell.CellY()); - - if (on) - { - grid.RemoveGridObject(obj); - grid.AddWorldObject(obj); - /*if (!grid.RemoveGridObject(obj, obj->GetGUID()) - || !grid.AddWorldObject(obj, obj->GetGUID())) - { - assert(false); - }*/ - } - else - { - grid.RemoveWorldObject(obj); - grid.AddGridObject(obj); - /*if (!grid.RemoveWorldObject(obj, obj->GetGUID()) - || !grid.AddGridObject(obj, obj->GetGUID())) - { - assert(false); - }*/ - } - obj->m_isWorldObject = on; -} - -template void Map::SwitchGridContainers(Creature *, bool); -//template void Map::SwitchGridContainers(DynamicObject *, bool); - -template -void Map::DeleteFromWorld(T* obj) -{ - // Note: In case resurrectable corpse and pet its removed from global lists in own destructor - delete obj; -} - -template<> -void Map::DeleteFromWorld(Player* pl) -{ - ObjectAccessor::Instance().RemoveObject(pl); - delete pl; -} - -void -Map::EnsureGridCreated(const GridPair &p) -{ - if (!getNGrid(p.x_coord, p.y_coord)) - { - Guard guard(*this); - if (!getNGrid(p.x_coord, p.y_coord)) - { - sLog.outDebug("Creating grid[%u,%u] for map %u instance %u", p.x_coord, p.y_coord, GetId(), i_InstanceId); - - setNGrid(new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld.getConfig(CONFIG_GRID_UNLOAD)), - p.x_coord, p.y_coord); - - // build a linkage between this map and NGridType - buildNGridLinkage(getNGrid(p.x_coord, p.y_coord)); - - getNGrid(p.x_coord, p.y_coord)->SetGridState(GRID_STATE_IDLE); - - //z coord - int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord; - int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord; - - if (!GridMaps[gx][gy]) - LoadMapAndVMap(gx,gy); - } - } -} - -void -Map::EnsureGridLoadedAtEnter(const Cell &cell, Player *player) -{ - EnsureGridLoaded(cell); - NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); - assert(grid != NULL); - - if (player) - { - DEBUG_LOG("Player %s enter cell[%u,%u] triggers loading of grid[%u,%u] on map %u", player->GetName(), cell.CellX(), cell.CellY(), cell.GridX(), cell.GridY(), GetId()); - } - else - { - DEBUG_LOG("Active object nearby triggers loading of grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), GetId()); - } - - // refresh grid state & timer - if (grid->GetGridState() != GRID_STATE_ACTIVE) - { - ResetGridExpiry(*grid, 0.1f); - grid->SetGridState(GRID_STATE_ACTIVE); - } -} - -bool Map::EnsureGridLoaded(const Cell &cell) -{ - EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); - NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); - - assert(grid != NULL); - if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY())) - { - sLog.outDebug("Loading grid[%u,%u] for map %u instance %u", cell.GridX(), cell.GridY(), GetId(), i_InstanceId); - - ObjectGridLoader loader(*grid, this, cell); - loader.LoadN(); - - // Add resurrectable corpses to world object list in grid - ObjectAccessor::Instance().AddCorpsesToGrid(GridPair(cell.GridX(),cell.GridY()),(*grid)(cell.CellX(), cell.CellY()), this); - - setGridObjectDataLoaded(true,cell.GridX(), cell.GridY()); - return true; - } - - return false; -} - -void Map::LoadGrid(float x, float y) -{ - CellPair pair = Trinity::ComputeCellPair(x, y); - Cell cell(pair); - EnsureGridLoaded(cell); -} - -bool Map::Add(Player *player) -{ - // Check if we are adding to correct map - assert (player->GetMap() == this); - CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("Map::Add: Player (GUID: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord); - return false; - } - - player->SetMap(this); - - Cell cell(p); - EnsureGridLoadedAtEnter(cell, player); - NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); - assert(grid != NULL); - AddToGrid(player, grid, cell); - - player->AddToWorld(); - - SendInitSelf(player); - SendInitTransports(player); - - player->m_clientGUIDs.clear(); - player->UpdateObjectVisibility(true); - - return true; -} - -template -void -Map::Add(T *obj) -{ - CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("Map::Add: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); - return; - } - - Cell cell(p); - if (obj->IsInWorld()) // need some clean up later - { - obj->UpdateObjectVisibility(true); - return; - } - - if (obj->isActiveObject()) - EnsureGridLoadedAtEnter(cell); - else - EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); - - NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); - assert(grid != NULL); - - AddToGrid(obj,grid,cell); - //obj->SetMap(this); - obj->AddToWorld(); - - if (obj->isActiveObject()) - AddToActive(obj); - - DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY()); - - //something, such as vehicle, needs to be update immediately - //also, trigger needs to cast spell, if not update, cannot see visual - obj->UpdateObjectVisibility(true); -} - -/* -void Map::MessageBroadcast(Player *player, WorldPacket *msg, bool to_self) -{ - CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); - - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("Map::MessageBroadcast: Player (GUID: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord); - return; - } - - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) - return; - - Trinity::MessageDeliverer post_man(*player, msg, to_self); - TypeContainerVisitor message(post_man); - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, message, *this, *player, GetVisibilityDistance()); -} - -void Map::MessageBroadcast(WorldObject *obj, WorldPacket *msg) -{ - CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("Map::MessageBroadcast: Object (GUID: %u TypeId: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); - return; - } - - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) - return; - - //TODO: currently on continents when Visibility.Distance.InFlight > Visibility.Distance.Continents - //we have alot of blinking mobs because monster move packet send is broken... - Trinity::ObjectMessageDeliverer post_man(*obj,msg); - TypeContainerVisitor message(post_man); - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, message, *this, *obj, GetVisibilityDistance()); -} - -void Map::MessageDistBroadcast(Player *player, WorldPacket *msg, float dist, bool to_self, bool own_team_only) -{ - CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); - - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("Map::MessageBroadcast: Player (GUID: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord); - return; - } - - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) - return; - - Trinity::MessageDistDeliverer post_man(*player, msg, dist, to_self, own_team_only); - TypeContainerVisitor message(post_man); - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, message, *this, *player, dist); -} - -void Map::MessageDistBroadcast(WorldObject *obj, WorldPacket *msg, float dist) -{ - CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - { - sLog.outError("Map::MessageBroadcast: Object (GUID: %u TypeId: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); - return; - } - - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) - return; - - Trinity::ObjectMessageDistDeliverer post_man(*obj, msg, dist); - TypeContainerVisitor message(post_man); - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, message, *this, *obj, dist); -} -*/ - -bool Map::loaded(const GridPair &p) const -{ - return (getNGrid(p.x_coord, p.y_coord) && isGridObjectDataLoaded(p.x_coord, p.y_coord)); -} - -void Map::Update(const uint32 &t_diff) -{ - /// update players at tick - for (m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) - { - Player* plr = m_mapRefIter->getSource(); - if (plr && plr->IsInWorld()) - plr->Update(t_diff); - } - - /// update active cells around players and active objects - resetMarkedCells(); - - Trinity::ObjectUpdater updater(t_diff); - // for creature - TypeContainerVisitor grid_object_update(updater); - // for pets - TypeContainerVisitor world_object_update(updater); - - // the player iterator is stored in the map object - // to make sure calls to Map::Remove don't invalidate it - for (m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) - { - Player* plr = m_mapRefIter->getSource(); - - if (!plr->IsInWorld()) - continue; - - CellPair standing_cell(Trinity::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY())); - - // Check for correctness of standing_cell, it also avoids problems with update_cell - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - continue; - - // the overloaded operators handle range checking - // so ther's no need for range checking inside the loop - CellPair begin_cell(standing_cell), end_cell(standing_cell); - //lets update mobs/objects in ALL visible cells around player! - CellArea area = Cell::CalculateCellArea(*plr, GetVisibilityDistance()); - area.ResizeBorders(begin_cell, end_cell); - - for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) - { - // marked cells are those that have been visited - // don't visit the same cell twice - uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; - if (!isCellMarked(cell_id)) - { - markCell(cell_id); - CellPair pair(x,y); - Cell cell(pair); - cell.data.Part.reserved = CENTER_DISTRICT; - //cell.SetNoCreate(); - cell.Visit(pair, grid_object_update, *this); - cell.Visit(pair, world_object_update, *this); - } - } - } - } - - // non-player active objects - if (!m_activeNonPlayers.empty()) - { - for (m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end();) - { - // skip not in world - WorldObject* obj = *m_activeNonPlayersIter; - - // step before processing, in this case if Map::Remove remove next object we correctly - // step to next-next, and if we step to end() then newly added objects can wait next update. - ++m_activeNonPlayersIter; - - if (!obj->IsInWorld()) - continue; - - CellPair standing_cell(Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY())); - - // Check for correctness of standing_cell, it also avoids problems with update_cell - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - continue; - - // the overloaded operators handle range checking - // so ther's no need for range checking inside the loop - CellPair begin_cell(standing_cell), end_cell(standing_cell); - begin_cell << 1; begin_cell -= 1; // upper left - end_cell >> 1; end_cell += 1; // lower right - - for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) - { - // marked cells are those that have been visited - // don't visit the same cell twice - uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; - if (!isCellMarked(cell_id)) - { - markCell(cell_id); - CellPair pair(x,y); - Cell cell(pair); - cell.data.Part.reserved = CENTER_DISTRICT; - //cell.SetNoCreate(); - cell.Visit(pair, grid_object_update, *this); - cell.Visit(pair, world_object_update, *this); - } - } - } - } - } - - ///- Process necessary scripts - if (!m_scriptSchedule.empty()) - { - i_scriptLock = true; - ScriptsProcess(); - i_scriptLock = false; - } - - MoveAllCreaturesInMoveList(); - - if (!m_mapRefManager.isEmpty() || !m_activeNonPlayers.empty()) - ProcessRelocationNotifies(t_diff); -} - -struct ResetNotifier -{ - templateinline void resetNotify(GridRefManager &m) - { - for (typename GridRefManager::iterator iter=m.begin(); iter != m.end(); ++iter) - iter->getSource()->ResetAllNotifies(); - } - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &m) { resetNotify(m);} - void Visit(PlayerMapType &m) { resetNotify(m);} -}; - -void Map::ProcessRelocationNotifies(const uint32 & diff) -{ - for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end(); ++i) - { - NGridType *grid = i->getSource(); - - if (grid->GetGridState() != GRID_STATE_ACTIVE) - continue; - - grid->getGridInfoRef()->getRelocationTimer().TUpdate(diff); - if (!grid->getGridInfoRef()->getRelocationTimer().TPassed()) - continue; - - uint32 gx = grid->getX(), gy = grid->getY(); - - CellPair cell_min(gx*MAX_NUMBER_OF_CELLS, gy*MAX_NUMBER_OF_CELLS); - CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); - - for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x) - { - for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y) - { - uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; - if (!isCellMarked(cell_id)) - continue; - - CellPair pair(x,y); - Cell cell(pair); - cell.SetNoCreate(); - - Trinity::DelayedUnitRelocation cell_relocation(cell, pair, *this, GetVisibilityDistance()); - TypeContainerVisitor grid_object_relocation(cell_relocation); - TypeContainerVisitor world_object_relocation(cell_relocation); - Visit(cell, grid_object_relocation); - Visit(cell, world_object_relocation); - } - } - } - - ResetNotifier reset; - TypeContainerVisitor grid_notifier(reset); - TypeContainerVisitor world_notifier(reset); - for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end(); ++i) - { - NGridType *grid = i->getSource(); - - if (grid->GetGridState() != GRID_STATE_ACTIVE) - continue; - - if (!grid->getGridInfoRef()->getRelocationTimer().TPassed()) - continue; - - grid->getGridInfoRef()->getRelocationTimer().TReset(diff, m_VisibilityNotifyPeriod); - - uint32 gx = grid->getX(), gy = grid->getY(); - - CellPair cell_min(gx*MAX_NUMBER_OF_CELLS, gy*MAX_NUMBER_OF_CELLS); - CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); - - for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x) - { - for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y) - { - uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; - if (!isCellMarked(cell_id)) - continue; - - CellPair pair(x,y); - Cell cell(pair); - cell.SetNoCreate(); - Visit(cell, grid_notifier); - Visit(cell, world_notifier); - } - } - } -} - -void Map::Remove(Player *player, bool remove) -{ - player->RemoveFromWorld(); - SendRemoveTransports(player); - - CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - sLog.outCrash("Map::Remove: Player is in invalid cell!"); - else - { - Cell cell(p); - if (!getNGrid(cell.data.Part.grid_x, cell.data.Part.grid_y)) - sLog.outError("Map::Remove() i_grids was NULL x:%d, y:%d",cell.data.Part.grid_x,cell.data.Part.grid_y); - else - { - DEBUG_LOG("Remove player %s from grid[%u,%u]", player->GetName(), cell.GridX(), cell.GridY()); - NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); - assert(grid != NULL); - - player->UpdateObjectVisibility(true); - RemoveFromGrid(player,grid,cell); - } - } - - if (remove) - DeleteFromWorld(player); -} - -bool Map::RemoveBones(uint64 guid, float x, float y) -{ - if (IsRemovalGrid(x, y)) - { - Corpse * corpse = ObjectAccessor::Instance().GetObjectInWorld(GetId(), x, y, guid, (Corpse*)NULL); - if (corpse && corpse->GetTypeId() == TYPEID_CORPSE && corpse->GetType() == CORPSE_BONES) - corpse->DeleteBonesFromWorld(); - else - return false; - } - return true; -} - -template -void -Map::Remove(T *obj, bool remove) -{ - obj->RemoveFromWorld(); - if (obj->isActiveObject()) - RemoveFromActive(obj); - - CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - sLog.outError("Map::Remove: Object " I64FMT " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); - else - { - Cell cell(p); - if (loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) - { - DEBUG_LOG("Remove object " I64FMT " from grid[%u,%u]", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y); - NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); - assert(grid != NULL); - - obj->UpdateObjectVisibility(true); - RemoveFromGrid(obj,grid,cell); - } - } - - obj->ResetMap(); - - if (remove) - { - // if option set then object already saved at this moment - if (!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) - obj->SaveRespawnTime(); - DeleteFromWorld(obj); - } -} - -void -Map::PlayerRelocation(Player *player, float x, float y, float z, float orientation) -{ - assert(player); - - CellPair old_val = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); - CellPair new_val = Trinity::ComputeCellPair(x, y); - - Cell old_cell(old_val); - Cell new_cell(new_val); - - player->Relocate(x, y, z, orientation); - - if (old_cell.DiffGrid(new_cell) || old_cell.DiffCell(new_cell)) - { - DEBUG_LOG("Player %s relocation grid[%u,%u]cell[%u,%u]->grid[%u,%u]cell[%u,%u]", player->GetName(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); - - NGridType* oldGrid = getNGrid(old_cell.GridX(), old_cell.GridY()); - RemoveFromGrid(player, oldGrid,old_cell); - - if (old_cell.DiffGrid(new_cell)) - EnsureGridLoadedAtEnter(new_cell, player); - - NGridType* newGrid = getNGrid(new_cell.GridX(), new_cell.GridY()); - AddToGrid(player, newGrid,new_cell); - } - - player->UpdateObjectVisibility(false); -} - -void -Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang) -{ - assert(CheckGridIntegrity(creature,false)); - - Cell old_cell = creature->GetCurrentCell(); - - CellPair new_val = Trinity::ComputeCellPair(x, y); - Cell new_cell(new_val); - - // delay creature move for grid/cell to grid/cell moves - if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell)) - { - #ifdef TRINITY_DEBUG - if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) - sLog.outDebug("Creature (GUID: %u Entry: %u) added to moving list from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", creature->GetGUIDLow(), creature->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); - #endif - AddCreatureToMoveList(creature, x, y, z, ang); - // in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList - } - else - { - creature->Relocate(x, y, z, ang); - creature->UpdateObjectVisibility(false); - } - - assert(CheckGridIntegrity(creature,true)); -} - -void Map::AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang) -{ - if (!c) - return; - - i_creaturesToMove[c] = CreatureMover(x, y, z, ang); -} - -void Map::MoveAllCreaturesInMoveList() -{ - while (!i_creaturesToMove.empty()) - { - // get data and remove element; - CreatureMoveList::iterator iter = i_creaturesToMove.begin(); - Creature* c = iter->first; - CreatureMover cm = iter->second; - i_creaturesToMove.erase(iter); - - // calculate cells - CellPair new_val = Trinity::ComputeCellPair(cm.x, cm.y); - Cell new_cell(new_val); - - // do move or do move to respawn or remove creature if previous all fail - if (CreatureCellRelocation(c,new_cell)) - { - // update pos - c->Relocate(cm.x, cm.y, cm.z, cm.ang); - //CreatureRelocationNotify(c,new_cell,new_cell.cellPair()); - c->UpdateObjectVisibility(false); - } - else - { - // if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid - // creature coordinates will be updated and notifiers send - if (!CreatureRespawnRelocation(c)) - { - // ... or unload (if respawn grid also not loaded) - #ifdef TRINITY_DEBUG - if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) - sLog.outDebug("Creature (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.",c->GetGUIDLow(),c->GetEntry()); - #endif - AddObjectToRemoveList(c); - } - } - } -} - -bool Map::CreatureCellRelocation(Creature *c, Cell new_cell) -{ - Cell const& old_cell = c->GetCurrentCell(); - if (!old_cell.DiffGrid(new_cell)) // in same grid - { - // if in same cell then none do - if (old_cell.DiffCell(new_cell)) - { - #ifdef TRINITY_DEBUG - if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) - sLog.outDebug("Creature (GUID: %u Entry: %u) moved in grid[%u,%u] from cell[%u,%u] to cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY()); - #endif - - RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); - AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); - } - else - { - #ifdef TRINITY_DEBUG - if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) - sLog.outDebug("Creature (GUID: %u Entry: %u) moved in same grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY()); - #endif - } - - return true; - } - - // in diff. grids but active creature - if (c->isActiveObject()) - { - EnsureGridLoadedAtEnter(new_cell); - - #ifdef TRINITY_DEBUG - if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) - sLog.outDebug("Active creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); - #endif - - RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); - AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); - - return true; - } - - // in diff. loaded grid normal creature - if (loaded(GridPair(new_cell.GridX(), new_cell.GridY()))) - { - #ifdef TRINITY_DEBUG - if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) - sLog.outDebug("Creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); - #endif - - RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); - EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY())); - AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); - - return true; - } - - // fail to move: normal creature attempt move to unloaded grid - #ifdef TRINITY_DEBUG - if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) - sLog.outDebug("Creature (GUID: %u Entry: %u) attempted to move from grid[%u,%u]cell[%u,%u] to unloaded grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); - #endif - return false; -} - -bool Map::CreatureRespawnRelocation(Creature *c) -{ - float resp_x, resp_y, resp_z, resp_o; - c->GetRespawnCoord(resp_x, resp_y, resp_z, &resp_o); - - CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y); - Cell resp_cell(resp_val); - - c->CombatStop(); - c->GetMotionMaster()->Clear(); - - #ifdef TRINITY_DEBUG - if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) - sLog.outDebug("Creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to respawn grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), c->GetCurrentCell().GridX(), c->GetCurrentCell().GridY(), c->GetCurrentCell().CellX(), c->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY()); - #endif - - // teleport it to respawn point (like normal respawn if player see) - if (CreatureCellRelocation(c,resp_cell)) - { - c->Relocate(resp_x, resp_y, resp_z, resp_o); - c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators - //CreatureRelocationNotify(c,resp_cell,resp_cell.cellPair()); - c->UpdateObjectVisibility(false); - return true; - } - else - return false; -} - -bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool unloadAll) -{ - NGridType *grid = getNGrid(x, y); - assert(grid != NULL); - - { - if (!unloadAll && ActiveObjectsNearGrid(x, y)) - return false; - - sLog.outDebug("Unloading grid[%u,%u] for map %u", x,y, GetId()); - - ObjectGridUnloader unloader(*grid); - - if (!unloadAll) - { - // Finish creature moves, remove and delete all creatures with delayed remove before moving to respawn grids - // Must know real mob position before move - MoveAllCreaturesInMoveList(); - - // move creatures to respawn grids if this is diff.grid or to remove list - unloader.MoveToRespawnN(); - - // Finish creature moves, remove and delete all creatures with delayed remove before unload - MoveAllCreaturesInMoveList(); - } - - ObjectGridCleaner cleaner(*grid); - cleaner.CleanN(); - - RemoveAllObjectsInRemoveList(); - - unloader.UnloadN(); - - assert(i_objectsToRemove.empty()); - - delete grid; - setNGrid(NULL, x, y); - } - int gx = (MAX_NUMBER_OF_GRIDS - 1) - x; - int gy = (MAX_NUMBER_OF_GRIDS - 1) - y; - - // delete grid map, but don't delete if it is from parent map (and thus only reference) - //+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps - { - if (i_InstanceId == 0) - { - if (GridMaps[gx][gy]) - { - GridMaps[gx][gy]->unloadData(); - delete GridMaps[gx][gy]; - } - // x and y are swapped - VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy); - } - else - ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridPair(gx, gy)); - - GridMaps[gx][gy] = NULL; - } - DEBUG_LOG("Unloading grid[%u,%u] for map %u finished", x,y, GetId()); - return true; -} - -void Map::RemoveAllPlayers() -{ - if (HavePlayers()) - { - for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - { - Player* plr = itr->getSource(); - if (!plr->IsBeingTeleportedFar()) - { - // this is happening for bg - sLog.outError("Map::UnloadAll: player %s is still in map %u during unload, this should not happen!", plr->GetName(), GetId()); - plr->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation()); - } - } - } -} - -void Map::UnloadAll() -{ - // clear all delayed moves, useless anyway do this moves before map unload. - i_creaturesToMove.clear(); - - for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end();) - { - NGridType &grid(*i->getSource()); - ++i; - UnloadGrid(grid.getX(), grid.getY(), true); // deletes the grid and removes it from the GridRefManager - } -} - -//***************************** -// Grid function -//***************************** -GridMap::GridMap() -{ - m_flags = 0; - // Area data - m_gridArea = 0; - m_area_map = NULL; - // Height level data - m_gridHeight = INVALID_HEIGHT; - m_gridGetHeight = &GridMap::getHeightFromFlat; - m_V9 = NULL; - m_V8 = NULL; - // Liquid data - m_liquidType = 0; - m_liquid_offX = 0; - m_liquid_offY = 0; - m_liquid_width = 0; - m_liquid_height = 0; - m_liquidLevel = INVALID_HEIGHT; - m_liquid_type = NULL; - m_liquid_map = NULL; -} - -GridMap::~GridMap() -{ - unloadData(); -} - -bool GridMap::loadData(char *filename) -{ - // Unload old data if exist - unloadData(); - - map_fileheader header; - // Not return error if file not found - FILE *in = fopen(filename, "rb"); - if (!in) - return true; - fread(&header, sizeof(header),1,in); - if (header.mapMagic == uint32(MAP_MAGIC) && - header.versionMagic == uint32(MAP_VERSION_MAGIC)) - { - // loadup area data - if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize)) - { - sLog.outError("Error loading map area data\n"); - fclose(in); - return false; - } - // loadup height data - if (header.heightMapOffset && !loadHeihgtData(in, header.heightMapOffset, header.heightMapSize)) - { - sLog.outError("Error loading map height data\n"); - fclose(in); - return false; - } - // loadup liquid data - if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize)) - { - sLog.outError("Error loading map liquids data\n"); - fclose(in); - return false; - } - fclose(in); - return true; - } - sLog.outError("Map file '%s' is a non-compatible version (outdated?). Please, create new using the ad.exe program.", filename); - fclose(in); - return false; -} - -void GridMap::unloadData() -{ - if (m_area_map) delete[] m_area_map; - if (m_V9) delete[] m_V9; - if (m_V8) delete[] m_V8; - if (m_liquid_type) delete[] m_liquid_type; - if (m_liquid_map) delete[] m_liquid_map; - m_area_map = NULL; - m_V9 = NULL; - m_V8 = NULL; - m_liquid_type = NULL; - m_liquid_map = NULL; - m_gridGetHeight = &GridMap::getHeightFromFlat; -} - -bool GridMap::loadAreaData(FILE *in, uint32 offset, uint32 /*size*/) -{ - map_areaHeader header; - fseek(in, offset, SEEK_SET); - fread(&header, sizeof(header), 1, in); - if (header.fourcc != uint32(MAP_AREA_MAGIC)) - return false; - - m_gridArea = header.gridArea; - if (!(header.flags & MAP_AREA_NO_AREA)) - { - m_area_map = new uint16 [16*16]; - fread(m_area_map, sizeof(uint16), 16*16, in); - } - return true; -} - -bool GridMap::loadHeihgtData(FILE *in, uint32 offset, uint32 /*size*/) -{ - map_heightHeader header; - fseek(in, offset, SEEK_SET); - fread(&header, sizeof(header), 1, in); - if (header.fourcc != uint32(MAP_HEIGHT_MAGIC)) - return false; - - m_gridHeight = header.gridHeight; - if (!(header.flags & MAP_HEIGHT_NO_HEIGHT)) - { - if ((header.flags & MAP_HEIGHT_AS_INT16)) - { - m_uint16_V9 = new uint16 [129*129]; - m_uint16_V8 = new uint16 [128*128]; - fread(m_uint16_V9, sizeof(uint16), 129*129, in); - fread(m_uint16_V8, sizeof(uint16), 128*128, in); - m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; - m_gridGetHeight = &GridMap::getHeightFromUint16; - } - else if ((header.flags & MAP_HEIGHT_AS_INT8)) - { - m_uint8_V9 = new uint8 [129*129]; - m_uint8_V8 = new uint8 [128*128]; - fread(m_uint8_V9, sizeof(uint8), 129*129, in); - fread(m_uint8_V8, sizeof(uint8), 128*128, in); - m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255; - m_gridGetHeight = &GridMap::getHeightFromUint8; - } - else - { - m_V9 = new float [129*129]; - m_V8 = new float [128*128]; - fread(m_V9, sizeof(float), 129*129, in); - fread(m_V8, sizeof(float), 128*128, in); - m_gridGetHeight = &GridMap::getHeightFromFloat; - } - } - else - m_gridGetHeight = &GridMap::getHeightFromFlat; - return true; -} - -bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 /*size*/) -{ - map_liquidHeader header; - fseek(in, offset, SEEK_SET); - fread(&header, sizeof(header), 1, in); - if (header.fourcc != uint32(MAP_LIQUID_MAGIC)) - return false; - - m_liquidType = header.liquidType; - m_liquid_offX = header.offsetX; - m_liquid_offY = header.offsetY; - m_liquid_width = header.width; - m_liquid_height= header.height; - m_liquidLevel = header.liquidLevel; - - if (!(header.flags & MAP_LIQUID_NO_TYPE)) - { - m_liquid_type = new uint8 [16*16]; - fread(m_liquid_type, sizeof(uint8), 16*16, in); - } - if (!(header.flags & MAP_LIQUID_NO_HEIGHT)) - { - m_liquid_map = new float [m_liquid_width*m_liquid_height]; - fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in); - } - return true; -} - -uint16 GridMap::getArea(float x, float y) -{ - if (!m_area_map) - return m_gridArea; - - x = 16 * (32 - x/SIZE_OF_GRIDS); - y = 16 * (32 - y/SIZE_OF_GRIDS); - int lx = (int)x & 15; - int ly = (int)y & 15; - return m_area_map[lx*16 + ly]; -} - -float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const -{ - return m_gridHeight; -} - -float GridMap::getHeightFromFloat(float x, float y) const -{ - if (!m_V8 || !m_V9) - return m_gridHeight; - - x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); - y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); - - int x_int = (int)x; - int y_int = (int)y; - x -= x_int; - y -= y_int; - x_int&=(MAP_RESOLUTION - 1); - y_int&=(MAP_RESOLUTION - 1); - - // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid - // +--------------> X - // | h1-------h2 Coordinates is: - // | | \ 1 / | h1 0,0 - // | | \ / | h2 0,1 - // | | 2 h5 3 | h3 1,0 - // | | / \ | h4 1,1 - // | | / 4 \ | h5 1/2,1/2 - // | h3-------h4 - // V Y - // For find height need - // 1 - detect triangle - // 2 - solve linear equation from triangle points - // Calculate coefficients for solve h = a*x + b*y + c - - float a,b,c; - // Select triangle: - if (x+y < 1) - { - if (x > y) - { - // 1 triangle (h1, h2, h5 points) - float h1 = m_V9[(x_int)*129 + y_int]; - float h2 = m_V9[(x_int+1)*129 + y_int]; - float h5 = 2 * m_V8[x_int*128 + y_int]; - a = h2-h1; - b = h5-h1-h2; - c = h1; - } - else - { - // 2 triangle (h1, h3, h5 points) - float h1 = m_V9[x_int*129 + y_int ]; - float h3 = m_V9[x_int*129 + y_int+1]; - float h5 = 2 * m_V8[x_int*128 + y_int]; - a = h5 - h1 - h3; - b = h3 - h1; - c = h1; - } - } - else - { - if (x > y) - { - // 3 triangle (h2, h4, h5 points) - float h2 = m_V9[(x_int+1)*129 + y_int ]; - float h4 = m_V9[(x_int+1)*129 + y_int+1]; - float h5 = 2 * m_V8[x_int*128 + y_int]; - a = h2 + h4 - h5; - b = h4 - h2; - c = h5 - h4; - } - else - { - // 4 triangle (h3, h4, h5 points) - float h3 = m_V9[(x_int)*129 + y_int+1]; - float h4 = m_V9[(x_int+1)*129 + y_int+1]; - float h5 = 2 * m_V8[x_int*128 + y_int]; - a = h4 - h3; - b = h3 + h4 - h5; - c = h5 - h4; - } - } - // Calculate height - return a * x + b * y + c; -} - -float GridMap::getHeightFromUint8(float x, float y) const -{ - if (!m_uint8_V8 || !m_uint8_V9) - return m_gridHeight; - - x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); - y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); - - int x_int = (int)x; - int y_int = (int)y; - x -= x_int; - y -= y_int; - x_int&=(MAP_RESOLUTION - 1); - y_int&=(MAP_RESOLUTION - 1); - - int32 a, b, c; - uint8 *V9_h1_ptr = &m_uint8_V9[x_int*128 + x_int + y_int]; - if (x+y < 1) - { - if (x > y) - { - // 1 triangle (h1, h2, h5 points) - int32 h1 = V9_h1_ptr[ 0]; - int32 h2 = V9_h1_ptr[129]; - int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; - a = h2-h1; - b = h5-h1-h2; - c = h1; - } - else - { - // 2 triangle (h1, h3, h5 points) - int32 h1 = V9_h1_ptr[0]; - int32 h3 = V9_h1_ptr[1]; - int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; - a = h5 - h1 - h3; - b = h3 - h1; - c = h1; - } - } - else - { - if (x > y) - { - // 3 triangle (h2, h4, h5 points) - int32 h2 = V9_h1_ptr[129]; - int32 h4 = V9_h1_ptr[130]; - int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; - a = h2 + h4 - h5; - b = h4 - h2; - c = h5 - h4; - } - else - { - // 4 triangle (h3, h4, h5 points) - int32 h3 = V9_h1_ptr[ 1]; - int32 h4 = V9_h1_ptr[130]; - int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; - a = h4 - h3; - b = h3 + h4 - h5; - c = h5 - h4; - } - } - // Calculate height - return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; -} - -float GridMap::getHeightFromUint16(float x, float y) const -{ - if (!m_uint16_V8 || !m_uint16_V9) - return m_gridHeight; - - x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); - y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); - - int x_int = (int)x; - int y_int = (int)y; - x -= x_int; - y -= y_int; - x_int&=(MAP_RESOLUTION - 1); - y_int&=(MAP_RESOLUTION - 1); - - int32 a, b, c; - uint16 *V9_h1_ptr = &m_uint16_V9[x_int*128 + x_int + y_int]; - if (x+y < 1) - { - if (x > y) - { - // 1 triangle (h1, h2, h5 points) - int32 h1 = V9_h1_ptr[ 0]; - int32 h2 = V9_h1_ptr[129]; - int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; - a = h2-h1; - b = h5-h1-h2; - c = h1; - } - else - { - // 2 triangle (h1, h3, h5 points) - int32 h1 = V9_h1_ptr[0]; - int32 h3 = V9_h1_ptr[1]; - int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; - a = h5 - h1 - h3; - b = h3 - h1; - c = h1; - } - } - else - { - if (x > y) - { - // 3 triangle (h2, h4, h5 points) - int32 h2 = V9_h1_ptr[129]; - int32 h4 = V9_h1_ptr[130]; - int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; - a = h2 + h4 - h5; - b = h4 - h2; - c = h5 - h4; - } - else - { - // 4 triangle (h3, h4, h5 points) - int32 h3 = V9_h1_ptr[ 1]; - int32 h4 = V9_h1_ptr[130]; - int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; - a = h4 - h3; - b = h3 + h4 - h5; - c = h5 - h4; - } - } - // Calculate height - return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; -} - -float GridMap::getLiquidLevel(float x, float y) -{ - if (!m_liquid_map) - return m_liquidLevel; - - x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); - y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); - - int cx_int = ((int)x & (MAP_RESOLUTION-1)) - m_liquid_offY; - int cy_int = ((int)y & (MAP_RESOLUTION-1)) - m_liquid_offX; - - if (cx_int < 0 || cx_int >=m_liquid_height) - return INVALID_HEIGHT; - if (cy_int < 0 || cy_int >=m_liquid_width) - return INVALID_HEIGHT; - - return m_liquid_map[cx_int*m_liquid_width + cy_int]; -} - -uint8 GridMap::getTerrainType(float x, float y) -{ - if (!m_liquid_type) - return m_liquidType; - - x = 16 * (32 - x/SIZE_OF_GRIDS); - y = 16 * (32 - y/SIZE_OF_GRIDS); - int lx = (int)x & 15; - int ly = (int)y & 15; - return m_liquid_type[lx*16 + ly]; -} - -// Get water state on map -inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) -{ - // Check water type (if no water return) - if (!m_liquid_type && !m_liquidType) - return LIQUID_MAP_NO_WATER; - - // Get cell - float cx = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); - float cy = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); - - int x_int = (int)cx & (MAP_RESOLUTION-1); - int y_int = (int)cy & (MAP_RESOLUTION-1); - - // Check water type in cell - uint8 type = m_liquid_type ? m_liquid_type[(x_int>>3)*16 + (y_int>>3)] : m_liquidType; - if (type == 0) - return LIQUID_MAP_NO_WATER; - - // Check req liquid type mask - if (ReqLiquidType && !(ReqLiquidType&type)) - return LIQUID_MAP_NO_WATER; - - // Check water level: - // Check water height map - int lx_int = x_int - m_liquid_offY; - int ly_int = y_int - m_liquid_offX; - if (lx_int < 0 || lx_int >=m_liquid_height) - return LIQUID_MAP_NO_WATER; - if (ly_int < 0 || ly_int >=m_liquid_width) - return LIQUID_MAP_NO_WATER; - - // Get water level - float liquid_level = m_liquid_map ? m_liquid_map[lx_int*m_liquid_width + ly_int] : m_liquidLevel; - // Get ground level (sub 0.2 for fix some errors) - float ground_level = getHeight(x, y); - - // Check water level and ground level - if (liquid_level < ground_level || z < ground_level - 2) - return LIQUID_MAP_NO_WATER; - - // All ok in water -> store data - if (data) - { - data->type = type; - data->level = liquid_level; - data->depth_level = ground_level; - } - - // For speed check as int values - int delta = int((liquid_level - z) * 10); - - // Get position delta - if (delta > 20) // Under water - return LIQUID_MAP_UNDER_WATER; - if (delta > 0) // In water - return LIQUID_MAP_IN_WATER; - if (delta > -1) // Walk on water - return LIQUID_MAP_WATER_WALK; - // Above water - return LIQUID_MAP_ABOVE_WATER; -} - -inline GridMap *Map::GetGrid(float x, float y) -{ - // half opt method - int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x - int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y - - // ensure GridMap is loaded - EnsureGridCreated(GridPair(63-gx,63-gy)); - - return GridMaps[gx][gy]; -} - -float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const -{ - // find raw .map surface under Z coordinates - float mapHeight; - if (GridMap *gmap = const_cast(this)->GetGrid(x, y)) - { - float _mapheight = gmap->getHeight(x,y); - - // look from a bit higher pos to find the floor, ignore under surface case - if (z + 2.0f > _mapheight) - mapHeight = _mapheight; - else - mapHeight = VMAP_INVALID_HEIGHT_VALUE; - } - else - mapHeight = VMAP_INVALID_HEIGHT_VALUE; - - float vmapHeight; - if (pUseVmaps) - { - VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - if (vmgr->isHeightCalcEnabled()) - { - // look from a bit higher pos to find the floor - vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f); - } - else - vmapHeight = VMAP_INVALID_HEIGHT_VALUE; - } - else - vmapHeight = VMAP_INVALID_HEIGHT_VALUE; - - // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT - // vmapheight set for any under Z value or <= INVALID_HEIGHT - - if (vmapHeight > INVALID_HEIGHT) - { - if (mapHeight > INVALID_HEIGHT) - { - // we have mapheight and vmapheight and must select more appropriate - - // we are already under the surface or vmap height above map heigt - // or if the distance of the vmap height is less the land height distance - if (z < mapHeight || vmapHeight > mapHeight || fabs(mapHeight-z) > fabs(vmapHeight-z)) - return vmapHeight; - else - return mapHeight; // better use .map surface height - - } - else - return vmapHeight; // we have only vmapHeight (if have) - } - else - { - if (!pUseVmaps) - return mapHeight; // explicitly use map data (if have) - else if (mapHeight > INVALID_HEIGHT && (z < mapHeight + 2 || z == MAX_HEIGHT)) - return mapHeight; // explicitly use map data if original z < mapHeight but map found (z+2 > mapHeight) - else - return VMAP_INVALID_HEIGHT_VALUE; // we not have any height - } -} - -inline bool IsOutdoorWMO(uint32 mogpFlags, int32 adtId, int32 rootId, int32 groupId, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry) -{ - bool outdoor = true; - - if(wmoEntry && atEntry) - { - if(atEntry->flags & AREA_FLAG_OUTSIDE) - return true; - if(atEntry->flags & AREA_FLAG_INSIDE) - return false; - } - - outdoor = mogpFlags&0x8; - - if(wmoEntry) - { - if(wmoEntry->Flags & 4) - return true; - if((wmoEntry->Flags & 2)!=0) - outdoor = false; - } - return outdoor; -} - -bool Map::IsOutdoors(float x, float y, float z) const -{ - uint32 mogpFlags; - int32 adtId, rootId, groupId; - - // no wmo found? -> outside by default - if(!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) - return true; - - AreaTableEntry const* atEntry = 0; - WMOAreaTableEntry const* wmoEntry= GetWMOAreaTableEntryByTripple(rootId, adtId, groupId); - if(wmoEntry) - { - DEBUG_LOG("Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->areaId); - atEntry = GetAreaEntryByAreaID(wmoEntry->areaId); - } - return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry); -} - -bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const -{ - float vmap_z = z; - VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - if (vmgr->getAreaInfo(GetId(), x, y, vmap_z, flags, adtId, rootId, groupId)) - { - // check if there's terrain between player height and object height - if(GridMap *gmap = const_cast(this)->GetGrid(x, y)) - { - float _mapheight = gmap->getHeight(x,y); - // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice... - if(z + 2.0f > _mapheight && _mapheight > vmap_z) - return false; - } - return true; - } - return false; -} - -uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const -{ - uint32 mogpFlags; - int32 adtId, rootId, groupId; - WMOAreaTableEntry const* wmoEntry = 0; - AreaTableEntry const* atEntry = 0; - bool haveAreaInfo = false; - - if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) - { - haveAreaInfo = true; - if (wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId)) - atEntry = GetAreaEntryByAreaID(wmoEntry->areaId); - } - - uint16 areaflag; - - if (atEntry) - areaflag = atEntry->exploreFlag; - else - { - if (GridMap *gmap = const_cast(this)->GetGrid(x, y)) - areaflag = gmap->getArea(x, y); - // this used while not all *.map files generated (instances) - else - areaflag = GetAreaFlagByMapId(i_mapEntry->MapID); - } - - if (isOutdoors) - { - if (haveAreaInfo) - *isOutdoors = IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry); - else - *isOutdoors = true; - } - return areaflag; - } - -uint8 Map::GetTerrainType(float x, float y) const -{ - if (GridMap *gmap = const_cast(this)->GetGrid(x, y)) - return gmap->getTerrainType(x, y); - else - return 0; -} - -ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) const -{ - ZLiquidStatus result = LIQUID_MAP_NO_WATER; - VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - float liquid_level, ground_level = INVALID_HEIGHT; - uint32 liquid_type; - if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) - { - sLog.outDebug("getLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type); - // Check water level and ground level - if (liquid_level > ground_level && z > ground_level - 2) - { - // All ok in water -> store data - if (data) - { - data->type = liquid_type; - data->level = liquid_level; - data->depth_level = ground_level; - } - - // For speed check as int values - int delta = int((liquid_level - z) * 10); - - // Get position delta - if (delta > 20) // Under water - return LIQUID_MAP_UNDER_WATER; - if (delta > 0 ) // In water - return LIQUID_MAP_IN_WATER; - if (delta > -1) // Walk on water - return LIQUID_MAP_WATER_WALK; - result = LIQUID_MAP_ABOVE_WATER; - } - } - - if(GridMap* gmap = const_cast(this)->GetGrid(x, y)) - { - LiquidData map_data; - ZLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data); - // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER: - if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level)) - { - if (data) - *data = map_data; - return map_result; - } - } - return result; -} - -float Map::GetWaterLevel(float x, float y) const -{ - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) - return gmap->getLiquidLevel(x, y); - else - return 0; -} - -uint32 Map::GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id) -{ - AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); - - if (entry) - return entry->ID; - else - return 0; -} - -uint32 Map::GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id) -{ - AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); - - if (entry) - return (entry->zone != 0) ? entry->zone : entry->ID; - else - return 0; -} - -void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id) -{ - AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); - - areaid = entry ? entry->ID : 0; - zoneid = entry ? ((entry->zone != 0) ? entry->zone : entry->ID) : 0; -} - -bool Map::IsInWater(float x, float y, float pZ, LiquidData *data) const -{ - // Check surface in x, y point for liquid - if (const_cast(this)->GetGrid(x, y)) - { - LiquidData liquid_status; - LiquidData *liquid_ptr = data ? data : &liquid_status; - if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr)) - return true; - } - return false; -} - -bool Map::IsUnderWater(float x, float y, float z) const -{ - if (const_cast(this)->GetGrid(x, y)) - { - if (getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN)&LIQUID_MAP_UNDER_WATER) - return true; - } - return false; -} - -bool Map::CheckGridIntegrity(Creature* c, bool moved) const -{ - Cell const& cur_cell = c->GetCurrentCell(); - - CellPair xy_val = Trinity::ComputeCellPair(c->GetPositionX(), c->GetPositionY()); - Cell xy_cell(xy_val); - if (xy_cell != cur_cell) - { - sLog.outDebug("Creature (GUID: %u) X: %f Y: %f (%s) is in grid[%u,%u]cell[%u,%u] instead of grid[%u,%u]cell[%u,%u]", - c->GetGUIDLow(), - c->GetPositionX(),c->GetPositionY(),(moved ? "final" : "original"), - cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(), - xy_cell.GridX(), xy_cell.GridY(), xy_cell.CellX(), xy_cell.CellY()); - return true; // not crash at error, just output error in debug mode - } - - return true; -} - -const char* Map::GetMapName() const -{ - return i_mapEntry ? i_mapEntry->name[sWorld.GetDefaultDbcLocale()] : "UNNAMEDMAP\x0"; -} - -void Map::UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair) -{ - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - Trinity::VisibleChangesNotifier notifier(*obj); - TypeContainerVisitor player_notifier(notifier); - cell.Visit(cellpair, player_notifier, *this, *obj, GetVisibilityDistance()); -} - -void Map::UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair) -{ - Trinity::VisibleNotifier notifier(*player); - - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - TypeContainerVisitor world_notifier(notifier); - TypeContainerVisitor grid_notifier(notifier); - cell.Visit(cellpair, world_notifier, *this, *player, GetVisibilityDistance()); - cell.Visit(cellpair, grid_notifier, *this, *player, GetVisibilityDistance()); - - // send data - notifier.SendToSelf(); -} -/* -void Map::PlayerRelocationNotify(Player* player, Cell cell, CellPair cellpair) -{ - Trinity::PlayerRelocationNotifier relocationNotifier(*player); - cell.data.Part.reserved = ALL_DISTRICT; - - TypeContainerVisitor p2grid_relocation(relocationNotifier); - TypeContainerVisitor p2world_relocation(relocationNotifier); - - cell.Visit(cellpair, p2grid_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS); - cell.Visit(cellpair, p2world_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS); -} - -void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellpair) -{ - Trinity::CreatureRelocationNotifier relocationNotifier(*creature); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); // not trigger load unloaded grids at notifier call - - TypeContainerVisitor c2world_relocation(relocationNotifier); - TypeContainerVisitor c2grid_relocation(relocationNotifier); - - cell.Visit(cellpair, c2world_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS); - cell.Visit(cellpair, c2grid_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS); -} -*/ - -void Map::SendInitSelf(Player * player) -{ - sLog.outDetail("Creating player data for himself %u", player->GetGUIDLow()); - - UpdateData data; - - // attach to player data current transport data - if (Transport* transport = player->GetTransport()) - { - transport->BuildCreateUpdateBlockForPlayer(&data, player); - } - - // build data for self presence in world at own client (one time for map) - player->BuildCreateUpdateBlockForPlayer(&data, player); - - // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map - if (Transport* transport = player->GetTransport()) - { - for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) - { - if (player != (*itr) && player->HaveAtClient(*itr)) - { - (*itr)->BuildCreateUpdateBlockForPlayer(&data, player); - } - } - } - - WorldPacket packet; - data.BuildPacket(&packet); - player->GetSession()->SendPacket(&packet); -} - -void Map::SendInitTransports(Player * player) -{ - // Hack to send out transports - MapManager::TransportMap& tmap = MapManager::Instance().m_TransportsByMap; - - // no transports at map - if (tmap.find(player->GetMapId()) == tmap.end()) - return; - - UpdateData transData; - - MapManager::TransportSet& tset = tmap[player->GetMapId()]; - - for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i) - { - // send data for current transport in other place - if ((*i) != player->GetTransport() && (*i)->GetMapId() == GetId()) - { - (*i)->BuildCreateUpdateBlockForPlayer(&transData, player); - } - } - - WorldPacket packet; - transData.BuildPacket(&packet); - player->GetSession()->SendPacket(&packet); -} - -void Map::SendRemoveTransports(Player * player) -{ - // Hack to send out transports - MapManager::TransportMap& tmap = MapManager::Instance().m_TransportsByMap; - - // no transports at map - if (tmap.find(player->GetMapId()) == tmap.end()) - return; - - UpdateData transData; - - MapManager::TransportSet& tset = tmap[player->GetMapId()]; - - // except used transport - for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i) - if ((*i) != player->GetTransport() && (*i)->GetMapId() != GetId()) - (*i)->BuildOutOfRangeUpdateBlock(&transData); - - WorldPacket packet; - transData.BuildPacket(&packet); - player->GetSession()->SendPacket(&packet); -} - -inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y) -{ - if (x >= MAX_NUMBER_OF_GRIDS || y >= MAX_NUMBER_OF_GRIDS) - { - sLog.outError("map::setNGrid() Invalid grid coordinates found: %d, %d!",x,y); - assert(false); - } - i_grids[x][y] = grid; -} - -void Map::DelayedUpdate(const uint32 t_diff) -{ - RemoveAllObjectsInRemoveList(); - - // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! - // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended - if (!IsBattleGroundOrArena()) - { - for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end();) - { - NGridType *grid = i->getSource(); - GridInfo *info = i->getSource()->getGridInfoRef(); - ++i; // The update might delete the map and we need the next map before the iterator gets invalid - assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE); - si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff); - } - } -} - -void Map::AddObjectToRemoveList(WorldObject *obj) -{ - assert(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId()); - - obj->CleanupsBeforeDelete(false); // remove or simplify at least cross referenced links - - i_objectsToRemove.insert(obj); - //sLog.outDebug("Object (GUID: %u TypeId: %u) added to removing list.",obj->GetGUIDLow(),obj->GetTypeId()); -} - -void Map::AddObjectToSwitchList(WorldObject *obj, bool on) -{ - assert(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId()); - - std::map::iterator itr = i_objectsToSwitch.find(obj); - if (itr == i_objectsToSwitch.end()) - i_objectsToSwitch.insert(itr, std::make_pair(obj, on)); - else if (itr->second != on) - i_objectsToSwitch.erase(itr); - else - assert(false); -} - -void Map::RemoveAllObjectsInRemoveList() -{ - while (!i_objectsToSwitch.empty()) - { - std::map::iterator itr = i_objectsToSwitch.begin(); - WorldObject *obj = itr->first; - bool on = itr->second; - i_objectsToSwitch.erase(itr); - - switch(obj->GetTypeId()) - { - case TYPEID_UNIT: - if (!obj->ToCreature()->isPet()) - SwitchGridContainers(obj->ToCreature(), on); - break; - } - } - - //sLog.outDebug("Object remover 1 check."); - while (!i_objectsToRemove.empty()) - { - std::set::iterator itr = i_objectsToRemove.begin(); - WorldObject* obj = *itr; - - switch(obj->GetTypeId()) - { - case TYPEID_CORPSE: - { - Corpse* corpse = ObjectAccessor::Instance().GetCorpse(*obj, obj->GetGUID()); - if (!corpse) - sLog.outError("Tried to delete corpse/bones %u that is not in map.", obj->GetGUIDLow()); - else - Remove(corpse,true); - break; - } - case TYPEID_DYNAMICOBJECT: - Remove((DynamicObject*)obj,true); - break; - case TYPEID_GAMEOBJECT: - Remove((GameObject*)obj,true); - break; - case TYPEID_UNIT: - // in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call - // make sure that like sources auras/etc removed before destructor start - obj->ToCreature()->CleanupsBeforeDelete(); - Remove(obj->ToCreature(),true); - break; - default: - sLog.outError("Non-grid object (TypeId: %u) is in grid object remove list, ignored.",obj->GetTypeId()); - break; - } - - i_objectsToRemove.erase(itr); - } - - //sLog.outDebug("Object remover 2 check."); -} - -uint32 Map::GetPlayersCountExceptGMs() const -{ - uint32 count = 0; - for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - if (!itr->getSource()->isGameMaster()) - ++count; - return count; -} - -void Map::SendToPlayers(WorldPacket const* data) const -{ - for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - itr->getSource()->GetSession()->SendPacket(data); -} - -bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const -{ - ASSERT(x < MAX_NUMBER_OF_GRIDS); - ASSERT(y < MAX_NUMBER_OF_GRIDS); - - CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS); - CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); - - //we must find visible range in cells so we unload only non-visible cells... - float viewDist = GetVisibilityDistance(); - int cell_range = (int)ceilf(viewDist / SIZE_OF_GRID_CELL) + 1; - - cell_min << cell_range; - cell_min -= cell_range; - cell_max >> cell_range; - cell_max += cell_range; - - for (MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter) - { - Player* plr = iter->getSource(); - - CellPair p = Trinity::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY()); - if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && - (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord)) - return true; - } - - for (ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter) - { - WorldObject* obj = *iter; - - CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && - (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord)) - return true; - } - - return false; -} - -void Map::AddToActive(Creature* c) -{ - AddToActiveHelper(c); - - // also not allow unloading spawn grid to prevent creating creature clone at load - if (!c->isPet() && c->GetDBTableGUIDLow()) - { - float x,y,z; - c->GetRespawnCoord(x,y,z); - GridPair p = Trinity::ComputeGridPair(x, y); - if (getNGrid(p.x_coord, p.y_coord)) - getNGrid(p.x_coord, p.y_coord)->incUnloadActiveLock(); - else - { - GridPair p2 = Trinity::ComputeGridPair(c->GetPositionX(), c->GetPositionY()); - sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] was not loaded.", - c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord); - } - } -} - -void Map::RemoveFromActive(Creature* c) -{ - RemoveFromActiveHelper(c); - - // also allow unloading spawn grid - if (!c->isPet() && c->GetDBTableGUIDLow()) - { - float x,y,z; - c->GetRespawnCoord(x,y,z); - GridPair p = Trinity::ComputeGridPair(x, y); - if (getNGrid(p.x_coord, p.y_coord)) - getNGrid(p.x_coord, p.y_coord)->decUnloadActiveLock(); - else - { - GridPair p2 = Trinity::ComputeGridPair(c->GetPositionX(), c->GetPositionY()); - sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] was not loaded.", - c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord); - } - } -} - -template void Map::Add(Corpse *); -template void Map::Add(Creature *); -template void Map::Add(GameObject *); -template void Map::Add(DynamicObject *); - -template void Map::Remove(Corpse *,bool); -template void Map::Remove(Creature *,bool); -template void Map::Remove(GameObject *, bool); -template void Map::Remove(DynamicObject *, bool); - -/* ******* Dungeon Instance Maps ******* */ - -InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent) - : Map(id, expiry, InstanceId, SpawnMode, _parent), - m_resetAfterUnload(false), m_unloadWhenEmpty(false), - i_data(NULL), i_script_id(0) -{ - //lets initialize visibility distance for dungeons - InstanceMap::InitVisibilityDistance(); - - // the timer is started by default, and stopped when the first player joins - // this make sure it gets unloaded if for some reason no player joins - m_unloadTimer = std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY); -} - -InstanceMap::~InstanceMap() -{ - if (i_data) - { - delete i_data; - i_data = NULL; - } -} - -void InstanceMap::InitVisibilityDistance() -{ - //init visibility distance for instances - m_VisibleDistance = World::GetMaxVisibleDistanceInInstances(); - m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInInstances(); -} - -/* - Do map specific checks to see if the player can enter -*/ -bool InstanceMap::CanEnter(Player *player) -{ - if (player->GetMapRef().getTarget() == this) - { - sLog.outError("InstanceMap::CanEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode()); - assert(false); - return false; - } - - // allow GM's to enter - if (player->isGameMaster()) - return Map::CanEnter(player); - - // cannot enter if the instance is full (player cap), GMs don't count - uint32 maxPlayers = GetMaxPlayers(); - if (GetPlayersCountExceptGMs() >= maxPlayers) - { - sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName()); - player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); - return false; - } - - // cannot enter while an encounter is in progress on raids - /*Group *pGroup = player->GetGroup(); - if (!player->isGameMaster() && pGroup && pGroup->InCombatToInstance(GetInstanceId()) && player->GetMapId() != GetId())*/ - if (IsRaid() && GetInstanceData() && GetInstanceData()->IsEncounterInProgress()) - { - player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); - return false; - } - - return Map::CanEnter(player); -} - -/* - Do map specific checks and add the player to the map if successful. -*/ -bool InstanceMap::Add(Player *player) -{ - // TODO: Not sure about checking player level: already done in HandleAreaTriggerOpcode - // GMs still can teleport player in instance. - // Is it needed? - - { - Guard guard(*this); - // Check moved to void WorldSession::HandleMoveWorldportAckOpcode() - //if (!CanEnter(player)) - //return false; - - // Dungeon only code - if (IsDungeon()) - { - // get or create an instance save for the map - InstanceSave *mapSave = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); - if (!mapSave) - { - sLog.outDetail("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId()); - mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true); - } - - // check for existing instance binds - InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), Difficulty(GetSpawnMode())); - if (playerBind && playerBind->perm) - { - // cannot enter other instances if bound permanently - if (playerBind->save != mapSave) - { - sLog.outError("InstanceMap::Add: player %s(%d) is permanently bound to instance %d,%d,%d,%d,%d,%d but he is being put into instance %d,%d,%d,%d,%d,%d", player->GetName(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); - return false; - } - } - else - { - Group *pGroup = player->GetGroup(); - if (pGroup) - { - // solo saves should be reset when entering a group - InstanceGroupBind *groupBind = pGroup->GetBoundInstance(this); - if (playerBind) - { - sLog.outError("InstanceMap::Add: player %s(%d) is being put into instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); - if (groupBind) sLog.outError("InstanceMap::Add: the group is bound to the instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); - //assert(false); - return false; - } - // bind to the group or keep using the group save - if (!groupBind) - pGroup->BindToInstance(mapSave, false); - else - { - // cannot jump to a different instance without resetting it - if (groupBind->save != mapSave) - { - sLog.outError("InstanceMap::Add: player %s(%d) is being put into instance %d,%d,%d but he is in group %d which is bound to instance %d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(pGroup->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); - if (mapSave) - sLog.outError("MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); - else - sLog.outError("MapSave NULL"); - if (groupBind->save) - sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount()); - else - sLog.outError("GroupBind save NULL"); - return false; - } - // if the group/leader is permanently bound to the instance - // players also become permanently bound when they enter - if (groupBind->perm) - { - WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); - data << uint32(0); - player->GetSession()->SendPacket(&data); - player->BindToInstance(mapSave, true); - } - } - } - else - { - // set up a solo bind or continue using it - if (!playerBind) - player->BindToInstance(mapSave, false); - else - // cannot jump to a different instance without resetting it - assert(playerBind->save == mapSave); - } - } - } - - // for normal instances cancel the reset schedule when the - // first player enters (no players yet) - SetResetSchedule(false); - - sLog.outDetail("MAP: Player '%s' entered instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName()); - // initialize unload state - m_unloadTimer = 0; - m_resetAfterUnload = false; - m_unloadWhenEmpty = false; - } - - // this will acquire the same mutex so it cannot be in the previous block - Map::Add(player); - - if (i_data) - i_data->OnPlayerEnter(player); - - return true; -} - -void InstanceMap::Update(const uint32& t_diff) -{ - Map::Update(t_diff); - - if (i_data) - i_data->Update(t_diff); -} - -void InstanceMap::Remove(Player *player, bool remove) -{ - sLog.outDetail("MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName()); - //if last player set unload timer - if (!m_unloadTimer && m_mapRefManager.getSize() == 1) - m_unloadTimer = m_unloadWhenEmpty ? MIN_UNLOAD_DELAY : std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY); - Map::Remove(player, remove); - // for normal instances schedule the reset after all players have left - SetResetSchedule(true); -} - -void InstanceMap::CreateInstanceData(bool load) -{ - if (i_data != NULL) - return; - - InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(GetId()); - if (mInstance) - { - i_script_id = mInstance->script_id; - i_data = sScriptMgr.CreateInstanceData(this); - } - - if (!i_data) - return; - - i_data->Initialize(); - - if (load) - { - // TODO: make a global storage for this - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT data FROM instance WHERE map = '%u' AND id = '%u'", GetId(), i_InstanceId); - if (result) - { - Field* fields = result->Fetch(); - std::string data = fields[0].GetString(); - if (data != "") - { - sLog.outDebug("Loading instance data for `%s` with id %u", objmgr.GetScriptName(i_script_id), i_InstanceId); - i_data->Load(data.c_str()); - } - } - } -} - -/* - Returns true if there are no players in the instance -*/ -bool InstanceMap::Reset(uint8 method) -{ - // note: since the map may not be loaded when the instance needs to be reset - // the instance must be deleted from the DB by InstanceSaveManager - - if (HavePlayers()) - { - if (method == INSTANCE_RESET_ALL) - { - // notify the players to leave the instance so it can be reset - for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - itr->getSource()->SendResetFailedNotify(GetId()); - } - else - { - if (method == INSTANCE_RESET_GLOBAL) - // set the homebind timer for players inside (1 minute) - for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - itr->getSource()->m_InstanceValid = false; - - // the unload timer is not started - // instead the map will unload immediately after the players have left - m_unloadWhenEmpty = true; - m_resetAfterUnload = true; - } - } - else - { - // unloaded at next update - m_unloadTimer = MIN_UNLOAD_DELAY; - m_resetAfterUnload = true; - } - - return m_mapRefManager.isEmpty(); -} - -void InstanceMap::PermBindAllPlayers(Player *player) -{ - if (!IsDungeon()) - return; - - InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); - if (!save) - { - sLog.outError("Cannot bind players, no instance save available for map!"); - return; - } - - Group *group = player->GetGroup(); - // group members outside the instance group don't get bound - for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - { - Player* plr = itr->getSource(); - // players inside an instance cannot be bound to other instances - // some players may already be permanently bound, in this case nothing happens - InstancePlayerBind *bind = plr->GetBoundInstance(save->GetMapId(), save->GetDifficulty()); - if (!bind || !bind->perm) - { - plr->BindToInstance(save, true); - WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); - data << uint32(0); - plr->GetSession()->SendPacket(&data); - } - - // if the leader is not in the instance the group will not get a perm bind - if (group && group->GetLeaderGUID() == plr->GetGUID()) - group->BindToInstance(save, true); - } -} - -void InstanceMap::UnloadAll() -{ - assert(!HavePlayers()); - - if (m_resetAfterUnload == true) - objmgr.DeleteRespawnTimeForInstance(GetInstanceId()); - - Map::UnloadAll(); -} - -void InstanceMap::SendResetWarnings(uint32 timeLeft) const -{ - for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - itr->getSource()->SendInstanceResetWarning(GetId(), itr->getSource()->GetDifficulty(IsRaid()), timeLeft); -} - -void InstanceMap::SetResetSchedule(bool on) -{ - // only for normal instances - // the reset time is only scheduled when there are no payers inside - // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled - if (IsDungeon() && !HavePlayers() && !IsRaidOrHeroicDungeon()) - { - InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); - if (!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId()); - else sInstanceSaveManager.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), Difficulty(GetSpawnMode()), GetInstanceId())); - } -} - -MapDifficulty const* Map::GetMapDifficulty() const -{ - return GetMapDifficultyData(GetId(),GetDifficulty()); -} - -uint32 InstanceMap::GetMaxPlayers() const -{ - if (MapDifficulty const* mapDiff = GetMapDifficulty()) - { - if (mapDiff->maxPlayers || IsRegularDifficulty()) // Normal case (expect that regular difficulty always have correct maxplayers) - return mapDiff->maxPlayers; - else // DBC have 0 maxplayers for heroic instances with expansion < 2 - { // The heroic entry exists, so we don't have to check anything, simply return normal max players - MapDifficulty const* normalDiff = GetMapDifficultyData(GetId(), REGULAR_DIFFICULTY); - return normalDiff ? normalDiff->maxPlayers : 0; - } - } - else // I'd rather assert(false); - return 0; -} - -uint32 InstanceMap::GetMaxResetDelay() const -{ - MapDifficulty const* mapDiff = GetMapDifficulty(); - return mapDiff ? mapDiff->resetTime : 0; -} - -/* ******* Battleground Instance Maps ******* */ - -BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent, uint8 spawnMode) - : Map(id, expiry, InstanceId, spawnMode, _parent) -{ - //lets initialize visibility distance for BG/Arenas - BattleGroundMap::InitVisibilityDistance(); -} - -BattleGroundMap::~BattleGroundMap() -{ -} - -void BattleGroundMap::InitVisibilityDistance() -{ - //init visibility distance for BG/Arenas - m_VisibleDistance = World::GetMaxVisibleDistanceInBGArenas(); - m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInBGArenas(); -} - -bool BattleGroundMap::CanEnter(Player * player) -{ - if (player->GetMapRef().getTarget() == this) - { - sLog.outError("BGMap::CanEnter - player %u is already in map!", player->GetGUIDLow()); - assert(false); - return false; - } - - if (player->GetBattleGroundId() != GetInstanceId()) - return false; - - // player number limit is checked in bgmgr, no need to do it here - - return Map::CanEnter(player); -} - -bool BattleGroundMap::Add(Player * player) -{ - { - Guard guard(*this); - //Check moved to void WorldSession::HandleMoveWorldportAckOpcode() - //if (!CanEnter(player)) - //return false; - // reset instance validity, battleground maps do not homebind - player->m_InstanceValid = true; - } - return Map::Add(player); -} - -void BattleGroundMap::Remove(Player *player, bool remove) -{ - sLog.outDetail("MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName()); - Map::Remove(player, remove); -} - -void BattleGroundMap::SetUnload() -{ - m_unloadTimer = MIN_UNLOAD_DELAY; -} - -void BattleGroundMap::RemoveAllPlayers() -{ - if (HavePlayers()) - for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - if (Player* plr = itr->getSource()) - if (!plr->IsBeingTeleportedFar()) - plr->TeleportTo(plr->GetBattleGroundEntryPoint()); - -} - -/// Put scripts in the execution queue -void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target) -{ - ///- Find the script map - ScriptMapMap::const_iterator s = scripts.find(id); - if (s == scripts.end()) - return; - - // prepare static data - uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source - uint64 targetGUID = target ? target->GetGUID() : (uint64)0; - uint64 ownerGUID = (source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; - - ///- Schedule script execution for all scripts in the script map - ScriptMap const *s2 = &(s->second); - bool immedScript = false; - for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter) - { - ScriptAction sa; - sa.sourceGUID = sourceGUID; - sa.targetGUID = targetGUID; - sa.ownerGUID = ownerGUID; - - sa.script = &iter->second; - m_scriptSchedule.insert(std::pair(time_t(sWorld.GetGameTime() + iter->first), sa)); - if (iter->first == 0) - immedScript = true; - - sWorld.IncreaseScheduledScriptsCount(); - } - ///- If one of the effects should be immediate, launch the script execution - if (/*start &&*/ immedScript && !i_scriptLock) - { - i_scriptLock = true; - ScriptsProcess(); - i_scriptLock = false; - } -} - -void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target) -{ - // NOTE: script record _must_ exist until command executed - - // prepare static data - uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; - uint64 targetGUID = target ? target->GetGUID() : (uint64)0; - uint64 ownerGUID = (source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; - - ScriptAction sa; - sa.sourceGUID = sourceGUID; - sa.targetGUID = targetGUID; - sa.ownerGUID = ownerGUID; - - sa.script = &script; - m_scriptSchedule.insert(std::pair(time_t(sWorld.GetGameTime() + delay), sa)); - - sWorld.IncreaseScheduledScriptsCount(); - - ///- If effects should be immediate, launch the script execution - if (delay == 0 && !i_scriptLock) - { - i_scriptLock = true; - ScriptsProcess(); - i_scriptLock = false; - } -} - -/// Process queued scripts -void Map::ScriptsProcess() -{ - if (m_scriptSchedule.empty()) - return; - - ///- Process overdue queued scripts - std::multimap::iterator iter = m_scriptSchedule.begin(); - // ok as multimap is a *sorted* associative container - while (!m_scriptSchedule.empty() && (iter->first <= sWorld.GetGameTime())) - { - ScriptAction const& step = iter->second; - - Object* source = NULL; - - if (step.sourceGUID) - { - switch (GUID_HIPART(step.sourceGUID)) - { - case HIGHGUID_ITEM: - // case HIGHGUID_CONTAINER: == HIGHGUID_ITEM - { - Player* player = HashMapHolder::Find(step.ownerGUID); - if (player) - source = player->GetItemByGuid(step.sourceGUID); - break; - } - case HIGHGUID_UNIT: - source = HashMapHolder::Find(step.sourceGUID); - break; - case HIGHGUID_PET: - source = HashMapHolder::Find(step.sourceGUID); - break; - //case HIGHGUID_VEHICLE: - // source = HashMapHolder::Find(step.sourceGUID); - // break; - case HIGHGUID_PLAYER: - source = HashMapHolder::Find(step.sourceGUID); - break; - case HIGHGUID_GAMEOBJECT: - source = HashMapHolder::Find(step.sourceGUID); - break; - case HIGHGUID_CORPSE: - source = HashMapHolder::Find(step.sourceGUID); - break; - case HIGHGUID_MO_TRANSPORT: - for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) - { - if ((*iter)->GetGUID() == step.sourceGUID) - { - source = reinterpret_cast(*iter); - break; - } - } - break; - default: - sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID)); - break; - } - } - - //if (source && !source->IsInWorld()) source = NULL; - - Object* target = NULL; - - if (step.targetGUID) - { - switch (GUID_HIPART(step.targetGUID)) - { - case HIGHGUID_UNIT: - target = HashMapHolder::Find(step.targetGUID); - break; - case HIGHGUID_PET: - target = HashMapHolder::Find(step.targetGUID); - break; - //case HIGHGUID_VEHICLE: - // target = HashMapHolder::Find(step.targetGUID); - // break; - case HIGHGUID_PLAYER: // empty GUID case also - target = HashMapHolder::Find(step.targetGUID); - break; - case HIGHGUID_GAMEOBJECT: - target = HashMapHolder::Find(step.targetGUID); - break; - case HIGHGUID_CORPSE: - target = HashMapHolder::Find(step.targetGUID); - break; - default: - sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID)); - break; - } - } - - //if (target && !target->IsInWorld()) target = NULL; - - switch (step.script->command) - { - case SCRIPT_COMMAND_TALK: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) call for NULL source.", step.script->id); - break; - } - - Creature* cSource = NULL; - cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); - - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) call for non supported source (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(), source->GetEntry(), source->GetGUIDLow()); - break; - } - - if (step.script->datalong > CHAT_TYPE_WHISPER) - { - sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) invalid chat type (%u), skipping.", step.script->id, step.script->datalong); - break; - } - - uint64 unit_target = target ? target->GetGUID() : 0; - - //datalong 0=normal say, 1=whisper, 2=yell, 3=emote text, 4=boss emote text - //TODO: Update for more chat types - switch (step.script->datalong) - { - case CHAT_TYPE_SAY: // Say - cSource->Say(step.script->dataint, LANG_UNIVERSAL, unit_target); - break; - case CHAT_TYPE_YELL: // Yell - cSource->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target); - break; - case CHAT_TYPE_TEXT_EMOTE: // Emote text - cSource->TextEmote(step.script->dataint, unit_target); - break; - case CHAT_TYPE_BOSS_EMOTE: // Boss Emote text - cSource->MonsterTextEmote(step.script->dataint, unit_target, true); - break; - case CHAT_TYPE_WHISPER: // Whisper - if (!unit_target || !IS_PLAYER_GUID(unit_target)) - { - sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) attempt to whisper (%u) NULL, skipping.", step.script->id, - step.script->datalong); - break; - } - cSource->Whisper(step.script->dataint,unit_target); - break; - default: - break; // must be already checked at load - } - break; - } - - case SCRIPT_COMMAND_EMOTE: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_EMOTE (script id: %u) call for NULL source.", step.script->id); - break; - } - - Creature* cSource = NULL; - cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); - - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) call for non supported source (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(), source->GetEntry(), source->GetGUIDLow()); - break; - } - - if (step.script->datalong2) - cSource->SetUInt32Value(UNIT_NPC_EMOTESTATE, step.script->datalong); - else - cSource->HandleEmoteCommand(step.script->datalong); - break; - } - - case SCRIPT_COMMAND_FIELD_SET: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_FIELD_SET (script id: %u) call for NULL source.", step.script->id); - break; - } - - Creature* cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_FIELD_SET (script id: %u) call for non-creature source.", step.script->id); - break; - } - - if (step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= cSource->GetValuesCount()) - { - sLog.outError("SCRIPT_COMMAND_FIELD_SET (script id: %u) call for wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u).", - step.script->id, step.script->datalong,source->GetValuesCount(),source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - cSource->SetUInt32Value(step.script->datalong, step.script->datalong2); - break; - } - - case SCRIPT_COMMAND_MOVE_TO: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_MOVE_TO (script id: %u) call for NULL creature.", step.script->id); - break; - } - - Creature* cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_MOVE_TO (script id: %u) call for non-creature (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - cSource->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2); - cSource->GetMap()->CreatureRelocation(cSource, step.script->x, step.script->y, step.script->z, 0); - break; - } - - case SCRIPT_COMMAND_FLAG_SET: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_FLAG_SET (script id: %u) call for NULL object.", step.script->id); - break; - } - - Creature* cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_FLAG_SET (script id: %u) call for non-creature source.", step.script->id); - break; - } - - if (step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= cSource->GetValuesCount()) - { - sLog.outError("SCRIPT_COMMAND_FLAG_SET (script id: %u) call for wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u).", - step.script->id, step.script->datalong,source->GetValuesCount(),source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - cSource->SetFlag(step.script->datalong, step.script->datalong2); - break; - } - - case SCRIPT_COMMAND_FLAG_REMOVE: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE (script id: %u) call for NULL object.", step.script->id); - break; - } - - Creature* cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE (script id: %u) call for non-creature source.", step.script->id); - break; - } - - if (step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= cSource->GetValuesCount()) - { - sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE (script id: %u) call for wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u).", - step.script->id, step.script->datalong,source->GetValuesCount(),source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - cSource->RemoveFlag(step.script->datalong, step.script->datalong2); - break; - } - - case SCRIPT_COMMAND_TELEPORT_TO: - { - // accept object in any one from target/source arg - if (!target && !source) - { - sLog.outError("SCRIPT_COMMAND_TELEPORT_TO (script id: %u) call for NULL object.", step.script->id); - break; - } - - if (step.script->datalong2 == 0) - { - Player* pSource = target->ToPlayer() != NULL ? target->ToPlayer() : source->ToPlayer(); - // must be only Player - if (!pSource) - { - sLog.outError("SCRIPT_COMMAND_TELEPORT_TO (script id: %u) call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", - step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); - break; - } - - pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o); - } - else if (step.script->datalong2 == 1) - { - Creature *cSource = target->ToCreature() != NULL ? target->ToCreature() : source->ToCreature(); - // must be only Creature - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_TELEPORT_TO (script id: %u) call for non-creature (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", - step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); - break; - } - - cSource->NearTeleportTo(step.script->x, step.script->y, step.script->z, step.script->o); - } - break; - } - - case SCRIPT_COMMAND_KILL_CREDIT: - { - // accept player in any one from target/source arg - if (!target && !source) - { - sLog.outError("SCRIPT_COMMAND_KILL_CREDIT (script id: %u) call for NULL object.", step.script->id); - break; - } - - Player* pSource = target->ToPlayer() != NULL ? target->ToPlayer() : source->ToPlayer(); - // must be only Player - if (!pSource) - { - sLog.outError("SCRIPT_COMMAND_KILL_CREDIT (script id: %u) call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", - step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); - break; - } - - if (step.script->datalong2) - pSource->RewardPlayerAndGroupAtEvent(step.script->datalong, pSource); - else - pSource->KilledMonsterCredit(step.script->datalong, 0); - - break; - } - - case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: - { - if (!step.script->datalong) // creature not specified - { - sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE (script id: %u) call with no creature parameter.", step.script->id); - break; - } - - if (!source) - { - sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE (script id: %u) call for NULL source object.", step.script->id); - break; - } - - WorldObject* summoner = dynamic_cast(source); - - if (!summoner) - { - sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE (script id: %u) call for non-WorldObject (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - float x = step.script->x; - float y = step.script->y; - float z = step.script->z; - float o = step.script->o; - - Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2); - if (!pCreature) - { - sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON (script id: %u) failed for creature (entry: %u).", step.script->id, step.script->datalong); - break; - } - - break; - } - - case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: - { - if (!step.script->datalong) // gameobject not specified - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) call with no gameobject parameter.", step.script->id); - break; - } - - if (!source) - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) call for NULL source object.", step.script->id); - break; - } - - WorldObject* summoner = dynamic_cast(source); - - if (!summoner) - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) call for non-WorldObject (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - GameObject *go = NULL; - int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2; - - CellPair p(Trinity::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - Trinity::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong); - Trinity::GameObjectSearcher checker(summoner, go,go_check); - - TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); - cell.Visit(p, object_checker, *summoner->GetMap()); - - if (!go) - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) failed for gameobject(guid: %u).", step.script->id, step.script->datalong); - break; - } - - if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE || - go->GetGoType() == GAMEOBJECT_TYPE_DOOR || - go->GetGoType() == GAMEOBJECT_TYPE_BUTTON || - go->GetGoType() == GAMEOBJECT_TYPE_TRAP) - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) can not be used with gameobject of type %u (guid: %u).", - step.script->id, uint32(go->GetGoType()), step.script->datalong); - break; - } - - if (go->isSpawned()) - break; //gameobject already spawned - - go->SetLootState(GO_READY); - go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds - - go->GetMap()->Add(go); - break; - } - case SCRIPT_COMMAND_OPEN_DOOR: - { - if (!step.script->datalong) // door not specified - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) call for NULL target door.", step.script->id); - break; - } - - if (!source) - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) call for NULL source unit.", step.script->id); - break; - } - - if (!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) call for non-unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - GameObject *door = NULL; - WorldObject* wSource = (WorldObject*)source; - - int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; - - CellPair p(Trinity::ComputeCellPair(wSource->GetPositionX(), wSource->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - Trinity::GameObjectWithDbGUIDCheck go_check(*wSource, step.script->datalong); - Trinity::GameObjectSearcher checker(wSource, door, go_check); - - TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); - cell.Visit(p, object_checker, *wSource->GetMap()); - - if (!door) - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) failed for gameobject(guid: %u).", step.script->id, step.script->datalong); - break; - } - if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR) - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) failed for non-door(GoType: %u, Entry: %u, GUID: %u).", - step.script->id, door->GetGoType(),door->GetEntry(),door->GetGUIDLow()); - break; - } - - if (door->GetGoState() != GO_STATE_READY) - break; //door already open - - door->UseDoorOrButton(time_to_close); - - if (target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType() == GAMEOBJECT_TYPE_BUTTON) - ((GameObject*)target)->UseDoorOrButton(time_to_close); - break; - } - case SCRIPT_COMMAND_CLOSE_DOOR: - { - if (!step.script->datalong) // guid for door not specified - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) call for NULL door.", step.script->id); - break; - } - - if (!source) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) call for NULL unit.", step.script->id); - break; - } - - if (!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) call for non-unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - GameObject *door = NULL; - WorldObject* wSource = (WorldObject*)source; - - int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; - - CellPair p(Trinity::ComputeCellPair(wSource->GetPositionX(), wSource->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - Trinity::GameObjectWithDbGUIDCheck go_check(*wSource, step.script->datalong); - Trinity::GameObjectSearcher checker(wSource, door, go_check); - - TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); - cell.Visit(p, object_checker, *wSource->GetMap()); - - if (!door) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) failed for gameobject(guid: %u).", step.script->id, step.script->datalong); - break; - } - if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) failed for non-door(GoType: %u, Entry: %u, GUID: %u).", - step.script->id, door->GetGoType(),door->GetEntry(),door->GetGUIDLow()); - break; - } - - if (door->GetGoState() == GO_STATE_READY) - break; //door already closed - - door->UseDoorOrButton(time_to_open); - - if (target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType() == GAMEOBJECT_TYPE_BUTTON) - ((GameObject*)target)->UseDoorOrButton(time_to_open); - - break; - } - case SCRIPT_COMMAND_QUEST_EXPLORED: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for NULL source.", step.script->id); - break; - } - - if (!target) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for NULL target.", step.script->id); - break; - } - - // when script called for item spell casting then target == (unit or GO) and source is player - WorldObject* worldObject; - Player* pTarget; - - pTarget = target->ToPlayer(); - if (pTarget) - { - if (source->GetTypeId() != TYPEID_UNIT && source->GetTypeId() != TYPEID_GAMEOBJECT && source->GetTypeId() != TYPEID_PLAYER) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for non-creature, non-gameobject or non-player (TypeId: %u), skipping.", - step.script->id, source->GetTypeId()); - break; - } - - worldObject = (WorldObject*)source; - } - else - { - if (target->GetTypeId() != TYPEID_UNIT && target->GetTypeId() != TYPEID_GAMEOBJECT && target->GetTypeId() != TYPEID_PLAYER) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for non-creature, non-gameobject or non-player (TypeId: %u), skipping.", - step.script->id, target->GetTypeId()); - break; - } - - pTarget = source->ToPlayer(); - if (!pTarget) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for non-player (TypeId: %u), skipping.", step.script->id, source->GetTypeId()); - break; - } - - worldObject = (WorldObject*)target; - } - - // quest id and flags checked at script loading - if ((worldObject->GetTypeId() != TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) && - (step.script->datalong2 == 0 || worldObject->IsWithinDistInMap(pTarget, float(step.script->datalong2)))) - pTarget->AreaExploredOrEventHappens(step.script->datalong); - else - pTarget->FailQuest(step.script->datalong); - - break; - } - - case SCRIPT_COMMAND_ACTIVATE_OBJECT: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT (script id: %u) must have source caster.", step.script->id); - break; - } - - if (!source->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT (script id: %u) source caster isn't unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - if (!target) - { - sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT (script id: %u) call for NULL gameobject.", step.script->id); - break; - } - - if (target->GetTypeId() != TYPEID_GAMEOBJECT) - { - sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT (script id: %u) call for non-gameobject (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, target->GetTypeId(),target->GetEntry(),target->GetGUIDLow()); - break; - } - - Unit* caster = (Unit*)source; - - GameObject *go = (GameObject*)target; - - go->Use(caster); - break; - } - - case SCRIPT_COMMAND_REMOVE_AURA: - { - Object* cmdTarget = step.script->datalong2 ? source : target; - - if (!cmdTarget) - { - sLog.outError("SCRIPT_COMMAND_REMOVE_AURA (script id: %u) call for NULL %s.", step.script->id, step.script->datalong2 ? "source" : "target"); - break; - } - - if (!cmdTarget->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_REMOVE_AURA (script id: %u) %s isn't unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId(),cmdTarget->GetEntry(),cmdTarget->GetGUIDLow()); - break; - } - - ((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong); - break; - } - - case SCRIPT_COMMAND_CAST_SPELL: - { - // TODO: Allow gameobjects to be targets and casters - if (!source) - { - sLog.outError("SCRIPT_COMMAND_CAST_SPELL (script id: %u) must have source caster.", step.script->id); - break; - } - - Unit* uSource = NULL; - Unit* uTarget = NULL; - // source/target cast spell at target/source (script->datalong2: 0: s->t 1: s->s 2: t->t 3: t->s - switch (step.script->datalong2) - { - case 0: // source -> target - uSource = dynamic_cast(source); - uTarget = dynamic_cast(target); - break; - case 1: // source -> source - uSource = dynamic_cast(source); - uTarget = dynamic_cast(source); - break; - case 2: // target -> target - uSource = dynamic_cast(target); - uTarget = dynamic_cast(target); - break; - case 3: // target -> source - uSource = dynamic_cast(target); - uTarget = dynamic_cast(source); - break; - case 4: // creature - uSource = dynamic_cast(source); - uTarget = GetClosestCreatureWithEntry(uSource, step.script->dataint, step.script->x); - break; - } - - if (!uSource || !uSource->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_CAST_SPELL (script id: %u) no source unit found for spell %u", step.script->id, step.script->datalong); - break; - } - - if (!uTarget || !uTarget->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_CAST_SPELL (script id: %u) no target unit found for spell %u", step.script->id, step.script->datalong); - break; - } - - uSource->CastSpell(uTarget, step.script->datalong, false); - break; - } - - case SCRIPT_COMMAND_PLAY_SOUND: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_PLAY_SOUND (script id: %u) call for NULL creature.", step.script->id); - break; - } - - WorldObject* pSource = dynamic_cast(source); - if (!pSource) - { - sLog.outError("SCRIPT_COMMAND_PLAY_SOUND (script id: %u) call for non-world object (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - // bitmask: 0/1=anyone/target, 0/2=with distance dependent - Player* pTarget; - if (step.script->datalong2 & 1) - { - if (!target) - { - sLog.outError("SCRIPT_COMMAND_PLAY_SOUND (script id: %u) in targeted mode call for NULL target.", step.script->id); - break; - } - - pTarget = target->ToPlayer(); - if (!pTarget) - { - sLog.outError("SCRIPT_COMMAND_PLAY_SOUND (script id: %u) in targeted mode call for non-player (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, target->GetTypeId(),target->GetEntry(),target->GetGUIDLow()); - break; - } - } - - // bitmask: 0/1=anyone/target, 0/2=with distance dependent - if (step.script->datalong2 & 2) - pSource->PlayDistanceSound(step.script->datalong, pTarget); - else - pSource->PlayDirectSound(step.script->datalong, pTarget); - break; - } - - case SCRIPT_COMMAND_CREATE_ITEM: - { - if (!target && !source) - { - sLog.outError("SCRIPT_COMMAND_CREATE_ITEM (script id: %u) call for NULL object.", step.script->id); - break; - } - - Player *pReceiver = target->ToPlayer() != NULL ? target->ToPlayer() : source->ToPlayer(); - // only Player - if (!pReceiver) - { - sLog.outError("SCRIPT_COMMAND_CREATE_ITEM (script id: %u) call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", - step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); - break; - } - - ItemPosCountVec dest; - uint8 msg = pReceiver->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, step.script->datalong, step.script->datalong2); - if (msg == EQUIP_ERR_OK) - { - if (Item* item = pReceiver->StoreNewItem(dest, step.script->datalong, true)) - pReceiver->SendNewItem(item, step.script->datalong2, false, true); - } - else - pReceiver->SendEquipError(msg,NULL,NULL); - - break; - } - - case SCRIPT_COMMAND_DESPAWN_SELF: - { - if (!target && !source) - { - sLog.outError("SCRIPT_COMMAND_DESPAWN_SELF (script id: %u) call for NULL object.", step.script->id); - break; - } - - Creature* cSource = target->ToCreature(); - // only creature - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_DESPAWN_SELF (script id: %u) call for non-creature (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", - step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); - break; - } - - cSource->ForcedDespawn(step.script->datalong); - break; - } - - case SCRIPT_COMMAND_LOAD_PATH: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_START_MOVE (script id: %u) cannot be applied to NON-existing unit.", step.script->id); - break; - } - - if (!source->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_START_MOVE (script id: %u) source mover isn't unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", - step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); - break; - } - - if (!sWaypointMgr->GetPath(step.script->datalong)) - { - sLog.outError("SCRIPT_COMMAND_START_MOVE (script id: %u) source mover has an invalid path, skipping.", step.script->id, step.script->datalong2); - break; - } - - ((Unit*)source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2); - break; - } - - case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT: - { - if (!step.script->datalong || !step.script->datalong2) - { - sLog.outError("SCRIPT_COMMAND_CALLSCRIPT (script id: %u) calls invalid db_script_id or lowguid not present: skipping.", step.script->id); - break; - } - - Creature* cTarget; - if (source) //using grid searcher - { - WorldObject* wSource = (WorldObject*)source; - CellPair p(Trinity::ComputeCellPair(wSource->GetPositionX(), wSource->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - Trinity::CreatureWithDbGUIDCheck target_check(wSource, step.script->datalong); - Trinity::CreatureSearcher checker(wSource, cTarget, target_check); - - TypeContainerVisitor, GridTypeMapContainer > unit_checker(checker); - cell.Visit(p, unit_checker, *wSource->GetMap()); - } - else //check hashmap holders - { - if (CreatureData const* data = objmgr.GetCreatureData(step.script->datalong)) - cTarget = ObjectAccessor::GetObjectInWorld(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->datalong, data->id, HIGHGUID_UNIT), cTarget); - } - - if (!cTarget) - { - sLog.outError("SCRIPT_COMMAND_CALLSCRIPT (script id: %u) target not found, creature entry %u", step.script->id, step.script->datalong); - break; - } - - //Lets choose our ScriptMap map - ScriptMapMap *datamap = NULL; - switch (step.script->dataint) - { - case 1: //QUEST END SCRIPTMAP - datamap = &sQuestEndScripts; - break; - case 2: //QUEST START SCRIPTMAP - datamap = &sQuestStartScripts; - break; - case 3: //SPELLS SCRIPTMAP - datamap = &sSpellScripts; - break; - case 4: //GAMEOBJECTS SCRIPTMAP - datamap = &sGameObjectScripts; - break; - case 5: //EVENTS SCRIPTMAP - datamap = &sEventScripts; - break; - case 6: //WAYPOINTS SCRIPTMAP - datamap = &sWaypointScripts; - break; - default: - sLog.outError("SCRIPT_COMMAND_CALLSCRIPT ERROR: no scriptmap present... ignoring"); - break; - } - //if no scriptmap present... - if (!datamap) - break; - - uint32 script_id = step.script->datalong2; - //insert script into schedule but do not start it - ScriptsStart(*datamap, script_id, cTarget, NULL/*, false*/); - break; - } - - case SCRIPT_COMMAND_KILL: - { - // TODO: Allow to kill objects other than self? - if (!source) - break; - - Creature* cSource = source->ToCreature(); - if (!cSource) - break; - - if (cSource->isDead()) - { - sLog.outError("SCRIPT_COMMAND_KILL (script id: %u) called for already dead creature, entry %u, guidLow %u", - step.script->id, cSource->GetEntry(), cSource->GetGUIDLow()); - break; - } - - cSource->setDeathState(JUST_DIED); - if (step.script->dataint == 1) - cSource->RemoveCorpse(); - - break; - } - - case SCRIPT_COMMAND_ORIENTATION: - { - if (!source || !source->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_ORIENTATION (script id: %u) call for NULL or non-unit source.", step.script->id); - break; - } - - Unit* uSource = (Unit*)source; - - if (!step.script->datalong) - uSource->SetOrientation(step.script->o); - else - { - if (!target || !target->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_ORIENTATION (script id: %u) call for NULL or non-unit target.", step.script->id); - break; - } - uSource->SetInFront((Unit*)target); - } - - uSource->SendMovementFlagUpdate(); - break; - } - case SCRIPT_COMMAND_EQUIP: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_EQUIP (script id: %u) call for NULL source.", step.script->id); - break; - } - - Creature* cSource = source->ToCreature(); - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_EQUIP (script id: %u) call, source is non-creature.", step.script->id); - break; - } - - cSource->LoadEquipment(step.script->datalong); - break; - } - case SCRIPT_COMMAND_MODEL: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_EQUIP (script id: %u) call for NULL source.", step.script->id); - break; - } - - Creature* cSource = source->ToCreature(); - if (!cSource) - { - sLog.outError("SCRIPT_COMMAND_EQUIP (script id: %u) call, source is non-creature.", step.script->id); - break; - } - - cSource->SetDisplayId(step.script->datalong); - break; - } - - case SCRIPT_COMMAND_CLOSE_GOSSIP: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_GOSSIP (script id: %u) for null source", step.script->id); - break; - } - - Player *pSource = source->ToPlayer(); - if (!pSource) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_GOSSIP (script id: %u) for non-player source.", step.script->id); - break; - } - - pSource->PlayerTalkClass->CloseGossip(); - break; - } - - case SCRIPT_COMMAND_PLAYMOVIE: - { - if (!source) - { - sLog.outError("SCRIPT_COMMAND_PLAYMOVIE (script id: %u) call for NULL source.", step.script->id); - break; - } - - Player* pSource = source->ToPlayer(); - if (!pSource) - { - sLog.outError("SCRIPT_COMMAND_PLAYMOVIE (script id: %u) call for non-player source.", step.script->id); - break; - } - pSource->SendMovieStart(step.script->datalong); - break; - } - - default: - sLog.outError("Unknown script command %u called.", step.script->command); - break; - } - - m_scriptSchedule.erase(iter); - sWorld.DecreaseScheduledScriptCount(); - - iter = m_scriptSchedule.begin(); - } -} - -Creature* -Map::GetCreature(uint64 guid) -{ - Creature * ret = NULL; - if (IS_CRE_OR_VEH_GUID(guid)) - ret = ObjectAccessor::GetObjectInWorld(guid, (Creature*)NULL); - - if (!ret) - return NULL; - - if (ret->GetMapId() != GetId()) - return NULL; - - if (ret->GetInstanceId() != GetInstanceId()) - return NULL; - - return ret; -} - -GameObject* -Map::GetGameObject(uint64 guid) -{ - GameObject * ret = ObjectAccessor::GetObjectInWorld(guid, (GameObject*)NULL); - if (!ret) - return NULL; - if (ret->GetMapId() != GetId()) - return NULL; - if (ret->GetInstanceId() != GetInstanceId()) - return NULL; - return ret; -} - -DynamicObject* -Map::GetDynamicObject(uint64 guid) -{ - DynamicObject * ret = ObjectAccessor::GetObjectInWorld(guid, (DynamicObject*)NULL); - if (!ret) - return NULL; - if (ret->GetMapId() != GetId()) - return NULL; - if (ret->GetInstanceId() != GetInstanceId()) - return NULL; - return ret; -} - -void Map::UpdateIteratorBack(Player *player) -{ - if (m_mapRefIter == player->GetMapRef()) - m_mapRefIter = m_mapRefIter->nocheck_prev(); -} diff --git a/src/server/game/Map/Map.h b/src/server/game/Map/Map.h deleted file mode 100644 index ceb526b8244..00000000000 --- a/src/server/game/Map/Map.h +++ /dev/null @@ -1,689 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_MAP_H -#define TRINITY_MAP_H - -#include "Platform/Define.h" -#include "Policies/ThreadingModel.h" -#include "ace/RW_Thread_Mutex.h" -#include "ace/Thread_Mutex.h" - -#include "DBCStructure.h" -#include "GridDefines.h" -#include "Cell.h" -#include "Timer.h" -#include "SharedDefines.h" -#include "GameSystem/GridRefManager.h" -#include "MapRefManager.h" -#include "mersennetwister/MersenneTwister.h" - -#include -#include - -class Unit; -class WorldPacket; -class InstanceData; -class Group; -class InstanceSave; -class Object; -class WorldObject; -class TempSummon; -class Player; -class CreatureGroup; -struct ScriptInfo; -struct ScriptAction; -struct Position; -class BattleGround; - -//****************************************** -// Map file format defines -//****************************************** -#define MAP_MAGIC 'SPAM' -#define MAP_VERSION_MAGIC '0.1w' -#define MAP_AREA_MAGIC 'AERA' -#define MAP_HEIGHT_MAGIC 'TGHM' -#define MAP_LIQUID_MAGIC 'QILM' - -struct map_fileheader -{ - uint32 mapMagic; - uint32 versionMagic; - uint32 areaMapOffset; - uint32 areaMapSize; - uint32 heightMapOffset; - uint32 heightMapSize; - uint32 liquidMapOffset; - uint32 liquidMapSize; -}; - -#define MAP_AREA_NO_AREA 0x0001 - -struct map_areaHeader -{ - uint32 fourcc; - uint16 flags; - uint16 gridArea; -}; - -#define MAP_HEIGHT_NO_HEIGHT 0x0001 -#define MAP_HEIGHT_AS_INT16 0x0002 -#define MAP_HEIGHT_AS_INT8 0x0004 - -struct map_heightHeader -{ - uint32 fourcc; - uint32 flags; - float gridHeight; - float gridMaxHeight; -}; - -#define MAP_LIQUID_NO_TYPE 0x0001 -#define MAP_LIQUID_NO_HEIGHT 0x0002 - -struct map_liquidHeader -{ - uint32 fourcc; - uint16 flags; - uint16 liquidType; - uint8 offsetX; - uint8 offsetY; - uint8 width; - uint8 height; - float liquidLevel; -}; - -enum ZLiquidStatus -{ - LIQUID_MAP_NO_WATER = 0x00000000, - LIQUID_MAP_ABOVE_WATER = 0x00000001, - LIQUID_MAP_WATER_WALK = 0x00000002, - LIQUID_MAP_IN_WATER = 0x00000004, - LIQUID_MAP_UNDER_WATER = 0x00000008 -}; - -#define MAP_LIQUID_TYPE_NO_WATER 0x00 -#define MAP_LIQUID_TYPE_WATER 0x01 -#define MAP_LIQUID_TYPE_OCEAN 0x02 -#define MAP_LIQUID_TYPE_MAGMA 0x04 -#define MAP_LIQUID_TYPE_SLIME 0x08 - -#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME) - -#define MAP_LIQUID_TYPE_DARK_WATER 0x10 -#define MAP_LIQUID_TYPE_WMO_WATER 0x20 - -struct LiquidData -{ - uint32 type; - float level; - float depth_level; -}; - -class GridMap -{ - uint32 m_flags; - // Area data - uint16 m_gridArea; - uint16 *m_area_map; - // Height level data - float m_gridHeight; - float m_gridIntHeightMultiplier; - union{ - float *m_V9; - uint16 *m_uint16_V9; - uint8 *m_uint8_V9; - }; - union{ - float *m_V8; - uint16 *m_uint16_V8; - uint8 *m_uint8_V8; - }; - // Liquid data - uint16 m_liquidType; - uint8 m_liquid_offX; - uint8 m_liquid_offY; - uint8 m_liquid_width; - uint8 m_liquid_height; - float m_liquidLevel; - uint8 *m_liquid_type; - float *m_liquid_map; - - bool loadAreaData(FILE *in, uint32 offset, uint32 size); - bool loadHeihgtData(FILE *in, uint32 offset, uint32 size); - bool loadLiquidData(FILE *in, uint32 offset, uint32 size); - - // Get height functions and pointers - typedef float (GridMap::*pGetHeightPtr) (float x, float y) const; - pGetHeightPtr m_gridGetHeight; - float getHeightFromFloat(float x, float y) const; - float getHeightFromUint16(float x, float y) const; - float getHeightFromUint8(float x, float y) const; - float getHeightFromFlat(float x, float y) const; - -public: - GridMap(); - ~GridMap(); - bool loadData(char *filaname); - void unloadData(); - - uint16 getArea(float x, float y); - inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);} - float getLiquidLevel(float x, float y); - uint8 getTerrainType(float x, float y); - ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0); -}; - -struct CreatureMover -{ - CreatureMover() : x(0), y(0), z(0), ang(0) {} - CreatureMover(float _x, float _y, float _z, float _ang) : x(_x), y(_y), z(_z), ang(_ang) {} - - float x, y, z, ang; -}; - -// 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 -#if defined(__GNUC__) -#pragma pack(1) -#else -#pragma pack(push,1) -#endif - -struct InstanceTemplate -{ - uint32 map; - uint32 parent; - uint32 access_id; - float startLocX; - float startLocY; - float startLocZ; - float startLocO; - uint32 script_id; - bool allowMount; -}; - -enum LevelRequirementVsMode -{ - LEVELREQUIREMENT_HEROIC = 70 -}; - -#if defined(__GNUC__) -#pragma pack() -#else -#pragma pack(pop) -#endif - -typedef UNORDERED_MAP CreatureMoveList; - -#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface -#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE -#define MIN_UNLOAD_DELAY 1 // immediate unload - -typedef std::map CreatureGroupHolderType; - -class Map : public GridRefManager, public Trinity::ObjectLevelLockable -{ - friend class MapReference; - public: - Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL); - virtual ~Map(); - - // currently unused for normal maps - bool CanUnload(uint32 diff) - { - if (!m_unloadTimer) return false; - if (m_unloadTimer <= diff) return true; - m_unloadTimer -= diff; - return false; - } - - virtual bool Add(Player *); - virtual void Remove(Player *, bool); - template void Add(T *); - template void Remove(T *, bool); - - virtual void Update(const uint32&); - - /* - void MessageBroadcast(Player *, WorldPacket *, bool to_self); - void MessageBroadcast(WorldObject *, WorldPacket *); - void MessageDistBroadcast(Player *, WorldPacket *, float dist, bool to_self, bool own_team_only = false); - void MessageDistBroadcast(WorldObject *, WorldPacket *, float dist); - */ - - float GetVisibilityDistance() const { return m_VisibleDistance; } - //function for setting up visibility distance for maps on per-type/per-Id basis - virtual void InitVisibilityDistance(); - - void PlayerRelocation(Player *, float x, float y, float z, float orientation); - void CreatureRelocation(Creature *creature, float x, float y, float z, float ang); - - template void Visit(const Cell& cell, TypeContainerVisitor &visitor); - - bool IsRemovalGrid(float x, float y) const - { - GridPair p = Trinity::ComputeGridPair(x, y); - return !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL; - } - - bool IsLoaded(float x, float y) const - { - GridPair p = Trinity::ComputeGridPair(x, y); - return loaded(p); - } - - bool GetUnloadLock(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); } - void SetUnloadLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); } - void LoadGrid(float x, float y); - bool UnloadGrid(const uint32 &x, const uint32 &y, bool pForce); - virtual void UnloadAll(); - - void ResetGridExpiry(NGridType &grid, float factor = 1) const - { - grid.ResetTimeTracker(time_t(float(i_gridExpiry)*factor)); - } - - time_t GetGridExpiry(void) const { return i_gridExpiry; } - uint32 GetId(void) const { return i_mapEntry->MapID; } - - static bool ExistMap(uint32 mapid, int gx, int gy); - static bool ExistVMap(uint32 mapid, int gx, int gy); - - static void InitStateMachine(); - static void DeleteStateMachine(); - - Map const * GetParent() const { return m_parentMap; } - - // some calls like isInWater should not use vmaps due to processor power - // can return INVALID_HEIGHT if under z+2 z coord not found height - float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; - - ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0) const; - - uint16 GetAreaFlag(float x, float y, float z, bool *isOutdoors=0) const; - bool GetAreaInfo(float x, float y, float z, uint32 &mogpflags, int32 &adtId, int32 &rootId, int32 &groupId) const; - - bool IsOutdoors(float x, float y, float z) const; - - uint8 GetTerrainType(float x, float y) const; - float GetWaterLevel(float x, float y) const; - bool IsInWater(float x, float y, float z, LiquidData *data = 0) const; - bool IsUnderWater(float x, float y, float z) const; - - static uint32 GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id); - static uint32 GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id); - static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id); - - uint32 GetAreaId(float x, float y, float z) const - { - return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),GetId()); - } - - uint32 GetZoneId(float x, float y, float z) const - { - return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),GetId()); - } - - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const - { - GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),GetId()); - } - - void MoveAllCreaturesInMoveList(); - void RemoveAllObjectsInRemoveList(); - virtual void RemoveAllPlayers(); - - bool CreatureRespawnRelocation(Creature *c); // used only in MoveAllCreaturesInMoveList and ObjectGridUnloader - - // assert print helper - bool CheckGridIntegrity(Creature* c, bool moved) const; - - uint32 GetInstanceId() const { return i_InstanceId; } - uint8 GetSpawnMode() const { return (i_spawnMode); } - virtual bool CanEnter(Player* /*player*/) { return true; } - const char* GetMapName() const; - - // have meaning only for instanced map (that have set real difficulty) - Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); } - bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; } - MapDifficulty const* GetMapDifficulty() const; - - bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); } - // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable - bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); } - bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); } - bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); } - bool IsRaidOrHeroicDungeon() const { return IsRaid() || i_spawnMode > DUNGEON_DIFFICULTY_NORMAL; } - bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; } - bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); } - bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } - bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); } - bool GetEntrancePos(int32 &mapid, float &x, float &y) - { - if (!i_mapEntry) - return false; - return i_mapEntry->GetEntrancePos(mapid, x, y); - } - - void AddObjectToRemoveList(WorldObject *obj); - void AddObjectToSwitchList(WorldObject *obj, bool on); - virtual void DelayedUpdate(const uint32 diff); - - virtual bool RemoveBones(uint64 guid, float x, float y); - - void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair); - void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair); - - void resetMarkedCells() { marked_cells.reset(); } - bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } - void markCell(uint32 pCellId) { marked_cells.set(pCellId); } - - bool HavePlayers() const { return !m_mapRefManager.isEmpty(); } - uint32 GetPlayersCountExceptGMs() const; - bool ActiveObjectsNearGrid(uint32 x, uint32 y) const; - - void AddWorldObject(WorldObject *obj) { i_worldObjects.insert(obj); } - void RemoveWorldObject(WorldObject *obj) { i_worldObjects.erase(obj); } - - void SendToPlayers(WorldPacket const* data) const; - - typedef MapRefManager PlayerList; - PlayerList const& GetPlayers() const { return m_mapRefManager; } - - //per-map script storage - void ScriptsStart(std::map > const& scripts, uint32 id, Object* source, Object* target); - void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); - - // must called with AddToWorld - template - void AddToActive(T* obj) { AddToActiveHelper(obj); } - - void AddToActive(Creature* obj); - - // must called with RemoveFromWorld - template - void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); } - - void RemoveFromActive(Creature* obj); - - template void SwitchGridContainers(T* obj, bool active); - template void VisitAll(const float &x, const float &y, float radius, NOTIFIER ¬ifier); - template void VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier); - template void VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier); - CreatureGroupHolderType CreatureGroupHolder; - - void UpdateIteratorBack(Player *player); - -#ifdef MAP_BASED_RAND_GEN - MTRand mtRand; - int32 irand(int32 min, int32 max) { return int32 (mtRand.randInt(max - min)) + min; } - uint32 urand(uint32 min, uint32 max) { return mtRand.randInt(max - min) + min; } - int32 rand32() { return mtRand.randInt(); } - double rand_norm() { return mtRand.randExc(); } - double rand_chance() { return mtRand.randExc(100.0); } -#endif - - TempSummon *SummonCreature(uint32 entry, const Position &pos, SummonPropertiesEntry const *properties = NULL, uint32 duration = 0, Unit *summoner = NULL, uint32 vehId = 0); - Creature* GetCreature(uint64 guid); - GameObject* GetGameObject(uint64 guid); - DynamicObject* GetDynamicObject(uint64 guid); - private: - void LoadMapAndVMap(int gx, int gy); - void LoadVMap(int gx, int gy); - void LoadMap(int gx,int gy, bool reload = false); - GridMap *GetGrid(float x, float y); - - void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } - - void SendInitSelf(Player * player); - - void SendInitTransports(Player * player); - void SendRemoveTransports(Player * player); - - bool CreatureCellRelocation(Creature *creature, Cell new_cell); - - void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang); - CreatureMoveList i_creaturesToMove; - - bool loaded(const GridPair &) const; - void EnsureGridCreated(const GridPair &); - bool EnsureGridLoaded(Cell const&); - void EnsureGridLoadedAtEnter(Cell const&, Player* player = NULL); - - void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } - - template void AddType(T *obj); - template void RemoveType(T *obj, bool); - - NGridType* getNGrid(uint32 x, uint32 y) const - { - ASSERT(x < MAX_NUMBER_OF_GRIDS); - ASSERT(y < MAX_NUMBER_OF_GRIDS); - return i_grids[x][y]; - } - - bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); } - void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); } - - void setNGrid(NGridType* grid, uint32 x, uint32 y); - void ScriptsProcess(); - - void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff); - protected: - void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); } - - typedef Trinity::ObjectLevelLockable::Lock Guard; - - MapEntry const* i_mapEntry; - uint8 i_spawnMode; - uint32 i_InstanceId; - uint32 m_unloadTimer; - float m_VisibleDistance; - - MapRefManager m_mapRefManager; - MapRefManager::iterator m_mapRefIter; - - int32 m_VisibilityNotifyPeriod; - - typedef std::set ActiveNonPlayers; - ActiveNonPlayers m_activeNonPlayers; - ActiveNonPlayers::iterator m_activeNonPlayersIter; - - private: - time_t i_gridExpiry; - - //used for fast base_map (e.g. MapInstanced class object) search for - //InstanceMaps and BattleGroundMaps... - Map* m_parentMap; - - NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; - GridMap *GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; - std::bitset marked_cells; - - //these functions used to process player/mob aggro reactions and - //visibility calculations. Highly optimized for massive calculations - void ProcessRelocationNotifies(const uint32 &diff); - - bool i_scriptLock; - std::set i_objectsToRemove; - std::map i_objectsToSwitch; - std::set i_worldObjects; - std::multimap m_scriptSchedule; - - // Type specific code for add/remove to/from grid - template - void AddToGrid(T*, NGridType *, Cell const&); - - template - void RemoveFromGrid(T*, NGridType *, Cell const&); - - template - void DeleteFromWorld(T*); - - template - void AddToActiveHelper(T* obj) - { - m_activeNonPlayers.insert(obj); - } - - template - void RemoveFromActiveHelper(T* obj) - { - // Map::Update for active object in proccess - if (m_activeNonPlayersIter != m_activeNonPlayers.end()) - { - ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj); - if (itr == m_activeNonPlayers.end()) - return; - if (itr == m_activeNonPlayersIter) - ++m_activeNonPlayersIter; - m_activeNonPlayers.erase(itr); - } - else - m_activeNonPlayers.erase(obj); - } -}; - -enum InstanceResetMethod -{ - INSTANCE_RESET_ALL, - INSTANCE_RESET_CHANGE_DIFFICULTY, - INSTANCE_RESET_GLOBAL, - INSTANCE_RESET_GROUP_DISBAND, - INSTANCE_RESET_GROUP_JOIN, - INSTANCE_RESET_RESPAWN_DELAY -}; - -class InstanceMap : public Map -{ - public: - InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent); - ~InstanceMap(); - bool Add(Player *); - void Remove(Player *, bool); - void Update(const uint32&); - void CreateInstanceData(bool load); - bool Reset(uint8 method); - uint32 GetScriptId() { return i_script_id; } - InstanceData* GetInstanceData() { return i_data; } - void PermBindAllPlayers(Player *player); - void UnloadAll(); - bool CanEnter(Player* player); - void SendResetWarnings(uint32 timeLeft) const; - void SetResetSchedule(bool on); - - uint32 GetMaxPlayers() const; - uint32 GetMaxResetDelay() const; - - virtual void InitVisibilityDistance(); - private: - bool m_resetAfterUnload; - bool m_unloadWhenEmpty; - InstanceData* i_data; - uint32 i_script_id; -}; - -class BattleGroundMap : public Map -{ - public: - BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode); - ~BattleGroundMap(); - - bool Add(Player *); - void Remove(Player *, bool); - bool CanEnter(Player* player); - void SetUnload(); - //void UnloadAll(bool pForce); - void RemoveAllPlayers(); - - virtual void InitVisibilityDistance(); - BattleGround* GetBG() { return m_bg; } - void SetBG(BattleGround* bg) { m_bg = bg; } - private: - BattleGround* m_bg; -}; - -/*inline -uint64 -Map::CalculateGridMask(const uint32 &y) const -{ - uint64 mask = 1; - mask <<= y; - return mask; -} -*/ - -template -inline void -Map::Visit(const Cell& cell, TypeContainerVisitor &visitor) -{ - const uint32 x = cell.GridX(); - const uint32 y = cell.GridY(); - const uint32 cell_x = cell.CellX(); - const uint32 cell_y = cell.CellY(); - - if (!cell.NoCreate() || loaded(GridPair(x,y))) - { - EnsureGridLoaded(cell); - getNGrid(x, y)->Visit(cell_x, cell_y, visitor); - } -} - -template -inline void -Map::VisitAll(const float &x, const float &y, float radius, NOTIFIER ¬ifier) -{ - CellPair p(Trinity::ComputeCellPair(x, y)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - TypeContainerVisitor world_object_notifier(notifier); - cell.Visit(p, world_object_notifier, *this, radius, x, y); - TypeContainerVisitor grid_object_notifier(notifier); - cell.Visit(p, grid_object_notifier, *this, radius, x, y); -} - -template -inline void -Map::VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier) -{ - CellPair p(Trinity::ComputeCellPair(x, y)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - TypeContainerVisitor world_object_notifier(notifier); - cell.Visit(p, world_object_notifier, *this, radius, x, y); -} - -template -inline void -Map::VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier) -{ - CellPair p(Trinity::ComputeCellPair(x, y)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - TypeContainerVisitor grid_object_notifier(notifier); - cell.Visit(p, grid_object_notifier, *this, radius, x, y); -} -#endif diff --git a/src/server/game/Map/MapInstanced.cpp b/src/server/game/Map/MapInstanced.cpp deleted file mode 100644 index 0736bfa6fb3..00000000000 --- a/src/server/game/Map/MapInstanced.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "MapInstanced.h" -#include "ObjectMgr.h" -#include "MapManager.h" -#include "BattleGround.h" -#include "VMapFactory.h" -#include "InstanceSaveMgr.h" -#include "World.h" - -MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DUNGEON_DIFFICULTY_NORMAL) -{ - // initialize instanced maps list - m_InstancedMaps.clear(); - // fill with zero - memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_GRIDS*sizeof(uint16)); -} - -void MapInstanced::InitVisibilityDistance() -{ - if (m_InstancedMaps.empty()) - return; - //initialize visibility distances for all instance copies - for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) - { - (*i).second->InitVisibilityDistance(); - } -} - -void MapInstanced::Update(const uint32& t) -{ - // take care of loaded GridMaps (when unused, unload it!) - Map::Update(t); - - // update the instanced maps - InstancedMaps::iterator i = m_InstancedMaps.begin(); - - while (i != m_InstancedMaps.end()) - { - if (i->second->CanUnload(t)) - { - if (!DestroyInstance(i)) // iterator incremented - { - //m_unloadTimer - } - } - else - { - // update only here, because it may schedule some bad things before delete - i->second->Update(t); - ++i; - } - } -} - -void MapInstanced::DelayedUpdate(const uint32 diff) -{ - for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) - i->second->DelayedUpdate(diff); - - Map::DelayedUpdate(diff); // this may be removed -} - -/* -void MapInstanced::RelocationNotify() -{ - for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) - i->second->RelocationNotify(); -} -*/ - -bool MapInstanced::RemoveBones(uint64 guid, float x, float y) -{ - bool remove_result = false; - - for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) - { - remove_result = remove_result || i->second->RemoveBones(guid, x, y); - } - - return remove_result || Map::RemoveBones(guid,x,y); -} - -void MapInstanced::UnloadAll() -{ - // Unload instanced maps - for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) - i->second->UnloadAll(); - - // Delete the maps only after everything is unloaded to prevent crashes - for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) - delete i->second; - - m_InstancedMaps.clear(); - - // Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!) - Map::UnloadAll(); -} - -/* -- return the right instance for the object, based on its InstanceId -- create the instance if it's not created already -- the player is not actually added to the instance (only in InstanceMap::Add) -*/ -Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player) -{ - if (GetId() != mapId || !player) - return NULL; - - Map* map = NULL; - uint32 NewInstanceId = 0; // instanceId of the resulting map - - if (IsBattleGroundOrArena()) - { - // instantiate or find existing bg map for player - // the instance id is set in battlegroundid - NewInstanceId = player->GetBattleGroundId(); - if (!NewInstanceId) return NULL; - map = _FindMap(NewInstanceId); - if (!map) - map = CreateBattleGround(NewInstanceId, player->GetBattleGround()); - } - else - { - InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid())); - InstanceSave *pSave = pBind ? pBind->save : NULL; - - // the player's permanent player bind is taken into consideration first - // then the player's group bind and finally the solo bind. - if (!pBind || !pBind->perm) - { - InstanceGroupBind *groupBind = NULL; - Group *group = player->GetGroup(); - // use the player's difficulty setting (it may not be the same as the group's) - if (group) - { - groupBind = group->GetBoundInstance(this); - if (groupBind) - pSave = groupBind->save; - } - } - if (pSave) - { - // solo/perm/group - NewInstanceId = pSave->GetInstanceId(); - map = _FindMap(NewInstanceId); - // it is possible that the save exists but the map doesn't - if (!map) - map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty()); - } - else - { - // if no instanceId via group members or instance saves is found - // the instance will be created for the first time - NewInstanceId = MapManager::Instance().GenerateInstanceId(); - - Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); - map = CreateInstance(NewInstanceId, NULL, diff); - } - } - - return map; -} - -InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, Difficulty difficulty) -{ - // load/create a map - Guard guard(*this); - - // make sure we have a valid map id - const MapEntry* entry = sMapStore.LookupEntry(GetId()); - if (!entry) - { - sLog.outError("CreateInstance: no entry for map %d", GetId()); - assert(false); - } - const InstanceTemplate * iTemplate = objmgr.GetInstanceTemplate(GetId()); - if (!iTemplate) - { - sLog.outError("CreateInstance: no instance template for map %d", GetId()); - assert(false); - } - - // some instances only have one difficulty - MapDifficulty const* mapDiff = GetMapDifficultyData(GetId(),difficulty); - if (!mapDiff) - difficulty = DUNGEON_DIFFICULTY_NORMAL; - - sLog.outDebug("MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); - - InstanceMap *map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this); - ASSERT(map->IsDungeon()); - - bool load_data = save != NULL; - map->CreateInstanceData(load_data); - - m_InstancedMaps[InstanceId] = map; - return map; -} - -BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId, BattleGround* bg) -{ - // load/create a map - Guard guard(*this); - - sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId()); - - PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),bg->GetMinLevel()); - - uint8 spawnMode = bracketEntry ? bracketEntry->difficulty : REGULAR_DIFFICULTY; - - BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode); - ASSERT(map->IsBattleGroundOrArena()); - map->SetBG(bg); - bg->SetBgMap(map); - - m_InstancedMaps[InstanceId] = map; - return map; -} - -// increments the iterator after erase -bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) -{ - itr->second->RemoveAllPlayers(); - if (itr->second->HavePlayers()) - { - ++itr; - return false; - } - - itr->second->UnloadAll(); - // should only unload VMaps if this is the last instance and grid unloading is enabled - if (m_InstancedMaps.size() <= 1 && sWorld.getConfig(CONFIG_GRID_UNLOAD)) - { - VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId()); - // in that case, unload grids of the base map, too - // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded - Map::UnloadAll(); - } - // erase map - delete itr->second; - m_InstancedMaps.erase(itr++); - return true; -} - -bool MapInstanced::CanEnter(Player * /*player*/) -{ - //assert(false); - return true; -} diff --git a/src/server/game/Map/MapInstanced.h b/src/server/game/Map/MapInstanced.h deleted file mode 100644 index 536257da011..00000000000 --- a/src/server/game/Map/MapInstanced.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_MAP_INSTANCED_H -#define TRINITY_MAP_INSTANCED_H - -#include "Map.h" -#include "InstanceSaveMgr.h" -#include "DBCEnums.h" - -class MapInstanced : public Map -{ - friend class MapManager; - public: - typedef UNORDERED_MAP< uint32, Map* > InstancedMaps; - - MapInstanced(uint32 id, time_t expiry); - ~MapInstanced() {} - - // functions overwrite Map versions - void Update(const uint32&); - void DelayedUpdate(const uint32 diff); - //void RelocationNotify(); - bool RemoveBones(uint64 guid, float x, float y); - void UnloadAll(); - bool CanEnter(Player* player); - - Map* CreateInstance(const uint32 mapId, Player * player); - Map* FindMap(uint32 InstanceId) const { return _FindMap(InstanceId); } - bool DestroyInstance(InstancedMaps::iterator &itr); - - void AddGridMapReference(const GridPair &p) - { - ++GridMapReference[p.x_coord][p.y_coord]; - SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), true); - } - - void RemoveGridMapReference(GridPair const& p) - { - --GridMapReference[p.x_coord][p.y_coord]; - if (!GridMapReference[p.x_coord][p.y_coord]) - SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), false); - } - - InstancedMaps &GetInstancedMaps() { return m_InstancedMaps; } - virtual void InitVisibilityDistance(); - - private: - - InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave *save, Difficulty difficulty); - BattleGroundMap* CreateBattleGround(uint32 InstanceId, BattleGround* bg); - - InstancedMaps m_InstancedMaps; - - Map* _FindMap(uint32 InstanceId) const - { - InstancedMaps::const_iterator i = m_InstancedMaps.find(InstanceId); - return(i == m_InstancedMaps.end() ? NULL : i->second); - } - - uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; -}; -#endif diff --git a/src/server/game/Map/MapManager.cpp b/src/server/game/Map/MapManager.cpp deleted file mode 100644 index de3d0ebbaff..00000000000 --- a/src/server/game/Map/MapManager.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "MapManager.h" -#include "InstanceSaveMgr.h" -#include "Policies/SingletonImp.h" -#include "Database/DatabaseEnv.h" -#include "Log.h" -#include "ObjectAccessor.h" -#include "Transports.h" -#include "GridDefines.h" -#include "MapInstanced.h" -#include "InstanceData.h" -#include "DestinationHolderImp.h" -#include "Config/ConfigEnv.h" -#include "World.h" -#include "CellImpl.h" -#include "Corpse.h" -#include "ObjectMgr.h" -#include "Language.h" -#include "WorldPacket.h" - -#define CLASS_LOCK Trinity::ClassLevelLockable -INSTANTIATE_SINGLETON_2(MapManager, CLASS_LOCK); -INSTANTIATE_CLASS_MUTEX(MapManager, ACE_Thread_Mutex); - -extern GridState* si_GridStates[]; // debugging code, should be deleted some day - -MapManager::MapManager() -{ - i_gridCleanUpDelay = sWorld.getConfig(CONFIG_INTERVAL_GRIDCLEAN); - i_timer.SetInterval(sWorld.getConfig(CONFIG_INTERVAL_MAPUPDATE)); -} - -MapManager::~MapManager() -{ - for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) - delete iter->second; - - for (TransportSet::iterator i = m_Transports.begin(); i != m_Transports.end(); ++i) - delete *i; - - Map::DeleteStateMachine(); -} - -void MapManager::Initialize() -{ - Map::InitStateMachine(); - - // debugging code, should be deleted some day - { - for (uint8 i = 0; i < MAX_GRID_STATE; ++i) - i_GridStates[i] = si_GridStates[i]; - - i_GridStateErrorCount = 0; - } - int num_threads(sWorld.getConfig(CONFIG_NUMTHREADS)); - // Start mtmaps if needed. - if (num_threads > 0 && m_updater.activate(num_threads) == -1) - abort(); - - InitMaxInstanceId(); -} - -void MapManager::InitializeVisibilityDistanceInfo() -{ - for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) - (*iter).second->InitVisibilityDistance(); -} - -// debugging code, should be deleted some day -void MapManager::checkAndCorrectGridStatesArray() -{ - bool ok = true; - for (int i=0; icheckMagic()) - { - ok = false; - si_GridStates[i]->setMagic(); - } - #endif - } - if (!ok) - ++i_GridStateErrorCount; -} - -Map* MapManager::_createBaseMap(uint32 id) -{ - Map *m = _findMap(id); - - if (m == NULL) - { - Guard guard(*this); - - const MapEntry* entry = sMapStore.LookupEntry(id); - if (entry && entry->Instanceable()) - { - m = new MapInstanced(id, i_gridCleanUpDelay); - } - else - { - m = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); - } - i_maps[id] = m; - } - - assert(m != NULL); - return m; -} - -Map* MapManager::CreateMap(uint32 id, const WorldObject* obj, uint32 /*instanceId*/) -{ - ASSERT(obj); - //if (!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId()); - Map *m = _createBaseMap(id); - - if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable()) m = ((MapInstanced*)m)->CreateInstance(id, (Player*)obj); - - return m; -} - -Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const -{ - Map *map = _findMap(mapid); - if (!map) - return NULL; - - if (!map->Instanceable()) - return instanceId == 0 ? map : NULL; - - return ((MapInstanced*)map)->FindMap(instanceId); -} - -bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) -{ - const MapEntry *entry = sMapStore.LookupEntry(mapid); - if (!entry) - return false; - - if (!entry->IsDungeon()) - return true; - - const char *mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; - - Group* pGroup = player->GetGroup(); - if (entry->IsRaid()) - { - // can only enter in a raid group - // GMs can avoid raid limitations - if ((!pGroup || !pGroup->isRaidGroup()) && !player->isGameMaster() && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_RAID)) - { - // probably there must be special opcode, because client has this string constant in GlobalStrings.lua - // TODO: this is not a good place to send the message - player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName); - sLog.outDebug("MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName(), mapName); - return false; - } - } - - //The player has a heroic mode and tries to enter into instance which has no a heroic mode - MapDifficulty const* mapDiff = GetMapDifficultyData(entry->MapID,player->GetDifficulty(entry->IsRaid())); - if (!mapDiff) - { - bool isNormalTargetMap = entry->IsRaid() - ? (player->GetRaidDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - : (player->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL); - - // Send aborted message - // FIX ME: what about absent normal/heroic mode with specific players limit... - player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, isNormalTargetMap ? DUNGEON_DIFFICULTY_NORMAL : DUNGEON_DIFFICULTY_HEROIC); - return false; - } - - if (!player->isAlive()) - { - if (Corpse *corpse = player->GetCorpse()) - { - // let enter in ghost mode in instance that connected to inner instance with corpse - uint32 instance_map = corpse->GetMapId(); - do - { - if (instance_map == mapid) - break; - - InstanceTemplate const* instance = objmgr.GetInstanceTemplate(instance_map); - instance_map = instance ? instance->parent : 0; - } - while (instance_map); - - if (!instance_map) - { - WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE); - player->GetSession()->SendPacket(&data); - sLog.outDebug("MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName(), mapName); - return false; - } - sLog.outDebug("MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName(), mapName); - } - else - sLog.outDebug("Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName()); - } - - InstanceTemplate const* instance = objmgr.GetInstanceTemplate(mapid); - if (!instance) - return false; - - //Get instance where player's group is bound & its map - if (pGroup) - { - InstanceGroupBind* boundedInstance = pGroup->GetBoundInstance(player); - if (boundedInstance && boundedInstance->save) - { - if (Map *boundedMap = MapManager::Instance().FindMap(mapid,boundedInstance->save->GetInstanceId())) - { - // Player permanently bounded to different instance than groups one - InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDungeonDifficulty()); - if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save && - boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId()) - { - //TODO: send some kind of error message to the player - return false; - } - - // Encounters in progress - if (!loginCheck && entry->IsRaid() && ((InstanceMap*)boundedMap)->GetInstanceData() && ((InstanceMap*)boundedMap)->GetInstanceData()->IsEncounterInProgress()) - { - sLog.outDebug("MAP: Player '%s' cannot enter instance '%s' while an encounter is in progress.", player->GetName(), mapName); - player->SendTransferAborted(mapid, TRANSFER_ABORT_ZONE_IN_COMBAT); - return false; - } - - // Instance is full - MapDifficulty const* mapDiff = ((InstanceMap*)boundedMap)->GetMapDifficulty(); - int8 maxPlayers = mapDiff ? mapDiff->maxPlayers : 0; - if (maxPlayers != -1) //-1: unlimited access - { - if (boundedMap->GetPlayersCountExceptGMs() >= (loginCheck ? maxPlayers+1 : maxPlayers)) - { - sLog.outDebug("MAP: Player '%s' cannot enter instance '%s' because it is full.", player->GetName(), mapName); - player->SendTransferAborted(mapid, TRANSFER_ABORT_MAX_PLAYERS); - return false; - } - } - } - } - } - - //Other requirements - return player->Satisfy(objmgr.GetAccessRequirement(instance->access_id), mapid, true); -} - -void MapManager::RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y) -{ - bool remove_result = _createBaseMap(mapid)->RemoveBones(guid, x, y); - - if (!remove_result) - { - sLog.outDebug("Bones %u not found in world. Delete from DB also.", GUID_LOPART(guid)); - } -} - -void MapManager::Update(uint32 diff) -{ - i_timer.Update(diff); - if (!i_timer.Passed()) - return; - - MapMapType::iterator iter = i_maps.begin(); - for (; iter != i_maps.end(); ++iter) - { - if (m_updater.activated()) - m_updater.schedule_update(*iter->second, i_timer.GetCurrent()); - else - { - iter->second->Update(i_timer.GetCurrent()); - } - } - if (m_updater.activated()) - m_updater.wait(); - - for (iter = i_maps.begin(); iter != i_maps.end(); ++iter) - iter->second->DelayedUpdate(i_timer.GetCurrent()); - - ObjectAccessor::Instance().Update(i_timer.GetCurrent()); - for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter) - (*iter)->Update(i_timer.GetCurrent()); - - i_timer.SetCurrent(0); -} - -void MapManager::DoDelayedMovesAndRemoves() -{ -} - -bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y) -{ - GridPair p = Trinity::ComputeGridPair(x,y); - - int gx=63-p.x_coord; - int gy=63-p.y_coord; - - return Map::ExistMap(mapid,gx,gy) && Map::ExistVMap(mapid,gx,gy); -} - -bool MapManager::IsValidMAP(uint32 mapid) -{ - MapEntry const* mEntry = sMapStore.LookupEntry(mapid); - return mEntry && (!mEntry->IsDungeon() || objmgr.GetInstanceTemplate(mapid)); - // TODO: add check for battleground template -} - -void MapManager::UnloadAll() -{ - for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) - iter->second->UnloadAll(); - - while (!i_maps.empty()) - { - delete i_maps.begin()->second; - i_maps.erase(i_maps.begin()); - } - - if (m_updater.activated()) - m_updater.deactivate(); -} - -void MapManager::InitMaxInstanceId() -{ - i_MaxInstanceId = 0; - - QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(id) FROM instance"); - if (result) - i_MaxInstanceId = result->Fetch()[0].GetUInt32(); -} - -uint32 MapManager::GetNumInstances() -{ - Guard guard(*this); - - uint32 ret = 0; - for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr) - { - Map *map = itr->second; - if (!map->Instanceable()) - continue; - MapInstanced::InstancedMaps &maps = ((MapInstanced *)map)->GetInstancedMaps(); - for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr) - if (mitr->second->IsDungeon()) ret++; - } - return ret; -} - -uint32 MapManager::GetNumPlayersInInstances() -{ - Guard guard(*this); - - uint32 ret = 0; - for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr) - { - Map *map = itr->second; - if (!map->Instanceable()) - continue; - MapInstanced::InstancedMaps &maps = ((MapInstanced *)map)->GetInstancedMaps(); - for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr) - if (mitr->second->IsDungeon()) - ret += ((InstanceMap*)mitr->second)->GetPlayers().getSize(); - } - return ret; -} diff --git a/src/server/game/Map/MapManager.h b/src/server/game/Map/MapManager.h deleted file mode 100644 index d94f9fced0e..00000000000 --- a/src/server/game/Map/MapManager.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_MAPMANAGER_H -#define TRINITY_MAPMANAGER_H - -#include "Platform/Define.h" -#include "Policies/Singleton.h" -#include "ace/Thread_Mutex.h" -#include "Common.h" -#include "Map.h" -#include "GridStates.h" -#include "MapUpdater.h" - -class Transport; - -class MapManager : public Trinity::Singleton > -{ - - friend class Trinity::OperatorNew; - typedef UNORDERED_MAP MapMapType; - typedef std::pair::iterator, bool> MapMapPair; - - public: - - Map* CreateMap(uint32, const WorldObject* obj, uint32 instanceId); - Map const* CreateBaseMap(uint32 id) const { return const_cast(this)->_createBaseMap(id); } - Map* FindMap(uint32 mapid, uint32 instanceId = 0) const; - - uint16 GetAreaFlag(uint32 mapid, float x, float y, float z) const - { - Map const* m = CreateBaseMap(mapid); - return m->GetAreaFlag(x, y, z); - } - uint32 GetAreaId(uint32 mapid, float x, float y, float z) const - { - return Map::GetAreaIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid); - } - uint32 GetZoneId(uint32 mapid, float x, float y, float z) const - { - return Map::GetZoneIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid); - } - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) - { - Map::GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(mapid, x, y, z),mapid); - } - - void Initialize(void); - void Update(uint32); - - void SetGridCleanUpDelay(uint32 t) - { - if (t < MIN_GRID_DELAY) - i_gridCleanUpDelay = MIN_GRID_DELAY; - else - i_gridCleanUpDelay = t; - } - - void SetMapUpdateInterval(uint32 t) - { - if (t > MIN_MAP_UPDATE_DELAY) - t = MIN_MAP_UPDATE_DELAY; - - i_timer.SetInterval(t); - i_timer.Reset(); - } - - //void LoadGrid(int mapid, int instId, float x, float y, const WorldObject* obj, bool no_unload = false); - void UnloadAll(); - - static bool ExistMapAndVMap(uint32 mapid, float x, float y); - static bool IsValidMAP(uint32 mapid); - - static bool IsValidMapCoord(uint32 mapid, float x,float y) - { - return IsValidMAP(mapid) && Trinity::IsValidMapCoord(x,y); - } - - static bool IsValidMapCoord(uint32 mapid, float x,float y,float z) - { - return IsValidMAP(mapid) && Trinity::IsValidMapCoord(x,y,z); - } - - static bool IsValidMapCoord(uint32 mapid, float x,float y,float z,float o) - { - return IsValidMAP(mapid) && Trinity::IsValidMapCoord(x,y,z,o); - } - - static bool IsValidMapCoord(WorldLocation const& loc) - { - return IsValidMapCoord(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation()); - } - - void DoDelayedMovesAndRemoves(); - - void LoadTransports(); - - typedef std::set TransportSet; - TransportSet m_Transports; - - typedef std::map TransportMap; - TransportMap m_TransportsByMap; - - bool CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck = false); - void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y); - uint32 GenerateInstanceId() { return ++i_MaxInstanceId; } - void InitMaxInstanceId(); - void InitializeVisibilityDistanceInfo(); - - /* statistics */ - uint32 GetNumInstances(); - uint32 GetNumPlayersInInstances(); - - private: - // debugging code, should be deleted some day - void checkAndCorrectGridStatesArray(); // just for debugging to find some memory overwrites - GridState* i_GridStates[MAX_GRID_STATE]; // shadow entries to the global array in Map.cpp - int i_GridStateErrorCount; - private: - MapManager(); - ~MapManager(); - - MapManager(const MapManager &); - MapManager& operator=(const MapManager &); - - Map* _createBaseMap(uint32 id); - Map* _findMap(uint32 id) const - { - MapMapType::const_iterator iter = i_maps.find(id); - return (iter == i_maps.end() ? NULL : iter->second); - } - - typedef Trinity::ClassLevelLockable::Lock Guard; - uint32 i_gridCleanUpDelay; - MapMapType i_maps; - IntervalTimer i_timer; - - uint32 i_MaxInstanceId; - MapUpdater m_updater; -}; -#endif diff --git a/src/server/game/Map/MapRefManager.h b/src/server/game/Map/MapRefManager.h deleted file mode 100644 index 4337aa75fd9..00000000000 --- a/src/server/game/Map/MapRefManager.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _MAPREFMANAGER -#define _MAPREFMANAGER - -#include "Utilities/LinkedReference/RefManager.h" - -class MapReference; - -class MapRefManager : public RefManager -{ - public: - typedef LinkedListHead::Iterator< MapReference > iterator; - typedef LinkedListHead::Iterator< MapReference const > const_iterator; - - MapReference* getFirst() { return (MapReference*)RefManager::getFirst(); } - MapReference const* getFirst() const { return (MapReference const*)RefManager::getFirst(); } - MapReference* getLast() { return (MapReference*)RefManager::getLast(); } - MapReference const* getLast() const { return (MapReference const*)RefManager::getLast(); } - - iterator begin() { return iterator(getFirst()); } - iterator end() { return iterator(NULL); } - iterator rbegin() { return iterator(getLast()); } - iterator rend() { return iterator(NULL); } - const_iterator begin() const { return const_iterator(getFirst()); } - const_iterator end() const { return const_iterator(NULL); } -}; -#endif - diff --git a/src/server/game/Map/MapReference.h b/src/server/game/Map/MapReference.h deleted file mode 100644 index 7cd4fcde76c..00000000000 --- a/src/server/game/Map/MapReference.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _MAPREFERENCE_H -#define _MAPREFERENCE_H - -#include "Utilities/LinkedReference/Reference.h" -#include "Map.h" - -class MapReference : public Reference -{ - protected: - void targetObjectBuildLink() - { - // called from link() - getTarget()->m_mapRefManager.insertFirst(this); - getTarget()->m_mapRefManager.incSize(); - } - void targetObjectDestroyLink() - { - // called from unlink() - if (isValid()) getTarget()->m_mapRefManager.decSize(); - } - void sourceObjectDestroyLink() - { - // called from invalidate() - getTarget()->m_mapRefManager.decSize(); - } - public: - MapReference() : Reference() {} - ~MapReference() { unlink(); } - MapReference *next() { return (MapReference*)Reference::next(); } - MapReference const *next() const { return (MapReference const*)Reference::next(); } - MapReference *nockeck_prev() { return (MapReference*)Reference::nocheck_prev(); } - MapReference const *nocheck_prev() const { return (MapReference const*)Reference::nocheck_prev(); } -}; -#endif - diff --git a/src/server/game/Map/MapUpdater.cpp b/src/server/game/Map/MapUpdater.cpp deleted file mode 100644 index f9bb5e2bbbc..00000000000 --- a/src/server/game/Map/MapUpdater.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include "MapUpdater.h" -#include "DelayExecutor.h" -#include "Map.h" -#include "Database/DatabaseEnv.h" - -#include -#include - -class WDBThreadStartReq1 : public ACE_Method_Request -{ - public: - - WDBThreadStartReq1() - { - } - - virtual int call() - { - WorldDatabase.ThreadStart(); - return 0; - } -}; - -class WDBThreadEndReq1 : public ACE_Method_Request -{ - public: - - WDBThreadEndReq1() - { - } - - virtual int call() - { - WorldDatabase.ThreadEnd(); - return 0; - } -}; - -class MapUpdateRequest : public ACE_Method_Request -{ - private: - - Map& m_map; - MapUpdater& m_updater; - ACE_UINT32 m_diff; - - public: - - MapUpdateRequest(Map& m, MapUpdater& u, ACE_UINT32 d) - : m_map(m), m_updater(u), m_diff(d) - { - } - - virtual int call() - { - m_map.Update (m_diff); - m_updater.update_finished (); - return 0; - } -}; - -MapUpdater::MapUpdater() - : m_mutex(), m_condition(m_mutex), m_executor(), pending_requests(0) -{ -} - -MapUpdater::~MapUpdater() -{ - deactivate(); -} - -int MapUpdater::activate(size_t num_threads) -{ - return m_executor.activate((int)num_threads, new WDBThreadStartReq1, new WDBThreadEndReq1); -} - -int MapUpdater::deactivate() -{ - wait(); - - return m_executor.deactivate(); -} - -int MapUpdater::wait() -{ - ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, m_mutex, -1); - - while (pending_requests > 0) - m_condition.wait(); - - return 0; -} - -int MapUpdater::schedule_update(Map& map, ACE_UINT32 diff) -{ - ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, m_mutex, -1); - - ++pending_requests; - - if (m_executor.execute(new MapUpdateRequest(map, *this, diff)) == -1) - { - ACE_DEBUG((LM_ERROR, ACE_TEXT("(%t) \n"), ACE_TEXT("Failed to schedule Map Update"))); - - --pending_requests; - return -1; - } - - return 0; -} - -bool MapUpdater::activated() -{ - return m_executor.activated(); -} - -void MapUpdater::update_finished() -{ - ACE_GUARD(ACE_Thread_Mutex, guard, m_mutex); - - if (pending_requests == 0) - { - ACE_ERROR((LM_ERROR, ACE_TEXT("(%t)\n"), ACE_TEXT("MapUpdater::update_finished BUG, report to devs"))); - return; - } - - --pending_requests; - - m_condition.broadcast(); -} diff --git a/src/server/game/Map/MapUpdater.h b/src/server/game/Map/MapUpdater.h deleted file mode 100644 index f301b15ca2f..00000000000 --- a/src/server/game/Map/MapUpdater.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _MAP_UPDATER_H_INCLUDED -#define _MAP_UPDATER_H_INCLUDED - -#include -#include - -#include "DelayExecutor.h" - -class Map; - -class MapUpdater -{ - public: - - MapUpdater(); - virtual ~MapUpdater(); - - friend class MapUpdateRequest; - - int schedule_update(Map& map, ACE_UINT32 diff); - - int wait(); - - int activate(size_t num_threads); - - int deactivate(); - - bool activated(); - - private: - - DelayExecutor m_executor; - ACE_Condition_Thread_Mutex m_condition; - ACE_Thread_Mutex m_mutex; - size_t pending_requests; - - void update_finished(); -}; - -#endif //_MAP_UPDATER_H_INCLUDED diff --git a/src/server/game/Map/ObjectPosSelector.cpp b/src/server/game/Map/ObjectPosSelector.cpp deleted file mode 100644 index 899dfec3fdb..00000000000 --- a/src/server/game/Map/ObjectPosSelector.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ObjectPosSelector.h" - -ObjectPosSelector::ObjectPosSelector(float x,float y,float size,float dist) -: m_center_x(x),m_center_y(y),m_size(size),m_dist(dist) -{ - m_anglestep = acos(m_dist/(m_dist+2*m_size)); - - m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].end(); - m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].end(); - - m_smallStepAngle[USED_POS_PLUS] = 0; - m_smallStepAngle[USED_POS_MINUS] = 0; - - m_smallStepOk[USED_POS_PLUS] = false; - m_smallStepOk[USED_POS_MINUS] = false; - - m_smallStepNextUsedPos[USED_POS_PLUS] = NULL; - m_smallStepNextUsedPos[USED_POS_MINUS] = NULL; -} - -ObjectPosSelector::UsedPosList::value_type const* ObjectPosSelector::nextUsedPos(UsedPosType uptype) -{ - UsedPosList::const_iterator itr = m_nextUsedPos[uptype]; - if(itr!=m_UsedPosLists[uptype].end()) - ++itr; - - if(itr==m_UsedPosLists[uptype].end()) - { - if(!m_UsedPosLists[~uptype].empty()) - return &*m_UsedPosLists[~uptype].rbegin(); - else - return NULL; - } - else - return &*itr; -} - -void ObjectPosSelector::AddUsedPos(float size,float angle,float dist) -{ - if(angle>=0) - m_UsedPosLists[USED_POS_PLUS].insert(UsedPosList::value_type(angle,UsedPos(1.0,size,dist))); - else - m_UsedPosLists[USED_POS_MINUS].insert(UsedPosList::value_type(-angle,UsedPos(-1.0,size,dist))); -} - -void ObjectPosSelector::InitializeAngle() -{ - m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].begin(); - m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].begin(); - - m_smallStepAngle[USED_POS_PLUS] = 0; - m_smallStepAngle[USED_POS_MINUS] = 0; - - m_smallStepOk[USED_POS_PLUS] = true; - m_smallStepOk[USED_POS_MINUS] = true; -} - -bool ObjectPosSelector::FirstAngle(float& angle) -{ - if(m_UsedPosLists[USED_POS_PLUS].empty() && !m_UsedPosLists[USED_POS_MINUS].empty() ) - return NextAngleFor(*m_UsedPosLists[USED_POS_MINUS].begin(),1.0,USED_POS_PLUS,angle); - else if(m_UsedPosLists[USED_POS_MINUS].empty() && !m_UsedPosLists[USED_POS_PLUS].empty() ) - return NextAngleFor(*m_UsedPosLists[USED_POS_PLUS].begin(),-1.0,USED_POS_MINUS,angle); - - return false; -} - -bool ObjectPosSelector::NextAngle(float& angle) -{ - while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() || - m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() || - m_smallStepOk[USED_POS_PLUS] || m_smallStepOk[USED_POS_MINUS] ) - { - // calculate next possible angle - if(NextPosibleAngle(angle)) - return true; - } - - return false; -} - -bool ObjectPosSelector::NextUsedAngle(float& angle) -{ - while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() || - m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() ) - { - // calculate next possible angle - if(!NextPosibleAngle(angle)) - return true; - } - - return false; -} - -bool ObjectPosSelector::NextPosibleAngle( float& angle ) -{ - // ++ direction less updated - if( m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() && - (m_nextUsedPos[USED_POS_MINUS]==m_UsedPosLists[USED_POS_MINUS].end() || m_nextUsedPos[USED_POS_PLUS]->first <= m_nextUsedPos[USED_POS_MINUS]->first) ) - { - bool ok; - if(m_smallStepOk[USED_POS_PLUS]) - ok = NextSmallStepAngle(1.0,USED_POS_PLUS,angle); - else - ok = NextAngleFor(*m_nextUsedPos[USED_POS_PLUS],1.0,USED_POS_PLUS,angle); - - if(!ok) - ++m_nextUsedPos[USED_POS_PLUS]; // increase. only at fail (original or checked) - return ok; - } - // -- direction less updated - else if( m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end()) - { - bool ok; - if(m_smallStepOk[USED_POS_MINUS]) - ok = NextSmallStepAngle(-1.0,USED_POS_MINUS,angle); - else - ok = NextAngleFor(*m_nextUsedPos[USED_POS_MINUS],-1.0,USED_POS_MINUS,angle); - - if(!ok) - ++m_nextUsedPos[USED_POS_MINUS]; - return ok; - } - else // both list empty - { - if( m_smallStepOk[USED_POS_PLUS] && (!m_smallStepOk[USED_POS_MINUS] || m_smallStepAngle[USED_POS_PLUS] <= m_smallStepAngle[USED_POS_MINUS]) ) - { - return NextSmallStepAngle(1.0,USED_POS_PLUS,angle); - } - // -- direction less updated - else if( m_smallStepOk[USED_POS_MINUS] ) - { - return NextSmallStepAngle(-1.0,USED_POS_MINUS,angle); - } - } - - // no angles - return false; -} diff --git a/src/server/game/Map/ObjectPosSelector.h b/src/server/game/Map/ObjectPosSelector.h deleted file mode 100644 index 84050611121..00000000000 --- a/src/server/game/Map/ObjectPosSelector.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _OBJECT_POS_SELECTOR_H -#define _OBJECT_POS_SELECTOR_H - -#include - -#include - -enum UsedPosType { USED_POS_PLUS, USED_POS_MINUS }; - -inline UsedPosType operator ~(UsedPosType uptype) -{ - return uptype==USED_POS_PLUS ? USED_POS_MINUS : USED_POS_PLUS; -} - -struct ObjectPosSelector -{ - struct UsedPos - { - UsedPos(float sign_, float size_,float dist_) : sign(sign_), size(size_),dist(dist_) {} - - float sign; - - float size; // size of point - float dist; // dist to central point (including central point size) - }; - - typedef std::multimap UsedPosList; // abs(angle)->Node - - ObjectPosSelector(float x,float y,float size,float dist); - - void AddUsedPos(float size,float angle,float dist); - void InitializeAngle(); - - bool FirstAngle(float& angle); - bool NextAngle(float& angle); - bool NextUsedAngle(float& angle); - - bool NextPosibleAngle( float& angle ); - - bool CheckAngle(UsedPosList::value_type const& nextUsedPos, float sign, float angle ) const - { - float angle_step2 = GetAngle(nextUsedPos.second); - - float next_angle = nextUsedPos.first; - if(nextUsedPos.second.sign * sign < 0) // last node from diff. list (-pi+alpha) - next_angle = 2*M_PI-next_angle; // move to positive - - return fabs(angle)+angle_step2 <= next_angle; - } - - bool CheckOriginal() const - { - return (m_UsedPosLists[USED_POS_PLUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_PLUS].begin(),1.0,0)) && - (m_UsedPosLists[USED_POS_MINUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_MINUS].begin(),-1.0,0)); - } - - bool IsNonBalanced() const { return m_UsedPosLists[USED_POS_PLUS].empty() != m_UsedPosLists[USED_POS_MINUS].empty(); } - - bool NextAngleFor( UsedPosList::value_type const& usedPos, float sign, UsedPosType uptype, float &angle ) - { - float angle_step = GetAngle(usedPos.second); - - // next possible angle - angle = usedPos.first * usedPos.second.sign + angle_step * sign; - - UsedPosList::value_type const* nextNode = nextUsedPos(uptype); - if(nextNode) - { - // if next node permit use selected angle, then do it - if(!CheckAngle(*nextNode, sign, angle)) - { - m_smallStepOk[uptype] = false; - return false; - } - } - - // possible more points - m_smallStepOk[uptype] = true; - m_smallStepAngle[uptype] = angle; - m_smallStepNextUsedPos[uptype] = nextNode; - - return true; - } - - bool NextSmallStepAngle( float sign, UsedPosType uptype, float &angle ) - { - // next possible angle - angle = m_smallStepAngle[uptype] + m_anglestep * sign; - - if(fabs(angle) > M_PI) - { - m_smallStepOk[uptype] = false; - return false; - } - - if(m_smallStepNextUsedPos[uptype]) - { - if(fabs(angle) >= m_smallStepNextUsedPos[uptype]->first) - { - m_smallStepOk[uptype] = false; - return false; - } - - // if next node permit use selected angle, then do it - if(!CheckAngle(*m_smallStepNextUsedPos[uptype], sign, angle)) - { - m_smallStepOk[uptype] = false; - return false; - } - } - - // possible more points - m_smallStepAngle[uptype] = angle; - return true; - } - - // next used post for m_nextUsedPos[uptype] - UsedPosList::value_type const* nextUsedPos(UsedPosType uptype); - - // angle from used pos to next possible free pos - float GetAngle(UsedPos const& usedPos) const { return acos(m_dist/(usedPos.dist+usedPos.size+m_size)); } - - float m_center_x; - float m_center_y; - float m_size; // size of object in center - float m_dist; // distance for searching pos (including central object size) - float m_anglestep; - - UsedPosList m_UsedPosLists[2]; - UsedPosList::const_iterator m_nextUsedPos[2]; - - // field for small step from first after next used pos until next pos - float m_smallStepAngle[2]; - bool m_smallStepOk[2]; - UsedPosList::value_type const* m_smallStepNextUsedPos[2]; -}; -#endif diff --git a/src/server/game/Map/ZoneScript.h b/src/server/game/Map/ZoneScript.h deleted file mode 100644 index ab74c8aa5d4..00000000000 --- a/src/server/game/Map/ZoneScript.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef ZONE_SCRIPT_H_ -#define ZONE_SCRIPT_H_ - -#include "Common.h" -#include "Creature.h" - -//struct CreatureData; -class Creature; -class GameObject; - -class ZoneScript -{ - public: - explicit ZoneScript() {} - - virtual uint32 GetCreatureEntry(uint32 /*guidlow*/, const CreatureData *data) { return data->id; } - virtual uint32 GetGameObjectEntry(uint32 /*guidlow*/, uint32 entry) { return entry; } - - virtual void OnCreatureCreate(Creature *, bool /*add*/) {} - virtual void OnGameObjectCreate(GameObject * /*go*/, bool /*add*/) {} - - //All-purpose data storage 64 bit - virtual uint64 GetData64(uint32 /*DataId*/) { return 0; } - virtual void SetData64(uint32 /*DataId*/, uint64 /*Value*/) {} - - //All-purpose data storage 32 bit - virtual uint32 GetData(uint32 /*DataId*/) { return 0; } - virtual void SetData(uint32 /*DataId*/, uint32 /*Value*/) {} - - virtual void ProcessEvent(GameObject * /*obj*/, uint32 /*eventId*/) {} -}; - -#endif \ No newline at end of file diff --git a/src/server/game/Maps/Cell/Cell.h b/src/server/game/Maps/Cell/Cell.h new file mode 100644 index 00000000000..49e0329ace6 --- /dev/null +++ b/src/server/game/Maps/Cell/Cell.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CELL_H +#define TRINITY_CELL_H + +#include + +#include "GameSystem/TypeContainer.h" +#include "GameSystem/TypeContainerVisitor.h" + +#include "GridDefines.h" + +class Map; +class WorldObject; + +enum District +{ + UPPER_DISTRICT = 1, + LOWER_DISTRICT = 1 << 1, + LEFT_DISTRICT = 1 << 2, + RIGHT_DISTRICT = 1 << 3, + CENTER_DISTRICT = 1 << 4, + UPPER_LEFT_DISTRICT = (UPPER_DISTRICT | LEFT_DISTRICT), + UPPER_RIGHT_DISTRICT = (UPPER_DISTRICT | RIGHT_DISTRICT), + LOWER_LEFT_DISTRICT = (LOWER_DISTRICT | LEFT_DISTRICT), + LOWER_RIGHT_DISTRICT = (LOWER_DISTRICT | RIGHT_DISTRICT), + ALL_DISTRICT = (UPPER_DISTRICT | LOWER_DISTRICT | LEFT_DISTRICT | RIGHT_DISTRICT | CENTER_DISTRICT) +}; + +struct CellArea +{ + CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {} + CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {} + bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; } + + void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const + { + begin_cell << left_offset; + begin_cell -= lower_offset; + end_cell >> right_offset; + end_cell += upper_offset; + } + + int right_offset; + int left_offset; + int upper_offset; + int lower_offset; +}; + +struct Cell +{ + Cell() { data.All = 0; } + Cell(const Cell &cell) { data.All = cell.data.All; } + explicit Cell(CellPair const& p); + + void operator|=(Cell &cell) + { + data.Part.reserved = 0; + cell.data.Part.reserved = 0; + uint32 x, y, old_x, old_y; + Compute(x, y); + cell.Compute(old_x, old_y); + + if (std::abs(int(x-old_x)) > 1 || std::abs(int(y-old_y)) > 1) + { + data.Part.reserved = ALL_DISTRICT; + cell.data.Part.reserved = ALL_DISTRICT; + return; + } + + if (x < old_x) + { + data.Part.reserved |= LEFT_DISTRICT; + cell.data.Part.reserved |= RIGHT_DISTRICT; + } + else if (old_x < x) + { + data.Part.reserved |= RIGHT_DISTRICT; + cell.data.Part.reserved |= LEFT_DISTRICT; + } + if (y < old_y) + { + data.Part.reserved |= UPPER_DISTRICT; + cell.data.Part.reserved |= LOWER_DISTRICT; + } + else if (old_y < y) + { + data.Part.reserved |= LOWER_DISTRICT; + cell.data.Part.reserved |= UPPER_DISTRICT; + } + } + + void Compute(uint32 &x, uint32 &y) const + { + x = data.Part.grid_x*MAX_NUMBER_OF_CELLS + data.Part.cell_x; + y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; + } + + bool DiffCell(const Cell &cell) const + { + return(data.Part.cell_x != cell.data.Part.cell_x || + data.Part.cell_y != cell.data.Part.cell_y); + } + + bool DiffGrid(const Cell &cell) const + { + return(data.Part.grid_x != cell.data.Part.grid_x || + data.Part.grid_y != cell.data.Part.grid_y); + } + + uint32 CellX() const { return data.Part.cell_x; } + uint32 CellY() const { return data.Part.cell_y; } + uint32 GridX() const { return data.Part.grid_x; } + uint32 GridY() const { return data.Part.grid_y; } + bool NoCreate() const { return data.Part.nocreate; } + void SetNoCreate() { data.Part.nocreate = 1; } + + CellPair cellPair() const + { + return CellPair( + data.Part.grid_x*MAX_NUMBER_OF_CELLS+data.Part.cell_x, + data.Part.grid_y*MAX_NUMBER_OF_CELLS+data.Part.cell_y); + } + + Cell& operator=(const Cell &cell) + { + this->data.All = cell.data.All; + return *this; + } + + bool operator == (const Cell &cell) const { return (data.All == cell.data.All); } + bool operator != (const Cell &cell) const { return !operator == (cell); } + union + { + struct + { + unsigned grid_x : 6; + unsigned grid_y : 6; + unsigned cell_x : 6; + unsigned cell_y : 6; + unsigned nocreate : 1; + unsigned reserved : 7; + } Part; + uint32 All; + } data; + + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &) const; + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, const WorldObject&, float) const; + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, float, float, float) const; + + static CellArea CalculateCellArea(const WorldObject &obj, float radius); + static CellArea CalculateCellArea(float x, float y, float radius); + +private: + template void VisitCircle(TypeContainerVisitor &, Map &, const CellPair&, const CellPair&) const; +}; + +#endif + diff --git a/src/server/game/Maps/Cell/CellImpl.h b/src/server/game/Maps/Cell/CellImpl.h new file mode 100644 index 00000000000..d906e81a5c9 --- /dev/null +++ b/src/server/game/Maps/Cell/CellImpl.h @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CELLIMPL_H +#define TRINITY_CELLIMPL_H + +#include + +#include "Cell.h" +#include "Map.h" +#include "Object.h" + +inline Cell::Cell(CellPair const& p) +{ + data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS; + data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; + data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; + data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; + data.Part.nocreate = 0; + data.Part.reserved = 0; +} + +template +inline void +Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m) const +{ + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + return; + + uint16 district = (District)this->data.Part.reserved; + if (district == CENTER_DISTRICT) + { + m.Visit(*this, visitor); + return; + } + + // set up the cell range based on the district + // the overloaded operators handle range checking + CellPair begin_cell = standing_cell; + CellPair end_cell = standing_cell; + + switch(district) + { + case ALL_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right + break; + } + case UPPER_LEFT_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + break; + } + case UPPER_RIGHT_DISTRICT: + { + begin_cell -= 1; // up + end_cell >> 1; // right + break; + } + case LOWER_LEFT_DISTRICT: + { + begin_cell << 1; // left + end_cell += 1; // down + break; + } + case LOWER_RIGHT_DISTRICT: + { + end_cell >> 1; end_cell += 1; // lower right + break; + } + case LEFT_DISTRICT: + { + begin_cell -= 1; // up + end_cell >> 1; end_cell += 1; // lower right + break; + } + case RIGHT_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell += 1; // down + break; + } + case UPPER_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; // right + break; + } + case LOWER_DISTRICT: + { + begin_cell << 1; // left + end_cell >> 1; end_cell += 1; // lower right + break; + } + default: + { + assert(false); + break; + } + } + + // loop the cell range + for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++) + { + CellPair cell_pair(x,y); + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } +} + +inline int CellHelper(const float radius) +{ + if (radius < 1.0f) + return 0; + + return (int)ceilf(radius/SIZE_OF_GRID_CELL); +} + +inline CellArea Cell::CalculateCellArea(const WorldObject &obj, float radius) +{ + return Cell::CalculateCellArea(obj.GetPositionX(), obj.GetPositionY(), radius); +} + +inline CellArea Cell::CalculateCellArea(float x, float y, float radius) +{ + if (radius <= 0.0f) + return CellArea(); + + //lets calculate object coord offsets from cell borders. + //TODO: add more correct/generic method for this task + const float x_offset = (x - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + const float y_offset = (y - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + + const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f); + const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f); + + const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + + const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET; + //lets calculate upper/lower/right/left corners for cell search + int right = CellHelper(tmp_diff + x_off); + int left = CellHelper(tmp_diff - x_off); + int upper = CellHelper(tmp_diff + y_off); + int lower = CellHelper(tmp_diff - y_off); + + return CellArea(right, left, upper, lower); +} + +template +inline void +Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m, float radius, float x_off, float y_off) const +{ + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + return; + + //no jokes here... Actually placing ASSERT() here was good idea, but + //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?) + //maybe it is better to just return when radius <= 0.0f? + if (radius <= 0.0f) + { + m.Visit(*this, visitor); + return; + } + //lets limit the upper value for search radius + if (radius > 333.0f) + radius = 333.0f; + + //lets calculate object coord offsets from cell borders. + CellArea area = Cell::CalculateCellArea(x_off, y_off, radius); + //if radius fits inside standing cell + if (!area) + { + m.Visit(*this, visitor); + return; + } + + CellPair begin_cell = standing_cell; + CellPair end_cell = standing_cell; + + area.ResizeBorders(begin_cell, end_cell); + //visit all cells, found in CalculateCellArea() + //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle + //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values + //there are nothing to optimize because SIZE_OF_GRID_CELL is too big... + if (((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4)) + { + VisitCircle(visitor, m, begin_cell, end_cell); + return; + } + + //ALWAYS visit standing cell first!!! Since we deal with small radiuses + //it is very essential to call visitor for standing cell firstly... + m.Visit(*this, visitor); + + // loop the cell range + for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + CellPair cell_pair(x,y); + //lets skip standing cell since we already visited it + if (cell_pair != standing_cell) + { + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } + } +} + +template +inline void +Cell::Visit(const CellPair& l, TypeContainerVisitor &visitor, Map &m, const WorldObject &obj, float radius) const +{ + //we should increase search radius by object's radius, otherwise + //we could have problems with huge creatures, which won't attack nearest players etc + Visit(l, visitor, m, radius + obj.GetObjectSize(), obj.GetPositionX(), obj.GetPositionY()); +} + +template +inline void +Cell::VisitCircle(TypeContainerVisitor &visitor, Map &m, const CellPair& begin_cell, const CellPair& end_cell) const +{ + //here is an algorithm for 'filling' circum-squared octagon + uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f); + //lets calculate x_start/x_end coords for central strip... + const uint32 x_start = begin_cell.x_coord + x_shift; + const uint32 x_end = end_cell.x_coord - x_shift; + + //visit central strip with constant width... + for (uint32 x = x_start; x <= x_end; ++x) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + CellPair cell_pair(x,y); + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } + + //if x_shift == 0 then we have too small cell area, which were already + //visited at previous step, so just return from procedure... + if (x_shift == 0) + return; + + uint32 y_start = end_cell.y_coord; + uint32 y_end = begin_cell.y_coord; + //now we are visiting borders of an octagon... + for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step) + { + //each step reduces strip height by 2 cells... + y_end += 1; + y_start -= 1; + for (uint32 y = y_start; y >= y_end; --y) + { + //we visit cells symmetrically from both sides, heading from center to sides and from up to bottom + //e.g. filling 2 trapezoids after filling central cell strip... + CellPair cell_pair_left(x_start - step, y); + Cell r_zone_left(cell_pair_left); + r_zone_left.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone_left, visitor); + + //right trapezoid cell visit + CellPair cell_pair_right(x_end + step, y); + Cell r_zone_right(cell_pair_right); + r_zone_right.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone_right, visitor); + } + } +} +#endif + diff --git a/src/server/game/Maps/Grid/GridDefines.h b/src/server/game/Maps/Grid/GridDefines.h new file mode 100644 index 00000000000..5269d0a094d --- /dev/null +++ b/src/server/game/Maps/Grid/GridDefines.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDDEFINES_H +#define TRINITY_GRIDDEFINES_H + +#include "Common.h" +#include "GameSystem/NGrid.h" +#include + +// Forward class definitions +class Corpse; +class Creature; +class DynamicObject; +class GameObject; +class Pet; +class Player; + +#define MAX_NUMBER_OF_CELLS 8 + +#define MAX_NUMBER_OF_GRIDS 64 + +#define SIZE_OF_GRIDS 533.33333f +#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2) + +#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) + +#define MIN_GRID_DELAY (MINUTE*IN_MILISECONDS) +#define MIN_MAP_UPDATE_DELAY 50 + +#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) + +#define CENTER_GRID_CELL_ID (MAX_NUMBER_OF_CELLS*MAX_NUMBER_OF_GRIDS/2) +#define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2) + +#define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) + +#define MAP_RESOLUTION 128 + +#define MAP_SIZE (SIZE_OF_GRIDS*MAX_NUMBER_OF_GRIDS) +#define MAP_HALFSIZE (MAP_SIZE/2) + +// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case) +typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes; +typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes; + +typedef GridRefManager CorpseMapType; +typedef GridRefManager CreatureMapType; +typedef GridRefManager DynamicObjectMapType; +typedef GridRefManager GameObjectMapType; +typedef GridRefManager PlayerMapType; + +typedef Grid GridType; +typedef NGrid NGridType; + +typedef TypeMapContainer GridTypeMapContainer; +typedef TypeMapContainer WorldTypeMapContainer; + +template +struct CoordPair +{ + CoordPair(uint32 x=0, uint32 y=0) : x_coord(x), y_coord(y) {} + CoordPair(const CoordPair &obj) : x_coord(obj.x_coord), y_coord(obj.y_coord) {} + bool operator == (const CoordPair &obj) const { return (obj.x_coord == x_coord && obj.y_coord == y_coord); } + bool operator != (const CoordPair &obj) const { return !operator == (obj); } + CoordPair& operator=(const CoordPair &obj) + { + x_coord = obj.x_coord; + y_coord = obj.y_coord; + return *this; + } + + void operator<<(const uint32 val) + { + if (x_coord > val) + x_coord -= val; + else + x_coord = 0; + } + + void operator>>(const uint32 val) + { + if (x_coord+val < LIMIT) + x_coord += val; + else + x_coord = LIMIT - 1; + } + + void operator-=(const uint32 val) + { + if (y_coord > val) + y_coord -= val; + else + y_coord = 0; + } + + void operator+=(const uint32 val) + { + if (y_coord+val < LIMIT) + y_coord += val; + else + y_coord = LIMIT - 1; + } + + uint32 x_coord; + uint32 y_coord; +}; + +typedef CoordPair GridPair; +typedef CoordPair CellPair; + +namespace Trinity +{ + template + inline RET_TYPE Compute(float x, float y, float center_offset, float size) + { + // calculate and store temporary values in double format for having same result as same mySQL calculations + double x_offset = (double(x) - center_offset)/size; + double y_offset = (double(y) - center_offset)/size; + + int x_val = int(x_offset+CENTER_VAL + 0.5); + int y_val = int(y_offset+CENTER_VAL + 0.5); + return RET_TYPE(x_val, y_val); + } + + inline GridPair ComputeGridPair(float x, float y) + { + return Compute(x, y, CENTER_GRID_OFFSET, SIZE_OF_GRIDS); + } + + inline CellPair ComputeCellPair(float x, float y) + { + return Compute(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL); + } + + inline CellPair ComputeCellPair(float x, float y, float &x_off, float &y_off) + { + double x_offset = (double(x) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + double y_offset = (double(y) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + + int x_val = int(x_offset + CENTER_GRID_CELL_ID + 0.5); + int y_val = int(y_offset + CENTER_GRID_CELL_ID + 0.5); + x_off = (float(x_offset) - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + y_off = (float(y_offset) - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + return CellPair(x_val, y_val); + } + + inline void NormalizeMapCoord(float &c) + { + if (c > MAP_HALFSIZE - 0.5) + c = MAP_HALFSIZE - 0.5; + else if (c < -(MAP_HALFSIZE - 0.5)) + c = -(MAP_HALFSIZE - 0.5); + } + + inline bool IsValidMapCoord(float c) + { + return finite(c) && (std::fabs(c) <= MAP_HALFSIZE - 0.5); + } + + inline bool IsValidMapCoord(float x, float y) + { + return IsValidMapCoord(x) && IsValidMapCoord(y); + } + + inline bool IsValidMapCoord(float x, float y, float z) + { + return IsValidMapCoord(x,y) && finite(z); + } + + inline bool IsValidMapCoord(float x, float y, float z, float o) + { + return IsValidMapCoord(x,y,z) && finite(o); + } +} +#endif diff --git a/src/server/game/Maps/Grid/GridNotifiers.cpp b/src/server/game/Maps/Grid/GridNotifiers.cpp new file mode 100644 index 00000000000..b10dfa8791e --- /dev/null +++ b/src/server/game/Maps/Grid/GridNotifiers.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "UpdateData.h" +#include "Item.h" +#include "Map.h" +#include "Transports.h" +#include "ObjectAccessor.h" +#include "CellImpl.h" + +using namespace Trinity; + +void +VisibleNotifier::SendToSelf() +{ + // at this moment i_clientGUIDs have guids that not iterate at grid level checks + // but exist one case when this possible and object not out of range: transports + if (Transport* transport = i_player.GetTransport()) + for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr != transport->GetPassengers().end();++itr) + { + if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end()) + { + vis_guids.erase((*itr)->GetGUID()); + + i_player.UpdateVisibilityOf((*itr), i_data, i_visibleNow); + + if (!(*itr)->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + (*itr)->UpdateVisibilityOf(&i_player); + } + } + + for (Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end(); ++it) + { + i_player.m_clientGUIDs.erase(*it); + i_data.AddOutOfRangeGUID(*it); + + if (IS_PLAYER_GUID(*it)) + { + Player* plr = ObjectAccessor::FindPlayer(*it); + if (plr && plr->IsInWorld() && !plr->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + plr->UpdateVisibilityOf(&i_player); + } + } + + if (!i_data.HasData()) + return; + + WorldPacket packet; + i_data.BuildPacket(&packet); + i_player.GetSession()->SendPacket(&packet); + + for (std::set::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it) + i_player.SendInitialVisiblePackets(*it); +} + +void +VisibleChangesNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if (iter->getSource() == &i_object) + continue; + + iter->getSource()->UpdateVisibilityOf(&i_object); + + if (!iter->getSource()->GetSharedVisionList().empty()) + for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + (*i)->UpdateVisibilityOf(&i_object); + } +} + +void +VisibleChangesNotifier::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if (!iter->getSource()->GetSharedVisionList().empty()) + for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + (*i)->UpdateVisibilityOf(&i_object); +} + +void +VisibleChangesNotifier::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) + if (Player* caster = (Player*)iter->getSource()->GetCaster()) + if (caster->m_seer == iter->getSource()) + caster->UpdateVisibilityOf(&i_object); +} + +inline void CreatureUnitRelocationWorker(Creature* c, Unit* u) +{ + if (!u->isAlive() || !c->isAlive() || c == u || u->isInFlight()) + return; + + if (c->HasReactState(REACT_AGGRESSIVE) && !c->hasUnitState(UNIT_STAT_SIGHTLESS)) + if (c->_IsWithinDist(u, c->m_SightDistance, true) && c->IsAIEnabled) + c->AI()->MoveInLineOfSight_Safe(u); +} + +void PlayerRelocationNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Player* plr = iter->getSource(); + + vis_guids.erase(plr->GetGUID()); + + i_player.UpdateVisibilityOf(plr,i_data,i_visibleNow); + + if (plr->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + plr->UpdateVisibilityOf(&i_player); + } +} + +void PlayerRelocationNotifier::Visit(CreatureMapType &m) +{ + bool relocated_for_ai = (&i_player == i_player.m_seer); + + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Creature * c = iter->getSource(); + + vis_guids.erase(c->GetGUID()); + + i_player.UpdateVisibilityOf(c,i_data,i_visibleNow); + + if (relocated_for_ai && !c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + CreatureUnitRelocationWorker(c, &i_player); + } +} + +void CreatureRelocationNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Player * pl = iter->getSource(); + + if (!pl->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + pl->UpdateVisibilityOf(&i_creature); + + CreatureUnitRelocationWorker(&i_creature, pl); + } +} + +void CreatureRelocationNotifier::Visit(CreatureMapType &m) +{ + if (!i_creature.isAlive()) + return; + + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Creature* c = iter->getSource(); + CreatureUnitRelocationWorker(&i_creature, c); + + if (!c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + CreatureUnitRelocationWorker(c, &i_creature); + } +} + +void DelayedUnitRelocation::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Creature * unit = iter->getSource(); + if (!unit->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + CreatureRelocationNotifier relocate(*unit); + + TypeContainerVisitor c2world_relocation(relocate); + TypeContainerVisitor c2grid_relocation(relocate); + + cell.Visit(p, c2world_relocation, i_map, *unit, i_radius); + cell.Visit(p, c2grid_relocation, i_map, *unit, i_radius); + } +} + +void DelayedUnitRelocation::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Player * player = iter->getSource(); + WorldObject const *viewPoint = player->m_seer; + + if (!viewPoint->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + if (player != viewPoint && !viewPoint->IsPositionValid()) + continue; + + CellPair pair2(Trinity::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY())); + Cell cell2(pair2); + //cell.SetNoCreate(); need load cells around viewPoint or player, that's why its commented + + PlayerRelocationNotifier relocate(*player); + TypeContainerVisitor c2world_relocation(relocate); + TypeContainerVisitor c2grid_relocation(relocate); + + cell2.Visit(pair2, c2world_relocation, i_map, *viewPoint, i_radius); + cell2.Visit(pair2, c2grid_relocation, i_map, *viewPoint, i_radius); + + relocate.SendToSelf(); + } +} + +void AIRelocationNotifier::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Creature *c = iter->getSource(); + CreatureUnitRelocationWorker(c, &i_unit); + if (isCreature) + CreatureUnitRelocationWorker((Creature*)&i_unit, c); + } +} + +void +MessageDistDeliverer::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Player *target = iter->getSource(); + if (!target->InSamePhase(i_phaseMask)) + continue; + + if (target->GetExactDistSq(i_source) > i_distSq) + continue; + + // Send packet to all who are sharing the player's vision + if (!target->GetSharedVisionList().empty()) + { + SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); + for (; i != target->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == target) + SendPacket(*i); + } + + if (target->m_seer == target || target->GetVehicle()) + SendPacket(target); + } +} + +void +MessageDistDeliverer::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) + continue; + + // Send packet to all who are sharing the creature's vision + if (!iter->getSource()->GetSharedVisionList().empty()) + { + SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + for (; i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + SendPacket(*i); + } + } +} + +void +MessageDistDeliverer::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) + continue; + + if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) + { + // Send packet back to the caster if the caster has vision of dynamic object + Player* caster = (Player*)iter->getSource()->GetCaster(); + if (caster && caster->m_seer == iter->getSource()) + SendPacket(caster); + } + } +} + +/* +void +MessageDistDeliverer::VisitObject(Player* plr) +{ + if (!i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam())) + { + SendPacket(plr); + } +} +*/ + +template void +ObjectUpdater::Visit(GridRefManager &m) +{ + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (iter->getSource()->IsInWorld()) + iter->getSource()->Update(i_timeDiff); + } +} + +bool CannibalizeObjectCheck::operator()(Corpse* u) +{ + // ignore bones + if (u->GetType() == CORPSE_BONES) + return false; + + Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); + + if (!owner || i_funit->IsFriendlyTo(owner)) + return false; + + if (i_funit->IsWithinDistInMap(u, i_range)) + return true; + + return false; +} + +template void ObjectUpdater::Visit(GameObjectMapType &); +template void ObjectUpdater::Visit(DynamicObjectMapType &); diff --git a/src/server/game/Maps/Grid/GridNotifiers.h b/src/server/game/Maps/Grid/GridNotifiers.h new file mode 100644 index 00000000000..b0abf0aae79 --- /dev/null +++ b/src/server/game/Maps/Grid/GridNotifiers.h @@ -0,0 +1,1232 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDNOTIFIERS_H +#define TRINITY_GRIDNOTIFIERS_H + +#include "ObjectGridLoader.h" +#include "UpdateData.h" +#include + +#include "Corpse.h" +#include "Object.h" +#include "DynamicObject.h" +#include "GameObject.h" +#include "Player.h" +#include "Unit.h" +#include "CreatureAI.h" + +class Player; +//class Map; + +namespace Trinity +{ + struct VisibleNotifier + { + Player &i_player; + UpdateData i_data; + std::set i_visibleNow; + Player::ClientGUIDs vis_guids; + + VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) {} + template void Visit(GridRefManager &m); + void SendToSelf(void); + }; + + struct VisibleChangesNotifier + { + WorldObject &i_object; + + explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {} + template void Visit(GridRefManager &) {} + void Visit(PlayerMapType &); + void Visit(CreatureMapType &); + void Visit(DynamicObjectMapType &); + }; + + struct PlayerRelocationNotifier : public VisibleNotifier + { + PlayerRelocationNotifier(Player &pl) : VisibleNotifier(pl) {} + + template void Visit(GridRefManager &m) { VisibleNotifier::Visit(m); } + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct CreatureRelocationNotifier + { + Creature &i_creature; + CreatureRelocationNotifier(Creature &c) : i_creature(c) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct DelayedUnitRelocation + { + Map &i_map; + Cell &cell; + CellPair &p; + const float i_radius; + DelayedUnitRelocation(Cell &c, CellPair &pair, Map &map, float radius) : + cell(c), p(pair), i_map(map), i_radius(radius) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct AIRelocationNotifier + { + Unit &i_unit; + bool isCreature; + explicit AIRelocationNotifier(Unit &unit) : i_unit(unit), isCreature(unit.GetTypeId() == TYPEID_UNIT) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + }; + + struct GridUpdater + { + GridType &i_grid; + uint32 i_timeDiff; + GridUpdater(GridType &grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) {} + + template void updateObjects(GridRefManager &m) + { + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + iter->getSource()->Update(i_timeDiff); + } + + void Visit(PlayerMapType &m) { updateObjects(m); } + void Visit(CreatureMapType &m){ updateObjects(m); } + void Visit(GameObjectMapType &m) { updateObjects(m); } + void Visit(DynamicObjectMapType &m) { updateObjects(m); } + void Visit(CorpseMapType &m) { updateObjects(m); } + }; + + struct MessageDistDeliverer + { + WorldObject *i_source; + WorldPacket *i_message; + uint32 i_phaseMask; + float i_distSq; + uint32 team; + Player const* skipped_receiver; + MessageDistDeliverer(WorldObject *src, WorldPacket *msg, float dist, bool own_team_only = false, Player const* skipped = NULL) + : i_source(src), i_message(msg), i_distSq(dist * dist), i_phaseMask(src->GetPhaseMask()) + , team((own_team_only && src->GetTypeId() == TYPEID_PLAYER) ? ((Player*)src)->GetTeam() : 0) + , skipped_receiver(skipped) + { + } + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(DynamicObjectMapType &m); + template void Visit(GridRefManager &) {} + + void SendPacket(Player* plr) + { + // never send packet to self + if (plr == i_source || (team && plr->GetTeam() != team) || skipped_receiver == plr) + return; + + plr->GetSession()->SendPacket(i_message); + } + }; + + struct ObjectUpdater + { + uint32 i_timeDiff; + explicit ObjectUpdater(const uint32 &diff) : i_timeDiff(diff) {} + template void Visit(GridRefManager &m); + void Visit(PlayerMapType &) {} + void Visit(CorpseMapType &) {} + void Visit(CreatureMapType &); + }; + + // SEARCHERS & LIST SEARCHERS & WORKERS + + // WorldObject searchers & workers + + template + struct WorldObjectSearcher + { + uint32 i_phaseMask; + WorldObject* &i_object; + Check &i_check; + + WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(DynamicObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct WorldObjectListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + WorldObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(GameObjectMapType &m); + void Visit(DynamicObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct WorldObjectWorker + { + uint32 i_phaseMask; + Do const& i_do; + + WorldObjectWorker(WorldObject const* searcher, Do const& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(GameObjectMapType &m) + { + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + void Visit(CreatureMapType &m) + { + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(CorpseMapType &m) + { + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(DynamicObjectMapType &m) + { + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // Gameobject searchers + + template + struct GameObjectSearcher + { + uint32 i_phaseMask; + GameObject* &i_object; + Check &i_check; + + GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check GO if any (Check can change requirements at each call) + template + struct GameObjectLastSearcher + { + uint32 i_phaseMask; + GameObject* &i_object; + Check& i_check; + + GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct GameObjectListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + GameObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Unit searchers + + // First accepted by Check Unit if any + template + struct UnitSearcher + { + uint32 i_phaseMask; + Unit* &i_object; + Check & i_check; + + UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check Unit if any (Check can change requirements at each call) + template + struct UnitLastSearcher + { + uint32 i_phaseMask; + Unit* &i_object; + Check & i_check; + + UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // All accepted by Check units if any + template + struct UnitListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + UnitListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Creature searchers + + template + struct CreatureSearcher + { + uint32 i_phaseMask; + Creature* &i_object; + Check & i_check; + + CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check Creature if any (Check can change requirements at each call) + template + struct CreatureLastSearcher + { + uint32 i_phaseMask; + Creature* &i_object; + Check & i_check; + + CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct CreatureListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + CreatureListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct CreatureWorker + { + uint32 i_phaseMask; + Do& i_do; + + CreatureWorker(WorldObject const* searcher, Do& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(CreatureMapType &m) + { + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // Player searchers + + template + struct PlayerSearcher + { + uint32 i_phaseMask; + Player* &i_object; + Check & i_check; + + PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + PlayerListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerWorker + { + uint32 i_phaseMask; + Do& i_do; + + PlayerWorker(WorldObject const* searcher, Do& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerDistWorker + { + WorldObject const* i_searcher; + float i_dist; + Do& i_do; + + PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do) + : i_searcher(searcher), i_dist(_dist), i_do(_do) {} + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // CHECKS && DO classes + + // WorldObject check classes + class RaiseDeadObjectCheck + { + public: + RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Creature* u) + { + if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || + u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() || + (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 || + (u->GetDisplayId() != u->GetNativeDisplayId())) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + class ExplodeCorpseObjectCheck + { + public: + ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Player* u) + { + if (u->getDeathState() != CORPSE || u->isInFlight() || + u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + bool operator()(Creature* u) + { + if (u->getDeathState() != CORPSE || u->isInFlight() || u->isDeadByDefault() || + (u->GetDisplayId() != u->GetNativeDisplayId()) || + (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + class CannibalizeObjectCheck + { + public: + CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Player* u) + { + if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + bool operator()(Corpse* u); + bool operator()(Creature* u) + { + if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || + (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + // WorldObject do classes + + class RespawnDo + { + public: + RespawnDo() {} + void operator()(Creature* u) const { u->Respawn(); } + void operator()(GameObject* u) const { u->Respawn(); } + void operator()(WorldObject*) const {} + void operator()(Corpse*) const {} + }; + + // GameObject checks + + class GameObjectFocusCheck + { + public: + GameObjectFocusCheck(Unit const* unit,uint32 focusId) : i_unit(unit), i_focusId(focusId) {} + bool operator()(GameObject* go) const + { + if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS) + return false; + + if (go->GetGOInfo()->spellFocus.focusId != i_focusId) + return false; + + float dist = (go->GetGOInfo()->spellFocus.dist)/2; + + return go->IsWithinDistInMap(i_unit, dist); + } + private: + Unit const* i_unit; + uint32 i_focusId; + }; + + // Find the nearest Fishing hole and return true only if source object is in range of hole + class NearestGameObjectFishingHole + { + public: + NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(GameObject* go) + { + if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, go->GetGOInfo()->fishinghole.radius)) + { + i_range = i_obj.GetDistance(go); + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + float i_range; + + // prevent clone + NearestGameObjectFishingHole(NearestGameObjectFishingHole const&); + }; + + class NearestGameObjectCheck + { + public: + NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) {} + bool operator()(GameObject* go) + { + if (i_obj.IsWithinDistInMap(go, i_range)) + { + i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + float i_range; + + // prevent clone this object + NearestGameObjectCheck(NearestGameObjectCheck const&); + }; + + // Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO) + class NearestGameObjectEntryInObjectRangeCheck + { + public: + NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj,uint32 entry, float range) : i_obj(obj), i_entry(entry), i_range(range) {} + bool operator()(GameObject* go) + { + if (go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range)) + { + i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + uint32 i_entry; + float i_range; + + // prevent clone this object + NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&); + }; + + class GameObjectWithDbGUIDCheck + { + public: + GameObjectWithDbGUIDCheck(WorldObject const& obj,uint32 db_guid) : i_obj(obj), i_db_guid(db_guid) {} + bool operator()(GameObject const* go) const + { + return go->GetDBTableGUIDLow() == i_db_guid; + } + private: + WorldObject const& i_obj; + uint32 i_db_guid; + }; + + // Unit checks + + class MostHPMissingInRange + { + public: + MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp) + { + i_hp = u->GetMaxHealth() - u->GetHealth(); + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + uint32 i_hp; + }; + + class FriendlyCCedInRange + { + public: + FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && + (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED))) + { + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + }; + + class FriendlyMissingBuffInRange + { + public: + FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && + !(u->HasAura(i_spell))) + { + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + uint32 i_spell; + }; + + class AnyUnfriendlyUnitInObjectRangeCheck + { + public: + AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u)) + return true; + else + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnfriendlyNoTotemUnitInObjectRangeCheck + { + public: + AnyUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (!u->isAlive()) + return false; + + if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) + return false; + + return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u); + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnfriendlyVisibleUnitInObjectRangeCheck + { + public: + AnyUnfriendlyVisibleUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) + : i_obj(obj), i_funit(funit), i_range(range) {} + + bool operator()(Unit* u) + { + return u->isAlive() + && i_obj->IsWithinDistInMap(u, i_range) + && !i_funit->IsFriendlyTo(u) + && u->isVisibleForOrDetect(i_funit, false); + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class CreatureWithDbGUIDCheck + { + public: + CreatureWithDbGUIDCheck(WorldObject const* obj, uint32 lowguid) : i_obj(obj), i_lowguid(lowguid) {} + bool operator()(Creature* u) + { + return u->GetDBTableGUIDLow() == i_lowguid; + } + private: + WorldObject const* i_obj; + uint32 i_lowguid; + }; + + class AnyFriendlyUnitInObjectRangeCheck + { + public: + AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) + return true; + else + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnitInObjectRangeCheck + { + public: + AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + WorldObject const* i_obj; + float i_range; + }; + + // Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit) + class NearestAttackableUnitInObjectRangeCheck + { + public: + NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) && + !i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,false)) + { + i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + + // prevent clone this object + NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); + }; + + class AnyAoETargetUnitInObjectRangeCheck + { + public: + AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) + : i_obj(obj), i_funit(funit), i_range(range) + { + Unit const* check = i_funit; + Unit const* owner = i_funit->GetOwner(); + if (owner) + check = owner; + i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER); + } + bool operator()(Unit* u) + { + // Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems + if (!u->isTargetableForAttack()) + return false; + if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) + return false; + + if ((i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u))&& i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + bool i_targetForPlayer; + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + // do attack at call of help to friendly crearture + class CallOfHelpCreatureInRangeDo + { + public: + CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range) + : i_funit(funit), i_enemy(enemy), i_range(range) + {} + void operator()(Creature* u) + { + if (u == i_funit) + return; + + if (!u->CanAssistTo(i_funit, i_enemy, false)) + return; + + // too far + if (!u->IsWithinDistInMap(i_enemy, i_range)) + return; + + // only if see assisted creature's enemy + if (!u->IsWithinLOSInMap(i_enemy)) + return; + + if (u->AI()) + u->AI()->AttackStart(i_enemy); + } + private: + Unit* const i_funit; + Unit* const i_enemy; + float i_range; + }; + + struct AnyDeadUnitCheck + { + bool operator()(Unit* u) { return !u->isAlive(); } + }; + + struct AnyStealthedCheck + { + bool operator()(Unit* u) { return u->GetVisibility() == VISIBILITY_GROUP_STEALTH; } + }; + + // Creature checks + + class NearestHostileUnitCheck + { + public: + explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0) : me(creature) + { + m_range = (dist == 0 ? 9999 : dist); + } + bool operator()(Unit* u) + { + if (!me->IsWithinDistInMap(u, m_range)) + return false; + + if (!me->canAttack(u)) + return false; + + m_range = me->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + + private: + Creature const *me; + float m_range; + NearestHostileUnitCheck(NearestHostileUnitCheck const&); + }; + + class NearestHostileUnitInAttackDistanceCheck + { + public: + explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0) : me(creature) + { + m_range = (dist == 0 ? 9999 : dist); + m_force = (dist == 0 ? false : true); + } + bool operator()(Unit* u) + { + if (!me->IsWithinDistInMap(u, m_range)) + return false; + + if (m_force) + { + if (!me->canAttack(u)) + return false; + } + else + { + if (!me->canStartAttack(u, false)) + return false; + } + + m_range = me->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + float GetLastRange() const { return m_range; } + private: + Creature const *me; + float m_range; + bool m_force; + NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&); + }; + + class AnyAssistCreatureInRangeCheck + { + public: + AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range) + : i_funit(funit), i_enemy(enemy), i_range(range) + { + } + bool operator()(Creature* u) + { + if (u == i_funit) + return false; + + if (!u->CanAssistTo(i_funit, i_enemy)) + return false; + + // too far + if (!i_funit->IsWithinDistInMap(u, i_range)) + return false; + + // only if see assisted creature + if (!i_funit->IsWithinLOSInMap(u)) + return false; + + return true; + } + private: + Unit* const i_funit; + Unit* const i_enemy; + float i_range; + }; + + class NearestAssistCreatureInCreatureRangeCheck + { + public: + NearestAssistCreatureInCreatureRangeCheck(Creature* obj, Unit* enemy, float range) + : i_obj(obj), i_enemy(enemy), i_range(range) {} + + bool operator()(Creature* u) + { + if (u == i_obj) + return false; + if (!u->CanAssistTo(i_obj,i_enemy)) + return false; + + if (!i_obj->IsWithinDistInMap(u, i_range)) + return false; + + if (!i_obj->IsWithinLOSInMap(u)) + return false; + + i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + float GetLastRange() const { return i_range; } + private: + Creature* const i_obj; + Unit* const i_enemy; + float i_range; + + // prevent clone this object + NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&); + }; + + // Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature) + class NearestCreatureEntryWithLiveStateInObjectRangeCheck + { + public: + NearestCreatureEntryWithLiveStateInObjectRangeCheck(WorldObject const& obj, uint32 entry, bool alive, float range) + : i_obj(obj), i_entry(entry), i_alive(alive), i_range(range) {} + + bool operator()(Creature* u) + { + if (u->GetEntry() == i_entry && u->isAlive() == i_alive && i_obj.IsWithinDistInMap(u, i_range)) + { + i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + uint32 i_entry; + bool i_alive; + float i_range; + + // prevent clone this object + NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&); + }; + + class AnyPlayerInObjectRangeCheck + { + public: + AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Player* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + WorldObject const* i_obj; + float i_range; + }; + + class AllFriendlyCreaturesInGrid + { + public: + AllFriendlyCreaturesInGrid(Unit const* obj) : pUnit(obj) {} + bool operator() (Unit* u) + { + if (u->isAlive() && u->GetVisibility() == VISIBILITY_ON && u->IsFriendlyTo(pUnit)) + return true; + + return false; + } + private: + Unit const* pUnit; + }; + + class AllGameObjectsWithEntryInRange + { + public: + AllGameObjectsWithEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} + bool operator() (GameObject* pGo) + { + if (pGo->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pGo,m_fRange,false)) + return true; + + return false; + } + private: + const WorldObject* m_pObject; + uint32 m_uiEntry; + float m_fRange; + }; + + class AllCreaturesOfEntryInRange + { + public: + AllCreaturesOfEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} + bool operator() (Unit* pUnit) + { + if (pUnit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pUnit,m_fRange,false)) + return true; + + return false; + } + + private: + const WorldObject* m_pObject; + uint32 m_uiEntry; + float m_fRange; + }; + + class PlayerAtMinimumRangeAway + { + public: + PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : pUnit(unit), fRange(fMinRange) {} + bool operator() (Player* pPlayer) + { + //No threat list check, must be done explicit if expected to be in combat with creature + if (!pPlayer->isGameMaster() && pPlayer->isAlive() && !pUnit->IsWithinDist(pPlayer,fRange,false)) + return true; + + return false; + } + + private: + Unit const* pUnit; + float fRange; + }; + + class GameObjectInRangeCheck + { + public: + GameObjectInRangeCheck(float _x, float _y, float _z, float _range) : x(_x), y(_y), z(_z), range(_range) {} + bool operator() (GameObject* go) + { + return go->IsInRange(x, y, z, range); + } + private: + float x, y, z, range; + }; + + // Player checks and do + + // Prepare using Builder localized packets with caching and send to player + template + class LocalizedPacketDo + { + public: + explicit LocalizedPacketDo(Builder& builder) : i_builder(builder) {} + + ~LocalizedPacketDo() + { + for (size_t i = 0; i < i_data_cache.size(); ++i) + delete i_data_cache[i]; + } + void operator()(Player* p); + + private: + Builder& i_builder; + std::vector i_data_cache; // 0 = default, i => i-1 locale index + }; + + // Prepare using Builder localized packets with caching and send to player + template + class LocalizedPacketListDo + { + public: + typedef std::vector WorldPacketList; + explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {} + + ~LocalizedPacketListDo() + { + for (size_t i = 0; i < i_data_cache.size(); ++i) + for (size_t j = 0; j < i_data_cache[i].size(); ++j) + delete i_data_cache[i][j]; + } + void operator()(Player* p); + + private: + Builder& i_builder; + std::vector i_data_cache; + // 0 = default, i => i-1 locale index + }; +} +#endif diff --git a/src/server/game/Maps/Grid/GridNotifiersImpl.h b/src/server/game/Maps/Grid/GridNotifiersImpl.h new file mode 100644 index 00000000000..26a9c0bd328 --- /dev/null +++ b/src/server/game/Maps/Grid/GridNotifiersImpl.h @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDNOTIFIERSIMPL_H +#define TRINITY_GRIDNOTIFIERSIMPL_H + +#include "GridNotifiers.h" +#include "WorldPacket.h" +#include "Corpse.h" +#include "Player.h" +#include "UpdateData.h" +#include "CreatureAI.h" +#include "SpellAuras.h" + + +template +inline void +Trinity::VisibleNotifier::Visit(GridRefManager &m) +{ + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + vis_guids.erase(iter->getSource()->GetGUID()); + i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow); + } +} + +inline void +Trinity::ObjectUpdater::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + if (iter->getSource()->IsInWorld() && !iter->getSource()->isSpiritService()) + iter->getSource()->Update(i_timeDiff); +} + +// SEARCHERS & LIST SEARCHERS & WORKERS + +// WorldObject searchers & workers + +template +void Trinity::WorldObjectSearcher::Visit(GameObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(CorpseMapType &m) +{ + // already found + if (i_object) + return; + + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(DynamicObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(CorpseMapType &m) +{ + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Gameobject searchers + +template +void Trinity::GameObjectSearcher::Visit(GameObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::GameObjectLastSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::GameObjectListSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Unit searchers + +template +void Trinity::UnitSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::UnitSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::UnitLastSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::UnitLastSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::UnitListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::UnitListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Creature searchers + +template +void Trinity::CreatureSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::CreatureLastSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::CreatureListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::PlayerListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::PlayerSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::LocalizedPacketDo::operator()(Player* p) +{ + int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacket* data; + + // create if not cached yet + if (i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx]) + { + if (i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + data = new WorldPacket(SMSG_MESSAGECHAT, 200); + + i_builder(*data,loc_idx); + + i_data_cache[cache_idx] = data; + } + else + data = i_data_cache[cache_idx]; + + p->SendDirectMessage(data); +} + +template +void Trinity::LocalizedPacketListDo::operator()(Player* p) +{ + int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacketList* data_list; + + // create if not cached yet + if (i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty()) + { + if (i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + data_list = &i_data_cache[cache_idx]; + + i_builder(*data_list,loc_idx); + } + else + data_list = &i_data_cache[cache_idx]; + + for (size_t i = 0; i < data_list->size(); ++i) + p->SendDirectMessage((*data_list)[i]); +} + +#endif // TRINITY_GRIDNOTIFIERSIMPL_H diff --git a/src/server/game/Maps/Grid/GridStates.cpp b/src/server/game/Maps/Grid/GridStates.cpp new file mode 100644 index 00000000000..9d39531cfad --- /dev/null +++ b/src/server/game/Maps/Grid/GridStates.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GridStates.h" +#include "GridNotifiers.h" +#include "GameSystem/Grid.h" +#include "Log.h" + +void +InvalidState::Update(Map &, NGridType &, GridInfo &, const uint32 &/*x*/, const uint32 &/*y*/, const uint32 &) const +{ +} + +void +ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const +{ + // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle + info.UpdateTimeTracker(t_diff); + if (info.getTimeTracker().Passed()) + { + if (grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y)) + { + ObjectGridStoper stoper(grid); + stoper.StopN(); + grid.SetGridState(GRID_STATE_IDLE); + sLog.outDebug("Grid[%u,%u] on map %u moved to IDLE state", x, y, m.GetId()); + } + else + { + m.ResetGridExpiry(grid, 0.1f); + } + } +} + +void +IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &) const +{ + m.ResetGridExpiry(grid); + grid.SetGridState(GRID_STATE_REMOVAL); + sLog.outDebug("Grid[%u,%u] on map %u moved to REMOVAL state", x, y, m.GetId()); +} + +void +RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const +{ + if (!info.getUnloadLock()) + { + info.UpdateTimeTracker(t_diff); + if (info.getTimeTracker().Passed()) + { + if (!m.UnloadGrid(x, y, false)) + { + sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players or active objects nearby", x, y, m.GetId()); + m.ResetGridExpiry(grid); + } + } + } +} + diff --git a/src/server/game/Maps/Grid/GridStates.h b/src/server/game/Maps/Grid/GridStates.h new file mode 100644 index 00000000000..c2a75ec45b7 --- /dev/null +++ b/src/server/game/Maps/Grid/GridStates.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDSTATES_H +#define TRINITY_GRIDSTATES_H + +#include "Map.h" +#include "Object.h" + +class GridState +{ + public: +#ifdef TRINITY_DEBUG +#define MAGIC_TESTVAL 0xFBE823BA + GridState() { i_Magic = MAGIC_TESTVAL; } + bool checkMagic() + { + if (i_Magic != MAGIC_TESTVAL) + { + sLog.outError("!!! GridState: Magic value gone !!!"); + return false; + } + return true; + } + void setMagic() { i_Magic = MAGIC_TESTVAL; } + unsigned int i_Magic; +#endif + virtual void Update(Map &, NGridType&, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const = 0; +}; + +class InvalidState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class ActiveState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class IdleState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class RemovalState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; +#endif + diff --git a/src/server/game/Maps/Grid/ObjectGridLoader.cpp b/src/server/game/Maps/Grid/ObjectGridLoader.cpp new file mode 100644 index 00000000000..ab69d9a966b --- /dev/null +++ b/src/server/game/Maps/Grid/ObjectGridLoader.cpp @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectGridLoader.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "Creature.h" +#include "Vehicle.h" +#include "GameObject.h" +#include "DynamicObject.h" +#include "Corpse.h" +#include "World.h" +#include "CellImpl.h" +#include "CreatureAI.h" + +class ObjectGridRespawnMover +{ + public: + ObjectGridRespawnMover() {} + + void Move(GridType &grid); + + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &m); +}; + +void +ObjectGridRespawnMover::Move(GridType &grid) +{ + TypeContainerVisitor mover(*this); + grid.Visit(mover); +} + +void +ObjectGridRespawnMover::Visit(CreatureMapType &m) +{ + // creature in unloading grid can have respawn point in another grid + // if it will be unloaded then it will not respawn in original grid until unload/load original grid + // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn. + for (CreatureMapType::iterator iter = m.begin(); iter != m.end();) + { + Creature * c = iter->getSource(); + ++iter; + + assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); + + Cell const& cur_cell = c->GetCurrentCell(); + + float resp_x, resp_y, resp_z; + c->GetRespawnCoord(resp_x, resp_y, resp_z); + CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y); + Cell resp_cell(resp_val); + + if (cur_cell.DiffGrid(resp_cell)) + { + c->GetMap()->CreatureRespawnRelocation(c); + // false result ignored: will be unload with other creatures at grid + } + } +} + +// for loading world object at grid loading (Corpses) +class ObjectWorldLoader +{ + public: + explicit ObjectWorldLoader(ObjectGridLoader& gloader) + : i_cell(gloader.i_cell), i_grid(gloader.i_grid), i_map(gloader.i_map), i_corpses (0) + {} + + void Visit(CorpseMapType &m); + + template void Visit(GridRefManager&) { } + + private: + Cell i_cell; + NGridType &i_grid; + Map* i_map; + public: + uint32 i_corpses; +}; + +template void addUnitState(T* /*obj*/, CellPair const& /*cell_pair*/) +{ +} + +template<> void addUnitState(Creature *obj, CellPair const& cell_pair) +{ + Cell cell(cell_pair); + + obj->SetCurrentCell(cell); + if (obj->isSpiritService()) + obj->setDeathState(DEAD); +} + +template +void AddObjectHelper(CellPair &cell, GridRefManager &m, uint32 &count, Map* map, T *obj) +{ + obj->GetGridRef().link(&m, obj); + addUnitState(obj,cell); + obj->AddToWorld(); + if (obj->isActiveObject()) + map->AddToActive(obj); + + ++count; +} + +template +void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager &m, uint32 &count, Map* map) +{ + for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) + { + T* obj = new T; + uint32 guid = *i_guid; + //sLog.outString("DEBUG: LoadHelper from table: %s for (guid: %u) Loading",table,guid); + if (!obj->LoadFromDB(guid, map)) + { + delete obj; + continue; + } + + AddObjectHelper(cell, m, count, map, obj); + } +} + +void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map) +{ + if (cell_corpses.empty()) + return; + + for (CellCorpseSet::const_iterator itr = cell_corpses.begin(); itr != cell_corpses.end(); ++itr) + { + if (itr->second != map->GetInstanceId()) + continue; + + uint32 player_guid = itr->first; + + Corpse *obj = ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid); + if (!obj) + continue; + + // TODO: this is a hack + // corpse's map should be reset when the map is unloaded + // but it may still exist when the grid is unloaded but map is not + // in that case map == currMap + obj->SetMap(map); + + AddObjectHelper(cell, m, count, map, obj); + } +} + +void +ObjectGridLoader::Visit(GameObjectMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); + + LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map); +} + +void +ObjectGridLoader::Visit(CreatureMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); + + LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map); +} + +void +ObjectWorldLoader::Visit(CorpseMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + // corpses are always added to spawn mode 0 and they are spawned by their instance id + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id); + LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map); +} + +void +ObjectGridLoader::Load(GridType &grid) +{ + { + TypeContainerVisitor loader(*this); + grid.Visit(loader); + } + + { + ObjectWorldLoader wloader(*this); + TypeContainerVisitor loader(wloader); + grid.Visit(loader); + i_corpses = wloader.i_corpses; + } +} + +void ObjectGridLoader::LoadN(void) +{ + i_gameObjects = 0; i_creatures = 0; i_corpses = 0; + i_cell.data.Part.cell_y = 0; + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + i_cell.data.Part.cell_x = x; + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + i_cell.data.Part.cell_y = y; + GridLoader loader; + loader.Load(i_grid(x, y), *this); + } + } + sLog.outDebug("%u GameObjects, %u Creatures, and %u Corpses/Bones loaded for grid %u on map %u", i_gameObjects, i_creatures, i_corpses,i_grid.GetGridId(), i_map->GetId()); +} + +void ObjectGridUnloader::MoveToRespawnN() +{ + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + ObjectGridRespawnMover mover; + mover.Move(i_grid(x, y)); + } + } +} + +void +ObjectGridUnloader::Unload(GridType &grid) +{ + TypeContainerVisitor unloader(*this); + grid.Visit(unloader); +} + +template +void +ObjectGridUnloader::Visit(GridRefManager &m) +{ + while (!m.isEmpty()) + { + T *obj = m.getFirst()->getSource(); + // if option set then object already saved at this moment + if (!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) + obj->SaveRespawnTime(); + ///- object will get delinked from the manager when deleted + delete obj; + } +} + +void +ObjectGridStoper::Stop(GridType &grid) +{ + TypeContainerVisitor stoper(*this); + grid.Visit(stoper); +} + +void +ObjectGridStoper::Visit(CreatureMapType &m) +{ + // stop any fights at grid de-activation and remove dynobjects created at cast by creatures + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + iter->getSource()->RemoveAllDynObjects(); + if (iter->getSource()->isInCombat()) + { + iter->getSource()->CombatStop(); + iter->getSource()->DeleteThreatList(); + iter->getSource()->AI()->EnterEvadeMode(); + } + } +} + +void +ObjectGridCleaner::Stop(GridType &grid) +{ + TypeContainerVisitor stoper(*this); + grid.Visit(stoper); +} + +void +ObjectGridCleaner::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + iter->getSource()->CleanupsBeforeDelete(); +} + +template +void +ObjectGridCleaner::Visit(GridRefManager &m) +{ + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + iter->getSource()->RemoveFromWorld(); +} + +template void ObjectGridUnloader::Visit(CreatureMapType &); +template void ObjectGridUnloader::Visit(GameObjectMapType &); +template void ObjectGridUnloader::Visit(DynamicObjectMapType &); +template void ObjectGridUnloader::Visit(CorpseMapType &); +template void ObjectGridCleaner::Visit(GameObjectMapType &); +template void ObjectGridCleaner::Visit(DynamicObjectMapType &); +template void ObjectGridCleaner::Visit(CorpseMapType &); diff --git a/src/server/game/Maps/Grid/ObjectGridLoader.h b/src/server/game/Maps/Grid/ObjectGridLoader.h new file mode 100644 index 00000000000..e890bf8d482 --- /dev/null +++ b/src/server/game/Maps/Grid/ObjectGridLoader.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_OBJECTGRIDLOADER_H +#define TRINITY_OBJECTGRIDLOADER_H + +#include "Utilities/TypeList.h" +#include "Platform/Define.h" +#include "GameSystem/GridLoader.h" +#include "GridDefines.h" +#include "Cell.h" + +class ObjectWorldLoader; + +class ObjectGridLoader +{ + friend class ObjectWorldLoader; + + public: + ObjectGridLoader(NGridType &grid, Map* map, const Cell &cell) + : i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses (0) + {} + + void Load(GridType &grid); + void Visit(GameObjectMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &) {} + + void Visit(DynamicObjectMapType&) { } + + void LoadN(void); + + private: + Cell i_cell; + NGridType &i_grid; + Map* i_map; + uint32 i_gameObjects; + uint32 i_creatures; + uint32 i_corpses; +}; + +class ObjectGridUnloader +{ + public: + ObjectGridUnloader(NGridType &grid) : i_grid(grid) {} + + void MoveToRespawnN(); + void UnloadN() + { + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + GridLoader loader; + loader.Unload(i_grid(x, y), *this); + } + } + } + + void Unload(GridType &grid); + template void Visit(GridRefManager &m); + private: + NGridType &i_grid; +}; + +class ObjectGridStoper +{ + public: + ObjectGridStoper(NGridType &grid) : i_grid(grid) {} + + void StopN() + { + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + GridLoader loader; + loader.Stop(i_grid(x, y), *this); + } + } + } + + void Stop(GridType &grid); + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + private: + NGridType &i_grid; +}; + +class ObjectGridCleaner +{ + public: + ObjectGridCleaner(NGridType &grid) : i_grid(grid) {} + + void CleanN() + { + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + GridLoader loader; + loader.Stop(i_grid(x, y), *this); + } + } + } + + void Stop(GridType &grid); + void Visit(CreatureMapType &m); + template void Visit(GridRefManager &); + private: + NGridType &i_grid; +}; + +typedef GridLoader GridLoaderType; +#endif + diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp new file mode 100644 index 00000000000..11bfdcd6f99 --- /dev/null +++ b/src/server/game/Maps/Map.cpp @@ -0,0 +1,3936 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MapManager.h" +#include "Player.h" +#include "Vehicle.h" +#include "GridNotifiers.h" +#include "Log.h" +#include "GridStates.h" +#include "CellImpl.h" +#include "InstanceData.h" +#include "Map.h" +#include "GridNotifiersImpl.h" +#include "Config/ConfigEnv.h" +#include "Transports.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "World.h" +#include "Group.h" +#include "MapRefManager.h" +#include "Vehicle.h" +#include "WaypointManager.h" +#include "DBCEnums.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "GossipDef.h" + +#include "MapInstanced.h" +#include "InstanceSaveMgr.h" +#include "VMapFactory.h" + +#define DEFAULT_GRID_EXPIRY 300 +#define MAX_GRID_LOAD_TIME 50 +#define MAX_CREATURE_ATTACK_RADIUS (45.0f * sWorld.getRate(RATE_CREATURE_AGGRO)) + +GridState* si_GridStates[MAX_GRID_STATE]; + +struct ScriptAction +{ + uint64 sourceGUID; + uint64 targetGUID; + uint64 ownerGUID; // owner of source if source is item + ScriptInfo const* script; // pointer to static script data +}; + +Map::~Map() +{ + UnloadAll(); + + while (!i_worldObjects.empty()) + { + WorldObject *obj = *i_worldObjects.begin(); + assert(obj->m_isWorldObject); + //assert(obj->GetTypeId() == TYPEID_CORPSE); + obj->RemoveFromWorld(); + obj->ResetMap(); + } + + if (!m_scriptSchedule.empty()) + sWorld.DecreaseScheduledScriptCount(m_scriptSchedule.size()); +} + +bool Map::ExistMap(uint32 mapid,int gx,int gy) +{ + int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; + char* tmp = new char[len]; + snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,gx,gy); + + FILE *pf=fopen(tmp,"rb"); + + if (!pf) + { + sLog.outError("Map file '%s': does not exist!",tmp); + delete[] tmp; + return false; + } + + map_fileheader header; + fread(&header, sizeof(header), 1, pf); + if (header.mapMagic != uint32(MAP_MAGIC) || + header.versionMagic != uint32(MAP_VERSION_MAGIC)) + { + sLog.outError("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.",tmp); + delete [] tmp; + fclose(pf); //close file before return + return false; + } + + delete [] tmp; + fclose(pf); + return true; +} + +bool Map::ExistVMap(uint32 mapid,int gx,int gy) +{ + if (VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager()) + { + if (vmgr->isMapLoadingEnabled()) + { + // x and y are swapped !! => fixed now + bool exists = vmgr->existsMap((sWorld.GetDataPath()+ "vmaps").c_str(), mapid, gx,gy); + if (!exists) + { + std::string name = vmgr->getDirFileName(mapid,gx,gy); + sLog.outError("VMap file '%s' is missing or points to wrong version of vmap file. Redo vmaps with latest version of vmap_assembler.exe.", (sWorld.GetDataPath()+"vmaps/"+name).c_str()); + return false; + } + } + } + + return true; +} + +void Map::LoadVMap(int gx,int gy) +{ + // x and y are swapped !! + int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath()+ "vmaps").c_str(), GetId(), gx,gy); + switch(vmapLoadResult) + { + case VMAP::VMAP_LOAD_RESULT_OK: + sLog.outDetail("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); + break; + case VMAP::VMAP_LOAD_RESULT_ERROR: + sLog.outDetail("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); + break; + case VMAP::VMAP_LOAD_RESULT_IGNORED: + DEBUG_LOG("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); + break; + } +} + +void Map::LoadMap(int gx,int gy, bool reload) +{ + if (i_InstanceId != 0) + { + if (GridMaps[gx][gy]) + return; + + // load grid map for base map + if (!m_parentMap->GridMaps[gx][gy]) + m_parentMap->EnsureGridCreated(GridPair(63-gx,63-gy)); + + ((MapInstanced*)(m_parentMap))->AddGridMapReference(GridPair(gx,gy)); + GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy]; + return; + } + + if (GridMaps[gx][gy] && !reload) + return; + + //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?) + if (GridMaps[gx][gy]) + { + sLog.outDetail("Unloading previously loaded map %u before reloading.",GetId()); + delete (GridMaps[gx][gy]); + GridMaps[gx][gy]=NULL; + } + + // map file name + char *tmp=NULL; + int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; + tmp = new char[len]; + snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),GetId(),gx,gy); + sLog.outDetail("Loading map %s",tmp); + // loading data + GridMaps[gx][gy] = new GridMap(); + if (!GridMaps[gx][gy]->loadData(tmp)) + { + sLog.outError("Error loading map file: \n %s\n", tmp); + } + delete [] tmp; +} + +void Map::LoadMapAndVMap(int gx,int gy) +{ + LoadMap(gx,gy); + if (i_InstanceId == 0) + LoadVMap(gx, gy); // Only load the data for the base map +} + +void Map::InitStateMachine() +{ + si_GridStates[GRID_STATE_INVALID] = new InvalidState; + si_GridStates[GRID_STATE_ACTIVE] = new ActiveState; + si_GridStates[GRID_STATE_IDLE] = new IdleState; + si_GridStates[GRID_STATE_REMOVAL] = new RemovalState; +} + +void Map::DeleteStateMachine() +{ + delete si_GridStates[GRID_STATE_INVALID]; + delete si_GridStates[GRID_STATE_ACTIVE]; + delete si_GridStates[GRID_STATE_IDLE]; + delete si_GridStates[GRID_STATE_REMOVAL]; +} + +Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent) + : i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId), m_unloadTimer(0), + m_activeNonPlayersIter(m_activeNonPlayers.end()), + i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this), + m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE), + m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD), + i_scriptLock(false) +{ + for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) + { + for (unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j) + { + //z code + GridMaps[idx][j] =NULL; + setNGrid(NULL, idx, j); + } + } + + //lets initialize visibility distance for map + Map::InitVisibilityDistance(); +} + +void Map::InitVisibilityDistance() +{ + //init visibility for continents + m_VisibleDistance = World::GetMaxVisibleDistanceOnContinents(); + m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodOnContinents(); +} + +// Template specialization of utility methods +template +void Map::AddToGrid(T* obj, NGridType *grid, Cell const& cell) +{ + if (obj->m_isWorldObject) + (*grid)(cell.CellX(), cell.CellY()).template AddWorldObject(obj); + else + (*grid)(cell.CellX(), cell.CellY()).template AddGridObject(obj); +} + +template<> +void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell) +{ + if (obj->m_isWorldObject) + (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(obj); + else + (*grid)(cell.CellX(), cell.CellY()).AddGridObject(obj); + + obj->SetCurrentCell(cell); +} + +template +void Map::RemoveFromGrid(T* obj, NGridType *grid, Cell const& cell) +{ + if (obj->m_isWorldObject) + (*grid)(cell.CellX(), cell.CellY()).template RemoveWorldObject(obj); + else + (*grid)(cell.CellX(), cell.CellY()).template RemoveGridObject(obj); +} + +template +void Map::SwitchGridContainers(T* obj, bool on) +{ + CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("Map::SwitchGridContainers: Object " I64FMT " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) + return; + + DEBUG_LOG("Switch object " I64FMT " from grid[%u,%u] %u", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y, on); + NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY()); + assert(ngrid != NULL); + + GridType &grid = (*ngrid)(cell.CellX(), cell.CellY()); + + if (on) + { + grid.RemoveGridObject(obj); + grid.AddWorldObject(obj); + /*if (!grid.RemoveGridObject(obj, obj->GetGUID()) + || !grid.AddWorldObject(obj, obj->GetGUID())) + { + assert(false); + }*/ + } + else + { + grid.RemoveWorldObject(obj); + grid.AddGridObject(obj); + /*if (!grid.RemoveWorldObject(obj, obj->GetGUID()) + || !grid.AddGridObject(obj, obj->GetGUID())) + { + assert(false); + }*/ + } + obj->m_isWorldObject = on; +} + +template void Map::SwitchGridContainers(Creature *, bool); +//template void Map::SwitchGridContainers(DynamicObject *, bool); + +template +void Map::DeleteFromWorld(T* obj) +{ + // Note: In case resurrectable corpse and pet its removed from global lists in own destructor + delete obj; +} + +template<> +void Map::DeleteFromWorld(Player* pl) +{ + ObjectAccessor::Instance().RemoveObject(pl); + delete pl; +} + +void +Map::EnsureGridCreated(const GridPair &p) +{ + if (!getNGrid(p.x_coord, p.y_coord)) + { + Guard guard(*this); + if (!getNGrid(p.x_coord, p.y_coord)) + { + sLog.outDebug("Creating grid[%u,%u] for map %u instance %u", p.x_coord, p.y_coord, GetId(), i_InstanceId); + + setNGrid(new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld.getConfig(CONFIG_GRID_UNLOAD)), + p.x_coord, p.y_coord); + + // build a linkage between this map and NGridType + buildNGridLinkage(getNGrid(p.x_coord, p.y_coord)); + + getNGrid(p.x_coord, p.y_coord)->SetGridState(GRID_STATE_IDLE); + + //z coord + int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord; + int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord; + + if (!GridMaps[gx][gy]) + LoadMapAndVMap(gx,gy); + } + } +} + +void +Map::EnsureGridLoadedAtEnter(const Cell &cell, Player *player) +{ + EnsureGridLoaded(cell); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + assert(grid != NULL); + + if (player) + { + DEBUG_LOG("Player %s enter cell[%u,%u] triggers loading of grid[%u,%u] on map %u", player->GetName(), cell.CellX(), cell.CellY(), cell.GridX(), cell.GridY(), GetId()); + } + else + { + DEBUG_LOG("Active object nearby triggers loading of grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), GetId()); + } + + // refresh grid state & timer + if (grid->GetGridState() != GRID_STATE_ACTIVE) + { + ResetGridExpiry(*grid, 0.1f); + grid->SetGridState(GRID_STATE_ACTIVE); + } +} + +bool Map::EnsureGridLoaded(const Cell &cell) +{ + EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + + assert(grid != NULL); + if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY())) + { + sLog.outDebug("Loading grid[%u,%u] for map %u instance %u", cell.GridX(), cell.GridY(), GetId(), i_InstanceId); + + ObjectGridLoader loader(*grid, this, cell); + loader.LoadN(); + + // Add resurrectable corpses to world object list in grid + ObjectAccessor::Instance().AddCorpsesToGrid(GridPair(cell.GridX(),cell.GridY()),(*grid)(cell.CellX(), cell.CellY()), this); + + setGridObjectDataLoaded(true,cell.GridX(), cell.GridY()); + return true; + } + + return false; +} + +void Map::LoadGrid(float x, float y) +{ + CellPair pair = Trinity::ComputeCellPair(x, y); + Cell cell(pair); + EnsureGridLoaded(cell); +} + +bool Map::Add(Player *player) +{ + // Check if we are adding to correct map + assert (player->GetMap() == this); + CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("Map::Add: Player (GUID: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord); + return false; + } + + player->SetMap(this); + + Cell cell(p); + EnsureGridLoadedAtEnter(cell, player); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + assert(grid != NULL); + AddToGrid(player, grid, cell); + + player->AddToWorld(); + + SendInitSelf(player); + SendInitTransports(player); + + player->m_clientGUIDs.clear(); + player->UpdateObjectVisibility(true); + + return true; +} + +template +void +Map::Add(T *obj) +{ + CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("Map::Add: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + if (obj->IsInWorld()) // need some clean up later + { + obj->UpdateObjectVisibility(true); + return; + } + + if (obj->isActiveObject()) + EnsureGridLoadedAtEnter(cell); + else + EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); + + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + assert(grid != NULL); + + AddToGrid(obj,grid,cell); + //obj->SetMap(this); + obj->AddToWorld(); + + if (obj->isActiveObject()) + AddToActive(obj); + + DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY()); + + //something, such as vehicle, needs to be update immediately + //also, trigger needs to cast spell, if not update, cannot see visual + obj->UpdateObjectVisibility(true); +} + +/* +void Map::MessageBroadcast(Player *player, WorldPacket *msg, bool to_self) +{ + CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("Map::MessageBroadcast: Player (GUID: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) + return; + + Trinity::MessageDeliverer post_man(*player, msg, to_self); + TypeContainerVisitor message(post_man); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *this, *player, GetVisibilityDistance()); +} + +void Map::MessageBroadcast(WorldObject *obj, WorldPacket *msg) +{ + CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("Map::MessageBroadcast: Object (GUID: %u TypeId: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) + return; + + //TODO: currently on continents when Visibility.Distance.InFlight > Visibility.Distance.Continents + //we have alot of blinking mobs because monster move packet send is broken... + Trinity::ObjectMessageDeliverer post_man(*obj,msg); + TypeContainerVisitor message(post_man); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *this, *obj, GetVisibilityDistance()); +} + +void Map::MessageDistBroadcast(Player *player, WorldPacket *msg, float dist, bool to_self, bool own_team_only) +{ + CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("Map::MessageBroadcast: Player (GUID: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) + return; + + Trinity::MessageDistDeliverer post_man(*player, msg, dist, to_self, own_team_only); + TypeContainerVisitor message(post_man); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *this, *player, dist); +} + +void Map::MessageDistBroadcast(WorldObject *obj, WorldPacket *msg, float dist) +{ + CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + { + sLog.outError("Map::MessageBroadcast: Object (GUID: %u TypeId: %u) have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUIDLow(), obj->GetTypeId(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + return; + } + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + if (!loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) + return; + + Trinity::ObjectMessageDistDeliverer post_man(*obj, msg, dist); + TypeContainerVisitor message(post_man); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, message, *this, *obj, dist); +} +*/ + +bool Map::loaded(const GridPair &p) const +{ + return (getNGrid(p.x_coord, p.y_coord) && isGridObjectDataLoaded(p.x_coord, p.y_coord)); +} + +void Map::Update(const uint32 &t_diff) +{ + /// update players at tick + for (m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) + { + Player* plr = m_mapRefIter->getSource(); + if (plr && plr->IsInWorld()) + plr->Update(t_diff); + } + + /// update active cells around players and active objects + resetMarkedCells(); + + Trinity::ObjectUpdater updater(t_diff); + // for creature + TypeContainerVisitor grid_object_update(updater); + // for pets + TypeContainerVisitor world_object_update(updater); + + // the player iterator is stored in the map object + // to make sure calls to Map::Remove don't invalidate it + for (m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) + { + Player* plr = m_mapRefIter->getSource(); + + if (!plr->IsInWorld()) + continue; + + CellPair standing_cell(Trinity::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY())); + + // Check for correctness of standing_cell, it also avoids problems with update_cell + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + continue; + + // the overloaded operators handle range checking + // so ther's no need for range checking inside the loop + CellPair begin_cell(standing_cell), end_cell(standing_cell); + //lets update mobs/objects in ALL visible cells around player! + CellArea area = Cell::CalculateCellArea(*plr, GetVisibilityDistance()); + area.ResizeBorders(begin_cell, end_cell); + + for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + // marked cells are those that have been visited + // don't visit the same cell twice + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if (!isCellMarked(cell_id)) + { + markCell(cell_id); + CellPair pair(x,y); + Cell cell(pair); + cell.data.Part.reserved = CENTER_DISTRICT; + //cell.SetNoCreate(); + cell.Visit(pair, grid_object_update, *this); + cell.Visit(pair, world_object_update, *this); + } + } + } + } + + // non-player active objects + if (!m_activeNonPlayers.empty()) + { + for (m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end();) + { + // skip not in world + WorldObject* obj = *m_activeNonPlayersIter; + + // step before processing, in this case if Map::Remove remove next object we correctly + // step to next-next, and if we step to end() then newly added objects can wait next update. + ++m_activeNonPlayersIter; + + if (!obj->IsInWorld()) + continue; + + CellPair standing_cell(Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY())); + + // Check for correctness of standing_cell, it also avoids problems with update_cell + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + continue; + + // the overloaded operators handle range checking + // so ther's no need for range checking inside the loop + CellPair begin_cell(standing_cell), end_cell(standing_cell); + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right + + for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + // marked cells are those that have been visited + // don't visit the same cell twice + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if (!isCellMarked(cell_id)) + { + markCell(cell_id); + CellPair pair(x,y); + Cell cell(pair); + cell.data.Part.reserved = CENTER_DISTRICT; + //cell.SetNoCreate(); + cell.Visit(pair, grid_object_update, *this); + cell.Visit(pair, world_object_update, *this); + } + } + } + } + } + + ///- Process necessary scripts + if (!m_scriptSchedule.empty()) + { + i_scriptLock = true; + ScriptsProcess(); + i_scriptLock = false; + } + + MoveAllCreaturesInMoveList(); + + if (!m_mapRefManager.isEmpty() || !m_activeNonPlayers.empty()) + ProcessRelocationNotifies(t_diff); +} + +struct ResetNotifier +{ + templateinline void resetNotify(GridRefManager &m) + { + for (typename GridRefManager::iterator iter=m.begin(); iter != m.end(); ++iter) + iter->getSource()->ResetAllNotifies(); + } + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &m) { resetNotify(m);} + void Visit(PlayerMapType &m) { resetNotify(m);} +}; + +void Map::ProcessRelocationNotifies(const uint32 & diff) +{ + for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end(); ++i) + { + NGridType *grid = i->getSource(); + + if (grid->GetGridState() != GRID_STATE_ACTIVE) + continue; + + grid->getGridInfoRef()->getRelocationTimer().TUpdate(diff); + if (!grid->getGridInfoRef()->getRelocationTimer().TPassed()) + continue; + + uint32 gx = grid->getX(), gy = grid->getY(); + + CellPair cell_min(gx*MAX_NUMBER_OF_CELLS, gy*MAX_NUMBER_OF_CELLS); + CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); + + for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x) + { + for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y) + { + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if (!isCellMarked(cell_id)) + continue; + + CellPair pair(x,y); + Cell cell(pair); + cell.SetNoCreate(); + + Trinity::DelayedUnitRelocation cell_relocation(cell, pair, *this, GetVisibilityDistance()); + TypeContainerVisitor grid_object_relocation(cell_relocation); + TypeContainerVisitor world_object_relocation(cell_relocation); + Visit(cell, grid_object_relocation); + Visit(cell, world_object_relocation); + } + } + } + + ResetNotifier reset; + TypeContainerVisitor grid_notifier(reset); + TypeContainerVisitor world_notifier(reset); + for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end(); ++i) + { + NGridType *grid = i->getSource(); + + if (grid->GetGridState() != GRID_STATE_ACTIVE) + continue; + + if (!grid->getGridInfoRef()->getRelocationTimer().TPassed()) + continue; + + grid->getGridInfoRef()->getRelocationTimer().TReset(diff, m_VisibilityNotifyPeriod); + + uint32 gx = grid->getX(), gy = grid->getY(); + + CellPair cell_min(gx*MAX_NUMBER_OF_CELLS, gy*MAX_NUMBER_OF_CELLS); + CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); + + for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x) + { + for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y) + { + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if (!isCellMarked(cell_id)) + continue; + + CellPair pair(x,y); + Cell cell(pair); + cell.SetNoCreate(); + Visit(cell, grid_notifier); + Visit(cell, world_notifier); + } + } + } +} + +void Map::Remove(Player *player, bool remove) +{ + player->RemoveFromWorld(); + SendRemoveTransports(player); + + CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + sLog.outCrash("Map::Remove: Player is in invalid cell!"); + else + { + Cell cell(p); + if (!getNGrid(cell.data.Part.grid_x, cell.data.Part.grid_y)) + sLog.outError("Map::Remove() i_grids was NULL x:%d, y:%d",cell.data.Part.grid_x,cell.data.Part.grid_y); + else + { + DEBUG_LOG("Remove player %s from grid[%u,%u]", player->GetName(), cell.GridX(), cell.GridY()); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + assert(grid != NULL); + + player->UpdateObjectVisibility(true); + RemoveFromGrid(player,grid,cell); + } + } + + if (remove) + DeleteFromWorld(player); +} + +bool Map::RemoveBones(uint64 guid, float x, float y) +{ + if (IsRemovalGrid(x, y)) + { + Corpse * corpse = ObjectAccessor::Instance().GetObjectInWorld(GetId(), x, y, guid, (Corpse*)NULL); + if (corpse && corpse->GetTypeId() == TYPEID_CORPSE && corpse->GetType() == CORPSE_BONES) + corpse->DeleteBonesFromWorld(); + else + return false; + } + return true; +} + +template +void +Map::Remove(T *obj, bool remove) +{ + obj->RemoveFromWorld(); + if (obj->isActiveObject()) + RemoveFromActive(obj); + + CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + sLog.outError("Map::Remove: Object " I64FMT " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + else + { + Cell cell(p); + if (loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y))) + { + DEBUG_LOG("Remove object " I64FMT " from grid[%u,%u]", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y); + NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + assert(grid != NULL); + + obj->UpdateObjectVisibility(true); + RemoveFromGrid(obj,grid,cell); + } + } + + obj->ResetMap(); + + if (remove) + { + // if option set then object already saved at this moment + if (!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) + obj->SaveRespawnTime(); + DeleteFromWorld(obj); + } +} + +void +Map::PlayerRelocation(Player *player, float x, float y, float z, float orientation) +{ + assert(player); + + CellPair old_val = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); + CellPair new_val = Trinity::ComputeCellPair(x, y); + + Cell old_cell(old_val); + Cell new_cell(new_val); + + player->Relocate(x, y, z, orientation); + + if (old_cell.DiffGrid(new_cell) || old_cell.DiffCell(new_cell)) + { + DEBUG_LOG("Player %s relocation grid[%u,%u]cell[%u,%u]->grid[%u,%u]cell[%u,%u]", player->GetName(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + + NGridType* oldGrid = getNGrid(old_cell.GridX(), old_cell.GridY()); + RemoveFromGrid(player, oldGrid,old_cell); + + if (old_cell.DiffGrid(new_cell)) + EnsureGridLoadedAtEnter(new_cell, player); + + NGridType* newGrid = getNGrid(new_cell.GridX(), new_cell.GridY()); + AddToGrid(player, newGrid,new_cell); + } + + player->UpdateObjectVisibility(false); +} + +void +Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang) +{ + assert(CheckGridIntegrity(creature,false)); + + Cell old_cell = creature->GetCurrentCell(); + + CellPair new_val = Trinity::ComputeCellPair(x, y); + Cell new_cell(new_val); + + // delay creature move for grid/cell to grid/cell moves + if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell)) + { + #ifdef TRINITY_DEBUG + if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) + sLog.outDebug("Creature (GUID: %u Entry: %u) added to moving list from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", creature->GetGUIDLow(), creature->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + AddCreatureToMoveList(creature, x, y, z, ang); + // in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList + } + else + { + creature->Relocate(x, y, z, ang); + creature->UpdateObjectVisibility(false); + } + + assert(CheckGridIntegrity(creature,true)); +} + +void Map::AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang) +{ + if (!c) + return; + + i_creaturesToMove[c] = CreatureMover(x, y, z, ang); +} + +void Map::MoveAllCreaturesInMoveList() +{ + while (!i_creaturesToMove.empty()) + { + // get data and remove element; + CreatureMoveList::iterator iter = i_creaturesToMove.begin(); + Creature* c = iter->first; + CreatureMover cm = iter->second; + i_creaturesToMove.erase(iter); + + // calculate cells + CellPair new_val = Trinity::ComputeCellPair(cm.x, cm.y); + Cell new_cell(new_val); + + // do move or do move to respawn or remove creature if previous all fail + if (CreatureCellRelocation(c,new_cell)) + { + // update pos + c->Relocate(cm.x, cm.y, cm.z, cm.ang); + //CreatureRelocationNotify(c,new_cell,new_cell.cellPair()); + c->UpdateObjectVisibility(false); + } + else + { + // if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid + // creature coordinates will be updated and notifiers send + if (!CreatureRespawnRelocation(c)) + { + // ... or unload (if respawn grid also not loaded) + #ifdef TRINITY_DEBUG + if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) + sLog.outDebug("Creature (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.",c->GetGUIDLow(),c->GetEntry()); + #endif + AddObjectToRemoveList(c); + } + } + } +} + +bool Map::CreatureCellRelocation(Creature *c, Cell new_cell) +{ + Cell const& old_cell = c->GetCurrentCell(); + if (!old_cell.DiffGrid(new_cell)) // in same grid + { + // if in same cell then none do + if (old_cell.DiffCell(new_cell)) + { + #ifdef TRINITY_DEBUG + if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) + sLog.outDebug("Creature (GUID: %u Entry: %u) moved in grid[%u,%u] from cell[%u,%u] to cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY()); + #endif + + RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); + AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); + } + else + { + #ifdef TRINITY_DEBUG + if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) + sLog.outDebug("Creature (GUID: %u Entry: %u) moved in same grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY()); + #endif + } + + return true; + } + + // in diff. grids but active creature + if (c->isActiveObject()) + { + EnsureGridLoadedAtEnter(new_cell); + + #ifdef TRINITY_DEBUG + if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) + sLog.outDebug("Active creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + + RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); + AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); + + return true; + } + + // in diff. loaded grid normal creature + if (loaded(GridPair(new_cell.GridX(), new_cell.GridY()))) + { + #ifdef TRINITY_DEBUG + if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) + sLog.outDebug("Creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + + RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); + EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY())); + AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); + + return true; + } + + // fail to move: normal creature attempt move to unloaded grid + #ifdef TRINITY_DEBUG + if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) + sLog.outDebug("Creature (GUID: %u Entry: %u) attempted to move from grid[%u,%u]cell[%u,%u] to unloaded grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); + #endif + return false; +} + +bool Map::CreatureRespawnRelocation(Creature *c) +{ + float resp_x, resp_y, resp_z, resp_o; + c->GetRespawnCoord(resp_x, resp_y, resp_z, &resp_o); + + CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y); + Cell resp_cell(resp_val); + + c->CombatStop(); + c->GetMotionMaster()->Clear(); + + #ifdef TRINITY_DEBUG + if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0) + sLog.outDebug("Creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to respawn grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), c->GetCurrentCell().GridX(), c->GetCurrentCell().GridY(), c->GetCurrentCell().CellX(), c->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY()); + #endif + + // teleport it to respawn point (like normal respawn if player see) + if (CreatureCellRelocation(c,resp_cell)) + { + c->Relocate(resp_x, resp_y, resp_z, resp_o); + c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators + //CreatureRelocationNotify(c,resp_cell,resp_cell.cellPair()); + c->UpdateObjectVisibility(false); + return true; + } + else + return false; +} + +bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool unloadAll) +{ + NGridType *grid = getNGrid(x, y); + assert(grid != NULL); + + { + if (!unloadAll && ActiveObjectsNearGrid(x, y)) + return false; + + sLog.outDebug("Unloading grid[%u,%u] for map %u", x,y, GetId()); + + ObjectGridUnloader unloader(*grid); + + if (!unloadAll) + { + // Finish creature moves, remove and delete all creatures with delayed remove before moving to respawn grids + // Must know real mob position before move + MoveAllCreaturesInMoveList(); + + // move creatures to respawn grids if this is diff.grid or to remove list + unloader.MoveToRespawnN(); + + // Finish creature moves, remove and delete all creatures with delayed remove before unload + MoveAllCreaturesInMoveList(); + } + + ObjectGridCleaner cleaner(*grid); + cleaner.CleanN(); + + RemoveAllObjectsInRemoveList(); + + unloader.UnloadN(); + + assert(i_objectsToRemove.empty()); + + delete grid; + setNGrid(NULL, x, y); + } + int gx = (MAX_NUMBER_OF_GRIDS - 1) - x; + int gy = (MAX_NUMBER_OF_GRIDS - 1) - y; + + // delete grid map, but don't delete if it is from parent map (and thus only reference) + //+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps + { + if (i_InstanceId == 0) + { + if (GridMaps[gx][gy]) + { + GridMaps[gx][gy]->unloadData(); + delete GridMaps[gx][gy]; + } + // x and y are swapped + VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy); + } + else + ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridPair(gx, gy)); + + GridMaps[gx][gy] = NULL; + } + DEBUG_LOG("Unloading grid[%u,%u] for map %u finished", x,y, GetId()); + return true; +} + +void Map::RemoveAllPlayers() +{ + if (HavePlayers()) + { + for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + { + Player* plr = itr->getSource(); + if (!plr->IsBeingTeleportedFar()) + { + // this is happening for bg + sLog.outError("Map::UnloadAll: player %s is still in map %u during unload, this should not happen!", plr->GetName(), GetId()); + plr->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation()); + } + } + } +} + +void Map::UnloadAll() +{ + // clear all delayed moves, useless anyway do this moves before map unload. + i_creaturesToMove.clear(); + + for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end();) + { + NGridType &grid(*i->getSource()); + ++i; + UnloadGrid(grid.getX(), grid.getY(), true); // deletes the grid and removes it from the GridRefManager + } +} + +//***************************** +// Grid function +//***************************** +GridMap::GridMap() +{ + m_flags = 0; + // Area data + m_gridArea = 0; + m_area_map = NULL; + // Height level data + m_gridHeight = INVALID_HEIGHT; + m_gridGetHeight = &GridMap::getHeightFromFlat; + m_V9 = NULL; + m_V8 = NULL; + // Liquid data + m_liquidType = 0; + m_liquid_offX = 0; + m_liquid_offY = 0; + m_liquid_width = 0; + m_liquid_height = 0; + m_liquidLevel = INVALID_HEIGHT; + m_liquid_type = NULL; + m_liquid_map = NULL; +} + +GridMap::~GridMap() +{ + unloadData(); +} + +bool GridMap::loadData(char *filename) +{ + // Unload old data if exist + unloadData(); + + map_fileheader header; + // Not return error if file not found + FILE *in = fopen(filename, "rb"); + if (!in) + return true; + fread(&header, sizeof(header),1,in); + if (header.mapMagic == uint32(MAP_MAGIC) && + header.versionMagic == uint32(MAP_VERSION_MAGIC)) + { + // loadup area data + if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize)) + { + sLog.outError("Error loading map area data\n"); + fclose(in); + return false; + } + // loadup height data + if (header.heightMapOffset && !loadHeihgtData(in, header.heightMapOffset, header.heightMapSize)) + { + sLog.outError("Error loading map height data\n"); + fclose(in); + return false; + } + // loadup liquid data + if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize)) + { + sLog.outError("Error loading map liquids data\n"); + fclose(in); + return false; + } + fclose(in); + return true; + } + sLog.outError("Map file '%s' is a non-compatible version (outdated?). Please, create new using the ad.exe program.", filename); + fclose(in); + return false; +} + +void GridMap::unloadData() +{ + if (m_area_map) delete[] m_area_map; + if (m_V9) delete[] m_V9; + if (m_V8) delete[] m_V8; + if (m_liquid_type) delete[] m_liquid_type; + if (m_liquid_map) delete[] m_liquid_map; + m_area_map = NULL; + m_V9 = NULL; + m_V8 = NULL; + m_liquid_type = NULL; + m_liquid_map = NULL; + m_gridGetHeight = &GridMap::getHeightFromFlat; +} + +bool GridMap::loadAreaData(FILE *in, uint32 offset, uint32 /*size*/) +{ + map_areaHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != uint32(MAP_AREA_MAGIC)) + return false; + + m_gridArea = header.gridArea; + if (!(header.flags & MAP_AREA_NO_AREA)) + { + m_area_map = new uint16 [16*16]; + fread(m_area_map, sizeof(uint16), 16*16, in); + } + return true; +} + +bool GridMap::loadHeihgtData(FILE *in, uint32 offset, uint32 /*size*/) +{ + map_heightHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != uint32(MAP_HEIGHT_MAGIC)) + return false; + + m_gridHeight = header.gridHeight; + if (!(header.flags & MAP_HEIGHT_NO_HEIGHT)) + { + if ((header.flags & MAP_HEIGHT_AS_INT16)) + { + m_uint16_V9 = new uint16 [129*129]; + m_uint16_V8 = new uint16 [128*128]; + fread(m_uint16_V9, sizeof(uint16), 129*129, in); + fread(m_uint16_V8, sizeof(uint16), 128*128, in); + m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; + m_gridGetHeight = &GridMap::getHeightFromUint16; + } + else if ((header.flags & MAP_HEIGHT_AS_INT8)) + { + m_uint8_V9 = new uint8 [129*129]; + m_uint8_V8 = new uint8 [128*128]; + fread(m_uint8_V9, sizeof(uint8), 129*129, in); + fread(m_uint8_V8, sizeof(uint8), 128*128, in); + m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255; + m_gridGetHeight = &GridMap::getHeightFromUint8; + } + else + { + m_V9 = new float [129*129]; + m_V8 = new float [128*128]; + fread(m_V9, sizeof(float), 129*129, in); + fread(m_V8, sizeof(float), 128*128, in); + m_gridGetHeight = &GridMap::getHeightFromFloat; + } + } + else + m_gridGetHeight = &GridMap::getHeightFromFlat; + return true; +} + +bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 /*size*/) +{ + map_liquidHeader header; + fseek(in, offset, SEEK_SET); + fread(&header, sizeof(header), 1, in); + if (header.fourcc != uint32(MAP_LIQUID_MAGIC)) + return false; + + m_liquidType = header.liquidType; + m_liquid_offX = header.offsetX; + m_liquid_offY = header.offsetY; + m_liquid_width = header.width; + m_liquid_height= header.height; + m_liquidLevel = header.liquidLevel; + + if (!(header.flags & MAP_LIQUID_NO_TYPE)) + { + m_liquid_type = new uint8 [16*16]; + fread(m_liquid_type, sizeof(uint8), 16*16, in); + } + if (!(header.flags & MAP_LIQUID_NO_HEIGHT)) + { + m_liquid_map = new float [m_liquid_width*m_liquid_height]; + fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in); + } + return true; +} + +uint16 GridMap::getArea(float x, float y) +{ + if (!m_area_map) + return m_gridArea; + + x = 16 * (32 - x/SIZE_OF_GRIDS); + y = 16 * (32 - y/SIZE_OF_GRIDS); + int lx = (int)x & 15; + int ly = (int)y & 15; + return m_area_map[lx*16 + ly]; +} + +float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const +{ + return m_gridHeight; +} + +float GridMap::getHeightFromFloat(float x, float y) const +{ + if (!m_V8 || !m_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid + // +--------------> X + // | h1-------h2 Coordinates is: + // | | \ 1 / | h1 0,0 + // | | \ / | h2 0,1 + // | | 2 h5 3 | h3 1,0 + // | | / \ | h4 1,1 + // | | / 4 \ | h5 1/2,1/2 + // | h3-------h4 + // V Y + // For find height need + // 1 - detect triangle + // 2 - solve linear equation from triangle points + // Calculate coefficients for solve h = a*x + b*y + c + + float a,b,c; + // Select triangle: + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + float h1 = m_V9[(x_int)*129 + y_int]; + float h2 = m_V9[(x_int+1)*129 + y_int]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + float h1 = m_V9[x_int*129 + y_int ]; + float h3 = m_V9[x_int*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + float h2 = m_V9[(x_int+1)*129 + y_int ]; + float h4 = m_V9[(x_int+1)*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + float h3 = m_V9[(x_int)*129 + y_int+1]; + float h4 = m_V9[(x_int+1)*129 + y_int+1]; + float h5 = 2 * m_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return a * x + b * y + c; +} + +float GridMap::getHeightFromUint8(float x, float y) const +{ + if (!m_uint8_V8 || !m_uint8_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + int32 a, b, c; + uint8 *V9_h1_ptr = &m_uint8_V9[x_int*128 + x_int + y_int]; + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + int32 h1 = V9_h1_ptr[ 0]; + int32 h2 = V9_h1_ptr[129]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h3 = V9_h1_ptr[1]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + int32 h2 = V9_h1_ptr[129]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + int32 h3 = V9_h1_ptr[ 1]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; +} + +float GridMap::getHeightFromUint16(float x, float y) const +{ + if (!m_uint16_V8 || !m_uint16_V9) + return m_gridHeight; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int&=(MAP_RESOLUTION - 1); + y_int&=(MAP_RESOLUTION - 1); + + int32 a, b, c; + uint16 *V9_h1_ptr = &m_uint16_V9[x_int*128 + x_int + y_int]; + if (x+y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + int32 h1 = V9_h1_ptr[ 0]; + int32 h2 = V9_h1_ptr[129]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h2-h1; + b = h5-h1-h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h3 = V9_h1_ptr[1]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + int32 h2 = V9_h1_ptr[129]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + int32 h3 = V9_h1_ptr[ 1]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight; +} + +float GridMap::getLiquidLevel(float x, float y) +{ + if (!m_liquid_map) + return m_liquidLevel; + + x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int cx_int = ((int)x & (MAP_RESOLUTION-1)) - m_liquid_offY; + int cy_int = ((int)y & (MAP_RESOLUTION-1)) - m_liquid_offX; + + if (cx_int < 0 || cx_int >=m_liquid_height) + return INVALID_HEIGHT; + if (cy_int < 0 || cy_int >=m_liquid_width) + return INVALID_HEIGHT; + + return m_liquid_map[cx_int*m_liquid_width + cy_int]; +} + +uint8 GridMap::getTerrainType(float x, float y) +{ + if (!m_liquid_type) + return m_liquidType; + + x = 16 * (32 - x/SIZE_OF_GRIDS); + y = 16 * (32 - y/SIZE_OF_GRIDS); + int lx = (int)x & 15; + int ly = (int)y & 15; + return m_liquid_type[lx*16 + ly]; +} + +// Get water state on map +inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) +{ + // Check water type (if no water return) + if (!m_liquid_type && !m_liquidType) + return LIQUID_MAP_NO_WATER; + + // Get cell + float cx = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS); + float cy = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS); + + int x_int = (int)cx & (MAP_RESOLUTION-1); + int y_int = (int)cy & (MAP_RESOLUTION-1); + + // Check water type in cell + uint8 type = m_liquid_type ? m_liquid_type[(x_int>>3)*16 + (y_int>>3)] : m_liquidType; + if (type == 0) + return LIQUID_MAP_NO_WATER; + + // Check req liquid type mask + if (ReqLiquidType && !(ReqLiquidType&type)) + return LIQUID_MAP_NO_WATER; + + // Check water level: + // Check water height map + int lx_int = x_int - m_liquid_offY; + int ly_int = y_int - m_liquid_offX; + if (lx_int < 0 || lx_int >=m_liquid_height) + return LIQUID_MAP_NO_WATER; + if (ly_int < 0 || ly_int >=m_liquid_width) + return LIQUID_MAP_NO_WATER; + + // Get water level + float liquid_level = m_liquid_map ? m_liquid_map[lx_int*m_liquid_width + ly_int] : m_liquidLevel; + // Get ground level (sub 0.2 for fix some errors) + float ground_level = getHeight(x, y); + + // Check water level and ground level + if (liquid_level < ground_level || z < ground_level - 2) + return LIQUID_MAP_NO_WATER; + + // All ok in water -> store data + if (data) + { + data->type = type; + data->level = liquid_level; + data->depth_level = ground_level; + } + + // For speed check as int values + int delta = int((liquid_level - z) * 10); + + // Get position delta + if (delta > 20) // Under water + return LIQUID_MAP_UNDER_WATER; + if (delta > 0) // In water + return LIQUID_MAP_IN_WATER; + if (delta > -1) // Walk on water + return LIQUID_MAP_WATER_WALK; + // Above water + return LIQUID_MAP_ABOVE_WATER; +} + +inline GridMap *Map::GetGrid(float x, float y) +{ + // half opt method + int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x + int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y + + // ensure GridMap is loaded + EnsureGridCreated(GridPair(63-gx,63-gy)); + + return GridMaps[gx][gy]; +} + +float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const +{ + // find raw .map surface under Z coordinates + float mapHeight; + if (GridMap *gmap = const_cast(this)->GetGrid(x, y)) + { + float _mapheight = gmap->getHeight(x,y); + + // look from a bit higher pos to find the floor, ignore under surface case + if (z + 2.0f > _mapheight) + mapHeight = _mapheight; + else + mapHeight = VMAP_INVALID_HEIGHT_VALUE; + } + else + mapHeight = VMAP_INVALID_HEIGHT_VALUE; + + float vmapHeight; + if (pUseVmaps) + { + VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); + if (vmgr->isHeightCalcEnabled()) + { + // look from a bit higher pos to find the floor + vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f); + } + else + vmapHeight = VMAP_INVALID_HEIGHT_VALUE; + } + else + vmapHeight = VMAP_INVALID_HEIGHT_VALUE; + + // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT + // vmapheight set for any under Z value or <= INVALID_HEIGHT + + if (vmapHeight > INVALID_HEIGHT) + { + if (mapHeight > INVALID_HEIGHT) + { + // we have mapheight and vmapheight and must select more appropriate + + // we are already under the surface or vmap height above map heigt + // or if the distance of the vmap height is less the land height distance + if (z < mapHeight || vmapHeight > mapHeight || fabs(mapHeight-z) > fabs(vmapHeight-z)) + return vmapHeight; + else + return mapHeight; // better use .map surface height + + } + else + return vmapHeight; // we have only vmapHeight (if have) + } + else + { + if (!pUseVmaps) + return mapHeight; // explicitly use map data (if have) + else if (mapHeight > INVALID_HEIGHT && (z < mapHeight + 2 || z == MAX_HEIGHT)) + return mapHeight; // explicitly use map data if original z < mapHeight but map found (z+2 > mapHeight) + else + return VMAP_INVALID_HEIGHT_VALUE; // we not have any height + } +} + +inline bool IsOutdoorWMO(uint32 mogpFlags, int32 adtId, int32 rootId, int32 groupId, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry) +{ + bool outdoor = true; + + if(wmoEntry && atEntry) + { + if(atEntry->flags & AREA_FLAG_OUTSIDE) + return true; + if(atEntry->flags & AREA_FLAG_INSIDE) + return false; + } + + outdoor = mogpFlags&0x8; + + if(wmoEntry) + { + if(wmoEntry->Flags & 4) + return true; + if((wmoEntry->Flags & 2)!=0) + outdoor = false; + } + return outdoor; +} + +bool Map::IsOutdoors(float x, float y, float z) const +{ + uint32 mogpFlags; + int32 adtId, rootId, groupId; + + // no wmo found? -> outside by default + if(!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) + return true; + + AreaTableEntry const* atEntry = 0; + WMOAreaTableEntry const* wmoEntry= GetWMOAreaTableEntryByTripple(rootId, adtId, groupId); + if(wmoEntry) + { + DEBUG_LOG("Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->areaId); + atEntry = GetAreaEntryByAreaID(wmoEntry->areaId); + } + return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry); +} + +bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const +{ + float vmap_z = z; + VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); + if (vmgr->getAreaInfo(GetId(), x, y, vmap_z, flags, adtId, rootId, groupId)) + { + // check if there's terrain between player height and object height + if(GridMap *gmap = const_cast(this)->GetGrid(x, y)) + { + float _mapheight = gmap->getHeight(x,y); + // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice... + if(z + 2.0f > _mapheight && _mapheight > vmap_z) + return false; + } + return true; + } + return false; +} + +uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const +{ + uint32 mogpFlags; + int32 adtId, rootId, groupId; + WMOAreaTableEntry const* wmoEntry = 0; + AreaTableEntry const* atEntry = 0; + bool haveAreaInfo = false; + + if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) + { + haveAreaInfo = true; + if (wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId)) + atEntry = GetAreaEntryByAreaID(wmoEntry->areaId); + } + + uint16 areaflag; + + if (atEntry) + areaflag = atEntry->exploreFlag; + else + { + if (GridMap *gmap = const_cast(this)->GetGrid(x, y)) + areaflag = gmap->getArea(x, y); + // this used while not all *.map files generated (instances) + else + areaflag = GetAreaFlagByMapId(i_mapEntry->MapID); + } + + if (isOutdoors) + { + if (haveAreaInfo) + *isOutdoors = IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry); + else + *isOutdoors = true; + } + return areaflag; + } + +uint8 Map::GetTerrainType(float x, float y) const +{ + if (GridMap *gmap = const_cast(this)->GetGrid(x, y)) + return gmap->getTerrainType(x, y); + else + return 0; +} + +ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data) const +{ + ZLiquidStatus result = LIQUID_MAP_NO_WATER; + VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); + float liquid_level, ground_level = INVALID_HEIGHT; + uint32 liquid_type; + if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) + { + sLog.outDebug("getLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type); + // Check water level and ground level + if (liquid_level > ground_level && z > ground_level - 2) + { + // All ok in water -> store data + if (data) + { + data->type = liquid_type; + data->level = liquid_level; + data->depth_level = ground_level; + } + + // For speed check as int values + int delta = int((liquid_level - z) * 10); + + // Get position delta + if (delta > 20) // Under water + return LIQUID_MAP_UNDER_WATER; + if (delta > 0 ) // In water + return LIQUID_MAP_IN_WATER; + if (delta > -1) // Walk on water + return LIQUID_MAP_WATER_WALK; + result = LIQUID_MAP_ABOVE_WATER; + } + } + + if(GridMap* gmap = const_cast(this)->GetGrid(x, y)) + { + LiquidData map_data; + ZLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data); + // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER: + if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level)) + { + if (data) + *data = map_data; + return map_result; + } + } + return result; +} + +float Map::GetWaterLevel(float x, float y) const +{ + if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + return gmap->getLiquidLevel(x, y); + else + return 0; +} + +uint32 Map::GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id) +{ + AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); + + if (entry) + return entry->ID; + else + return 0; +} + +uint32 Map::GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id) +{ + AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); + + if (entry) + return (entry->zone != 0) ? entry->zone : entry->ID; + else + return 0; +} + +void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id) +{ + AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id); + + areaid = entry ? entry->ID : 0; + zoneid = entry ? ((entry->zone != 0) ? entry->zone : entry->ID) : 0; +} + +bool Map::IsInWater(float x, float y, float pZ, LiquidData *data) const +{ + // Check surface in x, y point for liquid + if (const_cast(this)->GetGrid(x, y)) + { + LiquidData liquid_status; + LiquidData *liquid_ptr = data ? data : &liquid_status; + if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr)) + return true; + } + return false; +} + +bool Map::IsUnderWater(float x, float y, float z) const +{ + if (const_cast(this)->GetGrid(x, y)) + { + if (getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN)&LIQUID_MAP_UNDER_WATER) + return true; + } + return false; +} + +bool Map::CheckGridIntegrity(Creature* c, bool moved) const +{ + Cell const& cur_cell = c->GetCurrentCell(); + + CellPair xy_val = Trinity::ComputeCellPair(c->GetPositionX(), c->GetPositionY()); + Cell xy_cell(xy_val); + if (xy_cell != cur_cell) + { + sLog.outDebug("Creature (GUID: %u) X: %f Y: %f (%s) is in grid[%u,%u]cell[%u,%u] instead of grid[%u,%u]cell[%u,%u]", + c->GetGUIDLow(), + c->GetPositionX(),c->GetPositionY(),(moved ? "final" : "original"), + cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(), + xy_cell.GridX(), xy_cell.GridY(), xy_cell.CellX(), xy_cell.CellY()); + return true; // not crash at error, just output error in debug mode + } + + return true; +} + +const char* Map::GetMapName() const +{ + return i_mapEntry ? i_mapEntry->name[sWorld.GetDefaultDbcLocale()] : "UNNAMEDMAP\x0"; +} + +void Map::UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair) +{ + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + Trinity::VisibleChangesNotifier notifier(*obj); + TypeContainerVisitor player_notifier(notifier); + cell.Visit(cellpair, player_notifier, *this, *obj, GetVisibilityDistance()); +} + +void Map::UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair) +{ + Trinity::VisibleNotifier notifier(*player); + + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + TypeContainerVisitor world_notifier(notifier); + TypeContainerVisitor grid_notifier(notifier); + cell.Visit(cellpair, world_notifier, *this, *player, GetVisibilityDistance()); + cell.Visit(cellpair, grid_notifier, *this, *player, GetVisibilityDistance()); + + // send data + notifier.SendToSelf(); +} +/* +void Map::PlayerRelocationNotify(Player* player, Cell cell, CellPair cellpair) +{ + Trinity::PlayerRelocationNotifier relocationNotifier(*player); + cell.data.Part.reserved = ALL_DISTRICT; + + TypeContainerVisitor p2grid_relocation(relocationNotifier); + TypeContainerVisitor p2world_relocation(relocationNotifier); + + cell.Visit(cellpair, p2grid_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS); + cell.Visit(cellpair, p2world_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS); +} + +void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellpair) +{ + Trinity::CreatureRelocationNotifier relocationNotifier(*creature); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); // not trigger load unloaded grids at notifier call + + TypeContainerVisitor c2world_relocation(relocationNotifier); + TypeContainerVisitor c2grid_relocation(relocationNotifier); + + cell.Visit(cellpair, c2world_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS); + cell.Visit(cellpair, c2grid_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS); +} +*/ + +void Map::SendInitSelf(Player * player) +{ + sLog.outDetail("Creating player data for himself %u", player->GetGUIDLow()); + + UpdateData data; + + // attach to player data current transport data + if (Transport* transport = player->GetTransport()) + { + transport->BuildCreateUpdateBlockForPlayer(&data, player); + } + + // build data for self presence in world at own client (one time for map) + player->BuildCreateUpdateBlockForPlayer(&data, player); + + // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map + if (Transport* transport = player->GetTransport()) + { + for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) + { + if (player != (*itr) && player->HaveAtClient(*itr)) + { + (*itr)->BuildCreateUpdateBlockForPlayer(&data, player); + } + } + } + + WorldPacket packet; + data.BuildPacket(&packet); + player->GetSession()->SendPacket(&packet); +} + +void Map::SendInitTransports(Player * player) +{ + // Hack to send out transports + MapManager::TransportMap& tmap = MapManager::Instance().m_TransportsByMap; + + // no transports at map + if (tmap.find(player->GetMapId()) == tmap.end()) + return; + + UpdateData transData; + + MapManager::TransportSet& tset = tmap[player->GetMapId()]; + + for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i) + { + // send data for current transport in other place + if ((*i) != player->GetTransport() && (*i)->GetMapId() == GetId()) + { + (*i)->BuildCreateUpdateBlockForPlayer(&transData, player); + } + } + + WorldPacket packet; + transData.BuildPacket(&packet); + player->GetSession()->SendPacket(&packet); +} + +void Map::SendRemoveTransports(Player * player) +{ + // Hack to send out transports + MapManager::TransportMap& tmap = MapManager::Instance().m_TransportsByMap; + + // no transports at map + if (tmap.find(player->GetMapId()) == tmap.end()) + return; + + UpdateData transData; + + MapManager::TransportSet& tset = tmap[player->GetMapId()]; + + // except used transport + for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i) + if ((*i) != player->GetTransport() && (*i)->GetMapId() != GetId()) + (*i)->BuildOutOfRangeUpdateBlock(&transData); + + WorldPacket packet; + transData.BuildPacket(&packet); + player->GetSession()->SendPacket(&packet); +} + +inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y) +{ + if (x >= MAX_NUMBER_OF_GRIDS || y >= MAX_NUMBER_OF_GRIDS) + { + sLog.outError("map::setNGrid() Invalid grid coordinates found: %d, %d!",x,y); + assert(false); + } + i_grids[x][y] = grid; +} + +void Map::DelayedUpdate(const uint32 t_diff) +{ + RemoveAllObjectsInRemoveList(); + + // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! + // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended + if (!IsBattleGroundOrArena()) + { + for (GridRefManager::iterator i = GridRefManager::begin(); i != GridRefManager::end();) + { + NGridType *grid = i->getSource(); + GridInfo *info = i->getSource()->getGridInfoRef(); + ++i; // The update might delete the map and we need the next map before the iterator gets invalid + assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE); + si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff); + } + } +} + +void Map::AddObjectToRemoveList(WorldObject *obj) +{ + assert(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId()); + + obj->CleanupsBeforeDelete(false); // remove or simplify at least cross referenced links + + i_objectsToRemove.insert(obj); + //sLog.outDebug("Object (GUID: %u TypeId: %u) added to removing list.",obj->GetGUIDLow(),obj->GetTypeId()); +} + +void Map::AddObjectToSwitchList(WorldObject *obj, bool on) +{ + assert(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId()); + + std::map::iterator itr = i_objectsToSwitch.find(obj); + if (itr == i_objectsToSwitch.end()) + i_objectsToSwitch.insert(itr, std::make_pair(obj, on)); + else if (itr->second != on) + i_objectsToSwitch.erase(itr); + else + assert(false); +} + +void Map::RemoveAllObjectsInRemoveList() +{ + while (!i_objectsToSwitch.empty()) + { + std::map::iterator itr = i_objectsToSwitch.begin(); + WorldObject *obj = itr->first; + bool on = itr->second; + i_objectsToSwitch.erase(itr); + + switch(obj->GetTypeId()) + { + case TYPEID_UNIT: + if (!obj->ToCreature()->isPet()) + SwitchGridContainers(obj->ToCreature(), on); + break; + } + } + + //sLog.outDebug("Object remover 1 check."); + while (!i_objectsToRemove.empty()) + { + std::set::iterator itr = i_objectsToRemove.begin(); + WorldObject* obj = *itr; + + switch(obj->GetTypeId()) + { + case TYPEID_CORPSE: + { + Corpse* corpse = ObjectAccessor::Instance().GetCorpse(*obj, obj->GetGUID()); + if (!corpse) + sLog.outError("Tried to delete corpse/bones %u that is not in map.", obj->GetGUIDLow()); + else + Remove(corpse,true); + break; + } + case TYPEID_DYNAMICOBJECT: + Remove((DynamicObject*)obj,true); + break; + case TYPEID_GAMEOBJECT: + Remove((GameObject*)obj,true); + break; + case TYPEID_UNIT: + // in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call + // make sure that like sources auras/etc removed before destructor start + obj->ToCreature()->CleanupsBeforeDelete(); + Remove(obj->ToCreature(),true); + break; + default: + sLog.outError("Non-grid object (TypeId: %u) is in grid object remove list, ignored.",obj->GetTypeId()); + break; + } + + i_objectsToRemove.erase(itr); + } + + //sLog.outDebug("Object remover 2 check."); +} + +uint32 Map::GetPlayersCountExceptGMs() const +{ + uint32 count = 0; + for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + if (!itr->getSource()->isGameMaster()) + ++count; + return count; +} + +void Map::SendToPlayers(WorldPacket const* data) const +{ + for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + itr->getSource()->GetSession()->SendPacket(data); +} + +bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const +{ + ASSERT(x < MAX_NUMBER_OF_GRIDS); + ASSERT(y < MAX_NUMBER_OF_GRIDS); + + CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS); + CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); + + //we must find visible range in cells so we unload only non-visible cells... + float viewDist = GetVisibilityDistance(); + int cell_range = (int)ceilf(viewDist / SIZE_OF_GRID_CELL) + 1; + + cell_min << cell_range; + cell_min -= cell_range; + cell_max >> cell_range; + cell_max += cell_range; + + for (MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter) + { + Player* plr = iter->getSource(); + + CellPair p = Trinity::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY()); + if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && + (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord)) + return true; + } + + for (ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter) + { + WorldObject* obj = *iter; + + CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); + if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) && + (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord)) + return true; + } + + return false; +} + +void Map::AddToActive(Creature* c) +{ + AddToActiveHelper(c); + + // also not allow unloading spawn grid to prevent creating creature clone at load + if (!c->isPet() && c->GetDBTableGUIDLow()) + { + float x,y,z; + c->GetRespawnCoord(x,y,z); + GridPair p = Trinity::ComputeGridPair(x, y); + if (getNGrid(p.x_coord, p.y_coord)) + getNGrid(p.x_coord, p.y_coord)->incUnloadActiveLock(); + else + { + GridPair p2 = Trinity::ComputeGridPair(c->GetPositionX(), c->GetPositionY()); + sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] was not loaded.", + c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord); + } + } +} + +void Map::RemoveFromActive(Creature* c) +{ + RemoveFromActiveHelper(c); + + // also allow unloading spawn grid + if (!c->isPet() && c->GetDBTableGUIDLow()) + { + float x,y,z; + c->GetRespawnCoord(x,y,z); + GridPair p = Trinity::ComputeGridPair(x, y); + if (getNGrid(p.x_coord, p.y_coord)) + getNGrid(p.x_coord, p.y_coord)->decUnloadActiveLock(); + else + { + GridPair p2 = Trinity::ComputeGridPair(c->GetPositionX(), c->GetPositionY()); + sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] was not loaded.", + c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord); + } + } +} + +template void Map::Add(Corpse *); +template void Map::Add(Creature *); +template void Map::Add(GameObject *); +template void Map::Add(DynamicObject *); + +template void Map::Remove(Corpse *,bool); +template void Map::Remove(Creature *,bool); +template void Map::Remove(GameObject *, bool); +template void Map::Remove(DynamicObject *, bool); + +/* ******* Dungeon Instance Maps ******* */ + +InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent) + : Map(id, expiry, InstanceId, SpawnMode, _parent), + m_resetAfterUnload(false), m_unloadWhenEmpty(false), + i_data(NULL), i_script_id(0) +{ + //lets initialize visibility distance for dungeons + InstanceMap::InitVisibilityDistance(); + + // the timer is started by default, and stopped when the first player joins + // this make sure it gets unloaded if for some reason no player joins + m_unloadTimer = std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY); +} + +InstanceMap::~InstanceMap() +{ + if (i_data) + { + delete i_data; + i_data = NULL; + } +} + +void InstanceMap::InitVisibilityDistance() +{ + //init visibility distance for instances + m_VisibleDistance = World::GetMaxVisibleDistanceInInstances(); + m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInInstances(); +} + +/* + Do map specific checks to see if the player can enter +*/ +bool InstanceMap::CanEnter(Player *player) +{ + if (player->GetMapRef().getTarget() == this) + { + sLog.outError("InstanceMap::CanEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode()); + assert(false); + return false; + } + + // allow GM's to enter + if (player->isGameMaster()) + return Map::CanEnter(player); + + // cannot enter if the instance is full (player cap), GMs don't count + uint32 maxPlayers = GetMaxPlayers(); + if (GetPlayersCountExceptGMs() >= maxPlayers) + { + sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName()); + player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); + return false; + } + + // cannot enter while an encounter is in progress on raids + /*Group *pGroup = player->GetGroup(); + if (!player->isGameMaster() && pGroup && pGroup->InCombatToInstance(GetInstanceId()) && player->GetMapId() != GetId())*/ + if (IsRaid() && GetInstanceData() && GetInstanceData()->IsEncounterInProgress()) + { + player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); + return false; + } + + return Map::CanEnter(player); +} + +/* + Do map specific checks and add the player to the map if successful. +*/ +bool InstanceMap::Add(Player *player) +{ + // TODO: Not sure about checking player level: already done in HandleAreaTriggerOpcode + // GMs still can teleport player in instance. + // Is it needed? + + { + Guard guard(*this); + // Check moved to void WorldSession::HandleMoveWorldportAckOpcode() + //if (!CanEnter(player)) + //return false; + + // Dungeon only code + if (IsDungeon()) + { + // get or create an instance save for the map + InstanceSave *mapSave = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); + if (!mapSave) + { + sLog.outDetail("InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId()); + mapSave = sInstanceSaveManager.AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true); + } + + // check for existing instance binds + InstancePlayerBind *playerBind = player->GetBoundInstance(GetId(), Difficulty(GetSpawnMode())); + if (playerBind && playerBind->perm) + { + // cannot enter other instances if bound permanently + if (playerBind->save != mapSave) + { + sLog.outError("InstanceMap::Add: player %s(%d) is permanently bound to instance %d,%d,%d,%d,%d,%d but he is being put into instance %d,%d,%d,%d,%d,%d", player->GetName(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); + return false; + } + } + else + { + Group *pGroup = player->GetGroup(); + if (pGroup) + { + // solo saves should be reset when entering a group + InstanceGroupBind *groupBind = pGroup->GetBoundInstance(this); + if (playerBind) + { + sLog.outError("InstanceMap::Add: player %s(%d) is being put into instance %d,%d,%d,%d,%d,%d but he is in group %d and is bound to instance %d,%d,%d,%d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); + if (groupBind) sLog.outError("InstanceMap::Add: the group is bound to the instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); + //assert(false); + return false; + } + // bind to the group or keep using the group save + if (!groupBind) + pGroup->BindToInstance(mapSave, false); + else + { + // cannot jump to a different instance without resetting it + if (groupBind->save != mapSave) + { + sLog.outError("InstanceMap::Add: player %s(%d) is being put into instance %d,%d,%d but he is in group %d which is bound to instance %d,%d,%d!", player->GetName(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(pGroup->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); + if (mapSave) + sLog.outError("MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); + else + sLog.outError("MapSave NULL"); + if (groupBind->save) + sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount()); + else + sLog.outError("GroupBind save NULL"); + return false; + } + // if the group/leader is permanently bound to the instance + // players also become permanently bound when they enter + if (groupBind->perm) + { + WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); + data << uint32(0); + player->GetSession()->SendPacket(&data); + player->BindToInstance(mapSave, true); + } + } + } + else + { + // set up a solo bind or continue using it + if (!playerBind) + player->BindToInstance(mapSave, false); + else + // cannot jump to a different instance without resetting it + assert(playerBind->save == mapSave); + } + } + } + + // for normal instances cancel the reset schedule when the + // first player enters (no players yet) + SetResetSchedule(false); + + sLog.outDetail("MAP: Player '%s' entered instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName()); + // initialize unload state + m_unloadTimer = 0; + m_resetAfterUnload = false; + m_unloadWhenEmpty = false; + } + + // this will acquire the same mutex so it cannot be in the previous block + Map::Add(player); + + if (i_data) + i_data->OnPlayerEnter(player); + + return true; +} + +void InstanceMap::Update(const uint32& t_diff) +{ + Map::Update(t_diff); + + if (i_data) + i_data->Update(t_diff); +} + +void InstanceMap::Remove(Player *player, bool remove) +{ + sLog.outDetail("MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName()); + //if last player set unload timer + if (!m_unloadTimer && m_mapRefManager.getSize() == 1) + m_unloadTimer = m_unloadWhenEmpty ? MIN_UNLOAD_DELAY : std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY); + Map::Remove(player, remove); + // for normal instances schedule the reset after all players have left + SetResetSchedule(true); +} + +void InstanceMap::CreateInstanceData(bool load) +{ + if (i_data != NULL) + return; + + InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(GetId()); + if (mInstance) + { + i_script_id = mInstance->script_id; + i_data = sScriptMgr.CreateInstanceData(this); + } + + if (!i_data) + return; + + i_data->Initialize(); + + if (load) + { + // TODO: make a global storage for this + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT data FROM instance WHERE map = '%u' AND id = '%u'", GetId(), i_InstanceId); + if (result) + { + Field* fields = result->Fetch(); + std::string data = fields[0].GetString(); + if (data != "") + { + sLog.outDebug("Loading instance data for `%s` with id %u", objmgr.GetScriptName(i_script_id), i_InstanceId); + i_data->Load(data.c_str()); + } + } + } +} + +/* + Returns true if there are no players in the instance +*/ +bool InstanceMap::Reset(uint8 method) +{ + // note: since the map may not be loaded when the instance needs to be reset + // the instance must be deleted from the DB by InstanceSaveManager + + if (HavePlayers()) + { + if (method == INSTANCE_RESET_ALL) + { + // notify the players to leave the instance so it can be reset + for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + itr->getSource()->SendResetFailedNotify(GetId()); + } + else + { + if (method == INSTANCE_RESET_GLOBAL) + // set the homebind timer for players inside (1 minute) + for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + itr->getSource()->m_InstanceValid = false; + + // the unload timer is not started + // instead the map will unload immediately after the players have left + m_unloadWhenEmpty = true; + m_resetAfterUnload = true; + } + } + else + { + // unloaded at next update + m_unloadTimer = MIN_UNLOAD_DELAY; + m_resetAfterUnload = true; + } + + return m_mapRefManager.isEmpty(); +} + +void InstanceMap::PermBindAllPlayers(Player *player) +{ + if (!IsDungeon()) + return; + + InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); + if (!save) + { + sLog.outError("Cannot bind players, no instance save available for map!"); + return; + } + + Group *group = player->GetGroup(); + // group members outside the instance group don't get bound + for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + { + Player* plr = itr->getSource(); + // players inside an instance cannot be bound to other instances + // some players may already be permanently bound, in this case nothing happens + InstancePlayerBind *bind = plr->GetBoundInstance(save->GetMapId(), save->GetDifficulty()); + if (!bind || !bind->perm) + { + plr->BindToInstance(save, true); + WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); + data << uint32(0); + plr->GetSession()->SendPacket(&data); + } + + // if the leader is not in the instance the group will not get a perm bind + if (group && group->GetLeaderGUID() == plr->GetGUID()) + group->BindToInstance(save, true); + } +} + +void InstanceMap::UnloadAll() +{ + assert(!HavePlayers()); + + if (m_resetAfterUnload == true) + objmgr.DeleteRespawnTimeForInstance(GetInstanceId()); + + Map::UnloadAll(); +} + +void InstanceMap::SendResetWarnings(uint32 timeLeft) const +{ + for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + itr->getSource()->SendInstanceResetWarning(GetId(), itr->getSource()->GetDifficulty(IsRaid()), timeLeft); +} + +void InstanceMap::SetResetSchedule(bool on) +{ + // only for normal instances + // the reset time is only scheduled when there are no payers inside + // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled + if (IsDungeon() && !HavePlayers() && !IsRaidOrHeroicDungeon()) + { + InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId()); + if (!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId()); + else sInstanceSaveManager.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), Difficulty(GetSpawnMode()), GetInstanceId())); + } +} + +MapDifficulty const* Map::GetMapDifficulty() const +{ + return GetMapDifficultyData(GetId(),GetDifficulty()); +} + +uint32 InstanceMap::GetMaxPlayers() const +{ + if (MapDifficulty const* mapDiff = GetMapDifficulty()) + { + if (mapDiff->maxPlayers || IsRegularDifficulty()) // Normal case (expect that regular difficulty always have correct maxplayers) + return mapDiff->maxPlayers; + else // DBC have 0 maxplayers for heroic instances with expansion < 2 + { // The heroic entry exists, so we don't have to check anything, simply return normal max players + MapDifficulty const* normalDiff = GetMapDifficultyData(GetId(), REGULAR_DIFFICULTY); + return normalDiff ? normalDiff->maxPlayers : 0; + } + } + else // I'd rather assert(false); + return 0; +} + +uint32 InstanceMap::GetMaxResetDelay() const +{ + MapDifficulty const* mapDiff = GetMapDifficulty(); + return mapDiff ? mapDiff->resetTime : 0; +} + +/* ******* Battleground Instance Maps ******* */ + +BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent, uint8 spawnMode) + : Map(id, expiry, InstanceId, spawnMode, _parent) +{ + //lets initialize visibility distance for BG/Arenas + BattleGroundMap::InitVisibilityDistance(); +} + +BattleGroundMap::~BattleGroundMap() +{ +} + +void BattleGroundMap::InitVisibilityDistance() +{ + //init visibility distance for BG/Arenas + m_VisibleDistance = World::GetMaxVisibleDistanceInBGArenas(); + m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInBGArenas(); +} + +bool BattleGroundMap::CanEnter(Player * player) +{ + if (player->GetMapRef().getTarget() == this) + { + sLog.outError("BGMap::CanEnter - player %u is already in map!", player->GetGUIDLow()); + assert(false); + return false; + } + + if (player->GetBattleGroundId() != GetInstanceId()) + return false; + + // player number limit is checked in bgmgr, no need to do it here + + return Map::CanEnter(player); +} + +bool BattleGroundMap::Add(Player * player) +{ + { + Guard guard(*this); + //Check moved to void WorldSession::HandleMoveWorldportAckOpcode() + //if (!CanEnter(player)) + //return false; + // reset instance validity, battleground maps do not homebind + player->m_InstanceValid = true; + } + return Map::Add(player); +} + +void BattleGroundMap::Remove(Player *player, bool remove) +{ + sLog.outDetail("MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName()); + Map::Remove(player, remove); +} + +void BattleGroundMap::SetUnload() +{ + m_unloadTimer = MIN_UNLOAD_DELAY; +} + +void BattleGroundMap::RemoveAllPlayers() +{ + if (HavePlayers()) + for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) + if (Player* plr = itr->getSource()) + if (!plr->IsBeingTeleportedFar()) + plr->TeleportTo(plr->GetBattleGroundEntryPoint()); + +} + +/// Put scripts in the execution queue +void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target) +{ + ///- Find the script map + ScriptMapMap::const_iterator s = scripts.find(id); + if (s == scripts.end()) + return; + + // prepare static data + uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source + uint64 targetGUID = target ? target->GetGUID() : (uint64)0; + uint64 ownerGUID = (source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; + + ///- Schedule script execution for all scripts in the script map + ScriptMap const *s2 = &(s->second); + bool immedScript = false; + for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter) + { + ScriptAction sa; + sa.sourceGUID = sourceGUID; + sa.targetGUID = targetGUID; + sa.ownerGUID = ownerGUID; + + sa.script = &iter->second; + m_scriptSchedule.insert(std::pair(time_t(sWorld.GetGameTime() + iter->first), sa)); + if (iter->first == 0) + immedScript = true; + + sWorld.IncreaseScheduledScriptsCount(); + } + ///- If one of the effects should be immediate, launch the script execution + if (/*start &&*/ immedScript && !i_scriptLock) + { + i_scriptLock = true; + ScriptsProcess(); + i_scriptLock = false; + } +} + +void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target) +{ + // NOTE: script record _must_ exist until command executed + + // prepare static data + uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; + uint64 targetGUID = target ? target->GetGUID() : (uint64)0; + uint64 ownerGUID = (source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; + + ScriptAction sa; + sa.sourceGUID = sourceGUID; + sa.targetGUID = targetGUID; + sa.ownerGUID = ownerGUID; + + sa.script = &script; + m_scriptSchedule.insert(std::pair(time_t(sWorld.GetGameTime() + delay), sa)); + + sWorld.IncreaseScheduledScriptsCount(); + + ///- If effects should be immediate, launch the script execution + if (delay == 0 && !i_scriptLock) + { + i_scriptLock = true; + ScriptsProcess(); + i_scriptLock = false; + } +} + +/// Process queued scripts +void Map::ScriptsProcess() +{ + if (m_scriptSchedule.empty()) + return; + + ///- Process overdue queued scripts + std::multimap::iterator iter = m_scriptSchedule.begin(); + // ok as multimap is a *sorted* associative container + while (!m_scriptSchedule.empty() && (iter->first <= sWorld.GetGameTime())) + { + ScriptAction const& step = iter->second; + + Object* source = NULL; + + if (step.sourceGUID) + { + switch (GUID_HIPART(step.sourceGUID)) + { + case HIGHGUID_ITEM: + // case HIGHGUID_CONTAINER: == HIGHGUID_ITEM + { + Player* player = HashMapHolder::Find(step.ownerGUID); + if (player) + source = player->GetItemByGuid(step.sourceGUID); + break; + } + case HIGHGUID_UNIT: + source = HashMapHolder::Find(step.sourceGUID); + break; + case HIGHGUID_PET: + source = HashMapHolder::Find(step.sourceGUID); + break; + //case HIGHGUID_VEHICLE: + // source = HashMapHolder::Find(step.sourceGUID); + // break; + case HIGHGUID_PLAYER: + source = HashMapHolder::Find(step.sourceGUID); + break; + case HIGHGUID_GAMEOBJECT: + source = HashMapHolder::Find(step.sourceGUID); + break; + case HIGHGUID_CORPSE: + source = HashMapHolder::Find(step.sourceGUID); + break; + case HIGHGUID_MO_TRANSPORT: + for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) + { + if ((*iter)->GetGUID() == step.sourceGUID) + { + source = reinterpret_cast(*iter); + break; + } + } + break; + default: + sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID)); + break; + } + } + + //if (source && !source->IsInWorld()) source = NULL; + + Object* target = NULL; + + if (step.targetGUID) + { + switch (GUID_HIPART(step.targetGUID)) + { + case HIGHGUID_UNIT: + target = HashMapHolder::Find(step.targetGUID); + break; + case HIGHGUID_PET: + target = HashMapHolder::Find(step.targetGUID); + break; + //case HIGHGUID_VEHICLE: + // target = HashMapHolder::Find(step.targetGUID); + // break; + case HIGHGUID_PLAYER: // empty GUID case also + target = HashMapHolder::Find(step.targetGUID); + break; + case HIGHGUID_GAMEOBJECT: + target = HashMapHolder::Find(step.targetGUID); + break; + case HIGHGUID_CORPSE: + target = HashMapHolder::Find(step.targetGUID); + break; + default: + sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID)); + break; + } + } + + //if (target && !target->IsInWorld()) target = NULL; + + switch (step.script->command) + { + case SCRIPT_COMMAND_TALK: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) call for NULL source.", step.script->id); + break; + } + + Creature* cSource = NULL; + cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); + + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) call for non supported source (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(), source->GetEntry(), source->GetGUIDLow()); + break; + } + + if (step.script->datalong > CHAT_TYPE_WHISPER) + { + sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) invalid chat type (%u), skipping.", step.script->id, step.script->datalong); + break; + } + + uint64 unit_target = target ? target->GetGUID() : 0; + + //datalong 0=normal say, 1=whisper, 2=yell, 3=emote text, 4=boss emote text + //TODO: Update for more chat types + switch (step.script->datalong) + { + case CHAT_TYPE_SAY: // Say + cSource->Say(step.script->dataint, LANG_UNIVERSAL, unit_target); + break; + case CHAT_TYPE_YELL: // Yell + cSource->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target); + break; + case CHAT_TYPE_TEXT_EMOTE: // Emote text + cSource->TextEmote(step.script->dataint, unit_target); + break; + case CHAT_TYPE_BOSS_EMOTE: // Boss Emote text + cSource->MonsterTextEmote(step.script->dataint, unit_target, true); + break; + case CHAT_TYPE_WHISPER: // Whisper + if (!unit_target || !IS_PLAYER_GUID(unit_target)) + { + sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) attempt to whisper (%u) NULL, skipping.", step.script->id, + step.script->datalong); + break; + } + cSource->Whisper(step.script->dataint,unit_target); + break; + default: + break; // must be already checked at load + } + break; + } + + case SCRIPT_COMMAND_EMOTE: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_EMOTE (script id: %u) call for NULL source.", step.script->id); + break; + } + + Creature* cSource = NULL; + cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); + + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_TALK (script id: %u) call for non supported source (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(), source->GetEntry(), source->GetGUIDLow()); + break; + } + + if (step.script->datalong2) + cSource->SetUInt32Value(UNIT_NPC_EMOTESTATE, step.script->datalong); + else + cSource->HandleEmoteCommand(step.script->datalong); + break; + } + + case SCRIPT_COMMAND_FIELD_SET: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_FIELD_SET (script id: %u) call for NULL source.", step.script->id); + break; + } + + Creature* cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_FIELD_SET (script id: %u) call for non-creature source.", step.script->id); + break; + } + + if (step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= cSource->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FIELD_SET (script id: %u) call for wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u).", + step.script->id, step.script->datalong,source->GetValuesCount(),source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + cSource->SetUInt32Value(step.script->datalong, step.script->datalong2); + break; + } + + case SCRIPT_COMMAND_MOVE_TO: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_MOVE_TO (script id: %u) call for NULL creature.", step.script->id); + break; + } + + Creature* cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_MOVE_TO (script id: %u) call for non-creature (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + cSource->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2); + cSource->GetMap()->CreatureRelocation(cSource, step.script->x, step.script->y, step.script->z, 0); + break; + } + + case SCRIPT_COMMAND_FLAG_SET: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_FLAG_SET (script id: %u) call for NULL object.", step.script->id); + break; + } + + Creature* cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_FLAG_SET (script id: %u) call for non-creature source.", step.script->id); + break; + } + + if (step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= cSource->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FLAG_SET (script id: %u) call for wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u).", + step.script->id, step.script->datalong,source->GetValuesCount(),source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + cSource->SetFlag(step.script->datalong, step.script->datalong2); + break; + } + + case SCRIPT_COMMAND_FLAG_REMOVE: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE (script id: %u) call for NULL object.", step.script->id); + break; + } + + Creature* cSource = source->ToCreature() != NULL ? source->ToCreature() : target->ToCreature(); + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE (script id: %u) call for non-creature source.", step.script->id); + break; + } + + if (step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= cSource->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE (script id: %u) call for wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u).", + step.script->id, step.script->datalong,source->GetValuesCount(),source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + cSource->RemoveFlag(step.script->datalong, step.script->datalong2); + break; + } + + case SCRIPT_COMMAND_TELEPORT_TO: + { + // accept object in any one from target/source arg + if (!target && !source) + { + sLog.outError("SCRIPT_COMMAND_TELEPORT_TO (script id: %u) call for NULL object.", step.script->id); + break; + } + + if (step.script->datalong2 == 0) + { + Player* pSource = target->ToPlayer() != NULL ? target->ToPlayer() : source->ToPlayer(); + // must be only Player + if (!pSource) + { + sLog.outError("SCRIPT_COMMAND_TELEPORT_TO (script id: %u) call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", + step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); + break; + } + + pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o); + } + else if (step.script->datalong2 == 1) + { + Creature *cSource = target->ToCreature() != NULL ? target->ToCreature() : source->ToCreature(); + // must be only Creature + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_TELEPORT_TO (script id: %u) call for non-creature (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", + step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); + break; + } + + cSource->NearTeleportTo(step.script->x, step.script->y, step.script->z, step.script->o); + } + break; + } + + case SCRIPT_COMMAND_KILL_CREDIT: + { + // accept player in any one from target/source arg + if (!target && !source) + { + sLog.outError("SCRIPT_COMMAND_KILL_CREDIT (script id: %u) call for NULL object.", step.script->id); + break; + } + + Player* pSource = target->ToPlayer() != NULL ? target->ToPlayer() : source->ToPlayer(); + // must be only Player + if (!pSource) + { + sLog.outError("SCRIPT_COMMAND_KILL_CREDIT (script id: %u) call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", + step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); + break; + } + + if (step.script->datalong2) + pSource->RewardPlayerAndGroupAtEvent(step.script->datalong, pSource); + else + pSource->KilledMonsterCredit(step.script->datalong, 0); + + break; + } + + case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: + { + if (!step.script->datalong) // creature not specified + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE (script id: %u) call with no creature parameter.", step.script->id); + break; + } + + if (!source) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE (script id: %u) call for NULL source object.", step.script->id); + break; + } + + WorldObject* summoner = dynamic_cast(source); + + if (!summoner) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE (script id: %u) call for non-WorldObject (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + float x = step.script->x; + float y = step.script->y; + float z = step.script->z; + float o = step.script->o; + + Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2); + if (!pCreature) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON (script id: %u) failed for creature (entry: %u).", step.script->id, step.script->datalong); + break; + } + + break; + } + + case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: + { + if (!step.script->datalong) // gameobject not specified + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) call with no gameobject parameter.", step.script->id); + break; + } + + if (!source) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) call for NULL source object.", step.script->id); + break; + } + + WorldObject* summoner = dynamic_cast(source); + + if (!summoner) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) call for non-WorldObject (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + GameObject *go = NULL; + int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2; + + CellPair p(Trinity::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + Trinity::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong); + Trinity::GameObjectSearcher checker(summoner, go,go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + cell.Visit(p, object_checker, *summoner->GetMap()); + + if (!go) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) failed for gameobject(guid: %u).", step.script->id, step.script->datalong); + break; + } + + if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE || + go->GetGoType() == GAMEOBJECT_TYPE_DOOR || + go->GetGoType() == GAMEOBJECT_TYPE_BUTTON || + go->GetGoType() == GAMEOBJECT_TYPE_TRAP) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT (script id: %u) can not be used with gameobject of type %u (guid: %u).", + step.script->id, uint32(go->GetGoType()), step.script->datalong); + break; + } + + if (go->isSpawned()) + break; //gameobject already spawned + + go->SetLootState(GO_READY); + go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds + + go->GetMap()->Add(go); + break; + } + case SCRIPT_COMMAND_OPEN_DOOR: + { + if (!step.script->datalong) // door not specified + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) call for NULL target door.", step.script->id); + break; + } + + if (!source) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) call for NULL source unit.", step.script->id); + break; + } + + if (!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) call for non-unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + GameObject *door = NULL; + WorldObject* wSource = (WorldObject*)source; + + int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; + + CellPair p(Trinity::ComputeCellPair(wSource->GetPositionX(), wSource->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + Trinity::GameObjectWithDbGUIDCheck go_check(*wSource, step.script->datalong); + Trinity::GameObjectSearcher checker(wSource, door, go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + cell.Visit(p, object_checker, *wSource->GetMap()); + + if (!door) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) failed for gameobject(guid: %u).", step.script->id, step.script->datalong); + break; + } + if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR (script id: %u) failed for non-door(GoType: %u, Entry: %u, GUID: %u).", + step.script->id, door->GetGoType(),door->GetEntry(),door->GetGUIDLow()); + break; + } + + if (door->GetGoState() != GO_STATE_READY) + break; //door already open + + door->UseDoorOrButton(time_to_close); + + if (target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType() == GAMEOBJECT_TYPE_BUTTON) + ((GameObject*)target)->UseDoorOrButton(time_to_close); + break; + } + case SCRIPT_COMMAND_CLOSE_DOOR: + { + if (!step.script->datalong) // guid for door not specified + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) call for NULL door.", step.script->id); + break; + } + + if (!source) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) call for NULL unit.", step.script->id); + break; + } + + if (!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) call for non-unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + GameObject *door = NULL; + WorldObject* wSource = (WorldObject*)source; + + int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; + + CellPair p(Trinity::ComputeCellPair(wSource->GetPositionX(), wSource->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + Trinity::GameObjectWithDbGUIDCheck go_check(*wSource, step.script->datalong); + Trinity::GameObjectSearcher checker(wSource, door, go_check); + + TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); + cell.Visit(p, object_checker, *wSource->GetMap()); + + if (!door) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) failed for gameobject(guid: %u).", step.script->id, step.script->datalong); + break; + } + if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR (script id: %u) failed for non-door(GoType: %u, Entry: %u, GUID: %u).", + step.script->id, door->GetGoType(),door->GetEntry(),door->GetGUIDLow()); + break; + } + + if (door->GetGoState() == GO_STATE_READY) + break; //door already closed + + door->UseDoorOrButton(time_to_open); + + if (target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType() == GAMEOBJECT_TYPE_BUTTON) + ((GameObject*)target)->UseDoorOrButton(time_to_open); + + break; + } + case SCRIPT_COMMAND_QUEST_EXPLORED: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for NULL source.", step.script->id); + break; + } + + if (!target) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for NULL target.", step.script->id); + break; + } + + // when script called for item spell casting then target == (unit or GO) and source is player + WorldObject* worldObject; + Player* pTarget; + + pTarget = target->ToPlayer(); + if (pTarget) + { + if (source->GetTypeId() != TYPEID_UNIT && source->GetTypeId() != TYPEID_GAMEOBJECT && source->GetTypeId() != TYPEID_PLAYER) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for non-creature, non-gameobject or non-player (TypeId: %u), skipping.", + step.script->id, source->GetTypeId()); + break; + } + + worldObject = (WorldObject*)source; + } + else + { + if (target->GetTypeId() != TYPEID_UNIT && target->GetTypeId() != TYPEID_GAMEOBJECT && target->GetTypeId() != TYPEID_PLAYER) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for non-creature, non-gameobject or non-player (TypeId: %u), skipping.", + step.script->id, target->GetTypeId()); + break; + } + + pTarget = source->ToPlayer(); + if (!pTarget) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED (script id %u) call for non-player (TypeId: %u), skipping.", step.script->id, source->GetTypeId()); + break; + } + + worldObject = (WorldObject*)target; + } + + // quest id and flags checked at script loading + if ((worldObject->GetTypeId() != TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) && + (step.script->datalong2 == 0 || worldObject->IsWithinDistInMap(pTarget, float(step.script->datalong2)))) + pTarget->AreaExploredOrEventHappens(step.script->datalong); + else + pTarget->FailQuest(step.script->datalong); + + break; + } + + case SCRIPT_COMMAND_ACTIVATE_OBJECT: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT (script id: %u) must have source caster.", step.script->id); + break; + } + + if (!source->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT (script id: %u) source caster isn't unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + if (!target) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT (script id: %u) call for NULL gameobject.", step.script->id); + break; + } + + if (target->GetTypeId() != TYPEID_GAMEOBJECT) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT (script id: %u) call for non-gameobject (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, target->GetTypeId(),target->GetEntry(),target->GetGUIDLow()); + break; + } + + Unit* caster = (Unit*)source; + + GameObject *go = (GameObject*)target; + + go->Use(caster); + break; + } + + case SCRIPT_COMMAND_REMOVE_AURA: + { + Object* cmdTarget = step.script->datalong2 ? source : target; + + if (!cmdTarget) + { + sLog.outError("SCRIPT_COMMAND_REMOVE_AURA (script id: %u) call for NULL %s.", step.script->id, step.script->datalong2 ? "source" : "target"); + break; + } + + if (!cmdTarget->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_REMOVE_AURA (script id: %u) %s isn't unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId(),cmdTarget->GetEntry(),cmdTarget->GetGUIDLow()); + break; + } + + ((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong); + break; + } + + case SCRIPT_COMMAND_CAST_SPELL: + { + // TODO: Allow gameobjects to be targets and casters + if (!source) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL (script id: %u) must have source caster.", step.script->id); + break; + } + + Unit* uSource = NULL; + Unit* uTarget = NULL; + // source/target cast spell at target/source (script->datalong2: 0: s->t 1: s->s 2: t->t 3: t->s + switch (step.script->datalong2) + { + case 0: // source -> target + uSource = dynamic_cast(source); + uTarget = dynamic_cast(target); + break; + case 1: // source -> source + uSource = dynamic_cast(source); + uTarget = dynamic_cast(source); + break; + case 2: // target -> target + uSource = dynamic_cast(target); + uTarget = dynamic_cast(target); + break; + case 3: // target -> source + uSource = dynamic_cast(target); + uTarget = dynamic_cast(source); + break; + case 4: // creature + uSource = dynamic_cast(source); + uTarget = GetClosestCreatureWithEntry(uSource, step.script->dataint, step.script->x); + break; + } + + if (!uSource || !uSource->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL (script id: %u) no source unit found for spell %u", step.script->id, step.script->datalong); + break; + } + + if (!uTarget || !uTarget->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL (script id: %u) no target unit found for spell %u", step.script->id, step.script->datalong); + break; + } + + uSource->CastSpell(uTarget, step.script->datalong, false); + break; + } + + case SCRIPT_COMMAND_PLAY_SOUND: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_PLAY_SOUND (script id: %u) call for NULL creature.", step.script->id); + break; + } + + WorldObject* pSource = dynamic_cast(source); + if (!pSource) + { + sLog.outError("SCRIPT_COMMAND_PLAY_SOUND (script id: %u) call for non-world object (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + // bitmask: 0/1=anyone/target, 0/2=with distance dependent + Player* pTarget; + if (step.script->datalong2 & 1) + { + if (!target) + { + sLog.outError("SCRIPT_COMMAND_PLAY_SOUND (script id: %u) in targeted mode call for NULL target.", step.script->id); + break; + } + + pTarget = target->ToPlayer(); + if (!pTarget) + { + sLog.outError("SCRIPT_COMMAND_PLAY_SOUND (script id: %u) in targeted mode call for non-player (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, target->GetTypeId(),target->GetEntry(),target->GetGUIDLow()); + break; + } + } + + // bitmask: 0/1=anyone/target, 0/2=with distance dependent + if (step.script->datalong2 & 2) + pSource->PlayDistanceSound(step.script->datalong, pTarget); + else + pSource->PlayDirectSound(step.script->datalong, pTarget); + break; + } + + case SCRIPT_COMMAND_CREATE_ITEM: + { + if (!target && !source) + { + sLog.outError("SCRIPT_COMMAND_CREATE_ITEM (script id: %u) call for NULL object.", step.script->id); + break; + } + + Player *pReceiver = target->ToPlayer() != NULL ? target->ToPlayer() : source->ToPlayer(); + // only Player + if (!pReceiver) + { + sLog.outError("SCRIPT_COMMAND_CREATE_ITEM (script id: %u) call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", + step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); + break; + } + + ItemPosCountVec dest; + uint8 msg = pReceiver->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, step.script->datalong, step.script->datalong2); + if (msg == EQUIP_ERR_OK) + { + if (Item* item = pReceiver->StoreNewItem(dest, step.script->datalong, true)) + pReceiver->SendNewItem(item, step.script->datalong2, false, true); + } + else + pReceiver->SendEquipError(msg,NULL,NULL); + + break; + } + + case SCRIPT_COMMAND_DESPAWN_SELF: + { + if (!target && !source) + { + sLog.outError("SCRIPT_COMMAND_DESPAWN_SELF (script id: %u) call for NULL object.", step.script->id); + break; + } + + Creature* cSource = target->ToCreature(); + // only creature + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_DESPAWN_SELF (script id: %u) call for non-creature (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", + step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); + break; + } + + cSource->ForcedDespawn(step.script->datalong); + break; + } + + case SCRIPT_COMMAND_LOAD_PATH: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_START_MOVE (script id: %u) cannot be applied to NON-existing unit.", step.script->id); + break; + } + + if (!source->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_START_MOVE (script id: %u) source mover isn't unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", + step.script->id, source->GetTypeId(),source->GetEntry(),source->GetGUIDLow()); + break; + } + + if (!sWaypointMgr->GetPath(step.script->datalong)) + { + sLog.outError("SCRIPT_COMMAND_START_MOVE (script id: %u) source mover has an invalid path, skipping.", step.script->id, step.script->datalong2); + break; + } + + ((Unit*)source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2); + break; + } + + case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT: + { + if (!step.script->datalong || !step.script->datalong2) + { + sLog.outError("SCRIPT_COMMAND_CALLSCRIPT (script id: %u) calls invalid db_script_id or lowguid not present: skipping.", step.script->id); + break; + } + + Creature* cTarget; + if (source) //using grid searcher + { + WorldObject* wSource = (WorldObject*)source; + CellPair p(Trinity::ComputeCellPair(wSource->GetPositionX(), wSource->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + Trinity::CreatureWithDbGUIDCheck target_check(wSource, step.script->datalong); + Trinity::CreatureSearcher checker(wSource, cTarget, target_check); + + TypeContainerVisitor, GridTypeMapContainer > unit_checker(checker); + cell.Visit(p, unit_checker, *wSource->GetMap()); + } + else //check hashmap holders + { + if (CreatureData const* data = objmgr.GetCreatureData(step.script->datalong)) + cTarget = ObjectAccessor::GetObjectInWorld(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->datalong, data->id, HIGHGUID_UNIT), cTarget); + } + + if (!cTarget) + { + sLog.outError("SCRIPT_COMMAND_CALLSCRIPT (script id: %u) target not found, creature entry %u", step.script->id, step.script->datalong); + break; + } + + //Lets choose our ScriptMap map + ScriptMapMap *datamap = NULL; + switch (step.script->dataint) + { + case 1: //QUEST END SCRIPTMAP + datamap = &sQuestEndScripts; + break; + case 2: //QUEST START SCRIPTMAP + datamap = &sQuestStartScripts; + break; + case 3: //SPELLS SCRIPTMAP + datamap = &sSpellScripts; + break; + case 4: //GAMEOBJECTS SCRIPTMAP + datamap = &sGameObjectScripts; + break; + case 5: //EVENTS SCRIPTMAP + datamap = &sEventScripts; + break; + case 6: //WAYPOINTS SCRIPTMAP + datamap = &sWaypointScripts; + break; + default: + sLog.outError("SCRIPT_COMMAND_CALLSCRIPT ERROR: no scriptmap present... ignoring"); + break; + } + //if no scriptmap present... + if (!datamap) + break; + + uint32 script_id = step.script->datalong2; + //insert script into schedule but do not start it + ScriptsStart(*datamap, script_id, cTarget, NULL/*, false*/); + break; + } + + case SCRIPT_COMMAND_KILL: + { + // TODO: Allow to kill objects other than self? + if (!source) + break; + + Creature* cSource = source->ToCreature(); + if (!cSource) + break; + + if (cSource->isDead()) + { + sLog.outError("SCRIPT_COMMAND_KILL (script id: %u) called for already dead creature, entry %u, guidLow %u", + step.script->id, cSource->GetEntry(), cSource->GetGUIDLow()); + break; + } + + cSource->setDeathState(JUST_DIED); + if (step.script->dataint == 1) + cSource->RemoveCorpse(); + + break; + } + + case SCRIPT_COMMAND_ORIENTATION: + { + if (!source || !source->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_ORIENTATION (script id: %u) call for NULL or non-unit source.", step.script->id); + break; + } + + Unit* uSource = (Unit*)source; + + if (!step.script->datalong) + uSource->SetOrientation(step.script->o); + else + { + if (!target || !target->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_ORIENTATION (script id: %u) call for NULL or non-unit target.", step.script->id); + break; + } + uSource->SetInFront((Unit*)target); + } + + uSource->SendMovementFlagUpdate(); + break; + } + case SCRIPT_COMMAND_EQUIP: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_EQUIP (script id: %u) call for NULL source.", step.script->id); + break; + } + + Creature* cSource = source->ToCreature(); + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_EQUIP (script id: %u) call, source is non-creature.", step.script->id); + break; + } + + cSource->LoadEquipment(step.script->datalong); + break; + } + case SCRIPT_COMMAND_MODEL: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_EQUIP (script id: %u) call for NULL source.", step.script->id); + break; + } + + Creature* cSource = source->ToCreature(); + if (!cSource) + { + sLog.outError("SCRIPT_COMMAND_EQUIP (script id: %u) call, source is non-creature.", step.script->id); + break; + } + + cSource->SetDisplayId(step.script->datalong); + break; + } + + case SCRIPT_COMMAND_CLOSE_GOSSIP: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_GOSSIP (script id: %u) for null source", step.script->id); + break; + } + + Player *pSource = source->ToPlayer(); + if (!pSource) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_GOSSIP (script id: %u) for non-player source.", step.script->id); + break; + } + + pSource->PlayerTalkClass->CloseGossip(); + break; + } + + case SCRIPT_COMMAND_PLAYMOVIE: + { + if (!source) + { + sLog.outError("SCRIPT_COMMAND_PLAYMOVIE (script id: %u) call for NULL source.", step.script->id); + break; + } + + Player* pSource = source->ToPlayer(); + if (!pSource) + { + sLog.outError("SCRIPT_COMMAND_PLAYMOVIE (script id: %u) call for non-player source.", step.script->id); + break; + } + pSource->SendMovieStart(step.script->datalong); + break; + } + + default: + sLog.outError("Unknown script command %u called.", step.script->command); + break; + } + + m_scriptSchedule.erase(iter); + sWorld.DecreaseScheduledScriptCount(); + + iter = m_scriptSchedule.begin(); + } +} + +Creature* +Map::GetCreature(uint64 guid) +{ + Creature * ret = NULL; + if (IS_CRE_OR_VEH_GUID(guid)) + ret = ObjectAccessor::GetObjectInWorld(guid, (Creature*)NULL); + + if (!ret) + return NULL; + + if (ret->GetMapId() != GetId()) + return NULL; + + if (ret->GetInstanceId() != GetInstanceId()) + return NULL; + + return ret; +} + +GameObject* +Map::GetGameObject(uint64 guid) +{ + GameObject * ret = ObjectAccessor::GetObjectInWorld(guid, (GameObject*)NULL); + if (!ret) + return NULL; + if (ret->GetMapId() != GetId()) + return NULL; + if (ret->GetInstanceId() != GetInstanceId()) + return NULL; + return ret; +} + +DynamicObject* +Map::GetDynamicObject(uint64 guid) +{ + DynamicObject * ret = ObjectAccessor::GetObjectInWorld(guid, (DynamicObject*)NULL); + if (!ret) + return NULL; + if (ret->GetMapId() != GetId()) + return NULL; + if (ret->GetInstanceId() != GetInstanceId()) + return NULL; + return ret; +} + +void Map::UpdateIteratorBack(Player *player) +{ + if (m_mapRefIter == player->GetMapRef()) + m_mapRefIter = m_mapRefIter->nocheck_prev(); +} diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h new file mode 100644 index 00000000000..ceb526b8244 --- /dev/null +++ b/src/server/game/Maps/Map.h @@ -0,0 +1,689 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_MAP_H +#define TRINITY_MAP_H + +#include "Platform/Define.h" +#include "Policies/ThreadingModel.h" +#include "ace/RW_Thread_Mutex.h" +#include "ace/Thread_Mutex.h" + +#include "DBCStructure.h" +#include "GridDefines.h" +#include "Cell.h" +#include "Timer.h" +#include "SharedDefines.h" +#include "GameSystem/GridRefManager.h" +#include "MapRefManager.h" +#include "mersennetwister/MersenneTwister.h" + +#include +#include + +class Unit; +class WorldPacket; +class InstanceData; +class Group; +class InstanceSave; +class Object; +class WorldObject; +class TempSummon; +class Player; +class CreatureGroup; +struct ScriptInfo; +struct ScriptAction; +struct Position; +class BattleGround; + +//****************************************** +// Map file format defines +//****************************************** +#define MAP_MAGIC 'SPAM' +#define MAP_VERSION_MAGIC '0.1w' +#define MAP_AREA_MAGIC 'AERA' +#define MAP_HEIGHT_MAGIC 'TGHM' +#define MAP_LIQUID_MAGIC 'QILM' + +struct map_fileheader +{ + uint32 mapMagic; + uint32 versionMagic; + uint32 areaMapOffset; + uint32 areaMapSize; + uint32 heightMapOffset; + uint32 heightMapSize; + uint32 liquidMapOffset; + uint32 liquidMapSize; +}; + +#define MAP_AREA_NO_AREA 0x0001 + +struct map_areaHeader +{ + uint32 fourcc; + uint16 flags; + uint16 gridArea; +}; + +#define MAP_HEIGHT_NO_HEIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 + +struct map_heightHeader +{ + uint32 fourcc; + uint32 flags; + float gridHeight; + float gridMaxHeight; +}; + +#define MAP_LIQUID_NO_TYPE 0x0001 +#define MAP_LIQUID_NO_HEIGHT 0x0002 + +struct map_liquidHeader +{ + uint32 fourcc; + uint16 flags; + uint16 liquidType; + uint8 offsetX; + uint8 offsetY; + uint8 width; + uint8 height; + float liquidLevel; +}; + +enum ZLiquidStatus +{ + LIQUID_MAP_NO_WATER = 0x00000000, + LIQUID_MAP_ABOVE_WATER = 0x00000001, + LIQUID_MAP_WATER_WALK = 0x00000002, + LIQUID_MAP_IN_WATER = 0x00000004, + LIQUID_MAP_UNDER_WATER = 0x00000008 +}; + +#define MAP_LIQUID_TYPE_NO_WATER 0x00 +#define MAP_LIQUID_TYPE_WATER 0x01 +#define MAP_LIQUID_TYPE_OCEAN 0x02 +#define MAP_LIQUID_TYPE_MAGMA 0x04 +#define MAP_LIQUID_TYPE_SLIME 0x08 + +#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME) + +#define MAP_LIQUID_TYPE_DARK_WATER 0x10 +#define MAP_LIQUID_TYPE_WMO_WATER 0x20 + +struct LiquidData +{ + uint32 type; + float level; + float depth_level; +}; + +class GridMap +{ + uint32 m_flags; + // Area data + uint16 m_gridArea; + uint16 *m_area_map; + // Height level data + float m_gridHeight; + float m_gridIntHeightMultiplier; + union{ + float *m_V9; + uint16 *m_uint16_V9; + uint8 *m_uint8_V9; + }; + union{ + float *m_V8; + uint16 *m_uint16_V8; + uint8 *m_uint8_V8; + }; + // Liquid data + uint16 m_liquidType; + uint8 m_liquid_offX; + uint8 m_liquid_offY; + uint8 m_liquid_width; + uint8 m_liquid_height; + float m_liquidLevel; + uint8 *m_liquid_type; + float *m_liquid_map; + + bool loadAreaData(FILE *in, uint32 offset, uint32 size); + bool loadHeihgtData(FILE *in, uint32 offset, uint32 size); + bool loadLiquidData(FILE *in, uint32 offset, uint32 size); + + // Get height functions and pointers + typedef float (GridMap::*pGetHeightPtr) (float x, float y) const; + pGetHeightPtr m_gridGetHeight; + float getHeightFromFloat(float x, float y) const; + float getHeightFromUint16(float x, float y) const; + float getHeightFromUint8(float x, float y) const; + float getHeightFromFlat(float x, float y) const; + +public: + GridMap(); + ~GridMap(); + bool loadData(char *filaname); + void unloadData(); + + uint16 getArea(float x, float y); + inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);} + float getLiquidLevel(float x, float y); + uint8 getTerrainType(float x, float y); + ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0); +}; + +struct CreatureMover +{ + CreatureMover() : x(0), y(0), z(0), ang(0) {} + CreatureMover(float _x, float _y, float _z, float _ang) : x(_x), y(_y), z(_z), ang(_ang) {} + + float x, y, z, ang; +}; + +// 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 +#if defined(__GNUC__) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +struct InstanceTemplate +{ + uint32 map; + uint32 parent; + uint32 access_id; + float startLocX; + float startLocY; + float startLocZ; + float startLocO; + uint32 script_id; + bool allowMount; +}; + +enum LevelRequirementVsMode +{ + LEVELREQUIREMENT_HEROIC = 70 +}; + +#if defined(__GNUC__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +typedef UNORDERED_MAP CreatureMoveList; + +#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface +#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE +#define MIN_UNLOAD_DELAY 1 // immediate unload + +typedef std::map CreatureGroupHolderType; + +class Map : public GridRefManager, public Trinity::ObjectLevelLockable +{ + friend class MapReference; + public: + Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL); + virtual ~Map(); + + // currently unused for normal maps + bool CanUnload(uint32 diff) + { + if (!m_unloadTimer) return false; + if (m_unloadTimer <= diff) return true; + m_unloadTimer -= diff; + return false; + } + + virtual bool Add(Player *); + virtual void Remove(Player *, bool); + template void Add(T *); + template void Remove(T *, bool); + + virtual void Update(const uint32&); + + /* + void MessageBroadcast(Player *, WorldPacket *, bool to_self); + void MessageBroadcast(WorldObject *, WorldPacket *); + void MessageDistBroadcast(Player *, WorldPacket *, float dist, bool to_self, bool own_team_only = false); + void MessageDistBroadcast(WorldObject *, WorldPacket *, float dist); + */ + + float GetVisibilityDistance() const { return m_VisibleDistance; } + //function for setting up visibility distance for maps on per-type/per-Id basis + virtual void InitVisibilityDistance(); + + void PlayerRelocation(Player *, float x, float y, float z, float orientation); + void CreatureRelocation(Creature *creature, float x, float y, float z, float ang); + + template void Visit(const Cell& cell, TypeContainerVisitor &visitor); + + bool IsRemovalGrid(float x, float y) const + { + GridPair p = Trinity::ComputeGridPair(x, y); + return !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL; + } + + bool IsLoaded(float x, float y) const + { + GridPair p = Trinity::ComputeGridPair(x, y); + return loaded(p); + } + + bool GetUnloadLock(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); } + void SetUnloadLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); } + void LoadGrid(float x, float y); + bool UnloadGrid(const uint32 &x, const uint32 &y, bool pForce); + virtual void UnloadAll(); + + void ResetGridExpiry(NGridType &grid, float factor = 1) const + { + grid.ResetTimeTracker(time_t(float(i_gridExpiry)*factor)); + } + + time_t GetGridExpiry(void) const { return i_gridExpiry; } + uint32 GetId(void) const { return i_mapEntry->MapID; } + + static bool ExistMap(uint32 mapid, int gx, int gy); + static bool ExistVMap(uint32 mapid, int gx, int gy); + + static void InitStateMachine(); + static void DeleteStateMachine(); + + Map const * GetParent() const { return m_parentMap; } + + // some calls like isInWater should not use vmaps due to processor power + // can return INVALID_HEIGHT if under z+2 z coord not found height + float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; + + ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0) const; + + uint16 GetAreaFlag(float x, float y, float z, bool *isOutdoors=0) const; + bool GetAreaInfo(float x, float y, float z, uint32 &mogpflags, int32 &adtId, int32 &rootId, int32 &groupId) const; + + bool IsOutdoors(float x, float y, float z) const; + + uint8 GetTerrainType(float x, float y) const; + float GetWaterLevel(float x, float y) const; + bool IsInWater(float x, float y, float z, LiquidData *data = 0) const; + bool IsUnderWater(float x, float y, float z) const; + + static uint32 GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id); + static uint32 GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id); + static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id); + + uint32 GetAreaId(float x, float y, float z) const + { + return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),GetId()); + } + + uint32 GetZoneId(float x, float y, float z) const + { + return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),GetId()); + } + + void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const + { + GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),GetId()); + } + + void MoveAllCreaturesInMoveList(); + void RemoveAllObjectsInRemoveList(); + virtual void RemoveAllPlayers(); + + bool CreatureRespawnRelocation(Creature *c); // used only in MoveAllCreaturesInMoveList and ObjectGridUnloader + + // assert print helper + bool CheckGridIntegrity(Creature* c, bool moved) const; + + uint32 GetInstanceId() const { return i_InstanceId; } + uint8 GetSpawnMode() const { return (i_spawnMode); } + virtual bool CanEnter(Player* /*player*/) { return true; } + const char* GetMapName() const; + + // have meaning only for instanced map (that have set real difficulty) + Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); } + bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; } + MapDifficulty const* GetMapDifficulty() const; + + bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); } + // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable + bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); } + bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); } + bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); } + bool IsRaidOrHeroicDungeon() const { return IsRaid() || i_spawnMode > DUNGEON_DIFFICULTY_NORMAL; } + bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; } + bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); } + bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } + bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); } + bool GetEntrancePos(int32 &mapid, float &x, float &y) + { + if (!i_mapEntry) + return false; + return i_mapEntry->GetEntrancePos(mapid, x, y); + } + + void AddObjectToRemoveList(WorldObject *obj); + void AddObjectToSwitchList(WorldObject *obj, bool on); + virtual void DelayedUpdate(const uint32 diff); + + virtual bool RemoveBones(uint64 guid, float x, float y); + + void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair); + void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair); + + void resetMarkedCells() { marked_cells.reset(); } + bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } + void markCell(uint32 pCellId) { marked_cells.set(pCellId); } + + bool HavePlayers() const { return !m_mapRefManager.isEmpty(); } + uint32 GetPlayersCountExceptGMs() const; + bool ActiveObjectsNearGrid(uint32 x, uint32 y) const; + + void AddWorldObject(WorldObject *obj) { i_worldObjects.insert(obj); } + void RemoveWorldObject(WorldObject *obj) { i_worldObjects.erase(obj); } + + void SendToPlayers(WorldPacket const* data) const; + + typedef MapRefManager PlayerList; + PlayerList const& GetPlayers() const { return m_mapRefManager; } + + //per-map script storage + void ScriptsStart(std::map > const& scripts, uint32 id, Object* source, Object* target); + void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); + + // must called with AddToWorld + template + void AddToActive(T* obj) { AddToActiveHelper(obj); } + + void AddToActive(Creature* obj); + + // must called with RemoveFromWorld + template + void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); } + + void RemoveFromActive(Creature* obj); + + template void SwitchGridContainers(T* obj, bool active); + template void VisitAll(const float &x, const float &y, float radius, NOTIFIER ¬ifier); + template void VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier); + template void VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier); + CreatureGroupHolderType CreatureGroupHolder; + + void UpdateIteratorBack(Player *player); + +#ifdef MAP_BASED_RAND_GEN + MTRand mtRand; + int32 irand(int32 min, int32 max) { return int32 (mtRand.randInt(max - min)) + min; } + uint32 urand(uint32 min, uint32 max) { return mtRand.randInt(max - min) + min; } + int32 rand32() { return mtRand.randInt(); } + double rand_norm() { return mtRand.randExc(); } + double rand_chance() { return mtRand.randExc(100.0); } +#endif + + TempSummon *SummonCreature(uint32 entry, const Position &pos, SummonPropertiesEntry const *properties = NULL, uint32 duration = 0, Unit *summoner = NULL, uint32 vehId = 0); + Creature* GetCreature(uint64 guid); + GameObject* GetGameObject(uint64 guid); + DynamicObject* GetDynamicObject(uint64 guid); + private: + void LoadMapAndVMap(int gx, int gy); + void LoadVMap(int gx, int gy); + void LoadMap(int gx,int gy, bool reload = false); + GridMap *GetGrid(float x, float y); + + void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } + + void SendInitSelf(Player * player); + + void SendInitTransports(Player * player); + void SendRemoveTransports(Player * player); + + bool CreatureCellRelocation(Creature *creature, Cell new_cell); + + void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang); + CreatureMoveList i_creaturesToMove; + + bool loaded(const GridPair &) const; + void EnsureGridCreated(const GridPair &); + bool EnsureGridLoaded(Cell const&); + void EnsureGridLoadedAtEnter(Cell const&, Player* player = NULL); + + void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } + + template void AddType(T *obj); + template void RemoveType(T *obj, bool); + + NGridType* getNGrid(uint32 x, uint32 y) const + { + ASSERT(x < MAX_NUMBER_OF_GRIDS); + ASSERT(y < MAX_NUMBER_OF_GRIDS); + return i_grids[x][y]; + } + + bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); } + void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); } + + void setNGrid(NGridType* grid, uint32 x, uint32 y); + void ScriptsProcess(); + + void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff); + protected: + void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); } + + typedef Trinity::ObjectLevelLockable::Lock Guard; + + MapEntry const* i_mapEntry; + uint8 i_spawnMode; + uint32 i_InstanceId; + uint32 m_unloadTimer; + float m_VisibleDistance; + + MapRefManager m_mapRefManager; + MapRefManager::iterator m_mapRefIter; + + int32 m_VisibilityNotifyPeriod; + + typedef std::set ActiveNonPlayers; + ActiveNonPlayers m_activeNonPlayers; + ActiveNonPlayers::iterator m_activeNonPlayersIter; + + private: + time_t i_gridExpiry; + + //used for fast base_map (e.g. MapInstanced class object) search for + //InstanceMaps and BattleGroundMaps... + Map* m_parentMap; + + NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; + GridMap *GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; + std::bitset marked_cells; + + //these functions used to process player/mob aggro reactions and + //visibility calculations. Highly optimized for massive calculations + void ProcessRelocationNotifies(const uint32 &diff); + + bool i_scriptLock; + std::set i_objectsToRemove; + std::map i_objectsToSwitch; + std::set i_worldObjects; + std::multimap m_scriptSchedule; + + // Type specific code for add/remove to/from grid + template + void AddToGrid(T*, NGridType *, Cell const&); + + template + void RemoveFromGrid(T*, NGridType *, Cell const&); + + template + void DeleteFromWorld(T*); + + template + void AddToActiveHelper(T* obj) + { + m_activeNonPlayers.insert(obj); + } + + template + void RemoveFromActiveHelper(T* obj) + { + // Map::Update for active object in proccess + if (m_activeNonPlayersIter != m_activeNonPlayers.end()) + { + ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj); + if (itr == m_activeNonPlayers.end()) + return; + if (itr == m_activeNonPlayersIter) + ++m_activeNonPlayersIter; + m_activeNonPlayers.erase(itr); + } + else + m_activeNonPlayers.erase(obj); + } +}; + +enum InstanceResetMethod +{ + INSTANCE_RESET_ALL, + INSTANCE_RESET_CHANGE_DIFFICULTY, + INSTANCE_RESET_GLOBAL, + INSTANCE_RESET_GROUP_DISBAND, + INSTANCE_RESET_GROUP_JOIN, + INSTANCE_RESET_RESPAWN_DELAY +}; + +class InstanceMap : public Map +{ + public: + InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent); + ~InstanceMap(); + bool Add(Player *); + void Remove(Player *, bool); + void Update(const uint32&); + void CreateInstanceData(bool load); + bool Reset(uint8 method); + uint32 GetScriptId() { return i_script_id; } + InstanceData* GetInstanceData() { return i_data; } + void PermBindAllPlayers(Player *player); + void UnloadAll(); + bool CanEnter(Player* player); + void SendResetWarnings(uint32 timeLeft) const; + void SetResetSchedule(bool on); + + uint32 GetMaxPlayers() const; + uint32 GetMaxResetDelay() const; + + virtual void InitVisibilityDistance(); + private: + bool m_resetAfterUnload; + bool m_unloadWhenEmpty; + InstanceData* i_data; + uint32 i_script_id; +}; + +class BattleGroundMap : public Map +{ + public: + BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode); + ~BattleGroundMap(); + + bool Add(Player *); + void Remove(Player *, bool); + bool CanEnter(Player* player); + void SetUnload(); + //void UnloadAll(bool pForce); + void RemoveAllPlayers(); + + virtual void InitVisibilityDistance(); + BattleGround* GetBG() { return m_bg; } + void SetBG(BattleGround* bg) { m_bg = bg; } + private: + BattleGround* m_bg; +}; + +/*inline +uint64 +Map::CalculateGridMask(const uint32 &y) const +{ + uint64 mask = 1; + mask <<= y; + return mask; +} +*/ + +template +inline void +Map::Visit(const Cell& cell, TypeContainerVisitor &visitor) +{ + const uint32 x = cell.GridX(); + const uint32 y = cell.GridY(); + const uint32 cell_x = cell.CellX(); + const uint32 cell_y = cell.CellY(); + + if (!cell.NoCreate() || loaded(GridPair(x,y))) + { + EnsureGridLoaded(cell); + getNGrid(x, y)->Visit(cell_x, cell_y, visitor); + } +} + +template +inline void +Map::VisitAll(const float &x, const float &y, float radius, NOTIFIER ¬ifier) +{ + CellPair p(Trinity::ComputeCellPair(x, y)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + TypeContainerVisitor world_object_notifier(notifier); + cell.Visit(p, world_object_notifier, *this, radius, x, y); + TypeContainerVisitor grid_object_notifier(notifier); + cell.Visit(p, grid_object_notifier, *this, radius, x, y); +} + +template +inline void +Map::VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier) +{ + CellPair p(Trinity::ComputeCellPair(x, y)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + TypeContainerVisitor world_object_notifier(notifier); + cell.Visit(p, world_object_notifier, *this, radius, x, y); +} + +template +inline void +Map::VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier) +{ + CellPair p(Trinity::ComputeCellPair(x, y)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + TypeContainerVisitor grid_object_notifier(notifier); + cell.Visit(p, grid_object_notifier, *this, radius, x, y); +} +#endif diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp new file mode 100644 index 00000000000..0736bfa6fb3 --- /dev/null +++ b/src/server/game/Maps/MapInstanced.cpp @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MapInstanced.h" +#include "ObjectMgr.h" +#include "MapManager.h" +#include "BattleGround.h" +#include "VMapFactory.h" +#include "InstanceSaveMgr.h" +#include "World.h" + +MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DUNGEON_DIFFICULTY_NORMAL) +{ + // initialize instanced maps list + m_InstancedMaps.clear(); + // fill with zero + memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_GRIDS*sizeof(uint16)); +} + +void MapInstanced::InitVisibilityDistance() +{ + if (m_InstancedMaps.empty()) + return; + //initialize visibility distances for all instance copies + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) + { + (*i).second->InitVisibilityDistance(); + } +} + +void MapInstanced::Update(const uint32& t) +{ + // take care of loaded GridMaps (when unused, unload it!) + Map::Update(t); + + // update the instanced maps + InstancedMaps::iterator i = m_InstancedMaps.begin(); + + while (i != m_InstancedMaps.end()) + { + if (i->second->CanUnload(t)) + { + if (!DestroyInstance(i)) // iterator incremented + { + //m_unloadTimer + } + } + else + { + // update only here, because it may schedule some bad things before delete + i->second->Update(t); + ++i; + } + } +} + +void MapInstanced::DelayedUpdate(const uint32 diff) +{ + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) + i->second->DelayedUpdate(diff); + + Map::DelayedUpdate(diff); // this may be removed +} + +/* +void MapInstanced::RelocationNotify() +{ + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) + i->second->RelocationNotify(); +} +*/ + +bool MapInstanced::RemoveBones(uint64 guid, float x, float y) +{ + bool remove_result = false; + + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) + { + remove_result = remove_result || i->second->RemoveBones(guid, x, y); + } + + return remove_result || Map::RemoveBones(guid,x,y); +} + +void MapInstanced::UnloadAll() +{ + // Unload instanced maps + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) + i->second->UnloadAll(); + + // Delete the maps only after everything is unloaded to prevent crashes + for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i) + delete i->second; + + m_InstancedMaps.clear(); + + // Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!) + Map::UnloadAll(); +} + +/* +- return the right instance for the object, based on its InstanceId +- create the instance if it's not created already +- the player is not actually added to the instance (only in InstanceMap::Add) +*/ +Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player) +{ + if (GetId() != mapId || !player) + return NULL; + + Map* map = NULL; + uint32 NewInstanceId = 0; // instanceId of the resulting map + + if (IsBattleGroundOrArena()) + { + // instantiate or find existing bg map for player + // the instance id is set in battlegroundid + NewInstanceId = player->GetBattleGroundId(); + if (!NewInstanceId) return NULL; + map = _FindMap(NewInstanceId); + if (!map) + map = CreateBattleGround(NewInstanceId, player->GetBattleGround()); + } + else + { + InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid())); + InstanceSave *pSave = pBind ? pBind->save : NULL; + + // the player's permanent player bind is taken into consideration first + // then the player's group bind and finally the solo bind. + if (!pBind || !pBind->perm) + { + InstanceGroupBind *groupBind = NULL; + Group *group = player->GetGroup(); + // use the player's difficulty setting (it may not be the same as the group's) + if (group) + { + groupBind = group->GetBoundInstance(this); + if (groupBind) + pSave = groupBind->save; + } + } + if (pSave) + { + // solo/perm/group + NewInstanceId = pSave->GetInstanceId(); + map = _FindMap(NewInstanceId); + // it is possible that the save exists but the map doesn't + if (!map) + map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty()); + } + else + { + // if no instanceId via group members or instance saves is found + // the instance will be created for the first time + NewInstanceId = MapManager::Instance().GenerateInstanceId(); + + Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); + map = CreateInstance(NewInstanceId, NULL, diff); + } + } + + return map; +} + +InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, Difficulty difficulty) +{ + // load/create a map + Guard guard(*this); + + // make sure we have a valid map id + const MapEntry* entry = sMapStore.LookupEntry(GetId()); + if (!entry) + { + sLog.outError("CreateInstance: no entry for map %d", GetId()); + assert(false); + } + const InstanceTemplate * iTemplate = objmgr.GetInstanceTemplate(GetId()); + if (!iTemplate) + { + sLog.outError("CreateInstance: no instance template for map %d", GetId()); + assert(false); + } + + // some instances only have one difficulty + MapDifficulty const* mapDiff = GetMapDifficultyData(GetId(),difficulty); + if (!mapDiff) + difficulty = DUNGEON_DIFFICULTY_NORMAL; + + sLog.outDebug("MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); + + InstanceMap *map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this); + ASSERT(map->IsDungeon()); + + bool load_data = save != NULL; + map->CreateInstanceData(load_data); + + m_InstancedMaps[InstanceId] = map; + return map; +} + +BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId, BattleGround* bg) +{ + // load/create a map + Guard guard(*this); + + sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId()); + + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),bg->GetMinLevel()); + + uint8 spawnMode = bracketEntry ? bracketEntry->difficulty : REGULAR_DIFFICULTY; + + BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode); + ASSERT(map->IsBattleGroundOrArena()); + map->SetBG(bg); + bg->SetBgMap(map); + + m_InstancedMaps[InstanceId] = map; + return map; +} + +// increments the iterator after erase +bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) +{ + itr->second->RemoveAllPlayers(); + if (itr->second->HavePlayers()) + { + ++itr; + return false; + } + + itr->second->UnloadAll(); + // should only unload VMaps if this is the last instance and grid unloading is enabled + if (m_InstancedMaps.size() <= 1 && sWorld.getConfig(CONFIG_GRID_UNLOAD)) + { + VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId()); + // in that case, unload grids of the base map, too + // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded + Map::UnloadAll(); + } + // erase map + delete itr->second; + m_InstancedMaps.erase(itr++); + return true; +} + +bool MapInstanced::CanEnter(Player * /*player*/) +{ + //assert(false); + return true; +} diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h new file mode 100644 index 00000000000..536257da011 --- /dev/null +++ b/src/server/game/Maps/MapInstanced.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_MAP_INSTANCED_H +#define TRINITY_MAP_INSTANCED_H + +#include "Map.h" +#include "InstanceSaveMgr.h" +#include "DBCEnums.h" + +class MapInstanced : public Map +{ + friend class MapManager; + public: + typedef UNORDERED_MAP< uint32, Map* > InstancedMaps; + + MapInstanced(uint32 id, time_t expiry); + ~MapInstanced() {} + + // functions overwrite Map versions + void Update(const uint32&); + void DelayedUpdate(const uint32 diff); + //void RelocationNotify(); + bool RemoveBones(uint64 guid, float x, float y); + void UnloadAll(); + bool CanEnter(Player* player); + + Map* CreateInstance(const uint32 mapId, Player * player); + Map* FindMap(uint32 InstanceId) const { return _FindMap(InstanceId); } + bool DestroyInstance(InstancedMaps::iterator &itr); + + void AddGridMapReference(const GridPair &p) + { + ++GridMapReference[p.x_coord][p.y_coord]; + SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), true); + } + + void RemoveGridMapReference(GridPair const& p) + { + --GridMapReference[p.x_coord][p.y_coord]; + if (!GridMapReference[p.x_coord][p.y_coord]) + SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), false); + } + + InstancedMaps &GetInstancedMaps() { return m_InstancedMaps; } + virtual void InitVisibilityDistance(); + + private: + + InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave *save, Difficulty difficulty); + BattleGroundMap* CreateBattleGround(uint32 InstanceId, BattleGround* bg); + + InstancedMaps m_InstancedMaps; + + Map* _FindMap(uint32 InstanceId) const + { + InstancedMaps::const_iterator i = m_InstancedMaps.find(InstanceId); + return(i == m_InstancedMaps.end() ? NULL : i->second); + } + + uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; +}; +#endif diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp new file mode 100644 index 00000000000..de3d0ebbaff --- /dev/null +++ b/src/server/game/Maps/MapManager.cpp @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MapManager.h" +#include "InstanceSaveMgr.h" +#include "Policies/SingletonImp.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "ObjectAccessor.h" +#include "Transports.h" +#include "GridDefines.h" +#include "MapInstanced.h" +#include "InstanceData.h" +#include "DestinationHolderImp.h" +#include "Config/ConfigEnv.h" +#include "World.h" +#include "CellImpl.h" +#include "Corpse.h" +#include "ObjectMgr.h" +#include "Language.h" +#include "WorldPacket.h" + +#define CLASS_LOCK Trinity::ClassLevelLockable +INSTANTIATE_SINGLETON_2(MapManager, CLASS_LOCK); +INSTANTIATE_CLASS_MUTEX(MapManager, ACE_Thread_Mutex); + +extern GridState* si_GridStates[]; // debugging code, should be deleted some day + +MapManager::MapManager() +{ + i_gridCleanUpDelay = sWorld.getConfig(CONFIG_INTERVAL_GRIDCLEAN); + i_timer.SetInterval(sWorld.getConfig(CONFIG_INTERVAL_MAPUPDATE)); +} + +MapManager::~MapManager() +{ + for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) + delete iter->second; + + for (TransportSet::iterator i = m_Transports.begin(); i != m_Transports.end(); ++i) + delete *i; + + Map::DeleteStateMachine(); +} + +void MapManager::Initialize() +{ + Map::InitStateMachine(); + + // debugging code, should be deleted some day + { + for (uint8 i = 0; i < MAX_GRID_STATE; ++i) + i_GridStates[i] = si_GridStates[i]; + + i_GridStateErrorCount = 0; + } + int num_threads(sWorld.getConfig(CONFIG_NUMTHREADS)); + // Start mtmaps if needed. + if (num_threads > 0 && m_updater.activate(num_threads) == -1) + abort(); + + InitMaxInstanceId(); +} + +void MapManager::InitializeVisibilityDistanceInfo() +{ + for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) + (*iter).second->InitVisibilityDistance(); +} + +// debugging code, should be deleted some day +void MapManager::checkAndCorrectGridStatesArray() +{ + bool ok = true; + for (int i=0; icheckMagic()) + { + ok = false; + si_GridStates[i]->setMagic(); + } + #endif + } + if (!ok) + ++i_GridStateErrorCount; +} + +Map* MapManager::_createBaseMap(uint32 id) +{ + Map *m = _findMap(id); + + if (m == NULL) + { + Guard guard(*this); + + const MapEntry* entry = sMapStore.LookupEntry(id); + if (entry && entry->Instanceable()) + { + m = new MapInstanced(id, i_gridCleanUpDelay); + } + else + { + m = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); + } + i_maps[id] = m; + } + + assert(m != NULL); + return m; +} + +Map* MapManager::CreateMap(uint32 id, const WorldObject* obj, uint32 /*instanceId*/) +{ + ASSERT(obj); + //if (!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId()); + Map *m = _createBaseMap(id); + + if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable()) m = ((MapInstanced*)m)->CreateInstance(id, (Player*)obj); + + return m; +} + +Map* MapManager::FindMap(uint32 mapid, uint32 instanceId) const +{ + Map *map = _findMap(mapid); + if (!map) + return NULL; + + if (!map->Instanceable()) + return instanceId == 0 ? map : NULL; + + return ((MapInstanced*)map)->FindMap(instanceId); +} + +bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) +{ + const MapEntry *entry = sMapStore.LookupEntry(mapid); + if (!entry) + return false; + + if (!entry->IsDungeon()) + return true; + + const char *mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; + + Group* pGroup = player->GetGroup(); + if (entry->IsRaid()) + { + // can only enter in a raid group + // GMs can avoid raid limitations + if ((!pGroup || !pGroup->isRaidGroup()) && !player->isGameMaster() && !sWorld.getConfig(CONFIG_INSTANCE_IGNORE_RAID)) + { + // probably there must be special opcode, because client has this string constant in GlobalStrings.lua + // TODO: this is not a good place to send the message + player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName); + sLog.outDebug("MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName(), mapName); + return false; + } + } + + //The player has a heroic mode and tries to enter into instance which has no a heroic mode + MapDifficulty const* mapDiff = GetMapDifficultyData(entry->MapID,player->GetDifficulty(entry->IsRaid())); + if (!mapDiff) + { + bool isNormalTargetMap = entry->IsRaid() + ? (player->GetRaidDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + : (player->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL); + + // Send aborted message + // FIX ME: what about absent normal/heroic mode with specific players limit... + player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, isNormalTargetMap ? DUNGEON_DIFFICULTY_NORMAL : DUNGEON_DIFFICULTY_HEROIC); + return false; + } + + if (!player->isAlive()) + { + if (Corpse *corpse = player->GetCorpse()) + { + // let enter in ghost mode in instance that connected to inner instance with corpse + uint32 instance_map = corpse->GetMapId(); + do + { + if (instance_map == mapid) + break; + + InstanceTemplate const* instance = objmgr.GetInstanceTemplate(instance_map); + instance_map = instance ? instance->parent : 0; + } + while (instance_map); + + if (!instance_map) + { + WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE); + player->GetSession()->SendPacket(&data); + sLog.outDebug("MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName(), mapName); + return false; + } + sLog.outDebug("MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName(), mapName); + } + else + sLog.outDebug("Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName()); + } + + InstanceTemplate const* instance = objmgr.GetInstanceTemplate(mapid); + if (!instance) + return false; + + //Get instance where player's group is bound & its map + if (pGroup) + { + InstanceGroupBind* boundedInstance = pGroup->GetBoundInstance(player); + if (boundedInstance && boundedInstance->save) + { + if (Map *boundedMap = MapManager::Instance().FindMap(mapid,boundedInstance->save->GetInstanceId())) + { + // Player permanently bounded to different instance than groups one + InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDungeonDifficulty()); + if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save && + boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId()) + { + //TODO: send some kind of error message to the player + return false; + } + + // Encounters in progress + if (!loginCheck && entry->IsRaid() && ((InstanceMap*)boundedMap)->GetInstanceData() && ((InstanceMap*)boundedMap)->GetInstanceData()->IsEncounterInProgress()) + { + sLog.outDebug("MAP: Player '%s' cannot enter instance '%s' while an encounter is in progress.", player->GetName(), mapName); + player->SendTransferAborted(mapid, TRANSFER_ABORT_ZONE_IN_COMBAT); + return false; + } + + // Instance is full + MapDifficulty const* mapDiff = ((InstanceMap*)boundedMap)->GetMapDifficulty(); + int8 maxPlayers = mapDiff ? mapDiff->maxPlayers : 0; + if (maxPlayers != -1) //-1: unlimited access + { + if (boundedMap->GetPlayersCountExceptGMs() >= (loginCheck ? maxPlayers+1 : maxPlayers)) + { + sLog.outDebug("MAP: Player '%s' cannot enter instance '%s' because it is full.", player->GetName(), mapName); + player->SendTransferAborted(mapid, TRANSFER_ABORT_MAX_PLAYERS); + return false; + } + } + } + } + } + + //Other requirements + return player->Satisfy(objmgr.GetAccessRequirement(instance->access_id), mapid, true); +} + +void MapManager::RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y) +{ + bool remove_result = _createBaseMap(mapid)->RemoveBones(guid, x, y); + + if (!remove_result) + { + sLog.outDebug("Bones %u not found in world. Delete from DB also.", GUID_LOPART(guid)); + } +} + +void MapManager::Update(uint32 diff) +{ + i_timer.Update(diff); + if (!i_timer.Passed()) + return; + + MapMapType::iterator iter = i_maps.begin(); + for (; iter != i_maps.end(); ++iter) + { + if (m_updater.activated()) + m_updater.schedule_update(*iter->second, i_timer.GetCurrent()); + else + { + iter->second->Update(i_timer.GetCurrent()); + } + } + if (m_updater.activated()) + m_updater.wait(); + + for (iter = i_maps.begin(); iter != i_maps.end(); ++iter) + iter->second->DelayedUpdate(i_timer.GetCurrent()); + + ObjectAccessor::Instance().Update(i_timer.GetCurrent()); + for (TransportSet::iterator iter = m_Transports.begin(); iter != m_Transports.end(); ++iter) + (*iter)->Update(i_timer.GetCurrent()); + + i_timer.SetCurrent(0); +} + +void MapManager::DoDelayedMovesAndRemoves() +{ +} + +bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y) +{ + GridPair p = Trinity::ComputeGridPair(x,y); + + int gx=63-p.x_coord; + int gy=63-p.y_coord; + + return Map::ExistMap(mapid,gx,gy) && Map::ExistVMap(mapid,gx,gy); +} + +bool MapManager::IsValidMAP(uint32 mapid) +{ + MapEntry const* mEntry = sMapStore.LookupEntry(mapid); + return mEntry && (!mEntry->IsDungeon() || objmgr.GetInstanceTemplate(mapid)); + // TODO: add check for battleground template +} + +void MapManager::UnloadAll() +{ + for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) + iter->second->UnloadAll(); + + while (!i_maps.empty()) + { + delete i_maps.begin()->second; + i_maps.erase(i_maps.begin()); + } + + if (m_updater.activated()) + m_updater.deactivate(); +} + +void MapManager::InitMaxInstanceId() +{ + i_MaxInstanceId = 0; + + QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(id) FROM instance"); + if (result) + i_MaxInstanceId = result->Fetch()[0].GetUInt32(); +} + +uint32 MapManager::GetNumInstances() +{ + Guard guard(*this); + + uint32 ret = 0; + for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr) + { + Map *map = itr->second; + if (!map->Instanceable()) + continue; + MapInstanced::InstancedMaps &maps = ((MapInstanced *)map)->GetInstancedMaps(); + for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr) + if (mitr->second->IsDungeon()) ret++; + } + return ret; +} + +uint32 MapManager::GetNumPlayersInInstances() +{ + Guard guard(*this); + + uint32 ret = 0; + for (MapMapType::iterator itr = i_maps.begin(); itr != i_maps.end(); ++itr) + { + Map *map = itr->second; + if (!map->Instanceable()) + continue; + MapInstanced::InstancedMaps &maps = ((MapInstanced *)map)->GetInstancedMaps(); + for (MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr) + if (mitr->second->IsDungeon()) + ret += ((InstanceMap*)mitr->second)->GetPlayers().getSize(); + } + return ret; +} diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h new file mode 100644 index 00000000000..d94f9fced0e --- /dev/null +++ b/src/server/game/Maps/MapManager.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_MAPMANAGER_H +#define TRINITY_MAPMANAGER_H + +#include "Platform/Define.h" +#include "Policies/Singleton.h" +#include "ace/Thread_Mutex.h" +#include "Common.h" +#include "Map.h" +#include "GridStates.h" +#include "MapUpdater.h" + +class Transport; + +class MapManager : public Trinity::Singleton > +{ + + friend class Trinity::OperatorNew; + typedef UNORDERED_MAP MapMapType; + typedef std::pair::iterator, bool> MapMapPair; + + public: + + Map* CreateMap(uint32, const WorldObject* obj, uint32 instanceId); + Map const* CreateBaseMap(uint32 id) const { return const_cast(this)->_createBaseMap(id); } + Map* FindMap(uint32 mapid, uint32 instanceId = 0) const; + + uint16 GetAreaFlag(uint32 mapid, float x, float y, float z) const + { + Map const* m = CreateBaseMap(mapid); + return m->GetAreaFlag(x, y, z); + } + uint32 GetAreaId(uint32 mapid, float x, float y, float z) const + { + return Map::GetAreaIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid); + } + uint32 GetZoneId(uint32 mapid, float x, float y, float z) const + { + return Map::GetZoneIdByAreaFlag(GetAreaFlag(mapid, x, y, z),mapid); + } + void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) + { + Map::GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(mapid, x, y, z),mapid); + } + + void Initialize(void); + void Update(uint32); + + void SetGridCleanUpDelay(uint32 t) + { + if (t < MIN_GRID_DELAY) + i_gridCleanUpDelay = MIN_GRID_DELAY; + else + i_gridCleanUpDelay = t; + } + + void SetMapUpdateInterval(uint32 t) + { + if (t > MIN_MAP_UPDATE_DELAY) + t = MIN_MAP_UPDATE_DELAY; + + i_timer.SetInterval(t); + i_timer.Reset(); + } + + //void LoadGrid(int mapid, int instId, float x, float y, const WorldObject* obj, bool no_unload = false); + void UnloadAll(); + + static bool ExistMapAndVMap(uint32 mapid, float x, float y); + static bool IsValidMAP(uint32 mapid); + + static bool IsValidMapCoord(uint32 mapid, float x,float y) + { + return IsValidMAP(mapid) && Trinity::IsValidMapCoord(x,y); + } + + static bool IsValidMapCoord(uint32 mapid, float x,float y,float z) + { + return IsValidMAP(mapid) && Trinity::IsValidMapCoord(x,y,z); + } + + static bool IsValidMapCoord(uint32 mapid, float x,float y,float z,float o) + { + return IsValidMAP(mapid) && Trinity::IsValidMapCoord(x,y,z,o); + } + + static bool IsValidMapCoord(WorldLocation const& loc) + { + return IsValidMapCoord(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation()); + } + + void DoDelayedMovesAndRemoves(); + + void LoadTransports(); + + typedef std::set TransportSet; + TransportSet m_Transports; + + typedef std::map TransportMap; + TransportMap m_TransportsByMap; + + bool CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck = false); + void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y); + uint32 GenerateInstanceId() { return ++i_MaxInstanceId; } + void InitMaxInstanceId(); + void InitializeVisibilityDistanceInfo(); + + /* statistics */ + uint32 GetNumInstances(); + uint32 GetNumPlayersInInstances(); + + private: + // debugging code, should be deleted some day + void checkAndCorrectGridStatesArray(); // just for debugging to find some memory overwrites + GridState* i_GridStates[MAX_GRID_STATE]; // shadow entries to the global array in Map.cpp + int i_GridStateErrorCount; + private: + MapManager(); + ~MapManager(); + + MapManager(const MapManager &); + MapManager& operator=(const MapManager &); + + Map* _createBaseMap(uint32 id); + Map* _findMap(uint32 id) const + { + MapMapType::const_iterator iter = i_maps.find(id); + return (iter == i_maps.end() ? NULL : iter->second); + } + + typedef Trinity::ClassLevelLockable::Lock Guard; + uint32 i_gridCleanUpDelay; + MapMapType i_maps; + IntervalTimer i_timer; + + uint32 i_MaxInstanceId; + MapUpdater m_updater; +}; +#endif diff --git a/src/server/game/Maps/MapRefManager.h b/src/server/game/Maps/MapRefManager.h new file mode 100644 index 00000000000..4337aa75fd9 --- /dev/null +++ b/src/server/game/Maps/MapRefManager.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MAPREFMANAGER +#define _MAPREFMANAGER + +#include "Utilities/LinkedReference/RefManager.h" + +class MapReference; + +class MapRefManager : public RefManager +{ + public: + typedef LinkedListHead::Iterator< MapReference > iterator; + typedef LinkedListHead::Iterator< MapReference const > const_iterator; + + MapReference* getFirst() { return (MapReference*)RefManager::getFirst(); } + MapReference const* getFirst() const { return (MapReference const*)RefManager::getFirst(); } + MapReference* getLast() { return (MapReference*)RefManager::getLast(); } + MapReference const* getLast() const { return (MapReference const*)RefManager::getLast(); } + + iterator begin() { return iterator(getFirst()); } + iterator end() { return iterator(NULL); } + iterator rbegin() { return iterator(getLast()); } + iterator rend() { return iterator(NULL); } + const_iterator begin() const { return const_iterator(getFirst()); } + const_iterator end() const { return const_iterator(NULL); } +}; +#endif + diff --git a/src/server/game/Maps/MapReference.h b/src/server/game/Maps/MapReference.h new file mode 100644 index 00000000000..7cd4fcde76c --- /dev/null +++ b/src/server/game/Maps/MapReference.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MAPREFERENCE_H +#define _MAPREFERENCE_H + +#include "Utilities/LinkedReference/Reference.h" +#include "Map.h" + +class MapReference : public Reference +{ + protected: + void targetObjectBuildLink() + { + // called from link() + getTarget()->m_mapRefManager.insertFirst(this); + getTarget()->m_mapRefManager.incSize(); + } + void targetObjectDestroyLink() + { + // called from unlink() + if (isValid()) getTarget()->m_mapRefManager.decSize(); + } + void sourceObjectDestroyLink() + { + // called from invalidate() + getTarget()->m_mapRefManager.decSize(); + } + public: + MapReference() : Reference() {} + ~MapReference() { unlink(); } + MapReference *next() { return (MapReference*)Reference::next(); } + MapReference const *next() const { return (MapReference const*)Reference::next(); } + MapReference *nockeck_prev() { return (MapReference*)Reference::nocheck_prev(); } + MapReference const *nocheck_prev() const { return (MapReference const*)Reference::nocheck_prev(); } +}; +#endif + diff --git a/src/server/game/Maps/MapUpdater.cpp b/src/server/game/Maps/MapUpdater.cpp new file mode 100644 index 00000000000..f9bb5e2bbbc --- /dev/null +++ b/src/server/game/Maps/MapUpdater.cpp @@ -0,0 +1,129 @@ +#include "MapUpdater.h" +#include "DelayExecutor.h" +#include "Map.h" +#include "Database/DatabaseEnv.h" + +#include +#include + +class WDBThreadStartReq1 : public ACE_Method_Request +{ + public: + + WDBThreadStartReq1() + { + } + + virtual int call() + { + WorldDatabase.ThreadStart(); + return 0; + } +}; + +class WDBThreadEndReq1 : public ACE_Method_Request +{ + public: + + WDBThreadEndReq1() + { + } + + virtual int call() + { + WorldDatabase.ThreadEnd(); + return 0; + } +}; + +class MapUpdateRequest : public ACE_Method_Request +{ + private: + + Map& m_map; + MapUpdater& m_updater; + ACE_UINT32 m_diff; + + public: + + MapUpdateRequest(Map& m, MapUpdater& u, ACE_UINT32 d) + : m_map(m), m_updater(u), m_diff(d) + { + } + + virtual int call() + { + m_map.Update (m_diff); + m_updater.update_finished (); + return 0; + } +}; + +MapUpdater::MapUpdater() + : m_mutex(), m_condition(m_mutex), m_executor(), pending_requests(0) +{ +} + +MapUpdater::~MapUpdater() +{ + deactivate(); +} + +int MapUpdater::activate(size_t num_threads) +{ + return m_executor.activate((int)num_threads, new WDBThreadStartReq1, new WDBThreadEndReq1); +} + +int MapUpdater::deactivate() +{ + wait(); + + return m_executor.deactivate(); +} + +int MapUpdater::wait() +{ + ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, m_mutex, -1); + + while (pending_requests > 0) + m_condition.wait(); + + return 0; +} + +int MapUpdater::schedule_update(Map& map, ACE_UINT32 diff) +{ + ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, m_mutex, -1); + + ++pending_requests; + + if (m_executor.execute(new MapUpdateRequest(map, *this, diff)) == -1) + { + ACE_DEBUG((LM_ERROR, ACE_TEXT("(%t) \n"), ACE_TEXT("Failed to schedule Map Update"))); + + --pending_requests; + return -1; + } + + return 0; +} + +bool MapUpdater::activated() +{ + return m_executor.activated(); +} + +void MapUpdater::update_finished() +{ + ACE_GUARD(ACE_Thread_Mutex, guard, m_mutex); + + if (pending_requests == 0) + { + ACE_ERROR((LM_ERROR, ACE_TEXT("(%t)\n"), ACE_TEXT("MapUpdater::update_finished BUG, report to devs"))); + return; + } + + --pending_requests; + + m_condition.broadcast(); +} diff --git a/src/server/game/Maps/MapUpdater.h b/src/server/game/Maps/MapUpdater.h new file mode 100644 index 00000000000..f301b15ca2f --- /dev/null +++ b/src/server/game/Maps/MapUpdater.h @@ -0,0 +1,40 @@ +#ifndef _MAP_UPDATER_H_INCLUDED +#define _MAP_UPDATER_H_INCLUDED + +#include +#include + +#include "DelayExecutor.h" + +class Map; + +class MapUpdater +{ + public: + + MapUpdater(); + virtual ~MapUpdater(); + + friend class MapUpdateRequest; + + int schedule_update(Map& map, ACE_UINT32 diff); + + int wait(); + + int activate(size_t num_threads); + + int deactivate(); + + bool activated(); + + private: + + DelayExecutor m_executor; + ACE_Condition_Thread_Mutex m_condition; + ACE_Thread_Mutex m_mutex; + size_t pending_requests; + + void update_finished(); +}; + +#endif //_MAP_UPDATER_H_INCLUDED diff --git a/src/server/game/Maps/ZoneScript.h b/src/server/game/Maps/ZoneScript.h new file mode 100644 index 00000000000..ab74c8aa5d4 --- /dev/null +++ b/src/server/game/Maps/ZoneScript.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ZONE_SCRIPT_H_ +#define ZONE_SCRIPT_H_ + +#include "Common.h" +#include "Creature.h" + +//struct CreatureData; +class Creature; +class GameObject; + +class ZoneScript +{ + public: + explicit ZoneScript() {} + + virtual uint32 GetCreatureEntry(uint32 /*guidlow*/, const CreatureData *data) { return data->id; } + virtual uint32 GetGameObjectEntry(uint32 /*guidlow*/, uint32 entry) { return entry; } + + virtual void OnCreatureCreate(Creature *, bool /*add*/) {} + virtual void OnGameObjectCreate(GameObject * /*go*/, bool /*add*/) {} + + //All-purpose data storage 64 bit + virtual uint64 GetData64(uint32 /*DataId*/) { return 0; } + virtual void SetData64(uint32 /*DataId*/, uint64 /*Value*/) {} + + //All-purpose data storage 32 bit + virtual uint32 GetData(uint32 /*DataId*/) { return 0; } + virtual void SetData(uint32 /*DataId*/, uint32 /*Value*/) {} + + virtual void ProcessEvent(GameObject * /*obj*/, uint32 /*eventId*/) {} +}; + +#endif \ No newline at end of file diff --git a/src/server/game/Miscellaneous/Formulas.h b/src/server/game/Miscellaneous/Formulas.h new file mode 100644 index 00000000000..e5961834a78 --- /dev/null +++ b/src/server/game/Miscellaneous/Formulas.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_FORMULAS_H +#define TRINITY_FORMULAS_H + +#include "World.h" + +namespace Trinity +{ + namespace Honor + { + inline uint32 hk_honor_at_level(uint8 level, uint32 count = 1) + { + return uint32(ceil(count * (33.333f * ((float)level) / 21.50537f))); + } + } + namespace XP + { + enum XPColorChar { RED, ORANGE, YELLOW, GREEN, GRAY }; + + inline uint8 GetGrayLevel(uint8 pl_level) + { + if (pl_level <= 5) + return 0; + else if (pl_level <= 39) + return pl_level - 5 - pl_level/10; + else if (pl_level <= 59) + return pl_level - 1 - pl_level/5; + else + return pl_level - 9; + } + + inline XPColorChar GetColorCode(uint8 pl_level, uint8 mob_level) + { + if (mob_level >= pl_level + 5) + return RED; + else if (mob_level >= pl_level + 3) + return ORANGE; + else if (mob_level >= pl_level - 2) + return YELLOW; + else if (mob_level > GetGrayLevel(pl_level)) + return GREEN; + else + return GRAY; + } + + inline uint8 GetZeroDifference(uint8 pl_level) + { + if (pl_level < 8) return 5; + if (pl_level < 10) return 6; + if (pl_level < 12) return 7; + if (pl_level < 16) return 8; + if (pl_level < 20) return 9; + if (pl_level < 30) return 11; + if (pl_level < 40) return 12; + if (pl_level < 45) return 13; + if (pl_level < 50) return 14; + if (pl_level < 55) return 15; + if (pl_level < 60) return 16; + return 17; + } + + inline uint32 BaseGain(uint8 pl_level, uint8 mob_level, ContentLevels content) + { + uint32 nBaseExp; + switch (content) + { + case CONTENT_1_60: nBaseExp = 45; break; + case CONTENT_61_70: nBaseExp = 235; break; + case CONTENT_71_80: nBaseExp = 580; break; + default: + sLog.outError("BaseGain: Unsupported content level %u",content); + nBaseExp = 45; break; + } + + if (mob_level >= pl_level) + { + uint8 nLevelDiff = mob_level - pl_level; + if (nLevelDiff > 4) + nLevelDiff = 4; + return ((pl_level*5 + nBaseExp) * (20 + nLevelDiff)/10 + 1)/2; + } + else + { + uint8 gray_level = GetGrayLevel(pl_level); + if (mob_level > gray_level) + { + uint8 ZD = GetZeroDifference(pl_level); + return (pl_level*5 + nBaseExp) * (ZD + mob_level - pl_level)/ZD; + } + return 0; + } + } + + inline uint32 Gain(Player *pl, Unit *u) + { + if (u->GetTypeId() == TYPEID_UNIT && ( + ((Creature*)u)->isTotem() || ((Creature*)u)->isPet() || + (((Creature*)u)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL))) + return 0; + + uint32 xp_gain = BaseGain(pl->getLevel(), u->getLevel(), GetContentLevelsForMapAndZone(u->GetMapId(),u->GetZoneId())); + if (xp_gain == 0) + return 0; + + //elites in instances have a 2.75x xp bonus instead of the regular 2x world bonus + if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isElite()) + { + if(u->GetMap() && u->GetMap()->IsDungeon()) + xp_gain *= 2.75; + else + xp_gain *= 2; + } + + return uint32(xp_gain*sWorld.getRate(RATE_XP_KILL)); + } + + inline float xp_in_group_rate(uint32 count, bool isRaid) + { + if (isRaid) + { + // FIX ME: must apply decrease modifiers dependent from raid size + return 1.0f; + } + else + { + switch (count) + { + case 0: + case 1: + case 2: + return 1.0f; + case 3: + return 1.166f; + case 4: + return 1.3f; + case 5: + default: + return 1.4f; + } + } + } + } +} +#endif + diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h new file mode 100644 index 00000000000..c0c8fc486f3 --- /dev/null +++ b/src/server/game/Miscellaneous/Language.h @@ -0,0 +1,1007 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __TRINITY_LANGUAGE_H +#define __TRINITY_LANGUAGE_H + +enum TrinityStrings +{ + // for chat commands + LANG_SELECT_CHAR_OR_CREATURE = 1, + LANG_SELECT_CREATURE = 2, + + // level 0 chat + LANG_SYSTEMMESSAGE = 3, + LANG_EVENTMESSAGE = 4, + LANG_NO_HELP_CMD = 5, + LANG_NO_CMD = 6, + LANG_NO_SUBCMD = 7, + LANG_SUBCMDS_LIST = 8, + LANG_AVIABLE_CMD = 9, + LANG_CMD_SYNTAX = 10, + LANG_ACCOUNT_LEVEL = 11, + LANG_CONNECTED_USERS = 12, + LANG_UPTIME = 13, + LANG_PLAYER_SAVED = 14, + LANG_PLAYERS_SAVED = 15, + LANG_GMS_ON_SRV = 16, + LANG_GMS_NOT_LOGGED = 17, + LANG_YOU_IN_FLIGHT = 18, + //LANG_YOU_IN_BATTLEGROUND = 19, not used + //LANG_TARGET_IN_FLIGHT = 20, not used + LANG_CHAR_IN_FLIGHT = 21, + LANG_CHAR_NON_MOUNTED = 22, + LANG_YOU_IN_COMBAT = 23, + LANG_YOU_USED_IT_RECENTLY = 24, + LANG_COMMAND_NOTCHANGEPASSWORD = 25, + LANG_COMMAND_PASSWORD = 26, + LANG_COMMAND_WRONGOLDPASSWORD = 27, + LANG_COMMAND_ACCLOCKLOCKED = 28, + LANG_COMMAND_ACCLOCKUNLOCKED = 29, + LANG_SPELL_RANK = 30, + LANG_KNOWN = 31, + LANG_LEARN = 32, + LANG_PASSIVE = 33, + LANG_TALENT = 34, + LANG_ACTIVE = 35, + LANG_COMPLETE = 36, + LANG_OFFLINE = 37, + LANG_ON = 38, + LANG_OFF = 39, + LANG_YOU_ARE = 40, + LANG_VISIBLE = 41, + LANG_INVISIBLE = 42, + LANG_DONE = 43, + LANG_YOU = 44, + LANG_UNKNOWN = 45, + LANG_ERROR = 46, + LANG_NON_EXIST_CHARACTER = 47, + LANG_FRIEND_IGNORE_UNKNOWN = 48, + LANG_LEVEL_MINREQUIRED = 49, + LANG_LEVEL_MINREQUIRED_AND_ITEM = 50, + LANG_NPC_TAINER_HELLO = 51, + LANG_COMMAND_INVALID_ITEM_COUNT = 52, + LANG_COMMAND_MAIL_ITEMS_LIMIT = 53, + LANG_NEW_PASSWORDS_NOT_MATCH = 54, + LANG_PASSWORD_TOO_LONG = 55, + LANG_MOTD_CURRENT = 56, + LANG_USING_WORLD_DB = 57, + LANG_USING_SCRIPT_LIB = 58, + LANG_USING_EVENT_AI = 59, + LANG_CONNECTED_PLAYERS = 60, + LANG_ACCOUNT_ADDON = 61, + // Room for more level 0 62-99 not used + + // level 1 chat + LANG_GLOBAL_NOTIFY = 100, + LANG_MAP_POSITION = 101, + LANG_IS_TELEPORTED = 102, + LANG_CANNOT_SUMMON_TO_INST = 103, + LANG_CANNOT_GO_TO_INST_PARTY = 104, + LANG_CANNOT_GO_TO_INST_GM = 105, + LANG_CANNOT_GO_INST_INST = 106, + LANG_CANNOT_SUMMON_INST_INST = 107, + LANG_SUMMONING = 108, + LANG_SUMMONED_BY = 109, + LANG_TELEPORTING_TO = 110, + LANG_TELEPORTED_TO_BY = 111, + LANG_NO_PLAYER = 112, + LANG_APPEARING_AT = 113, + LANG_APPEARING_TO = 114, + LANG_BAD_VALUE = 115, + LANG_NO_CHAR_SELECTED = 116, + LANG_NOT_IN_GROUP = 117, + + LANG_YOU_CHANGE_HP = 118, + LANG_YOURS_HP_CHANGED = 119, + LANG_YOU_CHANGE_MANA = 120, + LANG_YOURS_MANA_CHANGED = 121, + LANG_YOU_CHANGE_ENERGY = 122, + LANG_YOURS_ENERGY_CHANGED = 123, + + LANG_CURRENT_ENERGY = 124, //log + LANG_YOU_CHANGE_RAGE = 125, + LANG_YOURS_RAGE_CHANGED = 126, + LANG_YOU_CHANGE_LVL = 127, + LANG_CURRENT_FACTION = 128, + LANG_WRONG_FACTION = 129, + LANG_YOU_CHANGE_FACTION = 130, + LANG_YOU_CHANGE_SPELLFLATID = 131, + LANG_YOURS_SPELLFLATID_CHANGED = 132, + LANG_YOU_GIVE_TAXIS = 133, + LANG_YOU_REMOVE_TAXIS = 134, + LANG_YOURS_TAXIS_ADDED = 135, + LANG_YOURS_TAXIS_REMOVED = 136, + + LANG_YOU_CHANGE_ASPEED = 137, + LANG_YOURS_ASPEED_CHANGED = 138, + LANG_YOU_CHANGE_SPEED = 139, + LANG_YOURS_SPEED_CHANGED = 140, + LANG_YOU_CHANGE_SWIM_SPEED = 141, + LANG_YOURS_SWIM_SPEED_CHANGED = 142, + LANG_YOU_CHANGE_BACK_SPEED = 143, + LANG_YOURS_BACK_SPEED_CHANGED = 144, + LANG_YOU_CHANGE_FLY_SPEED = 145, + LANG_YOURS_FLY_SPEED_CHANGED = 146, + + LANG_YOU_CHANGE_SIZE = 147, + LANG_YOURS_SIZE_CHANGED = 148, + LANG_NO_MOUNT = 149, + LANG_YOU_GIVE_MOUNT = 150, + LANG_MOUNT_GIVED = 151, + + LANG_CURRENT_MONEY = 152, + LANG_YOU_TAKE_ALL_MONEY = 153, + LANG_YOURS_ALL_MONEY_GONE = 154, + LANG_YOU_TAKE_MONEY = 155, + LANG_YOURS_MONEY_TAKEN = 156, + LANG_YOU_GIVE_MONEY = 157, + LANG_YOURS_MONEY_GIVEN = 158, + LANG_YOU_HEAR_SOUND = 159, + + LANG_NEW_MONEY = 160, // Log + + LANG_REMOVE_BIT = 161, + LANG_SET_BIT = 162, + LANG_COMMAND_TELE_TABLEEMPTY = 163, + LANG_COMMAND_TELE_NOTFOUND = 164, + LANG_COMMAND_TELE_PARAMETER = 165, + LANG_COMMAND_TELE_NOLOCATION = 166, + // 167 // not used + LANG_COMMAND_TELE_LOCATION = 168, + + LANG_MAIL_SENT = 169, + LANG_SOUND_NOT_EXIST = 170, + LANG_CANT_TELEPORT_SELF = 171, + LANG_CONSOLE_COMMAND = 172, + LANG_YOU_CHANGE_RUNIC_POWER = 173, + LANG_YOURS_RUNIC_POWER_CHANGED = 174, + LANG_LIQUID_STATUS = 175, + // Room for more level 1 176-199 not used + + // level 2 chat + LANG_NO_SELECTION = 200, + LANG_OBJECT_GUID = 201, + LANG_TOO_LONG_NAME = 202, + LANG_CHARS_ONLY = 203, + LANG_TOO_LONG_SUBNAME = 204, + LANG_NOT_IMPLEMENTED = 205, + + LANG_ITEM_ADDED_TO_LIST = 206, + LANG_ITEM_NOT_FOUND = 207, + LANG_ITEM_DELETED_FROM_LIST = 208, + LANG_ITEM_NOT_IN_LIST = 209, + LANG_ITEM_ALREADY_IN_LIST = 210, + + LANG_RESET_SPELLS_ONLINE = 211, + LANG_RESET_SPELLS_OFFLINE = 212, + LANG_RESET_TALENTS_ONLINE = 213, + LANG_RESET_TALENTS_OFFLINE = 214, + LANG_RESET_SPELLS = 215, + LANG_RESET_TALENTS = 216, + + LANG_RESETALL_UNKNOWN_CASE = 217, + LANG_RESETALL_SPELLS = 218, + LANG_RESETALL_TALENTS = 219, + + LANG_WAYPOINT_NOTFOUND = 220, + LANG_WAYPOINT_NOTFOUNDLAST = 221, + LANG_WAYPOINT_NOTFOUNDSEARCH = 222, + LANG_WAYPOINT_NOTFOUNDDBPROBLEM = 223, + LANG_WAYPOINT_CREATSELECTED = 224, + LANG_WAYPOINT_CREATNOTFOUND = 225, + LANG_WAYPOINT_VP_SELECT = 226, + LANG_WAYPOINT_VP_NOTFOUND = 227, + LANG_WAYPOINT_VP_NOTCREATED = 228, + LANG_WAYPOINT_VP_ALLREMOVED = 229, + LANG_WAYPOINT_NOTCREATED = 230, + LANG_WAYPOINT_NOGUID = 231, + LANG_WAYPOINT_NOWAYPOINTGIVEN = 232, + LANG_WAYPOINT_ARGUMENTREQ = 233, + LANG_WAYPOINT_ADDED = 234, + LANG_WAYPOINT_ADDED_NO = 235, + LANG_WAYPOINT_CHANGED = 236, + LANG_WAYPOINT_CHANGED_NO = 237, + LANG_WAYPOINT_EXPORTED = 238, + LANG_WAYPOINT_NOTHINGTOEXPORT = 239, + LANG_WAYPOINT_IMPORTED = 240, + LANG_WAYPOINT_REMOVED = 241, + LANG_WAYPOINT_NOTREMOVED = 242, + LANG_WAYPOINT_TOOFAR1 = 243, + LANG_WAYPOINT_TOOFAR2 = 244, + LANG_WAYPOINT_TOOFAR3 = 245, + LANG_WAYPOINT_INFO_TITLE = 246, + LANG_WAYPOINT_INFO_WAITTIME = 247, + LANG_WAYPOINT_INFO_MODEL = 248, + LANG_WAYPOINT_INFO_EMOTE = 249, + LANG_WAYPOINT_INFO_SPELL = 250, + LANG_WAYPOINT_INFO_TEXT = 251, + LANG_WAYPOINT_INFO_AISCRIPT = 252, + + LANG_RENAME_PLAYER = 253, + LANG_RENAME_PLAYER_GUID = 254, + + LANG_WAYPOINT_WPCREATNOTFOUND = 255, + LANG_WAYPOINT_NPCNOTFOUND = 256, + + LANG_MOVE_TYPE_SET = 257, + LANG_MOVE_TYPE_SET_NODEL = 258, + LANG_USE_BOL = 259, + LANG_VALUE_SAVED = 260, + LANG_VALUE_SAVED_REJOIN = 261, + + LANG_COMMAND_GOAREATRNOTFOUND = 262, + LANG_INVALID_TARGET_COORD = 263, + LANG_INVALID_ZONE_COORD = 264, + LANG_INVALID_ZONE_MAP = 265, + LANG_COMMAND_TARGETOBJNOTFOUND = 266, + LANG_COMMAND_GOOBJNOTFOUND = 267, + LANG_COMMAND_GOCREATNOTFOUND = 268, + LANG_COMMAND_GOCREATMULTIPLE = 269, + LANG_COMMAND_DELCREATMESSAGE = 270, + LANG_COMMAND_CREATUREMOVED = 271, + LANG_COMMAND_CREATUREATSAMEMAP = 272, + LANG_COMMAND_OBJNOTFOUND = 273, + LANG_COMMAND_DELOBJREFERCREATURE = 274, + LANG_COMMAND_DELOBJMESSAGE = 275, + LANG_COMMAND_TURNOBJMESSAGE = 276, + LANG_COMMAND_MOVEOBJMESSAGE = 277, + LANG_COMMAND_VENDORSELECTION = 278, + LANG_COMMAND_NEEDITEMSEND = 279, + LANG_COMMAND_ADDVENDORITEMITEMS = 280, + LANG_COMMAND_KICKSELF = 281, + LANG_COMMAND_KICKMESSAGE = 282, + // 283, not used + LANG_COMMAND_WHISPERACCEPTING = 284, + LANG_COMMAND_WHISPERON = 285, + LANG_COMMAND_WHISPEROFF = 286, + LANG_COMMAND_CREATGUIDNOTFOUND = 287, + // TICKET STRINGS NEED REWRITE // 288-296 FREE + + // END + LANG_COMMAND_SPAWNDIST = 297, + LANG_COMMAND_SPAWNTIME = 298, + LANG_COMMAND_MODIFY_HONOR = 299, + + LANG_YOUR_CHAT_DISABLED = 300, + LANG_YOU_DISABLE_CHAT = 301, + LANG_CHAT_ALREADY_ENABLED = 302, + LANG_YOUR_CHAT_ENABLED = 303, + LANG_YOU_ENABLE_CHAT = 304, + + LANG_COMMAND_MODIFY_REP = 305, + LANG_COMMAND_MODIFY_ARENA = 306, + LANG_COMMAND_FACTION_NOTFOUND = 307, + LANG_COMMAND_FACTION_UNKNOWN = 308, + LANG_COMMAND_FACTION_INVPARAM = 309, + LANG_COMMAND_FACTION_DELTA = 310, + LANG_FACTION_LIST = 311, + LANG_FACTION_VISIBLE = 312, + LANG_FACTION_ATWAR = 313, + LANG_FACTION_PEACE_FORCED = 314, + LANG_FACTION_HIDDEN = 315, + LANG_FACTION_INVISIBLE_FORCED = 316, + LANG_FACTION_INACTIVE = 317, + LANG_REP_HATED = 318, + LANG_REP_HOSTILE = 319, + LANG_REP_UNFRIENDLY = 320, + LANG_REP_NEUTRAL = 321, + LANG_REP_FRIENDLY = 322, + LANG_REP_HONORED = 323, + LANG_REP_REVERED = 324, + LANG_REP_EXALTED = 325, + LANG_COMMAND_FACTION_NOREP_ERROR = 326, + LANG_FACTION_NOREPUTATION = 327, + LANG_LOOKUP_PLAYER_ACCOUNT = 328, + LANG_LOOKUP_PLAYER_CHARACTER = 329, + LANG_NO_PLAYERS_FOUND = 330, + LANG_EXTENDED_COST_NOT_EXIST = 331, + LANG_GM_ON = 332, + LANG_GM_OFF = 333, + LANG_GM_CHAT_ON = 334, + LANG_GM_CHAT_OFF = 335, + LANG_YOU_REPAIR_ITEMS = 336, + LANG_YOUR_ITEMS_REPAIRED = 337, + LANG_YOU_SET_WATERWALK = 338, + LANG_YOUR_WATERWALK_SET = 339, + LANG_CREATURE_FOLLOW_YOU_NOW = 340, + LANG_CREATURE_NOT_FOLLOW_YOU = 341, + LANG_CREATURE_NOT_FOLLOW_YOU_NOW = 342, + LANG_CREATURE_NON_TAMEABLE = 343, + LANG_YOU_ALREADY_HAVE_PET = 344, + LANG_CUSTOMIZE_PLAYER = 345, + LANG_CUSTOMIZE_PLAYER_GUID = 346, + LANG_COMMAND_GOTAXINODENOTFOUND = 347, + LANG_GAMEOBJECT_HAVE_INVALID_DATA = 348, + LANG_TITLE_LIST_CHAT = 349, + LANG_TITLE_LIST_CONSOLE = 350, + LANG_COMMAND_NOTITLEFOUND = 351, + LANG_INVALID_TITLE_ID = 352, + LANG_TITLE_ADD_RES = 353, + LANG_TITLE_REMOVE_RES = 354, + LANG_TITLE_CURRENT_RES = 355, + LANG_CURRENT_TITLE_RESET = 356, + // Room for more level 2 357-399 not used + + // level 3 chat + LANG_SCRIPTS_RELOADED = 400, + LANG_YOU_CHANGE_SECURITY = 401, + LANG_YOURS_SECURITY_CHANGED = 402, + LANG_YOURS_SECURITY_IS_LOW = 403, + LANG_CREATURE_MOVE_DISABLED = 404, + LANG_CREATURE_MOVE_ENABLED = 405, + LANG_NO_WEATHER = 406, + LANG_WEATHER_DISABLED = 407, + + LANG_BAN_YOUBANNED = 408, + LANG_BAN_YOUPERMBANNED = 409, + LANG_BAN_NOTFOUND = 410, + + LANG_UNBAN_UNBANNED = 411, + LANG_UNBAN_ERROR = 412, + + LANG_ACCOUNT_NOT_EXIST = 413, + + LANG_BANINFO_NOCHARACTER = 414, + LANG_BANINFO_NOIP = 415, + LANG_BANINFO_NOACCOUNTBAN = 416, + LANG_BANINFO_BANHISTORY = 417, + LANG_BANINFO_HISTORYENTRY = 418, + LANG_BANINFO_INFINITE = 419, + LANG_BANINFO_NEVER = 420, + LANG_BANINFO_YES = 421, + LANG_BANINFO_NO = 422, + LANG_BANINFO_IPENTRY = 423, + + LANG_BANLIST_NOIP = 424, + LANG_BANLIST_NOACCOUNT = 425, + LANG_BANLIST_NOCHARACTER = 426, + LANG_BANLIST_MATCHINGIP = 427, + LANG_BANLIST_MATCHINGACCOUNT = 428, + + LANG_COMMAND_LEARN_MANY_SPELLS = 429, + LANG_COMMAND_LEARN_CLASS_SPELLS = 430, + LANG_COMMAND_LEARN_CLASS_TALENTS = 431, + LANG_COMMAND_LEARN_ALL_LANG = 432, + LANG_COMMAND_LEARN_ALL_CRAFT = 433, + LANG_COMMAND_COULDNOTFIND = 434, + LANG_COMMAND_ITEMIDINVALID = 435, + LANG_COMMAND_NOITEMFOUND = 436, + LANG_COMMAND_LISTOBJINVALIDID = 437, + LANG_COMMAND_LISTITEMMESSAGE = 438, + LANG_COMMAND_LISTOBJMESSAGE = 439, + LANG_COMMAND_INVALIDCREATUREID = 440, + LANG_COMMAND_LISTCREATUREMESSAGE = 441, + LANG_COMMAND_NOAREAFOUND = 442, + LANG_COMMAND_NOITEMSETFOUND = 443, + LANG_COMMAND_NOSKILLFOUND = 444, + LANG_COMMAND_NOSPELLFOUND = 445, + LANG_COMMAND_NOQUESTFOUND = 446, + LANG_COMMAND_NOCREATUREFOUND = 447, + LANG_COMMAND_NOGAMEOBJECTFOUND = 448, + LANG_COMMAND_GRAVEYARDNOEXIST = 449, + LANG_COMMAND_GRAVEYARDALRLINKED = 450, + LANG_COMMAND_GRAVEYARDLINKED = 451, + LANG_COMMAND_GRAVEYARDWRONGZONE = 452, + // = 453, + LANG_COMMAND_GRAVEYARDERROR = 454, + LANG_COMMAND_GRAVEYARD_NOTEAM = 455, + LANG_COMMAND_GRAVEYARD_ANY = 456, + LANG_COMMAND_GRAVEYARD_ALLIANCE = 457, + LANG_COMMAND_GRAVEYARD_HORDE = 458, + LANG_COMMAND_GRAVEYARDNEAREST = 459, + LANG_COMMAND_ZONENOGRAVEYARDS = 460, + LANG_COMMAND_ZONENOGRAFACTION = 461, + LANG_COMMAND_TP_ALREADYEXIST = 462, + LANG_COMMAND_TP_ADDED = 463, + LANG_COMMAND_TP_ADDEDERR = 464, + LANG_COMMAND_TP_DELETED = 465, + LANG_COMMAND_NOTAXINODEFOUND = 466, + LANG_COMMAND_TARGET_LISTAURAS = 467, + LANG_COMMAND_TARGET_AURADETAIL = 468, + LANG_COMMAND_TARGET_LISTAURATYPE = 469, + LANG_COMMAND_TARGET_AURASIMPLE = 470, + + LANG_COMMAND_QUEST_NOTFOUND = 471, + LANG_COMMAND_QUEST_STARTFROMITEM = 472, + LANG_COMMAND_QUEST_REMOVED = 473, + LANG_COMMAND_QUEST_REWARDED = 474, + LANG_COMMAND_QUEST_COMPLETE = 475, + LANG_COMMAND_QUEST_ACTIVE = 476, + + LANG_COMMAND_FLYMODE_STATUS = 477, + + LANG_COMMAND_OPCODESENT = 478, + + LANG_COMMAND_IMPORT_SUCCESS = 479, + LANG_COMMAND_IMPORT_FAILED = 480, + LANG_COMMAND_EXPORT_SUCCESS = 481, + LANG_COMMAND_EXPORT_FAILED = 482, + + LANG_COMMAND_SPELL_BROKEN = 483, + + LANG_SET_SKILL = 484, + LANG_SET_SKILL_ERROR = 485, + + LANG_INVALID_SKILL_ID = 486, + LANG_LEARNING_GM_SKILLS = 487, + LANG_YOU_KNOWN_SPELL = 488, + LANG_TARGET_KNOWN_SPELL = 489, + LANG_UNKNOWN_SPELL = 490, + LANG_FORGET_SPELL = 491, + LANG_REMOVEALL_COOLDOWN = 492, + LANG_REMOVE_COOLDOWN = 493, + + LANG_ADDITEM = 494, //log + LANG_ADDITEMSET = 495, //log + LANG_REMOVEITEM = 496, + LANG_ITEM_CANNOT_CREATE = 497, + LANG_INSERT_GUILD_NAME = 498, + LANG_PLAYER_NOT_FOUND = 499, + LANG_PLAYER_IN_GUILD = 500, + LANG_GUILD_NOT_CREATED = 501, + LANG_NO_ITEMS_FROM_ITEMSET_FOUND = 502, + + LANG_DISTANCE = 503, + + LANG_ITEM_SLOT = 504, + LANG_ITEM_SLOT_NOT_EXIST = 505, + LANG_ITEM_ADDED_TO_SLOT = 506, + LANG_ITEM_SAVE_FAILED = 507, + LANG_ITEMLIST_SLOT = 508, + LANG_ITEMLIST_MAIL = 509, + LANG_ITEMLIST_AUCTION = 510, + + LANG_WRONG_LINK_TYPE = 511, + LANG_ITEM_LIST_CHAT = 512, + LANG_QUEST_LIST_CHAT = 513, + LANG_CREATURE_ENTRY_LIST_CHAT = 514, + LANG_CREATURE_LIST_CHAT = 515, + LANG_GO_ENTRY_LIST_CHAT = 516, + LANG_GO_LIST_CHAT = 517, + LANG_ITEMSET_LIST_CHAT = 518, + LANG_TELE_LIST = 519, + LANG_SPELL_LIST = 520, + LANG_SKILL_LIST_CHAT = 521, + + LANG_GAMEOBJECT_NOT_EXIST = 522, + + LANG_GAMEOBJECT_CURRENT = 523, //log + LANG_GAMEOBJECT_DETAIL = 524, + LANG_GAMEOBJECT_ADD = 525, + + LANG_MOVEGENS_LIST = 526, + LANG_MOVEGENS_IDLE = 527, + LANG_MOVEGENS_RANDOM = 528, + LANG_MOVEGENS_WAYPOINT = 529, + LANG_MOVEGENS_ANIMAL_RANDOM = 530, + LANG_MOVEGENS_CONFUSED = 531, + LANG_MOVEGENS_TARGETED_PLAYER = 532, + LANG_MOVEGENS_TARGETED_CREATURE = 533, + LANG_MOVEGENS_TARGETED_NULL = 534, + LANG_MOVEGENS_HOME_CREATURE = 535, + LANG_MOVEGENS_HOME_PLAYER = 536, + LANG_MOVEGENS_FLIGHT = 537, + LANG_MOVEGENS_UNKNOWN = 538, + + LANG_NPCINFO_CHAR = 539, + LANG_NPCINFO_LEVEL = 540, + LANG_NPCINFO_HEALTH = 541, + LANG_NPCINFO_FLAGS = 542, + LANG_NPCINFO_LOOT = 543, + LANG_NPCINFO_POSITION = 544, + LANG_NPCINFO_VENDOR = 545, + LANG_NPCINFO_TRAINER = 546, + LANG_NPCINFO_DUNGEON_ID = 547, + + LANG_PINFO_ACCOUNT = 548, + LANG_PINFO_LEVEL = 549, + LANG_PINFO_NO_REP = 550, + + LANG_YOU_SET_EXPLORE_ALL = 551, + LANG_YOU_SET_EXPLORE_NOTHING = 552, + LANG_YOURS_EXPLORE_SET_ALL = 553, + LANG_YOURS_EXPLORE_SET_NOTHING = 554, + + LANG_HOVER_ENABLED = 555, + LANG_HOVER_DISABLED = 556, + LANG_YOURS_LEVEL_UP = 557, + LANG_YOURS_LEVEL_DOWN = 558, + LANG_YOURS_LEVEL_PROGRESS_RESET = 559, + LANG_EXPLORE_AREA = 560, + LANG_UNEXPLORE_AREA = 561, + + LANG_UPDATE = 562, + LANG_UPDATE_CHANGE = 563, + LANG_TOO_BIG_INDEX = 564, + LANG_SET_UINT = 565, //log + LANG_SET_UINT_FIELD = 566, + LANG_SET_FLOAT = 567, //log + LANG_SET_FLOAT_FIELD = 568, + LANG_GET_UINT = 569, //log + LANG_GET_UINT_FIELD = 570, + LANG_GET_FLOAT = 571, //log + LANG_GET_FLOAT_FIELD = 572, + LANG_SET_32BIT = 573, //log + LANG_SET_32BIT_FIELD = 574, + LANG_CHANGE_32BIT = 575, //log + LANG_CHANGE_32BIT_FIELD = 576, + + LANG_INVISIBLE_INVISIBLE = 577, + LANG_INVISIBLE_VISIBLE = 578, + LANG_SELECTED_TARGET_NOT_HAVE_VICTIM = 579, + + LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST = 580, + LANG_COMMAND_NEAROBJMESSAGE = 581, + LANG_COMMAND_RAWPAWNTIMES = 582, + + LANG_EVENT_ENTRY_LIST_CHAT = 583, + LANG_NOEVENTFOUND = 584, + LANG_EVENT_NOT_EXIST = 585, + LANG_EVENT_INFO = 586, + LANG_EVENT_ALREADY_ACTIVE = 587, + LANG_EVENT_NOT_ACTIVE = 588, + + LANG_MOVEGENS_POINT = 589, + LANG_MOVEGENS_FEAR = 590, + LANG_MOVEGENS_DISTRACT = 591, + + LANG_COMMAND_LEARN_ALL_RECIPES = 592, + LANG_BANLIST_ACCOUNTS = 593, + LANG_BANLIST_ACCOUNTS_HEADER = 594, + LANG_BANLIST_IPS = 595, + LANG_BANLIST_IPS_HEADER = 596, + LANG_GMLIST = 597, + LANG_GMLIST_HEADER = 598, + LANG_GMLIST_EMPTY = 599, + // End Level 3 list, continued at 1100 + + // Battleground + LANG_BG_A_WINS = 600, + LANG_BG_H_WINS = 601, + + LANG_BG_WS_START_TWO_MINUTES = 753, + LANG_BG_WS_START_ONE_MINUTE = 602, + LANG_BG_WS_START_HALF_MINUTE = 603, + LANG_BG_WS_HAS_BEGUN = 604, + + LANG_BG_WS_CAPTURED_HF = 605, + LANG_BG_WS_CAPTURED_AF = 606, + LANG_BG_WS_DROPPED_HF = 607, + LANG_BG_WS_DROPPED_AF = 608, + LANG_BG_WS_RETURNED_AF = 609, + LANG_BG_WS_RETURNED_HF = 610, + LANG_BG_WS_PICKEDUP_HF = 611, + LANG_BG_WS_PICKEDUP_AF = 612, + LANG_BG_WS_F_PLACED = 613, + LANG_BG_WS_ALLIANCE_FLAG_RESPAWNED = 614, + LANG_BG_WS_HORDE_FLAG_RESPAWNED = 615, + + LANG_BG_EY_START_TWO_MINUTES = 755, + LANG_BG_EY_START_ONE_MINUTE = 636, + LANG_BG_EY_START_HALF_MINUTE = 637, + LANG_BG_EY_HAS_BEGUN = 638, + + LANG_BG_AB_ALLY = 650, + LANG_BG_AB_HORDE = 651, + LANG_BG_AB_NODE_STABLES = 652, + LANG_BG_AB_NODE_BLACKSMITH = 653, + LANG_BG_AB_NODE_FARM = 654, + LANG_BG_AB_NODE_LUMBER_MILL = 655, + LANG_BG_AB_NODE_GOLD_MINE = 656, + LANG_BG_AB_NODE_TAKEN = 657, + LANG_BG_AB_NODE_DEFENDED = 658, + LANG_BG_AB_NODE_ASSAULTED = 659, + LANG_BG_AB_NODE_CLAIMED = 660, + + LANG_BG_AB_START_TWO_MINUTES = 754, + LANG_BG_AB_START_ONE_MINUTE = 661, + LANG_BG_AB_START_HALF_MINUTE = 662, + LANG_BG_AB_HAS_BEGUN = 663, + LANG_BG_AB_A_NEAR_VICTORY = 664, + LANG_BG_AB_H_NEAR_VICTORY = 665, + LANG_BG_MARK_BY_MAIL = 666, + + LANG_BG_EY_HAS_TAKEN_A_M_TOWER = 667, + LANG_BG_EY_HAS_TAKEN_H_M_TOWER = 668, + LANG_BG_EY_HAS_TAKEN_A_D_RUINS = 669, + LANG_BG_EY_HAS_TAKEN_H_D_RUINS = 670, + LANG_BG_EY_HAS_TAKEN_A_B_TOWER = 671, + LANG_BG_EY_HAS_TAKEN_H_B_TOWER = 672, + LANG_BG_EY_HAS_TAKEN_A_F_RUINS = 673, + LANG_BG_EY_HAS_TAKEN_H_F_RUINS = 674, + LANG_BG_EY_HAS_LOST_A_M_TOWER = 675, + LANG_BG_EY_HAS_LOST_H_M_TOWER = 676, + LANG_BG_EY_HAS_LOST_A_D_RUINS = 677, + LANG_BG_EY_HAS_LOST_H_D_RUINS = 678, + LANG_BG_EY_HAS_LOST_A_B_TOWER = 679, + LANG_BG_EY_HAS_LOST_H_B_TOWER = 680, + LANG_BG_EY_HAS_LOST_A_F_RUINS = 681, + LANG_BG_EY_HAS_LOST_H_F_RUINS = 682, + LANG_BG_EY_HAS_TAKEN_FLAG = 683, + LANG_BG_EY_CAPTURED_FLAG_A = 684, + LANG_BG_EY_CAPTURED_FLAG_H = 685, + LANG_BG_EY_DROPPED_FLAG = 686, + LANG_BG_EY_RESETED_FLAG = 687, + + LANG_ARENA_ONE_TOOLOW = 700, + LANG_ARENA_ONE_MINUTE = 701, + LANG_ARENA_THIRTY_SECONDS = 702, + LANG_ARENA_FIFTEEN_SECONDS = 703, + LANG_ARENA_HAS_BEGUN = 704, + + LANG_WAIT_BEFORE_SPEAKING = 705, + LANG_NOT_EQUIPPED_ITEM = 706, + LANG_PLAYER_DND = 707, + LANG_PLAYER_AFK = 708, + LANG_PLAYER_DND_DEFAULT = 709, + LANG_PLAYER_AFK_DEFAULT = 710, + + LANG_BG_QUEUE_ANNOUNCE_SELF = 711, + LANG_BG_QUEUE_ANNOUNCE_WORLD = 712, + LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713, +// = 714, not used + LANG_YOUR_BG_LEVEL_REQ_ERROR = 715, +// = 716, not used + LANG_BG_STARTED_ANNOUNCE_WORLD = 717, + LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN= 718, + LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT= 719, + + LANG_BG_GROUP_TOO_LARGE = 720, // "Your group is too large for this battleground. Please regroup to join." + LANG_ARENA_GROUP_TOO_LARGE = 721, // "Your group is too large for this arena. Please regroup to join." + LANG_ARENA_YOUR_TEAM_ONLY = 722, // "Your group has members not in your arena team. Please regroup to join." + LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match." + LANG_ARENA_GOLD_WINS = 724, // "The Gold Team wins!" + LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!" +// = 726, not used + LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining." + LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group." + LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group." + LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 730, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group." + LANG_BG_GROUP_MEMBER_DESERTER = 731, // "Someone in your party is Deserter. You can't join as group." + LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 732, // "Someone in your party is already in three battleground queues. You cannot join as group." + + LANG_CANNOT_TELE_TO_BG = 733, // "You cannot teleport to a battleground or arena map." + LANG_CANNOT_SUMMON_TO_BG = 734, // "You cannot summon players to a battleground or arena map." + LANG_CANNOT_GO_TO_BG_GM = 735, // "You must be in GM mode to teleport to a player in a battleground." + LANG_CANNOT_GO_TO_BG_FROM_BG = 736, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first." + LANG_DEBUG_ARENA_ON = 737, + LANG_DEBUG_ARENA_OFF = 738, + LANG_DEBUG_BG_ON = 739, + LANG_DEBUG_BG_OFF = 740, + LANG_DIST_ARENA_POINTS_START = 741, + LANG_DIST_ARENA_POINTS_ONLINE_START = 742, + LANG_DIST_ARENA_POINTS_ONLINE_END = 743, + LANG_DIST_ARENA_POINTS_TEAM_START = 744, + LANG_DIST_ARENA_POINTS_TEAM_END = 745, + LANG_DIST_ARENA_POINTS_END = 746, + LANG_BG_DISABLED = 747, + LANG_ARENA_DISABLED = 748, +// = 749, not used + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." +// = 752, not used +// LANG_BG_WS_START_TWO_MINUTES = 753, - defined above +// LANG_BG_AB_START_TWO_MINUTES = 754, - defined above +// LANG_BG_EY_START_TWO_MINUTES = 755, - defined above + + // Room for BG/ARENA = 773-784, 788-799 not used + LANG_ARENA_TESTING = 785, + LANG_AUTO_ANN = 786, + LANG_ANNOUNCE_COLOR = 787, + + // in game strings + LANG_PET_INVALID_NAME = 800, + LANG_NOT_ENOUGH_GOLD = 801, + LANG_NOT_FREE_TRADE_SLOTS = 802, + LANG_NOT_PARTNER_FREE_TRADE_SLOTS = 803, + LANG_YOU_NOT_HAVE_PERMISSION = 804, + LANG_UNKNOWN_LANGUAGE = 805, + LANG_NOT_LEARNED_LANGUAGE = 806, + LANG_NEED_CHARACTER_NAME = 807, + LANG_PLAYER_NOT_EXIST_OR_OFFLINE = 808, + LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND = 809, + LANG_ACHIEVEMENT_EARNED = 810, + LANG_GUILD_MASTER = 811, + LANG_GUILD_OFFICER = 812, + LANG_GUILD_VETERAN = 813, + LANG_GUILD_MEMBER = 814, + LANG_GUILD_INITIATE = 815, + LANG_ZONE_NOFLYZONE = 816, + + LANG_COMMAND_CREATURETEMPLATE_NOTFOUND = 817, + LANG_COMMAND_CREATURESTORAGE_NOTFOUND = 818, + // Room for in-game strings 819-999 not used + + // Level 4 (CLI only commands) + LANG_COMMAND_EXIT = 1000, + LANG_ACCOUNT_DELETED = 1001, + LANG_ACCOUNT_NOT_DELETED_SQL_ERROR = 1002, + LANG_ACCOUNT_NOT_DELETED = 1003, + LANG_ACCOUNT_CREATED = 1004, + LANG_ACCOUNT_TOO_LONG = 1005, + LANG_ACCOUNT_ALREADY_EXIST = 1006, + LANG_ACCOUNT_NOT_CREATED_SQL_ERROR = 1007, + LANG_ACCOUNT_NOT_CREATED = 1008, + LANG_CHARACTER_DELETED = 1009, + LANG_ACCOUNT_LIST_HEADER = 1010, + LANG_ACCOUNT_LIST_ERROR = 1011, + LANG_ACCOUNT_LIST_BAR = 1012, + LANG_ACCOUNT_LIST_LINE = 1013, + LANG_ACCOUNT_LIST_EMPTY = 1014, + LANG_ACCOUNT_LIST_BAR_HEADER = 1015, + // Room for more level 4 1016-1099 not used + + // Level 3 (continue) + LANG_ACCOUNT_SETADDON = 1100, + LANG_MOTD_NEW = 1101, + LANG_SENDMESSAGE = 1102, + LANG_EVENT_ENTRY_LIST_CONSOLE = 1103, + LANG_CREATURE_ENTRY_LIST_CONSOLE = 1104, + LANG_ITEM_LIST_CONSOLE = 1105, + LANG_ITEMSET_LIST_CONSOLE = 1106, + LANG_GO_ENTRY_LIST_CONSOLE = 1107, + LANG_QUEST_LIST_CONSOLE = 1108, + LANG_SKILL_LIST_CONSOLE = 1109, + LANG_CREATURE_LIST_CONSOLE = 1110, + LANG_GO_LIST_CONSOLE = 1111, + LANG_FILE_OPEN_FAIL = 1112, + LANG_ACCOUNT_CHARACTER_LIST_FULL = 1113, + LANG_DUMP_BROKEN = 1114, + LANG_INVALID_CHARACTER_NAME = 1115, + LANG_INVALID_CHARACTER_GUID = 1116, + LANG_CHARACTER_GUID_IN_USE = 1117, + LANG_ITEMLIST_GUILD = 1118, + LANG_MUST_MALE_OR_FEMALE = 1119, + LANG_YOU_CHANGE_GENDER = 1120, + LANG_YOUR_GENDER_CHANGED = 1121, + LANG_SKILL_VALUES = 1122, + LANG_NO_PET_FOUND = 1123, + LANG_WRONG_PET_TYPE = 1124, + LANG_COMMAND_LEARN_PET_TALENTS = 1125, + LANG_RESET_PET_TALENTS = 1126, + LANG_RESET_PET_TALENTS_ONLINE = 1127, + LANG_TAXINODE_ENTRY_LIST_CHAT = 1128, + LANG_TAXINODE_ENTRY_LIST_CONSOLE = 1129, + // Room for more level 3 1130-1199 not used + + // Debug commands + LANG_CINEMATIC_NOT_EXIST = 1200, + LANG_MOVIE_NOT_EXIST = 1201, + // Room for more debug 1202-1299 not used + + // FREE IDS 1300-9999 + + // AV + LANG_BG_AV_ALLY = 1300, + LANG_BG_AV_HORDE = 1301, + LANG_BG_AV_TOWER_TAKEN = 1302, + LANG_BG_AV_TOWER_ASSAULTED = 1303, + LANG_BG_AV_TOWER_DEFENDED = 1304, + LANG_BG_AV_GRAVE_TAKEN = 1305, + LANG_BG_AV_GRAVE_DEFENDED = 1306, + LANG_BG_AV_GRAVE_ASSAULTED = 1307, + + LANG_BG_AV_MINE_TAKEN = 1308, + LANG_BG_AV_MINE_NORTH = 1309, + LANG_BG_AV_MINE_SOUTH = 1310, + + LANG_BG_AV_NODE_GRAVE_STORM_AID = 1311, + LANG_BG_AV_NODE_TOWER_DUN_S = 1312, + LANG_BG_AV_NODE_TOWER_DUN_N = 1313, + LANG_BG_AV_NODE_GRAVE_STORMPIKE = 1314, + LANG_BG_AV_NODE_TOWER_ICEWING = 1315, + LANG_BG_AV_NODE_GRAVE_STONE = 1316, + LANG_BG_AV_NODE_TOWER_STONE = 1317, + LANG_BG_AV_NODE_GRAVE_SNOW = 1318, + LANG_BG_AV_NODE_TOWER_ICE = 1319, + LANG_BG_AV_NODE_GRAVE_ICE = 1320, + LANG_BG_AV_NODE_TOWER_POINT = 1321, + LANG_BG_AV_NODE_GRAVE_FROST = 1322, + LANG_BG_AV_NODE_TOWER_FROST_E = 1323, + LANG_BG_AV_NODE_TOWER_FROST_W = 1324, + LANG_BG_AV_NODE_GRAVE_FROST_HUT = 1325, + + LANG_BG_AV_START_ONE_MINUTE = 1326, + LANG_BG_AV_START_HALF_MINUTE = 1327, + LANG_BG_AV_HAS_BEGUN = 1328, + LANG_BG_AV_A_NEAR_LOSE = 1329, + LANG_BG_AV_H_NEAR_LOSE = 1330, + LANG_BG_AV_H_CAPTAIN_DEAD = 1331, + LANG_BG_AV_A_CAPTAIN_DEAD = 1332, + LANG_BG_AV_START_TWO_MINUTES = 1333, + // FREE IDS 1334-1999 + + // Ticket Strings 2000-2029 + LANG_COMMAND_TICKETNEW = 2000, + LANG_COMMAND_TICKETUPDATED = 2001, + LANG_COMMAND_TICKETPLAYERABANDON = 2002, + LANG_COMMAND_TICKETCLOSED = 2003, + LANG_COMMAND_TICKETDELETED = 2004, + LANG_COMMAND_TICKETNOTEXIST = 2005, + LANG_COMMAND_TICKETCLOSEFIRST = 2006, + LANG_COMMAND_TICKETALREADYASSIGNED = 2007, + LANG_COMMAND_TICKETRELOAD = 2008, + LANG_COMMAND_TICKETSHOWLIST = 2009, + LANG_COMMAND_TICKETSHOWONLINELIST = 2010, + LANG_COMMAND_TICKETSHOWCLOSEDLIST = 2011, + LANG_COMMAND_TICKETASSIGNERROR_A = 2012, + LANG_COMMAND_TICKETASSIGNERROR_B = 2013, + LANG_COMMAND_TICKETNOTASSIGNED = 2014, + LANG_COMMAND_TICKETUNASSIGNSECURITY = 2015, + LANG_COMMAND_TICKETCANNOTCLOSE = 2016, + LANG_COMMAND_TICKETLISTGUID = 2017, + LANG_COMMAND_TICKETLISTNAME = 2018, + LANG_COMMAND_TICKETLISTAGE = 2019, + LANG_COMMAND_TICKETLISTASSIGNEDTO = 2020, + LANG_COMMAND_TICKETLISTUNASSIGNED = 2021, + LANG_COMMAND_TICKETLISTMESSAGE = 2022, + LANG_COMMAND_TICKETLISTCOMMENT = 2023, + LANG_COMMAND_TICKETLISTADDCOMMENT = 2024, + LANG_COMMAND_TICKETLISTAGECREATE = 2025, + + // Trinity strings 5000-9999 + LANG_COMMAND_FREEZE = 5000, + LANG_COMMAND_FREEZE_ERROR = 5001, + LANG_COMMAND_FREEZE_WRONG = 5002, + LANG_COMMAND_UNFREEZE = 5003, + LANG_COMMAND_NO_FROZEN_PLAYERS = 5004, + LANG_COMMAND_LIST_FREEZE = 5005, + LANG_COMMAND_FROZEN_PLAYERS = 5006, + LANG_INSTANCE_RAID_GROUP_ONLY = 5007, + LANG_INSTANCE_CLOSED = 5008, + LANG_COMMAND_PLAYED_TO_ALL = 5009, + LANG_NPCINFO_LINKGUID = 5010, + LANG_TELEPORTED_TO_BY_CONSOLE = 5011, + // for command lookup map + LANG_COMMAND_NOMAPFOUND = 5012, + LANG_CONTINENT = 5013, + LANG_INSTANCE = 5014, + LANG_BATTLEGROUND = 5015, + LANG_ARENA = 5016, + LANG_RAID = 5017, + LANG_HEROIC = 5018, + LANG_MOUNTABLE = 5019, + LANG_NPCINFO_PHASEMASK = 5020, + LANG_NPCINFO_ARMOR = 5021, + LANG_CHANNEL_NOT_PUBLIC = 5022, + LANG_CHANNEL_PUBLIC_CHANGED = 5023, + LANG_GOINFO_ENTRY = 5024, + LANG_GOINFO_TYPE = 5025, + LANG_GOINFO_DISPLAYID = 5026, + LANG_GOINFO_NAME = 5027, + // Room for more Trinity strings 5028-9999 + + // Level requirement notifications + LANG_SAY_REQ = 6604, + LANG_WHISPER_REQ = 6605, + LANG_CHANNEL_REQ = 6606, + LANG_AUCTION_REQ = 6607, + LANG_TICKET_REQ = 6608, + LANG_TRADE_REQ = 6609, + LANG_TRADE_OTHER_REQ = 6610, + LANG_MAIL_SENDER_REQ = 6611, + LANG_MAIL_RECEIVER_REQ = 6612, + + + // Used for GM Announcements + LANG_GM_BROADCAST = 6613, + LANG_GM_NOTIFY = 6614, + LANG_GM_ANNOUNCE_COLOR = 6615, + + LANG_GM_SILENCE = 6616, // "Silence is ON for %s" - Spell 1852 + + LANG_WORLD_CLOSED = 7523, + LANG_WORLD_OPENED = 7524, + + // Use for not-in-offcial-sources patches + // 10000-10999 + // opvp hp + LANG_OPVP_HP_CAPTURE_OVERLOOK_H = 10001, + LANG_OPVP_HP_CAPTURE_OVERLOOK_A = 10002, + LANG_OPVP_HP_CAPTURE_STADIUM_H = 10003, + LANG_OPVP_HP_CAPTURE_STADIUM_A = 10004, + LANG_OPVP_HP_CAPTURE_BROKENHILL_H = 10005, + LANG_OPVP_HP_CAPTURE_BROKENHILL_A = 10006, + LANG_OPVP_HP_LOOSE_OVERLOOK_H = 10007, + LANG_OPVP_HP_LOOSE_OVERLOOK_A = 10008, + LANG_OPVP_HP_LOOSE_STADIUM_H = 10009, + LANG_OPVP_HP_LOOSE_STADIUM_A = 10010, + LANG_OPVP_HP_LOOSE_BROKENHILL_H = 10011, + LANG_OPVP_HP_LOOSE_BROKENHILL_A = 10012, + // opvp zm + LANG_OPVP_ZM_CAPTURE_WEST_H = 10013, + LANG_OPVP_ZM_CAPTURE_WEST_A = 10014, + LANG_OPVP_ZM_CAPTURE_EAST_H = 10015, + LANG_OPVP_ZM_CAPTURE_EAST_A = 10016, + LANG_OPVP_ZM_CAPTURE_GY_H = 10017, + LANG_OPVP_ZM_CAPTURE_GY_A = 10018, + LANG_OPVP_ZM_LOOSE_WEST_H = 10019, + LANG_OPVP_ZM_LOOSE_WEST_A = 10020, + LANG_OPVP_ZM_LOOSE_EAST_H = 10021, + LANG_OPVP_ZM_LOOSE_EAST_A = 10022, + LANG_OPVP_ZM_LOOSE_GY_H = 10023, + LANG_OPVP_ZM_LOOSE_GY_A = 10024, + // opvp na + LANG_OPVP_NA_CAPTURE_H = 10025, + LANG_OPVP_NA_CAPTURE_A = 10026, + LANG_OPVP_NA_LOOSE_H = 10027, + LANG_OPVP_NA_LOOSE_A = 10028, + // opvp tf + LANG_OPVP_TF_CAPTURE_H = 10029, + LANG_OPVP_TF_CAPTURE_A = 10030, + LANG_OPVP_TF_LOOSE_H = 10031, + LANG_OPVP_TF_LOOSE_A = 10032, + // opvp ep + LANG_OPVP_EP_CAPTURE_NPT_H = 10033, + LANG_OPVP_EP_CAPTURE_NPT_A = 10034, + LANG_OPVP_EP_CAPTURE_EWT_H = 10035, + LANG_OPVP_EP_CAPTURE_EWT_A = 10036, + LANG_OPVP_EP_CAPTURE_CGT_H = 10037, + LANG_OPVP_EP_CAPTURE_CGT_A = 10038, + LANG_OPVP_EP_CAPTURE_PWT_H = 10039, + LANG_OPVP_EP_CAPTURE_PWT_A = 10040, + LANG_OPVP_EP_LOOSE_NPT_H = 10041, + LANG_OPVP_EP_LOOSE_NPT_A = 10042, + LANG_OPVP_EP_LOOSE_EWT_H = 10043, + LANG_OPVP_EP_LOOSE_EWT_A = 10044, + LANG_OPVP_EP_LOOSE_CGT_H = 10045, + LANG_OPVP_EP_LOOSE_CGT_A = 10046, + LANG_OPVP_EP_LOOSE_PWT_H = 10047, + LANG_OPVP_EP_LOOSE_PWT_A = 10048, + // opvp si + LANG_OPVP_SI_CAPTURE_H = 10049, + LANG_OPVP_SI_CAPTURE_A = 10050, + // opvp gossips + LANG_OPVP_EP_FLIGHT_NPT = 10051, + LANG_OPVP_EP_FLIGHT_EWT = 10052, + LANG_OPVP_EP_FLIGHT_CGT = 10053, + LANG_OPVP_ZM_GOSSIP_ALLIANCE = 10054, + LANG_OPVP_ZM_GOSSIP_HORDE = 10055, + + LANG_BG_SA_START_TWO_MINUTES = 10056, + LANG_BG_SA_START_ONE_MINUTE = 10057, + LANG_BG_SA_START_HALF_MINUTE = 10058, + LANG_BG_SA_HAS_BEGUN = 10059, + LANG_BG_SA_IS_UNDER_ATTACK = 10060,//The %s is under attack! + LANG_BG_SA_WAS_DESTROYED = 10061,//The %s was destroyed! + LANG_BG_SA_ROUND_ONE_END = 10062,//Round 1 - finished! + LANG_BG_SA_ALLIANCE_CAPTURED_RELIC = 10063,//The Alliance captured the titan portal! + LANG_BG_SA_HORDE_CAPTURED_RELIC = 10064,//The Horde captured the titan portal! + LANG_BG_SA_ROUND_TWO_ONE_MINUTE = 10065,//Round 2 of the Battle for the Strand of the Ancients begins in 1 minute. + LANG_BG_SA_ROUND_TWO_START_HALF_MINUTE = 10066,//Round 2 begins in 30 seconds. Prepare yourselves! + LANG_BG_SA_CHAMBER_BREACHED = 10067,//The chamber has been breached! The titan relic is vulnerable! + LANG_BG_SA_A_GY_SOUTH = 10068,//The Alliance captured the South Graveyard! + LANG_BG_SA_A_GY_WEST = 10069,//The Alliance captured the West Graveyard! + LANG_BG_SA_A_GY_EAST = 10070,//The Alliance captured the East Graveyard! + LANG_BG_SA_H_GY_SOUTH = 10071,//The Horde captured the South Graveyard! + LANG_BG_SA_H_GY_WEST = 10072,//The Horde captured the West Graveyard! + LANG_BG_SA_H_GY_EAST = 10073,//The Horde captured the East Graveyard! + + // Use for custom patches 11000-11999 + LANG_AUTO_BROADCAST = 11000, + LANG_INVALID_REALMID = 11001, + + // NOT RESERVED IDS 12000-1999999999 + // `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID) + // For other tables maybe 2000010000-2147483647 (max index) +}; +#endif + diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h new file mode 100644 index 00000000000..903dd4b09ca --- /dev/null +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -0,0 +1,2772 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_SHAREDDEFINES_H +#define TRINITY_SHAREDDEFINES_H + +#include "Platform/Define.h" +#include + +// loot modes for creatures and gameobjects, bitmask! +enum LootModes +{ + LOOT_MODE_DEFAULT = 1, + LOOT_MODE_HARD_MODE_1 = 2, + LOOT_MODE_HARD_MODE_2 = 4, + LOOT_MODE_HARD_MODE_3 = 8, + LOOT_MODE_HARD_MODE_4 = 16 +}; + +enum Gender +{ + GENDER_MALE = 0, + GENDER_FEMALE = 1, + GENDER_NONE = 2 +}; + +// Race value is index in ChrRaces.dbc +enum Races +{ + RACE_HUMAN = 1, + RACE_ORC = 2, + RACE_DWARF = 3, + RACE_NIGHTELF = 4, + RACE_UNDEAD_PLAYER = 5, + RACE_TAUREN = 6, + RACE_GNOME = 7, + RACE_TROLL = 8, + //RACE_GOBLIN = 9, + RACE_BLOODELF = 10, + RACE_DRAENEI = 11 + //RACE_FEL_ORC = 12, + //RACE_NAGA = 13, + //RACE_BROKEN = 14, + //RACE_SKELETON = 15, + //RACE_VRYKUL = 16, + //RACE_TUSKARR = 17, + //RACE_FOREST_TROLL = 18, + //RACE_TAUNKA = 19, + //RACE_NORTHREND_SKELETON = 20, + //RACE_ICE_TROLL = 21 +}; + +// max+1 for player race +#define MAX_RACES 12 + +#define RACEMASK_ALL_PLAYABLE \ + ((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \ + (1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \ + (1<<(RACE_GNOME-1)) |(1<<(RACE_TROLL-1)) |(1<<(RACE_BLOODELF-1))| \ + (1<<(RACE_DRAENEI-1))) + +// Class value is index in ChrClasses.dbc +enum Classes +{ + CLASS_WARRIOR = 1, + CLASS_PALADIN = 2, + CLASS_HUNTER = 3, + CLASS_ROGUE = 4, + CLASS_PRIEST = 5, + CLASS_DEATH_KNIGHT = 6, + CLASS_SHAMAN = 7, + CLASS_MAGE = 8, + CLASS_WARLOCK = 9, + //CLASS_UNK = 10, + CLASS_DRUID = 11 +}; + +// max+1 for player class +#define MAX_CLASSES 12 + +#define CLASSMASK_ALL_PLAYABLE \ + ((1<<(CLASS_WARRIOR-1))|(1<<(CLASS_PALADIN-1))|(1<<(CLASS_HUNTER-1))| \ + (1<<(CLASS_ROGUE-1)) |(1<<(CLASS_PRIEST-1)) |(1<<(CLASS_SHAMAN-1))| \ + (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) | \ + (1<<(CLASS_DEATH_KNIGHT-1))) + +// valid classes for creature_template.unit_class +enum UnitClass +{ + UNIT_CLASS_WARRIOR = 1, + UNIT_CLASS_PALADIN = 2, + UNIT_CLASS_ROGUE = 4, + UNIT_CLASS_MAGE = 8, +}; + +#define CLASSMASK_ALL_CREATURES ((1<<(UNIT_CLASS_WARRIOR-1)) | (1<<(UNIT_CLASS_PALADIN-1)) | (1<<(UNIT_CLASS_ROGUE-1)) | (1<<(UNIT_CLASS_MAGE-1))) + +#define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1))) + +#define PLAYER_MAX_BATTLEGROUND_QUEUES 2 + +enum ReputationRank +{ + REP_HATED = 0, + REP_HOSTILE = 1, + REP_UNFRIENDLY = 2, + REP_NEUTRAL = 3, + REP_FRIENDLY = 4, + REP_HONORED = 5, + REP_REVERED = 6, + REP_EXALTED = 7 +}; + +#define MIN_REPUTATION_RANK (REP_HATED) +#define MAX_REPUTATION_RANK 8 + +enum MoneyConstants +{ + COPPER = 1, + SILVER = COPPER*100, + GOLD = SILVER*100 +}; + +enum Stats +{ + STAT_STRENGTH = 0, + STAT_AGILITY = 1, + STAT_STAMINA = 2, + STAT_INTELLECT = 3, + STAT_SPIRIT = 4 +}; + +#define MAX_STATS 5 + +enum Powers +{ + POWER_MANA = 0, + POWER_RAGE = 1, + POWER_FOCUS = 2, + POWER_ENERGY = 3, + POWER_HAPPINESS = 4, + POWER_RUNE = 5, + POWER_RUNIC_POWER = 6, + MAX_POWERS = 7, + POWER_ALL = 127, // default for class? + POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) +}; + +enum SpellSchools +{ + SPELL_SCHOOL_NORMAL = 0, + SPELL_SCHOOL_HOLY = 1, + SPELL_SCHOOL_FIRE = 2, + SPELL_SCHOOL_NATURE = 3, + SPELL_SCHOOL_FROST = 4, + SPELL_SCHOOL_SHADOW = 5, + SPELL_SCHOOL_ARCANE = 6 +}; + +#define MAX_SPELL_SCHOOL 7 + +enum SpellSchoolMask +{ + SPELL_SCHOOL_MASK_NONE = 0x00, // not exist + SPELL_SCHOOL_MASK_NORMAL = (1 << SPELL_SCHOOL_NORMAL), // PHYSICAL (Armor) + SPELL_SCHOOL_MASK_HOLY = (1 << SPELL_SCHOOL_HOLY), + SPELL_SCHOOL_MASK_FIRE = (1 << SPELL_SCHOOL_FIRE), + SPELL_SCHOOL_MASK_NATURE = (1 << SPELL_SCHOOL_NATURE), + SPELL_SCHOOL_MASK_FROST = (1 << SPELL_SCHOOL_FROST), + SPELL_SCHOOL_MASK_SHADOW = (1 << SPELL_SCHOOL_SHADOW), + SPELL_SCHOOL_MASK_ARCANE = (1 << SPELL_SCHOOL_ARCANE), + + // unions + + // 124, not include normal and holy damage + SPELL_SCHOOL_MASK_SPELL = (SPELL_SCHOOL_MASK_FIRE | + SPELL_SCHOOL_MASK_NATURE | SPELL_SCHOOL_MASK_FROST | + SPELL_SCHOOL_MASK_SHADOW | SPELL_SCHOOL_MASK_ARCANE), + // 126 + SPELL_SCHOOL_MASK_MAGIC = (SPELL_SCHOOL_MASK_HOLY | SPELL_SCHOOL_MASK_SPELL), + + // 127 + SPELL_SCHOOL_MASK_ALL = (SPELL_SCHOOL_MASK_NORMAL | SPELL_SCHOOL_MASK_MAGIC) +}; + +inline SpellSchools GetFirstSchoolInMask(SpellSchoolMask mask) +{ + for (int i = 0; i < MAX_SPELL_SCHOOL; ++i) + if (mask & (1 << i)) + return SpellSchools(i); + + return SPELL_SCHOOL_NORMAL; +} + +enum ItemQualities +{ + ITEM_QUALITY_POOR = 0, //GREY + ITEM_QUALITY_NORMAL = 1, //WHITE + ITEM_QUALITY_UNCOMMON = 2, //GREEN + ITEM_QUALITY_RARE = 3, //BLUE + ITEM_QUALITY_EPIC = 4, //PURPLE + ITEM_QUALITY_LEGENDARY = 5, //ORANGE + ITEM_QUALITY_ARTIFACT = 6, //LIGHT YELLOW + ITEM_QUALITY_HEIRLOOM = 7 +}; + +#define MAX_ITEM_QUALITY 8 + +enum SpellCategory +{ + SPELL_CATEGORY_FOOD = 11, + SPELL_CATEGORY_DRINK = 59, +}; + +const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = { + 0xff9d9d9d, //GREY + 0xffffffff, //WHITE + 0xff1eff00, //GREEN + 0xff0070dd, //BLUE + 0xffa335ee, //PURPLE + 0xffff8000, //ORANGE + 0xffe6cc80, //LIGHT YELLOW + 0xffe6cc80 //LIGHT YELLOW +}; + +// *********************************** +// Spell Attributes definitions +// *********************************** + +#define SPELL_ATTR_UNK0 0x00000001 // 0 +#define SPELL_ATTR_REQ_AMMO 0x00000002 // 1 +#define SPELL_ATTR_ON_NEXT_SWING 0x00000004 // 2 on next swing +#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 3.0.3 +#define SPELL_ATTR_UNK4 0x00000010 // 4 +#define SPELL_ATTR_TRADESPELL 0x00000020 // 5 trade spells, will be added by client to a sublist of profession spell +#define SPELL_ATTR_PASSIVE 0x00000040 // 6 Passive spell +#define SPELL_ATTR_UNK7 0x00000080 // 7 visible? +#define SPELL_ATTR_UNK8 0x00000100 // 8 +#define SPELL_ATTR_UNK9 0x00000200 // 9 +#define SPELL_ATTR_UNK10 0x00000400 // 10 on next swing 2 +#define SPELL_ATTR_UNK11 0x00000800 // 11 +#define SPELL_ATTR_DAYTIME_ONLY 0x00001000 // 12 only useable at daytime, not set in 2.4.2 +#define SPELL_ATTR_NIGHT_ONLY 0x00002000 // 13 only useable at night, not set in 2.4.2 +#define SPELL_ATTR_INDOORS_ONLY 0x00004000 // 14 only useable indoors, not set in 2.4.2 +#define SPELL_ATTR_OUTDOORS_ONLY 0x00008000 // 15 Only useable outdoors. +#define SPELL_ATTR_NOT_SHAPESHIFT 0x00010000 // 16 Not while shapeshifted +#define SPELL_ATTR_ONLY_STEALTHED 0x00020000 // 17 Must be in stealth +#define SPELL_ATTR_UNK18 0x00040000 // 18 +#define SPELL_ATTR_LEVEL_DAMAGE_CALCULATION 0x00080000 // 19 spelldamage depends on caster level +#define SPELL_ATTR_STOP_ATTACK_TARGET 0x00100000 // 20 Stop attack after use this spell (and not begin attack if use) +#define SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK 0x00200000 // 21 Cannot be dodged/parried/blocked +#define SPELL_ATTR_UNK22 0x00400000 // 22 shoot spells +#define SPELL_ATTR_CASTABLE_WHILE_DEAD 0x00800000 // 23 castable while dead? +#define SPELL_ATTR_CASTABLE_WHILE_MOUNTED 0x01000000 // 24 castable while mounted +#define SPELL_ATTR_DISABLED_WHILE_ACTIVE 0x02000000 // 25 Activate and start cooldown after aura fade or remove summoned creature or go +#define SPELL_ATTR_NEGATIVE_1 0x04000000 // 26 Many negative spells have this attr +#define SPELL_ATTR_CASTABLE_WHILE_SITTING 0x08000000 // 27 castable while sitting +#define SPELL_ATTR_CANT_USED_IN_COMBAT 0x10000000 // 28 Cannot be used in combat +#define SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY 0x20000000 // 29 unaffected by invulnerability (hmm possible not...) +#define SPELL_ATTR_BREAKABLE_BY_DAMAGE 0x40000000 // 30 +#define SPELL_ATTR_CANT_CANCEL 0x80000000 // 31 positive aura can't be canceled + +#define SPELL_ATTR_EX_DISMISS_PET 0x00000001 // 0 dismiss pet and not allow to summon new one? +#define SPELL_ATTR_EX_DRAIN_ALL_POWER 0x00000002 // 1 use all power (Only paladin Lay of Hands and Bunyanize) +#define SPELL_ATTR_EX_CHANNELED_1 0x00000004 // 2 channeled target +#define SPELL_ATTR_EX_PUT_CASTER_IN_COMBAT 0x00000008 // 3 spells that cause a caster to enter a combat +#define SPELL_ATTR_EX_UNK4 0x00000010 // 4 stealth and whirlwind +#define SPELL_ATTR_EX_NOT_BREAK_STEALTH 0x00000020 // 5 Not break stealth +#define SPELL_ATTR_EX_CHANNELED_2 0x00000040 // 6 channeled self +#define SPELL_ATTR_EX_NEGATIVE 0x00000080 // 7 +#define SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET 0x00000100 // 8 Spell req target not to be in combat state +#define SPELL_ATTR_EX_UNK9 0x00000200 // 9 melee spells +#define SPELL_ATTR_EX_UNK10 0x00000400 // 10 no generates threat on cast 100%? (old NO_INITIAL_AGGRO) +#define SPELL_ATTR_EX_UNK11 0x00000800 // 11 aura +#define SPELL_ATTR_EX_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX_STACK_FOR_DIFF_CASTERS 0x00004000 // 14 +#define SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY 0x00008000 // 15 remove auras on immunity +#define SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE 0x00010000 // 16 on immuniy +#define SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET 0x00020000 // 17 +#define SPELL_ATTR_EX_UNK18 0x00040000 // 18 +#define SPELL_ATTR_EX_CANT_TARGET_SELF 0x00080000 // 19 Applies only to unit target - for example Divine Intervention (19752) +#define SPELL_ATTR_EX_REQ_COMBO_POINTS1 0x00100000 // 20 Req combo points on target +#define SPELL_ATTR_EX_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX_REQ_COMBO_POINTS2 0x00400000 // 22 Req combo points on target +#define SPELL_ATTR_EX_UNK23 0x00800000 // 23 +#define SPELL_ATTR_EX_UNK24 0x01000000 // 24 Req fishing pole?? +#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 +#define SPELL_ATTR_EX_UNK26 0x04000000 // 26 works correctly with [target=focus] and [target=mouseover] macros? +#define SPELL_ATTR_EX_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX_IGNORE_IMMUNITY 0x10000000 // 28 removed from Chains of Ice 3.3.0 +#define SPELL_ATTR_EX_UNK29 0x20000000 // 29 +#define SPELL_ATTR_EX_ENABLE_AT_DODGE 0x40000000 // 30 Overpower, Wolverine Bite +#define SPELL_ATTR_EX_UNK31 0x80000000 // 31 + +#define SPELL_ATTR_EX2_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX2_UNK1 0x00000002 // 1 ? many triggered spells have this flag +#define SPELL_ATTR_EX2_CANT_REFLECTED 0x00000004 // 2 ? used for detect can or not spell reflected +#define SPELL_ATTR_EX2_UNK3 0x00000008 // 3 +#define SPELL_ATTR_EX2_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX2_AUTOREPEAT_FLAG 0x00000020 // 5 +#define SPELL_ATTR_EX2_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX2_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 3.0.3 +#define SPELL_ATTR_EX2_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX2_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX2_HEALTH_FUNNEL 0x00000800 // 11 +#define SPELL_ATTR_EX2_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX2_UNK13 0x00002000 // 13 Items enchanted by spells with this flag preserve the enchant to arenas +#define SPELL_ATTR_EX2_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 3.0.3 +#define SPELL_ATTR_EX2_TAME_BEAST 0x00010000 // 16 +#define SPELL_ATTR_EX2_NOT_RESET_AUTOSHOT 0x00020000 // 17 Hunters Shot and Stings only have this flag +#define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet +#define SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT 0x00080000 // 19 does not necessarly need shapeshift +#define SPELL_ATTR_EX2_UNK20 0x00100000 // 20 +#define SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD 0x00200000 // 21 for ice blocks, pala immunity buffs, priest absorb shields, but used also for other spells -> not sure! +#define SPELL_ATTR_EX2_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX2_UNK23 0x00800000 // 23 Only mage Arcane Concentration have this flag +#define SPELL_ATTR_EX2_UNK24 0x01000000 // 24 +#define SPELL_ATTR_EX2_UNK25 0x02000000 // 25 +#define SPELL_ATTR_EX2_UNK26 0x04000000 // 26 unaffected by school immunity +#define SPELL_ATTR_EX2_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 no breaks stealth if it fails?? +#define SPELL_ATTR_EX2_CANT_CRIT 0x20000000 // 29 Spell can't crit +#define SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER 0x40000000 // 30 spell can trigger even if triggered +#define SPELL_ATTR_EX2_FOOD_BUFF 0x80000000 // 31 Food or Drink Buff (like Well Fed) + +#define SPELL_ATTR_EX3_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX3_UNK1 0x00000002 // 1 +#define SPELL_ATTR_EX3_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX3_BLOCKABLE_SPELL 0x00000008 // 3 Only dmg class melee in 3.1.3 +#define SPELL_ATTR_EX3_UNK4 0x00000010 // 4 Druid Rebirth only this spell have this flag +#define SPELL_ATTR_EX3_UNK5 0x00000020 // 5 +#define SPELL_ATTR_EX3_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX3_STACK_FOR_DIFF_CASTERS 0x00000080 // 7 separate stack for every caster +#define SPELL_ATTR_EX3_PLAYERS_ONLY 0x00000100 // 8 Player only? +#define SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2 0x00000200 // 9 triggered from effect? +#define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required +#define SPELL_ATTR_EX3_BATTLEGROUND 0x00000800 // 11 Can casted only on battleground +#define SPELL_ATTR_EX3_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag +#define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag +#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 no triggers effects that trigger on casting a spell?? (15290 - 2.2ptr change) +#define SPELL_ATTR_EX3_NO_INITIAL_AGGRO 0x00020000 // 17 Soothe Animal, 39758, Mind Soothe +#define SPELL_ATTR_EX3_UNK18 0x00040000 // 18 added to Explosive Trap Effect 3.3.0, removed from Mutilate 3.3.0 +#define SPELL_ATTR_EX3_DISABLE_PROC 0x00080000 // 19 during aura proc no spells can trigger (20178, 20375) +#define SPELL_ATTR_EX3_DEATH_PERSISTENT 0x00100000 // 20 Death persistent spells +#define SPELL_ATTR_EX3_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX3_REQ_WAND 0x00400000 // 22 Req wand +#define SPELL_ATTR_EX3_UNK23 0x00800000 // 23 +#define SPELL_ATTR_EX3_REQ_OFFHAND 0x01000000 // 24 Req offhand weapon +#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25 no cause spell pushback ? +#define SPELL_ATTR_EX3_CAN_PROC_TRIGGERED 0x04000000 // 26 +#define SPELL_ATTR_EX3_DRAIN_SOUL 0x08000000 // 27 only drain soul has this flag +#define SPELL_ATTR_EX3_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX3_NO_DONE_BONUS 0x20000000 // 29 Ignore caster spellpower and done damage mods? +#define SPELL_ATTR_EX3_UNK30 0x40000000 // 30 Shaman's Fire Nova 3.3.0, Sweeping Strikes 3.3.0 +#define SPELL_ATTR_EX3_UNK31 0x80000000 // 31 + +#define SPELL_ATTR_EX4_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX4_UNK1 0x00000002 // 1 proc on finishing move? +#define SPELL_ATTR_EX4_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST 0x00000008 // 3 +#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4 This will no longer cause guards to attack on use?? +#define SPELL_ATTR_EX4_UNK5 0x00000020 // 5 +#define SPELL_ATTR_EX4_NOT_STEALABLE 0x00000040 // 6 although such auras might be dispellable, they cannot be stolen +#define SPELL_ATTR_EX4_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX4_FIXED_DAMAGE 0x00000100 // 8 decimate, share damage? +#define SPELL_ATTR_EX4_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST 0x00000400 // 10 Rogue Shiv have this flag +#define SPELL_ATTR_EX4_UNK11 0x00000800 // 11 +#define SPELL_ATTR_EX4_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX4_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX4_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX4_UNK15 0x00008000 // 15 +#define SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA 0x00010000 // 16 not usable in arena +#define SPELL_ATTR_EX4_USABLE_IN_ARENA 0x00020000 // 17 usable in arena +#define SPELL_ATTR_EX4_UNK18 0x00040000 // 18 +#define SPELL_ATTR_EX4_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX4_NOT_CHECK_SELFCAST_POWER 0x00100000 // 20 supersedes message "More powerful spell applied" for self casts. +#define SPELL_ATTR_EX4_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX4_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX4_UNK23 0x00800000 // 23 +#define SPELL_ATTR_EX4_UNK24 0x01000000 // 24 +#define SPELL_ATTR_EX4_UNK25 0x02000000 // 25 pet scaling auras +#define SPELL_ATTR_EX4_CAST_ONLY_IN_OUTLAND 0x04000000 // 26 Can only be used in Outland. +#define SPELL_ATTR_EX4_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX4_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX4_UNK29 0x20000000 // 29 +#define SPELL_ATTR_EX4_UNK30 0x40000000 // 30 +#define SPELL_ATTR_EX4_UNK31 0x80000000 // 31 + +#define SPELL_ATTR_EX5_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP 0x00000002 // 1 not need reagents if UNIT_FLAG_PREPARATION +#define SPELL_ATTR_EX5_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX5_USABLE_WHILE_STUNNED 0x00000008 // 3 usable while stunned +#define SPELL_ATTR_EX5_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX5_SINGLE_TARGET_SPELL 0x00000020 // 5 Only one target can be apply at a time +#define SPELL_ATTR_EX5_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX5_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX5_UNK8 0x00000100 // 8 +#define SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY 0x00000200 // 9 begin periodic tick at aura apply +#define SPELL_ATTR_EX5_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX5_UNK11 0x00000800 // 11 +#define SPELL_ATTR_EX5_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX5_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX5_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX5_UNK15 0x00008000 // 15 +#define SPELL_ATTR_EX5_UNK16 0x00010000 // 16 +#define SPELL_ATTR_EX5_USABLE_WHILE_FEARED 0x00020000 // 17 usable while feared +#define SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED 0x00040000 // 18 usable while confused +#define SPELL_ATTR_EX5_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX5_UNK20 0x00100000 // 20 +#define SPELL_ATTR_EX5_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX5_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX5_UNK23 0x00800000 // 23 +#define SPELL_ATTR_EX5_UNK24 0x01000000 // 24 +#define SPELL_ATTR_EX5_UNK25 0x02000000 // 25 +#define SPELL_ATTR_EX5_UNK26 0x04000000 // 26 +#define SPELL_ATTR_EX5_UNK27 0x08000000 // 27 +#define SPELL_ATTR_EX5_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX5_UNK29 0x20000000 // 29 +#define SPELL_ATTR_EX5_UNK30 0x40000000 // 30 +#define SPELL_ATTR_EX5_UNK31 0x80000000 // 31 Forces all nearby enemies to focus attacks caster + +#define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag +#define SPELL_ATTR_EX6_ONLY_IN_ARENA 0x00000002 // 1 only usable in arena +#define SPELL_ATTR_EX6_IGNORE_CASTER_AURAS 0x00000004 // 2 +#define SPELL_ATTR_EX6_UNK3 0x00000008 // 3 +#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX6_UNK5 0x00000020 // 5 +#define SPELL_ATTR_EX6_UNK6 0x00000040 // 6 +#define SPELL_ATTR_EX6_UNK7 0x00000080 // 7 +#define SPELL_ATTR_EX6_UNK8 0x00000100 // 8 +#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX6_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX6_NOT_IN_RAID_INSTANCE 0x00000800 // 11 not usable in raid instance +#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 +#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 +#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 +#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 +#define SPELL_ATTR_EX6_CLIENT_UI_TARGET_EFFECTS 0x00200000 // 21 it's only client-side attribute +#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3 + +#define SPELL_ATTR_EX7_UNK0 0x00000001 // 0 Shaman's new spells (Call of the ...), Feign Death. +#define SPELL_ATTR_EX7_UNK1 0x00000002 // 1 Not set in 3.2.2a. +#define SPELL_ATTR_EX7_REACTIVATE_AT_RESURRECT 0x00000004 // 2 Paladin's auras and 65607 only. +#define SPELL_ATTR_EX7_UNK3 0x00000008 // 3 Only 43574 test spell. +#define SPELL_ATTR_EX7_UNK4 0x00000010 // 4 Only 66109 test spell. +#define SPELL_ATTR_EX7_SUMMON_PLAYER_TOTEM 0x00000020 // 5 Only Shaman player totems. +#define SPELL_ATTR_EX7_UNK6 0x00000040 // 6 Dark Surge, Surge of Light, Burning Breath triggers (boss spells). +#define SPELL_ATTR_EX7_UNK7 0x00000080 // 7 66218 (Launch) spell. +#define SPELL_ATTR_EX7_UNK8 0x00000100 // 8 Teleports, mounts and other spells. +#define SPELL_ATTR_EX7_UNK9 0x00000200 // 9 Teleports, mounts and other spells. +#define SPELL_ATTR_EX7_DISPEL_CHARGES 0x00000400 // 10 Dispel and Spellsteal individual charges instead of whole aura. +#define SPELL_ATTR_EX7_INTERRUPT_ONLY_NONPLAYER 0x00000800 // 11 Only non-player casts interrupt, though Feral Charge - Bear has it. +#define SPELL_ATTR_EX7_UNK12 0x00001000 // 12 Not set in 3.2.2a. +#define SPELL_ATTR_EX7_UNK13 0x00002000 // 13 Not set in 3.2.2a. +#define SPELL_ATTR_EX7_UNK14 0x00004000 // 14 Only 52150 (Raise Dead - Pet) spell. +#define SPELL_ATTR_EX7_UNK15 0x00008000 // 15 Exorcism. Usable on players? 100% crit chance on undead and demons? +#define SPELL_ATTR_EX7_UNK16 0x00010000 // 16 Druid spells (29166, 54833, 64372, 68285). +#define SPELL_ATTR_EX7_UNK17 0x00020000 // 17 Only 27965 (Suicide) spell. +#define SPELL_ATTR_EX7_HAS_CHARGE_EFFECT 0x00040000 // 18 Only spells that have Charge among effects. +#define SPELL_ATTR_EX7_ZONE_TELEPORT 0x00080000 // 19 Teleports to specific zones. + +#define MIN_TALENT_SPEC 0 +#define MAX_TALENT_SPEC 1 +#define MIN_TALENT_SPECS 1 +#define MAX_TALENT_SPECS 2 +#define MAX_GLYPH_SLOT_INDEX 6 + +// Custom values +enum SpellClickUserTypes +{ + SPELL_CLICK_USER_ANY = 0, + SPELL_CLICK_USER_FRIEND = 1, + SPELL_CLICK_USER_RAID = 2, + SPELL_CLICK_USER_PARTY = 3, + SPELL_CLICK_USER_MAX = 4 +}; + +#define NPC_CLICK_CAST_CASTER_PLAYER 0x01 +#define NPC_CLICK_CAST_TARGET_PLAYER 0x02 +#define NPC_CLICK_CAST_ORIG_CASTER_OWNER 0x04 + +enum SheathTypes +{ + SHEATHETYPE_NONE = 0, + SHEATHETYPE_MAINHAND = 1, + SHEATHETYPE_OFFHAND = 2, + SHEATHETYPE_LARGEWEAPONLEFT = 3, + SHEATHETYPE_LARGEWEAPONRIGHT = 4, + SHEATHETYPE_HIPWEAPONLEFT = 5, + SHEATHETYPE_HIPWEAPONRIGHT = 6, + SHEATHETYPE_SHIELD = 7 +}; + +#define MAX_SHEATHETYPE 8 + +enum CharacterSlot +{ + SLOT_HEAD = 0, + SLOT_NECK = 1, + SLOT_SHOULDERS = 2, + SLOT_SHIRT = 3, + SLOT_CHEST = 4, + SLOT_WAIST = 5, + SLOT_LEGS = 6, + SLOT_FEET = 7, + SLOT_WRISTS = 8, + SLOT_HANDS = 9, + SLOT_FINGER1 = 10, + SLOT_FINGER2 = 11, + SLOT_TRINKET1 = 12, + SLOT_TRINKET2 = 13, + SLOT_BACK = 14, + SLOT_MAIN_HAND = 15, + SLOT_OFF_HAND = 16, + SLOT_RANGED = 17, + SLOT_TABARD = 18, + SLOT_EMPTY = 19 +}; + +enum Language +{ + LANG_UNIVERSAL = 0, + LANG_ORCISH = 1, + LANG_DARNASSIAN = 2, + LANG_TAURAHE = 3, + LANG_DWARVISH = 6, + LANG_COMMON = 7, + LANG_DEMONIC = 8, + LANG_TITAN = 9, + LANG_THALASSIAN = 10, + LANG_DRACONIC = 11, + LANG_KALIMAG = 12, + LANG_GNOMISH = 13, + LANG_TROLL = 14, + LANG_GUTTERSPEAK = 33, + LANG_DRAENEI = 35, + LANG_ZOMBIE = 36, + LANG_GNOMISH_BINARY = 37, + LANG_GOBLIN_BINARY = 38, + LANG_ADDON = 0xFFFFFFFF // used by addons, in 2.4.0 not exist, replaced by messagetype? +}; + +#define LANGUAGES_COUNT 19 + +enum TeamId +{ + TEAM_ALLIANCE = 0, + TEAM_HORDE, + TEAM_NEUTRAL, +}; + +enum Team +{ + HORDE = 67, + ALLIANCE = 469, + //TEAM_STEAMWHEEDLE_CARTEL = 169, // not used in code + //TEAM_ALLIANCE_FORCES = 891, + //TEAM_HORDE_FORCES = 892, + //TEAM_SANCTUARY = 936, + //TEAM_OUTLAND = 980, + TEAM_OTHER = 0, // if ReputationListId > 0 && Flags != FACTION_FLAG_TEAM_HEADER +}; + +const Team TeamId2Team[3] = {ALLIANCE, HORDE, TEAM_OTHER}; + +enum SpellEffects +{ + SPELL_EFFECT_INSTAKILL = 1, + SPELL_EFFECT_SCHOOL_DAMAGE = 2, + SPELL_EFFECT_DUMMY = 3, + SPELL_EFFECT_PORTAL_TELEPORT = 4, + SPELL_EFFECT_TELEPORT_UNITS = 5, + SPELL_EFFECT_APPLY_AURA = 6, + SPELL_EFFECT_ENVIRONMENTAL_DAMAGE = 7, + SPELL_EFFECT_POWER_DRAIN = 8, + SPELL_EFFECT_HEALTH_LEECH = 9, + SPELL_EFFECT_HEAL = 10, + SPELL_EFFECT_BIND = 11, + SPELL_EFFECT_PORTAL = 12, + SPELL_EFFECT_RITUAL_BASE = 13, + SPELL_EFFECT_RITUAL_SPECIALIZE = 14, + SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL = 15, + SPELL_EFFECT_QUEST_COMPLETE = 16, + SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL = 17, + SPELL_EFFECT_RESURRECT = 18, + SPELL_EFFECT_ADD_EXTRA_ATTACKS = 19, + SPELL_EFFECT_DODGE = 20, + SPELL_EFFECT_EVADE = 21, + SPELL_EFFECT_PARRY = 22, + SPELL_EFFECT_BLOCK = 23, + SPELL_EFFECT_CREATE_ITEM = 24, + SPELL_EFFECT_WEAPON = 25, + SPELL_EFFECT_DEFENSE = 26, + SPELL_EFFECT_PERSISTENT_AREA_AURA = 27, + SPELL_EFFECT_SUMMON = 28, + SPELL_EFFECT_LEAP = 29, + SPELL_EFFECT_ENERGIZE = 30, + SPELL_EFFECT_WEAPON_PERCENT_DAMAGE = 31, + SPELL_EFFECT_TRIGGER_MISSILE = 32, + SPELL_EFFECT_OPEN_LOCK = 33, + SPELL_EFFECT_SUMMON_CHANGE_ITEM = 34, + SPELL_EFFECT_APPLY_AREA_AURA_PARTY = 35, + SPELL_EFFECT_LEARN_SPELL = 36, + SPELL_EFFECT_SPELL_DEFENSE = 37, + SPELL_EFFECT_DISPEL = 38, + SPELL_EFFECT_LANGUAGE = 39, + SPELL_EFFECT_DUAL_WIELD = 40, + SPELL_EFFECT_JUMP = 41, + SPELL_EFFECT_JUMP2 = 42, + SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER= 43, + SPELL_EFFECT_SKILL_STEP = 44, + SPELL_EFFECT_ADD_HONOR = 45, + SPELL_EFFECT_SPAWN = 46, + SPELL_EFFECT_TRADE_SKILL = 47, + SPELL_EFFECT_STEALTH = 48, + SPELL_EFFECT_DETECT = 49, + SPELL_EFFECT_TRANS_DOOR = 50, + SPELL_EFFECT_FORCE_CRITICAL_HIT = 51, + SPELL_EFFECT_GUARANTEE_HIT = 52, + SPELL_EFFECT_ENCHANT_ITEM = 53, + SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY = 54, + SPELL_EFFECT_TAMECREATURE = 55, + SPELL_EFFECT_SUMMON_PET = 56, + SPELL_EFFECT_LEARN_PET_SPELL = 57, + SPELL_EFFECT_WEAPON_DAMAGE = 58, + SPELL_EFFECT_CREATE_RANDOM_ITEM = 59, + SPELL_EFFECT_PROFICIENCY = 60, + SPELL_EFFECT_SEND_EVENT = 61, + SPELL_EFFECT_POWER_BURN = 62, + SPELL_EFFECT_THREAT = 63, + SPELL_EFFECT_TRIGGER_SPELL = 64, + SPELL_EFFECT_APPLY_AREA_AURA_RAID = 65, + SPELL_EFFECT_CREATE_MANA_GEM = 66, + SPELL_EFFECT_HEAL_MAX_HEALTH = 67, + SPELL_EFFECT_INTERRUPT_CAST = 68, + SPELL_EFFECT_DISTRACT = 69, + SPELL_EFFECT_PULL = 70, + SPELL_EFFECT_PICKPOCKET = 71, + SPELL_EFFECT_ADD_FARSIGHT = 72, + SPELL_EFFECT_UNTRAIN_TALENTS = 73, + SPELL_EFFECT_APPLY_GLYPH = 74, + SPELL_EFFECT_HEAL_MECHANICAL = 75, + SPELL_EFFECT_SUMMON_OBJECT_WILD = 76, + SPELL_EFFECT_SCRIPT_EFFECT = 77, + SPELL_EFFECT_ATTACK = 78, + SPELL_EFFECT_SANCTUARY = 79, + SPELL_EFFECT_ADD_COMBO_POINTS = 80, + SPELL_EFFECT_CREATE_HOUSE = 81, + SPELL_EFFECT_BIND_SIGHT = 82, + SPELL_EFFECT_DUEL = 83, + SPELL_EFFECT_STUCK = 84, + SPELL_EFFECT_SUMMON_PLAYER = 85, + SPELL_EFFECT_ACTIVATE_OBJECT = 86, + SPELL_EFFECT_WMO_DAMAGE = 87, + SPELL_EFFECT_WMO_REPAIR = 88, + SPELL_EFFECT_WMO_CHANGE = 89, + SPELL_EFFECT_KILL_CREDIT = 90, + SPELL_EFFECT_THREAT_ALL = 91, + SPELL_EFFECT_ENCHANT_HELD_ITEM = 92, + SPELL_EFFECT_FORCE_DESELECT = 93, + SPELL_EFFECT_SELF_RESURRECT = 94, + SPELL_EFFECT_SKINNING = 95, + SPELL_EFFECT_CHARGE = 96, + SPELL_EFFECT_CAST_BUTTON = 97, + SPELL_EFFECT_KNOCK_BACK = 98, + SPELL_EFFECT_DISENCHANT = 99, + SPELL_EFFECT_INEBRIATE = 100, + SPELL_EFFECT_FEED_PET = 101, + SPELL_EFFECT_DISMISS_PET = 102, + SPELL_EFFECT_REPUTATION = 103, + SPELL_EFFECT_SUMMON_OBJECT_SLOT1 = 104, + SPELL_EFFECT_SUMMON_OBJECT_SLOT2 = 105, + SPELL_EFFECT_SUMMON_OBJECT_SLOT3 = 106, + SPELL_EFFECT_SUMMON_OBJECT_SLOT4 = 107, + SPELL_EFFECT_DISPEL_MECHANIC = 108, + SPELL_EFFECT_SUMMON_DEAD_PET = 109, + SPELL_EFFECT_DESTROY_ALL_TOTEMS = 110, + SPELL_EFFECT_DURABILITY_DAMAGE = 111, + SPELL_EFFECT_112 = 112, + SPELL_EFFECT_RESURRECT_NEW = 113, + SPELL_EFFECT_ATTACK_ME = 114, + SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115, + SPELL_EFFECT_SKIN_PLAYER_CORPSE = 116, + SPELL_EFFECT_SPIRIT_HEAL = 117, + SPELL_EFFECT_SKILL = 118, + SPELL_EFFECT_APPLY_AREA_AURA_PET = 119, + SPELL_EFFECT_TELEPORT_GRAVEYARD = 120, + SPELL_EFFECT_NORMALIZED_WEAPON_DMG = 121, + SPELL_EFFECT_122 = 122, + SPELL_EFFECT_SEND_TAXI = 123, + SPELL_EFFECT_PLAYER_PULL = 124, + SPELL_EFFECT_MODIFY_THREAT_PERCENT = 125, + SPELL_EFFECT_STEAL_BENEFICIAL_BUFF = 126, + SPELL_EFFECT_PROSPECTING = 127, + SPELL_EFFECT_APPLY_AREA_AURA_FRIEND = 128, + SPELL_EFFECT_APPLY_AREA_AURA_ENEMY = 129, + SPELL_EFFECT_REDIRECT_THREAT = 130, + SPELL_EFFECT_131 = 131, + SPELL_EFFECT_PLAY_MUSIC = 132, + SPELL_EFFECT_UNLEARN_SPECIALIZATION = 133, + SPELL_EFFECT_KILL_CREDIT2 = 134, + SPELL_EFFECT_CALL_PET = 135, + SPELL_EFFECT_HEAL_PCT = 136, + SPELL_EFFECT_ENERGIZE_PCT = 137, + SPELL_EFFECT_LEAP_BACK = 138, + SPELL_EFFECT_CLEAR_QUEST = 139, + SPELL_EFFECT_FORCE_CAST = 140, + SPELL_EFFECT_141 = 141, + SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE = 142, + SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143, + SPELL_EFFECT_KNOCK_BACK_2 = 144, + SPELL_EFFECT_145 = 145, + SPELL_EFFECT_ACTIVATE_RUNE = 146, + SPELL_EFFECT_QUEST_FAIL = 147, + SPELL_EFFECT_148 = 148, + SPELL_EFFECT_149 = 149, + SPELL_EFFECT_150 = 150, + SPELL_EFFECT_TRIGGER_SPELL_2 = 151, + SPELL_EFFECT_152 = 152, + SPELL_EFFECT_153 = 153, + SPELL_EFFECT_154 = 154, + SPELL_EFFECT_TITAN_GRIP = 155, + SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC = 156, + SPELL_EFFECT_CREATE_ITEM_2 = 157, + SPELL_EFFECT_MILLING = 158, + SPELL_EFFECT_ALLOW_RENAME_PET = 159, + SPELL_EFFECT_160 = 160, + SPELL_EFFECT_TALENT_SPEC_COUNT = 161, + SPELL_EFFECT_TALENT_SPEC_SELECT = 162, + SPELL_EFFECT_163 = 163, + SPELL_EFFECT_164 = 164, + TOTAL_SPELL_EFFECTS = 165 +}; + +enum SpellCastResult +{ + SPELL_FAILED_SUCCESS = 0, + SPELL_FAILED_AFFECTING_COMBAT = 1, + SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 2, + SPELL_FAILED_ALREADY_AT_FULL_MANA = 3, + SPELL_FAILED_ALREADY_AT_FULL_POWER = 4, + SPELL_FAILED_ALREADY_BEING_TAMED = 5, + SPELL_FAILED_ALREADY_HAVE_CHARM = 6, + SPELL_FAILED_ALREADY_HAVE_SUMMON = 7, + SPELL_FAILED_ALREADY_OPEN = 8, + SPELL_FAILED_AURA_BOUNCED = 9, + SPELL_FAILED_AUTOTRACK_INTERRUPTED = 10, + SPELL_FAILED_BAD_IMPLICIT_TARGETS = 11, + SPELL_FAILED_BAD_TARGETS = 12, + SPELL_FAILED_CANT_BE_CHARMED = 13, + SPELL_FAILED_CANT_BE_DISENCHANTED = 14, + SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 15, + SPELL_FAILED_CANT_BE_MILLED = 16, + SPELL_FAILED_CANT_BE_PROSPECTED = 17, + SPELL_FAILED_CANT_CAST_ON_TAPPED = 18, + SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 19, + SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 20, + SPELL_FAILED_CANT_STEALTH = 21, + SPELL_FAILED_CASTER_AURASTATE = 22, + SPELL_FAILED_CASTER_DEAD = 23, + SPELL_FAILED_CHARMED = 24, + SPELL_FAILED_CHEST_IN_USE = 25, + SPELL_FAILED_CONFUSED = 26, + SPELL_FAILED_DONT_REPORT = 27, + SPELL_FAILED_EQUIPPED_ITEM = 28, + SPELL_FAILED_EQUIPPED_ITEM_CLASS = 29, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 30, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 31, + SPELL_FAILED_ERROR = 32, + SPELL_FAILED_FIZZLE = 33, + SPELL_FAILED_FLEEING = 34, + SPELL_FAILED_FOOD_LOWLEVEL = 35, + SPELL_FAILED_HIGHLEVEL = 36, + SPELL_FAILED_HUNGER_SATIATED = 37, + SPELL_FAILED_IMMUNE = 38, + SPELL_FAILED_INCORRECT_AREA = 39, + SPELL_FAILED_INTERRUPTED = 40, + SPELL_FAILED_INTERRUPTED_COMBAT = 41, + SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 42, + SPELL_FAILED_ITEM_GONE = 43, + SPELL_FAILED_ITEM_NOT_FOUND = 44, + SPELL_FAILED_ITEM_NOT_READY = 45, + SPELL_FAILED_LEVEL_REQUIREMENT = 46, + SPELL_FAILED_LINE_OF_SIGHT = 47, + SPELL_FAILED_LOWLEVEL = 48, + SPELL_FAILED_LOW_CASTLEVEL = 49, + SPELL_FAILED_MAINHAND_EMPTY = 50, + SPELL_FAILED_MOVING = 51, + SPELL_FAILED_NEED_AMMO = 52, + SPELL_FAILED_NEED_AMMO_POUCH = 53, + SPELL_FAILED_NEED_EXOTIC_AMMO = 54, + SPELL_FAILED_NEED_MORE_ITEMS = 55, + SPELL_FAILED_NOPATH = 56, + SPELL_FAILED_NOT_BEHIND = 57, + SPELL_FAILED_NOT_FISHABLE = 58, + SPELL_FAILED_NOT_FLYING = 59, + SPELL_FAILED_NOT_HERE = 60, + SPELL_FAILED_NOT_INFRONT = 61, + SPELL_FAILED_NOT_IN_CONTROL = 62, + SPELL_FAILED_NOT_KNOWN = 63, + SPELL_FAILED_NOT_MOUNTED = 64, + SPELL_FAILED_NOT_ON_TAXI = 65, + SPELL_FAILED_NOT_ON_TRANSPORT = 66, + SPELL_FAILED_NOT_READY = 67, + SPELL_FAILED_NOT_SHAPESHIFT = 68, + SPELL_FAILED_NOT_STANDING = 69, + SPELL_FAILED_NOT_TRADEABLE = 70, + SPELL_FAILED_NOT_TRADING = 71, + SPELL_FAILED_NOT_UNSHEATHED = 72, + SPELL_FAILED_NOT_WHILE_GHOST = 73, + SPELL_FAILED_NOT_WHILE_LOOTING = 74, + SPELL_FAILED_NO_AMMO = 75, + SPELL_FAILED_NO_CHARGES_REMAIN = 76, + SPELL_FAILED_NO_CHAMPION = 77, + SPELL_FAILED_NO_COMBO_POINTS = 78, + SPELL_FAILED_NO_DUELING = 79, + SPELL_FAILED_NO_ENDURANCE = 80, + SPELL_FAILED_NO_FISH = 81, + SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 82, + SPELL_FAILED_NO_MOUNTS_ALLOWED = 83, + SPELL_FAILED_NO_PET = 84, + SPELL_FAILED_NO_POWER = 85, + SPELL_FAILED_NOTHING_TO_DISPEL = 86, + SPELL_FAILED_NOTHING_TO_STEAL = 87, + SPELL_FAILED_ONLY_ABOVEWATER = 88, + SPELL_FAILED_ONLY_DAYTIME = 89, + SPELL_FAILED_ONLY_INDOORS = 90, + SPELL_FAILED_ONLY_MOUNTED = 91, + SPELL_FAILED_ONLY_NIGHTTIME = 92, + SPELL_FAILED_ONLY_OUTDOORS = 93, + SPELL_FAILED_ONLY_SHAPESHIFT = 94, + SPELL_FAILED_ONLY_STEALTHED = 95, + SPELL_FAILED_ONLY_UNDERWATER = 96, + SPELL_FAILED_OUT_OF_RANGE = 97, + SPELL_FAILED_PACIFIED = 98, + SPELL_FAILED_POSSESSED = 99, + SPELL_FAILED_REAGENTS = 100, + SPELL_FAILED_REQUIRES_AREA = 101, + SPELL_FAILED_REQUIRES_SPELL_FOCUS = 102, + SPELL_FAILED_ROOTED = 103, + SPELL_FAILED_SILENCED = 104, + SPELL_FAILED_SPELL_IN_PROGRESS = 105, + SPELL_FAILED_SPELL_LEARNED = 106, + SPELL_FAILED_SPELL_UNAVAILABLE = 107, + SPELL_FAILED_STUNNED = 108, + SPELL_FAILED_TARGETS_DEAD = 109, + SPELL_FAILED_TARGET_AFFECTING_COMBAT = 110, + SPELL_FAILED_TARGET_AURASTATE = 111, + SPELL_FAILED_TARGET_DUELING = 112, + SPELL_FAILED_TARGET_ENEMY = 113, + SPELL_FAILED_TARGET_ENRAGED = 114, + SPELL_FAILED_TARGET_FRIENDLY = 115, + SPELL_FAILED_TARGET_IN_COMBAT = 116, + SPELL_FAILED_TARGET_IS_PLAYER = 117, + SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 118, + SPELL_FAILED_TARGET_NOT_DEAD = 119, + SPELL_FAILED_TARGET_NOT_IN_PARTY = 120, + SPELL_FAILED_TARGET_NOT_LOOTED = 121, + SPELL_FAILED_TARGET_NOT_PLAYER = 122, + SPELL_FAILED_TARGET_NO_POCKETS = 123, + SPELL_FAILED_TARGET_NO_WEAPONS = 124, + SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 125, + SPELL_FAILED_TARGET_UNSKINNABLE = 126, + SPELL_FAILED_THIRST_SATIATED = 127, + SPELL_FAILED_TOO_CLOSE = 128, + SPELL_FAILED_TOO_MANY_OF_ITEM = 129, + SPELL_FAILED_TOTEM_CATEGORY = 130, + SPELL_FAILED_TOTEMS = 131, + SPELL_FAILED_TRY_AGAIN = 132, + SPELL_FAILED_UNIT_NOT_BEHIND = 133, + SPELL_FAILED_UNIT_NOT_INFRONT = 134, + SPELL_FAILED_WRONG_PET_FOOD = 135, + SPELL_FAILED_NOT_WHILE_FATIGUED = 136, + SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 137, + SPELL_FAILED_NOT_WHILE_TRADING = 138, + SPELL_FAILED_TARGET_NOT_IN_RAID = 139, + SPELL_FAILED_TARGET_FREEFORALL = 140, + SPELL_FAILED_NO_EDIBLE_CORPSES = 141, + SPELL_FAILED_ONLY_BATTLEGROUNDS = 142, + SPELL_FAILED_TARGET_NOT_GHOST = 143, + SPELL_FAILED_TRANSFORM_UNUSABLE = 144, + SPELL_FAILED_WRONG_WEATHER = 145, + SPELL_FAILED_DAMAGE_IMMUNE = 146, + SPELL_FAILED_PREVENTED_BY_MECHANIC = 147, + SPELL_FAILED_PLAY_TIME = 148, + SPELL_FAILED_REPUTATION = 149, + SPELL_FAILED_MIN_SKILL = 150, + SPELL_FAILED_NOT_IN_ARENA = 151, + SPELL_FAILED_NOT_ON_SHAPESHIFT = 152, + SPELL_FAILED_NOT_ON_STEALTHED = 153, + SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 154, + SPELL_FAILED_NOT_ON_MOUNTED = 155, + SPELL_FAILED_TOO_SHALLOW = 156, + SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 157, + SPELL_FAILED_TARGET_IS_TRIVIAL = 158, + SPELL_FAILED_BM_OR_INVISGOD = 159, + SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 160, + SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 161, + SPELL_FAILED_NOT_IDLE = 162, + SPELL_FAILED_NOT_INACTIVE = 163, + SPELL_FAILED_PARTIAL_PLAYTIME = 164, + SPELL_FAILED_NO_PLAYTIME = 165, + SPELL_FAILED_NOT_IN_BATTLEGROUND = 166, + SPELL_FAILED_NOT_IN_RAID_INSTANCE = 167, + SPELL_FAILED_ONLY_IN_ARENA = 168, + SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 169, + SPELL_FAILED_ON_USE_ENCHANT = 170, + SPELL_FAILED_NOT_ON_GROUND = 171, + SPELL_FAILED_CUSTOM_ERROR = 172, + SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 173, + SPELL_FAILED_TOO_MANY_SOCKETS = 174, + SPELL_FAILED_INVALID_GLYPH = 175, + SPELL_FAILED_UNIQUE_GLYPH = 176, + SPELL_FAILED_GLYPH_SOCKET_LOCKED = 177, + SPELL_FAILED_NO_VALID_TARGETS = 178, + SPELL_FAILED_ITEM_AT_MAX_CHARGES = 179, + SPELL_FAILED_NOT_IN_BARBERSHOP = 180, + SPELL_FAILED_FISHING_TOO_LOW = 181, + SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 182, + SPELL_FAILED_SUMMON_PENDING = 183, + SPELL_FAILED_MAX_SOCKETS = 184, + SPELL_FAILED_PET_CAN_RENAME = 185, + SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 186, + SPELL_FAILED_UNKNOWN = 187, // actually doesn't exist in client + + SPELL_CAST_OK = 255 // custom value, don't must be send to client +}; + +// Spell aura states +enum AuraState +{ // (C) used in caster aura state (T) used in target aura state + // (c) used in caster aura state-not (t) used in target aura state-not + AURA_STATE_NONE = 0, // C | + AURA_STATE_DEFENSE = 1, // C | + AURA_STATE_HEALTHLESS_20_PERCENT = 2, // CcT | + AURA_STATE_BERSERKING = 3, // C T | + AURA_STATE_FROZEN = 4, // c t| frozen target + AURA_STATE_JUDGEMENT = 5, // C | + //AURA_STATE_UNKNOWN6 = 6, // | not used + AURA_STATE_HUNTER_PARRY = 7, // C | + //AURA_STATE_UNKNOWN7 = 7, // c | creature cheap shot / focused bursts spells + //AURA_STATE_UNKNOWN8 = 8, // t| test spells + //AURA_STATE_UNKNOWN9 = 9, // | + AURA_STATE_WARRIOR_VICTORY_RUSH = 10, // C | warrior victory rush + //AURA_STATE_UNKNOWN11 = 11, // C t| 60348 - Maelstrom Ready!, test spells + AURA_STATE_FAERIE_FIRE = 12, // c t| + AURA_STATE_HEALTHLESS_35_PERCENT = 13, // C T | + AURA_STATE_CONFLAGRATE = 14, // T | + AURA_STATE_SWIFTMEND = 15, // T | + AURA_STATE_DEADLY_POISON = 16, // T | + AURA_STATE_ENRAGE = 17, // C | + AURA_STATE_BLEEDING = 18, // T| + //AURA_STATE_UNKNOWN19 = 19, // | not used + //AURA_STATE_UNKNOWN20 = 20, // c | only (45317 Suicide) + //AURA_STATE_UNKNOWN21 = 21, // | not used + //AURA_STATE_UNKNOWN22 = 22, // C t| varius spells (63884, 50240) + AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C | +}; + +#define PER_CASTER_AURA_STATE_MASK (\ + (1<<(AURA_STATE_CONFLAGRATE-1))|(1<<(AURA_STATE_DEADLY_POISON-1))) + +// Spell mechanics +enum Mechanics +{ + MECHANIC_NONE = 0, + MECHANIC_CHARM = 1, + MECHANIC_DISORIENTED = 2, + MECHANIC_DISARM = 3, + MECHANIC_DISTRACT = 4, + MECHANIC_FEAR = 5, + MECHANIC_GRIP = 6, + MECHANIC_ROOT = 7, + MECHANIC_PACIFY = 8, //0 spells use this mechanic + MECHANIC_SILENCE = 9, + MECHANIC_SLEEP = 10, + MECHANIC_SNARE = 11, + MECHANIC_STUN = 12, + MECHANIC_FREEZE = 13, + MECHANIC_KNOCKOUT = 14, + MECHANIC_BLEED = 15, + MECHANIC_BANDAGE = 16, + MECHANIC_POLYMORPH = 17, + MECHANIC_BANISH = 18, + MECHANIC_SHIELD = 19, + MECHANIC_SHACKLE = 20, + MECHANIC_MOUNT = 21, + MECHANIC_INFECTED = 22, + MECHANIC_TURN = 23, + MECHANIC_HORROR = 24, + MECHANIC_INVULNERABILITY = 25, + MECHANIC_INTERRUPT = 26, + MECHANIC_DAZE = 27, + MECHANIC_DISCOVERY = 28, + MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block + MECHANIC_SAPPED = 30, + MECHANIC_ENRAGED = 31 +}; + +// Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967da6) +#define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK (\ + (1<(only this effect in the spell) can't cast to it, +//some aura(related to Mechanics or ImmuneToState) can't apply to it. +enum SpellImmunity +{ + IMMUNITY_EFFECT = 0, // enum SpellEffects + IMMUNITY_STATE = 1, // enum AuraType + IMMUNITY_SCHOOL = 2, // enum SpellSchoolMask + IMMUNITY_DAMAGE = 3, // enum SpellSchoolMask + IMMUNITY_DISPEL = 4, // enum DispelType + IMMUNITY_MECHANIC = 5, // enum Mechanics + IMMUNITY_ID = 6 +}; + +#define MAX_SPELL_IMMUNITY 7 + +enum Targets +{ + TARGET_UNIT_CASTER = 1, + TARGET_UNIT_NEARBY_ENEMY = 2, + TARGET_UNIT_NEARBY_ALLY = 3, + TARGET_UNIT_NEARBY_ALLY_UNK = 4, + TARGET_UNIT_PET = 5, + TARGET_UNIT_TARGET_ENEMY = 6, + TARGET_UNIT_AREA_ENTRY_SRC = 7, + TARGET_UNIT_AREA_ENTRY_DST = 8, + TARGET_DST_HOME = 9, // uses in teleport to innkeeper spells + TARGET_UNIT_TARGET_DEST_CASTER = 11, // teleport target to caster + TARGET_UNIT_AREA_ENEMY_SRC = 15, + TARGET_UNIT_AREA_ENEMY_DST = 16, + TARGET_DST_DB = 17, // uses in teleport spells and some other + TARGET_DST_CASTER = 18, + TARGET_UNIT_PARTY_CASTER = 20, + TARGET_UNIT_TARGET_ALLY = 21, + TARGET_SRC_CASTER = 22, + TARGET_GAMEOBJECT = 23, + //TARGET_OBJECT_OPEN + TARGET_UNIT_CONE_ENEMY = 24, + TARGET_UNIT_TARGET_ANY = 25, + TARGET_GAMEOBJECT_ITEM = 26, + //TARGET_OBJECT_ITEM_PICKLOCK + TARGET_UNIT_MASTER = 27, + TARGET_DEST_DYNOBJ_ENEMY = 28, + TARGET_DEST_DYNOBJ_ALLY = 29, // only for effect 27 + TARGET_UNIT_AREA_ALLY_SRC = 30, // in TargetB used only with TARGET_SRC_CASTER and in self casting range in TargetA + TARGET_UNIT_AREA_ALLY_DST = 31, + TARGET_MINION = 32, + //TARGET_DEST_SUMMON + TARGET_UNIT_AREA_PARTY_SRC = 33, + TARGET_UNIT_AREA_PARTY_DST = 34, // used in Tranquility + TARGET_UNIT_TARGET_PARTY = 35, + TARGET_DEST_CASTER_RANDOM_UNKNOWN = 36, //unknown + TARGET_UNIT_PARTY_TARGET = 37, + TARGET_UNIT_NEARBY_ENTRY = 38, + TARGET_UNIT_CASTER_FISHING = 39, + TARGET_GAMEOBJECT_NEARBY_ENTRY = 40, + TARGET_DEST_CASTER_FRONT_LEFT = 41, //earth totem + TARGET_DEST_CASTER_BACK_LEFT = 42, //water totem + TARGET_DEST_CASTER_BACK_RIGHT = 43, //air totem + TARGET_DEST_CASTER_FRONT_RIGHT = 44, //fire totem + TARGET_UNIT_CHAINHEAL = 45, + TARGET_DST_NEARBY_ENTRY = 46, + TARGET_DEST_CASTER_FRONT = 47, + TARGET_DEST_CASTER_BACK = 48, + TARGET_DEST_CASTER_RIGHT = 49, + TARGET_DEST_CASTER_LEFT = 50, + TARGET_OBJECT_AREA_SRC = 51, + TARGET_OBJECT_AREA_DST = 52, + TARGET_DST_TARGET_ENEMY = 53, // set unit coordinates as dest, only 16 target B imlemented + TARGET_UNIT_CONE_ENEMY_UNKNOWN = 54, // 180 degree, or different angle + TARGET_DEST_CASTER_FRONT_LEAP = 55, // for a leap spell + TARGET_UNIT_RAID_CASTER = 56, + TARGET_UNIT_TARGET_RAID = 57, + TARGET_UNIT_NEARBY_RAID = 58, + TARGET_UNIT_CONE_ALLY = 59, + TARGET_UNIT_CONE_ENTRY = 60, + TARGET_UNIT_CLASS_TARGET = 61, + TARGET_TEST = 62, // for a test spell + TARGET_DEST_TARGET_ANY = 63, + TARGET_DEST_TARGET_FRONT = 64, + TARGET_DEST_TARGET_BACK = 65, // uses in teleport behind spells + TARGET_DEST_TARGET_RIGHT = 66, + TARGET_DEST_TARGET_LEFT = 67, + TARGET_DEST_TARGET_FRONT_LEFT = 68, + TARGET_DEST_TARGET_BACK_LEFT = 69, + TARGET_DEST_TARGET_BACK_RIGHT = 70, + TARGET_DEST_TARGET_FRONT_RIGHT = 71, + TARGET_DEST_CASTER_RANDOM = 72, + TARGET_DEST_CASTER_RADIUS = 73, + TARGET_DEST_TARGET_RANDOM = 74, + TARGET_DEST_TARGET_RADIUS = 75, + TARGET_DEST_CHANNEL = 76, + TARGET_UNIT_CHANNEL = 77, + TARGET_DEST_DEST_FRONT = 78, + TARGET_DEST_DEST_BACK = 79, + TARGET_DEST_DEST_RIGHT = 80, + TARGET_DEST_DEST_LEFT = 81, + TARGET_DEST_DEST_FRONT_LEFT = 82, + TARGET_DEST_DEST_BACK_LEFT = 83, + TARGET_DEST_DEST_BACK_RIGHT = 84, + TARGET_DEST_DEST_FRONT_RIGHT = 85, + TARGET_DEST_DEST_RANDOM = 86, + TARGET_DEST_DEST = 87, + TARGET_DEST_DYNOBJ_NONE = 88, + TARGET_DEST_TRAJ = 89, + TARGET_UNIT_MINIPET = 90, + TARGET_DEST_DEST_RANDOM_DIR_DIST = 91, + TARGET_UNIT_UNK_92 = 92, + TARGET_CORPSE_AREA_ENEMY_PLAYER_SRC= 93, + TARGET_UNIT_VEHICLE = 94, + TARGET_UNIT_DRIVER = 95, + TARGET_UNIT_PASSENGER_0 = 96, + TARGET_UNIT_PASSENGER_1 = 97, + TARGET_UNIT_PASSENGER_2 = 98, + TARGET_UNIT_PASSENGER_3 = 99, + TARGET_UNIT_PASSENGER_4 = 100, + TARGET_UNIT_PASSENGER_5 = 101, + TARGET_UNIT_PASSENGER_6 = 102, + TARGET_UNIT_PASSENGER_7 = 103, + TARGET_UNIT_AREA_PATH = 104, + TARGET_UNIT_UNK_105 = 105, // 1 spell + TARGET_DEST_UNK_110 = 110, // some kind of traj? +}; + +#define TOTAL_SPELL_TARGETS 105 + +enum SpellMissInfo +{ + SPELL_MISS_NONE = 0, + SPELL_MISS_MISS = 1, + SPELL_MISS_RESIST = 2, + SPELL_MISS_DODGE = 3, + SPELL_MISS_PARRY = 4, + SPELL_MISS_BLOCK = 5, + SPELL_MISS_EVADE = 6, + SPELL_MISS_IMMUNE = 7, + SPELL_MISS_IMMUNE2 = 8, + SPELL_MISS_DEFLECT = 9, + SPELL_MISS_ABSORB = 10, + SPELL_MISS_REFLECT = 11 +}; + +enum SpellHitType +{ + SPELL_HIT_TYPE_UNK1 = 0x00001, + SPELL_HIT_TYPE_CRIT = 0x00002, + SPELL_HIT_TYPE_UNK3 = 0x00004, + SPELL_HIT_TYPE_UNK4 = 0x00008, + SPELL_HIT_TYPE_UNK5 = 0x00010, // replace caster? + SPELL_HIT_TYPE_UNK6 = 0x00020 +}; + +enum SpellDmgClass +{ + SPELL_DAMAGE_CLASS_NONE = 0, + SPELL_DAMAGE_CLASS_MAGIC = 1, + SPELL_DAMAGE_CLASS_MELEE = 2, + SPELL_DAMAGE_CLASS_RANGED = 3 +}; + +enum SpellPreventionType +{ + SPELL_PREVENTION_TYPE_NONE = 0, + SPELL_PREVENTION_TYPE_SILENCE = 1, + SPELL_PREVENTION_TYPE_PACIFY = 2 +}; + +enum GameobjectTypes +{ + GAMEOBJECT_TYPE_DOOR = 0, + GAMEOBJECT_TYPE_BUTTON = 1, + GAMEOBJECT_TYPE_QUESTGIVER = 2, + GAMEOBJECT_TYPE_CHEST = 3, + GAMEOBJECT_TYPE_BINDER = 4, + GAMEOBJECT_TYPE_GENERIC = 5, + GAMEOBJECT_TYPE_TRAP = 6, + GAMEOBJECT_TYPE_CHAIR = 7, + GAMEOBJECT_TYPE_SPELL_FOCUS = 8, + GAMEOBJECT_TYPE_TEXT = 9, + GAMEOBJECT_TYPE_GOOBER = 10, + GAMEOBJECT_TYPE_TRANSPORT = 11, + GAMEOBJECT_TYPE_AREADAMAGE = 12, + GAMEOBJECT_TYPE_CAMERA = 13, + GAMEOBJECT_TYPE_MAP_OBJECT = 14, + GAMEOBJECT_TYPE_MO_TRANSPORT = 15, + GAMEOBJECT_TYPE_DUEL_ARBITER = 16, + GAMEOBJECT_TYPE_FISHINGNODE = 17, + GAMEOBJECT_TYPE_SUMMONING_RITUAL = 18, + GAMEOBJECT_TYPE_MAILBOX = 19, + GAMEOBJECT_TYPE_DO_NOT_USE = 20, + GAMEOBJECT_TYPE_GUARDPOST = 21, + GAMEOBJECT_TYPE_SPELLCASTER = 22, + GAMEOBJECT_TYPE_MEETINGSTONE = 23, + GAMEOBJECT_TYPE_FLAGSTAND = 24, + GAMEOBJECT_TYPE_FISHINGHOLE = 25, + GAMEOBJECT_TYPE_FLAGDROP = 26, + GAMEOBJECT_TYPE_MINI_GAME = 27, + GAMEOBJECT_TYPE_DO_NOT_USE_2 = 28, + GAMEOBJECT_TYPE_CAPTURE_POINT = 29, + GAMEOBJECT_TYPE_AURA_GENERATOR = 30, + GAMEOBJECT_TYPE_DUNGEON_DIFFICULTY = 31, + GAMEOBJECT_TYPE_BARBER_CHAIR = 32, + GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING = 33, + GAMEOBJECT_TYPE_GUILD_BANK = 34, + GAMEOBJECT_TYPE_TRAPDOOR = 35 +}; + +#define MAX_GAMEOBJECT_TYPE 36 // sending to client this or greater value can crash client. + +#define GAMEOBJECT_FISHINGNODE_ENTRY 35591 // Better to define it somewhere instead of hardcoding everywhere + +enum GameObjectFlags +{ + GO_FLAG_IN_USE = 0x00000001, //disables interaction while animated + GO_FLAG_LOCKED = 0x00000002, //require key, spell, event, etc to be opened. Makes "Locked" appear in tooltip + GO_FLAG_INTERACT_COND = 0x00000004, //cannot interact (condition to interact) + GO_FLAG_TRANSPORT = 0x00000008, //any kind of transport? Object can transport (elevator, boat, car) + GO_FLAG_UNK1 = 0x00000010, // + GO_FLAG_NODESPAWN = 0x00000020, //never despawn, typically for doors, they just change state + GO_FLAG_TRIGGERED = 0x00000040, //typically, summoned objects. Triggered by spell or other events + GO_FLAG_DAMAGED = 0x00000200, + GO_FLAG_DESTROYED = 0x00000400, +}; + +enum TextEmotes +{ + TEXTEMOTE_AGREE = 1, + TEXTEMOTE_AMAZE = 2, + TEXTEMOTE_ANGRY = 3, + TEXTEMOTE_APOLOGIZE = 4, + TEXTEMOTE_APPLAUD = 5, + TEXTEMOTE_BASHFUL = 6, + TEXTEMOTE_BECKON = 7, + TEXTEMOTE_BEG = 8, + TEXTEMOTE_BITE = 9, + TEXTEMOTE_BLEED = 10, + TEXTEMOTE_BLINK = 11, + TEXTEMOTE_BLUSH = 12, + TEXTEMOTE_BONK = 13, + TEXTEMOTE_BORED = 14, + TEXTEMOTE_BOUNCE = 15, + TEXTEMOTE_BRB = 16, + TEXTEMOTE_BOW = 17, + TEXTEMOTE_BURP = 18, + TEXTEMOTE_BYE = 19, + TEXTEMOTE_CACKLE = 20, + TEXTEMOTE_CHEER = 21, + TEXTEMOTE_CHICKEN = 22, + TEXTEMOTE_CHUCKLE = 23, + TEXTEMOTE_CLAP = 24, + TEXTEMOTE_CONFUSED = 25, + TEXTEMOTE_CONGRATULATE = 26, + TEXTEMOTE_COUGH = 27, + TEXTEMOTE_COWER = 28, + TEXTEMOTE_CRACK = 29, + TEXTEMOTE_CRINGE = 30, + TEXTEMOTE_CRY = 31, + TEXTEMOTE_CURIOUS = 32, + TEXTEMOTE_CURTSEY = 33, + TEXTEMOTE_DANCE = 34, + TEXTEMOTE_DRINK = 35, + TEXTEMOTE_DROOL = 36, + TEXTEMOTE_EAT = 37, + TEXTEMOTE_EYE = 38, + TEXTEMOTE_FART = 39, + TEXTEMOTE_FIDGET = 40, + TEXTEMOTE_FLEX = 41, + TEXTEMOTE_FROWN = 42, + TEXTEMOTE_GASP = 43, + TEXTEMOTE_GAZE = 44, + TEXTEMOTE_GIGGLE = 45, + TEXTEMOTE_GLARE = 46, + TEXTEMOTE_GLOAT = 47, + TEXTEMOTE_GREET = 48, + TEXTEMOTE_GRIN = 49, + TEXTEMOTE_GROAN = 50, + TEXTEMOTE_GROVEL = 51, + TEXTEMOTE_GUFFAW = 52, + TEXTEMOTE_HAIL = 53, + TEXTEMOTE_HAPPY = 54, + TEXTEMOTE_HELLO = 55, + TEXTEMOTE_HUG = 56, + TEXTEMOTE_HUNGRY = 57, + TEXTEMOTE_KISS = 58, + TEXTEMOTE_KNEEL = 59, + TEXTEMOTE_LAUGH = 60, + TEXTEMOTE_LAYDOWN = 61, + TEXTEMOTE_MESSAGE = 62, + TEXTEMOTE_MOAN = 63, + TEXTEMOTE_MOON = 64, + TEXTEMOTE_MOURN = 65, + TEXTEMOTE_NO = 66, + TEXTEMOTE_NOD = 67, + TEXTEMOTE_NOSEPICK = 68, + TEXTEMOTE_PANIC = 69, + TEXTEMOTE_PEER = 70, + TEXTEMOTE_PLEAD = 71, + TEXTEMOTE_POINT = 72, + TEXTEMOTE_POKE = 73, + TEXTEMOTE_PRAY = 74, + TEXTEMOTE_ROAR = 75, + TEXTEMOTE_ROFL = 76, + TEXTEMOTE_RUDE = 77, + TEXTEMOTE_SALUTE = 78, + TEXTEMOTE_SCRATCH = 79, + TEXTEMOTE_SEXY = 80, + TEXTEMOTE_SHAKE = 81, + TEXTEMOTE_SHOUT = 82, + TEXTEMOTE_SHRUG = 83, + TEXTEMOTE_SHY = 84, + TEXTEMOTE_SIGH = 85, + TEXTEMOTE_SIT = 86, + TEXTEMOTE_SLEEP = 87, + TEXTEMOTE_SNARL = 88, + TEXTEMOTE_SPIT = 89, + TEXTEMOTE_STARE = 90, + TEXTEMOTE_SURPRISED = 91, + TEXTEMOTE_SURRENDER = 92, + TEXTEMOTE_TALK = 93, + TEXTEMOTE_TALKEX = 94, + TEXTEMOTE_TALKQ = 95, + TEXTEMOTE_TAP = 96, + TEXTEMOTE_THANK = 97, + TEXTEMOTE_THREATEN = 98, + TEXTEMOTE_TIRED = 99, + TEXTEMOTE_VICTORY = 100, + TEXTEMOTE_WAVE = 101, + TEXTEMOTE_WELCOME = 102, + TEXTEMOTE_WHINE = 103, + TEXTEMOTE_WHISTLE = 104, + TEXTEMOTE_WORK = 105, + TEXTEMOTE_YAWN = 106, + TEXTEMOTE_BOGGLE = 107, + TEXTEMOTE_CALM = 108, + TEXTEMOTE_COLD = 109, + TEXTEMOTE_COMFORT = 110, + TEXTEMOTE_CUDDLE = 111, + TEXTEMOTE_DUCK = 112, + TEXTEMOTE_INSULT = 113, + TEXTEMOTE_INTRODUCE = 114, + TEXTEMOTE_JK = 115, + TEXTEMOTE_LICK = 116, + TEXTEMOTE_LISTEN = 117, + TEXTEMOTE_LOST = 118, + TEXTEMOTE_MOCK = 119, + TEXTEMOTE_PONDER = 120, + TEXTEMOTE_POUNCE = 121, + TEXTEMOTE_PRAISE = 122, + TEXTEMOTE_PURR = 123, + TEXTEMOTE_PUZZLE = 124, + TEXTEMOTE_RAISE = 125, + TEXTEMOTE_READY = 126, + TEXTEMOTE_SHIMMY = 127, + TEXTEMOTE_SHIVER = 128, + TEXTEMOTE_SHOO = 129, + TEXTEMOTE_SLAP = 130, + TEXTEMOTE_SMIRK = 131, + TEXTEMOTE_SNIFF = 132, + TEXTEMOTE_SNUB = 133, + TEXTEMOTE_SOOTHE = 134, + TEXTEMOTE_STINK = 135, + TEXTEMOTE_TAUNT = 136, + TEXTEMOTE_TEASE = 137, + TEXTEMOTE_THIRSTY = 138, + TEXTEMOTE_VETO = 139, + TEXTEMOTE_SNICKER = 140, + TEXTEMOTE_STAND = 141, + TEXTEMOTE_TICKLE = 142, + TEXTEMOTE_VIOLIN = 143, + TEXTEMOTE_SMILE = 163, + TEXTEMOTE_RASP = 183, + TEXTEMOTE_PITY = 203, + TEXTEMOTE_GROWL = 204, + TEXTEMOTE_BARK = 205, + TEXTEMOTE_SCARED = 223, + TEXTEMOTE_FLOP = 224, + TEXTEMOTE_LOVE = 225, + TEXTEMOTE_MOO = 226, + TEXTEMOTE_OPENFIRE = 327, + TEXTEMOTE_FLIRT = 328, + TEXTEMOTE_JOKE = 329, + TEXTEMOTE_COMMEND = 243, + TEXTEMOTE_WINK = 363, + TEXTEMOTE_PAT = 364, + TEXTEMOTE_SERIOUS = 365, + TEXTEMOTE_MOUNTSPECIAL = 366, + TEXTEMOTE_GOODLUCK = 367, + TEXTEMOTE_BLAME = 368, + TEXTEMOTE_BLANK = 369, + TEXTEMOTE_BRANDISH = 370, + TEXTEMOTE_BREATH = 371, + TEXTEMOTE_DISAGREE = 372, + TEXTEMOTE_DOUBT = 373, + TEXTEMOTE_EMBARRASS = 374, + TEXTEMOTE_ENCOURAGE = 375, + TEXTEMOTE_ENEMY = 376, + TEXTEMOTE_EYEBROW = 377, + TEXTEMOTE_TOAST = 378 +}; + +enum Emote +{ + EMOTE_ONESHOT_NONE = 0, + EMOTE_ONESHOT_TALK = 1, + EMOTE_ONESHOT_BOW = 2, + EMOTE_ONESHOT_WAVE = 3, + EMOTE_ONESHOT_CHEER = 4, + EMOTE_ONESHOT_EXCLAMATION = 5, + EMOTE_ONESHOT_QUESTION = 6, + EMOTE_ONESHOT_EAT = 7, + EMOTE_STATE_DANCE = 10, + EMOTE_ONESHOT_LAUGH = 11, + EMOTE_STATE_SLEEP = 12, + EMOTE_STATE_SIT = 13, + EMOTE_ONESHOT_RUDE = 14, + EMOTE_ONESHOT_ROAR = 15, + EMOTE_ONESHOT_KNEEL = 16, + EMOTE_ONESHOT_KISS = 17, + EMOTE_ONESHOT_CRY = 18, + EMOTE_ONESHOT_CHICKEN = 19, + EMOTE_ONESHOT_BEG = 20, + EMOTE_ONESHOT_APPLAUD = 21, + EMOTE_ONESHOT_SHOUT = 22, + EMOTE_ONESHOT_FLEX = 23, + EMOTE_ONESHOT_SHY = 24, + EMOTE_ONESHOT_POINT = 25, + EMOTE_STATE_STAND = 26, + EMOTE_STATE_READYUNARMED = 27, + EMOTE_STATE_WORK_SHEATHED = 28, + EMOTE_STATE_POINT = 29, + EMOTE_STATE_NONE = 30, + EMOTE_ONESHOT_WOUND = 33, + EMOTE_ONESHOT_WOUNDCRITICAL = 34, + EMOTE_ONESHOT_ATTACKUNARMED = 35, + EMOTE_ONESHOT_ATTACK1H = 36, + EMOTE_ONESHOT_ATTACK2HTIGHT = 37, + EMOTE_ONESHOT_ATTACK2HLOOSE = 38, + EMOTE_ONESHOT_PARRYUNARMED = 39, + EMOTE_ONESHOT_PARRYSHIELD = 43, + EMOTE_ONESHOT_READYUNARMED = 44, + EMOTE_ONESHOT_READY1H = 45, + EMOTE_ONESHOT_READYBOW = 48, + EMOTE_ONESHOT_SPELLPRECAST = 50, + EMOTE_ONESHOT_SPELLCAST = 51, + EMOTE_ONESHOT_BATTLEROAR = 53, + EMOTE_ONESHOT_SPECIALATTACK1H = 54, + EMOTE_ONESHOT_KICK = 60, + EMOTE_ONESHOT_ATTACKTHROWN = 61, + EMOTE_STATE_STUN = 64, + EMOTE_STATE_DEAD = 65, + EMOTE_ONESHOT_SALUTE = 66, + EMOTE_STATE_KNEEL = 68, + EMOTE_STATE_USESTANDING = 69, + EMOTE_ONESHOT_WAVE_NOSHEATHE = 70, + EMOTE_ONESHOT_CHEER_NOSHEATHE = 71, + EMOTE_ONESHOT_EAT_NOSHEATHE = 92, + EMOTE_STATE_STUN_NOSHEATHE = 93, + EMOTE_ONESHOT_DANCE = 94, + EMOTE_ONESHOT_SALUTE_NOSHEATH = 113, + EMOTE_STATE_USESTANDING_NOSHEATHE = 133, + EMOTE_ONESHOT_LAUGH_NOSHEATHE = 153, + EMOTE_STATE_WORK = 173, + EMOTE_STATE_SPELLPRECAST = 193, + EMOTE_ONESHOT_READYRIFLE = 213, + EMOTE_STATE_READYRIFLE = 214, + EMOTE_STATE_WORK_MINING = 233, + EMOTE_STATE_WORK_CHOPWOOD = 234, + EMOTE_STATE_APPLAUD = 253, + EMOTE_ONESHOT_LIFTOFF = 254, + EMOTE_ONESHOT_YES = 273, + EMOTE_ONESHOT_NO = 274, + EMOTE_ONESHOT_TRAIN = 275, + EMOTE_ONESHOT_LAND = 293, + EMOTE_STATE_AT_EASE = 313, + EMOTE_STATE_READY1H = 333, + EMOTE_STATE_SPELLKNEELSTART = 353, + EMOTE_STATE_SUBMERGED = 373, + EMOTE_ONESHOT_SUBMERGE = 374, + EMOTE_STATE_READY2H = 375, + EMOTE_STATE_READYBOW = 376, + EMOTE_ONESHOT_MOUNTSPECIAL = 377, + EMOTE_STATE_TALK = 378, + EMOTE_STATE_FISHING = 379, + EMOTE_ONESHOT_FISHING = 380, + EMOTE_ONESHOT_LOOT = 381, + EMOTE_STATE_WHIRLWIND = 382, + EMOTE_STATE_DROWNED = 383, + EMOTE_STATE_HOLD_BOW = 384, + EMOTE_STATE_HOLD_RIFLE = 385, + EMOTE_STATE_HOLD_THROWN = 386, + EMOTE_ONESHOT_DROWN = 387, + EMOTE_ONESHOT_STOMP = 388, + EMOTE_ONESHOT_ATTACKOFF = 389, + EMOTE_ONESHOT_ATTACKOFFPIERCE = 390, + EMOTE_STATE_ROAR = 391, + EMOTE_STATE_LAUGH = 392, + EMOTE_ONESHOT_CREATURE_SPECIAL = 393, + EMOTE_ONESHOT_JUMPLANDRUN = 394, + EMOTE_ONESHOT_JUMPEND = 395, + EMOTE_ONESHOT_TALK_NOSHEATHE = 396, + EMOTE_ONESHOT_POINT_NOSHEATHE = 397, + EMOTE_STATE_CANNIBALIZE = 398, + EMOTE_ONESHOT_JUMPSTART = 399, + EMOTE_STATE_DANCESPECIAL = 400, + EMOTE_ONESHOT_DANCESPECIAL = 401, + EMOTE_ONESHOT_CUSTOMSPELL01 = 402, + EMOTE_ONESHOT_CUSTOMSPELL02 = 403, + EMOTE_ONESHOT_CUSTOMSPELL03 = 404, + EMOTE_ONESHOT_CUSTOMSPELL04 = 405, + EMOTE_ONESHOT_CUSTOMSPELL05 = 406, + EMOTE_ONESHOT_CUSTOMSPELL06 = 407, + EMOTE_ONESHOT_CUSTOMSPELL07 = 408, + EMOTE_ONESHOT_CUSTOMSPELL08 = 409, + EMOTE_ONESHOT_CUSTOMSPELL09 = 410, + EMOTE_ONESHOT_CUSTOMSPELL10 = 411, + EMOTE_STATE_EXCLAIM = 412, + EMOTE_STATE_DANCE_CUSTOM = 413, + EMOTE_STATE_SIT_CHAIR_MED = 415, + EMOTE_STATE_CUSTOM_SPELL_01 = 416, + EMOTE_STATE_CUSTOM_SPELL_02 = 417, + EMOTE_STATE_EAT = 418, + EMOTE_STATE_CUSTOM_SPELL_04 = 419, + EMOTE_STATE_CUSTOM_SPELL_03 = 420, + EMOTE_STATE_CUSTOM_SPELL_05 = 421, + EMOTE_STATE_SPELLEFFECT_HOLD = 422, + EMOTE_STATE_EAT_NO_SHEATHE = 423, + EMOTE_STATE_MOUNT = 424, + EMOTE_STATE_READY2HL = 425, + EMOTE_STATE_SIT_CHAIR_HIGH = 426, + EMOTE_STATE_FALL = 427, + EMOTE_STATE_LOOT = 428, + EMOTE_STATE_SUBMERGED_NEW = 429, + EMOTE_ONESHOT_COWER = 430, + EMOTE_STATE_COWER = 431, + EMOTE_ONESHOT_USESTANDING = 432, + EMOTE_STATE_STEALTH_STAND = 433, + EMOTE_ONESHOT_OMNICAST_GHOUL = 434, + EMOTE_ONESHOT_ATTACKBOW = 435, + EMOTE_ONESHOT_ATTACKRIFLE = 436, + EMOTE_STATE_SWIM_IDLE = 437, + EMOTE_STATE_ATTACK_UNARMED = 438, + EMOTE_ONESHOT_SPELLCAST_W_SOUND = 439, + EMOTE_ONESHOT_DODGE = 440, + EMOTE_ONESHOT_PARRY1H = 441, + EMOTE_ONESHOT_PARRY2H = 442, + EMOTE_ONESHOT_PARRY2HL = 443, + EMOTE_STATE_FLYFALL = 444, + EMOTE_ONESHOT_FLYDEATH = 445, + EMOTE_STATE_FLY_FALL = 446, + EMOTE_ONESHOT_FLY_SIT_GROUND_DOWN = 447, + EMOTE_ONESHOT_FLY_SIT_GROUND_UP = 448, + EMOTE_ONESHOT_EMERGE = 449, + EMOTE_ONESHOT_DRAGONSPIT = 450, + EMOTE_STATE_SPECIALUNARMED = 451, + EMOTE_ONESHOT_FLYGRAB = 452, + EMOTE_STATE_FLYGRABCLOSED = 453, + EMOTE_ONESHOT_FLYGRABTHROWN = 454, + EMOTE_STATE_FLY_SIT_GROUND = 455, + EMOTE_STATE_WALKBACKWARDS = 456, + EMOTE_ONESHOT_FLYTALK = 457, + EMOTE_ONESHOT_FLYATTACK1H = 458, + EMOTE_STATE_CUSTOMSPELL08 = 459, + EMOTE_ONESHOT_FLY_DRAGONSPIT = 460, + EMOTE_STATE_SIT_CHAIR_LOW = 461, + EMOTE_ONE_SHOT_STUN = 462, + EMOTE_ONESHOT_SPELLCAST_OMNI = 463, + EMOTE_STATE_READYTHROWN = 464 +}; + +enum Anim +{ + ANIM_STAND = 0x0, + ANIM_DEATH = 0x1, + ANIM_SPELL = 0x2, + ANIM_STOP = 0x3, + ANIM_WALK = 0x4, + ANIM_RUN = 0x5, + ANIM_DEAD = 0x6, + ANIM_RISE = 0x7, + ANIM_STANDWOUND = 0x8, + ANIM_COMBATWOUND = 0x9, + ANIM_COMBATCRITICAL = 0xA, + ANIM_SHUFFLE_LEFT = 0xB, + ANIM_SHUFFLE_RIGHT = 0xC, + ANIM_WALK_BACKWARDS = 0xD, + ANIM_STUN = 0xE, + ANIM_HANDS_CLOSED = 0xF, + ANIM_ATTACKUNARMED = 0x10, + ANIM_ATTACK1H = 0x11, + ANIM_ATTACK2HTIGHT = 0x12, + ANIM_ATTACK2HLOOSE = 0x13, + ANIM_PARRYUNARMED = 0x14, + ANIM_PARRY1H = 0x15, + ANIM_PARRY2HTIGHT = 0x16, + ANIM_PARRY2HLOOSE = 0x17, + ANIM_PARRYSHIELD = 0x18, + ANIM_READYUNARMED = 0x19, + ANIM_READY1H = 0x1A, + ANIM_READY2HTIGHT = 0x1B, + ANIM_READY2HLOOSE = 0x1C, + ANIM_READYBOW = 0x1D, + ANIM_DODGE = 0x1E, + ANIM_SPELLPRECAST = 0x1F, + ANIM_SPELLCAST = 0x20, + ANIM_SPELLCASTAREA = 0x21, + ANIM_NPCWELCOME = 0x22, + ANIM_NPCGOODBYE = 0x23, + ANIM_BLOCK = 0x24, + ANIM_JUMPSTART = 0x25, + ANIM_JUMP = 0x26, + ANIM_JUMPEND = 0x27, + ANIM_FALL = 0x28, + ANIM_SWIMIDLE = 0x29, + ANIM_SWIM = 0x2A, + ANIM_SWIM_LEFT = 0x2B, + ANIM_SWIM_RIGHT = 0x2C, + ANIM_SWIM_BACKWARDS = 0x2D, + ANIM_ATTACKBOW = 0x2E, + ANIM_FIREBOW = 0x2F, + ANIM_READYRIFLE = 0x30, + ANIM_ATTACKRIFLE = 0x31, + ANIM_LOOT = 0x32, + ANIM_SPELL_PRECAST_DIRECTED = 0x33, + ANIM_SPELL_PRECAST_OMNI = 0x34, + ANIM_SPELL_CAST_DIRECTED = 0x35, + ANIM_SPELL_CAST_OMNI = 0x36, + ANIM_SPELL_BATTLEROAR = 0x37, + ANIM_SPELL_READYABILITY = 0x38, + ANIM_SPELL_SPECIAL1H = 0x39, + ANIM_SPELL_SPECIAL2H = 0x3A, + ANIM_SPELL_SHIELDBASH = 0x3B, + ANIM_EMOTE_TALK = 0x3C, + ANIM_EMOTE_EAT = 0x3D, + ANIM_EMOTE_WORK = 0x3E, + ANIM_EMOTE_USE_STANDING = 0x3F, + ANIM_EMOTE_EXCLAMATION = 0x40, + ANIM_EMOTE_QUESTION = 0x41, + ANIM_EMOTE_BOW = 0x42, + ANIM_EMOTE_WAVE = 0x43, + ANIM_EMOTE_CHEER = 0x44, + ANIM_EMOTE_DANCE = 0x45, + ANIM_EMOTE_LAUGH = 0x46, + ANIM_EMOTE_SLEEP = 0x47, + ANIM_EMOTE_SIT_GROUND = 0x48, + ANIM_EMOTE_RUDE = 0x49, + ANIM_EMOTE_ROAR = 0x4A, + ANIM_EMOTE_KNEEL = 0x4B, + ANIM_EMOTE_KISS = 0x4C, + ANIM_EMOTE_CRY = 0x4D, + ANIM_EMOTE_CHICKEN = 0x4E, + ANIM_EMOTE_BEG = 0x4F, + ANIM_EMOTE_APPLAUD = 0x50, + ANIM_EMOTE_SHOUT = 0x51, + ANIM_EMOTE_FLEX = 0x52, + ANIM_EMOTE_SHY = 0x53, + ANIM_EMOTE_POINT = 0x54, + ANIM_ATTACK1HPIERCE = 0x55, + ANIM_ATTACK2HLOOSEPIERCE = 0x56, + ANIM_ATTACKOFF = 0x57, + ANIM_ATTACKOFFPIERCE = 0x58, + ANIM_SHEATHE = 0x59, + ANIM_HIPSHEATHE = 0x5A, + ANIM_MOUNT = 0x5B, + ANIM_RUN_LEANRIGHT = 0x5C, + ANIM_RUN_LEANLEFT = 0x5D, + ANIM_MOUNT_SPECIAL = 0x5E, + ANIM_KICK = 0x5F, + ANIM_SITDOWN = 0x60, + ANIM_SITTING = 0x61, + ANIM_SITUP = 0x62, + ANIM_SLEEPDOWN = 0x63, + ANIM_SLEEPING = 0x64, + ANIM_SLEEPUP = 0x65, + ANIM_SITCHAIRLOW = 0x66, + ANIM_SITCHAIRMEDIUM = 0x67, + ANIM_SITCHAIRHIGH = 0x68, + ANIM_LOADBOW = 0x69, + ANIM_LOADRIFLE = 0x6A, + ANIM_ATTACKTHROWN = 0x6B, + ANIM_READYTHROWN = 0x6C, + ANIM_HOLDBOW = 0x6D, + ANIM_HOLDRIFLE = 0x6E, + ANIM_HOLDTHROWN = 0x6F, + ANIM_LOADTHROWN = 0x70, + ANIM_EMOTE_SALUTE = 0x71, + ANIM_KNEELDOWN = 0x72, + ANIM_KNEELING = 0x73, + ANIM_KNEELUP = 0x74, + ANIM_ATTACKUNARMEDOFF = 0x75, + ANIM_SPECIALUNARMED = 0x76, + ANIM_STEALTHWALK = 0x77, + ANIM_STEALTHSTAND = 0x78, + ANIM_KNOCKDOWN = 0x79, + ANIM_EATING = 0x7A, + ANIM_USESTANDINGLOOP = 0x7B, + ANIM_CHANNELCASTDIRECTED = 0x7C, + ANIM_CHANNELCASTOMNI = 0x7D, + ANIM_WHIRLWIND = 0x7E, + ANIM_BIRTH = 0x7F, + ANIM_USESTANDINGSTART = 0x80, + ANIM_USESTANDINGEND = 0x81, + ANIM_HOWL = 0x82, + ANIM_DROWN = 0x83, + ANIM_DROWNED = 0x84, + ANIM_FISHINGCAST = 0x85, + ANIM_FISHINGLOOP = 0x86, + ANIM_FLY = 0x87, + ANIM_EMOTE_WORK_NO_SHEATHE = 0x88, + ANIM_EMOTE_STUN_NO_SHEATHE = 0x89, + ANIM_EMOTE_USE_STANDING_NO_SHEATHE= 0x8A, + ANIM_SPELL_SLEEP_DOWN = 0x8B, + ANIM_SPELL_KNEEL_START = 0x8C, + ANIM_SPELL_KNEEL_LOOP = 0x8D, + ANIM_SPELL_KNEEL_END = 0x8E, + ANIM_SPRINT = 0x8F, + ANIM_IN_FIGHT = 0x90, + + ANIM_GAMEOBJ_SPAWN = 145, + ANIM_GAMEOBJ_CLOSE = 146, + ANIM_GAMEOBJ_CLOSED = 147, + ANIM_GAMEOBJ_OPEN = 148, + ANIM_GAMEOBJ_OPENED = 149, + ANIM_GAMEOBJ_DESTROY = 150, + ANIM_GAMEOBJ_DESTROYED = 151, + ANIM_GAMEOBJ_REBUILD = 152, + ANIM_GAMEOBJ_CUSTOM0 = 153, + ANIM_GAMEOBJ_CUSTOM1 = 154, + ANIM_GAMEOBJ_CUSTOM2 = 155, + ANIM_GAMEOBJ_CUSTOM3 = 156, + ANIM_GAMEOBJ_DESPAWN = 157, + ANIM_HOLD = 158, + ANIM_DECAY = 159, + ANIM_BOWPULL = 160, + ANIM_BOWRELEASE = 161, + ANIM_SHIPSTART = 162, + ANIM_SHIPMOVEING = 163, + ANIM_SHIPSTOP = 164, + ANIM_GROUPARROW = 165, + ANIM_ARROW = 166, + ANIM_CORPSEARROW = 167, + ANIM_GUIDEARROW = 168, + ANIM_SWAY = 169, + ANIM_DRUIDCATPOUNCE = 170, + ANIM_DRUIDCATRIP = 171, + ANIM_DRUIDCATRAKE = 172, + ANIM_DRUIDCATRAVAGE = 173, + ANIM_DRUIDCATCLAW = 174, + ANIM_DRUIDCATCOWER = 175, + ANIM_DRUIDBEARSWIPE = 176, + ANIM_DRUIDBEARBITE = 177, + ANIM_DRUIDBEARMAUL = 178, + ANIM_DRUIDBEARBASH = 179, + ANIM_DRAGONTAIL = 180, + ANIM_DRAGONSTOMP = 181, + ANIM_DRAGONSPIT = 182, + ANIM_DRAGONSPITHOVER = 183, + ANIM_DRAGONSPITFLY = 184, + ANIM_EMOTEYES = 185, + ANIM_EMOTENO = 186, + ANIM_JUMPLANDRUN = 187, + ANIM_LOOTHOLD = 188, + ANIM_LOOTUP = 189, + ANIM_STANDHIGH = 190, + ANIM_IMPACT = 191, + ANIM_LIFTOFF = 192, + ANIM_HOVER = 193, + ANIM_SUCCUBUSENTICE = 194, + ANIM_EMOTETRAIN = 195, + ANIM_EMOTEDEAD = 196, + ANIM_EMOTEDANCEONCE = 197, + ANIM_DEFLECT = 198, + ANIM_EMOTEEATNOSHEATHE = 199, + ANIM_LAND = 200, + ANIM_SUBMERGE = 201, + ANIM_SUBMERGED = 202, + ANIM_CANNIBALIZE = 203, + ANIM_ARROWBIRTH = 204, + ANIM_GROURARROWBIRTH = 205, + ANIM_CORPSEARROWBIRTH = 206, + ANIM_GUIDEARROWBIRTH = 207, + ANIM_EMOTETALKNOSHEATHE = 208, + ANIM_EMOTEPOINTNOSHEATHE = 209, + ANIM_EMOTESALUTENOSHEATHE = 210, + ANIM_EMOTEDANCESPECIAL = 211, + ANIM_MUTILATE = 212, + ANIM_CUSTOMSPELL01 = 213, + ANIM_CUSTOMSPELL02 = 214, + ANIM_CUSTOMSPELL03 = 215, + ANIM_CUSTOMSPELL04 = 216, + ANIM_CUSTOMSPELL05 = 217, + ANIM_CUSTOMSPELL06 = 218, + ANIM_CUSTOMSPELL07 = 219, + ANIM_CUSTOMSPELL08 = 220, + ANIM_CUSTOMSPELL09 = 221, + ANIM_CUSTOMSPELL10 = 222, + ANIM_StealthRun = 223 +}; + +enum LockKeyType +{ + LOCK_KEY_NONE = 0, + LOCK_KEY_ITEM = 1, + LOCK_KEY_SKILL = 2 +}; + +enum LockType +{ + LOCKTYPE_PICKLOCK = 1, + LOCKTYPE_HERBALISM = 2, + LOCKTYPE_MINING = 3, + LOCKTYPE_DISARM_TRAP = 4, + LOCKTYPE_OPEN = 5, + LOCKTYPE_TREASURE = 6, + LOCKTYPE_CALCIFIED_ELVEN_GEMS = 7, + LOCKTYPE_CLOSE = 8, + LOCKTYPE_ARM_TRAP = 9, + LOCKTYPE_QUICK_OPEN = 10, + LOCKTYPE_QUICK_CLOSE = 11, + LOCKTYPE_OPEN_TINKERING = 12, + LOCKTYPE_OPEN_KNEELING = 13, + LOCKTYPE_OPEN_ATTACKING = 14, + LOCKTYPE_GAHZRIDIAN = 15, + LOCKTYPE_BLASTING = 16, + LOCKTYPE_SLOW_OPEN = 17, + LOCKTYPE_SLOW_CLOSE = 18, + LOCKTYPE_FISHING = 19, + LOCKTYPE_INSCRIPTION = 20, + LOCKTYPE_OPEN_FROM_VEHICLE = 21 +}; + +enum TrainerType // this is important type for npcs! +{ + TRAINER_TYPE_CLASS = 0, + TRAINER_TYPE_MOUNTS = 1, // on blizz it's 2 + TRAINER_TYPE_TRADESKILLS = 2, + TRAINER_TYPE_PETS = 3 +}; + +#define MAX_TRAINER_TYPE 4 + +// CreatureType.dbc +enum CreatureType +{ + CREATURE_TYPE_BEAST = 1, + CREATURE_TYPE_DRAGONKIN = 2, + CREATURE_TYPE_DEMON = 3, + CREATURE_TYPE_ELEMENTAL = 4, + CREATURE_TYPE_GIANT = 5, + CREATURE_TYPE_UNDEAD = 6, + CREATURE_TYPE_HUMANOID = 7, + CREATURE_TYPE_CRITTER = 8, + CREATURE_TYPE_MECHANICAL = 9, + CREATURE_TYPE_NOT_SPECIFIED = 10, + CREATURE_TYPE_TOTEM = 11, + CREATURE_TYPE_NON_COMBAT_PET = 12, + CREATURE_TYPE_GAS_CLOUD = 13 +}; + +uint32 const CREATURE_TYPEMASK_DEMON_OR_UNDEAD = (1 << (CREATURE_TYPE_DEMON-1)) | (1 << (CREATURE_TYPE_UNDEAD-1)); +uint32 const CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD = (1 << (CREATURE_TYPE_HUMANOID-1)) | (1 << (CREATURE_TYPE_UNDEAD-1)); +uint32 const CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL = (1 << (CREATURE_TYPE_MECHANICAL-1)) | (1 << (CREATURE_TYPE_ELEMENTAL-1)); + +// CreatureFamily.dbc +enum CreatureFamily +{ + CREATURE_FAMILY_WOLF = 1, + CREATURE_FAMILY_CAT = 2, + CREATURE_FAMILY_SPIDER = 3, + CREATURE_FAMILY_BEAR = 4, + CREATURE_FAMILY_BOAR = 5, + CREATURE_FAMILY_CROCOLISK = 6, + CREATURE_FAMILY_CARRION_BIRD = 7, + CREATURE_FAMILY_CRAB = 8, + CREATURE_FAMILY_GORILLA = 9, + CREATURE_FAMILY_HORSE_CUSTOM = 10, // not exist in DBC but used for horse like beasts in DB + CREATURE_FAMILY_RAPTOR = 11, + CREATURE_FAMILY_TALLSTRIDER = 12, + CREATURE_FAMILY_FELHUNTER = 15, + CREATURE_FAMILY_VOIDWALKER = 16, + CREATURE_FAMILY_SUCCUBUS = 17, + CREATURE_FAMILY_DOOMGUARD = 19, + CREATURE_FAMILY_SCORPID = 20, + CREATURE_FAMILY_TURTLE = 21, + CREATURE_FAMILY_IMP = 23, + CREATURE_FAMILY_BAT = 24, + CREATURE_FAMILY_HYENA = 25, + CREATURE_FAMILY_BIRD_OF_PREY = 26, + CREATURE_FAMILY_WIND_SERPENT = 27, + CREATURE_FAMILY_REMOTE_CONTROL = 28, + CREATURE_FAMILY_FELGUARD = 29, + CREATURE_FAMILY_DRAGONHAWK = 30, + CREATURE_FAMILY_RAVAGER = 31, + CREATURE_FAMILY_WARP_STALKER = 32, + CREATURE_FAMILY_SPOREBAT = 33, + CREATURE_FAMILY_NETHER_RAY = 34, + CREATURE_FAMILY_SERPENT = 35, + CREATURE_FAMILY_MOTH = 37, + CREATURE_FAMILY_CHIMAERA = 38, + CREATURE_FAMILY_DEVILSAUR = 39, + CREATURE_FAMILY_GHOUL = 40, + CREATURE_FAMILY_SILITHID = 41, + CREATURE_FAMILY_WORM = 42, + CREATURE_FAMILY_RHINO = 43, + CREATURE_FAMILY_WASP = 44, + CREATURE_FAMILY_CORE_HOUND = 45, + CREATURE_FAMILY_SPIRIT_BEAST = 46 +}; + +enum CreatureTypeFlags +{ + CREATURE_TYPEFLAGS_TAMEABLE = 0x000001, // Tameable by any hunter + CREATURE_TYPEFLAGS_GHOST = 0x000002, // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow? + CREATURE_TYPEFLAGS_UNK3 = 0x000004, + CREATURE_TYPEFLAGS_UNK4 = 0x000008, + CREATURE_TYPEFLAGS_UNK5 = 0x000010, + CREATURE_TYPEFLAGS_UNK6 = 0x000020, + CREATURE_TYPEFLAGS_UNK7 = 0x000040, + CREATURE_TYPEFLAGS_UNK8 = 0x000080, + CREATURE_TYPEFLAGS_HERBLOOT = 0x000100, // Can be looted by herbalist + CREATURE_TYPEFLAGS_MININGLOOT = 0x000200, // Can be looted by miner + CREATURE_TYPEFLAGS_UNK11 = 0x000400, + CREATURE_TYPEFLAGS_UNK12 = 0x000800, // ? Related to mounts in some way. If mounted, fight mounted, mount appear as independant when rider dies? + CREATURE_TYPEFLAGS_UNK13 = 0x001000, // ? Can aid any player in combat if in range? + CREATURE_TYPEFLAGS_UNK14 = 0x002000, + CREATURE_TYPEFLAGS_UNK15 = 0x004000, // ? Possibly not in use + CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x008000, // Can be looted by engineer + CREATURE_TYPEFLAGS_EXOTIC = 0x010000, // Can be tamed by hunter as exotic pet + CREATURE_TYPEFLAGS_UNK18 = 0x020000, // ? Related to vehicles/pvp? + CREATURE_TYPEFLAGS_UNK19 = 0x040000, // ? Related to vehicle/siege weapons? + CREATURE_TYPEFLAGS_UNK20 = 0x080000, + CREATURE_TYPEFLAGS_UNK21 = 0x100000, + CREATURE_TYPEFLAGS_UNK22 = 0x200000, + CREATURE_TYPEFLAGS_UNK23 = 0x400000, + CREATURE_TYPEFLAGS_UNK24 = 0x800000 // ? First seen in 3.2.2. Related to banner/backpack of creature/companion? +}; + +enum CreatureEliteType +{ + CREATURE_ELITE_NORMAL = 0, + CREATURE_ELITE_ELITE = 1, + CREATURE_ELITE_RAREELITE = 2, + CREATURE_ELITE_WORLDBOSS = 3, + CREATURE_ELITE_RARE = 4, + CREATURE_UNKNOWN = 5 // found in 2.2.3 for 2 mobs +}; + +// values based at Holidays.dbc +enum HolidayIds +{ + HOLIDAY_NONE = 0, + + HOLIDAY_FIREWORKS_SPECTACULAR = 62, + HOLIDAY_FEAST_OF_WINTER_VEIL = 141, + HOLIDAY_NOBLEGARDEN = 181, + HOLIDAY_CHILDRENS_WEEK = 201, + HOLIDAY_CALL_TO_ARMS_AV = 283, + HOLIDAY_CALL_TO_ARMS_WS = 284, + HOLIDAY_CALL_TO_ARMS_AB = 285, + HOLIDAY_FISHING_EXTRAVAGANZA = 301, + HOLIDAY_HARVEST_FESTIVAL = 321, + HOLIDAY_HALLOWS_END = 324, + HOLIDAY_LUNAR_FESTIVAL = 327, + HOLIDAY_LOVE_IS_IN_THE_AIR = 335, + HOLIDAY_FIRE_FESTIVAL = 341, + HOLIDAY_CALL_TO_ARMS_EY = 353, + HOLIDAY_BREWFEST = 372, + HOLIDAY_DARKMOON_FAIRE_ELWYNN = 374, + HOLIDAY_DARKMOON_FAIRE_THUNDER = 375, + HOLIDAY_DARKMOON_FAIRE_SHATTRATH = 376, + HOLIDAY_PIRATES_DAY = 398, + HOLIDAY_CALL_TO_ARMS_SA = 400, + HOLIDAY_PILGRIMS_BOUNTY = 404, + HOLIDAY_WOTLK_LAUNCH = 406, + HOLIDAY_DAY_OF_DEAD = 409, + HOLIDAY_CALL_TO_ARMS_ISLE_OF_C = 420 +}; + +// values based at QuestInfo.dbc +enum QuestTypes +{ + QUEST_TYPE_ELITE = 1, + QUEST_TYPE_LIFE = 21, + QUEST_TYPE_PVP = 41, + QUEST_TYPE_RAID = 62, + QUEST_TYPE_DUNGEON = 81, + QUEST_TYPE_WORLD_EVENT = 82, + QUEST_TYPE_LEGENDARY = 83, + QUEST_TYPE_ESCORT = 84, + QUEST_TYPE_HEROIC = 85, + QUEST_TYPE_RAID_10 = 88, + QUEST_TYPE_RAID_25 = 89 +}; + +// values based at QuestSort.dbc +enum QuestSort +{ + QUEST_SORT_EPIC = 1, + QUEST_SORT_WAILING_CAVERNS_OLD = 21, + QUEST_SORT_SEASONAL = 22, + QUEST_SORT_UNDERCITY_OLD = 23, + QUEST_SORT_HERBALISM = 24, + QUEST_SORT_BATTLEGROUNDS = 25, + QUEST_SORT_ULDAMN_OLD = 41, + QUEST_SORT_WARLOCK = 61, + QUEST_SORT_WARRIOR = 81, + QUEST_SORT_SHAMAN = 82, + QUEST_SORT_FISHING = 101, + QUEST_SORT_BLACKSMITHING = 121, + QUEST_SORT_PALADIN = 141, + QUEST_SORT_MAGE = 161, + QUEST_SORT_ROGUE = 162, + QUEST_SORT_ALCHEMY = 181, + QUEST_SORT_LEATHERWORKING = 182, + QUEST_SORT_ENGINERING = 201, + QUEST_SORT_TREASURE_MAP = 221, + QUEST_SORT_SUNKEN_TEMPLE_OLD = 241, + QUEST_SORT_HUNTER = 261, + QUEST_SORT_PRIEST = 262, + QUEST_SORT_DRUID = 263, + QUEST_SORT_TAILORING = 264, + QUEST_SORT_SPECIAL = 284, + QUEST_SORT_COOKING = 304, + QUEST_SORT_FIRST_AID = 324, + QUEST_SORT_LEGENDARY = 344, + QUEST_SORT_DARKMOON_FAIRE = 364, + QUEST_SORT_AHN_QIRAJ_WAR = 365, + QUEST_SORT_LUNAR_FESTIVAL = 366, + QUEST_SORT_REPUTATION = 367, + QUEST_SORT_INVASION = 368, + QUEST_SORT_MIDSUMMER = 369, + QUEST_SORT_BREWFEST = 370, + QUEST_SORT_INSCRIPTION = 371, + QUEST_SORT_DEATH_KNIGHT = 372, + QUEST_SORT_JEWELCRAFTING = 373 +}; + +inline uint8 ClassByQuestSort(int32 QuestSort) +{ + switch(QuestSort) + { + case QUEST_SORT_WARLOCK: return CLASS_WARLOCK; + case QUEST_SORT_WARRIOR: return CLASS_WARRIOR; + case QUEST_SORT_SHAMAN: return CLASS_SHAMAN; + case QUEST_SORT_PALADIN: return CLASS_PALADIN; + case QUEST_SORT_MAGE: return CLASS_MAGE; + case QUEST_SORT_ROGUE: return CLASS_ROGUE; + case QUEST_SORT_HUNTER: return CLASS_HUNTER; + case QUEST_SORT_PRIEST: return CLASS_PRIEST; + case QUEST_SORT_DRUID: return CLASS_DRUID; + case QUEST_SORT_DEATH_KNIGHT: return CLASS_DEATH_KNIGHT; + } + return 0; +} + +enum SkillType +{ + SKILL_NONE = 0, + + SKILL_FROST = 6, + SKILL_FIRE = 8, + SKILL_ARMS = 26, + SKILL_COMBAT = 38, + SKILL_SUBTLETY = 39, + SKILL_SWORDS = 43, + SKILL_AXES = 44, + SKILL_BOWS = 45, + SKILL_GUNS = 46, + SKILL_BEAST_MASTERY = 50, + SKILL_SURVIVAL = 51, + SKILL_MACES = 54, + SKILL_2H_SWORDS = 55, + SKILL_HOLY = 56, + SKILL_SHADOW = 78, + SKILL_DEFENSE = 95, + SKILL_LANG_COMMON = 98, + SKILL_RACIAL_DWARVEN = 101, + SKILL_LANG_ORCISH = 109, + SKILL_LANG_DWARVEN = 111, + SKILL_LANG_DARNASSIAN = 113, + SKILL_LANG_TAURAHE = 115, + SKILL_DUAL_WIELD = 118, + SKILL_RACIAL_TAUREN = 124, + SKILL_ORC_RACIAL = 125, + SKILL_RACIAL_NIGHT_ELF = 126, + SKILL_FIRST_AID = 129, + SKILL_FERAL_COMBAT = 134, + SKILL_STAVES = 136, + SKILL_LANG_THALASSIAN = 137, + SKILL_LANG_DRACONIC = 138, + SKILL_LANG_DEMON_TONGUE = 139, + SKILL_LANG_TITAN = 140, + SKILL_LANG_OLD_TONGUE = 141, + SKILL_SURVIVAL2 = 142, + SKILL_RIDING_HORSE = 148, + SKILL_RIDING_WOLF = 149, + SKILL_RIDING_RAM = 152, + SKILL_RIDING_TIGER = 150, + SKILL_SWIMING = 155, + SKILL_2H_MACES = 160, + SKILL_UNARMED = 162, + SKILL_MARKSMANSHIP = 163, + SKILL_BLACKSMITHING = 164, + SKILL_LEATHERWORKING = 165, + SKILL_ALCHEMY = 171, + SKILL_2H_AXES = 172, + SKILL_DAGGERS = 173, + SKILL_THROWN = 176, + SKILL_HERBALISM = 182, + SKILL_GENERIC_DND = 183, + SKILL_RETRIBUTION = 184, + SKILL_COOKING = 185, + SKILL_MINING = 186, + SKILL_PET_IMP = 188, + SKILL_PET_FELHUNTER = 189, + SKILL_TAILORING = 197, + SKILL_ENGINERING = 202, + SKILL_PET_SPIDER = 203, + SKILL_PET_VOIDWALKER = 204, + SKILL_PET_SUCCUBUS = 205, + SKILL_PET_INFERNAL = 206, + SKILL_PET_DOOMGUARD = 207, + SKILL_PET_WOLF = 208, + SKILL_PET_CAT = 209, + SKILL_PET_BEAR = 210, + SKILL_PET_BOAR = 211, + SKILL_PET_CROCILISK = 212, + SKILL_PET_CARRION_BIRD = 213, + SKILL_PET_CRAB = 214, + SKILL_PET_GORILLA = 215, + SKILL_PET_RAPTOR = 217, + SKILL_PET_TALLSTRIDER = 218, + SKILL_RACIAL_UNDED = 220, + SKILL_CROSSBOWS = 226, + SKILL_WANDS = 228, + SKILL_POLEARMS = 229, + SKILL_PET_SCORPID = 236, + SKILL_ARCANE = 237, + SKILL_PET_TURTLE = 251, + SKILL_ASSASSINATION = 253, + SKILL_FURY = 256, + SKILL_PROTECTION = 257, + SKILL_PROTECTION2 = 267, + SKILL_PET_TALENTS = 270, + SKILL_PLATE_MAIL = 293, + SKILL_LANG_GNOMISH = 313, + SKILL_LANG_TROLL = 315, + SKILL_ENCHANTING = 333, + SKILL_DEMONOLOGY = 354, + SKILL_AFFLICTION = 355, + SKILL_FISHING = 356, + SKILL_ENHANCEMENT = 373, + SKILL_RESTORATION = 374, + SKILL_ELEMENTAL_COMBAT = 375, + SKILL_SKINNING = 393, + SKILL_MAIL = 413, + SKILL_LEATHER = 414, + SKILL_CLOTH = 415, + SKILL_SHIELD = 433, + SKILL_FIST_WEAPONS = 473, + SKILL_RIDING_RAPTOR = 533, + SKILL_RIDING_MECHANOSTRIDER = 553, + SKILL_RIDING_UNDEAD_HORSE = 554, + SKILL_RESTORATION2 = 573, + SKILL_BALANCE = 574, + SKILL_DESTRUCTION = 593, + SKILL_HOLY2 = 594, + SKILL_DISCIPLINE = 613, + SKILL_LOCKPICKING = 633, + SKILL_PET_BAT = 653, + SKILL_PET_HYENA = 654, + SKILL_PET_BIRD_OF_PREY = 655, + SKILL_PET_WIND_SERPENT = 656, + SKILL_LANG_GUTTERSPEAK = 673, + SKILL_RIDING_KODO = 713, + SKILL_RACIAL_TROLL = 733, + SKILL_RACIAL_GNOME = 753, + SKILL_RACIAL_HUMAN = 754, + SKILL_JEWELCRAFTING = 755, + SKILL_RACIAL_BLOODELF = 756, + SKILL_PET_EVENT_RC = 758, + SKILL_LANG_DRAENEI = 759, + SKILL_RACIAL_DRAENEI = 760, + SKILL_PET_FELGUARD = 761, + SKILL_RIDING = 762, + SKILL_PET_DRAGONHAWK = 763, + SKILL_PET_NETHER_RAY = 764, + SKILL_PET_SPOREBAT = 765, + SKILL_PET_WARP_STALKER = 766, + SKILL_PET_RAVAGER = 767, + SKILL_PET_SERPENT = 768, + SKILL_INTERNAL = 769, + SKILL_DK_BLOOD = 770, + SKILL_DK_FROST = 771, + SKILL_DK_UNHOLY = 772, + SKILL_INSCRIPTION = 773, + SKILL_PET_MOTH = 775, + SKILL_RUNEFORGING = 776, + SKILL_MOUNTS = 777, + SKILL_COMPANIONS = 778, + SKILL_PET_EXOTIC_CHIMAERA = 780, + SKILL_PET_EXOTIC_DEVILSAUR = 781, + SKILL_PET_GHOUL = 782, + SKILL_PET_EXOTIC_SILITHID = 783, + SKILL_PET_EXOTIC_WORM = 784, + SKILL_PET_WASP = 785, + SKILL_PET_EXOTIC_RHINO = 786, + SKILL_PET_EXOTIC_CORE_HOUND = 787, + SKILL_PET_EXOTIC_SPIRIT_BEAST = 788 +}; + +#define MAX_SKILL_TYPE 789 + +inline SkillType SkillByLockType(LockType locktype) +{ + switch(locktype) + { + case LOCKTYPE_PICKLOCK: return SKILL_LOCKPICKING; + case LOCKTYPE_HERBALISM: return SKILL_HERBALISM; + case LOCKTYPE_MINING: return SKILL_MINING; + case LOCKTYPE_FISHING: return SKILL_FISHING; + case LOCKTYPE_INSCRIPTION: return SKILL_INSCRIPTION; + default: break; + } + return SKILL_NONE; +} + +inline uint32 SkillByQuestSort(int32 QuestSort) +{ + switch(QuestSort) + { + case QUEST_SORT_HERBALISM: return SKILL_HERBALISM; + case QUEST_SORT_FISHING: return SKILL_FISHING; + case QUEST_SORT_BLACKSMITHING: return SKILL_BLACKSMITHING; + case QUEST_SORT_ALCHEMY: return SKILL_ALCHEMY; + case QUEST_SORT_LEATHERWORKING: return SKILL_LEATHERWORKING; + case QUEST_SORT_ENGINERING: return SKILL_ENGINERING; + case QUEST_SORT_TAILORING: return SKILL_TAILORING; + case QUEST_SORT_COOKING: return SKILL_COOKING; + case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID; + case QUEST_SORT_JEWELCRAFTING: return SKILL_JEWELCRAFTING; + case QUEST_SORT_INSCRIPTION: return SKILL_INSCRIPTION; + } + return 0; +} + +enum SkillCategory +{ + SKILL_CATEGORY_ATTRIBUTES = 5, + SKILL_CATEGORY_WEAPON = 6, + SKILL_CATEGORY_CLASS = 7, + SKILL_CATEGORY_ARMOR = 8, + SKILL_CATEGORY_SECONDARY = 9, // secondary professions + SKILL_CATEGORY_LANGUAGES = 10, + SKILL_CATEGORY_PROFESSION = 11, // primary professions + SKILL_CATEGORY_GENERIC = 12 +}; + +enum TotemCategory +{ + TC_SKINNING_SKIFE_OLD = 1, + TC_EARTH_TOTEM = 2, + TC_AIR_TOTEM = 3, + TC_FIRE_TOTEM = 4, + TC_WATER_TOTEM = 5, + TC_COPPER_ROD = 6, + TC_SILVER_ROD = 7, + TC_GOLDEN_ROD = 8, + TC_TRUESILVER_ROD = 9, + TC_ARCANITE_ROD = 10, + TC_MINING_PICK_OLD = 11, + TC_PHILOSOPHERS_STONE = 12, + TC_BLACKSMITH_HAMMER_OLD = 13, + TC_ARCLIGHT_SPANNER = 14, + TC_GYROMATIC_MA = 15, + TC_MASTER_TOTEM = 21, + TC_FEL_IRON_ROD = 41, + TC_ADAMANTITE_ROD = 62, + TC_ETERNIUM_ROD = 63, + TC_HOLLOW_QUILL = 81, + TC_RUNED_AZURITE_ROD = 101, + TC_VIRTUOSO_INKING_SET = 121, + TC_DRUMS = 141, + TC_GNOMISH_ARMY_KNIFE = 161, + TC_BLACKSMITH_HAMMER = 162, + TC_MINING_PICK = 165, + TC_SKINNING_KNIFE = 166, + TC_HAMMER_PICK = 167, + TC_BLADED_PICKAXE = 168, + TC_FLINT_AND_TINDER = 169, + TC_RUNED_COBALT_ROD = 189, + TC_RUNED_TITANIUM_ROD = 190 +}; + +enum UnitDynFlags +{ + UNIT_DYNFLAG_NONE = 0x0000, + UNIT_DYNFLAG_LOOTABLE = 0x0001, + UNIT_DYNFLAG_TRACK_UNIT = 0x0002, + UNIT_DYNFLAG_TAPPED = 0x0004, // Lua_UnitIsTapped + UNIT_DYNFLAG_TAPPED_BY_PLAYER = 0x0008, // Lua_UnitIsTappedByPlayer + UNIT_DYNFLAG_SPECIALINFO = 0x0010, + UNIT_DYNFLAG_DEAD = 0x0020, + UNIT_DYNFLAG_REFER_A_FRIEND = 0x0040, + UNIT_DYNFLAG_TAPPED_BY_ALL_THREAT_LIST = 0x0080 // Lua_UnitIsTappedByAllThreatList +}; + +enum CorpseDynFlags +{ + CORPSE_DYNFLAG_LOOTABLE = 0x0001 +}; + +enum WeatherType +{ + WEATHER_TYPE_FINE = 0, + WEATHER_TYPE_RAIN = 1, + WEATHER_TYPE_SNOW = 2, + WEATHER_TYPE_STORM = 3, + WEATHER_TYPE_THUNDERS = 86, + WEATHER_TYPE_BLACKRAIN = 90 +}; + +#define MAX_WEATHER_TYPE 4 + +enum ChatMsg +{ + CHAT_MSG_ADDON = 0xFFFFFFFF, + CHAT_MSG_SYSTEM = 0x00, + CHAT_MSG_SAY = 0x01, + CHAT_MSG_PARTY = 0x02, + CHAT_MSG_RAID = 0x03, + CHAT_MSG_GUILD = 0x04, + CHAT_MSG_OFFICER = 0x05, + CHAT_MSG_YELL = 0x06, + CHAT_MSG_WHISPER = 0x07, + CHAT_MSG_WHISPER_FOREIGN = 0x08, + CHAT_MSG_WHISPER_INFORM = 0x09, + CHAT_MSG_EMOTE = 0x0A, + CHAT_MSG_TEXT_EMOTE = 0x0B, + CHAT_MSG_MONSTER_SAY = 0x0C, + CHAT_MSG_MONSTER_PARTY = 0x0D, + CHAT_MSG_MONSTER_YELL = 0x0E, + CHAT_MSG_MONSTER_WHISPER = 0x0F, + CHAT_MSG_MONSTER_EMOTE = 0x10, + CHAT_MSG_CHANNEL = 0x11, + CHAT_MSG_CHANNEL_JOIN = 0x12, + CHAT_MSG_CHANNEL_LEAVE = 0x13, + CHAT_MSG_CHANNEL_LIST = 0x14, + CHAT_MSG_CHANNEL_NOTICE = 0x15, + CHAT_MSG_CHANNEL_NOTICE_USER = 0x16, + CHAT_MSG_AFK = 0x17, + CHAT_MSG_DND = 0x18, + CHAT_MSG_IGNORED = 0x19, + CHAT_MSG_SKILL = 0x1A, + CHAT_MSG_LOOT = 0x1B, + CHAT_MSG_MONEY = 0x1C, + CHAT_MSG_OPENING = 0x1D, + CHAT_MSG_TRADESKILLS = 0x1E, + CHAT_MSG_PET_INFO = 0x1F, + CHAT_MSG_COMBAT_MISC_INFO = 0x20, + CHAT_MSG_COMBAT_XP_GAIN = 0x21, + CHAT_MSG_COMBAT_HONOR_GAIN = 0x22, + CHAT_MSG_COMBAT_FACTION_CHANGE = 0x23, + CHAT_MSG_BG_SYSTEM_NEUTRAL = 0x24, + CHAT_MSG_BG_SYSTEM_ALLIANCE = 0x25, + CHAT_MSG_BG_SYSTEM_HORDE = 0x26, + CHAT_MSG_RAID_LEADER = 0x27, + CHAT_MSG_RAID_WARNING = 0x28, + CHAT_MSG_RAID_BOSS_EMOTE = 0x29, + CHAT_MSG_RAID_BOSS_WHISPER = 0x2A, + CHAT_MSG_FILTERED = 0x2B, + CHAT_MSG_BATTLEGROUND = 0x2C, + CHAT_MSG_BATTLEGROUND_LEADER = 0x2D, + CHAT_MSG_RESTRICTED = 0x2E, + CHAT_MSG_BATTLENET = 0x2F, + CHAT_MSG_ACHIEVEMENT = 0x30, + CHAT_MSG_GUILD_ACHIEVEMENT = 0x31, + CHAT_MSG_ARENA_POINTS = 0x32, + CHAT_MSG_PARTY_LEADER = 0x33 +}; + +#define MAX_CHAT_MSG_TYPE 0x34 + +enum ChatLinkColors +{ + CHAT_LINK_COLOR_TRADE = 0xffffd000, // orange + CHAT_LINK_COLOR_TALENT = 0xff4e96f7, // blue + CHAT_LINK_COLOR_SPELL = 0xff71d5ff, // bright blue + CHAT_LINK_COLOR_ENCHANT = 0xffffd000, // orange + CHAT_LINK_COLOR_ACHIEVEMENT = 0xffffff00, + CHAT_LINK_COLOR_GLYPH = 0xff66bbff +}; + +// Values from ItemPetFood (power of (value-1) used for compare with CreatureFamilyEntry.petDietMask +enum PetDiet +{ + PET_DIET_MEAT = 1, + PET_DIET_FISH = 2, + PET_DIET_CHEESE = 3, + PET_DIET_BREAD = 4, + PET_DIET_FUNGAS = 5, + PET_DIET_FRUIT = 6, + PET_DIET_RAW_MEAT = 7, + PET_DIET_RAW_FISH = 8 +}; + +#define MAX_PET_DIET 9 + +#define CHAIN_SPELL_JUMP_RADIUS 10 + +// Max values for Guild & Guild Bank +#define GUILD_BANK_MAX_TABS 6 // send by client for money log also +#define GUILD_BANK_MAX_SLOTS 98 +#define GUILD_BANK_MAX_LOGS 25 +#define GUILD_BANK_MONEY_LOGS_TAB 100 // used for money log in DB +#define GUILD_EVENTLOG_MAX_RECORDS 100 +#define GUILD_RANKS_MIN_COUNT 5 +#define GUILD_RANKS_MAX_COUNT 10 + +enum AiReaction +{ + AI_REACTION_ALERT = 0, // pre-aggro (used in client packet handler) + AI_REACTION_FRIENDLY = 1, // (NOT used in client packet handler) + AI_REACTION_HOSTILE = 2, // sent on every attack, triggers aggro sound (used in client packet handler) + AI_REACTION_AFRAID = 3, // seen for polymorph (when AI not in control of self?) (NOT used in client packet handler) + AI_REACTION_DESTROY = 4, // used on object destroy (NOT used in client packet handler) +}; + +// Diminishing Returns Types +enum DiminishingReturnsType +{ + DRTYPE_NONE = 0, // this spell is not diminished, but may have limited it's duration to 10s + DRTYPE_PLAYER = 1, // this spell is diminished only when applied on players + DRTYPE_ALL = 2 // this spell is diminished in every case +}; + +// Diminishing Return Groups +enum DiminishingGroup +{ + // Common Groups + DIMINISHING_NONE = 0, + DIMINISHING_CONTROL_STUN, // Player Controlled stuns + DIMINISHING_TRIGGER_STUN, // By aura proced stuns, usualy chance on hit talents + DIMINISHING_CONTROL_ROOT, // Immobilizing effects from casted spells + DIMINISHING_TRIGGER_ROOT, // Immobilizing effects from triggered spells like Frostbite + DIMINISHING_CHARM, + DIMINISHING_POLYMORPH, // Also: Gouge, Sap, Repentance, Hungering Cold + DIMINISHING_KNOCKOUT, // Sap, Knockout mechanics + DIMINISHING_FEAR_BLIND, // Intimidating Shout, Howl of Terror, Blind + // Warlock Specific + DIMINISHING_DEATHCOIL, // Death Coil Diminish only with another Death Coil + // Druid Specific + DIMINISHING_CYCLONE, // From 2.3.0 + // Shared Class Specific + DIMINISHING_CHEAPSHOT_POUNCE, + DIMINISHING_DISARM, // From 2.3.0 + DIMINISHING_SILENCE, // From 2.3.0 + DIMINISHING_FREEZE_SLEEP, // Hunter's Freezing Trap + DIMINISHING_BANISH, + DIMINISHING_TAUNT, + DIMINISHING_LIMITONLY // Don't Diminish, but limit duration to 10s +}; + +enum SummonCategory +{ + SUMMON_CATEGORY_WILD = 0, + SUMMON_CATEGORY_ALLY = 1, + SUMMON_CATEGORY_PET = 2, + SUMMON_CATEGORY_PUPPET = 3, + SUMMON_CATEGORY_VEHICLE = 4, +}; + +enum SummonType +{ + SUMMON_TYPE_NONE = 0, + SUMMON_TYPE_PET = 1, + SUMMON_TYPE_GUARDIAN = 2, + SUMMON_TYPE_MINION = 3, + SUMMON_TYPE_TOTEM = 4, + SUMMON_TYPE_MINIPET = 5, + SUMMON_TYPE_GUARDIAN2 = 6, + SUMMON_TYPE_WILD2 = 7, + SUMMON_TYPE_WILD3 = 8, + SUMMON_TYPE_VEHICLE = 9, + SUMMON_TYPE_VEHICLE2 = 10, + SUMMON_TYPE_OBJECT = 11, +}; + +enum EventId +{ + EVENT_SPELLCLICK = 1001, + EVENT_FALL_GROUND = 1002, + EVENT_CHARGE = 1003, +}; + +enum ResponseCodes +{ + RESPONSE_SUCCESS = 0x00, + RESPONSE_FAILURE = 0x01, + RESPONSE_CANCELLED = 0x02, + RESPONSE_DISCONNECTED = 0x03, + RESPONSE_FAILED_TO_CONNECT = 0x04, + RESPONSE_CONNECTED = 0x05, + RESPONSE_VERSION_MISMATCH = 0x06, + + CSTATUS_CONNECTING = 0x07, + CSTATUS_NEGOTIATING_SECURITY = 0x08, + CSTATUS_NEGOTIATION_COMPLETE = 0x09, + CSTATUS_NEGOTIATION_FAILED = 0x0A, + CSTATUS_AUTHENTICATING = 0x0B, + + AUTH_OK = 0x0C, + AUTH_FAILED = 0x0D, + AUTH_REJECT = 0x0E, + AUTH_BAD_SERVER_PROOF = 0x0F, + AUTH_UNAVAILABLE = 0x10, + AUTH_SYSTEM_ERROR = 0x11, + AUTH_BILLING_ERROR = 0x12, + AUTH_BILLING_EXPIRED = 0x13, + AUTH_VERSION_MISMATCH = 0x14, + AUTH_UNKNOWN_ACCOUNT = 0x15, + AUTH_INCORRECT_PASSWORD = 0x16, + AUTH_SESSION_EXPIRED = 0x17, + AUTH_SERVER_SHUTTING_DOWN = 0x18, + AUTH_ALREADY_LOGGING_IN = 0x19, + AUTH_LOGIN_SERVER_NOT_FOUND = 0x1A, + AUTH_WAIT_QUEUE = 0x1B, + AUTH_BANNED = 0x1C, + AUTH_ALREADY_ONLINE = 0x1D, + AUTH_NO_TIME = 0x1E, + AUTH_DB_BUSY = 0x1F, + AUTH_SUSPENDED = 0x20, + AUTH_PARENTAL_CONTROL = 0x21, + AUTH_LOCKED_ENFORCED = 0x22, + + REALM_LIST_IN_PROGRESS = 0x23, + REALM_LIST_SUCCESS = 0x24, + REALM_LIST_FAILED = 0x25, + REALM_LIST_INVALID = 0x26, + REALM_LIST_REALM_NOT_FOUND = 0x27, + + ACCOUNT_CREATE_IN_PROGRESS = 0x28, + ACCOUNT_CREATE_SUCCESS = 0x29, + ACCOUNT_CREATE_FAILED = 0x2A, + + CHAR_LIST_RETRIEVING = 0x2B, + CHAR_LIST_RETRIEVED = 0x2C, + CHAR_LIST_FAILED = 0x2D, + + CHAR_CREATE_IN_PROGRESS = 0x2E, + CHAR_CREATE_SUCCESS = 0x2F, + CHAR_CREATE_ERROR = 0x30, + CHAR_CREATE_FAILED = 0x31, + CHAR_CREATE_NAME_IN_USE = 0x32, + CHAR_CREATE_DISABLED = 0x33, + CHAR_CREATE_PVP_TEAMS_VIOLATION = 0x34, + CHAR_CREATE_SERVER_LIMIT = 0x35, + CHAR_CREATE_ACCOUNT_LIMIT = 0x36, + CHAR_CREATE_SERVER_QUEUE = 0x37, + CHAR_CREATE_ONLY_EXISTING = 0x38, + CHAR_CREATE_EXPANSION = 0x39, + CHAR_CREATE_EXPANSION_CLASS = 0x3A, + CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B, + CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C, + CHAR_CREATE_CHARACTER_IN_GUILD = 0x3D, + CHAR_CREATE_RESTRICTED_RACECLASS = 0x3E, + CHAR_CREATE_CHARACTER_CHOOSE_RACE = 0x3F, + CHAR_CREATE_CHARACTER_ARENA_LEADER = 0x40, + CHAR_CREATE_CHARACTER_DELETE_MAIL = 0x41, + CHAR_CREATE_CHARACTER_SWAP_FACTION = 0x42, + CHAR_CREATE_CHARACTER_RACE_ONLY = 0x43, + + CHAR_CREATE_CHARACTER_GOLD_LIMIT = 0x44, + + CHAR_CREATE_FORCE_LOGIN = 0x45, + + CHAR_DELETE_IN_PROGRESS = 0x46, + CHAR_DELETE_SUCCESS = 0x47, + CHAR_DELETE_FAILED = 0x48, + CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x49, + CHAR_DELETE_FAILED_GUILD_LEADER = 0x4A, + CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x4B, + + CHAR_LOGIN_IN_PROGRESS = 0x4C, + CHAR_LOGIN_SUCCESS = 0x4D, + CHAR_LOGIN_NO_WORLD = 0x4E, + CHAR_LOGIN_DUPLICATE_CHARACTER = 0x4F, + CHAR_LOGIN_NO_INSTANCES = 0x50, + CHAR_LOGIN_FAILED = 0x51, + CHAR_LOGIN_DISABLED = 0x52, + CHAR_LOGIN_NO_CHARACTER = 0x53, + CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x54, + CHAR_LOGIN_LOCKED_BY_BILLING = 0x55, + CHAR_LOGIN_LOCKED_BY_MOBILE_AH = 0x56, + + CHAR_NAME_SUCCESS = 0x57, + CHAR_NAME_FAILURE = 0x58, + CHAR_NAME_NO_NAME = 0x59, + CHAR_NAME_TOO_SHORT = 0x5A, + CHAR_NAME_TOO_LONG = 0x5B, + CHAR_NAME_INVALID_CHARACTER = 0x5C, + CHAR_NAME_MIXED_LANGUAGES = 0x5D, + CHAR_NAME_PROFANE = 0x5E, + CHAR_NAME_RESERVED = 0x5F, + CHAR_NAME_INVALID_APOSTROPHE = 0x60, + CHAR_NAME_MULTIPLE_APOSTROPHES = 0x61, + CHAR_NAME_THREE_CONSECUTIVE = 0x62, + CHAR_NAME_INVALID_SPACE = 0x63, + CHAR_NAME_CONSECUTIVE_SPACES = 0x64, + CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x65, + CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x66, + CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x67 +}; + +/// Ban function modes +enum BanMode +{ + BAN_ACCOUNT, + BAN_CHARACTER, + BAN_IP +}; + +/// Ban function return codes +enum BanReturn +{ + BAN_SUCCESS, + BAN_SYNTAX_ERROR, + BAN_NOTFOUND +}; + +// indexes of BattlemasterList.dbc +enum BattleGroundTypeId +{ + BATTLEGROUND_TYPE_NONE = 0, + BATTLEGROUND_AV = 1, + BATTLEGROUND_WS = 2, + BATTLEGROUND_AB = 3, + BATTLEGROUND_NA = 4, + BATTLEGROUND_BE = 5, + BATTLEGROUND_AA = 6, + BATTLEGROUND_EY = 7, + BATTLEGROUND_RL = 8, + BATTLEGROUND_SA = 9, + BATTLEGROUND_DS = 10, + BATTLEGROUND_RV = 11, + BATTLEGROUND_IC = 30, + BATTLEGROUND_RB = 32 +}; + +#define MAX_BATTLEGROUND_TYPE_ID 33 + +enum MailResponseType +{ + MAIL_SEND = 0, + MAIL_MONEY_TAKEN = 1, + MAIL_ITEM_TAKEN = 2, + MAIL_RETURNED_TO_SENDER = 3, + MAIL_DELETED = 4, + MAIL_MADE_PERMANENT = 5 +}; + +enum MailResponseResult +{ + MAIL_OK = 0, + MAIL_ERR_EQUIP_ERROR = 1, + MAIL_ERR_CANNOT_SEND_TO_SELF = 2, + MAIL_ERR_NOT_ENOUGH_MONEY = 3, + MAIL_ERR_RECIPIENT_NOT_FOUND = 4, + MAIL_ERR_NOT_YOUR_TEAM = 5, + MAIL_ERR_INTERNAL_ERROR = 6, + MAIL_ERR_DISABLED_FOR_TRIAL_ACC = 14, + MAIL_ERR_RECIPIENT_CAP_REACHED = 15, + MAIL_ERR_CANT_SEND_WRAPPED_COD = 16, + MAIL_ERR_MAIL_AND_CHAT_SUSPENDED = 17, + MAIL_ERR_TOO_MANY_ATTACHMENTS = 18, + MAIL_ERR_MAIL_ATTACHMENT_INVALID = 19, + MAIL_ERR_ITEM_HAS_EXPIRED = 21, +}; + +enum SpellFamilyNames +{ + SPELLFAMILY_GENERIC = 0, + SPELLFAMILY_UNK1 = 1, // events, holidays + // 2 - unused + SPELLFAMILY_MAGE = 3, + SPELLFAMILY_WARRIOR = 4, + SPELLFAMILY_WARLOCK = 5, + SPELLFAMILY_PRIEST = 6, + SPELLFAMILY_DRUID = 7, + SPELLFAMILY_ROGUE = 8, + SPELLFAMILY_HUNTER = 9, + SPELLFAMILY_PALADIN = 10, + SPELLFAMILY_SHAMAN = 11, + SPELLFAMILY_UNK2 = 12, // 2 spells (silence resistance) + SPELLFAMILY_POTION = 13, + // 14 - unused + SPELLFAMILY_DEATHKNIGHT = 15, + // 16 - unused + SPELLFAMILY_PET = 17 +}; + +#endif diff --git a/src/server/game/Movement/MovementGenerator.cpp b/src/server/game/Movement/MovementGenerator.cpp new file mode 100644 index 00000000000..2cccf8a76dc --- /dev/null +++ b/src/server/game/Movement/MovementGenerator.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MovementGenerator.h" + +MovementGenerator::~MovementGenerator() +{ +} + + diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h new file mode 100644 index 00000000000..ab7a52c483e --- /dev/null +++ b/src/server/game/Movement/MovementGenerator.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_MOVEMENTGENERATOR_H +#define TRINITY_MOVEMENTGENERATOR_H + +#include "Platform/Define.h" +#include "Policies/Singleton.h" +#include "Dynamic/ObjectRegistry.h" +#include "Dynamic/FactoryHolder.h" +#include "Common.h" +#include "MotionMaster.h" + +class Unit; + +class MovementGenerator +{ + public: + virtual ~MovementGenerator(); + + virtual void Initialize(Unit &) = 0; + virtual void Finalize(Unit &) = 0; + + virtual void Reset(Unit &) = 0; + + virtual bool Update(Unit &, const uint32 &time_diff) = 0; + + virtual MovementGeneratorType GetMovementGeneratorType() = 0; + + virtual void unitSpeedChanged() { } + + virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } +}; + +template +class MovementGeneratorMedium : public MovementGenerator +{ + public: + void Initialize(Unit &u) + { + //u->AssertIsType(); + (static_cast(this))->Initialize(*((T*)&u)); + } + void Finalize(Unit &u) + { + //u->AssertIsType(); + (static_cast(this))->Finalize(*((T*)&u)); + } + void Reset(Unit &u) + { + //u->AssertIsType(); + (static_cast(this))->Reset(*((T*)&u)); + } + bool Update(Unit &u, const uint32 &time_diff) + { + //u->AssertIsType(); + return (static_cast(this))->Update(*((T*)&u), time_diff); + } + public: + // will not link if not overridden in the generators + void Initialize(T &u); + void Finalize(T &u); + void Reset(T &u); + bool Update(T &u, const uint32 &time_diff); +}; + +struct SelectableMovement : public FactoryHolder +{ + SelectableMovement(MovementGeneratorType mgt) : FactoryHolder(mgt) {} +}; + +template +struct MovementGeneratorFactory : public SelectableMovement +{ + MovementGeneratorFactory(MovementGeneratorType mgt) : SelectableMovement(mgt) {} + + MovementGenerator* Create(void *) const; +}; + +typedef FactoryHolder MovementGeneratorCreator; +typedef FactoryHolder::FactoryHolderRegistry MovementGeneratorRegistry; +typedef FactoryHolder::FactoryHolderRepository MovementGeneratorRepository; +#endif + + diff --git a/src/server/game/Movement/MovementGeneratorImpl.h b/src/server/game/Movement/MovementGeneratorImpl.h new file mode 100644 index 00000000000..d2778a5bff8 --- /dev/null +++ b/src/server/game/Movement/MovementGeneratorImpl.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_MOVEMENTGENERATOR_IMPL_H +#define TRINITY_MOVEMENTGENERATOR_IMPL_H + +#include "MovementGenerator.h" + +template +inline MovementGenerator* +MovementGeneratorFactory::Create(void * /*data*/) const +{ + return (new MOVEMENT_GEN()); +} +#endif + + diff --git a/src/server/game/Movement/MovementGenerators/MovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/MovementGenerator.cpp deleted file mode 100644 index 2cccf8a76dc..00000000000 --- a/src/server/game/Movement/MovementGenerators/MovementGenerator.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "MovementGenerator.h" - -MovementGenerator::~MovementGenerator() -{ -} - - diff --git a/src/server/game/Movement/MovementGenerators/MovementGenerator.h b/src/server/game/Movement/MovementGenerators/MovementGenerator.h deleted file mode 100644 index ab7a52c483e..00000000000 --- a/src/server/game/Movement/MovementGenerators/MovementGenerator.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_MOVEMENTGENERATOR_H -#define TRINITY_MOVEMENTGENERATOR_H - -#include "Platform/Define.h" -#include "Policies/Singleton.h" -#include "Dynamic/ObjectRegistry.h" -#include "Dynamic/FactoryHolder.h" -#include "Common.h" -#include "MotionMaster.h" - -class Unit; - -class MovementGenerator -{ - public: - virtual ~MovementGenerator(); - - virtual void Initialize(Unit &) = 0; - virtual void Finalize(Unit &) = 0; - - virtual void Reset(Unit &) = 0; - - virtual bool Update(Unit &, const uint32 &time_diff) = 0; - - virtual MovementGeneratorType GetMovementGeneratorType() = 0; - - virtual void unitSpeedChanged() { } - - virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } -}; - -template -class MovementGeneratorMedium : public MovementGenerator -{ - public: - void Initialize(Unit &u) - { - //u->AssertIsType(); - (static_cast(this))->Initialize(*((T*)&u)); - } - void Finalize(Unit &u) - { - //u->AssertIsType(); - (static_cast(this))->Finalize(*((T*)&u)); - } - void Reset(Unit &u) - { - //u->AssertIsType(); - (static_cast(this))->Reset(*((T*)&u)); - } - bool Update(Unit &u, const uint32 &time_diff) - { - //u->AssertIsType(); - return (static_cast(this))->Update(*((T*)&u), time_diff); - } - public: - // will not link if not overridden in the generators - void Initialize(T &u); - void Finalize(T &u); - void Reset(T &u); - bool Update(T &u, const uint32 &time_diff); -}; - -struct SelectableMovement : public FactoryHolder -{ - SelectableMovement(MovementGeneratorType mgt) : FactoryHolder(mgt) {} -}; - -template -struct MovementGeneratorFactory : public SelectableMovement -{ - MovementGeneratorFactory(MovementGeneratorType mgt) : SelectableMovement(mgt) {} - - MovementGenerator* Create(void *) const; -}; - -typedef FactoryHolder MovementGeneratorCreator; -typedef FactoryHolder::FactoryHolderRegistry MovementGeneratorRegistry; -typedef FactoryHolder::FactoryHolderRepository MovementGeneratorRepository; -#endif - - diff --git a/src/server/game/Movement/MovementGenerators/MovementGeneratorImpl.h b/src/server/game/Movement/MovementGenerators/MovementGeneratorImpl.h deleted file mode 100644 index d2778a5bff8..00000000000 --- a/src/server/game/Movement/MovementGenerators/MovementGeneratorImpl.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_MOVEMENTGENERATOR_IMPL_H -#define TRINITY_MOVEMENTGENERATOR_IMPL_H - -#include "MovementGenerator.h" - -template -inline MovementGenerator* -MovementGeneratorFactory::Create(void * /*data*/) const -{ - return (new MOVEMENT_GEN()); -} -#endif - - diff --git a/src/server/game/Movement/MovementHandler.cpp b/src/server/game/Movement/MovementHandler.cpp deleted file mode 100644 index 1148fe174fc..00000000000 --- a/src/server/game/Movement/MovementHandler.cpp +++ /dev/null @@ -1,746 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "Corpse.h" -#include "Player.h" -#include "Vehicle.h" -#include "SpellAuras.h" -#include "MapManager.h" -#include "Transports.h" -#include "BattleGround.h" -#include "WaypointMovementGenerator.h" -#include "InstanceSaveMgr.h" -#include "ObjectMgr.h" - -void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: got MSG_MOVE_WORLDPORT_ACK."); - HandleMoveWorldportAckOpcode(); -} - -void WorldSession::HandleMoveWorldportAckOpcode() -{ - // ignore unexpected far teleports - if (!GetPlayer()->IsBeingTeleportedFar()) - return; - - // get the teleport destination - WorldLocation &loc = GetPlayer()->GetTeleportDest(); - - // possible errors in the coordinate validity check - if (!MapManager::IsValidMapCoord(loc)) - { - LogoutPlayer(false); - return; - } - - // get the destination map entry, not the current one, this will fix homebind and reset greeting - MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId()); - InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.GetMapId()); - - // reset instance validity, except if going to an instance inside an instance - if (GetPlayer()->m_InstanceValid == false && !mInstance) - GetPlayer()->m_InstanceValid = true; - - GetPlayer()->SetSemaphoreTeleportFar(false); - - Map * oldMap = GetPlayer()->GetMap(); - assert(oldMap); - if (GetPlayer()->IsInWorld()) - { - sLog.outCrash("Player is still in world when teleported from map %u! to new map %u", oldMap->GetId(), loc.GetMapId()); - oldMap->Remove(GetPlayer(), false); - } - - // relocate the player to the teleport destination - Map * newMap = MapManager::Instance().CreateMap(loc.GetMapId(), GetPlayer(), 0); - // the CanEnter checks are done in TeleporTo but conditions may change - // while the player is in transit, for example the map may get full - if (!newMap || !newMap->CanEnter(GetPlayer())) - { - sLog.outError("Map %d could not be created for player %d, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUIDLow()); - GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); - return; - } - else - GetPlayer()->Relocate(&loc); - - GetPlayer()->ResetMap(); - GetPlayer()->SetMap(newMap); - - GetPlayer()->SendInitialPacketsBeforeAddToMap(); - if (!GetPlayer()->GetMap()->Add(GetPlayer())) - { - sLog.outError("WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.GetMapId()); - GetPlayer()->ResetMap(); - GetPlayer()->SetMap(oldMap); - GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); - return; - } - - // battleground state prepare (in case join to BG), at relogin/tele player not invited - // only add to bg group and object, if the player was invited (else he entered through command) - if (_player->InBattleGround()) - { - // cleanup setting if outdated - if (!mEntry->IsBattleGroundOrArena()) - { - // We're not in BG - _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); - // reset destination bg team - _player->SetBGTeam(0); - } - // join to bg case - else if (BattleGround *bg = _player->GetBattleGround()) - { - if (_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) - bg->AddPlayer(_player); - } - } - - GetPlayer()->SendInitialPacketsAfterAddToMap(); - - // flight fast teleport case - if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) - { - if (!_player->InBattleGround()) - { - // short preparations to continue flight - FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); - flight->Initialize(*GetPlayer()); - return; - } - - // battleground state prepare, stop flight - GetPlayer()->GetMotionMaster()->MovementExpired(); - GetPlayer()->CleanupAfterTaxiFlight(); - } - - // resurrect character at enter into instance where his corpse exist after add to map - Corpse *corpse = GetPlayer()->GetCorpse(); - if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) - { - if (mEntry->IsDungeon()) - { - GetPlayer()->ResurrectPlayer(0.5f,false); - GetPlayer()->SpawnCorpseBones(); - } - } - - bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattleGroundOrArena(); - if (mInstance) - { - Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid()); - if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID,diff)) - { - if (mapDiff->resetTime) - { - if (uint32 timeReset = sInstanceSaveManager.GetResetTimeFor(mEntry->MapID,diff)) - { - uint32 timeleft = timeReset - time(NULL); - GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft); - } - } - } - allowMount = mInstance->allowMount; - } - - // mount allow check - if (!allowMount) - _player->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // update zone immediately, otherwise leave channel will cause crash in mtmap - uint32 newzone, newarea; - GetPlayer()->GetZoneAndAreaId(newzone, newarea); - GetPlayer()->UpdateZone(newzone, newarea); - - // honorless target - if (GetPlayer()->pvpInfo.inHostileArea) - GetPlayer()->CastSpell(GetPlayer(), 2479, true); - - // resummon pet - GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); - - //lets process all delayed operations on successful teleport - GetPlayer()->ProcessDelayedOperations(); -} - -void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) -{ - sLog.outDebug("MSG_MOVE_TELEPORT_ACK"); - uint64 guid; - - if (!recv_data.readPackGUID(guid)) - return; - - uint32 flags, time; - recv_data >> flags >> time; - DEBUG_LOG("Guid " UI64FMTD, guid); - DEBUG_LOG("Flags %u, time %u", flags, time/IN_MILISECONDS); - - Unit *mover = _player->m_mover; - Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; - - if (!plMover || !plMover->IsBeingTeleportedNear()) - return; - - if (guid != plMover->GetGUID()) - return; - - plMover->SetSemaphoreTeleportNear(false); - - uint32 old_zone = plMover->GetZoneId(); - - WorldLocation const& dest = plMover->GetTeleportDest(); - - plMover->SetPosition(dest,true); - - uint32 newzone, newarea; - plMover->GetZoneAndAreaId(newzone, newarea); - plMover->UpdateZone(newzone, newarea); - - // new zone - if (old_zone != newzone) - { - // honorless target - if (plMover->pvpInfo.inHostileArea) - plMover->CastSpell(plMover, 2479, true); - } - - // resummon pet - GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); - - //lets process all delayed operations on successful teleport - GetPlayer()->ProcessDelayedOperations(); -} - -void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) -{ - uint16 opcode = recv_data.GetOpcode(); - //sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); - recv_data.hexlike(); - - Unit *mover = _player->m_mover; - - assert(mover != NULL); // there must always be a mover - - Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; - - // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck - if (plMover && plMover->IsBeingTeleported()) - { - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - } - - /* extract packet */ - uint64 guid; - - if (!recv_data.readPackGUID(guid)) - return; - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); - /*----------------*/ - - /* if (recv_data.size() != recv_data.rpos()) - { - sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos()); - KickPlayer();*/ - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - /* return; - }*/ - - if (!Trinity::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) - { - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - } - - /* handle special cases */ - if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) - { - // transports size limited - // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) - if (movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50) - { - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - } - - if (!Trinity::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y, - movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o)) - { - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - } - - // if we boarded a transport, add us to it - if (plMover && !plMover->GetTransport()) - { - // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list - for (MapManager::TransportSet::const_iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) - { - if ((*iter)->GetGUID() == movementInfo.t_guid) - { - plMover->m_transport = (*iter); - (*iter)->AddPassenger(plMover); - break; - } - } - } - - if (!mover->GetTransport() && !mover->GetVehicle()) - { - GameObject *go = mover->GetMap()->GetGameObject(movementInfo.t_guid); - if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) - movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; - } - } - else if (plMover && plMover->GetTransport()) // if we were on a transport, leave - { - plMover->m_transport->RemovePassenger(plMover); - plMover->m_transport = NULL; - movementInfo.t_x = 0.0f; - movementInfo.t_y = 0.0f; - movementInfo.t_z = 0.0f; - movementInfo.t_o = 0.0f; - movementInfo.t_time = 0; - movementInfo.t_seat = -1; - } - - // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight()) - plMover->HandleFall(movementInfo); - - if (plMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plMover->IsInWater()) - { - // now client not include swimming flag in case jumping under water - plMover->SetInWater(!plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z)); - } - - /*----------------------*/ - - /* process position-change */ - WorldPacket data(opcode, recv_data.size()); - movementInfo.time = getMSTime(); - movementInfo.guid = mover->GetGUID(); - WriteMovementInfo(&data, &movementInfo); - mover->SendMessageToSet(&data, _player); - - mover->m_movementInfo = movementInfo; - - // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() - if (mover->GetVehicle()) - { - mover->SetOrientation(movementInfo.o); - return; - } - - mover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); - - if (plMover) // nothing is charmed, or player charmed - { - plMover->UpdateFallInformationIfNeed(movementInfo, opcode); - - if (movementInfo.z < -500.0f) - { - if (plMover->InBattleGround() - && plMover->GetBattleGround() - && plMover->GetBattleGround()->HandlePlayerUnderMap(_player)) - { - // do nothing, the handle already did if returned true - } - else - { - // NOTE: this is actually called many times while falling - // even after the player has been teleported away - // TODO: discard movement packets after the player is rooted - if (plMover->isAlive()) - { - plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); - // pl can be alive if GM/etc - if (!plMover->isAlive()) - { - // change the death state to CORPSE to prevent the death timer from - // starting in the next player update - plMover->KillPlayer(); - plMover->BuildPlayerRepop(); - } - } - - // cancel the death timer here if started - plMover->RepopAtGraveyard(); - } - } - } - /*else // creature charmed - { - if (mover->canFly()) - { - bool flying = mover->IsFlying(); - if (flying != ((mover->GetByteValue(UNIT_FIELD_BYTES_1, 3) & 0x02) ? true : false)) - mover->SetFlying(flying); - } - }*/ - - //sLog.outString("Receive Movement Packet %s:", opcodeTable[recv_data.GetOpcode()]); - //mover->OutMovementInfo(); -} - -void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) -{ - uint32 opcode = recv_data.GetOpcode(); - sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); - - /* extract packet */ - uint64 guid; - uint32 unk1; - float newspeed; - - if (!recv_data.readPackGUID(guid)) - return; - - // now can skip not our packet - if (_player->GetGUID() != guid) - { - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - } - - // continue parse packet - - recv_data >> unk1; // counter or moveEvent - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); - - recv_data >> newspeed; - /*----------------*/ - - // client ACK send one packet for mounted/run case and need skip all except last from its - // in other cases anti-cheat check can be fail in false case - UnitMoveType move_type; - UnitMoveType force_move_type; - - static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" }; - - switch(opcode) - { - case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; - case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; - case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break; - case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; - case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break; - case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; - case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break; - case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break; - case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break; - default: - sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); - return; - } - - // skip all forced speed changes except last and unexpected - // in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both. - if (_player->m_forced_speed_changes[force_move_type] > 0) - { - --_player->m_forced_speed_changes[force_move_type]; - if (_player->m_forced_speed_changes[force_move_type] > 0) - return; - } - - if (!_player->GetTransport() && fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f) - { - if (_player->GetSpeed(move_type) > newspeed) // must be greater - just correct - { - sLog.outError("%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value", - move_type_name[move_type], _player->GetName(), _player->GetSpeed(move_type), newspeed); - _player->SetSpeed(move_type,_player->GetSpeedRate(move_type),true); - } - else // must be lesser - cheating - { - sLog.outBasic("Player %s from account id %u kicked for incorrect speed (must be %f instead %f)", - _player->GetName(),_player->GetSession()->GetAccountId(),_player->GetSpeed(move_type), newspeed); - _player->GetSession()->KickPlayer(); - } - } -} - -void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); - - uint64 guid; - recv_data >> guid; - - if (GetPlayer()->IsInWorld()) - if (Unit *mover = ObjectAccessor::GetUnit(*GetPlayer(), guid)) - { - GetPlayer()->SetMover(mover); - if (mover != GetPlayer() && mover->canFly()) - { - WorldPacket data(SMSG_MOVE_SET_CAN_FLY, 12); - data.append(mover->GetPackGUID()); - data << uint32(0); - SendPacket(&data); - } - } - else - { - sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " and should be " UI64FMTD, guid, _player->m_mover->GetGUID()); - GetPlayer()->SetMover(GetPlayer()); - } -} - -void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); - - uint64 old_mover_guid; - if (!recv_data.readPackGUID(old_mover_guid)) - return; - - /*if (_player->m_mover->GetGUID() == old_mover_guid) - { - sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid); - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - }*/ - - MovementInfo mi; - mi.guid = old_mover_guid; - ReadMovementInfo(recv_data, &mi); - - //ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo); - _player->m_movementInfo = mi; -} - -void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE"); - recv_data.hexlike(); - - uint64 vehicleGUID = _player->GetCharmGUID(); - - if (!vehicleGUID) // something wrong here... - { - recv_data.rpos(recv_data.wpos()); // prevent warnings spam - return; - } - - uint64 guid; - - if (!recv_data.readPackGUID(guid)) - return; - - MovementInfo mi; - mi.guid = guid; - ReadMovementInfo(recv_data, &mi); - - _player->m_movementInfo = mi; - - /* - ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);*/ - _player->ExitVehicle(); -} - -void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE"); - recv_data.hexlike(); - - Unit* vehicle_base = GetPlayer()->GetVehicleBase(); - if (!vehicle_base) - return; - - switch (recv_data.GetOpcode()) - { - case CMSG_REQUEST_VEHICLE_PREV_SEAT: - GetPlayer()->ChangeSeat(-1, false); - break; - case CMSG_REQUEST_VEHICLE_NEXT_SEAT: - GetPlayer()->ChangeSeat(-1, true); - break; - case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: - { - uint64 guid; // current vehicle guid - if (!recv_data.readPackGUID(guid)) - return; - - ReadMovementInfo(recv_data, &vehicle_base->m_movementInfo); - - uint64 accessory; // accessory guid - if (!recv_data.readPackGUID(accessory)) - return; - - int8 seatId; - recv_data >> seatId; - - if (vehicle_base->GetGUID() != guid) - return; - - if (!accessory) - GetPlayer()->ChangeSeat(-1, seatId > 0); // prev/next - else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), accessory)) - { - if (Vehicle *vehicle = vehUnit->GetVehicleKit()) - if (vehicle->HasEmptySeat(seatId)) - GetPlayer()->EnterVehicle(vehicle, seatId); - } - } - break; - case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: - { - uint64 guid; // current vehicle guid - if (!recv_data.readPackGUID(guid)) - return; - - int8 seatId; - recv_data >> seatId; - - if (vehicle_base->GetGUID() == guid) - GetPlayer()->ChangeSeat(seatId); - else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), guid)) - if (Vehicle *vehicle = vehUnit->GetVehicleKit()) - if (vehicle->HasEmptySeat(seatId)) - GetPlayer()->EnterVehicle(vehicle, seatId); - } - break; - default: - break; - } -} - -void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data) -{ - // Read guid - uint64 guid; - data >> guid; - - if (Player* pl=ObjectAccessor::FindPlayer(guid)) - { - if (!pl->GetVehicleKit()) - return; - if (!pl->IsInRaidWith(_player)) - return; - if (!pl->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) - return; - _player->EnterVehicle(pl); - } -} - -void WorldSession::HandleEjectPasenger(WorldPacket &data) -{ - if (data.GetOpcode() == CMSG_EJECT_PASSENGER) - { - if (Vehicle* Vv= _player->GetVehicleKit()) - { - uint64 guid; - data >> guid; - if (Player* Pl=ObjectAccessor::FindPlayer(guid)) - Pl->ExitVehicle(); - } - } -} - -void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT"); - recv_data.hexlike(); - GetPlayer()->ExitVehicle(); -} - -void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/) -{ - //sLog.outDebug("WORLD: Recvd CMSG_MOUNTSPECIAL_ANIM"); - - WorldPacket data(SMSG_MOUNTSPECIAL_ANIM, 8); - data << uint64(GetPlayer()->GetGUID()); - - GetPlayer()->SendMessageToSet(&data, false); -} - -void WorldSession::HandleMoveKnockBackAck(WorldPacket & recv_data) -{ - sLog.outDebug("CMSG_MOVE_KNOCK_BACK_ACK"); - - uint64 guid; // guid - unused - if (!recv_data.readPackGUID(guid)) - return; - - recv_data.read_skip(); // unk - - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); -} - -void WorldSession::HandleMoveHoverAck(WorldPacket& recv_data) -{ - sLog.outDebug("CMSG_MOVE_HOVER_ACK"); - - uint64 guid; // guid - unused - if (!recv_data.readPackGUID(guid)) - return; - - recv_data.read_skip(); // unk - - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip(); // unk2 -} - -void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recv_data) -{ - sLog.outDebug("CMSG_MOVE_WATER_WALK_ACK"); - - uint64 guid; // guid - unused - if (!recv_data.readPackGUID(guid)) - return; - - recv_data.read_skip(); // unk - - MovementInfo movementInfo; - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip(); // unk2 -} - -void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data) -{ - if (!_player->isAlive() || _player->isInCombat()) - return; - - uint64 summoner_guid; - bool agree; - recv_data >> summoner_guid; - recv_data >> agree; - - _player->SummonIfPossible(agree); -} - diff --git a/src/server/game/Movement/Path.h b/src/server/game/Movement/Path.h deleted file mode 100644 index 9ec079f3c9c..00000000000 --- a/src/server/game/Movement/Path.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_PATH_H -#define TRINITYCORE_PATH_H - -#include "Common.h" -#include - -class Path -{ - public: - struct PathNode - { - float x,y,z; - }; - - void SetLength(const unsigned int sz) - { - i_nodes.resize(sz); - } - - unsigned int Size() const { return i_nodes.size(); } - bool Empty() const { return i_nodes.empty(); } - void Resize(unsigned int sz) { i_nodes.resize(sz); } - void Clear(void) { i_nodes.clear(); } - PathNode const* GetNodes(uint32 start = 0) const { return &i_nodes[start]; } - float GetTotalLength() const { return GetTotalLength(0,Size()); } - float GetTotalLength(uint32 start, uint32 end) const - { - float len = 0, xd, yd, zd; - for (unsigned int idx=start+1; idx < end; ++idx) - { - xd = i_nodes[ idx ].x - i_nodes[ idx-1 ].x; - yd = i_nodes[ idx ].y - i_nodes[ idx-1 ].y; - zd = i_nodes[ idx ].z - i_nodes[ idx-1 ].z; - len += sqrtf(xd*xd + yd*yd + zd*zd); - } - return len; - } - - float GetPassedLength(uint32 curnode, float x, float y, float z) - { - float len = 0, xd, yd, zd; - for (unsigned int idx=1; idx < curnode; ++idx) - { - xd = i_nodes[ idx ].x - i_nodes[ idx-1 ].x; - yd = i_nodes[ idx ].y - i_nodes[ idx-1 ].y; - zd = i_nodes[ idx ].z - i_nodes[ idx-1 ].z; - len += sqrtf(xd*xd + yd*yd + zd*zd); - } - - if (curnode > 0) - { - xd = x - i_nodes[curnode-1].x; - yd = y - i_nodes[curnode-1].y; - zd = z - i_nodes[curnode-1].z; - len += sqrtf(xd*xd + yd*yd + zd*zd); - } - - return len; - } - - PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } - const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } - - protected: - std::vector i_nodes; -}; -#endif - diff --git a/src/server/game/Movement/TaxiHandler.cpp b/src/server/game/Movement/TaxiHandler.cpp deleted file mode 100644 index b0660527f71..00000000000 --- a/src/server/game/Movement/TaxiHandler.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "UpdateMask.h" -#include "Path.h" -#include "WaypointMovementGenerator.h" -#include "DestinationHolderImp.h" - -void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_TAXINODE_STATUS_QUERY"); - - uint64 guid; - - recv_data >> guid; - SendTaxiStatus(guid); -} - -void WorldSession::SendTaxiStatus(uint64 guid) -{ - // cheating checks - Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); - if (!unit) - { - sLog.outDebug("WorldSession::SendTaxiStatus - Unit (GUID: %u) not found.", uint32(GUID_LOPART(guid))); - return; - } - - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); - - // not found nearest - if (curloc == 0) - return; - - sLog.outDebug("WORLD: current location %u ",curloc); - - WorldPacket data(SMSG_TAXINODE_STATUS, 9); - data << guid; - data << uint8(GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0); - SendPacket(&data); - sLog.outDebug("WORLD: Sent SMSG_TAXINODE_STATUS"); -} - -void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_TAXIQUERYAVAILABLENODES"); - - uint64 guid; - recv_data >> guid; - - // cheating checks - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); - if (!unit) - { - sLog.outDebug("WORLD: HandleTaxiQueryAvailableNodes - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - // unknown taxi node case - if (SendLearnNewTaxiNode(unit)) - return; - - // known taxi node case - SendTaxiMenu(unit); -} - -void WorldSession::SendTaxiMenu(Creature* unit) -{ - // find current node - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); - - if (curloc == 0) - return; - - bool lastTaxiCheaterState = GetPlayer()->isTaxiCheater(); - if (unit->GetEntry() == 29480) GetPlayer()->SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it. - - sLog.outDebug("WORLD: CMSG_TAXINODE_STATUS_QUERY %u ",curloc); - - WorldPacket data(SMSG_SHOWTAXINODES, (4+8+4+8*4)); - data << uint32(1); - data << uint64(unit->GetGUID()); - data << uint32(curloc); - GetPlayer()->m_taxi.AppendTaximaskTo(data,GetPlayer()->isTaxiCheater()); - SendPacket(&data); - - sLog.outDebug("WORLD: Sent SMSG_SHOWTAXINODES"); - - GetPlayer()->SetTaxiCheater(lastTaxiCheaterState); -} - -void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode) -{ - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - while (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) - GetPlayer()->GetMotionMaster()->MovementExpired(false); - - if (mountDisplayId) - GetPlayer()->Mount(mountDisplayId); - - GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path,pathNode); -} - -bool WorldSession::SendLearnNewTaxiNode(Creature* unit) -{ - // find current node - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); - - if (curloc == 0) - return true; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result. - - if (GetPlayer()->m_taxi.SetTaximaskNode(curloc)) - { - WorldPacket msg(SMSG_NEW_TAXI_PATH, 0); - SendPacket(&msg); - - WorldPacket update(SMSG_TAXINODE_STATUS, 9); - update << uint64(unit->GetGUID()); - update << uint8(1); - SendPacket(&update); - - return true; - } - else - return false; -} - -void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXIEXPRESS"); - - uint64 guid; - uint32 node_count; - - recv_data >> guid >> node_count; - - Creature *npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); - if (!npc) - { - sLog.outDebug("WORLD: HandleActivateTaxiExpressOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid))); - return; - } - std::vector nodes; - - for (uint32 i = 0; i < node_count; ++i) - { - uint32 node; - recv_data >> node; - nodes.push_back(node); - } - - if (nodes.empty()) - return; - - sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXIEXPRESS from %d to %d" ,nodes.front(),nodes.back()); - - GetPlayer()->ActivateTaxiPathTo(nodes, npc); -} - -void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_MOVE_SPLINE_DONE"); - - uint64 guid; // used only for proper packet read - if (!recv_data.readPackGUID(guid)) - return; - - MovementInfo movementInfo; // used only for proper packet read - ReadMovementInfo(recv_data, &movementInfo); - - recv_data.read_skip(); // unk - - // in taxi flight packet received in 2 case: - // 1) end taxi path in far (multi-node) flight - // 2) switch from one map to other in case multim-map taxi path - // we need process only (1) - - uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); - if (!curDest) - return; - - TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); - - // far teleport case - if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId()) - { - if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) - { - // short preparations to continue flight - FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); - - flight->SetCurrentNodeAfterTeleport(); - Path::PathNode const& node = flight->GetPath()[flight->GetCurrentNode()]; - flight->SkipCurrentNode(); - - GetPlayer()->TeleportTo(curDestNode->map_id,node.x,node.y,node.z,GetPlayer()->GetOrientation()); - } - return; - } - - uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); - if (destinationnode > 0) // if more destinations to go - { - // current source node for next destination - uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); - - // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) - if (GetPlayer()->isTaxiCheater()) - { - if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) - { - WorldPacket data(SMSG_NEW_TAXI_PATH, 0); - _player->GetSession()->SendPacket(&data); - } - } - - sLog.outDebug("WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode); - - uint32 mountDisplayId = objmgr.GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam()); - - uint32 path, cost; - objmgr.GetTaxiPath(sourcenode, destinationnode, path, cost); - - if (path && mountDisplayId) - SendDoFlight(mountDisplayId, path, 1); // skip start fly node - else - GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next - return; - } - - GetPlayer()->CleanupAfterTaxiFlight(); - GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ()); - if (GetPlayer()->pvpInfo.inHostileArea) - GetPlayer()->CastSpell(GetPlayer(), 2479, true); -} - -void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXI"); - - uint64 guid; - std::vector nodes; - nodes.resize(2); - - recv_data >> guid >> nodes[0] >> nodes[1]; - sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXI from %d to %d" ,nodes[0],nodes[1]); - Creature *npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); - if (!npc) - { - sLog.outDebug("WORLD: HandleActivateTaxiOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid))); - return; - } - - GetPlayer()->ActivateTaxiPathTo(nodes, npc); -} diff --git a/src/server/game/Movement/Transports.cpp b/src/server/game/Movement/Transports.cpp deleted file mode 100644 index 444e115f8b9..00000000000 --- a/src/server/game/Movement/Transports.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" - -#include "Transports.h" -#include "MapManager.h" -#include "ObjectMgr.h" -#include "Path.h" - -#include "WorldPacket.h" -#include "DBCStores.h" -#include "ProgressBar.h" - -#include "World.h" - -void MapManager::LoadTransports() -{ - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, name, period FROM transports"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u transports", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Transport *t = new Transport; - - Field *fields = result->Fetch(); - - uint32 entry = fields[0].GetUInt32(); - std::string name = fields[1].GetCppString(); - t->m_period = fields[2].GetUInt32(); - - const GameObjectInfo *goinfo = objmgr.GetGameObjectInfo(entry); - - if (!goinfo) - { - sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str()); - delete t; - continue; - } - - if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT) - { - sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str()); - delete t; - continue; - } - - // sLog.outString("Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name); - - std::set mapsUsed; - - if (!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed)) - // skip transports with empty waypoints list - { - sLog.outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.",goinfo->moTransport.taxiPathId); - delete t; - continue; - } - - float x, y, z, o; - uint32 mapid; - x = t->m_WayPoints[0].x; y = t->m_WayPoints[0].y; z = t->m_WayPoints[0].z; mapid = t->m_WayPoints[0].mapid; o = 1; - - // creates the Gameobject - if (!t->Create(entry, mapid, x, y, z, o, 100, 0)) - { - delete t; - continue; - } - - m_Transports.insert(t); - - for (std::set::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i) - m_TransportsByMap[*i].insert(t); - - //If we someday decide to use the grid to track transports, here: - t->SetMap(MapManager::Instance().CreateMap(mapid, t, 0)); - - //t->GetMap()->Add((GameObject *)t); - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u transports", count); - - // check transport data DB integrity - result = WorldDatabase.Query("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); - if (result) // wrong data found - { - do - { - Field *fields = result->Fetch(); - - uint32 guid = fields[0].GetUInt32(); - uint32 entry = fields[1].GetUInt32(); - std::string name = fields[2].GetCppString(); - sLog.outErrorDb("Transport %u '%s' have record (GUID: %u) in `gameobject`. Transports DON'T must have any records in `gameobject` or its behavior will be unpredictable/bugged.",entry,name.c_str(),guid); - } - while (result->NextRow()); - } -} - -Transport::Transport() : GameObject() -{ - m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_ROTATION); -} - -bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) -{ - Relocate(x,y,z,ang); - // instance id and phaseMask isn't set to values different from std. - - if (!IsPositionValid()) - { - sLog.outError("Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", - guidlow,x,y); - return false; - } - - Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT); - - GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(guidlow); - - if (!goinfo) - { - sLog.outErrorDb("Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f",guidlow, mapid, x, y, z, ang); - return false; - } - - m_goInfo = goinfo; - - SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); - - SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); - //SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); - SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64)); - SetUInt32Value(GAMEOBJECT_LEVEL, m_period); - SetEntry(goinfo->id); - - SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); - - SetGoState(GO_STATE_READY); - SetGoType(GameobjectTypes(goinfo->type)); - - SetGoAnimProgress(animprogress); - if (dynflags) - SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags)); - - SetName(goinfo->name); - - return true; -} - -struct keyFrame -{ - keyFrame(float _x, float _y, float _z, uint32 _mapid, int _actionflag, int _delay) - { - x = _x; y = _y; z = _z; mapid = _mapid; actionflag = _actionflag; delay = _delay; distFromPrev = -1; distSinceStop = -1; distUntilStop = -1; - tFrom = 0; tTo = 0; - } - - float x; - float y; - float z; - uint32 mapid; - int actionflag; - int delay; - float distSinceStop; - float distUntilStop; - float distFromPrev; - float tFrom, tTo; -}; - -bool Transport::GenerateWaypoints(uint32 pathid, std::set &mapids) -{ - TransportPath path; - objmgr.GetTransportPathNodes(pathid, path); - - if (path.Empty()) - return false; - - std::vector keyFrames; - int mapChange = 0; - mapids.clear(); - for (size_t i = 1; i < path.Size() - 1; ++i) - { - if (mapChange == 0) - { - if ((path[i].mapid == path[i+1].mapid)) - { - keyFrame k(path[i].x, path[i].y, path[i].z, path[i].mapid, path[i].actionFlag, path[i].delay); - keyFrames.push_back(k); - mapids.insert(k.mapid); - } - else - { - mapChange = 1; - } - } - else - { - --mapChange; - } - } - - int lastStop = -1; - int firstStop = -1; - - // first cell is arrived at by teleportation :S - keyFrames[0].distFromPrev = 0; - if (keyFrames[0].actionflag == 2) - { - lastStop = 0; - } - - // find the rest of the distances between key points - for (size_t i = 1; i < keyFrames.size(); ++i) - { - if ((keyFrames[i].actionflag == 1) || (keyFrames[i].mapid != keyFrames[i-1].mapid)) - { - keyFrames[i].distFromPrev = 0; - } - else - { - keyFrames[i].distFromPrev = - sqrt(pow(keyFrames[i].x - keyFrames[i - 1].x, 2) + - pow(keyFrames[i].y - keyFrames[i - 1].y, 2) + - pow(keyFrames[i].z - keyFrames[i - 1].z, 2)); - } - if (keyFrames[i].actionflag == 2) - { - // remember first stop frame - if (firstStop == -1) - firstStop = i; - lastStop = i; - } - } - - float tmpDist = 0; - for (size_t i = 0; i < keyFrames.size(); ++i) - { - int j = (i + lastStop) % keyFrames.size(); - if (keyFrames[j].actionflag == 2) - tmpDist = 0; - else - tmpDist += keyFrames[j].distFromPrev; - keyFrames[j].distSinceStop = tmpDist; - } - - for (int i = int(keyFrames.size()) - 1; i >= 0; i--) - { - int j = (i + (firstStop+1)) % keyFrames.size(); - tmpDist += keyFrames[(j + 1) % keyFrames.size()].distFromPrev; - keyFrames[j].distUntilStop = tmpDist; - if (keyFrames[j].actionflag == 2) - tmpDist = 0; - } - - for (size_t i = 0; i < keyFrames.size(); ++i) - { - if (keyFrames[i].distSinceStop < (30 * 30 * 0.5f)) - keyFrames[i].tFrom = sqrt(2 * keyFrames[i].distSinceStop); - else - keyFrames[i].tFrom = ((keyFrames[i].distSinceStop - (30 * 30 * 0.5f)) / 30) + 30; - - if (keyFrames[i].distUntilStop < (30 * 30 * 0.5f)) - keyFrames[i].tTo = sqrt(2 * keyFrames[i].distUntilStop); - else - keyFrames[i].tTo = ((keyFrames[i].distUntilStop - (30 * 30 * 0.5f)) / 30) + 30; - - keyFrames[i].tFrom *= 1000; - keyFrames[i].tTo *= 1000; - } - - // for (int i = 0; i < keyFrames.size(); ++i) { - // sLog.outString("%f, %f, %f, %f, %f, %f, %f", keyFrames[i].x, keyFrames[i].y, keyFrames[i].distUntilStop, keyFrames[i].distSinceStop, keyFrames[i].distFromPrev, keyFrames[i].tFrom, keyFrames[i].tTo); - // } - - // Now we're completely set up; we can move along the length of each waypoint at 100 ms intervals - // speed = max(30, t) (remember x = 0.5s^2, and when accelerating, a = 1 unit/s^2 - int t = 0; - bool teleport = false; - if (keyFrames[keyFrames.size() - 1].mapid != keyFrames[0].mapid) - teleport = true; - - WayPoint pos(keyFrames[0].mapid, keyFrames[0].x, keyFrames[0].y, keyFrames[0].z, teleport, 0); - m_WayPoints[0] = pos; - t += keyFrames[0].delay * 1000; - - uint32 cM = keyFrames[0].mapid; - for (size_t i = 0; i < keyFrames.size() - 1; ++i) - { - float d = 0; - float tFrom = keyFrames[i].tFrom; - float tTo = keyFrames[i].tTo; - - // keep the generation of all these points; we use only a few now, but may need the others later - if (((d < keyFrames[i + 1].distFromPrev) && (tTo > 0))) - { - while ((d < keyFrames[i + 1].distFromPrev) && (tTo > 0)) - { - tFrom += 100; - tTo -= 100; - - if (d > 0) - { - float newX, newY, newZ; - newX = keyFrames[i].x + (keyFrames[i + 1].x - keyFrames[i].x) * d / keyFrames[i + 1].distFromPrev; - newY = keyFrames[i].y + (keyFrames[i + 1].y - keyFrames[i].y) * d / keyFrames[i + 1].distFromPrev; - newZ = keyFrames[i].z + (keyFrames[i + 1].z - keyFrames[i].z) * d / keyFrames[i + 1].distFromPrev; - - bool teleport = false; - if (keyFrames[i].mapid != cM) - { - teleport = true; - cM = keyFrames[i].mapid; - } - - // sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ); - WayPoint pos(keyFrames[i].mapid, newX, newY, newZ, teleport, i); - if (teleport) - m_WayPoints[t] = pos; - } - - if (tFrom < tTo) // caught in tFrom dock's "gravitational pull" - { - if (tFrom <= 30000) - { - d = 0.5f * (tFrom / 1000) * (tFrom / 1000); - } - else - { - d = 0.5f * 30 * 30 + 30 * ((tFrom - 30000) / 1000); - } - d = d - keyFrames[i].distSinceStop; - } - else - { - if (tTo <= 30000) - { - d = 0.5f * (tTo / 1000) * (tTo / 1000); - } - else - { - d = 0.5f * 30 * 30 + 30 * ((tTo - 30000) / 1000); - } - d = keyFrames[i].distUntilStop - d; - } - t += 100; - } - t -= 100; - } - - if (keyFrames[i + 1].tFrom > keyFrames[i + 1].tTo) - t += 100 - ((long)keyFrames[i + 1].tTo % 100); - else - t += (long)keyFrames[i + 1].tTo % 100; - - bool teleport = false; - if ((keyFrames[i + 1].actionflag == 1) || (keyFrames[i + 1].mapid != keyFrames[i].mapid)) - { - teleport = true; - cM = keyFrames[i + 1].mapid; - } - - WayPoint pos(keyFrames[i + 1].mapid, keyFrames[i + 1].x, keyFrames[i + 1].y, keyFrames[i + 1].z, teleport, i); - - // sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport); -/* - if (keyFrames[i+1].delay > 5) - pos.delayed = true; -*/ - //if (teleport) - m_WayPoints[t] = pos; - - t += keyFrames[i + 1].delay * 1000; - // sLog.outString("------"); - } - - uint32 timer = t; - - // sLog.outDetail(" Generated %lu waypoints, total time %u.", (unsigned long)m_WayPoints.size(), timer); - - m_curr = m_WayPoints.begin(); - m_curr = GetNextWayPoint(); - m_next = GetNextWayPoint(); - m_pathTime = timer; - - m_nextNodeTime = m_curr->first; - - return true; -} - -Transport::WayPointMap::const_iterator Transport::GetNextWayPoint() -{ - WayPointMap::const_iterator iter = m_curr; - ++iter; - if (iter == m_WayPoints.end()) - iter = m_WayPoints.begin(); - return iter; -} - -void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) -{ - Map const* oldMap = GetMap(); - Relocate(x, y, z); - - for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) - { - Player *plr = *itr; - ++itr; - - if (plr->isDead() && !plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) - { - plr->ResurrectPlayer(1.0); - } - plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT); - - //WorldPacket data(SMSG_811, 4); - //data << uint32(0); - //plr->GetSession()->SendPacket(&data); - } - - //we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference... - //player far teleport would try to create same instance, but we need it NOW for transport... - //correct me if I'm wrong O.o - //yes, you're right - - ResetMap(); - Map * newMap = MapManager::Instance().CreateMap(newMapid, this, 0); - SetMap(newMap); - assert (GetMap()); - - if (oldMap != newMap) - { - UpdateForMap(oldMap); - UpdateForMap(newMap); - } -} - -bool Transport::AddPassenger(Player* passenger) -{ - if (m_passengers.insert(passenger).second) - sLog.outDetail("Player %s boarded transport %s.", passenger->GetName(), GetName()); - return true; -} - -bool Transport::RemovePassenger(Player* passenger) -{ - if (m_passengers.erase(passenger)) - sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), GetName()); - return true; -} - -void Transport::CheckForEvent(uint32 entry, uint32 wp_id) -{ - uint32 key = entry*100+wp_id; - if (objmgr.TransportEventMap.find(key) != objmgr.TransportEventMap.end()) - GetMap()->ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL); -} - -void Transport::Update(uint32 /*p_time*/) -{ - if (m_WayPoints.size() <= 1) - return; - - m_timer = getMSTime() % m_period; - while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime)) - { - m_curr = GetNextWayPoint(); - m_next = GetNextWayPoint(); - - // first check help in case client-server transport coordinates de-synchronization - if (m_curr->second.mapid != GetMapId() || m_curr->second.teleport) - { - TeleportTransport(m_curr->second.mapid, m_curr->second.x, m_curr->second.y, m_curr->second.z); - } - else - { - Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z); - } -/* - if (m_curr->second.delayed) - { - switch (GetEntry()) - { - case 176495: - case 164871: - case 175080: - SendPlaySound(11804, false); break; // ZeppelinDocked - case 20808: - case 181646: - case 176231: - case 176244: - case 176310: - case 177233: - SendPlaySound(5495, false);break; // BoatDockingWarning - default: - SendPlaySound(5154, false); break; // ShipDocked - } - } -*/ - /* - for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) - { - PlayerSet::const_iterator it2 = itr; - ++itr; - //(*it2)->SetPosition(m_curr->second.x + (*it2)->GetTransOffsetX(), m_curr->second.y + (*it2)->GetTransOffsetY(), m_curr->second.z + (*it2)->GetTransOffsetZ(), (*it2)->GetTransOffsetO()); - } - */ - - m_nextNodeTime = m_curr->first; - - if (m_curr == m_WayPoints.begin() && (sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES) == 0) - sLog.outDetail(" ************ BEGIN ************** %s", this->m_name.c_str()); - - if ((sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES) == 0) - sLog.outDetail("%s moved to %d %f %f %f %d", this->m_name.c_str(), m_curr->second.id, m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid); - - //Transport Event System - CheckForEvent(this->GetEntry(), m_curr->second.id); - } -} - -void Transport::UpdateForMap(Map const* targetMap) -{ - Map::PlayerList const& pl = targetMap->GetPlayers(); - if (pl.isEmpty()) - return; - - if (GetMapId() == targetMap->GetId()) - { - for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) - { - if (this != itr->getSource()->GetTransport()) - { - UpdateData transData; - BuildCreateUpdateBlockForPlayer(&transData, itr->getSource()); - WorldPacket packet; - transData.BuildPacket(&packet); - itr->getSource()->SendDirectMessage(&packet); - } - } - } - else - { - UpdateData transData; - BuildOutOfRangeUpdateBlock(&transData); - WorldPacket out_packet; - transData.BuildPacket(&out_packet); - - for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) - if (this != itr->getSource()->GetTransport()) - itr->getSource()->SendDirectMessage(&out_packet); - } -} - diff --git a/src/server/game/Movement/Transports.h b/src/server/game/Movement/Transports.h deleted file mode 100644 index 25b9ade1461..00000000000 --- a/src/server/game/Movement/Transports.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRANSPORTS_H -#define TRANSPORTS_H - -#include "GameObject.h" - -#include -#include -#include - -class TransportPath -{ - public: - struct PathNode - { - uint32 mapid; - float x,y,z; - uint32 actionFlag; - uint32 delay; - }; - - void SetLength(const unsigned int sz) - { - i_nodes.resize(sz); - } - - unsigned int Size(void) const { return i_nodes.size(); } - bool Empty(void) const { return i_nodes.empty(); } - void Resize(unsigned int sz) { i_nodes.resize(sz); } - void Clear(void) { i_nodes.clear(); } - PathNode* GetNodes(void) { return static_cast(&i_nodes[0]); } - - PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } - const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } - - protected: - std::vector i_nodes; -}; - -class Transport : public GameObject -{ - public: - explicit Transport(); - - bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags); - bool GenerateWaypoints(uint32 pathid, std::set &mapids); - void Update(uint32 p_time); - bool AddPassenger(Player* passenger); - bool RemovePassenger(Player* passenger); - void CheckForEvent(uint32 entry, uint32 wp_id); - - typedef std::set PlayerSet; - PlayerSet const& GetPassengers() const { return m_passengers; } - - private: - struct WayPoint - { - WayPoint() : mapid(0), x(0), y(0), z(0), teleport(false), id(0) {} - WayPoint(uint32 _mapid, float _x, float _y, float _z, bool _teleport, uint32 _id) : - mapid(_mapid), x(_x), y(_y), z(_z), teleport(_teleport), id(_id) {} - uint32 mapid; - float x; - float y; - float z; - bool teleport; - uint32 id; - }; - - typedef std::map WayPointMap; - - WayPointMap::const_iterator m_curr; - WayPointMap::const_iterator m_next; - uint32 m_pathTime; - uint32 m_timer; - - PlayerSet m_passengers; - - public: - WayPointMap m_WayPoints; - uint32 m_nextNodeTime; - uint32 m_period; - - private: - void TeleportTransport(uint32 newMapid, float x, float y, float z); - void UpdateForMap(Map const* map); - WayPointMap::const_iterator GetNextWayPoint(); -}; -#endif - diff --git a/src/server/game/Movement/WaypointManager.cpp b/src/server/game/Movement/WaypointManager.cpp deleted file mode 100644 index 0cbdd0bf975..00000000000 --- a/src/server/game/Movement/WaypointManager.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Database/DatabaseEnv.h" -#include "GridDefines.h" -#include "WaypointManager.h" -#include "ProgressBar.h" -#include "MapManager.h" - -void WaypointStore::Free() -{ - for (UNORDERED_MAP::const_iterator itr = waypoint_map.begin(); itr != waypoint_map.end(); ++itr) - { - for (WaypointPath::const_iterator it = itr->second->begin(); it != itr->second->end(); ++it) - delete *it; - itr->second->clear(); - delete itr->second; - } - waypoint_map.clear(); -} - -void WaypointStore::Load() -{ - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT COUNT(id) FROM waypoint_data"); - if (!result) - { - sLog.outError("an error occured while loading the table `waypoint_data` (maybe it doesn't exist ?)"); - exit(1); // Stop server at loading non exited table or not accessable table - } - - records = (*result)[0].GetUInt32(); - - result = WorldDatabase.Query("SELECT id,point,position_x,position_y,position_z,move_flag,delay,action,action_chance FROM waypoint_data ORDER BY id, point"); - if (!result) - { - sLog.outErrorDb("The table `waypoint_data` is empty or corrupted"); - return; - } - - WaypointPath* path_data = NULL; - uint32 total_records = result->GetRowCount(); - - barGoLink bar(total_records); - uint32 count = 0; - Field *fields; - uint32 last_id = 0; - - do - { - fields = result->Fetch(); - uint32 id = fields[0].GetUInt32(); - bar.step(); - count++; - WaypointData *wp = new WaypointData; - - if (last_id != id) - path_data = new WaypointPath; - - float x,y,z; - x = fields[2].GetFloat(); - y = fields[3].GetFloat(); - z = fields[4].GetFloat(); - - Trinity::NormalizeMapCoord(x); - Trinity::NormalizeMapCoord(y); - - wp->id = fields[1].GetUInt32(); - wp->x = x; - wp->y = y; - wp->z = z; - wp->run = fields[5].GetBool(); - wp->delay = fields[6].GetUInt32(); - wp->event_id = fields[7].GetUInt32(); - wp->event_chance = fields[8].GetUInt8(); - - path_data->push_back(wp); - - if (id != last_id) - waypoint_map[id] = path_data; - - last_id = id; - - } while (result->NextRow()) ; - - sLog.outString(); - sLog.outString(">> Loaded %u waypoints", count); -} - -void WaypointStore::UpdatePath(uint32 id) -{ - if (waypoint_map.find(id)!= waypoint_map.end()) - waypoint_map[id]->clear(); - - QueryResult_AutoPtr result; - - result = WorldDatabase.PQuery("SELECT point,position_x,position_y,position_z,move_flag,delay,action,action_chance FROM waypoint_data WHERE id = %u ORDER BY point", id); - - if (!result) - return; - - WaypointPath* path_data; - path_data = new WaypointPath; - Field *fields; - - do - { - fields = result->Fetch(); - - WaypointData *wp = new WaypointData; - - float x,y,z; - x = fields[1].GetFloat(); - y = fields[2].GetFloat(); - z = fields[3].GetFloat(); - - Trinity::NormalizeMapCoord(x); - Trinity::NormalizeMapCoord(y); - - wp->id = fields[0].GetUInt32(); - wp->x = x; - wp->y = y; - wp->z = z; - wp->run = fields[4].GetBool(); - wp->delay = fields[5].GetUInt32(); - wp->event_id = fields[6].GetUInt32(); - wp->event_chance = fields[7].GetUInt8(); - - path_data->push_back(wp); - - } - while (result->NextRow()); - - waypoint_map[id] = path_data; -} - diff --git a/src/server/game/Movement/WaypointManager.h b/src/server/game/Movement/WaypointManager.h deleted file mode 100644 index 7efca558146..00000000000 --- a/src/server/game/Movement/WaypointManager.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_WAYPOINTMANAGER_H -#define TRINITY_WAYPOINTMANAGER_H - -#include -#include -#include - -struct WaypointData -{ - uint32 id; - float x,y,z; - bool run; - uint32 delay; - uint32 event_id; - uint8 event_chance; -}; - -typedef std::vector WaypointPath; - -class WaypointStore -{ - private : - uint32 records; - UNORDERED_MAP waypoint_map; - - public: - // Null Mutex is OK because WaypointMgr is initialized in the World thread before World is initialized - static WaypointStore* instance() { return ACE_Singleton::instance(); } - - ~WaypointStore() { Free(); } - void UpdatePath(uint32 id); - void Load(); - void Free(); - - WaypointPath* GetPath(uint32 id) - { - if (waypoint_map.find(id) != waypoint_map.end()) - return waypoint_map[id]; - else return 0; - } - - inline uint32 GetRecordsCount() { return records; } -}; - -#define sWaypointMgr WaypointStore::instance() - -#endif - diff --git a/src/server/game/Movement/Waypoints/Path.h b/src/server/game/Movement/Waypoints/Path.h new file mode 100644 index 00000000000..9ec079f3c9c --- /dev/null +++ b/src/server/game/Movement/Waypoints/Path.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_PATH_H +#define TRINITYCORE_PATH_H + +#include "Common.h" +#include + +class Path +{ + public: + struct PathNode + { + float x,y,z; + }; + + void SetLength(const unsigned int sz) + { + i_nodes.resize(sz); + } + + unsigned int Size() const { return i_nodes.size(); } + bool Empty() const { return i_nodes.empty(); } + void Resize(unsigned int sz) { i_nodes.resize(sz); } + void Clear(void) { i_nodes.clear(); } + PathNode const* GetNodes(uint32 start = 0) const { return &i_nodes[start]; } + float GetTotalLength() const { return GetTotalLength(0,Size()); } + float GetTotalLength(uint32 start, uint32 end) const + { + float len = 0, xd, yd, zd; + for (unsigned int idx=start+1; idx < end; ++idx) + { + xd = i_nodes[ idx ].x - i_nodes[ idx-1 ].x; + yd = i_nodes[ idx ].y - i_nodes[ idx-1 ].y; + zd = i_nodes[ idx ].z - i_nodes[ idx-1 ].z; + len += sqrtf(xd*xd + yd*yd + zd*zd); + } + return len; + } + + float GetPassedLength(uint32 curnode, float x, float y, float z) + { + float len = 0, xd, yd, zd; + for (unsigned int idx=1; idx < curnode; ++idx) + { + xd = i_nodes[ idx ].x - i_nodes[ idx-1 ].x; + yd = i_nodes[ idx ].y - i_nodes[ idx-1 ].y; + zd = i_nodes[ idx ].z - i_nodes[ idx-1 ].z; + len += sqrtf(xd*xd + yd*yd + zd*zd); + } + + if (curnode > 0) + { + xd = x - i_nodes[curnode-1].x; + yd = y - i_nodes[curnode-1].y; + zd = z - i_nodes[curnode-1].z; + len += sqrtf(xd*xd + yd*yd + zd*zd); + } + + return len; + } + + PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } + const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } + + protected: + std::vector i_nodes; +}; +#endif + diff --git a/src/server/game/Movement/Waypoints/WaypointManager.cpp b/src/server/game/Movement/Waypoints/WaypointManager.cpp new file mode 100644 index 00000000000..0cbdd0bf975 --- /dev/null +++ b/src/server/game/Movement/Waypoints/WaypointManager.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Database/DatabaseEnv.h" +#include "GridDefines.h" +#include "WaypointManager.h" +#include "ProgressBar.h" +#include "MapManager.h" + +void WaypointStore::Free() +{ + for (UNORDERED_MAP::const_iterator itr = waypoint_map.begin(); itr != waypoint_map.end(); ++itr) + { + for (WaypointPath::const_iterator it = itr->second->begin(); it != itr->second->end(); ++it) + delete *it; + itr->second->clear(); + delete itr->second; + } + waypoint_map.clear(); +} + +void WaypointStore::Load() +{ + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT COUNT(id) FROM waypoint_data"); + if (!result) + { + sLog.outError("an error occured while loading the table `waypoint_data` (maybe it doesn't exist ?)"); + exit(1); // Stop server at loading non exited table or not accessable table + } + + records = (*result)[0].GetUInt32(); + + result = WorldDatabase.Query("SELECT id,point,position_x,position_y,position_z,move_flag,delay,action,action_chance FROM waypoint_data ORDER BY id, point"); + if (!result) + { + sLog.outErrorDb("The table `waypoint_data` is empty or corrupted"); + return; + } + + WaypointPath* path_data = NULL; + uint32 total_records = result->GetRowCount(); + + barGoLink bar(total_records); + uint32 count = 0; + Field *fields; + uint32 last_id = 0; + + do + { + fields = result->Fetch(); + uint32 id = fields[0].GetUInt32(); + bar.step(); + count++; + WaypointData *wp = new WaypointData; + + if (last_id != id) + path_data = new WaypointPath; + + float x,y,z; + x = fields[2].GetFloat(); + y = fields[3].GetFloat(); + z = fields[4].GetFloat(); + + Trinity::NormalizeMapCoord(x); + Trinity::NormalizeMapCoord(y); + + wp->id = fields[1].GetUInt32(); + wp->x = x; + wp->y = y; + wp->z = z; + wp->run = fields[5].GetBool(); + wp->delay = fields[6].GetUInt32(); + wp->event_id = fields[7].GetUInt32(); + wp->event_chance = fields[8].GetUInt8(); + + path_data->push_back(wp); + + if (id != last_id) + waypoint_map[id] = path_data; + + last_id = id; + + } while (result->NextRow()) ; + + sLog.outString(); + sLog.outString(">> Loaded %u waypoints", count); +} + +void WaypointStore::UpdatePath(uint32 id) +{ + if (waypoint_map.find(id)!= waypoint_map.end()) + waypoint_map[id]->clear(); + + QueryResult_AutoPtr result; + + result = WorldDatabase.PQuery("SELECT point,position_x,position_y,position_z,move_flag,delay,action,action_chance FROM waypoint_data WHERE id = %u ORDER BY point", id); + + if (!result) + return; + + WaypointPath* path_data; + path_data = new WaypointPath; + Field *fields; + + do + { + fields = result->Fetch(); + + WaypointData *wp = new WaypointData; + + float x,y,z; + x = fields[1].GetFloat(); + y = fields[2].GetFloat(); + z = fields[3].GetFloat(); + + Trinity::NormalizeMapCoord(x); + Trinity::NormalizeMapCoord(y); + + wp->id = fields[0].GetUInt32(); + wp->x = x; + wp->y = y; + wp->z = z; + wp->run = fields[4].GetBool(); + wp->delay = fields[5].GetUInt32(); + wp->event_id = fields[6].GetUInt32(); + wp->event_chance = fields[7].GetUInt8(); + + path_data->push_back(wp); + + } + while (result->NextRow()); + + waypoint_map[id] = path_data; +} + diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h new file mode 100644 index 00000000000..7efca558146 --- /dev/null +++ b/src/server/game/Movement/Waypoints/WaypointManager.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_WAYPOINTMANAGER_H +#define TRINITY_WAYPOINTMANAGER_H + +#include +#include +#include + +struct WaypointData +{ + uint32 id; + float x,y,z; + bool run; + uint32 delay; + uint32 event_id; + uint8 event_chance; +}; + +typedef std::vector WaypointPath; + +class WaypointStore +{ + private : + uint32 records; + UNORDERED_MAP waypoint_map; + + public: + // Null Mutex is OK because WaypointMgr is initialized in the World thread before World is initialized + static WaypointStore* instance() { return ACE_Singleton::instance(); } + + ~WaypointStore() { Free(); } + void UpdatePath(uint32 id); + void Load(); + void Free(); + + WaypointPath* GetPath(uint32 id) + { + if (waypoint_map.find(id) != waypoint_map.end()) + return waypoint_map[id]; + else return 0; + } + + inline uint32 GetRecordsCount() { return records; } +}; + +#define sWaypointMgr WaypointStore::instance() + +#endif + diff --git a/src/server/game/Opcodes/Opcodes.cpp b/src/server/game/Opcodes/Opcodes.cpp deleted file mode 100644 index 0b67199b4ea..00000000000 --- a/src/server/game/Opcodes/Opcodes.cpp +++ /dev/null @@ -1,1338 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup u2w -*/ - -#include "Opcodes.h" -#include "WorldSession.h" - -/// Correspondence between opcodes and their names -OpcodeHandler opcodeTable[NUM_MSG_TYPES] = -{ - /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode }, - /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00D*/ { "CMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00E*/ { "SMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01E*/ { "SMSG_REFER_A_FRIEND_EXPIRED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x032*/ { "SMSG_DESTRUCTIBLE_BUILDING_DAMAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode }, - /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode }, - /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode }, - /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode }, - /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode }, - /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode }, - /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode }, - /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode }, - /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery }, - /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode }, - /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode }, - /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageTextQueryOpcode }, - /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode }, - /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode }, - /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode }, - /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode }, - /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode }, - /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleContactListOpcode }, - /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode }, - /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode }, - /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetContactNotesOpcode }, - /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode }, - /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode }, - /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode }, - /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode }, - /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode }, - /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteOpcode }, - /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode }, - /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode }, - /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode }, - /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupDisbandOpcode }, - /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode }, - /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode }, - /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode }, - /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode }, - /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode }, - /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode }, - /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode }, - /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode }, - /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode }, - /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode }, - /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode }, - /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode }, - /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode }, - /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode }, - /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleJoinChannel }, - /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleLeaveChannel }, - /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList }, - /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword }, - /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner }, - /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner }, - /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator }, - /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator }, - /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute }, - /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute }, - /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite }, - /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick }, - /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan }, - /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban }, - /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnouncements }, - /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate }, - /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode }, - /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode }, - /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem }, - /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode }, - /*0x0B2*/ { "CMSG_DESTROY_ITEMS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode }, - /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, - /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER, &WorldSession::HandleMoveWorldportAckOpcode }, - /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, - /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, - /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, - /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, - /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera }, - /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinematic }, - /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag }, - /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear }, - /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset }, - /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode }, - /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode }, - /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode }, - /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode }, - /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode }, - /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode }, - /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem }, - /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode }, - /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode }, - /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode }, - /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode }, - /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode }, - /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode }, - /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode }, - /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode }, - /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode }, - /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode }, - /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode }, - /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, &WorldSession::HandleCancelTradeOpcode}, - /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode }, - /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode }, - /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode }, - /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar }, - /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat }, - /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode }, - /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode }, - /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode }, - /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode }, - /*0x137*/ { "SMSG_EQUIPMENT_SET_SAVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling }, - /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode }, - /*0x13E*/ { "CMSG_EQUIPMENT_SET_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetDelete }, - /*0x13F*/ { "CMSG_INSTANCE_LOCK_WARNING_RESPONSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode }, - /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode }, - /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x147*/ { "SMSG_INSTANCE_LOCK_WARNING_QUERY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14B*/ { "SMSG_BATTLEFIELD_PORT_DENIED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x152*/ { "SMSG_BREAK_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode }, - /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode }, - /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode }, - /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode }, - /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode }, - /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode }, - /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode }, - /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode }, - /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction }, - /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction }, - /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon }, - /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename }, - /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode }, - /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode }, - /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode }, - /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode}, - /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode }, - /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQueryQuestOpcode}, - /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestAutoLaunch }, - /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode}, - /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCompleteQuest }, - /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode}, - /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode}, - /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel }, - /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest }, - /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest }, - /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept }, - /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandlePushQuestToParty }, - /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode }, - /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode }, - /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode }, - /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode }, - /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode }, - /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes }, - /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode }, - /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode }, - /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode }, - /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode }, - /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode }, - /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode }, - /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode }, - /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode }, - /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode }, - /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode }, - /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode }, - /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode }, - /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode }, - /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode }, - /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode }, - /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime }, - /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode }, - /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleReclaimCorpseOpcode }, - /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode }, - /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode }, - /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode }, - /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E3*/ { "CMSG_QUEST_POI_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPOIQuery }, - /*0x1E4*/ { "SMSG_QUEST_POI_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandlePetCastSpellOpcode }, - /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleSaveGuildEmblemOpcode }, - /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode}, - /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode }, - /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode }, - /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1FD*/ { "CMSG_PLAYER_DIFFICULTY_CHANGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1FF*/ { "SMSG_LFG_PLAYER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x200*/ { "SMSG_LFG_TELEPORT_DENIED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode }, - /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode }, - /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateOpcode }, - /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleRequestAccountData }, - /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleUpdateAccountData }, - /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20E*/ { "SMSG_PLAYER_DIFFICULTY_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode }, - /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode }, - /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode }, - /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode}, - /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode}, - /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x21E*/ { "SMSG_SET_REST_START_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode }, - /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode }, - /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode }, - /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode }, - /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode }, - /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode }, - /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail }, - /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMailList }, - /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldListOpcode }, - /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery }, - /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleMailTakeMoney }, - /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailTakeItem }, - /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMailMarkAsRead }, - /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleMailReturnToSender }, - /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete }, - /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem }, - /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode }, - /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP }, - /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode }, - /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem }, - /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem }, - /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems }, - /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems }, - /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid }, - /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems }, - /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode }, - /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, - /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode }, - /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode}, - /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, - /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet }, - /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet }, - /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot }, - /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet }, - /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet }, - /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult }, - /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode }, - /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode }, - /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode }, - /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode}, - /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode }, - /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode }, - /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryNextMailTime }, - /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleGroupRaidConvertOpcode }, - /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantLeaderOpcode}, - /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem }, - /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x292*/ { "CMSG_SET_SAVED_INSTANCE_EXTEND", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x293*/ { "SMSG_LFG_OFFER_CONTINUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo }, - /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode }, - /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, - /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode }, - /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode }, - /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeConfirmOpcode }, - /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode }, - /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode }, - /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B9*/ { "CMSG_SHOWING_HELM", STATUS_LOGGEDIN, &WorldSession::HandleShowingHelmOpcode }, - /*0x2BA*/ { "CMSG_SHOWING_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleShowingCloakOpcode }, - /*0x2BB*/ { "SMSG_LFG_ROLE_CHOSEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBarToggles }, - /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode }, - /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode }, - /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleCharRenameOpcode }, - /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleMoveSplineDoneOpcode }, - /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode }, - /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode }, - /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck }, - /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, - /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleMoveNotActiveMover }, - /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode }, - /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleFieldPortOpcode }, - /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode }, - /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattlemasterHelloOpcode }, - /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandlePVPLogDataOpcode }, - /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleLeaveBattlefieldOpcode }, - /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode}, - /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode}, - /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode }, - /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode}, - /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattlemasterJoinOpcode }, - /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode }, - /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoTextOpcode }, - /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiExpressOpcode }, - /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionInactiveOpcode }, - /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionOpcode }, - /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode }, - /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidTargetUpdateOpcode }, - /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode }, - /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleSetDungeonDifficultyOpcode}, - /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_NEVER, &WorldSession::Handle_NULL },//LOGGEDIN, &WorldSession::HandleGMSurveySubmit }, - /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveSetCanFlyAckOpcode }, - /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode }, - /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode }, - /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode }, - /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteOpcode }, - /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAcceptOpcode }, - /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDeclineOpcode }, - /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode }, - /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveOpcode }, - /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode }, - /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaderOpcode }, - /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattlemasterJoinArena }, - /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x35C*/ { "CMSG_LFG_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgJoinOpcode }, - /*0x35D*/ { "CMSG_LFG_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleLfgLeaveOpcode }, - /*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x35F*/ { "CMSG_SEARCH_LFG_LEAVE", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x360*/ { "SMSG_UPDATE_LFG_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x361*/ { "SMSG_LFG_PROPOSAL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x362*/ { "CMSG_LFG_PROPOSAL_RESULT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x363*/ { "SMSG_LFG_ROLE_CHECK_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x364*/ { "SMSG_LFG_JOIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x365*/ { "SMSG_LFG_QUEUE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgCommentOpcode }, - /*0x367*/ { "SMSG_LFG_UPDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x368*/ { "SMSG_LFG_UPDATE_PARTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x369*/ { "SMSG_LFG_UPDATE_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36A*/ { "CMSG_LFG_SET_ROLES", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetRolesOpcode }, - /*0x36B*/ { "CMSG_LFG_SET_NEEDS", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x36C*/ { "CMSG_LFG_SET_BOOT_VOTE", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x36D*/ { "SMSG_LFG_BOOT_PROPOSAL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36E*/ { "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLfgPlayerLockInfoRequestOpcode}, - /*0x36F*/ { "SMSG_LFG_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x370*/ { "CMSG_LFG_TELEPORT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x371*/ { "CMSG_LFD_PARTY_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLfgPartyLockInfoRequestOpcode}, - /*0x372*/ { "SMSG_LFG_PARTY_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleSetTitleOpcode }, - /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelMountAuraOpcode }, - /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaTeamsOpcode }, - /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempEnchantmentOpcode}, - /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode }, - /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmSplitOpcode }, - /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandlePartyAssignmentOpcode }, - /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleTimeSyncResp }, - /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSessionEnableOpcode }, - /*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B1*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B2*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B3*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B4*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B5*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B6*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B7*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B8*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B9*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BA*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3BB*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3BC*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BD*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BE*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BF*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C0*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C1*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C3*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C4*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C5*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C6*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishedOpcode}, - /*0x3C7*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleComplainOpcode }, - /*0x3C8*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C9*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3CA*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CB*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CD*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CF*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D0*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D1*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D2*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelDisplayListQuery }, - /*0x3D3*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleSetActiveVoiceChannel }, - /*0x3D4*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleGetChannelMemberCount }, - /*0x3D5*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3D6*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelVoiceOnOpcode }, - /*0x3D7*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D8*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D9*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3DA*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3DB*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DC*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DD*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DE*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DF*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3E0*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E1*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E2*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E3*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E4*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleReportPvPAFK }, - /*0x3E5*/ { "SMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3E6*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankerActivate }, - /*0x3E7*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQueryTab }, - /*0x3E8*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E9*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSwapItems }, - /*0x3EA*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab }, - /*0x3EB*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankUpdateTab }, - /*0x3EC*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositMoney }, - /*0x3ED*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdrawMoney }, - /*0x3EE*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLogQuery }, - /*0x3EF*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleSetChannelWatch }, - /*0x3F0*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F1*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F2*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F3*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3F4*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F5*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F6*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F7*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3F8*/ { "CMSG_SPELLCLICK", STATUS_LOGGEDIN, &WorldSession::HandleSpellClick }, - /*0x3F9*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3FA*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3FB*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3FC*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3FD*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildPermissions }, - /*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankMoneyWithdrawn }, - /*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogQueryOpcode }, - /*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_LOGGEDIN, &WorldSession::HandleMirrrorImageDataRequest }, - /*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x405*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x406*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x407*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x408*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x409*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleOptOutOfLootOpcode }, - /*0x40A*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleQueryGuildBankTabText }, - /*0x40B*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleSetGuildBankTabText }, - /*0x40C*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40D*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40E*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40F*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelDeclineInvite }, - /*0x410*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x411*/ { "SMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x412*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x413*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x414*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroyed }, - /*0x415*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x416*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x417*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusMultipleQuery}, - /*0x418*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x419*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleSetPlayerDeclinedNames }, - /*0x41A*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41B*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x41C*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x41D*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41E*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41F*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x420*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x421*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x422*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x423*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x424*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x425*/ { "CMSG_CHANGE_PERSONAL_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x426*/ { "CMSG_ALTER_APPEARANCE", STATUS_LOGGEDIN, &WorldSession::HandleAlterAppearance }, - /*0x427*/ { "SMSG_ENABLE_BARBER_SHOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x428*/ { "SMSG_BARBER_SHOP_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x429*/ { "CMSG_CALENDAR_GET_CALENDAR", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetCalendar }, - /*0x42A*/ { "CMSG_CALENDAR_GET_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetEvent }, - /*0x42B*/ { "CMSG_CALENDAR_GUILD_FILTER", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGuildFilter }, - /*0x42C*/ { "CMSG_CALENDAR_ARENA_TEAM", STATUS_LOGGEDIN, &WorldSession::HandleCalendarArenaTeam }, - /*0x42D*/ { "CMSG_CALENDAR_ADD_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarAddEvent }, - /*0x42E*/ { "CMSG_CALENDAR_UPDATE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarUpdateEvent }, - /*0x42F*/ { "CMSG_CALENDAR_REMOVE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarRemoveEvent }, - /*0x430*/ { "CMSG_CALENDAR_COPY_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarCopyEvent }, - /*0x431*/ { "CMSG_CALENDAR_EVENT_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventInvite }, - /*0x432*/ { "CMSG_CALENDAR_EVENT_RSVP", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRsvp }, - /*0x433*/ { "CMSG_CALENDAR_EVENT_REMOVE_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRemoveInvite }, - /*0x434*/ { "CMSG_CALENDAR_EVENT_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventStatus }, - /*0x435*/ { "CMSG_CALENDAR_EVENT_MODERATOR_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventModeratorStatus}, - /*0x436*/ { "SMSG_CALENDAR_SEND_CALENDAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x437*/ { "SMSG_CALENDAR_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x438*/ { "SMSG_CALENDAR_FILTER_GUILD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x439*/ { "SMSG_CALENDAR_ARENA_TEAM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x43A*/ { "SMSG_CALENDAR_EVENT_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x43B*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x43C*/ { "SMSG_CALENDAR_EVENT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x43D*/ { "SMSG_CALENDAR_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x43E*/ { "SMSG_CALENDAR_RAID_LOCKOUT_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x43F*/ { "SMSG_CALENDAR_RAID_LOCKOUT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x440*/ { "SMSG_CALENDAR_EVENT_INVITE_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x441*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x442*/ { "SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x443*/ { "SMSG_CALENDAR_EVENT_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x444*/ { "SMSG_CALENDAR_EVENT_UPDATED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x445*/ { "SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x446*/ { "CMSG_CALENDAR_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleCalendarComplain }, - /*0x447*/ { "CMSG_CALENDAR_GET_NUM_PENDING", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetNumPending }, - /*0x448*/ { "SMSG_CALENDAR_SEND_NUM_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x449*/ { "CMSG_SAVE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x44A*/ { "SMSG_NOTIFY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x44B*/ { "CMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x44C*/ { "SMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x44D*/ { "CMSG_LOAD_DANCES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x44E*/ { "CMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x44F*/ { "SMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x450*/ { "CMSG_SYNC_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x451*/ { "CMSG_DANCE_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x452*/ { "SMSG_DANCE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x453*/ { "SMSG_INVALIDATE_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x454*/ { "CMSG_DELETE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x455*/ { "SMSG_LEARNED_DANCE_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x456*/ { "CMSG_LEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x457*/ { "CMSG_UNLEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x458*/ { "CMSG_SET_RUNE_COUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x459*/ { "CMSG_SET_RUNE_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x45A*/ { "MSG_MOVE_SET_PITCH_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x45B*/ { "MSG_MOVE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x45C*/ { "SMSG_FORCE_PITCH_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x45F*/ { "SMSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x460*/ { "MSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x461*/ { "CMSG_MOVE_ABANDON_TRANSPORT_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x466*/ { "CMSG_SET_GLYPH_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x467*/ { "CMSG_SET_GLYPH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x468*/ { "SMSG_ACHIEVEMENT_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x469*/ { "SMSG_DYNAMIC_DROP_ROLL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x46A*/ { "SMSG_CRITERIA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x46B*/ { "CMSG_QUERY_INSPECT_ACHIEVEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleQueryInspectAchievements }, - /*0x46C*/ { "SMSG_RESPOND_INSPECT_ACHIEVEMENTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x46D*/ { "CMSG_DISMISS_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleDismissControlledVehicle }, - /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x471*/ { "SMSG_GROUP_SWAP_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize }, - /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_LOGGEDIN, &WorldSession::HandleRequestVehicleExit }, - /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, - /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, - /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, - /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandlePetLearnTalent }, - /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x47D*/ { "SMSG_ALL_ACHIEVEMENT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x47E*/ { "CMSG_FORCE_SAY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x47F*/ { "SMSG_HEALTH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x480*/ { "SMSG_POWER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x481*/ { "CMSG_GAMEOBJ_REPORT_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameobjectReportUse }, - /*0x482*/ { "SMSG_HIGHEST_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x483*/ { "SMSG_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x484*/ { "SMSG_THREAT_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x485*/ { "SMSG_THREAT_CLEAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x486*/ { "SMSG_CONVERT_RUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x487*/ { "SMSG_RESYNC_RUNES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x488*/ { "SMSG_ADD_RUNE_POWER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x489*/ { "CMSG_START_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x48A*/ { "CMSG_REMOVE_GLYPH", STATUS_LOGGEDIN, &WorldSession::HandleRemoveGlyph }, - /*0x48B*/ { "CMSG_DUMP_OBJECTS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x48C*/ { "SMSG_DUMP_OBJECTS_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x48D*/ { "CMSG_DISMISS_CRITTER", STATUS_LOGGEDIN, &WorldSession::HandleDismissCritter }, - /*0x48E*/ { "SMSG_NOTIFY_DEST_LOC_SPELL_CAST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x48F*/ { "CMSG_AUCTION_LIST_PENDING_SALES", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListPendingSales }, - /*0x490*/ { "SMSG_AUCTION_LIST_PENDING_SALES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x491*/ { "SMSG_MODIFY_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x492*/ { "SMSG_PET_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x493*/ { "CMSG_ENABLETAXI", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes }, - /*0x494*/ { "SMSG_PRE_RESURRECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x495*/ { "SMSG_AURA_UPDATE_ALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x496*/ { "SMSG_AURA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x497*/ { "CMSG_FLOOD_GRACE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, - /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49F*/ { "SMSG_ACHIEVEMENT_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4A0*/ { "CMSG_SERVER_INFO_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A1*/ { "SMSG_SERVER_INFO_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4A2*/ { "CMSG_CHECK_LOGIN_CRITERIA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A3*/ { "SMSG_SERVER_BUCK_DATA_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4A4*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A5*/ { "UMSG_UNKNOWN_1189", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A6*/ { "SMSG_BATTLEGROUND_INFO_THROTTLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4A7*/ { "SMSG_PLAYER_VEHICLE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4A8*/ { "CMSG_PLAYER_VEHICLE_ENTER", STATUS_LOGGEDIN, &WorldSession::HandleEnterPlayerVehicle }, - /*0x4A9*/ { "CMSG_EJECT_PASSENGER", STATUS_LOGGEDIN, &WorldSession::HandleEjectPasenger }, - /*0x4AA*/ { "SMSG_PET_GUIDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4AB*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4AC*/ { "UMSG_UNKNOWN_1196", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4AD*/ { "UMSG_UNKNOWN_1197", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4AE*/ { "UMSG_UNKNOWN_1198", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4AF*/ { "UMSG_UNKNOWN_1199", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4B0*/ { "UMSG_UNKNOWN_1200", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4B1*/ { "UMSG_UNKNOWN_1201", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4B2*/ { "SMSG_ITEM_REFUND_INFO_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4B3*/ { "CMSG_ITEM_REFUND_INFO", STATUS_LOGGEDIN, &WorldSession::HandleItemRefundInfoRequest }, - /*0x4B4*/ { "CMSG_ITEM_REFUND", STATUS_LOGGEDIN, &WorldSession::HandleItemRefund }, - /*0x4B5*/ { "SMSG_ITEM_REFUND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4B6*/ { "CMSG_CORPSE_MAP_POSITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseMapPositionQuery }, - /*0x4B7*/ { "SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4B8*/ { "CMSG_LFG_SET_ROLES_2", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x4B9*/ { "UMSG_UNKNOWN_1209", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4BA*/ { "CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4BB*/ { "SMSG_CALENDAR_ACTION_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4BC*/ { "SMSG_EQUIPMENT_SET_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4BD*/ { "CMSG_EQUIPMENT_SET_SAVE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetSave }, - /*0x4BE*/ { "CMSG_UPDATE_PROJECTILE_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4BF*/ { "SMSG_SET_PROJECTILE_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4C0*/ { "SMSG_TALENTS_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4C1*/ { "CMSG_LEARN_PREVIEW_TALENTS", STATUS_LOGGEDIN, &WorldSession::HandleLearnPreviewTalents }, - /*0x4C2*/ { "CMSG_LEARN_PREVIEW_TALENTS_PET", STATUS_LOGGEDIN, &WorldSession::HandleLearnPreviewTalentsPet }, - /*0x4C3*/ { "UMSG_UNKNOWN_1219", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4C4*/ { "UMSG_UNKNOWN_1220", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4C5*/ { "UMSG_UNKNOWN_1221", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4C6*/ { "UMSG_UNKNOWN_1222", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4C7*/ { "SMSG_ARENA_OPPONENT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4C8*/ { "SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4C9*/ { "UMSG_UNKNOWN_1225", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4CA*/ { "UMSG_UNKNOWN_1226", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4CB*/ { "UMSG_UNKNOWN_1227", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4CC*/ { "UMSG_UNKNOWN_1228", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4CD*/ { "SMSG_MULTIPLE_PACKETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4CE*/ { "SMSG_UNKNOWN_1230", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4CF*/ { "CMSG_UNKNOWN_1231_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4D0*/ { "SMSG_UNKNOWN_1232", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4D1*/ { "CMSG_UNKNOWN_1233_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4D2*/ { "SMSG_UNKNOWN_1234", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4D3*/ { "SMSG_UNKNOWN_1235", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4D4*/ { "SMSG_UNKNOWN_1236", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4D5*/ { "CMSG_EQUIPMENT_SET_USE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetUse }, - /*0x4D6*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4D7*/ { "UMSG_UNKNOWN_1239", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4D8*/ { "SMSG_UNKNOWN_1240", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4D9*/ { "CMSG_CHAR_FACTION_CHANGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4DA*/ { "SMSG_CHAR_FACTION_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4DB*/ { "UMSG_UNKNOWN_1243", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4DC*/ { "UMSG_UNKNOWN_1244", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4DD*/ { "UMSG_UNKNOWN_1245", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4DE*/ { "SMSG_BATTLEFIELD_MGR_ENTRY_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4E0*/ { "SMSG_BATTLEFIELD_MGR_ENTERED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4E1*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4E2*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4E3*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4E4*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4E5*/ { "SMSG_BATTLEFIELD_MGR_EJECT_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4E6*/ { "SMSG_BATTLEFIELD_MGR_EJECTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4E7*/ { "CMSG_BATTLEFIELD_MGR_EXIT_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4E8*/ { "SMSG_BATTLEFIELD_MGR_STATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4E9*/ { "UMSG_UNKNOWN_1257", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4EA*/ { "UMSG_UNKNOWN_1258", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4EB*/ { "MSG_SET_RAID_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleSetRaidDifficultyOpcode }, - /*0x4EC*/ { "UMSG_UNKNOWN_1260", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4ED*/ { "SMSG_TOGGLE_XP_GAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4EE*/ { "SMSG_GMRESPONSE_DB_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4EF*/ { "SMSG_GMRESPONSE_RECEIVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4F0*/ { "CMSG_GMRESPONSE_RESOLVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4F1*/ { "SMSG_GMRESPONSE_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4F2*/ { "UMSG_UNKNOWN_1266", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4F3*/ { "UMSG_UNKNOWN_1267", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4F4*/ { "UMSG_UNKNOWN_1268", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4F5*/ { "UMSG_UNKNOWN_1269", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4F6*/ { "CMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleWorldStateUITimerUpdate }, - /*0x4F7*/ { "SMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4F8*/ { "CMSG_CHAR_RACE_CHANGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4F9*/ { "UMSG_UNKNOWN_1273", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4FA*/ { "SMSG_TALENTS_INVOLUNTARILY_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4FB*/ { "UMSG_UNKNOWN_1275", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4FC*/ { "SMSG_UNKNOWN_1276", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4FD*/ { "SMSG_LOOT_SLOT_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4FE*/ { "UMSG_UNKNOWN_1278", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4FF*/ { "CMSG_READY_FOR_ACCOUNT_DATA_TIMES", STATUS_AUTHED, &WorldSession::HandleReadyForAccountDataTimes }, - /*0x500*/ { "CMSG_QUERY_QUESTS_COMPLETED", STATUS_LOGGEDIN, &WorldSession::HandleQueryQuestsCompleted }, - /*0x501*/ { "SMSG_QUERY_QUESTS_COMPLETED_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x502*/ { "CMSG_GM_REPORT_LAG", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x503*/ { "UMSG_UNKNOWN_1283", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x504*/ { "UMSG_UNKNOWN_1284", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x505*/ { "UMSG_UNKNOWN_1285", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x506*/ { "SMSG_CORPSE_NOT_IN_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x507*/ { "UMSG_UNKNOWN_1287", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x508*/ { "CMSG_SET_ALLOW_LOW_LEVEL_RAID1", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x509*/ { "CMSG_SET_ALLOW_LOW_LEVEL_RAID2", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x50A*/ { "SMSG_CAMERA_SHAKE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x50B*/ { "SMSG_UPDATE_ITEM_ENCHANTMENTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x50C*/ { "UMSG_UNKNOWN_1292", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x50D*/ { "SMSG_REDIRECT_CLIENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x50E*/ { "CMSG_REDIRECTION_FAILED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x50F*/ { "SMSG_UNKNOWN_1295", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x510*/ { "CMSG_UNKNOWN_1296", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x511*/ { "SMSG_FORCE_SEND_QUEUED_PACKETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x512*/ { "CMSG_REDIRECTION_AUTH_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x513*/ { "UMSG_UNKNOWN_1299", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x514*/ { "SMSG_COMBAT_LOG_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x515*/ { "SMSG_LFG_OPEN_FROM_GOSSIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x516*/ { "SMSG_UNKNOWN_1302", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x517*/ { "CMSG_UNKNOWN_1303", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x518*/ { "SMSG_UNKNOWN_1304", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x519*/ { "UMSG_UNKNOWN_1305", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x51A*/ { "UMSG_UNKNOWN_1306", STATUS_NEVER, &WorldSession::Handle_NULL }, -}; diff --git a/src/server/game/Opcodes/Opcodes.h b/src/server/game/Opcodes/Opcodes.h deleted file mode 100644 index 4ae6931c3f5..00000000000 --- a/src/server/game/Opcodes/Opcodes.h +++ /dev/null @@ -1,1378 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup u2w -/// @{ -/// \file - -#ifndef _OPCODES_H -#define _OPCODES_H - -#include "Common.h" - -// Note: this include need for be sure have full definition of class WorldSession -// if this class definition not complite then VS for x64 release use different size for -// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from -// table opcodeTable in source when Opcode.h included but WorldSession.h not included -#include "WorldSession.h" - -/// List of Opcodes -enum Opcodes -{ - MSG_NULL_ACTION = 0x000, - CMSG_BOOTME = 0x001, - CMSG_DBLOOKUP = 0x002, - SMSG_DBLOOKUP = 0x003, - CMSG_QUERY_OBJECT_POSITION = 0x004, - SMSG_QUERY_OBJECT_POSITION = 0x005, - CMSG_QUERY_OBJECT_ROTATION = 0x006, - SMSG_QUERY_OBJECT_ROTATION = 0x007, - CMSG_WORLD_TELEPORT = 0x008, - CMSG_TELEPORT_TO_UNIT = 0x009, - CMSG_ZONE_MAP = 0x00A, - SMSG_ZONE_MAP = 0x00B, - CMSG_DEBUG_CHANGECELLZONE = 0x00C, - CMSG_MOVE_CHARACTER_CHEAT = 0x00D, - SMSG_MOVE_CHARACTER_CHEAT = 0x00E, - CMSG_RECHARGE = 0x00F, - CMSG_LEARN_SPELL = 0x010, - CMSG_CREATEMONSTER = 0x011, - CMSG_DESTROYMONSTER = 0x012, - CMSG_CREATEITEM = 0x013, - CMSG_CREATEGAMEOBJECT = 0x014, - SMSG_CHECK_FOR_BOTS = 0x015, - CMSG_MAKEMONSTERATTACKGUID = 0x016, - CMSG_BOT_DETECTED2 = 0x017, - CMSG_FORCEACTION = 0x018, - CMSG_FORCEACTIONONOTHER = 0x019, - CMSG_FORCEACTIONSHOW = 0x01A, - SMSG_FORCEACTIONSHOW = 0x01B, - CMSG_PETGODMODE = 0x01C, - SMSG_PETGODMODE = 0x01D, - SMSG_REFER_A_FRIEND_EXPIRED = 0x01E, - CMSG_WEATHER_SPEED_CHEAT = 0x01F, - CMSG_UNDRESSPLAYER = 0x020, - CMSG_BEASTMASTER = 0x021, - CMSG_GODMODE = 0x022, - SMSG_GODMODE = 0x023, - CMSG_CHEAT_SETMONEY = 0x024, - CMSG_LEVEL_CHEAT = 0x025, - CMSG_PET_LEVEL_CHEAT = 0x026, - CMSG_SET_WORLDSTATE = 0x027, - CMSG_COOLDOWN_CHEAT = 0x028, - CMSG_USE_SKILL_CHEAT = 0x029, - CMSG_FLAG_QUEST = 0x02A, - CMSG_FLAG_QUEST_FINISH = 0x02B, - CMSG_CLEAR_QUEST = 0x02C, - CMSG_SEND_EVENT = 0x02D, - CMSG_DEBUG_AISTATE = 0x02E, - SMSG_DEBUG_AISTATE = 0x02F, - CMSG_DISABLE_PVP_CHEAT = 0x030, - CMSG_ADVANCE_SPAWN_TIME = 0x031, - SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x032, - CMSG_AUTH_SRP6_BEGIN = 0x033, - CMSG_AUTH_SRP6_PROOF = 0x034, - CMSG_AUTH_SRP6_RECODE = 0x035, - CMSG_CHAR_CREATE = 0x036, - CMSG_CHAR_ENUM = 0x037, - CMSG_CHAR_DELETE = 0x038, - SMSG_AUTH_SRP6_RESPONSE = 0x039, - SMSG_CHAR_CREATE = 0x03A, - SMSG_CHAR_ENUM = 0x03B, - SMSG_CHAR_DELETE = 0x03C, - CMSG_PLAYER_LOGIN = 0x03D, - SMSG_NEW_WORLD = 0x03E, - SMSG_TRANSFER_PENDING = 0x03F, - SMSG_TRANSFER_ABORTED = 0x040, - SMSG_CHARACTER_LOGIN_FAILED = 0x041, - SMSG_LOGIN_SETTIMESPEED = 0x042, - SMSG_GAMETIME_UPDATE = 0x043, - CMSG_GAMETIME_SET = 0x044, - SMSG_GAMETIME_SET = 0x045, - CMSG_GAMESPEED_SET = 0x046, - SMSG_GAMESPEED_SET = 0x047, - CMSG_SERVERTIME = 0x048, - SMSG_SERVERTIME = 0x049, - CMSG_PLAYER_LOGOUT = 0x04A, - CMSG_LOGOUT_REQUEST = 0x04B, - SMSG_LOGOUT_RESPONSE = 0x04C, - SMSG_LOGOUT_COMPLETE = 0x04D, - CMSG_LOGOUT_CANCEL = 0x04E, - SMSG_LOGOUT_CANCEL_ACK = 0x04F, - CMSG_NAME_QUERY = 0x050, - SMSG_NAME_QUERY_RESPONSE = 0x051, - CMSG_PET_NAME_QUERY = 0x052, - SMSG_PET_NAME_QUERY_RESPONSE = 0x053, - CMSG_GUILD_QUERY = 0x054, - SMSG_GUILD_QUERY_RESPONSE = 0x055, - CMSG_ITEM_QUERY_SINGLE = 0x056, - CMSG_ITEM_QUERY_MULTIPLE = 0x057, - SMSG_ITEM_QUERY_SINGLE_RESPONSE = 0x058, - SMSG_ITEM_QUERY_MULTIPLE_RESPONSE = 0x059, - CMSG_PAGE_TEXT_QUERY = 0x05A, - SMSG_PAGE_TEXT_QUERY_RESPONSE = 0x05B, - CMSG_QUEST_QUERY = 0x05C, - SMSG_QUEST_QUERY_RESPONSE = 0x05D, - CMSG_GAMEOBJECT_QUERY = 0x05E, - SMSG_GAMEOBJECT_QUERY_RESPONSE = 0x05F, - CMSG_CREATURE_QUERY = 0x060, - SMSG_CREATURE_QUERY_RESPONSE = 0x061, - CMSG_WHO = 0x062, - SMSG_WHO = 0x063, - CMSG_WHOIS = 0x064, - SMSG_WHOIS = 0x065, - CMSG_CONTACT_LIST = 0x066, - SMSG_CONTACT_LIST = 0x067, - SMSG_FRIEND_STATUS = 0x068, - CMSG_ADD_FRIEND = 0x069, - CMSG_DEL_FRIEND = 0x06A, - CMSG_SET_CONTACT_NOTES = 0x06B, - CMSG_ADD_IGNORE = 0x06C, - CMSG_DEL_IGNORE = 0x06D, - CMSG_GROUP_INVITE = 0x06E, - SMSG_GROUP_INVITE = 0x06F, - CMSG_GROUP_CANCEL = 0x070, - SMSG_GROUP_CANCEL = 0x071, - CMSG_GROUP_ACCEPT = 0x072, - CMSG_GROUP_DECLINE = 0x073, - SMSG_GROUP_DECLINE = 0x074, - CMSG_GROUP_UNINVITE = 0x075, - CMSG_GROUP_UNINVITE_GUID = 0x076, - SMSG_GROUP_UNINVITE = 0x077, - CMSG_GROUP_SET_LEADER = 0x078, - SMSG_GROUP_SET_LEADER = 0x079, - CMSG_LOOT_METHOD = 0x07A, - CMSG_GROUP_DISBAND = 0x07B, - SMSG_GROUP_DESTROYED = 0x07C, - SMSG_GROUP_LIST = 0x07D, - SMSG_PARTY_MEMBER_STATS = 0x07E, - SMSG_PARTY_COMMAND_RESULT = 0x07F, - UMSG_UPDATE_GROUP_MEMBERS = 0x080, - CMSG_GUILD_CREATE = 0x081, - CMSG_GUILD_INVITE = 0x082, - SMSG_GUILD_INVITE = 0x083, - CMSG_GUILD_ACCEPT = 0x084, - CMSG_GUILD_DECLINE = 0x085, - SMSG_GUILD_DECLINE = 0x086, - CMSG_GUILD_INFO = 0x087, - SMSG_GUILD_INFO = 0x088, - CMSG_GUILD_ROSTER = 0x089, - SMSG_GUILD_ROSTER = 0x08A, - CMSG_GUILD_PROMOTE = 0x08B, - CMSG_GUILD_DEMOTE = 0x08C, - CMSG_GUILD_LEAVE = 0x08D, - CMSG_GUILD_REMOVE = 0x08E, - CMSG_GUILD_DISBAND = 0x08F, - CMSG_GUILD_LEADER = 0x090, - CMSG_GUILD_MOTD = 0x091, - SMSG_GUILD_EVENT = 0x092, - SMSG_GUILD_COMMAND_RESULT = 0x093, - UMSG_UPDATE_GUILD = 0x094, - CMSG_MESSAGECHAT = 0x095, - SMSG_MESSAGECHAT = 0x096, - CMSG_JOIN_CHANNEL = 0x097, - CMSG_LEAVE_CHANNEL = 0x098, - SMSG_CHANNEL_NOTIFY = 0x099, - CMSG_CHANNEL_LIST = 0x09A, - SMSG_CHANNEL_LIST = 0x09B, - CMSG_CHANNEL_PASSWORD = 0x09C, - CMSG_CHANNEL_SET_OWNER = 0x09D, - CMSG_CHANNEL_OWNER = 0x09E, - CMSG_CHANNEL_MODERATOR = 0x09F, - CMSG_CHANNEL_UNMODERATOR = 0x0A0, - CMSG_CHANNEL_MUTE = 0x0A1, - CMSG_CHANNEL_UNMUTE = 0x0A2, - CMSG_CHANNEL_INVITE = 0x0A3, - CMSG_CHANNEL_KICK = 0x0A4, - CMSG_CHANNEL_BAN = 0x0A5, - CMSG_CHANNEL_UNBAN = 0x0A6, - CMSG_CHANNEL_ANNOUNCEMENTS = 0x0A7, - CMSG_CHANNEL_MODERATE = 0x0A8, - SMSG_UPDATE_OBJECT = 0x0A9, - SMSG_DESTROY_OBJECT = 0x0AA, - CMSG_USE_ITEM = 0x0AB, - CMSG_OPEN_ITEM = 0x0AC, - CMSG_READ_ITEM = 0x0AD, - SMSG_READ_ITEM_OK = 0x0AE, - SMSG_READ_ITEM_FAILED = 0x0AF, - SMSG_ITEM_COOLDOWN = 0x0B0, - CMSG_GAMEOBJ_USE = 0x0B1, - CMSG_DESTROY_ITEMS = 0x0B2, - SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3, - CMSG_AREATRIGGER = 0x0B4, - MSG_MOVE_START_FORWARD = 0x0B5, - MSG_MOVE_START_BACKWARD = 0x0B6, - MSG_MOVE_STOP = 0x0B7, - MSG_MOVE_START_STRAFE_LEFT = 0x0B8, - MSG_MOVE_START_STRAFE_RIGHT = 0x0B9, - MSG_MOVE_STOP_STRAFE = 0x0BA, - MSG_MOVE_JUMP = 0x0BB, - MSG_MOVE_START_TURN_LEFT = 0x0BC, - MSG_MOVE_START_TURN_RIGHT = 0x0BD, - MSG_MOVE_STOP_TURN = 0x0BE, - MSG_MOVE_START_PITCH_UP = 0x0BF, - MSG_MOVE_START_PITCH_DOWN = 0x0C0, - MSG_MOVE_STOP_PITCH = 0x0C1, - MSG_MOVE_SET_RUN_MODE = 0x0C2, - MSG_MOVE_SET_WALK_MODE = 0x0C3, - MSG_MOVE_TOGGLE_LOGGING = 0x0C4, - MSG_MOVE_TELEPORT = 0x0C5, - MSG_MOVE_TELEPORT_CHEAT = 0x0C6, - MSG_MOVE_TELEPORT_ACK = 0x0C7, - MSG_MOVE_TOGGLE_FALL_LOGGING = 0x0C8, - MSG_MOVE_FALL_LAND = 0x0C9, - MSG_MOVE_START_SWIM = 0x0CA, - MSG_MOVE_STOP_SWIM = 0x0CB, - MSG_MOVE_SET_RUN_SPEED_CHEAT = 0x0CC, - MSG_MOVE_SET_RUN_SPEED = 0x0CD, - MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT = 0x0CE, - MSG_MOVE_SET_RUN_BACK_SPEED = 0x0CF, - MSG_MOVE_SET_WALK_SPEED_CHEAT = 0x0D0, - MSG_MOVE_SET_WALK_SPEED = 0x0D1, - MSG_MOVE_SET_SWIM_SPEED_CHEAT = 0x0D2, - MSG_MOVE_SET_SWIM_SPEED = 0x0D3, - MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT = 0x0D4, - MSG_MOVE_SET_SWIM_BACK_SPEED = 0x0D5, - MSG_MOVE_SET_ALL_SPEED_CHEAT = 0x0D6, - MSG_MOVE_SET_TURN_RATE_CHEAT = 0x0D7, - MSG_MOVE_SET_TURN_RATE = 0x0D8, - MSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x0D9, - MSG_MOVE_SET_FACING = 0x0DA, - MSG_MOVE_SET_PITCH = 0x0DB, - MSG_MOVE_WORLDPORT_ACK = 0x0DC, - SMSG_MONSTER_MOVE = 0x0DD, - SMSG_MOVE_WATER_WALK = 0x0DE, - SMSG_MOVE_LAND_WALK = 0x0DF, - MSG_MOVE_SET_RAW_POSITION_ACK = 0x0E0, - CMSG_MOVE_SET_RAW_POSITION = 0x0E1, - SMSG_FORCE_RUN_SPEED_CHANGE = 0x0E2, - CMSG_FORCE_RUN_SPEED_CHANGE_ACK = 0x0E3, - SMSG_FORCE_RUN_BACK_SPEED_CHANGE = 0x0E4, - CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x0E5, - SMSG_FORCE_SWIM_SPEED_CHANGE = 0x0E6, - CMSG_FORCE_SWIM_SPEED_CHANGE_ACK = 0x0E7, - SMSG_FORCE_MOVE_ROOT = 0x0E8, - CMSG_FORCE_MOVE_ROOT_ACK = 0x0E9, - SMSG_FORCE_MOVE_UNROOT = 0x0EA, - CMSG_FORCE_MOVE_UNROOT_ACK = 0x0EB, - MSG_MOVE_ROOT = 0x0EC, - MSG_MOVE_UNROOT = 0x0ED, - MSG_MOVE_HEARTBEAT = 0x0EE, - SMSG_MOVE_KNOCK_BACK = 0x0EF, - CMSG_MOVE_KNOCK_BACK_ACK = 0x0F0, - MSG_MOVE_KNOCK_BACK = 0x0F1, - SMSG_MOVE_FEATHER_FALL = 0x0F2, - SMSG_MOVE_NORMAL_FALL = 0x0F3, - SMSG_MOVE_SET_HOVER = 0x0F4, - SMSG_MOVE_UNSET_HOVER = 0x0F5, - CMSG_MOVE_HOVER_ACK = 0x0F6, - MSG_MOVE_HOVER = 0x0F7, - CMSG_TRIGGER_CINEMATIC_CHEAT = 0x0F8, - CMSG_OPENING_CINEMATIC = 0x0F9, - SMSG_TRIGGER_CINEMATIC = 0x0FA, - CMSG_NEXT_CINEMATIC_CAMERA = 0x0FB, - CMSG_COMPLETE_CINEMATIC = 0x0FC, - SMSG_TUTORIAL_FLAGS = 0x0FD, - CMSG_TUTORIAL_FLAG = 0x0FE, - CMSG_TUTORIAL_CLEAR = 0x0FF, - CMSG_TUTORIAL_RESET = 0x100, - CMSG_STANDSTATECHANGE = 0x101, - CMSG_EMOTE = 0x102, - SMSG_EMOTE = 0x103, - CMSG_TEXT_EMOTE = 0x104, - SMSG_TEXT_EMOTE = 0x105, - CMSG_AUTOEQUIP_GROUND_ITEM = 0x106, - CMSG_AUTOSTORE_GROUND_ITEM = 0x107, - CMSG_AUTOSTORE_LOOT_ITEM = 0x108, - CMSG_STORE_LOOT_IN_SLOT = 0x109, - CMSG_AUTOEQUIP_ITEM = 0x10A, - CMSG_AUTOSTORE_BAG_ITEM = 0x10B, - CMSG_SWAP_ITEM = 0x10C, - CMSG_SWAP_INV_ITEM = 0x10D, - CMSG_SPLIT_ITEM = 0x10E, - CMSG_AUTOEQUIP_ITEM_SLOT = 0x10F, - OBSOLETE_DROP_ITEM = 0x110, - CMSG_DESTROYITEM = 0x111, - SMSG_INVENTORY_CHANGE_FAILURE = 0x112, - SMSG_OPEN_CONTAINER = 0x113, - CMSG_INSPECT = 0x114, - SMSG_INSPECT = 0x115, - CMSG_INITIATE_TRADE = 0x116, - CMSG_BEGIN_TRADE = 0x117, - CMSG_BUSY_TRADE = 0x118, - CMSG_IGNORE_TRADE = 0x119, - CMSG_ACCEPT_TRADE = 0x11A, - CMSG_UNACCEPT_TRADE = 0x11B, - CMSG_CANCEL_TRADE = 0x11C, - CMSG_SET_TRADE_ITEM = 0x11D, - CMSG_CLEAR_TRADE_ITEM = 0x11E, - CMSG_SET_TRADE_GOLD = 0x11F, - SMSG_TRADE_STATUS = 0x120, - SMSG_TRADE_STATUS_EXTENDED = 0x121, - SMSG_INITIALIZE_FACTIONS = 0x122, - SMSG_SET_FACTION_VISIBLE = 0x123, - SMSG_SET_FACTION_STANDING = 0x124, - CMSG_SET_FACTION_ATWAR = 0x125, - CMSG_SET_FACTION_CHEAT = 0x126, - SMSG_SET_PROFICIENCY = 0x127, - CMSG_SET_ACTION_BUTTON = 0x128, - SMSG_ACTION_BUTTONS = 0x129, - SMSG_INITIAL_SPELLS = 0x12A, - SMSG_LEARNED_SPELL = 0x12B, - SMSG_SUPERCEDED_SPELL = 0x12C, - CMSG_NEW_SPELL_SLOT = 0x12D, - CMSG_CAST_SPELL = 0x12E, - CMSG_CANCEL_CAST = 0x12F, - SMSG_CAST_FAILED = 0x130, - SMSG_SPELL_START = 0x131, - SMSG_SPELL_GO = 0x132, - SMSG_SPELL_FAILURE = 0x133, - SMSG_SPELL_COOLDOWN = 0x134, - SMSG_COOLDOWN_EVENT = 0x135, - CMSG_CANCEL_AURA = 0x136, - SMSG_EQUIPMENT_SET_SAVED = 0x137, - SMSG_PET_CAST_FAILED = 0x138, - MSG_CHANNEL_START = 0x139, - MSG_CHANNEL_UPDATE = 0x13A, - CMSG_CANCEL_CHANNELLING = 0x13B, - SMSG_AI_REACTION = 0x13C, - CMSG_SET_SELECTION = 0x13D, - CMSG_EQUIPMENT_SET_DELETE = 0x13E, - CMSG_INSTANCE_LOCK_WARNING_RESPONSE = 0x13F, - CMSG_UNUSED2 = 0x140, - CMSG_ATTACKSWING = 0x141, - CMSG_ATTACKSTOP = 0x142, - SMSG_ATTACKSTART = 0x143, - SMSG_ATTACKSTOP = 0x144, - SMSG_ATTACKSWING_NOTINRANGE = 0x145, - SMSG_ATTACKSWING_BADFACING = 0x146, - SMSG_INSTANCE_LOCK_WARNING_QUERY = 0x147, - SMSG_ATTACKSWING_DEADTARGET = 0x148, - SMSG_ATTACKSWING_CANT_ATTACK = 0x149, - SMSG_ATTACKERSTATEUPDATE = 0x14A, - SMSG_BATTLEFIELD_PORT_DENIED = 0x14B, - SMSG_DAMAGE_DONE_OBSOLETE = 0x14C, - SMSG_UNIT_SPELLCAST_START = 0x14D, - SMSG_CANCEL_COMBAT = 0x14E, - SMSG_SPELLBREAKLOG = 0x14F, - SMSG_SPELLHEALLOG = 0x150, - SMSG_SPELLENERGIZELOG = 0x151, - SMSG_BREAK_TARGET = 0x152, - CMSG_SAVE_PLAYER = 0x153, - CMSG_SETDEATHBINDPOINT = 0x154, - SMSG_BINDPOINTUPDATE = 0x155, - CMSG_GETDEATHBINDZONE = 0x156, - SMSG_BINDZONEREPLY = 0x157, - SMSG_PLAYERBOUND = 0x158, - SMSG_CLIENT_CONTROL_UPDATE = 0x159, - CMSG_REPOP_REQUEST = 0x15A, - SMSG_RESURRECT_REQUEST = 0x15B, - CMSG_RESURRECT_RESPONSE = 0x15C, - CMSG_LOOT = 0x15D, - CMSG_LOOT_MONEY = 0x15E, - CMSG_LOOT_RELEASE = 0x15F, - SMSG_LOOT_RESPONSE = 0x160, - SMSG_LOOT_RELEASE_RESPONSE = 0x161, - SMSG_LOOT_REMOVED = 0x162, - SMSG_LOOT_MONEY_NOTIFY = 0x163, - SMSG_LOOT_ITEM_NOTIFY = 0x164, - SMSG_LOOT_CLEAR_MONEY = 0x165, - SMSG_ITEM_PUSH_RESULT = 0x166, - SMSG_DUEL_REQUESTED = 0x167, - SMSG_DUEL_OUTOFBOUNDS = 0x168, - SMSG_DUEL_INBOUNDS = 0x169, - SMSG_DUEL_COMPLETE = 0x16A, - SMSG_DUEL_WINNER = 0x16B, - CMSG_DUEL_ACCEPTED = 0x16C, - CMSG_DUEL_CANCELLED = 0x16D, - SMSG_MOUNTRESULT = 0x16E, - SMSG_DISMOUNTRESULT = 0x16F, - SMSG_PUREMOUNT_CANCELLED_OBSOLETE = 0x170, // ERR_REMOVE_FROM_PVP_QUEUE_* events - CMSG_MOUNTSPECIAL_ANIM = 0x171, - SMSG_MOUNTSPECIAL_ANIM = 0x172, - SMSG_PET_TAME_FAILURE = 0x173, - CMSG_PET_SET_ACTION = 0x174, - CMSG_PET_ACTION = 0x175, - CMSG_PET_ABANDON = 0x176, - CMSG_PET_RENAME = 0x177, - SMSG_PET_NAME_INVALID = 0x178, - SMSG_PET_SPELLS = 0x179, - SMSG_PET_MODE = 0x17A, - CMSG_GOSSIP_HELLO = 0x17B, - CMSG_GOSSIP_SELECT_OPTION = 0x17C, - SMSG_GOSSIP_MESSAGE = 0x17D, - SMSG_GOSSIP_COMPLETE = 0x17E, - CMSG_NPC_TEXT_QUERY = 0x17F, - SMSG_NPC_TEXT_UPDATE = 0x180, - SMSG_NPC_WONT_TALK = 0x181, - CMSG_QUESTGIVER_STATUS_QUERY = 0x182, - SMSG_QUESTGIVER_STATUS = 0x183, - CMSG_QUESTGIVER_HELLO = 0x184, - SMSG_QUESTGIVER_QUEST_LIST = 0x185, - CMSG_QUESTGIVER_QUERY_QUEST = 0x186, - CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x187, - SMSG_QUESTGIVER_QUEST_DETAILS = 0x188, - CMSG_QUESTGIVER_ACCEPT_QUEST = 0x189, - CMSG_QUESTGIVER_COMPLETE_QUEST = 0x18A, - SMSG_QUESTGIVER_REQUEST_ITEMS = 0x18B, - CMSG_QUESTGIVER_REQUEST_REWARD = 0x18C, - SMSG_QUESTGIVER_OFFER_REWARD = 0x18D, - CMSG_QUESTGIVER_CHOOSE_REWARD = 0x18E, - SMSG_QUESTGIVER_QUEST_INVALID = 0x18F, - CMSG_QUESTGIVER_CANCEL = 0x190, - SMSG_QUESTGIVER_QUEST_COMPLETE = 0x191, - SMSG_QUESTGIVER_QUEST_FAILED = 0x192, - CMSG_QUESTLOG_SWAP_QUEST = 0x193, - CMSG_QUESTLOG_REMOVE_QUEST = 0x194, - SMSG_QUESTLOG_FULL = 0x195, - SMSG_QUESTUPDATE_FAILED = 0x196, - SMSG_QUESTUPDATE_FAILEDTIMER = 0x197, - SMSG_QUESTUPDATE_COMPLETE = 0x198, - SMSG_QUESTUPDATE_ADD_KILL = 0x199, - SMSG_QUESTUPDATE_ADD_ITEM = 0x19A, - CMSG_QUEST_CONFIRM_ACCEPT = 0x19B, - SMSG_QUEST_CONFIRM_ACCEPT = 0x19C, - CMSG_PUSHQUESTTOPARTY = 0x19D, - CMSG_LIST_INVENTORY = 0x19E, - SMSG_LIST_INVENTORY = 0x19F, - CMSG_SELL_ITEM = 0x1A0, - SMSG_SELL_ITEM = 0x1A1, - CMSG_BUY_ITEM = 0x1A2, - CMSG_BUY_ITEM_IN_SLOT = 0x1A3, - SMSG_BUY_ITEM = 0x1A4, - SMSG_BUY_FAILED = 0x1A5, - CMSG_TAXICLEARALLNODES = 0x1A6, - CMSG_TAXIENABLEALLNODES = 0x1A7, - CMSG_TAXISHOWNODES = 0x1A8, - SMSG_SHOWTAXINODES = 0x1A9, - CMSG_TAXINODE_STATUS_QUERY = 0x1AA, - SMSG_TAXINODE_STATUS = 0x1AB, - CMSG_TAXIQUERYAVAILABLENODES = 0x1AC, - CMSG_ACTIVATETAXI = 0x1AD, - SMSG_ACTIVATETAXIREPLY = 0x1AE, - SMSG_NEW_TAXI_PATH = 0x1AF, - CMSG_TRAINER_LIST = 0x1B0, - SMSG_TRAINER_LIST = 0x1B1, - CMSG_TRAINER_BUY_SPELL = 0x1B2, - SMSG_TRAINER_BUY_SUCCEEDED = 0x1B3, - SMSG_TRAINER_BUY_FAILED = 0x1B4, - CMSG_BINDER_ACTIVATE = 0x1B5, - SMSG_PLAYERBINDERROR = 0x1B6, - CMSG_BANKER_ACTIVATE = 0x1B7, - SMSG_SHOW_BANK = 0x1B8, - CMSG_BUY_BANK_SLOT = 0x1B9, - SMSG_BUY_BANK_SLOT_RESULT = 0x1BA, - CMSG_PETITION_SHOWLIST = 0x1BB, - SMSG_PETITION_SHOWLIST = 0x1BC, - CMSG_PETITION_BUY = 0x1BD, - CMSG_PETITION_SHOW_SIGNATURES = 0x1BE, - SMSG_PETITION_SHOW_SIGNATURES = 0x1BF, - CMSG_PETITION_SIGN = 0x1C0, - SMSG_PETITION_SIGN_RESULTS = 0x1C1, - MSG_PETITION_DECLINE = 0x1C2, - CMSG_OFFER_PETITION = 0x1C3, - CMSG_TURN_IN_PETITION = 0x1C4, - SMSG_TURN_IN_PETITION_RESULTS = 0x1C5, - CMSG_PETITION_QUERY = 0x1C6, - SMSG_PETITION_QUERY_RESPONSE = 0x1C7, - SMSG_FISH_NOT_HOOKED = 0x1C8, - SMSG_FISH_ESCAPED = 0x1C9, - CMSG_BUG = 0x1CA, - SMSG_NOTIFICATION = 0x1CB, - CMSG_PLAYED_TIME = 0x1CC, - SMSG_PLAYED_TIME = 0x1CD, - CMSG_QUERY_TIME = 0x1CE, - SMSG_QUERY_TIME_RESPONSE = 0x1CF, - SMSG_LOG_XPGAIN = 0x1D0, - SMSG_AURACASTLOG = 0x1D1, - CMSG_RECLAIM_CORPSE = 0x1D2, - CMSG_WRAP_ITEM = 0x1D3, - SMSG_LEVELUP_INFO = 0x1D4, - MSG_MINIMAP_PING = 0x1D5, - SMSG_RESISTLOG = 0x1D6, - SMSG_ENCHANTMENTLOG = 0x1D7, - CMSG_SET_SKILL_CHEAT = 0x1D8, - SMSG_START_MIRROR_TIMER = 0x1D9, - SMSG_PAUSE_MIRROR_TIMER = 0x1DA, - SMSG_STOP_MIRROR_TIMER = 0x1DB, - CMSG_PING = 0x1DC, - SMSG_PONG = 0x1DD, - SMSG_CLEAR_COOLDOWN = 0x1DE, - SMSG_GAMEOBJECT_PAGETEXT = 0x1DF, - CMSG_SETSHEATHED = 0x1E0, - SMSG_COOLDOWN_CHEAT = 0x1E1, - SMSG_SPELL_DELAYED = 0x1E2, - CMSG_QUEST_POI_QUERY = 0x1E3, - SMSG_QUEST_POI_QUERY_RESPONSE = 0x1E4, - CMSG_GHOST = 0x1E5, - CMSG_GM_INVIS = 0x1E6, - SMSG_INVALID_PROMOTION_CODE = 0x1E7, - MSG_GM_BIND_OTHER = 0x1E8, - MSG_GM_SUMMON = 0x1E9, - SMSG_ITEM_TIME_UPDATE = 0x1EA, - SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x1EB, - SMSG_AUTH_CHALLENGE = 0x1EC, - CMSG_AUTH_SESSION = 0x1ED, - SMSG_AUTH_RESPONSE = 0x1EE, - MSG_GM_SHOWLABEL = 0x1EF, - CMSG_PET_CAST_SPELL = 0x1F0, - MSG_SAVE_GUILD_EMBLEM = 0x1F1, - MSG_TABARDVENDOR_ACTIVATE = 0x1F2, - SMSG_PLAY_SPELL_VISUAL = 0x1F3, - CMSG_ZONEUPDATE = 0x1F4, - SMSG_PARTYKILLLOG = 0x1F5, - SMSG_COMPRESSED_UPDATE_OBJECT = 0x1F6, - SMSG_PLAY_SPELL_IMPACT = 0x1F7, - SMSG_EXPLORATION_EXPERIENCE = 0x1F8, - CMSG_GM_SET_SECURITY_GROUP = 0x1F9, - CMSG_GM_NUKE = 0x1FA, - MSG_RANDOM_ROLL = 0x1FB, - SMSG_ENVIRONMENTALDAMAGELOG = 0x1FC, - CMSG_PLAYER_DIFFICULTY_CHANGE = 0x1FD, - SMSG_RWHOIS = 0x1FE, - SMSG_LFG_PLAYER_REWARD = 0x1FF, // uint32, uint8, uint32, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32,uint32,uint32} - SMSG_LFG_TELEPORT_DENIED = 0x200, // uint32 (1,2,4,6;0,5,7) - CMSG_UNLEARN_SPELL = 0x201, - CMSG_UNLEARN_SKILL = 0x202, - SMSG_REMOVED_SPELL = 0x203, - CMSG_DECHARGE = 0x204, - CMSG_GMTICKET_CREATE = 0x205, - SMSG_GMTICKET_CREATE = 0x206, - CMSG_GMTICKET_UPDATETEXT = 0x207, - SMSG_GMTICKET_UPDATETEXT = 0x208, - SMSG_ACCOUNT_DATA_TIMES = 0x209, - CMSG_REQUEST_ACCOUNT_DATA = 0x20A, - CMSG_UPDATE_ACCOUNT_DATA = 0x20B, - SMSG_UPDATE_ACCOUNT_DATA = 0x20C, - SMSG_CLEAR_FAR_SIGHT_IMMEDIATE = 0x20D, - SMSG_PLAYER_DIFFICULTY_CHANGE = 0x20E, - CMSG_GM_TEACH = 0x20F, - CMSG_GM_CREATE_ITEM_TARGET = 0x210, - CMSG_GMTICKET_GETTICKET = 0x211, - SMSG_GMTICKET_GETTICKET = 0x212, - CMSG_UNLEARN_TALENTS = 0x213, - SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE = 0x214, - SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x215, - MSG_CORPSE_QUERY = 0x216, - CMSG_GMTICKET_DELETETICKET = 0x217, - SMSG_GMTICKET_DELETETICKET = 0x218, - SMSG_CHAT_WRONG_FACTION = 0x219, - CMSG_GMTICKET_SYSTEMSTATUS = 0x21A, - SMSG_GMTICKET_SYSTEMSTATUS = 0x21B, - CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C, - CMSG_SET_STAT_CHEAT = 0x21D, - SMSG_QUEST_FORCE_REMOVE = 0x21E, // uint32 questid - CMSG_SKILL_BUY_STEP = 0x21F, - CMSG_SKILL_BUY_RANK = 0x220, - CMSG_XP_CHEAT = 0x221, - SMSG_SPIRIT_HEALER_CONFIRM = 0x222, - CMSG_CHARACTER_POINT_CHEAT = 0x223, - SMSG_GOSSIP_POI = 0x224, - CMSG_CHAT_IGNORED = 0x225, - CMSG_GM_VISION = 0x226, - CMSG_SERVER_COMMAND = 0x227, - CMSG_GM_SILENCE = 0x228, - CMSG_GM_REVEALTO = 0x229, - CMSG_GM_RESURRECT = 0x22A, - CMSG_GM_SUMMONMOB = 0x22B, - CMSG_GM_MOVECORPSE = 0x22C, - CMSG_GM_FREEZE = 0x22D, - CMSG_GM_UBERINVIS = 0x22E, - CMSG_GM_REQUEST_PLAYER_INFO = 0x22F, - SMSG_GM_PLAYER_INFO = 0x230, - CMSG_GUILD_RANK = 0x231, - CMSG_GUILD_ADD_RANK = 0x232, - CMSG_GUILD_DEL_RANK = 0x233, - CMSG_GUILD_SET_PUBLIC_NOTE = 0x234, - CMSG_GUILD_SET_OFFICER_NOTE = 0x235, - SMSG_LOGIN_VERIFY_WORLD = 0x236, - CMSG_CLEAR_EXPLORATION = 0x237, - CMSG_SEND_MAIL = 0x238, - SMSG_SEND_MAIL_RESULT = 0x239, - CMSG_GET_MAIL_LIST = 0x23A, - SMSG_MAIL_LIST_RESULT = 0x23B, - CMSG_BATTLEFIELD_LIST = 0x23C, - SMSG_BATTLEFIELD_LIST = 0x23D, - CMSG_BATTLEFIELD_JOIN = 0x23E, - SMSG_BATTLEFIELD_WIN_OBSOLETE = 0x23F, - SMSG_BATTLEFIELD_LOSE_OBSOLETE = 0x240, - CMSG_TAXICLEARNODE = 0x241, - CMSG_TAXIENABLENODE = 0x242, - CMSG_ITEM_TEXT_QUERY = 0x243, - SMSG_ITEM_TEXT_QUERY_RESPONSE = 0x244, - CMSG_MAIL_TAKE_MONEY = 0x245, - CMSG_MAIL_TAKE_ITEM = 0x246, - CMSG_MAIL_MARK_AS_READ = 0x247, - CMSG_MAIL_RETURN_TO_SENDER = 0x248, - CMSG_MAIL_DELETE = 0x249, - CMSG_MAIL_CREATE_TEXT_ITEM = 0x24A, - SMSG_SPELLLOGMISS = 0x24B, - SMSG_SPELLLOGEXECUTE = 0x24C, - SMSG_DEBUGAURAPROC = 0x24D, - SMSG_PERIODICAURALOG = 0x24E, - SMSG_SPELLDAMAGESHIELD = 0x24F, - SMSG_SPELLNONMELEEDAMAGELOG = 0x250, - CMSG_LEARN_TALENT = 0x251, - SMSG_RESURRECT_FAILED = 0x252, - CMSG_TOGGLE_PVP = 0x253, - SMSG_ZONE_UNDER_ATTACK = 0x254, - MSG_AUCTION_HELLO = 0x255, - CMSG_AUCTION_SELL_ITEM = 0x256, - CMSG_AUCTION_REMOVE_ITEM = 0x257, - CMSG_AUCTION_LIST_ITEMS = 0x258, - CMSG_AUCTION_LIST_OWNER_ITEMS = 0x259, - CMSG_AUCTION_PLACE_BID = 0x25A, - SMSG_AUCTION_COMMAND_RESULT = 0x25B, - SMSG_AUCTION_LIST_RESULT = 0x25C, - SMSG_AUCTION_OWNER_LIST_RESULT = 0x25D, - SMSG_AUCTION_BIDDER_NOTIFICATION = 0x25E, - SMSG_AUCTION_OWNER_NOTIFICATION = 0x25F, - SMSG_PROCRESIST = 0x260, - SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE = 0x261, - SMSG_DISPEL_FAILED = 0x262, - SMSG_SPELLORDAMAGE_IMMUNE = 0x263, - CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x264, - SMSG_AUCTION_BIDDER_LIST_RESULT = 0x265, - SMSG_SET_FLAT_SPELL_MODIFIER = 0x266, - SMSG_SET_PCT_SPELL_MODIFIER = 0x267, - CMSG_SET_AMMO = 0x268, - SMSG_CORPSE_RECLAIM_DELAY = 0x269, - CMSG_SET_ACTIVE_MOVER = 0x26A, - CMSG_PET_CANCEL_AURA = 0x26B, - CMSG_PLAYER_AI_CHEAT = 0x26C, - CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x26D, - MSG_GM_ACCOUNT_ONLINE = 0x26E, - MSG_LIST_STABLED_PETS = 0x26F, - CMSG_STABLE_PET = 0x270, - CMSG_UNSTABLE_PET = 0x271, - CMSG_BUY_STABLE_SLOT = 0x272, - SMSG_STABLE_RESULT = 0x273, - CMSG_STABLE_REVIVE_PET = 0x274, - CMSG_STABLE_SWAP_PET = 0x275, - MSG_QUEST_PUSH_RESULT = 0x276, - SMSG_PLAY_MUSIC = 0x277, - SMSG_PLAY_OBJECT_SOUND = 0x278, - CMSG_REQUEST_PET_INFO = 0x279, - CMSG_FAR_SIGHT = 0x27A, - SMSG_SPELLDISPELLOG = 0x27B, - SMSG_DAMAGE_CALC_LOG = 0x27C, - CMSG_ENABLE_DAMAGE_LOG = 0x27D, - CMSG_GROUP_CHANGE_SUB_GROUP = 0x27E, - CMSG_REQUEST_PARTY_MEMBER_STATS = 0x27F, - CMSG_GROUP_SWAP_SUB_GROUP = 0x280, - CMSG_RESET_FACTION_CHEAT = 0x281, - CMSG_AUTOSTORE_BANK_ITEM = 0x282, - CMSG_AUTOBANK_ITEM = 0x283, - MSG_QUERY_NEXT_MAIL_TIME = 0x284, - SMSG_RECEIVED_MAIL = 0x285, - SMSG_RAID_GROUP_ONLY = 0x286, - CMSG_SET_DURABILITY_CHEAT = 0x287, - CMSG_SET_PVP_RANK_CHEAT = 0x288, - CMSG_ADD_PVP_MEDAL_CHEAT = 0x289, - CMSG_DEL_PVP_MEDAL_CHEAT = 0x28A, - CMSG_SET_PVP_TITLE = 0x28B, - SMSG_PVP_CREDIT = 0x28C, - SMSG_AUCTION_REMOVED_NOTIFICATION = 0x28D, - CMSG_GROUP_RAID_CONVERT = 0x28E, - CMSG_GROUP_ASSISTANT_LEADER = 0x28F, - CMSG_BUYBACK_ITEM = 0x290, - SMSG_SERVER_MESSAGE = 0x291, - CMSG_SET_SAVED_INSTANCE_EXTEND = 0x292, // lua: SetSavedInstanceExtend - SMSG_LFG_OFFER_CONTINUE = 0x293, - CMSG_MEETINGSTONE_CHEAT = 0x294, // not found 3.3 - SMSG_MEETINGSTONE_SETQUEUE = 0x295, // string, showed in console - CMSG_MEETINGSTONE_INFO = 0x296, // EVENT_LFG_UPDATE - SMSG_MEETINGSTONE_COMPLETE = 0x297, // EVENT_MAIL_SHOW - SMSG_MEETINGSTONE_IN_PROGRESS = 0x298, // uint32, some UPDATE_COOLDOWN events - SMSG_MEETINGSTONE_MEMBER_ADDED = 0x299, // uint32, errors: ERR_NOT_IN_GROUP (2,51) and ERR_NOT_IN_RAID (3,39,40) - CMSG_GMTICKETSYSTEM_TOGGLE = 0x29A, - CMSG_CANCEL_GROWTH_AURA = 0x29B, - SMSG_CANCEL_AUTO_REPEAT = 0x29C, - SMSG_STANDSTATE_UPDATE = 0x29D, - SMSG_LOOT_ALL_PASSED = 0x29E, - SMSG_LOOT_ROLL_WON = 0x29F, - CMSG_LOOT_ROLL = 0x2A0, - SMSG_LOOT_START_ROLL = 0x2A1, - SMSG_LOOT_ROLL = 0x2A2, - CMSG_LOOT_MASTER_GIVE = 0x2A3, - SMSG_LOOT_MASTER_LIST = 0x2A4, - SMSG_SET_FORCED_REACTIONS = 0x2A5, - SMSG_SPELL_FAILED_OTHER = 0x2A6, - SMSG_GAMEOBJECT_RESET_STATE = 0x2A7, - CMSG_REPAIR_ITEM = 0x2A8, - SMSG_CHAT_PLAYER_NOT_FOUND = 0x2A9, - MSG_TALENT_WIPE_CONFIRM = 0x2AA, - SMSG_SUMMON_REQUEST = 0x2AB, - CMSG_SUMMON_RESPONSE = 0x2AC, - MSG_MOVE_TOGGLE_GRAVITY_CHEAT = 0x2AD, - SMSG_MONSTER_MOVE_TRANSPORT = 0x2AE, - SMSG_PET_BROKEN = 0x2AF, - MSG_MOVE_FEATHER_FALL = 0x2B0, - MSG_MOVE_WATER_WALK = 0x2B1, - CMSG_SERVER_BROADCAST = 0x2B2, - CMSG_SELF_RES = 0x2B3, - SMSG_FEIGN_DEATH_RESISTED = 0x2B4, - CMSG_RUN_SCRIPT = 0x2B5, - SMSG_SCRIPT_MESSAGE = 0x2B6, - SMSG_DUEL_COUNTDOWN = 0x2B7, - SMSG_AREA_TRIGGER_MESSAGE = 0x2B8, - CMSG_SHOWING_HELM = 0x2B9, - CMSG_SHOWING_CLOAK = 0x2BA, - SMSG_LFG_ROLE_CHOSEN = 0x2BB, - SMSG_PLAYER_SKINNED = 0x2BC, - SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD, - CMSG_SET_EXPLORATION = 0x2BE, - CMSG_SET_ACTIONBAR_TOGGLES = 0x2BF, - UMSG_DELETE_GUILD_CHARTER = 0x2C0, - MSG_PETITION_RENAME = 0x2C1, - SMSG_INIT_WORLD_STATES = 0x2C2, - SMSG_UPDATE_WORLD_STATE = 0x2C3, - CMSG_ITEM_NAME_QUERY = 0x2C4, - SMSG_ITEM_NAME_QUERY_RESPONSE = 0x2C5, - SMSG_PET_ACTION_FEEDBACK = 0x2C6, - CMSG_CHAR_RENAME = 0x2C7, - SMSG_CHAR_RENAME = 0x2C8, - CMSG_MOVE_SPLINE_DONE = 0x2C9, - CMSG_MOVE_FALL_RESET = 0x2CA, - SMSG_INSTANCE_SAVE_CREATED = 0x2CB, - SMSG_RAID_INSTANCE_INFO = 0x2CC, - CMSG_REQUEST_RAID_INFO = 0x2CD, - CMSG_MOVE_TIME_SKIPPED = 0x2CE, - CMSG_MOVE_FEATHER_FALL_ACK = 0x2CF, - CMSG_MOVE_WATER_WALK_ACK = 0x2D0, - CMSG_MOVE_NOT_ACTIVE_MOVER = 0x2D1, - SMSG_PLAY_SOUND = 0x2D2, - CMSG_BATTLEFIELD_STATUS = 0x2D3, - SMSG_BATTLEFIELD_STATUS = 0x2D4, - CMSG_BATTLEFIELD_PORT = 0x2D5, - MSG_INSPECT_HONOR_STATS = 0x2D6, - CMSG_BATTLEMASTER_HELLO = 0x2D7, - CMSG_MOVE_START_SWIM_CHEAT = 0x2D8, - CMSG_MOVE_STOP_SWIM_CHEAT = 0x2D9, - SMSG_FORCE_WALK_SPEED_CHANGE = 0x2DA, - CMSG_FORCE_WALK_SPEED_CHANGE_ACK = 0x2DB, - SMSG_FORCE_SWIM_BACK_SPEED_CHANGE = 0x2DC, - CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x2DD, - SMSG_FORCE_TURN_RATE_CHANGE = 0x2DE, - CMSG_FORCE_TURN_RATE_CHANGE_ACK = 0x2DF, - MSG_PVP_LOG_DATA = 0x2E0, - CMSG_LEAVE_BATTLEFIELD = 0x2E1, - CMSG_AREA_SPIRIT_HEALER_QUERY = 0x2E2, - CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x2E3, - SMSG_AREA_SPIRIT_HEALER_TIME = 0x2E4, - CMSG_GM_UNTEACH = 0x2E5, - SMSG_WARDEN_DATA = 0x2E6, - CMSG_WARDEN_DATA = 0x2E7, - SMSG_GROUP_JOINED_BATTLEGROUND = 0x2E8, - MSG_BATTLEGROUND_PLAYER_POSITIONS = 0x2E9, - CMSG_PET_STOP_ATTACK = 0x2EA, - SMSG_BINDER_CONFIRM = 0x2EB, - SMSG_BATTLEGROUND_PLAYER_JOINED = 0x2EC, - SMSG_BATTLEGROUND_PLAYER_LEFT = 0x2ED, - CMSG_BATTLEMASTER_JOIN = 0x2EE, - SMSG_ADDON_INFO = 0x2EF, - CMSG_PET_UNLEARN = 0x2F0, // Deprecated 3.x - SMSG_PET_UNLEARN_CONFIRM = 0x2F1, // Deprecated 3.x - SMSG_PARTY_MEMBER_STATS_FULL = 0x2F2, - CMSG_PET_SPELL_AUTOCAST = 0x2F3, - SMSG_WEATHER = 0x2F4, - SMSG_PLAY_TIME_WARNING = 0x2F5, - SMSG_MINIGAME_SETUP = 0x2F6, - SMSG_MINIGAME_STATE = 0x2F7, - CMSG_MINIGAME_MOVE = 0x2F8, - SMSG_MINIGAME_MOVE_FAILED = 0x2F9, - SMSG_RAID_INSTANCE_MESSAGE = 0x2FA, - SMSG_COMPRESSED_MOVES = 0x2FB, - CMSG_GUILD_INFO_TEXT = 0x2FC, - SMSG_CHAT_RESTRICTED = 0x2FD, - SMSG_SPLINE_SET_RUN_SPEED = 0x2FE, - SMSG_SPLINE_SET_RUN_BACK_SPEED = 0x2FF, - SMSG_SPLINE_SET_SWIM_SPEED = 0x300, - SMSG_SPLINE_SET_WALK_SPEED = 0x301, - SMSG_SPLINE_SET_SWIM_BACK_SPEED = 0x302, - SMSG_SPLINE_SET_TURN_RATE = 0x303, - SMSG_SPLINE_MOVE_UNROOT = 0x304, - SMSG_SPLINE_MOVE_FEATHER_FALL = 0x305, - SMSG_SPLINE_MOVE_NORMAL_FALL = 0x306, - SMSG_SPLINE_MOVE_SET_HOVER = 0x307, - SMSG_SPLINE_MOVE_UNSET_HOVER = 0x308, - SMSG_SPLINE_MOVE_WATER_WALK = 0x309, - SMSG_SPLINE_MOVE_LAND_WALK = 0x30A, - SMSG_SPLINE_MOVE_START_SWIM = 0x30B, - SMSG_SPLINE_MOVE_STOP_SWIM = 0x30C, - SMSG_SPLINE_MOVE_SET_RUN_MODE = 0x30D, - SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x30E, - CMSG_GM_NUKE_ACCOUNT = 0x30F, - MSG_GM_DESTROY_CORPSE = 0x310, - CMSG_GM_DESTROY_ONLINE_CORPSE = 0x311, - CMSG_ACTIVATETAXIEXPRESS = 0x312, - SMSG_SET_FACTION_ATWAR = 0x313, - SMSG_GAMETIMEBIAS_SET = 0x314, - CMSG_DEBUG_ACTIONS_START = 0x315, - CMSG_DEBUG_ACTIONS_STOP = 0x316, - CMSG_SET_FACTION_INACTIVE = 0x317, - CMSG_SET_WATCHED_FACTION = 0x318, - MSG_MOVE_TIME_SKIPPED = 0x319, - SMSG_SPLINE_MOVE_ROOT = 0x31A, - CMSG_SET_EXPLORATION_ALL = 0x31B, - SMSG_INVALIDATE_PLAYER = 0x31C, - CMSG_RESET_INSTANCES = 0x31D, - SMSG_INSTANCE_RESET = 0x31E, - SMSG_INSTANCE_RESET_FAILED = 0x31F, - SMSG_UPDATE_LAST_INSTANCE = 0x320, - MSG_RAID_TARGET_UPDATE = 0x321, - MSG_RAID_READY_CHECK = 0x322, - CMSG_LUA_USAGE = 0x323, - SMSG_PET_ACTION_SOUND = 0x324, - SMSG_PET_DISMISS_SOUND = 0x325, - SMSG_GHOSTEE_GONE = 0x326, - CMSG_GM_UPDATE_TICKET_STATUS = 0x327, - SMSG_GM_TICKET_STATUS_UPDATE = 0x328, - MSG_SET_DUNGEON_DIFFICULTY = 0x329, - CMSG_GMSURVEY_SUBMIT = 0x32A, - SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x32B, - CMSG_IGNORE_KNOCKBACK_CHEAT = 0x32C, - SMSG_CHAT_PLAYER_AMBIGUOUS = 0x32D, - MSG_DELAY_GHOST_TELEPORT = 0x32E, - SMSG_SPELLINSTAKILLLOG = 0x32F, - SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x330, - CMSG_CHAT_FILTERED = 0x331, - SMSG_EXPECTED_SPAM_RECORDS = 0x332, - SMSG_SPELLSTEALLOG = 0x333, - CMSG_LOTTERY_QUERY_OBSOLETE = 0x334, - SMSG_LOTTERY_QUERY_RESULT_OBSOLETE = 0x335, - CMSG_BUY_LOTTERY_TICKET_OBSOLETE = 0x336, - SMSG_LOTTERY_RESULT_OBSOLETE = 0x337, - SMSG_CHARACTER_PROFILE = 0x338, - SMSG_CHARACTER_PROFILE_REALM_CONNECTED = 0x339, - SMSG_DEFENSE_MESSAGE = 0x33A, - SMSG_INSTANCE_DIFFICULTY = 0x33B, - MSG_GM_RESETINSTANCELIMIT = 0x33C, - SMSG_MOTD = 0x33D, - SMSG_MOVE_SET_FLIGHT = 0x33E, - SMSG_MOVE_UNSET_FLIGHT = 0x33F, - CMSG_MOVE_FLIGHT_ACK = 0x340, - MSG_MOVE_START_SWIM_CHEAT = 0x341, - MSG_MOVE_STOP_SWIM_CHEAT = 0x342, - SMSG_MOVE_SET_CAN_FLY = 0x343, - SMSG_MOVE_UNSET_CAN_FLY = 0x344, - CMSG_MOVE_SET_CAN_FLY_ACK = 0x345, - CMSG_MOVE_SET_FLY = 0x346, - CMSG_SOCKET_GEMS = 0x347, - CMSG_ARENA_TEAM_CREATE = 0x348, - SMSG_ARENA_TEAM_COMMAND_RESULT = 0x349, - UMSG_UPDATE_ARENA_TEAM_OBSOLETE = 0x34A, - CMSG_ARENA_TEAM_QUERY = 0x34B, - SMSG_ARENA_TEAM_QUERY_RESPONSE = 0x34C, - CMSG_ARENA_TEAM_ROSTER = 0x34D, - SMSG_ARENA_TEAM_ROSTER = 0x34E, - CMSG_ARENA_TEAM_INVITE = 0x34F, - SMSG_ARENA_TEAM_INVITE = 0x350, - CMSG_ARENA_TEAM_ACCEPT = 0x351, - CMSG_ARENA_TEAM_DECLINE = 0x352, - CMSG_ARENA_TEAM_LEAVE = 0x353, - CMSG_ARENA_TEAM_REMOVE = 0x354, - CMSG_ARENA_TEAM_DISBAND = 0x355, - CMSG_ARENA_TEAM_LEADER = 0x356, - SMSG_ARENA_TEAM_EVENT = 0x357, - CMSG_BATTLEMASTER_JOIN_ARENA = 0x358, - MSG_MOVE_START_ASCEND = 0x359, - MSG_MOVE_STOP_ASCEND = 0x35A, - SMSG_ARENA_TEAM_STATS = 0x35B, - CMSG_LFG_JOIN = 0x35C, // CMSG JoinLFG - CMSG_LFG_LEAVE = 0x35D, // CMSG LeaveLFG - CMSG_SEARCH_LFG_JOIN = 0x35E, // CMSG SearchLFGJoin - CMSG_SEARCH_LFG_LEAVE = 0x35F, // CMSG SearchLFGLeave - SMSG_UPDATE_LFG_LIST = 0x360, // SMSG uint32, uint32, if (uint8) { uint32 count, for (count) { uint64} }, uint32 count2, uint32, for (count2) { uint64, uint32 flags, if (flags & 0x2) {string}, if (flags & 0x10) {for (3) uint8}, if (flags & 0x80) {uint64, uint32}}, uint32 count3, uint32, for (count3) {uint64, uint32 flags, if (flags & 0x1) {uint8, uint8, uint8, for (3) uint8, uint32, uint32, uint32, uint32, uint32, uint32, float, float, uint32, uint32, uint32, uint32, uint32, float, uint32, uint32, uint32, uint32, uint32, uint32}, if (flags&0x2) string, if (flags&0x4) uint8, if (flags&0x8) uint64, if (flags&0x10) uint8, if (flags&0x20) uint32, if (flags&0x40) uint8, if (flags& 0x80) {uint64, uint32}} - SMSG_LFG_PROPOSAL_UPDATE = 0x361, // SMSG uint32, uint8, uint32, uint32, uint8, for (uint8) {uint32,uint8,uint8,uint8,uint8} - CMSG_LFG_PROPOSAL_RESULT = 0x362, // CMSG AcceptProposal, RejectProposal - SMSG_LFG_ROLE_CHECK_UPDATE = 0x363, // SMSG uint32, uint8, for (uint8) uint32, uint8, for (uint8) { uint64, uint8, uint32, uint8, } - SMSG_LFG_JOIN_RESULT = 0x364, // SMSG uint32 unk, uint32, if (unk == 6) { uint8 count, for (count) uint64 } - SMSG_LFG_QUEUE_STATUS = 0x365, // SMSG uint32 dungeon, uint32 lfgtype, uint32, uint32, uint32, uint32, uint8, uint8, uint8, uint8 - CMSG_SET_LFG_COMMENT = 0x366, // CMSG SetLFGComment - SMSG_LFG_UPDATE_PLAYER = 0x367, // SMSG uint8, if (uint8) { uint8, uint8, uint8, uint8, if (uint8) for (uint8) uint32, string} - SMSG_LFG_UPDATE_PARTY = 0x368, // SMSG uint8, if (uint8) { uint8, uint8, uint8, for (3) uint8, uint8, if (uint8) for (uint8) uint32, string} - SMSG_LFG_UPDATE_SEARCH = 0x369, // SMSG uint8 - CMSG_LFG_SET_ROLES = 0x36A, // CMSG SetLFGRoles - CMSG_LFG_SET_NEEDS = 0x36B, // CMSG SetLFGNeeds - CMSG_LFG_SET_BOOT_VOTE = 0x36C, // CMSG SetLFGBootVote - SMSG_LFG_BOOT_PLAYER = 0x36D, // SMSG uint8, uint8, uint8, uint64, uint32, uint32, uint32, uint32 - CMSG_LFD_PLAYER_LOCK_INFO_REQUEST = 0x36E, // CMSG RequestLFDPlayerLockInfo - SMSG_LFG_PLAYER_INFO = 0x36F, // SMSG uint8, for (uint8) { uint32, uint8, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32,uint32, uint32}}, uint32, for (uint32) {uint32,uint32} - CMSG_LFG_TELEPORT = 0x370, // CMSG LFGTeleport - CMSG_LFD_PARTY_LOCK_INFO_REQUEST = 0x371, // CMSG RequestLFDPartyLockInfo - SMSG_LFG_PARTY_INFO = 0x372, // SMSG uint8, for (uint8) uint64 - SMSG_TITLE_EARNED = 0x373, - CMSG_SET_TITLE = 0x374, - CMSG_CANCEL_MOUNT_AURA = 0x375, - SMSG_ARENA_ERROR = 0x376, - MSG_INSPECT_ARENA_TEAMS = 0x377, - SMSG_DEATH_RELEASE_LOC = 0x378, - CMSG_CANCEL_TEMP_ENCHANTMENT = 0x379, - SMSG_FORCED_DEATH_UPDATE = 0x37A, - CMSG_CHEAT_SET_HONOR_CURRENCY = 0x37B, - CMSG_CHEAT_SET_ARENA_CURRENCY = 0x37C, - MSG_MOVE_SET_FLIGHT_SPEED_CHEAT = 0x37D, - MSG_MOVE_SET_FLIGHT_SPEED = 0x37E, - MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT = 0x37F, - MSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x380, - SMSG_FORCE_FLIGHT_SPEED_CHANGE = 0x381, - CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x382, - SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE = 0x383, - CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x384, - SMSG_SPLINE_SET_FLIGHT_SPEED = 0x385, - SMSG_SPLINE_SET_FLIGHT_BACK_SPEED = 0x386, - CMSG_MAELSTROM_INVALIDATE_CACHE = 0x387, - SMSG_FLIGHT_SPLINE_SYNC = 0x388, - CMSG_SET_TAXI_BENCHMARK_MODE = 0x389, - SMSG_JOINED_BATTLEGROUND_QUEUE = 0x38A, - SMSG_REALM_SPLIT = 0x38B, - CMSG_REALM_SPLIT = 0x38C, - CMSG_MOVE_CHNG_TRANSPORT = 0x38D, - MSG_PARTY_ASSIGNMENT = 0x38E, - SMSG_OFFER_PETITION_ERROR = 0x38F, - SMSG_TIME_SYNC_REQ = 0x390, - CMSG_TIME_SYNC_RESP = 0x391, - CMSG_SEND_LOCAL_EVENT = 0x392, - CMSG_SEND_GENERAL_TRIGGER = 0x393, - CMSG_SEND_COMBAT_TRIGGER = 0x394, - CMSG_MAELSTROM_GM_SENT_MAIL = 0x395, - SMSG_RESET_FAILED_NOTIFY = 0x396, - SMSG_REAL_GROUP_UPDATE = 0x397, - SMSG_LFG_DISABLED = 0x398, - CMSG_ACTIVE_PVP_CHEAT = 0x399, - CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY = 0x39A, - SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE = 0x39B, - SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE = 0x39C, - SMSG_UPDATE_COMBO_POINTS = 0x39D, - SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x39E, - SMSG_VOICE_SESSION_LEAVE = 0x39F, - SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0, - CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1, - SMSG_VOICE_SET_TALKER_MUTED = 0x3A2, - SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE = 0x3A3, - SMSG_SET_EXTRA_AURA_INFO_OBSOLETE = 0x3A4, - SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE = 0x3A5, - SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE = 0x3A6, - MSG_MOVE_START_DESCEND = 0x3A7, - CMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A8, - SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A9, - SMSG_SPELL_CHANCE_PROC_LOG = 0x3AA, - CMSG_MOVE_SET_RUN_SPEED = 0x3AB, - SMSG_DISMOUNT = 0x3AC, - MSG_MOVE_UPDATE_CAN_FLY = 0x3AD, - MSG_RAID_READY_CHECK_CONFIRM = 0x3AE, - CMSG_VOICE_SESSION_ENABLE = 0x3AF, - SMSG_VOICE_SESSION_ENABLE = 0x3B0, - SMSG_VOICE_PARENTAL_CONTROLS = 0x3B1, - CMSG_GM_WHISPER = 0x3B2, - SMSG_GM_MESSAGECHAT = 0x3B3, - MSG_GM_GEARRATING = 0x3B4, - CMSG_COMMENTATOR_ENABLE = 0x3B5, - SMSG_COMMENTATOR_STATE_CHANGED = 0x3B6, - CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B7, - SMSG_COMMENTATOR_MAP_INFO = 0x3B8, - CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9, - SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3BA, - SMSG_COMMENTATOR_PLAYER_INFO = 0x3BB, - CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BC, - CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BD, - CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BE, - SMSG_CLEAR_TARGET = 0x3BF, - CMSG_BOT_DETECTED = 0x3C0, - SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C1, - CMSG_CHEAT_PLAYER_LOGIN = 0x3C2, - CMSG_CHEAT_PLAYER_LOOKUP = 0x3C3, - SMSG_CHEAT_PLAYER_LOOKUP = 0x3C4, - SMSG_KICK_REASON = 0x3C5, - MSG_RAID_READY_CHECK_FINISHED = 0x3C6, - CMSG_COMPLAIN = 0x3C7, - SMSG_COMPLAIN_RESULT = 0x3C8, - SMSG_FEATURE_SYSTEM_STATUS = 0x3C9, - CMSG_GM_SHOW_COMPLAINTS = 0x3CA, - CMSG_GM_UNSQUELCH = 0x3CB, - CMSG_CHANNEL_SILENCE_VOICE = 0x3CC, - CMSG_CHANNEL_SILENCE_ALL = 0x3CD, - CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CE, - CMSG_CHANNEL_UNSILENCE_ALL = 0x3CF, - CMSG_TARGET_CAST = 0x3D0, - CMSG_TARGET_SCRIPT_CAST = 0x3D1, - CMSG_CHANNEL_DISPLAY_LIST = 0x3D2, - CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D3, - CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D4, - SMSG_CHANNEL_MEMBER_COUNT = 0x3D5, - CMSG_CHANNEL_VOICE_ON = 0x3D6, - CMSG_CHANNEL_VOICE_OFF = 0x3D7, - CMSG_DEBUG_LIST_TARGETS = 0x3D8, - SMSG_DEBUG_LIST_TARGETS = 0x3D9, - SMSG_AVAILABLE_VOICE_CHANNEL = 0x3DA, - CMSG_ADD_VOICE_IGNORE = 0x3DB, - CMSG_DEL_VOICE_IGNORE = 0x3DC, - CMSG_PARTY_SILENCE = 0x3DD, - CMSG_PARTY_UNSILENCE = 0x3DE, - MSG_NOTIFY_PARTY_SQUELCH = 0x3DF, - SMSG_COMSAT_RECONNECT_TRY = 0x3E0, - SMSG_COMSAT_DISCONNECT = 0x3E1, - SMSG_COMSAT_CONNECT_FAIL = 0x3E2, - SMSG_VOICE_CHAT_STATUS = 0x3E3, - CMSG_REPORT_PVP_AFK = 0x3E4, - SMSG_REPORT_PVP_AFK_RESULT = 0x3E5, // SMSG? - CMSG_GUILD_BANKER_ACTIVATE = 0x3E6, - CMSG_GUILD_BANK_QUERY_TAB = 0x3E7, - SMSG_GUILD_BANK_LIST = 0x3E8, - CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E9, - CMSG_GUILD_BANK_BUY_TAB = 0x3EA, - CMSG_GUILD_BANK_UPDATE_TAB = 0x3EB, - CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EC, - CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3ED, - MSG_GUILD_BANK_LOG_QUERY = 0x3EE, - CMSG_SET_CHANNEL_WATCH = 0x3EF, - SMSG_USERLIST_ADD = 0x3F0, - SMSG_USERLIST_REMOVE = 0x3F1, - SMSG_USERLIST_UPDATE = 0x3F2, - CMSG_CLEAR_CHANNEL_WATCH = 0x3F3, - SMSG_INSPECT_TALENT = 0x3F4, - SMSG_GOGOGO_OBSOLETE = 0x3F5, - SMSG_ECHO_PARTY_SQUELCH = 0x3F6, - CMSG_SET_TITLE_SUFFIX = 0x3F7, - CMSG_SPELLCLICK = 0x3F8, - SMSG_LOOT_LIST = 0x3F9, - CMSG_GM_CHARACTER_RESTORE = 0x3FA, - CMSG_GM_CHARACTER_SAVE = 0x3FB, - SMSG_VOICESESSION_FULL = 0x3FC, - MSG_GUILD_PERMISSIONS = 0x3FD, - MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FE, - MSG_GUILD_EVENT_LOG_QUERY = 0x3FF, - CMSG_MAELSTROM_RENAME_GUILD = 0x400, - CMSG_GET_MIRRORIMAGE_DATA = 0x401, - SMSG_MIRRORIMAGE_DATA = 0x402, - SMSG_FORCE_DISPLAY_UPDATE = 0x403, - SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x404, - CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405, - SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x406, - CMSG_KEEP_ALIVE = 0x407, - SMSG_RAID_READY_CHECK_ERROR = 0x408, - CMSG_OPT_OUT_OF_LOOT = 0x409, - MSG_QUERY_GUILD_BANK_TEXT = 0x40A, - CMSG_SET_GUILD_BANK_TEXT = 0x40B, - CMSG_SET_GRANTABLE_LEVELS = 0x40C, - CMSG_GRANT_LEVEL = 0x40D, - CMSG_REFER_A_FRIEND = 0x40E, - MSG_GM_CHANGE_ARENA_RATING = 0x40F, - CMSG_DECLINE_CHANNEL_INVITE = 0x410, - SMSG_GROUPACTION_THROTTLED = 0x411, // SMSG? - SMSG_OVERRIDE_LIGHT = 0x412, - SMSG_TOTEM_CREATED = 0x413, - CMSG_TOTEM_DESTROYED = 0x414, - CMSG_EXPIRE_RAID_INSTANCE = 0x415, - CMSG_NO_SPELL_VARIANCE = 0x416, - CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x417, - SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x418, - CMSG_SET_PLAYER_DECLINED_NAMES = 0x419, - SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x41A, - CMSG_QUERY_SERVER_BUCK_DATA = 0x41B, - CMSG_CLEAR_SERVER_BUCK_DATA = 0x41C, - SMSG_SERVER_BUCK_DATA = 0x41D, - SMSG_SEND_UNLEARN_SPELLS = 0x41E, - SMSG_PROPOSE_LEVEL_GRANT = 0x41F, - CMSG_ACCEPT_LEVEL_GRANT = 0x420, - SMSG_REFER_A_FRIEND_FAILURE = 0x421, - SMSG_SPLINE_MOVE_SET_FLYING = 0x422, - SMSG_SPLINE_MOVE_UNSET_FLYING = 0x423, - SMSG_SUMMON_CANCEL = 0x424, - CMSG_CHANGE_PERSONAL_ARENA_RATING = 0x425, - CMSG_ALTER_APPEARANCE = 0x426, - SMSG_ENABLE_BARBER_SHOP = 0x427, - SMSG_BARBER_SHOP_RESULT = 0x428, - CMSG_CALENDAR_GET_CALENDAR = 0x429, - CMSG_CALENDAR_GET_EVENT = 0x42A, - CMSG_CALENDAR_GUILD_FILTER = 0x42B, - CMSG_CALENDAR_ARENA_TEAM = 0x42C, - CMSG_CALENDAR_ADD_EVENT = 0x42D, - CMSG_CALENDAR_UPDATE_EVENT = 0x42E, - CMSG_CALENDAR_REMOVE_EVENT = 0x42F, - CMSG_CALENDAR_COPY_EVENT = 0x430, - CMSG_CALENDAR_EVENT_INVITE = 0x431, - CMSG_CALENDAR_EVENT_RSVP = 0x432, - CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x433, - CMSG_CALENDAR_EVENT_STATUS = 0x434, - CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x435, - SMSG_CALENDAR_SEND_CALENDAR = 0x436, - SMSG_CALENDAR_SEND_EVENT = 0x437, - SMSG_CALENDAR_FILTER_GUILD = 0x438, - SMSG_CALENDAR_ARENA_TEAM = 0x439, - SMSG_CALENDAR_EVENT_INVITE = 0x43A, - SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x43B, - SMSG_CALENDAR_EVENT_STATUS = 0x43C, - SMSG_CALENDAR_COMMAND_RESULT = 0x43D, - SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x43E, - SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x43F, - SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x440, - SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x441, - SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x442, - SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x443, - SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444, - SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445, - CMSG_CALENDAR_COMPLAIN = 0x446, - CMSG_CALENDAR_GET_NUM_PENDING = 0x447, - SMSG_CALENDAR_SEND_NUM_PENDING = 0x448, - CMSG_SAVE_DANCE = 0x449, - SMSG_NOTIFY_DANCE = 0x44A, - CMSG_PLAY_DANCE = 0x44B, - SMSG_PLAY_DANCE = 0x44C, - CMSG_LOAD_DANCES = 0x44D, - CMSG_STOP_DANCE = 0x44E, - SMSG_STOP_DANCE = 0x44F, - CMSG_SYNC_DANCE = 0x450, - CMSG_DANCE_QUERY = 0x451, - SMSG_DANCE_QUERY_RESPONSE = 0x452, - SMSG_INVALIDATE_DANCE = 0x453, - CMSG_DELETE_DANCE = 0x454, - SMSG_LEARNED_DANCE_MOVES = 0x455, - CMSG_LEARN_DANCE_MOVE = 0x456, - CMSG_UNLEARN_DANCE_MOVE = 0x457, - CMSG_SET_RUNE_COUNT = 0x458, - CMSG_SET_RUNE_COOLDOWN = 0x459, - MSG_MOVE_SET_PITCH_RATE_CHEAT = 0x45A, - MSG_MOVE_SET_PITCH_RATE = 0x45B, - SMSG_FORCE_PITCH_RATE_CHANGE = 0x45C, - CMSG_FORCE_PITCH_RATE_CHANGE_ACK = 0x45D, - SMSG_SPLINE_SET_PITCH_RATE = 0x45E, - SMSG_MOVE_ABANDON_TRANSPORT = 0x45F, - SMSG_CALENDAR_UPDATE_INVITE_LIST = 0x460, - SMSG_CALENDAR_UPDATE_INVITE_LIST2 = 0x461, - CMSG_UPDATE_MISSILE_TRAJECTORY = 0x462, - SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x463, - SMSG_TRIGGER_MOVIE = 0x464, - CMSG_COMPLETE_MOVIE = 0x465, - CMSG_SET_GLYPH_SLOT = 0x466, - CMSG_SET_GLYPH = 0x467, - SMSG_ACHIEVEMENT_EARNED = 0x468, - SMSG_DYNAMIC_DROP_ROLL_RESULT = 0x469, - SMSG_CRITERIA_UPDATE = 0x46A, - CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x46B, - SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x46C, - CMSG_DISMISS_CONTROLLED_VEHICLE = 0x46D, - CMSG_COMPLETE_ACHIEVEMENT_CHEAT = 0x46E, - SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x46F, - CMSG_SET_CRITERIA_CHEAT = 0x470, - SMSG_CALENDAR_UPDATE_INVITE_LIST3 = 0x471, - CMSG_UNITANIMTIER_CHEAT = 0x472, - CMSG_CHAR_CUSTOMIZE = 0x473, - SMSG_CHAR_CUSTOMIZE = 0x474, - SMSG_PET_RENAMEABLE = 0x475, - CMSG_REQUEST_VEHICLE_EXIT = 0x476, - CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x477, - CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x478, - CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x479, - CMSG_PET_LEARN_TALENT = 0x47A, - CMSG_PET_UNLEARN_TALENTS = 0x47B, - SMSG_SET_PHASE_SHIFT = 0x47C, - SMSG_ALL_ACHIEVEMENT_DATA = 0x47D, - CMSG_FORCE_SAY_CHEAT = 0x47E, - SMSG_HEALTH_UPDATE = 0x47F, - SMSG_POWER_UPDATE = 0x480, - CMSG_GAMEOBJ_REPORT_USE = 0x481, - SMSG_HIGHEST_THREAT_UPDATE = 0x482, - SMSG_THREAT_UPDATE = 0x483, - SMSG_THREAT_REMOVE = 0x484, - SMSG_THREAT_CLEAR = 0x485, - SMSG_CONVERT_RUNE = 0x486, - SMSG_RESYNC_RUNES = 0x487, - SMSG_ADD_RUNE_POWER = 0x488, - CMSG_START_QUEST = 0x489, - CMSG_REMOVE_GLYPH = 0x48A, - CMSG_DUMP_OBJECTS = 0x48B, - SMSG_DUMP_OBJECTS_DATA = 0x48C, - CMSG_DISMISS_CRITTER = 0x48D, - SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x48E, - CMSG_AUCTION_LIST_PENDING_SALES = 0x48F, - SMSG_AUCTION_LIST_PENDING_SALES = 0x490, - SMSG_MODIFY_COOLDOWN = 0x491, - SMSG_PET_UPDATE_COMBO_POINTS = 0x492, - CMSG_ENABLETAXI = 0x493, - SMSG_PRE_RESURRECT = 0x494, - SMSG_AURA_UPDATE_ALL = 0x495, - SMSG_AURA_UPDATE = 0x496, - CMSG_FLOOD_GRACE_CHEAT = 0x497, - SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498, - SMSG_PET_LEARNED_SPELL = 0x499, - SMSG_PET_REMOVED_SPELL = 0x49A, - CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x49B, - CMSG_HEARTH_AND_RESURRECT = 0x49C, // not changed in 3.1 - SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x49D, // not changed 9626 - SMSG_CRITERIA_DELETED = 0x49E, // not changed 9626 - SMSG_ACHIEVEMENT_DELETED = 0x49F, // not changed 9626 - CMSG_SERVER_INFO_QUERY = 0x4A0, // not found - SMSG_SERVER_INFO_RESPONSE = 0x4A1, // not found - CMSG_CHECK_LOGIN_CRITERIA = 0x4A2, // not found - SMSG_SERVER_BUCK_DATA_START = 0x4A3, // not found - CMSG_QUERY_VEHICLE_STATUS = 0x4A4, // not found - UMSG_UNKNOWN_1189 = 0x4A5, // not found, old SMSG_PET_GUIDS - SMSG_BATTLEGROUND_INFO_THROTTLED = 0x4A6, // empty, "You can't do that yet" - SMSG_PLAYER_VEHICLE_DATA = 0x4A7, // smsg guid+uint32 (vehicle) - CMSG_PLAYER_VEHICLE_ENTER = 0x4A8, // cmsg uint64 - CMSG_EJECT_PASSENGER = 0x4A9, // cmsg uint64 - SMSG_PET_GUIDS = 0x4AA, // shifted+5 - SMSG_CLIENTCACHE_VERSION = 0x4AB, // shifted+5 - UMSG_UNKNOWN_1196 = 0x4AC, // not found - UMSG_UNKNOWN_1197 = 0x4AD, // not found - UMSG_UNKNOWN_1198 = 0x4AE, // not found - UMSG_UNKNOWN_1199 = 0x4AF, // not found - UMSG_UNKNOWN_1200 = 0x4B0, // not found - UMSG_UNKNOWN_1201 = 0x4B1, // not found - SMSG_ITEM_REFUND_INFO_RESPONSE = 0x4B2, // refund item info - CMSG_ITEM_REFUND_INFO = 0x4B3, // refund request? - CMSG_ITEM_REFUND = 0x4B4, // lua: ContainerRefundItemPurchase - SMSG_ITEM_REFUND_RESULT = 0x4B5, // refund item result - CMSG_CORPSE_MAP_POSITION_QUERY = 0x4B6, // CMSG, uint32 - SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x4B7, // SMSG, 3*float+float - UMSG_UNKNOWN_1208 = 0x4B8, // not found - UMSG_UNKNOWN_1209 = 0x4B9, // not found - CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP = 0x4BA, // CMSG, uint64, lua: CalendarContextEventSignUp - SMSG_CALENDAR_ACTION_PENDING = 0x4BB, // SMSG, calendar related EVENT_CALENDAR_ACTION_PENDING - SMSG_EQUIPMENT_SET_LIST = 0x4BC, // SMSG, equipment manager list? - CMSG_EQUIPMENT_SET_SAVE = 0x4BD, // CMSG, lua: SaveEquipmentSet - CMSG_UPDATE_PROJECTILE_POSITION = 0x4BE, // CMSG, uint64 caster, uint32 spellId, uint8 castId, vector3 position - SMSG_SET_PROJECTILE_POSITION = 0x4BF, // SMSG, uint64 caster, uint8 castId, vector3 position - SMSG_TALENTS_INFO = 0x4C0, // SMSG, talents related - CMSG_LEARN_PREVIEW_TALENTS = 0x4C1, // CMSG, lua: LearnPreviewTalents (for player?) - CMSG_LEARN_PREVIEW_TALENTS_PET = 0x4C2, // CMSG, lua: LearnPreviewTalents (for pet?) - UMSG_UNKNOWN_1219 = 0x4C3, // not found 3.2 - UMSG_UNKNOWN_1220 = 0x4C4, // not found 3.2 - UMSG_UNKNOWN_1221 = 0x4C5, // not found 3.2 - UMSG_UNKNOWN_1222 = 0x4C6, // not found 3.2 - SMSG_ARENA_OPPONENT_UPDATE = 0x4C7, // uint64, EVENT_ARENA_OPPONENT_UPDATE - SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED = 0x4C8, // uint32 "Can't modify arena team while queued or in a match." 3.2 - UMSG_UNKNOWN_1225 = 0x4C9, // not found 3.2 - UMSG_UNKNOWN_1226 = 0x4CA, // not found 3.2 - UMSG_UNKNOWN_1227 = 0x4CB, // not found 3.2 - UMSG_UNKNOWN_1228 = 0x4CC, // not found 3.2 - SMSG_MULTIPLE_PACKETS = 0x4CD, // SMSG, handles any opcode - SMSG_FORCE_UNK1_SPEED_CHANGE = 0x4CE, // SMSG, movement related - CMSG_FORCE_UNK1_SPEED_CHANGE_ACK = 0x4CF, // movement related - SMSG_FORCE_UNK2_SPEED_CHANGE = 0x4D0, // SMSG, movement related - CMSG_FORCE_UNK2_SPEED_CHANGE_ACK = 0x4D1, // movement related - MSG_MOVE_UNKNOWN_1234 = 0x4D2, // SMSG, movement related - SMSG_SPLINE_MOVE_UNKNOWN_1235 = 0x4D3, // SMSG, movement related - SMSG_SPLINE_MOVE_UNKNOWN_1236 = 0x4D4, // SMSG, movement related - CMSG_EQUIPMENT_SET_USE = 0x4D5, // CMSG, lua: UseEquipmentSet - SMSG_EQUIPMENT_SET_USE_RESULT = 0x4D6, // SMSG, UseEquipmentSetResult? - UMSG_UNKNOWN_1239 = 0x4D7, // not found 3.2 - SMSG_UNKNOWN_1240 = 0x4D8, // SMSG, uint64, string, doing nothing - CMSG_CHAR_FACTION_CHANGE = 0x4D9, // lua: CreateCharacter (PFC client response) - SMSG_CHAR_FACTION_CHANGE = 0x4DA, // response to 1241 (PFC server response) - UMSG_UNKNOWN_1243 = 0x4DB, // not found 3.2 - UMSG_UNKNOWN_1244 = 0x4DC, // not found 3.2 - UMSG_UNKNOWN_1245 = 0x4DD, // not found 3.2 - SMSG_BATTLEFIELD_MGR_ENTRY_INVITE = 0x4DE, // uint32, EVENT_BATTLEFIELD_MGR_ENTRY_INVITE - CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE = 0x4DF, // lua: BattlefieldMgrEntryInviteResponse - SMSG_BATTLEFIELD_MGR_ENTERED = 0x4E0, // uint32, uint8, uint8 EVENT_BATTLEFIELD_MGR_ENTERED - SMSG_BATTLEFIELD_MGR_QUEUE_INVITE = 0x4E1, // uint32 EVENT_BATTLEFIELD_MGR_QUEUE_INVITE - CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE = 0x4E2, // lua: BattlefieldMgrQueueInviteResponse - CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST = 0x4E3, // lua: BattlefieldMgrQueueRequest - SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE = 0x4E4, // uint32, uint8 EVENT_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE - SMSG_BATTLEFIELD_MGR_EJECT_PENDING = 0x4E5, // uint32 EVENT_BATTLEFIELD_MGR_EJECT_PENDING - SMSG_BATTLEFIELD_MGR_EJECTED = 0x4E6, // uint32, uint32, uint8 EVENT_BATTLEFIELD_MGR_EJECTED - CMSG_BATTLEFIELD_MGR_EXIT_REQUEST = 0x4E7, // lua: BattlefieldMgrExitRequest - SMSG_BATTLEFIELD_MGR_STATE_CHANGE = 0x4E8, // uint32, uint32 EVENT_BATTLEFIELD_MGR_STATE_CHANGE - UMSG_UNKNOWN_1257 = 0x4E9, // not found 3.2 - UMSG_UNKNOWN_1258 = 0x4EA, // not found 3.2 - MSG_SET_RAID_DIFFICULTY = 0x4EB, // lua: SetRaidDifficulty - UMSG_UNKNOWN_1260 = 0x4EC, // not found 3.2 - SMSG_TOGGLE_XP_GAIN = 0x4ED, // enable/disable XP gain console message - SMSG_GMRESPONSE_DB_ERROR = 0x4EE, // empty - SMSG_GMRESPONSE_RECEIVED = 0x4EF, // uint32, uint32, string[2000], string[4000][4] - CMSG_GMRESPONSE_RESOLVE = 0x4F0, // lua: GMResponseResolve - SMSG_GMRESPONSE_STATUS_UPDATE = 0x4F1, // uint8 (1 - EVENT_GMSURVEY_DISPLAY, 0 - EVENT_UPDATE_TICKET) - UMSG_UNKNOWN_1266 = 0x4F2, // not found 3.2 - UMSG_UNKNOWN_1267 = 0x4F3, // not found 3.2 - UMSG_UNKNOWN_1268 = 0x4F4, // not found 3.2 - UMSG_UNKNOWN_1269 = 0x4F5, // not found 3.2 - CMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F6, - SMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F7, - CMSG_CHAR_RACE_CHANGE = 0x4F8, // called from lua: CreateCharacter, paid race change - UMSG_UNKNOWN_1273 = 0x4F9, // not found 10554 - SMSG_TALENTS_INVOLUNTARILY_RESET = 0x4FA, // uint8 EVENT_TALENTS_INVOLUNTARILY_RESET - UMSG_UNKNOWN_1275 = 0x4FB, // not found 10554 - SMSG_UNKNOWN_1276 = 0x4FC, // does nothing in 10554 - SMSG_LOOT_SLOT_CHANGED = 0x4FD, // EVENT_LOOT_SLOT_CHANGED - UMSG_UNKNOWN_1278 = 0x4FE, // not found 10596 - CMSG_READY_FOR_ACCOUNT_DATA_TIMES = 0x4FF, // lua: ReadyForAccountDataTimes - CMSG_QUERY_QUESTS_COMPLETED = 0x500, // lua: QueryQuestsCompleted - SMSG_QUERY_QUESTS_COMPLETED_RESPONSE = 0x501, // response to 0x500 - CMSG_GM_REPORT_LAG = 0x502, // lua: GMReportLag - UMSG_UNKNOWN_1283 = 0x503, - UMSG_UNKNOWN_1284 = 0x504, - UMSG_UNKNOWN_1285 = 0x505, - SMSG_CORPSE_NOT_IN_INSTANCE = 0x506, - UMSG_UNKNOWN_1287 = 0x507, // not found - CMSG_SET_ALLOW_LOW_LEVEL_RAID1 = 0x508, // lua: SetAllowLowLevelRaid - CMSG_SET_ALLOW_LOW_LEVEL_RAID2 = 0x509, // lua: SetAllowLowLevelRaid - SMSG_CAMERA_SHAKE = 0x50A, // uint32 SpellEffectCameraShakes.dbc index, uint32 - SMSG_UPDATE_ITEM_ENCHANTMENTS = 0x50B, // some item update packet? - UMSG_UNKNOWN_1292 = 0x50C, // not found - SMSG_REDIRECT_CLIENT = 0x50D, // uint32 ip, uint16 port, uint32 unk, uint8[20] hash (ip + port, seed=sessionkey) - CMSG_REDIRECTION_FAILED = 0x50E, // something with networking - SMSG_UNKNOWN_1295 = 0x50F, // not found - disconnect - CMSG_UNKNOWN_1296 = 0x510, // something with networking - SMSG_FORCE_SEND_QUEUED_PACKETS = 0x511, // not found - crash - CMSG_REDIRECTION_AUTH_PROOF = 0x512, // something with networking - UMSG_UNKNOWN_1299 = 0x513, // not found - SMSG_UNKNOWN_1300 = 0x514, // SMSG - SMSG_UNKNOWN_1301 = 0x515, // event 0x204 (opens dungeon finder, probably for outdoor bosses) - SMSG_UNKNOWN_1302 = 0x516, // something with player movement (move event 58?) - CMSG_UNKNOWN_1303 = 0x517, // something with player movement (move event 58?) - SMSG_UNKNOWN_1304 = 0x518, // something with player movement (move event 58?), speed packet - UMSG_UNKNOWN_1305 = 0x519, // not found - UMSG_UNKNOWN_1306 = 0x51A, // not found - NUM_MSG_TYPES = 0x51B -}; - -/// Player state -enum SessionStatus -{ - STATUS_AUTHED = 0, ///< Player authenticated (_player == NULL, m_playerRecentlyLogout = false or will be reset before handler call, m_GUID have garbage) - STATUS_LOGGEDIN, ///< Player in game (_player != NULL, m_GUID == _player->GetGUID(), inWorld()) - STATUS_TRANSFER, ///< Player transferring to another map (_player != NULL, m_GUID == _player->GetGUID(), !inWorld()) - STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, ///< _player!= NULL or _player == NULL && m_playerRecentlyLogout, m_GUID store last _player guid) - STATUS_NEVER ///< Opcode not accepted from client (deprecated or server side only) -}; - -class WorldPacket; - -struct OpcodeHandler -{ - char const* name; - SessionStatus status; - void (WorldSession::*handler)(WorldPacket& recvPacket); -}; - -extern OpcodeHandler opcodeTable[NUM_MSG_TYPES]; - -/// Lookup opcode name for human understandable logging -inline const char* LookupOpcodeName(uint16 id) -{ - if (id >= NUM_MSG_TYPES) - return "Received unknown opcode, it's more than max!"; - return opcodeTable[id].name; -} -#endif -/// @} diff --git a/src/server/game/OutdoorPvP/OutdoorPvPEP.cpp b/src/server/game/OutdoorPvP/OutdoorPvPEP.cpp deleted file mode 100644 index 5691a3ce8be..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPEP.cpp +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "OutdoorPvPEP.h" -#include "WorldPacket.h" -#include "Player.h" -#include "GameObject.h" -#include "ObjectMgr.h" -#include "ObjectAccessor.h" -#include "OutdoorPvPMgr.h" -#include "Creature.h" -#include "Language.h" -#include "World.h" -#include "GossipDef.h" - -OPvPCapturePointEP_EWT::OPvPCapturePointEP_EWT(OutdoorPvP *pvp) -: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_UnitsSummonedSide(0) -{ - SetCapturePointData(EPCapturePoints[EP_EWT].entry,EPCapturePoints[EP_EWT].map,EPCapturePoints[EP_EWT].x,EPCapturePoints[EP_EWT].y,EPCapturePoints[EP_EWT].z,EPCapturePoints[EP_EWT].o,EPCapturePoints[EP_EWT].rot0,EPCapturePoints[EP_EWT].rot1,EPCapturePoints[EP_EWT].rot2,EPCapturePoints[EP_EWT].rot3); - AddObject(EP_EWT_FLAGS,EPTowerFlags[EP_EWT].entry,EPTowerFlags[EP_EWT].map,EPTowerFlags[EP_EWT].x,EPTowerFlags[EP_EWT].y,EPTowerFlags[EP_EWT].z,EPTowerFlags[EP_EWT].o,EPTowerFlags[EP_EWT].rot0,EPTowerFlags[EP_EWT].rot1,EPTowerFlags[EP_EWT].rot2,EPTowerFlags[EP_EWT].rot3); -} - -void OPvPCapturePointEP_EWT::ChangeState() -{ - if (fabs(m_value) == m_maxValue) // state won't change, only phase when maxed out! - { - // if changing from controlling alliance to horde or vice versa - if (m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State) - { - sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_EWT_A)); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_EWT] = 0; - } - else if (m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State) - { - sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_EWT_H)); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_EWT] = 0; - } - - uint32 artkit = 21; - - switch(m_State) - { - case OBJECTIVESTATE_ALLIANCE: - if (m_value == m_maxValue) - m_TowerState = EP_TS_A; - else - m_TowerState = EP_TS_A_P; - artkit = 2; - SummonSupportUnitAtNorthpassTower(ALLIANCE); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_EWT] = ALLIANCE; - if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A)); - break; - case OBJECTIVESTATE_HORDE: - if (m_value == -m_maxValue) - m_TowerState = EP_TS_H; - else - m_TowerState = EP_TS_H_P; - artkit = 1; - SummonSupportUnitAtNorthpassTower(HORDE); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_EWT] = HORDE; - if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H)); - break; - case OBJECTIVESTATE_NEUTRAL: - m_TowerState = EP_TS_N; - break; - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - m_TowerState = EP_TS_N_A; - break; - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - m_TowerState = EP_TS_N_H; - break; - } - - GameObject* flag = HashMapHolder::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder::Find(m_Objects[EP_EWT_FLAGS]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit); - } - - UpdateTowerState(); - - // complete quest objective - if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H) - SendObjectiveComplete(EP_EWT_CM, 0); - } -} - -void OPvPCapturePointEP_EWT::SendChangePhase() -{ - // send this too, sometimes the slider disappears, dunno why :( - SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); - // send these updates to only the ones in this objective - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); - // send this too, sometimes it resets :S - SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); -} - -void OPvPCapturePointEP_EWT::FillInitialWorldStates(WorldPacket &data) -{ - data << EP_EWT_A << uint32(bool(m_TowerState & EP_TS_A)); - data << EP_EWT_H << uint32(bool(m_TowerState & EP_TS_H)); - data << EP_EWT_A_P << uint32(bool(m_TowerState & EP_TS_A_P)); - data << EP_EWT_H_P << uint32(bool(m_TowerState & EP_TS_H_P)); - data << EP_EWT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); - data << EP_EWT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); - data << EP_EWT_N << uint32(bool(m_TowerState & EP_TS_N)); -} - -void OPvPCapturePointEP_EWT::UpdateTowerState() -{ - m_PvP->SendUpdateWorldState(EP_EWT_A , bool(m_TowerState & EP_TS_A)); - m_PvP->SendUpdateWorldState(EP_EWT_H , bool(m_TowerState & EP_TS_H)); - m_PvP->SendUpdateWorldState(EP_EWT_A_P , bool(m_TowerState & EP_TS_A_P)); - m_PvP->SendUpdateWorldState(EP_EWT_H_P , bool(m_TowerState & EP_TS_H_P)); - m_PvP->SendUpdateWorldState(EP_EWT_N_A , bool(m_TowerState & EP_TS_N_A)); - m_PvP->SendUpdateWorldState(EP_EWT_N_H , bool(m_TowerState & EP_TS_N_H)); - m_PvP->SendUpdateWorldState(EP_EWT_N , bool(m_TowerState & EP_TS_N)); -} - -bool OPvPCapturePointEP_EWT::HandlePlayerEnter(Player *plr) -{ - if (OPvPCapturePoint::HandlePlayerEnter(plr)) - { - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); - return true; - } - return false; -} - -void OPvPCapturePointEP_EWT::HandlePlayerLeave(Player *plr) -{ - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0); - OPvPCapturePoint::HandlePlayerLeave(plr); -} - -void OPvPCapturePointEP_EWT::SummonSupportUnitAtNorthpassTower(uint32 team) -{ - if (m_UnitsSummonedSide != team) - { - m_UnitsSummonedSide = team; - const creature_type * ct = NULL; - if (team == ALLIANCE) - ct=EP_EWT_Summons_A; - else - ct=EP_EWT_Summons_H; - - for (int i = 0; i < EP_EWT_NUM_CREATURES; ++i) - { - DelCreature(i); - AddCreature(i,ct[i].entry,ct[i].teamval,ct[i].map,ct[i].x,ct[i].y,ct[i].z,ct[i].o,1000000); - } - } -} - -// NPT -OPvPCapturePointEP_NPT::OPvPCapturePointEP_NPT(OutdoorPvP *pvp) -: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_SummonedGOSide(0) -{ - SetCapturePointData(EPCapturePoints[EP_NPT].entry,EPCapturePoints[EP_NPT].map,EPCapturePoints[EP_NPT].x,EPCapturePoints[EP_NPT].y,EPCapturePoints[EP_NPT].z,EPCapturePoints[EP_NPT].o,EPCapturePoints[EP_NPT].rot0,EPCapturePoints[EP_NPT].rot1,EPCapturePoints[EP_NPT].rot2,EPCapturePoints[EP_NPT].rot3); - AddObject(EP_NPT_FLAGS,EPTowerFlags[EP_NPT].entry,EPTowerFlags[EP_NPT].map,EPTowerFlags[EP_NPT].x,EPTowerFlags[EP_NPT].y,EPTowerFlags[EP_NPT].z,EPTowerFlags[EP_NPT].o,EPTowerFlags[EP_NPT].rot0,EPTowerFlags[EP_NPT].rot1,EPTowerFlags[EP_NPT].rot2,EPTowerFlags[EP_NPT].rot3); -} - -void OPvPCapturePointEP_NPT::ChangeState() -{ - if (fabs(m_value) == m_maxValue) // state won't change, only phase when maxed out! - { - // if changing from controlling alliance to horde or vice versa - if (m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State) - { - sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_NPT_A)); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_NPT] = 0; - } - else if (m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State) - { - sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_NPT_H)); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_NPT] = 0; - } - - uint32 artkit = 21; - - switch(m_State) - { - case OBJECTIVESTATE_ALLIANCE: - if (m_value == m_maxValue) - m_TowerState = EP_TS_A; - else - m_TowerState = EP_TS_A_P; - artkit = 2; - SummonGO(ALLIANCE); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_NPT] = ALLIANCE; - if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A)); - break; - case OBJECTIVESTATE_HORDE: - if (m_value == -m_maxValue) - m_TowerState = EP_TS_H; - else - m_TowerState = EP_TS_H_P; - artkit = 1; - SummonGO(HORDE); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_NPT] = HORDE; - if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H)); - break; - case OBJECTIVESTATE_NEUTRAL: - m_TowerState = EP_TS_N; - m_SummonedGOSide = 0; - DelObject(EP_NPT_BUFF); - break; - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - m_TowerState = EP_TS_N_A; - break; - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - m_TowerState = EP_TS_N_H; - break; - } - - GameObject* flag = HashMapHolder::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder::Find(m_Objects[EP_NPT_FLAGS]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit); - } - - UpdateTowerState(); - - // complete quest objective - if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H) - SendObjectiveComplete(EP_NPT_CM, 0); - } -} - -void OPvPCapturePointEP_NPT::SendChangePhase() -{ - // send this too, sometimes the slider disappears, dunno why :( - SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); - // send these updates to only the ones in this objective - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); - // send this too, sometimes it resets :S - SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); -} - -void OPvPCapturePointEP_NPT::FillInitialWorldStates(WorldPacket &data) -{ - data << EP_NPT_A << uint32(bool(m_TowerState & EP_TS_A)); - data << EP_NPT_H << uint32(bool(m_TowerState & EP_TS_H)); - data << EP_NPT_A_P << uint32(bool(m_TowerState & EP_TS_A_P)); - data << EP_NPT_H_P << uint32(bool(m_TowerState & EP_TS_H_P)); - data << EP_NPT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); - data << EP_NPT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); - data << EP_NPT_N << uint32(bool(m_TowerState & EP_TS_N)); -} - -void OPvPCapturePointEP_NPT::UpdateTowerState() -{ - m_PvP->SendUpdateWorldState(EP_NPT_A , bool(m_TowerState & EP_TS_A)); - m_PvP->SendUpdateWorldState(EP_NPT_H , bool(m_TowerState & EP_TS_H)); - m_PvP->SendUpdateWorldState(EP_NPT_A_P , bool(m_TowerState & EP_TS_A_P)); - m_PvP->SendUpdateWorldState(EP_NPT_H_P , bool(m_TowerState & EP_TS_H_P)); - m_PvP->SendUpdateWorldState(EP_NPT_N_A , bool(m_TowerState & EP_TS_N_A)); - m_PvP->SendUpdateWorldState(EP_NPT_N_H , bool(m_TowerState & EP_TS_N_H)); - m_PvP->SendUpdateWorldState(EP_NPT_N , bool(m_TowerState & EP_TS_N)); -} - -bool OPvPCapturePointEP_NPT::HandlePlayerEnter(Player *plr) -{ - if (OPvPCapturePoint::HandlePlayerEnter(plr)) - { - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); - return true; - } - return false; -} - -void OPvPCapturePointEP_NPT::HandlePlayerLeave(Player *plr) -{ - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0); - OPvPCapturePoint::HandlePlayerLeave(plr); -} - -void OPvPCapturePointEP_NPT::SummonGO(uint32 team) -{ - if (m_SummonedGOSide != team) - { - m_SummonedGOSide = team; - DelObject(EP_NPT_BUFF); - AddObject(EP_NPT_BUFF,EP_NPT_LordaeronShrine.entry,EP_NPT_LordaeronShrine.map,EP_NPT_LordaeronShrine.x,EP_NPT_LordaeronShrine.y,EP_NPT_LordaeronShrine.z,EP_NPT_LordaeronShrine.o,EP_NPT_LordaeronShrine.rot0,EP_NPT_LordaeronShrine.rot1,EP_NPT_LordaeronShrine.rot2,EP_NPT_LordaeronShrine.rot3); - GameObject * go = HashMapHolder::Find(m_Objects[EP_NPT_BUFF]); - if (go) - go->SetUInt32Value(GAMEOBJECT_FACTION,(team == ALLIANCE ? 84 : 83)); - } -} - -// CGT -OPvPCapturePointEP_CGT::OPvPCapturePointEP_CGT(OutdoorPvP *pvp) -: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_GraveyardSide(0) -{ - SetCapturePointData(EPCapturePoints[EP_CGT].entry,EPCapturePoints[EP_CGT].map,EPCapturePoints[EP_CGT].x,EPCapturePoints[EP_CGT].y,EPCapturePoints[EP_CGT].z,EPCapturePoints[EP_CGT].o,EPCapturePoints[EP_CGT].rot0,EPCapturePoints[EP_CGT].rot1,EPCapturePoints[EP_CGT].rot2,EPCapturePoints[EP_CGT].rot3); - AddObject(EP_CGT_FLAGS,EPTowerFlags[EP_CGT].entry,EPTowerFlags[EP_CGT].map,EPTowerFlags[EP_CGT].x,EPTowerFlags[EP_CGT].y,EPTowerFlags[EP_CGT].z,EPTowerFlags[EP_CGT].o,EPTowerFlags[EP_CGT].rot0,EPTowerFlags[EP_CGT].rot1,EPTowerFlags[EP_CGT].rot2,EPTowerFlags[EP_CGT].rot3); -} - -void OPvPCapturePointEP_CGT::ChangeState() -{ - if (fabs(m_value) == m_maxValue) // state won't change, only phase when maxed out! - { - // if changing from controlling alliance to horde or vice versa - if (m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State) - { - sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_CGT_A)); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_CGT] = 0; - } - else if (m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State) - { - sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_CGT_H)); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_CGT] = 0; - } - - uint32 artkit = 21; - - switch(m_State) - { - case OBJECTIVESTATE_ALLIANCE: - if (m_value == m_maxValue) - m_TowerState = EP_TS_A; - else - m_TowerState = EP_TS_A_P; - artkit = 2; - LinkGraveYard(ALLIANCE); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_CGT] = ALLIANCE; - if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A)); - break; - case OBJECTIVESTATE_HORDE: - if (m_value == -m_maxValue) - m_TowerState = EP_TS_H; - else - m_TowerState = EP_TS_H_P; - artkit = 1; - LinkGraveYard(HORDE); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_CGT] = HORDE; - if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H)); - break; - case OBJECTIVESTATE_NEUTRAL: - m_TowerState = EP_TS_N; - break; - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - m_TowerState = EP_TS_N_A; - break; - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - m_TowerState = EP_TS_N_H; - break; - } - - GameObject* flag = HashMapHolder::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder::Find(m_Objects[EP_CGT_FLAGS]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit); - } - - UpdateTowerState(); - - // complete quest objective - if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H) - SendObjectiveComplete(EP_CGT_CM, 0); - } -} - -void OPvPCapturePointEP_CGT::SendChangePhase() -{ - // send this too, sometimes the slider disappears, dunno why :( - SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); - // send these updates to only the ones in this objective - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); - // send this too, sometimes it resets :S - SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); -} - -void OPvPCapturePointEP_CGT::FillInitialWorldStates(WorldPacket &data) -{ - data << EP_CGT_A << uint32(bool(m_TowerState & EP_TS_A)); - data << EP_CGT_H << uint32(bool(m_TowerState & EP_TS_H)); - data << EP_CGT_A_P << uint32(bool(m_TowerState & EP_TS_A_P)); - data << EP_CGT_H_P << uint32(bool(m_TowerState & EP_TS_H_P)); - data << EP_CGT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); - data << EP_CGT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); - data << EP_CGT_N << uint32(bool(m_TowerState & EP_TS_N)); -} - -void OPvPCapturePointEP_CGT::UpdateTowerState() -{ - m_PvP->SendUpdateWorldState(EP_CGT_A , bool(m_TowerState & EP_TS_A)); - m_PvP->SendUpdateWorldState(EP_CGT_H , bool(m_TowerState & EP_TS_H)); - m_PvP->SendUpdateWorldState(EP_CGT_A_P , bool(m_TowerState & EP_TS_A_P)); - m_PvP->SendUpdateWorldState(EP_CGT_H_P , bool(m_TowerState & EP_TS_H_P)); - m_PvP->SendUpdateWorldState(EP_CGT_N_A , bool(m_TowerState & EP_TS_N_A)); - m_PvP->SendUpdateWorldState(EP_CGT_N_H , bool(m_TowerState & EP_TS_N_H)); - m_PvP->SendUpdateWorldState(EP_CGT_N , bool(m_TowerState & EP_TS_N)); -} - -bool OPvPCapturePointEP_CGT::HandlePlayerEnter(Player *plr) -{ - if (OPvPCapturePoint::HandlePlayerEnter(plr)) - { - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); - return true; - } - return false; -} - -void OPvPCapturePointEP_CGT::HandlePlayerLeave(Player *plr) -{ - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0); - OPvPCapturePoint::HandlePlayerLeave(plr); -} - -void OPvPCapturePointEP_CGT::LinkGraveYard(uint32 team) -{ - if (m_GraveyardSide != team) - { - m_GraveyardSide = team; - objmgr.RemoveGraveYardLink(EP_GraveYardId,EP_GraveYardZone,team,false); - objmgr.AddGraveYardLink(EP_GraveYardId,EP_GraveYardZone,team,false); - } -} - -// PWT -OPvPCapturePointEP_PWT::OPvPCapturePointEP_PWT(OutdoorPvP *pvp) -: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_FlightMasterSpawned(0) -{ - SetCapturePointData(EPCapturePoints[EP_PWT].entry,EPCapturePoints[EP_PWT].map,EPCapturePoints[EP_PWT].x,EPCapturePoints[EP_PWT].y,EPCapturePoints[EP_PWT].z,EPCapturePoints[EP_PWT].o,EPCapturePoints[EP_PWT].rot0,EPCapturePoints[EP_PWT].rot1,EPCapturePoints[EP_PWT].rot2,EPCapturePoints[EP_PWT].rot3); - AddObject(EP_PWT_FLAGS,EPTowerFlags[EP_PWT].entry,EPTowerFlags[EP_PWT].map,EPTowerFlags[EP_PWT].x,EPTowerFlags[EP_PWT].y,EPTowerFlags[EP_PWT].z,EPTowerFlags[EP_PWT].o,EPTowerFlags[EP_PWT].rot0,EPTowerFlags[EP_PWT].rot1,EPTowerFlags[EP_PWT].rot2,EPTowerFlags[EP_PWT].rot3); -} - -void OPvPCapturePointEP_PWT::ChangeState() -{ - if (fabs(m_value) == m_maxValue) // state won't change, only phase when maxed out! - { - // if changing from controlling alliance to horde or vice versa - if (m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State) - { - sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_PWT_A)); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_PWT] = 0; - } - else if (m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State) - { - sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_PWT_H)); - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_PWT] = 0; - } - - uint32 artkit = 21; - - switch(m_State) - { - case OBJECTIVESTATE_ALLIANCE: - if (m_value == m_maxValue) - m_TowerState = EP_TS_A; - else - m_TowerState = EP_TS_A_P; - SummonFlightMaster(ALLIANCE); - artkit = 2; - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_PWT] = ALLIANCE; - if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A)); - break; - case OBJECTIVESTATE_HORDE: - if (m_value == -m_maxValue) - m_TowerState = EP_TS_H; - else - m_TowerState = EP_TS_H_P; - SummonFlightMaster(HORDE); - artkit = 1; - ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_PWT] = HORDE; - if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H)); - break; - case OBJECTIVESTATE_NEUTRAL: - m_TowerState = EP_TS_N; - DelCreature(EP_PWT_FLIGHTMASTER); - m_FlightMasterSpawned = 0; - break; - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - m_TowerState = EP_TS_N_A; - break; - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - m_TowerState = EP_TS_N_H; - break; - } - - GameObject* flag = HashMapHolder::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder::Find(m_Objects[EP_PWT_FLAGS]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit); - } - - UpdateTowerState(); - - // complete quest objective - if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H) - SendObjectiveComplete(EP_PWT_CM, 0); - } -} - -void OPvPCapturePointEP_PWT::SendChangePhase() -{ - // send this too, sometimes the slider disappears, dunno why :( - SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); - // send these updates to only the ones in this objective - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); - // send this too, sometimes it resets :S - SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); -} - -void OPvPCapturePointEP_PWT::FillInitialWorldStates(WorldPacket &data) -{ - data << EP_PWT_A << uint32(bool(m_TowerState & EP_TS_A)); - data << EP_PWT_H << uint32(bool(m_TowerState & EP_TS_H)); - data << EP_PWT_A_P << uint32(bool(m_TowerState & EP_TS_A_P)); - data << EP_PWT_H_P << uint32(bool(m_TowerState & EP_TS_H_P)); - data << EP_PWT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); - data << EP_PWT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); - data << EP_PWT_N << uint32(bool(m_TowerState & EP_TS_N)); -} - -void OPvPCapturePointEP_PWT::UpdateTowerState() -{ - m_PvP->SendUpdateWorldState(EP_PWT_A , bool(m_TowerState & EP_TS_A)); - m_PvP->SendUpdateWorldState(EP_PWT_H , bool(m_TowerState & EP_TS_H)); - m_PvP->SendUpdateWorldState(EP_PWT_A_P , bool(m_TowerState & EP_TS_A_P)); - m_PvP->SendUpdateWorldState(EP_PWT_H_P , bool(m_TowerState & EP_TS_H_P)); - m_PvP->SendUpdateWorldState(EP_PWT_N_A , bool(m_TowerState & EP_TS_N_A)); - m_PvP->SendUpdateWorldState(EP_PWT_N_H , bool(m_TowerState & EP_TS_N_H)); - m_PvP->SendUpdateWorldState(EP_PWT_N , bool(m_TowerState & EP_TS_N)); -} - -bool OPvPCapturePointEP_PWT::HandlePlayerEnter(Player *plr) -{ - if (OPvPCapturePoint::HandlePlayerEnter(plr)) - { - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); - return true; - } - return false; -} - -void OPvPCapturePointEP_PWT::HandlePlayerLeave(Player *plr) -{ - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0); - OPvPCapturePoint::HandlePlayerLeave(plr); -} - -void OPvPCapturePointEP_PWT::SummonFlightMaster(uint32 team) -{ - if (m_FlightMasterSpawned != team) - { - m_FlightMasterSpawned = team; - DelCreature(EP_PWT_FLIGHTMASTER); - AddCreature(EP_PWT_FLIGHTMASTER,EP_PWT_FlightMaster.entry,team,EP_PWT_FlightMaster.map,EP_PWT_FlightMaster.x,EP_PWT_FlightMaster.y,EP_PWT_FlightMaster.z,EP_PWT_FlightMaster.o); - } -} - -// ep -OutdoorPvPEP::OutdoorPvPEP() -{ - m_TypeId = OUTDOOR_PVP_EP; - memset(EP_Controls,0,sizeof(EP_Controls)); - m_AllianceTowersControlled = 0; - m_HordeTowersControlled = 0; -} - -bool OutdoorPvPEP::SetupOutdoorPvP() -{ - for (int i = 0; i < EPBuffZonesNum; ++i) - RegisterZone(EPBuffZones[i]); - - AddCapturePoint(new OPvPCapturePointEP_EWT(this)); - AddCapturePoint(new OPvPCapturePointEP_PWT(this)); - AddCapturePoint(new OPvPCapturePointEP_CGT(this)); - AddCapturePoint(new OPvPCapturePointEP_NPT(this)); - return true; -} - -bool OutdoorPvPEP::Update(uint32 diff) -{ - if (OutdoorPvP::Update(diff)) - { - m_AllianceTowersControlled = 0; - m_HordeTowersControlled = 0; - for (int i = 0; i < EP_TOWER_NUM; ++i) - { - if (EP_Controls[i] == ALLIANCE) - ++m_AllianceTowersControlled; - else if (EP_Controls[i] == HORDE) - ++m_HordeTowersControlled; - SendUpdateWorldState(EP_UI_TOWER_COUNT_A,m_AllianceTowersControlled); - SendUpdateWorldState(EP_UI_TOWER_COUNT_H,m_HordeTowersControlled); - BuffTeams(); - } - return true; - } - return false; -} - -void OutdoorPvPEP::HandlePlayerEnterZone(Player * plr, uint32 zone) -{ - // add buffs - if (plr->GetTeam() == ALLIANCE) - { - if (m_AllianceTowersControlled && m_AllianceTowersControlled < 5) - plr->CastSpell(plr,EP_AllianceBuffs[m_AllianceTowersControlled-1],true); - } - else - { - if (m_HordeTowersControlled && m_HordeTowersControlled < 5) - plr->CastSpell(plr,EP_HordeBuffs[m_HordeTowersControlled-1],true); - } - OutdoorPvP::HandlePlayerEnterZone(plr,zone); -} - -void OutdoorPvPEP::HandlePlayerLeaveZone(Player * plr, uint32 zone) -{ - // remove buffs - if (plr->GetTeam() == ALLIANCE) - { - for (int i = 0; i < 4; ++i) - plr->RemoveAurasDueToSpell(EP_AllianceBuffs[i]); - } - else - { - for (int i = 0; i < 4; ++i) - plr->RemoveAurasDueToSpell(EP_HordeBuffs[i]); - } - OutdoorPvP::HandlePlayerLeaveZone(plr, zone); -} - -void OutdoorPvPEP::BuffTeams() -{ - for (PlayerSet::iterator itr = m_players[0].begin(); itr != m_players[0].end(); ++itr) - { - Player * plr = *itr; - { - for (int i = 0; i < 4; ++i) - plr->RemoveAurasDueToSpell(EP_AllianceBuffs[i]); - if (m_AllianceTowersControlled && m_AllianceTowersControlled < 5) - plr->CastSpell(plr,EP_AllianceBuffs[m_AllianceTowersControlled-1],true); - } - } - for (PlayerSet::iterator itr = m_players[1].begin(); itr != m_players[1].end(); ++itr) - { - Player * plr = *itr; - { - for (int i = 0; i < 4; ++i) - plr->RemoveAurasDueToSpell(EP_HordeBuffs[i]); - if (m_HordeTowersControlled && m_HordeTowersControlled < 5) - plr->CastSpell(plr,EP_HordeBuffs[m_HordeTowersControlled-1],true); - } - } -} - -void OutdoorPvPEP::FillInitialWorldStates(WorldPacket & data) -{ - data << EP_UI_TOWER_COUNT_A << m_AllianceTowersControlled; - data << EP_UI_TOWER_COUNT_H << m_HordeTowersControlled; - data << EP_UI_TOWER_SLIDER_DISPLAY << uint32(0); - data << EP_UI_TOWER_SLIDER_POS << uint32(50); - data << EP_UI_TOWER_SLIDER_N << uint32(100); - for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) - { - itr->second->FillInitialWorldStates(data); - } -} - -void OutdoorPvPEP::SendRemoveWorldStates(Player *plr) -{ - plr->SendUpdateWorldState(EP_UI_TOWER_COUNT_A,0); - plr->SendUpdateWorldState(EP_UI_TOWER_COUNT_H,0); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY,0); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS,0); - plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N,0); - - plr->SendUpdateWorldState(EP_EWT_A,0); - plr->SendUpdateWorldState(EP_EWT_H,0); - plr->SendUpdateWorldState(EP_EWT_N,0); - plr->SendUpdateWorldState(EP_EWT_A_P,0); - plr->SendUpdateWorldState(EP_EWT_H_P,0); - plr->SendUpdateWorldState(EP_EWT_N_A,0); - plr->SendUpdateWorldState(EP_EWT_N_H,0); - - plr->SendUpdateWorldState(EP_PWT_A,0); - plr->SendUpdateWorldState(EP_PWT_H,0); - plr->SendUpdateWorldState(EP_PWT_N,0); - plr->SendUpdateWorldState(EP_PWT_A_P,0); - plr->SendUpdateWorldState(EP_PWT_H_P,0); - plr->SendUpdateWorldState(EP_PWT_N_A,0); - plr->SendUpdateWorldState(EP_PWT_N_H,0); - - plr->SendUpdateWorldState(EP_NPT_A,0); - plr->SendUpdateWorldState(EP_NPT_H,0); - plr->SendUpdateWorldState(EP_NPT_N,0); - plr->SendUpdateWorldState(EP_NPT_A_P,0); - plr->SendUpdateWorldState(EP_NPT_H_P,0); - plr->SendUpdateWorldState(EP_NPT_N_A,0); - plr->SendUpdateWorldState(EP_NPT_N_H,0); - - plr->SendUpdateWorldState(EP_CGT_A,0); - plr->SendUpdateWorldState(EP_CGT_H,0); - plr->SendUpdateWorldState(EP_CGT_N,0); - plr->SendUpdateWorldState(EP_CGT_A_P,0); - plr->SendUpdateWorldState(EP_CGT_H_P,0); - plr->SendUpdateWorldState(EP_CGT_N_A,0); - plr->SendUpdateWorldState(EP_CGT_N_H,0); -} - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPEP.h b/src/server/game/OutdoorPvP/OutdoorPvPEP.h deleted file mode 100644 index 071d6bcde2d..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPEP.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef OUTDOOR_PVP_EP_ -#define OUTDOOR_PVP_EP_ - -#include "OutdoorPvPImpl.h" - -#include "DBCStructure.h" - -const uint32 EP_AllianceBuffs[4] = {11413, 11414, 11415, 1386}; - -const uint32 EP_HordeBuffs[4] = {30880, 30683, 30682, 29520}; - -const uint32 EP_GraveYardZone = 139; - -const uint32 EP_GraveYardId = 927; - -const uint32 EPBuffZonesNum = 3; - -const uint32 EP_EWT_CM = 17690; -const uint32 EP_CGT_CM = 17689; -const uint32 EP_NPT_CM = 17696; -const uint32 EP_PWT_CM = 17698; - -const uint32 EPBuffZones[EPBuffZonesNum] = {139, 2017, 2057}; - -enum EP_TaxiNodes { - EP_CGT_Taxi = 87, - EP_EWT_Taxi = 86, - EP_NPT_Taxi = 85, - EP_PWT_Taxi = 84 -}; - -enum EP_EastwallTowerWorldStates { - EP_EWT_A = 2354, - EP_EWT_H = 2356, - EP_EWT_A_P = 2357, // ally progressing - EP_EWT_H_P = 2358, - EP_EWT_N_A = 2359, // ally conquested - EP_EWT_N_H = 2360, - EP_EWT_N = 2361 -}; - -enum EP_NorthpassTowerWorldStates { - EP_NPT_N = 2352, - EP_NPT_N_A = 2362, - EP_NPT_N_H = 2363, - EP_NPT_A_P = 2364, - EP_NPT_H_P = 2365, - EP_NPT_A = 2372, - EP_NPT_H = 2373 -}; - -enum EP_PlagewoodTowerWorldStates { - EP_PWT_N_A = 2366, - EP_PWT_N_H = 2353, //2367 not present! use neutral! - EP_PWT_A_P = 2368, - EP_PWT_H_P = 2369, - EP_PWT_A = 2370, - EP_PWT_H = 2371, - EP_PWT_N = 2353 -}; - -enum EP_CrownGuardTowerWorldStates { - EP_CGT_N_A = 2374, - EP_CGT_N_H = 2375, - EP_CGT_A_P = 2376, - EP_CGT_H_P = 2377, - EP_CGT_A = 2378, - EP_CGT_H = 2379, - EP_CGT_N = 2355 -}; - -enum EP_WorldStates { - EP_UI_TOWER_SLIDER_DISPLAY = 2426, - EP_UI_TOWER_SLIDER_POS = 2427, - EP_UI_TOWER_SLIDER_N = 2428, - - EP_UI_TOWER_COUNT_A = 2327, - EP_UI_TOWER_COUNT_H = 2328 -}; - -enum EP_Summons { - EP_EWT_COMMANDER = 0, - EP_EWT_SOLDIER1, - EP_EWT_SOLDIER2, - EP_EWT_SOLDIER3, - EP_EWT_SOLDIER4, - EP_PWT_FLIGHTMASTER, -}; - -enum EP_GoSummons { - EP_NPT_BUFF = 0, - EP_NPT_FLAGS, - EP_EWT_FLAGS, - EP_CGT_FLAGS, - EP_PWT_FLAGS -}; - -enum EP_Towers { - EP_EWT = 0, // plaguelands 03 - EP_NPT,// plaguelands 01 - EP_PWT,// plaguelands 04 - EP_CGT,// plaguelands 02 - EP_TOWER_NUM -}; - -const go_type EPCapturePoints[EP_TOWER_NUM] = { - {182097,0,2574.51,-4794.89,144.704,-1.45003,-0.097056,0.095578,-0.656229,0.742165}, - {181899,0,3181.08,-4379.36,174.123,-2.03472,-0.065392,0.119494,-0.842275,0.521553}, - {182098,0,2962.71,-3042.31,154.789,2.08426,-0.074807,-0.113837,0.855928,0.49883}, - {182096,0,1860.85,-3731.23,196.716,-2.53214,0.033967,-0.131914,0.944741,-0.298177} -}; - -const go_type EPTowerFlags[EP_TOWER_NUM] = { - {182106,0,2569.60,-4772.93,115.399,2.72271,0,0,0.978148,0.207912}, - {182106,0,3148.17,-4365.51,145.029,1.53589,0,0,0.694658,0.71934}, - {182106,0,2992.63,-3022.95,125.593,3.03687,0,0,0.99863,0.052336}, - {182106,0,1838.42,-3703.56,167.713,0.890118,0,0,0.430511,0.902585} -}; - -const uint32 EPTowerPlayerEnterEvents[EP_TOWER_NUM] = {10691,10699,10701,10705}; - -const uint32 EPTowerPlayerLeaveEvents[EP_TOWER_NUM] = {10692,10698,10700,10704}; - -const uint32 EP_NUM_CREATURES = 6; -const uint32 EP_EWT_NUM_CREATURES = 5; - -// one lordaeron commander, 4 soldiers -// should be spawned at EWT and follow a path, but trans-grid pathing isn't safe, so summon them directly at NPT -const creature_type EP_EWT_Summons_A[EP_EWT_NUM_CREATURES] = { - {17635,469,0, 3167.61,-4352.09,138.20,4.5811}, - {17647,469,0, 3172.74,-4352.99,139.14,4.9873}, - {17647,469,0, 3165.89,-4354.46,138.67,3.7244}, - {17647,469,0, 3164.65,-4350.26,138.22,2.4794}, - {17647,469,0, 3169.91,-4349.68,138.37,0.7444} -}; - -const creature_type EP_EWT_Summons_H[EP_EWT_NUM_CREATURES] = { - {17995,67,0, 3167.61,-4352.09,138.20,4.5811}, - {17996,67,0, 3172.74,-4352.99,139.14,4.9873}, - {17996,67,0, 3165.89,-4354.46,138.67,3.7244}, - {17996,67,0, 3164.65,-4350.26,138.22,2.4794}, - {17996,67,0, 3169.91,-4349.68,138.37,0.7444} -}; - -enum EP_TowerStates { - EP_TS_N = 1, - EP_TS_N_A = 2, - EP_TS_N_H = 4, - EP_TS_A_P = 8, - EP_TS_H_P = 16, - EP_TS_A = 32, - EP_TS_H = 64 -}; - -// when spawning, pay attention at setting the faction manually! -const creature_type EP_PWT_FlightMaster = {17209,0,0,2987.5,-3049.11,120.126,5.75959}; - -// after spawning, modify the faction so that only the controller will be able to use it with SetUInt32Value(GAMEOBJECT_FACTION, faction_id); -const go_type EP_NPT_LordaeronShrine = {181682,0,3167.72,-4355.91,138.785,1.69297,0,0,0.748956,0.66262}; - -class OutdoorPvPEP; - -class OPvPCapturePointEP_EWT : public OPvPCapturePoint -{ -friend class OutdoorPvPEP; -public: - OPvPCapturePointEP_EWT(OutdoorPvP * pvp); - void ChangeState(); - void SendChangePhase(); - void FillInitialWorldStates(WorldPacket & data); - // used when player is activated/inactivated in the area - bool HandlePlayerEnter(Player * plr); - void HandlePlayerLeave(Player * plr); -protected: - void SummonSupportUnitAtNorthpassTower(uint32 team); - void UpdateTowerState(); -protected: - uint32 m_TowerState; - uint32 m_UnitsSummonedSide; -}; - -class OPvPCapturePointEP_NPT : public OPvPCapturePoint -{ -friend class OutdoorPvPEP; -public: - OPvPCapturePointEP_NPT(OutdoorPvP * pvp); - void ChangeState(); - void SendChangePhase(); - void FillInitialWorldStates(WorldPacket & data); - // used when player is activated/inactivated in the area - bool HandlePlayerEnter(Player * plr); - void HandlePlayerLeave(Player * plr); -protected: - void SummonGO(uint32 team); - void UpdateTowerState(); -protected: - uint32 m_TowerState; - uint32 m_SummonedGOSide; -}; - -class OPvPCapturePointEP_CGT : public OPvPCapturePoint -{ -friend class OutdoorPvPEP; -public: - OPvPCapturePointEP_CGT(OutdoorPvP * pvp); - void ChangeState(); - void SendChangePhase(); - void FillInitialWorldStates(WorldPacket & data); - // used when player is activated/inactivated in the area - bool HandlePlayerEnter(Player * plr); - void HandlePlayerLeave(Player * plr); -protected: - void LinkGraveYard(uint32 team); - void UpdateTowerState(); -protected: - uint32 m_TowerState; - uint32 m_GraveyardSide; -}; - -class OPvPCapturePointEP_PWT : public OPvPCapturePoint -{ -friend class OutdoorPvPEP; -public: - OPvPCapturePointEP_PWT(OutdoorPvP * pvp); - void ChangeState(); - void SendChangePhase(); - void FillInitialWorldStates(WorldPacket & data); - // used when player is activated/inactivated in the area - bool HandlePlayerEnter(Player * plr); - void HandlePlayerLeave(Player * plr); -protected: - void SummonFlightMaster(uint32 team); - void UpdateTowerState(); -protected: - uint32 m_FlightMasterSpawned; - uint32 m_TowerState; -}; - -class OutdoorPvPEP : public OutdoorPvP -{ -friend class OPvPCapturePointEP_EWT; -friend class OPvPCapturePointEP_NPT; -friend class OPvPCapturePointEP_PWT; -friend class OPvPCapturePointEP_CGT; -public: - OutdoorPvPEP(); - bool SetupOutdoorPvP(); - void HandlePlayerEnterZone(Player *plr, uint32 zone); - void HandlePlayerLeaveZone(Player *plr, uint32 zone); - bool Update(uint32 diff); - void FillInitialWorldStates(WorldPacket &data); - void SendRemoveWorldStates(Player * plr); - void BuffTeams(); -private: - // how many towers are controlled - uint32 EP_Controls[EP_TOWER_NUM]; - uint32 m_AllianceTowersControlled; - uint32 m_HordeTowersControlled; -}; - -#endif - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPHP.cpp b/src/server/game/OutdoorPvP/OutdoorPvPHP.cpp deleted file mode 100644 index f4f73d015ce..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPHP.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "OutdoorPvPHP.h" -#include "OutdoorPvP.h" -#include "OutdoorPvPMgr.h" -#include "Player.h" -#include "WorldPacket.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Language.h" - -const uint32 HP_LANG_LOOSE_A[HP_TOWER_NUM] = {LANG_OPVP_HP_LOOSE_BROKENHILL_A,LANG_OPVP_HP_LOOSE_OVERLOOK_A,LANG_OPVP_HP_LOOSE_STADIUM_A}; - -const uint32 HP_LANG_LOOSE_H[HP_TOWER_NUM] = {LANG_OPVP_HP_LOOSE_BROKENHILL_H,LANG_OPVP_HP_LOOSE_OVERLOOK_H,LANG_OPVP_HP_LOOSE_STADIUM_H}; - -const uint32 HP_LANG_CAPTURE_A[HP_TOWER_NUM] = {LANG_OPVP_HP_CAPTURE_BROKENHILL_A,LANG_OPVP_HP_CAPTURE_OVERLOOK_A,LANG_OPVP_HP_CAPTURE_STADIUM_A}; - -const uint32 HP_LANG_CAPTURE_H[HP_TOWER_NUM] = {LANG_OPVP_HP_CAPTURE_BROKENHILL_H,LANG_OPVP_HP_CAPTURE_OVERLOOK_H,LANG_OPVP_HP_CAPTURE_STADIUM_H}; - -OPvPCapturePointHP::OPvPCapturePointHP(OutdoorPvP *pvp,OutdoorPvPHPTowerType type) -: OPvPCapturePoint(pvp), m_TowerType(type) -{ - SetCapturePointData(HPCapturePoints[type].entry, - HPCapturePoints[type].map, - HPCapturePoints[type].x, - HPCapturePoints[type].y, - HPCapturePoints[type].z, - HPCapturePoints[type].o, - HPCapturePoints[type].rot0, - HPCapturePoints[type].rot1, - HPCapturePoints[type].rot2, - HPCapturePoints[type].rot3); - AddObject(type, - HPTowerFlags[type].entry, - HPTowerFlags[type].map, - HPTowerFlags[type].x, - HPTowerFlags[type].y, - HPTowerFlags[type].z, - HPTowerFlags[type].o, - HPTowerFlags[type].rot0, - HPTowerFlags[type].rot1, - HPTowerFlags[type].rot2, - HPTowerFlags[type].rot3); -} - -OutdoorPvPHP::OutdoorPvPHP() -{ - m_TypeId = OUTDOOR_PVP_HP; -} - -bool OutdoorPvPHP::SetupOutdoorPvP() -{ - m_AllianceTowersControlled = 0; - m_HordeTowersControlled = 0; - // add the zones affected by the pvp buff - for (int i = 0; i < OutdoorPvPHPBuffZonesNum; ++i) - RegisterZone(OutdoorPvPHPBuffZones[i]); - - AddCapturePoint(new OPvPCapturePointHP(this,HP_TOWER_BROKEN_HILL)); - - AddCapturePoint(new OPvPCapturePointHP(this,HP_TOWER_OVERLOOK)); - - AddCapturePoint(new OPvPCapturePointHP(this,HP_TOWER_STADIUM)); - - return true; -} - -void OutdoorPvPHP::HandlePlayerEnterZone(Player * plr, uint32 zone) -{ - // add buffs - if (plr->GetTeam() == ALLIANCE) - { - if (m_AllianceTowersControlled >=3) - plr->CastSpell(plr,AllianceBuff,true); - } - else - { - if (m_HordeTowersControlled >=3) - plr->CastSpell(plr,HordeBuff,true); - } - OutdoorPvP::HandlePlayerEnterZone(plr,zone); -} - -void OutdoorPvPHP::HandlePlayerLeaveZone(Player * plr, uint32 zone) -{ - // remove buffs - if (plr->GetTeam() == ALLIANCE) - { - plr->RemoveAurasDueToSpell(AllianceBuff); - } - else - { - plr->RemoveAurasDueToSpell(HordeBuff); - } - OutdoorPvP::HandlePlayerLeaveZone(plr, zone); -} - -bool OutdoorPvPHP::Update(uint32 diff) -{ - bool changed = OutdoorPvP::Update(diff); - if (changed) - { - if (m_AllianceTowersControlled == 3) - TeamApplyBuff(TEAM_ALLIANCE, AllianceBuff, HordeBuff); - else if (m_HordeTowersControlled == 3) - TeamApplyBuff(TEAM_HORDE, HordeBuff, AllianceBuff); - else - { - TeamCastSpell(TEAM_ALLIANCE, -AllianceBuff); - TeamCastSpell(TEAM_HORDE, -HordeBuff); - } - SendUpdateWorldState(HP_UI_TOWER_COUNT_A, m_AllianceTowersControlled); - SendUpdateWorldState(HP_UI_TOWER_COUNT_H, m_HordeTowersControlled); - } - return changed; -} - -void OutdoorPvPHP::SendRemoveWorldStates(Player *plr) -{ - plr->SendUpdateWorldState(HP_UI_TOWER_DISPLAY_A,0); - plr->SendUpdateWorldState(HP_UI_TOWER_DISPLAY_H,0); - plr->SendUpdateWorldState(HP_UI_TOWER_COUNT_H,0); - plr->SendUpdateWorldState(HP_UI_TOWER_COUNT_A,0); - plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_N,0); - plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_POS,0); - plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY,0); - for (int i = 0; i < HP_TOWER_NUM; ++i) - { - plr->SendUpdateWorldState(HP_MAP_N[i],0); - plr->SendUpdateWorldState(HP_MAP_A[i],0); - plr->SendUpdateWorldState(HP_MAP_H[i],0); - } -} - -void OutdoorPvPHP::FillInitialWorldStates(WorldPacket &data) -{ - data << uint32(HP_UI_TOWER_DISPLAY_A) << uint32(1); - data << uint32(HP_UI_TOWER_DISPLAY_H) << uint32(1); - data << uint32(HP_UI_TOWER_COUNT_A) << uint32(m_AllianceTowersControlled); - data << uint32(HP_UI_TOWER_COUNT_H) << uint32(m_HordeTowersControlled); - data << uint32(HP_UI_TOWER_SLIDER_DISPLAY) << uint32(0); - data << uint32(HP_UI_TOWER_SLIDER_POS) << uint32(50); - data << uint32(HP_UI_TOWER_SLIDER_N) << uint32(100); - for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) - { - itr->second->FillInitialWorldStates(data); - } -} - -void OPvPCapturePointHP::ChangeState() -{ - uint32 field = 0; - switch(m_OldState) - { - case OBJECTIVESTATE_NEUTRAL: - field = HP_MAP_N[m_TowerType]; - break; - case OBJECTIVESTATE_ALLIANCE: - field = HP_MAP_A[m_TowerType]; - if (((OutdoorPvPHP*)m_PvP)->m_AllianceTowersControlled) - ((OutdoorPvPHP*)m_PvP)->m_AllianceTowersControlled--; - sWorld.SendZoneText(OutdoorPvPHPBuffZones[0],objmgr.GetTrinityStringForDBCLocale(HP_LANG_LOOSE_A[m_TowerType])); - break; - case OBJECTIVESTATE_HORDE: - field = HP_MAP_H[m_TowerType]; - if (((OutdoorPvPHP*)m_PvP)->m_HordeTowersControlled) - ((OutdoorPvPHP*)m_PvP)->m_HordeTowersControlled--; - sWorld.SendZoneText(OutdoorPvPHPBuffZones[0],objmgr.GetTrinityStringForDBCLocale(HP_LANG_LOOSE_H[m_TowerType])); - break; - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - field = HP_MAP_N[m_TowerType]; - break; - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - field = HP_MAP_N[m_TowerType]; - break; - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - field = HP_MAP_A[m_TowerType]; - break; - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - field = HP_MAP_H[m_TowerType]; - break; - } - - // send world state update - if (field) - { - m_PvP->SendUpdateWorldState(field, 0); - field = 0; - } - uint32 artkit = 21; - uint32 artkit2 = HP_TowerArtKit_N[m_TowerType]; - switch(m_State) - { - case OBJECTIVESTATE_NEUTRAL: - field = HP_MAP_N[m_TowerType]; - break; - case OBJECTIVESTATE_ALLIANCE: - field = HP_MAP_A[m_TowerType]; - artkit = 2; - artkit2 = HP_TowerArtKit_A[m_TowerType]; - if (((OutdoorPvPHP*)m_PvP)->m_AllianceTowersControlled<3) - ((OutdoorPvPHP*)m_PvP)->m_AllianceTowersControlled++; - sWorld.SendZoneText(OutdoorPvPHPBuffZones[0],objmgr.GetTrinityStringForDBCLocale(HP_LANG_CAPTURE_A[m_TowerType])); - break; - case OBJECTIVESTATE_HORDE: - field = HP_MAP_H[m_TowerType]; - artkit = 1; - artkit2 = HP_TowerArtKit_H[m_TowerType]; - if (((OutdoorPvPHP*)m_PvP)->m_HordeTowersControlled<3) - ((OutdoorPvPHP*)m_PvP)->m_HordeTowersControlled++; - sWorld.SendZoneText(OutdoorPvPHPBuffZones[0],objmgr.GetTrinityStringForDBCLocale(HP_LANG_CAPTURE_H[m_TowerType])); - break; - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - field = HP_MAP_N[m_TowerType]; - break; - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - field = HP_MAP_N[m_TowerType]; - break; - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - field = HP_MAP_A[m_TowerType]; - artkit = 2; - artkit2 = HP_TowerArtKit_A[m_TowerType]; - break; - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - field = HP_MAP_H[m_TowerType]; - artkit = 1; - artkit2 = HP_TowerArtKit_H[m_TowerType]; - break; - } - - GameObject* flag = HashMapHolder::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder::Find(m_Objects[m_TowerType]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit2); - } - - // send world state update - if (field) - m_PvP->SendUpdateWorldState(field, 1); - - // complete quest objective - if (m_State == OBJECTIVESTATE_ALLIANCE || m_State == OBJECTIVESTATE_HORDE) - SendObjectiveComplete(HP_CREDITMARKER[m_TowerType], 0); -} - -void OPvPCapturePointHP::SendChangePhase() -{ - SendUpdateWorldState(HP_UI_TOWER_SLIDER_N, m_neutralValuePct); - // send these updates to only the ones in this objective - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - SendUpdateWorldState(HP_UI_TOWER_SLIDER_POS, phase); - // send this too, sometimes the slider disappears, dunno why :( - SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY, 1); -} - -void OPvPCapturePointHP::FillInitialWorldStates(WorldPacket &data) -{ - switch(m_State) - { - case OBJECTIVESTATE_ALLIANCE: - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - data << uint32(HP_MAP_N[m_TowerType]) << uint32(0); - data << uint32(HP_MAP_A[m_TowerType]) << uint32(1); - data << uint32(HP_MAP_H[m_TowerType]) << uint32(0); - break; - case OBJECTIVESTATE_HORDE: - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - data << uint32(HP_MAP_N[m_TowerType]) << uint32(0); - data << uint32(HP_MAP_A[m_TowerType]) << uint32(0); - data << uint32(HP_MAP_H[m_TowerType]) << uint32(1); - break; - case OBJECTIVESTATE_NEUTRAL: - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - default: - data << uint32(HP_MAP_N[m_TowerType]) << uint32(1); - data << uint32(HP_MAP_A[m_TowerType]) << uint32(0); - data << uint32(HP_MAP_H[m_TowerType]) << uint32(0); - break; - } -} - -bool OPvPCapturePointHP::HandlePlayerEnter(Player *plr) -{ - if (OPvPCapturePoint::HandlePlayerEnter(plr)) - { - plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY, 1); - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_POS, phase); - plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_N, m_neutralValuePct); - return true; - } - return false; -} - -void OPvPCapturePointHP::HandlePlayerLeave(Player *plr) -{ - plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY, 0); - OPvPCapturePoint::HandlePlayerLeave(plr); -} - -void OutdoorPvPHP::HandleKillImpl(Player *plr, Unit * killed) -{ - if (killed->GetTypeId() != TYPEID_PLAYER) - return; - - if (plr->GetTeam() == ALLIANCE && killed->ToPlayer()->GetTeam() != ALLIANCE) - plr->CastSpell(plr,AlliancePlayerKillReward,true); - else if (plr->GetTeam() == HORDE && killed->ToPlayer()->GetTeam() != HORDE) - plr->CastSpell(plr,HordePlayerKillReward,true); -} diff --git a/src/server/game/OutdoorPvP/OutdoorPvPHP.h b/src/server/game/OutdoorPvP/OutdoorPvPHP.h deleted file mode 100644 index e23eb1f9369..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPHP.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef OUTDOOR_PVP_HP_ -#define OUTDOOR_PVP_HP_ - -#include "OutdoorPvPImpl.h" - -#define OutdoorPvPHPBuffZonesNum 6 - // HP, citadel, ramparts, blood furnace, shattered halls, mag's lair -const uint32 OutdoorPvPHPBuffZones[OutdoorPvPHPBuffZonesNum] = { 3483, 3563, 3562, 3713, 3714, 3836 }; - -enum OutdoorPvPHPSpells -{ - AlliancePlayerKillReward = 32155, - HordePlayerKillReward = 32158, - AllianceBuff = 32071, - HordeBuff = 32049 -}; - -enum OutdoorPvPHPTowerType{ - HP_TOWER_BROKEN_HILL = 0, - HP_TOWER_OVERLOOK = 1, - HP_TOWER_STADIUM = 2, - HP_TOWER_NUM = 3 -}; - -const uint32 HP_CREDITMARKER[HP_TOWER_NUM] = {19032,19028,19029}; - -const uint32 HP_CapturePointEvent_Enter[HP_TOWER_NUM] = {11404,11396,11388}; - -const uint32 HP_CapturePointEvent_Leave[HP_TOWER_NUM] = {11403,11395,11387}; - -enum OutdoorPvPHPWorldStates{ - HP_UI_TOWER_DISPLAY_A = 0x9ba, - HP_UI_TOWER_DISPLAY_H = 0x9b9, - - HP_UI_TOWER_COUNT_H = 0x9ae, - HP_UI_TOWER_COUNT_A = 0x9ac, - - HP_UI_TOWER_SLIDER_N = 2475, - HP_UI_TOWER_SLIDER_POS = 2474, - HP_UI_TOWER_SLIDER_DISPLAY = 2473 -}; - -const uint32 HP_MAP_N[HP_TOWER_NUM] = {0x9b5,0x9b2,0x9a8}; - -const uint32 HP_MAP_A[HP_TOWER_NUM] = {0x9b3,0x9b0,0x9a7}; - -const uint32 HP_MAP_H[HP_TOWER_NUM] = {0x9b4,0x9b1,0x9a6}; - -const uint32 HP_TowerArtKit_A[HP_TOWER_NUM] = {65,62,67}; - -const uint32 HP_TowerArtKit_H[HP_TOWER_NUM] = {64,61,68}; - -const uint32 HP_TowerArtKit_N[HP_TOWER_NUM] = {66,63,69}; - -const go_type HPCapturePoints[HP_TOWER_NUM] = { - {182175,530,-471.462,3451.09,34.6432,0.174533,0,0,0.087156,0.996195}, // 0 - Broken Hill - {182174,530,-184.889,3476.93,38.205,-0.017453,0,0,0.008727,-0.999962}, // 1 - Overlook - {182173,530,-290.016,3702.42,56.6729,0.034907,0,0,0.017452,0.999848} // 2 - Stadium -}; - -const go_type HPTowerFlags[HP_TOWER_NUM] = { - {183514,530,-467.078,3528.17,64.7121,3.14159,0,0,1,0}, // 0 broken hill - {182525,530,-187.887,3459.38,60.0403,-3.12414,0,0,0.999962,-0.008727}, // 1 overlook - {183515,530,-289.610,3696.83,75.9447,3.12414,0,0,0.999962,0.008727} // 2 stadium -}; - -class OPvPCapturePointHP : public OPvPCapturePoint -{ -public: - OPvPCapturePointHP(OutdoorPvP * pvp, OutdoorPvPHPTowerType type); - void ChangeState(); - void SendChangePhase(); - void FillInitialWorldStates(WorldPacket & data); - // used when player is activated/inactivated in the area - bool HandlePlayerEnter(Player * plr); - void HandlePlayerLeave(Player * plr); -private: - OutdoorPvPHPTowerType m_TowerType; -}; - -class OutdoorPvPHP : public OutdoorPvP -{ -friend class OPvPCapturePointHP; -public: - OutdoorPvPHP(); - bool SetupOutdoorPvP(); - void HandlePlayerEnterZone(Player *plr, uint32 zone); - void HandlePlayerLeaveZone(Player *plr, uint32 zone); - bool Update(uint32 diff); - void FillInitialWorldStates(WorldPacket &data); - void SendRemoveWorldStates(Player * plr); - void HandleKillImpl(Player * plr, Unit * killed); -private: - // how many towers are controlled - uint32 m_AllianceTowersControlled; - uint32 m_HordeTowersControlled; -}; - -#endif - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPNA.cpp b/src/server/game/OutdoorPvP/OutdoorPvPNA.cpp deleted file mode 100644 index 2360c1e0fb0..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPNA.cpp +++ /dev/null @@ -1,664 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "OutdoorPvPNA.h" -#include "Player.h" -#include "ObjectMgr.h" -#include "OutdoorPvPMgr.h" -#include "WorldPacket.h" -#include "Language.h" -#include "World.h" - -OutdoorPvPNA::OutdoorPvPNA() -{ - m_TypeId = OUTDOOR_PVP_NA; -} - -void OutdoorPvPNA::HandleKillImpl(Player *plr, Unit * killed) -{ - if (killed->GetTypeId() == TYPEID_PLAYER && plr->GetTeam() != killed->ToPlayer()->GetTeam()) - { - plr->KilledMonsterCredit(NA_CREDIT_MARKER,0); // 0 guid, btw it isn't even used in killedmonster function :S - if (plr->GetTeam() == ALLIANCE) - plr->CastSpell(plr,NA_KILL_TOKEN_ALLIANCE,true); - else - plr->CastSpell(plr,NA_KILL_TOKEN_HORDE,true); - } -} - -uint32 OPvPCapturePointNA::GetAliveGuardsCount() -{ - uint32 cnt = 0; - for (std::map::iterator itr = m_Creatures.begin(); itr != m_Creatures.end(); ++itr) - { - switch(itr->first) - { - case NA_NPC_GUARD_01: - case NA_NPC_GUARD_02: - case NA_NPC_GUARD_03: - case NA_NPC_GUARD_04: - case NA_NPC_GUARD_05: - case NA_NPC_GUARD_06: - case NA_NPC_GUARD_07: - case NA_NPC_GUARD_08: - case NA_NPC_GUARD_09: - case NA_NPC_GUARD_10: - case NA_NPC_GUARD_11: - case NA_NPC_GUARD_12: - case NA_NPC_GUARD_13: - case NA_NPC_GUARD_14: - case NA_NPC_GUARD_15: - { - if (Creature * cr = HashMapHolder::Find(itr->second)) - { - if (cr->isAlive()) - ++cnt; - } - else if (CreatureData const * cd = objmgr.GetCreatureData(GUID_LOPART(itr->second))) - { - if (!cd->is_dead) - ++cnt; - } - } - break; - default: - break; - } - } - return cnt; -} - -void OPvPCapturePointNA::SpawnNPCsForTeam(uint32 team) -{ - const creature_type * creatures = NULL; - if (team == ALLIANCE) - creatures=AllianceControlNPCs; - else if (team == HORDE) - creatures=HordeControlNPCs; - else - return; - for (int i = 0; i < NA_CONTROL_NPC_NUM; ++i) - AddCreature(i,creatures[i].entry,creatures[i].teamval,creatures[i].map,creatures[i].x,creatures[i].y,creatures[i].z,creatures[i].o,1000000); -} - -void OPvPCapturePointNA::DeSpawnNPCs() -{ - for (int i = 0; i < NA_CONTROL_NPC_NUM; ++i) - DelCreature(i); -} - -void OPvPCapturePointNA::SpawnGOsForTeam(uint32 team) -{ - const go_type * gos = NULL; - if (team == ALLIANCE) - gos=AllianceControlGOs; - else if (team == HORDE) - gos=HordeControlGOs; - else - return; - for (int i = 0; i < NA_CONTROL_GO_NUM; ++i) - { - if (i == NA_ROOST_S || - i == NA_ROOST_W || - i == NA_ROOST_N || - i == NA_ROOST_E || - i == NA_BOMB_WAGON_S || - i == NA_BOMB_WAGON_W || - i == NA_BOMB_WAGON_N || - i == NA_BOMB_WAGON_E) - continue; // roosts and bomb wagons are spawned when someone uses the matching destroyed roost - AddObject(i,gos[i].entry,gos[i].map,gos[i].x,gos[i].y,gos[i].z,gos[i].o,gos[i].rot0,gos[i].rot1,gos[i].rot2,gos[i].rot3); - } -} - -void OPvPCapturePointNA::DeSpawnGOs() -{ - for (int i = 0; i < NA_CONTROL_GO_NUM; ++i) - { - DelObject(i); - } -} - -void OPvPCapturePointNA::FactionTakeOver(uint32 team) -{ - if (m_ControllingFaction) - objmgr.RemoveGraveYardLink(NA_HALAA_GRAVEYARD,NA_HALAA_GRAVEYARD_ZONE,m_ControllingFaction,false); - if (m_ControllingFaction == ALLIANCE) - sWorld.SendZoneText(NA_HALAA_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_NA_LOOSE_A)); - else if (m_ControllingFaction == HORDE) - sWorld.SendZoneText(NA_HALAA_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_NA_LOOSE_H)); - - m_ControllingFaction = team; - if (m_ControllingFaction) - objmgr.AddGraveYardLink(NA_HALAA_GRAVEYARD,NA_HALAA_GRAVEYARD_ZONE,m_ControllingFaction,false); - DeSpawnGOs(); - DeSpawnNPCs(); - SpawnGOsForTeam(team); - SpawnNPCsForTeam(team); - m_GuardsAlive = NA_GUARDS_MAX; - m_capturable = false; - this->UpdateHalaaWorldState(); - if (team == ALLIANCE) - { - m_WyvernStateSouth = WYVERN_NEU_HORDE; - m_WyvernStateNorth = WYVERN_NEU_HORDE; - m_WyvernStateEast = WYVERN_NEU_HORDE; - m_WyvernStateWest = WYVERN_NEU_HORDE; - m_PvP->TeamApplyBuff(TEAM_ALLIANCE, NA_CAPTURE_BUFF); - m_PvP->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW, 0); - m_PvP->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW, 1); - m_PvP->SendUpdateWorldState(NA_UI_GUARDS_LEFT, m_GuardsAlive); - sWorld.SendZoneText(NA_HALAA_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_NA_CAPTURE_A)); - } - else - { - m_WyvernStateSouth = WYVERN_NEU_ALLIANCE; - m_WyvernStateNorth = WYVERN_NEU_ALLIANCE; - m_WyvernStateEast = WYVERN_NEU_ALLIANCE; - m_WyvernStateWest = WYVERN_NEU_ALLIANCE; - m_PvP->TeamApplyBuff(TEAM_HORDE, NA_CAPTURE_BUFF); - m_PvP->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW, 1); - m_PvP->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW, 0); - m_PvP->SendUpdateWorldState(NA_UI_GUARDS_LEFT, m_GuardsAlive); - sWorld.SendZoneText(NA_HALAA_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_NA_CAPTURE_H)); - } - UpdateWyvernRoostWorldState(NA_ROOST_S); - UpdateWyvernRoostWorldState(NA_ROOST_N); - UpdateWyvernRoostWorldState(NA_ROOST_W); - UpdateWyvernRoostWorldState(NA_ROOST_E); -} - -bool OPvPCapturePointNA::HandlePlayerEnter(Player *plr) -{ - if (OPvPCapturePoint::HandlePlayerEnter(plr)) - { - plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_DISPLAY, 1); - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_POS, phase); - plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_N, m_neutralValuePct); - return true; - } - return false; -} - -void OPvPCapturePointNA::HandlePlayerLeave(Player *plr) -{ - plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_DISPLAY, 0); - OPvPCapturePoint::HandlePlayerLeave(plr); -} - -OPvPCapturePointNA::OPvPCapturePointNA(OutdoorPvP *pvp) : -OPvPCapturePoint(pvp), m_capturable(true), m_GuardsAlive(0), m_ControllingFaction(0), -m_HalaaState(HALAA_N), m_WyvernStateSouth(0), m_WyvernStateNorth(0), m_WyvernStateWest(0), -m_WyvernStateEast(0), m_RespawnTimer(NA_RESPAWN_TIME), m_GuardCheckTimer(NA_GUARD_CHECK_TIME) -{ - SetCapturePointData(182210,530,-1572.57,7945.3,-22.475,2.05949,0,0,0.857167,0.515038); -} - -bool OutdoorPvPNA::SetupOutdoorPvP() -{ -// m_TypeId = OUTDOOR_PVP_NA; _MUST_ be set in ctor, because of spawns cleanup - // add the zones affected by the pvp buff - RegisterZone(NA_BUFF_ZONE); - - // halaa - m_obj = new OPvPCapturePointNA(this); - if (!m_obj) - return false; - AddCapturePoint(m_obj); - - return true; -} - -void OutdoorPvPNA::HandlePlayerEnterZone(Player * plr, uint32 zone) -{ - // add buffs - if (plr->GetTeam() == m_obj->m_ControllingFaction) - plr->CastSpell(plr,NA_CAPTURE_BUFF,true); - OutdoorPvP::HandlePlayerEnterZone(plr,zone); -} - -void OutdoorPvPNA::HandlePlayerLeaveZone(Player * plr, uint32 zone) -{ - // remove buffs - plr->RemoveAurasDueToSpell(NA_CAPTURE_BUFF); - OutdoorPvP::HandlePlayerLeaveZone(plr, zone); -} - -void OutdoorPvPNA::FillInitialWorldStates(WorldPacket &data) -{ - m_obj->FillInitialWorldStates(data); -} - -void OPvPCapturePointNA::FillInitialWorldStates(WorldPacket &data) -{ - if (m_ControllingFaction == ALLIANCE) - { - data << NA_UI_HORDE_GUARDS_SHOW << uint32(0); - data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(1); - } - else if (m_ControllingFaction == HORDE) - { - data << NA_UI_HORDE_GUARDS_SHOW << uint32(1); - data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(0); - } - else - { - data << NA_UI_HORDE_GUARDS_SHOW << uint32(0); - data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(0); - } - - data << NA_UI_GUARDS_MAX << NA_GUARDS_MAX; - data << NA_UI_GUARDS_LEFT << uint32(m_GuardsAlive); - - data << NA_UI_TOWER_SLIDER_DISPLAY << uint32(0); - data << NA_UI_TOWER_SLIDER_POS << uint32(50); - data << NA_UI_TOWER_SLIDER_N << uint32(100); - - data << NA_MAP_WYVERN_NORTH_NEU_H << uint32(bool(m_WyvernStateNorth & WYVERN_NEU_HORDE)); - data << NA_MAP_WYVERN_NORTH_NEU_A << uint32(bool(m_WyvernStateNorth & WYVERN_NEU_ALLIANCE)); - data << NA_MAP_WYVERN_NORTH_H << uint32(bool(m_WyvernStateNorth & WYVERN_HORDE)); - data << NA_MAP_WYVERN_NORTH_A << uint32(bool(m_WyvernStateNorth & WYVERN_ALLIANCE)); - - data << NA_MAP_WYVERN_SOUTH_NEU_H << uint32(bool(m_WyvernStateSouth & WYVERN_NEU_HORDE)); - data << NA_MAP_WYVERN_SOUTH_NEU_A << uint32(bool(m_WyvernStateSouth & WYVERN_NEU_ALLIANCE)); - data << NA_MAP_WYVERN_SOUTH_H << uint32(bool(m_WyvernStateSouth & WYVERN_HORDE)); - data << NA_MAP_WYVERN_SOUTH_A << uint32(bool(m_WyvernStateSouth & WYVERN_ALLIANCE)); - - data << NA_MAP_WYVERN_WEST_NEU_H << uint32(bool(m_WyvernStateWest & WYVERN_NEU_HORDE)); - data << NA_MAP_WYVERN_WEST_NEU_A << uint32(bool(m_WyvernStateWest & WYVERN_NEU_ALLIANCE)); - data << NA_MAP_WYVERN_WEST_H << uint32(bool(m_WyvernStateWest & WYVERN_HORDE)); - data << NA_MAP_WYVERN_WEST_A << uint32(bool(m_WyvernStateWest & WYVERN_ALLIANCE)); - - data << NA_MAP_WYVERN_EAST_NEU_H << uint32(bool(m_WyvernStateEast & WYVERN_NEU_HORDE)); - data << NA_MAP_WYVERN_EAST_NEU_A << uint32(bool(m_WyvernStateEast & WYVERN_NEU_ALLIANCE)); - data << NA_MAP_WYVERN_EAST_H << uint32(bool(m_WyvernStateEast & WYVERN_HORDE)); - data << NA_MAP_WYVERN_EAST_A << uint32(bool(m_WyvernStateEast & WYVERN_ALLIANCE)); - - data << NA_MAP_HALAA_NEUTRAL << uint32(bool(m_HalaaState & HALAA_N)); - data << NA_MAP_HALAA_NEU_A << uint32(bool(m_HalaaState & HALAA_N_A)); - data << NA_MAP_HALAA_NEU_H << uint32(bool(m_HalaaState & HALAA_N_H)); - data << NA_MAP_HALAA_HORDE << uint32(bool(m_HalaaState & HALAA_H)); - data << NA_MAP_HALAA_ALLIANCE << uint32(bool(m_HalaaState & HALAA_A)); -} - -void OutdoorPvPNA::SendRemoveWorldStates(Player *plr) -{ - plr->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW,0); - plr->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW,0); - plr->SendUpdateWorldState(NA_UI_GUARDS_MAX,0); - plr->SendUpdateWorldState(NA_UI_GUARDS_LEFT,0); - plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_DISPLAY,0); - plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_POS,0); - plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_N,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_NEU_H,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_NEU_A,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_H,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_A,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_NEU_H,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_NEU_A,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_H,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_A,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_WEST_NEU_H,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_WEST_NEU_A,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_WEST_H,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_WEST_A,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_EAST_NEU_H,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_EAST_NEU_A,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_EAST_H,0); - plr->SendUpdateWorldState(NA_MAP_WYVERN_EAST_A,0); - plr->SendUpdateWorldState(NA_MAP_HALAA_NEUTRAL,0); - plr->SendUpdateWorldState(NA_MAP_HALAA_NEU_A,0); - plr->SendUpdateWorldState(NA_MAP_HALAA_NEU_H,0); - plr->SendUpdateWorldState(NA_MAP_HALAA_HORDE,0); - plr->SendUpdateWorldState(NA_MAP_HALAA_ALLIANCE,0); -} - -bool OutdoorPvPNA::Update(uint32 diff) -{ - return m_obj->Update(diff); -} - -bool OPvPCapturePointNA::HandleCustomSpell(Player * plr, uint32 spellId, GameObject * /*go*/) -{ - std::vector nodes; - nodes.resize(2); - bool retval = false; - switch(spellId) - { - case NA_SPELL_FLY_NORTH: - nodes[0] = FlightPathStartNodes[NA_ROOST_N]; - nodes[1] = FlightPathEndNodes[NA_ROOST_N]; - plr->ActivateTaxiPathTo(nodes); - plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); - plr->UpdatePvP(true,true); - retval = true; - break; - case NA_SPELL_FLY_SOUTH: - nodes[0] = FlightPathStartNodes[NA_ROOST_S]; - nodes[1] = FlightPathEndNodes[NA_ROOST_S]; - plr->ActivateTaxiPathTo(nodes); - plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); - plr->UpdatePvP(true,true); - retval = true; - break; - case NA_SPELL_FLY_WEST: - nodes[0] = FlightPathStartNodes[NA_ROOST_W]; - nodes[1] = FlightPathEndNodes[NA_ROOST_W]; - plr->ActivateTaxiPathTo(nodes); - plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); - plr->UpdatePvP(true,true); - retval = true; - break; - case NA_SPELL_FLY_EAST: - nodes[0] = FlightPathStartNodes[NA_ROOST_E]; - nodes[1] = FlightPathEndNodes[NA_ROOST_E]; - plr->ActivateTaxiPathTo(nodes); - plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); - plr->UpdatePvP(true,true); - retval = true; - break; - default: - break; - } - - if (retval) - { - //Adding items - uint32 noSpaceForCount = 0; - - // check space and find places - ItemPosCountVec dest; - - int32 count = 10; - uint32 itemid = 24538; - // bomb id count - uint8 msg = plr->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemid, count, &noSpaceForCount); - if (msg != EQUIP_ERR_OK) // convert to possible store amount - count -= noSpaceForCount; - - if (count == 0 || dest.empty()) // can't add any - { - return true; - } - - Item* item = plr->StoreNewItem(dest, itemid, true); - - if (count > 0 && item) - { - plr->SendNewItem(item,count,true,false); - } - - return true; - } - return false; -} - -int32 OPvPCapturePointNA::HandleOpenGo(Player *plr, uint64 guid) -{ - uint32 retval = OPvPCapturePoint::HandleOpenGo(plr, guid); - if (retval >= 0) - { - const go_type * gos = NULL; - if (m_ControllingFaction == ALLIANCE) - gos=AllianceControlGOs; - else if (m_ControllingFaction == HORDE) - gos=HordeControlGOs; - else - return -1; - - int32 del = -1; - int32 del2 = -1; - int32 add = -1; - int32 add2 = -1; - - switch(retval) - { - case NA_DESTROYED_ROOST_S: - del = NA_DESTROYED_ROOST_S; - add = NA_ROOST_S; - add2 = NA_BOMB_WAGON_S; - if (m_ControllingFaction == HORDE) - m_WyvernStateSouth = WYVERN_ALLIANCE; - else - m_WyvernStateSouth = WYVERN_HORDE; - UpdateWyvernRoostWorldState(NA_ROOST_S); - break; - case NA_DESTROYED_ROOST_N: - del = NA_DESTROYED_ROOST_N; - add = NA_ROOST_N; - add2 = NA_BOMB_WAGON_N; - if (m_ControllingFaction == HORDE) - m_WyvernStateNorth = WYVERN_ALLIANCE; - else - m_WyvernStateNorth = WYVERN_HORDE; - UpdateWyvernRoostWorldState(NA_ROOST_N); - break; - case NA_DESTROYED_ROOST_W: - del = NA_DESTROYED_ROOST_W; - add = NA_ROOST_W; - add2 = NA_BOMB_WAGON_W; - if (m_ControllingFaction == HORDE) - m_WyvernStateWest = WYVERN_ALLIANCE; - else - m_WyvernStateWest = WYVERN_HORDE; - UpdateWyvernRoostWorldState(NA_ROOST_W); - break; - case NA_DESTROYED_ROOST_E: - del = NA_DESTROYED_ROOST_E; - add = NA_ROOST_E; - add2 = NA_BOMB_WAGON_E; - if (m_ControllingFaction == HORDE) - m_WyvernStateEast = WYVERN_ALLIANCE; - else - m_WyvernStateEast = WYVERN_HORDE; - UpdateWyvernRoostWorldState(NA_ROOST_E); - break; - case NA_BOMB_WAGON_S: - del = NA_BOMB_WAGON_S; - del2 = NA_ROOST_S; - add = NA_DESTROYED_ROOST_S; - if (m_ControllingFaction == HORDE) - m_WyvernStateSouth = WYVERN_NEU_ALLIANCE; - else - m_WyvernStateSouth = WYVERN_NEU_HORDE; - UpdateWyvernRoostWorldState(NA_ROOST_S); - break; - case NA_BOMB_WAGON_N: - del = NA_BOMB_WAGON_N; - del2 = NA_ROOST_N; - add = NA_DESTROYED_ROOST_N; - if (m_ControllingFaction == HORDE) - m_WyvernStateNorth = WYVERN_NEU_ALLIANCE; - else - m_WyvernStateNorth = WYVERN_NEU_HORDE; - UpdateWyvernRoostWorldState(NA_ROOST_N); - break; - case NA_BOMB_WAGON_W: - del = NA_BOMB_WAGON_W; - del2 = NA_ROOST_W; - add = NA_DESTROYED_ROOST_W; - if (m_ControllingFaction == HORDE) - m_WyvernStateWest = WYVERN_NEU_ALLIANCE; - else - m_WyvernStateWest = WYVERN_NEU_HORDE; - UpdateWyvernRoostWorldState(NA_ROOST_W); - break; - case NA_BOMB_WAGON_E: - del = NA_BOMB_WAGON_E; - del2 = NA_ROOST_E; - add = NA_DESTROYED_ROOST_E; - if (m_ControllingFaction == HORDE) - m_WyvernStateEast = WYVERN_NEU_ALLIANCE; - else - m_WyvernStateEast = WYVERN_NEU_HORDE; - UpdateWyvernRoostWorldState(NA_ROOST_E); - break; - default: - return -1; - break; - } - - if (del>-1) - DelObject(del); - - if (del2>-1) - DelObject(del2); - - if (add>-1) - AddObject(add,gos[add].entry,gos[add].map,gos[add].x,gos[add].y,gos[add].z,gos[add].o,gos[add].rot0,gos[add].rot1,gos[add].rot2,gos[add].rot3); - - if (add2>-1) - AddObject(add2,gos[add2].entry,gos[add2].map,gos[add2].x,gos[add2].y,gos[add2].z,gos[add2].o,gos[add2].rot0,gos[add2].rot1,gos[add2].rot2,gos[add2].rot3); - - return retval; - } - return -1; -} - -bool OPvPCapturePointNA::Update(uint32 diff) -{ - // let the controlling faction advance in phase - bool capturable = false; - if (m_ControllingFaction == ALLIANCE && m_activePlayers[0].size() > m_activePlayers[1].size()) - capturable = true; - else if (m_ControllingFaction == HORDE && m_activePlayers[0].size() < m_activePlayers[1].size()) - capturable = true; - - if (m_GuardCheckTimer < diff) - { - m_GuardCheckTimer = NA_GUARD_CHECK_TIME; - uint32 cnt = GetAliveGuardsCount(); - if (cnt != m_GuardsAlive) - { - m_GuardsAlive = cnt; - if (m_GuardsAlive == 0) - m_capturable = true; - // update the guard count for the players in zone - m_PvP->SendUpdateWorldState(NA_UI_GUARDS_LEFT,m_GuardsAlive); - } - } else m_GuardCheckTimer -= diff; - - if (m_capturable || capturable) - { - if (m_RespawnTimer < diff) - { - // if the guards have been killed, then the challenger has one hour to take over halaa. - // in case they fail to do it, the guards are respawned, and they have to start again. - if (m_ControllingFaction) - FactionTakeOver(m_ControllingFaction); - m_RespawnTimer = NA_RESPAWN_TIME; - } else m_RespawnTimer -= diff; - - return OPvPCapturePoint::Update(diff); - } - return false; -} - -void OPvPCapturePointNA::ChangeState() -{ - uint32 artkit = 21; - switch(m_State) - { - case OBJECTIVESTATE_NEUTRAL: - m_HalaaState = HALAA_N; - break; - case OBJECTIVESTATE_ALLIANCE: - m_HalaaState = HALAA_A; - FactionTakeOver(ALLIANCE); - artkit = 2; - break; - case OBJECTIVESTATE_HORDE: - m_HalaaState = HALAA_H; - FactionTakeOver(HORDE); - artkit = 1; - break; - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - m_HalaaState = HALAA_N_A; - break; - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - m_HalaaState = HALAA_N_H; - break; - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - m_HalaaState = HALAA_N_A; - artkit = 2; - break; - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - m_HalaaState = HALAA_N_H; - artkit = 1; - break; - } - - GameObject* flag = HashMapHolder::Find(m_capturePointGUID); - if (flag) - { - flag->SetGoArtKit(artkit); - } - - UpdateHalaaWorldState(); -} - -void OPvPCapturePointNA::SendChangePhase() -{ - // send this too, sometimes the slider disappears, dunno why :( - SendUpdateWorldState(NA_UI_TOWER_SLIDER_DISPLAY, 1); - // send these updates to only the ones in this objective - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - SendUpdateWorldState(NA_UI_TOWER_SLIDER_POS, phase); - SendUpdateWorldState(NA_UI_TOWER_SLIDER_N, m_neutralValuePct); -} - -void OPvPCapturePointNA::UpdateHalaaWorldState() -{ - m_PvP->SendUpdateWorldState(NA_MAP_HALAA_NEUTRAL ,uint32(bool(m_HalaaState & HALAA_N))); - m_PvP->SendUpdateWorldState(NA_MAP_HALAA_NEU_A ,uint32(bool(m_HalaaState & HALAA_N_A))); - m_PvP->SendUpdateWorldState(NA_MAP_HALAA_NEU_H ,uint32(bool(m_HalaaState & HALAA_N_H))); - m_PvP->SendUpdateWorldState(NA_MAP_HALAA_HORDE ,uint32(bool(m_HalaaState & HALAA_H))); - m_PvP->SendUpdateWorldState(NA_MAP_HALAA_ALLIANCE ,uint32(bool(m_HalaaState & HALAA_A))); -} - -void OPvPCapturePointNA::UpdateWyvernRoostWorldState(uint32 roost) -{ - switch(roost) - { - case NA_ROOST_S: - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_NEU_H,uint32(bool(m_WyvernStateSouth & WYVERN_NEU_HORDE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_NEU_A,uint32(bool(m_WyvernStateSouth & WYVERN_NEU_ALLIANCE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_H,uint32(bool(m_WyvernStateSouth & WYVERN_HORDE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_A,uint32(bool(m_WyvernStateSouth & WYVERN_ALLIANCE))); - break; - case NA_ROOST_N: - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_NEU_H,uint32(bool(m_WyvernStateNorth & WYVERN_NEU_HORDE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_NEU_A,uint32(bool(m_WyvernStateNorth & WYVERN_NEU_ALLIANCE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_H,uint32(bool(m_WyvernStateNorth & WYVERN_HORDE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_A,uint32(bool(m_WyvernStateNorth & WYVERN_ALLIANCE))); - break; - case NA_ROOST_W: - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_WEST_NEU_H,uint32(bool(m_WyvernStateWest & WYVERN_NEU_HORDE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_WEST_NEU_A,uint32(bool(m_WyvernStateWest & WYVERN_NEU_ALLIANCE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_WEST_H,uint32(bool(m_WyvernStateWest & WYVERN_HORDE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_WEST_A,uint32(bool(m_WyvernStateWest & WYVERN_ALLIANCE))); - break; - case NA_ROOST_E: - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_EAST_NEU_H,uint32(bool(m_WyvernStateEast & WYVERN_NEU_HORDE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_EAST_NEU_A,uint32(bool(m_WyvernStateEast & WYVERN_NEU_ALLIANCE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_EAST_H,uint32(bool(m_WyvernStateEast & WYVERN_HORDE))); - m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_EAST_A,uint32(bool(m_WyvernStateEast & WYVERN_ALLIANCE))); - break; - } -} diff --git a/src/server/game/OutdoorPvP/OutdoorPvPNA.h b/src/server/game/OutdoorPvP/OutdoorPvPNA.h deleted file mode 100644 index 124f51e8040..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPNA.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef OUTDOOR_PVP_NA_ -#define OUTDOOR_PVP_NA_ - -// TODO: "sometimes" set to neutral - -#include "OutdoorPvPImpl.h" -enum OutdoorPvPNASpells -{ - NA_KILL_TOKEN_ALLIANCE = 33005, - NA_KILL_TOKEN_HORDE = 33004, - NA_CAPTURE_BUFF = 33795 // strength of the halaani -}; -// kill credit for pks -const uint32 NA_CREDIT_MARKER = 24867; -const uint32 NA_GUARDS_MAX = 15; - -const uint32 NA_BUFF_ZONE = 3518; - -const uint32 NA_HALAA_GRAVEYARD = 993; - -const uint32 NA_HALAA_GRAVEYARD_ZONE = 3518; // need to add zone id, not area id - -const uint32 NA_RESPAWN_TIME = 3600000; // one hour to capture after defeating all guards - -const uint32 NA_GUARD_CHECK_TIME = 500; // every half second - -enum OutdoorPvPNAWorldStates{ - NA_UI_HORDE_GUARDS_SHOW = 2503, - NA_UI_ALLIANCE_GUARDS_SHOW = 2502, - NA_UI_GUARDS_MAX = 2493, - NA_UI_GUARDS_LEFT = 2491, - - NA_UI_TOWER_SLIDER_DISPLAY = 2495, - NA_UI_TOWER_SLIDER_POS = 2494, - NA_UI_TOWER_SLIDER_N = 2497, - - NA_MAP_WYVERN_NORTH_NEU_H = 2762, - NA_MAP_WYVERN_NORTH_NEU_A = 2662, - NA_MAP_WYVERN_NORTH_H = 2663, - NA_MAP_WYVERN_NORTH_A = 2664, - - NA_MAP_WYVERN_SOUTH_NEU_H = 2760, - NA_MAP_WYVERN_SOUTH_NEU_A = 2670, - NA_MAP_WYVERN_SOUTH_H = 2668, - NA_MAP_WYVERN_SOUTH_A = 2669, - - NA_MAP_WYVERN_WEST_NEU_H = 2761, - NA_MAP_WYVERN_WEST_NEU_A = 2667, - NA_MAP_WYVERN_WEST_H = 2665, - NA_MAP_WYVERN_WEST_A = 2666, - - NA_MAP_WYVERN_EAST_NEU_H = 2763, - NA_MAP_WYVERN_EAST_NEU_A = 2659, - NA_MAP_WYVERN_EAST_H = 2660, - NA_MAP_WYVERN_EAST_A = 2661, - - NA_MAP_HALAA_NEUTRAL = 2671, - NA_MAP_HALAA_NEU_A = 2676, - NA_MAP_HALAA_NEU_H = 2677, - NA_MAP_HALAA_HORDE = 2672, - NA_MAP_HALAA_ALLIANCE = 2673 -}; - -const uint32 FLIGHT_NODES_NUM = 4; - -// used to access the elements of Horde/AllyControlGOs -enum ControlGOTypes{ - NA_ROOST_S = 0, - NA_ROOST_W = 1, - NA_ROOST_N = 2, - NA_ROOST_E = 3, - - NA_BOMB_WAGON_S = 4, - NA_BOMB_WAGON_W = 5, - NA_BOMB_WAGON_N = 6, - NA_BOMB_WAGON_E = 7, - - NA_DESTROYED_ROOST_S = 8, - NA_DESTROYED_ROOST_W = 9, - NA_DESTROYED_ROOST_N = 10, - NA_DESTROYED_ROOST_E = 11, - - NA_CONTROL_GO_NUM = 12 -}; - -const uint32 FlightPathStartNodes[FLIGHT_NODES_NUM] = {103,105,107,109}; -const uint32 FlightPathEndNodes[FLIGHT_NODES_NUM] = {104,106,108,110}; - -enum FlightSpellsNA{ - NA_SPELL_FLY_SOUTH = 32059, - NA_SPELL_FLY_WEST = 32068, - NA_SPELL_FLY_NORTH = 32075, - NA_SPELL_FLY_EAST = 32081 -}; - -// spawned when the alliance is attacking, horde is in control -const go_type HordeControlGOs[NA_CONTROL_GO_NUM] = { - {182267,530,-1815.8,8036.51,-26.2354,-2.89725,0,0,0.992546,-0.121869}, //ALLY_ROOST_SOUTH - {182280,530,-1507.95,8132.1,-19.5585,-1.3439,0,0,0.622515,-0.782608}, //ALLY_ROOST_WEST - {182281,530,-1384.52,7779.33,-11.1663,-0.575959,0,0,0.284015,-0.95882}, //ALLY_ROOST_NORTH - {182282,530,-1650.11,7732.56,-15.4505,-2.80998,0,0,0.986286,-0.165048}, //ALLY_ROOST_EAST - - {182222,530,-1825.4022,8039.2602,-26.08,-2.89725,0,0,0.992546,-0.121869}, //HORDE_BOMB_WAGON_SOUTH - {182272,530,-1515.37,8136.91,-20.42,-1.3439,0,0,0.622515,-0.782608}, //HORDE_BOMB_WAGON_WEST - {182273,530,-1377.95,7773.44,-10.31,-0.575959,0,0,0.284015,-0.95882}, //HORDE_BOMB_WAGON_NORTH - {182274,530,-1659.87,7733.15,-15.75,-2.80998,0,0,0.986286,-0.165048}, //HORDE_BOMB_WAGON_EAST - - {182266,530,-1815.8,8036.51,-26.2354,-2.89725,0,0,0.992546,-0.121869}, //DESTROYED_ALLY_ROOST_SOUTH - {182275,530,-1507.95,8132.1,-19.5585,-1.3439,0,0,0.622515,-0.782608}, //DESTROYED_ALLY_ROOST_WEST - {182276,530,-1384.52,7779.33,-11.1663,-0.575959,0,0,0.284015,-0.95882}, //DESTROYED_ALLY_ROOST_NORTH - {182277,530,-1650.11,7732.56,-15.4505,-2.80998,0,0,0.986286,-0.165048} //DESTROYED_ALLY_ROOST_EAST -}; - -// spawned when the horde is attacking, alliance is in control -const go_type AllianceControlGOs[NA_CONTROL_GO_NUM] = { - {182301,530,-1815.8,8036.51,-26.2354,-2.89725,0,0,0.992546,-0.121869}, //HORDE_ROOST_SOUTH - {182302,530,-1507.95,8132.1,-19.5585,-1.3439,0,0,0.622515,-0.782608}, //HORDE_ROOST_WEST - {182303,530,-1384.52,7779.33,-11.1663,-0.575959,0,0,0.284015,-0.95882}, //HORDE_ROOST_NORTH - {182304,530,-1650.11,7732.56,-15.4505,-2.80998,0,0,0.986286,-0.165048}, //HORDE_ROOST_EAST - - {182305,530,-1825.4022,8039.2602,-26.08,-2.89725,0,0,0.992546,-0.121869}, //ALLY_BOMB_WAGON_SOUTH - {182306,530,-1515.37,8136.91,-20.42,-1.3439,0,0,0.622515,-0.782608}, //ALLY_BOMB_WAGON_WEST - {182307,530,-1377.95,7773.44,-10.31,-0.575959,0,0,0.284015,-0.95882}, //ALLY_BOMB_WAGON_NORTH - {182308,530,-1659.87,7733.15,-15.75,-2.80998,0,0,0.986286,-0.165048}, //ALLY_BOMB_WAGON_EAST - - {182297,530,-1815.8,8036.51,-26.2354,-2.89725,0,0,0.992546,-0.121869}, //DESTROYED_HORDE_ROOST_SOUTH - {182298,530,-1507.95,8132.1,-19.5585,-1.3439,0,0,0.622515,-0.782608}, //DESTROYED_HORDE_ROOST_WEST - {182299,530,-1384.52,7779.33,-11.1663,-0.575959,0,0,0.284015,-0.95882}, //DESTROYED_HORDE_ROOST_NORTH - {182300,530,-1650.11,7732.56,-15.4505,-2.80998,0,0,0.986286,-0.165048} //DESTROYED_HORDE_ROOST_EAST -}; - -enum ControlNPCTypes{ - NA_NPC_RESEARCHER = 0, - NA_NPC_QUARTERMASTER, - NA_NPC_BLADE_MERCHANT, - NA_NPC_FOOD_MERCHANT, - NA_NPC_AMMO, - - NA_NPC_GUARD_01, - NA_NPC_GUARD_02, - NA_NPC_GUARD_03, - NA_NPC_GUARD_04, - NA_NPC_GUARD_05, - NA_NPC_GUARD_06, - NA_NPC_GUARD_07, - NA_NPC_GUARD_08, - NA_NPC_GUARD_09, - NA_NPC_GUARD_10, - NA_NPC_GUARD_11, - NA_NPC_GUARD_12, - NA_NPC_GUARD_13, - NA_NPC_GUARD_14, - NA_NPC_GUARD_15, - - NA_CONTROL_NPC_NUM -}; - -const creature_type HordeControlNPCs[NA_CONTROL_NPC_NUM] = { - {18816,67,530,-1523.92,7951.76,-17.6942,3.51172}, - {18821,67,530,-1527.75,7952.46,-17.6948,3.99317}, - {21474,67,530,-1520.14,7927.11,-20.2527,3.39389}, - {21484,67,530,-1524.84,7930.34,-20.182,3.6405}, - {21483,67,530,-1570.01,7993.8,-22.4505,5.02655}, - {18192,67,530,-1654.06,8000.46,-26.59,3.37}, - {18192,67,530,-1487.18,7899.1,-19.53,0.954}, - {18192,67,530,-1480.88,7908.79,-19.19,4.485}, - {18192,67,530,-1540.56,7995.44,-20.45,0.947}, - {18192,67,530,-1546.95,8000.85,-20.72,6.035}, - {18192,67,530,-1595.31,7860.53,-21.51,3.747}, - {18192,67,530,-1642.31,7995.59,-25.8,3.317}, - {18192,67,530,-1545.46,7995.35,-20.63,1.094}, - {18192,67,530,-1487.58,7907.99,-19.27,5.567}, - {18192,67,530,-1651.54,7988.56,-26.5289,2.98451}, - {18192,67,530,-1602.46,7866.43,-22.1177,4.74729}, - {18192,67,530,-1591.22,7875.29,-22.3536,4.34587}, - {18192,67,530,-1550.6,7944.45,-21.63,3.559}, - {18192,67,530,-1545.57,7935.83,-21.13,3.448}, - {18192,67,530,-1550.86,7937.56,-21.7,3.801} -}; - -const creature_type AllianceControlNPCs[NA_CONTROL_NPC_NUM] = { - {18817,469,530,-1591.18,8020.39,-22.2042,4.59022}, - {18822,469,530,-1588.0,8019.0,-22.2042,4.06662}, - {21485,469,530,-1521.93,7927.37,-20.2299,3.24631}, - {21487,469,530,-1540.33,7971.95,-20.7186,3.07178}, - {21488,469,530,-1570.01,7993.8,-22.4505,5.02655}, - {18256,469,530,-1654.06,8000.46,-26.59,3.37}, - {18256,469,530,-1487.18,7899.1,-19.53,0.954}, - {18256,469,530,-1480.88,7908.79,-19.19,4.485}, - {18256,469,530,-1540.56,7995.44,-20.45,0.947}, - {18256,469,530,-1546.95,8000.85,-20.72,6.035}, - {18256,469,530,-1595.31,7860.53,-21.51,3.747}, - {18256,469,530,-1642.31,7995.59,-25.8,3.317}, - {18256,469,530,-1545.46,7995.35,-20.63,1.094}, - {18256,469,530,-1487.58,7907.99,-19.27,5.567}, - {18256,469,530,-1651.54,7988.56,-26.5289,2.98451}, - {18256,469,530,-1602.46,7866.43,-22.1177,4.74729}, - {18256,469,530,-1591.22,7875.29,-22.3536,4.34587}, - {18256,469,530,-1603.75,8000.36,-24.18,4.516}, - {18256,469,530,-1585.73,7994.68,-23.29,4.439}, - {18256,469,530,-1595.5,7991.27,-23.53,4.738} -}; - -enum WyvernStates{ - WYVERN_NEU_HORDE = 1, - WYVERN_NEU_ALLIANCE = 2, - WYVERN_HORDE = 4, - WYVERN_ALLIANCE = 8 -}; - -enum HalaaStates{ - HALAA_N = 1, - HALAA_N_A = 2, - HALAA_A = 4, - HALAA_N_H = 8, - HALAA_H = 16 -}; - -class Unit; -class Creature; -class OutdoorPvPNA; -class OPvPCapturePointNA : public OPvPCapturePoint -{ -friend class OutdoorPvPNA; -public: - OPvPCapturePointNA(OutdoorPvP * pvp); - bool Update(uint32 diff); - void ChangeState(); - void SendChangePhase(); - void FillInitialWorldStates(WorldPacket & data); - // used when player is activated/inactivated in the area - bool HandlePlayerEnter(Player * plr); - void HandlePlayerLeave(Player * plr); - bool HandleCustomSpell(Player *plr, uint32 spellId, GameObject * go); - int32 HandleOpenGo(Player *plr, uint64 guid); - uint32 GetAliveGuardsCount(); -protected: - // called when a faction takes control - void FactionTakeOver(uint32 team); - - void DeSpawnNPCs(); - void DeSpawnGOs(); - void SpawnNPCsForTeam(uint32 team); - void SpawnGOsForTeam(uint32 team); - - void UpdateWyvernRoostWorldState(uint32 roost); - void UpdateHalaaWorldState(); - -private: - bool m_capturable; - uint32 m_GuardsAlive; - uint32 m_ControllingFaction; - uint32 m_WyvernStateNorth; - uint32 m_WyvernStateSouth; - uint32 m_WyvernStateEast; - uint32 m_WyvernStateWest; - uint32 m_HalaaState; - uint32 m_RespawnTimer; - uint32 m_GuardCheckTimer; -}; - -class OutdoorPvPNA : public OutdoorPvP -{ -friend class OPvPCapturePointNA; -public: - OutdoorPvPNA(); - bool SetupOutdoorPvP(); - void HandlePlayerEnterZone(Player *plr, uint32 zone); - void HandlePlayerLeaveZone(Player *plr, uint32 zone); - bool Update(uint32 diff); - void FillInitialWorldStates(WorldPacket &data); - void SendRemoveWorldStates(Player * plr); - void HandleKillImpl(Player * plr, Unit * killed); -private: - OPvPCapturePointNA * m_obj; -}; - -#endif - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPSI.cpp b/src/server/game/OutdoorPvP/OutdoorPvPSI.cpp deleted file mode 100644 index 408901f9d06..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPSI.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "OutdoorPvPSI.h" -#include "WorldPacket.h" -#include "Player.h" -#include "GameObject.h" -#include "MapManager.h" -#include "ObjectMgr.h" -#include "OutdoorPvPMgr.h" -#include "Language.h" -#include "World.h" - -OutdoorPvPSI::OutdoorPvPSI() -{ - m_TypeId = OUTDOOR_PVP_SI; - m_Gathered_A = 0; - m_Gathered_H = 0; - m_LastController = 0; -} - -void OutdoorPvPSI::FillInitialWorldStates(WorldPacket &data) -{ - data << SI_GATHERED_A << m_Gathered_A; - data << SI_GATHERED_H << m_Gathered_H; - data << SI_SILITHYST_MAX << SI_MAX_RESOURCES; -} - -void OutdoorPvPSI::SendRemoveWorldStates(Player *plr) -{ - plr->SendUpdateWorldState(SI_GATHERED_A,0); - plr->SendUpdateWorldState(SI_GATHERED_H,0); - plr->SendUpdateWorldState(SI_SILITHYST_MAX,0); -} - -void OutdoorPvPSI::UpdateWorldState() -{ - SendUpdateWorldState(SI_GATHERED_A,m_Gathered_A); - SendUpdateWorldState(SI_GATHERED_H,m_Gathered_H); - SendUpdateWorldState(SI_SILITHYST_MAX,SI_MAX_RESOURCES); -} - -bool OutdoorPvPSI::SetupOutdoorPvP() -{ - for (int i = 0; i < OutdoorPvPSIBuffZonesNum; ++i) - RegisterZone(OutdoorPvPSIBuffZones[i]); - return true; -} - -bool OutdoorPvPSI::Update(uint32 /*diff*/) -{ - return false; -} - -void OutdoorPvPSI::HandlePlayerEnterZone(Player * plr, uint32 zone) -{ - if (plr->GetTeam() == m_LastController) - plr->CastSpell(plr,SI_CENARION_FAVOR,true); - OutdoorPvP::HandlePlayerEnterZone(plr,zone); -} - -void OutdoorPvPSI::HandlePlayerLeaveZone(Player * plr, uint32 zone) -{ - // remove buffs - plr->RemoveAurasDueToSpell(SI_CENARION_FAVOR); - OutdoorPvP::HandlePlayerLeaveZone(plr, zone); -} - -bool OutdoorPvPSI::HandleAreaTrigger(Player *plr, uint32 trigger) -{ - switch(trigger) - { - case SI_AREATRIGGER_A: - if (plr->GetTeam() == ALLIANCE && plr->HasAura(SI_SILITHYST_FLAG)) - { - // remove aura - plr->RemoveAurasDueToSpell(SI_SILITHYST_FLAG); - ++ m_Gathered_A; - if (m_Gathered_A >= SI_MAX_RESOURCES) - { - TeamApplyBuff(TEAM_ALLIANCE, SI_CENARION_FAVOR); - sWorld.SendZoneText(OutdoorPvPSIBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_SI_CAPTURE_A)); - m_LastController = ALLIANCE; - m_Gathered_A = 0; - m_Gathered_H = 0; - } - UpdateWorldState(); - // reward player - plr->CastSpell(plr,SI_TRACES_OF_SILITHYST,true); - // add 19 honor - plr->RewardHonor(NULL,1,19); - // add 20 cenarion circle repu - plr->GetReputationMgr().ModifyReputation(sFactionStore.LookupEntry(609),20); - // complete quest - plr->KilledMonsterCredit(SI_TURNIN_QUEST_CM_A,0); - } - return true; - case SI_AREATRIGGER_H: - if (plr->GetTeam() == HORDE && plr->HasAura(SI_SILITHYST_FLAG)) - { - // remove aura - plr->RemoveAurasDueToSpell(SI_SILITHYST_FLAG); - ++ m_Gathered_H; - if (m_Gathered_H >= SI_MAX_RESOURCES) - { - TeamApplyBuff(TEAM_HORDE, SI_CENARION_FAVOR); - sWorld.SendZoneText(OutdoorPvPSIBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_SI_CAPTURE_H)); - m_LastController = HORDE; - m_Gathered_A = 0; - m_Gathered_H = 0; - } - UpdateWorldState(); - // reward player - plr->CastSpell(plr,SI_TRACES_OF_SILITHYST,true); - // add 19 honor - plr->RewardHonor(NULL,1,19); - // add 20 cenarion circle repu - plr->GetReputationMgr().ModifyReputation(sFactionStore.LookupEntry(609),20); - // complete quest - plr->KilledMonsterCredit(SI_TURNIN_QUEST_CM_H,0); - } - return true; - } - return false; -} - -bool OutdoorPvPSI::HandleDropFlag(Player *plr, uint32 spellId) -{ - if (spellId == SI_SILITHYST_FLAG) - { - // if it was dropped away from the player's turn-in point, then create a silithyst mound, if it was dropped near the areatrigger, then it was dispelled by the outdoorpvp, so do nothing - switch(plr->GetTeam()) - { - case ALLIANCE: - { - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(SI_AREATRIGGER_A); - if (atEntry) - { - // 5.0f is safe-distance - if (plr->GetDistance(atEntry->x,atEntry->y,atEntry->z) > 5.0f + atEntry->radius) - { - // he dropped it further, summon mound - GameObject * go = new GameObject; - Map * map = plr->GetMap(); - if (!map) - { - delete go; - return true; - } - - if (!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map, plr->GetPhaseMask(), plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,GO_STATE_READY)) - { - delete go; - } - else - { - go->SetRespawnTime(0); - map->Add(go); - } - } - } - } - break; - case HORDE: - { - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(SI_AREATRIGGER_H); - if (atEntry) - { - // 5.0f is safe-distance - if (plr->GetDistance(atEntry->x,atEntry->y,atEntry->z) > 5.0f + atEntry->radius) - { - // he dropped it further, summon mound - GameObject * go = new GameObject; - Map * map = plr->GetMap(); - if (!map) - { - delete go; - return true; - } - if (!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map, plr->GetPhaseMask() ,plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,GO_STATE_READY)) - { - delete go; - } - else - { - go->SetRespawnTime(0); - map->Add(go); - } - } - } - } - break; - } - return true; - } - return false; -} - -bool OutdoorPvPSI::HandleCustomSpell(Player *plr, uint32 spellId, GameObject *go) -{ - if (!go || spellId != SI_SILITHYST_FLAG_GO_SPELL) - return false; - plr->CastSpell(plr,SI_SILITHYST_FLAG,true); - if (go->GetGOInfo()->id == SI_SILITHYST_MOUND) - { - // despawn go - go->SetRespawnTime(0); - go->Delete(); - } - return true; -} - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPSI.h b/src/server/game/OutdoorPvP/OutdoorPvPSI.h deleted file mode 100644 index 3176669c42c..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPSI.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef OUTDOOR_PVP_SI_ -#define OUTDOOR_PVP_SI_ - -#include "OutdoorPvPImpl.h" - -enum OutdoorPvPSISpells -{ - SI_SILITHYST_FLAG_GO_SPELL = 29518, - SI_SILITHYST_FLAG = 29519, - SI_TRACES_OF_SILITHYST = 29534, - SI_CENARION_FAVOR = 30754 -}; - -const uint32 SI_MAX_RESOURCES = 200; - -const uint32 OutdoorPvPSIBuffZonesNum = 3; - -const uint32 OutdoorPvPSIBuffZones[OutdoorPvPSIBuffZonesNum] = { 1377, 3428, 3429 }; - -const uint32 SI_AREATRIGGER_H = 4168; - -const uint32 SI_AREATRIGGER_A = 4162; - -const uint32 SI_TURNIN_QUEST_CM_A = 17090; - -const uint32 SI_TURNIN_QUEST_CM_H = 18199; - -const uint32 SI_SILITHYST_MOUND = 181597; - -enum SI_WorldStates{ - SI_GATHERED_A = 2313, - SI_GATHERED_H = 2314, - SI_SILITHYST_MAX = 2317 -}; - -class OutdoorPvPSI : public OutdoorPvP -{ -public: - OutdoorPvPSI(); - bool SetupOutdoorPvP(); - void HandlePlayerEnterZone(Player *plr, uint32 zone); - void HandlePlayerLeaveZone(Player *plr, uint32 zone); - bool Update(uint32 diff); - void FillInitialWorldStates(WorldPacket &data); - void SendRemoveWorldStates(Player * plr); - bool HandleAreaTrigger(Player * plr, uint32 trigger); - bool HandleDropFlag(Player * plr, uint32 spellId); - bool HandleCustomSpell(Player * plr, uint32 spellId, GameObject *go); - void UpdateWorldState(); -private: - uint32 m_Gathered_A; - uint32 m_Gathered_H; - uint32 m_LastController; -}; - -#endif - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPTF.cpp b/src/server/game/OutdoorPvP/OutdoorPvPTF.cpp deleted file mode 100644 index 4d5682bf1d6..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPTF.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "OutdoorPvPTF.h" -#include "OutdoorPvPMgr.h" -#include "WorldPacket.h" -#include "Player.h" -#include "ObjectMgr.h" -#include "Language.h" -#include "World.h" - -OutdoorPvPTF::OutdoorPvPTF() -{ - m_TypeId = OUTDOOR_PVP_TF; -} - -OPvPCapturePointTF::OPvPCapturePointTF(OutdoorPvP *pvp, OutdoorPvPTF_TowerType type) -: OPvPCapturePoint(pvp), m_TowerType(type), m_TowerState(TF_TOWERSTATE_N) -{ - SetCapturePointData(TFCapturePoints[type].entry,TFCapturePoints[type].map,TFCapturePoints[type].x,TFCapturePoints[type].y,TFCapturePoints[type].z,TFCapturePoints[type].o,TFCapturePoints[type].rot0,TFCapturePoints[type].rot1,TFCapturePoints[type].rot2,TFCapturePoints[type].rot3); -} - -void OPvPCapturePointTF::FillInitialWorldStates(WorldPacket &data) -{ - data << uint32(TFTowerWorldStates[m_TowerType].n) << uint32(bool(m_TowerState & TF_TOWERSTATE_N)); - data << uint32(TFTowerWorldStates[m_TowerType].h) << uint32(bool(m_TowerState & TF_TOWERSTATE_H)); - data << uint32(TFTowerWorldStates[m_TowerType].a) << uint32(bool(m_TowerState & TF_TOWERSTATE_A)); -} - -void OutdoorPvPTF::FillInitialWorldStates(WorldPacket &data) -{ - data << TF_UI_TOWER_SLIDER_POS << uint32(50); - data << TF_UI_TOWER_SLIDER_N << uint32(100); - data << TF_UI_TOWER_SLIDER_DISPLAY << uint32(0); - - data << TF_UI_TOWER_COUNT_H << m_HordeTowersControlled; - data << TF_UI_TOWER_COUNT_A << m_AllianceTowersControlled; - data << TF_UI_TOWERS_CONTROLLED_DISPLAY << uint32(!m_IsLocked); - - data << TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT << first_digit; - data << TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT << second_digit; - data << TF_UI_LOCKED_TIME_HOURS << hours_left; - - data << TF_UI_LOCKED_DISPLAY_NEUTRAL << uint32(m_IsLocked && !m_HordeTowersControlled && !m_AllianceTowersControlled); - data << TF_UI_LOCKED_DISPLAY_HORDE << uint32(m_IsLocked && (m_HordeTowersControlled > m_AllianceTowersControlled)); - data << TF_UI_LOCKED_DISPLAY_ALLIANCE << uint32(m_IsLocked && (m_HordeTowersControlled < m_AllianceTowersControlled)); - - for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) - { - itr->second->FillInitialWorldStates(data); - } -} - -void OutdoorPvPTF::SendRemoveWorldStates(Player * plr) -{ - plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_POS,uint32(0)); - plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_N,uint32(0)); - plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_DISPLAY,uint32(0)); - - plr->SendUpdateWorldState(TF_UI_TOWER_COUNT_H,uint32(0)); - plr->SendUpdateWorldState(TF_UI_TOWER_COUNT_A,uint32(0)); - plr->SendUpdateWorldState(TF_UI_TOWERS_CONTROLLED_DISPLAY,uint32(0)); - - plr->SendUpdateWorldState(TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT,uint32(0)); - plr->SendUpdateWorldState(TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT,uint32(0)); - plr->SendUpdateWorldState(TF_UI_LOCKED_TIME_HOURS,uint32(0)); - - plr->SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_NEUTRAL,uint32(0)); - plr->SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_HORDE,uint32(0)); - plr->SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_ALLIANCE,uint32(0)); - - for (int i = 0; i < TF_TOWER_NUM; ++i) - { - plr->SendUpdateWorldState(uint32(TFTowerWorldStates[i].n),uint32(0)); - plr->SendUpdateWorldState(uint32(TFTowerWorldStates[i].h),uint32(0)); - plr->SendUpdateWorldState(uint32(TFTowerWorldStates[i].a),uint32(0)); - } -} - -void OPvPCapturePointTF::UpdateTowerState() -{ - m_PvP->SendUpdateWorldState(uint32(TFTowerWorldStates[m_TowerType].n),uint32(bool(m_TowerState & TF_TOWERSTATE_N))); - m_PvP->SendUpdateWorldState(uint32(TFTowerWorldStates[m_TowerType].h),uint32(bool(m_TowerState & TF_TOWERSTATE_H))); - m_PvP->SendUpdateWorldState(uint32(TFTowerWorldStates[m_TowerType].a),uint32(bool(m_TowerState & TF_TOWERSTATE_A))); -} - -bool OPvPCapturePointTF::HandlePlayerEnter(Player *plr) -{ - if (OPvPCapturePoint::HandlePlayerEnter(plr)) - { - plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_DISPLAY, 1); - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_POS, phase); - plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_N, m_neutralValuePct); - return true; - } - return false; -} - -void OPvPCapturePointTF::HandlePlayerLeave(Player *plr) -{ - plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_DISPLAY, 0); - OPvPCapturePoint::HandlePlayerLeave(plr); -} - -bool OutdoorPvPTF::Update(uint32 diff) -{ - bool changed = OutdoorPvP::Update(diff); - - if (changed) - { - if (m_AllianceTowersControlled == TF_TOWER_NUM) - { - TeamApplyBuff(TEAM_ALLIANCE, TF_CAPTURE_BUFF); - m_IsLocked = true; - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_NEUTRAL,uint32(0)); - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_HORDE,uint32(0)); - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_ALLIANCE,uint32(1)); - SendUpdateWorldState(TF_UI_TOWERS_CONTROLLED_DISPLAY, uint32(0)); - } - else if (m_HordeTowersControlled == TF_TOWER_NUM) - { - TeamApplyBuff(TEAM_HORDE, TF_CAPTURE_BUFF); - m_IsLocked = true; - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_NEUTRAL,uint32(0)); - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_HORDE,uint32(1)); - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_ALLIANCE,uint32(0)); - SendUpdateWorldState(TF_UI_TOWERS_CONTROLLED_DISPLAY, uint32(0)); - } - else - { - TeamCastSpell(TEAM_ALLIANCE, -TF_CAPTURE_BUFF); - TeamCastSpell(TEAM_HORDE, -TF_CAPTURE_BUFF); - } - SendUpdateWorldState(TF_UI_TOWER_COUNT_A, m_AllianceTowersControlled); - SendUpdateWorldState(TF_UI_TOWER_COUNT_H, m_HordeTowersControlled); - } - if (m_IsLocked) - { - // lock timer is down, release lock - if (m_LockTimer < diff) - { - m_LockTimer = TF_LOCK_TIME; - m_LockTimerUpdate = 0; - m_IsLocked = false; - SendUpdateWorldState(TF_UI_TOWERS_CONTROLLED_DISPLAY, uint32(1)); - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_NEUTRAL,uint32(0)); - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_HORDE,uint32(0)); - SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_ALLIANCE,uint32(0)); - } - else - { - // worldstateui update timer is down, update ui with new time data - if (m_LockTimerUpdate < diff) - { - m_LockTimerUpdate = TF_LOCK_TIME_UPDATE; - uint32 minutes_left = m_LockTimer / 60000; - hours_left = minutes_left / 60; - minutes_left -= hours_left * 60; - second_digit = minutes_left % 10; - first_digit = minutes_left / 10; - - SendUpdateWorldState(TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT,first_digit); - SendUpdateWorldState(TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT,second_digit); - SendUpdateWorldState(TF_UI_LOCKED_TIME_HOURS,hours_left); - } else m_LockTimerUpdate -= diff; - m_LockTimer -= diff; - } - } - return changed; -} - -void OutdoorPvPTF::HandlePlayerEnterZone(Player * plr, uint32 zone) -{ - if (plr->GetTeam() == ALLIANCE) - { - if (m_AllianceTowersControlled >= TF_TOWER_NUM) - plr->CastSpell(plr,TF_CAPTURE_BUFF,true); - } - else - { - if (m_HordeTowersControlled >= TF_TOWER_NUM) - plr->CastSpell(plr,TF_CAPTURE_BUFF,true); - } - OutdoorPvP::HandlePlayerEnterZone(plr,zone); -} - -void OutdoorPvPTF::HandlePlayerLeaveZone(Player * plr, uint32 zone) -{ - // remove buffs - plr->RemoveAurasDueToSpell(TF_CAPTURE_BUFF); - OutdoorPvP::HandlePlayerLeaveZone(plr, zone); -} - -bool OutdoorPvPTF::SetupOutdoorPvP() -{ - m_AllianceTowersControlled = 0; - m_HordeTowersControlled = 0; - - m_IsLocked = false; - m_LockTimer = TF_LOCK_TIME; - m_LockTimerUpdate = 0; - hours_left = 6; - second_digit = 0; - first_digit = 0; - - // add the zones affected by the pvp buff - for (int i = 0; i < OutdoorPvPTFBuffZonesNum; ++i) - RegisterZone(OutdoorPvPTFBuffZones[i]); - - AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_NW)); - AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_N)); - AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_NE)); - AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_SE)); - AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_S)); - - return true; -} - -bool OPvPCapturePointTF::Update(uint32 diff) -{ - // can update even in locked state if gathers the controlling faction - bool canupdate = ((((OutdoorPvPTF*)m_PvP)->m_AllianceTowersControlled > 0) && m_activePlayers[0].size() > m_activePlayers[1].size()) || - ((((OutdoorPvPTF*)m_PvP)->m_HordeTowersControlled > 0) && m_activePlayers[0].size() < m_activePlayers[1].size()); - // if gathers the other faction, then only update if the pvp is unlocked - canupdate = canupdate || !((OutdoorPvPTF*)m_PvP)->m_IsLocked; - return canupdate && OPvPCapturePoint::Update(diff); -} - -void OPvPCapturePointTF::ChangeState() -{ - // if changing from controlling alliance to horde - if (m_OldState == OBJECTIVESTATE_ALLIANCE) - { - if (((OutdoorPvPTF*)m_PvP)->m_AllianceTowersControlled) - ((OutdoorPvPTF*)m_PvP)->m_AllianceTowersControlled--; - sWorld.SendZoneText(OutdoorPvPTFBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_TF_LOOSE_A)); - } - // if changing from controlling horde to alliance - else if (m_OldState == OBJECTIVESTATE_HORDE) - { - if (((OutdoorPvPTF*)m_PvP)->m_HordeTowersControlled) - ((OutdoorPvPTF*)m_PvP)->m_HordeTowersControlled--; - sWorld.SendZoneText(OutdoorPvPTFBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_TF_LOOSE_H)); - } - - uint32 artkit = 21; - - switch(m_State) - { - case OBJECTIVESTATE_ALLIANCE: - m_TowerState = TF_TOWERSTATE_A; - artkit = 2; - if (((OutdoorPvPTF*)m_PvP)->m_AllianceTowersControlledm_AllianceTowersControlled++; - sWorld.SendZoneText(OutdoorPvPTFBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_TF_CAPTURE_A)); - for (PlayerSet::iterator itr = m_activePlayers[0].begin(); itr != m_activePlayers[0].end(); ++itr) - (*itr)->AreaExploredOrEventHappens(TF_ALLY_QUEST); - break; - case OBJECTIVESTATE_HORDE: - m_TowerState = TF_TOWERSTATE_H; - artkit = 1; - if (((OutdoorPvPTF*)m_PvP)->m_HordeTowersControlledm_HordeTowersControlled++; - sWorld.SendZoneText(OutdoorPvPTFBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_TF_CAPTURE_H)); - for (PlayerSet::iterator itr = m_activePlayers[1].begin(); itr != m_activePlayers[1].end(); ++itr) - (*itr)->AreaExploredOrEventHappens(TF_HORDE_QUEST); - break; - case OBJECTIVESTATE_NEUTRAL: - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - m_TowerState = TF_TOWERSTATE_N; - break; - } - - GameObject* flag = HashMapHolder::Find(m_capturePointGUID); - if (flag) - flag->SetGoArtKit(artkit); - - UpdateTowerState(); -} - -void OPvPCapturePointTF::SendChangePhase() -{ - // send this too, sometimes the slider disappears, dunno why :( - SendUpdateWorldState(TF_UI_TOWER_SLIDER_DISPLAY, 1); - // send these updates to only the ones in this objective - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - SendUpdateWorldState(TF_UI_TOWER_SLIDER_POS, phase); - // send this too, sometimes it resets :S - SendUpdateWorldState(TF_UI_TOWER_SLIDER_N, m_neutralValuePct); -} - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPTF.h b/src/server/game/OutdoorPvP/OutdoorPvPTF.h deleted file mode 100644 index 3a88b7fd309..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPTF.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef OUTDOOR_PVP_TF_ -#define OUTDOOR_PVP_TF_ - -#include "OutdoorPvPImpl.h" - -const uint32 OutdoorPvPTFBuffZonesNum = 5; - -const uint32 OutdoorPvPTFBuffZones[OutdoorPvPTFBuffZonesNum] = { 3519 /*Terokkar Forest*/, 3791 /*Sethekk Halls*/, 3789 /*Shadow Labyrinth*/, 3792 /*Mana-Tombs*/, 3790 /*Auchenai Crypts*/ }; - -// locked for 6 hours after capture -const uint32 TF_LOCK_TIME = 3600 * 6 * 1000; -// update lock timer every 1/4 minute (overkill, but this way it's sure the timer won't "jump" 2 minutes at once.) -const uint32 TF_LOCK_TIME_UPDATE = 15000; - -// blessing of auchindoun -#define TF_CAPTURE_BUFF 33377 - -const uint32 TF_ALLY_QUEST = 11505; -const uint32 TF_HORDE_QUEST = 11506; - -enum OutdoorPvPTF_TowerType{ - TF_TOWER_NW = 0, - TF_TOWER_N, - TF_TOWER_NE, - TF_TOWER_SE, - TF_TOWER_S, - TF_TOWER_NUM -}; - -const go_type TFCapturePoints[TF_TOWER_NUM] = { - {183104,530,-3081.65,5335.03,17.1853,-2.14675,0,0,0.878817,-0.477159}, - {183411,530,-2939.9,4788.73,18.987,2.77507,0,0,0.983255,0.182236}, - {183412,530,-3174.94,4440.97,16.2281,1.86750,0,0.803857,0.594823}, - {183413,530,-3603.31,4529.15,20.9077,0.994838,0,0,0.477159,0.878817}, - {183414,530,-3812.37,4899.3,17.7249,0.087266,0,0,0.043619,0.999048} -}; - -struct tf_tower_world_state{ - uint32 n; - uint32 h; - uint32 a; -}; - -const tf_tower_world_state TFTowerWorldStates[TF_TOWER_NUM] = { - {0xa79,0xa7a,0xa7b}, - {0xa7e,0xa7d,0xa7c}, - {0xa82,0xa81,0xa80}, - {0xa88,0xa87,0xa86}, - {0xa85,0xa84,0xa83} -}; - -const uint32 TFTowerPlayerEnterEvents[TF_TOWER_NUM] = {12226, 12497, 12486, 12499, 12501}; - -const uint32 TFTowerPlayerLeaveEvents[TF_TOWER_NUM] = {12225, 12496, 12487, 12498, 12500}; - -enum TFWorldStates{ - TF_UI_TOWER_SLIDER_POS = 0xa41, - TF_UI_TOWER_SLIDER_N = 0xa40, - TF_UI_TOWER_SLIDER_DISPLAY = 0xa3f, - - TF_UI_TOWER_COUNT_H = 0xa3e, - TF_UI_TOWER_COUNT_A = 0xa3d, - TF_UI_TOWERS_CONTROLLED_DISPLAY = 0xa3c, - - TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT = 0x9d0, - TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT = 0x9ce, - TF_UI_LOCKED_TIME_HOURS = 0x9cd, - TF_UI_LOCKED_DISPLAY_NEUTRAL = 0x9cc, - TF_UI_LOCKED_DISPLAY_HORDE = 0xad0, - TF_UI_LOCKED_DISPLAY_ALLIANCE = 0xacf -}; - -enum TFTowerStates { - TF_TOWERSTATE_N = 1, - TF_TOWERSTATE_H = 2, - TF_TOWERSTATE_A = 4 -}; - -class OPvPCapturePointTF : public OPvPCapturePoint -{ -public: - OPvPCapturePointTF(OutdoorPvP * pvp, OutdoorPvPTF_TowerType type); - bool Update(uint32 diff); - void ChangeState(); - void SendChangePhase(); - void FillInitialWorldStates(WorldPacket & data); - // used when player is activated/inactivated in the area - bool HandlePlayerEnter(Player * plr); - void HandlePlayerLeave(Player * plr); - void UpdateTowerState(); -protected: - OutdoorPvPTF_TowerType m_TowerType; - uint32 m_TowerState; -}; - -class OutdoorPvPTF : public OutdoorPvP -{ -friend class OPvPCapturePointTF; -public: - OutdoorPvPTF(); - bool SetupOutdoorPvP(); - void HandlePlayerEnterZone(Player *plr, uint32 zone); - void HandlePlayerLeaveZone(Player *plr, uint32 zone); - bool Update(uint32 diff); - void FillInitialWorldStates(WorldPacket &data); - void SendRemoveWorldStates(Player * plr); -private: - bool m_IsLocked; - uint32 m_LockTimer; - uint32 m_LockTimerUpdate; - uint32 m_AllianceTowersControlled; - uint32 m_HordeTowersControlled; - uint32 hours_left, second_digit, first_digit; -}; - -#endif - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPZM.cpp b/src/server/game/OutdoorPvP/OutdoorPvPZM.cpp deleted file mode 100644 index fb548816c3a..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPZM.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "OutdoorPvPZM.h" -#include "ObjectMgr.h" -#include "OutdoorPvPMgr.h" -#include "Player.h" -#include "Creature.h" -#include "ObjectAccessor.h" -#include "WorldPacket.h" -#include "GossipDef.h" -#include "World.h" - -OPvPCapturePointZM_Beacon::OPvPCapturePointZM_Beacon(OutdoorPvP *pvp, ZM_BeaconType type) -: OPvPCapturePoint(pvp), m_TowerType(type), m_TowerState(ZM_TOWERSTATE_N) -{ - SetCapturePointData(ZMCapturePoints[type].entry,ZMCapturePoints[type].map,ZMCapturePoints[type].x,ZMCapturePoints[type].y,ZMCapturePoints[type].z,ZMCapturePoints[type].o,ZMCapturePoints[type].rot0,ZMCapturePoints[type].rot1,ZMCapturePoints[type].rot2,ZMCapturePoints[type].rot3); -} - -void OPvPCapturePointZM_Beacon::FillInitialWorldStates(WorldPacket &data) -{ - data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_n) << uint32(bool(m_TowerState & ZM_TOWERSTATE_N)); - data << uint32(ZMBeaconInfo[m_TowerType].map_tower_n) << uint32(bool(m_TowerState & ZM_TOWERSTATE_N)); - data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_a) << uint32(bool(m_TowerState & ZM_TOWERSTATE_A)); - data << uint32(ZMBeaconInfo[m_TowerType].map_tower_a) << uint32(bool(m_TowerState & ZM_TOWERSTATE_A)); - data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_h) << uint32(bool(m_TowerState & ZM_TOWERSTATE_H)); - data << uint32(ZMBeaconInfo[m_TowerType].map_tower_h) << uint32(bool(m_TowerState & ZM_TOWERSTATE_H)); -} - -void OPvPCapturePointZM_Beacon::UpdateTowerState() -{ - m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].ui_tower_n),uint32(bool(m_TowerState & ZM_TOWERSTATE_N))); - m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].map_tower_n),uint32(bool(m_TowerState & ZM_TOWERSTATE_N))); - m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].ui_tower_a),uint32(bool(m_TowerState & ZM_TOWERSTATE_A))); - m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].map_tower_a),uint32(bool(m_TowerState & ZM_TOWERSTATE_A))); - m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].ui_tower_h),uint32(bool(m_TowerState & ZM_TOWERSTATE_H))); - m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].map_tower_h),uint32(bool(m_TowerState & ZM_TOWERSTATE_H))); -} - -bool OPvPCapturePointZM_Beacon::HandlePlayerEnter(Player *plr) -{ - if (OPvPCapturePoint::HandlePlayerEnter(plr)) - { - plr->SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_disp, 1); - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - plr->SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_pos, phase); - plr->SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_n, m_neutralValuePct); - return true; - } - return false; -} - -void OPvPCapturePointZM_Beacon::HandlePlayerLeave(Player *plr) -{ - plr->SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_disp, 0); - OPvPCapturePoint::HandlePlayerLeave(plr); -} - -void OPvPCapturePointZM_Beacon::ChangeState() -{ - // if changing from controlling alliance to horde - if (m_OldState == OBJECTIVESTATE_ALLIANCE) - { - if (((OutdoorPvPZM*)m_PvP)->m_AllianceTowersControlled) - ((OutdoorPvPZM*)m_PvP)->m_AllianceTowersControlled--; - sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(ZMBeaconLooseA[m_TowerType])); - } - // if changing from controlling horde to alliance - else if (m_OldState == OBJECTIVESTATE_HORDE) - { - if (((OutdoorPvPZM*)m_PvP)->m_HordeTowersControlled) - ((OutdoorPvPZM*)m_PvP)->m_HordeTowersControlled--; - sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(ZMBeaconLooseH[m_TowerType])); - } - - switch(m_State) - { - case OBJECTIVESTATE_ALLIANCE: - m_TowerState = ZM_TOWERSTATE_A; - if (((OutdoorPvPZM*)m_PvP)->m_AllianceTowersControlledm_AllianceTowersControlled++; - sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(ZMBeaconCaptureA[m_TowerType])); - break; - case OBJECTIVESTATE_HORDE: - m_TowerState = ZM_TOWERSTATE_H; - if (((OutdoorPvPZM*)m_PvP)->m_HordeTowersControlledm_HordeTowersControlled++; - sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(ZMBeaconCaptureH[m_TowerType])); - break; - case OBJECTIVESTATE_NEUTRAL: - case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: - case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: - case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - m_TowerState = ZM_TOWERSTATE_N; - break; - } - - UpdateTowerState(); -} - -void OPvPCapturePointZM_Beacon::SendChangePhase() -{ - // send this too, sometimes the slider disappears, dunno why :( - SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_disp, 1); - // send these updates to only the ones in this objective - uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); - SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_pos, phase); - SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_n, m_neutralValuePct); -} - -bool OutdoorPvPZM::Update(uint32 diff) -{ - bool changed = OutdoorPvP::Update(diff); - if (changed) - { - if (m_AllianceTowersControlled == ZM_NUM_BEACONS) - m_GraveYard->SetBeaconState(ALLIANCE); - else if (m_HordeTowersControlled == ZM_NUM_BEACONS) - m_GraveYard->SetBeaconState(HORDE); - else - m_GraveYard->SetBeaconState(0); - } - return changed; -} - -void OutdoorPvPZM::HandlePlayerEnterZone(Player * plr, uint32 zone) -{ - if (plr->GetTeam() == ALLIANCE) - { - if (m_GraveYard->m_GraveYardState & ZM_GRAVEYARD_A) - plr->CastSpell(plr,ZM_CAPTURE_BUFF,true); - } - else - { - if (m_GraveYard->m_GraveYardState & ZM_GRAVEYARD_H) - plr->CastSpell(plr,ZM_CAPTURE_BUFF,true); - } - OutdoorPvP::HandlePlayerEnterZone(plr,zone); -} - -void OutdoorPvPZM::HandlePlayerLeaveZone(Player * plr, uint32 zone) -{ - // remove buffs - plr->RemoveAurasDueToSpell(ZM_CAPTURE_BUFF); - // remove flag - plr->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); - plr->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_H); - OutdoorPvP::HandlePlayerLeaveZone(plr, zone); -} - -OutdoorPvPZM::OutdoorPvPZM() -{ - m_TypeId = OUTDOOR_PVP_ZM; - m_GraveYard = NULL; - m_AllianceTowersControlled = 0; - m_HordeTowersControlled = 0; - -} - -bool OutdoorPvPZM::SetupOutdoorPvP() -{ - m_AllianceTowersControlled = 0; - m_HordeTowersControlled = 0; - - // add the zones affected by the pvp buff - for (int i = 0; i < OutdoorPvPZMBuffZonesNum; ++i) - RegisterZone(OutdoorPvPZMBuffZones[i]); - - AddCapturePoint(new OPvPCapturePointZM_Beacon(this,ZM_BEACON_WEST)); - AddCapturePoint(new OPvPCapturePointZM_Beacon(this,ZM_BEACON_EAST)); - m_GraveYard = new OPvPCapturePointZM_GraveYard(this); - AddCapturePoint(m_GraveYard); // though the update function isn't used, the handleusego is! - - return true; -} - -void OutdoorPvPZM::HandleKillImpl(Player *plr, Unit * killed) -{ - if (killed->GetTypeId() != TYPEID_PLAYER) - return; - - if (plr->GetTeam() == ALLIANCE && killed->ToPlayer()->GetTeam() != ALLIANCE) - plr->CastSpell(plr,ZM_AlliancePlayerKillReward,true); - else if (plr->GetTeam() == HORDE && killed->ToPlayer()->GetTeam() != HORDE) - plr->CastSpell(plr,ZM_HordePlayerKillReward,true); -} - -bool OPvPCapturePointZM_GraveYard::Update(uint32 /*diff*/) -{ - bool retval = m_State != m_OldState; - m_State = m_OldState; - return retval; -} - -int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player *plr, uint64 guid) -{ - uint32 retval = OPvPCapturePoint::HandleOpenGo(plr, guid); - if (retval >= 0) - { - if (plr->HasAura(ZM_BATTLE_STANDARD_A) && m_GraveYardState != ZM_GRAVEYARD_A) - { - if (m_GraveYardState == ZM_GRAVEYARD_H) - sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_LOOSE_GY_H)); - m_GraveYardState = ZM_GRAVEYARD_A; - DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant - AddObject(0,ZM_Banner_A.entry,ZM_Banner_A.map,ZM_Banner_A.x,ZM_Banner_A.y,ZM_Banner_A.z,ZM_Banner_A.o,ZM_Banner_A.rot0,ZM_Banner_A.rot1,ZM_Banner_A.rot2,ZM_Banner_A.rot3); - objmgr.RemoveGraveYardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, HORDE); // rem gy - objmgr.AddGraveYardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, ALLIANCE, false); // add gy - m_PvP->TeamApplyBuff(TEAM_ALLIANCE, ZM_CAPTURE_BUFF); - plr->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); - sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_A)); - } - else if (plr->HasAura(ZM_BATTLE_STANDARD_H) && m_GraveYardState != ZM_GRAVEYARD_H) - { - if (m_GraveYardState == ZM_GRAVEYARD_A) - sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_LOOSE_GY_A)); - m_GraveYardState = ZM_GRAVEYARD_H; - DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant - AddObject(0,ZM_Banner_H.entry,ZM_Banner_H.map,ZM_Banner_H.x,ZM_Banner_H.y,ZM_Banner_H.z,ZM_Banner_H.o,ZM_Banner_H.rot0,ZM_Banner_H.rot1,ZM_Banner_H.rot2,ZM_Banner_H.rot3); - objmgr.RemoveGraveYardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, ALLIANCE); // rem gy - objmgr.AddGraveYardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, HORDE, false); // add gy - m_PvP->TeamApplyBuff(TEAM_HORDE, ZM_CAPTURE_BUFF); - plr->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_H); - sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_H)); - } - UpdateTowerState(); - } - return retval; -} - -OPvPCapturePointZM_GraveYard::OPvPCapturePointZM_GraveYard(OutdoorPvP *pvp) -: OPvPCapturePoint(pvp) -{ - m_BothControllingFaction = 0; - m_GraveYardState = ZM_GRAVEYARD_N; - m_FlagCarrierGUID = 0; - // add field scouts here - AddCreature(ZM_ALLIANCE_FIELD_SCOUT,ZM_AllianceFieldScout.entry,ZM_AllianceFieldScout.teamval,ZM_AllianceFieldScout.map,ZM_AllianceFieldScout.x,ZM_AllianceFieldScout.y,ZM_AllianceFieldScout.z,ZM_AllianceFieldScout.o); - AddCreature(ZM_HORDE_FIELD_SCOUT,ZM_HordeFieldScout.entry,ZM_HordeFieldScout.teamval,ZM_HordeFieldScout.map,ZM_HordeFieldScout.x,ZM_HordeFieldScout.y,ZM_HordeFieldScout.z,ZM_HordeFieldScout.o); - // add neutral banner - AddObject(0,ZM_Banner_N.entry,ZM_Banner_N.map,ZM_Banner_N.x,ZM_Banner_N.y,ZM_Banner_N.z,ZM_Banner_N.o,ZM_Banner_N.rot0,ZM_Banner_N.rot1,ZM_Banner_N.rot2,ZM_Banner_N.rot3); -} - -void OPvPCapturePointZM_GraveYard::UpdateTowerState() -{ - m_PvP->SendUpdateWorldState(ZM_MAP_GRAVEYARD_N,uint32(bool(m_GraveYardState & ZM_GRAVEYARD_N))); - m_PvP->SendUpdateWorldState(ZM_MAP_GRAVEYARD_H,uint32(bool(m_GraveYardState & ZM_GRAVEYARD_H))); - m_PvP->SendUpdateWorldState(ZM_MAP_GRAVEYARD_A,uint32(bool(m_GraveYardState & ZM_GRAVEYARD_A))); - - m_PvP->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_READY,uint32(m_BothControllingFaction == ALLIANCE)); - m_PvP->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_NOT_READY,uint32(m_BothControllingFaction != ALLIANCE)); - m_PvP->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_READY,uint32(m_BothControllingFaction == HORDE)); - m_PvP->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_NOT_READY,uint32(m_BothControllingFaction != HORDE)); -} - -void OPvPCapturePointZM_GraveYard::FillInitialWorldStates(WorldPacket &data) -{ - data << ZM_MAP_GRAVEYARD_N << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_N)); - data << ZM_MAP_GRAVEYARD_H << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_H)); - data << ZM_MAP_GRAVEYARD_A << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_A)); - - data << ZM_MAP_ALLIANCE_FLAG_READY << uint32(m_BothControllingFaction == ALLIANCE); - data << ZM_MAP_ALLIANCE_FLAG_NOT_READY << uint32(m_BothControllingFaction != ALLIANCE); - data << ZM_MAP_HORDE_FLAG_READY << uint32(m_BothControllingFaction == HORDE); - data << ZM_MAP_HORDE_FLAG_NOT_READY << uint32(m_BothControllingFaction != HORDE); -} - -void OPvPCapturePointZM_GraveYard::SetBeaconState(uint32 controlling_faction) -{ - // nothing to do here - if (m_BothControllingFaction == controlling_faction) - return; - m_BothControllingFaction = controlling_faction; - - switch(controlling_faction) - { - case ALLIANCE: - // if ally already controls the gy and taken back both beacons, return, nothing to do for us - if (m_GraveYardState & ZM_GRAVEYARD_A) - return; - // ally doesn't control the gy, but controls the side beacons -> add gossip option, add neutral banner - break; - case HORDE: - // if horde already controls the gy and taken back both beacons, return, nothing to do for us - if (m_GraveYardState & ZM_GRAVEYARD_H) - return; - // horde doesn't control the gy, but controls the side beacons -> add gossip option, add neutral banner - break; - default: - // if the graveyard is not neutral, then leave it that way - // if the graveyard is neutral, then we have to dispel the buff from the flag carrier - if (m_GraveYardState & ZM_GRAVEYARD_N) - { - // gy was neutral, thus neutral banner was spawned, it is possible that someone was taking the flag to the gy - if (m_FlagCarrierGUID) - { - // remove flag from carrier, reset flag carrier guid - Player * p = objmgr.GetPlayer(m_FlagCarrierGUID); - if (p) - { - p->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); - p->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_H); - } - m_FlagCarrierGUID = 0; - } - } - break; - } - // send worldstateupdate - UpdateTowerState(); -} - -bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso) -{ - uint64 guid = c->GetGUID(); - std::map::iterator itr = m_CreatureTypes.find(guid); - if (itr != m_CreatureTypes.end()) - { - if (itr->second == ZM_ALLIANCE_FIELD_SCOUT && plr->GetTeam() == ALLIANCE && m_BothControllingFaction == ALLIANCE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_A) - return true; - else if (itr->second == ZM_HORDE_FIELD_SCOUT && plr->GetTeam() == HORDE && m_BothControllingFaction == HORDE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_H) - return true; - } - return false; -} - -bool OPvPCapturePointZM_GraveYard::HandleGossipOption(Player *plr, uint64 guid, uint32 /*gossipid*/) -{ - std::map::iterator itr = m_CreatureTypes.find(guid); - if (itr != m_CreatureTypes.end()) - { - Creature * cr = HashMapHolder::Find(guid); - if (!cr) - return true; - // if the flag is already taken, then return - if (m_FlagCarrierGUID) - return true; - if (itr->second == ZM_ALLIANCE_FIELD_SCOUT) - { - cr->CastSpell(plr,ZM_BATTLE_STANDARD_A,true); - m_FlagCarrierGUID = plr->GetGUID(); - } - else if (itr->second == ZM_HORDE_FIELD_SCOUT) - { - cr->CastSpell(plr,ZM_BATTLE_STANDARD_H,true); - m_FlagCarrierGUID = plr->GetGUID(); - } - UpdateTowerState(); - plr->PlayerTalkClass->CloseGossip(); - return true; - } - return false; -} - -bool OPvPCapturePointZM_GraveYard::HandleDropFlag(Player * /*plr*/, uint32 spellId) -{ - switch(spellId) - { - case ZM_BATTLE_STANDARD_A: - m_FlagCarrierGUID = 0; - return true; - case ZM_BATTLE_STANDARD_H: - m_FlagCarrierGUID = 0; - return true; - } - return false; -} - -void OutdoorPvPZM::FillInitialWorldStates(WorldPacket &data) -{ - data << ZM_WORLDSTATE_UNK_1 << uint32(1); - for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) - { - itr->second->FillInitialWorldStates(data); - } -} - -void OutdoorPvPZM::SendRemoveWorldStates(Player *plr) -{ - plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_N_W,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_POS_W,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_DISPLAY_W,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_N_E,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_POS_E,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_DISPLAY_E,0); - plr->SendUpdateWorldState(ZM_WORLDSTATE_UNK_1,1); - plr->SendUpdateWorldState(ZM_UI_TOWER_EAST_N,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_EAST_H,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_EAST_A,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_WEST_N,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_WEST_H,0); - plr->SendUpdateWorldState(ZM_UI_TOWER_WEST_A,0); - plr->SendUpdateWorldState(ZM_MAP_TOWER_EAST_N,0); - plr->SendUpdateWorldState(ZM_MAP_TOWER_EAST_H,0); - plr->SendUpdateWorldState(ZM_MAP_TOWER_EAST_A,0); - plr->SendUpdateWorldState(ZM_MAP_GRAVEYARD_H,0); - plr->SendUpdateWorldState(ZM_MAP_GRAVEYARD_A,0); - plr->SendUpdateWorldState(ZM_MAP_GRAVEYARD_N,0); - plr->SendUpdateWorldState(ZM_MAP_TOWER_WEST_N,0); - plr->SendUpdateWorldState(ZM_MAP_TOWER_WEST_H,0); - plr->SendUpdateWorldState(ZM_MAP_TOWER_WEST_A,0); - plr->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_READY,0); - plr->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_NOT_READY,0); - plr->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_NOT_READY,0); - plr->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_READY,0); -} - diff --git a/src/server/game/OutdoorPvP/OutdoorPvPZM.h b/src/server/game/OutdoorPvP/OutdoorPvPZM.h deleted file mode 100644 index cd26e6bb527..00000000000 --- a/src/server/game/OutdoorPvP/OutdoorPvPZM.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef OUTDOOR_PVP_ZM_ -#define OUTDOOR_PVP_ZM_ - -#include "OutdoorPvPImpl.h" -#include "Language.h" - -const uint32 OutdoorPvPZMBuffZonesNum = 5; -// the buff is cast in these zones -const uint32 OutdoorPvPZMBuffZones[OutdoorPvPZMBuffZonesNum] = {3521,3607,3717,3715,3716}; -// linked when the central tower is controlled -const uint32 ZM_GRAVEYARD_ZONE = 3521; -// linked when the central tower is controlled -const uint32 ZM_GRAVEYARD_ID = 969; - -enum OutdoorPvPZMSpells -{ - // cast on the players of the controlling faction - ZM_CAPTURE_BUFF = 33779, // twin spire blessing - // spell that the field scout casts on the player to carry the flag - ZM_BATTLE_STANDARD_A = 32430, - // spell that the field scout casts on the player to carry the flag - ZM_BATTLE_STANDARD_H = 32431, - // token create spell - ZM_AlliancePlayerKillReward = 32155, - // token create spell - ZM_HordePlayerKillReward = 32158 -}; - -// banners 182527, 182528, 182529, gotta check them ingame -const go_type ZM_Banner_A = { 182527,530,253.54,7083.81,36.7728,-0.017453,0,0,0.008727,-0.999962 }; -const go_type ZM_Banner_H = { 182528,530,253.54,7083.81,36.7728,-0.017453,0,0,0.008727,-0.999962 }; -const go_type ZM_Banner_N = { 182529,530,253.54,7083.81,36.7728,-0.017453,0,0,0.008727,-0.999962 }; - -// horde field scout spawn data -const creature_type ZM_HordeFieldScout = {18564,67,530,296.625,7818.4,42.6294,5.18363}; -// alliance field scout spawn data -const creature_type ZM_AllianceFieldScout = {18581,469,530,374.395,6230.08,22.8351,0.593412}; - -enum ZMCreatureTypes{ - ZM_ALLIANCE_FIELD_SCOUT = 0, - ZM_HORDE_FIELD_SCOUT, - ZM_CREATURE_NUM -}; - -struct zm_beacon { - uint32 slider_disp; - uint32 slider_n; - uint32 slider_pos; - uint32 ui_tower_n; - uint32 ui_tower_h; - uint32 ui_tower_a; - uint32 map_tower_n; - uint32 map_tower_h; - uint32 map_tower_a; - uint32 event_enter; - uint32 event_leave; -}; - -enum ZM_BeaconType{ - ZM_BEACON_EAST = 0, - ZM_BEACON_WEST, - ZM_NUM_BEACONS -}; - -const zm_beacon ZMBeaconInfo[ZM_NUM_BEACONS] = { - {2533,2535,2534,2560,2559,2558,2652,2651,2650,11807,11806}, - {2527,2529,2528,2557,2556,2555,2646,2645,2644,11805,11804} -}; - -const uint32 ZMBeaconCaptureA[ZM_NUM_BEACONS] = { - LANG_OPVP_ZM_CAPTURE_EAST_A, - LANG_OPVP_ZM_CAPTURE_WEST_A -}; - -const uint32 ZMBeaconCaptureH[ZM_NUM_BEACONS] = { - LANG_OPVP_ZM_CAPTURE_EAST_H, - LANG_OPVP_ZM_CAPTURE_WEST_H -}; - -const uint32 ZMBeaconLooseA[ZM_NUM_BEACONS] = { - LANG_OPVP_ZM_LOOSE_EAST_A, - LANG_OPVP_ZM_LOOSE_WEST_A -}; - -const uint32 ZMBeaconLooseH[ZM_NUM_BEACONS] = { - LANG_OPVP_ZM_LOOSE_EAST_H, - LANG_OPVP_ZM_LOOSE_WEST_H -}; - -const go_type ZMCapturePoints[ZM_NUM_BEACONS] = { - {182523,530,303.243,6841.36,40.1245,-1.58825,0,0,0.71325,-0.700909}, - {182522,530,336.466,7340.26,41.4984,-1.58825,0,0,0.71325,-0.700909} -}; - -enum OutdoorPvPZMWorldStates -{ - ZM_UI_TOWER_SLIDER_N_W = 2529, - ZM_UI_TOWER_SLIDER_POS_W = 2528, - ZM_UI_TOWER_SLIDER_DISPLAY_W = 2527, - - ZM_UI_TOWER_SLIDER_N_E = 2535, - ZM_UI_TOWER_SLIDER_POS_E = 2534, - ZM_UI_TOWER_SLIDER_DISPLAY_E = 2533, - - ZM_WORLDSTATE_UNK_1 = 2653, - - ZM_UI_TOWER_EAST_N = 2560, - ZM_UI_TOWER_EAST_H = 2559, - ZM_UI_TOWER_EAST_A = 2558, - ZM_UI_TOWER_WEST_N = 2557, - ZM_UI_TOWER_WEST_H = 2556, - ZM_UI_TOWER_WEST_A = 2555, - - ZM_MAP_TOWER_EAST_N = 2652, - ZM_MAP_TOWER_EAST_H = 2651, - ZM_MAP_TOWER_EAST_A = 2650, - ZM_MAP_GRAVEYARD_H = 2649, - ZM_MAP_GRAVEYARD_A = 2648, - ZM_MAP_GRAVEYARD_N = 2647, - ZM_MAP_TOWER_WEST_N = 2646, - ZM_MAP_TOWER_WEST_H = 2645, - ZM_MAP_TOWER_WEST_A = 2644, - - ZM_MAP_HORDE_FLAG_READY = 2658, - ZM_MAP_HORDE_FLAG_NOT_READY = 2657, - ZM_MAP_ALLIANCE_FLAG_NOT_READY = 2656, - ZM_MAP_ALLIANCE_FLAG_READY = 2655 -}; - -enum ZM_TowerStateMask{ - ZM_TOWERSTATE_N = 1, - ZM_TOWERSTATE_A = 2, - ZM_TOWERSTATE_H = 4 -}; - -class OutdoorPvPZM; -class OPvPCapturePointZM_Beacon : public OPvPCapturePoint -{ -friend class OutdoorPvPZM; -public: - OPvPCapturePointZM_Beacon(OutdoorPvP * pvp, ZM_BeaconType type); - void ChangeState(); - void SendChangePhase(); - void FillInitialWorldStates(WorldPacket & data); - // used when player is activated/inactivated in the area - bool HandlePlayerEnter(Player * plr); - void HandlePlayerLeave(Player * plr); - void UpdateTowerState(); -protected: - ZM_BeaconType m_TowerType; - uint32 m_TowerState; -}; - -enum ZM_GraveYardState{ - ZM_GRAVEYARD_N = 1, - ZM_GRAVEYARD_A = 2, - ZM_GRAVEYARD_H = 4 -}; - -class OPvPCapturePointZM_GraveYard : public OPvPCapturePoint -{ -friend class OutdoorPvPZM; -public: - OPvPCapturePointZM_GraveYard(OutdoorPvP * pvp); - bool Update(uint32 diff); - void ChangeState() {} - void FillInitialWorldStates(WorldPacket & data); - void UpdateTowerState(); - int32 HandleOpenGo(Player *plr, uint64 guid); - void SetBeaconState(uint32 controlling_team); // not good atm - bool HandleGossipOption(Player * plr, uint64 guid, uint32 gossipid); - bool HandleDropFlag(Player * plr, uint32 spellId); - bool CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso); -private: - uint32 m_GraveYardState; -protected: - uint32 m_BothControllingFaction; - uint64 m_FlagCarrierGUID; -}; - -class OutdoorPvPZM : public OutdoorPvP -{ -friend class OPvPCapturePointZM_Beacon; -public: - OutdoorPvPZM(); - bool SetupOutdoorPvP(); - void HandlePlayerEnterZone(Player *plr, uint32 zone); - void HandlePlayerLeaveZone(Player *plr, uint32 zone); - bool Update(uint32 diff); - void FillInitialWorldStates(WorldPacket &data); - void SendRemoveWorldStates(Player * plr); - void HandleKillImpl(Player * plr, Unit * killed); -private: - OPvPCapturePointZM_GraveYard * m_GraveYard; - uint32 m_AllianceTowersControlled; - uint32 m_HordeTowersControlled; -}; - -// todo: flag carrier death/leave/mount/activitychange should give back the gossip options -#endif - diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.cpp b/src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.cpp new file mode 100644 index 00000000000..5691a3ce8be --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.cpp @@ -0,0 +1,765 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "OutdoorPvPEP.h" +#include "WorldPacket.h" +#include "Player.h" +#include "GameObject.h" +#include "ObjectMgr.h" +#include "ObjectAccessor.h" +#include "OutdoorPvPMgr.h" +#include "Creature.h" +#include "Language.h" +#include "World.h" +#include "GossipDef.h" + +OPvPCapturePointEP_EWT::OPvPCapturePointEP_EWT(OutdoorPvP *pvp) +: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_UnitsSummonedSide(0) +{ + SetCapturePointData(EPCapturePoints[EP_EWT].entry,EPCapturePoints[EP_EWT].map,EPCapturePoints[EP_EWT].x,EPCapturePoints[EP_EWT].y,EPCapturePoints[EP_EWT].z,EPCapturePoints[EP_EWT].o,EPCapturePoints[EP_EWT].rot0,EPCapturePoints[EP_EWT].rot1,EPCapturePoints[EP_EWT].rot2,EPCapturePoints[EP_EWT].rot3); + AddObject(EP_EWT_FLAGS,EPTowerFlags[EP_EWT].entry,EPTowerFlags[EP_EWT].map,EPTowerFlags[EP_EWT].x,EPTowerFlags[EP_EWT].y,EPTowerFlags[EP_EWT].z,EPTowerFlags[EP_EWT].o,EPTowerFlags[EP_EWT].rot0,EPTowerFlags[EP_EWT].rot1,EPTowerFlags[EP_EWT].rot2,EPTowerFlags[EP_EWT].rot3); +} + +void OPvPCapturePointEP_EWT::ChangeState() +{ + if (fabs(m_value) == m_maxValue) // state won't change, only phase when maxed out! + { + // if changing from controlling alliance to horde or vice versa + if (m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State) + { + sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_EWT_A)); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_EWT] = 0; + } + else if (m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State) + { + sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_EWT_H)); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_EWT] = 0; + } + + uint32 artkit = 21; + + switch(m_State) + { + case OBJECTIVESTATE_ALLIANCE: + if (m_value == m_maxValue) + m_TowerState = EP_TS_A; + else + m_TowerState = EP_TS_A_P; + artkit = 2; + SummonSupportUnitAtNorthpassTower(ALLIANCE); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_EWT] = ALLIANCE; + if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A)); + break; + case OBJECTIVESTATE_HORDE: + if (m_value == -m_maxValue) + m_TowerState = EP_TS_H; + else + m_TowerState = EP_TS_H_P; + artkit = 1; + SummonSupportUnitAtNorthpassTower(HORDE); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_EWT] = HORDE; + if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H)); + break; + case OBJECTIVESTATE_NEUTRAL: + m_TowerState = EP_TS_N; + break; + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + m_TowerState = EP_TS_N_A; + break; + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + m_TowerState = EP_TS_N_H; + break; + } + + GameObject* flag = HashMapHolder::Find(m_capturePointGUID); + GameObject* flag2 = HashMapHolder::Find(m_Objects[EP_EWT_FLAGS]); + if (flag) + { + flag->SetGoArtKit(artkit); + } + if (flag2) + { + flag2->SetGoArtKit(artkit); + } + + UpdateTowerState(); + + // complete quest objective + if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H) + SendObjectiveComplete(EP_EWT_CM, 0); + } +} + +void OPvPCapturePointEP_EWT::SendChangePhase() +{ + // send this too, sometimes the slider disappears, dunno why :( + SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); + // send these updates to only the ones in this objective + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); + // send this too, sometimes it resets :S + SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); +} + +void OPvPCapturePointEP_EWT::FillInitialWorldStates(WorldPacket &data) +{ + data << EP_EWT_A << uint32(bool(m_TowerState & EP_TS_A)); + data << EP_EWT_H << uint32(bool(m_TowerState & EP_TS_H)); + data << EP_EWT_A_P << uint32(bool(m_TowerState & EP_TS_A_P)); + data << EP_EWT_H_P << uint32(bool(m_TowerState & EP_TS_H_P)); + data << EP_EWT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); + data << EP_EWT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); + data << EP_EWT_N << uint32(bool(m_TowerState & EP_TS_N)); +} + +void OPvPCapturePointEP_EWT::UpdateTowerState() +{ + m_PvP->SendUpdateWorldState(EP_EWT_A , bool(m_TowerState & EP_TS_A)); + m_PvP->SendUpdateWorldState(EP_EWT_H , bool(m_TowerState & EP_TS_H)); + m_PvP->SendUpdateWorldState(EP_EWT_A_P , bool(m_TowerState & EP_TS_A_P)); + m_PvP->SendUpdateWorldState(EP_EWT_H_P , bool(m_TowerState & EP_TS_H_P)); + m_PvP->SendUpdateWorldState(EP_EWT_N_A , bool(m_TowerState & EP_TS_N_A)); + m_PvP->SendUpdateWorldState(EP_EWT_N_H , bool(m_TowerState & EP_TS_N_H)); + m_PvP->SendUpdateWorldState(EP_EWT_N , bool(m_TowerState & EP_TS_N)); +} + +bool OPvPCapturePointEP_EWT::HandlePlayerEnter(Player *plr) +{ + if (OPvPCapturePoint::HandlePlayerEnter(plr)) + { + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); + return true; + } + return false; +} + +void OPvPCapturePointEP_EWT::HandlePlayerLeave(Player *plr) +{ + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0); + OPvPCapturePoint::HandlePlayerLeave(plr); +} + +void OPvPCapturePointEP_EWT::SummonSupportUnitAtNorthpassTower(uint32 team) +{ + if (m_UnitsSummonedSide != team) + { + m_UnitsSummonedSide = team; + const creature_type * ct = NULL; + if (team == ALLIANCE) + ct=EP_EWT_Summons_A; + else + ct=EP_EWT_Summons_H; + + for (int i = 0; i < EP_EWT_NUM_CREATURES; ++i) + { + DelCreature(i); + AddCreature(i,ct[i].entry,ct[i].teamval,ct[i].map,ct[i].x,ct[i].y,ct[i].z,ct[i].o,1000000); + } + } +} + +// NPT +OPvPCapturePointEP_NPT::OPvPCapturePointEP_NPT(OutdoorPvP *pvp) +: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_SummonedGOSide(0) +{ + SetCapturePointData(EPCapturePoints[EP_NPT].entry,EPCapturePoints[EP_NPT].map,EPCapturePoints[EP_NPT].x,EPCapturePoints[EP_NPT].y,EPCapturePoints[EP_NPT].z,EPCapturePoints[EP_NPT].o,EPCapturePoints[EP_NPT].rot0,EPCapturePoints[EP_NPT].rot1,EPCapturePoints[EP_NPT].rot2,EPCapturePoints[EP_NPT].rot3); + AddObject(EP_NPT_FLAGS,EPTowerFlags[EP_NPT].entry,EPTowerFlags[EP_NPT].map,EPTowerFlags[EP_NPT].x,EPTowerFlags[EP_NPT].y,EPTowerFlags[EP_NPT].z,EPTowerFlags[EP_NPT].o,EPTowerFlags[EP_NPT].rot0,EPTowerFlags[EP_NPT].rot1,EPTowerFlags[EP_NPT].rot2,EPTowerFlags[EP_NPT].rot3); +} + +void OPvPCapturePointEP_NPT::ChangeState() +{ + if (fabs(m_value) == m_maxValue) // state won't change, only phase when maxed out! + { + // if changing from controlling alliance to horde or vice versa + if (m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State) + { + sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_NPT_A)); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_NPT] = 0; + } + else if (m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State) + { + sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_NPT_H)); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_NPT] = 0; + } + + uint32 artkit = 21; + + switch(m_State) + { + case OBJECTIVESTATE_ALLIANCE: + if (m_value == m_maxValue) + m_TowerState = EP_TS_A; + else + m_TowerState = EP_TS_A_P; + artkit = 2; + SummonGO(ALLIANCE); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_NPT] = ALLIANCE; + if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A)); + break; + case OBJECTIVESTATE_HORDE: + if (m_value == -m_maxValue) + m_TowerState = EP_TS_H; + else + m_TowerState = EP_TS_H_P; + artkit = 1; + SummonGO(HORDE); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_NPT] = HORDE; + if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H)); + break; + case OBJECTIVESTATE_NEUTRAL: + m_TowerState = EP_TS_N; + m_SummonedGOSide = 0; + DelObject(EP_NPT_BUFF); + break; + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + m_TowerState = EP_TS_N_A; + break; + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + m_TowerState = EP_TS_N_H; + break; + } + + GameObject* flag = HashMapHolder::Find(m_capturePointGUID); + GameObject* flag2 = HashMapHolder::Find(m_Objects[EP_NPT_FLAGS]); + if (flag) + { + flag->SetGoArtKit(artkit); + } + if (flag2) + { + flag2->SetGoArtKit(artkit); + } + + UpdateTowerState(); + + // complete quest objective + if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H) + SendObjectiveComplete(EP_NPT_CM, 0); + } +} + +void OPvPCapturePointEP_NPT::SendChangePhase() +{ + // send this too, sometimes the slider disappears, dunno why :( + SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); + // send these updates to only the ones in this objective + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); + // send this too, sometimes it resets :S + SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); +} + +void OPvPCapturePointEP_NPT::FillInitialWorldStates(WorldPacket &data) +{ + data << EP_NPT_A << uint32(bool(m_TowerState & EP_TS_A)); + data << EP_NPT_H << uint32(bool(m_TowerState & EP_TS_H)); + data << EP_NPT_A_P << uint32(bool(m_TowerState & EP_TS_A_P)); + data << EP_NPT_H_P << uint32(bool(m_TowerState & EP_TS_H_P)); + data << EP_NPT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); + data << EP_NPT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); + data << EP_NPT_N << uint32(bool(m_TowerState & EP_TS_N)); +} + +void OPvPCapturePointEP_NPT::UpdateTowerState() +{ + m_PvP->SendUpdateWorldState(EP_NPT_A , bool(m_TowerState & EP_TS_A)); + m_PvP->SendUpdateWorldState(EP_NPT_H , bool(m_TowerState & EP_TS_H)); + m_PvP->SendUpdateWorldState(EP_NPT_A_P , bool(m_TowerState & EP_TS_A_P)); + m_PvP->SendUpdateWorldState(EP_NPT_H_P , bool(m_TowerState & EP_TS_H_P)); + m_PvP->SendUpdateWorldState(EP_NPT_N_A , bool(m_TowerState & EP_TS_N_A)); + m_PvP->SendUpdateWorldState(EP_NPT_N_H , bool(m_TowerState & EP_TS_N_H)); + m_PvP->SendUpdateWorldState(EP_NPT_N , bool(m_TowerState & EP_TS_N)); +} + +bool OPvPCapturePointEP_NPT::HandlePlayerEnter(Player *plr) +{ + if (OPvPCapturePoint::HandlePlayerEnter(plr)) + { + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); + return true; + } + return false; +} + +void OPvPCapturePointEP_NPT::HandlePlayerLeave(Player *plr) +{ + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0); + OPvPCapturePoint::HandlePlayerLeave(plr); +} + +void OPvPCapturePointEP_NPT::SummonGO(uint32 team) +{ + if (m_SummonedGOSide != team) + { + m_SummonedGOSide = team; + DelObject(EP_NPT_BUFF); + AddObject(EP_NPT_BUFF,EP_NPT_LordaeronShrine.entry,EP_NPT_LordaeronShrine.map,EP_NPT_LordaeronShrine.x,EP_NPT_LordaeronShrine.y,EP_NPT_LordaeronShrine.z,EP_NPT_LordaeronShrine.o,EP_NPT_LordaeronShrine.rot0,EP_NPT_LordaeronShrine.rot1,EP_NPT_LordaeronShrine.rot2,EP_NPT_LordaeronShrine.rot3); + GameObject * go = HashMapHolder::Find(m_Objects[EP_NPT_BUFF]); + if (go) + go->SetUInt32Value(GAMEOBJECT_FACTION,(team == ALLIANCE ? 84 : 83)); + } +} + +// CGT +OPvPCapturePointEP_CGT::OPvPCapturePointEP_CGT(OutdoorPvP *pvp) +: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_GraveyardSide(0) +{ + SetCapturePointData(EPCapturePoints[EP_CGT].entry,EPCapturePoints[EP_CGT].map,EPCapturePoints[EP_CGT].x,EPCapturePoints[EP_CGT].y,EPCapturePoints[EP_CGT].z,EPCapturePoints[EP_CGT].o,EPCapturePoints[EP_CGT].rot0,EPCapturePoints[EP_CGT].rot1,EPCapturePoints[EP_CGT].rot2,EPCapturePoints[EP_CGT].rot3); + AddObject(EP_CGT_FLAGS,EPTowerFlags[EP_CGT].entry,EPTowerFlags[EP_CGT].map,EPTowerFlags[EP_CGT].x,EPTowerFlags[EP_CGT].y,EPTowerFlags[EP_CGT].z,EPTowerFlags[EP_CGT].o,EPTowerFlags[EP_CGT].rot0,EPTowerFlags[EP_CGT].rot1,EPTowerFlags[EP_CGT].rot2,EPTowerFlags[EP_CGT].rot3); +} + +void OPvPCapturePointEP_CGT::ChangeState() +{ + if (fabs(m_value) == m_maxValue) // state won't change, only phase when maxed out! + { + // if changing from controlling alliance to horde or vice versa + if (m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State) + { + sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_CGT_A)); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_CGT] = 0; + } + else if (m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State) + { + sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_CGT_H)); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_CGT] = 0; + } + + uint32 artkit = 21; + + switch(m_State) + { + case OBJECTIVESTATE_ALLIANCE: + if (m_value == m_maxValue) + m_TowerState = EP_TS_A; + else + m_TowerState = EP_TS_A_P; + artkit = 2; + LinkGraveYard(ALLIANCE); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_CGT] = ALLIANCE; + if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A)); + break; + case OBJECTIVESTATE_HORDE: + if (m_value == -m_maxValue) + m_TowerState = EP_TS_H; + else + m_TowerState = EP_TS_H_P; + artkit = 1; + LinkGraveYard(HORDE); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_CGT] = HORDE; + if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H)); + break; + case OBJECTIVESTATE_NEUTRAL: + m_TowerState = EP_TS_N; + break; + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + m_TowerState = EP_TS_N_A; + break; + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + m_TowerState = EP_TS_N_H; + break; + } + + GameObject* flag = HashMapHolder::Find(m_capturePointGUID); + GameObject* flag2 = HashMapHolder::Find(m_Objects[EP_CGT_FLAGS]); + if (flag) + { + flag->SetGoArtKit(artkit); + } + if (flag2) + { + flag2->SetGoArtKit(artkit); + } + + UpdateTowerState(); + + // complete quest objective + if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H) + SendObjectiveComplete(EP_CGT_CM, 0); + } +} + +void OPvPCapturePointEP_CGT::SendChangePhase() +{ + // send this too, sometimes the slider disappears, dunno why :( + SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); + // send these updates to only the ones in this objective + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); + // send this too, sometimes it resets :S + SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); +} + +void OPvPCapturePointEP_CGT::FillInitialWorldStates(WorldPacket &data) +{ + data << EP_CGT_A << uint32(bool(m_TowerState & EP_TS_A)); + data << EP_CGT_H << uint32(bool(m_TowerState & EP_TS_H)); + data << EP_CGT_A_P << uint32(bool(m_TowerState & EP_TS_A_P)); + data << EP_CGT_H_P << uint32(bool(m_TowerState & EP_TS_H_P)); + data << EP_CGT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); + data << EP_CGT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); + data << EP_CGT_N << uint32(bool(m_TowerState & EP_TS_N)); +} + +void OPvPCapturePointEP_CGT::UpdateTowerState() +{ + m_PvP->SendUpdateWorldState(EP_CGT_A , bool(m_TowerState & EP_TS_A)); + m_PvP->SendUpdateWorldState(EP_CGT_H , bool(m_TowerState & EP_TS_H)); + m_PvP->SendUpdateWorldState(EP_CGT_A_P , bool(m_TowerState & EP_TS_A_P)); + m_PvP->SendUpdateWorldState(EP_CGT_H_P , bool(m_TowerState & EP_TS_H_P)); + m_PvP->SendUpdateWorldState(EP_CGT_N_A , bool(m_TowerState & EP_TS_N_A)); + m_PvP->SendUpdateWorldState(EP_CGT_N_H , bool(m_TowerState & EP_TS_N_H)); + m_PvP->SendUpdateWorldState(EP_CGT_N , bool(m_TowerState & EP_TS_N)); +} + +bool OPvPCapturePointEP_CGT::HandlePlayerEnter(Player *plr) +{ + if (OPvPCapturePoint::HandlePlayerEnter(plr)) + { + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); + return true; + } + return false; +} + +void OPvPCapturePointEP_CGT::HandlePlayerLeave(Player *plr) +{ + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0); + OPvPCapturePoint::HandlePlayerLeave(plr); +} + +void OPvPCapturePointEP_CGT::LinkGraveYard(uint32 team) +{ + if (m_GraveyardSide != team) + { + m_GraveyardSide = team; + objmgr.RemoveGraveYardLink(EP_GraveYardId,EP_GraveYardZone,team,false); + objmgr.AddGraveYardLink(EP_GraveYardId,EP_GraveYardZone,team,false); + } +} + +// PWT +OPvPCapturePointEP_PWT::OPvPCapturePointEP_PWT(OutdoorPvP *pvp) +: OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_FlightMasterSpawned(0) +{ + SetCapturePointData(EPCapturePoints[EP_PWT].entry,EPCapturePoints[EP_PWT].map,EPCapturePoints[EP_PWT].x,EPCapturePoints[EP_PWT].y,EPCapturePoints[EP_PWT].z,EPCapturePoints[EP_PWT].o,EPCapturePoints[EP_PWT].rot0,EPCapturePoints[EP_PWT].rot1,EPCapturePoints[EP_PWT].rot2,EPCapturePoints[EP_PWT].rot3); + AddObject(EP_PWT_FLAGS,EPTowerFlags[EP_PWT].entry,EPTowerFlags[EP_PWT].map,EPTowerFlags[EP_PWT].x,EPTowerFlags[EP_PWT].y,EPTowerFlags[EP_PWT].z,EPTowerFlags[EP_PWT].o,EPTowerFlags[EP_PWT].rot0,EPTowerFlags[EP_PWT].rot1,EPTowerFlags[EP_PWT].rot2,EPTowerFlags[EP_PWT].rot3); +} + +void OPvPCapturePointEP_PWT::ChangeState() +{ + if (fabs(m_value) == m_maxValue) // state won't change, only phase when maxed out! + { + // if changing from controlling alliance to horde or vice versa + if (m_OldState == OBJECTIVESTATE_ALLIANCE && m_OldState != m_State) + { + sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_PWT_A)); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_PWT] = 0; + } + else if (m_OldState == OBJECTIVESTATE_HORDE && m_OldState != m_State) + { + sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_LOOSE_PWT_H)); + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_PWT] = 0; + } + + uint32 artkit = 21; + + switch(m_State) + { + case OBJECTIVESTATE_ALLIANCE: + if (m_value == m_maxValue) + m_TowerState = EP_TS_A; + else + m_TowerState = EP_TS_A_P; + SummonFlightMaster(ALLIANCE); + artkit = 2; + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_PWT] = ALLIANCE; + if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A)); + break; + case OBJECTIVESTATE_HORDE: + if (m_value == -m_maxValue) + m_TowerState = EP_TS_H; + else + m_TowerState = EP_TS_H_P; + SummonFlightMaster(HORDE); + artkit = 1; + ((OutdoorPvPEP*)m_PvP)->EP_Controls[EP_PWT] = HORDE; + if (m_OldState != m_State) sWorld.SendZoneText(EP_GraveYardZone,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H)); + break; + case OBJECTIVESTATE_NEUTRAL: + m_TowerState = EP_TS_N; + DelCreature(EP_PWT_FLIGHTMASTER); + m_FlightMasterSpawned = 0; + break; + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + m_TowerState = EP_TS_N_A; + break; + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + m_TowerState = EP_TS_N_H; + break; + } + + GameObject* flag = HashMapHolder::Find(m_capturePointGUID); + GameObject* flag2 = HashMapHolder::Find(m_Objects[EP_PWT_FLAGS]); + if (flag) + { + flag->SetGoArtKit(artkit); + } + if (flag2) + { + flag2->SetGoArtKit(artkit); + } + + UpdateTowerState(); + + // complete quest objective + if (m_TowerState == EP_TS_A || m_TowerState == EP_TS_H) + SendObjectiveComplete(EP_PWT_CM, 0); + } +} + +void OPvPCapturePointEP_PWT::SendChangePhase() +{ + // send this too, sometimes the slider disappears, dunno why :( + SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); + // send these updates to only the ones in this objective + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); + // send this too, sometimes it resets :S + SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); +} + +void OPvPCapturePointEP_PWT::FillInitialWorldStates(WorldPacket &data) +{ + data << EP_PWT_A << uint32(bool(m_TowerState & EP_TS_A)); + data << EP_PWT_H << uint32(bool(m_TowerState & EP_TS_H)); + data << EP_PWT_A_P << uint32(bool(m_TowerState & EP_TS_A_P)); + data << EP_PWT_H_P << uint32(bool(m_TowerState & EP_TS_H_P)); + data << EP_PWT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); + data << EP_PWT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); + data << EP_PWT_N << uint32(bool(m_TowerState & EP_TS_N)); +} + +void OPvPCapturePointEP_PWT::UpdateTowerState() +{ + m_PvP->SendUpdateWorldState(EP_PWT_A , bool(m_TowerState & EP_TS_A)); + m_PvP->SendUpdateWorldState(EP_PWT_H , bool(m_TowerState & EP_TS_H)); + m_PvP->SendUpdateWorldState(EP_PWT_A_P , bool(m_TowerState & EP_TS_A_P)); + m_PvP->SendUpdateWorldState(EP_PWT_H_P , bool(m_TowerState & EP_TS_H_P)); + m_PvP->SendUpdateWorldState(EP_PWT_N_A , bool(m_TowerState & EP_TS_N_A)); + m_PvP->SendUpdateWorldState(EP_PWT_N_H , bool(m_TowerState & EP_TS_N_H)); + m_PvP->SendUpdateWorldState(EP_PWT_N , bool(m_TowerState & EP_TS_N)); +} + +bool OPvPCapturePointEP_PWT::HandlePlayerEnter(Player *plr) +{ + if (OPvPCapturePoint::HandlePlayerEnter(plr)) + { + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 1); + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS, phase); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, m_neutralValuePct); + return true; + } + return false; +} + +void OPvPCapturePointEP_PWT::HandlePlayerLeave(Player *plr) +{ + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY, 0); + OPvPCapturePoint::HandlePlayerLeave(plr); +} + +void OPvPCapturePointEP_PWT::SummonFlightMaster(uint32 team) +{ + if (m_FlightMasterSpawned != team) + { + m_FlightMasterSpawned = team; + DelCreature(EP_PWT_FLIGHTMASTER); + AddCreature(EP_PWT_FLIGHTMASTER,EP_PWT_FlightMaster.entry,team,EP_PWT_FlightMaster.map,EP_PWT_FlightMaster.x,EP_PWT_FlightMaster.y,EP_PWT_FlightMaster.z,EP_PWT_FlightMaster.o); + } +} + +// ep +OutdoorPvPEP::OutdoorPvPEP() +{ + m_TypeId = OUTDOOR_PVP_EP; + memset(EP_Controls,0,sizeof(EP_Controls)); + m_AllianceTowersControlled = 0; + m_HordeTowersControlled = 0; +} + +bool OutdoorPvPEP::SetupOutdoorPvP() +{ + for (int i = 0; i < EPBuffZonesNum; ++i) + RegisterZone(EPBuffZones[i]); + + AddCapturePoint(new OPvPCapturePointEP_EWT(this)); + AddCapturePoint(new OPvPCapturePointEP_PWT(this)); + AddCapturePoint(new OPvPCapturePointEP_CGT(this)); + AddCapturePoint(new OPvPCapturePointEP_NPT(this)); + return true; +} + +bool OutdoorPvPEP::Update(uint32 diff) +{ + if (OutdoorPvP::Update(diff)) + { + m_AllianceTowersControlled = 0; + m_HordeTowersControlled = 0; + for (int i = 0; i < EP_TOWER_NUM; ++i) + { + if (EP_Controls[i] == ALLIANCE) + ++m_AllianceTowersControlled; + else if (EP_Controls[i] == HORDE) + ++m_HordeTowersControlled; + SendUpdateWorldState(EP_UI_TOWER_COUNT_A,m_AllianceTowersControlled); + SendUpdateWorldState(EP_UI_TOWER_COUNT_H,m_HordeTowersControlled); + BuffTeams(); + } + return true; + } + return false; +} + +void OutdoorPvPEP::HandlePlayerEnterZone(Player * plr, uint32 zone) +{ + // add buffs + if (plr->GetTeam() == ALLIANCE) + { + if (m_AllianceTowersControlled && m_AllianceTowersControlled < 5) + plr->CastSpell(plr,EP_AllianceBuffs[m_AllianceTowersControlled-1],true); + } + else + { + if (m_HordeTowersControlled && m_HordeTowersControlled < 5) + plr->CastSpell(plr,EP_HordeBuffs[m_HordeTowersControlled-1],true); + } + OutdoorPvP::HandlePlayerEnterZone(plr,zone); +} + +void OutdoorPvPEP::HandlePlayerLeaveZone(Player * plr, uint32 zone) +{ + // remove buffs + if (plr->GetTeam() == ALLIANCE) + { + for (int i = 0; i < 4; ++i) + plr->RemoveAurasDueToSpell(EP_AllianceBuffs[i]); + } + else + { + for (int i = 0; i < 4; ++i) + plr->RemoveAurasDueToSpell(EP_HordeBuffs[i]); + } + OutdoorPvP::HandlePlayerLeaveZone(plr, zone); +} + +void OutdoorPvPEP::BuffTeams() +{ + for (PlayerSet::iterator itr = m_players[0].begin(); itr != m_players[0].end(); ++itr) + { + Player * plr = *itr; + { + for (int i = 0; i < 4; ++i) + plr->RemoveAurasDueToSpell(EP_AllianceBuffs[i]); + if (m_AllianceTowersControlled && m_AllianceTowersControlled < 5) + plr->CastSpell(plr,EP_AllianceBuffs[m_AllianceTowersControlled-1],true); + } + } + for (PlayerSet::iterator itr = m_players[1].begin(); itr != m_players[1].end(); ++itr) + { + Player * plr = *itr; + { + for (int i = 0; i < 4; ++i) + plr->RemoveAurasDueToSpell(EP_HordeBuffs[i]); + if (m_HordeTowersControlled && m_HordeTowersControlled < 5) + plr->CastSpell(plr,EP_HordeBuffs[m_HordeTowersControlled-1],true); + } + } +} + +void OutdoorPvPEP::FillInitialWorldStates(WorldPacket & data) +{ + data << EP_UI_TOWER_COUNT_A << m_AllianceTowersControlled; + data << EP_UI_TOWER_COUNT_H << m_HordeTowersControlled; + data << EP_UI_TOWER_SLIDER_DISPLAY << uint32(0); + data << EP_UI_TOWER_SLIDER_POS << uint32(50); + data << EP_UI_TOWER_SLIDER_N << uint32(100); + for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) + { + itr->second->FillInitialWorldStates(data); + } +} + +void OutdoorPvPEP::SendRemoveWorldStates(Player *plr) +{ + plr->SendUpdateWorldState(EP_UI_TOWER_COUNT_A,0); + plr->SendUpdateWorldState(EP_UI_TOWER_COUNT_H,0); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_DISPLAY,0); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_POS,0); + plr->SendUpdateWorldState(EP_UI_TOWER_SLIDER_N,0); + + plr->SendUpdateWorldState(EP_EWT_A,0); + plr->SendUpdateWorldState(EP_EWT_H,0); + plr->SendUpdateWorldState(EP_EWT_N,0); + plr->SendUpdateWorldState(EP_EWT_A_P,0); + plr->SendUpdateWorldState(EP_EWT_H_P,0); + plr->SendUpdateWorldState(EP_EWT_N_A,0); + plr->SendUpdateWorldState(EP_EWT_N_H,0); + + plr->SendUpdateWorldState(EP_PWT_A,0); + plr->SendUpdateWorldState(EP_PWT_H,0); + plr->SendUpdateWorldState(EP_PWT_N,0); + plr->SendUpdateWorldState(EP_PWT_A_P,0); + plr->SendUpdateWorldState(EP_PWT_H_P,0); + plr->SendUpdateWorldState(EP_PWT_N_A,0); + plr->SendUpdateWorldState(EP_PWT_N_H,0); + + plr->SendUpdateWorldState(EP_NPT_A,0); + plr->SendUpdateWorldState(EP_NPT_H,0); + plr->SendUpdateWorldState(EP_NPT_N,0); + plr->SendUpdateWorldState(EP_NPT_A_P,0); + plr->SendUpdateWorldState(EP_NPT_H_P,0); + plr->SendUpdateWorldState(EP_NPT_N_A,0); + plr->SendUpdateWorldState(EP_NPT_N_H,0); + + plr->SendUpdateWorldState(EP_CGT_A,0); + plr->SendUpdateWorldState(EP_CGT_H,0); + plr->SendUpdateWorldState(EP_CGT_N,0); + plr->SendUpdateWorldState(EP_CGT_A_P,0); + plr->SendUpdateWorldState(EP_CGT_H_P,0); + plr->SendUpdateWorldState(EP_CGT_N_A,0); + plr->SendUpdateWorldState(EP_CGT_N_H,0); +} + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.h b/src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.h new file mode 100644 index 00000000000..071d6bcde2d --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPEP.h @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OUTDOOR_PVP_EP_ +#define OUTDOOR_PVP_EP_ + +#include "OutdoorPvPImpl.h" + +#include "DBCStructure.h" + +const uint32 EP_AllianceBuffs[4] = {11413, 11414, 11415, 1386}; + +const uint32 EP_HordeBuffs[4] = {30880, 30683, 30682, 29520}; + +const uint32 EP_GraveYardZone = 139; + +const uint32 EP_GraveYardId = 927; + +const uint32 EPBuffZonesNum = 3; + +const uint32 EP_EWT_CM = 17690; +const uint32 EP_CGT_CM = 17689; +const uint32 EP_NPT_CM = 17696; +const uint32 EP_PWT_CM = 17698; + +const uint32 EPBuffZones[EPBuffZonesNum] = {139, 2017, 2057}; + +enum EP_TaxiNodes { + EP_CGT_Taxi = 87, + EP_EWT_Taxi = 86, + EP_NPT_Taxi = 85, + EP_PWT_Taxi = 84 +}; + +enum EP_EastwallTowerWorldStates { + EP_EWT_A = 2354, + EP_EWT_H = 2356, + EP_EWT_A_P = 2357, // ally progressing + EP_EWT_H_P = 2358, + EP_EWT_N_A = 2359, // ally conquested + EP_EWT_N_H = 2360, + EP_EWT_N = 2361 +}; + +enum EP_NorthpassTowerWorldStates { + EP_NPT_N = 2352, + EP_NPT_N_A = 2362, + EP_NPT_N_H = 2363, + EP_NPT_A_P = 2364, + EP_NPT_H_P = 2365, + EP_NPT_A = 2372, + EP_NPT_H = 2373 +}; + +enum EP_PlagewoodTowerWorldStates { + EP_PWT_N_A = 2366, + EP_PWT_N_H = 2353, //2367 not present! use neutral! + EP_PWT_A_P = 2368, + EP_PWT_H_P = 2369, + EP_PWT_A = 2370, + EP_PWT_H = 2371, + EP_PWT_N = 2353 +}; + +enum EP_CrownGuardTowerWorldStates { + EP_CGT_N_A = 2374, + EP_CGT_N_H = 2375, + EP_CGT_A_P = 2376, + EP_CGT_H_P = 2377, + EP_CGT_A = 2378, + EP_CGT_H = 2379, + EP_CGT_N = 2355 +}; + +enum EP_WorldStates { + EP_UI_TOWER_SLIDER_DISPLAY = 2426, + EP_UI_TOWER_SLIDER_POS = 2427, + EP_UI_TOWER_SLIDER_N = 2428, + + EP_UI_TOWER_COUNT_A = 2327, + EP_UI_TOWER_COUNT_H = 2328 +}; + +enum EP_Summons { + EP_EWT_COMMANDER = 0, + EP_EWT_SOLDIER1, + EP_EWT_SOLDIER2, + EP_EWT_SOLDIER3, + EP_EWT_SOLDIER4, + EP_PWT_FLIGHTMASTER, +}; + +enum EP_GoSummons { + EP_NPT_BUFF = 0, + EP_NPT_FLAGS, + EP_EWT_FLAGS, + EP_CGT_FLAGS, + EP_PWT_FLAGS +}; + +enum EP_Towers { + EP_EWT = 0, // plaguelands 03 + EP_NPT,// plaguelands 01 + EP_PWT,// plaguelands 04 + EP_CGT,// plaguelands 02 + EP_TOWER_NUM +}; + +const go_type EPCapturePoints[EP_TOWER_NUM] = { + {182097,0,2574.51,-4794.89,144.704,-1.45003,-0.097056,0.095578,-0.656229,0.742165}, + {181899,0,3181.08,-4379.36,174.123,-2.03472,-0.065392,0.119494,-0.842275,0.521553}, + {182098,0,2962.71,-3042.31,154.789,2.08426,-0.074807,-0.113837,0.855928,0.49883}, + {182096,0,1860.85,-3731.23,196.716,-2.53214,0.033967,-0.131914,0.944741,-0.298177} +}; + +const go_type EPTowerFlags[EP_TOWER_NUM] = { + {182106,0,2569.60,-4772.93,115.399,2.72271,0,0,0.978148,0.207912}, + {182106,0,3148.17,-4365.51,145.029,1.53589,0,0,0.694658,0.71934}, + {182106,0,2992.63,-3022.95,125.593,3.03687,0,0,0.99863,0.052336}, + {182106,0,1838.42,-3703.56,167.713,0.890118,0,0,0.430511,0.902585} +}; + +const uint32 EPTowerPlayerEnterEvents[EP_TOWER_NUM] = {10691,10699,10701,10705}; + +const uint32 EPTowerPlayerLeaveEvents[EP_TOWER_NUM] = {10692,10698,10700,10704}; + +const uint32 EP_NUM_CREATURES = 6; +const uint32 EP_EWT_NUM_CREATURES = 5; + +// one lordaeron commander, 4 soldiers +// should be spawned at EWT and follow a path, but trans-grid pathing isn't safe, so summon them directly at NPT +const creature_type EP_EWT_Summons_A[EP_EWT_NUM_CREATURES] = { + {17635,469,0, 3167.61,-4352.09,138.20,4.5811}, + {17647,469,0, 3172.74,-4352.99,139.14,4.9873}, + {17647,469,0, 3165.89,-4354.46,138.67,3.7244}, + {17647,469,0, 3164.65,-4350.26,138.22,2.4794}, + {17647,469,0, 3169.91,-4349.68,138.37,0.7444} +}; + +const creature_type EP_EWT_Summons_H[EP_EWT_NUM_CREATURES] = { + {17995,67,0, 3167.61,-4352.09,138.20,4.5811}, + {17996,67,0, 3172.74,-4352.99,139.14,4.9873}, + {17996,67,0, 3165.89,-4354.46,138.67,3.7244}, + {17996,67,0, 3164.65,-4350.26,138.22,2.4794}, + {17996,67,0, 3169.91,-4349.68,138.37,0.7444} +}; + +enum EP_TowerStates { + EP_TS_N = 1, + EP_TS_N_A = 2, + EP_TS_N_H = 4, + EP_TS_A_P = 8, + EP_TS_H_P = 16, + EP_TS_A = 32, + EP_TS_H = 64 +}; + +// when spawning, pay attention at setting the faction manually! +const creature_type EP_PWT_FlightMaster = {17209,0,0,2987.5,-3049.11,120.126,5.75959}; + +// after spawning, modify the faction so that only the controller will be able to use it with SetUInt32Value(GAMEOBJECT_FACTION, faction_id); +const go_type EP_NPT_LordaeronShrine = {181682,0,3167.72,-4355.91,138.785,1.69297,0,0,0.748956,0.66262}; + +class OutdoorPvPEP; + +class OPvPCapturePointEP_EWT : public OPvPCapturePoint +{ +friend class OutdoorPvPEP; +public: + OPvPCapturePointEP_EWT(OutdoorPvP * pvp); + void ChangeState(); + void SendChangePhase(); + void FillInitialWorldStates(WorldPacket & data); + // used when player is activated/inactivated in the area + bool HandlePlayerEnter(Player * plr); + void HandlePlayerLeave(Player * plr); +protected: + void SummonSupportUnitAtNorthpassTower(uint32 team); + void UpdateTowerState(); +protected: + uint32 m_TowerState; + uint32 m_UnitsSummonedSide; +}; + +class OPvPCapturePointEP_NPT : public OPvPCapturePoint +{ +friend class OutdoorPvPEP; +public: + OPvPCapturePointEP_NPT(OutdoorPvP * pvp); + void ChangeState(); + void SendChangePhase(); + void FillInitialWorldStates(WorldPacket & data); + // used when player is activated/inactivated in the area + bool HandlePlayerEnter(Player * plr); + void HandlePlayerLeave(Player * plr); +protected: + void SummonGO(uint32 team); + void UpdateTowerState(); +protected: + uint32 m_TowerState; + uint32 m_SummonedGOSide; +}; + +class OPvPCapturePointEP_CGT : public OPvPCapturePoint +{ +friend class OutdoorPvPEP; +public: + OPvPCapturePointEP_CGT(OutdoorPvP * pvp); + void ChangeState(); + void SendChangePhase(); + void FillInitialWorldStates(WorldPacket & data); + // used when player is activated/inactivated in the area + bool HandlePlayerEnter(Player * plr); + void HandlePlayerLeave(Player * plr); +protected: + void LinkGraveYard(uint32 team); + void UpdateTowerState(); +protected: + uint32 m_TowerState; + uint32 m_GraveyardSide; +}; + +class OPvPCapturePointEP_PWT : public OPvPCapturePoint +{ +friend class OutdoorPvPEP; +public: + OPvPCapturePointEP_PWT(OutdoorPvP * pvp); + void ChangeState(); + void SendChangePhase(); + void FillInitialWorldStates(WorldPacket & data); + // used when player is activated/inactivated in the area + bool HandlePlayerEnter(Player * plr); + void HandlePlayerLeave(Player * plr); +protected: + void SummonFlightMaster(uint32 team); + void UpdateTowerState(); +protected: + uint32 m_FlightMasterSpawned; + uint32 m_TowerState; +}; + +class OutdoorPvPEP : public OutdoorPvP +{ +friend class OPvPCapturePointEP_EWT; +friend class OPvPCapturePointEP_NPT; +friend class OPvPCapturePointEP_PWT; +friend class OPvPCapturePointEP_CGT; +public: + OutdoorPvPEP(); + bool SetupOutdoorPvP(); + void HandlePlayerEnterZone(Player *plr, uint32 zone); + void HandlePlayerLeaveZone(Player *plr, uint32 zone); + bool Update(uint32 diff); + void FillInitialWorldStates(WorldPacket &data); + void SendRemoveWorldStates(Player * plr); + void BuffTeams(); +private: + // how many towers are controlled + uint32 EP_Controls[EP_TOWER_NUM]; + uint32 m_AllianceTowersControlled; + uint32 m_HordeTowersControlled; +}; + +#endif + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.cpp b/src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.cpp new file mode 100644 index 00000000000..f4f73d015ce --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.cpp @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "OutdoorPvPHP.h" +#include "OutdoorPvP.h" +#include "OutdoorPvPMgr.h" +#include "Player.h" +#include "WorldPacket.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Language.h" + +const uint32 HP_LANG_LOOSE_A[HP_TOWER_NUM] = {LANG_OPVP_HP_LOOSE_BROKENHILL_A,LANG_OPVP_HP_LOOSE_OVERLOOK_A,LANG_OPVP_HP_LOOSE_STADIUM_A}; + +const uint32 HP_LANG_LOOSE_H[HP_TOWER_NUM] = {LANG_OPVP_HP_LOOSE_BROKENHILL_H,LANG_OPVP_HP_LOOSE_OVERLOOK_H,LANG_OPVP_HP_LOOSE_STADIUM_H}; + +const uint32 HP_LANG_CAPTURE_A[HP_TOWER_NUM] = {LANG_OPVP_HP_CAPTURE_BROKENHILL_A,LANG_OPVP_HP_CAPTURE_OVERLOOK_A,LANG_OPVP_HP_CAPTURE_STADIUM_A}; + +const uint32 HP_LANG_CAPTURE_H[HP_TOWER_NUM] = {LANG_OPVP_HP_CAPTURE_BROKENHILL_H,LANG_OPVP_HP_CAPTURE_OVERLOOK_H,LANG_OPVP_HP_CAPTURE_STADIUM_H}; + +OPvPCapturePointHP::OPvPCapturePointHP(OutdoorPvP *pvp,OutdoorPvPHPTowerType type) +: OPvPCapturePoint(pvp), m_TowerType(type) +{ + SetCapturePointData(HPCapturePoints[type].entry, + HPCapturePoints[type].map, + HPCapturePoints[type].x, + HPCapturePoints[type].y, + HPCapturePoints[type].z, + HPCapturePoints[type].o, + HPCapturePoints[type].rot0, + HPCapturePoints[type].rot1, + HPCapturePoints[type].rot2, + HPCapturePoints[type].rot3); + AddObject(type, + HPTowerFlags[type].entry, + HPTowerFlags[type].map, + HPTowerFlags[type].x, + HPTowerFlags[type].y, + HPTowerFlags[type].z, + HPTowerFlags[type].o, + HPTowerFlags[type].rot0, + HPTowerFlags[type].rot1, + HPTowerFlags[type].rot2, + HPTowerFlags[type].rot3); +} + +OutdoorPvPHP::OutdoorPvPHP() +{ + m_TypeId = OUTDOOR_PVP_HP; +} + +bool OutdoorPvPHP::SetupOutdoorPvP() +{ + m_AllianceTowersControlled = 0; + m_HordeTowersControlled = 0; + // add the zones affected by the pvp buff + for (int i = 0; i < OutdoorPvPHPBuffZonesNum; ++i) + RegisterZone(OutdoorPvPHPBuffZones[i]); + + AddCapturePoint(new OPvPCapturePointHP(this,HP_TOWER_BROKEN_HILL)); + + AddCapturePoint(new OPvPCapturePointHP(this,HP_TOWER_OVERLOOK)); + + AddCapturePoint(new OPvPCapturePointHP(this,HP_TOWER_STADIUM)); + + return true; +} + +void OutdoorPvPHP::HandlePlayerEnterZone(Player * plr, uint32 zone) +{ + // add buffs + if (plr->GetTeam() == ALLIANCE) + { + if (m_AllianceTowersControlled >=3) + plr->CastSpell(plr,AllianceBuff,true); + } + else + { + if (m_HordeTowersControlled >=3) + plr->CastSpell(plr,HordeBuff,true); + } + OutdoorPvP::HandlePlayerEnterZone(plr,zone); +} + +void OutdoorPvPHP::HandlePlayerLeaveZone(Player * plr, uint32 zone) +{ + // remove buffs + if (plr->GetTeam() == ALLIANCE) + { + plr->RemoveAurasDueToSpell(AllianceBuff); + } + else + { + plr->RemoveAurasDueToSpell(HordeBuff); + } + OutdoorPvP::HandlePlayerLeaveZone(plr, zone); +} + +bool OutdoorPvPHP::Update(uint32 diff) +{ + bool changed = OutdoorPvP::Update(diff); + if (changed) + { + if (m_AllianceTowersControlled == 3) + TeamApplyBuff(TEAM_ALLIANCE, AllianceBuff, HordeBuff); + else if (m_HordeTowersControlled == 3) + TeamApplyBuff(TEAM_HORDE, HordeBuff, AllianceBuff); + else + { + TeamCastSpell(TEAM_ALLIANCE, -AllianceBuff); + TeamCastSpell(TEAM_HORDE, -HordeBuff); + } + SendUpdateWorldState(HP_UI_TOWER_COUNT_A, m_AllianceTowersControlled); + SendUpdateWorldState(HP_UI_TOWER_COUNT_H, m_HordeTowersControlled); + } + return changed; +} + +void OutdoorPvPHP::SendRemoveWorldStates(Player *plr) +{ + plr->SendUpdateWorldState(HP_UI_TOWER_DISPLAY_A,0); + plr->SendUpdateWorldState(HP_UI_TOWER_DISPLAY_H,0); + plr->SendUpdateWorldState(HP_UI_TOWER_COUNT_H,0); + plr->SendUpdateWorldState(HP_UI_TOWER_COUNT_A,0); + plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_N,0); + plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_POS,0); + plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY,0); + for (int i = 0; i < HP_TOWER_NUM; ++i) + { + plr->SendUpdateWorldState(HP_MAP_N[i],0); + plr->SendUpdateWorldState(HP_MAP_A[i],0); + plr->SendUpdateWorldState(HP_MAP_H[i],0); + } +} + +void OutdoorPvPHP::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(HP_UI_TOWER_DISPLAY_A) << uint32(1); + data << uint32(HP_UI_TOWER_DISPLAY_H) << uint32(1); + data << uint32(HP_UI_TOWER_COUNT_A) << uint32(m_AllianceTowersControlled); + data << uint32(HP_UI_TOWER_COUNT_H) << uint32(m_HordeTowersControlled); + data << uint32(HP_UI_TOWER_SLIDER_DISPLAY) << uint32(0); + data << uint32(HP_UI_TOWER_SLIDER_POS) << uint32(50); + data << uint32(HP_UI_TOWER_SLIDER_N) << uint32(100); + for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) + { + itr->second->FillInitialWorldStates(data); + } +} + +void OPvPCapturePointHP::ChangeState() +{ + uint32 field = 0; + switch(m_OldState) + { + case OBJECTIVESTATE_NEUTRAL: + field = HP_MAP_N[m_TowerType]; + break; + case OBJECTIVESTATE_ALLIANCE: + field = HP_MAP_A[m_TowerType]; + if (((OutdoorPvPHP*)m_PvP)->m_AllianceTowersControlled) + ((OutdoorPvPHP*)m_PvP)->m_AllianceTowersControlled--; + sWorld.SendZoneText(OutdoorPvPHPBuffZones[0],objmgr.GetTrinityStringForDBCLocale(HP_LANG_LOOSE_A[m_TowerType])); + break; + case OBJECTIVESTATE_HORDE: + field = HP_MAP_H[m_TowerType]; + if (((OutdoorPvPHP*)m_PvP)->m_HordeTowersControlled) + ((OutdoorPvPHP*)m_PvP)->m_HordeTowersControlled--; + sWorld.SendZoneText(OutdoorPvPHPBuffZones[0],objmgr.GetTrinityStringForDBCLocale(HP_LANG_LOOSE_H[m_TowerType])); + break; + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + field = HP_MAP_N[m_TowerType]; + break; + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + field = HP_MAP_N[m_TowerType]; + break; + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + field = HP_MAP_A[m_TowerType]; + break; + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + field = HP_MAP_H[m_TowerType]; + break; + } + + // send world state update + if (field) + { + m_PvP->SendUpdateWorldState(field, 0); + field = 0; + } + uint32 artkit = 21; + uint32 artkit2 = HP_TowerArtKit_N[m_TowerType]; + switch(m_State) + { + case OBJECTIVESTATE_NEUTRAL: + field = HP_MAP_N[m_TowerType]; + break; + case OBJECTIVESTATE_ALLIANCE: + field = HP_MAP_A[m_TowerType]; + artkit = 2; + artkit2 = HP_TowerArtKit_A[m_TowerType]; + if (((OutdoorPvPHP*)m_PvP)->m_AllianceTowersControlled<3) + ((OutdoorPvPHP*)m_PvP)->m_AllianceTowersControlled++; + sWorld.SendZoneText(OutdoorPvPHPBuffZones[0],objmgr.GetTrinityStringForDBCLocale(HP_LANG_CAPTURE_A[m_TowerType])); + break; + case OBJECTIVESTATE_HORDE: + field = HP_MAP_H[m_TowerType]; + artkit = 1; + artkit2 = HP_TowerArtKit_H[m_TowerType]; + if (((OutdoorPvPHP*)m_PvP)->m_HordeTowersControlled<3) + ((OutdoorPvPHP*)m_PvP)->m_HordeTowersControlled++; + sWorld.SendZoneText(OutdoorPvPHPBuffZones[0],objmgr.GetTrinityStringForDBCLocale(HP_LANG_CAPTURE_H[m_TowerType])); + break; + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + field = HP_MAP_N[m_TowerType]; + break; + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + field = HP_MAP_N[m_TowerType]; + break; + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + field = HP_MAP_A[m_TowerType]; + artkit = 2; + artkit2 = HP_TowerArtKit_A[m_TowerType]; + break; + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + field = HP_MAP_H[m_TowerType]; + artkit = 1; + artkit2 = HP_TowerArtKit_H[m_TowerType]; + break; + } + + GameObject* flag = HashMapHolder::Find(m_capturePointGUID); + GameObject* flag2 = HashMapHolder::Find(m_Objects[m_TowerType]); + if (flag) + { + flag->SetGoArtKit(artkit); + } + if (flag2) + { + flag2->SetGoArtKit(artkit2); + } + + // send world state update + if (field) + m_PvP->SendUpdateWorldState(field, 1); + + // complete quest objective + if (m_State == OBJECTIVESTATE_ALLIANCE || m_State == OBJECTIVESTATE_HORDE) + SendObjectiveComplete(HP_CREDITMARKER[m_TowerType], 0); +} + +void OPvPCapturePointHP::SendChangePhase() +{ + SendUpdateWorldState(HP_UI_TOWER_SLIDER_N, m_neutralValuePct); + // send these updates to only the ones in this objective + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + SendUpdateWorldState(HP_UI_TOWER_SLIDER_POS, phase); + // send this too, sometimes the slider disappears, dunno why :( + SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY, 1); +} + +void OPvPCapturePointHP::FillInitialWorldStates(WorldPacket &data) +{ + switch(m_State) + { + case OBJECTIVESTATE_ALLIANCE: + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + data << uint32(HP_MAP_N[m_TowerType]) << uint32(0); + data << uint32(HP_MAP_A[m_TowerType]) << uint32(1); + data << uint32(HP_MAP_H[m_TowerType]) << uint32(0); + break; + case OBJECTIVESTATE_HORDE: + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + data << uint32(HP_MAP_N[m_TowerType]) << uint32(0); + data << uint32(HP_MAP_A[m_TowerType]) << uint32(0); + data << uint32(HP_MAP_H[m_TowerType]) << uint32(1); + break; + case OBJECTIVESTATE_NEUTRAL: + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + default: + data << uint32(HP_MAP_N[m_TowerType]) << uint32(1); + data << uint32(HP_MAP_A[m_TowerType]) << uint32(0); + data << uint32(HP_MAP_H[m_TowerType]) << uint32(0); + break; + } +} + +bool OPvPCapturePointHP::HandlePlayerEnter(Player *plr) +{ + if (OPvPCapturePoint::HandlePlayerEnter(plr)) + { + plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY, 1); + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_POS, phase); + plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_N, m_neutralValuePct); + return true; + } + return false; +} + +void OPvPCapturePointHP::HandlePlayerLeave(Player *plr) +{ + plr->SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY, 0); + OPvPCapturePoint::HandlePlayerLeave(plr); +} + +void OutdoorPvPHP::HandleKillImpl(Player *plr, Unit * killed) +{ + if (killed->GetTypeId() != TYPEID_PLAYER) + return; + + if (plr->GetTeam() == ALLIANCE && killed->ToPlayer()->GetTeam() != ALLIANCE) + plr->CastSpell(plr,AlliancePlayerKillReward,true); + else if (plr->GetTeam() == HORDE && killed->ToPlayer()->GetTeam() != HORDE) + plr->CastSpell(plr,HordePlayerKillReward,true); +} diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.h b/src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.h new file mode 100644 index 00000000000..e23eb1f9369 --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPHP.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OUTDOOR_PVP_HP_ +#define OUTDOOR_PVP_HP_ + +#include "OutdoorPvPImpl.h" + +#define OutdoorPvPHPBuffZonesNum 6 + // HP, citadel, ramparts, blood furnace, shattered halls, mag's lair +const uint32 OutdoorPvPHPBuffZones[OutdoorPvPHPBuffZonesNum] = { 3483, 3563, 3562, 3713, 3714, 3836 }; + +enum OutdoorPvPHPSpells +{ + AlliancePlayerKillReward = 32155, + HordePlayerKillReward = 32158, + AllianceBuff = 32071, + HordeBuff = 32049 +}; + +enum OutdoorPvPHPTowerType{ + HP_TOWER_BROKEN_HILL = 0, + HP_TOWER_OVERLOOK = 1, + HP_TOWER_STADIUM = 2, + HP_TOWER_NUM = 3 +}; + +const uint32 HP_CREDITMARKER[HP_TOWER_NUM] = {19032,19028,19029}; + +const uint32 HP_CapturePointEvent_Enter[HP_TOWER_NUM] = {11404,11396,11388}; + +const uint32 HP_CapturePointEvent_Leave[HP_TOWER_NUM] = {11403,11395,11387}; + +enum OutdoorPvPHPWorldStates{ + HP_UI_TOWER_DISPLAY_A = 0x9ba, + HP_UI_TOWER_DISPLAY_H = 0x9b9, + + HP_UI_TOWER_COUNT_H = 0x9ae, + HP_UI_TOWER_COUNT_A = 0x9ac, + + HP_UI_TOWER_SLIDER_N = 2475, + HP_UI_TOWER_SLIDER_POS = 2474, + HP_UI_TOWER_SLIDER_DISPLAY = 2473 +}; + +const uint32 HP_MAP_N[HP_TOWER_NUM] = {0x9b5,0x9b2,0x9a8}; + +const uint32 HP_MAP_A[HP_TOWER_NUM] = {0x9b3,0x9b0,0x9a7}; + +const uint32 HP_MAP_H[HP_TOWER_NUM] = {0x9b4,0x9b1,0x9a6}; + +const uint32 HP_TowerArtKit_A[HP_TOWER_NUM] = {65,62,67}; + +const uint32 HP_TowerArtKit_H[HP_TOWER_NUM] = {64,61,68}; + +const uint32 HP_TowerArtKit_N[HP_TOWER_NUM] = {66,63,69}; + +const go_type HPCapturePoints[HP_TOWER_NUM] = { + {182175,530,-471.462,3451.09,34.6432,0.174533,0,0,0.087156,0.996195}, // 0 - Broken Hill + {182174,530,-184.889,3476.93,38.205,-0.017453,0,0,0.008727,-0.999962}, // 1 - Overlook + {182173,530,-290.016,3702.42,56.6729,0.034907,0,0,0.017452,0.999848} // 2 - Stadium +}; + +const go_type HPTowerFlags[HP_TOWER_NUM] = { + {183514,530,-467.078,3528.17,64.7121,3.14159,0,0,1,0}, // 0 broken hill + {182525,530,-187.887,3459.38,60.0403,-3.12414,0,0,0.999962,-0.008727}, // 1 overlook + {183515,530,-289.610,3696.83,75.9447,3.12414,0,0,0.999962,0.008727} // 2 stadium +}; + +class OPvPCapturePointHP : public OPvPCapturePoint +{ +public: + OPvPCapturePointHP(OutdoorPvP * pvp, OutdoorPvPHPTowerType type); + void ChangeState(); + void SendChangePhase(); + void FillInitialWorldStates(WorldPacket & data); + // used when player is activated/inactivated in the area + bool HandlePlayerEnter(Player * plr); + void HandlePlayerLeave(Player * plr); +private: + OutdoorPvPHPTowerType m_TowerType; +}; + +class OutdoorPvPHP : public OutdoorPvP +{ +friend class OPvPCapturePointHP; +public: + OutdoorPvPHP(); + bool SetupOutdoorPvP(); + void HandlePlayerEnterZone(Player *plr, uint32 zone); + void HandlePlayerLeaveZone(Player *plr, uint32 zone); + bool Update(uint32 diff); + void FillInitialWorldStates(WorldPacket &data); + void SendRemoveWorldStates(Player * plr); + void HandleKillImpl(Player * plr, Unit * killed); +private: + // how many towers are controlled + uint32 m_AllianceTowersControlled; + uint32 m_HordeTowersControlled; +}; + +#endif + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.cpp b/src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.cpp new file mode 100644 index 00000000000..2360c1e0fb0 --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.cpp @@ -0,0 +1,664 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "OutdoorPvPNA.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "OutdoorPvPMgr.h" +#include "WorldPacket.h" +#include "Language.h" +#include "World.h" + +OutdoorPvPNA::OutdoorPvPNA() +{ + m_TypeId = OUTDOOR_PVP_NA; +} + +void OutdoorPvPNA::HandleKillImpl(Player *plr, Unit * killed) +{ + if (killed->GetTypeId() == TYPEID_PLAYER && plr->GetTeam() != killed->ToPlayer()->GetTeam()) + { + plr->KilledMonsterCredit(NA_CREDIT_MARKER,0); // 0 guid, btw it isn't even used in killedmonster function :S + if (plr->GetTeam() == ALLIANCE) + plr->CastSpell(plr,NA_KILL_TOKEN_ALLIANCE,true); + else + plr->CastSpell(plr,NA_KILL_TOKEN_HORDE,true); + } +} + +uint32 OPvPCapturePointNA::GetAliveGuardsCount() +{ + uint32 cnt = 0; + for (std::map::iterator itr = m_Creatures.begin(); itr != m_Creatures.end(); ++itr) + { + switch(itr->first) + { + case NA_NPC_GUARD_01: + case NA_NPC_GUARD_02: + case NA_NPC_GUARD_03: + case NA_NPC_GUARD_04: + case NA_NPC_GUARD_05: + case NA_NPC_GUARD_06: + case NA_NPC_GUARD_07: + case NA_NPC_GUARD_08: + case NA_NPC_GUARD_09: + case NA_NPC_GUARD_10: + case NA_NPC_GUARD_11: + case NA_NPC_GUARD_12: + case NA_NPC_GUARD_13: + case NA_NPC_GUARD_14: + case NA_NPC_GUARD_15: + { + if (Creature * cr = HashMapHolder::Find(itr->second)) + { + if (cr->isAlive()) + ++cnt; + } + else if (CreatureData const * cd = objmgr.GetCreatureData(GUID_LOPART(itr->second))) + { + if (!cd->is_dead) + ++cnt; + } + } + break; + default: + break; + } + } + return cnt; +} + +void OPvPCapturePointNA::SpawnNPCsForTeam(uint32 team) +{ + const creature_type * creatures = NULL; + if (team == ALLIANCE) + creatures=AllianceControlNPCs; + else if (team == HORDE) + creatures=HordeControlNPCs; + else + return; + for (int i = 0; i < NA_CONTROL_NPC_NUM; ++i) + AddCreature(i,creatures[i].entry,creatures[i].teamval,creatures[i].map,creatures[i].x,creatures[i].y,creatures[i].z,creatures[i].o,1000000); +} + +void OPvPCapturePointNA::DeSpawnNPCs() +{ + for (int i = 0; i < NA_CONTROL_NPC_NUM; ++i) + DelCreature(i); +} + +void OPvPCapturePointNA::SpawnGOsForTeam(uint32 team) +{ + const go_type * gos = NULL; + if (team == ALLIANCE) + gos=AllianceControlGOs; + else if (team == HORDE) + gos=HordeControlGOs; + else + return; + for (int i = 0; i < NA_CONTROL_GO_NUM; ++i) + { + if (i == NA_ROOST_S || + i == NA_ROOST_W || + i == NA_ROOST_N || + i == NA_ROOST_E || + i == NA_BOMB_WAGON_S || + i == NA_BOMB_WAGON_W || + i == NA_BOMB_WAGON_N || + i == NA_BOMB_WAGON_E) + continue; // roosts and bomb wagons are spawned when someone uses the matching destroyed roost + AddObject(i,gos[i].entry,gos[i].map,gos[i].x,gos[i].y,gos[i].z,gos[i].o,gos[i].rot0,gos[i].rot1,gos[i].rot2,gos[i].rot3); + } +} + +void OPvPCapturePointNA::DeSpawnGOs() +{ + for (int i = 0; i < NA_CONTROL_GO_NUM; ++i) + { + DelObject(i); + } +} + +void OPvPCapturePointNA::FactionTakeOver(uint32 team) +{ + if (m_ControllingFaction) + objmgr.RemoveGraveYardLink(NA_HALAA_GRAVEYARD,NA_HALAA_GRAVEYARD_ZONE,m_ControllingFaction,false); + if (m_ControllingFaction == ALLIANCE) + sWorld.SendZoneText(NA_HALAA_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_NA_LOOSE_A)); + else if (m_ControllingFaction == HORDE) + sWorld.SendZoneText(NA_HALAA_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_NA_LOOSE_H)); + + m_ControllingFaction = team; + if (m_ControllingFaction) + objmgr.AddGraveYardLink(NA_HALAA_GRAVEYARD,NA_HALAA_GRAVEYARD_ZONE,m_ControllingFaction,false); + DeSpawnGOs(); + DeSpawnNPCs(); + SpawnGOsForTeam(team); + SpawnNPCsForTeam(team); + m_GuardsAlive = NA_GUARDS_MAX; + m_capturable = false; + this->UpdateHalaaWorldState(); + if (team == ALLIANCE) + { + m_WyvernStateSouth = WYVERN_NEU_HORDE; + m_WyvernStateNorth = WYVERN_NEU_HORDE; + m_WyvernStateEast = WYVERN_NEU_HORDE; + m_WyvernStateWest = WYVERN_NEU_HORDE; + m_PvP->TeamApplyBuff(TEAM_ALLIANCE, NA_CAPTURE_BUFF); + m_PvP->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW, 0); + m_PvP->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW, 1); + m_PvP->SendUpdateWorldState(NA_UI_GUARDS_LEFT, m_GuardsAlive); + sWorld.SendZoneText(NA_HALAA_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_NA_CAPTURE_A)); + } + else + { + m_WyvernStateSouth = WYVERN_NEU_ALLIANCE; + m_WyvernStateNorth = WYVERN_NEU_ALLIANCE; + m_WyvernStateEast = WYVERN_NEU_ALLIANCE; + m_WyvernStateWest = WYVERN_NEU_ALLIANCE; + m_PvP->TeamApplyBuff(TEAM_HORDE, NA_CAPTURE_BUFF); + m_PvP->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW, 1); + m_PvP->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW, 0); + m_PvP->SendUpdateWorldState(NA_UI_GUARDS_LEFT, m_GuardsAlive); + sWorld.SendZoneText(NA_HALAA_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_NA_CAPTURE_H)); + } + UpdateWyvernRoostWorldState(NA_ROOST_S); + UpdateWyvernRoostWorldState(NA_ROOST_N); + UpdateWyvernRoostWorldState(NA_ROOST_W); + UpdateWyvernRoostWorldState(NA_ROOST_E); +} + +bool OPvPCapturePointNA::HandlePlayerEnter(Player *plr) +{ + if (OPvPCapturePoint::HandlePlayerEnter(plr)) + { + plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_DISPLAY, 1); + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_POS, phase); + plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_N, m_neutralValuePct); + return true; + } + return false; +} + +void OPvPCapturePointNA::HandlePlayerLeave(Player *plr) +{ + plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_DISPLAY, 0); + OPvPCapturePoint::HandlePlayerLeave(plr); +} + +OPvPCapturePointNA::OPvPCapturePointNA(OutdoorPvP *pvp) : +OPvPCapturePoint(pvp), m_capturable(true), m_GuardsAlive(0), m_ControllingFaction(0), +m_HalaaState(HALAA_N), m_WyvernStateSouth(0), m_WyvernStateNorth(0), m_WyvernStateWest(0), +m_WyvernStateEast(0), m_RespawnTimer(NA_RESPAWN_TIME), m_GuardCheckTimer(NA_GUARD_CHECK_TIME) +{ + SetCapturePointData(182210,530,-1572.57,7945.3,-22.475,2.05949,0,0,0.857167,0.515038); +} + +bool OutdoorPvPNA::SetupOutdoorPvP() +{ +// m_TypeId = OUTDOOR_PVP_NA; _MUST_ be set in ctor, because of spawns cleanup + // add the zones affected by the pvp buff + RegisterZone(NA_BUFF_ZONE); + + // halaa + m_obj = new OPvPCapturePointNA(this); + if (!m_obj) + return false; + AddCapturePoint(m_obj); + + return true; +} + +void OutdoorPvPNA::HandlePlayerEnterZone(Player * plr, uint32 zone) +{ + // add buffs + if (plr->GetTeam() == m_obj->m_ControllingFaction) + plr->CastSpell(plr,NA_CAPTURE_BUFF,true); + OutdoorPvP::HandlePlayerEnterZone(plr,zone); +} + +void OutdoorPvPNA::HandlePlayerLeaveZone(Player * plr, uint32 zone) +{ + // remove buffs + plr->RemoveAurasDueToSpell(NA_CAPTURE_BUFF); + OutdoorPvP::HandlePlayerLeaveZone(plr, zone); +} + +void OutdoorPvPNA::FillInitialWorldStates(WorldPacket &data) +{ + m_obj->FillInitialWorldStates(data); +} + +void OPvPCapturePointNA::FillInitialWorldStates(WorldPacket &data) +{ + if (m_ControllingFaction == ALLIANCE) + { + data << NA_UI_HORDE_GUARDS_SHOW << uint32(0); + data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(1); + } + else if (m_ControllingFaction == HORDE) + { + data << NA_UI_HORDE_GUARDS_SHOW << uint32(1); + data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(0); + } + else + { + data << NA_UI_HORDE_GUARDS_SHOW << uint32(0); + data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(0); + } + + data << NA_UI_GUARDS_MAX << NA_GUARDS_MAX; + data << NA_UI_GUARDS_LEFT << uint32(m_GuardsAlive); + + data << NA_UI_TOWER_SLIDER_DISPLAY << uint32(0); + data << NA_UI_TOWER_SLIDER_POS << uint32(50); + data << NA_UI_TOWER_SLIDER_N << uint32(100); + + data << NA_MAP_WYVERN_NORTH_NEU_H << uint32(bool(m_WyvernStateNorth & WYVERN_NEU_HORDE)); + data << NA_MAP_WYVERN_NORTH_NEU_A << uint32(bool(m_WyvernStateNorth & WYVERN_NEU_ALLIANCE)); + data << NA_MAP_WYVERN_NORTH_H << uint32(bool(m_WyvernStateNorth & WYVERN_HORDE)); + data << NA_MAP_WYVERN_NORTH_A << uint32(bool(m_WyvernStateNorth & WYVERN_ALLIANCE)); + + data << NA_MAP_WYVERN_SOUTH_NEU_H << uint32(bool(m_WyvernStateSouth & WYVERN_NEU_HORDE)); + data << NA_MAP_WYVERN_SOUTH_NEU_A << uint32(bool(m_WyvernStateSouth & WYVERN_NEU_ALLIANCE)); + data << NA_MAP_WYVERN_SOUTH_H << uint32(bool(m_WyvernStateSouth & WYVERN_HORDE)); + data << NA_MAP_WYVERN_SOUTH_A << uint32(bool(m_WyvernStateSouth & WYVERN_ALLIANCE)); + + data << NA_MAP_WYVERN_WEST_NEU_H << uint32(bool(m_WyvernStateWest & WYVERN_NEU_HORDE)); + data << NA_MAP_WYVERN_WEST_NEU_A << uint32(bool(m_WyvernStateWest & WYVERN_NEU_ALLIANCE)); + data << NA_MAP_WYVERN_WEST_H << uint32(bool(m_WyvernStateWest & WYVERN_HORDE)); + data << NA_MAP_WYVERN_WEST_A << uint32(bool(m_WyvernStateWest & WYVERN_ALLIANCE)); + + data << NA_MAP_WYVERN_EAST_NEU_H << uint32(bool(m_WyvernStateEast & WYVERN_NEU_HORDE)); + data << NA_MAP_WYVERN_EAST_NEU_A << uint32(bool(m_WyvernStateEast & WYVERN_NEU_ALLIANCE)); + data << NA_MAP_WYVERN_EAST_H << uint32(bool(m_WyvernStateEast & WYVERN_HORDE)); + data << NA_MAP_WYVERN_EAST_A << uint32(bool(m_WyvernStateEast & WYVERN_ALLIANCE)); + + data << NA_MAP_HALAA_NEUTRAL << uint32(bool(m_HalaaState & HALAA_N)); + data << NA_MAP_HALAA_NEU_A << uint32(bool(m_HalaaState & HALAA_N_A)); + data << NA_MAP_HALAA_NEU_H << uint32(bool(m_HalaaState & HALAA_N_H)); + data << NA_MAP_HALAA_HORDE << uint32(bool(m_HalaaState & HALAA_H)); + data << NA_MAP_HALAA_ALLIANCE << uint32(bool(m_HalaaState & HALAA_A)); +} + +void OutdoorPvPNA::SendRemoveWorldStates(Player *plr) +{ + plr->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW,0); + plr->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW,0); + plr->SendUpdateWorldState(NA_UI_GUARDS_MAX,0); + plr->SendUpdateWorldState(NA_UI_GUARDS_LEFT,0); + plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_DISPLAY,0); + plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_POS,0); + plr->SendUpdateWorldState(NA_UI_TOWER_SLIDER_N,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_NEU_H,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_NEU_A,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_H,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_A,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_NEU_H,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_NEU_A,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_H,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_A,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_WEST_NEU_H,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_WEST_NEU_A,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_WEST_H,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_WEST_A,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_EAST_NEU_H,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_EAST_NEU_A,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_EAST_H,0); + plr->SendUpdateWorldState(NA_MAP_WYVERN_EAST_A,0); + plr->SendUpdateWorldState(NA_MAP_HALAA_NEUTRAL,0); + plr->SendUpdateWorldState(NA_MAP_HALAA_NEU_A,0); + plr->SendUpdateWorldState(NA_MAP_HALAA_NEU_H,0); + plr->SendUpdateWorldState(NA_MAP_HALAA_HORDE,0); + plr->SendUpdateWorldState(NA_MAP_HALAA_ALLIANCE,0); +} + +bool OutdoorPvPNA::Update(uint32 diff) +{ + return m_obj->Update(diff); +} + +bool OPvPCapturePointNA::HandleCustomSpell(Player * plr, uint32 spellId, GameObject * /*go*/) +{ + std::vector nodes; + nodes.resize(2); + bool retval = false; + switch(spellId) + { + case NA_SPELL_FLY_NORTH: + nodes[0] = FlightPathStartNodes[NA_ROOST_N]; + nodes[1] = FlightPathEndNodes[NA_ROOST_N]; + plr->ActivateTaxiPathTo(nodes); + plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + plr->UpdatePvP(true,true); + retval = true; + break; + case NA_SPELL_FLY_SOUTH: + nodes[0] = FlightPathStartNodes[NA_ROOST_S]; + nodes[1] = FlightPathEndNodes[NA_ROOST_S]; + plr->ActivateTaxiPathTo(nodes); + plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + plr->UpdatePvP(true,true); + retval = true; + break; + case NA_SPELL_FLY_WEST: + nodes[0] = FlightPathStartNodes[NA_ROOST_W]; + nodes[1] = FlightPathEndNodes[NA_ROOST_W]; + plr->ActivateTaxiPathTo(nodes); + plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + plr->UpdatePvP(true,true); + retval = true; + break; + case NA_SPELL_FLY_EAST: + nodes[0] = FlightPathStartNodes[NA_ROOST_E]; + nodes[1] = FlightPathEndNodes[NA_ROOST_E]; + plr->ActivateTaxiPathTo(nodes); + plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + plr->UpdatePvP(true,true); + retval = true; + break; + default: + break; + } + + if (retval) + { + //Adding items + uint32 noSpaceForCount = 0; + + // check space and find places + ItemPosCountVec dest; + + int32 count = 10; + uint32 itemid = 24538; + // bomb id count + uint8 msg = plr->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemid, count, &noSpaceForCount); + if (msg != EQUIP_ERR_OK) // convert to possible store amount + count -= noSpaceForCount; + + if (count == 0 || dest.empty()) // can't add any + { + return true; + } + + Item* item = plr->StoreNewItem(dest, itemid, true); + + if (count > 0 && item) + { + plr->SendNewItem(item,count,true,false); + } + + return true; + } + return false; +} + +int32 OPvPCapturePointNA::HandleOpenGo(Player *plr, uint64 guid) +{ + uint32 retval = OPvPCapturePoint::HandleOpenGo(plr, guid); + if (retval >= 0) + { + const go_type * gos = NULL; + if (m_ControllingFaction == ALLIANCE) + gos=AllianceControlGOs; + else if (m_ControllingFaction == HORDE) + gos=HordeControlGOs; + else + return -1; + + int32 del = -1; + int32 del2 = -1; + int32 add = -1; + int32 add2 = -1; + + switch(retval) + { + case NA_DESTROYED_ROOST_S: + del = NA_DESTROYED_ROOST_S; + add = NA_ROOST_S; + add2 = NA_BOMB_WAGON_S; + if (m_ControllingFaction == HORDE) + m_WyvernStateSouth = WYVERN_ALLIANCE; + else + m_WyvernStateSouth = WYVERN_HORDE; + UpdateWyvernRoostWorldState(NA_ROOST_S); + break; + case NA_DESTROYED_ROOST_N: + del = NA_DESTROYED_ROOST_N; + add = NA_ROOST_N; + add2 = NA_BOMB_WAGON_N; + if (m_ControllingFaction == HORDE) + m_WyvernStateNorth = WYVERN_ALLIANCE; + else + m_WyvernStateNorth = WYVERN_HORDE; + UpdateWyvernRoostWorldState(NA_ROOST_N); + break; + case NA_DESTROYED_ROOST_W: + del = NA_DESTROYED_ROOST_W; + add = NA_ROOST_W; + add2 = NA_BOMB_WAGON_W; + if (m_ControllingFaction == HORDE) + m_WyvernStateWest = WYVERN_ALLIANCE; + else + m_WyvernStateWest = WYVERN_HORDE; + UpdateWyvernRoostWorldState(NA_ROOST_W); + break; + case NA_DESTROYED_ROOST_E: + del = NA_DESTROYED_ROOST_E; + add = NA_ROOST_E; + add2 = NA_BOMB_WAGON_E; + if (m_ControllingFaction == HORDE) + m_WyvernStateEast = WYVERN_ALLIANCE; + else + m_WyvernStateEast = WYVERN_HORDE; + UpdateWyvernRoostWorldState(NA_ROOST_E); + break; + case NA_BOMB_WAGON_S: + del = NA_BOMB_WAGON_S; + del2 = NA_ROOST_S; + add = NA_DESTROYED_ROOST_S; + if (m_ControllingFaction == HORDE) + m_WyvernStateSouth = WYVERN_NEU_ALLIANCE; + else + m_WyvernStateSouth = WYVERN_NEU_HORDE; + UpdateWyvernRoostWorldState(NA_ROOST_S); + break; + case NA_BOMB_WAGON_N: + del = NA_BOMB_WAGON_N; + del2 = NA_ROOST_N; + add = NA_DESTROYED_ROOST_N; + if (m_ControllingFaction == HORDE) + m_WyvernStateNorth = WYVERN_NEU_ALLIANCE; + else + m_WyvernStateNorth = WYVERN_NEU_HORDE; + UpdateWyvernRoostWorldState(NA_ROOST_N); + break; + case NA_BOMB_WAGON_W: + del = NA_BOMB_WAGON_W; + del2 = NA_ROOST_W; + add = NA_DESTROYED_ROOST_W; + if (m_ControllingFaction == HORDE) + m_WyvernStateWest = WYVERN_NEU_ALLIANCE; + else + m_WyvernStateWest = WYVERN_NEU_HORDE; + UpdateWyvernRoostWorldState(NA_ROOST_W); + break; + case NA_BOMB_WAGON_E: + del = NA_BOMB_WAGON_E; + del2 = NA_ROOST_E; + add = NA_DESTROYED_ROOST_E; + if (m_ControllingFaction == HORDE) + m_WyvernStateEast = WYVERN_NEU_ALLIANCE; + else + m_WyvernStateEast = WYVERN_NEU_HORDE; + UpdateWyvernRoostWorldState(NA_ROOST_E); + break; + default: + return -1; + break; + } + + if (del>-1) + DelObject(del); + + if (del2>-1) + DelObject(del2); + + if (add>-1) + AddObject(add,gos[add].entry,gos[add].map,gos[add].x,gos[add].y,gos[add].z,gos[add].o,gos[add].rot0,gos[add].rot1,gos[add].rot2,gos[add].rot3); + + if (add2>-1) + AddObject(add2,gos[add2].entry,gos[add2].map,gos[add2].x,gos[add2].y,gos[add2].z,gos[add2].o,gos[add2].rot0,gos[add2].rot1,gos[add2].rot2,gos[add2].rot3); + + return retval; + } + return -1; +} + +bool OPvPCapturePointNA::Update(uint32 diff) +{ + // let the controlling faction advance in phase + bool capturable = false; + if (m_ControllingFaction == ALLIANCE && m_activePlayers[0].size() > m_activePlayers[1].size()) + capturable = true; + else if (m_ControllingFaction == HORDE && m_activePlayers[0].size() < m_activePlayers[1].size()) + capturable = true; + + if (m_GuardCheckTimer < diff) + { + m_GuardCheckTimer = NA_GUARD_CHECK_TIME; + uint32 cnt = GetAliveGuardsCount(); + if (cnt != m_GuardsAlive) + { + m_GuardsAlive = cnt; + if (m_GuardsAlive == 0) + m_capturable = true; + // update the guard count for the players in zone + m_PvP->SendUpdateWorldState(NA_UI_GUARDS_LEFT,m_GuardsAlive); + } + } else m_GuardCheckTimer -= diff; + + if (m_capturable || capturable) + { + if (m_RespawnTimer < diff) + { + // if the guards have been killed, then the challenger has one hour to take over halaa. + // in case they fail to do it, the guards are respawned, and they have to start again. + if (m_ControllingFaction) + FactionTakeOver(m_ControllingFaction); + m_RespawnTimer = NA_RESPAWN_TIME; + } else m_RespawnTimer -= diff; + + return OPvPCapturePoint::Update(diff); + } + return false; +} + +void OPvPCapturePointNA::ChangeState() +{ + uint32 artkit = 21; + switch(m_State) + { + case OBJECTIVESTATE_NEUTRAL: + m_HalaaState = HALAA_N; + break; + case OBJECTIVESTATE_ALLIANCE: + m_HalaaState = HALAA_A; + FactionTakeOver(ALLIANCE); + artkit = 2; + break; + case OBJECTIVESTATE_HORDE: + m_HalaaState = HALAA_H; + FactionTakeOver(HORDE); + artkit = 1; + break; + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + m_HalaaState = HALAA_N_A; + break; + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + m_HalaaState = HALAA_N_H; + break; + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + m_HalaaState = HALAA_N_A; + artkit = 2; + break; + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + m_HalaaState = HALAA_N_H; + artkit = 1; + break; + } + + GameObject* flag = HashMapHolder::Find(m_capturePointGUID); + if (flag) + { + flag->SetGoArtKit(artkit); + } + + UpdateHalaaWorldState(); +} + +void OPvPCapturePointNA::SendChangePhase() +{ + // send this too, sometimes the slider disappears, dunno why :( + SendUpdateWorldState(NA_UI_TOWER_SLIDER_DISPLAY, 1); + // send these updates to only the ones in this objective + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + SendUpdateWorldState(NA_UI_TOWER_SLIDER_POS, phase); + SendUpdateWorldState(NA_UI_TOWER_SLIDER_N, m_neutralValuePct); +} + +void OPvPCapturePointNA::UpdateHalaaWorldState() +{ + m_PvP->SendUpdateWorldState(NA_MAP_HALAA_NEUTRAL ,uint32(bool(m_HalaaState & HALAA_N))); + m_PvP->SendUpdateWorldState(NA_MAP_HALAA_NEU_A ,uint32(bool(m_HalaaState & HALAA_N_A))); + m_PvP->SendUpdateWorldState(NA_MAP_HALAA_NEU_H ,uint32(bool(m_HalaaState & HALAA_N_H))); + m_PvP->SendUpdateWorldState(NA_MAP_HALAA_HORDE ,uint32(bool(m_HalaaState & HALAA_H))); + m_PvP->SendUpdateWorldState(NA_MAP_HALAA_ALLIANCE ,uint32(bool(m_HalaaState & HALAA_A))); +} + +void OPvPCapturePointNA::UpdateWyvernRoostWorldState(uint32 roost) +{ + switch(roost) + { + case NA_ROOST_S: + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_NEU_H,uint32(bool(m_WyvernStateSouth & WYVERN_NEU_HORDE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_NEU_A,uint32(bool(m_WyvernStateSouth & WYVERN_NEU_ALLIANCE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_H,uint32(bool(m_WyvernStateSouth & WYVERN_HORDE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_SOUTH_A,uint32(bool(m_WyvernStateSouth & WYVERN_ALLIANCE))); + break; + case NA_ROOST_N: + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_NEU_H,uint32(bool(m_WyvernStateNorth & WYVERN_NEU_HORDE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_NEU_A,uint32(bool(m_WyvernStateNorth & WYVERN_NEU_ALLIANCE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_H,uint32(bool(m_WyvernStateNorth & WYVERN_HORDE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_NORTH_A,uint32(bool(m_WyvernStateNorth & WYVERN_ALLIANCE))); + break; + case NA_ROOST_W: + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_WEST_NEU_H,uint32(bool(m_WyvernStateWest & WYVERN_NEU_HORDE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_WEST_NEU_A,uint32(bool(m_WyvernStateWest & WYVERN_NEU_ALLIANCE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_WEST_H,uint32(bool(m_WyvernStateWest & WYVERN_HORDE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_WEST_A,uint32(bool(m_WyvernStateWest & WYVERN_ALLIANCE))); + break; + case NA_ROOST_E: + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_EAST_NEU_H,uint32(bool(m_WyvernStateEast & WYVERN_NEU_HORDE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_EAST_NEU_A,uint32(bool(m_WyvernStateEast & WYVERN_NEU_ALLIANCE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_EAST_H,uint32(bool(m_WyvernStateEast & WYVERN_HORDE))); + m_PvP->SendUpdateWorldState(NA_MAP_WYVERN_EAST_A,uint32(bool(m_WyvernStateEast & WYVERN_ALLIANCE))); + break; + } +} diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.h b/src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.h new file mode 100644 index 00000000000..124f51e8040 --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPNA.h @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OUTDOOR_PVP_NA_ +#define OUTDOOR_PVP_NA_ + +// TODO: "sometimes" set to neutral + +#include "OutdoorPvPImpl.h" +enum OutdoorPvPNASpells +{ + NA_KILL_TOKEN_ALLIANCE = 33005, + NA_KILL_TOKEN_HORDE = 33004, + NA_CAPTURE_BUFF = 33795 // strength of the halaani +}; +// kill credit for pks +const uint32 NA_CREDIT_MARKER = 24867; +const uint32 NA_GUARDS_MAX = 15; + +const uint32 NA_BUFF_ZONE = 3518; + +const uint32 NA_HALAA_GRAVEYARD = 993; + +const uint32 NA_HALAA_GRAVEYARD_ZONE = 3518; // need to add zone id, not area id + +const uint32 NA_RESPAWN_TIME = 3600000; // one hour to capture after defeating all guards + +const uint32 NA_GUARD_CHECK_TIME = 500; // every half second + +enum OutdoorPvPNAWorldStates{ + NA_UI_HORDE_GUARDS_SHOW = 2503, + NA_UI_ALLIANCE_GUARDS_SHOW = 2502, + NA_UI_GUARDS_MAX = 2493, + NA_UI_GUARDS_LEFT = 2491, + + NA_UI_TOWER_SLIDER_DISPLAY = 2495, + NA_UI_TOWER_SLIDER_POS = 2494, + NA_UI_TOWER_SLIDER_N = 2497, + + NA_MAP_WYVERN_NORTH_NEU_H = 2762, + NA_MAP_WYVERN_NORTH_NEU_A = 2662, + NA_MAP_WYVERN_NORTH_H = 2663, + NA_MAP_WYVERN_NORTH_A = 2664, + + NA_MAP_WYVERN_SOUTH_NEU_H = 2760, + NA_MAP_WYVERN_SOUTH_NEU_A = 2670, + NA_MAP_WYVERN_SOUTH_H = 2668, + NA_MAP_WYVERN_SOUTH_A = 2669, + + NA_MAP_WYVERN_WEST_NEU_H = 2761, + NA_MAP_WYVERN_WEST_NEU_A = 2667, + NA_MAP_WYVERN_WEST_H = 2665, + NA_MAP_WYVERN_WEST_A = 2666, + + NA_MAP_WYVERN_EAST_NEU_H = 2763, + NA_MAP_WYVERN_EAST_NEU_A = 2659, + NA_MAP_WYVERN_EAST_H = 2660, + NA_MAP_WYVERN_EAST_A = 2661, + + NA_MAP_HALAA_NEUTRAL = 2671, + NA_MAP_HALAA_NEU_A = 2676, + NA_MAP_HALAA_NEU_H = 2677, + NA_MAP_HALAA_HORDE = 2672, + NA_MAP_HALAA_ALLIANCE = 2673 +}; + +const uint32 FLIGHT_NODES_NUM = 4; + +// used to access the elements of Horde/AllyControlGOs +enum ControlGOTypes{ + NA_ROOST_S = 0, + NA_ROOST_W = 1, + NA_ROOST_N = 2, + NA_ROOST_E = 3, + + NA_BOMB_WAGON_S = 4, + NA_BOMB_WAGON_W = 5, + NA_BOMB_WAGON_N = 6, + NA_BOMB_WAGON_E = 7, + + NA_DESTROYED_ROOST_S = 8, + NA_DESTROYED_ROOST_W = 9, + NA_DESTROYED_ROOST_N = 10, + NA_DESTROYED_ROOST_E = 11, + + NA_CONTROL_GO_NUM = 12 +}; + +const uint32 FlightPathStartNodes[FLIGHT_NODES_NUM] = {103,105,107,109}; +const uint32 FlightPathEndNodes[FLIGHT_NODES_NUM] = {104,106,108,110}; + +enum FlightSpellsNA{ + NA_SPELL_FLY_SOUTH = 32059, + NA_SPELL_FLY_WEST = 32068, + NA_SPELL_FLY_NORTH = 32075, + NA_SPELL_FLY_EAST = 32081 +}; + +// spawned when the alliance is attacking, horde is in control +const go_type HordeControlGOs[NA_CONTROL_GO_NUM] = { + {182267,530,-1815.8,8036.51,-26.2354,-2.89725,0,0,0.992546,-0.121869}, //ALLY_ROOST_SOUTH + {182280,530,-1507.95,8132.1,-19.5585,-1.3439,0,0,0.622515,-0.782608}, //ALLY_ROOST_WEST + {182281,530,-1384.52,7779.33,-11.1663,-0.575959,0,0,0.284015,-0.95882}, //ALLY_ROOST_NORTH + {182282,530,-1650.11,7732.56,-15.4505,-2.80998,0,0,0.986286,-0.165048}, //ALLY_ROOST_EAST + + {182222,530,-1825.4022,8039.2602,-26.08,-2.89725,0,0,0.992546,-0.121869}, //HORDE_BOMB_WAGON_SOUTH + {182272,530,-1515.37,8136.91,-20.42,-1.3439,0,0,0.622515,-0.782608}, //HORDE_BOMB_WAGON_WEST + {182273,530,-1377.95,7773.44,-10.31,-0.575959,0,0,0.284015,-0.95882}, //HORDE_BOMB_WAGON_NORTH + {182274,530,-1659.87,7733.15,-15.75,-2.80998,0,0,0.986286,-0.165048}, //HORDE_BOMB_WAGON_EAST + + {182266,530,-1815.8,8036.51,-26.2354,-2.89725,0,0,0.992546,-0.121869}, //DESTROYED_ALLY_ROOST_SOUTH + {182275,530,-1507.95,8132.1,-19.5585,-1.3439,0,0,0.622515,-0.782608}, //DESTROYED_ALLY_ROOST_WEST + {182276,530,-1384.52,7779.33,-11.1663,-0.575959,0,0,0.284015,-0.95882}, //DESTROYED_ALLY_ROOST_NORTH + {182277,530,-1650.11,7732.56,-15.4505,-2.80998,0,0,0.986286,-0.165048} //DESTROYED_ALLY_ROOST_EAST +}; + +// spawned when the horde is attacking, alliance is in control +const go_type AllianceControlGOs[NA_CONTROL_GO_NUM] = { + {182301,530,-1815.8,8036.51,-26.2354,-2.89725,0,0,0.992546,-0.121869}, //HORDE_ROOST_SOUTH + {182302,530,-1507.95,8132.1,-19.5585,-1.3439,0,0,0.622515,-0.782608}, //HORDE_ROOST_WEST + {182303,530,-1384.52,7779.33,-11.1663,-0.575959,0,0,0.284015,-0.95882}, //HORDE_ROOST_NORTH + {182304,530,-1650.11,7732.56,-15.4505,-2.80998,0,0,0.986286,-0.165048}, //HORDE_ROOST_EAST + + {182305,530,-1825.4022,8039.2602,-26.08,-2.89725,0,0,0.992546,-0.121869}, //ALLY_BOMB_WAGON_SOUTH + {182306,530,-1515.37,8136.91,-20.42,-1.3439,0,0,0.622515,-0.782608}, //ALLY_BOMB_WAGON_WEST + {182307,530,-1377.95,7773.44,-10.31,-0.575959,0,0,0.284015,-0.95882}, //ALLY_BOMB_WAGON_NORTH + {182308,530,-1659.87,7733.15,-15.75,-2.80998,0,0,0.986286,-0.165048}, //ALLY_BOMB_WAGON_EAST + + {182297,530,-1815.8,8036.51,-26.2354,-2.89725,0,0,0.992546,-0.121869}, //DESTROYED_HORDE_ROOST_SOUTH + {182298,530,-1507.95,8132.1,-19.5585,-1.3439,0,0,0.622515,-0.782608}, //DESTROYED_HORDE_ROOST_WEST + {182299,530,-1384.52,7779.33,-11.1663,-0.575959,0,0,0.284015,-0.95882}, //DESTROYED_HORDE_ROOST_NORTH + {182300,530,-1650.11,7732.56,-15.4505,-2.80998,0,0,0.986286,-0.165048} //DESTROYED_HORDE_ROOST_EAST +}; + +enum ControlNPCTypes{ + NA_NPC_RESEARCHER = 0, + NA_NPC_QUARTERMASTER, + NA_NPC_BLADE_MERCHANT, + NA_NPC_FOOD_MERCHANT, + NA_NPC_AMMO, + + NA_NPC_GUARD_01, + NA_NPC_GUARD_02, + NA_NPC_GUARD_03, + NA_NPC_GUARD_04, + NA_NPC_GUARD_05, + NA_NPC_GUARD_06, + NA_NPC_GUARD_07, + NA_NPC_GUARD_08, + NA_NPC_GUARD_09, + NA_NPC_GUARD_10, + NA_NPC_GUARD_11, + NA_NPC_GUARD_12, + NA_NPC_GUARD_13, + NA_NPC_GUARD_14, + NA_NPC_GUARD_15, + + NA_CONTROL_NPC_NUM +}; + +const creature_type HordeControlNPCs[NA_CONTROL_NPC_NUM] = { + {18816,67,530,-1523.92,7951.76,-17.6942,3.51172}, + {18821,67,530,-1527.75,7952.46,-17.6948,3.99317}, + {21474,67,530,-1520.14,7927.11,-20.2527,3.39389}, + {21484,67,530,-1524.84,7930.34,-20.182,3.6405}, + {21483,67,530,-1570.01,7993.8,-22.4505,5.02655}, + {18192,67,530,-1654.06,8000.46,-26.59,3.37}, + {18192,67,530,-1487.18,7899.1,-19.53,0.954}, + {18192,67,530,-1480.88,7908.79,-19.19,4.485}, + {18192,67,530,-1540.56,7995.44,-20.45,0.947}, + {18192,67,530,-1546.95,8000.85,-20.72,6.035}, + {18192,67,530,-1595.31,7860.53,-21.51,3.747}, + {18192,67,530,-1642.31,7995.59,-25.8,3.317}, + {18192,67,530,-1545.46,7995.35,-20.63,1.094}, + {18192,67,530,-1487.58,7907.99,-19.27,5.567}, + {18192,67,530,-1651.54,7988.56,-26.5289,2.98451}, + {18192,67,530,-1602.46,7866.43,-22.1177,4.74729}, + {18192,67,530,-1591.22,7875.29,-22.3536,4.34587}, + {18192,67,530,-1550.6,7944.45,-21.63,3.559}, + {18192,67,530,-1545.57,7935.83,-21.13,3.448}, + {18192,67,530,-1550.86,7937.56,-21.7,3.801} +}; + +const creature_type AllianceControlNPCs[NA_CONTROL_NPC_NUM] = { + {18817,469,530,-1591.18,8020.39,-22.2042,4.59022}, + {18822,469,530,-1588.0,8019.0,-22.2042,4.06662}, + {21485,469,530,-1521.93,7927.37,-20.2299,3.24631}, + {21487,469,530,-1540.33,7971.95,-20.7186,3.07178}, + {21488,469,530,-1570.01,7993.8,-22.4505,5.02655}, + {18256,469,530,-1654.06,8000.46,-26.59,3.37}, + {18256,469,530,-1487.18,7899.1,-19.53,0.954}, + {18256,469,530,-1480.88,7908.79,-19.19,4.485}, + {18256,469,530,-1540.56,7995.44,-20.45,0.947}, + {18256,469,530,-1546.95,8000.85,-20.72,6.035}, + {18256,469,530,-1595.31,7860.53,-21.51,3.747}, + {18256,469,530,-1642.31,7995.59,-25.8,3.317}, + {18256,469,530,-1545.46,7995.35,-20.63,1.094}, + {18256,469,530,-1487.58,7907.99,-19.27,5.567}, + {18256,469,530,-1651.54,7988.56,-26.5289,2.98451}, + {18256,469,530,-1602.46,7866.43,-22.1177,4.74729}, + {18256,469,530,-1591.22,7875.29,-22.3536,4.34587}, + {18256,469,530,-1603.75,8000.36,-24.18,4.516}, + {18256,469,530,-1585.73,7994.68,-23.29,4.439}, + {18256,469,530,-1595.5,7991.27,-23.53,4.738} +}; + +enum WyvernStates{ + WYVERN_NEU_HORDE = 1, + WYVERN_NEU_ALLIANCE = 2, + WYVERN_HORDE = 4, + WYVERN_ALLIANCE = 8 +}; + +enum HalaaStates{ + HALAA_N = 1, + HALAA_N_A = 2, + HALAA_A = 4, + HALAA_N_H = 8, + HALAA_H = 16 +}; + +class Unit; +class Creature; +class OutdoorPvPNA; +class OPvPCapturePointNA : public OPvPCapturePoint +{ +friend class OutdoorPvPNA; +public: + OPvPCapturePointNA(OutdoorPvP * pvp); + bool Update(uint32 diff); + void ChangeState(); + void SendChangePhase(); + void FillInitialWorldStates(WorldPacket & data); + // used when player is activated/inactivated in the area + bool HandlePlayerEnter(Player * plr); + void HandlePlayerLeave(Player * plr); + bool HandleCustomSpell(Player *plr, uint32 spellId, GameObject * go); + int32 HandleOpenGo(Player *plr, uint64 guid); + uint32 GetAliveGuardsCount(); +protected: + // called when a faction takes control + void FactionTakeOver(uint32 team); + + void DeSpawnNPCs(); + void DeSpawnGOs(); + void SpawnNPCsForTeam(uint32 team); + void SpawnGOsForTeam(uint32 team); + + void UpdateWyvernRoostWorldState(uint32 roost); + void UpdateHalaaWorldState(); + +private: + bool m_capturable; + uint32 m_GuardsAlive; + uint32 m_ControllingFaction; + uint32 m_WyvernStateNorth; + uint32 m_WyvernStateSouth; + uint32 m_WyvernStateEast; + uint32 m_WyvernStateWest; + uint32 m_HalaaState; + uint32 m_RespawnTimer; + uint32 m_GuardCheckTimer; +}; + +class OutdoorPvPNA : public OutdoorPvP +{ +friend class OPvPCapturePointNA; +public: + OutdoorPvPNA(); + bool SetupOutdoorPvP(); + void HandlePlayerEnterZone(Player *plr, uint32 zone); + void HandlePlayerLeaveZone(Player *plr, uint32 zone); + bool Update(uint32 diff); + void FillInitialWorldStates(WorldPacket &data); + void SendRemoveWorldStates(Player * plr); + void HandleKillImpl(Player * plr, Unit * killed); +private: + OPvPCapturePointNA * m_obj; +}; + +#endif + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.cpp b/src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.cpp new file mode 100644 index 00000000000..408901f9d06 --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "OutdoorPvPSI.h" +#include "WorldPacket.h" +#include "Player.h" +#include "GameObject.h" +#include "MapManager.h" +#include "ObjectMgr.h" +#include "OutdoorPvPMgr.h" +#include "Language.h" +#include "World.h" + +OutdoorPvPSI::OutdoorPvPSI() +{ + m_TypeId = OUTDOOR_PVP_SI; + m_Gathered_A = 0; + m_Gathered_H = 0; + m_LastController = 0; +} + +void OutdoorPvPSI::FillInitialWorldStates(WorldPacket &data) +{ + data << SI_GATHERED_A << m_Gathered_A; + data << SI_GATHERED_H << m_Gathered_H; + data << SI_SILITHYST_MAX << SI_MAX_RESOURCES; +} + +void OutdoorPvPSI::SendRemoveWorldStates(Player *plr) +{ + plr->SendUpdateWorldState(SI_GATHERED_A,0); + plr->SendUpdateWorldState(SI_GATHERED_H,0); + plr->SendUpdateWorldState(SI_SILITHYST_MAX,0); +} + +void OutdoorPvPSI::UpdateWorldState() +{ + SendUpdateWorldState(SI_GATHERED_A,m_Gathered_A); + SendUpdateWorldState(SI_GATHERED_H,m_Gathered_H); + SendUpdateWorldState(SI_SILITHYST_MAX,SI_MAX_RESOURCES); +} + +bool OutdoorPvPSI::SetupOutdoorPvP() +{ + for (int i = 0; i < OutdoorPvPSIBuffZonesNum; ++i) + RegisterZone(OutdoorPvPSIBuffZones[i]); + return true; +} + +bool OutdoorPvPSI::Update(uint32 /*diff*/) +{ + return false; +} + +void OutdoorPvPSI::HandlePlayerEnterZone(Player * plr, uint32 zone) +{ + if (plr->GetTeam() == m_LastController) + plr->CastSpell(plr,SI_CENARION_FAVOR,true); + OutdoorPvP::HandlePlayerEnterZone(plr,zone); +} + +void OutdoorPvPSI::HandlePlayerLeaveZone(Player * plr, uint32 zone) +{ + // remove buffs + plr->RemoveAurasDueToSpell(SI_CENARION_FAVOR); + OutdoorPvP::HandlePlayerLeaveZone(plr, zone); +} + +bool OutdoorPvPSI::HandleAreaTrigger(Player *plr, uint32 trigger) +{ + switch(trigger) + { + case SI_AREATRIGGER_A: + if (plr->GetTeam() == ALLIANCE && plr->HasAura(SI_SILITHYST_FLAG)) + { + // remove aura + plr->RemoveAurasDueToSpell(SI_SILITHYST_FLAG); + ++ m_Gathered_A; + if (m_Gathered_A >= SI_MAX_RESOURCES) + { + TeamApplyBuff(TEAM_ALLIANCE, SI_CENARION_FAVOR); + sWorld.SendZoneText(OutdoorPvPSIBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_SI_CAPTURE_A)); + m_LastController = ALLIANCE; + m_Gathered_A = 0; + m_Gathered_H = 0; + } + UpdateWorldState(); + // reward player + plr->CastSpell(plr,SI_TRACES_OF_SILITHYST,true); + // add 19 honor + plr->RewardHonor(NULL,1,19); + // add 20 cenarion circle repu + plr->GetReputationMgr().ModifyReputation(sFactionStore.LookupEntry(609),20); + // complete quest + plr->KilledMonsterCredit(SI_TURNIN_QUEST_CM_A,0); + } + return true; + case SI_AREATRIGGER_H: + if (plr->GetTeam() == HORDE && plr->HasAura(SI_SILITHYST_FLAG)) + { + // remove aura + plr->RemoveAurasDueToSpell(SI_SILITHYST_FLAG); + ++ m_Gathered_H; + if (m_Gathered_H >= SI_MAX_RESOURCES) + { + TeamApplyBuff(TEAM_HORDE, SI_CENARION_FAVOR); + sWorld.SendZoneText(OutdoorPvPSIBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_SI_CAPTURE_H)); + m_LastController = HORDE; + m_Gathered_A = 0; + m_Gathered_H = 0; + } + UpdateWorldState(); + // reward player + plr->CastSpell(plr,SI_TRACES_OF_SILITHYST,true); + // add 19 honor + plr->RewardHonor(NULL,1,19); + // add 20 cenarion circle repu + plr->GetReputationMgr().ModifyReputation(sFactionStore.LookupEntry(609),20); + // complete quest + plr->KilledMonsterCredit(SI_TURNIN_QUEST_CM_H,0); + } + return true; + } + return false; +} + +bool OutdoorPvPSI::HandleDropFlag(Player *plr, uint32 spellId) +{ + if (spellId == SI_SILITHYST_FLAG) + { + // if it was dropped away from the player's turn-in point, then create a silithyst mound, if it was dropped near the areatrigger, then it was dispelled by the outdoorpvp, so do nothing + switch(plr->GetTeam()) + { + case ALLIANCE: + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(SI_AREATRIGGER_A); + if (atEntry) + { + // 5.0f is safe-distance + if (plr->GetDistance(atEntry->x,atEntry->y,atEntry->z) > 5.0f + atEntry->radius) + { + // he dropped it further, summon mound + GameObject * go = new GameObject; + Map * map = plr->GetMap(); + if (!map) + { + delete go; + return true; + } + + if (!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map, plr->GetPhaseMask(), plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,GO_STATE_READY)) + { + delete go; + } + else + { + go->SetRespawnTime(0); + map->Add(go); + } + } + } + } + break; + case HORDE: + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(SI_AREATRIGGER_H); + if (atEntry) + { + // 5.0f is safe-distance + if (plr->GetDistance(atEntry->x,atEntry->y,atEntry->z) > 5.0f + atEntry->radius) + { + // he dropped it further, summon mound + GameObject * go = new GameObject; + Map * map = plr->GetMap(); + if (!map) + { + delete go; + return true; + } + if (!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map, plr->GetPhaseMask() ,plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,GO_STATE_READY)) + { + delete go; + } + else + { + go->SetRespawnTime(0); + map->Add(go); + } + } + } + } + break; + } + return true; + } + return false; +} + +bool OutdoorPvPSI::HandleCustomSpell(Player *plr, uint32 spellId, GameObject *go) +{ + if (!go || spellId != SI_SILITHYST_FLAG_GO_SPELL) + return false; + plr->CastSpell(plr,SI_SILITHYST_FLAG,true); + if (go->GetGOInfo()->id == SI_SILITHYST_MOUND) + { + // despawn go + go->SetRespawnTime(0); + go->Delete(); + } + return true; +} + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.h b/src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.h new file mode 100644 index 00000000000..3176669c42c --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPSI.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OUTDOOR_PVP_SI_ +#define OUTDOOR_PVP_SI_ + +#include "OutdoorPvPImpl.h" + +enum OutdoorPvPSISpells +{ + SI_SILITHYST_FLAG_GO_SPELL = 29518, + SI_SILITHYST_FLAG = 29519, + SI_TRACES_OF_SILITHYST = 29534, + SI_CENARION_FAVOR = 30754 +}; + +const uint32 SI_MAX_RESOURCES = 200; + +const uint32 OutdoorPvPSIBuffZonesNum = 3; + +const uint32 OutdoorPvPSIBuffZones[OutdoorPvPSIBuffZonesNum] = { 1377, 3428, 3429 }; + +const uint32 SI_AREATRIGGER_H = 4168; + +const uint32 SI_AREATRIGGER_A = 4162; + +const uint32 SI_TURNIN_QUEST_CM_A = 17090; + +const uint32 SI_TURNIN_QUEST_CM_H = 18199; + +const uint32 SI_SILITHYST_MOUND = 181597; + +enum SI_WorldStates{ + SI_GATHERED_A = 2313, + SI_GATHERED_H = 2314, + SI_SILITHYST_MAX = 2317 +}; + +class OutdoorPvPSI : public OutdoorPvP +{ +public: + OutdoorPvPSI(); + bool SetupOutdoorPvP(); + void HandlePlayerEnterZone(Player *plr, uint32 zone); + void HandlePlayerLeaveZone(Player *plr, uint32 zone); + bool Update(uint32 diff); + void FillInitialWorldStates(WorldPacket &data); + void SendRemoveWorldStates(Player * plr); + bool HandleAreaTrigger(Player * plr, uint32 trigger); + bool HandleDropFlag(Player * plr, uint32 spellId); + bool HandleCustomSpell(Player * plr, uint32 spellId, GameObject *go); + void UpdateWorldState(); +private: + uint32 m_Gathered_A; + uint32 m_Gathered_H; + uint32 m_LastController; +}; + +#endif + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.cpp b/src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.cpp new file mode 100644 index 00000000000..4d5682bf1d6 --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "OutdoorPvPTF.h" +#include "OutdoorPvPMgr.h" +#include "WorldPacket.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "Language.h" +#include "World.h" + +OutdoorPvPTF::OutdoorPvPTF() +{ + m_TypeId = OUTDOOR_PVP_TF; +} + +OPvPCapturePointTF::OPvPCapturePointTF(OutdoorPvP *pvp, OutdoorPvPTF_TowerType type) +: OPvPCapturePoint(pvp), m_TowerType(type), m_TowerState(TF_TOWERSTATE_N) +{ + SetCapturePointData(TFCapturePoints[type].entry,TFCapturePoints[type].map,TFCapturePoints[type].x,TFCapturePoints[type].y,TFCapturePoints[type].z,TFCapturePoints[type].o,TFCapturePoints[type].rot0,TFCapturePoints[type].rot1,TFCapturePoints[type].rot2,TFCapturePoints[type].rot3); +} + +void OPvPCapturePointTF::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(TFTowerWorldStates[m_TowerType].n) << uint32(bool(m_TowerState & TF_TOWERSTATE_N)); + data << uint32(TFTowerWorldStates[m_TowerType].h) << uint32(bool(m_TowerState & TF_TOWERSTATE_H)); + data << uint32(TFTowerWorldStates[m_TowerType].a) << uint32(bool(m_TowerState & TF_TOWERSTATE_A)); +} + +void OutdoorPvPTF::FillInitialWorldStates(WorldPacket &data) +{ + data << TF_UI_TOWER_SLIDER_POS << uint32(50); + data << TF_UI_TOWER_SLIDER_N << uint32(100); + data << TF_UI_TOWER_SLIDER_DISPLAY << uint32(0); + + data << TF_UI_TOWER_COUNT_H << m_HordeTowersControlled; + data << TF_UI_TOWER_COUNT_A << m_AllianceTowersControlled; + data << TF_UI_TOWERS_CONTROLLED_DISPLAY << uint32(!m_IsLocked); + + data << TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT << first_digit; + data << TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT << second_digit; + data << TF_UI_LOCKED_TIME_HOURS << hours_left; + + data << TF_UI_LOCKED_DISPLAY_NEUTRAL << uint32(m_IsLocked && !m_HordeTowersControlled && !m_AllianceTowersControlled); + data << TF_UI_LOCKED_DISPLAY_HORDE << uint32(m_IsLocked && (m_HordeTowersControlled > m_AllianceTowersControlled)); + data << TF_UI_LOCKED_DISPLAY_ALLIANCE << uint32(m_IsLocked && (m_HordeTowersControlled < m_AllianceTowersControlled)); + + for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) + { + itr->second->FillInitialWorldStates(data); + } +} + +void OutdoorPvPTF::SendRemoveWorldStates(Player * plr) +{ + plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_POS,uint32(0)); + plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_N,uint32(0)); + plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_DISPLAY,uint32(0)); + + plr->SendUpdateWorldState(TF_UI_TOWER_COUNT_H,uint32(0)); + plr->SendUpdateWorldState(TF_UI_TOWER_COUNT_A,uint32(0)); + plr->SendUpdateWorldState(TF_UI_TOWERS_CONTROLLED_DISPLAY,uint32(0)); + + plr->SendUpdateWorldState(TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT,uint32(0)); + plr->SendUpdateWorldState(TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT,uint32(0)); + plr->SendUpdateWorldState(TF_UI_LOCKED_TIME_HOURS,uint32(0)); + + plr->SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_NEUTRAL,uint32(0)); + plr->SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_HORDE,uint32(0)); + plr->SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_ALLIANCE,uint32(0)); + + for (int i = 0; i < TF_TOWER_NUM; ++i) + { + plr->SendUpdateWorldState(uint32(TFTowerWorldStates[i].n),uint32(0)); + plr->SendUpdateWorldState(uint32(TFTowerWorldStates[i].h),uint32(0)); + plr->SendUpdateWorldState(uint32(TFTowerWorldStates[i].a),uint32(0)); + } +} + +void OPvPCapturePointTF::UpdateTowerState() +{ + m_PvP->SendUpdateWorldState(uint32(TFTowerWorldStates[m_TowerType].n),uint32(bool(m_TowerState & TF_TOWERSTATE_N))); + m_PvP->SendUpdateWorldState(uint32(TFTowerWorldStates[m_TowerType].h),uint32(bool(m_TowerState & TF_TOWERSTATE_H))); + m_PvP->SendUpdateWorldState(uint32(TFTowerWorldStates[m_TowerType].a),uint32(bool(m_TowerState & TF_TOWERSTATE_A))); +} + +bool OPvPCapturePointTF::HandlePlayerEnter(Player *plr) +{ + if (OPvPCapturePoint::HandlePlayerEnter(plr)) + { + plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_DISPLAY, 1); + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_POS, phase); + plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_N, m_neutralValuePct); + return true; + } + return false; +} + +void OPvPCapturePointTF::HandlePlayerLeave(Player *plr) +{ + plr->SendUpdateWorldState(TF_UI_TOWER_SLIDER_DISPLAY, 0); + OPvPCapturePoint::HandlePlayerLeave(plr); +} + +bool OutdoorPvPTF::Update(uint32 diff) +{ + bool changed = OutdoorPvP::Update(diff); + + if (changed) + { + if (m_AllianceTowersControlled == TF_TOWER_NUM) + { + TeamApplyBuff(TEAM_ALLIANCE, TF_CAPTURE_BUFF); + m_IsLocked = true; + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_NEUTRAL,uint32(0)); + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_HORDE,uint32(0)); + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_ALLIANCE,uint32(1)); + SendUpdateWorldState(TF_UI_TOWERS_CONTROLLED_DISPLAY, uint32(0)); + } + else if (m_HordeTowersControlled == TF_TOWER_NUM) + { + TeamApplyBuff(TEAM_HORDE, TF_CAPTURE_BUFF); + m_IsLocked = true; + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_NEUTRAL,uint32(0)); + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_HORDE,uint32(1)); + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_ALLIANCE,uint32(0)); + SendUpdateWorldState(TF_UI_TOWERS_CONTROLLED_DISPLAY, uint32(0)); + } + else + { + TeamCastSpell(TEAM_ALLIANCE, -TF_CAPTURE_BUFF); + TeamCastSpell(TEAM_HORDE, -TF_CAPTURE_BUFF); + } + SendUpdateWorldState(TF_UI_TOWER_COUNT_A, m_AllianceTowersControlled); + SendUpdateWorldState(TF_UI_TOWER_COUNT_H, m_HordeTowersControlled); + } + if (m_IsLocked) + { + // lock timer is down, release lock + if (m_LockTimer < diff) + { + m_LockTimer = TF_LOCK_TIME; + m_LockTimerUpdate = 0; + m_IsLocked = false; + SendUpdateWorldState(TF_UI_TOWERS_CONTROLLED_DISPLAY, uint32(1)); + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_NEUTRAL,uint32(0)); + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_HORDE,uint32(0)); + SendUpdateWorldState(TF_UI_LOCKED_DISPLAY_ALLIANCE,uint32(0)); + } + else + { + // worldstateui update timer is down, update ui with new time data + if (m_LockTimerUpdate < diff) + { + m_LockTimerUpdate = TF_LOCK_TIME_UPDATE; + uint32 minutes_left = m_LockTimer / 60000; + hours_left = minutes_left / 60; + minutes_left -= hours_left * 60; + second_digit = minutes_left % 10; + first_digit = minutes_left / 10; + + SendUpdateWorldState(TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT,first_digit); + SendUpdateWorldState(TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT,second_digit); + SendUpdateWorldState(TF_UI_LOCKED_TIME_HOURS,hours_left); + } else m_LockTimerUpdate -= diff; + m_LockTimer -= diff; + } + } + return changed; +} + +void OutdoorPvPTF::HandlePlayerEnterZone(Player * plr, uint32 zone) +{ + if (plr->GetTeam() == ALLIANCE) + { + if (m_AllianceTowersControlled >= TF_TOWER_NUM) + plr->CastSpell(plr,TF_CAPTURE_BUFF,true); + } + else + { + if (m_HordeTowersControlled >= TF_TOWER_NUM) + plr->CastSpell(plr,TF_CAPTURE_BUFF,true); + } + OutdoorPvP::HandlePlayerEnterZone(plr,zone); +} + +void OutdoorPvPTF::HandlePlayerLeaveZone(Player * plr, uint32 zone) +{ + // remove buffs + plr->RemoveAurasDueToSpell(TF_CAPTURE_BUFF); + OutdoorPvP::HandlePlayerLeaveZone(plr, zone); +} + +bool OutdoorPvPTF::SetupOutdoorPvP() +{ + m_AllianceTowersControlled = 0; + m_HordeTowersControlled = 0; + + m_IsLocked = false; + m_LockTimer = TF_LOCK_TIME; + m_LockTimerUpdate = 0; + hours_left = 6; + second_digit = 0; + first_digit = 0; + + // add the zones affected by the pvp buff + for (int i = 0; i < OutdoorPvPTFBuffZonesNum; ++i) + RegisterZone(OutdoorPvPTFBuffZones[i]); + + AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_NW)); + AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_N)); + AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_NE)); + AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_SE)); + AddCapturePoint(new OPvPCapturePointTF(this,TF_TOWER_S)); + + return true; +} + +bool OPvPCapturePointTF::Update(uint32 diff) +{ + // can update even in locked state if gathers the controlling faction + bool canupdate = ((((OutdoorPvPTF*)m_PvP)->m_AllianceTowersControlled > 0) && m_activePlayers[0].size() > m_activePlayers[1].size()) || + ((((OutdoorPvPTF*)m_PvP)->m_HordeTowersControlled > 0) && m_activePlayers[0].size() < m_activePlayers[1].size()); + // if gathers the other faction, then only update if the pvp is unlocked + canupdate = canupdate || !((OutdoorPvPTF*)m_PvP)->m_IsLocked; + return canupdate && OPvPCapturePoint::Update(diff); +} + +void OPvPCapturePointTF::ChangeState() +{ + // if changing from controlling alliance to horde + if (m_OldState == OBJECTIVESTATE_ALLIANCE) + { + if (((OutdoorPvPTF*)m_PvP)->m_AllianceTowersControlled) + ((OutdoorPvPTF*)m_PvP)->m_AllianceTowersControlled--; + sWorld.SendZoneText(OutdoorPvPTFBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_TF_LOOSE_A)); + } + // if changing from controlling horde to alliance + else if (m_OldState == OBJECTIVESTATE_HORDE) + { + if (((OutdoorPvPTF*)m_PvP)->m_HordeTowersControlled) + ((OutdoorPvPTF*)m_PvP)->m_HordeTowersControlled--; + sWorld.SendZoneText(OutdoorPvPTFBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_TF_LOOSE_H)); + } + + uint32 artkit = 21; + + switch(m_State) + { + case OBJECTIVESTATE_ALLIANCE: + m_TowerState = TF_TOWERSTATE_A; + artkit = 2; + if (((OutdoorPvPTF*)m_PvP)->m_AllianceTowersControlledm_AllianceTowersControlled++; + sWorld.SendZoneText(OutdoorPvPTFBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_TF_CAPTURE_A)); + for (PlayerSet::iterator itr = m_activePlayers[0].begin(); itr != m_activePlayers[0].end(); ++itr) + (*itr)->AreaExploredOrEventHappens(TF_ALLY_QUEST); + break; + case OBJECTIVESTATE_HORDE: + m_TowerState = TF_TOWERSTATE_H; + artkit = 1; + if (((OutdoorPvPTF*)m_PvP)->m_HordeTowersControlledm_HordeTowersControlled++; + sWorld.SendZoneText(OutdoorPvPTFBuffZones[0],objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_TF_CAPTURE_H)); + for (PlayerSet::iterator itr = m_activePlayers[1].begin(); itr != m_activePlayers[1].end(); ++itr) + (*itr)->AreaExploredOrEventHappens(TF_HORDE_QUEST); + break; + case OBJECTIVESTATE_NEUTRAL: + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + m_TowerState = TF_TOWERSTATE_N; + break; + } + + GameObject* flag = HashMapHolder::Find(m_capturePointGUID); + if (flag) + flag->SetGoArtKit(artkit); + + UpdateTowerState(); +} + +void OPvPCapturePointTF::SendChangePhase() +{ + // send this too, sometimes the slider disappears, dunno why :( + SendUpdateWorldState(TF_UI_TOWER_SLIDER_DISPLAY, 1); + // send these updates to only the ones in this objective + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + SendUpdateWorldState(TF_UI_TOWER_SLIDER_POS, phase); + // send this too, sometimes it resets :S + SendUpdateWorldState(TF_UI_TOWER_SLIDER_N, m_neutralValuePct); +} + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.h b/src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.h new file mode 100644 index 00000000000..3a88b7fd309 --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPTF.h @@ -0,0 +1,117 @@ +#ifndef OUTDOOR_PVP_TF_ +#define OUTDOOR_PVP_TF_ + +#include "OutdoorPvPImpl.h" + +const uint32 OutdoorPvPTFBuffZonesNum = 5; + +const uint32 OutdoorPvPTFBuffZones[OutdoorPvPTFBuffZonesNum] = { 3519 /*Terokkar Forest*/, 3791 /*Sethekk Halls*/, 3789 /*Shadow Labyrinth*/, 3792 /*Mana-Tombs*/, 3790 /*Auchenai Crypts*/ }; + +// locked for 6 hours after capture +const uint32 TF_LOCK_TIME = 3600 * 6 * 1000; +// update lock timer every 1/4 minute (overkill, but this way it's sure the timer won't "jump" 2 minutes at once.) +const uint32 TF_LOCK_TIME_UPDATE = 15000; + +// blessing of auchindoun +#define TF_CAPTURE_BUFF 33377 + +const uint32 TF_ALLY_QUEST = 11505; +const uint32 TF_HORDE_QUEST = 11506; + +enum OutdoorPvPTF_TowerType{ + TF_TOWER_NW = 0, + TF_TOWER_N, + TF_TOWER_NE, + TF_TOWER_SE, + TF_TOWER_S, + TF_TOWER_NUM +}; + +const go_type TFCapturePoints[TF_TOWER_NUM] = { + {183104,530,-3081.65,5335.03,17.1853,-2.14675,0,0,0.878817,-0.477159}, + {183411,530,-2939.9,4788.73,18.987,2.77507,0,0,0.983255,0.182236}, + {183412,530,-3174.94,4440.97,16.2281,1.86750,0,0.803857,0.594823}, + {183413,530,-3603.31,4529.15,20.9077,0.994838,0,0,0.477159,0.878817}, + {183414,530,-3812.37,4899.3,17.7249,0.087266,0,0,0.043619,0.999048} +}; + +struct tf_tower_world_state{ + uint32 n; + uint32 h; + uint32 a; +}; + +const tf_tower_world_state TFTowerWorldStates[TF_TOWER_NUM] = { + {0xa79,0xa7a,0xa7b}, + {0xa7e,0xa7d,0xa7c}, + {0xa82,0xa81,0xa80}, + {0xa88,0xa87,0xa86}, + {0xa85,0xa84,0xa83} +}; + +const uint32 TFTowerPlayerEnterEvents[TF_TOWER_NUM] = {12226, 12497, 12486, 12499, 12501}; + +const uint32 TFTowerPlayerLeaveEvents[TF_TOWER_NUM] = {12225, 12496, 12487, 12498, 12500}; + +enum TFWorldStates{ + TF_UI_TOWER_SLIDER_POS = 0xa41, + TF_UI_TOWER_SLIDER_N = 0xa40, + TF_UI_TOWER_SLIDER_DISPLAY = 0xa3f, + + TF_UI_TOWER_COUNT_H = 0xa3e, + TF_UI_TOWER_COUNT_A = 0xa3d, + TF_UI_TOWERS_CONTROLLED_DISPLAY = 0xa3c, + + TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT = 0x9d0, + TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT = 0x9ce, + TF_UI_LOCKED_TIME_HOURS = 0x9cd, + TF_UI_LOCKED_DISPLAY_NEUTRAL = 0x9cc, + TF_UI_LOCKED_DISPLAY_HORDE = 0xad0, + TF_UI_LOCKED_DISPLAY_ALLIANCE = 0xacf +}; + +enum TFTowerStates { + TF_TOWERSTATE_N = 1, + TF_TOWERSTATE_H = 2, + TF_TOWERSTATE_A = 4 +}; + +class OPvPCapturePointTF : public OPvPCapturePoint +{ +public: + OPvPCapturePointTF(OutdoorPvP * pvp, OutdoorPvPTF_TowerType type); + bool Update(uint32 diff); + void ChangeState(); + void SendChangePhase(); + void FillInitialWorldStates(WorldPacket & data); + // used when player is activated/inactivated in the area + bool HandlePlayerEnter(Player * plr); + void HandlePlayerLeave(Player * plr); + void UpdateTowerState(); +protected: + OutdoorPvPTF_TowerType m_TowerType; + uint32 m_TowerState; +}; + +class OutdoorPvPTF : public OutdoorPvP +{ +friend class OPvPCapturePointTF; +public: + OutdoorPvPTF(); + bool SetupOutdoorPvP(); + void HandlePlayerEnterZone(Player *plr, uint32 zone); + void HandlePlayerLeaveZone(Player *plr, uint32 zone); + bool Update(uint32 diff); + void FillInitialWorldStates(WorldPacket &data); + void SendRemoveWorldStates(Player * plr); +private: + bool m_IsLocked; + uint32 m_LockTimer; + uint32 m_LockTimerUpdate; + uint32 m_AllianceTowersControlled; + uint32 m_HordeTowersControlled; + uint32 hours_left, second_digit, first_digit; +}; + +#endif + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.cpp b/src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.cpp new file mode 100644 index 00000000000..fb548816c3a --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.cpp @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "OutdoorPvPZM.h" +#include "ObjectMgr.h" +#include "OutdoorPvPMgr.h" +#include "Player.h" +#include "Creature.h" +#include "ObjectAccessor.h" +#include "WorldPacket.h" +#include "GossipDef.h" +#include "World.h" + +OPvPCapturePointZM_Beacon::OPvPCapturePointZM_Beacon(OutdoorPvP *pvp, ZM_BeaconType type) +: OPvPCapturePoint(pvp), m_TowerType(type), m_TowerState(ZM_TOWERSTATE_N) +{ + SetCapturePointData(ZMCapturePoints[type].entry,ZMCapturePoints[type].map,ZMCapturePoints[type].x,ZMCapturePoints[type].y,ZMCapturePoints[type].z,ZMCapturePoints[type].o,ZMCapturePoints[type].rot0,ZMCapturePoints[type].rot1,ZMCapturePoints[type].rot2,ZMCapturePoints[type].rot3); +} + +void OPvPCapturePointZM_Beacon::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_n) << uint32(bool(m_TowerState & ZM_TOWERSTATE_N)); + data << uint32(ZMBeaconInfo[m_TowerType].map_tower_n) << uint32(bool(m_TowerState & ZM_TOWERSTATE_N)); + data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_a) << uint32(bool(m_TowerState & ZM_TOWERSTATE_A)); + data << uint32(ZMBeaconInfo[m_TowerType].map_tower_a) << uint32(bool(m_TowerState & ZM_TOWERSTATE_A)); + data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_h) << uint32(bool(m_TowerState & ZM_TOWERSTATE_H)); + data << uint32(ZMBeaconInfo[m_TowerType].map_tower_h) << uint32(bool(m_TowerState & ZM_TOWERSTATE_H)); +} + +void OPvPCapturePointZM_Beacon::UpdateTowerState() +{ + m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].ui_tower_n),uint32(bool(m_TowerState & ZM_TOWERSTATE_N))); + m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].map_tower_n),uint32(bool(m_TowerState & ZM_TOWERSTATE_N))); + m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].ui_tower_a),uint32(bool(m_TowerState & ZM_TOWERSTATE_A))); + m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].map_tower_a),uint32(bool(m_TowerState & ZM_TOWERSTATE_A))); + m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].ui_tower_h),uint32(bool(m_TowerState & ZM_TOWERSTATE_H))); + m_PvP->SendUpdateWorldState(uint32(ZMBeaconInfo[m_TowerType].map_tower_h),uint32(bool(m_TowerState & ZM_TOWERSTATE_H))); +} + +bool OPvPCapturePointZM_Beacon::HandlePlayerEnter(Player *plr) +{ + if (OPvPCapturePoint::HandlePlayerEnter(plr)) + { + plr->SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_disp, 1); + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + plr->SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_pos, phase); + plr->SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_n, m_neutralValuePct); + return true; + } + return false; +} + +void OPvPCapturePointZM_Beacon::HandlePlayerLeave(Player *plr) +{ + plr->SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_disp, 0); + OPvPCapturePoint::HandlePlayerLeave(plr); +} + +void OPvPCapturePointZM_Beacon::ChangeState() +{ + // if changing from controlling alliance to horde + if (m_OldState == OBJECTIVESTATE_ALLIANCE) + { + if (((OutdoorPvPZM*)m_PvP)->m_AllianceTowersControlled) + ((OutdoorPvPZM*)m_PvP)->m_AllianceTowersControlled--; + sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(ZMBeaconLooseA[m_TowerType])); + } + // if changing from controlling horde to alliance + else if (m_OldState == OBJECTIVESTATE_HORDE) + { + if (((OutdoorPvPZM*)m_PvP)->m_HordeTowersControlled) + ((OutdoorPvPZM*)m_PvP)->m_HordeTowersControlled--; + sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(ZMBeaconLooseH[m_TowerType])); + } + + switch(m_State) + { + case OBJECTIVESTATE_ALLIANCE: + m_TowerState = ZM_TOWERSTATE_A; + if (((OutdoorPvPZM*)m_PvP)->m_AllianceTowersControlledm_AllianceTowersControlled++; + sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(ZMBeaconCaptureA[m_TowerType])); + break; + case OBJECTIVESTATE_HORDE: + m_TowerState = ZM_TOWERSTATE_H; + if (((OutdoorPvPZM*)m_PvP)->m_HordeTowersControlledm_HordeTowersControlled++; + sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(ZMBeaconCaptureH[m_TowerType])); + break; + case OBJECTIVESTATE_NEUTRAL: + case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: + case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: + case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: + case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: + m_TowerState = ZM_TOWERSTATE_N; + break; + } + + UpdateTowerState(); +} + +void OPvPCapturePointZM_Beacon::SendChangePhase() +{ + // send this too, sometimes the slider disappears, dunno why :( + SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_disp, 1); + // send these updates to only the ones in this objective + uint32 phase = (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f); + SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_pos, phase); + SendUpdateWorldState(ZMBeaconInfo[m_TowerType].slider_n, m_neutralValuePct); +} + +bool OutdoorPvPZM::Update(uint32 diff) +{ + bool changed = OutdoorPvP::Update(diff); + if (changed) + { + if (m_AllianceTowersControlled == ZM_NUM_BEACONS) + m_GraveYard->SetBeaconState(ALLIANCE); + else if (m_HordeTowersControlled == ZM_NUM_BEACONS) + m_GraveYard->SetBeaconState(HORDE); + else + m_GraveYard->SetBeaconState(0); + } + return changed; +} + +void OutdoorPvPZM::HandlePlayerEnterZone(Player * plr, uint32 zone) +{ + if (plr->GetTeam() == ALLIANCE) + { + if (m_GraveYard->m_GraveYardState & ZM_GRAVEYARD_A) + plr->CastSpell(plr,ZM_CAPTURE_BUFF,true); + } + else + { + if (m_GraveYard->m_GraveYardState & ZM_GRAVEYARD_H) + plr->CastSpell(plr,ZM_CAPTURE_BUFF,true); + } + OutdoorPvP::HandlePlayerEnterZone(plr,zone); +} + +void OutdoorPvPZM::HandlePlayerLeaveZone(Player * plr, uint32 zone) +{ + // remove buffs + plr->RemoveAurasDueToSpell(ZM_CAPTURE_BUFF); + // remove flag + plr->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); + plr->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_H); + OutdoorPvP::HandlePlayerLeaveZone(plr, zone); +} + +OutdoorPvPZM::OutdoorPvPZM() +{ + m_TypeId = OUTDOOR_PVP_ZM; + m_GraveYard = NULL; + m_AllianceTowersControlled = 0; + m_HordeTowersControlled = 0; + +} + +bool OutdoorPvPZM::SetupOutdoorPvP() +{ + m_AllianceTowersControlled = 0; + m_HordeTowersControlled = 0; + + // add the zones affected by the pvp buff + for (int i = 0; i < OutdoorPvPZMBuffZonesNum; ++i) + RegisterZone(OutdoorPvPZMBuffZones[i]); + + AddCapturePoint(new OPvPCapturePointZM_Beacon(this,ZM_BEACON_WEST)); + AddCapturePoint(new OPvPCapturePointZM_Beacon(this,ZM_BEACON_EAST)); + m_GraveYard = new OPvPCapturePointZM_GraveYard(this); + AddCapturePoint(m_GraveYard); // though the update function isn't used, the handleusego is! + + return true; +} + +void OutdoorPvPZM::HandleKillImpl(Player *plr, Unit * killed) +{ + if (killed->GetTypeId() != TYPEID_PLAYER) + return; + + if (plr->GetTeam() == ALLIANCE && killed->ToPlayer()->GetTeam() != ALLIANCE) + plr->CastSpell(plr,ZM_AlliancePlayerKillReward,true); + else if (plr->GetTeam() == HORDE && killed->ToPlayer()->GetTeam() != HORDE) + plr->CastSpell(plr,ZM_HordePlayerKillReward,true); +} + +bool OPvPCapturePointZM_GraveYard::Update(uint32 /*diff*/) +{ + bool retval = m_State != m_OldState; + m_State = m_OldState; + return retval; +} + +int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player *plr, uint64 guid) +{ + uint32 retval = OPvPCapturePoint::HandleOpenGo(plr, guid); + if (retval >= 0) + { + if (plr->HasAura(ZM_BATTLE_STANDARD_A) && m_GraveYardState != ZM_GRAVEYARD_A) + { + if (m_GraveYardState == ZM_GRAVEYARD_H) + sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_LOOSE_GY_H)); + m_GraveYardState = ZM_GRAVEYARD_A; + DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant + AddObject(0,ZM_Banner_A.entry,ZM_Banner_A.map,ZM_Banner_A.x,ZM_Banner_A.y,ZM_Banner_A.z,ZM_Banner_A.o,ZM_Banner_A.rot0,ZM_Banner_A.rot1,ZM_Banner_A.rot2,ZM_Banner_A.rot3); + objmgr.RemoveGraveYardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, HORDE); // rem gy + objmgr.AddGraveYardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, ALLIANCE, false); // add gy + m_PvP->TeamApplyBuff(TEAM_ALLIANCE, ZM_CAPTURE_BUFF); + plr->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); + sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_A)); + } + else if (plr->HasAura(ZM_BATTLE_STANDARD_H) && m_GraveYardState != ZM_GRAVEYARD_H) + { + if (m_GraveYardState == ZM_GRAVEYARD_A) + sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_LOOSE_GY_A)); + m_GraveYardState = ZM_GRAVEYARD_H; + DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant + AddObject(0,ZM_Banner_H.entry,ZM_Banner_H.map,ZM_Banner_H.x,ZM_Banner_H.y,ZM_Banner_H.z,ZM_Banner_H.o,ZM_Banner_H.rot0,ZM_Banner_H.rot1,ZM_Banner_H.rot2,ZM_Banner_H.rot3); + objmgr.RemoveGraveYardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, ALLIANCE); // rem gy + objmgr.AddGraveYardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, HORDE, false); // add gy + m_PvP->TeamApplyBuff(TEAM_HORDE, ZM_CAPTURE_BUFF); + plr->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_H); + sWorld.SendZoneText(ZM_GRAVEYARD_ZONE,objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_H)); + } + UpdateTowerState(); + } + return retval; +} + +OPvPCapturePointZM_GraveYard::OPvPCapturePointZM_GraveYard(OutdoorPvP *pvp) +: OPvPCapturePoint(pvp) +{ + m_BothControllingFaction = 0; + m_GraveYardState = ZM_GRAVEYARD_N; + m_FlagCarrierGUID = 0; + // add field scouts here + AddCreature(ZM_ALLIANCE_FIELD_SCOUT,ZM_AllianceFieldScout.entry,ZM_AllianceFieldScout.teamval,ZM_AllianceFieldScout.map,ZM_AllianceFieldScout.x,ZM_AllianceFieldScout.y,ZM_AllianceFieldScout.z,ZM_AllianceFieldScout.o); + AddCreature(ZM_HORDE_FIELD_SCOUT,ZM_HordeFieldScout.entry,ZM_HordeFieldScout.teamval,ZM_HordeFieldScout.map,ZM_HordeFieldScout.x,ZM_HordeFieldScout.y,ZM_HordeFieldScout.z,ZM_HordeFieldScout.o); + // add neutral banner + AddObject(0,ZM_Banner_N.entry,ZM_Banner_N.map,ZM_Banner_N.x,ZM_Banner_N.y,ZM_Banner_N.z,ZM_Banner_N.o,ZM_Banner_N.rot0,ZM_Banner_N.rot1,ZM_Banner_N.rot2,ZM_Banner_N.rot3); +} + +void OPvPCapturePointZM_GraveYard::UpdateTowerState() +{ + m_PvP->SendUpdateWorldState(ZM_MAP_GRAVEYARD_N,uint32(bool(m_GraveYardState & ZM_GRAVEYARD_N))); + m_PvP->SendUpdateWorldState(ZM_MAP_GRAVEYARD_H,uint32(bool(m_GraveYardState & ZM_GRAVEYARD_H))); + m_PvP->SendUpdateWorldState(ZM_MAP_GRAVEYARD_A,uint32(bool(m_GraveYardState & ZM_GRAVEYARD_A))); + + m_PvP->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_READY,uint32(m_BothControllingFaction == ALLIANCE)); + m_PvP->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_NOT_READY,uint32(m_BothControllingFaction != ALLIANCE)); + m_PvP->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_READY,uint32(m_BothControllingFaction == HORDE)); + m_PvP->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_NOT_READY,uint32(m_BothControllingFaction != HORDE)); +} + +void OPvPCapturePointZM_GraveYard::FillInitialWorldStates(WorldPacket &data) +{ + data << ZM_MAP_GRAVEYARD_N << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_N)); + data << ZM_MAP_GRAVEYARD_H << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_H)); + data << ZM_MAP_GRAVEYARD_A << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_A)); + + data << ZM_MAP_ALLIANCE_FLAG_READY << uint32(m_BothControllingFaction == ALLIANCE); + data << ZM_MAP_ALLIANCE_FLAG_NOT_READY << uint32(m_BothControllingFaction != ALLIANCE); + data << ZM_MAP_HORDE_FLAG_READY << uint32(m_BothControllingFaction == HORDE); + data << ZM_MAP_HORDE_FLAG_NOT_READY << uint32(m_BothControllingFaction != HORDE); +} + +void OPvPCapturePointZM_GraveYard::SetBeaconState(uint32 controlling_faction) +{ + // nothing to do here + if (m_BothControllingFaction == controlling_faction) + return; + m_BothControllingFaction = controlling_faction; + + switch(controlling_faction) + { + case ALLIANCE: + // if ally already controls the gy and taken back both beacons, return, nothing to do for us + if (m_GraveYardState & ZM_GRAVEYARD_A) + return; + // ally doesn't control the gy, but controls the side beacons -> add gossip option, add neutral banner + break; + case HORDE: + // if horde already controls the gy and taken back both beacons, return, nothing to do for us + if (m_GraveYardState & ZM_GRAVEYARD_H) + return; + // horde doesn't control the gy, but controls the side beacons -> add gossip option, add neutral banner + break; + default: + // if the graveyard is not neutral, then leave it that way + // if the graveyard is neutral, then we have to dispel the buff from the flag carrier + if (m_GraveYardState & ZM_GRAVEYARD_N) + { + // gy was neutral, thus neutral banner was spawned, it is possible that someone was taking the flag to the gy + if (m_FlagCarrierGUID) + { + // remove flag from carrier, reset flag carrier guid + Player * p = objmgr.GetPlayer(m_FlagCarrierGUID); + if (p) + { + p->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); + p->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_H); + } + m_FlagCarrierGUID = 0; + } + } + break; + } + // send worldstateupdate + UpdateTowerState(); +} + +bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso) +{ + uint64 guid = c->GetGUID(); + std::map::iterator itr = m_CreatureTypes.find(guid); + if (itr != m_CreatureTypes.end()) + { + if (itr->second == ZM_ALLIANCE_FIELD_SCOUT && plr->GetTeam() == ALLIANCE && m_BothControllingFaction == ALLIANCE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_A) + return true; + else if (itr->second == ZM_HORDE_FIELD_SCOUT && plr->GetTeam() == HORDE && m_BothControllingFaction == HORDE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_H) + return true; + } + return false; +} + +bool OPvPCapturePointZM_GraveYard::HandleGossipOption(Player *plr, uint64 guid, uint32 /*gossipid*/) +{ + std::map::iterator itr = m_CreatureTypes.find(guid); + if (itr != m_CreatureTypes.end()) + { + Creature * cr = HashMapHolder::Find(guid); + if (!cr) + return true; + // if the flag is already taken, then return + if (m_FlagCarrierGUID) + return true; + if (itr->second == ZM_ALLIANCE_FIELD_SCOUT) + { + cr->CastSpell(plr,ZM_BATTLE_STANDARD_A,true); + m_FlagCarrierGUID = plr->GetGUID(); + } + else if (itr->second == ZM_HORDE_FIELD_SCOUT) + { + cr->CastSpell(plr,ZM_BATTLE_STANDARD_H,true); + m_FlagCarrierGUID = plr->GetGUID(); + } + UpdateTowerState(); + plr->PlayerTalkClass->CloseGossip(); + return true; + } + return false; +} + +bool OPvPCapturePointZM_GraveYard::HandleDropFlag(Player * /*plr*/, uint32 spellId) +{ + switch(spellId) + { + case ZM_BATTLE_STANDARD_A: + m_FlagCarrierGUID = 0; + return true; + case ZM_BATTLE_STANDARD_H: + m_FlagCarrierGUID = 0; + return true; + } + return false; +} + +void OutdoorPvPZM::FillInitialWorldStates(WorldPacket &data) +{ + data << ZM_WORLDSTATE_UNK_1 << uint32(1); + for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) + { + itr->second->FillInitialWorldStates(data); + } +} + +void OutdoorPvPZM::SendRemoveWorldStates(Player *plr) +{ + plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_N_W,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_POS_W,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_DISPLAY_W,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_N_E,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_POS_E,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_SLIDER_DISPLAY_E,0); + plr->SendUpdateWorldState(ZM_WORLDSTATE_UNK_1,1); + plr->SendUpdateWorldState(ZM_UI_TOWER_EAST_N,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_EAST_H,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_EAST_A,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_WEST_N,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_WEST_H,0); + plr->SendUpdateWorldState(ZM_UI_TOWER_WEST_A,0); + plr->SendUpdateWorldState(ZM_MAP_TOWER_EAST_N,0); + plr->SendUpdateWorldState(ZM_MAP_TOWER_EAST_H,0); + plr->SendUpdateWorldState(ZM_MAP_TOWER_EAST_A,0); + plr->SendUpdateWorldState(ZM_MAP_GRAVEYARD_H,0); + plr->SendUpdateWorldState(ZM_MAP_GRAVEYARD_A,0); + plr->SendUpdateWorldState(ZM_MAP_GRAVEYARD_N,0); + plr->SendUpdateWorldState(ZM_MAP_TOWER_WEST_N,0); + plr->SendUpdateWorldState(ZM_MAP_TOWER_WEST_H,0); + plr->SendUpdateWorldState(ZM_MAP_TOWER_WEST_A,0); + plr->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_READY,0); + plr->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_NOT_READY,0); + plr->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_NOT_READY,0); + plr->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_READY,0); +} + diff --git a/src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.h b/src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.h new file mode 100644 index 00000000000..cd26e6bb527 --- /dev/null +++ b/src/server/game/OutdoorPvP/Zones/OutdoorPvPZM.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OUTDOOR_PVP_ZM_ +#define OUTDOOR_PVP_ZM_ + +#include "OutdoorPvPImpl.h" +#include "Language.h" + +const uint32 OutdoorPvPZMBuffZonesNum = 5; +// the buff is cast in these zones +const uint32 OutdoorPvPZMBuffZones[OutdoorPvPZMBuffZonesNum] = {3521,3607,3717,3715,3716}; +// linked when the central tower is controlled +const uint32 ZM_GRAVEYARD_ZONE = 3521; +// linked when the central tower is controlled +const uint32 ZM_GRAVEYARD_ID = 969; + +enum OutdoorPvPZMSpells +{ + // cast on the players of the controlling faction + ZM_CAPTURE_BUFF = 33779, // twin spire blessing + // spell that the field scout casts on the player to carry the flag + ZM_BATTLE_STANDARD_A = 32430, + // spell that the field scout casts on the player to carry the flag + ZM_BATTLE_STANDARD_H = 32431, + // token create spell + ZM_AlliancePlayerKillReward = 32155, + // token create spell + ZM_HordePlayerKillReward = 32158 +}; + +// banners 182527, 182528, 182529, gotta check them ingame +const go_type ZM_Banner_A = { 182527,530,253.54,7083.81,36.7728,-0.017453,0,0,0.008727,-0.999962 }; +const go_type ZM_Banner_H = { 182528,530,253.54,7083.81,36.7728,-0.017453,0,0,0.008727,-0.999962 }; +const go_type ZM_Banner_N = { 182529,530,253.54,7083.81,36.7728,-0.017453,0,0,0.008727,-0.999962 }; + +// horde field scout spawn data +const creature_type ZM_HordeFieldScout = {18564,67,530,296.625,7818.4,42.6294,5.18363}; +// alliance field scout spawn data +const creature_type ZM_AllianceFieldScout = {18581,469,530,374.395,6230.08,22.8351,0.593412}; + +enum ZMCreatureTypes{ + ZM_ALLIANCE_FIELD_SCOUT = 0, + ZM_HORDE_FIELD_SCOUT, + ZM_CREATURE_NUM +}; + +struct zm_beacon { + uint32 slider_disp; + uint32 slider_n; + uint32 slider_pos; + uint32 ui_tower_n; + uint32 ui_tower_h; + uint32 ui_tower_a; + uint32 map_tower_n; + uint32 map_tower_h; + uint32 map_tower_a; + uint32 event_enter; + uint32 event_leave; +}; + +enum ZM_BeaconType{ + ZM_BEACON_EAST = 0, + ZM_BEACON_WEST, + ZM_NUM_BEACONS +}; + +const zm_beacon ZMBeaconInfo[ZM_NUM_BEACONS] = { + {2533,2535,2534,2560,2559,2558,2652,2651,2650,11807,11806}, + {2527,2529,2528,2557,2556,2555,2646,2645,2644,11805,11804} +}; + +const uint32 ZMBeaconCaptureA[ZM_NUM_BEACONS] = { + LANG_OPVP_ZM_CAPTURE_EAST_A, + LANG_OPVP_ZM_CAPTURE_WEST_A +}; + +const uint32 ZMBeaconCaptureH[ZM_NUM_BEACONS] = { + LANG_OPVP_ZM_CAPTURE_EAST_H, + LANG_OPVP_ZM_CAPTURE_WEST_H +}; + +const uint32 ZMBeaconLooseA[ZM_NUM_BEACONS] = { + LANG_OPVP_ZM_LOOSE_EAST_A, + LANG_OPVP_ZM_LOOSE_WEST_A +}; + +const uint32 ZMBeaconLooseH[ZM_NUM_BEACONS] = { + LANG_OPVP_ZM_LOOSE_EAST_H, + LANG_OPVP_ZM_LOOSE_WEST_H +}; + +const go_type ZMCapturePoints[ZM_NUM_BEACONS] = { + {182523,530,303.243,6841.36,40.1245,-1.58825,0,0,0.71325,-0.700909}, + {182522,530,336.466,7340.26,41.4984,-1.58825,0,0,0.71325,-0.700909} +}; + +enum OutdoorPvPZMWorldStates +{ + ZM_UI_TOWER_SLIDER_N_W = 2529, + ZM_UI_TOWER_SLIDER_POS_W = 2528, + ZM_UI_TOWER_SLIDER_DISPLAY_W = 2527, + + ZM_UI_TOWER_SLIDER_N_E = 2535, + ZM_UI_TOWER_SLIDER_POS_E = 2534, + ZM_UI_TOWER_SLIDER_DISPLAY_E = 2533, + + ZM_WORLDSTATE_UNK_1 = 2653, + + ZM_UI_TOWER_EAST_N = 2560, + ZM_UI_TOWER_EAST_H = 2559, + ZM_UI_TOWER_EAST_A = 2558, + ZM_UI_TOWER_WEST_N = 2557, + ZM_UI_TOWER_WEST_H = 2556, + ZM_UI_TOWER_WEST_A = 2555, + + ZM_MAP_TOWER_EAST_N = 2652, + ZM_MAP_TOWER_EAST_H = 2651, + ZM_MAP_TOWER_EAST_A = 2650, + ZM_MAP_GRAVEYARD_H = 2649, + ZM_MAP_GRAVEYARD_A = 2648, + ZM_MAP_GRAVEYARD_N = 2647, + ZM_MAP_TOWER_WEST_N = 2646, + ZM_MAP_TOWER_WEST_H = 2645, + ZM_MAP_TOWER_WEST_A = 2644, + + ZM_MAP_HORDE_FLAG_READY = 2658, + ZM_MAP_HORDE_FLAG_NOT_READY = 2657, + ZM_MAP_ALLIANCE_FLAG_NOT_READY = 2656, + ZM_MAP_ALLIANCE_FLAG_READY = 2655 +}; + +enum ZM_TowerStateMask{ + ZM_TOWERSTATE_N = 1, + ZM_TOWERSTATE_A = 2, + ZM_TOWERSTATE_H = 4 +}; + +class OutdoorPvPZM; +class OPvPCapturePointZM_Beacon : public OPvPCapturePoint +{ +friend class OutdoorPvPZM; +public: + OPvPCapturePointZM_Beacon(OutdoorPvP * pvp, ZM_BeaconType type); + void ChangeState(); + void SendChangePhase(); + void FillInitialWorldStates(WorldPacket & data); + // used when player is activated/inactivated in the area + bool HandlePlayerEnter(Player * plr); + void HandlePlayerLeave(Player * plr); + void UpdateTowerState(); +protected: + ZM_BeaconType m_TowerType; + uint32 m_TowerState; +}; + +enum ZM_GraveYardState{ + ZM_GRAVEYARD_N = 1, + ZM_GRAVEYARD_A = 2, + ZM_GRAVEYARD_H = 4 +}; + +class OPvPCapturePointZM_GraveYard : public OPvPCapturePoint +{ +friend class OutdoorPvPZM; +public: + OPvPCapturePointZM_GraveYard(OutdoorPvP * pvp); + bool Update(uint32 diff); + void ChangeState() {} + void FillInitialWorldStates(WorldPacket & data); + void UpdateTowerState(); + int32 HandleOpenGo(Player *plr, uint64 guid); + void SetBeaconState(uint32 controlling_team); // not good atm + bool HandleGossipOption(Player * plr, uint64 guid, uint32 gossipid); + bool HandleDropFlag(Player * plr, uint32 spellId); + bool CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso); +private: + uint32 m_GraveYardState; +protected: + uint32 m_BothControllingFaction; + uint64 m_FlagCarrierGUID; +}; + +class OutdoorPvPZM : public OutdoorPvP +{ +friend class OPvPCapturePointZM_Beacon; +public: + OutdoorPvPZM(); + bool SetupOutdoorPvP(); + void HandlePlayerEnterZone(Player *plr, uint32 zone); + void HandlePlayerLeaveZone(Player *plr, uint32 zone); + bool Update(uint32 diff); + void FillInitialWorldStates(WorldPacket &data); + void SendRemoveWorldStates(Player * plr); + void HandleKillImpl(Player * plr, Unit * killed); +private: + OPvPCapturePointZM_GraveYard * m_GraveYard; + uint32 m_AllianceTowersControlled; + uint32 m_HordeTowersControlled; +}; + +// todo: flag carrier death/leave/mount/activitychange should give back the gossip options +#endif + diff --git a/src/server/game/PrecompiledHeaders/ScriptedPch.cpp b/src/server/game/PrecompiledHeaders/ScriptedPch.cpp new file mode 100644 index 00000000000..a80690d05da --- /dev/null +++ b/src/server/game/PrecompiledHeaders/ScriptedPch.cpp @@ -0,0 +1,6 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#include "ScriptedPch.h" + diff --git a/src/server/game/PrecompiledHeaders/ScriptedPch.h b/src/server/game/PrecompiledHeaders/ScriptedPch.h new file mode 100644 index 00000000000..1e83a88b87a --- /dev/null +++ b/src/server/game/PrecompiledHeaders/ScriptedPch.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_PRECOMPILED_H +#define SC_PRECOMPILED_H + +#include "ScriptMgr.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GameEventMgr.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Unit.h" +#include "GameObject.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "ScriptedInstance.h" +#include "CombatAI.h" +#include "PassiveAI.h" +#include "Chat.h" +#include "DBCStructure.h" +#include "DBCStores.h" +#include "ObjectMgr.h" + +#ifdef WIN32 +#include + +#endif + +#endif + diff --git a/src/server/game/Quests/QueryHandler.cpp b/src/server/game/Quests/QueryHandler.cpp deleted file mode 100644 index 1067ad49bc4..00000000000 --- a/src/server/game/Quests/QueryHandler.cpp +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Language.h" -#include "Database/DatabaseEnv.h" -#include "Database/DatabaseImpl.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "UpdateMask.h" -#include "NPCHandler.h" -#include "Pet.h" -#include "MapManager.h" - -void WorldSession::SendNameQueryOpcode(Player *p) -{ - if (!p) - return; - // guess size - WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+10)); - data.append(p->GetPackGUID()); // player guid - data << uint8(0); // added in 3.1 - data << p->GetName(); // played name - data << uint8(0); // realm name for cross realm BG usage - data << uint8(p->getRace()); - data << uint8(p->getGender()); - data << uint8(p->getClass()); - if (DeclinedName const* names = p->GetDeclinedNames()) - { - data << uint8(1); // is declined - for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - data << names->name[i]; - } - else - data << uint8(0); // is not declined - - SendPacket(&data); -} - -void WorldSession::SendNameQueryOpcodeFromDB(uint64 guid) -{ - CharacterDatabase.AsyncPQuery(&WorldSession::SendNameQueryOpcodeFromDBCallBack, GetAccountId(), - !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? - // ------- Query Without Declined Names -------- - // 0 1 2 3 4 - "SELECT guid, name, race, gender, class " - "FROM characters WHERE guid = '%u'" - : - // --------- Query With Declined Names --------- - // 0 1 2 3 4 - "SELECT characters.guid, name, race, gender, class, " - // 5 6 7 8 9 - "genitive, dative, accusative, instrumental, prepositional " - "FROM characters LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid WHERE characters.guid = '%u'", - GUID_LOPART(guid)); -} - -void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, uint32 accountId) -{ - if (!result) - return; - - WorldSession * session = sWorld.FindSession(accountId); - if (!session) - return; - - Field *fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - std::string name = fields[1].GetCppString(); - uint8 pRace = 0, pGender = 0, pClass = 0; - if (name == "") - name = session->GetTrinityString(LANG_NON_EXIST_CHARACTER); - else - { - pRace = fields[2].GetUInt8(); - pGender = fields[3].GetUInt8(); - pClass = fields[4].GetUInt8(); - } - // guess size - WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+1+10)); - data.appendPackGUID(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); - data << uint8(0); // added in 3.1 - data << name; - data << uint8(0); // realm name for cross realm BG usage - data << uint8(pRace); // race - data << uint8(pGender); // gender - data << uint8(pClass); // class - - // if the first declined name field (5) is empty, the rest must be too - if (sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && fields[5].GetCppString() != "") - { - data << uint8(1); // is declined - for (int i = 5; i < MAX_DECLINED_NAME_CASES+5; ++i) - data << fields[i].GetCppString(); - } - else - data << uint8(0); // is not declined - - session->SendPacket(&data); -} - -void WorldSession::HandleNameQueryOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - recv_data >> guid; - - Player *pChar = objmgr.GetPlayer(guid); - - if (pChar) - SendNameQueryOpcode(pChar); - else - SendNameQueryOpcodeFromDB(guid); -} - -void WorldSession::HandleQueryTimeOpcode(WorldPacket & /*recv_data*/) -{ - SendQueryTimeResponse(); -} - -void WorldSession::SendQueryTimeResponse() -{ - WorldPacket data(SMSG_QUERY_TIME_RESPONSE, 4+4); - data << uint32(time(NULL)); - data << uint32(sWorld.GetNextDailyQuestsResetTime() - time(NULL)); - SendPacket(&data); -} - -/// Only _static_ data send in this packet !!! -void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) -{ - uint32 entry; - recv_data >> entry; - uint64 guid; - recv_data >> guid; - - CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); - if (ci) - { - - std::string Name, SubName; - Name = ci->Name; - SubName = ci->SubName; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - CreatureLocale const *cl = objmgr.GetCreatureLocale(entry); - if (cl) - { - if (cl->Name.size() > size_t(loc_idx) && !cl->Name[loc_idx].empty()) - Name = cl->Name[loc_idx]; - if (cl->SubName.size() > size_t(loc_idx) && !cl->SubName[loc_idx].empty()) - SubName = cl->SubName[loc_idx]; - } - } - sLog.outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name, entry); - // guess size - WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); - data << uint32(entry); // creature entry - data << Name; - data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty - data << SubName; - data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 - data << uint32(ci->type_flags); // flags - data << uint32(ci->type); // CreatureType.dbc - data << uint32(ci->family); // CreatureFamily.dbc - data << uint32(ci->rank); // Creature Rank (elite, boss, etc) - data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit - data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit - data << uint32(ci->Modelid1); // Modelid1 - data << uint32(ci->Modelid2); // Modelid2 - data << uint32(ci->Modelid3); // Modelid3 - data << uint32(ci->Modelid4); // Modelid4 - data << float(ci->ModHealth); // dmg/hp modifier - data << float(ci->ModMana); // dmg/mana modifier - data << uint8(ci->RacialLeader); - for (uint32 i = 0; i < 6; ++i) - data << uint32(ci->questItems[i]); // itemId[6], quest drop - data << uint32(ci->movementId); // CreatureMovementInfo.dbc - SendPacket(&data); - sLog.outDebug("WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); - } - else - { - sLog.outDebug("WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)", - GUID_LOPART(guid), entry); - WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 4); - data << uint32(entry | 0x80000000); - SendPacket(&data); - sLog.outDebug("WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); - } -} - -/// Only _static_ data send in this packet !!! -void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) -{ - uint32 entryID; - recv_data >> entryID; - uint64 guid; - recv_data >> guid; - - const GameObjectInfo *info = objmgr.GetGameObjectInfo(entryID); - if (info) - { - std::string Name; - std::string IconName; - std::string CastBarCaption; - - Name = info->name; - IconName = info->IconName; - CastBarCaption = info->castBarCaption; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - GameObjectLocale const *gl = objmgr.GetGameObjectLocale(entryID); - if (gl) - { - if (gl->Name.size() > size_t(loc_idx) && !gl->Name[loc_idx].empty()) - Name = gl->Name[loc_idx]; - if (gl->CastBarCaption.size() > size_t(loc_idx) && !gl->CastBarCaption[loc_idx].empty()) - CastBarCaption = gl->CastBarCaption[loc_idx]; - } - } - sLog.outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name, entryID); - WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150); - data << uint32(entryID); - data << uint32(info->type); - data << uint32(info->displayId); - data << Name; - data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4 - data << IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword) - data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") - data << info->unk1; // 2.0.3, string - data.append(info->raw.data, 24); - data << float(info->size); // go size - for (uint32 i = 0; i < 6; ++i) - data << uint32(info->questItems[i]); // itemId[6], quest drop - SendPacket(&data); - sLog.outDebug("WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); - } - else - { - sLog.outDebug("WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)", - GUID_LOPART(guid), entryID); - WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 4); - data << uint32(entryID | 0x80000000); - SendPacket(&data); - sLog.outDebug("WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); - } -} - -void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDetail("WORLD: Received MSG_CORPSE_QUERY"); - - Corpse *corpse = GetPlayer()->GetCorpse(); - - if (!corpse) - { - WorldPacket data(MSG_CORPSE_QUERY, 1); - data << uint8(0); // corpse not found - SendPacket(&data); - return; - } - - uint32 mapid = corpse->GetMapId(); - float x = corpse->GetPositionX(); - float y = corpse->GetPositionY(); - float z = corpse->GetPositionZ(); - uint32 corpsemapid = mapid; - - // if corpse at different map - if (mapid != _player->GetMapId()) - { - // search entrance map for proper show entrance - if (MapEntry const* corpseMapEntry = sMapStore.LookupEntry(mapid)) - { - if (corpseMapEntry->IsDungeon() && corpseMapEntry->entrance_map >= 0) - { - // if corpse map have entrance - if (Map const* entranceMap = MapManager::Instance().CreateBaseMap(corpseMapEntry->entrance_map)) - { - mapid = corpseMapEntry->entrance_map; - x = corpseMapEntry->entrance_x; - y = corpseMapEntry->entrance_y; - z = entranceMap->GetHeight(x, y, MAX_HEIGHT); - } - } - } - } - - WorldPacket data(MSG_CORPSE_QUERY, 1+(6*4)); - data << uint8(1); // corpse found - data << int32(mapid); - data << float(x); - data << float(y); - data << float(z); - data << int32(corpsemapid); - data << uint32(0); // unknown - SendPacket(&data); -} - -void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) -{ - uint32 textID; - uint64 guid; - - recv_data >> textID; - sLog.outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); - - recv_data >> guid; - GetPlayer()->SetUInt64Value(UNIT_FIELD_TARGET, guid); - - GossipText const* pGossip = objmgr.GetGossipText(textID); - - WorldPacket data(SMSG_NPC_TEXT_UPDATE, 100); // guess size - data << textID; - - if (!pGossip) - { - for (uint32 i = 0; i < 8; ++i) - { - data << float(0); - data << "Greetings $N"; - data << "Greetings $N"; - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - } - } - else - { - std::string Text_0[8], Text_1[8]; - for (int i = 0; i < 8; ++i) - { - Text_0[i]=pGossip->Options[i].Text_0; - Text_1[i]=pGossip->Options[i].Text_1; - } - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - NpcTextLocale const *nl = objmgr.GetNpcTextLocale(textID); - if (nl) - { - for (int i = 0; i < 8; ++i) - { - if (nl->Text_0[i].size() > size_t(loc_idx) && !nl->Text_0[i][loc_idx].empty()) - Text_0[i]=nl->Text_0[i][loc_idx]; - if (nl->Text_1[i].size() > size_t(loc_idx) && !nl->Text_1[i][loc_idx].empty()) - Text_1[i]=nl->Text_1[i][loc_idx]; - } - } - } - - for (int i = 0; i < 8; ++i) - { - data << pGossip->Options[i].Probability; - - if (Text_0[i].empty()) - data << Text_1[i]; - else - data << Text_0[i]; - - if (Text_1[i].empty()) - data << Text_0[i]; - else - data << Text_1[i]; - - data << pGossip->Options[i].Language; - - for (int j = 0; j < 3; ++j) - { - data << pGossip->Options[i].Emotes[j]._Delay; - data << pGossip->Options[i].Emotes[j]._Emote; - } - } - } - - SendPacket(&data); - - sLog.outDebug("WORLD: Sent SMSG_NPC_TEXT_UPDATE"); -} - -void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data) -{ - sLog.outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY"); - recv_data.hexlike(); - - uint32 pageID; - recv_data >> pageID; - recv_data.read_skip(); // guid - - while (pageID) - { - PageText const *pPage = sPageTextStore.LookupEntry(pageID); - // guess size - WorldPacket data(SMSG_PAGE_TEXT_QUERY_RESPONSE, 50); - data << pageID; - - if (!pPage) - { - data << "Item page missing."; - data << uint32(0); - pageID = 0; - } - else - { - std::string Text = pPage->Text; - - int loc_idx = GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - PageTextLocale const *pl = objmgr.GetPageTextLocale(pageID); - if (pl) - { - if (pl->Text.size() > size_t(loc_idx) && !pl->Text[loc_idx].empty()) - Text = pl->Text[loc_idx]; - } - } - - data << Text; - data << uint32(pPage->Next_Page); - pageID = pPage->Next_Page; - } - SendPacket(&data); - - sLog.outDebug("WORLD: Sent SMSG_PAGE_TEXT_QUERY_RESPONSE"); - } -} - -void WorldSession::HandleCorpseMapPositionQuery(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: Recv CMSG_CORPSE_MAP_POSITION_QUERY"); - - uint32 unk; - recv_data >> unk; - - WorldPacket data(SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE, 4+4+4+4); - data << float(0); - data << float(0); - data << float(0); - data << float(0); - SendPacket(&data); -} - -void WorldSession::HandleQuestPOIQuery(WorldPacket& recv_data) -{ - uint32 count; - recv_data >> count; // quest count, max=25 - - if (count >= MAX_QUEST_LOG_SIZE) - return; - - WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4+(4+4)*count); - data << uint32(count); // count - - for (int i = 0; i < count; ++i) - { - uint32 questId; - recv_data >> questId; // quest id - - bool questOk = false; - - uint16 questSlot = _player->FindQuestSlot(questId); - - if (questSlot != MAX_QUEST_LOG_SIZE) - questOk =_player->GetQuestSlotQuestId(questSlot) == questId; - - if (questOk) - { - QuestPOIVector const *POI = objmgr.GetQuestPOIVector(questId); - - if (POI) - { - data << uint32(questId); // quest ID - data << uint32(POI->size()); // POI count - - for (QuestPOIVector::const_iterator itr = POI->begin(); itr != POI->end(); ++itr) - { - data << uint32(itr->Id); // POI index - data << int32(itr->ObjectiveIndex); // objective index - data << uint32(itr->MapId); // mapid - data << uint32(itr->AreaId); // areaid - data << uint32(itr->Unk2); // unknown - data << uint32(itr->Unk3); // unknown - data << uint32(itr->Unk4); // unknown - data << uint32(itr->points.size()); // POI points count - - for (std::vector::const_iterator itr2 = itr->points.begin(); itr2 != itr->points.end(); ++itr2) - { - data << int32(itr2->x); // POI point x - data << int32(itr2->y); // POI point y - } - } - } - else - { - data << uint32(questId); // quest ID - data << uint32(0); // POI count - } - } - else - { - data << uint32(questId); // quest ID - data << uint32(0); // POI count - } - } - - SendPacket(&data); -} \ No newline at end of file diff --git a/src/server/game/Quests/QuestHandler.cpp b/src/server/game/Quests/QuestHandler.cpp deleted file mode 100644 index 8043f5ed149..00000000000 --- a/src/server/game/Quests/QuestHandler.cpp +++ /dev/null @@ -1,721 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Log.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "World.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "GossipDef.h" -#include "QuestDef.h" -#include "ObjectAccessor.h" -#include "Group.h" -#include "BattleGround.h" -#include "BattleGroundAV.h" -#include "ScriptMgr.h" - -void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - uint8 questStatus = DIALOG_STATUS_NONE; - uint8 defstatus = DIALOG_STATUS_NONE; - - Object* questgiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - if (!questgiver) - { - sLog.outDetail("Error in CMSG_QUESTGIVER_STATUS_QUERY, called for not found questgiver (Typeid: %u GUID: %u)",GuidHigh2TypeId(GUID_HIPART(guid)),GUID_LOPART(guid)); - return; - } - - switch(questgiver->GetTypeId()) - { - case TYPEID_UNIT: - { - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u",uint32(GUID_LOPART(guid))); - Creature* cr_questgiver=questgiver->ToCreature(); - if (!cr_questgiver->IsHostileTo(_player)) // not show quest status to enemies - { - questStatus = sScriptMgr.NPCDialogStatus(_player, cr_questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, cr_questgiver, defstatus); - } - break; - } - case TYPEID_GAMEOBJECT: - { - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u",uint32(GUID_LOPART(guid))); - GameObject* go_questgiver=(GameObject*)questgiver; - questStatus = sScriptMgr.GODialogStatus(_player, go_questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, go_questgiver, defstatus); - break; - } - default: - sLog.outError("QuestGiver called for unexpected type %u", questgiver->GetTypeId()); - break; - } - - //inform client about status of quest - _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid); -} - -void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - sLog.outDebug ("WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); - - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_NONE); - if (!pCreature) - { - sLog.outDebug ("WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", - GUID_LOPART(guid)); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - // Stop the npc if moving - pCreature->StopMoving(); - - if (sScriptMgr.GossipHello(_player, pCreature)) - return; - - _player->PrepareGossipMenu(pCreature, pCreature->GetCreatureInfo()->GossipMenuId, true); - _player->SendPreparedGossip(pCreature); -} - -void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket & recv_data) -{ - uint64 guid; - uint32 quest; - uint32 unk1; - recv_data >> guid >> quest >> unk1; - - if (!GetPlayer()->isAlive()) - return; - - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), quest, unk1); - - Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT|TYPEMASK_ITEM|TYPEMASK_PLAYER); - - // no or incorrect quest giver - if (!pObject - || (pObject->GetTypeId() != TYPEID_PLAYER && !pObject->hasQuest(quest)) - || (pObject->GetTypeId() == TYPEID_PLAYER && !pObject->ToPlayer()->CanShareQuest(quest)) -) - { - _player->PlayerTalkClass->CloseGossip(); - _player->SetDivider(0); - return; - } - - Quest const* qInfo = objmgr.GetQuestTemplate(quest); - if (qInfo) - { - // prevent cheating - if (!GetPlayer()->CanTakeQuest(qInfo,true)) - { - _player->PlayerTalkClass->CloseGossip(); - _player->SetDivider(0); - return; - } - - if (_player->GetDivider() != 0) - { - Player *pPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); - if (pPlayer) - { - pPlayer->SendPushToPartyResponse(_player, QUEST_PARTY_MSG_ACCEPT_QUEST); - _player->SetDivider(0); - } - } - - if (_player->CanAddQuest(qInfo, true)) - { - _player->AddQuest(qInfo, pObject); - - if (qInfo->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) - { - if (Group* pGroup = _player->GetGroup()) - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* pPlayer = itr->getSource(); - - if (!pPlayer || pPlayer == _player) // not self - continue; - - if (pPlayer->CanTakeQuest(qInfo, true)) - { - pPlayer->SetDivider(_player->GetGUID()); - - //need confirmation that any gossip window will close - pPlayer->PlayerTalkClass->CloseGossip(); - - _player->SendQuestConfirmAccept(qInfo, pPlayer); - } - } - } - } - - if (_player->CanCompleteQuest(quest)) - _player->CompleteQuest(quest); - - switch(pObject->GetTypeId()) - { - case TYPEID_UNIT: - sScriptMgr.QuestAccept(_player, (pObject->ToCreature()), qInfo); - break; - case TYPEID_ITEM: - case TYPEID_CONTAINER: - { - sScriptMgr.ItemQuestAccept(_player, ((Item*)pObject), qInfo); - - // destroy not required for quest finish quest starting item - bool destroyItem = true; - for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) - { - if ((qInfo->ReqItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetProto()->MaxCount > 0)) - { - destroyItem = false; - break; - } - } - - if (destroyItem) - _player->DestroyItem(((Item*)pObject)->GetBagSlot(),((Item*)pObject)->GetSlot(),true); - - break; - } - case TYPEID_GAMEOBJECT: - sScriptMgr.GOQuestAccept(_player, ((GameObject*)pObject), qInfo); - break; - } - _player->PlayerTalkClass->CloseGossip(); - - if (qInfo->GetSrcSpell() > 0) - _player->CastSpell(_player, qInfo->GetSrcSpell(), true); - - return; - } - } - - _player->PlayerTalkClass->CloseGossip(); -} - -void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPacket & recv_data) -{ - uint64 guid; - uint32 quest; - uint8 unk1; - recv_data >> guid >> quest >> unk1; - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_QUERY_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), quest, unk1); - - // Verify that the guid is valid and is a questgiver or involved in the requested quest - Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT|TYPEMASK_ITEM); - if (!pObject||!pObject->hasQuest(quest) && !pObject->hasInvolvedQuest(quest)) - { - _player->PlayerTalkClass->CloseGossip(); - return; - } - - Quest const* pQuest = objmgr.GetQuestTemplate(quest); - if (pQuest) - { - if (pQuest->HasFlag(QUEST_FLAGS_AUTO_ACCEPT) && _player->CanAddQuest(pQuest, true)) - { - _player->AddQuest(pQuest, pObject); - if (_player->CanCompleteQuest(quest)) - _player->CompleteQuest(quest); - } - - if (pQuest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE)) - _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, pObject->GetGUID(), _player->CanCompleteQuest(pQuest->GetQuestId()), true); - else - _player->PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, pObject->GetGUID(), true); - } -} - -void WorldSession::HandleQuestQueryOpcode(WorldPacket & recv_data) -{ - uint32 quest; - recv_data >> quest; - sLog.outDebug("WORLD: Received CMSG_QUEST_QUERY quest = %u",quest); - - Quest const *pQuest = objmgr.GetQuestTemplate(quest); - if (pQuest) - { - _player->PlayerTalkClass->SendQuestQueryResponse(pQuest); - } -} - -void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) -{ - uint32 quest, reward; - uint64 guid; - recv_data >> guid >> quest >> reward; - - if (reward >= QUEST_REWARD_CHOICES_COUNT) - { - sLog.outError("Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (probably packet hacking)", _player->GetName(), _player->GetGUIDLow(), reward); - return; - } - - if (!GetPlayer()->isAlive()) - return; - - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %u, quest = %u, reward = %u",uint32(GUID_LOPART(guid)),quest,reward); - - Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - if (!pObject) - return; - - if (!pObject->hasInvolvedQuest(quest)) - return; - - Quest const *pQuest = objmgr.GetQuestTemplate(quest); - if (pQuest) - { - if (_player->CanRewardQuest(pQuest, reward, true)) - { - _player->RewardQuest(pQuest, reward, pObject); - - switch(pObject->GetTypeId()) - { - case TYPEID_UNIT: - if (!(sScriptMgr.ChooseReward(_player, (pObject->ToCreature()), pQuest, reward))) - { - // Send next quest - if (Quest const* nextquest = _player->GetNextQuest(guid ,pQuest)) - _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextquest,guid,true); - } - break; - case TYPEID_GAMEOBJECT: - if (!sScriptMgr.GOChooseReward(_player, ((GameObject*)pObject), pQuest, reward)) - { - // Send next quest - if (Quest const* nextquest = _player->GetNextQuest(guid ,pQuest)) - _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextquest,guid,true); - } - break; - } - } - else - _player->PlayerTalkClass->SendQuestGiverOfferReward(pQuest, guid, true); - } -} - -void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket & recv_data) -{ - uint32 quest; - uint64 guid; - recv_data >> guid >> quest; - - if (!GetPlayer()->isAlive()) - return; - - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_REQUEST_REWARD npc = %u, quest = %u",uint32(GUID_LOPART(guid)),quest); - - Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); - if (!pObject||!pObject->hasInvolvedQuest(quest)) - return; - - if (_player->CanCompleteQuest(quest)) - _player->CompleteQuest(quest); - - if (_player->GetQuestStatus(quest) != QUEST_STATUS_COMPLETE) - return; - - if (Quest const *pQuest = objmgr.GetQuestTemplate(quest)) - _player->PlayerTalkClass->SendQuestGiverOfferReward(pQuest, guid, true); -} - -void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recv_data*/) -{ - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_CANCEL"); - - _player->PlayerTalkClass->CloseGossip(); -} - -void WorldSession::HandleQuestLogSwapQuest(WorldPacket& recv_data) -{ - uint8 slot1, slot2; - recv_data >> slot1 >> slot2; - - if (slot1 == slot2 || slot1 >= MAX_QUEST_LOG_SIZE || slot2 >= MAX_QUEST_LOG_SIZE) - return; - - sLog.outDebug("WORLD: Received CMSG_QUESTLOG_SWAP_QUEST slot 1 = %u, slot 2 = %u", slot1, slot2); - - GetPlayer()->SwapQuestSlot(slot1,slot2); -} - -void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) -{ - uint8 slot; - recv_data >> slot; - - sLog.outDebug("WORLD: Received CMSG_QUESTLOG_REMOVE_QUEST slot = %u",slot); - - if (slot < MAX_QUEST_LOG_SIZE) - { - if (uint32 quest = _player->GetQuestSlotQuestId(slot)) - { - if (!_player->TakeQuestSourceItem(quest, true)) - return; // can't un-equip some items, reject quest cancel - - if (const Quest *pQuest = objmgr.GetQuestTemplate(quest)) - { - if (pQuest->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) - _player->RemoveTimedQuest(quest); - } - - _player->TakeQuestSourceItem(quest, true); // remove quest src item from player - _player->SetQuestStatus(quest, QUEST_STATUS_NONE); - _player->GetAchievementMgr().RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest); - } - - _player->SetQuestSlot(slot, 0); - - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1); - } -} - -void WorldSession::HandleQuestConfirmAccept(WorldPacket& recv_data) -{ - uint32 quest; - recv_data >> quest; - - sLog.outDebug("WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = %u", quest); - - if (const Quest* pQuest = objmgr.GetQuestTemplate(quest)) - { - if (!pQuest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) - return; - - Player* pOriginalPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); - - if (!pOriginalPlayer) - return; - - if (pQuest->GetType() == QUEST_TYPE_RAID) - { - if (!_player->IsInSameRaidWith(pOriginalPlayer)) - return; - } - else - { - if (!_player->IsInSameGroupWith(pOriginalPlayer)) - return; - } - - if (_player->CanAddQuest(pQuest, true)) - _player->AddQuest(pQuest, NULL); // NULL, this prevent DB script from duplicate running - - _player->SetDivider(0); - } -} - -void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recv_data) -{ - uint32 quest; - uint64 guid; - recv_data >> guid >> quest; - - if (!GetPlayer()->isAlive()) - return; - - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, quest = %u",uint32(GUID_LOPART(guid)),quest); - - Quest const *pQuest = objmgr.GetQuestTemplate(quest); - if (pQuest) - { - // TODO: need a virtual function - if (GetPlayer()->InBattleGround()) - if (BattleGround* bg = GetPlayer()->GetBattleGround()) - if (bg->GetTypeID() == BATTLEGROUND_AV) - ((BattleGroundAV*)bg)->HandleQuestComplete(quest, GetPlayer()); - - if (_player->GetQuestStatus(quest) != QUEST_STATUS_COMPLETE) - { - if (pQuest->IsRepeatable()) - _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanCompleteRepeatableQuest(pQuest), false); - else - _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanRewardQuest(pQuest,false), false); - } - else - { - if (pQuest->GetReqItemsCount()) // some items required - _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanRewardQuest(pQuest,false), false); - else // no items required - _player->PlayerTalkClass->SendQuestGiverOfferReward(pQuest, guid, true); - } - } -} - -void WorldSession::HandleQuestgiverQuestAutoLaunch(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_QUEST_AUTOLAUNCH"); -} - -void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) -{ - uint32 questId; - recvPacket >> questId; - - sLog.outDebug("WORLD: Received CMSG_PUSHQUESTTOPARTY quest = %u", questId); - - if (Quest const *pQuest = objmgr.GetQuestTemplate(questId)) - { - if (Group* pGroup = _player->GetGroup()) - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player *pPlayer = itr->getSource(); - - if (!pPlayer || pPlayer == _player) // skip self - continue; - - _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST); - - if (!pPlayer->SatisfyQuestStatus(pQuest, false)) - { - _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_HAVE_QUEST); - continue; - } - - if (pPlayer->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE) - { - _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_FINISH_QUEST); - continue; - } - - if (!pPlayer->CanTakeQuest(pQuest, false)) - { - _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_CANT_TAKE_QUEST); - continue; - } - - if (!pPlayer->SatisfyQuestLog(false)) - { - _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_LOG_FULL); - continue; - } - - if (pPlayer->GetDivider() != 0) - { - _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_BUSY); - continue; - } - - pPlayer->PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, _player->GetGUID(), true); - pPlayer->SetDivider(_player->GetGUID()); - } - } - } -} - -void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) -{ - uint64 guid; - uint8 msg; - recvPacket >> guid >> msg; - - sLog.outDebug("WORLD: Received MSG_QUEST_PUSH_RESULT"); - - if (_player->GetDivider() != 0) - { - Player *pPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); - if (pPlayer) - { - WorldPacket data(MSG_QUEST_PUSH_RESULT, (8+1)); - data << uint64(guid); - data << uint8(msg); // valid values: 0-8 - pPlayer->GetSession()->SendPacket(&data); - _player->SetDivider(0); - } - } -} - -uint32 WorldSession::getDialogStatus(Player *pPlayer, Object* questgiver, uint32 defstatus) -{ - uint32 result = defstatus; - - QuestRelations const* qir; - QuestRelations const* qr; - - switch(questgiver->GetTypeId()) - { - case TYPEID_GAMEOBJECT: - { - qir = &objmgr.mGOQuestInvolvedRelations; - qr = &objmgr.mGOQuestRelations; - break; - } - case TYPEID_UNIT: - { - qir = &objmgr.mCreatureQuestInvolvedRelations; - qr = &objmgr.mCreatureQuestRelations; - break; - } - default: - //its imposible, but check ^) - sLog.outError("Warning: GetDialogStatus called for unexpected type %u", questgiver->GetTypeId()); - return DIALOG_STATUS_NONE; - } - - for (QuestRelations::const_iterator i = qir->lower_bound(questgiver->GetEntry()); i != qir->upper_bound(questgiver->GetEntry()); ++i) - { - uint32 result2 = 0; - uint32 quest_id = i->second; - Quest const *pQuest = objmgr.GetQuestTemplate(quest_id); - if (!pQuest) continue; - - QuestStatus status = pPlayer->GetQuestStatus(quest_id); - if ((status == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(quest_id)) || - (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false))) - { - if (pQuest->IsAutoComplete() && pQuest->IsRepeatable()) - result2 = DIALOG_STATUS_REWARD_REP; - else - result2 = DIALOG_STATUS_REWARD; - } - else if (status == QUEST_STATUS_INCOMPLETE) - result2 = DIALOG_STATUS_INCOMPLETE; - - if (result2 > result) - result = result2; - } - - for (QuestRelations::const_iterator i = qr->lower_bound(questgiver->GetEntry()); i != qr->upper_bound(questgiver->GetEntry()); ++i) - { - uint32 result2 = 0; - uint32 quest_id = i->second; - Quest const *pQuest = objmgr.GetQuestTemplate(quest_id); - if (!pQuest) - continue; - - QuestStatus status = pPlayer->GetQuestStatus(quest_id); - if (status == QUEST_STATUS_NONE) - { - if (pPlayer->CanSeeStartQuest(pQuest)) - { - if (pPlayer->SatisfyQuestLevel(pQuest, false)) - { - if (pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && pPlayer->getQuestStatusMap()[quest_id].m_rewarded)) - result2 = DIALOG_STATUS_REWARD_REP; - else if (pPlayer->getLevel() <= ((pPlayer->GetQuestLevel(pQuest) == -1) ? pPlayer->getLevel() : pPlayer->GetQuestLevel(pQuest) + sWorld.getConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) - { - if (pQuest->HasFlag(QUEST_FLAGS_DAILY) || pQuest->HasFlag(QUEST_FLAGS_WEEKLY)) - result2 = DIALOG_STATUS_AVAILABLE_REP; - else - result2 = DIALOG_STATUS_AVAILABLE; - } - else - result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE; - } - else - result2 = DIALOG_STATUS_UNAVAILABLE; - } - } - - if (result2 > result) - result = result2; - } - - return result; -} - -void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket*/) -{ - sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY"); - - uint32 count = 0; - - WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4); - data << uint32(count); // placeholder - - for (Player::ClientGUIDs::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr) - { - uint8 questStatus = DIALOG_STATUS_NONE; - uint8 defstatus = DIALOG_STATUS_NONE; - - if (IS_CRE_OR_VEH_OR_PET_GUID(*itr)) - { - // need also pet quests case support - Creature *questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(),*itr); - if (!questgiver || questgiver->IsHostileTo(_player)) - continue; - if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) - continue; - questStatus = sScriptMgr.NPCDialogStatus(_player, questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, questgiver, defstatus); - - data << uint64(questgiver->GetGUID()); - data << uint8(questStatus); - ++count; - } - else if (IS_GAMEOBJECT_GUID(*itr)) - { - GameObject *questgiver = GetPlayer()->GetMap()->GetGameObject(*itr); - if (!questgiver) - continue; - if (questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) - continue; - questStatus = sScriptMgr.GODialogStatus(_player, questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, questgiver, defstatus); - - data << uint64(questgiver->GetGUID()); - data << uint8(questStatus); - ++count; - } - } - - data.put(0, count); // write real count - SendPacket(&data); -} - -void WorldSession::HandleQueryQuestsCompleted(WorldPacket & /*recv_data*/) -{ - uint32 count = 0; - - WorldPacket data(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, 4+4*count); - data << uint32(count); - - for (QuestStatusMap::const_iterator itr = _player->getQuestStatusMap().begin(); itr != _player->getQuestStatusMap().end(); ++itr) - { - if (itr->second.m_rewarded) - { - data << uint32(itr->first); - count++; - } - } - data.put(0, count); - SendPacket(&data); -} diff --git a/src/server/game/ScriptMgr/ScriptLoader.cpp b/src/server/game/ScriptMgr/ScriptLoader.cpp deleted file mode 100644 index 2006c091287..00000000000 --- a/src/server/game/ScriptMgr/ScriptLoader.cpp +++ /dev/null @@ -1,1023 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" - -#ifdef WIN32 - #define DO_SCRIPTS -#endif - -#ifdef DO_SCRIPTS -//custom - -//examples -void AddSC_example_creature(); -void AddSC_example_escort(); -void AddSC_example_gossip_codebox(); -void AddSC_example_misc(); - -//world -void AddSC_areatrigger_scripts(); -void AddSC_boss_emeriss(); -void AddSC_boss_taerar(); -void AddSC_boss_ysondre(); -void AddSC_generic_creature(); -void AddSC_go_scripts(); -void AddSC_guards(); -void AddSC_item_scripts(); -void AddSC_npc_professions(); -void AddSC_npc_innkeeper(); -void AddSC_npcs_special(); -void AddSC_npc_taxi(); - -//eastern kingdoms -void AddSC_alterac_valley(); //Alterac Valley -void AddSC_boss_balinda(); -void AddSC_boss_drekthar(); -void AddSC_boss_galvangar(); -void AddSC_boss_vanndar(); -void AddSC_blackrock_depths(); //Blackrock Depths -void AddSC_boss_ambassador_flamelash(); -void AddSC_boss_anubshiah(); -void AddSC_boss_draganthaurissan(); -void AddSC_boss_general_angerforge(); -void AddSC_boss_gorosh_the_dervish(); -void AddSC_boss_grizzle(); -void AddSC_boss_high_interrogator_gerstahn(); -void AddSC_boss_magmus(); -void AddSC_boss_moira_bronzebeard(); -void AddSC_boss_tomb_of_seven(); -void AddSC_instance_blackrock_depths(); -void AddSC_blackrock_spire(); //Blackrock Spire -void AddSC_boss_drakkisath(); -void AddSC_boss_halycon(); -void AddSC_boss_highlordomokk(); -void AddSC_boss_mothersmolderweb(); -void AddSC_boss_overlordwyrmthalak(); -void AddSC_boss_shadowvosh(); -void AddSC_boss_thebeast(); -void AddSC_boss_warmastervoone(); -void AddSC_boss_quatermasterzigris(); -void AddSC_boss_pyroguard_emberseer(); -void AddSC_boss_gyth(); -void AddSC_boss_rend_blackhand(); -void AddSC_instance_blackrock_spire(); -void AddSC_boss_razorgore(); //Blackwing lair -void AddSC_boss_vael(); -void AddSC_boss_broodlord(); -void AddSC_boss_firemaw(); -void AddSC_boss_ebonroc(); -void AddSC_boss_flamegor(); -void AddSC_boss_chromaggus(); -void AddSC_boss_nefarian(); -void AddSC_boss_victor_nefarius(); -void AddSC_boss_mr_smite(); -void AddSC_deadmines(); //Deadmines -void AddSC_instance_deadmines(); -void AddSC_gnomeregan(); //Gnomeregan -void AddSC_instance_gnomeregan(); -void AddSC_boss_attumen(); //Karazhan -void AddSC_boss_curator(); -void AddSC_boss_maiden_of_virtue(); -void AddSC_boss_shade_of_aran(); -void AddSC_boss_malchezaar(); -void AddSC_boss_terestian_illhoof(); -void AddSC_boss_moroes(); -void AddSC_bosses_opera(); -void AddSC_boss_netherspite(); -void AddSC_instance_karazhan(); -void AddSC_karazhan(); -void AddSC_boss_nightbane(); -void AddSC_boss_felblood_kaelthas(); // Magister's Terrace -void AddSC_boss_selin_fireheart(); -void AddSC_boss_vexallus(); -void AddSC_boss_priestess_delrissa(); -void AddSC_instance_magisters_terrace(); -void AddSC_magisters_terrace(); -void AddSC_boss_lucifron(); //Molten core -void AddSC_boss_magmadar(); -void AddSC_boss_gehennas(); -void AddSC_boss_garr(); -void AddSC_boss_baron_geddon(); -void AddSC_boss_shazzrah(); -void AddSC_boss_golemagg(); -void AddSC_boss_sulfuron(); -void AddSC_boss_majordomo(); -void AddSC_boss_ragnaros(); -void AddSC_instance_molten_core(); -void AddSC_molten_core(); -void AddSC_the_scarlet_enclave(); //Scarlet Enclave -void AddSC_the_scarlet_enclave_c1(); -void AddSC_the_scarlet_enclave_c2(); -void AddSC_the_scarlet_enclave_c5(); -void AddSC_boss_arcanist_doan(); //Scarlet Monastery -void AddSC_boss_azshir_the_sleepless(); -void AddSC_boss_bloodmage_thalnos(); -void AddSC_boss_headless_horseman(); -void AddSC_boss_herod(); -void AddSC_boss_high_inquisitor_fairbanks(); -void AddSC_boss_houndmaster_loksey(); -void AddSC_boss_interrogator_vishas(); -void AddSC_boss_scorn(); -void AddSC_instance_scarlet_monastery(); -void AddSC_boss_mograine_and_whitemane(); -void AddSC_boss_darkmaster_gandling(); //Scholomance -void AddSC_boss_death_knight_darkreaver(); -void AddSC_boss_theolenkrastinov(); -void AddSC_boss_illuciabarov(); -void AddSC_boss_instructormalicia(); -void AddSC_boss_jandicebarov(); -void AddSC_boss_kormok(); -void AddSC_boss_lordalexeibarov(); -void AddSC_boss_lorekeeperpolkelt(); -void AddSC_boss_rasfrost(); -void AddSC_boss_theravenian(); -void AddSC_boss_vectus(); -void AddSC_instance_scholomance(); -void AddSC_shadowfang_keep(); //Shadowfang keep -void AddSC_instance_shadowfang_keep(); -void AddSC_boss_magistrate_barthilas(); //Stratholme -void AddSC_boss_maleki_the_pallid(); -void AddSC_boss_nerubenkan(); -void AddSC_boss_cannon_master_willey(); -void AddSC_boss_baroness_anastari(); -void AddSC_boss_ramstein_the_gorger(); -void AddSC_boss_timmy_the_cruel(); -void AddSC_boss_postmaster_malown(); -void AddSC_boss_baron_rivendare(); -void AddSC_boss_dathrohan_balnazzar(); -void AddSC_boss_order_of_silver_hand(); -void AddSC_instance_stratholme(); -void AddSC_stratholme(); -void AddSC_sunken_temple(); // Sunken Temple -void AddSC_instance_sunken_temple(); -void AddSC_instance_sunwell_plateau(); //Sunwell Plateau -void AddSC_boss_kalecgos(); -void AddSC_boss_brutallus(); -void AddSC_boss_felmyst(); -void AddSC_boss_eredar_twins(); -void AddSC_boss_muru(); -void AddSC_boss_kiljaeden(); -void AddSC_sunwell_plateau(); -void AddSC_boss_archaedas(); //Uldaman -void AddSC_boss_ironaya(); -void AddSC_uldaman(); -void AddSC_instance_uldaman(); -void AddSC_boss_akilzon(); //Zul'Aman -void AddSC_boss_halazzi(); -void AddSC_boss_hex_lord_malacrass(); -void AddSC_boss_janalai(); -void AddSC_boss_nalorakk(); -void AddSC_boss_zuljin(); -void AddSC_instance_zulaman(); -void AddSC_zulaman(); -void AddSC_boss_jeklik(); //Zul'Gurub -void AddSC_boss_venoxis(); -void AddSC_boss_marli(); -void AddSC_boss_mandokir(); -void AddSC_boss_gahzranka(); -void AddSC_boss_thekal(); -void AddSC_boss_arlokk(); -void AddSC_boss_jindo(); -void AddSC_boss_hakkar(); -void AddSC_boss_grilek(); -void AddSC_boss_hazzarah(); -void AddSC_boss_renataki(); -void AddSC_boss_wushoolay(); -void AddSC_instance_zulgurub(); - -//void AddSC_alterac_mountains(); -void AddSC_arathi_highlands(); -void AddSC_blasted_lands(); -void AddSC_boss_kruul(); -void AddSC_burning_steppes(); -void AddSC_dun_morogh(); -void AddSC_duskwood(); -void AddSC_eastern_plaguelands(); -void AddSC_elwynn_forest(); -void AddSC_eversong_woods(); -void AddSC_ghostlands(); -void AddSC_hinterlands(); -void AddSC_ironforge(); -void AddSC_isle_of_queldanas(); -void AddSC_loch_modan(); -void AddSC_redridge_mountains(); -void AddSC_searing_gorge(); -void AddSC_silvermoon_city(); -void AddSC_silverpine_forest(); -void AddSC_stormwind_city(); -void AddSC_stranglethorn_vale(); -void AddSC_tirisfal_glades(); -void AddSC_undercity(); -void AddSC_western_plaguelands(); -void AddSC_westfall(); -void AddSC_wetlands(); - -//kalimdor -void AddSC_blackfathom_deeps(); //Blackfathom Depths -void AddSC_boss_gelihast(); -void AddSC_boss_kelris(); -void AddSC_boss_aku_mai(); -void AddSC_instance_blackfathom_deeps(); -void AddSC_hyjal(); //CoT Battle for Mt. Hyjal -void AddSC_boss_archimonde(); -void AddSC_instance_mount_hyjal(); -void AddSC_hyjal_trash(); -void AddSC_boss_rage_winterchill(); -void AddSC_boss_anetheron(); -void AddSC_boss_kazrogal(); -void AddSC_boss_azgalor(); -void AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad -void AddSC_boss_epoch_hunter(); -void AddSC_boss_lieutenant_drake(); -void AddSC_instance_old_hillsbrad(); -void AddSC_old_hillsbrad(); -void AddSC_boss_aeonus(); //CoT The Dark Portal -void AddSC_boss_chrono_lord_deja(); -void AddSC_boss_temporus(); -void AddSC_dark_portal(); -void AddSC_instance_dark_portal(); -void AddSC_boss_epoch(); //CoT Culling Of Stratholme -void AddSC_boss_infinite_corruptor(); -void AddSC_boss_salramm(); -void AddSC_boss_mal_ganis(); -void AddSC_boss_meathook(); -void AddSC_culling_of_stratholme(); -void AddSC_instance_culling_of_stratholme(); -void AddSC_boss_celebras_the_cursed(); //Maraudon -void AddSC_boss_landslide(); -void AddSC_boss_noxxion(); -void AddSC_boss_ptheradras(); -void AddSC_boss_onyxia(); //Onyxia's Lair -void AddSC_instance_onyxias_lair(); -void AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs -void AddSC_razorfen_downs(); -void AddSC_instance_razorfen_downs(); -void AddSC_razorfen_kraul(); //Razorfen Kraul -void AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj -void AddSC_boss_rajaxx(); -void AddSC_boss_moam(); -void AddSC_boss_buru(); -void AddSC_boss_ayamiss(); -void AddSC_boss_ossirian(); -void AddSC_instance_ruins_of_ahnqiraj(); -void AddSC_boss_cthun(); //Temple of ahn'qiraj -void AddSC_boss_fankriss(); -void AddSC_boss_huhuran(); -void AddSC_bug_trio(); -void AddSC_boss_sartura(); -void AddSC_boss_skeram(); -void AddSC_boss_twinemperors(); -void AddSC_mob_anubisath_sentinel(); -void AddSC_instance_temple_of_ahnqiraj(); -void AddSC_wailing_caverns(); //Wailing caverns -void AddSC_instance_wailing_caverns(); -void AddSC_zulfarrak(); //Zul'Farrak generic -void AddSC_instance_zulfarrak(); //Zul'Farrak instance script - -void AddSC_ashenvale(); -void AddSC_azshara(); -void AddSC_azuremyst_isle(); -void AddSC_bloodmyst_isle(); -void AddSC_boss_azuregos(); -void AddSC_darkshore(); -void AddSC_desolace(); -void AddSC_durotar(); -void AddSC_dustwallow_marsh(); -void AddSC_felwood(); -void AddSC_feralas(); -void AddSC_moonglade(); -void AddSC_mulgore(); -void AddSC_orgrimmar(); -void AddSC_silithus(); -void AddSC_stonetalon_mountains(); -void AddSC_tanaris(); -void AddSC_teldrassil(); -void AddSC_the_barrens(); -void AddSC_thousand_needles(); -void AddSC_thunder_bluff(); -void AddSC_ungoro_crater(); -void AddSC_winterspring(); - -//northrend -void AddSC_boss_slad_ran(); -void AddSC_boss_moorabi(); -void AddSC_boss_drakkari_colossus(); -void AddSC_boss_gal_darah(); -void AddSC_boss_eck(); -void AddSC_instance_gundrak(); -void AddSC_boss_krik_thir(); //Azjol-Nerub -void AddSC_boss_hadronox(); -void AddSC_boss_anub_arak(); -void AddSC_instance_azjol_nerub(); -void AddSC_instance_ahnkahet(); //Azjol-Nerub Ahn'kahet -void AddSC_boss_amanitar(); -void AddSC_boss_taldaram(); -void AddSC_boss_jedoga_shadowseeker(); -void AddSC_boss_elder_nadox(); -void AddSC_boss_volazj(); -void AddSC_boss_argent_challenge(); //Trial of the Champion -void AddSC_boss_black_knight(); -void AddSC_boss_grand_champions(); -void AddSC_instance_trial_of_the_champion(); -void AddSC_trial_of_the_champion(); -void AddSC_boss_anubrekhan(); //Naxxramas -void AddSC_boss_maexxna(); -void AddSC_boss_patchwerk(); -void AddSC_boss_grobbulus(); -void AddSC_boss_razuvious(); -void AddSC_boss_kelthuzad(); -void AddSC_boss_loatheb(); -void AddSC_boss_noth(); -void AddSC_boss_gluth(); -void AddSC_boss_sapphiron(); -void AddSC_boss_four_horsemen(); -void AddSC_boss_faerlina(); -void AddSC_boss_heigan(); -void AddSC_boss_gothik(); -void AddSC_boss_thaddius(); -void AddSC_instance_naxxramas(); -void AddSC_boss_magus_telestra(); //The Nexus Nexus -void AddSC_boss_anomalus(); -void AddSC_boss_ormorok(); -void AddSC_boss_keristrasza(); -void AddSC_instance_nexus(); -void AddSC_boss_drakos(); //The Nexus The Oculus -void AddSC_boss_urom(); -void AddSC_instance_oculus(); -void AddSC_oculus(); -void AddSC_boss_sartharion(); //Obsidian Sanctum -void AddSC_instance_obsidian_sanctum(); -void AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning -void AddSC_boss_loken(); -void AddSC_boss_ionar(); -void AddSC_boss_volkhan(); -void AddSC_instance_halls_of_lightning(); -void AddSC_boss_maiden_of_grief(); //Ulduar Halls of Stone -void AddSC_boss_krystallus(); -void AddSC_boss_sjonnir(); -void AddSC_instance_halls_of_stone(); -void AddSC_halls_of_stone(); -void AddSC_boss_auriaya(); //Ulduar Ulduar -void AddSC_boss_flame_leviathan(); -void AddSC_boss_ignis(); -void AddSC_boss_razorscale(); -void AddSC_boss_xt002(); -void AddSC_boss_kologarn(); -void AddSC_boss_assembly_of_iron(); -void AddSC_ulduar_teleporter(); -void AddSC_instance_ulduar(); -void AddSC_boss_keleseth(); //Utgarde Keep -void AddSC_boss_skarvald_dalronn(); -void AddSC_boss_ingvar_the_plunderer(); -void AddSC_instance_utgarde_keep(); -void AddSC_boss_svala(); //Utgarde pinnacle -void AddSC_boss_palehoof(); -void AddSC_boss_skadi(); -void AddSC_boss_ymiron(); -void AddSC_instance_utgarde_pinnacle(); -void AddSC_utgarde_keep(); -void AddSC_boss_archavon(); //Vault of Archavon -void AddSC_boss_emalon(); -void AddSC_boss_koralon(); -void AddSC_boss_toravon(); -void AddSC_instance_archavon(); -void AddSC_boss_trollgore(); //Drak'Tharon Keep -void AddSC_boss_novos(); -void AddSC_boss_dred(); -void AddSC_boss_tharon_ja(); -void AddSC_instance_drak_tharon(); -void AddSC_boss_cyanigosa(); //Violet Hold -void AddSC_boss_erekem(); -void AddSC_boss_ichoron(); -void AddSC_boss_lavanthor(); -void AddSC_boss_moragg(); -void AddSC_boss_xevozz(); -void AddSC_boss_zuramat(); -void AddSC_instance_violet_hold(); -void AddSC_violet_hold(); -void AddSC_instance_forge_of_souls(); //Forge of Souls -void AddSC_forge_of_souls(); -void AddSC_boss_bronjahm(); -void AddSC_boss_devourer_of_souls(); -void AddSC_instance_pit_of_saron(); //Pit of Saron -void AddSC_pit_of_saron(); -void AddSC_boss_garfrost(); -void AddSC_boss_ick(); -void AddSC_boss_tyrannus(); -void AddSC_instance_halls_of_reflection(); // Halls of Reflection -void AddSC_halls_of_reflection(); -void AddSC_boss_falric(); -void AddSC_boss_marwyn(); - -void AddSC_dalaran(); -void AddSC_borean_tundra(); -void AddSC_dragonblight(); -void AddSC_grizzly_hills(); -void AddSC_howling_fjord(); -void AddSC_icecrown(); -void AddSC_sholazar_basin(); -void AddSC_storm_peaks(); -void AddSC_zuldrak(); -void AddSC_crystalsong_forest(); - -//outland -void AddSC_boss_exarch_maladaar(); //Auchindoun Auchenai Crypts -void AddSC_boss_shirrak_the_dead_watcher(); -void AddSC_boss_nexusprince_shaffar(); //Auchindoun Mana Tombs -void AddSC_boss_pandemonius(); -void AddSC_boss_darkweaver_syth(); //Auchindoun Sekketh Halls -void AddSC_boss_talon_king_ikiss(); -void AddSC_instance_sethekk_halls(); -void AddSC_instance_shadow_labyrinth(); //Auchindoun Shadow Labyrinth -void AddSC_boss_ambassador_hellmaw(); -void AddSC_boss_blackheart_the_inciter(); -void AddSC_boss_grandmaster_vorpil(); -void AddSC_boss_murmur(); -void AddSC_black_temple(); //Black Temple -void AddSC_boss_illidan(); -void AddSC_boss_shade_of_akama(); -void AddSC_boss_supremus(); -void AddSC_boss_gurtogg_bloodboil(); -void AddSC_boss_mother_shahraz(); -void AddSC_boss_reliquary_of_souls(); -void AddSC_boss_teron_gorefiend(); -void AddSC_boss_najentus(); -void AddSC_boss_illidari_council(); -void AddSC_instance_black_temple(); -void AddSC_boss_fathomlord_karathress(); //CR Serpent Shrine Cavern -void AddSC_boss_hydross_the_unstable(); -void AddSC_boss_lady_vashj(); -void AddSC_boss_leotheras_the_blind(); -void AddSC_boss_morogrim_tidewalker(); -void AddSC_instance_serpentshrine_cavern(); -void AddSC_boss_the_lurker_below(); -void AddSC_boss_hydromancer_thespia(); //CR Steam Vault -void AddSC_boss_mekgineer_steamrigger(); -void AddSC_boss_warlord_kalithresh(); -void AddSC_instance_steam_vault(); -void AddSC_boss_hungarfen(); //CR Underbog -void AddSC_boss_the_black_stalker(); -void AddSC_boss_gruul(); //Gruul's Lair -void AddSC_boss_high_king_maulgar(); -void AddSC_instance_gruuls_lair(); -void AddSC_boss_broggok(); //HC Blood Furnace -void AddSC_boss_kelidan_the_breaker(); -void AddSC_boss_the_maker(); -void AddSC_instance_blood_furnace(); -void AddSC_boss_magtheridon(); //HC Magtheridon's Lair -void AddSC_instance_magtheridons_lair(); -void AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls -void AddSC_boss_warbringer_omrogg(); -void AddSC_boss_warchief_kargath_bladefist(); -void AddSC_instance_shattered_halls(); -void AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts -void AddSC_boss_omor_the_unscarred(); -void AddSC_boss_vazruden_the_herald(); -void AddSC_instance_ramparts(); -void AddSC_arcatraz(); //TK Arcatraz -void AddSC_boss_harbinger_skyriss(); -void AddSC_instance_arcatraz(); -void AddSC_boss_high_botanist_freywinn(); //TK Botanica -void AddSC_boss_laj(); -void AddSC_boss_warp_splinter(); -void AddSC_boss_alar(); //TK The Eye -void AddSC_boss_kaelthas(); -void AddSC_boss_void_reaver(); -void AddSC_boss_high_astromancer_solarian(); -void AddSC_instance_the_eye(); -void AddSC_the_eye(); -void AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar -void AddSC_boss_nethermancer_sepethrea(); -void AddSC_boss_pathaleon_the_calculator(); -void AddSC_instance_mechanar(); - -void AddSC_blades_edge_mountains(); -void AddSC_boss_doomlordkazzak(); -void AddSC_boss_doomwalker(); -void AddSC_hellfire_peninsula(); -void AddSC_nagrand(); -void AddSC_netherstorm(); -void AddSC_shadowmoon_valley(); -void AddSC_shattrath_city(); -void AddSC_terokkar_forest(); -void AddSC_zangarmarsh(); -void AddSC_onevents(); - -#endif - -void AddScripts() -{ -#ifdef DO_SCRIPTS - - //custom - - //examples - AddSC_example_creature(); - AddSC_example_escort(); - AddSC_example_gossip_codebox(); - AddSC_example_misc(); - - //world - AddSC_areatrigger_scripts(); - AddSC_boss_emeriss(); - AddSC_boss_taerar(); - AddSC_boss_ysondre(); - AddSC_generic_creature(); - AddSC_go_scripts(); - AddSC_guards(); - AddSC_item_scripts(); - AddSC_npc_professions(); - AddSC_npc_innkeeper(); - AddSC_npcs_special(); - AddSC_npc_taxi(); - - //eastern kingdoms - AddSC_alterac_valley(); //Alterac Valley - AddSC_boss_balinda(); - AddSC_boss_drekthar(); - AddSC_boss_galvangar(); - AddSC_boss_vanndar(); - AddSC_blackrock_depths(); //Blackrock Depths - AddSC_boss_ambassador_flamelash(); - AddSC_boss_anubshiah(); - AddSC_boss_draganthaurissan(); - AddSC_boss_general_angerforge(); - AddSC_boss_gorosh_the_dervish(); - AddSC_boss_grizzle(); - AddSC_boss_high_interrogator_gerstahn(); - AddSC_boss_magmus(); - AddSC_boss_moira_bronzebeard(); - AddSC_boss_tomb_of_seven(); - AddSC_instance_blackrock_depths(); - AddSC_blackrock_spire(); //Blackrock Spire - AddSC_boss_drakkisath(); - AddSC_boss_halycon(); - AddSC_boss_highlordomokk(); - AddSC_boss_mothersmolderweb(); - AddSC_boss_overlordwyrmthalak(); - AddSC_boss_shadowvosh(); - AddSC_boss_thebeast(); - AddSC_boss_warmastervoone(); - AddSC_boss_quatermasterzigris(); - AddSC_boss_pyroguard_emberseer(); - AddSC_boss_gyth(); - AddSC_boss_rend_blackhand(); - AddSC_instance_blackrock_spire(); - AddSC_boss_razorgore(); //Blackwing lair - AddSC_boss_vael(); - AddSC_boss_broodlord(); - AddSC_boss_firemaw(); - AddSC_boss_ebonroc(); - AddSC_boss_flamegor(); - AddSC_boss_chromaggus(); - AddSC_boss_nefarian(); - AddSC_boss_victor_nefarius(); - AddSC_boss_mr_smite(); - AddSC_deadmines(); //Deadmines - AddSC_instance_deadmines(); - AddSC_gnomeregan(); //Gnomeregan - AddSC_instance_gnomeregan(); - AddSC_boss_attumen(); //Karazhan - AddSC_boss_curator(); - AddSC_boss_maiden_of_virtue(); - AddSC_boss_shade_of_aran(); - AddSC_boss_malchezaar(); - AddSC_boss_terestian_illhoof(); - AddSC_boss_moroes(); - AddSC_bosses_opera(); - AddSC_boss_netherspite(); - AddSC_instance_karazhan(); - AddSC_karazhan(); - AddSC_boss_nightbane(); - AddSC_boss_felblood_kaelthas(); // Magister's Terrace - AddSC_boss_selin_fireheart(); - AddSC_boss_vexallus(); - AddSC_boss_priestess_delrissa(); - AddSC_instance_magisters_terrace(); - AddSC_magisters_terrace(); - AddSC_boss_lucifron(); //Molten core - AddSC_boss_magmadar(); - AddSC_boss_gehennas(); - AddSC_boss_garr(); - AddSC_boss_baron_geddon(); - AddSC_boss_shazzrah(); - AddSC_boss_golemagg(); - AddSC_boss_sulfuron(); - AddSC_boss_majordomo(); - AddSC_boss_ragnaros(); - AddSC_instance_molten_core(); - AddSC_molten_core(); - AddSC_the_scarlet_enclave(); //Scarlet Enclave - AddSC_the_scarlet_enclave_c1(); - AddSC_the_scarlet_enclave_c2(); - AddSC_the_scarlet_enclave_c5(); - AddSC_boss_arcanist_doan(); //Scarlet Monastery - AddSC_boss_azshir_the_sleepless(); - AddSC_boss_bloodmage_thalnos(); - AddSC_boss_headless_horseman(); - AddSC_boss_herod(); - AddSC_boss_high_inquisitor_fairbanks(); - AddSC_boss_houndmaster_loksey(); - AddSC_boss_interrogator_vishas(); - AddSC_boss_scorn(); - AddSC_instance_scarlet_monastery(); - AddSC_boss_mograine_and_whitemane(); - AddSC_boss_darkmaster_gandling(); //Scholomance - AddSC_boss_death_knight_darkreaver(); - AddSC_boss_theolenkrastinov(); - AddSC_boss_illuciabarov(); - AddSC_boss_instructormalicia(); - AddSC_boss_jandicebarov(); - AddSC_boss_kormok(); - AddSC_boss_lordalexeibarov(); - AddSC_boss_lorekeeperpolkelt(); - AddSC_boss_rasfrost(); - AddSC_boss_theravenian(); - AddSC_boss_vectus(); - AddSC_instance_scholomance(); - AddSC_shadowfang_keep(); //Shadowfang keep - AddSC_instance_shadowfang_keep(); - AddSC_boss_magistrate_barthilas(); //Stratholme - AddSC_boss_maleki_the_pallid(); - AddSC_boss_nerubenkan(); - AddSC_boss_cannon_master_willey(); - AddSC_boss_baroness_anastari(); - AddSC_boss_ramstein_the_gorger(); - AddSC_boss_timmy_the_cruel(); - AddSC_boss_postmaster_malown(); - AddSC_boss_baron_rivendare(); - AddSC_boss_dathrohan_balnazzar(); - AddSC_boss_order_of_silver_hand(); - AddSC_instance_stratholme(); - AddSC_stratholme(); - AddSC_sunken_temple(); // Sunken Temple - AddSC_instance_sunken_temple(); - AddSC_instance_sunwell_plateau(); //Sunwell Plateau - AddSC_boss_kalecgos(); - AddSC_boss_brutallus(); - AddSC_boss_felmyst(); - AddSC_boss_eredar_twins(); - AddSC_boss_muru(); - AddSC_boss_kiljaeden(); - AddSC_sunwell_plateau(); - AddSC_boss_archaedas(); //Uldaman - AddSC_boss_ironaya(); - AddSC_uldaman(); - AddSC_instance_uldaman(); - AddSC_boss_akilzon(); //Zul'Aman - AddSC_boss_halazzi(); - AddSC_boss_hex_lord_malacrass(); - AddSC_boss_janalai(); - AddSC_boss_nalorakk(); - AddSC_boss_zuljin(); - AddSC_instance_zulaman(); - AddSC_zulaman(); - AddSC_boss_jeklik(); //Zul'Gurub - AddSC_boss_venoxis(); - AddSC_boss_marli(); - AddSC_boss_mandokir(); - AddSC_boss_gahzranka(); - AddSC_boss_thekal(); - AddSC_boss_arlokk(); - AddSC_boss_jindo(); - AddSC_boss_hakkar(); - AddSC_boss_grilek(); - AddSC_boss_hazzarah(); - AddSC_boss_renataki(); - AddSC_boss_wushoolay(); - AddSC_instance_zulgurub(); - - //AddSC_alterac_mountains(); - AddSC_arathi_highlands(); - AddSC_blasted_lands(); - AddSC_boss_kruul(); - AddSC_burning_steppes(); - AddSC_dun_morogh(); - AddSC_duskwood(); - AddSC_eastern_plaguelands(); - AddSC_elwynn_forest(); - AddSC_eversong_woods(); - AddSC_ghostlands(); - AddSC_hinterlands(); - AddSC_ironforge(); - AddSC_isle_of_queldanas(); - AddSC_loch_modan(); - AddSC_redridge_mountains(); - AddSC_searing_gorge(); - AddSC_silvermoon_city(); - AddSC_silverpine_forest(); - AddSC_stormwind_city(); - AddSC_stranglethorn_vale(); - AddSC_tirisfal_glades(); - AddSC_undercity(); - AddSC_western_plaguelands(); - AddSC_westfall(); - AddSC_wetlands(); - - //kalimdor - AddSC_blackfathom_deeps(); //Blackfathom Depths - AddSC_boss_gelihast(); - AddSC_boss_kelris(); - AddSC_boss_aku_mai(); - AddSC_instance_blackfathom_deeps(); - AddSC_hyjal(); //CoT Battle for Mt. Hyjal - AddSC_boss_archimonde(); - AddSC_instance_mount_hyjal(); - AddSC_hyjal_trash(); - AddSC_boss_rage_winterchill(); - AddSC_boss_anetheron(); - AddSC_boss_kazrogal(); - AddSC_boss_azgalor(); - AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad - AddSC_boss_epoch_hunter(); - AddSC_boss_lieutenant_drake(); - AddSC_instance_old_hillsbrad(); - AddSC_old_hillsbrad(); - AddSC_boss_aeonus(); //CoT The Dark Portal - AddSC_boss_chrono_lord_deja(); - AddSC_boss_temporus(); - AddSC_dark_portal(); - AddSC_instance_dark_portal(); - AddSC_boss_epoch(); //CoT Culling Of Stratholme - AddSC_boss_infinite_corruptor(); - AddSC_boss_salramm(); - AddSC_boss_mal_ganis(); - AddSC_boss_meathook(); - AddSC_culling_of_stratholme(); - AddSC_instance_culling_of_stratholme(); - AddSC_boss_celebras_the_cursed(); //Maraudon - AddSC_boss_landslide(); - AddSC_boss_noxxion(); - AddSC_boss_ptheradras(); - AddSC_boss_onyxia(); //Onyxia's Lair - AddSC_instance_onyxias_lair(); - AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs - AddSC_razorfen_downs(); - AddSC_instance_razorfen_downs(); - AddSC_razorfen_kraul(); //Razorfen Kraul - AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj - AddSC_boss_rajaxx(); - AddSC_boss_moam(); - AddSC_boss_buru(); - AddSC_boss_ayamiss(); - AddSC_boss_ossirian(); - AddSC_instance_ruins_of_ahnqiraj(); - AddSC_boss_cthun(); //Temple of ahn'qiraj - AddSC_boss_fankriss(); - AddSC_boss_huhuran(); - AddSC_bug_trio(); - AddSC_boss_sartura(); - AddSC_boss_skeram(); - AddSC_boss_twinemperors(); - AddSC_mob_anubisath_sentinel(); - AddSC_instance_temple_of_ahnqiraj(); - AddSC_wailing_caverns(); //Wailing caverns - AddSC_instance_wailing_caverns(); - AddSC_zulfarrak(); //Zul'Farrak generic - AddSC_instance_zulfarrak(); //Zul'Farrak instance script - - AddSC_ashenvale(); - AddSC_azshara(); - AddSC_azuremyst_isle(); - AddSC_bloodmyst_isle(); - AddSC_boss_azuregos(); - AddSC_darkshore(); - AddSC_desolace(); - AddSC_durotar(); - AddSC_dustwallow_marsh(); - AddSC_felwood(); - AddSC_feralas(); - AddSC_moonglade(); - AddSC_mulgore(); - AddSC_orgrimmar(); - AddSC_silithus(); - AddSC_stonetalon_mountains(); - AddSC_tanaris(); - AddSC_teldrassil(); - AddSC_the_barrens(); - AddSC_thousand_needles(); - AddSC_thunder_bluff(); - AddSC_ungoro_crater(); - AddSC_winterspring(); - - //northrend - AddSC_boss_slad_ran(); //Gundrak - AddSC_boss_moorabi(); - AddSC_boss_drakkari_colossus(); - AddSC_boss_gal_darah(); - AddSC_boss_eck(); - AddSC_instance_gundrak(); - AddSC_boss_amanitar(); - AddSC_boss_taldaram(); //Azjol-Nerub Ahn'kahet - AddSC_boss_elder_nadox(); - AddSC_boss_jedoga_shadowseeker(); - AddSC_boss_volazj(); - AddSC_instance_ahnkahet(); - AddSC_boss_argent_challenge(); //Trial of the Champion - AddSC_boss_black_knight(); - AddSC_boss_grand_champions(); - AddSC_instance_trial_of_the_champion(); - AddSC_trial_of_the_champion(); - AddSC_boss_krik_thir(); //Azjol-Nerub Azjol-Nerub - AddSC_boss_hadronox(); - AddSC_boss_anub_arak(); - AddSC_instance_azjol_nerub(); - AddSC_boss_anubrekhan(); //Naxxramas - AddSC_boss_maexxna(); - AddSC_boss_patchwerk(); - AddSC_boss_grobbulus(); - AddSC_boss_razuvious(); - AddSC_boss_kelthuzad(); - AddSC_boss_loatheb(); - AddSC_boss_noth(); - AddSC_boss_gluth(); - AddSC_boss_sapphiron(); - AddSC_boss_four_horsemen(); - AddSC_boss_faerlina(); - AddSC_boss_heigan(); - AddSC_boss_gothik(); - AddSC_boss_thaddius(); - AddSC_instance_naxxramas(); - AddSC_boss_magus_telestra(); //The Nexus Nexus - AddSC_boss_anomalus(); - AddSC_boss_ormorok(); - AddSC_boss_keristrasza(); - AddSC_instance_nexus(); - AddSC_boss_drakos(); //The Nexus The Oculus - AddSC_boss_urom(); - AddSC_instance_oculus(); - AddSC_oculus(); - AddSC_boss_sartharion(); //Obsidian Sanctum - AddSC_instance_obsidian_sanctum(); - AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning - AddSC_boss_loken(); - AddSC_boss_ionar(); - AddSC_boss_volkhan(); - AddSC_instance_halls_of_lightning(); - AddSC_boss_maiden_of_grief(); //Ulduar Halls of Stone - AddSC_boss_krystallus(); - AddSC_boss_sjonnir(); - AddSC_instance_halls_of_stone(); - AddSC_halls_of_stone(); - AddSC_boss_auriaya(); //Ulduar Ulduar - AddSC_boss_flame_leviathan(); - AddSC_boss_ignis(); - AddSC_boss_razorscale(); - AddSC_boss_xt002(); - AddSC_boss_assembly_of_iron(); - AddSC_boss_kologarn(); - AddSC_ulduar_teleporter(); - AddSC_instance_ulduar(); - AddSC_boss_keleseth(); //Utgarde Keep - AddSC_boss_skarvald_dalronn(); - AddSC_boss_ingvar_the_plunderer(); - AddSC_instance_utgarde_keep(); - AddSC_boss_svala(); //Utgarde pinnacle - AddSC_boss_palehoof(); - AddSC_boss_skadi(); - AddSC_boss_ymiron(); - AddSC_instance_utgarde_pinnacle(); - AddSC_utgarde_keep(); - AddSC_boss_archavon(); //Vault of Archavon - AddSC_boss_emalon(); - AddSC_boss_koralon(); - AddSC_boss_toravon(); - AddSC_instance_archavon(); - AddSC_boss_trollgore(); //Drak'Tharon Keep - AddSC_boss_novos(); - AddSC_boss_dred(); - AddSC_boss_tharon_ja(); - AddSC_instance_drak_tharon(); - AddSC_boss_cyanigosa(); //Violet Hold - AddSC_boss_erekem(); - AddSC_boss_ichoron(); - AddSC_boss_lavanthor(); - AddSC_boss_moragg(); - AddSC_boss_xevozz(); - AddSC_boss_zuramat(); - AddSC_instance_violet_hold(); - AddSC_violet_hold(); - AddSC_instance_forge_of_souls(); //Forge of Souls - AddSC_forge_of_souls(); - AddSC_boss_bronjahm(); - AddSC_boss_devourer_of_souls(); - AddSC_instance_pit_of_saron(); //Pit of Saron - AddSC_pit_of_saron(); - AddSC_boss_garfrost(); - AddSC_boss_ick(); - AddSC_boss_tyrannus(); - AddSC_instance_halls_of_reflection(); // Halls of Reflection - AddSC_halls_of_reflection(); - AddSC_boss_falric(); - AddSC_boss_marwyn(); - - AddSC_dalaran(); - AddSC_borean_tundra(); - AddSC_dragonblight(); - AddSC_grizzly_hills(); - AddSC_howling_fjord(); - AddSC_icecrown(); - AddSC_sholazar_basin(); - AddSC_storm_peaks(); - AddSC_zuldrak(); - AddSC_crystalsong_forest(); - - //outland - AddSC_boss_exarch_maladaar(); //Auchindoun Auchenai Crypts - AddSC_boss_shirrak_the_dead_watcher(); - AddSC_boss_nexusprince_shaffar(); //Auchindoun Mana Tombs - AddSC_boss_pandemonius(); - AddSC_boss_darkweaver_syth(); //Auchindoun Sekketh Halls - AddSC_boss_talon_king_ikiss(); - AddSC_instance_sethekk_halls(); - AddSC_instance_shadow_labyrinth(); //Auchindoun Shadow Labyrinth - AddSC_boss_ambassador_hellmaw(); - AddSC_boss_blackheart_the_inciter(); - AddSC_boss_grandmaster_vorpil(); - AddSC_boss_murmur(); - AddSC_black_temple(); //Black Temple - AddSC_boss_illidan(); - AddSC_boss_shade_of_akama(); - AddSC_boss_supremus(); - AddSC_boss_gurtogg_bloodboil(); - AddSC_boss_mother_shahraz(); - AddSC_boss_reliquary_of_souls(); - AddSC_boss_teron_gorefiend(); - AddSC_boss_najentus(); - AddSC_boss_illidari_council(); - AddSC_instance_black_temple(); - AddSC_boss_fathomlord_karathress(); //CR Serpent Shrine Cavern - AddSC_boss_hydross_the_unstable(); - AddSC_boss_lady_vashj(); - AddSC_boss_leotheras_the_blind(); - AddSC_boss_morogrim_tidewalker(); - AddSC_instance_serpentshrine_cavern(); - AddSC_boss_the_lurker_below(); - AddSC_boss_hydromancer_thespia(); //CR Steam Vault - AddSC_boss_mekgineer_steamrigger(); - AddSC_boss_warlord_kalithresh(); - AddSC_instance_steam_vault(); - AddSC_boss_hungarfen(); //CR Underbog - AddSC_boss_the_black_stalker(); - AddSC_boss_gruul(); //Gruul's Lair - AddSC_boss_high_king_maulgar(); - AddSC_instance_gruuls_lair(); - AddSC_boss_broggok(); //HC Blood Furnace - AddSC_boss_kelidan_the_breaker(); - AddSC_boss_the_maker(); - AddSC_instance_blood_furnace(); - AddSC_boss_magtheridon(); //HC Magtheridon's Lair - AddSC_instance_magtheridons_lair(); - AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls - AddSC_boss_warbringer_omrogg(); - AddSC_boss_warchief_kargath_bladefist(); - AddSC_instance_shattered_halls(); - AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts - AddSC_boss_omor_the_unscarred(); - AddSC_boss_vazruden_the_herald(); - AddSC_instance_ramparts(); - AddSC_arcatraz(); //TK Arcatraz - AddSC_boss_harbinger_skyriss(); - AddSC_instance_arcatraz(); - AddSC_boss_high_botanist_freywinn(); //TK Botanica - AddSC_boss_laj(); - AddSC_boss_warp_splinter(); - AddSC_boss_alar(); //TK The Eye - AddSC_boss_kaelthas(); - AddSC_boss_void_reaver(); - AddSC_boss_high_astromancer_solarian(); - AddSC_instance_the_eye(); - AddSC_the_eye(); - AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar - AddSC_boss_nethermancer_sepethrea(); - AddSC_boss_pathaleon_the_calculator(); - AddSC_instance_mechanar(); - - AddSC_blades_edge_mountains(); - AddSC_boss_doomlordkazzak(); - AddSC_boss_doomwalker(); - AddSC_hellfire_peninsula(); - AddSC_nagrand(); - AddSC_netherstorm(); - AddSC_shadowmoon_valley(); - AddSC_shattrath_city(); - AddSC_terokkar_forest(); - AddSC_zangarmarsh(); - AddSC_onevents(); - -#endif -} diff --git a/src/server/game/ScriptMgr/ScriptLoader.h b/src/server/game/ScriptMgr/ScriptLoader.h deleted file mode 100644 index 57fb7d821f1..00000000000 --- a/src/server/game/ScriptMgr/ScriptLoader.h +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef SC_SCRIPTLOADER_H -#define SC_SCRIPTLOADER_H - -void AddScripts(); - -#endif diff --git a/src/server/game/ScriptMgr/ScriptMgr.cpp b/src/server/game/ScriptMgr/ScriptMgr.cpp deleted file mode 100644 index 2dcfd258942..00000000000 --- a/src/server/game/ScriptMgr/ScriptMgr.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/* Copyright (C) 2006 - 2008 TrinityScript - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#include "ScriptedPch.h" -#include "Config/Config.h" -#include "Database/DatabaseEnv.h" -#include "DBCStores.h" -#include "ObjectMgr.h" -#include "ProgressBar.h" -#include "ScriptLoader.h" -#include "ScriptSystem.h" -#include "Policies/SingletonImp.h" - -INSTANTIATE_SINGLETON_1(ScriptMgr); - -int num_sc_scripts; -Script *m_scripts[MAX_SCRIPTS]; - -void FillSpellSummary(); -void LoadOverridenSQLData(); - -void ScriptMgr::LoadDatabase() -{ - pSystemMgr.LoadVersion(); - pSystemMgr.LoadScriptTexts(); - pSystemMgr.LoadScriptTextsCustom(); - pSystemMgr.LoadScriptWaypoints(); -} - -struct TSpellSummary { - uint8 Targets; // set of enum SelectTarget - uint8 Effects; // set of enum SelectEffect -}extern *SpellSummary; - -ScriptMgr::ScriptMgr() -{ - -} -ScriptMgr::~ScriptMgr() -{ - -} - -void ScriptMgr::ScriptsInit() -{ - //Trinity Script startup - outstring_log(" _____ _ _ _ ____ _ _"); - outstring_log("|_ _| __(_)_ __ (_) |_ _ _/ ___| ___ _ __(_)_ __ | |_ "); - outstring_log(" | || '__| | '_ \\| | __| | | \\___ \\ / __| \'__| | \'_ \\| __|"); - outstring_log(" | || | | | | | | | |_| |_| |___) | (__| | | | |_) | |_ "); - outstring_log(" |_||_| |_|_| |_|_|\\__|\\__, |____/ \\___|_| |_| .__/ \\__|"); - outstring_log(" |___/ |_| "); - outstring_log(""); - outstring_log(""); - - //Load database (must be called after SD2Config.SetSource). - LoadDatabase(); - - outstring_log("TSCR: Loading C++ scripts"); - barGoLink bar(1); - bar.step(); - outstring_log(""); - - for (uint16 i =0; i> Loaded %i C++ Scripts.", num_sc_scripts); - - outstring_log(">> Load Overriden SQL Data."); - LoadOverridenSQLData(); -} - -//********************************* -//*** Functions used globally *** - -void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget) -{ - if (!pSource) - { - error_log("TSCR: DoScriptText entry %i, invalid Source pointer.", iTextEntry); - return; - } - - if (iTextEntry >= 0) - { - error_log("TSCR: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.", pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry); - return; - } - - const StringTextData* pData = pSystemMgr.GetTextData(iTextEntry); - - if (!pData) - { - error_log("TSCR: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.", pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry); - return; - } - - debug_log("TSCR: DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u", iTextEntry, pData->uiSoundId, pData->uiType, pData->uiLanguage, pData->uiEmote); - - if (pData->uiSoundId) - { - if (GetSoundEntriesStore()->LookupEntry(pData->uiSoundId)) - { - pSource->SendPlaySound(pData->uiSoundId, false); - } - else - error_log("TSCR: DoScriptText entry %i tried to process invalid sound id %u.", iTextEntry, pData->uiSoundId); - } - - if (pData->uiEmote) - { - if (pSource->GetTypeId() == TYPEID_UNIT || pSource->GetTypeId() == TYPEID_PLAYER) - ((Unit*)pSource)->HandleEmoteCommand(pData->uiEmote); - else - error_log("TSCR: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", iTextEntry, pSource->GetTypeId()); - } - - switch(pData->uiType) - { - case CHAT_TYPE_SAY: - pSource->MonsterSay(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0); - break; - case CHAT_TYPE_YELL: - pSource->MonsterYell(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0); - break; - case CHAT_TYPE_TEXT_EMOTE: - pSource->MonsterTextEmote(iTextEntry, pTarget ? pTarget->GetGUID() : 0); - break; - case CHAT_TYPE_BOSS_EMOTE: - pSource->MonsterTextEmote(iTextEntry, pTarget ? pTarget->GetGUID() : 0, true); - break; - case CHAT_TYPE_WHISPER: - { - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - pSource->MonsterWhisper(iTextEntry, pTarget->GetGUID()); - else - error_log("TSCR: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry); - } - break; - case CHAT_TYPE_BOSS_WHISPER: - { - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - pSource->MonsterWhisper(iTextEntry, pTarget->GetGUID(), true); - else - error_log("TSCR: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry); - } - break; - case CHAT_TYPE_ZONE_YELL: - pSource->MonsterYellToZone(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0); - break; - } -} - -void Script::RegisterSelf() -{ - // try to find scripts which try to use another script's allocated memory - // that means didn't allocate memory for script - for (uint16 i = 0; i < MAX_SCRIPTS; ++i) - { - // somebody forgot to allocate memory for a script by a method like this: newscript = new Script - if (m_scripts[i] == this) - { - error_log("ScriptName: '%s' - Forgot to allocate memory, so this script and/or the script before that can't work.", Name.c_str()); - // don't register it - // and don't delete it because its memory is used for another script - return; - } - } - - int id = GetScriptId(Name.c_str()); - if (id) - { - // try to find the script in assigned scripts - bool IsExist = false; - for (uint16 i = 0; i < MAX_SCRIPTS; ++i) - { - if (m_scripts[i]) - { - // if the assigned script's name and the new script's name is the same - if (m_scripts[i]->Name == Name) - { - IsExist = true; - break; - } - } - } - - // if the script doesn't assigned -> assign it! - if (!IsExist) - { - m_scripts[id] = this; - ++num_sc_scripts; - } - // if the script is already assigned -> delete it! - else - { - // TODO: write a better error message than this one :) - error_log("ScriptName: '%s' already assigned with the same ScriptName, so the script can't work.", Name.c_str()); - delete this; - } - } - else - { - if (Name.find("example") == std::string::npos) - error_db_log("TrinityScript: RegisterSelf, but script named %s does not have ScriptName assigned in database.",(this)->Name.c_str()); - delete this; - } -} - -void ScriptMgr::OnLogin(Player *pPlayer) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnLogin) return; - tmpscript->pOnLogin(pPlayer); -} - -void ScriptMgr::OnLogout(Player *pPlayer) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnLogout) return; - tmpscript->pOnLogout(pPlayer); -} - -void ScriptMgr::OnPVPKill(Player *killer, Player *killed) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnPVPKill) return; - tmpscript->pOnPVPKill(killer, killed); -} - -bool ScriptMgr::OnSpellCast (Unit *pUnitTarget, Item *pItemTarget, GameObject *pGoTarget, uint32 i, SpellEntry const *spell) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnSpellCast) return true; - return tmpscript->pOnSpellCast(pUnitTarget,pItemTarget,pGoTarget,i,spell); -} - -uint32 ScriptMgr::OnGetXP(Player *pPlayer, uint32 amount) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnGetXP) return amount; - return tmpscript->pOnGetXP(pPlayer,amount); -} - -uint32 ScriptMgr::OnGetMoney(Player *pPlayer, int32 amount) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnGetMoney) return amount; - return tmpscript->pOnGetMoney(pPlayer,amount); -} - -bool ScriptMgr::OnPlayerChat(Player *pPlayer, const char *text) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnPlayerChat) return true; - return tmpscript->pOnPlayerChat(pPlayer,text); -} - -void ScriptMgr::OnServerStartup() -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnServerStartup) return; - tmpscript->pOnServerStartup(); -} - -void ScriptMgr::OnServerShutdown() -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnServerShutdown) return; - tmpscript->pOnServerShutdown(); -} - -void ScriptMgr::OnAreaChange(Player *pPlayer, AreaTableEntry const *pArea) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnAreaChange) return; - tmpscript->pOnAreaChange(pPlayer, pArea); -} - -bool ScriptMgr::OnItemClick (Player *pPlayer, Item *pItem) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnItemClick) return true; - return tmpscript->pOnItemClick(pPlayer,pItem); -} - -bool ScriptMgr::OnItemOpen (Player *pPlayer, Item *pItem) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnItemOpen) return true; - return tmpscript->pOnItemOpen(pPlayer,pItem); -} - -bool ScriptMgr::OnGoClick (Player *pPlayer, GameObject *pGameObject) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnGoClick) return true; - return tmpscript->pOnGoClick(pPlayer,pGameObject); -} - -void ScriptMgr::OnCreatureKill (Player *pPlayer, Creature *pCreature) -{ - Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; - if (!tmpscript || !tmpscript->pOnCreatureKill) return; - tmpscript->pOnCreatureKill(pPlayer,pCreature); -} - -char const* ScriptMgr::ScriptsVersion() -{ - return "Integrated Trinity Scripts"; -} - -bool ScriptMgr::GossipHello (Player * pPlayer, Creature* pCreature) -{ - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pGossipHello) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGossipHello(pPlayer, pCreature); -} - -bool ScriptMgr::GossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - debug_log("TSCR: Gossip selection, sender: %d, action: %d", uiSender, uiAction); - - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pGossipSelect) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGossipSelect(pPlayer, pCreature, uiSender, uiAction); -} - -bool ScriptMgr::GossipSelectWithCode(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode) -{ - debug_log("TSCR: Gossip selection with code, sender: %d, action: %d", uiSender, uiAction); - - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pGossipSelectWithCode) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGossipSelectWithCode(pPlayer, pCreature, uiSender, uiAction, sCode); -} - -bool ScriptMgr::GOSelect(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction) -{ - if (!pGO) - return false; - debug_log("TSCR: Gossip selection, sender: %d, action: %d", uiSender, uiAction); - - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOSelect) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOSelect(pPlayer, pGO, uiSender, uiAction); -} - -bool ScriptMgr::GOSelectWithCode(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction, const char* sCode) -{ - if (!pGO) - return false; - debug_log("TSCR: Gossip selection, sender: %d, action: %d",uiSender, uiAction); - - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOSelectWithCode) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOSelectWithCode(pPlayer, pGO, uiSender ,uiAction, sCode); -} - -bool ScriptMgr::QuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pQuestAccept) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pQuestAccept(pPlayer, pCreature, pQuest); -} - -bool ScriptMgr::QuestSelect(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pQuestSelect) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pQuestSelect(pPlayer, pCreature, pQuest); -} - -bool ScriptMgr::QuestComplete(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pQuestComplete) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pQuestComplete(pPlayer, pCreature, pQuest); -} - -bool ScriptMgr::ChooseReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt) -{ - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pChooseReward) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pChooseReward(pPlayer, pCreature, pQuest, opt); -} - -uint32 ScriptMgr::NPCDialogStatus(Player* pPlayer, Creature* pCreature) -{ - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->pNPCDialogStatus) return 100; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pNPCDialogStatus(pPlayer, pCreature); -} - -uint32 ScriptMgr::GODialogStatus(Player* pPlayer, GameObject* pGO) -{ - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGODialogStatus) return 100; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGODialogStatus(pPlayer, pGO); -} - -bool ScriptMgr::ItemHello(Player* pPlayer, Item* pItem, Quest const* pQuest) -{ - Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; - if (!tmpscript || !tmpscript->pItemHello) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pItemHello(pPlayer, pItem, pQuest); -} - -bool ScriptMgr::ItemQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest) -{ - Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; - if (!tmpscript || !tmpscript->pItemQuestAccept) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pItemQuestAccept(pPlayer, pItem, pQuest); -} - -bool ScriptMgr::GOHello(Player* pPlayer, GameObject* pGO) -{ - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOHello) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOHello(pPlayer, pGO); -} - -bool ScriptMgr::GOQuestAccept(Player* pPlayer, GameObject* pGO, Quest const* pQuest) -{ - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOQuestAccept) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOQuestAccept(pPlayer, pGO, pQuest); -} - -bool ScriptMgr::GOChooseReward(Player* pPlayer, GameObject* pGO, Quest const* pQuest, uint32 opt) -{ - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript || !tmpscript->pGOChooseReward) return false; - - pPlayer->PlayerTalkClass->ClearMenus(); - return tmpscript->pGOChooseReward(pPlayer, pGO, pQuest, opt); -} - -void ScriptMgr::GODestroyed(Player* pPlayer, GameObject* pGO, uint32 destroyedEvent) -{ - Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; - if (!tmpscript) return; - tmpscript->pGODestroyed(pPlayer, pGO, destroyedEvent); -} - -bool ScriptMgr::AreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry) -{ - Script *tmpscript = m_scripts[GetAreaTriggerScriptId(atEntry->id)]; - if (!tmpscript || !tmpscript->pAreaTrigger) return false; - - return tmpscript->pAreaTrigger(pPlayer, atEntry); -} - -CreatureAI* ScriptMgr::GetAI(Creature* pCreature) -{ - Script *tmpscript = m_scripts[pCreature->GetScriptId()]; - if (!tmpscript || !tmpscript->GetAI) return NULL; - - return tmpscript->GetAI(pCreature); -} - -bool ScriptMgr::ItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) -{ - Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; - if (!tmpscript || !tmpscript->pItemUse) return false; - - return tmpscript->pItemUse(pPlayer, pItem, targets); -} - -bool ScriptMgr::ItemExpire(Player* pPlayer, ItemPrototype const * pItemProto) -{ - Script *tmpscript = m_scripts[pItemProto->ScriptId]; - if (!tmpscript || !tmpscript->pItemExpire) return true; - - return tmpscript->pItemExpire(pPlayer, pItemProto); -} - -bool ScriptMgr::EffectDummyCreature(Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget) -{ - Script *tmpscript = m_scripts[crTarget->GetScriptId()]; - - if (!tmpscript || !tmpscript->pEffectDummyCreature) return false; - - return tmpscript->pEffectDummyCreature(caster, spellId, effIndex, crTarget); -} - -bool ScriptMgr::EffectDummyGameObj(Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget) -{ - Script *tmpscript = m_scripts[gameObjTarget->GetGOInfo()->ScriptId]; - - if (!tmpscript || !tmpscript->pEffectDummyGameObj) return false; - - return tmpscript->pEffectDummyGameObj(caster, spellId, effIndex, gameObjTarget); -} - -bool ScriptMgr::EffectDummyItem(Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget) -{ - Script *tmpscript = m_scripts[itemTarget->GetProto()->ScriptId]; - - if (!tmpscript || !tmpscript->pEffectDummyItem) return false; - - return tmpscript->pEffectDummyItem(caster, spellId, effIndex, itemTarget); -} - -InstanceData* ScriptMgr::CreateInstanceData(Map *map) -{ - if (!map->IsDungeon()) return NULL; - - Script *tmpscript = m_scripts[((InstanceMap*)map)->GetScriptId()]; - if (!tmpscript || !tmpscript->GetInstanceData) return NULL; - - return tmpscript->GetInstanceData(map); -} - diff --git a/src/server/game/ScriptMgr/ScriptMgr.h b/src/server/game/ScriptMgr/ScriptMgr.h deleted file mode 100644 index ed7200d5786..00000000000 --- a/src/server/game/ScriptMgr/ScriptMgr.h +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright (C) 2008-2010 Trinity - * - * Thanks to the original authors: ScriptDev2 - * - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef SC_SCRIPTMGR_H -#define SC_SCRIPTMGR_H - -#include "Common.h" -#include "Platform/CompilerDefs.h" -#include "DBCStructure.h" -#include "Config/ConfigEnv.h" - -class Player; -class Creature; -class CreatureAI; -class InstanceData; -class Quest; -class Item; -class GameObject; -class SpellCastTargets; -class Map; -class Unit; -class WorldObject; -struct ItemPrototype; - -#define MAX_SCRIPTS 5000 //72 bytes each (approx 351kb) -#define VISIBLE_RANGE (166.0f) //MAX visible range (size of grid) -#define DEFAULT_TEXT "" - -struct Script -{ - Script() : - pOnLogin(NULL), pOnLogout(NULL), pOnPVPKill(NULL), pOnSpellCast(NULL), pOnGetXP(NULL), - pOnGetMoney(NULL), pOnPlayerChat(NULL), pOnServerStartup(NULL), pOnServerShutdown(NULL), - pOnAreaChange(NULL), pOnItemClick(NULL), pOnItemOpen(NULL), pOnGoClick(NULL), pOnCreatureKill(NULL), - pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL), - pGOSelect(NULL), pGOSelectWithCode(NULL), - pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), - pChooseReward(NULL), pGODestroyed(NULL), pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), - pGOQuestAccept(NULL), pGOChooseReward(NULL),pItemUse(NULL), pItemExpire(NULL), - pEffectDummyCreature(NULL), pEffectDummyGameObj(NULL), pEffectDummyItem(NULL), - GetAI(NULL), GetInstanceData(NULL) - {} - - std::string Name; - - //Methods to be scripted - void (*pOnLogin)(Player*); - void (*pOnLogout)(Player*); - void (*pOnPVPKill)(Player*, Player*); - bool (*pOnSpellCast)(Unit*, Item*, GameObject*, uint32, SpellEntry const*); - uint32 (*pOnGetXP)(Player*, uint32); - int32 (*pOnGetMoney)(Player*, int32); - bool (*pOnPlayerChat)(Player*, const char*); - void (*pOnServerStartup)(); - void (*pOnServerShutdown)(); - void (*pOnAreaChange)(Player*, AreaTableEntry const*); - bool (*pOnItemClick)(Player*, Item*); - bool (*pOnItemOpen)(Player*, Item*); - bool (*pOnGoClick)(Player*, GameObject*); - void (*pOnCreatureKill)(Player*, Creature*); - bool (*pGossipHello)(Player*, Creature*); - bool (*pQuestAccept)(Player*, Creature*, Quest const*); - bool (*pGossipSelect)(Player*, Creature*, uint32 , uint32); - bool (*pGossipSelectWithCode)(Player*, Creature*, uint32 , uint32 , const char*); - bool (*pGOSelect)(Player*, GameObject*, uint32 , uint32); - bool (*pGOSelectWithCode)(Player*, GameObject*, uint32 , uint32 , const char*); - bool (*pQuestSelect)(Player*, Creature*, Quest const*); - bool (*pQuestComplete)(Player*, Creature*, Quest const*); - uint32 (*pNPCDialogStatus)(Player*, Creature*); - uint32 (*pGODialogStatus)(Player*, GameObject * _GO); - bool (*pChooseReward)(Player*, Creature*, Quest const*, uint32); - bool (*pItemHello)(Player*, Item*, Quest const*); - bool (*pGOHello)(Player*, GameObject*); - bool (*pAreaTrigger)(Player*, AreaTriggerEntry const*); - bool (*pItemQuestAccept)(Player*, Item *, Quest const*); - bool (*pGOQuestAccept)(Player*, GameObject*, Quest const*); - bool (*pGOChooseReward)(Player*, GameObject*, Quest const*, uint32); - void (*pGODestroyed)(Player*, GameObject*, uint32); - bool (*pItemUse)(Player*, Item*, SpellCastTargets const&); - bool (*pItemExpire)(Player*, ItemPrototype const *); - bool (*pEffectDummyCreature)(Unit*, uint32, uint32, Creature*); - bool (*pEffectDummyGameObj)(Unit*, uint32, uint32, GameObject*); - bool (*pEffectDummyItem)(Unit*, uint32, uint32, Item*); - - CreatureAI* (*GetAI)(Creature*); - InstanceData* (*GetInstanceData)(Map*); - - void RegisterSelf(); -}; - -class ScriptMgr -{ - public: - ScriptMgr(); - ~ScriptMgr(); - - void ScriptsInit(); - void LoadDatabase(); - char const* ScriptsVersion(); - - //event handlers - void OnLogin(Player *pPlayer); - void OnLogout(Player *pPlayer); - void OnPVPKill(Player *killer, Player *killed); - bool OnSpellCast (Unit *pUnitTarget, Item *pItemTarget, GameObject *pGoTarget, uint32 i, SpellEntry const *spell); - uint32 OnGetXP(Player *pPlayer, uint32 amount); - uint32 OnGetMoney(Player *pPlayer, int32 amount); - bool OnPlayerChat(Player *pPlayer, const char *text); - void OnServerStartup(); - void OnServerShutdown(); - void OnAreaChange(Player *pPlayer, AreaTableEntry const *pArea); - bool OnItemClick (Player *pPlayer, Item *pItem); - bool OnItemOpen (Player *pPlayer, Item *pItem); - bool OnGoClick (Player *pPlayer, GameObject *pGameObject); - void OnCreatureKill (Player *pPlayer, Creature *pCreature); - bool GossipHello (Player * pPlayer, Creature* pCreature); - bool GossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction); - bool GossipSelectWithCode(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode); - bool GOSelect(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction); - bool GOSelectWithCode(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction, const char* sCode); - bool QuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest); - bool QuestSelect(Player* pPlayer, Creature* pCreature, Quest const* pQuest); - bool QuestComplete(Player* pPlayer, Creature* pCreature, Quest const* pQuest); - bool ChooseReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt); - uint32 NPCDialogStatus(Player* pPlayer, Creature* pCreature); - uint32 GODialogStatus(Player* pPlayer, GameObject* pGO); - bool ItemHello(Player* pPlayer, Item* pItem, Quest const* pQuest); - bool ItemQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest); - bool GOHello(Player* pPlayer, GameObject* pGO); - bool GOQuestAccept(Player* pPlayer, GameObject* pGO, Quest const* pQuest); - bool GOChooseReward(Player* pPlayer, GameObject* pGO, Quest const* pQuest, uint32 opt); - void GODestroyed(Player* pPlayer, GameObject* pGO, uint32 destroyedEvent); - bool AreaTrigger(Player* pPlayer,AreaTriggerEntry const* atEntry); - CreatureAI* GetAI(Creature* pCreature); - bool ItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets); - bool ItemExpire(Player* pPlayer, ItemPrototype const * pItemProto); - bool EffectDummyCreature(Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget); - bool EffectDummyGameObj(Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget); - bool EffectDummyItem(Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget); - InstanceData* CreateInstanceData(Map *map); -}; - -//Config file accessors -//std::string GetConfigValueStr(char const* option); -//int32 GetConfigValueInt32(char const* option); -//float GetConfigValueFloat(char const* option); - -//Generic scripting text function -void DoScriptText(int32 textEntry, WorldObject* pSource, Unit *pTarget = NULL); - -#if COMPILER == COMPILER_GNU -#define FUNC_PTR(name,callconvention,returntype,parameters) typedef returntype(*name)parameters __attribute__ ((callconvention)); -#else -#define FUNC_PTR(name, callconvention, returntype, parameters) typedef returntype(callconvention *name)parameters; -#endif - -#define sScriptMgr Trinity::Singleton::Instance() -#endif - diff --git a/src/server/game/ScriptMgr/ScriptSystem.cpp b/src/server/game/ScriptMgr/ScriptSystem.cpp deleted file mode 100644 index 0037b100412..00000000000 --- a/src/server/game/ScriptMgr/ScriptSystem.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * Thanks to the original authors: MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ScriptSystem.h" -#include "ProgressBar.h" -#include "ObjectMgr.h" -#include "Database/DatabaseEnv.h" - -SystemMgr::SystemMgr() -{ -} - -SystemMgr& SystemMgr::Instance() -{ - static SystemMgr pSysMgr; - return pSysMgr; -} - -void SystemMgr::LoadVersion() -{ - //Get Version information - QueryResult_AutoPtr Result = WorldDatabase.Query("SELECT script_version FROM version LIMIT 1"); - - if (Result) - { - Field* pFields = Result->Fetch(); - - outstring_log("TSCR: Database version is: %s", pFields[0].GetString()); - outstring_log(""); - } - else - { - error_log("TSCR: Missing `version`.`script_version` information."); - outstring_log(""); - } -} - -void SystemMgr::LoadScriptTexts() -{ - outstring_log("TSCR: Loading Script Texts..."); - LoadTrinityStrings(WorldDatabase,"script_texts",TEXT_SOURCE_RANGE,1+(TEXT_SOURCE_RANGE*2)); - - QueryResult_AutoPtr Result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM script_texts"); - - outstring_log("TSCR: Loading Script Texts additional data..."); - - if (Result) - { - barGoLink bar(Result->GetRowCount()); - uint32 uiCount = 0; - - do - { - bar.step(); - Field* pFields = Result->Fetch(); - StringTextData pTemp; - - int32 iId = pFields[0].GetInt32(); - pTemp.uiSoundId = pFields[1].GetUInt32(); - pTemp.uiType = pFields[2].GetUInt32(); - pTemp.uiLanguage = pFields[3].GetUInt32(); - pTemp.uiEmote = pFields[4].GetUInt32(); - - if (iId >= 0) - { - error_db_log("TSCR: Entry %i in table `script_texts` is not a negative value.", iId); - continue; - } - - if (iId > TEXT_SOURCE_RANGE || iId <= TEXT_SOURCE_RANGE*2) - { - error_db_log("TSCR: Entry %i in table `script_texts` is out of accepted entry range for table.", iId); - continue; - } - - if (pTemp.uiSoundId) - { - if (!GetSoundEntriesStore()->LookupEntry(pTemp.uiSoundId)) - error_db_log("TSCR: Entry %i in table `script_texts` has soundId %u but sound does not exist.", iId, pTemp.uiSoundId); - } - - if (!GetLanguageDescByID(pTemp.uiLanguage)) - error_db_log("TSCR: Entry %i in table `script_texts` using Language %u but Language does not exist.", iId, pTemp.uiLanguage); - - if (pTemp.uiType > CHAT_TYPE_ZONE_YELL) - error_db_log("TSCR: Entry %i in table `script_texts` has Type %u but this Chat Type does not exist.", iId, pTemp.uiType); - - m_mTextDataMap[iId] = pTemp; - ++uiCount; - } while (Result->NextRow()); - - outstring_log(""); - outstring_log(">> Loaded %u additional Script Texts data.", uiCount); - } - else - { - barGoLink bar(1); - bar.step(); - outstring_log(""); - outstring_log(">> Loaded 0 additional Script Texts data. DB table `script_texts` is empty."); - } -} - -void SystemMgr::LoadScriptTextsCustom() -{ - outstring_log("TSCR: Loading Custom Texts..."); - LoadTrinityStrings(WorldDatabase,"custom_texts",TEXT_SOURCE_RANGE*2,1+(TEXT_SOURCE_RANGE*3)); - - QueryResult_AutoPtr Result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM custom_texts"); - - outstring_log("TSCR: Loading Custom Texts additional data..."); - - if (Result) - { - barGoLink bar(Result->GetRowCount()); - uint32 uiCount = 0; - - do - { - bar.step(); - Field* pFields = Result->Fetch(); - StringTextData pTemp; - - int32 iId = pFields[0].GetInt32(); - pTemp.uiSoundId = pFields[1].GetUInt32(); - pTemp.uiType = pFields[2].GetUInt32(); - pTemp.uiLanguage = pFields[3].GetUInt32(); - pTemp.uiEmote = pFields[4].GetUInt32(); - - if (iId >= 0) - { - error_db_log("TSCR: Entry %i in table `custom_texts` is not a negative value.", iId); - continue; - } - - if (iId > TEXT_SOURCE_RANGE*2 || iId <= TEXT_SOURCE_RANGE*3) - { - error_db_log("TSCR: Entry %i in table `custom_texts` is out of accepted entry range for table.", iId); - continue; - } - - if (pTemp.uiSoundId) - { - if (!GetSoundEntriesStore()->LookupEntry(pTemp.uiSoundId)) - error_db_log("TSCR: Entry %i in table `custom_texts` has soundId %u but sound does not exist.", iId, pTemp.uiSoundId); - } - - if (!GetLanguageDescByID(pTemp.uiLanguage)) - error_db_log("TSCR: Entry %i in table `custom_texts` using Language %u but Language does not exist.", iId, pTemp.uiLanguage); - - if (pTemp.uiType > CHAT_TYPE_ZONE_YELL) - error_db_log("TSCR: Entry %i in table `custom_texts` has Type %u but this Chat Type does not exist.", iId, pTemp.uiType); - - m_mTextDataMap[iId] = pTemp; - ++uiCount; - } while (Result->NextRow()); - - outstring_log(""); - outstring_log(">> Loaded %u additional Custom Texts data.", uiCount); - } - else - { - barGoLink bar(1); - bar.step(); - outstring_log(""); - outstring_log(">> Loaded 0 additional Custom Texts data. DB table `custom_texts` is empty."); - } -} - -void SystemMgr::LoadScriptWaypoints() -{ - // Drop Existing Waypoint list - m_mPointMoveMap.clear(); - - uint64 uiCreatureCount = 0; - - // Load Waypoints - QueryResult_AutoPtr Result = WorldDatabase.Query("SELECT COUNT(entry) FROM script_waypoint GROUP BY entry"); - if (Result) - uiCreatureCount = Result->GetRowCount(); - - outstring_log("TSCR: Loading Script Waypoints for %u creature(s)...", uiCreatureCount); - - Result = WorldDatabase.Query("SELECT entry, pointid, location_x, location_y, location_z, waittime FROM script_waypoint ORDER BY pointid"); - - if (Result) - { - barGoLink bar(Result->GetRowCount()); - uint32 uiNodeCount = 0; - - do - { - bar.step(); - Field* pFields = Result->Fetch(); - ScriptPointMove pTemp; - - pTemp.uiCreatureEntry = pFields[0].GetUInt32(); - uint32 uiEntry = pTemp.uiCreatureEntry; - pTemp.uiPointId = pFields[1].GetUInt32(); - pTemp.fX = pFields[2].GetFloat(); - pTemp.fY = pFields[3].GetFloat(); - pTemp.fZ = pFields[4].GetFloat(); - pTemp.uiWaitTime = pFields[5].GetUInt32(); - - CreatureInfo const* pCInfo = GetCreatureTemplateStore(pTemp.uiCreatureEntry); - - if (!pCInfo) - { - error_db_log("TSCR: DB table script_waypoint has waypoint for non-existant creature entry %u", pTemp.uiCreatureEntry); - continue; - } - - if (!pCInfo->ScriptID) - error_db_log("TSCR: DB table script_waypoint has waypoint for creature entry %u, but creature does not have ScriptName defined and then useless.", pTemp.uiCreatureEntry); - - m_mPointMoveMap[uiEntry].push_back(pTemp); - ++uiNodeCount; - } while (Result->NextRow()); - - outstring_log(""); - outstring_log(">> Loaded %u Script Waypoint nodes.", uiNodeCount); - } - else - { - barGoLink bar(1); - bar.step(); - outstring_log(""); - outstring_log(">> Loaded 0 Script Waypoints. DB table `script_waypoint` is empty."); - } -} diff --git a/src/server/game/ScriptMgr/ScriptSystem.h b/src/server/game/ScriptMgr/ScriptSystem.h deleted file mode 100644 index f78cd2e64fa..00000000000 --- a/src/server/game/ScriptMgr/ScriptSystem.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef SC_SYSTEM_H -#define SC_SYSTEM_H - -#define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available - -//TODO: find better namings and definitions. -//N=Neutral, A=Alliance, H=Horde. -//NEUTRAL or FRIEND = Hostility to player surroundings (not a good definition) -//ACTIVE or PASSIVE = Hostility to environment surroundings. -enum eEscortFaction -{ - FACTION_ESCORT_A_NEUTRAL_PASSIVE = 10, - FACTION_ESCORT_H_NEUTRAL_PASSIVE = 33, - FACTION_ESCORT_N_NEUTRAL_PASSIVE = 113, - - FACTION_ESCORT_A_NEUTRAL_ACTIVE = 231, - FACTION_ESCORT_H_NEUTRAL_ACTIVE = 232, - FACTION_ESCORT_N_NEUTRAL_ACTIVE = 250, - - FACTION_ESCORT_N_FRIEND_PASSIVE = 290, - FACTION_ESCORT_N_FRIEND_ACTIVE = 495, - - FACTION_ESCORT_A_PASSIVE = 774, - FACTION_ESCORT_H_PASSIVE = 775, - - FACTION_ESCORT_N_ACTIVE = 1986, - FACTION_ESCORT_H_ACTIVE = 2046 -}; - -struct ScriptPointMove -{ - uint32 uiCreatureEntry; - uint32 uiPointId; - float fX; - float fY; - float fZ; - uint32 uiWaitTime; -}; - -struct StringTextData -{ - uint32 uiSoundId; - uint8 uiType; - uint32 uiLanguage; - uint32 uiEmote; -}; - -#define pSystemMgr SystemMgr::Instance() - -class SystemMgr -{ - public: - SystemMgr(); - ~SystemMgr() {} - - static SystemMgr& Instance(); - - //Maps and lists - typedef UNORDERED_MAP TextDataMap; - typedef UNORDERED_MAP > PointMoveMap; - - //Database - void LoadVersion(); - void LoadScriptTexts(); - void LoadScriptTextsCustom(); - void LoadScriptWaypoints(); - - //Retrive from storage - StringTextData const* GetTextData(int32 uiTextId) const - { - TextDataMap::const_iterator itr = m_mTextDataMap.find(uiTextId); - - if (itr == m_mTextDataMap.end()) - return NULL; - - return &itr->second; - } - - std::vector const &GetPointMoveList(uint32 uiCreatureEntry) const - { - static std::vector vEmpty; - - PointMoveMap::const_iterator itr = m_mPointMoveMap.find(uiCreatureEntry); - - if (itr == m_mPointMoveMap.end()) - return vEmpty; - - return itr->second; - } - - protected: - TextDataMap m_mTextDataMap; //additional data for text strings - PointMoveMap m_mPointMoveMap; //coordinates for waypoints -}; - -#endif diff --git a/src/server/game/ScriptMgr/ScriptedPch.cpp b/src/server/game/ScriptMgr/ScriptedPch.cpp deleted file mode 100644 index a80690d05da..00000000000 --- a/src/server/game/ScriptMgr/ScriptedPch.cpp +++ /dev/null @@ -1,6 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#include "ScriptedPch.h" - diff --git a/src/server/game/ScriptMgr/ScriptedPch.h b/src/server/game/ScriptMgr/ScriptedPch.h deleted file mode 100644 index 1e83a88b87a..00000000000 --- a/src/server/game/ScriptMgr/ScriptedPch.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef SC_PRECOMPILED_H -#define SC_PRECOMPILED_H - -#include "ScriptMgr.h" -#include "Cell.h" -#include "CellImpl.h" -#include "GameEventMgr.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "Unit.h" -#include "GameObject.h" -#include "ScriptedCreature.h" -#include "ScriptedGossip.h" -#include "ScriptedInstance.h" -#include "CombatAI.h" -#include "PassiveAI.h" -#include "Chat.h" -#include "DBCStructure.h" -#include "DBCStores.h" -#include "ObjectMgr.h" - -#ifdef WIN32 -#include - -#endif - -#endif - diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp new file mode 100644 index 00000000000..2006c091287 --- /dev/null +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -0,0 +1,1023 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" + +#ifdef WIN32 + #define DO_SCRIPTS +#endif + +#ifdef DO_SCRIPTS +//custom + +//examples +void AddSC_example_creature(); +void AddSC_example_escort(); +void AddSC_example_gossip_codebox(); +void AddSC_example_misc(); + +//world +void AddSC_areatrigger_scripts(); +void AddSC_boss_emeriss(); +void AddSC_boss_taerar(); +void AddSC_boss_ysondre(); +void AddSC_generic_creature(); +void AddSC_go_scripts(); +void AddSC_guards(); +void AddSC_item_scripts(); +void AddSC_npc_professions(); +void AddSC_npc_innkeeper(); +void AddSC_npcs_special(); +void AddSC_npc_taxi(); + +//eastern kingdoms +void AddSC_alterac_valley(); //Alterac Valley +void AddSC_boss_balinda(); +void AddSC_boss_drekthar(); +void AddSC_boss_galvangar(); +void AddSC_boss_vanndar(); +void AddSC_blackrock_depths(); //Blackrock Depths +void AddSC_boss_ambassador_flamelash(); +void AddSC_boss_anubshiah(); +void AddSC_boss_draganthaurissan(); +void AddSC_boss_general_angerforge(); +void AddSC_boss_gorosh_the_dervish(); +void AddSC_boss_grizzle(); +void AddSC_boss_high_interrogator_gerstahn(); +void AddSC_boss_magmus(); +void AddSC_boss_moira_bronzebeard(); +void AddSC_boss_tomb_of_seven(); +void AddSC_instance_blackrock_depths(); +void AddSC_blackrock_spire(); //Blackrock Spire +void AddSC_boss_drakkisath(); +void AddSC_boss_halycon(); +void AddSC_boss_highlordomokk(); +void AddSC_boss_mothersmolderweb(); +void AddSC_boss_overlordwyrmthalak(); +void AddSC_boss_shadowvosh(); +void AddSC_boss_thebeast(); +void AddSC_boss_warmastervoone(); +void AddSC_boss_quatermasterzigris(); +void AddSC_boss_pyroguard_emberseer(); +void AddSC_boss_gyth(); +void AddSC_boss_rend_blackhand(); +void AddSC_instance_blackrock_spire(); +void AddSC_boss_razorgore(); //Blackwing lair +void AddSC_boss_vael(); +void AddSC_boss_broodlord(); +void AddSC_boss_firemaw(); +void AddSC_boss_ebonroc(); +void AddSC_boss_flamegor(); +void AddSC_boss_chromaggus(); +void AddSC_boss_nefarian(); +void AddSC_boss_victor_nefarius(); +void AddSC_boss_mr_smite(); +void AddSC_deadmines(); //Deadmines +void AddSC_instance_deadmines(); +void AddSC_gnomeregan(); //Gnomeregan +void AddSC_instance_gnomeregan(); +void AddSC_boss_attumen(); //Karazhan +void AddSC_boss_curator(); +void AddSC_boss_maiden_of_virtue(); +void AddSC_boss_shade_of_aran(); +void AddSC_boss_malchezaar(); +void AddSC_boss_terestian_illhoof(); +void AddSC_boss_moroes(); +void AddSC_bosses_opera(); +void AddSC_boss_netherspite(); +void AddSC_instance_karazhan(); +void AddSC_karazhan(); +void AddSC_boss_nightbane(); +void AddSC_boss_felblood_kaelthas(); // Magister's Terrace +void AddSC_boss_selin_fireheart(); +void AddSC_boss_vexallus(); +void AddSC_boss_priestess_delrissa(); +void AddSC_instance_magisters_terrace(); +void AddSC_magisters_terrace(); +void AddSC_boss_lucifron(); //Molten core +void AddSC_boss_magmadar(); +void AddSC_boss_gehennas(); +void AddSC_boss_garr(); +void AddSC_boss_baron_geddon(); +void AddSC_boss_shazzrah(); +void AddSC_boss_golemagg(); +void AddSC_boss_sulfuron(); +void AddSC_boss_majordomo(); +void AddSC_boss_ragnaros(); +void AddSC_instance_molten_core(); +void AddSC_molten_core(); +void AddSC_the_scarlet_enclave(); //Scarlet Enclave +void AddSC_the_scarlet_enclave_c1(); +void AddSC_the_scarlet_enclave_c2(); +void AddSC_the_scarlet_enclave_c5(); +void AddSC_boss_arcanist_doan(); //Scarlet Monastery +void AddSC_boss_azshir_the_sleepless(); +void AddSC_boss_bloodmage_thalnos(); +void AddSC_boss_headless_horseman(); +void AddSC_boss_herod(); +void AddSC_boss_high_inquisitor_fairbanks(); +void AddSC_boss_houndmaster_loksey(); +void AddSC_boss_interrogator_vishas(); +void AddSC_boss_scorn(); +void AddSC_instance_scarlet_monastery(); +void AddSC_boss_mograine_and_whitemane(); +void AddSC_boss_darkmaster_gandling(); //Scholomance +void AddSC_boss_death_knight_darkreaver(); +void AddSC_boss_theolenkrastinov(); +void AddSC_boss_illuciabarov(); +void AddSC_boss_instructormalicia(); +void AddSC_boss_jandicebarov(); +void AddSC_boss_kormok(); +void AddSC_boss_lordalexeibarov(); +void AddSC_boss_lorekeeperpolkelt(); +void AddSC_boss_rasfrost(); +void AddSC_boss_theravenian(); +void AddSC_boss_vectus(); +void AddSC_instance_scholomance(); +void AddSC_shadowfang_keep(); //Shadowfang keep +void AddSC_instance_shadowfang_keep(); +void AddSC_boss_magistrate_barthilas(); //Stratholme +void AddSC_boss_maleki_the_pallid(); +void AddSC_boss_nerubenkan(); +void AddSC_boss_cannon_master_willey(); +void AddSC_boss_baroness_anastari(); +void AddSC_boss_ramstein_the_gorger(); +void AddSC_boss_timmy_the_cruel(); +void AddSC_boss_postmaster_malown(); +void AddSC_boss_baron_rivendare(); +void AddSC_boss_dathrohan_balnazzar(); +void AddSC_boss_order_of_silver_hand(); +void AddSC_instance_stratholme(); +void AddSC_stratholme(); +void AddSC_sunken_temple(); // Sunken Temple +void AddSC_instance_sunken_temple(); +void AddSC_instance_sunwell_plateau(); //Sunwell Plateau +void AddSC_boss_kalecgos(); +void AddSC_boss_brutallus(); +void AddSC_boss_felmyst(); +void AddSC_boss_eredar_twins(); +void AddSC_boss_muru(); +void AddSC_boss_kiljaeden(); +void AddSC_sunwell_plateau(); +void AddSC_boss_archaedas(); //Uldaman +void AddSC_boss_ironaya(); +void AddSC_uldaman(); +void AddSC_instance_uldaman(); +void AddSC_boss_akilzon(); //Zul'Aman +void AddSC_boss_halazzi(); +void AddSC_boss_hex_lord_malacrass(); +void AddSC_boss_janalai(); +void AddSC_boss_nalorakk(); +void AddSC_boss_zuljin(); +void AddSC_instance_zulaman(); +void AddSC_zulaman(); +void AddSC_boss_jeklik(); //Zul'Gurub +void AddSC_boss_venoxis(); +void AddSC_boss_marli(); +void AddSC_boss_mandokir(); +void AddSC_boss_gahzranka(); +void AddSC_boss_thekal(); +void AddSC_boss_arlokk(); +void AddSC_boss_jindo(); +void AddSC_boss_hakkar(); +void AddSC_boss_grilek(); +void AddSC_boss_hazzarah(); +void AddSC_boss_renataki(); +void AddSC_boss_wushoolay(); +void AddSC_instance_zulgurub(); + +//void AddSC_alterac_mountains(); +void AddSC_arathi_highlands(); +void AddSC_blasted_lands(); +void AddSC_boss_kruul(); +void AddSC_burning_steppes(); +void AddSC_dun_morogh(); +void AddSC_duskwood(); +void AddSC_eastern_plaguelands(); +void AddSC_elwynn_forest(); +void AddSC_eversong_woods(); +void AddSC_ghostlands(); +void AddSC_hinterlands(); +void AddSC_ironforge(); +void AddSC_isle_of_queldanas(); +void AddSC_loch_modan(); +void AddSC_redridge_mountains(); +void AddSC_searing_gorge(); +void AddSC_silvermoon_city(); +void AddSC_silverpine_forest(); +void AddSC_stormwind_city(); +void AddSC_stranglethorn_vale(); +void AddSC_tirisfal_glades(); +void AddSC_undercity(); +void AddSC_western_plaguelands(); +void AddSC_westfall(); +void AddSC_wetlands(); + +//kalimdor +void AddSC_blackfathom_deeps(); //Blackfathom Depths +void AddSC_boss_gelihast(); +void AddSC_boss_kelris(); +void AddSC_boss_aku_mai(); +void AddSC_instance_blackfathom_deeps(); +void AddSC_hyjal(); //CoT Battle for Mt. Hyjal +void AddSC_boss_archimonde(); +void AddSC_instance_mount_hyjal(); +void AddSC_hyjal_trash(); +void AddSC_boss_rage_winterchill(); +void AddSC_boss_anetheron(); +void AddSC_boss_kazrogal(); +void AddSC_boss_azgalor(); +void AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad +void AddSC_boss_epoch_hunter(); +void AddSC_boss_lieutenant_drake(); +void AddSC_instance_old_hillsbrad(); +void AddSC_old_hillsbrad(); +void AddSC_boss_aeonus(); //CoT The Dark Portal +void AddSC_boss_chrono_lord_deja(); +void AddSC_boss_temporus(); +void AddSC_dark_portal(); +void AddSC_instance_dark_portal(); +void AddSC_boss_epoch(); //CoT Culling Of Stratholme +void AddSC_boss_infinite_corruptor(); +void AddSC_boss_salramm(); +void AddSC_boss_mal_ganis(); +void AddSC_boss_meathook(); +void AddSC_culling_of_stratholme(); +void AddSC_instance_culling_of_stratholme(); +void AddSC_boss_celebras_the_cursed(); //Maraudon +void AddSC_boss_landslide(); +void AddSC_boss_noxxion(); +void AddSC_boss_ptheradras(); +void AddSC_boss_onyxia(); //Onyxia's Lair +void AddSC_instance_onyxias_lair(); +void AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs +void AddSC_razorfen_downs(); +void AddSC_instance_razorfen_downs(); +void AddSC_razorfen_kraul(); //Razorfen Kraul +void AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj +void AddSC_boss_rajaxx(); +void AddSC_boss_moam(); +void AddSC_boss_buru(); +void AddSC_boss_ayamiss(); +void AddSC_boss_ossirian(); +void AddSC_instance_ruins_of_ahnqiraj(); +void AddSC_boss_cthun(); //Temple of ahn'qiraj +void AddSC_boss_fankriss(); +void AddSC_boss_huhuran(); +void AddSC_bug_trio(); +void AddSC_boss_sartura(); +void AddSC_boss_skeram(); +void AddSC_boss_twinemperors(); +void AddSC_mob_anubisath_sentinel(); +void AddSC_instance_temple_of_ahnqiraj(); +void AddSC_wailing_caverns(); //Wailing caverns +void AddSC_instance_wailing_caverns(); +void AddSC_zulfarrak(); //Zul'Farrak generic +void AddSC_instance_zulfarrak(); //Zul'Farrak instance script + +void AddSC_ashenvale(); +void AddSC_azshara(); +void AddSC_azuremyst_isle(); +void AddSC_bloodmyst_isle(); +void AddSC_boss_azuregos(); +void AddSC_darkshore(); +void AddSC_desolace(); +void AddSC_durotar(); +void AddSC_dustwallow_marsh(); +void AddSC_felwood(); +void AddSC_feralas(); +void AddSC_moonglade(); +void AddSC_mulgore(); +void AddSC_orgrimmar(); +void AddSC_silithus(); +void AddSC_stonetalon_mountains(); +void AddSC_tanaris(); +void AddSC_teldrassil(); +void AddSC_the_barrens(); +void AddSC_thousand_needles(); +void AddSC_thunder_bluff(); +void AddSC_ungoro_crater(); +void AddSC_winterspring(); + +//northrend +void AddSC_boss_slad_ran(); +void AddSC_boss_moorabi(); +void AddSC_boss_drakkari_colossus(); +void AddSC_boss_gal_darah(); +void AddSC_boss_eck(); +void AddSC_instance_gundrak(); +void AddSC_boss_krik_thir(); //Azjol-Nerub +void AddSC_boss_hadronox(); +void AddSC_boss_anub_arak(); +void AddSC_instance_azjol_nerub(); +void AddSC_instance_ahnkahet(); //Azjol-Nerub Ahn'kahet +void AddSC_boss_amanitar(); +void AddSC_boss_taldaram(); +void AddSC_boss_jedoga_shadowseeker(); +void AddSC_boss_elder_nadox(); +void AddSC_boss_volazj(); +void AddSC_boss_argent_challenge(); //Trial of the Champion +void AddSC_boss_black_knight(); +void AddSC_boss_grand_champions(); +void AddSC_instance_trial_of_the_champion(); +void AddSC_trial_of_the_champion(); +void AddSC_boss_anubrekhan(); //Naxxramas +void AddSC_boss_maexxna(); +void AddSC_boss_patchwerk(); +void AddSC_boss_grobbulus(); +void AddSC_boss_razuvious(); +void AddSC_boss_kelthuzad(); +void AddSC_boss_loatheb(); +void AddSC_boss_noth(); +void AddSC_boss_gluth(); +void AddSC_boss_sapphiron(); +void AddSC_boss_four_horsemen(); +void AddSC_boss_faerlina(); +void AddSC_boss_heigan(); +void AddSC_boss_gothik(); +void AddSC_boss_thaddius(); +void AddSC_instance_naxxramas(); +void AddSC_boss_magus_telestra(); //The Nexus Nexus +void AddSC_boss_anomalus(); +void AddSC_boss_ormorok(); +void AddSC_boss_keristrasza(); +void AddSC_instance_nexus(); +void AddSC_boss_drakos(); //The Nexus The Oculus +void AddSC_boss_urom(); +void AddSC_instance_oculus(); +void AddSC_oculus(); +void AddSC_boss_sartharion(); //Obsidian Sanctum +void AddSC_instance_obsidian_sanctum(); +void AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning +void AddSC_boss_loken(); +void AddSC_boss_ionar(); +void AddSC_boss_volkhan(); +void AddSC_instance_halls_of_lightning(); +void AddSC_boss_maiden_of_grief(); //Ulduar Halls of Stone +void AddSC_boss_krystallus(); +void AddSC_boss_sjonnir(); +void AddSC_instance_halls_of_stone(); +void AddSC_halls_of_stone(); +void AddSC_boss_auriaya(); //Ulduar Ulduar +void AddSC_boss_flame_leviathan(); +void AddSC_boss_ignis(); +void AddSC_boss_razorscale(); +void AddSC_boss_xt002(); +void AddSC_boss_kologarn(); +void AddSC_boss_assembly_of_iron(); +void AddSC_ulduar_teleporter(); +void AddSC_instance_ulduar(); +void AddSC_boss_keleseth(); //Utgarde Keep +void AddSC_boss_skarvald_dalronn(); +void AddSC_boss_ingvar_the_plunderer(); +void AddSC_instance_utgarde_keep(); +void AddSC_boss_svala(); //Utgarde pinnacle +void AddSC_boss_palehoof(); +void AddSC_boss_skadi(); +void AddSC_boss_ymiron(); +void AddSC_instance_utgarde_pinnacle(); +void AddSC_utgarde_keep(); +void AddSC_boss_archavon(); //Vault of Archavon +void AddSC_boss_emalon(); +void AddSC_boss_koralon(); +void AddSC_boss_toravon(); +void AddSC_instance_archavon(); +void AddSC_boss_trollgore(); //Drak'Tharon Keep +void AddSC_boss_novos(); +void AddSC_boss_dred(); +void AddSC_boss_tharon_ja(); +void AddSC_instance_drak_tharon(); +void AddSC_boss_cyanigosa(); //Violet Hold +void AddSC_boss_erekem(); +void AddSC_boss_ichoron(); +void AddSC_boss_lavanthor(); +void AddSC_boss_moragg(); +void AddSC_boss_xevozz(); +void AddSC_boss_zuramat(); +void AddSC_instance_violet_hold(); +void AddSC_violet_hold(); +void AddSC_instance_forge_of_souls(); //Forge of Souls +void AddSC_forge_of_souls(); +void AddSC_boss_bronjahm(); +void AddSC_boss_devourer_of_souls(); +void AddSC_instance_pit_of_saron(); //Pit of Saron +void AddSC_pit_of_saron(); +void AddSC_boss_garfrost(); +void AddSC_boss_ick(); +void AddSC_boss_tyrannus(); +void AddSC_instance_halls_of_reflection(); // Halls of Reflection +void AddSC_halls_of_reflection(); +void AddSC_boss_falric(); +void AddSC_boss_marwyn(); + +void AddSC_dalaran(); +void AddSC_borean_tundra(); +void AddSC_dragonblight(); +void AddSC_grizzly_hills(); +void AddSC_howling_fjord(); +void AddSC_icecrown(); +void AddSC_sholazar_basin(); +void AddSC_storm_peaks(); +void AddSC_zuldrak(); +void AddSC_crystalsong_forest(); + +//outland +void AddSC_boss_exarch_maladaar(); //Auchindoun Auchenai Crypts +void AddSC_boss_shirrak_the_dead_watcher(); +void AddSC_boss_nexusprince_shaffar(); //Auchindoun Mana Tombs +void AddSC_boss_pandemonius(); +void AddSC_boss_darkweaver_syth(); //Auchindoun Sekketh Halls +void AddSC_boss_talon_king_ikiss(); +void AddSC_instance_sethekk_halls(); +void AddSC_instance_shadow_labyrinth(); //Auchindoun Shadow Labyrinth +void AddSC_boss_ambassador_hellmaw(); +void AddSC_boss_blackheart_the_inciter(); +void AddSC_boss_grandmaster_vorpil(); +void AddSC_boss_murmur(); +void AddSC_black_temple(); //Black Temple +void AddSC_boss_illidan(); +void AddSC_boss_shade_of_akama(); +void AddSC_boss_supremus(); +void AddSC_boss_gurtogg_bloodboil(); +void AddSC_boss_mother_shahraz(); +void AddSC_boss_reliquary_of_souls(); +void AddSC_boss_teron_gorefiend(); +void AddSC_boss_najentus(); +void AddSC_boss_illidari_council(); +void AddSC_instance_black_temple(); +void AddSC_boss_fathomlord_karathress(); //CR Serpent Shrine Cavern +void AddSC_boss_hydross_the_unstable(); +void AddSC_boss_lady_vashj(); +void AddSC_boss_leotheras_the_blind(); +void AddSC_boss_morogrim_tidewalker(); +void AddSC_instance_serpentshrine_cavern(); +void AddSC_boss_the_lurker_below(); +void AddSC_boss_hydromancer_thespia(); //CR Steam Vault +void AddSC_boss_mekgineer_steamrigger(); +void AddSC_boss_warlord_kalithresh(); +void AddSC_instance_steam_vault(); +void AddSC_boss_hungarfen(); //CR Underbog +void AddSC_boss_the_black_stalker(); +void AddSC_boss_gruul(); //Gruul's Lair +void AddSC_boss_high_king_maulgar(); +void AddSC_instance_gruuls_lair(); +void AddSC_boss_broggok(); //HC Blood Furnace +void AddSC_boss_kelidan_the_breaker(); +void AddSC_boss_the_maker(); +void AddSC_instance_blood_furnace(); +void AddSC_boss_magtheridon(); //HC Magtheridon's Lair +void AddSC_instance_magtheridons_lair(); +void AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls +void AddSC_boss_warbringer_omrogg(); +void AddSC_boss_warchief_kargath_bladefist(); +void AddSC_instance_shattered_halls(); +void AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts +void AddSC_boss_omor_the_unscarred(); +void AddSC_boss_vazruden_the_herald(); +void AddSC_instance_ramparts(); +void AddSC_arcatraz(); //TK Arcatraz +void AddSC_boss_harbinger_skyriss(); +void AddSC_instance_arcatraz(); +void AddSC_boss_high_botanist_freywinn(); //TK Botanica +void AddSC_boss_laj(); +void AddSC_boss_warp_splinter(); +void AddSC_boss_alar(); //TK The Eye +void AddSC_boss_kaelthas(); +void AddSC_boss_void_reaver(); +void AddSC_boss_high_astromancer_solarian(); +void AddSC_instance_the_eye(); +void AddSC_the_eye(); +void AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar +void AddSC_boss_nethermancer_sepethrea(); +void AddSC_boss_pathaleon_the_calculator(); +void AddSC_instance_mechanar(); + +void AddSC_blades_edge_mountains(); +void AddSC_boss_doomlordkazzak(); +void AddSC_boss_doomwalker(); +void AddSC_hellfire_peninsula(); +void AddSC_nagrand(); +void AddSC_netherstorm(); +void AddSC_shadowmoon_valley(); +void AddSC_shattrath_city(); +void AddSC_terokkar_forest(); +void AddSC_zangarmarsh(); +void AddSC_onevents(); + +#endif + +void AddScripts() +{ +#ifdef DO_SCRIPTS + + //custom + + //examples + AddSC_example_creature(); + AddSC_example_escort(); + AddSC_example_gossip_codebox(); + AddSC_example_misc(); + + //world + AddSC_areatrigger_scripts(); + AddSC_boss_emeriss(); + AddSC_boss_taerar(); + AddSC_boss_ysondre(); + AddSC_generic_creature(); + AddSC_go_scripts(); + AddSC_guards(); + AddSC_item_scripts(); + AddSC_npc_professions(); + AddSC_npc_innkeeper(); + AddSC_npcs_special(); + AddSC_npc_taxi(); + + //eastern kingdoms + AddSC_alterac_valley(); //Alterac Valley + AddSC_boss_balinda(); + AddSC_boss_drekthar(); + AddSC_boss_galvangar(); + AddSC_boss_vanndar(); + AddSC_blackrock_depths(); //Blackrock Depths + AddSC_boss_ambassador_flamelash(); + AddSC_boss_anubshiah(); + AddSC_boss_draganthaurissan(); + AddSC_boss_general_angerforge(); + AddSC_boss_gorosh_the_dervish(); + AddSC_boss_grizzle(); + AddSC_boss_high_interrogator_gerstahn(); + AddSC_boss_magmus(); + AddSC_boss_moira_bronzebeard(); + AddSC_boss_tomb_of_seven(); + AddSC_instance_blackrock_depths(); + AddSC_blackrock_spire(); //Blackrock Spire + AddSC_boss_drakkisath(); + AddSC_boss_halycon(); + AddSC_boss_highlordomokk(); + AddSC_boss_mothersmolderweb(); + AddSC_boss_overlordwyrmthalak(); + AddSC_boss_shadowvosh(); + AddSC_boss_thebeast(); + AddSC_boss_warmastervoone(); + AddSC_boss_quatermasterzigris(); + AddSC_boss_pyroguard_emberseer(); + AddSC_boss_gyth(); + AddSC_boss_rend_blackhand(); + AddSC_instance_blackrock_spire(); + AddSC_boss_razorgore(); //Blackwing lair + AddSC_boss_vael(); + AddSC_boss_broodlord(); + AddSC_boss_firemaw(); + AddSC_boss_ebonroc(); + AddSC_boss_flamegor(); + AddSC_boss_chromaggus(); + AddSC_boss_nefarian(); + AddSC_boss_victor_nefarius(); + AddSC_boss_mr_smite(); + AddSC_deadmines(); //Deadmines + AddSC_instance_deadmines(); + AddSC_gnomeregan(); //Gnomeregan + AddSC_instance_gnomeregan(); + AddSC_boss_attumen(); //Karazhan + AddSC_boss_curator(); + AddSC_boss_maiden_of_virtue(); + AddSC_boss_shade_of_aran(); + AddSC_boss_malchezaar(); + AddSC_boss_terestian_illhoof(); + AddSC_boss_moroes(); + AddSC_bosses_opera(); + AddSC_boss_netherspite(); + AddSC_instance_karazhan(); + AddSC_karazhan(); + AddSC_boss_nightbane(); + AddSC_boss_felblood_kaelthas(); // Magister's Terrace + AddSC_boss_selin_fireheart(); + AddSC_boss_vexallus(); + AddSC_boss_priestess_delrissa(); + AddSC_instance_magisters_terrace(); + AddSC_magisters_terrace(); + AddSC_boss_lucifron(); //Molten core + AddSC_boss_magmadar(); + AddSC_boss_gehennas(); + AddSC_boss_garr(); + AddSC_boss_baron_geddon(); + AddSC_boss_shazzrah(); + AddSC_boss_golemagg(); + AddSC_boss_sulfuron(); + AddSC_boss_majordomo(); + AddSC_boss_ragnaros(); + AddSC_instance_molten_core(); + AddSC_molten_core(); + AddSC_the_scarlet_enclave(); //Scarlet Enclave + AddSC_the_scarlet_enclave_c1(); + AddSC_the_scarlet_enclave_c2(); + AddSC_the_scarlet_enclave_c5(); + AddSC_boss_arcanist_doan(); //Scarlet Monastery + AddSC_boss_azshir_the_sleepless(); + AddSC_boss_bloodmage_thalnos(); + AddSC_boss_headless_horseman(); + AddSC_boss_herod(); + AddSC_boss_high_inquisitor_fairbanks(); + AddSC_boss_houndmaster_loksey(); + AddSC_boss_interrogator_vishas(); + AddSC_boss_scorn(); + AddSC_instance_scarlet_monastery(); + AddSC_boss_mograine_and_whitemane(); + AddSC_boss_darkmaster_gandling(); //Scholomance + AddSC_boss_death_knight_darkreaver(); + AddSC_boss_theolenkrastinov(); + AddSC_boss_illuciabarov(); + AddSC_boss_instructormalicia(); + AddSC_boss_jandicebarov(); + AddSC_boss_kormok(); + AddSC_boss_lordalexeibarov(); + AddSC_boss_lorekeeperpolkelt(); + AddSC_boss_rasfrost(); + AddSC_boss_theravenian(); + AddSC_boss_vectus(); + AddSC_instance_scholomance(); + AddSC_shadowfang_keep(); //Shadowfang keep + AddSC_instance_shadowfang_keep(); + AddSC_boss_magistrate_barthilas(); //Stratholme + AddSC_boss_maleki_the_pallid(); + AddSC_boss_nerubenkan(); + AddSC_boss_cannon_master_willey(); + AddSC_boss_baroness_anastari(); + AddSC_boss_ramstein_the_gorger(); + AddSC_boss_timmy_the_cruel(); + AddSC_boss_postmaster_malown(); + AddSC_boss_baron_rivendare(); + AddSC_boss_dathrohan_balnazzar(); + AddSC_boss_order_of_silver_hand(); + AddSC_instance_stratholme(); + AddSC_stratholme(); + AddSC_sunken_temple(); // Sunken Temple + AddSC_instance_sunken_temple(); + AddSC_instance_sunwell_plateau(); //Sunwell Plateau + AddSC_boss_kalecgos(); + AddSC_boss_brutallus(); + AddSC_boss_felmyst(); + AddSC_boss_eredar_twins(); + AddSC_boss_muru(); + AddSC_boss_kiljaeden(); + AddSC_sunwell_plateau(); + AddSC_boss_archaedas(); //Uldaman + AddSC_boss_ironaya(); + AddSC_uldaman(); + AddSC_instance_uldaman(); + AddSC_boss_akilzon(); //Zul'Aman + AddSC_boss_halazzi(); + AddSC_boss_hex_lord_malacrass(); + AddSC_boss_janalai(); + AddSC_boss_nalorakk(); + AddSC_boss_zuljin(); + AddSC_instance_zulaman(); + AddSC_zulaman(); + AddSC_boss_jeklik(); //Zul'Gurub + AddSC_boss_venoxis(); + AddSC_boss_marli(); + AddSC_boss_mandokir(); + AddSC_boss_gahzranka(); + AddSC_boss_thekal(); + AddSC_boss_arlokk(); + AddSC_boss_jindo(); + AddSC_boss_hakkar(); + AddSC_boss_grilek(); + AddSC_boss_hazzarah(); + AddSC_boss_renataki(); + AddSC_boss_wushoolay(); + AddSC_instance_zulgurub(); + + //AddSC_alterac_mountains(); + AddSC_arathi_highlands(); + AddSC_blasted_lands(); + AddSC_boss_kruul(); + AddSC_burning_steppes(); + AddSC_dun_morogh(); + AddSC_duskwood(); + AddSC_eastern_plaguelands(); + AddSC_elwynn_forest(); + AddSC_eversong_woods(); + AddSC_ghostlands(); + AddSC_hinterlands(); + AddSC_ironforge(); + AddSC_isle_of_queldanas(); + AddSC_loch_modan(); + AddSC_redridge_mountains(); + AddSC_searing_gorge(); + AddSC_silvermoon_city(); + AddSC_silverpine_forest(); + AddSC_stormwind_city(); + AddSC_stranglethorn_vale(); + AddSC_tirisfal_glades(); + AddSC_undercity(); + AddSC_western_plaguelands(); + AddSC_westfall(); + AddSC_wetlands(); + + //kalimdor + AddSC_blackfathom_deeps(); //Blackfathom Depths + AddSC_boss_gelihast(); + AddSC_boss_kelris(); + AddSC_boss_aku_mai(); + AddSC_instance_blackfathom_deeps(); + AddSC_hyjal(); //CoT Battle for Mt. Hyjal + AddSC_boss_archimonde(); + AddSC_instance_mount_hyjal(); + AddSC_hyjal_trash(); + AddSC_boss_rage_winterchill(); + AddSC_boss_anetheron(); + AddSC_boss_kazrogal(); + AddSC_boss_azgalor(); + AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad + AddSC_boss_epoch_hunter(); + AddSC_boss_lieutenant_drake(); + AddSC_instance_old_hillsbrad(); + AddSC_old_hillsbrad(); + AddSC_boss_aeonus(); //CoT The Dark Portal + AddSC_boss_chrono_lord_deja(); + AddSC_boss_temporus(); + AddSC_dark_portal(); + AddSC_instance_dark_portal(); + AddSC_boss_epoch(); //CoT Culling Of Stratholme + AddSC_boss_infinite_corruptor(); + AddSC_boss_salramm(); + AddSC_boss_mal_ganis(); + AddSC_boss_meathook(); + AddSC_culling_of_stratholme(); + AddSC_instance_culling_of_stratholme(); + AddSC_boss_celebras_the_cursed(); //Maraudon + AddSC_boss_landslide(); + AddSC_boss_noxxion(); + AddSC_boss_ptheradras(); + AddSC_boss_onyxia(); //Onyxia's Lair + AddSC_instance_onyxias_lair(); + AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs + AddSC_razorfen_downs(); + AddSC_instance_razorfen_downs(); + AddSC_razorfen_kraul(); //Razorfen Kraul + AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj + AddSC_boss_rajaxx(); + AddSC_boss_moam(); + AddSC_boss_buru(); + AddSC_boss_ayamiss(); + AddSC_boss_ossirian(); + AddSC_instance_ruins_of_ahnqiraj(); + AddSC_boss_cthun(); //Temple of ahn'qiraj + AddSC_boss_fankriss(); + AddSC_boss_huhuran(); + AddSC_bug_trio(); + AddSC_boss_sartura(); + AddSC_boss_skeram(); + AddSC_boss_twinemperors(); + AddSC_mob_anubisath_sentinel(); + AddSC_instance_temple_of_ahnqiraj(); + AddSC_wailing_caverns(); //Wailing caverns + AddSC_instance_wailing_caverns(); + AddSC_zulfarrak(); //Zul'Farrak generic + AddSC_instance_zulfarrak(); //Zul'Farrak instance script + + AddSC_ashenvale(); + AddSC_azshara(); + AddSC_azuremyst_isle(); + AddSC_bloodmyst_isle(); + AddSC_boss_azuregos(); + AddSC_darkshore(); + AddSC_desolace(); + AddSC_durotar(); + AddSC_dustwallow_marsh(); + AddSC_felwood(); + AddSC_feralas(); + AddSC_moonglade(); + AddSC_mulgore(); + AddSC_orgrimmar(); + AddSC_silithus(); + AddSC_stonetalon_mountains(); + AddSC_tanaris(); + AddSC_teldrassil(); + AddSC_the_barrens(); + AddSC_thousand_needles(); + AddSC_thunder_bluff(); + AddSC_ungoro_crater(); + AddSC_winterspring(); + + //northrend + AddSC_boss_slad_ran(); //Gundrak + AddSC_boss_moorabi(); + AddSC_boss_drakkari_colossus(); + AddSC_boss_gal_darah(); + AddSC_boss_eck(); + AddSC_instance_gundrak(); + AddSC_boss_amanitar(); + AddSC_boss_taldaram(); //Azjol-Nerub Ahn'kahet + AddSC_boss_elder_nadox(); + AddSC_boss_jedoga_shadowseeker(); + AddSC_boss_volazj(); + AddSC_instance_ahnkahet(); + AddSC_boss_argent_challenge(); //Trial of the Champion + AddSC_boss_black_knight(); + AddSC_boss_grand_champions(); + AddSC_instance_trial_of_the_champion(); + AddSC_trial_of_the_champion(); + AddSC_boss_krik_thir(); //Azjol-Nerub Azjol-Nerub + AddSC_boss_hadronox(); + AddSC_boss_anub_arak(); + AddSC_instance_azjol_nerub(); + AddSC_boss_anubrekhan(); //Naxxramas + AddSC_boss_maexxna(); + AddSC_boss_patchwerk(); + AddSC_boss_grobbulus(); + AddSC_boss_razuvious(); + AddSC_boss_kelthuzad(); + AddSC_boss_loatheb(); + AddSC_boss_noth(); + AddSC_boss_gluth(); + AddSC_boss_sapphiron(); + AddSC_boss_four_horsemen(); + AddSC_boss_faerlina(); + AddSC_boss_heigan(); + AddSC_boss_gothik(); + AddSC_boss_thaddius(); + AddSC_instance_naxxramas(); + AddSC_boss_magus_telestra(); //The Nexus Nexus + AddSC_boss_anomalus(); + AddSC_boss_ormorok(); + AddSC_boss_keristrasza(); + AddSC_instance_nexus(); + AddSC_boss_drakos(); //The Nexus The Oculus + AddSC_boss_urom(); + AddSC_instance_oculus(); + AddSC_oculus(); + AddSC_boss_sartharion(); //Obsidian Sanctum + AddSC_instance_obsidian_sanctum(); + AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning + AddSC_boss_loken(); + AddSC_boss_ionar(); + AddSC_boss_volkhan(); + AddSC_instance_halls_of_lightning(); + AddSC_boss_maiden_of_grief(); //Ulduar Halls of Stone + AddSC_boss_krystallus(); + AddSC_boss_sjonnir(); + AddSC_instance_halls_of_stone(); + AddSC_halls_of_stone(); + AddSC_boss_auriaya(); //Ulduar Ulduar + AddSC_boss_flame_leviathan(); + AddSC_boss_ignis(); + AddSC_boss_razorscale(); + AddSC_boss_xt002(); + AddSC_boss_assembly_of_iron(); + AddSC_boss_kologarn(); + AddSC_ulduar_teleporter(); + AddSC_instance_ulduar(); + AddSC_boss_keleseth(); //Utgarde Keep + AddSC_boss_skarvald_dalronn(); + AddSC_boss_ingvar_the_plunderer(); + AddSC_instance_utgarde_keep(); + AddSC_boss_svala(); //Utgarde pinnacle + AddSC_boss_palehoof(); + AddSC_boss_skadi(); + AddSC_boss_ymiron(); + AddSC_instance_utgarde_pinnacle(); + AddSC_utgarde_keep(); + AddSC_boss_archavon(); //Vault of Archavon + AddSC_boss_emalon(); + AddSC_boss_koralon(); + AddSC_boss_toravon(); + AddSC_instance_archavon(); + AddSC_boss_trollgore(); //Drak'Tharon Keep + AddSC_boss_novos(); + AddSC_boss_dred(); + AddSC_boss_tharon_ja(); + AddSC_instance_drak_tharon(); + AddSC_boss_cyanigosa(); //Violet Hold + AddSC_boss_erekem(); + AddSC_boss_ichoron(); + AddSC_boss_lavanthor(); + AddSC_boss_moragg(); + AddSC_boss_xevozz(); + AddSC_boss_zuramat(); + AddSC_instance_violet_hold(); + AddSC_violet_hold(); + AddSC_instance_forge_of_souls(); //Forge of Souls + AddSC_forge_of_souls(); + AddSC_boss_bronjahm(); + AddSC_boss_devourer_of_souls(); + AddSC_instance_pit_of_saron(); //Pit of Saron + AddSC_pit_of_saron(); + AddSC_boss_garfrost(); + AddSC_boss_ick(); + AddSC_boss_tyrannus(); + AddSC_instance_halls_of_reflection(); // Halls of Reflection + AddSC_halls_of_reflection(); + AddSC_boss_falric(); + AddSC_boss_marwyn(); + + AddSC_dalaran(); + AddSC_borean_tundra(); + AddSC_dragonblight(); + AddSC_grizzly_hills(); + AddSC_howling_fjord(); + AddSC_icecrown(); + AddSC_sholazar_basin(); + AddSC_storm_peaks(); + AddSC_zuldrak(); + AddSC_crystalsong_forest(); + + //outland + AddSC_boss_exarch_maladaar(); //Auchindoun Auchenai Crypts + AddSC_boss_shirrak_the_dead_watcher(); + AddSC_boss_nexusprince_shaffar(); //Auchindoun Mana Tombs + AddSC_boss_pandemonius(); + AddSC_boss_darkweaver_syth(); //Auchindoun Sekketh Halls + AddSC_boss_talon_king_ikiss(); + AddSC_instance_sethekk_halls(); + AddSC_instance_shadow_labyrinth(); //Auchindoun Shadow Labyrinth + AddSC_boss_ambassador_hellmaw(); + AddSC_boss_blackheart_the_inciter(); + AddSC_boss_grandmaster_vorpil(); + AddSC_boss_murmur(); + AddSC_black_temple(); //Black Temple + AddSC_boss_illidan(); + AddSC_boss_shade_of_akama(); + AddSC_boss_supremus(); + AddSC_boss_gurtogg_bloodboil(); + AddSC_boss_mother_shahraz(); + AddSC_boss_reliquary_of_souls(); + AddSC_boss_teron_gorefiend(); + AddSC_boss_najentus(); + AddSC_boss_illidari_council(); + AddSC_instance_black_temple(); + AddSC_boss_fathomlord_karathress(); //CR Serpent Shrine Cavern + AddSC_boss_hydross_the_unstable(); + AddSC_boss_lady_vashj(); + AddSC_boss_leotheras_the_blind(); + AddSC_boss_morogrim_tidewalker(); + AddSC_instance_serpentshrine_cavern(); + AddSC_boss_the_lurker_below(); + AddSC_boss_hydromancer_thespia(); //CR Steam Vault + AddSC_boss_mekgineer_steamrigger(); + AddSC_boss_warlord_kalithresh(); + AddSC_instance_steam_vault(); + AddSC_boss_hungarfen(); //CR Underbog + AddSC_boss_the_black_stalker(); + AddSC_boss_gruul(); //Gruul's Lair + AddSC_boss_high_king_maulgar(); + AddSC_instance_gruuls_lair(); + AddSC_boss_broggok(); //HC Blood Furnace + AddSC_boss_kelidan_the_breaker(); + AddSC_boss_the_maker(); + AddSC_instance_blood_furnace(); + AddSC_boss_magtheridon(); //HC Magtheridon's Lair + AddSC_instance_magtheridons_lair(); + AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls + AddSC_boss_warbringer_omrogg(); + AddSC_boss_warchief_kargath_bladefist(); + AddSC_instance_shattered_halls(); + AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts + AddSC_boss_omor_the_unscarred(); + AddSC_boss_vazruden_the_herald(); + AddSC_instance_ramparts(); + AddSC_arcatraz(); //TK Arcatraz + AddSC_boss_harbinger_skyriss(); + AddSC_instance_arcatraz(); + AddSC_boss_high_botanist_freywinn(); //TK Botanica + AddSC_boss_laj(); + AddSC_boss_warp_splinter(); + AddSC_boss_alar(); //TK The Eye + AddSC_boss_kaelthas(); + AddSC_boss_void_reaver(); + AddSC_boss_high_astromancer_solarian(); + AddSC_instance_the_eye(); + AddSC_the_eye(); + AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar + AddSC_boss_nethermancer_sepethrea(); + AddSC_boss_pathaleon_the_calculator(); + AddSC_instance_mechanar(); + + AddSC_blades_edge_mountains(); + AddSC_boss_doomlordkazzak(); + AddSC_boss_doomwalker(); + AddSC_hellfire_peninsula(); + AddSC_nagrand(); + AddSC_netherstorm(); + AddSC_shadowmoon_valley(); + AddSC_shattrath_city(); + AddSC_terokkar_forest(); + AddSC_zangarmarsh(); + AddSC_onevents(); + +#endif +} diff --git a/src/server/game/Scripting/ScriptLoader.h b/src/server/game/Scripting/ScriptLoader.h new file mode 100644 index 00000000000..57fb7d821f1 --- /dev/null +++ b/src/server/game/Scripting/ScriptLoader.h @@ -0,0 +1,10 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_SCRIPTLOADER_H +#define SC_SCRIPTLOADER_H + +void AddScripts(); + +#endif diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp new file mode 100644 index 00000000000..2dcfd258942 --- /dev/null +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -0,0 +1,549 @@ +/* Copyright (C) 2006 - 2008 TrinityScript + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#include "ScriptedPch.h" +#include "Config/Config.h" +#include "Database/DatabaseEnv.h" +#include "DBCStores.h" +#include "ObjectMgr.h" +#include "ProgressBar.h" +#include "ScriptLoader.h" +#include "ScriptSystem.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1(ScriptMgr); + +int num_sc_scripts; +Script *m_scripts[MAX_SCRIPTS]; + +void FillSpellSummary(); +void LoadOverridenSQLData(); + +void ScriptMgr::LoadDatabase() +{ + pSystemMgr.LoadVersion(); + pSystemMgr.LoadScriptTexts(); + pSystemMgr.LoadScriptTextsCustom(); + pSystemMgr.LoadScriptWaypoints(); +} + +struct TSpellSummary { + uint8 Targets; // set of enum SelectTarget + uint8 Effects; // set of enum SelectEffect +}extern *SpellSummary; + +ScriptMgr::ScriptMgr() +{ + +} +ScriptMgr::~ScriptMgr() +{ + +} + +void ScriptMgr::ScriptsInit() +{ + //Trinity Script startup + outstring_log(" _____ _ _ _ ____ _ _"); + outstring_log("|_ _| __(_)_ __ (_) |_ _ _/ ___| ___ _ __(_)_ __ | |_ "); + outstring_log(" | || '__| | '_ \\| | __| | | \\___ \\ / __| \'__| | \'_ \\| __|"); + outstring_log(" | || | | | | | | | |_| |_| |___) | (__| | | | |_) | |_ "); + outstring_log(" |_||_| |_|_| |_|_|\\__|\\__, |____/ \\___|_| |_| .__/ \\__|"); + outstring_log(" |___/ |_| "); + outstring_log(""); + outstring_log(""); + + //Load database (must be called after SD2Config.SetSource). + LoadDatabase(); + + outstring_log("TSCR: Loading C++ scripts"); + barGoLink bar(1); + bar.step(); + outstring_log(""); + + for (uint16 i =0; i> Loaded %i C++ Scripts.", num_sc_scripts); + + outstring_log(">> Load Overriden SQL Data."); + LoadOverridenSQLData(); +} + +//********************************* +//*** Functions used globally *** + +void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget) +{ + if (!pSource) + { + error_log("TSCR: DoScriptText entry %i, invalid Source pointer.", iTextEntry); + return; + } + + if (iTextEntry >= 0) + { + error_log("TSCR: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.", pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry); + return; + } + + const StringTextData* pData = pSystemMgr.GetTextData(iTextEntry); + + if (!pData) + { + error_log("TSCR: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.", pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry); + return; + } + + debug_log("TSCR: DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u", iTextEntry, pData->uiSoundId, pData->uiType, pData->uiLanguage, pData->uiEmote); + + if (pData->uiSoundId) + { + if (GetSoundEntriesStore()->LookupEntry(pData->uiSoundId)) + { + pSource->SendPlaySound(pData->uiSoundId, false); + } + else + error_log("TSCR: DoScriptText entry %i tried to process invalid sound id %u.", iTextEntry, pData->uiSoundId); + } + + if (pData->uiEmote) + { + if (pSource->GetTypeId() == TYPEID_UNIT || pSource->GetTypeId() == TYPEID_PLAYER) + ((Unit*)pSource)->HandleEmoteCommand(pData->uiEmote); + else + error_log("TSCR: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", iTextEntry, pSource->GetTypeId()); + } + + switch(pData->uiType) + { + case CHAT_TYPE_SAY: + pSource->MonsterSay(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0); + break; + case CHAT_TYPE_YELL: + pSource->MonsterYell(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0); + break; + case CHAT_TYPE_TEXT_EMOTE: + pSource->MonsterTextEmote(iTextEntry, pTarget ? pTarget->GetGUID() : 0); + break; + case CHAT_TYPE_BOSS_EMOTE: + pSource->MonsterTextEmote(iTextEntry, pTarget ? pTarget->GetGUID() : 0, true); + break; + case CHAT_TYPE_WHISPER: + { + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + pSource->MonsterWhisper(iTextEntry, pTarget->GetGUID()); + else + error_log("TSCR: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry); + } + break; + case CHAT_TYPE_BOSS_WHISPER: + { + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + pSource->MonsterWhisper(iTextEntry, pTarget->GetGUID(), true); + else + error_log("TSCR: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry); + } + break; + case CHAT_TYPE_ZONE_YELL: + pSource->MonsterYellToZone(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0); + break; + } +} + +void Script::RegisterSelf() +{ + // try to find scripts which try to use another script's allocated memory + // that means didn't allocate memory for script + for (uint16 i = 0; i < MAX_SCRIPTS; ++i) + { + // somebody forgot to allocate memory for a script by a method like this: newscript = new Script + if (m_scripts[i] == this) + { + error_log("ScriptName: '%s' - Forgot to allocate memory, so this script and/or the script before that can't work.", Name.c_str()); + // don't register it + // and don't delete it because its memory is used for another script + return; + } + } + + int id = GetScriptId(Name.c_str()); + if (id) + { + // try to find the script in assigned scripts + bool IsExist = false; + for (uint16 i = 0; i < MAX_SCRIPTS; ++i) + { + if (m_scripts[i]) + { + // if the assigned script's name and the new script's name is the same + if (m_scripts[i]->Name == Name) + { + IsExist = true; + break; + } + } + } + + // if the script doesn't assigned -> assign it! + if (!IsExist) + { + m_scripts[id] = this; + ++num_sc_scripts; + } + // if the script is already assigned -> delete it! + else + { + // TODO: write a better error message than this one :) + error_log("ScriptName: '%s' already assigned with the same ScriptName, so the script can't work.", Name.c_str()); + delete this; + } + } + else + { + if (Name.find("example") == std::string::npos) + error_db_log("TrinityScript: RegisterSelf, but script named %s does not have ScriptName assigned in database.",(this)->Name.c_str()); + delete this; + } +} + +void ScriptMgr::OnLogin(Player *pPlayer) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnLogin) return; + tmpscript->pOnLogin(pPlayer); +} + +void ScriptMgr::OnLogout(Player *pPlayer) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnLogout) return; + tmpscript->pOnLogout(pPlayer); +} + +void ScriptMgr::OnPVPKill(Player *killer, Player *killed) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnPVPKill) return; + tmpscript->pOnPVPKill(killer, killed); +} + +bool ScriptMgr::OnSpellCast (Unit *pUnitTarget, Item *pItemTarget, GameObject *pGoTarget, uint32 i, SpellEntry const *spell) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnSpellCast) return true; + return tmpscript->pOnSpellCast(pUnitTarget,pItemTarget,pGoTarget,i,spell); +} + +uint32 ScriptMgr::OnGetXP(Player *pPlayer, uint32 amount) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnGetXP) return amount; + return tmpscript->pOnGetXP(pPlayer,amount); +} + +uint32 ScriptMgr::OnGetMoney(Player *pPlayer, int32 amount) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnGetMoney) return amount; + return tmpscript->pOnGetMoney(pPlayer,amount); +} + +bool ScriptMgr::OnPlayerChat(Player *pPlayer, const char *text) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnPlayerChat) return true; + return tmpscript->pOnPlayerChat(pPlayer,text); +} + +void ScriptMgr::OnServerStartup() +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnServerStartup) return; + tmpscript->pOnServerStartup(); +} + +void ScriptMgr::OnServerShutdown() +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnServerShutdown) return; + tmpscript->pOnServerShutdown(); +} + +void ScriptMgr::OnAreaChange(Player *pPlayer, AreaTableEntry const *pArea) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnAreaChange) return; + tmpscript->pOnAreaChange(pPlayer, pArea); +} + +bool ScriptMgr::OnItemClick (Player *pPlayer, Item *pItem) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnItemClick) return true; + return tmpscript->pOnItemClick(pPlayer,pItem); +} + +bool ScriptMgr::OnItemOpen (Player *pPlayer, Item *pItem) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnItemOpen) return true; + return tmpscript->pOnItemOpen(pPlayer,pItem); +} + +bool ScriptMgr::OnGoClick (Player *pPlayer, GameObject *pGameObject) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnGoClick) return true; + return tmpscript->pOnGoClick(pPlayer,pGameObject); +} + +void ScriptMgr::OnCreatureKill (Player *pPlayer, Creature *pCreature) +{ + Script *tmpscript = m_scripts[GetScriptId("scripted_on_events")]; + if (!tmpscript || !tmpscript->pOnCreatureKill) return; + tmpscript->pOnCreatureKill(pPlayer,pCreature); +} + +char const* ScriptMgr::ScriptsVersion() +{ + return "Integrated Trinity Scripts"; +} + +bool ScriptMgr::GossipHello (Player * pPlayer, Creature* pCreature) +{ + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->pGossipHello) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipHello(pPlayer, pCreature); +} + +bool ScriptMgr::GossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + debug_log("TSCR: Gossip selection, sender: %d, action: %d", uiSender, uiAction); + + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->pGossipSelect) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipSelect(pPlayer, pCreature, uiSender, uiAction); +} + +bool ScriptMgr::GossipSelectWithCode(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode) +{ + debug_log("TSCR: Gossip selection with code, sender: %d, action: %d", uiSender, uiAction); + + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->pGossipSelectWithCode) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGossipSelectWithCode(pPlayer, pCreature, uiSender, uiAction, sCode); +} + +bool ScriptMgr::GOSelect(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction) +{ + if (!pGO) + return false; + debug_log("TSCR: Gossip selection, sender: %d, action: %d", uiSender, uiAction); + + Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; + if (!tmpscript || !tmpscript->pGOSelect) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOSelect(pPlayer, pGO, uiSender, uiAction); +} + +bool ScriptMgr::GOSelectWithCode(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction, const char* sCode) +{ + if (!pGO) + return false; + debug_log("TSCR: Gossip selection, sender: %d, action: %d",uiSender, uiAction); + + Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; + if (!tmpscript || !tmpscript->pGOSelectWithCode) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOSelectWithCode(pPlayer, pGO, uiSender ,uiAction, sCode); +} + +bool ScriptMgr::QuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->pQuestAccept) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestAccept(pPlayer, pCreature, pQuest); +} + +bool ScriptMgr::QuestSelect(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->pQuestSelect) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestSelect(pPlayer, pCreature, pQuest); +} + +bool ScriptMgr::QuestComplete(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->pQuestComplete) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pQuestComplete(pPlayer, pCreature, pQuest); +} + +bool ScriptMgr::ChooseReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt) +{ + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->pChooseReward) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pChooseReward(pPlayer, pCreature, pQuest, opt); +} + +uint32 ScriptMgr::NPCDialogStatus(Player* pPlayer, Creature* pCreature) +{ + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->pNPCDialogStatus) return 100; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pNPCDialogStatus(pPlayer, pCreature); +} + +uint32 ScriptMgr::GODialogStatus(Player* pPlayer, GameObject* pGO) +{ + Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; + if (!tmpscript || !tmpscript->pGODialogStatus) return 100; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGODialogStatus(pPlayer, pGO); +} + +bool ScriptMgr::ItemHello(Player* pPlayer, Item* pItem, Quest const* pQuest) +{ + Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; + if (!tmpscript || !tmpscript->pItemHello) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pItemHello(pPlayer, pItem, pQuest); +} + +bool ScriptMgr::ItemQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest) +{ + Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; + if (!tmpscript || !tmpscript->pItemQuestAccept) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pItemQuestAccept(pPlayer, pItem, pQuest); +} + +bool ScriptMgr::GOHello(Player* pPlayer, GameObject* pGO) +{ + Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; + if (!tmpscript || !tmpscript->pGOHello) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOHello(pPlayer, pGO); +} + +bool ScriptMgr::GOQuestAccept(Player* pPlayer, GameObject* pGO, Quest const* pQuest) +{ + Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; + if (!tmpscript || !tmpscript->pGOQuestAccept) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOQuestAccept(pPlayer, pGO, pQuest); +} + +bool ScriptMgr::GOChooseReward(Player* pPlayer, GameObject* pGO, Quest const* pQuest, uint32 opt) +{ + Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; + if (!tmpscript || !tmpscript->pGOChooseReward) return false; + + pPlayer->PlayerTalkClass->ClearMenus(); + return tmpscript->pGOChooseReward(pPlayer, pGO, pQuest, opt); +} + +void ScriptMgr::GODestroyed(Player* pPlayer, GameObject* pGO, uint32 destroyedEvent) +{ + Script *tmpscript = m_scripts[pGO->GetGOInfo()->ScriptId]; + if (!tmpscript) return; + tmpscript->pGODestroyed(pPlayer, pGO, destroyedEvent); +} + +bool ScriptMgr::AreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry) +{ + Script *tmpscript = m_scripts[GetAreaTriggerScriptId(atEntry->id)]; + if (!tmpscript || !tmpscript->pAreaTrigger) return false; + + return tmpscript->pAreaTrigger(pPlayer, atEntry); +} + +CreatureAI* ScriptMgr::GetAI(Creature* pCreature) +{ + Script *tmpscript = m_scripts[pCreature->GetScriptId()]; + if (!tmpscript || !tmpscript->GetAI) return NULL; + + return tmpscript->GetAI(pCreature); +} + +bool ScriptMgr::ItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) +{ + Script *tmpscript = m_scripts[pItem->GetProto()->ScriptId]; + if (!tmpscript || !tmpscript->pItemUse) return false; + + return tmpscript->pItemUse(pPlayer, pItem, targets); +} + +bool ScriptMgr::ItemExpire(Player* pPlayer, ItemPrototype const * pItemProto) +{ + Script *tmpscript = m_scripts[pItemProto->ScriptId]; + if (!tmpscript || !tmpscript->pItemExpire) return true; + + return tmpscript->pItemExpire(pPlayer, pItemProto); +} + +bool ScriptMgr::EffectDummyCreature(Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget) +{ + Script *tmpscript = m_scripts[crTarget->GetScriptId()]; + + if (!tmpscript || !tmpscript->pEffectDummyCreature) return false; + + return tmpscript->pEffectDummyCreature(caster, spellId, effIndex, crTarget); +} + +bool ScriptMgr::EffectDummyGameObj(Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget) +{ + Script *tmpscript = m_scripts[gameObjTarget->GetGOInfo()->ScriptId]; + + if (!tmpscript || !tmpscript->pEffectDummyGameObj) return false; + + return tmpscript->pEffectDummyGameObj(caster, spellId, effIndex, gameObjTarget); +} + +bool ScriptMgr::EffectDummyItem(Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget) +{ + Script *tmpscript = m_scripts[itemTarget->GetProto()->ScriptId]; + + if (!tmpscript || !tmpscript->pEffectDummyItem) return false; + + return tmpscript->pEffectDummyItem(caster, spellId, effIndex, itemTarget); +} + +InstanceData* ScriptMgr::CreateInstanceData(Map *map) +{ + if (!map->IsDungeon()) return NULL; + + Script *tmpscript = m_scripts[((InstanceMap*)map)->GetScriptId()]; + if (!tmpscript || !tmpscript->GetInstanceData) return NULL; + + return tmpscript->GetInstanceData(map); +} + diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h new file mode 100644 index 00000000000..ed7200d5786 --- /dev/null +++ b/src/server/game/Scripting/ScriptMgr.h @@ -0,0 +1,163 @@ +/* Copyright (C) 2008-2010 Trinity + * + * Thanks to the original authors: ScriptDev2 + * + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_SCRIPTMGR_H +#define SC_SCRIPTMGR_H + +#include "Common.h" +#include "Platform/CompilerDefs.h" +#include "DBCStructure.h" +#include "Config/ConfigEnv.h" + +class Player; +class Creature; +class CreatureAI; +class InstanceData; +class Quest; +class Item; +class GameObject; +class SpellCastTargets; +class Map; +class Unit; +class WorldObject; +struct ItemPrototype; + +#define MAX_SCRIPTS 5000 //72 bytes each (approx 351kb) +#define VISIBLE_RANGE (166.0f) //MAX visible range (size of grid) +#define DEFAULT_TEXT "" + +struct Script +{ + Script() : + pOnLogin(NULL), pOnLogout(NULL), pOnPVPKill(NULL), pOnSpellCast(NULL), pOnGetXP(NULL), + pOnGetMoney(NULL), pOnPlayerChat(NULL), pOnServerStartup(NULL), pOnServerShutdown(NULL), + pOnAreaChange(NULL), pOnItemClick(NULL), pOnItemOpen(NULL), pOnGoClick(NULL), pOnCreatureKill(NULL), + pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL), + pGOSelect(NULL), pGOSelectWithCode(NULL), + pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), + pChooseReward(NULL), pGODestroyed(NULL), pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), + pGOQuestAccept(NULL), pGOChooseReward(NULL),pItemUse(NULL), pItemExpire(NULL), + pEffectDummyCreature(NULL), pEffectDummyGameObj(NULL), pEffectDummyItem(NULL), + GetAI(NULL), GetInstanceData(NULL) + {} + + std::string Name; + + //Methods to be scripted + void (*pOnLogin)(Player*); + void (*pOnLogout)(Player*); + void (*pOnPVPKill)(Player*, Player*); + bool (*pOnSpellCast)(Unit*, Item*, GameObject*, uint32, SpellEntry const*); + uint32 (*pOnGetXP)(Player*, uint32); + int32 (*pOnGetMoney)(Player*, int32); + bool (*pOnPlayerChat)(Player*, const char*); + void (*pOnServerStartup)(); + void (*pOnServerShutdown)(); + void (*pOnAreaChange)(Player*, AreaTableEntry const*); + bool (*pOnItemClick)(Player*, Item*); + bool (*pOnItemOpen)(Player*, Item*); + bool (*pOnGoClick)(Player*, GameObject*); + void (*pOnCreatureKill)(Player*, Creature*); + bool (*pGossipHello)(Player*, Creature*); + bool (*pQuestAccept)(Player*, Creature*, Quest const*); + bool (*pGossipSelect)(Player*, Creature*, uint32 , uint32); + bool (*pGossipSelectWithCode)(Player*, Creature*, uint32 , uint32 , const char*); + bool (*pGOSelect)(Player*, GameObject*, uint32 , uint32); + bool (*pGOSelectWithCode)(Player*, GameObject*, uint32 , uint32 , const char*); + bool (*pQuestSelect)(Player*, Creature*, Quest const*); + bool (*pQuestComplete)(Player*, Creature*, Quest const*); + uint32 (*pNPCDialogStatus)(Player*, Creature*); + uint32 (*pGODialogStatus)(Player*, GameObject * _GO); + bool (*pChooseReward)(Player*, Creature*, Quest const*, uint32); + bool (*pItemHello)(Player*, Item*, Quest const*); + bool (*pGOHello)(Player*, GameObject*); + bool (*pAreaTrigger)(Player*, AreaTriggerEntry const*); + bool (*pItemQuestAccept)(Player*, Item *, Quest const*); + bool (*pGOQuestAccept)(Player*, GameObject*, Quest const*); + bool (*pGOChooseReward)(Player*, GameObject*, Quest const*, uint32); + void (*pGODestroyed)(Player*, GameObject*, uint32); + bool (*pItemUse)(Player*, Item*, SpellCastTargets const&); + bool (*pItemExpire)(Player*, ItemPrototype const *); + bool (*pEffectDummyCreature)(Unit*, uint32, uint32, Creature*); + bool (*pEffectDummyGameObj)(Unit*, uint32, uint32, GameObject*); + bool (*pEffectDummyItem)(Unit*, uint32, uint32, Item*); + + CreatureAI* (*GetAI)(Creature*); + InstanceData* (*GetInstanceData)(Map*); + + void RegisterSelf(); +}; + +class ScriptMgr +{ + public: + ScriptMgr(); + ~ScriptMgr(); + + void ScriptsInit(); + void LoadDatabase(); + char const* ScriptsVersion(); + + //event handlers + void OnLogin(Player *pPlayer); + void OnLogout(Player *pPlayer); + void OnPVPKill(Player *killer, Player *killed); + bool OnSpellCast (Unit *pUnitTarget, Item *pItemTarget, GameObject *pGoTarget, uint32 i, SpellEntry const *spell); + uint32 OnGetXP(Player *pPlayer, uint32 amount); + uint32 OnGetMoney(Player *pPlayer, int32 amount); + bool OnPlayerChat(Player *pPlayer, const char *text); + void OnServerStartup(); + void OnServerShutdown(); + void OnAreaChange(Player *pPlayer, AreaTableEntry const *pArea); + bool OnItemClick (Player *pPlayer, Item *pItem); + bool OnItemOpen (Player *pPlayer, Item *pItem); + bool OnGoClick (Player *pPlayer, GameObject *pGameObject); + void OnCreatureKill (Player *pPlayer, Creature *pCreature); + bool GossipHello (Player * pPlayer, Creature* pCreature); + bool GossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction); + bool GossipSelectWithCode(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode); + bool GOSelect(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction); + bool GOSelectWithCode(Player* pPlayer, GameObject* pGO, uint32 uiSender, uint32 uiAction, const char* sCode); + bool QuestAccept(Player* pPlayer, Creature* pCreature, Quest const* pQuest); + bool QuestSelect(Player* pPlayer, Creature* pCreature, Quest const* pQuest); + bool QuestComplete(Player* pPlayer, Creature* pCreature, Quest const* pQuest); + bool ChooseReward(Player* pPlayer, Creature* pCreature, Quest const* pQuest, uint32 opt); + uint32 NPCDialogStatus(Player* pPlayer, Creature* pCreature); + uint32 GODialogStatus(Player* pPlayer, GameObject* pGO); + bool ItemHello(Player* pPlayer, Item* pItem, Quest const* pQuest); + bool ItemQuestAccept(Player* pPlayer, Item* pItem, Quest const* pQuest); + bool GOHello(Player* pPlayer, GameObject* pGO); + bool GOQuestAccept(Player* pPlayer, GameObject* pGO, Quest const* pQuest); + bool GOChooseReward(Player* pPlayer, GameObject* pGO, Quest const* pQuest, uint32 opt); + void GODestroyed(Player* pPlayer, GameObject* pGO, uint32 destroyedEvent); + bool AreaTrigger(Player* pPlayer,AreaTriggerEntry const* atEntry); + CreatureAI* GetAI(Creature* pCreature); + bool ItemUse(Player* pPlayer, Item* pItem, SpellCastTargets const& targets); + bool ItemExpire(Player* pPlayer, ItemPrototype const * pItemProto); + bool EffectDummyCreature(Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget); + bool EffectDummyGameObj(Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget); + bool EffectDummyItem(Unit *caster, uint32 spellId, uint32 effIndex, Item *itemTarget); + InstanceData* CreateInstanceData(Map *map); +}; + +//Config file accessors +//std::string GetConfigValueStr(char const* option); +//int32 GetConfigValueInt32(char const* option); +//float GetConfigValueFloat(char const* option); + +//Generic scripting text function +void DoScriptText(int32 textEntry, WorldObject* pSource, Unit *pTarget = NULL); + +#if COMPILER == COMPILER_GNU +#define FUNC_PTR(name,callconvention,returntype,parameters) typedef returntype(*name)parameters __attribute__ ((callconvention)); +#else +#define FUNC_PTR(name, callconvention, returntype, parameters) typedef returntype(callconvention *name)parameters; +#endif + +#define sScriptMgr Trinity::Singleton::Instance() +#endif + diff --git a/src/server/game/Scripting/ScriptSystem.cpp b/src/server/game/Scripting/ScriptSystem.cpp new file mode 100644 index 00000000000..0037b100412 --- /dev/null +++ b/src/server/game/Scripting/ScriptSystem.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * Thanks to the original authors: MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ScriptSystem.h" +#include "ProgressBar.h" +#include "ObjectMgr.h" +#include "Database/DatabaseEnv.h" + +SystemMgr::SystemMgr() +{ +} + +SystemMgr& SystemMgr::Instance() +{ + static SystemMgr pSysMgr; + return pSysMgr; +} + +void SystemMgr::LoadVersion() +{ + //Get Version information + QueryResult_AutoPtr Result = WorldDatabase.Query("SELECT script_version FROM version LIMIT 1"); + + if (Result) + { + Field* pFields = Result->Fetch(); + + outstring_log("TSCR: Database version is: %s", pFields[0].GetString()); + outstring_log(""); + } + else + { + error_log("TSCR: Missing `version`.`script_version` information."); + outstring_log(""); + } +} + +void SystemMgr::LoadScriptTexts() +{ + outstring_log("TSCR: Loading Script Texts..."); + LoadTrinityStrings(WorldDatabase,"script_texts",TEXT_SOURCE_RANGE,1+(TEXT_SOURCE_RANGE*2)); + + QueryResult_AutoPtr Result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM script_texts"); + + outstring_log("TSCR: Loading Script Texts additional data..."); + + if (Result) + { + barGoLink bar(Result->GetRowCount()); + uint32 uiCount = 0; + + do + { + bar.step(); + Field* pFields = Result->Fetch(); + StringTextData pTemp; + + int32 iId = pFields[0].GetInt32(); + pTemp.uiSoundId = pFields[1].GetUInt32(); + pTemp.uiType = pFields[2].GetUInt32(); + pTemp.uiLanguage = pFields[3].GetUInt32(); + pTemp.uiEmote = pFields[4].GetUInt32(); + + if (iId >= 0) + { + error_db_log("TSCR: Entry %i in table `script_texts` is not a negative value.", iId); + continue; + } + + if (iId > TEXT_SOURCE_RANGE || iId <= TEXT_SOURCE_RANGE*2) + { + error_db_log("TSCR: Entry %i in table `script_texts` is out of accepted entry range for table.", iId); + continue; + } + + if (pTemp.uiSoundId) + { + if (!GetSoundEntriesStore()->LookupEntry(pTemp.uiSoundId)) + error_db_log("TSCR: Entry %i in table `script_texts` has soundId %u but sound does not exist.", iId, pTemp.uiSoundId); + } + + if (!GetLanguageDescByID(pTemp.uiLanguage)) + error_db_log("TSCR: Entry %i in table `script_texts` using Language %u but Language does not exist.", iId, pTemp.uiLanguage); + + if (pTemp.uiType > CHAT_TYPE_ZONE_YELL) + error_db_log("TSCR: Entry %i in table `script_texts` has Type %u but this Chat Type does not exist.", iId, pTemp.uiType); + + m_mTextDataMap[iId] = pTemp; + ++uiCount; + } while (Result->NextRow()); + + outstring_log(""); + outstring_log(">> Loaded %u additional Script Texts data.", uiCount); + } + else + { + barGoLink bar(1); + bar.step(); + outstring_log(""); + outstring_log(">> Loaded 0 additional Script Texts data. DB table `script_texts` is empty."); + } +} + +void SystemMgr::LoadScriptTextsCustom() +{ + outstring_log("TSCR: Loading Custom Texts..."); + LoadTrinityStrings(WorldDatabase,"custom_texts",TEXT_SOURCE_RANGE*2,1+(TEXT_SOURCE_RANGE*3)); + + QueryResult_AutoPtr Result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM custom_texts"); + + outstring_log("TSCR: Loading Custom Texts additional data..."); + + if (Result) + { + barGoLink bar(Result->GetRowCount()); + uint32 uiCount = 0; + + do + { + bar.step(); + Field* pFields = Result->Fetch(); + StringTextData pTemp; + + int32 iId = pFields[0].GetInt32(); + pTemp.uiSoundId = pFields[1].GetUInt32(); + pTemp.uiType = pFields[2].GetUInt32(); + pTemp.uiLanguage = pFields[3].GetUInt32(); + pTemp.uiEmote = pFields[4].GetUInt32(); + + if (iId >= 0) + { + error_db_log("TSCR: Entry %i in table `custom_texts` is not a negative value.", iId); + continue; + } + + if (iId > TEXT_SOURCE_RANGE*2 || iId <= TEXT_SOURCE_RANGE*3) + { + error_db_log("TSCR: Entry %i in table `custom_texts` is out of accepted entry range for table.", iId); + continue; + } + + if (pTemp.uiSoundId) + { + if (!GetSoundEntriesStore()->LookupEntry(pTemp.uiSoundId)) + error_db_log("TSCR: Entry %i in table `custom_texts` has soundId %u but sound does not exist.", iId, pTemp.uiSoundId); + } + + if (!GetLanguageDescByID(pTemp.uiLanguage)) + error_db_log("TSCR: Entry %i in table `custom_texts` using Language %u but Language does not exist.", iId, pTemp.uiLanguage); + + if (pTemp.uiType > CHAT_TYPE_ZONE_YELL) + error_db_log("TSCR: Entry %i in table `custom_texts` has Type %u but this Chat Type does not exist.", iId, pTemp.uiType); + + m_mTextDataMap[iId] = pTemp; + ++uiCount; + } while (Result->NextRow()); + + outstring_log(""); + outstring_log(">> Loaded %u additional Custom Texts data.", uiCount); + } + else + { + barGoLink bar(1); + bar.step(); + outstring_log(""); + outstring_log(">> Loaded 0 additional Custom Texts data. DB table `custom_texts` is empty."); + } +} + +void SystemMgr::LoadScriptWaypoints() +{ + // Drop Existing Waypoint list + m_mPointMoveMap.clear(); + + uint64 uiCreatureCount = 0; + + // Load Waypoints + QueryResult_AutoPtr Result = WorldDatabase.Query("SELECT COUNT(entry) FROM script_waypoint GROUP BY entry"); + if (Result) + uiCreatureCount = Result->GetRowCount(); + + outstring_log("TSCR: Loading Script Waypoints for %u creature(s)...", uiCreatureCount); + + Result = WorldDatabase.Query("SELECT entry, pointid, location_x, location_y, location_z, waittime FROM script_waypoint ORDER BY pointid"); + + if (Result) + { + barGoLink bar(Result->GetRowCount()); + uint32 uiNodeCount = 0; + + do + { + bar.step(); + Field* pFields = Result->Fetch(); + ScriptPointMove pTemp; + + pTemp.uiCreatureEntry = pFields[0].GetUInt32(); + uint32 uiEntry = pTemp.uiCreatureEntry; + pTemp.uiPointId = pFields[1].GetUInt32(); + pTemp.fX = pFields[2].GetFloat(); + pTemp.fY = pFields[3].GetFloat(); + pTemp.fZ = pFields[4].GetFloat(); + pTemp.uiWaitTime = pFields[5].GetUInt32(); + + CreatureInfo const* pCInfo = GetCreatureTemplateStore(pTemp.uiCreatureEntry); + + if (!pCInfo) + { + error_db_log("TSCR: DB table script_waypoint has waypoint for non-existant creature entry %u", pTemp.uiCreatureEntry); + continue; + } + + if (!pCInfo->ScriptID) + error_db_log("TSCR: DB table script_waypoint has waypoint for creature entry %u, but creature does not have ScriptName defined and then useless.", pTemp.uiCreatureEntry); + + m_mPointMoveMap[uiEntry].push_back(pTemp); + ++uiNodeCount; + } while (Result->NextRow()); + + outstring_log(""); + outstring_log(">> Loaded %u Script Waypoint nodes.", uiNodeCount); + } + else + { + barGoLink bar(1); + bar.step(); + outstring_log(""); + outstring_log(">> Loaded 0 Script Waypoints. DB table `script_waypoint` is empty."); + } +} diff --git a/src/server/game/Scripting/ScriptSystem.h b/src/server/game/Scripting/ScriptSystem.h new file mode 100644 index 00000000000..f78cd2e64fa --- /dev/null +++ b/src/server/game/Scripting/ScriptSystem.h @@ -0,0 +1,100 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_SYSTEM_H +#define SC_SYSTEM_H + +#define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available + +//TODO: find better namings and definitions. +//N=Neutral, A=Alliance, H=Horde. +//NEUTRAL or FRIEND = Hostility to player surroundings (not a good definition) +//ACTIVE or PASSIVE = Hostility to environment surroundings. +enum eEscortFaction +{ + FACTION_ESCORT_A_NEUTRAL_PASSIVE = 10, + FACTION_ESCORT_H_NEUTRAL_PASSIVE = 33, + FACTION_ESCORT_N_NEUTRAL_PASSIVE = 113, + + FACTION_ESCORT_A_NEUTRAL_ACTIVE = 231, + FACTION_ESCORT_H_NEUTRAL_ACTIVE = 232, + FACTION_ESCORT_N_NEUTRAL_ACTIVE = 250, + + FACTION_ESCORT_N_FRIEND_PASSIVE = 290, + FACTION_ESCORT_N_FRIEND_ACTIVE = 495, + + FACTION_ESCORT_A_PASSIVE = 774, + FACTION_ESCORT_H_PASSIVE = 775, + + FACTION_ESCORT_N_ACTIVE = 1986, + FACTION_ESCORT_H_ACTIVE = 2046 +}; + +struct ScriptPointMove +{ + uint32 uiCreatureEntry; + uint32 uiPointId; + float fX; + float fY; + float fZ; + uint32 uiWaitTime; +}; + +struct StringTextData +{ + uint32 uiSoundId; + uint8 uiType; + uint32 uiLanguage; + uint32 uiEmote; +}; + +#define pSystemMgr SystemMgr::Instance() + +class SystemMgr +{ + public: + SystemMgr(); + ~SystemMgr() {} + + static SystemMgr& Instance(); + + //Maps and lists + typedef UNORDERED_MAP TextDataMap; + typedef UNORDERED_MAP > PointMoveMap; + + //Database + void LoadVersion(); + void LoadScriptTexts(); + void LoadScriptTextsCustom(); + void LoadScriptWaypoints(); + + //Retrive from storage + StringTextData const* GetTextData(int32 uiTextId) const + { + TextDataMap::const_iterator itr = m_mTextDataMap.find(uiTextId); + + if (itr == m_mTextDataMap.end()) + return NULL; + + return &itr->second; + } + + std::vector const &GetPointMoveList(uint32 uiCreatureEntry) const + { + static std::vector vEmpty; + + PointMoveMap::const_iterator itr = m_mPointMoveMap.find(uiCreatureEntry); + + if (itr == m_mPointMoveMap.end()) + return vEmpty; + + return itr->second; + } + + protected: + TextDataMap m_mTextDataMap; //additional data for text strings + PointMoveMap m_mPointMoveMap; //coordinates for waypoints +}; + +#endif diff --git a/src/server/game/Server/Protocol/Handlers/AddonHandler.cpp b/src/server/game/Server/Protocol/Handlers/AddonHandler.cpp new file mode 100644 index 00000000000..a9c8101d7b1 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/AddonHandler.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "zlib/zlib.h" + +#include "AddonHandler.h" +#include "Database/DatabaseEnv.h" +#include "Policies/SingletonImp.h" +#include "Opcodes.h" + +#include "Log.h" + +INSTANTIATE_SINGLETON_1( AddonHandler ); + +AddonHandler::AddonHandler() +{ +} + +AddonHandler::~AddonHandler() +{ +} + +bool AddonHandler::BuildAddonPacket(WorldPacket *Source, WorldPacket *Target) +{ + ByteBuffer AddOnPacked; + uLongf AddonRealSize; + uint32 CurrentPosition; + uint32 TempValue; + + unsigned char tdata[256] = + { + 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, + 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, + 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, + 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, + 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, + 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, + 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, + 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, + 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, + 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, + 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, + 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, + 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, + 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, + 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, + 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 + }; + + // broken addon packet, can't be received from real client + if (Source->rpos() + 4 > Source->size()) + return false; + + *Source >> TempValue; // get real size of the packed structure + + // empty addon packet, nothing process, can't be received from real client + if(!TempValue) + return false; + + AddonRealSize = TempValue; // temp value because ZLIB only excepts uLongf + + CurrentPosition = Source->rpos(); // get the position of the pointer in the structure + + AddOnPacked.resize(AddonRealSize); // resize target for zlib action + + if (!uncompress(const_cast(AddOnPacked.contents()), &AddonRealSize, const_cast((*Source).contents() + CurrentPosition), (*Source).size() - CurrentPosition)!= Z_OK) + { + Target->Initialize(SMSG_ADDON_INFO); + + uint32 addonsCount; + AddOnPacked >> addonsCount; // addons count? + + for(uint32 i = 0; i < addonsCount; ++i) + { + std::string addonName; + uint8 enabled; + uint32 crc, unk2; + + // check next addon data format correctness + if(AddOnPacked.rpos()+1 > AddOnPacked.size()) + return false; + + AddOnPacked >> addonName; + + // recheck next addon data format correctness + if(AddOnPacked.rpos()+1+4+4 > AddOnPacked.size()) + return false; + + AddOnPacked >> enabled >> crc >> unk2; + + sLog.outDebug("ADDON: Name: %s, Enabled: 0x%x, CRC: 0x%x, Unknown2: 0x%x", addonName.c_str(), enabled, crc, unk2); + + uint8 state = (enabled ? 2 : 1); + *Target << uint8(state); + + uint8 unk1 = (enabled ? 1 : 0); + *Target << uint8(unk1); + if (unk1) + { + uint8 unk2 = (crc != 0x4c1c776d); // If addon is Standard addon CRC + *Target << uint8(unk2); + if (unk2) + Target->append(tdata, sizeof(tdata)); + + *Target << uint32(0); + } + + uint8 unk3 = (enabled ? 0 : 1); + *Target << uint8(unk3); + if (unk3) + { + // String, 256 (null terminated?) + *Target << uint8(0); + } + } + + uint32 unk4; + AddOnPacked >> unk4; + + uint32 count = 0; + *Target << uint32(count); + /*for(uint32 i = 0; i < count; ++i) + { + uint32 + string (16 bytes) + string (16 bytes) + uint32 + }*/ + + if(AddOnPacked.rpos() != AddOnPacked.size()) + sLog.outDebug("packet under read!"); + } + else + { + sLog.outError("Addon packet uncompress error :("); + return false; + } + return true; +} + +/* Code use in 1.10.2 when client not ignore ban state sended for addons. Saved for reference if client switch to use server ban state information +void AddonHandler::BuildAddonPacket(WorldPacket* Source, WorldPacket* Target, uint32 Packetoffset) +{ + ByteBuffer AddOnPacked; + uLongf AddonRealSize; + uint32 CurrentPosition; + uint32 TempValue; + + *Source >> TempValue; //get real size of the packed structure + + AddonRealSize = TempValue; //temp value becouse ZLIB only excepts uLongf + + CurrentPosition = Source->rpos(); //get the position of the pointer in the structure + + AddOnPacked.resize(AddonRealSize); //resize target for zlib action + + if (!uncompress((uint8*)AddOnPacked.contents(), &AddonRealSize, (uint8*)(*Source).contents() + CurrentPosition, (*Source).size() - CurrentPosition)!= Z_OK) + { + bool* AddonAllowed = new bool; //handle addon check and enable-ing + + uint32 Unknown1; + uint8 Unknown0; + + AddOnPacked >> Unknown0; + AddOnPacked >> Unknown1; + + Target->Initialize(SMSG_ADDON_INFO); + + uint32 i = 5; //offset for addon extraction + while(i != AddOnPacked.size()) + { + std::string AddonNames; + AddOns* Addonstr = new AddOns; + uint8 unk6; + uint64 CRCCHECK; + AddOnPacked >> AddonNames >> CRCCHECK >> unk6; + + //sLog.outDebug("ADDON: Name:%s CRC:%x Unknown:%x",AddonNames.c_str(), CRCCHECK,unk6); + + Addonstr->Name = AddonNames; + Addonstr->CRC = CRCCHECK; + + //if not allowed but unknown added to list + if (GetAddonStatus(Addonstr, AddonAllowed)) // If addon is new + { + Addonstr->Enabled = m_Addon_Default; // by default new addons are set from Config file + *AddonAllowed = m_Addon_Default; // Set addon allowed on default value + _AddAddon(Addonstr); + sLog.outDetail("Found new Addon, Name:%s CRC:%x Unknown:%x",AddonNames.c_str(), CRCCHECK, unk6); + } + + if (CRCCHECK == 0x4C1C776D01LL) //If addon is Standard addon CRC + { + //value's standard Addons + *Target << uint8(0) << uint8(2) << uint8(1) << uint8(0) << uint32(0); + } + else if (*AddonAllowed) //if addon is Custom addons + //value's enable addon + *Target << uint8(0x00) << uint8(0x01) << uint8(0x00) << uint8(0x01); + else + //value's disable addom + *Target << uint8(0x00) << uint8(0x0) << uint8(0x00) << uint8(0x0); + + i += AddonNames.size() + 10; + } + *Target << uint8(0x0); + + //delete mem allocation + delete AddonAllowed; + } + else + { + //handle uncompress error + } +} +*/ + diff --git a/src/server/game/Server/Protocol/Handlers/AddonHandler.h b/src/server/game/Server/Protocol/Handlers/AddonHandler.h new file mode 100644 index 00000000000..999785339bc --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/AddonHandler.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ADDONHANDLER_H +#define __ADDONHANDLER_H + +#include "Common.h" +#include "Config/ConfigEnv.h" +#include "Policies/Singleton.h" + +#include "WorldPacket.h" + +class AddonHandler +{ + public: + /* Construction */ + AddonHandler(); + ~AddonHandler(); + //built addon packet + bool BuildAddonPacket(WorldPacket* Source, WorldPacket* Target); +}; +#define sAddOnHandler Trinity::Singleton::Instance() +#endif + diff --git a/src/server/game/Server/Protocol/Handlers/ArenaTeamHandler.cpp b/src/server/game/Server/Protocol/Handlers/ArenaTeamHandler.cpp new file mode 100644 index 00000000000..3a9a14524f9 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/ArenaTeamHandler.cpp @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Player.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Database/DatabaseEnv.h" + +#include "ArenaTeam.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "SocialMgr.h" + +void WorldSession::HandleInspectArenaTeamsOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("MSG_INSPECT_ARENA_TEAMS"); + + uint64 guid; + recv_data >> guid; + sLog.outDebug("Inspect Arena stats (GUID: %u TypeId: %u)", GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); + + if (Player *plr = objmgr.GetPlayer(guid)) + { + for (uint8 i = 0; i < MAX_ARENA_SLOT; ++i) + { + if (uint32 a_id = plr->GetArenaTeamId(i)) + { + if (ArenaTeam *at = objmgr.GetArenaTeamById(a_id)) + at->InspectStats(this, plr->GetGUID()); + } + } + } +} + +void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_ARENA_TEAM_QUERY"); + + uint32 ArenaTeamId; + recv_data >> ArenaTeamId; + + if (ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId)) + { + arenateam->Query(this); + arenateam->Stats(this); + } +} + +void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_ARENA_TEAM_ROSTER"); + + uint32 ArenaTeamId; // arena team id + recv_data >> ArenaTeamId; + + if (ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId)) + arenateam->Roster(this); +} + +void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_INVITE"); + + uint32 ArenaTeamId; // arena team id + std::string Invitedname; + + Player * player = NULL; + + recv_data >> ArenaTeamId >> Invitedname; + + if (!Invitedname.empty()) + { + if (!normalizePlayerName(Invitedname)) + return; + + player = ObjectAccessor::Instance().FindPlayerByName(Invitedname.c_str()); + } + + if (!player) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); + return; + } + + if (player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); + return; + } + + ArenaTeam *arenateam = objmgr.GetArenaTeamById(ArenaTeamId); + if (!arenateam) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM); + return; + } + + // OK result but not send invite + if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + return; + + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + return; + } + + if (player->GetArenaTeamId(arenateam->GetSlot())) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); + return; + } + + if (player->GetArenaTeamIdInvited()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + return; + } + + if (arenateam->GetMembersSize() >= arenateam->GetType() * 2) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, arenateam->GetName(), "", ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S); + return; + } + + sLog.outDebug("Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName(), Invitedname.c_str()); + + player->SetArenaTeamIdInvited(arenateam->GetId()); + + WorldPacket data(SMSG_ARENA_TEAM_INVITE, (8+10)); + data << GetPlayer()->GetName(); + data << arenateam->GetName(); + player->GetSession()->SendPacket(&data); + + sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_INVITE"); +} + +void WorldSession::HandleArenaTeamAcceptOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("CMSG_ARENA_TEAM_ACCEPT"); // empty opcode + + ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited()); + if (!at) + return; + + if (_player->GetArenaTeamId(at->GetSlot())) + { + // already in arena team that size + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ALREADY_IN_ARENA_TEAM); + return; + } + + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain())) + { + // not let enemies sign petition + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + return; + } + + if (!at->AddMember(_player->GetGUID())) + { + // arena team not found + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_INTERNAL); + return; + } + + // event + at->BroadcastEvent(ERR_ARENA_TEAM_JOIN_SS, _player->GetGUID(), 2, _player->GetName(), at->GetName(), ""); +} + +void WorldSession::HandleArenaTeamDeclineOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("CMSG_ARENA_TEAM_DECLINE"); // empty opcode + + _player->SetArenaTeamIdInvited(0); // no more invited +} + +void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_LEAVE"); + + uint32 ArenaTeamId; // arena team id + recv_data >> ArenaTeamId; + + ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); + if (!at) + return; + + if (_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1) + { + // check for correctness + SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); + return; + } + + // arena team has only one member (=captain) + if (_player->GetGUID() == at->GetCaptain()) + { + at->Disband(this); + delete at; + return; + } + + at->DelMember(_player->GetGUID()); + + // event + at->BroadcastEvent(ERR_ARENA_TEAM_LEAVE_SS, _player->GetGUID(), 2, _player->GetName(), at->GetName(), ""); + + // send you are no longer member of team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0); +} + +void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_DISBAND"); + + uint32 ArenaTeamId; // arena team id + recv_data >> ArenaTeamId; + + if (ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId)) + { + if (at->GetCaptain() != _player->GetGUID()) + return; + + if (at->IsFighting()) + return; + + at->Disband(this); + delete at; + } +} + +void WorldSession::HandleArenaTeamRemoveOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_REMOVE"); + + uint32 ArenaTeamId; + std::string name; + + recv_data >> ArenaTeamId; + recv_data >> name; + + ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); + if (!at) // arena team not found + return; + + if (at->GetCaptain() != _player->GetGUID()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); + return; + } + + if (!normalizePlayerName(name)) + return; + + ArenaTeamMember* member = at->GetMember(name); + if (!member) // member not found + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); + return; + } + + if (at->GetCaptain() == member->guid) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); + return; + } + + at->DelMember(member->guid); + + // event + at->BroadcastEvent(ERR_ARENA_TEAM_REMOVE_SSS, 0, 3, name, at->GetName(), _player->GetName()); +} + +void WorldSession::HandleArenaTeamLeaderOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ARENA_TEAM_LEADER"); + + uint32 ArenaTeamId; + std::string name; + + recv_data >> ArenaTeamId; + recv_data >> name; + + ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); + if (!at) // arena team not found + return; + + if (at->GetCaptain() != _player->GetGUID()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); + return; + } + + if (!normalizePlayerName(name)) + return; + + ArenaTeamMember* member = at->GetMember(name); + if (!member) // member not found + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); + return; + } + + if (at->GetCaptain() == member->guid) // target player already captain + return; + + at->SetCaptain(member->guid); + + // event + at->BroadcastEvent(ERR_ARENA_TEAM_LEADER_CHANGED_SSS, 0, 3, _player->GetName(), name, at->GetName()); +} + +void WorldSession::SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id) +{ + WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4); + data << uint32(team_action); + data << team; + data << player; + data << uint32(error_id); + SendPacket(&data); +} + +void WorldSession::SendNotInArenaTeamPacket(uint8 type) +{ + WorldPacket data(SMSG_ARENA_ERROR, 4+1); // 886 - You are not in a %uv%u arena team + uint32 unk = 0; + data << uint32(unk); // unk(0) + if (!unk) + data << uint8(type); // team type (2=2v2,3=3v3,5=5v5), can be used for custom types... + SendPacket(&data); +} + +/* ++ERR_ARENA_NO_TEAM_II "You are not in a %dv%d arena team" + ++ERR_ARENA_TEAM_CREATE_S "%s created. To disband, use /teamdisband [2v2, 3v3, 5v5]." ++ERR_ARENA_TEAM_INVITE_SS "You have invited %s to join %s" ++ERR_ARENA_TEAM_QUIT_S "You are no longer a member of %s" +ERR_ARENA_TEAM_FOUNDER_S "Congratulations, you are a founding member of %s! To leave, use /teamquit [2v2, 3v3, 5v5]." + ++ERR_ARENA_TEAM_INTERNAL "Internal arena team error" ++ERR_ALREADY_IN_ARENA_TEAM "You are already in an arena team of that size" ++ERR_ALREADY_IN_ARENA_TEAM_S "%s is already in an arena team of that size" ++ERR_INVITED_TO_ARENA_TEAM "You have already been invited into an arena team" ++ERR_ALREADY_INVITED_TO_ARENA_TEAM_S "%s has already been invited to an arena team" ++ERR_ARENA_TEAM_NAME_INVALID "That name contains invalid characters, please enter a new name" ++ERR_ARENA_TEAM_NAME_EXISTS_S "There is already an arena team named \"%s\"" ++ERR_ARENA_TEAM_LEADER_LEAVE_S "You must promote a new team captain using /teamcaptain before leaving the team" ++ERR_ARENA_TEAM_PERMISSIONS "You don't have permission to do that" ++ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM "You are not in an arena team of that size" ++ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS "%s is not in %s" ++ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S "\"%s\" not found" ++ERR_ARENA_TEAM_NOT_ALLIED "You cannot invite players from the opposing alliance" + ++ERR_ARENA_TEAM_JOIN_SS "%s has joined %s" ++ERR_ARENA_TEAM_YOU_JOIN_S "You have joined %s. To leave, use /teamquit [2v2, 3v3, 5v5]." + ++ERR_ARENA_TEAM_LEAVE_SS "%s has left %s" + ++ERR_ARENA_TEAM_LEADER_IS_SS "%s is the captain of %s" ++ERR_ARENA_TEAM_LEADER_CHANGED_SSS "%s has made %s the new captain of %s" + ++ERR_ARENA_TEAM_REMOVE_SSS "%s has been kicked out of %s by %s" + ++ERR_ARENA_TEAM_DISBANDED_S "%s has disbanded %s" + +ERR_ARENA_TEAM_TARGET_TOO_LOW_S "%s is not high enough level to join your team" + +ERR_ARENA_TEAM_TOO_MANY_MEMBERS_S "%s is full" + +ERR_ARENA_TEAM_LEVEL_TOO_LOW_I "You must be level %d to form an arena team" +*/ diff --git a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp new file mode 100644 index 00000000000..8fec3b7df1d --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp @@ -0,0 +1,664 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectMgr.h" +#include "Player.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" + +#include "AuctionHouseBot.h" +#include "AuctionHouseMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "UpdateMask.h" +#include "Util.h" + +//please DO NOT use iterator++, because it is slower than ++iterator!!! +//post-incrementation is always slower than pre-incrementation ! + +//void called when player click on auctioneer npc +void WorldSession::HandleAuctionHelloOpcode(WorldPacket & recv_data) +{ + uint64 guid; //NPC guid + recv_data >> guid; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); + if (!unit) + { + sLog.outDebug("WORLD: HandleAuctionHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + SendAuctionHello(guid, unit); +} + +//this void causes that auction window is opened +void WorldSession::SendAuctionHello(uint64 guid, Creature* unit) +{ + if (GetPlayer()->getLevel() < sWorld.getConfig(CONFIG_AUCTION_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_AUCTION_REQ), sWorld.getConfig(CONFIG_AUCTION_LEVEL_REQ)); + return; + } + + AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->getFaction()); + if (!ahEntry) + return; + + WorldPacket data(MSG_AUCTION_HELLO, 12); + data << uint64(guid); + data << uint32(ahEntry->houseId); + data << uint8(1); // 3.3.3: 1 - AH enabled, 0 - AH disabled + SendPacket(&data); +} + +//call this method when player bids, creates, or deletes auction +void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError) +{ + WorldPacket data(SMSG_AUCTION_COMMAND_RESULT, 16); + data << auctionId; + data << Action; + data << ErrorCode; + if (!ErrorCode && Action) + data << bidError; //when bid, then send 0, once... + SendPacket(&data); +} + +//this function sends notification, if bidder is online +void WorldSession::SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template) +{ + WorldPacket data(SMSG_AUCTION_BIDDER_NOTIFICATION, (8*4)); + data << uint32(location); + data << uint32(auctionId); + data << uint64(bidder); + data << uint32(bidSum); + data << uint32(diff); + data << uint32(item_template); + data << uint32(0); + SendPacket(&data); +} + +//this void causes on client to display: "Your auction sold" +void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction) +{ + WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, (7*4)); + data << auction->Id; + data << auction->bid; + data << (uint32) 0; //unk + data << (uint32) 0; //unk + data << (uint32) 0; //unk + data << auction->item_template; + data << (uint32) 0; //unk + SendPacket(&data); +} + +//this function sends mail to old bidder +void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPrice) +{ + uint64 oldBidder_guid = MAKE_NEW_GUID(auction->bidder,0, HIGHGUID_PLAYER); + Player *oldBidder = objmgr.GetPlayer(oldBidder_guid); + + uint32 oldBidder_accId = 0; + if (!oldBidder) + oldBidder_accId = objmgr.GetPlayerAccountIdByGUID(oldBidder_guid); + + // old bidder exist + if (oldBidder || oldBidder_accId) + { + std::ostringstream msgAuctionOutbiddedSubject; + msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED << ":0:0"; + + if (oldBidder && !_player) + oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, auctionbot.GetAHBplayerGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); + + if (oldBidder && _player) + oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, _player->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); + + MailDraft(msgAuctionOutbiddedSubject.str(), "") // TODO: fix body + .AddMoney(auction->bid) + .SendMailTo(MailReceiver(oldBidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED); + } +} + +//this function sends mail, when auction is cancelled to old bidder +void WorldSession::SendAuctionCancelledToBidderMail(AuctionEntry* auction) +{ + uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER); + Player *bidder = objmgr.GetPlayer(bidder_guid); + + uint32 bidder_accId = 0; + if (!bidder) + bidder_accId = objmgr.GetPlayerAccountIdByGUID(bidder_guid); + + // bidder exist + if (bidder || bidder_accId) + { + std::ostringstream msgAuctionCancelledSubject; + msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER << ":0:0"; + + MailDraft(msgAuctionCancelledSubject.str(), "") // TODO: fix body + .AddMoney(auction->bid) + .SendMailTo(MailReceiver(bidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED); + } +} + +//this void creates new auction and adds auction to some auctionhouse +void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) +{ + uint64 auctioneer, item; + uint32 etime, bid, buyout; + recv_data >> auctioneer; + recv_data.read_skip(); // const 1? + recv_data >> item; + recv_data.read_skip(); // unk 3.2.2, const 1? + recv_data >> bid; + recv_data >> buyout; + recv_data >> etime; + + Player *pl = GetPlayer(); + + if (!item || !bid || !etime) + return; //check for cheaters + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); + return; + } + + AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(pCreature->getFaction()); + if (!auctionHouseEntry) + { + sLog.outDebug("WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", uint32(GUID_LOPART(auctioneer))); + return; + } + + sLog.outDebug("WORLD: HandleAuctionSellItem - ETIME: %u", etime); + + // client send time in minutes, convert to common used sec time + etime *= MINUTE; + + sLog.outDebug("WORLD: HandleAuctionSellItem - ETIME: %u", etime); + + // client understand only 3 auction time + switch(etime) + { + case 1*MIN_AUCTION_TIME: + case 2*MIN_AUCTION_TIME: + case 4*MIN_AUCTION_TIME: + break; + default: + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + Item *it = pl->GetItemByGuid(item); + //do not allow to sell already auctioned items + if (auctionmgr.GetAItem(GUID_LOPART(item))) + { + sLog.outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", pl->GetName(), GUID_LOPART(item)); + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) + if (!it) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); + return; + } + + if (!it->CanBeTraded()) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + + if (it->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION)) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); + return; + } + + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); + + //we have to take deposit : + uint32 deposit = auctionmgr.GetAuctionDeposit(auctionHouseEntry, etime, it); + if (pl->GetMoney() < deposit) + { + SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); + return; + } + + if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand(GetAccountId(),"GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", + GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount()); + } + + pl->ModifyMoney(-int32(deposit)); + + uint32 auction_time = uint32(etime * sWorld.getRate(RATE_AUCTION_TIME)); + + AuctionEntry *AH = new AuctionEntry; + AH->Id = objmgr.GenerateAuctionID(); + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + AH->auctioneer = 23442; + else + AH->auctioneer = GUID_LOPART(auctioneer); + AH->item_guidlow = GUID_LOPART(item); + AH->item_template = it->GetEntry(); + AH->owner = pl->GetGUIDLow(); + AH->startbid = bid; + AH->bidder = 0; + AH->bid = 0; + AH->buyout = buyout; + AH->expire_time = time(NULL) + auction_time; + AH->deposit = deposit; + AH->auctionHouseEntry = auctionHouseEntry; + + sLog.outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), AH->auctioneer, bid, buyout, auction_time, AH->GetHouseId()); + auctionmgr.AddAItem(it); + auctionHouse->AddAuction(AH); + + pl->MoveItemFromInventory(it->GetBagSlot(), it->GetSlot(), true); + + CharacterDatabase.BeginTransaction(); + it->DeleteFromInventoryDB(); + it->SaveToDB(); // recursive and not have transaction guard into self, not in inventiory and can be save standalone + AH->SaveToDB(); + pl->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); + + SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); + + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); +} + +//this function is called when client bids or buys out auction +void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) +{ + uint64 auctioneer; + uint32 auctionId; + uint32 price; + recv_data >> auctioneer; + recv_data >> auctionId >> price; + + if (!auctionId || !price) + return; //check for cheaters + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + AuctionHouseObject *auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); + + AuctionEntry *auction = auctionHouse->GetAuction(auctionId); + Player *pl = GetPlayer(); + + if (!auction || auction->owner == pl->GetGUIDLow()) + { + //you cannot bid your own auction: + SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); + return; + } + + // impossible have online own another character (use this for speedup check in case online owner) + Player* auction_owner = objmgr.GetPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); + if (!auction_owner && objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == pl->GetSession()->GetAccountId()) + { + //you cannot bid your another character auction: + SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); + return; + } + + // cheating + if (price <= auction->bid || price < auction->startbid) + return; + + // price too low for next bid if not buyout + if ((price < auction->buyout || auction->buyout == 0) && + price < auction->bid + auction->GetAuctionOutBid()) + { + //auction has already higher bid, client tests it! + return; + } + + if (price > pl->GetMoney()) + { + //you don't have enought money!, client tests! + //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); + return; + } + + if (price < auction->buyout || auction->buyout == 0) + { + if (auction->bidder > 0) + { + if (auction->bidder == pl->GetGUIDLow()) + pl->ModifyMoney(-int32(price - auction->bid)); + else + { + // mail to last bidder and return money + SendAuctionOutbiddedMail(auction, price); + pl->ModifyMoney(-int32(price)); + } + } + else + pl->ModifyMoney(-int32(price)); + + auction->bidder = pl->GetGUIDLow(); + auction->bid = price; + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); + + // after this update we should save player's money ... + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); + + SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK, 0); + } + else + { + //buyout: + if (pl->GetGUIDLow() == auction->bidder) + pl->ModifyMoney(-int32(auction->buyout - auction->bid)); + else + { + pl->ModifyMoney(-int32(auction->buyout)); + if (auction->bidder) //buyout for bidded auction .. + SendAuctionOutbiddedMail(auction, auction->buyout); + } + auction->bidder = pl->GetGUIDLow(); + auction->bid = auction->buyout; + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); + + auctionmgr.SendAuctionSalePendingMail(auction); + auctionmgr.SendAuctionSuccessfulMail(auction); + auctionmgr.SendAuctionWonMail(auction); + + SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); + + CharacterDatabase.BeginTransaction(); + auction->DeleteFromDB(); + uint32 item_template = auction->item_template; + auctionmgr.RemoveAItem(auction->item_guidlow); + auctionHouse->RemoveAuction(auction, item_template); + } + pl->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); +} + +//this void is called when auction_owner cancels his auction +void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) +{ + uint64 auctioneer; + uint32 auctionId; + recv_data >> auctioneer; + recv_data >> auctionId; + //sLog.outDebug("Cancel AUCTION AuctionID: %u", auctionId); + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); + + AuctionEntry *auction = auctionHouse->GetAuction(auctionId); + Player *pl = GetPlayer(); + + if (auction && auction->owner == pl->GetGUIDLow()) + { + Item *pItem = auctionmgr.GetAItem(auction->item_guidlow); + if (pItem) + { + if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid + { + uint32 auctionCut = auction->GetAuctionCut(); + if (pl->GetMoney() < auctionCut) //player doesn't have enough money, maybe message needed + return; + //some auctionBidderNotification would be needed, but don't know that parts.. + SendAuctionCancelledToBidderMail(auction); + pl->ModifyMoney(-int32(auctionCut)); + } + // Return the item by mail + std::ostringstream msgAuctionCanceledOwner; + msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED << ":0:0"; + + // item will deleted or added to received mail list + MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body + .AddItem(pItem) + .SendMailTo(pl, auction, MAIL_CHECK_MASK_COPIED); + } + else + { + sLog.outError("Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->item_guidlow); + SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); + return; + } + } + else + { + SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); + //this code isn't possible ... maybe there should be assert + sLog.outError("CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", pl->GetGUIDLow(), auctionId); + return; + } + + //inform player, that auction is removed + SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, AUCTION_OK); + + // Now remove the auction + CharacterDatabase.BeginTransaction(); + pl->SaveInventoryAndGoldToDB(); + auction->DeleteFromDB(); + uint32 item_template = auction->item_template; + auctionmgr.RemoveAItem(auction->item_guidlow); + auctionHouse->RemoveAuction(auction, item_template); + CharacterDatabase.CommitTransaction(); +} + +//called when player lists his bids +void WorldSession::HandleAuctionListBidderItems(WorldPacket & recv_data) +{ + uint64 guid; //NPC guid + uint32 listfrom; //page of auctions + uint32 outbiddedCount; //count of outbidded auctions + + recv_data >> guid; + recv_data >> listfrom; // not used in fact (this list not have page control in client) + recv_data >> outbiddedCount; + if (recv_data.size() != (16 + outbiddedCount * 4)) + { + sLog.outError("Client sent bad opcode!!! with count: %u and size : %lu (must be: %u)", outbiddedCount, (unsigned long)recv_data.size(),(16 + outbiddedCount * 4)); + outbiddedCount = 0; + } + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); + + WorldPacket data(SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4)); + Player *pl = GetPlayer(); + data << (uint32) 0; //add 0 as count + uint32 count = 0; + uint32 totalcount = 0; + while (outbiddedCount > 0) //add all data, which client requires + { + --outbiddedCount; + uint32 outbiddedAuctionId; + recv_data >> outbiddedAuctionId; + AuctionEntry * auction = auctionHouse->GetAuction(outbiddedAuctionId); + if (auction && auction->BuildAuctionInfo(data)) + { + ++totalcount; + ++count; + } + } + + auctionHouse->BuildListBidderItems(data,pl,count,totalcount); + data.put(0, count); // add count to placeholder + data << totalcount; + data << (uint32)300; //unk 2.3.0 + SendPacket(&data); +} + +//this void sends player info about his auctions +void WorldSession::HandleAuctionListOwnerItems(WorldPacket & recv_data) +{ + uint32 listfrom; + uint64 guid; + + recv_data >> guid; + recv_data >> listfrom; // not used in fact (this list not have page control in client) + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleAuctionListOwnerItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); + + WorldPacket data(SMSG_AUCTION_OWNER_LIST_RESULT, (4+4+4)); + data << (uint32) 0; // amount place holder + + uint32 count = 0; + uint32 totalcount = 0; + + auctionHouse->BuildListOwnerItems(data,_player,count,totalcount); + data.put(0, count); + data << (uint32) totalcount; + data << (uint32) 0; + SendPacket(&data); +} + +//this void is called when player clicks on search button +void WorldSession::HandleAuctionListItems(WorldPacket & recv_data) +{ + std::string searchedname; + uint8 levelmin, levelmax, usable; + uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality; + uint64 guid; + + recv_data >> guid; + recv_data >> listfrom; // start, used for page control listing by 50 elements + recv_data >> searchedname; + + recv_data >> levelmin >> levelmax; + recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; + recv_data >> quality >> usable; + + recv_data.read_skip(16); // unknown 16 bytes: 00 07 01 00 00 01 05 00 06 00 09 01 08 00 03 00 + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleAuctionListItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); + + //sLog.outDebug("Auctionhouse search (GUID: %u TypeId: %u)", , list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u", + // GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid)), listfrom, searchedname.c_str(), levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable); + + WorldPacket data(SMSG_AUCTION_LIST_RESULT, (4+4+4)); + uint32 count = 0; + uint32 totalcount = 0; + data << (uint32) 0; + + // converting string that we try to find to lower case + std::wstring wsearchedname; + if (!Utf8toWStr(searchedname,wsearchedname)) + return; + + wstrToLower(wsearchedname); + + auctionHouse->BuildListAuctionItems(data,_player, + wsearchedname, listfrom, levelmin, levelmax, usable, + auctionSlotID, auctionMainCategory, auctionSubCategory, quality, + count,totalcount); + + data.put(0, count); + data << (uint32) totalcount; + data << (uint32) 300; // unk 2.3.0 const? + SendPacket(&data); +} + +void WorldSession::HandleAuctionListPendingSales(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES"); + + recv_data.read_skip(); + + uint32 count = 0; + + WorldPacket data(SMSG_AUCTION_LIST_PENDING_SALES, 4); + data << uint32(count); // count + /*for (uint32 i = 0; i < count; ++i) + { + data << ""; // string + data << ""; // string + data << uint32(0); + data << uint32(0); + data << float(0); + }*/ + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp b/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp new file mode 100644 index 00000000000..e779f2a8ab1 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/BattleGroundHandler.cpp @@ -0,0 +1,803 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" +#include "WorldSession.h" + +#include "ArenaTeam.h" +#include "BattleGroundMgr.h" +#include "BattleGroundWS.h" +#include "BattleGround.h" +#include "Chat.h" +#include "Language.h" +#include "Log.h" +#include "Player.h" +#include "Object.h" +#include "Opcodes.h" + +void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + sLog.outDebug("WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); + + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); + if (!unit) + return; + + if (!unit->isBattleMaster()) // it's not battlemaster + return; + + // Stop the npc if moving + unit->StopMoving(); + + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(unit->GetEntry()); + + if (!_player->GetBGAccessByLevel(bgTypeId)) + { + // temp, must be gossip message... + SendNotification(LANG_YOUR_BG_LEVEL_REQ_ERROR); + return; + } + + SendBattlegGroundList(guid, bgTypeId); +} + +void WorldSession::SendBattlegGroundList(uint64 guid, BattleGroundTypeId bgTypeId) +{ + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundListPacket(&data, guid, _player, bgTypeId, 0); + SendPacket(&data); +} + +void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket & recv_data) +{ + uint64 guid; + uint32 bgTypeId_; + uint32 instanceId; + uint8 joinAsGroup; + bool isPremade = false; + Group * grp = NULL; + + recv_data >> guid; // battlemaster guid + recv_data >> bgTypeId_; // battleground type id (DBC id) + recv_data >> instanceId; // instance id, 0 if First Available selected + recv_data >> joinAsGroup; // join as group + + if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) + { + sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow()); + return; + } + + BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); + + sLog.outDebug("WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid), GuidHigh2TypeId(GUID_HIPART(guid))); + + // can do this, since it's battleground, not arena + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); + BattleGroundQueueTypeId bgQueueTypeIdRandom = BattleGroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); + + // ignore if player is already in BG + if (_player->InBattleGround()) + return; + + // get bg instance or bg template if instance not found + BattleGround *bg = NULL; + if (instanceId) + bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId); + + if (!bg) + bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + if (!bg) + return; + + // expected bracket entry + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); + if (!bracketEntry) + return; + + GroupJoinBattlegroundResult err; + + // check queue conditions + if (!joinAsGroup) + { + // check Deserter debuff + if (!_player->CanJoinToBattleground()) + { + WorldPacket data; + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); + _player->GetSession()->SendPacket(&data); + return; + } + + if (_player->GetBattleGroundQueueIndex(bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES) + { + //player is already in random queue + WorldPacket data; + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_RANDOM_BG); + _player->GetSession()->SendPacket(&data); + return; + } + + if (_player->InBattleGroundQueue() && bgTypeId == BATTLEGROUND_RB) + { + //player is already in queue, can't start random queue + WorldPacket data; + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_NON_RANDOM_BG); + _player->GetSession()->SendPacket(&data); + return; + } + + // check if already in queue + if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) + //player is already in this queue + return; + + // check if has free queue slots + if (!_player->HasFreeBattleGroundQueueId()) + { + WorldPacket data; + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES); + _player->GetSession()->SendPacket(&data); + return; + } + + BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; + + GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0); + uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); + // already checked if queueSlot is valid, now just get it + uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); + + WorldPacket data; + // send status packet (in queue) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); + SendPacket(&data); + sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); + } + else + { + grp = _player->GetGroup(); + // no group found, error + if (!grp) + return; + if (grp->GetLeaderGUID() != _player->GetGUID()) + return; + err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); + isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); + + BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; + GroupQueueInfo * ginfo = NULL; + uint32 avgTime = 0; + + if (err > 0) + { + sLog.outDebug("Battleground: the following players are joining as group:"); + ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0); + avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); + } + + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + if (!member) continue; // this should never happen + + WorldPacket data; + + if (err <= 0) + { + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); + member->GetSession()->SendPacket(&data); + continue; + } + + // add to queue + uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); + + // send status packet (in queue) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); + member->GetSession()->SendPacket(&data); + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); + member->GetSession()->SendPacket(&data); + sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); + } + sLog.outDebug("Battleground: group end"); + + } + sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); +} + +void WorldSession::HandleBattleGroundPlayerPositionsOpcode(WorldPacket & /*recv_data*/) +{ + // empty opcode + sLog.outDebug("WORLD: Recvd MSG_BATTLEGROUND_PLAYER_POSITIONS Message"); + + BattleGround *bg = _player->GetBattleGround(); + if (!bg) // can't be received if player not in battleground + return; + + switch(bg->GetTypeID(true)) + { + case BATTLEGROUND_WS: + { + uint32 count1 = 0; //always constant zero? + uint32 count2 = 0; //count of next fields + + Player *ali_plr = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetAllianceFlagPickerGUID()); + if (ali_plr) + ++count2; + + Player *horde_plr = objmgr.GetPlayer(((BattleGroundWS*)bg)->GetHordeFlagPickerGUID()); + if (horde_plr) + ++count2; + + WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4+16*count1+16*count2)); + data << count1; // alliance flag holders count - obsolete, now always 0 + /*for (uint8 i = 0; i < count1; ++i) + { + data << uint64(0); // guid + data << (float)0; // x + data << (float)0; // y + }*/ + data << count2; // horde flag holders count - obsolete, now count of next fields + if (ali_plr) + { + data << (uint64)ali_plr->GetGUID(); + data << (float)ali_plr->GetPositionX(); + data << (float)ali_plr->GetPositionY(); + } + if (horde_plr) + { + data << (uint64)horde_plr->GetGUID(); + data << (float)horde_plr->GetPositionX(); + data << (float)horde_plr->GetPositionY(); + } + + SendPacket(&data); + } + break; + case BATTLEGROUND_EY: + //TODO : fix me! + break; + case BATTLEGROUND_AB: + case BATTLEGROUND_AV: + { + //for other BG types - send default + WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4)); + data << uint32(0); + data << uint32(0); + SendPacket(&data); + } + break; + default: + //maybe it is sent also in arena - do nothing + break; + } +} + +void WorldSession::HandlePVPLogDataOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: Recvd MSG_PVP_LOG_DATA Message"); + + BattleGround *bg = _player->GetBattleGround(); + if (!bg) + return; + + WorldPacket data; + sBattleGroundMgr.BuildPvpLogDataPacket(&data, bg); + SendPacket(&data); + + sLog.outDebug("WORLD: Sent MSG_PVP_LOG_DATA Message"); +} + +void WorldSession::HandleBattlefieldListOpcode(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_BATTLEFIELD_LIST Message"); + + uint32 bgTypeId; + recv_data >> bgTypeId; // id from DBC + + uint8 fromWhere; + recv_data >> fromWhere; // 0 - battlemaster (lua: ShowBattlefieldList), 1 - UI (lua: RequestBattlegroundInstanceInfo) + + uint8 unk1; + recv_data >> unk1; // Unknown 3.2.2 + + BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); + if (!bl) + { + sLog.outError("Battleground: invalid bgtype received."); + return; + } + + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundListPacket(&data, 0, _player, BattleGroundTypeId(bgTypeId), fromWhere); + SendPacket(&data); +} + +void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); + + uint8 type; // arenatype if arena + uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 + uint32 bgTypeId_; // type id from dbc + uint16 unk; // 0x1F90 constant? + uint8 action; // enter battle 0x1, leave queue 0x0 + + recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action; + + if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) + { + sLog.outError("BattlegroundHandler: invalid bgtype (%u) received.", bgTypeId_); + return; + } + if (!_player->InBattleGroundQueue()) + { + sLog.outError("BattlegroundHandler: Invalid CMSG_BATTLEFIELD_PORT received from player (%u), he is not in bg_queue.", _player->GetGUIDLow()); + return; + } + + //get GroupQueueInfo from BattleGroundQueue + BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, type); + BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; + //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattleGroundQueue::RemovePlayer() function + GroupQueueInfo ginfo; + if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) + { + sLog.outError("BattlegroundHandler: itrplayerstatus not found."); + return; + } + // if action == 1, then instanceId is required + if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) + { + sLog.outError("BattlegroundHandler: instance not found."); + return; + } + + BattleGround *bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); + + // bg template might and must be used in case of leaving queue, when instance is not created yet + if (!bg && action == 0) + bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + if (!bg) + { + sLog.outError("BattlegroundHandler: bg_template not found for type id %u.", bgTypeId); + return; + } + + // expected bracket entry + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); + if (!bracketEntry) + return; + + //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it + if (action == 1 && ginfo.ArenaType == 0) + { + //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue + if (!_player->CanJoinToBattleground()) + { + //send bg command result to show nice message + WorldPacket data2; + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); + _player->GetSession()->SendPacket(&data2); + action = 0; + sLog.outDebug("Battleground: player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUIDLow()); + } + //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue + if (_player->getLevel() > bg->GetMaxLevel()) + { + sLog.outError("Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!", + _player->GetName(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID()); + action = 0; + } + } + uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); + WorldPacket data; + switch(action) + { + case 1: // port to battleground + if (!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) + return; // cheating? + + if (!_player->InBattleGround()) + _player->SetBattleGroundEntryPoint(); + + // resurrect the player + if (!_player->isAlive()) + { + _player->ResurrectPlayer(1.0f); + _player->SpawnCorpseBones(); + } + // stop taxi flight at port + if (_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->CleanupAfterTaxiFlight(); + } + + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType()); + _player->GetSession()->SendPacket(&data); + // remove battleground queue status from BGmgr + bgQueue.RemovePlayer(_player->GetGUID(), false); + // this is still needed here if battleground "jumping" shouldn't add deserter debuff + // also this is required to prevent stuck at old battleground after SetBattleGroundId set to new + if (BattleGround *currentBg = _player->GetBattleGround()) + currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); + + // set the destination instance id + _player->SetBattleGroundId(bg->GetInstanceID(), bgTypeId); + // set the destination team + _player->SetBGTeam(ginfo.Team); + // bg->HandleBeforeTeleportToBattleGround(_player); + sBattleGroundMgr.SendToBattleGround(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); + // add only in HandleMoveWorldPortAck() + // bg->AddPlayer(_player,team); + sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId); + break; + case 0: // leave queue + // if player leaves rated arena match before match start, it is counted as he played but he lost + if (ginfo.IsRated) + { + ArenaTeam * at = objmgr.GetArenaTeamById(ginfo.Team); + if (at) + { + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), ginfo.OpponentsTeamRating); + at->MemberLost(_player, ginfo.OpponentsTeamRating); + at->SaveToDB(); + } + } + _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0); + bgQueue.RemovePlayer(_player->GetGUID(), true); + // player left queue, we should update it - do not update Arena Queue + if (!ginfo.ArenaType) + sBattleGroundMgr.ScheduleQueueUpdate(ginfo.ArenaTeamRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); + SendPacket(&data); + sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName(), _player->GetGUIDLow(), bg->GetTypeID(), bgQueueTypeId); + break; + default: + sLog.outError("Battleground port: unknown action %u", action); + break; + } +} + +void WorldSession::HandleLeaveBattlefieldOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_LEAVE_BATTLEFIELD Message"); + + recv_data.read_skip(); // unk1 + recv_data.read_skip(); // unk2 + recv_data.read_skip(); // BattleGroundTypeId + recv_data.read_skip(); // unk3 + + // not allow leave battleground in combat + if (_player->isInCombat()) + if (BattleGround* bg = _player->GetBattleGround()) + if (bg->GetStatus() != STATUS_WAIT_LEAVE) + return; + + _player->LeaveBattleground(); +} + +void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recv_data*/) +{ + // empty opcode + sLog.outDebug("WORLD: Battleground status"); + + WorldPacket data; + // we must update all queues here + BattleGround *bg = NULL; + for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) + { + BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i); + if (!bgQueueTypeId) + continue; + BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(bgQueueTypeId); + uint8 arenaType = BattleGroundMgr::BGArenaType(bgQueueTypeId); + if (bgTypeId == _player->GetBattleGroundTypeId()) + { + bg = _player->GetBattleGround(); + //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena + //so i must use bg pointer to get that information + if (bg && bg->GetArenaType() == arenaType) + { + // this line is checked, i only don't know if GetStartTime is changing itself after bg end! + // send status in BattleGround + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType); + SendPacket(&data); + continue; + } + } + //we are sending update to player about queue - he can be invited there! + //get GroupQueueInfo for queue status + BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; + GroupQueueInfo ginfo; + if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) + continue; + if (ginfo.IsInvitedToBGInstanceGUID) + { + bg = sBattleGroundMgr.GetBattleGround(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); + if (!bg) + continue; + uint32 remainingTime = getMSTimeDiff(getMSTime(), ginfo.RemoveInviteTime); + // send status invited to BattleGround + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0, arenaType); + SendPacket(&data); + } + else + { + bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + if (!bg) + continue; + + // expected bracket entry + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); + if (!bracketEntry) + continue; + + uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId()); + // send status in BattleGround Queue + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(ginfo.JoinTime, getMSTime()), arenaType); + SendPacket(&data); + } + } +} + +void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY"); + + BattleGround *bg = _player->GetBattleGround(); + + uint64 guid; + recv_data >> guid; + + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); + if (!unit) + return; + + if (!unit->isSpiritService()) // it's not spirit service + return; + + if (bg) + sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, guid); +} + + +void WorldSession::HandleAreaSpiritHealerQueueOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE"); + + BattleGround *bg = _player->GetBattleGround(); + + uint64 guid; + recv_data >> guid; + + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); + if (!unit) + return; + + if (!unit->isSpiritService()) // it's not spirit service + return; + + if (bg) + bg->AddPlayerToResurrectQueue(guid, _player->GetGUID()); +} + + +void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); + //recv_data.hexlike(); + + uint64 guid; // arena Battlemaster guid + uint8 arenaslot; // 2v2, 3v3 or 5v5 + uint8 asGroup; // asGroup + uint8 isRated; // isRated + Group * grp = NULL; + + recv_data >> guid >> arenaslot >> asGroup >> isRated; + + // ignore if we already in BG or BG queue + if (_player->InBattleGround()) + return; + + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); + if (!unit) + return; + + if (!unit->isBattleMaster()) // it's not battle master + return; + + uint8 arenatype = 0; + uint32 arenaRating = 0; + + switch(arenaslot) + { + case 0: + arenatype = ARENA_TYPE_2v2; + break; + case 1: + arenatype = ARENA_TYPE_3v3; + break; + case 2: + arenatype = ARENA_TYPE_5v5; + break; + default: + sLog.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot); + return; + } + + //check existance + BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA); + if (!bg) + { + sLog.outError("Battleground: template bg (all arenas) not found"); + return; + } + + BattleGroundTypeId bgTypeId = bg->GetTypeID(); + BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); + PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(),_player->getLevel()); + if (!bracketEntry) + return; + + GroupJoinBattlegroundResult err = ERR_GROUP_JOIN_BATTLEGROUND_FAIL; + + if (!asGroup) + { + // check if already in queue + if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) + //player is already in this queue + return; + // check if has free queue slots + if (!_player->HasFreeBattleGroundQueueId()) + return; + } + else + { + grp = _player->GetGroup(); + // no group found, error + if (!grp) + return; + if (grp->GetLeaderGUID() != _player->GetGUID()) + return; + err = grp->CanJoinBattleGroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); + } + + uint32 ateamId = 0; + + if (isRated) + { + ateamId = _player->GetArenaTeamId(arenaslot); + // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) + ArenaTeam * at = objmgr.GetArenaTeamById(ateamId); + if (!at) + { + _player->GetSession()->SendNotInArenaTeamPacket(arenatype); + return; + } + // get the team rating for queueing + arenaRating = at->GetRating(); + // the arenateam id must match for everyone in the group + // get the personal ratings for queueing + uint32 avg_pers_rating = 0; + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + + // calc avg personal rating + avg_pers_rating += member->GetArenaPersonalRating(arenaslot); + } + + if (arenatype) + avg_pers_rating /= arenatype; + + // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating + if (avg_pers_rating + 150 < arenaRating) + arenaRating = avg_pers_rating; + + if (arenaRating <= 0) + arenaRating = 1; + } + + BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; + if (asGroup) + { + uint32 avgTime = 0; + + if (err > 0) + { + sLog.outDebug("Battleground: arena join as group start"); + if (isRated) + { + sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype); + bg->SetRated(true); + } + else + bg->SetRated(false); + + GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); + avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); + } + + for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + if (!member) + continue; + + WorldPacket data; + + if (err <= 0) + { + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); + member->GetSession()->SendPacket(&data); + continue; + } + + // add to queue + uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); + + // send status packet (in queue) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); + member->GetSession()->SendPacket(&data); + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, err); + member->GetSession()->SendPacket(&data); + sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); + } + } + else + { + GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, ateamId); + uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); + uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); + + WorldPacket data; + // send status packet (in queue) + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); + SendPacket(&data); + sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); + } + sBattleGroundMgr.ScheduleQueueUpdate(arenaRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); +} + +void WorldSession::HandleReportPvPAFK(WorldPacket & recv_data) +{ + uint64 playerGuid; + recv_data >> playerGuid; + Player *reportedPlayer = objmgr.GetPlayer(playerGuid); + + if (!reportedPlayer) + { + sLog.outDebug("WorldSession::HandleReportPvPAFK: player not found"); + return; + } + + sLog.outDebug("WorldSession::HandleReportPvPAFK: %s reported %s", _player->GetName(), reportedPlayer->GetName()); + + reportedPlayer->ReportedAfkBy(_player); +} diff --git a/src/server/game/Server/Protocol/Handlers/CalendarHandler.cpp b/src/server/game/Server/Protocol/Handlers/CalendarHandler.cpp new file mode 100644 index 00000000000..f6679c5d5ac --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/CalendarHandler.cpp @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" + +#include "InstanceSaveMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Player.h" + +void WorldSession::HandleCalendarGetCalendar(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_CALENDAR"); // empty + + time_t cur_time = time(NULL); + + WorldPacket data(SMSG_CALENDAR_SEND_CALENDAR,4+4*0+4+4*0+4+4); + + data << uint32(0); // invite count + /* + for (;;) + { + uint64 inviteId; + uint64 unkGuid0; + uint8 unk1, unk2, unk3; + uint64 creatorGuid; + } + */ + + data << uint32(0); // event count + /* + for (;;) + { + uint64 eventId; + std::string title; // 128 chars + uint32 type; + uint32 occurrenceTime; + uint32 flags; + uint32 unk4; -- possibly mapid for dungeon/raid + uint64 creatorGuid; + } + */ + + data << uint32(0); // unk + data << uint32(secsToTimeBitFields(cur_time)); // current time + + uint32 counter = 0; + size_t p_counter = data.wpos(); + data << uint32(counter); // instance save count + + for (int i = 0; i < MAX_DIFFICULTY; ++i) + { + for (Player::BoundInstancesMap::const_iterator itr = _player->m_boundInstances[i].begin(); itr != _player->m_boundInstances[i].end(); ++itr) + { + if (itr->second.perm) + { + InstanceSave *save = itr->second.save; + data << uint32(save->GetMapId()); + data << uint32(save->GetDifficulty()); + data << uint32(save->GetResetTime() - cur_time); + data << uint64(save->GetInstanceId()); // instance save id as unique instance copy id + ++counter; + } + } + } + + data.put(p_counter, counter); + + data << uint32(1135753200); // unk (28.12.2005 12:00) + + counter = 0; + p_counter = data.wpos(); + data << uint32(counter); // raid reset count + + ResetTimeByMapDifficultyMap const& resets = sInstanceSaveManager.GetResetTimeMap(); + for (ResetTimeByMapDifficultyMap::const_iterator itr = resets.begin(); itr != resets.end(); ++itr) + { + uint32 mapid = PAIR32_LOPART(itr->first); + MapEntry const* mapEnt = sMapStore.LookupEntry(mapid); + if (!mapEnt || !mapEnt->IsRaid()) + continue; + + data << uint32(mapid); + data << uint32(itr->second - cur_time); + data << uint32(mapEnt->unk_time); + ++counter; + } + + data.put(p_counter, counter); + + data << uint32(0); // holiday count? + /* + for (;;) + { + uint32 unk5, unk6, unk7, unk8, unk9; + for (uint32 j = 0; j < 26; ++j) + { + uint32 unk10; + } + for (uint32 j = 0; j < 10; ++j) + { + uint32 unk11; + } + for (uint32 j = 0; j < 10; ++j) + { + uint32 unk12; + } + std::string holidayName; // 64 chars + } + */ + + sLog.outDebug("Sending calendar"); + data.hexlike(); + SendPacket(&data); +} + +void WorldSession::HandleCalendarGetEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_EVENT"); + recv_data.hexlike(); + recv_data.read_skip(); // unk +} + +void WorldSession::HandleCalendarGuildFilter(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GUILD_FILTER"); + recv_data.hexlike(); + recv_data.read_skip(); // unk1 + recv_data.read_skip(); // unk2 + recv_data.read_skip(); // unk3 +} + +void WorldSession::HandleCalendarArenaTeam(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_ARENA_TEAM"); + recv_data.hexlike(); + recv_data.read_skip(); // unk +} + +void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //std::string unk1, unk2; + //recv_data >> (std::string)unk1; + //recv_data >> (std::string)unk2; + + //uint8 unk3, unk4; + //uint32 unk5, unk6, unk7, unk8, unk9, count = 0; + //recv_data >> (uint8)unk3; + //recv_data >> (uint8)unk4; + //recv_data >> (uint32)unk5; + //recv_data >> (uint32)unk6; + //recv_data >> (uint32)unk7; + //recv_data >> (uint32)unk8; + //recv_data >> (uint32)unk9; + //if (!((unk9 >> 6) & 1)) + //{ + // recv_data >> (uint32)count; + // if (count) + // { + // uint8 unk12,unk13; + // uint64 guid; + // for (int i=0; i> (uint8)unk12; + // recv_data >> (uint8)unk13; + // } + // } + //} +} + +void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> std::string + //recv_data >> std::string + //recv_data >> uint8 + //recv_data >> uint8 + //recv_data >> uint32 + //recv_data >> uint32 + //recv_data >> uint32 + //recv_data >> uint32 + //recv_data >> uint32 +} + +void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint32 + +} + +void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint32 + +} + +void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> std::string + //recv_data >> uint8 + //recv_data >> uint8 + +} + +void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint32 + +} + +void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data.readPackGUID(guid) + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint64 +} + +void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data.readPackGUID(guid) + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint32 +} + +void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data.readPackGUID(guid) + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint32 +} + +void WorldSession::HandleCalendarComplain(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN"); + recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam + + //recv_data >> uint64 + //recv_data >> uint64 + //recv_data >> uint64 +} + +void WorldSession::HandleCalendarGetNumPending(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_NUM_PENDING"); // empty + + WorldPacket data(SMSG_CALENDAR_SEND_NUM_PENDING, 4); + data << uint32(0); // 0 - no pending invites, 1 - some pending invites + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp b/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp new file mode 100644 index 00000000000..0f615579cb6 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Policies/SingletonImp.h" + +#include "ObjectMgr.h" // for normalizePlayerName +#include "ChannelMgr.h" + +void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + + uint32 channel_id; + uint8 unknown1, unknown2; + std::string channelname, pass; + + recvPacket >> channel_id >> unknown1 >> unknown2; + recvPacket >> channelname; + + if (channelname.empty()) + return; + + recvPacket >> pass; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + cMgr->team = _player->GetTeam(); + if (Channel *chn = cMgr->GetJoinChannel(channelname, channel_id)) + chn->Join(_player->GetGUID(), pass.c_str()); + } +} + +void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + + uint32 unk; + std::string channelname; + recvPacket >> unk; // channel id? + recvPacket >> channelname; + + if (channelname.empty()) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Leave(_player->GetGUID(), true); + cMgr->LeftChannel(channelname); + } +} + +void WorldSession::HandleChannelList(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->List(_player); +} + +void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, pass; + recvPacket >> channelname; + + recvPacket >> pass; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Password(_player->GetGUID(), pass.c_str()); +} + +void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, newp; + recvPacket >> channelname; + + recvPacket >> newp; + + if (!normalizePlayerName(newp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetOwner(_player->GetGUID(), newp.c_str()); +} + +void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SendWhoOwner(_player->GetGUID()); +} + +void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetModerator(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnsetModerator(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelMute(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->SetMute(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnsetMute(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Invite(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelKick(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Kick(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelBan(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Ban(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + + std::string channelname, otp; + recvPacket >> channelname; + + recvPacket >> otp; + + if (!normalizePlayerName(otp)) + return; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->UnBan(_player->GetGUID(), otp.c_str()); +} + +void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Announce(_player->GetGUID()); +} + +void WorldSession::HandleChannelModerate(WorldPacket& recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->Moderate(_player->GetGUID()); +} + +void WorldSession::HandleChannelDisplayListQuery(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->List(_player); +} + +void WorldSession::HandleGetChannelMemberCount(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + { + WorldPacket data(SMSG_CHANNEL_MEMBER_COUNT, chn->GetName().size()+1+1+4); + data << chn->GetName(); + data << uint8(chn->GetFlags()); + data << uint32(chn->GetNumPlayers()); + SendPacket(&data); + } + } +} + +void WorldSession::HandleSetChannelWatch(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); + //recvPacket.hexlike(); + std::string channelname; + recvPacket >> channelname; + /*if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + if (Channel *chn = cMgr->GetChannel(channelname, _player)) + chn->JoinNotify(_player->GetGUID());*/ +} + diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp new file mode 100644 index 00000000000..416827d73ea --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -0,0 +1,1406 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "SystemConfig.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Auth/md5.h" +#include "Database/DatabaseEnv.h" +#include "Database/DatabaseImpl.h" + +#include "ArenaTeam.h" +#include "Chat.h" +#include "Group.h" +#include "Guild.h" +#include "Language.h" +#include "Log.h" +#include "Opcodes.h" +#include "Player.h" +#include "PlayerDump.h" +#include "SharedDefines.h" +#include "SocialMgr.h" +#include "UpdateMask.h" +#include "Util.h" +#include "ScriptMgr.h" + +class LoginQueryHolder : public SqlQueryHolder +{ + private: + uint32 m_accountId; + uint64 m_guid; + public: + LoginQueryHolder(uint32 accountId, uint64 guid) + : m_accountId(accountId), m_guid(guid) { } + uint64 GetGuid() const { return m_guid; } + uint32 GetAccountId() const { return m_accountId; } + bool Initialize(); +}; + +bool LoginQueryHolder::Initialize() +{ + SetSize(MAX_PLAYER_LOGIN_QUERY); + + bool res = true; + + // NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure. + // !!! NOTE: including unused `zone`,`online` + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags," + "position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost," + "resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty," + "arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk," + "health, power1, power2, power3, power4, power5, power6, power7, instance_id, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT guid FROM group_member WHERE memberGuid =%u", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADWEKLYQUESTSTATUS,"SELECT quest FROM character_queststatus_weekly WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADREPUTATION, "SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADINVENTORY, "SELECT data,text,bag,slot,item,item_template FROM character_inventory JOIN item_instance ON character_inventory.item = item_instance.guid WHERE character_inventory.guid = '%u' ORDER BY bag,slot", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACTIONS, "SELECT a.button,a.action,a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activespec AND a.guid = '%u' ORDER BY button", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = '%u' AND (checked & 1)=0 AND deliver_time <= '" UI64FMTD "'", GUID_LOPART(m_guid),(uint64)time(NULL)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADMAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = '%u' AND (checked & 1)=0", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSOCIALLIST, "SELECT friend,flags,note FROM character_social WHERE guid = '%u' LIMIT 255", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADHOMEBIND, "SELECT map,zone,position_x,position_y,position_z FROM character_homebind WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS, "SELECT spell,item,time FROM character_spell_cooldown WHERE guid = '%u'", GUID_LOPART(m_guid)); + if (sWorld.getConfig(CONFIG_DECLINED_NAMES_USED)) + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid)); + // in other case still be dummy query + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, wons_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = '%u' ORDER BY setindex", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBGDATA, "SELECT instance_id, team, join_x, join_y, join_z, join_o, join_map, taxi_start, taxi_end, mount_spell FROM character_battleground_data WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGLYPHS, "SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 FROM character_glyphs WHERE guid='%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADTALENTS, "SELECT spell, spec FROM character_talent WHERE guid='%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA, "SELECT type, time, data FROM character_account_data WHERE guid='%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADRANDOMBG, "SELECT guid FROM character_battleground_random WHERE guid = '%u'", GUID_LOPART(m_guid)); + + return res; +} + +// don't call WorldSession directly +// it may get deleted before the query callbacks get executed +// instead pass an account id to this handler +class CharacterHandler +{ + + public: + void HandleCharEnumCallback(QueryResult_AutoPtr result, uint32 account) + { + WorldSession * session = sWorld.FindSession(account); + if (!session) + return; + session->HandleCharEnum(result); + } + void HandlePlayerLoginCallback(QueryResult_AutoPtr /*dummy*/, SqlQueryHolder * holder) + { + if (!holder) return; + WorldSession *session = sWorld.FindSession(((LoginQueryHolder*)holder)->GetAccountId()); + if (!session) + { + delete holder; + return; + } + session->HandlePlayerLogin((LoginQueryHolder*)holder); + } +} chrHandler; + +void WorldSession::HandleCharEnum(QueryResult_AutoPtr result) +{ + WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size + + uint8 num = 0; + + data << num; + + if (result) + { + do + { + uint32 guidlow = (*result)[0].GetUInt32(); + sLog.outDetail("Loading char guid %u from account %u.",guidlow,GetAccountId()); + if (Player::BuildEnumData(result, &data)) + ++num; + } + while (result->NextRow()); + } + + data.put(0, num); + + SendPacket(&data); +} + +void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/) +{ + /// get all the data necessary for loading all characters (along with their pets) on the account + CharacterDatabase.AsyncPQuery(&chrHandler, &CharacterHandler::HandleCharEnumCallback, GetAccountId(), + !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? + // ------- Query Without Declined Names -------- + // 0 1 2 3 4 5 6 7 + "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " + // 8 9 10 11 12 13 14 + "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " + // 15 16 17 18 19 + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache " + "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' " + "LEFT JOIN guild_member ON characters.guid = guild_member.guid " + "WHERE characters.account = '%u' ORDER BY characters.guid" + : + // --------- Query With Declined Names --------- + // 0 1 2 3 4 5 6 7 + "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " + // 8 9 10 11 12 13 14 + "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " + // 15 16 17 18 19 20 + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_declinedname.genitive " + "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' " + "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid " + "LEFT JOIN guild_member ON characters.guid = guild_member.guid " + "WHERE characters.account = '%u' ORDER BY characters.guid", + PET_SAVE_AS_CURRENT,GetAccountId()); +} + +void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data) +{ + std::string name; + uint8 race_,class_; + + recv_data >> name; + + recv_data >> race_; + recv_data >> class_; + + WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases + + if (GetSecurity() == SEC_PLAYER) + { + if (uint32 mask = sWorld.getConfig(CONFIG_CHARACTERS_CREATING_DISABLED)) + { + bool disabled = false; + + uint32 team = Player::TeamForRace(race_); + switch(team) + { + case ALLIANCE: disabled = mask & (1<<0); break; + case HORDE: disabled = mask & (1<<1); break; + } + + if (disabled) + { + data << (uint8)CHAR_CREATE_DISABLED; + SendPacket(&data); + return; + } + } + } + + ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); + ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); + + if (!classEntry || !raceEntry) + { + data << (uint8)CHAR_CREATE_FAILED; + SendPacket(&data); + sLog.outError("Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); + return; + } + + // prevent character creating Expansion race without Expansion account + if (raceEntry->expansion > Expansion()) + { + data << (uint8)CHAR_CREATE_EXPANSION; + sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->expansion,race_); + SendPacket(&data); + return; + } + + // prevent character creating Expansion class without Expansion account + if (classEntry->expansion > Expansion()) + { + data << (uint8)CHAR_CREATE_EXPANSION_CLASS; + sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->expansion,class_); + SendPacket(&data); + return; + } + + // prevent character creating with invalid name + if (!normalizePlayerName(name)) + { + data << (uint8)CHAR_NAME_NO_NAME; + SendPacket(&data); + sLog.outError("Account:[%d] but tried to Create character with empty [name] ",GetAccountId()); + return; + } + + // check name limitations + uint8 res = ObjectMgr::CheckPlayerName(name,true); + if (res != CHAR_NAME_SUCCESS) + { + data << uint8(res); + SendPacket(&data); + return; + } + + if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name)) + { + data << (uint8)CHAR_NAME_RESERVED; + SendPacket(&data); + return; + } + + if (objmgr.GetPlayerGUIDByName(name)) + { + data << (uint8)CHAR_CREATE_NAME_IN_USE; + SendPacket(&data); + return; + } + + QueryResult_AutoPtr resultacct = LoginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); + if (resultacct) + { + Field *fields=resultacct->Fetch(); + uint32 acctcharcount = fields[0].GetUInt32(); + + if (acctcharcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) + { + data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; + SendPacket(&data); + return; + } + } + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", GetAccountId()); + uint8 charcount = 0; + if (result) + { + Field *fields=result->Fetch(); + charcount = fields[0].GetUInt8(); + + if (charcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_REALM)) + { + data << (uint8)CHAR_CREATE_SERVER_LIMIT; + SendPacket(&data); + return; + } + } + + // speedup check for heroic class disabled case + uint32 heroic_free_slots = sWorld.getConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM); + if (heroic_free_slots == 0 && GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket(&data); + return; + } + + // speedup check for heroic class disabled case + uint32 req_level_for_heroic = sWorld.getConfig(CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING); + if (GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; + SendPacket(&data); + return; + } + + bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; + uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); + + bool have_same_race = false; + + // if 0 then allowed creating without any characters + bool have_req_level_for_heroic = (req_level_for_heroic == 0); + + if (!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) + { + QueryResult_AutoPtr result2 = CharacterDatabase.PQuery("SELECT level,race,class FROM characters WHERE account = '%u' %s", + GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1"); + if (result2) + { + uint32 team_= Player::TeamForRace(race_); + + Field* field = result2->Fetch(); + uint8 acc_race = field[1].GetUInt32(); + + if (GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) + { + uint8 acc_class = field[2].GetUInt32(); + if (acc_class == CLASS_DEATH_KNIGHT) + { + if (heroic_free_slots > 0) + --heroic_free_slots; + + if (heroic_free_slots == 0) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket(&data); + return; + } + } + + if (!have_req_level_for_heroic) + { + uint32 acc_level = field[0].GetUInt32(); + if (acc_level >= req_level_for_heroic) + have_req_level_for_heroic = true; + } + } + + // need to check team only for first character + // TODO: what to if account already has characters of both races? + if (!AllowTwoSideAccounts) + { + uint32 acc_team=0; + if (acc_race > 0) + acc_team = Player::TeamForRace(acc_race); + + if (acc_team != team_) + { + data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; + SendPacket(&data); + return; + } + } + + // search same race for cinematic or same class if need + // TODO: check if cinematic already shown? (already logged in?; cinematic field) + while ((skipCinematics == 1 && !have_same_race) || class_ == CLASS_DEATH_KNIGHT) + { + if (!result2->NextRow()) + break; + + field = result2->Fetch(); + acc_race = field[1].GetUInt32(); + + if (!have_same_race) + have_same_race = race_ == acc_race; + + if (GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) + { + uint8 acc_class = field[2].GetUInt32(); + if (acc_class == CLASS_DEATH_KNIGHT) + { + if (heroic_free_slots > 0) + --heroic_free_slots; + + if (heroic_free_slots == 0) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket(&data); + return; + } + } + + if (!have_req_level_for_heroic) + { + uint32 acc_level = field[0].GetUInt32(); + if (acc_level >= req_level_for_heroic) + have_req_level_for_heroic = true; + } + } + } + } + } + + if (GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && !have_req_level_for_heroic) + { + data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; + SendPacket(&data); + return; + } + + // extract other data required for player creating + uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; + recv_data >> gender >> skin >> face; + recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; + + if (recv_data.rpos() < recv_data.wpos()) + { + uint8 unk; + recv_data >> unk; + sLog.outDebug("Character creation %s (account %u) has unhandled tail data: [%u]", name.c_str(), GetAccountId(), unk); + } + + Player * pNewChar = new Player(this); + if (!pNewChar->Create(objmgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId)) + { + // Player not create (race/class problem?) + pNewChar->CleanupsBeforeDelete(); + delete pNewChar; + + data << (uint8)CHAR_CREATE_ERROR; + SendPacket(&data); + + return; + } + + if ((have_same_race && skipCinematics == 1) || skipCinematics == 2) + pNewChar->setCinematic(1); // not show intro + + pNewChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login + + // Player created, save it now + pNewChar->SaveToDB(); + charcount+=1; + + LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); + LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); + + pNewChar->CleanupsBeforeDelete(); + + data << (uint8)CHAR_CREATE_SUCCESS; + SendPacket(&data); + + std::string IP_str = GetRemoteAddress(); + sLog.outBasic("Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), pNewChar->GetGUIDLow()); + sLog.outChar("Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), pNewChar->GetGUIDLow()); + delete pNewChar; // created only to call SaveToDB() + +} + +void WorldSession::HandleCharDeleteOpcode(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + + // can't delete loaded character + if (objmgr.GetPlayer(guid)) + return; + + uint32 accountId = 0; + std::string name; + + // is guild leader + if (objmgr.GetGuildByLeader(guid)) + { + WorldPacket data(SMSG_CHAR_DELETE, 1); + data << (uint8)CHAR_DELETE_FAILED_GUILD_LEADER; + SendPacket(&data); + return; + } + + // is arena team captain + if (objmgr.GetArenaTeamByCaptain(guid)) + { + WorldPacket data(SMSG_CHAR_DELETE, 1); + data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN; + SendPacket(&data); + return; + } + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT account,name FROM characters WHERE guid='%u'", GUID_LOPART(guid)); + if (result) + { + Field *fields = result->Fetch(); + accountId = fields[0].GetUInt32(); + name = fields[1].GetCppString(); + } + + // prevent deleting other players' characters using cheating tools + if (accountId != GetAccountId()) + return; + + std::string IP_str = GetRemoteAddress(); + sLog.outDetail("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid)); + sLog.outChar("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid)); + + if (sLog.IsOutCharDump()) // optimize GetPlayerDump call + { + std::string dump = PlayerDumpWriter().GetDump(GUID_LOPART(guid)); + sLog.outCharDump(dump.c_str(),GetAccountId(),GUID_LOPART(guid),name.c_str()); + } + + Player::DeleteFromDB(guid, GetAccountId()); + + WorldPacket data(SMSG_CHAR_DELETE, 1); + data << (uint8)CHAR_DELETE_SUCCESS; + SendPacket(&data); +} + +void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data) +{ + if (PlayerLoading() || GetPlayer() != NULL) + { + sLog.outError("Player tryes to login again, AccountId = %d",GetAccountId()); + return; + } + + m_playerLoading = true; + uint64 playerGuid = 0; + + DEBUG_LOG("WORLD: Recvd Player Logon Message"); + + recv_data >> playerGuid; + + LoginQueryHolder *holder = new LoginQueryHolder(GetAccountId(), playerGuid); + if (!holder->Initialize()) + { + delete holder; // delete all unprocessed queries + m_playerLoading = false; + return; + } + + CharacterDatabase.DelayQueryHolder(&chrHandler, &CharacterHandler::HandlePlayerLoginCallback, holder); +} + +void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) +{ + uint64 playerGuid = holder->GetGuid(); + + Player* pCurrChar = new Player(this); + // for send server info and strings (config) + ChatHandler chH = ChatHandler(pCurrChar); + + // "GetAccountId() == db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) + if (!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) + { + KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick + delete pCurrChar; // delete it manually + delete holder; // delete all unprocessed queries + m_playerLoading = false; + return; + } + + pCurrChar->GetMotionMaster()->Initialize(); + + SetPlayer(pCurrChar); + + pCurrChar->SendDungeonDifficulty(false); + + WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20); + data << pCurrChar->GetMapId(); + data << pCurrChar->GetPositionX(); + data << pCurrChar->GetPositionY(); + data << pCurrChar->GetPositionZ(); + data << pCurrChar->GetOrientation(); + SendPacket(&data); + + // load player specific part before send times + LoadAccountData(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA),PER_CHARACTER_CACHE_MASK); + SendAccountDataTimes(PER_CHARACTER_CACHE_MASK); + + data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 + data << uint8(2); // unknown value + data << uint8(0); // enable(1)/disable(0) voice chat interface in client + SendPacket(&data); + + // Send MOTD + { + data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 + data << (uint32)0; + + uint32 linecount=0; + std::string str_motd = sWorld.GetMotd(); + std::string::size_type pos, nextpos; + + pos = 0; + while ((nextpos= str_motd.find('@',pos)) != std::string::npos) + { + if (nextpos != pos) + { + data << str_motd.substr(pos,nextpos-pos); + ++linecount; + } + pos = nextpos+1; + } + + if (posGetGUIDLow()); + QueryResult_AutoPtr resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); + + if (resultGuild) + { + Field *fields = resultGuild->Fetch(); + pCurrChar->SetInGuild(fields[0].GetUInt32()); + pCurrChar->SetRank(fields[1].GetUInt32()); + } + else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership + { + pCurrChar->SetInGuild(0); + pCurrChar->SetRank(0); + } + + if (pCurrChar->GetGuildId() != 0) + { + Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); + if (guild) + { + data.Initialize(SMSG_GUILD_EVENT, (1+1+guild->GetMOTD().size()+1)); + data << uint8(GE_MOTD); + data << uint8(1); + data << guild->GetMOTD(); + SendPacket(&data); + DEBUG_LOG("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)"); + + guild->DisplayGuildBankTabsInfo(this); + + guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetGUID(), 1, pCurrChar->GetName(), "", ""); + } + else + { + // remove wrong guild data + sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); + pCurrChar->SetInGuild(0); + } + } + + data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4); + data << uint32(0); + data << uint32(0); + SendPacket(&data); + + pCurrChar->SendInitialPacketsBeforeAddToMap(); + + //Show cinematic at the first time that player login + if (!pCurrChar->getCinematic()) + { + pCurrChar->setCinematic(1); + + if (ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) + { + if (cEntry->CinematicSequence) + pCurrChar->SendCinematicStart(cEntry->CinematicSequence); + else if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) + pCurrChar->SendCinematicStart(rEntry->CinematicSequence); + + // send new char string if not empty + if (!sWorld.GetNewCharString().empty()) + chH.PSendSysMessage(sWorld.GetNewCharString().c_str()); + } + } + + if (!pCurrChar->GetMap()->Add(pCurrChar) || !pCurrChar->CheckInstanceLoginValid()) + { + AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId()); + if (at) + pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); + else + pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); + } + + ObjectAccessor::Instance().AddObject(pCurrChar); + //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); + + pCurrChar->SendInitialPacketsAfterAddToMap(); + + CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); + LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId()); + pCurrChar->SetInGameTime(getMSTime()); + + // announce group about member online (must be after add to player list to receive announce to self) + if (Group *group = pCurrChar->GetGroup()) + { + //pCurrChar->groupInfo.group->SendInit(this); // useless + group->SendUpdate(); + group->ResetMaxEnchantingLevel(); + } + + // friend status + sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); + + // Place character in world (and load zone) before some object loading + pCurrChar->LoadCorpse(); + + // setting Ghost+speed if dead + if (pCurrChar->m_deathState != ALIVE) + { + // not blizz like, we must correctly save and load player instead... + if (pCurrChar->getRace() == RACE_NIGHTELF) + pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) + pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) + + pCurrChar->SetMovement(MOVE_WATER_WALK); + } + + pCurrChar->ContinueTaxiFlight(); + + // reset for all pets before pet loading + if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) + Pet::resetTalentsForAllPetsOf(pCurrChar); + + // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned) + pCurrChar->LoadPet(); + + // Set FFA PvP for non GM in non-rest mode + if (sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING)) + pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + + if (pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) + pCurrChar->SetContestedPvP(); + + // Apply at_login requests + if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) + { + pCurrChar->resetSpells(); + SendNotification(LANG_RESET_SPELLS); + } + + if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) + { + pCurrChar->resetTalents(true); + pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state + SendNotification(LANG_RESET_TALENTS); + } + + if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST)) + pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST); + + // show time before shutdown if shutdown planned. + if (sWorld.IsShutdowning()) + sWorld.ShutdownMsg(true,pCurrChar); + + if (sWorld.getConfig(CONFIG_ALL_TAXI_PATHS)) + pCurrChar->SetTaxiCheater(true); + + if (pCurrChar->isGameMaster()) + SendNotification(LANG_GM_ON); + + std::string IP_str = GetRemoteAddress(); + sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (GUID: %u)", + GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow()); + + if (!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED)) + pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); + + m_playerLoading = false; + + //Hook for OnLogin Event + sScriptMgr.OnLogin(pCurrChar); + delete holder; +} + +void WorldSession::HandleSetFactionAtWar(WorldPacket & recv_data) +{ + DEBUG_LOG("WORLD: Received CMSG_SET_FACTION_ATWAR"); + + uint32 repListID; + uint8 flag; + + recv_data >> repListID; + recv_data >> flag; + + GetPlayer()->GetReputationMgr().SetAtWar(repListID,flag); +} + +//I think this function is never used :/ I dunno, but i guess this opcode not exists +void WorldSession::HandleSetFactionCheat(WorldPacket & /*recv_data*/) +{ + sLog.outError("WORLD SESSION: HandleSetFactionCheat, not expected call, please report."); + /* + uint32 FactionID; + uint32 Standing; + + recv_data >> FactionID; + recv_data >> Standing; + + std::list::iterator itr; + + for (itr = GetPlayer()->factions.begin(); itr != GetPlayer()->factions.end(); ++itr) + { + if (itr->ReputationListID == FactionID) + { + itr->Standing += Standing; + itr->Flags = (itr->Flags | 1); + break; + } + } + */ + GetPlayer()->GetReputationMgr().SendStates(); +} + +void WorldSession::HandleMeetingStoneInfo(WorldPacket & /*recv_data*/) +{ + DEBUG_LOG("WORLD: Received CMSG_MEETING_STONE_INFO"); + + //SendLfgUpdate(0, 0, 0); +} + +void WorldSession::HandleTutorialFlag(WorldPacket & recv_data) +{ + uint32 iFlag; + recv_data >> iFlag; + + uint32 wInt = (iFlag / 32); + if (wInt >= 8) + { + //sLog.outError("CHEATER? Account:[%d] Guid[%u] tried to send wrong CMSG_TUTORIAL_FLAG", GetAccountId(),GetGUID()); + return; + } + uint32 rInt = (iFlag % 32); + + uint32 tutflag = GetTutorialInt(wInt); + tutflag |= (1 << rInt); + SetTutorialInt(wInt, tutflag); + + //sLog.outDebug("Received Tutorial Flag Set {%u}.", iFlag); +} + +void WorldSession::HandleTutorialClear(WorldPacket & /*recv_data*/) +{ + for (int i = 0; i < 8; ++i) + SetTutorialInt(i, 0xFFFFFFFF); +} + +void WorldSession::HandleTutorialReset(WorldPacket & /*recv_data*/) +{ + for (int i = 0; i < 8; ++i) + SetTutorialInt(i, 0x00000000); +} + +void WorldSession::HandleSetWatchedFactionOpcode(WorldPacket & recv_data) +{ + DEBUG_LOG("WORLD: Received CMSG_SET_WATCHED_FACTION"); + uint32 fact; + recv_data >> fact; + GetPlayer()->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fact); +} + +void WorldSession::HandleSetFactionInactiveOpcode(WorldPacket & recv_data) +{ + DEBUG_LOG("WORLD: Received CMSG_SET_FACTION_INACTIVE"); + uint32 replistid; + uint8 inactive; + recv_data >> replistid >> inactive; + + _player->GetReputationMgr().SetInactive(replistid, inactive); +} + +void WorldSession::HandleShowingHelmOpcode(WorldPacket & /*recv_data*/) +{ + DEBUG_LOG("CMSG_SHOWING_HELM for %s", _player->GetName()); + _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM); +} + +void WorldSession::HandleShowingCloakOpcode(WorldPacket & /*recv_data*/) +{ + DEBUG_LOG("CMSG_SHOWING_CLOAK for %s", _player->GetName()); + _player->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK); +} + +void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data) +{ + uint64 guid; + std::string newname; + + recv_data >> guid; + recv_data >> newname; + + // prevent character rename to invalid name + if (!normalizePlayerName(newname)) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << uint8(CHAR_NAME_NO_NAME); + SendPacket(&data); + return; + } + + uint8 res = ObjectMgr::CheckPlayerName(newname,true); + if (res != CHAR_NAME_SUCCESS) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << uint8(res); + SendPacket(&data); + return; + } + + // check name limitations + if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << uint8(CHAR_NAME_RESERVED); + SendPacket(&data); + return; + } + + std::string escaped_newname = newname; + CharacterDatabase.escape_string(escaped_newname); + + // make sure that the character belongs to the current account, that rename at login is enabled + // and that there is no character with the desired new name + CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, + GetAccountId(), newname, + "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", + GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str() +); +} + +void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string newname) +{ + WorldSession * session = sWorld.FindSession(accountId); + if (!session) + return; + + if (!result) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << uint8(CHAR_CREATE_ERROR); + session->SendPacket(&data); + return; + } + + uint32 guidLow = result->Fetch()[0].GetUInt32(); + uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); + std::string oldname = result->Fetch()[1].GetCppString(); + + CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow); + + sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str()); + + WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1)); + data << uint8(RESPONSE_SUCCESS); + data << uint64(guid); + data << newname; + session->SendPacket(&data); +} + +void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) +{ + uint64 guid; + + recv_data >> guid; + + // not accept declined names for unsupported languages + std::string name; + if (!objmgr.GetPlayerNameByGUID(guid, name)) + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); + data << uint32(1); + data << uint64(guid); + SendPacket(&data); + return; + } + + std::wstring wname; + if (!Utf8toWStr(name, wname)) + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); + data << uint32(1); + data << uint64(guid); + SendPacket(&data); + return; + } + + if (!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); + data << uint32(1); + data << uint64(guid); + SendPacket(&data); + return; + } + + std::string name2; + DeclinedName declinedname; + + recv_data >> name2; + + if (name2 != name) // character have different name + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); + data << uint32(1); + data << uint64(guid); + SendPacket(&data); + return; + } + + for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + { + recv_data >> declinedname.name[i]; + if (!normalizePlayerName(declinedname.name[i])) + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); + data << uint32(1); + data << uint64(guid); + SendPacket(&data); + return; + } + } + + if (!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname, 0), declinedname)) + { + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); + data << uint32(1); + data << uint64(guid); + SendPacket(&data); + return; + } + + for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + CharacterDatabase.escape_string(declinedname.name[i]); + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid)); + CharacterDatabase.PExecute("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%s','%s','%s','%s','%s')", + GUID_LOPART(guid), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); + CharacterDatabase.CommitTransaction(); + + WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); + data << uint32(0); // OK + data << uint64(guid); + SendPacket(&data); +} + +void WorldSession::HandleAlterAppearance(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_ALTER_APPEARANCE"); + + uint32 Hair, Color, FacialHair, SkinColor; + recv_data >> Hair >> Color >> FacialHair >> SkinColor; + + BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair); + + if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->getGender()) + return; + + BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair); + + if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender()) + return; + + BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(SkinColor); + + if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->getGender())) + return; + + uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id, bs_skinColor); + + // 0 - ok + // 1,3 - not enough money + // 2 - you have to seat on barber chair + if (_player->GetMoney() < Cost) + { + WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); + data << uint32(1); // no money + SendPacket(&data); + return; + } + else + { + WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); + data << uint32(0); // ok + SendPacket(&data); + } + + _player->ModifyMoney(-int32(Cost)); // it isn't free + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, Cost); + + _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id)); + _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color)); + _player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id)); + if (bs_skinColor) + _player->SetByteValue(PLAYER_BYTES, 0, uint8(bs_skinColor->hair_id)); + + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); + + _player->SetStandState(0); // stand up +} + +void WorldSession::HandleRemoveGlyph(WorldPacket & recv_data) +{ + uint32 slot; + recv_data >> slot; + + if (slot >= MAX_GLYPH_SLOT_INDEX) + { + sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot); + return; + } + + if (uint32 glyph = _player->GetGlyph(slot)) + { + if (GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) + { + _player->RemoveAurasDueToSpell(gp->SpellId); + _player->SetGlyph(slot, 0); + _player->SendTalentsInfoData(false); + } + } +} + +void WorldSession::HandleCharCustomize(WorldPacket& recv_data) +{ + uint64 guid; + std::string newname; + + recv_data >> guid; + recv_data >> newname; + + uint8 gender, skin, face, hairStyle, hairColor, facialHair; + recv_data >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face; + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); + if (!result) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_ERROR); + SendPacket(&data); + return; + } + + Field *fields = result->Fetch(); + uint32 at_loginFlags = fields[0].GetUInt32(); + + if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_ERROR); + SendPacket(&data); + return; + } + + // prevent character rename to invalid name + if (!normalizePlayerName(newname)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_NAME_NO_NAME); + SendPacket(&data); + return; + } + + uint8 res = ObjectMgr::CheckPlayerName(newname,true); + if (res != CHAR_NAME_SUCCESS) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(res); + SendPacket(&data); + return; + } + + // check name limitations + if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_NAME_RESERVED); + SendPacket(&data); + return; + } + + // character with this name already exist + if (uint64 newguid = objmgr.GetPlayerGUIDByName(newname)) + { + if (newguid != guid) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_NAME_IN_USE); + SendPacket(&data); + return; + } + } + + CharacterDatabase.escape_string(newname); + if (QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid ='%u'", GUID_LOPART(guid))) + { + std::string oldname = result->Fetch()[0].GetCppString(); + std::string IP_str = GetRemoteAddress(); + sLog.outChar("Account: %d (IP: %s), Character[%s] (guid:%u) Customized to: %s", GetAccountId(), IP_str.c_str(), oldname.c_str(), GUID_LOPART(guid), newname.c_str()); + } + Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); + CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_CUSTOMIZE), GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); + + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newname.size()+1)+6); + data << uint8(RESPONSE_SUCCESS); + data << uint64(guid); + data << newname; + data << uint8(gender); + data << uint8(skin); + data << uint8(face); + data << uint8(hairStyle); + data << uint8(hairColor); + data << uint8(facialHair); + SendPacket(&data); +} + +void WorldSession::HandleEquipmentSetSave(WorldPacket &recv_data) +{ + sLog.outDebug("CMSG_EQUIPMENT_SET_SAVE"); + + uint64 setGuid; + if (!recv_data.readPackGUID(setGuid)) + return; + + uint32 index; + recv_data >> index; + if (index >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount + return; + + std::string name; + recv_data >> name; + + std::string iconName; + recv_data >> iconName; + + EquipmentSet eqSet; + + eqSet.Guid = setGuid; + eqSet.Name = name; + eqSet.IconName = iconName; + eqSet.state = EQUIPMENT_SET_NEW; + + for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) + { + uint64 itemGuid; + if (!recv_data.readPackGUID(itemGuid)) + return; + + Item *item = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + + if (!item && itemGuid) // cheating check 1 + return; + + if (item && item->GetGUID() != itemGuid) // cheating check 2 + return; + + eqSet.Items[i] = GUID_LOPART(itemGuid); + } + + _player->SetEquipmentSet(index, eqSet); +} + +void WorldSession::HandleEquipmentSetDelete(WorldPacket &recv_data) +{ + sLog.outDebug("CMSG_EQUIPMENT_SET_DELETE"); + + uint64 setGuid; + if (!recv_data.readPackGUID(setGuid)) + return; + + _player->DeleteEquipmentSet(setGuid); +} + +void WorldSession::HandleEquipmentSetUse(WorldPacket &recv_data) +{ + sLog.outDebug("CMSG_EQUIPMENT_SET_USE"); + recv_data.hexlike(); + + for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) + { + uint64 itemGuid; + if (!recv_data.readPackGUID(itemGuid)) + return; + + uint8 srcbag, srcslot; + recv_data >> srcbag >> srcslot; + + sLog.outDebug("Item " UI64FMTD ": srcbag %u, srcslot %u", itemGuid, srcbag, srcslot); + + Item *item = _player->GetItemByGuid(itemGuid); + + uint16 dstpos = i | (INVENTORY_SLOT_BAG_0 << 8); + + if (!item) + { + Item *uItem = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + if (!uItem) + continue; + + ItemPosCountVec sDest; + uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, uItem, false); + if (msg == EQUIP_ERR_OK) + { + _player->RemoveItem(INVENTORY_SLOT_BAG_0, i, true); + _player->StoreItem(sDest, uItem, true); + } + else + _player->SendEquipError(msg, uItem, NULL); + + continue; + } + + if (item->GetPos() == dstpos) + continue; + + _player->SwapItem(item->GetPos(), dstpos); + } + + WorldPacket data(SMSG_EQUIPMENT_SET_USE_RESULT, 1); + data << uint8(0); // 4 - equipment swap failed - inventory is full + SendPacket(&data); +} + +void WorldSession::HandleOnPVPKill(Player *killed) +{ + sScriptMgr.OnPVPKill(GetPlayer(), killed); +} + +bool WorldSession::HandleOnPlayerChat(const char *text) +{ + return sScriptMgr.OnPlayerChat(GetPlayer(), text); +} + +uint32 WorldSession::HandleOnGetXP(uint32 amount) +{ + return sScriptMgr.OnGetXP(GetPlayer(), amount); +} + +int32 WorldSession::HandleOnGetMoney(int32 amount) +{ + return sScriptMgr.OnGetMoney(GetPlayer(), amount); +} + +void WorldSession::HandleOnAreaChange(AreaTableEntry const *pArea) +{ + sScriptMgr.OnAreaChange(GetPlayer(), pArea); +} + +bool WorldSession::HandleOnItemClick(Item *pItem) +{ + return sScriptMgr.OnItemClick(GetPlayer(), pItem); +} + +bool WorldSession::HandleOnItemOpen(Item *pItem) +{ + return sScriptMgr.OnItemOpen(GetPlayer(), pItem); +} + +bool WorldSession::HandleOnGoClick(GameObject *pGameObject) +{ + return sScriptMgr.OnGoClick(GetPlayer(), pGameObject); +} + +void WorldSession::HandleOnCreatureKill(Creature *pCreature) +{ + sScriptMgr.OnCreatureKill(GetPlayer(), pCreature); +} diff --git a/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp b/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp new file mode 100644 index 00000000000..88e2b5473a5 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp @@ -0,0 +1,756 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Database/DatabaseEnv.h" + +#include "CellImpl.h" +#include "Chat.h" +#include "ChannelMgr.h" +#include "GridNotifiersImpl.h" +#include "Group.h" +#include "Guild.h" +#include "Language.h" +#include "Log.h" +#include "Opcodes.h" +#include "Player.h" +#include "SpellAuras.h" +#include "SpellAuraEffects.h" +#include "Util.h" + +bool WorldSession::processChatmessageFurtherAfterSecurityChecks(std::string& msg, uint32 lang) +{ + if (lang != LANG_ADDON) + { + // strip invisible characters for non-addon messages + if (sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING)) + stripLineInvisibleChars(msg); + + if (sWorld.getConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY) && GetSecurity() < SEC_MODERATOR + && !ChatHandler(this).isValidChatMessage(msg.c_str())) + { + sLog.outError("Player %s (GUID: %u) sent a chatmessage with an invalid link: %s", GetPlayer()->GetName(), + GetPlayer()->GetGUIDLow(), msg.c_str()); + if (sWorld.getConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK)) + KickPlayer(); + return false; + } + } + + return true; +} + +void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) +{ + uint32 type; + uint32 lang; + + recv_data >> type; + recv_data >> lang; + + if (type >= MAX_CHAT_MSG_TYPE) + { + sLog.outError("CHAT: Wrong message type received: %u", type); + return; + } + + //sLog.outDebug("CHAT: packet received. type %u, lang %u", type, lang); + + // prevent talking at unknown language (cheating) + LanguageDesc const* langDesc = GetLanguageDescByID(lang); + if (!langDesc) + { + SendNotification(LANG_UNKNOWN_LANGUAGE); + return; + } + if (langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) + { + // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) + Unit::AuraEffectList const& langAuras = _player->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE); + bool foundAura = false; + for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i) + { + if ((*i)->GetMiscValue() == int32(lang)) + { + foundAura = true; + break; + } + } + if (!foundAura) + { + SendNotification(LANG_NOT_LEARNED_LANGUAGE); + return; + } + } + + if (lang == LANG_ADDON) + { + if (sWorld.getConfig(CONFIG_CHATLOG_ADDON)) + { + std::string msg = ""; + recv_data >> msg; + + if (msg.empty()) + { + sLog.outDebug("Player %s send empty addon msg", GetPlayer()->GetName()); + return; + } + + sLog.outChat("[ADDON] Player %s sends: %s", + GetPlayer()->GetName(), msg.c_str()); + } + + // Disabled addon channel? + if (!sWorld.getConfig(CONFIG_ADDON_CHANNEL)) + return; + } + // LANG_ADDON should not be changed nor be affected by flood control + else + { + // send in universal language if player in .gmon mode (ignore spell effects) + if (_player->isGameMaster()) + lang = LANG_UNIVERSAL; + else + { + // send in universal language in two side iteration allowed mode + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT)) + lang = LANG_UNIVERSAL; + else + { + switch(type) + { + case CHAT_MSG_PARTY: + case CHAT_MSG_RAID: + case CHAT_MSG_RAID_LEADER: + case CHAT_MSG_RAID_WARNING: + // allow two side chat at group channel if two side group allowed + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) + lang = LANG_UNIVERSAL; + break; + case CHAT_MSG_GUILD: + case CHAT_MSG_OFFICER: + // allow two side chat at guild channel if two side guild allowed + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) + lang = LANG_UNIVERSAL; + break; + } + } + + // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) + Unit::AuraEffectList const& ModLangAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE); + if (!ModLangAuras.empty()) + lang = ModLangAuras.front()->GetMiscValue(); + } + + if (!_player->CanSpeak()) + { + std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); + SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); + return; + } + + if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) + GetPlayer()->UpdateSpeakTime(); + } + + if (GetPlayer()->HasAura(1852) && type != CHAT_MSG_WHISPER) + { + std::string msg=""; + recv_data >> msg; + + SendNotification(GetTrinityString(LANG_GM_SILENCE), GetPlayer()->GetName()); + return; + } + + switch(type) + { + case CHAT_MSG_SAY: + case CHAT_MSG_EMOTE: + case CHAT_MSG_YELL: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_SAY_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_SAY_REQ), sWorld.getConfig(CONFIG_CHAT_SAY_LEVEL_REQ)); + return; + } + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + if (type == CHAT_MSG_SAY) + GetPlayer()->Say(msg, lang); + else if (type == CHAT_MSG_EMOTE) + GetPlayer()->TextEmote(msg); + else if (type == CHAT_MSG_YELL) + GetPlayer()->Yell(msg, lang); + } break; + + case CHAT_MSG_WHISPER: + { + std::string to, msg; + recv_data >> to; + recv_data >> msg; + + if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_WHISPER_REQ), sWorld.getConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)); + return; + } + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + if (!normalizePlayerName(to)) + { + SendPlayerNotFoundNotice(to); + break; + } + + Player *player = objmgr.GetPlayer(to.c_str()); + uint32 tSecurity = GetSecurity(); + uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; + if (!player || (tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())) + { + SendPlayerNotFoundNotice(to); + return; + } + + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) && tSecurity == SEC_PLAYER && pSecurity == SEC_PLAYER) + { + uint32 sidea = GetPlayer()->GetTeam(); + uint32 sideb = player->GetTeam(); + if (sidea != sideb) + { + SendWrongFactionNotice(); + return; + } + } + + if (GetPlayer()->HasAura(1852) && !player->isGameMaster()) + { + SendNotification(GetTrinityString(LANG_GM_SILENCE), GetPlayer()->GetName()); + return; + } + + GetPlayer()->Whisper(msg, lang, player->GetGUID()); + } break; + + case CHAT_MSG_PARTY: + case CHAT_MSG_PARTY_LEADER: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + // if player is in battleground, he cannot say to battleground members by /p + Group *group = GetPlayer()->GetOriginalGroup(); + if (!group) + { + group = _player->GetGroup(); + if (!group || group->isBGGroup()) + return; + } + + if ((type == CHAT_MSG_PARTY_LEADER) && !group->IsLeader(_player->GetGUID())) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, type, lang, NULL, 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetGUID())); + + if (sWorld.getConfig(CONFIG_CHATLOG_PARTY)) + sLog.outChat("[PARTY] Player %s tells group with leader %s: %s", + GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); + } break; + + case CHAT_MSG_GUILD: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + if (GetPlayer()->GetGuildId()) + { + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + + if (guild) + guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); + + if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHATLOG_GUILD)) + { + sLog.outChat("[GUILD] Player %s tells guild %s: %s", + GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); + } + else if (lang == LANG_ADDON && sWorld.getConfig(CONFIG_CHATLOG_ADDON)) + { + sLog.outChat("[ADDON] Player %s sends to guild %s: %s", + GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); + } + } + + break; + } + case CHAT_MSG_OFFICER: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + if (GetPlayer()->GetGuildId()) + { + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + + if (guild) + guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); + + if (sWorld.getConfig(CONFIG_CHATLOG_GUILD)) + sLog.outChat("[OFFICER] Player %s tells guild %s officers: %s", + GetPlayer()->GetName(), guild->GetName().c_str(), msg.c_str()); + } + break; + } + case CHAT_MSG_RAID: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + // if player is in battleground, he cannot say to battleground members by /ra + Group *group = GetPlayer()->GetOriginalGroup(); + if (!group) + { + group = GetPlayer()->GetGroup(); + if (!group || group->isBGGroup() || !group->isRaidGroup()) + return; + } + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) + sLog.outChat("[RAID] Player %s tells raid with leader %s: %s", + GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); + } break; + case CHAT_MSG_RAID_LEADER: + { + std::string msg; + recv_data >> msg; + + if (msg.empty()) + break; + + if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) + break; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + // if player is in battleground, he cannot say to battleground members by /ra + Group *group = GetPlayer()->GetOriginalGroup(); + if (!group) + { + group = GetPlayer()->GetGroup(); + if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetGUID())) + return; + } + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) + sLog.outChat("[RAID] Leader player %s tells raid: %s", + GetPlayer()->GetName(), msg.c_str()); + } break; + case CHAT_MSG_RAID_WARNING: + { + std::string msg; + recv_data >> msg; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + Group *group = GetPlayer()->GetGroup(); + if (!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID())) || group->isBGGroup()) + return; + + WorldPacket data; + //in battleground, raid warning is sent only to players in battleground - code is ok + ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_RAID)) + sLog.outChat("[RAID] Leader player %s warns raid with: %s", + GetPlayer()->GetName(), msg.c_str()); + } break; + + case CHAT_MSG_BATTLEGROUND: + { + std::string msg; + recv_data >> msg; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + //battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() + Group *group = GetPlayer()->GetGroup(); + if (!group || !group->isBGGroup()) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_BGROUND)) + sLog.outChat("[BATTLEGROUND] Player %s tells battleground with leader %s: %s", + GetPlayer()->GetName(), group->GetLeaderName(), msg.c_str()); + } break; + + case CHAT_MSG_BATTLEGROUND_LEADER: + { + std::string msg; + recv_data >> msg; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (msg.empty()) + break; + + // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() + Group *group = GetPlayer()->GetGroup(); + if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID())) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(), NULL); + group->BroadcastPacket(&data, false); + + if (sWorld.getConfig(CONFIG_CHATLOG_BGROUND)) + sLog.outChat("[RAID] Leader player %s tells battleground: %s", + GetPlayer()->GetName(), msg.c_str()); + } break; + + case CHAT_MSG_CHANNEL: + { + std::string channel, msg; + recv_data >> channel; + recv_data >> msg; + + if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) + return; + + if (_player->getLevel() < sWorld.getConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_CHANNEL_REQ), sWorld.getConfig(CONFIG_CHAT_CHANNEL_LEVEL_REQ)); + return; + } + + if (msg.empty()) + break; + + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) + { + + if (Channel *chn = cMgr->GetChannel(channel, _player)) + { + chn->Say(_player->GetGUID(), msg.c_str(), lang); + + if ((chn->HasFlag(CHANNEL_FLAG_TRADE) || + chn->HasFlag(CHANNEL_FLAG_GENERAL) || + chn->HasFlag(CHANNEL_FLAG_CITY) || + chn->HasFlag(CHANNEL_FLAG_LFG)) && + sWorld.getConfig(CONFIG_CHATLOG_SYSCHAN)) + sLog.outChat("[SYSCHAN] Player %s tells channel %s: %s", + GetPlayer()->GetName(), chn->GetName().c_str(), msg.c_str()); + else if (sWorld.getConfig(CONFIG_CHATLOG_CHANNEL)) + sLog.outChat("[CHANNEL] Player %s tells channel %s: %s", + GetPlayer()->GetName(), chn->GetName().c_str(), msg.c_str()); + } + } + } break; + + case CHAT_MSG_AFK: + { + std::string msg; + recv_data >> msg; + + if ((msg.empty() || !_player->isAFK()) && !_player->isInCombat()) + { + if (!_player->isAFK()) + { + if (msg.empty()) + msg = GetTrinityString(LANG_PLAYER_AFK_DEFAULT); + _player->afkMsg = msg; + } + _player->ToggleAFK(); + if (_player->isAFK() && _player->isDND()) + _player->ToggleDND(); + } + } break; + + case CHAT_MSG_DND: + { + std::string msg; + recv_data >> msg; + + if (msg.empty() || !_player->isDND()) + { + if (!_player->isDND()) + { + if (msg.empty()) + msg = GetTrinityString(LANG_PLAYER_DND_DEFAULT); + _player->dndMsg = msg; + } + _player->ToggleDND(); + if (_player->isDND() && _player->isAFK()) + _player->ToggleAFK(); + } + } break; + + default: + sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang); + break; + } +} + +void WorldSession::HandleEmoteOpcode(WorldPacket & recv_data) +{ + if (!GetPlayer()->isAlive()) + return; + + uint32 emote; + recv_data >> emote; + GetPlayer()->HandleEmoteCommand(emote); +} + +namespace Trinity +{ + class EmoteChatBuilder + { + public: + EmoteChatBuilder(Player const& pl, uint32 text_emote, uint32 emote_num, Unit const* target) + : i_player(pl), i_text_emote(text_emote), i_emote_num(emote_num), i_target(target) {} + + void operator()(WorldPacket& data, int32 loc_idx) + { + char const* nam = i_target ? i_target->GetNameForLocaleIdx(loc_idx) : NULL; + uint32 namlen = (nam ? strlen(nam) : 0) + 1; + + data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); + data << i_player.GetGUID(); + data << (uint32)i_text_emote; + data << i_emote_num; + data << (uint32)namlen; + if (namlen > 1) + data.append(nam, namlen); + else + data << (uint8)0x00; + } + + private: + Player const& i_player; + uint32 i_text_emote; + uint32 i_emote_num; + Unit const* i_target; + }; +} // namespace Trinity + +void WorldSession::HandleTextEmoteOpcode(WorldPacket & recv_data) +{ + if (!GetPlayer()->isAlive()) + return; + + if (!GetPlayer()->CanSpeak()) + { + std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); + SendNotification(GetTrinityString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); + return; + } + + uint32 text_emote, emoteNum; + uint64 guid; + + recv_data >> text_emote; + recv_data >> emoteNum; + recv_data >> guid; + + EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); + if (!em) + return; + + uint32 emote_anim = em->textid; + + switch(emote_anim) + { + case EMOTE_STATE_SLEEP: + case EMOTE_STATE_SIT: + case EMOTE_STATE_KNEEL: + case EMOTE_ONESHOT_NONE: + break; + default: + GetPlayer()->HandleEmoteCommand(emote_anim); + break; + } + + Unit* unit = ObjectAccessor::GetUnit(*_player, guid); + + CellPair p = Trinity::ComputeCellPair(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); + + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit); + Trinity::LocalizedPacketDo emote_do(emote_builder); + Trinity::PlayerDistWorker > emote_worker(GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), emote_do); + TypeContainerVisitor >, WorldTypeMapContainer> message(emote_worker); + cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); + + //Send scripted event call + if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI()) + ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote); +} + +void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data) +{ + uint64 iguid; + uint8 unk; + //sLog.outDebug("WORLD: Received CMSG_CHAT_IGNORED"); + + recv_data >> iguid; + recv_data >> unk; // probably related to spam reporting + + Player *player = objmgr.GetPlayer(iguid); + if (!player || !player->GetSession()) + return; + + WorldPacket data; + ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), GetPlayer()->GetName(), NULL); + player->GetSession()->SendPacket(&data); +} + +void WorldSession::HandleChannelDeclineInvite(WorldPacket &recvPacket) +{ + sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); +} + +void WorldSession::SendPlayerNotFoundNotice(std::string name) +{ + WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, name.size()+1); + data << name; + SendPacket(&data); +} + +void WorldSession::SendPlayerAmbiguousNotice(std::string name) +{ + WorldPacket data(SMSG_CHAT_PLAYER_AMBIGUOUS, name.size()+1); + data << name; + SendPacket(&data); +} + +void WorldSession::SendWrongFactionNotice() +{ + WorldPacket data(SMSG_CHAT_WRONG_FACTION, 0); + SendPacket(&data); +} + +void WorldSession::SendChatRestrictedNotice(ChatRestrictionType restriction) +{ + WorldPacket data(SMSG_CHAT_RESTRICTED, 1); + data << uint8(restriction); + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp b/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp new file mode 100644 index 00000000000..404b70c1c84 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/CombatHandler.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "ObjectAccessor.h" +#include "CreatureAI.h" +#include "ObjectDefines.h" + +void WorldSession::HandleAttackSwingOpcode(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + + DEBUG_LOG("WORLD: Recvd CMSG_ATTACKSWING Message guidlow:%u guidhigh:%u", GUID_LOPART(guid), GUID_HIPART(guid)); + + Unit *pEnemy = ObjectAccessor::GetUnit(*_player, guid); + + if (!pEnemy) + { + if (!IS_UNIT_GUID(guid)) + sLog.outError("WORLD: Object %u (TypeID: %u) isn't player, pet or creature",GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); + else + sLog.outError("WORLD: Enemy %s %u not found",GetLogNameForGuid(guid),GUID_LOPART(guid)); + + // stop attack state at client + SendAttackStop(NULL); + return; + } + + if (!_player->canAttack(pEnemy)) + { + sLog.outError("WORLD: Enemy %s %u is friendly",(IS_PLAYER_GUID(guid) ? "player" : "creature"),GUID_LOPART(guid)); + + // stop attack state at client + SendAttackStop(pEnemy); + return; + } + + _player->Attack(pEnemy,true); +} + +void WorldSession::HandleAttackStopOpcode(WorldPacket & /*recv_data*/) +{ + GetPlayer()->AttackStop(); +} + +void WorldSession::HandleSetSheathedOpcode(WorldPacket & recv_data) +{ + uint32 sheathed; + recv_data >> sheathed; + + //sLog.outDebug("WORLD: Recvd CMSG_SETSHEATHED Message guidlow:%u value1:%u", GetPlayer()->GetGUIDLow(), sheathed); + + if (sheathed >= MAX_SHEATH_STATE) + { + sLog.outError("Unknown sheath state %u ??",sheathed); + return; + } + + GetPlayer()->SetSheath(SheathState(sheathed)); +} + +void WorldSession::SendAttackStop(Unit const* enemy) +{ + WorldPacket data(SMSG_ATTACKSTOP, (4+20)); // we guess size + data.append(GetPlayer()->GetPackGUID()); + data.append(enemy ? enemy->GetPackGUID() : 0); // must be packed guid + data << uint32(0); // unk, can be 1 also + SendPacket(&data); +} + diff --git a/src/server/game/Server/Protocol/Handlers/DuelHandler.cpp b/src/server/game/Server/Protocol/Handlers/DuelHandler.cpp new file mode 100644 index 00000000000..99c8a774b03 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/DuelHandler.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Log.h" +#include "Opcodes.h" +#include "UpdateData.h" +#include "Player.h" + +void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket) +{ + uint64 guid; + Player *pl; + Player *plTarget; + + if (!GetPlayer()->duel) // ignore accept from duel-sender + return; + + recvPacket >> guid; + + pl = GetPlayer(); + plTarget = pl->duel->opponent; + + if (pl == pl->duel->initiator || !plTarget || pl == plTarget || pl->duel->startTime != 0 || plTarget->duel->startTime != 0) + return; + + //sLog.outDebug("WORLD: received CMSG_DUEL_ACCEPTED"); + DEBUG_LOG("Player 1 is: %u (%s)", pl->GetGUIDLow(),pl->GetName()); + DEBUG_LOG("Player 2 is: %u (%s)", plTarget->GetGUIDLow(),plTarget->GetName()); + + time_t now = time(NULL); + pl->duel->startTimer = now; + plTarget->duel->startTimer = now; + + pl->SendDuelCountdown(3000); + plTarget->SendDuelCountdown(3000); +} + +void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket) +{ + //sLog.outDebug("WORLD: received CMSG_DUEL_CANCELLED"); + + // no duel requested + if (!GetPlayer()->duel) + return; + + // player surrendered in a duel using /forfeit + if (GetPlayer()->duel->startTime != 0) + { + GetPlayer()->CombatStopWithPets(true); + if (GetPlayer()->duel->opponent) + GetPlayer()->duel->opponent->CombatStopWithPets(true); + + GetPlayer()->CastSpell(GetPlayer(), 7267, true); // beg + GetPlayer()->DuelComplete(DUEL_WON); + return; + } + + // player either discarded the duel using the "discard button" + // or used "/forfeit" before countdown reached 0 + uint64 guid; + recvPacket >> guid; + + GetPlayer()->DuelComplete(DUEL_INTERUPTED); +} diff --git a/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp b/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp new file mode 100644 index 00000000000..f973bc24722 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/GroupHandler.cpp @@ -0,0 +1,940 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Opcodes.h" +#include "Log.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Group.h" +#include "SocialMgr.h" +#include "Util.h" +#include "SpellAuras.h" +#include "Vehicle.h" +#include "LFG.h" + +class Aura; + +/* differeces from off: + -you can uninvite yourself - is is useful + -you can accept invitation even if leader went offline +*/ +/* todo: + -group_destroyed msg is sent but not shown + -reduce xp gaining when in raid group + -quest sharing has to be corrected + -FIX sending PartyMemberStats +*/ + +void WorldSession::SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res) +{ + WorldPacket data(SMSG_PARTY_COMMAND_RESULT, (4+member.size()+1+4+4)); + data << (uint32)operation; + data << member; + data << (uint32)res; + data << uint32(0); // LFD cooldown related (used with ERR_PARTY_LFG_BOOT_COOLDOWN_S and ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S) + + SendPacket(&data); +} + +void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) +{ + std::string membername; + recv_data >> membername; + + // attempt add selected player + + // cheating + if (!normalizePlayerName(membername)) + { + SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); + return; + } + + Player *player = objmgr.GetPlayer(membername.c_str()); + + // no player + if (!player) + { + SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); + return; + } + + // restrict invite to GMs + if (!sWorld.getConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->isGameMaster() && player->isGameMaster()) + return; + + // can't group with + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) + { + SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION); + return; + } + if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) + { + SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S); + return; + } + // just ignore us + if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty()) + { + SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); + return; + } + + if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + { + SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); + return; + } + + Group *group = GetPlayer()->GetGroup(); + if (group && group->isBGGroup()) + group = GetPlayer()->GetOriginalGroup(); + + Group *group2 = player->GetGroup(); + if (group2 && group2->isBGGroup()) + group2 = player->GetOriginalGroup(); + // player already in another group or invited + if (group2 || player->GetGroupInvite()) + { + SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S); + return; + } + + if (group) + { + // not have permissions for invite + if (group->isRaidGroup() && !group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + { + SendPartyResult(PARTY_OP_INVITE, "", ERR_NOT_LEADER); + return; + } + // not have place + if (group->IsFull()) + { + SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); + return; + } + } + + // ok, but group not exist, start a new group + // but don't create and save the group to the DB until + // at least one person joins + if (!group) + { + group = new Group; + // new group: if can't add then delete + if (!group->AddLeaderInvite(GetPlayer())) + { + delete group; + return; + } + if (!group->AddInvite(player)) + { + delete group; + return; + } + } + else + { + // already existed group: if can't add then just leave + if (!group->AddInvite(player)) + { + return; + } + } + + // ok, we do it + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << uint8(1); // invited/already in group flag + data << GetPlayer()->GetName(); // max len 48 + data << uint32(0); // unk + data << uint8(0); // count + //for (int i = 0; i < count; ++i) + // data << uint32(0); + data << uint32(0); // unk + player->GetSession()->SendPacket(&data); + + SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); + SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); + SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK); +} + +void WorldSession::HandleGroupAcceptOpcode(WorldPacket & /*recv_data*/) +{ + Group *group = GetPlayer()->GetGroupInvite(); + if (!group) return; + + if (group->GetLeaderGUID() == GetPlayer()->GetGUID()) + { + sLog.outError("HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); + return; + } + + // remove in from ivites in any case + group->RemoveInvite(GetPlayer()); + + /** error handling **/ + /********************/ + + // not have place + if (group->IsFull()) + { + SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL); + return; + } + + Player* leader = objmgr.GetPlayer(group->GetLeaderGUID()); + + // forming a new group, create it + if (!group->IsCreated()) + { + if (leader) + group->RemoveInvite(leader); + group->Create(group->GetLeaderGUID(), group->GetLeaderName()); + objmgr.AddGroup(group); + } + + // everything's fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!! + if (!group->AddMember(GetPlayer()->GetGUID(), GetPlayer()->GetName())) + return; + + SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); + for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + if (Player *plrg = itr->getSource()) + { + plrg->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_CLEAR_LOCK_LIST); + plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_CLEAR_LOCK_LIST); + } + + group->BroadcastGroupUpdate(); +} + +void WorldSession::HandleGroupDeclineOpcode(WorldPacket & /*recv_data*/) +{ + Group *group = GetPlayer()->GetGroupInvite(); + if (!group) return; + + // remember leader if online + Player *leader = objmgr.GetPlayer(group->GetLeaderGUID()); + + // uninvite, group can be deleted + GetPlayer()->UninviteFromGroup(); + + if (!leader || !leader->GetSession()) + return; + + // report + WorldPacket data(SMSG_GROUP_DECLINE, 10); // guess size + data << GetPlayer()->GetName(); + leader->GetSession()->SendPacket(&data); +} + +void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + recv_data.read_skip(); // reason + + //can't uninvite yourself + if (guid == GetPlayer()->GetGUID()) + { + sLog.outError("WorldSession::HandleGroupUninviteGuidOpcode: leader %s(%d) tried to uninvite himself from the group.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); + return; + } + + PartyResult res = GetPlayer()->CanUninviteFromGroup(); + if (res != ERR_PARTY_RESULT_OK) + { + SendPartyResult(PARTY_OP_UNINVITE, "", res); + return; + } + + Group* grp = GetPlayer()->GetGroup(); + if (!grp) + return; + + if (grp->IsMember(guid)) + { + Player::RemoveFromGroup(grp,guid); + return; + } + + if (Player* plr = grp->GetInvited(guid)) + { + plr->UninviteFromGroup(); + return; + } + + SendPartyResult(PARTY_OP_UNINVITE, "", ERR_TARGET_NOT_IN_GROUP_S); +} + +void WorldSession::HandleGroupUninviteOpcode(WorldPacket & recv_data) +{ + std::string membername; + recv_data >> membername; + + // player not found + if (!normalizePlayerName(membername)) + return; + + // can't uninvite yourself + if (GetPlayer()->GetName() == membername) + { + sLog.outError("WorldSession::HandleGroupUninviteOpcode: leader %s(%d) tried to uninvite himself from the group.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); + return; + } + + PartyResult res = GetPlayer()->CanUninviteFromGroup(); + if (res != ERR_PARTY_RESULT_OK) + { + SendPartyResult(PARTY_OP_UNINVITE, "", res); + return; + } + + Group* grp = GetPlayer()->GetGroup(); + if (!grp) + return; + + if (uint64 guid = grp->GetMemberGUID(membername)) + { + Player::RemoveFromGroup(grp,guid); + return; + } + + if (Player* plr = grp->GetInvited(membername)) + { + plr->UninviteFromGroup(); + return; + } + + SendPartyResult(PARTY_OP_UNINVITE, membername, ERR_TARGET_NOT_IN_GROUP_S); +} + +void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket & recv_data) +{ + Group *group = GetPlayer()->GetGroup(); + if (!group) + return; + + uint64 guid; + recv_data >> guid; + + Player *player = objmgr.GetPlayer(guid); + + /** error handling **/ + if (!player || !group->IsLeader(GetPlayer()->GetGUID()) || player->GetGroup() != group) + return; + /********************/ + + // everything's fine, do it + group->ChangeLeader(guid); +} + +void WorldSession::HandleGroupDisbandOpcode(WorldPacket & /*recv_data*/) +{ + if (!GetPlayer()->GetGroup()) + return; + + if (_player->InBattleGround()) + { + SendPartyResult(PARTY_OP_INVITE, "", ERR_INVITE_RESTRICTED); + return; + } + + /** error handling **/ + /********************/ + + // everything's fine, do it + SendPartyResult(PARTY_OP_LEAVE, GetPlayer()->GetName(), ERR_PARTY_RESULT_OK); + + GetPlayer()->RemoveFromGroup(); +} + +void WorldSession::HandleLootMethodOpcode(WorldPacket & recv_data) +{ + Group *group = GetPlayer()->GetGroup(); + if (!group) + return; + + uint32 lootMethod; + uint64 lootMaster; + uint32 lootThreshold; + recv_data >> lootMethod >> lootMaster >> lootThreshold; + + /** error handling **/ + if (!group->IsLeader(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + group->SetLootMethod((LootMethod)lootMethod); + group->SetLooterGuid(lootMaster); + group->SetLootThreshold((ItemQualities)lootThreshold); + group->SendUpdate(); +} + +void WorldSession::HandleLootRoll(WorldPacket &recv_data) +{ + if (!GetPlayer()->GetGroup()) + return; + + uint64 Guid; + uint32 NumberOfPlayers; + uint8 rollType; + recv_data >> Guid; //guid of the item rolled + recv_data >> NumberOfPlayers; + recv_data >> rollType; //0: pass, 1: need, 2: greed + + //sLog.outDebug("WORLD RECIEVE CMSG_LOOT_ROLL, From:%u, Numberofplayers:%u, Choise:%u", (uint32)Guid, NumberOfPlayers, Choise); + + Group* group = GetPlayer()->GetGroup(); + if (!group) + return; + + // everything's fine, do it + group->CountRollVote(GetPlayer()->GetGUID(), Guid, NumberOfPlayers, rollType); + + switch (rollType) + { + case ROLL_NEED: + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1); + break; + case ROLL_GREED: + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1); + break; + } +} + +void WorldSession::HandleMinimapPingOpcode(WorldPacket& recv_data) +{ + if (!GetPlayer()->GetGroup()) + return; + + float x, y; + recv_data >> x; + recv_data >> y; + + //sLog.outDebug("Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y); + + /** error handling **/ + /********************/ + + // everything's fine, do it + WorldPacket data(MSG_MINIMAP_PING, (8+4+4)); + data << uint64(GetPlayer()->GetGUID()); + data << float(x); + data << float(y); + GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID()); +} + +void WorldSession::HandleRandomRollOpcode(WorldPacket& recv_data) +{ + uint32 minimum, maximum, roll; + recv_data >> minimum; + recv_data >> maximum; + + /** error handling **/ + if (minimum > maximum || maximum > 10000) // < 32768 for urand call + return; + /********************/ + + // everything's fine, do it + roll = urand(minimum, maximum); + + //sLog.outDebug("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll); + + WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8); + data << uint32(minimum); + data << uint32(maximum); + data << uint32(roll); + data << uint64(GetPlayer()->GetGUID()); + if (GetPlayer()->GetGroup()) + GetPlayer()->GetGroup()->BroadcastPacket(&data, false); + else + SendPacket(&data); +} + +void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket & recv_data) +{ + Group *group = GetPlayer()->GetGroup(); + if (!group) + return; + + uint8 x; + recv_data >> x; + + /** error handling **/ + /********************/ + + // everything's fine, do it + if (x == 0xFF) // target icon request + { + group->SendTargetIconList(this); + } + else // target icon update + { + if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + return; + + uint64 guid; + recv_data >> guid; + group->SetTargetIcon(x, _player->GetGUID(), guid); + } +} + +void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recv_data*/) +{ + Group *group = GetPlayer()->GetGroup(); + if (!group) + return; + + if (_player->InBattleGround()) + return; + + /** error handling **/ + if (!group->IsLeader(GetPlayer()->GetGUID()) || group->GetMembersCount() < 2) + return; + /********************/ + + // everything's fine, do it (is it 0 (PARTY_OP_INVITE) correct code) + SendPartyResult(PARTY_OP_INVITE, "", ERR_PARTY_RESULT_OK); + group->ConvertToRaid(); +} + +void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket & recv_data) +{ + // we will get correct pointer for group here, so we don't have to check if group is BG raid + Group *group = GetPlayer()->GetGroup(); + if (!group) + return; + + std::string name; + uint8 groupNr; + recv_data >> name; + + recv_data >> groupNr; + + /** error handling **/ + uint64 senderGuid = GetPlayer()->GetGUID(); + if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid)) + return; + + if (!group->HasFreeSlotSubGroup(groupNr)) + return; + /********************/ + + Player *movedPlayer=objmgr.GetPlayer(name.c_str()); + if (!movedPlayer) + return; + + //Do not allow leader to change group of player in combat + if (movedPlayer->isInCombat()) + return; + + // everything's fine, do it + group->ChangeMembersGroup(movedPlayer, groupNr); +} + +void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket & recv_data) +{ + Group *group = GetPlayer()->GetGroup(); + if (!group) + return; + + uint64 guid; + uint8 flag; + recv_data >> guid; + recv_data >> flag; + + /** error handling **/ + if (!group->IsLeader(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + group->SetAssistant(guid, (flag != 0)); +} + +void WorldSession::HandlePartyAssignmentOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("MSG_PARTY_ASSIGNMENT"); + + Group *group = GetPlayer()->GetGroup(); + if (!group) + return; + + uint8 flag, apply; + uint64 guid; + recv_data >> flag >> apply; + recv_data >> guid; + + /** error handling **/ + uint64 senderGuid = GetPlayer()->GetGUID(); + if (!group->IsLeader(senderGuid) && group->IsAssistant(senderGuid)) + return; + /********************/ + + // everything's fine, do it + if (flag == 0) + group->SetMainTank(guid, apply); + + else if (flag == 1) + group->SetMainAssistant(guid, apply); +} + +void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket & recv_data) +{ + Group *group = GetPlayer()->GetGroup(); + if (!group) + return; + + if (recv_data.empty()) // request + { + /** error handling **/ + if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + return; + /********************/ + + // everything's fine, do it + WorldPacket data(MSG_RAID_READY_CHECK, 8); + data << GetPlayer()->GetGUID(); + group->BroadcastPacket(&data, false, -1); + + group->OfflineReadyCheck(); + } + else // answer + { + uint8 state; + recv_data >> state; + + // everything's fine, do it + WorldPacket data(MSG_RAID_READY_CHECK_CONFIRM, 9); + data << uint64(GetPlayer()->GetGUID()); + data << uint8(state); + group->BroadcastReadyCheck(&data); + } +} + +void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket & /*recv_data*/) +{ + //Group* group = GetPlayer()->GetGroup(); + //if (!group) + // return; + + //if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID())) + // return; + + // Is any reaction need? +} + +void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data) +{ + uint32 mask = player->GetGroupUpdateFlag(); + + if (mask == GROUP_UPDATE_FLAG_NONE) + return; + + if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also + mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); + + if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets + mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); + + uint32 byteCount = 0; + for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) + if (mask & (1 << i)) + byteCount += GroupUpdateLength[i]; + + data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); + data->append(player->GetPackGUID()); + *data << (uint32) mask; + + if (mask & GROUP_UPDATE_FLAG_STATUS) + { + if (player) + { + if (player->IsPvP()) + *data << (uint16) (MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); + else + *data << (uint16) MEMBER_STATUS_ONLINE; + } + else + *data << (uint16) MEMBER_STATUS_OFFLINE; + } + + if (mask & GROUP_UPDATE_FLAG_CUR_HP) + *data << (uint32) player->GetHealth(); + + if (mask & GROUP_UPDATE_FLAG_MAX_HP) + *data << (uint32) player->GetMaxHealth(); + + Powers powerType = player->getPowerType(); + if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) + *data << (uint8) powerType; + + if (mask & GROUP_UPDATE_FLAG_CUR_POWER) + *data << (uint16) player->GetPower(powerType); + + if (mask & GROUP_UPDATE_FLAG_MAX_POWER) + *data << (uint16) player->GetMaxPower(powerType); + + if (mask & GROUP_UPDATE_FLAG_LEVEL) + *data << (uint16) player->getLevel(); + + if (mask & GROUP_UPDATE_FLAG_ZONE) + *data << (uint16) player->GetZoneId(); + + if (mask & GROUP_UPDATE_FLAG_POSITION) + *data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY(); + + if (mask & GROUP_UPDATE_FLAG_AURAS) + { + const uint64& auramask = player->GetAuraUpdateMaskForRaid(); + *data << uint64(auramask); + for (uint32 i = 0; i < MAX_AURAS; ++i) + { + if (auramask & (uint64(1) << i)) + { + AuraApplication const * aurApp = player->GetVisibleAura(i); + *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); + *data << uint8(1); + } + } + } + + Pet *pet = player->GetPet(); + if (mask & GROUP_UPDATE_FLAG_PET_GUID) + { + if (pet) + *data << (uint64) pet->GetGUID(); + else + *data << (uint64) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_NAME) + { + if (pet) + *data << pet->GetName(); + else + *data << (uint8) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) + { + if (pet) + *data << (uint16) pet->GetDisplayId(); + else + *data << (uint16) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) + { + if (pet) + *data << (uint32) pet->GetHealth(); + else + *data << (uint32) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) + { + if (pet) + *data << (uint32) pet->GetMaxHealth(); + else + *data << (uint32) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) + { + if (pet) + *data << (uint8) pet->getPowerType(); + else + *data << (uint8) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) + { + if (pet) + *data << (uint16) pet->GetPower(pet->getPowerType()); + else + *data << (uint16) 0; + } + + if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) + { + if (pet) + *data << (uint16) pet->GetMaxPower(pet->getPowerType()); + else + *data << (uint16) 0; + } + + if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) + { + if (player->GetVehicle()){ + Vehicle* vv=player->GetVehicle(); + *data << (uint32) vv->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]; + } + } + + if (mask & GROUP_UPDATE_FLAG_PET_AURAS) + { + if (pet) + { + const uint64& auramask = pet->GetAuraUpdateMaskForRaid(); + *data << uint64(auramask); + for (uint32 i = 0; i < MAX_AURAS; ++i) + { + if (auramask & (uint64(1) << i)) + { + AuraApplication const * aurApp = player->GetVisibleAura(i); + *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); + *data << uint8(1); + } + } + } + else + *data << (uint64) 0; + } +} + +/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ +void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); + uint64 Guid; + recv_data >> Guid; + + Player *player = objmgr.GetPlayer(Guid); + if (!player) + { + WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); + data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related + data.appendPackGUID(Guid); + data << (uint32) GROUP_UPDATE_FLAG_STATUS; + data << (uint16) MEMBER_STATUS_OFFLINE; + SendPacket(&data); + return; + } + + Pet *pet = player->GetPet(); + + WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); + data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related + data.append(player->GetPackGUID()); + + uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF + if (pet) + mask1 = 0x7FFFFFFF; // for hunters and other classes with pets + + Powers powerType = player->getPowerType(); + data << (uint32) mask1; // group update mask + data << (uint16) MEMBER_STATUS_ONLINE; // member's online status + data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP + data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP + data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE + data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER + data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER + data << (uint16) player->getLevel(); // GROUP_UPDATE_FLAG_LEVEL + data << (uint16) player->GetZoneId(); // GROUP_UPDATE_FLAG_ZONE + data << (uint16) player->GetPositionX(); // GROUP_UPDATE_FLAG_POSITION + data << (uint16) player->GetPositionY(); // GROUP_UPDATE_FLAG_POSITION + + uint64 auramask = 0; + size_t maskPos = data.wpos(); + data << (uint64) auramask; // placeholder + for (uint8 i = 0; i < MAX_AURAS; ++i) + { + if (AuraApplication * aurApp = player->GetVisibleAura(i)) + { + auramask |= (uint64(1) << i); + data << (uint32) aurApp->GetBase()->GetId(); + data << (uint8) 1; + } + } + data.put(maskPos,auramask); // GROUP_UPDATE_FLAG_AURAS + + if (pet) + { + Powers petpowertype = pet->getPowerType(); + data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID + data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME + data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID + data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP + data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP + data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE + data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER + data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER + + uint64 petauramask = 0; + size_t petMaskPos = data.wpos(); + data << (uint64) petauramask; // placeholder + for (uint8 i = 0; i < MAX_AURAS; ++i) + { + if (AuraApplication * auraApp = pet->GetVisibleAura(i)) + { + petauramask |= (uint64(1) << i); + data << (uint32) auraApp->GetBase()->GetId(); + data << (uint8) 1; + } + } + data.put(petMaskPos,petauramask); // GROUP_UPDATE_FLAG_PET_AURAS + } + else + { + data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_NAME + data << (uint64) 0; // GROUP_UPDATE_FLAG_PET_AURAS + } + + SendPacket(&data); +} + +/*!*/void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket & /*recv_data*/) +{ + // every time the player checks the character screen + _player->SendRaidInfo(); +} + +/*void WorldSession::HandleGroupCancelOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: got CMSG_GROUP_CANCEL."); +}*/ + +void WorldSession::HandleOptOutOfLootOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_OPT_OUT_OF_LOOT"); + + uint32 passOnLoot; + recv_data >> passOnLoot; // 1 always pass, 0 do not pass + + // ignore if player not loaded + if (!GetPlayer()) // needed because STATUS_AUTHED + { + if (passOnLoot != 0) + sLog.outError("CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!"); + return; + } + + GetPlayer()->SetPassOnGroupLoot(passOnLoot); +} diff --git a/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp b/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp new file mode 100644 index 00000000000..6803fe63a86 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp @@ -0,0 +1,1225 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Guild.h" +#include "GossipDef.h" +#include "SocialMgr.h" + +void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_QUERY"); + + uint32 guildId; + recvPacket >> guildId; + + if (Guild *guild = objmgr.GetGuildById(guildId)) + { + guild->Query(this); + return; + } + + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); +} + +void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_CREATE"); + + std::string gname; + recvPacket >> gname; + + if (GetPlayer()->GetGuildId()) // already in guild + return; + + Guild *guild = new Guild; + if (!guild->Create(GetPlayer(), gname)) + { + delete guild; + return; + } + + objmgr.AddGuild(guild); +} + +void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_INVITE"); + + std::string Invitedname, plname; + + Player * player = NULL; + recvPacket >> Invitedname; + + if (normalizePlayerName(Invitedname)) + player = ObjectAccessor::Instance().FindPlayerByName(Invitedname.c_str()); + + if (!player) + { + SendGuildCommandResult(GUILD_INVITE_S, Invitedname, ERR_GUILD_PLAYER_NOT_FOUND_S); + return; + } + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + // OK result but not send invite + if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + return; + + // not let enemies sign guild charter + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam()) + { + SendGuildCommandResult(GUILD_INVITE_S, Invitedname, ERR_GUILD_NOT_ALLIED); + return; + } + + if (player->GetGuildId()) + { + plname = player->GetName(); + SendGuildCommandResult(GUILD_INVITE_S, plname, ERR_ALREADY_IN_GUILD_S); + return; + } + + if (player->GetGuildIdInvited()) + { + plname = player->GetName(); + SendGuildCommandResult(GUILD_INVITE_S, plname, ERR_ALREADY_INVITED_TO_GUILD_S); + return; + } + + if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_INVITE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + sLog.outDebug("Player %s Invited %s to Join his Guild", GetPlayer()->GetName(), Invitedname.c_str()); + + player->SetGuildIdInvited(GetPlayer()->GetGuildId()); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_INVITE_PLAYER, GetPlayer()->GetGUIDLow(), player->GetGUIDLow(), 0); + + WorldPacket data(SMSG_GUILD_INVITE, (8+10)); // guess size + data << GetPlayer()->GetName(); + data << guild->GetName(); + player->GetSession()->SendPacket(&data); + + sLog.outDebug("WORLD: Sent (SMSG_GUILD_INVITE)"); +} + +void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_REMOVE"); + + std::string plName; + recvPacket >> plName; + + if (!normalizePlayerName(plName)) + return; + + Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_REMOVE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + uint64 plGuid; + MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); + if (!slot) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + + if (slot->RankId == GR_GUILDMASTER) + { + SendGuildCommandResult(GUILD_QUIT_S, "", ERR_GUILD_LEADER_LEAVE); + return; + } + + //do not allow to kick player with same or higher rights + if (GetPlayer()->GetRank() >= slot->RankId) + { + SendGuildCommandResult(GUILD_QUIT_S, plName, ERR_GUILD_RANK_TOO_HIGH_S); + return; + } + + guild->DelMember(plGuid); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), 0); + + guild->BroadcastEvent(GE_REMOVED, 0, 2, plName, _player->GetName(), ""); +} + +void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/) +{ + Guild *guild; + Player *player = GetPlayer(); + + sLog.outDebug("WORLD: Received CMSG_GUILD_ACCEPT"); + + guild = objmgr.GetGuildById(player->GetGuildIdInvited()); + if (!guild || player->GetGuildId()) + return; + + // not let enemies sign guild charter + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != objmgr.GetPlayerTeamByGUID(guild->GetLeader())) + return; + + if (!guild->AddMember(GetPlayer()->GetGUID(),guild->GetLowestRank())) + return; + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_JOIN_GUILD, GetPlayer()->GetGUIDLow(), 0, 0); + + guild->BroadcastEvent(GE_JOINED, player->GetGUID(), 1, player->GetName(), "", ""); + + sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); +} + +void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_DECLINE"); + + GetPlayer()->SetGuildIdInvited(0); + GetPlayer()->SetInGuild(0); +} + +void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/) +{ + Guild *guild; + sLog.outDebug("WORLD: Received CMSG_GUILD_INFO"); + + guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + WorldPacket data(SMSG_GUILD_INFO, (guild->GetName().size() + 4 + 4 + 4)); + data << guild->GetName(); + data << secsToTimeBitFields(guild->GetCreatedDate()); // 3.x (prev. year + month + day) + data << guild->GetMemberSize(); // char amount + data << guild->GetMemberSize(); // acc amount + + SendPacket(&data); +} + +void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_ROSTER"); + + if (Guild* guild = objmgr.GetGuildById(_player->GetGuildId())) + guild->Roster(this); +} + +void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_PROMOTE"); + + std::string plName; + recvPacket >> plName; + + if (!normalizePlayerName(plName)) + return; + + Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_PROMOTE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + uint64 plGuid; + MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); + + if (!slot) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + + if (plGuid == GetPlayer()->GetGUID()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_NAME_INVALID); + return; + } + + //allow to promote only to lower rank than member's rank + //guildmaster's rank = 0 + //GetPlayer()->GetRank() + 1 is highest rank that current player can promote to + if (GetPlayer()->GetRank() + 1 >= slot->RankId) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_HIGH_S); + return; + } + + uint32 newRankId = slot->RankId - 1; //when promoting player, rank is decreased + + guild->BroadcastEvent(GE_PROMOTION, 0, 3, _player->GetName(), plName, guild->GetRankName(newRankId)); + + guild->ChangeRank(plGuid, newRankId); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_PROMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId); +} + +void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_DEMOTE"); + + std::string plName; + recvPacket >> plName; + + if (!normalizePlayerName(plName)) + return; + + Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_DEMOTE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + uint64 plGuid; + MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); + + if (!slot) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + + if (plGuid == GetPlayer()->GetGUID()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_NAME_INVALID); + return; + } + + //do not allow to demote same or higher rank + if (GetPlayer()->GetRank() >= slot->RankId) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_HIGH_S); + return; + } + + //do not allow to demote lowest rank + if (slot->RankId >= guild->GetLowestRank()) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_LOW_S); + return; + } + + uint32 newRankId = slot->RankId + 1; //when demoting player, rank is increased + + guild->ChangeRank(plGuid, newRankId); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId); + + guild->BroadcastEvent(GE_DEMOTION, 0, 3, _player->GetName(), plName, guild->GetRankName(slot->RankId)); +} + +void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_LEAVE"); + + Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (_player->GetGUID() == guild->GetLeader() && guild->GetMemberSize() > 1) + { + SendGuildCommandResult(GUILD_QUIT_S, "", ERR_GUILD_LEADER_LEAVE); + return; + } + + if (_player->GetGUID() == guild->GetLeader()) + { + guild->Disband(); + return; + } + + guild->DelMember(_player->GetGUID()); + // Put record into guildlog + guild->LogGuildEvent(GUILD_EVENT_LOG_LEAVE_GUILD, _player->GetGUIDLow(), 0, 0); + + guild->BroadcastEvent(GE_LEFT, _player->GetGUID(), 1, _player->GetName(), "", ""); + + SendGuildCommandResult(GUILD_QUIT_S, guild->GetName(), ERR_PLAYER_NO_MORE_IN_GUILD); +} + +void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_DISBAND"); + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (GetPlayer()->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + guild->Disband(); + + sLog.outDebug("WORLD: Guild Successfully Disbanded"); +} + +void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_LEADER"); + + std::string name; + recvPacket >> name; + + Player *oldLeader = GetPlayer(); + + if (!normalizePlayerName(name)) + return; + + Guild *guild = objmgr.GetGuildById(oldLeader->GetGuildId()); + + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (oldLeader->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + uint64 newLeaderGUID; + MemberSlot* slot = guild->GetMemberSlot(name, newLeaderGUID); + + if (!slot) + { + SendGuildCommandResult(GUILD_INVITE_S, name, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + + guild->SetLeader(newLeaderGUID); + guild->ChangeRank(oldLeader->GetGUID(), GR_OFFICER); + + guild->BroadcastEvent(GE_LEADER_CHANGED, 0, 2, oldLeader->GetName(), name, ""); +} + +void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_MOTD"); + + std::string MOTD; + + if (!recvPacket.empty()) + recvPacket >> MOTD; + else + MOTD = ""; + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_SETMOTD)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + guild->SetMOTD(MOTD); + + guild->BroadcastEvent(GE_MOTD, 0, 1, MOTD, "", ""); +} + +void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_SET_PUBLIC_NOTE"); + + std::string name,PNOTE; + recvPacket >> name; + + if (!normalizePlayerName(name)) + return; + + Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EPNOTE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + uint64 plGuid; + MemberSlot* slot = guild->GetMemberSlot(name, plGuid); + + if (!slot) + { + SendGuildCommandResult(GUILD_INVITE_S, name, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + + recvPacket >> PNOTE; + guild->SetPNOTE(plGuid, PNOTE); + + guild->Roster(this); +} + +void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_SET_OFFICER_NOTE"); + + std::string plName, OFFNOTE; + recvPacket >> plName; + + if (!normalizePlayerName(plName)) + return; + + Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EOFFNOTE)) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + uint64 plGuid; + MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); + + if (!slot) + { + SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S); + return; + } + + recvPacket >> OFFNOTE; + guild->SetOFFNOTE(plGuid, OFFNOTE); + + guild->Roster(this); +} + +void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) +{ + std::string rankname; + uint32 rankId; + uint32 rights, MoneyPerDay; + + sLog.outDebug("WORLD: Received CMSG_GUILD_RANK"); + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + else if (GetPlayer()->GetGUID() != guild->GetLeader()) + { + recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + recvPacket >> rankId; + recvPacket >> rights; + recvPacket >> rankname; + recvPacket >> MoneyPerDay; + + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + uint32 BankRights; + uint32 BankSlotPerDay; + + recvPacket >> BankRights; + recvPacket >> BankSlotPerDay; + guild->SetBankRightsAndSlots(rankId, uint8(i), uint16(BankRights & 0xFF), uint16(BankSlotPerDay), true); + } + + sLog.outDebug("WORLD: Changed RankName to %s , Rights to 0x%.4X", rankname.c_str(), rights); + + guild->SetBankMoneyPerDay(rankId, MoneyPerDay); + guild->SetRankName(rankId, rankname); + + if (rankId == GR_GUILDMASTER) // prevent loss leader rights + rights = GR_RIGHT_ALL; + + guild->SetRankRights(rankId, rights); + + guild->Query(this); + guild->Roster(); // broadcast for tab rights update +} + +void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_ADD_RANK"); + + std::string rankname; + recvPacket >> rankname; + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (GetPlayer()->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + if (guild->GetRanksSize() >= GUILD_RANKS_MAX_COUNT) // client not let create more 10 than ranks + return; + + guild->CreateRank(rankname, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); + + guild->Query(this); + guild->Roster(); // broadcast for tab rights update +} + +void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_DEL_RANK"); + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + else if (GetPlayer()->GetGUID() != guild->GetLeader()) + { + SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + guild->DelRank(); + + guild->Query(this); + guild->Roster(); // broadcast for tab rights update +} + +void WorldSession::SendGuildCommandResult(uint32 typecmd, const std::string& str,uint32 cmdresult) +{ + WorldPacket data(SMSG_GUILD_COMMAND_RESULT, (8+str.size()+1)); + data << typecmd; + data << str; + data << cmdresult; + SendPacket(&data); + + sLog.outDebug("WORLD: Sent (SMSG_GUILD_COMMAND_RESULT)"); +} + +void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received CMSG_GUILD_INFO_TEXT"); + + std::string GINFO; + + recvPacket >> GINFO; + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); + return; + } + + if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_MODIFY_GUILD_INFO)) + { + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PERMISSIONS); + return; + } + + guild->SetGINFO(GINFO); +} + +void WorldSession::HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: Received MSG_SAVE_GUILD_EMBLEM"); + + uint64 vendorGuid; + + uint32 EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor; + + recvPacket >> vendorGuid; + recvPacket >> EmblemStyle >> EmblemColor >> BorderStyle >> BorderColor >> BackgroundColor; + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid,UNIT_NPC_FLAG_TABARDDESIGNER); + if (!pCreature) + { + //"That's not an emblem vendor!" + SendSaveGuildEmblem(ERR_GUILDEMBLEM_INVALIDVENDOR); + sLog.outDebug("WORLD: HandleSaveGuildEmblemOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(vendorGuid)); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); + if (!guild) + { + //"You are not part of a guild!"; + SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOGUILD); + return; + } + + if (guild->GetLeader() != GetPlayer()->GetGUID()) + { + //"Only guild leaders can create emblems." + SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOTGUILDMASTER); + return; + } + + if (GetPlayer()->GetMoney() < 10*GOLD) + { + //"You can't afford to do that." + SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOTENOUGHMONEY); + return; + } + + GetPlayer()->ModifyMoney(-10*GOLD); + guild->SetEmblem(EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor); + + //"Guild Emblem saved." + SendSaveGuildEmblem(ERR_GUILDEMBLEM_SUCCESS); + + guild->Query(this); +} + +void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */) +{ + // empty + sLog.outDebug("WORLD: Received (MSG_GUILD_EVENT_LOG_QUERY)"); + if (uint32 GuildId = GetPlayer()->GetGuildId()) + if (Guild *pGuild = objmgr.GetGuildById(GuildId)) + pGuild->DisplayGuildEventLog(this); +} + +/****** GUILD BANK *******/ + +void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket & /* recv_data */) +{ + sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_MONEY_WITHDRAWN)"); + if (uint32 GuildId = GetPlayer()->GetGuildId()) + if (Guild *pGuild = objmgr.GetGuildById(GuildId)) + pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); +} + +void WorldSession::HandleGuildPermissions(WorldPacket& /* recv_data */) +{ + sLog.outDebug("WORLD: Received (MSG_GUILD_PERMISSIONS)"); + + if (uint32 GuildId = GetPlayer()->GetGuildId()) + { + if (Guild *pGuild = objmgr.GetGuildById(GuildId)) + { + uint32 rankId = GetPlayer()->GetRank(); + + WorldPacket data(MSG_GUILD_PERMISSIONS, 4*15+1); + data << uint32(rankId); // guild rank id + data << uint32(pGuild->GetRankRights(rankId)); // rank rights + // money per day left + data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow())); + data << uint8(pGuild->GetPurchasedTabs()); // tabs count + // why sending all info when not all tabs are purchased??? + for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) + { + data << uint32(pGuild->GetBankRights(rankId, uint8(i))); + data << uint32(pGuild->GetMemberSlotWithdrawRem(GetPlayer()->GetGUIDLow(), uint8(i))); + } + SendPacket(&data); + sLog.outDebug("WORLD: Sent (MSG_GUILD_PERMISSIONS)"); + } + } +} + +/* Called when clicking on Guild bank gameobject */ +void WorldSession::HandleGuildBankerActivate(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANKER_ACTIVATE)"); + + uint64 GoGuid; + uint8 unk; + recv_data >> GoGuid >> unk; + + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + return; + + if (uint32 GuildId = GetPlayer()->GetGuildId()) + { + if (Guild *pGuild = objmgr.GetGuildById(GuildId)) + { + pGuild->DisplayGuildBankTabsInfo(this); // this also will load guild bank if not yet + return; + } + } + + SendGuildCommandResult(GUILD_UNK1, "", ERR_GUILD_PLAYER_NOT_IN_GUILD); +} + +/* Called when opening guild bank tab only (first one) */ +void WorldSession::HandleGuildBankQueryTab(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_QUERY_TAB)"); + + uint64 GoGuid; + uint8 TabId, unk1; + recv_data >> GoGuid >> TabId >> unk1; + + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (!GuildId) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + + if (TabId >= pGuild->GetPurchasedTabs()) + return; + + // Let's update the amount of gold the player can withdraw before displaying the content + // This is useful if money withdraw right has changed + pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); + pGuild->DisplayGuildBankContent(this, TabId); +} + +void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_DEPOSIT_MONEY)"); + + uint64 GoGuid; + uint32 money; + recv_data >> GoGuid >> money; + + if (!money) + return; + + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + return; + + if (GetPlayer()->GetMoney() < money) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (!GuildId) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + + if (!pGuild->GetPurchasedTabs()) + return; + + CharacterDatabase.BeginTransaction(); + + pGuild->SetBankMoney(pGuild->GetGuildBankMoney()+money); + GetPlayer()->ModifyMoney(-int(money)); + GetPlayer()->SaveGoldToDB(); + + CharacterDatabase.CommitTransaction(); + + // logging money + if (_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit money (Amount: %u) to guild bank (Guild ID %u)", + _player->GetName(),_player->GetSession()->GetAccountId(),money,GuildId); + } + + // log + pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); + + pGuild->DisplayGuildBankTabsInfo(this); + pGuild->DisplayGuildBankContent(this, 0); + pGuild->DisplayGuildBankMoneyUpdate(this); +} + +void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_WITHDRAW_MONEY)"); + + uint64 GoGuid; + uint32 money; + recv_data >> GoGuid >> money; + + if (!money) + return; + + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (GuildId == 0) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + + if (!pGuild->GetPurchasedTabs()) + return; + + if (pGuild->GetGuildBankMoney()HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_WITHDRAW_GOLD)) + return; + + CharacterDatabase.BeginTransaction(); + + if (!pGuild->MemberMoneyWithdraw(money, GetPlayer()->GetGUIDLow())) + { + CharacterDatabase.RollbackTransaction(); + return; + } + + GetPlayer()->ModifyMoney(money); + GetPlayer()->SaveGoldToDB(); + + CharacterDatabase.CommitTransaction(); + + // Log + pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); + + pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); + pGuild->DisplayGuildBankTabsInfo(this); + pGuild->DisplayGuildBankContent(this,0); + pGuild->DisplayGuildBankMoneyUpdate(this); +} + +void WorldSession::HandleGuildBankSwapItems(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_SWAP_ITEMS)"); + + uint64 GoGuid; + uint8 BankToBank; + + uint8 BankTab, BankTabSlot, AutoStore; + uint8 PlayerSlot = NULL_SLOT; + uint8 PlayerBag = NULL_BAG; + uint8 BankTabDst = 0, BankTabSlotDst = 0, unk2; + uint8 ToChar = 1; + uint32 ItemEntry, unk1; + uint32 AutoStoreCount = 0; + uint32 SplitedAmount = 0; + + recv_data >> GoGuid >> BankToBank; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (!GuildId) + { + recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet + return; + } + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + { + recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet + return; + } + + if (BankToBank) + { + recv_data >> BankTabDst; + recv_data >> BankTabSlotDst; + recv_data >> unk1; // always 0 + recv_data >> BankTab; + recv_data >> BankTabSlot; + recv_data >> ItemEntry; + recv_data >> unk2; // always 0 + recv_data >> SplitedAmount; + + if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS || + (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) || + BankTab >= pGuild->GetPurchasedTabs() || + BankTabDst >= pGuild->GetPurchasedTabs()) + { + recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet + return; + } + } + else + { + recv_data >> BankTab; + recv_data >> BankTabSlot; + recv_data >> ItemEntry; + recv_data >> AutoStore; + if (AutoStore) + { + recv_data >> AutoStoreCount; + recv_data.read_skip(); // ToChar (?), always and expected to be 1 (autostore only triggered in guild->ToChar) + recv_data.read_skip(); // unknown, always 0 + } + else + { + recv_data >> PlayerBag; + recv_data >> PlayerSlot; + recv_data >> ToChar; + recv_data >> SplitedAmount; + } + + if (BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF || + BankTab >= pGuild->GetPurchasedTabs()) + { + recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet + return; + } + } + + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + return; + + if (BankTab >= pGuild->GetPurchasedTabs()) + return; + + // Bank <-> Bank + if (BankToBank) + { + pGuild->SwapItems(_player, BankTab, BankTabSlot, BankTabDst, BankTabSlotDst, SplitedAmount); + return; + } + + // Player <-> Bank + + // allow work with inventory only + if (!Player::IsInventoryPos(PlayerBag, PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT)) + { + _player->SendEquipError(EQUIP_ERR_NONE, NULL, NULL); + return; + } + + // BankToChar swap or char to bank remaining + if (ToChar) // Bank -> Char cases + pGuild->MoveFromBankToChar(_player, BankTab, BankTabSlot, PlayerBag, PlayerSlot, SplitedAmount); + else // Char -> Bank cases + pGuild->MoveFromCharToBank(_player, PlayerBag, PlayerSlot, BankTab, BankTabSlot, SplitedAmount); +} + +void WorldSession::HandleGuildBankBuyTab(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_BUY_TAB)"); + + uint64 GoGuid; + uint8 TabId; + + recv_data >> GoGuid; + recv_data >> TabId; + + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (!GuildId) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + + // m_PurchasedTabs = 0 when buying Tab 0, that is why this check can be made + if (TabId != pGuild->GetPurchasedTabs()) + return; + + uint32 TabCost = GetGuildBankTabPrice(TabId) * GOLD; + if (!TabCost) + return; + + if (GetPlayer()->GetMoney() < TabCost) // Should not happen, this is checked by client + return; + + // Go on with creating tab + pGuild->CreateNewBankTab(); + GetPlayer()->ModifyMoney(-int(TabCost)); + pGuild->SetBankMoneyPerDay(GetPlayer()->GetRank(), WITHDRAW_MONEY_UNLIMITED); + pGuild->SetBankRightsAndSlots(GetPlayer()->GetRank(), TabId, GUILD_BANK_RIGHT_FULL, WITHDRAW_SLOT_UNLIMITED, true); + pGuild->Roster(); // broadcast for tab rights update + pGuild->DisplayGuildBankTabsInfo(this); +} + +void WorldSession::HandleGuildBankUpdateTab(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_UPDATE_TAB)"); + + uint64 GoGuid; + uint8 TabId; + std::string Name; + std::string IconIndex; + + recv_data >> GoGuid; + recv_data >> TabId; + recv_data >> Name; + recv_data >> IconIndex; + + if (Name.empty()) + return; + + if (IconIndex.empty()) + return; + + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + return; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (!GuildId) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + + if (TabId >= pGuild->GetPurchasedTabs()) + return; + + pGuild->SetGuildBankTabInfo(TabId, Name, IconIndex); + pGuild->DisplayGuildBankTabsInfo(this); + pGuild->DisplayGuildBankContent(this, TabId); +} + +void WorldSession::HandleGuildBankLogQuery(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_LOG_QUERY)"); + + uint8 TabId; + recv_data >> TabId; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (!GuildId) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + + // GUILD_BANK_MAX_TABS send by client for money log + if (TabId >= pGuild->GetPurchasedTabs() && TabId != GUILD_BANK_MAX_TABS) + return; + + pGuild->DisplayGuildBankLogs(this, TabId); +} + +void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Received MSG_QUERY_GUILD_BANK_TEXT"); + + uint8 TabId; + recv_data >> TabId; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (!GuildId) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + + if (TabId >= pGuild->GetPurchasedTabs()) + return; + + pGuild->SendGuildBankTabText(this, TabId); +} + +void WorldSession::HandleSetGuildBankTabText(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_SET_GUILD_BANK_TEXT"); + + uint8 TabId; + std::string Text; + recv_data >> TabId; + recv_data >> Text; + + uint32 GuildId = GetPlayer()->GetGuildId(); + if (!GuildId) + return; + + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + + if (TabId >= pGuild->GetPurchasedTabs()) + return; + + pGuild->SetGuildBankTabText(TabId, Text); +} + +void WorldSession::SendSaveGuildEmblem(uint32 msg) +{ + WorldPacket data(MSG_SAVE_GUILD_EMBLEM, 4); + data << uint32(msg); // not part of guild + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp new file mode 100644 index 00000000000..53aede43492 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp @@ -0,0 +1,1430 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "Item.h" +#include "UpdateData.h" +#include "ObjectAccessor.h" + +void WorldSession::HandleSplitItemOpcode(WorldPacket & recv_data) +{ + //sLog.outDebug("WORLD: CMSG_SPLIT_ITEM"); + uint8 srcbag, srcslot, dstbag, dstslot; + uint32 count; + + recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count; + //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count); + + uint16 src = ((srcbag << 8) | srcslot); + uint16 dst = ((dstbag << 8) | dstslot); + + if (src == dst) + return; + + if (count == 0) + return; //check count - if zero it's fake packet + + if (!_player->IsValidPos(srcbag,srcslot)) + { + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + if (!_player->IsValidPos(dstbag,dstslot)) + { + _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); + return; + } + + _player->SplitItem(src, dst, count); +} + +void WorldSession::HandleSwapInvItemOpcode(WorldPacket & recv_data) +{ + //sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM"); + uint8 srcslot, dstslot; + + recv_data >> dstslot >> srcslot; + //sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot); + + // prevent attempt swap same item to current position generated by client at special checting sequence + if (srcslot == dstslot) + return; + + if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + { + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + { + _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); + return; + } + + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + + _player->SwapItem(src, dst); +} + +void WorldSession::HandleAutoEquipItemSlotOpcode(WorldPacket & recv_data) +{ + uint64 itemguid; + uint8 dstslot; + recv_data >> itemguid >> dstslot; + + // cheating attempt, client should never send opcode in that case + if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, dstslot)) + return; + + Item* item = _player->GetItemByGuid(itemguid); + uint16 dstpos = dstslot | (INVENTORY_SLOT_BAG_0 << 8); + + if (!item || item->GetPos() == dstpos) + return; + + _player->SwapItem(item->GetPos(), dstpos); +} + +void WorldSession::HandleSwapItem(WorldPacket & recv_data) +{ + //sLog.outDebug("WORLD: CMSG_SWAP_ITEM"); + uint8 dstbag, dstslot, srcbag, srcslot; + + recv_data >> dstbag >> dstslot >> srcbag >> srcslot ; + //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot); + + uint16 src = ((srcbag << 8) | srcslot); + uint16 dst = ((dstbag << 8) | dstslot); + + // prevent attempt swap same item to current position generated by client at special checting sequence + if (src == dst) + return; + + if (!_player->IsValidPos(srcbag,srcslot)) + { + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + if (!_player->IsValidPos(dstbag,dstslot)) + { + _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); + return; + } + + _player->SwapItem(src, dst); +} + +void WorldSession::HandleAutoEquipItemOpcode(WorldPacket & recv_data) +{ + //sLog.outDebug("WORLD: CMSG_AUTOEQUIP_ITEM"); + uint8 srcbag, srcslot; + + recv_data >> srcbag >> srcslot; + //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); + + Item *pSrcItem = _player->GetItemByPos(srcbag, srcslot); + if (!pSrcItem) + return; // only at cheat + + uint16 dest; + uint8 msg = _player->CanEquipItem(NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag()); + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, pSrcItem, NULL); + return; + } + + uint16 src = pSrcItem->GetPos(); + if (dest == src) // prevent equip in same slot, only at cheat + return; + + Item *pDstItem = _player->GetItemByPos(dest); + if (!pDstItem) // empty slot, simple case + { + _player->RemoveItem(srcbag, srcslot, true); + _player->EquipItem(dest, pSrcItem, true); + _player->AutoUnequipOffhandIfNeed(); + } + else // have currently equipped item, not simple case + { + uint8 dstbag = pDstItem->GetBagSlot(); + uint8 dstslot = pDstItem->GetSlot(); + + msg = _player->CanUnequipItem(dest, !pSrcItem->IsBag()); + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, pDstItem, NULL); + return; + } + + // check dest->src move possibility + ItemPosCountVec sSrc; + uint16 eSrc = 0; + if (_player->IsInventoryPos(src)) + { + msg = _player->CanStoreItem(srcbag, srcslot, sSrc, pDstItem, true); + if (msg != EQUIP_ERR_OK) + msg = _player->CanStoreItem(srcbag, NULL_SLOT, sSrc, pDstItem, true); + if (msg != EQUIP_ERR_OK) + msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true); + } + else if (_player->IsBankPos(src)) + { + msg = _player->CanBankItem(srcbag, srcslot, sSrc, pDstItem, true); + if (msg != EQUIP_ERR_OK) + msg = _player->CanBankItem(srcbag, NULL_SLOT, sSrc, pDstItem, true); + if (msg != EQUIP_ERR_OK) + msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true); + } + else if (_player->IsEquipmentPos(src)) + { + msg = _player->CanEquipItem(srcslot, eSrc, pDstItem, true); + if (msg == EQUIP_ERR_OK) + msg = _player->CanUnequipItem(eSrc, true); + } + + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, pDstItem, pSrcItem); + return; + } + + // now do moves, remove... + _player->RemoveItem(dstbag, dstslot, false); + _player->RemoveItem(srcbag, srcslot, false); + + // add to dest + _player->EquipItem(dest, pSrcItem, true); + + // add to src + if (_player->IsInventoryPos(src)) + _player->StoreItem(sSrc, pDstItem, true); + else if (_player->IsBankPos(src)) + _player->BankItem(sSrc, pDstItem, true); + else if (_player->IsEquipmentPos(src)) + _player->EquipItem(eSrc, pDstItem, true); + + _player->AutoUnequipOffhandIfNeed(); + } +} + +void WorldSession::HandleDestroyItemOpcode(WorldPacket & recv_data) +{ + //sLog.outDebug("WORLD: CMSG_DESTROYITEM"); + uint8 bag, slot, count, data1, data2, data3; + + recv_data >> bag >> slot >> count >> data1 >> data2 >> data3; + //sLog.outDebug("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count); + + uint16 pos = (bag << 8) | slot; + + // prevent drop unequipable items (in combat, for example) and non-empty bags + if (_player->IsEquipmentPos(pos) || _player->IsBagPos(pos)) + { + uint8 msg = _player->CanUnequipItem(pos, false); + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, _player->GetItemByPos(pos), NULL); + return; + } + } + + Item *pItem = _player->GetItemByPos(bag, slot); + if (!pItem) + { + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + if (count) + { + uint32 i_count = count; + _player->DestroyItemCount(pItem, i_count, true); + } + else + _player->DestroyItem(bag, slot, true); +} + +// Only _static_ data send in this packet !!! +void WorldSession::HandleItemQuerySingleOpcode(WorldPacket & recv_data) +{ + //sLog.outDebug("WORLD: CMSG_ITEM_QUERY_SINGLE"); + uint32 item; + recv_data >> item; + + sLog.outDetail("STORAGE: Item Query = %u", item); + + ItemPrototype const *pProto = objmgr.GetItemPrototype(item); + if (pProto) + { + std::string Name = pProto->Name1; + std::string Description = pProto->Description; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); + if (il) + { + if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty()) + Name = il->Name[loc_idx]; + if (il->Description.size() > size_t(loc_idx) && !il->Description[loc_idx].empty()) + Description = il->Description[loc_idx]; + } + } + // guess size + WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600); + data << pProto->ItemId; + data << pProto->Class; + data << pProto->SubClass; + data << int32(pProto->Unk0); // new 2.0.3, not exist in wdb cache? + data << Name; + data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name... + data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00); + data << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00); + data << pProto->DisplayInfoID; + data << pProto->Quality; + data << pProto->Flags; + data << pProto->Flags2; + data << pProto->BuyPrice; + data << pProto->SellPrice; + data << pProto->InventoryType; + data << pProto->AllowableClass; + data << pProto->AllowableRace; + data << pProto->ItemLevel; + data << pProto->RequiredLevel; + data << pProto->RequiredSkill; + data << pProto->RequiredSkillRank; + data << pProto->RequiredSpell; + data << pProto->RequiredHonorRank; + data << pProto->RequiredCityRank; + data << pProto->RequiredReputationFaction; + data << pProto->RequiredReputationRank; + data << int32(pProto->MaxCount); + data << int32(pProto->Stackable); + data << pProto->ContainerSlots; + data << pProto->StatsCount; // item stats count + for (uint32 i = 0; i < pProto->StatsCount; ++i) + { + data << pProto->ItemStat[i].ItemStatType; + data << pProto->ItemStat[i].ItemStatValue; + } + data << pProto->ScalingStatDistribution; // scaling stats distribution + data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column + for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i) + { + data << pProto->Damage[i].DamageMin; + data << pProto->Damage[i].DamageMax; + data << pProto->Damage[i].DamageType; + } + + // resistances (7) + data << pProto->Armor; + data << pProto->HolyRes; + data << pProto->FireRes; + data << pProto->NatureRes; + data << pProto->FrostRes; + data << pProto->ShadowRes; + data << pProto->ArcaneRes; + + data << pProto->Delay; + data << pProto->AmmoType; + data << pProto->RangedModRange; + + for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s) + { + // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown + // use `item_template` or if not set then only use spell cooldowns + SpellEntry const* spell = sSpellStore.LookupEntry(pProto->Spells[s].SpellId); + if (spell) + { + bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0; + + data << pProto->Spells[s].SpellId; + data << pProto->Spells[s].SpellTrigger; + data << uint32(-abs(pProto->Spells[s].SpellCharges)); + + if (db_data) + { + data << uint32(pProto->Spells[s].SpellCooldown); + data << uint32(pProto->Spells[s].SpellCategory); + data << uint32(pProto->Spells[s].SpellCategoryCooldown); + } + else + { + data << uint32(spell->RecoveryTime); + data << uint32(spell->Category); + data << uint32(spell->CategoryRecoveryTime); + } + } + else + { + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(-1); + data << uint32(0); + data << uint32(-1); + } + } + data << pProto->Bonding; + data << Description; + data << pProto->PageText; + data << pProto->LanguageID; + data << pProto->PageMaterial; + data << pProto->StartQuest; + data << pProto->LockID; + data << int32(pProto->Material); + data << pProto->Sheath; + data << pProto->RandomProperty; + data << pProto->RandomSuffix; + data << pProto->Block; + data << pProto->ItemSet; + data << pProto->MaxDurability; + data << pProto->Area; + data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch + data << pProto->BagFamily; + data << pProto->TotemCategory; + for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s) + { + data << pProto->Socket[s].Color; + data << pProto->Socket[s].Content; + } + data << pProto->socketBonus; + data << pProto->GemProperties; + data << pProto->RequiredDisenchantSkill; + data << pProto->ArmorDamageModifier; + data << abs(pProto->Duration); // added in 2.4.2.8209, duration (seconds) + data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory + data << pProto->HolidayId; // Holiday.dbc? + SendPacket(&data); + } + else + { + sLog.outDebug("WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item); + WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4); + data << uint32(item | 0x80000000); + SendPacket(&data); + } +} + +void WorldSession::HandleReadItem(WorldPacket & recv_data) +{ + //sLog.outDebug("WORLD: CMSG_READ_ITEM"); + + uint8 bag, slot; + recv_data >> bag >> slot; + + //sLog.outDetail("STORAGE: Read bag = %u, slot = %u", bag, slot); + Item *pItem = _player->GetItemByPos(bag, slot); + + if (pItem && pItem->GetProto()->PageText) + { + WorldPacket data; + + uint8 msg = _player->CanUseItem(pItem); + if (msg == EQUIP_ERR_OK) + { + data.Initialize (SMSG_READ_ITEM_OK, 8); + sLog.outDetail("STORAGE: Item page sent"); + } + else + { + data.Initialize(SMSG_READ_ITEM_FAILED, 8); + sLog.outDetail("STORAGE: Unable to read item"); + _player->SendEquipError(msg, pItem, NULL); + } + data << pItem->GetGUID(); + SendPacket(&data); + } + else + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); +} + +void WorldSession::HandlePageQuerySkippedOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_PAGE_TEXT_QUERY"); + + uint32 itemid; + uint64 guid; + + recv_data >> itemid >> guid; + + sLog.outDetail("Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u", + itemid, GUID_LOPART(guid), GUID_ENPART(guid), GUID_HIPART(guid)); +} + +void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_SELL_ITEM"); + uint64 vendorguid, itemguid; + uint32 count; + + recv_data >> vendorguid >> itemguid >> count; + + if (!itemguid) + return; + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); + _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + Item *pItem = _player->GetItemByGuid(itemguid); + if (pItem) + { + // prevent sell not owner item + if (_player->GetGUID() != pItem->GetOwnerGUID()) + { + _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + + // prevent sell non empty bag by drag-and-drop at vendor's item list + if (pItem->IsBag() && !((Bag*)pItem)->IsEmpty()) + { + _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + + // prevent sell currently looted item + if (_player->GetLootGUID() == pItem->GetGUID()) + { + _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + + // special case at auto sell (sell all) + if (count == 0) + { + count = pItem->GetCount(); + } + else + { + // prevent sell more items that exist in stack (possible only not from client) + if (count > pItem->GetCount()) + { + _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + } + + ItemPrototype const *pProto = pItem->GetProto(); + if (pProto) + { + if (pProto->SellPrice > 0) + { + if (count < pItem->GetCount()) // need split items + { + Item *pNewItem = pItem->CloneItem(count, _player); + if (!pNewItem) + { + sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count); + _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + + pItem->SetCount(pItem->GetCount() - count); + _player->ItemRemovedQuestCheck(pItem->GetEntry(), count); + if (_player->IsInWorld()) + pItem->SendUpdateToPlayer(_player); + pItem->SetState(ITEM_CHANGED, _player); + + _player->AddItemToBuyBackSlot(pNewItem); + if (_player->IsInWorld()) + pNewItem->SendUpdateToPlayer(_player); + } + else + { + _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); + _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true); + pItem->RemoveFromUpdateQueueOf(_player); + _player->AddItemToBuyBackSlot(pItem); + } + + uint32 money = pProto->SellPrice * count; + _player->ModifyMoney(money); + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money); + } + else + _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); + return; + } + } + _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0); + return; +} + +void WorldSession::HandleBuybackItem(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_BUYBACK_ITEM"); + uint64 vendorguid; + uint32 slot; + + recv_data >> vendorguid >> slot; + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); + _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + Item *pItem = _player->GetItemFromBuyBackSlot(slot); + if (pItem) + { + uint32 price = _player->GetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START); + if (_player->GetMoney() < price) + { + _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, pItem->GetEntry(), 0); + return; + } + + ItemPosCountVec dest; + uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false); + if (msg == EQUIP_ERR_OK) + { + _player->ModifyMoney(-(int32)price); + _player->RemoveItemFromBuyBackSlot(slot, false); + _player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount()); + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount()); + _player->StoreItem(dest, pItem, true); + } + else + _player->SendEquipError(msg, pItem, NULL); + return; + } + else + _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, pCreature, 0, 0); +} + +void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_BUY_ITEM_IN_SLOT"); + uint64 vendorguid, bagguid; + uint32 item, slot, count; + uint8 bagslot; + + recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count; + + // client expects count starting at 1, and we send vendorslot+1 to client already + if (slot > 0) + --slot; + else + return; // cheating + + uint8 bag = NULL_BAG; // init for case invalid bagGUID + + // find bag slot by bag guid + if (bagguid == _player->GetGUID()) + bag = INVENTORY_SLOT_BAG_0; + else + { + for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + if (Bag *pBag = (Bag*)_player->GetItemByPos(INVENTORY_SLOT_BAG_0,i)) + { + if (bagguid == pBag->GetGUID()) + { + bag = i; + break; + } + } + } + } + + // bag not found, cheating? + if (bag == NULL_BAG) + return; + + GetPlayer()->BuyItemFromVendorSlot(vendorguid,slot,item,count,bag,bagslot); +} + +void WorldSession::HandleBuyItemOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_BUY_ITEM"); + uint64 vendorguid; + uint32 item, slot, count; + uint8 unk1; + + recv_data >> vendorguid >> item >> slot >> count >> unk1; + + // client expects count starting at 1, and we send vendorslot+1 to client already + if (slot > 0) + --slot; + else + return; // cheating + + GetPlayer()->BuyItemFromVendorSlot(vendorguid,slot,item,count,NULL_BAG,NULL_SLOT); +} + +void WorldSession::HandleListInventoryOpcode(WorldPacket & recv_data) +{ + uint64 guid; + + recv_data >> guid; + + if (!GetPlayer()->isAlive()) + return; + + sLog.outDebug("WORLD: Recvd CMSG_LIST_INVENTORY"); + + SendListInventory(guid); +} + +void WorldSession::SendListInventory(uint64 vendorguid) +{ + sLog.outDebug("WORLD: Sent SMSG_LIST_INVENTORY"); + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); + if (!pCreature) + { + sLog.outDebug("WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); + _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + // Stop the npc if moving + pCreature->StopMoving(); + + VendorItemData const* vItems = pCreature->GetVendorItems(); + if (!vItems) + { + _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); + return; + } + + uint8 numitems = vItems->GetItemCount(); + uint8 count = 0; + + WorldPacket data(SMSG_LIST_INVENTORY, (8+1+numitems*8*4)); + data << uint64(vendorguid); + + size_t count_pos = data.wpos(); + data << uint8(count); + + float discountMod = _player->GetReputationPriceDiscount(pCreature); + + for (uint8 vendorslot = 0; vendorslot < numitems; ++vendorslot ) + { + if (VendorItem const* crItem = vItems->GetItem(vendorslot)) + { + if (ItemPrototype const *pProto = objmgr.GetItemPrototype(crItem->item)) + { + if ((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster()) + continue; + // Only display items in vendor lists for the team the + // player is on. If GM on, display all items. + // `item_template`.`Faction` is actually `Team`. + // 1 == Horde / 2 == Alliance. Field will be renamed in later + // patch. + if (pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE || pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE && !_player->isGameMaster()) + continue; + ++count; + + // reputation discount + int32 price = uint32(floor(pProto->BuyPrice * discountMod)); + + data << uint32(vendorslot+1); // client expects counting to start at 1 + data << uint32(crItem->item); + data << uint32(pProto->DisplayInfoID); + data << int32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem)); + data << uint32(price); + data << uint32(pProto->MaxDurability); + data << uint32(pProto->BuyCount); + data << uint32(crItem->ExtendedCost); + } + } + } + + if (count == 0 || data.size() != 8 + 1 + size_t(count) * 8 * 4) + return; + + data.put(count_pos, count); + SendPacket(&data); +} + +void WorldSession::HandleAutoStoreBagItemOpcode(WorldPacket & recv_data) +{ + //sLog.outDebug("WORLD: CMSG_AUTOSTORE_BAG_ITEM"); + uint8 srcbag, srcslot, dstbag; + + recv_data >> srcbag >> srcslot >> dstbag; + //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag); + + Item *pItem = _player->GetItemByPos(srcbag, srcslot); + if (!pItem) + return; + + if (!_player->IsValidPos(dstbag,NULL_SLOT)) + { + _player->SendEquipError(EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL); + return; + } + + uint16 src = pItem->GetPos(); + + // check unequip potability for equipped items and bank bags + if (_player->IsEquipmentPos (src) || _player->IsBagPos (src)) + { + uint8 msg = _player->CanUnequipItem(src, !_player->IsBagPos (src)); + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, pItem, NULL); + return; + } + } + + ItemPosCountVec dest; + uint8 msg = _player->CanStoreItem(dstbag, NULL_SLOT, dest, pItem, false); + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, pItem, NULL); + return; + } + + // no-op: placed in same slot + if (dest.size() == 1 && dest[0].pos == src) + { + // just remove grey item state + _player->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); + return; + } + + _player->RemoveItem(srcbag, srcslot, true); + _player->StoreItem(dest, pItem, true); +} + +void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: CMSG_BUY_BANK_SLOT"); + + uint64 guid; + recvPacket >> guid; + + // cheating protection + /* not critical if "cheated", and check skip allow by slots in bank windows open by .bank command. + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + */ + + uint32 slot = _player->GetBankBagSlotCount(); + + // next slot + ++slot; + + sLog.outDetail("PLAYER: Buy bank bag slot, slot number = %u", slot); + + BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot); + + WorldPacket data(SMSG_BUY_BANK_SLOT_RESULT, 4); + + if (!slotEntry) + { + data << uint32(ERR_BANKSLOT_FAILED_TOO_MANY); + SendPacket(&data); + return; + } + + uint32 price = slotEntry->price; + + if (_player->GetMoney() < price) + { + data << uint32(ERR_BANKSLOT_INSUFFICIENT_FUNDS); + SendPacket(&data); + return; + } + + _player->SetBankBagSlotCount(slot); + _player->ModifyMoney(-int32(price)); + + data << uint32(ERR_BANKSLOT_OK); + SendPacket(&data); + + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT); +} + +void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: CMSG_AUTOBANK_ITEM"); + uint8 srcbag, srcslot; + + recvPacket >> srcbag >> srcslot; + sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); + + Item *pItem = _player->GetItemByPos(srcbag, srcslot); + if (!pItem) + return; + + ItemPosCountVec dest; + uint8 msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, dest, pItem, false); + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, pItem, NULL); + return; + } + + _player->RemoveItem(srcbag, srcslot, true); + _player->BankItem(dest, pItem, true); +} + +void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket) +{ + sLog.outDebug("WORLD: CMSG_AUTOSTORE_BANK_ITEM"); + uint8 srcbag, srcslot; + + recvPacket >> srcbag >> srcslot; + sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); + + Item *pItem = _player->GetItemByPos(srcbag, srcslot); + if (!pItem) + return; + + if (_player->IsBankPos(srcbag, srcslot)) // moving from bank to inventory + { + ItemPosCountVec dest; + uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false); + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, pItem, NULL); + return; + } + + _player->RemoveItem(srcbag, srcslot, true); + _player->StoreItem(dest, pItem, true); + } + else // moving from inventory to bank + { + ItemPosCountVec dest; + uint8 msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, dest, pItem, false); + if (msg != EQUIP_ERR_OK) + { + _player->SendEquipError(msg, pItem, NULL); + return; + } + + _player->RemoveItem(srcbag, srcslot, true); + _player->BankItem(dest, pItem, true); + } +} + +void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data) +{ + if (!GetPlayer()->isAlive()) + { + GetPlayer()->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL); + return; + } + + sLog.outDebug("WORLD: CMSG_SET_AMMO"); + uint32 item; + + recv_data >> item; + + if (!item) + GetPlayer()->RemoveAmmo(); + else + GetPlayer()->SetAmmo(item); +} + +void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID) +{ + WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10 + data << uint64(Target); + data << uint64(Caster); + data << uint32(ItemID); + data << uint32(SpellID); + data << uint8(0); + SendPacket(&data); +} + +void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration) +{ + // last check 2.0.10 + WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8)); + data << uint64(Itemguid); + data << uint32(slot); + data << uint32(Duration); + data << uint64(Playerguid); + SendPacket(&data); +} + +void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data) +{ + uint32 itemid; + recv_data >> itemid; + recv_data.read_skip(); // guid + + sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid); + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid); + if (pProto) + { + std::string Name; + Name = pProto->Name1; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId); + if (il) + { + if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty()) + Name = il->Name[loc_idx]; + } + } + // guess size + WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+10)); + data << uint32(pProto->ItemId); + data << Name; + data << uint32(pProto->InventoryType); + SendPacket(&data); + return; + } +// This is a BS check, there are lots of items listed in Item.dbc that do not even exist on official -- so we can NEVER get the data for them. +// If you *really* want to spam your error log -- uncomment this. +/* else + { + // listed in dbc or not expected to exist unknown item + if (sItemStore.LookupEntry(itemid)) + sLog.outErrorDb("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (item listed in Item.dbc but not exist in DB)", itemid); + else + sLog.outError("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (unknown item, not listed in Item.dbc)", itemid); + } */ +} + +void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("Received opcode CMSG_WRAP_ITEM"); + + uint8 gift_bag, gift_slot, item_bag, item_slot; + //recv_data.hexlike(); + + recv_data >> gift_bag >> gift_slot; // paper + recv_data >> item_bag >> item_slot; // item + + sLog.outDebug("WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot); + + Item *gift = _player->GetItemByPos(gift_bag, gift_slot); + if (!gift) + { + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); + return; + } + + if (!gift->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPER))// cheating: non-wrapper wrapper + { + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); + return; + } + + Item *item = _player->GetItemByPos(item_bag, item_slot); + + if (!item) + { + _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL); + return; + } + + if (item == gift) // not possable with pacjket from real client + { + _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL); + return; + } + + if (item->IsEquipped()) + { + _player->SendEquipError(EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL); + return; + } + + if (item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR)) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); + { + _player->SendEquipError(EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL); + return; + } + + if (item->IsBag()) + { + _player->SendEquipError(EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL); + return; + } + + if (item->IsSoulBound()) + { + _player->SendEquipError(EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL); + return; + } + + if (item->GetMaxStackCount() != 1) + { + _player->SendEquipError(EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL); + return; + } + + // maybe not correct check (it is better than nothing) + if (item->GetProto()->MaxCount>0) + { + _player->SendEquipError(EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL); + return; + } + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS)); + item->SetEntry(gift->GetEntry()); + + switch (item->GetEntry()) + { + case 5042: item->SetEntry(5043); break; + case 5048: item->SetEntry(5044); break; + case 17303: item->SetEntry(17302); break; + case 17304: item->SetEntry(17305); break; + case 17307: item->SetEntry(17308); break; + case 21830: item->SetEntry(21831); break; + } + item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID()); + item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); + item->SetState(ITEM_CHANGED, _player); + + if (item->GetState() == ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance` + { + // after save it will be impossible to remove the item from the queue + item->RemoveFromUpdateQueueOf(_player); + item->SaveToDB(); // item gave inventory record unchanged and can be save standalone + } + CharacterDatabase.CommitTransaction(); + + uint32 count = 1; + _player->DestroyItemCount(gift, count, true); +} + +void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: CMSG_SOCKET_GEMS"); + + uint64 item_guid; + uint64 gem_guids[MAX_GEM_SOCKETS]; + + recv_data >> item_guid; + if (!item_guid) + return; + + for (int i = 0; i < MAX_GEM_SOCKETS; ++i) + recv_data >> gem_guids[i]; + + //cheat -> tried to socket same gem multiple times + if ((gem_guids[0] && (gem_guids[0] == gem_guids[1] || gem_guids[0] == gem_guids[2])) || + (gem_guids[1] && (gem_guids[1] == gem_guids[2]))) + return; + + Item *itemTarget = _player->GetItemByGuid(item_guid); + if (!itemTarget) //missing item to socket + return; + + ItemPrototype const* itemProto = itemTarget->GetProto(); + if (!itemProto) + return; + + //this slot is excepted when applying / removing meta gem bonus + uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT); + + Item *Gems[MAX_GEM_SOCKETS]; + for (int i = 0; i < MAX_GEM_SOCKETS; ++i) + Gems[i] = gem_guids[i] ? _player->GetItemByGuid(gem_guids[i]) : NULL; + + GemPropertiesEntry const *GemProps[MAX_GEM_SOCKETS]; + for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get geminfo from dbc storage + GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL; + + for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //check for hack maybe + { + if (!GemProps[i]) + continue; + + // tried to put gem in socket where no socket exists (take care about prismatic sockets) + if (!itemProto->Socket[i].Color) + { + // no prismatic socket + if (!itemTarget->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) + return; + + // not first not-colored (not normaly used) socket + if (i != 0 && !itemProto->Socket[i-1].Color && (i+1 >= MAX_GEM_SOCKETS || itemProto->Socket[i+1].Color)) + return; + + // ok, this is first not colored socket for item with prismatic socket + } + + // tried to put normal gem in meta socket + if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META) + return; + + // tried to put meta gem in normal socket + if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META) + return; + } + + uint32 GemEnchants[MAX_GEM_SOCKETS]; + uint32 OldEnchants[MAX_GEM_SOCKETS]; + for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get new and old enchantments + { + GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0; + OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i)); + } + + // check unique-equipped conditions + for (int i = 0; i < MAX_GEM_SOCKETS; ++i) + { + if (!Gems[i]) + continue; + + // continue check for case when attempt add 2 similar unique equipped gems in one item. + ItemPrototype const* iGemProto = Gems[i]->GetProto(); + + // unique item (for new and already placed bit removed enchantments + if (iGemProto->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED) + { + for (int j = 0; j < MAX_GEM_SOCKETS; ++j) + { + if (i == j) // skip self + continue; + + if (Gems[j]) + { + if (iGemProto->ItemId == Gems[j]->GetEntry()) + { + _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); + return; + } + } + else if (OldEnchants[j]) + { + if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) + { + if (iGemProto->ItemId == enchantEntry->GemID) + { + _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); + return; + } + } + } + + } + } + + // unique limit type item + int32 limit_newcount = 0; + if (iGemProto->ItemLimitCategory) + { + if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->ItemLimitCategory)) + { + for (int j = 0; j < MAX_GEM_SOCKETS; ++j) + { + if (Gems[j]) + { + // destroyed gem + if (OldEnchants[j]) + { + if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) + if (ItemPrototype const* jProto = ObjectMgr::GetItemPrototype(enchantEntry->GemID)) + if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory) + --limit_newcount; + } + + // new gem + if (iGemProto->ItemLimitCategory == Gems[j]->GetProto()->ItemLimitCategory) + ++limit_newcount; + } + // existed gem + else if (OldEnchants[j]) + { + if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) + if (ItemPrototype const* jProto = ObjectMgr::GetItemPrototype(enchantEntry->GemID)) + if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory) + ++limit_newcount; + } + } + + if (limit_newcount > 0 && uint32(limit_newcount) > limitEntry->maxCount) + { + _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL); + return; + } + } + } + + // for equipped item check all equipment for duplicate equipped gems + if (itemTarget->IsEquipped()) + { + if (uint8 res = _player->CanEquipUniqueItem(Gems[i],slot,limit_newcount >= 0 ? limit_newcount : 0)) + { + _player->SendEquipError(res, itemTarget, NULL); + return; + } + } + } + + bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus + _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item) + + //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met + + //remove ALL enchants + for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) + _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),false); + + for (int i = 0; i < MAX_GEM_SOCKETS; ++i) + { + if (GemEnchants[i]) + { + itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i],0,0); + if (Item* guidItem = _player->GetItemByGuid(gem_guids[i])) + _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true); + } + } + + for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) + _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true); + + bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state + if (SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change... + { + _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false); + itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0); + _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,true); + //it is not displayed, client has an inbuilt system to determine if the bonus is activated + } + + _player->ToggleMetaGemsActive(slot, true); //turn on all metagems (except for target item) +} + +void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT"); + + uint32 eslot; + + recv_data >> eslot; + + // apply only to equipped item + if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0,eslot)) + return; + + Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot); + + if (!item) + return; + + if (!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)) + return; + + GetPlayer()->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); + item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT); +} + +void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: CMSG_ITEM_REFUND_INFO"); + + uint64 guid; + recv_data >> guid; // item guid + + Item *item = _player->GetItemByGuid(guid); + if (!item) + { + sLog.outDebug("Item refund: item not found!"); + return; + } + + GetPlayer()->SendRefundInfo(item); +} + +void WorldSession::HandleItemRefund(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_ITEM_REFUND"); + uint64 guid; + recv_data >> guid; // item guid + + Item *item = _player->GetItemByGuid(guid); + if (!item) + { + sLog.outDebug("Item refund: item not found!"); + return; + } + + GetPlayer()->RefundItem(item); +} + +/** + * Handles the packet sent by the client when requesting information about item text. + * + * This function is called when player clicks on item which has some flag set + */ +void WorldSession::HandleItemTextQuery(WorldPacket & recv_data ) +{ + uint64 itemGuid; + recv_data >> itemGuid; + + sLog.outDebug("CMSG_ITEM_TEXT_QUERY item guid: %u", GUID_LOPART(itemGuid)); + + WorldPacket data(SMSG_ITEM_TEXT_QUERY_RESPONSE, (4+10)); // guess size + + if (Item *item = _player->GetItemByGuid(itemGuid)) + { + data << uint8(0); // has text + data << uint64(itemGuid); // item guid + data << item->GetText(); + } + else + { + data << uint8(1); // no text + } + + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp new file mode 100644 index 00000000000..0746973ff4c --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp @@ -0,0 +1,251 @@ +/* + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "LFGMgr.h" +#include "WorldSession.h" +#include "WorldPacket.h" +#include "Player.h" + +void WorldSession::HandleLfgJoinOpcode(WorldPacket &recv_data) +{ + sLog.outDebug("CMSG_LFG_JOIN"); + + uint8 numDungeons; + uint32 dungeon; + uint32 roles; + std::string comment; + + recv_data >> roles; + recv_data.read_skip(); // unk - always 0 + recv_data.read_skip(); // unk - always 0 + recv_data >> numDungeons; + if (!numDungeons) + { + sLog.outError("Invalid CMSG_LFG_JOIN packet sent by %s", GetPlayer()->GetName()); + recv_data.rpos(recv_data.wpos()); + return; + } + + GetPlayer()->m_lookingForGroup.roles = uint8(roles); + for (int8 i = 0 ; i < numDungeons; ++i) + { + recv_data >> dungeon; + // remove the type from the dungeon entry + GetPlayer()->m_lookingForGroup.applyDungeons.insert((dungeon & 0x00FFFFFF)); + } + + recv_data >> numDungeons; // unk - always 3 + for (int8 i = 0 ; i < numDungeons; ++i) + recv_data.read_skip(); // unk - always 0 + + recv_data >> comment; + + GetPlayer()->m_lookingForGroup.comment = comment; + sLFGMgr.Join(GetPlayer()); +} + +void WorldSession::HandleLfgLeaveOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("CMSG_LFG_LEAVE"); + + // Check cheating - only leader can leave the queue + if (Group *grp = GetPlayer()->GetGroup()) + { + if (grp->GetLeaderGUID() != GetPlayer()->GetGUID()) + return; + else + sLFGMgr.Leave(GetPlayer(), grp); + } + else + sLFGMgr.Leave(GetPlayer()); +} + +void WorldSession::HandleLfgSetRolesOpcode(WorldPacket &recv_data) +{ + sLog.outDebug("CMSG_LFG_SET_ROLES"); + + uint8 roles; + recv_data >> roles; // Player Group Roles + + Group *grp = GetPlayer()->GetGroup(); + if (!grp) + return; + GetPlayer()->m_lookingForGroup.roles = roles; + sLFGMgr.UpdateRoleCheck(grp, GetPlayer()); +} + +void WorldSession::HandleSetLfgCommentOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_SET_LFG_COMMENT"); + + std::string comment; + recv_data >> comment; + + GetPlayer()->m_lookingForGroup.comment = comment; +} + +void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket &/*recv_data*/) +{ + sLog.outDebug("CMSG_LFD_PLAYER_LOCK_INFO_REQUEST"); + sLFGMgr.SendLfgPlayerInfo(GetPlayer()); +} + +void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket &/*recv_data*/) +{ + sLog.outDebug("CMSG_LFD_PARTY_LOCK_INFO_REQUEST"); + sLFGMgr.SendLfgPartyInfo(GetPlayer()); +} + +void WorldSession::SendLfgUpdatePlayer(uint8 updateType) +{ + bool queued = false; + bool extrainfo = false; + + switch(updateType) + { + case LFG_UPDATETYPE_JOIN_PROPOSAL: + case LFG_UPDATETYPE_ADDED_TO_QUEUE: + queued = true; + extrainfo = true; + break; + //case LFG_UPDATETYPE_CLEAR_LOCK_LIST: // TODO: Sometimes has extrainfo - Check ocurrences... + case LFG_UPDATETYPE_PROPOSAL_FOUND: + extrainfo = true; + break; + } + sLog.outDebug("SMSG_LFG_UPDATE_PLAYER"); + WorldPacket data(SMSG_LFG_UPDATE_PLAYER, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + GetPlayer()->m_lookingForGroup.applyDungeons.size() * 4 + GetPlayer()->m_lookingForGroup.comment.length())); + data << uint8(updateType); // Lfg Update type + data << uint8(extrainfo); // Extra info + if (extrainfo) + { + data << uint8(queued); // Join the queue + data << uint8(0); // unk - Always 0 + data << uint8(0); // unk - Always 0 + + uint8 size = GetPlayer()->m_lookingForGroup.applyDungeons.size(); + data << uint8(size); + + for (LfgDungeonSet::const_iterator it = GetPlayer()->m_lookingForGroup.applyDungeons.begin(); it != GetPlayer()->m_lookingForGroup.applyDungeons.end(); ++it) + data << uint32(*it); + data << GetPlayer()->m_lookingForGroup.comment; + } + SendPacket(&data); +} + +void WorldSession::SendLfgUpdateParty(uint8 updateType) +{ + bool join = false; + bool extrainfo = false; + bool queued = false; + + switch(updateType) + { + case LFG_UPDATETYPE_JOIN_PROPOSAL: + extrainfo = true; + break; + case LFG_UPDATETYPE_ADDED_TO_QUEUE: + extrainfo = true; + join = true; + queued = true; + break; + case LFG_UPDATETYPE_CLEAR_LOCK_LIST: + // join = true; // TODO: Sometimes queued and extrainfo - Check ocurrences... + queued = true; + break; + case LFG_UPDATETYPE_PROPOSAL_FOUND: + extrainfo = true; + join = true; + break; + } + + sLog.outDebug("SMSG_LFG_UPDATE_PARTY"); + WorldPacket data(SMSG_LFG_UPDATE_PARTY, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + 1 + GetPlayer()->m_lookingForGroup.applyDungeons.size() * 4 + GetPlayer()->m_lookingForGroup.comment.length())); + data << uint8(updateType); // Lfg Update type + data << uint8(extrainfo); // Extra info + if (extrainfo) + { + data << uint8(join); // LFG Join + data << uint8(queued); // Join the queue + data << uint8(0); // unk - Always 0 + data << uint8(0); // unk - Always 0 + for (uint8 i = 0; i < 3; ++i) + data << uint8(0); // unk - Always 0 + + uint8 size = GetPlayer()->m_lookingForGroup.applyDungeons.size(); + data << uint8(size); + + for (LfgDungeonSet::const_iterator it = GetPlayer()->m_lookingForGroup.applyDungeons.begin(); it != GetPlayer()->m_lookingForGroup.applyDungeons.end(); ++it) + data << uint32(*it); + + data << GetPlayer()->m_lookingForGroup.comment; + } + SendPacket(&data); +} + +void WorldSession::SendLfgRoleChosen(uint64 guid, uint8 roles) +{ + sLog.outDebug("SMSG_LFG_ROLE_CHOSEN"); + + WorldPacket data(SMSG_LFG_ROLE_CHOSEN); + data << uint64(guid); // Guid + data << uint8(roles > 0); // Ready + data << uint32(roles); // Roles + SendPacket(&data); +} + +void WorldSession::SendLfgJoinResult(uint8 checkResult, uint8 checkValue) +{ + if (checkResult == LFG_JOIN_PARTY_NOT_MEET_REQS) // Should never happen - its handled in Mgr + return; + + sLog.outDebug("SMSG_LFG_JOIN_RESULT"); + + WorldPacket data(SMSG_LFG_JOIN_RESULT); + data << uint32(checkResult); // Check Result + data << uint32(checkValue); // Check Value + SendPacket(&data); +} + +void WorldSession::SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps) +{ + sLog.outDebug("SMSG_LFG_QUEUE_STATUS"); + WorldPacket data(SMSG_LFG_QUEUE_STATUS); + + data << uint32(dungeon); // Dungeon + data << uint32(avgWaitTime); // Average Wait time + data << uint32(waitTime); // Wait Time + data << uint32(waitTimeTanks); // Wait Tanks + data << uint32(waitTimeHealer); // Wait Healers + data << uint32(waitTimeDps); // Wait Dps + data << uint8(tanks); // Tanks needed + data << uint8(healers); // Healers needed + data << uint8(dps); // Dps needed + data << uint32(queuedTime); // Player wait time in queue + SendPacket(&data); +} + +void WorldSession::SendLfgUpdateSearch(bool update) +{ + sLog.outDebug("SMSG_LFG_UPDATE_SEARCH"); + + WorldPacket data(SMSG_LFG_UPDATE_SEARCH); + data << uint8(update); // In Lfg Queue? + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/LootHandler.cpp b/src/server/game/Server/Protocol/Handlers/LootHandler.cpp new file mode 100644 index 00000000000..55aefb3c1f5 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/LootHandler.cpp @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "Log.h" +#include "Corpse.h" +#include "GameObject.h" +#include "Player.h" +#include "ObjectAccessor.h" +#include "WorldSession.h" +#include "LootMgr.h" +#include "Object.h" +#include "Group.h" +#include "World.h" +#include "Util.h" + +void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); + Player *player = GetPlayer(); + uint64 lguid = player->GetLootGUID(); + Loot *loot; + uint8 lootSlot; + + recv_data >> lootSlot; + + if (IS_GAMEOBJECT_GUID(lguid)) + { + GameObject *go = player->GetMap()->GetGameObject(lguid); + + // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO + if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE))) + { + player->SendLootRelease(lguid); + return; + } + + loot = &go->loot; + } + else if (IS_ITEM_GUID(lguid)) + { + Item *pItem = player->GetItemByGuid(lguid); + + if (!pItem) + { + player->SendLootRelease(lguid); + return; + } + + loot = &pItem->loot; + } + else if (IS_CORPSE_GUID(lguid)) + { + Corpse *bones = ObjectAccessor::GetCorpse(*player, lguid); + if (!bones) + { + player->SendLootRelease(lguid); + return; + } + loot = &bones->loot; + } + else + { + Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); + + bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); + + if (!ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + { + player->SendLootRelease(lguid); + return; + } + + loot = &pCreature->loot; + } + + QuestItem *qitem = NULL; + QuestItem *ffaitem = NULL; + QuestItem *conditem = NULL; + + LootItem *item = loot->LootItemInSlot(lootSlot,player,&qitem,&ffaitem,&conditem); + + if (!item) + { + player->SendEquipError(EQUIP_ERR_ALREADY_LOOTED, NULL, NULL); + return; + } + + // questitems use the blocked field for other purposes + if (!qitem && item->is_blocked) + { + player->SendLootRelease(lguid); + return; + } + + ItemPosCountVec dest; + uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item->itemid, item->count); + if (msg == EQUIP_ERR_OK) + { + Item * newitem = player->StoreNewItem(dest, item->itemid, true, item->randomPropertyId); + + if (qitem) + { + qitem->is_looted = true; + //freeforall is 1 if everyone's supposed to get the quest item. + if (item->freeforall || loot->GetPlayerQuestItems().size() == 1) + player->SendNotifyLootItemRemoved(lootSlot); + else + loot->NotifyQuestItemRemoved(qitem->index); + } + else + { + if (ffaitem) + { + //freeforall case, notify only one player of the removal + ffaitem->is_looted=true; + player->SendNotifyLootItemRemoved(lootSlot); + } + else + { + //not freeforall, notify everyone + if (conditem) + conditem->is_looted=true; + loot->NotifyItemRemoved(lootSlot); + } + } + + //if only one person is supposed to loot the item, then set it to looted + if (!item->freeforall) + item->is_looted = true; + + --loot->unlootedCount; + + player->SendNewItem(newitem, uint32(item->count), false, false, true); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item->count); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count); + } + else + player->SendEquipError(msg, NULL, NULL); +} + +void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: CMSG_LOOT_MONEY"); + + Player *player = GetPlayer(); + uint64 guid = player->GetLootGUID(); + if (!guid) + return; + + Loot *pLoot = NULL; + + switch(GUID_HIPART(guid)) + { + case HIGHGUID_GAMEOBJECT: + { + GameObject *pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); + + // not check distance for GO in case owned GO (fishing bobber case, for example) + if (pGameObject && ((pGameObject->GetOwnerGUID() == _player->GetGUID() || pGameObject->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))) + pLoot = &pGameObject->loot; + + break; + } + case HIGHGUID_CORPSE: // remove insignia ONLY in BG + { + Corpse *bones = ObjectAccessor::GetCorpse(*GetPlayer(), guid); + + if (bones && bones->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + pLoot = &bones->loot; + + break; + } + case HIGHGUID_ITEM: + { + if (Item *item = GetPlayer()->GetItemByGuid(guid)) + pLoot = &item->loot; + break; + } + case HIGHGUID_UNIT: + { + Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); + + bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); + + if (ok_loot && pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + pLoot = &pCreature->loot ; + + break; + } + default: + return; // unlootable type + } + + if (pLoot) + { + if (!IS_ITEM_GUID(guid) && player->GetGroup()) //item can be looted only single player + { + Group *group = player->GetGroup(); + + std::vector playersNear; + for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* playerGroup = itr->getSource(); + if (!playerGroup) + continue; + if (player->IsWithinDistInMap(playerGroup,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) + playersNear.push_back(playerGroup); + } + + uint32 money_per_player = uint32((pLoot->gold)/(playersNear.size())); + + for (std::vector::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) + { + (*i)->ModifyMoney(money_per_player); + (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player); + //Offset surely incorrect, but works + WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); + data << uint32(money_per_player); + (*i)->GetSession()->SendPacket(&data); + } + } + else + { + player->ModifyMoney(pLoot->gold); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold); + } + pLoot->gold = 0; + pLoot->NotifyMoneyRemoved(); + } +} + +void WorldSession::HandleLootOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_LOOT"); + + uint64 guid; + recv_data >> guid; + + // Check possible cheat + if (!_player->isAlive()) + return; + + GetPlayer()->SendLoot(guid, LOOT_CORPSE); +} + +void WorldSession::HandleLootReleaseOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_LOOT_RELEASE"); + + // cheaters can modify lguid to prevent correct apply loot release code and re-loot + // use internal stored guid + recv_data.read_skip(); // guid; + + if (uint64 lguid = GetPlayer()->GetLootGUID()) + DoLootRelease(lguid); +} + +void WorldSession::DoLootRelease(uint64 lguid) +{ + Player *player = GetPlayer(); + Loot *loot; + + player->SetLootGUID(0); + player->SendLootRelease(lguid); + + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); + + if (!player->IsInWorld()) + return; + + if (IS_GAMEOBJECT_GUID(lguid)) + { + GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid); + + // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO + if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE))) + return; + + loot = &go->loot; + + if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) + { + // locked doors are opened with spelleffect openlock, prevent remove its as looted + go->UseDoorOrButton(); + } + else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) + { + // GO is mineral vein? so it is not removed after its looted + if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) + { + uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; + uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; + + // only vein pass this check + if (go_min != 0 && go_max > go_min) + { + float amount_rate = sWorld.getRate(RATE_MINING_AMOUNT); + float min_amount = go_min*amount_rate; + float max_amount = go_max*amount_rate; + + go->AddUse(); + float uses = float(go->GetUseCount()); + + if (uses < max_amount) + { + if (uses >= min_amount) + { + float chance_rate = sWorld.getRate(RATE_MINING_NEXT); + + int32 ReqValue = 175; + LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); + if (lockInfo) + ReqValue = lockInfo->Skill[0]; + float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); + double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses)); + if (roll_chance_f(100*chance+skill)) + { + go->SetLootState(GO_READY); + } + else // not have more uses + go->SetLootState(GO_JUST_DEACTIVATED); + } + else // 100% chance until min uses + go->SetLootState(GO_READY); + } + else // max uses already + go->SetLootState(GO_JUST_DEACTIVATED); + } + else // not vein + go->SetLootState(GO_JUST_DEACTIVATED); + } + else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) + { // The fishing hole used once more + go->AddUse(); // if the max usage is reached, will be despawned in next tick + if (go->GetUseCount() >= irand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens)) + { + go->SetLootState(GO_JUST_DEACTIVATED); + } + else + go->SetLootState(GO_READY); + } + else // not chest (or vein/herb/etc) + go->SetLootState(GO_JUST_DEACTIVATED); + + loot->clear(); + } + else + { + // not fully looted object + go->SetLootState(GO_ACTIVATED); + + // if the round robin player release, reset it. + if (player->GetGUID() == loot->roundRobinPlayer) + { + if (Group* pGroup = player->GetGroup()) + { + if (pGroup->GetLootMethod() != MASTER_LOOT) + { + loot->roundRobinPlayer = 0; + } + } + else + loot->roundRobinPlayer = 0; + } + } + } + else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG + { + Corpse *corpse = ObjectAccessor::GetCorpse(*player, lguid); + if (!corpse || !corpse->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + return; + + loot = &corpse->loot; + + if (loot->isLooted()) + { + loot->clear(); + corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); + } + } + else if (IS_ITEM_GUID(lguid)) + { + Item *pItem = player->GetItemByGuid(lguid); + if (!pItem) + return; + + ItemPrototype const* proto = pItem->GetProto(); + + // destroy only 5 items from stack in case prospecting and milling + if ((proto->BagFamily & (BAG_FAMILY_MASK_MINING_SUPP|BAG_FAMILY_MASK_HERBS)) && + proto->Class == ITEM_CLASS_TRADE_GOODS) + { + pItem->m_lootGenerated = false; + pItem->loot.clear(); + + uint32 count = pItem->GetCount(); + + // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. + if (count > 5) + count = 5; + + player->DestroyItemCount(pItem, count, true); + } + else + // FIXME: item must not be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or cheating possible. + player->DestroyItem(pItem->GetBagSlot(),pItem->GetSlot(), true); + return; // item can be looted only single player + } + else + { + Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); + + bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); + if (!ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + return; + + loot = &pCreature->loot; + if (loot->isLooted()) + { + // skip pickpocketing loot for speed, skinning timer redunction is no-op in fact + if (!pCreature->isAlive()) + pCreature->AllLootRemovedFromCorpse(); + + pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pCreature->SetLootRecipient(NULL); + loot->clear(); + } + else + { + // if the round robin player release, reset it. + if (player->GetGUID() == loot->roundRobinPlayer) + { + if (Group* pGroup = player->GetGroup()) + { + if (pGroup->GetLootMethod() != MASTER_LOOT) + { + loot->roundRobinPlayer = 0; + pGroup->SendLooter(pCreature, NULL); + + // force update of dynamic flags, otherwise other group's players still not able to loot. + pCreature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); + } + } + else + loot->roundRobinPlayer = 0; + } + } + } + + //Player is not looking at loot list, he doesn't need to see updates on the loot list + loot->RemoveLooter(player->GetGUID()); +} + +void WorldSession::HandleLootMasterGiveOpcode(WorldPacket & recv_data) +{ + uint8 slotid; + uint64 lootguid, target_playerguid; + + recv_data >> lootguid >> slotid >> target_playerguid; + + if (!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetGUID()) + { + _player->SendLootRelease(GetPlayer()->GetLootGUID()); + return; + } + + Player *target = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(target_playerguid, 0, HIGHGUID_PLAYER)); + if (!target) + return; + + sLog.outDebug("WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = [%s].", target->GetName()); + + if (_player->GetLootGUID() != lootguid) + return; + + Loot *pLoot = NULL; + + if (IS_CRE_OR_VEH_GUID(GetPlayer()->GetLootGUID())) + { + Creature *pCreature = GetPlayer()->GetMap()->GetCreature(lootguid); + if (!pCreature) + return; + + pLoot = &pCreature->loot; + } + else if (IS_GAMEOBJECT_GUID(GetPlayer()->GetLootGUID())) + { + GameObject *pGO = GetPlayer()->GetMap()->GetGameObject(lootguid); + if (!pGO) + return; + + pLoot = &pGO->loot; + } + + if (!pLoot) + return; + + if (slotid > pLoot->items.size()) + { + sLog.outDebug("AutoLootItem: Player %s might be using a hack! (slot %d, size %lu)",GetPlayer()->GetName(), slotid, (unsigned long)pLoot->items.size()); + return; + } + + LootItem& item = pLoot->items[slotid]; + + ItemPosCountVec dest; + uint8 msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count); + if (msg != EQUIP_ERR_OK) + { + target->SendEquipError(msg, NULL, NULL); + _player->SendEquipError(msg, NULL, NULL); // send duplicate of error massage to master looter + return; + } + + // not move item from loot to target inventory + Item * newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId); + target->SendNewItem(newitem, uint32(item.count), false, false, true); + target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count); + target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, pLoot->loot_type, item.count); + target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count); + + // mark as looted + item.count=0; + item.is_looted=true; + + pLoot->NotifyItemRemoved(slotid); + --pLoot->unlootedCount; +} + diff --git a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp new file mode 100644 index 00000000000..ea6f892c126 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp @@ -0,0 +1,1721 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "Database/DatabaseEnv.h" +#include "Database/DatabaseImpl.h" +#include "WorldPacket.h" +#include "Opcodes.h" +#include "Log.h" +#include "Player.h" +#include "GossipDef.h" +#include "World.h" +#include "ObjectMgr.h" +#include "WorldSession.h" +#include "Auth/BigNumber.h" +#include "Auth/Sha1.h" +#include "UpdateData.h" +#include "LootMgr.h" +#include "Chat.h" +#include +#include "ObjectAccessor.h" +#include "Object.h" +#include "BattleGround.h" +#include "OutdoorPvP.h" +#include "Pet.h" +#include "SocialMgr.h" +#include "CellImpl.h" +#include "AccountMgr.h" +#include "Vehicle.h" +#include "CreatureAI.h" +#include "DBCEnums.h" +#include "ScriptMgr.h" +#include "MapManager.h" +#include "InstanceData.h" + +void WorldSession::HandleRepopRequestOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_REPOP_REQUEST Message"); + + recv_data.read_skip(); + + if (GetPlayer()->isAlive()||GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + return; + + // the world update order is sessions, players, creatures + // the netcode runs in parallel with all of these + // creatures can kill players + // so if the server is lagging enough the player can + // release spirit after he's killed but before he is updated + if (GetPlayer()->getDeathState() == JUST_DIED) + { + sLog.outDebug("HandleRepopRequestOpcode: got request after player %s(%d) was killed and before he was updated", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); + GetPlayer()->KillPlayer(); + } + + //this is spirit release confirm? + GetPlayer()->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT, true); + GetPlayer()->BuildPlayerRepop(); + GetPlayer()->RepopAtGraveyard(); +} + +void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION"); + + uint32 gossipListId; + uint32 menuId; + uint64 guid; + std::string code = ""; + + recv_data >> guid >> menuId >> gossipListId; + + if (_player->PlayerTalkClass->GossipOptionCoded(gossipListId)) + { + // recheck + sLog.outBasic("reading string"); + recv_data >> code; + sLog.outBasic("string read: %s", code.c_str()); + } + + Creature *unit = NULL; + GameObject *go = NULL; + if (IS_CRE_OR_VEH_GUID(guid)) + { + unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); + if (!unit) + { + sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + } + else if (IS_GAMEOBJECT_GUID(guid)) + { + go = _player->GetMap()->GetGameObject(guid); + if (!go) + { + sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - GameObject (GUID: %u) not found.", uint32(GUID_LOPART(guid))); + return; + } + } + else + { + sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - unsupported GUID type for highguid %u. lowpart %u.", uint32(GUID_HIPART(guid)), uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + if ((unit && unit->GetCreatureInfo()->ScriptID != unit->LastUsedScriptID) || (go && go->GetGOInfo()->ScriptId != go->LastUsedScriptID)) + { + sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - Script reloaded while in use, ignoring and set new scipt id"); + if (unit) + unit->LastUsedScriptID = unit->GetCreatureInfo()->ScriptID; + if (go) + go->LastUsedScriptID = go->GetGOInfo()->ScriptId; + _player->PlayerTalkClass->CloseGossip(); + return; + } + if (!code.empty()) + { + if (unit) + { + if (!sScriptMgr.GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId), code.c_str())) + _player->OnGossipSelect(unit, gossipListId, menuId); + } + else + sScriptMgr.GOSelectWithCode(_player, go, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId), code.c_str()); + } + else + { + if (unit) + { + if (!sScriptMgr.GossipSelect(_player, unit, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId))) + _player->OnGossipSelect(unit, gossipListId, menuId); + } + else + sScriptMgr.GOSelect(_player, go, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId)); + } +} + +void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_WHO Message"); + //recv_data.hexlike(); + + uint32 clientcount = 0; + + uint32 level_min, level_max, racemask, classmask, zones_count, str_count; + uint32 zoneids[10]; // 10 is client limit + std::string player_name, guild_name; + + recv_data >> level_min; // maximal player level, default 0 + recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) + recv_data >> player_name; // player name, case sensitive... + + recv_data >> guild_name; // guild name, case sensitive... + + recv_data >> racemask; // race mask + recv_data >> classmask; // class mask + recv_data >> zones_count; // zones count, client limit = 10 (2.0.10) + + if (zones_count > 10) + return; // can't be received from real client or broken packet + + for (uint32 i = 0; i < zones_count; ++i) + { + uint32 temp; + recv_data >> temp; // zone id, 0 if zone is unknown... + zoneids[i] = temp; + sLog.outDebug("Zone %u: %u", i, zoneids[i]); + } + + recv_data >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) + + if (str_count > 4) + return; // can't be received from real client or broken packet + + sLog.outDebug("Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", level_min, level_max, player_name.c_str(), guild_name.c_str(), racemask, classmask, zones_count, str_count); + + std::wstring str[4]; // 4 is client limit + for (uint32 i = 0; i < str_count; ++i) + { + std::string temp; + recv_data >> temp; // user entered string, it used as universal search pattern(guild+player name)? + + if (!Utf8toWStr(temp,str[i])) + continue; + + wstrToLower(str[i]); + + sLog.outDebug("String %u: %s", i, temp.c_str()); + } + + std::wstring wplayer_name; + std::wstring wguild_name; + if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name))) + return; + wstrToLower(wplayer_name); + wstrToLower(wguild_name); + + // client send in case not set max level value 100 but Trinity supports 255 max level, + // update it to show GMs with characters after 100 level + if (level_max >= MAX_LEVEL) + level_max = STRONG_MAX_LEVEL; + + uint32 team = _player->GetTeam(); + uint32 security = GetSecurity(); + bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); + uint32 gmLevelInWhoList = sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); + + WorldPacket data(SMSG_WHO, 50); // guess size + data << uint32(clientcount); // clientcount place holder, listed count + data << uint32(clientcount); // clientcount place holder, online count + + ObjectAccessor::Guard guard(*HashMapHolder::GetLock()); + HashMapHolder::MapType& m = ObjectAccessor::Instance().GetPlayers(); + for (HashMapHolder::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) + { + if (security == SEC_PLAYER) + { + // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST + if (itr->second->GetTeam() != team && !allowTwoSideWhoList) + continue; + + // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST + if ((itr->second->GetSession()->GetSecurity() > gmLevelInWhoList)) + continue; + } + + //do not process players which are not in world + if (!(itr->second->IsInWorld())) + continue; + + // check if target is globally visible for player + if (!(itr->second->IsVisibleGloballyFor(_player))) + continue; + + // check if target's level is in level range + uint8 lvl = itr->second->getLevel(); + if (lvl < level_min || lvl > level_max) + continue; + + // check if class matches classmask + uint32 class_ = itr->second->getClass(); + if (!(classmask & (1 << class_))) + continue; + + // check if race matches racemask + uint32 race = itr->second->getRace(); + if (!(racemask & (1 << race))) + continue; + + uint32 pzoneid = itr->second->GetZoneId(); + + bool z_show = true; + for (uint32 i = 0; i < zones_count; ++i) + { + if (zoneids[i] == pzoneid) + { + z_show = true; + break; + } + + z_show = false; + } + if (!z_show) + continue; + + std::string pname = itr->second->GetName(); + std::wstring wpname; + if (!Utf8toWStr(pname,wpname)) + continue; + wstrToLower(wpname); + + if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos)) + continue; + + std::string gname = objmgr.GetGuildNameById(itr->second->GetGuildId()); + std::wstring wgname; + if (!Utf8toWStr(gname,wgname)) + continue; + wstrToLower(wgname); + + if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos)) + continue; + + std::string aname; + if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(itr->second->GetZoneId())) + aname = areaEntry->area_name[GetSessionDbcLocale()]; + + bool s_show = true; + for (uint32 i = 0; i < str_count; ++i) + { + if (!str[i].empty()) + { + if (wgname.find(str[i]) != std::wstring::npos || + wpname.find(str[i]) != std::wstring::npos || + Utf8FitTo(aname, str[i])) + { + s_show = true; + break; + } + s_show = false; + } + } + if (!s_show) + continue; + + data << pname; // player name + data << gname; // guild name + data << uint32(lvl); // player level + data << uint32(class_); // player class + data << uint32(race); // player race + data << uint8(0); // new 2.4.0 + data << uint32(pzoneid); // player zone id + + // 49 is maximum player count sent to client - can be overridden + // through config, but is unstable + if ((++clientcount) == sWorld.getConfig(CONFIG_MAX_WHO)) + break; + } + + uint32 count = m.size(); + data.put( 0, clientcount ); // insert right count, listed count + data.put( 4, count > 50 ? count : clientcount ); // insert right count, online count + + SendPacket(&data); + sLog.outDebug("WORLD: Send SMSG_WHO Message"); +} + +void WorldSession::HandleLogoutRequestOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", GetSecurity()); + + if (uint64 lguid = GetPlayer()->GetLootGUID()) + DoLootRelease(lguid); + + uint8 reason = 0; + + if (GetPlayer()->isInCombat()) + reason = 1; + else if (GetPlayer()->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_JUMPING | MOVEMENTFLAG_FALLING)) + reason = 3; // is jumping or falling + else if (GetPlayer()->duel || GetPlayer()->HasAura(9454)) // is dueling or frozen by GM via freeze command + reason = 2; // FIXME - Need the correct value + + if (reason) + { + WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); + data << uint8(reason); + data << uint32(0); + SendPacket(&data); + LogoutRequest(0); + return; + } + + //instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in TrinityCore.conf + if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->isInFlight() || + GetSecurity() >= sWorld.getConfig(CONFIG_INSTANT_LOGOUT)) + { + WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); + data << uint8(0); + data << uint32(16777216); + SendPacket(&data); + LogoutPlayer(true); + return; + } + + // not set flags if player can't free move to prevent lost state at logout cancel + if (GetPlayer()->CanFreeMove()) + { + GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); + + WorldPacket data(SMSG_FORCE_MOVE_ROOT, (8+4)); // guess size + data.append(GetPlayer()->GetPackGUID()); + data << (uint32)2; + SendPacket(&data); + GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + } + + WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); + data << uint8(0); + data << uint32(0); + SendPacket(&data); + LogoutRequest(time(NULL)); +} + +void WorldSession::HandlePlayerLogoutOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: Recvd CMSG_PLAYER_LOGOUT Message"); +} + +void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: Recvd CMSG_LOGOUT_CANCEL Message"); + + LogoutRequest(0); + + WorldPacket data(SMSG_LOGOUT_CANCEL_ACK, 0); + SendPacket(&data); + + // not remove flags if can't free move - its not set in Logout request code. + if (GetPlayer()->CanFreeMove()) + { + //!we can move again + data.Initialize(SMSG_FORCE_MOVE_UNROOT, 8); // guess size + data.append(GetPlayer()->GetPackGUID()); + data << uint32(0); + SendPacket(&data); + + //! Stand Up + GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND); + + //! DISABLE_ROTATE + GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + } + + sLog.outDebug("WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message"); +} + +void WorldSession::HandleTogglePvP(WorldPacket & recv_data) +{ + // this opcode can be used in two ways: Either set explicit new status or toggle old status + if (recv_data.size() == 1) + { + bool newPvPStatus; + recv_data >> newPvPStatus; + GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus); + GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus); + } + else + { + GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER); + } + + if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) + { + if (!GetPlayer()->IsPvP() || GetPlayer()->pvpInfo.endTimer != 0) + GetPlayer()->UpdatePvP(true, true); + } + else + { + if (!GetPlayer()->pvpInfo.inHostileArea && GetPlayer()->IsPvP()) + GetPlayer()->pvpInfo.endTimer = time(NULL); // start toggle-off + } + + //if (OutdoorPvP * pvp = _player->GetOutdoorPvP()) + // pvp->HandlePlayerActivityChanged(_player); +} + +void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recv_data) +{ + uint32 newZone; + recv_data >> newZone; + + sLog.outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); + + // use server size data + uint32 newzone, newarea; + GetPlayer()->GetZoneAndAreaId(newzone,newarea); + GetPlayer()->UpdateZone(newzone,newarea); + //GetPlayer()->SendInitWorldStates(true,newZone); +} + +void WorldSession::HandleSetTargetOpcode(WorldPacket & recv_data) +{ + // When this packet send? + uint64 guid ; + recv_data >> guid; + + _player->SetUInt32Value(UNIT_FIELD_TARGET, guid); + + // update reputation list if need + Unit* unit = ObjectAccessor::GetUnit(*_player, guid); + if (!unit) + return; + + if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction())) + _player->GetReputationMgr().SetVisible(factionTemplateEntry); +} + +void WorldSession::HandleSetSelectionOpcode(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + + _player->SetSelection(guid); + + // update reputation list if need + Unit* unit = ObjectAccessor::GetUnit(*_player, guid); + if (!unit) + return; + + if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction())) + _player->GetReputationMgr().SetVisible(factionTemplateEntry); +} + +void WorldSession::HandleStandStateChangeOpcode(WorldPacket & recv_data) +{ + // sLog.outDebug("WORLD: Received CMSG_STANDSTATECHANGE"); -- too many spam in log at lags/debug stop + uint32 animstate; + recv_data >> animstate; + + _player->SetStandState(animstate); +} + +void WorldSession::HandleContactListOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_CONTACT_LIST"); + uint32 unk; + recv_data >> unk; + sLog.outDebug("unk value is %u", unk); + _player->GetSocial()->SendSocialList(); +} + +void WorldSession::HandleAddFriendOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_ADD_FRIEND"); + + std::string friendName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN); + std::string friendNote; + + recv_data >> friendName; + + recv_data >> friendNote; + + if (!normalizePlayerName(friendName)) + return; + + CharacterDatabase.escape_string(friendName); // prevent SQL injection - normal name don't must changed by this call + + sLog.outDebug("WORLD: %s asked to add friend : '%s'", + GetPlayer()->GetName(), friendName.c_str()); + + CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddFriendOpcodeCallBack, GetAccountId(), friendNote, "SELECT guid, race, account FROM characters WHERE name = '%s'", friendName.c_str()); +} + +void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string friendNote) +{ + uint64 friendGuid; + uint64 friendAcctid; + uint32 team; + FriendsResult friendResult; + + WorldSession * session = sWorld.FindSession(accountId); + + if (!session || !session->GetPlayer()) + return; + + friendResult = FRIEND_NOT_FOUND; + friendGuid = 0; + + if (result) + { + friendGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + team = Player::TeamForRace((*result)[1].GetUInt8()); + friendAcctid = (*result)[2].GetUInt32(); + + if (session->GetSecurity() >= SEC_MODERATOR || sWorld.getConfig(CONFIG_ALLOW_GM_FRIEND) || accmgr.GetSecurity(friendAcctid) < SEC_MODERATOR) + { + if (friendGuid) + { + if (friendGuid == session->GetPlayer()->GetGUID()) + friendResult = FRIEND_SELF; + else if (session->GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && session->GetSecurity() < SEC_MODERATOR) + friendResult = FRIEND_ENEMY; + else if (session->GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid))) + friendResult = FRIEND_ALREADY; + else + { + Player* pFriend = ObjectAccessor::FindPlayer(friendGuid); + if (pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(session->GetPlayer())) + friendResult = FRIEND_ADDED_ONLINE; + else + friendResult = FRIEND_ADDED_OFFLINE; + if (!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false)) + { + friendResult = FRIEND_LIST_FULL; + sLog.outDebug("WORLD: %s's friend list is full.", session->GetPlayer()->GetName()); + } + } + session->GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote); + } + } + } + + sSocialMgr.SendFriendStatus(session->GetPlayer(), friendResult, GUID_LOPART(friendGuid), false); + + sLog.outDebug("WORLD: Sent (SMSG_FRIEND_STATUS)"); +} + +void WorldSession::HandleDelFriendOpcode(WorldPacket & recv_data) +{ + uint64 FriendGUID; + + sLog.outDebug("WORLD: Received CMSG_DEL_FRIEND"); + + recv_data >> FriendGUID; + + _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(FriendGUID), false); + + sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_REMOVED, GUID_LOPART(FriendGUID), false); + + sLog.outDebug("WORLD: Sent motd (SMSG_FRIEND_STATUS)"); +} + +void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_ADD_IGNORE"); + + std::string IgnoreName = GetTrinityString(LANG_FRIEND_IGNORE_UNKNOWN); + + recv_data >> IgnoreName; + + if (!normalizePlayerName(IgnoreName)) + return; + + CharacterDatabase.escape_string(IgnoreName); // prevent SQL injection - normal name don't must changed by this call + + sLog.outDebug("WORLD: %s asked to Ignore: '%s'", + GetPlayer()->GetName(), IgnoreName.c_str()); + + CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddIgnoreOpcodeCallBack, GetAccountId(), "SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str()); +} + +void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId) +{ + uint64 IgnoreGuid; + FriendsResult ignoreResult; + + WorldSession * session = sWorld.FindSession(accountId); + + if (!session || !session->GetPlayer()) + return; + + ignoreResult = FRIEND_IGNORE_NOT_FOUND; + IgnoreGuid = 0; + + if (result) + { + IgnoreGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER); + + if (IgnoreGuid) + { + if (IgnoreGuid == session->GetPlayer()->GetGUID()) //not add yourself + ignoreResult = FRIEND_IGNORE_SELF; + else if (session->GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid))) + ignoreResult = FRIEND_IGNORE_ALREADY; + else + { + ignoreResult = FRIEND_IGNORE_ADDED; + + // ignore list full + if (!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true)) + ignoreResult = FRIEND_IGNORE_FULL; + } + } + } + + sSocialMgr.SendFriendStatus(session->GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false); + + sLog.outDebug("WORLD: Sent (SMSG_FRIEND_STATUS)"); +} + +void WorldSession::HandleDelIgnoreOpcode(WorldPacket & recv_data) +{ + uint64 IgnoreGUID; + + sLog.outDebug("WORLD: Received CMSG_DEL_IGNORE"); + + recv_data >> IgnoreGUID; + + _player->GetSocial()->RemoveFromSocialList(GUID_LOPART(IgnoreGUID), true); + + sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_IGNORE_REMOVED, GUID_LOPART(IgnoreGUID), false); + + sLog.outDebug("WORLD: Sent motd (SMSG_FRIEND_STATUS)"); +} + +void WorldSession::HandleSetContactNotesOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_SET_CONTACT_NOTES"); + uint64 guid; + std::string note; + recv_data >> guid >> note; + _player->GetSocial()->SetFriendNote(guid, note); +} + +void WorldSession::HandleBugOpcode(WorldPacket & recv_data) +{ + uint32 suggestion, contentlen, typelen; + std::string content, type; + + recv_data >> suggestion >> contentlen >> content; + + recv_data >> typelen >> type; + + if (suggestion == 0) + sLog.outDebug("WORLD: Received CMSG_BUG [Bug Report]"); + else + sLog.outDebug("WORLD: Received CMSG_BUG [Suggestion]"); + + sLog.outDebug("%s", type.c_str()); + sLog.outDebug("%s", content.c_str()); + + CharacterDatabase.escape_string(type); + CharacterDatabase.escape_string(content); + CharacterDatabase.PExecute ("INSERT INTO bugreport (type,content) VALUES('%s', '%s')", type.c_str(), content.c_str()); +} + +void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) +{ + sLog.outDetail("WORLD: Received CMSG_RECLAIM_CORPSE"); + + uint64 guid; + recv_data >> guid; + + if (GetPlayer()->isAlive()) + return; + + // do not allow corpse reclaim in arena + if (GetPlayer()->InArena()) + return; + + // body not released yet + if (!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + return; + + Corpse *corpse = GetPlayer()->GetCorpse(); + + if (!corpse) + return; + + // prevent resurrect before 30-sec delay after body release not finished + if (corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP) > time(NULL)) + return; + + if (!corpse->IsWithinDistInMap(GetPlayer(), CORPSE_RECLAIM_RADIUS, true)) + return; + + // resurrect + GetPlayer()->ResurrectPlayer(GetPlayer()->InBattleGround() ? 1.0f : 0.5f); + + // spawn bones + GetPlayer()->SpawnCorpseBones(); +} + +void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) +{ + sLog.outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE"); + + uint64 guid; + uint8 status; + recv_data >> guid; + recv_data >> status; + + if (GetPlayer()->isAlive()) + return; + + if (status == 0) + { + GetPlayer()->clearResurrectRequestData(); // reject + return; + } + + if (!GetPlayer()->isRessurectRequestedBy(guid)) + return; + + GetPlayer()->ResurectUsingRequestData(); +} + +void WorldSession::SendAreaTriggerMessage(const char* Text, ...) +{ + va_list ap; + char szStr [1024]; + szStr[0] = '\0'; + + va_start(ap, Text); + vsnprintf(szStr, 1024, Text, ap); + va_end(ap); + + uint32 length = strlen(szStr)+1; + WorldPacket data(SMSG_AREA_TRIGGER_MESSAGE, 4+length); + data << length; + data << szStr; + SendPacket(&data); +} + +void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_AREATRIGGER"); + + uint32 Trigger_ID; + + recv_data >> Trigger_ID; + sLog.outDebug("Trigger ID:%u",Trigger_ID); + + if (GetPlayer()->isInFlight()) + { + sLog.outDebug("Player '%s' (GUID: %u) in flight, ignore Area Trigger ID:%u",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow(), Trigger_ID); + return; + } + + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + if (!atEntry) + { + sLog.outDebug("Player '%s' (GUID: %u) send unknown (by DBC) Area Trigger ID:%u",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow(), Trigger_ID); + return; + } + + if (GetPlayer()->GetMapId() != atEntry->mapid) + { + sLog.outDebug("Player '%s' (GUID: %u) too far (trigger map: %u player map: %u), ignore Area Trigger ID: %u", GetPlayer()->GetName(), atEntry->mapid, GetPlayer()->GetMapId(), GetPlayer()->GetGUIDLow(), Trigger_ID); + return; + } + + // delta is safe radius + const float delta = 5.0f; + // check if player in the range of areatrigger + Player* pl = GetPlayer(); + + if (atEntry->radius > 0) + { + // if we have radius check it + float dist = pl->GetDistance(atEntry->x,atEntry->y,atEntry->z); + if (dist > atEntry->radius + delta) + { + sLog.outDebug("Player '%s' (GUID: %u) too far (radius: %f distance: %f), ignore Area Trigger ID: %u", + pl->GetName(), pl->GetGUIDLow(), atEntry->radius, dist, Trigger_ID); + return; + } + } + else + { + // we have only extent + + // rotate the players position instead of rotating the whole cube, that way we can make a simplified + // is-in-cube check and we have to calculate only one point instead of 4 + + // 2PI = 360°, keep in mind that ingame orientation is counter-clockwise + double rotation = 2*M_PI-atEntry->box_orientation; + double sinVal = sin(rotation); + double cosVal = cos(rotation); + + float playerBoxDistX = pl->GetPositionX() - atEntry->x; + float playerBoxDistY = pl->GetPositionY() - atEntry->y; + + float rotPlayerX = atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal; + float rotPlayerY = atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal; + + // box edges are parallel to coordiante axis, so we can treat every dimension independently :D + float dz = pl->GetPositionZ() - atEntry->z; + float dx = rotPlayerX - atEntry->x; + float dy = rotPlayerY - atEntry->y; + if ((fabs(dx) > atEntry->box_x/2 + delta) || + (fabs(dy) > atEntry->box_y/2 + delta) || + (fabs(dz) > atEntry->box_z/2 + delta)) + { + sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotatedPlayerX: %f rotatedPlayerY: %f dZ:%f), ignore Area Trigger ID: %u", + pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotPlayerX, rotPlayerY, dz, Trigger_ID); + return; + } + } + + if (sScriptMgr.AreaTrigger(GetPlayer(), atEntry)) + return; + + uint32 quest_id = objmgr.GetQuestForAreaTrigger(Trigger_ID); + if (quest_id && GetPlayer()->isAlive() && GetPlayer()->IsActiveQuest(quest_id)) + { + Quest const* pQuest = objmgr.GetQuestTemplate(quest_id); + if (pQuest) + { + if (GetPlayer()->GetQuestStatus(quest_id) == QUEST_STATUS_INCOMPLETE) + GetPlayer()->AreaExploredOrEventHappens(quest_id); + } + } + + if (objmgr.IsTavernAreaTrigger(Trigger_ID)) + { + // set resting flag we are in the inn + GetPlayer()->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + GetPlayer()->InnEnter(time(NULL), atEntry->mapid, atEntry->x, atEntry->y, atEntry->z); + GetPlayer()->SetRestType(REST_TYPE_IN_TAVERN); + + if (sWorld.IsFFAPvPRealm()) + GetPlayer()->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); + + return; + } + + if (GetPlayer()->InBattleGround()) + { + BattleGround* bg = GetPlayer()->GetBattleGround(); + if (bg) + if (bg->GetStatus() == STATUS_IN_PROGRESS) + bg->HandleAreaTrigger(GetPlayer(), Trigger_ID); + + return; + } + + if (OutdoorPvP * pvp = GetPlayer()->GetOutdoorPvP()) + { + if (pvp->HandleAreaTrigger(_player, Trigger_ID)) + return; + } + + // NULL if all values default (non teleport trigger) + AreaTrigger const* at = objmgr.GetAreaTrigger(Trigger_ID); + if (!at) + return; + + if (!GetPlayer()->Satisfy(objmgr.GetAccessRequirement(at->access_id), at->target_mapId, true)) + return; + + // check if player can enter instance : instance not full, and raid instance not in encounter fight + if (!MapManager::Instance().CanPlayerEnter(at->target_mapId, GetPlayer(), false)) + return; + + GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT); +} + +void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) +{ + sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); + + uint32 type, timestamp, decompressedSize; + recv_data >> type >> timestamp >> decompressedSize; + + sLog.outDebug("UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize); + + if (type > NUM_ACCOUNT_DATA_TYPES) + return; + + if (decompressedSize == 0) // erase + { + SetAccountData(AccountDataType(type), 0, ""); + + WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); + data << uint32(type); + data << uint32(0); + SendPacket(&data); + + return; + } + + if (decompressedSize > 0xFFFF) + { + recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case + sLog.outError("UAD: Account data packet too big, size %u", decompressedSize); + return; + } + + ByteBuffer dest; + dest.resize(decompressedSize); + + uLongf realSize = decompressedSize; + if (uncompress(const_cast(dest.contents()), &realSize, const_cast(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) + { + recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case + sLog.outError("UAD: Failed to decompress account data"); + return; + } + + recv_data.rpos(recv_data.wpos()); // uncompress read (recv_data.size() - recv_data.rpos()) + + std::string adata; + dest >> adata; + + SetAccountData(AccountDataType(type), timestamp, adata); + + WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); + data << uint32(type); + data << uint32(0); + SendPacket(&data); +} + +void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) +{ + sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); + + uint32 type; + recv_data >> type; + + sLog.outDebug("RAD: type %u", type); + + if (type > NUM_ACCOUNT_DATA_TYPES) + return; + + AccountData *adata = GetAccountData(AccountDataType(type)); + + uint32 size = adata->Data.size(); + + uLongf destSize = compressBound(size); + + ByteBuffer dest; + dest.resize(destSize); + + if (size && compress(const_cast(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) + { + sLog.outDebug("RAD: Failed to compress account data"); + return; + } + + dest.resize(destSize); + + WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize); + data << uint64(_player ? _player->GetGUID() : 0); // player guid + data << uint32(type); // type (0-7) + data << uint32(adata->Time); // unix time + data << uint32(size); // decompressed length + data.append(dest); // compressed data + SendPacket(&data); +} + +void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_SET_ACTION_BUTTON"); + uint8 button; + uint32 packetData; + recv_data >> button >> packetData; + + uint32 action = ACTION_BUTTON_ACTION(packetData); + uint8 type = ACTION_BUTTON_TYPE(packetData); + + sLog.outDetail("BUTTON: %u ACTION: %u TYPE: %u", button, action, type); + if (!packetData) + { + sLog.outDetail("MISC: Remove action from button %u", button); + GetPlayer()->removeActionButton(button); + } + else + { + switch(type) + { + case ACTION_BUTTON_MACRO: + case ACTION_BUTTON_CMACRO: + sLog.outDetail("MISC: Added Macro %u into button %u", action, button); + break; + case ACTION_BUTTON_EQSET: + sLog.outDetail("MISC: Added EquipmentSet %u into button %u", action, button); + break; + case ACTION_BUTTON_SPELL: + sLog.outDetail("MISC: Added Spell %u into button %u", action, button); + break; + case ACTION_BUTTON_ITEM: + sLog.outDetail("MISC: Added Item %u into button %u", action, button); + break; + default: + sLog.outError("MISC: Unknown action button type %u for action %u into button %u", type, action, button); + return; + } + GetPlayer()->addActionButton(button, action, type); + } +} + +void WorldSession::HandleCompleteCinematic(WorldPacket & /*recv_data*/) +{ + DEBUG_LOG("WORLD: Player is watching cinema"); +} + +void WorldSession::HandleNextCinematicCamera(WorldPacket & /*recv_data*/) +{ + DEBUG_LOG("WORLD: Which movie to play"); +} + +void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) +{ + /* WorldSession::Update(getMSTime());*/ + DEBUG_LOG("WORLD: Time Lag/Synchronization Resent/Update"); + + uint64 guid; + if (!recv_data.readPackGUID(guid)) + { + recv_data.rpos(recv_data.wpos()); + return; + } + recv_data.read_skip(); + /* + uint64 guid; + uint32 time_skipped; + recv_data >> guid; + recv_data >> time_skipped; + sLog.outDebug("WORLD: CMSG_MOVE_TIME_SKIPPED"); + + /// TODO + must be need use in Trinity + We substract server Lags to move time (AntiLags) + for exmaple + GetPlayer()->ModifyLastMoveTime(-int32(time_skipped)); + */ +} + +void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data) +{ + DEBUG_LOG("WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); + + // no used + recv_data.rpos(recv_data.wpos()); // prevent warnings spam +} + +void WorldSession::HandleMoveUnRootAck(WorldPacket& recv_data) +{ + // no used + recv_data.rpos(recv_data.wpos()); // prevent warnings spam +/* + uint64 guid; + recv_data >> guid; + + // now can skip not our packet + if (_player->GetGUID() != guid) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + + sLog.outDebug("WORLD: CMSG_FORCE_MOVE_UNROOT_ACK"); + + recv_data.read_skip(); // unk + + MovementInfo movementInfo; + movementInfo.guid = guid; + ReadMovementInfo(recv_data, &movementInfo); + recv_data.read_skip(); // unk2 +*/ +} + +void WorldSession::HandleMoveRootAck(WorldPacket& recv_data) +{ + // no used + recv_data.rpos(recv_data.wpos()); // prevent warnings spam +/* + uint64 guid; + recv_data >> guid; + + // now can skip not our packet + if (_player->GetGUID() != guid) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + + sLog.outDebug("WORLD: CMSG_FORCE_MOVE_ROOT_ACK"); + + recv_data.read_skip(); // unk + + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); +*/ +} + +void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data) +{ + uint8 ActionBar; + + recv_data >> ActionBar; + + if (!GetPlayer()) // ignore until not logged (check needed because STATUS_AUTHED) + { + if (ActionBar != 0) + sLog.outError("WorldSession::HandleSetActionBarToggles in not logged state with value: %u, ignored",uint32(ActionBar)); + return; + } + + GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, ActionBar); +} + +void WorldSession::HandleWardenDataOpcode(WorldPacket& recv_data) +{ + recv_data.read_skip(); + /* + uint8 tmp; + recv_data >> tmp; + sLog.outDebug("Received opcode CMSG_WARDEN_DATA, not resolve.uint8 = %u",tmp); + */ +} + +void WorldSession::HandlePlayedTime(WorldPacket& recv_data) +{ + uint8 unk1; + recv_data >> unk1; // 0 or 1 expected + + WorldPacket data(SMSG_PLAYED_TIME, 4 + 4 + 1); + data << uint32(_player->GetTotalPlayedTime()); + data << uint32(_player->GetLevelPlayedTime()); + data << uint8(unk1); // 0 - will not show in chat frame + SendPacket(&data); +} + +void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) +{ + uint64 guid; + recv_data >> guid; + DEBUG_LOG("Inspected guid is " UI64FMTD, guid); + + _player->SetSelection(guid); + + Player *plr = objmgr.GetPlayer(guid); + if (!plr) // wrong player + return; + + uint32 talent_points = 0x47; + uint32 guid_size = plr->GetPackGUID().wpos(); + WorldPacket data(SMSG_INSPECT_TALENT, guid_size+4+talent_points); + data.append(plr->GetPackGUID()); + + if (sWorld.getConfig(CONFIG_TALENTS_INSPECTING) || _player->isGameMaster()) + { + plr->BuildPlayerTalentsInfoData(&data); + } + else + { + data << uint32(0); // unspentTalentPoints + data << uint8(0); // talentGroupCount + data << uint8(0); // talentGroupIndex + } + + plr->BuildEnchantmentsInfoData(&data); + SendPacket(&data); +} + +void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) +{ + uint64 guid; + recv_data >> guid; + + Player *player = objmgr.GetPlayer(guid); + + if (!player) + { + sLog.outError("InspectHonorStats: WTF, player not found..."); + return; + } + + WorldPacket data(MSG_INSPECT_HONOR_STATS, 8+1+4*4); + data << uint64(player->GetGUID()); + data << uint8(player->GetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY)); + data << uint32(player->GetUInt32Value(PLAYER_FIELD_KILLS)); + data << uint32(player->GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + data << uint32(player->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); + data << uint32(player->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); + SendPacket(&data); +} + +void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) +{ + // write in client console: worldport 469 452 6454 2536 180 or /console worldport 469 452 6454 2536 180 + // Received opcode CMSG_WORLD_TELEPORT + // Time is ***, map=469, x=452.000000, y=6454.000000, z=2536.000000, orient=3.141593 + + uint32 time; + uint32 mapid; + float PositionX; + float PositionY; + float PositionZ; + float Orientation; + + recv_data >> time; // time in m.sec. + recv_data >> mapid; + recv_data >> PositionX; + recv_data >> PositionY; + recv_data >> PositionZ; + recv_data >> Orientation; // o (3.141593 = 180 degrees) + + //sLog.outDebug("Received opcode CMSG_WORLD_TELEPORT"); + if (GetPlayer()->isInFlight()) + { + sLog.outDebug("Player '%s' (GUID: %u) in flight, ignore worldport command.",GetPlayer()->GetName(),GetPlayer()->GetGUIDLow()); + return; + } + + DEBUG_LOG("Time %u sec, map=%u, x=%f, y=%f, z=%f, orient=%f", time/1000, mapid, PositionX, PositionY, PositionZ, Orientation); + + if (GetSecurity() >= SEC_ADMINISTRATOR) + GetPlayer()->TeleportTo(mapid,PositionX,PositionY,PositionZ,Orientation); + else + SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); + sLog.outDebug("Received worldport command from player %s", GetPlayer()->GetName()); +} + +void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("Received opcode CMSG_WHOIS"); + std::string charname; + recv_data >> charname; + + if (GetSecurity() < SEC_ADMINISTRATOR) + { + SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); + return; + } + + if (charname.empty() || !normalizePlayerName (charname)) + { + SendNotification(LANG_NEED_CHARACTER_NAME); + return; + } + + Player *plr = objmgr.GetPlayer(charname.c_str()); + + if (!plr) + { + SendNotification(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, charname.c_str()); + return; + } + + uint32 accid = plr->GetSession()->GetAccountId(); + + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid); + if (!result) + { + SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, charname.c_str()); + return; + } + + Field *fields = result->Fetch(); + std::string acc = fields[0].GetCppString(); + if (acc.empty()) + acc = "Unknown"; + std::string email = fields[1].GetCppString(); + if (email.empty()) + email = "Unknown"; + std::string lastip = fields[2].GetCppString(); + if (lastip.empty()) + lastip = "Unknown"; + + std::string msg = charname + "'s " + "account is " + acc + ", e-mail: " + email + ", last ip: " + lastip; + + WorldPacket data(SMSG_WHOIS, msg.size()+1); + data << msg; + _player->GetSession()->SendPacket(&data); + + sLog.outDebug("Received whois command from player %s for character %s", GetPlayer()->GetName(), charname.c_str()); +} + +void WorldSession::HandleComplainOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_COMPLAIN"); + recv_data.hexlike(); + + uint8 spam_type; // 0 - mail, 1 - chat + uint64 spammer_guid; + uint32 unk1 = 0; + uint32 unk2 = 0; + uint32 unk3 = 0; + uint32 unk4 = 0; + std::string description = ""; + recv_data >> spam_type; // unk 0x01 const, may be spam type (mail/chat) + recv_data >> spammer_guid; // player guid + switch(spam_type) + { + case 0: + recv_data >> unk1; // const 0 + recv_data >> unk2; // probably mail id + recv_data >> unk3; // const 0 + break; + case 1: + recv_data >> unk1; // probably language + recv_data >> unk2; // message type? + recv_data >> unk3; // probably channel id + recv_data >> unk4; // unk random value + recv_data >> description; // spam description string (messagetype, channel name, player name, message) + break; + } + + // NOTE: all chat messages from this spammer automatically ignored by spam reporter until logout in case chat spam. + // if it's mail spam - ALL mails from this spammer automatically removed by client + + // Complaint Received message + WorldPacket data(SMSG_COMPLAIN_RESULT, 1); + data << uint8(0); + SendPacket(&data); + + sLog.outDebug("REPORT SPAM: type %u, guid %u, unk1 %u, unk2 %u, unk3 %u, unk4 %u, message %s", spam_type, GUID_LOPART(spammer_guid), unk1, unk2, unk3, unk4, description.c_str()); +} + +void WorldSession::HandleRealmSplitOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_REALM_SPLIT"); + + uint32 unk; + std::string split_date = "01/01/01"; + recv_data >> unk; + + WorldPacket data(SMSG_REALM_SPLIT, 4+4+split_date.size()+1); + data << unk; + data << uint32(0x00000000); // realm split state + // split states: + // 0x0 realm normal + // 0x1 realm split + // 0x2 realm split pending + data << split_date; + SendPacket(&data); + //sLog.outDebug("response sent %u", unk); +} + +void WorldSession::HandleFarSightOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_FAR_SIGHT"); + //recv_data.hexlike(); + + uint8 apply; + recv_data >> apply; + + switch(apply) + { + case 0: + sLog.outDebug("Player %u set vision to self", _player->GetGUIDLow()); + _player->SetSeer(_player); + break; + case 1: + sLog.outDebug("Added FarSight " I64FMT " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow()); + if (WorldObject *target = _player->GetViewpoint()) + _player->SetSeer(target); + else + sLog.outError("Player %s requests non-existing seer", _player->GetName()); + break; + default: + sLog.outDebug("Unhandled mode in CMSG_FAR_SIGHT: %u", apply); + return; + } + + GetPlayer()->UpdateVisibilityForPlayer(); +} + +void WorldSession::HandleSetTitleOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_SET_TITLE"); + + int32 title; + recv_data >> title; + + // -1 at none + if (title > 0 && title < MAX_TITLE_INDEX) + { + if (!GetPlayer()->HasTitle(title)) + return; + } + else + title = 0; + + GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title); +} + +void WorldSession::HandleTimeSyncResp(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_TIME_SYNC_RESP"); + + uint32 counter, clientTicks; + recv_data >> counter >> clientTicks; + + if (counter != _player->m_timeSyncCounter - 1) + sLog.outDebug("Wrong time sync counter from player %s (cheater?)", _player->GetName()); + + sLog.outDebug("Time sync received: counter %u, client ticks %u, time since last sync %u", counter, clientTicks, clientTicks - _player->m_timeSyncClient); + + uint32 ourTicks = clientTicks + (getMSTime() - _player->m_timeSyncServer); + + // diff should be small + sLog.outDebug("Our ticks: %u, diff %u, latency %u", ourTicks, ourTicks - clientTicks, GetLatency()); + + _player->m_timeSyncClient = clientTicks; +} + +void WorldSession::HandleResetInstancesOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: CMSG_RESET_INSTANCES"); + Group *pGroup = _player->GetGroup(); + if (pGroup) + { + if (pGroup->IsLeader(_player->GetGUID())) + { + pGroup->ResetInstances(INSTANCE_RESET_ALL, false, _player); + pGroup->ResetInstances(INSTANCE_RESET_ALL, true,_player); + } + } + else + { + _player->ResetInstances(INSTANCE_RESET_ALL, false); + _player->ResetInstances(INSTANCE_RESET_ALL, true); + } +} + +void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("MSG_SET_DUNGEON_DIFFICULTY"); + + uint32 mode; + recv_data >> mode; + + if (mode >= MAX_DUNGEON_DIFFICULTY) + { + sLog.outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode); + return; + } + + if (Difficulty(mode) == _player->GetDungeonDifficulty()) + return; + + // cannot reset while in an instance + Map *map = _player->GetMap(); + if (map && map->IsDungeon()) + { + sLog.outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); + return; + } + + if (_player->getLevel() < LEVELREQUIREMENT_HEROIC) + return; + + Group *pGroup = _player->GetGroup(); + if (pGroup) + { + if (pGroup->IsLeader(_player->GetGUID())) + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* pGroupGuy = itr->getSource(); + if (!pGroupGuy) + continue; + + if (!pGroupGuy->IsInMap(pGroupGuy)) + return; + + map = pGroupGuy->GetMap(); + if (map && map->IsNonRaidDungeon()) + { + sLog.outError("WorldSession::HandleSetDungeonDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); + return; + } + } + // the difficulty is set even if the instances can't be reset + //_player->SendDungeonDifficulty(true); + pGroup->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, _player); + pGroup->SetDungeonDifficulty(Difficulty(mode)); + } + } + else + { + _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false); + _player->SetDungeonDifficulty(Difficulty(mode)); + } +} + +void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("MSG_SET_RAID_DIFFICULTY"); + + uint32 mode; + recv_data >> mode; + + if (mode >= MAX_RAID_DIFFICULTY) + { + sLog.outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d sent an invalid instance mode %d!", _player->GetGUIDLow(), mode); + return; + } + + // cannot reset while in an instance + Map *map = _player->GetMap(); + if (map && map->IsDungeon()) + { + sLog.outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); + return; + } + + if (Difficulty(mode) == _player->GetRaidDifficulty()) + return; + + if (_player->getLevel() < LEVELREQUIREMENT_HEROIC) + return; + + Group *pGroup = _player->GetGroup(); + if (pGroup) + { + if (pGroup->IsLeader(_player->GetGUID())) + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* pGroupGuy = itr->getSource(); + if (!pGroupGuy) + continue; + + if (!pGroupGuy->IsInMap(pGroupGuy)) + return; + + map = pGroupGuy->GetMap(); + if (map && map->IsRaid()) + { + sLog.outError("WorldSession::HandleSetRaidDifficultyOpcode: player %d tried to reset the instance while inside!", _player->GetGUIDLow()); + return; + } + } + // the difficulty is set even if the instances can't be reset + //_player->SendDungeonDifficulty(true); + pGroup->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, _player); + pGroup->SetRaidDifficulty(Difficulty(mode)); + } + } + else + { + _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true); + _player->SetRaidDifficulty(Difficulty(mode)); + } +} + +void WorldSession::HandleCancelMountAuraOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: CMSG_CANCEL_MOUNT_AURA"); + + //If player is not mounted, so go out :) + if (!_player->IsMounted()) // not blizz like; no any messages on blizz + { + ChatHandler(this).SendSysMessage(LANG_CHAR_NON_MOUNTED); + return; + } + + if (_player->isInFlight()) // not blizz like; no any messages on blizz + { + ChatHandler(this).SendSysMessage(LANG_YOU_IN_FLIGHT); + return; + } + + _player->Unmount(); + _player->RemoveAurasByType(SPELL_AURA_MOUNTED); +} + +void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket & recv_data) +{ + // fly mode on/off + sLog.outDebug("WORLD: CMSG_MOVE_SET_CAN_FLY_ACK"); + //recv_data.hexlike(); + + uint64 guid; // guid - unused + if (!recv_data.readPackGUID(guid)) + return; + + recv_data.read_skip(); // unk + + MovementInfo movementInfo; + movementInfo.guid = guid; + ReadMovementInfo(recv_data, &movementInfo); + + recv_data.read_skip(); // unk2 + + _player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags(); +} + +void WorldSession::HandleRequestPetInfoOpcode(WorldPacket & /*recv_data */) +{ + /* + sLog.outDebug("WORLD: CMSG_REQUEST_PET_INFO"); + recv_data.hexlike(); + */ +} + +void WorldSession::HandleSetTaxiBenchmarkOpcode(WorldPacket & recv_data) +{ + uint8 mode; + recv_data >> mode; + + sLog.outDebug("Client used \"/timetest %d\" command", mode); +} + +void WorldSession::HandleQueryInspectAchievements(WorldPacket & recv_data) +{ + uint64 guid; + if (!recv_data.readPackGUID(guid)) + return; + + Player *player = objmgr.GetPlayer(guid); + if (!player) + return; + + player->GetAchievementMgr().SendRespondInspectAchievements(_player); +} + +void WorldSession::HandleWorldStateUITimerUpdate(WorldPacket& /*recv_data*/) +{ + // empty opcode + sLog.outDebug("WORLD: CMSG_WORLD_STATE_UI_TIMER_UPDATE"); + + WorldPacket data(SMSG_WORLD_STATE_UI_TIMER_UPDATE, 4); + data << uint32(time(NULL)); + SendPacket(&data); +} + +void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recv_data*/) +{ + // empty opcode + sLog.outDebug("WORLD: CMSG_READY_FOR_ACCOUNT_DATA_TIMES"); + + SendAccountDataTimes(GLOBAL_CACHE_MASK); +} + +void WorldSession::SendSetPhaseShift(uint32 PhaseShift) +{ + WorldPacket data(SMSG_SET_PHASE_SHIFT, 4); + data << uint32(PhaseShift); + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp new file mode 100644 index 00000000000..1148fe174fc --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp @@ -0,0 +1,746 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "Corpse.h" +#include "Player.h" +#include "Vehicle.h" +#include "SpellAuras.h" +#include "MapManager.h" +#include "Transports.h" +#include "BattleGround.h" +#include "WaypointMovementGenerator.h" +#include "InstanceSaveMgr.h" +#include "ObjectMgr.h" + +void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: got MSG_MOVE_WORLDPORT_ACK."); + HandleMoveWorldportAckOpcode(); +} + +void WorldSession::HandleMoveWorldportAckOpcode() +{ + // ignore unexpected far teleports + if (!GetPlayer()->IsBeingTeleportedFar()) + return; + + // get the teleport destination + WorldLocation &loc = GetPlayer()->GetTeleportDest(); + + // possible errors in the coordinate validity check + if (!MapManager::IsValidMapCoord(loc)) + { + LogoutPlayer(false); + return; + } + + // get the destination map entry, not the current one, this will fix homebind and reset greeting + MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId()); + InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.GetMapId()); + + // reset instance validity, except if going to an instance inside an instance + if (GetPlayer()->m_InstanceValid == false && !mInstance) + GetPlayer()->m_InstanceValid = true; + + GetPlayer()->SetSemaphoreTeleportFar(false); + + Map * oldMap = GetPlayer()->GetMap(); + assert(oldMap); + if (GetPlayer()->IsInWorld()) + { + sLog.outCrash("Player is still in world when teleported from map %u! to new map %u", oldMap->GetId(), loc.GetMapId()); + oldMap->Remove(GetPlayer(), false); + } + + // relocate the player to the teleport destination + Map * newMap = MapManager::Instance().CreateMap(loc.GetMapId(), GetPlayer(), 0); + // the CanEnter checks are done in TeleporTo but conditions may change + // while the player is in transit, for example the map may get full + if (!newMap || !newMap->CanEnter(GetPlayer())) + { + sLog.outError("Map %d could not be created for player %d, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUIDLow()); + GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); + return; + } + else + GetPlayer()->Relocate(&loc); + + GetPlayer()->ResetMap(); + GetPlayer()->SetMap(newMap); + + GetPlayer()->SendInitialPacketsBeforeAddToMap(); + if (!GetPlayer()->GetMap()->Add(GetPlayer())) + { + sLog.outError("WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.GetMapId()); + GetPlayer()->ResetMap(); + GetPlayer()->SetMap(oldMap); + GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); + return; + } + + // battleground state prepare (in case join to BG), at relogin/tele player not invited + // only add to bg group and object, if the player was invited (else he entered through command) + if (_player->InBattleGround()) + { + // cleanup setting if outdated + if (!mEntry->IsBattleGroundOrArena()) + { + // We're not in BG + _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); + // reset destination bg team + _player->SetBGTeam(0); + } + // join to bg case + else if (BattleGround *bg = _player->GetBattleGround()) + { + if (_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) + bg->AddPlayer(_player); + } + } + + GetPlayer()->SendInitialPacketsAfterAddToMap(); + + // flight fast teleport case + if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) + { + if (!_player->InBattleGround()) + { + // short preparations to continue flight + FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); + flight->Initialize(*GetPlayer()); + return; + } + + // battleground state prepare, stop flight + GetPlayer()->GetMotionMaster()->MovementExpired(); + GetPlayer()->CleanupAfterTaxiFlight(); + } + + // resurrect character at enter into instance where his corpse exist after add to map + Corpse *corpse = GetPlayer()->GetCorpse(); + if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) + { + if (mEntry->IsDungeon()) + { + GetPlayer()->ResurrectPlayer(0.5f,false); + GetPlayer()->SpawnCorpseBones(); + } + } + + bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattleGroundOrArena(); + if (mInstance) + { + Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid()); + if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID,diff)) + { + if (mapDiff->resetTime) + { + if (uint32 timeReset = sInstanceSaveManager.GetResetTimeFor(mEntry->MapID,diff)) + { + uint32 timeleft = timeReset - time(NULL); + GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft); + } + } + } + allowMount = mInstance->allowMount; + } + + // mount allow check + if (!allowMount) + _player->RemoveAurasByType(SPELL_AURA_MOUNTED); + + // update zone immediately, otherwise leave channel will cause crash in mtmap + uint32 newzone, newarea; + GetPlayer()->GetZoneAndAreaId(newzone, newarea); + GetPlayer()->UpdateZone(newzone, newarea); + + // honorless target + if (GetPlayer()->pvpInfo.inHostileArea) + GetPlayer()->CastSpell(GetPlayer(), 2479, true); + + // resummon pet + GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); + + //lets process all delayed operations on successful teleport + GetPlayer()->ProcessDelayedOperations(); +} + +void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) +{ + sLog.outDebug("MSG_MOVE_TELEPORT_ACK"); + uint64 guid; + + if (!recv_data.readPackGUID(guid)) + return; + + uint32 flags, time; + recv_data >> flags >> time; + DEBUG_LOG("Guid " UI64FMTD, guid); + DEBUG_LOG("Flags %u, time %u", flags, time/IN_MILISECONDS); + + Unit *mover = _player->m_mover; + Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; + + if (!plMover || !plMover->IsBeingTeleportedNear()) + return; + + if (guid != plMover->GetGUID()) + return; + + plMover->SetSemaphoreTeleportNear(false); + + uint32 old_zone = plMover->GetZoneId(); + + WorldLocation const& dest = plMover->GetTeleportDest(); + + plMover->SetPosition(dest,true); + + uint32 newzone, newarea; + plMover->GetZoneAndAreaId(newzone, newarea); + plMover->UpdateZone(newzone, newarea); + + // new zone + if (old_zone != newzone) + { + // honorless target + if (plMover->pvpInfo.inHostileArea) + plMover->CastSpell(plMover, 2479, true); + } + + // resummon pet + GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); + + //lets process all delayed operations on successful teleport + GetPlayer()->ProcessDelayedOperations(); +} + +void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) +{ + uint16 opcode = recv_data.GetOpcode(); + //sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); + recv_data.hexlike(); + + Unit *mover = _player->m_mover; + + assert(mover != NULL); // there must always be a mover + + Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; + + // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck + if (plMover && plMover->IsBeingTeleported()) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + + /* extract packet */ + uint64 guid; + + if (!recv_data.readPackGUID(guid)) + return; + + MovementInfo movementInfo; + movementInfo.guid = guid; + ReadMovementInfo(recv_data, &movementInfo); + /*----------------*/ + + /* if (recv_data.size() != recv_data.rpos()) + { + sLog.outError("MovementHandler: player %s (guid %d, account %u) sent a packet (opcode %u) that is " SIZEFMTD " bytes larger than it should be. Kicked as cheater.", _player->GetName(), _player->GetGUIDLow(), _player->GetSession()->GetAccountId(), recv_data.GetOpcode(), recv_data.size() - recv_data.rpos()); + KickPlayer();*/ + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + /* return; + }*/ + + if (!Trinity::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + + /* handle special cases */ + if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) + { + // transports size limited + // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) + if (movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + + if (!Trinity::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y + movementInfo.t_y, + movementInfo.z + movementInfo.t_z, movementInfo.o + movementInfo.t_o)) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + + // if we boarded a transport, add us to it + if (plMover && !plMover->GetTransport()) + { + // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list + for (MapManager::TransportSet::const_iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) + { + if ((*iter)->GetGUID() == movementInfo.t_guid) + { + plMover->m_transport = (*iter); + (*iter)->AddPassenger(plMover); + break; + } + } + } + + if (!mover->GetTransport() && !mover->GetVehicle()) + { + GameObject *go = mover->GetMap()->GetGameObject(movementInfo.t_guid); + if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) + movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; + } + } + else if (plMover && plMover->GetTransport()) // if we were on a transport, leave + { + plMover->m_transport->RemovePassenger(plMover); + plMover->m_transport = NULL; + movementInfo.t_x = 0.0f; + movementInfo.t_y = 0.0f; + movementInfo.t_z = 0.0f; + movementInfo.t_o = 0.0f; + movementInfo.t_time = 0; + movementInfo.t_seat = -1; + } + + // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). + if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight()) + plMover->HandleFall(movementInfo); + + if (plMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plMover->IsInWater()) + { + // now client not include swimming flag in case jumping under water + plMover->SetInWater(!plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z)); + } + + /*----------------------*/ + + /* process position-change */ + WorldPacket data(opcode, recv_data.size()); + movementInfo.time = getMSTime(); + movementInfo.guid = mover->GetGUID(); + WriteMovementInfo(&data, &movementInfo); + mover->SendMessageToSet(&data, _player); + + mover->m_movementInfo = movementInfo; + + // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() + if (mover->GetVehicle()) + { + mover->SetOrientation(movementInfo.o); + return; + } + + mover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + + if (plMover) // nothing is charmed, or player charmed + { + plMover->UpdateFallInformationIfNeed(movementInfo, opcode); + + if (movementInfo.z < -500.0f) + { + if (plMover->InBattleGround() + && plMover->GetBattleGround() + && plMover->GetBattleGround()->HandlePlayerUnderMap(_player)) + { + // do nothing, the handle already did if returned true + } + else + { + // NOTE: this is actually called many times while falling + // even after the player has been teleported away + // TODO: discard movement packets after the player is rooted + if (plMover->isAlive()) + { + plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); + // pl can be alive if GM/etc + if (!plMover->isAlive()) + { + // change the death state to CORPSE to prevent the death timer from + // starting in the next player update + plMover->KillPlayer(); + plMover->BuildPlayerRepop(); + } + } + + // cancel the death timer here if started + plMover->RepopAtGraveyard(); + } + } + } + /*else // creature charmed + { + if (mover->canFly()) + { + bool flying = mover->IsFlying(); + if (flying != ((mover->GetByteValue(UNIT_FIELD_BYTES_1, 3) & 0x02) ? true : false)) + mover->SetFlying(flying); + } + }*/ + + //sLog.outString("Receive Movement Packet %s:", opcodeTable[recv_data.GetOpcode()]); + //mover->OutMovementInfo(); +} + +void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) +{ + uint32 opcode = recv_data.GetOpcode(); + sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); + + /* extract packet */ + uint64 guid; + uint32 unk1; + float newspeed; + + if (!recv_data.readPackGUID(guid)) + return; + + // now can skip not our packet + if (_player->GetGUID() != guid) + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + + // continue parse packet + + recv_data >> unk1; // counter or moveEvent + + MovementInfo movementInfo; + movementInfo.guid = guid; + ReadMovementInfo(recv_data, &movementInfo); + + recv_data >> newspeed; + /*----------------*/ + + // client ACK send one packet for mounted/run case and need skip all except last from its + // in other cases anti-cheat check can be fail in false case + UnitMoveType move_type; + UnitMoveType force_move_type; + + static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" }; + + switch(opcode) + { + case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; + case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; + case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break; + case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; + case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break; + case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; + case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break; + case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break; + case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break; + default: + sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); + return; + } + + // skip all forced speed changes except last and unexpected + // in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both. + if (_player->m_forced_speed_changes[force_move_type] > 0) + { + --_player->m_forced_speed_changes[force_move_type]; + if (_player->m_forced_speed_changes[force_move_type] > 0) + return; + } + + if (!_player->GetTransport() && fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f) + { + if (_player->GetSpeed(move_type) > newspeed) // must be greater - just correct + { + sLog.outError("%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value", + move_type_name[move_type], _player->GetName(), _player->GetSpeed(move_type), newspeed); + _player->SetSpeed(move_type,_player->GetSpeedRate(move_type),true); + } + else // must be lesser - cheating + { + sLog.outBasic("Player %s from account id %u kicked for incorrect speed (must be %f instead %f)", + _player->GetName(),_player->GetSession()->GetAccountId(),_player->GetSpeed(move_type), newspeed); + _player->GetSession()->KickPlayer(); + } + } +} + +void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); + + uint64 guid; + recv_data >> guid; + + if (GetPlayer()->IsInWorld()) + if (Unit *mover = ObjectAccessor::GetUnit(*GetPlayer(), guid)) + { + GetPlayer()->SetMover(mover); + if (mover != GetPlayer() && mover->canFly()) + { + WorldPacket data(SMSG_MOVE_SET_CAN_FLY, 12); + data.append(mover->GetPackGUID()); + data << uint32(0); + SendPacket(&data); + } + } + else + { + sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " and should be " UI64FMTD, guid, _player->m_mover->GetGUID()); + GetPlayer()->SetMover(GetPlayer()); + } +} + +void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); + + uint64 old_mover_guid; + if (!recv_data.readPackGUID(old_mover_guid)) + return; + + /*if (_player->m_mover->GetGUID() == old_mover_guid) + { + sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid); + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + }*/ + + MovementInfo mi; + mi.guid = old_mover_guid; + ReadMovementInfo(recv_data, &mi); + + //ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo); + _player->m_movementInfo = mi; +} + +void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE"); + recv_data.hexlike(); + + uint64 vehicleGUID = _player->GetCharmGUID(); + + if (!vehicleGUID) // something wrong here... + { + recv_data.rpos(recv_data.wpos()); // prevent warnings spam + return; + } + + uint64 guid; + + if (!recv_data.readPackGUID(guid)) + return; + + MovementInfo mi; + mi.guid = guid; + ReadMovementInfo(recv_data, &mi); + + _player->m_movementInfo = mi; + + /* + ReadMovementInfo(recv_data, &_player->m_mover->m_movementInfo);*/ + _player->ExitVehicle(); +} + +void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE"); + recv_data.hexlike(); + + Unit* vehicle_base = GetPlayer()->GetVehicleBase(); + if (!vehicle_base) + return; + + switch (recv_data.GetOpcode()) + { + case CMSG_REQUEST_VEHICLE_PREV_SEAT: + GetPlayer()->ChangeSeat(-1, false); + break; + case CMSG_REQUEST_VEHICLE_NEXT_SEAT: + GetPlayer()->ChangeSeat(-1, true); + break; + case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: + { + uint64 guid; // current vehicle guid + if (!recv_data.readPackGUID(guid)) + return; + + ReadMovementInfo(recv_data, &vehicle_base->m_movementInfo); + + uint64 accessory; // accessory guid + if (!recv_data.readPackGUID(accessory)) + return; + + int8 seatId; + recv_data >> seatId; + + if (vehicle_base->GetGUID() != guid) + return; + + if (!accessory) + GetPlayer()->ChangeSeat(-1, seatId > 0); // prev/next + else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), accessory)) + { + if (Vehicle *vehicle = vehUnit->GetVehicleKit()) + if (vehicle->HasEmptySeat(seatId)) + GetPlayer()->EnterVehicle(vehicle, seatId); + } + } + break; + case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: + { + uint64 guid; // current vehicle guid + if (!recv_data.readPackGUID(guid)) + return; + + int8 seatId; + recv_data >> seatId; + + if (vehicle_base->GetGUID() == guid) + GetPlayer()->ChangeSeat(seatId); + else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), guid)) + if (Vehicle *vehicle = vehUnit->GetVehicleKit()) + if (vehicle->HasEmptySeat(seatId)) + GetPlayer()->EnterVehicle(vehicle, seatId); + } + break; + default: + break; + } +} + +void WorldSession::HandleEnterPlayerVehicle(WorldPacket &data) +{ + // Read guid + uint64 guid; + data >> guid; + + if (Player* pl=ObjectAccessor::FindPlayer(guid)) + { + if (!pl->GetVehicleKit()) + return; + if (!pl->IsInRaidWith(_player)) + return; + if (!pl->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + return; + _player->EnterVehicle(pl); + } +} + +void WorldSession::HandleEjectPasenger(WorldPacket &data) +{ + if (data.GetOpcode() == CMSG_EJECT_PASSENGER) + { + if (Vehicle* Vv= _player->GetVehicleKit()) + { + uint64 guid; + data >> guid; + if (Player* Pl=ObjectAccessor::FindPlayer(guid)) + Pl->ExitVehicle(); + } + } +} + +void WorldSession::HandleRequestVehicleExit(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_REQUEST_VEHICLE_EXIT"); + recv_data.hexlike(); + GetPlayer()->ExitVehicle(); +} + +void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/) +{ + //sLog.outDebug("WORLD: Recvd CMSG_MOUNTSPECIAL_ANIM"); + + WorldPacket data(SMSG_MOUNTSPECIAL_ANIM, 8); + data << uint64(GetPlayer()->GetGUID()); + + GetPlayer()->SendMessageToSet(&data, false); +} + +void WorldSession::HandleMoveKnockBackAck(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_MOVE_KNOCK_BACK_ACK"); + + uint64 guid; // guid - unused + if (!recv_data.readPackGUID(guid)) + return; + + recv_data.read_skip(); // unk + + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); +} + +void WorldSession::HandleMoveHoverAck(WorldPacket& recv_data) +{ + sLog.outDebug("CMSG_MOVE_HOVER_ACK"); + + uint64 guid; // guid - unused + if (!recv_data.readPackGUID(guid)) + return; + + recv_data.read_skip(); // unk + + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); + + recv_data.read_skip(); // unk2 +} + +void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recv_data) +{ + sLog.outDebug("CMSG_MOVE_WATER_WALK_ACK"); + + uint64 guid; // guid - unused + if (!recv_data.readPackGUID(guid)) + return; + + recv_data.read_skip(); // unk + + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); + + recv_data.read_skip(); // unk2 +} + +void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data) +{ + if (!_player->isAlive() || _player->isInCombat()) + return; + + uint64 summoner_guid; + bool agree; + recv_data >> summoner_guid; + recv_data >> agree; + + _player->SummonIfPossible(agree); +} + diff --git a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp new file mode 100644 index 00000000000..4e73fb381af --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp @@ -0,0 +1,869 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Player.h" +#include "GossipDef.h" +#include "UpdateMask.h" +#include "ObjectAccessor.h" +#include "Creature.h" +#include "Pet.h" +#include "BattleGroundMgr.h" +#include "BattleGround.h" +#include "Guild.h" +#include "ScriptMgr.h" + +void WorldSession::HandleTabardVendorActivateOpcode(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TABARDDESIGNER); + if (!unit) + { + sLog.outDebug("WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + SendTabardVendorActivate(guid); +} + +void WorldSession::SendTabardVendorActivate(uint64 guid) +{ + WorldPacket data(MSG_TABARDVENDOR_ACTIVATE, 8); + data << guid; + SendPacket(&data); +} + +void WorldSession::HandleBankerActivateOpcode(WorldPacket & recv_data) +{ + uint64 guid; + + sLog.outDebug("WORLD: Received CMSG_BANKER_ACTIVATE"); + + recv_data >> guid; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_BANKER); + if (!unit) + { + sLog.outDebug("WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + SendShowBank(guid); +} + +void WorldSession::SendShowBank(uint64 guid) +{ + WorldPacket data(SMSG_SHOW_BANK, 8); + data << guid; + SendPacket(&data); +} + +void WorldSession::HandleTrainerListOpcode(WorldPacket & recv_data) +{ + uint64 guid; + + recv_data >> guid; + SendTrainerList(guid); +} + +void WorldSession::SendTrainerList(uint64 guid) +{ + std::string str = GetTrinityString(LANG_NPC_TAINER_HELLO); + SendTrainerList(guid, str); +} + +void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle) +{ + sLog.outDebug("WORLD: SendTrainerList"); + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TRAINER); + if (!unit) + { + sLog.outDebug("WORLD: SendTrainerList - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + // trainer list loaded at check; + if (!unit->isCanTrainingOf(_player,true)) + return; + + CreatureInfo const *ci = unit->GetCreatureInfo(); + + if (!ci) + { + sLog.outDebug("WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!",GUID_LOPART(guid)); + return; + } + + TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); + if (!trainer_spells) + { + sLog.outDebug("WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", + GUID_LOPART(guid), unit->GetEntry()); + return; + } + + WorldPacket data(SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1); + data << guid; + data << uint32(trainer_spells->trainerType); + + size_t count_pos = data.wpos(); + data << uint32(trainer_spells->spellList.size()); + + // reputation discount + float fDiscountMod = _player->GetReputationPriceDiscount(unit); + bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; + + uint32 count = 0; + for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) + { + TrainerSpell const* tSpell = &itr->second; + + bool valid = true; + bool primary_prof_first_rank = false; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS ; ++i) + { + if (!tSpell->learnedSpell[i]) + continue; + if (!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell[i])) + { + valid = false; + break; + } + if (spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell[i])) + primary_prof_first_rank = true; + } + if (!valid) + continue; + + TrainerSpellState state = _player->GetTrainerSpellState(tSpell); + + data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) + data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); + data << uint32(floor(tSpell->spellCost * fDiscountMod)); + + data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0); + // primary prof. learn confirmation dialog + data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state + data << uint8(tSpell->reqLevel); + data << uint32(tSpell->reqSkill); + data << uint32(tSpell->reqSkillValue); + //prev + req or req + 0 + uint8 maxReq = 0; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS ; ++i) + { + if (!tSpell->learnedSpell[i]) + continue; + if (SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learnedSpell[i])) + { + if (chain_node->prev) + { + data << uint32(chain_node->prev); + ++maxReq; + } + } + if (maxReq == 3) + break; + SpellsRequiringSpellMapBounds spellsRequired = spellmgr.GetSpellsRequiredForSpellBounds(tSpell->learnedSpell[i]); + for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2) + { + data << uint32(itr2->second); + ++maxReq; + } + if (maxReq == 3) + break; + } + while (maxReq < 3) + { + data << uint32(0); + ++maxReq; + } + + ++count; + } + + data << strTitle; + + data.put(count_pos,count); + SendPacket(&data); +} + +void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recv_data) +{ + uint64 guid; + uint32 spellId = 0; + + recv_data >> guid >> spellId; + sLog.outDebug("WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId); + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); + if (!unit) + { + sLog.outDebug("WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + if (!unit->isCanTrainingOf(_player,true)) + return; + + // check present spell in trainer spell list + TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); + if (!trainer_spells) + return; + + // not found, cheat? + TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); + if (!trainer_spell) + return; + + // can't be learn, cheat? Or double learn with lags... + if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN) + return; + + // apply reputation discount + uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); + + // check money requirement + if (_player->GetMoney() < nSpellCost) + return; + + _player->ModifyMoney(-int32(nSpellCost)); + + WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer + data << uint64(guid); + data << uint32(0xB3); // index from SpellVisualKit.dbc + SendPacket(&data); + + data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player + data << uint64(_player->GetGUID()); + data << uint32(0x016A); // index from SpellVisualKit.dbc + SendPacket(&data); + + // learn explicitly or cast explicitly + if (trainer_spell->IsCastable()) + _player->CastSpell(_player,trainer_spell->spell,true); + else + _player->learnSpell(spellId, false); + + data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); + data << uint64(guid); + data << uint32(spellId); // should be same as in packet from client + SendPacket(&data); +} + +void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_GOSSIP_HELLO"); + + uint64 guid; + recv_data >> guid; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); + if (!unit) + { + sLog.outDebug("WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); + // remove fake death + //if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + // GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + if (unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider()) + { + unit->StopMoving(); + } + + // If spiritguide, no need for gossip menu, just put player into resurrect queue + if (unit->isSpiritGuide()) + { + BattleGround *bg = _player->GetBattleGround(); + if (bg) + { + bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID()); + sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID()); + return; + } + } + + if (!sScriptMgr.GossipHello(_player, unit)) + { +// _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID()); + _player->PrepareGossipMenu(unit, unit->GetCreatureInfo()->GossipMenuId, true); + _player->SendPreparedGossip(unit); + } +} + +/*void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION"); + + uint32 option; + uint32 unk; + uint64 guid; + std::string code = ""; + + recv_data >> guid >> unk >> option; + + if (_player->PlayerTalkClass->GossipOptionCoded(option)) + { + sLog.outDebug("reading string"); + recv_data >> code; + sLog.outDebug("string read: %s", code.c_str()); + } + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); + if (!unit) + { + sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + if (!code.empty()) + { + if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str())) + unit->OnGossipSelect (_player, option); + } + else + { + if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option))) + unit->OnGossipSelect (_player, option); + } +}*/ + +void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE"); + + uint64 guid; + + recv_data >> guid; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_SPIRITHEALER); + if (!unit) + { + sLog.outDebug("WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + SendSpiritResurrect(); +} + +void WorldSession::SendSpiritResurrect() +{ + _player->ResurrectPlayer(0.5f, true); + + _player->DurabilityLossAll(0.25f,true); + + // get corpse nearest graveyard + WorldSafeLocsEntry const *corpseGrave = NULL; + Corpse *corpse = _player->GetCorpse(); + if (corpse) + corpseGrave = objmgr.GetClosestGraveYard( + corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam()); + + // now can spawn bones + _player->SpawnCorpseBones(); + + // teleport to nearest from corpse graveyard, if different from nearest to player ghost + if (corpseGrave) + { + WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard( + _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam()); + + if (corpseGrave != ghostGrave) + _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation()); + // or update at original position + else + _player->UpdateObjectVisibility(); + } + // or update at original position + else + _player->UpdateObjectVisibility(); +} + +void WorldSession::HandleBinderActivateOpcode(WorldPacket & recv_data) +{ + uint64 npcGUID; + recv_data >> npcGUID; + + if (!GetPlayer()->IsInWorld() || !GetPlayer()->isAlive()) + return; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID,UNIT_NPC_FLAG_INNKEEPER); + if (!unit) + { + sLog.outDebug("WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + SendBindPoint(unit); +} + +void WorldSession::SendBindPoint(Creature *npc) +{ + // prevent set homebind to instances in any case + if (GetPlayer()->GetMap()->Instanceable()) + return; + + uint32 bindspell = 3286; + + // update sql homebind + CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", + _player->GetMapId(), _player->GetAreaId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow()); + _player->m_homebindMapId = _player->GetMapId(); + _player->m_homebindAreaId = _player->GetAreaId(); + _player->m_homebindX = _player->GetPositionX(); + _player->m_homebindY = _player->GetPositionY(); + _player->m_homebindZ = _player->GetPositionZ(); + + // send spell for homebinding (3286) + npc->CastSpell(_player, bindspell, true); + + WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, (8+4)); + data << uint64(npc->GetGUID()); + data << uint32(bindspell); + SendPacket(&data); + + _player->PlayerTalkClass->CloseGossip(); +} + +void WorldSession::HandleListStabledPetsOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS"); + uint64 npcGUID; + + recv_data >> npcGUID; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug("WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + // remove mounts this fix bug where getting pet from stable while mounted deletes pet. + if (GetPlayer()->IsMounted()) + GetPlayer()->RemoveAurasByType(SPELL_AURA_MOUNTED); + + SendStablePet(npcGUID); +} + +void WorldSession::SendStablePet(uint64 guid) +{ + sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send."); + + WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size + data << uint64 (guid); + + Pet *pet = _player->GetPet(); + + size_t wpos = data.wpos(); + data << uint8(0); // place holder for slot show number + + data << uint8(GetPlayer()->m_stableSlots); + + uint8 num = 0; // counter for place holder + + // not let move dead pet in slot + if (pet && pet->isAlive() && pet->getPetType() == HUNTER_PET) + { + data << uint32(pet->GetCharmInfo()->GetPetNumber()); + data << uint32(pet->GetEntry()); + data << uint32(pet->getLevel()); + data << pet->GetName(); // petname + data << uint8(1); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show) + ++num; + } + + // 0 1 2 3 4 + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT owner, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot", + _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); + + if (result) + { + do + { + Field *fields = result->Fetch(); + + data << uint32(fields[1].GetUInt32()); // petnumber + data << uint32(fields[2].GetUInt32()); // creature entry + data << uint32(fields[3].GetUInt32()); // level + data << fields[4].GetString(); // name + data << uint8(2); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show) + + ++num; + }while (result->NextRow()); + } + + data.put(wpos, num); // set real data to placeholder + SendPacket(&data); +} + +void WorldSession::HandleStablePet(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Recv CMSG_STABLE_PET"); + uint64 npcGUID; + + recv_data >> npcGUID; + + if (!GetPlayer()->isAlive()) + return; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug("WORLD: HandleStablePet - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + Pet *pet = _player->GetPet(); + + // can't place in stable dead pet + if (!pet||!pet->isAlive()||pet->getPetType() != HUNTER_PET) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + uint32 free_slot = 1; + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot ", + _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); + if (result) + { + do + { + Field *fields = result->Fetch(); + + uint32 slot = fields[1].GetUInt32(); + + // slots ordered in query, and if not equal then free + if (slot != free_slot) + break; + + // this slot not free, skip + ++free_slot; + }while (result->NextRow()); + } + + WorldPacket data(SMSG_STABLE_RESULT, 1); + if (free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots) + { + _player->RemovePet(pet,PetSaveMode(free_slot)); + data << uint8(0x08); + } + else + data << uint8(0x06); + + SendPacket(&data); +} + +void WorldSession::HandleUnstablePet(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET."); + uint64 npcGUID; + uint32 petnumber; + + recv_data >> npcGUID >> petnumber; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug("WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + uint32 creature_id = 0; + + { + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot >='%u' AND slot <= '%u'", + _player->GetGUIDLow(),petnumber,PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); + if (result) + { + Field *fields = result->Fetch(); + creature_id = fields[0].GetUInt32(); + } + } + + if (!creature_id) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(creature_id); + if (!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets())) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + Pet* pet = _player->GetPet(); + if (pet && pet->isAlive()) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + // delete dead pet + if (pet) + _player->RemovePet(pet,PET_SAVE_AS_DELETED); + + Pet *newpet = new Pet(_player, HUNTER_PET); + if (!newpet->LoadPetFromDB(_player,creature_id,petnumber)) + { + delete newpet; + newpet = NULL; + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x09); + SendPacket(&data); +} + +void WorldSession::HandleBuyStableSlot(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT."); + uint64 npcGUID; + + recv_data >> npcGUID; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug("WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + WorldPacket data(SMSG_STABLE_RESULT, 200); + + if (GetPlayer()->m_stableSlots < MAX_PET_STABLES) + { + StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1); + if (_player->GetMoney() >= SlotPrice->Price) + { + ++GetPlayer()->m_stableSlots; + _player->ModifyMoney(-int32(SlotPrice->Price)); + data << uint8(0x0A); // success buy + } + else + data << uint8(0x06); + } + else + data << uint8(0x06); + + SendPacket(&data); +} + +void WorldSession::HandleStableRevivePet(WorldPacket &/* recv_data */) +{ + sLog.outDebug("HandleStableRevivePet: Not implemented"); +} + +void WorldSession::HandleStableSwapPet(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET."); + uint64 npcGUID; + uint32 pet_number; + + recv_data >> npcGUID >> pet_number; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + if (!unit) + { + sLog.outDebug("WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size + + Pet* pet = _player->GetPet(); + + if (!pet || pet->getPetType() != HUNTER_PET) + return; + + // find swapped pet slot in stable + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'", + _player->GetGUIDLow(),pet_number); + if (!result) + return; + + Field *fields = result->Fetch(); + + uint32 slot = fields[0].GetUInt32(); + uint32 creature_id = fields[1].GetUInt32(); + + if (!creature_id) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(creature_id); + if (!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets())) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + // move alive pet to slot or delete dead pet + _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED); + + // summon unstabled pet + Pet *newpet = new Pet(_player); + if (!newpet->LoadPetFromDB(_player,creature_id,pet_number)) + { + delete newpet; + data << uint8(0x06); + } + else + data << uint8(0x09); + + SendPacket(&data); +} + +void WorldSession::HandleRepairItemOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_REPAIR_ITEM"); + + uint64 npcGUID, itemGUID; + uint8 guildBank; // new in 2.3.2, bool that means from guild bank money + + recv_data >> npcGUID >> itemGUID >> guildBank; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_REPAIR); + if (!unit) + { + sLog.outDebug("WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGUID))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + // reputation discount + float discountMod = _player->GetReputationPriceDiscount(unit); + + uint32 TotalCost = 0; + if (itemGUID) + { + sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID)); + + Item* item = _player->GetItemByGuid(itemGUID); + + if (item) + TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false); + } + else + { + sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID)); + + TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false); + } + if (guildBank) + { + uint32 GuildId = _player->GetGuildId(); + if (!GuildId) + return; + Guild *pGuild = objmgr.GetGuildById(GuildId); + if (!pGuild) + return; + pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost); + pGuild->SendMoneyInfo(this, _player->GetGUIDLow()); + } +} + diff --git a/src/server/game/Server/Protocol/Handlers/NPCHandler.h b/src/server/game/Server/Protocol/Handlers/NPCHandler.h new file mode 100644 index 00000000000..98e2fd218d3 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/NPCHandler.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __NPCHANDLER_H +#define __NPCHANDLER_H + +// 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 +#if defined(__GNUC__) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +struct PageText +{ + uint32 Page_ID; + char * Text; + + uint32 Next_Page; +}; + +// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform +#if defined(__GNUC__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +struct QEmote +{ + uint32 _Emote; + uint32 _Delay; +}; + +struct GossipTextOption +{ + std::string Text_0; + std::string Text_1; + uint32 Language; + float Probability; + QEmote Emotes[3]; +}; + +struct GossipText +{ + GossipTextOption Options[8]; +}; + +struct PageTextLocale +{ + std::vector Text; +}; + +struct NpcTextLocale +{ + NpcTextLocale() { Text_0.resize(8); Text_1.resize(8); } + + std::vector > Text_0; + std::vector > Text_1; +}; +#endif + diff --git a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp new file mode 100644 index 00000000000..34e6845762b --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp @@ -0,0 +1,813 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Spell.h" +#include "ObjectAccessor.h" +#include "CreatureAI.h" +#include "Util.h" +#include "Pet.h" +#include "World.h" + +void WorldSession::HandleDismissCritter(WorldPacket &recv_data) +{ + uint64 guid; + recv_data >> guid; + + sLog.outDebug("WORLD: Received CMSG_DISMISS_CRITTER for GUID %u", guid); + + Unit* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); + + if (!pet) + { + sLog.outError("Vanitypet %u does not exist", uint32(GUID_LOPART(guid))); + return; + } + + if (_player->GetCritterGUID() == pet->GetGUID()) + { + if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isSummon()) + pet->ToTempSummon()->UnSummon(); + } +} + +void WorldSession::HandlePetAction(WorldPacket & recv_data) +{ + uint64 guid1; + uint32 data; + uint64 guid2; + recv_data >> guid1; //pet guid + recv_data >> data; + recv_data >> guid2; //tag guid + + uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data); + uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); //delete = 0x07 CastSpell = C1 + + // used also for charmed creature + Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); + sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), uint32(flag), spellid, uint32(GUID_LOPART(guid2))); + if (!pet) + { + sLog.outError("Pet %u not exist.", uint32(GUID_LOPART(guid1))); + return; + } + + if (pet != GetPlayer()->GetFirstControlled()) + { + sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName()); + return; + } + + if (!pet->isAlive()) + return; + + //TODO: allow control charmed player? + if (pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) + return; + + if (GetPlayer()->m_Controlled.size() == 1) + HandlePetActionHelper(pet, guid1, spellid, flag, guid2); + else + { + //If a pet is dismissed, m_Controlled will change + std::vector controlled; + for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr) + if ((*itr)->GetEntry() == pet->GetEntry() && (*itr)->isAlive()) + controlled.push_back(*itr); + for (std::vector::iterator itr = controlled.begin(); itr != controlled.end(); ++itr) + HandlePetActionHelper(*itr, guid1, spellid, flag, guid2); + } +} + +void WorldSession::HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid, uint16 flag, uint64 guid2) +{ + CharmInfo *charmInfo = pet->GetCharmInfo(); + if (!charmInfo) + { + sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); + return; + } + + switch(flag) + { + case ACT_COMMAND: //0x07 + switch(spellid) + { + case COMMAND_STAY: //flat=1792 //STAY + pet->AttackStop(); + pet->InterruptNonMeleeSpells(false); + pet->GetMotionMaster()->MoveIdle(); + charmInfo->SetCommandState(COMMAND_STAY); + + charmInfo->SetIsCommandAttack(false); + charmInfo->SetIsAtStay(true); + charmInfo->SetIsFollowing(false); + charmInfo->SetIsReturning(false); + charmInfo->SaveStayPosition(); + break; + case COMMAND_FOLLOW: //spellid=1792 //FOLLOW + pet->AttackStop(); + pet->InterruptNonMeleeSpells(false); + pet->GetMotionMaster()->MoveFollow(_player,PET_FOLLOW_DIST,pet->GetFollowAngle()); + charmInfo->SetCommandState(COMMAND_FOLLOW); + + charmInfo->SetIsCommandAttack(false); + charmInfo->SetIsAtStay(false); + charmInfo->SetIsReturning(true); + charmInfo->SetIsFollowing(false); + break; + case COMMAND_ATTACK: //spellid=1792 //ATTACK + { + // Can't attack if owner is pacified + if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY)) + { + //pet->SendPetCastFail(spellid, SPELL_FAILED_PACIFIED); + //TODO: Send proper error message to client + return; + } + + // only place where pet can be player + Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, guid2); + if (!TargetUnit) + return; + + if (!pet->canAttack(TargetUnit)) + return; + + // Not let attack through obstructions + if (sWorld.getConfig(CONFIG_PET_LOS)) + { + + if (!pet->IsWithinLOSInMap(TargetUnit)) + return; + + } + + pet->clearUnitState(UNIT_STAT_FOLLOW); + // This is true if pet has no target or has target but targets differs. + if (pet->getVictim() != TargetUnit || (pet->getVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack())) + { + if (pet->getVictim()) + pet->AttackStop(); + + if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature()->IsAIEnabled) + { + charmInfo->SetIsCommandAttack(true); + charmInfo->SetIsAtStay(false); + charmInfo->SetIsFollowing(false); + charmInfo->SetIsReturning(false); + + pet->ToCreature()->AI()->AttackStart(TargetUnit); + + //10% chance to play special pet attack talk, else growl + if (pet->ToCreature()->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) + pet->SendPetTalk((uint32)PET_TALK_ATTACK); + else + { + // 90% chance for pet and 100% chance for charmed creature + pet->SendPetAIReaction(guid1); + } + } + else // charmed player + { + if (pet->getVictim() && pet->getVictim() != TargetUnit) + pet->AttackStop(); + + charmInfo->SetIsCommandAttack(true); + charmInfo->SetIsAtStay(false); + charmInfo->SetIsFollowing(false); + charmInfo->SetIsReturning(false); + + pet->Attack(TargetUnit,true); + pet->SendPetAIReaction(guid1); + } + } + break; + } + case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) + if (pet->GetCharmerGUID() == GetPlayer()->GetGUID()) + _player->StopCastingCharm(); + else if (pet->GetOwnerGUID() == GetPlayer()->GetGUID()) + { + assert(pet->GetTypeId() == TYPEID_UNIT); + if (pet->isPet()) + { + if (((Pet*)pet)->getPetType() == HUNTER_PET) + GetPlayer()->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); + else + //dismissing a summoned pet is like killing them (this prevents returning a soulshard...) + pet->setDeathState(CORPSE); + } + else if (pet->HasUnitTypeMask(UNIT_MASK_MINION)) + { + ((Minion*)pet)->UnSummon(); + } + } + break; + default: + sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); + } + break; + case ACT_REACTION: // 0x6 + switch(spellid) + { + case REACT_PASSIVE: //passive + pet->AttackStop(); + + case REACT_DEFENSIVE: //recovery + case REACT_AGGRESSIVE: //activete + if (pet->GetTypeId() == TYPEID_UNIT) + pet->ToCreature()->SetReactState(ReactStates(spellid)); + break; + } + break; + case ACT_DISABLED: // 0x81 spell (disabled), ignore + case ACT_PASSIVE: // 0x01 + case ACT_ENABLED: // 0xC1 spell + { + Unit* unit_target = NULL; + + if (guid2) + unit_target = ObjectAccessor::GetUnit(*_player,guid2); + + // do not cast unknown spells + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); + if (!spellInfo) + { + sLog.outError("WORLD: unknown PET spell id %i", spellid); + return; + } + + if (spellInfo->StartRecoveryCategory > 0) + if (pet->ToCreature()->GetGlobalCooldown() > 0) + return; + + for (uint32 i = 0; i < 3; ++i) + { + if (spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_SRC || spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENEMY_DST || spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_DYNOBJ_ENEMY) + return; + } + + // do not cast not learned spells + if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) + return; + + // Clear the flags as if owner clicked 'attack'. AI will reset them + // after AttackStart, even if spell failed + if (pet->GetCharmInfo()) + { + pet->GetCharmInfo()->SetIsAtStay(false); + pet->GetCharmInfo()->SetIsCommandAttack(true); + pet->GetCharmInfo()->SetIsReturning(false); + pet->GetCharmInfo()->SetIsFollowing(false); + } + + Spell *spell = new Spell(pet, spellInfo, false); + + SpellCastResult result = spell->CheckPetCast(unit_target); + + //auto turn to target unless possessed + if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed() && !pet->IsVehicle()) + { + if (unit_target) + { + pet->SetInFront(unit_target); + if (unit_target->GetTypeId() == TYPEID_PLAYER) + pet->SendUpdateToPlayer((Player*)unit_target); + } + else if (Unit *unit_target2 = spell->m_targets.getUnitTarget()) + { + pet->SetInFront(unit_target2); + if (unit_target2->GetTypeId() == TYPEID_PLAYER) + pet->SendUpdateToPlayer((Player*)unit_target2); + } + if (Unit* powner = pet->GetCharmerOrOwner()) + if (powner->GetTypeId() == TYPEID_PLAYER) + pet->SendUpdateToPlayer(powner->ToPlayer()); + result = SPELL_CAST_OK; + } + + if (result == SPELL_CAST_OK) + { + pet->ToCreature()->AddCreatureSpellCooldown(spellid); + + unit_target = spell->m_targets.getUnitTarget(); + + //10% chance to play special pet attack talk, else growl + //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell + if (pet->ToCreature()->isPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) + pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + else + { + pet->SendPetAIReaction(guid1); + } + + if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->isPossessed() && !pet->IsVehicle()) + { + // This is true if pet has no target or has target but targets differs. + if (pet->getVictim() != unit_target) + { + if (pet->getVictim()) + pet->AttackStop(); + pet->GetMotionMaster()->Clear(); + if (pet->ToCreature()->IsAIEnabled) + pet->ToCreature()->AI()->AttackStart(unit_target); + } + } + + spell->prepare(&(spell->m_targets)); + } + else + { + if (pet->isPossessed() || pet->IsVehicle()) + Spell::SendCastResult(GetPlayer(),spellInfo,0,result); + else + pet->SendPetCastFail(spellid, result); + + if (!pet->ToCreature()->HasSpellCooldown(spellid)) + GetPlayer()->SendClearCooldown(spellid, pet); + + spell->finish(false); + delete spell; + + // reset specific flags in case of spell fail. AI will reset other flags + if (pet->GetCharmInfo()) + pet->GetCharmInfo()->SetIsCommandAttack(false); + } + break; + } + default: + sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); + } +} + +void WorldSession::HandlePetNameQuery(WorldPacket & recv_data) +{ + sLog.outDetail("HandlePetNameQuery. CMSG_PET_NAME_QUERY"); + + uint32 petnumber; + uint64 petguid; + + recv_data >> petnumber; + recv_data >> petguid; + + SendPetNameQuery(petguid,petnumber); +} + +void WorldSession::SendPetNameQuery(uint64 petguid, uint32 petnumber) +{ + Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); + if (!pet) + { + WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+7+1)); + data << uint32(petnumber); + data << "Unknown"; + data << uint32(0); + data << uint8(0); + _player->GetSession()->SendPacket(&data); + return; + } + + std::string name = pet->GetName(); + + WorldPacket data(SMSG_PET_NAME_QUERY_RESPONSE, (4+4+name.size()+1)); + data << uint32(petnumber); + data << name.c_str(); + data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); + + if (pet->isPet() && ((Pet*)pet)->GetDeclinedNames()) + { + data << uint8(1); + for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + data << ((Pet*)pet)->GetDeclinedNames()->name[i]; + } + else + data << uint8(0); + + _player->GetSession()->SendPacket(&data); +} + +void WorldSession::HandlePetSetAction(WorldPacket & recv_data) +{ + sLog.outDetail("HandlePetSetAction. CMSG_PET_SET_ACTION"); + + uint64 petguid; + uint8 count; + + recv_data >> petguid; + + Unit* pet = ObjectAccessor::GetUnit(*_player, petguid); + + if (!pet || pet != _player->GetFirstControlled()) + { + sLog.outError("HandlePetSetAction: Unknown pet or pet owner."); + return; + } + + CharmInfo *charmInfo = pet->GetCharmInfo(); + if (!charmInfo) + { + sLog.outError("WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); + return; + } + + count = (recv_data.size() == 24) ? 2 : 1; + + uint32 position[2]; + uint32 data[2]; + bool move_command = false; + + for (uint8 i = 0; i < count; ++i) + { + recv_data >> position[i]; + recv_data >> data[i]; + + uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); + + //ignore invalid position + if (position[i] >= MAX_UNIT_ACTION_BAR_INDEX) + return; + + // in the normal case, command and reaction buttons can only be moved, not removed + // at moving count == 2, at removing count == 1 + // ignore attempt to remove command|reaction buttons (not possible at normal case) + if (act_state == ACT_COMMAND || act_state == ACT_REACTION) + { + if (count == 1) + return; + + move_command = true; + } + } + + // check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness) + if (move_command) + { + uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]); + if (act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION) + { + uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]); + UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]); + if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() || + act_state_0 != actionEntry_1->GetType()) + return; + } + + uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]); + if (act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION) + { + uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]); + UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]); + if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() || + act_state_1 != actionEntry_0->GetType()) + return; + } + } + + for (uint8 i = 0; i < count; ++i) + { + uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]); + uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); + + sLog.outDetail("Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position[i], spell_id, uint32(act_state)); + + //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add + if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) + { + //sign for autocast + if (act_state == ACT_ENABLED && spell_id) + { + if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet()) + ((Pet*)pet)->ToggleAutocast(spell_id, true); + else + charmInfo->ToggleCreatureAutocast(spell_id, true); + } + //sign for no/turn off autocast + else if (act_state == ACT_DISABLED && spell_id) + { + if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->isPet()) + ((Pet*)pet)->ToggleAutocast(spell_id, false); + else + charmInfo->ToggleCreatureAutocast(spell_id, false); + + } + + charmInfo->SetActionBar(position[i],spell_id,ActiveStates(act_state)); + } + } +} + +void WorldSession::HandlePetRename(WorldPacket & recv_data) +{ + sLog.outDetail("HandlePetRename. CMSG_PET_RENAME"); + + uint64 petguid; + uint8 isdeclined; + + std::string name; + DeclinedName declinedname; + + recv_data >> petguid; + recv_data >> name; + recv_data >> isdeclined; + + Pet* pet = ObjectAccessor::GetPet(petguid); + // check it! + if (!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || + !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || + pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) + return; + + PetNameInvalidReason res = ObjectMgr::CheckPetName(name); + if (res != PET_NAME_SUCCESS) + { + SendPetNameInvalid(res, name, NULL); + return; + } + + if (objmgr.IsReservedName(name)) + { + SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); + return; + } + + pet->SetName(name); + + Unit *owner = pet->GetOwner(); + if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) + owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); + + pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); + + if (isdeclined) + { + for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + { + recv_data >> declinedname.name[i]; + } + + std::wstring wname; + Utf8toWStr(name, wname); + if (!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname,0),declinedname)) + { + SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); + return; + } + } + + CharacterDatabase.BeginTransaction(); + if (isdeclined) + { + for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + CharacterDatabase.escape_string(declinedname.name[i]); + CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); + CharacterDatabase.PExecute("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", + pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); + } + + CharacterDatabase.escape_string(name); + CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); + CharacterDatabase.CommitTransaction(); + + pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); +} + +void WorldSession::HandlePetAbandon(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; //pet guid + sLog.outDetail("HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid)); + + if (!_player->IsInWorld()) + return; + + // pet/charmed + Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); + if (pet) + { + if (pet->isPet()) + { + if (pet->GetGUID() == _player->GetPetGUID()) + { + uint32 feelty = pet->GetPower(POWER_HAPPINESS); + pet->SetPower(POWER_HAPPINESS ,(feelty-50000) > 0 ?(feelty-50000) : 0); + } + + _player->RemovePet((Pet*)pet,PET_SAVE_AS_DELETED); + } + else if (pet->GetGUID() == _player->GetCharmGUID()) + _player->StopCastingCharm(); + } +} + +void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) +{ + sLog.outDetail("CMSG_PET_SPELL_AUTOCAST"); + uint64 guid; + uint32 spellid; + uint8 state; //1 for on, 0 for off + recvPacket >> guid >> spellid >> state; + + if (!_player->GetGuardianPet() && !_player->GetCharm()) + return; + + if (ObjectAccessor::FindPlayer(guid)) + return; + + Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); + + if (!pet || (pet != _player->GetGuardianPet() && pet != _player->GetCharm())) + { + sLog.outError("HandlePetSpellAutocastOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName()); + return; + } + + // do not add not learned spells/ passive spells + if (!pet->HasSpell(spellid) || IsAutocastableSpell(spellid)) + return; + + CharmInfo *charmInfo = pet->GetCharmInfo(); + if (!charmInfo) + { + sLog.outError("WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); + return; + } + + if (pet->isPet()) + ((Pet*)pet)->ToggleAutocast(spellid, state); + else + pet->GetCharmInfo()->ToggleCreatureAutocast(spellid, state); + + charmInfo->SetSpellAutocast(spellid,state); +} + +void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) +{ + sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); + + uint64 guid; + uint32 spellid; + uint8 cast_count; + uint8 unk_flags; // flags (if 0x02 - some additional data are received) + + recvPacket >> guid >> cast_count >> spellid >> unk_flags; + + sLog.outDebug("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags); + + // This opcode is also sent from charmed and possessed units (players and creatures) + if (!_player->GetGuardianPet() && !_player->GetCharm()) + return; + + Unit* caster = ObjectAccessor::GetUnit(*_player, guid); + + if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm())) + { + sLog.outError("HandlePetCastSpellOpcode: Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName()); + return; + } + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); + if (!spellInfo) + { + sLog.outError("WORLD: unknown PET spell id %i", spellid); + return; + } + + if (spellInfo->StartRecoveryCategory > 0) //Check if spell is affected by GCD + if (caster->GetTypeId() == TYPEID_UNIT && caster->ToCreature()->GetGlobalCooldown() > 0) + { + caster->SendPetCastFail(spellid, SPELL_FAILED_NOT_READY); + return; + } + + // do not cast not learned spells + if (!caster->HasSpell(spellid) || IsPassiveSpell(spellid)) + return; + + SpellCastTargets targets; + if (!targets.read(&recvPacket,caster)) + return; + + caster->clearUnitState(UNIT_STAT_FOLLOW); + + Spell *spell = new Spell(caster, spellInfo, spellid == 33395); // water elemental can cast freeze as triggered + spell->m_cast_count = spellid == 33395 ? 0 : cast_count; // probably pending spell cast + spell->m_targets = targets; + + // TODO: need to check victim? + SpellCastResult result; + if (caster->m_movedPlayer) + result = spell->CheckPetCast(caster->m_movedPlayer->GetSelectedUnit()); + else + result = spell->CheckPetCast(NULL); + if (result == SPELL_CAST_OK) + { + if (caster->GetTypeId() == TYPEID_UNIT) + { + Creature* pet = caster->ToCreature(); + pet->AddCreatureSpellCooldown(spellid); + if (pet->isPet()) + { + Pet* p = (Pet*)pet; + // 10% chance to play special pet attack talk, else growl + // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell + if (p->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) + pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + else + pet->SendPetAIReaction(guid); + } + } + + spell->prepare(&(spell->m_targets)); + } + else + { + caster->SendPetCastFail(spellid, result); + if (caster->GetTypeId() == TYPEID_PLAYER) + { + if (!caster->ToPlayer()->HasSpellCooldown(spellid)) + GetPlayer()->SendClearCooldown(spellid, caster); + } + else + { + if (!caster->ToCreature()->HasSpellCooldown(spellid)) + GetPlayer()->SendClearCooldown(spellid, caster); + } + + spell->finish(false); + delete spell; + } +} + +void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName) +{ + WorldPacket data(SMSG_PET_NAME_INVALID, 4 + name.size() + 1 + 1); + data << uint32(error); + data << name; + if (declinedName) + { + data << uint8(1); + for (uint32 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + data << declinedName->name[i]; + } + else + data << uint8(0); + SendPacket(&data); +} + +void WorldSession::HandlePetLearnTalent(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_PET_LEARN_TALENT"); + + uint64 guid; + uint32 talent_id, requested_rank; + recv_data >> guid >> talent_id >> requested_rank; + + _player->LearnPetTalent(guid, talent_id, requested_rank); + _player->SendTalentsInfoData(true); +} + +void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket & recv_data) +{ + sLog.outDebug("CMSG_LEARN_PREVIEW_TALENTS_PET"); + + uint64 guid; + recv_data >> guid; + + uint32 talentsCount; + recv_data >> talentsCount; + + uint32 talentId, talentRank; + + for (uint32 i = 0; i < talentsCount; ++i) + { + recv_data >> talentId >> talentRank; + + _player->LearnPetTalent(guid, talentId, talentRank); + } + + _player->SendTalentsInfoData(true); +} diff --git a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp new file mode 100644 index 00000000000..7f578c22656 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp @@ -0,0 +1,938 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Guild.h" +#include "ArenaTeam.h" +#include "GossipDef.h" +#include "SocialMgr.h" + +/*enum PetitionType // dbc data +{ + PETITION_TYPE_GUILD = 1, + PETITION_TYPE_ARENA_TEAM = 3 +};*/ + +// Charters ID in item_template +#define GUILD_CHARTER 5863 +#define GUILD_CHARTER_COST 1000 // 10 S +#define ARENA_TEAM_CHARTER_2v2 23560 +#define ARENA_TEAM_CHARTER_2v2_COST 800000 // 80 G +#define ARENA_TEAM_CHARTER_3v3 23561 +#define ARENA_TEAM_CHARTER_3v3_COST 1200000 // 120 G +#define ARENA_TEAM_CHARTER_5v5 23562 +#define ARENA_TEAM_CHARTER_5v5_COST 2000000 // 200 G + +void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("Received opcode CMSG_PETITION_BUY"); + recv_data.hexlike(); + + uint64 guidNPC; + uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client + std::string name; + + recv_data >> guidNPC; // NPC GUID + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data >> name; // name + recv_data.read_skip(); // some string + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + recv_data.read_skip(); // 0 + + for (int i = 0; i < 10; ++i) + recv_data.read_skip(); + + recv_data >> clientIndex; // index + recv_data.read_skip(); // 0 + + sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str()); + + // prevent cheating + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC,UNIT_NPC_FLAG_PETITIONER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC)); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + uint32 charterid = 0; + uint32 cost = 0; + uint32 type = 0; + if (pCreature->isTabardDesigner()) + { + // if tabard designer, then trying to buy a guild charter. + // do not let if already in guild. + if (_player->GetGuildId()) + return; + + charterid = GUILD_CHARTER; + cost = GUILD_CHARTER_COST; + type = 9; + } + else + { + // TODO: find correct opcode + if (_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + return; + } + + switch(clientIndex) // arenaSlot+1 as received from client (1 from 3 case) + { + case 1: + charterid = ARENA_TEAM_CHARTER_2v2; + cost = ARENA_TEAM_CHARTER_2v2_COST; + type = 2; // 2v2 + break; + case 2: + charterid = ARENA_TEAM_CHARTER_3v3; + cost = ARENA_TEAM_CHARTER_3v3_COST; + type = 3; // 3v3 + break; + case 3: + charterid = ARENA_TEAM_CHARTER_5v5; + cost = ARENA_TEAM_CHARTER_5v5_COST; + type = 5; // 5v5 + break; + default: + sLog.outDebug("unknown selection at buy arena petition: %u", clientIndex); + return; + } + + if (_player->GetArenaTeamId(clientIndex - 1)) // arenaSlot+1 as received from client + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); + return; + } + } + + if (type == 9) + { + if (objmgr.GetGuildByName(name)) + { + SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S); + return; + } + if (objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) + { + SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_INVALID); + return; + } + } + else + { + if (objmgr.GetArenaTeamByName(name)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); + return; + } + if (objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); + return; + } + } + + ItemPrototype const *pProto = objmgr.GetItemPrototype(charterid); + if (!pProto) + { + _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0); + return; + } + + if (_player->GetMoney() < cost) + { //player hasn't got enough money + _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0); + return; + } + + ItemPosCountVec dest; + uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount); + if (msg != EQUIP_ERR_OK) + { + _player->SendBuyError(msg, pCreature, charterid, 0); + return; + } + + _player->ModifyMoney(-(int32)cost); + Item *charter = _player->StoreNewItem(dest, charterid, true); + if (!charter) + return; + + charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow()); + // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id + // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item) + charter->SetState(ITEM_CHANGED, _player); + _player->SendNewItem(charter, 1, true, false); + + // a petition is invalid, if both the owner and the type matches + // we checked above, if this player is in an arenateam, so this must be + // datacorruption + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type); + + std::ostringstream ssInvalidPetitionGUIDs; + + if (result) + { + do + { + Field *fields = result->Fetch(); + ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , "; + } while (result->NextRow()); + } + + // delete petitions with the same guid as this one + ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'"; + + sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); + CharacterDatabase.escape_string(name); + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); + CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); + CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')", + _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type); + CharacterDatabase.CommitTransaction(); +} + +void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) +{ + // ok + sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES"); + //recv_data.hexlike(); + + uint8 signs = 0; + uint64 petitionguid; + recv_data >> petitionguid; // petition guid + + // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?) + uint32 petitionguid_low = GUID_LOPART(petitionguid); + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low); + if (!result) + { + sLog.outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); + return; + } + Field *fields = result->Fetch(); + uint32 type = fields[0].GetUInt32(); + + // if guild petition and has guild => error, return; + if (type == 9 && _player->GetGuildId()) + return; + + result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low); + + // result == NULL also correct in case no sign yet + if (result) + signs = result->GetRowCount(); + + sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low); + + WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12)); + data << uint64(petitionguid); // petition guid + data << uint64(_player->GetGUID()); // owner guid + data << uint32(petitionguid_low); // guild guid (in mangos always same as GUID_LOPART(petitionguid) + data << uint8(signs); // sign's count + + for (uint8 i = 1; i <= signs; ++i) + { + Field *fields2 = result->Fetch(); + uint64 plguid = fields2[0].GetUInt64(); + + data << uint64(plguid); // Player GUID + data << (uint32)0; // there 0 ... + + result->NextRow(); + } + SendPacket(&data); +} + +void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("Received opcode CMSG_PETITION_QUERY"); // ok + //recv_data.hexlike(); + + uint32 guildguid; + uint64 petitionguid; + recv_data >> guildguid; // in Trinity always same as GUID_LOPART(petitionguid) + recv_data >> petitionguid; // petition guid + sLog.outDebug("CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid); + + SendPetitionQueryOpcode(petitionguid); +} + +void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) +{ + uint64 ownerguid = 0; + uint32 type; + std::string name = "NO_NAME_FOR_GUID"; + uint8 signs = 0; + + QueryResult_AutoPtr result = CharacterDatabase.PQuery( + "SELECT ownerguid, name, " + " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " + " type " + "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); + + if (result) + { + Field* fields = result->Fetch(); + ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + name = fields[1].GetCppString(); + signs = fields[2].GetUInt8(); + type = fields[3].GetUInt32(); + } + else + { + sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); + return; + } + + WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*12+2+10)); + data << uint32(GUID_LOPART(petitionguid)); // guild/team guid (in Trinity always same as GUID_LOPART(petition guid) + data << uint64(ownerguid); // charter owner guid + data << name; // name (guild/arena team) + data << uint8(0); // some string + if (type == 9) + { + data << uint32(9); + data << uint32(9); + data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition + } + else + { + data << uint32(type-1); + data << uint32(type-1); + data << uint32(type); // bypass client - side limitation, a different value is needed here for each petition + } + data << uint32(0); // 5 + data << uint32(0); // 6 + data << uint32(0); // 7 + data << uint32(0); // 8 + data << uint16(0); // 9 2 bytes field + data << uint32(0); // 10 + data << uint32(0); // 11 + data << uint32(0); // 13 count of next strings? + + for (int i = 0; i < 10; ++i) + data << uint8(0); // some string + + data << uint32(0); // 14 + + if (type == 9) + data << uint32(0); // 15 0 - guild, 1 - arena team + else + data << uint32(1); + + SendPacket(&data); +} + +void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("Received opcode MSG_PETITION_RENAME"); // ok + //recv_data.hexlike(); + + uint64 petitionguid; + uint32 type; + std::string newname; + + recv_data >> petitionguid; // guid + recv_data >> newname; // new name + + Item *item = _player->GetItemByGuid(petitionguid); + if (!item) + return; + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + + if (result) + { + Field* fields = result->Fetch(); + type = fields[0].GetUInt32(); + } + else + { + sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); + return; + } + + if (type == 9) + { + if (objmgr.GetGuildByName(newname)) + { + SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_GUILD_NAME_EXISTS_S); + return; + } + if (objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) + { + SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_GUILD_NAME_INVALID); + return; + } + } + else + { + if (objmgr.GetArenaTeamByName(newname)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S); + return; + } + if (objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID); + return; + } + } + + std::string db_newname = newname; + CharacterDatabase.escape_string(db_newname); + CharacterDatabase.PExecute("UPDATE petition SET name = '%s' WHERE petitionguid = '%u'", + db_newname.c_str(), GUID_LOPART(petitionguid)); + + sLog.outDebug("Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionguid), newname.c_str()); + WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1)); + data << uint64(petitionguid); + data << newname; + SendPacket(&data); +} + +void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); // ok + //recv_data.hexlike(); + + Field *fields; + uint64 petitionguid; + uint8 unk; + recv_data >> petitionguid; // petition guid + recv_data >> unk; + + QueryResult_AutoPtr result = CharacterDatabase.PQuery( + "SELECT ownerguid, " + " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " + " type " + "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); + + if (!result) + { + sLog.outError("Petition %u is not found for player %u %s", GUID_LOPART(petitionguid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName()); + return; + } + + fields = result->Fetch(); + uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + uint8 signs = fields[1].GetUInt8(); + uint32 type = fields[2].GetUInt32(); + + uint32 plguidlo = _player->GetGUIDLow(); + if (GUID_LOPART(ownerguid) == plguidlo) + return; + + // not let enemies sign guild charter + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid)) + { + if (type != 9) + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + else + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_NOT_ALLIED); + return; + } + + if (type != 9) + { + if (_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); + return; + } + + uint8 slot = ArenaTeam::GetSlotByType(type); + if (slot >= MAX_ARENA_SLOT) + return; + + if (_player->GetArenaTeamId(slot)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); + return; + } + + if (_player->GetArenaTeamIdInvited()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + return; + } + } + else + { + if (_player->GetGuildId()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_IN_GUILD_S); + return; + } + if (_player->GetGuildIdInvited()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S); + return; + } + } + + if (++signs > type) // client signs maximum + return; + + //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account + //not allow sign another player from already sign player account + result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid)); + + if (result) + { + WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); + data << uint64(petitionguid); + data << uint64(_player->GetGUID()); + data << (uint32)PETITION_SIGN_ALREADY_SIGNED; + + // close at signer side + SendPacket(&data); + + // update for owner if online + if (Player *owner = objmgr.GetPlayer(ownerguid)) + owner->GetSession()->SendPacket(&data); + return; + } + + CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId()); + + sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId()); + + WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); + data << uint64(petitionguid); + data << uint64(_player->GetGUID()); + data << uint32(PETITION_SIGN_OK); + + // close at signer side + SendPacket(&data); + + // update signs count on charter, required testing... + //Item *item = _player->GetItemByGuid(petitionguid)); + //if (item) + // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); + + // update for owner if online + if (Player *owner = objmgr.GetPlayer(ownerguid)) + owner->GetSession()->SendPacket(&data); +} + +void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); // ok + //recv_data.hexlike(); + + uint64 petitionguid; + uint64 ownerguid; + recv_data >> petitionguid; // petition guid + sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if (!result) + return; + + Field *fields = result->Fetch(); + ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + + Player *owner = objmgr.GetPlayer(ownerguid); + if (owner) // petition owner online + { + WorldPacket data(MSG_PETITION_DECLINE, 8); + data << uint64(_player->GetGUID()); + owner->GetSession()->SendPacket(&data); + } +} + +void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); // ok + //recv_data.hexlike(); + + uint8 signs = 0; + uint64 petitionguid, plguid; + uint32 type, junk; + Player *player; + recv_data >> junk; // this is not petition type! + recv_data >> petitionguid; // petition guid + recv_data >> plguid; // player guid + + player = ObjectAccessor::FindPlayer(plguid); + if (!player) + return; + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if (!result) + return; + + Field *fields = result->Fetch(); + type = fields[0].GetUInt32(); + + sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); + + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam()) + { + if (type != 9) + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + else + SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_NOT_ALLIED); + return; + } + + if (type != 9) + { + if (player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + // player is too low level to join an arena team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_TARGET_TOO_LOW_S); + return; + } + + uint8 slot = ArenaTeam::GetSlotByType(type); + if (slot >= MAX_ARENA_SLOT) + return; + + if (player->GetArenaTeamId(slot)) + { + // player is already in an arena team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S); + return; + } + + if (player->GetArenaTeamIdInvited()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + return; + } + } + else + { + if (player->GetGuildId()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_IN_GUILD_S); + return; + } + + if (player->GetGuildIdInvited()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S); + return; + } + } + + result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + // result == NULL also correct charter without signs + if (result) + signs = result->GetRowCount(); + + WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12)); + data << uint64(petitionguid); // petition guid + data << uint64(_player->GetGUID()); // owner guid + data << uint32(GUID_LOPART(petitionguid)); // guild guid (in mangos always same as GUID_LOPART(petition guid) + data << uint8(signs); // sign's count + + for (uint8 i = 1; i <= signs; ++i) + { + Field *fields2 = result->Fetch(); + plguid = fields2[0].GetUInt64(); + + data << uint64(plguid); // Player GUID + data << (uint32)0; // there 0 ... + + result->NextRow(); + } + + player->GetSession()->SendPacket(&data); +} + +void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok + //recv_data.hexlike(); + + WorldPacket data; + uint64 petitionguid; + + uint32 ownerguidlo; + uint32 type; + std::string name; + + recv_data >> petitionguid; + + sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); + + // data + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if (result) + { + Field *fields = result->Fetch(); + ownerguidlo = fields[0].GetUInt32(); + name = fields[1].GetCppString(); + type = fields[2].GetUInt32(); + } + else + { + sLog.outError("petition table has broken data!"); + return; + } + + if (type == 9) + { + if (_player->GetGuildId()) + { + data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); + data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild + _player->GetSession()->SendPacket(&data); + return; + } + } + else + { + uint8 slot = ArenaTeam::GetSlotByType(type); + if (slot >= MAX_ARENA_SLOT) + return; + + if (_player->GetArenaTeamId(slot)) + { + //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); + //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild + //_player->GetSession()->SendPacket(&data); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); + return; + } + } + + if (_player->GetGUIDLow() != ownerguidlo) + return; + + // signs + uint8 signs; + result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if (result) + signs = result->GetRowCount(); + else + signs = 0; + + uint32 count; + //if (signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS)) + if (type == 9) + count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS); + else + count = type-1; + if (signs < count) + { + data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); + data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures... + SendPacket(&data); + return; + } + + if (type == 9) + { + if (objmgr.GetGuildByName(name)) + { + SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S); + return; + } + } + else + { + if (objmgr.GetArenaTeamByName(name)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); + return; + } + } + + // and at last charter item check + Item *item = _player->GetItemByGuid(petitionguid); + if (!item) + return; + + // OK! + + // delete charter item + _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true); + + if (type == 9) // create guild + { + Guild* guild = new Guild; + if (!guild->Create(_player, name)) + { + delete guild; + return; + } + + // register guild and add guildmaster + objmgr.AddGuild(guild); + + // add members + for (uint8 i = 0; i < signs; ++i) + { + Field* fields = result->Fetch(); + guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank()); + result->NextRow(); + } + } + else // or arena team + { + ArenaTeam* at = new ArenaTeam; + if (!at->Create(_player->GetGUID(), type, name)) + { + sLog.outError("PetitionsHandler: arena team create failed."); + delete at; + return; + } + + uint32 icon, iconcolor, border, bordercolor, backgroud; + recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor; + + at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor); + + // register team and add captain + objmgr.AddArenaTeam(at); + sLog.outDebug("PetitonsHandler: arena team added to objmrg"); + + // add members + for (uint8 i = 0; i < signs; ++i) + { + Field* fields = result->Fetch(); + uint64 memberGUID = fields[0].GetUInt64(); + sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID)); + at->AddMember(memberGUID); + result->NextRow(); + } + } + + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + CharacterDatabase.CommitTransaction(); + + // created + sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid)); + + data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); + data << (uint32)PETITION_TURN_OK; + SendPacket(&data); +} + +void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("Received CMSG_PETITION_SHOWLIST"); // ok + //recv_data.hexlike(); + + uint64 guid; + recv_data >> guid; + + SendPetitionShowList(guid); +} + +void WorldSession::SendPetitionShowList(uint64 guid) +{ + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER); + if (!pCreature) + { + sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + uint8 count = 0; + if (pCreature->isTabardDesigner()) + count = 1; + else + count = 3; + + WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6); + data << guid; // npc guid + data << count; // count + if (count == 1) + { + data << uint32(1); // index + data << uint32(GUILD_CHARTER); // charter entry + data << uint32(16161); // charter display id + data << uint32(GUILD_CHARTER_COST); // charter cost + data << uint32(0); // unknown + data << uint32(9); // required signs? + } + else + { + // 2v2 + data << uint32(1); // index + data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry + data << uint32(16161); // charter display id + data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost + data << uint32(2); // unknown + data << uint32(2); // required signs? + // 3v3 + data << uint32(2); // index + data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry + data << uint32(16161); // charter display id + data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost + data << uint32(3); // unknown + data << uint32(3); // required signs? + // 5v5 + data << uint32(3); // index + data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry + data << uint32(16161); // charter display id + data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost + data << uint32(5); // unknown + data << uint32(5); // required signs? + } + //for (uint8 i = 0; i < count; ++i) + //{ + // data << uint32(i); // index + // data << uint32(GUILD_CHARTER); // charter entry + // data << uint32(16161); // charter display id + // data << uint32(GUILD_CHARTER_COST+i); // charter cost + // data << uint32(0); // unknown + // data << uint32(9); // required signs? + //} + SendPacket(&data); + sLog.outDebug("Sent SMSG_PETITION_SHOWLIST"); +} diff --git a/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp b/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp new file mode 100644 index 00000000000..1067ad49bc4 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/QueryHandler.cpp @@ -0,0 +1,539 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Language.h" +#include "Database/DatabaseEnv.h" +#include "Database/DatabaseImpl.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "UpdateMask.h" +#include "NPCHandler.h" +#include "Pet.h" +#include "MapManager.h" + +void WorldSession::SendNameQueryOpcode(Player *p) +{ + if (!p) + return; + // guess size + WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+10)); + data.append(p->GetPackGUID()); // player guid + data << uint8(0); // added in 3.1 + data << p->GetName(); // played name + data << uint8(0); // realm name for cross realm BG usage + data << uint8(p->getRace()); + data << uint8(p->getGender()); + data << uint8(p->getClass()); + if (DeclinedName const* names = p->GetDeclinedNames()) + { + data << uint8(1); // is declined + for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + data << names->name[i]; + } + else + data << uint8(0); // is not declined + + SendPacket(&data); +} + +void WorldSession::SendNameQueryOpcodeFromDB(uint64 guid) +{ + CharacterDatabase.AsyncPQuery(&WorldSession::SendNameQueryOpcodeFromDBCallBack, GetAccountId(), + !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ? + // ------- Query Without Declined Names -------- + // 0 1 2 3 4 + "SELECT guid, name, race, gender, class " + "FROM characters WHERE guid = '%u'" + : + // --------- Query With Declined Names --------- + // 0 1 2 3 4 + "SELECT characters.guid, name, race, gender, class, " + // 5 6 7 8 9 + "genitive, dative, accusative, instrumental, prepositional " + "FROM characters LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid WHERE characters.guid = '%u'", + GUID_LOPART(guid)); +} + +void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, uint32 accountId) +{ + if (!result) + return; + + WorldSession * session = sWorld.FindSession(accountId); + if (!session) + return; + + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + std::string name = fields[1].GetCppString(); + uint8 pRace = 0, pGender = 0, pClass = 0; + if (name == "") + name = session->GetTrinityString(LANG_NON_EXIST_CHARACTER); + else + { + pRace = fields[2].GetUInt8(); + pGender = fields[3].GetUInt8(); + pClass = fields[4].GetUInt8(); + } + // guess size + WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+1+10)); + data.appendPackGUID(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); + data << uint8(0); // added in 3.1 + data << name; + data << uint8(0); // realm name for cross realm BG usage + data << uint8(pRace); // race + data << uint8(pGender); // gender + data << uint8(pClass); // class + + // if the first declined name field (5) is empty, the rest must be too + if (sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && fields[5].GetCppString() != "") + { + data << uint8(1); // is declined + for (int i = 5; i < MAX_DECLINED_NAME_CASES+5; ++i) + data << fields[i].GetCppString(); + } + else + data << uint8(0); // is not declined + + session->SendPacket(&data); +} + +void WorldSession::HandleNameQueryOpcode(WorldPacket & recv_data) +{ + uint64 guid; + + recv_data >> guid; + + Player *pChar = objmgr.GetPlayer(guid); + + if (pChar) + SendNameQueryOpcode(pChar); + else + SendNameQueryOpcodeFromDB(guid); +} + +void WorldSession::HandleQueryTimeOpcode(WorldPacket & /*recv_data*/) +{ + SendQueryTimeResponse(); +} + +void WorldSession::SendQueryTimeResponse() +{ + WorldPacket data(SMSG_QUERY_TIME_RESPONSE, 4+4); + data << uint32(time(NULL)); + data << uint32(sWorld.GetNextDailyQuestsResetTime() - time(NULL)); + SendPacket(&data); +} + +/// Only _static_ data send in this packet !!! +void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) +{ + uint32 entry; + recv_data >> entry; + uint64 guid; + recv_data >> guid; + + CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); + if (ci) + { + + std::string Name, SubName; + Name = ci->Name; + SubName = ci->SubName; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + CreatureLocale const *cl = objmgr.GetCreatureLocale(entry); + if (cl) + { + if (cl->Name.size() > size_t(loc_idx) && !cl->Name[loc_idx].empty()) + Name = cl->Name[loc_idx]; + if (cl->SubName.size() > size_t(loc_idx) && !cl->SubName[loc_idx].empty()) + SubName = cl->SubName[loc_idx]; + } + } + sLog.outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name, entry); + // guess size + WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); + data << uint32(entry); // creature entry + data << Name; + data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty + data << SubName; + data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 + data << uint32(ci->type_flags); // flags + data << uint32(ci->type); // CreatureType.dbc + data << uint32(ci->family); // CreatureFamily.dbc + data << uint32(ci->rank); // Creature Rank (elite, boss, etc) + data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit + data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit + data << uint32(ci->Modelid1); // Modelid1 + data << uint32(ci->Modelid2); // Modelid2 + data << uint32(ci->Modelid3); // Modelid3 + data << uint32(ci->Modelid4); // Modelid4 + data << float(ci->ModHealth); // dmg/hp modifier + data << float(ci->ModMana); // dmg/mana modifier + data << uint8(ci->RacialLeader); + for (uint32 i = 0; i < 6; ++i) + data << uint32(ci->questItems[i]); // itemId[6], quest drop + data << uint32(ci->movementId); // CreatureMovementInfo.dbc + SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); + } + else + { + sLog.outDebug("WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)", + GUID_LOPART(guid), entry); + WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 4); + data << uint32(entry | 0x80000000); + SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE"); + } +} + +/// Only _static_ data send in this packet !!! +void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) +{ + uint32 entryID; + recv_data >> entryID; + uint64 guid; + recv_data >> guid; + + const GameObjectInfo *info = objmgr.GetGameObjectInfo(entryID); + if (info) + { + std::string Name; + std::string IconName; + std::string CastBarCaption; + + Name = info->name; + IconName = info->IconName; + CastBarCaption = info->castBarCaption; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + GameObjectLocale const *gl = objmgr.GetGameObjectLocale(entryID); + if (gl) + { + if (gl->Name.size() > size_t(loc_idx) && !gl->Name[loc_idx].empty()) + Name = gl->Name[loc_idx]; + if (gl->CastBarCaption.size() > size_t(loc_idx) && !gl->CastBarCaption[loc_idx].empty()) + CastBarCaption = gl->CastBarCaption[loc_idx]; + } + } + sLog.outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name, entryID); + WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150); + data << uint32(entryID); + data << uint32(info->type); + data << uint32(info->displayId); + data << Name; + data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4 + data << IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword) + data << CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting") + data << info->unk1; // 2.0.3, string + data.append(info->raw.data, 24); + data << float(info->size); // go size + for (uint32 i = 0; i < 6; ++i) + data << uint32(info->questItems[i]); // itemId[6], quest drop + SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); + } + else + { + sLog.outDebug("WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)", + GUID_LOPART(guid), entryID); + WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 4); + data << uint32(entryID | 0x80000000); + SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); + } +} + +void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDetail("WORLD: Received MSG_CORPSE_QUERY"); + + Corpse *corpse = GetPlayer()->GetCorpse(); + + if (!corpse) + { + WorldPacket data(MSG_CORPSE_QUERY, 1); + data << uint8(0); // corpse not found + SendPacket(&data); + return; + } + + uint32 mapid = corpse->GetMapId(); + float x = corpse->GetPositionX(); + float y = corpse->GetPositionY(); + float z = corpse->GetPositionZ(); + uint32 corpsemapid = mapid; + + // if corpse at different map + if (mapid != _player->GetMapId()) + { + // search entrance map for proper show entrance + if (MapEntry const* corpseMapEntry = sMapStore.LookupEntry(mapid)) + { + if (corpseMapEntry->IsDungeon() && corpseMapEntry->entrance_map >= 0) + { + // if corpse map have entrance + if (Map const* entranceMap = MapManager::Instance().CreateBaseMap(corpseMapEntry->entrance_map)) + { + mapid = corpseMapEntry->entrance_map; + x = corpseMapEntry->entrance_x; + y = corpseMapEntry->entrance_y; + z = entranceMap->GetHeight(x, y, MAX_HEIGHT); + } + } + } + } + + WorldPacket data(MSG_CORPSE_QUERY, 1+(6*4)); + data << uint8(1); // corpse found + data << int32(mapid); + data << float(x); + data << float(y); + data << float(z); + data << int32(corpsemapid); + data << uint32(0); // unknown + SendPacket(&data); +} + +void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) +{ + uint32 textID; + uint64 guid; + + recv_data >> textID; + sLog.outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); + + recv_data >> guid; + GetPlayer()->SetUInt64Value(UNIT_FIELD_TARGET, guid); + + GossipText const* pGossip = objmgr.GetGossipText(textID); + + WorldPacket data(SMSG_NPC_TEXT_UPDATE, 100); // guess size + data << textID; + + if (!pGossip) + { + for (uint32 i = 0; i < 8; ++i) + { + data << float(0); + data << "Greetings $N"; + data << "Greetings $N"; + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + } + } + else + { + std::string Text_0[8], Text_1[8]; + for (int i = 0; i < 8; ++i) + { + Text_0[i]=pGossip->Options[i].Text_0; + Text_1[i]=pGossip->Options[i].Text_1; + } + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + NpcTextLocale const *nl = objmgr.GetNpcTextLocale(textID); + if (nl) + { + for (int i = 0; i < 8; ++i) + { + if (nl->Text_0[i].size() > size_t(loc_idx) && !nl->Text_0[i][loc_idx].empty()) + Text_0[i]=nl->Text_0[i][loc_idx]; + if (nl->Text_1[i].size() > size_t(loc_idx) && !nl->Text_1[i][loc_idx].empty()) + Text_1[i]=nl->Text_1[i][loc_idx]; + } + } + } + + for (int i = 0; i < 8; ++i) + { + data << pGossip->Options[i].Probability; + + if (Text_0[i].empty()) + data << Text_1[i]; + else + data << Text_0[i]; + + if (Text_1[i].empty()) + data << Text_0[i]; + else + data << Text_1[i]; + + data << pGossip->Options[i].Language; + + for (int j = 0; j < 3; ++j) + { + data << pGossip->Options[i].Emotes[j]._Delay; + data << pGossip->Options[i].Emotes[j]._Emote; + } + } + } + + SendPacket(&data); + + sLog.outDebug("WORLD: Sent SMSG_NPC_TEXT_UPDATE"); +} + +void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data) +{ + sLog.outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY"); + recv_data.hexlike(); + + uint32 pageID; + recv_data >> pageID; + recv_data.read_skip(); // guid + + while (pageID) + { + PageText const *pPage = sPageTextStore.LookupEntry(pageID); + // guess size + WorldPacket data(SMSG_PAGE_TEXT_QUERY_RESPONSE, 50); + data << pageID; + + if (!pPage) + { + data << "Item page missing."; + data << uint32(0); + pageID = 0; + } + else + { + std::string Text = pPage->Text; + + int loc_idx = GetSessionDbLocaleIndex(); + if (loc_idx >= 0) + { + PageTextLocale const *pl = objmgr.GetPageTextLocale(pageID); + if (pl) + { + if (pl->Text.size() > size_t(loc_idx) && !pl->Text[loc_idx].empty()) + Text = pl->Text[loc_idx]; + } + } + + data << Text; + data << uint32(pPage->Next_Page); + pageID = pPage->Next_Page; + } + SendPacket(&data); + + sLog.outDebug("WORLD: Sent SMSG_PAGE_TEXT_QUERY_RESPONSE"); + } +} + +void WorldSession::HandleCorpseMapPositionQuery(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Recv CMSG_CORPSE_MAP_POSITION_QUERY"); + + uint32 unk; + recv_data >> unk; + + WorldPacket data(SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE, 4+4+4+4); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + SendPacket(&data); +} + +void WorldSession::HandleQuestPOIQuery(WorldPacket& recv_data) +{ + uint32 count; + recv_data >> count; // quest count, max=25 + + if (count >= MAX_QUEST_LOG_SIZE) + return; + + WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4+(4+4)*count); + data << uint32(count); // count + + for (int i = 0; i < count; ++i) + { + uint32 questId; + recv_data >> questId; // quest id + + bool questOk = false; + + uint16 questSlot = _player->FindQuestSlot(questId); + + if (questSlot != MAX_QUEST_LOG_SIZE) + questOk =_player->GetQuestSlotQuestId(questSlot) == questId; + + if (questOk) + { + QuestPOIVector const *POI = objmgr.GetQuestPOIVector(questId); + + if (POI) + { + data << uint32(questId); // quest ID + data << uint32(POI->size()); // POI count + + for (QuestPOIVector::const_iterator itr = POI->begin(); itr != POI->end(); ++itr) + { + data << uint32(itr->Id); // POI index + data << int32(itr->ObjectiveIndex); // objective index + data << uint32(itr->MapId); // mapid + data << uint32(itr->AreaId); // areaid + data << uint32(itr->Unk2); // unknown + data << uint32(itr->Unk3); // unknown + data << uint32(itr->Unk4); // unknown + data << uint32(itr->points.size()); // POI points count + + for (std::vector::const_iterator itr2 = itr->points.begin(); itr2 != itr->points.end(); ++itr2) + { + data << int32(itr2->x); // POI point x + data << int32(itr2->y); // POI point y + } + } + } + else + { + data << uint32(questId); // quest ID + data << uint32(0); // POI count + } + } + else + { + data << uint32(questId); // quest ID + data << uint32(0); // POI count + } + } + + SendPacket(&data); +} \ No newline at end of file diff --git a/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp b/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp new file mode 100644 index 00000000000..8043f5ed149 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/QuestHandler.cpp @@ -0,0 +1,721 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "World.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "GossipDef.h" +#include "QuestDef.h" +#include "ObjectAccessor.h" +#include "Group.h" +#include "BattleGround.h" +#include "BattleGroundAV.h" +#include "ScriptMgr.h" + +void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + uint8 questStatus = DIALOG_STATUS_NONE; + uint8 defstatus = DIALOG_STATUS_NONE; + + Object* questgiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + if (!questgiver) + { + sLog.outDetail("Error in CMSG_QUESTGIVER_STATUS_QUERY, called for not found questgiver (Typeid: %u GUID: %u)",GuidHigh2TypeId(GUID_HIPART(guid)),GUID_LOPART(guid)); + return; + } + + switch(questgiver->GetTypeId()) + { + case TYPEID_UNIT: + { + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u",uint32(GUID_LOPART(guid))); + Creature* cr_questgiver=questgiver->ToCreature(); + if (!cr_questgiver->IsHostileTo(_player)) // not show quest status to enemies + { + questStatus = sScriptMgr.NPCDialogStatus(_player, cr_questgiver); + if (questStatus > 6) + questStatus = getDialogStatus(_player, cr_questgiver, defstatus); + } + break; + } + case TYPEID_GAMEOBJECT: + { + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u",uint32(GUID_LOPART(guid))); + GameObject* go_questgiver=(GameObject*)questgiver; + questStatus = sScriptMgr.GODialogStatus(_player, go_questgiver); + if (questStatus > 6) + questStatus = getDialogStatus(_player, go_questgiver, defstatus); + break; + } + default: + sLog.outError("QuestGiver called for unexpected type %u", questgiver->GetTypeId()); + break; + } + + //inform client about status of quest + _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid); +} + +void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + + sLog.outDebug ("WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); + + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_NONE); + if (!pCreature) + { + sLog.outDebug ("WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", + GUID_LOPART(guid)); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + // Stop the npc if moving + pCreature->StopMoving(); + + if (sScriptMgr.GossipHello(_player, pCreature)) + return; + + _player->PrepareGossipMenu(pCreature, pCreature->GetCreatureInfo()->GossipMenuId, true); + _player->SendPreparedGossip(pCreature); +} + +void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket & recv_data) +{ + uint64 guid; + uint32 quest; + uint32 unk1; + recv_data >> guid >> quest >> unk1; + + if (!GetPlayer()->isAlive()) + return; + + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), quest, unk1); + + Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT|TYPEMASK_ITEM|TYPEMASK_PLAYER); + + // no or incorrect quest giver + if (!pObject + || (pObject->GetTypeId() != TYPEID_PLAYER && !pObject->hasQuest(quest)) + || (pObject->GetTypeId() == TYPEID_PLAYER && !pObject->ToPlayer()->CanShareQuest(quest)) +) + { + _player->PlayerTalkClass->CloseGossip(); + _player->SetDivider(0); + return; + } + + Quest const* qInfo = objmgr.GetQuestTemplate(quest); + if (qInfo) + { + // prevent cheating + if (!GetPlayer()->CanTakeQuest(qInfo,true)) + { + _player->PlayerTalkClass->CloseGossip(); + _player->SetDivider(0); + return; + } + + if (_player->GetDivider() != 0) + { + Player *pPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); + if (pPlayer) + { + pPlayer->SendPushToPartyResponse(_player, QUEST_PARTY_MSG_ACCEPT_QUEST); + _player->SetDivider(0); + } + } + + if (_player->CanAddQuest(qInfo, true)) + { + _player->AddQuest(qInfo, pObject); + + if (qInfo->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) + { + if (Group* pGroup = _player->GetGroup()) + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* pPlayer = itr->getSource(); + + if (!pPlayer || pPlayer == _player) // not self + continue; + + if (pPlayer->CanTakeQuest(qInfo, true)) + { + pPlayer->SetDivider(_player->GetGUID()); + + //need confirmation that any gossip window will close + pPlayer->PlayerTalkClass->CloseGossip(); + + _player->SendQuestConfirmAccept(qInfo, pPlayer); + } + } + } + } + + if (_player->CanCompleteQuest(quest)) + _player->CompleteQuest(quest); + + switch(pObject->GetTypeId()) + { + case TYPEID_UNIT: + sScriptMgr.QuestAccept(_player, (pObject->ToCreature()), qInfo); + break; + case TYPEID_ITEM: + case TYPEID_CONTAINER: + { + sScriptMgr.ItemQuestAccept(_player, ((Item*)pObject), qInfo); + + // destroy not required for quest finish quest starting item + bool destroyItem = true; + for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) + { + if ((qInfo->ReqItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetProto()->MaxCount > 0)) + { + destroyItem = false; + break; + } + } + + if (destroyItem) + _player->DestroyItem(((Item*)pObject)->GetBagSlot(),((Item*)pObject)->GetSlot(),true); + + break; + } + case TYPEID_GAMEOBJECT: + sScriptMgr.GOQuestAccept(_player, ((GameObject*)pObject), qInfo); + break; + } + _player->PlayerTalkClass->CloseGossip(); + + if (qInfo->GetSrcSpell() > 0) + _player->CastSpell(_player, qInfo->GetSrcSpell(), true); + + return; + } + } + + _player->PlayerTalkClass->CloseGossip(); +} + +void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPacket & recv_data) +{ + uint64 guid; + uint32 quest; + uint8 unk1; + recv_data >> guid >> quest >> unk1; + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_QUERY_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), quest, unk1); + + // Verify that the guid is valid and is a questgiver or involved in the requested quest + Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT|TYPEMASK_ITEM); + if (!pObject||!pObject->hasQuest(quest) && !pObject->hasInvolvedQuest(quest)) + { + _player->PlayerTalkClass->CloseGossip(); + return; + } + + Quest const* pQuest = objmgr.GetQuestTemplate(quest); + if (pQuest) + { + if (pQuest->HasFlag(QUEST_FLAGS_AUTO_ACCEPT) && _player->CanAddQuest(pQuest, true)) + { + _player->AddQuest(pQuest, pObject); + if (_player->CanCompleteQuest(quest)) + _player->CompleteQuest(quest); + } + + if (pQuest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE)) + _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, pObject->GetGUID(), _player->CanCompleteQuest(pQuest->GetQuestId()), true); + else + _player->PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, pObject->GetGUID(), true); + } +} + +void WorldSession::HandleQuestQueryOpcode(WorldPacket & recv_data) +{ + uint32 quest; + recv_data >> quest; + sLog.outDebug("WORLD: Received CMSG_QUEST_QUERY quest = %u",quest); + + Quest const *pQuest = objmgr.GetQuestTemplate(quest); + if (pQuest) + { + _player->PlayerTalkClass->SendQuestQueryResponse(pQuest); + } +} + +void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) +{ + uint32 quest, reward; + uint64 guid; + recv_data >> guid >> quest >> reward; + + if (reward >= QUEST_REWARD_CHOICES_COUNT) + { + sLog.outError("Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (probably packet hacking)", _player->GetName(), _player->GetGUIDLow(), reward); + return; + } + + if (!GetPlayer()->isAlive()) + return; + + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %u, quest = %u, reward = %u",uint32(GUID_LOPART(guid)),quest,reward); + + Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + if (!pObject) + return; + + if (!pObject->hasInvolvedQuest(quest)) + return; + + Quest const *pQuest = objmgr.GetQuestTemplate(quest); + if (pQuest) + { + if (_player->CanRewardQuest(pQuest, reward, true)) + { + _player->RewardQuest(pQuest, reward, pObject); + + switch(pObject->GetTypeId()) + { + case TYPEID_UNIT: + if (!(sScriptMgr.ChooseReward(_player, (pObject->ToCreature()), pQuest, reward))) + { + // Send next quest + if (Quest const* nextquest = _player->GetNextQuest(guid ,pQuest)) + _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextquest,guid,true); + } + break; + case TYPEID_GAMEOBJECT: + if (!sScriptMgr.GOChooseReward(_player, ((GameObject*)pObject), pQuest, reward)) + { + // Send next quest + if (Quest const* nextquest = _player->GetNextQuest(guid ,pQuest)) + _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextquest,guid,true); + } + break; + } + } + else + _player->PlayerTalkClass->SendQuestGiverOfferReward(pQuest, guid, true); + } +} + +void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket & recv_data) +{ + uint32 quest; + uint64 guid; + recv_data >> guid >> quest; + + if (!GetPlayer()->isAlive()) + return; + + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_REQUEST_REWARD npc = %u, quest = %u",uint32(GUID_LOPART(guid)),quest); + + Object* pObject = ObjectAccessor::GetObjectByTypeMask(*_player, guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); + if (!pObject||!pObject->hasInvolvedQuest(quest)) + return; + + if (_player->CanCompleteQuest(quest)) + _player->CompleteQuest(quest); + + if (_player->GetQuestStatus(quest) != QUEST_STATUS_COMPLETE) + return; + + if (Quest const *pQuest = objmgr.GetQuestTemplate(quest)) + _player->PlayerTalkClass->SendQuestGiverOfferReward(pQuest, guid, true); +} + +void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recv_data*/) +{ + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_CANCEL"); + + _player->PlayerTalkClass->CloseGossip(); +} + +void WorldSession::HandleQuestLogSwapQuest(WorldPacket& recv_data) +{ + uint8 slot1, slot2; + recv_data >> slot1 >> slot2; + + if (slot1 == slot2 || slot1 >= MAX_QUEST_LOG_SIZE || slot2 >= MAX_QUEST_LOG_SIZE) + return; + + sLog.outDebug("WORLD: Received CMSG_QUESTLOG_SWAP_QUEST slot 1 = %u, slot 2 = %u", slot1, slot2); + + GetPlayer()->SwapQuestSlot(slot1,slot2); +} + +void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) +{ + uint8 slot; + recv_data >> slot; + + sLog.outDebug("WORLD: Received CMSG_QUESTLOG_REMOVE_QUEST slot = %u",slot); + + if (slot < MAX_QUEST_LOG_SIZE) + { + if (uint32 quest = _player->GetQuestSlotQuestId(slot)) + { + if (!_player->TakeQuestSourceItem(quest, true)) + return; // can't un-equip some items, reject quest cancel + + if (const Quest *pQuest = objmgr.GetQuestTemplate(quest)) + { + if (pQuest->HasFlag(QUEST_TRINITY_FLAGS_TIMED)) + _player->RemoveTimedQuest(quest); + } + + _player->TakeQuestSourceItem(quest, true); // remove quest src item from player + _player->SetQuestStatus(quest, QUEST_STATUS_NONE); + _player->GetAchievementMgr().RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest); + } + + _player->SetQuestSlot(slot, 0); + + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1); + } +} + +void WorldSession::HandleQuestConfirmAccept(WorldPacket& recv_data) +{ + uint32 quest; + recv_data >> quest; + + sLog.outDebug("WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = %u", quest); + + if (const Quest* pQuest = objmgr.GetQuestTemplate(quest)) + { + if (!pQuest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) + return; + + Player* pOriginalPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); + + if (!pOriginalPlayer) + return; + + if (pQuest->GetType() == QUEST_TYPE_RAID) + { + if (!_player->IsInSameRaidWith(pOriginalPlayer)) + return; + } + else + { + if (!_player->IsInSameGroupWith(pOriginalPlayer)) + return; + } + + if (_player->CanAddQuest(pQuest, true)) + _player->AddQuest(pQuest, NULL); // NULL, this prevent DB script from duplicate running + + _player->SetDivider(0); + } +} + +void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recv_data) +{ + uint32 quest; + uint64 guid; + recv_data >> guid >> quest; + + if (!GetPlayer()->isAlive()) + return; + + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, quest = %u",uint32(GUID_LOPART(guid)),quest); + + Quest const *pQuest = objmgr.GetQuestTemplate(quest); + if (pQuest) + { + // TODO: need a virtual function + if (GetPlayer()->InBattleGround()) + if (BattleGround* bg = GetPlayer()->GetBattleGround()) + if (bg->GetTypeID() == BATTLEGROUND_AV) + ((BattleGroundAV*)bg)->HandleQuestComplete(quest, GetPlayer()); + + if (_player->GetQuestStatus(quest) != QUEST_STATUS_COMPLETE) + { + if (pQuest->IsRepeatable()) + _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanCompleteRepeatableQuest(pQuest), false); + else + _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanRewardQuest(pQuest,false), false); + } + else + { + if (pQuest->GetReqItemsCount()) // some items required + _player->PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, _player->CanRewardQuest(pQuest,false), false); + else // no items required + _player->PlayerTalkClass->SendQuestGiverOfferReward(pQuest, guid, true); + } + } +} + +void WorldSession::HandleQuestgiverQuestAutoLaunch(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_QUEST_AUTOLAUNCH"); +} + +void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) +{ + uint32 questId; + recvPacket >> questId; + + sLog.outDebug("WORLD: Received CMSG_PUSHQUESTTOPARTY quest = %u", questId); + + if (Quest const *pQuest = objmgr.GetQuestTemplate(questId)) + { + if (Group* pGroup = _player->GetGroup()) + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pPlayer = itr->getSource(); + + if (!pPlayer || pPlayer == _player) // skip self + continue; + + _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST); + + if (!pPlayer->SatisfyQuestStatus(pQuest, false)) + { + _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_HAVE_QUEST); + continue; + } + + if (pPlayer->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE) + { + _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_FINISH_QUEST); + continue; + } + + if (!pPlayer->CanTakeQuest(pQuest, false)) + { + _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_CANT_TAKE_QUEST); + continue; + } + + if (!pPlayer->SatisfyQuestLog(false)) + { + _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_LOG_FULL); + continue; + } + + if (pPlayer->GetDivider() != 0) + { + _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_BUSY); + continue; + } + + pPlayer->PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, _player->GetGUID(), true); + pPlayer->SetDivider(_player->GetGUID()); + } + } + } +} + +void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) +{ + uint64 guid; + uint8 msg; + recvPacket >> guid >> msg; + + sLog.outDebug("WORLD: Received MSG_QUEST_PUSH_RESULT"); + + if (_player->GetDivider() != 0) + { + Player *pPlayer = ObjectAccessor::FindPlayer(_player->GetDivider()); + if (pPlayer) + { + WorldPacket data(MSG_QUEST_PUSH_RESULT, (8+1)); + data << uint64(guid); + data << uint8(msg); // valid values: 0-8 + pPlayer->GetSession()->SendPacket(&data); + _player->SetDivider(0); + } + } +} + +uint32 WorldSession::getDialogStatus(Player *pPlayer, Object* questgiver, uint32 defstatus) +{ + uint32 result = defstatus; + + QuestRelations const* qir; + QuestRelations const* qr; + + switch(questgiver->GetTypeId()) + { + case TYPEID_GAMEOBJECT: + { + qir = &objmgr.mGOQuestInvolvedRelations; + qr = &objmgr.mGOQuestRelations; + break; + } + case TYPEID_UNIT: + { + qir = &objmgr.mCreatureQuestInvolvedRelations; + qr = &objmgr.mCreatureQuestRelations; + break; + } + default: + //its imposible, but check ^) + sLog.outError("Warning: GetDialogStatus called for unexpected type %u", questgiver->GetTypeId()); + return DIALOG_STATUS_NONE; + } + + for (QuestRelations::const_iterator i = qir->lower_bound(questgiver->GetEntry()); i != qir->upper_bound(questgiver->GetEntry()); ++i) + { + uint32 result2 = 0; + uint32 quest_id = i->second; + Quest const *pQuest = objmgr.GetQuestTemplate(quest_id); + if (!pQuest) continue; + + QuestStatus status = pPlayer->GetQuestStatus(quest_id); + if ((status == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(quest_id)) || + (pQuest->IsAutoComplete() && pPlayer->CanTakeQuest(pQuest, false))) + { + if (pQuest->IsAutoComplete() && pQuest->IsRepeatable()) + result2 = DIALOG_STATUS_REWARD_REP; + else + result2 = DIALOG_STATUS_REWARD; + } + else if (status == QUEST_STATUS_INCOMPLETE) + result2 = DIALOG_STATUS_INCOMPLETE; + + if (result2 > result) + result = result2; + } + + for (QuestRelations::const_iterator i = qr->lower_bound(questgiver->GetEntry()); i != qr->upper_bound(questgiver->GetEntry()); ++i) + { + uint32 result2 = 0; + uint32 quest_id = i->second; + Quest const *pQuest = objmgr.GetQuestTemplate(quest_id); + if (!pQuest) + continue; + + QuestStatus status = pPlayer->GetQuestStatus(quest_id); + if (status == QUEST_STATUS_NONE) + { + if (pPlayer->CanSeeStartQuest(pQuest)) + { + if (pPlayer->SatisfyQuestLevel(pQuest, false)) + { + if (pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && pPlayer->getQuestStatusMap()[quest_id].m_rewarded)) + result2 = DIALOG_STATUS_REWARD_REP; + else if (pPlayer->getLevel() <= ((pPlayer->GetQuestLevel(pQuest) == -1) ? pPlayer->getLevel() : pPlayer->GetQuestLevel(pQuest) + sWorld.getConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) + { + if (pQuest->HasFlag(QUEST_FLAGS_DAILY) || pQuest->HasFlag(QUEST_FLAGS_WEEKLY)) + result2 = DIALOG_STATUS_AVAILABLE_REP; + else + result2 = DIALOG_STATUS_AVAILABLE; + } + else + result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE; + } + else + result2 = DIALOG_STATUS_UNAVAILABLE; + } + } + + if (result2 > result) + result = result2; + } + + return result; +} + +void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Received CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY"); + + uint32 count = 0; + + WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4); + data << uint32(count); // placeholder + + for (Player::ClientGUIDs::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr) + { + uint8 questStatus = DIALOG_STATUS_NONE; + uint8 defstatus = DIALOG_STATUS_NONE; + + if (IS_CRE_OR_VEH_OR_PET_GUID(*itr)) + { + // need also pet quests case support + Creature *questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(),*itr); + if (!questgiver || questgiver->IsHostileTo(_player)) + continue; + if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) + continue; + questStatus = sScriptMgr.NPCDialogStatus(_player, questgiver); + if (questStatus > 6) + questStatus = getDialogStatus(_player, questgiver, defstatus); + + data << uint64(questgiver->GetGUID()); + data << uint8(questStatus); + ++count; + } + else if (IS_GAMEOBJECT_GUID(*itr)) + { + GameObject *questgiver = GetPlayer()->GetMap()->GetGameObject(*itr); + if (!questgiver) + continue; + if (questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) + continue; + questStatus = sScriptMgr.GODialogStatus(_player, questgiver); + if (questStatus > 6) + questStatus = getDialogStatus(_player, questgiver, defstatus); + + data << uint64(questgiver->GetGUID()); + data << uint8(questStatus); + ++count; + } + } + + data.put(0, count); // write real count + SendPacket(&data); +} + +void WorldSession::HandleQueryQuestsCompleted(WorldPacket & /*recv_data*/) +{ + uint32 count = 0; + + WorldPacket data(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, 4+4*count); + data << uint32(count); + + for (QuestStatusMap::const_iterator itr = _player->getQuestStatusMap().begin(); itr != _player->getQuestStatusMap().end(); ++itr) + { + if (itr->second.m_rewarded) + { + data << uint32(itr->first); + count++; + } + } + data.put(0, count); + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/SkillHandler.cpp b/src/server/game/Server/Protocol/Handlers/SkillHandler.cpp new file mode 100644 index 00000000000..312065f9f13 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/SkillHandler.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Opcodes.h" +#include "Log.h" +#include "Player.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "ObjectAccessor.h" +#include "UpdateMask.h" + +void WorldSession::HandleLearnTalentOpcode(WorldPacket & recv_data) +{ + uint32 talent_id, requested_rank; + recv_data >> talent_id >> requested_rank; + + _player->LearnTalent(talent_id, requested_rank); + _player->SendTalentsInfoData(false); +} + +void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) +{ + sLog.outDebug("CMSG_LEARN_PREVIEW_TALENTS"); + + uint32 talentsCount; + recvPacket >> talentsCount; + + uint32 talentId, talentRank; + + for (uint32 i = 0; i < talentsCount; ++i) + { + recvPacket >> talentId >> talentRank; + + _player->LearnTalent(talentId, talentRank); + } + + _player->SendTalentsInfoData(false); +} + +void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket & recv_data) +{ + sLog.outDetail("MSG_TALENT_WIPE_CONFIRM"); + uint64 guid; + recv_data >> guid; + + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TRAINER); + if (!unit) + { + sLog.outDebug("WORLD: HandleTalentWipeConfirmOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + if (!(_player->resetTalents())) + { + WorldPacket data(MSG_TALENT_WIPE_CONFIRM, 8+4); //you have not any talent + data << uint64(0); + data << uint32(0); + SendPacket(&data); + return; + } + + _player->SendTalentsInfoData(false); + unit->CastSpell(_player, 14867, true); //spell: "Untalent Visual Effect" +} + +void WorldSession::HandleUnlearnSkillOpcode(WorldPacket & recv_data) +{ + uint32 skill_id; + recv_data >> skill_id; + GetPlayer()->SetSkill(skill_id, 0, 0, 0); +} + diff --git a/src/server/game/Server/Protocol/Handlers/SpellHandler.cpp b/src/server/game/Server/Protocol/Handlers/SpellHandler.cpp new file mode 100644 index 00000000000..b8a4a127824 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/SpellHandler.cpp @@ -0,0 +1,649 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "DBCStores.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Log.h" +#include "Opcodes.h" +#include "Spell.h" +#include "Totem.h" +#include "TemporarySummon.h" +#include "SpellAuras.h" +#include "CreatureAI.h" +#include "ScriptMgr.h" + +void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) +{ + // TODO: add targets.read() check + Player* pUser = _player; + + // ignore for remote control state + if (pUser->m_mover != pUser) + return; + + uint8 bagIndex, slot; + uint8 unk_flags; // flags (if 0x02 - some additional data are received) + uint8 cast_count; // next cast if exists (single or not) + uint64 item_guid; + uint32 glyphIndex; // something to do with glyphs? + uint32 spellid; // casted spell id + + recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags; + + if (glyphIndex >= MAX_GLYPH_SLOT_INDEX) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + Item *pItem = pUser->GetUseableItemByPos(bagIndex, slot); + if (!pItem) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + if (pItem->GetGUID() != item_guid) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, unk_flags, (uint32)recvPacket.size()); + + ItemPrototype const *proto = pItem->GetProto(); + if (!proto) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL); + return; + } + + // some item classes can be used only in equipped state + if (proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL); + return; + } + + uint8 msg = pUser->CanUseItem(pItem); + if (msg != EQUIP_ERR_OK) + { + pUser->SendEquipError(msg, pItem, NULL); + return; + } + + // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) + if (proto->Class == ITEM_CLASS_CONSUMABLE && !(proto->Flags & ITEM_FLAGS_USEABLE_IN_ARENA) && pUser->InArena()) + { + pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL); + return; + } + + if (pUser->isInCombat()) + { + for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + { + if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId)) + { + if (IsNonCombatSpell(spellInfo)) + { + pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT,pItem,NULL); + return; + } + } + } + } + + // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) + if (pItem->GetProto()->Bonding == BIND_WHEN_USE || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM) + { + if (!pItem->IsSoulBound()) + { + pItem->SetState(ITEM_CHANGED, pUser); + pItem->SetBinding(true); + } + } + + SpellCastTargets targets; + if (!targets.read(&recvPacket, pUser)) + return; + + targets.Update(pUser); + + if (!pItem->IsTargetValidForItemUse(targets.getUnitTarget())) + { + // free gray item after use fail + pUser->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); + + // send spell error + if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid)) + { + // for implicit area/coord target spells + if (!targets.getUnitTarget()) + Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_NO_VALID_TARGETS); + // for explicit target spells + else + Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_BAD_TARGETS); + } + return; + } + + //Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. + if (!sScriptMgr.ItemUse(pUser,pItem,targets)) + { + // no script or script not process request by self + pUser->CastItemUseSpell(pItem,targets,cast_count,glyphIndex); + } +} + +#define OPEN_CHEST 11437 +#define OPEN_SAFE 11535 +#define OPEN_CAGE 11792 +#define OPEN_BOOTY_CHEST 5107 +#define OPEN_STRONGBOX 8517 + +void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) +{ + sLog.outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i",(uint32)recvPacket.size()); + + Player* pUser = _player; + + // ignore for remote control state + if (pUser->m_mover != pUser) + return; + + uint8 bagIndex, slot; + + recvPacket >> bagIndex >> slot; + + sLog.outDetail("bagIndex: %u, slot: %u",bagIndex,slot); + + Item *pItem = pUser->GetItemByPos(bagIndex, slot); + if (!pItem) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + ItemPrototype const *proto = pItem->GetProto(); + if (!proto) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL); + return; + } + + if (!pUser->GetSession()->HandleOnItemOpen(pItem)) + return; + + // locked item + uint32 lockId = proto->LockID; + if (lockId) + { + LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); + + if (!lockInfo) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL); + sLog.outError("WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", pItem->GetGUIDLow(), lockId); + return; + } + + // required picklocking + if (lockInfo->Skill[1] || lockInfo->Skill[0]) + { + pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL); + return; + } + } + + if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))// wrapped? + { + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT entry, flags FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); + if (result) + { + Field *fields = result->Fetch(); + uint32 entry = fields[0].GetUInt32(); + uint32 flags = fields[1].GetUInt32(); + + pItem->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, 0); + pItem->SetEntry(entry); + pItem->SetUInt32Value(ITEM_FIELD_FLAGS, flags); + pItem->SetState(ITEM_CHANGED, pUser); + } + else + { + sLog.outError("Wrapped item %u don't have record in character_gifts table and will deleted", pItem->GetGUIDLow()); + pUser->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); + return; + } + CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); + } + else + pUser->SendLoot(pItem->GetGUID(),LOOT_CORPSE); +} + +void WorldSession::HandleGameObjectUseOpcode(WorldPacket & recv_data) +{ + uint64 guid; + + recv_data >> guid; + + sLog.outDebug("WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid)); + + // ignore for remote control state + if (_player->m_mover != _player) + return; + + GameObject *obj = GetPlayer()->GetMap()->GetGameObject(guid); + + if (!obj) + return; + + if (sScriptMgr.GOHello(_player, obj)) + return; + + obj->Use(_player); +} + +void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) +{ + uint64 guid; + recvPacket >> guid; + + sLog.outDebug("WORLD: Recvd CMSG_GAMEOBJ_REPORT_USE Message [in game guid: %u]", GUID_LOPART(guid)); + + // ignore for remote control state + if (_player->m_mover != _player) + return; + + GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); + if (!go) + return; + + if (!go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + return; + + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); +} + +void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) +{ + uint32 spellId; + uint8 cast_count, unk_flags; + recvPacket >> cast_count; + recvPacket >> spellId; + recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received) + + // ignore for remote control state (for player case) + Unit* mover = _player->m_mover; + if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) + { + recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet + return; + } + + sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", spellId, cast_count, unk_flags, (uint32)recvPacket.size()); + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + + if (!spellInfo) + { + sLog.outError("WORLD: unknown spell id %u", spellId); + recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet + return; + } + + if (mover->GetTypeId() == TYPEID_PLAYER) + { + // not have spell in spellbook or spell passive and not casted by client + if (!mover->ToPlayer()->HasActiveSpell (spellId) || IsPassiveSpell(spellId)) + { + //cheater? kick? ban? + recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet + return; + } + } + else + { + // not have spell in spellbook or spell passive and not casted by client + if ((mover->GetTypeId() == TYPEID_UNIT && !mover->ToCreature()->HasSpell(spellId)) || IsPassiveSpell(spellId)) + { + //cheater? kick? ban? + recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet + return; + } + } + + // Client is resending autoshot cast opcode when other spell is casted during shoot rotation + // Skip it to prevent "interrupt" message + if (IsAutoRepeatRangedSpell(spellInfo) && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) + && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) + return; + + // can't use our own spells when we're in possession of another unit, + if (_player->isPossessing()) + return; + + // client provided targets + SpellCastTargets targets; + if (!targets.read(&recvPacket,mover)) + { + recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet + return; + } + + // some spell cast packet including more data (for projectiles?) + if (unk_flags & 0x02) + { + //recvPacket.read_skip(); // unk1, coords? + //recvPacket.read_skip(); // unk1, coords? + uint8 unk1; + recvPacket >> unk1; // >> 1 or 0 + if (unk1) + { + recvPacket.read_skip(); // >> MSG_MOVE_STOP + uint64 guid; // guid - unused + if (!recvPacket.readPackGUID(guid)) + return; + + MovementInfo movementInfo; + ReadMovementInfo(recvPacket, &movementInfo); + } + } + + // auto-selection buff level base at target level (in spellInfo) + if (targets.getUnitTarget()) + { + SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel()); + + // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message + if (actualSpellInfo) + spellInfo = actualSpellInfo; + } + + Spell *spell = new Spell(mover, spellInfo, false); + spell->m_cast_count = cast_count; // set count of casts + spell->prepare(&targets); +} + +void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) +{ + uint32 spellId; + + recvPacket.read_skip(); // counter, increments with every CANCEL packet, don't use for now + recvPacket >> spellId; + + if (_player->IsNonMeleeSpellCasted(false)) + _player->InterruptNonMeleeSpells(false,spellId,false); +} + +void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) +{ + uint32 spellId; + recvPacket >> spellId; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo) + return; + + // not allow remove non positive spells and spells with attr SPELL_ATTR_CANT_CANCEL + if (!IsPositiveSpell(spellId) || (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL)) + return; + + // channeled spell case (it currently casted then) + if (IsChanneledSpell(spellInfo)) + { + if (Spell* curSpell = _player->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + if (curSpell->m_spellInfo->Id == spellId) + _player->InterruptSpell(CURRENT_CHANNELED_SPELL); + return; + } + + // non channeled case + // maybe should only remove one buff when there are multiple? + _player->RemoveOwnedAura(spellId, 0, 0, AURA_REMOVE_BY_CANCEL); +} + +void WorldSession::HandlePetCancelAuraOpcode(WorldPacket& recvPacket) +{ + uint64 guid; + uint32 spellId; + + recvPacket >> guid; + recvPacket >> spellId; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo) + { + sLog.outError("WORLD: unknown PET spell id %u", spellId); + return; + } + + Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); + + if (!pet) + { + sLog.outError("Pet %u not exist.", uint32(GUID_LOPART(guid))); + return; + } + + if (pet != GetPlayer()->GetGuardianPet() && pet != GetPlayer()->GetCharm()) + { + sLog.outError("HandlePetCancelAura.Pet %u isn't pet of player %s", uint32(GUID_LOPART(guid)),GetPlayer()->GetName()); + return; + } + + if (!pet->isAlive()) + { + pet->SendPetActionFeedback(FEEDBACK_PET_DEAD); + return; + } + + pet->RemoveOwnedAura(spellId, 0, 0, AURA_REMOVE_BY_CANCEL); + + pet->AddCreatureSpellCooldown(spellId); +} + +void WorldSession::HandleCancelGrowthAuraOpcode(WorldPacket& /*recvPacket*/) +{ +} + +void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& /*recvPacket*/) +{ + // may be better send SMSG_CANCEL_AUTO_REPEAT? + // cancel and prepare for deleting + _player->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); +} + +void WorldSession::HandleCancelChanneling(WorldPacket & recv_data) +{ + recv_data.read_skip(); // spellid, not used + + // ignore for remote control state (for player case) + Unit* mover = _player->m_mover; + if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) + return; + + mover->InterruptSpell(CURRENT_CHANNELED_SPELL); +} + +void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket) +{ + // ignore for remote control state + if (_player->m_mover != _player) + return; + + uint8 slotId; + + recvPacket >> slotId; + + ++slotId; + if (slotId >= MAX_TOTEM_SLOT) + return; + + if (!_player->m_SummonSlot[slotId]) + return; + + Creature* totem = GetPlayer()->GetMap()->GetCreature(_player->m_SummonSlot[slotId]); + // Don't unsummon sentry totem + if (totem && totem->isTotem() && totem->GetEntry() != SENTRY_TOTEM_ENTRY) + totem->ToTotem()->UnSummon(); +} + +void WorldSession::HandleSelfResOpcode(WorldPacket & /*recv_data*/) +{ + sLog.outDebug("WORLD: CMSG_SELF_RES"); // empty opcode + + if (_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)); + if (spellInfo) + _player->CastSpell(_player,spellInfo,false,0); + + _player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); + } +} + +void WorldSession::HandleSpellClick(WorldPacket & recv_data) +{ + uint64 guid; + recv_data >> guid; + + // this will get something not in world. crash + Creature *unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); + + if (!unit) + return; + + // TODO: Unit::SetCharmedBy: 28782 is not in world but 0 is trying to charm it! -> crash + if (!unit->IsInWorld()) + { + sLog.outCrash("Spell click target %u is not in world!", unit->GetEntry()); + assert(false); + return; + } + + SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(unit->GetEntry()); + for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) + { + if (itr->second.IsFitToRequirements(_player, unit)) + { + Unit *caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_PLAYER) ? (Unit*)_player : (Unit*)unit; + Unit *target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_PLAYER) ? (Unit*)_player : (Unit*)unit; + uint64 origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? unit->GetOwnerGUID() : 0; + caster->CastSpell(target, itr->second.spellId, true, NULL, NULL, origCasterGUID); + } + } + + if (unit->IsVehicle()) + { + if (unit->CheckPlayerCondition(_player)) + _player->EnterVehicle(unit); + } + + unit->AI()->DoAction(EVENT_SPELLCLICK); +} + +void WorldSession::HandleMirrrorImageDataRequest(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_GET_MIRRORIMAGE_DATA"); + uint64 guid; + recv_data >> guid; + + // Get unit for which data is needed by client + Unit *unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL); + if (!unit) + return; + + // Get creator of the unit + Unit *creator = ObjectAccessor::GetObjectInWorld(unit->GetCreatorGUID(),(Unit*)NULL); + if (!creator) + return; + + WorldPacket data(SMSG_MIRRORIMAGE_DATA, 68); + data << uint64(guid); + data << uint32(creator->GetDisplayId()); + if (creator->GetTypeId() == TYPEID_PLAYER) + { + Player * pCreator = creator->ToPlayer(); + data << uint8(pCreator->getRace()); + data << uint8(pCreator->getGender()); + data << uint8(pCreator->getClass()); + data << uint8(pCreator->GetByteValue(PLAYER_BYTES, 0)); // skin + data << uint8(pCreator->GetByteValue(PLAYER_BYTES, 1)); // face + data << uint8(pCreator->GetByteValue(PLAYER_BYTES, 2)); // hair + data << uint8(pCreator->GetByteValue(PLAYER_BYTES, 3)); // haircolor + data << uint8(pCreator->GetByteValue(PLAYER_BYTES_2, 0)); // facialhair + data << uint32(pCreator->GetGuildId()); // unk + + static const EquipmentSlots ItemSlots[] = + { + EQUIPMENT_SLOT_HEAD, + EQUIPMENT_SLOT_SHOULDERS, + EQUIPMENT_SLOT_BODY, + EQUIPMENT_SLOT_CHEST, + EQUIPMENT_SLOT_WAIST, + EQUIPMENT_SLOT_LEGS, + EQUIPMENT_SLOT_FEET, + EQUIPMENT_SLOT_WRISTS, + EQUIPMENT_SLOT_HANDS, + EQUIPMENT_SLOT_BACK, + EQUIPMENT_SLOT_TABARD, + EQUIPMENT_SLOT_END + }; + + // Display items in visible slots + for (EquipmentSlots const* itr = &ItemSlots[0]; *itr != EQUIPMENT_SLOT_END; ++itr) + { + if (*itr == EQUIPMENT_SLOT_HEAD && pCreator->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) + data << uint32(0); + else if (*itr == EQUIPMENT_SLOT_BACK && pCreator->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK)) + data << uint32(0); + else if (Item const *item = pCreator->GetItemByPos(INVENTORY_SLOT_BAG_0, *itr)) + data << uint32(item->GetProto()->DisplayInfoID); + else + data << uint32(0); + } + } + else + { + // Skip player data for creatures + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + } + + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp b/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp new file mode 100644 index 00000000000..b0660527f71 --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/TaxiHandler.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "UpdateMask.h" +#include "Path.h" +#include "WaypointMovementGenerator.h" +#include "DestinationHolderImp.h" + +void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_TAXINODE_STATUS_QUERY"); + + uint64 guid; + + recv_data >> guid; + SendTaxiStatus(guid); +} + +void WorldSession::SendTaxiStatus(uint64 guid) +{ + // cheating checks + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); + if (!unit) + { + sLog.outDebug("WorldSession::SendTaxiStatus - Unit (GUID: %u) not found.", uint32(GUID_LOPART(guid))); + return; + } + + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); + + // not found nearest + if (curloc == 0) + return; + + sLog.outDebug("WORLD: current location %u ",curloc); + + WorldPacket data(SMSG_TAXINODE_STATUS, 9); + data << guid; + data << uint8(GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0); + SendPacket(&data); + sLog.outDebug("WORLD: Sent SMSG_TAXINODE_STATUS"); +} + +void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_TAXIQUERYAVAILABLENODES"); + + uint64 guid; + recv_data >> guid; + + // cheating checks + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); + if (!unit) + { + sLog.outDebug("WORLD: HandleTaxiQueryAvailableNodes - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + return; + } + + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + // unknown taxi node case + if (SendLearnNewTaxiNode(unit)) + return; + + // known taxi node case + SendTaxiMenu(unit); +} + +void WorldSession::SendTaxiMenu(Creature* unit) +{ + // find current node + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); + + if (curloc == 0) + return; + + bool lastTaxiCheaterState = GetPlayer()->isTaxiCheater(); + if (unit->GetEntry() == 29480) GetPlayer()->SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it. + + sLog.outDebug("WORLD: CMSG_TAXINODE_STATUS_QUERY %u ",curloc); + + WorldPacket data(SMSG_SHOWTAXINODES, (4+8+4+8*4)); + data << uint32(1); + data << uint64(unit->GetGUID()); + data << uint32(curloc); + GetPlayer()->m_taxi.AppendTaximaskTo(data,GetPlayer()->isTaxiCheater()); + SendPacket(&data); + + sLog.outDebug("WORLD: Sent SMSG_SHOWTAXINODES"); + + GetPlayer()->SetTaxiCheater(lastTaxiCheaterState); +} + +void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode) +{ + // remove fake death + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + + while (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) + GetPlayer()->GetMotionMaster()->MovementExpired(false); + + if (mountDisplayId) + GetPlayer()->Mount(mountDisplayId); + + GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path,pathNode); +} + +bool WorldSession::SendLearnNewTaxiNode(Creature* unit) +{ + // find current node + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer()->GetTeam()); + + if (curloc == 0) + return true; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result. + + if (GetPlayer()->m_taxi.SetTaximaskNode(curloc)) + { + WorldPacket msg(SMSG_NEW_TAXI_PATH, 0); + SendPacket(&msg); + + WorldPacket update(SMSG_TAXINODE_STATUS, 9); + update << uint64(unit->GetGUID()); + update << uint8(1); + SendPacket(&update); + + return true; + } + else + return false; +} + +void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXIEXPRESS"); + + uint64 guid; + uint32 node_count; + + recv_data >> guid >> node_count; + + Creature *npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); + if (!npc) + { + sLog.outDebug("WORLD: HandleActivateTaxiExpressOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid))); + return; + } + std::vector nodes; + + for (uint32 i = 0; i < node_count; ++i) + { + uint32 node; + recv_data >> node; + nodes.push_back(node); + } + + if (nodes.empty()) + return; + + sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXIEXPRESS from %d to %d" ,nodes.front(),nodes.back()); + + GetPlayer()->ActivateTaxiPathTo(nodes, npc); +} + +void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_MOVE_SPLINE_DONE"); + + uint64 guid; // used only for proper packet read + if (!recv_data.readPackGUID(guid)) + return; + + MovementInfo movementInfo; // used only for proper packet read + ReadMovementInfo(recv_data, &movementInfo); + + recv_data.read_skip(); // unk + + // in taxi flight packet received in 2 case: + // 1) end taxi path in far (multi-node) flight + // 2) switch from one map to other in case multim-map taxi path + // we need process only (1) + + uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); + if (!curDest) + return; + + TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); + + // far teleport case + if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId()) + { + if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) + { + // short preparations to continue flight + FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); + + flight->SetCurrentNodeAfterTeleport(); + Path::PathNode const& node = flight->GetPath()[flight->GetCurrentNode()]; + flight->SkipCurrentNode(); + + GetPlayer()->TeleportTo(curDestNode->map_id,node.x,node.y,node.z,GetPlayer()->GetOrientation()); + } + return; + } + + uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); + if (destinationnode > 0) // if more destinations to go + { + // current source node for next destination + uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); + + // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) + if (GetPlayer()->isTaxiCheater()) + { + if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) + { + WorldPacket data(SMSG_NEW_TAXI_PATH, 0); + _player->GetSession()->SendPacket(&data); + } + } + + sLog.outDebug("WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode); + + uint32 mountDisplayId = objmgr.GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam()); + + uint32 path, cost; + objmgr.GetTaxiPath(sourcenode, destinationnode, path, cost); + + if (path && mountDisplayId) + SendDoFlight(mountDisplayId, path, 1); // skip start fly node + else + GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next + return; + } + + GetPlayer()->CleanupAfterTaxiFlight(); + GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ()); + if (GetPlayer()->pvpInfo.inHostileArea) + GetPlayer()->CastSpell(GetPlayer(), 2479, true); +} + +void WorldSession::HandleActivateTaxiOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXI"); + + uint64 guid; + std::vector nodes; + nodes.resize(2); + + recv_data >> guid >> nodes[0] >> nodes[1]; + sLog.outDebug("WORLD: Received CMSG_ACTIVATETAXI from %d to %d" ,nodes[0],nodes[1]); + Creature *npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); + if (!npc) + { + sLog.outDebug("WORLD: HandleActivateTaxiOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid))); + return; + } + + GetPlayer()->ActivateTaxiPathTo(nodes, npc); +} diff --git a/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp b/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp new file mode 100644 index 00000000000..72ed25adbca --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/TicketHandler.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Language.h" +#include "WorldPacket.h" +#include "Common.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "World.h" + +void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) +{ + if (GetPlayer()->getLevel() < sWorld.getConfig(CONFIG_TICKET_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_TICKET_REQ), sWorld.getConfig(CONFIG_TICKET_LEVEL_REQ)); + return; + } + + if (GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(GetPlayer()->GetGUID())) + { + WorldPacket data(SMSG_GMTICKET_CREATE, 4); + data << uint32(1); // 1 - You already have GM ticket + SendPacket(&data); + return; + } + + uint32 map; + float x, y, z; + std::string ticketText, ticketText2; + + SendQueryTimeResponse(); + + WorldPacket data(SMSG_GMTICKET_CREATE, 4); + recv_data >> map; + recv_data >> x; + recv_data >> y; + recv_data >> z; + recv_data >> ticketText; + recv_data >> ticketText2; + + GM_Ticket *ticket = new GM_Ticket; + ticket->name = GetPlayer()->GetName(); + ticket->guid = objmgr.GenerateGMTicketId(); + ticket->playerGuid = GetPlayer()->GetGUID(); + ticket->message = ticketText; + ticket->createtime = time(NULL); + ticket->map = map; + ticket->pos_x = x; + ticket->pos_y = y; + ticket->pos_z = z; + ticket->timestamp = time(NULL); + ticket->closed = 0; + ticket->assignedToGM = 0; + ticket->comment = ""; + + objmgr.AddOrUpdateGMTicket(*ticket, true); + + data << uint32(2); + SendPacket(&data); + + sWorld.SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName(), ticket->guid); + +} + +void WorldSession::HandleGMTicketUpdateOpcode(WorldPacket & recv_data) +{ + WorldPacket data(SMSG_GMTICKET_UPDATETEXT, 4); + + std::string message; + recv_data >> message; + + GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(GetPlayer()->GetGUID()); + if (!ticket) + { + data << uint32(1); + SendPacket(&data); + return; + } + + ticket->message = message; + ticket->timestamp = time(NULL); + + objmgr.AddOrUpdateGMTicket(*ticket); + + data << uint32(2); + SendPacket(&data); + + sWorld.SendGMText(LANG_COMMAND_TICKETUPDATED, GetPlayer()->GetName(), ticket->guid); + +} + +void WorldSession::HandleGMTicketDeleteOpcode(WorldPacket & /*recv_data*/) +{ + GM_Ticket* ticket = objmgr.GetGMTicketByPlayer(GetPlayer()->GetGUID()); + + if (ticket) + { + WorldPacket data(SMSG_GMTICKET_DELETETICKET, 4); + data << uint32(9); + SendPacket(&data); + + sWorld.SendGMText(LANG_COMMAND_TICKETPLAYERABANDON, GetPlayer()->GetName(), ticket->guid); + objmgr.RemoveGMTicket(ticket, GetPlayer()->GetGUID(), false); + SendGMTicketGetTicket(0x0A, 0); + } +} + +void WorldSession::HandleGMTicketGetTicketOpcode(WorldPacket & /*recv_data*/) +{ + SendQueryTimeResponse(); + + GM_Ticket *ticket = objmgr.GetGMTicketByPlayer(GetPlayer()->GetGUID()); + if (ticket) + SendGMTicketGetTicket(0x06, ticket->message.c_str()); + else + SendGMTicketGetTicket(0x0A, 0); + +} + +void WorldSession::HandleGMTicketSystemStatusOpcode(WorldPacket & /*recv_data*/) +{ + WorldPacket data(SMSG_GMTICKET_SYSTEMSTATUS, 4); + data << uint32(1); + SendPacket(&data); +} + +void WorldSession::SendGMTicketGetTicket(uint32 status, char const* text) +{ + int len = text ? strlen(text) : 0; + WorldPacket data(SMSG_GMTICKET_GETTICKET, (4+len+1+4+2+4+4)); + data << uint32(status); // standard 0x0A, 0x06 if text present + data << uint32(1); // unk flags, if 0, can't edit the ticket + if (status == 6) + { + data << text; // ticket text + data << uint8(0x7); // ticket category + data << float(0); // tickets in queue? + data << float(0); // if > "tickets in queue" then "We are currently experiencing a high volume of petitions." + data << float(0); // 0 - "Your ticket will be serviced soon", 1 - "Wait time currently unavailable" + data << uint8(0); // if == 2 and next field == 1 then "Your ticket has been escalated" + data << uint8(0); // const + } + SendPacket(&data); +} diff --git a/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp b/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp new file mode 100644 index 00000000000..448a6e0520d --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "World.h" +#include "ObjectAccessor.h" +#include "Log.h" +#include "Opcodes.h" +#include "Player.h" +#include "Item.h" +#include "SocialMgr.h" +#include "Language.h" + +enum TradeStatus +{ + TRADE_STATUS_BUSY = 0, + TRADE_STATUS_BEGIN_TRADE = 1, + TRADE_STATUS_OPEN_WINDOW = 2, + TRADE_STATUS_TRADE_CANCELED = 3, + TRADE_STATUS_TRADE_ACCEPT = 4, + TRADE_STATUS_BUSY_2 = 5, + TRADE_STATUS_NO_TARGET = 6, + TRADE_STATUS_BACK_TO_TRADE = 7, + TRADE_STATUS_TRADE_COMPLETE = 8, + // 9? + TRADE_STATUS_TARGET_TO_FAR = 10, + TRADE_STATUS_WRONG_FACTION = 11, + TRADE_STATUS_CLOSE_WINDOW = 12, + // 13? + TRADE_STATUS_IGNORE_YOU = 14, + TRADE_STATUS_YOU_STUNNED = 15, + TRADE_STATUS_TARGET_STUNNED = 16, + TRADE_STATUS_YOU_DEAD = 17, + TRADE_STATUS_TARGET_DEAD = 18, + TRADE_STATUS_YOU_LOGOUT = 19, + TRADE_STATUS_TARGET_LOGOUT = 20, + TRADE_STATUS_TRIAL_ACCOUNT = 21, // Trial accounts can not perform that action + TRADE_STATUS_ONLY_CONJURED = 22 // You can only trade conjured items... (cross realm BG related). +}; + +void WorldSession::SendTradeStatus(uint32 status) +{ + WorldPacket data; + + switch(status) + { + case TRADE_STATUS_BEGIN_TRADE: + data.Initialize(SMSG_TRADE_STATUS, 4+8); + data << uint32(status); + data << uint64(0); + break; + case TRADE_STATUS_OPEN_WINDOW: + data.Initialize(SMSG_TRADE_STATUS, 4+4); + data << uint32(status); + data << uint32(0); // added in 2.4.0 + break; + case TRADE_STATUS_CLOSE_WINDOW: + data.Initialize(SMSG_TRADE_STATUS, 4+4+1+4); + data << uint32(status); + data << uint32(0); + data << uint8(0); + data << uint32(0); + break; + case TRADE_STATUS_ONLY_CONJURED: + data.Initialize(SMSG_TRADE_STATUS, 4+1); + data << uint32(status); + data << uint8(0); + break; + default: + data.Initialize(SMSG_TRADE_STATUS, 4); + data << uint32(status); + break; + } + + SendPacket(&data); +} + +void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Ignore Trade %u",_player->GetGUIDLow()); + // recvPacket.print_storage(); +} + +void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/) +{ + sLog.outDebug("WORLD: Busy Trade %u",_player->GetGUIDLow()); + // recvPacket.print_storage(); +} + +void WorldSession::SendUpdateTrade() +{ + Item *item = NULL; + + if (!_player || !_player->pTrader) + return; + + // reset trade status + if (_player->acceptTrade) + { + _player->acceptTrade = false; + SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + } + + if (_player->pTrader->acceptTrade) + { + _player->pTrader->acceptTrade = false; + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + } + + WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, (100)); // guess size + data << (uint8) 1; // can be different (only seen 0 and 1) + data << (uint32) 0; // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?) + data << (uint32) TRADE_SLOT_COUNT; // trade slots count/number?, = next field in most cases + data << (uint32) TRADE_SLOT_COUNT; // trade slots count/number?, = prev field in most cases + data << (uint32) _player->pTrader->tradeGold; // trader gold + data << (uint32) 0; // spell casted on lowest slot item + + for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) + { + item = (_player->pTrader->tradeItems[i] != 0 ? _player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]) : NULL); + + data << (uint8) i; // trade slot number, if not specified, then end of packet + + if (item) + { + data << (uint32) item->GetProto()->ItemId; // entry + // display id + data << (uint32) item->GetProto()->DisplayInfoID; + // stack count + data << (uint32) item->GetUInt32Value(ITEM_FIELD_STACK_COUNT); + data << (uint32) 0; // probably gift=1, created_by=0? + // gift creator + data << (uint64) item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR); + data << (uint32) item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT); + for (uint8 j = 0; j < 3; ++j) + data << (uint32) 0; // enchantment id (permanent/gems?) + // creator + data << (uint64) item->GetUInt64Value(ITEM_FIELD_CREATOR); + data << (uint32) item->GetSpellCharges(); // charges + data << (uint32) item->GetItemSuffixFactor(); // SuffixFactor + // random properties id + data << (int32) item->GetItemRandomPropertyId(); + data << (uint32) item->GetProto()->LockID; // lock id + // max durability + data << (uint32) item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); + // durability + data << (uint32) item->GetUInt32Value(ITEM_FIELD_DURABILITY); + } + else + { + for (uint8 j = 0; j < 18; j++) + data << uint32(0); + } + } + SendPacket(&data); +} + +//============================================================== +// transfer the items to the players + +void WorldSession::moveItems(Item* myItems[], Item* hisItems[]) +{ + for (int i=0; ipTrader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, myItems[i], false) == EQUIP_ERR_OK); + bool playerCanTrade = (hisItems[i] == NULL || _player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, hisItems[i], false) == EQUIP_ERR_OK); + if (traderCanTrade && playerCanTrade) + { + // Ok, if trade item exists and can be stored + // If we trade in both directions we had to check, if the trade will work before we actually do it + // A roll back is not possible after we stored it + if (myItems[i]) + { + // logging + sLog.outDebug("partner storing: %u",myItems[i]->GetGUIDLow()); + if (_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", + _player->GetName(),_player->GetSession()->GetAccountId(), + myItems[i]->GetProto()->Name1,myItems[i]->GetEntry(),myItems[i]->GetCount(), + _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId()); + } + + // store + _player->pTrader->MoveItemToInventory(traderDst, myItems[i], true, true); + } + if (hisItems[i]) + { + // logging + sLog.outDebug("player storing: %u",hisItems[i]->GetGUIDLow()); + if (_player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + sLog.outCommand(_player->pTrader->GetSession()->GetAccountId(),"GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", + _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(), + hisItems[i]->GetProto()->Name1,hisItems[i]->GetEntry(),hisItems[i]->GetCount(), + _player->GetName(),_player->GetSession()->GetAccountId()); + } + + // store + _player->MoveItemToInventory(playerDst, hisItems[i], true, true); + } + } + else + { + // in case of fatal error log error message + // return the already removed items to the original owner + if (myItems[i]) + { + if (!traderCanTrade) + sLog.outError("trader can't store item: %u",myItems[i]->GetGUIDLow()); + if (_player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, myItems[i], false) == EQUIP_ERR_OK) + _player->MoveItemToInventory(playerDst, myItems[i], true, true); + else + sLog.outError("player can't take item back: %u",myItems[i]->GetGUIDLow()); + } + // return the already removed items to the original owner + if (hisItems[i]) + { + if (!playerCanTrade) + sLog.outError("player can't store item: %u",hisItems[i]->GetGUIDLow()); + if (_player->pTrader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, hisItems[i], false) == EQUIP_ERR_OK) + _player->pTrader->MoveItemToInventory(traderDst, hisItems[i], true, true); + else + sLog.outError("trader can't take item back: %u",hisItems[i]->GetGUIDLow()); + } + } + } +} + +//============================================================== + +void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) +{ + Item *myItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; + Item *hisItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; + bool myCanCompleteTrade=true,hisCanCompleteTrade=true; + + if (!GetPlayer()->pTrader) + return; + + // not accept case incorrect money amount + if (_player->tradeGold > _player->GetMoney()) + { + SendNotification(LANG_NOT_ENOUGH_GOLD); + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->acceptTrade = false; + return; + } + + // not accept case incorrect money amount + if (_player->pTrader->tradeGold > _player->pTrader->GetMoney()) + { + _player->pTrader->GetSession()->SendNotification(LANG_NOT_ENOUGH_GOLD); + SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->pTrader->acceptTrade = false; + return; + } + + // not accept if some items now can't be trade (cheating) + for (int i=0; itradeItems[i] != 0) + { + if (Item* item =_player->GetItemByGuid(_player->tradeItems[i])) + { + if (!item->CanBeTraded()) + { + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + } + } + if (_player->pTrader->tradeItems[i] != 0) + { + if (Item* item =_player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i])) + { + if (!item->CanBeTraded()) + { + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + } + } + } + + _player->acceptTrade = true; + if (_player->pTrader->acceptTrade) + { + // inform partner client + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); + + // store items in local list and set 'in-trade' flag + for (int i=0; itradeItems[i] != 0) + { + //Can return NULL + myItems[i] = _player->GetItemByGuid(_player->tradeItems[i]); + if (myItems[i]) + { + myItems[i]->SetInTrade(); + sLog.outDebug("Player trade item bag: %u slot: %u", myItems[i]->GetBagSlot(), myItems[i]->GetSlot()); + } + } + if (_player->pTrader->tradeItems[i] != 0) + { + //Can return NULL + hisItems[i]=_player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]); + if (hisItems[i]) + { + hisItems[i]->SetInTrade(); + sLog.outDebug("Player trade item bag: %u slot: %u", hisItems[i]->GetBagSlot(), hisItems[i]->GetSlot()); + } + } + } + + // test if item will fit in each inventory + hisCanCompleteTrade = (_player->pTrader->CanStoreItems(myItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); + myCanCompleteTrade = (_player->CanStoreItems(hisItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); + + // clear 'in-trade' flag + for (int i=0; iSetInTrade(false); + if (hisItems[i]) hisItems[i]->SetInTrade(false); + } + + // in case of missing space report error + if (!myCanCompleteTrade) + { + SendNotification(LANG_NOT_FREE_TRADE_SLOTS); + GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS); + SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + return; + } + else if (!hisCanCompleteTrade) + { + SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS); + GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS); + SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + return; + } + + // execute trade: 1. remove + for (int i=0; iSetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID()); + iPtr = _player->GetItemByGuid(_player->tradeItems[i]); + _player->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true); + } + if (hisItems[i]) + { + hisItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR,_player->pTrader->GetGUID()); + iPtr = _player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]); + _player->pTrader->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true); + } + } + + // execute trade: 2. store + moveItems(myItems, hisItems); + + // logging money + if (sWorld.getConfig(CONFIG_GM_LOG_TRADE)) + { + if (_player->GetSession()->GetSecurity() > SEC_PLAYER && _player->tradeGold > 0) + { + sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", + _player->GetName(),_player->GetSession()->GetAccountId(), + _player->tradeGold, + _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId()); + } + if (_player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && _player->pTrader->tradeGold > 0) + { + sLog.outCommand(_player->pTrader->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", + _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(), + _player->pTrader->tradeGold, + _player->GetName(),_player->GetSession()->GetAccountId()); + } + } + + // update money + _player->ModifyMoney(-int32(_player->tradeGold)); + _player->ModifyMoney(_player->pTrader->tradeGold); + _player->pTrader->ModifyMoney(-int32(_player->pTrader->tradeGold)); + _player->pTrader->ModifyMoney(_player->tradeGold); + + _player->ClearTrade(); + _player->pTrader->ClearTrade(); + + // desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards) + CharacterDatabase.BeginTransaction(); + _player->SaveInventoryAndGoldToDB(); + _player->pTrader->SaveInventoryAndGoldToDB(); + CharacterDatabase.CommitTransaction(); + + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); + SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); + + _player->pTrader->pTrader = NULL; + _player->pTrader = NULL; + } + else + { + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); + } +} + +void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/) +{ + if (!GetPlayer()->pTrader) + return; + + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); + _player->acceptTrade = false; +} + +void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/) +{ + if (!_player->pTrader) + return; + + _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW); + _player->pTrader->ClearTrade(); + + SendTradeStatus(TRADE_STATUS_OPEN_WINDOW); + _player->ClearTrade(); +} + +void WorldSession::SendCancelTrade() +{ + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); +} + +void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/) +{ + // sended also after LOGOUT COMPLETE + if (_player) // needed because STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT + _player->TradeCancel(true); +} + +void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) +{ + if (GetPlayer()->pTrader) + return; + + uint64 ID; + + if (!GetPlayer()->isAlive()) + { + SendTradeStatus(TRADE_STATUS_YOU_DEAD); + return; + } + + if (GetPlayer()->hasUnitState(UNIT_STAT_STUNNED)) + { + SendTradeStatus(TRADE_STATUS_YOU_STUNNED); + return; + } + + if (isLogingOut()) + { + SendTradeStatus(TRADE_STATUS_YOU_LOGOUT); + return; + } + + if (GetPlayer()->isInFlight()) + { + SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); + return; + } + + if (GetPlayer()->getLevel() < sWorld.getConfig(CONFIG_TRADE_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_TRADE_REQ), sWorld.getConfig(CONFIG_TRADE_LEVEL_REQ)); + return; + } + + recvPacket >> ID; + + Player* pOther = ObjectAccessor::FindPlayer(ID); + + if (!pOther) + { + SendTradeStatus(TRADE_STATUS_NO_TARGET); + return; + } + + if (pOther == GetPlayer() || pOther->pTrader) + { + SendTradeStatus(TRADE_STATUS_BUSY); + return; + } + + if (!pOther->isAlive()) + { + SendTradeStatus(TRADE_STATUS_TARGET_DEAD); + return; + } + + if (pOther->isInFlight()) + { + SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); + return; + } + + if (pOther->hasUnitState(UNIT_STAT_STUNNED)) + { + SendTradeStatus(TRADE_STATUS_TARGET_STUNNED); + return; + } + + if (pOther->GetSession()->isLogingOut()) + { + SendTradeStatus(TRADE_STATUS_TARGET_LOGOUT); + return; + } + + if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) + { + SendTradeStatus(TRADE_STATUS_IGNORE_YOU); + return; + } + + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && pOther->GetTeam() !=_player->GetTeam()) + { + SendTradeStatus(TRADE_STATUS_WRONG_FACTION); + return; + } + + if (!pOther->IsWithinDistInMap(_player,10.0f,false)) + { + SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); + return; + } + + if (pOther->getLevel() < sWorld.getConfig(CONFIG_TRADE_LEVEL_REQ)) + { + SendNotification(GetTrinityString(LANG_TRADE_OTHER_REQ), sWorld.getConfig(CONFIG_TRADE_LEVEL_REQ)); + return; + } + + // OK start trade + _player->pTrader = pOther; + pOther->pTrader =_player; + + WorldPacket data(SMSG_TRADE_STATUS, 12); + data << (uint32) TRADE_STATUS_BEGIN_TRADE; + data << (uint64)_player->GetGUID(); + _player->pTrader->GetSession()->SendPacket(&data); +} + +void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket) +{ + if (!_player->pTrader) + return; + + uint32 gold; + + recvPacket >> gold; + + // gold can be incorrect, but this is checked at trade finished. + _player->tradeGold = gold; + + _player->pTrader->GetSession()->SendUpdateTrade(); +} + +void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket) +{ + if (!_player->pTrader) + return; + + // send update + uint8 tradeSlot; + uint8 bag; + uint8 slot; + + recvPacket >> tradeSlot; + recvPacket >> bag; + recvPacket >> slot; + + // invalid slot number + if (tradeSlot >= TRADE_SLOT_COUNT) + { + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + + // check cheating, can't fail with correct client operations + Item* item = _player->GetItemByPos(bag,slot); + if (!item || (tradeSlot != TRADE_SLOT_NONTRADED && !item->CanBeTraded())) + { + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + + uint64 iGUID = item->GetGUID(); + + // prevent place single item into many trade slots using cheating and client bugs + for (int i = 0; i < TRADE_SLOT_COUNT; ++i) + { + if (_player->tradeItems[i] == iGUID) + { + // cheating attempt + SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); + return; + } + } + + _player->tradeItems[tradeSlot] = iGUID; + + _player->pTrader->GetSession()->SendUpdateTrade(); +} + +void WorldSession::HandleClearTradeItemOpcode(WorldPacket& recvPacket) +{ + if (!_player->pTrader) + return; + + uint8 tradeSlot; + recvPacket >> tradeSlot; + + // invalid slot number + if (tradeSlot >= TRADE_SLOT_COUNT) + return; + + _player->tradeItems[tradeSlot] = 0; + + _player->pTrader->GetSession()->SendUpdateTrade(); +} + diff --git a/src/server/game/Server/Protocol/Handlers/VoiceChatHandler.cpp b/src/server/game/Server/Protocol/Handlers/VoiceChatHandler.cpp new file mode 100644 index 00000000000..78aafe1999b --- /dev/null +++ b/src/server/game/Server/Protocol/Handlers/VoiceChatHandler.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "Log.h" + +void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_VOICE_SESSION_ENABLE"); + // uint8 isVoiceEnabled, uint8 isMicrophoneEnabled + recv_data.read_skip(); + recv_data.read_skip(); + recv_data.hexlike(); +} + +void WorldSession::HandleChannelVoiceOnOpcode(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_CHANNEL_VOICE_ON"); + // Enable Voice button in channel context menu + recv_data.hexlike(); +} + +void WorldSession::HandleSetActiveVoiceChannel(WorldPacket & recv_data) +{ + sLog.outDebug("WORLD: CMSG_SET_ACTIVE_VOICE_CHANNEL"); + recv_data.read_skip(); + recv_data.read_skip(); + recv_data.hexlike(); +} + diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp new file mode 100644 index 00000000000..0b67199b4ea --- /dev/null +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -0,0 +1,1338 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup u2w +*/ + +#include "Opcodes.h" +#include "WorldSession.h" + +/// Correspondence between opcodes and their names +OpcodeHandler opcodeTable[NUM_MSG_TYPES] = +{ + /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode }, + /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00D*/ { "CMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00E*/ { "SMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01E*/ { "SMSG_REFER_A_FRIEND_EXPIRED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x032*/ { "SMSG_DESTRUCTIBLE_BUILDING_DAMAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode }, + /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode }, + /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode }, + /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode }, + /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode }, + /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode }, + /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode }, + /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode }, + /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery }, + /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode }, + /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode }, + /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageTextQueryOpcode }, + /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode }, + /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode }, + /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode }, + /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode }, + /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode }, + /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleContactListOpcode }, + /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode }, + /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode }, + /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetContactNotesOpcode }, + /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode }, + /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode }, + /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode }, + /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode }, + /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode }, + /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteOpcode }, + /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode }, + /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode }, + /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode }, + /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupDisbandOpcode }, + /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode }, + /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode }, + /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode }, + /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode }, + /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode }, + /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode }, + /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode }, + /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode }, + /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode }, + /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode }, + /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode }, + /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode }, + /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode }, + /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode }, + /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleJoinChannel }, + /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleLeaveChannel }, + /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList }, + /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword }, + /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner }, + /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner }, + /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator }, + /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator }, + /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute }, + /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute }, + /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite }, + /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick }, + /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan }, + /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban }, + /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnouncements }, + /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate }, + /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode }, + /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode }, + /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem }, + /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode }, + /*0x0B2*/ { "CMSG_DESTROY_ITEMS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode }, + /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, + /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER, &WorldSession::HandleMoveWorldportAckOpcode }, + /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, + /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, + /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, + /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, + /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera }, + /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinematic }, + /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag }, + /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear }, + /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset }, + /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode }, + /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode }, + /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode }, + /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode }, + /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode }, + /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode }, + /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem }, + /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode }, + /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode }, + /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode }, + /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode }, + /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode }, + /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode }, + /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode }, + /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode }, + /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode }, + /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode }, + /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode }, + /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, &WorldSession::HandleCancelTradeOpcode}, + /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode }, + /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode }, + /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode }, + /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar }, + /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat }, + /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode }, + /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode }, + /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode }, + /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode }, + /*0x137*/ { "SMSG_EQUIPMENT_SET_SAVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling }, + /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode }, + /*0x13E*/ { "CMSG_EQUIPMENT_SET_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetDelete }, + /*0x13F*/ { "CMSG_INSTANCE_LOCK_WARNING_RESPONSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode }, + /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode }, + /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x147*/ { "SMSG_INSTANCE_LOCK_WARNING_QUERY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14B*/ { "SMSG_BATTLEFIELD_PORT_DENIED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x152*/ { "SMSG_BREAK_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode }, + /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode }, + /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode }, + /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode }, + /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode }, + /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode }, + /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode }, + /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode }, + /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction }, + /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction }, + /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon }, + /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename }, + /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode }, + /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode }, + /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode }, + /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode}, + /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode }, + /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQueryQuestOpcode}, + /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestAutoLaunch }, + /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode}, + /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCompleteQuest }, + /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode}, + /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode}, + /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel }, + /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest }, + /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest }, + /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept }, + /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandlePushQuestToParty }, + /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode }, + /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode }, + /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode }, + /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode }, + /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode }, + /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes }, + /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode }, + /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode }, + /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode }, + /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode }, + /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode }, + /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode }, + /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode }, + /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode }, + /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode }, + /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode }, + /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode }, + /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode }, + /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode }, + /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode }, + /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode }, + /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime }, + /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode }, + /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleReclaimCorpseOpcode }, + /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode }, + /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode }, + /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode }, + /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E3*/ { "CMSG_QUEST_POI_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPOIQuery }, + /*0x1E4*/ { "SMSG_QUEST_POI_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandlePetCastSpellOpcode }, + /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleSaveGuildEmblemOpcode }, + /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode}, + /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode }, + /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode }, + /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1FD*/ { "CMSG_PLAYER_DIFFICULTY_CHANGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1FF*/ { "SMSG_LFG_PLAYER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x200*/ { "SMSG_LFG_TELEPORT_DENIED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode }, + /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode }, + /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateOpcode }, + /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleRequestAccountData }, + /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleUpdateAccountData }, + /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20E*/ { "SMSG_PLAYER_DIFFICULTY_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode }, + /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode }, + /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode }, + /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode}, + /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode}, + /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x21E*/ { "SMSG_SET_REST_START_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode }, + /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode }, + /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode }, + /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode }, + /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode }, + /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode }, + /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail }, + /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMailList }, + /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldListOpcode }, + /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery }, + /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleMailTakeMoney }, + /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailTakeItem }, + /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMailMarkAsRead }, + /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleMailReturnToSender }, + /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete }, + /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem }, + /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode }, + /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP }, + /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode }, + /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem }, + /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem }, + /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems }, + /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems }, + /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid }, + /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems }, + /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode }, + /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, + /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode }, + /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode}, + /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, + /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet }, + /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet }, + /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot }, + /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet }, + /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet }, + /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult }, + /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode }, + /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode }, + /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode }, + /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode}, + /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode }, + /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode }, + /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryNextMailTime }, + /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleGroupRaidConvertOpcode }, + /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantLeaderOpcode}, + /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem }, + /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x292*/ { "CMSG_SET_SAVED_INSTANCE_EXTEND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x293*/ { "SMSG_LFG_OFFER_CONTINUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo }, + /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode }, + /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, + /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode }, + /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode }, + /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeConfirmOpcode }, + /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode }, + /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode }, + /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B9*/ { "CMSG_SHOWING_HELM", STATUS_LOGGEDIN, &WorldSession::HandleShowingHelmOpcode }, + /*0x2BA*/ { "CMSG_SHOWING_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleShowingCloakOpcode }, + /*0x2BB*/ { "SMSG_LFG_ROLE_CHOSEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBarToggles }, + /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode }, + /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode }, + /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleCharRenameOpcode }, + /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleMoveSplineDoneOpcode }, + /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode }, + /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode }, + /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck }, + /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, + /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleMoveNotActiveMover }, + /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode }, + /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleFieldPortOpcode }, + /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode }, + /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattlemasterHelloOpcode }, + /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandlePVPLogDataOpcode }, + /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleLeaveBattlefieldOpcode }, + /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode}, + /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode}, + /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode }, + /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode}, + /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattlemasterJoinOpcode }, + /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode }, + /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoTextOpcode }, + /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiExpressOpcode }, + /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionInactiveOpcode }, + /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionOpcode }, + /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode }, + /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidTargetUpdateOpcode }, + /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode }, + /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleSetDungeonDifficultyOpcode}, + /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_NEVER, &WorldSession::Handle_NULL },//LOGGEDIN, &WorldSession::HandleGMSurveySubmit }, + /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveSetCanFlyAckOpcode }, + /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode }, + /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode }, + /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode }, + /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteOpcode }, + /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAcceptOpcode }, + /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDeclineOpcode }, + /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode }, + /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveOpcode }, + /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode }, + /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaderOpcode }, + /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattlemasterJoinArena }, + /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x35C*/ { "CMSG_LFG_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgJoinOpcode }, + /*0x35D*/ { "CMSG_LFG_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleLfgLeaveOpcode }, + /*0x35E*/ { "CMSG_SEARCH_LFG_JOIN", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x35F*/ { "CMSG_SEARCH_LFG_LEAVE", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x360*/ { "SMSG_UPDATE_LFG_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x361*/ { "SMSG_LFG_PROPOSAL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x362*/ { "CMSG_LFG_PROPOSAL_RESULT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x363*/ { "SMSG_LFG_ROLE_CHECK_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x364*/ { "SMSG_LFG_JOIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x365*/ { "SMSG_LFG_QUEUE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgCommentOpcode }, + /*0x367*/ { "SMSG_LFG_UPDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x368*/ { "SMSG_LFG_UPDATE_PARTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x369*/ { "SMSG_LFG_UPDATE_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36A*/ { "CMSG_LFG_SET_ROLES", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetRolesOpcode }, + /*0x36B*/ { "CMSG_LFG_SET_NEEDS", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x36C*/ { "CMSG_LFG_SET_BOOT_VOTE", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x36D*/ { "SMSG_LFG_BOOT_PROPOSAL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36E*/ { "CMSG_LFD_PLAYER_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLfgPlayerLockInfoRequestOpcode}, + /*0x36F*/ { "SMSG_LFG_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x370*/ { "CMSG_LFG_TELEPORT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x371*/ { "CMSG_LFD_PARTY_LOCK_INFO_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLfgPartyLockInfoRequestOpcode}, + /*0x372*/ { "SMSG_LFG_PARTY_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleSetTitleOpcode }, + /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelMountAuraOpcode }, + /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaTeamsOpcode }, + /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempEnchantmentOpcode}, + /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode }, + /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmSplitOpcode }, + /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandlePartyAssignmentOpcode }, + /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleTimeSyncResp }, + /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, + /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSessionEnableOpcode }, + /*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B1*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B2*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B3*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B4*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B5*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B6*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B7*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B8*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B9*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BA*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BB*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BC*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BD*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BE*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BF*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C0*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C1*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C3*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C4*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C5*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C6*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishedOpcode}, + /*0x3C7*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleComplainOpcode }, + /*0x3C8*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C9*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3CA*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CB*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CD*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CF*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D0*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D1*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D2*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelDisplayListQuery }, + /*0x3D3*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleSetActiveVoiceChannel }, + /*0x3D4*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleGetChannelMemberCount }, + /*0x3D5*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3D6*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelVoiceOnOpcode }, + /*0x3D7*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D8*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D9*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3DA*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3DB*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DC*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DD*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DE*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DF*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3E0*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E1*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E2*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E3*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E4*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleReportPvPAFK }, + /*0x3E5*/ { "SMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3E6*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankerActivate }, + /*0x3E7*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQueryTab }, + /*0x3E8*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E9*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSwapItems }, + /*0x3EA*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab }, + /*0x3EB*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankUpdateTab }, + /*0x3EC*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositMoney }, + /*0x3ED*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdrawMoney }, + /*0x3EE*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLogQuery }, + /*0x3EF*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleSetChannelWatch }, + /*0x3F0*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F1*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F2*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F3*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F4*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F5*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F6*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F7*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F8*/ { "CMSG_SPELLCLICK", STATUS_LOGGEDIN, &WorldSession::HandleSpellClick }, + /*0x3F9*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3FA*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3FB*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3FC*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3FD*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildPermissions }, + /*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankMoneyWithdrawn }, + /*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogQueryOpcode }, + /*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_LOGGEDIN, &WorldSession::HandleMirrrorImageDataRequest }, + /*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x405*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x406*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x407*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x408*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x409*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleOptOutOfLootOpcode }, + /*0x40A*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleQueryGuildBankTabText }, + /*0x40B*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleSetGuildBankTabText }, + /*0x40C*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40D*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40E*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40F*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelDeclineInvite }, + /*0x410*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x411*/ { "SMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x412*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x413*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x414*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroyed }, + /*0x415*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x416*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x417*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusMultipleQuery}, + /*0x418*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x419*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleSetPlayerDeclinedNames }, + /*0x41A*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41B*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x41C*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x41D*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41E*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41F*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x420*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x421*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x422*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x423*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x424*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x425*/ { "CMSG_CHANGE_PERSONAL_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x426*/ { "CMSG_ALTER_APPEARANCE", STATUS_LOGGEDIN, &WorldSession::HandleAlterAppearance }, + /*0x427*/ { "SMSG_ENABLE_BARBER_SHOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x428*/ { "SMSG_BARBER_SHOP_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x429*/ { "CMSG_CALENDAR_GET_CALENDAR", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetCalendar }, + /*0x42A*/ { "CMSG_CALENDAR_GET_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetEvent }, + /*0x42B*/ { "CMSG_CALENDAR_GUILD_FILTER", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGuildFilter }, + /*0x42C*/ { "CMSG_CALENDAR_ARENA_TEAM", STATUS_LOGGEDIN, &WorldSession::HandleCalendarArenaTeam }, + /*0x42D*/ { "CMSG_CALENDAR_ADD_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarAddEvent }, + /*0x42E*/ { "CMSG_CALENDAR_UPDATE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarUpdateEvent }, + /*0x42F*/ { "CMSG_CALENDAR_REMOVE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarRemoveEvent }, + /*0x430*/ { "CMSG_CALENDAR_COPY_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarCopyEvent }, + /*0x431*/ { "CMSG_CALENDAR_EVENT_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventInvite }, + /*0x432*/ { "CMSG_CALENDAR_EVENT_RSVP", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRsvp }, + /*0x433*/ { "CMSG_CALENDAR_EVENT_REMOVE_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRemoveInvite }, + /*0x434*/ { "CMSG_CALENDAR_EVENT_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventStatus }, + /*0x435*/ { "CMSG_CALENDAR_EVENT_MODERATOR_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventModeratorStatus}, + /*0x436*/ { "SMSG_CALENDAR_SEND_CALENDAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x437*/ { "SMSG_CALENDAR_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x438*/ { "SMSG_CALENDAR_FILTER_GUILD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x439*/ { "SMSG_CALENDAR_ARENA_TEAM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43A*/ { "SMSG_CALENDAR_EVENT_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43B*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43C*/ { "SMSG_CALENDAR_EVENT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43D*/ { "SMSG_CALENDAR_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43E*/ { "SMSG_CALENDAR_RAID_LOCKOUT_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43F*/ { "SMSG_CALENDAR_RAID_LOCKOUT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x440*/ { "SMSG_CALENDAR_EVENT_INVITE_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x441*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x442*/ { "SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x443*/ { "SMSG_CALENDAR_EVENT_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x444*/ { "SMSG_CALENDAR_EVENT_UPDATED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x445*/ { "SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x446*/ { "CMSG_CALENDAR_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleCalendarComplain }, + /*0x447*/ { "CMSG_CALENDAR_GET_NUM_PENDING", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetNumPending }, + /*0x448*/ { "SMSG_CALENDAR_SEND_NUM_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x449*/ { "CMSG_SAVE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44A*/ { "SMSG_NOTIFY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x44B*/ { "CMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44C*/ { "SMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x44D*/ { "CMSG_LOAD_DANCES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44E*/ { "CMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44F*/ { "SMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x450*/ { "CMSG_SYNC_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x451*/ { "CMSG_DANCE_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x452*/ { "SMSG_DANCE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x453*/ { "SMSG_INVALIDATE_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x454*/ { "CMSG_DELETE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x455*/ { "SMSG_LEARNED_DANCE_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x456*/ { "CMSG_LEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x457*/ { "CMSG_UNLEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x458*/ { "CMSG_SET_RUNE_COUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x459*/ { "CMSG_SET_RUNE_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45A*/ { "MSG_MOVE_SET_PITCH_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45B*/ { "MSG_MOVE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45C*/ { "SMSG_FORCE_PITCH_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x45F*/ { "SMSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x460*/ { "MSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x461*/ { "CMSG_MOVE_ABANDON_TRANSPORT_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x466*/ { "CMSG_SET_GLYPH_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x467*/ { "CMSG_SET_GLYPH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x468*/ { "SMSG_ACHIEVEMENT_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x469*/ { "SMSG_DYNAMIC_DROP_ROLL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46A*/ { "SMSG_CRITERIA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46B*/ { "CMSG_QUERY_INSPECT_ACHIEVEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleQueryInspectAchievements }, + /*0x46C*/ { "SMSG_RESPOND_INSPECT_ACHIEVEMENTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46D*/ { "CMSG_DISMISS_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleDismissControlledVehicle }, + /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x471*/ { "SMSG_GROUP_SWAP_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize }, + /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_LOGGEDIN, &WorldSession::HandleRequestVehicleExit }, + /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, + /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, + /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, + /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandlePetLearnTalent }, + /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x47D*/ { "SMSG_ALL_ACHIEVEMENT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x47E*/ { "CMSG_FORCE_SAY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x47F*/ { "SMSG_HEALTH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x480*/ { "SMSG_POWER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x481*/ { "CMSG_GAMEOBJ_REPORT_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameobjectReportUse }, + /*0x482*/ { "SMSG_HIGHEST_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x483*/ { "SMSG_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x484*/ { "SMSG_THREAT_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x485*/ { "SMSG_THREAT_CLEAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x486*/ { "SMSG_CONVERT_RUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x487*/ { "SMSG_RESYNC_RUNES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x488*/ { "SMSG_ADD_RUNE_POWER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x489*/ { "CMSG_START_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x48A*/ { "CMSG_REMOVE_GLYPH", STATUS_LOGGEDIN, &WorldSession::HandleRemoveGlyph }, + /*0x48B*/ { "CMSG_DUMP_OBJECTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x48C*/ { "SMSG_DUMP_OBJECTS_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x48D*/ { "CMSG_DISMISS_CRITTER", STATUS_LOGGEDIN, &WorldSession::HandleDismissCritter }, + /*0x48E*/ { "SMSG_NOTIFY_DEST_LOC_SPELL_CAST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x48F*/ { "CMSG_AUCTION_LIST_PENDING_SALES", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListPendingSales }, + /*0x490*/ { "SMSG_AUCTION_LIST_PENDING_SALES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x491*/ { "SMSG_MODIFY_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x492*/ { "SMSG_PET_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x493*/ { "CMSG_ENABLETAXI", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes }, + /*0x494*/ { "SMSG_PRE_RESURRECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x495*/ { "SMSG_AURA_UPDATE_ALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x496*/ { "SMSG_AURA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x497*/ { "CMSG_FLOOD_GRACE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleChangeSeatsOnControlledVehicle}, + /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49F*/ { "SMSG_ACHIEVEMENT_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A0*/ { "CMSG_SERVER_INFO_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A1*/ { "SMSG_SERVER_INFO_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A2*/ { "CMSG_CHECK_LOGIN_CRITERIA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A3*/ { "SMSG_SERVER_BUCK_DATA_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A4*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A5*/ { "UMSG_UNKNOWN_1189", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A6*/ { "SMSG_BATTLEGROUND_INFO_THROTTLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A7*/ { "SMSG_PLAYER_VEHICLE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A8*/ { "CMSG_PLAYER_VEHICLE_ENTER", STATUS_LOGGEDIN, &WorldSession::HandleEnterPlayerVehicle }, + /*0x4A9*/ { "CMSG_EJECT_PASSENGER", STATUS_LOGGEDIN, &WorldSession::HandleEjectPasenger }, + /*0x4AA*/ { "SMSG_PET_GUIDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4AB*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4AC*/ { "UMSG_UNKNOWN_1196", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4AD*/ { "UMSG_UNKNOWN_1197", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4AE*/ { "UMSG_UNKNOWN_1198", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4AF*/ { "UMSG_UNKNOWN_1199", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4B0*/ { "UMSG_UNKNOWN_1200", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4B1*/ { "UMSG_UNKNOWN_1201", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4B2*/ { "SMSG_ITEM_REFUND_INFO_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4B3*/ { "CMSG_ITEM_REFUND_INFO", STATUS_LOGGEDIN, &WorldSession::HandleItemRefundInfoRequest }, + /*0x4B4*/ { "CMSG_ITEM_REFUND", STATUS_LOGGEDIN, &WorldSession::HandleItemRefund }, + /*0x4B5*/ { "SMSG_ITEM_REFUND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4B6*/ { "CMSG_CORPSE_MAP_POSITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseMapPositionQuery }, + /*0x4B7*/ { "SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4B8*/ { "CMSG_LFG_SET_ROLES_2", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x4B9*/ { "UMSG_UNKNOWN_1209", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4BA*/ { "CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4BB*/ { "SMSG_CALENDAR_ACTION_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4BC*/ { "SMSG_EQUIPMENT_SET_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4BD*/ { "CMSG_EQUIPMENT_SET_SAVE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetSave }, + /*0x4BE*/ { "CMSG_UPDATE_PROJECTILE_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4BF*/ { "SMSG_SET_PROJECTILE_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4C0*/ { "SMSG_TALENTS_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4C1*/ { "CMSG_LEARN_PREVIEW_TALENTS", STATUS_LOGGEDIN, &WorldSession::HandleLearnPreviewTalents }, + /*0x4C2*/ { "CMSG_LEARN_PREVIEW_TALENTS_PET", STATUS_LOGGEDIN, &WorldSession::HandleLearnPreviewTalentsPet }, + /*0x4C3*/ { "UMSG_UNKNOWN_1219", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4C4*/ { "UMSG_UNKNOWN_1220", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4C5*/ { "UMSG_UNKNOWN_1221", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4C6*/ { "UMSG_UNKNOWN_1222", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4C7*/ { "SMSG_ARENA_OPPONENT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4C8*/ { "SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4C9*/ { "UMSG_UNKNOWN_1225", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4CA*/ { "UMSG_UNKNOWN_1226", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4CB*/ { "UMSG_UNKNOWN_1227", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4CC*/ { "UMSG_UNKNOWN_1228", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4CD*/ { "SMSG_MULTIPLE_PACKETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4CE*/ { "SMSG_UNKNOWN_1230", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4CF*/ { "CMSG_UNKNOWN_1231_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4D0*/ { "SMSG_UNKNOWN_1232", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4D1*/ { "CMSG_UNKNOWN_1233_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4D2*/ { "SMSG_UNKNOWN_1234", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4D3*/ { "SMSG_UNKNOWN_1235", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4D4*/ { "SMSG_UNKNOWN_1236", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4D5*/ { "CMSG_EQUIPMENT_SET_USE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetUse }, + /*0x4D6*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4D7*/ { "UMSG_UNKNOWN_1239", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4D8*/ { "SMSG_UNKNOWN_1240", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4D9*/ { "CMSG_CHAR_FACTION_CHANGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4DA*/ { "SMSG_CHAR_FACTION_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4DB*/ { "UMSG_UNKNOWN_1243", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4DC*/ { "UMSG_UNKNOWN_1244", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4DD*/ { "UMSG_UNKNOWN_1245", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4DE*/ { "SMSG_BATTLEFIELD_MGR_ENTRY_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4E0*/ { "SMSG_BATTLEFIELD_MGR_ENTERED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4E1*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4E2*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4E3*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4E4*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4E5*/ { "SMSG_BATTLEFIELD_MGR_EJECT_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4E6*/ { "SMSG_BATTLEFIELD_MGR_EJECTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4E7*/ { "CMSG_BATTLEFIELD_MGR_EXIT_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4E8*/ { "SMSG_BATTLEFIELD_MGR_STATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4E9*/ { "UMSG_UNKNOWN_1257", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4EA*/ { "UMSG_UNKNOWN_1258", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4EB*/ { "MSG_SET_RAID_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleSetRaidDifficultyOpcode }, + /*0x4EC*/ { "UMSG_UNKNOWN_1260", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4ED*/ { "SMSG_TOGGLE_XP_GAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4EE*/ { "SMSG_GMRESPONSE_DB_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4EF*/ { "SMSG_GMRESPONSE_RECEIVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4F0*/ { "CMSG_GMRESPONSE_RESOLVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4F1*/ { "SMSG_GMRESPONSE_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4F2*/ { "UMSG_UNKNOWN_1266", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4F3*/ { "UMSG_UNKNOWN_1267", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4F4*/ { "UMSG_UNKNOWN_1268", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4F5*/ { "UMSG_UNKNOWN_1269", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4F6*/ { "CMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleWorldStateUITimerUpdate }, + /*0x4F7*/ { "SMSG_WORLD_STATE_UI_TIMER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4F8*/ { "CMSG_CHAR_RACE_CHANGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4F9*/ { "UMSG_UNKNOWN_1273", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4FA*/ { "SMSG_TALENTS_INVOLUNTARILY_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4FB*/ { "UMSG_UNKNOWN_1275", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4FC*/ { "SMSG_UNKNOWN_1276", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4FD*/ { "SMSG_LOOT_SLOT_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4FE*/ { "UMSG_UNKNOWN_1278", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4FF*/ { "CMSG_READY_FOR_ACCOUNT_DATA_TIMES", STATUS_AUTHED, &WorldSession::HandleReadyForAccountDataTimes }, + /*0x500*/ { "CMSG_QUERY_QUESTS_COMPLETED", STATUS_LOGGEDIN, &WorldSession::HandleQueryQuestsCompleted }, + /*0x501*/ { "SMSG_QUERY_QUESTS_COMPLETED_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x502*/ { "CMSG_GM_REPORT_LAG", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x503*/ { "UMSG_UNKNOWN_1283", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x504*/ { "UMSG_UNKNOWN_1284", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x505*/ { "UMSG_UNKNOWN_1285", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x506*/ { "SMSG_CORPSE_NOT_IN_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x507*/ { "UMSG_UNKNOWN_1287", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x508*/ { "CMSG_SET_ALLOW_LOW_LEVEL_RAID1", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x509*/ { "CMSG_SET_ALLOW_LOW_LEVEL_RAID2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x50A*/ { "SMSG_CAMERA_SHAKE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x50B*/ { "SMSG_UPDATE_ITEM_ENCHANTMENTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x50C*/ { "UMSG_UNKNOWN_1292", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x50D*/ { "SMSG_REDIRECT_CLIENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x50E*/ { "CMSG_REDIRECTION_FAILED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x50F*/ { "SMSG_UNKNOWN_1295", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x510*/ { "CMSG_UNKNOWN_1296", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x511*/ { "SMSG_FORCE_SEND_QUEUED_PACKETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x512*/ { "CMSG_REDIRECTION_AUTH_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x513*/ { "UMSG_UNKNOWN_1299", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x514*/ { "SMSG_COMBAT_LOG_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x515*/ { "SMSG_LFG_OPEN_FROM_GOSSIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x516*/ { "SMSG_UNKNOWN_1302", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x517*/ { "CMSG_UNKNOWN_1303", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x518*/ { "SMSG_UNKNOWN_1304", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x519*/ { "UMSG_UNKNOWN_1305", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x51A*/ { "UMSG_UNKNOWN_1306", STATUS_NEVER, &WorldSession::Handle_NULL }, +}; diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h new file mode 100644 index 00000000000..4ae6931c3f5 --- /dev/null +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -0,0 +1,1378 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup u2w +/// @{ +/// \file + +#ifndef _OPCODES_H +#define _OPCODES_H + +#include "Common.h" + +// Note: this include need for be sure have full definition of class WorldSession +// if this class definition not complite then VS for x64 release use different size for +// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from +// table opcodeTable in source when Opcode.h included but WorldSession.h not included +#include "WorldSession.h" + +/// List of Opcodes +enum Opcodes +{ + MSG_NULL_ACTION = 0x000, + CMSG_BOOTME = 0x001, + CMSG_DBLOOKUP = 0x002, + SMSG_DBLOOKUP = 0x003, + CMSG_QUERY_OBJECT_POSITION = 0x004, + SMSG_QUERY_OBJECT_POSITION = 0x005, + CMSG_QUERY_OBJECT_ROTATION = 0x006, + SMSG_QUERY_OBJECT_ROTATION = 0x007, + CMSG_WORLD_TELEPORT = 0x008, + CMSG_TELEPORT_TO_UNIT = 0x009, + CMSG_ZONE_MAP = 0x00A, + SMSG_ZONE_MAP = 0x00B, + CMSG_DEBUG_CHANGECELLZONE = 0x00C, + CMSG_MOVE_CHARACTER_CHEAT = 0x00D, + SMSG_MOVE_CHARACTER_CHEAT = 0x00E, + CMSG_RECHARGE = 0x00F, + CMSG_LEARN_SPELL = 0x010, + CMSG_CREATEMONSTER = 0x011, + CMSG_DESTROYMONSTER = 0x012, + CMSG_CREATEITEM = 0x013, + CMSG_CREATEGAMEOBJECT = 0x014, + SMSG_CHECK_FOR_BOTS = 0x015, + CMSG_MAKEMONSTERATTACKGUID = 0x016, + CMSG_BOT_DETECTED2 = 0x017, + CMSG_FORCEACTION = 0x018, + CMSG_FORCEACTIONONOTHER = 0x019, + CMSG_FORCEACTIONSHOW = 0x01A, + SMSG_FORCEACTIONSHOW = 0x01B, + CMSG_PETGODMODE = 0x01C, + SMSG_PETGODMODE = 0x01D, + SMSG_REFER_A_FRIEND_EXPIRED = 0x01E, + CMSG_WEATHER_SPEED_CHEAT = 0x01F, + CMSG_UNDRESSPLAYER = 0x020, + CMSG_BEASTMASTER = 0x021, + CMSG_GODMODE = 0x022, + SMSG_GODMODE = 0x023, + CMSG_CHEAT_SETMONEY = 0x024, + CMSG_LEVEL_CHEAT = 0x025, + CMSG_PET_LEVEL_CHEAT = 0x026, + CMSG_SET_WORLDSTATE = 0x027, + CMSG_COOLDOWN_CHEAT = 0x028, + CMSG_USE_SKILL_CHEAT = 0x029, + CMSG_FLAG_QUEST = 0x02A, + CMSG_FLAG_QUEST_FINISH = 0x02B, + CMSG_CLEAR_QUEST = 0x02C, + CMSG_SEND_EVENT = 0x02D, + CMSG_DEBUG_AISTATE = 0x02E, + SMSG_DEBUG_AISTATE = 0x02F, + CMSG_DISABLE_PVP_CHEAT = 0x030, + CMSG_ADVANCE_SPAWN_TIME = 0x031, + SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x032, + CMSG_AUTH_SRP6_BEGIN = 0x033, + CMSG_AUTH_SRP6_PROOF = 0x034, + CMSG_AUTH_SRP6_RECODE = 0x035, + CMSG_CHAR_CREATE = 0x036, + CMSG_CHAR_ENUM = 0x037, + CMSG_CHAR_DELETE = 0x038, + SMSG_AUTH_SRP6_RESPONSE = 0x039, + SMSG_CHAR_CREATE = 0x03A, + SMSG_CHAR_ENUM = 0x03B, + SMSG_CHAR_DELETE = 0x03C, + CMSG_PLAYER_LOGIN = 0x03D, + SMSG_NEW_WORLD = 0x03E, + SMSG_TRANSFER_PENDING = 0x03F, + SMSG_TRANSFER_ABORTED = 0x040, + SMSG_CHARACTER_LOGIN_FAILED = 0x041, + SMSG_LOGIN_SETTIMESPEED = 0x042, + SMSG_GAMETIME_UPDATE = 0x043, + CMSG_GAMETIME_SET = 0x044, + SMSG_GAMETIME_SET = 0x045, + CMSG_GAMESPEED_SET = 0x046, + SMSG_GAMESPEED_SET = 0x047, + CMSG_SERVERTIME = 0x048, + SMSG_SERVERTIME = 0x049, + CMSG_PLAYER_LOGOUT = 0x04A, + CMSG_LOGOUT_REQUEST = 0x04B, + SMSG_LOGOUT_RESPONSE = 0x04C, + SMSG_LOGOUT_COMPLETE = 0x04D, + CMSG_LOGOUT_CANCEL = 0x04E, + SMSG_LOGOUT_CANCEL_ACK = 0x04F, + CMSG_NAME_QUERY = 0x050, + SMSG_NAME_QUERY_RESPONSE = 0x051, + CMSG_PET_NAME_QUERY = 0x052, + SMSG_PET_NAME_QUERY_RESPONSE = 0x053, + CMSG_GUILD_QUERY = 0x054, + SMSG_GUILD_QUERY_RESPONSE = 0x055, + CMSG_ITEM_QUERY_SINGLE = 0x056, + CMSG_ITEM_QUERY_MULTIPLE = 0x057, + SMSG_ITEM_QUERY_SINGLE_RESPONSE = 0x058, + SMSG_ITEM_QUERY_MULTIPLE_RESPONSE = 0x059, + CMSG_PAGE_TEXT_QUERY = 0x05A, + SMSG_PAGE_TEXT_QUERY_RESPONSE = 0x05B, + CMSG_QUEST_QUERY = 0x05C, + SMSG_QUEST_QUERY_RESPONSE = 0x05D, + CMSG_GAMEOBJECT_QUERY = 0x05E, + SMSG_GAMEOBJECT_QUERY_RESPONSE = 0x05F, + CMSG_CREATURE_QUERY = 0x060, + SMSG_CREATURE_QUERY_RESPONSE = 0x061, + CMSG_WHO = 0x062, + SMSG_WHO = 0x063, + CMSG_WHOIS = 0x064, + SMSG_WHOIS = 0x065, + CMSG_CONTACT_LIST = 0x066, + SMSG_CONTACT_LIST = 0x067, + SMSG_FRIEND_STATUS = 0x068, + CMSG_ADD_FRIEND = 0x069, + CMSG_DEL_FRIEND = 0x06A, + CMSG_SET_CONTACT_NOTES = 0x06B, + CMSG_ADD_IGNORE = 0x06C, + CMSG_DEL_IGNORE = 0x06D, + CMSG_GROUP_INVITE = 0x06E, + SMSG_GROUP_INVITE = 0x06F, + CMSG_GROUP_CANCEL = 0x070, + SMSG_GROUP_CANCEL = 0x071, + CMSG_GROUP_ACCEPT = 0x072, + CMSG_GROUP_DECLINE = 0x073, + SMSG_GROUP_DECLINE = 0x074, + CMSG_GROUP_UNINVITE = 0x075, + CMSG_GROUP_UNINVITE_GUID = 0x076, + SMSG_GROUP_UNINVITE = 0x077, + CMSG_GROUP_SET_LEADER = 0x078, + SMSG_GROUP_SET_LEADER = 0x079, + CMSG_LOOT_METHOD = 0x07A, + CMSG_GROUP_DISBAND = 0x07B, + SMSG_GROUP_DESTROYED = 0x07C, + SMSG_GROUP_LIST = 0x07D, + SMSG_PARTY_MEMBER_STATS = 0x07E, + SMSG_PARTY_COMMAND_RESULT = 0x07F, + UMSG_UPDATE_GROUP_MEMBERS = 0x080, + CMSG_GUILD_CREATE = 0x081, + CMSG_GUILD_INVITE = 0x082, + SMSG_GUILD_INVITE = 0x083, + CMSG_GUILD_ACCEPT = 0x084, + CMSG_GUILD_DECLINE = 0x085, + SMSG_GUILD_DECLINE = 0x086, + CMSG_GUILD_INFO = 0x087, + SMSG_GUILD_INFO = 0x088, + CMSG_GUILD_ROSTER = 0x089, + SMSG_GUILD_ROSTER = 0x08A, + CMSG_GUILD_PROMOTE = 0x08B, + CMSG_GUILD_DEMOTE = 0x08C, + CMSG_GUILD_LEAVE = 0x08D, + CMSG_GUILD_REMOVE = 0x08E, + CMSG_GUILD_DISBAND = 0x08F, + CMSG_GUILD_LEADER = 0x090, + CMSG_GUILD_MOTD = 0x091, + SMSG_GUILD_EVENT = 0x092, + SMSG_GUILD_COMMAND_RESULT = 0x093, + UMSG_UPDATE_GUILD = 0x094, + CMSG_MESSAGECHAT = 0x095, + SMSG_MESSAGECHAT = 0x096, + CMSG_JOIN_CHANNEL = 0x097, + CMSG_LEAVE_CHANNEL = 0x098, + SMSG_CHANNEL_NOTIFY = 0x099, + CMSG_CHANNEL_LIST = 0x09A, + SMSG_CHANNEL_LIST = 0x09B, + CMSG_CHANNEL_PASSWORD = 0x09C, + CMSG_CHANNEL_SET_OWNER = 0x09D, + CMSG_CHANNEL_OWNER = 0x09E, + CMSG_CHANNEL_MODERATOR = 0x09F, + CMSG_CHANNEL_UNMODERATOR = 0x0A0, + CMSG_CHANNEL_MUTE = 0x0A1, + CMSG_CHANNEL_UNMUTE = 0x0A2, + CMSG_CHANNEL_INVITE = 0x0A3, + CMSG_CHANNEL_KICK = 0x0A4, + CMSG_CHANNEL_BAN = 0x0A5, + CMSG_CHANNEL_UNBAN = 0x0A6, + CMSG_CHANNEL_ANNOUNCEMENTS = 0x0A7, + CMSG_CHANNEL_MODERATE = 0x0A8, + SMSG_UPDATE_OBJECT = 0x0A9, + SMSG_DESTROY_OBJECT = 0x0AA, + CMSG_USE_ITEM = 0x0AB, + CMSG_OPEN_ITEM = 0x0AC, + CMSG_READ_ITEM = 0x0AD, + SMSG_READ_ITEM_OK = 0x0AE, + SMSG_READ_ITEM_FAILED = 0x0AF, + SMSG_ITEM_COOLDOWN = 0x0B0, + CMSG_GAMEOBJ_USE = 0x0B1, + CMSG_DESTROY_ITEMS = 0x0B2, + SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3, + CMSG_AREATRIGGER = 0x0B4, + MSG_MOVE_START_FORWARD = 0x0B5, + MSG_MOVE_START_BACKWARD = 0x0B6, + MSG_MOVE_STOP = 0x0B7, + MSG_MOVE_START_STRAFE_LEFT = 0x0B8, + MSG_MOVE_START_STRAFE_RIGHT = 0x0B9, + MSG_MOVE_STOP_STRAFE = 0x0BA, + MSG_MOVE_JUMP = 0x0BB, + MSG_MOVE_START_TURN_LEFT = 0x0BC, + MSG_MOVE_START_TURN_RIGHT = 0x0BD, + MSG_MOVE_STOP_TURN = 0x0BE, + MSG_MOVE_START_PITCH_UP = 0x0BF, + MSG_MOVE_START_PITCH_DOWN = 0x0C0, + MSG_MOVE_STOP_PITCH = 0x0C1, + MSG_MOVE_SET_RUN_MODE = 0x0C2, + MSG_MOVE_SET_WALK_MODE = 0x0C3, + MSG_MOVE_TOGGLE_LOGGING = 0x0C4, + MSG_MOVE_TELEPORT = 0x0C5, + MSG_MOVE_TELEPORT_CHEAT = 0x0C6, + MSG_MOVE_TELEPORT_ACK = 0x0C7, + MSG_MOVE_TOGGLE_FALL_LOGGING = 0x0C8, + MSG_MOVE_FALL_LAND = 0x0C9, + MSG_MOVE_START_SWIM = 0x0CA, + MSG_MOVE_STOP_SWIM = 0x0CB, + MSG_MOVE_SET_RUN_SPEED_CHEAT = 0x0CC, + MSG_MOVE_SET_RUN_SPEED = 0x0CD, + MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT = 0x0CE, + MSG_MOVE_SET_RUN_BACK_SPEED = 0x0CF, + MSG_MOVE_SET_WALK_SPEED_CHEAT = 0x0D0, + MSG_MOVE_SET_WALK_SPEED = 0x0D1, + MSG_MOVE_SET_SWIM_SPEED_CHEAT = 0x0D2, + MSG_MOVE_SET_SWIM_SPEED = 0x0D3, + MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT = 0x0D4, + MSG_MOVE_SET_SWIM_BACK_SPEED = 0x0D5, + MSG_MOVE_SET_ALL_SPEED_CHEAT = 0x0D6, + MSG_MOVE_SET_TURN_RATE_CHEAT = 0x0D7, + MSG_MOVE_SET_TURN_RATE = 0x0D8, + MSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x0D9, + MSG_MOVE_SET_FACING = 0x0DA, + MSG_MOVE_SET_PITCH = 0x0DB, + MSG_MOVE_WORLDPORT_ACK = 0x0DC, + SMSG_MONSTER_MOVE = 0x0DD, + SMSG_MOVE_WATER_WALK = 0x0DE, + SMSG_MOVE_LAND_WALK = 0x0DF, + MSG_MOVE_SET_RAW_POSITION_ACK = 0x0E0, + CMSG_MOVE_SET_RAW_POSITION = 0x0E1, + SMSG_FORCE_RUN_SPEED_CHANGE = 0x0E2, + CMSG_FORCE_RUN_SPEED_CHANGE_ACK = 0x0E3, + SMSG_FORCE_RUN_BACK_SPEED_CHANGE = 0x0E4, + CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK = 0x0E5, + SMSG_FORCE_SWIM_SPEED_CHANGE = 0x0E6, + CMSG_FORCE_SWIM_SPEED_CHANGE_ACK = 0x0E7, + SMSG_FORCE_MOVE_ROOT = 0x0E8, + CMSG_FORCE_MOVE_ROOT_ACK = 0x0E9, + SMSG_FORCE_MOVE_UNROOT = 0x0EA, + CMSG_FORCE_MOVE_UNROOT_ACK = 0x0EB, + MSG_MOVE_ROOT = 0x0EC, + MSG_MOVE_UNROOT = 0x0ED, + MSG_MOVE_HEARTBEAT = 0x0EE, + SMSG_MOVE_KNOCK_BACK = 0x0EF, + CMSG_MOVE_KNOCK_BACK_ACK = 0x0F0, + MSG_MOVE_KNOCK_BACK = 0x0F1, + SMSG_MOVE_FEATHER_FALL = 0x0F2, + SMSG_MOVE_NORMAL_FALL = 0x0F3, + SMSG_MOVE_SET_HOVER = 0x0F4, + SMSG_MOVE_UNSET_HOVER = 0x0F5, + CMSG_MOVE_HOVER_ACK = 0x0F6, + MSG_MOVE_HOVER = 0x0F7, + CMSG_TRIGGER_CINEMATIC_CHEAT = 0x0F8, + CMSG_OPENING_CINEMATIC = 0x0F9, + SMSG_TRIGGER_CINEMATIC = 0x0FA, + CMSG_NEXT_CINEMATIC_CAMERA = 0x0FB, + CMSG_COMPLETE_CINEMATIC = 0x0FC, + SMSG_TUTORIAL_FLAGS = 0x0FD, + CMSG_TUTORIAL_FLAG = 0x0FE, + CMSG_TUTORIAL_CLEAR = 0x0FF, + CMSG_TUTORIAL_RESET = 0x100, + CMSG_STANDSTATECHANGE = 0x101, + CMSG_EMOTE = 0x102, + SMSG_EMOTE = 0x103, + CMSG_TEXT_EMOTE = 0x104, + SMSG_TEXT_EMOTE = 0x105, + CMSG_AUTOEQUIP_GROUND_ITEM = 0x106, + CMSG_AUTOSTORE_GROUND_ITEM = 0x107, + CMSG_AUTOSTORE_LOOT_ITEM = 0x108, + CMSG_STORE_LOOT_IN_SLOT = 0x109, + CMSG_AUTOEQUIP_ITEM = 0x10A, + CMSG_AUTOSTORE_BAG_ITEM = 0x10B, + CMSG_SWAP_ITEM = 0x10C, + CMSG_SWAP_INV_ITEM = 0x10D, + CMSG_SPLIT_ITEM = 0x10E, + CMSG_AUTOEQUIP_ITEM_SLOT = 0x10F, + OBSOLETE_DROP_ITEM = 0x110, + CMSG_DESTROYITEM = 0x111, + SMSG_INVENTORY_CHANGE_FAILURE = 0x112, + SMSG_OPEN_CONTAINER = 0x113, + CMSG_INSPECT = 0x114, + SMSG_INSPECT = 0x115, + CMSG_INITIATE_TRADE = 0x116, + CMSG_BEGIN_TRADE = 0x117, + CMSG_BUSY_TRADE = 0x118, + CMSG_IGNORE_TRADE = 0x119, + CMSG_ACCEPT_TRADE = 0x11A, + CMSG_UNACCEPT_TRADE = 0x11B, + CMSG_CANCEL_TRADE = 0x11C, + CMSG_SET_TRADE_ITEM = 0x11D, + CMSG_CLEAR_TRADE_ITEM = 0x11E, + CMSG_SET_TRADE_GOLD = 0x11F, + SMSG_TRADE_STATUS = 0x120, + SMSG_TRADE_STATUS_EXTENDED = 0x121, + SMSG_INITIALIZE_FACTIONS = 0x122, + SMSG_SET_FACTION_VISIBLE = 0x123, + SMSG_SET_FACTION_STANDING = 0x124, + CMSG_SET_FACTION_ATWAR = 0x125, + CMSG_SET_FACTION_CHEAT = 0x126, + SMSG_SET_PROFICIENCY = 0x127, + CMSG_SET_ACTION_BUTTON = 0x128, + SMSG_ACTION_BUTTONS = 0x129, + SMSG_INITIAL_SPELLS = 0x12A, + SMSG_LEARNED_SPELL = 0x12B, + SMSG_SUPERCEDED_SPELL = 0x12C, + CMSG_NEW_SPELL_SLOT = 0x12D, + CMSG_CAST_SPELL = 0x12E, + CMSG_CANCEL_CAST = 0x12F, + SMSG_CAST_FAILED = 0x130, + SMSG_SPELL_START = 0x131, + SMSG_SPELL_GO = 0x132, + SMSG_SPELL_FAILURE = 0x133, + SMSG_SPELL_COOLDOWN = 0x134, + SMSG_COOLDOWN_EVENT = 0x135, + CMSG_CANCEL_AURA = 0x136, + SMSG_EQUIPMENT_SET_SAVED = 0x137, + SMSG_PET_CAST_FAILED = 0x138, + MSG_CHANNEL_START = 0x139, + MSG_CHANNEL_UPDATE = 0x13A, + CMSG_CANCEL_CHANNELLING = 0x13B, + SMSG_AI_REACTION = 0x13C, + CMSG_SET_SELECTION = 0x13D, + CMSG_EQUIPMENT_SET_DELETE = 0x13E, + CMSG_INSTANCE_LOCK_WARNING_RESPONSE = 0x13F, + CMSG_UNUSED2 = 0x140, + CMSG_ATTACKSWING = 0x141, + CMSG_ATTACKSTOP = 0x142, + SMSG_ATTACKSTART = 0x143, + SMSG_ATTACKSTOP = 0x144, + SMSG_ATTACKSWING_NOTINRANGE = 0x145, + SMSG_ATTACKSWING_BADFACING = 0x146, + SMSG_INSTANCE_LOCK_WARNING_QUERY = 0x147, + SMSG_ATTACKSWING_DEADTARGET = 0x148, + SMSG_ATTACKSWING_CANT_ATTACK = 0x149, + SMSG_ATTACKERSTATEUPDATE = 0x14A, + SMSG_BATTLEFIELD_PORT_DENIED = 0x14B, + SMSG_DAMAGE_DONE_OBSOLETE = 0x14C, + SMSG_UNIT_SPELLCAST_START = 0x14D, + SMSG_CANCEL_COMBAT = 0x14E, + SMSG_SPELLBREAKLOG = 0x14F, + SMSG_SPELLHEALLOG = 0x150, + SMSG_SPELLENERGIZELOG = 0x151, + SMSG_BREAK_TARGET = 0x152, + CMSG_SAVE_PLAYER = 0x153, + CMSG_SETDEATHBINDPOINT = 0x154, + SMSG_BINDPOINTUPDATE = 0x155, + CMSG_GETDEATHBINDZONE = 0x156, + SMSG_BINDZONEREPLY = 0x157, + SMSG_PLAYERBOUND = 0x158, + SMSG_CLIENT_CONTROL_UPDATE = 0x159, + CMSG_REPOP_REQUEST = 0x15A, + SMSG_RESURRECT_REQUEST = 0x15B, + CMSG_RESURRECT_RESPONSE = 0x15C, + CMSG_LOOT = 0x15D, + CMSG_LOOT_MONEY = 0x15E, + CMSG_LOOT_RELEASE = 0x15F, + SMSG_LOOT_RESPONSE = 0x160, + SMSG_LOOT_RELEASE_RESPONSE = 0x161, + SMSG_LOOT_REMOVED = 0x162, + SMSG_LOOT_MONEY_NOTIFY = 0x163, + SMSG_LOOT_ITEM_NOTIFY = 0x164, + SMSG_LOOT_CLEAR_MONEY = 0x165, + SMSG_ITEM_PUSH_RESULT = 0x166, + SMSG_DUEL_REQUESTED = 0x167, + SMSG_DUEL_OUTOFBOUNDS = 0x168, + SMSG_DUEL_INBOUNDS = 0x169, + SMSG_DUEL_COMPLETE = 0x16A, + SMSG_DUEL_WINNER = 0x16B, + CMSG_DUEL_ACCEPTED = 0x16C, + CMSG_DUEL_CANCELLED = 0x16D, + SMSG_MOUNTRESULT = 0x16E, + SMSG_DISMOUNTRESULT = 0x16F, + SMSG_PUREMOUNT_CANCELLED_OBSOLETE = 0x170, // ERR_REMOVE_FROM_PVP_QUEUE_* events + CMSG_MOUNTSPECIAL_ANIM = 0x171, + SMSG_MOUNTSPECIAL_ANIM = 0x172, + SMSG_PET_TAME_FAILURE = 0x173, + CMSG_PET_SET_ACTION = 0x174, + CMSG_PET_ACTION = 0x175, + CMSG_PET_ABANDON = 0x176, + CMSG_PET_RENAME = 0x177, + SMSG_PET_NAME_INVALID = 0x178, + SMSG_PET_SPELLS = 0x179, + SMSG_PET_MODE = 0x17A, + CMSG_GOSSIP_HELLO = 0x17B, + CMSG_GOSSIP_SELECT_OPTION = 0x17C, + SMSG_GOSSIP_MESSAGE = 0x17D, + SMSG_GOSSIP_COMPLETE = 0x17E, + CMSG_NPC_TEXT_QUERY = 0x17F, + SMSG_NPC_TEXT_UPDATE = 0x180, + SMSG_NPC_WONT_TALK = 0x181, + CMSG_QUESTGIVER_STATUS_QUERY = 0x182, + SMSG_QUESTGIVER_STATUS = 0x183, + CMSG_QUESTGIVER_HELLO = 0x184, + SMSG_QUESTGIVER_QUEST_LIST = 0x185, + CMSG_QUESTGIVER_QUERY_QUEST = 0x186, + CMSG_QUESTGIVER_QUEST_AUTOLAUNCH = 0x187, + SMSG_QUESTGIVER_QUEST_DETAILS = 0x188, + CMSG_QUESTGIVER_ACCEPT_QUEST = 0x189, + CMSG_QUESTGIVER_COMPLETE_QUEST = 0x18A, + SMSG_QUESTGIVER_REQUEST_ITEMS = 0x18B, + CMSG_QUESTGIVER_REQUEST_REWARD = 0x18C, + SMSG_QUESTGIVER_OFFER_REWARD = 0x18D, + CMSG_QUESTGIVER_CHOOSE_REWARD = 0x18E, + SMSG_QUESTGIVER_QUEST_INVALID = 0x18F, + CMSG_QUESTGIVER_CANCEL = 0x190, + SMSG_QUESTGIVER_QUEST_COMPLETE = 0x191, + SMSG_QUESTGIVER_QUEST_FAILED = 0x192, + CMSG_QUESTLOG_SWAP_QUEST = 0x193, + CMSG_QUESTLOG_REMOVE_QUEST = 0x194, + SMSG_QUESTLOG_FULL = 0x195, + SMSG_QUESTUPDATE_FAILED = 0x196, + SMSG_QUESTUPDATE_FAILEDTIMER = 0x197, + SMSG_QUESTUPDATE_COMPLETE = 0x198, + SMSG_QUESTUPDATE_ADD_KILL = 0x199, + SMSG_QUESTUPDATE_ADD_ITEM = 0x19A, + CMSG_QUEST_CONFIRM_ACCEPT = 0x19B, + SMSG_QUEST_CONFIRM_ACCEPT = 0x19C, + CMSG_PUSHQUESTTOPARTY = 0x19D, + CMSG_LIST_INVENTORY = 0x19E, + SMSG_LIST_INVENTORY = 0x19F, + CMSG_SELL_ITEM = 0x1A0, + SMSG_SELL_ITEM = 0x1A1, + CMSG_BUY_ITEM = 0x1A2, + CMSG_BUY_ITEM_IN_SLOT = 0x1A3, + SMSG_BUY_ITEM = 0x1A4, + SMSG_BUY_FAILED = 0x1A5, + CMSG_TAXICLEARALLNODES = 0x1A6, + CMSG_TAXIENABLEALLNODES = 0x1A7, + CMSG_TAXISHOWNODES = 0x1A8, + SMSG_SHOWTAXINODES = 0x1A9, + CMSG_TAXINODE_STATUS_QUERY = 0x1AA, + SMSG_TAXINODE_STATUS = 0x1AB, + CMSG_TAXIQUERYAVAILABLENODES = 0x1AC, + CMSG_ACTIVATETAXI = 0x1AD, + SMSG_ACTIVATETAXIREPLY = 0x1AE, + SMSG_NEW_TAXI_PATH = 0x1AF, + CMSG_TRAINER_LIST = 0x1B0, + SMSG_TRAINER_LIST = 0x1B1, + CMSG_TRAINER_BUY_SPELL = 0x1B2, + SMSG_TRAINER_BUY_SUCCEEDED = 0x1B3, + SMSG_TRAINER_BUY_FAILED = 0x1B4, + CMSG_BINDER_ACTIVATE = 0x1B5, + SMSG_PLAYERBINDERROR = 0x1B6, + CMSG_BANKER_ACTIVATE = 0x1B7, + SMSG_SHOW_BANK = 0x1B8, + CMSG_BUY_BANK_SLOT = 0x1B9, + SMSG_BUY_BANK_SLOT_RESULT = 0x1BA, + CMSG_PETITION_SHOWLIST = 0x1BB, + SMSG_PETITION_SHOWLIST = 0x1BC, + CMSG_PETITION_BUY = 0x1BD, + CMSG_PETITION_SHOW_SIGNATURES = 0x1BE, + SMSG_PETITION_SHOW_SIGNATURES = 0x1BF, + CMSG_PETITION_SIGN = 0x1C0, + SMSG_PETITION_SIGN_RESULTS = 0x1C1, + MSG_PETITION_DECLINE = 0x1C2, + CMSG_OFFER_PETITION = 0x1C3, + CMSG_TURN_IN_PETITION = 0x1C4, + SMSG_TURN_IN_PETITION_RESULTS = 0x1C5, + CMSG_PETITION_QUERY = 0x1C6, + SMSG_PETITION_QUERY_RESPONSE = 0x1C7, + SMSG_FISH_NOT_HOOKED = 0x1C8, + SMSG_FISH_ESCAPED = 0x1C9, + CMSG_BUG = 0x1CA, + SMSG_NOTIFICATION = 0x1CB, + CMSG_PLAYED_TIME = 0x1CC, + SMSG_PLAYED_TIME = 0x1CD, + CMSG_QUERY_TIME = 0x1CE, + SMSG_QUERY_TIME_RESPONSE = 0x1CF, + SMSG_LOG_XPGAIN = 0x1D0, + SMSG_AURACASTLOG = 0x1D1, + CMSG_RECLAIM_CORPSE = 0x1D2, + CMSG_WRAP_ITEM = 0x1D3, + SMSG_LEVELUP_INFO = 0x1D4, + MSG_MINIMAP_PING = 0x1D5, + SMSG_RESISTLOG = 0x1D6, + SMSG_ENCHANTMENTLOG = 0x1D7, + CMSG_SET_SKILL_CHEAT = 0x1D8, + SMSG_START_MIRROR_TIMER = 0x1D9, + SMSG_PAUSE_MIRROR_TIMER = 0x1DA, + SMSG_STOP_MIRROR_TIMER = 0x1DB, + CMSG_PING = 0x1DC, + SMSG_PONG = 0x1DD, + SMSG_CLEAR_COOLDOWN = 0x1DE, + SMSG_GAMEOBJECT_PAGETEXT = 0x1DF, + CMSG_SETSHEATHED = 0x1E0, + SMSG_COOLDOWN_CHEAT = 0x1E1, + SMSG_SPELL_DELAYED = 0x1E2, + CMSG_QUEST_POI_QUERY = 0x1E3, + SMSG_QUEST_POI_QUERY_RESPONSE = 0x1E4, + CMSG_GHOST = 0x1E5, + CMSG_GM_INVIS = 0x1E6, + SMSG_INVALID_PROMOTION_CODE = 0x1E7, + MSG_GM_BIND_OTHER = 0x1E8, + MSG_GM_SUMMON = 0x1E9, + SMSG_ITEM_TIME_UPDATE = 0x1EA, + SMSG_ITEM_ENCHANT_TIME_UPDATE = 0x1EB, + SMSG_AUTH_CHALLENGE = 0x1EC, + CMSG_AUTH_SESSION = 0x1ED, + SMSG_AUTH_RESPONSE = 0x1EE, + MSG_GM_SHOWLABEL = 0x1EF, + CMSG_PET_CAST_SPELL = 0x1F0, + MSG_SAVE_GUILD_EMBLEM = 0x1F1, + MSG_TABARDVENDOR_ACTIVATE = 0x1F2, + SMSG_PLAY_SPELL_VISUAL = 0x1F3, + CMSG_ZONEUPDATE = 0x1F4, + SMSG_PARTYKILLLOG = 0x1F5, + SMSG_COMPRESSED_UPDATE_OBJECT = 0x1F6, + SMSG_PLAY_SPELL_IMPACT = 0x1F7, + SMSG_EXPLORATION_EXPERIENCE = 0x1F8, + CMSG_GM_SET_SECURITY_GROUP = 0x1F9, + CMSG_GM_NUKE = 0x1FA, + MSG_RANDOM_ROLL = 0x1FB, + SMSG_ENVIRONMENTALDAMAGELOG = 0x1FC, + CMSG_PLAYER_DIFFICULTY_CHANGE = 0x1FD, + SMSG_RWHOIS = 0x1FE, + SMSG_LFG_PLAYER_REWARD = 0x1FF, // uint32, uint8, uint32, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32,uint32,uint32} + SMSG_LFG_TELEPORT_DENIED = 0x200, // uint32 (1,2,4,6;0,5,7) + CMSG_UNLEARN_SPELL = 0x201, + CMSG_UNLEARN_SKILL = 0x202, + SMSG_REMOVED_SPELL = 0x203, + CMSG_DECHARGE = 0x204, + CMSG_GMTICKET_CREATE = 0x205, + SMSG_GMTICKET_CREATE = 0x206, + CMSG_GMTICKET_UPDATETEXT = 0x207, + SMSG_GMTICKET_UPDATETEXT = 0x208, + SMSG_ACCOUNT_DATA_TIMES = 0x209, + CMSG_REQUEST_ACCOUNT_DATA = 0x20A, + CMSG_UPDATE_ACCOUNT_DATA = 0x20B, + SMSG_UPDATE_ACCOUNT_DATA = 0x20C, + SMSG_CLEAR_FAR_SIGHT_IMMEDIATE = 0x20D, + SMSG_PLAYER_DIFFICULTY_CHANGE = 0x20E, + CMSG_GM_TEACH = 0x20F, + CMSG_GM_CREATE_ITEM_TARGET = 0x210, + CMSG_GMTICKET_GETTICKET = 0x211, + SMSG_GMTICKET_GETTICKET = 0x212, + CMSG_UNLEARN_TALENTS = 0x213, + SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE = 0x214, + SMSG_GAMEOBJECT_DESPAWN_ANIM = 0x215, + MSG_CORPSE_QUERY = 0x216, + CMSG_GMTICKET_DELETETICKET = 0x217, + SMSG_GMTICKET_DELETETICKET = 0x218, + SMSG_CHAT_WRONG_FACTION = 0x219, + CMSG_GMTICKET_SYSTEMSTATUS = 0x21A, + SMSG_GMTICKET_SYSTEMSTATUS = 0x21B, + CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C, + CMSG_SET_STAT_CHEAT = 0x21D, + SMSG_QUEST_FORCE_REMOVE = 0x21E, // uint32 questid + CMSG_SKILL_BUY_STEP = 0x21F, + CMSG_SKILL_BUY_RANK = 0x220, + CMSG_XP_CHEAT = 0x221, + SMSG_SPIRIT_HEALER_CONFIRM = 0x222, + CMSG_CHARACTER_POINT_CHEAT = 0x223, + SMSG_GOSSIP_POI = 0x224, + CMSG_CHAT_IGNORED = 0x225, + CMSG_GM_VISION = 0x226, + CMSG_SERVER_COMMAND = 0x227, + CMSG_GM_SILENCE = 0x228, + CMSG_GM_REVEALTO = 0x229, + CMSG_GM_RESURRECT = 0x22A, + CMSG_GM_SUMMONMOB = 0x22B, + CMSG_GM_MOVECORPSE = 0x22C, + CMSG_GM_FREEZE = 0x22D, + CMSG_GM_UBERINVIS = 0x22E, + CMSG_GM_REQUEST_PLAYER_INFO = 0x22F, + SMSG_GM_PLAYER_INFO = 0x230, + CMSG_GUILD_RANK = 0x231, + CMSG_GUILD_ADD_RANK = 0x232, + CMSG_GUILD_DEL_RANK = 0x233, + CMSG_GUILD_SET_PUBLIC_NOTE = 0x234, + CMSG_GUILD_SET_OFFICER_NOTE = 0x235, + SMSG_LOGIN_VERIFY_WORLD = 0x236, + CMSG_CLEAR_EXPLORATION = 0x237, + CMSG_SEND_MAIL = 0x238, + SMSG_SEND_MAIL_RESULT = 0x239, + CMSG_GET_MAIL_LIST = 0x23A, + SMSG_MAIL_LIST_RESULT = 0x23B, + CMSG_BATTLEFIELD_LIST = 0x23C, + SMSG_BATTLEFIELD_LIST = 0x23D, + CMSG_BATTLEFIELD_JOIN = 0x23E, + SMSG_BATTLEFIELD_WIN_OBSOLETE = 0x23F, + SMSG_BATTLEFIELD_LOSE_OBSOLETE = 0x240, + CMSG_TAXICLEARNODE = 0x241, + CMSG_TAXIENABLENODE = 0x242, + CMSG_ITEM_TEXT_QUERY = 0x243, + SMSG_ITEM_TEXT_QUERY_RESPONSE = 0x244, + CMSG_MAIL_TAKE_MONEY = 0x245, + CMSG_MAIL_TAKE_ITEM = 0x246, + CMSG_MAIL_MARK_AS_READ = 0x247, + CMSG_MAIL_RETURN_TO_SENDER = 0x248, + CMSG_MAIL_DELETE = 0x249, + CMSG_MAIL_CREATE_TEXT_ITEM = 0x24A, + SMSG_SPELLLOGMISS = 0x24B, + SMSG_SPELLLOGEXECUTE = 0x24C, + SMSG_DEBUGAURAPROC = 0x24D, + SMSG_PERIODICAURALOG = 0x24E, + SMSG_SPELLDAMAGESHIELD = 0x24F, + SMSG_SPELLNONMELEEDAMAGELOG = 0x250, + CMSG_LEARN_TALENT = 0x251, + SMSG_RESURRECT_FAILED = 0x252, + CMSG_TOGGLE_PVP = 0x253, + SMSG_ZONE_UNDER_ATTACK = 0x254, + MSG_AUCTION_HELLO = 0x255, + CMSG_AUCTION_SELL_ITEM = 0x256, + CMSG_AUCTION_REMOVE_ITEM = 0x257, + CMSG_AUCTION_LIST_ITEMS = 0x258, + CMSG_AUCTION_LIST_OWNER_ITEMS = 0x259, + CMSG_AUCTION_PLACE_BID = 0x25A, + SMSG_AUCTION_COMMAND_RESULT = 0x25B, + SMSG_AUCTION_LIST_RESULT = 0x25C, + SMSG_AUCTION_OWNER_LIST_RESULT = 0x25D, + SMSG_AUCTION_BIDDER_NOTIFICATION = 0x25E, + SMSG_AUCTION_OWNER_NOTIFICATION = 0x25F, + SMSG_PROCRESIST = 0x260, + SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE = 0x261, + SMSG_DISPEL_FAILED = 0x262, + SMSG_SPELLORDAMAGE_IMMUNE = 0x263, + CMSG_AUCTION_LIST_BIDDER_ITEMS = 0x264, + SMSG_AUCTION_BIDDER_LIST_RESULT = 0x265, + SMSG_SET_FLAT_SPELL_MODIFIER = 0x266, + SMSG_SET_PCT_SPELL_MODIFIER = 0x267, + CMSG_SET_AMMO = 0x268, + SMSG_CORPSE_RECLAIM_DELAY = 0x269, + CMSG_SET_ACTIVE_MOVER = 0x26A, + CMSG_PET_CANCEL_AURA = 0x26B, + CMSG_PLAYER_AI_CHEAT = 0x26C, + CMSG_CANCEL_AUTO_REPEAT_SPELL = 0x26D, + MSG_GM_ACCOUNT_ONLINE = 0x26E, + MSG_LIST_STABLED_PETS = 0x26F, + CMSG_STABLE_PET = 0x270, + CMSG_UNSTABLE_PET = 0x271, + CMSG_BUY_STABLE_SLOT = 0x272, + SMSG_STABLE_RESULT = 0x273, + CMSG_STABLE_REVIVE_PET = 0x274, + CMSG_STABLE_SWAP_PET = 0x275, + MSG_QUEST_PUSH_RESULT = 0x276, + SMSG_PLAY_MUSIC = 0x277, + SMSG_PLAY_OBJECT_SOUND = 0x278, + CMSG_REQUEST_PET_INFO = 0x279, + CMSG_FAR_SIGHT = 0x27A, + SMSG_SPELLDISPELLOG = 0x27B, + SMSG_DAMAGE_CALC_LOG = 0x27C, + CMSG_ENABLE_DAMAGE_LOG = 0x27D, + CMSG_GROUP_CHANGE_SUB_GROUP = 0x27E, + CMSG_REQUEST_PARTY_MEMBER_STATS = 0x27F, + CMSG_GROUP_SWAP_SUB_GROUP = 0x280, + CMSG_RESET_FACTION_CHEAT = 0x281, + CMSG_AUTOSTORE_BANK_ITEM = 0x282, + CMSG_AUTOBANK_ITEM = 0x283, + MSG_QUERY_NEXT_MAIL_TIME = 0x284, + SMSG_RECEIVED_MAIL = 0x285, + SMSG_RAID_GROUP_ONLY = 0x286, + CMSG_SET_DURABILITY_CHEAT = 0x287, + CMSG_SET_PVP_RANK_CHEAT = 0x288, + CMSG_ADD_PVP_MEDAL_CHEAT = 0x289, + CMSG_DEL_PVP_MEDAL_CHEAT = 0x28A, + CMSG_SET_PVP_TITLE = 0x28B, + SMSG_PVP_CREDIT = 0x28C, + SMSG_AUCTION_REMOVED_NOTIFICATION = 0x28D, + CMSG_GROUP_RAID_CONVERT = 0x28E, + CMSG_GROUP_ASSISTANT_LEADER = 0x28F, + CMSG_BUYBACK_ITEM = 0x290, + SMSG_SERVER_MESSAGE = 0x291, + CMSG_SET_SAVED_INSTANCE_EXTEND = 0x292, // lua: SetSavedInstanceExtend + SMSG_LFG_OFFER_CONTINUE = 0x293, + CMSG_MEETINGSTONE_CHEAT = 0x294, // not found 3.3 + SMSG_MEETINGSTONE_SETQUEUE = 0x295, // string, showed in console + CMSG_MEETINGSTONE_INFO = 0x296, // EVENT_LFG_UPDATE + SMSG_MEETINGSTONE_COMPLETE = 0x297, // EVENT_MAIL_SHOW + SMSG_MEETINGSTONE_IN_PROGRESS = 0x298, // uint32, some UPDATE_COOLDOWN events + SMSG_MEETINGSTONE_MEMBER_ADDED = 0x299, // uint32, errors: ERR_NOT_IN_GROUP (2,51) and ERR_NOT_IN_RAID (3,39,40) + CMSG_GMTICKETSYSTEM_TOGGLE = 0x29A, + CMSG_CANCEL_GROWTH_AURA = 0x29B, + SMSG_CANCEL_AUTO_REPEAT = 0x29C, + SMSG_STANDSTATE_UPDATE = 0x29D, + SMSG_LOOT_ALL_PASSED = 0x29E, + SMSG_LOOT_ROLL_WON = 0x29F, + CMSG_LOOT_ROLL = 0x2A0, + SMSG_LOOT_START_ROLL = 0x2A1, + SMSG_LOOT_ROLL = 0x2A2, + CMSG_LOOT_MASTER_GIVE = 0x2A3, + SMSG_LOOT_MASTER_LIST = 0x2A4, + SMSG_SET_FORCED_REACTIONS = 0x2A5, + SMSG_SPELL_FAILED_OTHER = 0x2A6, + SMSG_GAMEOBJECT_RESET_STATE = 0x2A7, + CMSG_REPAIR_ITEM = 0x2A8, + SMSG_CHAT_PLAYER_NOT_FOUND = 0x2A9, + MSG_TALENT_WIPE_CONFIRM = 0x2AA, + SMSG_SUMMON_REQUEST = 0x2AB, + CMSG_SUMMON_RESPONSE = 0x2AC, + MSG_MOVE_TOGGLE_GRAVITY_CHEAT = 0x2AD, + SMSG_MONSTER_MOVE_TRANSPORT = 0x2AE, + SMSG_PET_BROKEN = 0x2AF, + MSG_MOVE_FEATHER_FALL = 0x2B0, + MSG_MOVE_WATER_WALK = 0x2B1, + CMSG_SERVER_BROADCAST = 0x2B2, + CMSG_SELF_RES = 0x2B3, + SMSG_FEIGN_DEATH_RESISTED = 0x2B4, + CMSG_RUN_SCRIPT = 0x2B5, + SMSG_SCRIPT_MESSAGE = 0x2B6, + SMSG_DUEL_COUNTDOWN = 0x2B7, + SMSG_AREA_TRIGGER_MESSAGE = 0x2B8, + CMSG_SHOWING_HELM = 0x2B9, + CMSG_SHOWING_CLOAK = 0x2BA, + SMSG_LFG_ROLE_CHOSEN = 0x2BB, + SMSG_PLAYER_SKINNED = 0x2BC, + SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD, + CMSG_SET_EXPLORATION = 0x2BE, + CMSG_SET_ACTIONBAR_TOGGLES = 0x2BF, + UMSG_DELETE_GUILD_CHARTER = 0x2C0, + MSG_PETITION_RENAME = 0x2C1, + SMSG_INIT_WORLD_STATES = 0x2C2, + SMSG_UPDATE_WORLD_STATE = 0x2C3, + CMSG_ITEM_NAME_QUERY = 0x2C4, + SMSG_ITEM_NAME_QUERY_RESPONSE = 0x2C5, + SMSG_PET_ACTION_FEEDBACK = 0x2C6, + CMSG_CHAR_RENAME = 0x2C7, + SMSG_CHAR_RENAME = 0x2C8, + CMSG_MOVE_SPLINE_DONE = 0x2C9, + CMSG_MOVE_FALL_RESET = 0x2CA, + SMSG_INSTANCE_SAVE_CREATED = 0x2CB, + SMSG_RAID_INSTANCE_INFO = 0x2CC, + CMSG_REQUEST_RAID_INFO = 0x2CD, + CMSG_MOVE_TIME_SKIPPED = 0x2CE, + CMSG_MOVE_FEATHER_FALL_ACK = 0x2CF, + CMSG_MOVE_WATER_WALK_ACK = 0x2D0, + CMSG_MOVE_NOT_ACTIVE_MOVER = 0x2D1, + SMSG_PLAY_SOUND = 0x2D2, + CMSG_BATTLEFIELD_STATUS = 0x2D3, + SMSG_BATTLEFIELD_STATUS = 0x2D4, + CMSG_BATTLEFIELD_PORT = 0x2D5, + MSG_INSPECT_HONOR_STATS = 0x2D6, + CMSG_BATTLEMASTER_HELLO = 0x2D7, + CMSG_MOVE_START_SWIM_CHEAT = 0x2D8, + CMSG_MOVE_STOP_SWIM_CHEAT = 0x2D9, + SMSG_FORCE_WALK_SPEED_CHANGE = 0x2DA, + CMSG_FORCE_WALK_SPEED_CHANGE_ACK = 0x2DB, + SMSG_FORCE_SWIM_BACK_SPEED_CHANGE = 0x2DC, + CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK = 0x2DD, + SMSG_FORCE_TURN_RATE_CHANGE = 0x2DE, + CMSG_FORCE_TURN_RATE_CHANGE_ACK = 0x2DF, + MSG_PVP_LOG_DATA = 0x2E0, + CMSG_LEAVE_BATTLEFIELD = 0x2E1, + CMSG_AREA_SPIRIT_HEALER_QUERY = 0x2E2, + CMSG_AREA_SPIRIT_HEALER_QUEUE = 0x2E3, + SMSG_AREA_SPIRIT_HEALER_TIME = 0x2E4, + CMSG_GM_UNTEACH = 0x2E5, + SMSG_WARDEN_DATA = 0x2E6, + CMSG_WARDEN_DATA = 0x2E7, + SMSG_GROUP_JOINED_BATTLEGROUND = 0x2E8, + MSG_BATTLEGROUND_PLAYER_POSITIONS = 0x2E9, + CMSG_PET_STOP_ATTACK = 0x2EA, + SMSG_BINDER_CONFIRM = 0x2EB, + SMSG_BATTLEGROUND_PLAYER_JOINED = 0x2EC, + SMSG_BATTLEGROUND_PLAYER_LEFT = 0x2ED, + CMSG_BATTLEMASTER_JOIN = 0x2EE, + SMSG_ADDON_INFO = 0x2EF, + CMSG_PET_UNLEARN = 0x2F0, // Deprecated 3.x + SMSG_PET_UNLEARN_CONFIRM = 0x2F1, // Deprecated 3.x + SMSG_PARTY_MEMBER_STATS_FULL = 0x2F2, + CMSG_PET_SPELL_AUTOCAST = 0x2F3, + SMSG_WEATHER = 0x2F4, + SMSG_PLAY_TIME_WARNING = 0x2F5, + SMSG_MINIGAME_SETUP = 0x2F6, + SMSG_MINIGAME_STATE = 0x2F7, + CMSG_MINIGAME_MOVE = 0x2F8, + SMSG_MINIGAME_MOVE_FAILED = 0x2F9, + SMSG_RAID_INSTANCE_MESSAGE = 0x2FA, + SMSG_COMPRESSED_MOVES = 0x2FB, + CMSG_GUILD_INFO_TEXT = 0x2FC, + SMSG_CHAT_RESTRICTED = 0x2FD, + SMSG_SPLINE_SET_RUN_SPEED = 0x2FE, + SMSG_SPLINE_SET_RUN_BACK_SPEED = 0x2FF, + SMSG_SPLINE_SET_SWIM_SPEED = 0x300, + SMSG_SPLINE_SET_WALK_SPEED = 0x301, + SMSG_SPLINE_SET_SWIM_BACK_SPEED = 0x302, + SMSG_SPLINE_SET_TURN_RATE = 0x303, + SMSG_SPLINE_MOVE_UNROOT = 0x304, + SMSG_SPLINE_MOVE_FEATHER_FALL = 0x305, + SMSG_SPLINE_MOVE_NORMAL_FALL = 0x306, + SMSG_SPLINE_MOVE_SET_HOVER = 0x307, + SMSG_SPLINE_MOVE_UNSET_HOVER = 0x308, + SMSG_SPLINE_MOVE_WATER_WALK = 0x309, + SMSG_SPLINE_MOVE_LAND_WALK = 0x30A, + SMSG_SPLINE_MOVE_START_SWIM = 0x30B, + SMSG_SPLINE_MOVE_STOP_SWIM = 0x30C, + SMSG_SPLINE_MOVE_SET_RUN_MODE = 0x30D, + SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x30E, + CMSG_GM_NUKE_ACCOUNT = 0x30F, + MSG_GM_DESTROY_CORPSE = 0x310, + CMSG_GM_DESTROY_ONLINE_CORPSE = 0x311, + CMSG_ACTIVATETAXIEXPRESS = 0x312, + SMSG_SET_FACTION_ATWAR = 0x313, + SMSG_GAMETIMEBIAS_SET = 0x314, + CMSG_DEBUG_ACTIONS_START = 0x315, + CMSG_DEBUG_ACTIONS_STOP = 0x316, + CMSG_SET_FACTION_INACTIVE = 0x317, + CMSG_SET_WATCHED_FACTION = 0x318, + MSG_MOVE_TIME_SKIPPED = 0x319, + SMSG_SPLINE_MOVE_ROOT = 0x31A, + CMSG_SET_EXPLORATION_ALL = 0x31B, + SMSG_INVALIDATE_PLAYER = 0x31C, + CMSG_RESET_INSTANCES = 0x31D, + SMSG_INSTANCE_RESET = 0x31E, + SMSG_INSTANCE_RESET_FAILED = 0x31F, + SMSG_UPDATE_LAST_INSTANCE = 0x320, + MSG_RAID_TARGET_UPDATE = 0x321, + MSG_RAID_READY_CHECK = 0x322, + CMSG_LUA_USAGE = 0x323, + SMSG_PET_ACTION_SOUND = 0x324, + SMSG_PET_DISMISS_SOUND = 0x325, + SMSG_GHOSTEE_GONE = 0x326, + CMSG_GM_UPDATE_TICKET_STATUS = 0x327, + SMSG_GM_TICKET_STATUS_UPDATE = 0x328, + MSG_SET_DUNGEON_DIFFICULTY = 0x329, + CMSG_GMSURVEY_SUBMIT = 0x32A, + SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x32B, + CMSG_IGNORE_KNOCKBACK_CHEAT = 0x32C, + SMSG_CHAT_PLAYER_AMBIGUOUS = 0x32D, + MSG_DELAY_GHOST_TELEPORT = 0x32E, + SMSG_SPELLINSTAKILLLOG = 0x32F, + SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x330, + CMSG_CHAT_FILTERED = 0x331, + SMSG_EXPECTED_SPAM_RECORDS = 0x332, + SMSG_SPELLSTEALLOG = 0x333, + CMSG_LOTTERY_QUERY_OBSOLETE = 0x334, + SMSG_LOTTERY_QUERY_RESULT_OBSOLETE = 0x335, + CMSG_BUY_LOTTERY_TICKET_OBSOLETE = 0x336, + SMSG_LOTTERY_RESULT_OBSOLETE = 0x337, + SMSG_CHARACTER_PROFILE = 0x338, + SMSG_CHARACTER_PROFILE_REALM_CONNECTED = 0x339, + SMSG_DEFENSE_MESSAGE = 0x33A, + SMSG_INSTANCE_DIFFICULTY = 0x33B, + MSG_GM_RESETINSTANCELIMIT = 0x33C, + SMSG_MOTD = 0x33D, + SMSG_MOVE_SET_FLIGHT = 0x33E, + SMSG_MOVE_UNSET_FLIGHT = 0x33F, + CMSG_MOVE_FLIGHT_ACK = 0x340, + MSG_MOVE_START_SWIM_CHEAT = 0x341, + MSG_MOVE_STOP_SWIM_CHEAT = 0x342, + SMSG_MOVE_SET_CAN_FLY = 0x343, + SMSG_MOVE_UNSET_CAN_FLY = 0x344, + CMSG_MOVE_SET_CAN_FLY_ACK = 0x345, + CMSG_MOVE_SET_FLY = 0x346, + CMSG_SOCKET_GEMS = 0x347, + CMSG_ARENA_TEAM_CREATE = 0x348, + SMSG_ARENA_TEAM_COMMAND_RESULT = 0x349, + UMSG_UPDATE_ARENA_TEAM_OBSOLETE = 0x34A, + CMSG_ARENA_TEAM_QUERY = 0x34B, + SMSG_ARENA_TEAM_QUERY_RESPONSE = 0x34C, + CMSG_ARENA_TEAM_ROSTER = 0x34D, + SMSG_ARENA_TEAM_ROSTER = 0x34E, + CMSG_ARENA_TEAM_INVITE = 0x34F, + SMSG_ARENA_TEAM_INVITE = 0x350, + CMSG_ARENA_TEAM_ACCEPT = 0x351, + CMSG_ARENA_TEAM_DECLINE = 0x352, + CMSG_ARENA_TEAM_LEAVE = 0x353, + CMSG_ARENA_TEAM_REMOVE = 0x354, + CMSG_ARENA_TEAM_DISBAND = 0x355, + CMSG_ARENA_TEAM_LEADER = 0x356, + SMSG_ARENA_TEAM_EVENT = 0x357, + CMSG_BATTLEMASTER_JOIN_ARENA = 0x358, + MSG_MOVE_START_ASCEND = 0x359, + MSG_MOVE_STOP_ASCEND = 0x35A, + SMSG_ARENA_TEAM_STATS = 0x35B, + CMSG_LFG_JOIN = 0x35C, // CMSG JoinLFG + CMSG_LFG_LEAVE = 0x35D, // CMSG LeaveLFG + CMSG_SEARCH_LFG_JOIN = 0x35E, // CMSG SearchLFGJoin + CMSG_SEARCH_LFG_LEAVE = 0x35F, // CMSG SearchLFGLeave + SMSG_UPDATE_LFG_LIST = 0x360, // SMSG uint32, uint32, if (uint8) { uint32 count, for (count) { uint64} }, uint32 count2, uint32, for (count2) { uint64, uint32 flags, if (flags & 0x2) {string}, if (flags & 0x10) {for (3) uint8}, if (flags & 0x80) {uint64, uint32}}, uint32 count3, uint32, for (count3) {uint64, uint32 flags, if (flags & 0x1) {uint8, uint8, uint8, for (3) uint8, uint32, uint32, uint32, uint32, uint32, uint32, float, float, uint32, uint32, uint32, uint32, uint32, float, uint32, uint32, uint32, uint32, uint32, uint32}, if (flags&0x2) string, if (flags&0x4) uint8, if (flags&0x8) uint64, if (flags&0x10) uint8, if (flags&0x20) uint32, if (flags&0x40) uint8, if (flags& 0x80) {uint64, uint32}} + SMSG_LFG_PROPOSAL_UPDATE = 0x361, // SMSG uint32, uint8, uint32, uint32, uint8, for (uint8) {uint32,uint8,uint8,uint8,uint8} + CMSG_LFG_PROPOSAL_RESULT = 0x362, // CMSG AcceptProposal, RejectProposal + SMSG_LFG_ROLE_CHECK_UPDATE = 0x363, // SMSG uint32, uint8, for (uint8) uint32, uint8, for (uint8) { uint64, uint8, uint32, uint8, } + SMSG_LFG_JOIN_RESULT = 0x364, // SMSG uint32 unk, uint32, if (unk == 6) { uint8 count, for (count) uint64 } + SMSG_LFG_QUEUE_STATUS = 0x365, // SMSG uint32 dungeon, uint32 lfgtype, uint32, uint32, uint32, uint32, uint8, uint8, uint8, uint8 + CMSG_SET_LFG_COMMENT = 0x366, // CMSG SetLFGComment + SMSG_LFG_UPDATE_PLAYER = 0x367, // SMSG uint8, if (uint8) { uint8, uint8, uint8, uint8, if (uint8) for (uint8) uint32, string} + SMSG_LFG_UPDATE_PARTY = 0x368, // SMSG uint8, if (uint8) { uint8, uint8, uint8, for (3) uint8, uint8, if (uint8) for (uint8) uint32, string} + SMSG_LFG_UPDATE_SEARCH = 0x369, // SMSG uint8 + CMSG_LFG_SET_ROLES = 0x36A, // CMSG SetLFGRoles + CMSG_LFG_SET_NEEDS = 0x36B, // CMSG SetLFGNeeds + CMSG_LFG_SET_BOOT_VOTE = 0x36C, // CMSG SetLFGBootVote + SMSG_LFG_BOOT_PLAYER = 0x36D, // SMSG uint8, uint8, uint8, uint64, uint32, uint32, uint32, uint32 + CMSG_LFD_PLAYER_LOCK_INFO_REQUEST = 0x36E, // CMSG RequestLFDPlayerLockInfo + SMSG_LFG_PLAYER_INFO = 0x36F, // SMSG uint8, for (uint8) { uint32, uint8, uint32, uint32, uint32, uint32, uint8, for (uint8) {uint32,uint32, uint32}}, uint32, for (uint32) {uint32,uint32} + CMSG_LFG_TELEPORT = 0x370, // CMSG LFGTeleport + CMSG_LFD_PARTY_LOCK_INFO_REQUEST = 0x371, // CMSG RequestLFDPartyLockInfo + SMSG_LFG_PARTY_INFO = 0x372, // SMSG uint8, for (uint8) uint64 + SMSG_TITLE_EARNED = 0x373, + CMSG_SET_TITLE = 0x374, + CMSG_CANCEL_MOUNT_AURA = 0x375, + SMSG_ARENA_ERROR = 0x376, + MSG_INSPECT_ARENA_TEAMS = 0x377, + SMSG_DEATH_RELEASE_LOC = 0x378, + CMSG_CANCEL_TEMP_ENCHANTMENT = 0x379, + SMSG_FORCED_DEATH_UPDATE = 0x37A, + CMSG_CHEAT_SET_HONOR_CURRENCY = 0x37B, + CMSG_CHEAT_SET_ARENA_CURRENCY = 0x37C, + MSG_MOVE_SET_FLIGHT_SPEED_CHEAT = 0x37D, + MSG_MOVE_SET_FLIGHT_SPEED = 0x37E, + MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT = 0x37F, + MSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x380, + SMSG_FORCE_FLIGHT_SPEED_CHANGE = 0x381, + CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK = 0x382, + SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE = 0x383, + CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK = 0x384, + SMSG_SPLINE_SET_FLIGHT_SPEED = 0x385, + SMSG_SPLINE_SET_FLIGHT_BACK_SPEED = 0x386, + CMSG_MAELSTROM_INVALIDATE_CACHE = 0x387, + SMSG_FLIGHT_SPLINE_SYNC = 0x388, + CMSG_SET_TAXI_BENCHMARK_MODE = 0x389, + SMSG_JOINED_BATTLEGROUND_QUEUE = 0x38A, + SMSG_REALM_SPLIT = 0x38B, + CMSG_REALM_SPLIT = 0x38C, + CMSG_MOVE_CHNG_TRANSPORT = 0x38D, + MSG_PARTY_ASSIGNMENT = 0x38E, + SMSG_OFFER_PETITION_ERROR = 0x38F, + SMSG_TIME_SYNC_REQ = 0x390, + CMSG_TIME_SYNC_RESP = 0x391, + CMSG_SEND_LOCAL_EVENT = 0x392, + CMSG_SEND_GENERAL_TRIGGER = 0x393, + CMSG_SEND_COMBAT_TRIGGER = 0x394, + CMSG_MAELSTROM_GM_SENT_MAIL = 0x395, + SMSG_RESET_FAILED_NOTIFY = 0x396, + SMSG_REAL_GROUP_UPDATE = 0x397, + SMSG_LFG_DISABLED = 0x398, + CMSG_ACTIVE_PVP_CHEAT = 0x399, + CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY = 0x39A, + SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE = 0x39B, + SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE = 0x39C, + SMSG_UPDATE_COMBO_POINTS = 0x39D, + SMSG_VOICE_SESSION_ROSTER_UPDATE = 0x39E, + SMSG_VOICE_SESSION_LEAVE = 0x39F, + SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0, + CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1, + SMSG_VOICE_SET_TALKER_MUTED = 0x3A2, + SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE = 0x3A3, + SMSG_SET_EXTRA_AURA_INFO_OBSOLETE = 0x3A4, + SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE = 0x3A5, + SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE = 0x3A6, + MSG_MOVE_START_DESCEND = 0x3A7, + CMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A8, + SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A9, + SMSG_SPELL_CHANCE_PROC_LOG = 0x3AA, + CMSG_MOVE_SET_RUN_SPEED = 0x3AB, + SMSG_DISMOUNT = 0x3AC, + MSG_MOVE_UPDATE_CAN_FLY = 0x3AD, + MSG_RAID_READY_CHECK_CONFIRM = 0x3AE, + CMSG_VOICE_SESSION_ENABLE = 0x3AF, + SMSG_VOICE_SESSION_ENABLE = 0x3B0, + SMSG_VOICE_PARENTAL_CONTROLS = 0x3B1, + CMSG_GM_WHISPER = 0x3B2, + SMSG_GM_MESSAGECHAT = 0x3B3, + MSG_GM_GEARRATING = 0x3B4, + CMSG_COMMENTATOR_ENABLE = 0x3B5, + SMSG_COMMENTATOR_STATE_CHANGED = 0x3B6, + CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B7, + SMSG_COMMENTATOR_MAP_INFO = 0x3B8, + CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9, + SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3BA, + SMSG_COMMENTATOR_PLAYER_INFO = 0x3BB, + CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BC, + CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BD, + CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BE, + SMSG_CLEAR_TARGET = 0x3BF, + CMSG_BOT_DETECTED = 0x3C0, + SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C1, + CMSG_CHEAT_PLAYER_LOGIN = 0x3C2, + CMSG_CHEAT_PLAYER_LOOKUP = 0x3C3, + SMSG_CHEAT_PLAYER_LOOKUP = 0x3C4, + SMSG_KICK_REASON = 0x3C5, + MSG_RAID_READY_CHECK_FINISHED = 0x3C6, + CMSG_COMPLAIN = 0x3C7, + SMSG_COMPLAIN_RESULT = 0x3C8, + SMSG_FEATURE_SYSTEM_STATUS = 0x3C9, + CMSG_GM_SHOW_COMPLAINTS = 0x3CA, + CMSG_GM_UNSQUELCH = 0x3CB, + CMSG_CHANNEL_SILENCE_VOICE = 0x3CC, + CMSG_CHANNEL_SILENCE_ALL = 0x3CD, + CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CE, + CMSG_CHANNEL_UNSILENCE_ALL = 0x3CF, + CMSG_TARGET_CAST = 0x3D0, + CMSG_TARGET_SCRIPT_CAST = 0x3D1, + CMSG_CHANNEL_DISPLAY_LIST = 0x3D2, + CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D3, + CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D4, + SMSG_CHANNEL_MEMBER_COUNT = 0x3D5, + CMSG_CHANNEL_VOICE_ON = 0x3D6, + CMSG_CHANNEL_VOICE_OFF = 0x3D7, + CMSG_DEBUG_LIST_TARGETS = 0x3D8, + SMSG_DEBUG_LIST_TARGETS = 0x3D9, + SMSG_AVAILABLE_VOICE_CHANNEL = 0x3DA, + CMSG_ADD_VOICE_IGNORE = 0x3DB, + CMSG_DEL_VOICE_IGNORE = 0x3DC, + CMSG_PARTY_SILENCE = 0x3DD, + CMSG_PARTY_UNSILENCE = 0x3DE, + MSG_NOTIFY_PARTY_SQUELCH = 0x3DF, + SMSG_COMSAT_RECONNECT_TRY = 0x3E0, + SMSG_COMSAT_DISCONNECT = 0x3E1, + SMSG_COMSAT_CONNECT_FAIL = 0x3E2, + SMSG_VOICE_CHAT_STATUS = 0x3E3, + CMSG_REPORT_PVP_AFK = 0x3E4, + SMSG_REPORT_PVP_AFK_RESULT = 0x3E5, // SMSG? + CMSG_GUILD_BANKER_ACTIVATE = 0x3E6, + CMSG_GUILD_BANK_QUERY_TAB = 0x3E7, + SMSG_GUILD_BANK_LIST = 0x3E8, + CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E9, + CMSG_GUILD_BANK_BUY_TAB = 0x3EA, + CMSG_GUILD_BANK_UPDATE_TAB = 0x3EB, + CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EC, + CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3ED, + MSG_GUILD_BANK_LOG_QUERY = 0x3EE, + CMSG_SET_CHANNEL_WATCH = 0x3EF, + SMSG_USERLIST_ADD = 0x3F0, + SMSG_USERLIST_REMOVE = 0x3F1, + SMSG_USERLIST_UPDATE = 0x3F2, + CMSG_CLEAR_CHANNEL_WATCH = 0x3F3, + SMSG_INSPECT_TALENT = 0x3F4, + SMSG_GOGOGO_OBSOLETE = 0x3F5, + SMSG_ECHO_PARTY_SQUELCH = 0x3F6, + CMSG_SET_TITLE_SUFFIX = 0x3F7, + CMSG_SPELLCLICK = 0x3F8, + SMSG_LOOT_LIST = 0x3F9, + CMSG_GM_CHARACTER_RESTORE = 0x3FA, + CMSG_GM_CHARACTER_SAVE = 0x3FB, + SMSG_VOICESESSION_FULL = 0x3FC, + MSG_GUILD_PERMISSIONS = 0x3FD, + MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FE, + MSG_GUILD_EVENT_LOG_QUERY = 0x3FF, + CMSG_MAELSTROM_RENAME_GUILD = 0x400, + CMSG_GET_MIRRORIMAGE_DATA = 0x401, + SMSG_MIRRORIMAGE_DATA = 0x402, + SMSG_FORCE_DISPLAY_UPDATE = 0x403, + SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x404, + CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405, + SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x406, + CMSG_KEEP_ALIVE = 0x407, + SMSG_RAID_READY_CHECK_ERROR = 0x408, + CMSG_OPT_OUT_OF_LOOT = 0x409, + MSG_QUERY_GUILD_BANK_TEXT = 0x40A, + CMSG_SET_GUILD_BANK_TEXT = 0x40B, + CMSG_SET_GRANTABLE_LEVELS = 0x40C, + CMSG_GRANT_LEVEL = 0x40D, + CMSG_REFER_A_FRIEND = 0x40E, + MSG_GM_CHANGE_ARENA_RATING = 0x40F, + CMSG_DECLINE_CHANNEL_INVITE = 0x410, + SMSG_GROUPACTION_THROTTLED = 0x411, // SMSG? + SMSG_OVERRIDE_LIGHT = 0x412, + SMSG_TOTEM_CREATED = 0x413, + CMSG_TOTEM_DESTROYED = 0x414, + CMSG_EXPIRE_RAID_INSTANCE = 0x415, + CMSG_NO_SPELL_VARIANCE = 0x416, + CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x417, + SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x418, + CMSG_SET_PLAYER_DECLINED_NAMES = 0x419, + SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x41A, + CMSG_QUERY_SERVER_BUCK_DATA = 0x41B, + CMSG_CLEAR_SERVER_BUCK_DATA = 0x41C, + SMSG_SERVER_BUCK_DATA = 0x41D, + SMSG_SEND_UNLEARN_SPELLS = 0x41E, + SMSG_PROPOSE_LEVEL_GRANT = 0x41F, + CMSG_ACCEPT_LEVEL_GRANT = 0x420, + SMSG_REFER_A_FRIEND_FAILURE = 0x421, + SMSG_SPLINE_MOVE_SET_FLYING = 0x422, + SMSG_SPLINE_MOVE_UNSET_FLYING = 0x423, + SMSG_SUMMON_CANCEL = 0x424, + CMSG_CHANGE_PERSONAL_ARENA_RATING = 0x425, + CMSG_ALTER_APPEARANCE = 0x426, + SMSG_ENABLE_BARBER_SHOP = 0x427, + SMSG_BARBER_SHOP_RESULT = 0x428, + CMSG_CALENDAR_GET_CALENDAR = 0x429, + CMSG_CALENDAR_GET_EVENT = 0x42A, + CMSG_CALENDAR_GUILD_FILTER = 0x42B, + CMSG_CALENDAR_ARENA_TEAM = 0x42C, + CMSG_CALENDAR_ADD_EVENT = 0x42D, + CMSG_CALENDAR_UPDATE_EVENT = 0x42E, + CMSG_CALENDAR_REMOVE_EVENT = 0x42F, + CMSG_CALENDAR_COPY_EVENT = 0x430, + CMSG_CALENDAR_EVENT_INVITE = 0x431, + CMSG_CALENDAR_EVENT_RSVP = 0x432, + CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x433, + CMSG_CALENDAR_EVENT_STATUS = 0x434, + CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x435, + SMSG_CALENDAR_SEND_CALENDAR = 0x436, + SMSG_CALENDAR_SEND_EVENT = 0x437, + SMSG_CALENDAR_FILTER_GUILD = 0x438, + SMSG_CALENDAR_ARENA_TEAM = 0x439, + SMSG_CALENDAR_EVENT_INVITE = 0x43A, + SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x43B, + SMSG_CALENDAR_EVENT_STATUS = 0x43C, + SMSG_CALENDAR_COMMAND_RESULT = 0x43D, + SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x43E, + SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x43F, + SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x440, + SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x441, + SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x442, + SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x443, + SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444, + SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445, + CMSG_CALENDAR_COMPLAIN = 0x446, + CMSG_CALENDAR_GET_NUM_PENDING = 0x447, + SMSG_CALENDAR_SEND_NUM_PENDING = 0x448, + CMSG_SAVE_DANCE = 0x449, + SMSG_NOTIFY_DANCE = 0x44A, + CMSG_PLAY_DANCE = 0x44B, + SMSG_PLAY_DANCE = 0x44C, + CMSG_LOAD_DANCES = 0x44D, + CMSG_STOP_DANCE = 0x44E, + SMSG_STOP_DANCE = 0x44F, + CMSG_SYNC_DANCE = 0x450, + CMSG_DANCE_QUERY = 0x451, + SMSG_DANCE_QUERY_RESPONSE = 0x452, + SMSG_INVALIDATE_DANCE = 0x453, + CMSG_DELETE_DANCE = 0x454, + SMSG_LEARNED_DANCE_MOVES = 0x455, + CMSG_LEARN_DANCE_MOVE = 0x456, + CMSG_UNLEARN_DANCE_MOVE = 0x457, + CMSG_SET_RUNE_COUNT = 0x458, + CMSG_SET_RUNE_COOLDOWN = 0x459, + MSG_MOVE_SET_PITCH_RATE_CHEAT = 0x45A, + MSG_MOVE_SET_PITCH_RATE = 0x45B, + SMSG_FORCE_PITCH_RATE_CHANGE = 0x45C, + CMSG_FORCE_PITCH_RATE_CHANGE_ACK = 0x45D, + SMSG_SPLINE_SET_PITCH_RATE = 0x45E, + SMSG_MOVE_ABANDON_TRANSPORT = 0x45F, + SMSG_CALENDAR_UPDATE_INVITE_LIST = 0x460, + SMSG_CALENDAR_UPDATE_INVITE_LIST2 = 0x461, + CMSG_UPDATE_MISSILE_TRAJECTORY = 0x462, + SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x463, + SMSG_TRIGGER_MOVIE = 0x464, + CMSG_COMPLETE_MOVIE = 0x465, + CMSG_SET_GLYPH_SLOT = 0x466, + CMSG_SET_GLYPH = 0x467, + SMSG_ACHIEVEMENT_EARNED = 0x468, + SMSG_DYNAMIC_DROP_ROLL_RESULT = 0x469, + SMSG_CRITERIA_UPDATE = 0x46A, + CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x46B, + SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x46C, + CMSG_DISMISS_CONTROLLED_VEHICLE = 0x46D, + CMSG_COMPLETE_ACHIEVEMENT_CHEAT = 0x46E, + SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x46F, + CMSG_SET_CRITERIA_CHEAT = 0x470, + SMSG_CALENDAR_UPDATE_INVITE_LIST3 = 0x471, + CMSG_UNITANIMTIER_CHEAT = 0x472, + CMSG_CHAR_CUSTOMIZE = 0x473, + SMSG_CHAR_CUSTOMIZE = 0x474, + SMSG_PET_RENAMEABLE = 0x475, + CMSG_REQUEST_VEHICLE_EXIT = 0x476, + CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x477, + CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x478, + CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x479, + CMSG_PET_LEARN_TALENT = 0x47A, + CMSG_PET_UNLEARN_TALENTS = 0x47B, + SMSG_SET_PHASE_SHIFT = 0x47C, + SMSG_ALL_ACHIEVEMENT_DATA = 0x47D, + CMSG_FORCE_SAY_CHEAT = 0x47E, + SMSG_HEALTH_UPDATE = 0x47F, + SMSG_POWER_UPDATE = 0x480, + CMSG_GAMEOBJ_REPORT_USE = 0x481, + SMSG_HIGHEST_THREAT_UPDATE = 0x482, + SMSG_THREAT_UPDATE = 0x483, + SMSG_THREAT_REMOVE = 0x484, + SMSG_THREAT_CLEAR = 0x485, + SMSG_CONVERT_RUNE = 0x486, + SMSG_RESYNC_RUNES = 0x487, + SMSG_ADD_RUNE_POWER = 0x488, + CMSG_START_QUEST = 0x489, + CMSG_REMOVE_GLYPH = 0x48A, + CMSG_DUMP_OBJECTS = 0x48B, + SMSG_DUMP_OBJECTS_DATA = 0x48C, + CMSG_DISMISS_CRITTER = 0x48D, + SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x48E, + CMSG_AUCTION_LIST_PENDING_SALES = 0x48F, + SMSG_AUCTION_LIST_PENDING_SALES = 0x490, + SMSG_MODIFY_COOLDOWN = 0x491, + SMSG_PET_UPDATE_COMBO_POINTS = 0x492, + CMSG_ENABLETAXI = 0x493, + SMSG_PRE_RESURRECT = 0x494, + SMSG_AURA_UPDATE_ALL = 0x495, + SMSG_AURA_UPDATE = 0x496, + CMSG_FLOOD_GRACE_CHEAT = 0x497, + SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498, + SMSG_PET_LEARNED_SPELL = 0x499, + SMSG_PET_REMOVED_SPELL = 0x49A, + CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x49B, + CMSG_HEARTH_AND_RESURRECT = 0x49C, // not changed in 3.1 + SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x49D, // not changed 9626 + SMSG_CRITERIA_DELETED = 0x49E, // not changed 9626 + SMSG_ACHIEVEMENT_DELETED = 0x49F, // not changed 9626 + CMSG_SERVER_INFO_QUERY = 0x4A0, // not found + SMSG_SERVER_INFO_RESPONSE = 0x4A1, // not found + CMSG_CHECK_LOGIN_CRITERIA = 0x4A2, // not found + SMSG_SERVER_BUCK_DATA_START = 0x4A3, // not found + CMSG_QUERY_VEHICLE_STATUS = 0x4A4, // not found + UMSG_UNKNOWN_1189 = 0x4A5, // not found, old SMSG_PET_GUIDS + SMSG_BATTLEGROUND_INFO_THROTTLED = 0x4A6, // empty, "You can't do that yet" + SMSG_PLAYER_VEHICLE_DATA = 0x4A7, // smsg guid+uint32 (vehicle) + CMSG_PLAYER_VEHICLE_ENTER = 0x4A8, // cmsg uint64 + CMSG_EJECT_PASSENGER = 0x4A9, // cmsg uint64 + SMSG_PET_GUIDS = 0x4AA, // shifted+5 + SMSG_CLIENTCACHE_VERSION = 0x4AB, // shifted+5 + UMSG_UNKNOWN_1196 = 0x4AC, // not found + UMSG_UNKNOWN_1197 = 0x4AD, // not found + UMSG_UNKNOWN_1198 = 0x4AE, // not found + UMSG_UNKNOWN_1199 = 0x4AF, // not found + UMSG_UNKNOWN_1200 = 0x4B0, // not found + UMSG_UNKNOWN_1201 = 0x4B1, // not found + SMSG_ITEM_REFUND_INFO_RESPONSE = 0x4B2, // refund item info + CMSG_ITEM_REFUND_INFO = 0x4B3, // refund request? + CMSG_ITEM_REFUND = 0x4B4, // lua: ContainerRefundItemPurchase + SMSG_ITEM_REFUND_RESULT = 0x4B5, // refund item result + CMSG_CORPSE_MAP_POSITION_QUERY = 0x4B6, // CMSG, uint32 + SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x4B7, // SMSG, 3*float+float + UMSG_UNKNOWN_1208 = 0x4B8, // not found + UMSG_UNKNOWN_1209 = 0x4B9, // not found + CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP = 0x4BA, // CMSG, uint64, lua: CalendarContextEventSignUp + SMSG_CALENDAR_ACTION_PENDING = 0x4BB, // SMSG, calendar related EVENT_CALENDAR_ACTION_PENDING + SMSG_EQUIPMENT_SET_LIST = 0x4BC, // SMSG, equipment manager list? + CMSG_EQUIPMENT_SET_SAVE = 0x4BD, // CMSG, lua: SaveEquipmentSet + CMSG_UPDATE_PROJECTILE_POSITION = 0x4BE, // CMSG, uint64 caster, uint32 spellId, uint8 castId, vector3 position + SMSG_SET_PROJECTILE_POSITION = 0x4BF, // SMSG, uint64 caster, uint8 castId, vector3 position + SMSG_TALENTS_INFO = 0x4C0, // SMSG, talents related + CMSG_LEARN_PREVIEW_TALENTS = 0x4C1, // CMSG, lua: LearnPreviewTalents (for player?) + CMSG_LEARN_PREVIEW_TALENTS_PET = 0x4C2, // CMSG, lua: LearnPreviewTalents (for pet?) + UMSG_UNKNOWN_1219 = 0x4C3, // not found 3.2 + UMSG_UNKNOWN_1220 = 0x4C4, // not found 3.2 + UMSG_UNKNOWN_1221 = 0x4C5, // not found 3.2 + UMSG_UNKNOWN_1222 = 0x4C6, // not found 3.2 + SMSG_ARENA_OPPONENT_UPDATE = 0x4C7, // uint64, EVENT_ARENA_OPPONENT_UPDATE + SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED = 0x4C8, // uint32 "Can't modify arena team while queued or in a match." 3.2 + UMSG_UNKNOWN_1225 = 0x4C9, // not found 3.2 + UMSG_UNKNOWN_1226 = 0x4CA, // not found 3.2 + UMSG_UNKNOWN_1227 = 0x4CB, // not found 3.2 + UMSG_UNKNOWN_1228 = 0x4CC, // not found 3.2 + SMSG_MULTIPLE_PACKETS = 0x4CD, // SMSG, handles any opcode + SMSG_FORCE_UNK1_SPEED_CHANGE = 0x4CE, // SMSG, movement related + CMSG_FORCE_UNK1_SPEED_CHANGE_ACK = 0x4CF, // movement related + SMSG_FORCE_UNK2_SPEED_CHANGE = 0x4D0, // SMSG, movement related + CMSG_FORCE_UNK2_SPEED_CHANGE_ACK = 0x4D1, // movement related + MSG_MOVE_UNKNOWN_1234 = 0x4D2, // SMSG, movement related + SMSG_SPLINE_MOVE_UNKNOWN_1235 = 0x4D3, // SMSG, movement related + SMSG_SPLINE_MOVE_UNKNOWN_1236 = 0x4D4, // SMSG, movement related + CMSG_EQUIPMENT_SET_USE = 0x4D5, // CMSG, lua: UseEquipmentSet + SMSG_EQUIPMENT_SET_USE_RESULT = 0x4D6, // SMSG, UseEquipmentSetResult? + UMSG_UNKNOWN_1239 = 0x4D7, // not found 3.2 + SMSG_UNKNOWN_1240 = 0x4D8, // SMSG, uint64, string, doing nothing + CMSG_CHAR_FACTION_CHANGE = 0x4D9, // lua: CreateCharacter (PFC client response) + SMSG_CHAR_FACTION_CHANGE = 0x4DA, // response to 1241 (PFC server response) + UMSG_UNKNOWN_1243 = 0x4DB, // not found 3.2 + UMSG_UNKNOWN_1244 = 0x4DC, // not found 3.2 + UMSG_UNKNOWN_1245 = 0x4DD, // not found 3.2 + SMSG_BATTLEFIELD_MGR_ENTRY_INVITE = 0x4DE, // uint32, EVENT_BATTLEFIELD_MGR_ENTRY_INVITE + CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE = 0x4DF, // lua: BattlefieldMgrEntryInviteResponse + SMSG_BATTLEFIELD_MGR_ENTERED = 0x4E0, // uint32, uint8, uint8 EVENT_BATTLEFIELD_MGR_ENTERED + SMSG_BATTLEFIELD_MGR_QUEUE_INVITE = 0x4E1, // uint32 EVENT_BATTLEFIELD_MGR_QUEUE_INVITE + CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE = 0x4E2, // lua: BattlefieldMgrQueueInviteResponse + CMSG_BATTLEFIELD_MGR_QUEUE_REQUEST = 0x4E3, // lua: BattlefieldMgrQueueRequest + SMSG_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE = 0x4E4, // uint32, uint8 EVENT_BATTLEFIELD_MGR_QUEUE_REQUEST_RESPONSE + SMSG_BATTLEFIELD_MGR_EJECT_PENDING = 0x4E5, // uint32 EVENT_BATTLEFIELD_MGR_EJECT_PENDING + SMSG_BATTLEFIELD_MGR_EJECTED = 0x4E6, // uint32, uint32, uint8 EVENT_BATTLEFIELD_MGR_EJECTED + CMSG_BATTLEFIELD_MGR_EXIT_REQUEST = 0x4E7, // lua: BattlefieldMgrExitRequest + SMSG_BATTLEFIELD_MGR_STATE_CHANGE = 0x4E8, // uint32, uint32 EVENT_BATTLEFIELD_MGR_STATE_CHANGE + UMSG_UNKNOWN_1257 = 0x4E9, // not found 3.2 + UMSG_UNKNOWN_1258 = 0x4EA, // not found 3.2 + MSG_SET_RAID_DIFFICULTY = 0x4EB, // lua: SetRaidDifficulty + UMSG_UNKNOWN_1260 = 0x4EC, // not found 3.2 + SMSG_TOGGLE_XP_GAIN = 0x4ED, // enable/disable XP gain console message + SMSG_GMRESPONSE_DB_ERROR = 0x4EE, // empty + SMSG_GMRESPONSE_RECEIVED = 0x4EF, // uint32, uint32, string[2000], string[4000][4] + CMSG_GMRESPONSE_RESOLVE = 0x4F0, // lua: GMResponseResolve + SMSG_GMRESPONSE_STATUS_UPDATE = 0x4F1, // uint8 (1 - EVENT_GMSURVEY_DISPLAY, 0 - EVENT_UPDATE_TICKET) + UMSG_UNKNOWN_1266 = 0x4F2, // not found 3.2 + UMSG_UNKNOWN_1267 = 0x4F3, // not found 3.2 + UMSG_UNKNOWN_1268 = 0x4F4, // not found 3.2 + UMSG_UNKNOWN_1269 = 0x4F5, // not found 3.2 + CMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F6, + SMSG_WORLD_STATE_UI_TIMER_UPDATE = 0x4F7, + CMSG_CHAR_RACE_CHANGE = 0x4F8, // called from lua: CreateCharacter, paid race change + UMSG_UNKNOWN_1273 = 0x4F9, // not found 10554 + SMSG_TALENTS_INVOLUNTARILY_RESET = 0x4FA, // uint8 EVENT_TALENTS_INVOLUNTARILY_RESET + UMSG_UNKNOWN_1275 = 0x4FB, // not found 10554 + SMSG_UNKNOWN_1276 = 0x4FC, // does nothing in 10554 + SMSG_LOOT_SLOT_CHANGED = 0x4FD, // EVENT_LOOT_SLOT_CHANGED + UMSG_UNKNOWN_1278 = 0x4FE, // not found 10596 + CMSG_READY_FOR_ACCOUNT_DATA_TIMES = 0x4FF, // lua: ReadyForAccountDataTimes + CMSG_QUERY_QUESTS_COMPLETED = 0x500, // lua: QueryQuestsCompleted + SMSG_QUERY_QUESTS_COMPLETED_RESPONSE = 0x501, // response to 0x500 + CMSG_GM_REPORT_LAG = 0x502, // lua: GMReportLag + UMSG_UNKNOWN_1283 = 0x503, + UMSG_UNKNOWN_1284 = 0x504, + UMSG_UNKNOWN_1285 = 0x505, + SMSG_CORPSE_NOT_IN_INSTANCE = 0x506, + UMSG_UNKNOWN_1287 = 0x507, // not found + CMSG_SET_ALLOW_LOW_LEVEL_RAID1 = 0x508, // lua: SetAllowLowLevelRaid + CMSG_SET_ALLOW_LOW_LEVEL_RAID2 = 0x509, // lua: SetAllowLowLevelRaid + SMSG_CAMERA_SHAKE = 0x50A, // uint32 SpellEffectCameraShakes.dbc index, uint32 + SMSG_UPDATE_ITEM_ENCHANTMENTS = 0x50B, // some item update packet? + UMSG_UNKNOWN_1292 = 0x50C, // not found + SMSG_REDIRECT_CLIENT = 0x50D, // uint32 ip, uint16 port, uint32 unk, uint8[20] hash (ip + port, seed=sessionkey) + CMSG_REDIRECTION_FAILED = 0x50E, // something with networking + SMSG_UNKNOWN_1295 = 0x50F, // not found - disconnect + CMSG_UNKNOWN_1296 = 0x510, // something with networking + SMSG_FORCE_SEND_QUEUED_PACKETS = 0x511, // not found - crash + CMSG_REDIRECTION_AUTH_PROOF = 0x512, // something with networking + UMSG_UNKNOWN_1299 = 0x513, // not found + SMSG_UNKNOWN_1300 = 0x514, // SMSG + SMSG_UNKNOWN_1301 = 0x515, // event 0x204 (opens dungeon finder, probably for outdoor bosses) + SMSG_UNKNOWN_1302 = 0x516, // something with player movement (move event 58?) + CMSG_UNKNOWN_1303 = 0x517, // something with player movement (move event 58?) + SMSG_UNKNOWN_1304 = 0x518, // something with player movement (move event 58?), speed packet + UMSG_UNKNOWN_1305 = 0x519, // not found + UMSG_UNKNOWN_1306 = 0x51A, // not found + NUM_MSG_TYPES = 0x51B +}; + +/// Player state +enum SessionStatus +{ + STATUS_AUTHED = 0, ///< Player authenticated (_player == NULL, m_playerRecentlyLogout = false or will be reset before handler call, m_GUID have garbage) + STATUS_LOGGEDIN, ///< Player in game (_player != NULL, m_GUID == _player->GetGUID(), inWorld()) + STATUS_TRANSFER, ///< Player transferring to another map (_player != NULL, m_GUID == _player->GetGUID(), !inWorld()) + STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, ///< _player!= NULL or _player == NULL && m_playerRecentlyLogout, m_GUID store last _player guid) + STATUS_NEVER ///< Opcode not accepted from client (deprecated or server side only) +}; + +class WorldPacket; + +struct OpcodeHandler +{ + char const* name; + SessionStatus status; + void (WorldSession::*handler)(WorldPacket& recvPacket); +}; + +extern OpcodeHandler opcodeTable[NUM_MSG_TYPES]; + +/// Lookup opcode name for human understandable logging +inline const char* LookupOpcodeName(uint16 id) +{ + if (id >= NUM_MSG_TYPES) + return "Received unknown opcode, it's more than max!"; + return opcodeTable[id].name; +} +#endif +/// @} diff --git a/src/server/game/Server/Protocol/WorldLog.cpp b/src/server/game/Server/Protocol/WorldLog.cpp new file mode 100644 index 00000000000..7c6c4020336 --- /dev/null +++ b/src/server/game/Server/Protocol/WorldLog.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup u2w +*/ + +#include "WorldLog.h" +#include "Policies/SingletonImp.h" +#include "Config/ConfigEnv.h" +#include "Log.h" + +#define CLASS_LOCK Trinity::ClassLevelLockable +INSTANTIATE_SINGLETON_2(WorldLog, CLASS_LOCK); +INSTANTIATE_CLASS_MUTEX(WorldLog, ACE_Thread_Mutex); + +WorldLog::WorldLog() : i_file(NULL) +{ + Initialize(); +} + +WorldLog::~WorldLog() +{ + if (i_file != NULL) + fclose(i_file); + i_file = NULL; +} + +/// Open the log file (if specified so in the configuration file) +void WorldLog::Initialize() +{ + std::string logsDir = sConfig.GetStringDefault("LogsDir",""); + + if (!logsDir.empty()) + { + if ((logsDir.at(logsDir.length()-1) != '/') && (logsDir.at(logsDir.length()-1) != '\\')) + logsDir.append("/"); + } + + std::string logname = sConfig.GetStringDefault("WorldLogFile", ""); + if (!logname.empty()) + { + i_file = fopen((logsDir+logname).c_str(), "w"); + } + + m_dbWorld = sConfig.GetBoolDefault("LogDB.World", false); // can be VERY heavy if enabled +} + +void WorldLog::outTimestampLog(char const *fmt, ...) +{ + if (LogWorld()) + { + Guard guard(*this); + ASSERT(i_file); + + Log::outTimestamp(i_file); + va_list args; + va_start(args, fmt); + vfprintf(i_file, fmt, args); + //fprintf(i_file, "\n"); + va_end(args); + + fflush(i_file); + } + + if (sLog.GetLogDB() && m_dbWorld) + { + va_list ap2; + va_start(ap2, fmt); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); + sLog.outDB(LOG_TYPE_WORLD, nnew_str); + va_end(ap2); + } +} + +void WorldLog::outLog(char const *fmt, ...) +{ + if (LogWorld()) + { + Guard guard(*this); + ASSERT(i_file); + + va_list args; + va_start(args, fmt); + vfprintf(i_file, fmt, args); + //fprintf(i_file, "\n"); + va_end(args); + + fflush(i_file); + } + + if (sLog.GetLogDB() && m_dbWorld) + { + va_list ap2; + va_start(ap2, fmt); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); + sLog.outDB(LOG_TYPE_WORLD, nnew_str); + va_end(ap2); + } +} + +#define sWorldLog WorldLog::Instance() + diff --git a/src/server/game/Server/Protocol/WorldLog.h b/src/server/game/Server/Protocol/WorldLog.h new file mode 100644 index 00000000000..4ee9bb178ec --- /dev/null +++ b/src/server/game/Server/Protocol/WorldLog.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup u2w +/// @{ +/// \file + +#ifndef TRINITY_WORLDLOG_H +#define TRINITY_WORLDLOG_H + +#include "Common.h" +#include "Policies/Singleton.h" +#include "Errors.h" + +#include + +/// %Log packets to a file +class WorldLog : public Trinity::Singleton > +{ + friend class Trinity::OperatorNew; + WorldLog(); + WorldLog(const WorldLog &); + WorldLog& operator=(const WorldLog &); + typedef Trinity::ClassLevelLockable::Lock Guard; + + /// Close the file in destructor + ~WorldLog(); + + public: + void Initialize(); + /// Is the world logger active? + bool LogWorld(void) const { return (i_file != NULL); } + /// %Log to the file + void outLog(char const *fmt, ...); + void outTimestampLog(char const *fmt, ...); + + private: + FILE *i_file; + + bool m_dbWorld; +}; + +#define sWorldLog WorldLog::Instance() +#endif +/// @} + diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp new file mode 100644 index 00000000000..bc737717840 --- /dev/null +++ b/src/server/game/Server/WorldSession.cpp @@ -0,0 +1,959 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup u2w +*/ + +#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "Opcodes.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Player.h" +#include "Vehicle.h" +#include "ObjectMgr.h" +#include "Group.h" +#include "Guild.h" +#include "World.h" +#include "ObjectAccessor.h" +#include "BattleGroundMgr.h" +#include "OutdoorPvPMgr.h" +#include "MapManager.h" +#include "SocialMgr.h" +#include "zlib/zlib.h" +#include "ScriptMgr.h" +#include "LFGMgr.h" + +/// WorldSession constructor +WorldSession::WorldSession(uint32 id, WorldSocket *sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale) : +LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time), +_player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_expansion(expansion), +m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)), +_logoutTime(0), m_inQueue(false), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_playerSave(false), +m_latency(0), m_TutorialsChanged(false), m_timeOutTime(0) +{ + if (sock) + { + m_Address = sock->GetRemoteAddress (); + sock->AddReference (); + ResetTimeOutTime(); + LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); + } +} + +/// WorldSession destructor +WorldSession::~WorldSession() +{ + ///- unload player if not unloaded + if (_player) + LogoutPlayer (true); + + /// - If have unclosed socket, close it + if (m_Socket) + { + m_Socket->CloseSocket (); + m_Socket->RemoveReference (); + m_Socket = NULL; + } + + ///- empty incoming packet queue + WorldPacket* packet; + while (_recvQueue.next(packet)) + delete packet; + + LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); + CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = %u;", GetAccountId()); +} + +void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const +{ + sLog.outError("Client (account %u) send packet %s (%u) with size " SIZEFMTD " but expected %u (attempt crash server?), skipped", + GetAccountId(),LookupOpcodeName(packet.GetOpcode()),packet.GetOpcode(),packet.size(),size); +} + +/// Get the player name +char const* WorldSession::GetPlayerName() const +{ + return GetPlayer() ? GetPlayer()->GetName() : ""; +} + +/// Send a packet to the client +void WorldSession::SendPacket(WorldPacket const* packet) +{ + if (!m_Socket) + return; + + #ifdef TRINITY_DEBUG + + // Code for network use statistic + static uint64 sendPacketCount = 0; + static uint64 sendPacketBytes = 0; + + static time_t firstTime = time(NULL); + static time_t lastTime = firstTime; // next 60 secs start time + + static uint64 sendLastPacketCount = 0; + static uint64 sendLastPacketBytes = 0; + + time_t cur_time = time(NULL); + + if ((cur_time - lastTime) < 60) + { + sendPacketCount+=1; + sendPacketBytes+=packet->size(); + + sendLastPacketCount+=1; + sendLastPacketBytes+=packet->size(); + } + else + { + uint64 minTime = uint64(cur_time - lastTime); + uint64 fullTime = uint64(lastTime - firstTime); + sLog.outDetail("Send all time packets count: " UI64FMTD " bytes: " UI64FMTD " avr.count/sec: %f avr.bytes/sec: %f time: %u",sendPacketCount,sendPacketBytes,float(sendPacketCount)/fullTime,float(sendPacketBytes)/fullTime,uint32(fullTime)); + sLog.outDetail("Send last min packets count: " UI64FMTD " bytes: " UI64FMTD " avr.count/sec: %f avr.bytes/sec: %f",sendLastPacketCount,sendLastPacketBytes,float(sendLastPacketCount)/minTime,float(sendLastPacketBytes)/minTime); + + lastTime = cur_time; + sendLastPacketCount = 1; + sendLastPacketBytes = packet->wpos(); // wpos is real written size + } + + #endif // !TRINITY_DEBUG + + if (m_Socket->SendPacket (*packet) == -1) + m_Socket->CloseSocket (); +} + +/// Add an incoming packet to the queue +void WorldSession::QueuePacket(WorldPacket* new_packet) +{ + _recvQueue.add(new_packet); +} + +/// Logging helper for unexpected opcodes +void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char *reason) +{ + sLog.outError("SESSION: received unexpected opcode %s (0x%.4X) %s", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode(), + reason); +} + +/// Logging helper for unexpected opcodes +void WorldSession::LogUnprocessedTail(WorldPacket *packet) +{ + sLog.outError("SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode(), + packet->rpos(),packet->wpos()); + + packet->print_storage(); +} + +/// Update the WorldSession (triggered by World update) +bool WorldSession::Update(uint32 diff) +{ + /// Update Timeout timer. + UpdateTimeOutTime(diff); + + ///- Before we process anything: + /// If necessary, kick the player from the character select screen + if (IsConnectionIdle()) + m_Socket->CloseSocket(); + + ///- Retrieve packets from the receive queue and call the appropriate handlers + /// not proccess packets if socket already closed + WorldPacket* packet; + while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet)) + { + /*#if 1 + sLog.outError("MOEP: %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + #endif*/ + + if (packet->GetOpcode() >= NUM_MSG_TYPES) + { + sLog.outError("SESSION: received non-existed opcode %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + } + else + { + OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; + try + { + switch (opHandle.status) + { + case STATUS_LOGGEDIN: + if (!_player) + { + // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets + if (!m_playerRecentlyLogout) + LogUnexpectedOpcode(packet, "the player has not logged in yet"); + } + else if (_player->IsInWorld()) + { + (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } + // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer + break; + case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT: + if (!_player && !m_playerRecentlyLogout) + { + LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout"); + } + else + { + // not expected _player or must checked in packet hanlder + (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } + break; + case STATUS_TRANSFER: + if (!_player) + LogUnexpectedOpcode(packet, "the player has not logged in yet"); + else if (_player->IsInWorld()) + LogUnexpectedOpcode(packet, "the player is still in world"); + else + { + (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } + break; + case STATUS_AUTHED: + // prevent cheating with skip queue wait + if (m_inQueue) + { + LogUnexpectedOpcode(packet, "the player not pass queue yet"); + break; + } + + // single from authed time opcodes send in to after logout time + // and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes. + if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) + m_playerRecentlyLogout = false; + + (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + break; + case STATUS_NEVER: + /* + sLog.outError("SESSION: received not allowed opcode %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + */ + break; + } + } + catch(ByteBufferException &) + { + sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", + packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); + if (sLog.IsOutDebug()) + { + sLog.outDebug("Dumping error causing packet:"); + packet->hexlike(); + } + } + } + + delete packet; + } + + time_t currTime = time(NULL); + ///- If necessary, log the player out + if (ShouldLogOut(currTime) && !m_playerLoading) + LogoutPlayer(true); + + ///- Cleanup socket pointer if need + if (m_Socket && m_Socket->IsClosed()) + { + m_Socket->RemoveReference(); + m_Socket = NULL; + } + + if (!m_Socket) + return false; //Will remove this session from the world session map + + return true; +} + +/// %Log the player out +void WorldSession::LogoutPlayer(bool Save) +{ + // finish pending transfers before starting the logout + while (_player && _player->IsBeingTeleportedFar()) + HandleMoveWorldportAckOpcode(); + + m_playerLogout = true; + m_playerSave = Save; + + if (_player) + { + sLFGMgr.Leave(_player); + GetPlayer()->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); + GetPlayer()->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); + GetPlayer()->GetSession()->SendLfgUpdateSearch(false); + + if (uint64 lguid = GetPlayer()->GetLootGUID()) + DoLootRelease(lguid); + + ///- If the player just died before logging out, make him appear as a ghost + //FIXME: logout must be delayed in case lost connection with client in time of combat + if (_player->GetDeathTimer()) + { + _player->getHostileRefManager().deleteReferences(); + _player->BuildPlayerRepop(); + _player->RepopAtGraveyard(); + } + else if (!_player->getAttackers().empty()) + { + _player->CombatStop(); + _player->getHostileRefManager().setOnlineOfflineState(false); + _player->RemoveAllAurasOnDeath(); + + // build set of player who attack _player or who have pet attacking of _player + std::set aset; + for (Unit::AttackerSet::const_iterator itr = _player->getAttackers().begin(); itr != _player->getAttackers().end(); ++itr) + { + Unit* owner = (*itr)->GetOwner(); // including player controlled case + if (owner) + { + if (owner->GetTypeId() == TYPEID_PLAYER) + aset.insert(owner->ToPlayer()); + } + else + if ((*itr)->GetTypeId() == TYPEID_PLAYER) + aset.insert((Player*)(*itr)); + } + + _player->SetPvPDeath(!aset.empty()); + _player->KillPlayer(); + _player->BuildPlayerRepop(); + _player->RepopAtGraveyard(); + + // give honor to all attackers from set like group case + for (std::set::const_iterator itr = aset.begin(); itr != aset.end(); ++itr) + (*itr)->RewardHonor(_player,aset.size()); + + // give bg rewards and update counters like kill by first from attackers + // this can't be called for all attackers. + if (!aset.empty()) + if (BattleGround *bg = _player->GetBattleGround()) + bg->HandleKillPlayer(_player,*aset.begin()); + } + else if (_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) + { + // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION + _player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT); + //_player->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time + _player->KillPlayer(); + _player->BuildPlayerRepop(); + _player->RepopAtGraveyard(); + } + //drop a flag if player is carrying it + if (BattleGround *bg = _player->GetBattleGround()) + bg->EventPlayerLoggedOut(_player); + + ///- Teleport to home if the player is in an invalid instance + if (!_player->m_InstanceValid && !_player->isGameMaster()) + _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation()); + + sOutdoorPvPMgr.HandlePlayerLeaveZone(_player,_player->GetZoneId()); + + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) + { + if (BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i)) + { + _player->RemoveBattleGroundQueueId(bgQueueTypeId); + sBattleGroundMgr.m_BattleGroundQueues[ bgQueueTypeId ].RemovePlayer(_player->GetGUID(), true); + } + } + + // Repop at GraveYard or other player far teleport will prevent saving player because of not present map + // Teleport player immediately for correct player save + while (_player->IsBeingTeleportedFar()) + HandleMoveWorldportAckOpcode(); + + ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members + Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); + if (guild) + { + guild->SetMemberStats(_player->GetGUID()); + guild->UpdateLogoutTime(_player->GetGUID()); + + guild->BroadcastEvent(GE_SIGNED_OFF, _player->GetGUID(), 1, _player->GetName(), "", ""); + } + + ///- Remove pet + _player->RemovePet(NULL,PET_SAVE_AS_CURRENT, true); + + ///- empty buyback items and save the player in the database + // some save parts only correctly work in case player present in map/player_lists (pets, etc) + if (Save) + { + uint32 eslot; + for (int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; ++j) + { + eslot = j - BUYBACK_SLOT_START; + _player->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (eslot * 2), 0); + _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0); + _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, 0); + } + _player->SaveToDB(); + } + + ///- Leave all channels before player delete... + _player->CleanupChannels(); + + ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group. + _player->UninviteFromGroup(); + + // remove player from the group if he is: + // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) + if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket) + _player->RemoveFromGroup(); + + ///- Send update to group and reset stored max enchanting level + if (_player->GetGroup()) + { + _player->GetGroup()->SendUpdate(); + _player->GetGroup()->ResetMaxEnchantingLevel(); + } + + ///- Broadcast a logout message to the player's friends + sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true); + sSocialMgr.RemovePlayerSocial (_player->GetGUIDLow ()); + + ///- Remove the player from the world + // the player may not be in the world when logging out + // e.g if he got disconnected during a transfer to another map + // calls to GetMap in this case may cause crashes + _player->CleanupsBeforeDelete(); + sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() ,_player->GetGUIDLow()); + Map* _map = _player->GetMap(); + _map->Remove(_player, true); + SetPlayer(NULL); // deleted in Remove call + + ///- Send the 'logout complete' packet to the client + WorldPacket data(SMSG_LOGOUT_COMPLETE, 0); + SendPacket(&data); + + ///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline + //No SQL injection as AccountId is uint32 + CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = '%u'", + GetAccountId()); + sLog.outDebug("SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); + } + + //Hook for OnLogout Event + sScriptMgr.OnLogout(_player); + + m_playerLogout = false; + m_playerSave = false; + m_playerRecentlyLogout = true; + LogoutRequest(0); +} + +/// Kick a player out of the World +void WorldSession::KickPlayer() +{ + if (m_Socket) + m_Socket->CloseSocket (); +} + +void WorldSession::SendNotification(const char *format,...) +{ + if (format) + { + va_list ap; + char szStr [1024]; + szStr[0] = '\0'; + va_start(ap, format); + vsnprintf(szStr, 1024, format, ap); + va_end(ap); + + WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr)+1)); + data << szStr; + SendPacket(&data); + } +} + +void WorldSession::SendNotification(int32 string_id,...) +{ + char const* format = GetTrinityString(string_id); + if (format) + { + va_list ap; + char szStr [1024]; + szStr[0] = '\0'; + va_start(ap, string_id); + vsnprintf(szStr, 1024, format, ap); + va_end(ap); + + WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr)+1)); + data << szStr; + SendPacket(&data); + } +} + +const char * WorldSession::GetTrinityString(int32 entry) const +{ + return objmgr.GetTrinityString(entry,GetSessionDbLocaleIndex()); +} + +void WorldSession::Handle_NULL(WorldPacket& recvPacket) +{ + sLog.outError("SESSION: received unhandled opcode %s (0x%.4X)", + LookupOpcodeName(recvPacket.GetOpcode()), + recvPacket.GetOpcode()); +} + +void WorldSession::Handle_EarlyProccess(WorldPacket& recvPacket) +{ + sLog.outError("SESSION: received opcode %s (0x%.4X) that must be processed in WorldSocket::OnRead", + LookupOpcodeName(recvPacket.GetOpcode()), + recvPacket.GetOpcode()); +} + +void WorldSession::Handle_ServerSide(WorldPacket& recvPacket) +{ + sLog.outError("SESSION: received server-side opcode %s (0x%.4X)", + LookupOpcodeName(recvPacket.GetOpcode()), + recvPacket.GetOpcode()); +} + +void WorldSession::Handle_Deprecated(WorldPacket& recvPacket) +{ + sLog.outError("SESSION: received deprecated opcode %s (0x%.4X)", + LookupOpcodeName(recvPacket.GetOpcode()), + recvPacket.GetOpcode()); +} + +void WorldSession::SendAuthWaitQue(uint32 position) +{ + if (position == 0) + { + WorldPacket packet(SMSG_AUTH_RESPONSE, 1); + packet << uint8(AUTH_OK); + SendPacket(&packet); + } + else + { + WorldPacket packet(SMSG_AUTH_RESPONSE, 6); + packet << uint8(AUTH_WAIT_QUEUE); + packet << uint32(position); + packet << uint8(0); // unk + SendPacket(&packet); + } +} + +void WorldSession::LoadGlobalAccountData() +{ + LoadAccountData( + CharacterDatabase.PQuery("SELECT type, time, data FROM account_data WHERE account='%u'", GetAccountId()), + GLOBAL_CACHE_MASK +); +} + +void WorldSession::LoadAccountData(QueryResult_AutoPtr result, uint32 mask) +{ + for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i) + if (mask & (1 << i)) + m_accountData[i] = AccountData(); + + if (!result) + return; + + do + { + Field *fields = result->Fetch(); + + uint32 type = fields[0].GetUInt32(); + if (type >= NUM_ACCOUNT_DATA_TYPES) + { + sLog.outError("Table `%s` have invalid account data type (%u), ignore.", + mask == GLOBAL_CACHE_MASK ? "account_data" : "character_account_data", type); + continue; + } + + if ((mask & (1 << type)) == 0) + { + sLog.outError("Table `%s` have non appropriate for table account data type (%u), ignore.", + mask == GLOBAL_CACHE_MASK ? "account_data" : "character_account_data", type); + continue; + } + + m_accountData[type].Time = fields[1].GetUInt32(); + m_accountData[type].Data = fields[2].GetCppString(); + + } while (result->NextRow()); +} + +void WorldSession::SetAccountData(AccountDataType type, time_t time_, std::string data) +{ + if ((1 << type) & GLOBAL_CACHE_MASK) + { + uint32 acc = GetAccountId(); + + CharacterDatabase.BeginTransaction (); + CharacterDatabase.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type); + CharacterDatabase.escape_string(data); + CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str()); + CharacterDatabase.CommitTransaction (); + } + else + { + // _player can be NULL and packet received after logout but m_GUID still store correct guid + if (!m_GUIDLow) + return; + + CharacterDatabase.BeginTransaction (); + CharacterDatabase.PExecute("DELETE FROM character_account_data WHERE guid='%u' AND type='%u'", m_GUIDLow, type); + CharacterDatabase.escape_string(data); + CharacterDatabase.PExecute("INSERT INTO character_account_data VALUES ('%u','%u','%u','%s')", m_GUIDLow, type, (uint32)time_, data.c_str()); + CharacterDatabase.CommitTransaction (); + } + + m_accountData[type].Time = time_; + m_accountData[type].Data = data; +} + +void WorldSession::SendAccountDataTimes(uint32 mask) +{ + WorldPacket data(SMSG_ACCOUNT_DATA_TIMES, 4+1+4+8*4); // changed in WotLK + data << uint32(time(NULL)); // unix time of something + data << uint8(1); + data << uint32(mask); // type mask + for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i) + if (mask & (1 << i)) + data << uint32(GetAccountData(AccountDataType(i))->Time);// also unix time + SendPacket(&data); +} + +void WorldSession::LoadTutorialsData() +{ + for (int aX = 0 ; aX < 8 ; ++aX) + m_Tutorials[ aX ] = 0; + + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7 FROM character_tutorial WHERE account = '%u'", GetAccountId()); + + if (result) + { + do + { + Field *fields = result->Fetch(); + + for (int iI = 0; iI < 8; ++iI) + m_Tutorials[iI] = fields[iI].GetUInt32(); + } + while (result->NextRow()); + } + m_TutorialsChanged = false; +} + +void WorldSession::SendTutorialsData() +{ + WorldPacket data(SMSG_TUTORIAL_FLAGS, 4*8); + for (uint32 i = 0; i < 8; ++i) + data << m_Tutorials[i]; + SendPacket(&data); +} + +void WorldSession::SaveTutorialsData() +{ + if (!m_TutorialsChanged) + return; + + uint32 Rows=0; + // it's better than rebuilding indexes multiple times + QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT count(*) AS r FROM character_tutorial WHERE account = '%u'", GetAccountId()); + if (result) + Rows = result->Fetch()[0].GetUInt32(); + + if (Rows) + { + CharacterDatabase.PExecute("UPDATE character_tutorial SET tut0='%u', tut1='%u', tut2='%u', tut3='%u', tut4='%u', tut5='%u', tut6='%u', tut7='%u' WHERE account = '%u'", + m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7], GetAccountId()); + } + else + { + CharacterDatabase.PExecute("INSERT INTO character_tutorial (account,tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7) VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetAccountId(), m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7]); + } + + m_TutorialsChanged = false; +} + +void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi) +{ + data >> mi->flags; + data >> mi->unk1; + data >> mi->time; + data >> mi->x; + data >> mi->y; + data >> mi->z; + data >> mi->o; + + if (mi->flags & MOVEMENTFLAG_ONTRANSPORT) + { + if (!data.readPackGUID(mi->t_guid)) + return; + + data >> mi->t_x; + data >> mi->t_y; + data >> mi->t_z; + data >> mi->t_o; + data >> mi->t_time; + data >> mi->t_seat; + } + + if ((mi->flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi->unk1 & 0x20)) + { + data >> mi->s_pitch; + } + + data >> mi->fallTime; + + if (mi->flags & MOVEMENTFLAG_JUMPING) + { + data >> mi->j_zspeed; + data >> mi->j_sinAngle; + data >> mi->j_cosAngle; + data >> mi->j_xyspeed; + } + + if (mi->flags & MOVEMENTFLAG_SPLINE) + { + data >> mi->u_unk1; + } +} + +void WorldSession::WriteMovementInfo(WorldPacket *data, MovementInfo *mi) +{ + data->appendPackGUID(mi->guid); + + *data << mi->flags; + *data << mi->unk1; + *data << mi->time; + *data << mi->x; + *data << mi->y; + *data << mi->z; + *data << mi->o; + + if (mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { + data->appendPackGUID(mi->t_guid); + + *data << mi->t_x; + *data << mi->t_y; + *data << mi->t_z; + *data << mi->t_o; + *data << mi->t_time; + *data << mi->t_seat; + } + + if ((mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING))) || (mi->unk1 & 0x20)) + { + *data << mi->s_pitch; + } + + *data << mi->fallTime; + + if (mi->HasMovementFlag(MOVEMENTFLAG_JUMPING)) + { + *data << mi->j_zspeed; + *data << mi->j_sinAngle; + *data << mi->j_cosAngle; + *data << mi->j_xyspeed; + } + + if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE)) + { + *data << mi->u_unk1; + } +} + +void WorldSession::ReadAddonsInfo(WorldPacket &data) +{ + if (data.rpos() + 4 > data.size()) + return; + uint32 size; + data >> size; + + if (!size) + return; + + if (size > 0xFFFFF) + { + sLog.outError("WorldSession::ReadAddonsInfo addon info too big, size %u", size); + return; + } + + uLongf uSize = size; + + uint32 pos = data.rpos(); + + ByteBuffer addonInfo; + addonInfo.resize(size); + + if (uncompress(const_cast(addonInfo.contents()), &uSize, const_cast(data.contents() + pos), data.size() - pos) == Z_OK) + { + uint32 addonsCount; + addonInfo >> addonsCount; // addons count + + for (uint32 i = 0; i < addonsCount; ++i) + { + std::string addonName; + uint8 enabled; + uint32 crc, unk1; + + // check next addon data format correctness + if (addonInfo.rpos()+1 > addonInfo.size()) + return; + + addonInfo >> addonName; + + addonInfo >> enabled >> crc >> unk1; + + sLog.outDetail("ADDON: Name: %s, Enabled: 0x%x, CRC: 0x%x, Unknown2: 0x%x", addonName.c_str(), enabled, crc, unk1); + + AddonInfo addon(addonName, enabled, crc, 2, true); + + SavedAddon const* savedAddon = sAddonMgr.GetAddonInfo(addonName); + if (savedAddon) + { + bool match = true; + + if (addon.CRC != savedAddon->CRC) + match = false; + + if (!match) + sLog.outDetail("ADDON: %s was known, but didn't match known CRC (0x%x)!", addon.Name.c_str(), savedAddon->CRC); + else + sLog.outDetail("ADDON: %s was known, CRC is correct (0x%x)", addon.Name.c_str(), savedAddon->CRC); + } + else + { + sAddonMgr.SaveAddon(addon); + + sLog.outDetail("ADDON: %s (0x%x) was not known, saving...", addon.Name.c_str(), addon.CRC); + } + + // TODO: Find out when to not use CRC/pubkey, and other possible states. + m_addonsList.push_back(addon); + } + + uint32 currentTime; + addonInfo >> currentTime; + sLog.outDebug("ADDON: CurrentTime: %u", currentTime); + + if (addonInfo.rpos() != addonInfo.size()) + sLog.outDebug("packet under-read!"); + } + else + sLog.outError("Addon packet uncompress error!"); +} + +void WorldSession::SendAddonsInfo() +{ + uint8 addonPublicKey[256] = + { + 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, + 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, + 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, + 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, + 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, + 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, + 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, + 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, + 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, + 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, + 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, + 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, + 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, + 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, + 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, + 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 + }; + + WorldPacket data(SMSG_ADDON_INFO, 4); + + for (AddonsList::iterator itr = m_addonsList.begin(); itr != m_addonsList.end(); ++itr) + { + data << uint8(itr->State); + + uint8 crcpub = itr->UsePublicKeyOrCRC; + data << uint8(crcpub); + if (crcpub) + { + uint8 usepk = (itr->CRC != STANDARD_ADDON_CRC); // If addon is Standard addon CRC + data << uint8(usepk); + if (usepk) // if CRC is wrong, add public key (client need it) + { + sLog.outDetail("ADDON: CRC (0x%x) for addon %s is wrong (does not match expected 0x%x), sending pubkey", + itr->CRC, itr->Name.c_str(), STANDARD_ADDON_CRC); + + data.append(addonPublicKey, sizeof(addonPublicKey)); + } + + data << uint32(/*itr->CRC*/ 0); // TODO: Find out the meaning of this. + } + + uint8 unk3 = 0; // 0 is sent here + data << uint8(unk3); + if (unk3) + { + // String, length 256 (null terminated) + data << uint8(0); + } + } + + m_addonsList.clear(); + + uint32 count = 0; + data << uint32(count); + /*for (uint32 i = 0; i < count; ++i) + { + uint32 + string (16 bytes) + string (16 bytes) + uint32 + uint32 + }*/ + + SendPacket(&data); +} + +void WorldSession::SetPlayer(Player *plr) +{ + _player = plr; + + // set m_GUID that can be used while player loggined and later until m_playerRecentlyLogout not reset + if (_player) + m_GUIDLow = _player->GetGUIDLow(); +} diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h new file mode 100644 index 00000000000..c17f3e3f3e6 --- /dev/null +++ b/src/server/game/Server/WorldSession.h @@ -0,0 +1,829 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup u2w +/// @{ +/// \file + +#ifndef __WORLDSESSION_H +#define __WORLDSESSION_H + +#include "Common.h" +#include "SharedDefines.h" +#include "AddonMgr.h" +#include "QueryResult.h" +#include "World.h" + +struct ItemPrototype; +struct AuctionEntry; +struct DeclinedName; +struct MovementInfo; + +class Creature; +class Item; +class Object; +class Player; +class Unit; +class GameObject; +class WorldPacket; +class WorldSocket; +class QueryResult; +class LoginQueryHolder; +class CharacterHandler; +struct AreaTableEntry; + +enum AccountDataType +{ + GLOBAL_CONFIG_CACHE = 0, // 0x01 g + PER_CHARACTER_CONFIG_CACHE = 1, // 0x02 p + GLOBAL_BINDINGS_CACHE = 2, // 0x04 g + PER_CHARACTER_BINDINGS_CACHE = 3, // 0x08 p + GLOBAL_MACROS_CACHE = 4, // 0x10 g + PER_CHARACTER_MACROS_CACHE = 5, // 0x20 p + PER_CHARACTER_LAYOUT_CACHE = 6, // 0x40 p + PER_CHARACTER_CHAT_CACHE = 7, // 0x80 p +}; + +#define NUM_ACCOUNT_DATA_TYPES 8 + +#define GLOBAL_CACHE_MASK 0x15 +#define PER_CHARACTER_CACHE_MASK 0xEA + +struct AccountData +{ + AccountData() : Time(0), Data("") {} + + time_t Time; + std::string Data; +}; + +enum PartyOperation +{ + PARTY_OP_INVITE = 0, + PARTY_OP_UNINVITE = 1, + PARTY_OP_LEAVE = 2, + PARTY_OP_SWAP = 4 +}; + +enum PartyResult +{ + ERR_PARTY_RESULT_OK = 0, + ERR_BAD_PLAYER_NAME_S = 1, + ERR_TARGET_NOT_IN_GROUP_S = 2, + ERR_TARGET_NOT_IN_INSTANCE_S = 3, + ERR_GROUP_FULL = 4, + ERR_ALREADY_IN_GROUP_S = 5, + ERR_NOT_IN_GROUP = 6, + ERR_NOT_LEADER = 7, + ERR_PLAYER_WRONG_FACTION = 8, + ERR_IGNORING_YOU_S = 9, + ERR_LFG_PENDING = 12, + ERR_INVITE_RESTRICTED = 13, + ERR_GROUP_SWAP_FAILED = 14, // if (PartyOperation == PARTY_OP_SWAP) ERR_GROUP_SWAP_FAILED else ERR_INVITE_IN_COMBAT + ERR_INVITE_UNKNOWN_REALM = 15, + ERR_INVITE_NO_PARTY_SERVER = 16, + ERR_INVITE_PARTY_BUSY = 17, + ERR_PARTY_TARGET_AMBIGUOUS = 18, + ERR_PARTY_LFG_INVITE_RAID_LOCKED = 19, + ERR_PARTY_LFG_BOOT_LIMIT = 20, + ERR_PARTY_LFG_BOOT_COOLDOWN_S = 21, + ERR_PARTY_LFG_BOOT_IN_PROGRESS = 22, + ERR_PARTY_LFG_BOOT_TOO_FEW_PLAYERS = 23, + ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S = 24, + ERR_RAID_DISALLOWED_BY_LEVEL = 25, + ERR_PARTY_LFG_BOOT_IN_COMBAT = 26, + ERR_VOTE_KICK_REASON_NEEDED = 27, + ERR_PARTY_LFG_BOOT_DUNGEON_COMPLETE = 28, + ERR_PARTY_LFG_BOOT_LOOT_ROLLS = 29, + ERR_PARTY_LFG_TELEPORT_IN_COMBAT = 30 +}; + +enum ChatRestrictionType +{ + ERR_CHAT_RESTRICTED = 0, + ERR_CHAT_THROTTLED = 1, + ERR_USER_SQUELCHED = 2, + ERR_YELL_RESTRICTED = 3 +}; + +/// Player session in the World +class WorldSession +{ + friend class CharacterHandler; + public: + WorldSession(uint32 id, WorldSocket *sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale); + ~WorldSession(); + + bool PlayerLoading() const { return m_playerLoading; } + bool PlayerLogout() const { return m_playerLogout; } + bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; } + + void SizeError(WorldPacket const& packet, uint32 size) const; + + void ReadAddonsInfo(WorldPacket &data); + void SendAddonsInfo(); + + void ReadMovementInfo(WorldPacket &data, MovementInfo *mi); + void WriteMovementInfo(WorldPacket *data, MovementInfo *mi); + + void SendPacket(WorldPacket const* packet); + void SendNotification(const char *format,...) ATTR_PRINTF(2,3); + void SendNotification(int32 string_id,...); + void SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName); + void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res); + void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2,3); + void SendSetPhaseShift(uint32 phaseShift); + void SendQueryTimeResponse(); + + AccountTypes GetSecurity() const { return _security; } + uint32 GetAccountId() const { return _accountId; } + Player* GetPlayer() const { return _player; } + char const* GetPlayerName() const; + void SetSecurity(AccountTypes security) { _security = security; } + std::string const& GetRemoteAddress() { return m_Address; } + void SetPlayer(Player *plr); + uint8 Expansion() const { return m_expansion; } + + /// Session in auth.queue currently + void SetInQueue(bool state) { m_inQueue = state; } + + /// Is the user engaged in a log out process? + bool isLogingOut() const { return _logoutTime || m_playerLogout; } + + /// Engage the logout process for the user + void LogoutRequest(time_t requestTime) + { + _logoutTime = requestTime; + } + + /// Is logout cooldown expired? + bool ShouldLogOut(time_t currTime) const + { + return (_logoutTime > 0 && currTime >= _logoutTime + 20); + } + + void LogoutPlayer(bool Save); + void KickPlayer(); + + void QueuePacket(WorldPacket* new_packet); + bool Update(uint32 diff); + + /// Handle the authentication waiting queue (to be completed) + void SendAuthWaitQue(uint32 position); + + //void SendTestCreatureQueryOpcode(uint32 entry, uint64 guid, uint32 testvalue); + void SendNameQueryOpcode(Player* p); + void SendNameQueryOpcodeFromDB(uint64 guid); + static void SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, uint32 accountId); + + void SendTrainerList(uint64 guid); + void SendTrainerList(uint64 guid, const std::string& strTitle); + void SendListInventory(uint64 guid); + void SendShowBank(uint64 guid); + void SendTabardVendorActivate(uint64 guid); + void SendSpiritResurrect(); + void SendBindPoint(Creature* npc); + + void SendAttackStop(Unit const* enemy); + + void SendBattlegGroundList(uint64 guid, BattleGroundTypeId bgTypeId); + + void SendTradeStatus(uint32 status); + void SendCancelTrade(); + + void SendStablePet(uint64 guid); + void SendPetitionQueryOpcode(uint64 petitionguid); + void SendUpdateTrade(); + + //pet + void SendPetNameQuery(uint64 guid, uint32 petnumber); + + // Account Data + AccountData *GetAccountData(AccountDataType type) { return &m_accountData[type]; } + void SetAccountData(AccountDataType type, time_t time_, std::string data); + void SendAccountDataTimes(uint32 mask); + void LoadGlobalAccountData(); + void LoadAccountData(QueryResult_AutoPtr result, uint32 mask); + void LoadTutorialsData(); + void SendTutorialsData(); + void SaveTutorialsData(); + uint32 GetTutorialInt(uint32 intId) + { + return m_Tutorials[intId]; + } + + void SetTutorialInt(uint32 intId, uint32 value) + { + if (m_Tutorials[intId] != value) + { + m_Tutorials[intId] = value; + m_TutorialsChanged = true; + } + } + //used with item_page table + bool SendItemInfo(uint32 itemid, WorldPacket data); + //auction + void SendAuctionHello(uint64 guid, Creature * unit); + void SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0); + void SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template); + void SendAuctionOwnerNotification(AuctionEntry * auction); + void SendAuctionOutbiddedMail(AuctionEntry * auction, uint32 newPrice); + void SendAuctionCancelledToBidderMail(AuctionEntry* auction); + + //Item Enchantment + void SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID); + void SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration); + + //Taxi + void SendTaxiStatus(uint64 guid); + void SendTaxiMenu(Creature* unit); + void SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode = 0); + bool SendLearnNewTaxiNode(Creature* unit); + + // Guild/Arena Team + void SendGuildCommandResult(uint32 typecmd, const std::string& str, uint32 cmdresult); + void SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id); + void SendNotInArenaTeamPacket(uint8 type); + void SendPetitionShowList(uint64 guid); + void SendSaveGuildEmblem(uint32 msg); + // Looking For Group + // TRUE values set by client sending CMSG_LFG_SET_AUTOJOIN and CMSG_LFM_CLEAR_AUTOFILL before player login + bool LookingForGroup_auto_join; + bool LookingForGroup_auto_add; + + void BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data); + + void DoLootRelease(uint64 lguid); + + // Account mute time + time_t m_muteTime; + + // Locales + LocaleConstant GetSessionDbcLocale() const { return m_sessionDbcLocale; } + int GetSessionDbLocaleIndex() const { return m_sessionDbLocaleIndex; } + const char *GetTrinityString(int32 entry) const; + + uint32 GetLatency() const { return m_latency; } + void SetLatency(uint32 latency) { m_latency = latency; } + uint32 getDialogStatus(Player *pPlayer, Object* questgiver, uint32 defstatus); + + time_t m_timeOutTime; + void UpdateTimeOutTime(uint32 diff) + { + if (diff > m_timeOutTime) + m_timeOutTime = 0; + else + m_timeOutTime -= diff; + } + void ResetTimeOutTime() + { + m_timeOutTime = sWorld.getConfig(CONFIG_SOCKET_TIMEOUTTIME); + } + bool IsConnectionIdle() const + { + if (m_timeOutTime <= 0 && !m_inQueue) + return true; + return false; + } + + + public: // opcodes handlers + + void Handle_NULL(WorldPacket& recvPacket); // not used + void Handle_EarlyProccess(WorldPacket& recvPacket);// just mark packets processed in WorldSocket::OnRead + void Handle_ServerSide(WorldPacket& recvPacket); // sever side only, can't be accepted from client + void Handle_Deprecated(WorldPacket& recvPacket); // never used anymore by client + + void HandleCharEnumOpcode(WorldPacket& recvPacket); + void HandleCharDeleteOpcode(WorldPacket& recvPacket); + void HandleCharCreateOpcode(WorldPacket& recvPacket); + void HandlePlayerLoginOpcode(WorldPacket& recvPacket); + void HandleCharEnum(QueryResult_AutoPtr result); + void HandlePlayerLogin(LoginQueryHolder * holder); + + // played time + void HandlePlayedTime(WorldPacket& recvPacket); + + // new + void HandleMoveUnRootAck(WorldPacket& recvPacket); + void HandleMoveRootAck(WorldPacket& recvPacket); + void HandleLookingForGroup(WorldPacket& recvPacket); + + // new inspect + void HandleInspectOpcode(WorldPacket& recvPacket); + + // new party stats + void HandleInspectHonorStatsOpcode(WorldPacket& recvPacket); + + void HandleMoveWaterWalkAck(WorldPacket& recvPacket); + void HandleFeatherFallAck(WorldPacket &recv_data); + + void HandleMoveHoverAck(WorldPacket & recv_data); + + void HandleMountSpecialAnimOpcode(WorldPacket &recvdata); + + // character view + void HandleShowingHelmOpcode(WorldPacket& recv_data); + void HandleShowingCloakOpcode(WorldPacket& recv_data); + + // repair + void HandleRepairItemOpcode(WorldPacket& recvPacket); + + // Knockback + void HandleMoveKnockBackAck(WorldPacket& recvPacket); + + void HandleMoveTeleportAck(WorldPacket& recvPacket); + void HandleForceSpeedChangeAck(WorldPacket & recv_data); + + void HandlePingOpcode(WorldPacket& recvPacket); + void HandleAuthSessionOpcode(WorldPacket& recvPacket); + void HandleRepopRequestOpcode(WorldPacket& recvPacket); + void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket); + void HandleLootMoneyOpcode(WorldPacket& recvPacket); + void HandleLootOpcode(WorldPacket& recvPacket); + void HandleLootReleaseOpcode(WorldPacket& recvPacket); + void HandleLootMasterGiveOpcode(WorldPacket& recvPacket); + void HandleWhoOpcode(WorldPacket& recvPacket); + void HandleLogoutRequestOpcode(WorldPacket& recvPacket); + void HandlePlayerLogoutOpcode(WorldPacket& recvPacket); + void HandleLogoutCancelOpcode(WorldPacket& recvPacket); + + // GM Ticket opcodes + void HandleGMTicketCreateOpcode(WorldPacket& recvPacket); + void HandleGMTicketUpdateOpcode(WorldPacket& recvPacket); + void HandleGMTicketDeleteOpcode(WorldPacket& recvPacket); + void HandleGMTicketGetTicketOpcode(WorldPacket& recvPacket); + void HandleGMTicketSystemStatusOpcode(WorldPacket& recvPacket); + void SendGMTicketGetTicket(uint32 status, char const* text); + + //void HandleGMSurveySubmit(WorldPacket& recvPacket); + + void HandleTogglePvP(WorldPacket& recvPacket); + + void HandleZoneUpdateOpcode(WorldPacket& recvPacket); + void HandleSetTargetOpcode(WorldPacket& recvPacket); + void HandleSetSelectionOpcode(WorldPacket& recvPacket); + void HandleStandStateChangeOpcode(WorldPacket& recvPacket); + void HandleEmoteOpcode(WorldPacket& recvPacket); + void HandleContactListOpcode(WorldPacket& recvPacket); + void HandleAddFriendOpcode(WorldPacket& recvPacket); + static void HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string friendNote); + void HandleDelFriendOpcode(WorldPacket& recvPacket); + void HandleAddIgnoreOpcode(WorldPacket& recvPacket); + static void HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId); + void HandleDelIgnoreOpcode(WorldPacket& recvPacket); + void HandleSetContactNotesOpcode(WorldPacket& recvPacket); + void HandleBugOpcode(WorldPacket& recvPacket); + void HandleSetAmmoOpcode(WorldPacket& recvPacket); + void HandleItemNameQueryOpcode(WorldPacket& recvPacket); + + void HandleAreaTriggerOpcode(WorldPacket& recvPacket); + + void HandleSetFactionAtWar(WorldPacket & recv_data); + void HandleSetFactionCheat(WorldPacket & recv_data); + void HandleSetWatchedFactionOpcode(WorldPacket & recv_data); + void HandleSetFactionInactiveOpcode(WorldPacket & recv_data); + + void HandleUpdateAccountData(WorldPacket& recvPacket); + void HandleRequestAccountData(WorldPacket& recvPacket); + void HandleSetActionButtonOpcode(WorldPacket& recvPacket); + + void HandleGameObjectUseOpcode(WorldPacket& recPacket); + void HandleMeetingStoneInfo(WorldPacket& recPacket); + void HandleGameobjectReportUse(WorldPacket& recvPacket); + + void HandleNameQueryOpcode(WorldPacket& recvPacket); + + void HandleQueryTimeOpcode(WorldPacket& recvPacket); + + void HandleCreatureQueryOpcode(WorldPacket& recvPacket); + + void HandleGameObjectQueryOpcode(WorldPacket& recvPacket); + + void HandleMoveWorldportAckOpcode(WorldPacket& recvPacket); + void HandleMoveWorldportAckOpcode(); // for server-side calls + + void HandleMovementOpcodes(WorldPacket& recvPacket); + void HandleSetActiveMoverOpcode(WorldPacket &recv_data); + void HandleMoveNotActiveMover(WorldPacket &recv_data); + void HandleDismissControlledVehicle(WorldPacket &recv_data); + void HandleRequestVehicleExit(WorldPacket &recv_data); + void HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data); + void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); + + void HandleRequestRaidInfoOpcode(WorldPacket & recv_data); + + void HandleBattlefieldStatusOpcode(WorldPacket &recv_data); + void HandleBattleMasterHelloOpcode(WorldPacket &recv_data); + + void HandleGroupInviteOpcode(WorldPacket& recvPacket); + //void HandleGroupCancelOpcode(WorldPacket& recvPacket); + void HandleGroupAcceptOpcode(WorldPacket& recvPacket); + void HandleGroupDeclineOpcode(WorldPacket& recvPacket); + void HandleGroupUninviteOpcode(WorldPacket& recvPacket); + void HandleGroupUninviteGuidOpcode(WorldPacket& recvPacket); + void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket); + void HandleGroupDisbandOpcode(WorldPacket& recvPacket); + void HandleOptOutOfLootOpcode(WorldPacket &recv_data); + void HandleLootMethodOpcode(WorldPacket& recvPacket); + void HandleLootRoll(WorldPacket &recv_data); + void HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data); + void HandleRaidTargetUpdateOpcode(WorldPacket & recv_data); + void HandleRaidReadyCheckOpcode(WorldPacket & recv_data); + void HandleRaidReadyCheckFinishedOpcode(WorldPacket & recv_data); + void HandleGroupRaidConvertOpcode(WorldPacket & recv_data); + void HandleGroupChangeSubGroupOpcode(WorldPacket & recv_data); + void HandleGroupAssistantLeaderOpcode(WorldPacket & recv_data); + void HandlePartyAssignmentOpcode(WorldPacket & recv_data); + + void HandlePetitionBuyOpcode(WorldPacket& recv_data); + void HandlePetitionShowSignOpcode(WorldPacket& recv_data); + void HandlePetitionQueryOpcode(WorldPacket& recv_data); + void HandlePetitionRenameOpcode(WorldPacket& recv_data); + void HandlePetitionSignOpcode(WorldPacket& recv_data); + void HandlePetitionDeclineOpcode(WorldPacket& recv_data); + void HandleOfferPetitionOpcode(WorldPacket& recv_data); + void HandleTurnInPetitionOpcode(WorldPacket& recv_data); + + void HandleGuildQueryOpcode(WorldPacket& recvPacket); + void HandleGuildCreateOpcode(WorldPacket& recvPacket); + void HandleGuildInviteOpcode(WorldPacket& recvPacket); + void HandleGuildRemoveOpcode(WorldPacket& recvPacket); + void HandleGuildAcceptOpcode(WorldPacket& recvPacket); + void HandleGuildDeclineOpcode(WorldPacket& recvPacket); + void HandleGuildInfoOpcode(WorldPacket& recvPacket); + void HandleGuildEventLogQueryOpcode(WorldPacket& recvPacket); + void HandleGuildRosterOpcode(WorldPacket& recvPacket); + void HandleGuildPromoteOpcode(WorldPacket& recvPacket); + void HandleGuildDemoteOpcode(WorldPacket& recvPacket); + void HandleGuildLeaveOpcode(WorldPacket& recvPacket); + void HandleGuildDisbandOpcode(WorldPacket& recvPacket); + void HandleGuildLeaderOpcode(WorldPacket& recvPacket); + void HandleGuildMOTDOpcode(WorldPacket& recvPacket); + void HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket); + void HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket); + void HandleGuildRankOpcode(WorldPacket& recvPacket); + void HandleGuildAddRankOpcode(WorldPacket& recvPacket); + void HandleGuildDelRankOpcode(WorldPacket& recvPacket); + void HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket); + void HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket); + + void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket); + void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket); + void HandleActivateTaxiOpcode(WorldPacket& recvPacket); + void HandleActivateTaxiExpressOpcode(WorldPacket& recvPacket); + void HandleMoveSplineDoneOpcode(WorldPacket& recvPacket); + + void HandleTabardVendorActivateOpcode(WorldPacket& recvPacket); + void HandleBankerActivateOpcode(WorldPacket& recvPacket); + void HandleBuyBankSlotOpcode(WorldPacket& recvPacket); + void HandleTrainerListOpcode(WorldPacket& recvPacket); + void HandleTrainerBuySpellOpcode(WorldPacket& recvPacket); + void HandlePetitionShowListOpcode(WorldPacket& recvPacket); + void HandleGossipHelloOpcode(WorldPacket& recvPacket); + void HandleGossipSelectOptionOpcode(WorldPacket& recvPacket); + void HandleSpiritHealerActivateOpcode(WorldPacket& recvPacket); + void HandleNpcTextQueryOpcode(WorldPacket& recvPacket); + void HandleBinderActivateOpcode(WorldPacket& recvPacket); + void HandleListStabledPetsOpcode(WorldPacket& recvPacket); + void HandleStablePet(WorldPacket& recvPacket); + void HandleUnstablePet(WorldPacket& recvPacket); + void HandleBuyStableSlot(WorldPacket& recvPacket); + void HandleStableRevivePet(WorldPacket& recvPacket); + void HandleStableSwapPet(WorldPacket& recvPacket); + + void HandleDuelAcceptedOpcode(WorldPacket& recvPacket); + void HandleDuelCancelledOpcode(WorldPacket& recvPacket); + + void HandleAcceptTradeOpcode(WorldPacket& recvPacket); + void HandleBeginTradeOpcode(WorldPacket& recvPacket); + void HandleBusyTradeOpcode(WorldPacket& recvPacket); + void HandleCancelTradeOpcode(WorldPacket& recvPacket); + void HandleClearTradeItemOpcode(WorldPacket& recvPacket); + void HandleIgnoreTradeOpcode(WorldPacket& recvPacket); + void HandleInitiateTradeOpcode(WorldPacket& recvPacket); + void HandleSetTradeGoldOpcode(WorldPacket& recvPacket); + void HandleSetTradeItemOpcode(WorldPacket& recvPacket); + void HandleUnacceptTradeOpcode(WorldPacket& recvPacket); + + void HandleAuctionHelloOpcode(WorldPacket& recvPacket); + void HandleAuctionListItems(WorldPacket & recv_data); + void HandleAuctionListBidderItems(WorldPacket & recv_data); + void HandleAuctionSellItem(WorldPacket & recv_data); + void HandleAuctionRemoveItem(WorldPacket & recv_data); + void HandleAuctionListOwnerItems(WorldPacket & recv_data); + void HandleAuctionPlaceBid(WorldPacket & recv_data); + void HandleAuctionListPendingSales(WorldPacket & recv_data); + + void HandleGetMailList(WorldPacket & recv_data); + void HandleSendMail(WorldPacket & recv_data); + void HandleMailTakeMoney(WorldPacket & recv_data); + void HandleMailTakeItem(WorldPacket & recv_data); + void HandleMailMarkAsRead(WorldPacket & recv_data); + void HandleMailReturnToSender(WorldPacket & recv_data); + void HandleMailDelete(WorldPacket & recv_data); + void HandleItemTextQuery(WorldPacket & recv_data); + void HandleMailCreateTextItem(WorldPacket & recv_data); + void HandleQueryNextMailTime(WorldPacket & recv_data); + void HandleCancelChanneling(WorldPacket & recv_data); + + void SendItemPageInfo(ItemPrototype *itemProto); + void HandleSplitItemOpcode(WorldPacket& recvPacket); + void HandleSwapInvItemOpcode(WorldPacket& recvPacket); + void HandleDestroyItemOpcode(WorldPacket& recvPacket); + void HandleAutoEquipItemOpcode(WorldPacket& recvPacket); + void HandleItemQuerySingleOpcode(WorldPacket& recvPacket); + void HandleSellItemOpcode(WorldPacket& recvPacket); + void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket); + void HandleBuyItemOpcode(WorldPacket& recvPacket); + void HandleListInventoryOpcode(WorldPacket& recvPacket); + void HandleAutoStoreBagItemOpcode(WorldPacket& recvPacket); + void HandleReadItem(WorldPacket& recvPacket); + void HandleAutoEquipItemSlotOpcode(WorldPacket & recvPacket); + void HandleSwapItem(WorldPacket & recvPacket); + void HandleBuybackItem(WorldPacket & recvPacket); + void HandleAutoBankItemOpcode(WorldPacket& recvPacket); + void HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket); + void HandleWrapItemOpcode(WorldPacket& recvPacket); + + void HandleAttackSwingOpcode(WorldPacket& recvPacket); + void HandleAttackStopOpcode(WorldPacket& recvPacket); + void HandleSetSheathedOpcode(WorldPacket& recvPacket); + + void HandleUseItemOpcode(WorldPacket& recvPacket); + void HandleOpenItemOpcode(WorldPacket& recvPacket); + void HandleCastSpellOpcode(WorldPacket& recvPacket); + void HandleCancelCastOpcode(WorldPacket& recvPacket); + void HandleCancelAuraOpcode(WorldPacket& recvPacket); + void HandleCancelGrowthAuraOpcode(WorldPacket& recvPacket); + void HandleCancelAutoRepeatSpellOpcode(WorldPacket& recvPacket); + + void HandleLearnTalentOpcode(WorldPacket& recvPacket); + void HandleLearnPreviewTalents(WorldPacket& recvPacket); + void HandleTalentWipeConfirmOpcode(WorldPacket& recvPacket); + void HandleUnlearnSkillOpcode(WorldPacket& recvPacket); + + void HandleQuestgiverStatusQueryOpcode(WorldPacket& recvPacket); + void HandleQuestgiverStatusMultipleQuery(WorldPacket& recvPacket); + void HandleQuestgiverHelloOpcode(WorldPacket& recvPacket); + void HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvPacket); + void HandleQuestgiverQueryQuestOpcode(WorldPacket& recvPacket); + void HandleQuestgiverChooseRewardOpcode(WorldPacket& recvPacket); + void HandleQuestgiverRequestRewardOpcode(WorldPacket& recvPacket); + void HandleQuestQueryOpcode(WorldPacket& recvPacket); + void HandleQuestgiverCancel(WorldPacket& recv_data); + void HandleQuestLogSwapQuest(WorldPacket& recv_data); + void HandleQuestLogRemoveQuest(WorldPacket& recv_data); + void HandleQuestConfirmAccept(WorldPacket& recv_data); + void HandleQuestgiverCompleteQuest(WorldPacket& recv_data); + void HandleQuestgiverQuestAutoLaunch(WorldPacket& recvPacket); + void HandlePushQuestToParty(WorldPacket& recvPacket); + void HandleQuestPushResult(WorldPacket& recvPacket); + + bool processChatmessageFurtherAfterSecurityChecks(std::string&, uint32); + void HandleMessagechatOpcode(WorldPacket& recvPacket); + void SendPlayerNotFoundNotice(std::string name); + void SendPlayerAmbiguousNotice(std::string name); + void SendWrongFactionNotice(); + void SendChatRestrictedNotice(ChatRestrictionType restriction); + void HandleTextEmoteOpcode(WorldPacket& recvPacket); + void HandleChatIgnoredOpcode(WorldPacket& recvPacket); + + void HandleReclaimCorpseOpcode(WorldPacket& recvPacket); + void HandleCorpseQueryOpcode(WorldPacket& recvPacket); + void HandleCorpseMapPositionQuery(WorldPacket& recvPacket); + void HandleResurrectResponseOpcode(WorldPacket& recvPacket); + void HandleSummonResponseOpcode(WorldPacket& recv_data); + + void HandleJoinChannel(WorldPacket& recvPacket); + void HandleLeaveChannel(WorldPacket& recvPacket); + void HandleChannelList(WorldPacket& recvPacket); + void HandleChannelPassword(WorldPacket& recvPacket); + void HandleChannelSetOwner(WorldPacket& recvPacket); + void HandleChannelOwner(WorldPacket& recvPacket); + void HandleChannelModerator(WorldPacket& recvPacket); + void HandleChannelUnmoderator(WorldPacket& recvPacket); + void HandleChannelMute(WorldPacket& recvPacket); + void HandleChannelUnmute(WorldPacket& recvPacket); + void HandleChannelInvite(WorldPacket& recvPacket); + void HandleChannelKick(WorldPacket& recvPacket); + void HandleChannelBan(WorldPacket& recvPacket); + void HandleChannelUnban(WorldPacket& recvPacket); + void HandleChannelAnnouncements(WorldPacket& recvPacket); + void HandleChannelModerate(WorldPacket& recvPacket); + void HandleChannelDeclineInvite(WorldPacket& recvPacket); + void HandleChannelDisplayListQuery(WorldPacket& recvPacket); + void HandleGetChannelMemberCount(WorldPacket& recvPacket); + void HandleSetChannelWatch(WorldPacket& recvPacket); + + void HandleCompleteCinematic(WorldPacket& recvPacket); + void HandleNextCinematicCamera(WorldPacket& recvPacket); + + void HandlePageQuerySkippedOpcode(WorldPacket& recvPacket); + void HandlePageTextQueryOpcode(WorldPacket& recvPacket); + + void HandleTutorialFlag (WorldPacket & recv_data); + void HandleTutorialClear(WorldPacket & recv_data); + void HandleTutorialReset(WorldPacket & recv_data); + + //Pet + void HandlePetAction(WorldPacket & recv_data); + void HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid, uint16 flag, uint64 guid2); + void HandlePetNameQuery(WorldPacket & recv_data); + void HandlePetSetAction(WorldPacket & recv_data); + void HandlePetAbandon(WorldPacket & recv_data); + void HandlePetRename(WorldPacket & recv_data); + void HandlePetCancelAuraOpcode(WorldPacket& recvPacket); + void HandlePetUnlearnOpcode(WorldPacket& recvPacket); + void HandlePetSpellAutocastOpcode(WorldPacket& recvPacket); + void HandlePetCastSpellOpcode(WorldPacket& recvPacket); + void HandlePetLearnTalent(WorldPacket& recvPacket); + void HandleLearnPreviewTalentsPet(WorldPacket& recvPacket); + + void HandleSetActionBarToggles(WorldPacket& recv_data); + + void HandleCharRenameOpcode(WorldPacket& recv_data); + static void HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string newname); + void HandleSetPlayerDeclinedNames(WorldPacket& recv_data); + + void HandleTotemDestroyed(WorldPacket& recv_data); + void HandleDismissCritter(WorldPacket& recv_data); + + //BattleGround + void HandleBattlemasterHelloOpcode(WorldPacket &recv_data); + void HandleBattlemasterJoinOpcode(WorldPacket &recv_data); + void HandleBattleGroundPlayerPositionsOpcode(WorldPacket& recv_data); + void HandlePVPLogDataOpcode(WorldPacket &recv_data); + void HandleBattleFieldPortOpcode(WorldPacket &recv_data); + void HandleBattlefieldListOpcode(WorldPacket &recv_data); + void HandleLeaveBattlefieldOpcode(WorldPacket &recv_data); + void HandleBattlemasterJoinArena(WorldPacket &recv_data); + void HandleReportPvPAFK(WorldPacket &recv_data); + + void HandleWardenDataOpcode(WorldPacket& recv_data); + void HandleWorldTeleportOpcode(WorldPacket& recv_data); + void HandleMinimapPingOpcode(WorldPacket& recv_data); + void HandleRandomRollOpcode(WorldPacket& recv_data); + void HandleFarSightOpcode(WorldPacket& recv_data); + void HandleSetDungeonDifficultyOpcode(WorldPacket& recv_data); + void HandleSetRaidDifficultyOpcode(WorldPacket& recv_data); + void HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data); + void HandleSetTitleOpcode(WorldPacket& recv_data); + void HandleRealmSplitOpcode(WorldPacket& recv_data); + void HandleTimeSyncResp(WorldPacket& recv_data); + void HandleWhoisOpcode(WorldPacket& recv_data); + void HandleResetInstancesOpcode(WorldPacket& recv_data); + + // Looking for Dungeon/Raid + void HandleSetLfgCommentOpcode(WorldPacket & recv_data); + void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recv_data); + void HandleLfgPartyLockInfoRequestOpcode(WorldPacket& recv_data); + void HandleLfgJoinOpcode(WorldPacket &recv_data); + void HandleLfgLeaveOpcode(WorldPacket & /*recv_data*/); + void HandleLfgSetRolesOpcode(WorldPacket &recv_data); + void SendLfgUpdatePlayer(uint8 updateType); + void SendLfgUpdateParty(uint8 updateType); + void SendLfgRoleChosen(uint64 guid, uint8 roles); + void SendLfgUpdateSearch(bool update); + void SendLfgJoinResult(uint8 checkResult, uint8 checkValue); + void SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps); + + // Arena Team + void HandleInspectArenaTeamsOpcode(WorldPacket& recv_data); + void HandleArenaTeamQueryOpcode(WorldPacket& recv_data); + void HandleArenaTeamRosterOpcode(WorldPacket& recv_data); + void HandleArenaTeamInviteOpcode(WorldPacket& recv_data); + void HandleArenaTeamAcceptOpcode(WorldPacket& recv_data); + void HandleArenaTeamDeclineOpcode(WorldPacket& recv_data); + void HandleArenaTeamLeaveOpcode(WorldPacket& recv_data); + void HandleArenaTeamRemoveOpcode(WorldPacket& recv_data); + void HandleArenaTeamDisbandOpcode(WorldPacket& recv_data); + void HandleArenaTeamLeaderOpcode(WorldPacket& recv_data); + + void HandleAreaSpiritHealerQueryOpcode(WorldPacket& recv_data); + void HandleAreaSpiritHealerQueueOpcode(WorldPacket& recv_data); + void HandleCancelMountAuraOpcode(WorldPacket& recv_data); + void HandleSelfResOpcode(WorldPacket& recv_data); + void HandleComplainOpcode(WorldPacket& recv_data); + void HandleRequestPetInfoOpcode(WorldPacket& recv_data); + + // Socket gem + void HandleSocketOpcode(WorldPacket& recv_data); + + void HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data); + + void HandleItemRefundInfoRequest(WorldPacket& recv_data); + void HandleItemRefund(WorldPacket& recv_data); + + void HandleChannelVoiceOnOpcode(WorldPacket & recv_data); + void HandleVoiceSessionEnableOpcode(WorldPacket& recv_data); + void HandleSetActiveVoiceChannel(WorldPacket& recv_data); + void HandleSetTaxiBenchmarkOpcode(WorldPacket& recv_data); + + // Guild Bank + void HandleGuildPermissions(WorldPacket& recv_data); + void HandleGuildBankMoneyWithdrawn(WorldPacket& recv_data); + void HandleGuildBankerActivate(WorldPacket& recv_data); + void HandleGuildBankQueryTab(WorldPacket& recv_data); + void HandleGuildBankLogQuery(WorldPacket& recv_data); + void HandleGuildBankDepositMoney(WorldPacket& recv_data); + void HandleGuildBankWithdrawMoney(WorldPacket& recv_data); + void HandleGuildBankSwapItems(WorldPacket& recv_data); + + void HandleGuildBankUpdateTab(WorldPacket& recv_data); + void HandleGuildBankBuyTab(WorldPacket& recv_data); + void HandleQueryGuildBankTabText(WorldPacket& recv_data); + void HandleSetGuildBankTabText(WorldPacket& recv_data); + + // Calendar + void HandleCalendarGetCalendar(WorldPacket& recv_data); + void HandleCalendarGetEvent(WorldPacket& recv_data); + void HandleCalendarGuildFilter(WorldPacket& recv_data); + void HandleCalendarArenaTeam(WorldPacket& recv_data); + void HandleCalendarAddEvent(WorldPacket& recv_data); + void HandleCalendarUpdateEvent(WorldPacket& recv_data); + void HandleCalendarRemoveEvent(WorldPacket& recv_data); + void HandleCalendarCopyEvent(WorldPacket& recv_data); + void HandleCalendarEventInvite(WorldPacket& recv_data); + void HandleCalendarEventRsvp(WorldPacket& recv_data); + void HandleCalendarEventRemoveInvite(WorldPacket& recv_data); + void HandleCalendarEventStatus(WorldPacket& recv_data); + void HandleCalendarEventModeratorStatus(WorldPacket& recv_data); + void HandleCalendarComplain(WorldPacket& recv_data); + void HandleCalendarGetNumPending(WorldPacket& recv_data); + + void HandleSpellClick(WorldPacket& recv_data); + void HandleMirrrorImageDataRequest(WorldPacket & recv_data); + void HandleAlterAppearance(WorldPacket& recv_data); + void HandleRemoveGlyph(WorldPacket& recv_data); + void HandleCharCustomize(WorldPacket& recv_data); + void HandleQueryInspectAchievements(WorldPacket& recv_data); + void HandleEquipmentSetSave(WorldPacket& recv_data); + void HandleEquipmentSetDelete(WorldPacket& recv_data); + void HandleEquipmentSetUse(WorldPacket& recv_data); + void HandleWorldStateUITimerUpdate(WorldPacket& recv_data); + void HandleReadyForAccountDataTimes(WorldPacket& recv_data); + void HandleQueryQuestsCompleted(WorldPacket& recv_data); + void HandleQuestPOIQuery(WorldPacket& recv_data); + void HandleOnPVPKill(Player *killed); + bool HandleOnPlayerChat(const char *text); + uint32 HandleOnGetXP(uint32 amount); + int32 HandleOnGetMoney(int32 amount); + void HandleOnAreaChange(AreaTableEntry const *pArea); + bool HandleOnItemClick(Item *pItem); + bool HandleOnItemOpen(Item *pItem); + bool HandleOnGoClick(GameObject *pGameObject); + void HandleOnCreatureKill(Creature *pCreature); + void HandleEjectPasenger(WorldPacket &data); + void HandleEnterPlayerVehicle(WorldPacket &data); + private: + // private trade methods + void moveItems(Item* myItems[], Item* hisItems[]); + + // logging helper + void LogUnexpectedOpcode(WorldPacket *packet, const char * reason); + void LogUnprocessedTail(WorldPacket *packet); + + uint32 m_GUIDLow; // set loggined or recently logout player (while m_playerRecentlyLogout set) + Player *_player; + WorldSocket *m_Socket; + std::string m_Address; + + AccountTypes _security; + uint32 _accountId; + uint8 m_expansion; + + time_t _logoutTime; + bool m_inQueue; // session wait in auth.queue + bool m_playerLoading; // code processed in LoginPlayer + bool m_playerLogout; // code processed in LogoutPlayer + bool m_playerRecentlyLogout; + bool m_playerSave; + LocaleConstant m_sessionDbcLocale; + int m_sessionDbLocaleIndex; + uint32 m_latency; + AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES]; + uint32 m_Tutorials[8]; + bool m_TutorialsChanged; + AddonsList m_addonsList; + ACE_Based::LockedQueue _recvQueue; +}; +#endif +/// @} diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp new file mode 100644 index 00000000000..c07b369d0b9 --- /dev/null +++ b/src/server/game/Server/WorldSocket.cpp @@ -0,0 +1,1064 @@ +/* +* Copyright (C) 2005-2009 MaNGOS +* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "WorldSocket.h" +#include "Common.h" + +#include "Util.h" +#include "World.h" +#include "WorldPacket.h" +#include "SharedDefines.h" +#include "ByteBuffer.h" +#include "Opcodes.h" +#include "Database/DatabaseEnv.h" +#include "Auth/BigNumber.h" +#include "Auth/Sha1.h" +#include "WorldSession.h" +#include "WorldSocketMgr.h" +#include "Log.h" +#include "WorldLog.h" + +#if defined(__GNUC__) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +struct ServerPktHeader +{ + /** + * size is the length of the payload _plus_ the length of the opcode + */ + ServerPktHeader(uint32 size, uint16 cmd) : size(size) + { + uint8 headerIndex=0; + if (isLargePacket()) + { + sLog.outDebug("initializing large server to client packet. Size: %u, cmd: %u", size, cmd); + header[headerIndex++] = 0x80|(0xFF &(size>>16)); + } + header[headerIndex++] = 0xFF &(size>>8); + header[headerIndex++] = 0xFF &size; + + header[headerIndex++] = 0xFF & cmd; + header[headerIndex++] = 0xFF & (cmd>>8); + } + + uint8 getHeaderLength() + { + // cmd = 2 bytes, size= 2||3bytes + return 2+(isLargePacket()?3:2); + } + + bool isLargePacket() + { + return size > 0x7FFF; + } + + const uint32 size; + uint8 header[5]; +}; + +struct ClientPktHeader +{ + uint16 size; + uint32 cmd; +}; + +#if defined(__GNUC__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +WorldSocket::WorldSocket (void) : +WorldHandler(), +m_Session(0), +m_RecvWPct(0), +m_RecvPct(), +m_Header(sizeof (ClientPktHeader)), +m_OutBuffer(0), +m_OutBufferSize(65536), +m_OutActive(false), +m_Seed(static_cast (rand32())), +m_OverSpeedPings(0), +m_LastPingTime(ACE_Time_Value::zero) +{ + reference_counting_policy().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + msg_queue()->high_water_mark(8*1024*1024); + msg_queue()->low_water_mark(8*1024*1024); +} + +WorldSocket::~WorldSocket (void) +{ + if (m_RecvWPct) + delete m_RecvWPct; + + if (m_OutBuffer) + m_OutBuffer->release(); + + closing_ = true; + + peer().close(); +} + +bool WorldSocket::IsClosed (void) const +{ + return closing_; +} + +void WorldSocket::CloseSocket (void) +{ + { + ACE_GUARD (LockType, Guard, m_OutBufferLock); + + if (closing_) + return; + + closing_ = true; + peer().close_writer(); + } + + { + ACE_GUARD (LockType, Guard, m_SessionLock); + + m_Session = NULL; + } +} + +const std::string& WorldSocket::GetRemoteAddress (void) const +{ + return m_Address; +} + +int WorldSocket::SendPacket (const WorldPacket& pct) +{ + ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); + + if (closing_) + return -1; + + // Dump outgoing packet. + if (sWorldLog.LogWorld()) + { + sWorldLog.outTimestampLog ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", + (uint32) get_handle(), + pct.size(), + LookupOpcodeName (pct.GetOpcode()), + pct.GetOpcode()); + + uint32 p = 0; + while (p < pct.size()) + { + for (uint32 j = 0; j < 16 && p < pct.size(); j++) + sWorldLog.outLog("%.2X ", const_cast(pct)[p++]); + + sWorldLog.outLog("\n"); + } + sWorldLog.outLog("\n"); + } + + ServerPktHeader header(pct.size()+2, pct.GetOpcode()); + m_Crypt.EncryptSend ((uint8*)header.header, header.getHeaderLength()); + + if (m_OutBuffer->space() >= pct.size() + header.getHeaderLength() && msg_queue()->is_empty()) + { + // Put the packet on the buffer. + if (m_OutBuffer->copy((char*) header.header, header.getHeaderLength()) == -1) + ACE_ASSERT (false); + + if (!pct.empty()) + if (m_OutBuffer->copy((char*) pct.contents(), pct.size()) == -1) + ACE_ASSERT (false); + } + else + { + // Enqueue the packet. + ACE_Message_Block* mb; + + ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size() + header.getHeaderLength()), -1); + + mb->copy((char*) header.header, header.getHeaderLength()); + + if (!pct.empty()) + mb->copy((const char*)pct.contents(), pct.size()); + + if (msg_queue()->enqueue_tail(mb,(ACE_Time_Value*)&ACE_Time_Value::zero) == -1) + { + sLog.outError("WorldSocket::SendPacket enqueue_tail failed"); + mb->release(); + return -1; + } + } + + return 0; +} + +long WorldSocket::AddReference (void) +{ + return static_cast (add_reference()); +} + +long WorldSocket::RemoveReference (void) +{ + return static_cast (remove_reference()); +} + +int WorldSocket::open (void *a) +{ + ACE_UNUSED_ARG (a); + + // Prevent double call to this func. + if (m_OutBuffer) + return -1; + + // This will also prevent the socket from being Updated + // while we are initializing it. + m_OutActive = true; + + // Hook for the manager. + if (sWorldSocketMgr->OnSocketOpen(this) == -1) + return -1; + + // Allocate the buffer. + ACE_NEW_RETURN (m_OutBuffer, ACE_Message_Block (m_OutBufferSize), -1); + + // Store peer address. + ACE_INET_Addr remote_addr; + + if (peer().get_remote_addr(remote_addr) == -1) + { + sLog.outError ("WorldSocket::open: peer().get_remote_addr errno = %s", ACE_OS::strerror (errno)); + return -1; + } + + m_Address = remote_addr.get_host_addr(); + + // Send startup packet. + WorldPacket packet (SMSG_AUTH_CHALLENGE, 24); + packet << uint32(1); // 1...31 + packet << m_Seed; + + BigNumber seed1; + seed1.SetRand(16 * 8); + packet.append(seed1.AsByteArray(16), 16); // new encryption seeds + + BigNumber seed2; + seed2.SetRand(16 * 8); + packet.append(seed2.AsByteArray(16), 16); // new encryption seeds + + if (SendPacket(packet) == -1) + return -1; + + // Register with ACE Reactor + if (reactor()->register_handler(this, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK) == -1) + { + sLog.outError ("WorldSocket::open: unable to register client handler errno = %s", ACE_OS::strerror (errno)); + return -1; + } + + // reactor takes care of the socket from now on + remove_reference(); + + return 0; +} + +int WorldSocket::close (int) +{ + shutdown(); + + closing_ = true; + + remove_reference(); + + return 0; +} + +int WorldSocket::handle_input (ACE_HANDLE) +{ + if (closing_) + return -1; + + switch (handle_input_missing_data()) + { + case -1 : + { + if ((errno == EWOULDBLOCK) || + (errno == EAGAIN)) + { + return Update(); // interesting line ,isn't it ? + } + + DEBUG_LOG("WorldSocket::handle_input: Peer error closing connection errno = %s", ACE_OS::strerror (errno)); + + errno = ECONNRESET; + return -1; + } + case 0: + { + DEBUG_LOG("WorldSocket::handle_input: Peer has closed connection"); + + errno = ECONNRESET; + return -1; + } + case 1: + return 1; + default: + return Update(); // another interesting line ;) + } + + ACE_NOTREACHED(return -1); +} + +int WorldSocket::handle_output (ACE_HANDLE) +{ + ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); + + if (closing_) + return -1; + + size_t send_len = m_OutBuffer->length(); + + if (send_len == 0) + return handle_output_queue(Guard); + +#ifdef MSG_NOSIGNAL + ssize_t n = peer().send (m_OutBuffer->rd_ptr(), send_len, MSG_NOSIGNAL); +#else + ssize_t n = peer().send (m_OutBuffer->rd_ptr(), send_len); +#endif // MSG_NOSIGNAL + + if (n == 0) + return -1; + else if (n == -1) + { + if (errno == EWOULDBLOCK || errno == EAGAIN) + return schedule_wakeup_output (Guard); + + return -1; + } + else if (n < (ssize_t)send_len) //now n > 0 + { + m_OutBuffer->rd_ptr (static_cast (n)); + + // move the data to the base of the buffer + m_OutBuffer->crunch(); + + return schedule_wakeup_output (Guard); + } + else //now n == send_len + { + m_OutBuffer->reset(); + + return handle_output_queue (Guard); + } + + ACE_NOTREACHED (return 0); +} + +int WorldSocket::handle_output_queue (GuardType& g) +{ + if (msg_queue()->is_empty()) + return cancel_wakeup_output(g); + + ACE_Message_Block *mblk; + + if (msg_queue()->dequeue_head(mblk, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) + { + sLog.outError("WorldSocket::handle_output_queue dequeue_head"); + return -1; + } + + const size_t send_len = mblk->length(); + +#ifdef MSG_NOSIGNAL + ssize_t n = peer().send (mblk->rd_ptr(), send_len, MSG_NOSIGNAL); +#else + ssize_t n = peer().send (mblk->rd_ptr(), send_len); +#endif // MSG_NOSIGNAL + + if (n == 0) + { + mblk->release(); + + return -1; + } + else if (n == -1) + { + if (errno == EWOULDBLOCK || errno == EAGAIN) + { + msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero); + return schedule_wakeup_output (g); + } + + mblk->release(); + return -1; + } + else if (n < (ssize_t)send_len) //now n > 0 + { + mblk->rd_ptr(static_cast (n)); + + if (msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero) == -1) + { + sLog.outError("WorldSocket::handle_output_queue enqueue_head"); + mblk->release(); + return -1; + } + + return schedule_wakeup_output (g); + } + else //now n == send_len + { + mblk->release(); + + return msg_queue()->is_empty() ? cancel_wakeup_output(g) : ACE_Event_Handler::WRITE_MASK; + } + + ACE_NOTREACHED(return -1); +} + +int WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask) +{ + // Critical section + { + ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); + + closing_ = true; + + if (h == ACE_INVALID_HANDLE) + peer().close_writer(); + } + + // Critical section + { + ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); + + m_Session = NULL; + } + + return 0; +} + +int WorldSocket::Update (void) +{ + if (closing_) + return -1; + + if (m_OutActive || (m_OutBuffer->length() == 0 && msg_queue()->is_empty())) + return 0; + + int ret; + do + ret = handle_output (get_handle()); + while (ret > 0); + + return ret; +} + +int WorldSocket::handle_input_header (void) +{ + ACE_ASSERT (m_RecvWPct == NULL); + + ACE_ASSERT (m_Header.length() == sizeof(ClientPktHeader)); + + m_Crypt.DecryptRecv ((uint8*) m_Header.rd_ptr(), sizeof(ClientPktHeader)); + + ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr()); + + EndianConvertReverse(header.size); + EndianConvert(header.cmd); + + if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240)) + { + sLog.outError ("WorldSocket::handle_input_header: client sent malformed packet size = %d , cmd = %d", + header.size, header.cmd); + + errno = EINVAL; + return -1; + } + + header.size -= 4; + + ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1); + + if (header.size > 0) + { + m_RecvWPct->resize (header.size); + m_RecvPct.base ((char*) m_RecvWPct->contents(), m_RecvWPct->size()); + } + else + { + ACE_ASSERT(m_RecvPct.space() == 0); + } + + return 0; +} + +int WorldSocket::handle_input_payload (void) +{ + // set errno properly here on error !!! + // now have a header and payload + + ACE_ASSERT (m_RecvPct.space() == 0); + ACE_ASSERT (m_Header.space() == 0); + ACE_ASSERT (m_RecvWPct != NULL); + + const int ret = ProcessIncoming (m_RecvWPct); + + m_RecvPct.base (NULL, 0); + m_RecvPct.reset(); + m_RecvWPct = NULL; + + m_Header.reset(); + + if (ret == -1) + errno = EINVAL; + + return ret; +} + +int WorldSocket::handle_input_missing_data (void) +{ + char buf [4096]; + + ACE_Data_Block db (sizeof (buf), + ACE_Message_Block::MB_DATA, + buf, + 0, + 0, + ACE_Message_Block::DONT_DELETE, + 0); + + ACE_Message_Block message_block(&db, + ACE_Message_Block::DONT_DELETE, + 0); + + const size_t recv_size = message_block.space(); + + const ssize_t n = peer().recv (message_block.wr_ptr(), + recv_size); + + if (n <= 0) + return n; + + message_block.wr_ptr (n); + + while (message_block.length() > 0) + { + if (m_Header.space() > 0) + { + //need to receive the header + const size_t to_header = (message_block.length() > m_Header.space() ? m_Header.space() : message_block.length()); + m_Header.copy (message_block.rd_ptr(), to_header); + message_block.rd_ptr (to_header); + + if (m_Header.space() > 0) + { + // Couldn't receive the whole header this time. + ACE_ASSERT (message_block.length() == 0); + errno = EWOULDBLOCK; + return -1; + } + + // We just received nice new header + if (handle_input_header() == -1) + { + ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); + return -1; + } + } + + // Its possible on some error situations that this happens + // for example on closing when epoll receives more chunked data and stuff + // hope this is not hack ,as proper m_RecvWPct is asserted around + if (!m_RecvWPct) + { + sLog.outError ("Forcing close on input m_RecvWPct = NULL"); + errno = EINVAL; + return -1; + } + + // We have full read header, now check the data payload + if (m_RecvPct.space() > 0) + { + //need more data in the payload + const size_t to_data = (message_block.length() > m_RecvPct.space() ? m_RecvPct.space() : message_block.length()); + m_RecvPct.copy (message_block.rd_ptr(), to_data); + message_block.rd_ptr (to_data); + + if (m_RecvPct.space() > 0) + { + // Couldn't receive the whole data this time. + ACE_ASSERT (message_block.length() == 0); + errno = EWOULDBLOCK; + return -1; + } + } + + //just received fresh new payload + if (handle_input_payload() == -1) + { + ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); + return -1; + } + } + + return n == recv_size ? 1 : 2; +} + +int WorldSocket::cancel_wakeup_output (GuardType& g) +{ + if (!m_OutActive) + return 0; + + m_OutActive = false; + + g.release(); + + if (reactor()->cancel_wakeup + (this, ACE_Event_Handler::WRITE_MASK) == -1) + { + // would be good to store errno from reactor with errno guard + sLog.outError ("WorldSocket::cancel_wakeup_output"); + return -1; + } + + return 0; +} + +int WorldSocket::schedule_wakeup_output (GuardType& g) +{ + if (m_OutActive) + return 0; + + m_OutActive = true; + + g.release(); + + if (reactor()->schedule_wakeup + (this, ACE_Event_Handler::WRITE_MASK) == -1) + { + sLog.outError ("WorldSocket::schedule_wakeup_output"); + return -1; + } + + return 0; +} + +int WorldSocket::ProcessIncoming (WorldPacket* new_pct) +{ + ACE_ASSERT (new_pct); + + // manage memory ;) + ACE_Auto_Ptr aptr (new_pct); + + const ACE_UINT16 opcode = new_pct->GetOpcode(); + + if (closing_) + return -1; + + // Dump received packet. + if (sWorldLog.LogWorld()) + { + sWorldLog.outTimestampLog ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", + (uint32) get_handle(), + new_pct->size(), + LookupOpcodeName (new_pct->GetOpcode()), + new_pct->GetOpcode()); + + uint32 p = 0; + while (p < new_pct->size()) + { + for (uint32 j = 0; j < 16 && p < new_pct->size(); j++) + sWorldLog.outLog ("%.2X ", (*new_pct)[p++]); + + sWorldLog.outLog ("\n"); + } + sWorldLog.outLog ("\n"); + } + + try { + switch(opcode) + { + case CMSG_PING: + return HandlePing (*new_pct); + case CMSG_AUTH_SESSION: + if (m_Session) + { + sLog.outError ("WorldSocket::ProcessIncoming: Player send CMSG_AUTH_SESSION again"); + return -1; + } + + return HandleAuthSession (*new_pct); + case CMSG_KEEP_ALIVE: + DEBUG_LOG ("CMSG_KEEP_ALIVE ,size: %d", new_pct->size()); + + return 0; + default: + { + ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); + + if (m_Session != NULL) + { + // Our Idle timer will reset on any non PING opcodes. + // Catches people idling on the login screen and any lingering ingame connections. + m_Session->ResetTimeOutTime(); + + // OK ,give the packet to WorldSession + aptr.release(); + // WARNINIG here we call it with locks held. + // Its possible to cause deadlock if QueuePacket calls back + m_Session->QueuePacket (new_pct); + return 0; + } + else + { + sLog.outError ("WorldSocket::ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); + return -1; + } + } + } + } + catch(ByteBufferException &) + { + sLog.outError("WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i. Disconnected client.", + opcode, GetRemoteAddress().c_str(), m_Session?m_Session->GetAccountId():-1); + if (sLog.IsOutDebug()) + { + sLog.outDebug("Dumping error causing packet:"); + new_pct->hexlike(); + } + + return -1; + } + + ACE_NOTREACHED (return 0); +} + +int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) +{ + // NOTE: ATM the socket is singlethread, have this in mind ... + uint8 digest[20]; + uint32 clientSeed; + uint32 unk2, unk3; + uint64 unk4; + uint32 BuiltNumberClient; + uint32 id, security; + //uint8 expansion = 0; + LocaleConstant locale; + std::string account; + Sha1Hash sha1; + BigNumber v, s, g, N; + WorldPacket packet, SendAddonPacked; + + BigNumber K; + + if (sWorld.IsClosed()) + { + packet.Initialize(SMSG_AUTH_RESPONSE, 1); + packet << uint8(AUTH_REJECT); + SendPacket (packet); + + sLog.outError ("WorldSocket::HandleAuthSession: World closed, denying client (%s).", m_Session->GetRemoteAddress().c_str()); + return -1; + } + + // Read the content of the packet + recvPacket >> BuiltNumberClient; // for now no use + recvPacket >> unk2; + recvPacket >> account; + recvPacket >> unk3; + recvPacket >> clientSeed; + recvPacket >> unk4; + recvPacket.read (digest, 20); + + DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u", + BuiltNumberClient, + unk2, + account.c_str(), + unk3, + clientSeed); + + // Get the account information from the realmd database + std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below + LoginDatabase.escape_string (safe_account); + // No SQL injection, username escaped. + + QueryResult_AutoPtr result = + LoginDatabase.PQuery ("SELECT " + "id, " //0 + "sessionkey, " //1 + "last_ip, " //2 + "locked, " //3 + "v, " //4 + "s, " //5 + "expansion, " //6 + "mutetime, " //7 + "locale " //8 + "FROM account " + "WHERE username = '%s'", + safe_account.c_str()); + + // Stop if the account is not found + if (!result) + { + packet.Initialize (SMSG_AUTH_RESPONSE, 1); + packet << uint8 (AUTH_UNKNOWN_ACCOUNT); + + SendPacket (packet); + + sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); + return -1; + } + + Field* fields = result->Fetch(); + + uint8 expansion = fields[6].GetUInt8(); + uint32 world_expansion = sWorld.getConfig(CONFIG_EXPANSION); + if (expansion > world_expansion) + expansion = world_expansion; + //expansion = ((sWorld.getConfig(CONFIG_EXPANSION) > fields[6].GetUInt8()) ? fields[6].GetUInt8() : sWorld.getConfig(CONFIG_EXPANSION)); + + N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); + g.SetDword (7); + + v.SetHexStr(fields[4].GetString()); + s.SetHexStr (fields[5].GetString()); + + const char* sStr = s.AsHexStr(); //Must be freed by OPENSSL_free() + const char* vStr = v.AsHexStr(); //Must be freed by OPENSSL_free() + + DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s", + sStr, + vStr); + + OPENSSL_free ((void*) sStr); + OPENSSL_free ((void*) vStr); + + ///- Re-check ip locking (same check as in realmd). + if (fields[3].GetUInt8() == 1) // if ip is locked + { + if (strcmp (fields[2].GetString(), GetRemoteAddress().c_str())) + { + packet.Initialize (SMSG_AUTH_RESPONSE, 1); + packet << uint8 (AUTH_FAILED); + SendPacket (packet); + + sLog.outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); + return -1; + } + } + + id = fields[0].GetUInt32(); + /* + if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB + security = SEC_ADMINISTRATOR; + */ + + K.SetHexStr (fields[1].GetString()); + + time_t mutetime = time_t (fields[7].GetUInt64()); + + locale = LocaleConstant (fields[8].GetUInt8()); + if (locale >= MAX_LOCALE) + locale = LOCALE_enUS; + + // Checks gmlevel per Realm + result = + LoginDatabase.PQuery ("SELECT " + "RealmID, " //0 + "gmlevel " //1 + "FROM account_access " + "WHERE id = '%d'" + " AND (RealmID = '%d'" + " OR RealmID = '-1')", + id, realmID); + if (!result) + security = 0; + else + { + fields = result->Fetch(); + security = fields[1].GetInt32(); + } + + // Re-check account ban (same check as in realmd) + QueryResult_AutoPtr banresult = + LoginDatabase.PQuery ("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 " + "UNION " + "SELECT 1 FROM ip_banned WHERE ip = '%s'", + id, GetRemoteAddress().c_str()); + + if (banresult) // if account banned + { + packet.Initialize (SMSG_AUTH_RESPONSE, 1); + packet << uint8 (AUTH_BANNED); + SendPacket (packet); + + sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); + return -1; + } + + // Check locked state for server + sWorld.UpdateAllowedSecurity(); + AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); + sLog.outDebug("Allowed Level: %u Player Level %u", allowedAccountType, AccountTypes(security)); + if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType) + { + WorldPacket Packet (SMSG_AUTH_RESPONSE, 1); + Packet << uint8 (AUTH_UNAVAILABLE); + + SendPacket (packet); + + sLog.outDetail ("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough"); + return -1; + } + + // Check that Key and account name are the same on client and server + Sha1Hash sha; + + uint32 t = 0; + uint32 seed = m_Seed; + + sha.UpdateData (account); + sha.UpdateData ((uint8 *) & t, 4); + sha.UpdateData ((uint8 *) & clientSeed, 4); + sha.UpdateData ((uint8 *) & seed, 4); + sha.UpdateBigNumbers (&K, NULL); + sha.Finalize(); + + if (memcmp (sha.GetDigest(), digest, 20)) + { + packet.Initialize (SMSG_AUTH_RESPONSE, 1); + packet << uint8 (AUTH_FAILED); + + SendPacket (packet); + + sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); + return -1; + } + + std::string address = GetRemoteAddress(); + + DEBUG_LOG ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", + account.c_str(), + address.c_str()); + + // Update the last_ip in the database + // No SQL injection, username escaped. + LoginDatabase.escape_string (address); + + LoginDatabase.PExecute ("UPDATE account " + "SET last_ip = '%s' " + "WHERE username = '%s'", + address.c_str(), + safe_account.c_str()); + + // NOTE ATM the socket is single-threaded, have this in mind ... + ACE_NEW_RETURN (m_Session, WorldSession (id, this, AccountTypes(security), expansion, mutetime, locale), -1); + + m_Crypt.Init(&K); + + m_Session->LoadGlobalAccountData(); + m_Session->LoadTutorialsData(); + m_Session->ReadAddonsInfo(recvPacket); + + // Sleep this Network thread for + uint32 sleepTime = sWorld.getConfig(CONFIG_SESSION_ADD_DELAY); + ACE_OS::sleep (ACE_Time_Value (0, sleepTime)); + + sWorld.AddSession (m_Session); + + return 0; +} + +int WorldSocket::HandlePing (WorldPacket& recvPacket) +{ + uint32 ping; + uint32 latency; + + // Get the ping packet content + recvPacket >> ping; + recvPacket >> latency; + + if (m_LastPingTime == ACE_Time_Value::zero) + m_LastPingTime = ACE_OS::gettimeofday(); // for 1st ping + else + { + ACE_Time_Value cur_time = ACE_OS::gettimeofday(); + ACE_Time_Value diff_time (cur_time); + diff_time -= m_LastPingTime; + m_LastPingTime = cur_time; + + if (diff_time < ACE_Time_Value (27)) + { + ++m_OverSpeedPings; + + uint32 max_count = sWorld.getConfig (CONFIG_MAX_OVERSPEED_PINGS); + + if (max_count && m_OverSpeedPings > max_count) + { + ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); + + if (m_Session && m_Session->GetSecurity() == SEC_PLAYER) + { + sLog.outError ("WorldSocket::HandlePing: Player kicked for " + "over-speed pings address = %s", + GetRemoteAddress().c_str()); + + return -1; + } + } + } + else + m_OverSpeedPings = 0; + } + + // critical section + { + ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); + + if (m_Session) + m_Session->SetLatency (latency); + else + { + sLog.outError ("WorldSocket::HandlePing: peer sent CMSG_PING, " + "but is not authenticated or got recently kicked," + " address = %s", + GetRemoteAddress().c_str()); + return -1; + } + } + + WorldPacket packet (SMSG_PONG, 4); + packet << ping; + return SendPacket (packet); +} diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h new file mode 100644 index 00000000000..70654274215 --- /dev/null +++ b/src/server/game/Server/WorldSocket.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \addtogroup u2w User to World Communication + * @{ + * \file WorldSocket.h + * \author Derex + */ + +#ifndef _WORLDSOCKET_H +#define _WORLDSOCKET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "Common.h" +#include "Auth/AuthCrypt.h" + +class ACE_Message_Block; +class WorldPacket; +class WorldSession; + +/// Handler that can communicate over stream sockets. +typedef ACE_Svc_Handler WorldHandler; + +/** + * WorldSocket. + * + * This class is responsible for the communication with + * remote clients. + * Most methods return -1 on failure. + * The class uses reference counting. + * + * For output the class uses one buffer (64K usually) and + * a queue where it stores packet if there is no place on + * the queue. The reason this is done, is because the server + * does really a lot of small-size writes to it, and it doesn't + * scale well to allocate memory for every. When something is + * written to the output buffer the socket is not immediately + * activated for output (again for the same reason), there + * is 10ms celling (thats why there is Update() method). + * This concept is similar to TCP_CORK, but TCP_CORK + * uses 200ms celling. As result overhead generated by + * sending packets from "producer" threads is minimal, + * and doing a lot of writes with small size is tolerated. + * + * The calls to Update() method are managed by WorldSocketMgr + * and ReactorRunnable. + * + * For input ,the class uses one 1024 bytes buffer on stack + * to which it does recv() calls. And then received data is + * distributed where its needed. 1024 matches pretty well the + * traffic generated by client for now. + * + * The input/output do speculative reads/writes (AKA it tryes + * to read all data available in the kernel buffer or tryes to + * write everything available in userspace buffer), + * which is ok for using with Level and Edge Triggered IO + * notification. + * + */ +class WorldSocket : protected WorldHandler +{ + public: + /// Declare some friends + friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >; + friend class WorldSocketMgr; + friend class ReactorRunnable; + + /// Declare the acceptor for this class + typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor; + + /// Mutex type used for various synchronizations. + typedef ACE_Thread_Mutex LockType; + typedef ACE_Guard GuardType; + + /// Check if socket is closed. + bool IsClosed (void) const; + + /// Close the socket. + void CloseSocket (void); + + /// Get address of connected peer. + const std::string& GetRemoteAddress (void) const; + + /// Send A packet on the socket, this function is reentrant. + /// @param pct packet to send + /// @return -1 of failure + int SendPacket (const WorldPacket& pct); + + /// Add reference to this object. + long AddReference (void); + + /// Remove reference to this object. + long RemoveReference (void); + + protected: + /// things called by ACE framework. + WorldSocket (void); + virtual ~WorldSocket (void); + + /// Called on open ,the void* is the acceptor. + virtual int open (void *); + + /// Called on failures inside of the acceptor, don't call from your code. + virtual int close (int); + + /// Called when we can read from the socket. + virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE); + + /// Called when the socket can write. + virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE); + + /// Called when connection is closed or error happens. + virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); + + /// Called by WorldSocketMgr/ReactorRunnable. + int Update (void); + + private: + /// Helper functions for processing incoming data. + int handle_input_header (void); + int handle_input_payload (void); + int handle_input_missing_data (void); + + /// Help functions to mark/unmark the socket for output. + /// @param g the guard is for m_OutBufferLock, the function will release it + int cancel_wakeup_output (GuardType& g); + int schedule_wakeup_output (GuardType& g); + + /// Drain the queue if its not empty. + int handle_output_queue (GuardType& g); + + /// process one incoming packet. + /// @param new_pct received packet ,note that you need to delete it. + int ProcessIncoming (WorldPacket* new_pct); + + /// Called by ProcessIncoming() on CMSG_AUTH_SESSION. + int HandleAuthSession (WorldPacket& recvPacket); + + /// Called by ProcessIncoming() on CMSG_PING. + int HandlePing (WorldPacket& recvPacket); + + private: + /// Time in which the last ping was received + ACE_Time_Value m_LastPingTime; + + /// Keep track of over-speed pings ,to prevent ping flood. + uint32 m_OverSpeedPings; + + /// Address of the remote peer + std::string m_Address; + + /// Class used for managing encryption of the headers + AuthCrypt m_Crypt; + + /// Mutex lock to protect m_Session + LockType m_SessionLock; + + /// Session to which received packets are routed + WorldSession* m_Session; + + /// here are stored the fragments of the received data + WorldPacket* m_RecvWPct; + + /// This block actually refers to m_RecvWPct contents, + /// which allows easy and safe writing to it. + /// It wont free memory when its deleted. m_RecvWPct takes care of freeing. + ACE_Message_Block m_RecvPct; + + /// Fragment of the received header. + ACE_Message_Block m_Header; + + /// Mutex for protecting output related data. + LockType m_OutBufferLock; + + /// Buffer used for writing output. + ACE_Message_Block *m_OutBuffer; + + /// Size of the m_OutBuffer. + size_t m_OutBufferSize; + + /// True if the socket is registered with the reactor for output + bool m_OutActive; + + uint32 m_Seed; + +}; + +#endif /* _WORLDSOCKET_H */ + +/// @} + diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp new file mode 100644 index 00000000000..c23d08e6f78 --- /dev/null +++ b/src/server/game/Server/WorldSocketMgr.cpp @@ -0,0 +1,369 @@ +/* +* Copyright (C) 2005-2008,2007 MaNGOS +* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** \file WorldSocketMgr.cpp +* \ingroup u2w +* \author Derex +*/ + +#include "WorldSocketMgr.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Log.h" +#include "Common.h" +#include "Config/ConfigEnv.h" +#include "Database/DatabaseEnv.h" +#include "WorldSocket.h" + +/** +* This is a helper class to WorldSocketMgr ,that manages +* network threads, and assigning connections from acceptor thread +* to other network threads +*/ +class ReactorRunnable : protected ACE_Task_Base +{ + public: + + ReactorRunnable() : + m_ThreadId(-1), + m_Connections(0), + m_Reactor(0) + { + ACE_Reactor_Impl* imp = 0; + + #if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL) + + imp = new ACE_Dev_Poll_Reactor(); + + imp->max_notify_iterations (128); + imp->restart (1); + + #else + + imp = new ACE_TP_Reactor(); + imp->max_notify_iterations (128); + + #endif + + m_Reactor = new ACE_Reactor (imp, 1); + } + + virtual ~ReactorRunnable() + { + Stop(); + Wait(); + + if (m_Reactor) + delete m_Reactor; + } + + void Stop() + { + m_Reactor->end_reactor_event_loop(); + } + + int Start() + { + if (m_ThreadId != -1) + return -1; + + return (m_ThreadId = activate()); + } + + void Wait() { ACE_Task_Base::wait(); } + + long Connections() + { + return static_cast (m_Connections.value()); + } + + int AddSocket (WorldSocket* sock) + { + ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, m_NewSockets_Lock, -1); + + ++m_Connections; + sock->AddReference(); + sock->reactor (m_Reactor); + m_NewSockets.insert (sock); + + return 0; + } + + ACE_Reactor* GetReactor() + { + return m_Reactor; + } + + protected: + + void AddNewSockets() + { + ACE_GUARD (ACE_Thread_Mutex, Guard, m_NewSockets_Lock); + + if (m_NewSockets.empty()) + return; + + for (SocketSet::const_iterator i = m_NewSockets.begin(); i != m_NewSockets.end(); ++i) + { + WorldSocket* sock = (*i); + + if (sock->IsClosed()) + { + sock->RemoveReference(); + --m_Connections; + } + else + m_Sockets.insert (sock); + } + + m_NewSockets.clear(); + } + + virtual int svc() + { + DEBUG_LOG ("Network Thread Starting"); + + WorldDatabase.ThreadStart(); + + ACE_ASSERT (m_Reactor); + + SocketSet::iterator i, t; + + while (!m_Reactor->reactor_event_loop_done()) + { + // dont be too smart to move this outside the loop + // the run_reactor_event_loop will modify interval + ACE_Time_Value interval (0, 10000); + + if (m_Reactor->run_reactor_event_loop (interval) == -1) + break; + + AddNewSockets(); + + for (i = m_Sockets.begin(); i != m_Sockets.end();) + { + if ((*i)->Update() == -1) + { + t = i; + ++i; + (*t)->CloseSocket(); + (*t)->RemoveReference(); + --m_Connections; + m_Sockets.erase (t); + } + else + ++i; + } + } + + WorldDatabase.ThreadEnd(); + + DEBUG_LOG ("Network Thread Exitting"); + + return 0; + } + + private: + typedef ACE_Atomic_Op AtomicInt; + typedef std::set SocketSet; + + ACE_Reactor* m_Reactor; + AtomicInt m_Connections; + int m_ThreadId; + + SocketSet m_Sockets; + + SocketSet m_NewSockets; + ACE_Thread_Mutex m_NewSockets_Lock; +}; + +WorldSocketMgr::WorldSocketMgr() : + m_NetThreadsCount(0), + m_NetThreads(0), + m_SockOutKBuff(-1), + m_SockOutUBuff(65536), + m_UseNoDelay(true), + m_Acceptor (0) +{ +} + +WorldSocketMgr::~WorldSocketMgr() +{ + if (m_NetThreads) + delete [] m_NetThreads; + + if (m_Acceptor) + delete m_Acceptor; +} + +int +WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address) +{ + m_UseNoDelay = sConfig.GetBoolDefault ("Network.TcpNodelay", true); + + int num_threads = sConfig.GetIntDefault ("Network.Threads", 1); + + if (num_threads <= 0) + { + sLog.outError ("Network.Threads is wrong in your config file"); + return -1; + } + + m_NetThreadsCount = static_cast (num_threads + 1); + + m_NetThreads = new ReactorRunnable[m_NetThreadsCount]; + + sLog.outBasic ("Max allowed socket connections %d", ACE::max_handles()); + + // -1 means use default + m_SockOutKBuff = sConfig.GetIntDefault ("Network.OutKBuff", -1); + + m_SockOutUBuff = sConfig.GetIntDefault ("Network.OutUBuff", 65536); + + if (m_SockOutUBuff <= 0) + { + sLog.outError ("Network.OutUBuff is wrong in your config file"); + return -1; + } + + WorldSocket::Acceptor *acc = new WorldSocket::Acceptor; + m_Acceptor = acc; + + ACE_INET_Addr listen_addr (port, address); + + if (acc->open(listen_addr, m_NetThreads[0].GetReactor(), ACE_NONBLOCK) == -1) + { + sLog.outError ("Failed to open acceptor ,check if the port is free"); + return -1; + } + + for (size_t i = 0; i < m_NetThreadsCount; ++i) + m_NetThreads[i].Start(); + + return 0; +} + +int +WorldSocketMgr::StartNetwork (ACE_UINT16 port, const char* address) +{ + if (!sLog.IsOutDebug()) + ACE_Log_Msg::instance()->priority_mask (LM_ERROR, ACE_Log_Msg::PROCESS); + + if (StartReactiveIO(port, address) == -1) + return -1; + + return 0; +} + +void +WorldSocketMgr::StopNetwork() +{ + if (m_Acceptor) + { + WorldSocket::Acceptor* acc = dynamic_cast (m_Acceptor); + + if (acc) + acc->close(); + } + + if (m_NetThreadsCount != 0) + { + for (size_t i = 0; i < m_NetThreadsCount; ++i) + m_NetThreads[i].Stop(); + } + + Wait(); +} + +void +WorldSocketMgr::Wait() +{ + if (m_NetThreadsCount != 0) + { + for (size_t i = 0; i < m_NetThreadsCount; ++i) + m_NetThreads[i].Wait(); + } +} + +int +WorldSocketMgr::OnSocketOpen (WorldSocket* sock) +{ + // set some options here + if (m_SockOutKBuff >= 0) + { + if (sock->peer().set_option (SOL_SOCKET, + SO_SNDBUF, + (void*) & m_SockOutKBuff, + sizeof (int)) == -1 && errno != ENOTSUP) + { + sLog.outError ("WorldSocketMgr::OnSocketOpen set_option SO_SNDBUF"); + return -1; + } + } + + static const int ndoption = 1; + + // Set TCP_NODELAY. + if (m_UseNoDelay) + { + if (sock->peer().set_option (ACE_IPPROTO_TCP, + TCP_NODELAY, + (void*)&ndoption, + sizeof (int)) == -1) + { + sLog.outError ("WorldSocketMgr::OnSocketOpen: peer().set_option TCP_NODELAY errno = %s", ACE_OS::strerror (errno)); + return -1; + } + } + + sock->m_OutBufferSize = static_cast (m_SockOutUBuff); + + // we skip the Acceptor Thread + size_t min = 1; + + ACE_ASSERT (m_NetThreadsCount >= 1); + + for (size_t i = 1; i < m_NetThreadsCount; ++i) + if (m_NetThreads[i].Connections() < m_NetThreads[min].Connections()) + min = i; + + return m_NetThreads[min].AddSocket (sock); +} + +WorldSocketMgr* +WorldSocketMgr::Instance() +{ + return ACE_Singleton::instance(); +} + diff --git a/src/server/game/Server/WorldSocketMgr.h b/src/server/game/Server/WorldSocketMgr.h new file mode 100644 index 00000000000..11345304962 --- /dev/null +++ b/src/server/game/Server/WorldSocketMgr.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \addtogroup u2w User to World Communication + * @{ + * \file WorldSocketMgr.h + * \author Derex + */ + +#ifndef __WORLDSOCKETMGR_H +#define __WORLDSOCKETMGR_H + +#include +#include +#include + +class WorldSocket; +class ReactorRunnable; +class ACE_Event_Handler; + +/// Manages all sockets connected to peers and network threads +class WorldSocketMgr +{ +public: + friend class WorldSocket; + friend class ACE_Singleton; + + /// Start network, listen at address:port . + int StartNetwork (ACE_UINT16 port, const char* address); + + /// Stops all network threads, It will wait for all running threads . + void StopNetwork(); + + /// Wait untill all network threads have "joined" . + void Wait(); + + /// Make this class singleton . + static WorldSocketMgr* Instance(); + +private: + int OnSocketOpen(WorldSocket* sock); + + int StartReactiveIO(ACE_UINT16 port, const char* address); + +private: + WorldSocketMgr(); + virtual ~WorldSocketMgr(); + + ReactorRunnable* m_NetThreads; + size_t m_NetThreadsCount; + + int m_SockOutKBuff; + int m_SockOutUBuff; + bool m_UseNoDelay; + + ACE_Event_Handler* m_Acceptor; +}; + +#define sWorldSocketMgr WorldSocketMgr::Instance() + +#endif +/// @} + diff --git a/src/server/game/Skills/SkillHandler.cpp b/src/server/game/Skills/SkillHandler.cpp deleted file mode 100644 index 312065f9f13..00000000000 --- a/src/server/game/Skills/SkillHandler.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "Opcodes.h" -#include "Log.h" -#include "Player.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "ObjectAccessor.h" -#include "UpdateMask.h" - -void WorldSession::HandleLearnTalentOpcode(WorldPacket & recv_data) -{ - uint32 talent_id, requested_rank; - recv_data >> talent_id >> requested_rank; - - _player->LearnTalent(talent_id, requested_rank); - _player->SendTalentsInfoData(false); -} - -void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) -{ - sLog.outDebug("CMSG_LEARN_PREVIEW_TALENTS"); - - uint32 talentsCount; - recvPacket >> talentsCount; - - uint32 talentId, talentRank; - - for (uint32 i = 0; i < talentsCount; ++i) - { - recvPacket >> talentId >> talentRank; - - _player->LearnTalent(talentId, talentRank); - } - - _player->SendTalentsInfoData(false); -} - -void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket & recv_data) -{ - sLog.outDetail("MSG_TALENT_WIPE_CONFIRM"); - uint64 guid; - recv_data >> guid; - - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TRAINER); - if (!unit) - { - sLog.outDebug("WORLD: HandleTalentWipeConfirmOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); - return; - } - - // remove fake death - if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if (!(_player->resetTalents())) - { - WorldPacket data(MSG_TALENT_WIPE_CONFIRM, 8+4); //you have not any talent - data << uint64(0); - data << uint32(0); - SendPacket(&data); - return; - } - - _player->SendTalentsInfoData(false); - unit->CastSpell(_player, 14867, true); //spell: "Untalent Visual Effect" -} - -void WorldSession::HandleUnlearnSkillOpcode(WorldPacket & recv_data) -{ - uint32 skill_id; - recv_data >> skill_id; - GetPlayer()->SetSkill(skill_id, 0, 0, 0); -} - diff --git a/src/server/game/Spells/SpellHandler.cpp b/src/server/game/Spells/SpellHandler.cpp deleted file mode 100644 index b8a4a127824..00000000000 --- a/src/server/game/Spells/SpellHandler.cpp +++ /dev/null @@ -1,649 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "DBCStores.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Spell.h" -#include "Totem.h" -#include "TemporarySummon.h" -#include "SpellAuras.h" -#include "CreatureAI.h" -#include "ScriptMgr.h" - -void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) -{ - // TODO: add targets.read() check - Player* pUser = _player; - - // ignore for remote control state - if (pUser->m_mover != pUser) - return; - - uint8 bagIndex, slot; - uint8 unk_flags; // flags (if 0x02 - some additional data are received) - uint8 cast_count; // next cast if exists (single or not) - uint64 item_guid; - uint32 glyphIndex; // something to do with glyphs? - uint32 spellid; // casted spell id - - recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags; - - if (glyphIndex >= MAX_GLYPH_SLOT_INDEX) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - Item *pItem = pUser->GetUseableItemByPos(bagIndex, slot); - if (!pItem) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - if (pItem->GetGUID() != item_guid) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, unk_flags, (uint32)recvPacket.size()); - - ItemPrototype const *proto = pItem->GetProto(); - if (!proto) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL); - return; - } - - // some item classes can be used only in equipped state - if (proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL); - return; - } - - uint8 msg = pUser->CanUseItem(pItem); - if (msg != EQUIP_ERR_OK) - { - pUser->SendEquipError(msg, pItem, NULL); - return; - } - - // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) - if (proto->Class == ITEM_CLASS_CONSUMABLE && !(proto->Flags & ITEM_FLAGS_USEABLE_IN_ARENA) && pUser->InArena()) - { - pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL); - return; - } - - if (pUser->isInCombat()) - { - for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId)) - { - if (IsNonCombatSpell(spellInfo)) - { - pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT,pItem,NULL); - return; - } - } - } - } - - // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) - if (pItem->GetProto()->Bonding == BIND_WHEN_USE || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM) - { - if (!pItem->IsSoulBound()) - { - pItem->SetState(ITEM_CHANGED, pUser); - pItem->SetBinding(true); - } - } - - SpellCastTargets targets; - if (!targets.read(&recvPacket, pUser)) - return; - - targets.Update(pUser); - - if (!pItem->IsTargetValidForItemUse(targets.getUnitTarget())) - { - // free gray item after use fail - pUser->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); - - // send spell error - if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid)) - { - // for implicit area/coord target spells - if (!targets.getUnitTarget()) - Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_NO_VALID_TARGETS); - // for explicit target spells - else - Spell::SendCastResult(_player,spellInfo,cast_count,SPELL_FAILED_BAD_TARGETS); - } - return; - } - - //Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. - if (!sScriptMgr.ItemUse(pUser,pItem,targets)) - { - // no script or script not process request by self - pUser->CastItemUseSpell(pItem,targets,cast_count,glyphIndex); - } -} - -#define OPEN_CHEST 11437 -#define OPEN_SAFE 11535 -#define OPEN_CAGE 11792 -#define OPEN_BOOTY_CHEST 5107 -#define OPEN_STRONGBOX 8517 - -void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) -{ - sLog.outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i",(uint32)recvPacket.size()); - - Player* pUser = _player; - - // ignore for remote control state - if (pUser->m_mover != pUser) - return; - - uint8 bagIndex, slot; - - recvPacket >> bagIndex >> slot; - - sLog.outDetail("bagIndex: %u, slot: %u",bagIndex,slot); - - Item *pItem = pUser->GetItemByPos(bagIndex, slot); - if (!pItem) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } - - ItemPrototype const *proto = pItem->GetProto(); - if (!proto) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL); - return; - } - - if (!pUser->GetSession()->HandleOnItemOpen(pItem)) - return; - - // locked item - uint32 lockId = proto->LockID; - if (lockId) - { - LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); - - if (!lockInfo) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL); - sLog.outError("WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", pItem->GetGUIDLow(), lockId); - return; - } - - // required picklocking - if (lockInfo->Skill[1] || lockInfo->Skill[0]) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL); - return; - } - } - - if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))// wrapped? - { - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT entry, flags FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); - if (result) - { - Field *fields = result->Fetch(); - uint32 entry = fields[0].GetUInt32(); - uint32 flags = fields[1].GetUInt32(); - - pItem->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, 0); - pItem->SetEntry(entry); - pItem->SetUInt32Value(ITEM_FIELD_FLAGS, flags); - pItem->SetState(ITEM_CHANGED, pUser); - } - else - { - sLog.outError("Wrapped item %u don't have record in character_gifts table and will deleted", pItem->GetGUIDLow()); - pUser->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); - return; - } - CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); - } - else - pUser->SendLoot(pItem->GetGUID(),LOOT_CORPSE); -} - -void WorldSession::HandleGameObjectUseOpcode(WorldPacket & recv_data) -{ - uint64 guid; - - recv_data >> guid; - - sLog.outDebug("WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid)); - - // ignore for remote control state - if (_player->m_mover != _player) - return; - - GameObject *obj = GetPlayer()->GetMap()->GetGameObject(guid); - - if (!obj) - return; - - if (sScriptMgr.GOHello(_player, obj)) - return; - - obj->Use(_player); -} - -void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) -{ - uint64 guid; - recvPacket >> guid; - - sLog.outDebug("WORLD: Recvd CMSG_GAMEOBJ_REPORT_USE Message [in game guid: %u]", GUID_LOPART(guid)); - - // ignore for remote control state - if (_player->m_mover != _player) - return; - - GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); - if (!go) - return; - - if (!go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) - return; - - _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); -} - -void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) -{ - uint32 spellId; - uint8 cast_count, unk_flags; - recvPacket >> cast_count; - recvPacket >> spellId; - recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received) - - // ignore for remote control state (for player case) - Unit* mover = _player->m_mover; - if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) - { - recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet - return; - } - - sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", spellId, cast_count, unk_flags, (uint32)recvPacket.size()); - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); - - if (!spellInfo) - { - sLog.outError("WORLD: unknown spell id %u", spellId); - recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet - return; - } - - if (mover->GetTypeId() == TYPEID_PLAYER) - { - // not have spell in spellbook or spell passive and not casted by client - if (!mover->ToPlayer()->HasActiveSpell (spellId) || IsPassiveSpell(spellId)) - { - //cheater? kick? ban? - recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet - return; - } - } - else - { - // not have spell in spellbook or spell passive and not casted by client - if ((mover->GetTypeId() == TYPEID_UNIT && !mover->ToCreature()->HasSpell(spellId)) || IsPassiveSpell(spellId)) - { - //cheater? kick? ban? - recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet - return; - } - } - - // Client is resending autoshot cast opcode when other spell is casted during shoot rotation - // Skip it to prevent "interrupt" message - if (IsAutoRepeatRangedSpell(spellInfo) && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) - && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) - return; - - // can't use our own spells when we're in possession of another unit, - if (_player->isPossessing()) - return; - - // client provided targets - SpellCastTargets targets; - if (!targets.read(&recvPacket,mover)) - { - recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet - return; - } - - // some spell cast packet including more data (for projectiles?) - if (unk_flags & 0x02) - { - //recvPacket.read_skip(); // unk1, coords? - //recvPacket.read_skip(); // unk1, coords? - uint8 unk1; - recvPacket >> unk1; // >> 1 or 0 - if (unk1) - { - recvPacket.read_skip(); // >> MSG_MOVE_STOP - uint64 guid; // guid - unused - if (!recvPacket.readPackGUID(guid)) - return; - - MovementInfo movementInfo; - ReadMovementInfo(recvPacket, &movementInfo); - } - } - - // auto-selection buff level base at target level (in spellInfo) - if (targets.getUnitTarget()) - { - SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel()); - - // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message - if (actualSpellInfo) - spellInfo = actualSpellInfo; - } - - Spell *spell = new Spell(mover, spellInfo, false); - spell->m_cast_count = cast_count; // set count of casts - spell->prepare(&targets); -} - -void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) -{ - uint32 spellId; - - recvPacket.read_skip(); // counter, increments with every CANCEL packet, don't use for now - recvPacket >> spellId; - - if (_player->IsNonMeleeSpellCasted(false)) - _player->InterruptNonMeleeSpells(false,spellId,false); -} - -void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) -{ - uint32 spellId; - recvPacket >> spellId; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo) - return; - - // not allow remove non positive spells and spells with attr SPELL_ATTR_CANT_CANCEL - if (!IsPositiveSpell(spellId) || (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL)) - return; - - // channeled spell case (it currently casted then) - if (IsChanneledSpell(spellInfo)) - { - if (Spell* curSpell = _player->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - if (curSpell->m_spellInfo->Id == spellId) - _player->InterruptSpell(CURRENT_CHANNELED_SPELL); - return; - } - - // non channeled case - // maybe should only remove one buff when there are multiple? - _player->RemoveOwnedAura(spellId, 0, 0, AURA_REMOVE_BY_CANCEL); -} - -void WorldSession::HandlePetCancelAuraOpcode(WorldPacket& recvPacket) -{ - uint64 guid; - uint32 spellId; - - recvPacket >> guid; - recvPacket >> spellId; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo) - { - sLog.outError("WORLD: unknown PET spell id %u", spellId); - return; - } - - Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); - - if (!pet) - { - sLog.outError("Pet %u not exist.", uint32(GUID_LOPART(guid))); - return; - } - - if (pet != GetPlayer()->GetGuardianPet() && pet != GetPlayer()->GetCharm()) - { - sLog.outError("HandlePetCancelAura.Pet %u isn't pet of player %s", uint32(GUID_LOPART(guid)),GetPlayer()->GetName()); - return; - } - - if (!pet->isAlive()) - { - pet->SendPetActionFeedback(FEEDBACK_PET_DEAD); - return; - } - - pet->RemoveOwnedAura(spellId, 0, 0, AURA_REMOVE_BY_CANCEL); - - pet->AddCreatureSpellCooldown(spellId); -} - -void WorldSession::HandleCancelGrowthAuraOpcode(WorldPacket& /*recvPacket*/) -{ -} - -void WorldSession::HandleCancelAutoRepeatSpellOpcode(WorldPacket& /*recvPacket*/) -{ - // may be better send SMSG_CANCEL_AUTO_REPEAT? - // cancel and prepare for deleting - _player->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); -} - -void WorldSession::HandleCancelChanneling(WorldPacket & recv_data) -{ - recv_data.read_skip(); // spellid, not used - - // ignore for remote control state (for player case) - Unit* mover = _player->m_mover; - if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) - return; - - mover->InterruptSpell(CURRENT_CHANNELED_SPELL); -} - -void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket) -{ - // ignore for remote control state - if (_player->m_mover != _player) - return; - - uint8 slotId; - - recvPacket >> slotId; - - ++slotId; - if (slotId >= MAX_TOTEM_SLOT) - return; - - if (!_player->m_SummonSlot[slotId]) - return; - - Creature* totem = GetPlayer()->GetMap()->GetCreature(_player->m_SummonSlot[slotId]); - // Don't unsummon sentry totem - if (totem && totem->isTotem() && totem->GetEntry() != SENTRY_TOTEM_ENTRY) - totem->ToTotem()->UnSummon(); -} - -void WorldSession::HandleSelfResOpcode(WorldPacket & /*recv_data*/) -{ - sLog.outDebug("WORLD: CMSG_SELF_RES"); // empty opcode - - if (_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)); - if (spellInfo) - _player->CastSpell(_player,spellInfo,false,0); - - _player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); - } -} - -void WorldSession::HandleSpellClick(WorldPacket & recv_data) -{ - uint64 guid; - recv_data >> guid; - - // this will get something not in world. crash - Creature *unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); - - if (!unit) - return; - - // TODO: Unit::SetCharmedBy: 28782 is not in world but 0 is trying to charm it! -> crash - if (!unit->IsInWorld()) - { - sLog.outCrash("Spell click target %u is not in world!", unit->GetEntry()); - assert(false); - return; - } - - SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(unit->GetEntry()); - for (SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) - { - if (itr->second.IsFitToRequirements(_player, unit)) - { - Unit *caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_PLAYER) ? (Unit*)_player : (Unit*)unit; - Unit *target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_PLAYER) ? (Unit*)_player : (Unit*)unit; - uint64 origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? unit->GetOwnerGUID() : 0; - caster->CastSpell(target, itr->second.spellId, true, NULL, NULL, origCasterGUID); - } - } - - if (unit->IsVehicle()) - { - if (unit->CheckPlayerCondition(_player)) - _player->EnterVehicle(unit); - } - - unit->AI()->DoAction(EVENT_SPELLCLICK); -} - -void WorldSession::HandleMirrrorImageDataRequest(WorldPacket & recv_data) -{ - sLog.outDebug("WORLD: CMSG_GET_MIRRORIMAGE_DATA"); - uint64 guid; - recv_data >> guid; - - // Get unit for which data is needed by client - Unit *unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL); - if (!unit) - return; - - // Get creator of the unit - Unit *creator = ObjectAccessor::GetObjectInWorld(unit->GetCreatorGUID(),(Unit*)NULL); - if (!creator) - return; - - WorldPacket data(SMSG_MIRRORIMAGE_DATA, 68); - data << uint64(guid); - data << uint32(creator->GetDisplayId()); - if (creator->GetTypeId() == TYPEID_PLAYER) - { - Player * pCreator = creator->ToPlayer(); - data << uint8(pCreator->getRace()); - data << uint8(pCreator->getGender()); - data << uint8(pCreator->getClass()); - data << uint8(pCreator->GetByteValue(PLAYER_BYTES, 0)); // skin - data << uint8(pCreator->GetByteValue(PLAYER_BYTES, 1)); // face - data << uint8(pCreator->GetByteValue(PLAYER_BYTES, 2)); // hair - data << uint8(pCreator->GetByteValue(PLAYER_BYTES, 3)); // haircolor - data << uint8(pCreator->GetByteValue(PLAYER_BYTES_2, 0)); // facialhair - data << uint32(pCreator->GetGuildId()); // unk - - static const EquipmentSlots ItemSlots[] = - { - EQUIPMENT_SLOT_HEAD, - EQUIPMENT_SLOT_SHOULDERS, - EQUIPMENT_SLOT_BODY, - EQUIPMENT_SLOT_CHEST, - EQUIPMENT_SLOT_WAIST, - EQUIPMENT_SLOT_LEGS, - EQUIPMENT_SLOT_FEET, - EQUIPMENT_SLOT_WRISTS, - EQUIPMENT_SLOT_HANDS, - EQUIPMENT_SLOT_BACK, - EQUIPMENT_SLOT_TABARD, - EQUIPMENT_SLOT_END - }; - - // Display items in visible slots - for (EquipmentSlots const* itr = &ItemSlots[0]; *itr != EQUIPMENT_SLOT_END; ++itr) - { - if (*itr == EQUIPMENT_SLOT_HEAD && pCreator->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) - data << uint32(0); - else if (*itr == EQUIPMENT_SLOT_BACK && pCreator->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK)) - data << uint32(0); - else if (Item const *item = pCreator->GetItemByPos(INVENTORY_SLOT_BAG_0, *itr)) - data << uint32(item->GetProto()->DisplayInfoID); - else - data << uint32(0); - } - } - else - { - // Skip player data for creatures - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - } - - SendPacket(&data); -} diff --git a/src/server/game/World/WorldLog.cpp b/src/server/game/World/WorldLog.cpp deleted file mode 100644 index 7c6c4020336..00000000000 --- a/src/server/game/World/WorldLog.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup u2w -*/ - -#include "WorldLog.h" -#include "Policies/SingletonImp.h" -#include "Config/ConfigEnv.h" -#include "Log.h" - -#define CLASS_LOCK Trinity::ClassLevelLockable -INSTANTIATE_SINGLETON_2(WorldLog, CLASS_LOCK); -INSTANTIATE_CLASS_MUTEX(WorldLog, ACE_Thread_Mutex); - -WorldLog::WorldLog() : i_file(NULL) -{ - Initialize(); -} - -WorldLog::~WorldLog() -{ - if (i_file != NULL) - fclose(i_file); - i_file = NULL; -} - -/// Open the log file (if specified so in the configuration file) -void WorldLog::Initialize() -{ - std::string logsDir = sConfig.GetStringDefault("LogsDir",""); - - if (!logsDir.empty()) - { - if ((logsDir.at(logsDir.length()-1) != '/') && (logsDir.at(logsDir.length()-1) != '\\')) - logsDir.append("/"); - } - - std::string logname = sConfig.GetStringDefault("WorldLogFile", ""); - if (!logname.empty()) - { - i_file = fopen((logsDir+logname).c_str(), "w"); - } - - m_dbWorld = sConfig.GetBoolDefault("LogDB.World", false); // can be VERY heavy if enabled -} - -void WorldLog::outTimestampLog(char const *fmt, ...) -{ - if (LogWorld()) - { - Guard guard(*this); - ASSERT(i_file); - - Log::outTimestamp(i_file); - va_list args; - va_start(args, fmt); - vfprintf(i_file, fmt, args); - //fprintf(i_file, "\n"); - va_end(args); - - fflush(i_file); - } - - if (sLog.GetLogDB() && m_dbWorld) - { - va_list ap2; - va_start(ap2, fmt); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); - sLog.outDB(LOG_TYPE_WORLD, nnew_str); - va_end(ap2); - } -} - -void WorldLog::outLog(char const *fmt, ...) -{ - if (LogWorld()) - { - Guard guard(*this); - ASSERT(i_file); - - va_list args; - va_start(args, fmt); - vfprintf(i_file, fmt, args); - //fprintf(i_file, "\n"); - va_end(args); - - fflush(i_file); - } - - if (sLog.GetLogDB() && m_dbWorld) - { - va_list ap2; - va_start(ap2, fmt); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); - sLog.outDB(LOG_TYPE_WORLD, nnew_str); - va_end(ap2); - } -} - -#define sWorldLog WorldLog::Instance() - diff --git a/src/server/game/World/WorldLog.h b/src/server/game/World/WorldLog.h deleted file mode 100644 index 4ee9bb178ec..00000000000 --- a/src/server/game/World/WorldLog.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup u2w -/// @{ -/// \file - -#ifndef TRINITY_WORLDLOG_H -#define TRINITY_WORLDLOG_H - -#include "Common.h" -#include "Policies/Singleton.h" -#include "Errors.h" - -#include - -/// %Log packets to a file -class WorldLog : public Trinity::Singleton > -{ - friend class Trinity::OperatorNew; - WorldLog(); - WorldLog(const WorldLog &); - WorldLog& operator=(const WorldLog &); - typedef Trinity::ClassLevelLockable::Lock Guard; - - /// Close the file in destructor - ~WorldLog(); - - public: - void Initialize(); - /// Is the world logger active? - bool LogWorld(void) const { return (i_file != NULL); } - /// %Log to the file - void outLog(char const *fmt, ...); - void outTimestampLog(char const *fmt, ...); - - private: - FILE *i_file; - - bool m_dbWorld; -}; - -#define sWorldLog WorldLog::Instance() -#endif -/// @} - diff --git a/src/server/game/World/WorldSession.cpp b/src/server/game/World/WorldSession.cpp deleted file mode 100644 index bc737717840..00000000000 --- a/src/server/game/World/WorldSession.cpp +++ /dev/null @@ -1,959 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup u2w -*/ - -#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "Log.h" -#include "Opcodes.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Player.h" -#include "Vehicle.h" -#include "ObjectMgr.h" -#include "Group.h" -#include "Guild.h" -#include "World.h" -#include "ObjectAccessor.h" -#include "BattleGroundMgr.h" -#include "OutdoorPvPMgr.h" -#include "MapManager.h" -#include "SocialMgr.h" -#include "zlib/zlib.h" -#include "ScriptMgr.h" -#include "LFGMgr.h" - -/// WorldSession constructor -WorldSession::WorldSession(uint32 id, WorldSocket *sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale) : -LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time), -_player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_expansion(expansion), -m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)), -_logoutTime(0), m_inQueue(false), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_playerSave(false), -m_latency(0), m_TutorialsChanged(false), m_timeOutTime(0) -{ - if (sock) - { - m_Address = sock->GetRemoteAddress (); - sock->AddReference (); - ResetTimeOutTime(); - LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); - } -} - -/// WorldSession destructor -WorldSession::~WorldSession() -{ - ///- unload player if not unloaded - if (_player) - LogoutPlayer (true); - - /// - If have unclosed socket, close it - if (m_Socket) - { - m_Socket->CloseSocket (); - m_Socket->RemoveReference (); - m_Socket = NULL; - } - - ///- empty incoming packet queue - WorldPacket* packet; - while (_recvQueue.next(packet)) - delete packet; - - LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); - CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = %u;", GetAccountId()); -} - -void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const -{ - sLog.outError("Client (account %u) send packet %s (%u) with size " SIZEFMTD " but expected %u (attempt crash server?), skipped", - GetAccountId(),LookupOpcodeName(packet.GetOpcode()),packet.GetOpcode(),packet.size(),size); -} - -/// Get the player name -char const* WorldSession::GetPlayerName() const -{ - return GetPlayer() ? GetPlayer()->GetName() : ""; -} - -/// Send a packet to the client -void WorldSession::SendPacket(WorldPacket const* packet) -{ - if (!m_Socket) - return; - - #ifdef TRINITY_DEBUG - - // Code for network use statistic - static uint64 sendPacketCount = 0; - static uint64 sendPacketBytes = 0; - - static time_t firstTime = time(NULL); - static time_t lastTime = firstTime; // next 60 secs start time - - static uint64 sendLastPacketCount = 0; - static uint64 sendLastPacketBytes = 0; - - time_t cur_time = time(NULL); - - if ((cur_time - lastTime) < 60) - { - sendPacketCount+=1; - sendPacketBytes+=packet->size(); - - sendLastPacketCount+=1; - sendLastPacketBytes+=packet->size(); - } - else - { - uint64 minTime = uint64(cur_time - lastTime); - uint64 fullTime = uint64(lastTime - firstTime); - sLog.outDetail("Send all time packets count: " UI64FMTD " bytes: " UI64FMTD " avr.count/sec: %f avr.bytes/sec: %f time: %u",sendPacketCount,sendPacketBytes,float(sendPacketCount)/fullTime,float(sendPacketBytes)/fullTime,uint32(fullTime)); - sLog.outDetail("Send last min packets count: " UI64FMTD " bytes: " UI64FMTD " avr.count/sec: %f avr.bytes/sec: %f",sendLastPacketCount,sendLastPacketBytes,float(sendLastPacketCount)/minTime,float(sendLastPacketBytes)/minTime); - - lastTime = cur_time; - sendLastPacketCount = 1; - sendLastPacketBytes = packet->wpos(); // wpos is real written size - } - - #endif // !TRINITY_DEBUG - - if (m_Socket->SendPacket (*packet) == -1) - m_Socket->CloseSocket (); -} - -/// Add an incoming packet to the queue -void WorldSession::QueuePacket(WorldPacket* new_packet) -{ - _recvQueue.add(new_packet); -} - -/// Logging helper for unexpected opcodes -void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char *reason) -{ - sLog.outError("SESSION: received unexpected opcode %s (0x%.4X) %s", - LookupOpcodeName(packet->GetOpcode()), - packet->GetOpcode(), - reason); -} - -/// Logging helper for unexpected opcodes -void WorldSession::LogUnprocessedTail(WorldPacket *packet) -{ - sLog.outError("SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", - LookupOpcodeName(packet->GetOpcode()), - packet->GetOpcode(), - packet->rpos(),packet->wpos()); - - packet->print_storage(); -} - -/// Update the WorldSession (triggered by World update) -bool WorldSession::Update(uint32 diff) -{ - /// Update Timeout timer. - UpdateTimeOutTime(diff); - - ///- Before we process anything: - /// If necessary, kick the player from the character select screen - if (IsConnectionIdle()) - m_Socket->CloseSocket(); - - ///- Retrieve packets from the receive queue and call the appropriate handlers - /// not proccess packets if socket already closed - WorldPacket* packet; - while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet)) - { - /*#if 1 - sLog.outError("MOEP: %s (0x%.4X)", - LookupOpcodeName(packet->GetOpcode()), - packet->GetOpcode()); - #endif*/ - - if (packet->GetOpcode() >= NUM_MSG_TYPES) - { - sLog.outError("SESSION: received non-existed opcode %s (0x%.4X)", - LookupOpcodeName(packet->GetOpcode()), - packet->GetOpcode()); - } - else - { - OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; - try - { - switch (opHandle.status) - { - case STATUS_LOGGEDIN: - if (!_player) - { - // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets - if (!m_playerRecentlyLogout) - LogUnexpectedOpcode(packet, "the player has not logged in yet"); - } - else if (_player->IsInWorld()) - { - (this->*opHandle.handler)(*packet); - if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) - LogUnprocessedTail(packet); - } - // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer - break; - case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT: - if (!_player && !m_playerRecentlyLogout) - { - LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout"); - } - else - { - // not expected _player or must checked in packet hanlder - (this->*opHandle.handler)(*packet); - if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) - LogUnprocessedTail(packet); - } - break; - case STATUS_TRANSFER: - if (!_player) - LogUnexpectedOpcode(packet, "the player has not logged in yet"); - else if (_player->IsInWorld()) - LogUnexpectedOpcode(packet, "the player is still in world"); - else - { - (this->*opHandle.handler)(*packet); - if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) - LogUnprocessedTail(packet); - } - break; - case STATUS_AUTHED: - // prevent cheating with skip queue wait - if (m_inQueue) - { - LogUnexpectedOpcode(packet, "the player not pass queue yet"); - break; - } - - // single from authed time opcodes send in to after logout time - // and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes. - if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) - m_playerRecentlyLogout = false; - - (this->*opHandle.handler)(*packet); - if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) - LogUnprocessedTail(packet); - break; - case STATUS_NEVER: - /* - sLog.outError("SESSION: received not allowed opcode %s (0x%.4X)", - LookupOpcodeName(packet->GetOpcode()), - packet->GetOpcode()); - */ - break; - } - } - catch(ByteBufferException &) - { - sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", - packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); - if (sLog.IsOutDebug()) - { - sLog.outDebug("Dumping error causing packet:"); - packet->hexlike(); - } - } - } - - delete packet; - } - - time_t currTime = time(NULL); - ///- If necessary, log the player out - if (ShouldLogOut(currTime) && !m_playerLoading) - LogoutPlayer(true); - - ///- Cleanup socket pointer if need - if (m_Socket && m_Socket->IsClosed()) - { - m_Socket->RemoveReference(); - m_Socket = NULL; - } - - if (!m_Socket) - return false; //Will remove this session from the world session map - - return true; -} - -/// %Log the player out -void WorldSession::LogoutPlayer(bool Save) -{ - // finish pending transfers before starting the logout - while (_player && _player->IsBeingTeleportedFar()) - HandleMoveWorldportAckOpcode(); - - m_playerLogout = true; - m_playerSave = Save; - - if (_player) - { - sLFGMgr.Leave(_player); - GetPlayer()->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - GetPlayer()->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - GetPlayer()->GetSession()->SendLfgUpdateSearch(false); - - if (uint64 lguid = GetPlayer()->GetLootGUID()) - DoLootRelease(lguid); - - ///- If the player just died before logging out, make him appear as a ghost - //FIXME: logout must be delayed in case lost connection with client in time of combat - if (_player->GetDeathTimer()) - { - _player->getHostileRefManager().deleteReferences(); - _player->BuildPlayerRepop(); - _player->RepopAtGraveyard(); - } - else if (!_player->getAttackers().empty()) - { - _player->CombatStop(); - _player->getHostileRefManager().setOnlineOfflineState(false); - _player->RemoveAllAurasOnDeath(); - - // build set of player who attack _player or who have pet attacking of _player - std::set aset; - for (Unit::AttackerSet::const_iterator itr = _player->getAttackers().begin(); itr != _player->getAttackers().end(); ++itr) - { - Unit* owner = (*itr)->GetOwner(); // including player controlled case - if (owner) - { - if (owner->GetTypeId() == TYPEID_PLAYER) - aset.insert(owner->ToPlayer()); - } - else - if ((*itr)->GetTypeId() == TYPEID_PLAYER) - aset.insert((Player*)(*itr)); - } - - _player->SetPvPDeath(!aset.empty()); - _player->KillPlayer(); - _player->BuildPlayerRepop(); - _player->RepopAtGraveyard(); - - // give honor to all attackers from set like group case - for (std::set::const_iterator itr = aset.begin(); itr != aset.end(); ++itr) - (*itr)->RewardHonor(_player,aset.size()); - - // give bg rewards and update counters like kill by first from attackers - // this can't be called for all attackers. - if (!aset.empty()) - if (BattleGround *bg = _player->GetBattleGround()) - bg->HandleKillPlayer(_player,*aset.begin()); - } - else if (_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) - { - // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION - _player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT); - //_player->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time - _player->KillPlayer(); - _player->BuildPlayerRepop(); - _player->RepopAtGraveyard(); - } - //drop a flag if player is carrying it - if (BattleGround *bg = _player->GetBattleGround()) - bg->EventPlayerLoggedOut(_player); - - ///- Teleport to home if the player is in an invalid instance - if (!_player->m_InstanceValid && !_player->isGameMaster()) - _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation()); - - sOutdoorPvPMgr.HandlePlayerLeaveZone(_player,_player->GetZoneId()); - - for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) - { - if (BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i)) - { - _player->RemoveBattleGroundQueueId(bgQueueTypeId); - sBattleGroundMgr.m_BattleGroundQueues[ bgQueueTypeId ].RemovePlayer(_player->GetGUID(), true); - } - } - - // Repop at GraveYard or other player far teleport will prevent saving player because of not present map - // Teleport player immediately for correct player save - while (_player->IsBeingTeleportedFar()) - HandleMoveWorldportAckOpcode(); - - ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members - Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); - if (guild) - { - guild->SetMemberStats(_player->GetGUID()); - guild->UpdateLogoutTime(_player->GetGUID()); - - guild->BroadcastEvent(GE_SIGNED_OFF, _player->GetGUID(), 1, _player->GetName(), "", ""); - } - - ///- Remove pet - _player->RemovePet(NULL,PET_SAVE_AS_CURRENT, true); - - ///- empty buyback items and save the player in the database - // some save parts only correctly work in case player present in map/player_lists (pets, etc) - if (Save) - { - uint32 eslot; - for (int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; ++j) - { - eslot = j - BUYBACK_SLOT_START; - _player->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (eslot * 2), 0); - _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0); - _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, 0); - } - _player->SaveToDB(); - } - - ///- Leave all channels before player delete... - _player->CleanupChannels(); - - ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group. - _player->UninviteFromGroup(); - - // remove player from the group if he is: - // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) - if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket) - _player->RemoveFromGroup(); - - ///- Send update to group and reset stored max enchanting level - if (_player->GetGroup()) - { - _player->GetGroup()->SendUpdate(); - _player->GetGroup()->ResetMaxEnchantingLevel(); - } - - ///- Broadcast a logout message to the player's friends - sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true); - sSocialMgr.RemovePlayerSocial (_player->GetGUIDLow ()); - - ///- Remove the player from the world - // the player may not be in the world when logging out - // e.g if he got disconnected during a transfer to another map - // calls to GetMap in this case may cause crashes - _player->CleanupsBeforeDelete(); - sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() ,_player->GetGUIDLow()); - Map* _map = _player->GetMap(); - _map->Remove(_player, true); - SetPlayer(NULL); // deleted in Remove call - - ///- Send the 'logout complete' packet to the client - WorldPacket data(SMSG_LOGOUT_COMPLETE, 0); - SendPacket(&data); - - ///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline - //No SQL injection as AccountId is uint32 - CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = '%u'", - GetAccountId()); - sLog.outDebug("SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); - } - - //Hook for OnLogout Event - sScriptMgr.OnLogout(_player); - - m_playerLogout = false; - m_playerSave = false; - m_playerRecentlyLogout = true; - LogoutRequest(0); -} - -/// Kick a player out of the World -void WorldSession::KickPlayer() -{ - if (m_Socket) - m_Socket->CloseSocket (); -} - -void WorldSession::SendNotification(const char *format,...) -{ - if (format) - { - va_list ap; - char szStr [1024]; - szStr[0] = '\0'; - va_start(ap, format); - vsnprintf(szStr, 1024, format, ap); - va_end(ap); - - WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr)+1)); - data << szStr; - SendPacket(&data); - } -} - -void WorldSession::SendNotification(int32 string_id,...) -{ - char const* format = GetTrinityString(string_id); - if (format) - { - va_list ap; - char szStr [1024]; - szStr[0] = '\0'; - va_start(ap, string_id); - vsnprintf(szStr, 1024, format, ap); - va_end(ap); - - WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr)+1)); - data << szStr; - SendPacket(&data); - } -} - -const char * WorldSession::GetTrinityString(int32 entry) const -{ - return objmgr.GetTrinityString(entry,GetSessionDbLocaleIndex()); -} - -void WorldSession::Handle_NULL(WorldPacket& recvPacket) -{ - sLog.outError("SESSION: received unhandled opcode %s (0x%.4X)", - LookupOpcodeName(recvPacket.GetOpcode()), - recvPacket.GetOpcode()); -} - -void WorldSession::Handle_EarlyProccess(WorldPacket& recvPacket) -{ - sLog.outError("SESSION: received opcode %s (0x%.4X) that must be processed in WorldSocket::OnRead", - LookupOpcodeName(recvPacket.GetOpcode()), - recvPacket.GetOpcode()); -} - -void WorldSession::Handle_ServerSide(WorldPacket& recvPacket) -{ - sLog.outError("SESSION: received server-side opcode %s (0x%.4X)", - LookupOpcodeName(recvPacket.GetOpcode()), - recvPacket.GetOpcode()); -} - -void WorldSession::Handle_Deprecated(WorldPacket& recvPacket) -{ - sLog.outError("SESSION: received deprecated opcode %s (0x%.4X)", - LookupOpcodeName(recvPacket.GetOpcode()), - recvPacket.GetOpcode()); -} - -void WorldSession::SendAuthWaitQue(uint32 position) -{ - if (position == 0) - { - WorldPacket packet(SMSG_AUTH_RESPONSE, 1); - packet << uint8(AUTH_OK); - SendPacket(&packet); - } - else - { - WorldPacket packet(SMSG_AUTH_RESPONSE, 6); - packet << uint8(AUTH_WAIT_QUEUE); - packet << uint32(position); - packet << uint8(0); // unk - SendPacket(&packet); - } -} - -void WorldSession::LoadGlobalAccountData() -{ - LoadAccountData( - CharacterDatabase.PQuery("SELECT type, time, data FROM account_data WHERE account='%u'", GetAccountId()), - GLOBAL_CACHE_MASK -); -} - -void WorldSession::LoadAccountData(QueryResult_AutoPtr result, uint32 mask) -{ - for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i) - if (mask & (1 << i)) - m_accountData[i] = AccountData(); - - if (!result) - return; - - do - { - Field *fields = result->Fetch(); - - uint32 type = fields[0].GetUInt32(); - if (type >= NUM_ACCOUNT_DATA_TYPES) - { - sLog.outError("Table `%s` have invalid account data type (%u), ignore.", - mask == GLOBAL_CACHE_MASK ? "account_data" : "character_account_data", type); - continue; - } - - if ((mask & (1 << type)) == 0) - { - sLog.outError("Table `%s` have non appropriate for table account data type (%u), ignore.", - mask == GLOBAL_CACHE_MASK ? "account_data" : "character_account_data", type); - continue; - } - - m_accountData[type].Time = fields[1].GetUInt32(); - m_accountData[type].Data = fields[2].GetCppString(); - - } while (result->NextRow()); -} - -void WorldSession::SetAccountData(AccountDataType type, time_t time_, std::string data) -{ - if ((1 << type) & GLOBAL_CACHE_MASK) - { - uint32 acc = GetAccountId(); - - CharacterDatabase.BeginTransaction (); - CharacterDatabase.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type); - CharacterDatabase.escape_string(data); - CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str()); - CharacterDatabase.CommitTransaction (); - } - else - { - // _player can be NULL and packet received after logout but m_GUID still store correct guid - if (!m_GUIDLow) - return; - - CharacterDatabase.BeginTransaction (); - CharacterDatabase.PExecute("DELETE FROM character_account_data WHERE guid='%u' AND type='%u'", m_GUIDLow, type); - CharacterDatabase.escape_string(data); - CharacterDatabase.PExecute("INSERT INTO character_account_data VALUES ('%u','%u','%u','%s')", m_GUIDLow, type, (uint32)time_, data.c_str()); - CharacterDatabase.CommitTransaction (); - } - - m_accountData[type].Time = time_; - m_accountData[type].Data = data; -} - -void WorldSession::SendAccountDataTimes(uint32 mask) -{ - WorldPacket data(SMSG_ACCOUNT_DATA_TIMES, 4+1+4+8*4); // changed in WotLK - data << uint32(time(NULL)); // unix time of something - data << uint8(1); - data << uint32(mask); // type mask - for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i) - if (mask & (1 << i)) - data << uint32(GetAccountData(AccountDataType(i))->Time);// also unix time - SendPacket(&data); -} - -void WorldSession::LoadTutorialsData() -{ - for (int aX = 0 ; aX < 8 ; ++aX) - m_Tutorials[ aX ] = 0; - - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7 FROM character_tutorial WHERE account = '%u'", GetAccountId()); - - if (result) - { - do - { - Field *fields = result->Fetch(); - - for (int iI = 0; iI < 8; ++iI) - m_Tutorials[iI] = fields[iI].GetUInt32(); - } - while (result->NextRow()); - } - m_TutorialsChanged = false; -} - -void WorldSession::SendTutorialsData() -{ - WorldPacket data(SMSG_TUTORIAL_FLAGS, 4*8); - for (uint32 i = 0; i < 8; ++i) - data << m_Tutorials[i]; - SendPacket(&data); -} - -void WorldSession::SaveTutorialsData() -{ - if (!m_TutorialsChanged) - return; - - uint32 Rows=0; - // it's better than rebuilding indexes multiple times - QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT count(*) AS r FROM character_tutorial WHERE account = '%u'", GetAccountId()); - if (result) - Rows = result->Fetch()[0].GetUInt32(); - - if (Rows) - { - CharacterDatabase.PExecute("UPDATE character_tutorial SET tut0='%u', tut1='%u', tut2='%u', tut3='%u', tut4='%u', tut5='%u', tut6='%u', tut7='%u' WHERE account = '%u'", - m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7], GetAccountId()); - } - else - { - CharacterDatabase.PExecute("INSERT INTO character_tutorial (account,tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7) VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetAccountId(), m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7]); - } - - m_TutorialsChanged = false; -} - -void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi) -{ - data >> mi->flags; - data >> mi->unk1; - data >> mi->time; - data >> mi->x; - data >> mi->y; - data >> mi->z; - data >> mi->o; - - if (mi->flags & MOVEMENTFLAG_ONTRANSPORT) - { - if (!data.readPackGUID(mi->t_guid)) - return; - - data >> mi->t_x; - data >> mi->t_y; - data >> mi->t_z; - data >> mi->t_o; - data >> mi->t_time; - data >> mi->t_seat; - } - - if ((mi->flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi->unk1 & 0x20)) - { - data >> mi->s_pitch; - } - - data >> mi->fallTime; - - if (mi->flags & MOVEMENTFLAG_JUMPING) - { - data >> mi->j_zspeed; - data >> mi->j_sinAngle; - data >> mi->j_cosAngle; - data >> mi->j_xyspeed; - } - - if (mi->flags & MOVEMENTFLAG_SPLINE) - { - data >> mi->u_unk1; - } -} - -void WorldSession::WriteMovementInfo(WorldPacket *data, MovementInfo *mi) -{ - data->appendPackGUID(mi->guid); - - *data << mi->flags; - *data << mi->unk1; - *data << mi->time; - *data << mi->x; - *data << mi->y; - *data << mi->z; - *data << mi->o; - - if (mi->HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - { - data->appendPackGUID(mi->t_guid); - - *data << mi->t_x; - *data << mi->t_y; - *data << mi->t_z; - *data << mi->t_o; - *data << mi->t_time; - *data << mi->t_seat; - } - - if ((mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING))) || (mi->unk1 & 0x20)) - { - *data << mi->s_pitch; - } - - *data << mi->fallTime; - - if (mi->HasMovementFlag(MOVEMENTFLAG_JUMPING)) - { - *data << mi->j_zspeed; - *data << mi->j_sinAngle; - *data << mi->j_cosAngle; - *data << mi->j_xyspeed; - } - - if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE)) - { - *data << mi->u_unk1; - } -} - -void WorldSession::ReadAddonsInfo(WorldPacket &data) -{ - if (data.rpos() + 4 > data.size()) - return; - uint32 size; - data >> size; - - if (!size) - return; - - if (size > 0xFFFFF) - { - sLog.outError("WorldSession::ReadAddonsInfo addon info too big, size %u", size); - return; - } - - uLongf uSize = size; - - uint32 pos = data.rpos(); - - ByteBuffer addonInfo; - addonInfo.resize(size); - - if (uncompress(const_cast(addonInfo.contents()), &uSize, const_cast(data.contents() + pos), data.size() - pos) == Z_OK) - { - uint32 addonsCount; - addonInfo >> addonsCount; // addons count - - for (uint32 i = 0; i < addonsCount; ++i) - { - std::string addonName; - uint8 enabled; - uint32 crc, unk1; - - // check next addon data format correctness - if (addonInfo.rpos()+1 > addonInfo.size()) - return; - - addonInfo >> addonName; - - addonInfo >> enabled >> crc >> unk1; - - sLog.outDetail("ADDON: Name: %s, Enabled: 0x%x, CRC: 0x%x, Unknown2: 0x%x", addonName.c_str(), enabled, crc, unk1); - - AddonInfo addon(addonName, enabled, crc, 2, true); - - SavedAddon const* savedAddon = sAddonMgr.GetAddonInfo(addonName); - if (savedAddon) - { - bool match = true; - - if (addon.CRC != savedAddon->CRC) - match = false; - - if (!match) - sLog.outDetail("ADDON: %s was known, but didn't match known CRC (0x%x)!", addon.Name.c_str(), savedAddon->CRC); - else - sLog.outDetail("ADDON: %s was known, CRC is correct (0x%x)", addon.Name.c_str(), savedAddon->CRC); - } - else - { - sAddonMgr.SaveAddon(addon); - - sLog.outDetail("ADDON: %s (0x%x) was not known, saving...", addon.Name.c_str(), addon.CRC); - } - - // TODO: Find out when to not use CRC/pubkey, and other possible states. - m_addonsList.push_back(addon); - } - - uint32 currentTime; - addonInfo >> currentTime; - sLog.outDebug("ADDON: CurrentTime: %u", currentTime); - - if (addonInfo.rpos() != addonInfo.size()) - sLog.outDebug("packet under-read!"); - } - else - sLog.outError("Addon packet uncompress error!"); -} - -void WorldSession::SendAddonsInfo() -{ - uint8 addonPublicKey[256] = - { - 0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54, - 0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75, - 0xFF, 0x31, 0xFE, 0x2F, 0x64, 0x3F, 0x3D, 0x6D, 0x07, 0xD9, 0x44, 0x9B, 0x40, 0x85, 0x59, 0x34, - 0x4E, 0x10, 0xE1, 0xE7, 0x43, 0x69, 0xEF, 0x7C, 0x16, 0xFC, 0xB4, 0xED, 0x1B, 0x95, 0x28, 0xA8, - 0x23, 0x76, 0x51, 0x31, 0x57, 0x30, 0x2B, 0x79, 0x08, 0x50, 0x10, 0x1C, 0x4A, 0x1A, 0x2C, 0xC8, - 0x8B, 0x8F, 0x05, 0x2D, 0x22, 0x3D, 0xDB, 0x5A, 0x24, 0x7A, 0x0F, 0x13, 0x50, 0x37, 0x8F, 0x5A, - 0xCC, 0x9E, 0x04, 0x44, 0x0E, 0x87, 0x01, 0xD4, 0xA3, 0x15, 0x94, 0x16, 0x34, 0xC6, 0xC2, 0xC3, - 0xFB, 0x49, 0xFE, 0xE1, 0xF9, 0xDA, 0x8C, 0x50, 0x3C, 0xBE, 0x2C, 0xBB, 0x57, 0xED, 0x46, 0xB9, - 0xAD, 0x8B, 0xC6, 0xDF, 0x0E, 0xD6, 0x0F, 0xBE, 0x80, 0xB3, 0x8B, 0x1E, 0x77, 0xCF, 0xAD, 0x22, - 0xCF, 0xB7, 0x4B, 0xCF, 0xFB, 0xF0, 0x6B, 0x11, 0x45, 0x2D, 0x7A, 0x81, 0x18, 0xF2, 0x92, 0x7E, - 0x98, 0x56, 0x5D, 0x5E, 0x69, 0x72, 0x0A, 0x0D, 0x03, 0x0A, 0x85, 0xA2, 0x85, 0x9C, 0xCB, 0xFB, - 0x56, 0x6E, 0x8F, 0x44, 0xBB, 0x8F, 0x02, 0x22, 0x68, 0x63, 0x97, 0xBC, 0x85, 0xBA, 0xA8, 0xF7, - 0xB5, 0x40, 0x68, 0x3C, 0x77, 0x86, 0x6F, 0x4B, 0xD7, 0x88, 0xCA, 0x8A, 0xD7, 0xCE, 0x36, 0xF0, - 0x45, 0x6E, 0xD5, 0x64, 0x79, 0x0F, 0x17, 0xFC, 0x64, 0xDD, 0x10, 0x6F, 0xF3, 0xF5, 0xE0, 0xA6, - 0xC3, 0xFB, 0x1B, 0x8C, 0x29, 0xEF, 0x8E, 0xE5, 0x34, 0xCB, 0xD1, 0x2A, 0xCE, 0x79, 0xC3, 0x9A, - 0x0D, 0x36, 0xEA, 0x01, 0xE0, 0xAA, 0x91, 0x20, 0x54, 0xF0, 0x72, 0xD8, 0x1E, 0xC7, 0x89, 0xD2 - }; - - WorldPacket data(SMSG_ADDON_INFO, 4); - - for (AddonsList::iterator itr = m_addonsList.begin(); itr != m_addonsList.end(); ++itr) - { - data << uint8(itr->State); - - uint8 crcpub = itr->UsePublicKeyOrCRC; - data << uint8(crcpub); - if (crcpub) - { - uint8 usepk = (itr->CRC != STANDARD_ADDON_CRC); // If addon is Standard addon CRC - data << uint8(usepk); - if (usepk) // if CRC is wrong, add public key (client need it) - { - sLog.outDetail("ADDON: CRC (0x%x) for addon %s is wrong (does not match expected 0x%x), sending pubkey", - itr->CRC, itr->Name.c_str(), STANDARD_ADDON_CRC); - - data.append(addonPublicKey, sizeof(addonPublicKey)); - } - - data << uint32(/*itr->CRC*/ 0); // TODO: Find out the meaning of this. - } - - uint8 unk3 = 0; // 0 is sent here - data << uint8(unk3); - if (unk3) - { - // String, length 256 (null terminated) - data << uint8(0); - } - } - - m_addonsList.clear(); - - uint32 count = 0; - data << uint32(count); - /*for (uint32 i = 0; i < count; ++i) - { - uint32 - string (16 bytes) - string (16 bytes) - uint32 - uint32 - }*/ - - SendPacket(&data); -} - -void WorldSession::SetPlayer(Player *plr) -{ - _player = plr; - - // set m_GUID that can be used while player loggined and later until m_playerRecentlyLogout not reset - if (_player) - m_GUIDLow = _player->GetGUIDLow(); -} diff --git a/src/server/game/World/WorldSession.h b/src/server/game/World/WorldSession.h deleted file mode 100644 index c17f3e3f3e6..00000000000 --- a/src/server/game/World/WorldSession.h +++ /dev/null @@ -1,829 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup u2w -/// @{ -/// \file - -#ifndef __WORLDSESSION_H -#define __WORLDSESSION_H - -#include "Common.h" -#include "SharedDefines.h" -#include "AddonMgr.h" -#include "QueryResult.h" -#include "World.h" - -struct ItemPrototype; -struct AuctionEntry; -struct DeclinedName; -struct MovementInfo; - -class Creature; -class Item; -class Object; -class Player; -class Unit; -class GameObject; -class WorldPacket; -class WorldSocket; -class QueryResult; -class LoginQueryHolder; -class CharacterHandler; -struct AreaTableEntry; - -enum AccountDataType -{ - GLOBAL_CONFIG_CACHE = 0, // 0x01 g - PER_CHARACTER_CONFIG_CACHE = 1, // 0x02 p - GLOBAL_BINDINGS_CACHE = 2, // 0x04 g - PER_CHARACTER_BINDINGS_CACHE = 3, // 0x08 p - GLOBAL_MACROS_CACHE = 4, // 0x10 g - PER_CHARACTER_MACROS_CACHE = 5, // 0x20 p - PER_CHARACTER_LAYOUT_CACHE = 6, // 0x40 p - PER_CHARACTER_CHAT_CACHE = 7, // 0x80 p -}; - -#define NUM_ACCOUNT_DATA_TYPES 8 - -#define GLOBAL_CACHE_MASK 0x15 -#define PER_CHARACTER_CACHE_MASK 0xEA - -struct AccountData -{ - AccountData() : Time(0), Data("") {} - - time_t Time; - std::string Data; -}; - -enum PartyOperation -{ - PARTY_OP_INVITE = 0, - PARTY_OP_UNINVITE = 1, - PARTY_OP_LEAVE = 2, - PARTY_OP_SWAP = 4 -}; - -enum PartyResult -{ - ERR_PARTY_RESULT_OK = 0, - ERR_BAD_PLAYER_NAME_S = 1, - ERR_TARGET_NOT_IN_GROUP_S = 2, - ERR_TARGET_NOT_IN_INSTANCE_S = 3, - ERR_GROUP_FULL = 4, - ERR_ALREADY_IN_GROUP_S = 5, - ERR_NOT_IN_GROUP = 6, - ERR_NOT_LEADER = 7, - ERR_PLAYER_WRONG_FACTION = 8, - ERR_IGNORING_YOU_S = 9, - ERR_LFG_PENDING = 12, - ERR_INVITE_RESTRICTED = 13, - ERR_GROUP_SWAP_FAILED = 14, // if (PartyOperation == PARTY_OP_SWAP) ERR_GROUP_SWAP_FAILED else ERR_INVITE_IN_COMBAT - ERR_INVITE_UNKNOWN_REALM = 15, - ERR_INVITE_NO_PARTY_SERVER = 16, - ERR_INVITE_PARTY_BUSY = 17, - ERR_PARTY_TARGET_AMBIGUOUS = 18, - ERR_PARTY_LFG_INVITE_RAID_LOCKED = 19, - ERR_PARTY_LFG_BOOT_LIMIT = 20, - ERR_PARTY_LFG_BOOT_COOLDOWN_S = 21, - ERR_PARTY_LFG_BOOT_IN_PROGRESS = 22, - ERR_PARTY_LFG_BOOT_TOO_FEW_PLAYERS = 23, - ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S = 24, - ERR_RAID_DISALLOWED_BY_LEVEL = 25, - ERR_PARTY_LFG_BOOT_IN_COMBAT = 26, - ERR_VOTE_KICK_REASON_NEEDED = 27, - ERR_PARTY_LFG_BOOT_DUNGEON_COMPLETE = 28, - ERR_PARTY_LFG_BOOT_LOOT_ROLLS = 29, - ERR_PARTY_LFG_TELEPORT_IN_COMBAT = 30 -}; - -enum ChatRestrictionType -{ - ERR_CHAT_RESTRICTED = 0, - ERR_CHAT_THROTTLED = 1, - ERR_USER_SQUELCHED = 2, - ERR_YELL_RESTRICTED = 3 -}; - -/// Player session in the World -class WorldSession -{ - friend class CharacterHandler; - public: - WorldSession(uint32 id, WorldSocket *sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale); - ~WorldSession(); - - bool PlayerLoading() const { return m_playerLoading; } - bool PlayerLogout() const { return m_playerLogout; } - bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; } - - void SizeError(WorldPacket const& packet, uint32 size) const; - - void ReadAddonsInfo(WorldPacket &data); - void SendAddonsInfo(); - - void ReadMovementInfo(WorldPacket &data, MovementInfo *mi); - void WriteMovementInfo(WorldPacket *data, MovementInfo *mi); - - void SendPacket(WorldPacket const* packet); - void SendNotification(const char *format,...) ATTR_PRINTF(2,3); - void SendNotification(int32 string_id,...); - void SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName); - void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res); - void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2,3); - void SendSetPhaseShift(uint32 phaseShift); - void SendQueryTimeResponse(); - - AccountTypes GetSecurity() const { return _security; } - uint32 GetAccountId() const { return _accountId; } - Player* GetPlayer() const { return _player; } - char const* GetPlayerName() const; - void SetSecurity(AccountTypes security) { _security = security; } - std::string const& GetRemoteAddress() { return m_Address; } - void SetPlayer(Player *plr); - uint8 Expansion() const { return m_expansion; } - - /// Session in auth.queue currently - void SetInQueue(bool state) { m_inQueue = state; } - - /// Is the user engaged in a log out process? - bool isLogingOut() const { return _logoutTime || m_playerLogout; } - - /// Engage the logout process for the user - void LogoutRequest(time_t requestTime) - { - _logoutTime = requestTime; - } - - /// Is logout cooldown expired? - bool ShouldLogOut(time_t currTime) const - { - return (_logoutTime > 0 && currTime >= _logoutTime + 20); - } - - void LogoutPlayer(bool Save); - void KickPlayer(); - - void QueuePacket(WorldPacket* new_packet); - bool Update(uint32 diff); - - /// Handle the authentication waiting queue (to be completed) - void SendAuthWaitQue(uint32 position); - - //void SendTestCreatureQueryOpcode(uint32 entry, uint64 guid, uint32 testvalue); - void SendNameQueryOpcode(Player* p); - void SendNameQueryOpcodeFromDB(uint64 guid); - static void SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, uint32 accountId); - - void SendTrainerList(uint64 guid); - void SendTrainerList(uint64 guid, const std::string& strTitle); - void SendListInventory(uint64 guid); - void SendShowBank(uint64 guid); - void SendTabardVendorActivate(uint64 guid); - void SendSpiritResurrect(); - void SendBindPoint(Creature* npc); - - void SendAttackStop(Unit const* enemy); - - void SendBattlegGroundList(uint64 guid, BattleGroundTypeId bgTypeId); - - void SendTradeStatus(uint32 status); - void SendCancelTrade(); - - void SendStablePet(uint64 guid); - void SendPetitionQueryOpcode(uint64 petitionguid); - void SendUpdateTrade(); - - //pet - void SendPetNameQuery(uint64 guid, uint32 petnumber); - - // Account Data - AccountData *GetAccountData(AccountDataType type) { return &m_accountData[type]; } - void SetAccountData(AccountDataType type, time_t time_, std::string data); - void SendAccountDataTimes(uint32 mask); - void LoadGlobalAccountData(); - void LoadAccountData(QueryResult_AutoPtr result, uint32 mask); - void LoadTutorialsData(); - void SendTutorialsData(); - void SaveTutorialsData(); - uint32 GetTutorialInt(uint32 intId) - { - return m_Tutorials[intId]; - } - - void SetTutorialInt(uint32 intId, uint32 value) - { - if (m_Tutorials[intId] != value) - { - m_Tutorials[intId] = value; - m_TutorialsChanged = true; - } - } - //used with item_page table - bool SendItemInfo(uint32 itemid, WorldPacket data); - //auction - void SendAuctionHello(uint64 guid, Creature * unit); - void SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0); - void SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template); - void SendAuctionOwnerNotification(AuctionEntry * auction); - void SendAuctionOutbiddedMail(AuctionEntry * auction, uint32 newPrice); - void SendAuctionCancelledToBidderMail(AuctionEntry* auction); - - //Item Enchantment - void SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID); - void SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration); - - //Taxi - void SendTaxiStatus(uint64 guid); - void SendTaxiMenu(Creature* unit); - void SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode = 0); - bool SendLearnNewTaxiNode(Creature* unit); - - // Guild/Arena Team - void SendGuildCommandResult(uint32 typecmd, const std::string& str, uint32 cmdresult); - void SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id); - void SendNotInArenaTeamPacket(uint8 type); - void SendPetitionShowList(uint64 guid); - void SendSaveGuildEmblem(uint32 msg); - // Looking For Group - // TRUE values set by client sending CMSG_LFG_SET_AUTOJOIN and CMSG_LFM_CLEAR_AUTOFILL before player login - bool LookingForGroup_auto_join; - bool LookingForGroup_auto_add; - - void BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data); - - void DoLootRelease(uint64 lguid); - - // Account mute time - time_t m_muteTime; - - // Locales - LocaleConstant GetSessionDbcLocale() const { return m_sessionDbcLocale; } - int GetSessionDbLocaleIndex() const { return m_sessionDbLocaleIndex; } - const char *GetTrinityString(int32 entry) const; - - uint32 GetLatency() const { return m_latency; } - void SetLatency(uint32 latency) { m_latency = latency; } - uint32 getDialogStatus(Player *pPlayer, Object* questgiver, uint32 defstatus); - - time_t m_timeOutTime; - void UpdateTimeOutTime(uint32 diff) - { - if (diff > m_timeOutTime) - m_timeOutTime = 0; - else - m_timeOutTime -= diff; - } - void ResetTimeOutTime() - { - m_timeOutTime = sWorld.getConfig(CONFIG_SOCKET_TIMEOUTTIME); - } - bool IsConnectionIdle() const - { - if (m_timeOutTime <= 0 && !m_inQueue) - return true; - return false; - } - - - public: // opcodes handlers - - void Handle_NULL(WorldPacket& recvPacket); // not used - void Handle_EarlyProccess(WorldPacket& recvPacket);// just mark packets processed in WorldSocket::OnRead - void Handle_ServerSide(WorldPacket& recvPacket); // sever side only, can't be accepted from client - void Handle_Deprecated(WorldPacket& recvPacket); // never used anymore by client - - void HandleCharEnumOpcode(WorldPacket& recvPacket); - void HandleCharDeleteOpcode(WorldPacket& recvPacket); - void HandleCharCreateOpcode(WorldPacket& recvPacket); - void HandlePlayerLoginOpcode(WorldPacket& recvPacket); - void HandleCharEnum(QueryResult_AutoPtr result); - void HandlePlayerLogin(LoginQueryHolder * holder); - - // played time - void HandlePlayedTime(WorldPacket& recvPacket); - - // new - void HandleMoveUnRootAck(WorldPacket& recvPacket); - void HandleMoveRootAck(WorldPacket& recvPacket); - void HandleLookingForGroup(WorldPacket& recvPacket); - - // new inspect - void HandleInspectOpcode(WorldPacket& recvPacket); - - // new party stats - void HandleInspectHonorStatsOpcode(WorldPacket& recvPacket); - - void HandleMoveWaterWalkAck(WorldPacket& recvPacket); - void HandleFeatherFallAck(WorldPacket &recv_data); - - void HandleMoveHoverAck(WorldPacket & recv_data); - - void HandleMountSpecialAnimOpcode(WorldPacket &recvdata); - - // character view - void HandleShowingHelmOpcode(WorldPacket& recv_data); - void HandleShowingCloakOpcode(WorldPacket& recv_data); - - // repair - void HandleRepairItemOpcode(WorldPacket& recvPacket); - - // Knockback - void HandleMoveKnockBackAck(WorldPacket& recvPacket); - - void HandleMoveTeleportAck(WorldPacket& recvPacket); - void HandleForceSpeedChangeAck(WorldPacket & recv_data); - - void HandlePingOpcode(WorldPacket& recvPacket); - void HandleAuthSessionOpcode(WorldPacket& recvPacket); - void HandleRepopRequestOpcode(WorldPacket& recvPacket); - void HandleAutostoreLootItemOpcode(WorldPacket& recvPacket); - void HandleLootMoneyOpcode(WorldPacket& recvPacket); - void HandleLootOpcode(WorldPacket& recvPacket); - void HandleLootReleaseOpcode(WorldPacket& recvPacket); - void HandleLootMasterGiveOpcode(WorldPacket& recvPacket); - void HandleWhoOpcode(WorldPacket& recvPacket); - void HandleLogoutRequestOpcode(WorldPacket& recvPacket); - void HandlePlayerLogoutOpcode(WorldPacket& recvPacket); - void HandleLogoutCancelOpcode(WorldPacket& recvPacket); - - // GM Ticket opcodes - void HandleGMTicketCreateOpcode(WorldPacket& recvPacket); - void HandleGMTicketUpdateOpcode(WorldPacket& recvPacket); - void HandleGMTicketDeleteOpcode(WorldPacket& recvPacket); - void HandleGMTicketGetTicketOpcode(WorldPacket& recvPacket); - void HandleGMTicketSystemStatusOpcode(WorldPacket& recvPacket); - void SendGMTicketGetTicket(uint32 status, char const* text); - - //void HandleGMSurveySubmit(WorldPacket& recvPacket); - - void HandleTogglePvP(WorldPacket& recvPacket); - - void HandleZoneUpdateOpcode(WorldPacket& recvPacket); - void HandleSetTargetOpcode(WorldPacket& recvPacket); - void HandleSetSelectionOpcode(WorldPacket& recvPacket); - void HandleStandStateChangeOpcode(WorldPacket& recvPacket); - void HandleEmoteOpcode(WorldPacket& recvPacket); - void HandleContactListOpcode(WorldPacket& recvPacket); - void HandleAddFriendOpcode(WorldPacket& recvPacket); - static void HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string friendNote); - void HandleDelFriendOpcode(WorldPacket& recvPacket); - void HandleAddIgnoreOpcode(WorldPacket& recvPacket); - static void HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId); - void HandleDelIgnoreOpcode(WorldPacket& recvPacket); - void HandleSetContactNotesOpcode(WorldPacket& recvPacket); - void HandleBugOpcode(WorldPacket& recvPacket); - void HandleSetAmmoOpcode(WorldPacket& recvPacket); - void HandleItemNameQueryOpcode(WorldPacket& recvPacket); - - void HandleAreaTriggerOpcode(WorldPacket& recvPacket); - - void HandleSetFactionAtWar(WorldPacket & recv_data); - void HandleSetFactionCheat(WorldPacket & recv_data); - void HandleSetWatchedFactionOpcode(WorldPacket & recv_data); - void HandleSetFactionInactiveOpcode(WorldPacket & recv_data); - - void HandleUpdateAccountData(WorldPacket& recvPacket); - void HandleRequestAccountData(WorldPacket& recvPacket); - void HandleSetActionButtonOpcode(WorldPacket& recvPacket); - - void HandleGameObjectUseOpcode(WorldPacket& recPacket); - void HandleMeetingStoneInfo(WorldPacket& recPacket); - void HandleGameobjectReportUse(WorldPacket& recvPacket); - - void HandleNameQueryOpcode(WorldPacket& recvPacket); - - void HandleQueryTimeOpcode(WorldPacket& recvPacket); - - void HandleCreatureQueryOpcode(WorldPacket& recvPacket); - - void HandleGameObjectQueryOpcode(WorldPacket& recvPacket); - - void HandleMoveWorldportAckOpcode(WorldPacket& recvPacket); - void HandleMoveWorldportAckOpcode(); // for server-side calls - - void HandleMovementOpcodes(WorldPacket& recvPacket); - void HandleSetActiveMoverOpcode(WorldPacket &recv_data); - void HandleMoveNotActiveMover(WorldPacket &recv_data); - void HandleDismissControlledVehicle(WorldPacket &recv_data); - void HandleRequestVehicleExit(WorldPacket &recv_data); - void HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data); - void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); - - void HandleRequestRaidInfoOpcode(WorldPacket & recv_data); - - void HandleBattlefieldStatusOpcode(WorldPacket &recv_data); - void HandleBattleMasterHelloOpcode(WorldPacket &recv_data); - - void HandleGroupInviteOpcode(WorldPacket& recvPacket); - //void HandleGroupCancelOpcode(WorldPacket& recvPacket); - void HandleGroupAcceptOpcode(WorldPacket& recvPacket); - void HandleGroupDeclineOpcode(WorldPacket& recvPacket); - void HandleGroupUninviteOpcode(WorldPacket& recvPacket); - void HandleGroupUninviteGuidOpcode(WorldPacket& recvPacket); - void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket); - void HandleGroupDisbandOpcode(WorldPacket& recvPacket); - void HandleOptOutOfLootOpcode(WorldPacket &recv_data); - void HandleLootMethodOpcode(WorldPacket& recvPacket); - void HandleLootRoll(WorldPacket &recv_data); - void HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data); - void HandleRaidTargetUpdateOpcode(WorldPacket & recv_data); - void HandleRaidReadyCheckOpcode(WorldPacket & recv_data); - void HandleRaidReadyCheckFinishedOpcode(WorldPacket & recv_data); - void HandleGroupRaidConvertOpcode(WorldPacket & recv_data); - void HandleGroupChangeSubGroupOpcode(WorldPacket & recv_data); - void HandleGroupAssistantLeaderOpcode(WorldPacket & recv_data); - void HandlePartyAssignmentOpcode(WorldPacket & recv_data); - - void HandlePetitionBuyOpcode(WorldPacket& recv_data); - void HandlePetitionShowSignOpcode(WorldPacket& recv_data); - void HandlePetitionQueryOpcode(WorldPacket& recv_data); - void HandlePetitionRenameOpcode(WorldPacket& recv_data); - void HandlePetitionSignOpcode(WorldPacket& recv_data); - void HandlePetitionDeclineOpcode(WorldPacket& recv_data); - void HandleOfferPetitionOpcode(WorldPacket& recv_data); - void HandleTurnInPetitionOpcode(WorldPacket& recv_data); - - void HandleGuildQueryOpcode(WorldPacket& recvPacket); - void HandleGuildCreateOpcode(WorldPacket& recvPacket); - void HandleGuildInviteOpcode(WorldPacket& recvPacket); - void HandleGuildRemoveOpcode(WorldPacket& recvPacket); - void HandleGuildAcceptOpcode(WorldPacket& recvPacket); - void HandleGuildDeclineOpcode(WorldPacket& recvPacket); - void HandleGuildInfoOpcode(WorldPacket& recvPacket); - void HandleGuildEventLogQueryOpcode(WorldPacket& recvPacket); - void HandleGuildRosterOpcode(WorldPacket& recvPacket); - void HandleGuildPromoteOpcode(WorldPacket& recvPacket); - void HandleGuildDemoteOpcode(WorldPacket& recvPacket); - void HandleGuildLeaveOpcode(WorldPacket& recvPacket); - void HandleGuildDisbandOpcode(WorldPacket& recvPacket); - void HandleGuildLeaderOpcode(WorldPacket& recvPacket); - void HandleGuildMOTDOpcode(WorldPacket& recvPacket); - void HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket); - void HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket); - void HandleGuildRankOpcode(WorldPacket& recvPacket); - void HandleGuildAddRankOpcode(WorldPacket& recvPacket); - void HandleGuildDelRankOpcode(WorldPacket& recvPacket); - void HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket); - void HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket); - - void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket); - void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket); - void HandleActivateTaxiOpcode(WorldPacket& recvPacket); - void HandleActivateTaxiExpressOpcode(WorldPacket& recvPacket); - void HandleMoveSplineDoneOpcode(WorldPacket& recvPacket); - - void HandleTabardVendorActivateOpcode(WorldPacket& recvPacket); - void HandleBankerActivateOpcode(WorldPacket& recvPacket); - void HandleBuyBankSlotOpcode(WorldPacket& recvPacket); - void HandleTrainerListOpcode(WorldPacket& recvPacket); - void HandleTrainerBuySpellOpcode(WorldPacket& recvPacket); - void HandlePetitionShowListOpcode(WorldPacket& recvPacket); - void HandleGossipHelloOpcode(WorldPacket& recvPacket); - void HandleGossipSelectOptionOpcode(WorldPacket& recvPacket); - void HandleSpiritHealerActivateOpcode(WorldPacket& recvPacket); - void HandleNpcTextQueryOpcode(WorldPacket& recvPacket); - void HandleBinderActivateOpcode(WorldPacket& recvPacket); - void HandleListStabledPetsOpcode(WorldPacket& recvPacket); - void HandleStablePet(WorldPacket& recvPacket); - void HandleUnstablePet(WorldPacket& recvPacket); - void HandleBuyStableSlot(WorldPacket& recvPacket); - void HandleStableRevivePet(WorldPacket& recvPacket); - void HandleStableSwapPet(WorldPacket& recvPacket); - - void HandleDuelAcceptedOpcode(WorldPacket& recvPacket); - void HandleDuelCancelledOpcode(WorldPacket& recvPacket); - - void HandleAcceptTradeOpcode(WorldPacket& recvPacket); - void HandleBeginTradeOpcode(WorldPacket& recvPacket); - void HandleBusyTradeOpcode(WorldPacket& recvPacket); - void HandleCancelTradeOpcode(WorldPacket& recvPacket); - void HandleClearTradeItemOpcode(WorldPacket& recvPacket); - void HandleIgnoreTradeOpcode(WorldPacket& recvPacket); - void HandleInitiateTradeOpcode(WorldPacket& recvPacket); - void HandleSetTradeGoldOpcode(WorldPacket& recvPacket); - void HandleSetTradeItemOpcode(WorldPacket& recvPacket); - void HandleUnacceptTradeOpcode(WorldPacket& recvPacket); - - void HandleAuctionHelloOpcode(WorldPacket& recvPacket); - void HandleAuctionListItems(WorldPacket & recv_data); - void HandleAuctionListBidderItems(WorldPacket & recv_data); - void HandleAuctionSellItem(WorldPacket & recv_data); - void HandleAuctionRemoveItem(WorldPacket & recv_data); - void HandleAuctionListOwnerItems(WorldPacket & recv_data); - void HandleAuctionPlaceBid(WorldPacket & recv_data); - void HandleAuctionListPendingSales(WorldPacket & recv_data); - - void HandleGetMailList(WorldPacket & recv_data); - void HandleSendMail(WorldPacket & recv_data); - void HandleMailTakeMoney(WorldPacket & recv_data); - void HandleMailTakeItem(WorldPacket & recv_data); - void HandleMailMarkAsRead(WorldPacket & recv_data); - void HandleMailReturnToSender(WorldPacket & recv_data); - void HandleMailDelete(WorldPacket & recv_data); - void HandleItemTextQuery(WorldPacket & recv_data); - void HandleMailCreateTextItem(WorldPacket & recv_data); - void HandleQueryNextMailTime(WorldPacket & recv_data); - void HandleCancelChanneling(WorldPacket & recv_data); - - void SendItemPageInfo(ItemPrototype *itemProto); - void HandleSplitItemOpcode(WorldPacket& recvPacket); - void HandleSwapInvItemOpcode(WorldPacket& recvPacket); - void HandleDestroyItemOpcode(WorldPacket& recvPacket); - void HandleAutoEquipItemOpcode(WorldPacket& recvPacket); - void HandleItemQuerySingleOpcode(WorldPacket& recvPacket); - void HandleSellItemOpcode(WorldPacket& recvPacket); - void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket); - void HandleBuyItemOpcode(WorldPacket& recvPacket); - void HandleListInventoryOpcode(WorldPacket& recvPacket); - void HandleAutoStoreBagItemOpcode(WorldPacket& recvPacket); - void HandleReadItem(WorldPacket& recvPacket); - void HandleAutoEquipItemSlotOpcode(WorldPacket & recvPacket); - void HandleSwapItem(WorldPacket & recvPacket); - void HandleBuybackItem(WorldPacket & recvPacket); - void HandleAutoBankItemOpcode(WorldPacket& recvPacket); - void HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket); - void HandleWrapItemOpcode(WorldPacket& recvPacket); - - void HandleAttackSwingOpcode(WorldPacket& recvPacket); - void HandleAttackStopOpcode(WorldPacket& recvPacket); - void HandleSetSheathedOpcode(WorldPacket& recvPacket); - - void HandleUseItemOpcode(WorldPacket& recvPacket); - void HandleOpenItemOpcode(WorldPacket& recvPacket); - void HandleCastSpellOpcode(WorldPacket& recvPacket); - void HandleCancelCastOpcode(WorldPacket& recvPacket); - void HandleCancelAuraOpcode(WorldPacket& recvPacket); - void HandleCancelGrowthAuraOpcode(WorldPacket& recvPacket); - void HandleCancelAutoRepeatSpellOpcode(WorldPacket& recvPacket); - - void HandleLearnTalentOpcode(WorldPacket& recvPacket); - void HandleLearnPreviewTalents(WorldPacket& recvPacket); - void HandleTalentWipeConfirmOpcode(WorldPacket& recvPacket); - void HandleUnlearnSkillOpcode(WorldPacket& recvPacket); - - void HandleQuestgiverStatusQueryOpcode(WorldPacket& recvPacket); - void HandleQuestgiverStatusMultipleQuery(WorldPacket& recvPacket); - void HandleQuestgiverHelloOpcode(WorldPacket& recvPacket); - void HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvPacket); - void HandleQuestgiverQueryQuestOpcode(WorldPacket& recvPacket); - void HandleQuestgiverChooseRewardOpcode(WorldPacket& recvPacket); - void HandleQuestgiverRequestRewardOpcode(WorldPacket& recvPacket); - void HandleQuestQueryOpcode(WorldPacket& recvPacket); - void HandleQuestgiverCancel(WorldPacket& recv_data); - void HandleQuestLogSwapQuest(WorldPacket& recv_data); - void HandleQuestLogRemoveQuest(WorldPacket& recv_data); - void HandleQuestConfirmAccept(WorldPacket& recv_data); - void HandleQuestgiverCompleteQuest(WorldPacket& recv_data); - void HandleQuestgiverQuestAutoLaunch(WorldPacket& recvPacket); - void HandlePushQuestToParty(WorldPacket& recvPacket); - void HandleQuestPushResult(WorldPacket& recvPacket); - - bool processChatmessageFurtherAfterSecurityChecks(std::string&, uint32); - void HandleMessagechatOpcode(WorldPacket& recvPacket); - void SendPlayerNotFoundNotice(std::string name); - void SendPlayerAmbiguousNotice(std::string name); - void SendWrongFactionNotice(); - void SendChatRestrictedNotice(ChatRestrictionType restriction); - void HandleTextEmoteOpcode(WorldPacket& recvPacket); - void HandleChatIgnoredOpcode(WorldPacket& recvPacket); - - void HandleReclaimCorpseOpcode(WorldPacket& recvPacket); - void HandleCorpseQueryOpcode(WorldPacket& recvPacket); - void HandleCorpseMapPositionQuery(WorldPacket& recvPacket); - void HandleResurrectResponseOpcode(WorldPacket& recvPacket); - void HandleSummonResponseOpcode(WorldPacket& recv_data); - - void HandleJoinChannel(WorldPacket& recvPacket); - void HandleLeaveChannel(WorldPacket& recvPacket); - void HandleChannelList(WorldPacket& recvPacket); - void HandleChannelPassword(WorldPacket& recvPacket); - void HandleChannelSetOwner(WorldPacket& recvPacket); - void HandleChannelOwner(WorldPacket& recvPacket); - void HandleChannelModerator(WorldPacket& recvPacket); - void HandleChannelUnmoderator(WorldPacket& recvPacket); - void HandleChannelMute(WorldPacket& recvPacket); - void HandleChannelUnmute(WorldPacket& recvPacket); - void HandleChannelInvite(WorldPacket& recvPacket); - void HandleChannelKick(WorldPacket& recvPacket); - void HandleChannelBan(WorldPacket& recvPacket); - void HandleChannelUnban(WorldPacket& recvPacket); - void HandleChannelAnnouncements(WorldPacket& recvPacket); - void HandleChannelModerate(WorldPacket& recvPacket); - void HandleChannelDeclineInvite(WorldPacket& recvPacket); - void HandleChannelDisplayListQuery(WorldPacket& recvPacket); - void HandleGetChannelMemberCount(WorldPacket& recvPacket); - void HandleSetChannelWatch(WorldPacket& recvPacket); - - void HandleCompleteCinematic(WorldPacket& recvPacket); - void HandleNextCinematicCamera(WorldPacket& recvPacket); - - void HandlePageQuerySkippedOpcode(WorldPacket& recvPacket); - void HandlePageTextQueryOpcode(WorldPacket& recvPacket); - - void HandleTutorialFlag (WorldPacket & recv_data); - void HandleTutorialClear(WorldPacket & recv_data); - void HandleTutorialReset(WorldPacket & recv_data); - - //Pet - void HandlePetAction(WorldPacket & recv_data); - void HandlePetActionHelper(Unit *pet, uint64 guid1, uint16 spellid, uint16 flag, uint64 guid2); - void HandlePetNameQuery(WorldPacket & recv_data); - void HandlePetSetAction(WorldPacket & recv_data); - void HandlePetAbandon(WorldPacket & recv_data); - void HandlePetRename(WorldPacket & recv_data); - void HandlePetCancelAuraOpcode(WorldPacket& recvPacket); - void HandlePetUnlearnOpcode(WorldPacket& recvPacket); - void HandlePetSpellAutocastOpcode(WorldPacket& recvPacket); - void HandlePetCastSpellOpcode(WorldPacket& recvPacket); - void HandlePetLearnTalent(WorldPacket& recvPacket); - void HandleLearnPreviewTalentsPet(WorldPacket& recvPacket); - - void HandleSetActionBarToggles(WorldPacket& recv_data); - - void HandleCharRenameOpcode(WorldPacket& recv_data); - static void HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string newname); - void HandleSetPlayerDeclinedNames(WorldPacket& recv_data); - - void HandleTotemDestroyed(WorldPacket& recv_data); - void HandleDismissCritter(WorldPacket& recv_data); - - //BattleGround - void HandleBattlemasterHelloOpcode(WorldPacket &recv_data); - void HandleBattlemasterJoinOpcode(WorldPacket &recv_data); - void HandleBattleGroundPlayerPositionsOpcode(WorldPacket& recv_data); - void HandlePVPLogDataOpcode(WorldPacket &recv_data); - void HandleBattleFieldPortOpcode(WorldPacket &recv_data); - void HandleBattlefieldListOpcode(WorldPacket &recv_data); - void HandleLeaveBattlefieldOpcode(WorldPacket &recv_data); - void HandleBattlemasterJoinArena(WorldPacket &recv_data); - void HandleReportPvPAFK(WorldPacket &recv_data); - - void HandleWardenDataOpcode(WorldPacket& recv_data); - void HandleWorldTeleportOpcode(WorldPacket& recv_data); - void HandleMinimapPingOpcode(WorldPacket& recv_data); - void HandleRandomRollOpcode(WorldPacket& recv_data); - void HandleFarSightOpcode(WorldPacket& recv_data); - void HandleSetDungeonDifficultyOpcode(WorldPacket& recv_data); - void HandleSetRaidDifficultyOpcode(WorldPacket& recv_data); - void HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data); - void HandleSetTitleOpcode(WorldPacket& recv_data); - void HandleRealmSplitOpcode(WorldPacket& recv_data); - void HandleTimeSyncResp(WorldPacket& recv_data); - void HandleWhoisOpcode(WorldPacket& recv_data); - void HandleResetInstancesOpcode(WorldPacket& recv_data); - - // Looking for Dungeon/Raid - void HandleSetLfgCommentOpcode(WorldPacket & recv_data); - void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recv_data); - void HandleLfgPartyLockInfoRequestOpcode(WorldPacket& recv_data); - void HandleLfgJoinOpcode(WorldPacket &recv_data); - void HandleLfgLeaveOpcode(WorldPacket & /*recv_data*/); - void HandleLfgSetRolesOpcode(WorldPacket &recv_data); - void SendLfgUpdatePlayer(uint8 updateType); - void SendLfgUpdateParty(uint8 updateType); - void SendLfgRoleChosen(uint64 guid, uint8 roles); - void SendLfgUpdateSearch(bool update); - void SendLfgJoinResult(uint8 checkResult, uint8 checkValue); - void SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps); - - // Arena Team - void HandleInspectArenaTeamsOpcode(WorldPacket& recv_data); - void HandleArenaTeamQueryOpcode(WorldPacket& recv_data); - void HandleArenaTeamRosterOpcode(WorldPacket& recv_data); - void HandleArenaTeamInviteOpcode(WorldPacket& recv_data); - void HandleArenaTeamAcceptOpcode(WorldPacket& recv_data); - void HandleArenaTeamDeclineOpcode(WorldPacket& recv_data); - void HandleArenaTeamLeaveOpcode(WorldPacket& recv_data); - void HandleArenaTeamRemoveOpcode(WorldPacket& recv_data); - void HandleArenaTeamDisbandOpcode(WorldPacket& recv_data); - void HandleArenaTeamLeaderOpcode(WorldPacket& recv_data); - - void HandleAreaSpiritHealerQueryOpcode(WorldPacket& recv_data); - void HandleAreaSpiritHealerQueueOpcode(WorldPacket& recv_data); - void HandleCancelMountAuraOpcode(WorldPacket& recv_data); - void HandleSelfResOpcode(WorldPacket& recv_data); - void HandleComplainOpcode(WorldPacket& recv_data); - void HandleRequestPetInfoOpcode(WorldPacket& recv_data); - - // Socket gem - void HandleSocketOpcode(WorldPacket& recv_data); - - void HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data); - - void HandleItemRefundInfoRequest(WorldPacket& recv_data); - void HandleItemRefund(WorldPacket& recv_data); - - void HandleChannelVoiceOnOpcode(WorldPacket & recv_data); - void HandleVoiceSessionEnableOpcode(WorldPacket& recv_data); - void HandleSetActiveVoiceChannel(WorldPacket& recv_data); - void HandleSetTaxiBenchmarkOpcode(WorldPacket& recv_data); - - // Guild Bank - void HandleGuildPermissions(WorldPacket& recv_data); - void HandleGuildBankMoneyWithdrawn(WorldPacket& recv_data); - void HandleGuildBankerActivate(WorldPacket& recv_data); - void HandleGuildBankQueryTab(WorldPacket& recv_data); - void HandleGuildBankLogQuery(WorldPacket& recv_data); - void HandleGuildBankDepositMoney(WorldPacket& recv_data); - void HandleGuildBankWithdrawMoney(WorldPacket& recv_data); - void HandleGuildBankSwapItems(WorldPacket& recv_data); - - void HandleGuildBankUpdateTab(WorldPacket& recv_data); - void HandleGuildBankBuyTab(WorldPacket& recv_data); - void HandleQueryGuildBankTabText(WorldPacket& recv_data); - void HandleSetGuildBankTabText(WorldPacket& recv_data); - - // Calendar - void HandleCalendarGetCalendar(WorldPacket& recv_data); - void HandleCalendarGetEvent(WorldPacket& recv_data); - void HandleCalendarGuildFilter(WorldPacket& recv_data); - void HandleCalendarArenaTeam(WorldPacket& recv_data); - void HandleCalendarAddEvent(WorldPacket& recv_data); - void HandleCalendarUpdateEvent(WorldPacket& recv_data); - void HandleCalendarRemoveEvent(WorldPacket& recv_data); - void HandleCalendarCopyEvent(WorldPacket& recv_data); - void HandleCalendarEventInvite(WorldPacket& recv_data); - void HandleCalendarEventRsvp(WorldPacket& recv_data); - void HandleCalendarEventRemoveInvite(WorldPacket& recv_data); - void HandleCalendarEventStatus(WorldPacket& recv_data); - void HandleCalendarEventModeratorStatus(WorldPacket& recv_data); - void HandleCalendarComplain(WorldPacket& recv_data); - void HandleCalendarGetNumPending(WorldPacket& recv_data); - - void HandleSpellClick(WorldPacket& recv_data); - void HandleMirrrorImageDataRequest(WorldPacket & recv_data); - void HandleAlterAppearance(WorldPacket& recv_data); - void HandleRemoveGlyph(WorldPacket& recv_data); - void HandleCharCustomize(WorldPacket& recv_data); - void HandleQueryInspectAchievements(WorldPacket& recv_data); - void HandleEquipmentSetSave(WorldPacket& recv_data); - void HandleEquipmentSetDelete(WorldPacket& recv_data); - void HandleEquipmentSetUse(WorldPacket& recv_data); - void HandleWorldStateUITimerUpdate(WorldPacket& recv_data); - void HandleReadyForAccountDataTimes(WorldPacket& recv_data); - void HandleQueryQuestsCompleted(WorldPacket& recv_data); - void HandleQuestPOIQuery(WorldPacket& recv_data); - void HandleOnPVPKill(Player *killed); - bool HandleOnPlayerChat(const char *text); - uint32 HandleOnGetXP(uint32 amount); - int32 HandleOnGetMoney(int32 amount); - void HandleOnAreaChange(AreaTableEntry const *pArea); - bool HandleOnItemClick(Item *pItem); - bool HandleOnItemOpen(Item *pItem); - bool HandleOnGoClick(GameObject *pGameObject); - void HandleOnCreatureKill(Creature *pCreature); - void HandleEjectPasenger(WorldPacket &data); - void HandleEnterPlayerVehicle(WorldPacket &data); - private: - // private trade methods - void moveItems(Item* myItems[], Item* hisItems[]); - - // logging helper - void LogUnexpectedOpcode(WorldPacket *packet, const char * reason); - void LogUnprocessedTail(WorldPacket *packet); - - uint32 m_GUIDLow; // set loggined or recently logout player (while m_playerRecentlyLogout set) - Player *_player; - WorldSocket *m_Socket; - std::string m_Address; - - AccountTypes _security; - uint32 _accountId; - uint8 m_expansion; - - time_t _logoutTime; - bool m_inQueue; // session wait in auth.queue - bool m_playerLoading; // code processed in LoginPlayer - bool m_playerLogout; // code processed in LogoutPlayer - bool m_playerRecentlyLogout; - bool m_playerSave; - LocaleConstant m_sessionDbcLocale; - int m_sessionDbLocaleIndex; - uint32 m_latency; - AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES]; - uint32 m_Tutorials[8]; - bool m_TutorialsChanged; - AddonsList m_addonsList; - ACE_Based::LockedQueue _recvQueue; -}; -#endif -/// @} diff --git a/src/server/game/World/WorldSocket.cpp b/src/server/game/World/WorldSocket.cpp deleted file mode 100644 index c07b369d0b9..00000000000 --- a/src/server/game/World/WorldSocket.cpp +++ /dev/null @@ -1,1064 +0,0 @@ -/* -* Copyright (C) 2005-2009 MaNGOS -* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "WorldSocket.h" -#include "Common.h" - -#include "Util.h" -#include "World.h" -#include "WorldPacket.h" -#include "SharedDefines.h" -#include "ByteBuffer.h" -#include "Opcodes.h" -#include "Database/DatabaseEnv.h" -#include "Auth/BigNumber.h" -#include "Auth/Sha1.h" -#include "WorldSession.h" -#include "WorldSocketMgr.h" -#include "Log.h" -#include "WorldLog.h" - -#if defined(__GNUC__) -#pragma pack(1) -#else -#pragma pack(push,1) -#endif - -struct ServerPktHeader -{ - /** - * size is the length of the payload _plus_ the length of the opcode - */ - ServerPktHeader(uint32 size, uint16 cmd) : size(size) - { - uint8 headerIndex=0; - if (isLargePacket()) - { - sLog.outDebug("initializing large server to client packet. Size: %u, cmd: %u", size, cmd); - header[headerIndex++] = 0x80|(0xFF &(size>>16)); - } - header[headerIndex++] = 0xFF &(size>>8); - header[headerIndex++] = 0xFF &size; - - header[headerIndex++] = 0xFF & cmd; - header[headerIndex++] = 0xFF & (cmd>>8); - } - - uint8 getHeaderLength() - { - // cmd = 2 bytes, size= 2||3bytes - return 2+(isLargePacket()?3:2); - } - - bool isLargePacket() - { - return size > 0x7FFF; - } - - const uint32 size; - uint8 header[5]; -}; - -struct ClientPktHeader -{ - uint16 size; - uint32 cmd; -}; - -#if defined(__GNUC__) -#pragma pack() -#else -#pragma pack(pop) -#endif - -WorldSocket::WorldSocket (void) : -WorldHandler(), -m_Session(0), -m_RecvWPct(0), -m_RecvPct(), -m_Header(sizeof (ClientPktHeader)), -m_OutBuffer(0), -m_OutBufferSize(65536), -m_OutActive(false), -m_Seed(static_cast (rand32())), -m_OverSpeedPings(0), -m_LastPingTime(ACE_Time_Value::zero) -{ - reference_counting_policy().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); - - msg_queue()->high_water_mark(8*1024*1024); - msg_queue()->low_water_mark(8*1024*1024); -} - -WorldSocket::~WorldSocket (void) -{ - if (m_RecvWPct) - delete m_RecvWPct; - - if (m_OutBuffer) - m_OutBuffer->release(); - - closing_ = true; - - peer().close(); -} - -bool WorldSocket::IsClosed (void) const -{ - return closing_; -} - -void WorldSocket::CloseSocket (void) -{ - { - ACE_GUARD (LockType, Guard, m_OutBufferLock); - - if (closing_) - return; - - closing_ = true; - peer().close_writer(); - } - - { - ACE_GUARD (LockType, Guard, m_SessionLock); - - m_Session = NULL; - } -} - -const std::string& WorldSocket::GetRemoteAddress (void) const -{ - return m_Address; -} - -int WorldSocket::SendPacket (const WorldPacket& pct) -{ - ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); - - if (closing_) - return -1; - - // Dump outgoing packet. - if (sWorldLog.LogWorld()) - { - sWorldLog.outTimestampLog ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", - (uint32) get_handle(), - pct.size(), - LookupOpcodeName (pct.GetOpcode()), - pct.GetOpcode()); - - uint32 p = 0; - while (p < pct.size()) - { - for (uint32 j = 0; j < 16 && p < pct.size(); j++) - sWorldLog.outLog("%.2X ", const_cast(pct)[p++]); - - sWorldLog.outLog("\n"); - } - sWorldLog.outLog("\n"); - } - - ServerPktHeader header(pct.size()+2, pct.GetOpcode()); - m_Crypt.EncryptSend ((uint8*)header.header, header.getHeaderLength()); - - if (m_OutBuffer->space() >= pct.size() + header.getHeaderLength() && msg_queue()->is_empty()) - { - // Put the packet on the buffer. - if (m_OutBuffer->copy((char*) header.header, header.getHeaderLength()) == -1) - ACE_ASSERT (false); - - if (!pct.empty()) - if (m_OutBuffer->copy((char*) pct.contents(), pct.size()) == -1) - ACE_ASSERT (false); - } - else - { - // Enqueue the packet. - ACE_Message_Block* mb; - - ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size() + header.getHeaderLength()), -1); - - mb->copy((char*) header.header, header.getHeaderLength()); - - if (!pct.empty()) - mb->copy((const char*)pct.contents(), pct.size()); - - if (msg_queue()->enqueue_tail(mb,(ACE_Time_Value*)&ACE_Time_Value::zero) == -1) - { - sLog.outError("WorldSocket::SendPacket enqueue_tail failed"); - mb->release(); - return -1; - } - } - - return 0; -} - -long WorldSocket::AddReference (void) -{ - return static_cast (add_reference()); -} - -long WorldSocket::RemoveReference (void) -{ - return static_cast (remove_reference()); -} - -int WorldSocket::open (void *a) -{ - ACE_UNUSED_ARG (a); - - // Prevent double call to this func. - if (m_OutBuffer) - return -1; - - // This will also prevent the socket from being Updated - // while we are initializing it. - m_OutActive = true; - - // Hook for the manager. - if (sWorldSocketMgr->OnSocketOpen(this) == -1) - return -1; - - // Allocate the buffer. - ACE_NEW_RETURN (m_OutBuffer, ACE_Message_Block (m_OutBufferSize), -1); - - // Store peer address. - ACE_INET_Addr remote_addr; - - if (peer().get_remote_addr(remote_addr) == -1) - { - sLog.outError ("WorldSocket::open: peer().get_remote_addr errno = %s", ACE_OS::strerror (errno)); - return -1; - } - - m_Address = remote_addr.get_host_addr(); - - // Send startup packet. - WorldPacket packet (SMSG_AUTH_CHALLENGE, 24); - packet << uint32(1); // 1...31 - packet << m_Seed; - - BigNumber seed1; - seed1.SetRand(16 * 8); - packet.append(seed1.AsByteArray(16), 16); // new encryption seeds - - BigNumber seed2; - seed2.SetRand(16 * 8); - packet.append(seed2.AsByteArray(16), 16); // new encryption seeds - - if (SendPacket(packet) == -1) - return -1; - - // Register with ACE Reactor - if (reactor()->register_handler(this, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK) == -1) - { - sLog.outError ("WorldSocket::open: unable to register client handler errno = %s", ACE_OS::strerror (errno)); - return -1; - } - - // reactor takes care of the socket from now on - remove_reference(); - - return 0; -} - -int WorldSocket::close (int) -{ - shutdown(); - - closing_ = true; - - remove_reference(); - - return 0; -} - -int WorldSocket::handle_input (ACE_HANDLE) -{ - if (closing_) - return -1; - - switch (handle_input_missing_data()) - { - case -1 : - { - if ((errno == EWOULDBLOCK) || - (errno == EAGAIN)) - { - return Update(); // interesting line ,isn't it ? - } - - DEBUG_LOG("WorldSocket::handle_input: Peer error closing connection errno = %s", ACE_OS::strerror (errno)); - - errno = ECONNRESET; - return -1; - } - case 0: - { - DEBUG_LOG("WorldSocket::handle_input: Peer has closed connection"); - - errno = ECONNRESET; - return -1; - } - case 1: - return 1; - default: - return Update(); // another interesting line ;) - } - - ACE_NOTREACHED(return -1); -} - -int WorldSocket::handle_output (ACE_HANDLE) -{ - ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); - - if (closing_) - return -1; - - size_t send_len = m_OutBuffer->length(); - - if (send_len == 0) - return handle_output_queue(Guard); - -#ifdef MSG_NOSIGNAL - ssize_t n = peer().send (m_OutBuffer->rd_ptr(), send_len, MSG_NOSIGNAL); -#else - ssize_t n = peer().send (m_OutBuffer->rd_ptr(), send_len); -#endif // MSG_NOSIGNAL - - if (n == 0) - return -1; - else if (n == -1) - { - if (errno == EWOULDBLOCK || errno == EAGAIN) - return schedule_wakeup_output (Guard); - - return -1; - } - else if (n < (ssize_t)send_len) //now n > 0 - { - m_OutBuffer->rd_ptr (static_cast (n)); - - // move the data to the base of the buffer - m_OutBuffer->crunch(); - - return schedule_wakeup_output (Guard); - } - else //now n == send_len - { - m_OutBuffer->reset(); - - return handle_output_queue (Guard); - } - - ACE_NOTREACHED (return 0); -} - -int WorldSocket::handle_output_queue (GuardType& g) -{ - if (msg_queue()->is_empty()) - return cancel_wakeup_output(g); - - ACE_Message_Block *mblk; - - if (msg_queue()->dequeue_head(mblk, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) - { - sLog.outError("WorldSocket::handle_output_queue dequeue_head"); - return -1; - } - - const size_t send_len = mblk->length(); - -#ifdef MSG_NOSIGNAL - ssize_t n = peer().send (mblk->rd_ptr(), send_len, MSG_NOSIGNAL); -#else - ssize_t n = peer().send (mblk->rd_ptr(), send_len); -#endif // MSG_NOSIGNAL - - if (n == 0) - { - mblk->release(); - - return -1; - } - else if (n == -1) - { - if (errno == EWOULDBLOCK || errno == EAGAIN) - { - msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero); - return schedule_wakeup_output (g); - } - - mblk->release(); - return -1; - } - else if (n < (ssize_t)send_len) //now n > 0 - { - mblk->rd_ptr(static_cast (n)); - - if (msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero) == -1) - { - sLog.outError("WorldSocket::handle_output_queue enqueue_head"); - mblk->release(); - return -1; - } - - return schedule_wakeup_output (g); - } - else //now n == send_len - { - mblk->release(); - - return msg_queue()->is_empty() ? cancel_wakeup_output(g) : ACE_Event_Handler::WRITE_MASK; - } - - ACE_NOTREACHED(return -1); -} - -int WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask) -{ - // Critical section - { - ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); - - closing_ = true; - - if (h == ACE_INVALID_HANDLE) - peer().close_writer(); - } - - // Critical section - { - ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); - - m_Session = NULL; - } - - return 0; -} - -int WorldSocket::Update (void) -{ - if (closing_) - return -1; - - if (m_OutActive || (m_OutBuffer->length() == 0 && msg_queue()->is_empty())) - return 0; - - int ret; - do - ret = handle_output (get_handle()); - while (ret > 0); - - return ret; -} - -int WorldSocket::handle_input_header (void) -{ - ACE_ASSERT (m_RecvWPct == NULL); - - ACE_ASSERT (m_Header.length() == sizeof(ClientPktHeader)); - - m_Crypt.DecryptRecv ((uint8*) m_Header.rd_ptr(), sizeof(ClientPktHeader)); - - ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr()); - - EndianConvertReverse(header.size); - EndianConvert(header.cmd); - - if ((header.size < 4) || (header.size > 10240) || (header.cmd > 10240)) - { - sLog.outError ("WorldSocket::handle_input_header: client sent malformed packet size = %d , cmd = %d", - header.size, header.cmd); - - errno = EINVAL; - return -1; - } - - header.size -= 4; - - ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1); - - if (header.size > 0) - { - m_RecvWPct->resize (header.size); - m_RecvPct.base ((char*) m_RecvWPct->contents(), m_RecvWPct->size()); - } - else - { - ACE_ASSERT(m_RecvPct.space() == 0); - } - - return 0; -} - -int WorldSocket::handle_input_payload (void) -{ - // set errno properly here on error !!! - // now have a header and payload - - ACE_ASSERT (m_RecvPct.space() == 0); - ACE_ASSERT (m_Header.space() == 0); - ACE_ASSERT (m_RecvWPct != NULL); - - const int ret = ProcessIncoming (m_RecvWPct); - - m_RecvPct.base (NULL, 0); - m_RecvPct.reset(); - m_RecvWPct = NULL; - - m_Header.reset(); - - if (ret == -1) - errno = EINVAL; - - return ret; -} - -int WorldSocket::handle_input_missing_data (void) -{ - char buf [4096]; - - ACE_Data_Block db (sizeof (buf), - ACE_Message_Block::MB_DATA, - buf, - 0, - 0, - ACE_Message_Block::DONT_DELETE, - 0); - - ACE_Message_Block message_block(&db, - ACE_Message_Block::DONT_DELETE, - 0); - - const size_t recv_size = message_block.space(); - - const ssize_t n = peer().recv (message_block.wr_ptr(), - recv_size); - - if (n <= 0) - return n; - - message_block.wr_ptr (n); - - while (message_block.length() > 0) - { - if (m_Header.space() > 0) - { - //need to receive the header - const size_t to_header = (message_block.length() > m_Header.space() ? m_Header.space() : message_block.length()); - m_Header.copy (message_block.rd_ptr(), to_header); - message_block.rd_ptr (to_header); - - if (m_Header.space() > 0) - { - // Couldn't receive the whole header this time. - ACE_ASSERT (message_block.length() == 0); - errno = EWOULDBLOCK; - return -1; - } - - // We just received nice new header - if (handle_input_header() == -1) - { - ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); - return -1; - } - } - - // Its possible on some error situations that this happens - // for example on closing when epoll receives more chunked data and stuff - // hope this is not hack ,as proper m_RecvWPct is asserted around - if (!m_RecvWPct) - { - sLog.outError ("Forcing close on input m_RecvWPct = NULL"); - errno = EINVAL; - return -1; - } - - // We have full read header, now check the data payload - if (m_RecvPct.space() > 0) - { - //need more data in the payload - const size_t to_data = (message_block.length() > m_RecvPct.space() ? m_RecvPct.space() : message_block.length()); - m_RecvPct.copy (message_block.rd_ptr(), to_data); - message_block.rd_ptr (to_data); - - if (m_RecvPct.space() > 0) - { - // Couldn't receive the whole data this time. - ACE_ASSERT (message_block.length() == 0); - errno = EWOULDBLOCK; - return -1; - } - } - - //just received fresh new payload - if (handle_input_payload() == -1) - { - ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); - return -1; - } - } - - return n == recv_size ? 1 : 2; -} - -int WorldSocket::cancel_wakeup_output (GuardType& g) -{ - if (!m_OutActive) - return 0; - - m_OutActive = false; - - g.release(); - - if (reactor()->cancel_wakeup - (this, ACE_Event_Handler::WRITE_MASK) == -1) - { - // would be good to store errno from reactor with errno guard - sLog.outError ("WorldSocket::cancel_wakeup_output"); - return -1; - } - - return 0; -} - -int WorldSocket::schedule_wakeup_output (GuardType& g) -{ - if (m_OutActive) - return 0; - - m_OutActive = true; - - g.release(); - - if (reactor()->schedule_wakeup - (this, ACE_Event_Handler::WRITE_MASK) == -1) - { - sLog.outError ("WorldSocket::schedule_wakeup_output"); - return -1; - } - - return 0; -} - -int WorldSocket::ProcessIncoming (WorldPacket* new_pct) -{ - ACE_ASSERT (new_pct); - - // manage memory ;) - ACE_Auto_Ptr aptr (new_pct); - - const ACE_UINT16 opcode = new_pct->GetOpcode(); - - if (closing_) - return -1; - - // Dump received packet. - if (sWorldLog.LogWorld()) - { - sWorldLog.outTimestampLog ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", - (uint32) get_handle(), - new_pct->size(), - LookupOpcodeName (new_pct->GetOpcode()), - new_pct->GetOpcode()); - - uint32 p = 0; - while (p < new_pct->size()) - { - for (uint32 j = 0; j < 16 && p < new_pct->size(); j++) - sWorldLog.outLog ("%.2X ", (*new_pct)[p++]); - - sWorldLog.outLog ("\n"); - } - sWorldLog.outLog ("\n"); - } - - try { - switch(opcode) - { - case CMSG_PING: - return HandlePing (*new_pct); - case CMSG_AUTH_SESSION: - if (m_Session) - { - sLog.outError ("WorldSocket::ProcessIncoming: Player send CMSG_AUTH_SESSION again"); - return -1; - } - - return HandleAuthSession (*new_pct); - case CMSG_KEEP_ALIVE: - DEBUG_LOG ("CMSG_KEEP_ALIVE ,size: %d", new_pct->size()); - - return 0; - default: - { - ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); - - if (m_Session != NULL) - { - // Our Idle timer will reset on any non PING opcodes. - // Catches people idling on the login screen and any lingering ingame connections. - m_Session->ResetTimeOutTime(); - - // OK ,give the packet to WorldSession - aptr.release(); - // WARNINIG here we call it with locks held. - // Its possible to cause deadlock if QueuePacket calls back - m_Session->QueuePacket (new_pct); - return 0; - } - else - { - sLog.outError ("WorldSocket::ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); - return -1; - } - } - } - } - catch(ByteBufferException &) - { - sLog.outError("WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i. Disconnected client.", - opcode, GetRemoteAddress().c_str(), m_Session?m_Session->GetAccountId():-1); - if (sLog.IsOutDebug()) - { - sLog.outDebug("Dumping error causing packet:"); - new_pct->hexlike(); - } - - return -1; - } - - ACE_NOTREACHED (return 0); -} - -int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) -{ - // NOTE: ATM the socket is singlethread, have this in mind ... - uint8 digest[20]; - uint32 clientSeed; - uint32 unk2, unk3; - uint64 unk4; - uint32 BuiltNumberClient; - uint32 id, security; - //uint8 expansion = 0; - LocaleConstant locale; - std::string account; - Sha1Hash sha1; - BigNumber v, s, g, N; - WorldPacket packet, SendAddonPacked; - - BigNumber K; - - if (sWorld.IsClosed()) - { - packet.Initialize(SMSG_AUTH_RESPONSE, 1); - packet << uint8(AUTH_REJECT); - SendPacket (packet); - - sLog.outError ("WorldSocket::HandleAuthSession: World closed, denying client (%s).", m_Session->GetRemoteAddress().c_str()); - return -1; - } - - // Read the content of the packet - recvPacket >> BuiltNumberClient; // for now no use - recvPacket >> unk2; - recvPacket >> account; - recvPacket >> unk3; - recvPacket >> clientSeed; - recvPacket >> unk4; - recvPacket.read (digest, 20); - - DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u", - BuiltNumberClient, - unk2, - account.c_str(), - unk3, - clientSeed); - - // Get the account information from the realmd database - std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below - LoginDatabase.escape_string (safe_account); - // No SQL injection, username escaped. - - QueryResult_AutoPtr result = - LoginDatabase.PQuery ("SELECT " - "id, " //0 - "sessionkey, " //1 - "last_ip, " //2 - "locked, " //3 - "v, " //4 - "s, " //5 - "expansion, " //6 - "mutetime, " //7 - "locale " //8 - "FROM account " - "WHERE username = '%s'", - safe_account.c_str()); - - // Stop if the account is not found - if (!result) - { - packet.Initialize (SMSG_AUTH_RESPONSE, 1); - packet << uint8 (AUTH_UNKNOWN_ACCOUNT); - - SendPacket (packet); - - sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); - return -1; - } - - Field* fields = result->Fetch(); - - uint8 expansion = fields[6].GetUInt8(); - uint32 world_expansion = sWorld.getConfig(CONFIG_EXPANSION); - if (expansion > world_expansion) - expansion = world_expansion; - //expansion = ((sWorld.getConfig(CONFIG_EXPANSION) > fields[6].GetUInt8()) ? fields[6].GetUInt8() : sWorld.getConfig(CONFIG_EXPANSION)); - - N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); - g.SetDword (7); - - v.SetHexStr(fields[4].GetString()); - s.SetHexStr (fields[5].GetString()); - - const char* sStr = s.AsHexStr(); //Must be freed by OPENSSL_free() - const char* vStr = v.AsHexStr(); //Must be freed by OPENSSL_free() - - DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s", - sStr, - vStr); - - OPENSSL_free ((void*) sStr); - OPENSSL_free ((void*) vStr); - - ///- Re-check ip locking (same check as in realmd). - if (fields[3].GetUInt8() == 1) // if ip is locked - { - if (strcmp (fields[2].GetString(), GetRemoteAddress().c_str())) - { - packet.Initialize (SMSG_AUTH_RESPONSE, 1); - packet << uint8 (AUTH_FAILED); - SendPacket (packet); - - sLog.outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); - return -1; - } - } - - id = fields[0].GetUInt32(); - /* - if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB - security = SEC_ADMINISTRATOR; - */ - - K.SetHexStr (fields[1].GetString()); - - time_t mutetime = time_t (fields[7].GetUInt64()); - - locale = LocaleConstant (fields[8].GetUInt8()); - if (locale >= MAX_LOCALE) - locale = LOCALE_enUS; - - // Checks gmlevel per Realm - result = - LoginDatabase.PQuery ("SELECT " - "RealmID, " //0 - "gmlevel " //1 - "FROM account_access " - "WHERE id = '%d'" - " AND (RealmID = '%d'" - " OR RealmID = '-1')", - id, realmID); - if (!result) - security = 0; - else - { - fields = result->Fetch(); - security = fields[1].GetInt32(); - } - - // Re-check account ban (same check as in realmd) - QueryResult_AutoPtr banresult = - LoginDatabase.PQuery ("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 " - "UNION " - "SELECT 1 FROM ip_banned WHERE ip = '%s'", - id, GetRemoteAddress().c_str()); - - if (banresult) // if account banned - { - packet.Initialize (SMSG_AUTH_RESPONSE, 1); - packet << uint8 (AUTH_BANNED); - SendPacket (packet); - - sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); - return -1; - } - - // Check locked state for server - sWorld.UpdateAllowedSecurity(); - AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit(); - sLog.outDebug("Allowed Level: %u Player Level %u", allowedAccountType, AccountTypes(security)); - if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType) - { - WorldPacket Packet (SMSG_AUTH_RESPONSE, 1); - Packet << uint8 (AUTH_UNAVAILABLE); - - SendPacket (packet); - - sLog.outDetail ("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough"); - return -1; - } - - // Check that Key and account name are the same on client and server - Sha1Hash sha; - - uint32 t = 0; - uint32 seed = m_Seed; - - sha.UpdateData (account); - sha.UpdateData ((uint8 *) & t, 4); - sha.UpdateData ((uint8 *) & clientSeed, 4); - sha.UpdateData ((uint8 *) & seed, 4); - sha.UpdateBigNumbers (&K, NULL); - sha.Finalize(); - - if (memcmp (sha.GetDigest(), digest, 20)) - { - packet.Initialize (SMSG_AUTH_RESPONSE, 1); - packet << uint8 (AUTH_FAILED); - - SendPacket (packet); - - sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); - return -1; - } - - std::string address = GetRemoteAddress(); - - DEBUG_LOG ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", - account.c_str(), - address.c_str()); - - // Update the last_ip in the database - // No SQL injection, username escaped. - LoginDatabase.escape_string (address); - - LoginDatabase.PExecute ("UPDATE account " - "SET last_ip = '%s' " - "WHERE username = '%s'", - address.c_str(), - safe_account.c_str()); - - // NOTE ATM the socket is single-threaded, have this in mind ... - ACE_NEW_RETURN (m_Session, WorldSession (id, this, AccountTypes(security), expansion, mutetime, locale), -1); - - m_Crypt.Init(&K); - - m_Session->LoadGlobalAccountData(); - m_Session->LoadTutorialsData(); - m_Session->ReadAddonsInfo(recvPacket); - - // Sleep this Network thread for - uint32 sleepTime = sWorld.getConfig(CONFIG_SESSION_ADD_DELAY); - ACE_OS::sleep (ACE_Time_Value (0, sleepTime)); - - sWorld.AddSession (m_Session); - - return 0; -} - -int WorldSocket::HandlePing (WorldPacket& recvPacket) -{ - uint32 ping; - uint32 latency; - - // Get the ping packet content - recvPacket >> ping; - recvPacket >> latency; - - if (m_LastPingTime == ACE_Time_Value::zero) - m_LastPingTime = ACE_OS::gettimeofday(); // for 1st ping - else - { - ACE_Time_Value cur_time = ACE_OS::gettimeofday(); - ACE_Time_Value diff_time (cur_time); - diff_time -= m_LastPingTime; - m_LastPingTime = cur_time; - - if (diff_time < ACE_Time_Value (27)) - { - ++m_OverSpeedPings; - - uint32 max_count = sWorld.getConfig (CONFIG_MAX_OVERSPEED_PINGS); - - if (max_count && m_OverSpeedPings > max_count) - { - ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); - - if (m_Session && m_Session->GetSecurity() == SEC_PLAYER) - { - sLog.outError ("WorldSocket::HandlePing: Player kicked for " - "over-speed pings address = %s", - GetRemoteAddress().c_str()); - - return -1; - } - } - } - else - m_OverSpeedPings = 0; - } - - // critical section - { - ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); - - if (m_Session) - m_Session->SetLatency (latency); - else - { - sLog.outError ("WorldSocket::HandlePing: peer sent CMSG_PING, " - "but is not authenticated or got recently kicked," - " address = %s", - GetRemoteAddress().c_str()); - return -1; - } - } - - WorldPacket packet (SMSG_PONG, 4); - packet << ping; - return SendPacket (packet); -} diff --git a/src/server/game/World/WorldSocket.h b/src/server/game/World/WorldSocket.h deleted file mode 100644 index 70654274215..00000000000 --- a/src/server/game/World/WorldSocket.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \addtogroup u2w User to World Communication - * @{ - * \file WorldSocket.h - * \author Derex - */ - -#ifndef _WORLDSOCKET_H -#define _WORLDSOCKET_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -#pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "Common.h" -#include "Auth/AuthCrypt.h" - -class ACE_Message_Block; -class WorldPacket; -class WorldSession; - -/// Handler that can communicate over stream sockets. -typedef ACE_Svc_Handler WorldHandler; - -/** - * WorldSocket. - * - * This class is responsible for the communication with - * remote clients. - * Most methods return -1 on failure. - * The class uses reference counting. - * - * For output the class uses one buffer (64K usually) and - * a queue where it stores packet if there is no place on - * the queue. The reason this is done, is because the server - * does really a lot of small-size writes to it, and it doesn't - * scale well to allocate memory for every. When something is - * written to the output buffer the socket is not immediately - * activated for output (again for the same reason), there - * is 10ms celling (thats why there is Update() method). - * This concept is similar to TCP_CORK, but TCP_CORK - * uses 200ms celling. As result overhead generated by - * sending packets from "producer" threads is minimal, - * and doing a lot of writes with small size is tolerated. - * - * The calls to Update() method are managed by WorldSocketMgr - * and ReactorRunnable. - * - * For input ,the class uses one 1024 bytes buffer on stack - * to which it does recv() calls. And then received data is - * distributed where its needed. 1024 matches pretty well the - * traffic generated by client for now. - * - * The input/output do speculative reads/writes (AKA it tryes - * to read all data available in the kernel buffer or tryes to - * write everything available in userspace buffer), - * which is ok for using with Level and Edge Triggered IO - * notification. - * - */ -class WorldSocket : protected WorldHandler -{ - public: - /// Declare some friends - friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >; - friend class WorldSocketMgr; - friend class ReactorRunnable; - - /// Declare the acceptor for this class - typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor; - - /// Mutex type used for various synchronizations. - typedef ACE_Thread_Mutex LockType; - typedef ACE_Guard GuardType; - - /// Check if socket is closed. - bool IsClosed (void) const; - - /// Close the socket. - void CloseSocket (void); - - /// Get address of connected peer. - const std::string& GetRemoteAddress (void) const; - - /// Send A packet on the socket, this function is reentrant. - /// @param pct packet to send - /// @return -1 of failure - int SendPacket (const WorldPacket& pct); - - /// Add reference to this object. - long AddReference (void); - - /// Remove reference to this object. - long RemoveReference (void); - - protected: - /// things called by ACE framework. - WorldSocket (void); - virtual ~WorldSocket (void); - - /// Called on open ,the void* is the acceptor. - virtual int open (void *); - - /// Called on failures inside of the acceptor, don't call from your code. - virtual int close (int); - - /// Called when we can read from the socket. - virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE); - - /// Called when the socket can write. - virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE); - - /// Called when connection is closed or error happens. - virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, - ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); - - /// Called by WorldSocketMgr/ReactorRunnable. - int Update (void); - - private: - /// Helper functions for processing incoming data. - int handle_input_header (void); - int handle_input_payload (void); - int handle_input_missing_data (void); - - /// Help functions to mark/unmark the socket for output. - /// @param g the guard is for m_OutBufferLock, the function will release it - int cancel_wakeup_output (GuardType& g); - int schedule_wakeup_output (GuardType& g); - - /// Drain the queue if its not empty. - int handle_output_queue (GuardType& g); - - /// process one incoming packet. - /// @param new_pct received packet ,note that you need to delete it. - int ProcessIncoming (WorldPacket* new_pct); - - /// Called by ProcessIncoming() on CMSG_AUTH_SESSION. - int HandleAuthSession (WorldPacket& recvPacket); - - /// Called by ProcessIncoming() on CMSG_PING. - int HandlePing (WorldPacket& recvPacket); - - private: - /// Time in which the last ping was received - ACE_Time_Value m_LastPingTime; - - /// Keep track of over-speed pings ,to prevent ping flood. - uint32 m_OverSpeedPings; - - /// Address of the remote peer - std::string m_Address; - - /// Class used for managing encryption of the headers - AuthCrypt m_Crypt; - - /// Mutex lock to protect m_Session - LockType m_SessionLock; - - /// Session to which received packets are routed - WorldSession* m_Session; - - /// here are stored the fragments of the received data - WorldPacket* m_RecvWPct; - - /// This block actually refers to m_RecvWPct contents, - /// which allows easy and safe writing to it. - /// It wont free memory when its deleted. m_RecvWPct takes care of freeing. - ACE_Message_Block m_RecvPct; - - /// Fragment of the received header. - ACE_Message_Block m_Header; - - /// Mutex for protecting output related data. - LockType m_OutBufferLock; - - /// Buffer used for writing output. - ACE_Message_Block *m_OutBuffer; - - /// Size of the m_OutBuffer. - size_t m_OutBufferSize; - - /// True if the socket is registered with the reactor for output - bool m_OutActive; - - uint32 m_Seed; - -}; - -#endif /* _WORLDSOCKET_H */ - -/// @} - diff --git a/src/server/game/World/WorldSocketMgr.cpp b/src/server/game/World/WorldSocketMgr.cpp deleted file mode 100644 index c23d08e6f78..00000000000 --- a/src/server/game/World/WorldSocketMgr.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* -* Copyright (C) 2005-2008,2007 MaNGOS -* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/** \file WorldSocketMgr.cpp -* \ingroup u2w -* \author Derex -*/ - -#include "WorldSocketMgr.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Log.h" -#include "Common.h" -#include "Config/ConfigEnv.h" -#include "Database/DatabaseEnv.h" -#include "WorldSocket.h" - -/** -* This is a helper class to WorldSocketMgr ,that manages -* network threads, and assigning connections from acceptor thread -* to other network threads -*/ -class ReactorRunnable : protected ACE_Task_Base -{ - public: - - ReactorRunnable() : - m_ThreadId(-1), - m_Connections(0), - m_Reactor(0) - { - ACE_Reactor_Impl* imp = 0; - - #if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL) - - imp = new ACE_Dev_Poll_Reactor(); - - imp->max_notify_iterations (128); - imp->restart (1); - - #else - - imp = new ACE_TP_Reactor(); - imp->max_notify_iterations (128); - - #endif - - m_Reactor = new ACE_Reactor (imp, 1); - } - - virtual ~ReactorRunnable() - { - Stop(); - Wait(); - - if (m_Reactor) - delete m_Reactor; - } - - void Stop() - { - m_Reactor->end_reactor_event_loop(); - } - - int Start() - { - if (m_ThreadId != -1) - return -1; - - return (m_ThreadId = activate()); - } - - void Wait() { ACE_Task_Base::wait(); } - - long Connections() - { - return static_cast (m_Connections.value()); - } - - int AddSocket (WorldSocket* sock) - { - ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, m_NewSockets_Lock, -1); - - ++m_Connections; - sock->AddReference(); - sock->reactor (m_Reactor); - m_NewSockets.insert (sock); - - return 0; - } - - ACE_Reactor* GetReactor() - { - return m_Reactor; - } - - protected: - - void AddNewSockets() - { - ACE_GUARD (ACE_Thread_Mutex, Guard, m_NewSockets_Lock); - - if (m_NewSockets.empty()) - return; - - for (SocketSet::const_iterator i = m_NewSockets.begin(); i != m_NewSockets.end(); ++i) - { - WorldSocket* sock = (*i); - - if (sock->IsClosed()) - { - sock->RemoveReference(); - --m_Connections; - } - else - m_Sockets.insert (sock); - } - - m_NewSockets.clear(); - } - - virtual int svc() - { - DEBUG_LOG ("Network Thread Starting"); - - WorldDatabase.ThreadStart(); - - ACE_ASSERT (m_Reactor); - - SocketSet::iterator i, t; - - while (!m_Reactor->reactor_event_loop_done()) - { - // dont be too smart to move this outside the loop - // the run_reactor_event_loop will modify interval - ACE_Time_Value interval (0, 10000); - - if (m_Reactor->run_reactor_event_loop (interval) == -1) - break; - - AddNewSockets(); - - for (i = m_Sockets.begin(); i != m_Sockets.end();) - { - if ((*i)->Update() == -1) - { - t = i; - ++i; - (*t)->CloseSocket(); - (*t)->RemoveReference(); - --m_Connections; - m_Sockets.erase (t); - } - else - ++i; - } - } - - WorldDatabase.ThreadEnd(); - - DEBUG_LOG ("Network Thread Exitting"); - - return 0; - } - - private: - typedef ACE_Atomic_Op AtomicInt; - typedef std::set SocketSet; - - ACE_Reactor* m_Reactor; - AtomicInt m_Connections; - int m_ThreadId; - - SocketSet m_Sockets; - - SocketSet m_NewSockets; - ACE_Thread_Mutex m_NewSockets_Lock; -}; - -WorldSocketMgr::WorldSocketMgr() : - m_NetThreadsCount(0), - m_NetThreads(0), - m_SockOutKBuff(-1), - m_SockOutUBuff(65536), - m_UseNoDelay(true), - m_Acceptor (0) -{ -} - -WorldSocketMgr::~WorldSocketMgr() -{ - if (m_NetThreads) - delete [] m_NetThreads; - - if (m_Acceptor) - delete m_Acceptor; -} - -int -WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address) -{ - m_UseNoDelay = sConfig.GetBoolDefault ("Network.TcpNodelay", true); - - int num_threads = sConfig.GetIntDefault ("Network.Threads", 1); - - if (num_threads <= 0) - { - sLog.outError ("Network.Threads is wrong in your config file"); - return -1; - } - - m_NetThreadsCount = static_cast (num_threads + 1); - - m_NetThreads = new ReactorRunnable[m_NetThreadsCount]; - - sLog.outBasic ("Max allowed socket connections %d", ACE::max_handles()); - - // -1 means use default - m_SockOutKBuff = sConfig.GetIntDefault ("Network.OutKBuff", -1); - - m_SockOutUBuff = sConfig.GetIntDefault ("Network.OutUBuff", 65536); - - if (m_SockOutUBuff <= 0) - { - sLog.outError ("Network.OutUBuff is wrong in your config file"); - return -1; - } - - WorldSocket::Acceptor *acc = new WorldSocket::Acceptor; - m_Acceptor = acc; - - ACE_INET_Addr listen_addr (port, address); - - if (acc->open(listen_addr, m_NetThreads[0].GetReactor(), ACE_NONBLOCK) == -1) - { - sLog.outError ("Failed to open acceptor ,check if the port is free"); - return -1; - } - - for (size_t i = 0; i < m_NetThreadsCount; ++i) - m_NetThreads[i].Start(); - - return 0; -} - -int -WorldSocketMgr::StartNetwork (ACE_UINT16 port, const char* address) -{ - if (!sLog.IsOutDebug()) - ACE_Log_Msg::instance()->priority_mask (LM_ERROR, ACE_Log_Msg::PROCESS); - - if (StartReactiveIO(port, address) == -1) - return -1; - - return 0; -} - -void -WorldSocketMgr::StopNetwork() -{ - if (m_Acceptor) - { - WorldSocket::Acceptor* acc = dynamic_cast (m_Acceptor); - - if (acc) - acc->close(); - } - - if (m_NetThreadsCount != 0) - { - for (size_t i = 0; i < m_NetThreadsCount; ++i) - m_NetThreads[i].Stop(); - } - - Wait(); -} - -void -WorldSocketMgr::Wait() -{ - if (m_NetThreadsCount != 0) - { - for (size_t i = 0; i < m_NetThreadsCount; ++i) - m_NetThreads[i].Wait(); - } -} - -int -WorldSocketMgr::OnSocketOpen (WorldSocket* sock) -{ - // set some options here - if (m_SockOutKBuff >= 0) - { - if (sock->peer().set_option (SOL_SOCKET, - SO_SNDBUF, - (void*) & m_SockOutKBuff, - sizeof (int)) == -1 && errno != ENOTSUP) - { - sLog.outError ("WorldSocketMgr::OnSocketOpen set_option SO_SNDBUF"); - return -1; - } - } - - static const int ndoption = 1; - - // Set TCP_NODELAY. - if (m_UseNoDelay) - { - if (sock->peer().set_option (ACE_IPPROTO_TCP, - TCP_NODELAY, - (void*)&ndoption, - sizeof (int)) == -1) - { - sLog.outError ("WorldSocketMgr::OnSocketOpen: peer().set_option TCP_NODELAY errno = %s", ACE_OS::strerror (errno)); - return -1; - } - } - - sock->m_OutBufferSize = static_cast (m_SockOutUBuff); - - // we skip the Acceptor Thread - size_t min = 1; - - ACE_ASSERT (m_NetThreadsCount >= 1); - - for (size_t i = 1; i < m_NetThreadsCount; ++i) - if (m_NetThreads[i].Connections() < m_NetThreads[min].Connections()) - min = i; - - return m_NetThreads[min].AddSocket (sock); -} - -WorldSocketMgr* -WorldSocketMgr::Instance() -{ - return ACE_Singleton::instance(); -} - diff --git a/src/server/game/World/WorldSocketMgr.h b/src/server/game/World/WorldSocketMgr.h deleted file mode 100644 index 11345304962..00000000000 --- a/src/server/game/World/WorldSocketMgr.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \addtogroup u2w User to World Communication - * @{ - * \file WorldSocketMgr.h - * \author Derex - */ - -#ifndef __WORLDSOCKETMGR_H -#define __WORLDSOCKETMGR_H - -#include -#include -#include - -class WorldSocket; -class ReactorRunnable; -class ACE_Event_Handler; - -/// Manages all sockets connected to peers and network threads -class WorldSocketMgr -{ -public: - friend class WorldSocket; - friend class ACE_Singleton; - - /// Start network, listen at address:port . - int StartNetwork (ACE_UINT16 port, const char* address); - - /// Stops all network threads, It will wait for all running threads . - void StopNetwork(); - - /// Wait untill all network threads have "joined" . - void Wait(); - - /// Make this class singleton . - static WorldSocketMgr* Instance(); - -private: - int OnSocketOpen(WorldSocket* sock); - - int StartReactiveIO(ACE_UINT16 port, const char* address); - -private: - WorldSocketMgr(); - virtual ~WorldSocketMgr(); - - ReactorRunnable* m_NetThreads; - size_t m_NetThreadsCount; - - int m_SockOutKBuff; - int m_SockOutUBuff; - bool m_UseNoDelay; - - ACE_Event_Handler* m_Acceptor; -}; - -#define sWorldSocketMgr WorldSocketMgr::Instance() - -#endif -/// @} - -- cgit v1.2.3 From 2225a6bcf7af401a780d93dae43b903dba68c463 Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:00:52 +0200 Subject: * Rename some PCH files. --HG-- branch : trunk --- src/server/game/PrecompiledHeaders/NixCorePCH.cpp | 1 + src/server/game/PrecompiledHeaders/NixCorePCH.h | 12 ++++++++ src/server/game/PrecompiledHeaders/ScriptPCH.cpp | 6 ++++ src/server/game/PrecompiledHeaders/ScriptPCH.h | 32 ++++++++++++++++++++++ src/server/game/PrecompiledHeaders/ScriptedPch.cpp | 6 ---- src/server/game/PrecompiledHeaders/ScriptedPch.h | 32 ---------------------- src/server/game/PrecompiledHeaders/WinCorePCH.cpp | 1 + src/server/game/PrecompiledHeaders/WinCorePCH.h | 14 ++++++++++ src/server/game/PrecompiledHeaders/pchdef.cpp | 1 - src/server/game/PrecompiledHeaders/pchdef.h | 14 ---------- src/server/game/PrecompiledHeaders/pchlinux.cpp | 1 - src/server/game/PrecompiledHeaders/pchlinux.h | 12 -------- 12 files changed, 66 insertions(+), 66 deletions(-) create mode 100644 src/server/game/PrecompiledHeaders/NixCorePCH.cpp create mode 100644 src/server/game/PrecompiledHeaders/NixCorePCH.h create mode 100644 src/server/game/PrecompiledHeaders/ScriptPCH.cpp create mode 100644 src/server/game/PrecompiledHeaders/ScriptPCH.h delete mode 100644 src/server/game/PrecompiledHeaders/ScriptedPch.cpp delete mode 100644 src/server/game/PrecompiledHeaders/ScriptedPch.h create mode 100644 src/server/game/PrecompiledHeaders/WinCorePCH.cpp create mode 100644 src/server/game/PrecompiledHeaders/WinCorePCH.h delete mode 100644 src/server/game/PrecompiledHeaders/pchdef.cpp delete mode 100644 src/server/game/PrecompiledHeaders/pchdef.h delete mode 100644 src/server/game/PrecompiledHeaders/pchlinux.cpp delete mode 100644 src/server/game/PrecompiledHeaders/pchlinux.h (limited to 'src/server') diff --git a/src/server/game/PrecompiledHeaders/NixCorePCH.cpp b/src/server/game/PrecompiledHeaders/NixCorePCH.cpp new file mode 100644 index 00000000000..e588392689e --- /dev/null +++ b/src/server/game/PrecompiledHeaders/NixCorePCH.cpp @@ -0,0 +1 @@ +#include "pchdef.h" \ No newline at end of file diff --git a/src/server/game/PrecompiledHeaders/NixCorePCH.h b/src/server/game/PrecompiledHeaders/NixCorePCH.h new file mode 100644 index 00000000000..7252e980e7d --- /dev/null +++ b/src/server/game/PrecompiledHeaders/NixCorePCH.h @@ -0,0 +1,12 @@ +//add here most rarely modified headers to speed up debug build compilation +#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it +#include "Common.h" + +#include "MapManager.h" +#include "Log.h" +#include "ObjectAccessor.h" +#include "ObjectDefines.h" +#include "Database/SQLStorage.h" +#include "Opcodes.h" +#include "SharedDefines.h" +#include "ObjectMgr.h" diff --git a/src/server/game/PrecompiledHeaders/ScriptPCH.cpp b/src/server/game/PrecompiledHeaders/ScriptPCH.cpp new file mode 100644 index 00000000000..a80690d05da --- /dev/null +++ b/src/server/game/PrecompiledHeaders/ScriptPCH.cpp @@ -0,0 +1,6 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#include "ScriptedPch.h" + diff --git a/src/server/game/PrecompiledHeaders/ScriptPCH.h b/src/server/game/PrecompiledHeaders/ScriptPCH.h new file mode 100644 index 00000000000..1e83a88b87a --- /dev/null +++ b/src/server/game/PrecompiledHeaders/ScriptPCH.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_PRECOMPILED_H +#define SC_PRECOMPILED_H + +#include "ScriptMgr.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GameEventMgr.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Unit.h" +#include "GameObject.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "ScriptedInstance.h" +#include "CombatAI.h" +#include "PassiveAI.h" +#include "Chat.h" +#include "DBCStructure.h" +#include "DBCStores.h" +#include "ObjectMgr.h" + +#ifdef WIN32 +#include + +#endif + +#endif + diff --git a/src/server/game/PrecompiledHeaders/ScriptedPch.cpp b/src/server/game/PrecompiledHeaders/ScriptedPch.cpp deleted file mode 100644 index a80690d05da..00000000000 --- a/src/server/game/PrecompiledHeaders/ScriptedPch.cpp +++ /dev/null @@ -1,6 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#include "ScriptedPch.h" - diff --git a/src/server/game/PrecompiledHeaders/ScriptedPch.h b/src/server/game/PrecompiledHeaders/ScriptedPch.h deleted file mode 100644 index 1e83a88b87a..00000000000 --- a/src/server/game/PrecompiledHeaders/ScriptedPch.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef SC_PRECOMPILED_H -#define SC_PRECOMPILED_H - -#include "ScriptMgr.h" -#include "Cell.h" -#include "CellImpl.h" -#include "GameEventMgr.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "Unit.h" -#include "GameObject.h" -#include "ScriptedCreature.h" -#include "ScriptedGossip.h" -#include "ScriptedInstance.h" -#include "CombatAI.h" -#include "PassiveAI.h" -#include "Chat.h" -#include "DBCStructure.h" -#include "DBCStores.h" -#include "ObjectMgr.h" - -#ifdef WIN32 -#include - -#endif - -#endif - diff --git a/src/server/game/PrecompiledHeaders/WinCorePCH.cpp b/src/server/game/PrecompiledHeaders/WinCorePCH.cpp new file mode 100644 index 00000000000..e588392689e --- /dev/null +++ b/src/server/game/PrecompiledHeaders/WinCorePCH.cpp @@ -0,0 +1 @@ +#include "pchdef.h" \ No newline at end of file diff --git a/src/server/game/PrecompiledHeaders/WinCorePCH.h b/src/server/game/PrecompiledHeaders/WinCorePCH.h new file mode 100644 index 00000000000..cd1ea4a418a --- /dev/null +++ b/src/server/game/PrecompiledHeaders/WinCorePCH.h @@ -0,0 +1,14 @@ +//add here most rarely modified headers to speed up debug build compilation +#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it +#include "Common.h" + +#include "MapManager.h" +#include "Log.h" +#include "ObjectAccessor.h" +#include "ObjectDefines.h" +#include "Database/SQLStorage.h" +#include "Opcodes.h" +#include "SharedDefines.h" +#include "ObjectMgr.h" + +#include "ScriptedPch.h" \ No newline at end of file diff --git a/src/server/game/PrecompiledHeaders/pchdef.cpp b/src/server/game/PrecompiledHeaders/pchdef.cpp deleted file mode 100644 index e588392689e..00000000000 --- a/src/server/game/PrecompiledHeaders/pchdef.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pchdef.h" \ No newline at end of file diff --git a/src/server/game/PrecompiledHeaders/pchdef.h b/src/server/game/PrecompiledHeaders/pchdef.h deleted file mode 100644 index cd1ea4a418a..00000000000 --- a/src/server/game/PrecompiledHeaders/pchdef.h +++ /dev/null @@ -1,14 +0,0 @@ -//add here most rarely modified headers to speed up debug build compilation -#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it -#include "Common.h" - -#include "MapManager.h" -#include "Log.h" -#include "ObjectAccessor.h" -#include "ObjectDefines.h" -#include "Database/SQLStorage.h" -#include "Opcodes.h" -#include "SharedDefines.h" -#include "ObjectMgr.h" - -#include "ScriptedPch.h" \ No newline at end of file diff --git a/src/server/game/PrecompiledHeaders/pchlinux.cpp b/src/server/game/PrecompiledHeaders/pchlinux.cpp deleted file mode 100644 index e588392689e..00000000000 --- a/src/server/game/PrecompiledHeaders/pchlinux.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pchdef.h" \ No newline at end of file diff --git a/src/server/game/PrecompiledHeaders/pchlinux.h b/src/server/game/PrecompiledHeaders/pchlinux.h deleted file mode 100644 index 7252e980e7d..00000000000 --- a/src/server/game/PrecompiledHeaders/pchlinux.h +++ /dev/null @@ -1,12 +0,0 @@ -//add here most rarely modified headers to speed up debug build compilation -#include "WorldSocket.h" // must be first to make ACE happy with ACE includes in it -#include "Common.h" - -#include "MapManager.h" -#include "Log.h" -#include "ObjectAccessor.h" -#include "ObjectDefines.h" -#include "Database/SQLStorage.h" -#include "Opcodes.h" -#include "SharedDefines.h" -#include "ObjectMgr.h" -- cgit v1.2.3 From f27daddd1b95616b7e68bc384eeffb3c62e9bdd2 Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:08:23 +0200 Subject: * Restructuring authserver and worldserver. --HG-- branch : trunk --- src/server/authserver/Authentication/AuthCodes.cpp | 37 + src/server/authserver/Authentication/AuthCodes.h | 97 ++ src/server/authserver/Realms/RealmList.cpp | 100 ++ src/server/authserver/Realms/RealmList.h | 79 ++ src/server/authserver/Server/AuthSocket.cpp | 1069 ++++++++++++++++++++ src/server/authserver/Server/AuthSocket.h | 97 ++ src/server/authserver/Server/RealmAcceptor.h | 52 + src/server/authserver/Server/RealmSocket.cpp | 324 ++++++ src/server/authserver/Server/RealmSocket.h | 85 ++ src/server/worldserver/CommandLine/CliRunnable.cpp | 445 ++++++++ src/server/worldserver/CommandLine/CliRunnable.h | 35 + src/server/worldserver/RemoteAccess/RASocket.cpp | 265 +++++ src/server/worldserver/RemoteAccess/RASocket.h | 68 ++ .../worldserver/WorldThread/WorldRunnable.cpp | 97 ++ src/server/worldserver/WorldThread/WorldRunnable.h | 35 + 15 files changed, 2885 insertions(+) create mode 100644 src/server/authserver/Authentication/AuthCodes.cpp create mode 100644 src/server/authserver/Authentication/AuthCodes.h create mode 100644 src/server/authserver/Realms/RealmList.cpp create mode 100644 src/server/authserver/Realms/RealmList.h create mode 100644 src/server/authserver/Server/AuthSocket.cpp create mode 100644 src/server/authserver/Server/AuthSocket.h create mode 100644 src/server/authserver/Server/RealmAcceptor.h create mode 100644 src/server/authserver/Server/RealmSocket.cpp create mode 100644 src/server/authserver/Server/RealmSocket.h create mode 100644 src/server/worldserver/CommandLine/CliRunnable.cpp create mode 100644 src/server/worldserver/CommandLine/CliRunnable.h create mode 100644 src/server/worldserver/RemoteAccess/RASocket.cpp create mode 100644 src/server/worldserver/RemoteAccess/RASocket.h create mode 100644 src/server/worldserver/WorldThread/WorldRunnable.cpp create mode 100644 src/server/worldserver/WorldThread/WorldRunnable.h (limited to 'src/server') diff --git a/src/server/authserver/Authentication/AuthCodes.cpp b/src/server/authserver/Authentication/AuthCodes.cpp new file mode 100644 index 00000000000..812949e0823 --- /dev/null +++ b/src/server/authserver/Authentication/AuthCodes.cpp @@ -0,0 +1,37 @@ +#include "AuthCodes.h" + +namespace AuthHelper +{ + +bool IsPreBCAcceptedClientBuild(int build) +{ + int accepted_versions[] = PRE_BC_ACCEPTED_CLIENT_BUILD; + for (int i = 0; accepted_versions[i]; ++i) + { + if (build == accepted_versions[i]) + { + return true; + } + } + return false; +} + +bool IsPostBCAcceptedClientBuild(int build) +{ + int accepted_versions[] = POST_BC_ACCEPTED_CLIENT_BUILD; + for (int i = 0; accepted_versions[i]; ++i) + { + if (build == accepted_versions[i]) + { + return true; + } + } + return false; +} + +bool IsAcceptedClientBuild(int build) +{ + return (IsPostBCAcceptedClientBuild(build) || IsPreBCAcceptedClientBuild(build)); +} + +}; diff --git a/src/server/authserver/Authentication/AuthCodes.h b/src/server/authserver/Authentication/AuthCodes.h new file mode 100644 index 00000000000..eb6e4abfb08 --- /dev/null +++ b/src/server/authserver/Authentication/AuthCodes.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#ifndef _AUTHCODES_H +#define _AUTHCODES_H + +enum AuthResult +{ + WOW_SUCCESS = 0x00, + WOW_FAIL_UNKNOWN0 = 0x01, ///< ? Unable to connect + WOW_FAIL_UNKNOWN1 = 0x02, ///< ? Unable to connect + WOW_FAIL_BANNED = 0x03, ///< This account has been closed and is no longer available for use. Please go to /banned.html for further information. + WOW_FAIL_UNKNOWN_ACCOUNT = 0x04, ///< The information you have entered is not valid. Please check the spelling of the account name and password. If you need help in retrieving a lost or stolen password, see for more information + WOW_FAIL_INCORRECT_PASSWORD = 0x05, ///< The information you have entered is not valid. Please check the spelling of the account name and password. If you need help in retrieving a lost or stolen password, see for more information + WOW_FAIL_ALREADY_ONLINE = 0x06, ///< This account is already logged into . Please check the spelling and try again. + WOW_FAIL_NO_TIME = 0x07, ///< You have used up your prepaid time for this account. Please purchase more to continue playing + WOW_FAIL_DB_BUSY = 0x08, ///< Could not log in to at this time. Please try again later. + WOW_FAIL_VERSION_INVALID = 0x09, ///< Unable to validate game version. This may be caused by file corruption or interference of another program. Please visit for more information and possible solutions to this issue. + WOW_FAIL_VERSION_UPDATE = 0x0A, ///< Downloading + WOW_FAIL_INVALID_SERVER = 0x0B, ///< Unable to connect + WOW_FAIL_SUSPENDED = 0x0C, ///< This account has been temporarily suspended. Please go to /banned.html for further information + WOW_FAIL_FAIL_NOACCESS = 0x0D, ///< Unable to connect + WOW_SUCCESS_SURVEY = 0x0E, ///< Connected. + WOW_FAIL_PARENTCONTROL = 0x0F, ///< Access to this account has been blocked by parental controls. Your settings may be changed in your account preferences at + WOW_FAIL_LOCKED_ENFORCED = 0x10, ///< You have applied a lock to your account. You can change your locked status by calling your account lock phone number. + WOW_FAIL_TRIAL_ENDED = 0x11, ///< Your trial subscription has expired. Please visit to upgrade your account. + WOW_FAIL_USE_BATTLENET = 0x12, ///< WOW_FAIL_OTHER This account is now attached to a Battle.net account. Please login with your Battle.net account email address and password. +}; + +enum LoginResult +{ + LOGIN_OK = 0x00, + LOGIN_FAILED = 0x01, + LOGIN_FAILED2 = 0x02, + LOGIN_BANNED = 0x03, + LOGIN_UNKNOWN_ACCOUNT = 0x04, + LOGIN_UNKNOWN_ACCOUNT3 = 0x05, + LOGIN_ALREADYONLINE = 0x06, + LOGIN_NOTIME = 0x07, + LOGIN_DBBUSY = 0x08, + LOGIN_BADVERSION = 0x09, + LOGIN_DOWNLOAD_FILE = 0x0A, + LOGIN_FAILED3 = 0x0B, + LOGIN_SUSPENDED = 0x0C, + LOGIN_FAILED4 = 0x0D, + LOGIN_CONNECTED = 0x0E, + LOGIN_PARENTALCONTROL = 0x0F, + LOGIN_LOCKED_ENFORCED = 0x10, +}; + +//multirealm supported versions: +//1.12.1 build 5875 +//1.12.2 build 6005 +//2.4.3 build 8606 +//3.1.3 build 9947 +//3.1.3 build 10146 Chinese build +//3.2.2a build 10505 +//3.3.0a build 11159 +//3.3.2 build 11403 +//3.3.3a build 11723 + +#define POST_BC_ACCEPTED_CLIENT_BUILD {11723, 11403, 11159, 10571, 10505, 10146, 9947, 8606, 0} +#define PRE_BC_ACCEPTED_CLIENT_BUILD {5875, 6005, 0} + +#define POST_BC_EXP_FLAG 0x2 +#define PRE_BC_EXP_FLAG 0x1 +#define NO_VALID_EXP_FLAG 0x0 + +namespace AuthHelper +{ + bool IsAcceptedClientBuild(int build); + bool IsPostBCAcceptedClientBuild(int build); + bool IsPreBCAcceptedClientBuild(int build); +}; + +#endif diff --git a/src/server/authserver/Realms/RealmList.cpp b/src/server/authserver/Realms/RealmList.cpp new file mode 100644 index 00000000000..1e989c36c5d --- /dev/null +++ b/src/server/authserver/Realms/RealmList.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#include "Common.h" +#include "RealmList.h" +#include "Database/DatabaseEnv.h" + + +extern DatabaseType LoginDatabase; + +RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)) +{ +} + +/// Load the realm list from the database +void RealmList::Initialize(uint32 updateInterval) +{ + m_UpdateInterval = updateInterval; + + ///- Get the content of the realmlist table in the database + UpdateRealms(true); +} + +void RealmList::UpdateRealm(uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build) +{ + ///- Create new if not exist or update existed + Realm& realm = m_realms[name]; + + realm.m_ID = ID; + realm.name = name; + realm.icon = icon; + realm.color = color; + realm.timezone = timezone; + realm.allowedSecurityLevel = allowedSecurityLevel; + realm.populationLevel = popu; + + ///- Append port to IP address. + std::ostringstream ss; + ss << address << ":" << port; + realm.address = ss.str(); + realm.gamebuild = build; +} + +void RealmList::UpdateIfNeed() +{ + // maybe disabled or updated recently + if (!m_UpdateInterval || m_NextUpdateTime > time(NULL)) + return; + + m_NextUpdateTime = time(NULL) + m_UpdateInterval; + + // Clears Realm list + m_realms.clear(); + + // Get the content of the realmlist table in the database + UpdateRealms(false); +} + +void RealmList::UpdateRealms(bool init) +{ + sLog.outDetail("Updating Realm List..."); + + QueryResult_AutoPtr result = LoginDatabase.Query("SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE color <> 3 ORDER BY name"); + + ///- Circle through results and add them to the realm map + if (result) + { + do + { + Field *fields = result->Fetch(); + + uint8 allowedSecurityLevel = fields[7].GetUInt8(); + + UpdateRealm(fields[0].GetUInt32(), fields[1].GetCppString(),fields[2].GetCppString(),fields[3].GetUInt32(),fields[4].GetUInt8(), fields[5].GetUInt8(), fields[6].GetUInt8(), (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), fields[8].GetFloat(), fields[9].GetUInt32()); + if (init) + sLog.outString("Added realm \"%s\".", fields[1].GetString()); + } while(result->NextRow()); + } +} diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/authserver/Realms/RealmList.h new file mode 100644 index 00000000000..b29b561c797 --- /dev/null +++ b/src/server/authserver/Realms/RealmList.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup realmd +/// @{ +/// \file + +#ifndef _REALMLIST_H +#define _REALMLIST_H + +#include +#include +#include "Common.h" + +/// Storage object for a realm +struct Realm +{ + std::string address; + std::string name; + uint8 icon; + uint8 color; + uint8 timezone; + uint32 m_ID; + AccountTypes allowedSecurityLevel; + float populationLevel; + uint32 gamebuild; +}; + +/// Storage object for the list of realms on the server +class RealmList +{ + public: + // Null_Mutex is safe because the singleton initialized before the acceptor initialized(another place where the singleton called) + static RealmList* instance() { return ACE_Singleton::instance(); } + + typedef std::map RealmMap; + + RealmList(); + ~RealmList() {} + + void Initialize(uint32 updateInterval); + + void UpdateIfNeed(); + + void AddRealm(Realm NewRealm) {m_realms[NewRealm.name] = NewRealm;} + + RealmMap::const_iterator begin() const { return m_realms.begin(); } + RealmMap::const_iterator end() const { return m_realms.end(); } + uint32 size() const { return m_realms.size(); } + private: + void UpdateRealms(bool init); + void UpdateRealm(uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build); + private: + RealmMap m_realms; ///< Internal map of realms + uint32 m_UpdateInterval; + time_t m_NextUpdateTime; +}; + +#define sRealmList RealmList::instance() + +#endif +/// @} diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp new file mode 100644 index 00000000000..cc293097977 --- /dev/null +++ b/src/server/authserver/Server/AuthSocket.cpp @@ -0,0 +1,1069 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "ByteBuffer.h" +#include "Config/ConfigEnv.h" +#include "Log.h" +#include "RealmList.h" +#include "AuthSocket.h" +#include "AuthCodes.h" +#include +#include "Auth/Sha1.h" +//#include "Util.h" -- for commented utf8ToUpperOnlyLatin + +extern DatabaseType LoginDatabase; + +#define ChunkSize 2048 + +enum eAuthCmd +{ + //AUTH_NO_CMD = 0xFF, + AUTH_LOGON_CHALLENGE = 0x00, + AUTH_LOGON_PROOF = 0x01, + AUTH_RECONNECT_CHALLENGE = 0x02, + AUTH_RECONNECT_PROOF = 0x03, + //update srv =4 + REALM_LIST = 0x10, + XFER_INITIATE = 0x30, + XFER_DATA = 0x31, + XFER_ACCEPT = 0x32, + XFER_RESUME = 0x33, + XFER_CANCEL = 0x34 +}; + +enum eStatus +{ + STATUS_CONNECTED = 0, + STATUS_AUTHED +}; + +// 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 paltform +#if defined(__GNUC__) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +typedef struct AUTH_LOGON_CHALLENGE_C +{ + uint8 cmd; + uint8 error; + uint16 size; + uint8 gamename[4]; + uint8 version1; + uint8 version2; + uint8 version3; + uint16 build; + uint8 platform[4]; + uint8 os[4]; + uint8 country[4]; + uint32 timezone_bias; + uint32 ip; + uint8 I_len; + uint8 I[1]; +} sAuthLogonChallenge_C; + +typedef struct AUTH_LOGON_PROOF_C +{ + uint8 cmd; + uint8 A[32]; + uint8 M1[20]; + uint8 crc_hash[20]; + uint8 number_of_keys; + uint8 securityFlags; // 0x00-0x04 +} sAuthLogonProof_C; + +typedef struct AUTH_LOGON_PROOF_S +{ + uint8 cmd; + uint8 error; + uint8 M2[20]; + uint32 unk1; + uint32 unk2; + uint16 unk3; +} sAuthLogonProof_S; + +typedef struct AUTH_LOGON_PROOF_S_OLD +{ + uint8 cmd; + uint8 error; + uint8 M2[20]; + //uint32 unk1; + uint32 unk2; + //uint16 unk3; +} sAuthLogonProof_S_Old; + +typedef struct AUTH_RECONNECT_PROOF_C +{ + uint8 cmd; + uint8 R1[16]; + uint8 R2[20]; + uint8 R3[20]; + uint8 number_of_keys; +} sAuthReconnectProof_C; + +typedef struct XFER_INIT +{ + uint8 cmd; // XFER_INITIATE + uint8 fileNameLen; // strlen(fileName); + uint8 fileName[5]; // fileName[fileNameLen] + uint64 file_size; // file size (bytes) + uint8 md5[MD5_DIGEST_LENGTH]; // MD5 +} XFER_INIT; + +typedef struct XFER_DATA +{ + uint8 opcode; + uint16 data_size; + uint8 data[ChunkSize]; +} XFER_DATA_STRUCT; + +typedef struct AuthHandler +{ + eAuthCmd cmd; + uint32 status; + bool (AuthSocket::*handler)(void); +} AuthHandler; + +// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some paltform +#if defined(__GNUC__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +/// Launch a thread to transfer a patch to the client +class PatcherRunnable: public ACE_Based::Runnable +{ + public: + PatcherRunnable(class AuthSocket *); + void run(); + + private: + AuthSocket * mySocket; +}; + +typedef struct PATCH_INFO +{ + uint8 md5[MD5_DIGEST_LENGTH]; +} PATCH_INFO; + +/// Caches MD5 hash of client patches present on the server +class Patcher +{ + public: + typedef std::map Patches; + ~Patcher(); + Patcher(); + Patches::const_iterator begin() const { return _patches.begin(); } + Patches::const_iterator end() const { return _patches.end(); } + void LoadPatchMD5(char*); + bool GetHash(char * pat,uint8 mymd5[16]); + + private: + void LoadPatchesInfo(); + Patches _patches; +}; + +const AuthHandler table[] = +{ + { AUTH_LOGON_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleLogonChallenge }, + { AUTH_LOGON_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleLogonProof }, + { AUTH_RECONNECT_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleReconnectChallenge}, + { AUTH_RECONNECT_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleReconnectProof }, + { REALM_LIST, STATUS_AUTHED, &AuthSocket::_HandleRealmList }, + { XFER_ACCEPT, STATUS_CONNECTED, &AuthSocket::_HandleXferAccept }, + { XFER_RESUME, STATUS_CONNECTED, &AuthSocket::_HandleXferResume }, + { XFER_CANCEL, STATUS_CONNECTED, &AuthSocket::_HandleXferCancel } +}; + +#define AUTH_TOTAL_COMMANDS sizeof(table)/sizeof(AuthHandler) + +///Holds the MD5 hash of client patches present on the server +Patcher PatchesCache; + +/// Constructor - set the N and g values for SRP6 +AuthSocket::AuthSocket(RealmSocket& socket) : socket_(socket) +{ + N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); + g.SetDword(7); + _authed = false; + _accountSecurityLevel = SEC_PLAYER; +} + +/// Close patch file descriptor before leaving +AuthSocket::~AuthSocket(void) +{ +} + +/// Accept the connection and set the s random value for SRP6 +void AuthSocket::OnAccept(void) +{ + sLog.outBasic("Accepting connection from '%s'", socket().get_remote_address().c_str()); +} + +void AuthSocket::OnClose(void) +{ + sLog.outDebug("AuthSocket::OnClose"); +} + +/// Read the packet from the client +void AuthSocket::OnRead() +{ + uint8 _cmd; + while (1) + { + if (!socket().recv_soft((char *)&_cmd, 1)) + return; + + size_t i; + + ///- Circle through known commands and call the correct command handler + for (i = 0; i < AUTH_TOTAL_COMMANDS; ++i) + { + if ((uint8)table[i].cmd == _cmd && + (table[i].status == STATUS_CONNECTED || + (_authed && table[i].status == STATUS_AUTHED))) + { + DEBUG_LOG("[Auth] got data for cmd %u recv length %u", (uint32)_cmd, (uint32)socket().recv_len()); + + if (!(*this.*table[i].handler)()) + { + DEBUG_LOG("Command handler failed for cmd %u recv length %u", (uint32)_cmd, (uint32)socket().recv_len()); + return; + } + break; + } + } + + // Report unknown packets in the error log + if (i == AUTH_TOTAL_COMMANDS) + { + sLog.outError("[Auth] got unknown packet from '%s'", socket().get_remote_address().c_str()); + socket().shutdown(); + return; + } + } +} + +/// Make the SRP6 calculation from hash in dB +void AuthSocket::_SetVSFields(const std::string& rI) +{ + s.SetRand(s_BYTE_SIZE * 8); + + BigNumber I; + I.SetHexStr(rI.c_str()); + + // In case of leading zeros in the rI hash, restore them + uint8 mDigest[SHA_DIGEST_LENGTH]; + memset(mDigest, 0, SHA_DIGEST_LENGTH); + if (I.GetNumBytes() <= SHA_DIGEST_LENGTH) + memcpy(mDigest, I.AsByteArray(), I.GetNumBytes()); + + std::reverse(mDigest, mDigest + SHA_DIGEST_LENGTH); + + Sha1Hash sha; + sha.UpdateData(s.AsByteArray(), s.GetNumBytes()); + sha.UpdateData(mDigest, SHA_DIGEST_LENGTH); + sha.Finalize(); + BigNumber x; + x.SetBinary(sha.GetDigest(), sha.GetLength()); + v = g.ModExp(x, N); + // No SQL injection (username escaped) + const char *v_hex, *s_hex; + v_hex = v.AsHexStr(); + s_hex = s.AsHexStr(); + LoginDatabase.PExecute("UPDATE account SET v = '%s', s = '%s' WHERE username = '%s'", v_hex, s_hex, _safelogin.c_str()); + OPENSSL_free((void*)v_hex); + OPENSSL_free((void*)s_hex); +} + +/// Logon Challenge command handler +bool AuthSocket::_HandleLogonChallenge() +{ + DEBUG_LOG("Entering _HandleLogonChallenge"); + if (socket().recv_len() < sizeof(sAuthLogonChallenge_C)) + return false; + + ///- Read the first 4 bytes (header) to get the length of the remaining of the packet + std::vector buf; + buf.resize(4); + + socket().recv((char *)&buf[0], 4); + + EndianConvert(*((uint16*)(buf[0]))); + uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; + DEBUG_LOG("[AuthChallenge] got header, body is %#04x bytes", remaining); + + if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (socket().recv_len() < remaining)) + return false; + + //No big fear of memory outage (size is int16, i.e. < 65536) + buf.resize(remaining + buf.size() + 1); + buf[buf.size() - 1] = 0; + sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; + + ///- Read the remaining of the packet + socket().recv((char *)&buf[4], remaining); + DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size); + DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I); + + // BigEndian code, nop in little endian case + // size already converted + EndianConvert(*((uint32*)(&ch->gamename[0]))); + EndianConvert(ch->build); + EndianConvert(*((uint32*)(&ch->platform[0]))); + EndianConvert(*((uint32*)(&ch->os[0]))); + EndianConvert(*((uint32*)(&ch->country[0]))); + EndianConvert(ch->timezone_bias); + EndianConvert(ch->ip); + + ByteBuffer pkt; + + _login = (const char*)ch->I; + _build = ch->build; + _expversion = (AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : NO_VALID_EXP_FLAG) + (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG); + + ///- Normalize account name + //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form + + //Escape the user login to avoid further SQL injection + //Memory will be freed on AuthSocket object destruction + _safelogin = _login; + LoginDatabase.escape_string(_safelogin); + + _build = ch->build; + + pkt << (uint8) AUTH_LOGON_CHALLENGE; + pkt << (uint8) 0x00; + + ///- Verify that this IP is not in the ip_banned table + // No SQL injection possible (paste the IP address as passed by the socket) + LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + + std::string address(socket().get_remote_address().c_str()); + LoginDatabase.escape_string(address); + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); + if (result) + { + pkt << (uint8)WOW_FAIL_BANNED; + sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!", address.c_str ()); + } + else + { + ///- Get the account details from the account table + // No SQL injection (escaped user name) + + result = LoginDatabase.PQuery("SELECT a.sha_pass_hash,a.id,a.locked,a.last_ip,aa.gmlevel,a.v,a.s " + "FROM account a " + "LEFT JOIN account_access aa " + "ON (a.id = aa.id) " + "WHERE a.username = '%s'",_safelogin.c_str ()); + if (result) + { + ///- If the IP is 'locked', check that the player comes indeed from the correct IP address + bool locked = false; + if ((*result)[2].GetUInt8() == 1) // if ip is locked + { + DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); + DEBUG_LOG("[AuthChallenge] Player address is '%s'", socket().get_remote_address().c_str()); + if (strcmp((*result)[3].GetString(),socket().get_remote_address().c_str())) + { + DEBUG_LOG("[AuthChallenge] Account IP differs"); + pkt << (uint8) WOW_FAIL_SUSPENDED; + locked=true; + } + else + DEBUG_LOG("[AuthChallenge] Account IP matches"); + } + else + DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); + + if (!locked) + { + //set expired bans to inactive + LoginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + ///- If the account is banned, reject the logon attempt + QueryResult_AutoPtr banresult = LoginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); + if (banresult) + { + if ((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) + { + pkt << (uint8) WOW_FAIL_BANNED; + sLog.outBasic("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); + } + else + { + pkt << (uint8) WOW_FAIL_SUSPENDED; + sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); + } + } + else + { + ///- Get the password from the account table, upper it, and make the SRP6 calculation + std::string rI = (*result)[0].GetCppString(); + + ///- Don't calculate (v, s) if there are already some in the database + std::string databaseV = (*result)[5].GetCppString(); + std::string databaseS = (*result)[6].GetCppString(); + + sLog.outDebug("database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str()); + + // multiply with 2, bytes are stored as hexstring + if (databaseV.size() != s_BYTE_SIZE*2 || databaseS.size() != s_BYTE_SIZE*2) + _SetVSFields(rI); + else + { + s.SetHexStr(databaseS.c_str()); + v.SetHexStr(databaseV.c_str()); + } + + b.SetRand(19 * 8); + BigNumber gmod = g.ModExp(b, N); + B = ((v * 3) + gmod) % N; + + ASSERT(gmod.GetNumBytes() <= 32); + + BigNumber unk3; + unk3.SetRand(16 * 8); + + ///- Fill the response packet with the result + pkt << uint8(WOW_SUCCESS); + + // B may be calculated < 32B so we force minimal length to 32B + pkt.append(B.AsByteArray(32), 32); // 32 bytes + pkt << uint8(1); + pkt.append(g.AsByteArray(), 1); + pkt << uint8(32); + pkt.append(N.AsByteArray(32), 32); + pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes + pkt.append(unk3.AsByteArray(16), 16); + uint8 securityFlags = 0; + pkt << uint8(securityFlags); // security flags (0x0...0x04) + + if (securityFlags & 0x01) // PIN input + { + pkt << uint32(0); + pkt << uint64(0) << uint64(0); // 16 bytes hash? + } + + if (securityFlags & 0x02) // Matrix input + { + pkt << uint8(0); + pkt << uint8(0); + pkt << uint8(0); + pkt << uint8(0); + pkt << uint64(0); + } + + if (securityFlags & 0x04) // Security token input + pkt << uint8(1); + + uint8 secLevel = (*result)[4].GetUInt8(); + _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; + + _localizationName.resize(4); + for (int i = 0; i < 4; ++i) + _localizationName[i] = ch->country[4-i-1]; + + sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName)); + } + } + } + else //no account + { + pkt<< (uint8) WOW_FAIL_UNKNOWN_ACCOUNT; + } + } + + socket().send((char const*)pkt.contents(), pkt.size()); + return true; +} + +/// Logon Proof command handler +bool AuthSocket::_HandleLogonProof() +{ + DEBUG_LOG("Entering _HandleLogonProof"); + ///- Read the packet + sAuthLogonProof_C lp; + + if (!socket().recv((char *)&lp, sizeof(sAuthLogonProof_C))) + return false; + + ///
  • If the client has no valid version + if (_expversion == NO_VALID_EXP_FLAG) + { + ///- Check if we have the appropriate patch on the disk + + sLog.outDebug("Client with invalid version, patching is not implemented"); + socket().shutdown(); + return true; + } + ///
+ + ///- Continue the SRP6 calculation based on data received from the client + BigNumber A; + + A.SetBinary(lp.A, 32); + + // SRP safeguard: abort if A==0 + if (A.isZero()) + { + socket().shutdown(); + return true; + } + + Sha1Hash sha; + sha.UpdateBigNumbers(&A, &B, NULL); + sha.Finalize(); + BigNumber u; + u.SetBinary(sha.GetDigest(), 20); + BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N); + + uint8 t[32]; + uint8 t1[16]; + uint8 vK[40]; + memcpy(t, S.AsByteArray(32), 32); + for (int i = 0; i < 16; ++i) + { + t1[i] = t[i * 2]; + } + sha.Initialize(); + sha.UpdateData(t1, 16); + sha.Finalize(); + for (int i = 0; i < 20; ++i) + { + vK[i * 2] = sha.GetDigest()[i]; + } + for (int i = 0; i < 16; ++i) + { + t1[i] = t[i * 2 + 1]; + } + sha.Initialize(); + sha.UpdateData(t1, 16); + sha.Finalize(); + for (int i = 0; i < 20; ++i) + { + vK[i * 2 + 1] = sha.GetDigest()[i]; + } + K.SetBinary(vK, 40); + + uint8 hash[20]; + + sha.Initialize(); + sha.UpdateBigNumbers(&N, NULL); + sha.Finalize(); + memcpy(hash, sha.GetDigest(), 20); + sha.Initialize(); + sha.UpdateBigNumbers(&g, NULL); + sha.Finalize(); + for (int i = 0; i < 20; ++i) + { + hash[i] ^= sha.GetDigest()[i]; + } + BigNumber t3; + t3.SetBinary(hash, 20); + + sha.Initialize(); + sha.UpdateData(_login); + sha.Finalize(); + uint8 t4[SHA_DIGEST_LENGTH]; + memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH); + + sha.Initialize(); + sha.UpdateBigNumbers(&t3, NULL); + sha.UpdateData(t4, SHA_DIGEST_LENGTH); + sha.UpdateBigNumbers(&s, &A, &B, &K, NULL); + sha.Finalize(); + BigNumber M; + M.SetBinary(sha.GetDigest(), 20); + + ///- Check if SRP6 results match (password is correct), else send an error + if (!memcmp(M.AsByteArray(), lp.M1, 20)) + { + sLog.outBasic("User '%s' successfully authenticated", _login.c_str()); + + ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account + // No SQL injection (escaped user name) and IP address as received by socket + const char* K_hex = K.AsHexStr(); + LoginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, socket().get_remote_address().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str()); + OPENSSL_free((void*)K_hex); + + ///- Finish SRP6 and send the final result to the client + sha.Initialize(); + sha.UpdateBigNumbers(&A, &M, &K, NULL); + sha.Finalize(); + + if (_expversion & POST_BC_EXP_FLAG)//2.4.3 and 3.1.3 clients (10146 is Chinese build for 3.1.3) + { + sAuthLogonProof_S proof; + memcpy(proof.M2, sha.GetDigest(), 20); + proof.cmd = AUTH_LOGON_PROOF; + proof.error = 0; + proof.unk1 = 0x00800000; + proof.unk2 = 0x00; + proof.unk3 = 0x00; + socket().send((char *)&proof, sizeof(proof)); + } + else + { + sAuthLogonProof_S_Old proof; + memcpy(proof.M2, sha.GetDigest(), 20); + proof.cmd = AUTH_LOGON_PROOF; + proof.error = 0; + //proof.unk1 = 0x00800000; + proof.unk2 = 0x00; + //proof.unk3 = 0x00; + socket().send((char *)&proof, sizeof(proof)); + } + + ///- Set _authed to true! + _authed = true; + } + else + { + char data[4]= { AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0}; + socket().send(data, sizeof(data)); + sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ()); + + uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0); + if (MaxWrongPassCount > 0) + { + //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP + LoginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '%s'",_safelogin.c_str()); + + if (QueryResult_AutoPtr loginfail = LoginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '%s'", _safelogin.c_str())) + { + Field* fields = loginfail->Fetch(); + uint32 failed_logins = fields[1].GetUInt32(); + + if (failed_logins >= MaxWrongPassCount) + { + uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600); + bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false); + + if (WrongPassBanType) + { + uint32 acc_id = fields[0].GetUInt32(); + LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)", + acc_id, WrongPassBanTime); + sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", + _login.c_str(), WrongPassBanTime, failed_logins); + } + else + { + std::string current_ip(socket().get_remote_address().c_str()); + LoginDatabase.escape_string(current_ip); + LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')", + current_ip.c_str(), WrongPassBanTime); + sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times", + current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins); + } + } + } + } + } + + return true; +} + +/// Reconnect Challenge command handler +bool AuthSocket::_HandleReconnectChallenge() +{ + DEBUG_LOG("Entering _HandleReconnectChallenge"); + if (socket().recv_len() < sizeof(sAuthLogonChallenge_C)) + return false; + + ///- Read the first 4 bytes (header) to get the length of the remaining of the packet + std::vector buf; + buf.resize(4); + + socket().recv((char *)&buf[0], 4); + + EndianConvert(*((uint16*)(buf[0]))); + uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; + DEBUG_LOG("[ReconnectChallenge] got header, body is %#04x bytes", remaining); + + if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (socket().recv_len() < remaining)) + return false; + + //No big fear of memory outage (size is int16, i.e. < 65536) + buf.resize(remaining + buf.size() + 1); + buf[buf.size() - 1] = 0; + sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; + + ///- Read the remaining of the packet + socket().recv((char *)&buf[4], remaining); + DEBUG_LOG("[ReconnectChallenge] got full packet, %#04x bytes", ch->size); + DEBUG_LOG("[ReconnectChallenge] name(%d): '%s'", ch->I_len, ch->I); + + _login = (const char*)ch->I; + _safelogin = _login; + + QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT sessionkey FROM account WHERE username = '%s'", _safelogin.c_str ()); + + // Stop if the account is not found + if (!result) + { + sLog.outError("[ERROR] user %s tried to login and we cannot find his session key in the database.", _login.c_str()); + socket().shutdown(); + return false; + } + + Field* fields = result->Fetch (); + K.SetHexStr (fields[0].GetString ()); + + ///- Sending response + ByteBuffer pkt; + pkt << (uint8) AUTH_RECONNECT_CHALLENGE; + pkt << (uint8) 0x00; + _reconnectProof.SetRand(16 * 8); + pkt.append(_reconnectProof.AsByteArray(16), 16); // 16 bytes random + pkt << (uint64) 0x00 << (uint64) 0x00; // 16 bytes zeros + socket().send((char const*)pkt.contents(), pkt.size()); + return true; +} + +/// Reconnect Proof command handler +bool AuthSocket::_HandleReconnectProof() +{ + DEBUG_LOG("Entering _HandleReconnectProof"); + ///- Read the packet + sAuthReconnectProof_C lp; + if (!socket().recv((char *)&lp, sizeof(sAuthReconnectProof_C))) + return false; + + if (_login.empty() || !_reconnectProof.GetNumBytes() || !K.GetNumBytes()) + return false; + + BigNumber t1; + t1.SetBinary(lp.R1, 16); + + Sha1Hash sha; + sha.Initialize(); + sha.UpdateData(_login); + sha.UpdateBigNumbers(&t1, &_reconnectProof, &K, NULL); + sha.Finalize(); + + if (!memcmp(sha.GetDigest(), lp.R2, SHA_DIGEST_LENGTH)) + { + ///- Sending response + ByteBuffer pkt; + pkt << (uint8) AUTH_RECONNECT_PROOF; + pkt << (uint8) 0x00; + pkt << (uint16) 0x00; // 2 bytes zeros + socket().send((char const*)pkt.contents(), pkt.size()); + + ///- Set _authed to true! + _authed = true; + + return true; + } + else + { + sLog.outError("[ERROR] user %s tried to login, but session invalid.", _login.c_str()); + socket().shutdown(); + return false; + } +} + +/// %Realm List command handler +bool AuthSocket::_HandleRealmList() +{ + DEBUG_LOG("Entering _HandleRealmList"); + if (socket().recv_len() < 5) + return false; + + socket().recv_skip(5); + + ///- Get the user id (else close the connection) + // No SQL injection (escaped user name) + + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",_safelogin.c_str()); + if (!result) + { + sLog.outError("[ERROR] user %s tried to login and we cannot find him in the database.",_login.c_str()); + socket().shutdown(); + return false; + } + + uint32 id = (*result)[0].GetUInt32(); + + ///- Update realm list if need + sRealmList->UpdateIfNeed(); + + ///- Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) + ByteBuffer pkt; + + size_t RealmListSize = 0; + for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i) + { + // don't work with realms which not compatible with the client + if (_expversion & POST_BC_EXP_FLAG) // 2.4.3 and 3.1.3 cliens + { + if (i->second.gamebuild != _build) + continue; + } + else if (_expversion & PRE_BC_EXP_FLAG) // 1.12.1 and 1.12.2 clients are compatible with eachother + { + if (!AuthHelper::IsPreBCAcceptedClientBuild(i->second.gamebuild)) + continue; + } + + uint8 AmountOfCharacters; + + // No SQL injection. id of realm is controlled by the database. + result = LoginDatabase.PQuery("SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); + if (result) + { + Field *fields = result->Fetch(); + AmountOfCharacters = fields[0].GetUInt8(); + } + else + AmountOfCharacters = 0; + + uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; + + pkt << i->second.icon; // realm type + if ( _expversion & POST_BC_EXP_FLAG )//only 2.4.3 and 3.1.3 cliens + pkt << lock; // if 1, then realm locked + pkt << i->second.color; // if 2, then realm is offline + pkt << i->first; + pkt << i->second.address; + pkt << i->second.populationLevel; + pkt << AmountOfCharacters; + pkt << i->second.timezone; // realm category + if ( _expversion & POST_BC_EXP_FLAG )//2.4.3 and 3.1.3 clients + pkt << (uint8) 0x2C; // unk, may be realm number/id? + else + pkt << (uint8) 0x0; //1.12.1 and 1.12.2 clients + + ++RealmListSize; + } + + if ( _expversion & POST_BC_EXP_FLAG )//2.4.3 and 3.1.3 cliens + { + pkt << (uint8) 0x10; + pkt << (uint8) 0x00; + }else{//1.12.1 and 1.12.2 clients + pkt << (uint8) 0x00; + pkt << (uint8) 0x02; + } + + // make a ByteBuffer which stores the RealmList's size + ByteBuffer RealmListSizeBuffer; + RealmListSizeBuffer << (uint32)0; + if (_expversion & POST_BC_EXP_FLAG) // only 2.4.3 and 3.1.3 cliens + RealmListSizeBuffer << (uint16)RealmListSize; + else + RealmListSizeBuffer << (uint32)RealmListSize; + + ByteBuffer hdr; + hdr << (uint8) REALM_LIST; + hdr << (uint16)(pkt.size() + RealmListSizeBuffer.size()); + hdr.append(RealmListSizeBuffer); // append RealmList's size buffer + hdr.append(pkt); // append realms in the realmlist + + socket().send((char const*)hdr.contents(), hdr.size()); + + return true; +} + +/// Resume patch transfer +bool AuthSocket::_HandleXferResume() +{ + DEBUG_LOG("Entering _HandleXferResume"); + ///- Check packet length and patch existence + if (socket().recv_len() < 9 || !pPatch) + { + sLog.outError("Error while resuming patch transfer (wrong packet)"); + return false; + } + + ///- Launch a PatcherRunnable thread starting at given patch file offset + uint64 start; + socket().recv_skip(1); + socket().recv((char*)&start,sizeof(start)); + fseek(pPatch, start, 0); + + ACE_Based::Thread u(new PatcherRunnable(this)); + return true; +} + +/// Cancel patch transfer +bool AuthSocket::_HandleXferCancel() +{ + DEBUG_LOG("Entering _HandleXferCancel"); + + ///- Close and delete the socket + socket().recv_skip(1); //clear input buffer + + socket().shutdown(); + + return true; +} + +/// Accept patch transfer +bool AuthSocket::_HandleXferAccept() +{ + DEBUG_LOG("Entering _HandleXferAccept"); + + ///- Check packet length and patch existence + if (!pPatch) + { + sLog.outError("Error while accepting patch transfer (wrong packet)"); + return false; + } + + ///- Launch a PatcherRunnable thread, starting at the beginning of the patch file + socket().recv_skip(1); // clear input buffer + fseek(pPatch, 0, 0); + + ACE_Based::Thread u(new PatcherRunnable(this)); + return true; +} + +PatcherRunnable::PatcherRunnable(class AuthSocket * as) +{ + mySocket = as; +} + +/// Send content of patch file to the client +void PatcherRunnable::run() +{ +} + +/// Preload MD5 hashes of existing patch files on server +#ifndef _WIN32 +#include +#include +void Patcher::LoadPatchesInfo() +{ + DIR * dirp; + //int errno; + struct dirent * dp; + dirp = opendir("./patches/"); + if (!dirp) + return; + while (dirp) + { + errno = 0; + if ((dp = readdir(dirp)) != NULL) + { + int l = strlen(dp->d_name); + if (l < 8) + continue; + if (!memcmp(&dp->d_name[l-4],".mpq",4)) + LoadPatchMD5(dp->d_name); + } + else + { + if (errno != 0) + { + closedir(dirp); + return; + } + break; + } + } + + if (dirp) + closedir(dirp); +} + +#else +void Patcher::LoadPatchesInfo() +{ + WIN32_FIND_DATA fil; + HANDLE hFil=FindFirstFile("./patches/*.mpq", &fil); + if (hFil == INVALID_HANDLE_VALUE) + return; // no patches were found + + do + { + LoadPatchMD5(fil.cFileName); + } + while(FindNextFile(hFil, &fil)); +} +#endif + +/// Calculate and store MD5 hash for a given patch file +void Patcher::LoadPatchMD5(char * szFileName) +{ + ///- Try to open the patch file + std::string path = "./patches/"; + path += szFileName; + FILE *pPatch = fopen(path.c_str(), "rb"); + sLog.outDebug("Loading patch info from %s\n", path.c_str()); + if (!pPatch) + { + sLog.outError("Error loading patch %s\n", path.c_str()); + return; + } + + ///- Calculate the MD5 hash + MD5_CTX ctx; + MD5_Init(&ctx); + uint8* buf = new uint8[512*1024]; + + while (!feof(pPatch)) + { + size_t read = fread(buf, 1, 512*1024, pPatch); + MD5_Update(&ctx, buf, read); + } + delete [] buf; + fclose(pPatch); + + ///- Store the result in the internal patch hash map + _patches[path] = new PATCH_INFO; + MD5_Final((uint8 *)&_patches[path]->md5, &ctx); +} + +/// Get cached MD5 hash for a given patch file +bool Patcher::GetHash(char * pat, uint8 mymd5[16]) +{ + for (Patches::iterator i = _patches.begin(); i != _patches.end(); ++i) + if (!stricmp(pat, i->first.c_str())) + { + memcpy(mymd5, i->second->md5, 16); + return true; + } + + return false; +} + +/// Launch the patch hashing mechanism on object creation +Patcher::Patcher() +{ + LoadPatchesInfo(); +} + +/// Empty and delete the patch map on termination +Patcher::~Patcher() +{ + for (Patches::iterator i = _patches.begin(); i != _patches.end(); ++i) + delete i->second; +} diff --git a/src/server/authserver/Server/AuthSocket.h b/src/server/authserver/Server/AuthSocket.h new file mode 100644 index 00000000000..bfd0fa4fdca --- /dev/null +++ b/src/server/authserver/Server/AuthSocket.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup realmd +/// @{ +/// \file + +#ifndef _AUTHSOCKET_H +#define _AUTHSOCKET_H + +#include "Common.h" +#include "Auth/BigNumber.h" + +#include "RealmSocket.h" + +enum RealmFlags +{ + REALM_FLAG_NONE = 0x00, + REALM_FLAG_INVALID = 0x01, + REALM_FLAG_OFFLINE = 0x02, + REALM_FLAG_SPECIFYBUILD = 0x04, // client will show realm version in RealmList screen in form "RealmName (major.minor.revision.build)" + REALM_FLAG_UNK1 = 0x08, + REALM_FLAG_UNK2 = 0x10, + REALM_FLAG_RECOMMENDED = 0x20, // client checks pop == 600f + REALM_FLAG_NEW = 0x40, // client checks pop == 200f + REALM_FLAG_FULL = 0x80 // client checks pop == 400f +}; + +/// Handle login commands +class AuthSocket: public RealmSocket::Session +{ + public: + const static int s_BYTE_SIZE = 32; + + AuthSocket(RealmSocket& socket); + virtual ~AuthSocket(void); + + virtual void OnRead(void); + virtual void OnAccept(void); + virtual void OnClose(void); + + bool _HandleLogonChallenge(); + bool _HandleLogonProof(); + bool _HandleReconnectChallenge(); + bool _HandleReconnectProof(); + bool _HandleRealmList(); + //data transfer handle for patch + + bool _HandleXferResume(); + bool _HandleXferCancel(); + bool _HandleXferAccept(); + + void _SetVSFields(const std::string& rI); + + FILE *pPatch; + ACE_Thread_Mutex patcherLock; + + private: + RealmSocket& socket_; + RealmSocket& socket(void) { return socket_; } + + BigNumber N, s, g, v; + BigNumber b, B; + BigNumber K; + BigNumber _reconnectProof; + + bool _authed; + + std::string _login; + std::string _safelogin; + + // Since GetLocaleByName() is _NOT_ bijective, we have to store the locale as a string. Otherwise we can't differ + // between enUS and enGB, which is important for the patch system + std::string _localizationName; + uint16 _build; + uint8 _expversion; + AccountTypes _accountSecurityLevel; +}; +#endif +/// @} diff --git a/src/server/authserver/Server/RealmAcceptor.h b/src/server/authserver/Server/RealmAcceptor.h new file mode 100644 index 00000000000..5e243ea915b --- /dev/null +++ b/src/server/authserver/Server/RealmAcceptor.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd + */ + +#ifndef __REALMACCEPTOR_H__ +#define __REALMACCEPTOR_H__ + +#include +#include + +#include "RealmSocket.h" +#include "AuthSocket.h" + +class RealmAcceptor : public ACE_Acceptor +{ + public: + RealmAcceptor(void) { } + virtual ~RealmAcceptor(void) { } + + protected: + virtual int make_svc_handler(RealmSocket *&sh) + { + if (sh == 0) + ACE_NEW_RETURN(sh, RealmSocket, -1); + + sh->reactor(reactor()); + sh->set_session(new AuthSocket(*sh)); + return 0; + } +}; + +#endif /* __REALMACCEPTOR_H__ */ diff --git a/src/server/authserver/Server/RealmSocket.cpp b/src/server/authserver/Server/RealmSocket.cpp new file mode 100644 index 00000000000..7eb96cb96f8 --- /dev/null +++ b/src/server/authserver/Server/RealmSocket.cpp @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd + */ + +#include "RealmSocket.h" + +#include "Log.h" + +#include +#include +#include + +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + +RealmSocket::Session::Session(void) +{ +} + +RealmSocket::Session::~Session(void) +{ +} + +RealmSocket::RealmSocket(void): + session_(NULL), + input_buffer_(4096), + remote_address_() +{ + reference_counting_policy().value( + ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + msg_queue()->high_water_mark(8*1024*1024); + msg_queue()->low_water_mark(8*1024*1024); + +} + +RealmSocket::~RealmSocket(void) +{ + if (msg_queue()) + msg_queue()->close(); + + // delete RealmSocketObject must never be called from our code. + closing_ = true; + + if (session_) + delete session_; + + peer().close(); +} + +int RealmSocket::open(void * arg) +{ + ACE_INET_Addr addr; + + if (peer ().get_remote_addr (addr) == -1) + { + sLog.outError ("RealmSocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror (errno)); + return -1; + } + + remote_address_ = addr.get_host_addr(); + + // Register with ACE Reactor + if (Base::open(arg) == -1) + return -1; + + if (session_ != NULL) + { + session_->OnAccept(); + } + + // reactor takes care of the socket from now on + remove_reference(); + + return 0; +} + +int RealmSocket::close(int) +{ + shutdown(); + + closing_ = true; + + remove_reference(); + + return 0; +} + +const ACE_CString& RealmSocket::get_remote_address(void) const +{ + return remote_address_; +} + +size_t RealmSocket::recv_len(void) const +{ + return input_buffer_.length(); +} + +bool RealmSocket::recv_soft(char *buf, size_t len) +{ + if (input_buffer_.length() < len) + return false; + + ACE_OS::memcpy(buf, input_buffer_.rd_ptr(), len); + + return true; +} + +bool RealmSocket::recv(char *buf, size_t len) +{ + bool ret = recv_soft(buf, len); + + if (ret) + recv_skip(len); + + return ret; +} + +void RealmSocket::recv_skip(size_t len) +{ + input_buffer_.rd_ptr(len); +} + +ssize_t RealmSocket::noblk_send(ACE_Message_Block &message_block) +{ + const size_t len = message_block.length(); + + if (len == 0) + return -1; + + // Try to send the message directly. + ssize_t n = peer().send(message_block.rd_ptr(), len, MSG_NOSIGNAL); + + if (n < 0) + { + if (errno == EWOULDBLOCK) + // Blocking signal + return 0; + else + // Error happened + return -1; + } + else if (n == 0) + { + // Can this happen ? + return -1; + } + + // return bytes transmitted + return n; +} + +bool RealmSocket::send(const char *buf, size_t len) +{ + if (buf == NULL || len == 0) + return true; + + ACE_Data_Block db( + len, + ACE_Message_Block::MB_DATA, + (const char*)buf, + 0, + 0, + ACE_Message_Block::DONT_DELETE, + 0); + + ACE_Message_Block message_block( + &db, + ACE_Message_Block::DONT_DELETE, + 0); + + message_block.wr_ptr(len); + + if (msg_queue()->is_empty()) + { + // Try to send it directly. + ssize_t n = noblk_send(message_block); + + if (n < 0) + return false; + else if (n == len) + return true; + + // fall down + message_block.rd_ptr((size_t)n); + } + + ACE_Message_Block *mb = message_block.clone(); + + if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value *) &ACE_Time_Value::zero) == -1) + { + mb->release(); + return false; + } + + if (reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK) == -1) + return false; + + return true; +} + +int RealmSocket::handle_output(ACE_HANDLE /*= ACE_INVALID_HANDLE*/) +{ + if (closing_) + return -1; + + ACE_Message_Block *mb = 0; + + if (msg_queue()->is_empty()) + { + reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK); + return 0; + } + + if (msg_queue()->dequeue_head(mb, (ACE_Time_Value *) &ACE_Time_Value::zero) == -1) + return -1; + + ssize_t n = noblk_send(*mb); + + if (n < 0) + { + mb->release(); + return -1; + } + else if (n == mb->length()) + { + mb->release(); + return 1; + } + else + { + mb->rd_ptr(n); + + if (msg_queue()->enqueue_head(mb, (ACE_Time_Value *) &ACE_Time_Value::zero) == -1) + { + mb->release(); + return -1; + } + + return 0; + } + + ACE_NOTREACHED(return -1); +} + +int RealmSocket::handle_close(ACE_HANDLE h, ACE_Reactor_Mask /*m*/) +{ + // As opposed to WorldSocket::handle_close, we don't need locks here. + + closing_ = true; + + if (h == ACE_INVALID_HANDLE) + peer ().close_writer (); + + if (session_ != NULL) + { + session_->OnClose(); + } + + return 0; +} + +int RealmSocket::handle_input(ACE_HANDLE /*= ACE_INVALID_HANDLE*/) +{ + if (closing_) + return -1; + + const ssize_t space = input_buffer_.space(); + + ssize_t n = peer().recv(input_buffer_.wr_ptr(), space); + + if (n < 0) + { + return errno == EWOULDBLOCK ? 0 : -1; + } + else if (n == 0) + { + // EOF + return -1; + } + + input_buffer_.wr_ptr((size_t)n); + + if (session_ != NULL) + { + session_->OnRead(); + + input_buffer_.crunch(); + } + + // return 1 in case there is more data to read from OS + return n == space ? 1 : 0; +} + + +void RealmSocket::set_session(Session* session) +{ + if (session_ != NULL) + delete session_; + + session_ = session; +} + diff --git a/src/server/authserver/Server/RealmSocket.h b/src/server/authserver/Server/RealmSocket.h new file mode 100644 index 00000000000..13be8327533 --- /dev/null +++ b/src/server/authserver/Server/RealmSocket.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd + */ + +#ifndef __REALMSOCKET_H__ +#define __REALMSOCKET_H__ + +#include +#include +#include +#include +#include +#include + +class RealmSocket : public ACE_Svc_Handler +{ + private: + typedef ACE_Svc_Handler Base; + + public: + class Session + { + public: + Session(void); + virtual ~Session(void); + + virtual void OnRead(void) = 0; + virtual void OnAccept(void) = 0; + virtual void OnClose(void) = 0; + }; + + RealmSocket(void); + virtual ~RealmSocket(void); + + size_t recv_len(void) const; + bool recv_soft(char *buf, size_t len); + bool recv(char *buf, size_t len); + void recv_skip(size_t len); + + bool send(const char *buf, size_t len); + + const ACE_CString& get_remote_address(void) const; + + virtual int open(void *); + + virtual int close(int); + + virtual int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE); + virtual int handle_output(ACE_HANDLE = ACE_INVALID_HANDLE); + + virtual int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); + + void set_session(Session* session); + + private: + ssize_t noblk_send(ACE_Message_Block &message_block); + + private: + ACE_Message_Block input_buffer_; + Session* session_; + ACE_CString remote_address_; +}; + +#endif /* __REALMSOCKET_H__ */ diff --git a/src/server/worldserver/CommandLine/CliRunnable.cpp b/src/server/worldserver/CommandLine/CliRunnable.cpp new file mode 100644 index 00000000000..b39faf694db --- /dev/null +++ b/src/server/worldserver/CommandLine/CliRunnable.cpp @@ -0,0 +1,445 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd +/// @{ +/// \file + +#include "Common.h" +#include "ObjectMgr.h" +#include "World.h" +#include "WorldSession.h" +#include "Config/ConfigEnv.h" + +#include "AccountMgr.h" +#include "Chat.h" +#include "CliRunnable.h" +#include "Language.h" +#include "Log.h" +#include "MapManager.h" +#include "Player.h" +#include "Util.h" + +#if PLATFORM != WINDOWS +#include +#include + +char * command_finder(const char* text, int state) +{ + static int idx,len; + const char* ret; + ChatCommand *cmd = ChatHandler::getCommandTable(); + + if(!state) + { + idx = 0; + len = strlen(text); + } + + while(ret = cmd[idx].Name) + { + if(!cmd[idx].AllowConsole) + { + idx++; + continue; + } + + idx++; + //printf("Checking %s \n", cmd[idx].Name); + if (strncmp(ret, text, len) == 0) + return strdup(ret); + if(cmd[idx].Name == NULL) + break; + } + + return ((char*)NULL); +} + +char ** cli_completion(const char * text, int start, int end) +{ + char ** matches; + matches = (char**)NULL; + + if(start == 0) + matches = rl_completion_matches((char*)text,&command_finder); + else + rl_bind_key('\t',rl_abort); + return (matches); +} +#endif + +void utf8print(const char* str) +{ +#if PLATFORM == PLATFORM_WINDOWS + wchar_t wtemp_buf[6000]; + size_t wtemp_len = 6000-1; + if(!Utf8toWStr(str,strlen(str),wtemp_buf,wtemp_len)) + return; + + char temp_buf[6000]; + CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1); + printf(temp_buf); +#else +{ + va_list v; + vprintf(str, v); + va_end(v); + fflush(stdout); +} +#endif +} + +/// Delete a user account and all associated characters in this realm +/// \todo This function has to be enhanced to respect the login/realm split (delete char, delete account chars in realm, delete account chars in realm then delete account +bool ChatHandler::HandleAccountDeleteCommand(const char* args) +{ + if(!*args) + return false; + + ///- Get the account name from the command line + char *account_name_str=strtok ((char*)args," "); + if (!account_name_str) + return false; + + std::string account_name = account_name_str; + if(!AccountMgr::normalizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + uint32 account_id = accmgr.GetId(account_name); + if(!account_id) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + /// Commands not recommended call from chat, but support anyway + /// can delete only for account with less security + /// This is also reject self apply in fact + if(HasLowerSecurityAccount (NULL,account_id,true)) + return false; + + AccountOpResult result = accmgr.DeleteAccount(account_id); + switch(result) + { + case AOR_OK: + PSendSysMessage(LANG_ACCOUNT_DELETED,account_name.c_str()); + break; + case AOR_NAME_NOT_EXIST: + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + case AOR_DB_INTERNAL_ERROR: + PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR,account_name.c_str()); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_ACCOUNT_NOT_DELETED,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleCharacterDeleteCommand(const char* args) +{ + if(!*args) + return false; + + char *character_name_str = strtok((char*)args," "); + if(!character_name_str) + return false; + + std::string character_name = character_name_str; + if(!normalizePlayerName(character_name)) + return false; + + uint64 character_guid; + uint32 account_id; + + Player *player = objmgr.GetPlayer(character_name.c_str()); + if(player) + { + character_guid = player->GetGUID(); + account_id = player->GetSession()->GetAccountId(); + player->GetSession()->KickPlayer(); + } + else + { + character_guid = objmgr.GetPlayerGUIDByName(character_name); + if(!character_guid) + { + PSendSysMessage(LANG_NO_PLAYER,character_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + account_id = objmgr.GetPlayerAccountIdByGUID(character_guid); + } + + std::string account_name; + accmgr.GetName (account_id,account_name); + + Player::DeleteFromDB(character_guid, account_id, true); + PSendSysMessage(LANG_CHARACTER_DELETED,character_name.c_str(),GUID_LOPART(character_guid),account_name.c_str(), account_id); + return true; +} + +/// Exit the realm +bool ChatHandler::HandleServerExitCommand(const char* /*args*/) +{ + SendSysMessage(LANG_COMMAND_EXIT); + World::StopNow(SHUTDOWN_EXIT_CODE); + return true; +} + +/// Display info on users currently in the realm +bool ChatHandler::HandleAccountOnlineListCommand(const char* /*args*/) +{ + ///- Get the list of accounts ID logged to the realm + QueryResult_AutoPtr resultDB = CharacterDatabase.Query("SELECT name,account,map,zone FROM characters WHERE online > 0"); + if (!resultDB) + { + SendSysMessage(LANG_ACCOUNT_LIST_EMPTY); + return true; + } + + ///- Display the list of account/characters online + SendSysMessage(LANG_ACCOUNT_LIST_BAR_HEADER); + SendSysMessage(LANG_ACCOUNT_LIST_HEADER); + SendSysMessage(LANG_ACCOUNT_LIST_BAR); + + ///- Circle through accounts + do + { + Field *fieldsDB = resultDB->Fetch(); + std::string name = fieldsDB[0].GetCppString(); + uint32 account = fieldsDB[1].GetUInt32(); + + ///- Get the username, last IP and GM level of each account + // No SQL injection. account is uint32. + QueryResult_AutoPtr resultLogin = + LoginDatabase.PQuery("SELECT a.username, a.last_ip, aa.gmlevel, a.expansion " + "FROM account a " + "LEFT JOIN account_access aa " + "ON (a.id = aa.id) " + "WHERE a.id = '%u'", account); + if(resultLogin) + { + Field *fieldsLogin = resultLogin->Fetch(); + PSendSysMessage(LANG_ACCOUNT_LIST_LINE, + fieldsLogin[0].GetString(),name.c_str(),fieldsLogin[1].GetString(),fieldsDB[2].GetInt32(),fieldsDB[3].GetInt32(),fieldsLogin[3].GetUInt32(),fieldsLogin[2].GetUInt32()); + } + else + PSendSysMessage(LANG_ACCOUNT_LIST_ERROR,name.c_str()); + + }while(resultDB->NextRow()); + + SendSysMessage(LANG_ACCOUNT_LIST_BAR); + return true; +} + +/// Create an account +bool ChatHandler::HandleAccountCreateCommand(const char* args) +{ + if(!*args) + return false; + + ///- %Parse the command line arguments + char *szAcc = strtok((char*)args, " "); + char *szPassword = strtok(NULL, " "); + if(!szAcc || !szPassword) + return false; + + // normalized in accmgr.CreateAccount + std::string account_name = szAcc; + std::string password = szPassword; + + AccountOpResult result = accmgr.CreateAccount(account_name, password); + switch(result) + { + case AOR_OK: + PSendSysMessage(LANG_ACCOUNT_CREATED,account_name.c_str()); + break; + case AOR_NAME_TOO_LONG: + SendSysMessage(LANG_ACCOUNT_TOO_LONG); + SetSentErrorMessage(true); + return false; + case AOR_NAME_ALREDY_EXIST: + SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); + SetSentErrorMessage(true); + return false; + case AOR_DB_INTERNAL_ERROR: + PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR,account_name.c_str()); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_ACCOUNT_NOT_CREATED,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +/// Set the level of logging +bool ChatHandler::HandleServerSetLogFileLevelCommand(const char *args) +{ + if(!*args) + return false; + + char *NewLevel = strtok((char*)args, " "); + if (!NewLevel) + return false; + + sLog.SetLogFileLevel(NewLevel); + return true; +} + +/// Set the level of logging +bool ChatHandler::HandleServerSetLogLevelCommand(const char *args) +{ + if(!*args) + return false; + + char *NewLevel = strtok((char*)args, " "); + if (!NewLevel) + return false; + + sLog.SetLogLevel(NewLevel); + return true; +} + +/// set diff time record interval +bool ChatHandler::HandleServerSetDiffTimeCommand(const char *args) +{ + if(!*args) + return false; + + char *NewTimeStr = strtok((char*)args, " "); + if(!NewTimeStr) + return false; + + int32 NewTime =atoi(NewTimeStr); + if(NewTime < 0) + return false; + + sWorld.SetRecordDiffInterval(NewTime); + printf( "Record diff every %u ms\n", NewTime); + return true; +} + +/// @} + +#ifdef linux +// Non-blocking keypress detector, when return pressed, return 1, else always return 0 +int kb_hit_return() +{ + struct timeval tv; + fd_set fds; + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); + return FD_ISSET(STDIN_FILENO, &fds); +} +#endif + +/// %Thread start +void CliRunnable::run() +{ + ///- Init new SQL thread for the world database (one connection call enough) + WorldDatabase.ThreadStart(); // let thread do safe mySQL requests + + char commandbuf[256]; + + ///- Display the list of available CLI functions then beep + sLog.outString(""); + #if PLATFORM != WINDOWS + rl_attempted_completion_function = cli_completion; + #endif + if(sConfig.GetBoolDefault("BeepAtStart", true)) + printf("\a"); // \a = Alert + + // print this here the first time + // later it will be printed after command queue updates + printf("TC>"); + + ///- As long as the World is running (no World::m_stopEvent), get the command line and handle it + while (!World::IsStopped()) + { + fflush(stdout); + + char *command_str ; // = fgets(commandbuf,sizeof(commandbuf),stdin); + + #if PLATFORM == WINDOWS + command_str = fgets(commandbuf,sizeof(commandbuf),stdin); + #else + command_str = readline("TC>"); + rl_bind_key('\t',rl_complete); + #endif + if (command_str != NULL) + { + for (int x=0; command_str[x]; x++) + if(command_str[x]=='\r'||command_str[x]=='\n') + { + command_str[x]=0; + break; + } + + if(!*command_str) + { + #if PLATFORM == WINDOWS + printf("TC>"); + #endif + continue; + } + + std::string command; + if(!consoleToUtf8(command_str,command)) // convert from console encoding to utf8 + { + #if PLATFORM == WINDOWS + printf("TC>"); + #endif + continue; + } + fflush(stdout); + sWorld.QueueCliCommand(&utf8print,command.c_str()); + #if PLATFORM != WINDOWS + add_history(command.c_str()); + #endif + + } + else if (feof(stdin)) + { + World::StopNow(SHUTDOWN_EXIT_CODE); + } + + } + + ///- End the database thread + WorldDatabase.ThreadEnd(); // free mySQL thread resources +} diff --git a/src/server/worldserver/CommandLine/CliRunnable.h b/src/server/worldserver/CommandLine/CliRunnable.h new file mode 100644 index 00000000000..9f990b2b469 --- /dev/null +++ b/src/server/worldserver/CommandLine/CliRunnable.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd +/// @{ +/// \file + +#ifndef __CLIRUNNABLE_H +#define __CLIRUNNABLE_H + +/// Command Line Interface handling thread +class CliRunnable : public ACE_Based::Runnable +{ + public: + void run(); +}; +#endif +/// @} diff --git a/src/server/worldserver/RemoteAccess/RASocket.cpp b/src/server/worldserver/RemoteAccess/RASocket.cpp new file mode 100644 index 00000000000..32c16d9980f --- /dev/null +++ b/src/server/worldserver/RemoteAccess/RASocket.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup Trinityd +*/ + +#include "Common.h" +#include "Config/ConfigEnv.h" +#include "Database/DatabaseEnv.h" +#include "AccountMgr.h" +#include "Log.h" +#include "RASocket.h" +#include "Util.h" +#include "World.h" + +/// \todo Make this thread safe if in the future 2 admins should be able to log at the same time. +SOCKET r; + +#define dropclient {Sendf("I'm busy right now, come back later."); \ + SetCloseAndDelete(); \ + return; \ + } + +uint32 iSession=0; ///< Session number (incremented each time a new connection is made) +unsigned int iUsers=0; ///< Number of active administrators + +typedef int(* pPrintf)(const char*,...); + +void ParseCommand(CliCommandHolder::Print*, char*command); + +/// RASocket constructor +RASocket::RASocket(ISocketHandler &h): TcpSocket(h) +{ + + ///- Increment the session number + iSess =iSession++ ; + + ///- Get the config parameters + bSecure = sConfig.GetBoolDefault( "RA.Secure", true ); + iMinLevel = sConfig.GetIntDefault( "RA.MinLevel", 3 ); + + ///- Initialize buffer and data + iInputLength=0; + buff=new char[RA_BUFF_SIZE]; + stage=NONE; +} + +/// RASocket destructor +RASocket::~RASocket() +{ + ///- Delete buffer and decrease active admins count + delete [] buff; + + sLog.outRemote("Connection was closed.\n"); + + if(stage==OK) + iUsers--; +} + +/// Accept an incoming connection +void RASocket::OnAccept() +{ + std::string ss=GetRemoteAddress(); + sLog.outRemote("Incoming connection from %s.\n",ss.c_str()); + ///- If there is already an active admin, drop the connection + if(iUsers) + dropclient + + ///- Else print Motd + Sendf("%s\r\n",sWorld.GetMotd()); +} + +/// Read data from the network +void RASocket::OnRead() +{ + ///- Read data and check input length + TcpSocket::OnRead(); + + unsigned int sz=ibuf.GetLength(); + if(iInputLength+sz>=RA_BUFF_SIZE) + { + sLog.outRemote("Input buffer overflow, possible DOS attack.\n"); + SetCloseAndDelete(); + return; + } + + ///- If there is already an active admin (other than you), drop the connection + if(stage!=OK && iUsers) + dropclient + + char *inp = new char [sz+1]; + ibuf.Read(inp,sz); + + /// \todo Can somebody explain this 'Linux bugfix'? + if(stage==NONE) + if(sz>4) //linux remote telnet + if(memcmp(inp ,"USER ",5)) + { + delete [] inp;return; + printf("lin bugfix"); + } //linux bugfix + + ///- Discard data after line break or line feed + bool gotenter=false; + unsigned int y=0; + for (; y
  • If the input is 'USER ' + case NONE: + if(!memcmp(buff,"USER ",5)) //got "USER" cmd + { + szLogin=&buff[5]; + + ///- Get the password from the account table + std::string login = szLogin; + + ///- Convert Account name to Upper Format + AccountMgr::normalizeString(login); + + ///- Escape the Login to allow quotes in names + LoginDatabase.escape_string(login); + + QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT a.id, aa.gmlevel, aa.RealmID FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = '%s'",login.c_str ()); + + ///- If the user is not found, deny access + if(!result) + { + Sendf("-No such user.\r\n"); + sLog.outRemote("User %s does not exist.\n",szLogin.c_str()); + if(bSecure)SetCloseAndDelete(); + } + else + { + Field *fields = result->Fetch(); + + //szPass=fields[0].GetString(); + + ///- if gmlevel is too low, deny access + if(fields[1].GetUInt32() If the input is 'PASS ' (and the user already gave his username) + case LG: + if(!memcmp(buff,"PASS ",5)) //got "PASS" cmd + { //login+pass ok + ///- If password is correct, increment the number of active administrators + std::string login = szLogin; + std::string pw = &buff[5]; + + AccountMgr::normalizeString(login); + AccountMgr::normalizeString(pw); + LoginDatabase.escape_string(login); + LoginDatabase.escape_string(pw); + + QueryResult_AutoPtr check = LoginDatabase.PQuery( + "SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT('%s',':','%s'))", + login.c_str(), login.c_str(), pw.c_str()); + + if(check) + { + r=GetSocket(); + stage=OK; + ++iUsers; + + Sendf("+Logged in.\r\n"); + sLog.outRemote("User %s has logged in.\n",szLogin.c_str()); + Sendf("TC>"); + } + else + { + ///- Else deny access + Sendf("-Wrong pass.\r\n"); + sLog.outRemote("User %s has failed to log in.\n",szLogin.c_str()); + if(bSecure)SetCloseAndDelete(); + } + } + break; + ///
  • If user is logged, parse and execute the command + case OK: + if(strlen(buff)) + { + sLog.outRemote("Got '%s' cmd.\n",buff); + sWorld.QueueCliCommand(&RASocket::zprint , buff); + } + else + Sendf("TC>"); + break; + /// + }; + + } +} + +/// Output function +void RASocket::zprint( const char * szText ) +{ + if( !szText ) + return; + + #ifdef RA_CRYPT + + char *megabuffer=strdup(szText); + unsigned int sz=strlen(megabuffer); + Encrypt(megabuffer,sz); + send(r,megabuffer,sz,0); + delete [] megabuffer; + + #else + + unsigned int sz=strlen(szText); + send(r,szText,sz,0); + + #endif +} diff --git a/src/server/worldserver/RemoteAccess/RASocket.h b/src/server/worldserver/RemoteAccess/RASocket.h new file mode 100644 index 00000000000..5c13724f90d --- /dev/null +++ b/src/server/worldserver/RemoteAccess/RASocket.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd +/// @{ +/// \file + +#ifndef _RASOCKET_H +#define _RASOCKET_H + +#include "sockets/TcpSocket.h" + +#include "Common.h" + +#define RA_BUFF_SIZE 1024 + +class ISocketHandler; + +/// Remote Administration socket +class RASocket: public TcpSocket +{ + public: + + RASocket(ISocketHandler& h); + ~RASocket(); + + void OnAccept(); + void OnRead(); + + private: + + char * buff; + std::string szLogin; + uint32 iSess; + unsigned int iInputLength; + bool bLog; + bool bSecure; //kick on wrong pass, non exist. user, user with no priv + //will protect from DOS, bruteforce attacks + //some 'smart' protection must be added for more security + uint8 iMinLevel; + enum + { + NONE, //initial value + LG, //only login was entered + OK, //both login and pass were given, and they are correct and user have enough priv. + }stage; + + static void zprint( const char * szText ); +}; +#endif +/// @} diff --git a/src/server/worldserver/WorldThread/WorldRunnable.cpp b/src/server/worldserver/WorldThread/WorldRunnable.cpp new file mode 100644 index 00000000000..c674ddbc06f --- /dev/null +++ b/src/server/worldserver/WorldThread/WorldRunnable.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup Trinityd +*/ + +#include "Common.h" +#include "ObjectAccessor.h" +#include "World.h" +#include "WorldSocketMgr.h" +#include "Database/DatabaseEnv.h" + +#include "BattleGroundMgr.h" +#include "MapManager.h" +#include "Timer.h" +#include "WorldRunnable.h" + +#define WORLD_SLEEP_CONST 50 + +#ifdef WIN32 +#include "ServiceWin32.h" +extern int m_ServiceStatus; +#endif + +/// Heartbeat for the World +void WorldRunnable::run() +{ + ///- Init new SQL thread for the world database + WorldDatabase.ThreadStart(); // let thread do safe mySQL requests (one connection call enough) + + sWorld.InitResultQueue(); + + uint32 realCurrTime = 0; + uint32 realPrevTime = getMSTime(); + + uint32 prevSleepTime = 0; // used for balanced full tick time length near WORLD_SLEEP_CONST + + ///- While we have not World::m_stopEvent, update the world + while (!World::IsStopped()) + { + ++World::m_worldLoopCounter; + realCurrTime = getMSTime(); + + uint32 diff = getMSTimeDiff(realPrevTime,realCurrTime); + + sWorld.Update( diff ); + realPrevTime = realCurrTime; + + // diff (D0) include time of previous sleep (d0) + tick time (t0) + // we want that next d1 + t1 == WORLD_SLEEP_CONST + // we can't know next t1 and then can use (t0 + d1) == WORLD_SLEEP_CONST requirement + // d1 = WORLD_SLEEP_CONST - t0 = WORLD_SLEEP_CONST - (D0 - d0) = WORLD_SLEEP_CONST + d0 - D0 + if (diff <= WORLD_SLEEP_CONST+prevSleepTime) + { + prevSleepTime = WORLD_SLEEP_CONST+prevSleepTime-diff; + ACE_Based::Thread::Sleep(prevSleepTime); + } + else + prevSleepTime = 0; + + #ifdef WIN32 + if (m_ServiceStatus == 0) World::StopNow(SHUTDOWN_EXIT_CODE); + while (m_ServiceStatus == 2) Sleep(1000); + #endif + } + + sWorld.KickAll(); // save and kick all players + sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call + + // unload battleground templates before different singletons destroyed + sBattleGroundMgr.DeleteAllBattleGrounds(); + + sWorldSocketMgr->StopNetwork(); + + MapManager::Instance().UnloadAll(); // unload all grids (including locked in memory) + + ///- End the database thread + WorldDatabase.ThreadEnd(); // free mySQL thread resources +} diff --git a/src/server/worldserver/WorldThread/WorldRunnable.h b/src/server/worldserver/WorldThread/WorldRunnable.h new file mode 100644 index 00000000000..f14ee021f36 --- /dev/null +++ b/src/server/worldserver/WorldThread/WorldRunnable.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd +/// @{ +/// \file + +#ifndef __WORLDRUNNABLE_H +#define __WORLDRUNNABLE_H + +/// Heartbeat thread for the World +class WorldRunnable : public ACE_Based::Runnable +{ + public: + void run(); +}; +#endif +/// @} -- cgit v1.2.3 From a9f575a7eb2bc46d7548d787250c81060240fb01 Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:08:35 +0200 Subject: * Delivering file deletions... --HG-- branch : trunk --- src/server/authserver/AuthCodes.cpp | 37 -- src/server/authserver/AuthCodes.h | 97 --- src/server/authserver/AuthSocket.cpp | 1069 ------------------------------ src/server/authserver/AuthSocket.h | 97 --- src/server/authserver/RealmAcceptor.h | 52 -- src/server/authserver/RealmList.cpp | 100 --- src/server/authserver/RealmList.h | 79 --- src/server/authserver/RealmSocket.cpp | 324 --------- src/server/authserver/RealmSocket.h | 85 --- src/server/worldserver/CliRunnable.cpp | 445 ------------- src/server/worldserver/CliRunnable.h | 35 - src/server/worldserver/RASocket.cpp | 265 -------- src/server/worldserver/RASocket.h | 68 -- src/server/worldserver/WorldRunnable.cpp | 97 --- src/server/worldserver/WorldRunnable.h | 35 - 15 files changed, 2885 deletions(-) delete mode 100644 src/server/authserver/AuthCodes.cpp delete mode 100644 src/server/authserver/AuthCodes.h delete mode 100644 src/server/authserver/AuthSocket.cpp delete mode 100644 src/server/authserver/AuthSocket.h delete mode 100644 src/server/authserver/RealmAcceptor.h delete mode 100644 src/server/authserver/RealmList.cpp delete mode 100644 src/server/authserver/RealmList.h delete mode 100644 src/server/authserver/RealmSocket.cpp delete mode 100644 src/server/authserver/RealmSocket.h delete mode 100644 src/server/worldserver/CliRunnable.cpp delete mode 100644 src/server/worldserver/CliRunnable.h delete mode 100644 src/server/worldserver/RASocket.cpp delete mode 100644 src/server/worldserver/RASocket.h delete mode 100644 src/server/worldserver/WorldRunnable.cpp delete mode 100644 src/server/worldserver/WorldRunnable.h (limited to 'src/server') diff --git a/src/server/authserver/AuthCodes.cpp b/src/server/authserver/AuthCodes.cpp deleted file mode 100644 index 812949e0823..00000000000 --- a/src/server/authserver/AuthCodes.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "AuthCodes.h" - -namespace AuthHelper -{ - -bool IsPreBCAcceptedClientBuild(int build) -{ - int accepted_versions[] = PRE_BC_ACCEPTED_CLIENT_BUILD; - for (int i = 0; accepted_versions[i]; ++i) - { - if (build == accepted_versions[i]) - { - return true; - } - } - return false; -} - -bool IsPostBCAcceptedClientBuild(int build) -{ - int accepted_versions[] = POST_BC_ACCEPTED_CLIENT_BUILD; - for (int i = 0; accepted_versions[i]; ++i) - { - if (build == accepted_versions[i]) - { - return true; - } - } - return false; -} - -bool IsAcceptedClientBuild(int build) -{ - return (IsPostBCAcceptedClientBuild(build) || IsPreBCAcceptedClientBuild(build)); -} - -}; diff --git a/src/server/authserver/AuthCodes.h b/src/server/authserver/AuthCodes.h deleted file mode 100644 index eb6e4abfb08..00000000000 --- a/src/server/authserver/AuthCodes.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup realmd -*/ - -#ifndef _AUTHCODES_H -#define _AUTHCODES_H - -enum AuthResult -{ - WOW_SUCCESS = 0x00, - WOW_FAIL_UNKNOWN0 = 0x01, ///< ? Unable to connect - WOW_FAIL_UNKNOWN1 = 0x02, ///< ? Unable to connect - WOW_FAIL_BANNED = 0x03, ///< This account has been closed and is no longer available for use. Please go to /banned.html for further information. - WOW_FAIL_UNKNOWN_ACCOUNT = 0x04, ///< The information you have entered is not valid. Please check the spelling of the account name and password. If you need help in retrieving a lost or stolen password, see for more information - WOW_FAIL_INCORRECT_PASSWORD = 0x05, ///< The information you have entered is not valid. Please check the spelling of the account name and password. If you need help in retrieving a lost or stolen password, see for more information - WOW_FAIL_ALREADY_ONLINE = 0x06, ///< This account is already logged into . Please check the spelling and try again. - WOW_FAIL_NO_TIME = 0x07, ///< You have used up your prepaid time for this account. Please purchase more to continue playing - WOW_FAIL_DB_BUSY = 0x08, ///< Could not log in to at this time. Please try again later. - WOW_FAIL_VERSION_INVALID = 0x09, ///< Unable to validate game version. This may be caused by file corruption or interference of another program. Please visit for more information and possible solutions to this issue. - WOW_FAIL_VERSION_UPDATE = 0x0A, ///< Downloading - WOW_FAIL_INVALID_SERVER = 0x0B, ///< Unable to connect - WOW_FAIL_SUSPENDED = 0x0C, ///< This account has been temporarily suspended. Please go to /banned.html for further information - WOW_FAIL_FAIL_NOACCESS = 0x0D, ///< Unable to connect - WOW_SUCCESS_SURVEY = 0x0E, ///< Connected. - WOW_FAIL_PARENTCONTROL = 0x0F, ///< Access to this account has been blocked by parental controls. Your settings may be changed in your account preferences at - WOW_FAIL_LOCKED_ENFORCED = 0x10, ///< You have applied a lock to your account. You can change your locked status by calling your account lock phone number. - WOW_FAIL_TRIAL_ENDED = 0x11, ///< Your trial subscription has expired. Please visit to upgrade your account. - WOW_FAIL_USE_BATTLENET = 0x12, ///< WOW_FAIL_OTHER This account is now attached to a Battle.net account. Please login with your Battle.net account email address and password. -}; - -enum LoginResult -{ - LOGIN_OK = 0x00, - LOGIN_FAILED = 0x01, - LOGIN_FAILED2 = 0x02, - LOGIN_BANNED = 0x03, - LOGIN_UNKNOWN_ACCOUNT = 0x04, - LOGIN_UNKNOWN_ACCOUNT3 = 0x05, - LOGIN_ALREADYONLINE = 0x06, - LOGIN_NOTIME = 0x07, - LOGIN_DBBUSY = 0x08, - LOGIN_BADVERSION = 0x09, - LOGIN_DOWNLOAD_FILE = 0x0A, - LOGIN_FAILED3 = 0x0B, - LOGIN_SUSPENDED = 0x0C, - LOGIN_FAILED4 = 0x0D, - LOGIN_CONNECTED = 0x0E, - LOGIN_PARENTALCONTROL = 0x0F, - LOGIN_LOCKED_ENFORCED = 0x10, -}; - -//multirealm supported versions: -//1.12.1 build 5875 -//1.12.2 build 6005 -//2.4.3 build 8606 -//3.1.3 build 9947 -//3.1.3 build 10146 Chinese build -//3.2.2a build 10505 -//3.3.0a build 11159 -//3.3.2 build 11403 -//3.3.3a build 11723 - -#define POST_BC_ACCEPTED_CLIENT_BUILD {11723, 11403, 11159, 10571, 10505, 10146, 9947, 8606, 0} -#define PRE_BC_ACCEPTED_CLIENT_BUILD {5875, 6005, 0} - -#define POST_BC_EXP_FLAG 0x2 -#define PRE_BC_EXP_FLAG 0x1 -#define NO_VALID_EXP_FLAG 0x0 - -namespace AuthHelper -{ - bool IsAcceptedClientBuild(int build); - bool IsPostBCAcceptedClientBuild(int build); - bool IsPreBCAcceptedClientBuild(int build); -}; - -#endif diff --git a/src/server/authserver/AuthSocket.cpp b/src/server/authserver/AuthSocket.cpp deleted file mode 100644 index cc293097977..00000000000 --- a/src/server/authserver/AuthSocket.cpp +++ /dev/null @@ -1,1069 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup realmd -*/ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "ByteBuffer.h" -#include "Config/ConfigEnv.h" -#include "Log.h" -#include "RealmList.h" -#include "AuthSocket.h" -#include "AuthCodes.h" -#include -#include "Auth/Sha1.h" -//#include "Util.h" -- for commented utf8ToUpperOnlyLatin - -extern DatabaseType LoginDatabase; - -#define ChunkSize 2048 - -enum eAuthCmd -{ - //AUTH_NO_CMD = 0xFF, - AUTH_LOGON_CHALLENGE = 0x00, - AUTH_LOGON_PROOF = 0x01, - AUTH_RECONNECT_CHALLENGE = 0x02, - AUTH_RECONNECT_PROOF = 0x03, - //update srv =4 - REALM_LIST = 0x10, - XFER_INITIATE = 0x30, - XFER_DATA = 0x31, - XFER_ACCEPT = 0x32, - XFER_RESUME = 0x33, - XFER_CANCEL = 0x34 -}; - -enum eStatus -{ - STATUS_CONNECTED = 0, - STATUS_AUTHED -}; - -// 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 paltform -#if defined(__GNUC__) -#pragma pack(1) -#else -#pragma pack(push,1) -#endif - -typedef struct AUTH_LOGON_CHALLENGE_C -{ - uint8 cmd; - uint8 error; - uint16 size; - uint8 gamename[4]; - uint8 version1; - uint8 version2; - uint8 version3; - uint16 build; - uint8 platform[4]; - uint8 os[4]; - uint8 country[4]; - uint32 timezone_bias; - uint32 ip; - uint8 I_len; - uint8 I[1]; -} sAuthLogonChallenge_C; - -typedef struct AUTH_LOGON_PROOF_C -{ - uint8 cmd; - uint8 A[32]; - uint8 M1[20]; - uint8 crc_hash[20]; - uint8 number_of_keys; - uint8 securityFlags; // 0x00-0x04 -} sAuthLogonProof_C; - -typedef struct AUTH_LOGON_PROOF_S -{ - uint8 cmd; - uint8 error; - uint8 M2[20]; - uint32 unk1; - uint32 unk2; - uint16 unk3; -} sAuthLogonProof_S; - -typedef struct AUTH_LOGON_PROOF_S_OLD -{ - uint8 cmd; - uint8 error; - uint8 M2[20]; - //uint32 unk1; - uint32 unk2; - //uint16 unk3; -} sAuthLogonProof_S_Old; - -typedef struct AUTH_RECONNECT_PROOF_C -{ - uint8 cmd; - uint8 R1[16]; - uint8 R2[20]; - uint8 R3[20]; - uint8 number_of_keys; -} sAuthReconnectProof_C; - -typedef struct XFER_INIT -{ - uint8 cmd; // XFER_INITIATE - uint8 fileNameLen; // strlen(fileName); - uint8 fileName[5]; // fileName[fileNameLen] - uint64 file_size; // file size (bytes) - uint8 md5[MD5_DIGEST_LENGTH]; // MD5 -} XFER_INIT; - -typedef struct XFER_DATA -{ - uint8 opcode; - uint16 data_size; - uint8 data[ChunkSize]; -} XFER_DATA_STRUCT; - -typedef struct AuthHandler -{ - eAuthCmd cmd; - uint32 status; - bool (AuthSocket::*handler)(void); -} AuthHandler; - -// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some paltform -#if defined(__GNUC__) -#pragma pack() -#else -#pragma pack(pop) -#endif - -/// Launch a thread to transfer a patch to the client -class PatcherRunnable: public ACE_Based::Runnable -{ - public: - PatcherRunnable(class AuthSocket *); - void run(); - - private: - AuthSocket * mySocket; -}; - -typedef struct PATCH_INFO -{ - uint8 md5[MD5_DIGEST_LENGTH]; -} PATCH_INFO; - -/// Caches MD5 hash of client patches present on the server -class Patcher -{ - public: - typedef std::map Patches; - ~Patcher(); - Patcher(); - Patches::const_iterator begin() const { return _patches.begin(); } - Patches::const_iterator end() const { return _patches.end(); } - void LoadPatchMD5(char*); - bool GetHash(char * pat,uint8 mymd5[16]); - - private: - void LoadPatchesInfo(); - Patches _patches; -}; - -const AuthHandler table[] = -{ - { AUTH_LOGON_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleLogonChallenge }, - { AUTH_LOGON_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleLogonProof }, - { AUTH_RECONNECT_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleReconnectChallenge}, - { AUTH_RECONNECT_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleReconnectProof }, - { REALM_LIST, STATUS_AUTHED, &AuthSocket::_HandleRealmList }, - { XFER_ACCEPT, STATUS_CONNECTED, &AuthSocket::_HandleXferAccept }, - { XFER_RESUME, STATUS_CONNECTED, &AuthSocket::_HandleXferResume }, - { XFER_CANCEL, STATUS_CONNECTED, &AuthSocket::_HandleXferCancel } -}; - -#define AUTH_TOTAL_COMMANDS sizeof(table)/sizeof(AuthHandler) - -///Holds the MD5 hash of client patches present on the server -Patcher PatchesCache; - -/// Constructor - set the N and g values for SRP6 -AuthSocket::AuthSocket(RealmSocket& socket) : socket_(socket) -{ - N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); - g.SetDword(7); - _authed = false; - _accountSecurityLevel = SEC_PLAYER; -} - -/// Close patch file descriptor before leaving -AuthSocket::~AuthSocket(void) -{ -} - -/// Accept the connection and set the s random value for SRP6 -void AuthSocket::OnAccept(void) -{ - sLog.outBasic("Accepting connection from '%s'", socket().get_remote_address().c_str()); -} - -void AuthSocket::OnClose(void) -{ - sLog.outDebug("AuthSocket::OnClose"); -} - -/// Read the packet from the client -void AuthSocket::OnRead() -{ - uint8 _cmd; - while (1) - { - if (!socket().recv_soft((char *)&_cmd, 1)) - return; - - size_t i; - - ///- Circle through known commands and call the correct command handler - for (i = 0; i < AUTH_TOTAL_COMMANDS; ++i) - { - if ((uint8)table[i].cmd == _cmd && - (table[i].status == STATUS_CONNECTED || - (_authed && table[i].status == STATUS_AUTHED))) - { - DEBUG_LOG("[Auth] got data for cmd %u recv length %u", (uint32)_cmd, (uint32)socket().recv_len()); - - if (!(*this.*table[i].handler)()) - { - DEBUG_LOG("Command handler failed for cmd %u recv length %u", (uint32)_cmd, (uint32)socket().recv_len()); - return; - } - break; - } - } - - // Report unknown packets in the error log - if (i == AUTH_TOTAL_COMMANDS) - { - sLog.outError("[Auth] got unknown packet from '%s'", socket().get_remote_address().c_str()); - socket().shutdown(); - return; - } - } -} - -/// Make the SRP6 calculation from hash in dB -void AuthSocket::_SetVSFields(const std::string& rI) -{ - s.SetRand(s_BYTE_SIZE * 8); - - BigNumber I; - I.SetHexStr(rI.c_str()); - - // In case of leading zeros in the rI hash, restore them - uint8 mDigest[SHA_DIGEST_LENGTH]; - memset(mDigest, 0, SHA_DIGEST_LENGTH); - if (I.GetNumBytes() <= SHA_DIGEST_LENGTH) - memcpy(mDigest, I.AsByteArray(), I.GetNumBytes()); - - std::reverse(mDigest, mDigest + SHA_DIGEST_LENGTH); - - Sha1Hash sha; - sha.UpdateData(s.AsByteArray(), s.GetNumBytes()); - sha.UpdateData(mDigest, SHA_DIGEST_LENGTH); - sha.Finalize(); - BigNumber x; - x.SetBinary(sha.GetDigest(), sha.GetLength()); - v = g.ModExp(x, N); - // No SQL injection (username escaped) - const char *v_hex, *s_hex; - v_hex = v.AsHexStr(); - s_hex = s.AsHexStr(); - LoginDatabase.PExecute("UPDATE account SET v = '%s', s = '%s' WHERE username = '%s'", v_hex, s_hex, _safelogin.c_str()); - OPENSSL_free((void*)v_hex); - OPENSSL_free((void*)s_hex); -} - -/// Logon Challenge command handler -bool AuthSocket::_HandleLogonChallenge() -{ - DEBUG_LOG("Entering _HandleLogonChallenge"); - if (socket().recv_len() < sizeof(sAuthLogonChallenge_C)) - return false; - - ///- Read the first 4 bytes (header) to get the length of the remaining of the packet - std::vector buf; - buf.resize(4); - - socket().recv((char *)&buf[0], 4); - - EndianConvert(*((uint16*)(buf[0]))); - uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; - DEBUG_LOG("[AuthChallenge] got header, body is %#04x bytes", remaining); - - if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (socket().recv_len() < remaining)) - return false; - - //No big fear of memory outage (size is int16, i.e. < 65536) - buf.resize(remaining + buf.size() + 1); - buf[buf.size() - 1] = 0; - sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; - - ///- Read the remaining of the packet - socket().recv((char *)&buf[4], remaining); - DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size); - DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I); - - // BigEndian code, nop in little endian case - // size already converted - EndianConvert(*((uint32*)(&ch->gamename[0]))); - EndianConvert(ch->build); - EndianConvert(*((uint32*)(&ch->platform[0]))); - EndianConvert(*((uint32*)(&ch->os[0]))); - EndianConvert(*((uint32*)(&ch->country[0]))); - EndianConvert(ch->timezone_bias); - EndianConvert(ch->ip); - - ByteBuffer pkt; - - _login = (const char*)ch->I; - _build = ch->build; - _expversion = (AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : NO_VALID_EXP_FLAG) + (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG); - - ///- Normalize account name - //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form - - //Escape the user login to avoid further SQL injection - //Memory will be freed on AuthSocket object destruction - _safelogin = _login; - LoginDatabase.escape_string(_safelogin); - - _build = ch->build; - - pkt << (uint8) AUTH_LOGON_CHALLENGE; - pkt << (uint8) 0x00; - - ///- Verify that this IP is not in the ip_banned table - // No SQL injection possible (paste the IP address as passed by the socket) - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); - - std::string address(socket().get_remote_address().c_str()); - LoginDatabase.escape_string(address); - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); - if (result) - { - pkt << (uint8)WOW_FAIL_BANNED; - sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!", address.c_str ()); - } - else - { - ///- Get the account details from the account table - // No SQL injection (escaped user name) - - result = LoginDatabase.PQuery("SELECT a.sha_pass_hash,a.id,a.locked,a.last_ip,aa.gmlevel,a.v,a.s " - "FROM account a " - "LEFT JOIN account_access aa " - "ON (a.id = aa.id) " - "WHERE a.username = '%s'",_safelogin.c_str ()); - if (result) - { - ///- If the IP is 'locked', check that the player comes indeed from the correct IP address - bool locked = false; - if ((*result)[2].GetUInt8() == 1) // if ip is locked - { - DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); - DEBUG_LOG("[AuthChallenge] Player address is '%s'", socket().get_remote_address().c_str()); - if (strcmp((*result)[3].GetString(),socket().get_remote_address().c_str())) - { - DEBUG_LOG("[AuthChallenge] Account IP differs"); - pkt << (uint8) WOW_FAIL_SUSPENDED; - locked=true; - } - else - DEBUG_LOG("[AuthChallenge] Account IP matches"); - } - else - DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); - - if (!locked) - { - //set expired bans to inactive - LoginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); - ///- If the account is banned, reject the logon attempt - QueryResult_AutoPtr banresult = LoginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); - if (banresult) - { - if ((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) - { - pkt << (uint8) WOW_FAIL_BANNED; - sLog.outBasic("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); - } - else - { - pkt << (uint8) WOW_FAIL_SUSPENDED; - sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); - } - } - else - { - ///- Get the password from the account table, upper it, and make the SRP6 calculation - std::string rI = (*result)[0].GetCppString(); - - ///- Don't calculate (v, s) if there are already some in the database - std::string databaseV = (*result)[5].GetCppString(); - std::string databaseS = (*result)[6].GetCppString(); - - sLog.outDebug("database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str()); - - // multiply with 2, bytes are stored as hexstring - if (databaseV.size() != s_BYTE_SIZE*2 || databaseS.size() != s_BYTE_SIZE*2) - _SetVSFields(rI); - else - { - s.SetHexStr(databaseS.c_str()); - v.SetHexStr(databaseV.c_str()); - } - - b.SetRand(19 * 8); - BigNumber gmod = g.ModExp(b, N); - B = ((v * 3) + gmod) % N; - - ASSERT(gmod.GetNumBytes() <= 32); - - BigNumber unk3; - unk3.SetRand(16 * 8); - - ///- Fill the response packet with the result - pkt << uint8(WOW_SUCCESS); - - // B may be calculated < 32B so we force minimal length to 32B - pkt.append(B.AsByteArray(32), 32); // 32 bytes - pkt << uint8(1); - pkt.append(g.AsByteArray(), 1); - pkt << uint8(32); - pkt.append(N.AsByteArray(32), 32); - pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes - pkt.append(unk3.AsByteArray(16), 16); - uint8 securityFlags = 0; - pkt << uint8(securityFlags); // security flags (0x0...0x04) - - if (securityFlags & 0x01) // PIN input - { - pkt << uint32(0); - pkt << uint64(0) << uint64(0); // 16 bytes hash? - } - - if (securityFlags & 0x02) // Matrix input - { - pkt << uint8(0); - pkt << uint8(0); - pkt << uint8(0); - pkt << uint8(0); - pkt << uint64(0); - } - - if (securityFlags & 0x04) // Security token input - pkt << uint8(1); - - uint8 secLevel = (*result)[4].GetUInt8(); - _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; - - _localizationName.resize(4); - for (int i = 0; i < 4; ++i) - _localizationName[i] = ch->country[4-i-1]; - - sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName)); - } - } - } - else //no account - { - pkt<< (uint8) WOW_FAIL_UNKNOWN_ACCOUNT; - } - } - - socket().send((char const*)pkt.contents(), pkt.size()); - return true; -} - -/// Logon Proof command handler -bool AuthSocket::_HandleLogonProof() -{ - DEBUG_LOG("Entering _HandleLogonProof"); - ///- Read the packet - sAuthLogonProof_C lp; - - if (!socket().recv((char *)&lp, sizeof(sAuthLogonProof_C))) - return false; - - ///
    • If the client has no valid version - if (_expversion == NO_VALID_EXP_FLAG) - { - ///- Check if we have the appropriate patch on the disk - - sLog.outDebug("Client with invalid version, patching is not implemented"); - socket().shutdown(); - return true; - } - ///
    - - ///- Continue the SRP6 calculation based on data received from the client - BigNumber A; - - A.SetBinary(lp.A, 32); - - // SRP safeguard: abort if A==0 - if (A.isZero()) - { - socket().shutdown(); - return true; - } - - Sha1Hash sha; - sha.UpdateBigNumbers(&A, &B, NULL); - sha.Finalize(); - BigNumber u; - u.SetBinary(sha.GetDigest(), 20); - BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N); - - uint8 t[32]; - uint8 t1[16]; - uint8 vK[40]; - memcpy(t, S.AsByteArray(32), 32); - for (int i = 0; i < 16; ++i) - { - t1[i] = t[i * 2]; - } - sha.Initialize(); - sha.UpdateData(t1, 16); - sha.Finalize(); - for (int i = 0; i < 20; ++i) - { - vK[i * 2] = sha.GetDigest()[i]; - } - for (int i = 0; i < 16; ++i) - { - t1[i] = t[i * 2 + 1]; - } - sha.Initialize(); - sha.UpdateData(t1, 16); - sha.Finalize(); - for (int i = 0; i < 20; ++i) - { - vK[i * 2 + 1] = sha.GetDigest()[i]; - } - K.SetBinary(vK, 40); - - uint8 hash[20]; - - sha.Initialize(); - sha.UpdateBigNumbers(&N, NULL); - sha.Finalize(); - memcpy(hash, sha.GetDigest(), 20); - sha.Initialize(); - sha.UpdateBigNumbers(&g, NULL); - sha.Finalize(); - for (int i = 0; i < 20; ++i) - { - hash[i] ^= sha.GetDigest()[i]; - } - BigNumber t3; - t3.SetBinary(hash, 20); - - sha.Initialize(); - sha.UpdateData(_login); - sha.Finalize(); - uint8 t4[SHA_DIGEST_LENGTH]; - memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH); - - sha.Initialize(); - sha.UpdateBigNumbers(&t3, NULL); - sha.UpdateData(t4, SHA_DIGEST_LENGTH); - sha.UpdateBigNumbers(&s, &A, &B, &K, NULL); - sha.Finalize(); - BigNumber M; - M.SetBinary(sha.GetDigest(), 20); - - ///- Check if SRP6 results match (password is correct), else send an error - if (!memcmp(M.AsByteArray(), lp.M1, 20)) - { - sLog.outBasic("User '%s' successfully authenticated", _login.c_str()); - - ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account - // No SQL injection (escaped user name) and IP address as received by socket - const char* K_hex = K.AsHexStr(); - LoginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, socket().get_remote_address().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str()); - OPENSSL_free((void*)K_hex); - - ///- Finish SRP6 and send the final result to the client - sha.Initialize(); - sha.UpdateBigNumbers(&A, &M, &K, NULL); - sha.Finalize(); - - if (_expversion & POST_BC_EXP_FLAG)//2.4.3 and 3.1.3 clients (10146 is Chinese build for 3.1.3) - { - sAuthLogonProof_S proof; - memcpy(proof.M2, sha.GetDigest(), 20); - proof.cmd = AUTH_LOGON_PROOF; - proof.error = 0; - proof.unk1 = 0x00800000; - proof.unk2 = 0x00; - proof.unk3 = 0x00; - socket().send((char *)&proof, sizeof(proof)); - } - else - { - sAuthLogonProof_S_Old proof; - memcpy(proof.M2, sha.GetDigest(), 20); - proof.cmd = AUTH_LOGON_PROOF; - proof.error = 0; - //proof.unk1 = 0x00800000; - proof.unk2 = 0x00; - //proof.unk3 = 0x00; - socket().send((char *)&proof, sizeof(proof)); - } - - ///- Set _authed to true! - _authed = true; - } - else - { - char data[4]= { AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0}; - socket().send(data, sizeof(data)); - sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ()); - - uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0); - if (MaxWrongPassCount > 0) - { - //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP - LoginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '%s'",_safelogin.c_str()); - - if (QueryResult_AutoPtr loginfail = LoginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '%s'", _safelogin.c_str())) - { - Field* fields = loginfail->Fetch(); - uint32 failed_logins = fields[1].GetUInt32(); - - if (failed_logins >= MaxWrongPassCount) - { - uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600); - bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false); - - if (WrongPassBanType) - { - uint32 acc_id = fields[0].GetUInt32(); - LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)", - acc_id, WrongPassBanTime); - sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", - _login.c_str(), WrongPassBanTime, failed_logins); - } - else - { - std::string current_ip(socket().get_remote_address().c_str()); - LoginDatabase.escape_string(current_ip); - LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')", - current_ip.c_str(), WrongPassBanTime); - sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times", - current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins); - } - } - } - } - } - - return true; -} - -/// Reconnect Challenge command handler -bool AuthSocket::_HandleReconnectChallenge() -{ - DEBUG_LOG("Entering _HandleReconnectChallenge"); - if (socket().recv_len() < sizeof(sAuthLogonChallenge_C)) - return false; - - ///- Read the first 4 bytes (header) to get the length of the remaining of the packet - std::vector buf; - buf.resize(4); - - socket().recv((char *)&buf[0], 4); - - EndianConvert(*((uint16*)(buf[0]))); - uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; - DEBUG_LOG("[ReconnectChallenge] got header, body is %#04x bytes", remaining); - - if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (socket().recv_len() < remaining)) - return false; - - //No big fear of memory outage (size is int16, i.e. < 65536) - buf.resize(remaining + buf.size() + 1); - buf[buf.size() - 1] = 0; - sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; - - ///- Read the remaining of the packet - socket().recv((char *)&buf[4], remaining); - DEBUG_LOG("[ReconnectChallenge] got full packet, %#04x bytes", ch->size); - DEBUG_LOG("[ReconnectChallenge] name(%d): '%s'", ch->I_len, ch->I); - - _login = (const char*)ch->I; - _safelogin = _login; - - QueryResult_AutoPtr result = LoginDatabase.PQuery ("SELECT sessionkey FROM account WHERE username = '%s'", _safelogin.c_str ()); - - // Stop if the account is not found - if (!result) - { - sLog.outError("[ERROR] user %s tried to login and we cannot find his session key in the database.", _login.c_str()); - socket().shutdown(); - return false; - } - - Field* fields = result->Fetch (); - K.SetHexStr (fields[0].GetString ()); - - ///- Sending response - ByteBuffer pkt; - pkt << (uint8) AUTH_RECONNECT_CHALLENGE; - pkt << (uint8) 0x00; - _reconnectProof.SetRand(16 * 8); - pkt.append(_reconnectProof.AsByteArray(16), 16); // 16 bytes random - pkt << (uint64) 0x00 << (uint64) 0x00; // 16 bytes zeros - socket().send((char const*)pkt.contents(), pkt.size()); - return true; -} - -/// Reconnect Proof command handler -bool AuthSocket::_HandleReconnectProof() -{ - DEBUG_LOG("Entering _HandleReconnectProof"); - ///- Read the packet - sAuthReconnectProof_C lp; - if (!socket().recv((char *)&lp, sizeof(sAuthReconnectProof_C))) - return false; - - if (_login.empty() || !_reconnectProof.GetNumBytes() || !K.GetNumBytes()) - return false; - - BigNumber t1; - t1.SetBinary(lp.R1, 16); - - Sha1Hash sha; - sha.Initialize(); - sha.UpdateData(_login); - sha.UpdateBigNumbers(&t1, &_reconnectProof, &K, NULL); - sha.Finalize(); - - if (!memcmp(sha.GetDigest(), lp.R2, SHA_DIGEST_LENGTH)) - { - ///- Sending response - ByteBuffer pkt; - pkt << (uint8) AUTH_RECONNECT_PROOF; - pkt << (uint8) 0x00; - pkt << (uint16) 0x00; // 2 bytes zeros - socket().send((char const*)pkt.contents(), pkt.size()); - - ///- Set _authed to true! - _authed = true; - - return true; - } - else - { - sLog.outError("[ERROR] user %s tried to login, but session invalid.", _login.c_str()); - socket().shutdown(); - return false; - } -} - -/// %Realm List command handler -bool AuthSocket::_HandleRealmList() -{ - DEBUG_LOG("Entering _HandleRealmList"); - if (socket().recv_len() < 5) - return false; - - socket().recv_skip(5); - - ///- Get the user id (else close the connection) - // No SQL injection (escaped user name) - - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",_safelogin.c_str()); - if (!result) - { - sLog.outError("[ERROR] user %s tried to login and we cannot find him in the database.",_login.c_str()); - socket().shutdown(); - return false; - } - - uint32 id = (*result)[0].GetUInt32(); - - ///- Update realm list if need - sRealmList->UpdateIfNeed(); - - ///- Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) - ByteBuffer pkt; - - size_t RealmListSize = 0; - for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i) - { - // don't work with realms which not compatible with the client - if (_expversion & POST_BC_EXP_FLAG) // 2.4.3 and 3.1.3 cliens - { - if (i->second.gamebuild != _build) - continue; - } - else if (_expversion & PRE_BC_EXP_FLAG) // 1.12.1 and 1.12.2 clients are compatible with eachother - { - if (!AuthHelper::IsPreBCAcceptedClientBuild(i->second.gamebuild)) - continue; - } - - uint8 AmountOfCharacters; - - // No SQL injection. id of realm is controlled by the database. - result = LoginDatabase.PQuery("SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); - if (result) - { - Field *fields = result->Fetch(); - AmountOfCharacters = fields[0].GetUInt8(); - } - else - AmountOfCharacters = 0; - - uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; - - pkt << i->second.icon; // realm type - if ( _expversion & POST_BC_EXP_FLAG )//only 2.4.3 and 3.1.3 cliens - pkt << lock; // if 1, then realm locked - pkt << i->second.color; // if 2, then realm is offline - pkt << i->first; - pkt << i->second.address; - pkt << i->second.populationLevel; - pkt << AmountOfCharacters; - pkt << i->second.timezone; // realm category - if ( _expversion & POST_BC_EXP_FLAG )//2.4.3 and 3.1.3 clients - pkt << (uint8) 0x2C; // unk, may be realm number/id? - else - pkt << (uint8) 0x0; //1.12.1 and 1.12.2 clients - - ++RealmListSize; - } - - if ( _expversion & POST_BC_EXP_FLAG )//2.4.3 and 3.1.3 cliens - { - pkt << (uint8) 0x10; - pkt << (uint8) 0x00; - }else{//1.12.1 and 1.12.2 clients - pkt << (uint8) 0x00; - pkt << (uint8) 0x02; - } - - // make a ByteBuffer which stores the RealmList's size - ByteBuffer RealmListSizeBuffer; - RealmListSizeBuffer << (uint32)0; - if (_expversion & POST_BC_EXP_FLAG) // only 2.4.3 and 3.1.3 cliens - RealmListSizeBuffer << (uint16)RealmListSize; - else - RealmListSizeBuffer << (uint32)RealmListSize; - - ByteBuffer hdr; - hdr << (uint8) REALM_LIST; - hdr << (uint16)(pkt.size() + RealmListSizeBuffer.size()); - hdr.append(RealmListSizeBuffer); // append RealmList's size buffer - hdr.append(pkt); // append realms in the realmlist - - socket().send((char const*)hdr.contents(), hdr.size()); - - return true; -} - -/// Resume patch transfer -bool AuthSocket::_HandleXferResume() -{ - DEBUG_LOG("Entering _HandleXferResume"); - ///- Check packet length and patch existence - if (socket().recv_len() < 9 || !pPatch) - { - sLog.outError("Error while resuming patch transfer (wrong packet)"); - return false; - } - - ///- Launch a PatcherRunnable thread starting at given patch file offset - uint64 start; - socket().recv_skip(1); - socket().recv((char*)&start,sizeof(start)); - fseek(pPatch, start, 0); - - ACE_Based::Thread u(new PatcherRunnable(this)); - return true; -} - -/// Cancel patch transfer -bool AuthSocket::_HandleXferCancel() -{ - DEBUG_LOG("Entering _HandleXferCancel"); - - ///- Close and delete the socket - socket().recv_skip(1); //clear input buffer - - socket().shutdown(); - - return true; -} - -/// Accept patch transfer -bool AuthSocket::_HandleXferAccept() -{ - DEBUG_LOG("Entering _HandleXferAccept"); - - ///- Check packet length and patch existence - if (!pPatch) - { - sLog.outError("Error while accepting patch transfer (wrong packet)"); - return false; - } - - ///- Launch a PatcherRunnable thread, starting at the beginning of the patch file - socket().recv_skip(1); // clear input buffer - fseek(pPatch, 0, 0); - - ACE_Based::Thread u(new PatcherRunnable(this)); - return true; -} - -PatcherRunnable::PatcherRunnable(class AuthSocket * as) -{ - mySocket = as; -} - -/// Send content of patch file to the client -void PatcherRunnable::run() -{ -} - -/// Preload MD5 hashes of existing patch files on server -#ifndef _WIN32 -#include -#include -void Patcher::LoadPatchesInfo() -{ - DIR * dirp; - //int errno; - struct dirent * dp; - dirp = opendir("./patches/"); - if (!dirp) - return; - while (dirp) - { - errno = 0; - if ((dp = readdir(dirp)) != NULL) - { - int l = strlen(dp->d_name); - if (l < 8) - continue; - if (!memcmp(&dp->d_name[l-4],".mpq",4)) - LoadPatchMD5(dp->d_name); - } - else - { - if (errno != 0) - { - closedir(dirp); - return; - } - break; - } - } - - if (dirp) - closedir(dirp); -} - -#else -void Patcher::LoadPatchesInfo() -{ - WIN32_FIND_DATA fil; - HANDLE hFil=FindFirstFile("./patches/*.mpq", &fil); - if (hFil == INVALID_HANDLE_VALUE) - return; // no patches were found - - do - { - LoadPatchMD5(fil.cFileName); - } - while(FindNextFile(hFil, &fil)); -} -#endif - -/// Calculate and store MD5 hash for a given patch file -void Patcher::LoadPatchMD5(char * szFileName) -{ - ///- Try to open the patch file - std::string path = "./patches/"; - path += szFileName; - FILE *pPatch = fopen(path.c_str(), "rb"); - sLog.outDebug("Loading patch info from %s\n", path.c_str()); - if (!pPatch) - { - sLog.outError("Error loading patch %s\n", path.c_str()); - return; - } - - ///- Calculate the MD5 hash - MD5_CTX ctx; - MD5_Init(&ctx); - uint8* buf = new uint8[512*1024]; - - while (!feof(pPatch)) - { - size_t read = fread(buf, 1, 512*1024, pPatch); - MD5_Update(&ctx, buf, read); - } - delete [] buf; - fclose(pPatch); - - ///- Store the result in the internal patch hash map - _patches[path] = new PATCH_INFO; - MD5_Final((uint8 *)&_patches[path]->md5, &ctx); -} - -/// Get cached MD5 hash for a given patch file -bool Patcher::GetHash(char * pat, uint8 mymd5[16]) -{ - for (Patches::iterator i = _patches.begin(); i != _patches.end(); ++i) - if (!stricmp(pat, i->first.c_str())) - { - memcpy(mymd5, i->second->md5, 16); - return true; - } - - return false; -} - -/// Launch the patch hashing mechanism on object creation -Patcher::Patcher() -{ - LoadPatchesInfo(); -} - -/// Empty and delete the patch map on termination -Patcher::~Patcher() -{ - for (Patches::iterator i = _patches.begin(); i != _patches.end(); ++i) - delete i->second; -} diff --git a/src/server/authserver/AuthSocket.h b/src/server/authserver/AuthSocket.h deleted file mode 100644 index bfd0fa4fdca..00000000000 --- a/src/server/authserver/AuthSocket.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup realmd -/// @{ -/// \file - -#ifndef _AUTHSOCKET_H -#define _AUTHSOCKET_H - -#include "Common.h" -#include "Auth/BigNumber.h" - -#include "RealmSocket.h" - -enum RealmFlags -{ - REALM_FLAG_NONE = 0x00, - REALM_FLAG_INVALID = 0x01, - REALM_FLAG_OFFLINE = 0x02, - REALM_FLAG_SPECIFYBUILD = 0x04, // client will show realm version in RealmList screen in form "RealmName (major.minor.revision.build)" - REALM_FLAG_UNK1 = 0x08, - REALM_FLAG_UNK2 = 0x10, - REALM_FLAG_RECOMMENDED = 0x20, // client checks pop == 600f - REALM_FLAG_NEW = 0x40, // client checks pop == 200f - REALM_FLAG_FULL = 0x80 // client checks pop == 400f -}; - -/// Handle login commands -class AuthSocket: public RealmSocket::Session -{ - public: - const static int s_BYTE_SIZE = 32; - - AuthSocket(RealmSocket& socket); - virtual ~AuthSocket(void); - - virtual void OnRead(void); - virtual void OnAccept(void); - virtual void OnClose(void); - - bool _HandleLogonChallenge(); - bool _HandleLogonProof(); - bool _HandleReconnectChallenge(); - bool _HandleReconnectProof(); - bool _HandleRealmList(); - //data transfer handle for patch - - bool _HandleXferResume(); - bool _HandleXferCancel(); - bool _HandleXferAccept(); - - void _SetVSFields(const std::string& rI); - - FILE *pPatch; - ACE_Thread_Mutex patcherLock; - - private: - RealmSocket& socket_; - RealmSocket& socket(void) { return socket_; } - - BigNumber N, s, g, v; - BigNumber b, B; - BigNumber K; - BigNumber _reconnectProof; - - bool _authed; - - std::string _login; - std::string _safelogin; - - // Since GetLocaleByName() is _NOT_ bijective, we have to store the locale as a string. Otherwise we can't differ - // between enUS and enGB, which is important for the patch system - std::string _localizationName; - uint16 _build; - uint8 _expversion; - AccountTypes _accountSecurityLevel; -}; -#endif -/// @} diff --git a/src/server/authserver/RealmAcceptor.h b/src/server/authserver/RealmAcceptor.h deleted file mode 100644 index 5e243ea915b..00000000000 --- a/src/server/authserver/RealmAcceptor.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup realmd - */ - -#ifndef __REALMACCEPTOR_H__ -#define __REALMACCEPTOR_H__ - -#include -#include - -#include "RealmSocket.h" -#include "AuthSocket.h" - -class RealmAcceptor : public ACE_Acceptor -{ - public: - RealmAcceptor(void) { } - virtual ~RealmAcceptor(void) { } - - protected: - virtual int make_svc_handler(RealmSocket *&sh) - { - if (sh == 0) - ACE_NEW_RETURN(sh, RealmSocket, -1); - - sh->reactor(reactor()); - sh->set_session(new AuthSocket(*sh)); - return 0; - } -}; - -#endif /* __REALMACCEPTOR_H__ */ diff --git a/src/server/authserver/RealmList.cpp b/src/server/authserver/RealmList.cpp deleted file mode 100644 index 1e989c36c5d..00000000000 --- a/src/server/authserver/RealmList.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup realmd -*/ - -#include "Common.h" -#include "RealmList.h" -#include "Database/DatabaseEnv.h" - - -extern DatabaseType LoginDatabase; - -RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)) -{ -} - -/// Load the realm list from the database -void RealmList::Initialize(uint32 updateInterval) -{ - m_UpdateInterval = updateInterval; - - ///- Get the content of the realmlist table in the database - UpdateRealms(true); -} - -void RealmList::UpdateRealm(uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build) -{ - ///- Create new if not exist or update existed - Realm& realm = m_realms[name]; - - realm.m_ID = ID; - realm.name = name; - realm.icon = icon; - realm.color = color; - realm.timezone = timezone; - realm.allowedSecurityLevel = allowedSecurityLevel; - realm.populationLevel = popu; - - ///- Append port to IP address. - std::ostringstream ss; - ss << address << ":" << port; - realm.address = ss.str(); - realm.gamebuild = build; -} - -void RealmList::UpdateIfNeed() -{ - // maybe disabled or updated recently - if (!m_UpdateInterval || m_NextUpdateTime > time(NULL)) - return; - - m_NextUpdateTime = time(NULL) + m_UpdateInterval; - - // Clears Realm list - m_realms.clear(); - - // Get the content of the realmlist table in the database - UpdateRealms(false); -} - -void RealmList::UpdateRealms(bool init) -{ - sLog.outDetail("Updating Realm List..."); - - QueryResult_AutoPtr result = LoginDatabase.Query("SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE color <> 3 ORDER BY name"); - - ///- Circle through results and add them to the realm map - if (result) - { - do - { - Field *fields = result->Fetch(); - - uint8 allowedSecurityLevel = fields[7].GetUInt8(); - - UpdateRealm(fields[0].GetUInt32(), fields[1].GetCppString(),fields[2].GetCppString(),fields[3].GetUInt32(),fields[4].GetUInt8(), fields[5].GetUInt8(), fields[6].GetUInt8(), (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), fields[8].GetFloat(), fields[9].GetUInt32()); - if (init) - sLog.outString("Added realm \"%s\".", fields[1].GetString()); - } while(result->NextRow()); - } -} diff --git a/src/server/authserver/RealmList.h b/src/server/authserver/RealmList.h deleted file mode 100644 index b29b561c797..00000000000 --- a/src/server/authserver/RealmList.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup realmd -/// @{ -/// \file - -#ifndef _REALMLIST_H -#define _REALMLIST_H - -#include -#include -#include "Common.h" - -/// Storage object for a realm -struct Realm -{ - std::string address; - std::string name; - uint8 icon; - uint8 color; - uint8 timezone; - uint32 m_ID; - AccountTypes allowedSecurityLevel; - float populationLevel; - uint32 gamebuild; -}; - -/// Storage object for the list of realms on the server -class RealmList -{ - public: - // Null_Mutex is safe because the singleton initialized before the acceptor initialized(another place where the singleton called) - static RealmList* instance() { return ACE_Singleton::instance(); } - - typedef std::map RealmMap; - - RealmList(); - ~RealmList() {} - - void Initialize(uint32 updateInterval); - - void UpdateIfNeed(); - - void AddRealm(Realm NewRealm) {m_realms[NewRealm.name] = NewRealm;} - - RealmMap::const_iterator begin() const { return m_realms.begin(); } - RealmMap::const_iterator end() const { return m_realms.end(); } - uint32 size() const { return m_realms.size(); } - private: - void UpdateRealms(bool init); - void UpdateRealm(uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build); - private: - RealmMap m_realms; ///< Internal map of realms - uint32 m_UpdateInterval; - time_t m_NextUpdateTime; -}; - -#define sRealmList RealmList::instance() - -#endif -/// @} diff --git a/src/server/authserver/RealmSocket.cpp b/src/server/authserver/RealmSocket.cpp deleted file mode 100644 index 7eb96cb96f8..00000000000 --- a/src/server/authserver/RealmSocket.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup realmd - */ - -#include "RealmSocket.h" - -#include "Log.h" - -#include -#include -#include - -#ifndef MSG_NOSIGNAL -#define MSG_NOSIGNAL 0 -#endif - -RealmSocket::Session::Session(void) -{ -} - -RealmSocket::Session::~Session(void) -{ -} - -RealmSocket::RealmSocket(void): - session_(NULL), - input_buffer_(4096), - remote_address_() -{ - reference_counting_policy().value( - ACE_Event_Handler::Reference_Counting_Policy::ENABLED); - - msg_queue()->high_water_mark(8*1024*1024); - msg_queue()->low_water_mark(8*1024*1024); - -} - -RealmSocket::~RealmSocket(void) -{ - if (msg_queue()) - msg_queue()->close(); - - // delete RealmSocketObject must never be called from our code. - closing_ = true; - - if (session_) - delete session_; - - peer().close(); -} - -int RealmSocket::open(void * arg) -{ - ACE_INET_Addr addr; - - if (peer ().get_remote_addr (addr) == -1) - { - sLog.outError ("RealmSocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror (errno)); - return -1; - } - - remote_address_ = addr.get_host_addr(); - - // Register with ACE Reactor - if (Base::open(arg) == -1) - return -1; - - if (session_ != NULL) - { - session_->OnAccept(); - } - - // reactor takes care of the socket from now on - remove_reference(); - - return 0; -} - -int RealmSocket::close(int) -{ - shutdown(); - - closing_ = true; - - remove_reference(); - - return 0; -} - -const ACE_CString& RealmSocket::get_remote_address(void) const -{ - return remote_address_; -} - -size_t RealmSocket::recv_len(void) const -{ - return input_buffer_.length(); -} - -bool RealmSocket::recv_soft(char *buf, size_t len) -{ - if (input_buffer_.length() < len) - return false; - - ACE_OS::memcpy(buf, input_buffer_.rd_ptr(), len); - - return true; -} - -bool RealmSocket::recv(char *buf, size_t len) -{ - bool ret = recv_soft(buf, len); - - if (ret) - recv_skip(len); - - return ret; -} - -void RealmSocket::recv_skip(size_t len) -{ - input_buffer_.rd_ptr(len); -} - -ssize_t RealmSocket::noblk_send(ACE_Message_Block &message_block) -{ - const size_t len = message_block.length(); - - if (len == 0) - return -1; - - // Try to send the message directly. - ssize_t n = peer().send(message_block.rd_ptr(), len, MSG_NOSIGNAL); - - if (n < 0) - { - if (errno == EWOULDBLOCK) - // Blocking signal - return 0; - else - // Error happened - return -1; - } - else if (n == 0) - { - // Can this happen ? - return -1; - } - - // return bytes transmitted - return n; -} - -bool RealmSocket::send(const char *buf, size_t len) -{ - if (buf == NULL || len == 0) - return true; - - ACE_Data_Block db( - len, - ACE_Message_Block::MB_DATA, - (const char*)buf, - 0, - 0, - ACE_Message_Block::DONT_DELETE, - 0); - - ACE_Message_Block message_block( - &db, - ACE_Message_Block::DONT_DELETE, - 0); - - message_block.wr_ptr(len); - - if (msg_queue()->is_empty()) - { - // Try to send it directly. - ssize_t n = noblk_send(message_block); - - if (n < 0) - return false; - else if (n == len) - return true; - - // fall down - message_block.rd_ptr((size_t)n); - } - - ACE_Message_Block *mb = message_block.clone(); - - if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value *) &ACE_Time_Value::zero) == -1) - { - mb->release(); - return false; - } - - if (reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK) == -1) - return false; - - return true; -} - -int RealmSocket::handle_output(ACE_HANDLE /*= ACE_INVALID_HANDLE*/) -{ - if (closing_) - return -1; - - ACE_Message_Block *mb = 0; - - if (msg_queue()->is_empty()) - { - reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK); - return 0; - } - - if (msg_queue()->dequeue_head(mb, (ACE_Time_Value *) &ACE_Time_Value::zero) == -1) - return -1; - - ssize_t n = noblk_send(*mb); - - if (n < 0) - { - mb->release(); - return -1; - } - else if (n == mb->length()) - { - mb->release(); - return 1; - } - else - { - mb->rd_ptr(n); - - if (msg_queue()->enqueue_head(mb, (ACE_Time_Value *) &ACE_Time_Value::zero) == -1) - { - mb->release(); - return -1; - } - - return 0; - } - - ACE_NOTREACHED(return -1); -} - -int RealmSocket::handle_close(ACE_HANDLE h, ACE_Reactor_Mask /*m*/) -{ - // As opposed to WorldSocket::handle_close, we don't need locks here. - - closing_ = true; - - if (h == ACE_INVALID_HANDLE) - peer ().close_writer (); - - if (session_ != NULL) - { - session_->OnClose(); - } - - return 0; -} - -int RealmSocket::handle_input(ACE_HANDLE /*= ACE_INVALID_HANDLE*/) -{ - if (closing_) - return -1; - - const ssize_t space = input_buffer_.space(); - - ssize_t n = peer().recv(input_buffer_.wr_ptr(), space); - - if (n < 0) - { - return errno == EWOULDBLOCK ? 0 : -1; - } - else if (n == 0) - { - // EOF - return -1; - } - - input_buffer_.wr_ptr((size_t)n); - - if (session_ != NULL) - { - session_->OnRead(); - - input_buffer_.crunch(); - } - - // return 1 in case there is more data to read from OS - return n == space ? 1 : 0; -} - - -void RealmSocket::set_session(Session* session) -{ - if (session_ != NULL) - delete session_; - - session_ = session; -} - diff --git a/src/server/authserver/RealmSocket.h b/src/server/authserver/RealmSocket.h deleted file mode 100644 index 13be8327533..00000000000 --- a/src/server/authserver/RealmSocket.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup realmd - */ - -#ifndef __REALMSOCKET_H__ -#define __REALMSOCKET_H__ - -#include -#include -#include -#include -#include -#include - -class RealmSocket : public ACE_Svc_Handler -{ - private: - typedef ACE_Svc_Handler Base; - - public: - class Session - { - public: - Session(void); - virtual ~Session(void); - - virtual void OnRead(void) = 0; - virtual void OnAccept(void) = 0; - virtual void OnClose(void) = 0; - }; - - RealmSocket(void); - virtual ~RealmSocket(void); - - size_t recv_len(void) const; - bool recv_soft(char *buf, size_t len); - bool recv(char *buf, size_t len); - void recv_skip(size_t len); - - bool send(const char *buf, size_t len); - - const ACE_CString& get_remote_address(void) const; - - virtual int open(void *); - - virtual int close(int); - - virtual int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE); - virtual int handle_output(ACE_HANDLE = ACE_INVALID_HANDLE); - - virtual int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE, - ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); - - void set_session(Session* session); - - private: - ssize_t noblk_send(ACE_Message_Block &message_block); - - private: - ACE_Message_Block input_buffer_; - Session* session_; - ACE_CString remote_address_; -}; - -#endif /* __REALMSOCKET_H__ */ diff --git a/src/server/worldserver/CliRunnable.cpp b/src/server/worldserver/CliRunnable.cpp deleted file mode 100644 index b39faf694db..00000000000 --- a/src/server/worldserver/CliRunnable.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup Trinityd -/// @{ -/// \file - -#include "Common.h" -#include "ObjectMgr.h" -#include "World.h" -#include "WorldSession.h" -#include "Config/ConfigEnv.h" - -#include "AccountMgr.h" -#include "Chat.h" -#include "CliRunnable.h" -#include "Language.h" -#include "Log.h" -#include "MapManager.h" -#include "Player.h" -#include "Util.h" - -#if PLATFORM != WINDOWS -#include -#include - -char * command_finder(const char* text, int state) -{ - static int idx,len; - const char* ret; - ChatCommand *cmd = ChatHandler::getCommandTable(); - - if(!state) - { - idx = 0; - len = strlen(text); - } - - while(ret = cmd[idx].Name) - { - if(!cmd[idx].AllowConsole) - { - idx++; - continue; - } - - idx++; - //printf("Checking %s \n", cmd[idx].Name); - if (strncmp(ret, text, len) == 0) - return strdup(ret); - if(cmd[idx].Name == NULL) - break; - } - - return ((char*)NULL); -} - -char ** cli_completion(const char * text, int start, int end) -{ - char ** matches; - matches = (char**)NULL; - - if(start == 0) - matches = rl_completion_matches((char*)text,&command_finder); - else - rl_bind_key('\t',rl_abort); - return (matches); -} -#endif - -void utf8print(const char* str) -{ -#if PLATFORM == PLATFORM_WINDOWS - wchar_t wtemp_buf[6000]; - size_t wtemp_len = 6000-1; - if(!Utf8toWStr(str,strlen(str),wtemp_buf,wtemp_len)) - return; - - char temp_buf[6000]; - CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1); - printf(temp_buf); -#else -{ - va_list v; - vprintf(str, v); - va_end(v); - fflush(stdout); -} -#endif -} - -/// Delete a user account and all associated characters in this realm -/// \todo This function has to be enhanced to respect the login/realm split (delete char, delete account chars in realm, delete account chars in realm then delete account -bool ChatHandler::HandleAccountDeleteCommand(const char* args) -{ - if(!*args) - return false; - - ///- Get the account name from the command line - char *account_name_str=strtok ((char*)args," "); - if (!account_name_str) - return false; - - std::string account_name = account_name_str; - if(!AccountMgr::normalizeString(account_name)) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - uint32 account_id = accmgr.GetId(account_name); - if(!account_id) - { - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - /// Commands not recommended call from chat, but support anyway - /// can delete only for account with less security - /// This is also reject self apply in fact - if(HasLowerSecurityAccount (NULL,account_id,true)) - return false; - - AccountOpResult result = accmgr.DeleteAccount(account_id); - switch(result) - { - case AOR_OK: - PSendSysMessage(LANG_ACCOUNT_DELETED,account_name.c_str()); - break; - case AOR_NAME_NOT_EXIST: - PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); - SetSentErrorMessage(true); - return false; - case AOR_DB_INTERNAL_ERROR: - PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR,account_name.c_str()); - SetSentErrorMessage(true); - return false; - default: - PSendSysMessage(LANG_ACCOUNT_NOT_DELETED,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -bool ChatHandler::HandleCharacterDeleteCommand(const char* args) -{ - if(!*args) - return false; - - char *character_name_str = strtok((char*)args," "); - if(!character_name_str) - return false; - - std::string character_name = character_name_str; - if(!normalizePlayerName(character_name)) - return false; - - uint64 character_guid; - uint32 account_id; - - Player *player = objmgr.GetPlayer(character_name.c_str()); - if(player) - { - character_guid = player->GetGUID(); - account_id = player->GetSession()->GetAccountId(); - player->GetSession()->KickPlayer(); - } - else - { - character_guid = objmgr.GetPlayerGUIDByName(character_name); - if(!character_guid) - { - PSendSysMessage(LANG_NO_PLAYER,character_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - account_id = objmgr.GetPlayerAccountIdByGUID(character_guid); - } - - std::string account_name; - accmgr.GetName (account_id,account_name); - - Player::DeleteFromDB(character_guid, account_id, true); - PSendSysMessage(LANG_CHARACTER_DELETED,character_name.c_str(),GUID_LOPART(character_guid),account_name.c_str(), account_id); - return true; -} - -/// Exit the realm -bool ChatHandler::HandleServerExitCommand(const char* /*args*/) -{ - SendSysMessage(LANG_COMMAND_EXIT); - World::StopNow(SHUTDOWN_EXIT_CODE); - return true; -} - -/// Display info on users currently in the realm -bool ChatHandler::HandleAccountOnlineListCommand(const char* /*args*/) -{ - ///- Get the list of accounts ID logged to the realm - QueryResult_AutoPtr resultDB = CharacterDatabase.Query("SELECT name,account,map,zone FROM characters WHERE online > 0"); - if (!resultDB) - { - SendSysMessage(LANG_ACCOUNT_LIST_EMPTY); - return true; - } - - ///- Display the list of account/characters online - SendSysMessage(LANG_ACCOUNT_LIST_BAR_HEADER); - SendSysMessage(LANG_ACCOUNT_LIST_HEADER); - SendSysMessage(LANG_ACCOUNT_LIST_BAR); - - ///- Circle through accounts - do - { - Field *fieldsDB = resultDB->Fetch(); - std::string name = fieldsDB[0].GetCppString(); - uint32 account = fieldsDB[1].GetUInt32(); - - ///- Get the username, last IP and GM level of each account - // No SQL injection. account is uint32. - QueryResult_AutoPtr resultLogin = - LoginDatabase.PQuery("SELECT a.username, a.last_ip, aa.gmlevel, a.expansion " - "FROM account a " - "LEFT JOIN account_access aa " - "ON (a.id = aa.id) " - "WHERE a.id = '%u'", account); - if(resultLogin) - { - Field *fieldsLogin = resultLogin->Fetch(); - PSendSysMessage(LANG_ACCOUNT_LIST_LINE, - fieldsLogin[0].GetString(),name.c_str(),fieldsLogin[1].GetString(),fieldsDB[2].GetInt32(),fieldsDB[3].GetInt32(),fieldsLogin[3].GetUInt32(),fieldsLogin[2].GetUInt32()); - } - else - PSendSysMessage(LANG_ACCOUNT_LIST_ERROR,name.c_str()); - - }while(resultDB->NextRow()); - - SendSysMessage(LANG_ACCOUNT_LIST_BAR); - return true; -} - -/// Create an account -bool ChatHandler::HandleAccountCreateCommand(const char* args) -{ - if(!*args) - return false; - - ///- %Parse the command line arguments - char *szAcc = strtok((char*)args, " "); - char *szPassword = strtok(NULL, " "); - if(!szAcc || !szPassword) - return false; - - // normalized in accmgr.CreateAccount - std::string account_name = szAcc; - std::string password = szPassword; - - AccountOpResult result = accmgr.CreateAccount(account_name, password); - switch(result) - { - case AOR_OK: - PSendSysMessage(LANG_ACCOUNT_CREATED,account_name.c_str()); - break; - case AOR_NAME_TOO_LONG: - SendSysMessage(LANG_ACCOUNT_TOO_LONG); - SetSentErrorMessage(true); - return false; - case AOR_NAME_ALREDY_EXIST: - SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); - SetSentErrorMessage(true); - return false; - case AOR_DB_INTERNAL_ERROR: - PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR,account_name.c_str()); - SetSentErrorMessage(true); - return false; - default: - PSendSysMessage(LANG_ACCOUNT_NOT_CREATED,account_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - return true; -} - -/// Set the level of logging -bool ChatHandler::HandleServerSetLogFileLevelCommand(const char *args) -{ - if(!*args) - return false; - - char *NewLevel = strtok((char*)args, " "); - if (!NewLevel) - return false; - - sLog.SetLogFileLevel(NewLevel); - return true; -} - -/// Set the level of logging -bool ChatHandler::HandleServerSetLogLevelCommand(const char *args) -{ - if(!*args) - return false; - - char *NewLevel = strtok((char*)args, " "); - if (!NewLevel) - return false; - - sLog.SetLogLevel(NewLevel); - return true; -} - -/// set diff time record interval -bool ChatHandler::HandleServerSetDiffTimeCommand(const char *args) -{ - if(!*args) - return false; - - char *NewTimeStr = strtok((char*)args, " "); - if(!NewTimeStr) - return false; - - int32 NewTime =atoi(NewTimeStr); - if(NewTime < 0) - return false; - - sWorld.SetRecordDiffInterval(NewTime); - printf( "Record diff every %u ms\n", NewTime); - return true; -} - -/// @} - -#ifdef linux -// Non-blocking keypress detector, when return pressed, return 1, else always return 0 -int kb_hit_return() -{ - struct timeval tv; - fd_set fds; - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&fds); - FD_SET(STDIN_FILENO, &fds); - select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); - return FD_ISSET(STDIN_FILENO, &fds); -} -#endif - -/// %Thread start -void CliRunnable::run() -{ - ///- Init new SQL thread for the world database (one connection call enough) - WorldDatabase.ThreadStart(); // let thread do safe mySQL requests - - char commandbuf[256]; - - ///- Display the list of available CLI functions then beep - sLog.outString(""); - #if PLATFORM != WINDOWS - rl_attempted_completion_function = cli_completion; - #endif - if(sConfig.GetBoolDefault("BeepAtStart", true)) - printf("\a"); // \a = Alert - - // print this here the first time - // later it will be printed after command queue updates - printf("TC>"); - - ///- As long as the World is running (no World::m_stopEvent), get the command line and handle it - while (!World::IsStopped()) - { - fflush(stdout); - - char *command_str ; // = fgets(commandbuf,sizeof(commandbuf),stdin); - - #if PLATFORM == WINDOWS - command_str = fgets(commandbuf,sizeof(commandbuf),stdin); - #else - command_str = readline("TC>"); - rl_bind_key('\t',rl_complete); - #endif - if (command_str != NULL) - { - for (int x=0; command_str[x]; x++) - if(command_str[x]=='\r'||command_str[x]=='\n') - { - command_str[x]=0; - break; - } - - if(!*command_str) - { - #if PLATFORM == WINDOWS - printf("TC>"); - #endif - continue; - } - - std::string command; - if(!consoleToUtf8(command_str,command)) // convert from console encoding to utf8 - { - #if PLATFORM == WINDOWS - printf("TC>"); - #endif - continue; - } - fflush(stdout); - sWorld.QueueCliCommand(&utf8print,command.c_str()); - #if PLATFORM != WINDOWS - add_history(command.c_str()); - #endif - - } - else if (feof(stdin)) - { - World::StopNow(SHUTDOWN_EXIT_CODE); - } - - } - - ///- End the database thread - WorldDatabase.ThreadEnd(); // free mySQL thread resources -} diff --git a/src/server/worldserver/CliRunnable.h b/src/server/worldserver/CliRunnable.h deleted file mode 100644 index 9f990b2b469..00000000000 --- a/src/server/worldserver/CliRunnable.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup Trinityd -/// @{ -/// \file - -#ifndef __CLIRUNNABLE_H -#define __CLIRUNNABLE_H - -/// Command Line Interface handling thread -class CliRunnable : public ACE_Based::Runnable -{ - public: - void run(); -}; -#endif -/// @} diff --git a/src/server/worldserver/RASocket.cpp b/src/server/worldserver/RASocket.cpp deleted file mode 100644 index 32c16d9980f..00000000000 --- a/src/server/worldserver/RASocket.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup Trinityd -*/ - -#include "Common.h" -#include "Config/ConfigEnv.h" -#include "Database/DatabaseEnv.h" -#include "AccountMgr.h" -#include "Log.h" -#include "RASocket.h" -#include "Util.h" -#include "World.h" - -/// \todo Make this thread safe if in the future 2 admins should be able to log at the same time. -SOCKET r; - -#define dropclient {Sendf("I'm busy right now, come back later."); \ - SetCloseAndDelete(); \ - return; \ - } - -uint32 iSession=0; ///< Session number (incremented each time a new connection is made) -unsigned int iUsers=0; ///< Number of active administrators - -typedef int(* pPrintf)(const char*,...); - -void ParseCommand(CliCommandHolder::Print*, char*command); - -/// RASocket constructor -RASocket::RASocket(ISocketHandler &h): TcpSocket(h) -{ - - ///- Increment the session number - iSess =iSession++ ; - - ///- Get the config parameters - bSecure = sConfig.GetBoolDefault( "RA.Secure", true ); - iMinLevel = sConfig.GetIntDefault( "RA.MinLevel", 3 ); - - ///- Initialize buffer and data - iInputLength=0; - buff=new char[RA_BUFF_SIZE]; - stage=NONE; -} - -/// RASocket destructor -RASocket::~RASocket() -{ - ///- Delete buffer and decrease active admins count - delete [] buff; - - sLog.outRemote("Connection was closed.\n"); - - if(stage==OK) - iUsers--; -} - -/// Accept an incoming connection -void RASocket::OnAccept() -{ - std::string ss=GetRemoteAddress(); - sLog.outRemote("Incoming connection from %s.\n",ss.c_str()); - ///- If there is already an active admin, drop the connection - if(iUsers) - dropclient - - ///- Else print Motd - Sendf("%s\r\n",sWorld.GetMotd()); -} - -/// Read data from the network -void RASocket::OnRead() -{ - ///- Read data and check input length - TcpSocket::OnRead(); - - unsigned int sz=ibuf.GetLength(); - if(iInputLength+sz>=RA_BUFF_SIZE) - { - sLog.outRemote("Input buffer overflow, possible DOS attack.\n"); - SetCloseAndDelete(); - return; - } - - ///- If there is already an active admin (other than you), drop the connection - if(stage!=OK && iUsers) - dropclient - - char *inp = new char [sz+1]; - ibuf.Read(inp,sz); - - /// \todo Can somebody explain this 'Linux bugfix'? - if(stage==NONE) - if(sz>4) //linux remote telnet - if(memcmp(inp ,"USER ",5)) - { - delete [] inp;return; - printf("lin bugfix"); - } //linux bugfix - - ///- Discard data after line break or line feed - bool gotenter=false; - unsigned int y=0; - for (; y
  • If the input is 'USER ' - case NONE: - if(!memcmp(buff,"USER ",5)) //got "USER" cmd - { - szLogin=&buff[5]; - - ///- Get the password from the account table - std::string login = szLogin; - - ///- Convert Account name to Upper Format - AccountMgr::normalizeString(login); - - ///- Escape the Login to allow quotes in names - LoginDatabase.escape_string(login); - - QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT a.id, aa.gmlevel, aa.RealmID FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = '%s'",login.c_str ()); - - ///- If the user is not found, deny access - if(!result) - { - Sendf("-No such user.\r\n"); - sLog.outRemote("User %s does not exist.\n",szLogin.c_str()); - if(bSecure)SetCloseAndDelete(); - } - else - { - Field *fields = result->Fetch(); - - //szPass=fields[0].GetString(); - - ///- if gmlevel is too low, deny access - if(fields[1].GetUInt32() If the input is 'PASS ' (and the user already gave his username) - case LG: - if(!memcmp(buff,"PASS ",5)) //got "PASS" cmd - { //login+pass ok - ///- If password is correct, increment the number of active administrators - std::string login = szLogin; - std::string pw = &buff[5]; - - AccountMgr::normalizeString(login); - AccountMgr::normalizeString(pw); - LoginDatabase.escape_string(login); - LoginDatabase.escape_string(pw); - - QueryResult_AutoPtr check = LoginDatabase.PQuery( - "SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT('%s',':','%s'))", - login.c_str(), login.c_str(), pw.c_str()); - - if(check) - { - r=GetSocket(); - stage=OK; - ++iUsers; - - Sendf("+Logged in.\r\n"); - sLog.outRemote("User %s has logged in.\n",szLogin.c_str()); - Sendf("TC>"); - } - else - { - ///- Else deny access - Sendf("-Wrong pass.\r\n"); - sLog.outRemote("User %s has failed to log in.\n",szLogin.c_str()); - if(bSecure)SetCloseAndDelete(); - } - } - break; - ///
  • If user is logged, parse and execute the command - case OK: - if(strlen(buff)) - { - sLog.outRemote("Got '%s' cmd.\n",buff); - sWorld.QueueCliCommand(&RASocket::zprint , buff); - } - else - Sendf("TC>"); - break; - /// - }; - - } -} - -/// Output function -void RASocket::zprint( const char * szText ) -{ - if( !szText ) - return; - - #ifdef RA_CRYPT - - char *megabuffer=strdup(szText); - unsigned int sz=strlen(megabuffer); - Encrypt(megabuffer,sz); - send(r,megabuffer,sz,0); - delete [] megabuffer; - - #else - - unsigned int sz=strlen(szText); - send(r,szText,sz,0); - - #endif -} diff --git a/src/server/worldserver/RASocket.h b/src/server/worldserver/RASocket.h deleted file mode 100644 index 5c13724f90d..00000000000 --- a/src/server/worldserver/RASocket.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup Trinityd -/// @{ -/// \file - -#ifndef _RASOCKET_H -#define _RASOCKET_H - -#include "sockets/TcpSocket.h" - -#include "Common.h" - -#define RA_BUFF_SIZE 1024 - -class ISocketHandler; - -/// Remote Administration socket -class RASocket: public TcpSocket -{ - public: - - RASocket(ISocketHandler& h); - ~RASocket(); - - void OnAccept(); - void OnRead(); - - private: - - char * buff; - std::string szLogin; - uint32 iSess; - unsigned int iInputLength; - bool bLog; - bool bSecure; //kick on wrong pass, non exist. user, user with no priv - //will protect from DOS, bruteforce attacks - //some 'smart' protection must be added for more security - uint8 iMinLevel; - enum - { - NONE, //initial value - LG, //only login was entered - OK, //both login and pass were given, and they are correct and user have enough priv. - }stage; - - static void zprint( const char * szText ); -}; -#endif -/// @} diff --git a/src/server/worldserver/WorldRunnable.cpp b/src/server/worldserver/WorldRunnable.cpp deleted file mode 100644 index c674ddbc06f..00000000000 --- a/src/server/worldserver/WorldRunnable.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** \file - \ingroup Trinityd -*/ - -#include "Common.h" -#include "ObjectAccessor.h" -#include "World.h" -#include "WorldSocketMgr.h" -#include "Database/DatabaseEnv.h" - -#include "BattleGroundMgr.h" -#include "MapManager.h" -#include "Timer.h" -#include "WorldRunnable.h" - -#define WORLD_SLEEP_CONST 50 - -#ifdef WIN32 -#include "ServiceWin32.h" -extern int m_ServiceStatus; -#endif - -/// Heartbeat for the World -void WorldRunnable::run() -{ - ///- Init new SQL thread for the world database - WorldDatabase.ThreadStart(); // let thread do safe mySQL requests (one connection call enough) - - sWorld.InitResultQueue(); - - uint32 realCurrTime = 0; - uint32 realPrevTime = getMSTime(); - - uint32 prevSleepTime = 0; // used for balanced full tick time length near WORLD_SLEEP_CONST - - ///- While we have not World::m_stopEvent, update the world - while (!World::IsStopped()) - { - ++World::m_worldLoopCounter; - realCurrTime = getMSTime(); - - uint32 diff = getMSTimeDiff(realPrevTime,realCurrTime); - - sWorld.Update( diff ); - realPrevTime = realCurrTime; - - // diff (D0) include time of previous sleep (d0) + tick time (t0) - // we want that next d1 + t1 == WORLD_SLEEP_CONST - // we can't know next t1 and then can use (t0 + d1) == WORLD_SLEEP_CONST requirement - // d1 = WORLD_SLEEP_CONST - t0 = WORLD_SLEEP_CONST - (D0 - d0) = WORLD_SLEEP_CONST + d0 - D0 - if (diff <= WORLD_SLEEP_CONST+prevSleepTime) - { - prevSleepTime = WORLD_SLEEP_CONST+prevSleepTime-diff; - ACE_Based::Thread::Sleep(prevSleepTime); - } - else - prevSleepTime = 0; - - #ifdef WIN32 - if (m_ServiceStatus == 0) World::StopNow(SHUTDOWN_EXIT_CODE); - while (m_ServiceStatus == 2) Sleep(1000); - #endif - } - - sWorld.KickAll(); // save and kick all players - sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call - - // unload battleground templates before different singletons destroyed - sBattleGroundMgr.DeleteAllBattleGrounds(); - - sWorldSocketMgr->StopNetwork(); - - MapManager::Instance().UnloadAll(); // unload all grids (including locked in memory) - - ///- End the database thread - WorldDatabase.ThreadEnd(); // free mySQL thread resources -} diff --git a/src/server/worldserver/WorldRunnable.h b/src/server/worldserver/WorldRunnable.h deleted file mode 100644 index f14ee021f36..00000000000 --- a/src/server/worldserver/WorldRunnable.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/// \addtogroup Trinityd -/// @{ -/// \file - -#ifndef __WORLDRUNNABLE_H -#define __WORLDRUNNABLE_H - -/// Heartbeat thread for the World -class WorldRunnable : public ACE_Based::Runnable -{ - public: - void run(); -}; -#endif -/// @} -- cgit v1.2.3 From 57f64f1f5a8eccff388211e0d08bf9d630d48ada Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:18:57 +0200 Subject: * Restructuring shared. --HG-- branch : trunk --- src/server/shared/Auth/AuthCrypt.cpp | 81 -- src/server/shared/Auth/AuthCrypt.h | 47 - src/server/shared/Auth/BigNumber.cpp | 201 ---- src/server/shared/Auth/BigNumber.h | 96 -- src/server/shared/Auth/CMakeLists.txt | 27 - src/server/shared/Auth/Hmac.cpp | 62 -- src/server/shared/Auth/Hmac.h | 49 - src/server/shared/Auth/SARC4.cpp | 52 - src/server/shared/Auth/SARC4.h | 36 - src/server/shared/Auth/Sha1.cpp | 69 -- src/server/shared/Auth/Sha1.h | 53 - src/server/shared/Auth/md5.c | 385 -------- src/server/shared/Auth/md5.h | 92 -- src/server/shared/ByteBuffer.h | 601 ------------ src/server/shared/Config/CMakeLists.txt | 22 - src/server/shared/Config/Config.cpp | 105 -- src/server/shared/Config/Config.h | 53 - src/server/shared/Config/ConfigEnv.h | 30 - src/server/shared/Config/ConfigLibrary.vcproj | 137 --- src/server/shared/Config/dotconfpp/dotconfpp.cpp | 599 ------------ src/server/shared/Config/dotconfpp/dotconfpp.h | 97 -- src/server/shared/Config/dotconfpp/mempool.cpp | 100 -- src/server/shared/Config/dotconfpp/mempool.h | 46 - src/server/shared/Configuration/CMakeLists.txt | 22 + src/server/shared/Configuration/Config.cpp | 105 ++ src/server/shared/Configuration/Config.h | 53 + src/server/shared/Configuration/ConfigEnv.h | 30 + .../shared/Configuration/ConfigLibrary.vcproj | 137 +++ .../shared/Configuration/dotconfpp/dotconfpp.cpp | 599 ++++++++++++ .../shared/Configuration/dotconfpp/dotconfpp.h | 97 ++ .../shared/Configuration/dotconfpp/mempool.cpp | 100 ++ .../shared/Configuration/dotconfpp/mempool.h | 46 + .../Cryptography/Authentication/AuthCrypt.cpp | 81 ++ .../shared/Cryptography/Authentication/AuthCrypt.h | 47 + src/server/shared/Cryptography/BigNumber.cpp | 201 ++++ src/server/shared/Cryptography/BigNumber.h | 96 ++ src/server/shared/Cryptography/CMakeLists.txt | 27 + src/server/shared/Cryptography/Hmac.cpp | 62 ++ src/server/shared/Cryptography/Hmac.h | 49 + src/server/shared/Cryptography/SARC4.cpp | 52 + src/server/shared/Cryptography/SARC4.h | 36 + src/server/shared/Cryptography/Sha1.cpp | 69 ++ src/server/shared/Cryptography/Sha1.h | 53 + src/server/shared/Cryptography/md5.c | 385 ++++++++ src/server/shared/Cryptography/md5.h | 92 ++ src/server/shared/DataStores/DBCFileLoader.cpp | 270 ++++++ src/server/shared/DataStores/DBCFileLoader.h | 110 +++ src/server/shared/DataStores/DBCStore.h | 265 +++++ src/server/shared/Database/DBCFileLoader.cpp | 270 ------ src/server/shared/Database/DBCFileLoader.h | 110 --- src/server/shared/Database/DBCStore.h | 265 ----- src/server/shared/Debugging/Errors.h | 48 + src/server/shared/Debugging/MemoryLeaks.cpp | 32 + src/server/shared/Debugging/MemoryLeaks.h | 48 + .../shared/Debugging/WheatyExceptionReport.cpp | 1013 ++++++++++++++++++++ .../shared/Debugging/WheatyExceptionReport.h | 118 +++ src/server/shared/DelayExecutor.cpp | 111 --- src/server/shared/DelayExecutor.h | 37 - src/server/shared/Errors.h | 48 - src/server/shared/LockedQueue.h | 139 --- src/server/shared/Log.cpp | 1005 ------------------- src/server/shared/Log.h | 190 ---- src/server/shared/Logging/Log.cpp | 1005 +++++++++++++++++++ src/server/shared/Logging/Log.h | 190 ++++ src/server/shared/MemoryLeaks.cpp | 32 - src/server/shared/MemoryLeaks.h | 48 - src/server/shared/Packets/ByteBuffer.h | 601 ++++++++++++ src/server/shared/Packets/WorldPacket.h | 54 ++ src/server/shared/ProgressBar.cpp | 85 -- src/server/shared/ProgressBar.h | 42 - src/server/shared/ServiceWin32.cpp | 263 ----- src/server/shared/ServiceWin32.h | 31 - src/server/shared/SignalHandler.h | 43 - src/server/shared/Threading.cpp | 232 ----- src/server/shared/Threading.h | 108 --- src/server/shared/Threading/DelayExecutor.cpp | 111 +++ src/server/shared/Threading/DelayExecutor.h | 37 + src/server/shared/Threading/LockedQueue.h | 139 +++ src/server/shared/Threading/Threading.cpp | 232 +++++ src/server/shared/Threading/Threading.h | 108 +++ src/server/shared/Timer.h | 215 ----- src/server/shared/Util.cpp | 468 --------- src/server/shared/Util.h | 536 ----------- src/server/shared/Utilities/ProgressBar.cpp | 85 ++ src/server/shared/Utilities/ProgressBar.h | 42 + src/server/shared/Utilities/ServiceWin32.cpp | 263 +++++ src/server/shared/Utilities/ServiceWin32.h | 31 + src/server/shared/Utilities/SignalHandler.h | 43 + src/server/shared/Utilities/Timer.h | 215 +++++ src/server/shared/Utilities/Util.cpp | 468 +++++++++ src/server/shared/Utilities/Util.h | 536 +++++++++++ src/server/shared/WheatyExceptionReport.cpp | 1013 -------------------- src/server/shared/WheatyExceptionReport.h | 118 --- src/server/shared/WorldPacket.h | 54 -- 94 files changed, 8503 insertions(+), 8503 deletions(-) delete mode 100644 src/server/shared/Auth/AuthCrypt.cpp delete mode 100644 src/server/shared/Auth/AuthCrypt.h delete mode 100644 src/server/shared/Auth/BigNumber.cpp delete mode 100644 src/server/shared/Auth/BigNumber.h delete mode 100644 src/server/shared/Auth/CMakeLists.txt delete mode 100644 src/server/shared/Auth/Hmac.cpp delete mode 100644 src/server/shared/Auth/Hmac.h delete mode 100644 src/server/shared/Auth/SARC4.cpp delete mode 100644 src/server/shared/Auth/SARC4.h delete mode 100644 src/server/shared/Auth/Sha1.cpp delete mode 100644 src/server/shared/Auth/Sha1.h delete mode 100644 src/server/shared/Auth/md5.c delete mode 100644 src/server/shared/Auth/md5.h delete mode 100644 src/server/shared/ByteBuffer.h delete mode 100644 src/server/shared/Config/CMakeLists.txt delete mode 100644 src/server/shared/Config/Config.cpp delete mode 100644 src/server/shared/Config/Config.h delete mode 100644 src/server/shared/Config/ConfigEnv.h delete mode 100644 src/server/shared/Config/ConfigLibrary.vcproj delete mode 100644 src/server/shared/Config/dotconfpp/dotconfpp.cpp delete mode 100644 src/server/shared/Config/dotconfpp/dotconfpp.h delete mode 100644 src/server/shared/Config/dotconfpp/mempool.cpp delete mode 100644 src/server/shared/Config/dotconfpp/mempool.h create mode 100644 src/server/shared/Configuration/CMakeLists.txt create mode 100644 src/server/shared/Configuration/Config.cpp create mode 100644 src/server/shared/Configuration/Config.h create mode 100644 src/server/shared/Configuration/ConfigEnv.h create mode 100644 src/server/shared/Configuration/ConfigLibrary.vcproj create mode 100644 src/server/shared/Configuration/dotconfpp/dotconfpp.cpp create mode 100644 src/server/shared/Configuration/dotconfpp/dotconfpp.h create mode 100644 src/server/shared/Configuration/dotconfpp/mempool.cpp create mode 100644 src/server/shared/Configuration/dotconfpp/mempool.h create mode 100644 src/server/shared/Cryptography/Authentication/AuthCrypt.cpp create mode 100644 src/server/shared/Cryptography/Authentication/AuthCrypt.h create mode 100644 src/server/shared/Cryptography/BigNumber.cpp create mode 100644 src/server/shared/Cryptography/BigNumber.h create mode 100644 src/server/shared/Cryptography/CMakeLists.txt create mode 100644 src/server/shared/Cryptography/Hmac.cpp create mode 100644 src/server/shared/Cryptography/Hmac.h create mode 100644 src/server/shared/Cryptography/SARC4.cpp create mode 100644 src/server/shared/Cryptography/SARC4.h create mode 100644 src/server/shared/Cryptography/Sha1.cpp create mode 100644 src/server/shared/Cryptography/Sha1.h create mode 100644 src/server/shared/Cryptography/md5.c create mode 100644 src/server/shared/Cryptography/md5.h create mode 100644 src/server/shared/DataStores/DBCFileLoader.cpp create mode 100644 src/server/shared/DataStores/DBCFileLoader.h create mode 100644 src/server/shared/DataStores/DBCStore.h delete mode 100644 src/server/shared/Database/DBCFileLoader.cpp delete mode 100644 src/server/shared/Database/DBCFileLoader.h delete mode 100644 src/server/shared/Database/DBCStore.h create mode 100644 src/server/shared/Debugging/Errors.h create mode 100644 src/server/shared/Debugging/MemoryLeaks.cpp create mode 100644 src/server/shared/Debugging/MemoryLeaks.h create mode 100644 src/server/shared/Debugging/WheatyExceptionReport.cpp create mode 100644 src/server/shared/Debugging/WheatyExceptionReport.h delete mode 100644 src/server/shared/DelayExecutor.cpp delete mode 100644 src/server/shared/DelayExecutor.h delete mode 100644 src/server/shared/Errors.h delete mode 100644 src/server/shared/LockedQueue.h delete mode 100644 src/server/shared/Log.cpp delete mode 100644 src/server/shared/Log.h create mode 100644 src/server/shared/Logging/Log.cpp create mode 100644 src/server/shared/Logging/Log.h delete mode 100644 src/server/shared/MemoryLeaks.cpp delete mode 100644 src/server/shared/MemoryLeaks.h create mode 100644 src/server/shared/Packets/ByteBuffer.h create mode 100644 src/server/shared/Packets/WorldPacket.h delete mode 100644 src/server/shared/ProgressBar.cpp delete mode 100644 src/server/shared/ProgressBar.h delete mode 100644 src/server/shared/ServiceWin32.cpp delete mode 100644 src/server/shared/ServiceWin32.h delete mode 100644 src/server/shared/SignalHandler.h delete mode 100644 src/server/shared/Threading.cpp delete mode 100644 src/server/shared/Threading.h create mode 100644 src/server/shared/Threading/DelayExecutor.cpp create mode 100644 src/server/shared/Threading/DelayExecutor.h create mode 100644 src/server/shared/Threading/LockedQueue.h create mode 100644 src/server/shared/Threading/Threading.cpp create mode 100644 src/server/shared/Threading/Threading.h delete mode 100644 src/server/shared/Timer.h delete mode 100644 src/server/shared/Util.cpp delete mode 100644 src/server/shared/Util.h create mode 100644 src/server/shared/Utilities/ProgressBar.cpp create mode 100644 src/server/shared/Utilities/ProgressBar.h create mode 100644 src/server/shared/Utilities/ServiceWin32.cpp create mode 100644 src/server/shared/Utilities/ServiceWin32.h create mode 100644 src/server/shared/Utilities/SignalHandler.h create mode 100644 src/server/shared/Utilities/Timer.h create mode 100644 src/server/shared/Utilities/Util.cpp create mode 100644 src/server/shared/Utilities/Util.h delete mode 100644 src/server/shared/WheatyExceptionReport.cpp delete mode 100644 src/server/shared/WheatyExceptionReport.h delete mode 100644 src/server/shared/WorldPacket.h (limited to 'src/server') diff --git a/src/server/shared/Auth/AuthCrypt.cpp b/src/server/shared/Auth/AuthCrypt.cpp deleted file mode 100644 index b34b922b16a..00000000000 --- a/src/server/shared/Auth/AuthCrypt.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "AuthCrypt.h" -#include "Hmac.h" -#include "Log.h" -#include "BigNumber.h" - -AuthCrypt::AuthCrypt() : _clientDecrypt(SHA_DIGEST_LENGTH), _serverEncrypt(SHA_DIGEST_LENGTH) -{ - _initialized = false; -} - -AuthCrypt::~AuthCrypt() -{ - -} - -void AuthCrypt::Init(BigNumber *K) -{ - uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 }; - HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey); - uint8 *encryptHash = serverEncryptHmac.ComputeHash(K); - - uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE }; - HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey); - uint8 *decryptHash = clientDecryptHmac.ComputeHash(K); - - //SARC4 _serverDecrypt(encryptHash); - _clientDecrypt.Init(decryptHash); - _serverEncrypt.Init(encryptHash); - //SARC4 _clientEncrypt(decryptHash); - - uint8 syncBuf[1024]; - - memset(syncBuf, 0, 1024); - - _serverEncrypt.UpdateData(1024, syncBuf); - //_clientEncrypt.UpdateData(1024, syncBuf); - - memset(syncBuf, 0, 1024); - - //_serverDecrypt.UpdateData(1024, syncBuf); - _clientDecrypt.UpdateData(1024, syncBuf); - - _initialized = true; -} - -void AuthCrypt::DecryptRecv(uint8 *data, size_t len) -{ - if (!_initialized) - return; - - _clientDecrypt.UpdateData(len, data); -} - -void AuthCrypt::EncryptSend(uint8 *data, size_t len) -{ - if (!_initialized) - return; - - _serverEncrypt.UpdateData(len, data); -} - diff --git a/src/server/shared/Auth/AuthCrypt.h b/src/server/shared/Auth/AuthCrypt.h deleted file mode 100644 index 6695dc580cc..00000000000 --- a/src/server/shared/Auth/AuthCrypt.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTHCRYPT_H -#define _AUTHCRYPT_H - -#include -#include "SARC4.h" - -class BigNumber; - -class AuthCrypt -{ - public: - AuthCrypt(); - ~AuthCrypt(); - - void Init(BigNumber *K); - void DecryptRecv(uint8 *, size_t); - void EncryptSend(uint8 *, size_t); - - bool IsInitialized() { return _initialized; } - - private: - SARC4 _clientDecrypt; - SARC4 _serverEncrypt; - bool _initialized; -}; -#endif - diff --git a/src/server/shared/Auth/BigNumber.cpp b/src/server/shared/Auth/BigNumber.cpp deleted file mode 100644 index 64e9ef21ccc..00000000000 --- a/src/server/shared/Auth/BigNumber.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/BigNumber.h" -#include -#include - -BigNumber::BigNumber() -{ - _bn = BN_new(); - _array = NULL; -} - -BigNumber::BigNumber(const BigNumber &bn) -{ - _bn = BN_dup(bn._bn); - _array = NULL; -} - -BigNumber::BigNumber(uint32 val) -{ - _bn = BN_new(); - BN_set_word(_bn, val); - _array = NULL; -} - -BigNumber::~BigNumber() -{ - BN_free(_bn); - if(_array) delete[] _array; -} - -void BigNumber::SetDword(uint32 val) -{ - BN_set_word(_bn, val); -} - -void BigNumber::SetQword(uint64 val) -{ - BN_add_word(_bn, (uint32)(val >> 32)); - BN_lshift(_bn, _bn, 32); - BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF)); -} - -void BigNumber::SetBinary(const uint8 *bytes, int len) -{ - uint8 t[1000]; - for (int i = 0; i < len; i++) t[i] = bytes[len - 1 - i]; - BN_bin2bn(t, len, _bn); -} - -void BigNumber::SetHexStr(const char *str) -{ - BN_hex2bn(&_bn, str); -} - -void BigNumber::SetRand(int numbits) -{ - BN_rand(_bn, numbits, 0, 1); -} - -BigNumber BigNumber::operator=(const BigNumber &bn) -{ - BN_copy(_bn, bn._bn); - return *this; -} - -BigNumber BigNumber::operator+=(const BigNumber &bn) -{ - BN_add(_bn, _bn, bn._bn); - return *this; -} - -BigNumber BigNumber::operator-=(const BigNumber &bn) -{ - BN_sub(_bn, _bn, bn._bn); - return *this; -} - -BigNumber BigNumber::operator*=(const BigNumber &bn) -{ - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_mul(_bn, _bn, bn._bn, bnctx); - BN_CTX_free(bnctx); - - return *this; -} - -BigNumber BigNumber::operator/=(const BigNumber &bn) -{ - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_div(_bn, NULL, _bn, bn._bn, bnctx); - BN_CTX_free(bnctx); - - return *this; -} - -BigNumber BigNumber::operator%=(const BigNumber &bn) -{ - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_mod(_bn, _bn, bn._bn, bnctx); - BN_CTX_free(bnctx); - - return *this; -} - -BigNumber BigNumber::Exp(const BigNumber &bn) -{ - BigNumber ret; - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_exp(ret._bn, _bn, bn._bn, bnctx); - BN_CTX_free(bnctx); - - return ret; -} - -BigNumber BigNumber::ModExp(const BigNumber &bn1, const BigNumber &bn2) -{ - BigNumber ret; - BN_CTX *bnctx; - - bnctx = BN_CTX_new(); - BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx); - BN_CTX_free(bnctx); - - return ret; -} - -int BigNumber::GetNumBytes(void) -{ - return BN_num_bytes(_bn); -} - -uint32 BigNumber::AsDword() -{ - return (uint32)BN_get_word(_bn); -} - -bool BigNumber::isZero() const -{ - return BN_is_zero(_bn)!=0; -} - -uint8 *BigNumber::AsByteArray(int minSize, bool reverse) -{ - int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); - - if (_array) - { - delete[] _array; - _array = NULL; - } - _array = new uint8[length]; - - // If we need more bytes than length of BigNumber set the rest to 0 - if (length > GetNumBytes()) - memset((void*)_array, 0, length); - - BN_bn2bin(_bn, (unsigned char *)_array); - - if (reverse) - std::reverse(_array, _array + length); - - return _array; -} - -const char *BigNumber::AsHexStr() -{ - return BN_bn2hex(_bn); -} - -const char *BigNumber::AsDecStr() -{ - return BN_bn2dec(_bn); -} - diff --git a/src/server/shared/Auth/BigNumber.h b/src/server/shared/Auth/BigNumber.h deleted file mode 100644 index 1dd43c83fc7..00000000000 --- a/src/server/shared/Auth/BigNumber.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_BIGNUMBER_H -#define _AUTH_BIGNUMBER_H - -#include "Common.h" - -struct bignum_st; - -class BigNumber -{ - public: - BigNumber(); - BigNumber(const BigNumber &bn); - BigNumber(uint32); - ~BigNumber(); - - void SetDword(uint32); - void SetQword(uint64); - void SetBinary(const uint8 *bytes, int len); - void SetHexStr(const char *str); - - void SetRand(int numbits); - - BigNumber operator=(const BigNumber &bn); - - BigNumber operator+=(const BigNumber &bn); - BigNumber operator+(const BigNumber &bn) - { - BigNumber t(*this); - return t += bn; - } - BigNumber operator-=(const BigNumber &bn); - BigNumber operator-(const BigNumber &bn) - { - BigNumber t(*this); - return t -= bn; - } - BigNumber operator*=(const BigNumber &bn); - BigNumber operator*(const BigNumber &bn) - { - BigNumber t(*this); - return t *= bn; - } - BigNumber operator/=(const BigNumber &bn); - BigNumber operator/(const BigNumber &bn) - { - BigNumber t(*this); - return t /= bn; - } - BigNumber operator%=(const BigNumber &bn); - BigNumber operator%(const BigNumber &bn) - { - BigNumber t(*this); - return t %= bn; - } - - bool isZero() const; - - BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2); - BigNumber Exp(const BigNumber &); - - int GetNumBytes(void); - - struct bignum_st *BN() { return _bn; } - - uint32 AsDword(); - uint8* AsByteArray(int minSize = 0, bool reverse = true); - - const char *AsHexStr(); - const char *AsDecStr(); - - private: - struct bignum_st *_bn; - uint8 *_array; -}; -#endif - diff --git a/src/server/shared/Auth/CMakeLists.txt b/src/server/shared/Auth/CMakeLists.txt deleted file mode 100644 index 6e5d10d40e5..00000000000 --- a/src/server/shared/Auth/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ - -########### next target ############### - -SET(trinityauth_STAT_SRCS - AuthCrypt.cpp - AuthCrypt.h - BigNumber.cpp - BigNumber.h - Hmac.cpp - Hmac.h - Sha1.cpp - Sha1.h - md5.c - md5.h - SARC4.cpp - SARC4.h -) - -include_directories( - ${ACE_INCLUDE_DIR} - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/framework - ${MYSQL_INCLUDE_DIR} -) - -add_library(trinityauth STATIC ${trinityauth_STAT_SRCS}) diff --git a/src/server/shared/Auth/Hmac.cpp b/src/server/shared/Auth/Hmac.cpp deleted file mode 100644 index a30f1b2d1e2..00000000000 --- a/src/server/shared/Auth/Hmac.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/Hmac.h" -#include "BigNumber.h" - -HmacHash::HmacHash(uint32 len, uint8 *seed) -{ - HMAC_CTX_init(&m_ctx); - HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL); -} - -HmacHash::~HmacHash() -{ - HMAC_CTX_cleanup(&m_ctx); -} - -void HmacHash::UpdateBigNumber(BigNumber *bn) -{ - UpdateData(bn->AsByteArray(), bn->GetNumBytes()); -} - -void HmacHash::UpdateData(const uint8 *data, int length) -{ - HMAC_Update(&m_ctx, data, length); -} - -void HmacHash::UpdateData(const std::string &str) -{ - UpdateData((uint8 const*)str.c_str(), str.length()); -} - -void HmacHash::Finalize() -{ - uint32 length = 0; - HMAC_Final(&m_ctx, (uint8*)m_digest, &length); - ASSERT(length == SHA_DIGEST_LENGTH) -} - -uint8 *HmacHash::ComputeHash(BigNumber *bn) -{ - HMAC_Update(&m_ctx, bn->AsByteArray(), bn->GetNumBytes()); - Finalize(); - return (uint8*)m_digest; -} diff --git a/src/server/shared/Auth/Hmac.h b/src/server/shared/Auth/Hmac.h deleted file mode 100644 index 845d6e84802..00000000000 --- a/src/server/shared/Auth/Hmac.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_HMAC_H -#define _AUTH_HMAC_H - -#include "Common.h" -#include -#include - -class BigNumber; - -#define SEED_KEY_SIZE 16 - -class HmacHash -{ - public: - HmacHash(uint32 len, uint8 *seed); - ~HmacHash(); - void UpdateBigNumber(BigNumber *bn); - void UpdateData(const uint8 *data, int length); - void UpdateData(const std::string &str); - void Finalize(); - uint8 *ComputeHash(BigNumber *bn); - uint8 *GetDigest() { return (uint8*)m_digest; } - int GetLength() { return SHA_DIGEST_LENGTH; } - private: - HMAC_CTX m_ctx; - uint8 m_digest[SHA_DIGEST_LENGTH]; -}; -#endif - diff --git a/src/server/shared/Auth/SARC4.cpp b/src/server/shared/Auth/SARC4.cpp deleted file mode 100644 index 80cad4991e9..00000000000 --- a/src/server/shared/Auth/SARC4.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/SARC4.h" -#include - -SARC4::SARC4(uint8 len) -{ - EVP_CIPHER_CTX_init(&m_ctx); - EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); - EVP_CIPHER_CTX_set_key_length(&m_ctx, len); -} - -SARC4::SARC4(uint8 *seed, uint8 len) -{ - EVP_CIPHER_CTX_init(&m_ctx); - EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); - EVP_CIPHER_CTX_set_key_length(&m_ctx, len); - EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); -} - -SARC4::~SARC4() -{ - EVP_CIPHER_CTX_cleanup(&m_ctx); -} - -void SARC4::Init(uint8 *seed) -{ - EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); -} - -void SARC4::UpdateData(int len, uint8 *data) -{ - int outlen = 0; - EVP_EncryptUpdate(&m_ctx, data, &outlen, data, len); - EVP_EncryptFinal_ex(&m_ctx, data, &outlen); -} diff --git a/src/server/shared/Auth/SARC4.h b/src/server/shared/Auth/SARC4.h deleted file mode 100644 index 2e408627fc8..00000000000 --- a/src/server/shared/Auth/SARC4.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_SARC4_H -#define _AUTH_SARC4_H - -#include "Common.h" -#include - -class SARC4 -{ - public: - SARC4(uint8 len); - SARC4(uint8 *seed, uint8 len); - ~SARC4(); - void Init(uint8 *seed); - void UpdateData(int len, uint8 *data); - private: - EVP_CIPHER_CTX m_ctx; -}; -#endif diff --git a/src/server/shared/Auth/Sha1.cpp b/src/server/shared/Auth/Sha1.cpp deleted file mode 100644 index b63deb2c5f3..00000000000 --- a/src/server/shared/Auth/Sha1.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/Sha1.h" -#include "Auth/BigNumber.h" -#include - -Sha1Hash::Sha1Hash() -{ - SHA1_Init(&mC); -} - -Sha1Hash::~Sha1Hash() -{ - SHA1_Init(&mC); -} - -void Sha1Hash::UpdateData(const uint8 *dta, int len) -{ - SHA1_Update(&mC, dta, len); -} - -void Sha1Hash::UpdateData(const std::string &str) -{ - UpdateData((uint8 const*)str.c_str(), str.length()); -} - -void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...) -{ - va_list v; - BigNumber *bn; - - va_start(v, bn0); - bn = bn0; - while (bn) - { - UpdateData(bn->AsByteArray(), bn->GetNumBytes()); - bn = va_arg(v, BigNumber *); - } - va_end(v); -} - -void Sha1Hash::Initialize() -{ - SHA1_Init(&mC); -} - -void Sha1Hash::Finalize(void) -{ - SHA1_Final(mDigest, &mC); -} - diff --git a/src/server/shared/Auth/Sha1.h b/src/server/shared/Auth/Sha1.h deleted file mode 100644 index 2d7f361ae9a..00000000000 --- a/src/server/shared/Auth/Sha1.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_SHA1_H -#define _AUTH_SHA1_H - -#include "Common.h" -#include -#include - -class BigNumber; - -class Sha1Hash -{ - public: - Sha1Hash(); - ~Sha1Hash(); - - void UpdateFinalizeBigNumbers(BigNumber *bn0, ...); - void UpdateBigNumbers(BigNumber *bn0, ...); - - void UpdateData(const uint8 *dta, int len); - void UpdateData(const std::string &str); - - void Initialize(); - void Finalize(); - - uint8 *GetDigest(void) { return mDigest; }; - int GetLength(void) { return SHA_DIGEST_LENGTH; }; - - private: - SHA_CTX mC; - uint8 mDigest[SHA_DIGEST_LENGTH]; -}; -#endif - diff --git a/src/server/shared/Auth/md5.c b/src/server/shared/Auth/md5.c deleted file mode 100644 index 3e9735e2dbb..00000000000 --- a/src/server/shared/Auth/md5.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -*/ -/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - -The original and principal author of md5.c is L. Peter Deutsch -. Other authors are noted in the change history -that follows (in reverse chronological order): - -2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order -either statically or dynamically; added missing #include -in library. -2002-03-11 lpd Corrected argument list for main(), and added int return -type, in test program and T value program. -2002-02-21 lpd Added missing #include in test program. -2000-07-03 lpd Patched to eliminate warnings about "constant is -unsigned in ANSI C, signed in traditional"; made test program -self-checking. -1999-11-04 lpd Edited comments slightly for automatic TOC extraction. -1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). -1999-05-03 lpd Original version. -*/ - -#include "md5.h" -#include - -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ -#ifdef ARCH_IS_BIG_ENDIAN -# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) -#else -# define BYTE_ORDER 0 -#endif - -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; - #if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; - #else - /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; - #endif - - { - #if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ - #endif - #if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t *)0) & 3)) - { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } - else - { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } - #endif - #if BYTE_ORDER == 0 - else /* dynamic big-endian */ - #endif - #if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t *xp = data; - int i; - - # if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ - # else - # define xbuf X /* (static only) */ - # endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } - #endif - } - - #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ - #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); - #undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ - #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); - #undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ - #define H(x, y, z) ((x) ^ (y) ^ (z)) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); - #undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ - #define I(x, y, z) ((y) ^ ((x) | ~(z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); - #undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - ++pms->count[1]; - - /* Process an initial partial block. */ - if (offset) - { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = - { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} diff --git a/src/server/shared/Auth/md5.h b/src/server/shared/Auth/md5.h deleted file mode 100644 index 0463051b6a6..00000000000 --- a/src/server/shared/Auth/md5.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -*/ -/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - -The original and principal author of md5.h is L. Peter Deutsch -. Other authors are noted in the change history -that follows (in reverse chronological order): - -2002-04-13 lpd Removed support for non-ANSI compilers; removed -references to Ghostscript; clarified derivation from RFC 1321; -now handles byte order either statically or dynamically. -1999-11-04 lpd Edited comments slightly for automatic TOC extraction. -1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); -added conditionalization for C++ compilation from Martin -Purschke . -1999-05-03 lpd Original version. -*/ - -#ifndef md5_INCLUDED -# define md5_INCLUDED - -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s -{ - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ - #endif - - /* Initialize the algorithm. */ - void md5_init(md5_state_t *pms); - - /* Append a string to the message. */ - void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); - - /* Finish the message and return the digest. */ - void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); - - #ifdef __cplusplus -} /* end extern "C" */ -#endif -#endif /* md5_INCLUDED */ - diff --git a/src/server/shared/ByteBuffer.h b/src/server/shared/ByteBuffer.h deleted file mode 100644 index ba0240fb58b..00000000000 --- a/src/server/shared/ByteBuffer.h +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _BYTEBUFFER_H -#define _BYTEBUFFER_H - -#include "Common.h" -#include "Errors.h" -#include "Log.h" -#include "Utilities/ByteConverter.h" - -class ByteBufferException -{ - public: - ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size) - : add(_add), pos(_pos), esize(_esize), size(_size) - { - PrintPosError(); - } - - void PrintPosError() const - { - sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") value with size: " SIZEFMTD, - (add ? "put" : "get"), pos, size, esize); - } - private: - bool add; - size_t pos; - size_t esize; - size_t size; -}; - -class ByteBuffer -{ - public: - const static size_t DEFAULT_SIZE = 0x1000; - - // constructor - ByteBuffer(): _rpos(0), _wpos(0) - { - _storage.reserve(DEFAULT_SIZE); - } - - // constructor - ByteBuffer(size_t res): _rpos(0), _wpos(0) - { - _storage.reserve(res); - } - - // copy constructor - ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { } - - void clear() - { - _storage.clear(); - _rpos = _wpos = 0; - } - - template void append(T value) - { - EndianConvert(value); - append((uint8 *)&value, sizeof(value)); - } - - template void put(size_t pos,T value) - { - EndianConvert(value); - put(pos,(uint8 *)&value,sizeof(value)); - } - - ByteBuffer &operator<<(uint8 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(uint16 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(uint32 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(uint64 value) - { - append(value); - return *this; - } - - // signed as in 2e complement - ByteBuffer &operator<<(int8 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(int16 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(int32 value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(int64 value) - { - append(value); - return *this; - } - - // floating points - ByteBuffer &operator<<(float value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(double value) - { - append(value); - return *this; - } - - ByteBuffer &operator<<(const std::string &value) - { - append((uint8 const *)value.c_str(), value.length()); - append((uint8)0); - return *this; - } - - ByteBuffer &operator<<(const char *str) - { - append((uint8 const *)str, str ? strlen(str) : 0); - append((uint8)0); - return *this; - } - - ByteBuffer &operator>>(bool &value) - { - value = read() > 0 ? true : false; - return *this; - } - - ByteBuffer &operator>>(uint8 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(uint16 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(uint32 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(uint64 &value) - { - value = read(); - return *this; - } - - //signed as in 2e complement - ByteBuffer &operator>>(int8 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(int16 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(int32 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(int64 &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(float &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(double &value) - { - value = read(); - return *this; - } - - ByteBuffer &operator>>(std::string& value) - { - value.clear(); - while (rpos() < size()) // prevent crash at wrong string format in packet - { - char c = read(); - if (c == 0) - break; - value += c; - } - return *this; - } - - uint8 operator[](size_t pos) const - { - return read(pos); - } - - size_t rpos() const { return _rpos; } - - size_t rpos(size_t rpos_) - { - _rpos = rpos_; - return _rpos; - } - - size_t wpos() const { return _wpos; } - - size_t wpos(size_t wpos_) - { - _wpos = wpos_; - return _wpos; - } - - template - void read_skip() { read_skip(sizeof(T)); } - - void read_skip(size_t skip) - { - if(_rpos + skip > size()) - throw ByteBufferException(false, _rpos, skip, size()); - _rpos += skip; - } - - template T read() - { - T r = read(_rpos); - _rpos += sizeof(T); - return r; - } - - template T read(size_t pos) const - { - if(pos + sizeof(T) > size()) - throw ByteBufferException(false, pos, sizeof(T), size()); - T val = *((T const*)&_storage[pos]); - EndianConvert(val); - return val; - } - - void read(uint8 *dest, size_t len) - { - if(_rpos + len > size()) - throw ByteBufferException(false, _rpos, len, size()); - memcpy(dest, &_storage[_rpos], len); - _rpos += len; - } - - bool readPackGUID(uint64& guid) - { - if(rpos() + 1 > size()) - return false; - - guid = 0; - - uint8 guidmark = 0; - (*this) >> guidmark; - - for (int i = 0; i < 8; ++i) - { - if(guidmark & (uint8(1) << i)) - { - if(rpos() + 1 > size()) - return false; - - uint8 bit; - (*this) >> bit; - guid |= (uint64(bit) << (i * 8)); - } - } - - return true; - } - - const uint8 *contents() const { return &_storage[0]; } - - size_t size() const { return _storage.size(); } - bool empty() const { return _storage.empty(); } - - void resize(size_t newsize) - { - _storage.resize(newsize); - _rpos = 0; - _wpos = size(); - } - - void reserve(size_t ressize) - { - if (ressize > size()) - _storage.reserve(ressize); - } - - void append(const std::string& str) - { - append((uint8 const*)str.c_str(), str.size() + 1); - } - - void append(const char *src, size_t cnt) - { - return append((const uint8 *)src, cnt); - } - - template void append(const T *src, size_t cnt) - { - return append((const uint8 *)src, cnt * sizeof(T)); - } - - void append(const uint8 *src, size_t cnt) - { - if (!cnt) - return; - - ASSERT(size() < 10000000); - - if (_storage.size() < _wpos + cnt) - _storage.resize(_wpos + cnt); - memcpy(&_storage[_wpos], src, cnt); - _wpos += cnt; - } - - void append(const ByteBuffer& buffer) - { - if(buffer.wpos()) - append(buffer.contents(), buffer.wpos()); - } - - // can be used in SMSG_MONSTER_MOVE opcode - void appendPackXYZ(float x, float y, float z) - { - uint32 packed = 0; - packed |= ((int)(x / 0.25f) & 0x7FF); - packed |= ((int)(y / 0.25f) & 0x7FF) << 11; - packed |= ((int)(z / 0.25f) & 0x3FF) << 22; - *this << packed; - } - - void appendPackGUID(uint64 guid) - { - uint8 packGUID[8+1]; - packGUID[0] = 0; - size_t size = 1; - for(uint8 i = 0;guid != 0;++i) - { - if(guid & 0xFF) - { - packGUID[0] |= uint8(1 << i); - packGUID[size] = uint8(guid & 0xFF); - ++size; - } - - guid >>= 8; - } - append(packGUID, size); - } - - void put(size_t pos, const uint8 *src, size_t cnt) - { - if(pos + cnt > size()) - throw ByteBufferException(true, pos, cnt, size()); - memcpy(&_storage[pos], src, cnt); - } - - void print_storage() const - { - if(!sLog.IsOutDebug()) // optimize disabled debug output - return; - - sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); - for (uint32 i = 0; i < size(); ++i) - sLog.outDebugInLine("%u - ", read(i) ); - sLog.outDebug(" "); - } - - void textlike() const - { - if(!sLog.IsOutDebug()) // optimize disabled debug output - return; - - sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); - for (uint32 i = 0; i < size(); ++i) - sLog.outDebugInLine("%c", read(i) ); - sLog.outDebug(" "); - } - - void hexlike() const - { - if(!sLog.IsOutDebug()) // optimize disabled debug output - return; - - uint32 j = 1, k = 1; - sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); - - for (uint32 i = 0; i < size(); ++i) - { - if ((i == (j * 8)) && ((i != (k * 16)))) - { - if (read(i) < 0x10) - { - sLog.outDebugInLine("| 0%X ", read(i) ); - } - else - { - sLog.outDebugInLine("| %X ", read(i) ); - } - ++j; - } - else if (i == (k * 16)) - { - if (read(i) < 0x10) - { - sLog.outDebugInLine("\n"); - - sLog.outDebugInLine("0%X ", read(i) ); - } - else - { - sLog.outDebugInLine("\n"); - - sLog.outDebugInLine("%X ", read(i) ); - } - - ++k; - ++j; - } - else - { - if (read(i) < 0x10) - { - sLog.outDebugInLine("0%X ", read(i) ); - } - else - { - sLog.outDebugInLine("%X ", read(i) ); - } - } - } - sLog.outDebugInLine("\n"); - } - - protected: - size_t _rpos, _wpos; - std::vector _storage; -}; - -template -inline ByteBuffer &operator<<(ByteBuffer &b, std::vector v) -{ - b << (uint32)v.size(); - for (typename std::vector::iterator i = v.begin(); i != v.end(); ++i) - { - b << *i; - } - return b; -} - -template -inline ByteBuffer &operator>>(ByteBuffer &b, std::vector &v) -{ - uint32 vsize; - b >> vsize; - v.clear(); - while(vsize--) - { - T t; - b >> t; - v.push_back(t); - } - return b; -} - -template -inline ByteBuffer &operator<<(ByteBuffer &b, std::list v) -{ - b << (uint32)v.size(); - for (typename std::list::iterator i = v.begin(); i != v.end(); ++i) - { - b << *i; - } - return b; -} - -template -inline ByteBuffer &operator>>(ByteBuffer &b, std::list &v) -{ - uint32 vsize; - b >> vsize; - v.clear(); - while(vsize--) - { - T t; - b >> t; - v.push_back(t); - } - return b; -} - -template -inline ByteBuffer &operator<<(ByteBuffer &b, std::map &m) -{ - b << (uint32)m.size(); - for (typename std::map::iterator i = m.begin(); i != m.end(); ++i) - { - b << i->first << i->second; - } - return b; -} - -template -inline ByteBuffer &operator>>(ByteBuffer &b, std::map &m) -{ - uint32 msize; - b >> msize; - m.clear(); - while(msize--) - { - K k; - V v; - b >> k >> v; - m.insert(make_pair(k, v)); - } - return b; -} - -// TODO: Make a ByteBuffer.cpp and move all this inlining to it. -template<> inline std::string ByteBuffer::read() -{ - std::string tmp; - *this >> tmp; - return tmp; -} - -template<> -inline void ByteBuffer::read_skip() -{ - std::string temp; - *this >> temp; -} - -template<> -inline void ByteBuffer::read_skip() -{ - read_skip(); -} - -template<> -inline void ByteBuffer::read_skip() -{ - read_skip(); -} -#endif - diff --git a/src/server/shared/Config/CMakeLists.txt b/src/server/shared/Config/CMakeLists.txt deleted file mode 100644 index da1c2e8aa3b..00000000000 --- a/src/server/shared/Config/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ - -########### next target ############### - -SET(trinityconfig_STAT_SRCS - dotconfpp/dotconfpp.cpp - dotconfpp/dotconfpp.h - dotconfpp/mempool.cpp - dotconfpp/mempool.h - Config.cpp - Config.h - ConfigEnv.h -) - -include_directories( - ${ACE_INCLUDE_DIR} - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/framework -) - -add_library(trinityconfig STATIC ${trinityconfig_STAT_SRCS}) - diff --git a/src/server/shared/Config/Config.cpp b/src/server/shared/Config/Config.cpp deleted file mode 100644 index 39830104a7c..00000000000 --- a/src/server/shared/Config/Config.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ConfigEnv.h" -#include "Policies/SingletonImp.h" - -INSTANTIATE_SINGLETON_1(Config); - -Config::Config() : mIgnoreCase(true), mConf(NULL) -{ -} - -Config::~Config() -{ - delete mConf; -} - -bool Config::SetSource(const char *file, bool ignorecase) -{ - mIgnoreCase = ignorecase; - mFilename = file; - - return Reload(); -} - -bool Config::Reload() -{ - delete mConf; - - mConf = new DOTCONFDocument(mIgnoreCase ? - DOTCONFDocument::CASEINSENSETIVE : - DOTCONFDocument::CASESENSETIVE); - - if (mConf->setContent(mFilename.c_str()) == -1) - { - delete mConf; - mConf = NULL; - return false; - } - - return true; -} - -std::string Config::GetStringDefault(const char * name, std::string def) -{ - if(!mConf) - return std::string(def); - const DOTCONFDocumentNode * node = mConf->findNode(name); - if(!node || !node->getValue()) - return std::string(def); - return std::string(node->getValue()); -}; - -bool Config::GetBoolDefault(const char * name, const bool def) -{ - if(!mConf) - return false; - const DOTCONFDocumentNode * node = mConf->findNode(name); - if(!node || !node->getValue()) - return def; - const char * str = node->getValue(); - if(strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0 || - strcmp(str, "yes") == 0 || strcmp(str, "YES") == 0 || - strcmp(str, "1") == 0) - return true; - else - return false; -}; - -int32 Config::GetIntDefault(const char * name, const int32 def) -{ - if(!mConf) - return def; - const DOTCONFDocumentNode * node = mConf->findNode(name); - if(!node || !node->getValue()) - return def; - return atoi(node->getValue()); -}; - -float Config::GetFloatDefault(const char * name, const float def) -{ - if(!mConf) - return def; - const DOTCONFDocumentNode * node = mConf->findNode(name); - if(!node || !node->getValue()) - return def; - return atof(node->getValue()); -}; diff --git a/src/server/shared/Config/Config.h b/src/server/shared/Config/Config.h deleted file mode 100644 index ccc76073e46..00000000000 --- a/src/server/shared/Config/Config.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CONFIG_H -#define CONFIG_H - -#include -#include "Platform/Define.h" - -class DOTCONFDocument; - -class Config -{ - public: - Config(); - ~Config(); - - bool SetSource(const char *file, bool ignorecase = true); - bool Reload(); - - std::string GetStringDefault(const char * name, std::string def); - bool GetBoolDefault(const char * name, const bool def); - int32 GetIntDefault(const char * name, const int32 def); - float GetFloatDefault(const char * name, const float def); - - std::string GetFilename() const { return mFilename; } - private: - std::string mFilename; - bool mIgnoreCase; - DOTCONFDocument *mConf; -}; - -#define sConfig Trinity::Singleton::Instance() - -#endif - diff --git a/src/server/shared/Config/ConfigEnv.h b/src/server/shared/Config/ConfigEnv.h deleted file mode 100644 index 16e596fd2da..00000000000 --- a/src/server/shared/Config/ConfigEnv.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#if !defined(CONFIGENVIRONMENT_H) - -#define CONFIGENVIRONMENT_H - -#include "Common.h" -#include "dotconfpp/dotconfpp.h" -#include "Config.h" - -#endif - diff --git a/src/server/shared/Config/ConfigLibrary.vcproj b/src/server/shared/Config/ConfigLibrary.vcproj deleted file mode 100644 index a8f1fc322e7..00000000000 --- a/src/server/shared/Config/ConfigLibrary.vcproj +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/server/shared/Config/dotconfpp/dotconfpp.cpp b/src/server/shared/Config/dotconfpp/dotconfpp.cpp deleted file mode 100644 index 8760b118e38..00000000000 --- a/src/server/shared/Config/dotconfpp/dotconfpp.cpp +++ /dev/null @@ -1,599 +0,0 @@ - -#include "Common.h" - -#include "dotconfpp.h" - -#ifdef WIN32 -#define PATH_MAX _MAX_PATH -#define strcasecmp stricmp -#define realpath(path,resolved_path) _fullpath(resolved_path, path, _MAX_PATH) -#include -#else -#include -#include -#include -#include -#endif - -#if !defined(R_OK) -#define R_OK 04 -#endif - -DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL), - values(NULL), valuesCount(0), - name(NULL), lineNum(0), fileName(NULL), closed(true) -{ -} - -DOTCONFDocumentNode::~DOTCONFDocumentNode() -{ - free(name); - if(values != NULL){ - for (int i = 0 ; i < valuesCount; i++){ - free(values[i]); - } - free(values); - } -} - -void DOTCONFDocumentNode::pushValue(char * _value) -{ - ++valuesCount; - values = (char**)realloc(values, valuesCount*sizeof(char*)); - values[valuesCount-1] = strdup(_value); -} - -const char* DOTCONFDocumentNode::getValue(int index) const -{ - if(index >= valuesCount){ - return NULL; - } - return values[index]; -} - -DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity): - mempool(NULL), - curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL) -{ - if(caseSensitivity == CASESENSETIVE){ - cmp_func = strcmp; - } else { - cmp_func = strcasecmp; - } - - mempool = new AsyncDNSMemPool(1024); - mempool->initialize(); -} - -DOTCONFDocument::~DOTCONFDocument() -{ - for (std::list::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){ - delete(*i); - } - for (std::list::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i){ - free(*i); - } - for (std::list::iterator i = processedFiles.begin(); i != processedFiles.end(); ++i){ - free(*i); - } - free(fileName); - delete mempool; -} - -int DOTCONFDocument::cleanupLine(char * line) -{ - char * start = line; - char * bg = line; - bool multiline = false; - bool concat = false; - char * word = NULL; - - if(!words.empty() && quoted) - concat = true; - - while(*line){ - if((*line == '#' || *line == ';') && !quoted){ - *bg = 0; - if(strlen(start)){ - - if(concat){ - word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); - strcpy(word, words.back()); - strcat(word, start); - words.pop_back(); - concat = false; - } else { - word = mempool->strdup(start); - } - words.push_back(word); - } - break; - } - if(*line == '=' && !quoted){ - *line = ' ';continue; - } - - // Allowing \" in there causes problems with directory paths - // like "C:\TrinIty\" - //if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){ - if(*line == '\\' && (*(line+1) == '\'')) { - *bg++ = *(line+1); - line+=2; continue; - } - if(*line == '\\' && *(line+1) == 'n'){ - *bg++ = '\n'; - line+=2; continue; - } - if(*line == '\\' && *(line+1) == 'r'){ - *bg++ = '\r'; - line+=2; continue; - } - if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){ - *bg = 0; - if(strlen(start)){ - - if(concat){ - word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); - strcpy(word, words.back()); - strcat(word, start); - words.pop_back(); - concat = false; - } else { - word = mempool->strdup(start); - } - words.push_back(word); - } - multiline = true; - break; - } - if(*line == '"' || *line == '\''){ - quoted = !quoted; - ++line; continue; - } - if(isspace((unsigned char)*line) && !quoted){ - *bg++ = 0; - if(strlen(start)){ - - if(concat){ - word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); - strcpy(word, words.back()); - strcat(word, start); - words.pop_back(); - concat = false; - } else { - word = mempool->strdup(start); - } - words.push_back(word); - } - start = bg; - while(isspace((unsigned char)*++line)) {} - - continue; - } - *bg++ = *line++; - } - - if(quoted && !multiline){ - error(curLine, fileName, "unterminated quote"); - return -1; - } - - return multiline?1:0; -} - -int DOTCONFDocument::parseLine() -{ - char * word = NULL; - char * nodeName = NULL; - char * nodeValue = NULL; - DOTCONFDocumentNode * tagNode = NULL; - bool newNode = false; - - for (std::list::iterator i = words.begin(); i != words.end(); ++i) { - word = *i; - - if(*word == '<'){ - newNode = true; - } - - if(newNode){ - nodeValue = NULL; - nodeName = NULL; - newNode = false; - } - - size_t wordLen = strlen(word); - if(word[wordLen-1] == '>'){ - word[wordLen-1] = 0; - newNode = true; - } - - if(nodeName == NULL){ - nodeName = word; - bool closed = true; - if(*nodeName == '<'){ - if(*(nodeName+1) != '/'){ - ++nodeName; - closed = false; - } else { - nodeName+=2; - std::list::reverse_iterator itr=nodeTree.rbegin(); - for (; itr!=nodeTree.rend(); ++itr){ - if(!cmp_func(nodeName, (*itr)->name) && !(*itr)->closed){ - (*itr)->closed = true; - curParent = (*itr)->parentNode; - curPrev = *itr; - break; - } - } - if(itr==nodeTree.rend()){ - error(curLine, fileName, "not matched closing tag ", nodeName); - return -1; - } - continue; - } - } - tagNode = new DOTCONFDocumentNode; - tagNode->name = strdup(nodeName); - tagNode->document = this; - tagNode->fileName = processedFiles.back(); - tagNode->lineNum = curLine; - tagNode->closed = closed; - if(!nodeTree.empty()){ - DOTCONFDocumentNode * prev = nodeTree.back(); - if(prev->closed){ - - curPrev->nextNode = tagNode; - tagNode->previousNode = curPrev; - tagNode->parentNode = curParent; - - } else { - prev->childNode = tagNode; - tagNode->parentNode = prev; - curParent = prev; - } - } - nodeTree.push_back(tagNode); - curPrev = tagNode; - } else { - nodeValue = word; - tagNode->pushValue(nodeValue); - } - } - - return 0; -} -int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent) -{ - char str[512]; - int ret = 0; - curLine = 0; - curParent = _parent; - - quoted = false; - size_t slen = 0; - - while(fgets(str, 511, file)){ - ++curLine; - slen = strlen(str); - if( slen >= 510 ){ - error(curLine, fileName, "warning: line too long"); - } - if(str[slen-1] != '\n'){ - str[slen] = '\n'; - str[slen+1] = 0; - } - if((ret = cleanupLine(str)) == -1){ - break; - } - if(ret == 0){ - if(!words.empty()){ - ret = parseLine(); - mempool->free(); - words.clear(); - if(ret == -1){ - break; - } - } - } - } - - return ret; -} - -int DOTCONFDocument::checkConfig(const std::list::iterator & from) -{ - int ret = 0; - - DOTCONFDocumentNode * tagNode = NULL; - int vi = 0; - for (std::list::iterator i = from; i != nodeTree.end(); ++i){ - tagNode = *i; - if(!tagNode->closed){ - error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name); - ret = -1; - break; - } - vi = 0; - while( vi < tagNode->valuesCount ){ - - if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){ - ret = macroSubstitute(tagNode, vi ); - mempool->free(); - if(ret == -1){ - break; - } - } - ++vi; - } - if(ret == -1){ - break; - } - } - - return ret; -} - -int DOTCONFDocument::setContent(const char * _fileName) -{ - int ret = 0; - char realpathBuf[PATH_MAX]; - - if(realpath(_fileName, realpathBuf) == NULL){ - error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno)); - return -1; - } - - fileName = strdup(realpathBuf); - - processedFiles.push_back(strdup(realpathBuf)); - - if(( file = fopen(fileName, "r")) == NULL){ - error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno)); - return -1; - } - // Try read utf8 header and skip it if exist - uint32 utf8header = 0; - fgets((char*)&utf8header, 4, file); // Try read header - if (utf8header!=0x00BFBBEF) // If not exist - fseek(file, 0, SEEK_SET); // Reset read position - - ret = parseFile(); - - (void) fclose(file); - - if(!ret){ - - if( (ret = checkConfig(nodeTree.begin())) == -1){ - return -1; - } - - std::list::iterator from; - DOTCONFDocumentNode * tagNode = NULL; - int vi = 0; - for (std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ - tagNode = *i; - if(!cmp_func("DOTCONFPPIncludeFile", tagNode->name)){ - vi = 0; - while( vi < tagNode->valuesCount ){ - if(access(tagNode->values[vi], R_OK) == -1){ - error(tagNode->lineNum, tagNode->fileName, "%s: %s", tagNode->values[vi], strerror(errno)); - return -1; - } - if(realpath(tagNode->values[vi], realpathBuf) == NULL){ - error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", tagNode->values[vi], strerror(errno)); - return -1; - } - - bool processed = false; - for (std::list::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); ++itInode){ - if(!strcmp(*itInode, realpathBuf)){ - processed = true; - break; - } - } - if(processed){ - break; - } - - processedFiles.push_back(strdup(realpathBuf)); - - file = fopen(tagNode->values[vi], "r"); - if(file == NULL){ - error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno)); - return -1; - } - - fileName = strdup(realpathBuf); - from = nodeTree.end(); --from; - - ret = parseFile(); - (void) fclose(file); - if(ret == -1) - return -1; - if(checkConfig(++from) == -1){ - return -1; - } - ++vi; - } - } - } - - if(!requiredOptions.empty()) - ret = checkRequiredOptions(); - } - - return ret; -} - -int DOTCONFDocument::checkRequiredOptions() -{ - for (std::list::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){ - bool matched = false; - for (std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ - if(!cmp_func((*i)->name, *ci)){ - matched = true; - break; - } - } - if(!matched){ - error(0, NULL, "required option '%s' not specified", *ci); - return -1; - } - } - return 0; -} - -void DOTCONFDocument::error(int lineNum, const char * fileName_, const char * fmt, ...) -{ - va_list args; - va_start(args, fmt); - - size_t len = (lineNum!=0?strlen(fileName_):0) + strlen(fmt) + 50; - char * buf = (char*)mempool->alloc(len); - - if(lineNum) - (void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt); - else - (void) snprintf(buf, len, "DOTCONF++: %s\n", fmt); - - (void) vfprintf(stderr, buf, args); - - va_end(args); -} - -char * DOTCONFDocument::getSubstitution(char * macro, int lineNum) -{ - char * buf = NULL; - char * variable = macro+2; - - char * endBr = strchr(macro, '}'); - - if(!endBr){ - error(lineNum, fileName, "unterminated '{'"); - return NULL; - } - *endBr = 0; - - char * defaultValue = strchr(variable, ':'); - - if(defaultValue){ - *defaultValue++ = 0; - if(*defaultValue != '-'){ - error(lineNum, fileName, "incorrect macro substitution syntax"); - return NULL; - } - ++defaultValue; - if(*defaultValue == '"' || *defaultValue == '\''){ - ++defaultValue; - defaultValue[strlen(defaultValue)-1] = 0; - } - } else { - defaultValue = NULL; - } - - char * subs = getenv(variable); - if( subs ){ - buf = mempool->strdup(subs); - } else { - std::list::iterator i = nodeTree.begin(); - DOTCONFDocumentNode * tagNode = NULL; - for (; i!=nodeTree.end(); i++){ - tagNode = *i; - if(!cmp_func(tagNode->name, variable)){ - if(tagNode->valuesCount != 0){ - buf = mempool->strdup(tagNode->values[0]); - break; - } - } - } - if( i == nodeTree.end() ){ - if( defaultValue ){ - buf = mempool->strdup(defaultValue); - } else { - error(lineNum, fileName, "substitution not found and default value not given"); - return NULL; - } - } - } - return buf; -} - -int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex) -{ - int ret = 0; - char * macro = tagNode->values[valueIndex]; - size_t valueLen = strlen(tagNode->values[valueIndex])+1; - char * value = (char*)mempool->alloc(valueLen); - char * v = value; - char * subs = NULL; - - while(*macro){ - if(*macro == '$' && *(macro+1) == '{'){ - char * m = strchr(macro, '}'); - subs = getSubstitution(macro, tagNode->lineNum); - if(subs == NULL){ - ret = -1; - break; - } - macro = m + 1; - *v = 0; - v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen); - strcpy(v, value); - value = strcat(v, subs); - v = value + strlen(value); - continue; - } - *v++ = *macro++; - } - *v = 0; - - free(tagNode->values[valueIndex]); - tagNode->values[valueIndex] = strdup(value); - return ret; -} - -const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const -{ - if ( !nodeTree.empty() ) { - return *nodeTree.begin(); - } else { - return NULL; - } -} - -const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const -{ - - std::list::const_iterator i = nodeTree.begin(); - - if(startNode == NULL) - startNode = parentNode; - - if(startNode != NULL){ - while( i != nodeTree.end() && (*i) != startNode ){ - ++i; - } - if( i != nodeTree.end() ) ++i; - } - - for (; i!=nodeTree.end(); ++i){ - - if((*i)->parentNode != parentNode){ - continue; - } - if(!cmp_func(nodeName, (*i)->name)){ - return *i; - } - } - return NULL; -} - -void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames) -{ - while(*requiredOptionNames){ - requiredOptions.push_back(strdup( *requiredOptionNames )); - ++requiredOptionNames; - } -} - diff --git a/src/server/shared/Config/dotconfpp/dotconfpp.h b/src/server/shared/Config/dotconfpp/dotconfpp.h deleted file mode 100644 index 554b152f693..00000000000 --- a/src/server/shared/Config/dotconfpp/dotconfpp.h +++ /dev/null @@ -1,97 +0,0 @@ - - -#ifndef DOTCONFPP_H -#define DOTCONFPP_H - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "mempool.h" - -class DOTCONFDocument; - -class DOTCONFDocumentNode -{ -friend class DOTCONFDocument; -private: - DOTCONFDocumentNode * previousNode; - DOTCONFDocumentNode * nextNode; - DOTCONFDocumentNode * parentNode; - DOTCONFDocumentNode * childNode; - char ** values; - int valuesCount; - char * name; - const DOTCONFDocument * document; - int lineNum; - char * fileName; - bool closed; - - void pushValue(char * _value); - -public: - DOTCONFDocumentNode(); - ~DOTCONFDocumentNode(); - - const char * getConfigurationFileName()const { return fileName; } - int getConfigurationLineNumber() const { return lineNum; } - - const DOTCONFDocumentNode * getNextNode() const { return nextNode; } - const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; } - const DOTCONFDocumentNode * getParentNode() const { return parentNode; } - const DOTCONFDocumentNode * getChildNode() const { return childNode; } - const char* getValue(int index = 0) const; - const char * getName() const { return name; } - const DOTCONFDocument * getDocument() const { return document; } -}; - -class DOTCONFDocument -{ -public: - enum CaseSensitive { CASESENSETIVE, CASEINSENSETIVE }; -protected: - AsyncDNSMemPool * mempool; -private: - DOTCONFDocumentNode * curParent; - DOTCONFDocumentNode * curPrev; - int curLine; - bool quoted; - std::list nodeTree; - std::list requiredOptions; - std::list processedFiles; - FILE * file; - char * fileName; - std::list words; - int (*cmp_func)(const char *, const char *); - - int checkRequiredOptions(); - int parseLine(); - int parseFile(DOTCONFDocumentNode * _parent = NULL); - int checkConfig(const std::list::iterator & from); - int cleanupLine(char * line); - char * getSubstitution(char * macro, int lineNum); - int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex); - -protected: - virtual void error(int lineNum, const char * fileName, const char * fmt, ...) ATTR_PRINTF(4,5); - -public: - DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSETIVE); - virtual ~DOTCONFDocument(); - - int setContent(const char * _fileName); - - void setRequiredOptionNames(const char ** requiredOptionNames); - const DOTCONFDocumentNode * getFirstNode() const; - const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const; -}; - -#endif - diff --git a/src/server/shared/Config/dotconfpp/mempool.cpp b/src/server/shared/Config/dotconfpp/mempool.cpp deleted file mode 100644 index a23e33808bd..00000000000 --- a/src/server/shared/Config/dotconfpp/mempool.cpp +++ /dev/null @@ -1,100 +0,0 @@ - - -#include "mempool.h" - -AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size): - pool(NULL), pos(0), size(_size) -{ - pool = ::malloc(size); -} - -AsyncDNSMemPool::PoolChunk::~PoolChunk() -{ - ::free(pool); -} - -AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize): - chunks(NULL), chunksCount(0), defaultSize(_defaultSize), - poolUsage(0), poolUsageCounter(0) -{ -} - -AsyncDNSMemPool::~AsyncDNSMemPool() -{ - for (size_t i = 0; isize - chunk->pos) >= size){ - chunk->pos += size; - return ((char*)chunk->pool) + chunk->pos - size; - } - } - addNewChunk(size); - chunks[chunksCount-1]->pos = size; - return chunks[chunksCount-1]->pool; -} - -void AsyncDNSMemPool::free() -{ - size_t pu = 0; - size_t psz = 0; - ++poolUsageCounter; - - for (size_t i = 0; ipos; - psz += chunks[i]->size; - chunks[i]->pos = 0; - } - poolUsage=(poolUsage>pu)?poolUsage:pu; - - if(poolUsageCounter >= 10 && chunksCount > 1){ - psz -= chunks[chunksCount-1]->size; - if(poolUsage < psz){ - --chunksCount; - delete chunks[chunksCount]; - } - poolUsage = 0; - poolUsageCounter = 0; - } -} - -void * AsyncDNSMemPool::calloc(size_t size) -{ - return ::memset(this->alloc(size), 0, size); -} - -char * AsyncDNSMemPool::strdup(const char *str) -{ - return ::strcpy((char*)this->alloc(strlen(str)+1), str); -} - diff --git a/src/server/shared/Config/dotconfpp/mempool.h b/src/server/shared/Config/dotconfpp/mempool.h deleted file mode 100644 index 185b50798e1..00000000000 --- a/src/server/shared/Config/dotconfpp/mempool.h +++ /dev/null @@ -1,46 +0,0 @@ - - -#ifndef ASYNC_DNS_MEMPOOL_H -#define ASYNC_DNS_MEMPOOL_H - -#include -#include -#include - -#undef free -#undef calloc -#undef strdup - -class AsyncDNSMemPool -{ -private: - struct PoolChunk { - void * pool; - size_t pos; - size_t size; - - PoolChunk(size_t _size); - ~PoolChunk(); - }; - PoolChunk ** chunks; - size_t chunksCount; - size_t defaultSize; - - size_t poolUsage; - size_t poolUsageCounter; - - void addNewChunk(size_t size); - -public: - AsyncDNSMemPool(size_t _defaultSize = 4096); - virtual ~AsyncDNSMemPool(); - - int initialize(); - void free(); - void * alloc(size_t size); - void * calloc(size_t size); - char * strdup(const char *str); -}; - -#endif - diff --git a/src/server/shared/Configuration/CMakeLists.txt b/src/server/shared/Configuration/CMakeLists.txt new file mode 100644 index 00000000000..da1c2e8aa3b --- /dev/null +++ b/src/server/shared/Configuration/CMakeLists.txt @@ -0,0 +1,22 @@ + +########### next target ############### + +SET(trinityconfig_STAT_SRCS + dotconfpp/dotconfpp.cpp + dotconfpp/dotconfpp.h + dotconfpp/mempool.cpp + dotconfpp/mempool.h + Config.cpp + Config.h + ConfigEnv.h +) + +include_directories( + ${ACE_INCLUDE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/framework +) + +add_library(trinityconfig STATIC ${trinityconfig_STAT_SRCS}) + diff --git a/src/server/shared/Configuration/Config.cpp b/src/server/shared/Configuration/Config.cpp new file mode 100644 index 00000000000..39830104a7c --- /dev/null +++ b/src/server/shared/Configuration/Config.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ConfigEnv.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1(Config); + +Config::Config() : mIgnoreCase(true), mConf(NULL) +{ +} + +Config::~Config() +{ + delete mConf; +} + +bool Config::SetSource(const char *file, bool ignorecase) +{ + mIgnoreCase = ignorecase; + mFilename = file; + + return Reload(); +} + +bool Config::Reload() +{ + delete mConf; + + mConf = new DOTCONFDocument(mIgnoreCase ? + DOTCONFDocument::CASEINSENSETIVE : + DOTCONFDocument::CASESENSETIVE); + + if (mConf->setContent(mFilename.c_str()) == -1) + { + delete mConf; + mConf = NULL; + return false; + } + + return true; +} + +std::string Config::GetStringDefault(const char * name, std::string def) +{ + if(!mConf) + return std::string(def); + const DOTCONFDocumentNode * node = mConf->findNode(name); + if(!node || !node->getValue()) + return std::string(def); + return std::string(node->getValue()); +}; + +bool Config::GetBoolDefault(const char * name, const bool def) +{ + if(!mConf) + return false; + const DOTCONFDocumentNode * node = mConf->findNode(name); + if(!node || !node->getValue()) + return def; + const char * str = node->getValue(); + if(strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0 || + strcmp(str, "yes") == 0 || strcmp(str, "YES") == 0 || + strcmp(str, "1") == 0) + return true; + else + return false; +}; + +int32 Config::GetIntDefault(const char * name, const int32 def) +{ + if(!mConf) + return def; + const DOTCONFDocumentNode * node = mConf->findNode(name); + if(!node || !node->getValue()) + return def; + return atoi(node->getValue()); +}; + +float Config::GetFloatDefault(const char * name, const float def) +{ + if(!mConf) + return def; + const DOTCONFDocumentNode * node = mConf->findNode(name); + if(!node || !node->getValue()) + return def; + return atof(node->getValue()); +}; diff --git a/src/server/shared/Configuration/Config.h b/src/server/shared/Configuration/Config.h new file mode 100644 index 00000000000..ccc76073e46 --- /dev/null +++ b/src/server/shared/Configuration/Config.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include "Platform/Define.h" + +class DOTCONFDocument; + +class Config +{ + public: + Config(); + ~Config(); + + bool SetSource(const char *file, bool ignorecase = true); + bool Reload(); + + std::string GetStringDefault(const char * name, std::string def); + bool GetBoolDefault(const char * name, const bool def); + int32 GetIntDefault(const char * name, const int32 def); + float GetFloatDefault(const char * name, const float def); + + std::string GetFilename() const { return mFilename; } + private: + std::string mFilename; + bool mIgnoreCase; + DOTCONFDocument *mConf; +}; + +#define sConfig Trinity::Singleton::Instance() + +#endif + diff --git a/src/server/shared/Configuration/ConfigEnv.h b/src/server/shared/Configuration/ConfigEnv.h new file mode 100644 index 00000000000..16e596fd2da --- /dev/null +++ b/src/server/shared/Configuration/ConfigEnv.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(CONFIGENVIRONMENT_H) + +#define CONFIGENVIRONMENT_H + +#include "Common.h" +#include "dotconfpp/dotconfpp.h" +#include "Config.h" + +#endif + diff --git a/src/server/shared/Configuration/ConfigLibrary.vcproj b/src/server/shared/Configuration/ConfigLibrary.vcproj new file mode 100644 index 00000000000..a8f1fc322e7 --- /dev/null +++ b/src/server/shared/Configuration/ConfigLibrary.vcproj @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/server/shared/Configuration/dotconfpp/dotconfpp.cpp b/src/server/shared/Configuration/dotconfpp/dotconfpp.cpp new file mode 100644 index 00000000000..8760b118e38 --- /dev/null +++ b/src/server/shared/Configuration/dotconfpp/dotconfpp.cpp @@ -0,0 +1,599 @@ + +#include "Common.h" + +#include "dotconfpp.h" + +#ifdef WIN32 +#define PATH_MAX _MAX_PATH +#define strcasecmp stricmp +#define realpath(path,resolved_path) _fullpath(resolved_path, path, _MAX_PATH) +#include +#else +#include +#include +#include +#include +#endif + +#if !defined(R_OK) +#define R_OK 04 +#endif + +DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL), + values(NULL), valuesCount(0), + name(NULL), lineNum(0), fileName(NULL), closed(true) +{ +} + +DOTCONFDocumentNode::~DOTCONFDocumentNode() +{ + free(name); + if(values != NULL){ + for (int i = 0 ; i < valuesCount; i++){ + free(values[i]); + } + free(values); + } +} + +void DOTCONFDocumentNode::pushValue(char * _value) +{ + ++valuesCount; + values = (char**)realloc(values, valuesCount*sizeof(char*)); + values[valuesCount-1] = strdup(_value); +} + +const char* DOTCONFDocumentNode::getValue(int index) const +{ + if(index >= valuesCount){ + return NULL; + } + return values[index]; +} + +DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity): + mempool(NULL), + curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL) +{ + if(caseSensitivity == CASESENSETIVE){ + cmp_func = strcmp; + } else { + cmp_func = strcasecmp; + } + + mempool = new AsyncDNSMemPool(1024); + mempool->initialize(); +} + +DOTCONFDocument::~DOTCONFDocument() +{ + for (std::list::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){ + delete(*i); + } + for (std::list::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i){ + free(*i); + } + for (std::list::iterator i = processedFiles.begin(); i != processedFiles.end(); ++i){ + free(*i); + } + free(fileName); + delete mempool; +} + +int DOTCONFDocument::cleanupLine(char * line) +{ + char * start = line; + char * bg = line; + bool multiline = false; + bool concat = false; + char * word = NULL; + + if(!words.empty() && quoted) + concat = true; + + while(*line){ + if((*line == '#' || *line == ';') && !quoted){ + *bg = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + break; + } + if(*line == '=' && !quoted){ + *line = ' ';continue; + } + + // Allowing \" in there causes problems with directory paths + // like "C:\TrinIty\" + //if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){ + if(*line == '\\' && (*(line+1) == '\'')) { + *bg++ = *(line+1); + line+=2; continue; + } + if(*line == '\\' && *(line+1) == 'n'){ + *bg++ = '\n'; + line+=2; continue; + } + if(*line == '\\' && *(line+1) == 'r'){ + *bg++ = '\r'; + line+=2; continue; + } + if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){ + *bg = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + multiline = true; + break; + } + if(*line == '"' || *line == '\''){ + quoted = !quoted; + ++line; continue; + } + if(isspace((unsigned char)*line) && !quoted){ + *bg++ = 0; + if(strlen(start)){ + + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + start = bg; + while(isspace((unsigned char)*++line)) {} + + continue; + } + *bg++ = *line++; + } + + if(quoted && !multiline){ + error(curLine, fileName, "unterminated quote"); + return -1; + } + + return multiline?1:0; +} + +int DOTCONFDocument::parseLine() +{ + char * word = NULL; + char * nodeName = NULL; + char * nodeValue = NULL; + DOTCONFDocumentNode * tagNode = NULL; + bool newNode = false; + + for (std::list::iterator i = words.begin(); i != words.end(); ++i) { + word = *i; + + if(*word == '<'){ + newNode = true; + } + + if(newNode){ + nodeValue = NULL; + nodeName = NULL; + newNode = false; + } + + size_t wordLen = strlen(word); + if(word[wordLen-1] == '>'){ + word[wordLen-1] = 0; + newNode = true; + } + + if(nodeName == NULL){ + nodeName = word; + bool closed = true; + if(*nodeName == '<'){ + if(*(nodeName+1) != '/'){ + ++nodeName; + closed = false; + } else { + nodeName+=2; + std::list::reverse_iterator itr=nodeTree.rbegin(); + for (; itr!=nodeTree.rend(); ++itr){ + if(!cmp_func(nodeName, (*itr)->name) && !(*itr)->closed){ + (*itr)->closed = true; + curParent = (*itr)->parentNode; + curPrev = *itr; + break; + } + } + if(itr==nodeTree.rend()){ + error(curLine, fileName, "not matched closing tag ", nodeName); + return -1; + } + continue; + } + } + tagNode = new DOTCONFDocumentNode; + tagNode->name = strdup(nodeName); + tagNode->document = this; + tagNode->fileName = processedFiles.back(); + tagNode->lineNum = curLine; + tagNode->closed = closed; + if(!nodeTree.empty()){ + DOTCONFDocumentNode * prev = nodeTree.back(); + if(prev->closed){ + + curPrev->nextNode = tagNode; + tagNode->previousNode = curPrev; + tagNode->parentNode = curParent; + + } else { + prev->childNode = tagNode; + tagNode->parentNode = prev; + curParent = prev; + } + } + nodeTree.push_back(tagNode); + curPrev = tagNode; + } else { + nodeValue = word; + tagNode->pushValue(nodeValue); + } + } + + return 0; +} +int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent) +{ + char str[512]; + int ret = 0; + curLine = 0; + curParent = _parent; + + quoted = false; + size_t slen = 0; + + while(fgets(str, 511, file)){ + ++curLine; + slen = strlen(str); + if( slen >= 510 ){ + error(curLine, fileName, "warning: line too long"); + } + if(str[slen-1] != '\n'){ + str[slen] = '\n'; + str[slen+1] = 0; + } + if((ret = cleanupLine(str)) == -1){ + break; + } + if(ret == 0){ + if(!words.empty()){ + ret = parseLine(); + mempool->free(); + words.clear(); + if(ret == -1){ + break; + } + } + } + } + + return ret; +} + +int DOTCONFDocument::checkConfig(const std::list::iterator & from) +{ + int ret = 0; + + DOTCONFDocumentNode * tagNode = NULL; + int vi = 0; + for (std::list::iterator i = from; i != nodeTree.end(); ++i){ + tagNode = *i; + if(!tagNode->closed){ + error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name); + ret = -1; + break; + } + vi = 0; + while( vi < tagNode->valuesCount ){ + + if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){ + ret = macroSubstitute(tagNode, vi ); + mempool->free(); + if(ret == -1){ + break; + } + } + ++vi; + } + if(ret == -1){ + break; + } + } + + return ret; +} + +int DOTCONFDocument::setContent(const char * _fileName) +{ + int ret = 0; + char realpathBuf[PATH_MAX]; + + if(realpath(_fileName, realpathBuf) == NULL){ + error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno)); + return -1; + } + + fileName = strdup(realpathBuf); + + processedFiles.push_back(strdup(realpathBuf)); + + if(( file = fopen(fileName, "r")) == NULL){ + error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno)); + return -1; + } + // Try read utf8 header and skip it if exist + uint32 utf8header = 0; + fgets((char*)&utf8header, 4, file); // Try read header + if (utf8header!=0x00BFBBEF) // If not exist + fseek(file, 0, SEEK_SET); // Reset read position + + ret = parseFile(); + + (void) fclose(file); + + if(!ret){ + + if( (ret = checkConfig(nodeTree.begin())) == -1){ + return -1; + } + + std::list::iterator from; + DOTCONFDocumentNode * tagNode = NULL; + int vi = 0; + for (std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ + tagNode = *i; + if(!cmp_func("DOTCONFPPIncludeFile", tagNode->name)){ + vi = 0; + while( vi < tagNode->valuesCount ){ + if(access(tagNode->values[vi], R_OK) == -1){ + error(tagNode->lineNum, tagNode->fileName, "%s: %s", tagNode->values[vi], strerror(errno)); + return -1; + } + if(realpath(tagNode->values[vi], realpathBuf) == NULL){ + error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", tagNode->values[vi], strerror(errno)); + return -1; + } + + bool processed = false; + for (std::list::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); ++itInode){ + if(!strcmp(*itInode, realpathBuf)){ + processed = true; + break; + } + } + if(processed){ + break; + } + + processedFiles.push_back(strdup(realpathBuf)); + + file = fopen(tagNode->values[vi], "r"); + if(file == NULL){ + error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno)); + return -1; + } + + fileName = strdup(realpathBuf); + from = nodeTree.end(); --from; + + ret = parseFile(); + (void) fclose(file); + if(ret == -1) + return -1; + if(checkConfig(++from) == -1){ + return -1; + } + ++vi; + } + } + } + + if(!requiredOptions.empty()) + ret = checkRequiredOptions(); + } + + return ret; +} + +int DOTCONFDocument::checkRequiredOptions() +{ + for (std::list::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){ + bool matched = false; + for (std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ + if(!cmp_func((*i)->name, *ci)){ + matched = true; + break; + } + } + if(!matched){ + error(0, NULL, "required option '%s' not specified", *ci); + return -1; + } + } + return 0; +} + +void DOTCONFDocument::error(int lineNum, const char * fileName_, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + + size_t len = (lineNum!=0?strlen(fileName_):0) + strlen(fmt) + 50; + char * buf = (char*)mempool->alloc(len); + + if(lineNum) + (void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt); + else + (void) snprintf(buf, len, "DOTCONF++: %s\n", fmt); + + (void) vfprintf(stderr, buf, args); + + va_end(args); +} + +char * DOTCONFDocument::getSubstitution(char * macro, int lineNum) +{ + char * buf = NULL; + char * variable = macro+2; + + char * endBr = strchr(macro, '}'); + + if(!endBr){ + error(lineNum, fileName, "unterminated '{'"); + return NULL; + } + *endBr = 0; + + char * defaultValue = strchr(variable, ':'); + + if(defaultValue){ + *defaultValue++ = 0; + if(*defaultValue != '-'){ + error(lineNum, fileName, "incorrect macro substitution syntax"); + return NULL; + } + ++defaultValue; + if(*defaultValue == '"' || *defaultValue == '\''){ + ++defaultValue; + defaultValue[strlen(defaultValue)-1] = 0; + } + } else { + defaultValue = NULL; + } + + char * subs = getenv(variable); + if( subs ){ + buf = mempool->strdup(subs); + } else { + std::list::iterator i = nodeTree.begin(); + DOTCONFDocumentNode * tagNode = NULL; + for (; i!=nodeTree.end(); i++){ + tagNode = *i; + if(!cmp_func(tagNode->name, variable)){ + if(tagNode->valuesCount != 0){ + buf = mempool->strdup(tagNode->values[0]); + break; + } + } + } + if( i == nodeTree.end() ){ + if( defaultValue ){ + buf = mempool->strdup(defaultValue); + } else { + error(lineNum, fileName, "substitution not found and default value not given"); + return NULL; + } + } + } + return buf; +} + +int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex) +{ + int ret = 0; + char * macro = tagNode->values[valueIndex]; + size_t valueLen = strlen(tagNode->values[valueIndex])+1; + char * value = (char*)mempool->alloc(valueLen); + char * v = value; + char * subs = NULL; + + while(*macro){ + if(*macro == '$' && *(macro+1) == '{'){ + char * m = strchr(macro, '}'); + subs = getSubstitution(macro, tagNode->lineNum); + if(subs == NULL){ + ret = -1; + break; + } + macro = m + 1; + *v = 0; + v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen); + strcpy(v, value); + value = strcat(v, subs); + v = value + strlen(value); + continue; + } + *v++ = *macro++; + } + *v = 0; + + free(tagNode->values[valueIndex]); + tagNode->values[valueIndex] = strdup(value); + return ret; +} + +const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const +{ + if ( !nodeTree.empty() ) { + return *nodeTree.begin(); + } else { + return NULL; + } +} + +const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const +{ + + std::list::const_iterator i = nodeTree.begin(); + + if(startNode == NULL) + startNode = parentNode; + + if(startNode != NULL){ + while( i != nodeTree.end() && (*i) != startNode ){ + ++i; + } + if( i != nodeTree.end() ) ++i; + } + + for (; i!=nodeTree.end(); ++i){ + + if((*i)->parentNode != parentNode){ + continue; + } + if(!cmp_func(nodeName, (*i)->name)){ + return *i; + } + } + return NULL; +} + +void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames) +{ + while(*requiredOptionNames){ + requiredOptions.push_back(strdup( *requiredOptionNames )); + ++requiredOptionNames; + } +} + diff --git a/src/server/shared/Configuration/dotconfpp/dotconfpp.h b/src/server/shared/Configuration/dotconfpp/dotconfpp.h new file mode 100644 index 00000000000..554b152f693 --- /dev/null +++ b/src/server/shared/Configuration/dotconfpp/dotconfpp.h @@ -0,0 +1,97 @@ + + +#ifndef DOTCONFPP_H +#define DOTCONFPP_H + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "mempool.h" + +class DOTCONFDocument; + +class DOTCONFDocumentNode +{ +friend class DOTCONFDocument; +private: + DOTCONFDocumentNode * previousNode; + DOTCONFDocumentNode * nextNode; + DOTCONFDocumentNode * parentNode; + DOTCONFDocumentNode * childNode; + char ** values; + int valuesCount; + char * name; + const DOTCONFDocument * document; + int lineNum; + char * fileName; + bool closed; + + void pushValue(char * _value); + +public: + DOTCONFDocumentNode(); + ~DOTCONFDocumentNode(); + + const char * getConfigurationFileName()const { return fileName; } + int getConfigurationLineNumber() const { return lineNum; } + + const DOTCONFDocumentNode * getNextNode() const { return nextNode; } + const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; } + const DOTCONFDocumentNode * getParentNode() const { return parentNode; } + const DOTCONFDocumentNode * getChildNode() const { return childNode; } + const char* getValue(int index = 0) const; + const char * getName() const { return name; } + const DOTCONFDocument * getDocument() const { return document; } +}; + +class DOTCONFDocument +{ +public: + enum CaseSensitive { CASESENSETIVE, CASEINSENSETIVE }; +protected: + AsyncDNSMemPool * mempool; +private: + DOTCONFDocumentNode * curParent; + DOTCONFDocumentNode * curPrev; + int curLine; + bool quoted; + std::list nodeTree; + std::list requiredOptions; + std::list processedFiles; + FILE * file; + char * fileName; + std::list words; + int (*cmp_func)(const char *, const char *); + + int checkRequiredOptions(); + int parseLine(); + int parseFile(DOTCONFDocumentNode * _parent = NULL); + int checkConfig(const std::list::iterator & from); + int cleanupLine(char * line); + char * getSubstitution(char * macro, int lineNum); + int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex); + +protected: + virtual void error(int lineNum, const char * fileName, const char * fmt, ...) ATTR_PRINTF(4,5); + +public: + DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSETIVE); + virtual ~DOTCONFDocument(); + + int setContent(const char * _fileName); + + void setRequiredOptionNames(const char ** requiredOptionNames); + const DOTCONFDocumentNode * getFirstNode() const; + const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const; +}; + +#endif + diff --git a/src/server/shared/Configuration/dotconfpp/mempool.cpp b/src/server/shared/Configuration/dotconfpp/mempool.cpp new file mode 100644 index 00000000000..a23e33808bd --- /dev/null +++ b/src/server/shared/Configuration/dotconfpp/mempool.cpp @@ -0,0 +1,100 @@ + + +#include "mempool.h" + +AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size): + pool(NULL), pos(0), size(_size) +{ + pool = ::malloc(size); +} + +AsyncDNSMemPool::PoolChunk::~PoolChunk() +{ + ::free(pool); +} + +AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize): + chunks(NULL), chunksCount(0), defaultSize(_defaultSize), + poolUsage(0), poolUsageCounter(0) +{ +} + +AsyncDNSMemPool::~AsyncDNSMemPool() +{ + for (size_t i = 0; isize - chunk->pos) >= size){ + chunk->pos += size; + return ((char*)chunk->pool) + chunk->pos - size; + } + } + addNewChunk(size); + chunks[chunksCount-1]->pos = size; + return chunks[chunksCount-1]->pool; +} + +void AsyncDNSMemPool::free() +{ + size_t pu = 0; + size_t psz = 0; + ++poolUsageCounter; + + for (size_t i = 0; ipos; + psz += chunks[i]->size; + chunks[i]->pos = 0; + } + poolUsage=(poolUsage>pu)?poolUsage:pu; + + if(poolUsageCounter >= 10 && chunksCount > 1){ + psz -= chunks[chunksCount-1]->size; + if(poolUsage < psz){ + --chunksCount; + delete chunks[chunksCount]; + } + poolUsage = 0; + poolUsageCounter = 0; + } +} + +void * AsyncDNSMemPool::calloc(size_t size) +{ + return ::memset(this->alloc(size), 0, size); +} + +char * AsyncDNSMemPool::strdup(const char *str) +{ + return ::strcpy((char*)this->alloc(strlen(str)+1), str); +} + diff --git a/src/server/shared/Configuration/dotconfpp/mempool.h b/src/server/shared/Configuration/dotconfpp/mempool.h new file mode 100644 index 00000000000..185b50798e1 --- /dev/null +++ b/src/server/shared/Configuration/dotconfpp/mempool.h @@ -0,0 +1,46 @@ + + +#ifndef ASYNC_DNS_MEMPOOL_H +#define ASYNC_DNS_MEMPOOL_H + +#include +#include +#include + +#undef free +#undef calloc +#undef strdup + +class AsyncDNSMemPool +{ +private: + struct PoolChunk { + void * pool; + size_t pos; + size_t size; + + PoolChunk(size_t _size); + ~PoolChunk(); + }; + PoolChunk ** chunks; + size_t chunksCount; + size_t defaultSize; + + size_t poolUsage; + size_t poolUsageCounter; + + void addNewChunk(size_t size); + +public: + AsyncDNSMemPool(size_t _defaultSize = 4096); + virtual ~AsyncDNSMemPool(); + + int initialize(); + void free(); + void * alloc(size_t size); + void * calloc(size_t size); + char * strdup(const char *str); +}; + +#endif + diff --git a/src/server/shared/Cryptography/Authentication/AuthCrypt.cpp b/src/server/shared/Cryptography/Authentication/AuthCrypt.cpp new file mode 100644 index 00000000000..b34b922b16a --- /dev/null +++ b/src/server/shared/Cryptography/Authentication/AuthCrypt.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "AuthCrypt.h" +#include "Hmac.h" +#include "Log.h" +#include "BigNumber.h" + +AuthCrypt::AuthCrypt() : _clientDecrypt(SHA_DIGEST_LENGTH), _serverEncrypt(SHA_DIGEST_LENGTH) +{ + _initialized = false; +} + +AuthCrypt::~AuthCrypt() +{ + +} + +void AuthCrypt::Init(BigNumber *K) +{ + uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 }; + HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey); + uint8 *encryptHash = serverEncryptHmac.ComputeHash(K); + + uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE }; + HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey); + uint8 *decryptHash = clientDecryptHmac.ComputeHash(K); + + //SARC4 _serverDecrypt(encryptHash); + _clientDecrypt.Init(decryptHash); + _serverEncrypt.Init(encryptHash); + //SARC4 _clientEncrypt(decryptHash); + + uint8 syncBuf[1024]; + + memset(syncBuf, 0, 1024); + + _serverEncrypt.UpdateData(1024, syncBuf); + //_clientEncrypt.UpdateData(1024, syncBuf); + + memset(syncBuf, 0, 1024); + + //_serverDecrypt.UpdateData(1024, syncBuf); + _clientDecrypt.UpdateData(1024, syncBuf); + + _initialized = true; +} + +void AuthCrypt::DecryptRecv(uint8 *data, size_t len) +{ + if (!_initialized) + return; + + _clientDecrypt.UpdateData(len, data); +} + +void AuthCrypt::EncryptSend(uint8 *data, size_t len) +{ + if (!_initialized) + return; + + _serverEncrypt.UpdateData(len, data); +} + diff --git a/src/server/shared/Cryptography/Authentication/AuthCrypt.h b/src/server/shared/Cryptography/Authentication/AuthCrypt.h new file mode 100644 index 00000000000..6695dc580cc --- /dev/null +++ b/src/server/shared/Cryptography/Authentication/AuthCrypt.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTHCRYPT_H +#define _AUTHCRYPT_H + +#include +#include "SARC4.h" + +class BigNumber; + +class AuthCrypt +{ + public: + AuthCrypt(); + ~AuthCrypt(); + + void Init(BigNumber *K); + void DecryptRecv(uint8 *, size_t); + void EncryptSend(uint8 *, size_t); + + bool IsInitialized() { return _initialized; } + + private: + SARC4 _clientDecrypt; + SARC4 _serverEncrypt; + bool _initialized; +}; +#endif + diff --git a/src/server/shared/Cryptography/BigNumber.cpp b/src/server/shared/Cryptography/BigNumber.cpp new file mode 100644 index 00000000000..64e9ef21ccc --- /dev/null +++ b/src/server/shared/Cryptography/BigNumber.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/BigNumber.h" +#include +#include + +BigNumber::BigNumber() +{ + _bn = BN_new(); + _array = NULL; +} + +BigNumber::BigNumber(const BigNumber &bn) +{ + _bn = BN_dup(bn._bn); + _array = NULL; +} + +BigNumber::BigNumber(uint32 val) +{ + _bn = BN_new(); + BN_set_word(_bn, val); + _array = NULL; +} + +BigNumber::~BigNumber() +{ + BN_free(_bn); + if(_array) delete[] _array; +} + +void BigNumber::SetDword(uint32 val) +{ + BN_set_word(_bn, val); +} + +void BigNumber::SetQword(uint64 val) +{ + BN_add_word(_bn, (uint32)(val >> 32)); + BN_lshift(_bn, _bn, 32); + BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF)); +} + +void BigNumber::SetBinary(const uint8 *bytes, int len) +{ + uint8 t[1000]; + for (int i = 0; i < len; i++) t[i] = bytes[len - 1 - i]; + BN_bin2bn(t, len, _bn); +} + +void BigNumber::SetHexStr(const char *str) +{ + BN_hex2bn(&_bn, str); +} + +void BigNumber::SetRand(int numbits) +{ + BN_rand(_bn, numbits, 0, 1); +} + +BigNumber BigNumber::operator=(const BigNumber &bn) +{ + BN_copy(_bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator+=(const BigNumber &bn) +{ + BN_add(_bn, _bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator-=(const BigNumber &bn) +{ + BN_sub(_bn, _bn, bn._bn); + return *this; +} + +BigNumber BigNumber::operator*=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mul(_bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::operator/=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_div(_bn, NULL, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::operator%=(const BigNumber &bn) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mod(_bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return *this; +} + +BigNumber BigNumber::Exp(const BigNumber &bn) +{ + BigNumber ret; + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_exp(ret._bn, _bn, bn._bn, bnctx); + BN_CTX_free(bnctx); + + return ret; +} + +BigNumber BigNumber::ModExp(const BigNumber &bn1, const BigNumber &bn2) +{ + BigNumber ret; + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx); + BN_CTX_free(bnctx); + + return ret; +} + +int BigNumber::GetNumBytes(void) +{ + return BN_num_bytes(_bn); +} + +uint32 BigNumber::AsDword() +{ + return (uint32)BN_get_word(_bn); +} + +bool BigNumber::isZero() const +{ + return BN_is_zero(_bn)!=0; +} + +uint8 *BigNumber::AsByteArray(int minSize, bool reverse) +{ + int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); + + if (_array) + { + delete[] _array; + _array = NULL; + } + _array = new uint8[length]; + + // If we need more bytes than length of BigNumber set the rest to 0 + if (length > GetNumBytes()) + memset((void*)_array, 0, length); + + BN_bn2bin(_bn, (unsigned char *)_array); + + if (reverse) + std::reverse(_array, _array + length); + + return _array; +} + +const char *BigNumber::AsHexStr() +{ + return BN_bn2hex(_bn); +} + +const char *BigNumber::AsDecStr() +{ + return BN_bn2dec(_bn); +} + diff --git a/src/server/shared/Cryptography/BigNumber.h b/src/server/shared/Cryptography/BigNumber.h new file mode 100644 index 00000000000..1dd43c83fc7 --- /dev/null +++ b/src/server/shared/Cryptography/BigNumber.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_BIGNUMBER_H +#define _AUTH_BIGNUMBER_H + +#include "Common.h" + +struct bignum_st; + +class BigNumber +{ + public: + BigNumber(); + BigNumber(const BigNumber &bn); + BigNumber(uint32); + ~BigNumber(); + + void SetDword(uint32); + void SetQword(uint64); + void SetBinary(const uint8 *bytes, int len); + void SetHexStr(const char *str); + + void SetRand(int numbits); + + BigNumber operator=(const BigNumber &bn); + + BigNumber operator+=(const BigNumber &bn); + BigNumber operator+(const BigNumber &bn) + { + BigNumber t(*this); + return t += bn; + } + BigNumber operator-=(const BigNumber &bn); + BigNumber operator-(const BigNumber &bn) + { + BigNumber t(*this); + return t -= bn; + } + BigNumber operator*=(const BigNumber &bn); + BigNumber operator*(const BigNumber &bn) + { + BigNumber t(*this); + return t *= bn; + } + BigNumber operator/=(const BigNumber &bn); + BigNumber operator/(const BigNumber &bn) + { + BigNumber t(*this); + return t /= bn; + } + BigNumber operator%=(const BigNumber &bn); + BigNumber operator%(const BigNumber &bn) + { + BigNumber t(*this); + return t %= bn; + } + + bool isZero() const; + + BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2); + BigNumber Exp(const BigNumber &); + + int GetNumBytes(void); + + struct bignum_st *BN() { return _bn; } + + uint32 AsDword(); + uint8* AsByteArray(int minSize = 0, bool reverse = true); + + const char *AsHexStr(); + const char *AsDecStr(); + + private: + struct bignum_st *_bn; + uint8 *_array; +}; +#endif + diff --git a/src/server/shared/Cryptography/CMakeLists.txt b/src/server/shared/Cryptography/CMakeLists.txt new file mode 100644 index 00000000000..6e5d10d40e5 --- /dev/null +++ b/src/server/shared/Cryptography/CMakeLists.txt @@ -0,0 +1,27 @@ + +########### next target ############### + +SET(trinityauth_STAT_SRCS + AuthCrypt.cpp + AuthCrypt.h + BigNumber.cpp + BigNumber.h + Hmac.cpp + Hmac.h + Sha1.cpp + Sha1.h + md5.c + md5.h + SARC4.cpp + SARC4.h +) + +include_directories( + ${ACE_INCLUDE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/framework + ${MYSQL_INCLUDE_DIR} +) + +add_library(trinityauth STATIC ${trinityauth_STAT_SRCS}) diff --git a/src/server/shared/Cryptography/Hmac.cpp b/src/server/shared/Cryptography/Hmac.cpp new file mode 100644 index 00000000000..a30f1b2d1e2 --- /dev/null +++ b/src/server/shared/Cryptography/Hmac.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/Hmac.h" +#include "BigNumber.h" + +HmacHash::HmacHash(uint32 len, uint8 *seed) +{ + HMAC_CTX_init(&m_ctx); + HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL); +} + +HmacHash::~HmacHash() +{ + HMAC_CTX_cleanup(&m_ctx); +} + +void HmacHash::UpdateBigNumber(BigNumber *bn) +{ + UpdateData(bn->AsByteArray(), bn->GetNumBytes()); +} + +void HmacHash::UpdateData(const uint8 *data, int length) +{ + HMAC_Update(&m_ctx, data, length); +} + +void HmacHash::UpdateData(const std::string &str) +{ + UpdateData((uint8 const*)str.c_str(), str.length()); +} + +void HmacHash::Finalize() +{ + uint32 length = 0; + HMAC_Final(&m_ctx, (uint8*)m_digest, &length); + ASSERT(length == SHA_DIGEST_LENGTH) +} + +uint8 *HmacHash::ComputeHash(BigNumber *bn) +{ + HMAC_Update(&m_ctx, bn->AsByteArray(), bn->GetNumBytes()); + Finalize(); + return (uint8*)m_digest; +} diff --git a/src/server/shared/Cryptography/Hmac.h b/src/server/shared/Cryptography/Hmac.h new file mode 100644 index 00000000000..845d6e84802 --- /dev/null +++ b/src/server/shared/Cryptography/Hmac.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_HMAC_H +#define _AUTH_HMAC_H + +#include "Common.h" +#include +#include + +class BigNumber; + +#define SEED_KEY_SIZE 16 + +class HmacHash +{ + public: + HmacHash(uint32 len, uint8 *seed); + ~HmacHash(); + void UpdateBigNumber(BigNumber *bn); + void UpdateData(const uint8 *data, int length); + void UpdateData(const std::string &str); + void Finalize(); + uint8 *ComputeHash(BigNumber *bn); + uint8 *GetDigest() { return (uint8*)m_digest; } + int GetLength() { return SHA_DIGEST_LENGTH; } + private: + HMAC_CTX m_ctx; + uint8 m_digest[SHA_DIGEST_LENGTH]; +}; +#endif + diff --git a/src/server/shared/Cryptography/SARC4.cpp b/src/server/shared/Cryptography/SARC4.cpp new file mode 100644 index 00000000000..80cad4991e9 --- /dev/null +++ b/src/server/shared/Cryptography/SARC4.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/SARC4.h" +#include + +SARC4::SARC4(uint8 len) +{ + EVP_CIPHER_CTX_init(&m_ctx); + EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); + EVP_CIPHER_CTX_set_key_length(&m_ctx, len); +} + +SARC4::SARC4(uint8 *seed, uint8 len) +{ + EVP_CIPHER_CTX_init(&m_ctx); + EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); + EVP_CIPHER_CTX_set_key_length(&m_ctx, len); + EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); +} + +SARC4::~SARC4() +{ + EVP_CIPHER_CTX_cleanup(&m_ctx); +} + +void SARC4::Init(uint8 *seed) +{ + EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); +} + +void SARC4::UpdateData(int len, uint8 *data) +{ + int outlen = 0; + EVP_EncryptUpdate(&m_ctx, data, &outlen, data, len); + EVP_EncryptFinal_ex(&m_ctx, data, &outlen); +} diff --git a/src/server/shared/Cryptography/SARC4.h b/src/server/shared/Cryptography/SARC4.h new file mode 100644 index 00000000000..2e408627fc8 --- /dev/null +++ b/src/server/shared/Cryptography/SARC4.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_SARC4_H +#define _AUTH_SARC4_H + +#include "Common.h" +#include + +class SARC4 +{ + public: + SARC4(uint8 len); + SARC4(uint8 *seed, uint8 len); + ~SARC4(); + void Init(uint8 *seed); + void UpdateData(int len, uint8 *data); + private: + EVP_CIPHER_CTX m_ctx; +}; +#endif diff --git a/src/server/shared/Cryptography/Sha1.cpp b/src/server/shared/Cryptography/Sha1.cpp new file mode 100644 index 00000000000..b63deb2c5f3 --- /dev/null +++ b/src/server/shared/Cryptography/Sha1.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/Sha1.h" +#include "Auth/BigNumber.h" +#include + +Sha1Hash::Sha1Hash() +{ + SHA1_Init(&mC); +} + +Sha1Hash::~Sha1Hash() +{ + SHA1_Init(&mC); +} + +void Sha1Hash::UpdateData(const uint8 *dta, int len) +{ + SHA1_Update(&mC, dta, len); +} + +void Sha1Hash::UpdateData(const std::string &str) +{ + UpdateData((uint8 const*)str.c_str(), str.length()); +} + +void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...) +{ + va_list v; + BigNumber *bn; + + va_start(v, bn0); + bn = bn0; + while (bn) + { + UpdateData(bn->AsByteArray(), bn->GetNumBytes()); + bn = va_arg(v, BigNumber *); + } + va_end(v); +} + +void Sha1Hash::Initialize() +{ + SHA1_Init(&mC); +} + +void Sha1Hash::Finalize(void) +{ + SHA1_Final(mDigest, &mC); +} + diff --git a/src/server/shared/Cryptography/Sha1.h b/src/server/shared/Cryptography/Sha1.h new file mode 100644 index 00000000000..2d7f361ae9a --- /dev/null +++ b/src/server/shared/Cryptography/Sha1.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_SHA1_H +#define _AUTH_SHA1_H + +#include "Common.h" +#include +#include + +class BigNumber; + +class Sha1Hash +{ + public: + Sha1Hash(); + ~Sha1Hash(); + + void UpdateFinalizeBigNumbers(BigNumber *bn0, ...); + void UpdateBigNumbers(BigNumber *bn0, ...); + + void UpdateData(const uint8 *dta, int len); + void UpdateData(const std::string &str); + + void Initialize(); + void Finalize(); + + uint8 *GetDigest(void) { return mDigest; }; + int GetLength(void) { return SHA_DIGEST_LENGTH; }; + + private: + SHA_CTX mC; + uint8 mDigest[SHA_DIGEST_LENGTH]; +}; +#endif + diff --git a/src/server/shared/Cryptography/md5.c b/src/server/shared/Cryptography/md5.c new file mode 100644 index 00000000000..3e9735e2dbb --- /dev/null +++ b/src/server/shared/Cryptography/md5.c @@ -0,0 +1,385 @@ +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +*/ +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + +The original and principal author of md5.c is L. Peter Deutsch +. Other authors are noted in the change history +that follows (in reverse chronological order): + +2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order +either statically or dynamically; added missing #include +in library. +2002-03-11 lpd Corrected argument list for main(), and added int return +type, in test program and T value program. +2002-02-21 lpd Added missing #include in test program. +2000-07-03 lpd Patched to eliminate warnings about "constant is +unsigned in ANSI C, signed in traditional"; made test program +self-checking. +1999-11-04 lpd Edited comments slightly for automatic TOC extraction. +1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). +1999-05-03 lpd Original version. +*/ + +#include "md5.h" +#include + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + #if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; + #else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + const md5_word_t *X; + #endif + + { + #if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ + #endif + #if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) + { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } + else + { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } + #endif + #if BYTE_ORDER == 0 + else /* dynamic big-endian */ + #endif + #if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + + # if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ + # else + # define xbuf X /* (static only) */ + # endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } + #endif + } + + #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ + #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); + #undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ + #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); + #undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ + #define H(x, y, z) ((x) ^ (y) ^ (z)) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); + #undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ + #define I(x, y, z) ((y) ^ ((x) | ~(z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); + #undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + ++pms->count[1]; + + /* Process an initial partial block. */ + if (offset) + { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = + { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/server/shared/Cryptography/md5.h b/src/server/shared/Cryptography/md5.h new file mode 100644 index 00000000000..0463051b6a6 --- /dev/null +++ b/src/server/shared/Cryptography/md5.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +*/ +/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + +The original and principal author of md5.h is L. Peter Deutsch +. Other authors are noted in the change history +that follows (in reverse chronological order): + +2002-04-13 lpd Removed support for non-ANSI compilers; removed +references to Ghostscript; clarified derivation from RFC 1321; +now handles byte order either statically or dynamically. +1999-11-04 lpd Edited comments slightly for automatic TOC extraction. +1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); +added conditionalization for C++ compilation from Martin +Purschke . +1999-05-03 lpd Original version. +*/ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s +{ + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ + #endif + + /* Initialize the algorithm. */ + void md5_init(md5_state_t *pms); + + /* Append a string to the message. */ + void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); + + /* Finish the message and return the digest. */ + void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + + #ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif /* md5_INCLUDED */ + diff --git a/src/server/shared/DataStores/DBCFileLoader.cpp b/src/server/shared/DataStores/DBCFileLoader.cpp new file mode 100644 index 00000000000..bad87a36fce --- /dev/null +++ b/src/server/shared/DataStores/DBCFileLoader.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "DBCFileLoader.h" + +DBCFileLoader::DBCFileLoader() +{ + data = NULL; + fieldsOffset = NULL; +} + +bool DBCFileLoader::Load(const char *filename, const char *fmt) +{ + uint32 header; + if (data) + { + delete [] data; + data = NULL; + } + + FILE * f = fopen(filename,"rb"); + if (!f) + return false; + + if (fread(&header,4,1,f)!=1) // Number of records + return false; + + EndianConvert(header); + + if (header!=0x43424457) + return false; //'WDBC' + + if (fread(&recordCount,4,1,f)!=1) // Number of records + return false; + + EndianConvert(recordCount); + + if (fread(&fieldCount,4,1,f)!=1) // Number of fields + return false; + + EndianConvert(fieldCount); + + if (fread(&recordSize,4,1,f)!=1) // Size of a record + return false; + + EndianConvert(recordSize); + + if (fread(&stringSize,4,1,f)!=1) // String size + return false; + + EndianConvert(stringSize); + + fieldsOffset = new uint32[fieldCount]; + fieldsOffset[0] = 0; + for (uint32 i = 1; i < fieldCount; i++) + { + fieldsOffset[i] = fieldsOffset[i - 1]; + if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields + fieldsOffset[i] += 1; + else // 4 byte fields (int32/float/strings) + fieldsOffset[i] += 4; + } + + data = new unsigned char[recordSize*recordCount+stringSize]; + stringTable = data + recordSize*recordCount; + + if (fread(data,recordSize*recordCount+stringSize,1,f)!=1) + return false; + + fclose(f); + + return true; +} + +DBCFileLoader::~DBCFileLoader() +{ + if (data) + delete [] data; + + if (fieldsOffset) + delete [] fieldsOffset; +} + +DBCFileLoader::Record DBCFileLoader::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id*recordSize); +} + +uint32 DBCFileLoader::GetFormatRecordSize(const char * format,int32* index_pos) +{ + uint32 recordsize = 0; + int32 i = -1; + for (uint32 x=0; format[x]; ++x) + { + switch(format[x]) + { + case FT_FLOAT: + case FT_INT: + recordsize+=4; + break; + case FT_STRING: + recordsize+=sizeof(char*); + break; + case FT_SORT: + i=x; + break; + case FT_IND: + i=x; + recordsize+=4; + break; + case FT_BYTE: + recordsize += 1; + break; + } + } + + if (index_pos) + *index_pos = i; + + return recordsize; +} + +char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable) +{ + /* + format STRING, NA, FLOAT,NA,INT <=> + struct{ + char* field0, + float field1, + int field2 + }entry; + + this func will generate entry[rows] data; + */ + + typedef char * ptr; + if (strlen(format)!=fieldCount) + return NULL; + + //get struct size and index pos + int32 i; + uint32 recordsize=GetFormatRecordSize(format,&i); + + if (i>=0) + { + uint32 maxi=0; + //find max index + for (uint32 y=0; ymaxi)maxi=ind; + } + + // If higher index avalible from sql - use it instead of dbcs + if (sqlHighestIndex > maxi) + maxi = sqlHighestIndex; + + ++maxi; + records=maxi; + indexTable=new ptr[maxi]; + memset(indexTable,0,maxi*sizeof(ptr)); + } + else + { + records = recordCount + sqlRecordCount; + indexTable = new ptr[recordCount+ sqlRecordCount]; + } + + char* dataTable= new char[(recordCount + sqlRecordCount)*recordsize]; + + uint32 offset=0; + + for (uint32 y =0; y=0) + indexTable[getRecord(y).getUInt(i)]=&dataTable[offset]; + else + indexTable[y]=&dataTable[offset]; + + for (uint32 x=0; x + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DBC_FILE_LOADER_H +#define DBC_FILE_LOADER_H +#include "Platform/Define.h" +#include "Utilities/ByteConverter.h" +#include + +enum +{ + FT_NA='x', //not used or unknown, 4 byte size + FT_NA_BYTE='X', //not used or unknown, byte + FT_STRING='s', //char* + FT_FLOAT='f', //float + FT_INT='i', //uint32 + FT_BYTE='b', //uint8 + FT_SORT='d', //sorted by this field, field is not included + FT_IND='n', //the same,but parsed to data + FT_LOGIC='l', //Logical (boolean) + FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc + FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc +}; + +class DBCFileLoader +{ + public: + DBCFileLoader(); + ~DBCFileLoader(); + + bool Load(const char *filename, const char *fmt); + + class Record + { + public: + float getFloat(size_t field) const + { + assert(field < file.fieldCount); + float val = *reinterpret_cast(offset+file.GetOffset(field)); + EndianConvert(val); + return val; + } + uint32 getUInt(size_t field) const + { + assert(field < file.fieldCount); + uint32 val = *reinterpret_cast(offset+file.GetOffset(field)); + EndianConvert(val); + return val; + } + uint8 getUInt8(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast(offset+file.GetOffset(field)); + } + + const char *getString(size_t field) const + { + assert(field < file.fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file.stringSize); + return reinterpret_cast(file.stringTable + stringOffset); + } + + private: + Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) {} + unsigned char *offset; + DBCFileLoader &file; + + friend class DBCFileLoader; + + }; + + // Get record by id + Record getRecord(size_t id); + /// Get begin iterator over records + + uint32 GetNumRows() const { return recordCount; } + uint32 GetRowSize() const { return recordSize; } + uint32 GetCols() const { return fieldCount; } + uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; } + bool IsLoaded() { return data != NULL; } + char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable); + char* AutoProduceStrings(const char* fmt, char* dataTable); + static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL); + private: + + uint32 recordSize; + uint32 recordCount; + uint32 fieldCount; + uint32 stringSize; + uint32 *fieldsOffset; + unsigned char *data; + unsigned char *stringTable; +}; +#endif diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h new file mode 100644 index 00000000000..61e2f7a6d06 --- /dev/null +++ b/src/server/shared/DataStores/DBCStore.h @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DBCSTORE_H +#define DBCSTORE_H + +#include "DBCFileLoader.h" +#include "Log.h" + +struct SqlDbc +{ + const std::string * formatString; + const std::string * indexName; + std::string sqlTableName; + int32 indexPos; + int32 sqlIndexPos; + SqlDbc(const std::string * _filename, const std::string * _format, const std::string * _idname, const char * fmt) + :formatString(_format),sqlIndexPos(0), indexName (_idname) + { + // Convert dbc file name to sql table name + sqlTableName = *_filename; + for (uint32 i = 0; i< sqlTableName.size(); ++i) + { + if (isalpha(sqlTableName[i])) + sqlTableName[i] = tolower(sqlTableName[i]); + else if (sqlTableName[i] == '.') + sqlTableName[i] = '_'; + } + + // Get sql index position + DBCFileLoader::GetFormatRecordSize(fmt, &indexPos); + if (indexPos>=0) + { + for (int32 x=0; x < formatString->size(); x++) + { + // Count only fields present in sql + if ((*formatString)[x] == FT_SQL_PRESENT) + { + if (x == indexPos) + break; + ++sqlIndexPos; + } + } + } + } +}; + +template +class DBCStorage +{ + typedef std::list StringPoolList; + public: + explicit DBCStorage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { } + ~DBCStorage() { Clear(); } + + T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; } + uint32 GetNumRows() const { return nCount; } + char const* GetFormat() const { return fmt; } + uint32 GetFieldCount() const { return fieldCount; } + + bool Load(char const* fn, SqlDbc * sql) + { + DBCFileLoader dbc; + // Check if load was sucessful, only then continue + if (!dbc.Load(fn, fmt)) + return false; + + uint32 sqlRecordCount = 0; + uint32 sqlHighestIndex = 0; + Field *fields = NULL; + QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); + // Load data from sql + if (sql) + { + std::string query = "SELECT * FROM " + sql->sqlTableName; + if (sql->indexPos >= 0) + query +=" ORDER BY + " + *sql->indexName + " DESC"; + query += ";"; + + result = WorldDatabase.Query(query.c_str()); + if (result) + { + sqlRecordCount = result->GetRowCount(); + if (sql->indexPos >= 0) + { + fields = result->Fetch(); + sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32(); + } + // Check if sql index pos is valid + if (int32(result->GetFieldCount()-1) < sql->sqlIndexPos) + { + sLog.outError("Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str()); + return false; + } + } + } + char * sqlDataTable; + fieldCount = dbc.GetCols(); + m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable, sqlRecordCount, sqlHighestIndex, sqlDataTable); + + m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); + + // Insert sql data into arrays + if (result) + { + if (indexTable) + { + uint32 offset = 0; + uint32 rowIndex = dbc.GetNumRows(); + do + { + if (!fields) + fields = result->Fetch(); + + if(sql->indexPos >= 0) + { + uint32 id = fields[sql->sqlIndexPos].GetUInt32(); + if (indexTable[id]) + { + sLog.outError("Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str()); + return false; + } + indexTable[id]=(T*)&sqlDataTable[offset]; + } + else + indexTable[rowIndex]=(T*)&sqlDataTable[offset]; + uint32 columnNumber = 0; + uint32 sqlColumnNumber = 0; + + for (; columnNumber < sql->formatString->size(); ++columnNumber) + { + if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT) + { + switch(fmt[columnNumber]) + { + case FT_FLOAT: + *((float*)(&sqlDataTable[offset]))= 0.0f; + offset+=4; + break; + case FT_IND: + case FT_INT: + *((uint32*)(&sqlDataTable[offset]))=uint32(0); + offset+=4; + break; + case FT_BYTE: + *((uint8*)(&sqlDataTable[offset]))=uint8(0); + offset+=1; + break; + case FT_STRING: + // Beginning of the pool - empty string + *((char**)(&sqlDataTable[offset]))=m_stringPoolList.back(); + offset+=sizeof(char*); + break; + } + } + else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT) + { + bool validSqlColumn = true; + switch(fmt[columnNumber]) + { + case FT_FLOAT: + *((float*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetFloat(); + offset+=4; + break; + case FT_IND: + case FT_INT: + *((uint32*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt32(); + offset+=4; + break; + case FT_BYTE: + *((uint8*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt8(); + offset+=1; + break; + case FT_STRING: + sLog.outError("Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); + return false; + case FT_SORT: + break; + default: + validSqlColumn = false; + } + if (validSqlColumn && (columnNumber != (sql->formatString->size()-1))) + sqlColumnNumber++; + } + else + { + sLog.outError("Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); + return false; + } + } + if (sqlColumnNumber != (result->GetFieldCount()-1)) + { + sLog.outError("SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str()); + return false; + } + + fields = NULL; + ++rowIndex; + }while (result->NextRow()); + } + } + + // error in dbc file at loading if NULL + return indexTable!=NULL; + } + + bool LoadStringsFrom(char const* fn) + { + // DBC must be already loaded using Load + if(!indexTable) + return false; + + DBCFileLoader dbc; + // Check if load was successful, only then continue + if(!dbc.Load(fn, fmt)) + return false; + + m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); + + return true; + } + + void Clear() + { + if (!indexTable) + return; + + delete[] ((char*)indexTable); + indexTable = NULL; + delete[] ((char*)m_dataTable); + m_dataTable = NULL; + + while(!m_stringPoolList.empty()) + { + delete[] m_stringPoolList.front(); + m_stringPoolList.pop_front(); + } + nCount = 0; + } + + private: + char const* fmt; + uint32 nCount; + uint32 fieldCount; + T** indexTable; + T* m_dataTable; + StringPoolList m_stringPoolList; +}; + +#endif diff --git a/src/server/shared/Database/DBCFileLoader.cpp b/src/server/shared/Database/DBCFileLoader.cpp deleted file mode 100644 index bad87a36fce..00000000000 --- a/src/server/shared/Database/DBCFileLoader.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include "DBCFileLoader.h" - -DBCFileLoader::DBCFileLoader() -{ - data = NULL; - fieldsOffset = NULL; -} - -bool DBCFileLoader::Load(const char *filename, const char *fmt) -{ - uint32 header; - if (data) - { - delete [] data; - data = NULL; - } - - FILE * f = fopen(filename,"rb"); - if (!f) - return false; - - if (fread(&header,4,1,f)!=1) // Number of records - return false; - - EndianConvert(header); - - if (header!=0x43424457) - return false; //'WDBC' - - if (fread(&recordCount,4,1,f)!=1) // Number of records - return false; - - EndianConvert(recordCount); - - if (fread(&fieldCount,4,1,f)!=1) // Number of fields - return false; - - EndianConvert(fieldCount); - - if (fread(&recordSize,4,1,f)!=1) // Size of a record - return false; - - EndianConvert(recordSize); - - if (fread(&stringSize,4,1,f)!=1) // String size - return false; - - EndianConvert(stringSize); - - fieldsOffset = new uint32[fieldCount]; - fieldsOffset[0] = 0; - for (uint32 i = 1; i < fieldCount; i++) - { - fieldsOffset[i] = fieldsOffset[i - 1]; - if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields - fieldsOffset[i] += 1; - else // 4 byte fields (int32/float/strings) - fieldsOffset[i] += 4; - } - - data = new unsigned char[recordSize*recordCount+stringSize]; - stringTable = data + recordSize*recordCount; - - if (fread(data,recordSize*recordCount+stringSize,1,f)!=1) - return false; - - fclose(f); - - return true; -} - -DBCFileLoader::~DBCFileLoader() -{ - if (data) - delete [] data; - - if (fieldsOffset) - delete [] fieldsOffset; -} - -DBCFileLoader::Record DBCFileLoader::getRecord(size_t id) -{ - assert(data); - return Record(*this, data + id*recordSize); -} - -uint32 DBCFileLoader::GetFormatRecordSize(const char * format,int32* index_pos) -{ - uint32 recordsize = 0; - int32 i = -1; - for (uint32 x=0; format[x]; ++x) - { - switch(format[x]) - { - case FT_FLOAT: - case FT_INT: - recordsize+=4; - break; - case FT_STRING: - recordsize+=sizeof(char*); - break; - case FT_SORT: - i=x; - break; - case FT_IND: - i=x; - recordsize+=4; - break; - case FT_BYTE: - recordsize += 1; - break; - } - } - - if (index_pos) - *index_pos = i; - - return recordsize; -} - -char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable) -{ - /* - format STRING, NA, FLOAT,NA,INT <=> - struct{ - char* field0, - float field1, - int field2 - }entry; - - this func will generate entry[rows] data; - */ - - typedef char * ptr; - if (strlen(format)!=fieldCount) - return NULL; - - //get struct size and index pos - int32 i; - uint32 recordsize=GetFormatRecordSize(format,&i); - - if (i>=0) - { - uint32 maxi=0; - //find max index - for (uint32 y=0; ymaxi)maxi=ind; - } - - // If higher index avalible from sql - use it instead of dbcs - if (sqlHighestIndex > maxi) - maxi = sqlHighestIndex; - - ++maxi; - records=maxi; - indexTable=new ptr[maxi]; - memset(indexTable,0,maxi*sizeof(ptr)); - } - else - { - records = recordCount + sqlRecordCount; - indexTable = new ptr[recordCount+ sqlRecordCount]; - } - - char* dataTable= new char[(recordCount + sqlRecordCount)*recordsize]; - - uint32 offset=0; - - for (uint32 y =0; y=0) - indexTable[getRecord(y).getUInt(i)]=&dataTable[offset]; - else - indexTable[y]=&dataTable[offset]; - - for (uint32 x=0; x - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DBC_FILE_LOADER_H -#define DBC_FILE_LOADER_H -#include "Platform/Define.h" -#include "Utilities/ByteConverter.h" -#include - -enum -{ - FT_NA='x', //not used or unknown, 4 byte size - FT_NA_BYTE='X', //not used or unknown, byte - FT_STRING='s', //char* - FT_FLOAT='f', //float - FT_INT='i', //uint32 - FT_BYTE='b', //uint8 - FT_SORT='d', //sorted by this field, field is not included - FT_IND='n', //the same,but parsed to data - FT_LOGIC='l', //Logical (boolean) - FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc - FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc -}; - -class DBCFileLoader -{ - public: - DBCFileLoader(); - ~DBCFileLoader(); - - bool Load(const char *filename, const char *fmt); - - class Record - { - public: - float getFloat(size_t field) const - { - assert(field < file.fieldCount); - float val = *reinterpret_cast(offset+file.GetOffset(field)); - EndianConvert(val); - return val; - } - uint32 getUInt(size_t field) const - { - assert(field < file.fieldCount); - uint32 val = *reinterpret_cast(offset+file.GetOffset(field)); - EndianConvert(val); - return val; - } - uint8 getUInt8(size_t field) const - { - assert(field < file.fieldCount); - return *reinterpret_cast(offset+file.GetOffset(field)); - } - - const char *getString(size_t field) const - { - assert(field < file.fieldCount); - size_t stringOffset = getUInt(field); - assert(stringOffset < file.stringSize); - return reinterpret_cast(file.stringTable + stringOffset); - } - - private: - Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) {} - unsigned char *offset; - DBCFileLoader &file; - - friend class DBCFileLoader; - - }; - - // Get record by id - Record getRecord(size_t id); - /// Get begin iterator over records - - uint32 GetNumRows() const { return recordCount; } - uint32 GetRowSize() const { return recordSize; } - uint32 GetCols() const { return fieldCount; } - uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; } - bool IsLoaded() { return data != NULL; } - char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable); - char* AutoProduceStrings(const char* fmt, char* dataTable); - static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL); - private: - - uint32 recordSize; - uint32 recordCount; - uint32 fieldCount; - uint32 stringSize; - uint32 *fieldsOffset; - unsigned char *data; - unsigned char *stringTable; -}; -#endif diff --git a/src/server/shared/Database/DBCStore.h b/src/server/shared/Database/DBCStore.h deleted file mode 100644 index 61e2f7a6d06..00000000000 --- a/src/server/shared/Database/DBCStore.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DBCSTORE_H -#define DBCSTORE_H - -#include "DBCFileLoader.h" -#include "Log.h" - -struct SqlDbc -{ - const std::string * formatString; - const std::string * indexName; - std::string sqlTableName; - int32 indexPos; - int32 sqlIndexPos; - SqlDbc(const std::string * _filename, const std::string * _format, const std::string * _idname, const char * fmt) - :formatString(_format),sqlIndexPos(0), indexName (_idname) - { - // Convert dbc file name to sql table name - sqlTableName = *_filename; - for (uint32 i = 0; i< sqlTableName.size(); ++i) - { - if (isalpha(sqlTableName[i])) - sqlTableName[i] = tolower(sqlTableName[i]); - else if (sqlTableName[i] == '.') - sqlTableName[i] = '_'; - } - - // Get sql index position - DBCFileLoader::GetFormatRecordSize(fmt, &indexPos); - if (indexPos>=0) - { - for (int32 x=0; x < formatString->size(); x++) - { - // Count only fields present in sql - if ((*formatString)[x] == FT_SQL_PRESENT) - { - if (x == indexPos) - break; - ++sqlIndexPos; - } - } - } - } -}; - -template -class DBCStorage -{ - typedef std::list StringPoolList; - public: - explicit DBCStorage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { } - ~DBCStorage() { Clear(); } - - T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; } - uint32 GetNumRows() const { return nCount; } - char const* GetFormat() const { return fmt; } - uint32 GetFieldCount() const { return fieldCount; } - - bool Load(char const* fn, SqlDbc * sql) - { - DBCFileLoader dbc; - // Check if load was sucessful, only then continue - if (!dbc.Load(fn, fmt)) - return false; - - uint32 sqlRecordCount = 0; - uint32 sqlHighestIndex = 0; - Field *fields = NULL; - QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); - // Load data from sql - if (sql) - { - std::string query = "SELECT * FROM " + sql->sqlTableName; - if (sql->indexPos >= 0) - query +=" ORDER BY + " + *sql->indexName + " DESC"; - query += ";"; - - result = WorldDatabase.Query(query.c_str()); - if (result) - { - sqlRecordCount = result->GetRowCount(); - if (sql->indexPos >= 0) - { - fields = result->Fetch(); - sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32(); - } - // Check if sql index pos is valid - if (int32(result->GetFieldCount()-1) < sql->sqlIndexPos) - { - sLog.outError("Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str()); - return false; - } - } - } - char * sqlDataTable; - fieldCount = dbc.GetCols(); - m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable, sqlRecordCount, sqlHighestIndex, sqlDataTable); - - m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); - - // Insert sql data into arrays - if (result) - { - if (indexTable) - { - uint32 offset = 0; - uint32 rowIndex = dbc.GetNumRows(); - do - { - if (!fields) - fields = result->Fetch(); - - if(sql->indexPos >= 0) - { - uint32 id = fields[sql->sqlIndexPos].GetUInt32(); - if (indexTable[id]) - { - sLog.outError("Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str()); - return false; - } - indexTable[id]=(T*)&sqlDataTable[offset]; - } - else - indexTable[rowIndex]=(T*)&sqlDataTable[offset]; - uint32 columnNumber = 0; - uint32 sqlColumnNumber = 0; - - for (; columnNumber < sql->formatString->size(); ++columnNumber) - { - if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT) - { - switch(fmt[columnNumber]) - { - case FT_FLOAT: - *((float*)(&sqlDataTable[offset]))= 0.0f; - offset+=4; - break; - case FT_IND: - case FT_INT: - *((uint32*)(&sqlDataTable[offset]))=uint32(0); - offset+=4; - break; - case FT_BYTE: - *((uint8*)(&sqlDataTable[offset]))=uint8(0); - offset+=1; - break; - case FT_STRING: - // Beginning of the pool - empty string - *((char**)(&sqlDataTable[offset]))=m_stringPoolList.back(); - offset+=sizeof(char*); - break; - } - } - else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT) - { - bool validSqlColumn = true; - switch(fmt[columnNumber]) - { - case FT_FLOAT: - *((float*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetFloat(); - offset+=4; - break; - case FT_IND: - case FT_INT: - *((uint32*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt32(); - offset+=4; - break; - case FT_BYTE: - *((uint8*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt8(); - offset+=1; - break; - case FT_STRING: - sLog.outError("Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); - return false; - case FT_SORT: - break; - default: - validSqlColumn = false; - } - if (validSqlColumn && (columnNumber != (sql->formatString->size()-1))) - sqlColumnNumber++; - } - else - { - sLog.outError("Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); - return false; - } - } - if (sqlColumnNumber != (result->GetFieldCount()-1)) - { - sLog.outError("SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str()); - return false; - } - - fields = NULL; - ++rowIndex; - }while (result->NextRow()); - } - } - - // error in dbc file at loading if NULL - return indexTable!=NULL; - } - - bool LoadStringsFrom(char const* fn) - { - // DBC must be already loaded using Load - if(!indexTable) - return false; - - DBCFileLoader dbc; - // Check if load was successful, only then continue - if(!dbc.Load(fn, fmt)) - return false; - - m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable)); - - return true; - } - - void Clear() - { - if (!indexTable) - return; - - delete[] ((char*)indexTable); - indexTable = NULL; - delete[] ((char*)m_dataTable); - m_dataTable = NULL; - - while(!m_stringPoolList.empty()) - { - delete[] m_stringPoolList.front(); - m_stringPoolList.pop_front(); - } - nCount = 0; - } - - private: - char const* fmt; - uint32 nCount; - uint32 fieldCount; - T** indexTable; - T* m_dataTable; - StringPoolList m_stringPoolList; -}; - -#endif diff --git a/src/server/shared/Debugging/Errors.h b/src/server/shared/Debugging/Errors.h new file mode 100644 index 00000000000..15c6b1414ed --- /dev/null +++ b/src/server/shared/Debugging/Errors.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_ERRORS_H +#define TRINITYCORE_ERRORS_H + +#include "Common.h" + +#if PLATFORM != PLATFORM_WINDOWS +#ifndef HAVE_CONFIG_H +#include +#endif +#endif + +#ifdef HAVE_ACE_STACK_TRACE_H +#include "ace/Stack_Trace.h" +#endif + +#ifdef HAVE_ACE_STACK_TRACE_H // old versions ACE not have Stack_Trace.h but used at some oS for better compatibility +#define WPAssert( assertion ) { if (!(assertion)) { ACE_Stack_Trace st; fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__,__FUNCTION__, #assertion, st.c_str()); assert( #assertion &&0 ); } } +#else +#define WPAssert( assertion ) { if (!(assertion)) { fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED2:\n %s\n", __FILE__, __LINE__,__FUNCTION__, #assertion); assert( #assertion &&0 ); } } +#endif +#define WPError( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "%\n%s:%i in %s ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( false ); } +#define WPWarning( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s WARNING:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); } + +#define WPFatal( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s FATAL ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( #assertion &&0 ); abort(); } + +#define ASSERT WPAssert +#endif + diff --git a/src/server/shared/Debugging/MemoryLeaks.cpp b/src/server/shared/Debugging/MemoryLeaks.cpp new file mode 100644 index 00000000000..ef7e36c3b57 --- /dev/null +++ b/src/server/shared/Debugging/MemoryLeaks.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MemoryLeaks.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1( MemoryManager ) ; + +MemoryManager::MemoryManager( ) +{ + #if COMPILER == MICROSOFT + // standard leak check initialization + //_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + // uncomment to disable Visual Leak Detector from code + //VLDDisable(); + #endif +} diff --git a/src/server/shared/Debugging/MemoryLeaks.h b/src/server/shared/Debugging/MemoryLeaks.h new file mode 100644 index 00000000000..c8b8fb8e1b1 --- /dev/null +++ b/src/server/shared/Debugging/MemoryLeaks.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYSERVER_MEMORY_H +#define TRINITYSERVER_MEMORY_H + +#include "Platform/CompilerDefs.h" + +#if COMPILER == COMPILER_MICROSOFT + +#ifndef _WIN64 +// Visual Leak Detector support enabled +//#include +// standard Visual Studio leak check disabled, +//# define _CRTDBG_MAP_ALLOC +//# include +//# include +#else +//# define _CRTDBG_MAP_ALLOC +//# include +//# include +#endif + +#endif + + +#include "Policies/Singleton.h" + +struct MemoryManager : public Trinity::Singleton < MemoryManager > +{ + MemoryManager(); +}; +#endif diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp new file mode 100644 index 00000000000..8fb5d5e2d2a --- /dev/null +++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp @@ -0,0 +1,1013 @@ +//========================================== +// Matt Pietrek +// MSDN Magazine, 2002 +// FILE: WheatyExceptionReport.CPP +//========================================== +#define WIN32_LEAN_AND_MEAN +#pragma warning(disable:4996) +#pragma warning(disable:4312) +#pragma warning(disable:4311) +#include +#include +#include +#include +#define _NO_CVCONST_H +#include +#include "WheatyExceptionReport.h" +#include "SystemConfig.h" +#include "revision.h" +#define CrashFolder _T("Crashes") +//#pragma comment(linker, "/defaultlib:dbghelp.lib") + +inline LPTSTR ErrorMessage(DWORD dw) +{ + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL); + return (LPTSTR)lpMsgBuf; +} + +//============================== Global Variables ============================= + +// +// Declare the static variables of the WheatyExceptionReport class +// +TCHAR WheatyExceptionReport::m_szLogFileName[MAX_PATH]; +LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter; +HANDLE WheatyExceptionReport::m_hReportFile; +HANDLE WheatyExceptionReport::m_hProcess; + +// Declare global instance of class +WheatyExceptionReport g_WheatyExceptionReport; + +//============================== Class Methods ============================= + +WheatyExceptionReport::WheatyExceptionReport() // Constructor +{ + // Install the unhandled exception filter function + m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); + m_hProcess = GetCurrentProcess(); +} + +//============ +// Destructor +//============ +WheatyExceptionReport::~WheatyExceptionReport() +{ + if (m_previousFilter) + SetUnhandledExceptionFilter(m_previousFilter); +} + +//=========================================================== +// Entry point where control comes on an unhandled exception +//=========================================================== +LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( +PEXCEPTION_POINTERS pExceptionInfo) +{ + TCHAR module_folder_name[MAX_PATH]; + GetModuleFileName(0, module_folder_name, MAX_PATH); + TCHAR* pos = _tcsrchr(module_folder_name, '\\'); + if (!pos) + return 0; + pos[0] = '\0'; + ++pos; + + TCHAR crash_folder_path[MAX_PATH]; + sprintf(crash_folder_path, "%s\\%s", module_folder_name, CrashFolder); + if (!CreateDirectory(crash_folder_path, NULL)) + { + if (GetLastError() != ERROR_ALREADY_EXISTS) + return 0; + } + + SYSTEMTIME systime; + GetLocalTime(&systime); + sprintf(m_szLogFileName, "%s\\%s_[%u-%u_%u-%u-%u].txt", + crash_folder_path, pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); + + m_hReportFile = CreateFile(m_szLogFileName, + GENERIC_WRITE, + 0, + 0, + OPEN_ALWAYS, + FILE_FLAG_WRITE_THROUGH, + 0); + + if (m_hReportFile) + { + SetFilePointer(m_hReportFile, 0, 0, FILE_END); + + GenerateExceptionReport(pExceptionInfo); + + CloseHandle(m_hReportFile); + m_hReportFile = 0; + } + + if (m_previousFilter) + return m_previousFilter(pExceptionInfo); + else + return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/; +} + +BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount) +{ + if (!sProcessorName) + return FALSE; + + HKEY hKey; + LONG lRet; + lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), + 0, KEY_QUERY_VALUE, &hKey); + if (lRet != ERROR_SUCCESS) + return FALSE; + TCHAR szTmp[2048]; + DWORD cntBytes = sizeof(szTmp); + lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL, + (LPBYTE)szTmp, &cntBytes); + if (lRet != ERROR_SUCCESS) + return FALSE; + ::RegCloseKey(hKey); + sProcessorName[0] = '\0'; + // Skip spaces + TCHAR* psz = szTmp; + while (iswspace(*psz)) + ++psz; + _tcsncpy(sProcessorName, psz, maxcount); + return TRUE; +} + +BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax) +{ + // Try calling GetVersionEx using the OSVERSIONINFOEX structure. + // If that fails, try using the OSVERSIONINFO structure. + OSVERSIONINFOEX osvi = { 0 }; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + BOOL bOsVersionInfoEx; + bOsVersionInfoEx = ::GetVersionEx((LPOSVERSIONINFO)(&osvi)); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!::GetVersionEx((OSVERSIONINFO*)&osvi)) + return FALSE; + } + *szVersion = _T('\0'); + TCHAR wszTmp[128]; + switch (osvi.dwPlatformId) + { + // Windows NT product family. + case VER_PLATFORM_WIN32_NT: + // Test for the specific product family. + if (osvi.dwMajorVersion == 6) + _tcsncat(szVersion, _T("Windows Vista or Windows Server 2008 "), cntMax); + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + _tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax); + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + _tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax); + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + _tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax); + if (osvi.dwMajorVersion <= 4) + _tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax); + + // Test for specific product on Windows NT 4.0 SP6 and later. + if (bOsVersionInfoEx) + { + // Test for the workstation type. + #if WINVER < 0x0500 + if (osvi.wReserved[1] == VER_NT_WORKSTATION) + #else + if (osvi.wProductType == VER_NT_WORKSTATION) + #endif // WINVER < 0x0500 + { + if (osvi.dwMajorVersion == 4) + _tcsncat(szVersion, _T("Workstation 4.0 "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] & VER_SUITE_PERSONAL) + #else + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Home Edition "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] & VER_SUITE_EMBEDDEDNT) + #else + else if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Embedded "), cntMax); + else + _tcsncat(szVersion, _T("Professional "), cntMax); + } + // Test for the server type. + #if WINVER < 0x0500 + else if (osvi.wReserved[1] == VER_NT_SERVER) + #else + else if (osvi.wProductType == VER_NT_SERVER) + #endif // WINVER < 0x0500 + { + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + #if WINVER < 0x0500 + if (osvi.wReserved[0] & VER_SUITE_DATACENTER) + #else + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Datacenter Edition "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) + #else + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Enterprise Edition "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] == VER_SUITE_BLADE) + #else + else if (osvi.wSuiteMask == VER_SUITE_BLADE) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Web Edition "), cntMax); + else + _tcsncat(szVersion, _T("Standard Edition "), cntMax); + } + else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + #if WINVER < 0x0500 + if (osvi.wReserved[0] & VER_SUITE_DATACENTER) + #else + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Datacenter Server "), cntMax); + #if WINVER < 0x0500 + else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) + #else + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Advanced Server "), cntMax); + else + _tcsncat(szVersion, _T("Server "), cntMax); + } + else // Windows NT 4.0 + { + #if WINVER < 0x0500 + if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) + #else + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + #endif // WINVER < 0x0500 + _tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax); + else + _tcsncat(szVersion, _T("Server 4.0 "), cntMax); + } + } + } + // Display service pack (if any) and build number. + if (osvi.dwMajorVersion == 4 && _tcsicmp(osvi.szCSDVersion, _T("Service Pack 6")) == 0) + { + HKEY hKey; + LONG lRet; + + // Test for SP6 versus SP6a. + lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey); + if (lRet == ERROR_SUCCESS) + { + _stprintf(wszTmp, _T("Service Pack 6a (Version %d.%d, Build %d)"), + osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + _tcsncat(szVersion, wszTmp, cntMax); + } + else // Windows NT 4.0 prior to SP6a + { + _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), + osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + _tcsncat(szVersion, wszTmp, cntMax); + } + ::RegCloseKey(hKey); + } + else // Windows NT 3.51 and earlier or Windows 2000 and later + { + if (!_tcslen(osvi.szCSDVersion)) + _stprintf(wszTmp, _T("(Version %d.%d, Build %d)"), + osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + else + _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), + osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + _tcsncat(szVersion, wszTmp, cntMax); + } + break; + default: + _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), + osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); + _tcsncat(szVersion, wszTmp, cntMax); + break; + } + + return TRUE; +} + +void WheatyExceptionReport::PrintSystemInfo() +{ + SYSTEM_INFO SystemInfo; + ::GetSystemInfo(&SystemInfo); + + MEMORYSTATUS MemoryStatus; + MemoryStatus.dwLength = sizeof (MEMORYSTATUS); + ::GlobalMemoryStatus(&MemoryStatus); + TCHAR sString[1024]; + _tprintf(_T("//=====================================================\r\n")); + if (_GetProcessorName(sString, countof(sString))) + _tprintf(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), + sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); + else + _tprintf(_T("*** Hardware ***\r\nProcessor: \r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), + SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); + + if (_GetWindowsVersion(sString, countof(sString))) + _tprintf(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString); + else + _tprintf(_T("\r\n*** Operation System:\r\n\r\n")); +} + +//=========================================================================== +void WheatyExceptionReport::printTracesForAllThreads() +{ + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + + DWORD dwOwnerPID = GetCurrentProcessId(); + m_hProcess = GetCurrentProcess(); + // Take a snapshot of all running threads + hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) + return; + + // Fill in the size of the structure before using it. + te32.dwSize = sizeof(THREADENTRY32); + + // Retrieve information about the first thread, + // and exit if unsuccessful + if (!Thread32First(hThreadSnap, &te32)) + { + CloseHandle(hThreadSnap); // Must clean up the + // snapshot object! + return; + } + + // Now walk the thread list of the system, + // and display information about each thread + // associated with the specified process + do + { + if (te32.th32OwnerProcessID == dwOwnerPID) + { + CONTEXT context; + context.ContextFlags = 0xffffffff; + HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,false, te32.th32ThreadID); + if (threadHandle && GetThreadContext(threadHandle, &context)) + { + WriteStackDetails(&context, false, threadHandle); + } + CloseHandle(threadHandle); + } + } while(Thread32Next(hThreadSnap, &te32)); + +// Don't forget to clean up the snapshot object. + CloseHandle(hThreadSnap); +} + +//=========================================================================== +// Open the report file, and write the desired information to it. Called by +// WheatyUnhandledExceptionFilter +//=========================================================================== +void WheatyExceptionReport::GenerateExceptionReport( +PEXCEPTION_POINTERS pExceptionInfo) +{ + SYSTEMTIME systime; + GetLocalTime(&systime); + + // Start out with a banner + _tprintf(_T("Revision: %s\r\n"), _FULLVERSION); + _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute); + PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; + + PrintSystemInfo(); + // First print information about the type of fault + _tprintf(_T("\r\n//=====================================================\r\n")); + _tprintf(_T("Exception code: %08X %s\r\n"), + pExceptionRecord->ExceptionCode, + GetExceptionString(pExceptionRecord->ExceptionCode)); + + // Now print information about where the fault occured + TCHAR szFaultingModule[MAX_PATH]; + DWORD section; + DWORD_PTR offset; + GetLogicalAddress(pExceptionRecord->ExceptionAddress, + szFaultingModule, + sizeof(szFaultingModule), + section, offset); + +#ifdef _M_IX86 + _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"), + pExceptionRecord->ExceptionAddress, + section, offset, szFaultingModule); +#endif +#ifdef _M_X64 + _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"), + pExceptionRecord->ExceptionAddress, + section, offset, szFaultingModule); +#endif + + PCONTEXT pCtx = pExceptionInfo->ContextRecord; + + // Show the registers + #ifdef _M_IX86 // X86 Only! + _tprintf(_T("\r\nRegisters:\r\n")); + + _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n") + ,pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, + pCtx->Esi, pCtx->Edi); + + _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip); + _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"), + pCtx->SegSs, pCtx->Esp, pCtx->Ebp); + _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), + pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); + _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); + #endif + + #ifdef _M_X64 + _tprintf(_T("\r\nRegisters:\r\n")); + _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n") + _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n") + ,pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, + pCtx->Rsi, pCtx->Rdi ,pCtx->R9,pCtx->R10,pCtx->R11,pCtx->R12,pCtx->R13,pCtx->R14,pCtx->R15); + _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip); + _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"), + pCtx->SegSs, pCtx->Rsp, pCtx->Rbp); + _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), + pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); + _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); + #endif + + SymSetOptions(SYMOPT_DEFERRED_LOADS); + + // Initialize DbgHelp + if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) + { + _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"), + ErrorMessage(GetLastError())); + } + + CONTEXT trashableContext = *pCtx; + + WriteStackDetails(&trashableContext, false, NULL); + printTracesForAllThreads(); + +// #ifdef _M_IX86 // X86 Only! + + _tprintf(_T("========================\r\n")); + _tprintf(_T("Local Variables And Parameters\r\n")); + + trashableContext = *pCtx; + WriteStackDetails(&trashableContext, true, NULL); + + _tprintf(_T("========================\r\n")); + _tprintf(_T("Global Variables\r\n")); + + SymEnumSymbols(GetCurrentProcess(), + (DWORD64)GetModuleHandle(szFaultingModule), + 0, EnumerateSymbolsCallback, 0); + // #endif // X86 Only! + + SymCleanup(GetCurrentProcess()); + + _tprintf(_T("\r\n")); +} + +//====================================================================== +// Given an exception code, returns a pointer to a static string with a +// description of the exception +//====================================================================== +LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode) +{ + #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x); + + switch (dwCode) + { + EXCEPTION(ACCESS_VIOLATION) + EXCEPTION(DATATYPE_MISALIGNMENT) + EXCEPTION(BREAKPOINT) + EXCEPTION(SINGLE_STEP) + EXCEPTION(ARRAY_BOUNDS_EXCEEDED) + EXCEPTION(FLT_DENORMAL_OPERAND) + EXCEPTION(FLT_DIVIDE_BY_ZERO) + EXCEPTION(FLT_INEXACT_RESULT) + EXCEPTION(FLT_INVALID_OPERATION) + EXCEPTION(FLT_OVERFLOW) + EXCEPTION(FLT_STACK_CHECK) + EXCEPTION(FLT_UNDERFLOW) + EXCEPTION(INT_DIVIDE_BY_ZERO) + EXCEPTION(INT_OVERFLOW) + EXCEPTION(PRIV_INSTRUCTION) + EXCEPTION(IN_PAGE_ERROR) + EXCEPTION(ILLEGAL_INSTRUCTION) + EXCEPTION(NONCONTINUABLE_EXCEPTION) + EXCEPTION(STACK_OVERFLOW) + EXCEPTION(INVALID_DISPOSITION) + EXCEPTION(GUARD_PAGE) + EXCEPTION(INVALID_HANDLE) + } + + // If not one of the "known" exceptions, try to get the string + // from NTDLL.DLL's message table. + + static TCHAR szBuffer[512] = { 0 }; + + FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, + GetModuleHandle(_T("NTDLL.DLL")), + dwCode, 0, szBuffer, sizeof(szBuffer), 0); + + return szBuffer; +} + +//============================================================================= +// Given a linear address, locates the module, section, and offset containing +// that address. +// +// Note: the szModule paramater buffer is an output buffer of length specified +// by the len parameter (in characters!) +//============================================================================= +BOOL WheatyExceptionReport::GetLogicalAddress( +PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset) +{ + MEMORY_BASIC_INFORMATION mbi; + + if (!VirtualQuery(addr, &mbi, sizeof(mbi))) + return FALSE; + + DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase; + + if (!GetModuleFileName((HMODULE)hMod, szModule, len)) + return FALSE; + + // Point to the DOS header in memory + PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; + + // From the DOS header, find the NT (PE) header + PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + DWORD_PTR(pDosHdr->e_lfanew)); + + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr); + + DWORD_PTR rva = (DWORD_PTR)addr - hMod; // RVA is offset from module load address + + // Iterate through the section table, looking for the one that encompasses + // the linear address. + for (unsigned i = 0; + i < pNtHdr->FileHeader.NumberOfSections; + i++, pSection++) + { + DWORD_PTR sectionStart = pSection->VirtualAddress; + DWORD_PTR sectionEnd = sectionStart + + DWORD_PTR(max(pSection->SizeOfRawData, pSection->Misc.VirtualSize)); + + // Is the address in this section??? + if ((rva >= sectionStart) && (rva <= sectionEnd)) + { + // Yes, address is in the section. Calculate section and offset, + // and store in the "section" & "offset" params, which were + // passed by reference. + section = i+1; + offset = rva - sectionStart; + return TRUE; + } + } + + return FALSE; // Should never get here! +} + +// It contains SYMBOL_INFO structure plus additional +// space for the name of the symbol +struct CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE +{ + CSymbolInfoPackage() + { + si.SizeOfStruct = sizeof(SYMBOL_INFO); + si.MaxNameLen = sizeof(name); + } +}; + +//============================================================ +// Walks the stack, and writes the results to the report file +//============================================================ +void WheatyExceptionReport::WriteStackDetails( +PCONTEXT pContext, +bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output +{ + _tprintf(_T("\r\nCall stack:\r\n")); + + _tprintf(_T("Address Frame Function SourceFile\r\n")); + + DWORD dwMachineType = 0; + // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag + + STACKFRAME64 sf; + memset(&sf, 0, sizeof(sf)); + + #ifdef _M_IX86 + // Initialize the STACKFRAME structure for the first call. This is only + // necessary for Intel CPUs, and isn't mentioned in the documentation. + sf.AddrPC.Offset = pContext->Eip; + sf.AddrPC.Mode = AddrModeFlat; + sf.AddrStack.Offset = pContext->Esp; + sf.AddrStack.Mode = AddrModeFlat; + sf.AddrFrame.Offset = pContext->Ebp; + sf.AddrFrame.Mode = AddrModeFlat; + + dwMachineType = IMAGE_FILE_MACHINE_I386; + #endif + +#ifdef _M_X64 + sf.AddrPC.Offset = pContext->Rip; + sf.AddrPC.Mode = AddrModeFlat; + sf.AddrStack.Offset = pContext->Rsp; + sf.AddrStack.Mode = AddrModeFlat; + sf.AddrFrame.Offset = pContext->Rbp; + sf.AddrFrame.Mode = AddrModeFlat; + dwMachineType = IMAGE_FILE_MACHINE_AMD64; +#endif + + while (1) + { + // Get the next stack frame + if (! StackWalk64(dwMachineType, + m_hProcess, + pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(), + &sf, + pContext, + 0, + SymFunctionTableAccess64, + SymGetModuleBase64, + 0)) + break; + if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure + break; // the frame is OK. Bail if not. +#ifdef _M_IX86 + _tprintf(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); +#endif +#ifdef _M_X64 + _tprintf(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); +#endif + + DWORD64 symDisplacement = 0; // Displacement of the input address, + // relative to the start of the symbol + + // Get the name of the function for this stack frame entry + CSymbolInfoPackage sip; + if (SymFromAddr( + m_hProcess, // Process handle of the current process + sf.AddrPC.Offset, // Symbol address + &symDisplacement, // Address of the variable that will receive the displacement + &sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object) + { + _tprintf(_T("%hs+%I64X"), sip.si.Name, symDisplacement); + + } + else // No symbol found. Print out the logical address instead. + { + TCHAR szModule[MAX_PATH] = _T(""); + DWORD section = 0; + DWORD_PTR offset = 0; + + GetLogicalAddress((PVOID)sf.AddrPC.Offset, + szModule, sizeof(szModule), section, offset); +#ifdef _M_IX86 + _tprintf(_T("%04X:%08X %s"), section, offset, szModule); +#endif +#ifdef _M_X64 + _tprintf(_T("%04X:%016I64X %s"), section, offset, szModule); +#endif + } + + // Get the source line for this stack frame entry + IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE) }; + DWORD dwLineDisplacement; + if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, + &dwLineDisplacement, &lineInfo)) + { + _tprintf(_T(" %s line %u"),lineInfo.FileName,lineInfo.LineNumber); + } + + _tprintf(_T("\r\n")); + + // Write out the variables, if desired + if (bWriteVariables) + { + // Use SymSetContext to get just the locals/params for this frame + IMAGEHLP_STACK_FRAME imagehlpStackFrame; + imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; + SymSetContext(m_hProcess, &imagehlpStackFrame, 0); + + // Enumerate the locals/parameters + SymEnumSymbols(m_hProcess, 0, 0, EnumerateSymbolsCallback, &sf); + + _tprintf(_T("\r\n")); + } + } + +} + +////////////////////////////////////////////////////////////////////////////// +// The function invoked by SymEnumSymbols +////////////////////////////////////////////////////////////////////////////// + +BOOL CALLBACK +WheatyExceptionReport::EnumerateSymbolsCallback( +PSYMBOL_INFO pSymInfo, +ULONG SymbolSize, +PVOID UserContext) +{ + + char szBuffer[2048]; + + __try + { + if (FormatSymbolValue(pSymInfo, (STACKFRAME*)UserContext, + szBuffer, sizeof(szBuffer))) + _tprintf(_T("\t%s\r\n"), szBuffer); + } + __except(1) + { + _tprintf(_T("punting on symbol %s\r\n"), pSymInfo->Name); + } + + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// +// Given a SYMBOL_INFO representing a particular variable, displays its +// contents. If it's a user defined type, display the members and their +// values. +////////////////////////////////////////////////////////////////////////////// +bool WheatyExceptionReport::FormatSymbolValue( +PSYMBOL_INFO pSym, +STACKFRAME * sf, +char * pszBuffer, +unsigned cbBuffer) +{ + char * pszCurrBuffer = pszBuffer; + + // Indicate if the variable is a local or parameter + if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) + pszCurrBuffer += sprintf(pszCurrBuffer, "Parameter "); + else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) + pszCurrBuffer += sprintf(pszCurrBuffer, "Local "); + + // If it's a function, don't do anything. + if (pSym->Tag == 5) // SymTagFunction from CVCONST.H from the DIA SDK + return false; + + DWORD_PTR pVariable = 0; // Will point to the variable's data in memory + + if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) + { + // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) + { // This may change!!! + pVariable = sf->AddrFrame.Offset; + pVariable += (DWORD_PTR)pSym->Address; + } + // else + // return false; + } + else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) + { + return false; // Don't try to report register variable + } + else + { + pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable + } + + // Determine if the variable is a user defined type (UDT). IF so, bHandled + // will return true. + bool bHandled; + pszCurrBuffer = DumpTypeIndex(pszCurrBuffer,pSym->ModBase, pSym->TypeIndex, + 0, pVariable, bHandled, pSym->Name); + + if (!bHandled) + { + // The symbol wasn't a UDT, so do basic, stupid formatting of the + // variable. Based on the size, we're assuming it's a char, WORD, or + // DWORD. + BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase); + pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); + + // Emit the variable name + pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", pSym->Name); + + pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, pSym->Size, + (PVOID)pVariable); + } + + return true; +} + +////////////////////////////////////////////////////////////////////////////// +// If it's a user defined type (UDT), recurse through its members until we're +// at fundamental types. When he hit fundamental types, return +// bHandled = false, so that FormatSymbolValue() will format them. +////////////////////////////////////////////////////////////////////////////// +char * WheatyExceptionReport::DumpTypeIndex( +char * pszCurrBuffer, +DWORD64 modBase, +DWORD dwTypeIndex, +unsigned nestingLevel, +DWORD_PTR offset, +bool & bHandled, +char* Name) +{ + bHandled = false; + + // Get the name of the symbol. This will either be a Type name (if a UDT), + // or the structure member name. + WCHAR * pwszTypeName; + if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME, + &pwszTypeName)) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " %ls", pwszTypeName); + LocalFree(pwszTypeName); + } + + // Determine how many children this type has. + DWORD dwChildrenCount = 0; + SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, + &dwChildrenCount); + + if (!dwChildrenCount) // If no children, we're done + return pszCurrBuffer; + + // Prepare to get an array of "TypeIds", representing each of the children. + // SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a + // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this. + struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS + { + ULONG MoreChildIds[1024]; + FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);} + } children; + + children.Count = dwChildrenCount; + children.Start= 0; + + // Get the array of TypeIds, one for each child type + if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN, + &children)) + { + return pszCurrBuffer; + } + + // Append a line feed + pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n"); + + // Iterate through each of the children + for (unsigned i = 0; i < dwChildrenCount; i++) + { + // Add appropriate indentation level (since this routine is recursive) + for (unsigned j = 0; j <= nestingLevel+1; j++) + pszCurrBuffer += sprintf(pszCurrBuffer, "\t"); + + // Recurse for each of the child types + bool bHandled2; + BasicType basicType = GetBasicType(children.ChildId[i], modBase); + pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); + + pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, + children.ChildId[i], nestingLevel+1, + offset, bHandled2, ""/*Name */); + + // If the child wasn't a UDT, format it appropriately + if (!bHandled2) + { + // Get the offset of the child member, relative to its parent + DWORD dwMemberOffset; + SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], + TI_GET_OFFSET, &dwMemberOffset); + + // Get the real "TypeId" of the child. We need this for the + // SymGetTypeInfo(TI_GET_TYPEID) call below. + DWORD typeId; + SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], + TI_GET_TYPEID, &typeId); + + // Get the size of the child member + ULONG64 length; + SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_LENGTH,&length); + + // Calculate the address of the member + DWORD_PTR dwFinalOffset = offset + dwMemberOffset; + + // BasicType basicType = GetBasicType(children.ChildId[i], modBase); + // + // pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); + // + // Emit the variable name + // pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", Name); + + pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, + length, (PVOID)dwFinalOffset); + + pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n"); + } + } + + bHandled = true; + return pszCurrBuffer; +} + +char * WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer, +BasicType basicType, +DWORD64 length, +PVOID pAddress) +{ + // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!) + if (length == 1) + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PBYTE)pAddress); + else if (length == 2) + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PWORD)pAddress); + else if (length == 4) + { + if (basicType == btFloat) + { + pszCurrBuffer += sprintf(pszCurrBuffer," = %f", *(PFLOAT)pAddress); + } + else if (basicType == btChar) + { + if (!IsBadStringPtr(*(PSTR*)pAddress, 32)) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " = \"%.31s\"", + *(PDWORD)pAddress); + } + else + pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", + *(PDWORD)pAddress); + } + else + pszCurrBuffer += sprintf(pszCurrBuffer," = %X", *(PDWORD)pAddress); + } + else if (length == 8) + { + if (basicType == btFloat) + { + pszCurrBuffer += sprintf(pszCurrBuffer, " = %lf", + *(double *)pAddress); + } + else + pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X", + *(DWORD64*)pAddress); + } + + return pszCurrBuffer; +} + +BasicType +WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase) +{ + BasicType basicType; + if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, + TI_GET_BASETYPE, &basicType)) + { + return basicType; + } + + // Get the real "TypeId" of the child. We need this for the + // SymGetTypeInfo(TI_GET_TYPEID) call below. + DWORD typeId; + if (SymGetTypeInfo(m_hProcess,modBase, typeIndex, TI_GET_TYPEID, &typeId)) + { + if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE, + &basicType)) + { + return basicType; + } + } + + return btNoType; +} + +//============================================================================ +// Helper function that writes to the report file, and allows the user to use +// printf style formating +//============================================================================ +int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...) +{ + TCHAR szBuff[1024]; + int retValue; + DWORD cbWritten; + va_list argptr; + + va_start(argptr, format); + retValue = vsprintf(szBuff, format, argptr); + va_end(argptr); + + WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0); + + return retValue; +} + diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h new file mode 100644 index 00000000000..33fb4bc5b0e --- /dev/null +++ b/src/server/shared/Debugging/WheatyExceptionReport.h @@ -0,0 +1,118 @@ +#ifndef _WHEATYEXCEPTIONREPORT_ +#define _WHEATYEXCEPTIONREPORT_ + +#include + +#if _MSC_VER < 1400 +# define countof(array) (sizeof(array) / sizeof(array[0])) +#else +# include +# define countof _countof +#endif // _MSC_VER < 1400 + +enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK +{ + btNoType = 0, + btVoid = 1, + btChar = 2, + btWChar = 3, + btInt = 6, + btUInt = 7, + btFloat = 8, + btBCD = 9, + btBool = 10, + btLong = 13, + btULong = 14, + btCurrency = 25, + btDate = 26, + btVariant = 27, + btComplex = 28, + btBit = 29, + btBSTR = 30, + btHresult = 31 +}; + +const char* const rgBaseType[] = +{ + " ", // btNoType = 0, + " void ", // btVoid = 1, + " char* ", // btChar = 2, + " wchar_t* ", // btWChar = 3, + " signed char ", + " unsigned char ", + " int ", // btInt = 6, + " unsigned int ", // btUInt = 7, + " float ", // btFloat = 8, + " ", // btBCD = 9, + " bool ", // btBool = 10, + " short ", + " unsigned short ", + " long ", // btLong = 13, + " unsigned long ", // btULong = 14, + " __int8 ", + " __int16 ", + " __int32 ", + " __int64 ", + " __int128 ", + " unsigned __int8 ", + " unsigned __int16 ", + " unsigned __int32 ", + " unsigned __int64 ", + " unsigned __int128 ", + " ", // btCurrency = 25, + " ", // btDate = 26, + " VARIANT ", // btVariant = 27, + " ", // btComplex = 28, + " ", // btBit = 29, + " BSTR ", // btBSTR = 30, + " HRESULT " // btHresult = 31 +}; + +class WheatyExceptionReport +{ + public: + + WheatyExceptionReport(); + ~WheatyExceptionReport(); + + // entry point where control comes on an unhandled exception + static LONG WINAPI WheatyUnhandledExceptionFilter( + PEXCEPTION_POINTERS pExceptionInfo); + + static void printTracesForAllThreads(); + private: + // where report info is extracted and generated + static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo); + static void PrintSystemInfo(); + static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax); + static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount); + + // Helper functions + static LPTSTR GetExceptionString(DWORD dwCode); + static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len, + DWORD& section, DWORD_PTR& offset); + + static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle); + + static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO,ULONG, PVOID); + + static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer); + + static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool & , char*); + + static char * FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress); + + static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase); + + static int __cdecl _tprintf(const TCHAR * format, ...); + + // Variables used by the class + static TCHAR m_szLogFileName[MAX_PATH]; + static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; + static HANDLE m_hReportFile; + static HANDLE m_hProcess; +}; + +extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class +#endif //WheatyExceptionReport + diff --git a/src/server/shared/DelayExecutor.cpp b/src/server/shared/DelayExecutor.cpp deleted file mode 100644 index 9a718823232..00000000000 --- a/src/server/shared/DelayExecutor.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include -#include - -#include "DelayExecutor.h" - -DelayExecutor* DelayExecutor::instance() -{ - return ACE_Singleton::instance(); -} - -DelayExecutor::DelayExecutor() - : activated_(false), pre_svc_hook_(0), post_svc_hook_(0) -{ -} - -DelayExecutor::~DelayExecutor() -{ - if (pre_svc_hook_) - delete pre_svc_hook_; - - if (post_svc_hook_) - delete post_svc_hook_; - - deactivate(); -} - -int DelayExecutor::deactivate() -{ - if (!activated()) - return -1; - - activated(false); - queue_.queue()->deactivate(); - wait(); - - return 0; -} - -int DelayExecutor::svc() -{ - if (pre_svc_hook_) - pre_svc_hook_->call(); - - for (;;) - { - ACE_Method_Request* rq = queue_.dequeue(); - - if (!rq) - break; - - rq->call(); - delete rq; - } - - if (post_svc_hook_) - post_svc_hook_->call(); - - return 0; -} - -int DelayExecutor::activate(int num_threads, ACE_Method_Request* pre_svc_hook, ACE_Method_Request* post_svc_hook) -{ - if (activated()) - return -1; - - if (num_threads < 1) - return -1; - - if (pre_svc_hook_) - delete pre_svc_hook_; - - if (post_svc_hook_) - delete post_svc_hook_; - - pre_svc_hook_ = pre_svc_hook; - post_svc_hook_ = post_svc_hook; - - queue_.queue()->activate(); - - if (ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, num_threads) == -1) - return -1; - - activated(true); - - return true; -} - -int DelayExecutor::execute(ACE_Method_Request* new_req) -{ - if (new_req == NULL) - return -1; - - if (queue_.enqueue(new_req, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) - { - delete new_req; - ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%t) %p\n"), ACE_TEXT("DelayExecutor::execute enqueue")), -1); - } - - return 0; -} - -bool DelayExecutor::activated() -{ - return activated_; -} - -void DelayExecutor::activated(bool s) -{ - activated_ = s; -} diff --git a/src/server/shared/DelayExecutor.h b/src/server/shared/DelayExecutor.h deleted file mode 100644 index 664d8ca78a2..00000000000 --- a/src/server/shared/DelayExecutor.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _M_DELAY_EXECUTOR_H -#define _M_DELAY_EXECUTOR_H - -#include -#include -#include - -class DelayExecutor : protected ACE_Task_Base -{ - public: - - DelayExecutor(); - virtual ~DelayExecutor(); - - static DelayExecutor* instance(); - - int execute(ACE_Method_Request* new_req); - - int activate(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL); - - int deactivate(); - - bool activated(); - - virtual int svc(); - - private: - - ACE_Activation_Queue queue_; - ACE_Method_Request* pre_svc_hook_; - ACE_Method_Request* post_svc_hook_; - bool activated_; - - void activated(bool s); -}; - -#endif // _M_DELAY_EXECUTOR_H diff --git a/src/server/shared/Errors.h b/src/server/shared/Errors.h deleted file mode 100644 index 15c6b1414ed..00000000000 --- a/src/server/shared/Errors.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_ERRORS_H -#define TRINITYCORE_ERRORS_H - -#include "Common.h" - -#if PLATFORM != PLATFORM_WINDOWS -#ifndef HAVE_CONFIG_H -#include -#endif -#endif - -#ifdef HAVE_ACE_STACK_TRACE_H -#include "ace/Stack_Trace.h" -#endif - -#ifdef HAVE_ACE_STACK_TRACE_H // old versions ACE not have Stack_Trace.h but used at some oS for better compatibility -#define WPAssert( assertion ) { if (!(assertion)) { ACE_Stack_Trace st; fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__,__FUNCTION__, #assertion, st.c_str()); assert( #assertion &&0 ); } } -#else -#define WPAssert( assertion ) { if (!(assertion)) { fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED2:\n %s\n", __FILE__, __LINE__,__FUNCTION__, #assertion); assert( #assertion &&0 ); } } -#endif -#define WPError( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "%\n%s:%i in %s ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( false ); } -#define WPWarning( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s WARNING:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); } - -#define WPFatal( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s FATAL ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( #assertion &&0 ); abort(); } - -#define ASSERT WPAssert -#endif - diff --git a/src/server/shared/LockedQueue.h b/src/server/shared/LockedQueue.h deleted file mode 100644 index 9f8afae6c14..00000000000 --- a/src/server/shared/LockedQueue.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LOCKEDQUEUE_H -#define LOCKEDQUEUE_H - -#include -#include -#include -#include -#include "Errors.h" - -namespace ACE_Based -{ - template > - class LockedQueue - { - //! Lock access to the queue. - LockType _lock; - - //! Storage backing the queue. - StorageType _queue; - - //! Cancellation flag. - volatile bool _canceled; - - public: - - //! Create a LockedQueue. - LockedQueue() - : _canceled(false) - { - } - - //! Destroy a LockedQueue. - virtual ~LockedQueue() - { - } - - //! Adds an item to the queue. - void add(const T& item) - { - lock(); - - //ASSERT(!this->_canceled); - // throw Cancellation_Exception(); - - _queue.push_back(item); - - unlock(); - } - - //! Gets the next result in the queue, if any. - bool next(T& result) - { - // ACE_Guard g(this->_lock); - ACE_GUARD_RETURN (LockType, g, this->_lock, false); - - if (_queue.empty()) - return false; - - //ASSERT (!_queue.empty() || !this->_canceled); - // throw Cancellation_Exception(); - result = _queue.front(); - _queue.pop_front(); - - return true; - } - - //! Peeks at the top of the queue. Remember to unlock after use. - T& peek() - { - lock(); - - T& result = _queue.front(); - - return result; - } - - //! Cancels the queue. - void cancel() - { - lock(); - - _canceled = true; - - unlock(); - } - - //! Checks if the queue is cancelled. - bool cancelled() - { - ACE_Guard g(this->_lock); - return _canceled; - } - - //! Locks the queue for access. - void lock() - { - this->_lock.acquire(); - } - - //! Unlocks the queue. - void unlock() - { - this->_lock.release(); - } - - ///! Calls pop_front of the queue - void pop_front() - { - ACE_GUARD (LockType, g, this->_lock); - _queue.pop_front(); - } - - ///! Checks if we're empty or not with locks held - bool empty() - { - ACE_GUARD_RETURN (LockType, g, this->_lock, false); - return _queue.empty(); - } - }; -} -#endif diff --git a/src/server/shared/Log.cpp b/src/server/shared/Log.cpp deleted file mode 100644 index 187b9eaa79b..00000000000 --- a/src/server/shared/Log.cpp +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Log.h" -#include "Policies/SingletonImp.h" -#include "Config/ConfigEnv.h" -#include "Util.h" - -#include -#include - -INSTANTIATE_SINGLETON_1( Log ); - -Log::Log() : - raLogfile(NULL), logfile(NULL), gmLogfile(NULL), charLogfile(NULL), - dberLogfile(NULL), chatLogfile(NULL), m_gmlog_per_account(false), - m_enableLogDBLater(false), m_enableLogDB(false), m_colored(false), - arenaLogFile(NULL) -{ - Initialize(); -} - -Log::~Log() -{ - if( logfile != NULL ) - fclose(logfile); - logfile = NULL; - - if( gmLogfile != NULL ) - fclose(gmLogfile); - gmLogfile = NULL; - - if (charLogfile != NULL) - fclose(charLogfile); - charLogfile = NULL; - - if( dberLogfile != NULL ) - fclose(dberLogfile); - dberLogfile = NULL; - - if (raLogfile != NULL) - fclose(raLogfile); - raLogfile = NULL; - - if (chatLogfile != NULL) - fclose(chatLogfile); - chatLogfile = NULL; - - if (arenaLogFile != NULL) - fclose(arenaLogFile); - arenaLogFile = NULL; -} - -void Log::SetLogLevel(char *Level) -{ - int32 NewLevel =atoi((char*)Level); - if ( NewLevel <0 ) - NewLevel = 0; - m_logLevel = NewLevel; - - outString( "LogLevel is %u",m_logLevel ); -} - -void Log::SetLogFileLevel(char *Level) -{ - int32 NewLevel =atoi((char*)Level); - if ( NewLevel <0 ) - NewLevel = 0; - m_logFileLevel = NewLevel; - - outString( "LogFileLevel is %u",m_logFileLevel ); -} - -void Log::SetDBLogLevel(char *Level) -{ - int32 NewLevel = atoi((char*)Level); - if ( NewLevel < 0 ) - NewLevel = 0; - m_dbLogLevel = NewLevel; - - outString( "DBLogLevel is %u",m_dbLogLevel ); -} - -void Log::Initialize() -{ - /// Check whether we'll log GM commands/RA events/character outputs/chat stuffs - m_dbChar = sConfig.GetBoolDefault("LogDB.Char", false); - m_dbRA = sConfig.GetBoolDefault("LogDB.RA", false); - m_dbGM = sConfig.GetBoolDefault("LogDB.GM", false); - m_dbChat = sConfig.GetBoolDefault("LogDB.Chat", false); - - /// Realm must be 0 by default - SetRealmID(0); - - /// Common log files data - m_logsDir = sConfig.GetStringDefault("LogsDir",""); - if (!m_logsDir.empty()) - if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) - m_logsDir.append("/"); - - m_logsTimestamp = "_" + GetTimestampStr(); - - /// Open specific log files - logfile = openLogFile("LogFile","LogTimestamp","w"); - InitColors(sConfig.GetStringDefault("LogColors", "")); - - m_gmlog_per_account = sConfig.GetBoolDefault("GmLogPerAccount",false); - if(!m_gmlog_per_account) - gmLogfile = openLogFile("GMLogFile","GmLogTimestamp","a"); - else - { - // GM log settings for per account case - m_gmlog_filename_format = sConfig.GetStringDefault("GMLogFile", ""); - if(!m_gmlog_filename_format.empty()) - { - bool m_gmlog_timestamp = sConfig.GetBoolDefault("GmLogTimestamp",false); - - size_t dot_pos = m_gmlog_filename_format.find_last_of("."); - if(dot_pos!=m_gmlog_filename_format.npos) - { - if(m_gmlog_timestamp) - m_gmlog_filename_format.insert(dot_pos,m_logsTimestamp); - - m_gmlog_filename_format.insert(dot_pos,"_#%u"); - } - else - { - m_gmlog_filename_format += "_#%u"; - - if(m_gmlog_timestamp) - m_gmlog_filename_format += m_logsTimestamp; - } - - m_gmlog_filename_format = m_logsDir + m_gmlog_filename_format; - } - } - - charLogfile = openLogFile("CharLogFile","CharLogTimestamp","a"); - - dberLogfile = openLogFile("DBErrorLogFile",NULL,"a"); - raLogfile = openLogFile("RaLogFile",NULL,"a"); - chatLogfile = openLogFile("ChatLogFile","ChatLogTimestamp","a"); - arenaLogFile = openLogFile("ArenaLogFile",NULL,"a"); - - // Main log file settings - m_logLevel = sConfig.GetIntDefault("LogLevel", LOGL_NORMAL); - m_logFileLevel = sConfig.GetIntDefault("LogFileLevel", LOGL_NORMAL); - m_dbLogLevel = sConfig.GetIntDefault("DBLogLevel", LOGL_NORMAL); - - m_logFilter = 0; - - if(sConfig.GetBoolDefault("LogFilter_TransportMoves", true)) - m_logFilter |= LOG_FILTER_TRANSPORT_MOVES; - if(sConfig.GetBoolDefault("LogFilter_CreatureMoves", true)) - m_logFilter |= LOG_FILTER_CREATURE_MOVES; - if(sConfig.GetBoolDefault("LogFilter_VisibilityChanges", true)) - m_logFilter |= LOG_FILTER_VISIBILITY_CHANGES; - if(sConfig.GetBoolDefault("LogFilter_AchievementUpdates", true)) - m_logFilter |= LOG_FILTER_ACHIEVEMENT_UPDATES; - - // Char log settings - m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false); - m_charLog_Dump_Separate = sConfig.GetBoolDefault("CharLogDump.Separate", false); - if (m_charLog_Dump_Separate) - { - m_dumpsDir = sConfig.GetStringDefault("CharLogDump.SeparateDir", ""); - if (!m_dumpsDir.empty()) - if ((m_dumpsDir.at(m_dumpsDir.length() - 1) != '/') && (m_dumpsDir.at(m_dumpsDir.length() - 1) != '\\')) - m_dumpsDir.append("/"); - } -} - -FILE* Log::openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode) -{ - std::string logfn=sConfig.GetStringDefault(configFileName, ""); - if(logfn.empty()) - return NULL; - - if(configTimeStampFlag && sConfig.GetBoolDefault(configTimeStampFlag,false)) - { - size_t dot_pos = logfn.find_last_of("."); - if(dot_pos!=logfn.npos) - logfn.insert(dot_pos,m_logsTimestamp); - else - logfn += m_logsTimestamp; - } - - return fopen((m_logsDir+logfn).c_str(), mode); -} - -FILE* Log::openGmlogPerAccount(uint32 account) -{ - if(m_gmlog_filename_format.empty()) - return NULL; - - char namebuf[TRINITY_PATH_MAX]; - snprintf(namebuf,TRINITY_PATH_MAX,m_gmlog_filename_format.c_str(),account); - return fopen(namebuf, "a"); -} - -void Log::outTimestamp(FILE* file) -{ - time_t t = time(NULL); - tm* aTm = localtime(&t); - // YYYY year - // MM month (2 digits 01-12) - // DD day (2 digits 01-31) - // HH hour (2 digits 00-23) - // MM minutes (2 digits 00-59) - // SS seconds (2 digits 00-59) - fprintf(file,"%-4d-%02d-%02d %02d:%02d:%02d ",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); -} - -void Log::InitColors(const std::string& str) -{ - if(str.empty()) - { - m_colored = false; - return; - } - - int color[4]; - - std::istringstream ss(str); - - for (uint8 i = 0; i < LogLevels; ++i) - { - ss >> color[i]; - - if(!ss) - return; - - if(color[i] < 0 || color[i] >= Colors) - return; - } - - for (uint8 i = 0; i < LogLevels; ++i) - m_colors[i] = ColorTypes(color[i]); - - m_colored = true; -} - -void Log::SetColor(bool stdout_stream, ColorTypes color) -{ - #if PLATFORM == PLATFORM_WINDOWS - static WORD WinColorFG[Colors] = - { - 0, // BLACK - FOREGROUND_RED, // RED - FOREGROUND_GREEN, // GREEN - FOREGROUND_RED | FOREGROUND_GREEN, // BROWN - FOREGROUND_BLUE, // BLUE - FOREGROUND_RED | FOREGROUND_BLUE,// MAGENTA - FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,// WHITE - // YELLOW - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, - // RED_BOLD - FOREGROUND_RED | FOREGROUND_INTENSITY, - // GREEN_BOLD - FOREGROUND_GREEN | FOREGROUND_INTENSITY, - FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD - // MAGENTA_BOLD - FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, - // CYAN_BOLD - FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, - // WHITE_BOLD - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY - }; - - HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); - SetConsoleTextAttribute(hConsole, WinColorFG[color]); - #else - enum ANSITextAttr - { - TA_NORMAL=0, - TA_BOLD=1, - TA_BLINK=5, - TA_REVERSE=7 - }; - - enum ANSIFgTextAttr - { - FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, - FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW - }; - - enum ANSIBgTextAttr - { - BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, - BG_MAGENTA, BG_CYAN, BG_WHITE - }; - - static uint8 UnixColorFG[Colors] = - { - FG_BLACK, // BLACK - FG_RED, // RED - FG_GREEN, // GREEN - FG_BROWN, // BROWN - FG_BLUE, // BLUE - FG_MAGENTA, // MAGENTA - FG_CYAN, // CYAN - FG_WHITE, // WHITE - FG_YELLOW, // YELLOW - FG_RED, // LRED - FG_GREEN, // LGREEN - FG_BLUE, // LBLUE - FG_MAGENTA, // LMAGENTA - FG_CYAN, // LCYAN - FG_WHITE // LWHITE - }; - - fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : "")); - #endif -} - -void Log::ResetColor(bool stdout_stream) -{ - #if PLATFORM == PLATFORM_WINDOWS - HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); - SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED ); - #else - fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m"); - #endif -} - -std::string Log::GetTimestampStr() -{ - time_t t = time(NULL); - tm* aTm = localtime(&t); - // YYYY year - // MM month (2 digits 01-12) - // DD day (2 digits 01-31) - // HH hour (2 digits 00-23) - // MM minutes (2 digits 00-59) - // SS seconds (2 digits 00-59) - char buf[20]; - snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); - return std::string(buf); -} - -void Log::outDB(LogTypes type, const char * str) -{ - if (!str || type >= MAX_LOG_TYPES) - return; - - std::string new_str(str); - if (new_str.empty()) - return; - LoginDatabase.escape_string(new_str); - - LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) " - "VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, type, new_str.c_str()); -} - -void Log::outString(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB) - { - // we don't want empty strings in the DB - std::string s(str); - if (s.empty() || s == " ") - return; - - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_STRING, nnew_str); - va_end(ap2); - } - - if (m_colored) - SetColor(true,m_colors[LOGL_NORMAL]); - - va_list ap; - - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (m_colored) - ResetColor(true); - - printf("\n"); - if(logfile) - { - outTimestamp(logfile); - va_start(ap, str); - vfprintf(logfile, str, ap); - fprintf(logfile, "\n"); - va_end(ap); - - fflush(logfile); - } - fflush(stdout); -} - -void Log::outString() -{ - printf("\n"); - if (logfile) - { - outTimestamp(logfile); - fprintf(logfile, "\n"); - fflush(logfile); - } - fflush(stdout); -} - -void Log::outCrash(const char * err, ...) -{ - if (!err) - return; - - if (m_enableLogDB) - { - va_list ap2; - va_start(ap2, err); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2); - outDB(LOG_TYPE_CRASH, nnew_str); - va_end(ap2); - } - - if (m_colored) - SetColor(false,LRED); - - va_list ap; - - va_start(ap, err); - vutf8printf(stdout, err, &ap); - va_end(ap); - - if (m_colored) - ResetColor(false); - - fprintf(stderr, "\n"); - if (logfile) - { - outTimestamp(logfile); - fprintf(logfile, "CRASH ALERT: "); - - va_start(ap, err); - vfprintf(logfile, err, ap); - va_end(ap); - - fprintf(logfile, "\n"); - fflush(logfile); - } - fflush(stderr); -} - -void Log::outError(const char * err, ...) -{ - if (!err) - return; - - if (m_enableLogDB) - { - va_list ap2; - va_start(ap2, err); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2); - outDB(LOG_TYPE_ERROR, nnew_str); - va_end(ap2); - } - - if (m_colored) - SetColor(false,LRED); - - va_list ap; - - va_start(ap, err); - vutf8printf(stderr, err, &ap); - va_end(ap); - - if (m_colored) - ResetColor(false); - - fprintf( stderr, "\n"); - if (logfile) - { - outTimestamp(logfile); - fprintf(logfile, "ERROR: "); - - va_start(ap, err); - vfprintf(logfile, err, ap); - va_end(ap); - - fprintf(logfile, "\n"); - fflush(logfile); - } - fflush(stderr); -} - -void Log::outArena(const char * str, ...) -{ - if (!str) - return; - - if (arenaLogFile) - { - va_list ap; - outTimestamp(arenaLogFile); - va_start(ap, str); - vfprintf(arenaLogFile, str, ap); - fprintf(arenaLogFile, "\n"); - va_end(ap); - fflush(arenaLogFile); - } - fflush(stdout); -} - -void Log::outErrorDb(const char * err, ...) -{ - if (!err) - return; - - if (m_colored) - SetColor(false,LRED); - - va_list ap; - - va_start(ap, err); - vutf8printf(stderr, err, &ap); - va_end(ap); - - if (m_colored) - ResetColor(false); - - fprintf( stderr, "\n" ); - - if (logfile) - { - outTimestamp(logfile); - fprintf(logfile, "ERROR: " ); - - va_start(ap, err); - vfprintf(logfile, err, ap); - va_end(ap); - - fprintf(logfile, "\n" ); - fflush(logfile); - } - - if (dberLogfile) - { - outTimestamp(dberLogfile); - va_start(ap, err); - vfprintf(dberLogfile, err, ap); - va_end(ap); - - fprintf(dberLogfile, "\n" ); - fflush(dberLogfile); - } - fflush(stderr); -} - -void Log::outBasic(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbLogLevel > LOGL_NORMAL) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_BASIC, nnew_str); - va_end(ap2); - } - - if (m_logLevel > LOGL_NORMAL) - { - if (m_colored) - SetColor(true,m_colors[LOGL_BASIC]); - - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (m_colored) - ResetColor(true); - - printf("\n"); - - if (logfile) - { - outTimestamp(logfile); - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - fprintf(logfile, "\n" ); - va_end(ap); - fflush(logfile); - } - } - fflush(stdout); -} - -void Log::outDetail(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbLogLevel > LOGL_BASIC) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_DETAIL, nnew_str); - va_end(ap2); - } - - if (m_logLevel > LOGL_BASIC) - { - if (m_colored) - SetColor(true,m_colors[LOGL_DETAIL]); - - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (m_colored) - ResetColor(true); - - printf("\n"); - - if (logfile) - { - outTimestamp(logfile); - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - va_end(ap); - - fprintf(logfile, "\n"); - fflush(logfile); - } - } - - fflush(stdout); -} - -void Log::outDebugInLine(const char * str, ...) -{ - if (!str) - return; - - if (m_logLevel > LOGL_DETAIL) - { - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - //if(m_colored) - // ResetColor(true); - - if (logfile) - { - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - va_end(ap); - } - } -} - -void Log::outDebug(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbLogLevel > LOGL_DETAIL) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_DEBUG, nnew_str); - va_end(ap2); - } - - if( m_logLevel > LOGL_DETAIL ) - { - if (m_colored) - SetColor(true,m_colors[LOGL_DEBUG]); - - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if(m_colored) - ResetColor(true); - - printf( "\n" ); - - if (logfile) - { - outTimestamp(logfile); - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - va_end(ap); - - fprintf(logfile, "\n" ); - fflush(logfile); - } - } - fflush(stdout); -} - -void Log::outStringInLine(const char * str, ...) -{ - if (!str) - return; - - va_list ap; - - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (logfile) - { - va_start(ap, str); - vfprintf(logfile, str, ap); - va_end(ap); - } -} - -void Log::outCommand(uint32 account, const char * str, ...) -{ - if (!str) - return; - - // TODO: support accountid - if (m_enableLogDB && m_dbGM) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_GM, nnew_str); - va_end(ap2); - } - - if (m_logLevel > LOGL_NORMAL) - { - if (m_colored) - SetColor(true,m_colors[LOGL_BASIC]); - - va_list ap; - va_start(ap, str); - vutf8printf(stdout, str, &ap); - va_end(ap); - - if (m_colored) - ResetColor(true); - - printf("\n"); - - if (logfile) - { - outTimestamp(logfile); - va_list ap; - va_start(ap, str); - vfprintf(logfile, str, ap); - fprintf(logfile, "\n" ); - va_end(ap); - fflush(logfile); - } - } - - if (m_gmlog_per_account) - { - if (FILE* per_file = openGmlogPerAccount (account)) - { - outTimestamp(per_file); - va_list ap; - va_start(ap, str); - vfprintf(per_file, str, ap); - fprintf(per_file, "\n" ); - va_end(ap); - fclose(per_file); - } - } - else if (gmLogfile) - { - outTimestamp(gmLogfile); - va_list ap; - va_start(ap, str); - vfprintf(gmLogfile, str, ap); - fprintf(gmLogfile, "\n" ); - va_end(ap); - fflush(gmLogfile); - } - - fflush(stdout); -} - -void Log::outChar(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbChar) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_CHAR, nnew_str); - va_end(ap2); - } - - if (charLogfile) - { - outTimestamp(charLogfile); - va_list ap; - va_start(ap, str); - vfprintf(charLogfile, str, ap); - fprintf(charLogfile, "\n" ); - va_end(ap); - fflush(charLogfile); - } -} - -void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name) -{ - FILE *file = NULL; - if (m_charLog_Dump_Separate) - { - char fileName[29]; // Max length: name(12) + guid(11) + _.log (5) + \0 - snprintf(fileName, 29, "%d_%s.log", guid, name); - std::string sFileName(m_dumpsDir); - sFileName.append(fileName); - file = fopen((m_logsDir + sFileName).c_str(), "w"); - } - else - file = charLogfile; - if (file) - { - fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n", - account_id, guid, name, str); - fflush(file); - if (m_charLog_Dump_Separate) - fclose(file); - } -} - -void Log::outRemote(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbRA) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_RA, nnew_str); - va_end(ap2); - } - - if (raLogfile) - { - outTimestamp(raLogfile); - va_list ap; - va_start(ap, str); - vfprintf(raLogfile, str, ap); - fprintf(raLogfile, "\n" ); - va_end(ap); - fflush(raLogfile); - } - fflush(stdout); -} - -void Log::outChat(const char * str, ...) -{ - if (!str) - return; - - if (m_enableLogDB && m_dbChat) - { - va_list ap2; - va_start(ap2, str); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); - outDB(LOG_TYPE_CHAT, nnew_str); - va_end(ap2); - } - - if (chatLogfile) - { - outTimestamp(chatLogfile); - va_list ap; - va_start(ap, str); - vfprintf(chatLogfile, str, ap); - fprintf(chatLogfile, "\n" ); - fflush(chatLogfile); - va_end(ap); - } - fflush(stdout); -} - -void outstring_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outString(buf); -} - -void detail_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outDetail(buf); -} - -void debug_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outDebug(buf); -} - -void error_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outError(buf); -} - -void error_db_log(const char * str, ...) -{ - if (!str) - return; - - char buf[256]; - va_list ap; - va_start(ap, str); - vsnprintf(buf,256, str, ap); - va_end(ap); - - Trinity::Singleton::Instance().outErrorDb(buf); -} - diff --git a/src/server/shared/Log.h b/src/server/shared/Log.h deleted file mode 100644 index deb6c55e4e0..00000000000 --- a/src/server/shared/Log.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_LOG_H -#define TRINITYCORE_LOG_H - -#include "Common.h" -#include "Policies/Singleton.h" -#include "Database/DatabaseEnv.h" - -class Config; - -enum LogFilters -{ - LOG_FILTER_TRANSPORT_MOVES = 1, - LOG_FILTER_CREATURE_MOVES = 2, - LOG_FILTER_VISIBILITY_CHANGES = 4, - LOG_FILTER_ACHIEVEMENT_UPDATES = 8 -}; - -enum LogTypes -{ - LOG_TYPE_STRING = 0, - LOG_TYPE_ERROR = 1, - LOG_TYPE_BASIC = 2, - LOG_TYPE_DETAIL = 3, - LOG_TYPE_DEBUG = 4, - LOG_TYPE_CHAR = 5, - LOG_TYPE_WORLD = 6, - LOG_TYPE_RA = 7, - LOG_TYPE_GM = 8, - LOG_TYPE_CRASH = 9, - LOG_TYPE_CHAT = 10, - MAX_LOG_TYPES -}; - -enum LogLevel -{ - LOGL_NORMAL = 0, - LOGL_BASIC, - LOGL_DETAIL, - LOGL_DEBUG -}; - -const int LogLevels = int(LOGL_DEBUG)+1; - -enum ColorTypes -{ - BLACK, - RED, - GREEN, - BROWN, - BLUE, - MAGENTA, - CYAN, - GREY, - YELLOW, - LRED, - LGREEN, - LBLUE, - LMAGENTA, - LCYAN, - WHITE -}; - -const int Colors = int(WHITE)+1; - -class Log : public Trinity::Singleton > -{ - friend class Trinity::OperatorNew; - Log(); - ~Log(); - - public: - void Initialize(); - - void InitColors(const std::string& init_str); - void SetColor(bool stdout_stream, ColorTypes color); - void ResetColor(bool stdout_stream); - - void outDB( LogTypes type, const char * str ); - void outString( const char * str, ... ) ATTR_PRINTF(2,3); - void outString( ); - void outStringInLine( const char * str, ... ) ATTR_PRINTF(2,3); - void outError( const char * err, ... ) ATTR_PRINTF(2,3); - void outCrash( const char * err, ... ) ATTR_PRINTF(2,3); - void outBasic( const char * str, ... ) ATTR_PRINTF(2,3); - void outDetail( const char * str, ... ) ATTR_PRINTF(2,3); - void outDebug( const char * str, ... ) ATTR_PRINTF(2,3); - void outDebugInLine( const char * str, ... ) ATTR_PRINTF(2,3); - void outErrorDb( const char * str, ... ) ATTR_PRINTF(2,3); - void outChar( const char * str, ... ) ATTR_PRINTF(2,3); - void outCommand( uint32 account, const char * str, ...) ATTR_PRINTF(3,4); - void outRemote( const char * str, ... ) ATTR_PRINTF(2,3); - void outChat( const char * str, ... ) ATTR_PRINTF(2,3); - void outArena( const char * str, ... ) ATTR_PRINTF(2,3); - void outCharDump( const char * str, uint32 account_id, uint32 guid, const char * name ); - - static void outTimestamp(FILE* file); - static std::string GetTimestampStr(); - - void SetLogLevel(char * Level); - void SetLogFileLevel(char * Level); - void SetDBLogLevel(char * Level); - void SetRealmID(uint32 id) { realm = id; } - - uint32 getLogFilter() const { return m_logFilter; } - bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); } - bool IsOutCharDump() const { return m_charLog_Dump; } - - bool GetLogDB() { return m_enableLogDB; } - bool GetLogDBLater() { return m_enableLogDBLater; } - void SetLogDB(bool enable) { m_enableLogDB = enable; } - void SetLogDBLater(bool value) { m_enableLogDBLater = value; } - private: - FILE* openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode); - FILE* openGmlogPerAccount(uint32 account); - - FILE* raLogfile; - FILE* logfile; - FILE* gmLogfile; - FILE* charLogfile; - FILE* dberLogfile; - FILE* chatLogfile; - FILE* arenaLogFile; - - // cache values for after initilization use (like gm log per account case) - std::string m_logsDir; - std::string m_logsTimestamp; - - // gm log control - bool m_gmlog_per_account; - std::string m_gmlog_filename_format; - - bool m_enableLogDBLater; - bool m_enableLogDB; - uint32 realm; - - // log coloring - bool m_colored; - ColorTypes m_colors[4]; - - // log levels: - // 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug - uint8 m_dbLogLevel; - uint8 m_logLevel; - uint8 m_logFileLevel; - uint8 m_logFilter; - bool m_dbChar; - bool m_dbRA; - bool m_dbGM; - bool m_dbChat; - bool m_charLog_Dump; - bool m_charLog_Dump_Separate; - std::string m_dumpsDir; -}; - -#define sLog Trinity::Singleton::Instance() - -#ifdef TRINITY_DEBUG -#define DEBUG_LOG Trinity::Singleton::Instance().outDebug -#else -#define DEBUG_LOG -#endif - -// primary for script library -void outstring_log(const char * str, ...) ATTR_PRINTF(1,2); -void detail_log(const char * str, ...) ATTR_PRINTF(1,2); -void debug_log(const char * str, ...) ATTR_PRINTF(1,2); -void error_log(const char * str, ...) ATTR_PRINTF(1,2); -void error_db_log(const char * str, ...) ATTR_PRINTF(1,2); -#endif - diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp new file mode 100644 index 00000000000..187b9eaa79b --- /dev/null +++ b/src/server/shared/Logging/Log.cpp @@ -0,0 +1,1005 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "Policies/SingletonImp.h" +#include "Config/ConfigEnv.h" +#include "Util.h" + +#include +#include + +INSTANTIATE_SINGLETON_1( Log ); + +Log::Log() : + raLogfile(NULL), logfile(NULL), gmLogfile(NULL), charLogfile(NULL), + dberLogfile(NULL), chatLogfile(NULL), m_gmlog_per_account(false), + m_enableLogDBLater(false), m_enableLogDB(false), m_colored(false), + arenaLogFile(NULL) +{ + Initialize(); +} + +Log::~Log() +{ + if( logfile != NULL ) + fclose(logfile); + logfile = NULL; + + if( gmLogfile != NULL ) + fclose(gmLogfile); + gmLogfile = NULL; + + if (charLogfile != NULL) + fclose(charLogfile); + charLogfile = NULL; + + if( dberLogfile != NULL ) + fclose(dberLogfile); + dberLogfile = NULL; + + if (raLogfile != NULL) + fclose(raLogfile); + raLogfile = NULL; + + if (chatLogfile != NULL) + fclose(chatLogfile); + chatLogfile = NULL; + + if (arenaLogFile != NULL) + fclose(arenaLogFile); + arenaLogFile = NULL; +} + +void Log::SetLogLevel(char *Level) +{ + int32 NewLevel =atoi((char*)Level); + if ( NewLevel <0 ) + NewLevel = 0; + m_logLevel = NewLevel; + + outString( "LogLevel is %u",m_logLevel ); +} + +void Log::SetLogFileLevel(char *Level) +{ + int32 NewLevel =atoi((char*)Level); + if ( NewLevel <0 ) + NewLevel = 0; + m_logFileLevel = NewLevel; + + outString( "LogFileLevel is %u",m_logFileLevel ); +} + +void Log::SetDBLogLevel(char *Level) +{ + int32 NewLevel = atoi((char*)Level); + if ( NewLevel < 0 ) + NewLevel = 0; + m_dbLogLevel = NewLevel; + + outString( "DBLogLevel is %u",m_dbLogLevel ); +} + +void Log::Initialize() +{ + /// Check whether we'll log GM commands/RA events/character outputs/chat stuffs + m_dbChar = sConfig.GetBoolDefault("LogDB.Char", false); + m_dbRA = sConfig.GetBoolDefault("LogDB.RA", false); + m_dbGM = sConfig.GetBoolDefault("LogDB.GM", false); + m_dbChat = sConfig.GetBoolDefault("LogDB.Chat", false); + + /// Realm must be 0 by default + SetRealmID(0); + + /// Common log files data + m_logsDir = sConfig.GetStringDefault("LogsDir",""); + if (!m_logsDir.empty()) + if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) + m_logsDir.append("/"); + + m_logsTimestamp = "_" + GetTimestampStr(); + + /// Open specific log files + logfile = openLogFile("LogFile","LogTimestamp","w"); + InitColors(sConfig.GetStringDefault("LogColors", "")); + + m_gmlog_per_account = sConfig.GetBoolDefault("GmLogPerAccount",false); + if(!m_gmlog_per_account) + gmLogfile = openLogFile("GMLogFile","GmLogTimestamp","a"); + else + { + // GM log settings for per account case + m_gmlog_filename_format = sConfig.GetStringDefault("GMLogFile", ""); + if(!m_gmlog_filename_format.empty()) + { + bool m_gmlog_timestamp = sConfig.GetBoolDefault("GmLogTimestamp",false); + + size_t dot_pos = m_gmlog_filename_format.find_last_of("."); + if(dot_pos!=m_gmlog_filename_format.npos) + { + if(m_gmlog_timestamp) + m_gmlog_filename_format.insert(dot_pos,m_logsTimestamp); + + m_gmlog_filename_format.insert(dot_pos,"_#%u"); + } + else + { + m_gmlog_filename_format += "_#%u"; + + if(m_gmlog_timestamp) + m_gmlog_filename_format += m_logsTimestamp; + } + + m_gmlog_filename_format = m_logsDir + m_gmlog_filename_format; + } + } + + charLogfile = openLogFile("CharLogFile","CharLogTimestamp","a"); + + dberLogfile = openLogFile("DBErrorLogFile",NULL,"a"); + raLogfile = openLogFile("RaLogFile",NULL,"a"); + chatLogfile = openLogFile("ChatLogFile","ChatLogTimestamp","a"); + arenaLogFile = openLogFile("ArenaLogFile",NULL,"a"); + + // Main log file settings + m_logLevel = sConfig.GetIntDefault("LogLevel", LOGL_NORMAL); + m_logFileLevel = sConfig.GetIntDefault("LogFileLevel", LOGL_NORMAL); + m_dbLogLevel = sConfig.GetIntDefault("DBLogLevel", LOGL_NORMAL); + + m_logFilter = 0; + + if(sConfig.GetBoolDefault("LogFilter_TransportMoves", true)) + m_logFilter |= LOG_FILTER_TRANSPORT_MOVES; + if(sConfig.GetBoolDefault("LogFilter_CreatureMoves", true)) + m_logFilter |= LOG_FILTER_CREATURE_MOVES; + if(sConfig.GetBoolDefault("LogFilter_VisibilityChanges", true)) + m_logFilter |= LOG_FILTER_VISIBILITY_CHANGES; + if(sConfig.GetBoolDefault("LogFilter_AchievementUpdates", true)) + m_logFilter |= LOG_FILTER_ACHIEVEMENT_UPDATES; + + // Char log settings + m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false); + m_charLog_Dump_Separate = sConfig.GetBoolDefault("CharLogDump.Separate", false); + if (m_charLog_Dump_Separate) + { + m_dumpsDir = sConfig.GetStringDefault("CharLogDump.SeparateDir", ""); + if (!m_dumpsDir.empty()) + if ((m_dumpsDir.at(m_dumpsDir.length() - 1) != '/') && (m_dumpsDir.at(m_dumpsDir.length() - 1) != '\\')) + m_dumpsDir.append("/"); + } +} + +FILE* Log::openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode) +{ + std::string logfn=sConfig.GetStringDefault(configFileName, ""); + if(logfn.empty()) + return NULL; + + if(configTimeStampFlag && sConfig.GetBoolDefault(configTimeStampFlag,false)) + { + size_t dot_pos = logfn.find_last_of("."); + if(dot_pos!=logfn.npos) + logfn.insert(dot_pos,m_logsTimestamp); + else + logfn += m_logsTimestamp; + } + + return fopen((m_logsDir+logfn).c_str(), mode); +} + +FILE* Log::openGmlogPerAccount(uint32 account) +{ + if(m_gmlog_filename_format.empty()) + return NULL; + + char namebuf[TRINITY_PATH_MAX]; + snprintf(namebuf,TRINITY_PATH_MAX,m_gmlog_filename_format.c_str(),account); + return fopen(namebuf, "a"); +} + +void Log::outTimestamp(FILE* file) +{ + time_t t = time(NULL); + tm* aTm = localtime(&t); + // YYYY year + // MM month (2 digits 01-12) + // DD day (2 digits 01-31) + // HH hour (2 digits 00-23) + // MM minutes (2 digits 00-59) + // SS seconds (2 digits 00-59) + fprintf(file,"%-4d-%02d-%02d %02d:%02d:%02d ",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); +} + +void Log::InitColors(const std::string& str) +{ + if(str.empty()) + { + m_colored = false; + return; + } + + int color[4]; + + std::istringstream ss(str); + + for (uint8 i = 0; i < LogLevels; ++i) + { + ss >> color[i]; + + if(!ss) + return; + + if(color[i] < 0 || color[i] >= Colors) + return; + } + + for (uint8 i = 0; i < LogLevels; ++i) + m_colors[i] = ColorTypes(color[i]); + + m_colored = true; +} + +void Log::SetColor(bool stdout_stream, ColorTypes color) +{ + #if PLATFORM == PLATFORM_WINDOWS + static WORD WinColorFG[Colors] = + { + 0, // BLACK + FOREGROUND_RED, // RED + FOREGROUND_GREEN, // GREEN + FOREGROUND_RED | FOREGROUND_GREEN, // BROWN + FOREGROUND_BLUE, // BLUE + FOREGROUND_RED | FOREGROUND_BLUE,// MAGENTA + FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,// WHITE + // YELLOW + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, + // RED_BOLD + FOREGROUND_RED | FOREGROUND_INTENSITY, + // GREEN_BOLD + FOREGROUND_GREEN | FOREGROUND_INTENSITY, + FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD + // MAGENTA_BOLD + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + // CYAN_BOLD + FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + // WHITE_BOLD + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY + }; + + HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); + SetConsoleTextAttribute(hConsole, WinColorFG[color]); + #else + enum ANSITextAttr + { + TA_NORMAL=0, + TA_BOLD=1, + TA_BLINK=5, + TA_REVERSE=7 + }; + + enum ANSIFgTextAttr + { + FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, + FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW + }; + + enum ANSIBgTextAttr + { + BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, + BG_MAGENTA, BG_CYAN, BG_WHITE + }; + + static uint8 UnixColorFG[Colors] = + { + FG_BLACK, // BLACK + FG_RED, // RED + FG_GREEN, // GREEN + FG_BROWN, // BROWN + FG_BLUE, // BLUE + FG_MAGENTA, // MAGENTA + FG_CYAN, // CYAN + FG_WHITE, // WHITE + FG_YELLOW, // YELLOW + FG_RED, // LRED + FG_GREEN, // LGREEN + FG_BLUE, // LBLUE + FG_MAGENTA, // LMAGENTA + FG_CYAN, // LCYAN + FG_WHITE // LWHITE + }; + + fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : "")); + #endif +} + +void Log::ResetColor(bool stdout_stream) +{ + #if PLATFORM == PLATFORM_WINDOWS + HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE ); + SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED ); + #else + fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m"); + #endif +} + +std::string Log::GetTimestampStr() +{ + time_t t = time(NULL); + tm* aTm = localtime(&t); + // YYYY year + // MM month (2 digits 01-12) + // DD day (2 digits 01-31) + // HH hour (2 digits 00-23) + // MM minutes (2 digits 00-59) + // SS seconds (2 digits 00-59) + char buf[20]; + snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); + return std::string(buf); +} + +void Log::outDB(LogTypes type, const char * str) +{ + if (!str || type >= MAX_LOG_TYPES) + return; + + std::string new_str(str); + if (new_str.empty()) + return; + LoginDatabase.escape_string(new_str); + + LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) " + "VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, type, new_str.c_str()); +} + +void Log::outString(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB) + { + // we don't want empty strings in the DB + std::string s(str); + if (s.empty() || s == " ") + return; + + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_STRING, nnew_str); + va_end(ap2); + } + + if (m_colored) + SetColor(true,m_colors[LOGL_NORMAL]); + + va_list ap; + + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + ResetColor(true); + + printf("\n"); + if(logfile) + { + outTimestamp(logfile); + va_start(ap, str); + vfprintf(logfile, str, ap); + fprintf(logfile, "\n"); + va_end(ap); + + fflush(logfile); + } + fflush(stdout); +} + +void Log::outString() +{ + printf("\n"); + if (logfile) + { + outTimestamp(logfile); + fprintf(logfile, "\n"); + fflush(logfile); + } + fflush(stdout); +} + +void Log::outCrash(const char * err, ...) +{ + if (!err) + return; + + if (m_enableLogDB) + { + va_list ap2; + va_start(ap2, err); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2); + outDB(LOG_TYPE_CRASH, nnew_str); + va_end(ap2); + } + + if (m_colored) + SetColor(false,LRED); + + va_list ap; + + va_start(ap, err); + vutf8printf(stdout, err, &ap); + va_end(ap); + + if (m_colored) + ResetColor(false); + + fprintf(stderr, "\n"); + if (logfile) + { + outTimestamp(logfile); + fprintf(logfile, "CRASH ALERT: "); + + va_start(ap, err); + vfprintf(logfile, err, ap); + va_end(ap); + + fprintf(logfile, "\n"); + fflush(logfile); + } + fflush(stderr); +} + +void Log::outError(const char * err, ...) +{ + if (!err) + return; + + if (m_enableLogDB) + { + va_list ap2; + va_start(ap2, err); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2); + outDB(LOG_TYPE_ERROR, nnew_str); + va_end(ap2); + } + + if (m_colored) + SetColor(false,LRED); + + va_list ap; + + va_start(ap, err); + vutf8printf(stderr, err, &ap); + va_end(ap); + + if (m_colored) + ResetColor(false); + + fprintf( stderr, "\n"); + if (logfile) + { + outTimestamp(logfile); + fprintf(logfile, "ERROR: "); + + va_start(ap, err); + vfprintf(logfile, err, ap); + va_end(ap); + + fprintf(logfile, "\n"); + fflush(logfile); + } + fflush(stderr); +} + +void Log::outArena(const char * str, ...) +{ + if (!str) + return; + + if (arenaLogFile) + { + va_list ap; + outTimestamp(arenaLogFile); + va_start(ap, str); + vfprintf(arenaLogFile, str, ap); + fprintf(arenaLogFile, "\n"); + va_end(ap); + fflush(arenaLogFile); + } + fflush(stdout); +} + +void Log::outErrorDb(const char * err, ...) +{ + if (!err) + return; + + if (m_colored) + SetColor(false,LRED); + + va_list ap; + + va_start(ap, err); + vutf8printf(stderr, err, &ap); + va_end(ap); + + if (m_colored) + ResetColor(false); + + fprintf( stderr, "\n" ); + + if (logfile) + { + outTimestamp(logfile); + fprintf(logfile, "ERROR: " ); + + va_start(ap, err); + vfprintf(logfile, err, ap); + va_end(ap); + + fprintf(logfile, "\n" ); + fflush(logfile); + } + + if (dberLogfile) + { + outTimestamp(dberLogfile); + va_start(ap, err); + vfprintf(dberLogfile, err, ap); + va_end(ap); + + fprintf(dberLogfile, "\n" ); + fflush(dberLogfile); + } + fflush(stderr); +} + +void Log::outBasic(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbLogLevel > LOGL_NORMAL) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_BASIC, nnew_str); + va_end(ap2); + } + + if (m_logLevel > LOGL_NORMAL) + { + if (m_colored) + SetColor(true,m_colors[LOGL_BASIC]); + + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + ResetColor(true); + + printf("\n"); + + if (logfile) + { + outTimestamp(logfile); + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + fprintf(logfile, "\n" ); + va_end(ap); + fflush(logfile); + } + } + fflush(stdout); +} + +void Log::outDetail(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbLogLevel > LOGL_BASIC) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_DETAIL, nnew_str); + va_end(ap2); + } + + if (m_logLevel > LOGL_BASIC) + { + if (m_colored) + SetColor(true,m_colors[LOGL_DETAIL]); + + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + ResetColor(true); + + printf("\n"); + + if (logfile) + { + outTimestamp(logfile); + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + va_end(ap); + + fprintf(logfile, "\n"); + fflush(logfile); + } + } + + fflush(stdout); +} + +void Log::outDebugInLine(const char * str, ...) +{ + if (!str) + return; + + if (m_logLevel > LOGL_DETAIL) + { + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + //if(m_colored) + // ResetColor(true); + + if (logfile) + { + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + va_end(ap); + } + } +} + +void Log::outDebug(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbLogLevel > LOGL_DETAIL) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_DEBUG, nnew_str); + va_end(ap2); + } + + if( m_logLevel > LOGL_DETAIL ) + { + if (m_colored) + SetColor(true,m_colors[LOGL_DEBUG]); + + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if(m_colored) + ResetColor(true); + + printf( "\n" ); + + if (logfile) + { + outTimestamp(logfile); + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + va_end(ap); + + fprintf(logfile, "\n" ); + fflush(logfile); + } + } + fflush(stdout); +} + +void Log::outStringInLine(const char * str, ...) +{ + if (!str) + return; + + va_list ap; + + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (logfile) + { + va_start(ap, str); + vfprintf(logfile, str, ap); + va_end(ap); + } +} + +void Log::outCommand(uint32 account, const char * str, ...) +{ + if (!str) + return; + + // TODO: support accountid + if (m_enableLogDB && m_dbGM) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_GM, nnew_str); + va_end(ap2); + } + + if (m_logLevel > LOGL_NORMAL) + { + if (m_colored) + SetColor(true,m_colors[LOGL_BASIC]); + + va_list ap; + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + ResetColor(true); + + printf("\n"); + + if (logfile) + { + outTimestamp(logfile); + va_list ap; + va_start(ap, str); + vfprintf(logfile, str, ap); + fprintf(logfile, "\n" ); + va_end(ap); + fflush(logfile); + } + } + + if (m_gmlog_per_account) + { + if (FILE* per_file = openGmlogPerAccount (account)) + { + outTimestamp(per_file); + va_list ap; + va_start(ap, str); + vfprintf(per_file, str, ap); + fprintf(per_file, "\n" ); + va_end(ap); + fclose(per_file); + } + } + else if (gmLogfile) + { + outTimestamp(gmLogfile); + va_list ap; + va_start(ap, str); + vfprintf(gmLogfile, str, ap); + fprintf(gmLogfile, "\n" ); + va_end(ap); + fflush(gmLogfile); + } + + fflush(stdout); +} + +void Log::outChar(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbChar) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_CHAR, nnew_str); + va_end(ap2); + } + + if (charLogfile) + { + outTimestamp(charLogfile); + va_list ap; + va_start(ap, str); + vfprintf(charLogfile, str, ap); + fprintf(charLogfile, "\n" ); + va_end(ap); + fflush(charLogfile); + } +} + +void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name) +{ + FILE *file = NULL; + if (m_charLog_Dump_Separate) + { + char fileName[29]; // Max length: name(12) + guid(11) + _.log (5) + \0 + snprintf(fileName, 29, "%d_%s.log", guid, name); + std::string sFileName(m_dumpsDir); + sFileName.append(fileName); + file = fopen((m_logsDir + sFileName).c_str(), "w"); + } + else + file = charLogfile; + if (file) + { + fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n", + account_id, guid, name, str); + fflush(file); + if (m_charLog_Dump_Separate) + fclose(file); + } +} + +void Log::outRemote(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbRA) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_RA, nnew_str); + va_end(ap2); + } + + if (raLogfile) + { + outTimestamp(raLogfile); + va_list ap; + va_start(ap, str); + vfprintf(raLogfile, str, ap); + fprintf(raLogfile, "\n" ); + va_end(ap); + fflush(raLogfile); + } + fflush(stdout); +} + +void Log::outChat(const char * str, ...) +{ + if (!str) + return; + + if (m_enableLogDB && m_dbChat) + { + va_list ap2; + va_start(ap2, str); + char nnew_str[MAX_QUERY_LEN]; + vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2); + outDB(LOG_TYPE_CHAT, nnew_str); + va_end(ap2); + } + + if (chatLogfile) + { + outTimestamp(chatLogfile); + va_list ap; + va_start(ap, str); + vfprintf(chatLogfile, str, ap); + fprintf(chatLogfile, "\n" ); + fflush(chatLogfile); + va_end(ap); + } + fflush(stdout); +} + +void outstring_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outString(buf); +} + +void detail_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outDetail(buf); +} + +void debug_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outDebug(buf); +} + +void error_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outError(buf); +} + +void error_db_log(const char * str, ...) +{ + if (!str) + return; + + char buf[256]; + va_list ap; + va_start(ap, str); + vsnprintf(buf,256, str, ap); + va_end(ap); + + Trinity::Singleton::Instance().outErrorDb(buf); +} + diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h new file mode 100644 index 00000000000..deb6c55e4e0 --- /dev/null +++ b/src/server/shared/Logging/Log.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_LOG_H +#define TRINITYCORE_LOG_H + +#include "Common.h" +#include "Policies/Singleton.h" +#include "Database/DatabaseEnv.h" + +class Config; + +enum LogFilters +{ + LOG_FILTER_TRANSPORT_MOVES = 1, + LOG_FILTER_CREATURE_MOVES = 2, + LOG_FILTER_VISIBILITY_CHANGES = 4, + LOG_FILTER_ACHIEVEMENT_UPDATES = 8 +}; + +enum LogTypes +{ + LOG_TYPE_STRING = 0, + LOG_TYPE_ERROR = 1, + LOG_TYPE_BASIC = 2, + LOG_TYPE_DETAIL = 3, + LOG_TYPE_DEBUG = 4, + LOG_TYPE_CHAR = 5, + LOG_TYPE_WORLD = 6, + LOG_TYPE_RA = 7, + LOG_TYPE_GM = 8, + LOG_TYPE_CRASH = 9, + LOG_TYPE_CHAT = 10, + MAX_LOG_TYPES +}; + +enum LogLevel +{ + LOGL_NORMAL = 0, + LOGL_BASIC, + LOGL_DETAIL, + LOGL_DEBUG +}; + +const int LogLevels = int(LOGL_DEBUG)+1; + +enum ColorTypes +{ + BLACK, + RED, + GREEN, + BROWN, + BLUE, + MAGENTA, + CYAN, + GREY, + YELLOW, + LRED, + LGREEN, + LBLUE, + LMAGENTA, + LCYAN, + WHITE +}; + +const int Colors = int(WHITE)+1; + +class Log : public Trinity::Singleton > +{ + friend class Trinity::OperatorNew; + Log(); + ~Log(); + + public: + void Initialize(); + + void InitColors(const std::string& init_str); + void SetColor(bool stdout_stream, ColorTypes color); + void ResetColor(bool stdout_stream); + + void outDB( LogTypes type, const char * str ); + void outString( const char * str, ... ) ATTR_PRINTF(2,3); + void outString( ); + void outStringInLine( const char * str, ... ) ATTR_PRINTF(2,3); + void outError( const char * err, ... ) ATTR_PRINTF(2,3); + void outCrash( const char * err, ... ) ATTR_PRINTF(2,3); + void outBasic( const char * str, ... ) ATTR_PRINTF(2,3); + void outDetail( const char * str, ... ) ATTR_PRINTF(2,3); + void outDebug( const char * str, ... ) ATTR_PRINTF(2,3); + void outDebugInLine( const char * str, ... ) ATTR_PRINTF(2,3); + void outErrorDb( const char * str, ... ) ATTR_PRINTF(2,3); + void outChar( const char * str, ... ) ATTR_PRINTF(2,3); + void outCommand( uint32 account, const char * str, ...) ATTR_PRINTF(3,4); + void outRemote( const char * str, ... ) ATTR_PRINTF(2,3); + void outChat( const char * str, ... ) ATTR_PRINTF(2,3); + void outArena( const char * str, ... ) ATTR_PRINTF(2,3); + void outCharDump( const char * str, uint32 account_id, uint32 guid, const char * name ); + + static void outTimestamp(FILE* file); + static std::string GetTimestampStr(); + + void SetLogLevel(char * Level); + void SetLogFileLevel(char * Level); + void SetDBLogLevel(char * Level); + void SetRealmID(uint32 id) { realm = id; } + + uint32 getLogFilter() const { return m_logFilter; } + bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); } + bool IsOutCharDump() const { return m_charLog_Dump; } + + bool GetLogDB() { return m_enableLogDB; } + bool GetLogDBLater() { return m_enableLogDBLater; } + void SetLogDB(bool enable) { m_enableLogDB = enable; } + void SetLogDBLater(bool value) { m_enableLogDBLater = value; } + private: + FILE* openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode); + FILE* openGmlogPerAccount(uint32 account); + + FILE* raLogfile; + FILE* logfile; + FILE* gmLogfile; + FILE* charLogfile; + FILE* dberLogfile; + FILE* chatLogfile; + FILE* arenaLogFile; + + // cache values for after initilization use (like gm log per account case) + std::string m_logsDir; + std::string m_logsTimestamp; + + // gm log control + bool m_gmlog_per_account; + std::string m_gmlog_filename_format; + + bool m_enableLogDBLater; + bool m_enableLogDB; + uint32 realm; + + // log coloring + bool m_colored; + ColorTypes m_colors[4]; + + // log levels: + // 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug + uint8 m_dbLogLevel; + uint8 m_logLevel; + uint8 m_logFileLevel; + uint8 m_logFilter; + bool m_dbChar; + bool m_dbRA; + bool m_dbGM; + bool m_dbChat; + bool m_charLog_Dump; + bool m_charLog_Dump_Separate; + std::string m_dumpsDir; +}; + +#define sLog Trinity::Singleton::Instance() + +#ifdef TRINITY_DEBUG +#define DEBUG_LOG Trinity::Singleton::Instance().outDebug +#else +#define DEBUG_LOG +#endif + +// primary for script library +void outstring_log(const char * str, ...) ATTR_PRINTF(1,2); +void detail_log(const char * str, ...) ATTR_PRINTF(1,2); +void debug_log(const char * str, ...) ATTR_PRINTF(1,2); +void error_log(const char * str, ...) ATTR_PRINTF(1,2); +void error_db_log(const char * str, ...) ATTR_PRINTF(1,2); +#endif + diff --git a/src/server/shared/MemoryLeaks.cpp b/src/server/shared/MemoryLeaks.cpp deleted file mode 100644 index ef7e36c3b57..00000000000 --- a/src/server/shared/MemoryLeaks.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "MemoryLeaks.h" -#include "Policies/SingletonImp.h" - -INSTANTIATE_SINGLETON_1( MemoryManager ) ; - -MemoryManager::MemoryManager( ) -{ - #if COMPILER == MICROSOFT - // standard leak check initialization - //_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); - // uncomment to disable Visual Leak Detector from code - //VLDDisable(); - #endif -} diff --git a/src/server/shared/MemoryLeaks.h b/src/server/shared/MemoryLeaks.h deleted file mode 100644 index c8b8fb8e1b1..00000000000 --- a/src/server/shared/MemoryLeaks.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYSERVER_MEMORY_H -#define TRINITYSERVER_MEMORY_H - -#include "Platform/CompilerDefs.h" - -#if COMPILER == COMPILER_MICROSOFT - -#ifndef _WIN64 -// Visual Leak Detector support enabled -//#include -// standard Visual Studio leak check disabled, -//# define _CRTDBG_MAP_ALLOC -//# include -//# include -#else -//# define _CRTDBG_MAP_ALLOC -//# include -//# include -#endif - -#endif - - -#include "Policies/Singleton.h" - -struct MemoryManager : public Trinity::Singleton < MemoryManager > -{ - MemoryManager(); -}; -#endif diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h new file mode 100644 index 00000000000..ba0240fb58b --- /dev/null +++ b/src/server/shared/Packets/ByteBuffer.h @@ -0,0 +1,601 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BYTEBUFFER_H +#define _BYTEBUFFER_H + +#include "Common.h" +#include "Errors.h" +#include "Log.h" +#include "Utilities/ByteConverter.h" + +class ByteBufferException +{ + public: + ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size) + : add(_add), pos(_pos), esize(_esize), size(_size) + { + PrintPosError(); + } + + void PrintPosError() const + { + sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") value with size: " SIZEFMTD, + (add ? "put" : "get"), pos, size, esize); + } + private: + bool add; + size_t pos; + size_t esize; + size_t size; +}; + +class ByteBuffer +{ + public: + const static size_t DEFAULT_SIZE = 0x1000; + + // constructor + ByteBuffer(): _rpos(0), _wpos(0) + { + _storage.reserve(DEFAULT_SIZE); + } + + // constructor + ByteBuffer(size_t res): _rpos(0), _wpos(0) + { + _storage.reserve(res); + } + + // copy constructor + ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { } + + void clear() + { + _storage.clear(); + _rpos = _wpos = 0; + } + + template void append(T value) + { + EndianConvert(value); + append((uint8 *)&value, sizeof(value)); + } + + template void put(size_t pos,T value) + { + EndianConvert(value); + put(pos,(uint8 *)&value,sizeof(value)); + } + + ByteBuffer &operator<<(uint8 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(uint16 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(uint32 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(uint64 value) + { + append(value); + return *this; + } + + // signed as in 2e complement + ByteBuffer &operator<<(int8 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(int16 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(int32 value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(int64 value) + { + append(value); + return *this; + } + + // floating points + ByteBuffer &operator<<(float value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(double value) + { + append(value); + return *this; + } + + ByteBuffer &operator<<(const std::string &value) + { + append((uint8 const *)value.c_str(), value.length()); + append((uint8)0); + return *this; + } + + ByteBuffer &operator<<(const char *str) + { + append((uint8 const *)str, str ? strlen(str) : 0); + append((uint8)0); + return *this; + } + + ByteBuffer &operator>>(bool &value) + { + value = read() > 0 ? true : false; + return *this; + } + + ByteBuffer &operator>>(uint8 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(uint16 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(uint32 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(uint64 &value) + { + value = read(); + return *this; + } + + //signed as in 2e complement + ByteBuffer &operator>>(int8 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(int16 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(int32 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(int64 &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(float &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(double &value) + { + value = read(); + return *this; + } + + ByteBuffer &operator>>(std::string& value) + { + value.clear(); + while (rpos() < size()) // prevent crash at wrong string format in packet + { + char c = read(); + if (c == 0) + break; + value += c; + } + return *this; + } + + uint8 operator[](size_t pos) const + { + return read(pos); + } + + size_t rpos() const { return _rpos; } + + size_t rpos(size_t rpos_) + { + _rpos = rpos_; + return _rpos; + } + + size_t wpos() const { return _wpos; } + + size_t wpos(size_t wpos_) + { + _wpos = wpos_; + return _wpos; + } + + template + void read_skip() { read_skip(sizeof(T)); } + + void read_skip(size_t skip) + { + if(_rpos + skip > size()) + throw ByteBufferException(false, _rpos, skip, size()); + _rpos += skip; + } + + template T read() + { + T r = read(_rpos); + _rpos += sizeof(T); + return r; + } + + template T read(size_t pos) const + { + if(pos + sizeof(T) > size()) + throw ByteBufferException(false, pos, sizeof(T), size()); + T val = *((T const*)&_storage[pos]); + EndianConvert(val); + return val; + } + + void read(uint8 *dest, size_t len) + { + if(_rpos + len > size()) + throw ByteBufferException(false, _rpos, len, size()); + memcpy(dest, &_storage[_rpos], len); + _rpos += len; + } + + bool readPackGUID(uint64& guid) + { + if(rpos() + 1 > size()) + return false; + + guid = 0; + + uint8 guidmark = 0; + (*this) >> guidmark; + + for (int i = 0; i < 8; ++i) + { + if(guidmark & (uint8(1) << i)) + { + if(rpos() + 1 > size()) + return false; + + uint8 bit; + (*this) >> bit; + guid |= (uint64(bit) << (i * 8)); + } + } + + return true; + } + + const uint8 *contents() const { return &_storage[0]; } + + size_t size() const { return _storage.size(); } + bool empty() const { return _storage.empty(); } + + void resize(size_t newsize) + { + _storage.resize(newsize); + _rpos = 0; + _wpos = size(); + } + + void reserve(size_t ressize) + { + if (ressize > size()) + _storage.reserve(ressize); + } + + void append(const std::string& str) + { + append((uint8 const*)str.c_str(), str.size() + 1); + } + + void append(const char *src, size_t cnt) + { + return append((const uint8 *)src, cnt); + } + + template void append(const T *src, size_t cnt) + { + return append((const uint8 *)src, cnt * sizeof(T)); + } + + void append(const uint8 *src, size_t cnt) + { + if (!cnt) + return; + + ASSERT(size() < 10000000); + + if (_storage.size() < _wpos + cnt) + _storage.resize(_wpos + cnt); + memcpy(&_storage[_wpos], src, cnt); + _wpos += cnt; + } + + void append(const ByteBuffer& buffer) + { + if(buffer.wpos()) + append(buffer.contents(), buffer.wpos()); + } + + // can be used in SMSG_MONSTER_MOVE opcode + void appendPackXYZ(float x, float y, float z) + { + uint32 packed = 0; + packed |= ((int)(x / 0.25f) & 0x7FF); + packed |= ((int)(y / 0.25f) & 0x7FF) << 11; + packed |= ((int)(z / 0.25f) & 0x3FF) << 22; + *this << packed; + } + + void appendPackGUID(uint64 guid) + { + uint8 packGUID[8+1]; + packGUID[0] = 0; + size_t size = 1; + for(uint8 i = 0;guid != 0;++i) + { + if(guid & 0xFF) + { + packGUID[0] |= uint8(1 << i); + packGUID[size] = uint8(guid & 0xFF); + ++size; + } + + guid >>= 8; + } + append(packGUID, size); + } + + void put(size_t pos, const uint8 *src, size_t cnt) + { + if(pos + cnt > size()) + throw ByteBufferException(true, pos, cnt, size()); + memcpy(&_storage[pos], src, cnt); + } + + void print_storage() const + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); + for (uint32 i = 0; i < size(); ++i) + sLog.outDebugInLine("%u - ", read(i) ); + sLog.outDebug(" "); + } + + void textlike() const + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); + for (uint32 i = 0; i < size(); ++i) + sLog.outDebugInLine("%c", read(i) ); + sLog.outDebug(" "); + } + + void hexlike() const + { + if(!sLog.IsOutDebug()) // optimize disabled debug output + return; + + uint32 j = 1, k = 1; + sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() ); + + for (uint32 i = 0; i < size(); ++i) + { + if ((i == (j * 8)) && ((i != (k * 16)))) + { + if (read(i) < 0x10) + { + sLog.outDebugInLine("| 0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("| %X ", read(i) ); + } + ++j; + } + else if (i == (k * 16)) + { + if (read(i) < 0x10) + { + sLog.outDebugInLine("\n"); + + sLog.outDebugInLine("0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("\n"); + + sLog.outDebugInLine("%X ", read(i) ); + } + + ++k; + ++j; + } + else + { + if (read(i) < 0x10) + { + sLog.outDebugInLine("0%X ", read(i) ); + } + else + { + sLog.outDebugInLine("%X ", read(i) ); + } + } + } + sLog.outDebugInLine("\n"); + } + + protected: + size_t _rpos, _wpos; + std::vector _storage; +}; + +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::vector v) +{ + b << (uint32)v.size(); + for (typename std::vector::iterator i = v.begin(); i != v.end(); ++i) + { + b << *i; + } + return b; +} + +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::vector &v) +{ + uint32 vsize; + b >> vsize; + v.clear(); + while(vsize--) + { + T t; + b >> t; + v.push_back(t); + } + return b; +} + +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::list v) +{ + b << (uint32)v.size(); + for (typename std::list::iterator i = v.begin(); i != v.end(); ++i) + { + b << *i; + } + return b; +} + +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::list &v) +{ + uint32 vsize; + b >> vsize; + v.clear(); + while(vsize--) + { + T t; + b >> t; + v.push_back(t); + } + return b; +} + +template +inline ByteBuffer &operator<<(ByteBuffer &b, std::map &m) +{ + b << (uint32)m.size(); + for (typename std::map::iterator i = m.begin(); i != m.end(); ++i) + { + b << i->first << i->second; + } + return b; +} + +template +inline ByteBuffer &operator>>(ByteBuffer &b, std::map &m) +{ + uint32 msize; + b >> msize; + m.clear(); + while(msize--) + { + K k; + V v; + b >> k >> v; + m.insert(make_pair(k, v)); + } + return b; +} + +// TODO: Make a ByteBuffer.cpp and move all this inlining to it. +template<> inline std::string ByteBuffer::read() +{ + std::string tmp; + *this >> tmp; + return tmp; +} + +template<> +inline void ByteBuffer::read_skip() +{ + std::string temp; + *this >> temp; +} + +template<> +inline void ByteBuffer::read_skip() +{ + read_skip(); +} + +template<> +inline void ByteBuffer::read_skip() +{ + read_skip(); +} +#endif + diff --git a/src/server/shared/Packets/WorldPacket.h b/src/server/shared/Packets/WorldPacket.h new file mode 100644 index 00000000000..d708959f91d --- /dev/null +++ b/src/server/shared/Packets/WorldPacket.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYCORE_WORLDPACKET_H +#define TRINITYCORE_WORLDPACKET_H + +#include "Common.h" +#include "ByteBuffer.h" + +class WorldPacket : public ByteBuffer +{ + public: + // just container for later use + WorldPacket() : ByteBuffer(0), m_opcode(0) + { + } + explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { } + // copy constructor + WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) + { + } + + void Initialize(uint16 opcode, size_t newres=200) + { + clear(); + _storage.reserve(newres); + m_opcode = opcode; + } + + uint16 GetOpcode() const { return m_opcode; } + void SetOpcode(uint16 opcode) { m_opcode = opcode; } + + protected: + uint16 m_opcode; +}; +#endif + diff --git a/src/server/shared/ProgressBar.cpp b/src/server/shared/ProgressBar.cpp deleted file mode 100644 index c24d9f86f6b..00000000000 --- a/src/server/shared/ProgressBar.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "ProgressBar.h" - -char const* const barGoLink::empty = " "; -#ifdef _WIN32 -char const* const barGoLink::full = "\x3D"; -#else -char const* const barGoLink::full = "*"; -#endif - -barGoLink::~barGoLink() -{ - printf( "\n" ); - fflush(stdout); -} - -barGoLink::barGoLink( int row_count ) -{ - rec_no = 0; - rec_pos = 0; - indic_len = 50; - num_rec = row_count; - #ifdef _WIN32 - printf( "\x3D" ); - #else - printf( "[" ); - #endif - for (int i = 0; i < indic_len; i++ ) printf( empty ); - #ifdef _WIN32 - printf( "\x3D 0%%\r\x3D" ); - #else - printf( "] 0%%\r[" ); - #endif - fflush(stdout); -} - -void barGoLink::step( void ) -{ - int i, n; - - if ( num_rec == 0 ) return; - ++rec_no; - n = rec_no * indic_len / num_rec; - if ( n != rec_pos ) - { - #ifdef _WIN32 - printf( "\r\x3D" ); - #else - printf( "\r[" ); - #endif - for (i = 0; i < n; i++ ) printf( full ); - for (; i < indic_len; i++ ) printf( empty ); - float percent = (((float)n/(float)indic_len)*100); - #ifdef _WIN32 - printf( "\x3D %i%% \r\x3D", (int)percent); - #else - printf( "] %i%% \r[", (int)percent); - #endif - fflush(stdout); - - rec_pos = n; - } -} - diff --git a/src/server/shared/ProgressBar.h b/src/server/shared/ProgressBar.h deleted file mode 100644 index e7565590278..00000000000 --- a/src/server/shared/ProgressBar.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef TRINITYCORE_PROGRESSBAR_H -#define TRINITYCORE_PROGRESSBAR_H - -#include "Platform/Define.h" - -class barGoLink -{ - static char const * const empty; - static char const * const full; - - int rec_no; - int rec_pos; - int num_rec; - int indic_len; - - public: - - void step( void ); - barGoLink( int ); - ~barGoLink(); -}; -#endif - diff --git a/src/server/shared/ServiceWin32.cpp b/src/server/shared/ServiceWin32.cpp deleted file mode 100644 index 2c1df2ff483..00000000000 --- a/src/server/shared/ServiceWin32.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef WIN32 - -#include "Common.h" -#include "Log.h" -#include -#include -#include - -#if !defined(WINADVAPI) -#if !defined(_ADVAPI32_) -#define WINADVAPI DECLSPEC_IMPORT -#else -#define WINADVAPI -#endif -#endif - -extern int main(int argc, char ** argv); -extern char serviceLongName[]; -extern char serviceName[]; -extern char serviceDescription[]; - -extern int m_ServiceStatus; - -SERVICE_STATUS serviceStatus; - -SERVICE_STATUS_HANDLE serviceStatusHandle = 0; - -typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID); - -bool WinServiceInstall() -{ - CSD_T ChangeService_Config2; - HMODULE advapi32; - SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); - - if (serviceControlManager) - { - char path[_MAX_PATH + 10]; - if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0) - { - SC_HANDLE service; - std::strcat(path, " --service"); - service = CreateService(serviceControlManager, - serviceName, // name of service - serviceLongName, // service name to display - SERVICE_ALL_ACCESS, // desired access - // service type - SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, - SERVICE_AUTO_START, // start type - SERVICE_ERROR_IGNORE, // error control type - path, // service's binary - 0, // no load ordering group - 0, // no tag identifier - 0, // no dependencies - 0, // LocalSystem account - 0); // no password - if (service) - { - advapi32 = GetModuleHandle("ADVAPI32.DLL"); - if(!advapi32) - { - CloseServiceHandle(service); - CloseServiceHandle(serviceControlManager); - return false; - } - - ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A"); - if (!ChangeService_Config2) - { - CloseServiceHandle(service); - CloseServiceHandle(serviceControlManager); - return false; - } - - SERVICE_DESCRIPTION sdBuf; - sdBuf.lpDescription = serviceDescription; - ChangeService_Config2( - service, // handle to service - SERVICE_CONFIG_DESCRIPTION, // change: description - &sdBuf); // new data - - SC_ACTION _action[1]; - _action[0].Type = SC_ACTION_RESTART; - _action[0].Delay = 10000; - SERVICE_FAILURE_ACTIONS sfa; - ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS)); - sfa.lpsaActions = _action; - sfa.cActions = 1; - sfa.dwResetPeriod =INFINITE; - ChangeService_Config2( - service, // handle to service - SERVICE_CONFIG_FAILURE_ACTIONS, // information level - &sfa); // new data - - CloseServiceHandle(service); - - } - } - CloseServiceHandle(serviceControlManager); - } - return true; -} - -bool WinServiceUninstall() -{ - SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); - - if (serviceControlManager) - { - SC_HANDLE service = OpenService(serviceControlManager, - serviceName, SERVICE_QUERY_STATUS | DELETE); - if (service) - { - SERVICE_STATUS serviceStatus2; - if (QueryServiceStatus(service, &serviceStatus2)) - { - if (serviceStatus2.dwCurrentState == SERVICE_STOPPED) - DeleteService(service); - } - CloseServiceHandle(service); - } - - CloseServiceHandle(serviceControlManager); - } - return true; -} - -void WINAPI ServiceControlHandler(DWORD controlCode) -{ - switch (controlCode) - { - case SERVICE_CONTROL_INTERROGATE: - break; - - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - - m_ServiceStatus = 0; - return; - - case SERVICE_CONTROL_PAUSE: - m_ServiceStatus = 2; - serviceStatus.dwCurrentState = SERVICE_PAUSED; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - break; - - case SERVICE_CONTROL_CONTINUE: - serviceStatus.dwCurrentState = SERVICE_RUNNING; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - m_ServiceStatus = 1; - break; - - default: - if ( controlCode >= 128 && controlCode <= 255 ) - // user defined control code - break; - else - // unrecognized control code - break; - } - - SetServiceStatus(serviceStatusHandle, &serviceStatus); -} - -void WINAPI ServiceMain(DWORD argc, char *argv[]) -{ - // initialise service status - serviceStatus.dwServiceType = SERVICE_WIN32; - serviceStatus.dwCurrentState = SERVICE_START_PENDING; - serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; - serviceStatus.dwWin32ExitCode = NO_ERROR; - serviceStatus.dwServiceSpecificExitCode = NO_ERROR; - serviceStatus.dwCheckPoint = 0; - serviceStatus.dwWaitHint = 0; - - serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler); - - if ( serviceStatusHandle ) - { - char path[_MAX_PATH + 1]; - unsigned int i, last_slash = 0; - - GetModuleFileName(0, path, sizeof(path)/sizeof(path[0])); - - for (i = 0; i < std::strlen(path); i++) - { - if (path[i] == '\\') last_slash = i; - } - - path[last_slash] = 0; - - // service is starting - serviceStatus.dwCurrentState = SERVICE_START_PENDING; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - - // do initialisation here - SetCurrentDirectory(path); - - // running - serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); - serviceStatus.dwCurrentState = SERVICE_RUNNING; - SetServiceStatus( serviceStatusHandle, &serviceStatus ); - - //////////////////////// - // service main cycle // - //////////////////////// - - m_ServiceStatus = 1; - argc = 1; - main(argc , argv); - - // service was stopped - serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - - // do cleanup here - - // service is now stopped - serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); - serviceStatus.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus(serviceStatusHandle, &serviceStatus); - } -} - -bool WinServiceRun() -{ - SERVICE_TABLE_ENTRY serviceTable[] = - { - { serviceName, ServiceMain }, - { 0, 0 } - }; - - if (!StartServiceCtrlDispatcher(serviceTable)) - { - sLog.outError("StartService Failed. Error [%u]", ::GetLastError()); - return false; - } - return true; -} -#endif - diff --git a/src/server/shared/ServiceWin32.h b/src/server/shared/ServiceWin32.h deleted file mode 100644 index ddac785a0fb..00000000000 --- a/src/server/shared/ServiceWin32.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef WIN32 -#ifndef _WIN32_SERVICE_ -#define _WIN32_SERVICE_ - -bool WinServiceInstall(); -bool WinServiceUninstall(); -bool WinServiceRun(); - -#endif // _WIN32_SERVICE_ -#endif // WIN32 - diff --git a/src/server/shared/SignalHandler.h b/src/server/shared/SignalHandler.h deleted file mode 100644 index 0c4d8143c41..00000000000 --- a/src/server/shared/SignalHandler.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __SIGNAL_HANDLER_H__ -#define __SIGNAL_HANDLER_H__ - -#include - -namespace Trinity -{ - -/// Handle termination signals -class SignalHandler : public ACE_Event_Handler -{ - public: - int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL) - { - HandleSignal(SigNum); - return 0; - } - virtual void HandleSignal(int SigNum) {}; -}; - -} - -#endif /* __SIGNAL_HANDLER_H__ */ diff --git a/src/server/shared/Threading.cpp b/src/server/shared/Threading.cpp deleted file mode 100644 index 3938286dbdb..00000000000 --- a/src/server/shared/Threading.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Threading.h" -#include "Errors.h" -#include -#include -#include - -using namespace ACE_Based; - -ThreadPriority::ThreadPriority() -{ - for (int i = Idle; i < MAXPRIORITYNUM; ++i) - m_priority[i] = ACE_THR_PRI_OTHER_DEF; - - m_priority[Idle] = ACE_Sched_Params::priority_min(ACE_SCHED_OTHER); - m_priority[Realtime] = ACE_Sched_Params::priority_max(ACE_SCHED_OTHER); - - std::vector _tmp; - - ACE_Sched_Params::Policy _policy = ACE_SCHED_OTHER; - ACE_Sched_Priority_Iterator pr_iter(_policy); - - while (pr_iter.more()) - { - _tmp.push_back(pr_iter.priority()); - pr_iter.next(); - } - - ASSERT (!_tmp.empty()); - - if(_tmp.size() >= MAXPRIORITYNUM) - { - const size_t max_pos = _tmp.size(); - size_t min_pos = 1; - size_t norm_pos = 0; - for (size_t i = 0; i < max_pos; ++i) - { - if(_tmp[i] == ACE_THR_PRI_OTHER_DEF) - { - norm_pos = i + 1; - break; - } - } - - //since we have only 7(seven) values in enum Priority - //and 3 we know already (Idle, Normal, Realtime) so - //we need to split each list [Idle...Normal] and [Normal...Realtime] - //into ¹ piesces - const size_t _divider = 4; - size_t _div = (norm_pos - min_pos) / _divider; - if(_div == 0) - _div = 1; - - min_pos = (norm_pos - 1); - - m_priority[Low] = _tmp[min_pos -= _div]; - m_priority[Lowest] = _tmp[min_pos -= _div ]; - - _div = (max_pos - norm_pos) / _divider; - if(_div == 0) - _div = 1; - - min_pos = norm_pos - 1; - - m_priority[High] = _tmp[min_pos += _div]; - m_priority[Highest] = _tmp[min_pos += _div]; - } -} - -int ThreadPriority::getPriority(Priority p) const -{ - if(p < Idle) - p = Idle; - - if(p > Realtime) - p = Realtime; - - return m_priority[p]; -} - -#define THREADFLAG (THR_NEW_LWP | THR_SCHED_DEFAULT| THR_JOINABLE) - -Thread::Thread() : m_task(0), m_iThreadId(0), m_hThreadHandle(0) -{ - -} - -Thread::Thread(Runnable* instance) : m_task(instance), m_iThreadId(0), m_hThreadHandle(0) -{ - // register reference to m_task to prevent it deeltion until destructor - if (m_task) - m_task->incReference(); - - bool _start = start(); - ASSERT (_start); -} - -Thread::~Thread() -{ - //Wait(); - - // deleted runnable object (if no other references) - if (m_task) - m_task->decReference(); -} - -//initialize Thread's class static member -Thread::ThreadStorage Thread::m_ThreadStorage; -ThreadPriority Thread::m_TpEnum; - -bool Thread::start() -{ - if (m_task == 0 || m_iThreadId != 0) - return false; - - bool res = (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0); - - if (res) - m_task->incReference(); - - return res; -} - -bool Thread::wait() -{ - if (!m_hThreadHandle || !m_task) - return false; - - ACE_THR_FUNC_RETURN _value = ACE_THR_FUNC_RETURN(-1); - int _res = ACE_Thread::join(m_hThreadHandle, &_value); - - m_iThreadId = 0; - m_hThreadHandle = 0; - - return (_res == 0); -} - -void Thread::destroy() -{ - if (!m_iThreadId || !m_task) - return; - - if (ACE_Thread::kill(m_iThreadId, -1) != 0) - return; - - m_iThreadId = 0; - m_hThreadHandle = 0; - - // reference set at ACE_Thread::spawn - m_task->decReference(); -} - -void Thread::suspend() -{ - ACE_Thread::suspend(m_hThreadHandle); -} - -void Thread::resume() -{ - ACE_Thread::resume(m_hThreadHandle); -} - -ACE_THR_FUNC_RETURN Thread::ThreadTask(void * param) -{ - Runnable * _task = (Runnable*)param; - _task->run(); - - // task execution complete, free referecne added at - _task->decReference(); - - return (ACE_THR_FUNC_RETURN)0; -} - -ACE_thread_t Thread::currentId() -{ - return ACE_Thread::self(); -} - -ACE_hthread_t Thread::currentHandle() -{ - ACE_hthread_t _handle; - ACE_Thread::self(_handle); - - return _handle; -} - -Thread * Thread::current() -{ - Thread * _thread = m_ThreadStorage.ts_object(); - if(!_thread) - { - _thread = new Thread(); - _thread->m_iThreadId = Thread::currentId(); - _thread->m_hThreadHandle = Thread::currentHandle(); - - Thread * _oldValue = m_ThreadStorage.ts_object(_thread); - if(_oldValue) - delete _oldValue; - } - - return _thread; -} - -void Thread::setPriority(Priority type) -{ - int _priority = m_TpEnum.getPriority(type); - int _ok = ACE_Thread::setprio(m_hThreadHandle, _priority); - //remove this ASSERT in case you don't want to know is thread priority change was successful or not - ASSERT (_ok == 0); -} - -void Thread::Sleep(unsigned long msecs) -{ - ACE_OS::sleep(ACE_Time_Value(0, 1000 * msecs)); -} diff --git a/src/server/shared/Threading.h b/src/server/shared/Threading.h deleted file mode 100644 index fa046117c6e..00000000000 --- a/src/server/shared/Threading.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef THREADING_H -#define THREADING_H - -#include -#include -#include "ace/Atomic_Op.h" -#include - -namespace ACE_Based -{ - - class Runnable - { - public: - virtual ~Runnable() {} - virtual void run() = 0; - - void incReference() { ++m_refs; } - void decReference() - { - if(!--m_refs) - delete this; - } - private: - ACE_Atomic_Op m_refs; - }; - - enum Priority - { - Idle, - Lowest, - Low, - Normal, - High, - Highest, - Realtime, - }; - -#define MAXPRIORITYNUM (Realtime + 1) - - class ThreadPriority - { - public: - ThreadPriority(); - int getPriority(Priority p) const; - - private: - int m_priority[MAXPRIORITYNUM]; - }; - - class Thread - { - public: - Thread(); - explicit Thread(Runnable* instance); - ~Thread(); - - bool start(); - bool wait(); - void destroy(); - - void suspend(); - void resume(); - - void setPriority(Priority type); - - static void Sleep(unsigned long msecs); - static ACE_thread_t currentId(); - static ACE_hthread_t currentHandle(); - static Thread * current(); - - private: - Thread(const Thread&); - Thread& operator=(const Thread&); - - static ACE_THR_FUNC_RETURN ThreadTask(void * param); - - ACE_thread_t m_iThreadId; - ACE_hthread_t m_hThreadHandle; - Runnable * m_task; - - typedef ACE_TSS ThreadStorage; - //global object - container for Thread class representation of every thread - static ThreadStorage m_ThreadStorage; - //use this object to determine current OS thread priority values mapped to enum Priority{} - static ThreadPriority m_TpEnum; - }; - -} -#endif diff --git a/src/server/shared/Threading/DelayExecutor.cpp b/src/server/shared/Threading/DelayExecutor.cpp new file mode 100644 index 00000000000..9a718823232 --- /dev/null +++ b/src/server/shared/Threading/DelayExecutor.cpp @@ -0,0 +1,111 @@ +#include +#include +#include + +#include "DelayExecutor.h" + +DelayExecutor* DelayExecutor::instance() +{ + return ACE_Singleton::instance(); +} + +DelayExecutor::DelayExecutor() + : activated_(false), pre_svc_hook_(0), post_svc_hook_(0) +{ +} + +DelayExecutor::~DelayExecutor() +{ + if (pre_svc_hook_) + delete pre_svc_hook_; + + if (post_svc_hook_) + delete post_svc_hook_; + + deactivate(); +} + +int DelayExecutor::deactivate() +{ + if (!activated()) + return -1; + + activated(false); + queue_.queue()->deactivate(); + wait(); + + return 0; +} + +int DelayExecutor::svc() +{ + if (pre_svc_hook_) + pre_svc_hook_->call(); + + for (;;) + { + ACE_Method_Request* rq = queue_.dequeue(); + + if (!rq) + break; + + rq->call(); + delete rq; + } + + if (post_svc_hook_) + post_svc_hook_->call(); + + return 0; +} + +int DelayExecutor::activate(int num_threads, ACE_Method_Request* pre_svc_hook, ACE_Method_Request* post_svc_hook) +{ + if (activated()) + return -1; + + if (num_threads < 1) + return -1; + + if (pre_svc_hook_) + delete pre_svc_hook_; + + if (post_svc_hook_) + delete post_svc_hook_; + + pre_svc_hook_ = pre_svc_hook; + post_svc_hook_ = post_svc_hook; + + queue_.queue()->activate(); + + if (ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, num_threads) == -1) + return -1; + + activated(true); + + return true; +} + +int DelayExecutor::execute(ACE_Method_Request* new_req) +{ + if (new_req == NULL) + return -1; + + if (queue_.enqueue(new_req, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) + { + delete new_req; + ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%t) %p\n"), ACE_TEXT("DelayExecutor::execute enqueue")), -1); + } + + return 0; +} + +bool DelayExecutor::activated() +{ + return activated_; +} + +void DelayExecutor::activated(bool s) +{ + activated_ = s; +} diff --git a/src/server/shared/Threading/DelayExecutor.h b/src/server/shared/Threading/DelayExecutor.h new file mode 100644 index 00000000000..664d8ca78a2 --- /dev/null +++ b/src/server/shared/Threading/DelayExecutor.h @@ -0,0 +1,37 @@ +#ifndef _M_DELAY_EXECUTOR_H +#define _M_DELAY_EXECUTOR_H + +#include +#include +#include + +class DelayExecutor : protected ACE_Task_Base +{ + public: + + DelayExecutor(); + virtual ~DelayExecutor(); + + static DelayExecutor* instance(); + + int execute(ACE_Method_Request* new_req); + + int activate(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL); + + int deactivate(); + + bool activated(); + + virtual int svc(); + + private: + + ACE_Activation_Queue queue_; + ACE_Method_Request* pre_svc_hook_; + ACE_Method_Request* post_svc_hook_; + bool activated_; + + void activated(bool s); +}; + +#endif // _M_DELAY_EXECUTOR_H diff --git a/src/server/shared/Threading/LockedQueue.h b/src/server/shared/Threading/LockedQueue.h new file mode 100644 index 00000000000..9f8afae6c14 --- /dev/null +++ b/src/server/shared/Threading/LockedQueue.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef LOCKEDQUEUE_H +#define LOCKEDQUEUE_H + +#include +#include +#include +#include +#include "Errors.h" + +namespace ACE_Based +{ + template > + class LockedQueue + { + //! Lock access to the queue. + LockType _lock; + + //! Storage backing the queue. + StorageType _queue; + + //! Cancellation flag. + volatile bool _canceled; + + public: + + //! Create a LockedQueue. + LockedQueue() + : _canceled(false) + { + } + + //! Destroy a LockedQueue. + virtual ~LockedQueue() + { + } + + //! Adds an item to the queue. + void add(const T& item) + { + lock(); + + //ASSERT(!this->_canceled); + // throw Cancellation_Exception(); + + _queue.push_back(item); + + unlock(); + } + + //! Gets the next result in the queue, if any. + bool next(T& result) + { + // ACE_Guard g(this->_lock); + ACE_GUARD_RETURN (LockType, g, this->_lock, false); + + if (_queue.empty()) + return false; + + //ASSERT (!_queue.empty() || !this->_canceled); + // throw Cancellation_Exception(); + result = _queue.front(); + _queue.pop_front(); + + return true; + } + + //! Peeks at the top of the queue. Remember to unlock after use. + T& peek() + { + lock(); + + T& result = _queue.front(); + + return result; + } + + //! Cancels the queue. + void cancel() + { + lock(); + + _canceled = true; + + unlock(); + } + + //! Checks if the queue is cancelled. + bool cancelled() + { + ACE_Guard g(this->_lock); + return _canceled; + } + + //! Locks the queue for access. + void lock() + { + this->_lock.acquire(); + } + + //! Unlocks the queue. + void unlock() + { + this->_lock.release(); + } + + ///! Calls pop_front of the queue + void pop_front() + { + ACE_GUARD (LockType, g, this->_lock); + _queue.pop_front(); + } + + ///! Checks if we're empty or not with locks held + bool empty() + { + ACE_GUARD_RETURN (LockType, g, this->_lock, false); + return _queue.empty(); + } + }; +} +#endif diff --git a/src/server/shared/Threading/Threading.cpp b/src/server/shared/Threading/Threading.cpp new file mode 100644 index 00000000000..3938286dbdb --- /dev/null +++ b/src/server/shared/Threading/Threading.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Threading.h" +#include "Errors.h" +#include +#include +#include + +using namespace ACE_Based; + +ThreadPriority::ThreadPriority() +{ + for (int i = Idle; i < MAXPRIORITYNUM; ++i) + m_priority[i] = ACE_THR_PRI_OTHER_DEF; + + m_priority[Idle] = ACE_Sched_Params::priority_min(ACE_SCHED_OTHER); + m_priority[Realtime] = ACE_Sched_Params::priority_max(ACE_SCHED_OTHER); + + std::vector _tmp; + + ACE_Sched_Params::Policy _policy = ACE_SCHED_OTHER; + ACE_Sched_Priority_Iterator pr_iter(_policy); + + while (pr_iter.more()) + { + _tmp.push_back(pr_iter.priority()); + pr_iter.next(); + } + + ASSERT (!_tmp.empty()); + + if(_tmp.size() >= MAXPRIORITYNUM) + { + const size_t max_pos = _tmp.size(); + size_t min_pos = 1; + size_t norm_pos = 0; + for (size_t i = 0; i < max_pos; ++i) + { + if(_tmp[i] == ACE_THR_PRI_OTHER_DEF) + { + norm_pos = i + 1; + break; + } + } + + //since we have only 7(seven) values in enum Priority + //and 3 we know already (Idle, Normal, Realtime) so + //we need to split each list [Idle...Normal] and [Normal...Realtime] + //into ¹ piesces + const size_t _divider = 4; + size_t _div = (norm_pos - min_pos) / _divider; + if(_div == 0) + _div = 1; + + min_pos = (norm_pos - 1); + + m_priority[Low] = _tmp[min_pos -= _div]; + m_priority[Lowest] = _tmp[min_pos -= _div ]; + + _div = (max_pos - norm_pos) / _divider; + if(_div == 0) + _div = 1; + + min_pos = norm_pos - 1; + + m_priority[High] = _tmp[min_pos += _div]; + m_priority[Highest] = _tmp[min_pos += _div]; + } +} + +int ThreadPriority::getPriority(Priority p) const +{ + if(p < Idle) + p = Idle; + + if(p > Realtime) + p = Realtime; + + return m_priority[p]; +} + +#define THREADFLAG (THR_NEW_LWP | THR_SCHED_DEFAULT| THR_JOINABLE) + +Thread::Thread() : m_task(0), m_iThreadId(0), m_hThreadHandle(0) +{ + +} + +Thread::Thread(Runnable* instance) : m_task(instance), m_iThreadId(0), m_hThreadHandle(0) +{ + // register reference to m_task to prevent it deeltion until destructor + if (m_task) + m_task->incReference(); + + bool _start = start(); + ASSERT (_start); +} + +Thread::~Thread() +{ + //Wait(); + + // deleted runnable object (if no other references) + if (m_task) + m_task->decReference(); +} + +//initialize Thread's class static member +Thread::ThreadStorage Thread::m_ThreadStorage; +ThreadPriority Thread::m_TpEnum; + +bool Thread::start() +{ + if (m_task == 0 || m_iThreadId != 0) + return false; + + bool res = (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0); + + if (res) + m_task->incReference(); + + return res; +} + +bool Thread::wait() +{ + if (!m_hThreadHandle || !m_task) + return false; + + ACE_THR_FUNC_RETURN _value = ACE_THR_FUNC_RETURN(-1); + int _res = ACE_Thread::join(m_hThreadHandle, &_value); + + m_iThreadId = 0; + m_hThreadHandle = 0; + + return (_res == 0); +} + +void Thread::destroy() +{ + if (!m_iThreadId || !m_task) + return; + + if (ACE_Thread::kill(m_iThreadId, -1) != 0) + return; + + m_iThreadId = 0; + m_hThreadHandle = 0; + + // reference set at ACE_Thread::spawn + m_task->decReference(); +} + +void Thread::suspend() +{ + ACE_Thread::suspend(m_hThreadHandle); +} + +void Thread::resume() +{ + ACE_Thread::resume(m_hThreadHandle); +} + +ACE_THR_FUNC_RETURN Thread::ThreadTask(void * param) +{ + Runnable * _task = (Runnable*)param; + _task->run(); + + // task execution complete, free referecne added at + _task->decReference(); + + return (ACE_THR_FUNC_RETURN)0; +} + +ACE_thread_t Thread::currentId() +{ + return ACE_Thread::self(); +} + +ACE_hthread_t Thread::currentHandle() +{ + ACE_hthread_t _handle; + ACE_Thread::self(_handle); + + return _handle; +} + +Thread * Thread::current() +{ + Thread * _thread = m_ThreadStorage.ts_object(); + if(!_thread) + { + _thread = new Thread(); + _thread->m_iThreadId = Thread::currentId(); + _thread->m_hThreadHandle = Thread::currentHandle(); + + Thread * _oldValue = m_ThreadStorage.ts_object(_thread); + if(_oldValue) + delete _oldValue; + } + + return _thread; +} + +void Thread::setPriority(Priority type) +{ + int _priority = m_TpEnum.getPriority(type); + int _ok = ACE_Thread::setprio(m_hThreadHandle, _priority); + //remove this ASSERT in case you don't want to know is thread priority change was successful or not + ASSERT (_ok == 0); +} + +void Thread::Sleep(unsigned long msecs) +{ + ACE_OS::sleep(ACE_Time_Value(0, 1000 * msecs)); +} diff --git a/src/server/shared/Threading/Threading.h b/src/server/shared/Threading/Threading.h new file mode 100644 index 00000000000..fa046117c6e --- /dev/null +++ b/src/server/shared/Threading/Threading.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef THREADING_H +#define THREADING_H + +#include +#include +#include "ace/Atomic_Op.h" +#include + +namespace ACE_Based +{ + + class Runnable + { + public: + virtual ~Runnable() {} + virtual void run() = 0; + + void incReference() { ++m_refs; } + void decReference() + { + if(!--m_refs) + delete this; + } + private: + ACE_Atomic_Op m_refs; + }; + + enum Priority + { + Idle, + Lowest, + Low, + Normal, + High, + Highest, + Realtime, + }; + +#define MAXPRIORITYNUM (Realtime + 1) + + class ThreadPriority + { + public: + ThreadPriority(); + int getPriority(Priority p) const; + + private: + int m_priority[MAXPRIORITYNUM]; + }; + + class Thread + { + public: + Thread(); + explicit Thread(Runnable* instance); + ~Thread(); + + bool start(); + bool wait(); + void destroy(); + + void suspend(); + void resume(); + + void setPriority(Priority type); + + static void Sleep(unsigned long msecs); + static ACE_thread_t currentId(); + static ACE_hthread_t currentHandle(); + static Thread * current(); + + private: + Thread(const Thread&); + Thread& operator=(const Thread&); + + static ACE_THR_FUNC_RETURN ThreadTask(void * param); + + ACE_thread_t m_iThreadId; + ACE_hthread_t m_hThreadHandle; + Runnable * m_task; + + typedef ACE_TSS ThreadStorage; + //global object - container for Thread class representation of every thread + static ThreadStorage m_ThreadStorage; + //use this object to determine current OS thread priority values mapped to enum Priority{} + static ThreadPriority m_TpEnum; + }; + +} +#endif diff --git a/src/server/shared/Timer.h b/src/server/shared/Timer.h deleted file mode 100644 index 3e0a369b655..00000000000 --- a/src/server/shared/Timer.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_TIMER_H -#define TRINITY_TIMER_H - -#include "Platform/CompilerDefs.h" - -#if PLATFORM == PLATFORM_WINDOWS -# include -# include -# include -#else -# if defined(__APPLE_CC__) -# include -# endif -# include -# include -#endif - -#if PLATFORM == PLATFORM_WINDOWS -inline uint32 getMSTime() { return GetTickCount(); } -#else -inline uint32 getMSTime() -{ - struct timeval tv; - struct timezone tz; - gettimeofday( &tv, &tz ); - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); -} -#endif - -inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime) -{ - // getMSTime() have limited data range and this is case when it overflow in this tick - if (oldMSTime > newMSTime) - return (0xFFFFFFFF - oldMSTime) + newMSTime; - else - return newMSTime - oldMSTime; -} - -struct IntervalTimer -{ - public: - - IntervalTimer() - : _interval(0), _current(0) - { - } - - void Update(time_t diff) - { - _current += diff; - if (_current < 0) - _current = 0; - } - - bool Passed() - { - return _current >= _interval; - } - - void Reset() - { - if (_current >= _interval) - _current -= _interval; - } - - void SetCurrent(time_t current) - { - _current = current; - } - - void SetInterval(time_t interval) - { - _interval = interval; - } - - time_t GetInterval() const - { - return _interval; - } - - time_t GetCurrent() const - { - return _current; - } - - private: - - time_t _interval; - time_t _current; -}; - -struct TimeTracker -{ - public: - - TimeTracker(time_t expiry) - : i_expiryTime(expiry) - { - } - - void Update(time_t diff) - { - i_expiryTime -= diff; - } - - bool Passed() const - { - return i_expiryTime <= 0; - } - - void Reset(time_t interval) - { - i_expiryTime = interval; - } - - time_t GetExpiry() const - { - return i_expiryTime; - } - - private: - - time_t i_expiryTime; -}; - -struct TimeTrackerSmall -{ - public: - - TimeTrackerSmall(uint32 expiry) - : i_expiryTime(expiry) - { - } - - void Update(int32 diff) - { - i_expiryTime -= diff; - } - - bool Passed() const - { - return i_expiryTime <= 0; - } - - void Reset(uint32 interval) - { - i_expiryTime = interval; - } - - int32 GetExpiry() const - { - return i_expiryTime; - } - - private: - - int32 i_expiryTime; -}; - -struct PeriodicTimer -{ - public: - - PeriodicTimer(int32 period, int32 start_time) - : i_expireTime(start_time), i_period(period) - { - } - - bool Update(const uint32 &diff) - { - if ((i_expireTime -= diff) > 0) - return false; - - i_expireTime += i_period > diff ? i_period : diff; - return true; - } - - void SetPeriodic(int32 period, int32 start_time) - { - i_expireTime = start_time; - i_period = period; - } - - // Tracker interface - void TUpdate(int32 diff) { i_expireTime -= diff; } - bool TPassed() const { return i_expireTime <= 0; } - void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; } - - private: - - int32 i_period; - int32 i_expireTime; -}; - -#endif diff --git a/src/server/shared/Util.cpp b/src/server/shared/Util.cpp deleted file mode 100644 index a3c017fdbfd..00000000000 --- a/src/server/shared/Util.cpp +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Util.h" - -#include "sockets/socket_include.h" -#include "utf8cpp/utf8.h" -#include "mersennetwister/MersenneTwister.h" -#include - -typedef ACE_TSS MTRandTSS; -static MTRandTSS mtRand; - -int32 irand (int32 min, int32 max) -{ - return int32 (mtRand->randInt (max - min)) + min; -} - -uint32 urand (uint32 min, uint32 max) -{ - return mtRand->randInt (max - min) + min; -} - -int32 rand32 () -{ - return mtRand->randInt (); -} - -double rand_norm(void) -{ - return mtRand->randExc (); -} - -double rand_chance (void) -{ - return mtRand->randExc (100.0); -} - -Tokens StrSplit(const std::string &src, const std::string &sep) -{ - Tokens r; - std::string s; - for (std::string::const_iterator i = src.begin(); i != src.end(); i++) - { - if (sep.find(*i) != std::string::npos) - { - if (s.length()) r.push_back(s); - s = ""; - } - else - { - s += *i; - } - } - if (s.length()) r.push_back(s); - return r; -} - -void stripLineInvisibleChars(std::string &str) -{ - static std::string invChars = " \t\7\n"; - - size_t wpos = 0; - - bool space = false; - for (size_t pos = 0; pos < str.size(); ++pos) - { - if(invChars.find(str[pos])!=std::string::npos) - { - if(!space) - { - str[wpos++] = ' '; - space = true; - } - } - else - { - if(wpos!=pos) - str[wpos++] = str[pos]; - else - ++wpos; - space = false; - } - } - - if(wpos < str.size()) - str.erase(wpos,str.size()); - if(str.find("|TInterface")!=std::string::npos) - str.clear(); - -} - -std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly) -{ - uint32 secs = timeInSecs % MINUTE; - uint32 minutes = timeInSecs % HOUR / MINUTE; - uint32 hours = timeInSecs % DAY / HOUR; - uint32 days = timeInSecs / DAY; - - std::ostringstream ss; - if(days) - ss << days << (shortText ? "d" : " Day(s) "); - if(hours || hoursOnly) - ss << hours << (shortText ? "h" : " Hour(s) "); - if(!hoursOnly) - { - if(minutes) - ss << minutes << (shortText ? "m" : " Minute(s) "); - if(secs || (!days && !hours && !minutes) ) - ss << secs << (shortText ? "s" : " Second(s)."); - } - - return ss.str(); -} - -uint32 TimeStringToSecs(const std::string& timestring) -{ - uint32 secs = 0; - uint32 buffer = 0; - uint32 multiplier = 0; - - for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); itr++ ) - { - if(isdigit(*itr)) - { - buffer*=10; - buffer+= (*itr)-'0'; - } - else - { - switch(*itr) - { - case 'd': multiplier = DAY; break; - case 'h': multiplier = HOUR; break; - case 'm': multiplier = MINUTE; break; - case 's': multiplier = 1; break; - default : return 0; //bad format - } - buffer*=multiplier; - secs+=buffer; - buffer=0; - } - } - - return secs; -} - -std::string TimeToTimestampStr(time_t t) -{ - tm* aTm = localtime(&t); - // YYYY year - // MM month (2 digits 01-12) - // DD day (2 digits 01-31) - // HH hour (2 digits 00-23) - // MM minutes (2 digits 00-59) - // SS seconds (2 digits 00-59) - char buf[20]; - snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); - return std::string(buf); -} - -/// Check if the string is a valid ip address representation -bool IsIPAddress(char const* ipaddress) -{ - if(!ipaddress) - return false; - - // Let the big boys do it. - // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD) - return inet_addr(ipaddress) != INADDR_NONE; -} - -/// create PID file -uint32 CreatePIDFile(const std::string& filename) -{ - FILE * pid_file = fopen (filename.c_str(), "w" ); - if (pid_file == NULL) - return 0; - -#ifdef WIN32 - DWORD pid = GetCurrentProcessId(); -#else - pid_t pid = getpid(); -#endif - - fprintf(pid_file, "%d", pid ); - fclose(pid_file); - - return (uint32)pid; -} - -size_t utf8length(std::string& utf8str) -{ - try - { - return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); - } - catch(std::exception) - { - utf8str = ""; - return 0; - } -} - -void utf8truncate(std::string& utf8str,size_t len) -{ - try - { - size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); - if(wlen <= len) - return; - - std::wstring wstr; - wstr.resize(wlen); - utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); - wstr.resize(len); - char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]); - utf8str.resize(oend-(&utf8str[0])); // remove unused tail - } - catch(std::exception) - { - utf8str = ""; - } -} - -bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize) -{ - try - { - size_t len = utf8::distance(utf8str,utf8str+csize); - if(len > wsize) - { - if(wsize > 0) - wstr[0] = L'\0'; - wsize = 0; - return false; - } - - wsize = len; - utf8::utf8to16(utf8str,utf8str+csize,wstr); - wstr[len] = L'\0'; - } - catch(std::exception) - { - if(wsize > 0) - wstr[0] = L'\0'; - wsize = 0; - return false; - } - - return true; -} - -bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr) -{ - try - { - size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); - wstr.resize(len); - - utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); - } - catch(std::exception) - { - wstr = L""; - return false; - } - - return true; -} - -bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str) -{ - try - { - std::string utf8str2; - utf8str2.resize(size*4); // allocate for most long case - - char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]); - utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail - utf8str = utf8str2; - } - catch(std::exception) - { - utf8str = ""; - return false; - } - - return true; -} - -bool WStrToUtf8(std::wstring wstr, std::string& utf8str) -{ - try - { - std::string utf8str2; - utf8str2.resize(wstr.size()*4); // allocate for most long case - - char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]); - utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail - utf8str = utf8str2; - } - catch(std::exception) - { - utf8str = ""; - return false; - } - - return true; -} - -typedef wchar_t const* const* wstrlist; - -std::wstring GetMainPartOfName(std::wstring wname, uint32 declension) -{ - // supported only Cyrillic cases - if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5) - return wname; - - // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently) - - static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)}; - static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)}; - static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)}; - static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)}; - static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)}; - static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)}; - static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)}; - static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)}; - static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)}; - static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)}; - static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)}; - static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)}; - static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)}; - static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)}; - static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)}; - static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)}; - - static wchar_t const* const dropEnds[6][8] = { - { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL }, - { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL }, - { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL }, - { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL }, - { &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL }, - { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL } - }; - - for (wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr) - { - size_t len = size_t((*itr)[-1]); // get length from string size field - - if(wname.substr(wname.size()-len,len)==*itr) - return wname.substr(0,wname.size()-len); - } - - return wname; -} - -bool utf8ToConsole(const std::string& utf8str, std::string& conStr) -{ -#if PLATFORM == PLATFORM_WINDOWS - std::wstring wstr; - if(!Utf8toWStr(utf8str,wstr)) - return false; - - conStr.resize(wstr.size()); - CharToOemBuffW(&wstr[0],&conStr[0],wstr.size()); -#else - // not implemented yet - conStr = utf8str; -#endif - - return true; -} - -bool consoleToUtf8(const std::string& conStr,std::string& utf8str) -{ -#if PLATFORM == PLATFORM_WINDOWS - std::wstring wstr; - wstr.resize(conStr.size()); - OemToCharBuffW(&conStr[0],&wstr[0],conStr.size()); - - return WStrToUtf8(wstr,utf8str); -#else - // not implemented yet - utf8str = conStr; - return true; -#endif -} - -bool Utf8FitTo(const std::string& str, std::wstring search) -{ - std::wstring temp; - - if(!Utf8toWStr(str,temp)) - return false; - - // converting to lower case - wstrToLower( temp ); - - if(temp.find(search) == std::wstring::npos) - return false; - - return true; -} - -void utf8printf(FILE *out, const char *str, ...) -{ - va_list ap; - va_start(ap, str); - vutf8printf(out, str, &ap); - va_end(ap); -} - -void vutf8printf(FILE *out, const char *str, va_list* ap) -{ -#if PLATFORM == PLATFORM_WINDOWS - char temp_buf[32*1024]; - wchar_t wtemp_buf[32*1024]; - - size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap); - - size_t wtemp_len = 32*1024-1; - Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); - - CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1); - fprintf(out, temp_buf); -#else - vfprintf(out, str, *ap); -#endif -} - -void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result) -{ - std::ostringstream ss; - for (uint32 i=0; i>((1-j)*4)); - char encodedNibble; - if(nibble < 0x0A) - encodedNibble = '0'+nibble; - else - encodedNibble = 'A'+nibble-0x0A; - ss << encodedNibble; - } - } - result = ss.str(); -} - diff --git a/src/server/shared/Util.h b/src/server/shared/Util.h deleted file mode 100644 index 4f997725d25..00000000000 --- a/src/server/shared/Util.h +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _UTIL_H -#define _UTIL_H - -#include "Common.h" - -#include -#include - -typedef std::vector Tokens; - -Tokens StrSplit(const std::string &src, const std::string &sep); - -void stripLineInvisibleChars(std::string &src); - -std::string secsToTimeString(uint32 timeInSecs, bool shortText = false, bool hoursOnly = false); -uint32 TimeStringToSecs(const std::string& timestring); -std::string TimeToTimestampStr(time_t t); - -inline uint32 secsToTimeBitFields(time_t secs) -{ - tm* lt = localtime(&secs); - return (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min; -} - -/* Return a random number in the range min..max; (max-min) must be smaller than 32768. */ - int32 irand(int32 min, int32 max); - -/* Return a random number in the range min..max (inclusive). For reliable results, the difference -* between max and min should be less than RAND32_MAX. */ - uint32 urand(uint32 min, uint32 max); - -/* Return a random number in the range 0 .. RAND32_MAX. */ - int32 rand32(); - -/* Return a random double from 0.0 to 1.0 (exclusive). Floats support only 7 valid decimal digits. - * A double supports up to 15 valid decimal digits and is used internally (RAND32_MAX has 10 digits). - * With an FPU, there is usually no difference in performance between float and double. */ - double rand_norm(void); - -/* Return a random double from 0.0 to 99.9999999999999. Floats support only 7 valid decimal digits. - * A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits). - * With an FPU, there is usually no difference in performance between float and double. */ - double rand_chance(void); - -/* Return true if a random roll fits in the specified chance (range 0-100). */ -inline bool roll_chance_f(float chance) -{ - return chance > rand_chance(); -} - -/* Return true if a random roll fits in the specified chance (range 0-100). */ -inline bool roll_chance_i(int chance) -{ - return chance > irand(0, 99); -} - -inline void ApplyModUInt32Var(uint32& var, int32 val, bool apply) -{ - int32 cur = var; - cur += (apply ? val : -val); - if(cur < 0) - cur = 0; - var = cur; -} - -inline void ApplyModFloatVar(float& var, float val, bool apply) -{ - var += (apply ? val : -val); - if(var < 0) - var = 0; -} - -inline void ApplyPercentModFloatVar(float& var, float val, bool apply) -{ - if (val == -100.0f) // prevent set var to zero - val = -99.99f; - var *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)); -} - -bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr); -// in wsize==max size of buffer, out wsize==real string size -bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize); -inline bool Utf8toWStr(const std::string& utf8str, wchar_t* wstr, size_t& wsize) -{ - return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize); -} - -bool WStrToUtf8(std::wstring wstr, std::string& utf8str); -// size==real string size -bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str); - -size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence -void utf8truncate(std::string& utf8str,size_t len); - -inline bool isBasicLatinCharacter(wchar_t wchar) -{ - if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z - return true; - if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z - return true; - return false; -} - -inline bool isExtendedLatinCharacter(wchar_t wchar) -{ - if(isBasicLatinCharacter(wchar)) - return true; - if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS - return true; - if(wchar >= 0x00D8 && wchar <= 0x00DF) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN - return true; - if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S - return true; - if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS - return true; - if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN - return true; - if(wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK - return true; - if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S - return true; - return false; -} - -inline bool isCyrillicCharacter(wchar_t wchar) -{ - if(wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA - return true; - if(wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO - return true; - return false; -} - -inline bool isEastAsianCharacter(wchar_t wchar) -{ - if(wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo - return true; - if(wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana - return true; - if(wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo - return true; - if(wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext. - return true; - if(wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A - return true; - if(wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs - return true; - if(wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables - return true; - if(wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms - return true; - return false; -} - -inline bool isNumeric(wchar_t wchar) -{ - return (wchar >= L'0' && wchar <=L'9'); -} - -inline bool isNumeric(char c) -{ - return (c >= '0' && c <='9'); -} - -inline bool isNumericOrSpace(wchar_t wchar) -{ - return isNumeric(wchar) || wchar == L' '; -} - -inline bool isBasicLatinString(std::wstring wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if(!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isExtendedLatinString(std::wstring wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if(!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isCyrillicString(std::wstring wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if(!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isEastAsianString(std::wstring wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if(!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline wchar_t wcharToUpper(wchar_t wchar) -{ - if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z - return wchar_t(uint16(wchar)-0x0020); - if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S - return wchar_t(0x1E9E); - if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS - return wchar_t(uint16(wchar)-0x0020); - if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN - return wchar_t(uint16(wchar)-0x0020); - if(wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1) - { - if(wchar % 2 == 1) - return wchar_t(uint16(wchar)-0x0001); - } - if(wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA - return wchar_t(uint16(wchar)-0x0020); - if(wchar == 0x0451) // CYRILLIC SMALL LETTER IO - return wchar_t(0x0401); - - return wchar; -} - -inline wchar_t wcharToUpperOnlyLatin(wchar_t wchar) -{ - return isBasicLatinCharacter(wchar) ? wcharToUpper(wchar) : wchar; -} - -inline wchar_t wcharToLower(wchar_t wchar) -{ - if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z - return wchar_t(uint16(wchar)+0x0020); - if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS - return wchar_t(uint16(wchar)+0x0020); - if(wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN - return wchar_t(uint16(wchar)+0x0020); - if(wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0) - { - if(wchar % 2 == 0) - return wchar_t(uint16(wchar)+0x0001); - } - if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S - return wchar_t(0x00DF); - if(wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO - return wchar_t(0x0451); - if(wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA - return wchar_t(uint16(wchar)+0x0020); - - return wchar; -} - -inline void wstrToUpper(std::wstring& str) -{ - std::transform( str.begin(), str.end(), str.begin(), wcharToUpper ); -} - -inline void wstrToLower(std::wstring& str) -{ - std::transform( str.begin(), str.end(), str.begin(), wcharToLower ); -} - -std::wstring GetMainPartOfName(std::wstring wname, uint32 declension); - -bool utf8ToConsole(const std::string& utf8str, std::string& conStr); -bool consoleToUtf8(const std::string& conStr,std::string& utf8str); -bool Utf8FitTo(const std::string& str, std::wstring search); -void utf8printf(FILE *out, const char *str, ...); -void vutf8printf(FILE *out, const char *str, va_list* ap); - -bool IsIPAddress(char const* ipaddress); -uint32 CreatePIDFile(const std::string& filename); - -void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result); -#endif - -//handler for operations on large flags -#ifndef _FLAG96 -#define _FLAG96 - -#ifndef PAIR64_HIPART -#define PAIR64_HIPART(x) (uint32)((uint64(x) >> 32) & UI64LIT(0x00000000FFFFFFFF)) -#define PAIR64_LOPART(x) (uint32)(uint64(x) & UI64LIT(0x00000000FFFFFFFF)) -#endif - -class flag96 -{ -private: - uint32 part[3]; -public: - flag96(uint32 p1=0,uint32 p2=0,uint32 p3=0) - { - part[0]=p1; - part[1]=p2; - part[2]=p3; - } - - flag96(uint64 p1, uint32 p2) - { - part[0]=PAIR64_LOPART(p1); - part[1]=PAIR64_HIPART(p1); - part[2]=p2; - } - - inline bool IsEqual(uint32 p1=0, uint32 p2=0, uint32 p3=0) const - { - return ( - part[0]==p1 && - part[1]==p2 && - part[2]==p3); - }; - - inline bool HasFlag(uint32 p1=0, uint32 p2=0, uint32 p3=0) const - { - return ( - part[0]&p1 || - part[1]&p2 || - part[2]&p3); - }; - - inline void Set(uint32 p1=0, uint32 p2=0, uint32 p3=0) - { - part[0]=p1; - part[1]=p2; - part[2]=p3; - }; - - template - inline bool operator < (type & right) - { - for (uint8 i=3; i > 0; --i) - { - if (part[i-1]right.part[i-1]) - return 0; - } - return 0; - }; - - template - inline bool operator < (type & right) const - { - for (uint8 i = 3; i > 0; --i) - { - if (part[i-1]right.part[i-1]) - return 0; - } - return 0; - }; - - template - inline bool operator != (type & right) - { - if (part[0]!=right.part[0] - || part[1]!=right.part[1] - || part[2]!=right.part[2]) - return true; - return false; - } - - template - inline bool operator != (type & right) const - { - if (part[0]!=right.part[0] - || part[1]!=right.part[1] - || part[2]!=right.part[2]) - return true; - return false; - }; - - template - inline bool operator == (type & right) - { - if (part[0]!=right.part[0] - || part[1]!=right.part[1] - || part[2]!=right.part[2]) - return false; - return true; - }; - - template - inline bool operator == (type & right) const - { - if (part[0]!=right.part[0] - || part[1]!=right.part[1] - || part[2]!=right.part[2]) - return false; - return true; - }; - - template - inline void operator = (type & right) - { - part[0]=right.part[0]; - part[1]=right.part[1]; - part[2]=right.part[2]; - }; - - template - inline flag96 operator & (type & right) - { - flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); - return - ret; - }; - template - inline flag96 operator & (type & right) const - { - flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); - return - ret; - }; - - template - inline void operator &= (type & right) - { - *this=*this & right; - }; - - template - inline flag96 operator | (type & right) - { - flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); - return - ret; - }; - - template - inline flag96 operator | (type & right) const - { - flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); - return - ret; - }; - - template - inline void operator |= (type & right) - { - *this=*this | right; - }; - - inline void operator ~ () - { - part[2]=~part[2]; - part[1]=~part[1]; - part[0]=~part[0]; - }; - - template - inline flag96 operator ^ (type & right) - { - flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); - return - ret; - }; - - template - inline flag96 operator ^ (type & right) const - { - flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); - return - ret; - }; - - template - inline void operator ^= (type & right) - { - *this=*this^right; - }; - - inline operator bool() const - { - return( - part[0] != 0 || - part[1] != 0 || - part[2] != 0); - }; - - inline operator bool() - { - return( - part[0] != 0 || - part[1] != 0 || - part[2] != 0); - }; - - inline bool operator ! () const - { - return( - part[0] == 0 && - part[1] == 0 && - part[2] == 0); - }; - - inline bool operator ! () - { - return( - part[0] == 0 && - part[1] == 0 && - part[2] == 0); - }; - - inline uint32 & operator[](uint8 el) - { - return (part[el]); - }; - - inline const uint32 & operator[](uint8 el) const - { - return (part[el]); - }; -}; -#endif diff --git a/src/server/shared/Utilities/ProgressBar.cpp b/src/server/shared/Utilities/ProgressBar.cpp new file mode 100644 index 00000000000..c24d9f86f6b --- /dev/null +++ b/src/server/shared/Utilities/ProgressBar.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "ProgressBar.h" + +char const* const barGoLink::empty = " "; +#ifdef _WIN32 +char const* const barGoLink::full = "\x3D"; +#else +char const* const barGoLink::full = "*"; +#endif + +barGoLink::~barGoLink() +{ + printf( "\n" ); + fflush(stdout); +} + +barGoLink::barGoLink( int row_count ) +{ + rec_no = 0; + rec_pos = 0; + indic_len = 50; + num_rec = row_count; + #ifdef _WIN32 + printf( "\x3D" ); + #else + printf( "[" ); + #endif + for (int i = 0; i < indic_len; i++ ) printf( empty ); + #ifdef _WIN32 + printf( "\x3D 0%%\r\x3D" ); + #else + printf( "] 0%%\r[" ); + #endif + fflush(stdout); +} + +void barGoLink::step( void ) +{ + int i, n; + + if ( num_rec == 0 ) return; + ++rec_no; + n = rec_no * indic_len / num_rec; + if ( n != rec_pos ) + { + #ifdef _WIN32 + printf( "\r\x3D" ); + #else + printf( "\r[" ); + #endif + for (i = 0; i < n; i++ ) printf( full ); + for (; i < indic_len; i++ ) printf( empty ); + float percent = (((float)n/(float)indic_len)*100); + #ifdef _WIN32 + printf( "\x3D %i%% \r\x3D", (int)percent); + #else + printf( "] %i%% \r[", (int)percent); + #endif + fflush(stdout); + + rec_pos = n; + } +} + diff --git a/src/server/shared/Utilities/ProgressBar.h b/src/server/shared/Utilities/ProgressBar.h new file mode 100644 index 00000000000..e7565590278 --- /dev/null +++ b/src/server/shared/Utilities/ProgressBar.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef TRINITYCORE_PROGRESSBAR_H +#define TRINITYCORE_PROGRESSBAR_H + +#include "Platform/Define.h" + +class barGoLink +{ + static char const * const empty; + static char const * const full; + + int rec_no; + int rec_pos; + int num_rec; + int indic_len; + + public: + + void step( void ); + barGoLink( int ); + ~barGoLink(); +}; +#endif + diff --git a/src/server/shared/Utilities/ServiceWin32.cpp b/src/server/shared/Utilities/ServiceWin32.cpp new file mode 100644 index 00000000000..2c1df2ff483 --- /dev/null +++ b/src/server/shared/Utilities/ServiceWin32.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef WIN32 + +#include "Common.h" +#include "Log.h" +#include +#include +#include + +#if !defined(WINADVAPI) +#if !defined(_ADVAPI32_) +#define WINADVAPI DECLSPEC_IMPORT +#else +#define WINADVAPI +#endif +#endif + +extern int main(int argc, char ** argv); +extern char serviceLongName[]; +extern char serviceName[]; +extern char serviceDescription[]; + +extern int m_ServiceStatus; + +SERVICE_STATUS serviceStatus; + +SERVICE_STATUS_HANDLE serviceStatusHandle = 0; + +typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID); + +bool WinServiceInstall() +{ + CSD_T ChangeService_Config2; + HMODULE advapi32; + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); + + if (serviceControlManager) + { + char path[_MAX_PATH + 10]; + if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0) + { + SC_HANDLE service; + std::strcat(path, " --service"); + service = CreateService(serviceControlManager, + serviceName, // name of service + serviceLongName, // service name to display + SERVICE_ALL_ACCESS, // desired access + // service type + SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, + SERVICE_AUTO_START, // start type + SERVICE_ERROR_IGNORE, // error control type + path, // service's binary + 0, // no load ordering group + 0, // no tag identifier + 0, // no dependencies + 0, // LocalSystem account + 0); // no password + if (service) + { + advapi32 = GetModuleHandle("ADVAPI32.DLL"); + if(!advapi32) + { + CloseServiceHandle(service); + CloseServiceHandle(serviceControlManager); + return false; + } + + ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A"); + if (!ChangeService_Config2) + { + CloseServiceHandle(service); + CloseServiceHandle(serviceControlManager); + return false; + } + + SERVICE_DESCRIPTION sdBuf; + sdBuf.lpDescription = serviceDescription; + ChangeService_Config2( + service, // handle to service + SERVICE_CONFIG_DESCRIPTION, // change: description + &sdBuf); // new data + + SC_ACTION _action[1]; + _action[0].Type = SC_ACTION_RESTART; + _action[0].Delay = 10000; + SERVICE_FAILURE_ACTIONS sfa; + ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS)); + sfa.lpsaActions = _action; + sfa.cActions = 1; + sfa.dwResetPeriod =INFINITE; + ChangeService_Config2( + service, // handle to service + SERVICE_CONFIG_FAILURE_ACTIONS, // information level + &sfa); // new data + + CloseServiceHandle(service); + + } + } + CloseServiceHandle(serviceControlManager); + } + return true; +} + +bool WinServiceUninstall() +{ + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); + + if (serviceControlManager) + { + SC_HANDLE service = OpenService(serviceControlManager, + serviceName, SERVICE_QUERY_STATUS | DELETE); + if (service) + { + SERVICE_STATUS serviceStatus2; + if (QueryServiceStatus(service, &serviceStatus2)) + { + if (serviceStatus2.dwCurrentState == SERVICE_STOPPED) + DeleteService(service); + } + CloseServiceHandle(service); + } + + CloseServiceHandle(serviceControlManager); + } + return true; +} + +void WINAPI ServiceControlHandler(DWORD controlCode) +{ + switch (controlCode) + { + case SERVICE_CONTROL_INTERROGATE: + break; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + m_ServiceStatus = 0; + return; + + case SERVICE_CONTROL_PAUSE: + m_ServiceStatus = 2; + serviceStatus.dwCurrentState = SERVICE_PAUSED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + break; + + case SERVICE_CONTROL_CONTINUE: + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + m_ServiceStatus = 1; + break; + + default: + if ( controlCode >= 128 && controlCode <= 255 ) + // user defined control code + break; + else + // unrecognized control code + break; + } + + SetServiceStatus(serviceStatusHandle, &serviceStatus); +} + +void WINAPI ServiceMain(DWORD argc, char *argv[]) +{ + // initialise service status + serviceStatus.dwServiceType = SERVICE_WIN32; + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; + serviceStatus.dwWin32ExitCode = NO_ERROR; + serviceStatus.dwServiceSpecificExitCode = NO_ERROR; + serviceStatus.dwCheckPoint = 0; + serviceStatus.dwWaitHint = 0; + + serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler); + + if ( serviceStatusHandle ) + { + char path[_MAX_PATH + 1]; + unsigned int i, last_slash = 0; + + GetModuleFileName(0, path, sizeof(path)/sizeof(path[0])); + + for (i = 0; i < std::strlen(path); i++) + { + if (path[i] == '\\') last_slash = i; + } + + path[last_slash] = 0; + + // service is starting + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + // do initialisation here + SetCurrentDirectory(path); + + // running + serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus( serviceStatusHandle, &serviceStatus ); + + //////////////////////// + // service main cycle // + //////////////////////// + + m_ServiceStatus = 1; + argc = 1; + main(argc , argv); + + // service was stopped + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + // do cleanup here + + // service is now stopped + serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + } +} + +bool WinServiceRun() +{ + SERVICE_TABLE_ENTRY serviceTable[] = + { + { serviceName, ServiceMain }, + { 0, 0 } + }; + + if (!StartServiceCtrlDispatcher(serviceTable)) + { + sLog.outError("StartService Failed. Error [%u]", ::GetLastError()); + return false; + } + return true; +} +#endif + diff --git a/src/server/shared/Utilities/ServiceWin32.h b/src/server/shared/Utilities/ServiceWin32.h new file mode 100644 index 00000000000..ddac785a0fb --- /dev/null +++ b/src/server/shared/Utilities/ServiceWin32.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef WIN32 +#ifndef _WIN32_SERVICE_ +#define _WIN32_SERVICE_ + +bool WinServiceInstall(); +bool WinServiceUninstall(); +bool WinServiceRun(); + +#endif // _WIN32_SERVICE_ +#endif // WIN32 + diff --git a/src/server/shared/Utilities/SignalHandler.h b/src/server/shared/Utilities/SignalHandler.h new file mode 100644 index 00000000000..0c4d8143c41 --- /dev/null +++ b/src/server/shared/Utilities/SignalHandler.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __SIGNAL_HANDLER_H__ +#define __SIGNAL_HANDLER_H__ + +#include + +namespace Trinity +{ + +/// Handle termination signals +class SignalHandler : public ACE_Event_Handler +{ + public: + int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL) + { + HandleSignal(SigNum); + return 0; + } + virtual void HandleSignal(int SigNum) {}; +}; + +} + +#endif /* __SIGNAL_HANDLER_H__ */ diff --git a/src/server/shared/Utilities/Timer.h b/src/server/shared/Utilities/Timer.h new file mode 100644 index 00000000000..3e0a369b655 --- /dev/null +++ b/src/server/shared/Utilities/Timer.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_TIMER_H +#define TRINITY_TIMER_H + +#include "Platform/CompilerDefs.h" + +#if PLATFORM == PLATFORM_WINDOWS +# include +# include +# include +#else +# if defined(__APPLE_CC__) +# include +# endif +# include +# include +#endif + +#if PLATFORM == PLATFORM_WINDOWS +inline uint32 getMSTime() { return GetTickCount(); } +#else +inline uint32 getMSTime() +{ + struct timeval tv; + struct timezone tz; + gettimeofday( &tv, &tz ); + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); +} +#endif + +inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime) +{ + // getMSTime() have limited data range and this is case when it overflow in this tick + if (oldMSTime > newMSTime) + return (0xFFFFFFFF - oldMSTime) + newMSTime; + else + return newMSTime - oldMSTime; +} + +struct IntervalTimer +{ + public: + + IntervalTimer() + : _interval(0), _current(0) + { + } + + void Update(time_t diff) + { + _current += diff; + if (_current < 0) + _current = 0; + } + + bool Passed() + { + return _current >= _interval; + } + + void Reset() + { + if (_current >= _interval) + _current -= _interval; + } + + void SetCurrent(time_t current) + { + _current = current; + } + + void SetInterval(time_t interval) + { + _interval = interval; + } + + time_t GetInterval() const + { + return _interval; + } + + time_t GetCurrent() const + { + return _current; + } + + private: + + time_t _interval; + time_t _current; +}; + +struct TimeTracker +{ + public: + + TimeTracker(time_t expiry) + : i_expiryTime(expiry) + { + } + + void Update(time_t diff) + { + i_expiryTime -= diff; + } + + bool Passed() const + { + return i_expiryTime <= 0; + } + + void Reset(time_t interval) + { + i_expiryTime = interval; + } + + time_t GetExpiry() const + { + return i_expiryTime; + } + + private: + + time_t i_expiryTime; +}; + +struct TimeTrackerSmall +{ + public: + + TimeTrackerSmall(uint32 expiry) + : i_expiryTime(expiry) + { + } + + void Update(int32 diff) + { + i_expiryTime -= diff; + } + + bool Passed() const + { + return i_expiryTime <= 0; + } + + void Reset(uint32 interval) + { + i_expiryTime = interval; + } + + int32 GetExpiry() const + { + return i_expiryTime; + } + + private: + + int32 i_expiryTime; +}; + +struct PeriodicTimer +{ + public: + + PeriodicTimer(int32 period, int32 start_time) + : i_expireTime(start_time), i_period(period) + { + } + + bool Update(const uint32 &diff) + { + if ((i_expireTime -= diff) > 0) + return false; + + i_expireTime += i_period > diff ? i_period : diff; + return true; + } + + void SetPeriodic(int32 period, int32 start_time) + { + i_expireTime = start_time; + i_period = period; + } + + // Tracker interface + void TUpdate(int32 diff) { i_expireTime -= diff; } + bool TPassed() const { return i_expireTime <= 0; } + void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; } + + private: + + int32 i_period; + int32 i_expireTime; +}; + +#endif diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp new file mode 100644 index 00000000000..a3c017fdbfd --- /dev/null +++ b/src/server/shared/Utilities/Util.cpp @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Util.h" + +#include "sockets/socket_include.h" +#include "utf8cpp/utf8.h" +#include "mersennetwister/MersenneTwister.h" +#include + +typedef ACE_TSS MTRandTSS; +static MTRandTSS mtRand; + +int32 irand (int32 min, int32 max) +{ + return int32 (mtRand->randInt (max - min)) + min; +} + +uint32 urand (uint32 min, uint32 max) +{ + return mtRand->randInt (max - min) + min; +} + +int32 rand32 () +{ + return mtRand->randInt (); +} + +double rand_norm(void) +{ + return mtRand->randExc (); +} + +double rand_chance (void) +{ + return mtRand->randExc (100.0); +} + +Tokens StrSplit(const std::string &src, const std::string &sep) +{ + Tokens r; + std::string s; + for (std::string::const_iterator i = src.begin(); i != src.end(); i++) + { + if (sep.find(*i) != std::string::npos) + { + if (s.length()) r.push_back(s); + s = ""; + } + else + { + s += *i; + } + } + if (s.length()) r.push_back(s); + return r; +} + +void stripLineInvisibleChars(std::string &str) +{ + static std::string invChars = " \t\7\n"; + + size_t wpos = 0; + + bool space = false; + for (size_t pos = 0; pos < str.size(); ++pos) + { + if(invChars.find(str[pos])!=std::string::npos) + { + if(!space) + { + str[wpos++] = ' '; + space = true; + } + } + else + { + if(wpos!=pos) + str[wpos++] = str[pos]; + else + ++wpos; + space = false; + } + } + + if(wpos < str.size()) + str.erase(wpos,str.size()); + if(str.find("|TInterface")!=std::string::npos) + str.clear(); + +} + +std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly) +{ + uint32 secs = timeInSecs % MINUTE; + uint32 minutes = timeInSecs % HOUR / MINUTE; + uint32 hours = timeInSecs % DAY / HOUR; + uint32 days = timeInSecs / DAY; + + std::ostringstream ss; + if(days) + ss << days << (shortText ? "d" : " Day(s) "); + if(hours || hoursOnly) + ss << hours << (shortText ? "h" : " Hour(s) "); + if(!hoursOnly) + { + if(minutes) + ss << minutes << (shortText ? "m" : " Minute(s) "); + if(secs || (!days && !hours && !minutes) ) + ss << secs << (shortText ? "s" : " Second(s)."); + } + + return ss.str(); +} + +uint32 TimeStringToSecs(const std::string& timestring) +{ + uint32 secs = 0; + uint32 buffer = 0; + uint32 multiplier = 0; + + for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); itr++ ) + { + if(isdigit(*itr)) + { + buffer*=10; + buffer+= (*itr)-'0'; + } + else + { + switch(*itr) + { + case 'd': multiplier = DAY; break; + case 'h': multiplier = HOUR; break; + case 'm': multiplier = MINUTE; break; + case 's': multiplier = 1; break; + default : return 0; //bad format + } + buffer*=multiplier; + secs+=buffer; + buffer=0; + } + } + + return secs; +} + +std::string TimeToTimestampStr(time_t t) +{ + tm* aTm = localtime(&t); + // YYYY year + // MM month (2 digits 01-12) + // DD day (2 digits 01-31) + // HH hour (2 digits 00-23) + // MM minutes (2 digits 00-59) + // SS seconds (2 digits 00-59) + char buf[20]; + snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec); + return std::string(buf); +} + +/// Check if the string is a valid ip address representation +bool IsIPAddress(char const* ipaddress) +{ + if(!ipaddress) + return false; + + // Let the big boys do it. + // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD) + return inet_addr(ipaddress) != INADDR_NONE; +} + +/// create PID file +uint32 CreatePIDFile(const std::string& filename) +{ + FILE * pid_file = fopen (filename.c_str(), "w" ); + if (pid_file == NULL) + return 0; + +#ifdef WIN32 + DWORD pid = GetCurrentProcessId(); +#else + pid_t pid = getpid(); +#endif + + fprintf(pid_file, "%d", pid ); + fclose(pid_file); + + return (uint32)pid; +} + +size_t utf8length(std::string& utf8str) +{ + try + { + return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + } + catch(std::exception) + { + utf8str = ""; + return 0; + } +} + +void utf8truncate(std::string& utf8str,size_t len) +{ + try + { + size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + if(wlen <= len) + return; + + std::wstring wstr; + wstr.resize(wlen); + utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); + wstr.resize(len); + char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]); + utf8str.resize(oend-(&utf8str[0])); // remove unused tail + } + catch(std::exception) + { + utf8str = ""; + } +} + +bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize) +{ + try + { + size_t len = utf8::distance(utf8str,utf8str+csize); + if(len > wsize) + { + if(wsize > 0) + wstr[0] = L'\0'; + wsize = 0; + return false; + } + + wsize = len; + utf8::utf8to16(utf8str,utf8str+csize,wstr); + wstr[len] = L'\0'; + } + catch(std::exception) + { + if(wsize > 0) + wstr[0] = L'\0'; + wsize = 0; + return false; + } + + return true; +} + +bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr) +{ + try + { + size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size()); + wstr.resize(len); + + utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]); + } + catch(std::exception) + { + wstr = L""; + return false; + } + + return true; +} + +bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str) +{ + try + { + std::string utf8str2; + utf8str2.resize(size*4); // allocate for most long case + + char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]); + utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail + utf8str = utf8str2; + } + catch(std::exception) + { + utf8str = ""; + return false; + } + + return true; +} + +bool WStrToUtf8(std::wstring wstr, std::string& utf8str) +{ + try + { + std::string utf8str2; + utf8str2.resize(wstr.size()*4); // allocate for most long case + + char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]); + utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail + utf8str = utf8str2; + } + catch(std::exception) + { + utf8str = ""; + return false; + } + + return true; +} + +typedef wchar_t const* const* wstrlist; + +std::wstring GetMainPartOfName(std::wstring wname, uint32 declension) +{ + // supported only Cyrillic cases + if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5) + return wname; + + // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently) + + static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)}; + static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)}; + static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)}; + static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)}; + static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)}; + static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)}; + static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)}; + static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)}; + static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)}; + static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)}; + static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)}; + static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)}; + + static wchar_t const* const dropEnds[6][8] = { + { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL }, + { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL }, + { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL }, + { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL }, + { &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL }, + { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL } + }; + + for (wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr) + { + size_t len = size_t((*itr)[-1]); // get length from string size field + + if(wname.substr(wname.size()-len,len)==*itr) + return wname.substr(0,wname.size()-len); + } + + return wname; +} + +bool utf8ToConsole(const std::string& utf8str, std::string& conStr) +{ +#if PLATFORM == PLATFORM_WINDOWS + std::wstring wstr; + if(!Utf8toWStr(utf8str,wstr)) + return false; + + conStr.resize(wstr.size()); + CharToOemBuffW(&wstr[0],&conStr[0],wstr.size()); +#else + // not implemented yet + conStr = utf8str; +#endif + + return true; +} + +bool consoleToUtf8(const std::string& conStr,std::string& utf8str) +{ +#if PLATFORM == PLATFORM_WINDOWS + std::wstring wstr; + wstr.resize(conStr.size()); + OemToCharBuffW(&conStr[0],&wstr[0],conStr.size()); + + return WStrToUtf8(wstr,utf8str); +#else + // not implemented yet + utf8str = conStr; + return true; +#endif +} + +bool Utf8FitTo(const std::string& str, std::wstring search) +{ + std::wstring temp; + + if(!Utf8toWStr(str,temp)) + return false; + + // converting to lower case + wstrToLower( temp ); + + if(temp.find(search) == std::wstring::npos) + return false; + + return true; +} + +void utf8printf(FILE *out, const char *str, ...) +{ + va_list ap; + va_start(ap, str); + vutf8printf(out, str, &ap); + va_end(ap); +} + +void vutf8printf(FILE *out, const char *str, va_list* ap) +{ +#if PLATFORM == PLATFORM_WINDOWS + char temp_buf[32*1024]; + wchar_t wtemp_buf[32*1024]; + + size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap); + + size_t wtemp_len = 32*1024-1; + Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); + + CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1); + fprintf(out, temp_buf); +#else + vfprintf(out, str, *ap); +#endif +} + +void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result) +{ + std::ostringstream ss; + for (uint32 i=0; i>((1-j)*4)); + char encodedNibble; + if(nibble < 0x0A) + encodedNibble = '0'+nibble; + else + encodedNibble = 'A'+nibble-0x0A; + ss << encodedNibble; + } + } + result = ss.str(); +} + diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h new file mode 100644 index 00000000000..4f997725d25 --- /dev/null +++ b/src/server/shared/Utilities/Util.h @@ -0,0 +1,536 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _UTIL_H +#define _UTIL_H + +#include "Common.h" + +#include +#include + +typedef std::vector Tokens; + +Tokens StrSplit(const std::string &src, const std::string &sep); + +void stripLineInvisibleChars(std::string &src); + +std::string secsToTimeString(uint32 timeInSecs, bool shortText = false, bool hoursOnly = false); +uint32 TimeStringToSecs(const std::string& timestring); +std::string TimeToTimestampStr(time_t t); + +inline uint32 secsToTimeBitFields(time_t secs) +{ + tm* lt = localtime(&secs); + return (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min; +} + +/* Return a random number in the range min..max; (max-min) must be smaller than 32768. */ + int32 irand(int32 min, int32 max); + +/* Return a random number in the range min..max (inclusive). For reliable results, the difference +* between max and min should be less than RAND32_MAX. */ + uint32 urand(uint32 min, uint32 max); + +/* Return a random number in the range 0 .. RAND32_MAX. */ + int32 rand32(); + +/* Return a random double from 0.0 to 1.0 (exclusive). Floats support only 7 valid decimal digits. + * A double supports up to 15 valid decimal digits and is used internally (RAND32_MAX has 10 digits). + * With an FPU, there is usually no difference in performance between float and double. */ + double rand_norm(void); + +/* Return a random double from 0.0 to 99.9999999999999. Floats support only 7 valid decimal digits. + * A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits). + * With an FPU, there is usually no difference in performance between float and double. */ + double rand_chance(void); + +/* Return true if a random roll fits in the specified chance (range 0-100). */ +inline bool roll_chance_f(float chance) +{ + return chance > rand_chance(); +} + +/* Return true if a random roll fits in the specified chance (range 0-100). */ +inline bool roll_chance_i(int chance) +{ + return chance > irand(0, 99); +} + +inline void ApplyModUInt32Var(uint32& var, int32 val, bool apply) +{ + int32 cur = var; + cur += (apply ? val : -val); + if(cur < 0) + cur = 0; + var = cur; +} + +inline void ApplyModFloatVar(float& var, float val, bool apply) +{ + var += (apply ? val : -val); + if(var < 0) + var = 0; +} + +inline void ApplyPercentModFloatVar(float& var, float val, bool apply) +{ + if (val == -100.0f) // prevent set var to zero + val = -99.99f; + var *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)); +} + +bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr); +// in wsize==max size of buffer, out wsize==real string size +bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize); +inline bool Utf8toWStr(const std::string& utf8str, wchar_t* wstr, size_t& wsize) +{ + return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize); +} + +bool WStrToUtf8(std::wstring wstr, std::string& utf8str); +// size==real string size +bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str); + +size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence +void utf8truncate(std::string& utf8str,size_t len); + +inline bool isBasicLatinCharacter(wchar_t wchar) +{ + if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z + return true; + if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z + return true; + return false; +} + +inline bool isExtendedLatinCharacter(wchar_t wchar) +{ + if(isBasicLatinCharacter(wchar)) + return true; + if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS + return true; + if(wchar >= 0x00D8 && wchar <= 0x00DF) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN + return true; + if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S + return true; + if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS + return true; + if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN + return true; + if(wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK + return true; + if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S + return true; + return false; +} + +inline bool isCyrillicCharacter(wchar_t wchar) +{ + if(wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA + return true; + if(wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO + return true; + return false; +} + +inline bool isEastAsianCharacter(wchar_t wchar) +{ + if(wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo + return true; + if(wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana + return true; + if(wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo + return true; + if(wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext. + return true; + if(wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A + return true; + if(wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs + return true; + if(wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables + return true; + if(wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms + return true; + return false; +} + +inline bool isNumeric(wchar_t wchar) +{ + return (wchar >= L'0' && wchar <=L'9'); +} + +inline bool isNumeric(char c) +{ + return (c >= '0' && c <='9'); +} + +inline bool isNumericOrSpace(wchar_t wchar) +{ + return isNumeric(wchar) || wchar == L' '; +} + +inline bool isBasicLatinString(std::wstring wstr, bool numericOrSpace) +{ + for (size_t i = 0; i < wstr.size(); ++i) + if(!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) + return false; + return true; +} + +inline bool isExtendedLatinString(std::wstring wstr, bool numericOrSpace) +{ + for (size_t i = 0; i < wstr.size(); ++i) + if(!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) + return false; + return true; +} + +inline bool isCyrillicString(std::wstring wstr, bool numericOrSpace) +{ + for (size_t i = 0; i < wstr.size(); ++i) + if(!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) + return false; + return true; +} + +inline bool isEastAsianString(std::wstring wstr, bool numericOrSpace) +{ + for (size_t i = 0; i < wstr.size(); ++i) + if(!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) + return false; + return true; +} + +inline wchar_t wcharToUpper(wchar_t wchar) +{ + if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z + return wchar_t(uint16(wchar)-0x0020); + if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S + return wchar_t(0x1E9E); + if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS + return wchar_t(uint16(wchar)-0x0020); + if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN + return wchar_t(uint16(wchar)-0x0020); + if(wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1) + { + if(wchar % 2 == 1) + return wchar_t(uint16(wchar)-0x0001); + } + if(wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA + return wchar_t(uint16(wchar)-0x0020); + if(wchar == 0x0451) // CYRILLIC SMALL LETTER IO + return wchar_t(0x0401); + + return wchar; +} + +inline wchar_t wcharToUpperOnlyLatin(wchar_t wchar) +{ + return isBasicLatinCharacter(wchar) ? wcharToUpper(wchar) : wchar; +} + +inline wchar_t wcharToLower(wchar_t wchar) +{ + if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z + return wchar_t(uint16(wchar)+0x0020); + if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS + return wchar_t(uint16(wchar)+0x0020); + if(wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN + return wchar_t(uint16(wchar)+0x0020); + if(wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0) + { + if(wchar % 2 == 0) + return wchar_t(uint16(wchar)+0x0001); + } + if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S + return wchar_t(0x00DF); + if(wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO + return wchar_t(0x0451); + if(wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA + return wchar_t(uint16(wchar)+0x0020); + + return wchar; +} + +inline void wstrToUpper(std::wstring& str) +{ + std::transform( str.begin(), str.end(), str.begin(), wcharToUpper ); +} + +inline void wstrToLower(std::wstring& str) +{ + std::transform( str.begin(), str.end(), str.begin(), wcharToLower ); +} + +std::wstring GetMainPartOfName(std::wstring wname, uint32 declension); + +bool utf8ToConsole(const std::string& utf8str, std::string& conStr); +bool consoleToUtf8(const std::string& conStr,std::string& utf8str); +bool Utf8FitTo(const std::string& str, std::wstring search); +void utf8printf(FILE *out, const char *str, ...); +void vutf8printf(FILE *out, const char *str, va_list* ap); + +bool IsIPAddress(char const* ipaddress); +uint32 CreatePIDFile(const std::string& filename); + +void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result); +#endif + +//handler for operations on large flags +#ifndef _FLAG96 +#define _FLAG96 + +#ifndef PAIR64_HIPART +#define PAIR64_HIPART(x) (uint32)((uint64(x) >> 32) & UI64LIT(0x00000000FFFFFFFF)) +#define PAIR64_LOPART(x) (uint32)(uint64(x) & UI64LIT(0x00000000FFFFFFFF)) +#endif + +class flag96 +{ +private: + uint32 part[3]; +public: + flag96(uint32 p1=0,uint32 p2=0,uint32 p3=0) + { + part[0]=p1; + part[1]=p2; + part[2]=p3; + } + + flag96(uint64 p1, uint32 p2) + { + part[0]=PAIR64_LOPART(p1); + part[1]=PAIR64_HIPART(p1); + part[2]=p2; + } + + inline bool IsEqual(uint32 p1=0, uint32 p2=0, uint32 p3=0) const + { + return ( + part[0]==p1 && + part[1]==p2 && + part[2]==p3); + }; + + inline bool HasFlag(uint32 p1=0, uint32 p2=0, uint32 p3=0) const + { + return ( + part[0]&p1 || + part[1]&p2 || + part[2]&p3); + }; + + inline void Set(uint32 p1=0, uint32 p2=0, uint32 p3=0) + { + part[0]=p1; + part[1]=p2; + part[2]=p3; + }; + + template + inline bool operator < (type & right) + { + for (uint8 i=3; i > 0; --i) + { + if (part[i-1]right.part[i-1]) + return 0; + } + return 0; + }; + + template + inline bool operator < (type & right) const + { + for (uint8 i = 3; i > 0; --i) + { + if (part[i-1]right.part[i-1]) + return 0; + } + return 0; + }; + + template + inline bool operator != (type & right) + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return true; + return false; + } + + template + inline bool operator != (type & right) const + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return true; + return false; + }; + + template + inline bool operator == (type & right) + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return false; + return true; + }; + + template + inline bool operator == (type & right) const + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return false; + return true; + }; + + template + inline void operator = (type & right) + { + part[0]=right.part[0]; + part[1]=right.part[1]; + part[2]=right.part[2]; + }; + + template + inline flag96 operator & (type & right) + { + flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); + return + ret; + }; + template + inline flag96 operator & (type & right) const + { + flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); + return + ret; + }; + + template + inline void operator &= (type & right) + { + *this=*this & right; + }; + + template + inline flag96 operator | (type & right) + { + flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); + return + ret; + }; + + template + inline flag96 operator | (type & right) const + { + flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); + return + ret; + }; + + template + inline void operator |= (type & right) + { + *this=*this | right; + }; + + inline void operator ~ () + { + part[2]=~part[2]; + part[1]=~part[1]; + part[0]=~part[0]; + }; + + template + inline flag96 operator ^ (type & right) + { + flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); + return + ret; + }; + + template + inline flag96 operator ^ (type & right) const + { + flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); + return + ret; + }; + + template + inline void operator ^= (type & right) + { + *this=*this^right; + }; + + inline operator bool() const + { + return( + part[0] != 0 || + part[1] != 0 || + part[2] != 0); + }; + + inline operator bool() + { + return( + part[0] != 0 || + part[1] != 0 || + part[2] != 0); + }; + + inline bool operator ! () const + { + return( + part[0] == 0 && + part[1] == 0 && + part[2] == 0); + }; + + inline bool operator ! () + { + return( + part[0] == 0 && + part[1] == 0 && + part[2] == 0); + }; + + inline uint32 & operator[](uint8 el) + { + return (part[el]); + }; + + inline const uint32 & operator[](uint8 el) const + { + return (part[el]); + }; +}; +#endif diff --git a/src/server/shared/WheatyExceptionReport.cpp b/src/server/shared/WheatyExceptionReport.cpp deleted file mode 100644 index 8fb5d5e2d2a..00000000000 --- a/src/server/shared/WheatyExceptionReport.cpp +++ /dev/null @@ -1,1013 +0,0 @@ -//========================================== -// Matt Pietrek -// MSDN Magazine, 2002 -// FILE: WheatyExceptionReport.CPP -//========================================== -#define WIN32_LEAN_AND_MEAN -#pragma warning(disable:4996) -#pragma warning(disable:4312) -#pragma warning(disable:4311) -#include -#include -#include -#include -#define _NO_CVCONST_H -#include -#include "WheatyExceptionReport.h" -#include "SystemConfig.h" -#include "revision.h" -#define CrashFolder _T("Crashes") -//#pragma comment(linker, "/defaultlib:dbghelp.lib") - -inline LPTSTR ErrorMessage(DWORD dw) -{ - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL); - return (LPTSTR)lpMsgBuf; -} - -//============================== Global Variables ============================= - -// -// Declare the static variables of the WheatyExceptionReport class -// -TCHAR WheatyExceptionReport::m_szLogFileName[MAX_PATH]; -LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter; -HANDLE WheatyExceptionReport::m_hReportFile; -HANDLE WheatyExceptionReport::m_hProcess; - -// Declare global instance of class -WheatyExceptionReport g_WheatyExceptionReport; - -//============================== Class Methods ============================= - -WheatyExceptionReport::WheatyExceptionReport() // Constructor -{ - // Install the unhandled exception filter function - m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); - m_hProcess = GetCurrentProcess(); -} - -//============ -// Destructor -//============ -WheatyExceptionReport::~WheatyExceptionReport() -{ - if (m_previousFilter) - SetUnhandledExceptionFilter(m_previousFilter); -} - -//=========================================================== -// Entry point where control comes on an unhandled exception -//=========================================================== -LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( -PEXCEPTION_POINTERS pExceptionInfo) -{ - TCHAR module_folder_name[MAX_PATH]; - GetModuleFileName(0, module_folder_name, MAX_PATH); - TCHAR* pos = _tcsrchr(module_folder_name, '\\'); - if (!pos) - return 0; - pos[0] = '\0'; - ++pos; - - TCHAR crash_folder_path[MAX_PATH]; - sprintf(crash_folder_path, "%s\\%s", module_folder_name, CrashFolder); - if (!CreateDirectory(crash_folder_path, NULL)) - { - if (GetLastError() != ERROR_ALREADY_EXISTS) - return 0; - } - - SYSTEMTIME systime; - GetLocalTime(&systime); - sprintf(m_szLogFileName, "%s\\%s_[%u-%u_%u-%u-%u].txt", - crash_folder_path, pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); - - m_hReportFile = CreateFile(m_szLogFileName, - GENERIC_WRITE, - 0, - 0, - OPEN_ALWAYS, - FILE_FLAG_WRITE_THROUGH, - 0); - - if (m_hReportFile) - { - SetFilePointer(m_hReportFile, 0, 0, FILE_END); - - GenerateExceptionReport(pExceptionInfo); - - CloseHandle(m_hReportFile); - m_hReportFile = 0; - } - - if (m_previousFilter) - return m_previousFilter(pExceptionInfo); - else - return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/; -} - -BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount) -{ - if (!sProcessorName) - return FALSE; - - HKEY hKey; - LONG lRet; - lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), - 0, KEY_QUERY_VALUE, &hKey); - if (lRet != ERROR_SUCCESS) - return FALSE; - TCHAR szTmp[2048]; - DWORD cntBytes = sizeof(szTmp); - lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL, - (LPBYTE)szTmp, &cntBytes); - if (lRet != ERROR_SUCCESS) - return FALSE; - ::RegCloseKey(hKey); - sProcessorName[0] = '\0'; - // Skip spaces - TCHAR* psz = szTmp; - while (iswspace(*psz)) - ++psz; - _tcsncpy(sProcessorName, psz, maxcount); - return TRUE; -} - -BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax) -{ - // Try calling GetVersionEx using the OSVERSIONINFOEX structure. - // If that fails, try using the OSVERSIONINFO structure. - OSVERSIONINFOEX osvi = { 0 }; - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - BOOL bOsVersionInfoEx; - bOsVersionInfoEx = ::GetVersionEx((LPOSVERSIONINFO)(&osvi)); - if (!bOsVersionInfoEx) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!::GetVersionEx((OSVERSIONINFO*)&osvi)) - return FALSE; - } - *szVersion = _T('\0'); - TCHAR wszTmp[128]; - switch (osvi.dwPlatformId) - { - // Windows NT product family. - case VER_PLATFORM_WIN32_NT: - // Test for the specific product family. - if (osvi.dwMajorVersion == 6) - _tcsncat(szVersion, _T("Windows Vista or Windows Server 2008 "), cntMax); - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - _tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax); - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) - _tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax); - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) - _tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax); - if (osvi.dwMajorVersion <= 4) - _tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax); - - // Test for specific product on Windows NT 4.0 SP6 and later. - if (bOsVersionInfoEx) - { - // Test for the workstation type. - #if WINVER < 0x0500 - if (osvi.wReserved[1] == VER_NT_WORKSTATION) - #else - if (osvi.wProductType == VER_NT_WORKSTATION) - #endif // WINVER < 0x0500 - { - if (osvi.dwMajorVersion == 4) - _tcsncat(szVersion, _T("Workstation 4.0 "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] & VER_SUITE_PERSONAL) - #else - else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Home Edition "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] & VER_SUITE_EMBEDDEDNT) - #else - else if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Embedded "), cntMax); - else - _tcsncat(szVersion, _T("Professional "), cntMax); - } - // Test for the server type. - #if WINVER < 0x0500 - else if (osvi.wReserved[1] == VER_NT_SERVER) - #else - else if (osvi.wProductType == VER_NT_SERVER) - #endif // WINVER < 0x0500 - { - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - { - #if WINVER < 0x0500 - if (osvi.wReserved[0] & VER_SUITE_DATACENTER) - #else - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Datacenter Edition "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) - #else - else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Enterprise Edition "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] == VER_SUITE_BLADE) - #else - else if (osvi.wSuiteMask == VER_SUITE_BLADE) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Web Edition "), cntMax); - else - _tcsncat(szVersion, _T("Standard Edition "), cntMax); - } - else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) - { - #if WINVER < 0x0500 - if (osvi.wReserved[0] & VER_SUITE_DATACENTER) - #else - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Datacenter Server "), cntMax); - #if WINVER < 0x0500 - else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) - #else - else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Advanced Server "), cntMax); - else - _tcsncat(szVersion, _T("Server "), cntMax); - } - else // Windows NT 4.0 - { - #if WINVER < 0x0500 - if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE) - #else - if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - #endif // WINVER < 0x0500 - _tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax); - else - _tcsncat(szVersion, _T("Server 4.0 "), cntMax); - } - } - } - // Display service pack (if any) and build number. - if (osvi.dwMajorVersion == 4 && _tcsicmp(osvi.szCSDVersion, _T("Service Pack 6")) == 0) - { - HKEY hKey; - LONG lRet; - - // Test for SP6 versus SP6a. - lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey); - if (lRet == ERROR_SUCCESS) - { - _stprintf(wszTmp, _T("Service Pack 6a (Version %d.%d, Build %d)"), - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - else // Windows NT 4.0 prior to SP6a - { - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - ::RegCloseKey(hKey); - } - else // Windows NT 3.51 and earlier or Windows 2000 and later - { - if (!_tcslen(osvi.szCSDVersion)) - _stprintf(wszTmp, _T("(Version %d.%d, Build %d)"), - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - else - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - break; - default: - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - break; - } - - return TRUE; -} - -void WheatyExceptionReport::PrintSystemInfo() -{ - SYSTEM_INFO SystemInfo; - ::GetSystemInfo(&SystemInfo); - - MEMORYSTATUS MemoryStatus; - MemoryStatus.dwLength = sizeof (MEMORYSTATUS); - ::GlobalMemoryStatus(&MemoryStatus); - TCHAR sString[1024]; - _tprintf(_T("//=====================================================\r\n")); - if (_GetProcessorName(sString, countof(sString))) - _tprintf(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), - sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); - else - _tprintf(_T("*** Hardware ***\r\nProcessor: \r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), - SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); - - if (_GetWindowsVersion(sString, countof(sString))) - _tprintf(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString); - else - _tprintf(_T("\r\n*** Operation System:\r\n\r\n")); -} - -//=========================================================================== -void WheatyExceptionReport::printTracesForAllThreads() -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - DWORD dwOwnerPID = GetCurrentProcessId(); - m_hProcess = GetCurrentProcess(); - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return; - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if (!Thread32First(hThreadSnap, &te32)) - { - CloseHandle(hThreadSnap); // Must clean up the - // snapshot object! - return; - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwOwnerPID) - { - CONTEXT context; - context.ContextFlags = 0xffffffff; - HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,false, te32.th32ThreadID); - if (threadHandle && GetThreadContext(threadHandle, &context)) - { - WriteStackDetails(&context, false, threadHandle); - } - CloseHandle(threadHandle); - } - } while(Thread32Next(hThreadSnap, &te32)); - -// Don't forget to clean up the snapshot object. - CloseHandle(hThreadSnap); -} - -//=========================================================================== -// Open the report file, and write the desired information to it. Called by -// WheatyUnhandledExceptionFilter -//=========================================================================== -void WheatyExceptionReport::GenerateExceptionReport( -PEXCEPTION_POINTERS pExceptionInfo) -{ - SYSTEMTIME systime; - GetLocalTime(&systime); - - // Start out with a banner - _tprintf(_T("Revision: %s\r\n"), _FULLVERSION); - _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute); - PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; - - PrintSystemInfo(); - // First print information about the type of fault - _tprintf(_T("\r\n//=====================================================\r\n")); - _tprintf(_T("Exception code: %08X %s\r\n"), - pExceptionRecord->ExceptionCode, - GetExceptionString(pExceptionRecord->ExceptionCode)); - - // Now print information about where the fault occured - TCHAR szFaultingModule[MAX_PATH]; - DWORD section; - DWORD_PTR offset; - GetLogicalAddress(pExceptionRecord->ExceptionAddress, - szFaultingModule, - sizeof(szFaultingModule), - section, offset); - -#ifdef _M_IX86 - _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"), - pExceptionRecord->ExceptionAddress, - section, offset, szFaultingModule); -#endif -#ifdef _M_X64 - _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"), - pExceptionRecord->ExceptionAddress, - section, offset, szFaultingModule); -#endif - - PCONTEXT pCtx = pExceptionInfo->ContextRecord; - - // Show the registers - #ifdef _M_IX86 // X86 Only! - _tprintf(_T("\r\nRegisters:\r\n")); - - _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n") - ,pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, - pCtx->Esi, pCtx->Edi); - - _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip); - _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"), - pCtx->SegSs, pCtx->Esp, pCtx->Ebp); - _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), - pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); - _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); - #endif - - #ifdef _M_X64 - _tprintf(_T("\r\nRegisters:\r\n")); - _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n") - _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n") - ,pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, - pCtx->Rsi, pCtx->Rdi ,pCtx->R9,pCtx->R10,pCtx->R11,pCtx->R12,pCtx->R13,pCtx->R14,pCtx->R15); - _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip); - _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"), - pCtx->SegSs, pCtx->Rsp, pCtx->Rbp); - _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), - pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); - _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); - #endif - - SymSetOptions(SYMOPT_DEFERRED_LOADS); - - // Initialize DbgHelp - if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) - { - _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"), - ErrorMessage(GetLastError())); - } - - CONTEXT trashableContext = *pCtx; - - WriteStackDetails(&trashableContext, false, NULL); - printTracesForAllThreads(); - -// #ifdef _M_IX86 // X86 Only! - - _tprintf(_T("========================\r\n")); - _tprintf(_T("Local Variables And Parameters\r\n")); - - trashableContext = *pCtx; - WriteStackDetails(&trashableContext, true, NULL); - - _tprintf(_T("========================\r\n")); - _tprintf(_T("Global Variables\r\n")); - - SymEnumSymbols(GetCurrentProcess(), - (DWORD64)GetModuleHandle(szFaultingModule), - 0, EnumerateSymbolsCallback, 0); - // #endif // X86 Only! - - SymCleanup(GetCurrentProcess()); - - _tprintf(_T("\r\n")); -} - -//====================================================================== -// Given an exception code, returns a pointer to a static string with a -// description of the exception -//====================================================================== -LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode) -{ - #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x); - - switch (dwCode) - { - EXCEPTION(ACCESS_VIOLATION) - EXCEPTION(DATATYPE_MISALIGNMENT) - EXCEPTION(BREAKPOINT) - EXCEPTION(SINGLE_STEP) - EXCEPTION(ARRAY_BOUNDS_EXCEEDED) - EXCEPTION(FLT_DENORMAL_OPERAND) - EXCEPTION(FLT_DIVIDE_BY_ZERO) - EXCEPTION(FLT_INEXACT_RESULT) - EXCEPTION(FLT_INVALID_OPERATION) - EXCEPTION(FLT_OVERFLOW) - EXCEPTION(FLT_STACK_CHECK) - EXCEPTION(FLT_UNDERFLOW) - EXCEPTION(INT_DIVIDE_BY_ZERO) - EXCEPTION(INT_OVERFLOW) - EXCEPTION(PRIV_INSTRUCTION) - EXCEPTION(IN_PAGE_ERROR) - EXCEPTION(ILLEGAL_INSTRUCTION) - EXCEPTION(NONCONTINUABLE_EXCEPTION) - EXCEPTION(STACK_OVERFLOW) - EXCEPTION(INVALID_DISPOSITION) - EXCEPTION(GUARD_PAGE) - EXCEPTION(INVALID_HANDLE) - } - - // If not one of the "known" exceptions, try to get the string - // from NTDLL.DLL's message table. - - static TCHAR szBuffer[512] = { 0 }; - - FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, - GetModuleHandle(_T("NTDLL.DLL")), - dwCode, 0, szBuffer, sizeof(szBuffer), 0); - - return szBuffer; -} - -//============================================================================= -// Given a linear address, locates the module, section, and offset containing -// that address. -// -// Note: the szModule paramater buffer is an output buffer of length specified -// by the len parameter (in characters!) -//============================================================================= -BOOL WheatyExceptionReport::GetLogicalAddress( -PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset) -{ - MEMORY_BASIC_INFORMATION mbi; - - if (!VirtualQuery(addr, &mbi, sizeof(mbi))) - return FALSE; - - DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase; - - if (!GetModuleFileName((HMODULE)hMod, szModule, len)) - return FALSE; - - // Point to the DOS header in memory - PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; - - // From the DOS header, find the NT (PE) header - PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + DWORD_PTR(pDosHdr->e_lfanew)); - - PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr); - - DWORD_PTR rva = (DWORD_PTR)addr - hMod; // RVA is offset from module load address - - // Iterate through the section table, looking for the one that encompasses - // the linear address. - for (unsigned i = 0; - i < pNtHdr->FileHeader.NumberOfSections; - i++, pSection++) - { - DWORD_PTR sectionStart = pSection->VirtualAddress; - DWORD_PTR sectionEnd = sectionStart - + DWORD_PTR(max(pSection->SizeOfRawData, pSection->Misc.VirtualSize)); - - // Is the address in this section??? - if ((rva >= sectionStart) && (rva <= sectionEnd)) - { - // Yes, address is in the section. Calculate section and offset, - // and store in the "section" & "offset" params, which were - // passed by reference. - section = i+1; - offset = rva - sectionStart; - return TRUE; - } - } - - return FALSE; // Should never get here! -} - -// It contains SYMBOL_INFO structure plus additional -// space for the name of the symbol -struct CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE -{ - CSymbolInfoPackage() - { - si.SizeOfStruct = sizeof(SYMBOL_INFO); - si.MaxNameLen = sizeof(name); - } -}; - -//============================================================ -// Walks the stack, and writes the results to the report file -//============================================================ -void WheatyExceptionReport::WriteStackDetails( -PCONTEXT pContext, -bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output -{ - _tprintf(_T("\r\nCall stack:\r\n")); - - _tprintf(_T("Address Frame Function SourceFile\r\n")); - - DWORD dwMachineType = 0; - // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag - - STACKFRAME64 sf; - memset(&sf, 0, sizeof(sf)); - - #ifdef _M_IX86 - // Initialize the STACKFRAME structure for the first call. This is only - // necessary for Intel CPUs, and isn't mentioned in the documentation. - sf.AddrPC.Offset = pContext->Eip; - sf.AddrPC.Mode = AddrModeFlat; - sf.AddrStack.Offset = pContext->Esp; - sf.AddrStack.Mode = AddrModeFlat; - sf.AddrFrame.Offset = pContext->Ebp; - sf.AddrFrame.Mode = AddrModeFlat; - - dwMachineType = IMAGE_FILE_MACHINE_I386; - #endif - -#ifdef _M_X64 - sf.AddrPC.Offset = pContext->Rip; - sf.AddrPC.Mode = AddrModeFlat; - sf.AddrStack.Offset = pContext->Rsp; - sf.AddrStack.Mode = AddrModeFlat; - sf.AddrFrame.Offset = pContext->Rbp; - sf.AddrFrame.Mode = AddrModeFlat; - dwMachineType = IMAGE_FILE_MACHINE_AMD64; -#endif - - while (1) - { - // Get the next stack frame - if (! StackWalk64(dwMachineType, - m_hProcess, - pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(), - &sf, - pContext, - 0, - SymFunctionTableAccess64, - SymGetModuleBase64, - 0)) - break; - if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure - break; // the frame is OK. Bail if not. -#ifdef _M_IX86 - _tprintf(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); -#endif -#ifdef _M_X64 - _tprintf(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); -#endif - - DWORD64 symDisplacement = 0; // Displacement of the input address, - // relative to the start of the symbol - - // Get the name of the function for this stack frame entry - CSymbolInfoPackage sip; - if (SymFromAddr( - m_hProcess, // Process handle of the current process - sf.AddrPC.Offset, // Symbol address - &symDisplacement, // Address of the variable that will receive the displacement - &sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object) - { - _tprintf(_T("%hs+%I64X"), sip.si.Name, symDisplacement); - - } - else // No symbol found. Print out the logical address instead. - { - TCHAR szModule[MAX_PATH] = _T(""); - DWORD section = 0; - DWORD_PTR offset = 0; - - GetLogicalAddress((PVOID)sf.AddrPC.Offset, - szModule, sizeof(szModule), section, offset); -#ifdef _M_IX86 - _tprintf(_T("%04X:%08X %s"), section, offset, szModule); -#endif -#ifdef _M_X64 - _tprintf(_T("%04X:%016I64X %s"), section, offset, szModule); -#endif - } - - // Get the source line for this stack frame entry - IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE) }; - DWORD dwLineDisplacement; - if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, - &dwLineDisplacement, &lineInfo)) - { - _tprintf(_T(" %s line %u"),lineInfo.FileName,lineInfo.LineNumber); - } - - _tprintf(_T("\r\n")); - - // Write out the variables, if desired - if (bWriteVariables) - { - // Use SymSetContext to get just the locals/params for this frame - IMAGEHLP_STACK_FRAME imagehlpStackFrame; - imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; - SymSetContext(m_hProcess, &imagehlpStackFrame, 0); - - // Enumerate the locals/parameters - SymEnumSymbols(m_hProcess, 0, 0, EnumerateSymbolsCallback, &sf); - - _tprintf(_T("\r\n")); - } - } - -} - -////////////////////////////////////////////////////////////////////////////// -// The function invoked by SymEnumSymbols -////////////////////////////////////////////////////////////////////////////// - -BOOL CALLBACK -WheatyExceptionReport::EnumerateSymbolsCallback( -PSYMBOL_INFO pSymInfo, -ULONG SymbolSize, -PVOID UserContext) -{ - - char szBuffer[2048]; - - __try - { - if (FormatSymbolValue(pSymInfo, (STACKFRAME*)UserContext, - szBuffer, sizeof(szBuffer))) - _tprintf(_T("\t%s\r\n"), szBuffer); - } - __except(1) - { - _tprintf(_T("punting on symbol %s\r\n"), pSymInfo->Name); - } - - return TRUE; -} - -////////////////////////////////////////////////////////////////////////////// -// Given a SYMBOL_INFO representing a particular variable, displays its -// contents. If it's a user defined type, display the members and their -// values. -////////////////////////////////////////////////////////////////////////////// -bool WheatyExceptionReport::FormatSymbolValue( -PSYMBOL_INFO pSym, -STACKFRAME * sf, -char * pszBuffer, -unsigned cbBuffer) -{ - char * pszCurrBuffer = pszBuffer; - - // Indicate if the variable is a local or parameter - if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) - pszCurrBuffer += sprintf(pszCurrBuffer, "Parameter "); - else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) - pszCurrBuffer += sprintf(pszCurrBuffer, "Local "); - - // If it's a function, don't do anything. - if (pSym->Tag == 5) // SymTagFunction from CVCONST.H from the DIA SDK - return false; - - DWORD_PTR pVariable = 0; // Will point to the variable's data in memory - - if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) - { - // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) - { // This may change!!! - pVariable = sf->AddrFrame.Offset; - pVariable += (DWORD_PTR)pSym->Address; - } - // else - // return false; - } - else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) - { - return false; // Don't try to report register variable - } - else - { - pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable - } - - // Determine if the variable is a user defined type (UDT). IF so, bHandled - // will return true. - bool bHandled; - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer,pSym->ModBase, pSym->TypeIndex, - 0, pVariable, bHandled, pSym->Name); - - if (!bHandled) - { - // The symbol wasn't a UDT, so do basic, stupid formatting of the - // variable. Based on the size, we're assuming it's a char, WORD, or - // DWORD. - BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase); - pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); - - // Emit the variable name - pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", pSym->Name); - - pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, pSym->Size, - (PVOID)pVariable); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////////// -// If it's a user defined type (UDT), recurse through its members until we're -// at fundamental types. When he hit fundamental types, return -// bHandled = false, so that FormatSymbolValue() will format them. -////////////////////////////////////////////////////////////////////////////// -char * WheatyExceptionReport::DumpTypeIndex( -char * pszCurrBuffer, -DWORD64 modBase, -DWORD dwTypeIndex, -unsigned nestingLevel, -DWORD_PTR offset, -bool & bHandled, -char* Name) -{ - bHandled = false; - - // Get the name of the symbol. This will either be a Type name (if a UDT), - // or the structure member name. - WCHAR * pwszTypeName; - if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME, - &pwszTypeName)) - { - pszCurrBuffer += sprintf(pszCurrBuffer, " %ls", pwszTypeName); - LocalFree(pwszTypeName); - } - - // Determine how many children this type has. - DWORD dwChildrenCount = 0; - SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, - &dwChildrenCount); - - if (!dwChildrenCount) // If no children, we're done - return pszCurrBuffer; - - // Prepare to get an array of "TypeIds", representing each of the children. - // SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a - // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this. - struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS - { - ULONG MoreChildIds[1024]; - FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);} - } children; - - children.Count = dwChildrenCount; - children.Start= 0; - - // Get the array of TypeIds, one for each child type - if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN, - &children)) - { - return pszCurrBuffer; - } - - // Append a line feed - pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n"); - - // Iterate through each of the children - for (unsigned i = 0; i < dwChildrenCount; i++) - { - // Add appropriate indentation level (since this routine is recursive) - for (unsigned j = 0; j <= nestingLevel+1; j++) - pszCurrBuffer += sprintf(pszCurrBuffer, "\t"); - - // Recurse for each of the child types - bool bHandled2; - BasicType basicType = GetBasicType(children.ChildId[i], modBase); - pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); - - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, - children.ChildId[i], nestingLevel+1, - offset, bHandled2, ""/*Name */); - - // If the child wasn't a UDT, format it appropriately - if (!bHandled2) - { - // Get the offset of the child member, relative to its parent - DWORD dwMemberOffset; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], - TI_GET_OFFSET, &dwMemberOffset); - - // Get the real "TypeId" of the child. We need this for the - // SymGetTypeInfo(TI_GET_TYPEID) call below. - DWORD typeId; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], - TI_GET_TYPEID, &typeId); - - // Get the size of the child member - ULONG64 length; - SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_LENGTH,&length); - - // Calculate the address of the member - DWORD_PTR dwFinalOffset = offset + dwMemberOffset; - - // BasicType basicType = GetBasicType(children.ChildId[i], modBase); - // - // pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]); - // - // Emit the variable name - // pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", Name); - - pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, - length, (PVOID)dwFinalOffset); - - pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n"); - } - } - - bHandled = true; - return pszCurrBuffer; -} - -char * WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer, -BasicType basicType, -DWORD64 length, -PVOID pAddress) -{ - // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!) - if (length == 1) - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PBYTE)pAddress); - else if (length == 2) - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PWORD)pAddress); - else if (length == 4) - { - if (basicType == btFloat) - { - pszCurrBuffer += sprintf(pszCurrBuffer," = %f", *(PFLOAT)pAddress); - } - else if (basicType == btChar) - { - if (!IsBadStringPtr(*(PSTR*)pAddress, 32)) - { - pszCurrBuffer += sprintf(pszCurrBuffer, " = \"%.31s\"", - *(PDWORD)pAddress); - } - else - pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", - *(PDWORD)pAddress); - } - else - pszCurrBuffer += sprintf(pszCurrBuffer," = %X", *(PDWORD)pAddress); - } - else if (length == 8) - { - if (basicType == btFloat) - { - pszCurrBuffer += sprintf(pszCurrBuffer, " = %lf", - *(double *)pAddress); - } - else - pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X", - *(DWORD64*)pAddress); - } - - return pszCurrBuffer; -} - -BasicType -WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase) -{ - BasicType basicType; - if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, - TI_GET_BASETYPE, &basicType)) - { - return basicType; - } - - // Get the real "TypeId" of the child. We need this for the - // SymGetTypeInfo(TI_GET_TYPEID) call below. - DWORD typeId; - if (SymGetTypeInfo(m_hProcess,modBase, typeIndex, TI_GET_TYPEID, &typeId)) - { - if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE, - &basicType)) - { - return basicType; - } - } - - return btNoType; -} - -//============================================================================ -// Helper function that writes to the report file, and allows the user to use -// printf style formating -//============================================================================ -int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...) -{ - TCHAR szBuff[1024]; - int retValue; - DWORD cbWritten; - va_list argptr; - - va_start(argptr, format); - retValue = vsprintf(szBuff, format, argptr); - va_end(argptr); - - WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0); - - return retValue; -} - diff --git a/src/server/shared/WheatyExceptionReport.h b/src/server/shared/WheatyExceptionReport.h deleted file mode 100644 index 33fb4bc5b0e..00000000000 --- a/src/server/shared/WheatyExceptionReport.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef _WHEATYEXCEPTIONREPORT_ -#define _WHEATYEXCEPTIONREPORT_ - -#include - -#if _MSC_VER < 1400 -# define countof(array) (sizeof(array) / sizeof(array[0])) -#else -# include -# define countof _countof -#endif // _MSC_VER < 1400 - -enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK -{ - btNoType = 0, - btVoid = 1, - btChar = 2, - btWChar = 3, - btInt = 6, - btUInt = 7, - btFloat = 8, - btBCD = 9, - btBool = 10, - btLong = 13, - btULong = 14, - btCurrency = 25, - btDate = 26, - btVariant = 27, - btComplex = 28, - btBit = 29, - btBSTR = 30, - btHresult = 31 -}; - -const char* const rgBaseType[] = -{ - " ", // btNoType = 0, - " void ", // btVoid = 1, - " char* ", // btChar = 2, - " wchar_t* ", // btWChar = 3, - " signed char ", - " unsigned char ", - " int ", // btInt = 6, - " unsigned int ", // btUInt = 7, - " float ", // btFloat = 8, - " ", // btBCD = 9, - " bool ", // btBool = 10, - " short ", - " unsigned short ", - " long ", // btLong = 13, - " unsigned long ", // btULong = 14, - " __int8 ", - " __int16 ", - " __int32 ", - " __int64 ", - " __int128 ", - " unsigned __int8 ", - " unsigned __int16 ", - " unsigned __int32 ", - " unsigned __int64 ", - " unsigned __int128 ", - " ", // btCurrency = 25, - " ", // btDate = 26, - " VARIANT ", // btVariant = 27, - " ", // btComplex = 28, - " ", // btBit = 29, - " BSTR ", // btBSTR = 30, - " HRESULT " // btHresult = 31 -}; - -class WheatyExceptionReport -{ - public: - - WheatyExceptionReport(); - ~WheatyExceptionReport(); - - // entry point where control comes on an unhandled exception - static LONG WINAPI WheatyUnhandledExceptionFilter( - PEXCEPTION_POINTERS pExceptionInfo); - - static void printTracesForAllThreads(); - private: - // where report info is extracted and generated - static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo); - static void PrintSystemInfo(); - static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax); - static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount); - - // Helper functions - static LPTSTR GetExceptionString(DWORD dwCode); - static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len, - DWORD& section, DWORD_PTR& offset); - - static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle); - - static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO,ULONG, PVOID); - - static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer); - - static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool & , char*); - - static char * FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress); - - static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase); - - static int __cdecl _tprintf(const TCHAR * format, ...); - - // Variables used by the class - static TCHAR m_szLogFileName[MAX_PATH]; - static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; - static HANDLE m_hReportFile; - static HANDLE m_hProcess; -}; - -extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class -#endif //WheatyExceptionReport - diff --git a/src/server/shared/WorldPacket.h b/src/server/shared/WorldPacket.h deleted file mode 100644 index d708959f91d..00000000000 --- a/src/server/shared/WorldPacket.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_WORLDPACKET_H -#define TRINITYCORE_WORLDPACKET_H - -#include "Common.h" -#include "ByteBuffer.h" - -class WorldPacket : public ByteBuffer -{ - public: - // just container for later use - WorldPacket() : ByteBuffer(0), m_opcode(0) - { - } - explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { } - // copy constructor - WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) - { - } - - void Initialize(uint16 opcode, size_t newres=200) - { - clear(); - _storage.reserve(newres); - m_opcode = opcode; - } - - uint16 GetOpcode() const { return m_opcode; } - void SetOpcode(uint16 opcode) { m_opcode = opcode; } - - protected: - uint16 m_opcode; -}; -#endif - -- cgit v1.2.3 From 6cb5f529d647bc89aad4025f6eea0ccb68633546 Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:19:22 +0200 Subject: * Useless files. --HG-- branch : trunk --- src/server/shared/PacketLog.cpp | 160 ---------------------------------------- src/server/shared/PacketLog.h | 49 ------------ 2 files changed, 209 deletions(-) delete mode 100644 src/server/shared/PacketLog.cpp delete mode 100644 src/server/shared/PacketLog.h (limited to 'src/server') diff --git a/src/server/shared/PacketLog.cpp b/src/server/shared/PacketLog.cpp deleted file mode 100644 index 4e5cad69605..00000000000 --- a/src/server/shared/PacketLog.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "PacketLog.h" -#include "Config/ConfigEnv.h" -#include "Policies/SingletonImpl.h" - -#include - -INSTANTIATE_SINGLETON_1( PacketLog ); - -PacketLog::PacketLog() -{ - - if (sConfig.GetBoolDefault("LogRealm", false)) - { - FILE *pFile = fopen("realm.log", "w+"); - fclose(pFile); - } - - if (sConfig.GetBoolDefault("LogWorld", false)) - { - FILE *pFile = fopen("world.log", "w+"); - fclose(pFile); - } -} - -PacketLog::~PacketLog() -{ -} - -char PacketLog::makehexchar(int i) -{ - return (i<=9) ? '0'+i : 'A'+(i-10); -} - -int PacketLog::hextoint(char c) -{ - c = toupper(c); - return (c > '9' ? c - 'A' + 10 : c - '0'); -} - -void PacketLog::HexDump(const unsigned char* data, size_t length, const char* file) -{ - FILE *pFile; - pFile = fopen(file, "a"); - - const int char_offset = 16*3 + 2; - const int line_size = 16*3 + 16 + 3; - char line[line_size+1]; - - fprintf(pFile,"OFFSET 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 0123456789ABCDEF\n"); - fprintf(pFile,"--------------------------------------------------------------------------\n"); - - line[char_offset - 1] = ' '; - line[char_offset - 2] = ' '; - - for (size_t i=0; i>4); - line[bi++] = makehexchar(*data & 0x0f); - line[bi++] = ' '; - line[char_offset+(ci++)]=(isprint(*data) ? *data : '.'); - ++data; - } - - while (bi<16*3) - { - line[bi++]=' '; - } - - line[char_offset+(ci++)]='\n'; - line[char_offset+ci]=0; - - fprintf(pFile,"%06X %s", start_i, line); - } - fprintf(pFile, "\n\n"); - fclose(pFile); -} - -void PacketLog::HexDump(const char *data, size_t length, const char* file) -{ - HexDump((unsigned char *)data, length, file); -} - -void PacketLog::HexDumpStr(const char *msg, const char *data, size_t len, const char* file) -{ - FILE *pFile; - pFile = fopen(file, "a"); - fprintf(pFile,"%s\n", msg); - fclose(pFile); - - HexDump(data, len, file); -} - -void PacketLog::RealmHexDump(RealmPacket* data, uint32 socket, bool direction) -{ - if (!sConfig.GetBoolDefault("LogRealm", false)) - return; - - FILE *pFile; - pFile = fopen("realm.log", "a"); - - uint16 len = data->size() + 2; - uint8 opcode = data->GetOpcode(); - if (direction) - fprintf(pFile, "SERVER:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.2X\nDATA:\n", socket, len, opcode); - else - fprintf(pFile, "CLIENT:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.2X\nDATA:\n", socket, len, opcode); - - fclose(pFile); - HexDump((char *)data->contents(), data->size(), "realm.log"); - -} - -void PacketLog::WorldHexDump(WorldPacket* data, uint32 socket, bool direction) -{ - if (!sConfig.GetBoolDefault("LogWorld", false)) - return; - - FILE *pFile; - pFile = fopen("world.log", "a"); - - uint16 len = data->size(); - uint16 opcode = data->GetOpcode(); - if (direction) - fprintf(pFile, "SERVER:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.4X\nDATA:\n", socket, len, opcode); - else - fprintf(pFile, "CLIENT:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.4X\nDATA:\n", socket, len, opcode); - - fclose(pFile); - HexDump((char *)data->contents(), data->size(), "world.log"); - -} - diff --git a/src/server/shared/PacketLog.h b/src/server/shared/PacketLog.h deleted file mode 100644 index 462cc1eed51..00000000000 --- a/src/server/shared/PacketLog.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITYCORE_PACKETLOG_H -#define TRINITYCORE_PACKETLOG_H - -#include "Common.h" -#include "Policies/Singleton.h" -#include "RealmPacket.h" -#include "WorldPacket.h" - -class PacketLog -{ - public: - PacketLog(); - ~PacketLog(); - - int hextoint(char c); - char makehexchar(int i); - - void HexDump(const unsigned char* data, size_t length, const char* file); - void HexDump(const char *data, size_t length, const char* file); - void HexDumpStr(const char *msg, const char *data, size_t len, const char* file); - - void RealmHexDump(RealmPacket * data, uint32 socket, bool direction); - - void WorldHexDump(WorldPacket * data, uint32 socket, bool direction); -}; - -#define sPacketLog Trinity::Singleton::Instance() -#endif - -- cgit v1.2.3 From 309333ffffcef1ae74adf3781b57fc699b684bcf Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:23:22 +0200 Subject: * Rename some cryptographic files. --HG-- branch : trunk --- src/server/shared/Cryptography/ARC4.cpp | 52 ++++++++++++++++++++++++ src/server/shared/Cryptography/ARC4.h | 36 +++++++++++++++++ src/server/shared/Cryptography/HMACSHA1.cpp | 62 +++++++++++++++++++++++++++++ src/server/shared/Cryptography/HMACSHA1.h | 49 +++++++++++++++++++++++ src/server/shared/Cryptography/Hmac.cpp | 62 ----------------------------- src/server/shared/Cryptography/Hmac.h | 49 ----------------------- src/server/shared/Cryptography/SARC4.cpp | 52 ------------------------ src/server/shared/Cryptography/SARC4.h | 36 ----------------- 8 files changed, 199 insertions(+), 199 deletions(-) create mode 100644 src/server/shared/Cryptography/ARC4.cpp create mode 100644 src/server/shared/Cryptography/ARC4.h create mode 100644 src/server/shared/Cryptography/HMACSHA1.cpp create mode 100644 src/server/shared/Cryptography/HMACSHA1.h delete mode 100644 src/server/shared/Cryptography/Hmac.cpp delete mode 100644 src/server/shared/Cryptography/Hmac.h delete mode 100644 src/server/shared/Cryptography/SARC4.cpp delete mode 100644 src/server/shared/Cryptography/SARC4.h (limited to 'src/server') diff --git a/src/server/shared/Cryptography/ARC4.cpp b/src/server/shared/Cryptography/ARC4.cpp new file mode 100644 index 00000000000..80cad4991e9 --- /dev/null +++ b/src/server/shared/Cryptography/ARC4.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/SARC4.h" +#include + +SARC4::SARC4(uint8 len) +{ + EVP_CIPHER_CTX_init(&m_ctx); + EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); + EVP_CIPHER_CTX_set_key_length(&m_ctx, len); +} + +SARC4::SARC4(uint8 *seed, uint8 len) +{ + EVP_CIPHER_CTX_init(&m_ctx); + EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); + EVP_CIPHER_CTX_set_key_length(&m_ctx, len); + EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); +} + +SARC4::~SARC4() +{ + EVP_CIPHER_CTX_cleanup(&m_ctx); +} + +void SARC4::Init(uint8 *seed) +{ + EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); +} + +void SARC4::UpdateData(int len, uint8 *data) +{ + int outlen = 0; + EVP_EncryptUpdate(&m_ctx, data, &outlen, data, len); + EVP_EncryptFinal_ex(&m_ctx, data, &outlen); +} diff --git a/src/server/shared/Cryptography/ARC4.h b/src/server/shared/Cryptography/ARC4.h new file mode 100644 index 00000000000..2e408627fc8 --- /dev/null +++ b/src/server/shared/Cryptography/ARC4.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_SARC4_H +#define _AUTH_SARC4_H + +#include "Common.h" +#include + +class SARC4 +{ + public: + SARC4(uint8 len); + SARC4(uint8 *seed, uint8 len); + ~SARC4(); + void Init(uint8 *seed); + void UpdateData(int len, uint8 *data); + private: + EVP_CIPHER_CTX m_ctx; +}; +#endif diff --git a/src/server/shared/Cryptography/HMACSHA1.cpp b/src/server/shared/Cryptography/HMACSHA1.cpp new file mode 100644 index 00000000000..a30f1b2d1e2 --- /dev/null +++ b/src/server/shared/Cryptography/HMACSHA1.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/Hmac.h" +#include "BigNumber.h" + +HmacHash::HmacHash(uint32 len, uint8 *seed) +{ + HMAC_CTX_init(&m_ctx); + HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL); +} + +HmacHash::~HmacHash() +{ + HMAC_CTX_cleanup(&m_ctx); +} + +void HmacHash::UpdateBigNumber(BigNumber *bn) +{ + UpdateData(bn->AsByteArray(), bn->GetNumBytes()); +} + +void HmacHash::UpdateData(const uint8 *data, int length) +{ + HMAC_Update(&m_ctx, data, length); +} + +void HmacHash::UpdateData(const std::string &str) +{ + UpdateData((uint8 const*)str.c_str(), str.length()); +} + +void HmacHash::Finalize() +{ + uint32 length = 0; + HMAC_Final(&m_ctx, (uint8*)m_digest, &length); + ASSERT(length == SHA_DIGEST_LENGTH) +} + +uint8 *HmacHash::ComputeHash(BigNumber *bn) +{ + HMAC_Update(&m_ctx, bn->AsByteArray(), bn->GetNumBytes()); + Finalize(); + return (uint8*)m_digest; +} diff --git a/src/server/shared/Cryptography/HMACSHA1.h b/src/server/shared/Cryptography/HMACSHA1.h new file mode 100644 index 00000000000..845d6e84802 --- /dev/null +++ b/src/server/shared/Cryptography/HMACSHA1.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_HMAC_H +#define _AUTH_HMAC_H + +#include "Common.h" +#include +#include + +class BigNumber; + +#define SEED_KEY_SIZE 16 + +class HmacHash +{ + public: + HmacHash(uint32 len, uint8 *seed); + ~HmacHash(); + void UpdateBigNumber(BigNumber *bn); + void UpdateData(const uint8 *data, int length); + void UpdateData(const std::string &str); + void Finalize(); + uint8 *ComputeHash(BigNumber *bn); + uint8 *GetDigest() { return (uint8*)m_digest; } + int GetLength() { return SHA_DIGEST_LENGTH; } + private: + HMAC_CTX m_ctx; + uint8 m_digest[SHA_DIGEST_LENGTH]; +}; +#endif + diff --git a/src/server/shared/Cryptography/Hmac.cpp b/src/server/shared/Cryptography/Hmac.cpp deleted file mode 100644 index a30f1b2d1e2..00000000000 --- a/src/server/shared/Cryptography/Hmac.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/Hmac.h" -#include "BigNumber.h" - -HmacHash::HmacHash(uint32 len, uint8 *seed) -{ - HMAC_CTX_init(&m_ctx); - HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL); -} - -HmacHash::~HmacHash() -{ - HMAC_CTX_cleanup(&m_ctx); -} - -void HmacHash::UpdateBigNumber(BigNumber *bn) -{ - UpdateData(bn->AsByteArray(), bn->GetNumBytes()); -} - -void HmacHash::UpdateData(const uint8 *data, int length) -{ - HMAC_Update(&m_ctx, data, length); -} - -void HmacHash::UpdateData(const std::string &str) -{ - UpdateData((uint8 const*)str.c_str(), str.length()); -} - -void HmacHash::Finalize() -{ - uint32 length = 0; - HMAC_Final(&m_ctx, (uint8*)m_digest, &length); - ASSERT(length == SHA_DIGEST_LENGTH) -} - -uint8 *HmacHash::ComputeHash(BigNumber *bn) -{ - HMAC_Update(&m_ctx, bn->AsByteArray(), bn->GetNumBytes()); - Finalize(); - return (uint8*)m_digest; -} diff --git a/src/server/shared/Cryptography/Hmac.h b/src/server/shared/Cryptography/Hmac.h deleted file mode 100644 index 845d6e84802..00000000000 --- a/src/server/shared/Cryptography/Hmac.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_HMAC_H -#define _AUTH_HMAC_H - -#include "Common.h" -#include -#include - -class BigNumber; - -#define SEED_KEY_SIZE 16 - -class HmacHash -{ - public: - HmacHash(uint32 len, uint8 *seed); - ~HmacHash(); - void UpdateBigNumber(BigNumber *bn); - void UpdateData(const uint8 *data, int length); - void UpdateData(const std::string &str); - void Finalize(); - uint8 *ComputeHash(BigNumber *bn); - uint8 *GetDigest() { return (uint8*)m_digest; } - int GetLength() { return SHA_DIGEST_LENGTH; } - private: - HMAC_CTX m_ctx; - uint8 m_digest[SHA_DIGEST_LENGTH]; -}; -#endif - diff --git a/src/server/shared/Cryptography/SARC4.cpp b/src/server/shared/Cryptography/SARC4.cpp deleted file mode 100644 index 80cad4991e9..00000000000 --- a/src/server/shared/Cryptography/SARC4.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/SARC4.h" -#include - -SARC4::SARC4(uint8 len) -{ - EVP_CIPHER_CTX_init(&m_ctx); - EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); - EVP_CIPHER_CTX_set_key_length(&m_ctx, len); -} - -SARC4::SARC4(uint8 *seed, uint8 len) -{ - EVP_CIPHER_CTX_init(&m_ctx); - EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); - EVP_CIPHER_CTX_set_key_length(&m_ctx, len); - EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); -} - -SARC4::~SARC4() -{ - EVP_CIPHER_CTX_cleanup(&m_ctx); -} - -void SARC4::Init(uint8 *seed) -{ - EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); -} - -void SARC4::UpdateData(int len, uint8 *data) -{ - int outlen = 0; - EVP_EncryptUpdate(&m_ctx, data, &outlen, data, len); - EVP_EncryptFinal_ex(&m_ctx, data, &outlen); -} diff --git a/src/server/shared/Cryptography/SARC4.h b/src/server/shared/Cryptography/SARC4.h deleted file mode 100644 index 2e408627fc8..00000000000 --- a/src/server/shared/Cryptography/SARC4.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_SARC4_H -#define _AUTH_SARC4_H - -#include "Common.h" -#include - -class SARC4 -{ - public: - SARC4(uint8 len); - SARC4(uint8 *seed, uint8 len); - ~SARC4(); - void Init(uint8 *seed); - void UpdateData(int len, uint8 *data); - private: - EVP_CIPHER_CTX m_ctx; -}; -#endif -- cgit v1.2.3 From 5358270186312655556e8b6cd6b2dc39b18f4a44 Mon Sep 17 00:00:00 2001 From: Tartalo Date: Sun, 6 Jun 2010 23:29:55 +0200 Subject: Case sensitive renames on shared/ Fuck windows and insensitiveness --HG-- branch : trunk rename : src/server/shared/Cryptography/md5.c => src/server/shared/Cryptography/MD5.c rename : src/server/shared/Cryptography/md5.h => src/server/shared/Cryptography/MD5.h rename : src/server/shared/Cryptography/Sha1.cpp => src/server/shared/Cryptography/SHA1.cpp rename : src/server/shared/Cryptography/Sha1.h => src/server/shared/Cryptography/SHA1.h --- src/server/shared/Cryptography/MD5.c | 385 ++++++++++++++++++++++++++++++++ src/server/shared/Cryptography/MD5.h | 92 ++++++++ src/server/shared/Cryptography/SHA1.cpp | 69 ++++++ src/server/shared/Cryptography/SHA1.h | 53 +++++ src/server/shared/Cryptography/Sha1.cpp | 69 ------ src/server/shared/Cryptography/Sha1.h | 53 ----- src/server/shared/Cryptography/md5.c | 385 -------------------------------- src/server/shared/Cryptography/md5.h | 92 -------- 8 files changed, 599 insertions(+), 599 deletions(-) create mode 100644 src/server/shared/Cryptography/MD5.c create mode 100644 src/server/shared/Cryptography/MD5.h create mode 100644 src/server/shared/Cryptography/SHA1.cpp create mode 100644 src/server/shared/Cryptography/SHA1.h delete mode 100644 src/server/shared/Cryptography/Sha1.cpp delete mode 100644 src/server/shared/Cryptography/Sha1.h delete mode 100644 src/server/shared/Cryptography/md5.c delete mode 100644 src/server/shared/Cryptography/md5.h (limited to 'src/server') diff --git a/src/server/shared/Cryptography/MD5.c b/src/server/shared/Cryptography/MD5.c new file mode 100644 index 00000000000..3e9735e2dbb --- /dev/null +++ b/src/server/shared/Cryptography/MD5.c @@ -0,0 +1,385 @@ +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +*/ +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + +The original and principal author of md5.c is L. Peter Deutsch +. Other authors are noted in the change history +that follows (in reverse chronological order): + +2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order +either statically or dynamically; added missing #include +in library. +2002-03-11 lpd Corrected argument list for main(), and added int return +type, in test program and T value program. +2002-02-21 lpd Added missing #include in test program. +2000-07-03 lpd Patched to eliminate warnings about "constant is +unsigned in ANSI C, signed in traditional"; made test program +self-checking. +1999-11-04 lpd Edited comments slightly for automatic TOC extraction. +1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). +1999-05-03 lpd Original version. +*/ + +#include "md5.h" +#include + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + #if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; + #else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + const md5_word_t *X; + #endif + + { + #if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ + #endif + #if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) + { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } + else + { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } + #endif + #if BYTE_ORDER == 0 + else /* dynamic big-endian */ + #endif + #if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + + # if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ + # else + # define xbuf X /* (static only) */ + # endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } + #endif + } + + #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ + #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); + #undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ + #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); + #undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ + #define H(x, y, z) ((x) ^ (y) ^ (z)) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); + #undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ + #define I(x, y, z) ((y) ^ ((x) | ~(z))) + #define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); + #undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + ++pms->count[1]; + + /* Process an initial partial block. */ + if (offset) + { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = + { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/server/shared/Cryptography/MD5.h b/src/server/shared/Cryptography/MD5.h new file mode 100644 index 00000000000..0463051b6a6 --- /dev/null +++ b/src/server/shared/Cryptography/MD5.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +*/ +/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + +The original and principal author of md5.h is L. Peter Deutsch +. Other authors are noted in the change history +that follows (in reverse chronological order): + +2002-04-13 lpd Removed support for non-ANSI compilers; removed +references to Ghostscript; clarified derivation from RFC 1321; +now handles byte order either statically or dynamically. +1999-11-04 lpd Edited comments slightly for automatic TOC extraction. +1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); +added conditionalization for C++ compilation from Martin +Purschke . +1999-05-03 lpd Original version. +*/ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s +{ + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ + #endif + + /* Initialize the algorithm. */ + void md5_init(md5_state_t *pms); + + /* Append a string to the message. */ + void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); + + /* Finish the message and return the digest. */ + void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + + #ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif /* md5_INCLUDED */ + diff --git a/src/server/shared/Cryptography/SHA1.cpp b/src/server/shared/Cryptography/SHA1.cpp new file mode 100644 index 00000000000..b63deb2c5f3 --- /dev/null +++ b/src/server/shared/Cryptography/SHA1.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Auth/Sha1.h" +#include "Auth/BigNumber.h" +#include + +Sha1Hash::Sha1Hash() +{ + SHA1_Init(&mC); +} + +Sha1Hash::~Sha1Hash() +{ + SHA1_Init(&mC); +} + +void Sha1Hash::UpdateData(const uint8 *dta, int len) +{ + SHA1_Update(&mC, dta, len); +} + +void Sha1Hash::UpdateData(const std::string &str) +{ + UpdateData((uint8 const*)str.c_str(), str.length()); +} + +void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...) +{ + va_list v; + BigNumber *bn; + + va_start(v, bn0); + bn = bn0; + while (bn) + { + UpdateData(bn->AsByteArray(), bn->GetNumBytes()); + bn = va_arg(v, BigNumber *); + } + va_end(v); +} + +void Sha1Hash::Initialize() +{ + SHA1_Init(&mC); +} + +void Sha1Hash::Finalize(void) +{ + SHA1_Final(mDigest, &mC); +} + diff --git a/src/server/shared/Cryptography/SHA1.h b/src/server/shared/Cryptography/SHA1.h new file mode 100644 index 00000000000..2d7f361ae9a --- /dev/null +++ b/src/server/shared/Cryptography/SHA1.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _AUTH_SHA1_H +#define _AUTH_SHA1_H + +#include "Common.h" +#include +#include + +class BigNumber; + +class Sha1Hash +{ + public: + Sha1Hash(); + ~Sha1Hash(); + + void UpdateFinalizeBigNumbers(BigNumber *bn0, ...); + void UpdateBigNumbers(BigNumber *bn0, ...); + + void UpdateData(const uint8 *dta, int len); + void UpdateData(const std::string &str); + + void Initialize(); + void Finalize(); + + uint8 *GetDigest(void) { return mDigest; }; + int GetLength(void) { return SHA_DIGEST_LENGTH; }; + + private: + SHA_CTX mC; + uint8 mDigest[SHA_DIGEST_LENGTH]; +}; +#endif + diff --git a/src/server/shared/Cryptography/Sha1.cpp b/src/server/shared/Cryptography/Sha1.cpp deleted file mode 100644 index b63deb2c5f3..00000000000 --- a/src/server/shared/Cryptography/Sha1.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Auth/Sha1.h" -#include "Auth/BigNumber.h" -#include - -Sha1Hash::Sha1Hash() -{ - SHA1_Init(&mC); -} - -Sha1Hash::~Sha1Hash() -{ - SHA1_Init(&mC); -} - -void Sha1Hash::UpdateData(const uint8 *dta, int len) -{ - SHA1_Update(&mC, dta, len); -} - -void Sha1Hash::UpdateData(const std::string &str) -{ - UpdateData((uint8 const*)str.c_str(), str.length()); -} - -void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...) -{ - va_list v; - BigNumber *bn; - - va_start(v, bn0); - bn = bn0; - while (bn) - { - UpdateData(bn->AsByteArray(), bn->GetNumBytes()); - bn = va_arg(v, BigNumber *); - } - va_end(v); -} - -void Sha1Hash::Initialize() -{ - SHA1_Init(&mC); -} - -void Sha1Hash::Finalize(void) -{ - SHA1_Final(mDigest, &mC); -} - diff --git a/src/server/shared/Cryptography/Sha1.h b/src/server/shared/Cryptography/Sha1.h deleted file mode 100644 index 2d7f361ae9a..00000000000 --- a/src/server/shared/Cryptography/Sha1.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTH_SHA1_H -#define _AUTH_SHA1_H - -#include "Common.h" -#include -#include - -class BigNumber; - -class Sha1Hash -{ - public: - Sha1Hash(); - ~Sha1Hash(); - - void UpdateFinalizeBigNumbers(BigNumber *bn0, ...); - void UpdateBigNumbers(BigNumber *bn0, ...); - - void UpdateData(const uint8 *dta, int len); - void UpdateData(const std::string &str); - - void Initialize(); - void Finalize(); - - uint8 *GetDigest(void) { return mDigest; }; - int GetLength(void) { return SHA_DIGEST_LENGTH; }; - - private: - SHA_CTX mC; - uint8 mDigest[SHA_DIGEST_LENGTH]; -}; -#endif - diff --git a/src/server/shared/Cryptography/md5.c b/src/server/shared/Cryptography/md5.c deleted file mode 100644 index 3e9735e2dbb..00000000000 --- a/src/server/shared/Cryptography/md5.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -*/ -/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - -The original and principal author of md5.c is L. Peter Deutsch -. Other authors are noted in the change history -that follows (in reverse chronological order): - -2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order -either statically or dynamically; added missing #include -in library. -2002-03-11 lpd Corrected argument list for main(), and added int return -type, in test program and T value program. -2002-02-21 lpd Added missing #include in test program. -2000-07-03 lpd Patched to eliminate warnings about "constant is -unsigned in ANSI C, signed in traditional"; made test program -self-checking. -1999-11-04 lpd Edited comments slightly for automatic TOC extraction. -1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). -1999-05-03 lpd Original version. -*/ - -#include "md5.h" -#include - -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ -#ifdef ARCH_IS_BIG_ENDIAN -# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) -#else -# define BYTE_ORDER 0 -#endif - -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; - #if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; - #else - /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; - #endif - - { - #if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ - #endif - #if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t *)0) & 3)) - { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } - else - { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } - #endif - #if BYTE_ORDER == 0 - else /* dynamic big-endian */ - #endif - #if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t *xp = data; - int i; - - # if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ - # else - # define xbuf X /* (static only) */ - # endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } - #endif - } - - #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ - #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); - #undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ - #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); - #undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ - #define H(x, y, z) ((x) ^ (y) ^ (z)) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); - #undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ - #define I(x, y, z) ((y) ^ ((x) | ~(z))) - #define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); - #undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - ++pms->count[1]; - - /* Process an initial partial block. */ - if (offset) - { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = - { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} diff --git a/src/server/shared/Cryptography/md5.h b/src/server/shared/Cryptography/md5.h deleted file mode 100644 index 0463051b6a6..00000000000 --- a/src/server/shared/Cryptography/md5.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -*/ -/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - -The original and principal author of md5.h is L. Peter Deutsch -. Other authors are noted in the change history -that follows (in reverse chronological order): - -2002-04-13 lpd Removed support for non-ANSI compilers; removed -references to Ghostscript; clarified derivation from RFC 1321; -now handles byte order either statically or dynamically. -1999-11-04 lpd Edited comments slightly for automatic TOC extraction. -1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); -added conditionalization for C++ compilation from Martin -Purschke . -1999-05-03 lpd Original version. -*/ - -#ifndef md5_INCLUDED -# define md5_INCLUDED - -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s -{ - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ - #endif - - /* Initialize the algorithm. */ - void md5_init(md5_state_t *pms); - - /* Append a string to the message. */ - void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); - - /* Finish the message and return the digest. */ - void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); - - #ifdef __cplusplus -} /* end extern "C" */ -#endif -#endif /* md5_INCLUDED */ - -- cgit v1.2.3 From 7cb74345e049c3f39631dbd3ee2f028ca6ed4076 Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:30:25 +0200 Subject: * Move VMap code to game. --HG-- branch : trunk --- src/server/game/CollisionDetection/BIH.cpp | 304 ++++++++++++ src/server/game/CollisionDetection/BIH.h | 391 +++++++++++++++ src/server/game/CollisionDetection/CMakeLists.txt | 30 ++ src/server/game/CollisionDetection/IVMapManager.h | 106 ++++ src/server/game/CollisionDetection/MapTree.cpp | 450 +++++++++++++++++ src/server/game/CollisionDetection/MapTree.h | 97 ++++ .../game/CollisionDetection/ModelInstance.cpp | 219 +++++++++ src/server/game/CollisionDetection/ModelInstance.h | 81 ++++ .../game/CollisionDetection/TileAssembler.cpp | 494 +++++++++++++++++++ src/server/game/CollisionDetection/TileAssembler.h | 89 ++++ .../game/CollisionDetection/VMapDefinitions.h | 42 ++ src/server/game/CollisionDetection/VMapFactory.cpp | 136 ++++++ src/server/game/CollisionDetection/VMapFactory.h | 43 ++ .../game/CollisionDetection/VMapManager2.cpp | 336 +++++++++++++ src/server/game/CollisionDetection/VMapManager2.h | 114 +++++ src/server/game/CollisionDetection/VMapTools.h | 150 ++++++ src/server/game/CollisionDetection/WorldModel.cpp | 535 +++++++++++++++++++++ src/server/game/CollisionDetection/WorldModel.h | 123 +++++ src/server/shared/vmap/BIH.cpp | 304 ------------ src/server/shared/vmap/BIH.h | 391 --------------- src/server/shared/vmap/CMakeLists.txt | 30 -- src/server/shared/vmap/IVMapManager.h | 106 ---- src/server/shared/vmap/MapTree.cpp | 450 ----------------- src/server/shared/vmap/MapTree.h | 97 ---- src/server/shared/vmap/ModelInstance.cpp | 219 --------- src/server/shared/vmap/ModelInstance.h | 81 ---- src/server/shared/vmap/TileAssembler.cpp | 494 ------------------- src/server/shared/vmap/TileAssembler.h | 89 ---- src/server/shared/vmap/VMapDefinitions.h | 42 -- src/server/shared/vmap/VMapFactory.cpp | 136 ------ src/server/shared/vmap/VMapFactory.h | 43 -- src/server/shared/vmap/VMapManager2.cpp | 336 ------------- src/server/shared/vmap/VMapManager2.h | 114 ----- src/server/shared/vmap/VMapTools.h | 150 ------ src/server/shared/vmap/WorldModel.cpp | 535 --------------------- src/server/shared/vmap/WorldModel.h | 123 ----- 36 files changed, 3740 insertions(+), 3740 deletions(-) create mode 100644 src/server/game/CollisionDetection/BIH.cpp create mode 100644 src/server/game/CollisionDetection/BIH.h create mode 100644 src/server/game/CollisionDetection/CMakeLists.txt create mode 100644 src/server/game/CollisionDetection/IVMapManager.h create mode 100644 src/server/game/CollisionDetection/MapTree.cpp create mode 100644 src/server/game/CollisionDetection/MapTree.h create mode 100644 src/server/game/CollisionDetection/ModelInstance.cpp create mode 100644 src/server/game/CollisionDetection/ModelInstance.h create mode 100644 src/server/game/CollisionDetection/TileAssembler.cpp create mode 100644 src/server/game/CollisionDetection/TileAssembler.h create mode 100644 src/server/game/CollisionDetection/VMapDefinitions.h create mode 100644 src/server/game/CollisionDetection/VMapFactory.cpp create mode 100644 src/server/game/CollisionDetection/VMapFactory.h create mode 100644 src/server/game/CollisionDetection/VMapManager2.cpp create mode 100644 src/server/game/CollisionDetection/VMapManager2.h create mode 100644 src/server/game/CollisionDetection/VMapTools.h create mode 100644 src/server/game/CollisionDetection/WorldModel.cpp create mode 100644 src/server/game/CollisionDetection/WorldModel.h delete mode 100644 src/server/shared/vmap/BIH.cpp delete mode 100644 src/server/shared/vmap/BIH.h delete mode 100644 src/server/shared/vmap/CMakeLists.txt delete mode 100644 src/server/shared/vmap/IVMapManager.h delete mode 100644 src/server/shared/vmap/MapTree.cpp delete mode 100644 src/server/shared/vmap/MapTree.h delete mode 100644 src/server/shared/vmap/ModelInstance.cpp delete mode 100644 src/server/shared/vmap/ModelInstance.h delete mode 100644 src/server/shared/vmap/TileAssembler.cpp delete mode 100644 src/server/shared/vmap/TileAssembler.h delete mode 100644 src/server/shared/vmap/VMapDefinitions.h delete mode 100644 src/server/shared/vmap/VMapFactory.cpp delete mode 100644 src/server/shared/vmap/VMapFactory.h delete mode 100644 src/server/shared/vmap/VMapManager2.cpp delete mode 100644 src/server/shared/vmap/VMapManager2.h delete mode 100644 src/server/shared/vmap/VMapTools.h delete mode 100644 src/server/shared/vmap/WorldModel.cpp delete mode 100644 src/server/shared/vmap/WorldModel.h (limited to 'src/server') diff --git a/src/server/game/CollisionDetection/BIH.cpp b/src/server/game/CollisionDetection/BIH.cpp new file mode 100644 index 00000000000..4bd6b3c701e --- /dev/null +++ b/src/server/game/CollisionDetection/BIH.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BIH.h" + +void BIH::buildHierarchy(std::vector &tempTree, buildData &dat, BuildStats &stats) +{ + // create space for the first node + tempTree.push_back(3 << 30); // dummy leaf + tempTree.insert(tempTree.end(), 2, 0); + //tempTree.add(0); + + // seed bbox + AABound gridBox = { bounds.low(), bounds.high() }; + AABound nodeBox = gridBox; + // seed subdivide function + subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats); +} + +void BIH::subdivide(int left, int right, std::vector &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats) +{ + if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE) + { + // write leaf node + stats.updateLeaf(depth, right - left + 1); + createNode(tempTree, nodeIndex, left, right); + return; + } + // calculate extents + int axis = -1, prevAxis, rightOrig; + float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan(); + float split = G3D::fnan(), prevSplit; + bool wasLeft = true; + while (true) + { + prevAxis = axis; + prevSplit = split; + // perform quick consistency checks + Vector3 d( gridBox.hi - gridBox.lo ); + if (d.x < 0 || d.y < 0 || d.z < 0) + throw std::logic_error("negative node extents"); + for (int i = 0; i < 3; i++) + { + if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i]) + { + //UI.printError(Module.ACCEL, "Reached tree area in error - discarding node with: %d objects", right - left + 1); + throw std::logic_error("invalid node overlap"); + } + } + // find longest axis + axis = d.primaryAxis(); + split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]); + // partition L/R subsets + clipL = -G3D::inf(); + clipR = G3D::inf(); + rightOrig = right; // save this for later + float nodeL = G3D::inf(); + float nodeR = -G3D::inf(); + for (int i = left; i <= right;) + { + int obj = dat.indices[i]; + float minb = dat.primBound[obj].low()[axis]; + float maxb = dat.primBound[obj].high()[axis]; + float center = (minb + maxb) * 0.5f; + if (center <= split) + { + // stay left + i++; + if (clipL < maxb) + clipL = maxb; + } + else + { + // move to the right most + int t = dat.indices[i]; + dat.indices[i] = dat.indices[right]; + dat.indices[right] = t; + right--; + if (clipR > minb) + clipR = minb; + } + nodeL = std::min(nodeL, minb); + nodeR = std::max(nodeR, maxb); + } + // check for empty space + if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis]) + { + float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis]; + float nodeNewW = nodeR - nodeL; + // node box is too big compare to space occupied by primitives? + if (1.3f * nodeNewW < nodeBoxW) + { + stats.updateBVH2(); + int nextIndex = tempTree.size(); + // allocate child + tempTree.push_back(0); + tempTree.push_back(0); + tempTree.push_back(0); + // write bvh2 clip node + stats.updateInner(); + tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex; + tempTree[nodeIndex + 1] = floatToRawIntBits(nodeL); + tempTree[nodeIndex + 2] = floatToRawIntBits(nodeR); + // update nodebox and recurse + nodeBox.lo[axis] = nodeL; + nodeBox.hi[axis] = nodeR; + subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats); + return; + } + } + // ensure we are making progress in the subdivision + if (right == rightOrig) + { + // all left + if (prevAxis == axis && prevSplit == split) { + // we are stuck here - create a leaf + stats.updateLeaf(depth, right - left + 1); + createNode(tempTree, nodeIndex, left, right); + return; + } + if (clipL <= split) { + // keep looping on left half + gridBox.hi[axis] = split; + prevClip = clipL; + wasLeft = true; + continue; + } + gridBox.hi[axis] = split; + prevClip = G3D::fnan(); + } + else if (left > right) + { + // all right + if (prevAxis == axis && prevSplit == split) { + // we are stuck here - create a leaf + stats.updateLeaf(depth, right - left + 1); + createNode(tempTree, nodeIndex, left, right); + return; + } + right = rightOrig; + if (clipR >= split) { + // keep looping on right half + gridBox.lo[axis] = split; + prevClip = clipR; + wasLeft = false; + continue; + } + gridBox.lo[axis] = split; + prevClip = G3D::fnan(); + } + else + { + // we are actually splitting stuff + if (prevAxis != -1 && !isnan(prevClip)) + { + // second time through - lets create the previous split + // since it produced empty space + int nextIndex = tempTree.size(); + // allocate child node + tempTree.push_back(0); + tempTree.push_back(0); + tempTree.push_back(0); + if (wasLeft) { + // create a node with a left child + // write leaf node + stats.updateInner(); + tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex; + tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip); + tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf()); + } else { + // create a node with a right child + // write leaf node + stats.updateInner(); + tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3); + tempTree[nodeIndex + 1] = floatToRawIntBits(-G3D::inf()); + tempTree[nodeIndex + 2] = floatToRawIntBits(prevClip); + } + // count stats for the unused leaf + depth++; + stats.updateLeaf(depth, 0); + // now we keep going as we are, with a new nodeIndex: + nodeIndex = nextIndex; + } + break; + } + } + // compute index of child nodes + int nextIndex = tempTree.size(); + // allocate left node + int nl = right - left + 1; + int nr = rightOrig - (right + 1) + 1; + if (nl > 0) { + tempTree.push_back(0); + tempTree.push_back(0); + tempTree.push_back(0); + } else + nextIndex -= 3; + // allocate right node + if (nr > 0) { + tempTree.push_back(0); + tempTree.push_back(0); + tempTree.push_back(0); + } + // write leaf node + stats.updateInner(); + tempTree[nodeIndex + 0] = (axis << 30) | nextIndex; + tempTree[nodeIndex + 1] = floatToRawIntBits(clipL); + tempTree[nodeIndex + 2] = floatToRawIntBits(clipR); + // prepare L/R child boxes + AABound gridBoxL(gridBox), gridBoxR(gridBox); + AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox); + gridBoxL.hi[axis] = gridBoxR.lo[axis] = split; + nodeBoxL.hi[axis] = clipL; + nodeBoxR.lo[axis] = clipR; + // recurse + if (nl > 0) + subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats); + else + stats.updateLeaf(depth + 1, 0); + if (nr > 0) + subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats); + else + stats.updateLeaf(depth + 1, 0); +} + +bool BIH::writeToFile(FILE *wf) const +{ + uint32 treeSize = tree.size(); + uint32 check=0, count=0; + check += fwrite(&bounds.low(), sizeof(float), 3, wf); + check += fwrite(&bounds.high(), sizeof(float), 3, wf); + check += fwrite(&treeSize, sizeof(uint32), 1, wf); + check += fwrite(&tree[0], sizeof(uint32), treeSize, wf); + count = objects.size(); + check += fwrite(&count, sizeof(uint32), 1, wf); + check += fwrite(&objects[0], sizeof(uint32), count, wf); + return check == (3 + 3 + 2 + treeSize + count); +} + +bool BIH::readFromFile(FILE *rf) +{ + uint32 treeSize; + Vector3 lo, hi; + uint32 check=0, count=0; + check += fread(&lo, sizeof(float), 3, rf); + check += fread(&hi, sizeof(float), 3, rf); + bounds = AABox(lo, hi); + check += fread(&treeSize, sizeof(uint32), 1, rf); + tree.resize(treeSize); + check += fread(&tree[0], sizeof(uint32), treeSize, rf); + check += fread(&count, sizeof(uint32), 1, rf); + objects.resize(count); // = new uint32[nObjects]; + check += fread(&objects[0], sizeof(uint32), count, rf); + return check == (3 + 3 + 2 + treeSize + count); +} + +void BIH::BuildStats::updateLeaf(int depth, int n) +{ + numLeaves++; + minDepth = std::min(depth, minDepth); + maxDepth = std::max(depth, maxDepth); + sumDepth += depth; + minObjects = std::min(n, minObjects); + maxObjects = std::max(n, maxObjects); + sumObjects += n; + int nl = std::min(n, 5); + ++numLeavesN[nl]; +} + +void BIH::BuildStats::printStats() +{ + printf("Tree stats:\n"); + printf(" * Nodes: %d\n", numNodes); + printf(" * Leaves: %d\n", numLeaves); + printf(" * Objects: min %d\n", minObjects); + printf(" avg %.2f\n", (float) sumObjects / numLeaves); + printf(" avg(n>0) %.2f\n", (float) sumObjects / (numLeaves - numLeavesN[0])); + printf(" max %d\n", maxObjects); + printf(" * Depth: min %d\n", minDepth); + printf(" avg %.2f\n", (float) sumDepth / numLeaves); + printf(" max %d\n", maxDepth); + printf(" * Leaves w/: N=0 %3d%%\n", 100 * numLeavesN[0] / numLeaves); + printf(" N=1 %3d%%\n", 100 * numLeavesN[1] / numLeaves); + printf(" N=2 %3d%%\n", 100 * numLeavesN[2] / numLeaves); + printf(" N=3 %3d%%\n", 100 * numLeavesN[3] / numLeaves); + printf(" N=4 %3d%%\n", 100 * numLeavesN[4] / numLeaves); + printf(" N>4 %3d%%\n", 100 * numLeavesN[5] / numLeaves); + printf(" * BVH2 nodes: %d (%3d%%)\n", numBVH2, 100 * numBVH2 / (numNodes + numLeaves - 2 * numBVH2)); +} diff --git a/src/server/game/CollisionDetection/BIH.h b/src/server/game/CollisionDetection/BIH.h new file mode 100644 index 00000000000..15ae90c23eb --- /dev/null +++ b/src/server/game/CollisionDetection/BIH.h @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BIH_H +#define _BIH_H + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define MAX_STACK_SIZE 64 + +#ifdef _MSC_VER + #define isnan(x) _isnan(x) +#endif + +using G3D::Vector3; +using G3D::AABox; +using G3D::Ray; + +static inline uint32 floatToRawIntBits(float f) +{ + union + { + uint32 ival; + float fval; + } temp; + temp.fval=f; + return temp.ival; +} + +static inline float intBitsToFloat(uint32 i) +{ + union + { + uint32 ival; + float fval; + } temp; + temp.ival=i; + return temp.fval; +} + +struct AABound +{ + Vector3 lo, hi; +}; + +/** Bounding Interval Hierarchy Class. + Building and Ray-Intersection functions based on BIH from + Sunflow, a Java Raytracer, released under MIT/X11 License + http://sunflow.sourceforge.net/ + Copyright (c) 2003-2007 Christopher Kulla +*/ + +class BIH +{ + public: + BIH() {}; + template< class T, class BoundsFunc > + void build(const std::vector &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false) + { + if(primitives.size() == 0) + return; + buildData dat; + dat.maxPrims = leafSize; + dat.numPrims = primitives.size(); + dat.indices = new uint32[dat.numPrims]; + dat.primBound = new AABox[dat.numPrims]; + getBounds(primitives[0], bounds); + for (uint32 i=0; i tempTree; + BuildStats stats; + buildHierarchy(tempTree, dat, stats); + if (printStats) + stats.printStats(); + + objects.resize(dat.numPrims); + for (uint32 i=0; i + void intersectRay(const Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const + { + float intervalMin = 0.f; + float intervalMax = maxDist; + Vector3 org = r.origin(); + Vector3 dir = r.direction(); + Vector3 invDir; + float t1, t2; + for(int i=0; i<3; ++i) + { + invDir[i] = 1.f / dir[i]; + t1 = (bounds.low()[i] - org[i]) * invDir[i]; + t2 = (bounds.high()[i] - org[i]) * invDir[i]; + if (invDir[i] > 0) { + if (t1 > intervalMin) + intervalMin = t1; + if (t2 < intervalMax) + intervalMax = t2; + } else { + if (t2 > intervalMin) + intervalMin = t2; + if (t1 < intervalMax) + intervalMax = t1; + } + if (intervalMin > intervalMax) + return; + } + + uint32 offsetFront[3]; + uint32 offsetBack[3]; + uint32 offsetFront3[3]; + uint32 offsetBack3[3]; + // compute custom offsets from direction sign bit + + for(int i=0; i<3; ++i) + { + offsetFront[i] = floatToRawIntBits(dir[i]) >> 31; + offsetBack[i] = offsetFront[i] ^ 1; + offsetFront3[i] = offsetFront[i] * 3; + offsetBack3[i] = offsetBack[i] * 3; + + // avoid always adding 1 during the inner loop + ++offsetFront[i]; + ++offsetBack[i]; + } + + StackNode stack[MAX_STACK_SIZE]; + int stackPos = 0; + int node = 0; + + while (true) { + while (true) + { + uint32 tn = tree[node]; + uint32 axis = (tn & (3 << 30)) >> 30; + bool BVH2 = tn & (1 << 29); + int offset = tn & ~(7 << 29); + if (!BVH2) + { + if (axis < 3) + { + // "normal" interior node + float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; + float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; + // ray passes between clip zones + if (tf < intervalMin && tb > intervalMax) + break; + int back = offset + offsetBack3[axis]; + node = back; + // ray passes through far node only + if (tf < intervalMin) { + intervalMin = (tb >= intervalMin) ? tb : intervalMin; + continue; + } + node = offset + offsetFront3[axis]; // front + // ray passes through near node only + if (tb > intervalMax) { + intervalMax = (tf <= intervalMax) ? tf : intervalMax; + continue; + } + // ray passes through both nodes + // push back node + stack[stackPos].node = back; + stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin; + stack[stackPos].tfar = intervalMax; + stackPos++; + // update ray interval for front node + intervalMax = (tf <= intervalMax) ? tf : intervalMax; + continue; + } + else + { + // leaf - test some objects + int n = tree[node + 1]; + while (n > 0) { + bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirst); + if(stopAtFirst && hit) return; + --n; + ++offset; + } + break; + } + } + else + { + if (axis>2) + return; // should not happen + float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; + float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; + node = offset; + intervalMin = (tf >= intervalMin) ? tf : intervalMin; + intervalMax = (tb <= intervalMax) ? tb : intervalMax; + if (intervalMin > intervalMax) + break; + continue; + } + } // traversal loop + do + { + // stack is empty? + if (stackPos == 0) + return; + // move back up the stack + stackPos--; + intervalMin = stack[stackPos].tnear; + if (maxDist < intervalMin) + continue; + node = stack[stackPos].node; + intervalMax = stack[stackPos].tfar; + break; + } while (true); + } + } + + template + void intersectPoint(const Vector3 &p, IsectCallback& intersectCallback) const + { + if (!bounds.contains(p)) + return; + + StackNode stack[MAX_STACK_SIZE]; + int stackPos = 0; + int node = 0; + + while (true) { + while (true) + { + uint32 tn = tree[node]; + uint32 axis = (tn & (3 << 30)) >> 30; + bool BVH2 = tn & (1 << 29); + int offset = tn & ~(7 << 29); + if (!BVH2) + { + if (axis < 3) + { + // "normal" interior node + float tl = intBitsToFloat(tree[node + 1]); + float tr = intBitsToFloat(tree[node + 2]); + // point is between clip zones + if (tl < p[axis] && tr > p[axis]) + break; + int right = offset + 3; + node = right; + // point is in right node only + if (tl < p[axis]) { + continue; + } + node = offset; // left + // point is in left node only + if (tr > p[axis]) { + continue; + } + // point is in both nodes + // push back right node + stack[stackPos].node = right; + stackPos++; + continue; + } + else + { + // leaf - test some objects + int n = tree[node + 1]; + while (n > 0) { + intersectCallback(p, objects[offset]); // !!! + --n; + ++offset; + } + break; + } + } + else // BVH2 node (empty space cut off left and right) + { + if (axis>2) + return; // should not happen + float tl = intBitsToFloat(tree[node + 1]); + float tr = intBitsToFloat(tree[node + 2]); + node = offset; + if (tl > p[axis] || tr < p[axis]) + break; + continue; + } + } // traversal loop + + // stack is empty? + if (stackPos == 0) + return; + // move back up the stack + stackPos--; + node = stack[stackPos].node; + } + } + + bool writeToFile(FILE *wf) const; + bool readFromFile(FILE *rf); + + protected: + std::vector tree; + std::vector objects; + AABox bounds; + + struct buildData + { + uint32 *indices; + AABox *primBound; + uint32 numPrims; + int maxPrims; + }; + struct StackNode + { + uint32 node; + float tnear; + float tfar; + }; + + class BuildStats + { + private: + int numNodes; + int numLeaves; + int sumObjects; + int minObjects; + int maxObjects; + int sumDepth; + int minDepth; + int maxDepth; + int numLeavesN[6]; + int numBVH2; + + public: + BuildStats(): + numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF), + maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF), + maxDepth(0xFFFFFFFF), numBVH2(0) + { + for(int i=0; i<6; ++i) numLeavesN[i] = 0; + } + + void updateInner() { numNodes++; } + void updateBVH2() { numBVH2++; } + void updateLeaf(int depth, int n); + void printStats(); + }; + + void buildHierarchy(std::vector &tempTree, buildData &dat, BuildStats &stats); + + void createNode(std::vector &tempTree, int nodeIndex, uint32 left, uint32 right) { + // write leaf node + tempTree[nodeIndex + 0] = (3 << 30) | left; + tempTree[nodeIndex + 1] = right - left + 1; + } + + void subdivide(int left, int right, std::vector &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats); +}; + +#endif // _BIH_H diff --git a/src/server/game/CollisionDetection/CMakeLists.txt b/src/server/game/CollisionDetection/CMakeLists.txt new file mode 100644 index 00000000000..7d865d354e7 --- /dev/null +++ b/src/server/game/CollisionDetection/CMakeLists.txt @@ -0,0 +1,30 @@ + +########### next target ############### + +SET(vmaps_STAT_SRCS + BIH.h + BIH.cpp + IVMapManager.h + MapTree.cpp + MapTree.h + ModelInstance.cpp + ModelInstance.h + TileAssembler.cpp + TileAssembler.h + VMapDefinitions.h + VMapFactory.cpp + VMapFactory.h + VMapManager2.cpp + VMapManager2.h + VMapTools.h + WorldModel.cpp + WorldModel.h +) + +include_directories( + ${ACE_INCLUDE_DIR} + ${CMAKE_SOURCE_DIR}/src/server/framework + ${CMAKE_SOURCE_DIR}/dep/include/g3dlite +) + +add_library(vmaps STATIC ${vmaps_STAT_SRCS}) diff --git a/src/server/game/CollisionDetection/IVMapManager.h b/src/server/game/CollisionDetection/IVMapManager.h new file mode 100644 index 00000000000..00629eb122c --- /dev/null +++ b/src/server/game/CollisionDetection/IVMapManager.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _IVMAPMANAGER_H +#define _IVMAPMANAGER_H + +#include +#include + +//=========================================================== + +/** +This is the minimum interface to the VMapMamager. +*/ + +namespace VMAP +{ + + enum VMAP_LOAD_RESULT + { + VMAP_LOAD_RESULT_ERROR, + VMAP_LOAD_RESULT_OK, + VMAP_LOAD_RESULT_IGNORED, + }; + + #define VMAP_INVALID_HEIGHT -100000.0f // for check + #define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case + + //=========================================================== + class IVMapManager + { + private: + bool iEnableLineOfSightCalc; + bool iEnableHeightCalc; + + public: + IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) {} + + virtual ~IVMapManager(void) {} + + virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; + + virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; + + virtual void unloadMap(unsigned int pMapId, int x, int y) = 0; + virtual void unloadMap(unsigned int pMapId) = 0; + + virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0; + virtual float getHeight(unsigned int pMapId, float x, float y, float z) = 0; + /** + test if we hit an object. return true if we hit one. rx,ry,rz will hold the hit position or the dest position, if no intersection was found + return a position, that is pReduceDist closer to the origin + */ + virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) = 0; + /** + send debug commands + */ + virtual bool processCommand(char *pCommand)= 0; + + /** + Enable/disable LOS calculation + It is enabled by default. If it is enabled in mid game the maps have to loaded manualy + */ + void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; } + /** + Enable/disable model height calculation + It is enabled by default. If it is enabled in mid game the maps have to loaded manualy + */ + void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; } + + bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); } + bool isHeightCalcEnabled() const { return(iEnableHeightCalc); } + bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); } + + virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0; + /** + Block maps from being used. + parameter: String of map ids. Delimiter = "," + e.g.: "0,1,530" + */ + virtual void preventMapsFromBeingUsed(const char* pMapIdString) =0; + /** + Query world model area info. + \param z gets adjusted to the ground height for which this are info is valid + */ + virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0; + virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const=0; + }; + +} +#endif diff --git a/src/server/game/CollisionDetection/MapTree.cpp b/src/server/game/CollisionDetection/MapTree.cpp new file mode 100644 index 00000000000..8c77ee109f3 --- /dev/null +++ b/src/server/game/CollisionDetection/MapTree.cpp @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MapTree.h" +#include "ModelInstance.h" +#include "VMapManager2.h" +#include "VMapDefinitions.h" + +#include +#include +#include + +using G3D::Vector3; + +namespace VMAP +{ + + class MapRayCallback + { + public: + MapRayCallback(ModelInstance *val): prims(val) {} + ModelInstance *prims; + bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true) + { + return prims[entry].intersectRay(ray, distance, pStopAtFirstHit); + //std::cout << "trying to intersect '" << entity->name << "'\n"; + } + }; + + class AreaInfoCallback + { + public: + AreaInfoCallback(ModelInstance *val): prims(val) {} + void operator()(const Vector3& point, uint32 entry) + { +#ifdef VMAP_DEBUG + std::cout << "trying to intersect '" << prims[entry].name << "'\n"; +#endif + prims[entry].intersectPoint(point, aInfo); + } + + ModelInstance *prims; + AreaInfo aInfo; + }; + + class LocationInfoCallback + { + public: + LocationInfoCallback(ModelInstance *val, LocationInfo &info): prims(val), locInfo(info), result(false) {} + void operator()(const Vector3& point, uint32 entry) + { +#ifdef VMAP_DEBUG + std::cout << "trying to intersect '" << prims[entry].name << "'\n"; +#endif + if (prims[entry].GetLocationInfo(point, locInfo)) + result = true; + } + + ModelInstance *prims; + LocationInfo &locInfo; + bool result; + }; + + + //========================================================= + + std::string StaticMapTree::getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY) + { + std::stringstream tilefilename; + tilefilename.fill('0'); + tilefilename << std::setw(3) << mapID << "_"; + //tilefilename << std::setw(2) << tileX << "_" << std::setw(2) << tileY << ".vmtile"; + tilefilename << std::setw(2) << tileY << "_" << std::setw(2) << tileX << ".vmtile"; + return tilefilename.str(); + } + + bool StaticMapTree::getAreaInfo(Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const + { + AreaInfoCallback intersectionCallBack(iTreeValues); + iTree.intersectPoint(pos, intersectionCallBack); + if (intersectionCallBack.aInfo.result) + { + flags = intersectionCallBack.aInfo.flags; + adtId = intersectionCallBack.aInfo.adtId; + rootId = intersectionCallBack.aInfo.rootId; + groupId = intersectionCallBack.aInfo.groupId; + pos.z = intersectionCallBack.aInfo.ground_Z; + return true; + } + return false; + } + + bool StaticMapTree::GetLocationInfo(const Vector3 &pos, LocationInfo &info) const + { + LocationInfoCallback intersectionCallBack(iTreeValues, info); + iTree.intersectPoint(pos, intersectionCallBack); + return intersectionCallBack.result; + } + + StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath): + iMapID(mapID), /* iTree(0), */ iTreeValues(0), iBasePath(basePath) + { + if (iBasePath.length() > 0 && (iBasePath[iBasePath.length()-1] != '/' || iBasePath[iBasePath.length()-1] != '\\')) + { + iBasePath.append("/"); + } + } + + //========================================================= + //! Make sure to call unloadMap() to unregister acquired model references before destroying + StaticMapTree::~StaticMapTree() + { + delete[] iTreeValues; + } + + //========================================================= + /** + return dist to hit or inf() if no hit + */ + + float StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const + { + float distance = pMaxDist; + MapRayCallback intersectionCallBack(iTreeValues); + iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit); + return distance; + } + //========================================================= + + bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const + { + bool result = true; + float maxDist = (pos2 - pos1).magnitude(); + // prevent NaN values which can cause BIH intersection to enter infinite loop + if (maxDist < 1e-10f) + return true; + // direction with length of 1 + G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist); + float resultDist = getIntersectionTime(ray, maxDist, true); + if (resultDist < maxDist) + { + result = false; + } + return result; + } + //========================================================= + /** + When moving from pos1 to pos2 check if we hit an object. Return true and the position if we hit one + Return the hit pos or the original dest pos + */ + + bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const + { + bool result=false; + float maxDist = (pPos2 - pPos1).magnitude(); + // prevent NaN values which can cause BIH intersection to enter infinite loop + if (maxDist < 1e-10f) + { + pResultHitPos = pPos2; + return false; + } + Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1 + G3D::Ray ray(pPos1, dir); + float dist = getIntersectionTime(ray, maxDist, false); + if (dist < maxDist) + { + pResultHitPos = pPos1 + dir * dist; + if (pModifyDist < 0) + { + if ((pResultHitPos - pPos1).magnitude() > -pModifyDist) + { + pResultHitPos = pResultHitPos + dir*pModifyDist; + } + else + { + pResultHitPos = pPos1; + } + } + else + { + pResultHitPos = pResultHitPos + dir*pModifyDist; + } + result = true; + } + else + { + pResultHitPos = pPos2; + result = false; + } + return result; + } + + //========================================================= + + float StaticMapTree::getHeight(const Vector3& pPos) const + { + float height = G3D::inf(); + Vector3 dir = Vector3(0,0,-1); + G3D::Ray ray(pPos, dir); // direction with length of 1 + float maxDist = VMapDefinitions::getMaxCanFallDistance(); + float dist = getIntersectionTime(ray, maxDist, false); + if (dist < maxDist) + { + height = pPos.z - dist; + } + return(height); + } + + //========================================================= + + bool StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY) + { + std::string basePath = vmapPath; + if (basePath.length() > 0 && (basePath[basePath.length()-1] != '/' || basePath[basePath.length()-1] != '\\')) + basePath.append("/"); + std::string fullname = basePath + VMapManager2::getMapFileName(mapID); + bool success = true; + FILE *rf = fopen(fullname.c_str(), "rb"); + if (!rf) + return false; + // TODO: check magic number when implemented... + char tiled; + char chunk[8]; + if (!readChunk(rf, chunk, VMAP_MAGIC, 8) || fread(&tiled, sizeof(char), 1, rf) != 1) + { + fclose(rf); + return false; + } + if (tiled) + { + std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY); + FILE* tf = fopen(tilefile.c_str(), "rb"); + if (!tf) + success = false; + else + fclose(tf); + } + fclose(rf); + return success; + } + + //========================================================= + + bool StaticMapTree::InitMap(const std::string &fname, VMapManager2 *vm) + { + std::cout << "Initializing StaticMapTree '" << fname << "'\n"; + bool success = true; + std::string fullname = iBasePath + fname; + FILE *rf = fopen(fullname.c_str(), "rb"); + if (!rf) + return false; + else + { + char chunk[8]; + //general info + if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) success = false; + char tiled; + if (success && fread(&tiled, sizeof(char), 1, rf) != 1) success = false; + iIsTiled = bool(tiled); + // Nodes + if (success && !readChunk(rf, chunk, "NODE", 4)) success = false; + if (success) success = iTree.readFromFile(rf); + if (success) + { + iNTreeValues = iTree.primCount(); + iTreeValues = new ModelInstance[iNTreeValues]; + } + + if (success && !readChunk(rf, chunk, "GOBJ", 4)) success = false; + // global model spawns + // only non-tiled maps have them, and if so exactly one (so far at least...) + ModelSpawn spawn; +#ifdef VMAP_DEBUG + std::cout << "Map isTiled:" << bool(iIsTiled) << std::endl; +#endif + if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) + { + WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name); + std::cout << "StaticMapTree::InitMap(): loading " << spawn.name << std::endl; + if (model) + { + // assume that global model always is the first and only tree value (could be improved...) + iTreeValues[0] = ModelInstance(spawn, model); + iLoadedSpawns[0] = 1; + } + else + { + success = false; + std::cout << "error: could not acquire WorldModel pointer!\n"; + } + } + + fclose(rf); + } + return success; + } + + //========================================================= + + void StaticMapTree::UnloadMap(VMapManager2 *vm) + { + for (loadedSpawnMap::iterator i = iLoadedSpawns.begin(); i != iLoadedSpawns.end(); ++i) + { + iTreeValues[i->first].setUnloaded(); + for (uint32 refCount = 0; refCount < i->second; ++refCount) + vm->releaseModelInstance(iTreeValues[i->first].name); + } + iLoadedSpawns.clear(); + iLoadedTiles.clear(); + } + + //========================================================= + + bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm) + { + if (!iIsTiled) + { + // currently, core creates grids for all maps, whether it has terrain tiles or not + // so we need "fake" tile loads to know when we can unload map geometry + iLoadedTiles[packTileID(tileX, tileY)] = false; + return true; + } + if (!iTreeValues) + { + std::cout << "Tree has not been initialized!\n"; + return false; + } + bool result = true; + + std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); + FILE* tf = fopen(tilefile.c_str(), "rb"); + if (tf) + { + uint32 numSpawns; + if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) + result = false; + for (uint32 i=0; iacquireModelInstance(iBasePath, spawn.name); + if (!model) std::cout << "error: could not acquire WorldModel pointer!\n"; + + // update tree + uint32 referencedVal; + + fread(&referencedVal, sizeof(uint32), 1, tf); + if (!iLoadedSpawns.count(referencedVal)) + { +#ifdef VMAP_DEBUG + if (referencedVal > iNTreeValues) + { + std::cout << "invalid tree element! (" << referencedVal << "/" << iNTreeValues << ")\n"; + continue; + } +#endif + iTreeValues[referencedVal] = ModelInstance(spawn, model); + iLoadedSpawns[referencedVal] = 1; + } + else + { + ++iLoadedSpawns[referencedVal]; +#ifdef VMAP_DEBUG + if (iTreeValues[referencedVal].ID != spawn.ID) std::cout << "error: trying to load wrong spawn in node!\n"; + else if (iTreeValues[referencedVal].name != spawn.name) std::cout << "error: name collision on GUID="<< spawn.ID << "\n"; +#endif + } + } + } + iLoadedTiles[packTileID(tileX, tileY)] = true; + fclose(tf); + } + else + iLoadedTiles[packTileID(tileX, tileY)] = false; + return result; + } + + //========================================================= + + void StaticMapTree::UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm) + { + uint32 tileID = packTileID(tileX, tileY); + loadedTileMap::iterator tile = iLoadedTiles.find(tileID); + if (tile == iLoadedTiles.end()) + { + std::cout << "WARNING: trying to unload non-loaded tile. Map:" << iMapID << " X:" << tileX << " Y:" << tileY << std::endl; + return; + } + if (tile->second) // file associated with tile + { + std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); + FILE* tf = fopen(tilefile.c_str(), "rb"); + if (tf) + { + bool result=true; + uint32 numSpawns; + if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) + result = false; + for (uint32 i=0; ireleaseModelInstance(spawn.name); + + // update tree + uint32 referencedNode; + + fread(&referencedNode, sizeof(uint32), 1, tf); + if (!iLoadedSpawns.count(referencedNode)) + { + std::cout << "error! trying to unload non-referenced model '" << spawn.name << "' (ID:" << spawn.ID << ")\n"; + } + else if (--iLoadedSpawns[referencedNode] == 0) + { + //std::cout << "MapTree: removing '" << spawn.name << "' from tree\n"; + iTreeValues[referencedNode].setUnloaded(); + iLoadedSpawns.erase(referencedNode); + } + } + } + fclose(tf); + } + } + iLoadedTiles.erase(tile); + } + +} diff --git a/src/server/game/CollisionDetection/MapTree.h b/src/server/game/CollisionDetection/MapTree.h new file mode 100644 index 00000000000..7955cb92d68 --- /dev/null +++ b/src/server/game/CollisionDetection/MapTree.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MAPTREE_H +#define _MAPTREE_H + +#include "Platform/Define.h" +#include "Utilities/UnorderedMap.h" +#include "BIH.h" + +namespace VMAP +{ + class ModelInstance; + class GroupModel; + class VMapManager2; + + struct LocationInfo + { + LocationInfo(): hitInstance(0), hitModel(0), ground_Z(-G3D::inf()) {}; + const ModelInstance *hitInstance; + const GroupModel *hitModel; + float ground_Z; + }; + + class StaticMapTree + { + typedef UNORDERED_MAP loadedTileMap; + typedef UNORDERED_MAP loadedSpawnMap; + private: + uint32 iMapID; + bool iIsTiled; + BIH iTree; + ModelInstance *iTreeValues; // the tree entries + uint32 iNTreeValues; + + // Store all the map tile idents that are loaded for that map + // some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed + // empty tiles have no tile file, hence map with bool instead of just a set (consistency check) + loadedTileMap iLoadedTiles; + // stores to invalidate tree values, unload map, and to be able to report errors + loadedSpawnMap iLoadedSpawns; + std::string iBasePath; + + private: + float getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const; + //bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); } + public: + static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY); + static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX<<16 | tileY; } + static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY) { tileX = ID>>16; tileY = ID&0xFF; } + static bool CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY); + + StaticMapTree(uint32 mapID, const std::string &basePath); + ~StaticMapTree(); + + bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const; + bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const; + float getHeight(const G3D::Vector3& pPos) const; + bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; + bool GetLocationInfo(const Vector3 &pos, LocationInfo &info) const; + + bool InitMap(const std::string &fname, VMapManager2 *vm); + void UnloadMap(VMapManager2 *vm); + bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm); + void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm); + bool isTiled() const { return iIsTiled; } + uint32 numLoadedTiles() const { return iLoadedTiles.size(); } + }; + + struct AreaInfo + { + AreaInfo(): result(false), ground_Z(-G3D::inf()) {}; + bool result; + float ground_Z; + uint32 flags; + int32 adtId; + int32 rootId; + int32 groupId; + }; +} // VMAP + +#endif // _MAPTREE_H diff --git a/src/server/game/CollisionDetection/ModelInstance.cpp b/src/server/game/CollisionDetection/ModelInstance.cpp new file mode 100644 index 00000000000..677a08e147a --- /dev/null +++ b/src/server/game/CollisionDetection/ModelInstance.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ModelInstance.h" +#include "WorldModel.h" +#include "MapTree.h" + +using G3D::Vector3; +using G3D::Ray; + +namespace VMAP +{ + ModelInstance::ModelInstance(const ModelSpawn &spawn, WorldModel *model): ModelSpawn(spawn), iModel(model) + { + iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iRot.y/180.f, G3D::pi()*iRot.x/180.f, G3D::pi()*iRot.z/180.f).inverse(); + iInvScale = 1.f/iScale; + } + + bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const + { + if (!iModel) + { + //std::cout << "\n"; + return false; + } + float time = pRay.intersectionTime(iBound); + if (time == G3D::inf()) + { +// std::cout << "Ray does not hit '" << name << "'\n"; + + return false; + } +// std::cout << "Ray crosses bound of '" << name << "'\n"; +/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z + << " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z + << " t/tmax:" << time << "/" << pMaxDist; + std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: " + << iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */ + // child bounds are defined in object space: + Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale; + Ray modRay(p, iInvRot * pRay.direction()); + float distance = pMaxDist * iInvScale; + bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit); + distance *= iScale; + pMaxDist = distance; + return hit; + } + + void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const + { + if (!iModel) + { +#ifdef VMAP_DEBUG + std::cout << "\n"; +#endif + return; + } + + // M2 files don't contain area info, only WMO files + if (flags & MOD_M2) + return; + if (!iBound.contains(p)) + return; + // child bounds are defined in object space: + Vector3 pModel = iInvRot * (p - iPos) * iInvScale; + Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); + float zDist; + if (iModel->IntersectPoint(pModel, zDirModel, zDist, info)) + { + Vector3 modelGround = pModel + zDist * zDirModel; + // Transform back to world space. Note that: + // Mat * vec == vec * Mat.transpose() + // and for rotation matrices: Mat.inverse() == Mat.transpose() + float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; + if (info.ground_Z < world_Z) + { + info.ground_Z = world_Z; + info.adtId = adtId; + } + } + } + + bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const + { + if (!iModel) + { +#ifdef VMAP_DEBUG + std::cout << "\n"; +#endif + return false; + } + + // M2 files don't contain area info, only WMO files + if (flags & MOD_M2) + return false; + if (!iBound.contains(p)) + return false; + // child bounds are defined in object space: + Vector3 pModel = iInvRot * (p - iPos) * iInvScale; + Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); + float zDist; + if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info)) + { + Vector3 modelGround = pModel + zDist * zDirModel; + // Transform back to world space. Note that: + // Mat * vec == vec * Mat.transpose() + // and for rotation matrices: Mat.inverse() == Mat.transpose() + float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; + if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection? + { + info.ground_Z = world_Z; + info.hitInstance = this; + return true; + } + } + return false; + } + + bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const + { + // child bounds are defined in object space: + Vector3 pModel = iInvRot * (p - iPos) * iInvScale; + //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); + float zDist; + if (info.hitModel->GetLiquidLevel(pModel, zDist)) + { + // calculate world height (zDist in model coords): + // assume WMO not tilted (wouldn't make much sense anyway) + liqHeight = zDist * iScale + iPos.z; + return true; + } + return false; + } + + bool ModelSpawn::readFromFile(FILE *rf, ModelSpawn &spawn) + { + uint32 check=0, nameLen; + check += fread(&spawn.flags, sizeof(uint32), 1, rf); + // EoF? + if (!check) + { + if (ferror(rf)) + std::cout << "Error reading ModelSpawn!\n"; + return false; + } + check += fread(&spawn.adtId, sizeof(uint16), 1, rf); + check += fread(&spawn.ID, sizeof(uint32), 1, rf); + check += fread(&spawn.iPos, sizeof(float), 3, rf); + check += fread(&spawn.iRot, sizeof(float), 3, rf); + check += fread(&spawn.iScale, sizeof(float), 1, rf); + bool has_bound = (spawn.flags & MOD_HAS_BOUND); + if (has_bound) // only WMOs have bound in MPQ, only available after computation + { + Vector3 bLow, bHigh; + check += fread(&bLow, sizeof(float), 3, rf); + check += fread(&bHigh, sizeof(float), 3, rf); + spawn.iBound = G3D::AABox(bLow, bHigh); + } + check += fread(&nameLen, sizeof(uint32), 1, rf); + if(check != (has_bound ? 17 : 11)) + { + std::cout << "Error reading ModelSpawn!\n"; + return false; + } + char nameBuff[500]; + if (nameLen>500) // file names should never be that long, must be file error + { + std::cout << "Error reading ModelSpawn, file name too long!\n"; + return false; + } + check = fread(nameBuff, sizeof(char), nameLen, rf); + if (check != nameLen) + { + std::cout << "Error reading ModelSpawn!\n"; + return false; + } + spawn.name = std::string(nameBuff, nameLen); + return true; + } + + bool ModelSpawn::writeToFile(FILE *wf, const ModelSpawn &spawn) + { + uint32 check=0; + check += fwrite(&spawn.flags, sizeof(uint32), 1, wf); + check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf); + check += fwrite(&spawn.ID, sizeof(uint32), 1, wf); + check += fwrite(&spawn.iPos, sizeof(float), 3, wf); + check += fwrite(&spawn.iRot, sizeof(float), 3, wf); + check += fwrite(&spawn.iScale, sizeof(float), 1, wf); + bool has_bound = (spawn.flags & MOD_HAS_BOUND); + if(has_bound) // only WMOs have bound in MPQ, only available after computation + { + check += fwrite(&spawn.iBound.low(), sizeof(float), 3, wf); + check += fwrite(&spawn.iBound.high(), sizeof(float), 3, wf); + } + uint32 nameLen = spawn.name.length(); + check += fwrite(&nameLen, sizeof(uint32), 1, wf); + if(check != (has_bound ? 17 : 11)) return false; + check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf); + if(check != nameLen) return false; + return true; + } + +} diff --git a/src/server/game/CollisionDetection/ModelInstance.h b/src/server/game/CollisionDetection/ModelInstance.h new file mode 100644 index 00000000000..97b3ab632a1 --- /dev/null +++ b/src/server/game/CollisionDetection/ModelInstance.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MODELINSTANCE_H_ +#define _MODELINSTANCE_H_ + +#include +#include +#include +#include + +#include "Platform/Define.h" + +namespace VMAP +{ + class WorldModel; + struct AreaInfo; + struct LocationInfo; + + enum ModelFlags + { + MOD_M2 = 1, + MOD_WORLDSPAWN = 1<<1, + MOD_HAS_BOUND = 1<<2 + }; + + class ModelSpawn + { + public: + //mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name + uint32 flags; + uint16 adtId; + uint32 ID; + G3D::Vector3 iPos; + G3D::Vector3 iRot; + float iScale; + G3D::AABox iBound; + std::string name; + bool operator==(const ModelSpawn &other) const { return ID == other.ID; } + //uint32 hashCode() const { return ID; } + // temp? + const G3D::AABox& getBounds() const { return iBound; } + + + static bool readFromFile(FILE *rf, ModelSpawn &spawn); + static bool writeToFile(FILE *rw, const ModelSpawn &spawn); + }; + + class ModelInstance: public ModelSpawn + { + public: + ModelInstance(): iModel(0) {} + ModelInstance(const ModelSpawn &spawn, WorldModel *model); + void setUnloaded() { iModel = 0; } + bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const; + void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const; + bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const; + bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const; + protected: + G3D::Matrix3 iInvRot; + float iInvScale; + WorldModel *iModel; + }; +} // namespace VMAP + +#endif // _MODELINSTANCE diff --git a/src/server/game/CollisionDetection/TileAssembler.cpp b/src/server/game/CollisionDetection/TileAssembler.cpp new file mode 100644 index 00000000000..d01b54a7564 --- /dev/null +++ b/src/server/game/CollisionDetection/TileAssembler.cpp @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "WorldModel.h" +#include "TileAssembler.h" +#include "MapTree.h" +#include "BIH.h" +#include "VMapDefinitions.h" + +#include +#include +#include +#include + +using G3D::Vector3; +using G3D::AABox; +using G3D::inf; +using std::pair; + +template<> struct BoundsTrait +{ + static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); } +}; + +namespace VMAP +{ + bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len) + { + if (fread(dest, sizeof(char), len, rf) != len) return false; + return memcmp(dest, compare, len) == 0; + } + + Vector3 ModelPosition::transform(const Vector3& pIn) const + { + Vector3 out = pIn * iScale; + out = iRotation * out; + return(out); + } + + //================================================================= + + TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName) + { + iCurrentUniqueNameId = 0; + iFilterMethod = NULL; + iSrcDir = pSrcDirName; + iDestDir = pDestDirName; + //mkdir(iDestDir); + //init(); + } + + TileAssembler::~TileAssembler() + { + //delete iCoordModelMapping; + } + + bool TileAssembler::convertWorld2() + { + std::set spawnedModelFiles; + bool success = readMapSpawns(); + if (!success) + return false; + + // export Map data + for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter) + { + // build global map tree + std::vector mapSpawns; + UniqueEntryMap::iterator entry; + for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry) + { + // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail + if (entry->second.flags & MOD_M2) + { + if (!calculateTransformedBound(entry->second)) + break; + } + else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ + { + // TODO: remove extractor hack and uncomment below line: + //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); + entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); + } + mapSpawns.push_back(&(entry->second)); + spawnedModelFiles.insert(entry->second.name); + } + + BIH pTree; + pTree.build(mapSpawns, BoundsTrait::getBounds); + + // ===> possibly move this code to StaticMapTree class + std::map modelNodeIdx; + for (uint32 i=0; i(mapSpawns[i]->ID, i)); + if (!modelNodeIdx.empty()) + printf("min GUID: %u, max GUID: %u\n", modelNodeIdx.begin()->first, modelNodeIdx.rbegin()->first); + + // write map tree file + std::stringstream mapfilename; + mapfilename << iDestDir << "/" << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree"; + FILE *mapfile = fopen(mapfilename.str().c_str(), "wb"); + if (!mapfile) + { + success = false; + printf("Cannot open %s\n", mapfilename.str().c_str()); + break; + } + + //general info + if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false; + uint32 globalTileID = StaticMapTree::packTileID(65, 65); + pair globalRange = map_iter->second->TileEntries.equal_range(globalTileID); + char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO + if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false; + // Nodes + if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false; + if (success) success = pTree.writeToFile(mapfile); + // global map spawns (WDT), if any (most instances) + if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false; + + for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob) + { + success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); + } + + fclose(mapfile); + + // <==== + + // write map tile files, similar to ADT files, only with extra BSP tree node info + TileMap &tileEntries = map_iter->second->TileEntries; + TileMap::iterator tile; + for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) + { + const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second]; + if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... + continue; + uint32 nSpawns = tileEntries.count(tile->first); + std::stringstream tilefilename; + tilefilename.fill('0'); + tilefilename << iDestDir << "/" << std::setw(3) << map_iter->first << "_"; + uint32 x, y; + StaticMapTree::unpackTileID(tile->first, x, y); + tilefilename << std::setw(2) << x << "_" << std::setw(2) << y << ".vmtile"; + FILE *tilefile = fopen(tilefilename.str().c_str(), "wb"); + // write number of tile spawns + if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; + // write tile spawns + for (uint32 s=0; ssecond->UniqueEntries[tile->second]; + success = success && ModelSpawn::writeToFile(tilefile, spawn2); + // MapTree nodes to update when loading tile: + std::map::iterator nIdx = modelNodeIdx.find(spawn2.ID); + if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; + } + fclose(tilefile); + } + // break; //test, extract only first map; TODO: remvoe this line + } + + // export objects + std::cout << "\nConverting Model Files" << std::endl; + for (std::set::iterator mfile = spawnedModelFiles.begin(); mfile != spawnedModelFiles.end(); ++mfile) + { + std::cout << "Converting " << *mfile << std::endl; + if (!convertRawFile(*mfile)) + { + std::cout << "error converting " << *mfile << std::endl; + success = false; + break; + } + } + + //cleanup: + for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end(); ++map_iter) + { + delete map_iter->second; + } + return success; + } + + bool TileAssembler::readMapSpawns() + { + std::string fname = iSrcDir + "/dir_bin"; + FILE *dirf = fopen(fname.c_str(), "rb"); + if (!dirf) + { + printf("Could not read dir_bin file!\n"); + return false; + } + printf("Read coordinate mapping...\n"); + uint32 mapID, tileX, tileY, check=0; + G3D::Vector3 v1, v2; + ModelSpawn spawn; + while (!feof(dirf)) + { + check = 0; + // read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name + check += fread(&mapID, sizeof(uint32), 1, dirf); + if (check == 0) // EoF... + break; + check += fread(&tileX, sizeof(uint32), 1, dirf); + check += fread(&tileY, sizeof(uint32), 1, dirf); + if (!ModelSpawn::readFromFile(dirf, spawn)) + break; + + MapSpawns *current; + MapData::iterator map_iter = mapData.find(mapID); + if (map_iter == mapData.end()) + { + printf("spawning Map %d\n", mapID); + mapData[mapID] = current = new MapSpawns(); + } + else current = (*map_iter).second; + current->UniqueEntries.insert(pair(spawn.ID, spawn)); + current->TileEntries.insert(pair(StaticMapTree::packTileID(tileX, tileY), spawn.ID)); + } + bool success = (ferror(dirf) == 0); + fclose(dirf); + return success; + } + + bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) + { + std::string modelFilename = iSrcDir + "/" + spawn.name; + ModelPosition modelPosition; + modelPosition.iDir = spawn.iRot; + modelPosition.iScale = spawn.iScale; + modelPosition.init(); + + FILE *rf = fopen(modelFilename.c_str(), "rb"); + if (!rf) + { + printf("ERROR: Can't open model file: %s\n", modelFilename.c_str()); + return false; + } + + AABox modelBound; + bool boundEmpty=true; + char ident[8]; + + int readOperation = 1; + + // temporary use defines to simplify read/check code (close file and return at fail) + #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ + fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; + #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ + fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } + + READ_OR_RETURN(&ident, 8); + CMP_OR_RETURN(ident, "VMAP003"); + + // we have to read one int. This is needed during the export and we have to skip it here + uint32 tempNVectors; + READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); + + uint32 groups, wmoRootId; + char blockId[5]; + blockId[4] = 0; + int blocksize; + float *vectorarray = 0; + + READ_OR_RETURN(&groups, sizeof(uint32)); + READ_OR_RETURN(&wmoRootId, sizeof(uint32)); + if (groups != 1) printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); + + for (uint32 g=0; g0) + { + vectorarray = new float[nvectors*3]; + READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); + } + else + { + std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl; + return false; + } + + for (uint32 i=0, indexNo=0; indexNo0) + filename.append("/"); + filename.append(pModelFilename); + FILE *rf = fopen(filename.c_str(), "rb"); + + if (!rf) + { + printf("ERROR: Can't open model file in form: %s",pModelFilename.c_str()); + printf("... or form: %s",filename.c_str() ); + return false; + } + + char ident[8]; + + int readOperation = 1; + + // temporary use defines to simplify read/check code (close file and return at fail) + #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ + fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; + #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ + fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } + + READ_OR_RETURN(&ident, 8); + CMP_OR_RETURN(ident, "VMAP003"); + + // we have to read one int. This is needed during the export and we have to skip it here + uint32 tempNVectors; + READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); + + uint32 groups; + uint32 RootWMOID; + char blockId[5]; + blockId[4] = 0; + int blocksize; + + READ_OR_RETURN(&groups, sizeof(uint32)); + READ_OR_RETURN(&RootWMOID, sizeof(uint32)); + + std::vector groupsArray; + + for (uint32 g=0; g triangles; + std::vector vertexArray; + + uint32 mogpflags, GroupWMOID; + READ_OR_RETURN(&mogpflags, sizeof(uint32)); + READ_OR_RETURN(&GroupWMOID, sizeof(uint32)); + + float bbox1[3], bbox2[3]; + READ_OR_RETURN(bbox1, sizeof(float)*3); + READ_OR_RETURN(bbox2, sizeof(float)*3); + + uint32 liquidflags; + READ_OR_RETURN(&liquidflags, sizeof(uint32)); + + // will this ever be used? what is it good for anyway?? + uint32 branches; + READ_OR_RETURN(&blockId, 4); + CMP_OR_RETURN(blockId, "GRP "); + READ_OR_RETURN(&blocksize, sizeof(int)); + READ_OR_RETURN(&branches, sizeof(uint32)); + for (uint32 b=0; b0) + { + uint16 *indexarray = new uint16[nindexes]; + READ_OR_RETURN(indexarray, nindexes*sizeof(uint16)); + for (uint32 i=0; i0) + { + float *vectorarray = new float[nvectors*3]; + READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); + for (uint32 i=0; iGetHeightStorage(), size*sizeof(float)); + size = hlq.xtiles*hlq.ytiles; + READ_OR_RETURN(liquid->GetFlagsStorage(), size); + } + + groupsArray.push_back(GroupModel(mogpflags, GroupWMOID, AABox(Vector3(bbox1), Vector3(bbox2)))); + groupsArray.back().setMeshData(vertexArray, triangles); + groupsArray.back().setLiquidData(liquid); + + // drop of temporary use defines + #undef READ_OR_RETURN + #undef CMP_OR_RETURN + + } + fclose(rf); + + // write WorldModel + WorldModel model; + model.setRootWmoID(RootWMOID); + if (groupsArray.size()) + { + model.setGroupModels(groupsArray); + success = model.writeFile(iDestDir + "/" + pModelFilename + ".vmo"); + } + + //std::cout << "readRawFile2: '" << pModelFilename << "' tris: " << nElements << " nodes: " << nNodes << std::endl; + return success; + } +} diff --git a/src/server/game/CollisionDetection/TileAssembler.h b/src/server/game/CollisionDetection/TileAssembler.h new file mode 100644 index 00000000000..b26735708af --- /dev/null +++ b/src/server/game/CollisionDetection/TileAssembler.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _TILEASSEMBLER_H_ +#define _TILEASSEMBLER_H_ + +#include +#include +#include + +#include "ModelInstance.h" + +namespace VMAP +{ + /** + This Class is used to convert raw vector data into balanced BSP-Trees. + To start the conversion call convertWorld(). + */ + //=============================================== + + class ModelPosition + { + private: + G3D::Matrix3 iRotation; + public: + G3D::Vector3 iPos; + G3D::Vector3 iDir; + float iScale; + void init() + { + iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iDir.y/180.f, G3D::pi()*iDir.x/180.f, G3D::pi()*iDir.z/180.f); + } + G3D::Vector3 transform(const G3D::Vector3& pIn) const; + void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; } + }; + + typedef std::map UniqueEntryMap; + typedef std::multimap TileMap; + + struct MapSpawns + { + UniqueEntryMap UniqueEntries; + TileMap TileEntries; + }; + + typedef std::map MapData; + //=============================================== + + class TileAssembler + { + private: + std::string iDestDir; + std::string iSrcDir; + bool (*iFilterMethod)(char *pName); + G3D::Table iUniqueNameIds; + unsigned int iCurrentUniqueNameId; + MapData mapData; + + public: + TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName); + virtual ~TileAssembler(); + + bool convertWorld2(); + bool readMapSpawns(); + bool calculateTransformedBound(ModelSpawn &spawn); + + bool convertRawFile(const std::string& pModelFilename); + void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; } + std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName); + unsigned int getUniqueNameId(const std::string pName); + }; + +} // VMAP +#endif /*_TILEASSEMBLER_H_*/ diff --git a/src/server/game/CollisionDetection/VMapDefinitions.h b/src/server/game/CollisionDetection/VMapDefinitions.h new file mode 100644 index 00000000000..e4a34cc1397 --- /dev/null +++ b/src/server/game/CollisionDetection/VMapDefinitions.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _VMAPDEFINITIONS_H +#define _VMAPDEFINITIONS_H +#include + +#define LIQUID_TILE_SIZE (533.333f / 128.f) + +namespace VMAP +{ + //===================================== + #define MAX_CAN_FALL_DISTANCE 10.0f + const char VMAP_MAGIC[] = "VMAP_3.0"; + + class VMapDefinitions + { + public: + static float getMaxCanFallDistance() { return MAX_CAN_FALL_DISTANCE; } + }; + + //====================================== + + // defined in TileAssembler.cpp currently... + bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len); +} +#endif diff --git a/src/server/game/CollisionDetection/VMapFactory.cpp b/src/server/game/CollisionDetection/VMapFactory.cpp new file mode 100644 index 00000000000..331acbace47 --- /dev/null +++ b/src/server/game/CollisionDetection/VMapFactory.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "VMapFactory.h" +#include "VMapManager2.h" + +using namespace G3D; + +namespace VMAP +{ + void chompAndTrim(std::string& str) + { + while(str.length() >0) + { + char lc = str[str.length()-1]; + if(lc == '\r' || lc == '\n' || lc == ' ' || lc == '"' || lc == '\'') + { + str = str.substr(0,str.length()-1); + } + else + { + break; + } + } + while(str.length() >0) + { + char lc = str[0]; + if(lc == ' ' || lc == '"' || lc == '\'') + { + str = str.substr(1,str.length()-1); + } + else + { + break; + } + } + } + + IVMapManager *gVMapManager = 0; + Table* iIgnoreSpellIds=0; + + //=============================================== + // result false, if no more id are found + + bool getNextId(const std::string& pString, unsigned int& pStartPos, unsigned int& pId) + { + bool result = false; + unsigned int i; + for(i=pStartPos;ipStartPos) + { + std::string idString = pString.substr(pStartPos, i-pStartPos); + pStartPos = i+1; + chompAndTrim(idString); + pId = atoi(idString.c_str()); + result = true; + } + return(result); + } + + //=============================================== + /** + parameter: String of map ids. Delimiter = "," + */ + + void VMapFactory::preventSpellsFromBeingTestedForLoS(const char* pSpellIdString) + { + if(!iIgnoreSpellIds) + iIgnoreSpellIds = new Table(); + if(pSpellIdString != NULL) + { + unsigned int pos =0; + unsigned int id; + std::string confString(pSpellIdString); + chompAndTrim(confString); + while(getNextId(confString, pos, id)) + { + iIgnoreSpellIds->set(id, true); + } + } + } + + //=============================================== + + bool VMapFactory::checkSpellForLoS(unsigned int pSpellId) + { + return(!iIgnoreSpellIds->containsKey(pSpellId)); + } + + //=============================================== + // just return the instance + IVMapManager* VMapFactory::createOrGetVMapManager() + { + if(gVMapManager == 0) + gVMapManager= new VMapManager2(); // should be taken from config ... Please change if you like :-) + return gVMapManager; + } + + //=============================================== + // delete all internal data structures + void VMapFactory::clear() + { + if(iIgnoreSpellIds) + { + delete iIgnoreSpellIds; + iIgnoreSpellIds = NULL; + } + if(gVMapManager) + { + delete gVMapManager; + gVMapManager = NULL; + } + } +} diff --git a/src/server/game/CollisionDetection/VMapFactory.h b/src/server/game/CollisionDetection/VMapFactory.h new file mode 100644 index 00000000000..8dc2c01938a --- /dev/null +++ b/src/server/game/CollisionDetection/VMapFactory.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _VMAPFACTORY_H +#define _VMAPFACTORY_H + +#include "IVMapManager.h" + +/** +This is the access point to the VMapManager. +*/ + +namespace VMAP +{ + //=========================================================== + + class VMapFactory + { + public: + static IVMapManager* createOrGetVMapManager(); + static void clear(); + + static void preventSpellsFromBeingTestedForLoS(const char* pSpellIdString); + static bool checkSpellForLoS(unsigned int pSpellId); + }; + +} +#endif diff --git a/src/server/game/CollisionDetection/VMapManager2.cpp b/src/server/game/CollisionDetection/VMapManager2.cpp new file mode 100644 index 00000000000..1e8a84aee52 --- /dev/null +++ b/src/server/game/CollisionDetection/VMapManager2.cpp @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "VMapManager2.h" +#include "MapTree.h" +#include "ModelInstance.h" +#include "WorldModel.h" +#include "VMapDefinitions.h" + +using G3D::Vector3; + +namespace VMAP +{ + + //========================================================= + + VMapManager2::VMapManager2() + { + } + + //========================================================= + + VMapManager2::~VMapManager2(void) + { + for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i) + { + delete i->second; + } + for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i) + { + delete i->second.getModel(); + } + } + + //========================================================= + + Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const + { + Vector3 pos; + const float mid = 0.5 * 64.0 * 533.33333333f; + pos.x = mid - x; + pos.y = mid - y; + pos.z = z; + + return pos; + } + + //========================================================= + + Vector3 VMapManager2::convertPositionToMangosRep(float x, float y, float z) const + { + Vector3 pos; + const float mid = 0.5 * 64.0 * 533.33333333f; + pos.x = mid - x; + pos.y = mid - y; + pos.z = z; + + return pos; + } + //========================================================= + + // move to MapTree too? + std::string VMapManager2::getMapFileName(unsigned int pMapId) + { + std::stringstream fname; + fname.width(3); + fname << std::setfill('0') << pMapId << std::string(MAP_FILENAME_EXTENSION2); + return fname.str(); + } + + //========================================================= + /** + Block maps from being used. + parameter: String of map ids. Delimiter = "," + e.g.: "0,1,590" + */ + + void VMapManager2::preventMapsFromBeingUsed(const char* pMapIdString) + { + iIgnoreMapIds.clear(); + if (pMapIdString != NULL) + { + std::string map_str; + std::stringstream map_ss; + map_ss.str(std::string(pMapIdString)); + while (std::getline(map_ss, map_str, ',')) + { + std::stringstream ss2(map_str); + int map_num = -1; + ss2 >> map_num; + if (map_num >= 0) + { + std::cout << "ingoring Map " << map_num << " for VMaps\n"; + iIgnoreMapIds[map_num] = true; + // unload map in case it is loaded + unloadMap(map_num); + } + } + } + } + + //========================================================= + + int VMapManager2::loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) + { + int result = VMAP_LOAD_RESULT_IGNORED; + if (isMapLoadingEnabled() && !iIgnoreMapIds.count(pMapId)) + { + if (_loadMap(pMapId, pBasePath, x, y)) + result = VMAP_LOAD_RESULT_OK; + else + result = VMAP_LOAD_RESULT_ERROR; + } + return result; + } + + //========================================================= + // load one tile (internal use only) + + bool VMapManager2::_loadMap(unsigned int pMapId, const std::string &basePath, uint32 tileX, uint32 tileY) + { + InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); + if (instanceTree == iInstanceMapTrees.end()) + { + std::string mapFileName = getMapFileName(pMapId); + StaticMapTree *newTree = new StaticMapTree(pMapId, basePath); + if (!newTree->InitMap(mapFileName, this)) + return false; + instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(pMapId, newTree)).first; + } + return instanceTree->second->LoadMapTile(tileX, tileY, this); + } + + //========================================================= + + void VMapManager2::unloadMap(unsigned int pMapId) + { + InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); + if (instanceTree != iInstanceMapTrees.end()) + { + instanceTree->second->UnloadMap(this); + if (instanceTree->second->numLoadedTiles() == 0) + { + delete instanceTree->second; + iInstanceMapTrees.erase(pMapId); + } + } + } + + //========================================================= + + void VMapManager2::unloadMap(unsigned int pMapId, int x, int y) + { + InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); + if (instanceTree != iInstanceMapTrees.end()) + { + instanceTree->second->UnloadMapTile(x, y, this); + if (instanceTree->second->numLoadedTiles() == 0) + { + delete instanceTree->second; + iInstanceMapTrees.erase(pMapId); + } + } + } + + //========================================================== + + bool VMapManager2::isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) + { + if (!isLineOfSightCalcEnabled()) return true; + bool result = true; + InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); + if (instanceTree != iInstanceMapTrees.end()) + { + Vector3 pos1 = convertPositionToInternalRep(x1,y1,z1); + Vector3 pos2 = convertPositionToInternalRep(x2,y2,z2); + if (pos1 != pos2) + { + result = instanceTree->second->isInLineOfSight(pos1, pos2); + } + } + return result; + } + //========================================================= + /** + get the hit position and return true if we hit something + otherwise the result pos will be the dest pos + */ + bool VMapManager2::getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) + { + bool result = false; + rx=x2; + ry=y2; + rz=z2; + if (isLineOfSightCalcEnabled()) + { + InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); + if (instanceTree != iInstanceMapTrees.end()) + { + Vector3 pos1 = convertPositionToInternalRep(x1,y1,z1); + Vector3 pos2 = convertPositionToInternalRep(x2,y2,z2); + Vector3 resultPos; + result = instanceTree->second->getObjectHitPos(pos1, pos2, resultPos, pModifyDist); + resultPos = convertPositionToMangosRep(resultPos.x,resultPos.y,resultPos.z); + rx = resultPos.x; + ry = resultPos.y; + rz = resultPos.z; + } + } + return result; + } + + //========================================================= + /** + get height or INVALID_HEIGHT if no height available + */ + + float VMapManager2::getHeight(unsigned int pMapId, float x, float y, float z) + { + float height = VMAP_INVALID_HEIGHT_VALUE; //no height + if (isHeightCalcEnabled()) + { + InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); + if (instanceTree != iInstanceMapTrees.end()) + { + Vector3 pos = convertPositionToInternalRep(x,y,z); + height = instanceTree->second->getHeight(pos); + if (!(height < G3D::inf())) + { + height = VMAP_INVALID_HEIGHT_VALUE; //no height + } + } + } + return height; + } + + //========================================================= + + bool VMapManager2::getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const + { + bool result=false; + InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(pMapId); + if (instanceTree != iInstanceMapTrees.end()) + { + Vector3 pos = convertPositionToInternalRep(x, y, z); + result = instanceTree->second->getAreaInfo(pos, flags, adtId, rootId, groupId); + // z is not touched by convertPositionToMangosRep(), so just copy + z = pos.z; + } + return(result); + } + + bool VMapManager2::GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const + { + InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(pMapId); + if (instanceTree != iInstanceMapTrees.end()) + { + LocationInfo info; + Vector3 pos = convertPositionToInternalRep(x, y, z); + if (instanceTree->second->GetLocationInfo(pos, info)) + { + floor = info.ground_Z; + type = info.hitModel->GetLiquidType(); + if (ReqLiquidType && !(type & ReqLiquidType)) + return false; + if (info.hitInstance->GetLiquidLevel(pos, info, level)) + return true; + } + } + return false; + } + + //========================================================= + + WorldModel* VMapManager2::acquireModelInstance(const std::string &basepath, const std::string &filename) + { + ModelFileMap::iterator model = iLoadedModelFiles.find(filename); + if (model == iLoadedModelFiles.end()) + { + WorldModel *worldmodel = new WorldModel(); + if (!worldmodel->readFile(basepath + filename + ".vmo")) + { + std::cout << "VMapManager2: could not load '" << basepath << filename << ".vmo'!\n"; + delete worldmodel; + return NULL; + } + std::cout << "VMapManager2: loading file '" << basepath << filename << "'.\n"; + model = iLoadedModelFiles.insert(std::pair(filename, ManagedModel())).first; + model->second.setModel(worldmodel); + } + model->second.incRefCount(); + return model->second.getModel(); + } + + void VMapManager2::releaseModelInstance(const std::string &filename) + { + ModelFileMap::iterator model = iLoadedModelFiles.find(filename); + if (model == iLoadedModelFiles.end()) + { + std::cout << "VMapManager2: trying to unload non-loaded file '" << filename << "'!\n"; + return; + } + if( model->second.decRefCount() == 0) + { + std::cout << "VMapManager2: unloading file '" << filename << "'.\n"; + delete model->second.getModel(); + iLoadedModelFiles.erase(model); + } + } + //========================================================= + + bool VMapManager2::existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) + { + return StaticMapTree::CanLoadMap(std::string(pBasePath), pMapId, x, y); + } + +} // namespace VMAP diff --git a/src/server/game/CollisionDetection/VMapManager2.h b/src/server/game/CollisionDetection/VMapManager2.h new file mode 100644 index 00000000000..5f03b87b07f --- /dev/null +++ b/src/server/game/CollisionDetection/VMapManager2.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _VMAPMANAGER2_H +#define _VMAPMANAGER2_H + +#include "IVMapManager.h" +#include "Utilities/UnorderedMap.h" +#include "Platform/Define.h" +#include + +//=========================================================== + +#define MAP_FILENAME_EXTENSION2 ".vmtree" + +#define FILENAMEBUFFER_SIZE 500 + +/** +This is the main Class to manage loading and unloading of maps, line of sight, height calculation and so on. +For each map or map tile to load it reads a directory file that contains the ModelContainer files used by this map or map tile. +Each global map or instance has its own dynamic BSP-Tree. +The loaded ModelContainers are included in one of these BSP-Trees. +Additionally a table to match map ids and map names is used. +*/ + +//=========================================================== + +namespace VMAP +{ + class StaticMapTree; + class WorldModel; + + class ManagedModel + { + public: + ManagedModel(): iModel(0), iRefCount(0) {} + void setModel(WorldModel *model) { iModel = model; } + WorldModel *getModel() { return iModel; } + void incRefCount() { ++iRefCount; } + int decRefCount() { return --iRefCount; } + protected: + WorldModel *iModel; + int iRefCount; + }; + + typedef UNORDERED_MAP InstanceTreeMap; + typedef UNORDERED_MAP ModelFileMap; + + class VMapManager2 : public IVMapManager + { + protected: + // Tree to check collision + ModelFileMap iLoadedModelFiles; + InstanceTreeMap iInstanceMapTrees; + // UNORDERED_MAP iMapsSplitIntoTiles; + UNORDERED_MAP iIgnoreMapIds; + + bool _loadMap(uint32 pMapId, const std::string &basePath, uint32 tileX, uint32 tileY); + /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */ + + public: + // public for debug + G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const; + G3D::Vector3 convertPositionToMangosRep(float x, float y, float z) const; + static std::string getMapFileName(unsigned int pMapId); + + VMapManager2(); + ~VMapManager2(void); + + int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y); + + void unloadMap(unsigned int pMapId, int x, int y); + void unloadMap(unsigned int pMapId); + + bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) ; + /** + fill the hit pos and return true, if an object was hit + */ + bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist); + float getHeight(unsigned int pMapId, float x, float y, float z); + + bool processCommand(char *pCommand) { return false; } // for debug and extensions + + void preventMapsFromBeingUsed(const char* pMapIdString); + bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; + bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const; + + WorldModel* acquireModelInstance(const std::string &basepath, const std::string &filename); + void releaseModelInstance(const std::string &filename); + + // what's the use of this? o.O + virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const + { + return getMapFileName(pMapId); + } + virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y); + }; +} +#endif diff --git a/src/server/game/CollisionDetection/VMapTools.h b/src/server/game/CollisionDetection/VMapTools.h new file mode 100644 index 00000000000..dbbd9af9271 --- /dev/null +++ b/src/server/game/CollisionDetection/VMapTools.h @@ -0,0 +1,150 @@ +/* +* Copyright (C) 2005-2010 MaNGOS +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _VMAPTOOLS_H +#define _VMAPTOOLS_H + +#include +#include + +#include "NodeValueAccess.h" + +/** +The Class is mainly taken from G3D/AABSPTree.h but modified to be able to use our internal data structure. +This is an iterator that helps us analysing the BSP-Trees. +The collision detection is modified to return true, if we are inside an object. +*/ + +namespace VMAP +{ + template + class IntersectionCallBack { + public: + TValue* closestEntity; + G3D::Vector3 hitLocation; + G3D::Vector3 hitNormal; + + void operator()(const G3D::Ray& ray, const TValue* entity, bool pStopAtFirstHit, float& distance) { + entity->intersect(ray, distance, pStopAtFirstHit, hitLocation, hitNormal); + } + }; + + //============================================================== + //============================================================== + //============================================================== + + class MyCollisionDetection + { + private: + public: + + static bool collisionLocationForMovingPointFixedAABox( + const G3D::Vector3& origin, + const G3D::Vector3& dir, + const G3D::AABox& box, + G3D::Vector3& location, + bool& Inside) + { + + // Integer representation of a floating-point value. +#define IR(x) (reinterpret_cast(x)) + + Inside = true; + const G3D::Vector3& MinB = box.low(); + const G3D::Vector3& MaxB = box.high(); + G3D::Vector3 MaxT(-1.0f, -1.0f, -1.0f); + + // Find candidate planes. + for (int i = 0; i < 3; ++i) + { + if (origin[i] < MinB[i]) + { + location[i] = MinB[i]; + Inside = false; + + // Calculate T distances to candidate planes + if (IR(dir[i])) + { + MaxT[i] = (MinB[i] - origin[i]) / dir[i]; + } + } + else if (origin[i] > MaxB[i]) + { + location[i] = MaxB[i]; + Inside = false; + + // Calculate T distances to candidate planes + if (IR(dir[i])) + { + MaxT[i] = (MaxB[i] - origin[i]) / dir[i]; + } + } + } + + if (Inside) + { + // definite hit + location = origin; + return true; + } + + // Get largest of the maxT's for final choice of intersection + int WhichPlane = 0; + if (MaxT[1] > MaxT[WhichPlane]) + { + WhichPlane = 1; + } + + if (MaxT[2] > MaxT[WhichPlane]) + { + WhichPlane = 2; + } + + // Check final candidate actually inside box + if (IR(MaxT[WhichPlane]) & 0x80000000) + { + // Miss the box + return false; + } + + for (int i = 0; i < 3; ++i) + { + if (i != WhichPlane) + { + location[i] = origin[i] + MaxT[WhichPlane] * dir[i]; + if ((location[i] < MinB[i]) || + (location[i] > MaxB[i])) + { + // On this plane we're outside the box extents, so + // we miss the box + return false; + } + } + } + /* + // Choose the normal to be the plane normal facing into the ray + normal = G3D::Vector3::zero(); + normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0; + */ + return true; + +#undef IR + } + }; +} +#endif diff --git a/src/server/game/CollisionDetection/WorldModel.cpp b/src/server/game/CollisionDetection/WorldModel.cpp new file mode 100644 index 00000000000..690c77577ae --- /dev/null +++ b/src/server/game/CollisionDetection/WorldModel.cpp @@ -0,0 +1,535 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "WorldModel.h" +#include "VMapDefinitions.h" +#include "MapTree.h" + +using G3D::Vector3; +using G3D::Ray; + +template<> struct BoundsTrait +{ + static void getBounds(const VMAP::GroupModel& obj, G3D::AABox& out) { out = obj.GetBound(); } +}; + + +namespace VMAP +{ + bool IntersectTriangle(const MeshTriangle &tri, std::vector::const_iterator points, const G3D::Ray &ray, float &distance) + { + static const float EPS = 1e-5f; + + // See RTR2 ch. 13.7 for the algorithm. + + const Vector3 e1 = points[tri.idx1] - points[tri.idx0]; + const Vector3 e2 = points[tri.idx2] - points[tri.idx0]; + const Vector3 p(ray.direction().cross(e2)); + const float a = e1.dot(p); + + if (abs(a) < EPS) { + // Determinant is ill-conditioned; abort early + return false; + } + + const float f = 1.0f / a; + const Vector3 s(ray.origin() - points[tri.idx0]); + const float u = f * s.dot(p); + + if ((u < 0.0f) || (u > 1.0f)) { + // We hit the plane of the m_geometry, but outside the m_geometry + return false; + } + + const Vector3 q(s.cross(e1)); + const float v = f * ray.direction().dot(q); + + if ((v < 0.0f) || ((u + v) > 1.0f)) { + // We hit the plane of the triangle, but outside the triangle + return false; + } + + const float t = f * e2.dot(q); + + if ((t > 0.0f) && (t < distance)) + { + // This is a new hit, closer than the previous one + distance = t; + + /* baryCoord[0] = 1.0 - u - v; + baryCoord[1] = u; + baryCoord[2] = v; */ + + return true; + } + // This hit is after the previous hit, so ignore it + return false; + } + + class TriBoundFunc + { + public: + TriBoundFunc(std::vector &vert): vertices(vert.begin()) {} + void operator()(const MeshTriangle &tri, G3D::AABox &out) const + { + G3D::Vector3 lo = vertices[tri.idx0]; + G3D::Vector3 hi = lo; + + lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]); + hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]); + + out = G3D::AABox(lo, hi); + } + protected: + const std::vector::const_iterator vertices; + }; + + // ===================== WmoLiquid ================================== + + WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type): + iTilesX(width), iTilesY(height), iCorner(corner), iType(type) + { + iHeight = new float[(width+1)*(height+1)]; + iFlags = new uint8[width*height]; + } + + WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(0), iFlags(0) + { + *this = other; // use assignment operator... + } + + WmoLiquid::~WmoLiquid() + { + delete[] iHeight; + delete[] iFlags; + } + + WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other) + { + if (this == &other) + return *this; + iTilesX = other.iTilesX; + iTilesY = other.iTilesY; + iCorner = other.iCorner; + iType = other.iType; + delete iHeight; + delete iFlags; + if (other.iHeight) + { + iHeight = new float[(iTilesX+1)*(iTilesY+1)]; + memcpy(iHeight, other.iHeight, (iTilesX+1)*(iTilesY+1)*sizeof(float)); + } + else + iHeight = 0; + if (other.iFlags) + { + iFlags = new uint8[iTilesX * iTilesY]; + memcpy(iFlags, other.iFlags, iTilesX * iTilesY); + } + else + iFlags = 0; + return *this; + } + + bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const + { + uint32 tx = (pos.x - iCorner.x)/LIQUID_TILE_SIZE; + if (tx<0 || tx >= iTilesX) return false; + uint32 ty = (pos.y - iCorner.y)/LIQUID_TILE_SIZE; + if (ty<0 || ty >= iTilesY) return false; + // checking for 0x08 *might* be enough, but disabled tiles always are 0x?F: + if ((iFlags[tx + ty*iTilesX] & 0x0F) == 0x0F) + return false; + //placeholder...use only lower left corner vertex + liqHeight = /* iCorner.z + */ iHeight[tx + ty*(iTilesX+1)]; + return true; + } + + uint32 WmoLiquid::GetFileSize() + { + return 2 * sizeof(uint32) + + sizeof(Vector3) + + (iTilesX + 1)*(iTilesY + 1) * sizeof(float) + + iTilesX * iTilesY; + } + + bool WmoLiquid::writeToFile(FILE *wf) + { + bool result = true; + if (result && fwrite(&iTilesX, sizeof(uint32), 1, wf) != 1) result = false; + if (result && fwrite(&iTilesY, sizeof(uint32), 1, wf) != 1) result = false; + if (result && fwrite(&iCorner, sizeof(Vector3), 1, wf) != 1) result = false; + if (result && fwrite(&iType, sizeof(uint32), 1, wf) != 1) result = false; + uint32 size = (iTilesX + 1)*(iTilesY + 1); + if (result && fwrite(iHeight, sizeof(float), size, wf) != size) result = false; + size = iTilesX*iTilesY; + if (result && fwrite(iFlags, sizeof(uint8), size, wf) != size) result = false; + return result; + } + + bool WmoLiquid::readFromFile(FILE *rf, WmoLiquid *&out) + { + bool result = true; + WmoLiquid *liquid = new WmoLiquid(); + if (result && fread(&liquid->iTilesX, sizeof(uint32), 1, rf) != 1) result = false; + if (result && fread(&liquid->iTilesY, sizeof(uint32), 1, rf) != 1) result = false; + if (result && fread(&liquid->iCorner, sizeof(Vector3), 1, rf) != 1) result = false; + if (result && fread(&liquid->iType, sizeof(uint32), 1, rf) != 1) result = false; + uint32 size = (liquid->iTilesX + 1)*(liquid->iTilesY + 1); + liquid->iHeight = new float[size]; + if (result && fread(liquid->iHeight, sizeof(float), size, rf) != size) result = false; + size = liquid->iTilesX * liquid->iTilesY; + liquid->iFlags = new uint8[size]; + if (result && fread(liquid->iFlags, sizeof(uint8), size, rf) != size) result = false; + if (!result) + delete liquid; + out = liquid; + return result; + } + + // ===================== GroupModel ================================== + + GroupModel::GroupModel(const GroupModel &other): + iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID), + vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0) + { + if (other.iLiquid) + iLiquid = new WmoLiquid(*other.iLiquid); + } + + void GroupModel::setMeshData(std::vector &vert, std::vector &tri) + { + vertices.swap(vert); + triangles.swap(tri); + TriBoundFunc bFunc(vertices); + meshTree.build(triangles, bFunc); + } + + bool GroupModel::writeToFile(FILE *wf) + { + bool result = true; + uint32 chunkSize, count; + + if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) result = false; + if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) result = false; + if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) result = false; + + // write vertices + if (result && fwrite("VERT", 1, 4, wf) != 4) result = false; + count = vertices.size(); + chunkSize = sizeof(uint32)+ sizeof(Vector3)*count; + if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; + if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; + if (!count) // models without (collision) geometry end here, unsure if they are useful + return result; + if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) result = false; + + // write triangle mesh + if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false; + count = triangles.size(); + chunkSize = sizeof(uint32)+ sizeof(MeshTriangle)*count; + if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; + if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; + if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false; + + // write mesh BIH + if (result && fwrite("MBIH", 1, 4, wf) != 4) result = false; + if (result) result = meshTree.writeToFile(wf); + + // write liquid data + if (result && fwrite("LIQU", 1, 4, wf) != 4) result = false; + if (!iLiquid) + { + chunkSize = 0; + if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; + return result; + } + chunkSize = iLiquid->GetFileSize(); + if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; + if (result) result = iLiquid->writeToFile(wf); + + return result; + } + + bool GroupModel::readFromFile(FILE *rf) + { + char chunk[8]; + bool result = true; + uint32 chunkSize, count; + triangles.clear(); + vertices.clear(); + delete iLiquid; + iLiquid = 0; + + if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false; + if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false; + if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) result = false; + + // read vertices + if (result && !readChunk(rf, chunk, "VERT", 4)) result = false; + if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; + if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; + if (!count) // models without (collision) geometry end here, unsure if they are useful + return result; + if (result) vertices.resize(count); + if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) result = false; + + // read triangle mesh + if (result && !readChunk(rf, chunk, "TRIM", 4)) result = false; + if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; + if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; + if (result) triangles.resize(count); + if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) result = false; + + // read mesh BIH + if (result && !readChunk(rf, chunk, "MBIH", 4)) result = false; + if (result) result = meshTree.readFromFile(rf); + + // write liquid data + if (result && !readChunk(rf, chunk, "LIQU", 4)) result = false; + if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; + if (result && chunkSize > 0) + result = WmoLiquid::readFromFile(rf, iLiquid); + return result; + } + + struct GModelRayCallback + { + GModelRayCallback(const std::vector &tris, const std::vector &vert): + vertices(vert.begin()), triangles(tris.begin()), hit(false) {} + bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit) + { + bool result = IntersectTriangle(triangles[entry], vertices, ray, distance); + if (result) hit=true; + return hit; + } + std::vector::const_iterator vertices; + std::vector::const_iterator triangles; + bool hit; + }; + + bool GroupModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const + { + if (!triangles.size()) + return false; + GModelRayCallback callback(triangles, vertices); + meshTree.intersectRay(ray, callback, distance, stopAtFirstHit); + return callback.hit; + } + + bool GroupModel::IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const + { + if (!triangles.size() || !iBound.contains(pos)) + return false; + GModelRayCallback callback(triangles, vertices); + Vector3 rPos = pos - 0.1f * down; + float dist = G3D::inf(); + G3D::Ray ray(rPos, down); + bool hit = IntersectRay(ray, dist, false); + if (hit) + z_dist = dist - 0.1f; + return hit; + } + + bool GroupModel::GetLiquidLevel(const Vector3 &pos, float &liqHeight) const + { + if (iLiquid) + return iLiquid->GetLiquidHeight(pos, liqHeight); + return false; + } + + uint32 GroupModel::GetLiquidType() const + { + // convert to type mask, matching MAP_LIQUID_TYPE_* defines in Map.h + if (iLiquid) + return (1 << iLiquid->GetType()); + return 0; + } + + // ===================== WorldModel ================================== + + void WorldModel::setGroupModels(std::vector &models) + { + groupModels.swap(models); + groupTree.build(groupModels, BoundsTrait::getBounds, 1); + } + + struct WModelRayCallBack + { + WModelRayCallBack(const std::vector &mod): models(mod.begin()), hit(false) {} + bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit) + { + bool result = models[entry].IntersectRay(ray, distance, pStopAtFirstHit); + if (result) hit=true; + return hit; + } + std::vector::const_iterator models; + bool hit; + }; + + bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const + { + // small M2 workaround, maybe better make separate class with virtual intersection funcs + // in any case, there's no need to use a bound tree if we only have one submodel + if (groupModels.size() == 1) + return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit); + + WModelRayCallBack isc(groupModels); + groupTree.intersectRay(ray, isc, distance, stopAtFirstHit); + return isc.hit; + } + + class WModelAreaCallback { + public: + WModelAreaCallback(const std::vector &vals, const Vector3 &down): + prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) {} + std::vector::const_iterator prims; + std::vector::const_iterator hit; + float minVol; + float zDist; + Vector3 zVec; + void operator()(const Vector3& point, uint32 entry) + { + float group_Z; + //float pVol = prims[entry].GetBound().volume(); + //if(pVol < minVol) + //{ + /* if (prims[entry].iBound.contains(point)) */ + if (prims[entry].IsInsideObject(point, zVec, group_Z)) + { + //minVol = pVol; + //hit = prims + entry; + if (group_Z < zDist) + { + zDist = group_Z; + hit = prims + entry; + } +#ifdef VMAP_DEBUG + const GroupModel &gm = prims[entry]; + printf("%10u %8X %7.3f,%7.3f,%7.3f | %7.3f,%7.3f,%7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(), + gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z, + gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z); +#endif + } + //} + //std::cout << "trying to intersect '" << prims[entry].name << "'\n"; + } + }; + + bool WorldModel::IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const + { + if (!groupModels.size()) + return false; + WModelAreaCallback callback(groupModels, down); + groupTree.intersectPoint(p, callback); + if (callback.hit != groupModels.end()) + { + info.rootId = RootWMOID; + info.groupId = callback.hit->GetWmoID(); + info.flags = callback.hit->GetMogpFlags(); + info.result = true; + dist = callback.zDist; + return true; + } + return false; + } + + bool WorldModel::GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const + { + if (!groupModels.size()) + return false; + WModelAreaCallback callback(groupModels, down); + groupTree.intersectPoint(p, callback); + if (callback.hit != groupModels.end()) + { + info.hitModel = &(*callback.hit); + dist = callback.zDist; + return true; + } + return false; + } + + bool WorldModel::writeFile(const std::string &filename) + { + FILE *wf = fopen(filename.c_str(), "wb"); + if (!wf) + return false; + + bool result = true; + uint32 chunkSize, count; + result = fwrite(VMAP_MAGIC,1,8,wf) == 8; + if (result && fwrite("WMOD", 1, 4, wf) != 4) result = false; + chunkSize = sizeof(uint32) + sizeof(uint32); + if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; + if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false; + + // write group models + count=groupModels.size(); + if (count) + { + if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false; + //chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count; + //if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; + if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; + for (uint32 i=0; i + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _WORLDMODEL_H +#define _WORLDMODEL_H + +#include +#include +#include +#include +#include "BIH.h" + +#include "Platform/Define.h" + +namespace VMAP +{ + class TreeNode; + struct AreaInfo; + struct LocationInfo; + + class MeshTriangle + { + public: + MeshTriangle(){}; + MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) {}; + + uint32 idx0; + uint32 idx1; + uint32 idx2; + }; + + class WmoLiquid + { + public: + WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type); + WmoLiquid(const WmoLiquid &other); + ~WmoLiquid(); + WmoLiquid& operator=(const WmoLiquid &other); + bool GetLiquidHeight(const Vector3 &pos, float &liqHeight) const; + uint32 GetType() const { return iType; } + float *GetHeightStorage() { return iHeight; } + uint8 *GetFlagsStorage() { return iFlags; } + uint32 GetFileSize(); + bool writeToFile(FILE *wf); + static bool readFromFile(FILE *rf, WmoLiquid *&liquid); + private: + WmoLiquid(): iHeight(0), iFlags(0) {}; + uint32 iTilesX; //!< number of tiles in x direction, each + uint32 iTilesY; + Vector3 iCorner; //!< the lower corner + uint32 iType; //!< liquid type + float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values + uint8 *iFlags; //!< info if liquid tile is used + }; + + /*! holding additional info for WMO group files */ + class GroupModel + { + public: + GroupModel(): iLiquid(0) {} + GroupModel(const GroupModel &other); + GroupModel(uint32 mogpFlags, uint32 groupWMOID, const AABox &bound): + iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) {} + ~GroupModel() { delete iLiquid; } + + //! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry! + void setMeshData(std::vector &vert, std::vector &tri); + void setLiquidData(WmoLiquid *liquid) { iLiquid = liquid; } + bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; + bool IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const; + bool GetLiquidLevel(const Vector3 &pos, float &liqHeight) const; + uint32 GetLiquidType() const; + bool writeToFile(FILE *wf); + bool readFromFile(FILE *rf); + const G3D::AABox& GetBound() const { return iBound; } + uint32 GetMogpFlags() const { return iMogpFlags; } + uint32 GetWmoID() const { return iGroupWMOID; } + protected: + G3D::AABox iBound; + uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor + uint32 iGroupWMOID; + std::vector vertices; + std::vector triangles; + BIH meshTree; + WmoLiquid *iLiquid; + }; + /*! Holds a model (converted M2 or WMO) in its original coordinate space */ + class WorldModel + { + public: + WorldModel(): RootWMOID(0) {} + + //! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry! + void setGroupModels(std::vector &models); + void setRootWmoID(uint32 id) { RootWMOID = id; } + bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; + bool IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const; + bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const; + bool writeFile(const std::string &filename); + bool readFile(const std::string &filename); + protected: + uint32 RootWMOID; + std::vector groupModels; + BIH groupTree; + }; +} // namespace VMAP + +#endif // _WORLDMODEL_H diff --git a/src/server/shared/vmap/BIH.cpp b/src/server/shared/vmap/BIH.cpp deleted file mode 100644 index 4bd6b3c701e..00000000000 --- a/src/server/shared/vmap/BIH.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BIH.h" - -void BIH::buildHierarchy(std::vector &tempTree, buildData &dat, BuildStats &stats) -{ - // create space for the first node - tempTree.push_back(3 << 30); // dummy leaf - tempTree.insert(tempTree.end(), 2, 0); - //tempTree.add(0); - - // seed bbox - AABound gridBox = { bounds.low(), bounds.high() }; - AABound nodeBox = gridBox; - // seed subdivide function - subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats); -} - -void BIH::subdivide(int left, int right, std::vector &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats) -{ - if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE) - { - // write leaf node - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - // calculate extents - int axis = -1, prevAxis, rightOrig; - float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan(); - float split = G3D::fnan(), prevSplit; - bool wasLeft = true; - while (true) - { - prevAxis = axis; - prevSplit = split; - // perform quick consistency checks - Vector3 d( gridBox.hi - gridBox.lo ); - if (d.x < 0 || d.y < 0 || d.z < 0) - throw std::logic_error("negative node extents"); - for (int i = 0; i < 3; i++) - { - if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i]) - { - //UI.printError(Module.ACCEL, "Reached tree area in error - discarding node with: %d objects", right - left + 1); - throw std::logic_error("invalid node overlap"); - } - } - // find longest axis - axis = d.primaryAxis(); - split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]); - // partition L/R subsets - clipL = -G3D::inf(); - clipR = G3D::inf(); - rightOrig = right; // save this for later - float nodeL = G3D::inf(); - float nodeR = -G3D::inf(); - for (int i = left; i <= right;) - { - int obj = dat.indices[i]; - float minb = dat.primBound[obj].low()[axis]; - float maxb = dat.primBound[obj].high()[axis]; - float center = (minb + maxb) * 0.5f; - if (center <= split) - { - // stay left - i++; - if (clipL < maxb) - clipL = maxb; - } - else - { - // move to the right most - int t = dat.indices[i]; - dat.indices[i] = dat.indices[right]; - dat.indices[right] = t; - right--; - if (clipR > minb) - clipR = minb; - } - nodeL = std::min(nodeL, minb); - nodeR = std::max(nodeR, maxb); - } - // check for empty space - if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis]) - { - float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis]; - float nodeNewW = nodeR - nodeL; - // node box is too big compare to space occupied by primitives? - if (1.3f * nodeNewW < nodeBoxW) - { - stats.updateBVH2(); - int nextIndex = tempTree.size(); - // allocate child - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - // write bvh2 clip node - stats.updateInner(); - tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(nodeL); - tempTree[nodeIndex + 2] = floatToRawIntBits(nodeR); - // update nodebox and recurse - nodeBox.lo[axis] = nodeL; - nodeBox.hi[axis] = nodeR; - subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats); - return; - } - } - // ensure we are making progress in the subdivision - if (right == rightOrig) - { - // all left - if (prevAxis == axis && prevSplit == split) { - // we are stuck here - create a leaf - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - if (clipL <= split) { - // keep looping on left half - gridBox.hi[axis] = split; - prevClip = clipL; - wasLeft = true; - continue; - } - gridBox.hi[axis] = split; - prevClip = G3D::fnan(); - } - else if (left > right) - { - // all right - if (prevAxis == axis && prevSplit == split) { - // we are stuck here - create a leaf - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - right = rightOrig; - if (clipR >= split) { - // keep looping on right half - gridBox.lo[axis] = split; - prevClip = clipR; - wasLeft = false; - continue; - } - gridBox.lo[axis] = split; - prevClip = G3D::fnan(); - } - else - { - // we are actually splitting stuff - if (prevAxis != -1 && !isnan(prevClip)) - { - // second time through - lets create the previous split - // since it produced empty space - int nextIndex = tempTree.size(); - // allocate child node - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - if (wasLeft) { - // create a node with a left child - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip); - tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf()); - } else { - // create a node with a right child - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3); - tempTree[nodeIndex + 1] = floatToRawIntBits(-G3D::inf()); - tempTree[nodeIndex + 2] = floatToRawIntBits(prevClip); - } - // count stats for the unused leaf - depth++; - stats.updateLeaf(depth, 0); - // now we keep going as we are, with a new nodeIndex: - nodeIndex = nextIndex; - } - break; - } - } - // compute index of child nodes - int nextIndex = tempTree.size(); - // allocate left node - int nl = right - left + 1; - int nr = rightOrig - (right + 1) + 1; - if (nl > 0) { - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - } else - nextIndex -= 3; - // allocate right node - if (nr > 0) { - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - } - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (axis << 30) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(clipL); - tempTree[nodeIndex + 2] = floatToRawIntBits(clipR); - // prepare L/R child boxes - AABound gridBoxL(gridBox), gridBoxR(gridBox); - AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox); - gridBoxL.hi[axis] = gridBoxR.lo[axis] = split; - nodeBoxL.hi[axis] = clipL; - nodeBoxR.lo[axis] = clipR; - // recurse - if (nl > 0) - subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats); - else - stats.updateLeaf(depth + 1, 0); - if (nr > 0) - subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats); - else - stats.updateLeaf(depth + 1, 0); -} - -bool BIH::writeToFile(FILE *wf) const -{ - uint32 treeSize = tree.size(); - uint32 check=0, count=0; - check += fwrite(&bounds.low(), sizeof(float), 3, wf); - check += fwrite(&bounds.high(), sizeof(float), 3, wf); - check += fwrite(&treeSize, sizeof(uint32), 1, wf); - check += fwrite(&tree[0], sizeof(uint32), treeSize, wf); - count = objects.size(); - check += fwrite(&count, sizeof(uint32), 1, wf); - check += fwrite(&objects[0], sizeof(uint32), count, wf); - return check == (3 + 3 + 2 + treeSize + count); -} - -bool BIH::readFromFile(FILE *rf) -{ - uint32 treeSize; - Vector3 lo, hi; - uint32 check=0, count=0; - check += fread(&lo, sizeof(float), 3, rf); - check += fread(&hi, sizeof(float), 3, rf); - bounds = AABox(lo, hi); - check += fread(&treeSize, sizeof(uint32), 1, rf); - tree.resize(treeSize); - check += fread(&tree[0], sizeof(uint32), treeSize, rf); - check += fread(&count, sizeof(uint32), 1, rf); - objects.resize(count); // = new uint32[nObjects]; - check += fread(&objects[0], sizeof(uint32), count, rf); - return check == (3 + 3 + 2 + treeSize + count); -} - -void BIH::BuildStats::updateLeaf(int depth, int n) -{ - numLeaves++; - minDepth = std::min(depth, minDepth); - maxDepth = std::max(depth, maxDepth); - sumDepth += depth; - minObjects = std::min(n, minObjects); - maxObjects = std::max(n, maxObjects); - sumObjects += n; - int nl = std::min(n, 5); - ++numLeavesN[nl]; -} - -void BIH::BuildStats::printStats() -{ - printf("Tree stats:\n"); - printf(" * Nodes: %d\n", numNodes); - printf(" * Leaves: %d\n", numLeaves); - printf(" * Objects: min %d\n", minObjects); - printf(" avg %.2f\n", (float) sumObjects / numLeaves); - printf(" avg(n>0) %.2f\n", (float) sumObjects / (numLeaves - numLeavesN[0])); - printf(" max %d\n", maxObjects); - printf(" * Depth: min %d\n", minDepth); - printf(" avg %.2f\n", (float) sumDepth / numLeaves); - printf(" max %d\n", maxDepth); - printf(" * Leaves w/: N=0 %3d%%\n", 100 * numLeavesN[0] / numLeaves); - printf(" N=1 %3d%%\n", 100 * numLeavesN[1] / numLeaves); - printf(" N=2 %3d%%\n", 100 * numLeavesN[2] / numLeaves); - printf(" N=3 %3d%%\n", 100 * numLeavesN[3] / numLeaves); - printf(" N=4 %3d%%\n", 100 * numLeavesN[4] / numLeaves); - printf(" N>4 %3d%%\n", 100 * numLeavesN[5] / numLeaves); - printf(" * BVH2 nodes: %d (%3d%%)\n", numBVH2, 100 * numBVH2 / (numNodes + numLeaves - 2 * numBVH2)); -} diff --git a/src/server/shared/vmap/BIH.h b/src/server/shared/vmap/BIH.h deleted file mode 100644 index 15ae90c23eb..00000000000 --- a/src/server/shared/vmap/BIH.h +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _BIH_H -#define _BIH_H - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#define MAX_STACK_SIZE 64 - -#ifdef _MSC_VER - #define isnan(x) _isnan(x) -#endif - -using G3D::Vector3; -using G3D::AABox; -using G3D::Ray; - -static inline uint32 floatToRawIntBits(float f) -{ - union - { - uint32 ival; - float fval; - } temp; - temp.fval=f; - return temp.ival; -} - -static inline float intBitsToFloat(uint32 i) -{ - union - { - uint32 ival; - float fval; - } temp; - temp.ival=i; - return temp.fval; -} - -struct AABound -{ - Vector3 lo, hi; -}; - -/** Bounding Interval Hierarchy Class. - Building and Ray-Intersection functions based on BIH from - Sunflow, a Java Raytracer, released under MIT/X11 License - http://sunflow.sourceforge.net/ - Copyright (c) 2003-2007 Christopher Kulla -*/ - -class BIH -{ - public: - BIH() {}; - template< class T, class BoundsFunc > - void build(const std::vector &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false) - { - if(primitives.size() == 0) - return; - buildData dat; - dat.maxPrims = leafSize; - dat.numPrims = primitives.size(); - dat.indices = new uint32[dat.numPrims]; - dat.primBound = new AABox[dat.numPrims]; - getBounds(primitives[0], bounds); - for (uint32 i=0; i tempTree; - BuildStats stats; - buildHierarchy(tempTree, dat, stats); - if (printStats) - stats.printStats(); - - objects.resize(dat.numPrims); - for (uint32 i=0; i - void intersectRay(const Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const - { - float intervalMin = 0.f; - float intervalMax = maxDist; - Vector3 org = r.origin(); - Vector3 dir = r.direction(); - Vector3 invDir; - float t1, t2; - for(int i=0; i<3; ++i) - { - invDir[i] = 1.f / dir[i]; - t1 = (bounds.low()[i] - org[i]) * invDir[i]; - t2 = (bounds.high()[i] - org[i]) * invDir[i]; - if (invDir[i] > 0) { - if (t1 > intervalMin) - intervalMin = t1; - if (t2 < intervalMax) - intervalMax = t2; - } else { - if (t2 > intervalMin) - intervalMin = t2; - if (t1 < intervalMax) - intervalMax = t1; - } - if (intervalMin > intervalMax) - return; - } - - uint32 offsetFront[3]; - uint32 offsetBack[3]; - uint32 offsetFront3[3]; - uint32 offsetBack3[3]; - // compute custom offsets from direction sign bit - - for(int i=0; i<3; ++i) - { - offsetFront[i] = floatToRawIntBits(dir[i]) >> 31; - offsetBack[i] = offsetFront[i] ^ 1; - offsetFront3[i] = offsetFront[i] * 3; - offsetBack3[i] = offsetBack[i] * 3; - - // avoid always adding 1 during the inner loop - ++offsetFront[i]; - ++offsetBack[i]; - } - - StackNode stack[MAX_STACK_SIZE]; - int stackPos = 0; - int node = 0; - - while (true) { - while (true) - { - uint32 tn = tree[node]; - uint32 axis = (tn & (3 << 30)) >> 30; - bool BVH2 = tn & (1 << 29); - int offset = tn & ~(7 << 29); - if (!BVH2) - { - if (axis < 3) - { - // "normal" interior node - float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; - float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; - // ray passes between clip zones - if (tf < intervalMin && tb > intervalMax) - break; - int back = offset + offsetBack3[axis]; - node = back; - // ray passes through far node only - if (tf < intervalMin) { - intervalMin = (tb >= intervalMin) ? tb : intervalMin; - continue; - } - node = offset + offsetFront3[axis]; // front - // ray passes through near node only - if (tb > intervalMax) { - intervalMax = (tf <= intervalMax) ? tf : intervalMax; - continue; - } - // ray passes through both nodes - // push back node - stack[stackPos].node = back; - stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin; - stack[stackPos].tfar = intervalMax; - stackPos++; - // update ray interval for front node - intervalMax = (tf <= intervalMax) ? tf : intervalMax; - continue; - } - else - { - // leaf - test some objects - int n = tree[node + 1]; - while (n > 0) { - bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirst); - if(stopAtFirst && hit) return; - --n; - ++offset; - } - break; - } - } - else - { - if (axis>2) - return; // should not happen - float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; - float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; - node = offset; - intervalMin = (tf >= intervalMin) ? tf : intervalMin; - intervalMax = (tb <= intervalMax) ? tb : intervalMax; - if (intervalMin > intervalMax) - break; - continue; - } - } // traversal loop - do - { - // stack is empty? - if (stackPos == 0) - return; - // move back up the stack - stackPos--; - intervalMin = stack[stackPos].tnear; - if (maxDist < intervalMin) - continue; - node = stack[stackPos].node; - intervalMax = stack[stackPos].tfar; - break; - } while (true); - } - } - - template - void intersectPoint(const Vector3 &p, IsectCallback& intersectCallback) const - { - if (!bounds.contains(p)) - return; - - StackNode stack[MAX_STACK_SIZE]; - int stackPos = 0; - int node = 0; - - while (true) { - while (true) - { - uint32 tn = tree[node]; - uint32 axis = (tn & (3 << 30)) >> 30; - bool BVH2 = tn & (1 << 29); - int offset = tn & ~(7 << 29); - if (!BVH2) - { - if (axis < 3) - { - // "normal" interior node - float tl = intBitsToFloat(tree[node + 1]); - float tr = intBitsToFloat(tree[node + 2]); - // point is between clip zones - if (tl < p[axis] && tr > p[axis]) - break; - int right = offset + 3; - node = right; - // point is in right node only - if (tl < p[axis]) { - continue; - } - node = offset; // left - // point is in left node only - if (tr > p[axis]) { - continue; - } - // point is in both nodes - // push back right node - stack[stackPos].node = right; - stackPos++; - continue; - } - else - { - // leaf - test some objects - int n = tree[node + 1]; - while (n > 0) { - intersectCallback(p, objects[offset]); // !!! - --n; - ++offset; - } - break; - } - } - else // BVH2 node (empty space cut off left and right) - { - if (axis>2) - return; // should not happen - float tl = intBitsToFloat(tree[node + 1]); - float tr = intBitsToFloat(tree[node + 2]); - node = offset; - if (tl > p[axis] || tr < p[axis]) - break; - continue; - } - } // traversal loop - - // stack is empty? - if (stackPos == 0) - return; - // move back up the stack - stackPos--; - node = stack[stackPos].node; - } - } - - bool writeToFile(FILE *wf) const; - bool readFromFile(FILE *rf); - - protected: - std::vector tree; - std::vector objects; - AABox bounds; - - struct buildData - { - uint32 *indices; - AABox *primBound; - uint32 numPrims; - int maxPrims; - }; - struct StackNode - { - uint32 node; - float tnear; - float tfar; - }; - - class BuildStats - { - private: - int numNodes; - int numLeaves; - int sumObjects; - int minObjects; - int maxObjects; - int sumDepth; - int minDepth; - int maxDepth; - int numLeavesN[6]; - int numBVH2; - - public: - BuildStats(): - numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF), - maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF), - maxDepth(0xFFFFFFFF), numBVH2(0) - { - for(int i=0; i<6; ++i) numLeavesN[i] = 0; - } - - void updateInner() { numNodes++; } - void updateBVH2() { numBVH2++; } - void updateLeaf(int depth, int n); - void printStats(); - }; - - void buildHierarchy(std::vector &tempTree, buildData &dat, BuildStats &stats); - - void createNode(std::vector &tempTree, int nodeIndex, uint32 left, uint32 right) { - // write leaf node - tempTree[nodeIndex + 0] = (3 << 30) | left; - tempTree[nodeIndex + 1] = right - left + 1; - } - - void subdivide(int left, int right, std::vector &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats); -}; - -#endif // _BIH_H diff --git a/src/server/shared/vmap/CMakeLists.txt b/src/server/shared/vmap/CMakeLists.txt deleted file mode 100644 index 7d865d354e7..00000000000 --- a/src/server/shared/vmap/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ - -########### next target ############### - -SET(vmaps_STAT_SRCS - BIH.h - BIH.cpp - IVMapManager.h - MapTree.cpp - MapTree.h - ModelInstance.cpp - ModelInstance.h - TileAssembler.cpp - TileAssembler.h - VMapDefinitions.h - VMapFactory.cpp - VMapFactory.h - VMapManager2.cpp - VMapManager2.h - VMapTools.h - WorldModel.cpp - WorldModel.h -) - -include_directories( - ${ACE_INCLUDE_DIR} - ${CMAKE_SOURCE_DIR}/src/server/framework - ${CMAKE_SOURCE_DIR}/dep/include/g3dlite -) - -add_library(vmaps STATIC ${vmaps_STAT_SRCS}) diff --git a/src/server/shared/vmap/IVMapManager.h b/src/server/shared/vmap/IVMapManager.h deleted file mode 100644 index 00629eb122c..00000000000 --- a/src/server/shared/vmap/IVMapManager.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _IVMAPMANAGER_H -#define _IVMAPMANAGER_H - -#include -#include - -//=========================================================== - -/** -This is the minimum interface to the VMapMamager. -*/ - -namespace VMAP -{ - - enum VMAP_LOAD_RESULT - { - VMAP_LOAD_RESULT_ERROR, - VMAP_LOAD_RESULT_OK, - VMAP_LOAD_RESULT_IGNORED, - }; - - #define VMAP_INVALID_HEIGHT -100000.0f // for check - #define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case - - //=========================================================== - class IVMapManager - { - private: - bool iEnableLineOfSightCalc; - bool iEnableHeightCalc; - - public: - IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) {} - - virtual ~IVMapManager(void) {} - - virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; - - virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; - - virtual void unloadMap(unsigned int pMapId, int x, int y) = 0; - virtual void unloadMap(unsigned int pMapId) = 0; - - virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0; - virtual float getHeight(unsigned int pMapId, float x, float y, float z) = 0; - /** - test if we hit an object. return true if we hit one. rx,ry,rz will hold the hit position or the dest position, if no intersection was found - return a position, that is pReduceDist closer to the origin - */ - virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) = 0; - /** - send debug commands - */ - virtual bool processCommand(char *pCommand)= 0; - - /** - Enable/disable LOS calculation - It is enabled by default. If it is enabled in mid game the maps have to loaded manualy - */ - void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; } - /** - Enable/disable model height calculation - It is enabled by default. If it is enabled in mid game the maps have to loaded manualy - */ - void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; } - - bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); } - bool isHeightCalcEnabled() const { return(iEnableHeightCalc); } - bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); } - - virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0; - /** - Block maps from being used. - parameter: String of map ids. Delimiter = "," - e.g.: "0,1,530" - */ - virtual void preventMapsFromBeingUsed(const char* pMapIdString) =0; - /** - Query world model area info. - \param z gets adjusted to the ground height for which this are info is valid - */ - virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0; - virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const=0; - }; - -} -#endif diff --git a/src/server/shared/vmap/MapTree.cpp b/src/server/shared/vmap/MapTree.cpp deleted file mode 100644 index 8c77ee109f3..00000000000 --- a/src/server/shared/vmap/MapTree.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "MapTree.h" -#include "ModelInstance.h" -#include "VMapManager2.h" -#include "VMapDefinitions.h" - -#include -#include -#include - -using G3D::Vector3; - -namespace VMAP -{ - - class MapRayCallback - { - public: - MapRayCallback(ModelInstance *val): prims(val) {} - ModelInstance *prims; - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true) - { - return prims[entry].intersectRay(ray, distance, pStopAtFirstHit); - //std::cout << "trying to intersect '" << entity->name << "'\n"; - } - }; - - class AreaInfoCallback - { - public: - AreaInfoCallback(ModelInstance *val): prims(val) {} - void operator()(const Vector3& point, uint32 entry) - { -#ifdef VMAP_DEBUG - std::cout << "trying to intersect '" << prims[entry].name << "'\n"; -#endif - prims[entry].intersectPoint(point, aInfo); - } - - ModelInstance *prims; - AreaInfo aInfo; - }; - - class LocationInfoCallback - { - public: - LocationInfoCallback(ModelInstance *val, LocationInfo &info): prims(val), locInfo(info), result(false) {} - void operator()(const Vector3& point, uint32 entry) - { -#ifdef VMAP_DEBUG - std::cout << "trying to intersect '" << prims[entry].name << "'\n"; -#endif - if (prims[entry].GetLocationInfo(point, locInfo)) - result = true; - } - - ModelInstance *prims; - LocationInfo &locInfo; - bool result; - }; - - - //========================================================= - - std::string StaticMapTree::getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY) - { - std::stringstream tilefilename; - tilefilename.fill('0'); - tilefilename << std::setw(3) << mapID << "_"; - //tilefilename << std::setw(2) << tileX << "_" << std::setw(2) << tileY << ".vmtile"; - tilefilename << std::setw(2) << tileY << "_" << std::setw(2) << tileX << ".vmtile"; - return tilefilename.str(); - } - - bool StaticMapTree::getAreaInfo(Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const - { - AreaInfoCallback intersectionCallBack(iTreeValues); - iTree.intersectPoint(pos, intersectionCallBack); - if (intersectionCallBack.aInfo.result) - { - flags = intersectionCallBack.aInfo.flags; - adtId = intersectionCallBack.aInfo.adtId; - rootId = intersectionCallBack.aInfo.rootId; - groupId = intersectionCallBack.aInfo.groupId; - pos.z = intersectionCallBack.aInfo.ground_Z; - return true; - } - return false; - } - - bool StaticMapTree::GetLocationInfo(const Vector3 &pos, LocationInfo &info) const - { - LocationInfoCallback intersectionCallBack(iTreeValues, info); - iTree.intersectPoint(pos, intersectionCallBack); - return intersectionCallBack.result; - } - - StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath): - iMapID(mapID), /* iTree(0), */ iTreeValues(0), iBasePath(basePath) - { - if (iBasePath.length() > 0 && (iBasePath[iBasePath.length()-1] != '/' || iBasePath[iBasePath.length()-1] != '\\')) - { - iBasePath.append("/"); - } - } - - //========================================================= - //! Make sure to call unloadMap() to unregister acquired model references before destroying - StaticMapTree::~StaticMapTree() - { - delete[] iTreeValues; - } - - //========================================================= - /** - return dist to hit or inf() if no hit - */ - - float StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const - { - float distance = pMaxDist; - MapRayCallback intersectionCallBack(iTreeValues); - iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit); - return distance; - } - //========================================================= - - bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const - { - bool result = true; - float maxDist = (pos2 - pos1).magnitude(); - // prevent NaN values which can cause BIH intersection to enter infinite loop - if (maxDist < 1e-10f) - return true; - // direction with length of 1 - G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist); - float resultDist = getIntersectionTime(ray, maxDist, true); - if (resultDist < maxDist) - { - result = false; - } - return result; - } - //========================================================= - /** - When moving from pos1 to pos2 check if we hit an object. Return true and the position if we hit one - Return the hit pos or the original dest pos - */ - - bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const - { - bool result=false; - float maxDist = (pPos2 - pPos1).magnitude(); - // prevent NaN values which can cause BIH intersection to enter infinite loop - if (maxDist < 1e-10f) - { - pResultHitPos = pPos2; - return false; - } - Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1 - G3D::Ray ray(pPos1, dir); - float dist = getIntersectionTime(ray, maxDist, false); - if (dist < maxDist) - { - pResultHitPos = pPos1 + dir * dist; - if (pModifyDist < 0) - { - if ((pResultHitPos - pPos1).magnitude() > -pModifyDist) - { - pResultHitPos = pResultHitPos + dir*pModifyDist; - } - else - { - pResultHitPos = pPos1; - } - } - else - { - pResultHitPos = pResultHitPos + dir*pModifyDist; - } - result = true; - } - else - { - pResultHitPos = pPos2; - result = false; - } - return result; - } - - //========================================================= - - float StaticMapTree::getHeight(const Vector3& pPos) const - { - float height = G3D::inf(); - Vector3 dir = Vector3(0,0,-1); - G3D::Ray ray(pPos, dir); // direction with length of 1 - float maxDist = VMapDefinitions::getMaxCanFallDistance(); - float dist = getIntersectionTime(ray, maxDist, false); - if (dist < maxDist) - { - height = pPos.z - dist; - } - return(height); - } - - //========================================================= - - bool StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY) - { - std::string basePath = vmapPath; - if (basePath.length() > 0 && (basePath[basePath.length()-1] != '/' || basePath[basePath.length()-1] != '\\')) - basePath.append("/"); - std::string fullname = basePath + VMapManager2::getMapFileName(mapID); - bool success = true; - FILE *rf = fopen(fullname.c_str(), "rb"); - if (!rf) - return false; - // TODO: check magic number when implemented... - char tiled; - char chunk[8]; - if (!readChunk(rf, chunk, VMAP_MAGIC, 8) || fread(&tiled, sizeof(char), 1, rf) != 1) - { - fclose(rf); - return false; - } - if (tiled) - { - std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (!tf) - success = false; - else - fclose(tf); - } - fclose(rf); - return success; - } - - //========================================================= - - bool StaticMapTree::InitMap(const std::string &fname, VMapManager2 *vm) - { - std::cout << "Initializing StaticMapTree '" << fname << "'\n"; - bool success = true; - std::string fullname = iBasePath + fname; - FILE *rf = fopen(fullname.c_str(), "rb"); - if (!rf) - return false; - else - { - char chunk[8]; - //general info - if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) success = false; - char tiled; - if (success && fread(&tiled, sizeof(char), 1, rf) != 1) success = false; - iIsTiled = bool(tiled); - // Nodes - if (success && !readChunk(rf, chunk, "NODE", 4)) success = false; - if (success) success = iTree.readFromFile(rf); - if (success) - { - iNTreeValues = iTree.primCount(); - iTreeValues = new ModelInstance[iNTreeValues]; - } - - if (success && !readChunk(rf, chunk, "GOBJ", 4)) success = false; - // global model spawns - // only non-tiled maps have them, and if so exactly one (so far at least...) - ModelSpawn spawn; -#ifdef VMAP_DEBUG - std::cout << "Map isTiled:" << bool(iIsTiled) << std::endl; -#endif - if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) - { - WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name); - std::cout << "StaticMapTree::InitMap(): loading " << spawn.name << std::endl; - if (model) - { - // assume that global model always is the first and only tree value (could be improved...) - iTreeValues[0] = ModelInstance(spawn, model); - iLoadedSpawns[0] = 1; - } - else - { - success = false; - std::cout << "error: could not acquire WorldModel pointer!\n"; - } - } - - fclose(rf); - } - return success; - } - - //========================================================= - - void StaticMapTree::UnloadMap(VMapManager2 *vm) - { - for (loadedSpawnMap::iterator i = iLoadedSpawns.begin(); i != iLoadedSpawns.end(); ++i) - { - iTreeValues[i->first].setUnloaded(); - for (uint32 refCount = 0; refCount < i->second; ++refCount) - vm->releaseModelInstance(iTreeValues[i->first].name); - } - iLoadedSpawns.clear(); - iLoadedTiles.clear(); - } - - //========================================================= - - bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm) - { - if (!iIsTiled) - { - // currently, core creates grids for all maps, whether it has terrain tiles or not - // so we need "fake" tile loads to know when we can unload map geometry - iLoadedTiles[packTileID(tileX, tileY)] = false; - return true; - } - if (!iTreeValues) - { - std::cout << "Tree has not been initialized!\n"; - return false; - } - bool result = true; - - std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (tf) - { - uint32 numSpawns; - if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) - result = false; - for (uint32 i=0; iacquireModelInstance(iBasePath, spawn.name); - if (!model) std::cout << "error: could not acquire WorldModel pointer!\n"; - - // update tree - uint32 referencedVal; - - fread(&referencedVal, sizeof(uint32), 1, tf); - if (!iLoadedSpawns.count(referencedVal)) - { -#ifdef VMAP_DEBUG - if (referencedVal > iNTreeValues) - { - std::cout << "invalid tree element! (" << referencedVal << "/" << iNTreeValues << ")\n"; - continue; - } -#endif - iTreeValues[referencedVal] = ModelInstance(spawn, model); - iLoadedSpawns[referencedVal] = 1; - } - else - { - ++iLoadedSpawns[referencedVal]; -#ifdef VMAP_DEBUG - if (iTreeValues[referencedVal].ID != spawn.ID) std::cout << "error: trying to load wrong spawn in node!\n"; - else if (iTreeValues[referencedVal].name != spawn.name) std::cout << "error: name collision on GUID="<< spawn.ID << "\n"; -#endif - } - } - } - iLoadedTiles[packTileID(tileX, tileY)] = true; - fclose(tf); - } - else - iLoadedTiles[packTileID(tileX, tileY)] = false; - return result; - } - - //========================================================= - - void StaticMapTree::UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm) - { - uint32 tileID = packTileID(tileX, tileY); - loadedTileMap::iterator tile = iLoadedTiles.find(tileID); - if (tile == iLoadedTiles.end()) - { - std::cout << "WARNING: trying to unload non-loaded tile. Map:" << iMapID << " X:" << tileX << " Y:" << tileY << std::endl; - return; - } - if (tile->second) // file associated with tile - { - std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (tf) - { - bool result=true; - uint32 numSpawns; - if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) - result = false; - for (uint32 i=0; ireleaseModelInstance(spawn.name); - - // update tree - uint32 referencedNode; - - fread(&referencedNode, sizeof(uint32), 1, tf); - if (!iLoadedSpawns.count(referencedNode)) - { - std::cout << "error! trying to unload non-referenced model '" << spawn.name << "' (ID:" << spawn.ID << ")\n"; - } - else if (--iLoadedSpawns[referencedNode] == 0) - { - //std::cout << "MapTree: removing '" << spawn.name << "' from tree\n"; - iTreeValues[referencedNode].setUnloaded(); - iLoadedSpawns.erase(referencedNode); - } - } - } - fclose(tf); - } - } - iLoadedTiles.erase(tile); - } - -} diff --git a/src/server/shared/vmap/MapTree.h b/src/server/shared/vmap/MapTree.h deleted file mode 100644 index 7955cb92d68..00000000000 --- a/src/server/shared/vmap/MapTree.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _MAPTREE_H -#define _MAPTREE_H - -#include "Platform/Define.h" -#include "Utilities/UnorderedMap.h" -#include "BIH.h" - -namespace VMAP -{ - class ModelInstance; - class GroupModel; - class VMapManager2; - - struct LocationInfo - { - LocationInfo(): hitInstance(0), hitModel(0), ground_Z(-G3D::inf()) {}; - const ModelInstance *hitInstance; - const GroupModel *hitModel; - float ground_Z; - }; - - class StaticMapTree - { - typedef UNORDERED_MAP loadedTileMap; - typedef UNORDERED_MAP loadedSpawnMap; - private: - uint32 iMapID; - bool iIsTiled; - BIH iTree; - ModelInstance *iTreeValues; // the tree entries - uint32 iNTreeValues; - - // Store all the map tile idents that are loaded for that map - // some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed - // empty tiles have no tile file, hence map with bool instead of just a set (consistency check) - loadedTileMap iLoadedTiles; - // stores to invalidate tree values, unload map, and to be able to report errors - loadedSpawnMap iLoadedSpawns; - std::string iBasePath; - - private: - float getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const; - //bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); } - public: - static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY); - static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX<<16 | tileY; } - static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY) { tileX = ID>>16; tileY = ID&0xFF; } - static bool CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY); - - StaticMapTree(uint32 mapID, const std::string &basePath); - ~StaticMapTree(); - - bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const; - bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const; - float getHeight(const G3D::Vector3& pPos) const; - bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; - bool GetLocationInfo(const Vector3 &pos, LocationInfo &info) const; - - bool InitMap(const std::string &fname, VMapManager2 *vm); - void UnloadMap(VMapManager2 *vm); - bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm); - void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm); - bool isTiled() const { return iIsTiled; } - uint32 numLoadedTiles() const { return iLoadedTiles.size(); } - }; - - struct AreaInfo - { - AreaInfo(): result(false), ground_Z(-G3D::inf()) {}; - bool result; - float ground_Z; - uint32 flags; - int32 adtId; - int32 rootId; - int32 groupId; - }; -} // VMAP - -#endif // _MAPTREE_H diff --git a/src/server/shared/vmap/ModelInstance.cpp b/src/server/shared/vmap/ModelInstance.cpp deleted file mode 100644 index 677a08e147a..00000000000 --- a/src/server/shared/vmap/ModelInstance.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ModelInstance.h" -#include "WorldModel.h" -#include "MapTree.h" - -using G3D::Vector3; -using G3D::Ray; - -namespace VMAP -{ - ModelInstance::ModelInstance(const ModelSpawn &spawn, WorldModel *model): ModelSpawn(spawn), iModel(model) - { - iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iRot.y/180.f, G3D::pi()*iRot.x/180.f, G3D::pi()*iRot.z/180.f).inverse(); - iInvScale = 1.f/iScale; - } - - bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const - { - if (!iModel) - { - //std::cout << "\n"; - return false; - } - float time = pRay.intersectionTime(iBound); - if (time == G3D::inf()) - { -// std::cout << "Ray does not hit '" << name << "'\n"; - - return false; - } -// std::cout << "Ray crosses bound of '" << name << "'\n"; -/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z - << " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z - << " t/tmax:" << time << "/" << pMaxDist; - std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: " - << iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */ - // child bounds are defined in object space: - Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale; - Ray modRay(p, iInvRot * pRay.direction()); - float distance = pMaxDist * iInvScale; - bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit); - distance *= iScale; - pMaxDist = distance; - return hit; - } - - void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const - { - if (!iModel) - { -#ifdef VMAP_DEBUG - std::cout << "\n"; -#endif - return; - } - - // M2 files don't contain area info, only WMO files - if (flags & MOD_M2) - return; - if (!iBound.contains(p)) - return; - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (iModel->IntersectPoint(pModel, zDirModel, zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - // Transform back to world space. Note that: - // Mat * vec == vec * Mat.transpose() - // and for rotation matrices: Mat.inverse() == Mat.transpose() - float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; - if (info.ground_Z < world_Z) - { - info.ground_Z = world_Z; - info.adtId = adtId; - } - } - } - - bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const - { - if (!iModel) - { -#ifdef VMAP_DEBUG - std::cout << "\n"; -#endif - return false; - } - - // M2 files don't contain area info, only WMO files - if (flags & MOD_M2) - return false; - if (!iBound.contains(p)) - return false; - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - // Transform back to world space. Note that: - // Mat * vec == vec * Mat.transpose() - // and for rotation matrices: Mat.inverse() == Mat.transpose() - float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; - if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection? - { - info.ground_Z = world_Z; - info.hitInstance = this; - return true; - } - } - return false; - } - - bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const - { - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (info.hitModel->GetLiquidLevel(pModel, zDist)) - { - // calculate world height (zDist in model coords): - // assume WMO not tilted (wouldn't make much sense anyway) - liqHeight = zDist * iScale + iPos.z; - return true; - } - return false; - } - - bool ModelSpawn::readFromFile(FILE *rf, ModelSpawn &spawn) - { - uint32 check=0, nameLen; - check += fread(&spawn.flags, sizeof(uint32), 1, rf); - // EoF? - if (!check) - { - if (ferror(rf)) - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - check += fread(&spawn.adtId, sizeof(uint16), 1, rf); - check += fread(&spawn.ID, sizeof(uint32), 1, rf); - check += fread(&spawn.iPos, sizeof(float), 3, rf); - check += fread(&spawn.iRot, sizeof(float), 3, rf); - check += fread(&spawn.iScale, sizeof(float), 1, rf); - bool has_bound = (spawn.flags & MOD_HAS_BOUND); - if (has_bound) // only WMOs have bound in MPQ, only available after computation - { - Vector3 bLow, bHigh; - check += fread(&bLow, sizeof(float), 3, rf); - check += fread(&bHigh, sizeof(float), 3, rf); - spawn.iBound = G3D::AABox(bLow, bHigh); - } - check += fread(&nameLen, sizeof(uint32), 1, rf); - if(check != (has_bound ? 17 : 11)) - { - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - char nameBuff[500]; - if (nameLen>500) // file names should never be that long, must be file error - { - std::cout << "Error reading ModelSpawn, file name too long!\n"; - return false; - } - check = fread(nameBuff, sizeof(char), nameLen, rf); - if (check != nameLen) - { - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - spawn.name = std::string(nameBuff, nameLen); - return true; - } - - bool ModelSpawn::writeToFile(FILE *wf, const ModelSpawn &spawn) - { - uint32 check=0; - check += fwrite(&spawn.flags, sizeof(uint32), 1, wf); - check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf); - check += fwrite(&spawn.ID, sizeof(uint32), 1, wf); - check += fwrite(&spawn.iPos, sizeof(float), 3, wf); - check += fwrite(&spawn.iRot, sizeof(float), 3, wf); - check += fwrite(&spawn.iScale, sizeof(float), 1, wf); - bool has_bound = (spawn.flags & MOD_HAS_BOUND); - if(has_bound) // only WMOs have bound in MPQ, only available after computation - { - check += fwrite(&spawn.iBound.low(), sizeof(float), 3, wf); - check += fwrite(&spawn.iBound.high(), sizeof(float), 3, wf); - } - uint32 nameLen = spawn.name.length(); - check += fwrite(&nameLen, sizeof(uint32), 1, wf); - if(check != (has_bound ? 17 : 11)) return false; - check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf); - if(check != nameLen) return false; - return true; - } - -} diff --git a/src/server/shared/vmap/ModelInstance.h b/src/server/shared/vmap/ModelInstance.h deleted file mode 100644 index 97b3ab632a1..00000000000 --- a/src/server/shared/vmap/ModelInstance.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _MODELINSTANCE_H_ -#define _MODELINSTANCE_H_ - -#include -#include -#include -#include - -#include "Platform/Define.h" - -namespace VMAP -{ - class WorldModel; - struct AreaInfo; - struct LocationInfo; - - enum ModelFlags - { - MOD_M2 = 1, - MOD_WORLDSPAWN = 1<<1, - MOD_HAS_BOUND = 1<<2 - }; - - class ModelSpawn - { - public: - //mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name - uint32 flags; - uint16 adtId; - uint32 ID; - G3D::Vector3 iPos; - G3D::Vector3 iRot; - float iScale; - G3D::AABox iBound; - std::string name; - bool operator==(const ModelSpawn &other) const { return ID == other.ID; } - //uint32 hashCode() const { return ID; } - // temp? - const G3D::AABox& getBounds() const { return iBound; } - - - static bool readFromFile(FILE *rf, ModelSpawn &spawn); - static bool writeToFile(FILE *rw, const ModelSpawn &spawn); - }; - - class ModelInstance: public ModelSpawn - { - public: - ModelInstance(): iModel(0) {} - ModelInstance(const ModelSpawn &spawn, WorldModel *model); - void setUnloaded() { iModel = 0; } - bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const; - void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const; - bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const; - bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const; - protected: - G3D::Matrix3 iInvRot; - float iInvScale; - WorldModel *iModel; - }; -} // namespace VMAP - -#endif // _MODELINSTANCE diff --git a/src/server/shared/vmap/TileAssembler.cpp b/src/server/shared/vmap/TileAssembler.cpp deleted file mode 100644 index d01b54a7564..00000000000 --- a/src/server/shared/vmap/TileAssembler.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "WorldModel.h" -#include "TileAssembler.h" -#include "MapTree.h" -#include "BIH.h" -#include "VMapDefinitions.h" - -#include -#include -#include -#include - -using G3D::Vector3; -using G3D::AABox; -using G3D::inf; -using std::pair; - -template<> struct BoundsTrait -{ - static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); } -}; - -namespace VMAP -{ - bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len) - { - if (fread(dest, sizeof(char), len, rf) != len) return false; - return memcmp(dest, compare, len) == 0; - } - - Vector3 ModelPosition::transform(const Vector3& pIn) const - { - Vector3 out = pIn * iScale; - out = iRotation * out; - return(out); - } - - //================================================================= - - TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName) - { - iCurrentUniqueNameId = 0; - iFilterMethod = NULL; - iSrcDir = pSrcDirName; - iDestDir = pDestDirName; - //mkdir(iDestDir); - //init(); - } - - TileAssembler::~TileAssembler() - { - //delete iCoordModelMapping; - } - - bool TileAssembler::convertWorld2() - { - std::set spawnedModelFiles; - bool success = readMapSpawns(); - if (!success) - return false; - - // export Map data - for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter) - { - // build global map tree - std::vector mapSpawns; - UniqueEntryMap::iterator entry; - for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry) - { - // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail - if (entry->second.flags & MOD_M2) - { - if (!calculateTransformedBound(entry->second)) - break; - } - else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ - { - // TODO: remove extractor hack and uncomment below line: - //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); - entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); - } - mapSpawns.push_back(&(entry->second)); - spawnedModelFiles.insert(entry->second.name); - } - - BIH pTree; - pTree.build(mapSpawns, BoundsTrait::getBounds); - - // ===> possibly move this code to StaticMapTree class - std::map modelNodeIdx; - for (uint32 i=0; i(mapSpawns[i]->ID, i)); - if (!modelNodeIdx.empty()) - printf("min GUID: %u, max GUID: %u\n", modelNodeIdx.begin()->first, modelNodeIdx.rbegin()->first); - - // write map tree file - std::stringstream mapfilename; - mapfilename << iDestDir << "/" << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree"; - FILE *mapfile = fopen(mapfilename.str().c_str(), "wb"); - if (!mapfile) - { - success = false; - printf("Cannot open %s\n", mapfilename.str().c_str()); - break; - } - - //general info - if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false; - uint32 globalTileID = StaticMapTree::packTileID(65, 65); - pair globalRange = map_iter->second->TileEntries.equal_range(globalTileID); - char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO - if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false; - // Nodes - if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false; - if (success) success = pTree.writeToFile(mapfile); - // global map spawns (WDT), if any (most instances) - if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false; - - for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob) - { - success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); - } - - fclose(mapfile); - - // <==== - - // write map tile files, similar to ADT files, only with extra BSP tree node info - TileMap &tileEntries = map_iter->second->TileEntries; - TileMap::iterator tile; - for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) - { - const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second]; - if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... - continue; - uint32 nSpawns = tileEntries.count(tile->first); - std::stringstream tilefilename; - tilefilename.fill('0'); - tilefilename << iDestDir << "/" << std::setw(3) << map_iter->first << "_"; - uint32 x, y; - StaticMapTree::unpackTileID(tile->first, x, y); - tilefilename << std::setw(2) << x << "_" << std::setw(2) << y << ".vmtile"; - FILE *tilefile = fopen(tilefilename.str().c_str(), "wb"); - // write number of tile spawns - if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; - // write tile spawns - for (uint32 s=0; ssecond->UniqueEntries[tile->second]; - success = success && ModelSpawn::writeToFile(tilefile, spawn2); - // MapTree nodes to update when loading tile: - std::map::iterator nIdx = modelNodeIdx.find(spawn2.ID); - if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; - } - fclose(tilefile); - } - // break; //test, extract only first map; TODO: remvoe this line - } - - // export objects - std::cout << "\nConverting Model Files" << std::endl; - for (std::set::iterator mfile = spawnedModelFiles.begin(); mfile != spawnedModelFiles.end(); ++mfile) - { - std::cout << "Converting " << *mfile << std::endl; - if (!convertRawFile(*mfile)) - { - std::cout << "error converting " << *mfile << std::endl; - success = false; - break; - } - } - - //cleanup: - for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end(); ++map_iter) - { - delete map_iter->second; - } - return success; - } - - bool TileAssembler::readMapSpawns() - { - std::string fname = iSrcDir + "/dir_bin"; - FILE *dirf = fopen(fname.c_str(), "rb"); - if (!dirf) - { - printf("Could not read dir_bin file!\n"); - return false; - } - printf("Read coordinate mapping...\n"); - uint32 mapID, tileX, tileY, check=0; - G3D::Vector3 v1, v2; - ModelSpawn spawn; - while (!feof(dirf)) - { - check = 0; - // read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name - check += fread(&mapID, sizeof(uint32), 1, dirf); - if (check == 0) // EoF... - break; - check += fread(&tileX, sizeof(uint32), 1, dirf); - check += fread(&tileY, sizeof(uint32), 1, dirf); - if (!ModelSpawn::readFromFile(dirf, spawn)) - break; - - MapSpawns *current; - MapData::iterator map_iter = mapData.find(mapID); - if (map_iter == mapData.end()) - { - printf("spawning Map %d\n", mapID); - mapData[mapID] = current = new MapSpawns(); - } - else current = (*map_iter).second; - current->UniqueEntries.insert(pair(spawn.ID, spawn)); - current->TileEntries.insert(pair(StaticMapTree::packTileID(tileX, tileY), spawn.ID)); - } - bool success = (ferror(dirf) == 0); - fclose(dirf); - return success; - } - - bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) - { - std::string modelFilename = iSrcDir + "/" + spawn.name; - ModelPosition modelPosition; - modelPosition.iDir = spawn.iRot; - modelPosition.iScale = spawn.iScale; - modelPosition.init(); - - FILE *rf = fopen(modelFilename.c_str(), "rb"); - if (!rf) - { - printf("ERROR: Can't open model file: %s\n", modelFilename.c_str()); - return false; - } - - AABox modelBound; - bool boundEmpty=true; - char ident[8]; - - int readOperation = 1; - - // temporary use defines to simplify read/check code (close file and return at fail) - #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ - fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; - #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ - fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } - - READ_OR_RETURN(&ident, 8); - CMP_OR_RETURN(ident, "VMAP003"); - - // we have to read one int. This is needed during the export and we have to skip it here - uint32 tempNVectors; - READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); - - uint32 groups, wmoRootId; - char blockId[5]; - blockId[4] = 0; - int blocksize; - float *vectorarray = 0; - - READ_OR_RETURN(&groups, sizeof(uint32)); - READ_OR_RETURN(&wmoRootId, sizeof(uint32)); - if (groups != 1) printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); - - for (uint32 g=0; g0) - { - vectorarray = new float[nvectors*3]; - READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); - } - else - { - std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl; - return false; - } - - for (uint32 i=0, indexNo=0; indexNo0) - filename.append("/"); - filename.append(pModelFilename); - FILE *rf = fopen(filename.c_str(), "rb"); - - if (!rf) - { - printf("ERROR: Can't open model file in form: %s",pModelFilename.c_str()); - printf("... or form: %s",filename.c_str() ); - return false; - } - - char ident[8]; - - int readOperation = 1; - - // temporary use defines to simplify read/check code (close file and return at fail) - #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \ - fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++; - #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \ - fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } - - READ_OR_RETURN(&ident, 8); - CMP_OR_RETURN(ident, "VMAP003"); - - // we have to read one int. This is needed during the export and we have to skip it here - uint32 tempNVectors; - READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); - - uint32 groups; - uint32 RootWMOID; - char blockId[5]; - blockId[4] = 0; - int blocksize; - - READ_OR_RETURN(&groups, sizeof(uint32)); - READ_OR_RETURN(&RootWMOID, sizeof(uint32)); - - std::vector groupsArray; - - for (uint32 g=0; g triangles; - std::vector vertexArray; - - uint32 mogpflags, GroupWMOID; - READ_OR_RETURN(&mogpflags, sizeof(uint32)); - READ_OR_RETURN(&GroupWMOID, sizeof(uint32)); - - float bbox1[3], bbox2[3]; - READ_OR_RETURN(bbox1, sizeof(float)*3); - READ_OR_RETURN(bbox2, sizeof(float)*3); - - uint32 liquidflags; - READ_OR_RETURN(&liquidflags, sizeof(uint32)); - - // will this ever be used? what is it good for anyway?? - uint32 branches; - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "GRP "); - READ_OR_RETURN(&blocksize, sizeof(int)); - READ_OR_RETURN(&branches, sizeof(uint32)); - for (uint32 b=0; b0) - { - uint16 *indexarray = new uint16[nindexes]; - READ_OR_RETURN(indexarray, nindexes*sizeof(uint16)); - for (uint32 i=0; i0) - { - float *vectorarray = new float[nvectors*3]; - READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3); - for (uint32 i=0; iGetHeightStorage(), size*sizeof(float)); - size = hlq.xtiles*hlq.ytiles; - READ_OR_RETURN(liquid->GetFlagsStorage(), size); - } - - groupsArray.push_back(GroupModel(mogpflags, GroupWMOID, AABox(Vector3(bbox1), Vector3(bbox2)))); - groupsArray.back().setMeshData(vertexArray, triangles); - groupsArray.back().setLiquidData(liquid); - - // drop of temporary use defines - #undef READ_OR_RETURN - #undef CMP_OR_RETURN - - } - fclose(rf); - - // write WorldModel - WorldModel model; - model.setRootWmoID(RootWMOID); - if (groupsArray.size()) - { - model.setGroupModels(groupsArray); - success = model.writeFile(iDestDir + "/" + pModelFilename + ".vmo"); - } - - //std::cout << "readRawFile2: '" << pModelFilename << "' tris: " << nElements << " nodes: " << nNodes << std::endl; - return success; - } -} diff --git a/src/server/shared/vmap/TileAssembler.h b/src/server/shared/vmap/TileAssembler.h deleted file mode 100644 index b26735708af..00000000000 --- a/src/server/shared/vmap/TileAssembler.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _TILEASSEMBLER_H_ -#define _TILEASSEMBLER_H_ - -#include -#include -#include - -#include "ModelInstance.h" - -namespace VMAP -{ - /** - This Class is used to convert raw vector data into balanced BSP-Trees. - To start the conversion call convertWorld(). - */ - //=============================================== - - class ModelPosition - { - private: - G3D::Matrix3 iRotation; - public: - G3D::Vector3 iPos; - G3D::Vector3 iDir; - float iScale; - void init() - { - iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iDir.y/180.f, G3D::pi()*iDir.x/180.f, G3D::pi()*iDir.z/180.f); - } - G3D::Vector3 transform(const G3D::Vector3& pIn) const; - void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; } - }; - - typedef std::map UniqueEntryMap; - typedef std::multimap TileMap; - - struct MapSpawns - { - UniqueEntryMap UniqueEntries; - TileMap TileEntries; - }; - - typedef std::map MapData; - //=============================================== - - class TileAssembler - { - private: - std::string iDestDir; - std::string iSrcDir; - bool (*iFilterMethod)(char *pName); - G3D::Table iUniqueNameIds; - unsigned int iCurrentUniqueNameId; - MapData mapData; - - public: - TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName); - virtual ~TileAssembler(); - - bool convertWorld2(); - bool readMapSpawns(); - bool calculateTransformedBound(ModelSpawn &spawn); - - bool convertRawFile(const std::string& pModelFilename); - void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; } - std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName); - unsigned int getUniqueNameId(const std::string pName); - }; - -} // VMAP -#endif /*_TILEASSEMBLER_H_*/ diff --git a/src/server/shared/vmap/VMapDefinitions.h b/src/server/shared/vmap/VMapDefinitions.h deleted file mode 100644 index e4a34cc1397..00000000000 --- a/src/server/shared/vmap/VMapDefinitions.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _VMAPDEFINITIONS_H -#define _VMAPDEFINITIONS_H -#include - -#define LIQUID_TILE_SIZE (533.333f / 128.f) - -namespace VMAP -{ - //===================================== - #define MAX_CAN_FALL_DISTANCE 10.0f - const char VMAP_MAGIC[] = "VMAP_3.0"; - - class VMapDefinitions - { - public: - static float getMaxCanFallDistance() { return MAX_CAN_FALL_DISTANCE; } - }; - - //====================================== - - // defined in TileAssembler.cpp currently... - bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len); -} -#endif diff --git a/src/server/shared/vmap/VMapFactory.cpp b/src/server/shared/vmap/VMapFactory.cpp deleted file mode 100644 index 331acbace47..00000000000 --- a/src/server/shared/vmap/VMapFactory.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include "VMapFactory.h" -#include "VMapManager2.h" - -using namespace G3D; - -namespace VMAP -{ - void chompAndTrim(std::string& str) - { - while(str.length() >0) - { - char lc = str[str.length()-1]; - if(lc == '\r' || lc == '\n' || lc == ' ' || lc == '"' || lc == '\'') - { - str = str.substr(0,str.length()-1); - } - else - { - break; - } - } - while(str.length() >0) - { - char lc = str[0]; - if(lc == ' ' || lc == '"' || lc == '\'') - { - str = str.substr(1,str.length()-1); - } - else - { - break; - } - } - } - - IVMapManager *gVMapManager = 0; - Table* iIgnoreSpellIds=0; - - //=============================================== - // result false, if no more id are found - - bool getNextId(const std::string& pString, unsigned int& pStartPos, unsigned int& pId) - { - bool result = false; - unsigned int i; - for(i=pStartPos;ipStartPos) - { - std::string idString = pString.substr(pStartPos, i-pStartPos); - pStartPos = i+1; - chompAndTrim(idString); - pId = atoi(idString.c_str()); - result = true; - } - return(result); - } - - //=============================================== - /** - parameter: String of map ids. Delimiter = "," - */ - - void VMapFactory::preventSpellsFromBeingTestedForLoS(const char* pSpellIdString) - { - if(!iIgnoreSpellIds) - iIgnoreSpellIds = new Table(); - if(pSpellIdString != NULL) - { - unsigned int pos =0; - unsigned int id; - std::string confString(pSpellIdString); - chompAndTrim(confString); - while(getNextId(confString, pos, id)) - { - iIgnoreSpellIds->set(id, true); - } - } - } - - //=============================================== - - bool VMapFactory::checkSpellForLoS(unsigned int pSpellId) - { - return(!iIgnoreSpellIds->containsKey(pSpellId)); - } - - //=============================================== - // just return the instance - IVMapManager* VMapFactory::createOrGetVMapManager() - { - if(gVMapManager == 0) - gVMapManager= new VMapManager2(); // should be taken from config ... Please change if you like :-) - return gVMapManager; - } - - //=============================================== - // delete all internal data structures - void VMapFactory::clear() - { - if(iIgnoreSpellIds) - { - delete iIgnoreSpellIds; - iIgnoreSpellIds = NULL; - } - if(gVMapManager) - { - delete gVMapManager; - gVMapManager = NULL; - } - } -} diff --git a/src/server/shared/vmap/VMapFactory.h b/src/server/shared/vmap/VMapFactory.h deleted file mode 100644 index 8dc2c01938a..00000000000 --- a/src/server/shared/vmap/VMapFactory.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _VMAPFACTORY_H -#define _VMAPFACTORY_H - -#include "IVMapManager.h" - -/** -This is the access point to the VMapManager. -*/ - -namespace VMAP -{ - //=========================================================== - - class VMapFactory - { - public: - static IVMapManager* createOrGetVMapManager(); - static void clear(); - - static void preventSpellsFromBeingTestedForLoS(const char* pSpellIdString); - static bool checkSpellForLoS(unsigned int pSpellId); - }; - -} -#endif diff --git a/src/server/shared/vmap/VMapManager2.cpp b/src/server/shared/vmap/VMapManager2.cpp deleted file mode 100644 index 1e8a84aee52..00000000000 --- a/src/server/shared/vmap/VMapManager2.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include "VMapManager2.h" -#include "MapTree.h" -#include "ModelInstance.h" -#include "WorldModel.h" -#include "VMapDefinitions.h" - -using G3D::Vector3; - -namespace VMAP -{ - - //========================================================= - - VMapManager2::VMapManager2() - { - } - - //========================================================= - - VMapManager2::~VMapManager2(void) - { - for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i) - { - delete i->second; - } - for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i) - { - delete i->second.getModel(); - } - } - - //========================================================= - - Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const - { - Vector3 pos; - const float mid = 0.5 * 64.0 * 533.33333333f; - pos.x = mid - x; - pos.y = mid - y; - pos.z = z; - - return pos; - } - - //========================================================= - - Vector3 VMapManager2::convertPositionToMangosRep(float x, float y, float z) const - { - Vector3 pos; - const float mid = 0.5 * 64.0 * 533.33333333f; - pos.x = mid - x; - pos.y = mid - y; - pos.z = z; - - return pos; - } - //========================================================= - - // move to MapTree too? - std::string VMapManager2::getMapFileName(unsigned int pMapId) - { - std::stringstream fname; - fname.width(3); - fname << std::setfill('0') << pMapId << std::string(MAP_FILENAME_EXTENSION2); - return fname.str(); - } - - //========================================================= - /** - Block maps from being used. - parameter: String of map ids. Delimiter = "," - e.g.: "0,1,590" - */ - - void VMapManager2::preventMapsFromBeingUsed(const char* pMapIdString) - { - iIgnoreMapIds.clear(); - if (pMapIdString != NULL) - { - std::string map_str; - std::stringstream map_ss; - map_ss.str(std::string(pMapIdString)); - while (std::getline(map_ss, map_str, ',')) - { - std::stringstream ss2(map_str); - int map_num = -1; - ss2 >> map_num; - if (map_num >= 0) - { - std::cout << "ingoring Map " << map_num << " for VMaps\n"; - iIgnoreMapIds[map_num] = true; - // unload map in case it is loaded - unloadMap(map_num); - } - } - } - } - - //========================================================= - - int VMapManager2::loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) - { - int result = VMAP_LOAD_RESULT_IGNORED; - if (isMapLoadingEnabled() && !iIgnoreMapIds.count(pMapId)) - { - if (_loadMap(pMapId, pBasePath, x, y)) - result = VMAP_LOAD_RESULT_OK; - else - result = VMAP_LOAD_RESULT_ERROR; - } - return result; - } - - //========================================================= - // load one tile (internal use only) - - bool VMapManager2::_loadMap(unsigned int pMapId, const std::string &basePath, uint32 tileX, uint32 tileY) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); - if (instanceTree == iInstanceMapTrees.end()) - { - std::string mapFileName = getMapFileName(pMapId); - StaticMapTree *newTree = new StaticMapTree(pMapId, basePath); - if (!newTree->InitMap(mapFileName, this)) - return false; - instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(pMapId, newTree)).first; - } - return instanceTree->second->LoadMapTile(tileX, tileY, this); - } - - //========================================================= - - void VMapManager2::unloadMap(unsigned int pMapId) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); - if (instanceTree != iInstanceMapTrees.end()) - { - instanceTree->second->UnloadMap(this); - if (instanceTree->second->numLoadedTiles() == 0) - { - delete instanceTree->second; - iInstanceMapTrees.erase(pMapId); - } - } - } - - //========================================================= - - void VMapManager2::unloadMap(unsigned int pMapId, int x, int y) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); - if (instanceTree != iInstanceMapTrees.end()) - { - instanceTree->second->UnloadMapTile(x, y, this); - if (instanceTree->second->numLoadedTiles() == 0) - { - delete instanceTree->second; - iInstanceMapTrees.erase(pMapId); - } - } - } - - //========================================================== - - bool VMapManager2::isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) - { - if (!isLineOfSightCalcEnabled()) return true; - bool result = true; - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos1 = convertPositionToInternalRep(x1,y1,z1); - Vector3 pos2 = convertPositionToInternalRep(x2,y2,z2); - if (pos1 != pos2) - { - result = instanceTree->second->isInLineOfSight(pos1, pos2); - } - } - return result; - } - //========================================================= - /** - get the hit position and return true if we hit something - otherwise the result pos will be the dest pos - */ - bool VMapManager2::getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) - { - bool result = false; - rx=x2; - ry=y2; - rz=z2; - if (isLineOfSightCalcEnabled()) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos1 = convertPositionToInternalRep(x1,y1,z1); - Vector3 pos2 = convertPositionToInternalRep(x2,y2,z2); - Vector3 resultPos; - result = instanceTree->second->getObjectHitPos(pos1, pos2, resultPos, pModifyDist); - resultPos = convertPositionToMangosRep(resultPos.x,resultPos.y,resultPos.z); - rx = resultPos.x; - ry = resultPos.y; - rz = resultPos.z; - } - } - return result; - } - - //========================================================= - /** - get height or INVALID_HEIGHT if no height available - */ - - float VMapManager2::getHeight(unsigned int pMapId, float x, float y, float z) - { - float height = VMAP_INVALID_HEIGHT_VALUE; //no height - if (isHeightCalcEnabled()) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos = convertPositionToInternalRep(x,y,z); - height = instanceTree->second->getHeight(pos); - if (!(height < G3D::inf())) - { - height = VMAP_INVALID_HEIGHT_VALUE; //no height - } - } - } - return height; - } - - //========================================================= - - bool VMapManager2::getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const - { - bool result=false; - InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(pMapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos = convertPositionToInternalRep(x, y, z); - result = instanceTree->second->getAreaInfo(pos, flags, adtId, rootId, groupId); - // z is not touched by convertPositionToMangosRep(), so just copy - z = pos.z; - } - return(result); - } - - bool VMapManager2::GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const - { - InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(pMapId); - if (instanceTree != iInstanceMapTrees.end()) - { - LocationInfo info; - Vector3 pos = convertPositionToInternalRep(x, y, z); - if (instanceTree->second->GetLocationInfo(pos, info)) - { - floor = info.ground_Z; - type = info.hitModel->GetLiquidType(); - if (ReqLiquidType && !(type & ReqLiquidType)) - return false; - if (info.hitInstance->GetLiquidLevel(pos, info, level)) - return true; - } - } - return false; - } - - //========================================================= - - WorldModel* VMapManager2::acquireModelInstance(const std::string &basepath, const std::string &filename) - { - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); - if (model == iLoadedModelFiles.end()) - { - WorldModel *worldmodel = new WorldModel(); - if (!worldmodel->readFile(basepath + filename + ".vmo")) - { - std::cout << "VMapManager2: could not load '" << basepath << filename << ".vmo'!\n"; - delete worldmodel; - return NULL; - } - std::cout << "VMapManager2: loading file '" << basepath << filename << "'.\n"; - model = iLoadedModelFiles.insert(std::pair(filename, ManagedModel())).first; - model->second.setModel(worldmodel); - } - model->second.incRefCount(); - return model->second.getModel(); - } - - void VMapManager2::releaseModelInstance(const std::string &filename) - { - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); - if (model == iLoadedModelFiles.end()) - { - std::cout << "VMapManager2: trying to unload non-loaded file '" << filename << "'!\n"; - return; - } - if( model->second.decRefCount() == 0) - { - std::cout << "VMapManager2: unloading file '" << filename << "'.\n"; - delete model->second.getModel(); - iLoadedModelFiles.erase(model); - } - } - //========================================================= - - bool VMapManager2::existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) - { - return StaticMapTree::CanLoadMap(std::string(pBasePath), pMapId, x, y); - } - -} // namespace VMAP diff --git a/src/server/shared/vmap/VMapManager2.h b/src/server/shared/vmap/VMapManager2.h deleted file mode 100644 index 5f03b87b07f..00000000000 --- a/src/server/shared/vmap/VMapManager2.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _VMAPMANAGER2_H -#define _VMAPMANAGER2_H - -#include "IVMapManager.h" -#include "Utilities/UnorderedMap.h" -#include "Platform/Define.h" -#include - -//=========================================================== - -#define MAP_FILENAME_EXTENSION2 ".vmtree" - -#define FILENAMEBUFFER_SIZE 500 - -/** -This is the main Class to manage loading and unloading of maps, line of sight, height calculation and so on. -For each map or map tile to load it reads a directory file that contains the ModelContainer files used by this map or map tile. -Each global map or instance has its own dynamic BSP-Tree. -The loaded ModelContainers are included in one of these BSP-Trees. -Additionally a table to match map ids and map names is used. -*/ - -//=========================================================== - -namespace VMAP -{ - class StaticMapTree; - class WorldModel; - - class ManagedModel - { - public: - ManagedModel(): iModel(0), iRefCount(0) {} - void setModel(WorldModel *model) { iModel = model; } - WorldModel *getModel() { return iModel; } - void incRefCount() { ++iRefCount; } - int decRefCount() { return --iRefCount; } - protected: - WorldModel *iModel; - int iRefCount; - }; - - typedef UNORDERED_MAP InstanceTreeMap; - typedef UNORDERED_MAP ModelFileMap; - - class VMapManager2 : public IVMapManager - { - protected: - // Tree to check collision - ModelFileMap iLoadedModelFiles; - InstanceTreeMap iInstanceMapTrees; - // UNORDERED_MAP iMapsSplitIntoTiles; - UNORDERED_MAP iIgnoreMapIds; - - bool _loadMap(uint32 pMapId, const std::string &basePath, uint32 tileX, uint32 tileY); - /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */ - - public: - // public for debug - G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const; - G3D::Vector3 convertPositionToMangosRep(float x, float y, float z) const; - static std::string getMapFileName(unsigned int pMapId); - - VMapManager2(); - ~VMapManager2(void); - - int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y); - - void unloadMap(unsigned int pMapId, int x, int y); - void unloadMap(unsigned int pMapId); - - bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) ; - /** - fill the hit pos and return true, if an object was hit - */ - bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist); - float getHeight(unsigned int pMapId, float x, float y, float z); - - bool processCommand(char *pCommand) { return false; } // for debug and extensions - - void preventMapsFromBeingUsed(const char* pMapIdString); - bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; - bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const; - - WorldModel* acquireModelInstance(const std::string &basepath, const std::string &filename); - void releaseModelInstance(const std::string &filename); - - // what's the use of this? o.O - virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const - { - return getMapFileName(pMapId); - } - virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y); - }; -} -#endif diff --git a/src/server/shared/vmap/VMapTools.h b/src/server/shared/vmap/VMapTools.h deleted file mode 100644 index dbbd9af9271..00000000000 --- a/src/server/shared/vmap/VMapTools.h +++ /dev/null @@ -1,150 +0,0 @@ -/* -* Copyright (C) 2005-2010 MaNGOS -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef _VMAPTOOLS_H -#define _VMAPTOOLS_H - -#include -#include - -#include "NodeValueAccess.h" - -/** -The Class is mainly taken from G3D/AABSPTree.h but modified to be able to use our internal data structure. -This is an iterator that helps us analysing the BSP-Trees. -The collision detection is modified to return true, if we are inside an object. -*/ - -namespace VMAP -{ - template - class IntersectionCallBack { - public: - TValue* closestEntity; - G3D::Vector3 hitLocation; - G3D::Vector3 hitNormal; - - void operator()(const G3D::Ray& ray, const TValue* entity, bool pStopAtFirstHit, float& distance) { - entity->intersect(ray, distance, pStopAtFirstHit, hitLocation, hitNormal); - } - }; - - //============================================================== - //============================================================== - //============================================================== - - class MyCollisionDetection - { - private: - public: - - static bool collisionLocationForMovingPointFixedAABox( - const G3D::Vector3& origin, - const G3D::Vector3& dir, - const G3D::AABox& box, - G3D::Vector3& location, - bool& Inside) - { - - // Integer representation of a floating-point value. -#define IR(x) (reinterpret_cast(x)) - - Inside = true; - const G3D::Vector3& MinB = box.low(); - const G3D::Vector3& MaxB = box.high(); - G3D::Vector3 MaxT(-1.0f, -1.0f, -1.0f); - - // Find candidate planes. - for (int i = 0; i < 3; ++i) - { - if (origin[i] < MinB[i]) - { - location[i] = MinB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) - { - MaxT[i] = (MinB[i] - origin[i]) / dir[i]; - } - } - else if (origin[i] > MaxB[i]) - { - location[i] = MaxB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) - { - MaxT[i] = (MaxB[i] - origin[i]) / dir[i]; - } - } - } - - if (Inside) - { - // definite hit - location = origin; - return true; - } - - // Get largest of the maxT's for final choice of intersection - int WhichPlane = 0; - if (MaxT[1] > MaxT[WhichPlane]) - { - WhichPlane = 1; - } - - if (MaxT[2] > MaxT[WhichPlane]) - { - WhichPlane = 2; - } - - // Check final candidate actually inside box - if (IR(MaxT[WhichPlane]) & 0x80000000) - { - // Miss the box - return false; - } - - for (int i = 0; i < 3; ++i) - { - if (i != WhichPlane) - { - location[i] = origin[i] + MaxT[WhichPlane] * dir[i]; - if ((location[i] < MinB[i]) || - (location[i] > MaxB[i])) - { - // On this plane we're outside the box extents, so - // we miss the box - return false; - } - } - } - /* - // Choose the normal to be the plane normal facing into the ray - normal = G3D::Vector3::zero(); - normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0; - */ - return true; - -#undef IR - } - }; -} -#endif diff --git a/src/server/shared/vmap/WorldModel.cpp b/src/server/shared/vmap/WorldModel.cpp deleted file mode 100644 index 690c77577ae..00000000000 --- a/src/server/shared/vmap/WorldModel.cpp +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "WorldModel.h" -#include "VMapDefinitions.h" -#include "MapTree.h" - -using G3D::Vector3; -using G3D::Ray; - -template<> struct BoundsTrait -{ - static void getBounds(const VMAP::GroupModel& obj, G3D::AABox& out) { out = obj.GetBound(); } -}; - - -namespace VMAP -{ - bool IntersectTriangle(const MeshTriangle &tri, std::vector::const_iterator points, const G3D::Ray &ray, float &distance) - { - static const float EPS = 1e-5f; - - // See RTR2 ch. 13.7 for the algorithm. - - const Vector3 e1 = points[tri.idx1] - points[tri.idx0]; - const Vector3 e2 = points[tri.idx2] - points[tri.idx0]; - const Vector3 p(ray.direction().cross(e2)); - const float a = e1.dot(p); - - if (abs(a) < EPS) { - // Determinant is ill-conditioned; abort early - return false; - } - - const float f = 1.0f / a; - const Vector3 s(ray.origin() - points[tri.idx0]); - const float u = f * s.dot(p); - - if ((u < 0.0f) || (u > 1.0f)) { - // We hit the plane of the m_geometry, but outside the m_geometry - return false; - } - - const Vector3 q(s.cross(e1)); - const float v = f * ray.direction().dot(q); - - if ((v < 0.0f) || ((u + v) > 1.0f)) { - // We hit the plane of the triangle, but outside the triangle - return false; - } - - const float t = f * e2.dot(q); - - if ((t > 0.0f) && (t < distance)) - { - // This is a new hit, closer than the previous one - distance = t; - - /* baryCoord[0] = 1.0 - u - v; - baryCoord[1] = u; - baryCoord[2] = v; */ - - return true; - } - // This hit is after the previous hit, so ignore it - return false; - } - - class TriBoundFunc - { - public: - TriBoundFunc(std::vector &vert): vertices(vert.begin()) {} - void operator()(const MeshTriangle &tri, G3D::AABox &out) const - { - G3D::Vector3 lo = vertices[tri.idx0]; - G3D::Vector3 hi = lo; - - lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]); - hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]); - - out = G3D::AABox(lo, hi); - } - protected: - const std::vector::const_iterator vertices; - }; - - // ===================== WmoLiquid ================================== - - WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type): - iTilesX(width), iTilesY(height), iCorner(corner), iType(type) - { - iHeight = new float[(width+1)*(height+1)]; - iFlags = new uint8[width*height]; - } - - WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(0), iFlags(0) - { - *this = other; // use assignment operator... - } - - WmoLiquid::~WmoLiquid() - { - delete[] iHeight; - delete[] iFlags; - } - - WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other) - { - if (this == &other) - return *this; - iTilesX = other.iTilesX; - iTilesY = other.iTilesY; - iCorner = other.iCorner; - iType = other.iType; - delete iHeight; - delete iFlags; - if (other.iHeight) - { - iHeight = new float[(iTilesX+1)*(iTilesY+1)]; - memcpy(iHeight, other.iHeight, (iTilesX+1)*(iTilesY+1)*sizeof(float)); - } - else - iHeight = 0; - if (other.iFlags) - { - iFlags = new uint8[iTilesX * iTilesY]; - memcpy(iFlags, other.iFlags, iTilesX * iTilesY); - } - else - iFlags = 0; - return *this; - } - - bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const - { - uint32 tx = (pos.x - iCorner.x)/LIQUID_TILE_SIZE; - if (tx<0 || tx >= iTilesX) return false; - uint32 ty = (pos.y - iCorner.y)/LIQUID_TILE_SIZE; - if (ty<0 || ty >= iTilesY) return false; - // checking for 0x08 *might* be enough, but disabled tiles always are 0x?F: - if ((iFlags[tx + ty*iTilesX] & 0x0F) == 0x0F) - return false; - //placeholder...use only lower left corner vertex - liqHeight = /* iCorner.z + */ iHeight[tx + ty*(iTilesX+1)]; - return true; - } - - uint32 WmoLiquid::GetFileSize() - { - return 2 * sizeof(uint32) + - sizeof(Vector3) + - (iTilesX + 1)*(iTilesY + 1) * sizeof(float) + - iTilesX * iTilesY; - } - - bool WmoLiquid::writeToFile(FILE *wf) - { - bool result = true; - if (result && fwrite(&iTilesX, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&iTilesY, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&iCorner, sizeof(Vector3), 1, wf) != 1) result = false; - if (result && fwrite(&iType, sizeof(uint32), 1, wf) != 1) result = false; - uint32 size = (iTilesX + 1)*(iTilesY + 1); - if (result && fwrite(iHeight, sizeof(float), size, wf) != size) result = false; - size = iTilesX*iTilesY; - if (result && fwrite(iFlags, sizeof(uint8), size, wf) != size) result = false; - return result; - } - - bool WmoLiquid::readFromFile(FILE *rf, WmoLiquid *&out) - { - bool result = true; - WmoLiquid *liquid = new WmoLiquid(); - if (result && fread(&liquid->iTilesX, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&liquid->iTilesY, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&liquid->iCorner, sizeof(Vector3), 1, rf) != 1) result = false; - if (result && fread(&liquid->iType, sizeof(uint32), 1, rf) != 1) result = false; - uint32 size = (liquid->iTilesX + 1)*(liquid->iTilesY + 1); - liquid->iHeight = new float[size]; - if (result && fread(liquid->iHeight, sizeof(float), size, rf) != size) result = false; - size = liquid->iTilesX * liquid->iTilesY; - liquid->iFlags = new uint8[size]; - if (result && fread(liquid->iFlags, sizeof(uint8), size, rf) != size) result = false; - if (!result) - delete liquid; - out = liquid; - return result; - } - - // ===================== GroupModel ================================== - - GroupModel::GroupModel(const GroupModel &other): - iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID), - vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0) - { - if (other.iLiquid) - iLiquid = new WmoLiquid(*other.iLiquid); - } - - void GroupModel::setMeshData(std::vector &vert, std::vector &tri) - { - vertices.swap(vert); - triangles.swap(tri); - TriBoundFunc bFunc(vertices); - meshTree.build(triangles, bFunc); - } - - bool GroupModel::writeToFile(FILE *wf) - { - bool result = true; - uint32 chunkSize, count; - - if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) result = false; - if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) result = false; - - // write vertices - if (result && fwrite("VERT", 1, 4, wf) != 4) result = false; - count = vertices.size(); - chunkSize = sizeof(uint32)+ sizeof(Vector3)*count; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - if (!count) // models without (collision) geometry end here, unsure if they are useful - return result; - if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) result = false; - - // write triangle mesh - if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false; - count = triangles.size(); - chunkSize = sizeof(uint32)+ sizeof(MeshTriangle)*count; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false; - - // write mesh BIH - if (result && fwrite("MBIH", 1, 4, wf) != 4) result = false; - if (result) result = meshTree.writeToFile(wf); - - // write liquid data - if (result && fwrite("LIQU", 1, 4, wf) != 4) result = false; - if (!iLiquid) - { - chunkSize = 0; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - return result; - } - chunkSize = iLiquid->GetFileSize(); - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result) result = iLiquid->writeToFile(wf); - - return result; - } - - bool GroupModel::readFromFile(FILE *rf) - { - char chunk[8]; - bool result = true; - uint32 chunkSize, count; - triangles.clear(); - vertices.clear(); - delete iLiquid; - iLiquid = 0; - - if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false; - if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) result = false; - - // read vertices - if (result && !readChunk(rf, chunk, "VERT", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; - if (!count) // models without (collision) geometry end here, unsure if they are useful - return result; - if (result) vertices.resize(count); - if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) result = false; - - // read triangle mesh - if (result && !readChunk(rf, chunk, "TRIM", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; - if (result) triangles.resize(count); - if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) result = false; - - // read mesh BIH - if (result && !readChunk(rf, chunk, "MBIH", 4)) result = false; - if (result) result = meshTree.readFromFile(rf); - - // write liquid data - if (result && !readChunk(rf, chunk, "LIQU", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && chunkSize > 0) - result = WmoLiquid::readFromFile(rf, iLiquid); - return result; - } - - struct GModelRayCallback - { - GModelRayCallback(const std::vector &tris, const std::vector &vert): - vertices(vert.begin()), triangles(tris.begin()), hit(false) {} - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit) - { - bool result = IntersectTriangle(triangles[entry], vertices, ray, distance); - if (result) hit=true; - return hit; - } - std::vector::const_iterator vertices; - std::vector::const_iterator triangles; - bool hit; - }; - - bool GroupModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const - { - if (!triangles.size()) - return false; - GModelRayCallback callback(triangles, vertices); - meshTree.intersectRay(ray, callback, distance, stopAtFirstHit); - return callback.hit; - } - - bool GroupModel::IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const - { - if (!triangles.size() || !iBound.contains(pos)) - return false; - GModelRayCallback callback(triangles, vertices); - Vector3 rPos = pos - 0.1f * down; - float dist = G3D::inf(); - G3D::Ray ray(rPos, down); - bool hit = IntersectRay(ray, dist, false); - if (hit) - z_dist = dist - 0.1f; - return hit; - } - - bool GroupModel::GetLiquidLevel(const Vector3 &pos, float &liqHeight) const - { - if (iLiquid) - return iLiquid->GetLiquidHeight(pos, liqHeight); - return false; - } - - uint32 GroupModel::GetLiquidType() const - { - // convert to type mask, matching MAP_LIQUID_TYPE_* defines in Map.h - if (iLiquid) - return (1 << iLiquid->GetType()); - return 0; - } - - // ===================== WorldModel ================================== - - void WorldModel::setGroupModels(std::vector &models) - { - groupModels.swap(models); - groupTree.build(groupModels, BoundsTrait::getBounds, 1); - } - - struct WModelRayCallBack - { - WModelRayCallBack(const std::vector &mod): models(mod.begin()), hit(false) {} - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit) - { - bool result = models[entry].IntersectRay(ray, distance, pStopAtFirstHit); - if (result) hit=true; - return hit; - } - std::vector::const_iterator models; - bool hit; - }; - - bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const - { - // small M2 workaround, maybe better make separate class with virtual intersection funcs - // in any case, there's no need to use a bound tree if we only have one submodel - if (groupModels.size() == 1) - return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit); - - WModelRayCallBack isc(groupModels); - groupTree.intersectRay(ray, isc, distance, stopAtFirstHit); - return isc.hit; - } - - class WModelAreaCallback { - public: - WModelAreaCallback(const std::vector &vals, const Vector3 &down): - prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) {} - std::vector::const_iterator prims; - std::vector::const_iterator hit; - float minVol; - float zDist; - Vector3 zVec; - void operator()(const Vector3& point, uint32 entry) - { - float group_Z; - //float pVol = prims[entry].GetBound().volume(); - //if(pVol < minVol) - //{ - /* if (prims[entry].iBound.contains(point)) */ - if (prims[entry].IsInsideObject(point, zVec, group_Z)) - { - //minVol = pVol; - //hit = prims + entry; - if (group_Z < zDist) - { - zDist = group_Z; - hit = prims + entry; - } -#ifdef VMAP_DEBUG - const GroupModel &gm = prims[entry]; - printf("%10u %8X %7.3f,%7.3f,%7.3f | %7.3f,%7.3f,%7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(), - gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z, - gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z); -#endif - } - //} - //std::cout << "trying to intersect '" << prims[entry].name << "'\n"; - } - }; - - bool WorldModel::IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const - { - if (!groupModels.size()) - return false; - WModelAreaCallback callback(groupModels, down); - groupTree.intersectPoint(p, callback); - if (callback.hit != groupModels.end()) - { - info.rootId = RootWMOID; - info.groupId = callback.hit->GetWmoID(); - info.flags = callback.hit->GetMogpFlags(); - info.result = true; - dist = callback.zDist; - return true; - } - return false; - } - - bool WorldModel::GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const - { - if (!groupModels.size()) - return false; - WModelAreaCallback callback(groupModels, down); - groupTree.intersectPoint(p, callback); - if (callback.hit != groupModels.end()) - { - info.hitModel = &(*callback.hit); - dist = callback.zDist; - return true; - } - return false; - } - - bool WorldModel::writeFile(const std::string &filename) - { - FILE *wf = fopen(filename.c_str(), "wb"); - if (!wf) - return false; - - bool result = true; - uint32 chunkSize, count; - result = fwrite(VMAP_MAGIC,1,8,wf) == 8; - if (result && fwrite("WMOD", 1, 4, wf) != 4) result = false; - chunkSize = sizeof(uint32) + sizeof(uint32); - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false; - - // write group models - count=groupModels.size(); - if (count) - { - if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false; - //chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count; - //if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - for (uint32 i=0; i - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _WORLDMODEL_H -#define _WORLDMODEL_H - -#include -#include -#include -#include -#include "BIH.h" - -#include "Platform/Define.h" - -namespace VMAP -{ - class TreeNode; - struct AreaInfo; - struct LocationInfo; - - class MeshTriangle - { - public: - MeshTriangle(){}; - MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) {}; - - uint32 idx0; - uint32 idx1; - uint32 idx2; - }; - - class WmoLiquid - { - public: - WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type); - WmoLiquid(const WmoLiquid &other); - ~WmoLiquid(); - WmoLiquid& operator=(const WmoLiquid &other); - bool GetLiquidHeight(const Vector3 &pos, float &liqHeight) const; - uint32 GetType() const { return iType; } - float *GetHeightStorage() { return iHeight; } - uint8 *GetFlagsStorage() { return iFlags; } - uint32 GetFileSize(); - bool writeToFile(FILE *wf); - static bool readFromFile(FILE *rf, WmoLiquid *&liquid); - private: - WmoLiquid(): iHeight(0), iFlags(0) {}; - uint32 iTilesX; //!< number of tiles in x direction, each - uint32 iTilesY; - Vector3 iCorner; //!< the lower corner - uint32 iType; //!< liquid type - float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values - uint8 *iFlags; //!< info if liquid tile is used - }; - - /*! holding additional info for WMO group files */ - class GroupModel - { - public: - GroupModel(): iLiquid(0) {} - GroupModel(const GroupModel &other); - GroupModel(uint32 mogpFlags, uint32 groupWMOID, const AABox &bound): - iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) {} - ~GroupModel() { delete iLiquid; } - - //! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry! - void setMeshData(std::vector &vert, std::vector &tri); - void setLiquidData(WmoLiquid *liquid) { iLiquid = liquid; } - bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; - bool IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const; - bool GetLiquidLevel(const Vector3 &pos, float &liqHeight) const; - uint32 GetLiquidType() const; - bool writeToFile(FILE *wf); - bool readFromFile(FILE *rf); - const G3D::AABox& GetBound() const { return iBound; } - uint32 GetMogpFlags() const { return iMogpFlags; } - uint32 GetWmoID() const { return iGroupWMOID; } - protected: - G3D::AABox iBound; - uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor - uint32 iGroupWMOID; - std::vector vertices; - std::vector triangles; - BIH meshTree; - WmoLiquid *iLiquid; - }; - /*! Holds a model (converted M2 or WMO) in its original coordinate space */ - class WorldModel - { - public: - WorldModel(): RootWMOID(0) {} - - //! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry! - void setGroupModels(std::vector &models); - void setRootWmoID(uint32 id) { RootWMOID = id; } - bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; - bool IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const; - bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const; - bool writeFile(const std::string &filename); - bool readFile(const std::string &filename); - protected: - uint32 RootWMOID; - std::vector groupModels; - BIH groupTree; - }; -} // namespace VMAP - -#endif // _WORLDMODEL_H -- cgit v1.2.3 From 1170c67a70dbda204cafb72ed80402f18af3b9a6 Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:32:59 +0200 Subject: * Move some grid stuff. --HG-- branch : trunk --- src/server/game/Grids/Cell.h | 177 ++++ src/server/game/Grids/CellImpl.h | 297 ++++++ src/server/game/Grids/GridDefines.h | 193 ++++ src/server/game/Grids/GridNotifiers.cpp | 353 +++++++ src/server/game/Grids/GridNotifiers.h | 1232 ++++++++++++++++++++++++ src/server/game/Grids/GridNotifiersImpl.h | 453 +++++++++ src/server/game/Grids/GridStates.cpp | 76 ++ src/server/game/Grids/GridStates.h | 76 ++ src/server/game/Grids/ObjectGridLoader.cpp | 325 +++++++ src/server/game/Grids/ObjectGridLoader.h | 134 +++ src/server/game/Maps/Cell/Cell.h | 177 ---- src/server/game/Maps/Cell/CellImpl.h | 297 ------ src/server/game/Maps/Grid/GridDefines.h | 193 ---- src/server/game/Maps/Grid/GridNotifiers.cpp | 353 ------- src/server/game/Maps/Grid/GridNotifiers.h | 1232 ------------------------ src/server/game/Maps/Grid/GridNotifiersImpl.h | 453 --------- src/server/game/Maps/Grid/GridStates.cpp | 76 -- src/server/game/Maps/Grid/GridStates.h | 76 -- src/server/game/Maps/Grid/ObjectGridLoader.cpp | 325 ------- src/server/game/Maps/Grid/ObjectGridLoader.h | 134 --- 20 files changed, 3316 insertions(+), 3316 deletions(-) create mode 100644 src/server/game/Grids/Cell.h create mode 100644 src/server/game/Grids/CellImpl.h create mode 100644 src/server/game/Grids/GridDefines.h create mode 100644 src/server/game/Grids/GridNotifiers.cpp create mode 100644 src/server/game/Grids/GridNotifiers.h create mode 100644 src/server/game/Grids/GridNotifiersImpl.h create mode 100644 src/server/game/Grids/GridStates.cpp create mode 100644 src/server/game/Grids/GridStates.h create mode 100644 src/server/game/Grids/ObjectGridLoader.cpp create mode 100644 src/server/game/Grids/ObjectGridLoader.h delete mode 100644 src/server/game/Maps/Cell/Cell.h delete mode 100644 src/server/game/Maps/Cell/CellImpl.h delete mode 100644 src/server/game/Maps/Grid/GridDefines.h delete mode 100644 src/server/game/Maps/Grid/GridNotifiers.cpp delete mode 100644 src/server/game/Maps/Grid/GridNotifiers.h delete mode 100644 src/server/game/Maps/Grid/GridNotifiersImpl.h delete mode 100644 src/server/game/Maps/Grid/GridStates.cpp delete mode 100644 src/server/game/Maps/Grid/GridStates.h delete mode 100644 src/server/game/Maps/Grid/ObjectGridLoader.cpp delete mode 100644 src/server/game/Maps/Grid/ObjectGridLoader.h (limited to 'src/server') diff --git a/src/server/game/Grids/Cell.h b/src/server/game/Grids/Cell.h new file mode 100644 index 00000000000..49e0329ace6 --- /dev/null +++ b/src/server/game/Grids/Cell.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CELL_H +#define TRINITY_CELL_H + +#include + +#include "GameSystem/TypeContainer.h" +#include "GameSystem/TypeContainerVisitor.h" + +#include "GridDefines.h" + +class Map; +class WorldObject; + +enum District +{ + UPPER_DISTRICT = 1, + LOWER_DISTRICT = 1 << 1, + LEFT_DISTRICT = 1 << 2, + RIGHT_DISTRICT = 1 << 3, + CENTER_DISTRICT = 1 << 4, + UPPER_LEFT_DISTRICT = (UPPER_DISTRICT | LEFT_DISTRICT), + UPPER_RIGHT_DISTRICT = (UPPER_DISTRICT | RIGHT_DISTRICT), + LOWER_LEFT_DISTRICT = (LOWER_DISTRICT | LEFT_DISTRICT), + LOWER_RIGHT_DISTRICT = (LOWER_DISTRICT | RIGHT_DISTRICT), + ALL_DISTRICT = (UPPER_DISTRICT | LOWER_DISTRICT | LEFT_DISTRICT | RIGHT_DISTRICT | CENTER_DISTRICT) +}; + +struct CellArea +{ + CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {} + CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {} + bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; } + + void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const + { + begin_cell << left_offset; + begin_cell -= lower_offset; + end_cell >> right_offset; + end_cell += upper_offset; + } + + int right_offset; + int left_offset; + int upper_offset; + int lower_offset; +}; + +struct Cell +{ + Cell() { data.All = 0; } + Cell(const Cell &cell) { data.All = cell.data.All; } + explicit Cell(CellPair const& p); + + void operator|=(Cell &cell) + { + data.Part.reserved = 0; + cell.data.Part.reserved = 0; + uint32 x, y, old_x, old_y; + Compute(x, y); + cell.Compute(old_x, old_y); + + if (std::abs(int(x-old_x)) > 1 || std::abs(int(y-old_y)) > 1) + { + data.Part.reserved = ALL_DISTRICT; + cell.data.Part.reserved = ALL_DISTRICT; + return; + } + + if (x < old_x) + { + data.Part.reserved |= LEFT_DISTRICT; + cell.data.Part.reserved |= RIGHT_DISTRICT; + } + else if (old_x < x) + { + data.Part.reserved |= RIGHT_DISTRICT; + cell.data.Part.reserved |= LEFT_DISTRICT; + } + if (y < old_y) + { + data.Part.reserved |= UPPER_DISTRICT; + cell.data.Part.reserved |= LOWER_DISTRICT; + } + else if (old_y < y) + { + data.Part.reserved |= LOWER_DISTRICT; + cell.data.Part.reserved |= UPPER_DISTRICT; + } + } + + void Compute(uint32 &x, uint32 &y) const + { + x = data.Part.grid_x*MAX_NUMBER_OF_CELLS + data.Part.cell_x; + y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; + } + + bool DiffCell(const Cell &cell) const + { + return(data.Part.cell_x != cell.data.Part.cell_x || + data.Part.cell_y != cell.data.Part.cell_y); + } + + bool DiffGrid(const Cell &cell) const + { + return(data.Part.grid_x != cell.data.Part.grid_x || + data.Part.grid_y != cell.data.Part.grid_y); + } + + uint32 CellX() const { return data.Part.cell_x; } + uint32 CellY() const { return data.Part.cell_y; } + uint32 GridX() const { return data.Part.grid_x; } + uint32 GridY() const { return data.Part.grid_y; } + bool NoCreate() const { return data.Part.nocreate; } + void SetNoCreate() { data.Part.nocreate = 1; } + + CellPair cellPair() const + { + return CellPair( + data.Part.grid_x*MAX_NUMBER_OF_CELLS+data.Part.cell_x, + data.Part.grid_y*MAX_NUMBER_OF_CELLS+data.Part.cell_y); + } + + Cell& operator=(const Cell &cell) + { + this->data.All = cell.data.All; + return *this; + } + + bool operator == (const Cell &cell) const { return (data.All == cell.data.All); } + bool operator != (const Cell &cell) const { return !operator == (cell); } + union + { + struct + { + unsigned grid_x : 6; + unsigned grid_y : 6; + unsigned cell_x : 6; + unsigned cell_y : 6; + unsigned nocreate : 1; + unsigned reserved : 7; + } Part; + uint32 All; + } data; + + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &) const; + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, const WorldObject&, float) const; + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, float, float, float) const; + + static CellArea CalculateCellArea(const WorldObject &obj, float radius); + static CellArea CalculateCellArea(float x, float y, float radius); + +private: + template void VisitCircle(TypeContainerVisitor &, Map &, const CellPair&, const CellPair&) const; +}; + +#endif + diff --git a/src/server/game/Grids/CellImpl.h b/src/server/game/Grids/CellImpl.h new file mode 100644 index 00000000000..d906e81a5c9 --- /dev/null +++ b/src/server/game/Grids/CellImpl.h @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CELLIMPL_H +#define TRINITY_CELLIMPL_H + +#include + +#include "Cell.h" +#include "Map.h" +#include "Object.h" + +inline Cell::Cell(CellPair const& p) +{ + data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS; + data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; + data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; + data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; + data.Part.nocreate = 0; + data.Part.reserved = 0; +} + +template +inline void +Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m) const +{ + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + return; + + uint16 district = (District)this->data.Part.reserved; + if (district == CENTER_DISTRICT) + { + m.Visit(*this, visitor); + return; + } + + // set up the cell range based on the district + // the overloaded operators handle range checking + CellPair begin_cell = standing_cell; + CellPair end_cell = standing_cell; + + switch(district) + { + case ALL_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right + break; + } + case UPPER_LEFT_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + break; + } + case UPPER_RIGHT_DISTRICT: + { + begin_cell -= 1; // up + end_cell >> 1; // right + break; + } + case LOWER_LEFT_DISTRICT: + { + begin_cell << 1; // left + end_cell += 1; // down + break; + } + case LOWER_RIGHT_DISTRICT: + { + end_cell >> 1; end_cell += 1; // lower right + break; + } + case LEFT_DISTRICT: + { + begin_cell -= 1; // up + end_cell >> 1; end_cell += 1; // lower right + break; + } + case RIGHT_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell += 1; // down + break; + } + case UPPER_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; // right + break; + } + case LOWER_DISTRICT: + { + begin_cell << 1; // left + end_cell >> 1; end_cell += 1; // lower right + break; + } + default: + { + assert(false); + break; + } + } + + // loop the cell range + for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++) + { + CellPair cell_pair(x,y); + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } +} + +inline int CellHelper(const float radius) +{ + if (radius < 1.0f) + return 0; + + return (int)ceilf(radius/SIZE_OF_GRID_CELL); +} + +inline CellArea Cell::CalculateCellArea(const WorldObject &obj, float radius) +{ + return Cell::CalculateCellArea(obj.GetPositionX(), obj.GetPositionY(), radius); +} + +inline CellArea Cell::CalculateCellArea(float x, float y, float radius) +{ + if (radius <= 0.0f) + return CellArea(); + + //lets calculate object coord offsets from cell borders. + //TODO: add more correct/generic method for this task + const float x_offset = (x - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + const float y_offset = (y - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + + const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f); + const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f); + + const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + + const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET; + //lets calculate upper/lower/right/left corners for cell search + int right = CellHelper(tmp_diff + x_off); + int left = CellHelper(tmp_diff - x_off); + int upper = CellHelper(tmp_diff + y_off); + int lower = CellHelper(tmp_diff - y_off); + + return CellArea(right, left, upper, lower); +} + +template +inline void +Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m, float radius, float x_off, float y_off) const +{ + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + return; + + //no jokes here... Actually placing ASSERT() here was good idea, but + //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?) + //maybe it is better to just return when radius <= 0.0f? + if (radius <= 0.0f) + { + m.Visit(*this, visitor); + return; + } + //lets limit the upper value for search radius + if (radius > 333.0f) + radius = 333.0f; + + //lets calculate object coord offsets from cell borders. + CellArea area = Cell::CalculateCellArea(x_off, y_off, radius); + //if radius fits inside standing cell + if (!area) + { + m.Visit(*this, visitor); + return; + } + + CellPair begin_cell = standing_cell; + CellPair end_cell = standing_cell; + + area.ResizeBorders(begin_cell, end_cell); + //visit all cells, found in CalculateCellArea() + //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle + //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values + //there are nothing to optimize because SIZE_OF_GRID_CELL is too big... + if (((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4)) + { + VisitCircle(visitor, m, begin_cell, end_cell); + return; + } + + //ALWAYS visit standing cell first!!! Since we deal with small radiuses + //it is very essential to call visitor for standing cell firstly... + m.Visit(*this, visitor); + + // loop the cell range + for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + CellPair cell_pair(x,y); + //lets skip standing cell since we already visited it + if (cell_pair != standing_cell) + { + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } + } +} + +template +inline void +Cell::Visit(const CellPair& l, TypeContainerVisitor &visitor, Map &m, const WorldObject &obj, float radius) const +{ + //we should increase search radius by object's radius, otherwise + //we could have problems with huge creatures, which won't attack nearest players etc + Visit(l, visitor, m, radius + obj.GetObjectSize(), obj.GetPositionX(), obj.GetPositionY()); +} + +template +inline void +Cell::VisitCircle(TypeContainerVisitor &visitor, Map &m, const CellPair& begin_cell, const CellPair& end_cell) const +{ + //here is an algorithm for 'filling' circum-squared octagon + uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f); + //lets calculate x_start/x_end coords for central strip... + const uint32 x_start = begin_cell.x_coord + x_shift; + const uint32 x_end = end_cell.x_coord - x_shift; + + //visit central strip with constant width... + for (uint32 x = x_start; x <= x_end; ++x) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + CellPair cell_pair(x,y); + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } + + //if x_shift == 0 then we have too small cell area, which were already + //visited at previous step, so just return from procedure... + if (x_shift == 0) + return; + + uint32 y_start = end_cell.y_coord; + uint32 y_end = begin_cell.y_coord; + //now we are visiting borders of an octagon... + for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step) + { + //each step reduces strip height by 2 cells... + y_end += 1; + y_start -= 1; + for (uint32 y = y_start; y >= y_end; --y) + { + //we visit cells symmetrically from both sides, heading from center to sides and from up to bottom + //e.g. filling 2 trapezoids after filling central cell strip... + CellPair cell_pair_left(x_start - step, y); + Cell r_zone_left(cell_pair_left); + r_zone_left.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone_left, visitor); + + //right trapezoid cell visit + CellPair cell_pair_right(x_end + step, y); + Cell r_zone_right(cell_pair_right); + r_zone_right.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone_right, visitor); + } + } +} +#endif + diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h new file mode 100644 index 00000000000..5269d0a094d --- /dev/null +++ b/src/server/game/Grids/GridDefines.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDDEFINES_H +#define TRINITY_GRIDDEFINES_H + +#include "Common.h" +#include "GameSystem/NGrid.h" +#include + +// Forward class definitions +class Corpse; +class Creature; +class DynamicObject; +class GameObject; +class Pet; +class Player; + +#define MAX_NUMBER_OF_CELLS 8 + +#define MAX_NUMBER_OF_GRIDS 64 + +#define SIZE_OF_GRIDS 533.33333f +#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2) + +#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) + +#define MIN_GRID_DELAY (MINUTE*IN_MILISECONDS) +#define MIN_MAP_UPDATE_DELAY 50 + +#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) + +#define CENTER_GRID_CELL_ID (MAX_NUMBER_OF_CELLS*MAX_NUMBER_OF_GRIDS/2) +#define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2) + +#define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) + +#define MAP_RESOLUTION 128 + +#define MAP_SIZE (SIZE_OF_GRIDS*MAX_NUMBER_OF_GRIDS) +#define MAP_HALFSIZE (MAP_SIZE/2) + +// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case) +typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes; +typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes; + +typedef GridRefManager CorpseMapType; +typedef GridRefManager CreatureMapType; +typedef GridRefManager DynamicObjectMapType; +typedef GridRefManager GameObjectMapType; +typedef GridRefManager PlayerMapType; + +typedef Grid GridType; +typedef NGrid NGridType; + +typedef TypeMapContainer GridTypeMapContainer; +typedef TypeMapContainer WorldTypeMapContainer; + +template +struct CoordPair +{ + CoordPair(uint32 x=0, uint32 y=0) : x_coord(x), y_coord(y) {} + CoordPair(const CoordPair &obj) : x_coord(obj.x_coord), y_coord(obj.y_coord) {} + bool operator == (const CoordPair &obj) const { return (obj.x_coord == x_coord && obj.y_coord == y_coord); } + bool operator != (const CoordPair &obj) const { return !operator == (obj); } + CoordPair& operator=(const CoordPair &obj) + { + x_coord = obj.x_coord; + y_coord = obj.y_coord; + return *this; + } + + void operator<<(const uint32 val) + { + if (x_coord > val) + x_coord -= val; + else + x_coord = 0; + } + + void operator>>(const uint32 val) + { + if (x_coord+val < LIMIT) + x_coord += val; + else + x_coord = LIMIT - 1; + } + + void operator-=(const uint32 val) + { + if (y_coord > val) + y_coord -= val; + else + y_coord = 0; + } + + void operator+=(const uint32 val) + { + if (y_coord+val < LIMIT) + y_coord += val; + else + y_coord = LIMIT - 1; + } + + uint32 x_coord; + uint32 y_coord; +}; + +typedef CoordPair GridPair; +typedef CoordPair CellPair; + +namespace Trinity +{ + template + inline RET_TYPE Compute(float x, float y, float center_offset, float size) + { + // calculate and store temporary values in double format for having same result as same mySQL calculations + double x_offset = (double(x) - center_offset)/size; + double y_offset = (double(y) - center_offset)/size; + + int x_val = int(x_offset+CENTER_VAL + 0.5); + int y_val = int(y_offset+CENTER_VAL + 0.5); + return RET_TYPE(x_val, y_val); + } + + inline GridPair ComputeGridPair(float x, float y) + { + return Compute(x, y, CENTER_GRID_OFFSET, SIZE_OF_GRIDS); + } + + inline CellPair ComputeCellPair(float x, float y) + { + return Compute(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL); + } + + inline CellPair ComputeCellPair(float x, float y, float &x_off, float &y_off) + { + double x_offset = (double(x) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + double y_offset = (double(y) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + + int x_val = int(x_offset + CENTER_GRID_CELL_ID + 0.5); + int y_val = int(y_offset + CENTER_GRID_CELL_ID + 0.5); + x_off = (float(x_offset) - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + y_off = (float(y_offset) - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + return CellPair(x_val, y_val); + } + + inline void NormalizeMapCoord(float &c) + { + if (c > MAP_HALFSIZE - 0.5) + c = MAP_HALFSIZE - 0.5; + else if (c < -(MAP_HALFSIZE - 0.5)) + c = -(MAP_HALFSIZE - 0.5); + } + + inline bool IsValidMapCoord(float c) + { + return finite(c) && (std::fabs(c) <= MAP_HALFSIZE - 0.5); + } + + inline bool IsValidMapCoord(float x, float y) + { + return IsValidMapCoord(x) && IsValidMapCoord(y); + } + + inline bool IsValidMapCoord(float x, float y, float z) + { + return IsValidMapCoord(x,y) && finite(z); + } + + inline bool IsValidMapCoord(float x, float y, float z, float o) + { + return IsValidMapCoord(x,y,z) && finite(o); + } +} +#endif diff --git a/src/server/game/Grids/GridNotifiers.cpp b/src/server/game/Grids/GridNotifiers.cpp new file mode 100644 index 00000000000..b10dfa8791e --- /dev/null +++ b/src/server/game/Grids/GridNotifiers.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "UpdateData.h" +#include "Item.h" +#include "Map.h" +#include "Transports.h" +#include "ObjectAccessor.h" +#include "CellImpl.h" + +using namespace Trinity; + +void +VisibleNotifier::SendToSelf() +{ + // at this moment i_clientGUIDs have guids that not iterate at grid level checks + // but exist one case when this possible and object not out of range: transports + if (Transport* transport = i_player.GetTransport()) + for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr != transport->GetPassengers().end();++itr) + { + if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end()) + { + vis_guids.erase((*itr)->GetGUID()); + + i_player.UpdateVisibilityOf((*itr), i_data, i_visibleNow); + + if (!(*itr)->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + (*itr)->UpdateVisibilityOf(&i_player); + } + } + + for (Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end(); ++it) + { + i_player.m_clientGUIDs.erase(*it); + i_data.AddOutOfRangeGUID(*it); + + if (IS_PLAYER_GUID(*it)) + { + Player* plr = ObjectAccessor::FindPlayer(*it); + if (plr && plr->IsInWorld() && !plr->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + plr->UpdateVisibilityOf(&i_player); + } + } + + if (!i_data.HasData()) + return; + + WorldPacket packet; + i_data.BuildPacket(&packet); + i_player.GetSession()->SendPacket(&packet); + + for (std::set::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it) + i_player.SendInitialVisiblePackets(*it); +} + +void +VisibleChangesNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if (iter->getSource() == &i_object) + continue; + + iter->getSource()->UpdateVisibilityOf(&i_object); + + if (!iter->getSource()->GetSharedVisionList().empty()) + for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + (*i)->UpdateVisibilityOf(&i_object); + } +} + +void +VisibleChangesNotifier::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if (!iter->getSource()->GetSharedVisionList().empty()) + for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + (*i)->UpdateVisibilityOf(&i_object); +} + +void +VisibleChangesNotifier::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) + if (Player* caster = (Player*)iter->getSource()->GetCaster()) + if (caster->m_seer == iter->getSource()) + caster->UpdateVisibilityOf(&i_object); +} + +inline void CreatureUnitRelocationWorker(Creature* c, Unit* u) +{ + if (!u->isAlive() || !c->isAlive() || c == u || u->isInFlight()) + return; + + if (c->HasReactState(REACT_AGGRESSIVE) && !c->hasUnitState(UNIT_STAT_SIGHTLESS)) + if (c->_IsWithinDist(u, c->m_SightDistance, true) && c->IsAIEnabled) + c->AI()->MoveInLineOfSight_Safe(u); +} + +void PlayerRelocationNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Player* plr = iter->getSource(); + + vis_guids.erase(plr->GetGUID()); + + i_player.UpdateVisibilityOf(plr,i_data,i_visibleNow); + + if (plr->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + plr->UpdateVisibilityOf(&i_player); + } +} + +void PlayerRelocationNotifier::Visit(CreatureMapType &m) +{ + bool relocated_for_ai = (&i_player == i_player.m_seer); + + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Creature * c = iter->getSource(); + + vis_guids.erase(c->GetGUID()); + + i_player.UpdateVisibilityOf(c,i_data,i_visibleNow); + + if (relocated_for_ai && !c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + CreatureUnitRelocationWorker(c, &i_player); + } +} + +void CreatureRelocationNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Player * pl = iter->getSource(); + + if (!pl->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + pl->UpdateVisibilityOf(&i_creature); + + CreatureUnitRelocationWorker(&i_creature, pl); + } +} + +void CreatureRelocationNotifier::Visit(CreatureMapType &m) +{ + if (!i_creature.isAlive()) + return; + + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Creature* c = iter->getSource(); + CreatureUnitRelocationWorker(&i_creature, c); + + if (!c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + CreatureUnitRelocationWorker(c, &i_creature); + } +} + +void DelayedUnitRelocation::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Creature * unit = iter->getSource(); + if (!unit->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + CreatureRelocationNotifier relocate(*unit); + + TypeContainerVisitor c2world_relocation(relocate); + TypeContainerVisitor c2grid_relocation(relocate); + + cell.Visit(p, c2world_relocation, i_map, *unit, i_radius); + cell.Visit(p, c2grid_relocation, i_map, *unit, i_radius); + } +} + +void DelayedUnitRelocation::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Player * player = iter->getSource(); + WorldObject const *viewPoint = player->m_seer; + + if (!viewPoint->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + if (player != viewPoint && !viewPoint->IsPositionValid()) + continue; + + CellPair pair2(Trinity::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY())); + Cell cell2(pair2); + //cell.SetNoCreate(); need load cells around viewPoint or player, that's why its commented + + PlayerRelocationNotifier relocate(*player); + TypeContainerVisitor c2world_relocation(relocate); + TypeContainerVisitor c2grid_relocation(relocate); + + cell2.Visit(pair2, c2world_relocation, i_map, *viewPoint, i_radius); + cell2.Visit(pair2, c2grid_relocation, i_map, *viewPoint, i_radius); + + relocate.SendToSelf(); + } +} + +void AIRelocationNotifier::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Creature *c = iter->getSource(); + CreatureUnitRelocationWorker(c, &i_unit); + if (isCreature) + CreatureUnitRelocationWorker((Creature*)&i_unit, c); + } +} + +void +MessageDistDeliverer::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Player *target = iter->getSource(); + if (!target->InSamePhase(i_phaseMask)) + continue; + + if (target->GetExactDistSq(i_source) > i_distSq) + continue; + + // Send packet to all who are sharing the player's vision + if (!target->GetSharedVisionList().empty()) + { + SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); + for (; i != target->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == target) + SendPacket(*i); + } + + if (target->m_seer == target || target->GetVehicle()) + SendPacket(target); + } +} + +void +MessageDistDeliverer::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) + continue; + + // Send packet to all who are sharing the creature's vision + if (!iter->getSource()->GetSharedVisionList().empty()) + { + SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + for (; i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + SendPacket(*i); + } + } +} + +void +MessageDistDeliverer::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) + continue; + + if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) + { + // Send packet back to the caster if the caster has vision of dynamic object + Player* caster = (Player*)iter->getSource()->GetCaster(); + if (caster && caster->m_seer == iter->getSource()) + SendPacket(caster); + } + } +} + +/* +void +MessageDistDeliverer::VisitObject(Player* plr) +{ + if (!i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam())) + { + SendPacket(plr); + } +} +*/ + +template void +ObjectUpdater::Visit(GridRefManager &m) +{ + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (iter->getSource()->IsInWorld()) + iter->getSource()->Update(i_timeDiff); + } +} + +bool CannibalizeObjectCheck::operator()(Corpse* u) +{ + // ignore bones + if (u->GetType() == CORPSE_BONES) + return false; + + Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); + + if (!owner || i_funit->IsFriendlyTo(owner)) + return false; + + if (i_funit->IsWithinDistInMap(u, i_range)) + return true; + + return false; +} + +template void ObjectUpdater::Visit(GameObjectMapType &); +template void ObjectUpdater::Visit(DynamicObjectMapType &); diff --git a/src/server/game/Grids/GridNotifiers.h b/src/server/game/Grids/GridNotifiers.h new file mode 100644 index 00000000000..b0abf0aae79 --- /dev/null +++ b/src/server/game/Grids/GridNotifiers.h @@ -0,0 +1,1232 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDNOTIFIERS_H +#define TRINITY_GRIDNOTIFIERS_H + +#include "ObjectGridLoader.h" +#include "UpdateData.h" +#include + +#include "Corpse.h" +#include "Object.h" +#include "DynamicObject.h" +#include "GameObject.h" +#include "Player.h" +#include "Unit.h" +#include "CreatureAI.h" + +class Player; +//class Map; + +namespace Trinity +{ + struct VisibleNotifier + { + Player &i_player; + UpdateData i_data; + std::set i_visibleNow; + Player::ClientGUIDs vis_guids; + + VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) {} + template void Visit(GridRefManager &m); + void SendToSelf(void); + }; + + struct VisibleChangesNotifier + { + WorldObject &i_object; + + explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {} + template void Visit(GridRefManager &) {} + void Visit(PlayerMapType &); + void Visit(CreatureMapType &); + void Visit(DynamicObjectMapType &); + }; + + struct PlayerRelocationNotifier : public VisibleNotifier + { + PlayerRelocationNotifier(Player &pl) : VisibleNotifier(pl) {} + + template void Visit(GridRefManager &m) { VisibleNotifier::Visit(m); } + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct CreatureRelocationNotifier + { + Creature &i_creature; + CreatureRelocationNotifier(Creature &c) : i_creature(c) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct DelayedUnitRelocation + { + Map &i_map; + Cell &cell; + CellPair &p; + const float i_radius; + DelayedUnitRelocation(Cell &c, CellPair &pair, Map &map, float radius) : + cell(c), p(pair), i_map(map), i_radius(radius) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct AIRelocationNotifier + { + Unit &i_unit; + bool isCreature; + explicit AIRelocationNotifier(Unit &unit) : i_unit(unit), isCreature(unit.GetTypeId() == TYPEID_UNIT) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + }; + + struct GridUpdater + { + GridType &i_grid; + uint32 i_timeDiff; + GridUpdater(GridType &grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) {} + + template void updateObjects(GridRefManager &m) + { + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + iter->getSource()->Update(i_timeDiff); + } + + void Visit(PlayerMapType &m) { updateObjects(m); } + void Visit(CreatureMapType &m){ updateObjects(m); } + void Visit(GameObjectMapType &m) { updateObjects(m); } + void Visit(DynamicObjectMapType &m) { updateObjects(m); } + void Visit(CorpseMapType &m) { updateObjects(m); } + }; + + struct MessageDistDeliverer + { + WorldObject *i_source; + WorldPacket *i_message; + uint32 i_phaseMask; + float i_distSq; + uint32 team; + Player const* skipped_receiver; + MessageDistDeliverer(WorldObject *src, WorldPacket *msg, float dist, bool own_team_only = false, Player const* skipped = NULL) + : i_source(src), i_message(msg), i_distSq(dist * dist), i_phaseMask(src->GetPhaseMask()) + , team((own_team_only && src->GetTypeId() == TYPEID_PLAYER) ? ((Player*)src)->GetTeam() : 0) + , skipped_receiver(skipped) + { + } + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(DynamicObjectMapType &m); + template void Visit(GridRefManager &) {} + + void SendPacket(Player* plr) + { + // never send packet to self + if (plr == i_source || (team && plr->GetTeam() != team) || skipped_receiver == plr) + return; + + plr->GetSession()->SendPacket(i_message); + } + }; + + struct ObjectUpdater + { + uint32 i_timeDiff; + explicit ObjectUpdater(const uint32 &diff) : i_timeDiff(diff) {} + template void Visit(GridRefManager &m); + void Visit(PlayerMapType &) {} + void Visit(CorpseMapType &) {} + void Visit(CreatureMapType &); + }; + + // SEARCHERS & LIST SEARCHERS & WORKERS + + // WorldObject searchers & workers + + template + struct WorldObjectSearcher + { + uint32 i_phaseMask; + WorldObject* &i_object; + Check &i_check; + + WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(DynamicObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct WorldObjectListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + WorldObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(GameObjectMapType &m); + void Visit(DynamicObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct WorldObjectWorker + { + uint32 i_phaseMask; + Do const& i_do; + + WorldObjectWorker(WorldObject const* searcher, Do const& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(GameObjectMapType &m) + { + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + void Visit(CreatureMapType &m) + { + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(CorpseMapType &m) + { + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(DynamicObjectMapType &m) + { + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // Gameobject searchers + + template + struct GameObjectSearcher + { + uint32 i_phaseMask; + GameObject* &i_object; + Check &i_check; + + GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check GO if any (Check can change requirements at each call) + template + struct GameObjectLastSearcher + { + uint32 i_phaseMask; + GameObject* &i_object; + Check& i_check; + + GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct GameObjectListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + GameObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Unit searchers + + // First accepted by Check Unit if any + template + struct UnitSearcher + { + uint32 i_phaseMask; + Unit* &i_object; + Check & i_check; + + UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check Unit if any (Check can change requirements at each call) + template + struct UnitLastSearcher + { + uint32 i_phaseMask; + Unit* &i_object; + Check & i_check; + + UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // All accepted by Check units if any + template + struct UnitListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + UnitListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Creature searchers + + template + struct CreatureSearcher + { + uint32 i_phaseMask; + Creature* &i_object; + Check & i_check; + + CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check Creature if any (Check can change requirements at each call) + template + struct CreatureLastSearcher + { + uint32 i_phaseMask; + Creature* &i_object; + Check & i_check; + + CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct CreatureListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + CreatureListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct CreatureWorker + { + uint32 i_phaseMask; + Do& i_do; + + CreatureWorker(WorldObject const* searcher, Do& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(CreatureMapType &m) + { + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // Player searchers + + template + struct PlayerSearcher + { + uint32 i_phaseMask; + Player* &i_object; + Check & i_check; + + PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + PlayerListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerWorker + { + uint32 i_phaseMask; + Do& i_do; + + PlayerWorker(WorldObject const* searcher, Do& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerDistWorker + { + WorldObject const* i_searcher; + float i_dist; + Do& i_do; + + PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do) + : i_searcher(searcher), i_dist(_dist), i_do(_do) {} + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // CHECKS && DO classes + + // WorldObject check classes + class RaiseDeadObjectCheck + { + public: + RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Creature* u) + { + if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || + u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() || + (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 || + (u->GetDisplayId() != u->GetNativeDisplayId())) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + class ExplodeCorpseObjectCheck + { + public: + ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Player* u) + { + if (u->getDeathState() != CORPSE || u->isInFlight() || + u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + bool operator()(Creature* u) + { + if (u->getDeathState() != CORPSE || u->isInFlight() || u->isDeadByDefault() || + (u->GetDisplayId() != u->GetNativeDisplayId()) || + (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + class CannibalizeObjectCheck + { + public: + CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Player* u) + { + if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + bool operator()(Corpse* u); + bool operator()(Creature* u) + { + if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || + (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + // WorldObject do classes + + class RespawnDo + { + public: + RespawnDo() {} + void operator()(Creature* u) const { u->Respawn(); } + void operator()(GameObject* u) const { u->Respawn(); } + void operator()(WorldObject*) const {} + void operator()(Corpse*) const {} + }; + + // GameObject checks + + class GameObjectFocusCheck + { + public: + GameObjectFocusCheck(Unit const* unit,uint32 focusId) : i_unit(unit), i_focusId(focusId) {} + bool operator()(GameObject* go) const + { + if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS) + return false; + + if (go->GetGOInfo()->spellFocus.focusId != i_focusId) + return false; + + float dist = (go->GetGOInfo()->spellFocus.dist)/2; + + return go->IsWithinDistInMap(i_unit, dist); + } + private: + Unit const* i_unit; + uint32 i_focusId; + }; + + // Find the nearest Fishing hole and return true only if source object is in range of hole + class NearestGameObjectFishingHole + { + public: + NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(GameObject* go) + { + if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, go->GetGOInfo()->fishinghole.radius)) + { + i_range = i_obj.GetDistance(go); + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + float i_range; + + // prevent clone + NearestGameObjectFishingHole(NearestGameObjectFishingHole const&); + }; + + class NearestGameObjectCheck + { + public: + NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) {} + bool operator()(GameObject* go) + { + if (i_obj.IsWithinDistInMap(go, i_range)) + { + i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + float i_range; + + // prevent clone this object + NearestGameObjectCheck(NearestGameObjectCheck const&); + }; + + // Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO) + class NearestGameObjectEntryInObjectRangeCheck + { + public: + NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj,uint32 entry, float range) : i_obj(obj), i_entry(entry), i_range(range) {} + bool operator()(GameObject* go) + { + if (go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range)) + { + i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + uint32 i_entry; + float i_range; + + // prevent clone this object + NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&); + }; + + class GameObjectWithDbGUIDCheck + { + public: + GameObjectWithDbGUIDCheck(WorldObject const& obj,uint32 db_guid) : i_obj(obj), i_db_guid(db_guid) {} + bool operator()(GameObject const* go) const + { + return go->GetDBTableGUIDLow() == i_db_guid; + } + private: + WorldObject const& i_obj; + uint32 i_db_guid; + }; + + // Unit checks + + class MostHPMissingInRange + { + public: + MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp) + { + i_hp = u->GetMaxHealth() - u->GetHealth(); + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + uint32 i_hp; + }; + + class FriendlyCCedInRange + { + public: + FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && + (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED))) + { + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + }; + + class FriendlyMissingBuffInRange + { + public: + FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && + !(u->HasAura(i_spell))) + { + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + uint32 i_spell; + }; + + class AnyUnfriendlyUnitInObjectRangeCheck + { + public: + AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u)) + return true; + else + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnfriendlyNoTotemUnitInObjectRangeCheck + { + public: + AnyUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (!u->isAlive()) + return false; + + if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) + return false; + + return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u); + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnfriendlyVisibleUnitInObjectRangeCheck + { + public: + AnyUnfriendlyVisibleUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) + : i_obj(obj), i_funit(funit), i_range(range) {} + + bool operator()(Unit* u) + { + return u->isAlive() + && i_obj->IsWithinDistInMap(u, i_range) + && !i_funit->IsFriendlyTo(u) + && u->isVisibleForOrDetect(i_funit, false); + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class CreatureWithDbGUIDCheck + { + public: + CreatureWithDbGUIDCheck(WorldObject const* obj, uint32 lowguid) : i_obj(obj), i_lowguid(lowguid) {} + bool operator()(Creature* u) + { + return u->GetDBTableGUIDLow() == i_lowguid; + } + private: + WorldObject const* i_obj; + uint32 i_lowguid; + }; + + class AnyFriendlyUnitInObjectRangeCheck + { + public: + AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) + return true; + else + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnitInObjectRangeCheck + { + public: + AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + WorldObject const* i_obj; + float i_range; + }; + + // Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit) + class NearestAttackableUnitInObjectRangeCheck + { + public: + NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) && + !i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,false)) + { + i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + + // prevent clone this object + NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); + }; + + class AnyAoETargetUnitInObjectRangeCheck + { + public: + AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) + : i_obj(obj), i_funit(funit), i_range(range) + { + Unit const* check = i_funit; + Unit const* owner = i_funit->GetOwner(); + if (owner) + check = owner; + i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER); + } + bool operator()(Unit* u) + { + // Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems + if (!u->isTargetableForAttack()) + return false; + if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) + return false; + + if ((i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u))&& i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + bool i_targetForPlayer; + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + // do attack at call of help to friendly crearture + class CallOfHelpCreatureInRangeDo + { + public: + CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range) + : i_funit(funit), i_enemy(enemy), i_range(range) + {} + void operator()(Creature* u) + { + if (u == i_funit) + return; + + if (!u->CanAssistTo(i_funit, i_enemy, false)) + return; + + // too far + if (!u->IsWithinDistInMap(i_enemy, i_range)) + return; + + // only if see assisted creature's enemy + if (!u->IsWithinLOSInMap(i_enemy)) + return; + + if (u->AI()) + u->AI()->AttackStart(i_enemy); + } + private: + Unit* const i_funit; + Unit* const i_enemy; + float i_range; + }; + + struct AnyDeadUnitCheck + { + bool operator()(Unit* u) { return !u->isAlive(); } + }; + + struct AnyStealthedCheck + { + bool operator()(Unit* u) { return u->GetVisibility() == VISIBILITY_GROUP_STEALTH; } + }; + + // Creature checks + + class NearestHostileUnitCheck + { + public: + explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0) : me(creature) + { + m_range = (dist == 0 ? 9999 : dist); + } + bool operator()(Unit* u) + { + if (!me->IsWithinDistInMap(u, m_range)) + return false; + + if (!me->canAttack(u)) + return false; + + m_range = me->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + + private: + Creature const *me; + float m_range; + NearestHostileUnitCheck(NearestHostileUnitCheck const&); + }; + + class NearestHostileUnitInAttackDistanceCheck + { + public: + explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0) : me(creature) + { + m_range = (dist == 0 ? 9999 : dist); + m_force = (dist == 0 ? false : true); + } + bool operator()(Unit* u) + { + if (!me->IsWithinDistInMap(u, m_range)) + return false; + + if (m_force) + { + if (!me->canAttack(u)) + return false; + } + else + { + if (!me->canStartAttack(u, false)) + return false; + } + + m_range = me->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + float GetLastRange() const { return m_range; } + private: + Creature const *me; + float m_range; + bool m_force; + NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&); + }; + + class AnyAssistCreatureInRangeCheck + { + public: + AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range) + : i_funit(funit), i_enemy(enemy), i_range(range) + { + } + bool operator()(Creature* u) + { + if (u == i_funit) + return false; + + if (!u->CanAssistTo(i_funit, i_enemy)) + return false; + + // too far + if (!i_funit->IsWithinDistInMap(u, i_range)) + return false; + + // only if see assisted creature + if (!i_funit->IsWithinLOSInMap(u)) + return false; + + return true; + } + private: + Unit* const i_funit; + Unit* const i_enemy; + float i_range; + }; + + class NearestAssistCreatureInCreatureRangeCheck + { + public: + NearestAssistCreatureInCreatureRangeCheck(Creature* obj, Unit* enemy, float range) + : i_obj(obj), i_enemy(enemy), i_range(range) {} + + bool operator()(Creature* u) + { + if (u == i_obj) + return false; + if (!u->CanAssistTo(i_obj,i_enemy)) + return false; + + if (!i_obj->IsWithinDistInMap(u, i_range)) + return false; + + if (!i_obj->IsWithinLOSInMap(u)) + return false; + + i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + float GetLastRange() const { return i_range; } + private: + Creature* const i_obj; + Unit* const i_enemy; + float i_range; + + // prevent clone this object + NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&); + }; + + // Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature) + class NearestCreatureEntryWithLiveStateInObjectRangeCheck + { + public: + NearestCreatureEntryWithLiveStateInObjectRangeCheck(WorldObject const& obj, uint32 entry, bool alive, float range) + : i_obj(obj), i_entry(entry), i_alive(alive), i_range(range) {} + + bool operator()(Creature* u) + { + if (u->GetEntry() == i_entry && u->isAlive() == i_alive && i_obj.IsWithinDistInMap(u, i_range)) + { + i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + uint32 i_entry; + bool i_alive; + float i_range; + + // prevent clone this object + NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&); + }; + + class AnyPlayerInObjectRangeCheck + { + public: + AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Player* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + WorldObject const* i_obj; + float i_range; + }; + + class AllFriendlyCreaturesInGrid + { + public: + AllFriendlyCreaturesInGrid(Unit const* obj) : pUnit(obj) {} + bool operator() (Unit* u) + { + if (u->isAlive() && u->GetVisibility() == VISIBILITY_ON && u->IsFriendlyTo(pUnit)) + return true; + + return false; + } + private: + Unit const* pUnit; + }; + + class AllGameObjectsWithEntryInRange + { + public: + AllGameObjectsWithEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} + bool operator() (GameObject* pGo) + { + if (pGo->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pGo,m_fRange,false)) + return true; + + return false; + } + private: + const WorldObject* m_pObject; + uint32 m_uiEntry; + float m_fRange; + }; + + class AllCreaturesOfEntryInRange + { + public: + AllCreaturesOfEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} + bool operator() (Unit* pUnit) + { + if (pUnit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pUnit,m_fRange,false)) + return true; + + return false; + } + + private: + const WorldObject* m_pObject; + uint32 m_uiEntry; + float m_fRange; + }; + + class PlayerAtMinimumRangeAway + { + public: + PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : pUnit(unit), fRange(fMinRange) {} + bool operator() (Player* pPlayer) + { + //No threat list check, must be done explicit if expected to be in combat with creature + if (!pPlayer->isGameMaster() && pPlayer->isAlive() && !pUnit->IsWithinDist(pPlayer,fRange,false)) + return true; + + return false; + } + + private: + Unit const* pUnit; + float fRange; + }; + + class GameObjectInRangeCheck + { + public: + GameObjectInRangeCheck(float _x, float _y, float _z, float _range) : x(_x), y(_y), z(_z), range(_range) {} + bool operator() (GameObject* go) + { + return go->IsInRange(x, y, z, range); + } + private: + float x, y, z, range; + }; + + // Player checks and do + + // Prepare using Builder localized packets with caching and send to player + template + class LocalizedPacketDo + { + public: + explicit LocalizedPacketDo(Builder& builder) : i_builder(builder) {} + + ~LocalizedPacketDo() + { + for (size_t i = 0; i < i_data_cache.size(); ++i) + delete i_data_cache[i]; + } + void operator()(Player* p); + + private: + Builder& i_builder; + std::vector i_data_cache; // 0 = default, i => i-1 locale index + }; + + // Prepare using Builder localized packets with caching and send to player + template + class LocalizedPacketListDo + { + public: + typedef std::vector WorldPacketList; + explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {} + + ~LocalizedPacketListDo() + { + for (size_t i = 0; i < i_data_cache.size(); ++i) + for (size_t j = 0; j < i_data_cache[i].size(); ++j) + delete i_data_cache[i][j]; + } + void operator()(Player* p); + + private: + Builder& i_builder; + std::vector i_data_cache; + // 0 = default, i => i-1 locale index + }; +} +#endif diff --git a/src/server/game/Grids/GridNotifiersImpl.h b/src/server/game/Grids/GridNotifiersImpl.h new file mode 100644 index 00000000000..26a9c0bd328 --- /dev/null +++ b/src/server/game/Grids/GridNotifiersImpl.h @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDNOTIFIERSIMPL_H +#define TRINITY_GRIDNOTIFIERSIMPL_H + +#include "GridNotifiers.h" +#include "WorldPacket.h" +#include "Corpse.h" +#include "Player.h" +#include "UpdateData.h" +#include "CreatureAI.h" +#include "SpellAuras.h" + + +template +inline void +Trinity::VisibleNotifier::Visit(GridRefManager &m) +{ + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + vis_guids.erase(iter->getSource()->GetGUID()); + i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow); + } +} + +inline void +Trinity::ObjectUpdater::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + if (iter->getSource()->IsInWorld() && !iter->getSource()->isSpiritService()) + iter->getSource()->Update(i_timeDiff); +} + +// SEARCHERS & LIST SEARCHERS & WORKERS + +// WorldObject searchers & workers + +template +void Trinity::WorldObjectSearcher::Visit(GameObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(CorpseMapType &m) +{ + // already found + if (i_object) + return; + + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(DynamicObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(CorpseMapType &m) +{ + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Gameobject searchers + +template +void Trinity::GameObjectSearcher::Visit(GameObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::GameObjectLastSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::GameObjectListSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Unit searchers + +template +void Trinity::UnitSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::UnitSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::UnitLastSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::UnitLastSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::UnitListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::UnitListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Creature searchers + +template +void Trinity::CreatureSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::CreatureLastSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::CreatureListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::PlayerListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::PlayerSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::LocalizedPacketDo::operator()(Player* p) +{ + int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacket* data; + + // create if not cached yet + if (i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx]) + { + if (i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + data = new WorldPacket(SMSG_MESSAGECHAT, 200); + + i_builder(*data,loc_idx); + + i_data_cache[cache_idx] = data; + } + else + data = i_data_cache[cache_idx]; + + p->SendDirectMessage(data); +} + +template +void Trinity::LocalizedPacketListDo::operator()(Player* p) +{ + int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacketList* data_list; + + // create if not cached yet + if (i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty()) + { + if (i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + data_list = &i_data_cache[cache_idx]; + + i_builder(*data_list,loc_idx); + } + else + data_list = &i_data_cache[cache_idx]; + + for (size_t i = 0; i < data_list->size(); ++i) + p->SendDirectMessage((*data_list)[i]); +} + +#endif // TRINITY_GRIDNOTIFIERSIMPL_H diff --git a/src/server/game/Grids/GridStates.cpp b/src/server/game/Grids/GridStates.cpp new file mode 100644 index 00000000000..9d39531cfad --- /dev/null +++ b/src/server/game/Grids/GridStates.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GridStates.h" +#include "GridNotifiers.h" +#include "GameSystem/Grid.h" +#include "Log.h" + +void +InvalidState::Update(Map &, NGridType &, GridInfo &, const uint32 &/*x*/, const uint32 &/*y*/, const uint32 &) const +{ +} + +void +ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const +{ + // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle + info.UpdateTimeTracker(t_diff); + if (info.getTimeTracker().Passed()) + { + if (grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y)) + { + ObjectGridStoper stoper(grid); + stoper.StopN(); + grid.SetGridState(GRID_STATE_IDLE); + sLog.outDebug("Grid[%u,%u] on map %u moved to IDLE state", x, y, m.GetId()); + } + else + { + m.ResetGridExpiry(grid, 0.1f); + } + } +} + +void +IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &) const +{ + m.ResetGridExpiry(grid); + grid.SetGridState(GRID_STATE_REMOVAL); + sLog.outDebug("Grid[%u,%u] on map %u moved to REMOVAL state", x, y, m.GetId()); +} + +void +RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const +{ + if (!info.getUnloadLock()) + { + info.UpdateTimeTracker(t_diff); + if (info.getTimeTracker().Passed()) + { + if (!m.UnloadGrid(x, y, false)) + { + sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players or active objects nearby", x, y, m.GetId()); + m.ResetGridExpiry(grid); + } + } + } +} + diff --git a/src/server/game/Grids/GridStates.h b/src/server/game/Grids/GridStates.h new file mode 100644 index 00000000000..c2a75ec45b7 --- /dev/null +++ b/src/server/game/Grids/GridStates.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDSTATES_H +#define TRINITY_GRIDSTATES_H + +#include "Map.h" +#include "Object.h" + +class GridState +{ + public: +#ifdef TRINITY_DEBUG +#define MAGIC_TESTVAL 0xFBE823BA + GridState() { i_Magic = MAGIC_TESTVAL; } + bool checkMagic() + { + if (i_Magic != MAGIC_TESTVAL) + { + sLog.outError("!!! GridState: Magic value gone !!!"); + return false; + } + return true; + } + void setMagic() { i_Magic = MAGIC_TESTVAL; } + unsigned int i_Magic; +#endif + virtual void Update(Map &, NGridType&, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const = 0; +}; + +class InvalidState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class ActiveState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class IdleState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; + +class RemovalState : public GridState +{ + public: + + void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; +}; +#endif + diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp new file mode 100644 index 00000000000..ab69d9a966b --- /dev/null +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectGridLoader.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "Creature.h" +#include "Vehicle.h" +#include "GameObject.h" +#include "DynamicObject.h" +#include "Corpse.h" +#include "World.h" +#include "CellImpl.h" +#include "CreatureAI.h" + +class ObjectGridRespawnMover +{ + public: + ObjectGridRespawnMover() {} + + void Move(GridType &grid); + + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &m); +}; + +void +ObjectGridRespawnMover::Move(GridType &grid) +{ + TypeContainerVisitor mover(*this); + grid.Visit(mover); +} + +void +ObjectGridRespawnMover::Visit(CreatureMapType &m) +{ + // creature in unloading grid can have respawn point in another grid + // if it will be unloaded then it will not respawn in original grid until unload/load original grid + // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn. + for (CreatureMapType::iterator iter = m.begin(); iter != m.end();) + { + Creature * c = iter->getSource(); + ++iter; + + assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); + + Cell const& cur_cell = c->GetCurrentCell(); + + float resp_x, resp_y, resp_z; + c->GetRespawnCoord(resp_x, resp_y, resp_z); + CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y); + Cell resp_cell(resp_val); + + if (cur_cell.DiffGrid(resp_cell)) + { + c->GetMap()->CreatureRespawnRelocation(c); + // false result ignored: will be unload with other creatures at grid + } + } +} + +// for loading world object at grid loading (Corpses) +class ObjectWorldLoader +{ + public: + explicit ObjectWorldLoader(ObjectGridLoader& gloader) + : i_cell(gloader.i_cell), i_grid(gloader.i_grid), i_map(gloader.i_map), i_corpses (0) + {} + + void Visit(CorpseMapType &m); + + template void Visit(GridRefManager&) { } + + private: + Cell i_cell; + NGridType &i_grid; + Map* i_map; + public: + uint32 i_corpses; +}; + +template void addUnitState(T* /*obj*/, CellPair const& /*cell_pair*/) +{ +} + +template<> void addUnitState(Creature *obj, CellPair const& cell_pair) +{ + Cell cell(cell_pair); + + obj->SetCurrentCell(cell); + if (obj->isSpiritService()) + obj->setDeathState(DEAD); +} + +template +void AddObjectHelper(CellPair &cell, GridRefManager &m, uint32 &count, Map* map, T *obj) +{ + obj->GetGridRef().link(&m, obj); + addUnitState(obj,cell); + obj->AddToWorld(); + if (obj->isActiveObject()) + map->AddToActive(obj); + + ++count; +} + +template +void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager &m, uint32 &count, Map* map) +{ + for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) + { + T* obj = new T; + uint32 guid = *i_guid; + //sLog.outString("DEBUG: LoadHelper from table: %s for (guid: %u) Loading",table,guid); + if (!obj->LoadFromDB(guid, map)) + { + delete obj; + continue; + } + + AddObjectHelper(cell, m, count, map, obj); + } +} + +void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map) +{ + if (cell_corpses.empty()) + return; + + for (CellCorpseSet::const_iterator itr = cell_corpses.begin(); itr != cell_corpses.end(); ++itr) + { + if (itr->second != map->GetInstanceId()) + continue; + + uint32 player_guid = itr->first; + + Corpse *obj = ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid); + if (!obj) + continue; + + // TODO: this is a hack + // corpse's map should be reset when the map is unloaded + // but it may still exist when the grid is unloaded but map is not + // in that case map == currMap + obj->SetMap(map); + + AddObjectHelper(cell, m, count, map, obj); + } +} + +void +ObjectGridLoader::Visit(GameObjectMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); + + LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map); +} + +void +ObjectGridLoader::Visit(CreatureMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); + + LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map); +} + +void +ObjectWorldLoader::Visit(CorpseMapType &m) +{ + uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); + uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); + CellPair cell_pair(x,y); + uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; + + // corpses are always added to spawn mode 0 and they are spawned by their instance id + CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id); + LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map); +} + +void +ObjectGridLoader::Load(GridType &grid) +{ + { + TypeContainerVisitor loader(*this); + grid.Visit(loader); + } + + { + ObjectWorldLoader wloader(*this); + TypeContainerVisitor loader(wloader); + grid.Visit(loader); + i_corpses = wloader.i_corpses; + } +} + +void ObjectGridLoader::LoadN(void) +{ + i_gameObjects = 0; i_creatures = 0; i_corpses = 0; + i_cell.data.Part.cell_y = 0; + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + i_cell.data.Part.cell_x = x; + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + i_cell.data.Part.cell_y = y; + GridLoader loader; + loader.Load(i_grid(x, y), *this); + } + } + sLog.outDebug("%u GameObjects, %u Creatures, and %u Corpses/Bones loaded for grid %u on map %u", i_gameObjects, i_creatures, i_corpses,i_grid.GetGridId(), i_map->GetId()); +} + +void ObjectGridUnloader::MoveToRespawnN() +{ + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + ObjectGridRespawnMover mover; + mover.Move(i_grid(x, y)); + } + } +} + +void +ObjectGridUnloader::Unload(GridType &grid) +{ + TypeContainerVisitor unloader(*this); + grid.Visit(unloader); +} + +template +void +ObjectGridUnloader::Visit(GridRefManager &m) +{ + while (!m.isEmpty()) + { + T *obj = m.getFirst()->getSource(); + // if option set then object already saved at this moment + if (!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) + obj->SaveRespawnTime(); + ///- object will get delinked from the manager when deleted + delete obj; + } +} + +void +ObjectGridStoper::Stop(GridType &grid) +{ + TypeContainerVisitor stoper(*this); + grid.Visit(stoper); +} + +void +ObjectGridStoper::Visit(CreatureMapType &m) +{ + // stop any fights at grid de-activation and remove dynobjects created at cast by creatures + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + iter->getSource()->RemoveAllDynObjects(); + if (iter->getSource()->isInCombat()) + { + iter->getSource()->CombatStop(); + iter->getSource()->DeleteThreatList(); + iter->getSource()->AI()->EnterEvadeMode(); + } + } +} + +void +ObjectGridCleaner::Stop(GridType &grid) +{ + TypeContainerVisitor stoper(*this); + grid.Visit(stoper); +} + +void +ObjectGridCleaner::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + iter->getSource()->CleanupsBeforeDelete(); +} + +template +void +ObjectGridCleaner::Visit(GridRefManager &m) +{ + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + iter->getSource()->RemoveFromWorld(); +} + +template void ObjectGridUnloader::Visit(CreatureMapType &); +template void ObjectGridUnloader::Visit(GameObjectMapType &); +template void ObjectGridUnloader::Visit(DynamicObjectMapType &); +template void ObjectGridUnloader::Visit(CorpseMapType &); +template void ObjectGridCleaner::Visit(GameObjectMapType &); +template void ObjectGridCleaner::Visit(DynamicObjectMapType &); +template void ObjectGridCleaner::Visit(CorpseMapType &); diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/ObjectGridLoader.h new file mode 100644 index 00000000000..e890bf8d482 --- /dev/null +++ b/src/server/game/Grids/ObjectGridLoader.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_OBJECTGRIDLOADER_H +#define TRINITY_OBJECTGRIDLOADER_H + +#include "Utilities/TypeList.h" +#include "Platform/Define.h" +#include "GameSystem/GridLoader.h" +#include "GridDefines.h" +#include "Cell.h" + +class ObjectWorldLoader; + +class ObjectGridLoader +{ + friend class ObjectWorldLoader; + + public: + ObjectGridLoader(NGridType &grid, Map* map, const Cell &cell) + : i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses (0) + {} + + void Load(GridType &grid); + void Visit(GameObjectMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &) {} + + void Visit(DynamicObjectMapType&) { } + + void LoadN(void); + + private: + Cell i_cell; + NGridType &i_grid; + Map* i_map; + uint32 i_gameObjects; + uint32 i_creatures; + uint32 i_corpses; +}; + +class ObjectGridUnloader +{ + public: + ObjectGridUnloader(NGridType &grid) : i_grid(grid) {} + + void MoveToRespawnN(); + void UnloadN() + { + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + GridLoader loader; + loader.Unload(i_grid(x, y), *this); + } + } + } + + void Unload(GridType &grid); + template void Visit(GridRefManager &m); + private: + NGridType &i_grid; +}; + +class ObjectGridStoper +{ + public: + ObjectGridStoper(NGridType &grid) : i_grid(grid) {} + + void StopN() + { + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + GridLoader loader; + loader.Stop(i_grid(x, y), *this); + } + } + } + + void Stop(GridType &grid); + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + private: + NGridType &i_grid; +}; + +class ObjectGridCleaner +{ + public: + ObjectGridCleaner(NGridType &grid) : i_grid(grid) {} + + void CleanN() + { + for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) + { + for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) + { + GridLoader loader; + loader.Stop(i_grid(x, y), *this); + } + } + } + + void Stop(GridType &grid); + void Visit(CreatureMapType &m); + template void Visit(GridRefManager &); + private: + NGridType &i_grid; +}; + +typedef GridLoader GridLoaderType; +#endif + diff --git a/src/server/game/Maps/Cell/Cell.h b/src/server/game/Maps/Cell/Cell.h deleted file mode 100644 index 49e0329ace6..00000000000 --- a/src/server/game/Maps/Cell/Cell.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CELL_H -#define TRINITY_CELL_H - -#include - -#include "GameSystem/TypeContainer.h" -#include "GameSystem/TypeContainerVisitor.h" - -#include "GridDefines.h" - -class Map; -class WorldObject; - -enum District -{ - UPPER_DISTRICT = 1, - LOWER_DISTRICT = 1 << 1, - LEFT_DISTRICT = 1 << 2, - RIGHT_DISTRICT = 1 << 3, - CENTER_DISTRICT = 1 << 4, - UPPER_LEFT_DISTRICT = (UPPER_DISTRICT | LEFT_DISTRICT), - UPPER_RIGHT_DISTRICT = (UPPER_DISTRICT | RIGHT_DISTRICT), - LOWER_LEFT_DISTRICT = (LOWER_DISTRICT | LEFT_DISTRICT), - LOWER_RIGHT_DISTRICT = (LOWER_DISTRICT | RIGHT_DISTRICT), - ALL_DISTRICT = (UPPER_DISTRICT | LOWER_DISTRICT | LEFT_DISTRICT | RIGHT_DISTRICT | CENTER_DISTRICT) -}; - -struct CellArea -{ - CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {} - CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {} - bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; } - - void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const - { - begin_cell << left_offset; - begin_cell -= lower_offset; - end_cell >> right_offset; - end_cell += upper_offset; - } - - int right_offset; - int left_offset; - int upper_offset; - int lower_offset; -}; - -struct Cell -{ - Cell() { data.All = 0; } - Cell(const Cell &cell) { data.All = cell.data.All; } - explicit Cell(CellPair const& p); - - void operator|=(Cell &cell) - { - data.Part.reserved = 0; - cell.data.Part.reserved = 0; - uint32 x, y, old_x, old_y; - Compute(x, y); - cell.Compute(old_x, old_y); - - if (std::abs(int(x-old_x)) > 1 || std::abs(int(y-old_y)) > 1) - { - data.Part.reserved = ALL_DISTRICT; - cell.data.Part.reserved = ALL_DISTRICT; - return; - } - - if (x < old_x) - { - data.Part.reserved |= LEFT_DISTRICT; - cell.data.Part.reserved |= RIGHT_DISTRICT; - } - else if (old_x < x) - { - data.Part.reserved |= RIGHT_DISTRICT; - cell.data.Part.reserved |= LEFT_DISTRICT; - } - if (y < old_y) - { - data.Part.reserved |= UPPER_DISTRICT; - cell.data.Part.reserved |= LOWER_DISTRICT; - } - else if (old_y < y) - { - data.Part.reserved |= LOWER_DISTRICT; - cell.data.Part.reserved |= UPPER_DISTRICT; - } - } - - void Compute(uint32 &x, uint32 &y) const - { - x = data.Part.grid_x*MAX_NUMBER_OF_CELLS + data.Part.cell_x; - y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; - } - - bool DiffCell(const Cell &cell) const - { - return(data.Part.cell_x != cell.data.Part.cell_x || - data.Part.cell_y != cell.data.Part.cell_y); - } - - bool DiffGrid(const Cell &cell) const - { - return(data.Part.grid_x != cell.data.Part.grid_x || - data.Part.grid_y != cell.data.Part.grid_y); - } - - uint32 CellX() const { return data.Part.cell_x; } - uint32 CellY() const { return data.Part.cell_y; } - uint32 GridX() const { return data.Part.grid_x; } - uint32 GridY() const { return data.Part.grid_y; } - bool NoCreate() const { return data.Part.nocreate; } - void SetNoCreate() { data.Part.nocreate = 1; } - - CellPair cellPair() const - { - return CellPair( - data.Part.grid_x*MAX_NUMBER_OF_CELLS+data.Part.cell_x, - data.Part.grid_y*MAX_NUMBER_OF_CELLS+data.Part.cell_y); - } - - Cell& operator=(const Cell &cell) - { - this->data.All = cell.data.All; - return *this; - } - - bool operator == (const Cell &cell) const { return (data.All == cell.data.All); } - bool operator != (const Cell &cell) const { return !operator == (cell); } - union - { - struct - { - unsigned grid_x : 6; - unsigned grid_y : 6; - unsigned cell_x : 6; - unsigned cell_y : 6; - unsigned nocreate : 1; - unsigned reserved : 7; - } Part; - uint32 All; - } data; - - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &) const; - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, const WorldObject&, float) const; - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, float, float, float) const; - - static CellArea CalculateCellArea(const WorldObject &obj, float radius); - static CellArea CalculateCellArea(float x, float y, float radius); - -private: - template void VisitCircle(TypeContainerVisitor &, Map &, const CellPair&, const CellPair&) const; -}; - -#endif - diff --git a/src/server/game/Maps/Cell/CellImpl.h b/src/server/game/Maps/Cell/CellImpl.h deleted file mode 100644 index d906e81a5c9..00000000000 --- a/src/server/game/Maps/Cell/CellImpl.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CELLIMPL_H -#define TRINITY_CELLIMPL_H - -#include - -#include "Cell.h" -#include "Map.h" -#include "Object.h" - -inline Cell::Cell(CellPair const& p) -{ - data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS; - data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; - data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; - data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; - data.Part.nocreate = 0; - data.Part.reserved = 0; -} - -template -inline void -Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m) const -{ - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - return; - - uint16 district = (District)this->data.Part.reserved; - if (district == CENTER_DISTRICT) - { - m.Visit(*this, visitor); - return; - } - - // set up the cell range based on the district - // the overloaded operators handle range checking - CellPair begin_cell = standing_cell; - CellPair end_cell = standing_cell; - - switch(district) - { - case ALL_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell >> 1; end_cell += 1; // lower right - break; - } - case UPPER_LEFT_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - break; - } - case UPPER_RIGHT_DISTRICT: - { - begin_cell -= 1; // up - end_cell >> 1; // right - break; - } - case LOWER_LEFT_DISTRICT: - { - begin_cell << 1; // left - end_cell += 1; // down - break; - } - case LOWER_RIGHT_DISTRICT: - { - end_cell >> 1; end_cell += 1; // lower right - break; - } - case LEFT_DISTRICT: - { - begin_cell -= 1; // up - end_cell >> 1; end_cell += 1; // lower right - break; - } - case RIGHT_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell += 1; // down - break; - } - case UPPER_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell >> 1; // right - break; - } - case LOWER_DISTRICT: - { - begin_cell << 1; // left - end_cell >> 1; end_cell += 1; // lower right - break; - } - default: - { - assert(false); - break; - } - } - - // loop the cell range - for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++) - { - CellPair cell_pair(x,y); - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } -} - -inline int CellHelper(const float radius) -{ - if (radius < 1.0f) - return 0; - - return (int)ceilf(radius/SIZE_OF_GRID_CELL); -} - -inline CellArea Cell::CalculateCellArea(const WorldObject &obj, float radius) -{ - return Cell::CalculateCellArea(obj.GetPositionX(), obj.GetPositionY(), radius); -} - -inline CellArea Cell::CalculateCellArea(float x, float y, float radius) -{ - if (radius <= 0.0f) - return CellArea(); - - //lets calculate object coord offsets from cell borders. - //TODO: add more correct/generic method for this task - const float x_offset = (x - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - const float y_offset = (y - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - - const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f); - const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f); - - const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - - const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET; - //lets calculate upper/lower/right/left corners for cell search - int right = CellHelper(tmp_diff + x_off); - int left = CellHelper(tmp_diff - x_off); - int upper = CellHelper(tmp_diff + y_off); - int lower = CellHelper(tmp_diff - y_off); - - return CellArea(right, left, upper, lower); -} - -template -inline void -Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m, float radius, float x_off, float y_off) const -{ - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - return; - - //no jokes here... Actually placing ASSERT() here was good idea, but - //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?) - //maybe it is better to just return when radius <= 0.0f? - if (radius <= 0.0f) - { - m.Visit(*this, visitor); - return; - } - //lets limit the upper value for search radius - if (radius > 333.0f) - radius = 333.0f; - - //lets calculate object coord offsets from cell borders. - CellArea area = Cell::CalculateCellArea(x_off, y_off, radius); - //if radius fits inside standing cell - if (!area) - { - m.Visit(*this, visitor); - return; - } - - CellPair begin_cell = standing_cell; - CellPair end_cell = standing_cell; - - area.ResizeBorders(begin_cell, end_cell); - //visit all cells, found in CalculateCellArea() - //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle - //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values - //there are nothing to optimize because SIZE_OF_GRID_CELL is too big... - if (((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4)) - { - VisitCircle(visitor, m, begin_cell, end_cell); - return; - } - - //ALWAYS visit standing cell first!!! Since we deal with small radiuses - //it is very essential to call visitor for standing cell firstly... - m.Visit(*this, visitor); - - // loop the cell range - for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) - { - CellPair cell_pair(x,y); - //lets skip standing cell since we already visited it - if (cell_pair != standing_cell) - { - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } - } -} - -template -inline void -Cell::Visit(const CellPair& l, TypeContainerVisitor &visitor, Map &m, const WorldObject &obj, float radius) const -{ - //we should increase search radius by object's radius, otherwise - //we could have problems with huge creatures, which won't attack nearest players etc - Visit(l, visitor, m, radius + obj.GetObjectSize(), obj.GetPositionX(), obj.GetPositionY()); -} - -template -inline void -Cell::VisitCircle(TypeContainerVisitor &visitor, Map &m, const CellPair& begin_cell, const CellPair& end_cell) const -{ - //here is an algorithm for 'filling' circum-squared octagon - uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f); - //lets calculate x_start/x_end coords for central strip... - const uint32 x_start = begin_cell.x_coord + x_shift; - const uint32 x_end = end_cell.x_coord - x_shift; - - //visit central strip with constant width... - for (uint32 x = x_start; x <= x_end; ++x) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) - { - CellPair cell_pair(x,y); - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } - - //if x_shift == 0 then we have too small cell area, which were already - //visited at previous step, so just return from procedure... - if (x_shift == 0) - return; - - uint32 y_start = end_cell.y_coord; - uint32 y_end = begin_cell.y_coord; - //now we are visiting borders of an octagon... - for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step) - { - //each step reduces strip height by 2 cells... - y_end += 1; - y_start -= 1; - for (uint32 y = y_start; y >= y_end; --y) - { - //we visit cells symmetrically from both sides, heading from center to sides and from up to bottom - //e.g. filling 2 trapezoids after filling central cell strip... - CellPair cell_pair_left(x_start - step, y); - Cell r_zone_left(cell_pair_left); - r_zone_left.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone_left, visitor); - - //right trapezoid cell visit - CellPair cell_pair_right(x_end + step, y); - Cell r_zone_right(cell_pair_right); - r_zone_right.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone_right, visitor); - } - } -} -#endif - diff --git a/src/server/game/Maps/Grid/GridDefines.h b/src/server/game/Maps/Grid/GridDefines.h deleted file mode 100644 index 5269d0a094d..00000000000 --- a/src/server/game/Maps/Grid/GridDefines.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDDEFINES_H -#define TRINITY_GRIDDEFINES_H - -#include "Common.h" -#include "GameSystem/NGrid.h" -#include - -// Forward class definitions -class Corpse; -class Creature; -class DynamicObject; -class GameObject; -class Pet; -class Player; - -#define MAX_NUMBER_OF_CELLS 8 - -#define MAX_NUMBER_OF_GRIDS 64 - -#define SIZE_OF_GRIDS 533.33333f -#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2) - -#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) - -#define MIN_GRID_DELAY (MINUTE*IN_MILISECONDS) -#define MIN_MAP_UPDATE_DELAY 50 - -#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) - -#define CENTER_GRID_CELL_ID (MAX_NUMBER_OF_CELLS*MAX_NUMBER_OF_GRIDS/2) -#define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2) - -#define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) - -#define MAP_RESOLUTION 128 - -#define MAP_SIZE (SIZE_OF_GRIDS*MAX_NUMBER_OF_GRIDS) -#define MAP_HALFSIZE (MAP_SIZE/2) - -// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case) -typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes; -typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes; - -typedef GridRefManager CorpseMapType; -typedef GridRefManager CreatureMapType; -typedef GridRefManager DynamicObjectMapType; -typedef GridRefManager GameObjectMapType; -typedef GridRefManager PlayerMapType; - -typedef Grid GridType; -typedef NGrid NGridType; - -typedef TypeMapContainer GridTypeMapContainer; -typedef TypeMapContainer WorldTypeMapContainer; - -template -struct CoordPair -{ - CoordPair(uint32 x=0, uint32 y=0) : x_coord(x), y_coord(y) {} - CoordPair(const CoordPair &obj) : x_coord(obj.x_coord), y_coord(obj.y_coord) {} - bool operator == (const CoordPair &obj) const { return (obj.x_coord == x_coord && obj.y_coord == y_coord); } - bool operator != (const CoordPair &obj) const { return !operator == (obj); } - CoordPair& operator=(const CoordPair &obj) - { - x_coord = obj.x_coord; - y_coord = obj.y_coord; - return *this; - } - - void operator<<(const uint32 val) - { - if (x_coord > val) - x_coord -= val; - else - x_coord = 0; - } - - void operator>>(const uint32 val) - { - if (x_coord+val < LIMIT) - x_coord += val; - else - x_coord = LIMIT - 1; - } - - void operator-=(const uint32 val) - { - if (y_coord > val) - y_coord -= val; - else - y_coord = 0; - } - - void operator+=(const uint32 val) - { - if (y_coord+val < LIMIT) - y_coord += val; - else - y_coord = LIMIT - 1; - } - - uint32 x_coord; - uint32 y_coord; -}; - -typedef CoordPair GridPair; -typedef CoordPair CellPair; - -namespace Trinity -{ - template - inline RET_TYPE Compute(float x, float y, float center_offset, float size) - { - // calculate and store temporary values in double format for having same result as same mySQL calculations - double x_offset = (double(x) - center_offset)/size; - double y_offset = (double(y) - center_offset)/size; - - int x_val = int(x_offset+CENTER_VAL + 0.5); - int y_val = int(y_offset+CENTER_VAL + 0.5); - return RET_TYPE(x_val, y_val); - } - - inline GridPair ComputeGridPair(float x, float y) - { - return Compute(x, y, CENTER_GRID_OFFSET, SIZE_OF_GRIDS); - } - - inline CellPair ComputeCellPair(float x, float y) - { - return Compute(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL); - } - - inline CellPair ComputeCellPair(float x, float y, float &x_off, float &y_off) - { - double x_offset = (double(x) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - double y_offset = (double(y) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - - int x_val = int(x_offset + CENTER_GRID_CELL_ID + 0.5); - int y_val = int(y_offset + CENTER_GRID_CELL_ID + 0.5); - x_off = (float(x_offset) - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - y_off = (float(y_offset) - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - return CellPair(x_val, y_val); - } - - inline void NormalizeMapCoord(float &c) - { - if (c > MAP_HALFSIZE - 0.5) - c = MAP_HALFSIZE - 0.5; - else if (c < -(MAP_HALFSIZE - 0.5)) - c = -(MAP_HALFSIZE - 0.5); - } - - inline bool IsValidMapCoord(float c) - { - return finite(c) && (std::fabs(c) <= MAP_HALFSIZE - 0.5); - } - - inline bool IsValidMapCoord(float x, float y) - { - return IsValidMapCoord(x) && IsValidMapCoord(y); - } - - inline bool IsValidMapCoord(float x, float y, float z) - { - return IsValidMapCoord(x,y) && finite(z); - } - - inline bool IsValidMapCoord(float x, float y, float z, float o) - { - return IsValidMapCoord(x,y,z) && finite(o); - } -} -#endif diff --git a/src/server/game/Maps/Grid/GridNotifiers.cpp b/src/server/game/Maps/Grid/GridNotifiers.cpp deleted file mode 100644 index b10dfa8791e..00000000000 --- a/src/server/game/Maps/Grid/GridNotifiers.cpp +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "UpdateData.h" -#include "Item.h" -#include "Map.h" -#include "Transports.h" -#include "ObjectAccessor.h" -#include "CellImpl.h" - -using namespace Trinity; - -void -VisibleNotifier::SendToSelf() -{ - // at this moment i_clientGUIDs have guids that not iterate at grid level checks - // but exist one case when this possible and object not out of range: transports - if (Transport* transport = i_player.GetTransport()) - for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr != transport->GetPassengers().end();++itr) - { - if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end()) - { - vis_guids.erase((*itr)->GetGUID()); - - i_player.UpdateVisibilityOf((*itr), i_data, i_visibleNow); - - if (!(*itr)->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - (*itr)->UpdateVisibilityOf(&i_player); - } - } - - for (Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end(); ++it) - { - i_player.m_clientGUIDs.erase(*it); - i_data.AddOutOfRangeGUID(*it); - - if (IS_PLAYER_GUID(*it)) - { - Player* plr = ObjectAccessor::FindPlayer(*it); - if (plr && plr->IsInWorld() && !plr->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - plr->UpdateVisibilityOf(&i_player); - } - } - - if (!i_data.HasData()) - return; - - WorldPacket packet; - i_data.BuildPacket(&packet); - i_player.GetSession()->SendPacket(&packet); - - for (std::set::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it) - i_player.SendInitialVisiblePackets(*it); -} - -void -VisibleChangesNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - if (iter->getSource() == &i_object) - continue; - - iter->getSource()->UpdateVisibilityOf(&i_object); - - if (!iter->getSource()->GetSharedVisionList().empty()) - for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - (*i)->UpdateVisibilityOf(&i_object); - } -} - -void -VisibleChangesNotifier::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (!iter->getSource()->GetSharedVisionList().empty()) - for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - (*i)->UpdateVisibilityOf(&i_object); -} - -void -VisibleChangesNotifier::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) - if (Player* caster = (Player*)iter->getSource()->GetCaster()) - if (caster->m_seer == iter->getSource()) - caster->UpdateVisibilityOf(&i_object); -} - -inline void CreatureUnitRelocationWorker(Creature* c, Unit* u) -{ - if (!u->isAlive() || !c->isAlive() || c == u || u->isInFlight()) - return; - - if (c->HasReactState(REACT_AGGRESSIVE) && !c->hasUnitState(UNIT_STAT_SIGHTLESS)) - if (c->_IsWithinDist(u, c->m_SightDistance, true) && c->IsAIEnabled) - c->AI()->MoveInLineOfSight_Safe(u); -} - -void PlayerRelocationNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Player* plr = iter->getSource(); - - vis_guids.erase(plr->GetGUID()); - - i_player.UpdateVisibilityOf(plr,i_data,i_visibleNow); - - if (plr->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - plr->UpdateVisibilityOf(&i_player); - } -} - -void PlayerRelocationNotifier::Visit(CreatureMapType &m) -{ - bool relocated_for_ai = (&i_player == i_player.m_seer); - - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Creature * c = iter->getSource(); - - vis_guids.erase(c->GetGUID()); - - i_player.UpdateVisibilityOf(c,i_data,i_visibleNow); - - if (relocated_for_ai && !c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - CreatureUnitRelocationWorker(c, &i_player); - } -} - -void CreatureRelocationNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Player * pl = iter->getSource(); - - if (!pl->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - pl->UpdateVisibilityOf(&i_creature); - - CreatureUnitRelocationWorker(&i_creature, pl); - } -} - -void CreatureRelocationNotifier::Visit(CreatureMapType &m) -{ - if (!i_creature.isAlive()) - return; - - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Creature* c = iter->getSource(); - CreatureUnitRelocationWorker(&i_creature, c); - - if (!c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - CreatureUnitRelocationWorker(c, &i_creature); - } -} - -void DelayedUnitRelocation::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Creature * unit = iter->getSource(); - if (!unit->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - CreatureRelocationNotifier relocate(*unit); - - TypeContainerVisitor c2world_relocation(relocate); - TypeContainerVisitor c2grid_relocation(relocate); - - cell.Visit(p, c2world_relocation, i_map, *unit, i_radius); - cell.Visit(p, c2grid_relocation, i_map, *unit, i_radius); - } -} - -void DelayedUnitRelocation::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Player * player = iter->getSource(); - WorldObject const *viewPoint = player->m_seer; - - if (!viewPoint->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - if (player != viewPoint && !viewPoint->IsPositionValid()) - continue; - - CellPair pair2(Trinity::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY())); - Cell cell2(pair2); - //cell.SetNoCreate(); need load cells around viewPoint or player, that's why its commented - - PlayerRelocationNotifier relocate(*player); - TypeContainerVisitor c2world_relocation(relocate); - TypeContainerVisitor c2grid_relocation(relocate); - - cell2.Visit(pair2, c2world_relocation, i_map, *viewPoint, i_radius); - cell2.Visit(pair2, c2grid_relocation, i_map, *viewPoint, i_radius); - - relocate.SendToSelf(); - } -} - -void AIRelocationNotifier::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Creature *c = iter->getSource(); - CreatureUnitRelocationWorker(c, &i_unit); - if (isCreature) - CreatureUnitRelocationWorker((Creature*)&i_unit, c); - } -} - -void -MessageDistDeliverer::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Player *target = iter->getSource(); - if (!target->InSamePhase(i_phaseMask)) - continue; - - if (target->GetExactDistSq(i_source) > i_distSq) - continue; - - // Send packet to all who are sharing the player's vision - if (!target->GetSharedVisionList().empty()) - { - SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); - for (; i != target->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == target) - SendPacket(*i); - } - - if (target->m_seer == target || target->GetVehicle()) - SendPacket(target); - } -} - -void -MessageDistDeliverer::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (!iter->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) - continue; - - // Send packet to all who are sharing the creature's vision - if (!iter->getSource()->GetSharedVisionList().empty()) - { - SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - for (; i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - SendPacket(*i); - } - } -} - -void -MessageDistDeliverer::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (!iter->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) - continue; - - if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) - { - // Send packet back to the caster if the caster has vision of dynamic object - Player* caster = (Player*)iter->getSource()->GetCaster(); - if (caster && caster->m_seer == iter->getSource()) - SendPacket(caster); - } - } -} - -/* -void -MessageDistDeliverer::VisitObject(Player* plr) -{ - if (!i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam())) - { - SendPacket(plr); - } -} -*/ - -template void -ObjectUpdater::Visit(GridRefManager &m) -{ - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (iter->getSource()->IsInWorld()) - iter->getSource()->Update(i_timeDiff); - } -} - -bool CannibalizeObjectCheck::operator()(Corpse* u) -{ - // ignore bones - if (u->GetType() == CORPSE_BONES) - return false; - - Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); - - if (!owner || i_funit->IsFriendlyTo(owner)) - return false; - - if (i_funit->IsWithinDistInMap(u, i_range)) - return true; - - return false; -} - -template void ObjectUpdater::Visit(GameObjectMapType &); -template void ObjectUpdater::Visit(DynamicObjectMapType &); diff --git a/src/server/game/Maps/Grid/GridNotifiers.h b/src/server/game/Maps/Grid/GridNotifiers.h deleted file mode 100644 index b0abf0aae79..00000000000 --- a/src/server/game/Maps/Grid/GridNotifiers.h +++ /dev/null @@ -1,1232 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDNOTIFIERS_H -#define TRINITY_GRIDNOTIFIERS_H - -#include "ObjectGridLoader.h" -#include "UpdateData.h" -#include - -#include "Corpse.h" -#include "Object.h" -#include "DynamicObject.h" -#include "GameObject.h" -#include "Player.h" -#include "Unit.h" -#include "CreatureAI.h" - -class Player; -//class Map; - -namespace Trinity -{ - struct VisibleNotifier - { - Player &i_player; - UpdateData i_data; - std::set i_visibleNow; - Player::ClientGUIDs vis_guids; - - VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) {} - template void Visit(GridRefManager &m); - void SendToSelf(void); - }; - - struct VisibleChangesNotifier - { - WorldObject &i_object; - - explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {} - template void Visit(GridRefManager &) {} - void Visit(PlayerMapType &); - void Visit(CreatureMapType &); - void Visit(DynamicObjectMapType &); - }; - - struct PlayerRelocationNotifier : public VisibleNotifier - { - PlayerRelocationNotifier(Player &pl) : VisibleNotifier(pl) {} - - template void Visit(GridRefManager &m) { VisibleNotifier::Visit(m); } - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct CreatureRelocationNotifier - { - Creature &i_creature; - CreatureRelocationNotifier(Creature &c) : i_creature(c) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct DelayedUnitRelocation - { - Map &i_map; - Cell &cell; - CellPair &p; - const float i_radius; - DelayedUnitRelocation(Cell &c, CellPair &pair, Map &map, float radius) : - cell(c), p(pair), i_map(map), i_radius(radius) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct AIRelocationNotifier - { - Unit &i_unit; - bool isCreature; - explicit AIRelocationNotifier(Unit &unit) : i_unit(unit), isCreature(unit.GetTypeId() == TYPEID_UNIT) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - }; - - struct GridUpdater - { - GridType &i_grid; - uint32 i_timeDiff; - GridUpdater(GridType &grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) {} - - template void updateObjects(GridRefManager &m) - { - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - iter->getSource()->Update(i_timeDiff); - } - - void Visit(PlayerMapType &m) { updateObjects(m); } - void Visit(CreatureMapType &m){ updateObjects(m); } - void Visit(GameObjectMapType &m) { updateObjects(m); } - void Visit(DynamicObjectMapType &m) { updateObjects(m); } - void Visit(CorpseMapType &m) { updateObjects(m); } - }; - - struct MessageDistDeliverer - { - WorldObject *i_source; - WorldPacket *i_message; - uint32 i_phaseMask; - float i_distSq; - uint32 team; - Player const* skipped_receiver; - MessageDistDeliverer(WorldObject *src, WorldPacket *msg, float dist, bool own_team_only = false, Player const* skipped = NULL) - : i_source(src), i_message(msg), i_distSq(dist * dist), i_phaseMask(src->GetPhaseMask()) - , team((own_team_only && src->GetTypeId() == TYPEID_PLAYER) ? ((Player*)src)->GetTeam() : 0) - , skipped_receiver(skipped) - { - } - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(DynamicObjectMapType &m); - template void Visit(GridRefManager &) {} - - void SendPacket(Player* plr) - { - // never send packet to self - if (plr == i_source || (team && plr->GetTeam() != team) || skipped_receiver == plr) - return; - - plr->GetSession()->SendPacket(i_message); - } - }; - - struct ObjectUpdater - { - uint32 i_timeDiff; - explicit ObjectUpdater(const uint32 &diff) : i_timeDiff(diff) {} - template void Visit(GridRefManager &m); - void Visit(PlayerMapType &) {} - void Visit(CorpseMapType &) {} - void Visit(CreatureMapType &); - }; - - // SEARCHERS & LIST SEARCHERS & WORKERS - - // WorldObject searchers & workers - - template - struct WorldObjectSearcher - { - uint32 i_phaseMask; - WorldObject* &i_object; - Check &i_check; - - WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(GameObjectMapType &m); - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(CorpseMapType &m); - void Visit(DynamicObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct WorldObjectListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - WorldObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(CorpseMapType &m); - void Visit(GameObjectMapType &m); - void Visit(DynamicObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct WorldObjectWorker - { - uint32 i_phaseMask; - Do const& i_do; - - WorldObjectWorker(WorldObject const* searcher, Do const& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(GameObjectMapType &m) - { - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - void Visit(CreatureMapType &m) - { - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(CorpseMapType &m) - { - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(DynamicObjectMapType &m) - { - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // Gameobject searchers - - template - struct GameObjectSearcher - { - uint32 i_phaseMask; - GameObject* &i_object; - Check &i_check; - - GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check GO if any (Check can change requirements at each call) - template - struct GameObjectLastSearcher - { - uint32 i_phaseMask; - GameObject* &i_object; - Check& i_check; - - GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct GameObjectListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - GameObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Unit searchers - - // First accepted by Check Unit if any - template - struct UnitSearcher - { - uint32 i_phaseMask; - Unit* &i_object; - Check & i_check; - - UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check Unit if any (Check can change requirements at each call) - template - struct UnitLastSearcher - { - uint32 i_phaseMask; - Unit* &i_object; - Check & i_check; - - UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // All accepted by Check units if any - template - struct UnitListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - UnitListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Creature searchers - - template - struct CreatureSearcher - { - uint32 i_phaseMask; - Creature* &i_object; - Check & i_check; - - CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check Creature if any (Check can change requirements at each call) - template - struct CreatureLastSearcher - { - uint32 i_phaseMask; - Creature* &i_object; - Check & i_check; - - CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct CreatureListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - CreatureListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct CreatureWorker - { - uint32 i_phaseMask; - Do& i_do; - - CreatureWorker(WorldObject const* searcher, Do& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(CreatureMapType &m) - { - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // Player searchers - - template - struct PlayerSearcher - { - uint32 i_phaseMask; - Player* &i_object; - Check & i_check; - - PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - PlayerListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerWorker - { - uint32 i_phaseMask; - Do& i_do; - - PlayerWorker(WorldObject const* searcher, Do& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerDistWorker - { - WorldObject const* i_searcher; - float i_dist; - Do& i_do; - - PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do) - : i_searcher(searcher), i_dist(_dist), i_do(_do) {} - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // CHECKS && DO classes - - // WorldObject check classes - class RaiseDeadObjectCheck - { - public: - RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Creature* u) - { - if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || - u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() || - (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 || - (u->GetDisplayId() != u->GetNativeDisplayId())) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - class ExplodeCorpseObjectCheck - { - public: - ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (u->getDeathState() != CORPSE || u->isInFlight() || - u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - bool operator()(Creature* u) - { - if (u->getDeathState() != CORPSE || u->isInFlight() || u->isDeadByDefault() || - (u->GetDisplayId() != u->GetNativeDisplayId()) || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - class CannibalizeObjectCheck - { - public: - CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - bool operator()(Corpse* u); - bool operator()(Creature* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - // WorldObject do classes - - class RespawnDo - { - public: - RespawnDo() {} - void operator()(Creature* u) const { u->Respawn(); } - void operator()(GameObject* u) const { u->Respawn(); } - void operator()(WorldObject*) const {} - void operator()(Corpse*) const {} - }; - - // GameObject checks - - class GameObjectFocusCheck - { - public: - GameObjectFocusCheck(Unit const* unit,uint32 focusId) : i_unit(unit), i_focusId(focusId) {} - bool operator()(GameObject* go) const - { - if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS) - return false; - - if (go->GetGOInfo()->spellFocus.focusId != i_focusId) - return false; - - float dist = (go->GetGOInfo()->spellFocus.dist)/2; - - return go->IsWithinDistInMap(i_unit, dist); - } - private: - Unit const* i_unit; - uint32 i_focusId; - }; - - // Find the nearest Fishing hole and return true only if source object is in range of hole - class NearestGameObjectFishingHole - { - public: - NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(GameObject* go) - { - if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, go->GetGOInfo()->fishinghole.radius)) - { - i_range = i_obj.GetDistance(go); - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - float i_range; - - // prevent clone - NearestGameObjectFishingHole(NearestGameObjectFishingHole const&); - }; - - class NearestGameObjectCheck - { - public: - NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) {} - bool operator()(GameObject* go) - { - if (i_obj.IsWithinDistInMap(go, i_range)) - { - i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - float i_range; - - // prevent clone this object - NearestGameObjectCheck(NearestGameObjectCheck const&); - }; - - // Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO) - class NearestGameObjectEntryInObjectRangeCheck - { - public: - NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj,uint32 entry, float range) : i_obj(obj), i_entry(entry), i_range(range) {} - bool operator()(GameObject* go) - { - if (go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range)) - { - i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - uint32 i_entry; - float i_range; - - // prevent clone this object - NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&); - }; - - class GameObjectWithDbGUIDCheck - { - public: - GameObjectWithDbGUIDCheck(WorldObject const& obj,uint32 db_guid) : i_obj(obj), i_db_guid(db_guid) {} - bool operator()(GameObject const* go) const - { - return go->GetDBTableGUIDLow() == i_db_guid; - } - private: - WorldObject const& i_obj; - uint32 i_db_guid; - }; - - // Unit checks - - class MostHPMissingInRange - { - public: - MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp) - { - i_hp = u->GetMaxHealth() - u->GetHealth(); - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - uint32 i_hp; - }; - - class FriendlyCCedInRange - { - public: - FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && - (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED))) - { - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - }; - - class FriendlyMissingBuffInRange - { - public: - FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && - !(u->HasAura(i_spell))) - { - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - uint32 i_spell; - }; - - class AnyUnfriendlyUnitInObjectRangeCheck - { - public: - AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u)) - return true; - else - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnfriendlyNoTotemUnitInObjectRangeCheck - { - public: - AnyUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (!u->isAlive()) - return false; - - if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) - return false; - - return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u); - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnfriendlyVisibleUnitInObjectRangeCheck - { - public: - AnyUnfriendlyVisibleUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) - : i_obj(obj), i_funit(funit), i_range(range) {} - - bool operator()(Unit* u) - { - return u->isAlive() - && i_obj->IsWithinDistInMap(u, i_range) - && !i_funit->IsFriendlyTo(u) - && u->isVisibleForOrDetect(i_funit, false); - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class CreatureWithDbGUIDCheck - { - public: - CreatureWithDbGUIDCheck(WorldObject const* obj, uint32 lowguid) : i_obj(obj), i_lowguid(lowguid) {} - bool operator()(Creature* u) - { - return u->GetDBTableGUIDLow() == i_lowguid; - } - private: - WorldObject const* i_obj; - uint32 i_lowguid; - }; - - class AnyFriendlyUnitInObjectRangeCheck - { - public: - AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) - return true; - else - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnitInObjectRangeCheck - { - public: - AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - WorldObject const* i_obj; - float i_range; - }; - - // Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit) - class NearestAttackableUnitInObjectRangeCheck - { - public: - NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) && - !i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,false)) - { - i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - - // prevent clone this object - NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); - }; - - class AnyAoETargetUnitInObjectRangeCheck - { - public: - AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) - : i_obj(obj), i_funit(funit), i_range(range) - { - Unit const* check = i_funit; - Unit const* owner = i_funit->GetOwner(); - if (owner) - check = owner; - i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER); - } - bool operator()(Unit* u) - { - // Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems - if (!u->isTargetableForAttack()) - return false; - if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) - return false; - - if ((i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u))&& i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - bool i_targetForPlayer; - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - // do attack at call of help to friendly crearture - class CallOfHelpCreatureInRangeDo - { - public: - CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range) - : i_funit(funit), i_enemy(enemy), i_range(range) - {} - void operator()(Creature* u) - { - if (u == i_funit) - return; - - if (!u->CanAssistTo(i_funit, i_enemy, false)) - return; - - // too far - if (!u->IsWithinDistInMap(i_enemy, i_range)) - return; - - // only if see assisted creature's enemy - if (!u->IsWithinLOSInMap(i_enemy)) - return; - - if (u->AI()) - u->AI()->AttackStart(i_enemy); - } - private: - Unit* const i_funit; - Unit* const i_enemy; - float i_range; - }; - - struct AnyDeadUnitCheck - { - bool operator()(Unit* u) { return !u->isAlive(); } - }; - - struct AnyStealthedCheck - { - bool operator()(Unit* u) { return u->GetVisibility() == VISIBILITY_GROUP_STEALTH; } - }; - - // Creature checks - - class NearestHostileUnitCheck - { - public: - explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0) : me(creature) - { - m_range = (dist == 0 ? 9999 : dist); - } - bool operator()(Unit* u) - { - if (!me->IsWithinDistInMap(u, m_range)) - return false; - - if (!me->canAttack(u)) - return false; - - m_range = me->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - - private: - Creature const *me; - float m_range; - NearestHostileUnitCheck(NearestHostileUnitCheck const&); - }; - - class NearestHostileUnitInAttackDistanceCheck - { - public: - explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0) : me(creature) - { - m_range = (dist == 0 ? 9999 : dist); - m_force = (dist == 0 ? false : true); - } - bool operator()(Unit* u) - { - if (!me->IsWithinDistInMap(u, m_range)) - return false; - - if (m_force) - { - if (!me->canAttack(u)) - return false; - } - else - { - if (!me->canStartAttack(u, false)) - return false; - } - - m_range = me->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - float GetLastRange() const { return m_range; } - private: - Creature const *me; - float m_range; - bool m_force; - NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&); - }; - - class AnyAssistCreatureInRangeCheck - { - public: - AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range) - : i_funit(funit), i_enemy(enemy), i_range(range) - { - } - bool operator()(Creature* u) - { - if (u == i_funit) - return false; - - if (!u->CanAssistTo(i_funit, i_enemy)) - return false; - - // too far - if (!i_funit->IsWithinDistInMap(u, i_range)) - return false; - - // only if see assisted creature - if (!i_funit->IsWithinLOSInMap(u)) - return false; - - return true; - } - private: - Unit* const i_funit; - Unit* const i_enemy; - float i_range; - }; - - class NearestAssistCreatureInCreatureRangeCheck - { - public: - NearestAssistCreatureInCreatureRangeCheck(Creature* obj, Unit* enemy, float range) - : i_obj(obj), i_enemy(enemy), i_range(range) {} - - bool operator()(Creature* u) - { - if (u == i_obj) - return false; - if (!u->CanAssistTo(i_obj,i_enemy)) - return false; - - if (!i_obj->IsWithinDistInMap(u, i_range)) - return false; - - if (!i_obj->IsWithinLOSInMap(u)) - return false; - - i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - float GetLastRange() const { return i_range; } - private: - Creature* const i_obj; - Unit* const i_enemy; - float i_range; - - // prevent clone this object - NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&); - }; - - // Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature) - class NearestCreatureEntryWithLiveStateInObjectRangeCheck - { - public: - NearestCreatureEntryWithLiveStateInObjectRangeCheck(WorldObject const& obj, uint32 entry, bool alive, float range) - : i_obj(obj), i_entry(entry), i_alive(alive), i_range(range) {} - - bool operator()(Creature* u) - { - if (u->GetEntry() == i_entry && u->isAlive() == i_alive && i_obj.IsWithinDistInMap(u, i_range)) - { - i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - uint32 i_entry; - bool i_alive; - float i_range; - - // prevent clone this object - NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&); - }; - - class AnyPlayerInObjectRangeCheck - { - public: - AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Player* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - WorldObject const* i_obj; - float i_range; - }; - - class AllFriendlyCreaturesInGrid - { - public: - AllFriendlyCreaturesInGrid(Unit const* obj) : pUnit(obj) {} - bool operator() (Unit* u) - { - if (u->isAlive() && u->GetVisibility() == VISIBILITY_ON && u->IsFriendlyTo(pUnit)) - return true; - - return false; - } - private: - Unit const* pUnit; - }; - - class AllGameObjectsWithEntryInRange - { - public: - AllGameObjectsWithEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} - bool operator() (GameObject* pGo) - { - if (pGo->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pGo,m_fRange,false)) - return true; - - return false; - } - private: - const WorldObject* m_pObject; - uint32 m_uiEntry; - float m_fRange; - }; - - class AllCreaturesOfEntryInRange - { - public: - AllCreaturesOfEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} - bool operator() (Unit* pUnit) - { - if (pUnit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pUnit,m_fRange,false)) - return true; - - return false; - } - - private: - const WorldObject* m_pObject; - uint32 m_uiEntry; - float m_fRange; - }; - - class PlayerAtMinimumRangeAway - { - public: - PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : pUnit(unit), fRange(fMinRange) {} - bool operator() (Player* pPlayer) - { - //No threat list check, must be done explicit if expected to be in combat with creature - if (!pPlayer->isGameMaster() && pPlayer->isAlive() && !pUnit->IsWithinDist(pPlayer,fRange,false)) - return true; - - return false; - } - - private: - Unit const* pUnit; - float fRange; - }; - - class GameObjectInRangeCheck - { - public: - GameObjectInRangeCheck(float _x, float _y, float _z, float _range) : x(_x), y(_y), z(_z), range(_range) {} - bool operator() (GameObject* go) - { - return go->IsInRange(x, y, z, range); - } - private: - float x, y, z, range; - }; - - // Player checks and do - - // Prepare using Builder localized packets with caching and send to player - template - class LocalizedPacketDo - { - public: - explicit LocalizedPacketDo(Builder& builder) : i_builder(builder) {} - - ~LocalizedPacketDo() - { - for (size_t i = 0; i < i_data_cache.size(); ++i) - delete i_data_cache[i]; - } - void operator()(Player* p); - - private: - Builder& i_builder; - std::vector i_data_cache; // 0 = default, i => i-1 locale index - }; - - // Prepare using Builder localized packets with caching and send to player - template - class LocalizedPacketListDo - { - public: - typedef std::vector WorldPacketList; - explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {} - - ~LocalizedPacketListDo() - { - for (size_t i = 0; i < i_data_cache.size(); ++i) - for (size_t j = 0; j < i_data_cache[i].size(); ++j) - delete i_data_cache[i][j]; - } - void operator()(Player* p); - - private: - Builder& i_builder; - std::vector i_data_cache; - // 0 = default, i => i-1 locale index - }; -} -#endif diff --git a/src/server/game/Maps/Grid/GridNotifiersImpl.h b/src/server/game/Maps/Grid/GridNotifiersImpl.h deleted file mode 100644 index 26a9c0bd328..00000000000 --- a/src/server/game/Maps/Grid/GridNotifiersImpl.h +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDNOTIFIERSIMPL_H -#define TRINITY_GRIDNOTIFIERSIMPL_H - -#include "GridNotifiers.h" -#include "WorldPacket.h" -#include "Corpse.h" -#include "Player.h" -#include "UpdateData.h" -#include "CreatureAI.h" -#include "SpellAuras.h" - - -template -inline void -Trinity::VisibleNotifier::Visit(GridRefManager &m) -{ - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - { - vis_guids.erase(iter->getSource()->GetGUID()); - i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow); - } -} - -inline void -Trinity::ObjectUpdater::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - if (iter->getSource()->IsInWorld() && !iter->getSource()->isSpiritService()) - iter->getSource()->Update(i_timeDiff); -} - -// SEARCHERS & LIST SEARCHERS & WORKERS - -// WorldObject searchers & workers - -template -void Trinity::WorldObjectSearcher::Visit(GameObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(CorpseMapType &m) -{ - // already found - if (i_object) - return; - - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(DynamicObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(CorpseMapType &m) -{ - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Gameobject searchers - -template -void Trinity::GameObjectSearcher::Visit(GameObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::GameObjectLastSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::GameObjectListSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Unit searchers - -template -void Trinity::UnitSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::UnitSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::UnitLastSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::UnitLastSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::UnitListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::UnitListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Creature searchers - -template -void Trinity::CreatureSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::CreatureLastSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::CreatureListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::PlayerListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::PlayerSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::LocalizedPacketDo::operator()(Player* p) -{ - int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; - WorldPacket* data; - - // create if not cached yet - if (i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx]) - { - if (i_data_cache.size() < cache_idx+1) - i_data_cache.resize(cache_idx+1); - - data = new WorldPacket(SMSG_MESSAGECHAT, 200); - - i_builder(*data,loc_idx); - - i_data_cache[cache_idx] = data; - } - else - data = i_data_cache[cache_idx]; - - p->SendDirectMessage(data); -} - -template -void Trinity::LocalizedPacketListDo::operator()(Player* p) -{ - int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; - WorldPacketList* data_list; - - // create if not cached yet - if (i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty()) - { - if (i_data_cache.size() < cache_idx+1) - i_data_cache.resize(cache_idx+1); - - data_list = &i_data_cache[cache_idx]; - - i_builder(*data_list,loc_idx); - } - else - data_list = &i_data_cache[cache_idx]; - - for (size_t i = 0; i < data_list->size(); ++i) - p->SendDirectMessage((*data_list)[i]); -} - -#endif // TRINITY_GRIDNOTIFIERSIMPL_H diff --git a/src/server/game/Maps/Grid/GridStates.cpp b/src/server/game/Maps/Grid/GridStates.cpp deleted file mode 100644 index 9d39531cfad..00000000000 --- a/src/server/game/Maps/Grid/GridStates.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "GridStates.h" -#include "GridNotifiers.h" -#include "GameSystem/Grid.h" -#include "Log.h" - -void -InvalidState::Update(Map &, NGridType &, GridInfo &, const uint32 &/*x*/, const uint32 &/*y*/, const uint32 &) const -{ -} - -void -ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const -{ - // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle - info.UpdateTimeTracker(t_diff); - if (info.getTimeTracker().Passed()) - { - if (grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y)) - { - ObjectGridStoper stoper(grid); - stoper.StopN(); - grid.SetGridState(GRID_STATE_IDLE); - sLog.outDebug("Grid[%u,%u] on map %u moved to IDLE state", x, y, m.GetId()); - } - else - { - m.ResetGridExpiry(grid, 0.1f); - } - } -} - -void -IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &) const -{ - m.ResetGridExpiry(grid); - grid.SetGridState(GRID_STATE_REMOVAL); - sLog.outDebug("Grid[%u,%u] on map %u moved to REMOVAL state", x, y, m.GetId()); -} - -void -RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const -{ - if (!info.getUnloadLock()) - { - info.UpdateTimeTracker(t_diff); - if (info.getTimeTracker().Passed()) - { - if (!m.UnloadGrid(x, y, false)) - { - sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players or active objects nearby", x, y, m.GetId()); - m.ResetGridExpiry(grid); - } - } - } -} - diff --git a/src/server/game/Maps/Grid/GridStates.h b/src/server/game/Maps/Grid/GridStates.h deleted file mode 100644 index c2a75ec45b7..00000000000 --- a/src/server/game/Maps/Grid/GridStates.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDSTATES_H -#define TRINITY_GRIDSTATES_H - -#include "Map.h" -#include "Object.h" - -class GridState -{ - public: -#ifdef TRINITY_DEBUG -#define MAGIC_TESTVAL 0xFBE823BA - GridState() { i_Magic = MAGIC_TESTVAL; } - bool checkMagic() - { - if (i_Magic != MAGIC_TESTVAL) - { - sLog.outError("!!! GridState: Magic value gone !!!"); - return false; - } - return true; - } - void setMagic() { i_Magic = MAGIC_TESTVAL; } - unsigned int i_Magic; -#endif - virtual void Update(Map &, NGridType&, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const = 0; -}; - -class InvalidState : public GridState -{ - public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; -}; - -class ActiveState : public GridState -{ - public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; -}; - -class IdleState : public GridState -{ - public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; -}; - -class RemovalState : public GridState -{ - public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 &x, const uint32 &y, const uint32 &t_diff) const; -}; -#endif - diff --git a/src/server/game/Maps/Grid/ObjectGridLoader.cpp b/src/server/game/Maps/Grid/ObjectGridLoader.cpp deleted file mode 100644 index ab69d9a966b..00000000000 --- a/src/server/game/Maps/Grid/ObjectGridLoader.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ObjectGridLoader.h" -#include "ObjectAccessor.h" -#include "ObjectMgr.h" -#include "Creature.h" -#include "Vehicle.h" -#include "GameObject.h" -#include "DynamicObject.h" -#include "Corpse.h" -#include "World.h" -#include "CellImpl.h" -#include "CreatureAI.h" - -class ObjectGridRespawnMover -{ - public: - ObjectGridRespawnMover() {} - - void Move(GridType &grid); - - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &m); -}; - -void -ObjectGridRespawnMover::Move(GridType &grid) -{ - TypeContainerVisitor mover(*this); - grid.Visit(mover); -} - -void -ObjectGridRespawnMover::Visit(CreatureMapType &m) -{ - // creature in unloading grid can have respawn point in another grid - // if it will be unloaded then it will not respawn in original grid until unload/load original grid - // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn. - for (CreatureMapType::iterator iter = m.begin(); iter != m.end();) - { - Creature * c = iter->getSource(); - ++iter; - - assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); - - Cell const& cur_cell = c->GetCurrentCell(); - - float resp_x, resp_y, resp_z; - c->GetRespawnCoord(resp_x, resp_y, resp_z); - CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y); - Cell resp_cell(resp_val); - - if (cur_cell.DiffGrid(resp_cell)) - { - c->GetMap()->CreatureRespawnRelocation(c); - // false result ignored: will be unload with other creatures at grid - } - } -} - -// for loading world object at grid loading (Corpses) -class ObjectWorldLoader -{ - public: - explicit ObjectWorldLoader(ObjectGridLoader& gloader) - : i_cell(gloader.i_cell), i_grid(gloader.i_grid), i_map(gloader.i_map), i_corpses (0) - {} - - void Visit(CorpseMapType &m); - - template void Visit(GridRefManager&) { } - - private: - Cell i_cell; - NGridType &i_grid; - Map* i_map; - public: - uint32 i_corpses; -}; - -template void addUnitState(T* /*obj*/, CellPair const& /*cell_pair*/) -{ -} - -template<> void addUnitState(Creature *obj, CellPair const& cell_pair) -{ - Cell cell(cell_pair); - - obj->SetCurrentCell(cell); - if (obj->isSpiritService()) - obj->setDeathState(DEAD); -} - -template -void AddObjectHelper(CellPair &cell, GridRefManager &m, uint32 &count, Map* map, T *obj) -{ - obj->GetGridRef().link(&m, obj); - addUnitState(obj,cell); - obj->AddToWorld(); - if (obj->isActiveObject()) - map->AddToActive(obj); - - ++count; -} - -template -void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager &m, uint32 &count, Map* map) -{ - for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) - { - T* obj = new T; - uint32 guid = *i_guid; - //sLog.outString("DEBUG: LoadHelper from table: %s for (guid: %u) Loading",table,guid); - if (!obj->LoadFromDB(guid, map)) - { - delete obj; - continue; - } - - AddObjectHelper(cell, m, count, map, obj); - } -} - -void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map) -{ - if (cell_corpses.empty()) - return; - - for (CellCorpseSet::const_iterator itr = cell_corpses.begin(); itr != cell_corpses.end(); ++itr) - { - if (itr->second != map->GetInstanceId()) - continue; - - uint32 player_guid = itr->first; - - Corpse *obj = ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid); - if (!obj) - continue; - - // TODO: this is a hack - // corpse's map should be reset when the map is unloaded - // but it may still exist when the grid is unloaded but map is not - // in that case map == currMap - obj->SetMap(map); - - AddObjectHelper(cell, m, count, map, obj); - } -} - -void -ObjectGridLoader::Visit(GameObjectMapType &m) -{ - uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); - uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); - CellPair cell_pair(x,y); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); - - LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map); -} - -void -ObjectGridLoader::Visit(CreatureMapType &m) -{ - uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); - uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); - CellPair cell_pair(x,y); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); - - LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map); -} - -void -ObjectWorldLoader::Visit(CorpseMapType &m) -{ - uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX(); - uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY(); - CellPair cell_pair(x,y); - uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - - // corpses are always added to spawn mode 0 and they are spawned by their instance id - CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id); - LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map); -} - -void -ObjectGridLoader::Load(GridType &grid) -{ - { - TypeContainerVisitor loader(*this); - grid.Visit(loader); - } - - { - ObjectWorldLoader wloader(*this); - TypeContainerVisitor loader(wloader); - grid.Visit(loader); - i_corpses = wloader.i_corpses; - } -} - -void ObjectGridLoader::LoadN(void) -{ - i_gameObjects = 0; i_creatures = 0; i_corpses = 0; - i_cell.data.Part.cell_y = 0; - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - i_cell.data.Part.cell_x = x; - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - i_cell.data.Part.cell_y = y; - GridLoader loader; - loader.Load(i_grid(x, y), *this); - } - } - sLog.outDebug("%u GameObjects, %u Creatures, and %u Corpses/Bones loaded for grid %u on map %u", i_gameObjects, i_creatures, i_corpses,i_grid.GetGridId(), i_map->GetId()); -} - -void ObjectGridUnloader::MoveToRespawnN() -{ - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - ObjectGridRespawnMover mover; - mover.Move(i_grid(x, y)); - } - } -} - -void -ObjectGridUnloader::Unload(GridType &grid) -{ - TypeContainerVisitor unloader(*this); - grid.Visit(unloader); -} - -template -void -ObjectGridUnloader::Visit(GridRefManager &m) -{ - while (!m.isEmpty()) - { - T *obj = m.getFirst()->getSource(); - // if option set then object already saved at this moment - if (!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) - obj->SaveRespawnTime(); - ///- object will get delinked from the manager when deleted - delete obj; - } -} - -void -ObjectGridStoper::Stop(GridType &grid) -{ - TypeContainerVisitor stoper(*this); - grid.Visit(stoper); -} - -void -ObjectGridStoper::Visit(CreatureMapType &m) -{ - // stop any fights at grid de-activation and remove dynobjects created at cast by creatures - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - iter->getSource()->RemoveAllDynObjects(); - if (iter->getSource()->isInCombat()) - { - iter->getSource()->CombatStop(); - iter->getSource()->DeleteThreatList(); - iter->getSource()->AI()->EnterEvadeMode(); - } - } -} - -void -ObjectGridCleaner::Stop(GridType &grid) -{ - TypeContainerVisitor stoper(*this); - grid.Visit(stoper); -} - -void -ObjectGridCleaner::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - iter->getSource()->CleanupsBeforeDelete(); -} - -template -void -ObjectGridCleaner::Visit(GridRefManager &m) -{ - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - iter->getSource()->RemoveFromWorld(); -} - -template void ObjectGridUnloader::Visit(CreatureMapType &); -template void ObjectGridUnloader::Visit(GameObjectMapType &); -template void ObjectGridUnloader::Visit(DynamicObjectMapType &); -template void ObjectGridUnloader::Visit(CorpseMapType &); -template void ObjectGridCleaner::Visit(GameObjectMapType &); -template void ObjectGridCleaner::Visit(DynamicObjectMapType &); -template void ObjectGridCleaner::Visit(CorpseMapType &); diff --git a/src/server/game/Maps/Grid/ObjectGridLoader.h b/src/server/game/Maps/Grid/ObjectGridLoader.h deleted file mode 100644 index e890bf8d482..00000000000 --- a/src/server/game/Maps/Grid/ObjectGridLoader.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_OBJECTGRIDLOADER_H -#define TRINITY_OBJECTGRIDLOADER_H - -#include "Utilities/TypeList.h" -#include "Platform/Define.h" -#include "GameSystem/GridLoader.h" -#include "GridDefines.h" -#include "Cell.h" - -class ObjectWorldLoader; - -class ObjectGridLoader -{ - friend class ObjectWorldLoader; - - public: - ObjectGridLoader(NGridType &grid, Map* map, const Cell &cell) - : i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses (0) - {} - - void Load(GridType &grid); - void Visit(GameObjectMapType &m); - void Visit(CreatureMapType &m); - void Visit(CorpseMapType &) {} - - void Visit(DynamicObjectMapType&) { } - - void LoadN(void); - - private: - Cell i_cell; - NGridType &i_grid; - Map* i_map; - uint32 i_gameObjects; - uint32 i_creatures; - uint32 i_corpses; -}; - -class ObjectGridUnloader -{ - public: - ObjectGridUnloader(NGridType &grid) : i_grid(grid) {} - - void MoveToRespawnN(); - void UnloadN() - { - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - GridLoader loader; - loader.Unload(i_grid(x, y), *this); - } - } - } - - void Unload(GridType &grid); - template void Visit(GridRefManager &m); - private: - NGridType &i_grid; -}; - -class ObjectGridStoper -{ - public: - ObjectGridStoper(NGridType &grid) : i_grid(grid) {} - - void StopN() - { - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - GridLoader loader; - loader.Stop(i_grid(x, y), *this); - } - } - } - - void Stop(GridType &grid); - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - private: - NGridType &i_grid; -}; - -class ObjectGridCleaner -{ - public: - ObjectGridCleaner(NGridType &grid) : i_grid(grid) {} - - void CleanN() - { - for (unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x) - { - for (unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y) - { - GridLoader loader; - loader.Stop(i_grid(x, y), *this); - } - } - } - - void Stop(GridType &grid); - void Visit(CreatureMapType &m); - template void Visit(GridRefManager &); - private: - NGridType &i_grid; -}; - -typedef GridLoader GridLoaderType; -#endif - -- cgit v1.2.3 From 22950963e908017eefaccf0592feed29238f943b Mon Sep 17 00:00:00 2001 From: XTZGZoReX Date: Sun, 6 Jun 2010 23:44:21 +0200 Subject: * Get rid of framework and move the files to game and shared. --HG-- branch : trunk --- src/server/framework/CMakeLists.txt | 11 - src/server/framework/Dynamic/FactoryHolder.h | 63 - src/server/framework/Dynamic/ObjectRegistry.h | 111 -- src/server/framework/GameSystem/Grid.h | 143 --- src/server/framework/GameSystem/GridLoader.h | 79 -- src/server/framework/GameSystem/GridRefManager.h | 44 - src/server/framework/GameSystem/GridReference.h | 55 - src/server/framework/GameSystem/NGrid.h | 189 --- src/server/framework/GameSystem/TypeContainer.h | 126 -- .../framework/GameSystem/TypeContainerFunctions.h | 116 -- .../GameSystem/TypeContainerFunctionsPtr.h | 170 --- .../framework/GameSystem/TypeContainerVisitor.h | 119 -- src/server/framework/Network/SocketDefines.h | 49 - src/server/framework/Platform/CompilerDefs.h | 64 - src/server/framework/Platform/Define.h | 85 -- src/server/framework/Policies/CreationPolicy.h | 110 -- src/server/framework/Policies/ObjectLifeTime.cpp | 36 - src/server/framework/Policies/ObjectLifeTime.h | 53 - src/server/framework/Policies/Singleton.h | 65 -- src/server/framework/Policies/SingletonImp.h | 93 -- src/server/framework/Policies/ThreadingModel.h | 130 --- src/server/framework/Utilities/ByteConverter.h | 66 -- src/server/framework/Utilities/Callback.h | 386 ------ .../Utilities/CountedReference/Reference.h | 100 -- .../Utilities/CountedReference/ReferenceHolder.h | 42 - .../Utilities/CountedReference/ReferenceImpl.h | 133 --- src/server/framework/Utilities/EventProcessor.cpp | 101 -- src/server/framework/Utilities/EventProcessor.h | 73 -- src/server/framework/Utilities/LinkedList.h | 247 ---- .../Utilities/LinkedReference/RefManager.h | 58 - .../Utilities/LinkedReference/Reference.h | 94 -- src/server/framework/Utilities/TypeList.h | 46 - src/server/framework/Utilities/UnorderedMap.h | 73 -- src/server/game/Grids/Cell.h | 177 --- src/server/game/Grids/CellImpl.h | 297 ----- src/server/game/Grids/Cells/Cell.h | 177 +++ src/server/game/Grids/Cells/CellImpl.h | 297 +++++ src/server/game/Grids/Grid.h | 143 +++ src/server/game/Grids/GridLoader.h | 79 ++ src/server/game/Grids/GridNotifiers.cpp | 353 ------ src/server/game/Grids/GridNotifiers.h | 1232 -------------------- src/server/game/Grids/GridNotifiersImpl.h | 453 ------- src/server/game/Grids/GridRefManager.h | 44 + src/server/game/Grids/GridReference.h | 55 + src/server/game/Grids/NGrid.h | 189 +++ src/server/game/Grids/Notifiers/GridNotifiers.cpp | 353 ++++++ src/server/game/Grids/Notifiers/GridNotifiers.h | 1232 ++++++++++++++++++++ .../game/Grids/Notifiers/GridNotifiersImpl.h | 453 +++++++ src/server/shared/CompilerDefs.h | 64 + src/server/shared/Define.h | 85 ++ .../shared/Dynamic/CountedReference/Reference.h | 100 ++ .../Dynamic/CountedReference/ReferenceHolder.h | 42 + .../Dynamic/CountedReference/ReferenceImpl.h | 133 +++ src/server/shared/Dynamic/FactoryHolder.h | 63 + src/server/shared/Dynamic/LinkedList.h | 247 ++++ .../shared/Dynamic/LinkedReference/RefManager.h | 58 + .../shared/Dynamic/LinkedReference/Reference.h | 94 ++ src/server/shared/Dynamic/ObjectRegistry.h | 111 ++ src/server/shared/Dynamic/TypeContainer.h | 126 ++ src/server/shared/Dynamic/TypeContainerFunctions.h | 116 ++ .../shared/Dynamic/TypeContainerFunctionsPtr.h | 170 +++ src/server/shared/Dynamic/TypeContainerVisitor.h | 119 ++ src/server/shared/Dynamic/TypeList.h | 46 + src/server/shared/Dynamic/UnorderedMap.h | 73 ++ src/server/shared/Policies/CreationPolicy.h | 110 ++ src/server/shared/Policies/ObjectLifeTime.cpp | 36 + src/server/shared/Policies/ObjectLifeTime.h | 53 + src/server/shared/Policies/Singleton.h | 65 ++ src/server/shared/Policies/SingletonImp.h | 93 ++ src/server/shared/Policies/ThreadingModel.h | 130 +++ src/server/shared/Threading/Callback.h | 386 ++++++ src/server/shared/Utilities/ByteConverter.h | 66 ++ src/server/shared/Utilities/EventProcessor.cpp | 101 ++ src/server/shared/Utilities/EventProcessor.h | 73 ++ .../worldserver/RemoteAccess/SocketDefines.h | 49 + 75 files changed, 5831 insertions(+), 5842 deletions(-) delete mode 100644 src/server/framework/CMakeLists.txt delete mode 100644 src/server/framework/Dynamic/FactoryHolder.h delete mode 100644 src/server/framework/Dynamic/ObjectRegistry.h delete mode 100644 src/server/framework/GameSystem/Grid.h delete mode 100644 src/server/framework/GameSystem/GridLoader.h delete mode 100644 src/server/framework/GameSystem/GridRefManager.h delete mode 100644 src/server/framework/GameSystem/GridReference.h delete mode 100644 src/server/framework/GameSystem/NGrid.h delete mode 100644 src/server/framework/GameSystem/TypeContainer.h delete mode 100644 src/server/framework/GameSystem/TypeContainerFunctions.h delete mode 100644 src/server/framework/GameSystem/TypeContainerFunctionsPtr.h delete mode 100644 src/server/framework/GameSystem/TypeContainerVisitor.h delete mode 100644 src/server/framework/Network/SocketDefines.h delete mode 100644 src/server/framework/Platform/CompilerDefs.h delete mode 100644 src/server/framework/Platform/Define.h delete mode 100644 src/server/framework/Policies/CreationPolicy.h delete mode 100644 src/server/framework/Policies/ObjectLifeTime.cpp delete mode 100644 src/server/framework/Policies/ObjectLifeTime.h delete mode 100644 src/server/framework/Policies/Singleton.h delete mode 100644 src/server/framework/Policies/SingletonImp.h delete mode 100644 src/server/framework/Policies/ThreadingModel.h delete mode 100644 src/server/framework/Utilities/ByteConverter.h delete mode 100644 src/server/framework/Utilities/Callback.h delete mode 100644 src/server/framework/Utilities/CountedReference/Reference.h delete mode 100644 src/server/framework/Utilities/CountedReference/ReferenceHolder.h delete mode 100644 src/server/framework/Utilities/CountedReference/ReferenceImpl.h delete mode 100644 src/server/framework/Utilities/EventProcessor.cpp delete mode 100644 src/server/framework/Utilities/EventProcessor.h delete mode 100644 src/server/framework/Utilities/LinkedList.h delete mode 100644 src/server/framework/Utilities/LinkedReference/RefManager.h delete mode 100644 src/server/framework/Utilities/LinkedReference/Reference.h delete mode 100644 src/server/framework/Utilities/TypeList.h delete mode 100644 src/server/framework/Utilities/UnorderedMap.h delete mode 100644 src/server/game/Grids/Cell.h delete mode 100644 src/server/game/Grids/CellImpl.h create mode 100644 src/server/game/Grids/Cells/Cell.h create mode 100644 src/server/game/Grids/Cells/CellImpl.h create mode 100644 src/server/game/Grids/Grid.h create mode 100644 src/server/game/Grids/GridLoader.h delete mode 100644 src/server/game/Grids/GridNotifiers.cpp delete mode 100644 src/server/game/Grids/GridNotifiers.h delete mode 100644 src/server/game/Grids/GridNotifiersImpl.h create mode 100644 src/server/game/Grids/GridRefManager.h create mode 100644 src/server/game/Grids/GridReference.h create mode 100644 src/server/game/Grids/NGrid.h create mode 100644 src/server/game/Grids/Notifiers/GridNotifiers.cpp create mode 100644 src/server/game/Grids/Notifiers/GridNotifiers.h create mode 100644 src/server/game/Grids/Notifiers/GridNotifiersImpl.h create mode 100644 src/server/shared/CompilerDefs.h create mode 100644 src/server/shared/Define.h create mode 100644 src/server/shared/Dynamic/CountedReference/Reference.h create mode 100644 src/server/shared/Dynamic/CountedReference/ReferenceHolder.h create mode 100644 src/server/shared/Dynamic/CountedReference/ReferenceImpl.h create mode 100644 src/server/shared/Dynamic/FactoryHolder.h create mode 100644 src/server/shared/Dynamic/LinkedList.h create mode 100644 src/server/shared/Dynamic/LinkedReference/RefManager.h create mode 100644 src/server/shared/Dynamic/LinkedReference/Reference.h create mode 100644 src/server/shared/Dynamic/ObjectRegistry.h create mode 100644 src/server/shared/Dynamic/TypeContainer.h create mode 100644 src/server/shared/Dynamic/TypeContainerFunctions.h create mode 100644 src/server/shared/Dynamic/TypeContainerFunctionsPtr.h create mode 100644 src/server/shared/Dynamic/TypeContainerVisitor.h create mode 100644 src/server/shared/Dynamic/TypeList.h create mode 100644 src/server/shared/Dynamic/UnorderedMap.h create mode 100644 src/server/shared/Policies/CreationPolicy.h create mode 100644 src/server/shared/Policies/ObjectLifeTime.cpp create mode 100644 src/server/shared/Policies/ObjectLifeTime.h create mode 100644 src/server/shared/Policies/Singleton.h create mode 100644 src/server/shared/Policies/SingletonImp.h create mode 100644 src/server/shared/Policies/ThreadingModel.h create mode 100644 src/server/shared/Threading/Callback.h create mode 100644 src/server/shared/Utilities/ByteConverter.h create mode 100644 src/server/shared/Utilities/EventProcessor.cpp create mode 100644 src/server/shared/Utilities/EventProcessor.h create mode 100644 src/server/worldserver/RemoteAccess/SocketDefines.h (limited to 'src/server') diff --git a/src/server/framework/CMakeLists.txt b/src/server/framework/CMakeLists.txt deleted file mode 100644 index 76a256f3c5a..00000000000 --- a/src/server/framework/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -SET(trinityframework_STAT_SRCS - Policies/ObjectLifeTime.cpp - Utilities/EventProcessor.cpp -) - -include_directories( - ${ACE_INCLUDE_DIR} - ${CMAKE_SOURCE_DIR}/src/server/framework -) - -add_library(trinityframework STATIC ${trinityframework_STAT_SRCS}) diff --git a/src/server/framework/Dynamic/FactoryHolder.h b/src/server/framework/Dynamic/FactoryHolder.h deleted file mode 100644 index 282968d6097..00000000000 --- a/src/server/framework/Dynamic/FactoryHolder.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_FACTORY_HOLDER -#define TRINITY_FACTORY_HOLDER - -#include "Platform/Define.h" -#include "Utilities/TypeList.h" -#include "ObjectRegistry.h" -#include "Policies/SingletonImp.h" - -/** FactoryHolder holds a factory object of a specific type - */ -template -class FactoryHolder -{ - public: - typedef ObjectRegistry, Key > FactoryHolderRegistry; - typedef Trinity::Singleton FactoryHolderRepository; - - FactoryHolder(Key k) : i_key(k) {} - virtual ~FactoryHolder() {} - inline Key key() const { return i_key; } - - void RegisterSelf(void) { FactoryHolderRepository::Instance().InsertItem(this, i_key); } - void DeregisterSelf(void) { FactoryHolderRepository::Instance().RemoveItem(this, false); } - - /// Abstract Factory create method - virtual T* Create(void *data = NULL) const = 0; - private: - Key i_key; -}; - -/** Permissible is a classic way of letting the object decide - * whether how good they handle things. This is not retricted - * to factory selectors. - */ -template -class Permissible -{ - public: - virtual ~Permissible() {} - virtual int Permit(const T *) const = 0; -}; -#endif - diff --git a/src/server/framework/Dynamic/ObjectRegistry.h b/src/server/framework/Dynamic/ObjectRegistry.h deleted file mode 100644 index e6619427885..00000000000 --- a/src/server/framework/Dynamic/ObjectRegistry.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_OBJECTREGISTRY_H -#define TRINITY_OBJECTREGISTRY_H - -#include "Platform/Define.h" -#include "Utilities/UnorderedMap.h" -#include "Policies/Singleton.h" - -#include -#include -#include - -/** ObjectRegistry holds all registry item of the same type - */ -template -class ObjectRegistry -{ - public: - typedef std::map RegistryMapType; - - /// Returns a registry item - const T* GetRegistryItem(Key key) const - { - typename RegistryMapType::const_iterator iter = i_registeredObjects.find(key); - return( iter == i_registeredObjects.end() ? NULL : iter->second ); - } - - /// Inserts a registry item - bool InsertItem(T *obj, Key key, bool override = false) - { - typename RegistryMapType::iterator iter = i_registeredObjects.find(key); - if( iter != i_registeredObjects.end() ) - { - if( !override ) - return false; - delete iter->second; - i_registeredObjects.erase(iter); - } - - i_registeredObjects[key] = obj; - return true; - } - - /// Removes a registry item - void RemoveItem(Key key, bool delete_object = true) - { - typename RegistryMapType::iterator iter = i_registeredObjects.find(key); - if( iter != i_registeredObjects.end() ) - { - if( delete_object ) - delete iter->second; - i_registeredObjects.erase(iter); - } - } - - /// Returns true if registry contains an item - bool HasItem(Key key) const - { - return (i_registeredObjects.find(key) != i_registeredObjects.end()); - } - - /// Inefficiently return a vector of registered items - unsigned int GetRegisteredItems(std::vector &l) const - { - unsigned int sz = l.size(); - l.resize(sz + i_registeredObjects.size()); - for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) - l[sz++] = iter->first; - return i_registeredObjects.size(); - } - - /// Return the map of registered items - RegistryMapType const &GetRegisteredItems() const - { - return i_registeredObjects; - } - - private: - RegistryMapType i_registeredObjects; - friend class Trinity::OperatorNew >; - - // protected for friend use since it should be a singleton - ObjectRegistry() {} - ~ObjectRegistry() - { - for (typename RegistryMapType::iterator iter=i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) - delete iter->second; - i_registeredObjects.clear(); - } -}; -#endif - diff --git a/src/server/framework/GameSystem/Grid.h b/src/server/framework/GameSystem/Grid.h deleted file mode 100644 index 65bf3c92f9d..00000000000 --- a/src/server/framework/GameSystem/Grid.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRID_H -#define TRINITY_GRID_H - -/* - @class Grid - Grid is a logical segment of the game world represented inside TrinIty. - Grid is bind at compile time to a particular type of object which - we call it the object of interested. There are many types of loader, - specially, dynamic loader, static loader, or on-demand loader. There's - a subtle difference between dynamic loader and on-demand loader but - this is implementation specific to the loader class. From the - Grid's perspective, the loader meets its API requirement is suffice. -*/ - -#include "Platform/Define.h" -#include "Policies/ThreadingModel.h" -#include "TypeContainer.h" -#include "TypeContainerVisitor.h" - -// forward declaration -template class GridLoader; - -template -< -class ACTIVE_OBJECT, -class WORLD_OBJECT_TYPES, -class GRID_OBJECT_TYPES, -class ThreadModel = Trinity::SingleThreaded -> -class Grid -{ - // allows the GridLoader to access its internals - template friend class GridLoader; - public: - - /** destructor to clean up its resources. This includes unloading the - grid if it has not been unload. - */ - ~Grid() {} - - /** an object of interested enters the grid - */ - template void AddWorldObject(SPECIFIC_OBJECT *obj) - { - if(!i_objects.template insert(obj)) - assert(false); - } - - /** an object of interested exits the grid - */ - template void RemoveWorldObject(SPECIFIC_OBJECT *obj) - { - if(!i_objects.template remove(obj)) - assert(false); - } - - /** Refreshes/update the grid. This required for remote grids. - */ - void RefreshGrid(void) { /* TBI */} - - /** Locks a grid. Any object enters must wait until the grid is unlock. - */ - void LockGrid(void) { /* TBI */ } - - /** Unlocks the grid. - */ - void UnlockGrid(void) { /* TBI */ } - - /** Grid visitor for grid objects - */ - template void Visit(TypeContainerVisitor > &visitor) - { - visitor.Visit(i_container); - } - - /** Grid visitor for world objects - */ - template void Visit(TypeContainerVisitor > &visitor) - { - visitor.Visit(i_objects); - } - - /** Returns the number of object within the grid. - */ - unsigned int ActiveObjectsInGrid(void) const { return /*m_activeGridObjects.size()+*/i_objects.template Count(); } - - /** Inserts a container type object into the grid. - */ - template void AddGridObject(SPECIFIC_OBJECT *obj) - { - if(!i_container.template insert(obj)) - assert(false); - } - - /** Removes a containter type object from the grid - */ - template void RemoveGridObject(SPECIFIC_OBJECT *obj) - { - if(!i_container.template remove(obj)) - assert(false); - } - - /*bool NoWorldObjectInGrid() const - { - return i_objects.GetElements().isEmpty(); - } - - bool NoGridObjectInGrid() const - { - return i_container.GetElements().isEmpty(); - }*/ - private: - - typedef typename ThreadModel::Lock Guard; - typedef typename ThreadModel::VolatileType VolatileType; - - TypeMapContainer i_container; - TypeMapContainer i_objects; - //typedef std::set ActiveGridObjects; - //ActiveGridObjects m_activeGridObjects; -}; -#endif - diff --git a/src/server/framework/GameSystem/GridLoader.h b/src/server/framework/GameSystem/GridLoader.h deleted file mode 100644 index 03fa0f5b813..00000000000 --- a/src/server/framework/GameSystem/GridLoader.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDLOADER_H -#define TRINITY_GRIDLOADER_H - -/** - @class GridLoader - The GridLoader is working in conjuction with the Grid and responsible - for loading and unloading object-types (one or more) when objects - enters a grid. Unloading is scheduled and might be canceled if - an interested object re-enters. GridLoader does not do the actuall - loading and unloading but implements as a template pattern that - delicate its loading and unloading for the actualy loader and unloader. - GridLoader manages the grid (both local and remote). - */ - -#include "Platform/Define.h" -#include "Grid.h" -#include "TypeContainerVisitor.h" - -template -< -class ACTIVE_OBJECT, -class WORLD_OBJECT_TYPES, -class GRID_OBJECT_TYPES -> -class GridLoader -{ - public: - - /** Loads the grid - */ - template - void Load(Grid &grid, LOADER &loader) - { - grid.LockGrid(); - loader.Load(grid); - grid.UnlockGrid(); - } - - /** Stop the grid - */ - template - void Stop(Grid &grid, STOPER &stoper) - { - grid.LockGrid(); - stoper.Stop(grid); - grid.UnlockGrid(); - } - /** Unloads the grid - */ - template - void Unload(Grid &grid, UNLOADER &unloader) - { - grid.LockGrid(); - unloader.Unload(grid); - grid.UnlockGrid(); - } -}; -#endif - diff --git a/src/server/framework/GameSystem/GridRefManager.h b/src/server/framework/GameSystem/GridRefManager.h deleted file mode 100644 index 79799105fb7..00000000000 --- a/src/server/framework/GameSystem/GridRefManager.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _GRIDREFMANAGER -#define _GRIDREFMANAGER - -#include "Utilities/LinkedReference/RefManager.h" - -template -class GridReference; - -template -class GridRefManager : public RefManager, OBJECT> -{ - public: - typedef LinkedListHead::Iterator< GridReference > iterator; - - GridReference* getFirst() { return (GridReference*)RefManager, OBJECT>::getFirst(); } - GridReference* getLast() { return (GridReference*)RefManager, OBJECT>::getLast(); } - - iterator begin() { return iterator(getFirst()); } - iterator end() { return iterator(NULL); } - iterator rbegin() { return iterator(getLast()); } - iterator rend() { return iterator(NULL); } -}; -#endif - diff --git a/src/server/framework/GameSystem/GridReference.h b/src/server/framework/GameSystem/GridReference.h deleted file mode 100644 index d2e3a455895..00000000000 --- a/src/server/framework/GameSystem/GridReference.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _GRIDREFERENCE_H -#define _GRIDREFERENCE_H - -#include "Utilities/LinkedReference/Reference.h" - -template -class GridRefManager; - -template -class GridReference : public Reference, OBJECT> -{ - protected: - void targetObjectBuildLink() - { - // called from link() - this->getTarget()->insertFirst(this); - this->getTarget()->incSize(); - } - void targetObjectDestroyLink() - { - // called from unlink() - if(this->isValid()) this->getTarget()->decSize(); - } - void sourceObjectDestroyLink() - { - // called from invalidate() - this->getTarget()->decSize(); - } - public: - GridReference() : Reference, OBJECT>() {} - ~GridReference() { this->unlink(); } - GridReference *next() { return (GridReference*)Reference, OBJECT>::next(); } -}; -#endif - diff --git a/src/server/framework/GameSystem/NGrid.h b/src/server/framework/GameSystem/NGrid.h deleted file mode 100644 index 3810286e123..00000000000 --- a/src/server/framework/GameSystem/NGrid.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_NGRID_H -#define TRINITY_NGRID_H - -/** NGrid is nothing more than a wrapper of the Grid with an NxN cells - */ - -#include "GameSystem/Grid.h" -#include "GameSystem/GridReference.h" -#include "Timer.h" -#include "Util.h" - -#define DEFAULT_VISIBILITY_NOTIFY_PERIOD 1000 - -class GridInfo -{ -public: - GridInfo() - : i_timer(0), i_unloadActiveLockCount(0), i_unloadExplicitLock(false), i_unloadReferenceLock(false), - vis_Update(0, irand(0,DEFAULT_VISIBILITY_NOTIFY_PERIOD)) {} - GridInfo(time_t expiry, bool unload = true ) - : i_timer(expiry), i_unloadActiveLockCount(0), i_unloadExplicitLock(!unload), i_unloadReferenceLock(false), - vis_Update(0, irand(0,DEFAULT_VISIBILITY_NOTIFY_PERIOD)) {} - const TimeTracker& getTimeTracker() const { return i_timer; } - bool getUnloadLock() const { return i_unloadActiveLockCount || i_unloadExplicitLock || i_unloadReferenceLock; } - void setUnloadExplicitLock( bool on ) { i_unloadExplicitLock = on; } - void setUnloadReferenceLock( bool on ) { i_unloadReferenceLock = on; } - void incUnloadActiveLock() { ++i_unloadActiveLockCount; } - void decUnloadActiveLock() { if(i_unloadActiveLockCount) --i_unloadActiveLockCount; } - - void setTimer(const TimeTracker& pTimer) { i_timer = pTimer; } - void ResetTimeTracker(time_t interval) { i_timer.Reset(interval); } - void UpdateTimeTracker(time_t diff) { i_timer.Update(diff); } - PeriodicTimer& getRelocationTimer() { return vis_Update; } -private: - TimeTracker i_timer; - PeriodicTimer vis_Update; - - uint16 i_unloadActiveLockCount : 16; // lock from active object spawn points (prevent clone loading) - bool i_unloadExplicitLock : 1; // explicit manual lock or config setting - bool i_unloadReferenceLock : 1; // lock from instance map copy -}; - -typedef enum -{ - GRID_STATE_INVALID = 0, - GRID_STATE_ACTIVE = 1, - GRID_STATE_IDLE = 2, - GRID_STATE_REMOVAL= 3, - MAX_GRID_STATE = 4 -} grid_state_t; - -template -< -unsigned int N, -class ACTIVE_OBJECT, -class WORLD_OBJECT_TYPES, -class GRID_OBJECT_TYPES, -class ThreadModel = Trinity::SingleThreaded -> -class NGrid -{ - public: - - typedef Grid GridType; - NGrid(uint32 id, int32 x, int32 y, time_t expiry, bool unload = true) - : i_gridId(id), i_x(x), i_y(y), i_cellstate(GRID_STATE_INVALID), i_GridObjectDataLoaded(false) - { - i_GridInfo = GridInfo(expiry, unload); - } - - const GridType& operator()(unsigned short x, unsigned short y) const - { - ASSERT(x < N); - ASSERT(y < N); - return i_cells[x][y]; - } - - GridType& operator()(unsigned short x, unsigned short y) - { - ASSERT(x < N); - ASSERT(y < N); - return i_cells[x][y]; - } - - const uint32& GetGridId(void) const { return i_gridId; } - void SetGridId(const uint32 id) const { i_gridId = id; } - grid_state_t GetGridState(void) const { return i_cellstate; } - void SetGridState(grid_state_t s) { i_cellstate = s; } - int32 getX() const { return i_x; } - int32 getY() const { return i_y; } - - void link(GridRefManager >* pTo) - { - i_Reference.link(pTo, this); - } - bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; } - void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; } - - GridInfo* getGridInfoRef() { return &i_GridInfo; } - const TimeTracker& getTimeTracker() const { return i_GridInfo.getTimeTracker(); } - bool getUnloadLock() const { return i_GridInfo.getUnloadLock(); } - void setUnloadExplicitLock( bool on ) { i_GridInfo.setUnloadExplicitLock(on); } - void setUnloadReferenceLock( bool on ) { i_GridInfo.setUnloadReferenceLock(on); } - void incUnloadActiveLock() { i_GridInfo.incUnloadActiveLock(); } - void decUnloadActiveLock() { i_GridInfo.decUnloadActiveLock(); } - void ResetTimeTracker(time_t interval) { i_GridInfo.ResetTimeTracker(interval); } - void UpdateTimeTracker(time_t diff) { i_GridInfo.UpdateTimeTracker(diff); } - - template void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - getGridType(x, y).AddWorldObject(obj); - } - - template void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - getGridType(x, y).RemoveWorldObject(obj); - } - - template void Visit(TypeContainerVisitor > &visitor) - { - for (unsigned int x=0; x < N; ++x) - for (unsigned int y=0; y < N; ++y) - getGridType(x, y).Visit(visitor); - } - - template void Visit(const uint32 &x, const uint32 &y, TypeContainerVisitor > &visitor) - { - getGridType(x, y).Visit(visitor); - } - - unsigned int ActiveObjectsInGrid(void) const - { - unsigned int count=0; - for (unsigned int x=0; x < N; ++x) - for (unsigned int y=0; y < N; ++y) - count += i_cells[x][y].ActiveObjectsInGrid(); - return count; - } - - template bool AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - return getGridType(x, y).AddGridObject(obj); - } - - template bool RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - return getGridType(x, y).RemoveGridObject(obj); - } - - private: - - GridType& getGridType(const uint32& x, const uint32& y) - { - ASSERT(x < N); - ASSERT(y < N); - return i_cells[x][y]; - } - - uint32 i_gridId; - GridInfo i_GridInfo; - GridReference > i_Reference; - int32 i_x; - int32 i_y; - grid_state_t i_cellstate; - GridType i_cells[N][N]; - bool i_GridObjectDataLoaded; -}; -#endif - diff --git a/src/server/framework/GameSystem/TypeContainer.h b/src/server/framework/GameSystem/TypeContainer.h deleted file mode 100644 index c2c9b4fcdea..00000000000 --- a/src/server/framework/GameSystem/TypeContainer.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_TYPECONTAINER_H -#define TRINITY_TYPECONTAINER_H - -/* - * Here, you'll find a series of containers that allow you to hold multiple - * types of object at the same time. - */ - -#include -#include -#include "Platform/Define.h" -#include "Utilities/TypeList.h" -#include "GameSystem/GridRefManager.h" - -/* - * @class ContainerMapList is a mulit-type container for map elements - * By itself its meaningless but collaborate along with TypeContainers, - * it become the most powerfully container in the whole system. - */ -template struct ContainerMapList -{ - //std::map _element; - GridRefManager _element; -}; - -template<> struct ContainerMapList /* nothing is in type null */ -{ -}; -template struct ContainerMapList > -{ - ContainerMapList _elements; - ContainerMapList _TailElements; -}; - -/* - * @class ContaierArrayList is a multi-type container for - * array of elements. - */ -template struct ContainerArrayList -{ - std::vector _element; -}; - -// termination condition -template<> struct ContainerArrayList {}; -// recursion -template struct ContainerArrayList > -{ - ContainerArrayList _elements; - ContainerArrayList _TailElements; -}; - -/* - * @class ContainerList is a simple list of different types of elements - * - */ -template struct ContainerList -{ - OBJECT _element; -}; - -/* TypeNull is underfined */ -template<> struct ContainerList {}; -template struct ContainerList > -{ - ContainerList _elements; - ContainerMapList _TailElements; -}; - -#include "TypeContainerFunctions.h" - -/* - * @class TypeMapContainer contains a fixed number of types and is - * determined at compile time. This is probably the most complicated - * class and do its simplest thing, that is, holds objects - * of different types. - */ - -template -class TypeMapContainer -{ - public: - template size_t Count() const { return Trinity::Count(i_elements, (SPECIFIC_TYPE*)NULL); } - - /// inserts a specific object into the container - template bool insert(SPECIFIC_TYPE *obj) - { - SPECIFIC_TYPE* t = Trinity::Insert(i_elements, obj); - return (t != NULL); - } - - /// Removes the object from the container, and returns the removed object - template bool remove(SPECIFIC_TYPE* obj) - { - SPECIFIC_TYPE* t = Trinity::Remove(i_elements, obj); - return (t != NULL); - } - - ContainerMapList & GetElements(void) { return i_elements; } - const ContainerMapList & GetElements(void) const { return i_elements;} - - private: - ContainerMapList i_elements; -}; -#endif - diff --git a/src/server/framework/GameSystem/TypeContainerFunctions.h b/src/server/framework/GameSystem/TypeContainerFunctions.h deleted file mode 100644 index edfbb40e659..00000000000 --- a/src/server/framework/GameSystem/TypeContainerFunctions.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TYPECONTAINER_FUNCTIONS_H -#define TYPECONTAINER_FUNCTIONS_H - -/* - * Here you'll find a list of helper functions to make - * the TypeContainer usefull. Without it, its hard - * to access or mutate the container. - */ - -#include "Platform/Define.h" -#include "Utilities/TypeList.h" -#include - -namespace Trinity -{ - /* ContainerMapList Helpers */ - // count functions - template size_t Count(const ContainerMapList &elements, SPECIFIC_TYPE* /*fake*/) - { - return elements._element.getSize(); - }; - - template size_t Count(const ContainerMapList &/*elements*/, SPECIFIC_TYPE* /*fake*/) - { - return 0; - } - - template size_t Count(const ContainerMapList &/*elements*/, SPECIFIC_TYPE* /*fake*/) - { - return 0; - } - - template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) - { - return Count(elements._elements,fake); - } - - template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) - { - return Count(elements._TailElements, fake); - } - - // non-const insert functions - template SPECIFIC_TYPE* Insert(ContainerMapList &elements, SPECIFIC_TYPE *obj) - { - //elements._element[hdl] = obj; - obj->GetGridRef().link(&elements._element, obj); - return obj; - }; - - template SPECIFIC_TYPE* Insert(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/) - { - return NULL; - } - - // this is a missed - template SPECIFIC_TYPE* Insert(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/) - { - return NULL; // a missed - } - - // Recursion - template SPECIFIC_TYPE* Insert(ContainerMapList >&elements, SPECIFIC_TYPE *obj) - { - SPECIFIC_TYPE* t= Insert(elements._elements, obj); - return (t != NULL ? t : Insert(elements._TailElements, obj)); - } - - // non-const remove method - template SPECIFIC_TYPE* Remove(ContainerMapList & /*elements*/, SPECIFIC_TYPE *obj) - { - obj->GetGridRef().unlink(); - return obj; - } - - template SPECIFIC_TYPE* Remove(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/) - { - return NULL; - } - - // this is a missed - template SPECIFIC_TYPE* Remove(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/) - { - return NULL; // a missed - } - - template SPECIFIC_TYPE* Remove(ContainerMapList > &elements, SPECIFIC_TYPE *obj) - { - // The head element is bad - SPECIFIC_TYPE* t = Remove(elements._elements, obj); - return ( t != NULL ? t : Remove(elements._TailElements, obj) ); - } - -} -#endif - diff --git a/src/server/framework/GameSystem/TypeContainerFunctionsPtr.h b/src/server/framework/GameSystem/TypeContainerFunctionsPtr.h deleted file mode 100644 index 2affcc457cc..00000000000 --- a/src/server/framework/GameSystem/TypeContainerFunctionsPtr.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TYPECONTAINER_FUNCTIONS_PTR_H -#define TYPECONTAINER_FUNCTIONS_PTR_H - -/* - * Here you'll find a list of helper functions to make - * the TypeContainer usefull. Without it, its hard - * to access or mutate the container. - */ - -#include "Platform/Define.h" -#include "Utilities/TypeList.h" -#include - -namespace Trinity -{ - /* ContainerMapList Helpers */ - // count functions - // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) - // { - // return elements._element.size(); - // }; - // - // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) - // { - // return 0; - // } - // - // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) - // { - // return 0; - // } - // - // template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) - // { - // return Count(elements._elements,fake); - // } - // - // template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) - // { - // return Count(elements._TailElements, fake); - // } - - // non-const find functions - template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) - { - typename std::map >::iterator iter = elements._element.find(hdl); - return (iter == elements._element.end() ? NullPtr((SPECIFIC_TYPE*)NULL) : iter->second); - }; - - template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) - { - return NullPtr((SPECIFIC_TYPE*)NULL);// terminate recursion - } - - template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) - { - return NullPtr((SPECIFIC_TYPE*)NULL);// this is a missed - } - - template CountedPtr& Find(ContainerMapList >&elements, OBJECT_HANDLE hdl, CountedPtr* fake) - { - CountedPtr &t = Find(elements._elements, hdl,fake); - return (!t ? Find(elements._TailElements, hdl,fake) : t); - } - - // const find functions - template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) - { - typename CountedPtr::iterator iter = elements._element.find(hdl); - return (iter == elements._element.end() ? NullPtr((SPECIFIC_TYPE*)NULL) : iter->second); - }; - - template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) - { - return NullPtr((SPECIFIC_TYPE*)NULL); - } - - template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) - { - return NullPtr((SPECIFIC_TYPE*)NULL); - } - - template CountedPtr& Find(const ContainerMapList >&elements, OBJECT_HANDLE hdl, CountedPtr* fake) - { - CountedPtr &t = Find(elements._elements, hdl,fake); - if(!t) - t = Find(elements._TailElement, hdl,fake); - - return t; - } - - // non-const insert functions - template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) - { - elements._element[hdl] = obj; - return obj; - }; - - template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) - { - return NullPtr((SPECIFIC_TYPE*)NULL); - } - - // this is a missed - template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) - { - return NullPtr((SPECIFIC_TYPE*)NULL);// a missed - } - - // Recursion - template CountedPtr& Insert(ContainerMapList >&elements, CountedPtr &obj, OBJECT_HANDLE hdl) - { - CountedPtr &t= Insert(elements._elements, obj, hdl); - return (!t ? Insert(elements._TailElements, obj, hdl) : t); - } - - // non-const remove method - template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) - { - typename std::map >::iterator iter = elements._element.find(hdl); - if( iter != elements._element.end() ) - { - elements._element.erase(iter); - return true; - } - - return false; // found... terminate the search - } - - template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) - { - return false; - } - - // this is a missed - template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) - { - return false; - } - - template bool Remove(ContainerMapList > &elements, CountedPtr &obj, OBJECT_HANDLE hdl) - { - // The head element is bad - bool t = Remove(elements._elements, obj, hdl); - return ( !t ? Remove(elements._TailElements, obj, hdl) : t ); - } - -} -#endif - diff --git a/src/server/framework/GameSystem/TypeContainerVisitor.h b/src/server/framework/GameSystem/TypeContainerVisitor.h deleted file mode 100644 index f15075e5afd..00000000000 --- a/src/server/framework/GameSystem/TypeContainerVisitor.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_TYPECONTAINERVISITOR_H -#define TRINITY_TYPECONTAINERVISITOR_H - -/* - * @class TypeContainerVisitor is implemented as a visitor pattern. It is - * a visitor to the TypeContainerList or TypeContainerMapList. The visitor has - * to overload its types as a visit method is called. - */ - -#include "Platform/Define.h" -#include "TypeContainer.h" - -// forward declaration -template class TypeContainerVisitor; - -// visitor helper -template void VisitorHelper(VISITOR &v, TYPE_CONTAINER &c) -{ - v.Visit(c); -}; - -// terminate condition for container list -template void VisitorHelper(VISITOR &v, ContainerList &c) -{ -} - -template void VisitorHelper(VISITOR &v, ContainerList &c) -{ - v.Visit(c._element); -} - -// recursion for container list -template void VisitorHelper(VISITOR &v, ContainerList > &c) -{ - VisitorHelper(v, c._elements); - VisitorHelper(v, c._TailElements); -} - -// terminate condition container map list -template void VisitorHelper(VISITOR &/*v*/, ContainerMapList &/*c*/) -{ -} - -template void VisitorHelper(VISITOR &v, ContainerMapList &c) -{ - v.Visit(c._element); -} - -// recursion container map list -template void VisitorHelper(VISITOR &v, ContainerMapList > &c) -{ - VisitorHelper(v, c._elements); - VisitorHelper(v, c._TailElements); -} - -// array list -template void VisitorHelper(VISITOR &v, ContainerArrayList &c) -{ - v.Visit(c._element); -} - -template void VisitorHelper(VISITOR &/*v*/, ContainerArrayList &/*c*/) -{ -} - -// recursion -template void VisitorHelper(VISITOR &v, ContainerArrayList > &c) -{ - VisitorHelper(v, c._elements); - VisitorHelper(v, c._TailElements); -} - -// for TypeMapContainer -template void VisitorHelper(VISITOR &v, TypeMapContainer &c) -{ - VisitorHelper(v, c.GetElements()); -} - -template -class TypeContainerVisitor -{ - public: - TypeContainerVisitor(VISITOR &v) : i_visitor(v) {} - - void Visit(TYPE_CONTAINER &c) - { - VisitorHelper(i_visitor, c); - } - - void Visit(const TYPE_CONTAINER &c) const - { - VisitorHelper(i_visitor, c); - } - - private: - VISITOR &i_visitor; -}; -#endif - diff --git a/src/server/framework/Network/SocketDefines.h b/src/server/framework/Network/SocketDefines.h deleted file mode 100644 index 49366097ae6..00000000000 --- a/src/server/framework/Network/SocketDefines.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_SOCKETDEFINES_H -#define TRINITY_SOCKETDEFINES_H - -#ifdef WIN32 - -/* Windows socket definitions - */ -#define FD_SETSIZE 1024 -#include -#include - -typedef SOCKET SocketHandle; -typedef fd_set SelectSet; - -#else - -/* The unix socket definitions - */ -#include -#include -#ifdef __APPLE_CC__ -#include -#endif - -typedef int SocketHandle; -typedef fd_set SelectSet; -#endif -#endif - diff --git a/src/server/framework/Platform/CompilerDefs.h b/src/server/framework/Platform/CompilerDefs.h deleted file mode 100644 index fb7dbfe4caa..00000000000 --- a/src/server/framework/Platform/CompilerDefs.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_COMPILERDEFS_H -#define TRINITY_COMPILERDEFS_H - -#define PLATFORM_WINDOWS 0 -#define PLATFORM_UNIX 1 -#define PLATFORM_APPLE 2 -#define PLATFORM_INTEL 3 - -// must be first (win 64 also define WIN32) -#if defined( _WIN64 ) -# define PLATFORM PLATFORM_WINDOWS -#elif defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 ) -# define PLATFORM PLATFORM_WINDOWS -#elif defined( __APPLE_CC__ ) -# define PLATFORM PLATFORM_APPLE -#elif defined( __INTEL_COMPILER ) -# define PLATFORM PLATFORM_INTEL -#else -# define PLATFORM PLATFORM_UNIX -#endif - -#define COMPILER_MICROSOFT 0 -#define COMPILER_GNU 1 -#define COMPILER_BORLAND 2 -#define COMPILER_INTEL 3 - -#ifdef _MSC_VER -# define COMPILER COMPILER_MICROSOFT -#elif defined( __BORLANDC__ ) -# define COMPILER COMPILER_BORLAND -#elif defined( __INTEL_COMPILER ) -# define COMPILER COMPILER_INTEL -#elif defined( __GNUC__ ) -# define COMPILER COMPILER_GNU -#else -# pragma error "FATAL ERROR: Unknown compiler." -#endif - -#if COMPILER == COMPILER_MICROSOFT -# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data -# pragma warning( disable : 4786 ) // identifier was truncated to '255' characters in the debug information -#endif -#endif - diff --git a/src/server/framework/Platform/Define.h b/src/server/framework/Platform/Define.h deleted file mode 100644 index 9285bf289f9..00000000000 --- a/src/server/framework/Platform/Define.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_DEFINE_H -#define TRINITY_DEFINE_H - -#include - -#include -#include - -#include "Platform/CompilerDefs.h" - -#define TRINITY_LITTLEENDIAN 0 -#define TRINITY_BIGENDIAN 1 - -#if !defined(TRINITY_ENDIAN) -# if defined (ACE_BIG_ENDIAN) -# define TRINITY_ENDIAN TRINITY_BIGENDIAN -# else //ACE_BYTE_ORDER != ACE_BIG_ENDIAN -# define TRINITY_ENDIAN TRINITY_LITTLEENDIAN -# endif //ACE_BYTE_ORDER -#endif //TRINITY_ENDIAN - -#if PLATFORM == PLATFORM_WINDOWS -# define TRINITY_PATH_MAX MAX_PATH -# ifndef DECLSPEC_NORETURN -# define DECLSPEC_NORETURN __declspec(noreturn) -# endif //DECLSPEC_NORETURN -#else //PLATFORM != PLATFORM_WINDOWS -# define TRINITY_PATH_MAX PATH_MAX -# define DECLSPEC_NORETURN -#endif //PLATFORM - -#if !defined(DEBUG) -# define TRINITY_INLINE inline -#else //DEBUG -# if !defined(TRINITY_DEBUG) -# define TRINITY_DEBUG -# endif //TRINITY_DEBUG -# define TRINITY_INLINE -#endif //!DEBUG - -#if COMPILER == COMPILER_GNU -# define ATTR_NORETURN __attribute__((noreturn)) -# define ATTR_PRINTF(F,V) __attribute__ ((format (printf, F, V))) -#else //COMPILER != COMPILER_GNU -# define ATTR_NORETURN -# define ATTR_PRINTF(F,V) -#endif //COMPILER == COMPILER_GNU - -typedef ACE_INT64 int64; -typedef ACE_INT32 int32; -typedef ACE_INT16 int16; -typedef ACE_INT8 int8; -typedef ACE_UINT64 uint64; -typedef ACE_UINT32 uint32; -typedef ACE_UINT16 uint16; -typedef ACE_UINT8 uint8; - -#if COMPILER != COMPILER_MICROSOFT -typedef uint16 WORD; -typedef uint32 DWORD; -#endif //COMPILER - -typedef uint64 OBJECT_HANDLE; - -#endif //TRINITY_DEFINE_H diff --git a/src/server/framework/Policies/CreationPolicy.h b/src/server/framework/Policies/CreationPolicy.h deleted file mode 100644 index 8552ce7da52..00000000000 --- a/src/server/framework/Policies/CreationPolicy.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CREATIONPOLICY_H -#define TRINITY_CREATIONPOLICY_H - -#include -#include "Platform/Define.h" - -namespace Trinity -{ - /** - * OperatorNew policy creates an object on the heap using new. - */ - template - class OperatorNew - { - public: - static T* Create(void) { return (new T); } - static void Destroy(T *obj) { delete obj; } - }; - - /** - * LocalStaticCreation policy creates an object on the stack - * the first time call Create. - */ - template - class LocalStaticCreation - { - union MaxAlign - { - char t_[sizeof(T)]; - short int shortInt_; - int int_; - long int longInt_; - float float_; - double double_; - long double longDouble_; - struct Test; - int Test::* pMember_; - int (Test::*pMemberFn_)(int); - }; - public: - static T* Create(void) - { - static MaxAlign si_localStatic; - return new(&si_localStatic) T; - } - - static void Destroy(T *obj) { obj->~T(); } - }; - - /** - * CreateUsingMalloc by pass the memory manger. - */ - template - class CreateUsingMalloc - { - public: - static T* Create() - { - void* p = ::malloc(sizeof(T)); - if (!p) return 0; - return new(p) T; - } - - static void Destroy(T* p) - { - p->~T(); - ::free(p); - } - }; - - /** - * CreateOnCallBack creates the object base on the call back. - */ - template - class CreateOnCallBack - { - public: - static T* Create() - { - return CALL_BACK::createCallBack(); - } - - static void Destroy(T *p) - { - CALL_BACK::destroyCallBack(p); - } - }; -} -#endif - diff --git a/src/server/framework/Policies/ObjectLifeTime.cpp b/src/server/framework/Policies/ObjectLifeTime.cpp deleted file mode 100644 index fd16873ae92..00000000000 --- a/src/server/framework/Policies/ObjectLifeTime.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include "ObjectLifeTime.h" - -namespace Trinity -{ - extern "C" void external_wrapper(void *p) - { - std::atexit( (void (*)())p ); - } - - void at_exit( void (*func)() ) - { - external_wrapper((void*)func); - } -} - diff --git a/src/server/framework/Policies/ObjectLifeTime.h b/src/server/framework/Policies/ObjectLifeTime.h deleted file mode 100644 index 61b90b59f6e..00000000000 --- a/src/server/framework/Policies/ObjectLifeTime.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_OBJECTLIFETIME_H -#define TRINITY_OBJECTLIFETIME_H - -#include -#include "Platform/Define.h" - -typedef void (* Destroyer)(void); - -namespace Trinity -{ - void at_exit( void (*func)() ); - - template - class ObjectLifeTime - { - public: - static void ScheduleCall(void (*destroyer)() ) - { - at_exit( destroyer ); - } - - DECLSPEC_NORETURN static void OnDeadReference(void) ATTR_NORETURN; - - }; - - template - void ObjectLifeTime::OnDeadReference(void) // We don't handle Dead Reference for now - { - throw std::runtime_error("Dead Reference"); - } -} -#endif - diff --git a/src/server/framework/Policies/Singleton.h b/src/server/framework/Policies/Singleton.h deleted file mode 100644 index da898558ca5..00000000000 --- a/src/server/framework/Policies/Singleton.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_SINGLETON_H -#define TRINITY_SINGLETON_H - -/** - * @brief class Singleton - */ - -#include "CreationPolicy.h" -#include "ThreadingModel.h" -#include "ObjectLifeTime.h" - -namespace Trinity -{ - template - < - typename T, - class ThreadingModel = Trinity::SingleThreaded, - class CreatePolicy = Trinity::OperatorNew, - class LifeTimePolicy = Trinity::ObjectLifeTime - > - class Singleton - { - public: - static T& Instance(); - - protected: - Singleton() {}; - - private: - - // Prohibited actions...this does not prevent hijacking. - Singleton(const Singleton &); - Singleton& operator=(const Singleton &); - - // Singleton Helpers - static void DestroySingleton(); - - // data structure - typedef typename ThreadingModel::Lock Guard; - static T *si_instance; - static bool si_destroyed; - }; -} -#endif - diff --git a/src/server/framework/Policies/SingletonImp.h b/src/server/framework/Policies/SingletonImp.h deleted file mode 100644 index 3e985cd5c64..00000000000 --- a/src/server/framework/Policies/SingletonImp.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_SINGLETONIMPL_H -#define TRINITY_SINGLETONIMPL_H - -#include "Singleton.h" - -// avoid the using namespace here cuz -// its a .h file afterall - -template -< -typename T, -class ThreadingModel, -class CreatePolicy, -class LifeTimePolicy -> -T& -Trinity::Singleton::Instance() -{ - if( !si_instance ) - { - // double-checked Locking pattern - Guard(); - if( !si_instance ) - { - if( si_destroyed ) - { - si_destroyed = false; - LifeTimePolicy::OnDeadReference(); - } - si_instance = CreatePolicy::Create(); - LifeTimePolicy::ScheduleCall(&DestroySingleton); - } - } - - return *si_instance; -} - -template -< -typename T, -class ThreadingModel, -class CreatePolicy, -class LifeTimePolicy -> -void -Trinity::Singleton::DestroySingleton() -{ - CreatePolicy::Destroy(si_instance); - si_instance = NULL; - si_destroyed = true; -} - -#define INSTANTIATE_SINGLETON_1(TYPE) \ - template class Trinity::Singleton, Trinity::OperatorNew, Trinity::ObjectLifeTime >; \ - template<> TYPE* Trinity::Singleton, Trinity::OperatorNew, Trinity::ObjectLifeTime >::si_instance = 0; \ - template<> bool Trinity::Singleton, Trinity::OperatorNew, Trinity::ObjectLifeTime >::si_destroyed = false - -#define INSTANTIATE_SINGLETON_2(TYPE, THREADINGMODEL) \ - template class Trinity::Singleton, Trinity::ObjectLifeTime >; \ - template<> TYPE* Trinity::Singleton, Trinity::ObjectLifeTime >::si_instance = 0; \ - template<> bool Trinity::Singleton, Trinity::ObjectLifeTime >::si_destroyed = false - -#define INSTANTIATE_SINGLETON_3(TYPE, THREADINGMODEL, CREATIONPOLICY ) \ - template class Trinity::Singleton >; \ - template<> TYPE* Trinity::Singleton >::si_instance = 0; \ - template<> bool Trinity::Singleton >::si_destroyed = false - -#define INSTANTIATE_SINGLETON_4(TYPE, THREADINGMODEL, CREATIONPOLICY, OBJECTLIFETIME) \ - template class Trinity::Singleton; \ - template<> TYPE* Trinity::Singleton::si_instance = 0; \ - template<> bool Trinity::Singleton::si_destroyed = false -#endif - diff --git a/src/server/framework/Policies/ThreadingModel.h b/src/server/framework/Policies/ThreadingModel.h deleted file mode 100644 index d4c5e9a2333..00000000000 --- a/src/server/framework/Policies/ThreadingModel.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_THREADINGMODEL_H -#define TRINITY_THREADINGMODEL_H - -/** - * @class ThreadingModel - * - */ - -#include "Platform/Define.h" - -namespace Trinity -{ - inline void Guard(void *) {} - - template class GeneralLock - { - public: - GeneralLock(MUTEX &m) : i_mutex(m) - { - i_mutex.acquire(); - } - - ~GeneralLock() - { - i_mutex.release(); - } - private: - GeneralLock(const GeneralLock &); - GeneralLock& operator=(const GeneralLock &); - MUTEX &i_mutex; - }; - - template - class SingleThreaded - { - public: - - struct Lock // empty object - { - Lock() {} - Lock(const T &) {} - Lock(const SingleThreaded &) // for single threaded we ignore this - { - } - }; - - typedef T VolatileType; - }; - - // object level lockable - template - class ObjectLevelLockable - { - public: - ObjectLevelLockable() : i_mtx() {} - - friend class Lock; - - class Lock - { - public: - Lock(ObjectLevelLockable &host) : i_lock(host.i_mtx) - { - } - - private: - GeneralLock i_lock; - }; - - typedef volatile T VolatileType; - - private: - // prevent the compiler creating a copy construct - ObjectLevelLockable(const ObjectLevelLockable &); - ObjectLevelLockable& operator=(const ObjectLevelLockable &); - - MUTEX i_mtx; - }; - - template - class ClassLevelLockable - { - public: - class Lock; - friend class Lock; - typedef volatile T VolatileType; - - ClassLevelLockable() {} - - class Lock - { - public: - Lock(T& /*host*/) { ClassLevelLockable::si_mtx.acquire(); } - Lock(ClassLevelLockable &) { ClassLevelLockable::si_mtx.acquire(); } - Lock() { ClassLevelLockable::si_mtx.acquire(); } - ~Lock() { ClassLevelLockable::si_mtx.release(); } - }; - - private: - static MUTEX si_mtx; - }; - -} - -template MUTEX Trinity::ClassLevelLockable::si_mtx; - -#define INSTANTIATE_CLASS_MUTEX(CTYPE,MUTEX) \ - template class Trinity::ClassLevelLockable -#endif - diff --git a/src/server/framework/Utilities/ByteConverter.h b/src/server/framework/Utilities/ByteConverter.h deleted file mode 100644 index f8b6bd72498..00000000000 --- a/src/server/framework/Utilities/ByteConverter.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_BYTECONVERTER_H -#define TRINITY_BYTECONVERTER_H - -/** ByteConverter reverse your byte order. This is use - for cross platform where they have different endians. - */ - -#include -#include - -namespace ByteConverter -{ - template - inline void convert(char *val) - { - std::swap(*val, *(val + T - 1)); - convert(val + 1); - } - - template<> inline void convert<0>(char *) {} - template<> inline void convert<1>(char *) {} // ignore central byte - - template inline void apply(T *val) - { - convert((char *)(val)); - } -} - -#if TRINITY_ENDIAN == TRINITY_BIGENDIAN -template inline void EndianConvert(T& val) { ByteConverter::apply(&val); } -template inline void EndianConvertReverse(T&) { } -#else -template inline void EndianConvert(T&) { } -template inline void EndianConvertReverse(T& val) { ByteConverter::apply(&val); } -#endif - -template void EndianConvert(T*); // will generate link error -template void EndianConvertReverse(T*); // will generate link error - -inline void EndianConvert(uint8&) { } -inline void EndianConvert( int8&) { } -inline void EndianConvertReverse(uint8&) { } -inline void EndianConvertReverse( int8&) { } - -#endif - diff --git a/src/server/framework/Utilities/Callback.h b/src/server/framework/Utilities/Callback.h deleted file mode 100644 index d2e2c36851a..00000000000 --- a/src/server/framework/Utilities/Callback.h +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CALLBACK_H -#define TRINITY_CALLBACK_H - -/// ------------ BASE CLASSES ------------ - -namespace Trinity -{ - template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > - class _Callback - { - protected: - typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3, ParamType4); - Class *m_object; - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - ParamType3 m_param3; - ParamType4 m_param4; - void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3, m_param4); } - public: - _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) - : m_object(object), m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {} - _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4> const& cb) - : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {} - }; - - template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 > - class _Callback < Class, ParamType1, ParamType2, ParamType3 > - { - protected: - typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3); - Class *m_object; - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - ParamType3 m_param3; - void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3); } - public: - _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {} - _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3 > const& cb) - : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {} - }; - - template < class Class, typename ParamType1, typename ParamType2 > - class _Callback < Class, ParamType1, ParamType2 > - { - protected: - typedef void (Class::*Method)(ParamType1, ParamType2); - Class *m_object; - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - void _Execute() { (m_object->*m_method)(m_param1, m_param2); } - public: - _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2) - : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {} - _Callback(_Callback < Class, ParamType1, ParamType2 > const& cb) - : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {} - }; - - template < class Class, typename ParamType1 > - class _Callback < Class, ParamType1 > - { - protected: - typedef void (Class::*Method)(ParamType1); - Class *m_object; - Method m_method; - ParamType1 m_param1; - void _Execute() { (m_object->*m_method)(m_param1); } - public: - _Callback(Class *object, Method method, ParamType1 param1) - : m_object(object), m_method(method), m_param1(param1) {} - _Callback(_Callback < Class, ParamType1 > const& cb) - : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1) {} - }; - - template < class Class > - class _Callback < Class > - { - protected: - typedef void (Class::*Method)(); - Class *m_object; - Method m_method; - void _Execute() { (m_object->*m_method)(); } - public: - _Callback(Class *object, Method method) - : m_object(object), m_method(method) {} - _Callback(_Callback < Class > const& cb) - : m_object(cb.m_object), m_method(cb.m_method) {} - }; - - /// ---- Statics ---- - - template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > - class _SCallback - { - protected: - typedef void (*Method)(ParamType1, ParamType2, ParamType3, ParamType4); - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - ParamType3 m_param3; - ParamType4 m_param4; - void _Execute() { (*m_method)(m_param1, m_param2, m_param3, m_param4); } - public: - _SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) - : m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {} - _SCallback(_SCallback < ParamType1, ParamType2, ParamType3, ParamType4> const& cb) - : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {} - }; - - template < typename ParamType1, typename ParamType2, typename ParamType3 > - class _SCallback < ParamType1, ParamType2, ParamType3 > - { - protected: - typedef void (*Method)(ParamType1, ParamType2, ParamType3); - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - ParamType3 m_param3; - void _Execute() { (*m_method)(m_param1, m_param2, m_param3); } - public: - _SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : m_method(method), m_param1(param1), m_param2(param2), m_param3(param3) {} - _SCallback(_SCallback < ParamType1, ParamType2, ParamType3 > const& cb) - : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {} - }; - - template < typename ParamType1, typename ParamType2 > - class _SCallback < ParamType1, ParamType2 > - { - protected: - typedef void (*Method)(ParamType1, ParamType2); - Method m_method; - ParamType1 m_param1; - ParamType2 m_param2; - void _Execute() { (*m_method)(m_param1, m_param2); } - public: - _SCallback(Method method, ParamType1 param1, ParamType2 param2) - : m_method(method), m_param1(param1), m_param2(param2) {} - _SCallback(_SCallback < ParamType1, ParamType2 > const& cb) - : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {} - }; - - template < typename ParamType1 > - class _SCallback < ParamType1 > - { - protected: - typedef void (*Method)(ParamType1); - Method m_method; - ParamType1 m_param1; - void _Execute() { (*m_method)(m_param1); } - public: - _SCallback(Method method, ParamType1 param1) - : m_method(method), m_param1(param1) {} - _SCallback(_SCallback < ParamType1 > const& cb) - : m_method(cb.m_method), m_param1(cb.m_param1) {} - }; - - template < > - class _SCallback < > - { - protected: - typedef void (*Method)(); - Method m_method; - void _Execute() { (*m_method)(); } - public: - _SCallback(Method method) - : m_method(method) {} - _SCallback(_SCallback <> const& cb) - : m_method(cb.m_method) {} - }; -} - -/// --------- GENERIC CALLBACKS ---------- - -namespace Trinity -{ - class ICallback - { - public: - virtual void Execute() = 0; - virtual ~ICallback() {} - }; - - template < class CB > - class _ICallback : public CB, public ICallback - { - public: - _ICallback(CB const& cb) : CB(cb) {} - void Execute() { CB::_Execute(); } - }; - - template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > - class Callback : - public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > > - { - private: - typedef _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > C4; - public: - Callback(Class *object, typename C4::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) - : _ICallback< C4 >(C4(object, method, param1, param2, param3, param4)) {} - }; - - template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 > - class Callback < Class, ParamType1, ParamType2, ParamType3 > : - public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3 > > - { - private: - typedef _Callback < Class, ParamType1, ParamType2, ParamType3 > C3; - public: - Callback(Class *object, typename C3::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : _ICallback< C3 >(C3(object, method, param1, param2, param3)) {} - }; - - template < class Class, typename ParamType1, typename ParamType2 > - class Callback < Class, ParamType1, ParamType2 > : - public _ICallback< _Callback < Class, ParamType1, ParamType2 > > - { - private: - typedef _Callback < Class, ParamType1, ParamType2 > C2; - public: - Callback(Class *object, typename C2::Method method, ParamType1 param1, ParamType2 param2) - : _ICallback< C2 >(C2(object, method, param1, param2)) {} - }; - - template < class Class, typename ParamType1 > - class Callback < Class, ParamType1 > : - public _ICallback< _Callback < Class, ParamType1 > > - { - private: - typedef _Callback < Class, ParamType1 > C1; - public: - Callback(Class *object, typename C1::Method method, ParamType1 param1) - : _ICallback< C1 >(C1(object, method, param1)) {} - }; - - template < class Class > - class Callback < Class > : public _ICallback< _Callback < Class > > - { - private: - typedef _Callback < Class > C0; - public: - Callback(Class *object, typename C0::Method method) - : _ICallback< C0 >(C0(object, method)) {} - }; -} - -/// ---------- QUERY CALLBACKS ----------- - -#include "QueryResult.h" -class QueryResult; - -namespace Trinity -{ - class IQueryCallback - { - public: - virtual void Execute() = 0; - virtual ~IQueryCallback() {} - virtual void SetResult(QueryResult_AutoPtr result) = 0; - virtual QueryResult_AutoPtr GetResult() = 0; - }; - - template < class CB > - class _IQueryCallback : public CB, public IQueryCallback - { - public: - _IQueryCallback(CB const& cb) : CB(cb) {} - void Execute() { CB::_Execute(); } - void SetResult(QueryResult_AutoPtr result) { CB::m_param1 = result; } - QueryResult_AutoPtr GetResult() { return CB::m_param1; } - }; - - template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void > - class QueryCallback : - public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > > - { - private: - typedef _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > QC3; - public: - QueryCallback(Class *object, typename QC3::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : _IQueryCallback< QC3 >(QC3(object, method, result, param1, param2, param3)) {} - }; - - template < class Class, typename ParamType1, typename ParamType2 > - class QueryCallback < Class, ParamType1, ParamType2 > : - public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2 > > - { - private: - typedef _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2 > QC2; - public: - QueryCallback(Class *object, typename QC2::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2) - : _IQueryCallback< QC2 >(QC2(object, method, result, param1, param2)) {} - }; - - template < class Class, typename ParamType1 > - class QueryCallback < Class, ParamType1 > : - public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1 > > - { - private: - typedef _Callback < Class, QueryResult_AutoPtr, ParamType1 > QC1; - public: - QueryCallback(Class *object, typename QC1::Method method, QueryResult_AutoPtr result, ParamType1 param1) - : _IQueryCallback< QC1 >(QC1(object, method, result, param1)) {} - }; - - template < class Class > - class QueryCallback < Class > : public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr > > - { - private: - typedef _Callback < Class, QueryResult_AutoPtr > QC0; - public: - QueryCallback(Class *object, typename QC0::Method method, QueryResult_AutoPtr result) - : _IQueryCallback< QC0 >(QC0(object, method, result)) {} - }; - - /// ---- Statics ---- - - template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void > - class SQueryCallback : - public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > > - { - private: - typedef _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > QC3; - public: - SQueryCallback(typename QC3::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2, ParamType3 param3) - : _IQueryCallback< QC3 >(QC3(method, result, param1, param2, param3)) {} - }; - - template < typename ParamType1, typename ParamType2 > - class SQueryCallback < ParamType1, ParamType2 > : - public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2 > > - { - private: - typedef _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2 > QC2; - public: - SQueryCallback(typename QC2::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2) - : _IQueryCallback< QC2 >(QC2(method, result, param1, param2)) {} - }; - - template < typename ParamType1 > - class SQueryCallback < ParamType1 > : - public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1 > > - { - private: - typedef _SCallback < QueryResult_AutoPtr, ParamType1 > QC1; - public: - SQueryCallback(typename QC1::Method method, QueryResult_AutoPtr result, ParamType1 param1) - : _IQueryCallback< QC1 >(QC1(method, result, param1)) {} - }; - - template < > - class SQueryCallback < > : public _IQueryCallback< _SCallback < QueryResult_AutoPtr > > - { - private: - typedef _SCallback < QueryResult_AutoPtr > QC0; - public: - SQueryCallback(QC0::Method method, QueryResult_AutoPtr result) - : _IQueryCallback< QC0 >(QC0(method, result)) {} - }; -} - -#endif - diff --git a/src/server/framework/Utilities/CountedReference/Reference.h b/src/server/framework/Utilities/CountedReference/Reference.h deleted file mode 100644 index d3cfe55ffc0..00000000000 --- a/src/server/framework/Utilities/CountedReference/Reference.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_REFERENCE_H -#define TRINITY_REFERENCE_H - -/** - * Referencer - * Referencer is an object that holds a reference holder that hold a reference - * counted object. When an object's reference count drop to zero, it removes - * the object. This is a non intrusive mechanism and any object at any point - * in time can be referenced. When and object is reference counted, do not - * pass the object directly to other methods but rather, pass its - * reference around. Objects can be reference counted in both single threaded - * model and multi-threaded model - */ - -#include -#include "Platform/Define.h" -#include "Policies/ThreadingModel.h" -#include "ReferenceHolder.h" - -template -< -typename T, -class THREADING_MODEL = Trinity::SingleThreaded -> -class Referencer -{ - typedef typename THREADING_MODEL::Lock Lock; - typedef ReferenceHolder ReferenceeHolder; - public: - - /// Constructs a referencer. - Referencer(T *ref = NULL); - - /// Copy constructor - Referencer(const Referencer &obj) : i_holder(NULL) { *this = obj; } - - /// Destructor - ~Referencer(); - - /// Referencee accessor - T* referencee(void) { return (i_holder == NULL ? NULL : i_holder->i_referencee); } - const T* referencee(void) const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } - - //T& referencee(void){ return _referencee(); } - //const T& referencee(void) const { return const_cast(this)->_referencee(); } - operator T&(void) { return _referencee(); } - operator const T&(void) const { return *const_cast(this)->_referencee(); } - - /// cast operators - T* operator*() { return (i_holder == NULL ? NULL : i_holder->i_referencee); } - T const * operator*() const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } - - /// overload operators - T* operator->() { return (i_holder == NULL ? NULL : i_holder->i_referencee); } - const T * operator->() const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } - - /// operator = - Referencer& operator=(const Referencer &obj); - Referencer& operator=(T *); - - /// returns true if i_referencee is null - bool isNull(void) const { return i_holder == NULL; } - - private: - - T& _referencee(void) - { - if( i_holder == NULL ) - throw std::runtime_error("Invalid access to null pointer"); - return *i_holder->i_referencee; - } - - void deReference(ReferenceeHolder *); - void addReference(ReferenceeHolder *); - - // private data - ReferenceeHolder *i_holder; -}; -#endif - diff --git a/src/server/framework/Utilities/CountedReference/ReferenceHolder.h b/src/server/framework/Utilities/CountedReference/ReferenceHolder.h deleted file mode 100644 index 597e9854be0..00000000000 --- a/src/server/framework/Utilities/CountedReference/ReferenceHolder.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_REFERENCEHOLDER_H -#define TRINITY_REFERENCEHOLDER_H - -/** ReferenceHolder holds the actualy referenced obejct as well the refence - count. The ReferenecHolder implements as a policy base object and - will decided by the Reference class to be consnsitent. - */ - -template -< -typename T, -class THREADING_MODEL -> -struct ReferenceHolder : public THREADING_MODEL -{ - explicit ReferenceHolder(T *ref) : i_referencee(ref), i_referenceCount(0) {} - T *i_referencee; - unsigned int i_referenceCount; - typedef typename THREADING_MODEL::Lock Lock; -}; -#endif - diff --git a/src/server/framework/Utilities/CountedReference/ReferenceImpl.h b/src/server/framework/Utilities/CountedReference/ReferenceImpl.h deleted file mode 100644 index cde330179e3..00000000000 --- a/src/server/framework/Utilities/CountedReference/ReferenceImpl.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_REFERENCEIMPL_H -#define TRINITY_REFERENCEIMPL_H - -#include "Reference.h" - -template -< -typename T, -class THREADING_MODEL -> -Referencer::Referencer(T *ref) -: i_holder(NULL) -{ - if( ref != NULL ) - { - i_holder = new ReferenceeHolder(ref); - ++i_holder->i_referenceCount; - } -} - -template -< -typename T, -class THREADING_MODEL -> -Referencer::~Referencer() -{ - if( i_holder != NULL ) - deReference(i_holder); - i_holder = NULL; -} - -template -< -typename T, -class THREADING_MODEL -> -Referencer& -Referencer::operator=(const Referencer &obj) -{ - if( i_holder != NULL ) - deReference(i_holder); - if( obj.i_holder != NULL ) - addReference(obj.i_holder); - i_holder = obj.i_holder; - return *this; -} - -template -< -typename T, -class THREADING_MODEL -> -Referencer& -Referencer::operator=(T *ref) -{ - if( i_holder != NULL ) - deReference(i_holder); - i_holder = NULL; - if( ref != NULL ) - { - i_holder = new ReferenceeHolder(ref); - ++i_holder->i_referenceCount; - } - - return *this; -} - -template -< -typename T, -class THREADING_MODEL -> -void -Referencer::deReference(ReferenceHolder *holder) -{ - assert( holder != NULL && holder->i_referenceCount > 0); - bool delete_object = false; - - { - // The guard is within the scope due to the guard - // must release earlier than expected. - Lock guard(*holder); - Guard(&guard); - - --holder->i_referenceCount; - if( holder->i_referenceCount == 0 ) - delete_object = true; - } - - if( delete_object ) - { - delete holder->i_referencee; - delete holder; - } -} - -template -< -typename T, -class THREADING_MODEL -> -void -Referencer::addReference(ReferenceHolder *holder) -{ - assert( i_holder != NULL ); - Lock guard(*holder); - Guard(&guard); - - ++holder->i_referenceCount; -} -#endif - diff --git a/src/server/framework/Utilities/EventProcessor.cpp b/src/server/framework/Utilities/EventProcessor.cpp deleted file mode 100644 index c695b43313a..00000000000 --- a/src/server/framework/Utilities/EventProcessor.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "EventProcessor.h" - -EventProcessor::EventProcessor() -{ - m_time = 0; - m_aborting = false; -} - -EventProcessor::~EventProcessor() -{ - KillAllEvents(true); -} - -void EventProcessor::Update(uint32 p_time) -{ - // update time - m_time += p_time; - - // main event loop - EventList::iterator i; - while (((i = m_events.begin()) != m_events.end()) && i->first <= m_time) - { - // get and remove event from queue - BasicEvent* Event = i->second; - m_events.erase(i); - - if (!Event->to_Abort) - { - if (Event->Execute(m_time, p_time)) - { - // completely destroy event if it is not re-added - delete Event; - } - } - else - { - Event->Abort(m_time); - delete Event; - } - } -} - -void EventProcessor::KillAllEvents(bool force) -{ - // prevent event insertions - m_aborting = true; - - // first, abort all existing events - for (EventList::iterator i = m_events.begin(); i != m_events.end();) - { - EventList::iterator i_old = i; - ++i; - - i_old->second->to_Abort = true; - i_old->second->Abort(m_time); - if(force || i_old->second->IsDeletable()) - { - delete i_old->second; - - if(!force) // need per-element cleanup - m_events.erase (i_old); - } - } - - // fast clear event list (in force case) - if(force) - m_events.clear(); -} - -void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime) -{ - if (set_addtime) Event->m_addTime = m_time; - Event->m_execTime = e_time; - m_events.insert(std::pair(e_time, Event)); -} - -uint64 EventProcessor::CalculateTime(uint64 t_offset) -{ - return(m_time + t_offset); -} - diff --git a/src/server/framework/Utilities/EventProcessor.h b/src/server/framework/Utilities/EventProcessor.h deleted file mode 100644 index 2712967e1b7..00000000000 --- a/src/server/framework/Utilities/EventProcessor.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __EVENTPROCESSOR_H -#define __EVENTPROCESSOR_H - -#include "Platform/Define.h" - -#include - -// Note. All times are in milliseconds here. - -class BasicEvent -{ - public: - BasicEvent() { to_Abort = false; } - virtual ~BasicEvent() // override destructor to perform some actions on event removal - { - }; - - // this method executes when the event is triggered - // return false if event does not want to be deleted - // e_time is execution time, p_time is update interval - virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; } - - virtual bool IsDeletable() const { return true; } // this event can be safely deleted - - virtual void Abort(uint64 /*e_time*/) {} // this method executes when the event is aborted - - bool to_Abort; // set by externals when the event is aborted, aborted events don't execute - // and get Abort call when deleted - - // these can be used for time offset control - uint64 m_addTime; // time when the event was added to queue, filled by event handler - uint64 m_execTime; // planned time of next execution, filled by event handler -}; - -typedef std::multimap EventList; - -class EventProcessor -{ - public: - EventProcessor(); - ~EventProcessor(); - - void Update(uint32 p_time); - void KillAllEvents(bool force); - void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true); - uint64 CalculateTime(uint64 t_offset); - protected: - uint64 m_time; - EventList m_events; - bool m_aborting; -}; -#endif - diff --git a/src/server/framework/Utilities/LinkedList.h b/src/server/framework/Utilities/LinkedList.h deleted file mode 100644 index b26687767b3..00000000000 --- a/src/server/framework/Utilities/LinkedList.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _LINKEDLIST -#define _LINKEDLIST - -#include "Common.h" - -//============================================ -class LinkedListHead; - -class LinkedListElement -{ - private: - friend class LinkedListHead; - - LinkedListElement* iNext; - LinkedListElement* iPrev; - public: - LinkedListElement() { iNext = NULL; iPrev = NULL; } - ~LinkedListElement() { delink(); } - - bool hasNext() const { return(iNext && iNext->iNext != NULL); } - bool hasPrev() const { return(iPrev && iPrev->iPrev != NULL); } - bool isInList() const { return(iNext != NULL && iPrev != NULL); } - - LinkedListElement * next() { return hasNext() ? iNext : NULL; } - LinkedListElement const* next() const { return hasNext() ? iNext : NULL; } - LinkedListElement * prev() { return hasPrev() ? iPrev : NULL; } - LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; } - - LinkedListElement * nocheck_next() { return iNext; } - LinkedListElement const* nocheck_next() const { return iNext; } - LinkedListElement * nocheck_prev() { return iPrev; } - LinkedListElement const* nocheck_prev() const { return iPrev; } - - void delink() - { - if(isInList()) - { - iNext->iPrev = iPrev; iPrev->iNext = iNext; iNext = NULL; iPrev = NULL; - } - } - - void insertBefore(LinkedListElement* pElem) - { - pElem->iNext = this; - pElem->iPrev = iPrev; - iPrev->iNext = pElem; - iPrev = pElem; - } - - void insertAfter(LinkedListElement* pElem) - { - pElem->iPrev = this; - pElem->iNext = iNext; - iNext->iPrev = pElem; - iNext = pElem; - } -}; - -//============================================ - -class LinkedListHead -{ - private: - LinkedListElement iFirst; - LinkedListElement iLast; - uint32 iSize; - public: - LinkedListHead() - { - // create empty list - - iFirst.iNext = &iLast; - iLast.iPrev = &iFirst; - iSize = 0; - } - - bool isEmpty() const { return(!iFirst.iNext->isInList()); } - - LinkedListElement * getFirst() { return(isEmpty() ? NULL : iFirst.iNext); } - LinkedListElement const* getFirst() const { return(isEmpty() ? NULL : iFirst.iNext); } - - LinkedListElement * getLast() { return(isEmpty() ? NULL : iLast.iPrev); } - LinkedListElement const* getLast() const { return(isEmpty() ? NULL : iLast.iPrev); } - - void insertFirst(LinkedListElement* pElem) - { - iFirst.insertAfter(pElem); - } - - void insertLast(LinkedListElement* pElem) - { - iLast.insertBefore(pElem); - } - - uint32 getSize() const - { - if(!iSize) - { - uint32 result = 0; - LinkedListElement const* e = getFirst(); - while(e) - { - ++result; - e = e->next(); - } - return result; - } - else - return iSize; - } - - void incSize() { ++iSize; } - void decSize() { --iSize; } - - template - class Iterator - { - public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef _Ty value_type; - typedef ptrdiff_t difference_type; - typedef ptrdiff_t distance_type; - typedef _Ty* pointer; - typedef _Ty const* const_pointer; - typedef _Ty& reference; - typedef _Ty const & const_reference; - - Iterator() : _Ptr(0) - { // construct with null node pointer - } - - Iterator(pointer _Pnode) : _Ptr(_Pnode) - { // construct with node pointer _Pnode - } - - Iterator& operator=(Iterator const &_Right) - { - return (*this) = _Right._Ptr; - } - - Iterator& operator=(const_pointer const &_Right) - { - _Ptr = (pointer)_Right; - return (*this); - } - - reference operator*() - { // return designated value - return *_Ptr; - } - - pointer operator->() - { // return pointer to class object - return _Ptr; - } - - Iterator& operator++() - { // preincrement - _Ptr = _Ptr->next(); - return (*this); - } - - Iterator operator++(int) - { // postincrement - iterator _Tmp = *this; - ++*this; - return (_Tmp); - } - - Iterator& operator--() - { // predecrement - _Ptr = _Ptr->prev(); - return (*this); - } - - Iterator operator--(int) - { // postdecrement - iterator _Tmp = *this; - --*this; - return (_Tmp); - } - - bool operator==(Iterator const &_Right) const - { // test for iterator equality - return (_Ptr == _Right._Ptr); - } - - bool operator!=(Iterator const &_Right) const - { // test for iterator inequality - return (!(*this == _Right)); - } - - bool operator==(pointer const &_Right) const - { // test for pointer equality - return (_Ptr != _Right); - } - - bool operator!=(pointer const &_Right) const - { // test for pointer equality - return (!(*this == _Right)); - } - - bool operator==(const_reference _Right) const - { // test for reference equality - return (_Ptr == &_Right); - } - - bool operator!=(const_reference _Right) const - { // test for reference equality - return (_Ptr != &_Right); - } - - pointer _Mynode() - { // return node pointer - return (_Ptr); - } - - protected: - pointer _Ptr; // pointer to node - }; - - typedef Iterator iterator; -}; - -//============================================ -#endif - diff --git a/src/server/framework/Utilities/LinkedReference/RefManager.h b/src/server/framework/Utilities/LinkedReference/RefManager.h deleted file mode 100644 index 7e294b4f5f0..00000000000 --- a/src/server/framework/Utilities/LinkedReference/RefManager.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _REFMANAGER_H -#define _REFMANAGER_H -//===================================================== - -#include "Utilities/LinkedList.h" -#include "Utilities/LinkedReference/Reference.h" - -template class RefManager : public LinkedListHead -{ - public: - typedef LinkedListHead::Iterator< Reference > iterator; - RefManager() { } - virtual ~RefManager() { clearReferences(); } - - Reference* getFirst() { return ((Reference*) LinkedListHead::getFirst()); } - Reference const* getFirst() const { return ((Reference const*) LinkedListHead::getFirst()); } - Reference* getLast() { return ((Reference*) LinkedListHead::getLast()); } - Reference const* getLast() const { return ((Reference const*) LinkedListHead::getLast()); } - - iterator begin() { return iterator(getFirst()); } - iterator end() { return iterator(NULL); } - iterator rbegin() { return iterator(getLast()); } - iterator rend() { return iterator(NULL); } - - void clearReferences() - { - LinkedListElement* ref; - while((ref = getFirst()) != NULL) - { - ((Reference*) ref)->invalidate(); - ref->delink(); // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list - } - } -}; - -//===================================================== -#endif - diff --git a/src/server/framework/Utilities/LinkedReference/Reference.h b/src/server/framework/Utilities/LinkedReference/Reference.h deleted file mode 100644 index 4a1545f8f12..00000000000 --- a/src/server/framework/Utilities/LinkedReference/Reference.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _REFERENCE_H -#define _REFERENCE_H - -#include "Utilities/LinkedList.h" - -//===================================================== - -template class Reference : public LinkedListElement -{ - private: - TO* iRefTo; - FROM* iRefFrom; - protected: - // Tell our refTo (target) object that we have a link - virtual void targetObjectBuildLink() = 0; - - // Tell our refTo (taget) object, that the link is cut - virtual void targetObjectDestroyLink() = 0; - - // Tell our refFrom (source) object, that the link is cut (Target destroyed) - virtual void sourceObjectDestroyLink() = 0; - public: - Reference() { iRefTo = NULL; iRefFrom = NULL; } - virtual ~Reference() {} - - // Create new link - void link(TO* toObj, FROM* fromObj) - { - assert(fromObj); // fromObj MUST not be NULL - if(isValid()) - unlink(); - if(toObj != NULL) - { - iRefTo = toObj; - iRefFrom = fromObj; - targetObjectBuildLink(); - } - } - - // We don't need the reference anymore. Call comes from the refFrom object - // Tell our refTo object, that the link is cut - void unlink() { targetObjectDestroyLink(); delink(); iRefTo = NULL; iRefFrom = NULL; } - - // Link is invalid due to destruction of referenced target object. Call comes from the refTo object - // Tell our refFrom object, that the link is cut - void invalidate() // the iRefFrom MUST remain!! - { - sourceObjectDestroyLink(); delink(); iRefTo = NULL; - } - - bool isValid() const // Only check the iRefTo - { - return iRefTo != NULL; - } - - Reference * next() { return((Reference *) LinkedListElement::next()); } - Reference const * next() const { return((Reference const *) LinkedListElement::next()); } - Reference * prev() { return((Reference *) LinkedListElement::prev()); } - Reference const * prev() const { return((Reference const *) LinkedListElement::prev()); } - - Reference * nocheck_next() { return((Reference *) LinkedListElement::nocheck_next()); } - Reference const * nocheck_next() const { return((Reference const *) LinkedListElement::nocheck_next()); } - Reference * nocheck_prev() { return((Reference *) LinkedListElement::nocheck_prev()); } - Reference const * nocheck_prev() const { return((Reference const *) LinkedListElement::nocheck_prev()); } - - TO* operator ->() const { return iRefTo; } - TO* getTarget() const { return iRefTo; } - - FROM* getSource() const { return iRefFrom; } -}; - -//===================================================== -#endif - diff --git a/src/server/framework/Utilities/TypeList.h b/src/server/framework/Utilities/TypeList.h deleted file mode 100644 index 02bc08083c2..00000000000 --- a/src/server/framework/Utilities/TypeList.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_TYPELIST_H -#define TRINITY_TYPELIST_H - -/* - @struct TypeList - TypeList is the most simple but yet the most powerfull class of all. It holds - at compile time the different type of objects in a linked list. - */ - -class TypeNull; - -template -struct TypeList -{ - typedef HEAD Head; - typedef TAIL Tail; -}; - -// enough for now.. can be expand at any point in time as needed -#define TYPELIST_1(T1) TypeList -#define TYPELIST_2(T1, T2) TypeList -#define TYPELIST_3(T1, T2, T3) TypeList -#define TYPELIST_4(T1, T2, T3, T4) TypeList -#define TYPELIST_5(T1, T2, T3, T4, T5) TypeList -#endif - diff --git a/src/server/framework/Utilities/UnorderedMap.h b/src/server/framework/Utilities/UnorderedMap.h deleted file mode 100644 index fce5ec82bfc..00000000000 --- a/src/server/framework/Utilities/UnorderedMap.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_UNORDERED_MAP_H -#define TRINITY_UNORDERED_MAP_H - -#include "Platform/CompilerDefs.h" -#include "Platform/Define.h" - -#if COMPILER == COMPILER_INTEL -#include -#elif COMPILER == COMPILER_GNU && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3) -#include -#elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 -#include -#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1500 && _HAS_TR1 // VC9.0 and later -#include -#else -#include -#endif - -#ifdef _STLPORT_VERSION -#define UNORDERED_MAP std::hash_map -using std::hash_map; -#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1500 && _HAS_TR1 -#define UNORDERED_MAP std::tr1::unordered_map -#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1300 -#define UNORDERED_MAP stdext::hash_map -using stdext::hash_map; -#elif COMPILER == COMPILER_INTEL -#define UNORDERED_MAP std::hash_map -using std::hash_map; -#elif COMPILER == COMPILER_GNU && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3) -#define UNORDERED_MAP std::tr1::unordered_map -#elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 -#define UNORDERED_MAP __gnu_cxx::hash_map - -namespace __gnu_cxx -{ - template<> struct hash - { - size_t operator()(const unsigned long long &__x) const { return (size_t)__x; } - }; - template struct hash - { - size_t operator()(T * const &__x) const { return (size_t)__x; } - }; - -}; - -#else -#define UNORDERED_MAP std::hash_map -using std::hash_map; -#endif -#endif - diff --git a/src/server/game/Grids/Cell.h b/src/server/game/Grids/Cell.h deleted file mode 100644 index 49e0329ace6..00000000000 --- a/src/server/game/Grids/Cell.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CELL_H -#define TRINITY_CELL_H - -#include - -#include "GameSystem/TypeContainer.h" -#include "GameSystem/TypeContainerVisitor.h" - -#include "GridDefines.h" - -class Map; -class WorldObject; - -enum District -{ - UPPER_DISTRICT = 1, - LOWER_DISTRICT = 1 << 1, - LEFT_DISTRICT = 1 << 2, - RIGHT_DISTRICT = 1 << 3, - CENTER_DISTRICT = 1 << 4, - UPPER_LEFT_DISTRICT = (UPPER_DISTRICT | LEFT_DISTRICT), - UPPER_RIGHT_DISTRICT = (UPPER_DISTRICT | RIGHT_DISTRICT), - LOWER_LEFT_DISTRICT = (LOWER_DISTRICT | LEFT_DISTRICT), - LOWER_RIGHT_DISTRICT = (LOWER_DISTRICT | RIGHT_DISTRICT), - ALL_DISTRICT = (UPPER_DISTRICT | LOWER_DISTRICT | LEFT_DISTRICT | RIGHT_DISTRICT | CENTER_DISTRICT) -}; - -struct CellArea -{ - CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {} - CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {} - bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; } - - void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const - { - begin_cell << left_offset; - begin_cell -= lower_offset; - end_cell >> right_offset; - end_cell += upper_offset; - } - - int right_offset; - int left_offset; - int upper_offset; - int lower_offset; -}; - -struct Cell -{ - Cell() { data.All = 0; } - Cell(const Cell &cell) { data.All = cell.data.All; } - explicit Cell(CellPair const& p); - - void operator|=(Cell &cell) - { - data.Part.reserved = 0; - cell.data.Part.reserved = 0; - uint32 x, y, old_x, old_y; - Compute(x, y); - cell.Compute(old_x, old_y); - - if (std::abs(int(x-old_x)) > 1 || std::abs(int(y-old_y)) > 1) - { - data.Part.reserved = ALL_DISTRICT; - cell.data.Part.reserved = ALL_DISTRICT; - return; - } - - if (x < old_x) - { - data.Part.reserved |= LEFT_DISTRICT; - cell.data.Part.reserved |= RIGHT_DISTRICT; - } - else if (old_x < x) - { - data.Part.reserved |= RIGHT_DISTRICT; - cell.data.Part.reserved |= LEFT_DISTRICT; - } - if (y < old_y) - { - data.Part.reserved |= UPPER_DISTRICT; - cell.data.Part.reserved |= LOWER_DISTRICT; - } - else if (old_y < y) - { - data.Part.reserved |= LOWER_DISTRICT; - cell.data.Part.reserved |= UPPER_DISTRICT; - } - } - - void Compute(uint32 &x, uint32 &y) const - { - x = data.Part.grid_x*MAX_NUMBER_OF_CELLS + data.Part.cell_x; - y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; - } - - bool DiffCell(const Cell &cell) const - { - return(data.Part.cell_x != cell.data.Part.cell_x || - data.Part.cell_y != cell.data.Part.cell_y); - } - - bool DiffGrid(const Cell &cell) const - { - return(data.Part.grid_x != cell.data.Part.grid_x || - data.Part.grid_y != cell.data.Part.grid_y); - } - - uint32 CellX() const { return data.Part.cell_x; } - uint32 CellY() const { return data.Part.cell_y; } - uint32 GridX() const { return data.Part.grid_x; } - uint32 GridY() const { return data.Part.grid_y; } - bool NoCreate() const { return data.Part.nocreate; } - void SetNoCreate() { data.Part.nocreate = 1; } - - CellPair cellPair() const - { - return CellPair( - data.Part.grid_x*MAX_NUMBER_OF_CELLS+data.Part.cell_x, - data.Part.grid_y*MAX_NUMBER_OF_CELLS+data.Part.cell_y); - } - - Cell& operator=(const Cell &cell) - { - this->data.All = cell.data.All; - return *this; - } - - bool operator == (const Cell &cell) const { return (data.All == cell.data.All); } - bool operator != (const Cell &cell) const { return !operator == (cell); } - union - { - struct - { - unsigned grid_x : 6; - unsigned grid_y : 6; - unsigned cell_x : 6; - unsigned cell_y : 6; - unsigned nocreate : 1; - unsigned reserved : 7; - } Part; - uint32 All; - } data; - - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &) const; - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, const WorldObject&, float) const; - template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, float, float, float) const; - - static CellArea CalculateCellArea(const WorldObject &obj, float radius); - static CellArea CalculateCellArea(float x, float y, float radius); - -private: - template void VisitCircle(TypeContainerVisitor &, Map &, const CellPair&, const CellPair&) const; -}; - -#endif - diff --git a/src/server/game/Grids/CellImpl.h b/src/server/game/Grids/CellImpl.h deleted file mode 100644 index d906e81a5c9..00000000000 --- a/src/server/game/Grids/CellImpl.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_CELLIMPL_H -#define TRINITY_CELLIMPL_H - -#include - -#include "Cell.h" -#include "Map.h" -#include "Object.h" - -inline Cell::Cell(CellPair const& p) -{ - data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS; - data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; - data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; - data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; - data.Part.nocreate = 0; - data.Part.reserved = 0; -} - -template -inline void -Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m) const -{ - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - return; - - uint16 district = (District)this->data.Part.reserved; - if (district == CENTER_DISTRICT) - { - m.Visit(*this, visitor); - return; - } - - // set up the cell range based on the district - // the overloaded operators handle range checking - CellPair begin_cell = standing_cell; - CellPair end_cell = standing_cell; - - switch(district) - { - case ALL_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell >> 1; end_cell += 1; // lower right - break; - } - case UPPER_LEFT_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - break; - } - case UPPER_RIGHT_DISTRICT: - { - begin_cell -= 1; // up - end_cell >> 1; // right - break; - } - case LOWER_LEFT_DISTRICT: - { - begin_cell << 1; // left - end_cell += 1; // down - break; - } - case LOWER_RIGHT_DISTRICT: - { - end_cell >> 1; end_cell += 1; // lower right - break; - } - case LEFT_DISTRICT: - { - begin_cell -= 1; // up - end_cell >> 1; end_cell += 1; // lower right - break; - } - case RIGHT_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell += 1; // down - break; - } - case UPPER_DISTRICT: - { - begin_cell << 1; begin_cell -= 1; // upper left - end_cell >> 1; // right - break; - } - case LOWER_DISTRICT: - { - begin_cell << 1; // left - end_cell >> 1; end_cell += 1; // lower right - break; - } - default: - { - assert(false); - break; - } - } - - // loop the cell range - for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++) - { - CellPair cell_pair(x,y); - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } -} - -inline int CellHelper(const float radius) -{ - if (radius < 1.0f) - return 0; - - return (int)ceilf(radius/SIZE_OF_GRID_CELL); -} - -inline CellArea Cell::CalculateCellArea(const WorldObject &obj, float radius) -{ - return Cell::CalculateCellArea(obj.GetPositionX(), obj.GetPositionY(), radius); -} - -inline CellArea Cell::CalculateCellArea(float x, float y, float radius) -{ - if (radius <= 0.0f) - return CellArea(); - - //lets calculate object coord offsets from cell borders. - //TODO: add more correct/generic method for this task - const float x_offset = (x - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - const float y_offset = (y - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; - - const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f); - const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f); - - const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - - const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET; - //lets calculate upper/lower/right/left corners for cell search - int right = CellHelper(tmp_diff + x_off); - int left = CellHelper(tmp_diff - x_off); - int upper = CellHelper(tmp_diff + y_off); - int lower = CellHelper(tmp_diff - y_off); - - return CellArea(right, left, upper, lower); -} - -template -inline void -Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m, float radius, float x_off, float y_off) const -{ - if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) - return; - - //no jokes here... Actually placing ASSERT() here was good idea, but - //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?) - //maybe it is better to just return when radius <= 0.0f? - if (radius <= 0.0f) - { - m.Visit(*this, visitor); - return; - } - //lets limit the upper value for search radius - if (radius > 333.0f) - radius = 333.0f; - - //lets calculate object coord offsets from cell borders. - CellArea area = Cell::CalculateCellArea(x_off, y_off, radius); - //if radius fits inside standing cell - if (!area) - { - m.Visit(*this, visitor); - return; - } - - CellPair begin_cell = standing_cell; - CellPair end_cell = standing_cell; - - area.ResizeBorders(begin_cell, end_cell); - //visit all cells, found in CalculateCellArea() - //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle - //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values - //there are nothing to optimize because SIZE_OF_GRID_CELL is too big... - if (((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4)) - { - VisitCircle(visitor, m, begin_cell, end_cell); - return; - } - - //ALWAYS visit standing cell first!!! Since we deal with small radiuses - //it is very essential to call visitor for standing cell firstly... - m.Visit(*this, visitor); - - // loop the cell range - for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) - { - CellPair cell_pair(x,y); - //lets skip standing cell since we already visited it - if (cell_pair != standing_cell) - { - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } - } -} - -template -inline void -Cell::Visit(const CellPair& l, TypeContainerVisitor &visitor, Map &m, const WorldObject &obj, float radius) const -{ - //we should increase search radius by object's radius, otherwise - //we could have problems with huge creatures, which won't attack nearest players etc - Visit(l, visitor, m, radius + obj.GetObjectSize(), obj.GetPositionX(), obj.GetPositionY()); -} - -template -inline void -Cell::VisitCircle(TypeContainerVisitor &visitor, Map &m, const CellPair& begin_cell, const CellPair& end_cell) const -{ - //here is an algorithm for 'filling' circum-squared octagon - uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f); - //lets calculate x_start/x_end coords for central strip... - const uint32 x_start = begin_cell.x_coord + x_shift; - const uint32 x_end = end_cell.x_coord - x_shift; - - //visit central strip with constant width... - for (uint32 x = x_start; x <= x_end; ++x) - { - for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) - { - CellPair cell_pair(x,y); - Cell r_zone(cell_pair); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone, visitor); - } - } - - //if x_shift == 0 then we have too small cell area, which were already - //visited at previous step, so just return from procedure... - if (x_shift == 0) - return; - - uint32 y_start = end_cell.y_coord; - uint32 y_end = begin_cell.y_coord; - //now we are visiting borders of an octagon... - for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step) - { - //each step reduces strip height by 2 cells... - y_end += 1; - y_start -= 1; - for (uint32 y = y_start; y >= y_end; --y) - { - //we visit cells symmetrically from both sides, heading from center to sides and from up to bottom - //e.g. filling 2 trapezoids after filling central cell strip... - CellPair cell_pair_left(x_start - step, y); - Cell r_zone_left(cell_pair_left); - r_zone_left.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone_left, visitor); - - //right trapezoid cell visit - CellPair cell_pair_right(x_end + step, y); - Cell r_zone_right(cell_pair_right); - r_zone_right.data.Part.nocreate = this->data.Part.nocreate; - m.Visit(r_zone_right, visitor); - } - } -} -#endif - diff --git a/src/server/game/Grids/Cells/Cell.h b/src/server/game/Grids/Cells/Cell.h new file mode 100644 index 00000000000..49e0329ace6 --- /dev/null +++ b/src/server/game/Grids/Cells/Cell.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CELL_H +#define TRINITY_CELL_H + +#include + +#include "GameSystem/TypeContainer.h" +#include "GameSystem/TypeContainerVisitor.h" + +#include "GridDefines.h" + +class Map; +class WorldObject; + +enum District +{ + UPPER_DISTRICT = 1, + LOWER_DISTRICT = 1 << 1, + LEFT_DISTRICT = 1 << 2, + RIGHT_DISTRICT = 1 << 3, + CENTER_DISTRICT = 1 << 4, + UPPER_LEFT_DISTRICT = (UPPER_DISTRICT | LEFT_DISTRICT), + UPPER_RIGHT_DISTRICT = (UPPER_DISTRICT | RIGHT_DISTRICT), + LOWER_LEFT_DISTRICT = (LOWER_DISTRICT | LEFT_DISTRICT), + LOWER_RIGHT_DISTRICT = (LOWER_DISTRICT | RIGHT_DISTRICT), + ALL_DISTRICT = (UPPER_DISTRICT | LOWER_DISTRICT | LEFT_DISTRICT | RIGHT_DISTRICT | CENTER_DISTRICT) +}; + +struct CellArea +{ + CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {} + CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {} + bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; } + + void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const + { + begin_cell << left_offset; + begin_cell -= lower_offset; + end_cell >> right_offset; + end_cell += upper_offset; + } + + int right_offset; + int left_offset; + int upper_offset; + int lower_offset; +}; + +struct Cell +{ + Cell() { data.All = 0; } + Cell(const Cell &cell) { data.All = cell.data.All; } + explicit Cell(CellPair const& p); + + void operator|=(Cell &cell) + { + data.Part.reserved = 0; + cell.data.Part.reserved = 0; + uint32 x, y, old_x, old_y; + Compute(x, y); + cell.Compute(old_x, old_y); + + if (std::abs(int(x-old_x)) > 1 || std::abs(int(y-old_y)) > 1) + { + data.Part.reserved = ALL_DISTRICT; + cell.data.Part.reserved = ALL_DISTRICT; + return; + } + + if (x < old_x) + { + data.Part.reserved |= LEFT_DISTRICT; + cell.data.Part.reserved |= RIGHT_DISTRICT; + } + else if (old_x < x) + { + data.Part.reserved |= RIGHT_DISTRICT; + cell.data.Part.reserved |= LEFT_DISTRICT; + } + if (y < old_y) + { + data.Part.reserved |= UPPER_DISTRICT; + cell.data.Part.reserved |= LOWER_DISTRICT; + } + else if (old_y < y) + { + data.Part.reserved |= LOWER_DISTRICT; + cell.data.Part.reserved |= UPPER_DISTRICT; + } + } + + void Compute(uint32 &x, uint32 &y) const + { + x = data.Part.grid_x*MAX_NUMBER_OF_CELLS + data.Part.cell_x; + y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; + } + + bool DiffCell(const Cell &cell) const + { + return(data.Part.cell_x != cell.data.Part.cell_x || + data.Part.cell_y != cell.data.Part.cell_y); + } + + bool DiffGrid(const Cell &cell) const + { + return(data.Part.grid_x != cell.data.Part.grid_x || + data.Part.grid_y != cell.data.Part.grid_y); + } + + uint32 CellX() const { return data.Part.cell_x; } + uint32 CellY() const { return data.Part.cell_y; } + uint32 GridX() const { return data.Part.grid_x; } + uint32 GridY() const { return data.Part.grid_y; } + bool NoCreate() const { return data.Part.nocreate; } + void SetNoCreate() { data.Part.nocreate = 1; } + + CellPair cellPair() const + { + return CellPair( + data.Part.grid_x*MAX_NUMBER_OF_CELLS+data.Part.cell_x, + data.Part.grid_y*MAX_NUMBER_OF_CELLS+data.Part.cell_y); + } + + Cell& operator=(const Cell &cell) + { + this->data.All = cell.data.All; + return *this; + } + + bool operator == (const Cell &cell) const { return (data.All == cell.data.All); } + bool operator != (const Cell &cell) const { return !operator == (cell); } + union + { + struct + { + unsigned grid_x : 6; + unsigned grid_y : 6; + unsigned cell_x : 6; + unsigned cell_y : 6; + unsigned nocreate : 1; + unsigned reserved : 7; + } Part; + uint32 All; + } data; + + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &) const; + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, const WorldObject&, float) const; + template void Visit(const CellPair&, TypeContainerVisitor &visitor, Map &, float, float, float) const; + + static CellArea CalculateCellArea(const WorldObject &obj, float radius); + static CellArea CalculateCellArea(float x, float y, float radius); + +private: + template void VisitCircle(TypeContainerVisitor &, Map &, const CellPair&, const CellPair&) const; +}; + +#endif + diff --git a/src/server/game/Grids/Cells/CellImpl.h b/src/server/game/Grids/Cells/CellImpl.h new file mode 100644 index 00000000000..d906e81a5c9 --- /dev/null +++ b/src/server/game/Grids/Cells/CellImpl.h @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CELLIMPL_H +#define TRINITY_CELLIMPL_H + +#include + +#include "Cell.h" +#include "Map.h" +#include "Object.h" + +inline Cell::Cell(CellPair const& p) +{ + data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS; + data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; + data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; + data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; + data.Part.nocreate = 0; + data.Part.reserved = 0; +} + +template +inline void +Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m) const +{ + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + return; + + uint16 district = (District)this->data.Part.reserved; + if (district == CENTER_DISTRICT) + { + m.Visit(*this, visitor); + return; + } + + // set up the cell range based on the district + // the overloaded operators handle range checking + CellPair begin_cell = standing_cell; + CellPair end_cell = standing_cell; + + switch(district) + { + case ALL_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right + break; + } + case UPPER_LEFT_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + break; + } + case UPPER_RIGHT_DISTRICT: + { + begin_cell -= 1; // up + end_cell >> 1; // right + break; + } + case LOWER_LEFT_DISTRICT: + { + begin_cell << 1; // left + end_cell += 1; // down + break; + } + case LOWER_RIGHT_DISTRICT: + { + end_cell >> 1; end_cell += 1; // lower right + break; + } + case LEFT_DISTRICT: + { + begin_cell -= 1; // up + end_cell >> 1; end_cell += 1; // lower right + break; + } + case RIGHT_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell += 1; // down + break; + } + case UPPER_DISTRICT: + { + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; // right + break; + } + case LOWER_DISTRICT: + { + begin_cell << 1; // left + end_cell >> 1; end_cell += 1; // lower right + break; + } + default: + { + assert(false); + break; + } + } + + // loop the cell range + for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++) + { + CellPair cell_pair(x,y); + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } +} + +inline int CellHelper(const float radius) +{ + if (radius < 1.0f) + return 0; + + return (int)ceilf(radius/SIZE_OF_GRID_CELL); +} + +inline CellArea Cell::CalculateCellArea(const WorldObject &obj, float radius) +{ + return Cell::CalculateCellArea(obj.GetPositionX(), obj.GetPositionY(), radius); +} + +inline CellArea Cell::CalculateCellArea(float x, float y, float radius) +{ + if (radius <= 0.0f) + return CellArea(); + + //lets calculate object coord offsets from cell borders. + //TODO: add more correct/generic method for this task + const float x_offset = (x - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + const float y_offset = (y - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL; + + const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f); + const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f); + + const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; + + const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET; + //lets calculate upper/lower/right/left corners for cell search + int right = CellHelper(tmp_diff + x_off); + int left = CellHelper(tmp_diff - x_off); + int upper = CellHelper(tmp_diff + y_off); + int lower = CellHelper(tmp_diff - y_off); + + return CellArea(right, left, upper, lower); +} + +template +inline void +Cell::Visit(const CellPair& standing_cell, TypeContainerVisitor &visitor, Map &m, float radius, float x_off, float y_off) const +{ + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + return; + + //no jokes here... Actually placing ASSERT() here was good idea, but + //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?) + //maybe it is better to just return when radius <= 0.0f? + if (radius <= 0.0f) + { + m.Visit(*this, visitor); + return; + } + //lets limit the upper value for search radius + if (radius > 333.0f) + radius = 333.0f; + + //lets calculate object coord offsets from cell borders. + CellArea area = Cell::CalculateCellArea(x_off, y_off, radius); + //if radius fits inside standing cell + if (!area) + { + m.Visit(*this, visitor); + return; + } + + CellPair begin_cell = standing_cell; + CellPair end_cell = standing_cell; + + area.ResizeBorders(begin_cell, end_cell); + //visit all cells, found in CalculateCellArea() + //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle + //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values + //there are nothing to optimize because SIZE_OF_GRID_CELL is too big... + if (((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4)) + { + VisitCircle(visitor, m, begin_cell, end_cell); + return; + } + + //ALWAYS visit standing cell first!!! Since we deal with small radiuses + //it is very essential to call visitor for standing cell firstly... + m.Visit(*this, visitor); + + // loop the cell range + for (uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + CellPair cell_pair(x,y); + //lets skip standing cell since we already visited it + if (cell_pair != standing_cell) + { + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } + } +} + +template +inline void +Cell::Visit(const CellPair& l, TypeContainerVisitor &visitor, Map &m, const WorldObject &obj, float radius) const +{ + //we should increase search radius by object's radius, otherwise + //we could have problems with huge creatures, which won't attack nearest players etc + Visit(l, visitor, m, radius + obj.GetObjectSize(), obj.GetPositionX(), obj.GetPositionY()); +} + +template +inline void +Cell::VisitCircle(TypeContainerVisitor &visitor, Map &m, const CellPair& begin_cell, const CellPair& end_cell) const +{ + //here is an algorithm for 'filling' circum-squared octagon + uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f); + //lets calculate x_start/x_end coords for central strip... + const uint32 x_start = begin_cell.x_coord + x_shift; + const uint32 x_end = end_cell.x_coord - x_shift; + + //visit central strip with constant width... + for (uint32 x = x_start; x <= x_end; ++x) + { + for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + CellPair cell_pair(x,y); + Cell r_zone(cell_pair); + r_zone.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone, visitor); + } + } + + //if x_shift == 0 then we have too small cell area, which were already + //visited at previous step, so just return from procedure... + if (x_shift == 0) + return; + + uint32 y_start = end_cell.y_coord; + uint32 y_end = begin_cell.y_coord; + //now we are visiting borders of an octagon... + for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step) + { + //each step reduces strip height by 2 cells... + y_end += 1; + y_start -= 1; + for (uint32 y = y_start; y >= y_end; --y) + { + //we visit cells symmetrically from both sides, heading from center to sides and from up to bottom + //e.g. filling 2 trapezoids after filling central cell strip... + CellPair cell_pair_left(x_start - step, y); + Cell r_zone_left(cell_pair_left); + r_zone_left.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone_left, visitor); + + //right trapezoid cell visit + CellPair cell_pair_right(x_end + step, y); + Cell r_zone_right(cell_pair_right); + r_zone_right.data.Part.nocreate = this->data.Part.nocreate; + m.Visit(r_zone_right, visitor); + } + } +} +#endif + diff --git a/src/server/game/Grids/Grid.h b/src/server/game/Grids/Grid.h new file mode 100644 index 00000000000..65bf3c92f9d --- /dev/null +++ b/src/server/game/Grids/Grid.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRID_H +#define TRINITY_GRID_H + +/* + @class Grid + Grid is a logical segment of the game world represented inside TrinIty. + Grid is bind at compile time to a particular type of object which + we call it the object of interested. There are many types of loader, + specially, dynamic loader, static loader, or on-demand loader. There's + a subtle difference between dynamic loader and on-demand loader but + this is implementation specific to the loader class. From the + Grid's perspective, the loader meets its API requirement is suffice. +*/ + +#include "Platform/Define.h" +#include "Policies/ThreadingModel.h" +#include "TypeContainer.h" +#include "TypeContainerVisitor.h" + +// forward declaration +template class GridLoader; + +template +< +class ACTIVE_OBJECT, +class WORLD_OBJECT_TYPES, +class GRID_OBJECT_TYPES, +class ThreadModel = Trinity::SingleThreaded +> +class Grid +{ + // allows the GridLoader to access its internals + template friend class GridLoader; + public: + + /** destructor to clean up its resources. This includes unloading the + grid if it has not been unload. + */ + ~Grid() {} + + /** an object of interested enters the grid + */ + template void AddWorldObject(SPECIFIC_OBJECT *obj) + { + if(!i_objects.template insert(obj)) + assert(false); + } + + /** an object of interested exits the grid + */ + template void RemoveWorldObject(SPECIFIC_OBJECT *obj) + { + if(!i_objects.template remove(obj)) + assert(false); + } + + /** Refreshes/update the grid. This required for remote grids. + */ + void RefreshGrid(void) { /* TBI */} + + /** Locks a grid. Any object enters must wait until the grid is unlock. + */ + void LockGrid(void) { /* TBI */ } + + /** Unlocks the grid. + */ + void UnlockGrid(void) { /* TBI */ } + + /** Grid visitor for grid objects + */ + template void Visit(TypeContainerVisitor > &visitor) + { + visitor.Visit(i_container); + } + + /** Grid visitor for world objects + */ + template void Visit(TypeContainerVisitor > &visitor) + { + visitor.Visit(i_objects); + } + + /** Returns the number of object within the grid. + */ + unsigned int ActiveObjectsInGrid(void) const { return /*m_activeGridObjects.size()+*/i_objects.template Count(); } + + /** Inserts a container type object into the grid. + */ + template void AddGridObject(SPECIFIC_OBJECT *obj) + { + if(!i_container.template insert(obj)) + assert(false); + } + + /** Removes a containter type object from the grid + */ + template void RemoveGridObject(SPECIFIC_OBJECT *obj) + { + if(!i_container.template remove(obj)) + assert(false); + } + + /*bool NoWorldObjectInGrid() const + { + return i_objects.GetElements().isEmpty(); + } + + bool NoGridObjectInGrid() const + { + return i_container.GetElements().isEmpty(); + }*/ + private: + + typedef typename ThreadModel::Lock Guard; + typedef typename ThreadModel::VolatileType VolatileType; + + TypeMapContainer i_container; + TypeMapContainer i_objects; + //typedef std::set ActiveGridObjects; + //ActiveGridObjects m_activeGridObjects; +}; +#endif + diff --git a/src/server/game/Grids/GridLoader.h b/src/server/game/Grids/GridLoader.h new file mode 100644 index 00000000000..03fa0f5b813 --- /dev/null +++ b/src/server/game/Grids/GridLoader.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDLOADER_H +#define TRINITY_GRIDLOADER_H + +/** + @class GridLoader + The GridLoader is working in conjuction with the Grid and responsible + for loading and unloading object-types (one or more) when objects + enters a grid. Unloading is scheduled and might be canceled if + an interested object re-enters. GridLoader does not do the actuall + loading and unloading but implements as a template pattern that + delicate its loading and unloading for the actualy loader and unloader. + GridLoader manages the grid (both local and remote). + */ + +#include "Platform/Define.h" +#include "Grid.h" +#include "TypeContainerVisitor.h" + +template +< +class ACTIVE_OBJECT, +class WORLD_OBJECT_TYPES, +class GRID_OBJECT_TYPES +> +class GridLoader +{ + public: + + /** Loads the grid + */ + template + void Load(Grid &grid, LOADER &loader) + { + grid.LockGrid(); + loader.Load(grid); + grid.UnlockGrid(); + } + + /** Stop the grid + */ + template + void Stop(Grid &grid, STOPER &stoper) + { + grid.LockGrid(); + stoper.Stop(grid); + grid.UnlockGrid(); + } + /** Unloads the grid + */ + template + void Unload(Grid &grid, UNLOADER &unloader) + { + grid.LockGrid(); + unloader.Unload(grid); + grid.UnlockGrid(); + } +}; +#endif + diff --git a/src/server/game/Grids/GridNotifiers.cpp b/src/server/game/Grids/GridNotifiers.cpp deleted file mode 100644 index b10dfa8791e..00000000000 --- a/src/server/game/Grids/GridNotifiers.cpp +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "UpdateData.h" -#include "Item.h" -#include "Map.h" -#include "Transports.h" -#include "ObjectAccessor.h" -#include "CellImpl.h" - -using namespace Trinity; - -void -VisibleNotifier::SendToSelf() -{ - // at this moment i_clientGUIDs have guids that not iterate at grid level checks - // but exist one case when this possible and object not out of range: transports - if (Transport* transport = i_player.GetTransport()) - for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr != transport->GetPassengers().end();++itr) - { - if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end()) - { - vis_guids.erase((*itr)->GetGUID()); - - i_player.UpdateVisibilityOf((*itr), i_data, i_visibleNow); - - if (!(*itr)->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - (*itr)->UpdateVisibilityOf(&i_player); - } - } - - for (Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end(); ++it) - { - i_player.m_clientGUIDs.erase(*it); - i_data.AddOutOfRangeGUID(*it); - - if (IS_PLAYER_GUID(*it)) - { - Player* plr = ObjectAccessor::FindPlayer(*it); - if (plr && plr->IsInWorld() && !plr->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - plr->UpdateVisibilityOf(&i_player); - } - } - - if (!i_data.HasData()) - return; - - WorldPacket packet; - i_data.BuildPacket(&packet); - i_player.GetSession()->SendPacket(&packet); - - for (std::set::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it) - i_player.SendInitialVisiblePackets(*it); -} - -void -VisibleChangesNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - if (iter->getSource() == &i_object) - continue; - - iter->getSource()->UpdateVisibilityOf(&i_object); - - if (!iter->getSource()->GetSharedVisionList().empty()) - for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - (*i)->UpdateVisibilityOf(&i_object); - } -} - -void -VisibleChangesNotifier::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (!iter->getSource()->GetSharedVisionList().empty()) - for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - (*i)->UpdateVisibilityOf(&i_object); -} - -void -VisibleChangesNotifier::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) - if (Player* caster = (Player*)iter->getSource()->GetCaster()) - if (caster->m_seer == iter->getSource()) - caster->UpdateVisibilityOf(&i_object); -} - -inline void CreatureUnitRelocationWorker(Creature* c, Unit* u) -{ - if (!u->isAlive() || !c->isAlive() || c == u || u->isInFlight()) - return; - - if (c->HasReactState(REACT_AGGRESSIVE) && !c->hasUnitState(UNIT_STAT_SIGHTLESS)) - if (c->_IsWithinDist(u, c->m_SightDistance, true) && c->IsAIEnabled) - c->AI()->MoveInLineOfSight_Safe(u); -} - -void PlayerRelocationNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Player* plr = iter->getSource(); - - vis_guids.erase(plr->GetGUID()); - - i_player.UpdateVisibilityOf(plr,i_data,i_visibleNow); - - if (plr->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - plr->UpdateVisibilityOf(&i_player); - } -} - -void PlayerRelocationNotifier::Visit(CreatureMapType &m) -{ - bool relocated_for_ai = (&i_player == i_player.m_seer); - - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Creature * c = iter->getSource(); - - vis_guids.erase(c->GetGUID()); - - i_player.UpdateVisibilityOf(c,i_data,i_visibleNow); - - if (relocated_for_ai && !c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - CreatureUnitRelocationWorker(c, &i_player); - } -} - -void CreatureRelocationNotifier::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Player * pl = iter->getSource(); - - if (!pl->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - pl->UpdateVisibilityOf(&i_creature); - - CreatureUnitRelocationWorker(&i_creature, pl); - } -} - -void CreatureRelocationNotifier::Visit(CreatureMapType &m) -{ - if (!i_creature.isAlive()) - return; - - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - Creature* c = iter->getSource(); - CreatureUnitRelocationWorker(&i_creature, c); - - if (!c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - CreatureUnitRelocationWorker(c, &i_creature); - } -} - -void DelayedUnitRelocation::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Creature * unit = iter->getSource(); - if (!unit->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - CreatureRelocationNotifier relocate(*unit); - - TypeContainerVisitor c2world_relocation(relocate); - TypeContainerVisitor c2grid_relocation(relocate); - - cell.Visit(p, c2world_relocation, i_map, *unit, i_radius); - cell.Visit(p, c2grid_relocation, i_map, *unit, i_radius); - } -} - -void DelayedUnitRelocation::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Player * player = iter->getSource(); - WorldObject const *viewPoint = player->m_seer; - - if (!viewPoint->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) - continue; - - if (player != viewPoint && !viewPoint->IsPositionValid()) - continue; - - CellPair pair2(Trinity::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY())); - Cell cell2(pair2); - //cell.SetNoCreate(); need load cells around viewPoint or player, that's why its commented - - PlayerRelocationNotifier relocate(*player); - TypeContainerVisitor c2world_relocation(relocate); - TypeContainerVisitor c2grid_relocation(relocate); - - cell2.Visit(pair2, c2world_relocation, i_map, *viewPoint, i_radius); - cell2.Visit(pair2, c2grid_relocation, i_map, *viewPoint, i_radius); - - relocate.SendToSelf(); - } -} - -void AIRelocationNotifier::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Creature *c = iter->getSource(); - CreatureUnitRelocationWorker(c, &i_unit); - if (isCreature) - CreatureUnitRelocationWorker((Creature*)&i_unit, c); - } -} - -void -MessageDistDeliverer::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - Player *target = iter->getSource(); - if (!target->InSamePhase(i_phaseMask)) - continue; - - if (target->GetExactDistSq(i_source) > i_distSq) - continue; - - // Send packet to all who are sharing the player's vision - if (!target->GetSharedVisionList().empty()) - { - SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); - for (; i != target->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == target) - SendPacket(*i); - } - - if (target->m_seer == target || target->GetVehicle()) - SendPacket(target); - } -} - -void -MessageDistDeliverer::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (!iter->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) - continue; - - // Send packet to all who are sharing the creature's vision - if (!iter->getSource()->GetSharedVisionList().empty()) - { - SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); - for (; i != iter->getSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->getSource()) - SendPacket(*i); - } - } -} - -void -MessageDistDeliverer::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (!iter->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) - continue; - - if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) - { - // Send packet back to the caster if the caster has vision of dynamic object - Player* caster = (Player*)iter->getSource()->GetCaster(); - if (caster && caster->m_seer == iter->getSource()) - SendPacket(caster); - } - } -} - -/* -void -MessageDistDeliverer::VisitObject(Player* plr) -{ - if (!i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam())) - { - SendPacket(plr); - } -} -*/ - -template void -ObjectUpdater::Visit(GridRefManager &m) -{ - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - { - if (iter->getSource()->IsInWorld()) - iter->getSource()->Update(i_timeDiff); - } -} - -bool CannibalizeObjectCheck::operator()(Corpse* u) -{ - // ignore bones - if (u->GetType() == CORPSE_BONES) - return false; - - Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); - - if (!owner || i_funit->IsFriendlyTo(owner)) - return false; - - if (i_funit->IsWithinDistInMap(u, i_range)) - return true; - - return false; -} - -template void ObjectUpdater::Visit(GameObjectMapType &); -template void ObjectUpdater::Visit(DynamicObjectMapType &); diff --git a/src/server/game/Grids/GridNotifiers.h b/src/server/game/Grids/GridNotifiers.h deleted file mode 100644 index b0abf0aae79..00000000000 --- a/src/server/game/Grids/GridNotifiers.h +++ /dev/null @@ -1,1232 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDNOTIFIERS_H -#define TRINITY_GRIDNOTIFIERS_H - -#include "ObjectGridLoader.h" -#include "UpdateData.h" -#include - -#include "Corpse.h" -#include "Object.h" -#include "DynamicObject.h" -#include "GameObject.h" -#include "Player.h" -#include "Unit.h" -#include "CreatureAI.h" - -class Player; -//class Map; - -namespace Trinity -{ - struct VisibleNotifier - { - Player &i_player; - UpdateData i_data; - std::set i_visibleNow; - Player::ClientGUIDs vis_guids; - - VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) {} - template void Visit(GridRefManager &m); - void SendToSelf(void); - }; - - struct VisibleChangesNotifier - { - WorldObject &i_object; - - explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {} - template void Visit(GridRefManager &) {} - void Visit(PlayerMapType &); - void Visit(CreatureMapType &); - void Visit(DynamicObjectMapType &); - }; - - struct PlayerRelocationNotifier : public VisibleNotifier - { - PlayerRelocationNotifier(Player &pl) : VisibleNotifier(pl) {} - - template void Visit(GridRefManager &m) { VisibleNotifier::Visit(m); } - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct CreatureRelocationNotifier - { - Creature &i_creature; - CreatureRelocationNotifier(Creature &c) : i_creature(c) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct DelayedUnitRelocation - { - Map &i_map; - Cell &cell; - CellPair &p; - const float i_radius; - DelayedUnitRelocation(Cell &c, CellPair &pair, Map &map, float radius) : - cell(c), p(pair), i_map(map), i_radius(radius) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - void Visit(PlayerMapType &); - }; - - struct AIRelocationNotifier - { - Unit &i_unit; - bool isCreature; - explicit AIRelocationNotifier(Unit &unit) : i_unit(unit), isCreature(unit.GetTypeId() == TYPEID_UNIT) {} - template void Visit(GridRefManager &) {} - void Visit(CreatureMapType &); - }; - - struct GridUpdater - { - GridType &i_grid; - uint32 i_timeDiff; - GridUpdater(GridType &grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) {} - - template void updateObjects(GridRefManager &m) - { - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - iter->getSource()->Update(i_timeDiff); - } - - void Visit(PlayerMapType &m) { updateObjects(m); } - void Visit(CreatureMapType &m){ updateObjects(m); } - void Visit(GameObjectMapType &m) { updateObjects(m); } - void Visit(DynamicObjectMapType &m) { updateObjects(m); } - void Visit(CorpseMapType &m) { updateObjects(m); } - }; - - struct MessageDistDeliverer - { - WorldObject *i_source; - WorldPacket *i_message; - uint32 i_phaseMask; - float i_distSq; - uint32 team; - Player const* skipped_receiver; - MessageDistDeliverer(WorldObject *src, WorldPacket *msg, float dist, bool own_team_only = false, Player const* skipped = NULL) - : i_source(src), i_message(msg), i_distSq(dist * dist), i_phaseMask(src->GetPhaseMask()) - , team((own_team_only && src->GetTypeId() == TYPEID_PLAYER) ? ((Player*)src)->GetTeam() : 0) - , skipped_receiver(skipped) - { - } - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(DynamicObjectMapType &m); - template void Visit(GridRefManager &) {} - - void SendPacket(Player* plr) - { - // never send packet to self - if (plr == i_source || (team && plr->GetTeam() != team) || skipped_receiver == plr) - return; - - plr->GetSession()->SendPacket(i_message); - } - }; - - struct ObjectUpdater - { - uint32 i_timeDiff; - explicit ObjectUpdater(const uint32 &diff) : i_timeDiff(diff) {} - template void Visit(GridRefManager &m); - void Visit(PlayerMapType &) {} - void Visit(CorpseMapType &) {} - void Visit(CreatureMapType &); - }; - - // SEARCHERS & LIST SEARCHERS & WORKERS - - // WorldObject searchers & workers - - template - struct WorldObjectSearcher - { - uint32 i_phaseMask; - WorldObject* &i_object; - Check &i_check; - - WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(GameObjectMapType &m); - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(CorpseMapType &m); - void Visit(DynamicObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct WorldObjectListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - WorldObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - void Visit(CorpseMapType &m); - void Visit(GameObjectMapType &m); - void Visit(DynamicObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct WorldObjectWorker - { - uint32 i_phaseMask; - Do const& i_do; - - WorldObjectWorker(WorldObject const* searcher, Do const& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(GameObjectMapType &m) - { - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - void Visit(CreatureMapType &m) - { - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(CorpseMapType &m) - { - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - void Visit(DynamicObjectMapType &m) - { - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // Gameobject searchers - - template - struct GameObjectSearcher - { - uint32 i_phaseMask; - GameObject* &i_object; - Check &i_check; - - GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check GO if any (Check can change requirements at each call) - template - struct GameObjectLastSearcher - { - uint32 i_phaseMask; - GameObject* &i_object; - Check& i_check; - - GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct GameObjectListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - GameObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} - - void Visit(GameObjectMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Unit searchers - - // First accepted by Check Unit if any - template - struct UnitSearcher - { - uint32 i_phaseMask; - Unit* &i_object; - Check & i_check; - - UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check Unit if any (Check can change requirements at each call) - template - struct UnitLastSearcher - { - uint32 i_phaseMask; - Unit* &i_object; - Check & i_check; - - UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // All accepted by Check units if any - template - struct UnitListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - UnitListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Creature searchers - - template - struct CreatureSearcher - { - uint32 i_phaseMask; - Creature* &i_object; - Check & i_check; - - CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - // Last accepted by Check Creature if any (Check can change requirements at each call) - template - struct CreatureLastSearcher - { - uint32 i_phaseMask; - Creature* &i_object; - Check & i_check; - - CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct CreatureListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - CreatureListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(CreatureMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct CreatureWorker - { - uint32 i_phaseMask; - Do& i_do; - - CreatureWorker(WorldObject const* searcher, Do& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(CreatureMapType &m) - { - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // Player searchers - - template - struct PlayerSearcher - { - uint32 i_phaseMask; - Player* &i_object; - Check & i_check; - - PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} - - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerListSearcher - { - uint32 i_phaseMask; - std::list &i_objects; - Check& i_check; - - PlayerListSearcher(WorldObject const* searcher, std::list &objects, Check & check) - : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} - - void Visit(PlayerMapType &m); - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerWorker - { - uint32 i_phaseMask; - Do& i_do; - - PlayerWorker(WorldObject const* searcher, Do& _do) - : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - template - struct PlayerDistWorker - { - WorldObject const* i_searcher; - float i_dist; - Do& i_do; - - PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do) - : i_searcher(searcher), i_dist(_dist), i_do(_do) {} - - void Visit(PlayerMapType &m) - { - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist)) - i_do(itr->getSource()); - } - - template void Visit(GridRefManager &) {} - }; - - // CHECKS && DO classes - - // WorldObject check classes - class RaiseDeadObjectCheck - { - public: - RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Creature* u) - { - if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || - u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() || - (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 || - (u->GetDisplayId() != u->GetNativeDisplayId())) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - class ExplodeCorpseObjectCheck - { - public: - ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (u->getDeathState() != CORPSE || u->isInFlight() || - u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - bool operator()(Creature* u) - { - if (u->getDeathState() != CORPSE || u->isInFlight() || u->isDeadByDefault() || - (u->GetDisplayId() != u->GetNativeDisplayId()) || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - class CannibalizeObjectCheck - { - public: - CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} - bool operator()(Player* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - bool operator()(Corpse* u); - bool operator()(Creature* u) - { - if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || - (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) - return false; - - return i_funit->IsWithinDistInMap(u, i_range); - } - template bool operator()(NOT_INTERESTED*) { return false; } - private: - Unit* const i_funit; - float i_range; - }; - - // WorldObject do classes - - class RespawnDo - { - public: - RespawnDo() {} - void operator()(Creature* u) const { u->Respawn(); } - void operator()(GameObject* u) const { u->Respawn(); } - void operator()(WorldObject*) const {} - void operator()(Corpse*) const {} - }; - - // GameObject checks - - class GameObjectFocusCheck - { - public: - GameObjectFocusCheck(Unit const* unit,uint32 focusId) : i_unit(unit), i_focusId(focusId) {} - bool operator()(GameObject* go) const - { - if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS) - return false; - - if (go->GetGOInfo()->spellFocus.focusId != i_focusId) - return false; - - float dist = (go->GetGOInfo()->spellFocus.dist)/2; - - return go->IsWithinDistInMap(i_unit, dist); - } - private: - Unit const* i_unit; - uint32 i_focusId; - }; - - // Find the nearest Fishing hole and return true only if source object is in range of hole - class NearestGameObjectFishingHole - { - public: - NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(GameObject* go) - { - if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, go->GetGOInfo()->fishinghole.radius)) - { - i_range = i_obj.GetDistance(go); - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - float i_range; - - // prevent clone - NearestGameObjectFishingHole(NearestGameObjectFishingHole const&); - }; - - class NearestGameObjectCheck - { - public: - NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) {} - bool operator()(GameObject* go) - { - if (i_obj.IsWithinDistInMap(go, i_range)) - { - i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - float i_range; - - // prevent clone this object - NearestGameObjectCheck(NearestGameObjectCheck const&); - }; - - // Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO) - class NearestGameObjectEntryInObjectRangeCheck - { - public: - NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj,uint32 entry, float range) : i_obj(obj), i_entry(entry), i_range(range) {} - bool operator()(GameObject* go) - { - if (go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range)) - { - i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - uint32 i_entry; - float i_range; - - // prevent clone this object - NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&); - }; - - class GameObjectWithDbGUIDCheck - { - public: - GameObjectWithDbGUIDCheck(WorldObject const& obj,uint32 db_guid) : i_obj(obj), i_db_guid(db_guid) {} - bool operator()(GameObject const* go) const - { - return go->GetDBTableGUIDLow() == i_db_guid; - } - private: - WorldObject const& i_obj; - uint32 i_db_guid; - }; - - // Unit checks - - class MostHPMissingInRange - { - public: - MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp) - { - i_hp = u->GetMaxHealth() - u->GetHealth(); - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - uint32 i_hp; - }; - - class FriendlyCCedInRange - { - public: - FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && - (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED))) - { - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - }; - - class FriendlyMissingBuffInRange - { - public: - FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} - bool operator()(Unit* u) - { - if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && - !(u->HasAura(i_spell))) - { - return true; - } - return false; - } - private: - Unit const* i_obj; - float i_range; - uint32 i_spell; - }; - - class AnyUnfriendlyUnitInObjectRangeCheck - { - public: - AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u)) - return true; - else - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnfriendlyNoTotemUnitInObjectRangeCheck - { - public: - AnyUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (!u->isAlive()) - return false; - - if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) - return false; - - return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u); - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnfriendlyVisibleUnitInObjectRangeCheck - { - public: - AnyUnfriendlyVisibleUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) - : i_obj(obj), i_funit(funit), i_range(range) {} - - bool operator()(Unit* u) - { - return u->isAlive() - && i_obj->IsWithinDistInMap(u, i_range) - && !i_funit->IsFriendlyTo(u) - && u->isVisibleForOrDetect(i_funit, false); - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class CreatureWithDbGUIDCheck - { - public: - CreatureWithDbGUIDCheck(WorldObject const* obj, uint32 lowguid) : i_obj(obj), i_lowguid(lowguid) {} - bool operator()(Creature* u) - { - return u->GetDBTableGUIDLow() == i_lowguid; - } - private: - WorldObject const* i_obj; - uint32 i_lowguid; - }; - - class AnyFriendlyUnitInObjectRangeCheck - { - public: - AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) - return true; - else - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - class AnyUnitInObjectRangeCheck - { - public: - AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - WorldObject const* i_obj; - float i_range; - }; - - // Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit) - class NearestAttackableUnitInObjectRangeCheck - { - public: - NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} - bool operator()(Unit* u) - { - if (u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) && - !i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,false)) - { - i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - - return false; - } - private: - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - - // prevent clone this object - NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); - }; - - class AnyAoETargetUnitInObjectRangeCheck - { - public: - AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) - : i_obj(obj), i_funit(funit), i_range(range) - { - Unit const* check = i_funit; - Unit const* owner = i_funit->GetOwner(); - if (owner) - check = owner; - i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER); - } - bool operator()(Unit* u) - { - // Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems - if (!u->isTargetableForAttack()) - return false; - if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) - return false; - - if ((i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u))&& i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - bool i_targetForPlayer; - WorldObject const* i_obj; - Unit const* i_funit; - float i_range; - }; - - // do attack at call of help to friendly crearture - class CallOfHelpCreatureInRangeDo - { - public: - CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range) - : i_funit(funit), i_enemy(enemy), i_range(range) - {} - void operator()(Creature* u) - { - if (u == i_funit) - return; - - if (!u->CanAssistTo(i_funit, i_enemy, false)) - return; - - // too far - if (!u->IsWithinDistInMap(i_enemy, i_range)) - return; - - // only if see assisted creature's enemy - if (!u->IsWithinLOSInMap(i_enemy)) - return; - - if (u->AI()) - u->AI()->AttackStart(i_enemy); - } - private: - Unit* const i_funit; - Unit* const i_enemy; - float i_range; - }; - - struct AnyDeadUnitCheck - { - bool operator()(Unit* u) { return !u->isAlive(); } - }; - - struct AnyStealthedCheck - { - bool operator()(Unit* u) { return u->GetVisibility() == VISIBILITY_GROUP_STEALTH; } - }; - - // Creature checks - - class NearestHostileUnitCheck - { - public: - explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0) : me(creature) - { - m_range = (dist == 0 ? 9999 : dist); - } - bool operator()(Unit* u) - { - if (!me->IsWithinDistInMap(u, m_range)) - return false; - - if (!me->canAttack(u)) - return false; - - m_range = me->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - - private: - Creature const *me; - float m_range; - NearestHostileUnitCheck(NearestHostileUnitCheck const&); - }; - - class NearestHostileUnitInAttackDistanceCheck - { - public: - explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0) : me(creature) - { - m_range = (dist == 0 ? 9999 : dist); - m_force = (dist == 0 ? false : true); - } - bool operator()(Unit* u) - { - if (!me->IsWithinDistInMap(u, m_range)) - return false; - - if (m_force) - { - if (!me->canAttack(u)) - return false; - } - else - { - if (!me->canStartAttack(u, false)) - return false; - } - - m_range = me->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - float GetLastRange() const { return m_range; } - private: - Creature const *me; - float m_range; - bool m_force; - NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&); - }; - - class AnyAssistCreatureInRangeCheck - { - public: - AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range) - : i_funit(funit), i_enemy(enemy), i_range(range) - { - } - bool operator()(Creature* u) - { - if (u == i_funit) - return false; - - if (!u->CanAssistTo(i_funit, i_enemy)) - return false; - - // too far - if (!i_funit->IsWithinDistInMap(u, i_range)) - return false; - - // only if see assisted creature - if (!i_funit->IsWithinLOSInMap(u)) - return false; - - return true; - } - private: - Unit* const i_funit; - Unit* const i_enemy; - float i_range; - }; - - class NearestAssistCreatureInCreatureRangeCheck - { - public: - NearestAssistCreatureInCreatureRangeCheck(Creature* obj, Unit* enemy, float range) - : i_obj(obj), i_enemy(enemy), i_range(range) {} - - bool operator()(Creature* u) - { - if (u == i_obj) - return false; - if (!u->CanAssistTo(i_obj,i_enemy)) - return false; - - if (!i_obj->IsWithinDistInMap(u, i_range)) - return false; - - if (!i_obj->IsWithinLOSInMap(u)) - return false; - - i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check - return true; - } - float GetLastRange() const { return i_range; } - private: - Creature* const i_obj; - Unit* const i_enemy; - float i_range; - - // prevent clone this object - NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&); - }; - - // Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature) - class NearestCreatureEntryWithLiveStateInObjectRangeCheck - { - public: - NearestCreatureEntryWithLiveStateInObjectRangeCheck(WorldObject const& obj, uint32 entry, bool alive, float range) - : i_obj(obj), i_entry(entry), i_alive(alive), i_range(range) {} - - bool operator()(Creature* u) - { - if (u->GetEntry() == i_entry && u->isAlive() == i_alive && i_obj.IsWithinDistInMap(u, i_range)) - { - i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check - return true; - } - return false; - } - float GetLastRange() const { return i_range; } - private: - WorldObject const& i_obj; - uint32 i_entry; - bool i_alive; - float i_range; - - // prevent clone this object - NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&); - }; - - class AnyPlayerInObjectRangeCheck - { - public: - AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} - bool operator()(Player* u) - { - if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) - return true; - - return false; - } - private: - WorldObject const* i_obj; - float i_range; - }; - - class AllFriendlyCreaturesInGrid - { - public: - AllFriendlyCreaturesInGrid(Unit const* obj) : pUnit(obj) {} - bool operator() (Unit* u) - { - if (u->isAlive() && u->GetVisibility() == VISIBILITY_ON && u->IsFriendlyTo(pUnit)) - return true; - - return false; - } - private: - Unit const* pUnit; - }; - - class AllGameObjectsWithEntryInRange - { - public: - AllGameObjectsWithEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} - bool operator() (GameObject* pGo) - { - if (pGo->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pGo,m_fRange,false)) - return true; - - return false; - } - private: - const WorldObject* m_pObject; - uint32 m_uiEntry; - float m_fRange; - }; - - class AllCreaturesOfEntryInRange - { - public: - AllCreaturesOfEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} - bool operator() (Unit* pUnit) - { - if (pUnit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pUnit,m_fRange,false)) - return true; - - return false; - } - - private: - const WorldObject* m_pObject; - uint32 m_uiEntry; - float m_fRange; - }; - - class PlayerAtMinimumRangeAway - { - public: - PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : pUnit(unit), fRange(fMinRange) {} - bool operator() (Player* pPlayer) - { - //No threat list check, must be done explicit if expected to be in combat with creature - if (!pPlayer->isGameMaster() && pPlayer->isAlive() && !pUnit->IsWithinDist(pPlayer,fRange,false)) - return true; - - return false; - } - - private: - Unit const* pUnit; - float fRange; - }; - - class GameObjectInRangeCheck - { - public: - GameObjectInRangeCheck(float _x, float _y, float _z, float _range) : x(_x), y(_y), z(_z), range(_range) {} - bool operator() (GameObject* go) - { - return go->IsInRange(x, y, z, range); - } - private: - float x, y, z, range; - }; - - // Player checks and do - - // Prepare using Builder localized packets with caching and send to player - template - class LocalizedPacketDo - { - public: - explicit LocalizedPacketDo(Builder& builder) : i_builder(builder) {} - - ~LocalizedPacketDo() - { - for (size_t i = 0; i < i_data_cache.size(); ++i) - delete i_data_cache[i]; - } - void operator()(Player* p); - - private: - Builder& i_builder; - std::vector i_data_cache; // 0 = default, i => i-1 locale index - }; - - // Prepare using Builder localized packets with caching and send to player - template - class LocalizedPacketListDo - { - public: - typedef std::vector WorldPacketList; - explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {} - - ~LocalizedPacketListDo() - { - for (size_t i = 0; i < i_data_cache.size(); ++i) - for (size_t j = 0; j < i_data_cache[i].size(); ++j) - delete i_data_cache[i][j]; - } - void operator()(Player* p); - - private: - Builder& i_builder; - std::vector i_data_cache; - // 0 = default, i => i-1 locale index - }; -} -#endif diff --git a/src/server/game/Grids/GridNotifiersImpl.h b/src/server/game/Grids/GridNotifiersImpl.h deleted file mode 100644 index 26a9c0bd328..00000000000 --- a/src/server/game/Grids/GridNotifiersImpl.h +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRINITY_GRIDNOTIFIERSIMPL_H -#define TRINITY_GRIDNOTIFIERSIMPL_H - -#include "GridNotifiers.h" -#include "WorldPacket.h" -#include "Corpse.h" -#include "Player.h" -#include "UpdateData.h" -#include "CreatureAI.h" -#include "SpellAuras.h" - - -template -inline void -Trinity::VisibleNotifier::Visit(GridRefManager &m) -{ - for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) - { - vis_guids.erase(iter->getSource()->GetGUID()); - i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow); - } -} - -inline void -Trinity::ObjectUpdater::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - if (iter->getSource()->IsInWorld() && !iter->getSource()->isSpiritService()) - iter->getSource()->Update(i_timeDiff); -} - -// SEARCHERS & LIST SEARCHERS & WORKERS - -// WorldObject searchers & workers - -template -void Trinity::WorldObjectSearcher::Visit(GameObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(CorpseMapType &m) -{ - // already found - if (i_object) - return; - - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectSearcher::Visit(DynamicObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::WorldObjectListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(CorpseMapType &m) -{ - for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::WorldObjectListSearcher::Visit(DynamicObjectMapType &m) -{ - for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Gameobject searchers - -template -void Trinity::GameObjectSearcher::Visit(GameObjectMapType &m) -{ - // already found - if (i_object) - return; - - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::GameObjectLastSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::GameObjectListSearcher::Visit(GameObjectMapType &m) -{ - for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Unit searchers - -template -void Trinity::UnitSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::UnitSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::UnitLastSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::UnitLastSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::UnitListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::UnitListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -// Creature searchers - -template -void Trinity::CreatureSearcher::Visit(CreatureMapType &m) -{ - // already found - if (i_object) - return; - - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::CreatureLastSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - i_object = itr->getSource(); - } -} - -template -void Trinity::CreatureListSearcher::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::PlayerListSearcher::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->InSamePhase(i_phaseMask)) - if (i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); -} - -template -void Trinity::PlayerSearcher::Visit(PlayerMapType &m) -{ - // already found - if (i_object) - return; - - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - { - if (!itr->getSource()->InSamePhase(i_phaseMask)) - continue; - - if (i_check(itr->getSource())) - { - i_object = itr->getSource(); - return; - } - } -} - -template -void Trinity::LocalizedPacketDo::operator()(Player* p) -{ - int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; - WorldPacket* data; - - // create if not cached yet - if (i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx]) - { - if (i_data_cache.size() < cache_idx+1) - i_data_cache.resize(cache_idx+1); - - data = new WorldPacket(SMSG_MESSAGECHAT, 200); - - i_builder(*data,loc_idx); - - i_data_cache[cache_idx] = data; - } - else - data = i_data_cache[cache_idx]; - - p->SendDirectMessage(data); -} - -template -void Trinity::LocalizedPacketListDo::operator()(Player* p) -{ - int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); - uint32 cache_idx = loc_idx+1; - WorldPacketList* data_list; - - // create if not cached yet - if (i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty()) - { - if (i_data_cache.size() < cache_idx+1) - i_data_cache.resize(cache_idx+1); - - data_list = &i_data_cache[cache_idx]; - - i_builder(*data_list,loc_idx); - } - else - data_list = &i_data_cache[cache_idx]; - - for (size_t i = 0; i < data_list->size(); ++i) - p->SendDirectMessage((*data_list)[i]); -} - -#endif // TRINITY_GRIDNOTIFIERSIMPL_H diff --git a/src/server/game/Grids/GridRefManager.h b/src/server/game/Grids/GridRefManager.h new file mode 100644 index 00000000000..79799105fb7 --- /dev/null +++ b/src/server/game/Grids/GridRefManager.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GRIDREFMANAGER +#define _GRIDREFMANAGER + +#include "Utilities/LinkedReference/RefManager.h" + +template +class GridReference; + +template +class GridRefManager : public RefManager, OBJECT> +{ + public: + typedef LinkedListHead::Iterator< GridReference > iterator; + + GridReference* getFirst() { return (GridReference*)RefManager, OBJECT>::getFirst(); } + GridReference* getLast() { return (GridReference*)RefManager, OBJECT>::getLast(); } + + iterator begin() { return iterator(getFirst()); } + iterator end() { return iterator(NULL); } + iterator rbegin() { return iterator(getLast()); } + iterator rend() { return iterator(NULL); } +}; +#endif + diff --git a/src/server/game/Grids/GridReference.h b/src/server/game/Grids/GridReference.h new file mode 100644 index 00000000000..d2e3a455895 --- /dev/null +++ b/src/server/game/Grids/GridReference.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GRIDREFERENCE_H +#define _GRIDREFERENCE_H + +#include "Utilities/LinkedReference/Reference.h" + +template +class GridRefManager; + +template +class GridReference : public Reference, OBJECT> +{ + protected: + void targetObjectBuildLink() + { + // called from link() + this->getTarget()->insertFirst(this); + this->getTarget()->incSize(); + } + void targetObjectDestroyLink() + { + // called from unlink() + if(this->isValid()) this->getTarget()->decSize(); + } + void sourceObjectDestroyLink() + { + // called from invalidate() + this->getTarget()->decSize(); + } + public: + GridReference() : Reference, OBJECT>() {} + ~GridReference() { this->unlink(); } + GridReference *next() { return (GridReference*)Reference, OBJECT>::next(); } +}; +#endif + diff --git a/src/server/game/Grids/NGrid.h b/src/server/game/Grids/NGrid.h new file mode 100644 index 00000000000..3810286e123 --- /dev/null +++ b/src/server/game/Grids/NGrid.h @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_NGRID_H +#define TRINITY_NGRID_H + +/** NGrid is nothing more than a wrapper of the Grid with an NxN cells + */ + +#include "GameSystem/Grid.h" +#include "GameSystem/GridReference.h" +#include "Timer.h" +#include "Util.h" + +#define DEFAULT_VISIBILITY_NOTIFY_PERIOD 1000 + +class GridInfo +{ +public: + GridInfo() + : i_timer(0), i_unloadActiveLockCount(0), i_unloadExplicitLock(false), i_unloadReferenceLock(false), + vis_Update(0, irand(0,DEFAULT_VISIBILITY_NOTIFY_PERIOD)) {} + GridInfo(time_t expiry, bool unload = true ) + : i_timer(expiry), i_unloadActiveLockCount(0), i_unloadExplicitLock(!unload), i_unloadReferenceLock(false), + vis_Update(0, irand(0,DEFAULT_VISIBILITY_NOTIFY_PERIOD)) {} + const TimeTracker& getTimeTracker() const { return i_timer; } + bool getUnloadLock() const { return i_unloadActiveLockCount || i_unloadExplicitLock || i_unloadReferenceLock; } + void setUnloadExplicitLock( bool on ) { i_unloadExplicitLock = on; } + void setUnloadReferenceLock( bool on ) { i_unloadReferenceLock = on; } + void incUnloadActiveLock() { ++i_unloadActiveLockCount; } + void decUnloadActiveLock() { if(i_unloadActiveLockCount) --i_unloadActiveLockCount; } + + void setTimer(const TimeTracker& pTimer) { i_timer = pTimer; } + void ResetTimeTracker(time_t interval) { i_timer.Reset(interval); } + void UpdateTimeTracker(time_t diff) { i_timer.Update(diff); } + PeriodicTimer& getRelocationTimer() { return vis_Update; } +private: + TimeTracker i_timer; + PeriodicTimer vis_Update; + + uint16 i_unloadActiveLockCount : 16; // lock from active object spawn points (prevent clone loading) + bool i_unloadExplicitLock : 1; // explicit manual lock or config setting + bool i_unloadReferenceLock : 1; // lock from instance map copy +}; + +typedef enum +{ + GRID_STATE_INVALID = 0, + GRID_STATE_ACTIVE = 1, + GRID_STATE_IDLE = 2, + GRID_STATE_REMOVAL= 3, + MAX_GRID_STATE = 4 +} grid_state_t; + +template +< +unsigned int N, +class ACTIVE_OBJECT, +class WORLD_OBJECT_TYPES, +class GRID_OBJECT_TYPES, +class ThreadModel = Trinity::SingleThreaded +> +class NGrid +{ + public: + + typedef Grid GridType; + NGrid(uint32 id, int32 x, int32 y, time_t expiry, bool unload = true) + : i_gridId(id), i_x(x), i_y(y), i_cellstate(GRID_STATE_INVALID), i_GridObjectDataLoaded(false) + { + i_GridInfo = GridInfo(expiry, unload); + } + + const GridType& operator()(unsigned short x, unsigned short y) const + { + ASSERT(x < N); + ASSERT(y < N); + return i_cells[x][y]; + } + + GridType& operator()(unsigned short x, unsigned short y) + { + ASSERT(x < N); + ASSERT(y < N); + return i_cells[x][y]; + } + + const uint32& GetGridId(void) const { return i_gridId; } + void SetGridId(const uint32 id) const { i_gridId = id; } + grid_state_t GetGridState(void) const { return i_cellstate; } + void SetGridState(grid_state_t s) { i_cellstate = s; } + int32 getX() const { return i_x; } + int32 getY() const { return i_y; } + + void link(GridRefManager >* pTo) + { + i_Reference.link(pTo, this); + } + bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; } + void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; } + + GridInfo* getGridInfoRef() { return &i_GridInfo; } + const TimeTracker& getTimeTracker() const { return i_GridInfo.getTimeTracker(); } + bool getUnloadLock() const { return i_GridInfo.getUnloadLock(); } + void setUnloadExplicitLock( bool on ) { i_GridInfo.setUnloadExplicitLock(on); } + void setUnloadReferenceLock( bool on ) { i_GridInfo.setUnloadReferenceLock(on); } + void incUnloadActiveLock() { i_GridInfo.incUnloadActiveLock(); } + void decUnloadActiveLock() { i_GridInfo.decUnloadActiveLock(); } + void ResetTimeTracker(time_t interval) { i_GridInfo.ResetTimeTracker(interval); } + void UpdateTimeTracker(time_t diff) { i_GridInfo.UpdateTimeTracker(diff); } + + template void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) + { + getGridType(x, y).AddWorldObject(obj); + } + + template void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) + { + getGridType(x, y).RemoveWorldObject(obj); + } + + template void Visit(TypeContainerVisitor > &visitor) + { + for (unsigned int x=0; x < N; ++x) + for (unsigned int y=0; y < N; ++y) + getGridType(x, y).Visit(visitor); + } + + template void Visit(const uint32 &x, const uint32 &y, TypeContainerVisitor > &visitor) + { + getGridType(x, y).Visit(visitor); + } + + unsigned int ActiveObjectsInGrid(void) const + { + unsigned int count=0; + for (unsigned int x=0; x < N; ++x) + for (unsigned int y=0; y < N; ++y) + count += i_cells[x][y].ActiveObjectsInGrid(); + return count; + } + + template bool AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) + { + return getGridType(x, y).AddGridObject(obj); + } + + template bool RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) + { + return getGridType(x, y).RemoveGridObject(obj); + } + + private: + + GridType& getGridType(const uint32& x, const uint32& y) + { + ASSERT(x < N); + ASSERT(y < N); + return i_cells[x][y]; + } + + uint32 i_gridId; + GridInfo i_GridInfo; + GridReference > i_Reference; + int32 i_x; + int32 i_y; + grid_state_t i_cellstate; + GridType i_cells[N][N]; + bool i_GridObjectDataLoaded; +}; +#endif + diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp new file mode 100644 index 00000000000..b10dfa8791e --- /dev/null +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "UpdateData.h" +#include "Item.h" +#include "Map.h" +#include "Transports.h" +#include "ObjectAccessor.h" +#include "CellImpl.h" + +using namespace Trinity; + +void +VisibleNotifier::SendToSelf() +{ + // at this moment i_clientGUIDs have guids that not iterate at grid level checks + // but exist one case when this possible and object not out of range: transports + if (Transport* transport = i_player.GetTransport()) + for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr != transport->GetPassengers().end();++itr) + { + if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end()) + { + vis_guids.erase((*itr)->GetGUID()); + + i_player.UpdateVisibilityOf((*itr), i_data, i_visibleNow); + + if (!(*itr)->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + (*itr)->UpdateVisibilityOf(&i_player); + } + } + + for (Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end(); ++it) + { + i_player.m_clientGUIDs.erase(*it); + i_data.AddOutOfRangeGUID(*it); + + if (IS_PLAYER_GUID(*it)) + { + Player* plr = ObjectAccessor::FindPlayer(*it); + if (plr && plr->IsInWorld() && !plr->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + plr->UpdateVisibilityOf(&i_player); + } + } + + if (!i_data.HasData()) + return; + + WorldPacket packet; + i_data.BuildPacket(&packet); + i_player.GetSession()->SendPacket(&packet); + + for (std::set::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it) + i_player.SendInitialVisiblePackets(*it); +} + +void +VisibleChangesNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + if (iter->getSource() == &i_object) + continue; + + iter->getSource()->UpdateVisibilityOf(&i_object); + + if (!iter->getSource()->GetSharedVisionList().empty()) + for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + (*i)->UpdateVisibilityOf(&i_object); + } +} + +void +VisibleChangesNotifier::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if (!iter->getSource()->GetSharedVisionList().empty()) + for (SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + (*i)->UpdateVisibilityOf(&i_object); +} + +void +VisibleChangesNotifier::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) + if (Player* caster = (Player*)iter->getSource()->GetCaster()) + if (caster->m_seer == iter->getSource()) + caster->UpdateVisibilityOf(&i_object); +} + +inline void CreatureUnitRelocationWorker(Creature* c, Unit* u) +{ + if (!u->isAlive() || !c->isAlive() || c == u || u->isInFlight()) + return; + + if (c->HasReactState(REACT_AGGRESSIVE) && !c->hasUnitState(UNIT_STAT_SIGHTLESS)) + if (c->_IsWithinDist(u, c->m_SightDistance, true) && c->IsAIEnabled) + c->AI()->MoveInLineOfSight_Safe(u); +} + +void PlayerRelocationNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Player* plr = iter->getSource(); + + vis_guids.erase(plr->GetGUID()); + + i_player.UpdateVisibilityOf(plr,i_data,i_visibleNow); + + if (plr->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + plr->UpdateVisibilityOf(&i_player); + } +} + +void PlayerRelocationNotifier::Visit(CreatureMapType &m) +{ + bool relocated_for_ai = (&i_player == i_player.m_seer); + + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Creature * c = iter->getSource(); + + vis_guids.erase(c->GetGUID()); + + i_player.UpdateVisibilityOf(c,i_data,i_visibleNow); + + if (relocated_for_ai && !c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + CreatureUnitRelocationWorker(c, &i_player); + } +} + +void CreatureRelocationNotifier::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Player * pl = iter->getSource(); + + if (!pl->m_seer->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + pl->UpdateVisibilityOf(&i_creature); + + CreatureUnitRelocationWorker(&i_creature, pl); + } +} + +void CreatureRelocationNotifier::Visit(CreatureMapType &m) +{ + if (!i_creature.isAlive()) + return; + + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + { + Creature* c = iter->getSource(); + CreatureUnitRelocationWorker(&i_creature, c); + + if (!c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + CreatureUnitRelocationWorker(c, &i_creature); + } +} + +void DelayedUnitRelocation::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Creature * unit = iter->getSource(); + if (!unit->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + CreatureRelocationNotifier relocate(*unit); + + TypeContainerVisitor c2world_relocation(relocate); + TypeContainerVisitor c2grid_relocation(relocate); + + cell.Visit(p, c2world_relocation, i_map, *unit, i_radius); + cell.Visit(p, c2grid_relocation, i_map, *unit, i_radius); + } +} + +void DelayedUnitRelocation::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Player * player = iter->getSource(); + WorldObject const *viewPoint = player->m_seer; + + if (!viewPoint->isNeedNotify(NOTIFY_VISIBILITY_CHANGED)) + continue; + + if (player != viewPoint && !viewPoint->IsPositionValid()) + continue; + + CellPair pair2(Trinity::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY())); + Cell cell2(pair2); + //cell.SetNoCreate(); need load cells around viewPoint or player, that's why its commented + + PlayerRelocationNotifier relocate(*player); + TypeContainerVisitor c2world_relocation(relocate); + TypeContainerVisitor c2grid_relocation(relocate); + + cell2.Visit(pair2, c2world_relocation, i_map, *viewPoint, i_radius); + cell2.Visit(pair2, c2grid_relocation, i_map, *viewPoint, i_radius); + + relocate.SendToSelf(); + } +} + +void AIRelocationNotifier::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Creature *c = iter->getSource(); + CreatureUnitRelocationWorker(c, &i_unit); + if (isCreature) + CreatureUnitRelocationWorker((Creature*)&i_unit, c); + } +} + +void +MessageDistDeliverer::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + Player *target = iter->getSource(); + if (!target->InSamePhase(i_phaseMask)) + continue; + + if (target->GetExactDistSq(i_source) > i_distSq) + continue; + + // Send packet to all who are sharing the player's vision + if (!target->GetSharedVisionList().empty()) + { + SharedVisionList::const_iterator i = target->GetSharedVisionList().begin(); + for (; i != target->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == target) + SendPacket(*i); + } + + if (target->m_seer == target || target->GetVehicle()) + SendPacket(target); + } +} + +void +MessageDistDeliverer::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) + continue; + + // Send packet to all who are sharing the creature's vision + if (!iter->getSource()->GetSharedVisionList().empty()) + { + SharedVisionList::const_iterator i = iter->getSource()->GetSharedVisionList().begin(); + for (; i != iter->getSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->getSource()) + SendPacket(*i); + } + } +} + +void +MessageDistDeliverer::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (iter->getSource()->GetExactDistSq(i_source) > i_distSq) + continue; + + if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) + { + // Send packet back to the caster if the caster has vision of dynamic object + Player* caster = (Player*)iter->getSource()->GetCaster(); + if (caster && caster->m_seer == iter->getSource()) + SendPacket(caster); + } + } +} + +/* +void +MessageDistDeliverer::VisitObject(Player* plr) +{ + if (!i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam())) + { + SendPacket(plr); + } +} +*/ + +template void +ObjectUpdater::Visit(GridRefManager &m) +{ + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + if (iter->getSource()->IsInWorld()) + iter->getSource()->Update(i_timeDiff); + } +} + +bool CannibalizeObjectCheck::operator()(Corpse* u) +{ + // ignore bones + if (u->GetType() == CORPSE_BONES) + return false; + + Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); + + if (!owner || i_funit->IsFriendlyTo(owner)) + return false; + + if (i_funit->IsWithinDistInMap(u, i_range)) + return true; + + return false; +} + +template void ObjectUpdater::Visit(GameObjectMapType &); +template void ObjectUpdater::Visit(DynamicObjectMapType &); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h new file mode 100644 index 00000000000..b0abf0aae79 --- /dev/null +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -0,0 +1,1232 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDNOTIFIERS_H +#define TRINITY_GRIDNOTIFIERS_H + +#include "ObjectGridLoader.h" +#include "UpdateData.h" +#include + +#include "Corpse.h" +#include "Object.h" +#include "DynamicObject.h" +#include "GameObject.h" +#include "Player.h" +#include "Unit.h" +#include "CreatureAI.h" + +class Player; +//class Map; + +namespace Trinity +{ + struct VisibleNotifier + { + Player &i_player; + UpdateData i_data; + std::set i_visibleNow; + Player::ClientGUIDs vis_guids; + + VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) {} + template void Visit(GridRefManager &m); + void SendToSelf(void); + }; + + struct VisibleChangesNotifier + { + WorldObject &i_object; + + explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {} + template void Visit(GridRefManager &) {} + void Visit(PlayerMapType &); + void Visit(CreatureMapType &); + void Visit(DynamicObjectMapType &); + }; + + struct PlayerRelocationNotifier : public VisibleNotifier + { + PlayerRelocationNotifier(Player &pl) : VisibleNotifier(pl) {} + + template void Visit(GridRefManager &m) { VisibleNotifier::Visit(m); } + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct CreatureRelocationNotifier + { + Creature &i_creature; + CreatureRelocationNotifier(Creature &c) : i_creature(c) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct DelayedUnitRelocation + { + Map &i_map; + Cell &cell; + CellPair &p; + const float i_radius; + DelayedUnitRelocation(Cell &c, CellPair &pair, Map &map, float radius) : + cell(c), p(pair), i_map(map), i_radius(radius) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + void Visit(PlayerMapType &); + }; + + struct AIRelocationNotifier + { + Unit &i_unit; + bool isCreature; + explicit AIRelocationNotifier(Unit &unit) : i_unit(unit), isCreature(unit.GetTypeId() == TYPEID_UNIT) {} + template void Visit(GridRefManager &) {} + void Visit(CreatureMapType &); + }; + + struct GridUpdater + { + GridType &i_grid; + uint32 i_timeDiff; + GridUpdater(GridType &grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) {} + + template void updateObjects(GridRefManager &m) + { + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + iter->getSource()->Update(i_timeDiff); + } + + void Visit(PlayerMapType &m) { updateObjects(m); } + void Visit(CreatureMapType &m){ updateObjects(m); } + void Visit(GameObjectMapType &m) { updateObjects(m); } + void Visit(DynamicObjectMapType &m) { updateObjects(m); } + void Visit(CorpseMapType &m) { updateObjects(m); } + }; + + struct MessageDistDeliverer + { + WorldObject *i_source; + WorldPacket *i_message; + uint32 i_phaseMask; + float i_distSq; + uint32 team; + Player const* skipped_receiver; + MessageDistDeliverer(WorldObject *src, WorldPacket *msg, float dist, bool own_team_only = false, Player const* skipped = NULL) + : i_source(src), i_message(msg), i_distSq(dist * dist), i_phaseMask(src->GetPhaseMask()) + , team((own_team_only && src->GetTypeId() == TYPEID_PLAYER) ? ((Player*)src)->GetTeam() : 0) + , skipped_receiver(skipped) + { + } + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(DynamicObjectMapType &m); + template void Visit(GridRefManager &) {} + + void SendPacket(Player* plr) + { + // never send packet to self + if (plr == i_source || (team && plr->GetTeam() != team) || skipped_receiver == plr) + return; + + plr->GetSession()->SendPacket(i_message); + } + }; + + struct ObjectUpdater + { + uint32 i_timeDiff; + explicit ObjectUpdater(const uint32 &diff) : i_timeDiff(diff) {} + template void Visit(GridRefManager &m); + void Visit(PlayerMapType &) {} + void Visit(CorpseMapType &) {} + void Visit(CreatureMapType &); + }; + + // SEARCHERS & LIST SEARCHERS & WORKERS + + // WorldObject searchers & workers + + template + struct WorldObjectSearcher + { + uint32 i_phaseMask; + WorldObject* &i_object; + Check &i_check; + + WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(DynamicObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct WorldObjectListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + WorldObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + void Visit(CorpseMapType &m); + void Visit(GameObjectMapType &m); + void Visit(DynamicObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct WorldObjectWorker + { + uint32 i_phaseMask; + Do const& i_do; + + WorldObjectWorker(WorldObject const* searcher, Do const& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(GameObjectMapType &m) + { + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + void Visit(CreatureMapType &m) + { + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(CorpseMapType &m) + { + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + void Visit(DynamicObjectMapType &m) + { + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // Gameobject searchers + + template + struct GameObjectSearcher + { + uint32 i_phaseMask; + GameObject* &i_object; + Check &i_check; + + GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check GO if any (Check can change requirements at each call) + template + struct GameObjectLastSearcher + { + uint32 i_phaseMask; + GameObject* &i_object; + Check& i_check; + + GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct GameObjectListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + GameObjectListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} + + void Visit(GameObjectMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Unit searchers + + // First accepted by Check Unit if any + template + struct UnitSearcher + { + uint32 i_phaseMask; + Unit* &i_object; + Check & i_check; + + UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check Unit if any (Check can change requirements at each call) + template + struct UnitLastSearcher + { + uint32 i_phaseMask; + Unit* &i_object; + Check & i_check; + + UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // All accepted by Check units if any + template + struct UnitListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + UnitListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Creature searchers + + template + struct CreatureSearcher + { + uint32 i_phaseMask; + Creature* &i_object; + Check & i_check; + + CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + // Last accepted by Check Creature if any (Check can change requirements at each call) + template + struct CreatureLastSearcher + { + uint32 i_phaseMask; + Creature* &i_object; + Check & i_check; + + CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct CreatureListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + CreatureListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(CreatureMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct CreatureWorker + { + uint32 i_phaseMask; + Do& i_do; + + CreatureWorker(WorldObject const* searcher, Do& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(CreatureMapType &m) + { + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // Player searchers + + template + struct PlayerSearcher + { + uint32 i_phaseMask; + Player* &i_object; + Check & i_check; + + PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} + + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerListSearcher + { + uint32 i_phaseMask; + std::list &i_objects; + Check& i_check; + + PlayerListSearcher(WorldObject const* searcher, std::list &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} + + void Visit(PlayerMapType &m); + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerWorker + { + uint32 i_phaseMask; + Do& i_do; + + PlayerWorker(WorldObject const* searcher, Do& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + template + struct PlayerDistWorker + { + WorldObject const* i_searcher; + float i_dist; + Do& i_do; + + PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do) + : i_searcher(searcher), i_dist(_dist), i_do(_do) {} + + void Visit(PlayerMapType &m) + { + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist)) + i_do(itr->getSource()); + } + + template void Visit(GridRefManager &) {} + }; + + // CHECKS && DO classes + + // WorldObject check classes + class RaiseDeadObjectCheck + { + public: + RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Creature* u) + { + if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || + u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() || + (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 || + (u->GetDisplayId() != u->GetNativeDisplayId())) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + class ExplodeCorpseObjectCheck + { + public: + ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Player* u) + { + if (u->getDeathState() != CORPSE || u->isInFlight() || + u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + bool operator()(Creature* u) + { + if (u->getDeathState() != CORPSE || u->isInFlight() || u->isDeadByDefault() || + (u->GetDisplayId() != u->GetNativeDisplayId()) || + (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) != 0) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + class CannibalizeObjectCheck + { + public: + CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} + bool operator()(Player* u) + { + if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight()) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + bool operator()(Corpse* u); + bool operator()(Creature* u) + { + if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || + (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) == 0) + return false; + + return i_funit->IsWithinDistInMap(u, i_range); + } + template bool operator()(NOT_INTERESTED*) { return false; } + private: + Unit* const i_funit; + float i_range; + }; + + // WorldObject do classes + + class RespawnDo + { + public: + RespawnDo() {} + void operator()(Creature* u) const { u->Respawn(); } + void operator()(GameObject* u) const { u->Respawn(); } + void operator()(WorldObject*) const {} + void operator()(Corpse*) const {} + }; + + // GameObject checks + + class GameObjectFocusCheck + { + public: + GameObjectFocusCheck(Unit const* unit,uint32 focusId) : i_unit(unit), i_focusId(focusId) {} + bool operator()(GameObject* go) const + { + if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS) + return false; + + if (go->GetGOInfo()->spellFocus.focusId != i_focusId) + return false; + + float dist = (go->GetGOInfo()->spellFocus.dist)/2; + + return go->IsWithinDistInMap(i_unit, dist); + } + private: + Unit const* i_unit; + uint32 i_focusId; + }; + + // Find the nearest Fishing hole and return true only if source object is in range of hole + class NearestGameObjectFishingHole + { + public: + NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(GameObject* go) + { + if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, go->GetGOInfo()->fishinghole.radius)) + { + i_range = i_obj.GetDistance(go); + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + float i_range; + + // prevent clone + NearestGameObjectFishingHole(NearestGameObjectFishingHole const&); + }; + + class NearestGameObjectCheck + { + public: + NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) {} + bool operator()(GameObject* go) + { + if (i_obj.IsWithinDistInMap(go, i_range)) + { + i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + float i_range; + + // prevent clone this object + NearestGameObjectCheck(NearestGameObjectCheck const&); + }; + + // Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO) + class NearestGameObjectEntryInObjectRangeCheck + { + public: + NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj,uint32 entry, float range) : i_obj(obj), i_entry(entry), i_range(range) {} + bool operator()(GameObject* go) + { + if (go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range)) + { + i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + uint32 i_entry; + float i_range; + + // prevent clone this object + NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&); + }; + + class GameObjectWithDbGUIDCheck + { + public: + GameObjectWithDbGUIDCheck(WorldObject const& obj,uint32 db_guid) : i_obj(obj), i_db_guid(db_guid) {} + bool operator()(GameObject const* go) const + { + return go->GetDBTableGUIDLow() == i_db_guid; + } + private: + WorldObject const& i_obj; + uint32 i_db_guid; + }; + + // Unit checks + + class MostHPMissingInRange + { + public: + MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp) + { + i_hp = u->GetMaxHealth() - u->GetHealth(); + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + uint32 i_hp; + }; + + class FriendlyCCedInRange + { + public: + FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && + (u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED))) + { + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + }; + + class FriendlyMissingBuffInRange + { + public: + FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} + bool operator()(Unit* u) + { + if (u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && + !(u->HasAura(i_spell))) + { + return true; + } + return false; + } + private: + Unit const* i_obj; + float i_range; + uint32 i_spell; + }; + + class AnyUnfriendlyUnitInObjectRangeCheck + { + public: + AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u)) + return true; + else + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnfriendlyNoTotemUnitInObjectRangeCheck + { + public: + AnyUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (!u->isAlive()) + return false; + + if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) + return false; + + return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u); + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnfriendlyVisibleUnitInObjectRangeCheck + { + public: + AnyUnfriendlyVisibleUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) + : i_obj(obj), i_funit(funit), i_range(range) {} + + bool operator()(Unit* u) + { + return u->isAlive() + && i_obj->IsWithinDistInMap(u, i_range) + && !i_funit->IsFriendlyTo(u) + && u->isVisibleForOrDetect(i_funit, false); + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class CreatureWithDbGUIDCheck + { + public: + CreatureWithDbGUIDCheck(WorldObject const* obj, uint32 lowguid) : i_obj(obj), i_lowguid(lowguid) {} + bool operator()(Creature* u) + { + return u->GetDBTableGUIDLow() == i_lowguid; + } + private: + WorldObject const* i_obj; + uint32 i_lowguid; + }; + + class AnyFriendlyUnitInObjectRangeCheck + { + public: + AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) + return true; + else + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + class AnyUnitInObjectRangeCheck + { + public: + AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + WorldObject const* i_obj; + float i_range; + }; + + // Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit) + class NearestAttackableUnitInObjectRangeCheck + { + public: + NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} + bool operator()(Unit* u) + { + if (u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) && + !i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,false)) + { + i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + + return false; + } + private: + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + + // prevent clone this object + NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); + }; + + class AnyAoETargetUnitInObjectRangeCheck + { + public: + AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) + : i_obj(obj), i_funit(funit), i_range(range) + { + Unit const* check = i_funit; + Unit const* owner = i_funit->GetOwner(); + if (owner) + check = owner; + i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER); + } + bool operator()(Unit* u) + { + // Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems + if (!u->isTargetableForAttack()) + return false; + if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem()) + return false; + + if ((i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u))&& i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + bool i_targetForPlayer; + WorldObject const* i_obj; + Unit const* i_funit; + float i_range; + }; + + // do attack at call of help to friendly crearture + class CallOfHelpCreatureInRangeDo + { + public: + CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range) + : i_funit(funit), i_enemy(enemy), i_range(range) + {} + void operator()(Creature* u) + { + if (u == i_funit) + return; + + if (!u->CanAssistTo(i_funit, i_enemy, false)) + return; + + // too far + if (!u->IsWithinDistInMap(i_enemy, i_range)) + return; + + // only if see assisted creature's enemy + if (!u->IsWithinLOSInMap(i_enemy)) + return; + + if (u->AI()) + u->AI()->AttackStart(i_enemy); + } + private: + Unit* const i_funit; + Unit* const i_enemy; + float i_range; + }; + + struct AnyDeadUnitCheck + { + bool operator()(Unit* u) { return !u->isAlive(); } + }; + + struct AnyStealthedCheck + { + bool operator()(Unit* u) { return u->GetVisibility() == VISIBILITY_GROUP_STEALTH; } + }; + + // Creature checks + + class NearestHostileUnitCheck + { + public: + explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0) : me(creature) + { + m_range = (dist == 0 ? 9999 : dist); + } + bool operator()(Unit* u) + { + if (!me->IsWithinDistInMap(u, m_range)) + return false; + + if (!me->canAttack(u)) + return false; + + m_range = me->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + + private: + Creature const *me; + float m_range; + NearestHostileUnitCheck(NearestHostileUnitCheck const&); + }; + + class NearestHostileUnitInAttackDistanceCheck + { + public: + explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist = 0) : me(creature) + { + m_range = (dist == 0 ? 9999 : dist); + m_force = (dist == 0 ? false : true); + } + bool operator()(Unit* u) + { + if (!me->IsWithinDistInMap(u, m_range)) + return false; + + if (m_force) + { + if (!me->canAttack(u)) + return false; + } + else + { + if (!me->canStartAttack(u, false)) + return false; + } + + m_range = me->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + float GetLastRange() const { return m_range; } + private: + Creature const *me; + float m_range; + bool m_force; + NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&); + }; + + class AnyAssistCreatureInRangeCheck + { + public: + AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range) + : i_funit(funit), i_enemy(enemy), i_range(range) + { + } + bool operator()(Creature* u) + { + if (u == i_funit) + return false; + + if (!u->CanAssistTo(i_funit, i_enemy)) + return false; + + // too far + if (!i_funit->IsWithinDistInMap(u, i_range)) + return false; + + // only if see assisted creature + if (!i_funit->IsWithinLOSInMap(u)) + return false; + + return true; + } + private: + Unit* const i_funit; + Unit* const i_enemy; + float i_range; + }; + + class NearestAssistCreatureInCreatureRangeCheck + { + public: + NearestAssistCreatureInCreatureRangeCheck(Creature* obj, Unit* enemy, float range) + : i_obj(obj), i_enemy(enemy), i_range(range) {} + + bool operator()(Creature* u) + { + if (u == i_obj) + return false; + if (!u->CanAssistTo(i_obj,i_enemy)) + return false; + + if (!i_obj->IsWithinDistInMap(u, i_range)) + return false; + + if (!i_obj->IsWithinLOSInMap(u)) + return false; + + i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check + return true; + } + float GetLastRange() const { return i_range; } + private: + Creature* const i_obj; + Unit* const i_enemy; + float i_range; + + // prevent clone this object + NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&); + }; + + // Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature) + class NearestCreatureEntryWithLiveStateInObjectRangeCheck + { + public: + NearestCreatureEntryWithLiveStateInObjectRangeCheck(WorldObject const& obj, uint32 entry, bool alive, float range) + : i_obj(obj), i_entry(entry), i_alive(alive), i_range(range) {} + + bool operator()(Creature* u) + { + if (u->GetEntry() == i_entry && u->isAlive() == i_alive && i_obj.IsWithinDistInMap(u, i_range)) + { + i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check + return true; + } + return false; + } + float GetLastRange() const { return i_range; } + private: + WorldObject const& i_obj; + uint32 i_entry; + bool i_alive; + float i_range; + + // prevent clone this object + NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&); + }; + + class AnyPlayerInObjectRangeCheck + { + public: + AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {} + bool operator()(Player* u) + { + if (u->isAlive() && i_obj->IsWithinDistInMap(u, i_range)) + return true; + + return false; + } + private: + WorldObject const* i_obj; + float i_range; + }; + + class AllFriendlyCreaturesInGrid + { + public: + AllFriendlyCreaturesInGrid(Unit const* obj) : pUnit(obj) {} + bool operator() (Unit* u) + { + if (u->isAlive() && u->GetVisibility() == VISIBILITY_ON && u->IsFriendlyTo(pUnit)) + return true; + + return false; + } + private: + Unit const* pUnit; + }; + + class AllGameObjectsWithEntryInRange + { + public: + AllGameObjectsWithEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} + bool operator() (GameObject* pGo) + { + if (pGo->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pGo,m_fRange,false)) + return true; + + return false; + } + private: + const WorldObject* m_pObject; + uint32 m_uiEntry; + float m_fRange; + }; + + class AllCreaturesOfEntryInRange + { + public: + AllCreaturesOfEntryInRange(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {} + bool operator() (Unit* pUnit) + { + if (pUnit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pUnit,m_fRange,false)) + return true; + + return false; + } + + private: + const WorldObject* m_pObject; + uint32 m_uiEntry; + float m_fRange; + }; + + class PlayerAtMinimumRangeAway + { + public: + PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : pUnit(unit), fRange(fMinRange) {} + bool operator() (Player* pPlayer) + { + //No threat list check, must be done explicit if expected to be in combat with creature + if (!pPlayer->isGameMaster() && pPlayer->isAlive() && !pUnit->IsWithinDist(pPlayer,fRange,false)) + return true; + + return false; + } + + private: + Unit const* pUnit; + float fRange; + }; + + class GameObjectInRangeCheck + { + public: + GameObjectInRangeCheck(float _x, float _y, float _z, float _range) : x(_x), y(_y), z(_z), range(_range) {} + bool operator() (GameObject* go) + { + return go->IsInRange(x, y, z, range); + } + private: + float x, y, z, range; + }; + + // Player checks and do + + // Prepare using Builder localized packets with caching and send to player + template + class LocalizedPacketDo + { + public: + explicit LocalizedPacketDo(Builder& builder) : i_builder(builder) {} + + ~LocalizedPacketDo() + { + for (size_t i = 0; i < i_data_cache.size(); ++i) + delete i_data_cache[i]; + } + void operator()(Player* p); + + private: + Builder& i_builder; + std::vector i_data_cache; // 0 = default, i => i-1 locale index + }; + + // Prepare using Builder localized packets with caching and send to player + template + class LocalizedPacketListDo + { + public: + typedef std::vector WorldPacketList; + explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {} + + ~LocalizedPacketListDo() + { + for (size_t i = 0; i < i_data_cache.size(); ++i) + for (size_t j = 0; j < i_data_cache[i].size(); ++j) + delete i_data_cache[i][j]; + } + void operator()(Player* p); + + private: + Builder& i_builder; + std::vector i_data_cache; + // 0 = default, i => i-1 locale index + }; +} +#endif diff --git a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h new file mode 100644 index 00000000000..26a9c0bd328 --- /dev/null +++ b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_GRIDNOTIFIERSIMPL_H +#define TRINITY_GRIDNOTIFIERSIMPL_H + +#include "GridNotifiers.h" +#include "WorldPacket.h" +#include "Corpse.h" +#include "Player.h" +#include "UpdateData.h" +#include "CreatureAI.h" +#include "SpellAuras.h" + + +template +inline void +Trinity::VisibleNotifier::Visit(GridRefManager &m) +{ + for (typename GridRefManager::iterator iter = m.begin(); iter != m.end(); ++iter) + { + vis_guids.erase(iter->getSource()->GetGUID()); + i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_visibleNow); + } +} + +inline void +Trinity::ObjectUpdater::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter) + if (iter->getSource()->IsInWorld() && !iter->getSource()->isSpiritService()) + iter->getSource()->Update(i_timeDiff); +} + +// SEARCHERS & LIST SEARCHERS & WORKERS + +// WorldObject searchers & workers + +template +void Trinity::WorldObjectSearcher::Visit(GameObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(CorpseMapType &m) +{ + // already found + if (i_object) + return; + + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectSearcher::Visit(DynamicObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::WorldObjectListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(CorpseMapType &m) +{ + for (CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::WorldObjectListSearcher::Visit(DynamicObjectMapType &m) +{ + for (DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Gameobject searchers + +template +void Trinity::GameObjectSearcher::Visit(GameObjectMapType &m) +{ + // already found + if (i_object) + return; + + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::GameObjectLastSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::GameObjectListSearcher::Visit(GameObjectMapType &m) +{ + for (GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Unit searchers + +template +void Trinity::UnitSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::UnitSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::UnitLastSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::UnitLastSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::UnitListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::UnitListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +// Creature searchers + +template +void Trinity::CreatureSearcher::Visit(CreatureMapType &m) +{ + // already found + if (i_object) + return; + + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::CreatureLastSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + i_object = itr->getSource(); + } +} + +template +void Trinity::CreatureListSearcher::Visit(CreatureMapType &m) +{ + for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::PlayerListSearcher::Visit(PlayerMapType &m) +{ + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + if (itr->getSource()->InSamePhase(i_phaseMask)) + if (i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); +} + +template +void Trinity::PlayerSearcher::Visit(PlayerMapType &m) +{ + // already found + if (i_object) + return; + + for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) + { + if (!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) + { + i_object = itr->getSource(); + return; + } + } +} + +template +void Trinity::LocalizedPacketDo::operator()(Player* p) +{ + int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacket* data; + + // create if not cached yet + if (i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx]) + { + if (i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + data = new WorldPacket(SMSG_MESSAGECHAT, 200); + + i_builder(*data,loc_idx); + + i_data_cache[cache_idx] = data; + } + else + data = i_data_cache[cache_idx]; + + p->SendDirectMessage(data); +} + +template +void Trinity::LocalizedPacketListDo::operator()(Player* p) +{ + int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex(); + uint32 cache_idx = loc_idx+1; + WorldPacketList* data_list; + + // create if not cached yet + if (i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty()) + { + if (i_data_cache.size() < cache_idx+1) + i_data_cache.resize(cache_idx+1); + + data_list = &i_data_cache[cache_idx]; + + i_builder(*data_list,loc_idx); + } + else + data_list = &i_data_cache[cache_idx]; + + for (size_t i = 0; i < data_list->size(); ++i) + p->SendDirectMessage((*data_list)[i]); +} + +#endif // TRINITY_GRIDNOTIFIERSIMPL_H diff --git a/src/server/shared/CompilerDefs.h b/src/server/shared/CompilerDefs.h new file mode 100644 index 00000000000..fb7dbfe4caa --- /dev/null +++ b/src/server/shared/CompilerDefs.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_COMPILERDEFS_H +#define TRINITY_COMPILERDEFS_H + +#define PLATFORM_WINDOWS 0 +#define PLATFORM_UNIX 1 +#define PLATFORM_APPLE 2 +#define PLATFORM_INTEL 3 + +// must be first (win 64 also define WIN32) +#if defined( _WIN64 ) +# define PLATFORM PLATFORM_WINDOWS +#elif defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 ) +# define PLATFORM PLATFORM_WINDOWS +#elif defined( __APPLE_CC__ ) +# define PLATFORM PLATFORM_APPLE +#elif defined( __INTEL_COMPILER ) +# define PLATFORM PLATFORM_INTEL +#else +# define PLATFORM PLATFORM_UNIX +#endif + +#define COMPILER_MICROSOFT 0 +#define COMPILER_GNU 1 +#define COMPILER_BORLAND 2 +#define COMPILER_INTEL 3 + +#ifdef _MSC_VER +# define COMPILER COMPILER_MICROSOFT +#elif defined( __BORLANDC__ ) +# define COMPILER COMPILER_BORLAND +#elif defined( __INTEL_COMPILER ) +# define COMPILER COMPILER_INTEL +#elif defined( __GNUC__ ) +# define COMPILER COMPILER_GNU +#else +# pragma error "FATAL ERROR: Unknown compiler." +#endif + +#if COMPILER == COMPILER_MICROSOFT +# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data +# pragma warning( disable : 4786 ) // identifier was truncated to '255' characters in the debug information +#endif +#endif + diff --git a/src/server/shared/Define.h b/src/server/shared/Define.h new file mode 100644 index 00000000000..9285bf289f9 --- /dev/null +++ b/src/server/shared/Define.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_DEFINE_H +#define TRINITY_DEFINE_H + +#include + +#include +#include + +#include "Platform/CompilerDefs.h" + +#define TRINITY_LITTLEENDIAN 0 +#define TRINITY_BIGENDIAN 1 + +#if !defined(TRINITY_ENDIAN) +# if defined (ACE_BIG_ENDIAN) +# define TRINITY_ENDIAN TRINITY_BIGENDIAN +# else //ACE_BYTE_ORDER != ACE_BIG_ENDIAN +# define TRINITY_ENDIAN TRINITY_LITTLEENDIAN +# endif //ACE_BYTE_ORDER +#endif //TRINITY_ENDIAN + +#if PLATFORM == PLATFORM_WINDOWS +# define TRINITY_PATH_MAX MAX_PATH +# ifndef DECLSPEC_NORETURN +# define DECLSPEC_NORETURN __declspec(noreturn) +# endif //DECLSPEC_NORETURN +#else //PLATFORM != PLATFORM_WINDOWS +# define TRINITY_PATH_MAX PATH_MAX +# define DECLSPEC_NORETURN +#endif //PLATFORM + +#if !defined(DEBUG) +# define TRINITY_INLINE inline +#else //DEBUG +# if !defined(TRINITY_DEBUG) +# define TRINITY_DEBUG +# endif //TRINITY_DEBUG +# define TRINITY_INLINE +#endif //!DEBUG + +#if COMPILER == COMPILER_GNU +# define ATTR_NORETURN __attribute__((noreturn)) +# define ATTR_PRINTF(F,V) __attribute__ ((format (printf, F, V))) +#else //COMPILER != COMPILER_GNU +# define ATTR_NORETURN +# define ATTR_PRINTF(F,V) +#endif //COMPILER == COMPILER_GNU + +typedef ACE_INT64 int64; +typedef ACE_INT32 int32; +typedef ACE_INT16 int16; +typedef ACE_INT8 int8; +typedef ACE_UINT64 uint64; +typedef ACE_UINT32 uint32; +typedef ACE_UINT16 uint16; +typedef ACE_UINT8 uint8; + +#if COMPILER != COMPILER_MICROSOFT +typedef uint16 WORD; +typedef uint32 DWORD; +#endif //COMPILER + +typedef uint64 OBJECT_HANDLE; + +#endif //TRINITY_DEFINE_H diff --git a/src/server/shared/Dynamic/CountedReference/Reference.h b/src/server/shared/Dynamic/CountedReference/Reference.h new file mode 100644 index 00000000000..d3cfe55ffc0 --- /dev/null +++ b/src/server/shared/Dynamic/CountedReference/Reference.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_REFERENCE_H +#define TRINITY_REFERENCE_H + +/** + * Referencer + * Referencer is an object that holds a reference holder that hold a reference + * counted object. When an object's reference count drop to zero, it removes + * the object. This is a non intrusive mechanism and any object at any point + * in time can be referenced. When and object is reference counted, do not + * pass the object directly to other methods but rather, pass its + * reference around. Objects can be reference counted in both single threaded + * model and multi-threaded model + */ + +#include +#include "Platform/Define.h" +#include "Policies/ThreadingModel.h" +#include "ReferenceHolder.h" + +template +< +typename T, +class THREADING_MODEL = Trinity::SingleThreaded +> +class Referencer +{ + typedef typename THREADING_MODEL::Lock Lock; + typedef ReferenceHolder ReferenceeHolder; + public: + + /// Constructs a referencer. + Referencer(T *ref = NULL); + + /// Copy constructor + Referencer(const Referencer &obj) : i_holder(NULL) { *this = obj; } + + /// Destructor + ~Referencer(); + + /// Referencee accessor + T* referencee(void) { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + const T* referencee(void) const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + //T& referencee(void){ return _referencee(); } + //const T& referencee(void) const { return const_cast(this)->_referencee(); } + operator T&(void) { return _referencee(); } + operator const T&(void) const { return *const_cast(this)->_referencee(); } + + /// cast operators + T* operator*() { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + T const * operator*() const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + /// overload operators + T* operator->() { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + const T * operator->() const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + /// operator = + Referencer& operator=(const Referencer &obj); + Referencer& operator=(T *); + + /// returns true if i_referencee is null + bool isNull(void) const { return i_holder == NULL; } + + private: + + T& _referencee(void) + { + if( i_holder == NULL ) + throw std::runtime_error("Invalid access to null pointer"); + return *i_holder->i_referencee; + } + + void deReference(ReferenceeHolder *); + void addReference(ReferenceeHolder *); + + // private data + ReferenceeHolder *i_holder; +}; +#endif + diff --git a/src/server/shared/Dynamic/CountedReference/ReferenceHolder.h b/src/server/shared/Dynamic/CountedReference/ReferenceHolder.h new file mode 100644 index 00000000000..597e9854be0 --- /dev/null +++ b/src/server/shared/Dynamic/CountedReference/ReferenceHolder.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_REFERENCEHOLDER_H +#define TRINITY_REFERENCEHOLDER_H + +/** ReferenceHolder holds the actualy referenced obejct as well the refence + count. The ReferenecHolder implements as a policy base object and + will decided by the Reference class to be consnsitent. + */ + +template +< +typename T, +class THREADING_MODEL +> +struct ReferenceHolder : public THREADING_MODEL +{ + explicit ReferenceHolder(T *ref) : i_referencee(ref), i_referenceCount(0) {} + T *i_referencee; + unsigned int i_referenceCount; + typedef typename THREADING_MODEL::Lock Lock; +}; +#endif + diff --git a/src/server/shared/Dynamic/CountedReference/ReferenceImpl.h b/src/server/shared/Dynamic/CountedReference/ReferenceImpl.h new file mode 100644 index 00000000000..cde330179e3 --- /dev/null +++ b/src/server/shared/Dynamic/CountedReference/ReferenceImpl.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_REFERENCEIMPL_H +#define TRINITY_REFERENCEIMPL_H + +#include "Reference.h" + +template +< +typename T, +class THREADING_MODEL +> +Referencer::Referencer(T *ref) +: i_holder(NULL) +{ + if( ref != NULL ) + { + i_holder = new ReferenceeHolder(ref); + ++i_holder->i_referenceCount; + } +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer::~Referencer() +{ + if( i_holder != NULL ) + deReference(i_holder); + i_holder = NULL; +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer& +Referencer::operator=(const Referencer &obj) +{ + if( i_holder != NULL ) + deReference(i_holder); + if( obj.i_holder != NULL ) + addReference(obj.i_holder); + i_holder = obj.i_holder; + return *this; +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer& +Referencer::operator=(T *ref) +{ + if( i_holder != NULL ) + deReference(i_holder); + i_holder = NULL; + if( ref != NULL ) + { + i_holder = new ReferenceeHolder(ref); + ++i_holder->i_referenceCount; + } + + return *this; +} + +template +< +typename T, +class THREADING_MODEL +> +void +Referencer::deReference(ReferenceHolder *holder) +{ + assert( holder != NULL && holder->i_referenceCount > 0); + bool delete_object = false; + + { + // The guard is within the scope due to the guard + // must release earlier than expected. + Lock guard(*holder); + Guard(&guard); + + --holder->i_referenceCount; + if( holder->i_referenceCount == 0 ) + delete_object = true; + } + + if( delete_object ) + { + delete holder->i_referencee; + delete holder; + } +} + +template +< +typename T, +class THREADING_MODEL +> +void +Referencer::addReference(ReferenceHolder *holder) +{ + assert( i_holder != NULL ); + Lock guard(*holder); + Guard(&guard); + + ++holder->i_referenceCount; +} +#endif + diff --git a/src/server/shared/Dynamic/FactoryHolder.h b/src/server/shared/Dynamic/FactoryHolder.h new file mode 100644 index 00000000000..282968d6097 --- /dev/null +++ b/src/server/shared/Dynamic/FactoryHolder.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_FACTORY_HOLDER +#define TRINITY_FACTORY_HOLDER + +#include "Platform/Define.h" +#include "Utilities/TypeList.h" +#include "ObjectRegistry.h" +#include "Policies/SingletonImp.h" + +/** FactoryHolder holds a factory object of a specific type + */ +template +class FactoryHolder +{ + public: + typedef ObjectRegistry, Key > FactoryHolderRegistry; + typedef Trinity::Singleton FactoryHolderRepository; + + FactoryHolder(Key k) : i_key(k) {} + virtual ~FactoryHolder() {} + inline Key key() const { return i_key; } + + void RegisterSelf(void) { FactoryHolderRepository::Instance().InsertItem(this, i_key); } + void DeregisterSelf(void) { FactoryHolderRepository::Instance().RemoveItem(this, false); } + + /// Abstract Factory create method + virtual T* Create(void *data = NULL) const = 0; + private: + Key i_key; +}; + +/** Permissible is a classic way of letting the object decide + * whether how good they handle things. This is not retricted + * to factory selectors. + */ +template +class Permissible +{ + public: + virtual ~Permissible() {} + virtual int Permit(const T *) const = 0; +}; +#endif + diff --git a/src/server/shared/Dynamic/LinkedList.h b/src/server/shared/Dynamic/LinkedList.h new file mode 100644 index 00000000000..b26687767b3 --- /dev/null +++ b/src/server/shared/Dynamic/LinkedList.h @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LINKEDLIST +#define _LINKEDLIST + +#include "Common.h" + +//============================================ +class LinkedListHead; + +class LinkedListElement +{ + private: + friend class LinkedListHead; + + LinkedListElement* iNext; + LinkedListElement* iPrev; + public: + LinkedListElement() { iNext = NULL; iPrev = NULL; } + ~LinkedListElement() { delink(); } + + bool hasNext() const { return(iNext && iNext->iNext != NULL); } + bool hasPrev() const { return(iPrev && iPrev->iPrev != NULL); } + bool isInList() const { return(iNext != NULL && iPrev != NULL); } + + LinkedListElement * next() { return hasNext() ? iNext : NULL; } + LinkedListElement const* next() const { return hasNext() ? iNext : NULL; } + LinkedListElement * prev() { return hasPrev() ? iPrev : NULL; } + LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; } + + LinkedListElement * nocheck_next() { return iNext; } + LinkedListElement const* nocheck_next() const { return iNext; } + LinkedListElement * nocheck_prev() { return iPrev; } + LinkedListElement const* nocheck_prev() const { return iPrev; } + + void delink() + { + if(isInList()) + { + iNext->iPrev = iPrev; iPrev->iNext = iNext; iNext = NULL; iPrev = NULL; + } + } + + void insertBefore(LinkedListElement* pElem) + { + pElem->iNext = this; + pElem->iPrev = iPrev; + iPrev->iNext = pElem; + iPrev = pElem; + } + + void insertAfter(LinkedListElement* pElem) + { + pElem->iPrev = this; + pElem->iNext = iNext; + iNext->iPrev = pElem; + iNext = pElem; + } +}; + +//============================================ + +class LinkedListHead +{ + private: + LinkedListElement iFirst; + LinkedListElement iLast; + uint32 iSize; + public: + LinkedListHead() + { + // create empty list + + iFirst.iNext = &iLast; + iLast.iPrev = &iFirst; + iSize = 0; + } + + bool isEmpty() const { return(!iFirst.iNext->isInList()); } + + LinkedListElement * getFirst() { return(isEmpty() ? NULL : iFirst.iNext); } + LinkedListElement const* getFirst() const { return(isEmpty() ? NULL : iFirst.iNext); } + + LinkedListElement * getLast() { return(isEmpty() ? NULL : iLast.iPrev); } + LinkedListElement const* getLast() const { return(isEmpty() ? NULL : iLast.iPrev); } + + void insertFirst(LinkedListElement* pElem) + { + iFirst.insertAfter(pElem); + } + + void insertLast(LinkedListElement* pElem) + { + iLast.insertBefore(pElem); + } + + uint32 getSize() const + { + if(!iSize) + { + uint32 result = 0; + LinkedListElement const* e = getFirst(); + while(e) + { + ++result; + e = e->next(); + } + return result; + } + else + return iSize; + } + + void incSize() { ++iSize; } + void decSize() { --iSize; } + + template + class Iterator + { + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Ty value_type; + typedef ptrdiff_t difference_type; + typedef ptrdiff_t distance_type; + typedef _Ty* pointer; + typedef _Ty const* const_pointer; + typedef _Ty& reference; + typedef _Ty const & const_reference; + + Iterator() : _Ptr(0) + { // construct with null node pointer + } + + Iterator(pointer _Pnode) : _Ptr(_Pnode) + { // construct with node pointer _Pnode + } + + Iterator& operator=(Iterator const &_Right) + { + return (*this) = _Right._Ptr; + } + + Iterator& operator=(const_pointer const &_Right) + { + _Ptr = (pointer)_Right; + return (*this); + } + + reference operator*() + { // return designated value + return *_Ptr; + } + + pointer operator->() + { // return pointer to class object + return _Ptr; + } + + Iterator& operator++() + { // preincrement + _Ptr = _Ptr->next(); + return (*this); + } + + Iterator operator++(int) + { // postincrement + iterator _Tmp = *this; + ++*this; + return (_Tmp); + } + + Iterator& operator--() + { // predecrement + _Ptr = _Ptr->prev(); + return (*this); + } + + Iterator operator--(int) + { // postdecrement + iterator _Tmp = *this; + --*this; + return (_Tmp); + } + + bool operator==(Iterator const &_Right) const + { // test for iterator equality + return (_Ptr == _Right._Ptr); + } + + bool operator!=(Iterator const &_Right) const + { // test for iterator inequality + return (!(*this == _Right)); + } + + bool operator==(pointer const &_Right) const + { // test for pointer equality + return (_Ptr != _Right); + } + + bool operator!=(pointer const &_Right) const + { // test for pointer equality + return (!(*this == _Right)); + } + + bool operator==(const_reference _Right) const + { // test for reference equality + return (_Ptr == &_Right); + } + + bool operator!=(const_reference _Right) const + { // test for reference equality + return (_Ptr != &_Right); + } + + pointer _Mynode() + { // return node pointer + return (_Ptr); + } + + protected: + pointer _Ptr; // pointer to node + }; + + typedef Iterator iterator; +}; + +//============================================ +#endif + diff --git a/src/server/shared/Dynamic/LinkedReference/RefManager.h b/src/server/shared/Dynamic/LinkedReference/RefManager.h new file mode 100644 index 00000000000..7e294b4f5f0 --- /dev/null +++ b/src/server/shared/Dynamic/LinkedReference/RefManager.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _REFMANAGER_H +#define _REFMANAGER_H +//===================================================== + +#include "Utilities/LinkedList.h" +#include "Utilities/LinkedReference/Reference.h" + +template class RefManager : public LinkedListHead +{ + public: + typedef LinkedListHead::Iterator< Reference > iterator; + RefManager() { } + virtual ~RefManager() { clearReferences(); } + + Reference* getFirst() { return ((Reference*) LinkedListHead::getFirst()); } + Reference const* getFirst() const { return ((Reference const*) LinkedListHead::getFirst()); } + Reference* getLast() { return ((Reference*) LinkedListHead::getLast()); } + Reference const* getLast() const { return ((Reference const*) LinkedListHead::getLast()); } + + iterator begin() { return iterator(getFirst()); } + iterator end() { return iterator(NULL); } + iterator rbegin() { return iterator(getLast()); } + iterator rend() { return iterator(NULL); } + + void clearReferences() + { + LinkedListElement* ref; + while((ref = getFirst()) != NULL) + { + ((Reference*) ref)->invalidate(); + ref->delink(); // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list + } + } +}; + +//===================================================== +#endif + diff --git a/src/server/shared/Dynamic/LinkedReference/Reference.h b/src/server/shared/Dynamic/LinkedReference/Reference.h new file mode 100644 index 00000000000..4a1545f8f12 --- /dev/null +++ b/src/server/shared/Dynamic/LinkedReference/Reference.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _REFERENCE_H +#define _REFERENCE_H + +#include "Utilities/LinkedList.h" + +//===================================================== + +template class Reference : public LinkedListElement +{ + private: + TO* iRefTo; + FROM* iRefFrom; + protected: + // Tell our refTo (target) object that we have a link + virtual void targetObjectBuildLink() = 0; + + // Tell our refTo (taget) object, that the link is cut + virtual void targetObjectDestroyLink() = 0; + + // Tell our refFrom (source) object, that the link is cut (Target destroyed) + virtual void sourceObjectDestroyLink() = 0; + public: + Reference() { iRefTo = NULL; iRefFrom = NULL; } + virtual ~Reference() {} + + // Create new link + void link(TO* toObj, FROM* fromObj) + { + assert(fromObj); // fromObj MUST not be NULL + if(isValid()) + unlink(); + if(toObj != NULL) + { + iRefTo = toObj; + iRefFrom = fromObj; + targetObjectBuildLink(); + } + } + + // We don't need the reference anymore. Call comes from the refFrom object + // Tell our refTo object, that the link is cut + void unlink() { targetObjectDestroyLink(); delink(); iRefTo = NULL; iRefFrom = NULL; } + + // Link is invalid due to destruction of referenced target object. Call comes from the refTo object + // Tell our refFrom object, that the link is cut + void invalidate() // the iRefFrom MUST remain!! + { + sourceObjectDestroyLink(); delink(); iRefTo = NULL; + } + + bool isValid() const // Only check the iRefTo + { + return iRefTo != NULL; + } + + Reference * next() { return((Reference *) LinkedListElement::next()); } + Reference const * next() const { return((Reference const *) LinkedListElement::next()); } + Reference * prev() { return((Reference *) LinkedListElement::prev()); } + Reference const * prev() const { return((Reference const *) LinkedListElement::prev()); } + + Reference * nocheck_next() { return((Reference *) LinkedListElement::nocheck_next()); } + Reference const * nocheck_next() const { return((Reference const *) LinkedListElement::nocheck_next()); } + Reference * nocheck_prev() { return((Reference *) LinkedListElement::nocheck_prev()); } + Reference const * nocheck_prev() const { return((Reference const *) LinkedListElement::nocheck_prev()); } + + TO* operator ->() const { return iRefTo; } + TO* getTarget() const { return iRefTo; } + + FROM* getSource() const { return iRefFrom; } +}; + +//===================================================== +#endif + diff --git a/src/server/shared/Dynamic/ObjectRegistry.h b/src/server/shared/Dynamic/ObjectRegistry.h new file mode 100644 index 00000000000..e6619427885 --- /dev/null +++ b/src/server/shared/Dynamic/ObjectRegistry.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_OBJECTREGISTRY_H +#define TRINITY_OBJECTREGISTRY_H + +#include "Platform/Define.h" +#include "Utilities/UnorderedMap.h" +#include "Policies/Singleton.h" + +#include +#include +#include + +/** ObjectRegistry holds all registry item of the same type + */ +template +class ObjectRegistry +{ + public: + typedef std::map RegistryMapType; + + /// Returns a registry item + const T* GetRegistryItem(Key key) const + { + typename RegistryMapType::const_iterator iter = i_registeredObjects.find(key); + return( iter == i_registeredObjects.end() ? NULL : iter->second ); + } + + /// Inserts a registry item + bool InsertItem(T *obj, Key key, bool override = false) + { + typename RegistryMapType::iterator iter = i_registeredObjects.find(key); + if( iter != i_registeredObjects.end() ) + { + if( !override ) + return false; + delete iter->second; + i_registeredObjects.erase(iter); + } + + i_registeredObjects[key] = obj; + return true; + } + + /// Removes a registry item + void RemoveItem(Key key, bool delete_object = true) + { + typename RegistryMapType::iterator iter = i_registeredObjects.find(key); + if( iter != i_registeredObjects.end() ) + { + if( delete_object ) + delete iter->second; + i_registeredObjects.erase(iter); + } + } + + /// Returns true if registry contains an item + bool HasItem(Key key) const + { + return (i_registeredObjects.find(key) != i_registeredObjects.end()); + } + + /// Inefficiently return a vector of registered items + unsigned int GetRegisteredItems(std::vector &l) const + { + unsigned int sz = l.size(); + l.resize(sz + i_registeredObjects.size()); + for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) + l[sz++] = iter->first; + return i_registeredObjects.size(); + } + + /// Return the map of registered items + RegistryMapType const &GetRegisteredItems() const + { + return i_registeredObjects; + } + + private: + RegistryMapType i_registeredObjects; + friend class Trinity::OperatorNew >; + + // protected for friend use since it should be a singleton + ObjectRegistry() {} + ~ObjectRegistry() + { + for (typename RegistryMapType::iterator iter=i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter) + delete iter->second; + i_registeredObjects.clear(); + } +}; +#endif + diff --git a/src/server/shared/Dynamic/TypeContainer.h b/src/server/shared/Dynamic/TypeContainer.h new file mode 100644 index 00000000000..c2c9b4fcdea --- /dev/null +++ b/src/server/shared/Dynamic/TypeContainer.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_TYPECONTAINER_H +#define TRINITY_TYPECONTAINER_H + +/* + * Here, you'll find a series of containers that allow you to hold multiple + * types of object at the same time. + */ + +#include +#include +#include "Platform/Define.h" +#include "Utilities/TypeList.h" +#include "GameSystem/GridRefManager.h" + +/* + * @class ContainerMapList is a mulit-type container for map elements + * By itself its meaningless but collaborate along with TypeContainers, + * it become the most powerfully container in the whole system. + */ +template struct ContainerMapList +{ + //std::map _element; + GridRefManager _element; +}; + +template<> struct ContainerMapList /* nothing is in type null */ +{ +}; +template struct ContainerMapList > +{ + ContainerMapList _elements; + ContainerMapList _TailElements; +}; + +/* + * @class ContaierArrayList is a multi-type container for + * array of elements. + */ +template struct ContainerArrayList +{ + std::vector _element; +}; + +// termination condition +template<> struct ContainerArrayList {}; +// recursion +template struct ContainerArrayList > +{ + ContainerArrayList _elements; + ContainerArrayList _TailElements; +}; + +/* + * @class ContainerList is a simple list of different types of elements + * + */ +template struct ContainerList +{ + OBJECT _element; +}; + +/* TypeNull is underfined */ +template<> struct ContainerList {}; +template struct ContainerList > +{ + ContainerList _elements; + ContainerMapList _TailElements; +}; + +#include "TypeContainerFunctions.h" + +/* + * @class TypeMapContainer contains a fixed number of types and is + * determined at compile time. This is probably the most complicated + * class and do its simplest thing, that is, holds objects + * of different types. + */ + +template +class TypeMapContainer +{ + public: + template size_t Count() const { return Trinity::Count(i_elements, (SPECIFIC_TYPE*)NULL); } + + /// inserts a specific object into the container + template bool insert(SPECIFIC_TYPE *obj) + { + SPECIFIC_TYPE* t = Trinity::Insert(i_elements, obj); + return (t != NULL); + } + + /// Removes the object from the container, and returns the removed object + template bool remove(SPECIFIC_TYPE* obj) + { + SPECIFIC_TYPE* t = Trinity::Remove(i_elements, obj); + return (t != NULL); + } + + ContainerMapList & GetElements(void) { return i_elements; } + const ContainerMapList & GetElements(void) const { return i_elements;} + + private: + ContainerMapList i_elements; +}; +#endif + diff --git a/src/server/shared/Dynamic/TypeContainerFunctions.h b/src/server/shared/Dynamic/TypeContainerFunctions.h new file mode 100644 index 00000000000..edfbb40e659 --- /dev/null +++ b/src/server/shared/Dynamic/TypeContainerFunctions.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TYPECONTAINER_FUNCTIONS_H +#define TYPECONTAINER_FUNCTIONS_H + +/* + * Here you'll find a list of helper functions to make + * the TypeContainer usefull. Without it, its hard + * to access or mutate the container. + */ + +#include "Platform/Define.h" +#include "Utilities/TypeList.h" +#include + +namespace Trinity +{ + /* ContainerMapList Helpers */ + // count functions + template size_t Count(const ContainerMapList &elements, SPECIFIC_TYPE* /*fake*/) + { + return elements._element.getSize(); + }; + + template size_t Count(const ContainerMapList &/*elements*/, SPECIFIC_TYPE* /*fake*/) + { + return 0; + } + + template size_t Count(const ContainerMapList &/*elements*/, SPECIFIC_TYPE* /*fake*/) + { + return 0; + } + + template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) + { + return Count(elements._elements,fake); + } + + template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) + { + return Count(elements._TailElements, fake); + } + + // non-const insert functions + template SPECIFIC_TYPE* Insert(ContainerMapList &elements, SPECIFIC_TYPE *obj) + { + //elements._element[hdl] = obj; + obj->GetGridRef().link(&elements._element, obj); + return obj; + }; + + template SPECIFIC_TYPE* Insert(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/) + { + return NULL; + } + + // this is a missed + template SPECIFIC_TYPE* Insert(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/) + { + return NULL; // a missed + } + + // Recursion + template SPECIFIC_TYPE* Insert(ContainerMapList >&elements, SPECIFIC_TYPE *obj) + { + SPECIFIC_TYPE* t= Insert(elements._elements, obj); + return (t != NULL ? t : Insert(elements._TailElements, obj)); + } + + // non-const remove method + template SPECIFIC_TYPE* Remove(ContainerMapList & /*elements*/, SPECIFIC_TYPE *obj) + { + obj->GetGridRef().unlink(); + return obj; + } + + template SPECIFIC_TYPE* Remove(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/) + { + return NULL; + } + + // this is a missed + template SPECIFIC_TYPE* Remove(ContainerMapList &/*elements*/, SPECIFIC_TYPE * /*obj*/) + { + return NULL; // a missed + } + + template SPECIFIC_TYPE* Remove(ContainerMapList > &elements, SPECIFIC_TYPE *obj) + { + // The head element is bad + SPECIFIC_TYPE* t = Remove(elements._elements, obj); + return ( t != NULL ? t : Remove(elements._TailElements, obj) ); + } + +} +#endif + diff --git a/src/server/shared/Dynamic/TypeContainerFunctionsPtr.h b/src/server/shared/Dynamic/TypeContainerFunctionsPtr.h new file mode 100644 index 00000000000..2affcc457cc --- /dev/null +++ b/src/server/shared/Dynamic/TypeContainerFunctionsPtr.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TYPECONTAINER_FUNCTIONS_PTR_H +#define TYPECONTAINER_FUNCTIONS_PTR_H + +/* + * Here you'll find a list of helper functions to make + * the TypeContainer usefull. Without it, its hard + * to access or mutate the container. + */ + +#include "Platform/Define.h" +#include "Utilities/TypeList.h" +#include + +namespace Trinity +{ + /* ContainerMapList Helpers */ + // count functions + // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) + // { + // return elements._element.size(); + // }; + // + // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) + // { + // return 0; + // } + // + // template size_t Count(const ContainerMapList &elements, CountedPtr* /*fake*/) + // { + // return 0; + // } + // + // template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) + // { + // return Count(elements._elements,fake); + // } + // + // template size_t Count(const ContainerMapList >&elements, SPECIFIC_TYPE* fake) + // { + // return Count(elements._TailElements, fake); + // } + + // non-const find functions + template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + typename std::map >::iterator iter = elements._element.find(hdl); + return (iter == elements._element.end() ? NullPtr((SPECIFIC_TYPE*)NULL) : iter->second); + }; + + template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + return NullPtr((SPECIFIC_TYPE*)NULL);// terminate recursion + } + + template CountedPtr& Find(ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + return NullPtr((SPECIFIC_TYPE*)NULL);// this is a missed + } + + template CountedPtr& Find(ContainerMapList >&elements, OBJECT_HANDLE hdl, CountedPtr* fake) + { + CountedPtr &t = Find(elements._elements, hdl,fake); + return (!t ? Find(elements._TailElements, hdl,fake) : t); + } + + // const find functions + template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + typename CountedPtr::iterator iter = elements._element.find(hdl); + return (iter == elements._element.end() ? NullPtr((SPECIFIC_TYPE*)NULL) : iter->second); + }; + + template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + return NullPtr((SPECIFIC_TYPE*)NULL); + } + + template const CountedPtr& Find(const ContainerMapList &elements, OBJECT_HANDLE hdl, CountedPtr* /*fake*/) + { + return NullPtr((SPECIFIC_TYPE*)NULL); + } + + template CountedPtr& Find(const ContainerMapList >&elements, OBJECT_HANDLE hdl, CountedPtr* fake) + { + CountedPtr &t = Find(elements._elements, hdl,fake); + if(!t) + t = Find(elements._TailElement, hdl,fake); + + return t; + } + + // non-const insert functions + template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + elements._element[hdl] = obj; + return obj; + }; + + template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + return NullPtr((SPECIFIC_TYPE*)NULL); + } + + // this is a missed + template CountedPtr& Insert(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + return NullPtr((SPECIFIC_TYPE*)NULL);// a missed + } + + // Recursion + template CountedPtr& Insert(ContainerMapList >&elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + CountedPtr &t= Insert(elements._elements, obj, hdl); + return (!t ? Insert(elements._TailElements, obj, hdl) : t); + } + + // non-const remove method + template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + typename std::map >::iterator iter = elements._element.find(hdl); + if( iter != elements._element.end() ) + { + elements._element.erase(iter); + return true; + } + + return false; // found... terminate the search + } + + template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + return false; + } + + // this is a missed + template bool Remove(ContainerMapList &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + return false; + } + + template bool Remove(ContainerMapList > &elements, CountedPtr &obj, OBJECT_HANDLE hdl) + { + // The head element is bad + bool t = Remove(elements._elements, obj, hdl); + return ( !t ? Remove(elements._TailElements, obj, hdl) : t ); + } + +} +#endif + diff --git a/src/server/shared/Dynamic/TypeContainerVisitor.h b/src/server/shared/Dynamic/TypeContainerVisitor.h new file mode 100644 index 00000000000..f15075e5afd --- /dev/null +++ b/src/server/shared/Dynamic/TypeContainerVisitor.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_TYPECONTAINERVISITOR_H +#define TRINITY_TYPECONTAINERVISITOR_H + +/* + * @class TypeContainerVisitor is implemented as a visitor pattern. It is + * a visitor to the TypeContainerList or TypeContainerMapList. The visitor has + * to overload its types as a visit method is called. + */ + +#include "Platform/Define.h" +#include "TypeContainer.h" + +// forward declaration +template class TypeContainerVisitor; + +// visitor helper +template void VisitorHelper(VISITOR &v, TYPE_CONTAINER &c) +{ + v.Visit(c); +}; + +// terminate condition for container list +template void VisitorHelper(VISITOR &v, ContainerList &c) +{ +} + +template void VisitorHelper(VISITOR &v, ContainerList &c) +{ + v.Visit(c._element); +} + +// recursion for container list +template void VisitorHelper(VISITOR &v, ContainerList > &c) +{ + VisitorHelper(v, c._elements); + VisitorHelper(v, c._TailElements); +} + +// terminate condition container map list +template void VisitorHelper(VISITOR &/*v*/, ContainerMapList &/*c*/) +{ +} + +template void VisitorHelper(VISITOR &v, ContainerMapList &c) +{ + v.Visit(c._element); +} + +// recursion container map list +template void VisitorHelper(VISITOR &v, ContainerMapList > &c) +{ + VisitorHelper(v, c._elements); + VisitorHelper(v, c._TailElements); +} + +// array list +template void VisitorHelper(VISITOR &v, ContainerArrayList &c) +{ + v.Visit(c._element); +} + +template void VisitorHelper(VISITOR &/*v*/, ContainerArrayList &/*c*/) +{ +} + +// recursion +template void VisitorHelper(VISITOR &v, ContainerArrayList > &c) +{ + VisitorHelper(v, c._elements); + VisitorHelper(v, c._TailElements); +} + +// for TypeMapContainer +template void VisitorHelper(VISITOR &v, TypeMapContainer &c) +{ + VisitorHelper(v, c.GetElements()); +} + +template +class TypeContainerVisitor +{ + public: + TypeContainerVisitor(VISITOR &v) : i_visitor(v) {} + + void Visit(TYPE_CONTAINER &c) + { + VisitorHelper(i_visitor, c); + } + + void Visit(const TYPE_CONTAINER &c) const + { + VisitorHelper(i_visitor, c); + } + + private: + VISITOR &i_visitor; +}; +#endif + diff --git a/src/server/shared/Dynamic/TypeList.h b/src/server/shared/Dynamic/TypeList.h new file mode 100644 index 00000000000..02bc08083c2 --- /dev/null +++ b/src/server/shared/Dynamic/TypeList.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_TYPELIST_H +#define TRINITY_TYPELIST_H + +/* + @struct TypeList + TypeList is the most simple but yet the most powerfull class of all. It holds + at compile time the different type of objects in a linked list. + */ + +class TypeNull; + +template +struct TypeList +{ + typedef HEAD Head; + typedef TAIL Tail; +}; + +// enough for now.. can be expand at any point in time as needed +#define TYPELIST_1(T1) TypeList +#define TYPELIST_2(T1, T2) TypeList +#define TYPELIST_3(T1, T2, T3) TypeList +#define TYPELIST_4(T1, T2, T3, T4) TypeList +#define TYPELIST_5(T1, T2, T3, T4, T5) TypeList +#endif + diff --git a/src/server/shared/Dynamic/UnorderedMap.h b/src/server/shared/Dynamic/UnorderedMap.h new file mode 100644 index 00000000000..fce5ec82bfc --- /dev/null +++ b/src/server/shared/Dynamic/UnorderedMap.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_UNORDERED_MAP_H +#define TRINITY_UNORDERED_MAP_H + +#include "Platform/CompilerDefs.h" +#include "Platform/Define.h" + +#if COMPILER == COMPILER_INTEL +#include +#elif COMPILER == COMPILER_GNU && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3) +#include +#elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 +#include +#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1500 && _HAS_TR1 // VC9.0 and later +#include +#else +#include +#endif + +#ifdef _STLPORT_VERSION +#define UNORDERED_MAP std::hash_map +using std::hash_map; +#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1500 && _HAS_TR1 +#define UNORDERED_MAP std::tr1::unordered_map +#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1300 +#define UNORDERED_MAP stdext::hash_map +using stdext::hash_map; +#elif COMPILER == COMPILER_INTEL +#define UNORDERED_MAP std::hash_map +using std::hash_map; +#elif COMPILER == COMPILER_GNU && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3) +#define UNORDERED_MAP std::tr1::unordered_map +#elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 +#define UNORDERED_MAP __gnu_cxx::hash_map + +namespace __gnu_cxx +{ + template<> struct hash + { + size_t operator()(const unsigned long long &__x) const { return (size_t)__x; } + }; + template struct hash + { + size_t operator()(T * const &__x) const { return (size_t)__x; } + }; + +}; + +#else +#define UNORDERED_MAP std::hash_map +using std::hash_map; +#endif +#endif + diff --git a/src/server/shared/Policies/CreationPolicy.h b/src/server/shared/Policies/CreationPolicy.h new file mode 100644 index 00000000000..8552ce7da52 --- /dev/null +++ b/src/server/shared/Policies/CreationPolicy.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CREATIONPOLICY_H +#define TRINITY_CREATIONPOLICY_H + +#include +#include "Platform/Define.h" + +namespace Trinity +{ + /** + * OperatorNew policy creates an object on the heap using new. + */ + template + class OperatorNew + { + public: + static T* Create(void) { return (new T); } + static void Destroy(T *obj) { delete obj; } + }; + + /** + * LocalStaticCreation policy creates an object on the stack + * the first time call Create. + */ + template + class LocalStaticCreation + { + union MaxAlign + { + char t_[sizeof(T)]; + short int shortInt_; + int int_; + long int longInt_; + float float_; + double double_; + long double longDouble_; + struct Test; + int Test::* pMember_; + int (Test::*pMemberFn_)(int); + }; + public: + static T* Create(void) + { + static MaxAlign si_localStatic; + return new(&si_localStatic) T; + } + + static void Destroy(T *obj) { obj->~T(); } + }; + + /** + * CreateUsingMalloc by pass the memory manger. + */ + template + class CreateUsingMalloc + { + public: + static T* Create() + { + void* p = ::malloc(sizeof(T)); + if (!p) return 0; + return new(p) T; + } + + static void Destroy(T* p) + { + p->~T(); + ::free(p); + } + }; + + /** + * CreateOnCallBack creates the object base on the call back. + */ + template + class CreateOnCallBack + { + public: + static T* Create() + { + return CALL_BACK::createCallBack(); + } + + static void Destroy(T *p) + { + CALL_BACK::destroyCallBack(p); + } + }; +} +#endif + diff --git a/src/server/shared/Policies/ObjectLifeTime.cpp b/src/server/shared/Policies/ObjectLifeTime.cpp new file mode 100644 index 00000000000..fd16873ae92 --- /dev/null +++ b/src/server/shared/Policies/ObjectLifeTime.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "ObjectLifeTime.h" + +namespace Trinity +{ + extern "C" void external_wrapper(void *p) + { + std::atexit( (void (*)())p ); + } + + void at_exit( void (*func)() ) + { + external_wrapper((void*)func); + } +} + diff --git a/src/server/shared/Policies/ObjectLifeTime.h b/src/server/shared/Policies/ObjectLifeTime.h new file mode 100644 index 00000000000..61b90b59f6e --- /dev/null +++ b/src/server/shared/Policies/ObjectLifeTime.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_OBJECTLIFETIME_H +#define TRINITY_OBJECTLIFETIME_H + +#include +#include "Platform/Define.h" + +typedef void (* Destroyer)(void); + +namespace Trinity +{ + void at_exit( void (*func)() ); + + template + class ObjectLifeTime + { + public: + static void ScheduleCall(void (*destroyer)() ) + { + at_exit( destroyer ); + } + + DECLSPEC_NORETURN static void OnDeadReference(void) ATTR_NORETURN; + + }; + + template + void ObjectLifeTime::OnDeadReference(void) // We don't handle Dead Reference for now + { + throw std::runtime_error("Dead Reference"); + } +} +#endif + diff --git a/src/server/shared/Policies/Singleton.h b/src/server/shared/Policies/Singleton.h new file mode 100644 index 00000000000..da898558ca5 --- /dev/null +++ b/src/server/shared/Policies/Singleton.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_SINGLETON_H +#define TRINITY_SINGLETON_H + +/** + * @brief class Singleton + */ + +#include "CreationPolicy.h" +#include "ThreadingModel.h" +#include "ObjectLifeTime.h" + +namespace Trinity +{ + template + < + typename T, + class ThreadingModel = Trinity::SingleThreaded, + class CreatePolicy = Trinity::OperatorNew, + class LifeTimePolicy = Trinity::ObjectLifeTime + > + class Singleton + { + public: + static T& Instance(); + + protected: + Singleton() {}; + + private: + + // Prohibited actions...this does not prevent hijacking. + Singleton(const Singleton &); + Singleton& operator=(const Singleton &); + + // Singleton Helpers + static void DestroySingleton(); + + // data structure + typedef typename ThreadingModel::Lock Guard; + static T *si_instance; + static bool si_destroyed; + }; +} +#endif + diff --git a/src/server/shared/Policies/SingletonImp.h b/src/server/shared/Policies/SingletonImp.h new file mode 100644 index 00000000000..3e985cd5c64 --- /dev/null +++ b/src/server/shared/Policies/SingletonImp.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_SINGLETONIMPL_H +#define TRINITY_SINGLETONIMPL_H + +#include "Singleton.h" + +// avoid the using namespace here cuz +// its a .h file afterall + +template +< +typename T, +class ThreadingModel, +class CreatePolicy, +class LifeTimePolicy +> +T& +Trinity::Singleton::Instance() +{ + if( !si_instance ) + { + // double-checked Locking pattern + Guard(); + if( !si_instance ) + { + if( si_destroyed ) + { + si_destroyed = false; + LifeTimePolicy::OnDeadReference(); + } + si_instance = CreatePolicy::Create(); + LifeTimePolicy::ScheduleCall(&DestroySingleton); + } + } + + return *si_instance; +} + +template +< +typename T, +class ThreadingModel, +class CreatePolicy, +class LifeTimePolicy +> +void +Trinity::Singleton::DestroySingleton() +{ + CreatePolicy::Destroy(si_instance); + si_instance = NULL; + si_destroyed = true; +} + +#define INSTANTIATE_SINGLETON_1(TYPE) \ + template class Trinity::Singleton, Trinity::OperatorNew, Trinity::ObjectLifeTime >; \ + template<> TYPE* Trinity::Singleton, Trinity::OperatorNew, Trinity::ObjectLifeTime >::si_instance = 0; \ + template<> bool Trinity::Singleton, Trinity::OperatorNew, Trinity::ObjectLifeTime >::si_destroyed = false + +#define INSTANTIATE_SINGLETON_2(TYPE, THREADINGMODEL) \ + template class Trinity::Singleton, Trinity::ObjectLifeTime >; \ + template<> TYPE* Trinity::Singleton, Trinity::ObjectLifeTime >::si_instance = 0; \ + template<> bool Trinity::Singleton, Trinity::ObjectLifeTime >::si_destroyed = false + +#define INSTANTIATE_SINGLETON_3(TYPE, THREADINGMODEL, CREATIONPOLICY ) \ + template class Trinity::Singleton >; \ + template<> TYPE* Trinity::Singleton >::si_instance = 0; \ + template<> bool Trinity::Singleton >::si_destroyed = false + +#define INSTANTIATE_SINGLETON_4(TYPE, THREADINGMODEL, CREATIONPOLICY, OBJECTLIFETIME) \ + template class Trinity::Singleton; \ + template<> TYPE* Trinity::Singleton::si_instance = 0; \ + template<> bool Trinity::Singleton::si_destroyed = false +#endif + diff --git a/src/server/shared/Policies/ThreadingModel.h b/src/server/shared/Policies/ThreadingModel.h new file mode 100644 index 00000000000..d4c5e9a2333 --- /dev/null +++ b/src/server/shared/Policies/ThreadingModel.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_THREADINGMODEL_H +#define TRINITY_THREADINGMODEL_H + +/** + * @class ThreadingModel + * + */ + +#include "Platform/Define.h" + +namespace Trinity +{ + inline void Guard(void *) {} + + template class GeneralLock + { + public: + GeneralLock(MUTEX &m) : i_mutex(m) + { + i_mutex.acquire(); + } + + ~GeneralLock() + { + i_mutex.release(); + } + private: + GeneralLock(const GeneralLock &); + GeneralLock& operator=(const GeneralLock &); + MUTEX &i_mutex; + }; + + template + class SingleThreaded + { + public: + + struct Lock // empty object + { + Lock() {} + Lock(const T &) {} + Lock(const SingleThreaded &) // for single threaded we ignore this + { + } + }; + + typedef T VolatileType; + }; + + // object level lockable + template + class ObjectLevelLockable + { + public: + ObjectLevelLockable() : i_mtx() {} + + friend class Lock; + + class Lock + { + public: + Lock(ObjectLevelLockable &host) : i_lock(host.i_mtx) + { + } + + private: + GeneralLock i_lock; + }; + + typedef volatile T VolatileType; + + private: + // prevent the compiler creating a copy construct + ObjectLevelLockable(const ObjectLevelLockable &); + ObjectLevelLockable& operator=(const ObjectLevelLockable &); + + MUTEX i_mtx; + }; + + template + class ClassLevelLockable + { + public: + class Lock; + friend class Lock; + typedef volatile T VolatileType; + + ClassLevelLockable() {} + + class Lock + { + public: + Lock(T& /*host*/) { ClassLevelLockable::si_mtx.acquire(); } + Lock(ClassLevelLockable &) { ClassLevelLockable::si_mtx.acquire(); } + Lock() { ClassLevelLockable::si_mtx.acquire(); } + ~Lock() { ClassLevelLockable::si_mtx.release(); } + }; + + private: + static MUTEX si_mtx; + }; + +} + +template MUTEX Trinity::ClassLevelLockable::si_mtx; + +#define INSTANTIATE_CLASS_MUTEX(CTYPE,MUTEX) \ + template class Trinity::ClassLevelLockable +#endif + diff --git a/src/server/shared/Threading/Callback.h b/src/server/shared/Threading/Callback.h new file mode 100644 index 00000000000..d2e2c36851a --- /dev/null +++ b/src/server/shared/Threading/Callback.h @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_CALLBACK_H +#define TRINITY_CALLBACK_H + +/// ------------ BASE CLASSES ------------ + +namespace Trinity +{ + template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > + class _Callback + { + protected: + typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3, ParamType4); + Class *m_object; + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + ParamType3 m_param3; + ParamType4 m_param4; + void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3, m_param4); } + public: + _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) + : m_object(object), m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {} + _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4> const& cb) + : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {} + }; + + template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 > + class _Callback < Class, ParamType1, ParamType2, ParamType3 > + { + protected: + typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3); + Class *m_object; + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + ParamType3 m_param3; + void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3); } + public: + _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {} + _Callback(_Callback < Class, ParamType1, ParamType2, ParamType3 > const& cb) + : m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {} + }; + + template < class Class, typename ParamType1, typename ParamType2 > + class _Callback < Class, ParamType1, ParamType2 > + { + protected: + typedef void (Class::*Method)(ParamType1, ParamType2); + Class *m_object; + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + void _Execute() { (m_object->*m_method)(m_param1, m_param2); } + public: + _Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2) + : m_object(object), m_method(method), m_param1(param1), m_param2(param2) {} + _Callback(_Callback < Class, ParamType1, ParamType2 > const& cb) + : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {} + }; + + template < class Class, typename ParamType1 > + class _Callback < Class, ParamType1 > + { + protected: + typedef void (Class::*Method)(ParamType1); + Class *m_object; + Method m_method; + ParamType1 m_param1; + void _Execute() { (m_object->*m_method)(m_param1); } + public: + _Callback(Class *object, Method method, ParamType1 param1) + : m_object(object), m_method(method), m_param1(param1) {} + _Callback(_Callback < Class, ParamType1 > const& cb) + : m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1) {} + }; + + template < class Class > + class _Callback < Class > + { + protected: + typedef void (Class::*Method)(); + Class *m_object; + Method m_method; + void _Execute() { (m_object->*m_method)(); } + public: + _Callback(Class *object, Method method) + : m_object(object), m_method(method) {} + _Callback(_Callback < Class > const& cb) + : m_object(cb.m_object), m_method(cb.m_method) {} + }; + + /// ---- Statics ---- + + template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > + class _SCallback + { + protected: + typedef void (*Method)(ParamType1, ParamType2, ParamType3, ParamType4); + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + ParamType3 m_param3; + ParamType4 m_param4; + void _Execute() { (*m_method)(m_param1, m_param2, m_param3, m_param4); } + public: + _SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) + : m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {} + _SCallback(_SCallback < ParamType1, ParamType2, ParamType3, ParamType4> const& cb) + : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {} + }; + + template < typename ParamType1, typename ParamType2, typename ParamType3 > + class _SCallback < ParamType1, ParamType2, ParamType3 > + { + protected: + typedef void (*Method)(ParamType1, ParamType2, ParamType3); + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + ParamType3 m_param3; + void _Execute() { (*m_method)(m_param1, m_param2, m_param3); } + public: + _SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : m_method(method), m_param1(param1), m_param2(param2), m_param3(param3) {} + _SCallback(_SCallback < ParamType1, ParamType2, ParamType3 > const& cb) + : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {} + }; + + template < typename ParamType1, typename ParamType2 > + class _SCallback < ParamType1, ParamType2 > + { + protected: + typedef void (*Method)(ParamType1, ParamType2); + Method m_method; + ParamType1 m_param1; + ParamType2 m_param2; + void _Execute() { (*m_method)(m_param1, m_param2); } + public: + _SCallback(Method method, ParamType1 param1, ParamType2 param2) + : m_method(method), m_param1(param1), m_param2(param2) {} + _SCallback(_SCallback < ParamType1, ParamType2 > const& cb) + : m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {} + }; + + template < typename ParamType1 > + class _SCallback < ParamType1 > + { + protected: + typedef void (*Method)(ParamType1); + Method m_method; + ParamType1 m_param1; + void _Execute() { (*m_method)(m_param1); } + public: + _SCallback(Method method, ParamType1 param1) + : m_method(method), m_param1(param1) {} + _SCallback(_SCallback < ParamType1 > const& cb) + : m_method(cb.m_method), m_param1(cb.m_param1) {} + }; + + template < > + class _SCallback < > + { + protected: + typedef void (*Method)(); + Method m_method; + void _Execute() { (*m_method)(); } + public: + _SCallback(Method method) + : m_method(method) {} + _SCallback(_SCallback <> const& cb) + : m_method(cb.m_method) {} + }; +} + +/// --------- GENERIC CALLBACKS ---------- + +namespace Trinity +{ + class ICallback + { + public: + virtual void Execute() = 0; + virtual ~ICallback() {} + }; + + template < class CB > + class _ICallback : public CB, public ICallback + { + public: + _ICallback(CB const& cb) : CB(cb) {} + void Execute() { CB::_Execute(); } + }; + + template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void > + class Callback : + public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > > + { + private: + typedef _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > C4; + public: + Callback(Class *object, typename C4::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4) + : _ICallback< C4 >(C4(object, method, param1, param2, param3, param4)) {} + }; + + template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 > + class Callback < Class, ParamType1, ParamType2, ParamType3 > : + public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3 > > + { + private: + typedef _Callback < Class, ParamType1, ParamType2, ParamType3 > C3; + public: + Callback(Class *object, typename C3::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : _ICallback< C3 >(C3(object, method, param1, param2, param3)) {} + }; + + template < class Class, typename ParamType1, typename ParamType2 > + class Callback < Class, ParamType1, ParamType2 > : + public _ICallback< _Callback < Class, ParamType1, ParamType2 > > + { + private: + typedef _Callback < Class, ParamType1, ParamType2 > C2; + public: + Callback(Class *object, typename C2::Method method, ParamType1 param1, ParamType2 param2) + : _ICallback< C2 >(C2(object, method, param1, param2)) {} + }; + + template < class Class, typename ParamType1 > + class Callback < Class, ParamType1 > : + public _ICallback< _Callback < Class, ParamType1 > > + { + private: + typedef _Callback < Class, ParamType1 > C1; + public: + Callback(Class *object, typename C1::Method method, ParamType1 param1) + : _ICallback< C1 >(C1(object, method, param1)) {} + }; + + template < class Class > + class Callback < Class > : public _ICallback< _Callback < Class > > + { + private: + typedef _Callback < Class > C0; + public: + Callback(Class *object, typename C0::Method method) + : _ICallback< C0 >(C0(object, method)) {} + }; +} + +/// ---------- QUERY CALLBACKS ----------- + +#include "QueryResult.h" +class QueryResult; + +namespace Trinity +{ + class IQueryCallback + { + public: + virtual void Execute() = 0; + virtual ~IQueryCallback() {} + virtual void SetResult(QueryResult_AutoPtr result) = 0; + virtual QueryResult_AutoPtr GetResult() = 0; + }; + + template < class CB > + class _IQueryCallback : public CB, public IQueryCallback + { + public: + _IQueryCallback(CB const& cb) : CB(cb) {} + void Execute() { CB::_Execute(); } + void SetResult(QueryResult_AutoPtr result) { CB::m_param1 = result; } + QueryResult_AutoPtr GetResult() { return CB::m_param1; } + }; + + template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void > + class QueryCallback : + public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > > + { + private: + typedef _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > QC3; + public: + QueryCallback(Class *object, typename QC3::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : _IQueryCallback< QC3 >(QC3(object, method, result, param1, param2, param3)) {} + }; + + template < class Class, typename ParamType1, typename ParamType2 > + class QueryCallback < Class, ParamType1, ParamType2 > : + public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2 > > + { + private: + typedef _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2 > QC2; + public: + QueryCallback(Class *object, typename QC2::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2) + : _IQueryCallback< QC2 >(QC2(object, method, result, param1, param2)) {} + }; + + template < class Class, typename ParamType1 > + class QueryCallback < Class, ParamType1 > : + public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1 > > + { + private: + typedef _Callback < Class, QueryResult_AutoPtr, ParamType1 > QC1; + public: + QueryCallback(Class *object, typename QC1::Method method, QueryResult_AutoPtr result, ParamType1 param1) + : _IQueryCallback< QC1 >(QC1(object, method, result, param1)) {} + }; + + template < class Class > + class QueryCallback < Class > : public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr > > + { + private: + typedef _Callback < Class, QueryResult_AutoPtr > QC0; + public: + QueryCallback(Class *object, typename QC0::Method method, QueryResult_AutoPtr result) + : _IQueryCallback< QC0 >(QC0(object, method, result)) {} + }; + + /// ---- Statics ---- + + template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void > + class SQueryCallback : + public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > > + { + private: + typedef _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > QC3; + public: + SQueryCallback(typename QC3::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2, ParamType3 param3) + : _IQueryCallback< QC3 >(QC3(method, result, param1, param2, param3)) {} + }; + + template < typename ParamType1, typename ParamType2 > + class SQueryCallback < ParamType1, ParamType2 > : + public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2 > > + { + private: + typedef _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2 > QC2; + public: + SQueryCallback(typename QC2::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2) + : _IQueryCallback< QC2 >(QC2(method, result, param1, param2)) {} + }; + + template < typename ParamType1 > + class SQueryCallback < ParamType1 > : + public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1 > > + { + private: + typedef _SCallback < QueryResult_AutoPtr, ParamType1 > QC1; + public: + SQueryCallback(typename QC1::Method method, QueryResult_AutoPtr result, ParamType1 param1) + : _IQueryCallback< QC1 >(QC1(method, result, param1)) {} + }; + + template < > + class SQueryCallback < > : public _IQueryCallback< _SCallback < QueryResult_AutoPtr > > + { + private: + typedef _SCallback < QueryResult_AutoPtr > QC0; + public: + SQueryCallback(QC0::Method method, QueryResult_AutoPtr result) + : _IQueryCallback< QC0 >(QC0(method, result)) {} + }; +} + +#endif + diff --git a/src/server/shared/Utilities/ByteConverter.h b/src/server/shared/Utilities/ByteConverter.h new file mode 100644 index 00000000000..f8b6bd72498 --- /dev/null +++ b/src/server/shared/Utilities/ByteConverter.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_BYTECONVERTER_H +#define TRINITY_BYTECONVERTER_H + +/** ByteConverter reverse your byte order. This is use + for cross platform where they have different endians. + */ + +#include +#include + +namespace ByteConverter +{ + template + inline void convert(char *val) + { + std::swap(*val, *(val + T - 1)); + convert(val + 1); + } + + template<> inline void convert<0>(char *) {} + template<> inline void convert<1>(char *) {} // ignore central byte + + template inline void apply(T *val) + { + convert((char *)(val)); + } +} + +#if TRINITY_ENDIAN == TRINITY_BIGENDIAN +template inline void EndianConvert(T& val) { ByteConverter::apply(&val); } +template inline void EndianConvertReverse(T&) { } +#else +template inline void EndianConvert(T&) { } +template inline void EndianConvertReverse(T& val) { ByteConverter::apply(&val); } +#endif + +template void EndianConvert(T*); // will generate link error +template void EndianConvertReverse(T*); // will generate link error + +inline void EndianConvert(uint8&) { } +inline void EndianConvert( int8&) { } +inline void EndianConvertReverse(uint8&) { } +inline void EndianConvertReverse( int8&) { } + +#endif + diff --git a/src/server/shared/Utilities/EventProcessor.cpp b/src/server/shared/Utilities/EventProcessor.cpp new file mode 100644 index 00000000000..c695b43313a --- /dev/null +++ b/src/server/shared/Utilities/EventProcessor.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "EventProcessor.h" + +EventProcessor::EventProcessor() +{ + m_time = 0; + m_aborting = false; +} + +EventProcessor::~EventProcessor() +{ + KillAllEvents(true); +} + +void EventProcessor::Update(uint32 p_time) +{ + // update time + m_time += p_time; + + // main event loop + EventList::iterator i; + while (((i = m_events.begin()) != m_events.end()) && i->first <= m_time) + { + // get and remove event from queue + BasicEvent* Event = i->second; + m_events.erase(i); + + if (!Event->to_Abort) + { + if (Event->Execute(m_time, p_time)) + { + // completely destroy event if it is not re-added + delete Event; + } + } + else + { + Event->Abort(m_time); + delete Event; + } + } +} + +void EventProcessor::KillAllEvents(bool force) +{ + // prevent event insertions + m_aborting = true; + + // first, abort all existing events + for (EventList::iterator i = m_events.begin(); i != m_events.end();) + { + EventList::iterator i_old = i; + ++i; + + i_old->second->to_Abort = true; + i_old->second->Abort(m_time); + if(force || i_old->second->IsDeletable()) + { + delete i_old->second; + + if(!force) // need per-element cleanup + m_events.erase (i_old); + } + } + + // fast clear event list (in force case) + if(force) + m_events.clear(); +} + +void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime) +{ + if (set_addtime) Event->m_addTime = m_time; + Event->m_execTime = e_time; + m_events.insert(std::pair(e_time, Event)); +} + +uint64 EventProcessor::CalculateTime(uint64 t_offset) +{ + return(m_time + t_offset); +} + diff --git a/src/server/shared/Utilities/EventProcessor.h b/src/server/shared/Utilities/EventProcessor.h new file mode 100644 index 00000000000..2712967e1b7 --- /dev/null +++ b/src/server/shared/Utilities/EventProcessor.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __EVENTPROCESSOR_H +#define __EVENTPROCESSOR_H + +#include "Platform/Define.h" + +#include + +// Note. All times are in milliseconds here. + +class BasicEvent +{ + public: + BasicEvent() { to_Abort = false; } + virtual ~BasicEvent() // override destructor to perform some actions on event removal + { + }; + + // this method executes when the event is triggered + // return false if event does not want to be deleted + // e_time is execution time, p_time is update interval + virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; } + + virtual bool IsDeletable() const { return true; } // this event can be safely deleted + + virtual void Abort(uint64 /*e_time*/) {} // this method executes when the event is aborted + + bool to_Abort; // set by externals when the event is aborted, aborted events don't execute + // and get Abort call when deleted + + // these can be used for time offset control + uint64 m_addTime; // time when the event was added to queue, filled by event handler + uint64 m_execTime; // planned time of next execution, filled by event handler +}; + +typedef std::multimap EventList; + +class EventProcessor +{ + public: + EventProcessor(); + ~EventProcessor(); + + void Update(uint32 p_time); + void KillAllEvents(bool force); + void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true); + uint64 CalculateTime(uint64 t_offset); + protected: + uint64 m_time; + EventList m_events; + bool m_aborting; +}; +#endif + diff --git a/src/server/worldserver/RemoteAccess/SocketDefines.h b/src/server/worldserver/RemoteAccess/SocketDefines.h new file mode 100644 index 00000000000..49366097ae6 --- /dev/null +++ b/src/server/worldserver/RemoteAccess/SocketDefines.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_SOCKETDEFINES_H +#define TRINITY_SOCKETDEFINES_H + +#ifdef WIN32 + +/* Windows socket definitions + */ +#define FD_SETSIZE 1024 +#include +#include + +typedef SOCKET SocketHandle; +typedef fd_set SelectSet; + +#else + +/* The unix socket definitions + */ +#include +#include +#ifdef __APPLE_CC__ +#include +#endif + +typedef int SocketHandle; +typedef fd_set SelectSet; +#endif +#endif + -- cgit v1.2.3 From ba535da6bc5f3d44be43460eeda27ddefcb9e409 Mon Sep 17 00:00:00 2001 From: Tartalo Date: Sun, 6 Jun 2010 23:47:37 +0200 Subject: Remove framework from server CMakeLists.txt --HG-- branch : trunk --- src/server/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) (limited to 'src/server') diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 39a96cf1f3c..fa0cd1acce2 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -1,4 +1,3 @@ -add_subdirectory(framework) add_subdirectory(game) if (DO_SCRIPTS) add_subdirectory(scripts) -- cgit v1.2.3 From 910980d3c65273e1dba78ec3928d5b4e78d713bd Mon Sep 17 00:00:00 2001 From: Tartalo Date: Mon, 7 Jun 2010 00:00:11 +0200 Subject: More case sensitive renames --HG-- branch : trunk rename : src/server/scripts/custom/custom_example.cpp => src/server/scripts/Custom/custom_example.cpp rename : src/server/scripts/custom/custom_gossip_codebox.cpp => src/server/scripts/Custom/custom_gossip_codebox.cpp rename : src/server/scripts/custom/npc_acherus_taxi.cpp => src/server/scripts/Custom/npc_acherus_taxi.cpp rename : src/server/scripts/custom/npc_wyrmresttempel_taxi.cpp => src/server/scripts/Custom/npc_wyrmresttempel_taxi.cpp rename : src/server/scripts/custom/on_events.cpp => src/server/scripts/Custom/on_events.cpp rename : src/server/scripts/custom/test.cpp => src/server/scripts/Custom/test.cpp rename : src/server/scripts/eastern_kingdoms/alterac_mountains.cpp => src/server/scripts/EasternKingdoms/alterac_mountains.cpp rename : src/server/scripts/eastern_kingdoms/alterac_valley/alterac_valley.cpp => src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp rename : src/server/scripts/eastern_kingdoms/alterac_valley/boss_balinda.cpp => src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp rename : src/server/scripts/eastern_kingdoms/alterac_valley/boss_drekthar.cpp => src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp rename : src/server/scripts/eastern_kingdoms/alterac_valley/boss_galvangar.cpp => src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp rename : src/server/scripts/eastern_kingdoms/alterac_valley/boss_vanndar.cpp => src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp rename : src/server/scripts/eastern_kingdoms/arathi_highlands.cpp => src/server/scripts/EasternKingdoms/arathi_highlands.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h => src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_moira_bronzebeard.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp => src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h => src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp rename : src/server/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp => src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp rename : src/server/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp => src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp rename : src/server/scripts/eastern_kingdoms/blasted_lands.cpp => src/server/scripts/EasternKingdoms/blasted_lands.cpp rename : src/server/scripts/eastern_kingdoms/boss_kruul.cpp => src/server/scripts/EasternKingdoms/boss_kruul.cpp rename : src/server/scripts/eastern_kingdoms/burning_steppes.cpp => src/server/scripts/EasternKingdoms/burning_steppes.cpp rename : src/server/scripts/eastern_kingdoms/deadmines/boss_mr_smite.cpp => src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp rename : src/server/scripts/eastern_kingdoms/deadmines/deadmines.cpp => src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp rename : src/server/scripts/eastern_kingdoms/deadmines/deadmines.h => src/server/scripts/EasternKingdoms/deadmines/deadmines.h rename : src/server/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp => src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp rename : src/server/scripts/eastern_kingdoms/dun_morogh.cpp => src/server/scripts/EasternKingdoms/dun_morogh.cpp rename : src/server/scripts/eastern_kingdoms/duskwood.cpp => src/server/scripts/EasternKingdoms/duskwood.cpp rename : src/server/scripts/eastern_kingdoms/eastern_plaguelands.cpp => src/server/scripts/EasternKingdoms/eastern_plaguelands.cpp rename : src/server/scripts/eastern_kingdoms/elwynn_forest.cpp => src/server/scripts/EasternKingdoms/elwynn_forest.cpp rename : src/server/scripts/eastern_kingdoms/eversong_woods.cpp => src/server/scripts/EasternKingdoms/eversong_woods.cpp rename : src/server/scripts/eastern_kingdoms/ghostlands.cpp => src/server/scripts/EasternKingdoms/ghostlands.cpp rename : src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp => src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp rename : src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h => src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h rename : src/server/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp => src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp rename : src/server/scripts/eastern_kingdoms/hinterlands.cpp => src/server/scripts/EasternKingdoms/hinterlands.cpp rename : src/server/scripts/eastern_kingdoms/ironforge.cpp => src/server/scripts/EasternKingdoms/ironforge.cpp rename : src/server/scripts/eastern_kingdoms/isle_of_queldanas.cpp => src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_curator.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp => src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp => src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp => src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/karazhan.cpp => src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp rename : src/server/scripts/eastern_kingdoms/karazhan/karazhan.h => src/server/scripts/EasternKingdoms/karazhan/karazhan.h rename : src/server/scripts/eastern_kingdoms/loch_modan.cpp => src/server/scripts/EasternKingdoms/loch_modan.cpp rename : src/server/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp => src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp rename : src/server/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp => src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp rename : src/server/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp => src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp rename : src/server/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp => src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp rename : src/server/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp => src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp rename : src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp => src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp rename : src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h => src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h rename : src/server/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_garr.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp => src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp => src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/molten_core.cpp => src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp rename : src/server/scripts/eastern_kingdoms/molten_core/molten_core.h => src/server/scripts/EasternKingdoms/molten_core/molten_core.h rename : src/server/scripts/eastern_kingdoms/redridge_mountains.cpp => src/server/scripts/EasternKingdoms/redridge_mountains.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter1.cpp => src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter2.cpp => src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter5.cpp => src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_enclave/the_scarlet_enclave.cpp => src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp => src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp rename : src/server/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h => src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h rename : src/server/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp => src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp => src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp rename : src/server/scripts/eastern_kingdoms/scholomance/scholomance.h => src/server/scripts/EasternKingdoms/scholomance/scholomance.h rename : src/server/scripts/eastern_kingdoms/searing_gorge.cpp => src/server/scripts/EasternKingdoms/searing_gorge.cpp rename : src/server/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp => src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp rename : src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp => src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp rename : src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h => src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h rename : src/server/scripts/eastern_kingdoms/silvermoon_city.cpp => src/server/scripts/EasternKingdoms/silvermoon_city.cpp rename : src/server/scripts/eastern_kingdoms/silverpine_forest.cpp => src/server/scripts/EasternKingdoms/silverpine_forest.cpp rename : src/server/scripts/eastern_kingdoms/stormwind_city.cpp => src/server/scripts/EasternKingdoms/stormwind_city.cpp rename : src/server/scripts/eastern_kingdoms/stranglethorn_vale.cpp => src/server/scripts/EasternKingdoms/stranglethorn_vale.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp => src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp => src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/stratholme.cpp => src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp rename : src/server/scripts/eastern_kingdoms/stratholme/stratholme.h => src/server/scripts/EasternKingdoms/stratholme/stratholme.h rename : src/server/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp => src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp rename : src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp => src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp rename : src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h => src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp => src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_eredar_twins.cpp => src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_felmyst.cpp => src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp => src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp => src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp => src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp => src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.cpp => src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp rename : src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h => src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h rename : src/server/scripts/eastern_kingdoms/tirisfal_glades.cpp => src/server/scripts/EasternKingdoms/tirisfal_glades.cpp rename : src/server/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp => src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp rename : src/server/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp => src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp rename : src/server/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp => src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp rename : src/server/scripts/eastern_kingdoms/uldaman/uldaman.cpp => src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp rename : src/server/scripts/eastern_kingdoms/undercity.cpp => src/server/scripts/EasternKingdoms/undercity.cpp rename : src/server/scripts/eastern_kingdoms/western_plaguelands.cpp => src/server/scripts/EasternKingdoms/western_plaguelands.cpp rename : src/server/scripts/eastern_kingdoms/westfall.cpp => src/server/scripts/EasternKingdoms/westfall.cpp rename : src/server/scripts/eastern_kingdoms/wetlands.cpp => src/server/scripts/EasternKingdoms/wetlands.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp => src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp => src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/boss_hexlord.cpp => src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp => src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp => src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp => src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp => src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/zulaman.cpp => src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp rename : src/server/scripts/eastern_kingdoms/zulaman/zulaman.h => src/server/scripts/EasternKingdoms/zulaman/zulaman.h rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp => src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp => src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp rename : src/server/scripts/eastern_kingdoms/zulgurub/zulgurub.h => src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h rename : src/server/scripts/examples/example_creature.cpp => src/server/scripts/Examples/example_creature.cpp rename : src/server/scripts/examples/example_escort.cpp => src/server/scripts/Examples/example_escort.cpp rename : src/server/scripts/examples/example_gossip_codebox.cpp => src/server/scripts/Examples/example_gossip_codebox.cpp rename : src/server/scripts/examples/example_misc.cpp => src/server/scripts/Examples/example_misc.cpp rename : src/server/scripts/kalimdor/ashenvale.cpp => src/server/scripts/Kalimdor/ashenvale.cpp rename : src/server/scripts/kalimdor/azshara.cpp => src/server/scripts/Kalimdor/azshara.cpp rename : src/server/scripts/kalimdor/azuremyst_isle.cpp => src/server/scripts/Kalimdor/azuremyst_isle.cpp rename : src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.cpp => src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp rename : src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.h => src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h rename : src/server/scripts/kalimdor/blackfathom_depths/boss_aku_mai.cpp => src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp rename : src/server/scripts/kalimdor/blackfathom_depths/boss_gelihast.cpp => src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp rename : src/server/scripts/kalimdor/blackfathom_depths/boss_kelris.cpp => src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp rename : src/server/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp => src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp rename : src/server/scripts/kalimdor/bloodmyst_isle.cpp => src/server/scripts/Kalimdor/bloodmyst_isle.cpp rename : src/server/scripts/kalimdor/boss_azuregos.cpp => src/server/scripts/Kalimdor/boss_azuregos.cpp rename : src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp => src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp rename : src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp => src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp rename : src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp => src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp rename : src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp => src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp rename : src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp => src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp rename : src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp => src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp rename : src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h => src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h rename : src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp => src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp rename : src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp => src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp rename : src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp => src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp rename : src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp => src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp rename : src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp => src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp rename : src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h => src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h rename : src/server/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp => src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h => src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h => src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.h => src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h rename : src/server/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp => src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp rename : src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp => src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp rename : src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp => src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp rename : src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp => src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp rename : src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp => src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp rename : src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp => src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp rename : src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h => src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h rename : src/server/scripts/kalimdor/darkshore.cpp => src/server/scripts/Kalimdor/darkshore.cpp rename : src/server/scripts/kalimdor/desolace.cpp => src/server/scripts/Kalimdor/desolace.cpp rename : src/server/scripts/kalimdor/durotar.cpp => src/server/scripts/Kalimdor/durotar.cpp rename : src/server/scripts/kalimdor/dustwallow_marsh.cpp => src/server/scripts/Kalimdor/dustwallow_marsh.cpp rename : src/server/scripts/kalimdor/felwood.cpp => src/server/scripts/Kalimdor/felwood.cpp rename : src/server/scripts/kalimdor/feralas.cpp => src/server/scripts/Kalimdor/feralas.cpp rename : src/server/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp => src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp rename : src/server/scripts/kalimdor/maraudon/boss_landslide.cpp => src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp rename : src/server/scripts/kalimdor/maraudon/boss_noxxion.cpp => src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp rename : src/server/scripts/kalimdor/maraudon/boss_princess_theradras.cpp => src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp rename : src/server/scripts/kalimdor/moonglade.cpp => src/server/scripts/Kalimdor/moonglade.cpp rename : src/server/scripts/kalimdor/mulgore.cpp => src/server/scripts/Kalimdor/mulgore.cpp rename : src/server/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp => src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp rename : src/server/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp => src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp rename : src/server/scripts/kalimdor/onyxias_lair/onyxias_lair.h => src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h rename : src/server/scripts/kalimdor/orgrimmar.cpp => src/server/scripts/Kalimdor/orgrimmar.cpp rename : src/server/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp => src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp rename : src/server/scripts/kalimdor/razorfen_downs/instance_razorfen_downs.cpp => src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp rename : src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp => src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp rename : src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.h => src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h rename : src/server/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp => src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp rename : src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.cpp => src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp rename : src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h => src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h rename : src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp => src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp rename : src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp => src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp rename : src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp => src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp rename : src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp => src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp rename : src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp => src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp rename : src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp => src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp rename : src/server/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp => src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp rename : src/server/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h => src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h rename : src/server/scripts/kalimdor/silithus.cpp => src/server/scripts/Kalimdor/silithus.cpp rename : src/server/scripts/kalimdor/stonetalon_mountains.cpp => src/server/scripts/Kalimdor/stonetalon_mountains.cpp rename : src/server/scripts/kalimdor/tanaris.cpp => src/server/scripts/Kalimdor/tanaris.cpp rename : src/server/scripts/kalimdor/teldrassil.cpp => src/server/scripts/Kalimdor/teldrassil.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp => src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp rename : src/server/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h => src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h rename : src/server/scripts/kalimdor/the_barrens.cpp => src/server/scripts/Kalimdor/the_barrens.cpp rename : src/server/scripts/kalimdor/thousand_needles.cpp => src/server/scripts/Kalimdor/thousand_needles.cpp rename : src/server/scripts/kalimdor/thunder_bluff.cpp => src/server/scripts/Kalimdor/thunder_bluff.cpp rename : src/server/scripts/kalimdor/ungoro_crater.cpp => src/server/scripts/Kalimdor/ungoro_crater.cpp rename : src/server/scripts/kalimdor/wailing_caverns/instance_wailing_caverns.cpp => src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp rename : src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.cpp => src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp rename : src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.h => src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h rename : src/server/scripts/kalimdor/winterspring.cpp => src/server/scripts/Kalimdor/winterspring.cpp rename : src/server/scripts/kalimdor/zulfarrak/instance_zulfarrak.cpp => src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp rename : src/server/scripts/kalimdor/zulfarrak/zulfarrak.cpp => src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp rename : src/server/scripts/northrend/azjol_nerub/ahnkahet/ahnkahet.h => src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h rename : src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp => src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp rename : src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp => src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp rename : src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp => src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp rename : src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp => src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp rename : src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp => src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp rename : src/server/scripts/northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp => src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp rename : src/server/scripts/northrend/azjol_nerub/azjol_nerub/azjol_nerub.h => src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h rename : src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp => src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp rename : src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp => src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp rename : src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp => src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp rename : src/server/scripts/northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp => src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp rename : src/server/scripts/northrend/borean_tundra.cpp => src/server/scripts/Northrend/borean_tundra.cpp rename : src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp => src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp rename : src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp => src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp rename : src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp => src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp rename : src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp => src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp rename : src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp => src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp rename : src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h => src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h rename : src/server/scripts/northrend/crystalsong_forest.cpp => src/server/scripts/Northrend/crystalsong_forest.cpp rename : src/server/scripts/northrend/dalaran.cpp => src/server/scripts/Northrend/dalaran.cpp rename : src/server/scripts/northrend/dragonblight.cpp => src/server/scripts/Northrend/dragonblight.cpp rename : src/server/scripts/northrend/draktharon_keep/boss_dred.cpp => src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp rename : src/server/scripts/northrend/draktharon_keep/boss_novos.cpp => src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp rename : src/server/scripts/northrend/draktharon_keep/boss_tharon_ja.cpp => src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp rename : src/server/scripts/northrend/draktharon_keep/boss_trollgore.cpp => src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp rename : src/server/scripts/northrend/draktharon_keep/drak_tharon_keep.h => src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h rename : src/server/scripts/northrend/draktharon_keep/instance_drak_tharon_keep.cpp => src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp rename : src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp => src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp rename : src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp => src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp rename : src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp => src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp rename : src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h => src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h rename : src/server/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp => src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp rename : src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp => src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp rename : src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp => src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp rename : src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp => src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp rename : src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h => src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h rename : src/server/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp => src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp rename : src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp => src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp rename : src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp => src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp rename : src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp => src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp rename : src/server/scripts/northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp => src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp rename : src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp => src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp rename : src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.h => src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h rename : src/server/scripts/northrend/grizzly_hills.cpp => src/server/scripts/Northrend/grizzly_hills.cpp rename : src/server/scripts/northrend/gundrak/boss_drakkari_colossus.cpp => src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp rename : src/server/scripts/northrend/gundrak/boss_eck.cpp => src/server/scripts/Northrend/gundrak/boss_eck.cpp rename : src/server/scripts/northrend/gundrak/boss_gal_darah.cpp => src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp rename : src/server/scripts/northrend/gundrak/boss_moorabi.cpp => src/server/scripts/Northrend/gundrak/boss_moorabi.cpp rename : src/server/scripts/northrend/gundrak/boss_slad_ran.cpp => src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp rename : src/server/scripts/northrend/gundrak/gundrak.h => src/server/scripts/Northrend/gundrak/gundrak.h rename : src/server/scripts/northrend/gundrak/instance_gundrak.cpp => src/server/scripts/Northrend/gundrak/instance_gundrak.cpp rename : src/server/scripts/northrend/howling_fjord.cpp => src/server/scripts/Northrend/howling_fjord.cpp rename : src/server/scripts/northrend/icecrown.cpp => src/server/scripts/Northrend/icecrown.cpp rename : src/server/scripts/northrend/naxxramas/boss_anubrekhan.cpp => src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp rename : src/server/scripts/northrend/naxxramas/boss_faerlina.cpp => src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp rename : src/server/scripts/northrend/naxxramas/boss_four_horsemen.cpp => src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp rename : src/server/scripts/northrend/naxxramas/boss_gluth.cpp => src/server/scripts/Northrend/naxxramas/boss_gluth.cpp rename : src/server/scripts/northrend/naxxramas/boss_gothik.cpp => src/server/scripts/Northrend/naxxramas/boss_gothik.cpp rename : src/server/scripts/northrend/naxxramas/boss_grobbulus.cpp => src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp rename : src/server/scripts/northrend/naxxramas/boss_heigan.cpp => src/server/scripts/Northrend/naxxramas/boss_heigan.cpp rename : src/server/scripts/northrend/naxxramas/boss_highlord_mograine.cpp => src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp rename : src/server/scripts/northrend/naxxramas/boss_kelthuzad.cpp => src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp rename : src/server/scripts/northrend/naxxramas/boss_loatheb.cpp => src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp rename : src/server/scripts/northrend/naxxramas/boss_maexxna.cpp => src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp rename : src/server/scripts/northrend/naxxramas/boss_noth.cpp => src/server/scripts/Northrend/naxxramas/boss_noth.cpp rename : src/server/scripts/northrend/naxxramas/boss_patchwerk.cpp => src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp rename : src/server/scripts/northrend/naxxramas/boss_razuvious.cpp => src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp rename : src/server/scripts/northrend/naxxramas/boss_sapphiron.cpp => src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp rename : src/server/scripts/northrend/naxxramas/boss_thaddius.cpp => src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp rename : src/server/scripts/northrend/naxxramas/instance_naxxramas.cpp => src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp rename : src/server/scripts/northrend/naxxramas/naxxramas.h => src/server/scripts/Northrend/naxxramas/naxxramas.h rename : src/server/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp => src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp rename : src/server/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h => src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h rename : src/server/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp => src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp rename : src/server/scripts/northrend/nexus/nexus/boss_anomalus.cpp => src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp rename : src/server/scripts/northrend/nexus/nexus/boss_keristrasza.cpp => src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp rename : src/server/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp => src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp rename : src/server/scripts/northrend/nexus/nexus/boss_ormorok.cpp => src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp rename : src/server/scripts/northrend/nexus/nexus/commander_kolurg.cpp => src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp rename : src/server/scripts/northrend/nexus/nexus/commander_stoutbeard.cpp => src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp rename : src/server/scripts/northrend/nexus/nexus/instance_nexus.cpp => src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp rename : src/server/scripts/northrend/nexus/nexus/nexus.h => src/server/scripts/Northrend/nexus/nexus/nexus.h rename : src/server/scripts/northrend/nexus/oculus/boss_drakos.cpp => src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp rename : src/server/scripts/northrend/nexus/oculus/boss_eregos.cpp => src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp rename : src/server/scripts/northrend/nexus/oculus/boss_urom.cpp => src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp rename : src/server/scripts/northrend/nexus/oculus/boss_varos.cpp => src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp rename : src/server/scripts/northrend/nexus/oculus/instance_oculus.cpp => src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp rename : src/server/scripts/northrend/nexus/oculus/oculus.cpp => src/server/scripts/Northrend/nexus/oculus/oculus.cpp rename : src/server/scripts/northrend/nexus/oculus/oculus.h => src/server/scripts/Northrend/nexus/oculus/oculus.h rename : src/server/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp => src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp rename : src/server/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp => src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp rename : src/server/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h => src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h rename : src/server/scripts/northrend/sholazar_basin.cpp => src/server/scripts/Northrend/sholazar_basin.cpp rename : src/server/scripts/northrend/storm_peaks.cpp => src/server/scripts/Northrend/storm_peaks.cpp rename : src/server/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp => src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp rename : src/server/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp => src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp rename : src/server/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp => src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp rename : src/server/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp => src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp rename : src/server/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h => src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h rename : src/server/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp => src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp rename : src/server/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp => src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp rename : src/server/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp => src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp rename : src/server/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp => src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp rename : src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp => src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp rename : src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h => src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h rename : src/server/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp => src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_algalon.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_freya.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_hodir.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_ignis.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_thorim.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_xt002.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp rename : src/server/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp => src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp rename : src/server/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp => src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp rename : src/server/scripts/northrend/ulduar/ulduar/ulduar.h => src/server/scripts/Northrend/ulduar/ulduar/ulduar.h rename : src/server/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp => src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.h => src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h rename : src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp => src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp rename : src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h => src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h rename : src/server/scripts/northrend/vault_of_archavon/boss_archavon.cpp => src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp rename : src/server/scripts/northrend/vault_of_archavon/boss_emalon.cpp => src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp rename : src/server/scripts/northrend/vault_of_archavon/boss_koralon.cpp => src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp rename : src/server/scripts/northrend/vault_of_archavon/boss_toravon.cpp => src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp rename : src/server/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp => src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp rename : src/server/scripts/northrend/vault_of_archavon/vault_of_archavon.h => src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h rename : src/server/scripts/northrend/violet_hold/boss_cyanigosa.cpp => src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp rename : src/server/scripts/northrend/violet_hold/boss_erekem.cpp => src/server/scripts/Northrend/violet_hold/boss_erekem.cpp rename : src/server/scripts/northrend/violet_hold/boss_ichoron.cpp => src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp rename : src/server/scripts/northrend/violet_hold/boss_lavanthor.cpp => src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp rename : src/server/scripts/northrend/violet_hold/boss_moragg.cpp => src/server/scripts/Northrend/violet_hold/boss_moragg.cpp rename : src/server/scripts/northrend/violet_hold/boss_xevozz.cpp => src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp rename : src/server/scripts/northrend/violet_hold/boss_zuramat.cpp => src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp rename : src/server/scripts/northrend/violet_hold/instance_violet_hold.cpp => src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp rename : src/server/scripts/northrend/violet_hold/violet_hold.cpp => src/server/scripts/Northrend/violet_hold/violet_hold.cpp rename : src/server/scripts/northrend/violet_hold/violet_hold.h => src/server/scripts/Northrend/violet_hold/violet_hold.h rename : src/server/scripts/northrend/zuldrak.cpp => src/server/scripts/Northrend/zuldrak.cpp rename : src/server/scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp => src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp rename : src/server/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp => src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp rename : src/server/scripts/outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp => src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp rename : src/server/scripts/outland/auchindoun/mana_tombs/boss_pandemonius.cpp => src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp rename : src/server/scripts/outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp => src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp rename : src/server/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp => src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp rename : src/server/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp => src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp rename : src/server/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h => src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h rename : src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp => src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp rename : src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp => src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp rename : src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp => src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp rename : src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_murmur.cpp => src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp rename : src/server/scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp => src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp rename : src/server/scripts/outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h => src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h rename : src/server/scripts/outland/black_temple/black_temple.cpp => src/server/scripts/Outland/black_temple/black_temple.cpp rename : src/server/scripts/outland/black_temple/black_temple.h => src/server/scripts/Outland/black_temple/black_temple.h rename : src/server/scripts/outland/black_temple/boss_bloodboil.cpp => src/server/scripts/Outland/black_temple/boss_bloodboil.cpp rename : src/server/scripts/outland/black_temple/boss_illidan.cpp => src/server/scripts/Outland/black_temple/boss_illidan.cpp rename : src/server/scripts/outland/black_temple/boss_mother_shahraz.cpp => src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp rename : src/server/scripts/outland/black_temple/boss_reliquary_of_souls.cpp => src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp rename : src/server/scripts/outland/black_temple/boss_shade_of_akama.cpp => src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp rename : src/server/scripts/outland/black_temple/boss_supremus.cpp => src/server/scripts/Outland/black_temple/boss_supremus.cpp rename : src/server/scripts/outland/black_temple/boss_teron_gorefiend.cpp => src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp rename : src/server/scripts/outland/black_temple/boss_warlord_najentus.cpp => src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp rename : src/server/scripts/outland/black_temple/illidari_council.cpp => src/server/scripts/Outland/black_temple/illidari_council.cpp rename : src/server/scripts/outland/black_temple/instance_black_temple.cpp => src/server/scripts/Outland/black_temple/instance_black_temple.cpp rename : src/server/scripts/outland/blades_edge_mountains.cpp => src/server/scripts/Outland/blades_edge_mountains.cpp rename : src/server/scripts/outland/boss_doomlord_kazzak.cpp => src/server/scripts/Outland/boss_doomlord_kazzak.cpp rename : src/server/scripts/outland/boss_doomwalker.cpp => src/server/scripts/Outland/boss_doomwalker.cpp rename : src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp => src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp rename : src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp => src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp rename : src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp => src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp rename : src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp => src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp rename : src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp => src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp rename : src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp => src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp rename : src/server/scripts/outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp => src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp rename : src/server/scripts/outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h => src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h rename : src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp => src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp rename : src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp => src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp rename : src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp => src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp rename : src/server/scripts/outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp => src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp rename : src/server/scripts/outland/coilfang_resevoir/steam_vault/steam_vault.h => src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h rename : src/server/scripts/outland/coilfang_resevoir/underbog/boss_hungarfen.cpp => src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp rename : src/server/scripts/outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp => src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp rename : src/server/scripts/outland/gruuls_lair/boss_gruul.cpp => src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp rename : src/server/scripts/outland/gruuls_lair/boss_high_king_maulgar.cpp => src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp rename : src/server/scripts/outland/gruuls_lair/gruuls_lair.h => src/server/scripts/Outland/gruuls_lair/gruuls_lair.h rename : src/server/scripts/outland/gruuls_lair/instance_gruuls_lair.cpp => src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp rename : src/server/scripts/outland/hellfire_citadel/blood_furnace/blood_furnace.h => src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h rename : src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_broggok.cpp => src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp rename : src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp => src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp rename : src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp => src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp rename : src/server/scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp => src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp rename : src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp => src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp rename : src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp => src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp rename : src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp => src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp rename : src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h => src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h rename : src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp => src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp rename : src/server/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp => src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp rename : src/server/scripts/outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp => src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp rename : src/server/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h => src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h rename : src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp => src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp rename : src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp => src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp rename : src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp => src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp rename : src/server/scripts/outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp => src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp rename : src/server/scripts/outland/hellfire_citadel/shattered_halls/shattered_halls.h => src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h rename : src/server/scripts/outland/hellfire_peninsula.cpp => src/server/scripts/Outland/hellfire_peninsula.cpp rename : src/server/scripts/outland/nagrand.cpp => src/server/scripts/Outland/nagrand.cpp rename : src/server/scripts/outland/netherstorm.cpp => src/server/scripts/Outland/netherstorm.cpp rename : src/server/scripts/outland/shadowmoon_valley.cpp => src/server/scripts/Outland/shadowmoon_valley.cpp rename : src/server/scripts/outland/shattrath_city.cpp => src/server/scripts/Outland/shattrath_city.cpp rename : src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp => src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp rename : src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.h => src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h rename : src/server/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp => src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp rename : src/server/scripts/outland/tempest_keep/arcatraz/instance_arcatraz.cpp => src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp rename : src/server/scripts/outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp => src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp rename : src/server/scripts/outland/tempest_keep/botanica/boss_laj.cpp => src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp rename : src/server/scripts/outland/tempest_keep/botanica/boss_warp_splinter.cpp => src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp rename : src/server/scripts/outland/tempest_keep/the_eye/boss_alar.cpp => src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp rename : src/server/scripts/outland/tempest_keep/the_eye/boss_astromancer.cpp => src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp rename : src/server/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp => src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp rename : src/server/scripts/outland/tempest_keep/the_eye/boss_void_reaver.cpp => src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp rename : src/server/scripts/outland/tempest_keep/the_eye/instance_the_eye.cpp => src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp rename : src/server/scripts/outland/tempest_keep/the_eye/the_eye.cpp => src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp rename : src/server/scripts/outland/tempest_keep/the_eye/the_eye.h => src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h rename : src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp => src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp rename : src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp => src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp rename : src/server/scripts/outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp => src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp rename : src/server/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp => src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp rename : src/server/scripts/outland/tempest_keep/the_mechanar/instance_mechanar.cpp => src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp rename : src/server/scripts/outland/tempest_keep/the_mechanar/mechanar.h => src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h rename : src/server/scripts/outland/terokkar_forest.cpp => src/server/scripts/Outland/terokkar_forest.cpp rename : src/server/scripts/outland/zangarmarsh.cpp => src/server/scripts/Outland/zangarmarsh.cpp rename : src/server/scripts/world/areatrigger_scripts.cpp => src/server/scripts/World/areatrigger_scripts.cpp rename : src/server/scripts/world/boss_emeriss.cpp => src/server/scripts/World/boss_emeriss.cpp rename : src/server/scripts/world/boss_lethon.cpp => src/server/scripts/World/boss_lethon.cpp rename : src/server/scripts/world/boss_taerar.cpp => src/server/scripts/World/boss_taerar.cpp rename : src/server/scripts/world/boss_ysondre.cpp => src/server/scripts/World/boss_ysondre.cpp rename : src/server/scripts/world/go_scripts.cpp => src/server/scripts/World/go_scripts.cpp rename : src/server/scripts/world/guards.cpp => src/server/scripts/World/guards.cpp rename : src/server/scripts/world/item_scripts.cpp => src/server/scripts/World/item_scripts.cpp rename : src/server/scripts/world/mob_generic_creature.cpp => src/server/scripts/World/mob_generic_creature.cpp rename : src/server/scripts/world/npc_innkeeper.cpp => src/server/scripts/World/npc_innkeeper.cpp rename : src/server/scripts/world/npc_professions.cpp => src/server/scripts/World/npc_professions.cpp rename : src/server/scripts/world/npc_taxi.cpp => src/server/scripts/World/npc_taxi.cpp rename : src/server/scripts/world/npcs_special.cpp => src/server/scripts/World/npcs_special.cpp --- src/server/scripts/Custom/custom_example.cpp | 278 +++ .../scripts/Custom/custom_gossip_codebox.cpp | 89 + src/server/scripts/Custom/npc_acherus_taxi.cpp | 35 + .../scripts/Custom/npc_wyrmresttempel_taxi.cpp | 112 + src/server/scripts/Custom/on_events.cpp | 108 + src/server/scripts/Custom/test.cpp | 218 ++ .../scripts/EasternKingdoms/alterac_mountains.cpp | 32 + .../alterac_valley/alterac_valley.cpp | 180 ++ .../alterac_valley/boss_balinda.cpp | 203 ++ .../alterac_valley/boss_drekthar.cpp | 138 ++ .../alterac_valley/boss_galvangar.cpp | 129 + .../alterac_valley/boss_vanndar.cpp | 129 + .../scripts/EasternKingdoms/arathi_highlands.cpp | 132 + .../blackrock_depths/blackrock_depths.cpp | 1338 ++++++++++ .../blackrock_depths/blackrock_depths.h | 45 + .../blackrock_depths/boss_ambassador_flamelash.cpp | 91 + .../blackrock_depths/boss_anubshiah.cpp | 116 + .../boss_emperor_dagran_thaurissan.cpp | 111 + .../blackrock_depths/boss_general_angerforge.cpp | 132 + .../blackrock_depths/boss_gorosh_the_dervish.cpp | 84 + .../blackrock_depths/boss_grizzle.cpp | 94 + .../boss_high_interrogator_gerstahn.cpp | 106 + .../blackrock_depths/boss_magmus.cpp | 98 + .../blackrock_depths/boss_moira_bronzebeard.cpp | 98 + .../blackrock_depths/boss_tomb_of_seven.cpp | 254 ++ .../blackrock_depths/instance_blackrock_depths.cpp | 460 ++++ .../blackrock_spire/blackrock_spire.cpp | 77 + .../blackrock_spire/blackrock_spire.h | 26 + .../blackrock_spire/boss_drakkisath.cpp | 102 + .../EasternKingdoms/blackrock_spire/boss_gyth.cpp | 205 ++ .../blackrock_spire/boss_halycon.cpp | 96 + .../blackrock_spire/boss_highlord_omokk.cpp | 132 + .../blackrock_spire/boss_mother_smolderweb.cpp | 87 + .../blackrock_spire/boss_overlord_wyrmthalak.cpp | 126 + .../blackrock_spire/boss_pyroguard_emberseer.cpp | 93 + .../blackrock_spire/boss_quartermaster_zigris.cpp | 86 + .../blackrock_spire/boss_rend_blackhand.cpp | 92 + .../boss_shadow_hunter_voshgajin.cpp | 93 + .../blackrock_spire/boss_the_beast.cpp | 93 + .../blackrock_spire/boss_warmaster_voone.cpp | 122 + .../blackrock_spire/instance_blackrock_spire.cpp | 104 + .../blackwing_lair/boss_broodlord_lashlayer.cpp | 112 + .../blackwing_lair/boss_chromaggus.cpp | 301 +++ .../blackwing_lair/boss_ebonroc.cpp | 104 + .../blackwing_lair/boss_firemaw.cpp | 95 + .../blackwing_lair/boss_flamegor.cpp | 98 + .../blackwing_lair/boss_nefarian.cpp | 231 ++ .../blackwing_lair/boss_razorgore.cpp | 125 + .../blackwing_lair/boss_vaelastrasz.cpp | 262 ++ .../blackwing_lair/boss_victor_nefarius.cpp | 385 +++ .../blackwing_lair/instance_blackwing_lair.cpp | 25 + .../scripts/EasternKingdoms/blasted_lands.cpp | 161 ++ src/server/scripts/EasternKingdoms/boss_kruul.cpp | 154 ++ .../scripts/EasternKingdoms/burning_steppes.cpp | 153 ++ .../EasternKingdoms/deadmines/boss_mr_smite.cpp | 182 ++ .../EasternKingdoms/deadmines/deadmines.cpp | 60 + .../scripts/EasternKingdoms/deadmines/deadmines.h | 35 + .../deadmines/instance_deadmines.cpp | 256 ++ src/server/scripts/EasternKingdoms/dun_morogh.cpp | 102 + src/server/scripts/EasternKingdoms/duskwood.cpp | 126 + .../EasternKingdoms/eastern_plaguelands.cpp | 185 ++ .../scripts/EasternKingdoms/elwynn_forest.cpp | 101 + .../scripts/EasternKingdoms/eversong_woods.cpp | 711 ++++++ src/server/scripts/EasternKingdoms/ghostlands.cpp | 250 ++ .../EasternKingdoms/gnomeregan/gnomeregan.cpp | 593 +++++ .../EasternKingdoms/gnomeregan/gnomeregan.h | 48 + .../gnomeregan/instance_gnomeregan.cpp | 141 ++ src/server/scripts/EasternKingdoms/hinterlands.cpp | 350 +++ src/server/scripts/EasternKingdoms/ironforge.cpp | 93 + .../scripts/EasternKingdoms/isle_of_queldanas.cpp | 151 ++ .../EasternKingdoms/karazhan/boss_curator.cpp | 196 ++ .../karazhan/boss_maiden_of_virtue.cpp | 138 ++ .../EasternKingdoms/karazhan/boss_midnight.cpp | 310 +++ .../EasternKingdoms/karazhan/boss_moroes.cpp | 785 ++++++ .../EasternKingdoms/karazhan/boss_netherspite.cpp | 343 +++ .../EasternKingdoms/karazhan/boss_nightbane.cpp | 418 ++++ .../karazhan/boss_prince_malchezaar.cpp | 604 +++++ .../karazhan/boss_shade_of_aran.cpp | 569 +++++ .../karazhan/boss_terestian_illhoof.cpp | 417 ++++ .../EasternKingdoms/karazhan/bosses_opera.cpp | 1494 +++++++++++ .../EasternKingdoms/karazhan/instance_karazhan.cpp | 308 +++ .../scripts/EasternKingdoms/karazhan/karazhan.cpp | 646 +++++ .../scripts/EasternKingdoms/karazhan/karazhan.h | 53 + src/server/scripts/EasternKingdoms/loch_modan.cpp | 100 + .../magisters_terrace/boss_felblood_kaelthas.cpp | 680 +++++ .../magisters_terrace/boss_priestess_delrissa.cpp | 1321 ++++++++++ .../magisters_terrace/boss_selin_fireheart.cpp | 366 +++ .../magisters_terrace/boss_vexallus.cpp | 226 ++ .../instance_magisters_terrace.cpp | 205 ++ .../magisters_terrace/magisters_terrace.cpp | 174 ++ .../magisters_terrace/magisters_terrace.h | 31 + .../molten_core/boss_baron_geddon.cpp | 107 + .../EasternKingdoms/molten_core/boss_garr.cpp | 143 ++ .../EasternKingdoms/molten_core/boss_gehennas.cpp | 93 + .../EasternKingdoms/molten_core/boss_golemagg.cpp | 198 ++ .../EasternKingdoms/molten_core/boss_lucifron.cpp | 91 + .../EasternKingdoms/molten_core/boss_magmadar.cpp | 100 + .../molten_core/boss_majordomo_executus.cpp | 134 + .../EasternKingdoms/molten_core/boss_ragnaros.cpp | 297 +++ .../EasternKingdoms/molten_core/boss_shazzrah.cpp | 121 + .../molten_core/boss_sulfuron_harbinger.cpp | 205 ++ .../molten_core/instance_molten_core.cpp | 266 ++ .../EasternKingdoms/molten_core/molten_core.cpp | 81 + .../EasternKingdoms/molten_core/molten_core.h | 22 + .../scripts/EasternKingdoms/redridge_mountains.cpp | 172 ++ .../EasternKingdoms/scarlet_enclave/chapter1.cpp | 1079 ++++++++ .../EasternKingdoms/scarlet_enclave/chapter2.cpp | 995 ++++++++ .../EasternKingdoms/scarlet_enclave/chapter5.cpp | 1684 +++++++++++++ .../scarlet_enclave/the_scarlet_enclave.cpp | 119 + .../scarlet_monastery/boss_arcanist_doan.cpp | 128 + .../boss_azshir_the_sleepless.cpp | 98 + .../scarlet_monastery/boss_bloodmage_thalnos.cpp | 124 + .../scarlet_monastery/boss_headless_horseman.cpp | 892 +++++++ .../scarlet_monastery/boss_herod.cpp | 158 ++ .../boss_high_inquisitor_fairbanks.cpp | 133 + .../scarlet_monastery/boss_houndmaster_loksey.cpp | 77 + .../scarlet_monastery/boss_interrogator_vishas.cpp | 118 + .../boss_mograine_and_whitemane.cpp | 359 +++ .../scarlet_monastery/boss_scorn.cpp | 101 + .../instance_scarlet_monastery.cpp | 157 ++ .../scarlet_monastery/scarlet_monastery.h | 18 + .../scholomance/boss_darkmaster_gandling.cpp | 225 ++ .../scholomance/boss_death_knight_darkreaver.cpp | 58 + .../scholomance/boss_doctor_theolen_krastinov.cpp | 117 + .../scholomance/boss_illucia_barov.cpp | 117 + .../scholomance/boss_instructor_malicia.cpp | 153 ++ .../scholomance/boss_jandice_barov.cpp | 201 ++ .../EasternKingdoms/scholomance/boss_kormok.cpp | 120 + .../scholomance/boss_lord_alexei_barov.cpp | 99 + .../scholomance/boss_lorekeeper_polkelt.cpp | 114 + .../scholomance/boss_ras_frostwhisper.cpp | 123 + .../scholomance/boss_the_ravenian.cpp | 117 + .../EasternKingdoms/scholomance/boss_vectus.cpp | 105 + .../scholomance/instance_scholomance.cpp | 146 ++ .../EasternKingdoms/scholomance/scholomance.h | 17 + .../scripts/EasternKingdoms/searing_gorge.cpp | 169 ++ .../shadowfang_keep/instance_shadowfang_keep.cpp | 277 +++ .../shadowfang_keep/shadowfang_keep.cpp | 198 ++ .../shadowfang_keep/shadowfang_keep.h | 17 + .../scripts/EasternKingdoms/silvermoon_city.cpp | 102 + .../scripts/EasternKingdoms/silverpine_forest.cpp | 385 +++ .../scripts/EasternKingdoms/stormwind_city.cpp | 696 ++++++ .../scripts/EasternKingdoms/stranglethorn_vale.cpp | 122 + .../stratholme/boss_baron_rivendare.cpp | 190 ++ .../stratholme/boss_baroness_anastari.cpp | 127 + .../stratholme/boss_cannon_master_willey.cpp | 220 ++ .../stratholme/boss_dathrohan_balnazzar.cpp | 217 ++ .../stratholme/boss_magistrate_barthilas.cpp | 128 + .../stratholme/boss_maleki_the_pallid.cpp | 108 + .../EasternKingdoms/stratholme/boss_nerubenkan.cpp | 121 + .../stratholme/boss_order_of_silver_hand.cpp | 157 ++ .../stratholme/boss_postmaster_malown.cpp | 144 ++ .../stratholme/boss_ramstein_the_gorger.cpp | 102 + .../stratholme/boss_timmy_the_cruel.cpp | 83 + .../stratholme/instance_stratholme.cpp | 458 ++++ .../EasternKingdoms/stratholme/stratholme.cpp | 282 +++ .../EasternKingdoms/stratholme/stratholme.h | 28 + .../sunken_temple/instance_sunken_temple.cpp | 204 ++ .../sunken_temple/sunken_temple.cpp | 71 + .../EasternKingdoms/sunken_temple/sunken_temple.h | 22 + .../sunwell_plateau/boss_brutallus.cpp | 349 +++ .../sunwell_plateau/boss_eredar_twins.cpp | 762 ++++++ .../sunwell_plateau/boss_felmyst.cpp | 579 +++++ .../sunwell_plateau/boss_kalecgos.cpp | 794 ++++++ .../sunwell_plateau/boss_kiljaeden.cpp | 1408 +++++++++++ .../EasternKingdoms/sunwell_plateau/boss_muru.cpp | 640 +++++ .../sunwell_plateau/instance_sunwell_plateau.cpp | 297 +++ .../sunwell_plateau/sunwell_plateau.cpp | 65 + .../sunwell_plateau/sunwell_plateau.h | 95 + .../scripts/EasternKingdoms/tirisfal_glades.cpp | 208 ++ .../EasternKingdoms/uldaman/boss_archaedas.cpp | 497 ++++ .../EasternKingdoms/uldaman/boss_ironaya.cpp | 106 + .../EasternKingdoms/uldaman/instance_uldaman.cpp | 300 +++ .../scripts/EasternKingdoms/uldaman/uldaman.cpp | 205 ++ src/server/scripts/EasternKingdoms/undercity.cpp | 252 ++ .../EasternKingdoms/western_plaguelands.cpp | 396 +++ src/server/scripts/EasternKingdoms/westfall.cpp | 263 ++ src/server/scripts/EasternKingdoms/wetlands.cpp | 168 ++ .../EasternKingdoms/zulaman/boss_akilzon.cpp | 467 ++++ .../EasternKingdoms/zulaman/boss_halazzi.cpp | 401 +++ .../EasternKingdoms/zulaman/boss_hexlord.cpp | 907 +++++++ .../EasternKingdoms/zulaman/boss_janalai.cpp | 687 ++++++ .../EasternKingdoms/zulaman/boss_nalorakk.cpp | 451 ++++ .../EasternKingdoms/zulaman/boss_zuljin.cpp | 623 +++++ .../EasternKingdoms/zulaman/instance_zulaman.cpp | 320 +++ .../scripts/EasternKingdoms/zulaman/zulaman.cpp | 192 ++ .../scripts/EasternKingdoms/zulaman/zulaman.h | 19 + .../EasternKingdoms/zulgurub/boss_arlokk.cpp | 278 +++ .../EasternKingdoms/zulgurub/boss_gahzranka.cpp | 93 + .../EasternKingdoms/zulgurub/boss_grilek.cpp | 93 + .../EasternKingdoms/zulgurub/boss_hakkar.cpp | 250 ++ .../EasternKingdoms/zulgurub/boss_hazzarah.cpp | 104 + .../EasternKingdoms/zulgurub/boss_jeklik.cpp | 291 +++ .../EasternKingdoms/zulgurub/boss_jindo.cpp | 263 ++ .../EasternKingdoms/zulgurub/boss_mandokir.cpp | 333 +++ .../EasternKingdoms/zulgurub/boss_marli.cpp | 261 ++ .../EasternKingdoms/zulgurub/boss_renataki.cpp | 152 ++ .../EasternKingdoms/zulgurub/boss_thekal.cpp | 556 +++++ .../EasternKingdoms/zulgurub/boss_venoxis.cpp | 199 ++ .../EasternKingdoms/zulgurub/boss_wushoolay.cpp | 85 + .../EasternKingdoms/zulgurub/instance_zulgurub.cpp | 159 ++ .../scripts/EasternKingdoms/zulgurub/zulgurub.h | 28 + src/server/scripts/Examples/example_creature.cpp | 292 +++ src/server/scripts/Examples/example_escort.cpp | 229 ++ .../scripts/Examples/example_gossip_codebox.cpp | 99 + src/server/scripts/Examples/example_misc.cpp | 69 + src/server/scripts/Kalimdor/ashenvale.cpp | 465 ++++ src/server/scripts/Kalimdor/azshara.cpp | 514 ++++ src/server/scripts/Kalimdor/azuremyst_isle.cpp | 718 ++++++ .../blackfathom_depths/blackfathom_deeps.cpp | 252 ++ .../blackfathom_depths/blackfathom_deeps.h | 53 + .../Kalimdor/blackfathom_depths/boss_aku_mai.cpp | 94 + .../Kalimdor/blackfathom_depths/boss_gelihast.cpp | 85 + .../Kalimdor/blackfathom_depths/boss_kelris.cpp | 108 + .../instance_blackfathom_deeps.cpp | 259 ++ src/server/scripts/Kalimdor/bloodmyst_isle.cpp | 149 ++ src/server/scripts/Kalimdor/boss_azuregos.cpp | 155 ++ .../culling_of_stratholme/boss_epoch.cpp | 156 ++ .../culling_of_stratholme/boss_infinite.cpp | 88 + .../culling_of_stratholme/boss_mal_ganis.cpp | 262 ++ .../culling_of_stratholme/boss_meathook.cpp | 140 ++ .../culling_of_stratholme/boss_salramm.cpp | 170 ++ .../culling_of_stratholme.cpp | 1210 +++++++++ .../culling_of_stratholme/culling_of_stratholme.h | 68 + .../instance_culling_of_stratholme.cpp | 244 ++ .../caverns_of_time/dark_portal/boss_aeonus.cpp | 145 ++ .../dark_portal/boss_chrono_lord_deja.cpp | 154 ++ .../caverns_of_time/dark_portal/boss_temporus.cpp | 152 ++ .../caverns_of_time/dark_portal/dark_portal.cpp | 404 +++ .../caverns_of_time/dark_portal/dark_portal.h | 35 + .../dark_portal/instance_dark_portal.cpp | 346 +++ .../caverns_of_time/hyjal/boss_anetheron.cpp | 309 +++ .../caverns_of_time/hyjal/boss_archimonde.cpp | 635 +++++ .../caverns_of_time/hyjal/boss_azgalor.cpp | 285 +++ .../caverns_of_time/hyjal/boss_kazrogal.cpp | 197 ++ .../hyjal/boss_rage_winterchill.cpp | 192 ++ .../Kalimdor/caverns_of_time/hyjal/hyjal.cpp | 247 ++ .../scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h | 38 + .../Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp | 1157 +++++++++ .../Kalimdor/caverns_of_time/hyjal/hyjalAI.h | 248 ++ .../Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp | 1440 +++++++++++ .../Kalimdor/caverns_of_time/hyjal/hyjal_trash.h | 35 + .../caverns_of_time/hyjal/instance_hyjal.cpp | 324 +++ .../old_hillsbrad/boss_captain_skarloc.cpp | 152 ++ .../old_hillsbrad/boss_epoch_hunter.cpp | 138 ++ .../old_hillsbrad/boss_leutenant_drake.cpp | 190 ++ .../old_hillsbrad/instance_old_hillsbrad.cpp | 238 ++ .../old_hillsbrad/old_hillsbrad.cpp | 658 +++++ .../caverns_of_time/old_hillsbrad/old_hillsbrad.h | 19 + src/server/scripts/Kalimdor/darkshore.cpp | 398 +++ src/server/scripts/Kalimdor/desolace.cpp | 259 ++ src/server/scripts/Kalimdor/durotar.cpp | 103 + src/server/scripts/Kalimdor/dustwallow_marsh.cpp | 425 ++++ src/server/scripts/Kalimdor/felwood.cpp | 90 + src/server/scripts/Kalimdor/feralas.cpp | 206 ++ .../Kalimdor/maraudon/boss_celebras_the_cursed.cpp | 98 + .../scripts/Kalimdor/maraudon/boss_landslide.cpp | 95 + .../scripts/Kalimdor/maraudon/boss_noxxion.cpp | 131 + .../Kalimdor/maraudon/boss_princess_theradras.cpp | 109 + src/server/scripts/Kalimdor/moonglade.cpp | 571 +++++ src/server/scripts/Kalimdor/mulgore.cpp | 316 +++ .../scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp | 500 ++++ .../onyxias_lair/instance_onyxias_lair.cpp | 249 ++ .../scripts/Kalimdor/onyxias_lair/onyxias_lair.h | 65 + src/server/scripts/Kalimdor/orgrimmar.cpp | 286 +++ .../boss_amnennar_the_coldbringer.cpp | 130 + .../razorfen_downs/instance_razorfen_downs.cpp | 215 ++ .../Kalimdor/razorfen_downs/razorfen_downs.cpp | 165 ++ .../Kalimdor/razorfen_downs/razorfen_downs.h | 45 + .../razorfen_kraul/instance_razorfen_kraul.cpp | 104 + .../Kalimdor/razorfen_kraul/razorfen_kraul.cpp | 194 ++ .../Kalimdor/razorfen_kraul/razorfen_kraul.h | 21 + .../Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp | 125 + .../Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp | 72 + .../Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp | 143 ++ .../Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp | 162 ++ .../Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp | 79 + .../Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp | 85 + .../instance_ruins_of_ahnqiraj.cpp | 213 ++ .../Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h | 34 + src/server/scripts/Kalimdor/silithus.cpp | 1140 +++++++++ .../scripts/Kalimdor/stonetalon_mountains.cpp | 172 ++ src/server/scripts/Kalimdor/tanaris.cpp | 635 +++++ src/server/scripts/Kalimdor/teldrassil.cpp | 114 + .../Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp | 346 +++ .../Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp | 1307 ++++++++++ .../Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp | 206 ++ .../Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp | 148 ++ .../Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp | 140 ++ .../Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp | 297 +++ .../Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp | 298 +++ .../temple_of_ahnqiraj/boss_twinemperors.cpp | 596 +++++ .../Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp | 30 + .../instance_temple_of_ahnqiraj.cpp | 166 ++ .../temple_of_ahnqiraj/mob_anubisath_sentinel.cpp | 296 +++ .../temple_of_ahnqiraj/temple_of_ahnqiraj.h | 23 + src/server/scripts/Kalimdor/the_barrens.cpp | 701 ++++++ src/server/scripts/Kalimdor/thousand_needles.cpp | 454 ++++ src/server/scripts/Kalimdor/thunder_bluff.cpp | 138 ++ src/server/scripts/Kalimdor/ungoro_crater.cpp | 356 +++ .../wailing_caverns/instance_wailing_caverns.cpp | 142 ++ .../Kalimdor/wailing_caverns/wailing_caverns.cpp | 396 +++ .../Kalimdor/wailing_caverns/wailing_caverns.h | 24 + src/server/scripts/Kalimdor/winterspring.cpp | 168 ++ .../Kalimdor/zulfarrak/instance_zulfarrak.cpp | 58 + .../scripts/Kalimdor/zulfarrak/zulfarrak.cpp | 280 +++ .../Northrend/azjol_nerub/ahnkahet/ahnkahet.h | 52 + .../azjol_nerub/ahnkahet/boss_amanitar.cpp | 226 ++ .../azjol_nerub/ahnkahet/boss_elder_nadox.cpp | 283 +++ .../azjol_nerub/ahnkahet/boss_herald_volazj.cpp | 328 +++ .../ahnkahet/boss_jedoga_shadowseeker.cpp | 588 +++++ .../azjol_nerub/ahnkahet/boss_prince_taldaram.cpp | 412 ++++ .../azjol_nerub/ahnkahet/instance_ahnkahet.cpp | 313 +++ .../azjol_nerub/azjol_nerub/azjol_nerub.h | 38 + .../azjol_nerub/azjol_nerub/boss_anubarak.cpp | 360 +++ .../azjol_nerub/azjol_nerub/boss_hadronox.cpp | 206 ++ .../azjol_nerub/boss_krikthir_the_gatewatcher.cpp | 553 +++++ .../azjol_nerub/instance_azjol_nerub.cpp | 215 ++ src/server/scripts/Northrend/borean_tundra.cpp | 2323 +++++++++++++++++ .../boss_argent_challenge.cpp | 512 ++++ .../trial_of_the_champion/boss_black_knight.cpp | 373 +++ .../trial_of_the_champion/boss_grand_champions.cpp | 993 ++++++++ .../instance_trial_of_the_champion.cpp | 340 +++ .../trial_of_the_champion.cpp | 512 ++++ .../trial_of_the_champion/trial_of_the_champion.h | 115 + .../scripts/Northrend/crystalsong_forest.cpp | 110 + src/server/scripts/Northrend/dalaran.cpp | 159 ++ src/server/scripts/Northrend/dragonblight.cpp | 272 ++ .../Northrend/draktharon_keep/boss_dred.cpp | 270 ++ .../Northrend/draktharon_keep/boss_novos.cpp | 328 +++ .../Northrend/draktharon_keep/boss_tharon_ja.cpp | 260 ++ .../Northrend/draktharon_keep/boss_trollgore.cpp | 197 ++ .../Northrend/draktharon_keep/drak_tharon_keep.h | 40 + .../draktharon_keep/instance_drak_tharon_keep.cpp | 243 ++ .../frozen_halls/forge_of_souls/boss_bronjahm.cpp | 263 ++ .../forge_of_souls/boss_devourer_of_souls.cpp | 349 +++ .../frozen_halls/forge_of_souls/forge_of_souls.cpp | 899 +++++++ .../frozen_halls/forge_of_souls/forge_of_souls.h | 52 + .../forge_of_souls/instance_forge_of_souls.cpp | 168 ++ .../halls_of_reflection/boss_falric.cpp | 142 ++ .../halls_of_reflection/boss_marwyn.cpp | 133 + .../halls_of_reflection/halls_of_reflection.cpp | 1022 ++++++++ .../halls_of_reflection/halls_of_reflection.h | 156 ++ .../instance_halls_of_reflection.cpp | 431 ++++ .../pit_of_saron/boss_forgemaster_garfrost.cpp | 209 ++ .../frozen_halls/pit_of_saron/boss_krickandick.cpp | 482 ++++ .../pit_of_saron/boss_scourgelord_tyrannus.cpp | 273 ++ .../pit_of_saron/instance_pit_of_saron.cpp | 236 ++ .../frozen_halls/pit_of_saron/pit_of_saron.cpp | 1101 +++++++++ .../frozen_halls/pit_of_saron/pit_of_saron.h | 63 + src/server/scripts/Northrend/grizzly_hills.cpp | 625 +++++ .../Northrend/gundrak/boss_drakkari_colossus.cpp | 317 +++ src/server/scripts/Northrend/gundrak/boss_eck.cpp | 168 ++ .../scripts/Northrend/gundrak/boss_gal_darah.cpp | 288 +++ .../scripts/Northrend/gundrak/boss_moorabi.cpp | 175 ++ .../scripts/Northrend/gundrak/boss_slad_ran.cpp | 266 ++ src/server/scripts/Northrend/gundrak/gundrak.h | 54 + .../scripts/Northrend/gundrak/instance_gundrak.cpp | 536 ++++ src/server/scripts/Northrend/howling_fjord.cpp | 338 +++ src/server/scripts/Northrend/icecrown.cpp | 422 ++++ .../Northrend/naxxramas/boss_anubrekhan.cpp | 185 ++ .../scripts/Northrend/naxxramas/boss_faerlina.cpp | 218 ++ .../Northrend/naxxramas/boss_four_horsemen.cpp | 397 +++ .../scripts/Northrend/naxxramas/boss_gluth.cpp | 147 ++ .../scripts/Northrend/naxxramas/boss_gothik.cpp | 582 +++++ .../scripts/Northrend/naxxramas/boss_grobbulus.cpp | 142 ++ .../scripts/Northrend/naxxramas/boss_heigan.cpp | 149 ++ .../Northrend/naxxramas/boss_highlord_mograine.cpp | 179 ++ .../scripts/Northrend/naxxramas/boss_kelthuzad.cpp | 706 ++++++ .../scripts/Northrend/naxxramas/boss_loatheb.cpp | 125 + .../scripts/Northrend/naxxramas/boss_maexxna.cpp | 186 ++ .../scripts/Northrend/naxxramas/boss_noth.cpp | 212 ++ .../scripts/Northrend/naxxramas/boss_patchwerk.cpp | 159 ++ .../scripts/Northrend/naxxramas/boss_razuvious.cpp | 139 ++ .../scripts/Northrend/naxxramas/boss_sapphiron.cpp | 403 +++ .../scripts/Northrend/naxxramas/boss_thaddius.cpp | 400 +++ .../Northrend/naxxramas/instance_naxxramas.cpp | 324 +++ src/server/scripts/Northrend/naxxramas/naxxramas.h | 75 + .../nexus/eye_of_eternity/boss_malygos.cpp | 175 ++ .../nexus/eye_of_eternity/eye_of_eternity.h | 4 + .../eye_of_eternity/instance_eye_of_eternity.cpp | 21 + .../Northrend/nexus/nexus/boss_anomalus.cpp | 253 ++ .../Northrend/nexus/nexus/boss_keristrasza.cpp | 247 ++ .../Northrend/nexus/nexus/boss_magus_telestra.cpp | 327 +++ .../scripts/Northrend/nexus/nexus/boss_ormorok.cpp | 298 +++ .../Northrend/nexus/nexus/commander_kolurg.cpp | 58 + .../Northrend/nexus/nexus/commander_stoutbeard.cpp | 64 + .../Northrend/nexus/nexus/instance_nexus.cpp | 259 ++ src/server/scripts/Northrend/nexus/nexus/nexus.h | 35 + .../scripts/Northrend/nexus/oculus/boss_drakos.cpp | 218 ++ .../scripts/Northrend/nexus/oculus/boss_eregos.cpp | 129 + .../scripts/Northrend/nexus/oculus/boss_urom.cpp | 356 +++ .../scripts/Northrend/nexus/oculus/boss_varos.cpp | 105 + .../Northrend/nexus/oculus/instance_oculus.cpp | 205 ++ .../scripts/Northrend/nexus/oculus/oculus.cpp | 174 ++ src/server/scripts/Northrend/nexus/oculus/oculus.h | 34 + .../Northrend/obsidian_sanctum/boss_sartharion.cpp | 1421 +++++++++++ .../obsidian_sanctum/instance_obsidian_sanctum.cpp | 97 + .../Northrend/obsidian_sanctum/obsidian_sanctum.h | 20 + src/server/scripts/Northrend/sholazar_basin.cpp | 449 ++++ src/server/scripts/Northrend/storm_peaks.cpp | 491 ++++ .../ulduar/halls_of_lightning/boss_bjarngrim.cpp | 432 ++++ .../ulduar/halls_of_lightning/boss_ionar.cpp | 388 +++ .../ulduar/halls_of_lightning/boss_loken.cpp | 222 ++ .../ulduar/halls_of_lightning/boss_volkhan.cpp | 478 ++++ .../ulduar/halls_of_lightning/halls_of_lightning.h | 34 + .../instance_halls_of_lightning.cpp | 248 ++ .../ulduar/halls_of_stone/boss_krystallus.cpp | 148 ++ .../ulduar/halls_of_stone/boss_maiden_of_grief.cpp | 166 ++ .../ulduar/halls_of_stone/boss_sjonnir.cpp | 300 +++ .../ulduar/halls_of_stone/halls_of_stone.cpp | 724 ++++++ .../ulduar/halls_of_stone/halls_of_stone.h | 48 + .../halls_of_stone/instance_halls_of_stone.cpp | 254 ++ .../Northrend/ulduar/ulduar/boss_algalon.cpp | 384 +++ .../ulduar/ulduar/boss_assembly_of_iron.cpp | 589 +++++ .../Northrend/ulduar/ulduar/boss_auriaya.cpp | 106 + .../ulduar/ulduar/boss_flame_leviathan.cpp | 574 +++++ .../scripts/Northrend/ulduar/ulduar/boss_freya.cpp | 125 + .../Northrend/ulduar/ulduar/boss_general_vezax.cpp | 31 + .../scripts/Northrend/ulduar/ulduar/boss_hodir.cpp | 89 + .../scripts/Northrend/ulduar/ulduar/boss_ignis.cpp | 137 ++ .../Northrend/ulduar/ulduar/boss_kologarn.cpp | 166 ++ .../Northrend/ulduar/ulduar/boss_mimiron.cpp | 44 + .../Northrend/ulduar/ulduar/boss_razorscale.cpp | 331 +++ .../Northrend/ulduar/ulduar/boss_thorim.cpp | 103 + .../scripts/Northrend/ulduar/ulduar/boss_xt002.cpp | 850 +++++++ .../Northrend/ulduar/ulduar/boss_yoggsaron.cpp | 55 + .../Northrend/ulduar/ulduar/instance_ulduar.cpp | 408 +++ .../scripts/Northrend/ulduar/ulduar/ulduar.h | 71 + .../Northrend/ulduar/ulduar/ulduar_teleporter.cpp | 92 + .../utgarde_keep/boss_ingvar_the_plunderer.cpp | 442 ++++ .../utgarde_keep/utgarde_keep/boss_keleseth.cpp | 361 +++ .../utgarde_keep/boss_skarvald_dalronn.cpp | 389 +++ .../utgarde_keep/instance_utgarde_keep.cpp | 312 +++ .../utgarde_keep/utgarde_keep/utgarde_keep.cpp | 160 ++ .../utgarde_keep/utgarde_keep/utgarde_keep.h | 35 + .../utgarde_pinnacle/boss_palehoof.cpp | 830 +++++++ .../utgarde_keep/utgarde_pinnacle/boss_skadi.cpp | 477 ++++ .../utgarde_keep/utgarde_pinnacle/boss_svala.cpp | 408 +++ .../utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp | 367 +++ .../utgarde_pinnacle/instance_pinnacle.cpp | 241 ++ .../utgarde_pinnacle/utgarde_pinnacle.h | 42 + .../Northrend/vault_of_archavon/boss_archavon.cpp | 218 ++ .../Northrend/vault_of_archavon/boss_emalon.cpp | 270 ++ .../Northrend/vault_of_archavon/boss_koralon.cpp | 222 ++ .../Northrend/vault_of_archavon/boss_toravon.cpp | 301 +++ .../instance_vault_of_archavon.cpp | 143 ++ .../vault_of_archavon/vault_of_archavon.h | 28 + .../Northrend/violet_hold/boss_cyanigosa.cpp | 156 ++ .../scripts/Northrend/violet_hold/boss_erekem.cpp | 329 +++ .../scripts/Northrend/violet_hold/boss_ichoron.cpp | 394 +++ .../Northrend/violet_hold/boss_lavanthor.cpp | 155 ++ .../scripts/Northrend/violet_hold/boss_moragg.cpp | 133 + .../scripts/Northrend/violet_hold/boss_xevozz.cpp | 307 +++ .../scripts/Northrend/violet_hold/boss_zuramat.cpp | 178 ++ .../Northrend/violet_hold/instance_violet_hold.cpp | 528 ++++ .../scripts/Northrend/violet_hold/violet_hold.cpp | 274 +++ .../scripts/Northrend/violet_hold/violet_hold.h | 71 + src/server/scripts/Northrend/zuldrak.cpp | 1403 +++++++++++ .../auchenai_crypts/boss_exarch_maladaar.cpp | 348 +++ .../boss_shirrak_the_dead_watcher.cpp | 211 ++ .../mana_tombs/boss_nexusprince_shaffar.cpp | 358 +++ .../auchindoun/mana_tombs/boss_pandemonius.cpp | 126 + .../sethekk_halls/boss_darkweaver_syth.cpp | 414 ++++ .../sethekk_halls/boss_tailonking_ikiss.cpp | 213 ++ .../sethekk_halls/instance_sethekk_halls.cpp | 91 + .../auchindoun/sethekk_halls/sethekk_halls.h | 14 + .../shadow_labyrinth/boss_ambassador_hellmaw.cpp | 206 ++ .../boss_blackheart_the_inciter.cpp | 169 ++ .../shadow_labyrinth/boss_grandmaster_vorpil.cpp | 313 +++ .../auchindoun/shadow_labyrinth/boss_murmur.cpp | 205 ++ .../shadow_labyrinth/instance_shadow_labyrinth.cpp | 227 ++ .../auchindoun/shadow_labyrinth/shadow_labyrinth.h | 15 + .../scripts/Outland/black_temple/black_temple.cpp | 69 + .../scripts/Outland/black_temple/black_temple.h | 39 + .../Outland/black_temple/boss_bloodboil.cpp | 332 +++ .../scripts/Outland/black_temple/boss_illidan.cpp | 2248 +++++++++++++++++ .../Outland/black_temple/boss_mother_shahraz.cpp | 302 +++ .../black_temple/boss_reliquary_of_souls.cpp | 690 ++++++ .../Outland/black_temple/boss_shade_of_akama.cpp | 871 +++++++ .../scripts/Outland/black_temple/boss_supremus.cpp | 296 +++ .../Outland/black_temple/boss_teron_gorefiend.cpp | 508 ++++ .../Outland/black_temple/boss_warlord_najentus.cpp | 226 ++ .../Outland/black_temple/illidari_council.cpp | 874 +++++++ .../Outland/black_temple/instance_black_temple.cpp | 346 +++ .../scripts/Outland/blades_edge_mountains.cpp | 525 ++++ .../scripts/Outland/boss_doomlord_kazzak.cpp | 174 ++ src/server/scripts/Outland/boss_doomwalker.cpp | 178 ++ .../serpent_shrine/boss_fathomlord_karathress.cpp | 746 ++++++ .../serpent_shrine/boss_hydross_the_unstable.cpp | 379 +++ .../serpent_shrine/boss_lady_vashj.cpp | 1039 ++++++++ .../serpent_shrine/boss_leotheras_the_blind.cpp | 787 ++++++ .../serpent_shrine/boss_lurker_below.cpp | 458 ++++ .../serpent_shrine/boss_morogrim_tidewalker.cpp | 369 +++ .../serpent_shrine/instance_serpent_shrine.cpp | 398 +++ .../serpent_shrine/serpent_shrine.h | 45 + .../steam_vault/boss_hydromancer_thespia.cpp | 187 ++ .../steam_vault/boss_mekgineer_steamrigger.cpp | 264 ++ .../steam_vault/boss_warlord_kalithresh.cpp | 204 ++ .../steam_vault/instance_steam_vault.cpp | 231 ++ .../coilfang_resevoir/steam_vault/steam_vault.h | 17 + .../coilfang_resevoir/underbog/boss_hungarfen.cpp | 154 ++ .../underbog/boss_the_black_stalker.cpp | 185 ++ .../scripts/Outland/gruuls_lair/boss_gruul.cpp | 255 ++ .../Outland/gruuls_lair/boss_high_king_maulgar.cpp | 783 ++++++ .../scripts/Outland/gruuls_lair/gruuls_lair.h | 21 + .../Outland/gruuls_lair/instance_gruuls_lair.cpp | 193 ++ .../hellfire_citadel/blood_furnace/blood_furnace.h | 29 + .../blood_furnace/boss_broggok.cpp | 131 + .../blood_furnace/boss_kelidan_the_breaker.cpp | 356 +++ .../blood_furnace/boss_the_maker.cpp | 152 ++ .../blood_furnace/instance_blood_furnace.cpp | 232 ++ .../hellfire_ramparts/boss_omor_the_unscarred.cpp | 206 ++ .../hellfire_ramparts/boss_vazruden_the_herald.cpp | 467 ++++ .../boss_watchkeeper_gargolmar.cpp | 156 ++ .../hellfire_ramparts/hellfire_ramparts.h | 16 + .../instance_hellfire_ramparts.cpp | 84 + .../magtheridons_lair/boss_magtheridon.cpp | 570 +++++ .../instance_magtheridons_lair.cpp | 254 ++ .../magtheridons_lair/magtheridons_lair.h | 14 + .../shattered_halls/boss_nethekurse.cpp | 396 +++ .../shattered_halls/boss_warbringer_omrogg.cpp | 404 +++ .../boss_warchief_kargath_bladefist.cpp | 288 +++ .../shattered_halls/instance_shattered_halls.cpp | 114 + .../shattered_halls/shattered_halls.h | 14 + src/server/scripts/Outland/hellfire_peninsula.cpp | 522 ++++ src/server/scripts/Outland/nagrand.cpp | 886 +++++++ src/server/scripts/Outland/netherstorm.cpp | 925 +++++++ src/server/scripts/Outland/shadowmoon_valley.cpp | 1828 ++++++++++++++ src/server/scripts/Outland/shattrath_city.cpp | 673 +++++ .../Outland/tempest_keep/arcatraz/arcatraz.cpp | 520 ++++ .../Outland/tempest_keep/arcatraz/arcatraz.h | 21 + .../arcatraz/boss_harbinger_skyriss.cpp | 293 +++ .../tempest_keep/arcatraz/instance_arcatraz.cpp | 240 ++ .../botanica/boss_high_botanist_freywinn.cpp | 191 ++ .../Outland/tempest_keep/botanica/boss_laj.cpp | 205 ++ .../tempest_keep/botanica/boss_warp_splinter.cpp | 216 ++ .../Outland/tempest_keep/the_eye/boss_alar.cpp | 523 ++++ .../tempest_keep/the_eye/boss_astromancer.cpp | 466 ++++ .../Outland/tempest_keep/the_eye/boss_kaelthas.cpp | 1498 +++++++++++ .../tempest_keep/the_eye/boss_void_reaver.cpp | 179 ++ .../tempest_keep/the_eye/instance_the_eye.cpp | 176 ++ .../Outland/tempest_keep/the_eye/the_eye.cpp | 98 + .../scripts/Outland/tempest_keep/the_eye/the_eye.h | 20 + .../the_mechanar/boss_gatewatcher_gyrokill.cpp | 39 + .../the_mechanar/boss_gatewatcher_ironhand.cpp | 130 + .../the_mechanar/boss_nethermancer_sepethrea.cpp | 245 ++ .../the_mechanar/boss_pathaleon_the_calculator.cpp | 246 ++ .../the_mechanar/instance_mechanar.cpp | 86 + .../Outland/tempest_keep/the_mechanar/mechanar.h | 6 + src/server/scripts/Outland/terokkar_forest.cpp | 680 +++++ src/server/scripts/Outland/zangarmarsh.cpp | 424 ++++ src/server/scripts/World/areatrigger_scripts.cpp | 285 +++ src/server/scripts/World/boss_emeriss.cpp | 144 ++ src/server/scripts/World/boss_lethon.cpp | 25 + src/server/scripts/World/boss_taerar.cpp | 263 ++ src/server/scripts/World/boss_ysondre.cpp | 203 ++ src/server/scripts/World/go_scripts.cpp | 1182 +++++++++ src/server/scripts/World/guards.cpp | 227 ++ src/server/scripts/World/item_scripts.cpp | 479 ++++ src/server/scripts/World/mob_generic_creature.cpp | 228 ++ src/server/scripts/World/npc_innkeeper.cpp | 131 + src/server/scripts/World/npc_professions.cpp | 1342 ++++++++++ src/server/scripts/World/npc_taxi.cpp | 326 +++ src/server/scripts/World/npcs_special.cpp | 2600 ++++++++++++++++++++ src/server/scripts/custom/custom_example.cpp | 278 --- .../scripts/custom/custom_gossip_codebox.cpp | 89 - src/server/scripts/custom/npc_acherus_taxi.cpp | 35 - .../scripts/custom/npc_wyrmresttempel_taxi.cpp | 112 - src/server/scripts/custom/on_events.cpp | 108 - src/server/scripts/custom/test.cpp | 218 -- .../scripts/eastern_kingdoms/alterac_mountains.cpp | 32 - .../alterac_valley/alterac_valley.cpp | 180 -- .../alterac_valley/boss_balinda.cpp | 203 -- .../alterac_valley/boss_drekthar.cpp | 138 -- .../alterac_valley/boss_galvangar.cpp | 129 - .../alterac_valley/boss_vanndar.cpp | 129 - .../scripts/eastern_kingdoms/arathi_highlands.cpp | 132 - .../blackrock_depths/blackrock_depths.cpp | 1338 ---------- .../blackrock_depths/blackrock_depths.h | 45 - .../blackrock_depths/boss_ambassador_flamelash.cpp | 91 - .../blackrock_depths/boss_anubshiah.cpp | 116 - .../boss_emperor_dagran_thaurissan.cpp | 111 - .../blackrock_depths/boss_general_angerforge.cpp | 132 - .../blackrock_depths/boss_gorosh_the_dervish.cpp | 84 - .../blackrock_depths/boss_grizzle.cpp | 94 - .../boss_high_interrogator_gerstahn.cpp | 106 - .../blackrock_depths/boss_magmus.cpp | 98 - .../blackrock_depths/boss_moira_bronzebeard.cpp | 98 - .../blackrock_depths/boss_tomb_of_seven.cpp | 254 -- .../blackrock_depths/instance_blackrock_depths.cpp | 460 ---- .../blackrock_spire/blackrock_spire.cpp | 77 - .../blackrock_spire/blackrock_spire.h | 26 - .../blackrock_spire/boss_drakkisath.cpp | 102 - .../eastern_kingdoms/blackrock_spire/boss_gyth.cpp | 205 -- .../blackrock_spire/boss_halycon.cpp | 96 - .../blackrock_spire/boss_highlord_omokk.cpp | 132 - .../blackrock_spire/boss_mother_smolderweb.cpp | 87 - .../blackrock_spire/boss_overlord_wyrmthalak.cpp | 126 - .../blackrock_spire/boss_pyroguard_emberseer.cpp | 93 - .../blackrock_spire/boss_quartermaster_zigris.cpp | 86 - .../blackrock_spire/boss_rend_blackhand.cpp | 92 - .../boss_shadow_hunter_voshgajin.cpp | 93 - .../blackrock_spire/boss_the_beast.cpp | 93 - .../blackrock_spire/boss_warmaster_voone.cpp | 122 - .../blackrock_spire/instance_blackrock_spire.cpp | 104 - .../blackwing_lair/boss_broodlord_lashlayer.cpp | 112 - .../blackwing_lair/boss_chromaggus.cpp | 301 --- .../blackwing_lair/boss_ebonroc.cpp | 104 - .../blackwing_lair/boss_firemaw.cpp | 95 - .../blackwing_lair/boss_flamegor.cpp | 98 - .../blackwing_lair/boss_nefarian.cpp | 231 -- .../blackwing_lair/boss_razorgore.cpp | 125 - .../blackwing_lair/boss_vaelastrasz.cpp | 262 -- .../blackwing_lair/boss_victor_nefarius.cpp | 385 --- .../blackwing_lair/instance_blackwing_lair.cpp | 25 - .../scripts/eastern_kingdoms/blasted_lands.cpp | 161 -- src/server/scripts/eastern_kingdoms/boss_kruul.cpp | 154 -- .../scripts/eastern_kingdoms/burning_steppes.cpp | 153 -- .../eastern_kingdoms/deadmines/boss_mr_smite.cpp | 182 -- .../eastern_kingdoms/deadmines/deadmines.cpp | 60 - .../scripts/eastern_kingdoms/deadmines/deadmines.h | 35 - .../deadmines/instance_deadmines.cpp | 256 -- src/server/scripts/eastern_kingdoms/dun_morogh.cpp | 102 - src/server/scripts/eastern_kingdoms/duskwood.cpp | 126 - .../eastern_kingdoms/eastern_plaguelands.cpp | 185 -- .../scripts/eastern_kingdoms/elwynn_forest.cpp | 101 - .../scripts/eastern_kingdoms/eversong_woods.cpp | 711 ------ src/server/scripts/eastern_kingdoms/ghostlands.cpp | 250 -- .../eastern_kingdoms/gnomeregan/gnomeregan.cpp | 593 ----- .../eastern_kingdoms/gnomeregan/gnomeregan.h | 48 - .../gnomeregan/instance_gnomeregan.cpp | 141 -- .../scripts/eastern_kingdoms/hinterlands.cpp | 350 --- src/server/scripts/eastern_kingdoms/ironforge.cpp | 93 - .../scripts/eastern_kingdoms/isle_of_queldanas.cpp | 151 -- .../eastern_kingdoms/karazhan/boss_curator.cpp | 196 -- .../karazhan/boss_maiden_of_virtue.cpp | 138 -- .../eastern_kingdoms/karazhan/boss_midnight.cpp | 310 --- .../eastern_kingdoms/karazhan/boss_moroes.cpp | 785 ------ .../eastern_kingdoms/karazhan/boss_netherspite.cpp | 343 --- .../eastern_kingdoms/karazhan/boss_nightbane.cpp | 418 ---- .../karazhan/boss_prince_malchezaar.cpp | 604 ----- .../karazhan/boss_shade_of_aran.cpp | 569 ----- .../karazhan/boss_terestian_illhoof.cpp | 417 ---- .../eastern_kingdoms/karazhan/bosses_opera.cpp | 1494 ----------- .../karazhan/instance_karazhan.cpp | 308 --- .../scripts/eastern_kingdoms/karazhan/karazhan.cpp | 646 ----- .../scripts/eastern_kingdoms/karazhan/karazhan.h | 53 - src/server/scripts/eastern_kingdoms/loch_modan.cpp | 100 - .../magisters_terrace/boss_felblood_kaelthas.cpp | 680 ----- .../magisters_terrace/boss_priestess_delrissa.cpp | 1321 ---------- .../magisters_terrace/boss_selin_fireheart.cpp | 366 --- .../magisters_terrace/boss_vexallus.cpp | 226 -- .../instance_magisters_terrace.cpp | 205 -- .../magisters_terrace/magisters_terrace.cpp | 174 -- .../magisters_terrace/magisters_terrace.h | 31 - .../molten_core/boss_baron_geddon.cpp | 107 - .../eastern_kingdoms/molten_core/boss_garr.cpp | 143 -- .../eastern_kingdoms/molten_core/boss_gehennas.cpp | 93 - .../eastern_kingdoms/molten_core/boss_golemagg.cpp | 198 -- .../eastern_kingdoms/molten_core/boss_lucifron.cpp | 91 - .../eastern_kingdoms/molten_core/boss_magmadar.cpp | 100 - .../molten_core/boss_majordomo_executus.cpp | 134 - .../eastern_kingdoms/molten_core/boss_ragnaros.cpp | 297 --- .../eastern_kingdoms/molten_core/boss_shazzrah.cpp | 121 - .../molten_core/boss_sulfuron_harbinger.cpp | 205 -- .../molten_core/instance_molten_core.cpp | 266 -- .../eastern_kingdoms/molten_core/molten_core.cpp | 81 - .../eastern_kingdoms/molten_core/molten_core.h | 22 - .../eastern_kingdoms/redridge_mountains.cpp | 172 -- .../eastern_kingdoms/scarlet_enclave/chapter1.cpp | 1079 -------- .../eastern_kingdoms/scarlet_enclave/chapter2.cpp | 995 -------- .../eastern_kingdoms/scarlet_enclave/chapter5.cpp | 1684 ------------- .../scarlet_enclave/the_scarlet_enclave.cpp | 119 - .../scarlet_monastery/boss_arcanist_doan.cpp | 128 - .../boss_azshir_the_sleepless.cpp | 98 - .../scarlet_monastery/boss_bloodmage_thalnos.cpp | 124 - .../scarlet_monastery/boss_headless_horseman.cpp | 892 ------- .../scarlet_monastery/boss_herod.cpp | 158 -- .../boss_high_inquisitor_fairbanks.cpp | 133 - .../scarlet_monastery/boss_houndmaster_loksey.cpp | 77 - .../scarlet_monastery/boss_interrogator_vishas.cpp | 118 - .../boss_mograine_and_whitemane.cpp | 359 --- .../scarlet_monastery/boss_scorn.cpp | 101 - .../instance_scarlet_monastery.cpp | 157 -- .../scarlet_monastery/scarlet_monastery.h | 18 - .../scholomance/boss_darkmaster_gandling.cpp | 225 -- .../scholomance/boss_death_knight_darkreaver.cpp | 58 - .../scholomance/boss_doctor_theolen_krastinov.cpp | 117 - .../scholomance/boss_illucia_barov.cpp | 117 - .../scholomance/boss_instructor_malicia.cpp | 153 -- .../scholomance/boss_jandice_barov.cpp | 201 -- .../eastern_kingdoms/scholomance/boss_kormok.cpp | 120 - .../scholomance/boss_lord_alexei_barov.cpp | 99 - .../scholomance/boss_lorekeeper_polkelt.cpp | 114 - .../scholomance/boss_ras_frostwhisper.cpp | 123 - .../scholomance/boss_the_ravenian.cpp | 117 - .../eastern_kingdoms/scholomance/boss_vectus.cpp | 105 - .../scholomance/instance_scholomance.cpp | 146 -- .../eastern_kingdoms/scholomance/scholomance.h | 17 - .../scripts/eastern_kingdoms/searing_gorge.cpp | 169 -- .../shadowfang_keep/instance_shadowfang_keep.cpp | 277 --- .../shadowfang_keep/shadowfang_keep.cpp | 198 -- .../shadowfang_keep/shadowfang_keep.h | 17 - .../scripts/eastern_kingdoms/silvermoon_city.cpp | 102 - .../scripts/eastern_kingdoms/silverpine_forest.cpp | 385 --- .../scripts/eastern_kingdoms/stormwind_city.cpp | 696 ------ .../eastern_kingdoms/stranglethorn_vale.cpp | 122 - .../stratholme/boss_baron_rivendare.cpp | 190 -- .../stratholme/boss_baroness_anastari.cpp | 127 - .../stratholme/boss_cannon_master_willey.cpp | 220 -- .../stratholme/boss_dathrohan_balnazzar.cpp | 217 -- .../stratholme/boss_magistrate_barthilas.cpp | 128 - .../stratholme/boss_maleki_the_pallid.cpp | 108 - .../stratholme/boss_nerubenkan.cpp | 121 - .../stratholme/boss_order_of_silver_hand.cpp | 157 -- .../stratholme/boss_postmaster_malown.cpp | 144 -- .../stratholme/boss_ramstein_the_gorger.cpp | 102 - .../stratholme/boss_timmy_the_cruel.cpp | 83 - .../stratholme/instance_stratholme.cpp | 458 ---- .../eastern_kingdoms/stratholme/stratholme.cpp | 282 --- .../eastern_kingdoms/stratholme/stratholme.h | 28 - .../sunken_temple/instance_sunken_temple.cpp | 204 -- .../sunken_temple/sunken_temple.cpp | 71 - .../eastern_kingdoms/sunken_temple/sunken_temple.h | 22 - .../sunwell_plateau/boss_brutallus.cpp | 349 --- .../sunwell_plateau/boss_eredar_twins.cpp | 762 ------ .../sunwell_plateau/boss_felmyst.cpp | 579 ----- .../sunwell_plateau/boss_kalecgos.cpp | 794 ------ .../sunwell_plateau/boss_kiljaeden.cpp | 1408 ----------- .../eastern_kingdoms/sunwell_plateau/boss_muru.cpp | 640 ----- .../sunwell_plateau/instance_sunwell_plateau.cpp | 297 --- .../sunwell_plateau/sunwell_plateau.cpp | 65 - .../sunwell_plateau/sunwell_plateau.h | 95 - .../scripts/eastern_kingdoms/tirisfal_glades.cpp | 208 -- .../eastern_kingdoms/uldaman/boss_archaedas.cpp | 497 ---- .../eastern_kingdoms/uldaman/boss_ironaya.cpp | 106 - .../eastern_kingdoms/uldaman/instance_uldaman.cpp | 300 --- .../scripts/eastern_kingdoms/uldaman/uldaman.cpp | 205 -- src/server/scripts/eastern_kingdoms/undercity.cpp | 252 -- .../eastern_kingdoms/western_plaguelands.cpp | 396 --- src/server/scripts/eastern_kingdoms/westfall.cpp | 263 -- src/server/scripts/eastern_kingdoms/wetlands.cpp | 168 -- .../eastern_kingdoms/zulaman/boss_akilzon.cpp | 467 ---- .../eastern_kingdoms/zulaman/boss_halazzi.cpp | 401 --- .../eastern_kingdoms/zulaman/boss_hexlord.cpp | 907 ------- .../eastern_kingdoms/zulaman/boss_janalai.cpp | 687 ------ .../eastern_kingdoms/zulaman/boss_nalorakk.cpp | 451 ---- .../eastern_kingdoms/zulaman/boss_zuljin.cpp | 623 ----- .../eastern_kingdoms/zulaman/instance_zulaman.cpp | 320 --- .../scripts/eastern_kingdoms/zulaman/zulaman.cpp | 192 -- .../scripts/eastern_kingdoms/zulaman/zulaman.h | 19 - .../eastern_kingdoms/zulgurub/boss_arlokk.cpp | 278 --- .../eastern_kingdoms/zulgurub/boss_gahzranka.cpp | 93 - .../eastern_kingdoms/zulgurub/boss_grilek.cpp | 93 - .../eastern_kingdoms/zulgurub/boss_hakkar.cpp | 250 -- .../eastern_kingdoms/zulgurub/boss_hazzarah.cpp | 104 - .../eastern_kingdoms/zulgurub/boss_jeklik.cpp | 291 --- .../eastern_kingdoms/zulgurub/boss_jindo.cpp | 263 -- .../eastern_kingdoms/zulgurub/boss_mandokir.cpp | 333 --- .../eastern_kingdoms/zulgurub/boss_marli.cpp | 261 -- .../eastern_kingdoms/zulgurub/boss_renataki.cpp | 152 -- .../eastern_kingdoms/zulgurub/boss_thekal.cpp | 556 ----- .../eastern_kingdoms/zulgurub/boss_venoxis.cpp | 199 -- .../eastern_kingdoms/zulgurub/boss_wushoolay.cpp | 85 - .../zulgurub/instance_zulgurub.cpp | 159 -- .../scripts/eastern_kingdoms/zulgurub/zulgurub.h | 28 - src/server/scripts/examples/example_creature.cpp | 292 --- src/server/scripts/examples/example_escort.cpp | 229 -- .../scripts/examples/example_gossip_codebox.cpp | 99 - src/server/scripts/examples/example_misc.cpp | 69 - src/server/scripts/kalimdor/ashenvale.cpp | 465 ---- src/server/scripts/kalimdor/azshara.cpp | 514 ---- src/server/scripts/kalimdor/azuremyst_isle.cpp | 718 ------ .../blackfathom_depths/blackfathom_deeps.cpp | 252 -- .../blackfathom_depths/blackfathom_deeps.h | 53 - .../kalimdor/blackfathom_depths/boss_aku_mai.cpp | 94 - .../kalimdor/blackfathom_depths/boss_gelihast.cpp | 85 - .../kalimdor/blackfathom_depths/boss_kelris.cpp | 108 - .../instance_blackfathom_deeps.cpp | 259 -- src/server/scripts/kalimdor/bloodmyst_isle.cpp | 149 -- src/server/scripts/kalimdor/boss_azuregos.cpp | 155 -- .../culling_of_stratholme/boss_epoch.cpp | 156 -- .../culling_of_stratholme/boss_infinite.cpp | 88 - .../culling_of_stratholme/boss_mal_ganis.cpp | 262 -- .../culling_of_stratholme/boss_meathook.cpp | 140 -- .../culling_of_stratholme/boss_salramm.cpp | 170 -- .../culling_of_stratholme.cpp | 1210 --------- .../culling_of_stratholme/culling_of_stratholme.h | 68 - .../instance_culling_of_stratholme.cpp | 244 -- .../caverns_of_time/dark_portal/boss_aeonus.cpp | 145 -- .../dark_portal/boss_chrono_lord_deja.cpp | 154 -- .../caverns_of_time/dark_portal/boss_temporus.cpp | 152 -- .../caverns_of_time/dark_portal/dark_portal.cpp | 404 --- .../caverns_of_time/dark_portal/dark_portal.h | 35 - .../dark_portal/instance_dark_portal.cpp | 346 --- .../caverns_of_time/hyjal/boss_anetheron.cpp | 309 --- .../caverns_of_time/hyjal/boss_archimonde.cpp | 635 ----- .../caverns_of_time/hyjal/boss_azgalor.cpp | 285 --- .../caverns_of_time/hyjal/boss_kazrogal.cpp | 197 -- .../hyjal/boss_rage_winterchill.cpp | 192 -- .../kalimdor/caverns_of_time/hyjal/hyjal.cpp | 247 -- .../scripts/kalimdor/caverns_of_time/hyjal/hyjal.h | 38 - .../kalimdor/caverns_of_time/hyjal/hyjalAI.cpp | 1157 --------- .../kalimdor/caverns_of_time/hyjal/hyjalAI.h | 248 -- .../kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp | 1440 ----------- .../kalimdor/caverns_of_time/hyjal/hyjal_trash.h | 35 - .../caverns_of_time/hyjal/instance_hyjal.cpp | 324 --- .../old_hillsbrad/boss_captain_skarloc.cpp | 152 -- .../old_hillsbrad/boss_epoch_hunter.cpp | 138 -- .../old_hillsbrad/boss_leutenant_drake.cpp | 190 -- .../old_hillsbrad/instance_old_hillsbrad.cpp | 238 -- .../old_hillsbrad/old_hillsbrad.cpp | 658 ----- .../caverns_of_time/old_hillsbrad/old_hillsbrad.h | 19 - src/server/scripts/kalimdor/darkshore.cpp | 398 --- src/server/scripts/kalimdor/desolace.cpp | 259 -- src/server/scripts/kalimdor/durotar.cpp | 103 - src/server/scripts/kalimdor/dustwallow_marsh.cpp | 425 ---- src/server/scripts/kalimdor/felwood.cpp | 90 - src/server/scripts/kalimdor/feralas.cpp | 206 -- .../kalimdor/maraudon/boss_celebras_the_cursed.cpp | 98 - .../scripts/kalimdor/maraudon/boss_landslide.cpp | 95 - .../scripts/kalimdor/maraudon/boss_noxxion.cpp | 131 - .../kalimdor/maraudon/boss_princess_theradras.cpp | 109 - src/server/scripts/kalimdor/moonglade.cpp | 571 ----- src/server/scripts/kalimdor/mulgore.cpp | 316 --- .../scripts/kalimdor/onyxias_lair/boss_onyxia.cpp | 500 ---- .../onyxias_lair/instance_onyxias_lair.cpp | 249 -- .../scripts/kalimdor/onyxias_lair/onyxias_lair.h | 65 - src/server/scripts/kalimdor/orgrimmar.cpp | 286 --- .../boss_amnennar_the_coldbringer.cpp | 130 - .../razorfen_downs/instance_razorfen_downs.cpp | 215 -- .../kalimdor/razorfen_downs/razorfen_downs.cpp | 165 -- .../kalimdor/razorfen_downs/razorfen_downs.h | 45 - .../razorfen_kraul/instance_razorfen_kraul.cpp | 104 - .../kalimdor/razorfen_kraul/razorfen_kraul.cpp | 194 -- .../kalimdor/razorfen_kraul/razorfen_kraul.h | 21 - .../kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp | 125 - .../kalimdor/ruins_of_ahnqiraj/boss_buru.cpp | 72 - .../kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp | 143 -- .../kalimdor/ruins_of_ahnqiraj/boss_moam.cpp | 162 -- .../kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp | 79 - .../kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp | 85 - .../instance_ruins_of_ahnqiraj.cpp | 213 -- .../kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h | 34 - src/server/scripts/kalimdor/silithus.cpp | 1140 --------- .../scripts/kalimdor/stonetalon_mountains.cpp | 172 -- src/server/scripts/kalimdor/tanaris.cpp | 635 ----- src/server/scripts/kalimdor/teldrassil.cpp | 114 - .../kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp | 346 --- .../kalimdor/temple_of_ahnqiraj/boss_cthun.cpp | 1307 ---------- .../kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp | 206 -- .../kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp | 148 -- .../kalimdor/temple_of_ahnqiraj/boss_ouro.cpp | 140 -- .../kalimdor/temple_of_ahnqiraj/boss_sartura.cpp | 297 --- .../kalimdor/temple_of_ahnqiraj/boss_skeram.cpp | 298 --- .../temple_of_ahnqiraj/boss_twinemperors.cpp | 596 ----- .../kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp | 30 - .../instance_temple_of_ahnqiraj.cpp | 166 -- .../temple_of_ahnqiraj/mob_anubisath_sentinel.cpp | 296 --- .../temple_of_ahnqiraj/temple_of_ahnqiraj.h | 23 - src/server/scripts/kalimdor/the_barrens.cpp | 701 ------ src/server/scripts/kalimdor/thousand_needles.cpp | 454 ---- src/server/scripts/kalimdor/thunder_bluff.cpp | 138 -- src/server/scripts/kalimdor/ungoro_crater.cpp | 356 --- .../wailing_caverns/instance_wailing_caverns.cpp | 142 -- .../kalimdor/wailing_caverns/wailing_caverns.cpp | 396 --- .../kalimdor/wailing_caverns/wailing_caverns.h | 24 - src/server/scripts/kalimdor/winterspring.cpp | 168 -- .../kalimdor/zulfarrak/instance_zulfarrak.cpp | 58 - .../scripts/kalimdor/zulfarrak/zulfarrak.cpp | 280 --- .../northrend/azjol_nerub/ahnkahet/ahnkahet.h | 52 - .../azjol_nerub/ahnkahet/boss_amanitar.cpp | 226 -- .../azjol_nerub/ahnkahet/boss_elder_nadox.cpp | 283 --- .../azjol_nerub/ahnkahet/boss_herald_volazj.cpp | 328 --- .../ahnkahet/boss_jedoga_shadowseeker.cpp | 588 ----- .../azjol_nerub/ahnkahet/boss_prince_taldaram.cpp | 412 ---- .../azjol_nerub/ahnkahet/instance_ahnkahet.cpp | 313 --- .../azjol_nerub/azjol_nerub/azjol_nerub.h | 38 - .../azjol_nerub/azjol_nerub/boss_anubarak.cpp | 360 --- .../azjol_nerub/azjol_nerub/boss_hadronox.cpp | 206 -- .../azjol_nerub/boss_krikthir_the_gatewatcher.cpp | 553 ----- .../azjol_nerub/instance_azjol_nerub.cpp | 215 -- src/server/scripts/northrend/borean_tundra.cpp | 2323 ----------------- .../boss_argent_challenge.cpp | 512 ---- .../trial_of_the_champion/boss_black_knight.cpp | 373 --- .../trial_of_the_champion/boss_grand_champions.cpp | 993 -------- .../instance_trial_of_the_champion.cpp | 340 --- .../trial_of_the_champion.cpp | 512 ---- .../trial_of_the_champion/trial_of_the_champion.h | 115 - .../scripts/northrend/crystalsong_forest.cpp | 110 - src/server/scripts/northrend/dalaran.cpp | 159 -- src/server/scripts/northrend/dragonblight.cpp | 272 -- .../northrend/draktharon_keep/boss_dred.cpp | 270 -- .../northrend/draktharon_keep/boss_novos.cpp | 328 --- .../northrend/draktharon_keep/boss_tharon_ja.cpp | 260 -- .../northrend/draktharon_keep/boss_trollgore.cpp | 197 -- .../northrend/draktharon_keep/drak_tharon_keep.h | 40 - .../draktharon_keep/instance_drak_tharon_keep.cpp | 243 -- .../frozen_halls/forge_of_souls/boss_bronjahm.cpp | 263 -- .../forge_of_souls/boss_devourer_of_souls.cpp | 349 --- .../frozen_halls/forge_of_souls/forge_of_souls.cpp | 899 ------- .../frozen_halls/forge_of_souls/forge_of_souls.h | 52 - .../forge_of_souls/instance_forge_of_souls.cpp | 168 -- .../halls_of_reflection/boss_falric.cpp | 142 -- .../halls_of_reflection/boss_marwyn.cpp | 133 - .../halls_of_reflection/halls_of_reflection.cpp | 1022 -------- .../halls_of_reflection/halls_of_reflection.h | 156 -- .../instance_halls_of_reflection.cpp | 431 ---- .../pit_of_saron/boss_forgemaster_garfrost.cpp | 209 -- .../frozen_halls/pit_of_saron/boss_krickandick.cpp | 482 ---- .../pit_of_saron/boss_scourgelord_tyrannus.cpp | 273 -- .../pit_of_saron/instance_pit_of_saron.cpp | 236 -- .../frozen_halls/pit_of_saron/pit_of_saron.cpp | 1101 --------- .../frozen_halls/pit_of_saron/pit_of_saron.h | 63 - src/server/scripts/northrend/grizzly_hills.cpp | 625 ----- .../northrend/gundrak/boss_drakkari_colossus.cpp | 317 --- src/server/scripts/northrend/gundrak/boss_eck.cpp | 168 -- .../scripts/northrend/gundrak/boss_gal_darah.cpp | 288 --- .../scripts/northrend/gundrak/boss_moorabi.cpp | 175 -- .../scripts/northrend/gundrak/boss_slad_ran.cpp | 266 -- src/server/scripts/northrend/gundrak/gundrak.h | 54 - .../scripts/northrend/gundrak/instance_gundrak.cpp | 536 ---- src/server/scripts/northrend/howling_fjord.cpp | 338 --- src/server/scripts/northrend/icecrown.cpp | 422 ---- .../northrend/naxxramas/boss_anubrekhan.cpp | 185 -- .../scripts/northrend/naxxramas/boss_faerlina.cpp | 218 -- .../northrend/naxxramas/boss_four_horsemen.cpp | 397 --- .../scripts/northrend/naxxramas/boss_gluth.cpp | 147 -- .../scripts/northrend/naxxramas/boss_gothik.cpp | 582 ----- .../scripts/northrend/naxxramas/boss_grobbulus.cpp | 142 -- .../scripts/northrend/naxxramas/boss_heigan.cpp | 149 -- .../northrend/naxxramas/boss_highlord_mograine.cpp | 179 -- .../scripts/northrend/naxxramas/boss_kelthuzad.cpp | 706 ------ .../scripts/northrend/naxxramas/boss_loatheb.cpp | 125 - .../scripts/northrend/naxxramas/boss_maexxna.cpp | 186 -- .../scripts/northrend/naxxramas/boss_noth.cpp | 212 -- .../scripts/northrend/naxxramas/boss_patchwerk.cpp | 159 -- .../scripts/northrend/naxxramas/boss_razuvious.cpp | 139 -- .../scripts/northrend/naxxramas/boss_sapphiron.cpp | 403 --- .../scripts/northrend/naxxramas/boss_thaddius.cpp | 400 --- .../northrend/naxxramas/instance_naxxramas.cpp | 324 --- src/server/scripts/northrend/naxxramas/naxxramas.h | 75 - .../nexus/eye_of_eternity/boss_malygos.cpp | 175 -- .../nexus/eye_of_eternity/eye_of_eternity.h | 4 - .../eye_of_eternity/instance_eye_of_eternity.cpp | 21 - .../northrend/nexus/nexus/boss_anomalus.cpp | 253 -- .../northrend/nexus/nexus/boss_keristrasza.cpp | 247 -- .../northrend/nexus/nexus/boss_magus_telestra.cpp | 327 --- .../scripts/northrend/nexus/nexus/boss_ormorok.cpp | 298 --- .../northrend/nexus/nexus/commander_kolurg.cpp | 58 - .../northrend/nexus/nexus/commander_stoutbeard.cpp | 64 - .../northrend/nexus/nexus/instance_nexus.cpp | 259 -- src/server/scripts/northrend/nexus/nexus/nexus.h | 35 - .../scripts/northrend/nexus/oculus/boss_drakos.cpp | 218 -- .../scripts/northrend/nexus/oculus/boss_eregos.cpp | 129 - .../scripts/northrend/nexus/oculus/boss_urom.cpp | 356 --- .../scripts/northrend/nexus/oculus/boss_varos.cpp | 105 - .../northrend/nexus/oculus/instance_oculus.cpp | 205 -- .../scripts/northrend/nexus/oculus/oculus.cpp | 174 -- src/server/scripts/northrend/nexus/oculus/oculus.h | 34 - .../northrend/obsidian_sanctum/boss_sartharion.cpp | 1421 ----------- .../obsidian_sanctum/instance_obsidian_sanctum.cpp | 97 - .../northrend/obsidian_sanctum/obsidian_sanctum.h | 20 - src/server/scripts/northrend/sholazar_basin.cpp | 449 ---- src/server/scripts/northrend/storm_peaks.cpp | 491 ---- .../ulduar/halls_of_lightning/boss_bjarngrim.cpp | 432 ---- .../ulduar/halls_of_lightning/boss_ionar.cpp | 388 --- .../ulduar/halls_of_lightning/boss_loken.cpp | 222 -- .../ulduar/halls_of_lightning/boss_volkhan.cpp | 478 ---- .../ulduar/halls_of_lightning/halls_of_lightning.h | 34 - .../instance_halls_of_lightning.cpp | 248 -- .../ulduar/halls_of_stone/boss_krystallus.cpp | 148 -- .../ulduar/halls_of_stone/boss_maiden_of_grief.cpp | 166 -- .../ulduar/halls_of_stone/boss_sjonnir.cpp | 300 --- .../ulduar/halls_of_stone/halls_of_stone.cpp | 724 ------ .../ulduar/halls_of_stone/halls_of_stone.h | 48 - .../halls_of_stone/instance_halls_of_stone.cpp | 254 -- .../northrend/ulduar/ulduar/boss_algalon.cpp | 384 --- .../ulduar/ulduar/boss_assembly_of_iron.cpp | 589 ----- .../northrend/ulduar/ulduar/boss_auriaya.cpp | 106 - .../ulduar/ulduar/boss_flame_leviathan.cpp | 574 ----- .../scripts/northrend/ulduar/ulduar/boss_freya.cpp | 125 - .../northrend/ulduar/ulduar/boss_general_vezax.cpp | 31 - .../scripts/northrend/ulduar/ulduar/boss_hodir.cpp | 89 - .../scripts/northrend/ulduar/ulduar/boss_ignis.cpp | 137 -- .../northrend/ulduar/ulduar/boss_kologarn.cpp | 166 -- .../northrend/ulduar/ulduar/boss_mimiron.cpp | 44 - .../northrend/ulduar/ulduar/boss_razorscale.cpp | 331 --- .../northrend/ulduar/ulduar/boss_thorim.cpp | 103 - .../scripts/northrend/ulduar/ulduar/boss_xt002.cpp | 850 ------- .../northrend/ulduar/ulduar/boss_yoggsaron.cpp | 55 - .../northrend/ulduar/ulduar/instance_ulduar.cpp | 408 --- .../scripts/northrend/ulduar/ulduar/ulduar.h | 71 - .../northrend/ulduar/ulduar/ulduar_teleporter.cpp | 92 - .../utgarde_keep/boss_ingvar_the_plunderer.cpp | 442 ---- .../utgarde_keep/utgarde_keep/boss_keleseth.cpp | 361 --- .../utgarde_keep/boss_skarvald_dalronn.cpp | 389 --- .../utgarde_keep/instance_utgarde_keep.cpp | 312 --- .../utgarde_keep/utgarde_keep/utgarde_keep.cpp | 160 -- .../utgarde_keep/utgarde_keep/utgarde_keep.h | 35 - .../utgarde_pinnacle/boss_palehoof.cpp | 830 ------- .../utgarde_keep/utgarde_pinnacle/boss_skadi.cpp | 477 ---- .../utgarde_keep/utgarde_pinnacle/boss_svala.cpp | 408 --- .../utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp | 367 --- .../utgarde_pinnacle/instance_pinnacle.cpp | 241 -- .../utgarde_pinnacle/utgarde_pinnacle.h | 42 - .../northrend/vault_of_archavon/boss_archavon.cpp | 218 -- .../northrend/vault_of_archavon/boss_emalon.cpp | 270 -- .../northrend/vault_of_archavon/boss_koralon.cpp | 222 -- .../northrend/vault_of_archavon/boss_toravon.cpp | 301 --- .../instance_vault_of_archavon.cpp | 143 -- .../vault_of_archavon/vault_of_archavon.h | 28 - .../northrend/violet_hold/boss_cyanigosa.cpp | 156 -- .../scripts/northrend/violet_hold/boss_erekem.cpp | 329 --- .../scripts/northrend/violet_hold/boss_ichoron.cpp | 394 --- .../northrend/violet_hold/boss_lavanthor.cpp | 155 -- .../scripts/northrend/violet_hold/boss_moragg.cpp | 133 - .../scripts/northrend/violet_hold/boss_xevozz.cpp | 307 --- .../scripts/northrend/violet_hold/boss_zuramat.cpp | 178 -- .../northrend/violet_hold/instance_violet_hold.cpp | 528 ---- .../scripts/northrend/violet_hold/violet_hold.cpp | 274 --- .../scripts/northrend/violet_hold/violet_hold.h | 71 - src/server/scripts/northrend/zuldrak.cpp | 1403 ----------- .../auchenai_crypts/boss_exarch_maladaar.cpp | 348 --- .../boss_shirrak_the_dead_watcher.cpp | 211 -- .../mana_tombs/boss_nexusprince_shaffar.cpp | 358 --- .../auchindoun/mana_tombs/boss_pandemonius.cpp | 126 - .../sethekk_halls/boss_darkweaver_syth.cpp | 414 ---- .../sethekk_halls/boss_tailonking_ikiss.cpp | 213 -- .../sethekk_halls/instance_sethekk_halls.cpp | 91 - .../auchindoun/sethekk_halls/sethekk_halls.h | 14 - .../shadow_labyrinth/boss_ambassador_hellmaw.cpp | 206 -- .../boss_blackheart_the_inciter.cpp | 169 -- .../shadow_labyrinth/boss_grandmaster_vorpil.cpp | 313 --- .../auchindoun/shadow_labyrinth/boss_murmur.cpp | 205 -- .../shadow_labyrinth/instance_shadow_labyrinth.cpp | 227 -- .../auchindoun/shadow_labyrinth/shadow_labyrinth.h | 15 - .../scripts/outland/black_temple/black_temple.cpp | 69 - .../scripts/outland/black_temple/black_temple.h | 39 - .../outland/black_temple/boss_bloodboil.cpp | 332 --- .../scripts/outland/black_temple/boss_illidan.cpp | 2248 ----------------- .../outland/black_temple/boss_mother_shahraz.cpp | 302 --- .../black_temple/boss_reliquary_of_souls.cpp | 690 ------ .../outland/black_temple/boss_shade_of_akama.cpp | 871 ------- .../scripts/outland/black_temple/boss_supremus.cpp | 296 --- .../outland/black_temple/boss_teron_gorefiend.cpp | 508 ---- .../outland/black_temple/boss_warlord_najentus.cpp | 226 -- .../outland/black_temple/illidari_council.cpp | 874 ------- .../outland/black_temple/instance_black_temple.cpp | 346 --- .../scripts/outland/blades_edge_mountains.cpp | 525 ---- .../scripts/outland/boss_doomlord_kazzak.cpp | 174 -- src/server/scripts/outland/boss_doomwalker.cpp | 178 -- .../serpent_shrine/boss_fathomlord_karathress.cpp | 746 ------ .../serpent_shrine/boss_hydross_the_unstable.cpp | 379 --- .../serpent_shrine/boss_lady_vashj.cpp | 1039 -------- .../serpent_shrine/boss_leotheras_the_blind.cpp | 787 ------ .../serpent_shrine/boss_lurker_below.cpp | 458 ---- .../serpent_shrine/boss_morogrim_tidewalker.cpp | 369 --- .../serpent_shrine/instance_serpent_shrine.cpp | 398 --- .../serpent_shrine/serpent_shrine.h | 45 - .../steam_vault/boss_hydromancer_thespia.cpp | 187 -- .../steam_vault/boss_mekgineer_steamrigger.cpp | 264 -- .../steam_vault/boss_warlord_kalithresh.cpp | 204 -- .../steam_vault/instance_steam_vault.cpp | 231 -- .../coilfang_resevoir/steam_vault/steam_vault.h | 17 - .../coilfang_resevoir/underbog/boss_hungarfen.cpp | 154 -- .../underbog/boss_the_black_stalker.cpp | 185 -- .../scripts/outland/gruuls_lair/boss_gruul.cpp | 255 -- .../outland/gruuls_lair/boss_high_king_maulgar.cpp | 783 ------ .../scripts/outland/gruuls_lair/gruuls_lair.h | 21 - .../outland/gruuls_lair/instance_gruuls_lair.cpp | 193 -- .../hellfire_citadel/blood_furnace/blood_furnace.h | 29 - .../blood_furnace/boss_broggok.cpp | 131 - .../blood_furnace/boss_kelidan_the_breaker.cpp | 356 --- .../blood_furnace/boss_the_maker.cpp | 152 -- .../blood_furnace/instance_blood_furnace.cpp | 232 -- .../hellfire_ramparts/boss_omor_the_unscarred.cpp | 206 -- .../hellfire_ramparts/boss_vazruden_the_herald.cpp | 467 ---- .../boss_watchkeeper_gargolmar.cpp | 156 -- .../hellfire_ramparts/hellfire_ramparts.h | 16 - .../instance_hellfire_ramparts.cpp | 84 - .../magtheridons_lair/boss_magtheridon.cpp | 570 ----- .../instance_magtheridons_lair.cpp | 254 -- .../magtheridons_lair/magtheridons_lair.h | 14 - .../shattered_halls/boss_nethekurse.cpp | 396 --- .../shattered_halls/boss_warbringer_omrogg.cpp | 404 --- .../boss_warchief_kargath_bladefist.cpp | 288 --- .../shattered_halls/instance_shattered_halls.cpp | 114 - .../shattered_halls/shattered_halls.h | 14 - src/server/scripts/outland/hellfire_peninsula.cpp | 522 ---- src/server/scripts/outland/nagrand.cpp | 886 ------- src/server/scripts/outland/netherstorm.cpp | 925 ------- src/server/scripts/outland/shadowmoon_valley.cpp | 1828 -------------- src/server/scripts/outland/shattrath_city.cpp | 673 ----- .../outland/tempest_keep/arcatraz/arcatraz.cpp | 520 ---- .../outland/tempest_keep/arcatraz/arcatraz.h | 21 - .../arcatraz/boss_harbinger_skyriss.cpp | 293 --- .../tempest_keep/arcatraz/instance_arcatraz.cpp | 240 -- .../botanica/boss_high_botanist_freywinn.cpp | 191 -- .../outland/tempest_keep/botanica/boss_laj.cpp | 205 -- .../tempest_keep/botanica/boss_warp_splinter.cpp | 216 -- .../outland/tempest_keep/the_eye/boss_alar.cpp | 523 ---- .../tempest_keep/the_eye/boss_astromancer.cpp | 466 ---- .../outland/tempest_keep/the_eye/boss_kaelthas.cpp | 1498 ----------- .../tempest_keep/the_eye/boss_void_reaver.cpp | 179 -- .../tempest_keep/the_eye/instance_the_eye.cpp | 176 -- .../outland/tempest_keep/the_eye/the_eye.cpp | 98 - .../scripts/outland/tempest_keep/the_eye/the_eye.h | 20 - .../the_mechanar/boss_gatewatcher_gyrokill.cpp | 39 - .../the_mechanar/boss_gatewatcher_ironhand.cpp | 130 - .../the_mechanar/boss_nethermancer_sepethrea.cpp | 245 -- .../the_mechanar/boss_pathaleon_the_calculator.cpp | 246 -- .../the_mechanar/instance_mechanar.cpp | 86 - .../outland/tempest_keep/the_mechanar/mechanar.h | 6 - src/server/scripts/outland/terokkar_forest.cpp | 680 ----- src/server/scripts/outland/zangarmarsh.cpp | 424 ---- src/server/scripts/world/areatrigger_scripts.cpp | 285 --- src/server/scripts/world/boss_emeriss.cpp | 144 -- src/server/scripts/world/boss_lethon.cpp | 25 - src/server/scripts/world/boss_taerar.cpp | 263 -- src/server/scripts/world/boss_ysondre.cpp | 203 -- src/server/scripts/world/go_scripts.cpp | 1182 --------- src/server/scripts/world/guards.cpp | 227 -- src/server/scripts/world/item_scripts.cpp | 479 ---- src/server/scripts/world/mob_generic_creature.cpp | 228 -- src/server/scripts/world/npc_innkeeper.cpp | 131 - src/server/scripts/world/npc_professions.cpp | 1342 ---------- src/server/scripts/world/npc_taxi.cpp | 326 --- src/server/scripts/world/npcs_special.cpp | 2600 -------------------- 1130 files changed, 165145 insertions(+), 165145 deletions(-) create mode 100644 src/server/scripts/Custom/custom_example.cpp create mode 100644 src/server/scripts/Custom/custom_gossip_codebox.cpp create mode 100644 src/server/scripts/Custom/npc_acherus_taxi.cpp create mode 100644 src/server/scripts/Custom/npc_wyrmresttempel_taxi.cpp create mode 100644 src/server/scripts/Custom/on_events.cpp create mode 100644 src/server/scripts/Custom/test.cpp create mode 100644 src/server/scripts/EasternKingdoms/alterac_mountains.cpp create mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp create mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp create mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp create mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp create mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp create mode 100644 src/server/scripts/EasternKingdoms/arathi_highlands.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp create mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp create mode 100644 src/server/scripts/EasternKingdoms/blasted_lands.cpp create mode 100644 src/server/scripts/EasternKingdoms/boss_kruul.cpp create mode 100644 src/server/scripts/EasternKingdoms/burning_steppes.cpp create mode 100644 src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp create mode 100644 src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp create mode 100644 src/server/scripts/EasternKingdoms/deadmines/deadmines.h create mode 100644 src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp create mode 100644 src/server/scripts/EasternKingdoms/dun_morogh.cpp create mode 100644 src/server/scripts/EasternKingdoms/duskwood.cpp create mode 100644 src/server/scripts/EasternKingdoms/eastern_plaguelands.cpp create mode 100644 src/server/scripts/EasternKingdoms/elwynn_forest.cpp create mode 100644 src/server/scripts/EasternKingdoms/eversong_woods.cpp create mode 100644 src/server/scripts/EasternKingdoms/ghostlands.cpp create mode 100644 src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp create mode 100644 src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h create mode 100644 src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp create mode 100644 src/server/scripts/EasternKingdoms/hinterlands.cpp create mode 100644 src/server/scripts/EasternKingdoms/ironforge.cpp create mode 100644 src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp create mode 100644 src/server/scripts/EasternKingdoms/karazhan/karazhan.h create mode 100644 src/server/scripts/EasternKingdoms/loch_modan.cpp create mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp create mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp create mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp create mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp create mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp create mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp create mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp create mode 100644 src/server/scripts/EasternKingdoms/molten_core/molten_core.h create mode 100644 src/server/scripts/EasternKingdoms/redridge_mountains.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp create mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp create mode 100644 src/server/scripts/EasternKingdoms/scholomance/scholomance.h create mode 100644 src/server/scripts/EasternKingdoms/searing_gorge.cpp create mode 100644 src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp create mode 100644 src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp create mode 100644 src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h create mode 100644 src/server/scripts/EasternKingdoms/silvermoon_city.cpp create mode 100644 src/server/scripts/EasternKingdoms/silverpine_forest.cpp create mode 100644 src/server/scripts/EasternKingdoms/stormwind_city.cpp create mode 100644 src/server/scripts/EasternKingdoms/stranglethorn_vale.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp create mode 100644 src/server/scripts/EasternKingdoms/stratholme/stratholme.h create mode 100644 src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp create mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h create mode 100644 src/server/scripts/EasternKingdoms/tirisfal_glades.cpp create mode 100644 src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp create mode 100644 src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp create mode 100644 src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp create mode 100644 src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp create mode 100644 src/server/scripts/EasternKingdoms/undercity.cpp create mode 100644 src/server/scripts/EasternKingdoms/western_plaguelands.cpp create mode 100644 src/server/scripts/EasternKingdoms/westfall.cpp create mode 100644 src/server/scripts/EasternKingdoms/wetlands.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulaman/zulaman.h create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp create mode 100644 src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h create mode 100644 src/server/scripts/Examples/example_creature.cpp create mode 100644 src/server/scripts/Examples/example_escort.cpp create mode 100644 src/server/scripts/Examples/example_gossip_codebox.cpp create mode 100644 src/server/scripts/Examples/example_misc.cpp create mode 100644 src/server/scripts/Kalimdor/ashenvale.cpp create mode 100644 src/server/scripts/Kalimdor/azshara.cpp create mode 100644 src/server/scripts/Kalimdor/azuremyst_isle.cpp create mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp create mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h create mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp create mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp create mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp create mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp create mode 100644 src/server/scripts/Kalimdor/bloodmyst_isle.cpp create mode 100644 src/server/scripts/Kalimdor/boss_azuregos.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp create mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h create mode 100644 src/server/scripts/Kalimdor/darkshore.cpp create mode 100644 src/server/scripts/Kalimdor/desolace.cpp create mode 100644 src/server/scripts/Kalimdor/durotar.cpp create mode 100644 src/server/scripts/Kalimdor/dustwallow_marsh.cpp create mode 100644 src/server/scripts/Kalimdor/felwood.cpp create mode 100644 src/server/scripts/Kalimdor/feralas.cpp create mode 100644 src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp create mode 100644 src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp create mode 100644 src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp create mode 100644 src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp create mode 100644 src/server/scripts/Kalimdor/moonglade.cpp create mode 100644 src/server/scripts/Kalimdor/mulgore.cpp create mode 100644 src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp create mode 100644 src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp create mode 100644 src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h create mode 100644 src/server/scripts/Kalimdor/orgrimmar.cpp create mode 100644 src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp create mode 100644 src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp create mode 100644 src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp create mode 100644 src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h create mode 100644 src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp create mode 100644 src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp create mode 100644 src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h create mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp create mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp create mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp create mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp create mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp create mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp create mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp create mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h create mode 100644 src/server/scripts/Kalimdor/silithus.cpp create mode 100644 src/server/scripts/Kalimdor/stonetalon_mountains.cpp create mode 100644 src/server/scripts/Kalimdor/tanaris.cpp create mode 100644 src/server/scripts/Kalimdor/teldrassil.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp create mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h create mode 100644 src/server/scripts/Kalimdor/the_barrens.cpp create mode 100644 src/server/scripts/Kalimdor/thousand_needles.cpp create mode 100644 src/server/scripts/Kalimdor/thunder_bluff.cpp create mode 100644 src/server/scripts/Kalimdor/ungoro_crater.cpp create mode 100644 src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp create mode 100644 src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp create mode 100644 src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h create mode 100644 src/server/scripts/Kalimdor/winterspring.cpp create mode 100644 src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp create mode 100644 src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h create mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h create mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp create mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp create mode 100644 src/server/scripts/Northrend/borean_tundra.cpp create mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp create mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp create mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp create mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp create mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp create mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h create mode 100644 src/server/scripts/Northrend/crystalsong_forest.cpp create mode 100644 src/server/scripts/Northrend/dalaran.cpp create mode 100644 src/server/scripts/Northrend/dragonblight.cpp create mode 100644 src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp create mode 100644 src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp create mode 100644 src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp create mode 100644 src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp create mode 100644 src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h create mode 100644 src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h create mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h create mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp create mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h create mode 100644 src/server/scripts/Northrend/grizzly_hills.cpp create mode 100644 src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp create mode 100644 src/server/scripts/Northrend/gundrak/boss_eck.cpp create mode 100644 src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp create mode 100644 src/server/scripts/Northrend/gundrak/boss_moorabi.cpp create mode 100644 src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp create mode 100644 src/server/scripts/Northrend/gundrak/gundrak.h create mode 100644 src/server/scripts/Northrend/gundrak/instance_gundrak.cpp create mode 100644 src/server/scripts/Northrend/howling_fjord.cpp create mode 100644 src/server/scripts/Northrend/icecrown.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_gluth.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_gothik.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_heigan.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_noth.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp create mode 100644 src/server/scripts/Northrend/naxxramas/naxxramas.h create mode 100644 src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp create mode 100644 src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h create mode 100644 src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp create mode 100644 src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp create mode 100644 src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp create mode 100644 src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp create mode 100644 src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp create mode 100644 src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp create mode 100644 src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp create mode 100644 src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp create mode 100644 src/server/scripts/Northrend/nexus/nexus/nexus.h create mode 100644 src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp create mode 100644 src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp create mode 100644 src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp create mode 100644 src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp create mode 100644 src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp create mode 100644 src/server/scripts/Northrend/nexus/oculus/oculus.cpp create mode 100644 src/server/scripts/Northrend/nexus/oculus/oculus.h create mode 100644 src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp create mode 100644 src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp create mode 100644 src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h create mode 100644 src/server/scripts/Northrend/sholazar_basin.cpp create mode 100644 src/server/scripts/Northrend/storm_peaks.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h create mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/ulduar.h create mode 100644 src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp create mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h create mode 100644 src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp create mode 100644 src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp create mode 100644 src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp create mode 100644 src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp create mode 100644 src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp create mode 100644 src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h create mode 100644 src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/boss_erekem.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/boss_moragg.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/violet_hold.cpp create mode 100644 src/server/scripts/Northrend/violet_hold/violet_hold.h create mode 100644 src/server/scripts/Northrend/zuldrak.cpp create mode 100644 src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp create mode 100644 src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp create mode 100644 src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp create mode 100644 src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp create mode 100644 src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp create mode 100644 src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp create mode 100644 src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp create mode 100644 src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h create mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp create mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp create mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp create mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp create mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp create mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h create mode 100644 src/server/scripts/Outland/black_temple/black_temple.cpp create mode 100644 src/server/scripts/Outland/black_temple/black_temple.h create mode 100644 src/server/scripts/Outland/black_temple/boss_bloodboil.cpp create mode 100644 src/server/scripts/Outland/black_temple/boss_illidan.cpp create mode 100644 src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp create mode 100644 src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp create mode 100644 src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp create mode 100644 src/server/scripts/Outland/black_temple/boss_supremus.cpp create mode 100644 src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp create mode 100644 src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp create mode 100644 src/server/scripts/Outland/black_temple/illidari_council.cpp create mode 100644 src/server/scripts/Outland/black_temple/instance_black_temple.cpp create mode 100644 src/server/scripts/Outland/blades_edge_mountains.cpp create mode 100644 src/server/scripts/Outland/boss_doomlord_kazzak.cpp create mode 100644 src/server/scripts/Outland/boss_doomwalker.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h create mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h create mode 100644 src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp create mode 100644 src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp create mode 100644 src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp create mode 100644 src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp create mode 100644 src/server/scripts/Outland/gruuls_lair/gruuls_lair.h create mode 100644 src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h create mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h create mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h create mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp create mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h create mode 100644 src/server/scripts/Outland/hellfire_peninsula.cpp create mode 100644 src/server/scripts/Outland/nagrand.cpp create mode 100644 src/server/scripts/Outland/netherstorm.cpp create mode 100644 src/server/scripts/Outland/shadowmoon_valley.cpp create mode 100644 src/server/scripts/Outland/shattrath_city.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h create mode 100644 src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h create mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp create mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h create mode 100644 src/server/scripts/Outland/terokkar_forest.cpp create mode 100644 src/server/scripts/Outland/zangarmarsh.cpp create mode 100644 src/server/scripts/World/areatrigger_scripts.cpp create mode 100644 src/server/scripts/World/boss_emeriss.cpp create mode 100644 src/server/scripts/World/boss_lethon.cpp create mode 100644 src/server/scripts/World/boss_taerar.cpp create mode 100644 src/server/scripts/World/boss_ysondre.cpp create mode 100644 src/server/scripts/World/go_scripts.cpp create mode 100644 src/server/scripts/World/guards.cpp create mode 100644 src/server/scripts/World/item_scripts.cpp create mode 100644 src/server/scripts/World/mob_generic_creature.cpp create mode 100644 src/server/scripts/World/npc_innkeeper.cpp create mode 100644 src/server/scripts/World/npc_professions.cpp create mode 100644 src/server/scripts/World/npc_taxi.cpp create mode 100644 src/server/scripts/World/npcs_special.cpp delete mode 100644 src/server/scripts/custom/custom_example.cpp delete mode 100644 src/server/scripts/custom/custom_gossip_codebox.cpp delete mode 100644 src/server/scripts/custom/npc_acherus_taxi.cpp delete mode 100644 src/server/scripts/custom/npc_wyrmresttempel_taxi.cpp delete mode 100644 src/server/scripts/custom/on_events.cpp delete mode 100644 src/server/scripts/custom/test.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/alterac_mountains.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/alterac_valley/alterac_valley.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/alterac_valley/boss_balinda.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/alterac_valley/boss_drekthar.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/alterac_valley/boss_galvangar.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/alterac_valley/boss_vanndar.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/arathi_highlands.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_moira_bronzebeard.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/blasted_lands.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/boss_kruul.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/burning_steppes.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/deadmines/boss_mr_smite.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/deadmines/deadmines.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/deadmines/deadmines.h delete mode 100644 src/server/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/dun_morogh.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/duskwood.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/eastern_plaguelands.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/elwynn_forest.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/eversong_woods.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/ghostlands.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h delete mode 100644 src/server/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/hinterlands.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/ironforge.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/isle_of_queldanas.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_curator.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/karazhan.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/karazhan/karazhan.h delete mode 100644 src/server/scripts/eastern_kingdoms/loch_modan.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_garr.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/molten_core.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/molten_core/molten_core.h delete mode 100644 src/server/scripts/eastern_kingdoms/redridge_mountains.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter1.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter2.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter5.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_enclave/the_scarlet_enclave.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/scholomance/scholomance.h delete mode 100644 src/server/scripts/eastern_kingdoms/searing_gorge.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h delete mode 100644 src/server/scripts/eastern_kingdoms/silvermoon_city.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/silverpine_forest.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stormwind_city.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stranglethorn_vale.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/stratholme.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/stratholme/stratholme.h delete mode 100644 src/server/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_eredar_twins.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_felmyst.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h delete mode 100644 src/server/scripts/eastern_kingdoms/tirisfal_glades.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/uldaman/uldaman.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/undercity.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/western_plaguelands.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/westfall.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/wetlands.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/boss_hexlord.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/zulaman.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulaman/zulaman.h delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp delete mode 100644 src/server/scripts/eastern_kingdoms/zulgurub/zulgurub.h delete mode 100644 src/server/scripts/examples/example_creature.cpp delete mode 100644 src/server/scripts/examples/example_escort.cpp delete mode 100644 src/server/scripts/examples/example_gossip_codebox.cpp delete mode 100644 src/server/scripts/examples/example_misc.cpp delete mode 100644 src/server/scripts/kalimdor/ashenvale.cpp delete mode 100644 src/server/scripts/kalimdor/azshara.cpp delete mode 100644 src/server/scripts/kalimdor/azuremyst_isle.cpp delete mode 100644 src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.cpp delete mode 100644 src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.h delete mode 100644 src/server/scripts/kalimdor/blackfathom_depths/boss_aku_mai.cpp delete mode 100644 src/server/scripts/kalimdor/blackfathom_depths/boss_gelihast.cpp delete mode 100644 src/server/scripts/kalimdor/blackfathom_depths/boss_kelris.cpp delete mode 100644 src/server/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp delete mode 100644 src/server/scripts/kalimdor/bloodmyst_isle.cpp delete mode 100644 src/server/scripts/kalimdor/boss_azuregos.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.h delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp delete mode 100644 src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h delete mode 100644 src/server/scripts/kalimdor/darkshore.cpp delete mode 100644 src/server/scripts/kalimdor/desolace.cpp delete mode 100644 src/server/scripts/kalimdor/durotar.cpp delete mode 100644 src/server/scripts/kalimdor/dustwallow_marsh.cpp delete mode 100644 src/server/scripts/kalimdor/felwood.cpp delete mode 100644 src/server/scripts/kalimdor/feralas.cpp delete mode 100644 src/server/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp delete mode 100644 src/server/scripts/kalimdor/maraudon/boss_landslide.cpp delete mode 100644 src/server/scripts/kalimdor/maraudon/boss_noxxion.cpp delete mode 100644 src/server/scripts/kalimdor/maraudon/boss_princess_theradras.cpp delete mode 100644 src/server/scripts/kalimdor/moonglade.cpp delete mode 100644 src/server/scripts/kalimdor/mulgore.cpp delete mode 100644 src/server/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp delete mode 100644 src/server/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp delete mode 100644 src/server/scripts/kalimdor/onyxias_lair/onyxias_lair.h delete mode 100644 src/server/scripts/kalimdor/orgrimmar.cpp delete mode 100644 src/server/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp delete mode 100644 src/server/scripts/kalimdor/razorfen_downs/instance_razorfen_downs.cpp delete mode 100644 src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp delete mode 100644 src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.h delete mode 100644 src/server/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp delete mode 100644 src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.cpp delete mode 100644 src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h delete mode 100644 src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp delete mode 100644 src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp delete mode 100644 src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp delete mode 100644 src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp delete mode 100644 src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp delete mode 100644 src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp delete mode 100644 src/server/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp delete mode 100644 src/server/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h delete mode 100644 src/server/scripts/kalimdor/silithus.cpp delete mode 100644 src/server/scripts/kalimdor/stonetalon_mountains.cpp delete mode 100644 src/server/scripts/kalimdor/tanaris.cpp delete mode 100644 src/server/scripts/kalimdor/teldrassil.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp delete mode 100644 src/server/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h delete mode 100644 src/server/scripts/kalimdor/the_barrens.cpp delete mode 100644 src/server/scripts/kalimdor/thousand_needles.cpp delete mode 100644 src/server/scripts/kalimdor/thunder_bluff.cpp delete mode 100644 src/server/scripts/kalimdor/ungoro_crater.cpp delete mode 100644 src/server/scripts/kalimdor/wailing_caverns/instance_wailing_caverns.cpp delete mode 100644 src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.cpp delete mode 100644 src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.h delete mode 100644 src/server/scripts/kalimdor/winterspring.cpp delete mode 100644 src/server/scripts/kalimdor/zulfarrak/instance_zulfarrak.cpp delete mode 100644 src/server/scripts/kalimdor/zulfarrak/zulfarrak.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/ahnkahet/ahnkahet.h delete mode 100644 src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/azjol_nerub/azjol_nerub.h delete mode 100644 src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp delete mode 100644 src/server/scripts/northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp delete mode 100644 src/server/scripts/northrend/borean_tundra.cpp delete mode 100644 src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp delete mode 100644 src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp delete mode 100644 src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp delete mode 100644 src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp delete mode 100644 src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp delete mode 100644 src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h delete mode 100644 src/server/scripts/northrend/crystalsong_forest.cpp delete mode 100644 src/server/scripts/northrend/dalaran.cpp delete mode 100644 src/server/scripts/northrend/dragonblight.cpp delete mode 100644 src/server/scripts/northrend/draktharon_keep/boss_dred.cpp delete mode 100644 src/server/scripts/northrend/draktharon_keep/boss_novos.cpp delete mode 100644 src/server/scripts/northrend/draktharon_keep/boss_tharon_ja.cpp delete mode 100644 src/server/scripts/northrend/draktharon_keep/boss_trollgore.cpp delete mode 100644 src/server/scripts/northrend/draktharon_keep/drak_tharon_keep.h delete mode 100644 src/server/scripts/northrend/draktharon_keep/instance_drak_tharon_keep.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h delete mode 100644 src/server/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h delete mode 100644 src/server/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp delete mode 100644 src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.h delete mode 100644 src/server/scripts/northrend/grizzly_hills.cpp delete mode 100644 src/server/scripts/northrend/gundrak/boss_drakkari_colossus.cpp delete mode 100644 src/server/scripts/northrend/gundrak/boss_eck.cpp delete mode 100644 src/server/scripts/northrend/gundrak/boss_gal_darah.cpp delete mode 100644 src/server/scripts/northrend/gundrak/boss_moorabi.cpp delete mode 100644 src/server/scripts/northrend/gundrak/boss_slad_ran.cpp delete mode 100644 src/server/scripts/northrend/gundrak/gundrak.h delete mode 100644 src/server/scripts/northrend/gundrak/instance_gundrak.cpp delete mode 100644 src/server/scripts/northrend/howling_fjord.cpp delete mode 100644 src/server/scripts/northrend/icecrown.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_anubrekhan.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_faerlina.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_four_horsemen.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_gluth.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_gothik.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_grobbulus.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_heigan.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_highlord_mograine.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_kelthuzad.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_loatheb.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_maexxna.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_noth.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_patchwerk.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_razuvious.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_sapphiron.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/boss_thaddius.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/instance_naxxramas.cpp delete mode 100644 src/server/scripts/northrend/naxxramas/naxxramas.h delete mode 100644 src/server/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp delete mode 100644 src/server/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h delete mode 100644 src/server/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp delete mode 100644 src/server/scripts/northrend/nexus/nexus/boss_anomalus.cpp delete mode 100644 src/server/scripts/northrend/nexus/nexus/boss_keristrasza.cpp delete mode 100644 src/server/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp delete mode 100644 src/server/scripts/northrend/nexus/nexus/boss_ormorok.cpp delete mode 100644 src/server/scripts/northrend/nexus/nexus/commander_kolurg.cpp delete mode 100644 src/server/scripts/northrend/nexus/nexus/commander_stoutbeard.cpp delete mode 100644 src/server/scripts/northrend/nexus/nexus/instance_nexus.cpp delete mode 100644 src/server/scripts/northrend/nexus/nexus/nexus.h delete mode 100644 src/server/scripts/northrend/nexus/oculus/boss_drakos.cpp delete mode 100644 src/server/scripts/northrend/nexus/oculus/boss_eregos.cpp delete mode 100644 src/server/scripts/northrend/nexus/oculus/boss_urom.cpp delete mode 100644 src/server/scripts/northrend/nexus/oculus/boss_varos.cpp delete mode 100644 src/server/scripts/northrend/nexus/oculus/instance_oculus.cpp delete mode 100644 src/server/scripts/northrend/nexus/oculus/oculus.cpp delete mode 100644 src/server/scripts/northrend/nexus/oculus/oculus.h delete mode 100644 src/server/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp delete mode 100644 src/server/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp delete mode 100644 src/server/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h delete mode 100644 src/server/scripts/northrend/sholazar_basin.cpp delete mode 100644 src/server/scripts/northrend/storm_peaks.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h delete mode 100644 src/server/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_algalon.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_freya.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_hodir.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_ignis.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_thorim.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_xt002.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/ulduar.h delete mode 100644 src/server/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.h delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp delete mode 100644 src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h delete mode 100644 src/server/scripts/northrend/vault_of_archavon/boss_archavon.cpp delete mode 100644 src/server/scripts/northrend/vault_of_archavon/boss_emalon.cpp delete mode 100644 src/server/scripts/northrend/vault_of_archavon/boss_koralon.cpp delete mode 100644 src/server/scripts/northrend/vault_of_archavon/boss_toravon.cpp delete mode 100644 src/server/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp delete mode 100644 src/server/scripts/northrend/vault_of_archavon/vault_of_archavon.h delete mode 100644 src/server/scripts/northrend/violet_hold/boss_cyanigosa.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/boss_erekem.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/boss_ichoron.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/boss_lavanthor.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/boss_moragg.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/boss_xevozz.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/boss_zuramat.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/instance_violet_hold.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/violet_hold.cpp delete mode 100644 src/server/scripts/northrend/violet_hold/violet_hold.h delete mode 100644 src/server/scripts/northrend/zuldrak.cpp delete mode 100644 src/server/scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp delete mode 100644 src/server/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp delete mode 100644 src/server/scripts/outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp delete mode 100644 src/server/scripts/outland/auchindoun/mana_tombs/boss_pandemonius.cpp delete mode 100644 src/server/scripts/outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp delete mode 100644 src/server/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp delete mode 100644 src/server/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp delete mode 100644 src/server/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h delete mode 100644 src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp delete mode 100644 src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp delete mode 100644 src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp delete mode 100644 src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_murmur.cpp delete mode 100644 src/server/scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp delete mode 100644 src/server/scripts/outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h delete mode 100644 src/server/scripts/outland/black_temple/black_temple.cpp delete mode 100644 src/server/scripts/outland/black_temple/black_temple.h delete mode 100644 src/server/scripts/outland/black_temple/boss_bloodboil.cpp delete mode 100644 src/server/scripts/outland/black_temple/boss_illidan.cpp delete mode 100644 src/server/scripts/outland/black_temple/boss_mother_shahraz.cpp delete mode 100644 src/server/scripts/outland/black_temple/boss_reliquary_of_souls.cpp delete mode 100644 src/server/scripts/outland/black_temple/boss_shade_of_akama.cpp delete mode 100644 src/server/scripts/outland/black_temple/boss_supremus.cpp delete mode 100644 src/server/scripts/outland/black_temple/boss_teron_gorefiend.cpp delete mode 100644 src/server/scripts/outland/black_temple/boss_warlord_najentus.cpp delete mode 100644 src/server/scripts/outland/black_temple/illidari_council.cpp delete mode 100644 src/server/scripts/outland/black_temple/instance_black_temple.cpp delete mode 100644 src/server/scripts/outland/blades_edge_mountains.cpp delete mode 100644 src/server/scripts/outland/boss_doomlord_kazzak.cpp delete mode 100644 src/server/scripts/outland/boss_doomwalker.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h delete mode 100644 src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/steam_vault/steam_vault.h delete mode 100644 src/server/scripts/outland/coilfang_resevoir/underbog/boss_hungarfen.cpp delete mode 100644 src/server/scripts/outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp delete mode 100644 src/server/scripts/outland/gruuls_lair/boss_gruul.cpp delete mode 100644 src/server/scripts/outland/gruuls_lair/boss_high_king_maulgar.cpp delete mode 100644 src/server/scripts/outland/gruuls_lair/gruuls_lair.h delete mode 100644 src/server/scripts/outland/gruuls_lair/instance_gruuls_lair.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/blood_furnace/blood_furnace.h delete mode 100644 src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_broggok.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h delete mode 100644 src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h delete mode 100644 src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp delete mode 100644 src/server/scripts/outland/hellfire_citadel/shattered_halls/shattered_halls.h delete mode 100644 src/server/scripts/outland/hellfire_peninsula.cpp delete mode 100644 src/server/scripts/outland/nagrand.cpp delete mode 100644 src/server/scripts/outland/netherstorm.cpp delete mode 100644 src/server/scripts/outland/shadowmoon_valley.cpp delete mode 100644 src/server/scripts/outland/shattrath_city.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.h delete mode 100644 src/server/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/arcatraz/instance_arcatraz.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/botanica/boss_laj.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/botanica/boss_warp_splinter.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_eye/boss_alar.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_eye/boss_astromancer.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_eye/boss_void_reaver.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_eye/instance_the_eye.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_eye/the_eye.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_eye/the_eye.h delete mode 100644 src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_mechanar/instance_mechanar.cpp delete mode 100644 src/server/scripts/outland/tempest_keep/the_mechanar/mechanar.h delete mode 100644 src/server/scripts/outland/terokkar_forest.cpp delete mode 100644 src/server/scripts/outland/zangarmarsh.cpp delete mode 100644 src/server/scripts/world/areatrigger_scripts.cpp delete mode 100644 src/server/scripts/world/boss_emeriss.cpp delete mode 100644 src/server/scripts/world/boss_lethon.cpp delete mode 100644 src/server/scripts/world/boss_taerar.cpp delete mode 100644 src/server/scripts/world/boss_ysondre.cpp delete mode 100644 src/server/scripts/world/go_scripts.cpp delete mode 100644 src/server/scripts/world/guards.cpp delete mode 100644 src/server/scripts/world/item_scripts.cpp delete mode 100644 src/server/scripts/world/mob_generic_creature.cpp delete mode 100644 src/server/scripts/world/npc_innkeeper.cpp delete mode 100644 src/server/scripts/world/npc_professions.cpp delete mode 100644 src/server/scripts/world/npc_taxi.cpp delete mode 100644 src/server/scripts/world/npcs_special.cpp (limited to 'src/server') diff --git a/src/server/scripts/Custom/custom_example.cpp b/src/server/scripts/Custom/custom_example.cpp new file mode 100644 index 00000000000..0e230ba901d --- /dev/null +++ b/src/server/scripts/Custom/custom_example.cpp @@ -0,0 +1,278 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Custom_Example +SD%Complete: 100 +SDComment: Short custom scripting example +SDCategory: Script Examples +EndScriptData */ + +#include "precompiled.h" + +// **** This script is designed as an example for others to build on **** +// **** Please modify whatever you'd like to as this script is only for developement **** + +// **** Script Info **** +// This script is written in a way that it can be used for both friendly and hostile monsters +// Its primary purpose is to show just how much you can really do with scripts +// I recommend trying it out on both an agressive NPC and on friendly npc + +// **** Quick Info **** +// Functions with Handled Function marked above them are functions that are called automatically by the core +// Functions that are marked Custom Function are functions I've created to simplify code + +#define SPELL_BUFF 25661 +#define SPELL_ONE 12555 +#define SPELL_ONE_ALT 24099 +#define SPELL_TWO 10017 +#define SPELL_THREE 26027 +#define SPELL_ENRAGE 23537 +#define SPELL_BESERK 32309 + +#define SAY_AGGRO "Let the games begin." +#define SAY_RANDOM_0 "I see endless suffering. I see torment. I see rage. I see everything." +#define SAY_RANDOM_1 "Muahahahaha" +#define SAY_RANDOM_2 "These mortal infedels my lord, they have invaded your sanctum and seek to steal your secrets." +#define SAY_RANDOM_3 "You are already dead." +#define SAY_RANDOM_4 "Where to go? What to do? So many choices that all end in pain, end in death." +#define SAY_BESERK "$N, I sentance you to death!" +#define SAY_PHASE "The suffering has just begun!" + +#define GOSSIP_ITEM "I'm looking for a fight" +#define SAY_DANCE "I always thought I was a good dancer" +#define SAY_SALUTE "Move out Soldier!" + +struct TRINITY_DLL_DECL custom_exampleAI : public ScriptedAI +{ + //*** HANDLED FUNCTION *** + //This is the constructor, called only once when the Creature is first created + custom_exampleAI(Creature *c) : ScriptedAI(c) {} + + //*** CUSTOM VARIABLES **** + //These variables are for use only by this individual script. + //Nothing else will ever call them but us. + + uint32 Say_Timer; //Timer for random chat + uint32 Rebuff_Timer; //Timer for rebuffing + uint32 Spell_1_Timer; //Timer for spell 1 when in combat + uint32 Spell_2_Timer; //Timer for spell 1 when in combat + uint32 Spell_3_Timer; //Timer for spell 1 when in combat + uint32 Beserk_Timer; //Timer until we go into Beserk (enraged) mode + uint32 Phase; //The current battle phase we are in + uint32 Phase_Timer; //Timer until phase transition + + //*** HANDLED FUNCTION *** + //This is called whenever the core decides we need to evade + void Reset() + { + Phase = 1; //Start in phase 1 + Phase_Timer = 60000; //60 seconds + Spell_1_Timer = 5000; //5 seconds + Spell_2_Timer = 37000; //37 seconds + Spell_3_Timer = 19000; //19 seconds + Beserk_Timer = 120000; //2 minutes + } + + //*** HANDLED FUNCTION *** + //Attack Start is called whenever someone hits us. + void Aggro(Unit *who) + { + //Say some stuff + DoSay(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,8280); + } + + //*** HANDLED FUNCTION *** + //Update AI is called Every single map update (roughly once every 100ms if a player is within the grid) + void UpdateAI(const uint32 diff) + { + //Out of combat timers + if (!me->getVictim()) + { + //Random Say timer + if (Say_Timer < diff) + { + //Random switch between 5 outcomes + switch (rand()%5) + { + case 0: + DoYell(SAY_RANDOM_0,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,8831); //8831 is the index of the sound we are playing. You find these numbers in SoundEntries.dbc + break; + + case 1: + DoYell(SAY_RANDOM_1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,8818); + break; + + case 2: + DoYell(SAY_RANDOM_2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,8041); + break; + + case 3: + DoYell(SAY_RANDOM_3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,8581); + break; + + case 4: + DoYell(SAY_RANDOM_4,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,8791); + break; + } + + Say_Timer = 45000; //Say something agian in 45 seconds + }else Say_Timer -= diff; + + //Rebuff timer + if (Rebuff_Timer < diff) + { + DoCast(me,SPELL_BUFF); + Rebuff_Timer = 900000; //Rebuff agian in 15 minutes + }else Rebuff_Timer -= diff; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Spell 1 timer + if (Spell_1_Timer < diff) + { + //Cast spell one on our current target. + if (rand()%50 > 10) + DoCast(me->getVictim(),SPELL_ONE_ALT); + else if (me->IsWithinDist(me->getVictim(), 25)) + DoCast(me->getVictim(),SPELL_ONE); + + Spell_1_Timer = 5000; + }else Spell_1_Timer -= diff; + + //Spell 2 timer + if (Spell_2_Timer < diff) + { + //Cast spell one on our current target. + DoCast(me->getVictim(),SPELL_TWO); + + Spell_2_Timer = 37000; + }else Spell_2_Timer -= diff; + + //Spell 3 timer + if (Phase > 1) + if (Spell_3_Timer < diff) + { + //Cast spell one on our current target. + DoCast(me->getVictim(),SPELL_THREE); + + Spell_3_Timer = 19000; + }else Spell_3_Timer -= diff; + + //Beserk timer + if (Phase > 1) + if (Beserk_Timer < diff) + { + //Say our line then cast uber death spell + DoPlaySoundToSet(me,8588); + DoYell(SAY_BESERK,LANG_UNIVERSAL,me->getVictim()); + DoCast(me->getVictim(),SPELL_BESERK); + + //Cast our beserk spell agian in 12 seconds if we didn't kill everyone + Beserk_Timer = 12000; + }else Beserk_Timer -= diff; + + //Phase timer + if (Phase == 1) + if (Phase_Timer < diff) + { + //Go to next phase + Phase++; + DoYell(SAY_PHASE,LANG_UNIVERSAL,NULL); + DoCast(me,SPELL_ENRAGE); + }else Phase_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//This is the GetAI method used by all scripts that involve AI +//It is called every time a new Creature using this script is created +CreatureAI* GetAI_custom_example(Creature* pCreature) +{ + return new custom_exampleAI (pCreature); +} + +//This function is called when the player clicks an option on the gossip menu +void SendDefaultMenu_custom_example(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time + { + //Set our faction to hostile twoards all + pCreature->setFaction(24); + pCreature->Attack(pPlayer, true); + pPlayer->PlayerTalkClass->CloseGossip(); + } +} + +//This function is called when the player clicks an option on the gossip menu +bool GossipSelect_custom_example(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiSender == GOSSIP_SENDER_MAIN) + SendDefaultMenu_custom_example(pPlayer, pCreature, uiAction); + + return true; +} + +//This function is called when the player opens the gossip menu +bool GossipHello_custom_example(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetGUID()); + + return true; +} + +//Our Recive emote function +bool ReceiveEmote_custom_example(Player* pPlayer, Creature* pCreature, uint32 emote) +{ + pCreature->HandleEmoteCommand(emote); + + if (emote == TEXTEMOTE_DANCE) + ((custom_exampleAI*)_Creature->AI())->DoSay(SAY_DANCE,LANG_UNIVERSAL,NULL); + + if (emote == TEXTEMOTE_SALUTE) + ((custom_exampleAI*)_Creature->AI())->DoSay(SAY_SALUTE,LANG_UNIVERSAL,NULL); + + return true; +} + +//This is the actual function called only once durring InitScripts() +//It must define all handled functions that are to be run in this script +//For example if you want this Script to handle Emotes you must include +//newscript->ReciveEmote = My_Emote_Function; +void AddSC_custom_example() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="custom_example"; + newscript->GetAI = &GetAI_custom_example; + newscript->pGossipHello = &GossipHello_custom_example; + newscript->pGossipSelect = &GossipSelect_custom_example; + newscript->pReceiveEmote = &ReceiveEmote_custom_example; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Custom/custom_gossip_codebox.cpp b/src/server/scripts/Custom/custom_gossip_codebox.cpp new file mode 100644 index 00000000000..a00d2b7031f --- /dev/null +++ b/src/server/scripts/Custom/custom_gossip_codebox.cpp @@ -0,0 +1,89 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Custom_Gossip_Codebox +SD%Complete: 100 +SDComment: Show a codebox in gossip option +SDCategory: Script Examples +EndScriptData */ + +#include "precompiled.h" +#include + +#define GOSSIP_ITEM_EXTENDED "A quiz: what's your name?" +#define GOSSIP_ITEM "I'm not interested" + +#define SAY_NOT_INTERESTED "Normal select, guess you're not interested." +#define SAY_WRONG "Wrong!" +#define SAY_RIGHT "You're right, you are allowed to see my inner secrets." + +//This function is called when the player opens the gossip menubool +bool GossipHello_custom_gossip_codebox(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1, "", 0, true); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetGUID()); + return true; +} + +//This function is called when the player clicks an option on the gossip menubool +bool GossipSelect_custom_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pCreature->Say(SAY_NOT_INTERESTED, LANG_UNIVERSAL, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + } + return true; +} + +bool GossipSelectWithCode_custom_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode) +{ + if (uiSender == GOSSIP_SENDER_MAIN) + { + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + if (std::strcmp(sCode, pPlayer->GetName())!=0) + { + pCreature->Say(SAY_WRONG, LANG_UNIVERSAL, 0); + pCreature->CastSpell(pPlayer, 12826, true); + } + else + { + pCreature->Say(SAY_RIGHT, LANG_UNIVERSAL, 0); + pCreature->CastSpell(pPlayer, 26990, true); + } + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + } + } + return false; +} + +void AddSC_custom_gossip_codebox() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="custom_gossip_codebox"; + newscript->pGossipHello = &GossipHello_custom_gossip_codebox; + newscript->pGossipSelect = &GossipSelect_custom_gossip_codebox; + newscript->pGossipSelectWithCode = &GossipSelectWithCode_custom_gossip_codebox; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Custom/npc_acherus_taxi.cpp b/src/server/scripts/Custom/npc_acherus_taxi.cpp new file mode 100644 index 00000000000..6e00e365e8e --- /dev/null +++ b/src/server/scripts/Custom/npc_acherus_taxi.cpp @@ -0,0 +1,35 @@ +#include "ScriptedPch.h" +#include "WorldPacket.h" + +#define GOSSIP_FLIGHT "I need a ride" + +bool GossipHello_npc_acherus_taxi(Player *pPlayer, Creature *pCreature) +{ + pPlayer->SetTaxiCheater(true); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(9978, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_acherus_taxi(Player *pPlayer, Creature * /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + if (pPlayer->GetPositionZ() >= 316) + pPlayer->GetSession()->SendDoFlight(24446, 1053); + else + pPlayer->GetSession()->SendDoFlight(24446, 1054); + } + return true; +} + +void AddSC_npc_acherus_taxi() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_acherus_taxi"; + newscript->pGossipHello = &GossipHello_npc_acherus_taxi; + newscript->pGossipSelect = &GossipSelect_npc_acherus_taxi; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Custom/npc_wyrmresttempel_taxi.cpp b/src/server/scripts/Custom/npc_wyrmresttempel_taxi.cpp new file mode 100644 index 00000000000..d4c2cb5ab74 --- /dev/null +++ b/src/server/scripts/Custom/npc_wyrmresttempel_taxi.cpp @@ -0,0 +1,112 @@ +#include "ScriptedPch.h" +#include "WorldPacket.h" + +#define GOSSIP_UP "My Lord, I must go to the upper floor of the temple." +#define GOSSIP_DOWN "I would like to take a flight to the ground, Lord Afrasastrasz." +#define GOSSIP_MIDDLE "Can you spare a drake to travel to Lord Afrasastrasz, in the middle of the temple?" +#define GOSSIP_TOP "Please, Let me take one of these dragons to the top floor of the temple." +#define GOSSIP_BOTTOM "Yes, Please. I would like to return to the ground floor of the temple." +#define GOSSIP_ONEDOWN "I would like to see Lord Afrasastrasz, in the middle of the temple." + +bool GossipHello_npc_wyrmresttempel_middle_taxi(Player* pPlayer, Creature* pCreature) +{ +pPlayer->SetTaxiCheater(true); + +pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); +pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DOWN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(12887, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_wyrmresttempel_middle_taxi(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->GetSession()->SendDoFlight(6376, 881); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF + 2) + { + pPlayer->GetSession()->SendDoFlight(6376, 882); + + } +return true; +} + +bool GossipHello_npc_wyrmresttempel_bottom_taxi(Player* pPlayer, Creature* pCreature) +{ +pPlayer->SetTaxiCheater(true); + +pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TOP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); +pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MIDDLE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(12713, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_wyrmresttempel_bottom_taxi(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 4) + { + pPlayer->GetSession()->SendDoFlight(6376, 878); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF + 3) + { + pPlayer->GetSession()->SendDoFlight(6376, 883); + + } +return true; +} + +bool GossipHello_npc_wyrmresttempel_top_taxi(Player* pPlayer, Creature* pCreature) +{ +pPlayer->SetTaxiCheater(true); + +pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BOTTOM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); +pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ONEDOWN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + pPlayer->SEND_GOSSIP_MENU(12714, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_wyrmresttempel_top_taxi(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 5) + { + pPlayer->GetSession()->SendDoFlight(6376, 879); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF + 6) + + { + pPlayer->GetSession()->SendDoFlight(6376, 880); + + } +return true; +} + +void AddSC_npc_wyrmresttempel_taxi() +{ + Script *newscript; + +newscript = new Script; +newscript->Name = "npc_wyrmresttempelmiddle_taxi"; +newscript->pGossipHello = &GossipHello_npc_wyrmresttempel_middle_taxi; +newscript->pGossipSelect = &GossipSelect_npc_wyrmresttempel_middle_taxi; +newscript->RegisterSelf(); + +newscript = new Script; +newscript->Name = "npc_wyrmresttempelbottom_taxi"; +newscript->pGossipHello = &GossipHello_npc_wyrmresttempel_bottom_taxi; +newscript->pGossipSelect = &GossipSelect_npc_wyrmresttempel_bottom_taxi; +newscript->RegisterSelf(); + +newscript = new Script; +newscript->Name = "npc_wyrmresttempeltop_taxi"; +newscript->pGossipHello = &GossipHello_npc_wyrmresttempel_top_taxi; +newscript->pGossipSelect = &GossipSelect_npc_wyrmresttempel_top_taxi; +newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Custom/on_events.cpp b/src/server/scripts/Custom/on_events.cpp new file mode 100644 index 00000000000..94e54a07fba --- /dev/null +++ b/src/server/scripts/Custom/on_events.cpp @@ -0,0 +1,108 @@ +#include "ScriptedPch.h" +#include + +//This function is called when the player logs in (every login) +void OnLogin(Player * /*pPlayer*/) +{ + +} + +//This function is called when the player logs out +void OnLogout(Player * /*pPlayer*/) +{ + +} + +//This function is called when the player kills another player +void OnPVPKill(Player * /*killer*/, Player * /*killed*/) +{ + +} + +//This function is called when a players AreaID changes +void OnAreaChange(Player * /*pPlayer*/, AreaTableEntry const * /*pArea*/) +{ + +} + +//This is called when a player kills a creature (non pvp) +void OnCreatureKill(Player * /*pPlayer*/, Creature * /*pCreature*/) +{ + +} + +//This function is called when a player has a money exchange +int32 OnGetMoney(Player * /*pPlayer*/, int32 amount) +{ + return amount; +} + +//This function is called whenever a player gets XP +uint32 OnGetXP(Player * /*pPlayer*/, uint32 amount) +{ + return amount; +} + +//This function is called when a player clicks a GO Object +bool OnGoClick(Player * /*pPlayer*/, GameObject * /*pGameObject*/) +{ + return true; +} + +//This function is called when a player clicks and item +bool OnItemClick(Player * /*pPlayer*/, Item * /*pItem*/) +{ + return true; +} + +//This function is called when a player opens an item (like a clam) +bool OnItemOpen(Player * /*pPlayer*/, Item * /*pItem*/) +{ + return true; +} + +//This function is called when a player sends a chat message +bool OnPlayerChat(Player * /*pPlayer*/, const char * /*text*/) +{ + return true; +} + +//this function is called when the server starts +void OnServerStartup() +{ + +} +//this function is called when the server shuts down +void OnServerShutdown() +{ + +} + +//this function is called when a player casts a spell +bool OnSpellCast(Unit * /*pUnitTarget*/, Item * /*pItemTarget*/, GameObject * /*pGoTarget*/, uint32 /*i*/, SpellEntry const * /*spell*/) +{ + return true; +} + + void AddSC_onevents() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "scripted_on_events"; + newscript->pOnLogin = &OnLogin; + newscript->pOnLogout = &OnLogout; + newscript->pOnPVPKill = &OnPVPKill; + newscript->pOnAreaChange = &OnAreaChange; + newscript->pOnCreatureKill = &OnCreatureKill; + newscript->pOnGetMoney = &OnGetMoney; + newscript->pOnGetXP = &OnGetXP; + newscript->pOnGoClick = &OnGoClick; + newscript->pOnItemClick = &OnItemClick; + newscript->pOnItemOpen = &OnItemOpen; + newscript->pOnPlayerChat = &OnPlayerChat; + newscript->pOnServerShutdown = &OnServerShutdown; + newscript->pOnServerStartup = &OnServerStartup; + newscript->pOnSpellCast = &OnSpellCast; + + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Custom/test.cpp b/src/server/scripts/Custom/test.cpp new file mode 100644 index 00000000000..aa9e6879075 --- /dev/null +++ b/src/server/scripts/Custom/test.cpp @@ -0,0 +1,218 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Test +SD%Complete: 100 +SDComment: Script used for testing escortAI +SDCategory: Script Examples +EndScriptData */ + +#include "precompiled.h" +#include "escort_ai.h" + +#define SAY_WALK "Hmm a nice day for a walk alright" +#define SAY_ATTACK "Wild Felboar attack!" +#define SAY_TIME_TO_GO "Time for me to go! See ya around $N!" +#define SAY_BYE "Bye Bye!" +#define SAY_AGGRO1 "Help $N! I'm under attack!" +#define SAY_AGGRO2 "Die scum!" +#define WHISPER_TOO_FAR "How dare you leave me like that! I hate you! =*(" +#define SAY_DIE1 "...no...how could you let me die $N" +#define SAY_DIE2 "ugh..." +#define SAY_DEATHCOIL "Taste death!" +#define SAY_FIREWORKS "Fireworks!" +#define SAY_BUFF "Hmm, I think I could use a buff" + +#define GOSSIP_TEXT1 "Click to Test Escort(Attack, Defend, Run)" +#define GOSSIP_TEXT2 "Click to Test Escort(NoAttack, NoDefend, Walk)" +#define GOSSIP_TEXT3 "Click to Test Escort(NoAttack, Defend, Walk)" + +struct TRINITY_DLL_DECL npc_testAI : public npc_escortAI +{ + public: + + // CreatureAI functions + npc_testAI(Creature *c) : npc_escortAI(c) {} + + uint32 DeathCoilTimer; + uint32 ChatTimer; + + // Pure Virtual Functions + void WaypointReached(uint32 i) + { + switch (i) + { + case 1: + me->Say(SAY_WALK, LANG_UNIVERSAL, 0); + break; + + case 3: + { + me->Say(SAY_ATTACK, LANG_UNIVERSAL, 0); + Creature* temp = me->SummonCreature(21878, me->GetPositionX()+5, me->GetPositionY()+7, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + if (temp) + temp->AI()->AttackStart(me); + } + break; + + case 4: + { + me->Say(SAY_TIME_TO_GO, LANG_UNIVERSAL, PlayerGUID); + me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); + + Unit* temp = Unit::GetUnit(*me, PlayerGUID); + if (temp) + { + temp->MonsterSay(SAY_BYE, LANG_UNIVERSAL, 0); + temp->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); + } + } + break; + } + } + + void Aggro(Unit*) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + me->Say(SAY_AGGRO1, LANG_UNIVERSAL, PlayerGUID); + else me->Say(SAY_AGGRO2, LANG_UNIVERSAL, 0); + } + + void Reset() + { + DeathCoilTimer = 4000; + ChatTimer = 4000; + } + + void JustDied(Unit* killer) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + //killer = me when player got to far from creature + if (killer == me) + { + Unit *pTemp = Unit::GetUnit(*me,PlayerGUID); + if (pTemp) + DoWhisper(WHISPER_TOO_FAR, pTemp); + } + else me->Say(SAY_DIE1, LANG_UNIVERSAL, PlayerGUID); + } + else me->Say(SAY_DIE2, LANG_UNIVERSAL, 0); + } + + void UpdateAI(const uint32 diff) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + + //Combat check + if (me->isInCombat() && me->getVictim()) + { + if (DeathCoilTimer < diff) + { + me->Say(SAY_DEATHCOIL, LANG_UNIVERSAL, 0); + me->CastSpell(me->getVictim(), 33130, false); + + DeathCoilTimer = 4000; + }else DeathCoilTimer -= diff; + }else + { + //Out of combat but being escorted + if (HasEscortState(STATE_ESCORT_ESCORTING)) + if (ChatTimer < diff) + { + if (me->HasAura(3593, 0)) + { + me->Say(SAY_FIREWORKS, LANG_UNIVERSAL, 0); + me->CastSpell(me, 11540, false); + }else + { + me->Say(SAY_BUFF, LANG_UNIVERSAL, 0); + me->CastSpell(me, 3593, false); + } + + ChatTimer = 12000; + }else ChatTimer -= diff; + } + } +}; + +CreatureAI* GetAI_test(Creature* pCreature) +{ + npc_testAI* testAI = new npc_testAI(pCreature); + + testAI->AddWaypoint(0, 1231, -4419, 23); + testAI->AddWaypoint(1, 1198, -4440, 23, 0); + testAI->AddWaypoint(2, 1208, -4392, 23); + testAI->AddWaypoint(3, 1231, -4419, 23, 5000); + testAI->AddWaypoint(4, 1208, -4392, 23, 5000); + + return (CreatureAI*)testAI; +} + +bool GossipHello_npc_test(Player* pPlayer, Creature* pCreature) +{ + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + pCreature->prepareGossipMenu(pPlayer,0); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEXT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEXT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEXT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + + pCreature->sendPreparedGossip(pPlayer); + return true; +} + +bool GossipSelect_npc_test(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + ((npc_escortAI*)(pCreature->AI()))->Start(true, true, pPlayer->GetGUID()); + + return true; // prevent Trinity core handling + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + ((npc_escortAI*)(pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); + + return true; // prevent Trinity core handling + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF+3) + { + pPlayer->CLOSE_GOSSIP_MENU(); + ((npc_escortAI*)(pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); + + return true; // prevent Trinity core handling + } + return false; +} + +void AddSC_test() +{ + Script *newscript; + newscript = new Script; + newscript->Name="test"; + newscript->GetAI = &GetAI_test; + newscript->pGossipHello = &GossipHello_npc_test; + newscript->pGossipSelect = &GossipSelect_npc_test; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/alterac_mountains.cpp b/src/server/scripts/EasternKingdoms/alterac_mountains.cpp new file mode 100644 index 00000000000..8695a73131c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/alterac_mountains.cpp @@ -0,0 +1,32 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Alterac_Mountains +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Alterac Mountains +EndScriptData */ + +/* ContentData +EndContentData */ + +#include "ScriptedPch.h" + +/*void AddSC_alterac_mountains() +{ + Script *newscript; +}*/ diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp new file mode 100644 index 00000000000..a61fc21d5ba --- /dev/null +++ b/src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp @@ -0,0 +1,180 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_CHARGE = 22911, + SPELL_CLEAVE = 40504, + SPELL_DEMORALIZING_SHOUT = 23511, + SPELL_ENRAGE = 8599, + SPELL_WHIRLWIND1 = 15589, + SPELL_WHIRLWIND2 = 13736, + SPELL_NORTH_MARSHAL = 45828, + SPELL_SOUTH_MARSHAL = 45829, + SPELL_STONEHEARTH_MARSHAL = 45830, + SPELL_ICEWING_MARSHAL = 45831, + SPELL_ICEBLOOD_WARMASTER = 45822, + SPELL_TOWER_POINT_WARMASTER = 45823, + SPELL_WEST_FROSTWOLF_WARMASTER = 45824, + SPELL_EAST_FROSTWOLF_WARMASTER = 45826 +}; + +enum Creatures +{ + NPC_NORTH_MARSHAL = 14762, + NPC_SOUTH_MARSHAL = 14763, + NPC_ICEWING_MARSHAL = 14764, + NPC_STONEHEARTH_MARSHAL = 14765, + NPC_EAST_FROSTWOLF_WARMASTER = 14772, + NPC_ICEBLOOD_WARMASTER = 14773, + NPC_TOWER_POINT_WARMASTER = 14776, + NPC_WEST_FROSTWOLF_WARMASTER = 14777 +}; + +struct mob_av_marshal_or_warmasterAI : public ScriptedAI +{ + mob_av_marshal_or_warmasterAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiChargeTimer; + uint32 uiCleaveTimer; + uint32 uiDemoralizingShoutTimer; + uint32 uiWhirlwind1Timer; + uint32 uiWhirlwind2Timer; + uint32 uiEnrageTimer; + uint32 uiResetTimer; + + bool bHasAura; + + void Reset() + { + uiChargeTimer = urand(2*IN_MILISECONDS,12*IN_MILISECONDS); + uiCleaveTimer = urand(1*IN_MILISECONDS,11*IN_MILISECONDS); + uiDemoralizingShoutTimer = urand(2*IN_MILISECONDS,2*IN_MILISECONDS); + uiWhirlwind1Timer = urand(1*IN_MILISECONDS,12*IN_MILISECONDS); + uiWhirlwind2Timer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); + uiEnrageTimer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); + uiResetTimer = 5*IN_MILISECONDS; + + bHasAura = false; + } + + void JustRespawned() + { + Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!bHasAura) + { + switch(me->GetEntry()) + { + case NPC_NORTH_MARSHAL: + DoCast(me,SPELL_NORTH_MARSHAL); + break; + case NPC_SOUTH_MARSHAL: + DoCast(me,SPELL_SOUTH_MARSHAL); + break; + case NPC_STONEHEARTH_MARSHAL: + DoCast(me,SPELL_STONEHEARTH_MARSHAL); + break; + case NPC_ICEWING_MARSHAL: + DoCast(me,SPELL_ICEWING_MARSHAL); + break; + case NPC_EAST_FROSTWOLF_WARMASTER: + DoCast(me,SPELL_EAST_FROSTWOLF_WARMASTER); + break; + case NPC_WEST_FROSTWOLF_WARMASTER: + DoCast(me,SPELL_WEST_FROSTWOLF_WARMASTER); + break; + case NPC_ICEBLOOD_WARMASTER: + DoCast(me,SPELL_ICEBLOOD_WARMASTER); + break; + case NPC_TOWER_POINT_WARMASTER: + DoCast(me,SPELL_TOWER_POINT_WARMASTER); + break; + } + + bHasAura = true; + } + + if (!UpdateVictim()) + return; + + if (uiChargeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CHARGE); + uiChargeTimer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiChargeTimer -= diff; + + if (uiCleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + uiCleaveTimer = urand(10*IN_MILISECONDS,16*IN_MILISECONDS); + } else uiCleaveTimer -= diff; + + if (uiDemoralizingShoutTimer <= diff) + { + DoCast(me->getVictim(), SPELL_DEMORALIZING_SHOUT); + uiDemoralizingShoutTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiDemoralizingShoutTimer -= diff; + + if (uiWhirlwind1Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND1); + uiWhirlwind1Timer = urand(6*IN_MILISECONDS,20*IN_MILISECONDS); + } else uiWhirlwind1Timer -= diff; + + if (uiWhirlwind2Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND2); + uiWhirlwind2Timer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiWhirlwind2Timer -= diff; + + if (uiEnrageTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ENRAGE); + uiEnrageTimer = urand(10*IN_MILISECONDS,30*IN_MILISECONDS); + }else uiEnrageTimer -= diff; + + + // check if creature is not outside of building + if (uiResetTimer <= diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + EnterEvadeMode(); + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_av_marshal_or_warmaster(Creature *_Creature) +{ + return new mob_av_marshal_or_warmasterAI (_Creature); +} + +void AddSC_alterac_valley() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_av_marshal_or_warmaster"; + newscript->GetAI = &GetAI_mob_av_marshal_or_warmaster; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp new file mode 100644 index 00000000000..ce2a81c864a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp @@ -0,0 +1,203 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_ARCANE_EXPLOSION = 46608, + SPELL_CONE_OF_COLD = 38384, + SPELL_FIREBALL = 46988, + SPELL_FROSTBOLT = 46987 +}; + +enum Yells +{ + YELL_AGGRO = -2100019, + YELL_EVADE = -2100020 +}; + +enum Creatures +{ + NPC_WATER_ELEMENTAL = 25040 +}; + +enum WaterElementalSpells +{ + SPELL_WATERBOLT = 46983 +}; + +struct mob_water_elementalAI : public ScriptedAI +{ + mob_water_elementalAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWaterBoltTimer; + uint64 uiBalindaGUID; + uint32 uiResetTimer; + + void Reset() + { + uiWaterBoltTimer = 3*IN_MILISECONDS; + uiResetTimer = 5*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWaterBoltTimer < diff) + { + DoCast(me->getVictim(), SPELL_WATERBOLT); + uiWaterBoltTimer = 5*IN_MILISECONDS; + } else uiWaterBoltTimer -= diff; + + // check if creature is not outside of building + if (uiResetTimer < diff) + { + if (Creature *pBalinda = Unit::GetCreature(*me, uiBalindaGUID)) + if (me->GetDistance2d(pBalinda->GetHomePosition().GetPositionX(), pBalinda->GetHomePosition().GetPositionY()) > 50) + EnterEvadeMode(); + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_balindaAI : public ScriptedAI +{ + boss_balindaAI(Creature *c) : ScriptedAI(c), Summons(me) {} + + uint32 uiArcaneExplosionTimer; + uint32 uiConeOfColdTimer; + uint32 uiFireBoltTimer; + uint32 uiFrostboltTimer; + uint32 uiResetTimer; + uint32 uiWaterElementalTimer; + + SummonList Summons; + + void Reset() + { + uiArcaneExplosionTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); + uiConeOfColdTimer = 8*IN_MILISECONDS; + uiFireBoltTimer = 1*IN_MILISECONDS; + uiFrostboltTimer = 4*IN_MILISECONDS; + uiResetTimer = 5*IN_MILISECONDS; + uiWaterElementalTimer = 0; + + Summons.DespawnAll(); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + } + + void JustRespawned() + { + Reset(); + } + + void JustSummoned(Creature* summoned) + { + ((mob_water_elementalAI*)summoned->AI())->uiBalindaGUID = me->GetGUID(); + summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); + summoned->setFaction(me->getFaction()); + Summons.Summon(summoned); + } + + void JustDied(Unit* /*Killer*/) + { + Summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWaterElementalTimer < diff) + { + if (Summons.empty()) + me->SummonCreature(NPC_WATER_ELEMENTAL, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45*IN_MILISECONDS); + uiWaterElementalTimer = 50*IN_MILISECONDS; + } else uiWaterElementalTimer -= diff; + + if (uiArcaneExplosionTimer < diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); + uiArcaneExplosionTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiArcaneExplosionTimer -= diff; + + if (uiConeOfColdTimer < diff) + { + DoCast(me->getVictim(), SPELL_CONE_OF_COLD); + uiConeOfColdTimer = urand(10*IN_MILISECONDS,20*IN_MILISECONDS); + } else uiConeOfColdTimer -= diff; + + if (uiFireBoltTimer < diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL); + uiFireBoltTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); + } else uiFireBoltTimer -= diff; + + if (uiFrostboltTimer < diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + uiFrostboltTimer = urand(4*IN_MILISECONDS,12*IN_MILISECONDS); + } else uiFrostboltTimer -= diff; + + + // check if creature is not outside of building + if (uiResetTimer < diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + { + EnterEvadeMode(); + DoScriptText(YELL_EVADE, me); + } + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_balinda(Creature *_Creature) +{ + return new boss_balindaAI (_Creature); +} + +CreatureAI* GetAI_mob_water_elemental(Creature *_Creature) +{ + return new mob_water_elementalAI (_Creature); +} + +void AddSC_boss_balinda() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_balinda"; + newscript->GetAI = &GetAI_boss_balinda; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_water_elemental"; + newscript->GetAI = &GetAI_mob_water_elemental; + newscript->RegisterSelf(); +}; \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp new file mode 100644 index 00000000000..6477ebe5eaf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_WHIRLWIND = 15589, + SPELL_WHIRLWIND2 = 13736, + SPELL_KNOCKDOWN = 19128, + SPELL_FRENZY = 8269, + SPELL_SWEEPING_STRIKES = 18765, // not sure + SPELL_CLEAVE = 20677, // not sure + SPELL_WINDFURY = 35886, // not sure + SPELL_STORMPIKE = 51876 // not sure +}; + +enum Yells +{ + YELL_AGGRO = -1810000, + YELL_EVADE = -1810001, + YELL_RESPAWN = -1810002, + YELL_RANDOM1 = -1810003, + YELL_RANDOM2 = -1810004, + YELL_RANDOM3 = -1810005, + YELL_RANDOM4 = -1810006, + YELL_RANDOM5 = -1810007 +}; + +struct boss_drektharAI : public ScriptedAI +{ + boss_drektharAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWhirlwindTimer; + uint32 uiWhirlwind2Timer; + uint32 uiKnockdownTimer; + uint32 uiFrenzyTimer; + uint32 uiYellTimer; + uint32 uiResetTimer; + + void Reset() + { + uiWhirlwindTimer = urand(1*IN_MILISECONDS,20*IN_MILISECONDS); + uiWhirlwind2Timer = urand(1*IN_MILISECONDS,20*IN_MILISECONDS); + uiKnockdownTimer = 12*IN_MILISECONDS; + uiFrenzyTimer = 6*IN_MILISECONDS; + uiResetTimer = 5*IN_MILISECONDS; + uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds + } + + void Aggro(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + } + + void JustRespawned() + { + Reset(); + DoScriptText(YELL_RESPAWN, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWhirlwindTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + uiWhirlwindTimer = urand(8*IN_MILISECONDS,18*IN_MILISECONDS); + } else uiWhirlwindTimer -= diff; + + if (uiWhirlwind2Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND2); + uiWhirlwind2Timer = urand(7*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiWhirlwind2Timer -= diff; + + if (uiKnockdownTimer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + uiKnockdownTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiKnockdownTimer -= diff; + + if (uiFrenzyTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FRENZY); + uiFrenzyTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiFrenzyTimer -= diff; + + if (uiYellTimer <= diff) + { + DoScriptText(RAND(YELL_RANDOM1,YELL_RANDOM2,YELL_RANDOM3,YELL_RANDOM4,YELL_RANDOM5), me); + uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds + } else uiYellTimer -= diff; + + // check if creature is not outside of building + if (uiResetTimer <= diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + { + EnterEvadeMode(); + DoScriptText(YELL_EVADE, me); + } + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_boss_drekthar(Creature *_Creature) +{ + return new boss_drektharAI (_Creature); +} + +void AddSC_boss_drekthar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_drekthar"; + newscript->GetAI = &GetAI_boss_drekthar; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp new file mode 100644 index 00000000000..a12b9f267f9 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp @@ -0,0 +1,129 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_CLEAVE = 15284, + SPELL_FRIGHTENING_SHOUT = 19134, + SPELL_WHIRLWIND1 = 15589, + SPELL_WHIRLWIND2 = 13736, + SPELL_MORTAL_STRIKE = 16856 +}; + +enum Yells +{ + YELL_AGGRO = -1810021, + YELL_EVADE = -1810022 +}; + +struct boss_galvangarAI : public ScriptedAI +{ + boss_galvangarAI(Creature *c) : ScriptedAI(c) {} + + + uint32 uiCleaveTimer; + uint32 uiFrighteningShoutTimer; + uint32 uiWhirlwind1Timer; + uint32 uiWhirlwind2Timer; + uint32 uiMortalStrikeTimer; + uint32 uiResetTimer; + + + void Reset() + { + uiCleaveTimer = urand(1*IN_MILISECONDS,9*IN_MILISECONDS); + uiFrighteningShoutTimer = urand(2*IN_MILISECONDS,19*IN_MILISECONDS); + uiWhirlwind1Timer = urand(1*IN_MILISECONDS,13*IN_MILISECONDS); + uiWhirlwind2Timer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); + uiMortalStrikeTimer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); + uiResetTimer = 5*IN_MILISECONDS; + } + + void Aggro(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + } + + void JustRespawned() + { + Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiCleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + uiCleaveTimer = urand(10*IN_MILISECONDS,16*IN_MILISECONDS); + } else uiCleaveTimer -= diff; + + if (uiFrighteningShoutTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); + uiFrighteningShoutTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiFrighteningShoutTimer -= diff; + + if (uiWhirlwind1Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND1); + uiWhirlwind1Timer = urand(6*IN_MILISECONDS,10*IN_MILISECONDS); + } else uiWhirlwind1Timer -= diff; + + if (uiWhirlwind2Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND2); + uiWhirlwind2Timer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiWhirlwind2Timer -= diff; + + if (uiMortalStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + uiMortalStrikeTimer = urand(10*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiMortalStrikeTimer -= diff; + + // check if creature is not outside of building + if (uiResetTimer <= diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + { + EnterEvadeMode(); + DoScriptText(YELL_EVADE, me); + } + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_galvangar(Creature *_Creature) +{ + return new boss_galvangarAI (_Creature); +} + +void AddSC_boss_galvangar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_galvangar"; + newscript->GetAI = &GetAI_boss_galvangar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp new file mode 100644 index 00000000000..785827bc5d9 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp @@ -0,0 +1,129 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +enum Yells +{ + YELL_AGGRO = -1810008, + YELL_EVADE = -1810009, + YELL_RESPAWN1 = -1810010, + YELL_RESPAWN2 = -1810011, + YELL_RANDOM1 = -1810012, + YELL_RANDOM2 = -1810013, + YELL_RANDOM3 = -1810014, + YELL_RANDOM4 = -1810015, + YELL_RANDOM5 = -1810016, + YELL_RANDOM6 = -1810017, + YELL_RANDOM7 = -1810018 +}; + +enum Spells +{ + SPELL_AVATAR = 19135, + SPELL_THUNDERCLAP = 15588, + SPELL_STORMBOLT = 20685 // not sure +}; + +struct boss_vanndarAI : public ScriptedAI +{ + boss_vanndarAI(Creature *c) : ScriptedAI(c) {} + + + uint32 uiAvatarTimer; + uint32 uiThunderclapTimer; + uint32 uiStormboltTimer; + uint32 uiResetTimer; + uint32 uiYellTimer; + + + void Reset() + { + uiAvatarTimer = 3*IN_MILISECONDS; + uiThunderclapTimer = 4*IN_MILISECONDS; + uiStormboltTimer = 6*IN_MILISECONDS; + uiResetTimer = 5*IN_MILISECONDS; + uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } + + void Aggro(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + } + + void JustRespawned() + { + Reset(); + DoScriptText(RAND(YELL_RESPAWN1,YELL_RESPAWN2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiAvatarTimer <= diff) + { + DoCast(me->getVictim(), SPELL_AVATAR); + uiAvatarTimer = urand(15*IN_MILISECONDS,20*IN_MILISECONDS); + } else uiAvatarTimer -= diff; + + if (uiThunderclapTimer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + uiThunderclapTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiThunderclapTimer -= diff; + + if (uiStormboltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STORMBOLT); + uiStormboltTimer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiStormboltTimer -= diff; + + if (uiYellTimer <= diff) + { + DoScriptText(RAND(YELL_RANDOM1,YELL_RANDOM2,YELL_RANDOM3,YELL_RANDOM4,YELL_RANDOM5,YELL_RANDOM6,YELL_RANDOM7), me); + uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds + } else uiYellTimer -= diff; + + // check if creature is not outside of building + if (uiResetTimer <= diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + { + EnterEvadeMode(); + DoScriptText(YELL_EVADE, me); + } + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vanndar(Creature *_Creature) +{ + return new boss_vanndarAI (_Creature); +} + +void AddSC_boss_vanndar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vanndar"; + newscript->GetAI = &GetAI_boss_vanndar; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/arathi_highlands.cpp b/src/server/scripts/EasternKingdoms/arathi_highlands.cpp new file mode 100644 index 00000000000..86edbc2ed9d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/arathi_highlands.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Arathi Highlands +SD%Complete: 100 +SDComment: Quest support: 665 +SDCategory: Arathi Highlands +EndScriptData */ + +/* ContentData +npc_professor_phizzlethorpe +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_professor_phizzlethorpe +######*/ + +enum eEnums +{ + SAY_PROGRESS_1 = -1000264, + SAY_PROGRESS_2 = -1000265, + SAY_PROGRESS_3 = -1000266, + EMOTE_PROGRESS_4 = -1000267, + SAY_AGGRO = -1000268, + SAY_PROGRESS_5 = -1000269, + SAY_PROGRESS_6 = -1000270, + SAY_PROGRESS_7 = -1000271, + EMOTE_PROGRESS_8 = -1000272, + SAY_PROGRESS_9 = -1000273, + + QUEST_SUNKEN_TREASURE = 665, + MOB_VENGEFUL_SURGE = 2776 +}; + +struct npc_professor_phizzlethorpeAI : public npc_escortAI +{ + npc_professor_phizzlethorpeAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 uiPointId) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(uiPointId) + { + case 4:DoScriptText(SAY_PROGRESS_2, me, pPlayer);break; + case 5:DoScriptText(SAY_PROGRESS_3, me, pPlayer);break; + case 8:DoScriptText(EMOTE_PROGRESS_4, me);break; + case 9: + { + me->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96, -2142.49, 20.15, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + me->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96, -2142.49, 20.15, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + break; + } + case 10:DoScriptText(SAY_PROGRESS_5, me, pPlayer);break; + case 11: + DoScriptText(SAY_PROGRESS_6, me, pPlayer); + SetRun(); + break; + case 19:DoScriptText(SAY_PROGRESS_7, me, pPlayer); break; + case 20: + DoScriptText(EMOTE_PROGRESS_8, me); + DoScriptText(SAY_PROGRESS_9, me, pPlayer); + if (pPlayer) + CAST_PLR(pPlayer)->GroupEventHappens(QUEST_SUNKEN_TREASURE, me); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->AI()->AttackStart(me); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; + +bool QuestAccept_npc_professor_phizzlethorpe(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_SUNKEN_TREASURE) + { + DoScriptText(SAY_PROGRESS_1, pCreature, pPlayer); + if (npc_escortAI* pEscortAI = CAST_AI(npc_professor_phizzlethorpeAI, (pCreature->AI()))) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + + pCreature->setFaction(113); + } + return true; +} + +CreatureAI* GetAI_npc_professor_phizzlethorpeAI(Creature* pCreature) +{ + return new npc_professor_phizzlethorpeAI(pCreature); +} + +void AddSC_arathi_highlands() +{ + Script * newscript; + + newscript = new Script; + newscript->Name = "npc_professor_phizzlethorpe"; + newscript->GetAI = &GetAI_npc_professor_phizzlethorpeAI; + newscript->pQuestAccept = &QuestAccept_npc_professor_phizzlethorpe; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp new file mode 100644 index 00000000000..e04fa8444b2 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp @@ -0,0 +1,1338 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Blackrock_Depths +SD%Complete: 95 +SDComment: Quest support: 4001, 4342, 7604, 4322. Vendor Lokhtos Darkbargainer. Need to rewrite the Jail Break support +SDCategory: Blackrock Depths +EndScriptData */ + +/* ContentData +go_shadowforge_brazier +at_ring_of_law +npc_grimstone +mob_phalanx +npc_kharan_mighthammer +npc_lokhtos_darkbargainer +npc_dughal_stormwing +npc_marshal_windsor +npc_marshal_reginald_windsor +npc_tobias_seecher +npc_rocknot +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "blackrock_depths.h" + +/*###### ++## go_shadowforge_brazier ++######*/ + +bool GOHello_go_shadowforge_brazier(Player* /*pPlayer*/, GameObject* pGo) +{ + if (ScriptedInstance* pInstance = pGo->GetInstanceData()) + { + if (pInstance->GetData(TYPE_LYCEUM) == IN_PROGRESS) + pInstance->SetData(TYPE_LYCEUM, DONE); + else + pInstance->SetData(TYPE_LYCEUM, IN_PROGRESS); + // If used brazier open linked doors (North or South) + if (pGo->GetGUID() == pInstance->GetData64(DATA_SF_BRAZIER_N)) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GOLEM_DOOR_N), true); + else if (pGo->GetGUID() == pInstance->GetData64(DATA_SF_BRAZIER_S)) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GOLEM_DOOR_S), true); + } + return false; +} + +/*###### +## npc_grimstone +######*/ + +enum eGrimstone +{ + NPC_GRIMSTONE = 10096, + NPC_THELDREN = 16059, + + //4 or 6 in total? 1+2+1 / 2+2+2 / 3+3. Depending on this, code should be changed. + MAX_MOB_AMOUNT = 4 +}; + +uint32 RingMob[]= +{ + 8925, // Dredge Worm + 8926, // Deep Stinger + 8927, // Dark Screecher + 8928, // Burrowing Thundersnout + 8933, // Cave Creeper + 8932, // Borer Beetle +}; + +uint32 RingBoss[]= +{ + 9027, // Gorosh + 9028, // Grizzle + 9029, // Eviscerator + 9030, // Ok'thor + 9031, // Anub'shiah + 9032, // Hedrum +}; + +bool AreaTrigger_at_ring_of_law(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + if (ScriptedInstance* pInstance = pPlayer->GetInstanceData()) + { + if (pInstance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || pInstance->GetData(TYPE_RING_OF_LAW) == DONE) + return false; + + pInstance->SetData(TYPE_RING_OF_LAW,IN_PROGRESS); + pPlayer->SummonCreature(NPC_GRIMSTONE,625.559,-205.618,-52.735,2.609,TEMPSUMMON_DEAD_DESPAWN,0); + + return false; + } + return false; +} + +/*###### +## npc_grimstone +######*/ + +enum GrimstoneTexts +{ + SCRIPT_TEXT1 = -1000000, + SCRIPT_TEXT2 = -1000001, + SCRIPT_TEXT3 = -1000002, + SCRIPT_TEXT4 = -1000003, + SCRIPT_TEXT5 = -1000004, + SCRIPT_TEXT6 = -1000005 +}; + +//TODO: implement quest part of event (different end boss) +struct npc_grimstoneAI : public npc_escortAI +{ + npc_grimstoneAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + MobSpawnId = rand()%6; + } + + ScriptedInstance* pInstance; + + uint8 EventPhase; + uint32 Event_Timer; + + uint8 MobSpawnId; + uint8 MobCount; + uint32 MobDeath_Timer; + + uint64 RingMobGUID[4]; + uint64 RingBossGUID; + + bool CanWalk; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + EventPhase = 0; + Event_Timer = 1000; + + MobCount = 0; + MobDeath_Timer = 0; + + for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) + RingMobGUID[i] = 0; + + RingBossGUID = 0; + + CanWalk = false; + } + + //TODO: move them to center + void SummonRingMob() + { + if (Creature* tmp = me->SummonCreature(RingMob[MobSpawnId],608.960,-235.322,-53.907,1.857,TEMPSUMMON_DEAD_DESPAWN,0)) + RingMobGUID[MobCount] = tmp->GetGUID(); + + ++MobCount; + + if (MobCount == MAX_MOB_AMOUNT) + MobDeath_Timer = 2500; + } + + //TODO: move them to center + void SummonRingBoss() + { + if (Creature* tmp = me->SummonCreature(RingBoss[rand()%6],644.300,-175.989,-53.739,3.418,TEMPSUMMON_DEAD_DESPAWN,0)) + RingBossGUID = tmp->GetGUID(); + + MobDeath_Timer = 2500; + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 0: + DoScriptText(SCRIPT_TEXT1, me);//2 + CanWalk = false; + Event_Timer = 5000; + break; + case 1: + DoScriptText(SCRIPT_TEXT2, me);//4 + CanWalk = false; + Event_Timer = 5000; + break; + case 2: + CanWalk = false; + break; + case 3: + DoScriptText(SCRIPT_TEXT3, me);//5 + break; + case 4: + DoScriptText(SCRIPT_TEXT4, me);//6 + CanWalk = false; + Event_Timer = 5000; + break; + case 5: + if (pInstance) + { + pInstance->SetData(TYPE_RING_OF_LAW,DONE); + debug_log("TSCR: npc_grimstone: event reached end and set complete."); + } + break; + } + } + + void HandleGameObject(uint32 id, bool open) + { + pInstance->HandleGameObject(pInstance->GetData64(id), open); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (MobDeath_Timer) + { + if (MobDeath_Timer <= diff) + { + MobDeath_Timer = 2500; + + if (RingBossGUID) + { + Creature *boss = Unit::GetCreature(*me,RingBossGUID); + if (boss && !boss->isAlive() && boss->isDead()) + { + RingBossGUID = 0; + Event_Timer = 5000; + MobDeath_Timer = 0; + return; + } + return; + } + + for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) + { + Creature *mob = Unit::GetCreature(*me,RingMobGUID[i]); + if (mob && !mob->isAlive() && mob->isDead()) + { + RingMobGUID[i] = 0; + --MobCount; + + //seems all are gone, so set timer to continue and discontinue this + if (!MobCount) + { + Event_Timer = 5000; + MobDeath_Timer = 0; + } + } + } + } else MobDeath_Timer -= diff; + } + + if (Event_Timer) + { + if (Event_Timer <= diff) + { + switch(EventPhase) + { + case 0: + DoScriptText(SCRIPT_TEXT5, me);//1 + HandleGameObject(DATA_ARENA4, false); + Start(false, false); + CanWalk = true; + Event_Timer = 0; + break; + case 1: + CanWalk = true; + Event_Timer = 0; + break; + case 2: + Event_Timer = 2000; + break; + case 3: + HandleGameObject(DATA_ARENA1, true); + Event_Timer = 3000; + break; + case 4: + CanWalk = true; + me->SetVisibility(VISIBILITY_OFF); + SummonRingMob(); + Event_Timer = 8000; + break; + case 5: + SummonRingMob(); + SummonRingMob(); + Event_Timer = 8000; + break; + case 6: + SummonRingMob(); + Event_Timer = 0; + break; + case 7: + me->SetVisibility(VISIBILITY_ON); + HandleGameObject(DATA_ARENA1, false); + DoScriptText(SCRIPT_TEXT6, me);//4 + CanWalk = true; + Event_Timer = 0; + break; + case 8: + HandleGameObject(DATA_ARENA2, true); + Event_Timer = 5000; + break; + case 9: + me->SetVisibility(VISIBILITY_OFF); + SummonRingBoss(); + Event_Timer = 0; + break; + case 10: + //if quest, complete + HandleGameObject(DATA_ARENA2, false); + HandleGameObject(DATA_ARENA3, true); + HandleGameObject(DATA_ARENA4, true); + CanWalk = true; + Event_Timer = 0; + break; + } + ++EventPhase; + } else Event_Timer -= diff; + } + + if (CanWalk) + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_grimstone(Creature* pCreature) +{ + return new npc_grimstoneAI(pCreature); +} + +/*###### +## mob_phalanx +######*/ + +enum PhalanxSpells +{ + SPELL_THUNDERCLAP = 8732, + SPELL_FIREBALLVOLLEY = 22425, + SPELL_MIGHTYBLOW = 14099 +}; + +struct mob_phalanxAI : public ScriptedAI +{ + mob_phalanxAI(Creature *c) : ScriptedAI(c) {} + + uint32 ThunderClap_Timer; + uint32 FireballVolley_Timer; + uint32 MightyBlow_Timer; + + void Reset() + { + ThunderClap_Timer = 12000; + FireballVolley_Timer =0; + MightyBlow_Timer = 15000; + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ThunderClap_Timer + if (ThunderClap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + ThunderClap_Timer = 10000; + } else ThunderClap_Timer -= diff; + + //FireballVolley_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + if (FireballVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALLVOLLEY); + FireballVolley_Timer = 15000; + } else FireballVolley_Timer -= diff; + } + + //MightyBlow_Timer + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTYBLOW); + MightyBlow_Timer = 10000; + } else MightyBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_phalanx(Creature* pCreature) +{ + return new mob_phalanxAI (pCreature); +} + +/*###### +## npc_kharan_mighthammer +######*/ + +enum KharamQuests +{ + QUEST_4001 = 4001, + QUEST_4342 = 4342 +}; + +#define GOSSIP_ITEM_KHARAN_1 "I need to know where the princess are, Kharan!" +#define GOSSIP_ITEM_KHARAN_2 "All is not lost, Kharan!" + +#define GOSSIP_ITEM_KHARAN_3 "Gor'shak is my friend, you can trust me." +#define GOSSIP_ITEM_KHARAN_4 "Not enough, you need to tell me more." +#define GOSSIP_ITEM_KHARAN_5 "So what happened?" +#define GOSSIP_ITEM_KHARAN_6 "Continue..." +#define GOSSIP_ITEM_KHARAN_7 "So you suspect that someone on the inside was involved? That they were tipped off?" +#define GOSSIP_ITEM_KHARAN_8 "Continue with your story please." +#define GOSSIP_ITEM_KHARAN_9 "Indeed." +#define GOSSIP_ITEM_KHARAN_10 "The door is open, Kharan. You are a free man." + +bool GossipHello_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_4001) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (pPlayer->GetQuestStatus(4342) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + + if (pPlayer->GetTeam() == HORDE) + pPlayer->SEND_GOSSIP_MENU(2473, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(2474, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(2475, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(2476, pCreature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(2477, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(2478, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(2479, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + pPlayer->SEND_GOSSIP_MENU(2480, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); + pPlayer->SEND_GOSSIP_MENU(2481, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+8: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); + pPlayer->SEND_GOSSIP_MENU(2482, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+9: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pPlayer->GetTeam() == HORDE) + pPlayer->AreaExploredOrEventHappens(QUEST_4001); + else + pPlayer->AreaExploredOrEventHappens(QUEST_4342); + break; + } + return true; +} + +/*###### +## npc_lokhtos_darkbargainer +######*/ + +enum LokhtosItems +{ + ITEM_THRORIUM_BROTHERHOOD_CONTRACT = 18628, + ITEM_SULFURON_INGOT = 17203 +}; + +enum LokhtosQuests +{ + QUEST_A_BINDING_CONTRACT = 7604 +}; + +enum LokhtosSpells +{ + SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059 +}; + +#define GOSSIP_ITEM_SHOW_ACCESS "Show me what I have access to, Lothos." +#define GOSSIP_ITEM_GET_CONTRACT "Get Thorium Brotherhood Contract" + +bool GossipHello_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor() && pPlayer->GetReputationRank(59) >= REP_FRIENDLY) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_ITEM_SHOW_ACCESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (pPlayer->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 && + !pPlayer->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) && + pPlayer->HasItemCount(ITEM_SULFURON_INGOT, 1)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GET_CONTRACT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + } + + if (pPlayer->GetReputationRank(59) < REP_FRIENDLY) + pPlayer->SEND_GOSSIP_MENU(3673, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(3677, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false); + } + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_dughal_stormwing +######*/ + +enum DughalQuests +{ + QUEST_JAIL_BREAK = 4322 +}; + +#define SAY_DUGHAL_FREE "Thank you, $N! I'm free!!!" +#define GOSSIP_DUGHAL "You're free, Dughal! Get out of here!" + +/* +struct npc_dughal_stormwingAI : public npc_escortAI +{ + npc_dughal_stormwingAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + switch(i) + { + case 0:me->Say(SAY_DUGHAL_FREE, LANG_UNIVERSAL, PlayerGUID); break; + case 1:pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_OBJECTIVE_COMPLETED);break; + case 2: + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_ENDED); + break; + } + } + + void EnterCombat(Unit* who) {} + void Reset() {} + + void JustDied(Unit* killer) + { + if (IsBeingEscorted && killer == me) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_ENDED); + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; + if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_ENDED) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_dughal_stormwing(Creature* pCreature) +{ + npc_dughal_stormwingAI* dughal_stormwingAI = new npc_dughal_stormwingAI(pCreature); + + dughal_stormwingAI->AddWaypoint(0, 280.42,-82.86, -77.12,0); + dughal_stormwingAI->AddWaypoint(1, 287.64,-87.01, -76.79,0); + dughal_stormwingAI->AddWaypoint(2, 354.63,-64.95, -67.53,0); + + return dughal_stormwingAI; +} +bool GossipHello_npc_dughal_stormwing(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUGHAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2846, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_dughal_stormwing(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, true, pPlayer->GetGUID()); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_IN_PROGRESS); + } + return true; +} + */ +/*###### +## npc_marshal_windsor +######*/ + +#define SAY_WINDSOR_AGGRO1 "You locked up the wrong Marshal. Prepare to be destroyed!" +#define SAY_WINDSOR_AGGRO2 "I bet you're sorry now, aren't you !?!!" +#define SAY_WINDSOR_AGGRO3 "You better hold me back $N or they are going to feel some prison house beatings." +#define SAY_WINDSOR_1 "Let's get a move on. My gear should be in the storage area up this way..." +#define SAY_WINDSOR_4_1 "Check that cell, $N. If someone is alive in there, we need to get them out." +#define SAY_WINDSOR_4_2 "Get him out of there!" +#define SAY_WINDSOR_4_3 "Good work! We're almost there, $N. This way." +#define SAY_WINDSOR_6 "This is it, $N. My stuff should be in that room. Cover me, I'm going in!" +#define SAY_WINDSOR_9 "Ah, there it is!" +#define MOB_ENTRY_REGINALD_WINDSOR 9682 + +Player* pPlayerStart; +/* +struct npc_marshal_windsorAI : public npc_escortAI +{ + npc_marshal_windsorAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 1: + me->Say(SAY_WINDSOR_1, LANG_UNIVERSAL, PlayerGUID); + break; + case 7: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_WINDSOR_4_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 10: + me->setFaction(534); + break; + case 12: + me->Say(SAY_WINDSOR_6, LANG_UNIVERSAL, PlayerGUID); + pInstance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_IN_PROGRESS); + break; + case 13: + me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK + break; + case 14: + pInstance->SetData(DATA_GATE_SR,0); + me->setFaction(11); + break; + case 16: + me->Say(SAY_WINDSOR_9, LANG_UNIVERSAL, PlayerGUID); + break; + case 17: + me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK + break; + case 18: + pInstance->SetData(DATA_GATE_SC,0); + break; + case 19: + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SummonCreature(MOB_ENTRY_REGINALD_WINDSOR,403.61,-51.71,-63.92,3.600434,TEMPSUMMON_DEAD_DESPAWN ,0); + pInstance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_ENDED); + break; + } + } + + void EnterCombat(Unit* who) + { + switch (urand(0,2)) + { + case 0: me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); break; + case 1: me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); break; + case 2: me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); break; + } + } + + void Reset() {} + + void JustDied(Unit *slayer) + { + pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_FAILED); + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; + if (pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) + SetEscortPaused(false); + if (!pInstance->GetData(DATA_GATE_D) && pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_NOT_STARTED) + { + me->Say(SAY_WINDSOR_4_2, LANG_UNIVERSAL, PlayerGUID); + pInstance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_BEFORE_START); + } + if (pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) + { + me->Say(SAY_WINDSOR_4_3, LANG_UNIVERSAL, PlayerGUID); + pInstance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); + } + if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_SUPPLY_ROOM) == ENCOUNTER_STATE_ENDED) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_marshal_windsor(Creature* pCreature) +{ + npc_marshal_windsorAI* marshal_windsorAI = new npc_marshal_windsorAI(pCreature); + + marshal_windsorAI->AddWaypoint(0, 316.336,-225.528, -77.7258,7000); + marshal_windsorAI->AddWaypoint(1, 316.336,-225.528, -77.7258,2000); + marshal_windsorAI->AddWaypoint(2, 322.96,-207.13, -77.87,0); + marshal_windsorAI->AddWaypoint(3, 281.05,-172.16, -75.12,0); + marshal_windsorAI->AddWaypoint(4, 272.19,-139.14, -70.61,0); + marshal_windsorAI->AddWaypoint(5, 283.62,-116.09, -70.21,0); + marshal_windsorAI->AddWaypoint(6, 296.18,-94.30, -74.08,0); + marshal_windsorAI->AddWaypoint(7, 294.57,-93.11, -74.08,0); + marshal_windsorAI->AddWaypoint(8, 314.31,-74.31, -76.09,0); + marshal_windsorAI->AddWaypoint(9, 360.22,-62.93, -66.77,0); + marshal_windsorAI->AddWaypoint(10, 383.38,-69.40, -63.25,0); + marshal_windsorAI->AddWaypoint(11, 389.99,-67.86, -62.57,0); + marshal_windsorAI->AddWaypoint(12, 400.98,-72.01, -62.31,0); + marshal_windsorAI->AddWaypoint(13, 404.22,-62.30, -63.50,2300); + marshal_windsorAI->AddWaypoint(14, 404.22,-62.30, -63.50,1500); + marshal_windsorAI->AddWaypoint(15, 407.65,-51.86, -63.96,0); + marshal_windsorAI->AddWaypoint(16, 403.61,-51.71, -63.92,1000); + marshal_windsorAI->AddWaypoint(17, 403.61,-51.71, -63.92,2000); + marshal_windsorAI->AddWaypoint(18, 403.61,-51.71, -63.92,1000); + marshal_windsorAI->AddWaypoint(19, 403.61,-51.71, -63.92,0); + + return marshal_windsorAI; +} + +bool QuestAccept_npc_marshal_windsor(Player* pPlayer, Creature* pCreature, Quest const *quest) +{ + if (quest->GetQuestId() == 4322) + {PlayerStart = player; + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) + { + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_IN_PROGRESS); + pCreature->setFaction(11); + } + + } + return false; +} + */ +/*###### +## npc_marshal_reginald_windsor +######*/ + +#define SAY_REGINALD_WINDSOR_0_1 "Can you feel the power, $N??? It's time to ROCK!" +#define SAY_REGINALD_WINDSOR_0_2 "Now we just have to free Tobias and we can get out of here. This way!" +#define SAY_REGINALD_WINDSOR_5_1 "Open it." +#define SAY_REGINALD_WINDSOR_5_2 "I never did like those two. Let's get moving." +#define SAY_REGINALD_WINDSOR_7_1 "Open it and be careful this time!" +#define SAY_REGINALD_WINDSOR_7_2 "That intolerant dirtbag finally got what was coming to him. Good riddance!" +#define SAY_REGINALD_WINDSOR_7_3 "Alright, let's go." +#define SAY_REGINALD_WINDSOR_13_1 "Open it. We need to hurry up. I can smell those Dark Irons coming a mile away and I can tell you one thing, they're COMING!" +#define SAY_REGINALD_WINDSOR_13_2 "Administering fists of fury on Crest Killer!" +#define SAY_REGINALD_WINDSOR_13_3 "He has to be in the last cell. Unless... they killed him." +#define SAY_REGINALD_WINDSOR_14_1 "Get him out of there!" +#define SAY_REGINALD_WINDSOR_14_2 "Excellent work, $N. Let's find the exit. I think I know the way. Follow me!" +#define SAY_REGINALD_WINDSOR_20_1 "We made it!" +#define SAY_REGINALD_WINDSOR_20_2 "Meet me at Maxwell's encampment. We'll go over the next stages of the plan there and figure out a way to decode my tablets without the decryption ring." +#define MOB_ENTRY_SHILL_DINGER 9678 +#define MOB_ENTRY_CREST_KILLER 9680 + +int wp = 0; +/* +struct npc_marshal_reginald_windsorAI : public npc_escortAI +{ + npc_marshal_reginald_windsorAI(Creature *c) : npc_escortAI(c) + { + } + + void WaypointReached(uint32 i) + { + wp=i; + switch(i) + { + case 0: + me->setFaction(11); + me->Say(SAY_REGINALD_WINDSOR_0_1, LANG_UNIVERSAL, PlayerGUID); + break; + case 1: + me->Say(SAY_REGINALD_WINDSOR_0_2, LANG_UNIVERSAL, PlayerGUID); + break; + case 7: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_REGINALD_WINDSOR_5_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 8: + me->Say(SAY_REGINALD_WINDSOR_5_2, LANG_UNIVERSAL, PlayerGUID); + break; + case 11: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_REGINALD_WINDSOR_7_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 12: + me->Say(SAY_REGINALD_WINDSOR_7_2, LANG_UNIVERSAL, PlayerGUID); + break; + case 13: + me->Say(SAY_REGINALD_WINDSOR_7_3, LANG_UNIVERSAL, PlayerGUID); + break; + case 20: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_REGINALD_WINDSOR_13_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 21: + me->Say(SAY_REGINALD_WINDSOR_13_3, LANG_UNIVERSAL, PlayerGUID); + break; + case 23: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_REGINALD_WINDSOR_14_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 24: + me->Say(SAY_REGINALD_WINDSOR_14_2, LANG_UNIVERSAL, PlayerGUID); + break; + case 31: + me->Say(SAY_REGINALD_WINDSOR_20_1, LANG_UNIVERSAL, PlayerGUID); + break; + case 32: + me->Say(SAY_REGINALD_WINDSOR_20_2, LANG_UNIVERSAL, PlayerGUID); + PlayerStart->GroupEventHappens(QUEST_JAIL_BREAK, me); + pInstance->SetData(DATA_SHILL, ENCOUNTER_STATE_ENDED); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + if (who->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(who)->GetQuestStatus(4322) == QUEST_STATUS_INCOMPLETE) + { + float Radius = 10.0; + if (me->IsWithinDistInMap(who, Radius)) + { + SetEscortPaused(false); + Start(true, false, who->GetGUID()); + } + } + } + } + + void EnterCombat(Unit* who) + { + switch (urand(0,2)) + { + case 0: me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); break; + case 1: me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); break; + case 2: me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); break; + } + } + void Reset() {} + + void JustDied(Unit *slayer) + { + pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_FAILED); + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; + if (wp == 7) + { + if (!pInstance->GetData(DATA_GATE_J) && pInstance->GetData(DATA_JAZ) == ENCOUNTER_STATE_NOT_STARTED) + { + pInstance->SetData(DATA_CREATURE_JAZ,1); + pInstance->SetData(DATA_JAZ,ENCOUNTER_STATE_IN_PROGRESS); + } + if (pInstance->GetData(DATA_CREATURE_JAZ) && pInstance->GetData(DATA_CREATURE_OGRABISI) && pInstance->GetData(DATA_JAZ) == ENCOUNTER_STATE_IN_PROGRESS) + { + SetEscortPaused(false); + pInstance->SetData(DATA_JAZ,ENCOUNTER_STATE_ENDED); + } + } + else if (wp == 11) + { + if (!pInstance->GetData(DATA_GATE_S) && pInstance->GetData(DATA_SHILL) == ENCOUNTER_STATE_NOT_STARTED) + { + pInstance->SetData(DATA_CREATURE_SHILL,1); + pInstance->SetData(DATA_SHILL,ENCOUNTER_STATE_IN_PROGRESS); + } + if (pInstance->GetData(DATA_CREATURE_SHILL) && pInstance->GetData(DATA_SHILL) == ENCOUNTER_STATE_IN_PROGRESS) + { + pInstance->SetData(DATA_SHILL,ENCOUNTER_STATE_ENDED); + SetEscortPaused(false); + } + } + else if (wp == 20) + { + if (!pInstance->GetData(DATA_GATE_C) && pInstance->GetData(DATA_CREST) == ENCOUNTER_STATE_NOT_STARTED) + { + pInstance->SetData(DATA_CREATURE_CREST,1); + me->Say(SAY_REGINALD_WINDSOR_13_2, LANG_UNIVERSAL, PlayerGUID); + pInstance->SetData(DATA_CREST,ENCOUNTER_STATE_IN_PROGRESS); + } + if (pInstance->GetData(DATA_CREATURE_CREST) && pInstance->GetData(DATA_CREST) == ENCOUNTER_STATE_IN_PROGRESS) + { + SetEscortPaused(false); + pInstance->SetData(DATA_CREST,ENCOUNTER_STATE_ENDED); + } + } + if (pInstance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) SetEscortPaused(false); + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_marshal_reginald_windsor(Creature* pCreature) +{ + npc_marshal_reginald_windsorAI* marshal_reginald_windsorAI = new npc_marshal_reginald_windsorAI(pCreature); + + marshal_reginald_windsorAI->AddWaypoint(0, 403.61,-52.71, -63.92,4000); + marshal_reginald_windsorAI->AddWaypoint(1, 403.61,-52.71, -63.92,4000); + marshal_reginald_windsorAI->AddWaypoint(2, 406.33,-54.87, -63.95,0); + marshal_reginald_windsorAI->AddWaypoint(3, 407.99,-73.91, -62.26,0); + marshal_reginald_windsorAI->AddWaypoint(4, 557.03,-119.71, -61.83,0); + marshal_reginald_windsorAI->AddWaypoint(5, 573.40,-124.39, -65.07,0); + marshal_reginald_windsorAI->AddWaypoint(6, 593.91,-130.29, -69.25,0); + marshal_reginald_windsorAI->AddWaypoint(7, 593.21,-132.16, -69.25,0); + marshal_reginald_windsorAI->AddWaypoint(8, 593.21,-132.16, -69.25,3000); + marshal_reginald_windsorAI->AddWaypoint(9, 622.81,-135.55, -71.92,0); + marshal_reginald_windsorAI->AddWaypoint(10, 634.68,-151.29, -70.32,0); + marshal_reginald_windsorAI->AddWaypoint(11, 635.06,-153.25, -70.32,0); + marshal_reginald_windsorAI->AddWaypoint(12, 635.06,-153.25, -70.32,3000); + marshal_reginald_windsorAI->AddWaypoint(13, 635.06,-153.25, -70.32,1500); + marshal_reginald_windsorAI->AddWaypoint(14, 655.25,-172.39, -73.72,0); + marshal_reginald_windsorAI->AddWaypoint(15, 654.79,-226.30, -83.06,0); + marshal_reginald_windsorAI->AddWaypoint(16, 622.85,-268.85, -83.96,0); + marshal_reginald_windsorAI->AddWaypoint(17, 579.45,-275.56, -80.44,0); + marshal_reginald_windsorAI->AddWaypoint(18, 561.19,-266.85, -75.59,0); + marshal_reginald_windsorAI->AddWaypoint(19, 547.91,-253.92, -70.34,0); + marshal_reginald_windsorAI->AddWaypoint(20, 549.20,-252.40, -70.34,0); + marshal_reginald_windsorAI->AddWaypoint(21, 549.20,-252.40, -70.34,4000); + marshal_reginald_windsorAI->AddWaypoint(22, 555.33,-269.16, -74.40,0); + marshal_reginald_windsorAI->AddWaypoint(23, 554.31,-270.88, -74.40,0); + marshal_reginald_windsorAI->AddWaypoint(24, 554.31,-270.88, -74.40,4000); + marshal_reginald_windsorAI->AddWaypoint(25, 536.10,-249.60, -67.47,0); + marshal_reginald_windsorAI->AddWaypoint(26, 520.94,-216.65, -59.28,0); + marshal_reginald_windsorAI->AddWaypoint(27, 505.99,-148.74, -62.17,0); + marshal_reginald_windsorAI->AddWaypoint(28, 484.21,-56.24, -62.43,0); + marshal_reginald_windsorAI->AddWaypoint(29, 470.39,-6.01, -70.10,0); + marshal_reginald_windsorAI->AddWaypoint(30, 451.27,30.85, -70.07,0); + marshal_reginald_windsorAI->AddWaypoint(31, 452.45,29.85, -70.37,1500); + marshal_reginald_windsorAI->AddWaypoint(32, 452.45,29.85, -70.37,7000); + marshal_reginald_windsorAI->AddWaypoint(33, 452.45,29.85, -70.37,10000); + marshal_reginald_windsorAI->AddWaypoint(34, 451.27,31.85, -70.07,0); + + return marshal_reginald_windsorAI; +} +*/ +/*###### +## npc_tobias_seecher +######*/ + +#define SAY_TOBIAS_FREE "Thank you! I will run for safety immediately!" +/* +struct npc_tobias_seecherAI : public npc_escortAI +{ + npc_tobias_seecherAI(Creature *c) :npc_escortAI(c) {} + + void EnterCombat(Unit* who) {} + void Reset() {} + + void JustDied(Unit* killer) + { + if (IsBeingEscorted && killer == me) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_ENDED); + } + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 0:me->Say(SAY_TOBIAS_FREE, LANG_UNIVERSAL, PlayerGUID); break; + case 2: + pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_OBJECTIVE_COMPLETED);break; + case 4: + me->SetVisibility(VISIBILITY_OFF); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_ENDED); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; + if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_ENDED) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_tobias_seecher(Creature* pCreature) +{ + npc_tobias_seecherAI* tobias_seecherAI = new npc_tobias_seecherAI(pCreature); + + tobias_seecherAI->AddWaypoint(0, 549.21, -281.07, -75.27); + tobias_seecherAI->AddWaypoint(1, 554.39, -267.39, -73.68); + tobias_seecherAI->AddWaypoint(2, 533.59, -249.38, -67.04); + tobias_seecherAI->AddWaypoint(3, 519.44, -217.02, -59.34); + tobias_seecherAI->AddWaypoint(4, 506.55, -153.49, -62.34); + + return tobias_seecherAI; +} + +bool GossipHello_npc_tobias_seecher(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Get out of here, Tobias, you're free!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2847, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_tobias_seecher(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, true, pPlayer->GetGUID()); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_IN_PROGRESS); + } + return true; +} +*/ + +/*###### +## npc_rocknot +######*/ + +enum RocknotSays +{ + SAY_GOT_BEER = -1230000 +}; + +enum RocknotSpells +{ + SPELL_DRUNKEN_RAGE = 14872 +}; + +enum RocknotQuests +{ + QUEST_ALE = 4295 +}; + +struct npc_rocknotAI : public npc_escortAI +{ + npc_rocknotAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 BreakKeg_Timer; + uint32 BreakDoor_Timer; + + void Reset() + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + BreakKeg_Timer = 0; + BreakDoor_Timer = 0; + } + + void DoGo(uint32 id, uint32 state) + { + if (GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(id))) + pGo->SetGoState((GOState)state); + } + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch(i) + { + case 1: + me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); + break; + case 2: + me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); + break; + case 3: + me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); + break; + case 4: + me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); + break; + case 5: + me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); + BreakKeg_Timer = 2000; + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (BreakKeg_Timer) + { + if (BreakKeg_Timer <= diff) + { + DoGo(DATA_GO_BAR_KEG,0); + BreakKeg_Timer = 0; + BreakDoor_Timer = 1000; + } else BreakKeg_Timer -= diff; + } + + if (BreakDoor_Timer) + { + if (BreakDoor_Timer <= diff) + { + DoGo(DATA_GO_BAR_DOOR,2); + DoGo(DATA_GO_BAR_KEG_TRAP,0); //doesn't work very well, leaving code here for future + //spell by trap has effect61, this indicate the bar go hostile + + if (Unit *tmp = Unit::GetUnit(*me,pInstance->GetData64(DATA_PHALANX))) + tmp->setFaction(14); + + //for later, this event(s) has alot more to it. + //optionally, DONE can trigger bar to go hostile. + pInstance->SetData(TYPE_BAR,DONE); + + BreakDoor_Timer = 0; + } else BreakDoor_Timer -= diff; + } + + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_rocknot(Creature* pCreature) +{ + return new npc_rocknotAI(pCreature); +} + +bool ChooseReward_npc_rocknot(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest, uint32 /*item*/) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (!pInstance) + return true; + + if (pInstance->GetData(TYPE_BAR) == DONE || pInstance->GetData(TYPE_BAR) == SPECIAL) + return true; + + if (_Quest->GetQuestId() == QUEST_ALE) + { + if (pInstance->GetData(TYPE_BAR) != IN_PROGRESS) + pInstance->SetData(TYPE_BAR,IN_PROGRESS); + + pInstance->SetData(TYPE_BAR,SPECIAL); + + //keep track of amount in instance script, returns SPECIAL if amount ok and event in progress + if (pInstance->GetData(TYPE_BAR) == SPECIAL) + { + DoScriptText(SAY_GOT_BEER, pCreature); + pCreature->CastSpell(pCreature,SPELL_DRUNKEN_RAGE,false); + if (npc_escortAI* pEscortAI = CAST_AI(npc_rocknotAI, pCreature->AI())) + pEscortAI->Start(false, false); + } + } + + return true; +} + +/*###### +## +######*/ + +void AddSC_blackrock_depths() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_shadowforge_brazier"; + newscript->pGOHello = &GOHello_go_shadowforge_brazier; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_ring_of_law"; + newscript->pAreaTrigger = &AreaTrigger_at_ring_of_law; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_grimstone"; + newscript->GetAI = &GetAI_npc_grimstone; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phalanx"; + newscript->GetAI = &GetAI_mob_phalanx; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_kharan_mighthammer"; + newscript->pGossipHello = &GossipHello_npc_kharan_mighthammer; + newscript->pGossipSelect = &GossipSelect_npc_kharan_mighthammer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lokhtos_darkbargainer"; + newscript->pGossipHello = &GossipHello_npc_lokhtos_darkbargainer; + newscript->pGossipSelect = &GossipSelect_npc_lokhtos_darkbargainer; + newscript->RegisterSelf(); +/* + newscript = new Script; + newscript->Name = "npc_dughal_stormwing"; + newscript->pGossipHello = &GossipHello_npc_dughal_stormwing; + newscript->pGossipSelect = &GossipSelect_npc_dughal_stormwing; + newscript->GetAI = &GetAI_npc_dughal_stormwing; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tobias_seecher"; + newscript->pGossipHello = &GossipHello_npc_tobias_seecher; + newscript->pGossipSelect = &GossipSelect_npc_tobias_seecher; + newscript->GetAI = &GetAI_npc_tobias_seecher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_marshal_windsor"; + newscript->pQuestAccept = &QuestAccept_npc_marshal_windsor; + newscript->GetAI = &GetAI_npc_marshal_windsor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_marshal_reginald_windsor"; + newscript->GetAI = &GetAI_npc_marshal_reginald_windsor; + newscript->RegisterSelf(); +*/ + newscript = new Script; + newscript->Name = "npc_rocknot"; + newscript->GetAI = &GetAI_npc_rocknot; + newscript->pChooseReward = &ChooseReward_npc_rocknot; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h b/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h new file mode 100644 index 00000000000..edb340252b2 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BRD_H +#define DEF_BRD_H + +#define FACTION_NEUTRAL 734 +#define FACTION_HOSTILE 754 +#define FACTION_FRIEND 35 + +enum eTypes +{ + TYPE_RING_OF_LAW = 1, + TYPE_VAULT = 2, + TYPE_BAR = 3, + TYPE_TOMB_OF_SEVEN = 4, + TYPE_LYCEUM = 5, + TYPE_IRON_HALL = 6, + + DATA_EMPEROR = 10, + DATA_PHALANX = 11, + + DATA_ARENA1 = 12, + DATA_ARENA2 = 13, + DATA_ARENA3 = 14, + DATA_ARENA4 = 15, + + DATA_GO_BAR_KEG = 16, + DATA_GO_BAR_KEG_TRAP = 17, + DATA_GO_BAR_DOOR = 18, + DATA_GO_CHALICE = 19, + + DATA_GHOSTKILL = 20, + DATA_EVENSTARTER = 21, + + DATA_GOLEM_DOOR_N = 22, + DATA_GOLEM_DOOR_S = 23, + + DATA_THRONE_DOOR = 24, + + DATA_SF_BRAZIER_N = 25, + DATA_SF_BRAZIER_S = 26 +}; +#endif diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp new file mode 100644 index 00000000000..a387e816951 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ambassador_Flamelash +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_FIREBLAST = 15573 +}; + +struct boss_ambassador_flamelashAI : public ScriptedAI +{ + boss_ambassador_flamelashAI(Creature *c) : ScriptedAI(c) {} + + uint32 FireBlast_Timer; + uint32 Spirit_Timer; + + void Reset() + { + FireBlast_Timer = 2000; + Spirit_Timer = 24000; + } + + void EnterCombat(Unit * /*who*/) {} + + void SummonSpirits(Unit* victim) + { + if (Creature *Spirit = DoSpawnCreature(9178, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) + Spirit->AI()->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FireBlast_Timer + if (FireBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBLAST); + FireBlast_Timer = 7000; + } else FireBlast_Timer -= diff; + + //Spirit_Timer + if (Spirit_Timer <= diff) + { + SummonSpirits(me->getVictim()); + SummonSpirits(me->getVictim()); + SummonSpirits(me->getVictim()); + SummonSpirits(me->getVictim()); + + Spirit_Timer = 30000; + } else Spirit_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ambassador_flamelash(Creature* pCreature) +{ + return new boss_ambassador_flamelashAI (pCreature); +} + +void AddSC_boss_ambassador_flamelash() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ambassador_flamelash"; + newscript->GetAI = &GetAI_boss_ambassador_flamelash; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp new file mode 100644 index 00000000000..60e1dec236c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp @@ -0,0 +1,116 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Anubshiah +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_SHADOWBOLT = 17228, + SPELL_CURSEOFTONGUES = 15470, + SPELL_CURSEOFWEAKNESS = 17227, + SPELL_DEMONARMOR = 11735, + SPELL_ENVELOPINGWEB = 15471 +}; + +struct boss_anubshiahAI : public ScriptedAI +{ + boss_anubshiahAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowBolt_Timer; + uint32 CurseOfTongues_Timer; + uint32 CurseOfWeakness_Timer; + uint32 DemonArmor_Timer; + uint32 EnvelopingWeb_Timer; + + void Reset() + { + ShadowBolt_Timer = 7000; + CurseOfTongues_Timer = 24000; + CurseOfWeakness_Timer = 12000; + DemonArmor_Timer = 3000; + EnvelopingWeb_Timer = 16000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLT); + ShadowBolt_Timer = 7000; + } else ShadowBolt_Timer -= diff; + + //CurseOfTongues_Timer + if (CurseOfTongues_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CURSEOFTONGUES); + CurseOfTongues_Timer = 18000; + } else CurseOfTongues_Timer -= diff; + + //CurseOfWeakness_Timer + if (CurseOfWeakness_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); + CurseOfWeakness_Timer = 45000; + } else CurseOfWeakness_Timer -= diff; + + //DemonArmor_Timer + if (DemonArmor_Timer <= diff) + { + DoCast(me, SPELL_DEMONARMOR); + DemonArmor_Timer = 300000; + } else DemonArmor_Timer -= diff; + + //EnvelopingWeb_Timer + if (EnvelopingWeb_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ENVELOPINGWEB); + EnvelopingWeb_Timer = 12000; + } else EnvelopingWeb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_anubshiah(Creature* pCreature) +{ + return new boss_anubshiahAI (pCreature); +} + +void AddSC_boss_anubshiah() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_anubshiah"; + newscript->GetAI = &GetAI_boss_anubshiah; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp new file mode 100644 index 00000000000..29fe219d6ec --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp @@ -0,0 +1,111 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Emperor_Dagran_Thaurissan +SD%Complete: 99 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Yells +{ + SAY_AGGRO = -1230001, + SAY_SLAY = -1230002 +}; + +enum Spells +{ + SPELL_HANDOFTHAURISSAN = 17492, + SPELL_AVATAROFFLAME = 15636 +}; + +struct boss_draganthaurissanAI : public ScriptedAI +{ + boss_draganthaurissanAI(Creature *c) : ScriptedAI(c) {} + + uint32 HandOfThaurissan_Timer; + uint32 AvatarOfFlame_Timer; + //uint32 Counter; + + void Reset() + { + HandOfThaurissan_Timer = 4000; + AvatarOfFlame_Timer = 25000; + //Counter= 0; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + me->CallForHelp(VISIBLE_RANGE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (HandOfThaurissan_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_HANDOFTHAURISSAN); + + //3 Hands of Thaurissan will be casted + //if (Counter < 3) + //{ + // HandOfThaurissan_Timer = 1000; + // ++Counter; + //} + //else + //{ + HandOfThaurissan_Timer = 5000; + //Counter = 0; + //} + } else HandOfThaurissan_Timer -= diff; + + //AvatarOfFlame_Timer + if (AvatarOfFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_AVATAROFFLAME); + AvatarOfFlame_Timer = 18000; + } else AvatarOfFlame_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_draganthaurissan(Creature* pCreature) +{ + return new boss_draganthaurissanAI (pCreature); +} + +void AddSC_boss_draganthaurissan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_emperor_dagran_thaurissan"; + newscript->GetAI = &GetAI_boss_draganthaurissan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp new file mode 100644 index 00000000000..77d69263133 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_General_Angerforge +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_MIGHTYBLOW = 14099, + SPELL_HAMSTRING = 9080, + SPELL_CLEAVE = 20691 +}; + +struct boss_general_angerforgeAI : public ScriptedAI +{ + boss_general_angerforgeAI(Creature *c) : ScriptedAI(c) {} + + uint32 MightyBlow_Timer; + uint32 HamString_Timer; + uint32 Cleave_Timer; + uint32 Adds_Timer; + bool Medics; + + void Reset() + { + MightyBlow_Timer = 8000; + HamString_Timer = 12000; + Cleave_Timer = 16000; + Adds_Timer = 0; + Medics = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonAdds(Unit* victim) + { + if (Creature *SummonedAdd = DoSpawnCreature(8901, irand(-14,14), irand(-14,14), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedAdd->AI()->AttackStart(victim); + } + + void SummonMedics(Unit* victim) + { + if (Creature *SummonedMedic = DoSpawnCreature(8894, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedMedic->AI()->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //MightyBlow_Timer + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTYBLOW); + MightyBlow_Timer = 18000; + } else MightyBlow_Timer -= diff; + + //HamString_Timer + if (HamString_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + HamString_Timer = 15000; + } else HamString_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 9000; + } else Cleave_Timer -= diff; + + //Adds_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 21) + { + if (Adds_Timer <= diff) + { + // summon 3 Adds every 25s + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + + Adds_Timer = 25000; + } else Adds_Timer -= diff; + } + + //Summon Medics + if (!Medics && me->GetHealth()*100 / me->GetMaxHealth() < 21) + { + SummonMedics(me->getVictim()); + SummonMedics(me->getVictim()); + Medics = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_general_angerforge(Creature* pCreature) +{ + return new boss_general_angerforgeAI (pCreature); +} + +void AddSC_boss_general_angerforge() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_general_angerforge"; + newscript->GetAI = &GetAI_boss_general_angerforge; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp new file mode 100644 index 00000000000..886bc3fc909 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp @@ -0,0 +1,84 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gorosh_the_Dervish +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_WHIRLWIND = 15589, + SPELL_MORTALSTRIKE = 24573 +}; + +struct boss_gorosh_the_dervishAI : public ScriptedAI +{ + boss_gorosh_the_dervishAI(Creature *c) : ScriptedAI(c) {} + + uint32 WhirlWind_Timer; + uint32 MortalStrike_Timer; + + void Reset() + { + WhirlWind_Timer = 12000; + MortalStrike_Timer = 22000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //WhirlWind_Timer + if (WhirlWind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + WhirlWind_Timer = 15000; + } else WhirlWind_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 15000; + } else MortalStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gorosh_the_dervish(Creature* pCreature) +{ + return new boss_gorosh_the_dervishAI (pCreature); +} + +void AddSC_boss_gorosh_the_dervish() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gorosh_the_dervish"; + newscript->GetAI = &GetAI_boss_gorosh_the_dervish; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp new file mode 100644 index 00000000000..d3551d38790 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grizzle +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Yells +{ + EMOTE_GENERIC_FRENZY_KILL = -1000001 +}; + +enum Spells +{ + SPELL_GROUNDTREMOR = 6524, + SPELL_FRENZY = 28371 +}; + +struct boss_grizzleAI : public ScriptedAI +{ + boss_grizzleAI(Creature *c) : ScriptedAI(c) {} + + uint32 GroundTremor_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + GroundTremor_Timer = 12000; + Frenzy_Timer =0; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //GroundTremor_Timer + if (GroundTremor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GROUNDTREMOR); + GroundTremor_Timer = 8000; + } else GroundTremor_Timer -= diff; + + //Frenzy_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + if (Frenzy_Timer <= diff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); + + Frenzy_Timer = 15000; + } else Frenzy_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grizzle(Creature* pCreature) +{ + return new boss_grizzleAI (pCreature); +} + +void AddSC_boss_grizzle() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grizzle"; + newscript->GetAI = &GetAI_boss_grizzle; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp new file mode 100644 index 00000000000..2af203826a1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp @@ -0,0 +1,106 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Interrogator_Gerstahn +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_SHADOWWORDPAIN = 10894, + SPELL_MANABURN = 10876, + SPELL_PSYCHICSCREAM = 8122, + SPELL_SHADOWSHIELD = 22417 +}; + +struct boss_high_interrogator_gerstahnAI : public ScriptedAI +{ + boss_high_interrogator_gerstahnAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowWordPain_Timer; + uint32 ManaBurn_Timer; + uint32 PsychicScream_Timer; + uint32 ShadowShield_Timer; + + void Reset() + { + ShadowWordPain_Timer = 4000; + ManaBurn_Timer = 14000; + PsychicScream_Timer = 32000; + ShadowShield_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 7000; + } else ShadowWordPain_Timer -= diff; + + //ManaBurn_Timer + if (ManaBurn_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_MANABURN); + ManaBurn_Timer = 10000; + } else ManaBurn_Timer -= diff; + + //PsychicScream_Timer + if (PsychicScream_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PSYCHICSCREAM); + PsychicScream_Timer = 30000; + } else PsychicScream_Timer -= diff; + + //ShadowShield_Timer + if (ShadowShield_Timer <= diff) + { + DoCast(me, SPELL_SHADOWSHIELD); + ShadowShield_Timer = 25000; + } else ShadowShield_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_high_interrogator_gerstahn(Creature* pCreature) +{ + return new boss_high_interrogator_gerstahnAI (pCreature); +} + +void AddSC_boss_high_interrogator_gerstahn() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_high_interrogator_gerstahn"; + newscript->GetAI = &GetAI_boss_high_interrogator_gerstahn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp new file mode 100644 index 00000000000..2a0cf9be133 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Magmus +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_FIERYBURST = 13900, + SPELL_WARSTOMP = 24375 +}; + +enum eEnums +{ + DATA_THRONE_DOOR = 24 // not id or guid of doors but number of enum in blackrock_depths.h +}; + +struct boss_magmusAI : public ScriptedAI +{ + boss_magmusAI(Creature *c) : ScriptedAI(c) {} + + uint32 FieryBurst_Timer; + uint32 WarStomp_Timer; + + void Reset() + { + FieryBurst_Timer = 5000; + WarStomp_Timer =0; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FieryBurst_Timer + if (FieryBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIERYBURST); + FieryBurst_Timer = 6000; + } else FieryBurst_Timer -= diff; + + //WarStomp_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + if (WarStomp_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WARSTOMP); + WarStomp_Timer = 8000; + } else WarStomp_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + // When he die open door to last chamber + void JustDied(Unit *who) + { + if (ScriptedInstance* pInstance = who->GetInstanceData()) + pInstance->HandleGameObject(pInstance->GetData64(DATA_THRONE_DOOR), true); + } +}; +CreatureAI* GetAI_boss_magmus(Creature* pCreature) +{ + return new boss_magmusAI (pCreature); +} + +void AddSC_boss_magmus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magmus"; + newscript->GetAI = &GetAI_boss_magmus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp new file mode 100644 index 00000000000..1c0ed389287 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moira_Bronzbeard +SD%Complete: 90 +SDComment: Healing of Emperor NYI +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_HEAL = 10917, + SPELL_RENEW = 10929, + SPELL_SHIELD = 10901, + SPELL_MINDBLAST = 10947, + SPELL_SHADOWWORDPAIN = 10894, + SPELL_SMITE = 10934 +}; + +struct boss_moira_bronzebeardAI : public ScriptedAI +{ + boss_moira_bronzebeardAI(Creature *c) : ScriptedAI(c) {} + + uint32 Heal_Timer; + uint32 MindBlast_Timer; + uint32 ShadowWordPain_Timer; + uint32 Smite_Timer; + + void Reset() + { + Heal_Timer = 12000; //These times are probably wrong + MindBlast_Timer = 16000; + ShadowWordPain_Timer = 2000; + Smite_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //MindBlast_Timer + if (MindBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MINDBLAST); + MindBlast_Timer = 14000; + } else MindBlast_Timer -= diff; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 18000; + } else ShadowWordPain_Timer -= diff; + + //Smite_Timer + if (Smite_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SMITE); + Smite_Timer = 10000; + } else Smite_Timer -= diff; + + } +}; +CreatureAI* GetAI_boss_moira_bronzebeard(Creature* pCreature) +{ + return new boss_moira_bronzebeardAI (pCreature); +} + +void AddSC_boss_moira_bronzebeard() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_moira_bronzebeard"; + newscript->GetAI = &GetAI_boss_moira_bronzebeard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp new file mode 100644 index 00000000000..94a37e8da7e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp @@ -0,0 +1,254 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Tomb_Of_Seven +SD%Complete: 90 +SDComment: Learning Smelt Dark Iron if tribute quest rewarded. Missing event. +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" +#include "blackrock_depths.h" + +enum Spells +{ + SPELL_SMELT_DARK_IRON = 14891, + SPELL_LEARN_SMELT = 14894, +}; + +enum Quests +{ + QUEST_SPECTRAL_CHALICE = 4083 +}; + +enum Misc +{ + DATA_SKILLPOINT_MIN = 230 +}; + +#define GOSSIP_ITEM_TEACH_1 "Teach me the art of smelting dark iron" +#define GOSSIP_ITEM_TEACH_2 "Continue..." +#define GOSSIP_ITEM_TEACH_3 "[PH] Continue..." +#define GOSSIP_ITEM_TRIBUTE "I want to pay tribute" + +bool GossipHello_boss_gloomrel(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 1 && pPlayer->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN && !pPlayer->HasSpell(SPELL_SMELT_DARK_IRON)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 0 && pPlayer->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TRIBUTE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_boss_gloomrel(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + pPlayer->SEND_GOSSIP_MENU(2606, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, SPELL_LEARN_SMELT, false); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); + pPlayer->SEND_GOSSIP_MENU(2604, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+22: + pPlayer->CLOSE_GOSSIP_MENU(); + if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) + { + //are 5 minutes expected? go template may have data to despawn when used at quest + pInstance->DoRespawnGameObject(pInstance->GetData64(DATA_GO_CHALICE),MINUTE*5); + } + break; + } + return true; +} + +enum DoomrelSpells +{ + SPELL_SHADOWBOLTVOLLEY = 15245, + SPELL_IMMOLATE = 12742, + SPELL_CURSEOFWEAKNESS = 12493, + SPELL_DEMONARMOR = 13787, + SPELL_SUMMON_VOIDWALKERS = 15092 +}; + +struct boss_doomrelAI : public ScriptedAI +{ + boss_doomrelAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 ShadowVolley_Timer; + uint32 Immolate_Timer; + uint32 CurseOfWeakness_Timer; + uint32 DemonArmor_Timer; + bool Voidwalkers; + + void Reset() + { + ShadowVolley_Timer = 10000; + Immolate_Timer = 18000; + CurseOfWeakness_Timer = 5000; + DemonArmor_Timer = 16000; + Voidwalkers = false; + + me->setFaction(FACTION_FRIEND); + + // was set before event start, so set again + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + + if (pInstance) + if (pInstance->GetData(DATA_GHOSTKILL) >= 7) + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + else + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void EnterEvadeMode() + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + me->LoadCreaturesAddon(); + if (me->isAlive()) + me->GetMotionMaster()->MoveTargetedHome(); + me->SetLootRecipient(NULL); + if (pInstance) + pInstance->SetData64(DATA_EVENSTARTER, 0); + } + + void JustDied(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_GHOSTKILL, 1); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLTVOLLEY); + ShadowVolley_Timer = 12000; + } else ShadowVolley_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_IMMOLATE); + + Immolate_Timer = 25000; + } else Immolate_Timer -= diff; + + //CurseOfWeakness_Timer + if (CurseOfWeakness_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); + CurseOfWeakness_Timer = 45000; + } else CurseOfWeakness_Timer -= diff; + + //DemonArmor_Timer + if (DemonArmor_Timer <= diff) + { + DoCast(me, SPELL_DEMONARMOR); + DemonArmor_Timer = 300000; + } else DemonArmor_Timer -= diff; + + //Summon Voidwalkers + if (!Voidwalkers && me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + DoCast(me->getVictim(), SPELL_SUMMON_VOIDWALKERS, true); + Voidwalkers = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_doomrel(Creature* pCreature) +{ + return new boss_doomrelAI (pCreature); +} + +#define GOSSIP_ITEM_CHALLENGE "Your bondage is at an end, Doom'rel. I challenge you!" +#define GOSSIP_SELECT_DOOMREL "[PH] Continue..." + +bool GossipHello_boss_doomrel(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2601, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_boss_doomrel(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_DOOMREL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(2605, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + //start event here + pCreature->setFaction(FACTION_HOSTILE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pCreature->AI()->AttackStart(pPlayer); + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance) + pInstance->SetData64(DATA_EVENSTARTER,pPlayer->GetGUID()); + break; + } + return true; +} + +void AddSC_boss_tomb_of_seven() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_gloomrel"; + newscript->pGossipHello = &GossipHello_boss_gloomrel; + newscript->pGossipSelect = &GossipSelect_boss_gloomrel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_doomrel"; + newscript->GetAI = &GetAI_boss_doomrel; + newscript->pGossipHello = &GossipHello_boss_doomrel; + newscript->pGossipSelect = &GossipSelect_boss_doomrel; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp new file mode 100644 index 00000000000..7684aa6c6ac --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp @@ -0,0 +1,460 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Blackrock_Depths +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +/* +update `creature_template` set `npcflag`='1',`ScriptName`='npc_dughal_stormwing' where `entry`='9022'; +update `creature_template` set `ScriptName`='npc_marshal_windsor' where `entry`='9023'; +update `creature_template` set `ScriptName`='npc_marshal_reginald_windsor' where `entry`='9682'; +update `creature_template` set `npcflag`='1',`ScriptName`='npc_tobias_seecher' where `entry`='9679'; +update `instance_template` set `script`='instance_blackrock_depths' where `map`='230'; +*/ + +#include "ScriptedPch.h" +#include "blackrock_depths.h" + +#define TIMER_TOMBOFTHESEVEN 15000 + +enum eEnums +{ + MAX_ENCOUNTER = 6, + + NPC_EMPEROR = 9019, + NPC_PHALANX = 9502, + NPC_ANGERREL = 9035, + NPC_DOPEREL = 9040, + NPC_HATEREL = 9034, + NPC_VILEREL = 9036, + NPC_SEETHREL = 9038, + NPC_GLOOMREL = 9037, + NPC_DOOMREL = 9039, + NPC_MAGMUS = 9938, + + GO_ARENA1 = 161525, + GO_ARENA2 = 161522, + GO_ARENA3 = 161524, + GO_ARENA4 = 161523, + GO_SHADOW_LOCK = 161460, + GO_SHADOW_MECHANISM = 161461, + GO_SHADOW_GIANT_DOOR = 157923, + GO_SHADOW_DUMMY = 161516, + GO_BAR_KEG_SHOT = 170607, + GO_BAR_KEG_TRAP = 171941, + GO_BAR_DOOR = 170571, + GO_TOMB_ENTER = 170576, + GO_TOMB_EXIT = 170577, + GO_LYCEUM = 170558, + GO_SF_N = 174745, // Shadowforge Brazier North + GO_SF_S = 174744, // Shadowforge Brazier South + GO_GOLEM_ROOM_N = 170573, // Magmus door North + GO_GOLEM_ROOM_S = 170574, // Magmus door Soutsh + GO_THRONE_ROOM = 170575, // Throne door + + GO_SPECTRAL_CHALICE = 164869, + GO_CHEST_SEVEN = 169243 +}; + +struct instance_blackrock_depths : public ScriptedInstance +{ + instance_blackrock_depths(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 EmperorGUID; + uint64 PhalanxGUID; + uint64 MagmusGUID; + + uint64 GoArena1GUID; + uint64 GoArena2GUID; + uint64 GoArena3GUID; + uint64 GoArena4GUID; + uint64 GoShadowLockGUID; + uint64 GoShadowMechGUID; + uint64 GoShadowGiantGUID; + uint64 GoShadowDummyGUID; + uint64 GoBarKegGUID; + uint64 GoBarKegTrapGUID; + uint64 GoBarDoorGUID; + uint64 GoTombEnterGUID; + uint64 GoTombExitGUID; + uint64 GoLyceumGUID; + uint64 GoSFSGUID; + uint64 GoSFNGUID; + uint64 GoGolemNGUID; + uint64 GoGolemSGUID; + uint64 GoThroneGUID; + uint64 GoChestGUID; + + uint32 BarAleCount; + uint32 GhostKillCount; + uint64 TombBossGUIDs[7]; + uint64 TombEventStarterGUID; + uint32 TombTimer; + uint32 TombEventCounter; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + EmperorGUID = 0; + PhalanxGUID = 0; + MagmusGUID = 0; + + GoArena1GUID = 0; + GoArena2GUID = 0; + GoArena3GUID = 0; + GoArena4GUID = 0; + GoShadowLockGUID = 0; + GoShadowMechGUID = 0; + GoShadowGiantGUID = 0; + GoShadowDummyGUID = 0; + GoBarKegGUID = 0; + GoBarKegTrapGUID = 0; + GoBarDoorGUID = 0; + GoTombEnterGUID = 0; + GoTombExitGUID = 0; + GoLyceumGUID = 0; + GoSFSGUID = 0; + GoSFNGUID = 0; + GoGolemNGUID = 0; + GoGolemSGUID = 0; + GoThroneGUID = 0; + GoChestGUID = 0; + + BarAleCount = 0; + GhostKillCount = 0; + TombEventStarterGUID = 0; + TombTimer = TIMER_TOMBOFTHESEVEN; + TombEventCounter = 0; + + for (uint8 i = 0; i < 7; ++i) + TombBossGUIDs[i] = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_EMPEROR: EmperorGUID = pCreature->GetGUID(); break; + case NPC_PHALANX: PhalanxGUID = pCreature->GetGUID(); break; + case NPC_DOOMREL: TombBossGUIDs[0] = pCreature->GetGUID(); break; + case NPC_DOPEREL: TombBossGUIDs[1] = pCreature->GetGUID(); break; + case NPC_HATEREL: TombBossGUIDs[2] = pCreature->GetGUID(); break; + case NPC_VILEREL: TombBossGUIDs[3] = pCreature->GetGUID(); break; + case NPC_SEETHREL: TombBossGUIDs[4] = pCreature->GetGUID(); break; + case NPC_GLOOMREL: TombBossGUIDs[5] = pCreature->GetGUID(); break; + case NPC_ANGERREL: TombBossGUIDs[6] = pCreature->GetGUID(); break; + case NPC_MAGMUS: + MagmusGUID = pCreature->GetGUID(); + if (!pCreature->isAlive()) + HandleGameObject(GetData64(DATA_THRONE_DOOR), true); // if Magmus is dead open door to last boss + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_ARENA1: GoArena1GUID = pGo->GetGUID(); break; + case GO_ARENA2: GoArena2GUID = pGo->GetGUID(); break; + case GO_ARENA3: GoArena3GUID = pGo->GetGUID(); break; + case GO_ARENA4: GoArena4GUID = pGo->GetGUID(); break; + case GO_SHADOW_LOCK: GoShadowLockGUID = pGo->GetGUID(); break; + case GO_SHADOW_MECHANISM: GoShadowMechGUID = pGo->GetGUID(); break; + case GO_SHADOW_GIANT_DOOR: GoShadowGiantGUID = pGo->GetGUID(); break; + case GO_SHADOW_DUMMY: GoShadowDummyGUID = pGo->GetGUID(); break; + case GO_BAR_KEG_SHOT: GoBarKegGUID = pGo->GetGUID(); break; + case GO_BAR_KEG_TRAP: GoBarKegTrapGUID = pGo->GetGUID(); break; + case GO_BAR_DOOR: GoBarDoorGUID = pGo->GetGUID(); break; + case GO_TOMB_ENTER: GoTombEnterGUID = pGo->GetGUID(); break; + case GO_TOMB_EXIT: + GoTombExitGUID = pGo->GetGUID(); + if (GhostKillCount >= 7) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + case GO_LYCEUM: GoLyceumGUID = pGo->GetGUID(); break; + case GO_SF_S: GoSFSGUID = pGo->GetGUID(); break; + case GO_SF_N: GoSFNGUID = pGo->GetGUID(); break; + case GO_GOLEM_ROOM_N: GoGolemNGUID = pGo->GetGUID(); break; + case GO_GOLEM_ROOM_S: GoGolemSGUID = pGo->GetGUID(); break; + case GO_THRONE_ROOM: GoThroneGUID = pGo->GetGUID(); break; + case GO_CHEST_SEVEN: GoChestGUID = pGo->GetGUID(); break; + } + } + + void SetData64(uint32 type, uint64 data) + { + debug_log("TSCR: Instance Blackrock Depths: SetData64 update (Type: %u Data %u)", type, data); + + switch(type) + { + case DATA_EVENSTARTER: + TombEventStarterGUID = data; + if (!TombEventStarterGUID) + TombOfSevenReset();//reset + else + TombOfSevenStart();//start + break; + } + } + + void SetData(uint32 type, uint32 data) + { + debug_log("TSCR: Instance Blackrock Depths: SetData update (Type: %u Data %u)", type, data); + + switch(type) + { + case TYPE_RING_OF_LAW: + m_auiEncounter[0] = data; + break; + case TYPE_VAULT: + m_auiEncounter[1] = data; + break; + case TYPE_BAR: + if (data == SPECIAL) + ++BarAleCount; + else + m_auiEncounter[2] = data; + break; + case TYPE_TOMB_OF_SEVEN: + m_auiEncounter[3] = data; + break; + case TYPE_LYCEUM: + m_auiEncounter[4] = data; + break; + case TYPE_IRON_HALL: + m_auiEncounter[5] = data; + break; + case DATA_GHOSTKILL: + GhostKillCount += data; + break; + } + + if (data == DONE || GhostKillCount >= 7) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << GhostKillCount; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_RING_OF_LAW: + return m_auiEncounter[0]; + case TYPE_VAULT: + return m_auiEncounter[1]; + case TYPE_BAR: + if (m_auiEncounter[2] == IN_PROGRESS && BarAleCount == 3) + return SPECIAL; + else + return m_auiEncounter[2]; + case TYPE_TOMB_OF_SEVEN: + return m_auiEncounter[3]; + case TYPE_LYCEUM: + return m_auiEncounter[4]; + case TYPE_IRON_HALL: + return m_auiEncounter[5]; + case DATA_GHOSTKILL: + return GhostKillCount; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_EMPEROR: + return EmperorGUID; + case DATA_PHALANX: + return PhalanxGUID; + case DATA_ARENA1: + return GoArena1GUID; + case DATA_ARENA2: + return GoArena2GUID; + case DATA_ARENA3: + return GoArena3GUID; + case DATA_ARENA4: + return GoArena4GUID; + case DATA_GO_BAR_KEG: + return GoBarKegGUID; + case DATA_GO_BAR_KEG_TRAP: + return GoBarKegTrapGUID; + case DATA_GO_BAR_DOOR: + return GoBarDoorGUID; + case DATA_EVENSTARTER: + return TombEventStarterGUID; + case DATA_SF_BRAZIER_N: + return GoSFNGUID; + case DATA_SF_BRAZIER_S: + return GoSFSGUID; + case DATA_THRONE_DOOR: + return GoThroneGUID; + case DATA_GOLEM_DOOR_N: + return GoGolemNGUID; + case DATA_GOLEM_DOOR_S: + return GoGolemSGUID; + } + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> GhostKillCount; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + if (GhostKillCount > 0 && GhostKillCount < 7) + GhostKillCount = 0;//reset tomb of seven event + if (GhostKillCount >= 7) + GhostKillCount = 7; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void TombOfSevenEvent() + { + if (GhostKillCount < 7 && TombBossGUIDs[TombEventCounter]) + { + if (Creature* boss = instance->GetCreature(TombBossGUIDs[TombEventCounter])) + { + boss->setFaction(FACTION_HOSTILE); + boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + if (Unit *pTarget = boss->SelectNearestTarget(500)) + boss->AI()->AttackStart(pTarget); + } + } + } + + void TombOfSevenReset() + { + HandleGameObject(GoTombExitGUID,false);//event reseted, close exit door + HandleGameObject(GoTombEnterGUID,true);//event reseted, open entrance door + for (uint8 i = 0; i < 7; ++i) + { + if (Creature* boss = instance->GetCreature(TombBossGUIDs[i])) + { + if (!boss->isAlive()) + {//do not call EnterEvadeMode(), it will create infinit loops + boss->Respawn(); + boss->RemoveAllAuras(); + boss->DeleteThreatList(); + boss->CombatStop(true); + boss->LoadCreaturesAddon(); + boss->GetMotionMaster()->MoveTargetedHome(); + boss->SetLootRecipient(NULL); + } + boss->setFaction(FACTION_FRIEND); + } + } + GhostKillCount = 0; + TombEventStarterGUID = 0; + TombEventCounter = 0; + TombTimer = TIMER_TOMBOFTHESEVEN; + SetData(TYPE_TOMB_OF_SEVEN, NOT_STARTED); + } + + void TombOfSevenStart() + { + HandleGameObject(GoTombExitGUID,false);//event started, close exit door + HandleGameObject(GoTombEnterGUID,false);//event started, close entrance door + SetData(TYPE_TOMB_OF_SEVEN, IN_PROGRESS); + } + + void TombOfSevenEnd() + { + DoRespawnGameObject(GoChestGUID,DAY); + HandleGameObject(GoTombExitGUID,true);//event done, open exit door + HandleGameObject(GoTombEnterGUID,true);//event done, open entrance door + TombEventStarterGUID = 0; + SetData(TYPE_TOMB_OF_SEVEN, DONE); + } + void Update(uint32 diff) + { + if (TombEventStarterGUID && GhostKillCount < 7) + { + if (TombTimer <= diff) + { + TombTimer = TIMER_TOMBOFTHESEVEN; + ++TombEventCounter; + TombOfSevenEvent(); + // Check Killed bosses + for (uint8 i = 0; i < 7; ++i) + { + if (Creature* boss = instance->GetCreature(TombBossGUIDs[i])) + { + if (!boss->isAlive()) + { + GhostKillCount = i+1; + } + } + } + } else TombTimer -= diff; + } + if (GhostKillCount >= 7 && TombEventStarterGUID) + TombOfSevenEnd(); + } +}; + +InstanceData* GetInstanceData_instance_blackrock_depths(Map* pMap) +{ + return new instance_blackrock_depths(pMap); +} + + void AddSC_instance_blackrock_depths() + { + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blackrock_depths"; + newscript->GetInstanceData = &GetInstanceData_instance_blackrock_depths; + newscript->RegisterSelf(); + } diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp new file mode 100644 index 00000000000..2ea115e6e0b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp @@ -0,0 +1,77 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "blackrock_spire.h" + +enum Creatures +{ + NPC_ROOKERY_WHELP = 10161 +}; + +struct npc_rookey_whelpAI : public ScriptedAI +{ + npc_rookey_whelpAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void JustDied(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(WHELP_DEATH_COUNT, pInstance->GetData(WHELP_DEATH_COUNT)+1); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_rookey_whelp(Creature* pCreature) +{ + return new npc_rookey_whelpAI(pCreature); +} + +bool GOHello_rookey_egg(Player *pPlayer, GameObject * /*pGO*/) +{ + Position pos; + pPlayer->GetPosition(&pos); + pPlayer->SummonCreature(NPC_ROOKERY_WHELP, pos, TEMPSUMMON_TIMED_DESPAWN, 15*IN_MILISECONDS); + //destroy gobject need to be implemented + + return true; +}; + +void AddSC_blackrock_spire() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_rookey_whelp"; + newscript->GetAI = &GetAI_rookey_whelp; + newscript->RegisterSelf(); + newscript = new Script; + + newscript->Name = "go_rookey_egg"; + newscript->pGOHello = &GOHello_rookey_egg; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h new file mode 100644 index 00000000000..56b6e0cbe23 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_BRS_H +#define DEF_BRS_H + +enum Data +{ + EVENT_LEEEROY, + WHELP_DEATH_COUNT +}; + +#endif diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp new file mode 100644 index 00000000000..b53ddaf23ef --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp @@ -0,0 +1,102 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Drakkisath +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FIRENOVA 23462 +#define SPELL_CLEAVE 20691 +#define SPELL_CONFLIGURATION 16805 +#define SPELL_THUNDERCLAP 15548 //Not sure if right ID. 23931 would be a harder possibility. + +struct boss_drakkisathAI : public ScriptedAI +{ + boss_drakkisathAI(Creature *c) : ScriptedAI(c) {} + + uint32 FireNova_Timer; + uint32 Cleave_Timer; + uint32 Confliguration_Timer; + uint32 Thunderclap_Timer; + + void Reset() + { + FireNova_Timer = 6000; + Cleave_Timer = 8000; + Confliguration_Timer = 15000; + Thunderclap_Timer = 17000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FireNova_Timer + if (FireNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRENOVA); + FireNova_Timer = 10000; + } else FireNova_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 8000; + } else Cleave_Timer -= diff; + + //Confliguration_Timer + if (Confliguration_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CONFLIGURATION); + Confliguration_Timer = 18000; + } else Confliguration_Timer -= diff; + + //Thunderclap_Timer + if (Thunderclap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + Thunderclap_Timer = 20000; + } else Thunderclap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_drakkisath(Creature* pCreature) +{ + return new boss_drakkisathAI (pCreature); +} + +void AddSC_boss_drakkisath() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_drakkisath"; + newscript->GetAI = &GetAI_boss_drakkisath; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp new file mode 100644 index 00000000000..fcd2ea1a6d0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gyth +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CORROSIVEACID 20667 +#define SPELL_FREEZE 18763 +#define SPELL_FLAMEBREATH 20712 + +struct boss_gythAI : public ScriptedAI +{ + boss_gythAI(Creature *c) : ScriptedAI(c) {} + + uint32 Aggro_Timer; + uint32 Dragons_Timer; + uint32 Orc_Timer; + uint32 CorrosiveAcid_Timer; + uint32 Freeze_Timer; + uint32 Flamebreath_Timer; + uint32 Line1Count; + uint32 Line2Count; + + bool Event; + bool SummonedDragons; + bool SummonedOrcs; + bool SummonedRend; + bool bAggro; + bool RootSelf; + + void Reset() + { + Dragons_Timer = 3000; + Orc_Timer = 60000; + Aggro_Timer = 60000; + CorrosiveAcid_Timer = 8000; + Freeze_Timer = 11000; + Flamebreath_Timer = 4000; + Event = false; + SummonedDragons = false; + SummonedOrcs= false; + SummonedRend = false; + bAggro = false; + RootSelf = false; + + // how many times should the two lines of summoned creatures be spawned + // min 2 x 2, max 7 lines of attack in total + Line1Count = rand() % 4 + 2; + if (Line1Count < 5) + Line2Count = rand() % (5 - Line1Count) + 2; + else + Line2Count = 2; + + //Invisible for event start + me->SetDisplayId(11686); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonCreatureWithRandomTarget(uint32 creatureId) + { + Unit* Summoned = me->SummonCreature(creatureId, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240000); + if (Summoned) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Summoned->AddThreat(pTarget, 1.0f); + } + } + + void UpdateAI(const uint32 diff) + { + //char buf[200]; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!RootSelf) + { + //me->m_canMove = true; + DoCast(me, 33356); + RootSelf = true; + } + + if (!bAggro && Line1Count == 0 && Line2Count == 0) + { + if (Aggro_Timer <= diff) + { + bAggro = true; + // Visible now! + me->SetDisplayId(9723); + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } else Aggro_Timer -= diff; + } + + // Summon Dragon pack. 2 Dragons and 3 Whelps + if (!bAggro && !SummonedRend && Line1Count > 0) + { + if (Dragons_Timer <= diff) + { + SummonCreatureWithRandomTarget(10372); + SummonCreatureWithRandomTarget(10372); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + Line1Count = Line1Count - 1; + Dragons_Timer = 60000; + } else Dragons_Timer -= diff; + } + + //Summon Orc pack. 1 Orc Handler 1 Elite Dragonkin and 3 Whelps + if (!bAggro && !SummonedRend && Line1Count == 0 && Line2Count > 0) + { + if (Orc_Timer <= diff) + { + SummonCreatureWithRandomTarget(10447); + SummonCreatureWithRandomTarget(10317); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + Line2Count = Line2Count - 1; + Orc_Timer = 60000; + } else Orc_Timer -= diff; + } + + // we take part in the fight + if (bAggro) + { + // CorrosiveAcid_Timer + if (CorrosiveAcid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVEACID); + CorrosiveAcid_Timer = 7000; + } else CorrosiveAcid_Timer -= diff; + + // Freeze_Timer + if (Freeze_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FREEZE); + Freeze_Timer = 16000; + } else Freeze_Timer -= diff; + + // Flamebreath_Timer + if (Flamebreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBREATH); + Flamebreath_Timer = 10500; + } else Flamebreath_Timer -= diff; + + //Summon Rend + if (!SummonedRend && me->GetHealth()*100 / me->GetMaxHealth() < 11 + && me->GetHealth() > 0) + { + //summon Rend and Change model to normal Gyth + //Inturrupt any spell casting + me->InterruptNonMeleeSpells(false); + //Gyth model + me->SetDisplayId(9806); + me->SummonCreature(10429, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000); + SummonedRend = true; + } + + DoMeleeAttackIfReady(); + } // end if Aggro + } +}; + +CreatureAI* GetAI_boss_gyth(Creature* pCreature) +{ + return new boss_gythAI (pCreature); +} + +void AddSC_boss_gyth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gyth"; + newscript->GetAI = &GetAI_boss_gyth; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp new file mode 100644 index 00000000000..9e78667717a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp @@ -0,0 +1,96 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Halycon +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CROWDPUMMEL 10887 +#define SPELL_MIGHTYBLOW 14099 + +#define ADD_1X -169.839203 +#define ADD_1Y -324.961395 +#define ADD_1Z 64.401443 +#define ADD_1O 3.124724 + +struct boss_halyconAI : public ScriptedAI +{ + boss_halyconAI(Creature *c) : ScriptedAI(c) {} + + uint32 CrowdPummel_Timer; + uint32 MightyBlow_Timer; + bool Summoned; + + void Reset() + { + CrowdPummel_Timer = 8000; + MightyBlow_Timer = 14000; + Summoned = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //CrowdPummel_Timer + if (CrowdPummel_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CROWDPUMMEL); + CrowdPummel_Timer = 14000; + } else CrowdPummel_Timer -= diff; + + //MightyBlow_Timer + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTYBLOW); + MightyBlow_Timer = 10000; + } else MightyBlow_Timer -= diff; + + //Summon Gizrul + if (!Summoned && me->GetHealth()*100 / me->GetMaxHealth() < 25) + { + me->SummonCreature(10268,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000); + Summoned = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_halycon(Creature* pCreature) +{ + return new boss_halyconAI (pCreature); +} + +void AddSC_boss_halycon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_halycon"; + newscript->GetAI = &GetAI_boss_halycon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp new file mode 100644 index 00000000000..65f1e8081a0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Highlord_Omokk +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_WARSTOMP 24375 +#define SPELL_CLEAVE 15579 +#define SPELL_STRIKE 18368 +#define SPELL_REND 18106 +#define SPELL_SUNDERARMOR 24317 +#define SPELL_KNOCKAWAY 20686 +#define SPELL_SLOW 22356 + +struct boss_highlordomokkAI : public ScriptedAI +{ + boss_highlordomokkAI(Creature *c) : ScriptedAI(c) {} + + uint32 WarStomp_Timer; + uint32 Cleave_Timer; + uint32 Strike_Timer; + uint32 Rend_Timer; + uint32 SunderArmor_Timer; + uint32 KnockAway_Timer; + uint32 Slow_Timer; + + void Reset() + { + WarStomp_Timer = 15000; + Cleave_Timer = 6000; + Strike_Timer = 10000; + Rend_Timer = 14000; + SunderArmor_Timer = 2000; + KnockAway_Timer = 18000; + Slow_Timer = 24000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //WarStomp_Timer + if (WarStomp_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WARSTOMP); + WarStomp_Timer = 14000; + } else WarStomp_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 8000; + } else Cleave_Timer -= diff; + + //Strike_Timer + if (Strike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STRIKE); + Strike_Timer = 10000; + } else Strike_Timer -= diff; + + //Rend_Timer + if (Rend_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REND); + Rend_Timer = 18000; + } else Rend_Timer -= diff; + + //SunderArmor_Timer + if (SunderArmor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDERARMOR); + SunderArmor_Timer = 25000; + } else SunderArmor_Timer -= diff; + + //KnockAway_Timer + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + KnockAway_Timer = 12000; + } else KnockAway_Timer -= diff; + + //Slow_Timer + if (Slow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLOW); + Slow_Timer = 18000; + } else Slow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_highlordomokk(Creature* pCreature) +{ + return new boss_highlordomokkAI (pCreature); +} + +void AddSC_boss_highlordomokk() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_highlord_omokk"; + newscript->GetAI = &GetAI_boss_highlordomokk; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp new file mode 100644 index 00000000000..60dda5a5fab --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp @@ -0,0 +1,87 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mother_Smolderweb +SD%Complete: 100 +SDComment: Uncertain how often mother's milk is casted +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CRYSTALIZE 16104 +#define SPELL_MOTHERSMILK 16468 +#define SPELL_SUMMON_SPIRE_SPIDERLING 16103 + +struct boss_mothersmolderwebAI : public ScriptedAI +{ + boss_mothersmolderwebAI(Creature *c) : ScriptedAI(c) {} + + uint32 Crystalize_Timer; + uint32 MothersMilk_Timer; + + void Reset() + { + Crystalize_Timer = 20000; + MothersMilk_Timer = 10000; + } + + void EnterCombat(Unit * /*who*/) {} + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (me->GetHealth() <= damage) + DoCast(me, SPELL_SUMMON_SPIRE_SPIDERLING, true); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Crystalize_Timer + if (Crystalize_Timer <= diff) + { + DoCast(me, SPELL_CRYSTALIZE); + Crystalize_Timer = 15000; + } else Crystalize_Timer -= diff; + + //MothersMilk_Timer + if (MothersMilk_Timer <= diff) + { + DoCast(me, SPELL_MOTHERSMILK); + MothersMilk_Timer = urand(5000,12500); + } else MothersMilk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_mothersmolderweb(Creature* pCreature) +{ + return new boss_mothersmolderwebAI (pCreature); +} + +void AddSC_boss_mothersmolderweb() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_mother_smolderweb"; + newscript->GetAI = &GetAI_boss_mothersmolderweb; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp new file mode 100644 index 00000000000..8846442705b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp @@ -0,0 +1,126 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Overlord_Wyrmthalak +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_BLASTWAVE 11130 +#define SPELL_SHOUT 23511 +#define SPELL_CLEAVE 20691 +#define SPELL_KNOCKAWAY 20686 + +#define ADD_1X -39.355381 +#define ADD_1Y -513.456482 +#define ADD_1Z 88.472046 +#define ADD_1O 4.679872 + +#define ADD_2X -49.875881 +#define ADD_2Y -511.896942 +#define ADD_2Z 88.195160 +#define ADD_2O 4.613114 + +struct boss_overlordwyrmthalakAI : public ScriptedAI +{ + boss_overlordwyrmthalakAI(Creature *c) : ScriptedAI(c) {} + + uint32 BlastWave_Timer; + uint32 Shout_Timer; + uint32 Cleave_Timer; + uint32 Knockaway_Timer; + bool Summoned; + + void Reset() + { + BlastWave_Timer = 20000; + Shout_Timer = 2000; + Cleave_Timer = 6000; + Knockaway_Timer = 12000; + Summoned = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //BlastWave_Timer + if (BlastWave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLASTWAVE); + BlastWave_Timer = 20000; + } else BlastWave_Timer -= diff; + + //Shout_Timer + if (Shout_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHOUT); + Shout_Timer = 10000; + } else Shout_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //Knockaway_Timer + if (Knockaway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + Knockaway_Timer = 14000; + } else Knockaway_Timer -= diff; + + //Summon two Beserks + if (!Summoned && me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0, 100, true); + + if (Creature *SummonedCreature = me->SummonCreature(9216,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000)) + SummonedCreature->AI()->AttackStart(pTarget); + if (Creature *SummonedCreature = me->SummonCreature(9268,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,300000)) + SummonedCreature->AI()->AttackStart(pTarget); + Summoned = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_overlordwyrmthalak(Creature* pCreature) +{ + return new boss_overlordwyrmthalakAI (pCreature); +} + +void AddSC_boss_overlordwyrmthalak() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_overlord_wyrmthalak"; + newscript->GetAI = &GetAI_boss_overlordwyrmthalak; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp new file mode 100644 index 00000000000..6cbd6955665 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Pyroguard_Emberseer +SD%Complete: 100 +SDComment: Event to activate Emberseer NYI +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FIRENOVA 23462 +#define SPELL_FLAMEBUFFET 23341 +#define SPELL_PYROBLAST 17274 + +struct boss_pyroguard_emberseerAI : public ScriptedAI +{ + boss_pyroguard_emberseerAI(Creature *c) : ScriptedAI(c) {} + + uint32 FireNova_Timer; + uint32 FlameBuffet_Timer; + uint32 PyroBlast_Timer; + + void Reset() + { + FireNova_Timer = 6000; + FlameBuffet_Timer = 3000; + PyroBlast_Timer = 14000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FireNova_Timer + if (FireNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRENOVA); + FireNova_Timer = 6000; + } else FireNova_Timer -= diff; + + //FlameBuffet_Timer + if (FlameBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBUFFET); + FlameBuffet_Timer = 14000; + } else FlameBuffet_Timer -= diff; + + //PyroBlast_Timer + if (PyroBlast_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_PYROBLAST); + PyroBlast_Timer = 15000; + } else PyroBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_pyroguard_emberseer(Creature* pCreature) +{ + return new boss_pyroguard_emberseerAI (pCreature); +} + +void AddSC_boss_pyroguard_emberseer() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_pyroguard_emberseer"; + newscript->GetAI = &GetAI_boss_pyroguard_emberseer; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp new file mode 100644 index 00000000000..9058b35cd5c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Quartmaster_Zigris +SD%Complete: 100 +SDComment: Needs revision +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHOOT 16496 +#define SPELL_STUNBOMB 16497 +#define SPELL_HEALING_POTION 15504 +#define SPELL_HOOKEDNET 15609 + +struct boss_quatermasterzigrisAI : public ScriptedAI +{ + boss_quatermasterzigrisAI(Creature *c) : ScriptedAI(c) {} + + uint32 Shoot_Timer; + uint32 StunBomb_Timer; + //uint32 HelingPotion_Timer; + + void Reset() + { + Shoot_Timer = 1000; + StunBomb_Timer = 16000; + //HelingPotion_Timer = 25000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Shoot_Timer + if (Shoot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHOOT); + Shoot_Timer = 500; + } else Shoot_Timer -= diff; + + //StunBomb_Timer + if (StunBomb_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STUNBOMB); + StunBomb_Timer = 14000; + } else StunBomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_quatermasterzigris(Creature* pCreature) +{ + return new boss_quatermasterzigrisAI (pCreature); +} + +void AddSC_boss_quatermasterzigris() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "quartermaster_zigris"; + newscript->GetAI = &GetAI_boss_quatermasterzigris; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp new file mode 100644 index 00000000000..56de5dbb385 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp @@ -0,0 +1,92 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Rend_Blackhand +SD%Complete: 100 +SDComment: Intro event NYI +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_WHIRLWIND 26038 +#define SPELL_CLEAVE 20691 +#define SPELL_THUNDERCLAP 23931 //Not sure if he cast this spell + +struct boss_rend_blackhandAI : public ScriptedAI +{ + boss_rend_blackhandAI(Creature *c) : ScriptedAI(c) {} + + uint32 WhirlWind_Timer; + uint32 Cleave_Timer; + uint32 Thunderclap_Timer; + + void Reset() + { + WhirlWind_Timer = 20000; + Cleave_Timer = 5000; + Thunderclap_Timer = 9000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //WhirlWind_Timer + if (WhirlWind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + WhirlWind_Timer = 18000; + } else WhirlWind_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 10000; + } else Cleave_Timer -= diff; + + //Thunderclap_Timer + if (Thunderclap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + Thunderclap_Timer = 16000; + } else Thunderclap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_rend_blackhand(Creature* pCreature) +{ + return new boss_rend_blackhandAI (pCreature); +} + +void AddSC_boss_rend_blackhand() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_rend_blackhand"; + newscript->GetAI = &GetAI_boss_rend_blackhand; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp new file mode 100644 index 00000000000..73afc3b5afe --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shadow_Hunter_Voshgajin +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CURSEOFBLOOD 24673 +#define SPELL_HEX 16708 +#define SPELL_CLEAVE 20691 + +struct boss_shadowvoshAI : public ScriptedAI +{ + boss_shadowvoshAI(Creature *c) : ScriptedAI(c) {} + + uint32 CurseOfBlood_Timer; + uint32 Hex_Timer; + uint32 Cleave_Timer; + + void Reset() + { + CurseOfBlood_Timer = 2000; + Hex_Timer = 8000; + Cleave_Timer = 14000; + + //DoCast(me, SPELL_ICEARMOR, true); + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); + CurseOfBlood_Timer = 45000; + } else CurseOfBlood_Timer -= diff; + + //Hex_Timer + if (Hex_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_HEX); + Hex_Timer = 15000; + } else Hex_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_shadowvosh(Creature* pCreature) +{ + return new boss_shadowvoshAI (pCreature); +} + +void AddSC_boss_shadowvosh() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shadow_hunter_voshgajin"; + newscript->GetAI = &GetAI_boss_shadowvosh; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp new file mode 100644 index 00000000000..499f9cf4ce5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_The_Best +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FLAMEBREAK 16785 +#define SPELL_IMMOLATE 20294 +#define SPELL_TERRIFYINGROAR 14100 + +struct boss_thebeastAI : public ScriptedAI +{ + boss_thebeastAI(Creature *c) : ScriptedAI(c) {} + + uint32 Flamebreak_Timer; + uint32 Immolate_Timer; + uint32 TerrifyingRoar_Timer; + + void Reset() + { + Flamebreak_Timer = 12000; + Immolate_Timer = 3000; + TerrifyingRoar_Timer = 23000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Flamebreak_Timer + if (Flamebreak_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBREAK); + Flamebreak_Timer = 10000; + } else Flamebreak_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_IMMOLATE); + Immolate_Timer = 8000; + } else Immolate_Timer -= diff; + + //TerrifyingRoar_Timer + if (TerrifyingRoar_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TERRIFYINGROAR); + TerrifyingRoar_Timer = 20000; + } else TerrifyingRoar_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_thebeast(Creature* pCreature) +{ + return new boss_thebeastAI (pCreature); +} + +void AddSC_boss_thebeast() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_beast"; + newscript->GetAI = &GetAI_boss_thebeast; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp new file mode 100644 index 00000000000..50b47c94fc5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp @@ -0,0 +1,122 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warmaster_Voone +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SNAPKICK 15618 +#define SPELL_CLEAVE 15579 +#define SPELL_UPPERCUT 10966 +#define SPELL_MORTALSTRIKE 16856 +#define SPELL_PUMMEL 15615 +#define SPELL_THROWAXE 16075 + +struct boss_warmastervooneAI : public ScriptedAI +{ + boss_warmastervooneAI(Creature *c) : ScriptedAI(c) {} + + uint32 Snapkick_Timer; + uint32 Cleave_Timer; + uint32 Uppercut_Timer; + uint32 MortalStrike_Timer; + uint32 Pummel_Timer; + uint32 ThrowAxe_Timer; + + void Reset() + { + Snapkick_Timer = 8000; + Cleave_Timer = 14000; + Uppercut_Timer = 20000; + MortalStrike_Timer = 12000; + Pummel_Timer = 32000; + ThrowAxe_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Snapkick_Timer + if (Snapkick_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SNAPKICK); + Snapkick_Timer = 6000; + } else Snapkick_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 12000; + } else Cleave_Timer -= diff; + + //Uppercut_Timer + if (Uppercut_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_UPPERCUT); + Uppercut_Timer = 14000; + } else Uppercut_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 10000; + } else MortalStrike_Timer -= diff; + + //Pummel_Timer + if (Pummel_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PUMMEL); + Pummel_Timer = 16000; + } else Pummel_Timer -= diff; + + //ThrowAxe_Timer + if (ThrowAxe_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THROWAXE); + ThrowAxe_Timer = 8000; + } else ThrowAxe_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_warmastervoone(Creature* pCreature) +{ + return new boss_warmastervooneAI (pCreature); +} + +void AddSC_boss_warmastervoone() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_warmaster_voone"; + newscript->GetAI = &GetAI_boss_warmastervoone; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp new file mode 100644 index 00000000000..f2e2b39fe87 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "blackrock_spire.h" + +enum Achievements +{ + ACHIEV_LEROY_JENKINS = 2188 +}; + +struct instance_blackrock_spire : public ScriptedInstance +{ + instance_blackrock_spire(Map* pMap) : ScriptedInstance(pMap) {} + + uint32 uiLeeroyTimer; + uint32 uiWhelpCount; + uint32 uiLeroyData; + + bool bLeeeeeeeeroy; + + void Initialize() + { + uiLeeroyTimer = 15*IN_MILISECONDS; + uiWhelpCount = 0; + bLeeeeeeeeroy = true; + uiLeroyData = 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case EVENT_LEEEROY: + if (data == DONE) + DoCompleteAchievement(ACHIEV_LEROY_JENKINS); + uiLeroyData = data; + break; + case WHELP_DEATH_COUNT: + if (data == 1) + { + SetData(EVENT_LEEEROY, IN_PROGRESS); + //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Started"); + } + uiWhelpCount = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case EVENT_LEEEROY: return uiLeroyData; + case WHELP_DEATH_COUNT: return uiWhelpCount; + } + return 0; + } + + void Update(uint32 diff) + { + if (GetData(EVENT_LEEEROY) != FAIL && GetData(EVENT_LEEEROY) == IN_PROGRESS) + { + if (uiLeeroyTimer <= diff) + { + SetData(EVENT_LEEEROY, FAIL); + bLeeeeeeeeroy = false; + //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Failed"); + } else uiLeeroyTimer -= diff; + if (uiWhelpCount >= 50 && bLeeeeeeeeroy) + { + SetData(EVENT_LEEEROY, DONE); + //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Success"); + } + } + } +}; + +InstanceData* GetInstanceData_instance_blackrock_spire(Map* pMap) +{ + return new instance_blackrock_spire(pMap); +} + +void AddSC_instance_blackrock_spire() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blackrock_spire"; + newscript->GetInstanceData = &GetInstanceData_instance_blackrock_spire; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp new file mode 100644 index 00000000000..856e1236176 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp @@ -0,0 +1,112 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Broodlord_Lashlayer +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1469000 +#define SAY_LEASH -1469001 + +#define SPELL_CLEAVE 26350 +#define SPELL_BLASTWAVE 23331 +#define SPELL_MORTALSTRIKE 24573 +#define SPELL_KNOCKBACK 25778 + +struct boss_broodlordAI : public ScriptedAI +{ + boss_broodlordAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cleave_Timer; + uint32 BlastWave_Timer; + uint32 MortalStrike_Timer; + uint32 KnockBack_Timer; + + void Reset() + { + Cleave_Timer = 8000; //These times are probably wrong + BlastWave_Timer = 12000; + MortalStrike_Timer = 20000; + KnockBack_Timer = 30000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + // BlastWave + if (BlastWave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLASTWAVE); + BlastWave_Timer = urand(8000,16000); + } else BlastWave_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = urand(25000,35000); + } else MortalStrike_Timer -= diff; + + if (KnockBack_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKBACK); + //Drop 50% aggro + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-50); + + KnockBack_Timer = urand(15000,30000); + } else KnockBack_Timer -= diff; + + if (EnterEvadeIfOutOfCombatArea(diff)) + DoScriptText(SAY_LEASH, me); + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_broodlord(Creature* pCreature) +{ + return new boss_broodlordAI (pCreature); +} + +void AddSC_boss_broodlord() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_broodlord"; + newscript->GetAI = &GetAI_boss_broodlord; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp new file mode 100644 index 00000000000..08bebe95384 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp @@ -0,0 +1,301 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Chromaggus +SD%Complete: 95 +SDComment: Chromatic Mutation disabled due to lack of core support +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +enum Emotes +{ + EMOTE_FRENZY = -1469002, + EMOTE_SHIMMER = -1469003 +}; + +enum Spells +{ + //These spells are actually called elemental shield + //What they do is decrease all damage by 75% then they increase + //One school of damage by 1100% + SPELL_FIRE_VULNERABILITY = 22277, + SPELL_FROST_VULNERABILITY = 22278, + SPELL_SHADOW_VULNERABILITY = 22279, + SPELL_NATURE_VULNERABILITY = 22280, + SPELL_ARCANE_VULNERABILITY = 22281, + //Other spells + SPELL_INCINERATE = 23308, //Incinerate 23308,23309 + SPELL_TIMELAPSE = 23310, //Time lapse 23310, 23311(old threat mod that was removed in 2.01) + SPELL_CORROSIVEACID = 23313, //Corrosive Acid 23313, 23314 + SPELL_IGNITEFLESH = 23315, //Ignite Flesh 23315,23316 + SPELL_FROSTBURN = 23187, //Frost burn 23187, 23189 + //Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them + //Since Scripted spells arn't coded I'll just write a function that does the same thing + SPELL_BROODAF_BLUE = 23153, //Blue affliction 23153 + SPELL_BROODAF_BLACK = 23154, //Black affliction 23154 + SPELL_BROODAF_RED = 23155, //Red affliction 23155 (23168 on death) + SPELL_BROODAF_BRONZE = 23170, //Bronze Affliction 23170 + SPELL_BROODAF_GREEN = 23169, //Brood Affliction Green 23169 + SPELL_CHROMATIC_MUT_1 = 23174, //Spell cast on player if they get all 5 debuffs + SPELL_FRENZY = 28371, //The frenzy spell may be wrong + SPELL_ENRAGE = 28747 +}; + +struct boss_chromaggusAI : public ScriptedAI +{ + boss_chromaggusAI(Creature *c) : ScriptedAI(c) + { + //Select the 2 breaths that we are going to use until despawned + //5 possiblities for the first breath, 4 for the second, 20 total possiblites + //This way we don't end up casting 2 of the same breath + //TL TL would be stupid + switch (urand(0,19)) + { + //B1 - Incin + case 0: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 1: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 2: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 3: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - TL + case 4: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_INCINERATE; + break; + case 5: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 6: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 7: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Acid + case 8: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_INCINERATE; + break; + case 9: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 10: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 11: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Ignite + case 12: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_INCINERATE; + break; + case 13: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 14: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 15: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Frost + case 16: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_INCINERATE; + break; + case 17: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 18: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 19: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + }; + + EnterEvadeMode(); + } + + uint32 Breath1_Spell; + uint32 Breath2_Spell; + uint32 CurrentVurln_Spell; + + uint32 Shimmer_Timer; + uint32 Breath1_Timer; + uint32 Breath2_Timer; + uint32 Affliction_Timer; + uint32 Frenzy_Timer; + bool Enraged; + + void Reset() + { + CurrentVurln_Spell = 0; //We use this to store our last vulnerabilty spell so we can remove it later + + Shimmer_Timer = 0; //Time till we change vurlnerabilites + Breath1_Timer = 30000; //First breath is 30 seconds + Breath2_Timer = 60000; //Second is 1 minute so that we can alternate + Affliction_Timer = 10000; //This is special - 5 seconds means that we cast this on 1 player every 5 sconds + Frenzy_Timer = 15000; + + Enraged = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Shimmer_Timer Timer + if (Shimmer_Timer <= diff) + { + //Remove old vulnerabilty spell + if (CurrentVurln_Spell) + me->RemoveAurasDueToSpell(CurrentVurln_Spell); + + //Cast new random vulnerabilty on self + uint32 spell = RAND(SPELL_FIRE_VULNERABILITY, SPELL_FROST_VULNERABILITY, + SPELL_SHADOW_VULNERABILITY, SPELL_NATURE_VULNERABILITY, SPELL_ARCANE_VULNERABILITY); + + DoCast(me, spell); + CurrentVurln_Spell = spell; + + DoScriptText(EMOTE_SHIMMER, me); + Shimmer_Timer = 45000; + } else Shimmer_Timer -= diff; + + //Breath1_Timer + if (Breath1_Timer <= diff) + { + DoCast(me->getVictim(), Breath1_Spell); + Breath1_Timer = 60000; + } else Breath1_Timer -= diff; + + //Breath2_Timer + if (Breath2_Timer <= diff) + { + DoCast(me->getVictim(), Breath2_Spell); + Breath2_Timer = 60000; + } else Breath2_Timer -= diff; + + //Affliction_Timer + if (Affliction_Timer <= diff) + { + std::list threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) + { + Unit* pUnit; + if ((*i) && (*i)->getSource()) + { + pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit) + { + //Cast affliction + DoCast(pUnit, RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, + SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN), true); + + //Chromatic mutation if target is effected by all afflictions + if (pUnit->HasAura(SPELL_BROODAF_BLUE) + && pUnit->HasAura(SPELL_BROODAF_BLACK) + && pUnit->HasAura(SPELL_BROODAF_RED) + && pUnit->HasAura(SPELL_BROODAF_BRONZE) + && pUnit->HasAura(SPELL_BROODAF_GREEN)) + { + //pTarget->RemoveAllAuras(); + //DoCast(pTarget, SPELL_CHROMATIC_MUT_1); + + //Chromatic mutation is causing issues + //Assuming it is caused by a lack of core support for Charm + //So instead we instant kill our target + + //WORKAROUND + if (pUnit->GetTypeId() == TYPEID_PLAYER) + pUnit->CastSpell(pUnit, 5, false); + } + } + } + } + + Affliction_Timer = 10000; + } else Affliction_Timer -= diff; + + //Frenzy_Timer + if (Frenzy_Timer <= diff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_FRENZY, me); + Frenzy_Timer = urand(10000,15000); + } else Frenzy_Timer -= diff; + + //Enrage if not already enraged and below 20% + if (!Enraged && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_chromaggus(Creature* pCreature) +{ + return new boss_chromaggusAI (pCreature); +} + +void AddSC_boss_chromaggus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_chromaggus"; + newscript->GetAI = &GetAI_boss_chromaggus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp new file mode 100644 index 00000000000..49a999fc458 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ebonroc +SD%Complete: 50 +SDComment: Shadow of Ebonroc needs core support +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 18500 +#define SPELL_SHADOWOFEBONROC 23340 +#define SPELL_HEAL 41386 //Thea Heal spell of his Shadow + +struct boss_ebonrocAI : public ScriptedAI +{ + boss_ebonrocAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 ShadowOfEbonroc_Timer; + uint32 Heal_Timer; + + void Reset() + { + ShadowFlame_Timer = 15000; //These times are probably wrong + WingBuffet_Timer = 30000; + ShadowOfEbonroc_Timer = 45000; + Heal_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Shadowflame Timer + if (ShadowFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWFLAME); + ShadowFlame_Timer = urand(12000,15000); + } else ShadowFlame_Timer -= diff; + + //Wing Buffet Timer + if (WingBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WINGBUFFET); + WingBuffet_Timer = 25000; + } else WingBuffet_Timer -= diff; + + //Shadow of Ebonroc Timer + if (ShadowOfEbonroc_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWOFEBONROC); + ShadowOfEbonroc_Timer = urand(25000,350000); + } else ShadowOfEbonroc_Timer -= diff; + + if (me->getVictim()->HasAura(SPELL_SHADOWOFEBONROC)) + { + if (Heal_Timer <= diff) + { + DoCast(me, SPELL_HEAL); + Heal_Timer = urand(1000,3000); + } else Heal_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ebonroc(Creature* pCreature) +{ + return new boss_ebonrocAI (pCreature); +} + +void AddSC_boss_ebonroc() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ebonroc"; + newscript->GetAI = &GetAI_boss_ebonroc; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp new file mode 100644 index 00000000000..af62b1103bc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Firemaw +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 23339 +#define SPELL_FLAMEBUFFET 23341 + +struct boss_firemawAI : public ScriptedAI +{ + boss_firemawAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 FlameBuffet_Timer; + + void Reset() + { + ShadowFlame_Timer = 30000; //These times are probably wrong + WingBuffet_Timer = 24000; + FlameBuffet_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWFLAME); + ShadowFlame_Timer = urand(15000,18000); + } else ShadowFlame_Timer -= diff; + + //WingBuffet_Timer + if (WingBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WINGBUFFET); + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-75); + + WingBuffet_Timer = 25000; + } else WingBuffet_Timer -= diff; + + //FlameBuffet_Timer + if (FlameBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBUFFET); + FlameBuffet_Timer = 5000; + } else FlameBuffet_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_firemaw(Creature* pCreature) +{ + return new boss_firemawAI (pCreature); +} + +void AddSC_boss_firemaw() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_firemaw"; + newscript->GetAI = &GetAI_boss_firemaw; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp new file mode 100644 index 00000000000..b29fe41f2b1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Flamegor +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_FRENZY -1469031 + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 23339 +#define SPELL_FRENZY 23342 //This spell periodically triggers fire nova + +struct boss_flamegorAI : public ScriptedAI +{ + boss_flamegorAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + ShadowFlame_Timer = 21000; //These times are probably wrong + WingBuffet_Timer = 35000; + Frenzy_Timer = 10000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWFLAME); + ShadowFlame_Timer = 15000 + rand()%7000; + } else ShadowFlame_Timer -= diff; + + //WingBuffet_Timer + if (WingBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WINGBUFFET); + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-75); + + WingBuffet_Timer = 25000; + } else WingBuffet_Timer -= diff; + + //Frenzy_Timer + if (Frenzy_Timer <= diff) + { + DoScriptText(EMOTE_FRENZY, me); + DoCast(me, SPELL_FRENZY); + Frenzy_Timer = urand(8000, 10000); + } else Frenzy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_flamegor(Creature* pCreature) +{ + return new boss_flamegorAI (pCreature); +} + +void AddSC_boss_flamegor() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_flamegor"; + newscript->GetAI = &GetAI_boss_flamegor; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp new file mode 100644 index 00000000000..5ef05be519c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp @@ -0,0 +1,231 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Nefarian +SD%Complete: 80 +SDComment: Some issues with class calls effecting more than one class +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1469007 +#define SAY_XHEALTH -1469008 +#define SAY_SHADOWFLAME -1469009 +#define SAY_RAISE_SKELETONS -1469010 +#define SAY_SLAY -1469011 +#define SAY_DEATH -1469012 + +#define SAY_MAGE -1469013 +#define SAY_WARRIOR -1469014 +#define SAY_DRUID -1469015 +#define SAY_PRIEST -1469016 +#define SAY_PALADIN -1469017 +#define SAY_SHAMAN -1469018 +#define SAY_WARLOCK -1469019 +#define SAY_HUNTER -1469020 +#define SAY_ROGUE -1469021 + +#define SPELL_SHADOWFLAME_INITIAL 22972 +#define SPELL_SHADOWFLAME 22539 +#define SPELL_BELLOWINGROAR 22686 +#define SPELL_VEILOFSHADOW 7068 +#define SPELL_CLEAVE 20691 +#define SPELL_TAILLASH 23364 +#define SPELL_BONECONTRUST 23363 //23362, 23361 + +#define SPELL_MAGE 23410 //wild magic +#define SPELL_WARRIOR 23397 //beserk +#define SPELL_DRUID 23398 // cat form +#define SPELL_PRIEST 23401 // corrupted healing +#define SPELL_PALADIN 23418 //syphon blessing +#define SPELL_SHAMAN 23425 //totems +#define SPELL_WARLOCK 23427 //infernals +#define SPELL_HUNTER 23436 //bow broke +#define SPELL_ROGUE 23414 //Paralise + +struct boss_nefarianAI : public ScriptedAI +{ + boss_nefarianAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowFlame_Timer; + uint32 BellowingRoar_Timer; + uint32 VeilOfShadow_Timer; + uint32 Cleave_Timer; + uint32 TailLash_Timer; + uint32 ClassCall_Timer; + bool Phase3; + + uint32 DespawnTimer; + + void Reset() + { + ShadowFlame_Timer = 12000; //These times are probably wrong + BellowingRoar_Timer = 30000; + VeilOfShadow_Timer = 15000; + Cleave_Timer = 7000; + TailLash_Timer = 10000; + ClassCall_Timer = 35000; //35-40 seconds + Phase3 = false; + + DespawnTimer = 5000; + } + + void KilledUnit(Unit* Victim) + { + if (rand()%5) + return; + + DoScriptText(SAY_SLAY, me, Victim); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * who) + { + DoScriptText(RAND(SAY_XHEALTH,SAY_AGGRO,SAY_SHADOWFLAME), me); + + DoCast(who, SPELL_SHADOWFLAME_INITIAL); + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (DespawnTimer <= diff) + { + if (!UpdateVictim()) + me->ForcedDespawn(); + DespawnTimer = 5000; + } else DespawnTimer -= diff; + + if (!UpdateVictim()) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWFLAME); + ShadowFlame_Timer = 12000; + } else ShadowFlame_Timer -= diff; + + //BellowingRoar_Timer + if (BellowingRoar_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BELLOWINGROAR); + BellowingRoar_Timer = 30000; + } else BellowingRoar_Timer -= diff; + + //VeilOfShadow_Timer + if (VeilOfShadow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VEILOFSHADOW); + VeilOfShadow_Timer = 15000; + } else VeilOfShadow_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //TailLash_Timer + if (TailLash_Timer <= diff) + { + //Cast NYI since we need a better check for behind target + //DoCast(me->getVictim(), SPELL_TAILLASH); + + TailLash_Timer = 10000; + } else TailLash_Timer -= diff; + + //ClassCall_Timer + if (ClassCall_Timer <= diff) + { + //Cast a random class call + //On official it is based on what classes are currently on the hostil list + //but we can't do that yet so just randomly call one + + switch (urand(0,8)) + { + case 0: + DoScriptText(SAY_MAGE, me); + DoCast(me, SPELL_MAGE); + break; + case 1: + DoScriptText(SAY_WARRIOR, me); + DoCast(me, SPELL_WARRIOR); + break; + case 2: + DoScriptText(SAY_DRUID, me); + DoCast(me, SPELL_DRUID); + break; + case 3: + DoScriptText(SAY_PRIEST, me); + DoCast(me, SPELL_PRIEST); + break; + case 4: + DoScriptText(SAY_PALADIN, me); + DoCast(me, SPELL_PALADIN); + break; + case 5: + DoScriptText(SAY_SHAMAN, me); + DoCast(me, SPELL_SHAMAN); + break; + case 6: + DoScriptText(SAY_WARLOCK, me); + DoCast(me, SPELL_WARLOCK); + break; + case 7: + DoScriptText(SAY_HUNTER, me); + DoCast(me, SPELL_HUNTER); + break; + case 8: + DoScriptText(SAY_ROGUE, me); + DoCast(me, SPELL_ROGUE); + break; + } + + ClassCall_Timer = 35000 + (rand() % 5000); + } else ClassCall_Timer -= diff; + + //Phase3 begins when we are below X health + if (!Phase3 && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) + { + Phase3 = true; + DoScriptText(SAY_RAISE_SKELETONS, me); + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_nefarian(Creature* pCreature) +{ + return new boss_nefarianAI (pCreature); +} + +void AddSC_boss_nefarian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nefarian"; + newscript->GetAI = &GetAI_boss_nefarian; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp new file mode 100644 index 00000000000..a095756b18b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp @@ -0,0 +1,125 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Razorgore +SD%Complete: 50 +SDComment: Needs additional review. Phase 1 NYI (Grethok the Controller) +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +//Razorgore Phase 2 Script + +#define SAY_EGGS_BROKEN1 -1469022 +#define SAY_EGGS_BROKEN2 -1469023 +#define SAY_EGGS_BROKEN3 -1469024 +#define SAY_DEATH -1469025 + +#define SPELL_CLEAVE 22540 +#define SPELL_WARSTOMP 24375 +#define SPELL_FIREBALLVOLLEY 22425 +#define SPELL_CONFLAGRATION 23023 + +struct boss_razorgoreAI : public ScriptedAI +{ + boss_razorgoreAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cleave_Timer; + uint32 WarStomp_Timer; + uint32 FireballVolley_Timer; + uint32 Conflagration_Timer; + + void Reset() + { + Cleave_Timer = 15000; //These times are probably wrong + WarStomp_Timer = 35000; + FireballVolley_Timer = 7000; + Conflagration_Timer = 12000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = urand(7000,10000); + } else Cleave_Timer -= diff; + + //WarStomp_Timer + if (WarStomp_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WARSTOMP); + WarStomp_Timer = urand(15000,25000); + } else WarStomp_Timer -= diff; + + //FireballVolley_Timer + if (FireballVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALLVOLLEY); + FireballVolley_Timer = urand(12000,15000); + } else FireballVolley_Timer -= diff; + + //Conflagration_Timer + if (Conflagration_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CONFLAGRATION); + //We will remove this threat reduction and add an aura check. + + //if (DoGetThreat(me->getVictim())) + //DoModifyThreatPercent(me->getVictim(),-50); + + Conflagration_Timer = 12000; + } else Conflagration_Timer -= diff; + + // Aura Check. If the gamer is affected by confliguration we attack a random gamer. + if (me->getVictim() && me->getVictim()->HasAura(SPELL_CONFLAGRATION)) + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + me->TauntApply(pTarget); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_razorgore(Creature* pCreature) +{ + return new boss_razorgoreAI (pCreature); +} + +void AddSC_boss_razorgore() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_razorgore"; + newscript->GetAI = &GetAI_boss_razorgore; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp new file mode 100644 index 00000000000..f6e94307f2f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp @@ -0,0 +1,262 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vaelastrasz +SD%Complete: 75 +SDComment: Burning Adrenaline not correctly implemented in core +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_LINE1 -1469026 +#define SAY_LINE2 -1469027 +#define SAY_LINE3 -1469028 +#define SAY_HALFLIFE -1469029 +#define SAY_KILLTARGET -1469030 + +#define GOSSIP_ITEM "Start Event " + +#define SPELL_ESSENCEOFTHERED 23513 +#define SPELL_FLAMEBREATH 23461 +#define SPELL_FIRENOVA 23462 +#define SPELL_TAILSWIPE 15847 +#define SPELL_BURNINGADRENALINE 23620 +#define SPELL_CLEAVE 20684 //Chain cleave is most likely named something different and contains a dummy effect + +struct boss_vaelAI : public ScriptedAI +{ + boss_vaelAI(Creature *c) : ScriptedAI(c) + { + c->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + c->setFaction(35); + c->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + uint64 PlayerGUID; + uint32 SpeechTimer; + uint32 SpeechNum; + uint32 Cleave_Timer; + uint32 FlameBreath_Timer; + uint32 FireNova_Timer; + uint32 BurningAdrenalineCaster_Timer; + uint32 BurningAdrenalineTank_Timer; + uint32 TailSwipe_Timer; + bool HasYelled; + bool DoingSpeech; + + void Reset() + { + PlayerGUID = 0; + SpeechTimer = 0; + SpeechNum = 0; + Cleave_Timer = 8000; //These times are probably wrong + FlameBreath_Timer = 11000; + BurningAdrenalineCaster_Timer = 15000; + BurningAdrenalineTank_Timer = 45000; + FireNova_Timer = 5000; + TailSwipe_Timer = 20000; + HasYelled = false; + DoingSpeech = false; + } + + void BeginSpeech(Unit *pTarget) + { + //Stand up and begin speach + PlayerGUID = pTarget->GetGUID(); + + //10 seconds + DoScriptText(SAY_LINE1, me); + + SpeechTimer = 10000; + SpeechNum = 0; + DoingSpeech = true; + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + void KilledUnit(Unit * victim) + { + if (rand()%5) + return; + + DoScriptText(SAY_KILLTARGET, me, victim); + } + + void EnterCombat(Unit * /*who*/) + { + DoCast(me, SPELL_ESSENCEOFTHERED); + DoZoneInCombat(); + me->SetHealth(int(me->GetMaxHealth()*.3)); + } + + void UpdateAI(const uint32 diff) + { + //Speech + if (DoingSpeech) + { + if (SpeechTimer <= diff) + { + switch (SpeechNum) + { + case 0: + //16 seconds till next line + DoScriptText(SAY_LINE2, me); + SpeechTimer = 16000; + ++SpeechNum; + break; + case 1: + //This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!" + DoScriptText(SAY_LINE3, me); + SpeechTimer = 10000; + ++SpeechNum; + break; + case 2: + me->setFaction(103); + if (PlayerGUID && Unit::GetUnit((*me),PlayerGUID)) + { + AttackStart(Unit::GetUnit((*me),PlayerGUID)); + DoCast(me, SPELL_ESSENCEOFTHERED); + } + SpeechTimer = 0; + DoingSpeech = false; + break; + } + } else SpeechTimer -= diff; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + // Yell if hp lower than 15% + if (me->GetHealth()*100 / me->GetMaxHealth() < 15 && !HasYelled) + { + DoScriptText(SAY_HALFLIFE, me); + HasYelled = true; + } + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 15000; + } else Cleave_Timer -= diff; + + //FlameBreath_Timer + if (FlameBreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBREATH); + FlameBreath_Timer = urand(4000,8000); + } else FlameBreath_Timer -= diff; + + //BurningAdrenalineCaster_Timer + if (BurningAdrenalineCaster_Timer <= diff) + { + Unit *pTarget = NULL; + + uint8 i = 0; + while (i < 3) // max 3 tries to get a random target with power_mana + { + ++i; + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); //not aggro leader + if (pTarget && pTarget->getPowerType() == POWER_MANA) + i = 3; + } + if (pTarget) // cast on self (see below) + pTarget->CastSpell(pTarget,SPELL_BURNINGADRENALINE,1); + + BurningAdrenalineCaster_Timer = 15000; + } else BurningAdrenalineCaster_Timer -= diff; + + //BurningAdrenalineTank_Timer + if (BurningAdrenalineTank_Timer <= diff) + { + // have the victim cast the spell on himself otherwise the third effect aura will be applied + // to Vael instead of the player + me->getVictim()->CastSpell(me->getVictim(),SPELL_BURNINGADRENALINE,1); + + BurningAdrenalineTank_Timer = 45000; + } else BurningAdrenalineTank_Timer -= diff; + + //FireNova_Timer + if (FireNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRENOVA); + FireNova_Timer = 5000; + } else FireNova_Timer -= diff; + + //TailSwipe_Timer + if (TailSwipe_Timer <= diff) + { + //Only cast if we are behind + /*if (!me->HasInArc(M_PI, me->getVictim())) + { + DoCast(me->getVictim(), SPELL_TAILSWIPE); + }*/ + + TailSwipe_Timer = 20000; + } else TailSwipe_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void SendDefaultMenu_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(boss_vaelAI, pCreature->AI())->BeginSpeech(pPlayer); + } +} + +bool GossipSelect_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiSender == GOSSIP_SENDER_MAIN) + SendDefaultMenu_boss_vael(pPlayer, pCreature, uiAction); + + return true; +} + +bool GossipHello_boss_vael(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + + return true; +} + +CreatureAI* GetAI_boss_vael(Creature* pCreature) +{ + return new boss_vaelAI (pCreature); +} + +void AddSC_boss_vael() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vaelastrasz"; + newscript->GetAI = &GetAI_boss_vael; + newscript->pGossipHello = &GossipHello_boss_vael; + newscript->pGossipSelect = &GossipSelect_boss_vael; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp new file mode 100644 index 00000000000..dfeb2519bae --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp @@ -0,0 +1,385 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Victor_Nefarius +SD%Complete: 75 +SDComment: Missing some text, Vael beginning event, and spawns Nef in wrong place +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_GAMESBEGIN_1 -1469004 +#define SAY_GAMESBEGIN_2 -1469005 +#define SAY_VAEL_INTRO -1469006 //when he corrupts Vaelastrasz + +#define GOSSIP_ITEM_1 "I've made no mistakes." +#define GOSSIP_ITEM_2 "You have lost your mind, Nefarius. You speak in riddles." +#define GOSSIP_ITEM_3 "Please do." + +#define CREATURE_BRONZE_DRAKANOID 14263 +#define CREATURE_BLUE_DRAKANOID 14261 +#define CREATURE_RED_DRAKANOID 14264 +#define CREATURE_GREEN_DRAKANOID 14262 +#define CREATURE_BLACK_DRAKANOID 14265 + +#define CREATURE_CHROMATIC_DRAKANOID 14302 +#define CREATURE_NEFARIAN 11583 + +#define ADD_X1 -7591.151855 +#define ADD_X2 -7514.598633 +#define ADD_Y1 -1204.051880 +#define ADD_Y2 -1150.448853 +#define ADD_Z1 476.800476 +#define ADD_Z2 476.796570 + +#define NEF_X -7445 +#define NEF_Y -1332 +#define NEF_Z 536 + +#define HIDE_X -7592 +#define HIDE_Y -1264 +#define HIDE_Z 481 + +#define SPELL_SHADOWBOLT 21077 +#define SPELL_FEAR 26070 + +//This script is complicated +//Instead of morphing Victor Nefarius we will have him control phase 1 +//And then have him spawn "Nefarian" for phase 2 +//When phase 2 starts Victor Nefarius will go into hiding and stop attacking +//If Nefarian despawns because he killed the players then this guy will EnterEvadeMode +//and allow players to start the event over +//If nefarian dies then he will kill himself then he will kill himself in his hiding place +//To prevent players from doing the event twice + +struct boss_victor_nefariusAI : public ScriptedAI +{ + boss_victor_nefariusAI(Creature *c) : ScriptedAI(c) + { + NefarianGUID = 0; + switch (urand(0,19)) + { + case 0: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 1: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 2: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 3: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 4: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 5: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 6: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 7: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 8: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 9: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 10: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 11: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 12: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 13: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 14: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 15: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 16: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 17: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 18: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 19: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + } + } + + uint32 SpawnedAdds; + uint32 AddSpawnTimer; + uint32 ShadowBoltTimer; + uint32 FearTimer; + uint32 MindControlTimer; + uint32 ResetTimer; + uint32 DrakType1; + uint32 DrakType2; + uint64 NefarianGUID; + uint32 NefCheckTime; + + void Reset() + { + SpawnedAdds = 0; + AddSpawnTimer = 10000; + ShadowBoltTimer = 5000; + FearTimer = 8000; + ResetTimer = 900000; //On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier + NefarianGUID = 0; + NefCheckTime = 2000; + + me->SetUInt32Value(UNIT_NPC_FLAGS,1); + me->setFaction(35); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void BeginEvent(Player *pTarget) + { + DoScriptText(SAY_GAMESBEGIN_2, me); + + //Trinity::Singleton::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); + /* + list ::const_iterator i = MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); + + for (i = MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); i != MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().end(); ++i) + { + AttackStart((*i)); + } + */ + me->SetUInt32Value(UNIT_NPC_FLAGS,0); + me->setFaction(103); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + AttackStart(pTarget); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void MoveInLineOfSight(Unit *who) + { + //We simply use this function to find players until we can use pMap->GetPlayers() + + if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsHostileTo(who)) + { + //Add them to our threat list + me->AddThreat(who, 0.0f); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Only do this if we haven't spawned nef yet + if (SpawnedAdds < 42) + { + //ShadowBoltTimer + if (ShadowBoltTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SHADOWBOLT); + + ShadowBoltTimer = urand(3000,10000); + } else ShadowBoltTimer -= diff; + + //FearTimer + if (FearTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_FEAR); + + FearTimer = 10000 + (rand()%10000); + } else FearTimer -= diff; + + //Add spawning mechanism + if (AddSpawnTimer <= diff) + { + //Spawn 2 random types of creatures at the 2 locations + uint32 CreatureID; + Creature* Spawned = NULL; + Unit *pTarget = NULL; + + //1 in 3 chance it will be a chromatic + if (urand(0,2) == 0) + CreatureID = CREATURE_CHROMATIC_DRAKANOID; + else + CreatureID = DrakType1; + + ++SpawnedAdds; + + //Spawn Creature and force it to start attacking a random target + Spawned = me->SummonCreature(CreatureID,ADD_X1,ADD_Y1,ADD_Z1,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget && Spawned) + { + Spawned->AI()->AttackStart(pTarget); + Spawned->setFaction(103); + } + + //1 in 3 chance it will be a chromatic + if (urand(0,2) == 0) + CreatureID = CREATURE_CHROMATIC_DRAKANOID; + else + CreatureID = DrakType2; + + ++SpawnedAdds; + + Spawned = me->SummonCreature(CreatureID,ADD_X2,ADD_Y2,ADD_Z2,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget && Spawned) + { + Spawned->AI()->AttackStart(pTarget); + Spawned->setFaction(103); + } + + //Begin phase 2 by spawning Nefarian and what not + if (SpawnedAdds >= 42) + { + //Teleport Victor Nefarius way out of the map + //MapManager::Instance().GetMap(me->GetMapId(), me)->CreatureRelocation(me,0,0,-5000,0); + + //Inturrupt any spell casting + me->InterruptNonMeleeSpells(false); + + //Root self + DoCast(me, 33356); + + //Make super invis + DoCast(me, 8149); + + //Teleport self to a hiding spot (this causes errors in the Trinity log but no real issues) + DoTeleportTo(HIDE_X,HIDE_Y,HIDE_Z); + me->addUnitState(UNIT_STAT_FLEEING); + + //Spawn nef and have him attack a random target + Creature* Nefarian = me->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget && Nefarian) + { + Nefarian->AI()->AttackStart(pTarget); + Nefarian->setFaction(103); + NefarianGUID = Nefarian->GetGUID(); + } + else error_log("TSCR: Blackwing Lair: Unable to spawn nefarian properly."); + } + + AddSpawnTimer = 4000; + } else AddSpawnTimer -= diff; + } + else if (NefarianGUID) + { + if (NefCheckTime <= diff) + { + Unit* Nefarian = Unit::GetCreature((*me),NefarianGUID); + + //If nef is dead then we die to so the players get out of combat + //and cannot repeat the event + if (!Nefarian || !Nefarian->isAlive()) + { + NefarianGUID = 0; + me->ForcedDespawn(); + } + + NefCheckTime = 2000; + } else NefCheckTime -= diff; + } + } +}; + +CreatureAI* GetAI_boss_victor_nefarius(Creature* pCreature) +{ + return new boss_victor_nefariusAI (pCreature); +} + +bool GossipHello_boss_victor_nefarius(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1 , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(7134, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_boss_victor_nefarius(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(7198, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(7199, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + DoScriptText(SAY_GAMESBEGIN_1, pCreature); + CAST_AI(boss_victor_nefariusAI, pCreature->AI())->BeginEvent(pPlayer); + break; + } + return true; +} + +void AddSC_boss_victor_nefarius() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_victor_nefarius"; + newscript->GetAI = &GetAI_boss_victor_nefarius; + newscript->pGossipHello = &GossipHello_boss_victor_nefarius; + newscript->pGossipSelect = &GossipSelect_boss_victor_nefarius; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp new file mode 100644 index 00000000000..d6403fa1206 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp @@ -0,0 +1,25 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Blackwing_Lair +SD%Complete: 0 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + diff --git a/src/server/scripts/EasternKingdoms/blasted_lands.cpp b/src/server/scripts/EasternKingdoms/blasted_lands.cpp new file mode 100644 index 00000000000..768242fcd22 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/blasted_lands.cpp @@ -0,0 +1,161 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Blasted_Lands +SD%Complete: 90 +SDComment: Quest support: 2784, 2801, 3628. Missing some texts for Fallen Hero. Teleporter to Rise of the Defiler missing group support. +SDCategory: Blasted Lands +EndScriptData */ + +/* ContentData +npc_deathly_usher +npc_fallen_hero_of_horde +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_deathly_usher +######*/ + +#define GOSSIP_ITEM_USHER "I wish to to visit the Rise of the Defiler." + +#define SPELL_TELEPORT_SINGLE 12885 +#define SPELL_TELEPORT_SINGLE_IN_GROUP 13142 +#define SPELL_TELEPORT_GROUP 27686 + +bool GossipHello_npc_deathly_usher(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(3628) == QUEST_STATUS_INCOMPLETE && pPlayer->HasItemCount(10757, 1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_USHER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_deathly_usher(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, SPELL_TELEPORT_SINGLE, true); + } + + return true; +} + +/*###### +## npc_fallen_hero_of_horde +######*/ +#define GOSSIP_H_F1 "Why are you here?" +#define GOSSIP_H_F2 "Continue story..." + +#define GOSSIP_ITEM_FALLEN "Continue..." + +#define GOSSIP_ITEM_FALLEN1 "What could be worse than death?" +#define GOSSIP_ITEM_FALLEN2 "Subordinates?" +#define GOSSIP_ITEM_FALLEN3 "What are the stones of binding?" +#define GOSSIP_ITEM_FALLEN4 "You can count on me, Hero" +#define GOSSIP_ITEM_FALLEN5 "I shall" + +bool GossipHello_npc_fallen_hero_of_horde(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(2784) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_H_F1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (pPlayer->GetQuestStatus(2801) == QUEST_STATUS_INCOMPLETE && pPlayer->GetTeam() == HORDE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_H_F2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + if (pPlayer->GetQuestStatus(2801) == QUEST_STATUS_INCOMPLETE && pPlayer->GetTeam() == ALLIANCE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_H_F1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_fallen_hero_of_horde(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + pPlayer->SEND_GOSSIP_MENU(1392, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + pPlayer->SEND_GOSSIP_MENU(1411, pCreature->GetGUID()); + if (pPlayer->GetQuestStatus(2784) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(2784); + if (pPlayer->GetTeam() == ALLIANCE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(1411, pCreature->GetGUID()); + } + break; + + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); + pPlayer->SEND_GOSSIP_MENU(1451, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+21: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); + pPlayer->SEND_GOSSIP_MENU(1452, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+22: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23); + pPlayer->SEND_GOSSIP_MENU(1453, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+23: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24); + pPlayer->SEND_GOSSIP_MENU(1454, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+24: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25); + pPlayer->SEND_GOSSIP_MENU(1455, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+25: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26); + pPlayer->SEND_GOSSIP_MENU(1456, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+26: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(2801); + break; + } + return true; +} + +void AddSC_blasted_lands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_deathly_usher"; + newscript->pGossipHello = &GossipHello_npc_deathly_usher; + newscript->pGossipSelect = &GossipSelect_npc_deathly_usher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_fallen_hero_of_horde"; + newscript->pGossipHello = &GossipHello_npc_fallen_hero_of_horde; + newscript->pGossipSelect = &GossipSelect_npc_fallen_hero_of_horde; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/boss_kruul.cpp b/src/server/scripts/EasternKingdoms/boss_kruul.cpp new file mode 100644 index 00000000000..44a6431f9ea --- /dev/null +++ b/src/server/scripts/EasternKingdoms/boss_kruul.cpp @@ -0,0 +1,154 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kruul +SD%Complete: 100 +SDComment: Highlord Kruul are presumably no longer in-game on regular bases, however future events could bring him back. +SDCategory: Bosses +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWVOLLEY 21341 +#define SPELL_CLEAVE 20677 +#define SPELL_THUNDERCLAP 23931 +#define SPELL_TWISTEDREFLECTION 21063 +#define SPELL_VOIDBOLT 21066 +#define SPELL_RAGE 21340 +#define SPELL_CAPTURESOUL 21054 + +struct boss_kruulAI : public ScriptedAI +{ + boss_kruulAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowVolley_Timer; + uint32 Cleave_Timer; + uint32 ThunderClap_Timer; + uint32 TwistedReflection_Timer; + uint32 VoidBolt_Timer; + uint32 Rage_Timer; + uint32 Hound_Timer; + + void Reset() + { + ShadowVolley_Timer = 10000; + Cleave_Timer = 14000; + ThunderClap_Timer = 20000; + TwistedReflection_Timer = 25000; + VoidBolt_Timer = 30000; + Rage_Timer = 60000; //Cast rage after 1 minute + Hound_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit() + { + // When a player, pet or totem gets killed, Lord Kazzak casts this spell to instantly regenerate 70,000 health. + DoCast(me, SPELL_CAPTURESOUL); + } + + void SummonHounds(Unit* pVictim) + { + if (Creature *Hound = DoSpawnCreature(19207, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) + Hound->AI()->AttackStart(pVictim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer <= diff) + { + if (urand(0,99) < 45) + DoCast(me->getVictim(), SPELL_SHADOWVOLLEY); + + ShadowVolley_Timer = 5000; + } else ShadowVolley_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + if (urand(0,1)) + DoCast(me->getVictim(), SPELL_CLEAVE); + + Cleave_Timer = 10000; + } else Cleave_Timer -= diff; + + //ThunderClap_Timer + if (ThunderClap_Timer <= diff) + { + if (urand(0,9) < 2) + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + + ThunderClap_Timer = 12000; + } else ThunderClap_Timer -= diff; + + //TwistedReflection_Timer + if (TwistedReflection_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TWISTEDREFLECTION); + TwistedReflection_Timer = 30000; + } else TwistedReflection_Timer -= diff; + + //VoidBolt_Timer + if (VoidBolt_Timer <= diff) + { + if (urand(0,9) < 4) + DoCast(me->getVictim(), SPELL_VOIDBOLT); + + VoidBolt_Timer = 18000; + } else VoidBolt_Timer -= diff; + + //Rage_Timer + if (Rage_Timer <= diff) + { + DoCast(me, SPELL_RAGE); + Rage_Timer = 70000; + } else Rage_Timer -= diff; + + //Hound_Timer + if (Hound_Timer <= diff) + { + SummonHounds(me->getVictim()); + SummonHounds(me->getVictim()); + SummonHounds(me->getVictim()); + + Hound_Timer = 45000; + } else Hound_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_kruul(Creature* pCreature) +{ + return new boss_kruulAI (pCreature); +} + +void AddSC_boss_kruul() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kruul"; + newscript->GetAI = &GetAI_boss_kruul; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/burning_steppes.cpp b/src/server/scripts/EasternKingdoms/burning_steppes.cpp new file mode 100644 index 00000000000..5a1e338b70f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/burning_steppes.cpp @@ -0,0 +1,153 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Burning_Steppes +SD%Complete: 100 +SDComment: Quest support: 4224, 4866 +SDCategory: Burning Steppes +EndScriptData */ + +/* ContentData +npc_ragged_john +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_ragged_john +######*/ + +#define GOSSIP_HELLO "Official buisness, John. I need some information about Marsha Windsor. Tell me about the last time you saw him." +#define GOSSIP_SELECT1 "So what did you do?" +#define GOSSIP_SELECT2 "Start making sense, dwarf. I don't want to have anything to do with your cracker, your pappy, or any sort of 'discreditin'." +#define GOSSIP_SELECT3 "Ironfoe?" +#define GOSSIP_SELECT4 "Interesting... continue John." +#define GOSSIP_SELECT5 "So that's how Windsor died..." +#define GOSSIP_SELECT6 "So how did he die?" +#define GOSSIP_SELECT7 "Ok so where the hell is he? Wait a minute! Are you drunk?" +#define GOSSIP_SELECT8 "WHY is he in Blackrock Depths?" +#define GOSSIP_SELECT9 "300? So the Dark Irons killed him and dragged him into the Depths?" +#define GOSSIP_SELECT10 "Ahh... Ironfoe" +#define GOSSIP_SELECT11 "Thanks, Ragged John. Your story was very uplifting and informative" + +struct npc_ragged_johnAI : public ScriptedAI +{ + npc_ragged_johnAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + + void MoveInLineOfSight(Unit *who) + { + if (who->HasAura(16468)) + { + if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 15) && who->isInAccessiblePlaceFor(me)) + { + DoCast(who, 16472); + CAST_PLR(who)->AreaExploredOrEventHappens(4866); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) {} +}; + +CreatureAI* GetAI_npc_ragged_john(Creature* pCreature) +{ + return new npc_ragged_johnAI (pCreature); +} + +bool GossipHello_npc_ragged_john(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(4224) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(2713, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_ragged_john(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2714, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(2715, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(2716, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(2717, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + pPlayer->SEND_GOSSIP_MENU(2718, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + pPlayer->SEND_GOSSIP_MENU(2719, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + pPlayer->SEND_GOSSIP_MENU(2720, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + pPlayer->SEND_GOSSIP_MENU(2721, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+8: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + pPlayer->SEND_GOSSIP_MENU(2722, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+9: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + pPlayer->SEND_GOSSIP_MENU(2723, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+10: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + pPlayer->SEND_GOSSIP_MENU(2725, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(4224); + break; + } + return true; +} + +void AddSC_burning_steppes() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_ragged_john"; + newscript->GetAI = &GetAI_npc_ragged_john; + newscript->pGossipHello = &GossipHello_npc_ragged_john; + newscript->pGossipSelect = &GossipSelect_npc_ragged_john; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp b/src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp new file mode 100644 index 00000000000..5c6bab46e5a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp @@ -0,0 +1,182 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss Mr.Smite +SD%Complete: +SDComment: Timers and say taken from acid script +EndScriptData */ + +#include "ScriptedPch.h" +#include "deadmines.h" + +enum eSpels +{ + SPELL_TRASH = 3391, + SPELL_SMITE_STOMP = 6432, + SPELL_SMITE_SLAM = 6435, + SPELL_NIMBLE_REFLEXES = 6264, + + EQUIP_SWORD = 5191, + EQUIP_MACE = 7230, + + SAY_AGGRO = -1036001 +}; + +struct boss_mr_smiteAI : public ScriptedAI +{ + boss_mr_smiteAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiTrashTimer; + uint32 uiSlamTimer; + uint32 uiNimbleReflexesTimer; + + uint8 uiHealth; + + uint32 uiPhase; + uint32 uiTimer; + + void Reset() + { + uiTrashTimer = urand(5000,9000); + uiSlamTimer = 9000; + uiNimbleReflexesTimer = urand(15500,31600); + + uiHealth = 0; + + uiPhase = 0; + uiTimer = 0; + + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + } + + bool bCheckChances() + { + uint32 uiChances = urand(0,99); + if (uiChances <= 15) + return false; + else + return true; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + /*START ACID-AI*/ + if (uiTrashTimer <= uiDiff) + { + if (bCheckChances()) + DoCast(me, SPELL_TRASH); + uiTrashTimer = urand(6000,15500); + } else uiTrashTimer -= uiDiff; + + if (uiSlamTimer <= uiDiff) + { + if (bCheckChances()) + DoCast(me->getVictim(), SPELL_SMITE_SLAM); + uiSlamTimer = 11000; + } else uiSlamTimer -= uiDiff; + + if (uiNimbleReflexesTimer <= uiDiff) + { + if (bCheckChances()) + DoCast(me, SPELL_NIMBLE_REFLEXES); + uiNimbleReflexesTimer = urand(27300,60100); + } else uiNimbleReflexesTimer -= uiDiff; + /*END ACID-AI*/ + + if (uiHealth == 0 && me->GetHealth()*100 / me->GetMaxHealth() <= 66 || uiHealth == 1 && me->GetHealth()*100 / me->GetMaxHealth() <= 33) + { + ++uiHealth; + DoCastAOE(SPELL_SMITE_STOMP,false); + SetCombatMovement(false); + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_SMITE_CHEST))) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(1,-3.00+pGo->GetPositionX(),pGo->GetPositionY(),pGo->GetPositionZ()); + } + } + + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + me->HandleEmoteCommand(EMOTE_STATE_KNEEL); //dosen't work? + uiTimer = 1000; + uiPhase = 2; + break; + case 2: + if (uiHealth == 1) + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); + else + SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + uiTimer = 500; + uiPhase = 3; + break; + case 3: + SetCombatMovement(true); + me->GetMotionMaster()->MoveChase(me->getVictim(), me->m_CombatDistance); + uiPhase = 0; + break; + + } + } else uiTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + uiTimer = 1500; + uiPhase = 1; + } + +}; +CreatureAI* GetAI_boss_mr_smite(Creature* pCreature) +{ + return new boss_mr_smiteAI (pCreature); +} + +void AddSC_boss_mr_smite() +{ + Script* newscript; + newscript = new Script; + newscript->Name = "boss_mr_smite"; + newscript->GetAI = &GetAI_boss_mr_smite; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp b/src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp new file mode 100644 index 00000000000..5bc1121bead --- /dev/null +++ b/src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp @@ -0,0 +1,60 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Deadmines +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Deadmines +EndScriptData */ + +#include "ScriptedPch.h" +#include "deadmines.h" +#include "Spell.h" + +/*##### +# item_Defias_Gunpowder +#####*/ + +bool ItemUse_item_defias_gunpowder(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) +{ + ScriptedInstance *pInstance = pPlayer->GetInstanceData(); + + if (!pInstance) + { + pPlayer->GetSession()->SendNotification("Instance script not initialized"); + return true; + } + if (pInstance->GetData(EVENT_STATE)!= CANNON_NOT_USED) + return false; + if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT && + targets.getGOTarget()->GetEntry() == GO_DEFIAS_CANNON) + { + pInstance->SetData(EVENT_STATE, CANNON_GUNPOWDER_USED); + } + + pPlayer->DestroyItemCount(pItem->GetEntry(), 1, true); + return true; +} + +void AddSC_deadmines() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "item_defias_gunpowder"; + newscript->pItemUse = &ItemUse_item_defias_gunpowder; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/deadmines/deadmines.h b/src/server/scripts/EasternKingdoms/deadmines/deadmines.h new file mode 100644 index 00000000000..203494ad5b7 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/deadmines/deadmines.h @@ -0,0 +1,35 @@ +#ifndef DEF_DEADMINES_H +#define DEF_DEADMINES_H + +#include "ScriptedPch.h" + +enum CannonState +{ + CANNON_NOT_USED, + CANNON_GUNPOWDER_USED, + CANNON_BLAST_INITIATED, + PIRATES_ATTACK, + EVENT_DONE +}; + +enum Data +{ + EVENT_STATE, + EVENT_RHAHKZOR +}; + +enum Data64 +{ + DATA_SMITE_CHEST +}; + +enum GameObjects +{ + GO_FACTORY_DOOR = 13965, + GO_IRONCLAD_DOOR = 16397, + GO_DEFIAS_CANNON = 16398, + GO_DOOR_LEVER = 101833, + GO_MR_SMITE_CHEST = 144111 +}; +#endif + diff --git a/src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp b/src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp new file mode 100644 index 00000000000..f1aa0c62b8a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp @@ -0,0 +1,256 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Deadmines +SD%Complete: 100 +SDComment: +SDCategory: Deadmines +EndScriptData */ + +#include "ScriptedPch.h" +#include "deadmines.h" + +enum Sounds +{ + SOUND_CANNONFIRE = 1400, + SOUND_DESTROYDOOR = 3079, + SOUND_MR_SMITE_ALARM1 = 5775, + SOUND_MR_SMITE_ALARM2 = 5777 +}; + +#define SAY_MR_SMITE_ALARM1 "You there, check out that noise!" +#define SAY_MR_SMITE_ALARM2 "We're under attack! A vast, ye swabs! Repel the invaders!" + +enum Misc +{ + DATA_CANNON_BLAST_TIMER = 3000, + DATA_PIRATES_DELAY_TIMER = 1000 +}; + +struct instance_deadmines : public ScriptedInstance +{ + instance_deadmines(Map* pMap) : ScriptedInstance(pMap) { Initialize(); }; + + uint64 FactoryDoorGUID; + uint64 IronCladDoorGUID; + uint64 DefiasCannonGUID; + uint64 DoorLeverGUID; + uint64 DefiasPirate1GUID; + uint64 DefiasPirate2GUID; + uint64 DefiasCompanionGUID; + + uint32 State; + uint32 CannonBlast_Timer; + uint32 PiratesDelay_Timer; + uint64 uiSmiteChestGUID; + + void Initialize() + { + FactoryDoorGUID = 0; + IronCladDoorGUID = 0; + DefiasCannonGUID = 0; + DoorLeverGUID = 0; + DefiasPirate1GUID = 0; + DefiasPirate2GUID = 0; + DefiasCompanionGUID = 0; + + State = CANNON_NOT_USED; + uiSmiteChestGUID = 0; + } + + virtual void Update(uint32 diff) + { + if (!IronCladDoorGUID || !DefiasCannonGUID || !DoorLeverGUID) + return; + + GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID); + if (!pIronCladDoor) + return; + + switch (State) + { + case CANNON_GUNPOWDER_USED: + CannonBlast_Timer = DATA_CANNON_BLAST_TIMER; + // it's a hack - Mr. Smite should do that but his too far away + pIronCladDoor->SetName("Mr. Smite"); + pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM1, LANG_UNIVERSAL, 0); + DoPlaySound(pIronCladDoor, SOUND_MR_SMITE_ALARM1); + State = CANNON_BLAST_INITIATED; + break; + case CANNON_BLAST_INITIATED: + PiratesDelay_Timer = DATA_PIRATES_DELAY_TIMER; + if (CannonBlast_Timer <= diff) + { + SummonCreatures(); + ShootCannon(); + BlastOutDoor(); + LeverStucked(); + pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM2, LANG_UNIVERSAL, 0); + DoPlaySound(pIronCladDoor, SOUND_MR_SMITE_ALARM2); + State = PIRATES_ATTACK; + } else CannonBlast_Timer -= diff; + break; + case PIRATES_ATTACK: + if (PiratesDelay_Timer <= diff) + { + MoveCreaturesInside(); + State = EVENT_DONE; + } else PiratesDelay_Timer -= diff; + break; + } + } + + void SummonCreatures() + { + if (GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID)) + { + Creature *DefiasPirate1 = pIronCladDoor->SummonCreature(657,pIronCladDoor->GetPositionX() - 2,pIronCladDoor->GetPositionY()-7,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + Creature *DefiasPirate2 = pIronCladDoor->SummonCreature(657,pIronCladDoor->GetPositionX() + 3,pIronCladDoor->GetPositionY()-6,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + Creature *DefiasCompanion = pIronCladDoor->SummonCreature(3450,pIronCladDoor->GetPositionX() + 2,pIronCladDoor->GetPositionY()-6,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + + DefiasPirate1GUID = DefiasPirate1->GetGUID(); + DefiasPirate2GUID = DefiasPirate2->GetGUID(); + DefiasCompanionGUID = DefiasCompanion->GetGUID(); + } + } + + void MoveCreaturesInside() + { + if (!DefiasPirate1GUID || !DefiasPirate2GUID || !DefiasCompanionGUID) + return; + + Creature *pDefiasPirate1 = instance->GetCreature(DefiasPirate1GUID); + Creature *pDefiasPirate2 = instance->GetCreature(DefiasPirate2GUID); + Creature *pDefiasCompanion = instance->GetCreature(DefiasCompanionGUID); + if (!pDefiasPirate1 || !pDefiasPirate2 || !pDefiasCompanion) + return; + + MoveCreatureInside(pDefiasPirate1); + MoveCreatureInside(pDefiasPirate2); + MoveCreatureInside(pDefiasCompanion); + } + + void MoveCreatureInside(Creature* pCreature) + { + pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCreature->GetMotionMaster()->MovePoint(0, -102.7,-655.9, pCreature->GetPositionZ()); + } + + void ShootCannon() + { + if (GameObject *pDefiasCannon = instance->GetGameObject(DefiasCannonGUID)) + { + pDefiasCannon->SetGoState(GO_STATE_ACTIVE); + DoPlaySound(pDefiasCannon, SOUND_CANNONFIRE); + } + } + + void BlastOutDoor() + { + if (GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID)) + { + pIronCladDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + DoPlaySound(pIronCladDoor, SOUND_DESTROYDOOR); + } + } + + void LeverStucked() + { + if (GameObject *pDoorLever = instance->GetGameObject(DoorLeverGUID)) + pDoorLever->SetUInt32Value(GAMEOBJECT_FLAGS, 4); + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_FACTORY_DOOR: FactoryDoorGUID = pGo->GetGUID(); break; + case GO_IRONCLAD_DOOR: IronCladDoorGUID = pGo->GetGUID(); break; + case GO_DEFIAS_CANNON: DefiasCannonGUID = pGo->GetGUID(); break; + case GO_DOOR_LEVER: DoorLeverGUID = pGo->GetGUID(); break; + case GO_MR_SMITE_CHEST: uiSmiteChestGUID = pGo->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch (type) + { + case EVENT_STATE: + if (DefiasCannonGUID && IronCladDoorGUID) + State=data; + break; + case EVENT_RHAHKZOR: + if (data == DONE) + if (GameObject* pGo = instance->GetGameObject(FactoryDoorGUID)) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + } + } + + uint32 GetData(uint32 type) + { + switch (type) + { + case EVENT_STATE: + return State; + } + + return 0; + } + + uint64 GetData64(uint32 data) + { + switch (data) + { + case DATA_SMITE_CHEST: + return uiSmiteChestGUID; + } + + return 0; + } + + void DoPlaySound(GameObject* unit, uint32 sound) + { + WorldPacket data(4); + data.SetOpcode(SMSG_PLAY_SOUND); + data << uint32(sound); + unit->SendMessageToSet(&data,false); + } + + void DoPlaySoundCreature(Unit* unit, uint32 sound) + { + WorldPacket data(4); + data.SetOpcode(SMSG_PLAY_SOUND); + data << uint32(sound); + unit->SendMessageToSet(&data,false); + } +}; + +InstanceData* GetInstanceData_instance_deadmines(Map* pMap) +{ + return new instance_deadmines(pMap); +} + +void AddSC_instance_deadmines() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_deadmines"; + newscript->GetInstanceData = &GetInstanceData_instance_deadmines; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/dun_morogh.cpp b/src/server/scripts/EasternKingdoms/dun_morogh.cpp new file mode 100644 index 00000000000..4c47cc8bbb8 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/dun_morogh.cpp @@ -0,0 +1,102 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Dun_Morogh +SD%Complete: 50 +SDComment: Quest support: 1783 +SDCategory: Dun Morogh +EndScriptData */ + +/* ContentData +npc_narm_faulk +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_narm_faulk +######*/ + +// signed for 6172 +#define SAY_HEAL -1100280 + +struct npc_narm_faulkAI : public ScriptedAI +{ + uint32 lifeTimer; + bool spellHit; + + npc_narm_faulkAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + lifeTimer = 120000; + me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + me->SetStandState(UNIT_STAND_STATE_DEAD); + spellHit = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void MoveInLineOfSight(Unit * /*who*/) + { + return; + } + + void UpdateAI(const uint32 diff) + { + if (me->IsStandState()) + { + if (lifeTimer <= diff) + { + EnterEvadeMode(); + return; + } + else + lifeTimer -= diff; + } + } + + void SpellHit(Unit * /*Hitter*/, const SpellEntry *Spellkind) + { + if (Spellkind->Id == 8593 && !spellHit) + { + DoCast(me, 32343); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + //me->RemoveAllAuras(); + DoScriptText(SAY_HEAL, me); + spellHit = true; + } + } + +}; +CreatureAI* GetAI_npc_narm_faulk(Creature* pCreature) +{ + return new npc_narm_faulkAI (pCreature); +} + +void AddSC_dun_morogh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_narm_faulk"; + newscript->GetAI = &GetAI_npc_narm_faulk; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/duskwood.cpp b/src/server/scripts/EasternKingdoms/duskwood.cpp new file mode 100644 index 00000000000..89c0ebe4213 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/duskwood.cpp @@ -0,0 +1,126 @@ +/* Copyright (C) 2006 - 2009 kb_z + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Duskwood +SD%Complete: 100 +SDComment: Quest Support:8735 +SDCategory: Duskwood +EndScriptData */ + +#include "ScriptedPch.h" + +/*###### +# at_twilight_grove +######*/ + +bool AreaTrigger_at_twilight_grove(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + if (pPlayer->HasQuestForItem(21149)) + { + if (Unit* TCorrupter = pPlayer->SummonCreature(15625,-10328.16,-489.57,49.95,0,TEMPSUMMON_MANUAL_DESPAWN,60000)) + { + TCorrupter->setFaction(14); + TCorrupter->SetMaxHealth(832750); + } + if (Unit* CorrupterSpeaker = pPlayer->SummonCreature(1,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ()-1,0,TEMPSUMMON_TIMED_DESPAWN,15000)) + { + CorrupterSpeaker->SetName("Twilight Corrupter"); + CorrupterSpeaker->SetVisibility(VISIBILITY_ON); + CorrupterSpeaker->MonsterYell("Come, $N. See what the Nightmare brings...",0,pPlayer->GetGUID()); + } + } + return false; +}; + +/*###### +# boss_twilight_corrupter +######*/ + +#define SPELL_SOUL_CORRUPTION 25805 +#define SPELL_CREATURE_OF_NIGHTMARE 25806 +#define SPELL_LEVEL_UP 24312 + +struct boss_twilight_corrupterAI : public ScriptedAI +{ + boss_twilight_corrupterAI(Creature *c) : ScriptedAI(c) {} + + uint32 SoulCorruption_Timer; + uint32 CreatureOfNightmare_Timer; + uint8 KillCount; + + void Reset() + { + SoulCorruption_Timer = 15000; + CreatureOfNightmare_Timer = 30000; + KillCount = 0; + } + void EnterCombat(Unit* /*who*/) + { + me->MonsterYell("The Nightmare cannot be stopped!",0,me->GetGUID()); + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + { + ++KillCount; + me->MonsterTextEmote("Twilight Corrupter squeezes the last bit of life out of $N and swallows their soul.", victim->GetGUID(),true); + + if (KillCount == 3) + { + DoCast(me, SPELL_LEVEL_UP, true); + KillCount = 0; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + if (SoulCorruption_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOUL_CORRUPTION); + SoulCorruption_Timer = rand()%4000+15000; //gotta confirm Timers + } else SoulCorruption_Timer-=diff; + if (CreatureOfNightmare_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CREATURE_OF_NIGHTMARE); + CreatureOfNightmare_Timer = 45000; //gotta confirm Timers + } else CreatureOfNightmare_Timer-=diff; + DoMeleeAttackIfReady(); + }; +}; +CreatureAI* GetAI_boss_twilight_corrupter(Creature* pCreature) +{ + return new boss_twilight_corrupterAI (pCreature); +} + +void AddSC_duskwood() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_twilight_corrupter"; + newscript->GetAI = &GetAI_boss_twilight_corrupter; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_twilight_grove"; + newscript->pAreaTrigger = &AreaTrigger_at_twilight_grove; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/eastern_plaguelands.cpp b/src/server/scripts/EasternKingdoms/eastern_plaguelands.cpp new file mode 100644 index 00000000000..0c1d3e9072c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/eastern_plaguelands.cpp @@ -0,0 +1,185 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Eastern_Plaguelands +SD%Complete: 100 +SDComment: Quest support: 5211, 5742. Special vendor Augustus the Touched +SDCategory: Eastern Plaguelands +EndScriptData */ + +/* ContentData +mobs_ghoul_flayer +npc_augustus_the_touched +npc_darrowshire_spirit +npc_tirion_fordring +EndContentData */ + +#include "ScriptedPch.h" + +//id8530 - cannibal ghoul +//id8531 - gibbering ghoul +//id8532 - diseased flayer + +struct mobs_ghoul_flayerAI : public ScriptedAI +{ + mobs_ghoul_flayerAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + + void EnterCombat(Unit* /*who*/) {} + + void JustDied(Unit* Killer) + { + if (Killer->GetTypeId() == TYPEID_PLAYER) + me->SummonCreature(11064, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000); + } +}; + +CreatureAI* GetAI_mobs_ghoul_flayer(Creature* pCreature) +{ + return new mobs_ghoul_flayerAI (pCreature); +} + +/*###### +## npc_augustus_the_touched +######*/ + +bool GossipHello_npc_augustus_the_touched(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(6164)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_augustus_the_touched(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + return true; +} + +/*###### +## npc_darrowshire_spirit +######*/ + +#define SPELL_SPIRIT_SPAWNIN 17321 + +struct npc_darrowshire_spiritAI : public ScriptedAI +{ + npc_darrowshire_spiritAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + DoCast(me, SPELL_SPIRIT_SPAWNIN); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) {} + +}; +CreatureAI* GetAI_npc_darrowshire_spirit(Creature* pCreature) +{ + return new npc_darrowshire_spiritAI (pCreature); +} + +bool GossipHello_npc_darrowshire_spirit(Player* pPlayer, Creature* pCreature) +{ + pPlayer->SEND_GOSSIP_MENU(3873, pCreature->GetGUID()); + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + return true; +} + +/*###### +## npc_tirion_fordring +######*/ + +#define GOSSIP_HELLO "I am ready to hear your tale, Tirion." +#define GOSSIP_SELECT1 "Thank you, Tirion. What of your identity?" +#define GOSSIP_SELECT2 "That is terrible." +#define GOSSIP_SELECT3 "I will, Tirion." + +bool GossipHello_npc_tirion_fordring(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(5742) == QUEST_STATUS_INCOMPLETE && pPlayer->getStandState() == UNIT_STAND_STATE_SIT) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_tirion_fordring(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(4493, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(4494, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(4495, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(5742); + break; + } + return true; +} + +void AddSC_eastern_plaguelands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mobs_ghoul_flayer"; + newscript->GetAI = &GetAI_mobs_ghoul_flayer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_augustus_the_touched"; + newscript->pGossipHello = &GossipHello_npc_augustus_the_touched; + newscript->pGossipSelect = &GossipSelect_npc_augustus_the_touched; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_darrowshire_spirit"; + newscript->GetAI = &GetAI_npc_darrowshire_spirit; + newscript->pGossipHello = &GossipHello_npc_darrowshire_spirit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tirion_fordring"; + newscript->pGossipHello = &GossipHello_npc_tirion_fordring; + newscript->pGossipSelect = &GossipSelect_npc_tirion_fordring; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/elwynn_forest.cpp b/src/server/scripts/EasternKingdoms/elwynn_forest.cpp new file mode 100644 index 00000000000..b978507c557 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/elwynn_forest.cpp @@ -0,0 +1,101 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Elwynn_Forest +SD%Complete: 50 +SDComment: Quest support: 1786 +SDCategory: Elwynn Forest +EndScriptData */ + +/* ContentData +npc_henze_faulk +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_henze_faulk +######*/ + +#define SAY_HEAL -1100280 + +struct npc_henze_faulkAI : public ScriptedAI +{ + uint32 lifeTimer; + bool spellHit; + + npc_henze_faulkAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + lifeTimer = 120000; + me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + me->SetStandState(UNIT_STAND_STATE_DEAD); // lay down + spellHit = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void MoveInLineOfSight(Unit * /*who*/) + { + return; + } + + void UpdateAI(const uint32 diff) + { + if (me->IsStandState()) + { + if (lifeTimer <= diff) + { + EnterEvadeMode(); + return; + } + else + lifeTimer -= diff; + } + } + + void SpellHit(Unit * /*Hitter*/, const SpellEntry *Spellkind) + { + if (Spellkind->Id == 8593 && !spellHit) + { + DoCast(me, 32343); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + //me->RemoveAllAuras(); + DoScriptText(SAY_HEAL, me); + spellHit = true; + } + } + +}; +CreatureAI* GetAI_npc_henze_faulk(Creature* pCreature) +{ + return new npc_henze_faulkAI (pCreature); +} + +void AddSC_elwynn_forest() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_henze_faulk"; + newscript->GetAI = &GetAI_npc_henze_faulk; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/eversong_woods.cpp b/src/server/scripts/EasternKingdoms/eversong_woods.cpp new file mode 100644 index 00000000000..d1c7b9a6bfe --- /dev/null +++ b/src/server/scripts/EasternKingdoms/eversong_woods.cpp @@ -0,0 +1,711 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Eversong_Woods +SD%Complete: 100 +SDComment: Quest support: 8483, 8488, 8490, 9686 +SDCategory: Eversong Woods +EndScriptData */ + +/* ContentData +npc_prospector_anvilward +npc_apprentice_mirveda +npc_infused_crystal +npc_kelerun_bloodmourn +go_harbinger_second_trial +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_prospector_anvilward +######*/ + +#define GOSSIP_HELLO "I need a moment of your time, sir." +#define GOSSIP_SELECT "Why... yes, of course. I've something to show you right inside this building, Mr. Anvilward." + +enum eProspectorAnvilward +{ + SAY_ANVIL1 = -1000209, + SAY_ANVIL2 = -1000210, + QUEST_THE_DWARVEN_SPY = 8483, +}; + +struct npc_prospector_anvilwardAI : public npc_escortAI +{ + // CreatureAI functions + npc_prospector_anvilwardAI(Creature *c) : npc_escortAI(c) {} + + // Pure Virtual Functions + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch (i) + { + case 0: DoScriptText(SAY_ANVIL1, me, pPlayer); break; + case 5: DoScriptText(SAY_ANVIL2, me, pPlayer); break; + case 6: me->setFaction(24); break; + } + } + + void Reset() + { + me->RestoreFaction(); + } + + void JustDied(Unit* /*killer*/) + { + me->RestoreFaction(); + } +}; + +CreatureAI* GetAI_npc_prospector_anvilward(Creature* pCreature) +{ + return new npc_prospector_anvilwardAI(pCreature); +} + +bool GossipHello_npc_prospector_anvilward(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_THE_DWARVEN_SPY) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(8239, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_prospector_anvilward(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(8240, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + if (npc_escortAI* pEscortAI = CAST_AI(npc_prospector_anvilwardAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + break; + } + return true; +} + +/*###### +## Quest 9686 Second Trial +######*/ + +#define QUEST_SECOND_TRIAL 9686 + +#define MASTER_KELERUN_BLOODMOURN 17807 + +#define CHAMPION_BLOODWRATH 17809 +#define CHAMPION_LIGHTREND 17810 +#define CHAMPION_SWIFTBLADE 17811 +#define CHAMPION_SUNSTRIKER 17812 + +#define HARBINGER_OF_THE_SECOND_TRIAL 182052 + +#define SPELL_FLASH_OF_LIGHT 19939 +#define TIMER_FLASH_OF_LIGHT 3225 + +#define SPELL_SEAL_OF_JUSTICE 20164 +#define TIMER_SEAL_OF_JUSTICE 10000 + +#define SPELL_JUDGEMENT_OF_LIGHT 20271 +#define TIMER_JUDGEMENT_OF_LIGHT 10000 + +#define SPELL_SEAL_OF_COMMAND 20375 +#define TIMER_SEAL_OF_COMMAND 20000 + +#define OFFSET_NEXT_ATTACK 750 + +#define FACTION_HOSTILE 45 +#define FACTION_FRIENDLY 7 + +// missing from db +#define TEXT_SECOND_TRIAL_1 -1645006 +#define TEXT_SECOND_TRIAL_2 -1645007 +#define TEXT_SECOND_TRIAL_3 -1645008 +#define TEXT_SECOND_TRIAL_4 -1645009 + +struct Locations +{ + float x, y, z, o; +}; + +static Locations SpawnPosition[]= +{ + {5.3, -11.8, 0.361, 4.2}, + {11.2, -29.17, 0.361, 2.7}, + {-5.7, -34.85, 0.361, 1.09}, + {-11.9, -18, 0.361, 5.87} +}; + +static uint32 PaladinEntry[] = {CHAMPION_BLOODWRATH, CHAMPION_LIGHTREND, CHAMPION_SWIFTBLADE, CHAMPION_SUNSTRIKER}; + +/*###### +## npc_second_trial_paladin +######*/ + +struct npc_secondTrialAI : public ScriptedAI +{ + npc_secondTrialAI(Creature *c) : ScriptedAI(c) {} + + uint32 timer; + uint8 questPhase; + uint64 summonerGuid; + + bool spellFlashLight; + bool spellJustice; + bool spellJudLight; + bool spellCommand; + + uint32 timerFlashLight; + uint32 timerJustice; + uint32 timerJudLight; + uint32 timerCommand; + + void Reset() + { + + timer = 2000; + questPhase = 0; + summonerGuid = 0; + + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_KNEEL); + me->setFaction(FACTION_FRIENDLY); + + spellFlashLight = false; + spellJustice = false; + spellJudLight = false; + spellCommand = false; + + switch(me->GetEntry()) + { + case CHAMPION_BLOODWRATH: + spellFlashLight = true; + timerFlashLight = TIMER_FLASH_OF_LIGHT; + break; + case CHAMPION_LIGHTREND: + spellJustice = true; + timerJustice = 500; + break; + case CHAMPION_SWIFTBLADE: + spellJudLight = false; // Misses Script Effect // http://www.wowhead.com/?spell=20271 + timerJudLight = 500; + break; + case CHAMPION_SUNSTRIKER: + spellFlashLight = true; + spellJudLight = false; // Misses Script Effect // http://www.wowhead.com/?spell=20271 + spellCommand = false; // Misses Dummy // http://www.wowhead.com/?spell=20375 + timerFlashLight = TIMER_FLASH_OF_LIGHT; + timerJudLight = 500; + timerCommand = 1500; + break; + } + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (questPhase == 1) + if (timer <= diff) + { + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); + me->setFaction(FACTION_HOSTILE); + questPhase = 0; + + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + me->AddThreat(pTarget, 5000000.0f); + AttackStart(pTarget); + } + } + else + timer -= diff; + + if (!UpdateVictim()) + return; + + // healer + if (spellFlashLight) + if (me->GetHealth()*100 / me->GetMaxHealth() < 70) + if (timerFlashLight <= diff) + { + DoCast(me, SPELL_FLASH_OF_LIGHT); + timerFlashLight = TIMER_FLASH_OF_LIGHT + rand()%TIMER_FLASH_OF_LIGHT; + } + else + timerFlashLight -= diff; + + if (spellJustice) + if (timerJustice <= diff) + { + DoCast(me, SPELL_SEAL_OF_JUSTICE); + timerJustice = TIMER_SEAL_OF_JUSTICE + rand()%TIMER_SEAL_OF_JUSTICE; + } + else + timerJustice -= diff; + + if (spellJudLight) + if (timerJudLight <= diff) + { + DoCast(me, SPELL_JUDGEMENT_OF_LIGHT); + timerJudLight = TIMER_JUDGEMENT_OF_LIGHT + rand()%TIMER_JUDGEMENT_OF_LIGHT; + } + else + timerJudLight -= diff; + + if (spellCommand) + if (timerCommand <= diff) + { + DoCast(me, TIMER_SEAL_OF_COMMAND); + timerCommand = TIMER_SEAL_OF_COMMAND + rand()%TIMER_SEAL_OF_COMMAND; + } + else + timerCommand -= diff; + + DoMeleeAttackIfReady(); + } + + void Activate(uint64 summonerguid); + void KilledUnit(Unit* Killed); + void JustDied(Unit* Killer); + +}; + +/*###### +## npc_second_trial_controller +######*/ + +struct master_kelerun_bloodmournAI : public ScriptedAI +{ + master_kelerun_bloodmournAI(Creature *c) : ScriptedAI(c) {} + + uint8 questPhase; + uint8 paladinPhase; + uint32 timer; + + uint64 paladinGuid[4]; + + void Reset() + { + questPhase = 0; + timer = 60000; + paladinPhase = 0; + for (uint8 i = 0; i < 4; ++i) + paladinGuid[i] = 0; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + // Quest accepted but object not activated, object despawned (if in sync 1 minute!) + if (questPhase == 1) + { + if (timer <= diff) + Reset(); + else + timer -= diff; + } + // fight the 4 paladin mobs phase + else if (questPhase == 2) + { + if (timer <= diff) + { + if (Creature* paladinSpawn = Unit::GetCreature((*me), paladinGuid[paladinPhase])) + { + CAST_AI(npc_secondTrialAI, paladinSpawn->AI())->Activate(me->GetGUID()); + + switch(paladinPhase) + { + case 0: + DoScriptText(TEXT_SECOND_TRIAL_1,me); + break; + case 1: + DoScriptText(TEXT_SECOND_TRIAL_2,me); + break; + case 2: + DoScriptText(TEXT_SECOND_TRIAL_3,me); + break; + case 3: + DoScriptText(TEXT_SECOND_TRIAL_4,me); + break; + } + } + else + Reset(); + + questPhase = 4; + timer = OFFSET_NEXT_ATTACK; + } + else + timer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void StartEvent() + { + + if (questPhase == 1) + { // no player check, quest can be finished as group, so no complex PlayerGUID/group search code + + for (uint8 i = 0; i < 4; ++i) + if (Creature *pSummoned = DoSpawnCreature(PaladinEntry[i], SpawnPosition[i].x, SpawnPosition[i].y, SpawnPosition[i].z, SpawnPosition[i].o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 180000)) + paladinGuid[i] = pSummoned->GetGUID(); + + timer = OFFSET_NEXT_ATTACK; + questPhase = 2; + } + } + + void SecondTrialKill(); + void SummonedCreatureDespawn(Creature* /*c*/) {} +}; + +bool GossipHello_master_kelerun_bloodmourn(Player* pPlayer, Creature* pCreature) +{ + // quest only available if not already started + // Quest_template flag is set to : QUEST_FLAGS_EVENT + // Escort quests or any other event-driven quests. If player in party, all players that can accept this quest will receive confirmation box to accept quest. + // !not sure if this really works! + + if (CAST_AI(master_kelerun_bloodmournAI, pCreature->AI())->questPhase == 0) + { + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + pPlayer->SendPreparedQuest(pCreature->GetGUID()); + } + + pPlayer->SEND_GOSSIP_MENU(pCreature->GetEntry(), pCreature->GetGUID()); + return true; +} + +bool QuestAccept_master_kelerun_bloodmourn(Player* /*pPlayer*/, Creature* pCreature, Quest const *quest) +{ + // One Player exclusive quest, wait for user go activation + if (quest->GetQuestId() == QUEST_SECOND_TRIAL) + CAST_AI(master_kelerun_bloodmournAI, pCreature->AI())->questPhase = 1; + + return true; +} + +void master_kelerun_bloodmournAI::SecondTrialKill() +{ + if (questPhase > 0) + { + ++paladinPhase; + + if (paladinPhase < 4) + questPhase = 2; + else + Reset(); // Quest Complete, QuestComplete handler is in npc_secondTrialAI::JustDied + } +} + +void npc_secondTrialAI::JustDied(Unit* Killer) +{ + if (Killer->GetTypeId() == TYPEID_PLAYER) + { + if (Creature *pSummoner = Unit::GetCreature((*me), summonerGuid)) + CAST_AI(master_kelerun_bloodmournAI, pSummoner->AI())->SecondTrialKill(); + + // last kill quest complete for group + if (me->GetEntry() == CHAMPION_SUNSTRIKER) + { + if (Group *pGroup = CAST_PLR(Killer)->GetGroup()) + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pGroupGuy = itr->getSource(); + + // for any leave or dead (with not released body) group member at appropriate distance + if (pGroupGuy && pGroupGuy->IsAtGroupRewardDistance(me) && !pGroupGuy->GetCorpse() && pGroupGuy->GetQuestStatus(QUEST_SECOND_TRIAL) == QUEST_STATUS_INCOMPLETE) + pGroupGuy->CompleteQuest(QUEST_SECOND_TRIAL); + } + } + else if (CAST_PLR(Killer)->GetQuestStatus(QUEST_SECOND_TRIAL) == QUEST_STATUS_INCOMPLETE) + CAST_PLR(Killer)->CompleteQuest(QUEST_SECOND_TRIAL); + } + } +} + +void npc_secondTrialAI::KilledUnit(Unit* Killed) +{ + if (Killed->GetTypeId() == TYPEID_PLAYER) + if (CAST_PLR(Killed)->GetQuestStatus(QUEST_SECOND_TRIAL) == QUEST_STATUS_INCOMPLETE) + CAST_PLR(Killed)->FailQuest(QUEST_SECOND_TRIAL); +} + +void npc_secondTrialAI::Activate(uint64 summonerguid) +{ + questPhase = 1; + summonerGuid = summonerguid; +} + +CreatureAI* GetAI_master_kelerun_bloodmourn(Creature* pCreature) +{ + return new master_kelerun_bloodmournAI (pCreature); +} + +CreatureAI* GetAI_npc_secondTrial(Creature* pCreature) +{ + return new npc_secondTrialAI (pCreature); +} + +/*###### +## go_second_trial +######*/ + +bool GOHello_go_second_trial(Player* /*pPlayer*/, GameObject* pGO) +{ + // find spawn :: master_kelerun_bloodmourn + if (Creature *pCreature = pGO->FindNearestCreature(MASTER_KELERUN_BLOODMOURN, 30.0f)) + CAST_AI(master_kelerun_bloodmournAI, pCreature->AI())->StartEvent(); + + return true; +} + +/*###### +## npc_apprentice_mirveda +######*/ + +#define QUEST_UNEXPECTED_RESULT 8488 +#define MOB_GHARZUL 15958 +#define MOB_ANGERSHADE 15656 + +struct npc_apprentice_mirvedaAI : public ScriptedAI +{ + npc_apprentice_mirvedaAI(Creature* c) : ScriptedAI(c), Summons(me) {} + + uint32 KillCount; + uint64 PlayerGUID; + bool Summon; + SummonList Summons; + + void Reset() + { + KillCount = 0; + PlayerGUID = 0; + Summons.DespawnAll(); + Summon = false; + } + + void EnterCombat(Unit* /*who*/){} + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(me); + Summons.Summon(summoned); + } + + void SummonedCreatureDespawn(Creature* summoned) + { + Summons.Despawn(summoned); + ++KillCount; + } + + void JustDied(Unit* /*killer*/) + { + if (PlayerGUID) + if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) + CAST_PLR(pPlayer)->FailQuest(QUEST_UNEXPECTED_RESULT); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (KillCount >= 3 && PlayerGUID) + if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) + CAST_PLR(pPlayer)->CompleteQuest(QUEST_UNEXPECTED_RESULT); + + if (Summon) + { + me->SummonCreature(MOB_GHARZUL, 8745, -7134.32, 35.22, 0, TEMPSUMMON_CORPSE_DESPAWN, 4000); + me->SummonCreature(MOB_ANGERSHADE, 8745, -7134.32, 35.22, 0, TEMPSUMMON_CORPSE_DESPAWN, 4000); + me->SummonCreature(MOB_ANGERSHADE, 8745, -7134.32, 35.22, 0, TEMPSUMMON_CORPSE_DESPAWN, 4000); + Summon = false; + } + } +}; + +bool QuestAccept_npc_apprentice_mirveda(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_UNEXPECTED_RESULT) + { + CAST_AI(npc_apprentice_mirvedaAI, pCreature->AI())->Summon = true; + CAST_AI(npc_apprentice_mirvedaAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); + } + return true; +} + +CreatureAI* GetAI_npc_apprentice_mirvedaAI(Creature* pCreature) +{ + return new npc_apprentice_mirvedaAI (pCreature); +} + +/*###### +## npc_infused_crystal +######*/ + +#define MOB_ENRAGED_WRAITH 17086 +#define EMOTE -1000283 +#define QUEST_POWERING_OUR_DEFENSES 8490 + +struct Location +{ + float x, y, z; +}; + +static Location SpawnLocations[] = +{ + {8270.68, -7188.53, 139.619}, + {8284.27, -7187.78, 139.603}, + {8297.43, -7193.53, 139.603}, + {8303.5, -7201.96, 139.577}, + {8273.22, -7241.82, 139.382}, + {8254.89, -7222.12, 139.603}, + {8278.51, -7242.13, 139.162}, + {8267.97, -7239.17, 139.517} +}; + +struct npc_infused_crystalAI : public Scripted_NoMovementAI +{ + npc_infused_crystalAI(Creature* c) : Scripted_NoMovementAI(c) {} + + uint32 EndTimer; + uint32 WaveTimer; + bool Completed; + bool Progress; + uint64 PlayerGUID; + + void Reset() + { + EndTimer = 0; + Completed = false; + Progress = false; + PlayerGUID = 0; + WaveTimer = 0; + } + + void MoveInLineOfSight(Unit* who) + { + if (!Progress && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 10.0f)) + { + if (CAST_PLR(who)->GetQuestStatus(QUEST_POWERING_OUR_DEFENSES) == QUEST_STATUS_INCOMPLETE) + { + PlayerGUID = who->GetGUID(); + WaveTimer = 1000; + EndTimer = 60000; + Progress = true; + } + } + } + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(me); + } + + void JustDied(Unit* /*killer*/) + { + if (PlayerGUID && !Completed) + if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) + CAST_PLR(pPlayer)->FailQuest(QUEST_POWERING_OUR_DEFENSES); + } + + void UpdateAI(const uint32 diff) + { + if (EndTimer < diff && Progress) + { + DoScriptText(EMOTE, me); + Completed = true; + if (PlayerGUID) + if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) + CAST_PLR(pPlayer)->CompleteQuest(QUEST_POWERING_OUR_DEFENSES); + + me->DealDamage(me,me->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + } else EndTimer -= diff; + + if (WaveTimer < diff && !Completed && Progress) + { + uint32 ran1 = rand()%8; + uint32 ran2 = rand()%8; + uint32 ran3 = rand()%8; + me->SummonCreature(MOB_ENRAGED_WRAITH, SpawnLocations[ran1].x, SpawnLocations[ran1].y, SpawnLocations[ran1].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + me->SummonCreature(MOB_ENRAGED_WRAITH, SpawnLocations[ran2].x, SpawnLocations[ran2].y, SpawnLocations[ran2].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + me->SummonCreature(MOB_ENRAGED_WRAITH, SpawnLocations[ran3].x, SpawnLocations[ran3].y, SpawnLocations[ran3].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + WaveTimer = 30000; + } else WaveTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_infused_crystalAI(Creature* pCreature) +{ + return new npc_infused_crystalAI (pCreature); +} + +void AddSC_eversong_woods() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_prospector_anvilward"; + newscript->GetAI = &GetAI_npc_prospector_anvilward; + newscript->pGossipHello = &GossipHello_npc_prospector_anvilward; + newscript->pGossipSelect = &GossipSelect_npc_prospector_anvilward; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_second_trial_controller"; + newscript->GetAI = &GetAI_master_kelerun_bloodmourn; + newscript->pGossipHello = &GossipHello_master_kelerun_bloodmourn; + newscript->pQuestAccept = &QuestAccept_master_kelerun_bloodmourn; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_second_trial_paladin"; + newscript->GetAI = &GetAI_npc_secondTrial; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_second_trial"; + newscript->pGOHello = &GOHello_go_second_trial; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_apprentice_mirveda"; + newscript->GetAI = &GetAI_npc_apprentice_mirvedaAI; + newscript->pQuestAccept = &QuestAccept_npc_apprentice_mirveda; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_infused_crystal"; + newscript->GetAI = &GetAI_npc_infused_crystalAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/ghostlands.cpp b/src/server/scripts/EasternKingdoms/ghostlands.cpp new file mode 100644 index 00000000000..67e4e764959 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ghostlands.cpp @@ -0,0 +1,250 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Ghostlands +SD%Complete: 100 +SDComment: Quest support: 9692, 9212. Obtain Budd's Guise of Zul'aman. Vendor Rathis Tomber +SDCategory: Ghostlands +EndScriptData */ + +/* ContentData +npc_blood_knight_dawnstar +npc_budd_nedreck +npc_rathis_tomber +npc_ranger_lilatha +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_blood_knight_dawnstar +######*/ + +#define GOSSIP_H_BKD "Take Blood Knight Insignia" + +bool GossipHello_npc_blood_knight_dawnstar(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(9692) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(24226,1,true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_H_BKD, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_blood_knight_dawnstar(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 24226, 1, false); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, 24226, 1, true); + pPlayer->PlayerTalkClass->ClearMenus(); + } + } + return true; +} + +/*###### +## npc_budd_nedreck +######*/ + +#define GOSSIP_HBN "You gave the crew disguises?" + +bool GossipHello_npc_budd_nedreck(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(11166) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_budd_nedreck(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, 42540, false); + } + return true; +} + +/*###### +## npc_rathis_tomber +######*/ + +bool GossipHello_npc_rathis_tomber(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(9152)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + pPlayer->SEND_GOSSIP_MENU(8432, pCreature->GetGUID()); + }else + pPlayer->SEND_GOSSIP_MENU(8431, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_rathis_tomber(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + return true; +} + +/*###### +## npc_ranger_lilatha +######*/ + +enum eEnums +{ + SAY_START = -1000140, + SAY_PROGRESS1 = -1000141, + SAY_PROGRESS2 = -1000142, + SAY_PROGRESS3 = -1000143, + SAY_END1 = -1000144, + SAY_END2 = -1000145, + SAY_CAPTAIN_ANSWER = -1000146, + + QUEST_ESCAPE_FROM_THE_CATACOMBS = 9212, + GO_CAGE = 181152, + NPC_CAPTAIN_HELIOS = 16220, + FACTION_SMOON_E = 1603, +}; + +struct npc_ranger_lilathaAI : public npc_escortAI +{ + npc_ranger_lilathaAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 0: + { + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + if (GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 20)) + Cage->SetGoState(GO_STATE_ACTIVE); + DoScriptText(SAY_START, me, pPlayer); + break; + } + case 5: + DoScriptText(SAY_PROGRESS1, me, pPlayer); + case 11: + DoScriptText(SAY_PROGRESS2, me, pPlayer); + me->SetOrientation(4.762841); + break; + case 18: + { + DoScriptText(SAY_PROGRESS3, me, pPlayer); + Creature* Summ1 = me->SummonCreature(16342, 7627.083984, -7532.538086, 152.128616, 1.082733, TEMPSUMMON_DEAD_DESPAWN, 0); + Creature* Summ2 = me->SummonCreature(16343, 7620.432129, -7532.550293, 152.454865, 0.827478, TEMPSUMMON_DEAD_DESPAWN, 0); + if (Summ1 && Summ2) + { + Summ1->Attack(me, true); + Summ2->Attack(pPlayer, true); + } + me->AI()->AttackStart(Summ1); + break; + } + case 19: me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); break; + case 25: me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); break; + case 30: + if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(pPlayer)->GroupEventHappens(QUEST_ESCAPE_FROM_THE_CATACOMBS,me); + break; + case 32: + me->SetOrientation(2.978281); + DoScriptText(SAY_END1, me, pPlayer); + break; + case 33: + me->SetOrientation(5.858011); + DoScriptText(SAY_END2, me, pPlayer); + Unit* CaptainHelios = me->FindNearestCreature(NPC_CAPTAIN_HELIOS, 50); + if (CaptainHelios) + DoScriptText(SAY_CAPTAIN_ANSWER, CaptainHelios, pPlayer); + break; + } + } + + void Reset() + { + if (GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 20)) + Cage->SetGoState(GO_STATE_READY); + } +}; + +bool QuestAccept_npc_ranger_lilatha(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_ESCAPE_FROM_THE_CATACOMBS) + { + pCreature->setFaction(113); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_ranger_lilathaAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_ranger_lilathaAI(Creature* pCreature) +{ + return new npc_ranger_lilathaAI(pCreature); +} + +void AddSC_ghostlands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_blood_knight_dawnstar"; + newscript->pGossipHello = &GossipHello_npc_blood_knight_dawnstar; + newscript->pGossipSelect = &GossipSelect_npc_blood_knight_dawnstar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_budd_nedreck"; + newscript->pGossipHello = &GossipHello_npc_budd_nedreck; + newscript->pGossipSelect = &GossipSelect_npc_budd_nedreck; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_rathis_tomber"; + newscript->pGossipHello = &GossipHello_npc_rathis_tomber; + newscript->pGossipSelect = &GossipSelect_npc_rathis_tomber; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ranger_lilatha"; + newscript->GetAI = &GetAI_npc_ranger_lilathaAI; + newscript->pQuestAccept = &QuestAccept_npc_ranger_lilatha; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp new file mode 100644 index 00000000000..c39bfb69910 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp @@ -0,0 +1,593 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Gnomeregan +SDAuthor: Manuel +SD%Complete: 90% +SDComment: Some visual effects are not implemented. +Script Data End */ + +#include "ScriptedPch.h" +#include "gnomeregan.h" +#include "ScriptedEscortAI.h" + +#define GOSSIP_START_EVENT "I am ready to being" + +enum eBlastmasterEmiShortfuse +{ + GOSSIP_TEXT_EMI = 1693, + + SAY_BLASTMASTER_0 = -1090000, + SAY_BLASTMASTER_1 = -1090001, + SAY_BLASTMASTER_2 = -1090002, + SAY_BLASTMASTER_3 = -1090003, + SAY_BLASTMASTER_4 = -1090004, + SAY_BLASTMASTER_5 = -1090005, + SAY_BLASTMASTER_6 = -1090006, + SAY_BLASTMASTER_7 = -1090007, + SAY_BLASTMASTER_8 = -1090008, + SAY_BLASTMASTER_9 = -1090009, + SAY_BLASTMASTER_10 = -1090010, + SAY_BLASTMASTER_11 = -1090011, + SAY_BLASTMASTER_12 = -1090012, + SAY_BLASTMASTER_13 = -1090013, + SAY_BLASTMASTER_14 = -1090014, + SAY_BLASTMASTER_15 = -1090015, + SAY_BLASTMASTER_16 = -1090016, + SAY_BLASTMASTER_17 = -1090017, + SAY_BLASTMASTER_18 = -1090018, + SAY_BLASTMASTER_19 = -1090019, + SAY_BLASTMASTER_20 = -1090020, + SAY_BLASTMASTER_21 = -1090021, + SAY_BLASTMASTER_22 = -1090022, + SAY_BLASTMASTER_23 = -1090023, + SAY_BLASTMASTER_24 = -1090024, + SAY_BLASTMASTER_25 = -1090025, + SAY_BLASTMASTER_26 = -1090026, + SAY_BLASTMASTER_27 = -1090027, + + SAY_GRUBBIS = -1090028 +}; + +const Position SpawnPosition[] = +{ + {-557.630,-114.514,-152.209,0.641}, + {-555.263,-113.802,-152.737,0.311}, + {-552.154,-112.476,-153.349,0.621}, + {-548.692,-111.089,-154.090,0.621}, + {-546.905,-108.340,-154.877,0.729}, + {-547.736,-105.154,-155.176,0.372}, + {-547.274,-114.109,-153.952,0.735}, + {-552.534,-110.012,-153.577,0.747}, + {-550.708,-116.436,-153.103,0.679}, + {-554.030,-115.983,-152.635,0.695}, + {-494.595,-87.516,149.116,3.344}, + {-493.349,-90.845,-148.882,3.717}, + {-491.995,-87.619,-148.197,3.230}, + {-490.732,-90.739,-148.091,3.230}, + {-490.554,-89.114,-148.055,3.230}, + {-495.240,-90.808,-149.493,3.238}, + {-494.195,-89.553,-149.131,3.254} +}; + +struct npc_blastmaster_emi_shortfuseAI : public npc_escortAI +{ + npc_blastmaster_emi_shortfuseAI(Creature* pCreature) : npc_escortAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + pCreature->RestoreFaction(); + Reset(); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiTimer; + + std::list SummonList; + std::list GoSummonList; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + uiTimer = 0; + uiPhase = 0; + + RestoreAll(); + + SummonList.clear(); + GoSummonList.clear(); + } + } + + void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) + { + uiTimer = uiTimerStep; + if (bNextStep) + ++uiPhase; + else + uiPhase = uiPhaseStep; + } + + void CaveDestruction(bool bBool) + { + if (GoSummonList.empty()) + return; + + for (std::list::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) + { + if (GameObject* pGo = GameObject::GetGameObject(*me, *itr)) + { + if (pGo) + { + if (Creature *trigger = pGo->SummonTrigger(pGo->GetPositionX(), pGo->GetPositionY(),pGo->GetPositionZ(), 0, 1)) + { + //visual effects are not working! ¬¬ + trigger->CastSpell(trigger,11542,true); + trigger->CastSpell(trigger,35470,true); + } + pGo->RemoveFromWorld(); + //pGo->CastSpell(me,12158); makes all die?! + } + } + } + + if (bBool) + { + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) + pInstance->HandleGameObject(NULL,false,pGo); + }else + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) + pInstance->HandleGameObject(NULL,false,pGo); + } + + void SetInFace(bool bBool) + { + if (!pInstance) + return; + + if (bBool) + { + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) + me->SetFacingToObject(pGo); + }else + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) + me->SetFacingToObject(pGo); + } + + void RestoreAll() + { + if (!pInstance) + return; + + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) + pInstance->HandleGameObject(NULL,false,pGo); + + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) + pInstance->HandleGameObject(NULL,false,pGo); + + if (!GoSummonList.empty()) + for (std::list::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) + { + if (GameObject* pGo = GameObject::GetGameObject(*me, *itr)) + pGo->RemoveFromWorld(); + } + + if (!SummonList.empty()) + for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) + { + if (Creature* pSummon = Unit::GetCreature(*me, *itr)) + { + if (pSummon->isAlive()) + pSummon->DisappearAndDie(); + else + pSummon->RemoveCorpse(); + } + } + } + + void AggroAllPlayers(Creature* pTemp) + { + Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + pTemp->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(pTemp); + pTemp->AddThreat(pPlayer, 0.0f); + } + } + } + } + + void WaypointReached(uint32 uiPoint) + { + //just in case + if (GetPlayerForEscort()) + if (me->getFaction() != GetPlayerForEscort()->getFaction()) + me->setFaction(GetPlayerForEscort()->getFaction()); + + switch(uiPoint) + { + case 3: + SetEscortPaused(true); + NextStep(2000,false,3); + break; + case 7: + SetEscortPaused(true); + NextStep(2000,false,4); + break; + case 9: + NextStep(1000,false,8); + break; + case 10: + NextStep(25000,false,10); + break; + case 11: + SetEscortPaused(true); + SetInFace(true); + NextStep(1000,false,11); + break; + case 12: + NextStep(25000,false,18); + break; + case 13: + Summon(7); + NextStep(25000,false,19); + break; + case 14: + SetInFace(false); + DoScriptText(SAY_BLASTMASTER_26,me); + SetEscortPaused(true); + NextStep(5000,false,20); + break; + } + } + + void SetData(uint32 uiI,uint32 uiValue) + { + switch(uiI) + { + case 1: + SetEscortPaused(true); + DoScriptText(SAY_BLASTMASTER_0,me); + NextStep(1500,true); + break; + case 2: + if (!pInstance) + return; + + switch(uiValue) + { + case 1: + pInstance->SetData(TYPE_EVENT, IN_PROGRESS); + break; + case 2: + pInstance->SetData(TYPE_EVENT, DONE); + NextStep(5000,false,22); + break; + } + break; + } + } + + void Summon(uint8 uiCase) + { + switch(uiCase) + { + case 1: + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[5], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[6], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[7], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[8], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[9], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + break; + case 2: + if (GameObject* pGo = me->SummonGameObject(183410, -533.140,-105.322,-156.016, 0, 0, 0, 0, 0, 1000)) + { + GoSummonList.push_back(pGo->GetGUID()); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! + } + Summon(3); + break; + case 3: + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + DoScriptText(SAY_BLASTMASTER_19,me); + break; + case 4: + if (GameObject* pGo = me->SummonGameObject(183410, -542.199,-96.854,-155.790, 0, 0, 0, 0, 0, 1000)) + { + GoSummonList.push_back(pGo->GetGUID()); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + } + break; + case 5: + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + DoScriptText(SAY_BLASTMASTER_15,me); + break; + case 6: + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[10], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[11], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[12], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[13], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[14], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + break; + case 7: + if (GameObject* pGo = me->SummonGameObject(183410, -507.820,-103.333,-151.353, 0, 0, 0, 0, 0, 1000)) + { + GoSummonList.push_back(pGo->GetGUID()); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! + Summon(6); + } + break; + case 8: + if (GameObject* pGo = me->SummonGameObject(183410, -511.829,-86.249,-151.431, 0, 0, 0, 0, 0, 1000)) + { + GoSummonList.push_back(pGo->GetGUID()); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! + } + break; + case 9: + if (Creature* pGrubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000)) + DoScriptText(SAY_GRUBBIS,pGrubbis); + me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + break; + } + } + + void UpdateEscortAI(const uint32 uiDiff) + { + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + DoScriptText(SAY_BLASTMASTER_1,me); + NextStep(1500,true); + break; + case 2: + SetEscortPaused(false); + NextStep(0,false,0); + break; + case 3: + DoScriptText(SAY_BLASTMASTER_2,me); + SetEscortPaused(false); + NextStep(0,false,0); + break; + case 4: + DoScriptText(SAY_BLASTMASTER_3,me); + NextStep(3000,true); + break; + case 5: + DoScriptText(SAY_BLASTMASTER_4,me); + NextStep(3000,true); + break; + case 6: + SetInFace(true); + DoScriptText(SAY_BLASTMASTER_5,me); + Summon(1); + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) + pInstance->HandleGameObject(NULL,true,pGo); + NextStep(3000,true); + break; + case 7: + DoScriptText(SAY_BLASTMASTER_6,me); + SetEscortPaused(false); + NextStep(0,false,0); + break; + case 8: + me->HandleEmoteCommand(EMOTE_STATE_WORK); + NextStep(25000,true); + break; + case 9: + Summon(2); + NextStep(0,false); + break; + case 10: + Summon(4); + NextStep(0,false); + break; + case 11: + DoScriptText(SAY_BLASTMASTER_17,me); + NextStep(5000,true); + break; + case 12: + DoScriptText(SAY_BLASTMASTER_18,me); + NextStep(5000,true); + break; + case 13: + DoScriptText(SAY_BLASTMASTER_20,me); + CaveDestruction(true); + NextStep(8000,true); + break; + case 14: + DoScriptText(SAY_BLASTMASTER_21,me); + NextStep(8500,true); + break; + case 15: + DoScriptText(SAY_BLASTMASTER_22,me); + NextStep(2000,true); + break; + case 16: + DoScriptText(SAY_BLASTMASTER_23,me); + SetInFace(false); + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) + pInstance->HandleGameObject(NULL,true,pGo); + NextStep(2000,true); + break; + case 17: + SetEscortPaused(false); + DoScriptText(SAY_BLASTMASTER_24,me); + Summon(6); + NextStep(0,false); + break; + case 18: + Summon(7); + NextStep(0,false); + break; + case 19: + SetInFace(false); + Summon(8); + DoScriptText(SAY_BLASTMASTER_25,me); + NextStep(0,false); + break; + case 20: + DoScriptText(SAY_BLASTMASTER_27,me); + NextStep(2000,true); + break; + case 21: + Summon(9); + NextStep(0,false); + break; + case 22: + CaveDestruction(false); + DoScriptText(SAY_BLASTMASTER_20,me); + NextStep(0,false); + break; + } + } else uiTimer -= uiDiff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* pSummon) + { + SummonList.push_back(pSummon->GetGUID()); + AggroAllPlayers(pSummon); + } +}; + +CreatureAI* GetAI_npc_blastmaster_emi_shortfuse(Creature* pCreature) +{ + return new npc_blastmaster_emi_shortfuseAI(pCreature); +} + +bool GossipHello_npc_blastmaster_emi_shortfuse(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && pInstance->GetData(TYPE_EVENT) == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_EMI, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_blastmaster_emi_shortfuse(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + if (npc_escortAI* pEscortAI = CAST_AI(npc_blastmaster_emi_shortfuseAI, pCreature->AI())) + pEscortAI->Start(true, false,pPlayer->GetGUID()); + + pCreature->setFaction(pPlayer->getFaction()); + pCreature->AI()->SetData(1,0); + + pPlayer->CLOSE_GOSSIP_MENU(); + } + return true; +} + +struct boss_grubbisAI : public ScriptedAI +{ + boss_grubbisAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SetDataSummoner(); + } + + void SetDataSummoner() + { + if (!me->isSummon()) + return; + + if (Unit* pSummon = CAST_SUM(me)->GetSummoner()) + CAST_CRE(pSummon)->AI()->SetData(2,1); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (!me->isSummon()) + return; + + if (Unit* pSummon = CAST_SUM(me)->GetSummoner()) + CAST_CRE(pSummon)->AI()->SetData(2,2); + } +}; + +CreatureAI* GetAI_boss_grubbis(Creature* pCreature) +{ + return new boss_grubbisAI(pCreature); +} + +void AddSC_gnomeregan() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_blastmaster_emi_shortfuse"; + newscript->pGossipHello = &GossipHello_npc_blastmaster_emi_shortfuse; + newscript->pGossipSelect = &GossipSelect_npc_blastmaster_emi_shortfuse; + newscript->GetAI = &GetAI_npc_blastmaster_emi_shortfuse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_grubbis"; + newscript->GetAI = &GetAI_boss_grubbis; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h b/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h new file mode 100644 index 00000000000..e46c811e9b1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_GNOMEREGAN_H +#define DEF_GNOMEREGAN_H + +enum eGameObjects +{ + GO_CAVE_IN_LEFT = 146085, + GO_CAVE_IN_RIGHT = 146086 +}; + +enum eCreatures +{ + NPC_BLASTMASTER_EMI_SHORTFUSE = 7998, + NPC_CAVERNDEEP_AMBUSHER = 6207, + NPC_GRUBBIS = 7361, + NPC_CHOMPER = 6215 +}; + +enum eData +{ + TYPE_EVENT = 1 +}; + +enum eData64 +{ + DATA_GO_CAVE_IN_LEFT, + DATA_GO_CAVE_IN_RIGHT, + DATA_NPC_BASTMASTER_EMI_SHORTFUSE +}; + +#endif diff --git a/src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp b/src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp new file mode 100644 index 00000000000..980a6d3552b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "gnomeregan.h" + +#define MAX_ENCOUNTER 1 + +struct instance_gnomeregan : public ScriptedInstance +{ + instance_gnomeregan(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + }; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 uiCaveInLeftGUID; + uint64 uiCaveInRightGUID; + + uint64 uiBastmasterEmiShortfuseGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + uiCaveInLeftGUID = 0; + uiCaveInRightGUID = 0; + + uiBastmasterEmiShortfuseGUID = 0; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) + { + switch(pCreature->GetEntry()) + { + case NPC_BLASTMASTER_EMI_SHORTFUSE: uiBastmasterEmiShortfuseGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*bAdd*/) + { + switch(pGo->GetEntry()) + { + case GO_CAVE_IN_LEFT: + uiCaveInLeftGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE || m_auiEncounter[0] == NOT_STARTED) + HandleGameObject(NULL,false,pGo); + break; + case GO_CAVE_IN_RIGHT: + uiCaveInRightGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE || m_auiEncounter[0] == NOT_STARTED) + HandleGameObject(NULL,false,pGo); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_EVENT: + m_auiEncounter[0] = uiData; + if (uiData == DONE) + SaveToDB(); + break; + } + } + + uint32 GetData(uint32 uiType, uint32 /*uiData*/) + { + switch(uiType) + { + case TYPE_EVENT: return m_auiEncounter[0]; + } + } + + uint64 GetData64(uint32 uiType) + { + switch(uiType) + { + case DATA_GO_CAVE_IN_LEFT: return uiCaveInLeftGUID; + case DATA_GO_CAVE_IN_RIGHT: return uiCaveInRightGUID; + case DATA_NPC_BASTMASTER_EMI_SHORTFUSE: return uiBastmasterEmiShortfuseGUID; + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_gnomeregan(Map* pMap) +{ + return new instance_gnomeregan(pMap); +} + +void AddSC_instance_gnomeregan() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "instance_gnomeregan"; + newscript->GetInstanceData = &GetInstanceData_instance_gnomeregan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/hinterlands.cpp b/src/server/scripts/EasternKingdoms/hinterlands.cpp new file mode 100644 index 00000000000..59002936e14 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/hinterlands.cpp @@ -0,0 +1,350 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Hinterlands +SD%Complete: 100 +SDComment: Quest support: 863, 2742 +SDCategory: The Hinterlands +EndScriptData */ + +/* ContentData +npc_00x09hl +npc_rinji +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_00x09hl +######*/ + +enum eOOX +{ + SAY_OOX_START = -1000287, + SAY_OOX_AGGRO1 = -1000288, + SAY_OOX_AGGRO2 = -1000289, + SAY_OOX_AMBUSH = -1000290, + SAY_OOX_END = -1000292, + + QUEST_RESQUE_OOX_09 = 836, + + NPC_MARAUDING_OWL = 7808, + NPC_VILE_AMBUSHER = 7809, + + FACTION_ESCORTEE_A = 774, + FACTION_ESCORTEE_H = 775 +}; + +struct npc_00x09hlAI : public npc_escortAI +{ + npc_00x09hlAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void Reset() { } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 26: + DoScriptText(SAY_OOX_AMBUSH, me); + break; + case 43: + DoScriptText(SAY_OOX_AMBUSH, me); + break; + case 64: + DoScriptText(SAY_OOX_END, me); + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->GroupEventHappens(QUEST_RESQUE_OOX_09, me); + break; + } + } + + void WaypointStart(uint32 uiPointId) + { + switch(uiPointId) + { + case 27: + for (uint8 i = 0; i < 3; ++i) + { + const Position src = {147.927444f, -3851.513428f, 130.893f, 0}; + Position dst; + me->GetRandomPoint(src, 7.0f, dst); + DoSummon(NPC_MARAUDING_OWL, dst, 25000, TEMPSUMMON_CORPSE_TIMED_DESPAWN); + } + break; + case 44: + for (uint8 i = 0; i < 3; ++i) + { + const Position src = {-141.151581f, -4291.213867f, 120.130f, 0}; + Position dst; + me->GetRandomPoint(src, 7.0f, dst); + me->SummonCreature(NPC_VILE_AMBUSHER, dst, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 25000); + } + break; + } + } + + void Aggro(Unit* pWho) + { + if (pWho->GetEntry() == NPC_MARAUDING_OWL || pWho->GetEntry() == NPC_VILE_AMBUSHER) + return; + + if (rand()%1) + DoScriptText(SAY_OOX_AGGRO1, me); + else + DoScriptText(SAY_OOX_AGGRO2, me); + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + } +}; + +bool QuestAccept_npc_00x09hl(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_RESQUE_OOX_09) + { + pCreature->SetStandState(UNIT_STAND_STATE_STAND); + + if (pPlayer->GetTeam() == ALLIANCE) + pCreature->setFaction(FACTION_ESCORTEE_A); + else if (pPlayer->GetTeam() == HORDE) + pCreature->setFaction(FACTION_ESCORTEE_H); + + DoScriptText(SAY_OOX_START, pCreature, pPlayer); + + if (npc_00x09hlAI* pEscortAI = CAST_AI(npc_00x09hlAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + } + return true; +} + +CreatureAI* GetAI_npc_00x09hl(Creature* pCreature) +{ + return new npc_00x09hlAI(pCreature); +} + +/*###### +## npc_rinji +######*/ + +enum eRinji +{ + SAY_RIN_FREE = -1000403, //from here + SAY_RIN_BY_OUTRUNNER = -1000404, + SAY_RIN_HELP_1 = -1000405, + SAY_RIN_HELP_2 = -1000406, //to here, are used also by 6182 but this is wrong... + SAY_RIN_COMPLETE = -1000407, + SAY_RIN_PROGRESS_1 = -1000408, + SAY_RIN_PROGRESS_2 = -1000409, + + QUEST_RINJI_TRAPPED = 2742, + NPC_RANGER = 2694, + NPC_OUTRUNNER = 2691, + GO_RINJI_CAGE = 142036 +}; + +struct Location +{ + float m_fX, m_fY, m_fZ; +}; + +Location m_afAmbushSpawn[] = +{ + {191.296204, -2839.329346, 107.388}, + {70.972466, -2848.674805, 109.459} +}; + +Location m_afAmbushMoveTo[] = +{ + {166.630386, -2824.780273, 108.153}, + {70.886589, -2874.335449, 116.675} +}; + +struct npc_rinjiAI : public npc_escortAI +{ + npc_rinjiAI(Creature* pCreature) : npc_escortAI(pCreature) + { + m_bIsByOutrunner = false; + m_iSpawnId = 0; + } + + bool m_bIsByOutrunner; + uint32 m_uiPostEventCount; + uint32 m_uiPostEventTimer; + int m_iSpawnId; + + void Reset() + { + m_uiPostEventCount = 0; + m_uiPostEventTimer = 3000; + } + + void JustRespawned() + { + m_bIsByOutrunner = false; + m_iSpawnId = 0; + + npc_escortAI::JustRespawned(); + } + + void EnterCombat(Unit* pWho) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (pWho->GetEntry() == NPC_OUTRUNNER && !m_bIsByOutrunner) + { + DoScriptText(SAY_RIN_BY_OUTRUNNER, pWho); + m_bIsByOutrunner = true; + } + + if (rand()%4) + return; + + //only if attacked and escorter is not in combat? + DoScriptText(RAND(SAY_RIN_HELP_1,SAY_RIN_HELP_2), me); + } + } + + void DoSpawnAmbush(bool bFirst) + { + if (!bFirst) + m_iSpawnId = 1; + + me->SummonCreature(NPC_RANGER, + m_afAmbushSpawn[m_iSpawnId].m_fX, m_afAmbushSpawn[m_iSpawnId].m_fY, m_afAmbushSpawn[m_iSpawnId].m_fZ, 0.0f, + TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + + for (int i = 0; i < 2; ++i) + { + me->SummonCreature(NPC_OUTRUNNER, + m_afAmbushSpawn[m_iSpawnId].m_fX, m_afAmbushSpawn[m_iSpawnId].m_fY, m_afAmbushSpawn[m_iSpawnId].m_fZ, 0.0f, + TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + } + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pSummoned->GetMotionMaster()->MovePoint(0, m_afAmbushMoveTo[m_iSpawnId].m_fX, m_afAmbushMoveTo[m_iSpawnId].m_fY, m_afAmbushMoveTo[m_iSpawnId].m_fZ); + } + + void WaypointReached(uint32 uiPointId) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(uiPointId) + { + case 1: + DoScriptText(SAY_RIN_FREE, me, pPlayer); + break; + case 7: + DoSpawnAmbush(true); + break; + case 13: + DoSpawnAmbush(false); + break; + case 17: + DoScriptText(SAY_RIN_COMPLETE, me, pPlayer); + pPlayer->GroupEventHappens(QUEST_RINJI_TRAPPED, me); + SetRun(); + m_uiPostEventCount = 1; + break; + } + } + + void UpdateEscortAI(const uint32 uiDiff) + { + //Check if we have a current target + if (!UpdateVictim()) + { + if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPostEventCount) + { + if (m_uiPostEventTimer <= uiDiff) + { + m_uiPostEventTimer = 3000; + + if (Unit* pPlayer = GetPlayerForEscort()) + { + switch(m_uiPostEventCount) + { + case 1: + DoScriptText(SAY_RIN_PROGRESS_1, me, pPlayer); + ++m_uiPostEventCount; + break; + case 2: + DoScriptText(SAY_RIN_PROGRESS_2, me, pPlayer); + m_uiPostEventCount = 0; + break; + } + } + else + { + me->ForcedDespawn(); + return; + } + } + else + m_uiPostEventTimer -= uiDiff; + } + + return; + } + + DoMeleeAttackIfReady(); + } +}; + +bool QuestAccept_npc_rinji(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_RINJI_TRAPPED) + { + if (GameObject* pGo = pCreature->FindNearestGameObject(GO_RINJI_CAGE, INTERACTION_DISTANCE)) + pGo->UseDoorOrButton(); + + if (npc_rinjiAI* pEscortAI = CAST_AI(npc_rinjiAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + } + return true; +} + +CreatureAI* GetAI_npc_rinji(Creature* pCreature) +{ + return new npc_rinjiAI(pCreature); +} + +void AddSC_hinterlands() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_00x09hl"; + newscript->GetAI = &GetAI_npc_00x09hl; + newscript->pQuestAccept = &QuestAccept_npc_00x09hl; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_rinji"; + newscript->GetAI = &GetAI_npc_rinji; + newscript->pQuestAccept = &QuestAccept_npc_rinji; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/ironforge.cpp b/src/server/scripts/EasternKingdoms/ironforge.cpp new file mode 100644 index 00000000000..5be56cc6c9c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ironforge.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Ironforge +SD%Complete: 100 +SDComment: Quest support: 3702 +SDCategory: Ironforge +EndScriptData */ + +/* ContentData +npc_royal_historian_archesonus +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_royal_historian_archesonus +######*/ + +#define GOSSIP_ITEM_ROYAL "I am ready to listen" +#define GOSSIP_ITEM_ROYAL_1 "That is tragic. How did this happen?" +#define GOSSIP_ITEM_ROYAL_2 "Interesting, continue please." +#define GOSSIP_ITEM_ROYAL_3 "Unbelievable! How dare they??" +#define GOSSIP_ITEM_ROYAL_4 "Of course I will help!" + +bool GossipHello_npc_royal_historian_archesonus(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(3702) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(2235, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_royal_historian_archesonus(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2236, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(2237, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(2238, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(2239, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(3702); + break; + } + return true; +} + +void AddSC_ironforge() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_royal_historian_archesonus"; + newscript->pGossipHello = &GossipHello_npc_royal_historian_archesonus; + newscript->pGossipSelect = &GossipSelect_npc_royal_historian_archesonus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp b/src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp new file mode 100644 index 00000000000..e5a70fcb1af --- /dev/null +++ b/src/server/scripts/EasternKingdoms/isle_of_queldanas.cpp @@ -0,0 +1,151 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Isle_of_Queldanas +SD%Complete: 100 +SDComment: Quest support: 11524, 11525, 11532, 11533, 11542, 11543, 11541 +SDCategory: Isle Of Quel'Danas +EndScriptData */ + +/* ContentData +npc_converted_sentry +npc_greengill_slave +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_converted_sentry +######*/ + +#define SAY_CONVERTED_1 -1000188 +#define SAY_CONVERTED_2 -1000189 + +#define SPELL_CONVERT_CREDIT 45009 + +struct npc_converted_sentryAI : public ScriptedAI +{ + npc_converted_sentryAI(Creature *c) : ScriptedAI(c) {} + + bool Credit; + uint32 Timer; + + void Reset() + { + Credit = false; + Timer = 2500; + } + + void MoveInLineOfSight(Unit * /*who*/) {} + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!Credit) + { + if (Timer <= diff) + { + uint32 i = urand(1,2); + if (i == 1) + DoScriptText(SAY_CONVERTED_1, me); + else + DoScriptText(SAY_CONVERTED_2, me); + + DoCast(me, SPELL_CONVERT_CREDIT); + if (me->isPet()) + CAST_PET(me)->SetDuration(7500); + Credit = true; + } else Timer -= diff; + } + } +}; +CreatureAI* GetAI_npc_converted_sentry(Creature* pCreature) +{ + return new npc_converted_sentryAI (pCreature); +} + +/*###### +## npc_greengill_slave +######*/ + +#define ENRAGE 45111 +#define ORB 45109 +#define QUESTG 11541 +#define DM 25060 + +struct npc_greengill_slaveAI : public ScriptedAI +{ + npc_greengill_slaveAI(Creature* c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + + void EnterCombat(Unit* /*who*/){} + + void Reset() + { + PlayerGUID = 0; + } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if (!caster) + return; + + if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == ORB && !me->HasAura(ENRAGE)) + { + PlayerGUID = caster->GetGUID(); + if (PlayerGUID) + { + Unit* plr = Unit::GetUnit((*me), PlayerGUID); + if (plr && CAST_PLR(plr)->GetQuestStatus(QUESTG) == QUEST_STATUS_INCOMPLETE) + DoCast(plr, 45110, true); + } + DoCast(me, ENRAGE); + Unit* Myrmidon = me->FindNearestCreature(DM, 70); + if (Myrmidon) + { + me->AddThreat(Myrmidon, 100000.0f); + AttackStart(Myrmidon); + } + } + } + + void UpdateAI(const uint32 /*diff*/) + { + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_greengill_slaveAI(Creature* pCreature) +{ + return new npc_greengill_slaveAI(pCreature); +} + +void AddSC_isle_of_queldanas() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_converted_sentry"; + newscript->GetAI = &GetAI_npc_converted_sentry; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_greengill_slave"; + newscript->GetAI = &GetAI_npc_greengill_slaveAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp new file mode 100644 index 00000000000..7105d27ca6a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp @@ -0,0 +1,196 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Curator +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1532057 +#define SAY_SUMMON1 -1532058 +#define SAY_SUMMON2 -1532059 +#define SAY_EVOCATE -1532060 +#define SAY_ENRAGE -1532061 +#define SAY_KILL1 -1532062 +#define SAY_KILL2 -1532063 +#define SAY_DEATH -1532064 + +//Flare spell info +#define SPELL_ASTRAL_FLARE_PASSIVE 30234 //Visual effect + Flare damage + +//Curator spell info +#define SPELL_HATEFUL_BOLT 30383 +#define SPELL_EVOCATION 30254 +#define SPELL_ENRAGE 30403 //Arcane Infusion: Transforms Curator and adds damage. +#define SPELL_BERSERK 26662 + +struct boss_curatorAI : public ScriptedAI +{ + boss_curatorAI(Creature *c) : ScriptedAI(c) {} + + uint32 AddTimer; + uint32 HatefulBoltTimer; + uint32 BerserkTimer; + + bool Enraged; + bool Evocating; + + void Reset() + { + AddTimer = 10000; + HatefulBoltTimer = 15000; //This time may be wrong + BerserkTimer = 720000; //12 minutes + Enraged = false; + Evocating = false; + + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //always decrease BerserkTimer + if (BerserkTimer <= diff) + { + //if evocate, then break evocate + if (Evocating) + { + if (me->HasAura(SPELL_EVOCATION)) + me->RemoveAurasDueToSpell(SPELL_EVOCATION); + + Evocating = false; + } + + //may not be correct SAY (generic hard enrage) + DoScriptText(SAY_ENRAGE, me); + + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_BERSERK); + + //don't know if he's supposed to do summon/evocate after hard enrage (probably not) + Enraged = true; + } else BerserkTimer -= diff; + + if (Evocating) + { + //not supposed to do anything while evocate + if (me->HasAura(SPELL_EVOCATION)) + return; + else + Evocating = false; + } + + if (!Enraged) + { + if (AddTimer <= diff) + { + //Summon Astral Flare + Creature* AstralFlare = DoSpawnCreature(17096, rand()%37, rand()%37, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (AstralFlare && pTarget) + { + AstralFlare->CastSpell(AstralFlare, SPELL_ASTRAL_FLARE_PASSIVE, false); + AstralFlare->AI()->AttackStart(pTarget); + } + + //Reduce Mana by 10% of max health + if (int32 mana = me->GetMaxPower(POWER_MANA)) + { + mana /= 10; + me->ModifyPower(POWER_MANA, -mana); + + //if this get's us below 10%, then we evocate (the 10th should be summoned now) + if (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA) < 10) + { + DoScriptText(SAY_EVOCATE, me); + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_EVOCATION); + Evocating = true; + //no AddTimer cooldown, this will make first flare appear instantly after evocate end, like expected + return; + } + else + { + if (urand(0,1) == 0) + { + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + } + } + } + + AddTimer = 10000; + } else AddTimer -= diff; + + if (me->GetHealth()*100 / me->GetMaxHealth() <= 15) + { + Enraged = true; + DoCast(me, SPELL_ENRAGE); + DoScriptText(SAY_ENRAGE, me); + } + } + + if (HatefulBoltTimer <= diff) + { + if (Enraged) + HatefulBoltTimer = 7000; + else + HatefulBoltTimer = 15000; + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1)) + DoCast(pTarget, SPELL_HATEFUL_BOLT); + + } else HatefulBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_curator(Creature* pCreature) +{ + return new boss_curatorAI (pCreature); +} + +void AddSC_boss_curator() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_curator"; + newscript->GetAI = &GetAI_boss_curator; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp new file mode 100644 index 00000000000..21db1be1be3 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Maiden_of_Virtue +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1532018 +#define SAY_SLAY1 -1532019 +#define SAY_SLAY2 -1532020 +#define SAY_SLAY3 -1532021 +#define SAY_REPENTANCE1 -1532022 +#define SAY_REPENTANCE2 -1532023 +#define SAY_DEATH -1532024 + +#define SPELL_REPENTANCE 29511 +#define SPELL_HOLYFIRE 29522 +#define SPELL_HOLYWRATH 32445 +#define SPELL_HOLYGROUND 29512 +#define SPELL_BERSERK 26662 + +struct boss_maiden_of_virtueAI : public ScriptedAI +{ + boss_maiden_of_virtueAI(Creature *c) : ScriptedAI(c) {} + + uint32 Repentance_Timer; + uint32 Holyfire_Timer; + uint32 Holywrath_Timer; + uint32 Holyground_Timer; + uint32 Enrage_Timer; + + bool Enraged; + + void Reset() + { + Repentance_Timer = 25000+(rand()%15000); + Holyfire_Timer = 8000+(rand()%17000); + Holywrath_Timer = 15000+(rand()%10000); + Holyground_Timer = 3000; + Enrage_Timer = 600000; + + Enraged = false; + } + + void KilledUnit(Unit* /*Victim*/) + { + if (urand(0,1) == 0) + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Enrage_Timer < diff && !Enraged) + { + DoCast(me, SPELL_BERSERK, true); + Enraged = true; + } else Enrage_Timer -= diff; + + if (Holyground_Timer <= diff) + { + DoCast(me, SPELL_HOLYGROUND, true); //Triggered so it doesn't interrupt her at all + Holyground_Timer = 3000; + } else Holyground_Timer -= diff; + + if (Repentance_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REPENTANCE); + DoScriptText(RAND(SAY_REPENTANCE1,SAY_REPENTANCE2), me); + + Repentance_Timer = urand(25000,35000); //A little randomness on that spell + } else Repentance_Timer -= diff; + + if (Holyfire_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_HOLYFIRE); + + Holyfire_Timer = urand(8000,23000); //Anywhere from 8 to 23 seconds, good luck having several of those in a row! + } else Holyfire_Timer -= diff; + + if (Holywrath_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_HOLYWRATH); + + Holywrath_Timer = urand(20000,25000); //20-30 secs sounds nice + } else Holywrath_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_maiden_of_virtue(Creature* pCreature) +{ + return new boss_maiden_of_virtueAI (pCreature); +} + +void AddSC_boss_maiden_of_virtue() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_maiden_of_virtue"; + newscript->GetAI = &GetAI_boss_maiden_of_virtue; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp new file mode 100644 index 00000000000..a2f2a8b605e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp @@ -0,0 +1,310 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Midnight +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_MIDNIGHT_KILL -1532000 +#define SAY_APPEAR1 -1532001 +#define SAY_APPEAR2 -1532002 +#define SAY_APPEAR3 -1532003 +#define SAY_MOUNT -1532004 +#define SAY_KILL1 -1532005 +#define SAY_KILL2 -1532006 +#define SAY_DISARMED -1532007 +#define SAY_DEATH -1532008 +#define SAY_RANDOM1 -1532009 +#define SAY_RANDOM2 -1532010 + +#define SPELL_SHADOWCLEAVE 29832 +#define SPELL_INTANGIBLE_PRESENCE 29833 +#define SPELL_BERSERKER_CHARGE 26561 //Only when mounted + +#define MOUNTED_DISPLAYID 16040 + +//Attumen (TODO: Use the summoning spell instead of Creature id. It works , but is not convenient for us) +#define SUMMON_ATTUMEN 15550 + +struct boss_midnightAI : public ScriptedAI +{ + boss_midnightAI(Creature *c) : ScriptedAI(c) {} + + uint64 Attumen; + uint8 Phase; + uint32 Mount_Timer; + + void Reset() + { + Phase = 1; + Attumen = 0; + Mount_Timer = 0; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_ON); + } + + void EnterCombat(Unit* /*who*/) {} + + void KilledUnit(Unit * /*victim*/) + { + if (Phase == 2) + { + if (Unit *pUnit = Unit::GetUnit(*me, Attumen)) + DoScriptText(SAY_MIDNIGHT_KILL, pUnit); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Phase == 1 && (me->GetHealth()*100)/me->GetMaxHealth() < 95) + { + Phase = 2; + if (Creature* pAttumen = me->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000)) + { + Attumen = pAttumen->GetGUID(); + pAttumen->AI()->AttackStart(me->getVictim()); + SetMidnight(pAttumen, me->GetGUID()); + DoScriptText(RAND(SAY_APPEAR1,SAY_APPEAR2,SAY_APPEAR3), pAttumen); + } + } + else if (Phase == 2 && (me->GetHealth()*100)/me->GetMaxHealth() < 25) + { + if (Unit *pAttumen = Unit::GetUnit(*me, Attumen)) + Mount(pAttumen); + } + else if (Phase == 3) + { + if (Mount_Timer) + { + if (Mount_Timer <= diff) + { + Mount_Timer = 0; + me->SetVisibility(VISIBILITY_OFF); + me->GetMotionMaster()->MoveIdle(); + if (Unit *pAttumen = Unit::GetUnit(*me, Attumen)) + { + pAttumen->SetDisplayId(MOUNTED_DISPLAYID); + pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pAttumen->getVictim()) + { + pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim()); + pAttumen->SetUInt64Value(UNIT_FIELD_TARGET, pAttumen->getVictim()->GetGUID()); + } + pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X,1); + } + } else Mount_Timer -= diff; + } + } + + if (Phase != 3) + DoMeleeAttackIfReady(); + } + + void Mount(Unit *pAttumen) + { + DoScriptText(SAY_MOUNT, pAttumen); + Phase = 3; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + float angle = me->GetAngle(pAttumen); + float distance = me->GetDistance2d(pAttumen); + float newX = me->GetPositionX() + cos(angle)*(distance/2) ; + float newY = me->GetPositionY() + sin(angle)*(distance/2) ; + float newZ = 50; + //me->Relocate(newX,newY,newZ,angle); + //me->SendMonsterMove(newX, newY, newZ, 0, true, 1000); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, newX, newY, newZ); + distance += 10; + newX = me->GetPositionX() + cos(angle)*(distance/2) ; + newY = me->GetPositionY() + sin(angle)*(distance/2) ; + pAttumen->GetMotionMaster()->Clear(); + pAttumen->GetMotionMaster()->MovePoint(0, newX, newY, newZ); + //pAttumen->Relocate(newX,newY,newZ,-angle); + //pAttumen->SendMonsterMove(newX, newY, newZ, 0, true, 1000); + Mount_Timer = 1000; + } + + void SetMidnight(Creature *, uint64); //Below .. +}; + +CreatureAI* GetAI_boss_midnight(Creature* pCreature) +{ + return new boss_midnightAI(pCreature); +} + +struct boss_attumenAI : public ScriptedAI +{ + boss_attumenAI(Creature *c) : ScriptedAI(c) + { + Phase = 1; + + CleaveTimer = urand(10000,15000); + CurseTimer = 30000; + RandomYellTimer = urand(30000,60000); //Occasionally yell + ChargeTimer = 20000; + ResetTimer = 0; + } + + uint64 Midnight; + uint8 Phase; + uint32 CleaveTimer; + uint32 CurseTimer; + uint32 RandomYellTimer; + uint32 ChargeTimer; //only when mounted + uint32 ResetTimer; + + void Reset() + { + ResetTimer = 2000; + } + + void EnterCombat(Unit* /*who*/) {} + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + if (Unit *pMidnight = Unit::GetUnit(*me, Midnight)) + pMidnight->Kill(pMidnight); + } + + void UpdateAI(const uint32 diff) + { + if (ResetTimer) + { + if (ResetTimer <= diff) + { + ResetTimer = 0; + Unit *pMidnight = Unit::GetUnit(*me, Midnight); + if (pMidnight) + { + pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pMidnight->SetVisibility(VISIBILITY_ON); + } + Midnight = 0; + me->SetVisibility(VISIBILITY_OFF); + me->Kill(me); + } + } else ResetTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) + return; + + if (CleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWCLEAVE); + CleaveTimer = urand(10000,15000); + } else CleaveTimer -= diff; + + if (CurseTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); + CurseTimer = 30000; + } else CurseTimer -= diff; + + if (RandomYellTimer <= diff) + { + DoScriptText(RAND(SAY_RANDOM1,SAY_RANDOM2), me); + RandomYellTimer = urand(30000,60000); + } else RandomYellTimer -= diff; + + if (me->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID) + { + if (ChargeTimer <= diff) + { + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && !pTarget->IsWithinDist(me, ATTACK_DISTANCE, false)) + target_list.push_back(pTarget); + pTarget = NULL; + } + if (target_list.size()) + pTarget = *(target_list.begin()+rand()%target_list.size()); + + DoCast(pTarget, SPELL_BERSERKER_CHARGE); + ChargeTimer = 20000; + } else ChargeTimer -= diff; + } + else + { + if ((me->GetHealth()*100)/me->GetMaxHealth() < 25) + { + Creature *pMidnight = Unit::GetCreature(*me, Midnight); + if (pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT) + { + CAST_AI(boss_midnightAI, (pMidnight->AI()))->Mount(me); + me->SetHealth(pMidnight->GetHealth()); + DoResetThreat(); + } + } + } + + DoMeleeAttackIfReady(); + } + + void SpellHit(Unit * /*source*/, const SpellEntry *spell) + { + if (spell->Mechanic == MECHANIC_DISARM) + DoScriptText(SAY_DISARMED, me); + } +}; + +void boss_midnightAI::SetMidnight(Creature *pAttumen, uint64 value) +{ + CAST_AI(boss_attumenAI, pAttumen->AI())->Midnight = value; +} + +CreatureAI* GetAI_boss_attumen(Creature* pCreature) +{ + return new boss_attumenAI (pCreature); +} + +void AddSC_boss_attumen() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_attumen"; + newscript->GetAI = &GetAI_boss_attumen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_midnight"; + newscript->GetAI = &GetAI_boss_midnight; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp new file mode 100644 index 00000000000..6c8fabcca35 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp @@ -0,0 +1,785 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moroes +SD%Complete: 95 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define SAY_AGGRO -1532011 +#define SAY_SPECIAL_1 -1532012 +#define SAY_SPECIAL_2 -1532013 +#define SAY_KILL_1 -1532014 +#define SAY_KILL_2 -1532015 +#define SAY_KILL_3 -1532016 +#define SAY_DEATH -1532017 + +#define SPELL_VANISH 29448 +#define SPELL_GARROTE 37066 +#define SPELL_BLIND 34694 +#define SPELL_GOUGE 29425 +#define SPELL_FRENZY 37023 + +#define POS_Z 81.73 + +float Locations[4][3]= +{ + {-10991.0, -1884.33, 0.614315}, + {-10989.4, -1885.88, 0.904913}, + {-10978.1, -1887.07, 2.035550}, + {-10975.9, -1885.81, 2.253890}, +}; + +const uint32 Adds[6]= +{ + 17007, + 19872, + 19873, + 19874, + 19875, + 19876, +}; + +struct boss_moroesAI : public ScriptedAI +{ + boss_moroesAI(Creature *c) : ScriptedAI(c) + { + for (uint8 i = 0; i < 4; ++i) + { + AddId[i] = 0; + } + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint64 AddGUID[4]; + + uint32 Vanish_Timer; + uint32 Blind_Timer; + uint32 Gouge_Timer; + uint32 Wait_Timer; + uint32 CheckAdds_Timer; + uint32 AddId[4]; + + bool InVanish; + bool Enrage; + + void Reset() + { + Vanish_Timer = 30000; + Blind_Timer = 35000; + Gouge_Timer = 23000; + Wait_Timer = 0; + CheckAdds_Timer = 5000; + + Enrage = false; + InVanish = false; + if (me->GetHealth() > 0) + { + SpawnAdds(); + } + + if (pInstance) + pInstance->SetData(TYPE_MOROES, NOT_STARTED); + } + + void StartEvent() + { + if (pInstance) + pInstance->SetData(TYPE_MOROES, IN_PROGRESS); + + DoZoneInCombat(); + } + + void EnterCombat(Unit* /*who*/) + { + StartEvent(); + + DoScriptText(SAY_AGGRO, me); + AddsAttack(); + DoZoneInCombat(); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); + } + + void JustDied(Unit* /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_MOROES, DONE); + + DeSpawnAdds(); + + //remove aura from spell Garrote when Moroes dies + if (pInstance) + pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GARROTE); + } + + void SpawnAdds() + { + DeSpawnAdds(); + if (isAddlistEmpty()) + { + Creature *pCreature = NULL; + std::vector AddList; + + for (uint8 i = 0; i < 6; ++i) + AddList.push_back(Adds[i]); + + while (AddList.size() > 4) + AddList.erase((AddList.begin())+(rand()%AddList.size())); + + uint8 i = 0; + for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr) + { + uint32 entry = *itr; + + pCreature = me->SummonCreature(entry, Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + if (pCreature) + { + AddGUID[i] = pCreature->GetGUID(); + AddId[i] = entry; + } + ++i; + } + }else + { + for (uint8 i = 0; i < 4; ++i) + { + Creature *pCreature = me->SummonCreature(AddId[i], Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + if (pCreature) + { + AddGUID[i] = pCreature->GetGUID(); + } + } + } + } + + bool isAddlistEmpty() + { + for (uint8 i = 0; i < 4; ++i) + { + if (AddId[i] == 0) + return true; + } + return false; + } + + void DeSpawnAdds() + { + for (uint8 i = 0; i < 4 ; ++i) + { + Creature* Temp = NULL; + if (AddGUID[i]) + { + Temp = Creature::GetCreature((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + Temp->DisappearAndDie(); + } + } + } + + void AddsAttack() + { + for (uint8 i = 0; i < 4; ++i) + { + Creature* Temp = NULL; + if (AddGUID[i]) + { + Temp = Creature::GetCreature((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + { + Temp->AI()->AttackStart(me->getVictim()); + DoZoneInCombat(Temp); + } else + EnterEvadeMode(); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (pInstance && !pInstance->GetData(TYPE_MOROES)) + { + EnterEvadeMode(); + return; + } + + if (!Enrage && me->GetHealth()*100 / me->GetMaxHealth() < 30) + { + DoCast(me, SPELL_FRENZY); + Enrage = true; + } + + if (CheckAdds_Timer <= diff) + { + for (uint8 i = 0; i < 4; ++i) + { + Creature* Temp = NULL; + if (AddGUID[i]) + { + Temp = Unit::GetCreature((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + if (!Temp->getVictim()) + Temp->AI()->AttackStart(me->getVictim()); + } + } + CheckAdds_Timer = 5000; + } else CheckAdds_Timer -= diff; + + if (!Enrage) + { + //Cast Vanish, then Garrote random victim + if (Vanish_Timer <= diff) + { + DoCast(me, SPELL_VANISH); + InVanish = true; + Vanish_Timer = 30000; + Wait_Timer = 5000; + } else Vanish_Timer -= diff; + + if (Gouge_Timer <= diff) + { + DoCastVictim(SPELL_GOUGE); + Gouge_Timer = 40000; + } else Gouge_Timer -= diff; + + if (Blind_Timer <= diff) + { + std::list pTargets; + SelectTargetList(pTargets, 5, SELECT_TARGET_RANDOM, me->GetMeleeReach()*5, true); + for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) + if (!me->IsWithinMeleeRange(*i)) + { + DoCast(*i, SPELL_BLIND); + break; + } + Blind_Timer = 40000; + } else Blind_Timer -= diff; + } + + if (InVanish) + { + if (Wait_Timer <= diff) + { + DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2), me); + + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + pTarget->CastSpell(pTarget, SPELL_GARROTE,true); + + InVanish = false; + } else Wait_Timer -= diff; + } + + if (!InVanish) + DoMeleeAttackIfReady(); + } +}; + +struct boss_moroes_guestAI : public ScriptedAI +{ + ScriptedInstance* pInstance; + + uint64 GuestGUID[4]; + + boss_moroes_guestAI(Creature* c) : ScriptedAI(c) + { + for (uint8 i = 0; i < 4; ++i) + GuestGUID[i] = 0; + + pInstance = c->GetInstanceData(); + } + + void Reset() + { + if (pInstance) + pInstance->SetData(TYPE_MOROES, NOT_STARTED); + } + + void AcquireGUID() + { + if (!pInstance) + return; + + uint64 MoroesGUID = pInstance->GetData64(DATA_MOROES); + Creature* Moroes = (Unit::GetCreature((*me), MoroesGUID)); + if (Moroes) + { + for (uint8 i = 0; i < 4; ++i) + { + uint64 GUID = CAST_AI(boss_moroesAI, Moroes->AI())->AddGUID[i]; + if (GUID) + GuestGUID[i] = GUID; + } + } + } + + Unit* SelectGuestTarget() + { + uint64 TempGUID = GuestGUID[rand()%4]; + if (TempGUID) + { + Unit* pUnit = Unit::GetUnit((*me), TempGUID); + if (pUnit && pUnit->isAlive()) + return pUnit; + } + + return me; + } + + void UpdateAI(const uint32 /*diff*/) + { + if (pInstance && !pInstance->GetData(TYPE_MOROES)) + EnterEvadeMode(); + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_MANABURN 29405 +#define SPELL_MINDFLY 29570 +#define SPELL_SWPAIN 34441 +#define SPELL_SHADOWFORM 29406 + +struct boss_baroness_dorothea_millstipeAI : public boss_moroes_guestAI +{ + //Shadow Priest + boss_baroness_dorothea_millstipeAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 ManaBurn_Timer; + uint32 MindFlay_Timer; + uint32 ShadowWordPain_Timer; + + void Reset() + { + ManaBurn_Timer = 7000; + MindFlay_Timer = 1000; + ShadowWordPain_Timer = 6000; + + DoCast(me, SPELL_SHADOWFORM, true); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (MindFlay_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MINDFLY); + MindFlay_Timer = 12000; // 3 sec channeled + } else MindFlay_Timer -= diff; + + if (ManaBurn_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (pTarget->getPowerType() == POWER_MANA) + DoCast(pTarget, SPELL_MANABURN); + ManaBurn_Timer = 5000; // 3 sec cast + } else ManaBurn_Timer -= diff; + + if (ShadowWordPain_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_SWPAIN); + ShadowWordPain_Timer = 7000; + } + } else ShadowWordPain_Timer -= diff; + } +}; + +#define SPELL_HAMMEROFJUSTICE 13005 +#define SPELL_JUDGEMENTOFCOMMAND 29386 +#define SPELL_SEALOFCOMMAND 29385 + +struct boss_baron_rafe_dreugerAI : public boss_moroes_guestAI +{ + //Retr Pally + boss_baron_rafe_dreugerAI(Creature *c) : boss_moroes_guestAI(c){} + + uint32 HammerOfJustice_Timer; + uint32 SealOfCommand_Timer; + uint32 JudgementOfCommand_Timer; + + void Reset() + { + HammerOfJustice_Timer = 1000; + SealOfCommand_Timer = 7000; + JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (SealOfCommand_Timer <= diff) + { + DoCast(me, SPELL_SEALOFCOMMAND); + SealOfCommand_Timer = 32000; + JudgementOfCommand_Timer = 29000; + } else SealOfCommand_Timer -= diff; + + if (JudgementOfCommand_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_JUDGEMENTOFCOMMAND); + JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; + } else JudgementOfCommand_Timer -= diff; + + if (HammerOfJustice_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMMEROFJUSTICE); + HammerOfJustice_Timer = 12000; + } else HammerOfJustice_Timer -= diff; + } +}; + +#define SPELL_DISPELMAGIC 15090 //Self or other guest+Moroes +#define SPELL_GREATERHEAL 29564 //Self or other guest+Moroes +#define SPELL_HOLYFIRE 29563 +#define SPELL_PWSHIELD 29408 + +struct boss_lady_catriona_von_indiAI : public boss_moroes_guestAI +{ + //Holy Priest + boss_lady_catriona_von_indiAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 DispelMagic_Timer; + uint32 GreaterHeal_Timer; + uint32 HolyFire_Timer; + uint32 PowerWordShield_Timer; + + void Reset() + { + DispelMagic_Timer = 11000; + GreaterHeal_Timer = 1500; + HolyFire_Timer = 5000; + PowerWordShield_Timer = 1000; + + AcquireGUID(); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (PowerWordShield_Timer <= diff) + { + DoCast(me, SPELL_PWSHIELD); + PowerWordShield_Timer = 15000; + } else PowerWordShield_Timer -= diff; + + if (GreaterHeal_Timer <= diff) + { + Unit *pTarget = SelectGuestTarget(); + + DoCast(pTarget, SPELL_GREATERHEAL); + GreaterHeal_Timer = 17000; + } else GreaterHeal_Timer -= diff; + + if (HolyFire_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HOLYFIRE); + HolyFire_Timer = 22000; + } else HolyFire_Timer -= diff; + + if (DispelMagic_Timer <= diff) + { + if (Unit *pTarget = RAND(SelectGuestTarget(), SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))) + DoCast(pTarget, SPELL_DISPELMAGIC); + + DispelMagic_Timer = 25000; + } else DispelMagic_Timer -= diff; + } +}; + +#define SPELL_CLEANSE 29380 //Self or other guest+Moroes +#define SPELL_GREATERBLESSOFMIGHT 29381 //Self or other guest+Moroes +#define SPELL_HOLYLIGHT 29562 //Self or other guest+Moroes +#define SPELL_DIVINESHIELD 41367 + +struct boss_lady_keira_berrybuckAI : public boss_moroes_guestAI +{ + //Holy Pally + boss_lady_keira_berrybuckAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Cleanse_Timer; + uint32 GreaterBless_Timer; + uint32 HolyLight_Timer; + uint32 DivineShield_Timer; + + void Reset() + { + Cleanse_Timer = 13000; + GreaterBless_Timer = 1000; + HolyLight_Timer = 7000; + DivineShield_Timer = 31000; + + AcquireGUID(); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (DivineShield_Timer <= diff) + { + DoCast(me, SPELL_DIVINESHIELD); + DivineShield_Timer = 31000; + } else DivineShield_Timer -= diff; + + if (HolyLight_Timer <= diff) + { + Unit *pTarget = SelectGuestTarget(); + + DoCast(pTarget, SPELL_HOLYLIGHT); + HolyLight_Timer = 10000; + } else HolyLight_Timer -= diff; + + if (GreaterBless_Timer <= diff) + { + Unit *pTarget = SelectGuestTarget(); + + DoCast(pTarget, SPELL_GREATERBLESSOFMIGHT); + + GreaterBless_Timer = 50000; + } else GreaterBless_Timer -= diff; + + if (Cleanse_Timer <= diff) + { + Unit *pTarget = SelectGuestTarget(); + + DoCast(pTarget, SPELL_CLEANSE); + + Cleanse_Timer = 10000; + } else Cleanse_Timer -= diff; + } +}; + +#define SPELL_HAMSTRING 9080 +#define SPELL_MORTALSTRIKE 29572 +#define SPELL_WHIRLWIND 29573 + +struct boss_lord_robin_darisAI : public boss_moroes_guestAI +{ + //Arms Warr + boss_lord_robin_darisAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Hamstring_Timer; + uint32 MortalStrike_Timer; + uint32 WhirlWind_Timer; + + void Reset() + { + Hamstring_Timer = 7000; + MortalStrike_Timer = 10000; + WhirlWind_Timer = 21000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (Hamstring_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + Hamstring_Timer = 12000; + } else Hamstring_Timer -= diff; + + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 18000; + } else MortalStrike_Timer -= diff; + + if (WhirlWind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + WhirlWind_Timer = 21000; + } else WhirlWind_Timer -= diff; + } +}; + +#define SPELL_DISARM 8379 +#define SPELL_HEROICSTRIKE 29567 +#define SPELL_SHIELDBASH 11972 +#define SPELL_SHIELDWALL 29390 + +struct boss_lord_crispin_ferenceAI : public boss_moroes_guestAI +{ + //Arms Warr + boss_lord_crispin_ferenceAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Disarm_Timer; + uint32 HeroicStrike_Timer; + uint32 ShieldBash_Timer; + uint32 ShieldWall_Timer; + + void Reset() + { + Disarm_Timer = 6000; + HeroicStrike_Timer = 10000; + ShieldBash_Timer = 8000; + ShieldWall_Timer = 4000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (Disarm_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DISARM); + Disarm_Timer = 12000; + } else Disarm_Timer -= diff; + + if (HeroicStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HEROICSTRIKE); + HeroicStrike_Timer = 10000; + } else HeroicStrike_Timer -= diff; + + if (ShieldBash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHIELDBASH); + ShieldBash_Timer = 13000; + } else ShieldBash_Timer -= diff; + + if (ShieldWall_Timer <= diff) + { + DoCast(me, SPELL_SHIELDWALL); + ShieldWall_Timer = 21000; + } else ShieldWall_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_moroes(Creature* pCreature) +{ + return new boss_moroesAI (pCreature); +} + +CreatureAI* GetAI_baroness_dorothea_millstipe(Creature* pCreature) +{ + return new boss_baroness_dorothea_millstipeAI (pCreature); +} + +CreatureAI* GetAI_baron_rafe_dreuger(Creature* pCreature) +{ + return new boss_baron_rafe_dreugerAI (pCreature); +} + +CreatureAI* GetAI_lady_catriona_von_indi(Creature* pCreature) +{ + return new boss_lady_catriona_von_indiAI (pCreature); +} + +CreatureAI* GetAI_lady_keira_berrybuck(Creature* pCreature) +{ + return new boss_lady_keira_berrybuckAI (pCreature); +} + +CreatureAI* GetAI_lord_robin_daris(Creature* pCreature) +{ + return new boss_lord_robin_darisAI (pCreature); +} + +CreatureAI* GetAI_lord_crispin_ference(Creature* pCreature) +{ + return new boss_lord_crispin_ferenceAI (pCreature); +} + +void AddSC_boss_moroes() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_moroes"; + newscript->GetAI = &GetAI_boss_moroes; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_baroness_dorothea_millstipe"; + newscript->GetAI = &GetAI_baroness_dorothea_millstipe; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_baron_rafe_dreuger"; + newscript->GetAI = &GetAI_baron_rafe_dreuger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lady_catriona_von_indi"; + newscript->GetAI = &GetAI_lady_catriona_von_indi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lady_keira_berrybuck"; + newscript->GetAI = &GetAI_lady_keira_berrybuck; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_robin_daris"; + newscript->GetAI = &GetAI_lord_robin_daris; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_crispin_ference"; + newscript->GetAI = &GetAI_lord_crispin_ference; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp new file mode 100644 index 00000000000..004f1902bfc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp @@ -0,0 +1,343 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Netherspite +SD%Complete: 90 +SDComment: Not sure about timing and portals placing +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define EMOTE_PHASE_PORTAL -1532089 +#define EMOTE_PHASE_BANISH -1532090 + +#define SPELL_NETHERBURN_AURA 30522 +#define SPELL_VOIDZONE 37063 +#define SPELL_NETHER_INFUSION 38688 +#define SPELL_NETHERBREATH 38523 +#define SPELL_BANISH_VISUAL 39833 +#define SPELL_BANISH_ROOT 42716 +#define SPELL_EMPOWERMENT 38549 +#define SPELL_NETHERSPITE_ROAR 38684 + +const float PortalCoord[3][3] = +{ + {-11195.353516, -1613.237183, 278.237258}, // Left side + {-11137.846680, -1685.607422, 278.239258}, // Right side + {-11094.493164, -1591.969238, 279.949188} // Back side +}; + +enum Netherspite_Portal{ + RED_PORTAL = 0, // Perseverence + GREEN_PORTAL = 1, // Serenity + BLUE_PORTAL = 2 // Dominance +}; + +const uint32 PortalID[3] = {17369, 17367, 17368}; +const uint32 PortalVisual[3] = {30487,30490,30491}; +const uint32 PortalBeam[3] = {30465,30464,30463}; +const uint32 PlayerBuff[3] = {30421,30422,30423}; +const uint32 NetherBuff[3] = {30466,30467,30468}; +const uint32 PlayerDebuff[3] = {38637,38638,38639}; + +struct boss_netherspiteAI : public ScriptedAI +{ + boss_netherspiteAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + + for (int i=0; i<3; ++i) + { + PortalGUID[i] = 0; + BeamTarget[i] = 0; + BeamerGUID[i] = 0; + } + // need core fix + for (int i=0; i<3; ++i) + { + if (SpellEntry *spell = (SpellEntry*)GetSpellStore()->LookupEntry(PlayerBuff[i])) + spell->AttributesEx |= SPELL_ATTR_EX_NEGATIVE; + } + } + + ScriptedInstance* pInstance; + + bool PortalPhase; + bool Berserk; + uint32 PhaseTimer; // timer for phase switching + uint32 VoidZoneTimer; + uint32 NetherInfusionTimer; // berserking timer + uint32 NetherbreathTimer; + uint32 EmpowermentTimer; + uint32 PortalTimer; // timer for beam checking + uint64 PortalGUID[3]; // guid's of portals + uint64 BeamerGUID[3]; // guid's of auxiliary beaming portals + uint64 BeamTarget[3]; // guid's of portals' current targets + + bool IsBetween(WorldObject* u1, WorldObject *pTarget, WorldObject* u2) // the in-line checker + { + if (!u1 || !u2 || !pTarget) + return false; + + float xn, yn, xp, yp, xh, yh; + xn = u1->GetPositionX(); + yn = u1->GetPositionY(); + xp = u2->GetPositionX(); + yp = u2->GetPositionY(); + xh = pTarget->GetPositionX(); + yh = pTarget->GetPositionY(); + + // check if target is between (not checking distance from the beam yet) + if (dist(xn,yn,xh,yh) >= dist(xn,yn,xp,yp) || dist(xp,yp,xh,yh) >= dist(xn,yn,xp,yp)) + return false; + // check distance from the beam + return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn,yn,xp,yp) < 1.5f); + } + + float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance + { + return sqrt((xa-xb)*(xa-xb) + (ya-yb)*(ya-yb)); + } + + void Reset() + { + Berserk = false; + NetherInfusionTimer = 540000; + VoidZoneTimer = 15000; + NetherbreathTimer = 3000; + + HandleDoors(true); + DestroyPortals(); + } + + void SummonPortals() + { + uint8 r = rand()%4; + uint8 pos[3]; + pos[RED_PORTAL] = (r%2 ? (r>1 ? 2: 1): 0); + pos[GREEN_PORTAL] = (r%2 ? 0: (r>1 ? 2: 1)); + pos[BLUE_PORTAL] = (r>1 ? 1: 2); // Blue Portal not on the left side (0) + + for (int i=0; i<3; ++i) + if (Creature *portal = me->SummonCreature(PortalID[i],PortalCoord[pos[i]][0],PortalCoord[pos[i]][1],PortalCoord[pos[i]][2],0,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + PortalGUID[i] = portal->GetGUID(); + portal->AddAura(PortalVisual[i], portal); + } + } + + void DestroyPortals() + { + for (int i=0; i<3; ++i) + { + if (Creature *portal = Unit::GetCreature(*me, PortalGUID[i])) + portal->DisappearAndDie(); + if (Creature *portal = Unit::GetCreature(*me, BeamerGUID[i])) + portal->DisappearAndDie(); + PortalGUID[i] = 0; + BeamTarget[i] = 0; + } + } + + void UpdatePortals() // Here we handle the beams' behavior + { + for (int j=0; j<3; ++j) // j = color + if (Creature *portal = Unit::GetCreature(*me, PortalGUID[j])) + { + // the one who's been casted upon before + Unit *current = Unit::GetUnit(*portal, BeamTarget[j]); + // temporary store for the best suitable beam reciever + Unit *pTarget = me; + + if (Map* map = me->GetMap()) + { + Map::PlayerList const& players = map->GetPlayers(); + + // get the best suitable target + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player* p = i->getSource(); + if (p && p->isAlive() // alive + && (!pTarget || pTarget->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best + && !p->HasAura(PlayerDebuff[j],0) // not exhausted + && !p->HasAura(PlayerBuff[(j+1)%3],0) // not on another beam + && !p->HasAura(PlayerBuff[(j+2)%3],0) + && IsBetween(me, p, portal)) // on the beam + pTarget = p; + } + } + // buff the target + if (pTarget->GetTypeId() == TYPEID_PLAYER) + pTarget->AddAura(PlayerBuff[j], pTarget); + else + pTarget->AddAura(NetherBuff[j], pTarget); + // cast visual beam on the chosen target if switched + // simple target switching isn't working -> using BeamerGUID to cast (workaround) + if (!current || pTarget != current) + { + BeamTarget[j] = pTarget->GetGUID(); + // remove currently beaming portal + if (Creature *beamer = Unit::GetCreature(*portal, BeamerGUID[j])) + { + beamer->CastSpell(pTarget, PortalBeam[j], false); + beamer->DisappearAndDie(); + BeamerGUID[j] = 0; + } + // create new one and start beaming on the target + if (Creature *beamer = portal->SummonCreature(PortalID[j],portal->GetPositionX(),portal->GetPositionY(),portal->GetPositionZ(),portal->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,60000)) + { + beamer->CastSpell(pTarget, PortalBeam[j], false); + BeamerGUID[j] = beamer->GetGUID(); + } + } + // aggro target if Red Beam + if (j == RED_PORTAL && me->getVictim() != pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + me->getThreatManager().addThreat(pTarget, 100000.0f+DoGetThreat(me->getVictim())); + } + } + + void SwitchToPortalPhase() + { + me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT); + me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL); + SummonPortals(); + PhaseTimer = 60000; + PortalPhase = true; + PortalTimer = 10000; + EmpowermentTimer = 10000; + DoScriptText(EMOTE_PHASE_PORTAL,me); + } + + void SwitchToBanishPhase() + { + me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT); + me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA); + DoCast(me, SPELL_BANISH_VISUAL, true); + DoCast(me, SPELL_BANISH_ROOT, true); + DestroyPortals(); + PhaseTimer = 30000; + PortalPhase = false; + DoScriptText(EMOTE_PHASE_BANISH,me); + + for (int i=0; i<3; ++i) + me->RemoveAurasDueToSpell(NetherBuff[i]); + } + + void HandleDoors(bool open) // Massive Door switcher + { + if (GameObject *Door = GameObject::GetGameObject(*me, pInstance ? pInstance->GetData64(DATA_GO_MASSIVE_DOOR) : 0)) + Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY); + } + + void Aggro(Unit * /*who*/) + { + HandleDoors(false); + SwitchToPortalPhase(); + } + + void JustDied(Unit* /*killer*/) + { + HandleDoors(true); + DestroyPortals(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Void Zone + if (VoidZoneTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,45,true),SPELL_VOIDZONE,true); + VoidZoneTimer = 15000; + } else VoidZoneTimer -= diff; + + // NetherInfusion Berserk + if (!Berserk && NetherInfusionTimer <= diff) + { + me->AddAura(SPELL_NETHER_INFUSION, me); + DoCast(me, SPELL_NETHERSPITE_ROAR); + Berserk = true; + } else NetherInfusionTimer -= diff; + + if (PortalPhase) // PORTAL PHASE + { + // Distribute beams and buffs + if (PortalTimer <= diff) + { + UpdatePortals(); + PortalTimer = 1000; + } else PortalTimer -= diff; + + // Empowerment & Nether Burn + if (EmpowermentTimer <= diff) + { + DoCast(me, SPELL_EMPOWERMENT); + me->AddAura(SPELL_NETHERBURN_AURA, me); + EmpowermentTimer = 90000; + } else EmpowermentTimer -= diff; + + if (PhaseTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + SwitchToBanishPhase(); + return; + } + } else PhaseTimer -= diff; + } + else // BANISH PHASE + { + // Netherbreath + if (NetherbreathTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,40,true)) + DoCast(pTarget, SPELL_NETHERBREATH); + NetherbreathTimer = urand(5000,7000); + } else NetherbreathTimer -= diff; + + if (PhaseTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + SwitchToPortalPhase(); + return; + } + } else PhaseTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_netherspite(Creature *pCreature) +{ + return new boss_netherspiteAI(pCreature); +} + +void AddSC_boss_netherspite() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_netherspite"; + newscript->GetAI = GetAI_boss_netherspite; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp new file mode 100644 index 00000000000..2e8b6f51317 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp @@ -0,0 +1,418 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Nightbane +SD%Complete: 80 +SDComment: SDComment: Timers may incorrect +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +//phase 1 +#define SPELL_BELLOWING_ROAR 39427 +#define SPELL_CHARRED_EARTH 30129 +#define SPELL_DISTRACTING_ASH 30130 +#define SPELL_SMOLDERING_BREATH 30210 +#define SPELL_TAIL_SWEEP 25653 +//phase 2 +#define SPELL_RAIN_OF_BONES 37098 +#define SPELL_SMOKING_BLAST 37057 +#define SPELL_FIREBALL_BARRAGE 30282 +#define SPELL_SEARING_CINDERS 30127 +#define SPELL_SUMMON_SKELETON 30170 + +#define EMOTE_SUMMON "An ancient being awakens in the distance..." +#define YELL_AGGRO "What fools! I shall bring a quick end to your suffering!" +#define YELL_FLY_PHASE "Miserable vermin. I shall exterminate you from the air!" +#define YELL_LAND_PHASE_1 "Enough! I shall land and crush you myself!" +#define YELL_LAND_PHASE_2 "Insects! Let me show you my strength up close!" +#define EMOTE_BREATH "takes a deep breath." + +float IntroWay[8][3] = +{ + {-11053.37,-1794.48,149}, + {-11141.07,-1841.40,125}, + {-11187.28,-1890.23,125}, + {-11189.20,-1931.25,125}, + {-11153.76,-1948.93,125}, + {-11128.73,-1929.75,125}, + {-11140 , -1915 ,122}, + {-11163 , -1903 ,91.473} +}; + +struct boss_nightbaneAI : public ScriptedAI +{ + boss_nightbaneAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = true; + } + + ScriptedInstance* pInstance; + + uint32 Phase; + + bool RainBones; + bool Skeletons; + + uint32 BellowingRoarTimer; + uint32 CharredEarthTimer; + uint32 DistractingAshTimer; + uint32 SmolderingBreathTimer; + uint32 TailSweepTimer; + uint32 RainofBonesTimer; + uint32 SmokingBlastTimer; + uint32 FireballBarrageTimer; + uint32 SearingCindersTimer; + + uint32 FlyCount; + uint32 FlyTimer; + + bool Intro; + bool Flying; + bool Movement; + + uint32 WaitTimer; + uint32 MovePhase; + + void Reset() + { + BellowingRoarTimer = 30000; + CharredEarthTimer = 15000; + DistractingAshTimer = 20000; + SmolderingBreathTimer = 10000; + TailSweepTimer = 12000; + RainofBonesTimer = 10000; + SmokingBlastTimer = 20000; + FireballBarrageTimer = 13000; + SearingCindersTimer = 14000; + WaitTimer = 1000; + + Phase =1; + FlyCount = 0; + MovePhase = 0; + + me->SetSpeed(MOVE_RUN, 2.0f); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->setActive(true); + + if (pInstance) + { + if (pInstance->GetData(TYPE_NIGHTBANE) == DONE || pInstance->GetData(TYPE_NIGHTBANE) == IN_PROGRESS) + me->DisappearAndDie(); + else + pInstance->SetData(TYPE_NIGHTBANE, NOT_STARTED); + } + + HandleTerraceDoors(true); + + Flying = false; + Movement = false; + + if (!Intro) + { + me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0); + me->GetMotionMaster()->MoveTargetedHome(); + } + } + + void HandleTerraceDoors(bool open) + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_1), open); + pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_2), open); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(TYPE_NIGHTBANE, IN_PROGRESS); + + HandleTerraceDoors(false); + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + } + + void AttackStart(Unit* who) + { + if (!Intro && !Flying) + ScriptedAI::AttackStart(who); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_NIGHTBANE, DONE); + + HandleTerraceDoors(true); + } + + void MoveInLineOfSight(Unit *who) + { + if (!Intro && !Flying) + ScriptedAI::MoveInLineOfSight(who); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (Intro) + { + if (id >= 8) + { + Intro = false; + me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0); + return; + } + + WaitTimer = 1; + } + + if (Flying) + { + if (id == 0) + { + me->MonsterTextEmote(EMOTE_BREATH, 0, true); + Flying = false; + Phase = 2; + return; + } + + if (id == 3) + { + MovePhase = 4; + WaitTimer = 1; + return; + } + + if (id == 8) + { + Flying = false; + Phase = 1; + Movement = true; + return; + } + + WaitTimer = 1; + } + } + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(me->getVictim()); + } + + void TakeOff() + { + me->MonsterYell(YELL_FLY_PHASE, LANG_UNIVERSAL, NULL); + + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + (*me).GetMotionMaster()->Clear(false); + (*me).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]); + + Flying = true; + + FlyTimer = urand(45000,60000); //timer wrong between 45 and 60 seconds + ++FlyCount; + + RainofBonesTimer = 5000; //timer wrong (maybe) + RainBones = false; + Skeletons = false; + } + + void UpdateAI(const uint32 diff) + { + /* The timer for this was never setup apparently, not sure if the code works properly: + if (WaitTimer <= diff) + { + if (Intro) + { + if (MovePhase >= 7) + { + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); + } + else + { + me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]); + ++MovePhase; + } + } + if (Flying) + { + if (MovePhase >= 7) + { + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); + } + else + { + me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]); + ++MovePhase; + } + } + + WaitTimer = 0; + } else WaitTimer -= diff; + */ + + if (!UpdateVictim()) + return; + + if (Flying) + return; + + // Phase 1 "GROUND FIGHT" + if (Phase == 1) + { + if (Movement) + { + DoStartMovement(me->getVictim()); + Movement = false; + } + + if (BellowingRoarTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); + BellowingRoarTimer = urand(30000,40000); + } else BellowingRoarTimer -= diff; + + if (SmolderingBreathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SMOLDERING_BREATH); + SmolderingBreathTimer = 20000; + } else SmolderingBreathTimer -= diff; + + if (CharredEarthTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CHARRED_EARTH); + CharredEarthTimer = 20000; + } else CharredEarthTimer -= diff; + + if (TailSweepTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (!me->HasInArc(M_PI, pTarget)) + DoCast(pTarget, SPELL_TAIL_SWEEP); + TailSweepTimer = 15000; + } else TailSweepTimer -= diff; + + if (SearingCindersTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SEARING_CINDERS); + SearingCindersTimer = 10000; + } else SearingCindersTimer -= diff; + + uint32 Prozent; + Prozent = (me->GetHealth()*100) / me->GetMaxHealth(); + + if (Prozent < 75 && FlyCount == 0) // first take off 75% + TakeOff(); + + if (Prozent < 50 && FlyCount == 1) // secound take off 50% + TakeOff(); + + if (Prozent < 25 && FlyCount == 2) // third take off 25% + TakeOff(); + + DoMeleeAttackIfReady(); + } + + //Phase 2 "FLYING FIGHT" + if (Phase == 2) + { + if (!RainBones) + { + if (!Skeletons) + { + for (uint8 i = 0; i <= 3; ++i) + { + DoCast(me->getVictim(), SPELL_SUMMON_SKELETON); + Skeletons = true; + } + } + + if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2 + { + DoCast(me->getVictim(), SPELL_RAIN_OF_BONES); + RainBones = true; + SmokingBlastTimer = 20000; + } else RainofBonesTimer -= diff; + + if (DistractingAshTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_DISTRACTING_ASH); + DistractingAshTimer = 2000; //timer wrong + } else DistractingAshTimer -= diff; + } + + if (RainBones) + { + if (SmokingBlastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SMOKING_BLAST); + SmokingBlastTimer = 1500; //timer wrong + } else SmokingBlastTimer -= diff; + } + + if (FireballBarrageTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_FARTHEST, 0)) + DoCast(pTarget, SPELL_FIREBALL_BARRAGE); + FireballBarrageTimer = 20000; + } else FireballBarrageTimer -= diff; + + if (FlyTimer <= diff) //landing + { + me->MonsterYell(RAND(*YELL_LAND_PHASE_1,*YELL_LAND_PHASE_2), LANG_UNIVERSAL, NULL); + + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MovePoint(3,IntroWay[3][0],IntroWay[3][1],IntroWay[3][2]); + + Flying = true; + } else FlyTimer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_nightbane(Creature* pCreature) +{ + return new boss_nightbaneAI (pCreature); +} + +void AddSC_boss_nightbane() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nightbane"; + newscript->GetAI = &GetAI_boss_nightbane; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp new file mode 100644 index 00000000000..1071eae78a0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp @@ -0,0 +1,604 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Prince_Malchezzar +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define SAY_AGGRO -1532091 +#define SAY_AXE_TOSS1 -1532092 +#define SAY_AXE_TOSS2 -1532093 +#define SAY_SPECIAL1 -1532094 +#define SAY_SPECIAL2 -1532095 +#define SAY_SPECIAL3 -1532096 +#define SAY_SLAY1 -1532097 +#define SAY_SLAY2 -1532098 +#define SAY_SLAY3 -1532099 +#define SAY_SUMMON1 -1532100 +#define SAY_SUMMON2 -1532101 +#define SAY_DEATH -1532102 + +// 18 Coordinates for Infernal spawns +struct InfernalPoint +{ + float x,y; +}; + +#define INFERNAL_Z 275.5 + +static InfernalPoint InfernalPoints[] = +{ + {-10922.8, -1985.2}, + {-10916.2, -1996.2}, + {-10932.2, -2008.1}, + {-10948.8, -2022.1}, + {-10958.7, -1997.7}, + {-10971.5, -1997.5}, + {-10990.8, -1995.1}, + {-10989.8, -1976.5}, + {-10971.6, -1973.0}, + {-10955.5, -1974.0}, + {-10939.6, -1969.8}, + {-10958.0, -1952.2}, + {-10941.7, -1954.8}, + {-10943.1, -1988.5}, + {-10948.8, -2005.1}, + {-10984.0, -2019.3}, + {-10932.8, -1979.6}, + {-10935.7, -1996.0} +}; + +#define TOTAL_INFERNAL_POINTS 18 + +//Enfeeble is supposed to reduce hp to 1 and then heal player back to full when it ends +//Along with reducing healing and regen while enfeebled to 0% +//This spell effect will only reduce healing + +#define SPELL_ENFEEBLE 30843 //Enfeeble during phase 1 and 2 +#define SPELL_ENFEEBLE_EFFECT 41624 + +#define SPELL_SHADOWNOVA 30852 //Shadownova used during all phases +#define SPELL_SW_PAIN 30854 //Shadow word pain during phase 1 and 3 (different targeting rules though) +#define SPELL_THRASH_PASSIVE 12787 //Extra attack chance during phase 2 +#define SPELL_SUNDER_ARMOR 30901 //Sunder armor during phase 2 +#define SPELL_THRASH_AURA 12787 //Passive proc chance for thrash +#define SPELL_EQUIP_AXES 30857 //Visual for axe equiping +#define SPELL_AMPLIFY_DAMAGE 39095 //Amplifiy during phase 3 +#define SPELL_CLEAVE 30131 //Same as Nightbane. +#define SPELL_HELLFIRE 30859 //Infenals' hellfire aura +#define NETHERSPITE_INFERNAL 17646 //The netherspite infernal creature +#define MALCHEZARS_AXE 17650 //Malchezar's axes (creatures), summoned during phase 3 + +#define INFERNAL_MODEL_INVISIBLE 11686 //Infernal Effects +#define SPELL_INFERNAL_RELAY 30834 + +#define EQUIP_ID_AXE 33542 //Axes info + +//---------Infernal code first +struct netherspite_infernalAI : public ScriptedAI +{ + netherspite_infernalAI(Creature *c) : ScriptedAI(c) , + malchezaar(0), HellfireTimer(0), CleanupTimer(0), point(NULL) {} + + uint32 HellfireTimer; + uint32 CleanupTimer; + uint32 malchezaar; + InfernalPoint *point; + + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (HellfireTimer) + if (HellfireTimer <= diff) + { + DoCast(me, SPELL_HELLFIRE); + HellfireTimer = 0; + } + else HellfireTimer -= diff; + + if (CleanupTimer) + if (CleanupTimer <= diff) + { + Cleanup(); + CleanupTimer = 0; + } else CleanupTimer -= diff; + } + + void KilledUnit(Unit *who) + { + Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar); + if (pMalchezaar) + CAST_CRE(pMalchezaar)->AI()->KilledUnit(who); + } + + void SpellHit(Unit * /*who*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_INFERNAL_RELAY) + { + me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + HellfireTimer = 4000; + CleanupTimer = 170000; + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != malchezaar) + damage = 0; + } + + void Cleanup(); //below ... +}; + +struct boss_malchezaarAI : public ScriptedAI +{ + boss_malchezaarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 EnfeebleTimer; + uint32 EnfeebleResetTimer; + uint32 ShadowNovaTimer; + uint32 SWPainTimer; + uint32 SunderArmorTimer; + uint32 AmplifyDamageTimer; + uint32 Cleave_Timer; + uint32 InfernalTimer; + uint32 AxesTargetSwitchTimer; + uint32 InfernalCleanupTimer; + + std::vector infernals; + std::vector positions; + + uint64 axes[2]; + uint64 enfeeble_targets[5]; + uint64 enfeeble_health[5]; + + uint32 phase; + + void Reset() + { + AxesCleanup(); + ClearWeapons(); + InfernalCleanup(); + positions.clear(); + + for (uint8 i = 0; i < 5; ++i) + enfeeble_targets[i] = 0; + + for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i) + positions.push_back(&InfernalPoints[i]); + + EnfeebleTimer = 30000; + EnfeebleResetTimer = 38000; + ShadowNovaTimer = 35500; + SWPainTimer = 20000; + AmplifyDamageTimer = 5000; + Cleave_Timer = 8000; + InfernalTimer = 45000; + InfernalCleanupTimer = 47000; + AxesTargetSwitchTimer = urand(7500,20000); + SunderArmorTimer = urand(5000,10000); + phase = 1; + + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + AxesCleanup(); + ClearWeapons(); + InfernalCleanup(); + positions.clear(); + + for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i) + positions.push_back(&InfernalPoints[i]); + + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), false); // Open the door leading further in + } + + void InfernalCleanup() + { + //Infernal Cleanup + for (std::vector::const_iterator itr = infernals.begin(); itr != infernals.end(); ++itr) + if (Unit *pInfernal = Unit::GetUnit(*me, *itr)) + if (pInfernal->isAlive()) + { + pInfernal->SetVisibility(VISIBILITY_OFF); + pInfernal->setDeathState(JUST_DIED); + } + + infernals.clear(); + } + + void AxesCleanup() + { + for (uint8 i = 0; i < 2; ++i) + { + Unit *axe = Unit::GetUnit(*me, axes[i]); + if (axe && axe->isAlive()) + axe->Kill(axe); + axes[i] = 0; + } + } + + void ClearWeapons() + { + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + + //damage + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg); + me->UpdateDamagePhysical(BASE_ATTACK); + } + + void EnfeebleHealthEffect() + { + const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT); + if (!info) + return; + + std::list t_list = me->getThreatManager().getThreatList(); + std::vector targets; + + if (!t_list.size()) + return; + + //begin + 1, so we don't target the one with the highest threat + std::list::const_iterator itr = t_list.begin(); + std::advance(itr, 1); + for (; itr != t_list.end(); ++itr) //store the threat list in a different container + if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + if (pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + targets.push_back(pTarget); + + //cut down to size if we have more than 5 targets + while (targets.size() > 5) + targets.erase(targets.begin()+rand()%targets.size()); + + uint32 i = 0; + for (std::vector::const_iterator iter = targets.begin(); iter != targets.end(); ++iter, ++i) + if (Unit *pTarget = *iter) + { + enfeeble_targets[i] = pTarget->GetGUID(); + enfeeble_health[i] = pTarget->GetHealth(); + + pTarget->CastSpell(pTarget, SPELL_ENFEEBLE, true, 0, 0, me->GetGUID()); + pTarget->SetHealth(1); + } + } + + void EnfeebleResetHealth() + { + for (uint8 i = 0; i < 5; ++i) + { + Unit *pTarget = Unit::GetUnit(*me, enfeeble_targets[i]); + if (pTarget && pTarget->isAlive()) + pTarget->SetHealth(enfeeble_health[i]); + enfeeble_targets[i] = 0; + enfeeble_health[i] = 0; + } + } + + void SummonInfernal(const uint32 /*diff*/) + { + InfernalPoint *point = NULL; + Position pos; + if ((me->GetMapId() != 532) || positions.empty()) + me->GetRandomNearPosition(pos, 60); + else + { + std::vector::iterator itr = positions.begin()+rand()%positions.size(); + point = *itr; + positions.erase(itr); + pos.Relocate(point->x, point->y, INFERNAL_Z); + } + + Creature *Infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000); + + if (Infernal) + { + Infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE); + Infernal->setFaction(me->getFaction()); + if (point) + CAST_AI(netherspite_infernalAI, Infernal->AI())->point=point; + CAST_AI(netherspite_infernalAI, Infernal->AI())->malchezaar=me->GetGUID(); + + infernals.push_back(Infernal->GetGUID()); + DoCast(Infernal, SPELL_INFERNAL_RELAY); + } + + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (EnfeebleResetTimer && EnfeebleResetTimer <= diff) // Let's not forget to reset that + { + EnfeebleResetHealth(); + EnfeebleResetTimer = 0; + } else EnfeebleResetTimer -= diff; + + if (me->hasUnitState(UNIT_STAT_STUNNED)) // While shifting to phase 2 malchezaar stuns himself + return; + + if (me->GetUInt64Value(UNIT_FIELD_TARGET) != me->getVictim()->GetGUID()) + me->SetUInt64Value(UNIT_FIELD_TARGET, me->getVictim()->GetGUID()); + + if (phase == 1) + { + if ((me->GetHealth()*100) / me->GetMaxHealth() < 60) + { + me->InterruptNonMeleeSpells(false); + + phase = 2; + + //animation + DoCast(me, SPELL_EQUIP_AXES); + + //text + DoScriptText(SAY_AXE_TOSS1, me); + + //passive thrash aura + DoCast(me, SPELL_THRASH_AURA, true); + + //models + SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE); + + //damage + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg); + me->UpdateDamagePhysical(BASE_ATTACK); + + me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg); + me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg); + //Sigh, updating only works on main attack, do it manually .... + me->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg); + me->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg); + + me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100); + } + } + else if (phase == 2) + { + if ((me->GetHealth()*100) / me->GetMaxHealth() < 30) + { + InfernalTimer = 15000; + + phase = 3; + + ClearWeapons(); + + //remove thrash + me->RemoveAurasDueToSpell(SPELL_THRASH_AURA); + + DoScriptText(SAY_AXE_TOSS2, me); + + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + for (uint8 i = 0; i < 2; ++i) + { + Creature *axe = me->SummonCreature(MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + if (axe) + { + axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + axe->setFaction(me->getFaction()); + axes[i] = axe->GetGUID(); + if (pTarget) + { + axe->AI()->AttackStart(pTarget); + //axe->getThreatManager().tauntApply(pTarget); //Taunt Apply and fade out does not work properly + // So we'll use a hack to add a lot of threat to our target + axe->AddThreat(pTarget, 10000000.0f); + } + } + } + + if (ShadowNovaTimer > 35000) + ShadowNovaTimer = EnfeebleTimer + 5000; + + return; + } + + if (SunderArmorTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDER_ARMOR); + SunderArmorTimer = urand(10000,18000); + + } else SunderArmorTimer -= diff; + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = urand(6000,12000); + + } else Cleave_Timer -= diff; + } + else + { + if (AxesTargetSwitchTimer <= diff) + { + AxesTargetSwitchTimer = urand(7500,20000); + + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Unit *axe = Unit::GetUnit(*me, axes[i])) + { + if (axe->getVictim()) + DoModifyThreatPercent(axe->getVictim(), -100); + if (pTarget) + axe->AddThreat(pTarget, 1000000.0f); + //axe->getThreatManager().tauntFadeOut(axe->getVictim()); + //axe->getThreatManager().tauntApply(pTarget); + } + } + } + } else AxesTargetSwitchTimer -= diff; + + if (AmplifyDamageTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_AMPLIFY_DAMAGE); + AmplifyDamageTimer = urand(20000,30000); + } else AmplifyDamageTimer -= diff; + } + + //Time for global and double timers + if (InfernalTimer <= diff) + { + SummonInfernal(diff); + InfernalTimer = phase == 3 ? 14500 : 44500; // 15 secs in phase 3, 45 otherwise + } else InfernalTimer -= diff; + + if (ShadowNovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWNOVA); + ShadowNovaTimer = phase == 3 ? 31000 : uint32(-1); + } else ShadowNovaTimer -= diff; + + if (phase != 2) + { + if (SWPainTimer <= diff) + { + Unit *pTarget = NULL; + if (phase == 1) + pTarget = me->getVictim(); // the tank + else // anyone but the tank + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + + if (pTarget) + DoCast(pTarget, SPELL_SW_PAIN); + + SWPainTimer = 20000; + } else SWPainTimer -= diff; + } + + if (phase != 3) + { + if (EnfeebleTimer <= diff) + { + EnfeebleHealthEffect(); + EnfeebleTimer = 30000; + ShadowNovaTimer = 5000; + EnfeebleResetTimer = 9000; + } else EnfeebleTimer -= diff; + } + + if (phase == 2) + DoMeleeAttacksIfReady(); + else + DoMeleeAttackIfReady(); + } + + void DoMeleeAttacksIfReady() + { + if (me->IsWithinMeleeRange(me->getVictim()) && !me->IsNonMeleeSpellCasted(false)) + { + //Check for base attack + if (me->isAttackReady() && me->getVictim()) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + //Check for offhand attack + if (me->isAttackReady(OFF_ATTACK) && me->getVictim()) + { + me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK); + me->resetAttackTimer(OFF_ATTACK); + } + } + } + + void Cleanup(Creature *infernal, InfernalPoint *point) + { + for (std::vector::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr) + if (*itr == infernal->GetGUID()) + { + infernals.erase(itr); + break; + } + + positions.push_back(point); + } +}; + +void netherspite_infernalAI::Cleanup() +{ + Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar); + + if (pMalchezaar && pMalchezaar->isAlive()) + CAST_AI(boss_malchezaarAI, CAST_CRE(pMalchezaar)->AI())->Cleanup(me, point); +} + +CreatureAI* GetAI_netherspite_infernal(Creature* pCreature) +{ + return new netherspite_infernalAI (pCreature); +} + +CreatureAI* GetAI_boss_malchezaar(Creature* pCreature) +{ + return new boss_malchezaarAI (pCreature); +} + +void AddSC_boss_malchezaar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_malchezaar"; + newscript->GetAI = &GetAI_boss_malchezaar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "netherspite_infernal"; + newscript->GetAI = &GetAI_netherspite_infernal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp new file mode 100644 index 00000000000..394cff3ccc5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp @@ -0,0 +1,569 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shade_of_Aran +SD%Complete: 95 +SDComment: Flame wreath missing cast animation, mods won't triggere. +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedSimpleAI.h" +#include "karazhan.h" +#include "GameObject.h" + +#define SAY_AGGRO1 -1532073 +#define SAY_AGGRO2 -1532074 +#define SAY_AGGRO3 -1532075 +#define SAY_FLAMEWREATH1 -1532076 +#define SAY_FLAMEWREATH2 -1532077 +#define SAY_BLIZZARD1 -1532078 +#define SAY_BLIZZARD2 -1532079 +#define SAY_EXPLOSION1 -1532080 +#define SAY_EXPLOSION2 -1532081 +#define SAY_DRINK -1532082 //Low Mana / AoE Pyroblast +#define SAY_ELEMENTALS -1532083 +#define SAY_KILL1 -1532084 +#define SAY_KILL2 -1532085 +#define SAY_TIMEOVER -1532086 +#define SAY_DEATH -1532087 +#define SAY_ATIESH -1532088 //Atiesh is equipped by a raid member + +//Spells +#define SPELL_FROSTBOLT 29954 +#define SPELL_FIREBALL 29953 +#define SPELL_ARCMISSLE 29955 +#define SPELL_CHAINSOFICE 29991 +#define SPELL_DRAGONSBREATH 29964 +#define SPELL_MASSSLOW 30035 +#define SPELL_FLAME_WREATH 29946 +#define SPELL_AOE_CS 29961 +#define SPELL_PLAYERPULL 32265 +#define SPELL_AEXPLOSION 29973 +#define SPELL_MASS_POLY 29963 +#define SPELL_BLINK_CENTER 29967 +#define SPELL_ELEMENTALS 29962 +#define SPELL_CONJURE 29975 +#define SPELL_DRINK 30024 +#define SPELL_POTION 32453 +#define SPELL_AOE_PYROBLAST 29978 + +//Creature Spells +#define SPELL_CIRCULAR_BLIZZARD 29951 //29952 is the REAL circular blizzard that leaves persistant blizzards that last for 10 seconds +#define SPELL_WATERBOLT 31012 +#define SPELL_SHADOW_PYRO 29978 + +//Creatures +#define CREATURE_WATER_ELEMENTAL 17167 +#define CREATURE_SHADOW_OF_ARAN 18254 +#define CREATURE_ARAN_BLIZZARD 17161 + +enum SuperSpell +{ + SUPER_FLAME = 0, + SUPER_BLIZZARD, + SUPER_AE, +}; + +struct boss_aranAI : public ScriptedAI +{ + boss_aranAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 SecondarySpellTimer; + uint32 NormalCastTimer; + uint32 SuperCastTimer; + uint32 BerserkTimer; + uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering. + + uint8 LastSuperSpell; + + uint32 FlameWreathTimer; + uint32 FlameWreathCheckTime; + uint64 FlameWreathTarget[3]; + float FWTargPosX[3]; + float FWTargPosY[3]; + + uint32 CurrentNormalSpell; + uint32 ArcaneCooldown; + uint32 FireCooldown; + uint32 FrostCooldown; + + uint32 DrinkInturruptTimer; + + bool ElementalsSpawned; + bool Drinking; + bool DrinkInturrupted; + + void Reset() + { + SecondarySpellTimer = 5000; + NormalCastTimer = 0; + SuperCastTimer = 35000; + BerserkTimer = 720000; + CloseDoorTimer = 15000; + + LastSuperSpell = rand()%3; + + FlameWreathTimer = 0; + FlameWreathCheckTime = 0; + + CurrentNormalSpell = 0; + ArcaneCooldown = 0; + FireCooldown = 0; + FrostCooldown = 0; + + DrinkInturruptTimer = 10000; + + ElementalsSpawned = false; + Drinking = false; + DrinkInturrupted = false; + + if (pInstance) + { + // Not in progress + pInstance->SetData(TYPE_ARAN, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true); + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_ARAN, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + + if (pInstance) + { + pInstance->SetData(TYPE_ARAN, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false); + } + } + + void FlameWreathEffect() + { + std::vector targets; + std::list t_list = me->getThreatManager().getThreatList(); + + if (!t_list.size()) + return; + + //store the threat list in a different container + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //only on alive players + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + targets.push_back(pTarget); + } + + //cut down to size if we have more than 3 targets + while (targets.size() > 3) + targets.erase(targets.begin()+rand()%targets.size()); + + uint32 i = 0; + for (std::vector::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr) + { + if (*itr) + { + FlameWreathTarget[i] = (*itr)->GetGUID(); + FWTargPosX[i] = (*itr)->GetPositionX(); + FWTargPosY[i] = (*itr)->GetPositionY(); + DoCast((*itr), SPELL_FLAME_WREATH, true); + ++i; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (CloseDoorTimer) + { + if (CloseDoorTimer <= diff) + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false); + CloseDoorTimer = 0; + } + } else CloseDoorTimer -= diff; + } + + //Cooldowns for casts + if (ArcaneCooldown) + { + if (ArcaneCooldown >= diff) + ArcaneCooldown -= diff; + else ArcaneCooldown = 0; + } + + if (FireCooldown) + { + if (FireCooldown >= diff) + FireCooldown -= diff; + else FireCooldown = 0; + } + + if (FrostCooldown) + { + if (FrostCooldown >= diff) + FrostCooldown -= diff; + else FrostCooldown = 0; + } + + if (!Drinking && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA)) < 20) + { + Drinking = true; + me->InterruptNonMeleeSpells(false); + + DoScriptText(SAY_DRINK, me); + + if (!DrinkInturrupted) + { + DoCast(me, SPELL_MASS_POLY, true); + DoCast(me, SPELL_CONJURE, false); + DoCast(me, SPELL_DRINK, false); + me->SetStandState(UNIT_STAND_STATE_SIT); + DrinkInturruptTimer = 10000; + } + } + + //Drink Inturrupt + if (Drinking && DrinkInturrupted) + { + Drinking = false; + me->RemoveAurasDueToSpell(SPELL_DRINK); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)-32000); + DoCast(me, SPELL_POTION, false); + } + + //Drink Inturrupt Timer + if (Drinking && !DrinkInturrupted) + if (DrinkInturruptTimer >= diff) + DrinkInturruptTimer -= diff; + else + { + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_POTION, true); + DoCast(me, SPELL_AOE_PYROBLAST, false); + DrinkInturrupted = true; + Drinking = false; + } + + //Don't execute any more code if we are drinking + if (Drinking) + return; + + //Normal casts + if (NormalCastTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!pTarget) + return; + + uint32 Spells[3]; + uint8 AvailableSpells = 0; + + //Check for what spells are not on cooldown + if (!ArcaneCooldown) + { + Spells[AvailableSpells] = SPELL_ARCMISSLE; + ++AvailableSpells; + } + if (!FireCooldown) + { + Spells[AvailableSpells] = SPELL_FIREBALL; + ++AvailableSpells; + } + if (!FrostCooldown) + { + Spells[AvailableSpells] = SPELL_FROSTBOLT; + ++AvailableSpells; + } + + //If no available spells wait 1 second and try again + if (AvailableSpells) + { + CurrentNormalSpell = Spells[rand() % AvailableSpells]; + DoCast(pTarget, CurrentNormalSpell); + } + } + NormalCastTimer = 1000; + } else NormalCastTimer -= diff; + + if (SecondarySpellTimer <= diff) + { + switch (urand(0,1)) + { + case 0: + DoCast(me, SPELL_AOE_CS); + break; + case 1: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CHAINSOFICE); + break; + } + SecondarySpellTimer = urand(5000,20000); + } else SecondarySpellTimer -= diff; + + if (SuperCastTimer <= diff) + { + uint8 Available[2]; + + switch (LastSuperSpell) + { + case SUPER_AE: + Available[0] = SUPER_FLAME; + Available[1] = SUPER_BLIZZARD; + break; + case SUPER_FLAME: + Available[0] = SUPER_AE; + Available[1] = SUPER_BLIZZARD; + break; + case SUPER_BLIZZARD: + Available[0] = SUPER_FLAME; + Available[1] = SUPER_AE; + break; + } + + LastSuperSpell = Available[urand(0,1)]; + + switch (LastSuperSpell) + { + case SUPER_AE: + DoScriptText(RAND(SAY_EXPLOSION1,SAY_EXPLOSION2), me); + + DoCast(me, SPELL_BLINK_CENTER, true); + DoCast(me, SPELL_PLAYERPULL, true); + DoCast(me, SPELL_MASSSLOW, true); + DoCast(me, SPELL_AEXPLOSION, false); + break; + + case SUPER_FLAME: + DoScriptText(RAND(SAY_FLAMEWREATH1,SAY_FLAMEWREATH2), me); + + FlameWreathTimer = 20000; + FlameWreathCheckTime = 500; + + FlameWreathTarget[0] = 0; + FlameWreathTarget[1] = 0; + FlameWreathTarget[2] = 0; + + FlameWreathEffect(); + break; + + case SUPER_BLIZZARD: + DoScriptText(RAND(SAY_BLIZZARD1,SAY_BLIZZARD2), me); + + if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000)) + { + pSpawn->setFaction(me->getFaction()); + pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false); + } + break; + } + + SuperCastTimer = urand(35000,40000); + } else SuperCastTimer -= diff; + + if (!ElementalsSpawned && me->GetHealth()*100 / me->GetMaxHealth() < 40) + { + ElementalsSpawned = true; + + for (uint32 i = 0; i < 4; ++i) + { + if (Creature* pUnit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90000)) + { + pUnit->Attack(me->getVictim(), true); + pUnit->setFaction(me->getFaction()); + } + } + + DoScriptText(SAY_ELEMENTALS, me); + } + + if (BerserkTimer <= diff) + { + for (uint32 i = 0; i < 5; ++i) + { + if (Creature* pUnit = me->SummonCreature(CREATURE_SHADOW_OF_ARAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) + { + pUnit->Attack(me->getVictim(), true); + pUnit->setFaction(me->getFaction()); + } + } + + DoScriptText(SAY_TIMEOVER, me); + + BerserkTimer = 60000; + } else BerserkTimer -= diff; + + //Flame Wreath check + if (FlameWreathTimer) + { + if (FlameWreathTimer >= diff) + FlameWreathTimer -= diff; + else FlameWreathTimer = 0; + + if (FlameWreathCheckTime <= diff) + { + for (uint8 i = 0; i < 3; ++i) + { + if (!FlameWreathTarget[i]) + continue; + + Unit* pUnit = Unit::GetUnit(*me, FlameWreathTarget[i]); + if (pUnit && !pUnit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3)) + { + pUnit->CastSpell(pUnit, 20476, true, 0, 0, me->GetGUID()); + pUnit->CastSpell(pUnit, 11027, true); + FlameWreathTarget[i] = 0; + } + } + FlameWreathCheckTime = 500; + } else FlameWreathCheckTime -= diff; + } + + if (ArcaneCooldown && FireCooldown && FrostCooldown) + DoMeleeAttackIfReady(); + } + + void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) + { + if (!DrinkInturrupted && Drinking && damage) + DrinkInturrupted = true; + } + + void SpellHit(Unit* /*pAttacker*/, const SpellEntry* Spell) + { + //We only care about inturrupt effects and only if they are durring a spell currently being casted + if ((Spell->Effect[0] != SPELL_EFFECT_INTERRUPT_CAST && + Spell->Effect[1] != SPELL_EFFECT_INTERRUPT_CAST && + Spell->Effect[2] != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCasted(false)) + return; + + //Inturrupt effect + me->InterruptNonMeleeSpells(false); + + //Normally we would set the cooldown equal to the spell duration + //but we do not have access to the DurationStore + + switch (CurrentNormalSpell) + { + case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break; + case SPELL_FIREBALL: FireCooldown = 5000; break; + case SPELL_FROSTBOLT: FrostCooldown = 5000; break; + } + } +}; + +struct water_elementalAI : public ScriptedAI +{ + water_elementalAI(Creature *c) : ScriptedAI(c) {} + + uint32 CastTimer; + + void Reset() + { + CastTimer = 2000 + (rand()%3000); + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (CastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WATERBOLT); + CastTimer = urand(2000,5000); + } else CastTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_aran(Creature* pCreature) +{ + return new boss_aranAI (pCreature); +} + +CreatureAI* GetAI_water_elemental(Creature* pCreature) +{ + return new water_elementalAI (pCreature); +} + +// CONVERT TO ACID +CreatureAI* GetAI_shadow_of_aran(Creature* pCreature) +{ + outstring_log("TSCR: Convert simpleAI script for Creature Entry %u to ACID", pCreature->GetEntry()); + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_SHADOW_PYRO; + ai->Spell[0].Cooldown = 5000; + ai->Spell[0].First_Cast = 1000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->EnterEvadeMode(); + + return ai; +} + +void AddSC_boss_shade_of_aran() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shade_of_aran"; + newscript->GetAI = &GetAI_boss_aran; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadow_of_aran"; + newscript->GetAI = &GetAI_shadow_of_aran; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_aran_elemental"; + newscript->GetAI = &GetAI_water_elemental; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp new file mode 100644 index 00000000000..5305cc8d354 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp @@ -0,0 +1,417 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Terestian_Illhoof +SD%Complete: 95 +SDComment: Complete! Needs adjustments to use spell though. +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define SAY_SLAY1 -1532065 +#define SAY_SLAY2 -1532066 +#define SAY_DEATH -1532067 +#define SAY_AGGRO -1532068 +#define SAY_SACRIFICE1 -1532069 +#define SAY_SACRIFICE2 -1532070 +#define SAY_SUMMON1 -1532071 +#define SAY_SUMMON2 -1532072 + +#define SPELL_SUMMON_DEMONCHAINS 30120 // Summons demonic chains that maintain the ritual of sacrifice. +#define SPELL_DEMON_CHAINS 30206 // Instant - Visual Effect +#define SPELL_ENRAGE 23537 // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min. +#define SPELL_SHADOW_BOLT 30055 // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage. +#define SPELL_SACRIFICE 30115 // Teleports and adds the debuff +#define SPELL_BERSERK 32965 // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley. +#define SPELL_SUMMON_FIENDISIMP 30184 // Summons a Fiendish Imp. +#define SPELL_SUMMON_IMP 30066 // Summons Kil'rek + +#define SPELL_FIENDISH_PORTAL 30171 // Opens portal and summons Fiendish Portal, 2 sec cast +#define SPELL_FIENDISH_PORTAL_1 30179 // Opens portal and summons Fiendish Portal, instant cast + +#define SPELL_FIREBOLT 30050 // Blasts a target for 150 Fire damage. +#define SPELL_BROKEN_PACT 30065 // All damage taken increased by 25%. +#define SPELL_AMPLIFY_FLAMES 30053 // Increases the Fire damage taken by an enemy by 500 for 25 sec. + +#define CREATURE_DEMONCHAINS 17248 +#define CREATURE_FIENDISHIMP 17267 +#define CREATURE_PORTAL 17265 +#define CREATURE_KILREK 17229 + +struct mob_kilrekAI : public ScriptedAI +{ + mob_kilrekAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 TerestianGUID; + + uint32 AmplifyTimer; + + void Reset() + { + TerestianGUID = 0; + AmplifyTimer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + if (!pInstance) + { + ERROR_INST_DATA(me); + return; + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + uint64 TerestianGUID = pInstance->GetData64(DATA_TERESTIAN); + if (TerestianGUID) + { + Unit* Terestian = Unit::GetUnit((*me), TerestianGUID); + if (Terestian && Terestian->isAlive()) + DoCast(Terestian, SPELL_BROKEN_PACT, true); + } + } else ERROR_INST_DATA(me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (AmplifyTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES); + + AmplifyTimer = urand(10000,20000); + } else AmplifyTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_demon_chainAI : public ScriptedAI +{ + mob_demon_chainAI(Creature *c) : ScriptedAI(c) {} + + uint64 SacrificeGUID; + + void Reset() + { + SacrificeGUID = 0; + } + + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void JustDied(Unit * /*killer*/) + { + if (SacrificeGUID) + { + Unit* Sacrifice = Unit::GetUnit((*me),SacrificeGUID); + if (Sacrifice) + Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE); + } + } +}; + +struct mob_fiendish_portalAI : public PassiveAI +{ + mob_fiendish_portalAI(Creature *c) : PassiveAI(c),summons(me){} + + SummonList summons; + + void Reset() + { + summons.DespawnAll(); + } + + void JustSummoned(Creature* summon) + { + summons.Summon(summon); + DoZoneInCombat(summon); + } + + void DespawnAllImp() + { + summons.DespawnAll(); + } +}; + +struct boss_terestianAI : public ScriptedAI +{ + boss_terestianAI(Creature *c) : ScriptedAI(c) + { + for (uint8 i = 0; i < 2; ++i) + PortalGUID[i] = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint64 PortalGUID[2]; + uint8 PortalsCount; + + uint32 SacrificeTimer; + uint32 ShadowboltTimer; + uint32 SummonTimer; + uint32 BerserkTimer; + + bool SummonedPortals; + bool Berserk; + + void Reset() + { + for (uint8 i = 0; i < 2; ++i) + { + if (PortalGUID[i]) + { + if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[i])) + { + CAST_AI(mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp(); + pPortal->ForcedDespawn(); + } + + PortalGUID[i] = 0; + } + } + + PortalsCount = 0; + SacrificeTimer = 30000; + ShadowboltTimer = 5000; + SummonTimer = 10000; + BerserkTimer = 600000; + + SummonedPortals = false; + Berserk = false; + + if (pInstance) + pInstance->SetData(TYPE_TERESTIAN, NOT_STARTED); + + me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT); + + if (Minion* Kilrek = me->GetFirstMinion()) + { + if (!Kilrek->isAlive()) + { + Kilrek->UnSummon(); + DoCast(me, SPELL_SUMMON_IMP, true); + } + } + else DoCast(me, SPELL_SUMMON_IMP, true); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == CREATURE_PORTAL) + { + PortalGUID[PortalsCount] = pSummoned->GetGUID(); + ++PortalsCount; + + if (pSummoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1) + { + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + SummonedPortals = true; + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*killer*/) + { + for (uint8 i = 0; i < 2; ++i) + { + if (PortalGUID[i]) + { + if (Creature* pPortal = Unit::GetCreature((*me), PortalGUID[i])) + pPortal->ForcedDespawn(); + + PortalGUID[i] = 0; + } + } + + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_TERESTIAN, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (SacrificeTimer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + if (pTarget && pTarget->isAlive()) + { + DoCast(pTarget, SPELL_SACRIFICE, true); + DoCast(pTarget, SPELL_SUMMON_DEMONCHAINS, true); + + if (Creature* Chains = me->FindNearestCreature(CREATURE_DEMONCHAINS, 5000)) + { + CAST_AI(mob_demon_chainAI, Chains->AI())->SacrificeGUID = pTarget->GetGUID(); + Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true); + DoScriptText(RAND(SAY_SACRIFICE1,SAY_SACRIFICE2), me); + SacrificeTimer = 30000; + } + } + } else SacrificeTimer -= diff; + + if (ShadowboltTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT); + ShadowboltTimer = 10000; + } else ShadowboltTimer -= diff; + + if (SummonTimer <= diff) + { + if (!PortalGUID[0]) + DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL, false); + + if (!PortalGUID[1]) + DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL_1, false); + + if (PortalGUID[0] && PortalGUID[1]) + { + if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0,1)])) + pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false); + SummonTimer = 5000; + } + } else SummonTimer -= diff; + + if (!Berserk) + { + if (BerserkTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + Berserk = true; + } else BerserkTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_FIREBOLT 30050 // Blasts a target for 181-209 Fire damage. + +struct mob_fiendish_impAI : public ScriptedAI +{ + mob_fiendish_impAI(Creature *c) : ScriptedAI(c) {} + + uint32 FireboltTimer; + + void Reset() + { + FireboltTimer = 2000; + + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (FireboltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBOLT); + FireboltTimer = 2200; + } else FireboltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_kilrek(Creature* pCreature) +{ + return new mob_kilrekAI (pCreature); +} + +CreatureAI* GetAI_mob_fiendish_imp(Creature* pCreature) +{ + return new mob_fiendish_impAI (pCreature); +} + +CreatureAI* GetAI_mob_fiendish_portal(Creature* pCreature) +{ + return new mob_fiendish_portalAI (pCreature); +} + +CreatureAI* GetAI_boss_terestian_illhoof(Creature* pCreature) +{ + return new boss_terestianAI (pCreature); +} + +CreatureAI* GetAI_mob_demon_chain(Creature* pCreature) +{ + return new mob_demon_chainAI(pCreature); +} + +void AddSC_boss_terestian_illhoof() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_terestian_illhoof"; + newscript->GetAI = &GetAI_boss_terestian_illhoof; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fiendish_imp"; + newscript->GetAI = &GetAI_mob_fiendish_imp; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name= "mob_fiendish_portal"; + newscript->GetAI = &GetAI_mob_fiendish_portal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_kilrek"; + newscript->GetAI = &GetAI_mob_kilrek; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_demon_chain"; + newscript->GetAI = &GetAI_mob_demon_chain; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp new file mode 100644 index 00000000000..ae6de9c1add --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp @@ -0,0 +1,1494 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Bosses_Opera +SD%Complete: 90 +SDComment: Oz, Hood, and RAJ event implemented. RAJ event requires more testing. +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +/***********************************/ +/*** OPERA WIZARD OF OZ EVENT *****/ +/*********************************/ + +#define SAY_DOROTHEE_DEATH -1532025 +#define SAY_DOROTHEE_SUMMON -1532026 +#define SAY_DOROTHEE_TITO_DEATH -1532027 +#define SAY_DOROTHEE_AGGRO -1532028 + +#define SAY_ROAR_AGGRO -1532029 +#define SAY_ROAR_DEATH -1532030 +#define SAY_ROAR_SLAY -1532031 + +#define SAY_STRAWMAN_AGGRO -1532032 +#define SAY_STRAWMAN_DEATH -1532033 +#define SAY_STRAWMAN_SLAY -1532034 + +#define SAY_TINHEAD_AGGRO -1532035 +#define SAY_TINHEAD_DEATH -1532036 +#define SAY_TINHEAD_SLAY -1532037 +#define EMOTE_RUST -1532038 + +#define SAY_CRONE_AGGRO -1532039 +#define SAY_CRONE_AGGRO2 -1532040 +#define SAY_CRONE_DEATH -1532041 +#define SAY_CRONE_SLAY -1532042 + +/**** Spells ****/ +// Dorothee +#define SPELL_WATERBOLT 31012 +#define SPELL_SCREAM 31013 +#define SPELL_SUMMONTITO 31014 + +// Tito +#define SPELL_YIPPING 31015 + +// Strawman +#define SPELL_BRAIN_BASH 31046 +#define SPELL_BRAIN_WIPE 31069 +#define SPELL_BURNING_STRAW 31075 + +// Tinhead +#define SPELL_CLEAVE 31043 +#define SPELL_RUST 31086 + +// Roar +#define SPELL_MANGLE 31041 +#define SPELL_SHRED 31042 +#define SPELL_FRIGHTENED_SCREAM 31013 + +// Crone +#define SPELL_CHAIN_LIGHTNING 32337 + +// Cyclone +#define SPELL_KNOCKBACK 32334 +#define SPELL_CYCLONE_VISUAL 32332 + +/** Creature Entries **/ +#define CREATURE_TITO 17548 +#define CREATURE_CYCLONE 18412 +#define CREATURE_CRONE 18168 + +void SummonCroneIfReady(ScriptedInstance* pInstance, Creature* pCreature) +{ + pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, SPECIAL); // Increment DeathCount + + if (pInstance->GetData(DATA_OPERA_OZ_DEATHCOUNT) == 4) + { + if (Creature* pCrone = pCreature->SummonCreature(CREATURE_CRONE, -10891.96, -1755.95, pCreature->GetPositionZ(), 4.64, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) + { + if (pCreature->getVictim()) + pCrone->AI()->AttackStart(pCreature->getVictim()); + } + } +}; + +struct boss_dorotheeAI : public ScriptedAI +{ + boss_dorotheeAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + + uint32 WaterBoltTimer; + uint32 FearTimer; + uint32 SummonTitoTimer; + + bool SummonedTito; + bool TitoDied; + + void Reset() + { + AggroTimer = 500; + + WaterBoltTimer = 5000; + FearTimer = 15000; + SummonTitoTimer = 47500; + + SummonedTito = false; + TitoDied = false; + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_DOROTHEE_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void SummonTito(); // See below + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DOROTHEE_DEATH, me); + + if (pInstance) + SummonCroneIfReady(pInstance, me); + } + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + if (AggroTimer) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + } else AggroTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (WaterBoltTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_WATERBOLT); + WaterBoltTimer = TitoDied ? 1500 : 5000; + } else WaterBoltTimer -= diff; + + if (FearTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SCREAM); + FearTimer = 30000; + } else FearTimer -= diff; + + if (!SummonedTito) + { + if (SummonTitoTimer <= diff) + SummonTito(); + else SummonTitoTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_titoAI : public ScriptedAI +{ + mob_titoAI(Creature* c) : ScriptedAI(c) {} + + uint64 DorotheeGUID; + uint32 YipTimer; + + void Reset() + { + DorotheeGUID = 0; + YipTimer = 10000; + } + + void EnterCombat(Unit* /*who*/) {} + + void JustDied(Unit* /*killer*/) + { + if (DorotheeGUID) + { + Creature* Dorothee = (Unit::GetCreature((*me), DorotheeGUID)); + if (Dorothee && Dorothee->isAlive()) + { + CAST_AI(boss_dorotheeAI, Dorothee->AI())->TitoDied = true; + DoScriptText(SAY_DOROTHEE_TITO_DEATH, Dorothee); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (YipTimer <= diff) + { + DoCast(me->getVictim(), SPELL_YIPPING); + YipTimer = 10000; + } else YipTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void boss_dorotheeAI::SummonTito() +{ + if (Creature* pTito = me->SummonCreature(CREATURE_TITO, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + DoScriptText(SAY_DOROTHEE_SUMMON, me); + CAST_AI(mob_titoAI, pTito->AI())->DorotheeGUID = me->GetGUID(); + pTito->AI()->AttackStart(me->getVictim()); + SummonedTito = true; + TitoDied = false; + } +} + +struct boss_strawmanAI : public ScriptedAI +{ + boss_strawmanAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 BrainBashTimer; + uint32 BrainWipeTimer; + + void Reset() + { + AggroTimer = 13000; + BrainBashTimer = 5000; + BrainWipeTimer = 7000; + } + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_STRAWMAN_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry *Spell) + { + if ((Spell->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && (!(rand()%10))) + { + /* + if (not direct damage(aoe,dot)) + return; + */ + + DoCast(me, SPELL_BURNING_STRAW, true); + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_STRAWMAN_DEATH, me); + + if (pInstance) + SummonCroneIfReady(pInstance, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_STRAWMAN_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + if (AggroTimer) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + } else AggroTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (BrainBashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BRAIN_BASH); + BrainBashTimer = 15000; + } else BrainBashTimer -= diff; + + if (BrainWipeTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BRAIN_WIPE); + BrainWipeTimer = 20000; + } else BrainWipeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_tinheadAI : public ScriptedAI +{ + boss_tinheadAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 CleaveTimer; + uint32 RustTimer; + + uint8 RustCount; + + void Reset() + { + AggroTimer = 15000; + CleaveTimer = 5000; + RustTimer = 30000; + + RustCount = 0; + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_TINHEAD_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_TINHEAD_DEATH, me); + + if (pInstance) + SummonCroneIfReady(pInstance, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_TINHEAD_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + if (AggroTimer) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + } else AggroTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (CleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + CleaveTimer = 5000; + } else CleaveTimer -= diff; + + if (RustCount < 8) + { + if (RustTimer <= diff) + { + ++RustCount; + DoScriptText(EMOTE_RUST, me); + DoCast(me, SPELL_RUST); + RustTimer = 6000; + } else RustTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_roarAI : public ScriptedAI +{ + boss_roarAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 MangleTimer; + uint32 ShredTimer; + uint32 ScreamTimer; + + void Reset() + { + AggroTimer = 20000; + MangleTimer = 5000; + ShredTimer = 10000; + ScreamTimer = 15000; + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_ROAR_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_ROAR_DEATH, me); + + if (pInstance) + SummonCroneIfReady(pInstance, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_ROAR_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + if (AggroTimer) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + } else AggroTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (MangleTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MANGLE); + MangleTimer = urand(5000,8000); + } else MangleTimer -= diff; + + if (ShredTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHRED); + ShredTimer = urand(10000,15000); + } else ShredTimer -= diff; + + if (ScreamTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FRIGHTENED_SCREAM); + ScreamTimer = urand(20000,30000); + } else ScreamTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_croneAI : public ScriptedAI +{ + boss_croneAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 CycloneTimer; + uint32 ChainLightningTimer; + + void Reset() + { + CycloneTimer = 30000; + ChainLightningTimer = 10000; + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(RAND(SAY_CRONE_AGGRO,SAY_CRONE_AGGRO2), me); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_CRONE_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_OPERA, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); + + if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) + pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (CycloneTimer <= diff) + { + if (Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, urand(0,9), urand(0,9), 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000)) + Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_VISUAL, true); + CycloneTimer = 30000; + } else CycloneTimer -= diff; + + if (ChainLightningTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); + ChainLightningTimer = 15000; + } else ChainLightningTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_cycloneAI : public ScriptedAI +{ + mob_cycloneAI(Creature* c) : ScriptedAI(c) {} + + uint32 MoveTimer; + + void Reset() + { + MoveTimer = 1000; + } + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit* /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!me->HasAura(SPELL_KNOCKBACK)) + DoCast(me, SPELL_KNOCKBACK, true); + + if (MoveTimer <= diff) + { + Position pos; + me->GetRandomNearPosition(pos, 10); + me->GetMotionMaster()->MovePoint(0, pos); + MoveTimer = urand(5000,8000); + } else MoveTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_dorothee(Creature* pCreature) +{ + return new boss_dorotheeAI(pCreature); +} + +CreatureAI* GetAI_boss_strawman(Creature* pCreature) +{ + return new boss_strawmanAI(pCreature); +} + +CreatureAI* GetAI_boss_tinhead(Creature* pCreature) +{ + return new boss_tinheadAI(pCreature); +} + +CreatureAI* GetAI_boss_roar(Creature* pCreature) +{ + return new boss_roarAI(pCreature); +} + +CreatureAI* GetAI_boss_crone(Creature* pCreature) +{ + return new boss_croneAI(pCreature); +} + +CreatureAI* GetAI_mob_tito(Creature* pCreature) +{ + return new mob_titoAI(pCreature); +} + +CreatureAI* GetAI_mob_cyclone(Creature* pCreature) +{ + return new mob_cycloneAI(pCreature); +} + +/**************************************/ +/**** Opera Red Riding Hood Event ****/ +/************************************/ + +/**** Yells for the Wolf ****/ +#define SAY_WOLF_AGGRO -1532043 +#define SAY_WOLF_SLAY -1532044 +#define SAY_WOLF_HOOD -1532045 +#define SOUND_WOLF_DEATH 9275 //Only sound on death, no text. + +/**** Spells For The Wolf ****/ +#define SPELL_LITTLE_RED_RIDING_HOOD 30768 +#define SPELL_TERRIFYING_HOWL 30752 +#define SPELL_WIDE_SWIPE 30761 + +#define GOSSIP_GRANDMA "What phat lewtz you have grandmother?" + +/**** The Wolf's Entry ****/ +#define CREATURE_BIG_BAD_WOLF 17521 + +bool GossipHello_npc_grandmother(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GRANDMA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(8990, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_grandmother(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + if (Creature* pBigBadWolf = pCreature->SummonCreature(CREATURE_BIG_BAD_WOLF, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) + pBigBadWolf->AI()->AttackStart(pPlayer); + + pCreature->ForcedDespawn(); + } + + return true; +} + +struct boss_bigbadwolfAI : public ScriptedAI +{ + boss_bigbadwolfAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ChaseTimer; + uint32 FearTimer; + uint32 SwipeTimer; + + uint64 HoodGUID; + float TempThreat; + + bool IsChasing; + + void Reset() + { + ChaseTimer = 30000; + FearTimer = 25000 + rand()%10000; + SwipeTimer = 5000; + + HoodGUID = 0; + TempThreat = 0; + + IsChasing = false; + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_WOLF_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void JustDied(Unit* /*killer*/) + { + DoPlaySoundToSet(me, SOUND_WOLF_DEATH); + + if (pInstance) + { + pInstance->SetData(TYPE_OPERA, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); + + if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) + pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + + if (ChaseTimer <= diff) + { + if (!IsChasing) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(SAY_WOLF_HOOD, me); + DoCast(pTarget, SPELL_LITTLE_RED_RIDING_HOOD, true); + TempThreat = DoGetThreat(pTarget); + if (TempThreat) + DoModifyThreatPercent(pTarget, -100); + HoodGUID = pTarget->GetGUID(); + me->AddThreat(pTarget, 1000000.0f); + ChaseTimer = 20000; + IsChasing = true; + } + } + else + { + IsChasing = false; + + if (Unit *pTarget = Unit::GetUnit((*me), HoodGUID)) + { + HoodGUID = 0; + if (DoGetThreat(pTarget)) + DoModifyThreatPercent(pTarget, -100); + me->AddThreat(pTarget, TempThreat); + TempThreat = 0; + } + + ChaseTimer = 40000; + } + } else ChaseTimer -= diff; + + if (IsChasing) + return; + + if (FearTimer <= diff) + { + DoCast(me->getVictim(), SPELL_TERRIFYING_HOWL); + FearTimer = urand(25000,35000); + } else FearTimer -= diff; + + if (SwipeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WIDE_SWIPE); + SwipeTimer = urand(25000,30000); + } else SwipeTimer -= diff; + + } +}; + +CreatureAI* GetAI_boss_bigbadwolf(Creature* pCreature) +{ + return new boss_bigbadwolfAI(pCreature); +} + +/**********************************************/ +/******** Opera Romeo and Juliet Event *******/ +/********************************************/ + +/**** Speech *****/ +#define SAY_JULIANNE_AGGRO -1532046 +#define SAY_JULIANNE_ENTER -1532047 +#define SAY_JULIANNE_DEATH01 -1532048 +#define SAY_JULIANNE_DEATH02 -1532049 +#define SAY_JULIANNE_RESURRECT -1532050 +#define SAY_JULIANNE_SLAY -1532051 + +#define SAY_ROMULO_AGGRO -1532052 +#define SAY_ROMULO_DEATH -1532053 +#define SAY_ROMULO_ENTER -1532054 +#define SAY_ROMULO_RESURRECT -1532055 +#define SAY_ROMULO_SLAY -1532056 + +/***** Spells For Julianne *****/ +#define SPELL_BLINDING_PASSION 30890 +#define SPELL_DEVOTION 30887 +#define SPELL_ETERNAL_AFFECTION 30878 +#define SPELL_POWERFUL_ATTRACTION 30889 +#define SPELL_DRINK_POISON 30907 + +/***** Spells For Romulo ****/ +#define SPELL_BACKWARD_LUNGE 30815 +#define SPELL_DARING 30841 +#define SPELL_DEADLY_SWATHE 30817 +#define SPELL_POISON_THRUST 30822 + +/**** Other Misc. Spells ****/ +#define SPELL_UNDYING_LOVE 30951 +#define SPELL_RES_VISUAL 24171 + +/*** Misc. Information ****/ +#define CREATURE_ROMULO 17533 +#define ROMULO_X -10900 +#define ROMULO_Y -1758 + +enum RAJPhase +{ + PHASE_JULIANNE = 0, + PHASE_ROMULO = 1, + PHASE_BOTH = 2, +}; + +void PretendToDie(Creature* pCreature) +{ + pCreature->InterruptNonMeleeSpells(true); + pCreature->RemoveAllAuras(); + pCreature->SetHealth(0); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->GetMotionMaster()->MovementExpired(false); + pCreature->GetMotionMaster()->MoveIdle(); + pCreature->SetStandState(UNIT_STAND_STATE_DEAD); +}; + +void Resurrect(Creature *pTarget) +{ + pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTarget->SetHealth(pTarget->GetMaxHealth()); + pTarget->SetStandState(UNIT_STAND_STATE_STAND); + pTarget->CastSpell(pTarget, SPELL_RES_VISUAL, true); + if (pTarget->getVictim()) + { + pTarget->GetMotionMaster()->MoveChase(pTarget->getVictim()); + pTarget->AI()->AttackStart(pTarget->getVictim()); + } + else + pTarget->GetMotionMaster()->Initialize(); +}; + +struct boss_julianneAI : public ScriptedAI +{ + boss_julianneAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EntryYellTimer = 1000; + AggroYellTimer = 10000; + IsFakingDeath = false; + } + + ScriptedInstance* pInstance; + + uint32 EntryYellTimer; + uint32 AggroYellTimer; + + uint64 RomuloGUID; + + uint32 Phase; + + uint32 BlindingPassionTimer; + uint32 DevotionTimer; + uint32 EternalAffectionTimer; + uint32 PowerfulAttractionTimer; + uint32 SummonRomuloTimer; + uint32 ResurrectTimer; + uint32 DrinkPoisonTimer; + uint32 ResurrectSelfTimer; + + bool IsFakingDeath; + bool SummonedRomulo; + bool RomuloDead; + + void Reset() + { + RomuloGUID = 0; + Phase = PHASE_JULIANNE; + + BlindingPassionTimer = 30000; + DevotionTimer = 15000; + EternalAffectionTimer = 25000; + PowerfulAttractionTimer = 5000; + SummonRomuloTimer = 10000; + DrinkPoisonTimer = 0; + ResurrectSelfTimer = 0; + + if (IsFakingDeath) + { + Resurrect(me); + IsFakingDeath = false; + } + + SummonedRomulo = false; + RomuloDead = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry *Spell) + { + if (Spell->Id == SPELL_DRINK_POISON) + { + DoScriptText(SAY_JULIANNE_DEATH01, me); + DrinkPoisonTimer = 2500; + } + } + + void DamageTaken(Unit* done_by, uint32 &damage); + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_JULIANNE_DEATH02, me); + + if (pInstance) + { + pInstance->SetData(TYPE_OPERA, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); + if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) + pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_JULIANNE_SLAY, me); + } + + void UpdateAI(const uint32 diff); +}; + +struct boss_romuloAI : public ScriptedAI +{ + boss_romuloAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EntryYellTimer = 8000; + AggroYellTimer = 15000; + } + + ScriptedInstance* pInstance; + + uint64 JulianneGUID; + uint32 Phase; + + uint32 EntryYellTimer; + uint32 AggroYellTimer; + uint32 BackwardLungeTimer; + uint32 DaringTimer; + uint32 DeadlySwatheTimer; + uint32 PoisonThrustTimer; + uint32 ResurrectTimer; + + bool IsFakingDeath; + bool JulianneDead; + + void Reset() + { + JulianneGUID = 0; + Phase = PHASE_ROMULO; + + BackwardLungeTimer = 15000; + DaringTimer = 20000; + DeadlySwatheTimer = 25000; + PoisonThrustTimer = 10000; + ResurrectTimer = 10000; + + IsFakingDeath = false; + JulianneDead = false; + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void DamageTaken(Unit* done_by, uint32 &damage); + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_ROMULO_AGGRO, me); + if (JulianneGUID) + { + Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); + if (Julianne && Julianne->getVictim()) + { + me->AddThreat(Julianne->getVictim(), 1.0f); + AttackStart(Julianne->getVictim()); + } + } + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_ROMULO_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_OPERA, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); + + if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) + pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_ROMULO_SLAY, me); + } + + void UpdateAI(const uint32 diff); +}; + +void boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32 &damage) +{ + if (damage < me->GetHealth()) + return; + + //anything below only used if incoming damage will kill + + if (Phase == PHASE_JULIANNE) + { + damage = 0; + + //this means already drinking, so return + if (IsFakingDeath) + return; + + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_DRINK_POISON); + + IsFakingDeath = true; + //IS THIS USEFULL? Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); + return; + } + + if (Phase == PHASE_ROMULO) + { + error_log("TSCR: boss_julianneAI: cannot take damage in PHASE_ROMULO, why was i here?"); + damage = 0; + return; + } + + if (Phase == PHASE_BOTH) + { + //if this is true then we have to kill romulo too + if (RomuloDead) + { + if (Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID))) + { + Romulo->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Romulo->GetMotionMaster()->Clear(); + Romulo->setDeathState(JUST_DIED); + Romulo->CombatStop(true); + Romulo->DeleteThreatList(); + Romulo->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + return; + } + + //if not already returned, then romulo is alive and we can pretend die + if (Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID))) + { + PretendToDie(me); + IsFakingDeath = true; + CAST_AI(boss_romuloAI, Romulo->AI())->ResurrectTimer = 10000; + CAST_AI(boss_romuloAI, Romulo->AI())->JulianneDead = true; + damage = 0; + return; + } + } + error_log("TSCR: boss_julianneAI: DamageTaken reach end of code, that should not happen."); +} + +void boss_romuloAI::DamageTaken(Unit* /*done_by*/, uint32 &damage) +{ + if (damage < me->GetHealth()) + return; + + //anything below only used if incoming damage will kill + + if (Phase == PHASE_ROMULO) + { + DoScriptText(SAY_ROMULO_DEATH, me); + PretendToDie(me); + IsFakingDeath = true; + Phase = PHASE_BOTH; + + if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) + { + CAST_AI(boss_julianneAI, Julianne->AI())->RomuloDead = true; + CAST_AI(boss_julianneAI, Julianne->AI())->ResurrectSelfTimer = 10000; + } + + damage = 0; + return; + } + + if (Phase == PHASE_BOTH) + { + if (JulianneDead) + { + if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) + { + Julianne->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Julianne->GetMotionMaster()->Clear(); + Julianne->setDeathState(JUST_DIED); + Julianne->CombatStop(true); + Julianne->DeleteThreatList(); + Julianne->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + return; + } + + if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) + { + PretendToDie(me); + IsFakingDeath = true; + CAST_AI(boss_julianneAI, Julianne->AI())->ResurrectTimer = 10000; + CAST_AI(boss_julianneAI, Julianne->AI())->RomuloDead = true; + damage = 0; + return; + } + } + + error_log("TSCR: boss_romuloAI: DamageTaken reach end of code, that should not happen."); +} + +void boss_julianneAI::UpdateAI(const uint32 diff) +{ + if (EntryYellTimer) + { + if (EntryYellTimer <= diff) + { + DoScriptText(SAY_JULIANNE_ENTER, me); + EntryYellTimer = 0; + } else EntryYellTimer -= diff; + } + + if (AggroYellTimer) + { + if (AggroYellTimer <= diff) + { + DoScriptText(SAY_JULIANNE_AGGRO, me); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->setFaction(16); + AggroYellTimer = 0; + } else AggroYellTimer -= diff; + } + + if (DrinkPoisonTimer) + { + //will do this 2secs after spell hit. this is time to display visual as expected + if (DrinkPoisonTimer <= diff) + { + PretendToDie(me); + Phase = PHASE_ROMULO; + SummonRomuloTimer = 10000; + DrinkPoisonTimer = 0; + } else DrinkPoisonTimer -= diff; + } + + if (Phase == PHASE_ROMULO && !SummonedRomulo) + { + if (SummonRomuloTimer <= diff) + { + if (Creature* pRomulo = me->SummonCreature(CREATURE_ROMULO, ROMULO_X, ROMULO_Y, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) + { + RomuloGUID = pRomulo->GetGUID(); + CAST_AI(boss_romuloAI, pRomulo->AI())->JulianneGUID = me->GetGUID(); + CAST_AI(boss_romuloAI, pRomulo->AI())->Phase = PHASE_ROMULO; + DoZoneInCombat(pRomulo); + + pRomulo->setFaction(16); + } + SummonedRomulo = true; + } else SummonRomuloTimer -= diff; + } + + if (ResurrectSelfTimer) + { + if (ResurrectSelfTimer <= diff) + { + Resurrect(me); + Phase = PHASE_BOTH; + IsFakingDeath = false; + + if (me->getVictim()) + AttackStart(me->getVictim()); + + ResurrectSelfTimer = 0; + ResurrectTimer = 1000; + } else ResurrectSelfTimer -= diff; + } + + if (!UpdateVictim() || IsFakingDeath) + return; + + if (RomuloDead) + { + if (ResurrectTimer <= diff) + { + Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID)); + if (Romulo && CAST_AI(boss_romuloAI, Romulo->AI())->IsFakingDeath) + { + DoScriptText(SAY_JULIANNE_RESURRECT, me); + Resurrect(Romulo); + CAST_AI(boss_romuloAI, Romulo->AI())->IsFakingDeath = false; + RomuloDead = false; + ResurrectTimer = 10000; + } + } else ResurrectTimer -= diff; + } + + if (BlindingPassionTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BLINDING_PASSION); + BlindingPassionTimer = urand(30000,45000); + } else BlindingPassionTimer -= diff; + + if (DevotionTimer <= diff) + { + DoCast(me, SPELL_DEVOTION); + DevotionTimer = urand(15000,45000); + } else DevotionTimer -= diff; + + if (PowerfulAttractionTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_POWERFUL_ATTRACTION); + PowerfulAttractionTimer = urand(5000,30000); + } else PowerfulAttractionTimer -= diff; + + if (EternalAffectionTimer <= diff) + { + if (urand(0,1) && SummonedRomulo) + { + Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID)); + if (Romulo && Romulo->isAlive() && !RomuloDead) + DoCast(Romulo, SPELL_ETERNAL_AFFECTION); + } else DoCast(me, SPELL_ETERNAL_AFFECTION); + + EternalAffectionTimer = urand(45000,60000); + } else EternalAffectionTimer -= diff; + + DoMeleeAttackIfReady(); +} + +void boss_romuloAI::UpdateAI(const uint32 diff) +{ + if (!UpdateVictim() || IsFakingDeath) + return; + + if (JulianneDead) + { + if (ResurrectTimer <= diff) + { + Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); + if (Julianne && CAST_AI(boss_julianneAI, Julianne->AI())->IsFakingDeath) + { + DoScriptText(SAY_ROMULO_RESURRECT, me); + Resurrect(Julianne); + CAST_AI(boss_julianneAI, Julianne->AI())->IsFakingDeath = false; + JulianneDead = false; + ResurrectTimer = 10000; + } + } else ResurrectTimer -= diff; + } + + if (BackwardLungeTimer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + if (pTarget && !me->HasInArc(M_PI, pTarget)) + { + DoCast(pTarget, SPELL_BACKWARD_LUNGE); + BackwardLungeTimer = urand(15000,30000); + } + } else BackwardLungeTimer -= diff; + + if (DaringTimer <= diff) + { + DoCast(me, SPELL_DARING); + DaringTimer = urand(20000,40000); + } else DaringTimer -= diff; + + if (DeadlySwatheTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_DEADLY_SWATHE); + DeadlySwatheTimer = urand(15000,25000); + } else DeadlySwatheTimer -= diff; + + if (PoisonThrustTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_THRUST); + PoisonThrustTimer = urand(10000,20000); + } else PoisonThrustTimer -= diff; + + DoMeleeAttackIfReady(); +} + +CreatureAI* GetAI_boss_julianne(Creature* pCreature) +{ + return new boss_julianneAI(pCreature); +} + +CreatureAI* GetAI_boss_romulo(Creature* pCreature) +{ + return new boss_romuloAI(pCreature); +} + +void AddSC_bosses_opera() +{ + Script* newscript; + + // Oz + newscript = new Script; + newscript->GetAI = &GetAI_boss_dorothee; + newscript->Name = "boss_dorothee"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_strawman; + newscript->Name = "boss_strawman"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_tinhead; + newscript->Name = "boss_tinhead"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_roar; + newscript->Name = "boss_roar"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_crone; + newscript->Name = "boss_crone"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_tito; + newscript->Name = "mob_tito"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_cyclone; + newscript->Name = "mob_cyclone"; + newscript->RegisterSelf(); + + // Hood + newscript = new Script; + newscript->pGossipHello = &GossipHello_npc_grandmother; + newscript->pGossipSelect = &GossipSelect_npc_grandmother; + newscript->Name = "npc_grandmother"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_bigbadwolf; + newscript->Name = "boss_bigbadwolf"; + newscript->RegisterSelf(); + + // Romeo And Juliet + newscript = new Script; + newscript->GetAI = &GetAI_boss_julianne; + newscript->Name = "boss_julianne"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_romulo; + newscript->Name = "boss_romulo"; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp b/src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp new file mode 100644 index 00000000000..59c1236bcdc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp @@ -0,0 +1,308 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Karazhan +SD%Complete: 70 +SDComment: Instance Script for Karazhan to help in various encounters. TODO: GameObject visibility for Opera event. +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define MAX_ENCOUNTER 12 + +/* +0 - Attumen + Midnight (optional) +1 - Moroes +2 - Maiden of Virtue (optional) +3 - Hyakiss the Lurker / Rokad the Ravager / Shadikith the Glider +4 - Opera Event +5 - Curator +6 - Shade of Aran (optional) +7 - Terestian Illhoof (optional) +8 - Netherspite (optional) +9 - Chess Event +10 - Prince Malchezzar +11 - Nightbane +*/ + +struct instance_karazhan : public ScriptedInstance +{ + instance_karazhan(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string strSaveData; + + uint32 m_uiOperaEvent; + uint32 m_uiOzDeathCount; + + uint64 m_uiCurtainGUID; + uint64 m_uiStageDoorLeftGUID; + uint64 m_uiStageDoorRightGUID; + uint64 m_uiKilrekGUID; + uint64 m_uiTerestianGUID; + uint64 m_uiMoroesGUID; + uint64 m_uiLibraryDoor; // Door at Shade of Aran + uint64 m_uiMassiveDoor; // Door at Netherspite + uint64 m_uiSideEntranceDoor; // Side Entrance + uint64 m_uiGamesmansDoor; // Door before Chess + uint64 m_uiGamesmansExitDoor; // Door after Chess + uint64 m_uiNetherspaceDoor; // Door at Malchezaar + uint64 MastersTerraceDoor[2]; + uint64 ImageGUID; + uint64 DustCoveredChest; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + // 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered. + m_uiOperaEvent = urand(1,3); + m_uiOzDeathCount = 0; + + m_uiCurtainGUID = 0; + m_uiStageDoorLeftGUID = 0; + m_uiStageDoorRightGUID = 0; + + m_uiKilrekGUID = 0; + m_uiTerestianGUID = 0; + m_uiMoroesGUID = 0; + + m_uiLibraryDoor = 0; + m_uiMassiveDoor = 0; + m_uiSideEntranceDoor = 0; + m_uiGamesmansDoor = 0; + m_uiGamesmansExitDoor = 0; + m_uiNetherspaceDoor = 0; + MastersTerraceDoor[0]= 0; + MastersTerraceDoor[1]= 0; + ImageGUID = 0; + DustCoveredChest = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case 17229: m_uiKilrekGUID = pCreature->GetGUID(); break; + case 15688: m_uiTerestianGUID = pCreature->GetGUID(); break; + case 15687: m_uiMoroesGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 uiData) + { + switch (type) + { + case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break; + case TYPE_MOROES: + if (m_auiEncounter[1] == DONE) + break; + m_auiEncounter[1] = uiData; + break; + case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break; + case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break; + case TYPE_OPERA: m_auiEncounter[4] = uiData; break; + case TYPE_CURATOR: m_auiEncounter[5] = uiData; break; + case TYPE_ARAN: m_auiEncounter[6] = uiData; break; + case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break; + case TYPE_NETHERSPITE: m_auiEncounter[8] = uiData; break; + case TYPE_CHESS: + if (uiData == DONE) + DoRespawnGameObject(DustCoveredChest,DAY); + m_auiEncounter[9] = uiData; + break; + case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break; + case TYPE_NIGHTBANE: + if (m_auiEncounter[11] != DONE) + m_auiEncounter[11] = uiData; + break; + case DATA_OPERA_OZ_DEATHCOUNT: + if (uiData == SPECIAL) + ++m_uiOzDeathCount; + else if (uiData == IN_PROGRESS) + m_uiOzDeathCount = 0; + break; + } + + if (uiData == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " + << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11]; + + strSaveData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + void SetData64(uint32 identifier, uint64 data) + { + switch(identifier) + { + case DATA_IMAGE_OF_MEDIVH: ImageGUID = data; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 183932: m_uiCurtainGUID = pGo->GetGUID(); break; + case 184278: + m_uiStageDoorLeftGUID = pGo->GetGUID(); + if (m_auiEncounter[4] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case 184279: + m_uiStageDoorRightGUID = pGo->GetGUID(); + if (m_auiEncounter[4] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case 184517: m_uiLibraryDoor = pGo->GetGUID(); break; + case 185521: m_uiMassiveDoor = pGo->GetGUID(); break; + case 184276: m_uiGamesmansDoor = pGo->GetGUID(); break; + case 184277: m_uiGamesmansExitDoor = pGo->GetGUID(); break; + case 185134: m_uiNetherspaceDoor = pGo->GetGUID(); break; + case 184274: MastersTerraceDoor[0] = pGo->GetGUID(); break; + case 184280: MastersTerraceDoor[1] = pGo->GetGUID(); break; + case 184275: + m_uiSideEntranceDoor = pGo->GetGUID(); + if (m_auiEncounter[4] == DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + else + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + break; + case 185119: DustCoveredChest = pGo->GetGUID(); break; + } + + switch(m_uiOperaEvent) + { + //TODO: Set Object visibilities for Opera based on performance + case EVENT_OZ: + break; + + case EVENT_HOOD: + break; + + case EVENT_RAJ: + break; + } + } + + std::string GetSaveData() + { + return strSaveData; + } + + uint32 GetData(uint32 uiData) + { + switch (uiData) + { + case TYPE_ATTUMEN: return m_auiEncounter[0]; + case TYPE_MOROES: return m_auiEncounter[1]; + case TYPE_MAIDEN: return m_auiEncounter[2]; + case TYPE_OPTIONAL_BOSS: return m_auiEncounter[3]; + case TYPE_OPERA: return m_auiEncounter[4]; + case TYPE_CURATOR: return m_auiEncounter[5]; + case TYPE_ARAN: return m_auiEncounter[6]; + case TYPE_TERESTIAN: return m_auiEncounter[7]; + case TYPE_NETHERSPITE: return m_auiEncounter[8]; + case TYPE_CHESS: return m_auiEncounter[9]; + case TYPE_MALCHEZZAR: return m_auiEncounter[10]; + case TYPE_NIGHTBANE: return m_auiEncounter[11]; + case DATA_OPERA_PERFORMANCE: return m_uiOperaEvent; + case DATA_OPERA_OZ_DEATHCOUNT: return m_uiOzDeathCount; + case DATA_IMAGE_OF_MEDIVH: return ImageGUID; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch (uiData) + { + case DATA_KILREK: return m_uiKilrekGUID; + case DATA_TERESTIAN: return m_uiTerestianGUID; + case DATA_MOROES: return m_uiMoroesGUID; + case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID; + case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID; + case DATA_GO_CURTAINS: return m_uiCurtainGUID; + case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor; + case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor; + case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor; + case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor; + case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor; + case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor; + case DATA_MASTERS_TERRACE_DOOR_1: return MastersTerraceDoor[0]; + case DATA_MASTERS_TERRACE_DOOR_2: return MastersTerraceDoor[1]; + } + + return 0; + } + + void Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + std::istringstream loadStream(chrIn); + + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] + >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_karazhan(Map* pMap) +{ + return new instance_karazhan(pMap); +} + +void AddSC_instance_karazhan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_karazhan"; + newscript->GetInstanceData = &GetInstanceData_instance_karazhan; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp new file mode 100644 index 00000000000..5186a794b0d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp @@ -0,0 +1,646 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Karazhan +SD%Complete: 100 +SDComment: Support for Barnes (Opera controller) and Berthold (Doorman), Support for Quest 9645. +SDCategory: Karazhan +EndScriptData */ + +/* ContentData +npc_barnes +npc_berthold +npc_image_of_medivh +EndContentData */ + +#include "ScriptedPch.h" +#include "karazhan.h" +#include "ScriptedEscortAI.h" + +/*###### +# npc_barnesAI +######*/ + +#define GOSSIP_READY "I'm not an actor." + +#define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!" +#define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?" +#define OZ_GOSSIP1 "I'm not an actor." +#define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!" +#define OZ_GOSSIP2 "Ok, I'll give it a try, then." + +#define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?" +#define RAJ_GOSSIP1 "I've never been more ready." + +#define OZ_GM_GOSSIP1 "[GM] Change event to EVENT_OZ" +#define OZ_GM_GOSSIP2 "[GM] Change event to EVENT_HOOD" +#define OZ_GM_GOSSIP3 "[GM] Change event to EVENT_RAJ" + +struct Dialogue +{ + int32 textid; + uint32 timer; +}; + +static Dialogue OzDialogue[]= +{ + {-1532103, 6000}, + {-1532104, 18000}, + {-1532105, 9000}, + {-1532106, 15000} +}; + +static Dialogue HoodDialogue[]= +{ + {-1532107, 6000}, + {-1532108, 10000}, + {-1532109, 14000}, + {-1532110, 15000} +}; + +static Dialogue RAJDialogue[]= +{ + {-1532111, 5000}, + {-1532112, 7000}, + {-1532113, 14000}, + {-1532114, 14000} +}; + +// Entries and spawn locations for creatures in Oz event +float Spawns[6][2]= +{ + {17535, -10896}, // Dorothee + {17546, -10891}, // Roar + {17547, -10884}, // Tinhead + {17543, -10902}, // Strawman + {17603, -10892}, // Grandmother + {17534, -10900}, // Julianne +}; + +#define CREATURE_SPOTLIGHT 19525 + +#define SPELL_SPOTLIGHT 25824 +#define SPELL_TUXEDO 32616 + +#define SPAWN_Z 90.5 +#define SPAWN_Y -1758 +#define SPAWN_O 4.738 + +struct npc_barnesAI : public npc_escortAI +{ + npc_barnesAI(Creature* c) : npc_escortAI(c) + { + RaidWiped = false; + m_uiEventId = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 m_uiSpotlightGUID; + + uint32 TalkCount; + uint32 TalkTimer; + uint32 WipeTimer; + uint32 m_uiEventId; + + bool PerformanceReady; + bool RaidWiped; + + void Reset() + { + m_uiSpotlightGUID = 0; + + TalkCount = 0; + TalkTimer = 2000; + WipeTimer = 5000; + + PerformanceReady = false; + + if (pInstance) + m_uiEventId = pInstance->GetData(DATA_OPERA_PERFORMANCE); + } + + void StartEvent() + { + if (!pInstance) + return; + + pInstance->SetData(TYPE_OPERA, IN_PROGRESS); + + //resets count for this event, in case earlier failed + if (m_uiEventId == EVENT_OZ) + pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS); + + Start(false, false); + } + + void EnterCombat(Unit* /*who*/) {} + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch(i) + { + case 0: + DoCast(me, SPELL_TUXEDO, false); + pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT)); + break; + case 4: + TalkCount = 0; + SetEscortPaused(true); + + if (Creature* pSpotlight = me->SummonCreature(CREATURE_SPOTLIGHT, + me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f, + TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000)) + { + pSpotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pSpotlight->CastSpell(pSpotlight, SPELL_SPOTLIGHT, false); + m_uiSpotlightGUID = pSpotlight->GetGUID(); + } + break; + case 8: + pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT)); + PerformanceReady = true; + break; + case 9: + PrepareEncounter(); + pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_CURTAINS)); + break; + } + } + + void Talk(uint32 count) + { + int32 text = 0; + + switch(m_uiEventId) + { + case EVENT_OZ: + if (OzDialogue[count].textid) + text = OzDialogue[count].textid; + if (OzDialogue[count].timer) + TalkTimer = OzDialogue[count].timer; + break; + + case EVENT_HOOD: + if (HoodDialogue[count].textid) + text = HoodDialogue[count].textid; + if (HoodDialogue[count].timer) + TalkTimer = HoodDialogue[count].timer; + break; + + case EVENT_RAJ: + if (RAJDialogue[count].textid) + text = RAJDialogue[count].textid; + if (RAJDialogue[count].timer) + TalkTimer = RAJDialogue[count].timer; + break; + } + + if (text) + DoScriptText(text, me); + } + + void PrepareEncounter() + { + debug_log("TSCR: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId); + uint8 index = 0; + uint8 count = 0; + + switch(m_uiEventId) + { + case EVENT_OZ: + index = 0; + count = 4; + break; + case EVENT_HOOD: + index = 4; + count = index+1; + break; + case EVENT_RAJ: + index = 5; + count = index+1; + break; + } + + for (; index < count; ++index) + { + uint32 entry = ((uint32)Spawns[index][0]); + float PosX = Spawns[index][1]; + + if (Creature* pCreature = me->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) + { + // In case database has bad flags + pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + RaidWiped = false; + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (HasEscortState(STATE_ESCORT_PAUSED)) + { + if (TalkTimer <= diff) + { + if (TalkCount > 3) + { + if (Creature* pSpotlight = Unit::GetCreature(*me, m_uiSpotlightGUID)) + pSpotlight->ForcedDespawn(); + + SetEscortPaused(false); + return; + } + + Talk(TalkCount); + ++TalkCount; + } else TalkTimer -= diff; + } + + if (PerformanceReady) + { + if (!RaidWiped) + { + if (WipeTimer <= diff) + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) + return; + + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (PlayerList.isEmpty()) + return; + + RaidWiped = true; + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && !i->getSource()->isGameMaster()) + { + RaidWiped = false; + break; + } + } + + if (RaidWiped) + { + RaidWiped = true; + EnterEvadeMode(); + return; + } + + WipeTimer = 15000; + } else WipeTimer -= diff; + } + + } + } +}; + +CreatureAI* GetAI_npc_barnesAI(Creature* pCreature) +{ + return new npc_barnesAI(pCreature); +} + +bool GossipHello_npc_barnes(Player* pPlayer, Creature* pCreature) +{ + if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) + { + // Check for death of Moroes and if opera event is not done already + if (pInstance->GetData(TYPE_MOROES) == DONE && pInstance->GetData(TYPE_OPERA) != DONE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (pPlayer->isGameMaster()) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + } + + if (npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI,pCreature->AI())) + { + if (!pBarnesAI->RaidWiped) + pPlayer->SEND_GOSSIP_MENU(8970, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(8975, pCreature->GetGUID()); + + return true; + } + } + } + + pPlayer->SEND_GOSSIP_MENU(8978, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_barnes(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI, pCreature->AI()); + + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(8971, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + pBarnesAI->StartEvent(); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + pBarnesAI->m_uiEventId = EVENT_OZ; + outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_OZ",pPlayer->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pBarnesAI->m_uiEventId = EVENT_HOOD; + outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_HOOD",pPlayer->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pBarnesAI->m_uiEventId = EVENT_RAJ; + outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_RAJ",pPlayer->GetGUID()); + break; + } + + return true; +} + +/*### +# npc_berthold +####*/ + +enum eBerthold +{ + SPELL_TELEPORT = 39567 +}; + +#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library" + +bool GossipHello_npc_berthold(Player* pPlayer, Creature* pCreature) +{ + if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) + { + // Check if Shade of Aran event is done + if (pInstance->GetData(TYPE_ARAN) == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_berthold(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, true); + + pPlayer->CLOSE_GOSSIP_MENU(); + return true; +} + +/*### +# npc_image_of_medivh +####*/ + +#define SAY_DIALOG_MEDIVH_1 "You've got my attention, dragon. You'll find I'm not as easily scared as the villagers below." +#define SAY_DIALOG_ARCANAGOS_2 "Your dabbling in the arcane has gone too far, Medivh. You've attracted the attention of powers beyond your understanding. You must leave Karazhan at once!" +#define SAY_DIALOG_MEDIVH_3 "You dare challenge me at my own dwelling? Your arrogance is astounding, even for a dragon!" +#define SAY_DIALOG_ARCANAGOS_4 "A dark power seeks to use you, Medivh! If you stay, dire days will follow. You must hurry, we don't have much time!" +#define SAY_DIALOG_MEDIVH_5 "I do not know what you speak of, dragon... but I will not be bullied by this display of insolence. I'll leave Karazhan when it suits me!" +#define SAY_DIALOG_ARCANAGOS_6 "You leave me no alternative. I will stop you by force if you won't listen to reason!" +#define EMOTE_DIALOG_MEDIVH_7 "begins to cast a spell of great power, weaving his own essence into the magic." +#define SAY_DIALOG_ARCANAGOS_8 "What have you done, wizard? This cannot be! I'm burning from... within!" +#define SAY_DIALOG_MEDIVH_9 "He should not have angered me. I must go... recover my strength now..." + +#define MOB_ARCANAGOS 17652 +#define SPELL_FIRE_BALL 30967 +#define SPELL_UBER_FIREBALL 30971 +#define SPELL_CONFLAGRATION_BLAST 30977 +#define SPELL_MANA_SHIELD 31635 + +static float MedivPos[4] = {-11161.49,-1902.24,91.48,1.94}; +static float ArcanagosPos[4] = {-11169.75,-1881.48,95.39,4.83}; + +struct npc_image_of_medivhAI : public ScriptedAI +{ + npc_image_of_medivhAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint64 ArcanagosGUID; + + uint32 YellTimer; + uint32 Step; + uint32 FireMedivhTimer; + uint32 FireArcanagosTimer; + + bool EventStarted; + + void Reset() + { + ArcanagosGUID = 0; + + if (pInstance && pInstance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0) + { + pInstance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID()); + (*me).GetMotionMaster()->MovePoint(1,MedivPos[0],MedivPos[1],MedivPos[2]); + Step = 0; + }else + { + me->DealDamage(me,me->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + } + } + void EnterCombat(Unit* /*who*/) {} + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + if (id == 1) + { + StartEvent(); + me->SetOrientation(MedivPos[3]); + me->SetOrientation(MedivPos[3]); + } + } + + void StartEvent() + { + Step = 1; + EventStarted = true; + Creature* Arcanagos = me->SummonCreature(MOB_ARCANAGOS,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + if (!Arcanagos) + return; + ArcanagosGUID = Arcanagos->GetGUID(); + Arcanagos->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + (*Arcanagos).GetMotionMaster()->MovePoint(0,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2]); + Arcanagos->SetOrientation(ArcanagosPos[3]); + me->SetOrientation(MedivPos[3]); + YellTimer = 10000; + } + + uint32 NextStep(uint32 Step) + { + Unit* arca = Unit::GetUnit((*me),ArcanagosGUID); + Map* pMap = me->GetMap(); + switch(Step) + { + case 0: return 9999999; + case 1: + me->MonsterYell(SAY_DIALOG_MEDIVH_1,LANG_UNIVERSAL,NULL); + return 10000; + case 2: + if (arca) + CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_2,LANG_UNIVERSAL,NULL); + return 20000; + case 3: + me->MonsterYell(SAY_DIALOG_MEDIVH_3,LANG_UNIVERSAL,NULL); + return 10000; + case 4: + if (arca) + CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, NULL); + return 20000; + case 5: + me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, NULL); + return 20000; + case 6: + if (arca) + CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, NULL); + return 10000; + case 7: + FireArcanagosTimer = 500; + return 5000; + case 8: + FireMedivhTimer = 500; + DoCast(me, SPELL_MANA_SHIELD); + return 10000; + case 9: + me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false); + return 10000; + case 10: + if (arca) + DoCast(arca, SPELL_CONFLAGRATION_BLAST, false); + return 1000; + case 11: + if (arca) + CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL); + return 5000; + case 12: + arca->GetMotionMaster()->MovePoint(0, -11010.82,-1761.18, 156.47); + arca->setActive(true); + arca->InterruptNonMeleeSpells(true); + arca->SetSpeed(MOVE_FLIGHT, 2.0f); + return 10000; + case 13: + me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL); + return 10000; + case 14: + me->SetVisibility(VISIBILITY_OFF); + me->ClearInCombat(); + + if (pMap->IsDungeon()) + { + InstanceMap::PlayerList const &PlayerList = pMap->GetPlayers(); + for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive()) + { + if (i->getSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE) + i->getSource()->CompleteQuest(9645); + } + } + } + return 50000; + case 15: + arca->DealDamage(arca,arca->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return 5000; + default : return 9999999; + } + + } + + void UpdateAI(const uint32 diff) + { + + if (YellTimer <= diff) + { + if (EventStarted) + YellTimer = NextStep(Step++); + } else YellTimer -= diff; + + if (Step >= 7 && Step <= 12) + { + Unit* arca = Unit::GetUnit((*me),ArcanagosGUID); + + if (FireArcanagosTimer <= diff) + { + if (arca) + arca->CastSpell(me, SPELL_FIRE_BALL, false); + FireArcanagosTimer = 6000; + } else FireArcanagosTimer -= diff; + + if (FireMedivhTimer <= diff) + { + if (arca) + DoCast(arca, SPELL_FIRE_BALL); + FireMedivhTimer = 5000; + } else FireMedivhTimer -= diff; + } + } +}; + +CreatureAI* GetAI_npc_image_of_medivh(Creature* pCreature) +{ + return new npc_image_of_medivhAI(pCreature); +} + +void AddSC_karazhan() +{ + Script* newscript; + + newscript = new Script; + newscript->GetAI = &GetAI_npc_barnesAI; + newscript->Name = "npc_barnes"; + newscript->pGossipHello = &GossipHello_npc_barnes; + newscript->pGossipSelect = &GossipSelect_npc_barnes; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_berthold"; + newscript->pGossipHello = &GossipHello_npc_berthold; + newscript->pGossipSelect = &GossipSelect_npc_berthold; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_image_of_medivh"; + newscript->GetAI = &GetAI_npc_image_of_medivh; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/karazhan/karazhan.h b/src/server/scripts/EasternKingdoms/karazhan/karazhan.h new file mode 100644 index 00000000000..56a6b106332 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/karazhan/karazhan.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_KARAZHAN_H +#define DEF_KARAZHAN_H + +enum eEnums +{ + TYPE_ATTUMEN = 1, + TYPE_MOROES = 2, + TYPE_MAIDEN = 3, + TYPE_OPTIONAL_BOSS = 4, + TYPE_OPERA = 5, + TYPE_CURATOR = 6, + TYPE_ARAN = 7, + TYPE_TERESTIAN = 8, + TYPE_NETHERSPITE = 9, + TYPE_CHESS = 10, + TYPE_MALCHEZZAR = 11, + TYPE_NIGHTBANE = 12, + + DATA_OPERA_PERFORMANCE = 13, + DATA_OPERA_OZ_DEATHCOUNT = 14, + + DATA_KILREK = 15, + DATA_TERESTIAN = 16, + DATA_MOROES = 17, + DATA_GO_CURTAINS = 18, + DATA_GO_STAGEDOORLEFT = 19, + DATA_GO_STAGEDOORRIGHT = 20, + DATA_GO_LIBRARY_DOOR = 21, + DATA_GO_MASSIVE_DOOR = 22, + DATA_GO_NETHER_DOOR = 23, + DATA_GO_GAME_DOOR = 24, + DATA_GO_GAME_EXIT_DOOR = 25, + + DATA_IMAGE_OF_MEDIVH = 26, + DATA_MASTERS_TERRACE_DOOR_1 = 27, + DATA_MASTERS_TERRACE_DOOR_2 = 28, + DATA_GO_SIDE_ENTRANCE_DOOR = 29 +}; + +enum OperaEvents +{ + EVENT_OZ = 1, + EVENT_HOOD = 2, + EVENT_RAJ = 3 +}; + +#define ERROR_INST_DATA(a) error_log("TSCR: Instance Data for Karazhan not set properly. Encounter for Creature Entry %u may not work properly.", a->GetEntry()); +#endif + diff --git a/src/server/scripts/EasternKingdoms/loch_modan.cpp b/src/server/scripts/EasternKingdoms/loch_modan.cpp new file mode 100644 index 00000000000..e99a13fb675 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/loch_modan.cpp @@ -0,0 +1,100 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Loch_Modan +SD%Complete: 100 +SDComment: Quest support: 3181 +SDCategory: Loch Modan +EndScriptData */ + +/* ContentData +npc_mountaineer_pebblebitty +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_mountaineer_pebblebitty +######*/ + +#define GOSSIP_MP "Open the gate please, i need to get to Searing Gorge" + +#define GOSSIP_MP1 "But i need to get there, now open the gate!" +#define GOSSIP_MP2 "Ok, so what is this other way?" +#define GOSSIP_MP3 "Doesn't matter, i'm invulnerable." +#define GOSSIP_MP4 "Yes..." +#define GOSSIP_MP5 "Ok, i'll try to remember that." +#define GOSSIP_MP6 "A key? Ok!" + +bool GossipHello_npc_mountaineer_pebblebitty(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (!pPlayer->GetQuestRewardStatus(3181) == 1) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_mountaineer_pebblebitty(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(1833, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(1834, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(1835, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + pPlayer->SEND_GOSSIP_MENU(1836, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + pPlayer->SEND_GOSSIP_MENU(1837, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + pPlayer->SEND_GOSSIP_MENU(1838, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +void AddSC_loch_modan() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_mountaineer_pebblebitty"; + newscript->pGossipHello = &GossipHello_npc_mountaineer_pebblebitty; + newscript->pGossipSelect = &GossipSelect_npc_mountaineer_pebblebitty; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp new file mode 100644 index 00000000000..b5835dfe0a1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp @@ -0,0 +1,680 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Felblood_Kaelthas +SD%Complete: 80 +SDComment: Normal and Heroic Support. Issues: Arcane Spheres do not initially follow targets. +SDCategory: Magisters' Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" +#include "WorldPacket.h" + +#define SAY_AGGRO -1585023 //This yell should be done when the room is cleared. For now, set it as a movelineofsight yell. +#define SAY_PHOENIX -1585024 +#define SAY_FLAMESTRIKE -1585025 +#define SAY_GRAVITY_LAPSE -1585026 +#define SAY_TIRED -1585027 +#define SAY_RECAST_GRAVITY -1585028 +#define SAY_DEATH -1585029 + +/*** Spells ***/ + +// Phase 1 spells +#define SPELL_FIREBALL_NORMAL 44189 // Deals 2700-3300 damage at current target +#define SPELL_FIREBALL_HEROIC 46164 // 4950-6050 + +#define SPELL_PHOENIX 44194 // Summons a phoenix (Doesn't work?) +#define SPELL_PHOENIX_BURN 44197 // A spell Phoenix uses to damage everything around +#define SPELL_REBIRTH_DMG 44196 // DMG if a Phoenix rebirth happen + +#define SPELL_FLAMESTRIKE1_NORMAL 44190 // Damage part +#define SPELL_FLAMESTRIKE1_HEROIC 46163 // Heroic damage part +#define SPELL_FLAMESTRIKE2 44191 // Flamestrike indicator before the damage +#define SPELL_FLAMESTRIKE3 44192 // Summons the trigger + animation (projectile) + +#define SPELL_SHOCK_BARRIER 46165 // Heroic only; 10k damage shield, followed by Pyroblast +#define SPELL_PYROBLAST 36819 // Heroic only; 45-55k fire damage + +// Phase 2 spells +#define SPELL_GRAVITY_LAPSE_INITIAL 44224 // Cast at the beginning of every Gravity Lapse +#define SPELL_GRAVITY_LAPSE_CHANNEL 44251 // Channeled; blue beam animation to every enemy in range +#define SPELL_TELEPORT_CENTER 44218 // Should teleport people to the center. Requires DB entry in spell_target_position. +#define SPELL_GRAVITY_LAPSE_FLY 44227 // Hastens flyspeed and allows flying for 1 minute. For some reason removes 44226. +#define SPELL_GRAVITY_LAPSE_DOT 44226 // Knocks up in the air and applies a 300 DPS DoT. +#define SPELL_ARCANE_SPHERE_PASSIVE 44263 // Passive auras on Arcane Spheres +#define SPELL_POWER_FEEDBACK 44233 // Stuns him, making him take 50% more damage for 10 seconds. Cast after Gravity Lapse + +/*** Creatures ***/ +#define CREATURE_PHOENIX 24674 +#define CREATURE_PHOENIX_EGG 24675 +#define CREATURE_ARCANE_SPHERE 24708 + +/** Locations **/ +float KaelLocations[3][2]= +{ + {148.744659, 181.377426}, + {140.823883, 195.403046}, + {156.574188, 195.650482}, +}; + +#define LOCATION_Z -16.727455 + +struct boss_felblood_kaelthasAI : public ScriptedAI +{ + boss_felblood_kaelthasAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 FireballTimer; + uint32 PhoenixTimer; + uint32 FlameStrikeTimer; + uint32 CombatPulseTimer; + + //Heroic only + uint32 PyroblastTimer; + + uint32 GravityLapseTimer; + uint32 GravityLapsePhase; + // 0 = No Gravity Lapse + // 1 = Casting Gravity Lapse visual + // 2 = Teleported people to self + // 3 = Knocked people up in the air + // 4 = Applied an aura that allows them to fly, channeling visual, relased Arcane Orbs. + + bool FirstGravityLapse; + bool HasTaunted; + + uint8 Phase; + // 0 = Not started + // 1 = Fireball; Summon Phoenix; Flamestrike + // 2 = Gravity Lapses + + void Reset() + { + // TODO: Timers + FireballTimer = 0; + PhoenixTimer = 10000; + FlameStrikeTimer = 25000; + CombatPulseTimer = 0; + + PyroblastTimer = 60000; + + GravityLapseTimer = 0; + GravityLapsePhase = 0; + + FirstGravityLapse = true; + HasTaunted = false; + + Phase = 0; + + if (pInstance) + { + pInstance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), true); + // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here) + // Small door opened after event are expected to be closed by default + } + } + + void JustDied(Unit * /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), true); + // Open the encounter door + } + + void DamageTaken(Unit* /*done_by*/, uint32 &damage) + { + if (damage > me->GetHealth()) + RemoveGravityLapse(); // Remove Gravity Lapse so that players fall to ground if they kill him when in air. + } + + void EnterCombat(Unit * /*who*/) + { + if (!pInstance) + return; + + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), false); + //Close the encounter door, open it in JustDied/Reset + } + + void MoveInLineOfSight(Unit *who) + { + if (!HasTaunted && me->IsWithinDistInMap(who, 40.0)) + { + DoScriptText(SAY_AGGRO, me); + HasTaunted = true; + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void SetThreatList(Creature* SummonedUnit) + { + if (!SummonedUnit) + return; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + std::list::const_iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + { + float threat = me->getThreatManager().getThreat(pUnit); + SummonedUnit->AddThreat(pUnit, threat); + } + } + } + + void TeleportPlayersToSelf() + { + float x = KaelLocations[0][0]; + float y = KaelLocations[0][1]; + me->GetMap()->CreatureRelocation(me, x, y, LOCATION_Z, 0.0f); + //me->SendMonsterMove(x, y, LOCATION_Z, 0, 0, 0); // causes some issues... + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + pUnit->CastSpell(pUnit, SPELL_TELEPORT_CENTER, true); + } + DoCast(me, SPELL_TELEPORT_CENTER, true); + } + + void CastGravityLapseKnockUp() + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + // Knockback into the air + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, me->GetGUID()); + } + } + + void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + // Also needs an exception in spell system. + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, me->GetGUID()); + // Use packet hack + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + } + + void RemoveGravityLapse() + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); + pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); + + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + switch(Phase) + { + case 0: + { + // *Heroic mode only: + if (IsHeroic()) + { + if (PyroblastTimer <= diff) + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + DoCast(me, SPELL_SHOCK_BARRIER, true); + DoCast(me->getVictim(), SPELL_PYROBLAST); + PyroblastTimer = 60000; + } else PyroblastTimer -= diff; + } + + if (FireballTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL_NORMAL); + FireballTimer = urand(2000,6000); + } else FireballTimer -= diff; + + if (PhoenixTimer <= diff) + { + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + + uint8 random = urand(1,2); + float x = KaelLocations[random][0]; + float y = KaelLocations[random][1]; + + Creature* Phoenix = me->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + if (Phoenix) + { + Phoenix->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + SetThreatList(Phoenix); + Phoenix->AI()->AttackStart(pTarget); + } + + DoScriptText(SAY_PHOENIX, me); + + PhoenixTimer = 60000; + } else PhoenixTimer -= diff; + + if (FlameStrikeTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + DoCast(pTarget, SPELL_FLAMESTRIKE3, true); + DoScriptText(SAY_FLAMESTRIKE, me); + } + FlameStrikeTimer = urand(15000,25000); + } else FlameStrikeTimer -= diff; + + // Below 50% + if (me->GetMaxHealth() * 0.5 > me->GetHealth()) + { + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + GravityLapseTimer = 0; + GravityLapsePhase = 0; + Phase = 1; + } + + DoMeleeAttackIfReady(); + } + break; + + case 1: + { + if (GravityLapseTimer <= diff) + { + switch(GravityLapsePhase) + { + case 0: + if (FirstGravityLapse) // Different yells at 50%, and at every following Gravity Lapse + { + DoScriptText(SAY_GRAVITY_LAPSE, me); + FirstGravityLapse = false; + + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_STATUE_LEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_STATUE_RIGHT), true); + } + }else + { + DoScriptText(SAY_RECAST_GRAVITY, me); + } + + DoCast(me, SPELL_GRAVITY_LAPSE_INITIAL); + GravityLapseTimer = 2000 + diff;// Don't interrupt the visual spell + GravityLapsePhase = 1; + break; + + case 1: + TeleportPlayersToSelf(); + GravityLapseTimer = 1000; + GravityLapsePhase = 2; + break; + + case 2: + CastGravityLapseKnockUp(); + GravityLapseTimer = 1000; + GravityLapsePhase = 3; + break; + + case 3: + CastGravityLapseFly(); + GravityLapseTimer = 30000; + GravityLapsePhase = 4; + + for (uint8 i = 0; i < 3; ++i) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); + if (Orb && pTarget) + { + Orb->SetSpeed(MOVE_RUN, 0.5f); + Orb->AddThreat(pTarget, 1000000.0f); + Orb->AI()->AttackStart(pTarget); + } + + } + + DoCast(me, SPELL_GRAVITY_LAPSE_CHANNEL); + break; + + case 4: + me->InterruptNonMeleeSpells(false); + DoScriptText(SAY_TIRED, me); + DoCast(me, SPELL_POWER_FEEDBACK); + RemoveGravityLapse(); + GravityLapseTimer = 10000; + GravityLapsePhase = 0; + break; + } + } else GravityLapseTimer -= diff; + } + break; + } + } +}; + +struct mob_felkael_flamestrikeAI : public ScriptedAI +{ + mob_felkael_flamestrikeAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 FlameStrikeTimer; + + void Reset() + { + FlameStrikeTimer = 5000; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + + DoCast(me, SPELL_FLAMESTRIKE2, true); + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (FlameStrikeTimer <= diff) + { + DoCast(me, SPELL_FLAMESTRIKE1_NORMAL, true); + me->Kill(me); + } else FlameStrikeTimer -= diff; + } +}; + +struct mob_felkael_phoenixAI : public ScriptedAI +{ + mob_felkael_phoenixAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 BurnTimer; + uint32 Death_Timer; + bool Rebirth; + bool FakeDeath; + + void Reset() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + DoCast(me, SPELL_PHOENIX_BURN, true); + BurnTimer = 2000; + Death_Timer = 3000; + Rebirth = false; + FakeDeath = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage < me->GetHealth()) + return; + + //Prevent glitch if in fake death + if (FakeDeath) + { + damage = 0; + return; + + } + //Don't really die in all phases of Kael'Thas + if (pInstance && pInstance->GetData(DATA_KAELTHAS_EVENT) == 0) + { + //prevent death + damage = 0; + FakeDeath = true; + + me->InterruptNonMeleeSpells(false); + me->SetHealth(0); + me->StopMoving(); + me->ClearComboPointHolders(); + me->RemoveAllAurasOnDeath(); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->ClearAllReactives(); + me->SetUInt64Value(UNIT_FIELD_TARGET,0); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + + } + + } + + void JustDied(Unit* /*slayer*/) + { + me->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + } + + void UpdateAI(const uint32 diff) + { + + //If we are fake death, we cast revbirth and after that we kill the phoenix to spawn the egg. + if (FakeDeath) + { + if (!Rebirth) + { + DoCast(me, SPELL_REBIRTH_DMG); + Rebirth = true; + } + + if (Rebirth) + { + + if (Death_Timer <= diff) + { + me->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + me->DisappearAndDie(); + Rebirth = false; + } else Death_Timer -= diff; + } + + } + + if (!UpdateVictim()) + return; + + if (BurnTimer <= diff) + { + //spell Burn should possible do this, but it doesn't, so do this for now. + uint16 dmg = urand(1650,2050); + me->DealDamage(me, dmg, 0, DOT, SPELL_SCHOOL_MASK_FIRE, NULL, false); + BurnTimer += 2000; + } BurnTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_felkael_phoenix_eggAI : public ScriptedAI +{ + mob_felkael_phoenix_eggAI(Creature *c) : ScriptedAI(c) {} + + uint32 HatchTimer; + + void Reset() + { + HatchTimer = 10000; + } + + void EnterCombat(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (HatchTimer <= diff) + { + me->SummonCreature(CREATURE_PHOENIX, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + me->Kill(me); + } else HatchTimer -= diff; + + } +}; + +struct mob_arcane_sphereAI : public ScriptedAI +{ + mob_arcane_sphereAI(Creature *c) : ScriptedAI(c) { Reset(); } + + uint32 DespawnTimer; + uint32 ChangeTargetTimer; + + void Reset() + { + DespawnTimer = 30000; + ChangeTargetTimer = urand(6000,12000); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->setFaction(14); + DoCast(me, SPELL_ARCANE_SPHERE_PASSIVE, true); + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (DespawnTimer <= diff) + me->Kill(me); + else + DespawnTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (ChangeTargetTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + } + + ChangeTargetTimer = urand(5000,15000); + } else ChangeTargetTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_felblood_kaelthas(Creature* c) +{ + return new boss_felblood_kaelthasAI(c); +} + +CreatureAI* GetAI_mob_arcane_sphere(Creature* c) +{ + return new mob_arcane_sphereAI(c); +} + +CreatureAI* GetAI_mob_felkael_phoenix(Creature* c) +{ + return new mob_felkael_phoenixAI(c); +} + +CreatureAI* GetAI_mob_felkael_phoenix_egg(Creature* c) +{ + return new mob_felkael_phoenix_eggAI(c); +} + +CreatureAI* GetAI_mob_felkael_flamestrike(Creature* c) +{ + return new mob_felkael_flamestrikeAI(c); +} + +void AddSC_boss_felblood_kaelthas() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_felblood_kaelthas"; + newscript->GetAI = &GetAI_boss_felblood_kaelthas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_arcane_sphere"; + newscript->GetAI = &GetAI_mob_arcane_sphere; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felkael_phoenix"; + newscript->GetAI = &GetAI_mob_felkael_phoenix; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felkael_phoenix_egg"; + newscript->GetAI = &GetAI_mob_felkael_phoenix_egg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felkael_flamestrike"; + newscript->GetAI = &GetAI_mob_felkael_flamestrike; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp new file mode 100644 index 00000000000..2112eaabc87 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp @@ -0,0 +1,1321 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Priestess_Delrissa +SD%Complete: 65 +SDComment: No Heroic support yet. Needs further testing. Several scripts for pets disabled, not seem to require any special script. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" + +struct Speech +{ + int32 id; +}; + +static Speech LackeyDeath[]= +{ + {-1585013}, + {-1585014}, + {-1585015}, + {-1585016}, +}; + +static Speech PlayerDeath[]= +{ + {-1585017}, + {-1585018}, + {-1585019}, + {-1585020}, + {-1585021}, +}; + +enum eEnums +{ + SAY_AGGRO = -1585012, + SAY_DEATH = -1585022, + + SPELL_DISPEL_MAGIC = 27609, + SPELL_FLASH_HEAL = 17843, + SPELL_SW_PAIN_NORMAL = 14032, + SPELL_SW_PAIN_HEROIC = 15654, + SPELL_SHIELD = 44291, + SPELL_RENEW_NORMAL = 44174, + SPELL_RENEW_HEROIC = 46192, + + MAX_ACTIVE_LACKEY = 4 +}; + +const float fOrientation = 4.98; +const float fZLocation = -19.921; + +float LackeyLocations[4][2]= +{ + {123.77, 17.6007}, + {131.731, 15.0827}, + {121.563, 15.6213}, + {129.988, 17.2355}, +}; + +const uint32 m_auiAddEntries[] = +{ + 24557, //Kagani Nightstrike + 24558, //Elris Duskhallow + 24554, //Eramas Brightblaze + 24561, //Yazzaj + 24559, //Warlord Salaris + 24555, //Garaxxas + 24553, //Apoko + 24556, //Zelfan +}; + +struct boss_priestess_delrissaAI : public ScriptedAI +{ + boss_priestess_delrissaAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + memset(&m_auiLackeyGUID, 0, sizeof(m_auiLackeyGUID)); + LackeyEntryList.clear(); + } + + ScriptedInstance* pInstance; + + std::vector LackeyEntryList; + uint64 m_auiLackeyGUID[MAX_ACTIVE_LACKEY]; + + uint8 PlayersKilled; + + uint32 HealTimer; + uint32 RenewTimer; + uint32 ShieldTimer; + uint32 SWPainTimer; + uint32 DispelTimer; + uint32 ResetTimer; + + void Reset() + { + PlayersKilled = 0; + + HealTimer = 15000; + RenewTimer = 10000; + ShieldTimer = 2000; + SWPainTimer = 5000; + DispelTimer = 7500; + ResetTimer = 5000; + + InitializeLackeys(); + } + + //this mean she at some point evaded + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(DATA_DELRISSA_EVENT, FAIL); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + { + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[i])) + { + if (!pAdd->getVictim()) + { + who->SetInCombatWith(pAdd); + pAdd->AddThreat(who, 0.0f); + } + } + } + + if (pInstance) + pInstance->SetData(DATA_DELRISSA_EVENT, IN_PROGRESS); + } + + void InitializeLackeys() + { + //can be called if Creature are dead, so avoid + if (!me->isAlive()) + return; + + uint8 j = 0; + + //it's empty, so first time + if (LackeyEntryList.empty()) + { + //pre-allocate size for speed + LackeyEntryList.resize((sizeof(m_auiAddEntries) / sizeof(uint32))); + + //fill vector array with entries from Creature array + for (uint8 i = 0; i < LackeyEntryList.size(); ++i) + LackeyEntryList[i] = m_auiAddEntries[i]; + + //remove random entries + while (LackeyEntryList.size() > MAX_ACTIVE_LACKEY) + LackeyEntryList.erase(LackeyEntryList.begin() + rand()%LackeyEntryList.size()); + + //summon all the remaining in vector + for (std::vector::const_iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr) + { + if (Creature* pAdd = me->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0)) + m_auiLackeyGUID[j] = pAdd->GetGUID(); + + ++j; + } + } + else + { + for (std::vector::const_iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr) + { + Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[j]); + + //object already removed, not exist + if (!pAdd) + { + if (Creature* pAdd = me->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0)) + m_auiLackeyGUID[j] = pAdd->GetGUID(); + } + ++j; + } + } + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(PlayerDeath[PlayersKilled].id, me); + + if (PlayersKilled < 4) + ++PlayersKilled; + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + if (pInstance->GetData(DATA_DELRISSA_DEATH_COUNT) == MAX_ACTIVE_LACKEY) + pInstance->SetData(DATA_DELRISSA_EVENT, DONE); + else + { + if (me->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ResetTimer <= diff) + { + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + if (me->GetPositionZ() >= z+10) + { + EnterEvadeMode(); + return; + } + ResetTimer = 5000; + } else ResetTimer -= diff; + + if (HealTimer <= diff) + { + uint32 health = me->GetHealth(); + Unit *pTarget = me; + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + { + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[i])) + { + if (pAdd->isAlive() && pAdd->GetHealth() < health) + pTarget = pAdd; + } + } + + DoCast(pTarget, SPELL_FLASH_HEAL); + HealTimer = 15000; + } else HealTimer -= diff; + + if (RenewTimer <= diff) + { + Unit *pTarget = me; + + if (urand(0,1)) + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) + if (pAdd->isAlive()) + pTarget = pAdd; + + DoCast(pTarget, SPELL_RENEW_NORMAL); + RenewTimer = 5000; + } else RenewTimer -= diff; + + if (ShieldTimer <= diff) + { + Unit *pTarget = me; + + if (urand(0,1)) + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) + if (pAdd->isAlive() && !pAdd->HasAura(SPELL_SHIELD)) + pTarget = pAdd; + + DoCast(pTarget, SPELL_SHIELD); + ShieldTimer = 7500; + } else ShieldTimer -= diff; + + if (DispelTimer <= diff) + { + Unit *pTarget = NULL; + bool friendly = false; + + if (urand(0,1)) + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + else + { + friendly = true; + + if (urand(0,1)) + pTarget = me; + else + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) + if (pAdd->isAlive()) + pTarget = pAdd; + } + + if (pTarget) + DoCast(pTarget, SPELL_DISPEL_MAGIC); + + DispelTimer = 12000; + } else DispelTimer -= diff; + + if (SWPainTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SW_PAIN_NORMAL); + + SWPainTimer = 10000; + } else SWPainTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_priestess_delrissa(Creature* pCreature) +{ + return new boss_priestess_delrissaAI(pCreature); +} + +enum eHealingPotion +{ + SPELL_HEALING_POTION = 15503 +}; + +//all 8 possible lackey use this common +struct boss_priestess_lackey_commonAI : public ScriptedAI +{ + boss_priestess_lackey_commonAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + memset(&m_auiLackeyGUIDs, 0, sizeof(m_auiLackeyGUIDs)); + AcquireGUIDs(); + } + + ScriptedInstance* pInstance; + + uint64 m_auiLackeyGUIDs[MAX_ACTIVE_LACKEY]; + uint32 ResetThreatTimer; + + bool UsedPotion; + + void Reset() + { + UsedPotion = false; + + // These guys does not follow normal threat system rules + // For later development, some alternative threat system should be made + // We do not know what this system is based upon, but one theory is class (healers=high threat, dps=medium, etc) + // We reset their threat frequently as an alternative until such a system exist + ResetThreatTimer = urand(5000,20000); + + // in case she is not alive and Reset was for some reason called, respawn her (most likely party wipe after killing her) + if (Creature* pDelrissa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DELRISSA) : 0)) + { + if (!pDelrissa->isAlive()) + pDelrissa->Respawn(); + } + } + + void EnterCombat(Unit* pWho) + { + if (!pWho) + return; + + if (pInstance) + { + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + { + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUIDs[i])) + { + if (!pAdd->getVictim() && pAdd != me) + { + pWho->SetInCombatWith(pAdd); + pAdd->AddThreat(pWho, 0.0f); + } + } + } + + if (Creature* pDelrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA))) + { + if (pDelrissa->isAlive() && !pDelrissa->getVictim()) + { + pWho->SetInCombatWith(pDelrissa); + pDelrissa->AddThreat(pWho, 0.0f); + } + } + } + } + + void JustDied(Unit* /*killer*/) + { + if (!pInstance) + return; + + Creature* pDelrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA)); + uint32 uiLackeyDeathCount = pInstance->GetData(DATA_DELRISSA_DEATH_COUNT); + + if (!pDelrissa) + return; + + //should delrissa really yell if dead? + DoScriptText(LackeyDeath[uiLackeyDeathCount].id, pDelrissa); + + pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, SPECIAL); + + //increase local var, since we now may have four dead + ++uiLackeyDeathCount; + + if (uiLackeyDeathCount == MAX_ACTIVE_LACKEY) + { + //time to make her lootable and complete event if she died before lackeys + if (!pDelrissa->isAlive()) + { + if (!pDelrissa->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) + pDelrissa->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + pInstance->SetData(DATA_DELRISSA_EVENT, DONE); + } + } + } + + void KilledUnit(Unit* victim) + { + if (!pInstance) + return; + + if (Creature* Delrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA))) + Delrissa->AI()->KilledUnit(victim); + } + + void AcquireGUIDs() + { + if (!pInstance) + return; + + if (Creature* Delrissa = (Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA)))) + { + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + m_auiLackeyGUIDs[i] = CAST_AI(boss_priestess_delrissaAI, Delrissa->AI())->m_auiLackeyGUID[i]; + } + } + + void UpdateAI(const uint32 diff) + { + if (!UsedPotion && (me->GetHealth()*100 / me->GetMaxHealth()) < 25) + { + DoCast(me, SPELL_HEALING_POTION); + UsedPotion = true; + } + + if (ResetThreatTimer <= diff) + { + DoResetThreat(); + ResetThreatTimer = 5000 + rand()%15000; + } else ResetThreatTimer -= diff; + } +}; + +enum eRogueSpells +{ + SPELL_KIDNEY_SHOT = 27615, + SPELL_GOUGE = 12540, + SPELL_KICK = 27613, + SPELL_VANISH = 44290, + SPELL_BACKSTAB = 15657, + SPELL_EVISCERATE = 27611 +}; + +struct boss_kagani_nightstrikeAI : public boss_priestess_lackey_commonAI +{ + //Rogue + boss_kagani_nightstrikeAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Gouge_Timer; + uint32 Kick_Timer; + uint32 Vanish_Timer; + uint32 Eviscerate_Timer; + uint32 Wait_Timer; + bool InVanish; + + void Reset() + { + Gouge_Timer = 5500; + Kick_Timer = 7000; + Vanish_Timer = 2000; + Eviscerate_Timer = 6000; + Wait_Timer = 5000; + InVanish = false; + me->SetVisibility(VISIBILITY_ON); + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Vanish_Timer <= diff) + { + DoCast(me, SPELL_VANISH); + + Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0); + + DoResetThreat(); + + if (pUnit) + me->AddThreat(pUnit, 1000.0f); + + InVanish = true; + Vanish_Timer = 30000; + Wait_Timer = 10000; + } else Vanish_Timer -= diff; + + if (InVanish) + { + if (Wait_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BACKSTAB, true); + DoCast(me->getVictim(), SPELL_KIDNEY_SHOT, true); + me->SetVisibility(VISIBILITY_ON); // ...? Hacklike + InVanish = false; + } else Wait_Timer -= diff; + } + + if (Gouge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GOUGE); + Gouge_Timer = 5500; + } else Gouge_Timer -= diff; + + if (Kick_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KICK); + Kick_Timer = 7000; + } else Kick_Timer -= diff; + + if (Eviscerate_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_EVISCERATE); + Eviscerate_Timer = 4000; + } else Eviscerate_Timer -= diff; + + if (!InVanish) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kagani_nightstrike(Creature* pCreature) +{ + return new boss_kagani_nightstrikeAI(pCreature); +} + +enum eWarlockSpells +{ + SPELL_IMMOLATE = 44267, + SPELL_SHADOW_BOLT = 12471, + SPELL_SEED_OF_CORRUPTION = 44141, + SPELL_CURSE_OF_AGONY = 14875, + SPELL_FEAR = 38595, + SPELL_IMP_FIREBALL = 44164, + SPELL_SUMMON_IMP = 44163 +}; + +struct boss_ellris_duskhallowAI : public boss_priestess_lackey_commonAI +{ + //Warlock + boss_ellris_duskhallowAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Immolate_Timer; + uint32 Shadow_Bolt_Timer; + uint32 Seed_of_Corruption_Timer; + uint32 Curse_of_Agony_Timer; + uint32 Fear_Timer; + + void Reset() + { + Immolate_Timer = 6000; + Shadow_Bolt_Timer = 3000; + Seed_of_Corruption_Timer = 2000; + Curse_of_Agony_Timer = 1000; + Fear_Timer = 10000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void Aggro(Unit* /*pWho*/) + { + DoCast(me, SPELL_SUMMON_IMP); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Immolate_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_IMMOLATE); + Immolate_Timer = 6000; + } else Immolate_Timer -= diff; + + if (Shadow_Bolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + Shadow_Bolt_Timer = 5000; + } else Shadow_Bolt_Timer -= diff; + + if (Seed_of_Corruption_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_SEED_OF_CORRUPTION); + + Seed_of_Corruption_Timer = 10000; + } else Seed_of_Corruption_Timer -= diff; + + if (Curse_of_Agony_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_CURSE_OF_AGONY); + + Curse_of_Agony_Timer = 13000; + } else Curse_of_Agony_Timer -= diff; + + if (Fear_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_FEAR); + + Fear_Timer = 10000; + } else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_ellris_duskhallow(Creature* pCreature) +{ + return new boss_ellris_duskhallowAI(pCreature); +} + +enum eKickDown +{ + SPELL_KNOCKDOWN = 11428, + SPELL_SNAP_KICK = 46182 +}; + +struct boss_eramas_brightblazeAI : public boss_priestess_lackey_commonAI +{ + //Monk + boss_eramas_brightblazeAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Knockdown_Timer; + uint32 Snap_Kick_Timer; + + void Reset() + { + Knockdown_Timer = 6000; + Snap_Kick_Timer = 4500; + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Knockdown_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + Knockdown_Timer = 6000; + } else Knockdown_Timer -= diff; + + if (Snap_Kick_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SNAP_KICK); + Snap_Kick_Timer = 4500; + } else Snap_Kick_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_eramas_brightblaze(Creature* pCreature) +{ + return new boss_eramas_brightblazeAI(pCreature); +} + +enum eMageSpells +{ + SPELL_POLYMORPH = 13323, + SPELL_ICE_BLOCK = 27619, + SPELL_BLIZZARD = 44178, + SPELL_ICE_LANCE = 46194, + SPELL_CONE_OF_COLD = 38384, + SPELL_FROSTBOLT = 15043, + SPELL_BLINK = 14514 +}; + +struct boss_yazzaiAI : public boss_priestess_lackey_commonAI +{ + //Mage + boss_yazzaiAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + bool HasIceBlocked; + + uint32 Polymorph_Timer; + uint32 Ice_Block_Timer; + uint32 Wait_Timer; + uint32 Blizzard_Timer; + uint32 Ice_Lance_Timer; + uint32 Cone_of_Cold_Timer; + uint32 Frostbolt_Timer; + uint32 Blink_Timer; + + void Reset() + { + HasIceBlocked = false; + + Polymorph_Timer = 1000; + Ice_Block_Timer = 20000; + Wait_Timer = 10000; + Blizzard_Timer = 8000; + Ice_Lance_Timer = 12000; + Cone_of_Cold_Timer = 10000; + Frostbolt_Timer = 3000; + Blink_Timer = 8000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Polymorph_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_POLYMORPH); + Polymorph_Timer = 20000; + } + } else Polymorph_Timer -= diff; + + if (((me->GetHealth()*100 / me->GetMaxHealth()) < 35) && !HasIceBlocked) + { + DoCast(me, SPELL_ICE_BLOCK); + HasIceBlocked = true; + } + + if (Blizzard_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_BLIZZARD); + + Blizzard_Timer = 8000; + } else Blizzard_Timer -= diff; + + if (Ice_Lance_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ICE_LANCE); + Ice_Lance_Timer = 12000; + } else Ice_Lance_Timer -= diff; + + if (Cone_of_Cold_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CONE_OF_COLD); + Cone_of_Cold_Timer = 10000; + } else Cone_of_Cold_Timer -= diff; + + if (Frostbolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 8000; + } else Frostbolt_Timer -= diff; + + if (Blink_Timer <= diff) + { + bool InMeleeRange = false; + std::list& t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + //if in melee range + if (pTarget->IsWithinDistInMap(me, 5)) + { + InMeleeRange = true; + break; + } + } + } + + //if anybody is in melee range than escape by blink + if (InMeleeRange) + DoCast(me, SPELL_BLINK); + + Blink_Timer = 8000; + } else Blink_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_yazzai(Creature* pCreature) +{ + return new boss_yazzaiAI(pCreature); +} + +enum eWarriorSpells +{ + SPELL_INTERCEPT_STUN = 27577, + SPELL_DISARM = 27581, + SPELL_PIERCING_HOWL = 23600, + SPELL_FRIGHTENING_SHOUT = 19134, + SPELL_HAMSTRING = 27584, + SPELL_BATTLE_SHOUT = 27578, + SPELL_MORTAL_STRIKE = 44268 +}; + +struct boss_warlord_salarisAI : public boss_priestess_lackey_commonAI +{ + //Warrior + boss_warlord_salarisAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Intercept_Stun_Timer; + uint32 Disarm_Timer; + uint32 Piercing_Howl_Timer; + uint32 Frightening_Shout_Timer; + uint32 Hamstring_Timer; + uint32 Mortal_Strike_Timer; + + void Reset() + { + Intercept_Stun_Timer = 500; + Disarm_Timer = 6000; + Piercing_Howl_Timer = 10000; + Frightening_Shout_Timer = 18000; + Hamstring_Timer = 4500; + Mortal_Strike_Timer = 8000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_BATTLE_SHOUT); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Intercept_Stun_Timer <= diff) + { + bool InMeleeRange = false; + std::list& t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + //if in melee range + if (pTarget->IsWithinDistInMap(me, ATTACK_DISTANCE)) + { + InMeleeRange = true; + break; + } + } + } + + //if nobody is in melee range than try to use Intercept + if (!InMeleeRange) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_INTERCEPT_STUN); + } + + Intercept_Stun_Timer = 10000; + } else Intercept_Stun_Timer -= diff; + + if (Disarm_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DISARM); + Disarm_Timer = 6000; + } else Disarm_Timer -= diff; + + if (Hamstring_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + Hamstring_Timer = 4500; + } else Hamstring_Timer -= diff; + + if (Mortal_Strike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + Mortal_Strike_Timer = 4500; + } else Mortal_Strike_Timer -= diff; + + if (Piercing_Howl_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PIERCING_HOWL); + Piercing_Howl_Timer = 10000; + } else Piercing_Howl_Timer -= diff; + + if (Frightening_Shout_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); + Frightening_Shout_Timer = 18000; + } else Frightening_Shout_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_warlord_salaris(Creature* pCreature) +{ + return new boss_warlord_salarisAI(pCreature); +} + +enum eHunterSpells +{ + SPELL_AIMED_SHOT = 44271, + SPELL_SHOOT = 15620, + SPELL_CONCUSSIVE_SHOT = 27634, + SPELL_MULTI_SHOT = 31942, + SPELL_WING_CLIP = 44286, + SPELL_FREEZING_TRAP = 44136, + + NPC_SLIVER = 24552 +}; + +struct boss_garaxxasAI : public boss_priestess_lackey_commonAI +{ + //Hunter + boss_garaxxasAI(Creature *c) : boss_priestess_lackey_commonAI(c) { m_uiPetGUID = 0; } + + uint64 m_uiPetGUID; + + uint32 Aimed_Shot_Timer; + uint32 Shoot_Timer; + uint32 Concussive_Shot_Timer; + uint32 Multi_Shot_Timer; + uint32 Wing_Clip_Timer; + uint32 Freezing_Trap_Timer; + + void Reset() + { + Aimed_Shot_Timer = 6000; + Shoot_Timer = 2500; + Concussive_Shot_Timer = 8000; + Multi_Shot_Timer = 10000; + Wing_Clip_Timer = 4000; + Freezing_Trap_Timer = 15000; + + Unit* pPet = Unit::GetUnit(*me,m_uiPetGUID); + if (!pPet) + me->SummonCreature(NPC_SLIVER, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + + boss_priestess_lackey_commonAI::Reset(); + } + + void JustSummoned(Creature* pSummoned) + { + m_uiPetGUID = pSummoned->GetGUID(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (me->IsWithinDistInMap(me->getVictim(), ATTACK_DISTANCE)) + { + if (Wing_Clip_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WING_CLIP); + Wing_Clip_Timer = 4000; + } else Wing_Clip_Timer -= diff; + + if (Freezing_Trap_Timer <= diff) + { + //attempt find go summoned from spell (casted by me) + GameObject* pGo = me->GetGameObject(SPELL_FREEZING_TRAP); + + //if we have a pGo, we need to wait (only one trap at a time) + if (pGo) + Freezing_Trap_Timer = 2500; + else + { + //if pGo does not exist, then we can cast + DoCast(me->getVictim(), SPELL_FREEZING_TRAP); + Freezing_Trap_Timer = 15000; + } + } else Freezing_Trap_Timer -= diff; + + DoMeleeAttackIfReady(); + } + else + { + if (Concussive_Shot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CONCUSSIVE_SHOT); + Concussive_Shot_Timer = 8000; + } else Concussive_Shot_Timer -= diff; + + if (Multi_Shot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MULTI_SHOT); + Multi_Shot_Timer = 10000; + } else Multi_Shot_Timer -= diff; + + if (Aimed_Shot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_AIMED_SHOT); + Aimed_Shot_Timer = 6000; + } else Aimed_Shot_Timer -= diff; + + if (Shoot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHOOT); + Shoot_Timer = 2500; + } else Shoot_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_garaxxas(Creature* pCreature) +{ + return new boss_garaxxasAI(pCreature); +} + +enum Spells +{ + SPELL_WINDFURY_TOTEM = 27621, + SPELL_WAR_STOMP = 46026, + SPELL_PURGE = 27626, + SPELL_LESSER_HEALING_WAVE = 44256, + SPELL_FROST_SHOCK = 21401, + SPELL_FIRE_NOVA_TOTEM = 44257, + SPELL_EARTHBIND_TOTEM = 15786 +}; + +struct boss_apokoAI : public boss_priestess_lackey_commonAI +{ + //Shaman + boss_apokoAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Totem_Timer; + uint8 Totem_Amount; + uint32 War_Stomp_Timer; + uint32 Purge_Timer; + uint32 Healing_Wave_Timer; + uint32 Frost_Shock_Timer; + + void Reset() + { + Totem_Timer = 2000; + Totem_Amount = 1; + War_Stomp_Timer = 10000; + Purge_Timer = 8000; + Healing_Wave_Timer = 5000; + Frost_Shock_Timer = 7000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Totem_Timer <= diff) + { + DoCast(me, RAND(SPELL_WINDFURY_TOTEM,SPELL_FIRE_NOVA_TOTEM,SPELL_EARTHBIND_TOTEM)); + ++Totem_Amount; + Totem_Timer = Totem_Amount*2000; + } else Totem_Timer -= diff; + + if (War_Stomp_Timer <= diff) + { + DoCast(me, SPELL_WAR_STOMP); + War_Stomp_Timer = 10000; + } else War_Stomp_Timer -= diff; + + if (Purge_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_PURGE); + + Purge_Timer = 15000; + } else Purge_Timer -= diff; + + if (Frost_Shock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_SHOCK); + Frost_Shock_Timer = 7000; + } else Frost_Shock_Timer -= diff; + + if (Healing_Wave_Timer <= diff) + { + // std::vector::const_iterator itr = Group.begin() + rand()%Group.size(); + // uint64 guid = (*itr)->guid; + // if (guid) + // { + // Unit* pAdd = Unit::GetUnit(*me, (*itr)->guid); + // if (pAdd && pAdd->isAlive()) + // { + DoCast(me, SPELL_LESSER_HEALING_WAVE); + Healing_Wave_Timer = 5000; + // } + // } + } else Healing_Wave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_apoko(Creature* pCreature) +{ + return new boss_apokoAI(pCreature); +} + +enum eEngineerSpells +{ + SPELL_GOBLIN_DRAGON_GUN = 44272, + SPELL_ROCKET_LAUNCH = 44137, + SPELL_RECOMBOBULATE = 44274, + SPELL_HIGH_EXPLOSIVE_SHEEP = 44276, + SPELL_FEL_IRON_BOMB = 46024, + SPELL_SHEEP_EXPLOSION = 44279 +}; + +struct boss_zelfanAI : public boss_priestess_lackey_commonAI +{ + //Engineer + boss_zelfanAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Goblin_Dragon_Gun_Timer; + uint32 Rocket_Launch_Timer; + uint32 Recombobulate_Timer; + uint32 High_Explosive_Sheep_Timer; + uint32 Fel_Iron_Bomb_Timer; + + void Reset() + { + Goblin_Dragon_Gun_Timer = 20000; + Rocket_Launch_Timer = 7000; + Recombobulate_Timer = 4000; + High_Explosive_Sheep_Timer = 10000; + Fel_Iron_Bomb_Timer = 15000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Goblin_Dragon_Gun_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GOBLIN_DRAGON_GUN); + Goblin_Dragon_Gun_Timer = 10000; + } else Goblin_Dragon_Gun_Timer -= diff; + + if (Rocket_Launch_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ROCKET_LAUNCH); + Rocket_Launch_Timer = 9000; + } else Rocket_Launch_Timer -= diff; + + if (Fel_Iron_Bomb_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FEL_IRON_BOMB); + Fel_Iron_Bomb_Timer = 15000; + } else Fel_Iron_Bomb_Timer -= diff; + + if (Recombobulate_Timer <= diff) + { + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + { + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUIDs[i])) + { + if (pAdd->IsPolymorphed()) + { + DoCast(pAdd, SPELL_RECOMBOBULATE); + break; + } + } + } + Recombobulate_Timer = 2000; + } else Recombobulate_Timer -= diff; + + if (High_Explosive_Sheep_Timer <= diff) + { + DoCast(me, SPELL_HIGH_EXPLOSIVE_SHEEP); + High_Explosive_Sheep_Timer = 65000; + } else High_Explosive_Sheep_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_zelfan(Creature* pCreature) +{ + return new boss_zelfanAI(pCreature); +} + +//struct mob_high_explosive_sheepAI : public ScriptedAI +//{ +// mob_high_explosive_sheepAI(Creature *c) : ScriptedAI(c) {} +// +// uint32 Explosion_Timer; +// +// void Reset() +// { +// Explosion_Timer = 60000; +// } +// +// void JustDied(Unit *Killer){} +// +// void EnterCombat(Unit * /*who*/){} +// +// void UpdateAI(const uint32 diff) +// { +// if (Explosion_Timer <= diff) +// { +// DoCast(me->getVictim(), SPELL_SHEEP_EXPLOSION); +// }else +// Explosion_Timer -= diff; +// } +//}; + +//CreatureAI* GetAI_mob_high_explosive_sheep(Creature* pCreature) +//{ +// return new mob_high_explosive_sheepAI (pCreature); +//}; + +void AddSC_boss_priestess_delrissa() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_priestess_delrissa"; + newscript->GetAI = &GetAI_boss_priestess_delrissa; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_kagani_nightstrike"; + newscript->GetAI = &GetAI_boss_kagani_nightstrike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_ellris_duskhallow"; + newscript->GetAI = &GetAI_ellris_duskhallow; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_eramas_brightblaze"; + newscript->GetAI = &GetAI_eramas_brightblaze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_yazzai"; + newscript->GetAI = &GetAI_yazzai; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_warlord_salaris"; + newscript->GetAI = &GetAI_warlord_salaris; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_garaxxas"; + newscript->GetAI = &GetAI_garaxxas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_apoko"; + newscript->GetAI = &GetAI_apoko; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_zelfan"; + newscript->GetAI = &GetAI_zelfan; + newscript->RegisterSelf(); + + /*newscript = new Script; + newscript->Name = "mob_high_explosive_sheep"; + newscript->GetAI = &GetAI_mob_high_explosive_sheep; + newscript->RegisterSelf();*/ +} + diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp new file mode 100644 index 00000000000..adb0700eabf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp @@ -0,0 +1,366 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Selin_Fireheart +SD%Complete: 90 +SDComment: Heroic and Normal Support. Needs further testing. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" + +#define SAY_AGGRO -1585000 +#define SAY_ENERGY -1585001 +#define SAY_EMPOWERED -1585002 +#define SAY_KILL_1 -1585003 +#define SAY_KILL_2 -1585004 +#define SAY_DEATH -1585005 +#define EMOTE_CRYSTAL -1585006 + +//Crystal effect spells +#define SPELL_FEL_CRYSTAL_COSMETIC 44374 +#define SPELL_FEL_CRYSTAL_DUMMY 44329 +#define SPELL_FEL_CRYSTAL_VISUAL 44355 +#define SPELL_MANA_RAGE 44320 // This spell triggers 44321, which changes scale and regens mana Requires an entry in spell_script_target + +//Selin's spells +#define SPELL_DRAIN_LIFE 44294 +#define SPELL_FEL_EXPLOSION 44314 + +#define SPELL_DRAIN_MANA 46153 // Heroic only + +#define CRYSTALS_NUMBER 5 +#define DATA_CRYSTALS 6 + +#define CREATURE_FEL_CRYSTAL 24722 + +struct boss_selin_fireheartAI : public ScriptedAI +{ + boss_selin_fireheartAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + + Crystals.clear(); + //GUIDs per instance is static, so we only need to load them once. + if (pInstance) + { + uint32 size = pInstance->GetData(DATA_FEL_CRYSTAL_SIZE); + for (uint8 i = 0; i < size; ++i) + { + uint64 guid = pInstance->GetData64(DATA_FEL_CRYSTAL); + debug_log("TSCR: Selin: Adding Fel Crystal %u to list", guid); + Crystals.push_back(guid); + } + } + } + + ScriptedInstance* pInstance; + + std::list Crystals; + + uint32 DrainLifeTimer; + uint32 DrainManaTimer; + uint32 FelExplosionTimer; + uint32 DrainCrystalTimer; + uint32 EmpowerTimer; + + bool IsDraining; + bool DrainingCrystal; + + uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course). + + void Reset() + { + if (pInstance) + { + //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + //Unit* pUnit = Unit::GetUnit(*me, FelCrystals[i]); + Unit* pUnit = Unit::GetUnit(*me, *itr); + if (pUnit) + { + if (!pUnit->isAlive()) + CAST_CRE(pUnit)->Respawn(); // Let the core handle setting death state, etc. + + // Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here. + pUnit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + + pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); + // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here) + // Small door opened after event are expected to be closed by default + // Set Inst data for encounter + pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED); + } else error_log(ERROR_INST_DATA); + + DrainLifeTimer = 3000 + rand()%4000; + DrainManaTimer = DrainLifeTimer + 5000; + FelExplosionTimer = 2100; + DrainCrystalTimer = 10000 + rand()%5000; + DrainCrystalTimer = 20000 + rand()%5000; + EmpowerTimer = 10000; + + IsDraining = false; + DrainingCrystal = false; + CrystalGUID = 0; + } + + void SelectNearestCrystal() + { + if (Crystals.empty()) + return; + + //float ShortestDistance = 0; + CrystalGUID = 0; + Unit* pCrystal = NULL; + Unit* CrystalChosen = NULL; + //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + pCrystal = NULL; + //pCrystal = Unit::GetUnit(*me, FelCrystals[i]); + pCrystal = Unit::GetUnit(*me, *itr); + if (pCrystal && pCrystal->isAlive()) + { + // select nearest + if (!CrystalChosen || me->GetDistanceOrder(pCrystal, CrystalChosen, false)) + { + CrystalGUID = pCrystal->GetGUID(); + CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell. + } + } + } + if (CrystalChosen) + { + DoScriptText(SAY_ENERGY, me); + DoScriptText(EMOTE_CRYSTAL, me); + + CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true); + + float x, y, z; // coords that we move to, close to the crystal. + CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE); + + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->MovePoint(1, x, y, z); + DrainingCrystal = true; + } + } + + void ShatterRemainingCrystals() + { + if (Crystals.empty()) + return; + + //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + //Creature* pCrystal = (Unit::GetCreature(*me, FelCrystals[i])); + Creature* pCrystal = Unit::GetCreature(*me, *itr); + if (pCrystal && pCrystal->isAlive()) + pCrystal->Kill(pCrystal); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), false); + //Close the encounter door, open it in JustDied/Reset + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type == POINT_MOTION_TYPE && id == 1) + { + Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID); + if (CrystalChosen && CrystalChosen->isAlive()) + { + // Make the crystal attackable + // We also remove NON_ATTACKABLE in case the database has it set. + CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + CrystalChosen->CastSpell(me, SPELL_MANA_RAGE, true); + IsDraining = true; + } + else + { + // Make an error message in case something weird happened here + error_log("TSCR: Selin Fireheart unable to drain crystal as the crystal is either dead or despawned"); + DrainingCrystal = false; + } + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + pInstance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete! + pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); // Open the encounter door + pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_DOOR), true); // Open the door leading further in + ShatterRemainingCrystals(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!DrainingCrystal) + { + uint32 maxPowerMana = me->GetMaxPower(POWER_MANA); + if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10)) + { + if (DrainLifeTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE); + DrainLifeTimer = 10000; + } else DrainLifeTimer -= diff; + + // Heroic only + if (IsHeroic()) + { + if (DrainManaTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_DRAIN_MANA); + DrainManaTimer = 10000; + } else DrainManaTimer -= diff; + } + } + + if (FelExplosionTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_FEL_EXPLOSION); + FelExplosionTimer = 2000; + } + } else FelExplosionTimer -= diff; + + // If below 10% mana, start recharging + maxPowerMana = me->GetMaxPower(POWER_MANA); + if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10)) + { + if (DrainCrystalTimer <= diff) + { + SelectNearestCrystal(); + if (IsHeroic()) + DrainCrystalTimer = 10000 + rand()%5000; + else + DrainCrystalTimer = 20000 + rand()%5000; + } else DrainCrystalTimer -= diff; + } + + }else + { + if (IsDraining) + { + if (EmpowerTimer <= diff) + { + IsDraining = false; + DrainingCrystal = false; + + DoScriptText(SAY_EMPOWERED, me); + + Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID); + if (CrystalChosen && CrystalChosen->isAlive()) + // Use Deal Damage to kill it, not setDeathState. + CrystalChosen->Kill(CrystalChosen); + + CrystalGUID = 0; + + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } else EmpowerTimer -= diff; + } + } + + DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun. + } +}; + +CreatureAI* GetAI_boss_selin_fireheart(Creature* pCreature) +{ + return new boss_selin_fireheartAI (pCreature); +}; + +struct mob_fel_crystalAI : public ScriptedAI +{ + mob_fel_crystalAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} + + void JustDied(Unit* /*killer*/) + { + if (ScriptedInstance* pInstance = me->GetInstanceData()) + { + Creature* Selin = (Unit::GetCreature(*me, pInstance->GetData64(DATA_SELIN))); + if (Selin && Selin->isAlive()) + { + if (CAST_AI(boss_selin_fireheartAI, Selin->AI())->CrystalGUID == me->GetGUID()) + { + // Set this to false if we are the Creature that Selin is draining so his AI flows properly + CAST_AI(boss_selin_fireheartAI, Selin->AI())->DrainingCrystal = false; + CAST_AI(boss_selin_fireheartAI, Selin->AI())->IsDraining = false; + CAST_AI(boss_selin_fireheartAI, Selin->AI())->EmpowerTimer = 10000; + if (Selin->getVictim()) + { + Selin->AI()->AttackStart(Selin->getVictim()); + Selin->GetMotionMaster()->MoveChase(Selin->getVictim()); + } + } + } + } else error_log(ERROR_INST_DATA); + } +}; + +CreatureAI* GetAI_mob_fel_crystal(Creature* pCreature) +{ + return new mob_fel_crystalAI (pCreature); +}; + +void AddSC_boss_selin_fireheart() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_selin_fireheart"; + newscript->GetAI = &GetAI_boss_selin_fireheart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_crystal"; + newscript->GetAI = &GetAI_mob_fel_crystal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp new file mode 100644 index 00000000000..bc8bd5cec30 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp @@ -0,0 +1,226 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vexallus +SD%Complete: 90 +SDComment: Heroic and Normal support. Needs further testing. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" + +enum eEnums +{ + SAY_AGGRO = -1585007, + SAY_ENERGY = -1585008, + SAY_OVERLOAD = -1585009, + SAY_KILL = -1585010, + EMOTE_DISCHARGE_ENERGY = -1585011, + + //is this text for real? + //#define SAY_DEATH "What...happen...ed." + + //Pure energy spell info + SPELL_ENERGY_BOLT = 46156, + SPELL_ENERGY_FEEDBACK = 44335, + + //Vexallus spell info + SPELL_CHAIN_LIGHTNING = 44318, + SPELL_H_CHAIN_LIGHTNING = 46380, //heroic spell + SPELL_OVERLOAD = 44353, + SPELL_ARCANE_SHOCK = 44319, + SPELL_H_ARCANE_SHOCK = 46381, //heroic spell + + SPELL_SUMMON_PURE_ENERGY = 44322, //mod scale -10 + H_SPELL_SUMMON_PURE_ENERGY1 = 46154, //mod scale -5 + H_SPELL_SUMMON_PURE_ENERGY2 = 46159, //mod scale -5 + + //Creatures + NPC_PURE_ENERGY = 24745, + + INTERVAL_MODIFIER = 15, + INTERVAL_SWITCH = 6 +}; + +struct boss_vexallusAI : public ScriptedAI +{ + boss_vexallusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ChainLightningTimer; + uint32 ArcaneShockTimer; + uint32 OverloadTimer; + uint32 IntervalHealthAmount; + bool Enraged; + + void Reset() + { + ChainLightningTimer = 8000; + ArcaneShockTimer = 5000; + OverloadTimer = 1200; + IntervalHealthAmount = 1; + Enraged = false; + + if (pInstance) + pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_VEXALLUS_EVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature *summoned) + { + if (Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 0)) + summoned->GetMotionMaster()->MoveFollow(temp,0,0); + + //spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok + summoned->CastSpell(summoned,SPELL_ENERGY_BOLT,false,0,0,me->GetGUID()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!Enraged) + { + //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25% + if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(INTERVAL_MODIFIER*IntervalHealthAmount))) + { + //increase amount, unless we're at 10%, then we switch and return + if (IntervalHealthAmount == INTERVAL_SWITCH) + { + Enraged = true; + return; + } + else + ++IntervalHealthAmount; + + DoScriptText(SAY_ENERGY, me); + DoScriptText(EMOTE_DISCHARGE_ENERGY, me); + + if (IsHeroic()) + { + DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false); + DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false); + } + else + DoCast(me, SPELL_SUMMON_PURE_ENERGY, false); + + //below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core + me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (IsHeroic()) + me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + } + + if (ChainLightningTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + + ChainLightningTimer = 8000; + } else ChainLightningTimer -= diff; + + if (ArcaneShockTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + if (pTarget) + DoCast(pTarget, SPELL_ARCANE_SHOCK); + + ArcaneShockTimer = 8000; + } else ArcaneShockTimer -= diff; + } + else + { + if (OverloadTimer <= diff) + { + DoCast(me->getVictim(), SPELL_OVERLOAD); + + OverloadTimer = 2000; + } else OverloadTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vexallus(Creature* pCreature) +{ + return new boss_vexallusAI (pCreature); +}; + +struct mob_pure_energyAI : public ScriptedAI +{ + mob_pure_energyAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + + void JustDied(Unit* slayer) + { + if (Unit *temp = me->GetOwner()) + { + if (temp && temp->isAlive()) + slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID()); + } + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + void AttackStart(Unit * /*who*/) {} +}; + +CreatureAI* GetAI_mob_pure_energy(Creature* pCreature) +{ + return new mob_pure_energyAI (pCreature); +}; + +void AddSC_boss_vexallus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_vexallus"; + newscript->GetAI = &GetAI_boss_vexallus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_pure_energy"; + newscript->GetAI = &GetAI_mob_pure_energy; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp new file mode 100644 index 00000000000..455c03739bc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Magisters_Terrace +SD%Complete: 60 +SDComment: Designed only for Selin Fireheart +SDCategory: Magister's Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" + +#define MAX_ENCOUNTER 4 + +/* +0 - Selin Fireheart +1 - Vexallus +2 - Priestess Delrissa +3 - Kael'thas Sunstrider +*/ + +struct instance_magisters_terrace : public ScriptedInstance +{ + instance_magisters_terrace(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 DelrissaDeathCount; + + std::list FelCrystals; + std::list::const_iterator CrystalItr; + + uint64 SelinGUID; + uint64 DelrissaGUID; + uint64 VexallusDoorGUID; + uint64 SelinDoorGUID; + uint64 SelinEncounterDoorGUID; + uint64 DelrissaDoorGUID; + uint64 KaelDoorGUID; + uint64 KaelStatue[2]; + + bool InitializedItr; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + FelCrystals.clear(); + + DelrissaDeathCount = 0; + + SelinGUID = 0; + DelrissaGUID = 0; + VexallusDoorGUID = 0; + SelinDoorGUID = 0; + SelinEncounterDoorGUID = 0; + DelrissaDoorGUID = 0; + KaelDoorGUID = 0; + KaelStatue[0] = 0; + KaelStatue[1] = 0; + + InitializedItr = false; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + return false; + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_SELIN_EVENT: return m_auiEncounter[0]; + case DATA_VEXALLUS_EVENT: return m_auiEncounter[1]; + case DATA_DELRISSA_EVENT: return m_auiEncounter[2]; + case DATA_KAELTHAS_EVENT: return m_auiEncounter[3]; + case DATA_DELRISSA_DEATH_COUNT: return DelrissaDeathCount; + case DATA_FEL_CRYSTAL_SIZE: return FelCrystals.size(); + } + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch(identifier) + { + case DATA_SELIN_EVENT: m_auiEncounter[0] = data; break; + case DATA_VEXALLUS_EVENT: + if (data == DONE) + DoUseDoorOrButton(VexallusDoorGUID); + m_auiEncounter[1] = data; + break; + case DATA_DELRISSA_EVENT: + if (data == DONE) + DoUseDoorOrButton(DelrissaDoorGUID); + if (data == IN_PROGRESS) + DelrissaDeathCount = 0; + m_auiEncounter[2] = data; + break; + case DATA_KAELTHAS_EVENT: m_auiEncounter[3] = data; break; + + case DATA_DELRISSA_DEATH_COUNT: + if (data == SPECIAL) + ++DelrissaDeathCount; + else + DelrissaDeathCount = 0; + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 24723: SelinGUID = pCreature->GetGUID(); break; + case 24560: DelrissaGUID = pCreature->GetGUID(); break; + case 24722: FelCrystals.push_back(pCreature->GetGUID()); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 187896: VexallusDoorGUID = pGo->GetGUID(); break; + //SunwellRaid Gate 02 + case 187979: SelinDoorGUID = pGo->GetGUID(); break; + //Assembly Chamber Door + case 188065: SelinEncounterDoorGUID = pGo->GetGUID(); break; + case 187770: DelrissaDoorGUID = pGo->GetGUID(); break; + case 188064: KaelDoorGUID = pGo->GetGUID(); break; + case 188165: KaelStatue[0] = pGo->GetGUID(); break; + case 188166: KaelStatue[1] = pGo->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_SELIN: return SelinGUID; + case DATA_DELRISSA: return DelrissaGUID; + case DATA_VEXALLUS_DOOR: return VexallusDoorGUID; + case DATA_SELIN_DOOR: return SelinDoorGUID; + case DATA_SELIN_ENCOUNTER_DOOR: return SelinEncounterDoorGUID; + case DATA_DELRISSA_DOOR: return DelrissaDoorGUID; + case DATA_KAEL_DOOR: return KaelDoorGUID; + case DATA_KAEL_STATUE_LEFT: return KaelStatue[0]; + case DATA_KAEL_STATUE_RIGHT: return KaelStatue[1]; + + case DATA_FEL_CRYSTAL: + { + if (FelCrystals.empty()) + { + error_log("TSCR: Magisters Terrace: No Fel Crystals loaded in Inst Data"); + return 0; + } + + if (!InitializedItr) + { + CrystalItr = FelCrystals.begin(); + InitializedItr = true; + } + + uint64 guid = *CrystalItr; + ++CrystalItr; + return guid; + } + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_magisters_terrace(Map* pMap) +{ + return new instance_magisters_terrace(pMap); +} + +void AddSC_instance_magisters_terrace() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_magisters_terrace"; + newscript->GetInstanceData = &GetInstanceData_instance_magisters_terrace; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp new file mode 100644 index 00000000000..e46da9cb1bf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Magisters_Terrace +SD%Complete: 100 +SDComment: Quest support: 11490(post-event) +SDCategory: Magisters Terrace +EndScriptData */ + +/* ContentData +npc_kalecgos +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_kalecgos +######*/ + +enum eEnums +{ + SPELL_TRANSFORM_TO_KAEL = 44670, + SPELL_ORB_KILL_CREDIT = 46307, + NPC_KAEL = 24848, //human form entry + POINT_ID_LAND = 1 +}; + +const float afKaelLandPoint[] = {225.045, -276.236, -5.434}; + +#define GOSSIP_ITEM_KAEL_1 "Who are you?" +#define GOSSIP_ITEM_KAEL_2 "What can we do to assist you?" +#define GOSSIP_ITEM_KAEL_3 "What brings you to the Sunwell?" +#define GOSSIP_ITEM_KAEL_4 "You're not alone here?" +#define GOSSIP_ITEM_KAEL_5 "What would Kil'jaeden want with a mortal woman?" + +// This is friendly keal that appear after used Orb. +// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is +struct npc_kalecgosAI : public ScriptedAI +{ + npc_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 m_uiTransformTimer; + + void Reset() + { + m_uiTransformTimer = 0; + + // we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here + if (me->GetEntry() != NPC_KAEL) + me->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (uiPointId == POINT_ID_LAND) + m_uiTransformTimer = MINUTE*IN_MILISECONDS; + } + + // some targeting issues with the spell, so use this workaround as temporary solution + void DoWorkaroundForQuestCredit() + { + Map* pMap = me->GetMap(); + + if (!pMap || pMap->IsHeroic()) + return; + + Map::PlayerList const &lList = pMap->GetPlayers(); + + if (lList.isEmpty()) + return; + + SpellEntry const* pSpell = GetSpellStore()->LookupEntry(SPELL_ORB_KILL_CREDIT); + + for (Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pSpell && pSpell->EffectMiscValue[0]) + pPlayer->KilledMonsterCredit(pSpell->EffectMiscValue[0], 0); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiTransformTimer) + { + if (m_uiTransformTimer <= uiDiff) + { + DoCast(me, SPELL_ORB_KILL_CREDIT, false); + DoWorkaroundForQuestCredit(); + + // Transform and update entry, now ready for quest/read gossip + DoCast(me, SPELL_TRANSFORM_TO_KAEL, false); + me->UpdateEntry(NPC_KAEL); + + m_uiTransformTimer = 0; + } else m_uiTransformTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_kalecgos(Creature* pCreature) +{ + return new npc_kalecgosAI(pCreature); +} + +bool GossipHello_npc_kalecgos(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(12498, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_kalecgos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(12500, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(12502, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(12606, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(12607, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->SEND_GOSSIP_MENU(12608, pCreature->GetGUID()); + break; + } + + return true; +} + +void AddSC_magisters_terrace() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_kalecgos"; + newscript->GetAI = &GetAI_npc_kalecgos; + newscript->pGossipHello = &GossipHello_npc_kalecgos; + newscript->pGossipSelect = &GossipSelect_npc_kalecgos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h new file mode 100644 index 00000000000..d6419ea409c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MAGISTERS_TERRACE_H +#define DEF_MAGISTERS_TERRACE_H + +#define DATA_SELIN_EVENT 1 +#define DATA_VEXALLUS_EVENT 2 +#define DATA_DELRISSA_EVENT 3 +#define DATA_KAELTHAS_EVENT 4 + +#define DATA_SELIN 5 +#define DATA_FEL_CRYSTAL 6 +#define DATA_FEL_CRYSTAL_SIZE 7 + +#define DATA_VEXALLUS_DOOR 8 +#define DATA_SELIN_DOOR 9 +#define DATA_DELRISSA 10 +#define DATA_DELRISSA_DOOR 11 +#define DATA_SELIN_ENCOUNTER_DOOR 12 + +#define DATA_KAEL_DOOR 13 +#define DATA_KAEL_STATUE_LEFT 14 +#define DATA_KAEL_STATUE_RIGHT 15 + +#define DATA_DELRISSA_DEATH_COUNT 16 + +#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy." +#endif + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp new file mode 100644 index 00000000000..77c6fafa10a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp @@ -0,0 +1,107 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Baron_Geddon +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_SERVICE -1409000 + +#define SPELL_INFERNO 19695 +#define SPELL_IGNITEMANA 19659 +#define SPELL_LIVINGBOMB 20475 +#define SPELL_ARMAGEDDOM 20479 + +struct boss_baron_geddonAI : public ScriptedAI +{ + boss_baron_geddonAI(Creature *c) : ScriptedAI(c) {} + + uint32 Inferno_Timer; + uint32 IgniteMana_Timer; + uint32 LivingBomb_Timer; + + void Reset() + { + Inferno_Timer = 45000; //These times are probably wrong + IgniteMana_Timer = 30000; + LivingBomb_Timer = 35000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <2% hp cast Armageddom + if (me->GetHealth()*100 / me->GetMaxHealth() <= 2) + { + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_ARMAGEDDOM); + DoScriptText(EMOTE_SERVICE, me); + return; + } + + //Inferno_Timer + if (Inferno_Timer <= diff) + { + DoCast(me, SPELL_INFERNO); + Inferno_Timer = 45000; + } else Inferno_Timer -= diff; + + //IgniteMana_Timer + if (IgniteMana_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_IGNITEMANA); + + IgniteMana_Timer = 30000; + } else IgniteMana_Timer -= diff; + + //LivingBomb_Timer + if (LivingBomb_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LIVINGBOMB); + + LivingBomb_Timer = 35000; + } else LivingBomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_baron_geddon(Creature* pCreature) +{ + return new boss_baron_geddonAI (pCreature); +} + +void AddSC_boss_baron_geddon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_baron_geddon"; + newscript->GetAI = &GetAI_boss_baron_geddon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp new file mode 100644 index 00000000000..75891cf8c43 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp @@ -0,0 +1,143 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Garr +SD%Complete: 50 +SDComment: Adds NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +// Garr spells +#define SPELL_ANTIMAGICPULSE 19492 +#define SPELL_MAGMASHACKLES 19496 +#define SPELL_ENRAGE 19516 //Stacking enrage (stacks to 10 times) + +//Add spells +#define SPELL_ERUPTION 19497 +#define SPELL_IMMOLATE 20294 + +struct boss_garrAI : public ScriptedAI +{ + boss_garrAI(Creature *c) : ScriptedAI(c) {} + + uint32 AntiMagicPulse_Timer; + uint32 MagmaShackles_Timer; + uint32 CheckAdds_Timer; + uint64 Add[8]; + bool Enraged[8]; + + void Reset() + { + AntiMagicPulse_Timer = 25000; //These times are probably wrong + MagmaShackles_Timer = 15000; + CheckAdds_Timer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //AntiMagicPulse_Timer + if (AntiMagicPulse_Timer <= diff) + { + DoCast(me, SPELL_ANTIMAGICPULSE); + AntiMagicPulse_Timer = 10000 + rand()%5000; + } else AntiMagicPulse_Timer -= diff; + + //MagmaShackles_Timer + if (MagmaShackles_Timer <= diff) + { + DoCast(me, SPELL_MAGMASHACKLES); + MagmaShackles_Timer = 8000 + rand()%4000; + } else MagmaShackles_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_fireswornAI : public ScriptedAI +{ + mob_fireswornAI(Creature *c) : ScriptedAI(c) {} + + uint32 Immolate_Timer; + + void Reset() + { + Immolate_Timer = 4000; //These times are probably wrong + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_IMMOLATE); + + Immolate_Timer = urand(5000,10000); + } else Immolate_Timer -= diff; + + //Cast Erruption and let them die + if (me->GetHealth() <= me->GetMaxHealth() * 0.10) + { + DoCast(me->getVictim(), SPELL_ERUPTION); + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_garr(Creature* pCreature) +{ + return new boss_garrAI (pCreature); +} + +CreatureAI* GetAI_mob_firesworn(Creature* pCreature) +{ + return new mob_fireswornAI (pCreature); +} + +void AddSC_boss_garr() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_garr"; + newscript->GetAI = &GetAI_boss_garr; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_firesworn"; + newscript->GetAI = &GetAI_mob_firesworn; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp new file mode 100644 index 00000000000..9ebe69c0c4e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gehennas +SD%Complete: 90 +SDComment: Adds MC NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWBOLT 19728 +#define SPELL_RAINOFFIRE 19717 +#define SPELL_GEHENNASCURSE 19716 + +struct boss_gehennasAI : public ScriptedAI +{ + boss_gehennasAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowBolt_Timer; + uint32 RainOfFire_Timer; + uint32 GehennasCurse_Timer; + + void Reset() + { + ShadowBolt_Timer = 6000; + RainOfFire_Timer = 10000; + GehennasCurse_Timer = 12000; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_SHADOWBOLT); + + ShadowBolt_Timer = 7000; + } else ShadowBolt_Timer -= diff; + + //RainOfFire_Timer + if (RainOfFire_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_RAINOFFIRE); + + RainOfFire_Timer = urand(4000,12000); + } else RainOfFire_Timer -= diff; + + //GehennasCurse_Timer + if (GehennasCurse_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GEHENNASCURSE); + GehennasCurse_Timer = urand(22000,30000); + } else GehennasCurse_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gehennas(Creature* pCreature) +{ + return new boss_gehennasAI (pCreature); +} + +void AddSC_boss_gehennas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gehennas"; + newscript->GetAI = &GetAI_boss_gehennas; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp new file mode 100644 index 00000000000..2aba378d399 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp @@ -0,0 +1,198 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Golemagg +SD%Complete: 90 +SDComment: Timers need to be confirmed, Golemagg's Trust need to be checked +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" +#include "molten_core.h" + +enum eEnums +{ + SPELL_MAGMASPLASH = 13879, + SPELL_PYROBLAST = 20228, + SPELL_EARTHQUAKE = 19798, + SPELL_ENRAGE = 19953, + SPELL_GOLEMAGG_TRUST = 20553, + + // Core Rager + EMOTE_LOWHP = -1409002, + SPELL_MANGLE = 19820 +}; + +struct boss_golemaggAI : public ScriptedAI +{ + boss_golemaggAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiPyroblastTimer; + uint32 m_uiEarthquakeTimer; + uint32 m_uiBuffTimer; + bool m_bEnraged; + + void Reset() + { + m_uiPyroblastTimer = 7*IN_MILISECONDS; // These timers are probably wrong + m_uiEarthquakeTimer = 3*IN_MILISECONDS; + m_uiBuffTimer = 2.5*IN_MILISECONDS; + m_bEnraged = false; + + DoCast(me, SPELL_MAGMASPLASH, true); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance) + m_pInstance->SetData(DATA_GOLEMAGG_DEATH, 0); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //Pyroblast + if (m_uiPyroblastTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_PYROBLAST); + + m_uiPyroblastTimer = 7*IN_MILISECONDS; + } + else + m_uiPyroblastTimer -= uiDiff; + + // Enrage + if (!m_bEnraged && me->GetHealth()*100 < me->GetMaxHealth()*10) + { + DoCast(me, SPELL_ENRAGE); + m_bEnraged = true; + } + + // Earthquake + if (m_bEnraged) + { + if (m_uiEarthquakeTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_EARTHQUAKE); + m_uiEarthquakeTimer = 3*IN_MILISECONDS; + } + else + m_uiEarthquakeTimer -= uiDiff; + } + + /* + // Golemagg's Trust + if (m_uiBuffTimer <= uidiff) + { + DoCast(me, SPELL_GOLEMAGG_TRUST); + m_uiBuffTimer = 2.5*IN_MILISECONDS; + } + else + m_uiBuffTimer -= uiDiff; + */ + + DoMeleeAttackIfReady(); + } +}; + +struct mob_core_ragerAI : public ScriptedAI +{ + mob_core_ragerAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiMangleTimer; + + void Reset() + { + m_uiMangleTimer = 7*IN_MILISECONDS; // These times are probably wrong + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) + { + if (me->GetHealth()*100 < me->GetMaxHealth()*50) + { + if (m_pInstance) + { + if (Creature* pGolemagg = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_GOLEMAGG))) + { + if (pGolemagg->isAlive()) + { + DoScriptText(EMOTE_LOWHP, me); + me->SetHealth(me->GetMaxHealth()); + } + else + uiDamage = me->GetHealth(); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + // Mangle + if (m_uiMangleTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MANGLE); + m_uiMangleTimer = 10*IN_MILISECONDS; + } + else + m_uiMangleTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_golemagg(Creature* pCreature) +{ + return new boss_golemaggAI (pCreature); +} + +CreatureAI* GetAI_mob_core_rager(Creature* pCreature) +{ + return new mob_core_ragerAI (pCreature); +} + +void AddSC_boss_golemagg() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_golemagg"; + newscript->GetAI = &GetAI_boss_golemagg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_core_rager"; + newscript->GetAI = &GetAI_mob_core_rager; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp new file mode 100644 index 00000000000..50601f04147 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lucifron +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_IMPENDINGDOOM 19702 +#define SPELL_LUCIFRONCURSE 19703 +#define SPELL_SHADOWSHOCK 20603 + +struct boss_lucifronAI : public ScriptedAI +{ + boss_lucifronAI(Creature *c) : ScriptedAI(c) {} + + uint32 ImpendingDoom_Timer; + uint32 LucifronCurse_Timer; + uint32 ShadowShock_Timer; + + void Reset() + { + ImpendingDoom_Timer = 10000; //Initial cast after 10 seconds so the debuffs alternate + LucifronCurse_Timer = 20000; //Initial cast after 20 seconds + ShadowShock_Timer = 6000; //6 seconds + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Impending doom timer + if (ImpendingDoom_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_IMPENDINGDOOM); + ImpendingDoom_Timer = 20000; + } else ImpendingDoom_Timer -= diff; + + //Lucifron's curse timer + if (LucifronCurse_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LUCIFRONCURSE); + LucifronCurse_Timer = 15000; + } else LucifronCurse_Timer -= diff; + + //Shadowshock + if (ShadowShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWSHOCK); + ShadowShock_Timer = 6000; + } else ShadowShock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lucifron(Creature* pCreature) +{ + return new boss_lucifronAI (pCreature); +} + +void AddSC_boss_lucifron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lucifron"; + newscript->GetAI = &GetAI_boss_lucifron; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp new file mode 100644 index 00000000000..f612003b076 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp @@ -0,0 +1,100 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Magmadar +SD%Complete: 75 +SDComment: Conflag on ground nyi, fear causes issues without VMAPs +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_FRENZY -1409001 + +#define SPELL_FRENZY 19451 +#define SPELL_MAGMASPIT 19449 //This is actually a buff he gives himself +#define SPELL_PANIC 19408 +#define SPELL_LAVABOMB 19411 //This calls a dummy server side effect that isn't implemented yet +#define SPELL_LAVABOMB_ALT 19428 //This is the spell that the lava bomb casts + +struct boss_magmadarAI : public ScriptedAI +{ + boss_magmadarAI(Creature *c) : ScriptedAI(c) {} + + uint32 Frenzy_Timer; + uint32 Panic_Timer; + uint32 Lavabomb_Timer; + + void Reset() + { + Frenzy_Timer = 30000; + Panic_Timer = 20000; + Lavabomb_Timer = 12000; + + DoCast(me, SPELL_MAGMASPIT, true); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Frenzy_Timer + if (Frenzy_Timer <= diff) + { + DoScriptText(EMOTE_FRENZY, me); + DoCast(me, SPELL_FRENZY); + Frenzy_Timer = 15000; + } else Frenzy_Timer -= diff; + + //Panic_Timer + if (Panic_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PANIC); + Panic_Timer = 35000; + } else Panic_Timer -= diff; + + //Lavabomb_Timer + if (Lavabomb_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LAVABOMB_ALT); + + Lavabomb_Timer = 12000; + } else Lavabomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_magmadar(Creature* pCreature) +{ + return new boss_magmadarAI (pCreature); +} + +void AddSC_boss_magmadar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magmadar"; + newscript->GetAI = &GetAI_boss_magmadar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp new file mode 100644 index 00000000000..11ae70befcf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp @@ -0,0 +1,134 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Majordomo_Executus +SD%Complete: 30 +SDComment: Correct spawning and Event NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1409003 +#define SAY_SPAWN -1409004 +#define SAY_SLAY -1409005 +#define SAY_SPECIAL -1409006 +#define SAY_DEFEAT -1409007 + +#define SAY_SUMMON_MAJ -1409008 +#define SAY_ARRIVAL1_RAG -1409009 +#define SAY_ARRIVAL2_MAJ -1409010 +#define SAY_ARRIVAL3_RAG -1409011 +#define SAY_ARRIVAL5_RAG -1409012 + +#define SPAWN_RAG_X 838.51 +#define SPAWN_RAG_Y -829.84 +#define SPAWN_RAG_Z -232.00 +#define SPAWN_RAG_O 1.70 + +#define SPELL_MAGIC_REFLECTION 20619 +#define SPELL_DAMAGE_REFLECTION 21075 + +#define SPELL_BLASTWAVE 20229 +#define SPELL_AEGIS 20620 //This is self casted whenever we are below 50% +#define SPELL_TELEPORT 20618 +#define SPELL_SUMMON_RAGNAROS 19774 + +#define ENTRY_FLAMEWALKER_HEALER 11663 +#define ENTRY_FLAMEWALKER_ELITE 11664 + +struct boss_majordomoAI : public ScriptedAI +{ + boss_majordomoAI(Creature *c) : ScriptedAI(c) {} + + uint32 MagicReflection_Timer; + uint32 DamageReflection_Timer; + uint32 Blastwave_Timer; + + void Reset() + { + MagicReflection_Timer = 30000; //Damage reflection first so we alternate + DamageReflection_Timer = 15000; + Blastwave_Timer = 10000; + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%5) + return; + + DoScriptText(SAY_SLAY, me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Cast Ageis if less than 50% hp + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + DoCast(me, SPELL_AEGIS); + } + + //MagicReflection_Timer + // if (MagicReflection_Timer <= diff) + // { + // DoCast(me, SPELL_MAGICREFLECTION); + + //60 seconds until we should cast this agian + // MagicReflection_Timer = 30000; + // } else MagicReflection_Timer -= diff; + + //DamageReflection_Timer + // if (DamageReflection_Timer <= diff) + // { + // DoCast(me, SPELL_DAMAGEREFLECTION); + + //60 seconds until we should cast this agian + // DamageReflection_Timer = 30000; + // } else DamageReflection_Timer -= diff; + + //Blastwave_Timer + if (Blastwave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLASTWAVE); + Blastwave_Timer = 10000; + } else Blastwave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_majordomo(Creature* pCreature) +{ + return new boss_majordomoAI (pCreature); +} + +void AddSC_boss_majordomo() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_majordomo"; + newscript->GetAI = &GetAI_boss_majordomo; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp new file mode 100644 index 00000000000..71c0b40de3f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp @@ -0,0 +1,297 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ragnaros +SD%Complete: 75 +SDComment: Intro Dialog and event NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_REINFORCEMENTS1 -1409013 +#define SAY_REINFORCEMENTS2 -1409014 +#define SAY_HAND -1409015 +#define SAY_WRATH -1409016 +#define SAY_KILL -1409017 +#define SAY_MAGMABURST -1409018 + +#define SPELL_HANDOFRAGNAROS 19780 +#define SPELL_WRATHOFRAGNAROS 20566 +#define SPELL_LAVABURST 21158 + +#define SPELL_MAGMABURST 20565 //Ranged attack + +#define SPELL_SONSOFFLAME_DUMMY 21108 //Server side effect +#define SPELL_RAGSUBMERGE 21107 //Stealth aura +#define SPELL_RAGEMERGE 20568 +#define SPELL_MELTWEAPON 21388 +#define SPELL_ELEMENTALFIRE 20564 +#define SPELL_ERRUPTION 17731 + +#define ADD_1X 848.740356 +#define ADD_1Y -816.103455 +#define ADD_1Z -229.74327 +#define ADD_1O 2.615287 + +#define ADD_2X 852.560791 +#define ADD_2Y -849.861511 +#define ADD_2Z -228.560974 +#define ADD_2O 2.836073 + +#define ADD_3X 808.710632 +#define ADD_3Y -852.845764 +#define ADD_3Z -227.914963 +#define ADD_3O 0.964207 + +#define ADD_4X 786.597107 +#define ADD_4Y -821.132874 +#define ADD_4Z -226.350128 +#define ADD_4O 0.949377 + +#define ADD_5X 796.219116 +#define ADD_5Y -800.948059 +#define ADD_5Z -226.010361 +#define ADD_5O 0.560603 + +#define ADD_6X 821.602539 +#define ADD_6Y -782.744109 +#define ADD_6Z -226.023575 +#define ADD_6O 6.157440 + +#define ADD_7X 844.924744 +#define ADD_7Y -769.453735 +#define ADD_7Z -225.521698 +#define ADD_7O 4.4539958 + +#define ADD_8X 839.823364 +#define ADD_8Y -810.869385 +#define ADD_8Z -229.683182 +#define ADD_8O 4.693108 + +struct boss_ragnarosAI : public ScriptedAI +{ + boss_ragnarosAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 WrathOfRagnaros_Timer; + uint32 HandOfRagnaros_Timer; + uint32 LavaBurst_Timer; + uint32 MagmaBurst_Timer; + uint32 ElementalFire_Timer; + uint32 Erruption_Timer; + uint32 Submerge_Timer; + uint32 Attack_Timer; + + bool HasYelledMagmaBurst; + bool HasSubmergedOnce; + bool WasBanished; + bool HasAura; + + void Reset() + { + WrathOfRagnaros_Timer = 30000; + HandOfRagnaros_Timer = 25000; + LavaBurst_Timer = 10000; + MagmaBurst_Timer = 2000; + Erruption_Timer = 15000; + ElementalFire_Timer = 3000; + Submerge_Timer = 180000; + Attack_Timer = 90000; + HasYelledMagmaBurst = false; + HasSubmergedOnce = false; + WasBanished = false; + + DoCast(me, SPELL_MELTWEAPON, true); + HasAura = true; + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%5) + return; + + DoScriptText(SAY_KILL, me); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (WasBanished && Attack_Timer <= diff) + { + //Become unbanished again + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_RAGEMERGE); + WasBanished = false; + } else if (WasBanished) + { + Attack_Timer -= diff; + //Do nothing while banished + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //WrathOfRagnaros_Timer + if (WrathOfRagnaros_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WRATHOFRAGNAROS); + + if (urand(0,1)) + DoScriptText(SAY_WRATH, me); + + WrathOfRagnaros_Timer = 30000; + } else WrathOfRagnaros_Timer -= diff; + + //HandOfRagnaros_Timer + if (HandOfRagnaros_Timer <= diff) + { + DoCast(me, SPELL_HANDOFRAGNAROS); + + if (urand(0,1)) + DoScriptText(SAY_HAND, me); + + HandOfRagnaros_Timer = 25000; + } else HandOfRagnaros_Timer -= diff; + + //LavaBurst_Timer + if (LavaBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LAVABURST); + LavaBurst_Timer = 10000; + } else LavaBurst_Timer -= diff; + + //Erruption_Timer + if (LavaBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ERRUPTION); + Erruption_Timer = urand(20000,45000); + } else Erruption_Timer -= diff; + + //ElementalFire_Timer + if (ElementalFire_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ELEMENTALFIRE); + ElementalFire_Timer = urand(10000,14000); + } else ElementalFire_Timer -= diff; + + //Submerge_Timer + if (!WasBanished && Submerge_Timer <= diff) + { + //Creature spawning and ragnaros becomming unattackable + //is not very well supported in the core + //so added normaly spawning and banish workaround and attack again after 90 secs. + + me->InterruptNonMeleeSpells(false); + //Root self + DoCast(me, 23973); + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + + if (!HasSubmergedOnce) + { + DoScriptText(SAY_REINFORCEMENTS1, me); + + // summon 10 elementals + for (uint8 i = 0; i < 9; ++i) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (Creature* pSummoned = me->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000)) + pSummoned->AI()->AttackStart(pTarget); + } + } + + HasSubmergedOnce = true; + WasBanished = true; + DoCast(me, SPELL_RAGSUBMERGE); + Attack_Timer = 90000; + + } + else + { + DoScriptText(SAY_REINFORCEMENTS2, me); + + for (uint8 i = 0; i < 9; ++i) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (Creature* pSummoned = me->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000)) + pSummoned->AI()->AttackStart(pTarget); + } + } + + WasBanished = true; + DoCast(me, SPELL_RAGSUBMERGE); + Attack_Timer = 90000; + } + + Submerge_Timer = 180000; + } else Submerge_Timer -= diff; + + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + //Make sure our attack is ready and we arn't currently casting + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + else + { + //MagmaBurst_Timer + if (MagmaBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MAGMABURST); + + if (!HasYelledMagmaBurst) + { + //Say our dialog + DoScriptText(SAY_MAGMABURST, me); + HasYelledMagmaBurst = true; + } + + MagmaBurst_Timer = 2500; + } else MagmaBurst_Timer -= diff; + } + } +}; +CreatureAI* GetAI_boss_ragnaros(Creature* pCreature) +{ + return new boss_ragnarosAI (pCreature); +} + +void AddSC_boss_ragnaros() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ragnaros"; + newscript->GetAI = &GetAI_boss_ragnaros; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp new file mode 100644 index 00000000000..4b0774cdc54 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp @@ -0,0 +1,121 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shazzrah +SD%Complete: 75 +SDComment: Teleport NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_ARCANEEXPLOSION 19712 +#define SPELL_SHAZZRAHCURSE 19713 +#define SPELL_DEADENMAGIC 19714 +#define SPELL_COUNTERSPELL 19715 + +struct boss_shazzrahAI : public ScriptedAI +{ + boss_shazzrahAI(Creature *c) : ScriptedAI(c) {} + + uint32 ArcaneExplosion_Timer; + uint32 ShazzrahCurse_Timer; + uint32 DeadenMagic_Timer; + uint32 Countspell_Timer; + uint32 Blink_Timer; + + void Reset() + { + ArcaneExplosion_Timer = 6000; //These times are probably wrong + ShazzrahCurse_Timer = 10000; + DeadenMagic_Timer = 24000; + Countspell_Timer = 15000; + Blink_Timer = 30000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANEEXPLOSION); + ArcaneExplosion_Timer = 5000 + rand()%4000; + } else ArcaneExplosion_Timer -= diff; + + //ShazzrahCurse_Timer + if (ShazzrahCurse_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_SHAZZRAHCURSE); + + ShazzrahCurse_Timer = 25000 + rand()%5000; + } else ShazzrahCurse_Timer -= diff; + + //DeadenMagic_Timer + if (DeadenMagic_Timer <= diff) + { + DoCast(me, SPELL_DEADENMAGIC); + DeadenMagic_Timer = 35000; + } else DeadenMagic_Timer -= diff; + + //Countspell_Timer + if (Countspell_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_COUNTERSPELL); + Countspell_Timer = 16000 + rand()%4000; + } else Countspell_Timer -= diff; + + //Blink_Timer + if (Blink_Timer <= diff) + { + // Teleporting him to a random gamer and casting Arcane Explosion after that. + // Blink is not working cause of LoS System we need to do this hardcoded. + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0, 100, true)) + { + DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); + DoCast(pTarget, SPELL_ARCANEEXPLOSION); + DoResetThreat(); + } + + Blink_Timer = 45000; + } else Blink_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_shazzrah(Creature* pCreature) +{ + return new boss_shazzrahAI (pCreature); +} + +void AddSC_boss_shazzrah() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shazzrah"; + newscript->GetAI = &GetAI_boss_shazzrah; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp new file mode 100644 index 00000000000..83288fe003b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Sulfuron_Harbringer +SD%Complete: 80 +SDComment: Adds NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" +#include "molten_core.h" + +#define SPELL_DARKSTRIKE 19777 +#define SPELL_DEMORALIZINGSHOUT 19778 +#define SPELL_INSPIRE 19779 +#define SPELL_KNOCKDOWN 19780 +#define SPELL_FLAMESPEAR 19781 + +//Adds Spells +#define SPELL_HEAL 19775 +#define SPELL_SHADOWWORDPAIN 19776 +#define SPELL_IMMOLATE 20294 + +struct boss_sulfuronAI : public ScriptedAI +{ + boss_sulfuronAI(Creature *c) : ScriptedAI(c) {} + + uint32 Darkstrike_Timer; + uint32 DemoralizingShout_Timer; + uint32 Inspire_Timer; + uint32 Knockdown_Timer; + uint32 Flamespear_Timer; + + void Reset() + { + Darkstrike_Timer=10000; //These times are probably wrong + DemoralizingShout_Timer = 15000; + Inspire_Timer = 13000; + Knockdown_Timer = 6000; + Flamespear_Timer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //DemoralizingShout_Timer + if (DemoralizingShout_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DEMORALIZINGSHOUT); + DemoralizingShout_Timer = 15000 + rand()%5000; + } else DemoralizingShout_Timer -= diff; + + //Inspire_Timer + if (Inspire_Timer <= diff) + { + Creature *pTarget = NULL; + std::list pList = DoFindFriendlyMissingBuff(45.0f,SPELL_INSPIRE); + if (!pList.empty()) + { + std::list::const_iterator i = pList.begin(); + advance(i, (rand()%pList.size())); + pTarget = (*i); + } + + if (pTarget) + DoCast(pTarget, SPELL_INSPIRE); + + DoCast(me, SPELL_INSPIRE); + + Inspire_Timer = 20000 + rand()%6000; + } else Inspire_Timer -= diff; + + //Knockdown_Timer + if (Knockdown_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + Knockdown_Timer = 12000 + rand()%3000; + } else Knockdown_Timer -= diff; + + //Flamespear_Timer + if (Flamespear_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_FLAMESPEAR); + + Flamespear_Timer = 12000 + rand()%4000; + } else Flamespear_Timer -= diff; + + //DarkStrike_Timer + if (Darkstrike_Timer <= diff) + { + DoCast(me, SPELL_DARKSTRIKE); + Darkstrike_Timer = 15000 + rand()%3000; + } else Darkstrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_flamewaker_priestAI : public ScriptedAI +{ + mob_flamewaker_priestAI(Creature *c) : ScriptedAI(c) {} + + uint32 Heal_Timer; + uint32 ShadowWordPain_Timer; + uint32 Immolate_Timer; + + void Reset() + { + Heal_Timer = 15000+rand()%15000; + ShadowWordPain_Timer = 2000; + Immolate_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Casting Heal to Sulfuron or other Guards. + if (Heal_Timer <= diff) + { + Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1); + if (!pUnit) + return; + + DoCast(pUnit, SPELL_HEAL); + + Heal_Timer = 15000+rand()%5000; + } else Heal_Timer -= diff; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_SHADOWWORDPAIN); + + ShadowWordPain_Timer = 18000+rand()%8000; + } else ShadowWordPain_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); + + Immolate_Timer = 15000+rand()%10000; + } else Immolate_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_sulfuron(Creature* pCreature) +{ + return new boss_sulfuronAI (pCreature); +} + +CreatureAI* GetAI_mob_flamewaker_priest(Creature* pCreature) +{ + return new mob_flamewaker_priestAI (pCreature); +} + +void AddSC_boss_sulfuron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sulfuron"; + newscript->GetAI = &GetAI_boss_sulfuron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flamewaker_priest"; + newscript->GetAI = &GetAI_mob_flamewaker_priest; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp b/src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp new file mode 100644 index 00000000000..eb79c234134 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp @@ -0,0 +1,266 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Molten_Core +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" +#include "molten_core.h" + +#define MAX_ENCOUNTER 9 + +#define ID_LUCIFRON 12118 +#define ID_MAGMADAR 11982 +#define ID_GEHENNAS 12259 +#define ID_GARR 12057 +#define ID_GEDDON 12056 +#define ID_SHAZZRAH 12264 +#define ID_GOLEMAGG 11988 +#define ID_SULFURON 12098 +#define ID_DOMO 12018 +#define ID_RAGNAROS 11502 +#define ID_FLAMEWAKERPRIEST 11662 + +struct instance_molten_core : public ScriptedInstance +{ + instance_molten_core(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 Lucifron, Magmadar, Gehennas, Garr, Geddon, Shazzrah, Sulfuron, Golemagg, Domo, Ragnaros, FlamewakerPriest; + uint64 RuneKoro, RuneZeth, RuneMazj, RuneTheri, RuneBlaz, RuneKress, RuneMohn, m_uiFirelordCacheGUID; + + //If all Bosses are dead. + bool IsBossDied[9]; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Lucifron = 0; + Magmadar = 0; + Gehennas = 0; + Garr = 0; + Geddon = 0; + Shazzrah = 0; + Sulfuron = 0; + Golemagg = 0; + Domo = 0; + Ragnaros = 0; + FlamewakerPriest = 0; + + RuneKoro = 0; + RuneZeth = 0; + RuneMazj = 0; + RuneTheri = 0; + RuneBlaz = 0; + RuneKress = 0; + RuneMohn = 0; + + m_uiFirelordCacheGUID = 0; + + IsBossDied[0] = false; + IsBossDied[1] = false; + IsBossDied[2] = false; + IsBossDied[3] = false; + IsBossDied[4] = false; + IsBossDied[5] = false; + IsBossDied[6] = false; + + IsBossDied[7] = false; + IsBossDied[8] = false; + } + + bool IsEncounterInProgress() const + { + return false; + }; + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 176951: //Sulfuron + RuneKoro = pGo->GetGUID(); + break; + case 176952: //Geddon + RuneZeth = pGo->GetGUID(); + break; + case 176953: //Shazzrah + RuneMazj = pGo->GetGUID(); + break; + case 176954: //Golemagg + RuneTheri = pGo->GetGUID(); + break; + case 176955: //Garr + RuneBlaz = pGo->GetGUID(); + break; + case 176956: //Magmadar + RuneKress = pGo->GetGUID(); + break; + case 176957: //Gehennas + RuneMohn = pGo->GetGUID(); + break; + case 179703: + m_uiFirelordCacheGUID = pGo->GetGUID(); //when majordomo event == DONE DoRespawnGameObject(m_uiFirelordCacheGUID,); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case ID_LUCIFRON: + Lucifron = pCreature->GetGUID(); + break; + + case ID_MAGMADAR: + Magmadar = pCreature->GetGUID(); + break; + + case ID_GEHENNAS: + Gehennas = pCreature->GetGUID(); + break; + + case ID_GARR: + Garr = pCreature->GetGUID(); + break; + + case ID_GEDDON: + Geddon = pCreature->GetGUID(); + break; + + case ID_SHAZZRAH: + Shazzrah = pCreature->GetGUID(); + break; + + case ID_SULFURON: + Sulfuron = pCreature->GetGUID(); + break; + + case ID_GOLEMAGG: + Golemagg = pCreature->GetGUID(); + break; + + case ID_DOMO: + Domo = pCreature->GetGUID(); + break; + + case ID_RAGNAROS: + Ragnaros = pCreature->GetGUID(); + break; + + case ID_FLAMEWAKERPRIEST: + FlamewakerPriest = pCreature->GetGUID(); + break; + } + } + + uint64 GetData64 (uint32 identifier) + { + switch(identifier) + { + case DATA_SULFURON: + return Sulfuron; + case DATA_GOLEMAGG: + return Golemagg; + + case DATA_FLAMEWAKERPRIEST: + return FlamewakerPriest; + } + + return 0; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_LUCIFRONISDEAD: + if (IsBossDied[0]) + return 1; + break; + + case DATA_MAGMADARISDEAD: + if (IsBossDied[1]) + return 1; + break; + + case DATA_GEHENNASISDEAD: + if (IsBossDied[2]) + return 1; + break; + + case DATA_GARRISDEAD: + if (IsBossDied[3]) + return 1; + break; + + case DATA_GEDDONISDEAD: + if (IsBossDied[4]) + return 1; + break; + + case DATA_SHAZZRAHISDEAD: + if (IsBossDied[5]) + return 1; + break; + + case DATA_SULFURONISDEAD: + if (IsBossDied[6]) + return 1; + break; + + case DATA_GOLEMAGGISDEAD: + if (IsBossDied[7]) + return 1; + break; + + case DATA_MAJORDOMOISDEAD: + if (IsBossDied[8]) + return 1; + break; + } + + return 0; + } + + void SetData(uint32 type, uint32 /*data*/) + { + if (type == DATA_GOLEMAGG_DEATH) + IsBossDied[7] = true; + } +}; + +InstanceData* GetInstance_instance_molten_core(Map* pMap) +{ + return new instance_molten_core (pMap); +} + +void AddSC_instance_molten_core() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_molten_core"; + newscript->GetInstanceData = &GetInstance_instance_molten_core; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp b/src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp new file mode 100644 index 00000000000..f8fe5bf1477 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp @@ -0,0 +1,81 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Molten_Core +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +/* ContentData +mob_ancient_core_hound +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedSimpleAI.h" + +#define SPELL_CONE_OF_FIRE 19630 +#define SPELL_BITE 19771 + +//Random Debuff (each hound has only one of these) +#define SPELL_GROUND_STOMP 19364 +#define SPELL_ANCIENT_DREAD 19365 +#define SPELL_CAUTERIZING_FLAMES 19366 +#define SPELL_WITHERING_HEAT 19367 +#define SPELL_ANCIENT_DESPAIR 19369 +#define SPELL_ANCIENT_HYSTERIA 19372 + +CreatureAI* GetAI_mob_ancient_core_hound(Creature* pCreature) +{ + SimpleAI *ai = new SimpleAI(pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_CONE_OF_FIRE; + ai->Spell[0].Cooldown = 7000; + ai->Spell[0].First_Cast = 10000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + uint32 RandDebuff = RAND(SPELL_GROUND_STOMP,SPELL_ANCIENT_DREAD,SPELL_CAUTERIZING_FLAMES, + SPELL_WITHERING_HEAT,SPELL_ANCIENT_DESPAIR,SPELL_ANCIENT_HYSTERIA); + + ai->Spell[1].Enabled = true; + ai->Spell[1].Spell_Id = RandDebuff; + ai->Spell[1].Cooldown = 24000; + ai->Spell[1].First_Cast = 15000; + ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->Spell[2].Enabled = true; + ai->Spell[2].Spell_Id = SPELL_BITE; + ai->Spell[2].Cooldown = 6000; + ai->Spell[2].First_Cast = 4000; + ai->Spell[2].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->EnterEvadeMode(); + + return ai; +} + +void AddSC_molten_core() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_ancient_core_hound"; + newscript->GetAI = &GetAI_mob_ancient_core_hound; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/molten_core/molten_core.h b/src/server/scripts/EasternKingdoms/molten_core/molten_core.h new file mode 100644 index 00000000000..5874d8b9408 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/molten_core/molten_core.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MOLTEN_CORE_H +#define DEF_MOLTEN_CORE_H + +#define DATA_FLAMEWAKERPRIEST 1 +#define DATA_GARRISDEAD 2 +#define DATA_GEDDONISDEAD 3 +#define DATA_GEHENNASISDEAD 4 +#define DATA_GOLEMAGGISDEAD 5 +#define DATA_GOLEMAGG_DEATH 6 +#define DATA_LUCIFRONISDEAD 7 +#define DATA_MAGMADARISDEAD 8 +#define DATA_MAJORDOMOISDEAD 9 +#define DATA_SHAZZRAHISDEAD 10 +#define DATA_SULFURON 11 +#define DATA_SULFURONISDEAD 12 +#define DATA_GOLEMAGG 13 +#endif + diff --git a/src/server/scripts/EasternKingdoms/redridge_mountains.cpp b/src/server/scripts/EasternKingdoms/redridge_mountains.cpp new file mode 100644 index 00000000000..2f0b5821e86 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/redridge_mountains.cpp @@ -0,0 +1,172 @@ +/* Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Redridge Mountains +SD%Complete: 100% +SDComment: Support for quest 219. +Script Data End */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +enum eCorporalKeeshan +{ + QUEST_MISSING_IN_ACTION = 219, + + SAY_CORPORAL_1 = -1000464, + SAY_CORPORAL_2 = -1000465, + SAY_CORPORAL_3 = -1000466, + SAY_CORPORAL_4 = -1000467, + SAY_CORPORAL_5 = -1000468, + + SPELL_MOCKING_BLOW = 21008, + SPELL_SHIELD_BASH = 11972, +}; + +struct npc_corporal_keeshanAI : public npc_escortAI +{ + npc_corporal_keeshanAI(Creature* pCreature) : npc_escortAI(pCreature) {} + + uint32 uiPhase; + uint32 uiTimer; + uint32 uiMockingBlowTimer; + uint32 uiShieldBashTimer; + + void Reset() + { + uiTimer = 0; + uiPhase = 0; + uiMockingBlowTimer = 5000; + uiShieldBashTimer = 8000; + } + + void WaypointReached(uint32 uiI) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + if (uiI >= 65 && me->GetUnitMovementFlags() == MOVEMENTFLAG_WALK_MODE) + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + switch(uiI) + { + case 39: + SetEscortPaused(true); + uiTimer = 2000; + uiPhase = 1; + break; + case 65: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 115: + pPlayer->AreaExploredOrEventHappens(QUEST_MISSING_IN_ACTION); + uiTimer = 2000; + uiPhase = 4; + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (HasEscortState(STATE_ESCORT_NONE)) + return; + + npc_escortAI::UpdateAI(uiDiff); + + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + me->SetStandState(UNIT_STAND_STATE_SIT); + uiTimer = 1000; + uiPhase = 2; + break; + case 2: + DoScriptText(SAY_CORPORAL_2,me); + uiTimer = 15000; + uiPhase = 3; + break; + case 3: + DoScriptText(SAY_CORPORAL_3,me); + me->SetStandState(UNIT_STAND_STATE_STAND); + SetEscortPaused(false); + uiTimer = 0; + uiPhase = 0; + break; + case 4: + DoScriptText(SAY_CORPORAL_4, me); + uiTimer = 2500; + uiPhase = 5; + case 5: + DoScriptText(SAY_CORPORAL_5, me); + uiTimer = 0; + uiPhase = 0; + } + } else uiTimer -= uiDiff; + } + + if (!UpdateVictim()) + return; + + if (uiMockingBlowTimer <= uiDiff) + { + DoCast(me->getVictim(),SPELL_MOCKING_BLOW); + uiMockingBlowTimer = 5000; + } else uiMockingBlowTimer -= uiDiff; + + if (uiShieldBashTimer <= uiDiff) + { + DoCast(me->getVictim(),SPELL_MOCKING_BLOW); + uiShieldBashTimer = 8000; + } else uiShieldBashTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +bool QuestAccept_npc_corporal_keeshan(Player* pPlayer, Creature* pCreature, Quest const *pQuest) +{ + if (pQuest->GetQuestId() == QUEST_MISSING_IN_ACTION) + { + CAST_AI(npc_corporal_keeshanAI,pCreature->AI())->Start(true, false, pPlayer->GetGUID(),pQuest); + DoScriptText(SAY_CORPORAL_1, pCreature); + } + + return false; +} + +CreatureAI* GetAI_npc_corporal_keeshan(Creature* pCreature) +{ + return new npc_corporal_keeshanAI(pCreature); +} + +void AddSC_redridge_mountains() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_corporal_keeshan"; + newscript->GetAI = &GetAI_npc_corporal_keeshan; + newscript->pQuestAccept = &QuestAccept_npc_corporal_keeshan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp new file mode 100644 index 00000000000..bdbf6b7c081 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp @@ -0,0 +1,1079 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "Vehicle.h" +#include "ObjectMgr.h" +#include "ScriptedEscortAI.h" + +/*###### +##Quest 12848 +######*/ + +#define GCD_CAST 1 + +enum eDeathKnightSpells +{ + SPELL_SOUL_PRISON_CHAIN_SELF = 54612, + SPELL_SOUL_PRISON_CHAIN = 54613, + SPELL_DK_INITIATE_VISUAL = 51519, + + SPELL_ICY_TOUCH = 52372, + SPELL_PLAGUE_STRIKE = 52373, + SPELL_BLOOD_STRIKE = 52374, + SPELL_DEATH_COIL = 52375 +}; + +#define EVENT_ICY_TOUCH 1 +#define EVENT_PLAGUE_STRIKE 2 +#define EVENT_BLOOD_STRIKE 3 +#define EVENT_DEATH_COIL 4 + +//used by 29519,29520,29565,29566,29567 but signed for 29519 +int32 say_event_start[8] = +{ + -1609000,-1609001,-1609002,-1609003, + -1609004,-1609005,-1609006,-1609007 +}; + +int32 say_event_attack[9] = +{ + -1609008,-1609009,-1609010,-1609011,-1609012, + -1609013,-1609014,-1609015,-1609016 +}; + +uint32 acherus_soul_prison[12] = +{ + 191577, + 191580, + 191581, + 191582, + 191583, + 191584, + 191585, + 191586, + 191587, + 191588, + 191589, + 191590 +}; + +uint32 acherus_unworthy_initiate[5] = +{ + 29519, + 29520, + 29565, + 29566, + 29567 +}; + +enum UnworthyInitiatePhase +{ + PHASE_CHAINED, + PHASE_TO_EQUIP, + PHASE_EQUIPING, + PHASE_TO_ATTACK, + PHASE_ATTACKING, +}; + +struct npc_unworthy_initiateAI : public ScriptedAI +{ + npc_unworthy_initiateAI(Creature *c) : ScriptedAI(c) + { + me->SetReactState(REACT_PASSIVE); + if (!me->GetEquipmentId()) + if (const CreatureInfo *info = GetCreatureInfo(28406)) + if (info->equipmentId) + const_cast(me->GetCreatureInfo())->equipmentId = info->equipmentId; + } + + uint64 playerGUID; + UnworthyInitiatePhase phase; + uint32 wait_timer; + float anchorX, anchorY; + uint64 anchorGUID; + + EventMap events; + + void Reset() + { + anchorGUID = 0; + phase = PHASE_CHAINED; + events.Reset(); + me->setFaction(7); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); + me->LoadEquipment(0, true); + } + + void EnterCombat(Unit * /*who*/) + { + events.ScheduleEvent(EVENT_ICY_TOUCH, 1000, GCD_CAST); + events.ScheduleEvent(EVENT_PLAGUE_STRIKE, 3000, GCD_CAST); + events.ScheduleEvent(EVENT_BLOOD_STRIKE, 2000, GCD_CAST); + events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + { + wait_timer = 5000; + me->CastSpell(me, SPELL_DK_INITIATE_VISUAL, true); + + if (Player* starter = Unit::GetPlayer(playerGUID)) + DoScriptText(say_event_attack[rand()%9], me, starter); + + phase = PHASE_TO_ATTACK; + } + } + + void EventStart(Creature* anchor, Player *pTarget) + { + wait_timer = 5000; + phase = PHASE_TO_EQUIP; + + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN_SELF); + me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN); + + float z; + anchor->GetContactPoint(me, anchorX, anchorY, z, 1.0f); + + playerGUID = pTarget->GetGUID(); + DoScriptText(say_event_start[rand()%8], me, pTarget); + } + + void UpdateAI(const uint32 diff); +}; + +CreatureAI* GetAI_npc_unworthy_initiate(Creature* pCreature) +{ + return new npc_unworthy_initiateAI(pCreature); +} + +struct npc_unworthy_initiate_anchorAI : public PassiveAI +{ + npc_unworthy_initiate_anchorAI(Creature *c) : PassiveAI(c), prisonerGUID(0) {} + + uint64 prisonerGUID; + + void SetGUID(const uint64 &guid, int32 /*id*/) + { + if (!prisonerGUID) + prisonerGUID = guid; + } + + uint64 GetGUID(int32 /*id*/) { return prisonerGUID; } +}; + +void npc_unworthy_initiateAI::UpdateAI(const uint32 diff) +{ + switch(phase) + { + case PHASE_CHAINED: + if (!anchorGUID) + { + if (Creature *anchor = me->FindNearestCreature(29521, 30)) + { + anchor->AI()->SetGUID(me->GetGUID()); + anchor->CastSpell(me, SPELL_SOUL_PRISON_CHAIN, true); + anchorGUID = anchor->GetGUID(); + } + else + error_log("npc_unworthy_initiateAI: unable to find anchor!"); + + float dist = 99.0f; + GameObject *prison = NULL; + + for (uint8 i = 0; i < 12; ++i) + { + if (GameObject* temp_prison = me->FindNearestGameObject(acherus_soul_prison[i],30)) + { + if (me->IsWithinDist(temp_prison, dist, false)) + { + dist = me->GetDistance2d(temp_prison); + prison = temp_prison; + } + } + } + + if (prison) + prison->ResetDoorOrButton(); + else + error_log("npc_unworthy_initiateAI: unable to find prison!"); + } + return; + case PHASE_TO_EQUIP: + if (wait_timer) + { + if (wait_timer > diff) + wait_timer -= diff; + else + { + me->GetMotionMaster()->MovePoint(1, anchorX, anchorY, me->GetPositionZ()); + //debug_log("npc_unworthy_initiateAI: move to %f %f %f", anchorX, anchorY, me->GetPositionZ()); + phase = PHASE_EQUIPING; + wait_timer = 0; + } + } + return; + case PHASE_TO_ATTACK: + if (wait_timer) + { + if (wait_timer > diff) + wait_timer -= diff; + else + { + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + phase = PHASE_ATTACKING; + + if (Player *pTarget = Unit::GetPlayer(playerGUID)) + me->AI()->AttackStart(pTarget); + wait_timer = 0; + } + } + return; + case PHASE_ATTACKING: + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ICY_TOUCH: + DoCast(me->getVictim(), SPELL_ICY_TOUCH); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_ICY_TOUCH, 5000, GCD_CAST); + break; + case EVENT_PLAGUE_STRIKE: + DoCast(me->getVictim(), SPELL_PLAGUE_STRIKE); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(SPELL_PLAGUE_STRIKE, 5000, GCD_CAST); + break; + case EVENT_BLOOD_STRIKE: + DoCast(me->getVictim(), SPELL_BLOOD_STRIKE); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_BLOOD_STRIKE, 5000, GCD_CAST); + break; + case EVENT_DEATH_COIL: + DoCast(me->getVictim(), SPELL_DEATH_COIL); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); + break; + } + } + + DoMeleeAttackIfReady(); + } +} + +CreatureAI* GetAI_npc_unworthy_initiate_anchor(Creature* pCreature) +{ + return new npc_unworthy_initiate_anchorAI(pCreature); +} + +bool GOHello_go_acherus_soul_prison(Player* pPlayer, GameObject* pGo) +{ + if (Creature *anchor = pGo->FindNearestCreature(29521, 15)) + if (uint64 prisonerGUID = anchor->AI()->GetGUID()) + if (Creature* prisoner = Creature::GetCreature(*pPlayer, prisonerGUID)) + CAST_AI(npc_unworthy_initiateAI, prisoner->AI())->EventStart(anchor, pPlayer); + + return false; +} + +/*###### +## npc_death_knight_initiate +######*/ + +#define GOSSIP_ACCEPT_DUEL "I challenge you, death knight!" + +enum eDuelEnums +{ + SAY_DUEL_A = -1609080, + SAY_DUEL_B = -1609081, + SAY_DUEL_C = -1609082, + SAY_DUEL_D = -1609083, + SAY_DUEL_E = -1609084, + SAY_DUEL_F = -1609085, + SAY_DUEL_G = -1609086, + SAY_DUEL_H = -1609087, + SAY_DUEL_I = -1609088, + + SPELL_DUEL = 52996, + //SPELL_DUEL_TRIGGERED = 52990, + SPELL_DUEL_VICTORY = 52994, + SPELL_DUEL_FLAG = 52991, + + QUEST_DEATH_CHALLENGE = 12733, + FACTION_HOSTILE = 2068 +}; + +int32 m_auiRandomSay[] = +{ + SAY_DUEL_A, SAY_DUEL_B, SAY_DUEL_C, SAY_DUEL_D, SAY_DUEL_E, SAY_DUEL_F, SAY_DUEL_G, SAY_DUEL_H, SAY_DUEL_I +}; + +struct npc_death_knight_initiateAI : public CombatAI +{ + npc_death_knight_initiateAI(Creature* pCreature) : CombatAI(pCreature) + { + m_bIsDuelInProgress = false; + } + + bool lose; + uint64 m_uiDuelerGUID; + uint32 m_uiDuelTimer; + bool m_bIsDuelInProgress; + + void Reset() + { + lose = false; + me->RestoreFaction(); + CombatAI::Reset(); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); + + m_uiDuelerGUID = 0; + m_uiDuelTimer = 5000; + m_bIsDuelInProgress = false; + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if (!m_bIsDuelInProgress && pSpell->Id == SPELL_DUEL) + { + m_uiDuelerGUID = pCaster->GetGUID(); + m_bIsDuelInProgress = true; + } + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (m_bIsDuelInProgress && pDoneBy->IsControlledByPlayer()) + { + if (pDoneBy->GetGUID() != m_uiDuelerGUID && pDoneBy->GetOwnerGUID() != m_uiDuelerGUID) // other players cannot help + uiDamage = 0; + else if (uiDamage >= me->GetHealth()) + { + uiDamage = 0; + + if (!lose) + { + pDoneBy->RemoveGameObject(SPELL_DUEL_FLAG, true); + pDoneBy->AttackStop(); + me->CastSpell(pDoneBy, SPELL_DUEL_VICTORY, true); + lose = true; + me->CastSpell(me, 7267, true); + me->RestoreFaction(); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + { + if (m_bIsDuelInProgress) + { + if (m_uiDuelTimer <= uiDiff) + { + me->setFaction(FACTION_HOSTILE); + + if (Unit* pUnit = Unit::GetUnit(*me, m_uiDuelerGUID)) + AttackStart(pUnit); + } + else + m_uiDuelTimer -= uiDiff; + } + return; + } + + if (m_bIsDuelInProgress) + { + if (lose) + { + if (!me->HasAura(7267)) + EnterEvadeMode(); + return; + } + else if (me->getVictim()->GetTypeId() == TYPEID_PLAYER + && me->getVictim()->GetHealth() * 10 < me->getVictim()->GetMaxHealth()) + { + me->getVictim()->CastSpell(me->getVictim(), 7267, true); // beg + me->getVictim()->RemoveGameObject(SPELL_DUEL_FLAG, true); + EnterEvadeMode(); + return; + } + } + + // TODO: spells + + CombatAI::UpdateAI(uiDiff); + } +}; + +CreatureAI* GetAI_npc_death_knight_initiate(Creature* pCreature) +{ + return new npc_death_knight_initiateAI(pCreature); +} + +bool GossipHello_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_DEATH_CHALLENGE) == QUEST_STATUS_INCOMPLETE && pCreature->GetHealth() == pCreature->GetMaxHealth()) + { + if (pPlayer->GetHealth() * 10 < pPlayer->GetMaxHealth()) + return true; + + if (pPlayer->isInCombat() || pCreature->isInCombat()) + return true; + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ACCEPT_DUEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature),pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pPlayer->isInCombat() || pCreature->isInCombat()) + return true; + + if (npc_death_knight_initiateAI* pInitiateAI = CAST_AI(npc_death_knight_initiateAI, pCreature->AI())) + { + if (pInitiateAI->m_bIsDuelInProgress) + return true; + } + + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); + + int32 uiSayId = rand()% (sizeof(m_auiRandomSay)/sizeof(int32)); + DoScriptText(m_auiRandomSay[uiSayId], pCreature, pPlayer); + + pPlayer->CastSpell(pCreature, SPELL_DUEL, false); + pPlayer->CastSpell(pPlayer, SPELL_DUEL_FLAG, true); + } + return true; +} + +/*###### +## npc_dark_rider_of_acherus +######*/ + +#define DESPAWN_HORSE 52267 +#define SAY_DARK_RIDER "The realm of shadows awaits..." + +struct npc_dark_rider_of_acherusAI : public ScriptedAI +{ + npc_dark_rider_of_acherusAI(Creature *c) : ScriptedAI(c) {} + + uint32 PhaseTimer; + uint32 Phase; + bool Intro; + uint64 TargetGUID; + + void Reset() + { + PhaseTimer = 4000; + Phase = 0; + Intro = false; + TargetGUID = 0; + } + + void UpdateAI(const uint32 diff) + { + if (!Intro || !TargetGUID) + return; + + if (PhaseTimer <= diff) + { + switch(Phase) + { + case 0: + me->MonsterSay(SAY_DARK_RIDER, LANG_UNIVERSAL, 0); + PhaseTimer = 5000; + Phase = 1; + break; + case 1: + if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID)) + DoCast(pTarget, DESPAWN_HORSE, true); + PhaseTimer = 3000; + Phase = 2; + break; + case 2: + me->SetVisibility(VISIBILITY_OFF); + PhaseTimer = 2000; + Phase = 3; + break; + case 3: + me->ForcedDespawn(); + break; + default: + break; + } + } else PhaseTimer -= diff; + + } + + void InitDespawnHorse(Unit *who) + { + if (!who) + return; + + TargetGUID = who->GetGUID(); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->SetSpeed(MOVE_RUN, 0.4f); + me->GetMotionMaster()->MoveChase(who); + me->SetUInt64Value(UNIT_FIELD_TARGET, TargetGUID); + Intro = true; + } + +}; + +CreatureAI* GetAI_npc_dark_rider_of_acherus(Creature* pCreature) +{ + return new npc_dark_rider_of_acherusAI(pCreature); +} + +/*###### +## npc_salanar_the_horseman +######*/ + +enum eSalanar +{ + REALM_OF_SHADOWS = 52693, + EFFECT_STOLEN_HORSE = 52263, + DELIVER_STOLEN_HORSE = 52264, + CALL_DARK_RIDER = 52266, + SPELL_EFFECT_OVERTAKE = 52349 +}; + +struct npc_salanar_the_horsemanAI : public ScriptedAI +{ + npc_salanar_the_horsemanAI(Creature *c) : ScriptedAI(c) {} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == DELIVER_STOLEN_HORSE) + { + if (caster->GetTypeId() == TYPEID_UNIT && caster->IsVehicle()) + { + if (Unit *charmer = caster->GetCharmer()) + { + charmer->RemoveAurasDueToSpell(EFFECT_STOLEN_HORSE); + caster->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + caster->setFaction(35); + DoCast(caster, CALL_DARK_RIDER, true); + if (Creature* Dark_Rider = me->FindNearestCreature(28654, 15)) + CAST_AI(npc_dark_rider_of_acherusAI, Dark_Rider->AI())->InitDespawnHorse(caster); + } + } + } + } + + void MoveInLineOfSight(Unit *who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (who->GetTypeId() == TYPEID_UNIT && who->IsVehicle() && me->IsWithinDistInMap(who, 5.0f)) + { + if (Unit *charmer = who->GetCharmer()) + { + if (charmer->GetTypeId() == TYPEID_PLAYER) + { + // for quest Into the Realm of Shadows(12687) + if (me->GetEntry() == 28788 && CAST_PLR(charmer)->GetQuestStatus(12687) == QUEST_STATUS_INCOMPLETE) + { + CAST_PLR(charmer)->GroupEventHappens(12687, me); + charmer->RemoveAurasDueToSpell(SPELL_EFFECT_OVERTAKE); + CAST_CRE(who)->ForcedDespawn(); + //CAST_CRE(who)->Respawn(true); + } + + if (CAST_PLR(charmer)->HasAura(REALM_OF_SHADOWS)) + charmer->RemoveAurasDueToSpell(REALM_OF_SHADOWS); + } + } + } + } +}; + +CreatureAI* GetAI_npc_salanar_the_horseman(Creature* pCreature) +{ + return new npc_salanar_the_horsemanAI(pCreature); +} + +/*###### +## npc_ros_dark_rider +######*/ + +struct npc_ros_dark_riderAI : public ScriptedAI +{ + npc_ros_dark_riderAI(Creature *c) : ScriptedAI(c) {} + + void EnterCombat(Unit * /*who*/) + { + me->ExitVehicle(); + } + + void Reset() + { + Creature* deathcharger = me->FindNearestCreature(28782, 30); + if (!deathcharger) return; + deathcharger->RestoreFaction(); + deathcharger->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + deathcharger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (!me->GetVehicle() && deathcharger->IsVehicle() && deathcharger->GetVehicleKit()->HasEmptySeat(0)) + me->EnterVehicle(deathcharger); + } + + void JustDied(Unit *killer) + { + Creature* deathcharger = me->FindNearestCreature(28782, 30); + if (!deathcharger) return; + if (killer->GetTypeId() == TYPEID_PLAYER && deathcharger->GetTypeId() == TYPEID_UNIT && deathcharger->IsVehicle()) + { + deathcharger->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + deathcharger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + deathcharger->setFaction(2096); + } + } +}; + +CreatureAI* GetAI_npc_ros_dark_rider(Creature* pCreature) +{ + return new npc_ros_dark_riderAI(pCreature); +} + +// correct way: 52312 52314 52555 ... +enum SG +{ + GHOULS = 28845, + GHOSTS = 28846, +}; +struct npc_dkc1_gothikAI : public ScriptedAI +{ + npc_dkc1_gothikAI(Creature *c) : ScriptedAI(c) {} + + void MoveInLineOfSight(Unit *who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (who->GetEntry() == GHOULS && me->IsWithinDistInMap(who, 10.0f)) + { + if (Unit *owner = who->GetOwner()) + { + if (owner->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(owner)->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE) + { + //CAST_CRE(who)->CastSpell(owner, 52517, true); + CAST_PLR(owner)->KilledMonsterCredit(GHOULS, me->GetGUID()); + } + //Todo: Creatures must not be removed, but, must instead + // stand next to Gothik and be commanded into the pit + // and dig into the ground. + CAST_CRE(who)->ForcedDespawn(); + + if (CAST_PLR(owner)->GetQuestStatus(12698) == QUEST_STATUS_COMPLETE) + owner->RemoveAllMinionsByEntry(GHOULS); + } + } + } + } +}; + +CreatureAI* GetAI_npc_dkc1_gothik(Creature* pCreature) +{ + return new npc_dkc1_gothikAI(pCreature); +} + +struct npc_scarlet_ghoulAI : public ScriptedAI +{ + npc_scarlet_ghoulAI(Creature *c) : ScriptedAI(c) + { + // Ghouls should display their Birth Animation + // Crawling out of the ground + //DoCast(me, 35177, true); + //me->MonsterSay("Mommy?",LANG_UNIVERSAL,0); + me->SetReactState(REACT_DEFENSIVE); + } + + void FindMinions(Unit *owner) + { + std::list MinionList; + owner->GetAllMinionsByEntry(MinionList,GHOULS); + + if (!MinionList.empty()) + { + for (std::list::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr) + { + if (CAST_CRE(*itr)->GetOwner()->GetGUID() == me->GetOwner()->GetGUID()) + { + if (CAST_CRE(*itr)->isInCombat() && CAST_CRE(*itr)->getAttackerForHelper()) + { + AttackStart(CAST_CRE(*itr)->getAttackerForHelper()); + } + } + } + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!me->isInCombat()) + { + if (Unit *owner = me->GetOwner()) + { + if (owner->GetTypeId() == TYPEID_PLAYER && CAST_PLR(owner)->isInCombat()) + { + if (CAST_PLR(owner)->getAttackerForHelper() && CAST_PLR(owner)->getAttackerForHelper()->GetEntry() == GHOSTS) + { + AttackStart(CAST_PLR(owner)->getAttackerForHelper()); + } + else + { + FindMinions(owner); + } + } + } + } + + if (!UpdateVictim()) + return; + + //ScriptedAI::UpdateAI(diff); + //Check if we have a current target + if (me->getVictim()->GetEntry() == GHOSTS) + { + if (me->isAttackReady()) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + } + } +}; + +CreatureAI* GetAI_npc_scarlet_ghoul(Creature* pCreature) +{ + return new npc_scarlet_ghoulAI(pCreature); +} + +/*#### +## npc_scarlet_miner_cart +####*/ + +#define SPELL_CART_CHECK 54173 +#define SPELL_CART_DRAG 52465 + +struct npc_scarlet_miner_cartAI : public PassiveAI +{ + npc_scarlet_miner_cartAI(Creature *c) : PassiveAI(c), minerGUID(0) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetDisplayId(me->GetCreatureInfo()->Modelid1); // H0 is horse + } + + uint64 minerGUID; + + void SetGUID(const uint64 &guid, int32 /*id*/) + { + minerGUID = guid; + } + + void DoAction(const int32 /*param*/) + { + if (Creature *miner = Unit::GetCreature(*me, minerGUID)) + { + // very bad visual effect + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + //me->SetSpeed(MOVE_WALK, miner->GetSpeed(MOVE_WALK)); + me->SetSpeed(MOVE_RUN, miner->GetSpeed(MOVE_RUN)); + me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); + } + } + + void PassengerBoarded(Unit * /*who*/, int8 /*seatId*/, bool apply) + { + if (!apply) + if (Creature *miner = Unit::GetCreature(*me, minerGUID)) + miner->DisappearAndDie(); + } +}; + +CreatureAI* GetAI_npc_scarlet_miner_cart(Creature *_Creature) +{ + return new npc_scarlet_miner_cartAI(_Creature); +} + +/*#### +## npc_scarlet_miner +####*/ + +#define SAY_SCARLET_MINER1 "Where'd this come from? I better get this down to the ships before the foreman sees it!" +#define SAY_SCARLET_MINER2 "Now I can have a rest!" + +struct npc_scarlet_minerAI : public npc_escortAI +{ + npc_scarlet_minerAI(Creature *c) : npc_escortAI(c) + { + me->SetReactState(REACT_PASSIVE); + } + + uint32 IntroTimer; + uint32 IntroPhase; + uint64 carGUID; + + void Reset() + { + carGUID = 0; + IntroTimer = 0; + IntroPhase = 0; + } + + void InitWaypoint() + { + AddWaypoint(1, 2389.03, -5902.74, 109.014, 5000); + AddWaypoint(2, 2341.812012, -5900.484863, 102.619743); + AddWaypoint(3, 2306.561279, -5901.738281, 91.792419); + AddWaypoint(4, 2300.098389, -5912.618652, 86.014885); + AddWaypoint(5, 2294.142090, -5927.274414, 75.316849); + AddWaypoint(6, 2286.984375, -5944.955566, 63.714966); + AddWaypoint(7, 2280.001709, -5961.186035, 54.228283); + AddWaypoint(8, 2259.389648, -5974.197754, 42.359348); + AddWaypoint(9, 2242.882812, -5984.642578, 32.827850); + AddWaypoint(10, 2217.265625, -6028.959473, 7.675705); + AddWaypoint(11, 2202.595947, -6061.325684, 5.882018); + AddWaypoint(12, 2188.974609, -6080.866699, 3.370027); + + if (urand(0,1)) + { + AddWaypoint(13, 2176.483887, -6110.407227, 1.855181); + AddWaypoint(14, 2172.516602, -6146.752441, 1.074235); + AddWaypoint(15, 2138.918457, -6158.920898, 1.342926); + AddWaypoint(16, 2129.866699, -6174.107910, 4.380779); + AddWaypoint(17, 2117.709473, -6193.830078, 13.3542, 10000); + } + else + { + AddWaypoint(13, 2184.190186, -6166.447266, 0.968877); + AddWaypoint(14, 2234.265625, -6163.741211, 0.916021); + AddWaypoint(15, 2268.071777, -6158.750977, 1.822252); + AddWaypoint(16, 2270.028320, -6176.505859, 6.340538); + AddWaypoint(17, 2271.739014, -6195.401855, 13.3542, 10000); + } + } + + void InitCartQuest(Player *who) + { + carGUID = who->GetVehicleBase()->GetGUID(); + InitWaypoint(); + Start(false, false, who->GetGUID()); + SetDespawnAtFar(false); + } + + void WaypointReached(uint32 i) + { + switch (i) + { + case 1: + if (Unit *car = Unit::GetCreature(*me, carGUID)) + { + me->SetInFront(car); + me->SendMovementFlagUpdate(); + } + me->MonsterSay(SAY_SCARLET_MINER1,LANG_UNIVERSAL,NULL); + SetRun(true); + IntroTimer = 4000; + IntroPhase = 1; + break; + case 17: + if (Unit *car = Unit::GetCreature(*me, carGUID)) + { + me->SetInFront(car); + me->SendMovementFlagUpdate(); + car->Relocate(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ()); + car->SendMonsterStop(); + //this make player fall under ground, dunno why + //car->GetMotionMaster()->MovePoint(0, car->GetPositionX(), car->GetPositionY(), me->GetPositionZ()); + car->RemoveAura(SPELL_CART_DRAG); + } + me->MonsterSay(SAY_SCARLET_MINER2,LANG_UNIVERSAL,NULL); + break; + default: + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (IntroPhase) + { + if (IntroTimer <= diff) + { + if (IntroPhase == 1) + { + if (Creature *car = Unit::GetCreature(*me, carGUID)) + DoCast(car, SPELL_CART_DRAG); + IntroTimer = 800; + IntroPhase = 2; + } + else + { + if (Creature *car = Unit::GetCreature(*me, carGUID)) + car->AI()->DoAction(); + IntroPhase = 0; + } + } else IntroTimer-=diff; + } + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_scarlet_miner(Creature *_Creature) +{ + return new npc_scarlet_minerAI(_Creature); +} + +/*###### +## go_inconspicuous_mine_car +######*/ + +#define SPELL_CART_SUMM 52463 + +bool GOHello_go_inconspicuous_mine_car(Player* pPlayer, GameObject* /*pGO*/) +{ + if (pPlayer->GetQuestStatus(12701) == QUEST_STATUS_INCOMPLETE) + { + // Hack Why Trinity Dont Support Custom Summon Location + if (Creature *miner = pPlayer->SummonCreature(28841, 2383.869629, -5900.312500, 107.996086, pPlayer->GetOrientation(),TEMPSUMMON_DEAD_DESPAWN, 1)) + { + pPlayer->CastSpell(pPlayer, SPELL_CART_SUMM, true); + if (Creature *car = pPlayer->GetVehicleCreatureBase()) + { + if (car->GetEntry() == 28817) + { + car->AI()->SetGUID(miner->GetGUID()); + CAST_AI(npc_scarlet_minerAI, miner->AI())->InitCartQuest(pPlayer); + } else error_log("TSCR: GOHello_go_inconspicuous_mine_car vehicle entry is not correct."); + } else error_log("TSCR: GOHello_go_inconspicuous_mine_car player is not on the vehicle."); + } else error_log("TSCR: GOHello_go_inconspicuous_mine_car Scarlet Miner cant be found by script."); + } + return true; +} + +// npc 28912 quest 17217 boss 29001 mob 29007 go 191092 + +void AddSC_the_scarlet_enclave_c1() +{ + Script *newscript; + + // 12848 The Endless Hunger + newscript = new Script; + newscript->Name = "npc_unworthy_initiate"; + newscript->GetAI = &GetAI_npc_unworthy_initiate; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_unworthy_initiate_anchor"; + newscript->GetAI = &GetAI_npc_unworthy_initiate_anchor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_acherus_soul_prison"; + newscript->pGOHello = &GOHello_go_acherus_soul_prison; + newscript->RegisterSelf(); + + // Death's Challenge + newscript = new Script; + newscript->Name = "npc_death_knight_initiate"; + newscript->GetAI = &GetAI_npc_death_knight_initiate; + newscript->pGossipHello = &GossipHello_npc_death_knight_initiate; + newscript->pGossipSelect = &GossipSelect_npc_death_knight_initiate; + newscript->RegisterSelf(); + + // 12680 Grand Theft Palomino + newscript = new Script; + newscript->Name = "npc_salanar_the_horseman"; + newscript->GetAI = &GetAI_npc_salanar_the_horseman; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dark_rider_of_acherus"; + newscript->GetAI = &GetAI_npc_dark_rider_of_acherus; + newscript->RegisterSelf(); + + // 12687 Into the Realm of Shadows + newscript = new Script; + newscript->Name = "npc_ros_dark_rider"; + newscript->GetAI = &GetAI_npc_ros_dark_rider; + newscript->RegisterSelf(); + + // 12698 The Gift That Keeps On Giving + newscript = new Script; + newscript->Name = "npc_dkc1_gothik"; + newscript->GetAI = &GetAI_npc_dkc1_gothik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_scarlet_ghoul"; + newscript->GetAI = &GetAI_npc_scarlet_ghoul; + newscript->RegisterSelf(); + + // Massacre At Light's Point + newscript = new Script; + newscript->Name = "npc_scarlet_miner"; + newscript->GetAI = &GetAI_npc_scarlet_miner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_scarlet_miner_cart"; + newscript->GetAI = &GetAI_npc_scarlet_miner_cart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_inconspicuous_mine_car"; + newscript->pGOHello = &GOHello_go_inconspicuous_mine_car; + newscript->RegisterSelf(); +} + +/* +DELETE FROM `script_texts` WHERE `entry` IN(-1609301, -1609302); +INSERT INTO `script_texts` (`entry`,`content_default`,`type`,`language`,`emote`,`comment`) VALUES +(-1609301, 'Come, weakling! Strike me down!', 0, 0, 0, 'SAY_DEATH_RIDER_FINAL'), +(-1609302, '%s rears up, beckoning you to ride it.', 2, 0, 0, 'SAY_DEATH_CHARGER'); +*/ diff --git a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp new file mode 100644 index 00000000000..91f7e0e6cbe --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp @@ -0,0 +1,995 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +//How to win friends and influence enemies +// texts signed for creature 28939 but used for 28939,28940,28610 +enum win_friends +{ + SAY_PERSUADE1 = -1609501, + SAY_PERSUADE2 = -1609502, + SAY_PERSUADE3 = -1609503, + SAY_PERSUADE4 = -1609504, + SAY_PERSUADE5 = -1609505, + SAY_PERSUADE6 = -1609506, + SAY_PERSUADE7 = -1609507, + SAY_CRUSADER1 = -1609508, + SAY_CRUSADER2 = -1609509, + SAY_CRUSADER3 = -1609510, + SAY_CRUSADER4 = -1609511, + SAY_CRUSADER5 = -1609512, + SAY_CRUSADER6 = -1609513, + SAY_PERSUADED1 = -1609514, + SAY_PERSUADED2 = -1609515, + SAY_PERSUADED3 = -1609516, + SAY_PERSUADED4 = -1609517, + SAY_PERSUADED5 = -1609518, + SAY_PERSUADED6 = -1609519, + SPELL_PERSUASIVE_STRIKE = 52781 +}; + +struct npc_crusade_persuadedAI : public ScriptedAI +{ + npc_crusade_persuadedAI(Creature *pCreature) : ScriptedAI(pCreature) {} + + uint32 uiSpeech_timer; + uint32 uiSpeech_counter; + uint64 uiPlayerGUID; + + void Reset() + { + uiSpeech_timer = 0; + uiSpeech_counter = 0; + uiPlayerGUID = 0; + me->SetReactState(REACT_AGGRESSIVE); + me->RestoreFaction(); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_PERSUASIVE_STRIKE && caster->GetTypeId() == TYPEID_PLAYER && me->isAlive() && !uiSpeech_counter) + { + if (CAST_PLR(caster)->GetQuestStatus(12720) == QUEST_STATUS_INCOMPLETE) + { + uiPlayerGUID = caster->GetGUID(); + uiSpeech_timer = 1000; + uiSpeech_counter = 1; + me->setFaction(caster->getFaction()); + me->CombatStop(true); + me->GetMotionMaster()->MoveIdle(); + me->SetReactState(REACT_PASSIVE); + DoCastAOE(58111, true); + + DoScriptText(RAND(SAY_PERSUADE1,SAY_PERSUADE2,SAY_PERSUADE3, + SAY_PERSUADE4,SAY_PERSUADE5,SAY_PERSUADE6, + SAY_PERSUADE7), caster); + + DoScriptText(RAND(SAY_CRUSADER1,SAY_CRUSADER2,SAY_CRUSADER3, + SAY_CRUSADER4,SAY_CRUSADER5,SAY_CRUSADER6), me); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (uiSpeech_counter) + { + if (uiSpeech_timer <= diff) + { + Player* pPlayer = Unit::GetPlayer(uiPlayerGUID); + if (!pPlayer) + { + EnterEvadeMode(); + return; + } + + switch(uiSpeech_counter) + { + case 1: DoScriptText(SAY_PERSUADED1, me); uiSpeech_timer = 8000; break; + case 2: DoScriptText(SAY_PERSUADED2, me); uiSpeech_timer = 8000; break; + case 3: DoScriptText(SAY_PERSUADED3, me); uiSpeech_timer = 8000; break; + case 4: DoScriptText(SAY_PERSUADED4, me); uiSpeech_timer = 8000; break; + case 5: DoScriptText(SAY_PERSUADED5, pPlayer); uiSpeech_timer = 8000; break; + case 6: DoScriptText(SAY_PERSUADED6, me); + pPlayer->Kill(me); + //me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiSpeech_counter = 0; + pPlayer->GroupEventHappens(12720, me); + return; + } + + ++uiSpeech_counter; + DoCastAOE(58111, true); + } else uiSpeech_timer -= diff; + + return; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_crusade_persuaded(Creature* pCreature) +{ + return new npc_crusade_persuadedAI (pCreature); +} + +/*###### +## npc_koltira_deathweaver +######*/ + +enum eKoltira +{ + SAY_BREAKOUT1 = -1609561, + SAY_BREAKOUT2 = -1609562, + SAY_BREAKOUT3 = -1609563, + SAY_BREAKOUT4 = -1609564, + SAY_BREAKOUT5 = -1609565, + SAY_BREAKOUT6 = -1609566, + SAY_BREAKOUT7 = -1609567, + SAY_BREAKOUT8 = -1609568, + SAY_BREAKOUT9 = -1609569, + SAY_BREAKOUT10 = -1609570, + + SPELL_KOLTIRA_TRANSFORM = 52899, + SPELL_ANTI_MAGIC_ZONE = 52894, + + QUEST_BREAKOUT = 12727, + + NPC_CRIMSON_ACOLYTE = 29007, + NPC_HIGH_INQUISITOR_VALROTH = 29001, + NPC_KOLTIRA_ALT = 28447, + + //not sure about this id + //NPC_DEATH_KNIGHT_MOUNT = 29201, + MODEL_DEATH_KNIGHT_MOUNT = 25278 +}; + +struct npc_koltira_deathweaverAI : public npc_escortAI +{ + npc_koltira_deathweaverAI(Creature *pCreature) : npc_escortAI(pCreature) + { + me->SetReactState(REACT_DEFENSIVE); + } + + uint32 m_uiWave; + uint32 m_uiWave_Timer; + uint64 m_uiValrothGUID; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + m_uiWave = 0; + m_uiWave_Timer = 3000; + m_uiValrothGUID = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->LoadEquipment(0, true); + me->RemoveAura(SPELL_ANTI_MAGIC_ZONE); + } + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 0: + DoScriptText(SAY_BREAKOUT1, me); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + break; + case 1: + me->SetStandState(UNIT_STAND_STATE_KNEEL); + break; + case 2: + me->SetStandState(UNIT_STAND_STATE_STAND); + //me->UpdateEntry(NPC_KOLTIRA_ALT); //unclear if we must update or not + DoCast(me, SPELL_KOLTIRA_TRANSFORM); + me->LoadEquipment(me->GetEquipmentId()); + break; + case 3: + SetEscortPaused(true); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(SAY_BREAKOUT2, me); + DoCast(me, SPELL_ANTI_MAGIC_ZONE); // cast again that makes bubble up + break; + case 4: + SetRun(true); + break; + case 9: + me->Mount(MODEL_DEATH_KNIGHT_MOUNT); + break; + case 10: + me->Unmount(); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + if (Player* pPlayer = GetPlayerForEscort()) + { + pSummoned->AI()->AttackStart(pPlayer); + } + + if (pSummoned->GetEntry() == NPC_HIGH_INQUISITOR_VALROTH) + m_uiValrothGUID = pSummoned->GetGUID(); + + pSummoned->AddThreat(me, 0.0f); + pSummoned->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + void SummonAcolyte(uint32 uiAmount) + { + for (uint32 i = 0; i < uiAmount; ++i) + me->SummonCreature(NPC_CRIMSON_ACOLYTE, 1642.329, -6045.818, 127.583, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (HasEscortState(STATE_ESCORT_PAUSED)) + { + if (m_uiWave_Timer <= uiDiff) + { + switch(m_uiWave) + { + case 0: + DoScriptText(SAY_BREAKOUT3, me); + SummonAcolyte(3); + m_uiWave_Timer = 20000; + break; + case 1: + DoScriptText(SAY_BREAKOUT4, me); + SummonAcolyte(3); + m_uiWave_Timer = 20000; + break; + case 2: + DoScriptText(SAY_BREAKOUT5, me); + SummonAcolyte(4); + m_uiWave_Timer = 20000; + break; + case 3: + DoScriptText(SAY_BREAKOUT6, me); + me->SummonCreature(NPC_HIGH_INQUISITOR_VALROTH, 1642.329, -6045.818, 127.583, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + m_uiWave_Timer = 1000; + break; + case 4: + { + Creature* pTemp = Unit::GetCreature(*me, m_uiValrothGUID); + + if (!pTemp || !pTemp->isAlive()) + { + DoScriptText(SAY_BREAKOUT8, me); + m_uiWave_Timer = 5000; + } + else + { + m_uiWave_Timer = 2500; + return; //return, we don't want m_uiWave to increment now + } + break; + } + case 5: + DoScriptText(SAY_BREAKOUT9, me); + me->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); + // i do not know why the armor will also be removed + m_uiWave_Timer = 2500; + break; + case 6: + DoScriptText(SAY_BREAKOUT10, me); + SetEscortPaused(false); + break; + } + + ++m_uiWave; + } + else + m_uiWave_Timer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_koltira_deathweaver(Creature* pCreature) +{ + return new npc_koltira_deathweaverAI(pCreature); +} + +bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_BREAKOUT) + { + pCreature->SetStandState(UNIT_STAND_STATE_STAND); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_koltira_deathweaverAI,pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID()); + } + return true; +} + +//Scarlet courier +enum ScarletCourierEnum +{ + SAY_TREE1 = -1609531, + SAY_TREE2 = -1609532, + SPELL_SHOOT = 52818, + GO_INCONSPICUOUS_TREE = 191144, + NPC_SCARLET_COURIER = 29076 +}; + +struct mob_scarlet_courierAI : public ScriptedAI +{ + mob_scarlet_courierAI(Creature *pCreature) : ScriptedAI(pCreature) {} + + uint32 uiStage; + uint32 uiStage_timer; + + void Reset() + { + me->Mount(14338); // not sure about this id + uiStage = 1; + uiStage_timer = 3000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_TREE2, me); + me->Unmount(); + uiStage = 0; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + uiStage = 2; + } + + void UpdateAI(const uint32 diff) + { + if (uiStage && !me->isInCombat()) + { + if (uiStage_timer <= diff) + { + switch(uiStage) + { + case 1: + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + if (GameObject* tree = me->FindNearestGameObject(GO_INCONSPICUOUS_TREE, 40.0f)) + { + DoScriptText(SAY_TREE1, me); + float x, y, z; + tree->GetContactPoint(me, x, y, z); + me->GetMotionMaster()->MovePoint(1, x, y, z); + } + break; + case 2: + if (GameObject* tree = me->FindNearestGameObject(GO_INCONSPICUOUS_TREE, 40.0f)) + if (Unit *unit = tree->GetOwner()) + AttackStart(unit); + break; + } + uiStage_timer = 3000; + uiStage = 0; + } else uiStage_timer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_scarlet_courier(Creature* pCreature) +{ + return new mob_scarlet_courierAI (pCreature); +} + +//Koltira & Valroth- Breakout + +enum valroth +{ + SAY_VALROTH1 = -1609581, + SAY_VALROTH2 = -1609582, + SAY_VALROTH3 = -1609583, + SAY_VALROTH4 = -1609584, + SAY_VALROTH5 = -1609585, + SAY_VALROTH6 = -1609586, + SPELL_RENEW = 38210, + SPELL_INQUISITOR_PENANCE = 52922, + SPELL_VALROTH_SMITE = 52926, + SPELL_SUMMON_VALROTH_REMAINS = 52929 +}; + +struct mob_high_inquisitor_valrothAI : public ScriptedAI +{ + mob_high_inquisitor_valrothAI(Creature *pCreature) : ScriptedAI(pCreature) {} + + uint32 uiRenew_timer; + uint32 uiInquisitor_Penance_timer; + uint32 uiValroth_Smite_timer; + + void Reset() + { + uiRenew_timer = 1000; + uiInquisitor_Penance_timer = 2000; + uiValroth_Smite_timer = 1000; + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_VALROTH2, me); + DoCast(who, SPELL_VALROTH_SMITE); + } + + void UpdateAI(const uint32 diff) + { + if (uiRenew_timer <= diff) + { + Shout(); + DoCast(me, SPELL_RENEW); + uiRenew_timer = 1000 + rand()%5000; + } else uiRenew_timer -= diff; + + if (uiInquisitor_Penance_timer <= diff) + { + Shout(); + DoCast(me->getVictim(), SPELL_INQUISITOR_PENANCE); + uiInquisitor_Penance_timer = 2000 + rand()%5000; + } else uiInquisitor_Penance_timer -= diff; + + if (uiValroth_Smite_timer <= diff) + { + Shout(); + DoCast(me->getVictim(), SPELL_VALROTH_SMITE); + uiValroth_Smite_timer = 1000 + rand()%5000; + } else uiValroth_Smite_timer -= diff; + + DoMeleeAttackIfReady(); + } + + void Shout() + { + if (rand()%100 < 15) + DoScriptText(RAND(SAY_VALROTH3,SAY_VALROTH4,SAY_VALROTH5), me); + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_VALROTH6, me); + killer->CastSpell(me, SPELL_SUMMON_VALROTH_REMAINS, true); + } +}; + +CreatureAI* GetAI_mob_high_inquisitor_valroth(Creature* pCreature) +{ + return new mob_high_inquisitor_valrothAI (pCreature); +} + +/*###### +## npc_a_special_surprise +######*/ +//used by 29032,29061,29065,29067,29068,29070,29074,29072,29073,29071 but signed for 29032 +enum SpecialSurprise +{ + SAY_EXEC_START_1 = -1609025, // speech for all + SAY_EXEC_START_2 = -1609026, + SAY_EXEC_START_3 = -1609027, + SAY_EXEC_PROG_1 = -1609028, + SAY_EXEC_PROG_2 = -1609029, + SAY_EXEC_PROG_3 = -1609030, + SAY_EXEC_PROG_4 = -1609031, + SAY_EXEC_PROG_5 = -1609032, + SAY_EXEC_PROG_6 = -1609033, + SAY_EXEC_PROG_7 = -1609034, + SAY_EXEC_NAME_1 = -1609035, + SAY_EXEC_NAME_2 = -1609036, + SAY_EXEC_RECOG_1 = -1609037, + SAY_EXEC_RECOG_2 = -1609038, + SAY_EXEC_RECOG_3 = -1609039, + SAY_EXEC_RECOG_4 = -1609040, + SAY_EXEC_RECOG_5 = -1609041, + SAY_EXEC_RECOG_6 = -1609042, + SAY_EXEC_NOREM_1 = -1609043, + SAY_EXEC_NOREM_2 = -1609044, + SAY_EXEC_NOREM_3 = -1609045, + SAY_EXEC_NOREM_4 = -1609046, + SAY_EXEC_NOREM_5 = -1609047, + SAY_EXEC_NOREM_6 = -1609048, + SAY_EXEC_NOREM_7 = -1609049, + SAY_EXEC_NOREM_8 = -1609050, + SAY_EXEC_NOREM_9 = -1609051, + SAY_EXEC_THINK_1 = -1609052, + SAY_EXEC_THINK_2 = -1609053, + SAY_EXEC_THINK_3 = -1609054, + SAY_EXEC_THINK_4 = -1609055, + SAY_EXEC_THINK_5 = -1609056, + SAY_EXEC_THINK_6 = -1609057, + SAY_EXEC_THINK_7 = -1609058, + SAY_EXEC_THINK_8 = -1609059, + SAY_EXEC_THINK_9 = -1609060, + SAY_EXEC_THINK_10 = -1609061, + SAY_EXEC_LISTEN_1 = -1609062, + SAY_EXEC_LISTEN_2 = -1609063, + SAY_EXEC_LISTEN_3 = -1609064, + SAY_EXEC_LISTEN_4 = -1609065, + SAY_PLAGUEFIST = -1609066, + SAY_EXEC_TIME_1 = -1609067, + SAY_EXEC_TIME_2 = -1609068, + SAY_EXEC_TIME_3 = -1609069, + SAY_EXEC_TIME_4 = -1609070, + SAY_EXEC_TIME_5 = -1609071, + SAY_EXEC_TIME_6 = -1609072, + SAY_EXEC_TIME_7 = -1609073, + SAY_EXEC_TIME_8 = -1609074, + SAY_EXEC_TIME_9 = -1609075, + SAY_EXEC_TIME_10 = -1609076, + SAY_EXEC_WAITING = -1609077, + EMOTE_DIES = -1609078, + + NPC_PLAGUEFIST = 29053 +}; + +struct npc_a_special_surpriseAI : public ScriptedAI +{ + npc_a_special_surpriseAI(Creature *pCreature) : ScriptedAI(pCreature) {} + + uint32 ExecuteSpeech_Timer; + uint32 ExecuteSpeech_Counter; + uint64 PlayerGUID; + + void Reset() + { + ExecuteSpeech_Timer = 0; + ExecuteSpeech_Counter = 0; + PlayerGUID = 0; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + bool MeetQuestCondition(Unit* pPlayer) + { + switch(me->GetEntry()) + { + case 29061: // Ellen Stanbridge + if (CAST_PLR(pPlayer)->GetQuestStatus(12742) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29072: // Kug Ironjaw + if (CAST_PLR(pPlayer)->GetQuestStatus(12748) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29067: // Donovan Pulfrost + if (CAST_PLR(pPlayer)->GetQuestStatus(12744) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29065: // Yazmina Oakenthorn + if (CAST_PLR(pPlayer)->GetQuestStatus(12743) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29071: // Antoine Brack + if (CAST_PLR(pPlayer)->GetQuestStatus(12750) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29032: // Malar Bravehorn + if (CAST_PLR(pPlayer)->GetQuestStatus(12739) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29068: // Goby Blastenheimer + if (CAST_PLR(pPlayer)->GetQuestStatus(12745) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29073: // Iggy Darktusk + if (CAST_PLR(pPlayer)->GetQuestStatus(12749) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29074: // Lady Eonys + if (CAST_PLR(pPlayer)->GetQuestStatus(12747) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29070: // Valok the Righteous + if (CAST_PLR(pPlayer)->GetQuestStatus(12746) == QUEST_STATUS_INCOMPLETE) + return true; + break; + } + + return false; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (PlayerGUID || pWho->GetTypeId() != TYPEID_PLAYER || !pWho->IsWithinDist(me, INTERACTION_DISTANCE)) + return; + + if (MeetQuestCondition(pWho)) + PlayerGUID = pWho->GetGUID(); + } + + void UpdateAI(const uint32 diff) + { + if (PlayerGUID && !me->getVictim() && me->isAlive()) + { + if (ExecuteSpeech_Timer <= diff) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + if (!pPlayer) + { + Reset(); + return; + } + + //TODO: simplify text's selection + + switch(pPlayer->getRace()) + { + case RACE_HUMAN: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_5, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_5, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_7, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_6, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_ORC: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_6, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_7, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_8, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_8, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_DWARF: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_2, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_2, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_3, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_2, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_5, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_2, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_3, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_NIGHTELF: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_5, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_6, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_2, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_7, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_UNDEAD_PLAYER: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_3, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_4, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_3, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_1, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_3, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_4, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_TAUREN: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_5, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_8, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_9, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_9, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_GNOME: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_4, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_4, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_6, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_5, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_TROLL: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_3, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_7, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_2, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_6, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_9, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_10, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_4, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_10, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_BLOODELF: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + //case 5: //unknown + case 6: DoScriptText(SAY_EXEC_THINK_3, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_1, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_DRAENEI: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_2, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_1, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_4, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_2, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + } + + if (ExecuteSpeech_Counter >= 9) + ExecuteSpeech_Timer = 15000; + else + ExecuteSpeech_Timer = 7000; + + ++ExecuteSpeech_Counter; + } + else + ExecuteSpeech_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_npc_a_special_surprise(Creature* pCreature) +{ + return new npc_a_special_surpriseAI(pCreature); +} + +void AddSC_the_scarlet_enclave_c2() +{ + Script *newscript; + + // How to win friends and influence enemies + newscript = new Script; + newscript->Name = "npc_crusade_persuaded"; + newscript->GetAI = &GetAI_npc_crusade_persuaded; + newscript->RegisterSelf(); + + // Ambush At The Overlook + newscript = new Script; + newscript->Name = "mob_scarlet_courier"; + newscript->GetAI = &GetAI_mob_scarlet_courier; + newscript->RegisterSelf(); + + // 12727 Bloody Breakout + newscript = new Script; + newscript->Name = "npc_koltira_deathweaver"; + newscript->GetAI = &GetAI_npc_koltira_deathweaver; + newscript->pQuestAccept = &QuestAccept_npc_koltira_deathweaver; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_high_inquisitor_valroth"; + newscript->GetAI = &GetAI_mob_high_inquisitor_valroth; + newscript->RegisterSelf(); + + // A Special Suprise + newscript = new Script; + newscript->Name = "npc_a_special_surprise"; + newscript->GetAI = &GetAI_npc_a_special_surprise; + newscript->RegisterSelf(); +} + +/* +-- Bloody Breakout +UPDATE `creature_template` SET `ScriptName`='npc_koltira_deathweaver' WHERE `entry`='28912'; +UPDATE `creature_template` SET `ScriptName`='mob_high_inquisitor_valroth',minmana=6489,maxmana=6489,unit_flags=32768 WHERE `entry`='29001'; +UPDATE `creature_template` SET `ScriptName`='mob_eventai', `AIName`='EventAI',minmana=1020,maxmana=1058,unit_flags=32768 WHERE (`entry`='29007'); +DELETE FROM creature_ai_scripts WHERE id BETWEEN 90030 AND 90033; +INSERT INTO `creature_ai_scripts` VALUES ('90030', '29007', '0', '0', '100', '1', '1000', '4000', '1000', '4000', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Smite'); +INSERT INTO `creature_ai_scripts` VALUES ('90031', '29007', '0', '0', '100', '1', '1000', '10000', '20000', '21000', '11', '34809', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Fury'); +INSERT INTO `creature_ai_scripts` VALUES ('90032', '29007', '0', '0', '100', '1', '1000', '5000', '1000', '5000', '11', '19725', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Turn Undead'); +INSERT INTO `creature_ai_scripts` VALUES ('90033', '29007', '4', '0', '100', '0', '0', '0', '0', '0', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte aggro'); +*/ diff --git a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp new file mode 100644 index 00000000000..3b0ce186592 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp @@ -0,0 +1,1684 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +#define LESS_MOB // if you do not have a good server and do not want it to be laggy as hell +//Light of Dawn +enum mograine +{ +#ifdef LESS_MOB + ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - + ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data + ENCOUNTER_DEFENDER_NUMBER = 10, // how many of defender + ENCOUNTER_EARTHSHATTER_NUMBER = 1, // how many of earthshatter + ENCOUNTER_ABOMINATION_NUMBER = 2, // how many of abomination + ENCOUNTER_BEHEMOTH_NUMBER = 1, // how many of behemoth + ENCOUNTER_GHOUL_NUMBER = 5, // how many of ghoul + ENCOUNTER_WARRIOR_NUMBER = 1, // how many of warrior +#else + ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - + ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data + ENCOUNTER_DEFENDER_NUMBER = 20, // how many of defender + ENCOUNTER_EARTHSHATTER_NUMBER = 20, // how many of earthshatter + ENCOUNTER_ABOMINATION_NUMBER = 3, // how many of abomination + ENCOUNTER_BEHEMOTH_NUMBER = 2, // how many of behemoth + ENCOUNTER_GHOUL_NUMBER = 10, // how many of ghoul + ENCOUNTER_WARRIOR_NUMBER = 2, // how many of warrior +#endif + ENCOUNTER_TOTAL_DAWN = 300, // Total number + ENCOUNTER_TOTAL_SCOURGE = 10000, + + WORLD_STATE_REMAINS = 3592, + WORLD_STATE_COUNTDOWN = 3603, + WORLD_STATE_EVENT_BEGIN = 3605, + + SAY_LIGHT_OF_DAWN01 = -1609201, // pre text + SAY_LIGHT_OF_DAWN02 = -1609202, + SAY_LIGHT_OF_DAWN03 = -1609203, + SAY_LIGHT_OF_DAWN04 = -1609204, // intro + SAY_LIGHT_OF_DAWN05 = -1609205, + SAY_LIGHT_OF_DAWN06 = -1609206, + SAY_LIGHT_OF_DAWN07 = -1609207, // During the fight - Korfax, Champion of the Light + SAY_LIGHT_OF_DAWN08 = -1609208, // Lord Maxwell Tyrosus + SAY_LIGHT_OF_DAWN09 = -1609209, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN10 = -1609210, + SAY_LIGHT_OF_DAWN11 = -1609211, + SAY_LIGHT_OF_DAWN12 = -1609212, + SAY_LIGHT_OF_DAWN13 = -1609213, + SAY_LIGHT_OF_DAWN14 = -1609214, + SAY_LIGHT_OF_DAWN15 = -1609215, + SAY_LIGHT_OF_DAWN16 = -1609216, + SAY_LIGHT_OF_DAWN17 = -1609217, + SAY_LIGHT_OF_DAWN18 = -1609218, + SAY_LIGHT_OF_DAWN19 = -1609219, + SAY_LIGHT_OF_DAWN20 = -1609220, + SAY_LIGHT_OF_DAWN21 = -1609221, + SAY_LIGHT_OF_DAWN22 = -1609222, + SAY_LIGHT_OF_DAWN23 = -1609223, + SAY_LIGHT_OF_DAWN24 = -1609224, + SAY_LIGHT_OF_DAWN25 = -1609225, // After the fight + SAY_LIGHT_OF_DAWN26 = -1609226, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN27 = -1609227, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN28 = -1609228, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN29 = -1609229, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN30 = -1609230, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN31 = -1609231, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN32 = -1609232, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN33 = -1609233, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN34 = -1609234, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN35 = -1609235, // Darion Mograine + SAY_LIGHT_OF_DAWN36 = -1609236, // Darion Mograine + SAY_LIGHT_OF_DAWN37 = -1609237, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN38 = -1609238, // Darion Mograine + SAY_LIGHT_OF_DAWN39 = -1609239, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN40 = -1609240, // Darion Mograine + SAY_LIGHT_OF_DAWN41 = -1609241, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN42 = -1609242, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN43 = -1609243, // The Lich King + SAY_LIGHT_OF_DAWN44 = -1609244, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN45 = -1609245, // The Lich King + SAY_LIGHT_OF_DAWN46 = -1609246, // The Lich King + SAY_LIGHT_OF_DAWN47 = -1609247, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN48 = -1609248, // The Lich King + SAY_LIGHT_OF_DAWN49 = -1609249, // The Lich King + SAY_LIGHT_OF_DAWN50 = -1609250, // Lord Maxwell Tyrosus + SAY_LIGHT_OF_DAWN51 = -1609251, // The Lich King + SAY_LIGHT_OF_DAWN52 = -1609252, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN53 = -1609253, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN54 = -1609254, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN55 = -1609255, // The Lich King + SAY_LIGHT_OF_DAWN56 = -1609256, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN57 = -1609257, // The Lich King + SAY_LIGHT_OF_DAWN58 = -1609258, // The Lich King + SAY_LIGHT_OF_DAWN59 = -1609259, // The Lich King + SAY_LIGHT_OF_DAWN60 = -1609260, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN61 = -1609261, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN62 = -1609262, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN63 = -1609263, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN64 = -1609264, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN65 = -1609265, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN66 = -1609266, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN67 = -1609267, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN68 = -1609268, // Highlord Darion Mograine + + EMOTE_LIGHT_OF_DAWN01 = -1609269, // Emotes + EMOTE_LIGHT_OF_DAWN02 = -1609270, + EMOTE_LIGHT_OF_DAWN03 = -1609271, + EMOTE_LIGHT_OF_DAWN04 = -1609272, + EMOTE_LIGHT_OF_DAWN05 = -1609273, + EMOTE_LIGHT_OF_DAWN06 = -1609274, + EMOTE_LIGHT_OF_DAWN07 = -1609275, + EMOTE_LIGHT_OF_DAWN08 = -1609276, + EMOTE_LIGHT_OF_DAWN09 = -1609277, + EMOTE_LIGHT_OF_DAWN10 = -1609278, + EMOTE_LIGHT_OF_DAWN11 = -1609279, + EMOTE_LIGHT_OF_DAWN12 = -1609280, + EMOTE_LIGHT_OF_DAWN13 = -1609281, + EMOTE_LIGHT_OF_DAWN14 = -1609282, + EMOTE_LIGHT_OF_DAWN15 = -1609283, + EMOTE_LIGHT_OF_DAWN16 = -1609284, + EMOTE_LIGHT_OF_DAWN17 = -1609285, + EMOTE_LIGHT_OF_DAWN18 = -1609286, + + GO_LIGHT_OF_DAWN = 191330, + SPELL_THE_LIGHT_OF_DAWN_Q = 53606, // quest credit + + // ---- Dark Knight npc -------------------- + // Highlord Darion Mograine + NPC_HIGHLORD_DARION_MOGRAINE = 29173, + SPELL_ANTI_MAGIC_ZONE1 = 52893, + SPELL_DEATH_STRIKE = 53639, + SPELL_DEATH_EMBRACE = 53635, + SPELL_ICY_TOUCH1 = 49723, + SPELL_THE_LIGHT_OF_DAWN = 53658, + SPELL_THE_MIGHT_OF_MOGRAINE = 53642, // on players when begins + SPELL_UNHOLY_BLIGHT = 53640, + SPELL_ALEXANDROS_MOGRAINE_SPAWN = 53667, + SPELL_MOGRAINE_CHARGE = 53679, + SPELL_ASHBRINGER = 53701, + + // Koltira Deathweaver & Orbaz Bloodbane are using the same abilities + NPC_KOLTIRA_DEATHWEAVER = 29199, + NPC_ORBAZ_BLOODBANE = 29204, // this guy fleed + NPC_THASSARIAN = 29200, // he also does SPELL_THE_LIGHT_OF_DAWN 53658 + SPELL_BLOOD_STRIKE1 = 52374, + SPELL_DEATH_GRIP = 49576, + SPELL_ICY_TOUCH2 = 52372, + SPELL_PLAGUE_STRIKE1 = 50668, + // all do SPELL_HERO_AGGRO_AURA 53627 + + // Lich King + NPC_THE_LICH_KING = 29183, // show up at end + SPELL_APOCALYPSE = 53210, + SPELL_TELEPORT_VISUAL = 52233, + SPELL_SOUL_FEAST_ALEX = 53677, // on Alexandros + SPELL_SOUL_FEAST_TIRION = 53685, // on Tirion + SPELL_ICEBOUND_VISAGE = 53274, // not sure what is it for + SPELL_REBUKE = 53680, + + // others + NPC_RAMPAGING_ABOMINATION = 29186, + SPELL_CLEAVE1 = 53633, + SPELL_SCOURGE_HOOK = 50335, + SPELL_SCOURGE_AGGRO_AURA = 53624, + + NPC_FLESH_BEHEMOTH = 29190, // giant guy + SPELL_STOMP = 53634, + SPELL_THUNDERCLAP = 36706, + SPELL_HERO_AGGRO_AURA = 53627, + + NPC_ACHERUS_GHOUL = 29219, // just ghoul.... + SPELL_GHOULPLOSION = 53632, + + NPC_WARRIOR_OF_THE_FROZEN_WASTES = 29206, // use SPELL_CLEAVE 53631 + + NPC_HIGHLORD_ALEXANDROS_MOGRAINE = 29227, // ghost + NPC_DARION_MOGRAINE = 29228, // ghost + + // ---- Dawn npc -------------------- + // Highlord Tirion Fordring + NPC_HIGHLORD_TIRION_FORDRING = 29175, + EQUIP_HIGHLORD_TIRION_FORDRING = 13262, + SPELL_LAY_ON_HANDS = 53778, + SPELL_REBIRTH_OF_THE_ASHBRINGER = 53702, + SPELL_TIRION_CHARGE = 53705, + SPELL_TIRION_CHARGE_VISUAL = 53706, + + // others + NPC_KORFAX_CHAMPION_OF_THE_LIGHT = 29176, + SPELL_CLEAVE = 53631, + SPELL_HEROIC_LEAP = 53625, + + NPC_LORD_MAXWELL_TYROSUS = 29178, + NPC_LEONID_BARTHALOMEW_THE_REVERED = 29179, + NPC_DUKE_NICHOLAS_ZVERENHOFF = 29180, + + NPC_COMMANDER_ELIGOR_DAWNBRINGER = 29177, + SPELL_HOLY_LIGHT2 = 37979, + + NPC_RAYNE = 29181, + SPELL_REJUVENATION = 20664, + SPELL_STARFALL = 20678, + SPELL_TRANQUILITY = 25817, + SPELL_WRATH = 21807, + + NPC_DEFENDER_OF_THE_LIGHT = 29174, // also does SPELL_HEROIC_LEAP 53625 + SPELL_HOLY_LIGHT1 = 29427, + SPELL_HOLY_STRIKE = 53643, + SPELL_HOLY_WRATH = 53638, + SPELL_UPPERCUT = 53629, + + NPC_RIMBLAT_EARTHSHATTER = 29182, + SPELL_CHAIN_HEAL = 33642, + SPELL_THUNDER = 53630 +}; + +struct Locations +{ + float x, y, z, o; + uint32 id; +}; + +void UpdateWorldState(Map *map, uint32 id, uint32 state) +{ + Map::PlayerList const& players = map->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->SendUpdateWorldState(id,state); + } + } +} + +static Locations LightofDawnLoc[]= +{ + {2281.335, -5300.409, 85.170, 0}, // 0 Tirion Fordring loc + {2283.896, -5287.914, 83.066, 1.55}, // 1 Tirion Fordring loc2 + {2281.461, -5263.014, 81.164, 0}, // 2 Tirion charges + {2262.277, -5293.477, 82.167, 0}, // 3 Tirion run + {2270.286, -5287.73, 82.262, 0}, // 4 Tirion relocate + {2269.511, -5288.289, 82.225, 0}, // 5 Tirion forward + {2262.277, -5293.477, 82.167, 0}, // 6 Tirion runs to Darion + {2270.286, -5287.73, 82.262, 0}, + {2269.511, -5288.289, 82.225, 0}, + {2273.205, -5288.848, 82.617, 0}, // 9 Korfax loc1 + {2274.739, -5287.926, 82.684, 0}, // 10 Korfax loc2 + {2253.673, -5318.004, 81.724, 0}, // 11 Korfax kicked + {2287.028, -5309.644, 87.253, 0}, // 12 Maxwell loc1 + {2286.978, -5308.025, 86.83, 0}, // 13 Maxwell loc2 + {2248.877, -5307.586, 82.166, 0}, // 14 maxwell kicked + {2278.58, -5316.933, 88.319, 0}, // 15 Eligor loc1 + {2278.535, -5315.479, 88.08, 0}, // 16 Eligor loc2 + {2259.416, -5304.505, 82.149, 0}, // 17 eligor kicked + {2289.259, -5280.355, 82.112, 0}, // 18 Koltira loc1 + {2289.02, -5281.985, 82.207, 0}, // 19 Koltira loc2 + {2273.289, -5273.675, 81.701, 0}, // 20 Thassarian loc1 + {2273.332, -5275.544, 81.849, 0}, // 21 Thassarian loc2 + {2281.198, -5257.397, 80.224, 4.66}, // 22 Alexandros loc1 + {2281.156, -5259.934, 80.647, 0}, // 23 Alexandros loc2 + {2281.294, -5281.895, 82.445, 1.35}, // 24 Darion loc1 + {2281.093, -5263.013, 81.125, 0}, // 25 Darion loc1 + {2281.313, -5250.282, 79.322, 4.69}, // 26 Lich King spawns + {2281.523, -5261.058, 80.877, 0}, // 27 Lich king move forwards + {2272.709, -5255.552, 78.226, 0}, // 28 Lich king kicked + {2273.972, -5257.676, 78.862, 0} // 29 Lich king moves forward +}; + +struct npc_highlord_darion_mograineAI : public npc_escortAI +{ + npc_highlord_darion_mograineAI(Creature *pCreature) : npc_escortAI(pCreature) + { + Reset(); + } + + bool bIsBattle; + uint32 uiStep; + uint32 uiPhase_timer; + uint32 uiFight_duration; + uint32 uiTotal_dawn; + uint32 uiTotal_scourge; + uint32 uiSummon_counter; + + // Darion Mograine + uint32 uiAnti_magic_zone; + uint32 uiDeath_strike; + uint32 uiDeath_embrace; + uint32 uiIcy_touch; + uint32 uiUnholy_blight; + uint32 uiFight_speech; + uint32 uiSpawncheck; + uint32 uiTargetcheck; + + // Dawn + uint64 uiTirionGUID; + uint64 uiAlexandrosGUID; + uint64 uiDarionGUID; + uint64 uiKorfaxGUID; + uint64 uiMaxwellGUID; + uint64 uiEligorGUID; + uint64 uiRayneGUID; + uint64 uiDefenderGUID[ENCOUNTER_DEFENDER_NUMBER]; + uint64 uiEarthshatterGUID[ENCOUNTER_EARTHSHATTER_NUMBER]; + + // Death + uint64 uiKoltiraGUID; + uint64 uiOrbazGUID; + uint64 uiThassarianGUID; + uint64 uiLichKingGUID; + uint64 uiAbominationGUID[ENCOUNTER_ABOMINATION_NUMBER]; + uint64 uiBehemothGUID[ENCOUNTER_BEHEMOTH_NUMBER]; + uint64 uiGhoulGUID[ENCOUNTER_GHOUL_NUMBER]; + uint64 uiWarriorGUID[ENCOUNTER_WARRIOR_NUMBER]; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + bIsBattle = false; + uiStep = 0; + uiPhase_timer = 3000; + uiFight_duration = 300000; // 5 minutes + uiTotal_dawn = ENCOUNTER_TOTAL_DAWN; + uiTotal_scourge = ENCOUNTER_TOTAL_SCOURGE; + uiSummon_counter = 0; + + uiAnti_magic_zone = urand(1000,6000); + uiDeath_strike = urand(5000,10000); + uiDeath_embrace = urand(5000,10000); + uiIcy_touch = urand(5000,10000); + uiUnholy_blight = urand(5000,10000); + + uiFight_speech = 15000; + uiSpawncheck = 1000; + uiTargetcheck = 10000; + + me->SetStandState(UNIT_STAND_STATE_STAND); + me->Mount(25279); + me->SetVisibility(VISIBILITY_ON); + + UpdateWorldState(me->GetMap(), WORLD_STATE_REMAINS, 0); + //UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 0); + UpdateWorldState(me->GetMap(), WORLD_STATE_EVENT_BEGIN, 0); + + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiRayneGUID)) + pTemp->setDeathState(JUST_DIED); + + uiTirionGUID = NULL; + uiKorfaxGUID = NULL; + uiMaxwellGUID = NULL; + uiEligorGUID = NULL; + uiRayneGUID = NULL; + + for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiDefenderGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiDefenderGUID[i] = 0; + } + for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiEarthshatterGUID[i] = 0; + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->setDeathState(JUST_DIED); + + uiKoltiraGUID = NULL; + uiOrbazGUID = NULL; + uiThassarianGUID = NULL; + uiLichKingGUID = NULL; + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiAbominationGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiAbominationGUID[i] = 0; + } + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiBehemothGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiBehemothGUID[i] = 0; + } + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiGhoulGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiGhoulGUID[i] = 0; + } + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiWarriorGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiWarriorGUID[i] = 0; + } + } + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who == me) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void MoveInLineOfSight(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack() && me->IsHostileTo(who)) + if (me->IsWithinDistInMap(who, 20) && me->IsWithinLOSInMap(who)) + AttackStart(who); + } + + void SetHoldState(bool bOnHold) + { + SetEscortPaused(bOnHold); + } + + void WaypointReached(uint32 i) + { + switch (i) + { + case 0: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + SetHoldState(true); + break; + case 1: + SetHoldState(true); + + SpawnNPC(); + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN07, pTemp); + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN08, pTemp); + + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + NPCChangeTarget(uiGhoulGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + NPCChangeTarget(uiWarriorGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + NPCChangeTarget(uiAbominationGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + NPCChangeTarget(uiBehemothGUID[i]); + NPCChangeTarget(uiKoltiraGUID); + NPCChangeTarget(uiOrbazGUID); + NPCChangeTarget(uiThassarianGUID); + + me->Unmount(); + me->CastSpell(me, SPELL_THE_MIGHT_OF_MOGRAINE, true); // need to fix, on player only + + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + pTemp->Unmount(); + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + pTemp->Unmount(); + + bIsBattle = true; + break; + case 2: + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + DoCast(me, SPELL_THE_LIGHT_OF_DAWN); + break; + case 3: + { + //Unit* pTirion = Unit::GetCreature(*me, uiTirionGUID); + + DoScriptText(EMOTE_LIGHT_OF_DAWN05, me); + if (me->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) + me->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + { + if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) + pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[19].x, LightofDawnLoc[19].y, LightofDawnLoc[19].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + { + if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) + pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[21].x, LightofDawnLoc[21].y, LightofDawnLoc[21].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + { + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[10].x, LightofDawnLoc[10].y, LightofDawnLoc[10].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + { + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[13].x, LightofDawnLoc[13].y, LightofDawnLoc[13].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + { + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[16].x, LightofDawnLoc[16].y, LightofDawnLoc[16].z); + } + JumpToNextStep(10000); + } break; + case 4: + DoScriptText(SAY_LIGHT_OF_DAWN27, me); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); + SetHoldState(true); + break; + case 5: + DoScriptText(SAY_LIGHT_OF_DAWN33, me); + SetHoldState(true); + break; + case 6: + SetHoldState(true); + me->HandleEmoteCommand(EMOTE_ONESHOT_SPECIALATTACK1H); + JumpToNextStep(1000); + break; + case 7: + SetHoldState(true); + JumpToNextStep(2000); + break; + case 8: + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + me->CastSpell(pTemp, SPELL_ASHBRINGER, true); + DoScriptText(EMOTE_LIGHT_OF_DAWN14, me); + SetHoldState(true); + break; + } + } + + void EnterEvadeMode() + { + if (!bIsBattle)//do not reset self if we are in battle + npc_escortAI::EnterEvadeMode(); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (!bIsBattle) + { + if (uiPhase_timer <= diff) + { + // ******* Before battle ***************************************************************** + switch (uiStep) + { + case 0: // countdown + //UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 1); + break; + + case 1: // just delay + //UpdateWorldState(me->GetMap(), WORLD_STATE_REMAINS, 1); + UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 0); + UpdateWorldState(me->GetMap(), WORLD_STATE_EVENT_BEGIN, 1); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + JumpToNextStep(3000); + break; + + case 2: + DoScriptText(SAY_LIGHT_OF_DAWN04, me); + if (Creature* pKoltira = GetClosestCreatureWithEntry(me, NPC_KOLTIRA_DEATHWEAVER, 50.0f)) + uiKoltiraGUID = pKoltira->GetGUID(); + if (Creature* pOrbaz = GetClosestCreatureWithEntry(me, NPC_ORBAZ_BLOODBANE, 50.0f)) + uiOrbazGUID = pOrbaz->GetGUID(); + if (Creature* pThassarian = GetClosestCreatureWithEntry(me, NPC_THASSARIAN, 50.0f)) + uiThassarianGUID = pThassarian->GetGUID(); + JumpToNextStep(10000); + break; + + case 3: // rise + DoScriptText(SAY_LIGHT_OF_DAWN05, me); + JumpToNextStep(3000); + break; + + case 4: // summon ghoul + // Dunno whats the summon spell, so workaround + DoCast(me, 33271); // shack effect + uiPhase_timer = 500; + if (uiSummon_counter < ENCOUNTER_GHOUL_NUMBER) + { + Unit* pTemp = me->SummonCreature(NPC_ACHERUS_GHOUL, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->setFaction(2084); + uiGhoulGUID[uiSummon_counter] = pTemp->GetGUID(); + ++uiSummon_counter; + } + else + { + uiSummon_counter = 0; + ++uiStep; + } + break; + + case 5: // summon abomination + DoCast(me, 33271); // shack effect + uiPhase_timer = 500; + if (uiSummon_counter < ENCOUNTER_ABOMINATION_NUMBER) + { + Unit* pTemp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->setFaction(2084); + uiAbominationGUID[uiSummon_counter] = pTemp->GetGUID(); + ++uiSummon_counter; + } + else + { + uiSummon_counter = 0; + ++uiStep; + } + break; + + case 6: // summon warrior + DoCast(me, 33271); // shack effect + uiPhase_timer = 500; + if (uiSummon_counter < ENCOUNTER_WARRIOR_NUMBER) + { + Unit* pTemp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->setFaction(2084); + uiWarriorGUID[uiSummon_counter] = pTemp->GetGUID(); + ++uiSummon_counter; + } + else + { + uiSummon_counter = 0; + ++uiStep; + } + break; + + case 7: // summon warrior + DoCast(me, 33271); // shack effect + uiPhase_timer = 500; + if (uiSummon_counter < ENCOUNTER_BEHEMOTH_NUMBER) + { + Unit* pTemp = me->SummonCreature(NPC_FLESH_BEHEMOTH, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->setFaction(2084); + uiBehemothGUID[uiSummon_counter] = pTemp->GetGUID(); + ++uiSummon_counter; + } + else + { + uiSummon_counter = 0; + ++uiStep; + } + break; + + case 8: // summon announce + DoScriptText(SAY_LIGHT_OF_DAWN06, me); + JumpToNextStep(5000); + break; + + case 9: // charge begins + SetHoldState(false); + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + { + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) + { + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + { + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + } + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiAbominationGUID[i])) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiBehemothGUID[i])) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiGhoulGUID[i])) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiWarriorGUID[i])) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + JumpToNextStep(5000); + break; + + // ******* After battle ***************************************************************** + case 11: // Tirion starts to speak + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN28, pTemp); + JumpToNextStep(21000); + break; + + case 12: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN29, pTemp); + JumpToNextStep(13000); + break; + + case 13: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN30, pTemp); + JumpToNextStep(13000); + break; + + case 14: + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_LIGHT_OF_DAWN31, me); + JumpToNextStep(7000); + break; + + case 15: // summon gate + if (Unit* pTemp = me->SummonCreature(NPC_HIGHLORD_ALEXANDROS_MOGRAINE, LightofDawnLoc[22].x, LightofDawnLoc[22].y, LightofDawnLoc[22].z, LightofDawnLoc[22].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) + { + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->CastSpell(pTemp, SPELL_ALEXANDROS_MOGRAINE_SPAWN, true); + DoScriptText(EMOTE_LIGHT_OF_DAWN06, pTemp); + uiAlexandrosGUID = pTemp->GetGUID(); + } + JumpToNextStep(4000); + break; + + case 16: // Alexandros out + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[23].x, LightofDawnLoc[23].y, LightofDawnLoc[23].z); + DoScriptText(SAY_LIGHT_OF_DAWN32, pTemp); + } + SetHoldState(false); // makes darion turns back + JumpToNextStep(5000); + break; + + case 17: + me->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(SAY_LIGHT_OF_DAWN34, me); + JumpToNextStep(5000); + break; + + case 18: // Darion's spirit out + if (Unit* pTemp = me->SummonCreature(NPC_DARION_MOGRAINE, LightofDawnLoc[24].x, LightofDawnLoc[24].y, LightofDawnLoc[24].z, LightofDawnLoc[24].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) + { + DoScriptText(SAY_LIGHT_OF_DAWN35, pTemp); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + uiDarionGUID = pTemp->GetGUID(); + } + JumpToNextStep(4000); + break; + + case 19: // runs to father + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + { + DoScriptText(EMOTE_LIGHT_OF_DAWN07, pTemp); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[25].x, LightofDawnLoc[25].y, LightofDawnLoc[25].z); + } + JumpToNextStep(4000); + break; + + case 20: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN36, pTemp); + JumpToNextStep(4000); + break; + + case 21: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + DoScriptText(EMOTE_LIGHT_OF_DAWN08, pTemp); + JumpToNextStep(4000); + break; + + case 22: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN37, pTemp); + JumpToNextStep(8000); + break; + + case 23: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN38, pTemp); + JumpToNextStep(8000); + break; + + case 24: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN39, pTemp); + + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) // Tirion moves forward here + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[1].x, LightofDawnLoc[1].y, LightofDawnLoc[1].z); + + JumpToNextStep(15000); + break; + + case 25: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN40, pTemp); + JumpToNextStep(11000); + break; + + case 26: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN41, pTemp); + JumpToNextStep(5000); + break; + + case 27: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + pTemp->setDeathState(JUST_DIED); + JumpToNextStep(24000); + break; + + case 28: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN42, pTemp); + JumpToNextStep(6000); + break; + + case 29: // lich king spawns + if (Unit* pTemp = me->SummonCreature(NPC_THE_LICH_KING, LightofDawnLoc[26].x, LightofDawnLoc[26].y, LightofDawnLoc[26].z, LightofDawnLoc[26].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) + { + DoScriptText(SAY_LIGHT_OF_DAWN43, pTemp); + uiLichKingGUID = pTemp->GetGUID(); + if (Unit* pAlex = Unit::GetCreature(*me, uiAlexandrosGUID)) + pTemp->CastSpell(pAlex, SPELL_SOUL_FEAST_ALEX, false); + } + JumpToNextStep(2000); + break; + + case 30: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) // just hide him + { + DoScriptText(EMOTE_LIGHT_OF_DAWN09, pTemp); + pTemp->SetVisibility(VISIBILITY_OFF); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + pTemp->InterruptNonMeleeSpells(false); + DoScriptText(SAY_LIGHT_OF_DAWN45, pTemp); + } + JumpToNextStep(3000); + break; + + case 31: + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(EMOTE_LIGHT_OF_DAWN10, me); + DoScriptText(SAY_LIGHT_OF_DAWN44, me); + JumpToNextStep(3000); + break; + + case 32: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[27].x, LightofDawnLoc[27].y, LightofDawnLoc[27].z); + JumpToNextStep(6000); + break; + + case 33: // Darion supports to jump to lich king here + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoCast(me, SPELL_MOGRAINE_CHARGE); // jumping charge +// doesn't make it looks well, so workarounds, Darion charges, looks better + me->SetSpeed(MOVE_RUN, 3.0f); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + SetHoldState(false); + JumpToNextStep(0); + break; + + case 35: // Lich king counterattacks + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + pTemp->HandleEmoteCommand(EMOTE_ONESHOT_KICK); + DoScriptText(SAY_LIGHT_OF_DAWN46, pTemp); + } + me->SetSpeed(MOVE_RUN, 6.0f); + me->SetStandState(UNIT_STAND_STATE_DEAD); + SetHoldState(false); // Darion got kicked by lich king + JumpToNextStep(0); + break; + + case 37: // Lich king counterattacks + me->SetStandState(UNIT_STAND_STATE_KNEEL); + JumpToNextStep(3000); + break; + + case 38: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN47, pTemp); + JumpToNextStep(8000); + break; + + case 39: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN48, pTemp); + JumpToNextStep(15000); + break; + + case 40: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN49, pTemp); + JumpToNextStep(17000); + break; + + case 41: // Lich king - Apocalypse + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + DoScriptText(EMOTE_LIGHT_OF_DAWN11, pTemp); + DoScriptText(SAY_LIGHT_OF_DAWN51, pTemp); + if (Unit* pTirion = Unit::GetCreature(*me, uiTirionGUID)) + { + pTirion->SetStandState(UNIT_STAND_STATE_KNEEL); + //pTemp->CastSpell(pTirion, SPELL_APOCALYPSE, false); // not working + pTemp->CastSpell(pTirion, SPELL_SOUL_FEAST_TIRION, false); + DoScriptText(EMOTE_LIGHT_OF_DAWN12, pTirion); + } + } + JumpToNextStep(2000); + break; + + case 42: // Maxwell yells for attack + { + float fLichPositionX = 0, + fLichPositionY = 0, + fLichPositionZ = 0; + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + fLichPositionX = pTemp->GetPositionX(); + fLichPositionY = pTemp->GetPositionY(); + fLichPositionZ = pTemp->GetPositionZ(); + } + + if (fLichPositionX && fLichPositionY) + { + Unit* pTemp; + pTemp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->setFaction(me->getFaction()); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + uiDefenderGUID[0] = pTemp->GetGUID(); + + pTemp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->setFaction(me->getFaction()); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + uiEarthshatterGUID[0] = pTemp->GetGUID(); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + DoScriptText(SAY_LIGHT_OF_DAWN50, pTemp); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->HandleEmoteCommand(EMOTE_STATE_ATTACK_UNARMED); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + } + } + JumpToNextStep(4500); + break; + + case 43: // They all got kicked + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(EMOTE_LIGHT_OF_DAWN13, pTemp); + + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[14].x, LightofDawnLoc[14].y, LightofDawnLoc[14].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[11].x, LightofDawnLoc[11].y, LightofDawnLoc[11].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[17].x, LightofDawnLoc[17].y, LightofDawnLoc[17].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiDefenderGUID[0])) + { + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[0])) + { + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z); + } + JumpToNextStep(3000); + break; + + case 44: // make them stand up + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + JumpToNextStep(1000); + break; + + case 45: + DoScriptText(SAY_LIGHT_OF_DAWN52, me); + JumpToNextStep(5000); + break; + + case 46: // Darion stand up, "not today" + me->SetSpeed(MOVE_RUN, 1.0f); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_LIGHT_OF_DAWN53, me); + SetHoldState(false); // Darion throws sword + JumpToNextStep(7000); + break; + + case 47: // Ashbringer rebirth + me->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(EMOTE_LIGHT_OF_DAWN15, me); + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_HIGHLORD_TIRION_FORDRING)); + pTemp->CastSpell(pTemp, SPELL_REBIRTH_OF_THE_ASHBRINGER, false); + } + JumpToNextStep(1000); + break; + + case 48: // Show the cleansing effect (dawn of light) + //if (GameObject* pGo = me->GetMap()->GetGameObject(uiDawnofLightGUID)) + // pGo->SetPhaseMask(128, true); + me->SummonGameObject(GO_LIGHT_OF_DAWN, 2283.896, -5287.914, 83.066, 0, 0, 0, 0, 0, 30000); + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + if (pTemp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER, 0)) + pTemp->RemoveAurasDueToSpell(SPELL_REBIRTH_OF_THE_ASHBRINGER); + pTemp->CastSpell(pTemp, 41542, false); // workarounds, light expoded, makes it cool + pTemp->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->InterruptNonMeleeSpells(false); + JumpToNextStep(2500); + break; + + case 49: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN54, pTemp); + JumpToNextStep(4000); + break; + + case 50: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN55, pTemp); + JumpToNextStep(5000); + break; + + case 51: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN56, pTemp); + JumpToNextStep(1000); + break; + + case 52: // Tiron charges + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + DoScriptText(EMOTE_LIGHT_OF_DAWN16, pTemp); + pTemp->CastSpell(pTemp, SPELL_TIRION_CHARGE, false); // jumping charge + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); + pTemp->SetSpeed(MOVE_RUN, 3.0f); // workarounds, make Tirion still running + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2].x, LightofDawnLoc[2].y, LightofDawnLoc[2].z); + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->Relocate(LightofDawnLoc[28].x, LightofDawnLoc[28].y, LightofDawnLoc[28].z); // workarounds, he should kick back by Tirion, but here we relocate him + } + JumpToNextStep(1500); + break; + + case 53: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN57, pTemp); + JumpToNextStep(1000); + break; + + case 54: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + pTemp->SetSpeed(MOVE_RUN, 1.0f); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29].x, LightofDawnLoc[29].y, LightofDawnLoc[29].z); // 26 + } + JumpToNextStep(4000); + break; + + case 55: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); + JumpToNextStep(2000); + break; + + case 56: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + JumpToNextStep(1500); + break; + + case 57: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN58, pTemp); + JumpToNextStep(10000); + break; + + case 58: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN59, pTemp); + JumpToNextStep(10000); + break; + + case 59: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->CastSpell(pTemp, SPELL_TELEPORT_VISUAL, false); + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) // Tirion runs to Darion + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + pTemp->SetSpeed(MOVE_RUN, 1.0f); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[6].x, LightofDawnLoc[6].y, LightofDawnLoc[6].z); + } + JumpToNextStep(2500); + break; + + case 60: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) // Lich king disappears here + { + DoScriptText(EMOTE_LIGHT_OF_DAWN17, pTemp); + pTemp->Kill(pTemp); + } + JumpToNextStep(10000); + break; + + case 61: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN60, pTemp); + JumpToNextStep(3000); + break; + + case 62: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[7].x, LightofDawnLoc[7].y, LightofDawnLoc[7].z); + } + JumpToNextStep(5500); + break; + + case 63: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[8].x, LightofDawnLoc[8].y, LightofDawnLoc[8].z); + DoScriptText(SAY_LIGHT_OF_DAWN61, pTemp); + } + JumpToNextStep(15000); + break; + + case 64: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN62, pTemp); + JumpToNextStep(7000); + break; + + case 65: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN63, pTemp); + JumpToNextStep(10000); + break; + + case 66: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN64, pTemp); + JumpToNextStep(11000); + break; + + case 67: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN65, pTemp); + JumpToNextStep(10000); + break; + + case 68: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN66, pTemp); + JumpToNextStep(8000); + break; + + case 69: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN67, pTemp); + JumpToNextStep(10000); + break; + + case 70: + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_LIGHT_OF_DAWN68, me); + JumpToNextStep(10000); + break; + + case 71: + //if (GameObject* pGo = me->GetMap()->GetGameObject(uiDawnofLightGUID)) // Turn off dawn of light + // pGo->SetPhaseMask(0, true); + + { + Map *map = me->GetMap(); // search players with in 50 yards for quest credit + Map::PlayerList const &PlayerList = map->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->isAlive() && me->IsWithinDistInMap(i->getSource(), 50)) + i->getSource()->CastSpell(i->getSource(), SPELL_THE_LIGHT_OF_DAWN_Q, false); + } + } + me->SetVisibility(VISIBILITY_OFF); // respawns another Darion for quest turn in + me->SummonCreature(NPC_HIGHLORD_DARION_MOGRAINE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); + JumpToNextStep(1000); + break; + + case 72: + SetHoldState(false); // Escort ends + JumpToNextStep(25000); + break; + + case 73: + me->ForcedDespawn(); + break; + } + + } else uiPhase_timer -= diff; + } + + // ******* During battle ***************************************************************** + else + { + if (uiAnti_magic_zone <= diff) + { + DoCast(me, SPELL_ANTI_MAGIC_ZONE1); + uiAnti_magic_zone = 25000 + rand()%5000; + } else uiAnti_magic_zone -= diff; + + if (uiDeath_strike <= diff) + { + DoCast(me->getVictim(), SPELL_DEATH_STRIKE); + uiDeath_strike = 5000 + rand()%5000; + } else uiDeath_strike -= diff; + + if (uiDeath_embrace <= diff) + { + DoCast(me->getVictim(), SPELL_DEATH_EMBRACE); + uiDeath_embrace = 5000 + rand()%5000; + } else uiDeath_embrace -= diff; + + if (uiIcy_touch <= diff) + { + DoCast(me->getVictim(), SPELL_ICY_TOUCH1); + uiIcy_touch = 5000 + rand()%5000; + } else uiIcy_touch -= diff; + + if (uiUnholy_blight <= diff) + { + DoCast(me->getVictim(), SPELL_UNHOLY_BLIGHT); + uiUnholy_blight = 5000 + rand()%5000; + } else uiUnholy_blight -= diff; + + if (uiFight_speech <= diff) + { + DoScriptText(RAND(SAY_LIGHT_OF_DAWN09,SAY_LIGHT_OF_DAWN10,SAY_LIGHT_OF_DAWN11, + SAY_LIGHT_OF_DAWN12,SAY_LIGHT_OF_DAWN13,SAY_LIGHT_OF_DAWN14, + SAY_LIGHT_OF_DAWN15,SAY_LIGHT_OF_DAWN16,SAY_LIGHT_OF_DAWN17, + SAY_LIGHT_OF_DAWN18,SAY_LIGHT_OF_DAWN19,SAY_LIGHT_OF_DAWN20, + SAY_LIGHT_OF_DAWN21,SAY_LIGHT_OF_DAWN22,SAY_LIGHT_OF_DAWN23, + SAY_LIGHT_OF_DAWN24), me); + uiFight_speech = 15000 + rand()%5000; + } else uiFight_speech -= diff; + + // Check spawns + if (uiSpawncheck <= diff) + { + SpawnNPC(); + uiSpawncheck = 1000; + } else uiSpawncheck -= diff; + + // Check targets + if (uiTargetcheck <= diff) + { + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + NPCChangeTarget(uiGhoulGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + NPCChangeTarget(uiWarriorGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + NPCChangeTarget(uiAbominationGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + NPCChangeTarget(uiBehemothGUID[i]); + NPCChangeTarget(uiKoltiraGUID); + NPCChangeTarget(uiOrbazGUID); + NPCChangeTarget(uiThassarianGUID); + + uiTargetcheck = 10000; + } else uiTargetcheck -= diff; + + // Battle end + if (uiFight_duration <= diff + 5000) + { + if (!uiTirionGUID) + if (Unit* pTemp = me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING, LightofDawnLoc[0].x, LightofDawnLoc[0].y, LightofDawnLoc[0].z, 1.528, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000)) + { + pTemp->setFaction(me->getFaction()); + pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); + DoScriptText(SAY_LIGHT_OF_DAWN25, pTemp); + uiTirionGUID = pTemp->GetGUID(); + } + } + if (uiFight_duration <= diff) + { + bIsBattle = false; + uiFight_duration = 300000; + + if (me->HasAura(SPELL_THE_MIGHT_OF_MOGRAINE, 0)) + me->RemoveAurasDueToSpell(SPELL_THE_MIGHT_OF_MOGRAINE); + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + me->InterruptNonMeleeSpells(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) + DespawnNPC(uiDefenderGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) + DespawnNPC(uiEarthshatterGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + DespawnNPC(uiAbominationGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + DespawnNPC(uiBehemothGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + DespawnNPC(uiGhoulGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + DespawnNPC(uiWarriorGUID[i]); + + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[9].x, LightofDawnLoc[9].y, LightofDawnLoc[9].z); + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[12].x, LightofDawnLoc[12].y, LightofDawnLoc[12].z); + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[15].x, LightofDawnLoc[15].y, LightofDawnLoc[15].z); + } + DespawnNPC(uiRayneGUID); + + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[18].x, LightofDawnLoc[18].y, LightofDawnLoc[18].z); + pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false); + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) + DoScriptText(EMOTE_LIGHT_OF_DAWN04, pTemp); + + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[20].x, LightofDawnLoc[20].y, LightofDawnLoc[20].z); + pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false); + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN26, pTemp); + + SetHoldState(false); + + } else uiFight_duration -= diff; + + DoMeleeAttackIfReady(); + } + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhase_timer = uiTimer; + ++uiStep; + } + + void NPCChangeTarget(uint64 ui_GUID) + { + if (Creature* pTemp = Unit::GetCreature(*me, ui_GUID)) + if (pTemp->isAlive()) + if (Unit* pTarger = SelectUnit(SELECT_TARGET_RANDOM,0)) + if (pTarger->isAlive()) + { + // pTemp->DeleteThreatList(); + pTemp->AddThreat(pTarger, 0.0f); + pTemp->AI()->AttackStart(pTarger); + pTemp->SetInCombatWith(pTarger); + pTarger->SetInCombatWith(pTemp); + // pTemp->GetMotionMaster()->MoveChase(pTarger, 20.0f); + } + } + + void SpawnNPC() + { + Unit* pTemp = NULL; + + // Death + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiGhoulGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_ACHERUS_GHOUL, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2084); + uiGhoulGUID[i] = pTemp->GetGUID(); + } + } + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiAbominationGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2084); + uiAbominationGUID[i] = pTemp->GetGUID(); + } + } + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiWarriorGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2084); + uiWarriorGUID[i] = pTemp->GetGUID(); + } + } + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiBehemothGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_FLESH_BEHEMOTH, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2084); + uiBehemothGUID[i] = pTemp->GetGUID(); + } + } + + // Dawn + for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiDefenderGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiDefenderGUID[i] = pTemp->GetGUID(); + } + } + for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiEarthshatterGUID[i] = pTemp->GetGUID(); + } + } + pTemp = Unit::GetCreature(*me, uiKorfaxGUID); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_KORFAX_CHAMPION_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiKorfaxGUID = pTemp->GetGUID(); + } + pTemp = Unit::GetCreature(*me, uiMaxwellGUID); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_LORD_MAXWELL_TYROSUS, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiMaxwellGUID = pTemp->GetGUID(); + } + pTemp = Unit::GetCreature(*me, uiEligorGUID); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_COMMANDER_ELIGOR_DAWNBRINGER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiEligorGUID = pTemp->GetGUID(); + } + pTemp = Unit::GetCreature(*me, uiRayneGUID); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_RAYNE, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiRayneGUID = pTemp->GetGUID(); + } + } + + void DespawnNPC(uint64 pGUID) + { + if (Creature* pTemp = Unit::GetCreature(*me, pGUID)) + if (pTemp->isAlive()) + { + pTemp->SetVisibility(VISIBILITY_OFF); + pTemp->Kill(pTemp); + } + } +}; + +bool GossipHello_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(12801) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(0, "I am ready.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_highlord_darion_mograineAI, pCreature->AI())->uiStep = 1; + CAST_AI(npc_highlord_darion_mograineAI, pCreature->AI())->Start(true, false, pPlayer->GetGUID()); + break; + } + return true; +} + +/*###### +## npc the lich king in dawn of light +######*/ +struct npc_the_lich_king_tirion_dawnAI : public ScriptedAI +{ + npc_the_lich_king_tirion_dawnAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + void Reset() {} + void AttackStart(Unit * /*who*/) {} // very sample, just don't make them aggreesive + void UpdateAI(const uint32 /*diff*/) {} + void JustDied(Unit* /*killer*/) {} +}; + +CreatureAI* GetAI_npc_highlord_darion_mograine(Creature* pCreature) +{ + return new npc_highlord_darion_mograineAI(pCreature); +} + +CreatureAI* GetAI_npc_the_lich_king_tirion_dawn(Creature* pCreature) +{ + return new npc_the_lich_king_tirion_dawnAI (pCreature); +} + +void AddSC_the_scarlet_enclave_c5() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_highlord_darion_mograine"; + newscript->GetAI = &GetAI_npc_highlord_darion_mograine; + newscript->pGossipHello = &GossipHello_npc_highlord_darion_mograine; + newscript->pGossipSelect = &GossipSelect_npc_highlord_darion_mograine; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_the_lich_king_tirion_dawn"; + newscript->GetAI = &GetAI_npc_the_lich_king_tirion_dawn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp new file mode 100644 index 00000000000..cdfd69234fb --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" + +/*#### +## npc_valkyr_battle_maiden +####*/ +#define SPELL_REVIVE 51918 +#define VALK_WHISPER "It is not yet your time, champion. Rise! Rise and fight once more!" + +struct npc_valkyr_battle_maidenAI : public PassiveAI +{ + npc_valkyr_battle_maidenAI(Creature *c) : PassiveAI(c) {} + + uint32 FlyBackTimer; + float x, y, z; + uint32 phase; + + void Reset() + { + me->setActive(true); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlying(true); + FlyBackTimer = 500; + phase = 0; + + me->GetPosition(x, y, z); + z += 4; x -= 3.5; y -= 5; + me->GetMotionMaster()->Clear(false); + me->GetMap()->CreatureRelocation(me, x, y, z, 0.0f); + } + + void UpdateAI(const uint32 diff) + { + if (FlyBackTimer <= diff) + { + Player *plr = NULL; + if (me->isSummon()) + if (Unit *summoner = CAST_SUM(me)->GetSummoner()) + if (summoner->GetTypeId() == TYPEID_PLAYER) + plr = CAST_PLR(summoner); + + if (!plr) + phase = 3; + + switch(phase) + { + case 0: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->HandleEmoteCommand(EMOTE_STATE_FLYGRABCLOSED); + FlyBackTimer = 500; + break; + case 1: + plr->GetClosePoint(x,y,z, me->GetObjectSize()); + z += 2.5; x -= 2; y -= 1.5; + me->GetMotionMaster()->MovePoint(0, x, y, z); + me->SetUInt64Value(UNIT_FIELD_TARGET, plr->GetGUID()); + me->SetVisibility(VISIBILITY_ON); + FlyBackTimer = 4500; + break; + case 2: + if (!plr->isRessurectRequested()) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_CUSTOMSPELL01); + DoCast(plr, SPELL_REVIVE, true); + me->MonsterWhisper(VALK_WHISPER, plr->GetGUID()); + } + FlyBackTimer = 5000; + break; + case 3: + me->SetVisibility(VISIBILITY_OFF); + FlyBackTimer = 3000; + break; + case 4: + me->DisappearAndDie(); + break; + default: + //Nothing To DO + break; + } + ++phase; + } else FlyBackTimer-=diff; + } +}; + +CreatureAI* GetAI_npc_valkyr_battle_maiden(Creature* pCreature) +{ + return new npc_valkyr_battle_maidenAI (pCreature); +} + +void AddSC_the_scarlet_enclave() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_valkyr_battle_maiden"; + newscript->GetAI = &GetAI_npc_valkyr_battle_maiden; + newscript->RegisterSelf(); + + // Chapter 3: Scarlet Armies Approach... - An End To All Things... + // Chapter 4: An End To All Things... - An End To All Things... +} diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp new file mode 100644 index 00000000000..cb6ed1daf22 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp @@ -0,0 +1,128 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Arcanist_Doan +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1189019, + SAY_SPECIALAE = -1189020, + + SPELL_POLYMORPH = 13323, + SPELL_AOESILENCE = 8988, + SPELL_ARCANEEXPLOSION = 9433, + SPELL_FIREAOE = 9435, + SPELL_ARCANEBUBBLE = 9438, +}; + +struct boss_arcanist_doanAI : public ScriptedAI +{ + boss_arcanist_doanAI(Creature *c) : ScriptedAI(c) {} + + uint32 Polymorph_Timer; + uint32 AoESilence_Timer; + uint32 ArcaneExplosion_Timer; + bool bCanDetonate; + bool bShielded; + + void Reset() + { + Polymorph_Timer = 20000; + AoESilence_Timer = 15000; + ArcaneExplosion_Timer = 3000; + bCanDetonate = false; + bShielded = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (bShielded && bCanDetonate) + { + DoCast(me, SPELL_FIREAOE); + bCanDetonate = false; + } + + if (me->HasAura(SPELL_ARCANEBUBBLE)) + return; + + //If we are <50% hp cast Arcane Bubble + if (!bShielded && me->GetHealth()*100 / me->GetMaxHealth() <= 50) + { + //wait if we already casting + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoScriptText(SAY_SPECIALAE, me); + DoCast(me, SPELL_ARCANEBUBBLE); + + bCanDetonate = true; + bShielded = true; + } + + if (Polymorph_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_POLYMORPH); + + Polymorph_Timer = 20000; + } else Polymorph_Timer -= diff; + + //AoESilence_Timer + if (AoESilence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_AOESILENCE); + AoESilence_Timer = 15000 + rand()%5000; + } else AoESilence_Timer -= diff; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANEEXPLOSION); + ArcaneExplosion_Timer = 8000; + } else ArcaneExplosion_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_arcanist_doan(Creature* pCreature) +{ + return new boss_arcanist_doanAI (pCreature); +} + +void AddSC_boss_arcanist_doan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_arcanist_doan"; + newscript->GetAI = &GetAI_boss_arcanist_doan; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp new file mode 100644 index 00000000000..6b6efa0f934 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Azshir_the_Sleepless +SD%Complete: 80 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CALLOFTHEGRAVE 17831 +#define SPELL_TERRIFY 7399 +#define SPELL_SOULSIPHON 7290 + +struct boss_azshir_the_sleeplessAI : public ScriptedAI +{ + boss_azshir_the_sleeplessAI(Creature *c) : ScriptedAI(c) {} + + uint32 SoulSiphon_Timer; + uint32 CallOftheGrave_Timer; + uint32 Terrify_Timer; + + void Reset() + { + SoulSiphon_Timer = 1; + CallOftheGrave_Timer = 30000; + Terrify_Timer = 20000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <50% hp cast Soul Siphon rank 1 + if (me->GetHealth()*100 / me->GetMaxHealth() <= 50 && !me->IsNonMeleeSpellCasted(false)) + { + //SoulSiphon_Timer + if (SoulSiphon_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOULSIPHON); + return; + + //SoulSiphon_Timer = 20000; + } else SoulSiphon_Timer -= diff; + } + + //CallOfTheGrave_Timer + if (CallOftheGrave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CALLOFTHEGRAVE); + CallOftheGrave_Timer = 30000; + } else CallOftheGrave_Timer -= diff; + + //Terrify_Timer + if (Terrify_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TERRIFY); + Terrify_Timer = 20000; + } else Terrify_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_azshir_the_sleepless(Creature* pCreature) +{ + return new boss_azshir_the_sleeplessAI (pCreature); +} + +void AddSC_boss_azshir_the_sleepless() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_azshir_the_sleepless"; + newscript->GetAI = &GetAI_boss_azshir_the_sleepless; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp new file mode 100644 index 00000000000..f7b6b7cce4b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp @@ -0,0 +1,124 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Bloodmage_Thalnos +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1189016, + SAY_HEALTH = -1189017, + SAY_KILL = -1189018, + + SPELL_FLAMESHOCK = 8053, + SPELL_SHADOWBOLT = 1106, + SPELL_FLAMESPIKE = 8814, + SPELL_FIRENOVA = 16079, +}; + +struct boss_bloodmage_thalnosAI : public ScriptedAI +{ + boss_bloodmage_thalnosAI(Creature *c) : ScriptedAI(c) {} + + bool HpYell; + uint32 FlameShock_Timer; + uint32 ShadowBolt_Timer; + uint32 FlameSpike_Timer; + uint32 FireNova_Timer; + + void Reset() + { + HpYell = false; + FlameShock_Timer = 10000; + ShadowBolt_Timer = 2000; + FlameSpike_Timer = 8000; + FireNova_Timer = 40000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*Victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <35% hp + if (!HpYell && ((me->GetHealth()*100) / me->GetMaxHealth() <= 35)) + { + DoScriptText(SAY_HEALTH, me); + HpYell = true; + } + + //FlameShock_Timer + if (FlameShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMESHOCK); + FlameShock_Timer = 10000 + rand()%5000; + } else FlameShock_Timer -= diff; + + //FlameSpike_Timer + if (FlameSpike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMESPIKE); + FlameSpike_Timer = 30000; + } else FlameSpike_Timer -= diff; + + //FireNova_Timer + if (FireNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRENOVA); + FireNova_Timer = 40000; + } else FireNova_Timer -= diff; + + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLT); + ShadowBolt_Timer = 2000; + } else ShadowBolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bloodmage_thalnos(Creature* pCreature) +{ + return new boss_bloodmage_thalnosAI (pCreature); +} + +void AddSC_boss_bloodmage_thalnos() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_bloodmage_thalnos"; + newscript->GetAI = &GetAI_boss_bloodmage_thalnos; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp new file mode 100644 index 00000000000..17bbf0c23c6 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp @@ -0,0 +1,892 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Headless_Horseman +SD%Complete: +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "SpellMgr.h" +#include "scarlet_monastery.h" + +//this texts are already used by 3975 and 3976 +#define SAY_ENTRANCE -1189001 +#define SAY_REJOINED -1189002 +#define SAY_LOST_HEAD -1189003 +#define SAY_CONFLAGRATION -1189004 +#define SAY_SPROUTING_PUMPKINS -1189005 +#define SAY_PLAYER_DEATH -1189006 +#define SAY_DEATH -1189007 + +uint32 RandomLaugh[] = {11965, 11975, 11976}; + + // Entryes +#define HH_MOUNTED 23682 +#define HH_UNHORSED 23800 +#define HEAD 23775 +#define PULSING_PUMPKIN 23694 +#define PUMPKIN_FIEND 23545 +#define HELPER 23686 +#define WISP_INVIS 24034 + + //Spells +#define SPELL_CLEAVE 42587 +#define SPELL_CONFLAGRATION 42380 //Phase 2, can't find real spell(Dim Fire?) +//#define SPELL_CONFL_SPEED 22587 //8% increase speed, value 22587 from SPELL_CONFLAGRATION mains that spell? +#define SPELL_SUMMON_PUMPKIN 42394 + +#define SPELL_WHIRLWIND 43116 +#define SPELL_IMMUNE 42556 +#define SPELL_BODY_REGEN 42403 +#define SPELL_CONFUSE 43105 + +#define SPELL_FLYING_HEAD 42399 //visual flying head +#define SPELL_HEAD 42413 //visual buff, "head" +#define SPELL_HEAD_IS_DEAD 42428 //at killing head, Phase 3 + +#define SPELL_PUMPKIN_AURA 42280 +#define SPELL_PUMPKIN_AURA_GREEN 42294 +#define SPELL_SQUASH_SOUL 42514 +#define SPELL_SPROUTING 42281 +#define SPELL_SPROUT_BODY 42285 + + //Effects +#define SPELL_RHYME_BIG 42909 +//#define SPELL_RHYME_SMALL 42910 +#define SPELL_HEAD_SPEAKS 43129 +#define SPELL_HEAD_LANDS 42400 +#define SPELL_BODY_FLAME 42074 +#define SPELL_HEAD_FLAME 42971 +//#define SPELL_ENRAGE_VISUAL 42438 // he uses this spell? +#define SPELL_WISP_BLUE 42821 +#define SPELL_WISP_FLIGHT_PORT 42818 +//#define SPELL_WISP_INVIS 42823 +#define SPELL_SMOKE 42355 +#define SPELL_DEATH 42566 //not correct spell + +struct Locations +{ + float x, y, z; +}; + +static Locations FlightPoint[]= +{ + {1754.00,1346.00,17.50}, + {1765.00,1347.00,19.00}, + {1784.00,1346.80,25.40}, + {1803.30,1347.60,33.00}, + {1824.00,1350.00,42.60}, + {1838.80,1353.20,49.80}, + {1852.00,1357.60,55.70}, + {1861.30,1364.00,59.40}, + {1866.30,1374.80,61.70}, + {1864.00,1387.30,63.20}, + {1854.80,1399.40,64.10}, + {1844.00,1406.90,64.10}, + {1824.30,1411.40,63.30}, + {1801.00,1412.30,60.40}, + {1782.00,1410.10,55.50}, + {1770.50,1405.20,50.30}, + {1765.20,1400.70,46.60}, + {1761.40,1393.40,41.70}, + {1759.10,1386.70,36.60}, + {1757.80,1378.20,29.00}, + {1758.00,1367.00,19.51} +}; + +static Locations Spawn[]= +{ + {1776.27,1348.74,19.20}, //spawn point for pumpkin shrine mob + {1765.28,1347.46,17.55} //spawn point for smoke +}; + +static const char* Text[]= +{ + "Horseman rise...", + "Your time is nigh...", + "You felt death once...", + "Now, know demise!" +}; + +#define EMOTE_LAUGHS "Headless Horseman laughs" + +struct mob_wisp_invisAI : public ScriptedAI +{ + mob_wisp_invisAI(Creature *c) : ScriptedAI(c) + { + Creaturetype = delay = spell = spell2 = 0; + //that's hack but there are no info about range of this spells in dbc + SpellEntry *wisp = GET_SPELL(SPELL_WISP_BLUE); + if (wisp) + wisp->rangeIndex = 6; //100 yards + SpellEntry *port = GET_SPELL(SPELL_WISP_FLIGHT_PORT); + if (port) + port->rangeIndex = 6; + } + + uint32 Creaturetype; + uint32 delay; + uint32 spell; + uint32 spell2; + void Reset(){} + void EnterCombat(Unit * /*who*/){} + void SetType(uint32 _type) + { + switch(Creaturetype = _type) + { + case 1: + spell = SPELL_PUMPKIN_AURA_GREEN; + break; + case 2: + delay = 15000; + spell = SPELL_BODY_FLAME; + spell2 = SPELL_DEATH; + break; + case 3: + delay = 15000; + spell = SPELL_SMOKE; + break; + case 4: + delay = 7000; + spell2 = SPELL_WISP_BLUE; + break; + } + if (spell) + DoCast(me, spell); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_WISP_FLIGHT_PORT && Creaturetype == 4) + me->SetDisplayId(2027); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || Creaturetype != 1 || !who->isTargetableForAttack()) + return; + + if (me->IsWithinDist(who, 0.1, false) && !who->HasAura(SPELL_SQUASH_SOUL)) + DoCast(who, SPELL_SQUASH_SOUL); + } + + void UpdateAI(const uint32 diff) + { + if (delay) + { + if (delay <= diff) + { + me->RemoveAurasDueToSpell(SPELL_SMOKE); + if (spell2) + DoCast(me, spell2); + delay = 0; + } else delay -= diff; + } + } +}; + +struct mob_headAI : public ScriptedAI +{ + mob_headAI(Creature *c) : ScriptedAI(c) {} + + uint64 bodyGUID; + + uint32 Phase; + uint32 laugh; + uint32 wait; + + bool withbody; + bool die; + + void Reset() + { + Phase = 0; + bodyGUID = 0; + die = false; + withbody = true; + wait = 1000; + laugh = urand(15000,30000); + } + + void EnterCombat(Unit * /*who*/) {} + void SaySound(int32 textEntry, Unit *pTarget = 0) + { + DoScriptText(textEntry, me, pTarget); + //DoCast(me, SPELL_HEAD_SPEAKS, true); + Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000); + if (speaker) + speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); + laugh += 3000; + } + + void DamageTaken(Unit* /*done_by*/,uint32 &damage) + { + if (withbody) + return; + + switch(Phase) + { + case 1: + if (((me->GetHealth() - damage)*100)/me->GetMaxHealth() < 67) + Disappear(); + break; + case 2: + if (((me->GetHealth() - damage)*100)/me->GetMaxHealth() < 34) + Disappear(); + break; + case 3: + if (damage >= me->GetHealth()) + { + die = true; + withbody = true; + wait = 300; + damage = me->GetHealth() - me->GetMaxHealth()/100; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->StopMoving(); + //me->GetMotionMaster()->MoveIdle(); + DoCast(me, SPELL_HEAD_IS_DEAD); + } + break; + } + } + + void SpellHit(Unit *caster, const SpellEntry* spell) + { + if (!withbody) + return; + + if (spell->Id == SPELL_FLYING_HEAD) + { + if (Phase < 3) ++Phase; + else Phase = 3; + withbody = false; + if (!bodyGUID) + bodyGUID = caster->GetGUID(); + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_HEAD_LANDS, true); + DoCast(me, SPELL_HEAD, false); + SaySound(SAY_LOST_HEAD); + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveFleeing(caster->getVictim()); + } + } + void Disappear();//we must set returned=true(this will prevent from "body calls head" while head flying to body), see function below + void UpdateAI(const uint32 diff) + { + if (!withbody) + { + if (wait <= diff) + { + wait = 1000; + if (!me->getVictim()) return; + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveFleeing(me->getVictim()); + } else wait -= diff; + + if (laugh <= diff) + { + laugh = urand(15000,30000); + DoPlaySoundToSet(me, RandomLaugh[urand(0,2)]); + //DoCast(me, SPELL_HEAD_SPEAKS, true); //this spell remove buff "head" + Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000); + if (speaker) + speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); + me->MonsterTextEmote(EMOTE_LAUGHS,NULL); + } else laugh -= diff; + } + else + { + if (die) + { + if (wait <= diff) + { + die = false; + if (Unit *body = Unit::GetUnit((*me), bodyGUID)) + body->Kill(body); + me->Kill(me); + } else wait -= diff; + } + } + } +}; + +struct boss_headless_horsemanAI : public ScriptedAI +{ + boss_headless_horsemanAI(Creature *c) : ScriptedAI(c) + { + SpellEntry *confl = GET_SPELL(SPELL_CONFLAGRATION); + if (confl) + { + confl->EffectApplyAuraName[0] = SPELL_AURA_PERIODIC_DAMAGE_PERCENT; + confl->EffectBasePoints[0] = 10; + //confl->EffectBaseDice[0] = 10; + confl->DmgMultiplier[0] = 1; + } +/* + if (SpellEntry *confl = GET_SPELL(SPELL_CONFLAGRATION)) + confl->EffectTriggerSpell[1] = 22587; + + if (SpellEntry *speed = GET_SPELL(22587)) + { + speed->Effect[1] = SPELL_EFFECT_APPLY_AURA; + speed->EffectApplyAuraName[1] = SPELL_AURA_MOD_CONFUSE; + } +*/ + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint64 headGUID; + uint64 PlayerGUID; + + uint32 Phase; + uint32 id; + uint32 count; + uint32 say_timer; + + uint32 conflagrate; + uint32 summonadds; + uint32 cleave; + uint32 regen; + uint32 whirlwind; + uint32 laugh; + uint32 burn; + + bool withhead; + bool returned; + bool IsFlying; + bool wp_reached; + bool burned; + + void Reset() + { + Phase = 1; + conflagrate = 15000; + summonadds = 15000; + laugh = urand(16000,20000); + cleave = 2000; + regen = 1000; + burn = 6000; + count = 0; + say_timer = 3000; + + withhead = true; + returned = true; + burned = false; + IsFlying = false; + DoCast(me, SPELL_HEAD); + if (headGUID) + { + if (Creature* Head = Unit::GetCreature((*me), headGUID)) + Head->DisappearAndDie(); + + headGUID = 0; + } + + //if (pInstance) + // pInstance->SetData(DATA_HORSEMAN_EVENT, NOT_STARTED); + } + + void FlyMode() + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + me->SetSpeed(MOVE_WALK,5.0f,true); + wp_reached = false; + count = 0; + say_timer = 3000; + id = 0; + Phase = 0; + } + + void MovementInform(uint32 type, uint32 i) + { + if (type != POINT_MOTION_TYPE || !IsFlying || i != id) + return; + + wp_reached = true; + + switch (id) + { + case 0: + me->SetVisibility(VISIBILITY_ON); + break; + case 1: + { + if (Creature *smoke = me->SummonCreature(HELPER,Spawn[1].x,Spawn[1].y,Spawn[1].z,0,TEMPSUMMON_TIMED_DESPAWN,20000)) + CAST_AI(mob_wisp_invisAI, smoke->AI())->SetType(3); + DoCast(me, SPELL_RHYME_BIG); + break; + } + case 6: + if (pInstance) + pInstance->SetData(GAMEOBJECT_PUMPKIN_SHRINE, 0); //hide gameobject + break; + case 19: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + break; + case 20: + { + Phase = 1; + IsFlying = false; + wp_reached = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SaySound(SAY_ENTRANCE); + if (Unit *plr = Unit::GetUnit((*me),PlayerGUID)) + DoStartMovement(plr); + break; + } + } + ++id; + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); + DoZoneInCombat(); + } + void AttackStart(Unit* who) {ScriptedAI::AttackStart(who);} + void MoveInLineOfSight(Unit *who) + { + if (withhead && Phase != 0) + ScriptedAI::MoveInLineOfSight(who); + } + void KilledUnit(Unit *plr) + { + if (plr->GetTypeId() == TYPEID_PLAYER) + { + if (withhead) + SaySound(SAY_PLAYER_DEATH); + //maybe possible when player dies from conflagration + else if (Creature *Head = Unit::GetCreature((*me), headGUID)) + CAST_AI(mob_headAI, Head->AI())->SaySound(SAY_PLAYER_DEATH); + } + } + + void SaySound(int32 textEntry, Unit *pTarget = 0) + { + DoScriptText(textEntry, me, pTarget); + laugh += 4000; + } + + Player* SelectRandomPlayer(float range = 0.0f, bool checkLoS = true) + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) return NULL; + + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + Map::PlayerList::const_iterator i; + if (PlayerList.isEmpty()) return NULL; + + std::list temp; + std::list::const_iterator j; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if ((me->IsWithinLOSInMap(i->getSource()) || !checkLoS) && me->getVictim() != i->getSource() && + me->IsWithinDistInMap(i->getSource(), range) && i->getSource()->isAlive()) + temp.push_back(i->getSource()); + + if (temp.size()) + { + j = temp.begin(); + advance(j, rand()%temp.size()); + return (*j); + } + return NULL; + } + + void SpellHitTarget(Unit* unit, const SpellEntry* spell) + { + if (spell->Id == SPELL_CONFLAGRATION && unit->HasAura(SPELL_CONFLAGRATION)) + SaySound(SAY_CONFLAGRATION,unit); + } + + void JustDied(Unit* /*killer*/) + { + me->StopMoving(); + //me->GetMotionMaster()->MoveIdle(); + SaySound(SAY_DEATH); + if (Creature *flame = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000)) + flame->CastSpell(flame,SPELL_BODY_FLAME,false); + if (Creature *wisp = DoSpawnCreature(WISP_INVIS,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000)) + CAST_AI(mob_wisp_invisAI, wisp->AI())->SetType(4); + if (pInstance) + pInstance->SetData(DATA_HORSEMAN_EVENT, DONE); + } + + void SpellHit(Unit *caster, const SpellEntry* spell) + { + if (withhead) + return; + + if (spell->Id == SPELL_FLYING_HEAD) + { + if (Phase < 3) + ++Phase; + else + Phase = 3; + withhead = true; + me->RemoveAllAuras(); + me->SetName("Headless Horseman"); + me->SetHealth(me->GetMaxHealth()); + SaySound(SAY_REJOINED); + DoCast(me, SPELL_HEAD); + caster->GetMotionMaster()->Clear(false); + caster->GetMotionMaster()->MoveFollow(me,6,urand(0,5)); + //DoResetThreat();//not sure if need + std::list::const_iterator itr; + for (itr = caster->getThreatManager().getThreatList().begin(); itr != caster->getThreatManager().getThreatList().end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive() && pUnit != caster) + me->AddThreat(pUnit,caster->getThreatManager().getThreat(pUnit)); + } + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && withhead) + { + withhead = false; + returned = false; + damage = me->GetHealth() - me->GetMaxHealth()/100; + me->RemoveAllAuras(); + me->SetName("Headless Horseman, Unhorsed"); + + if (!headGUID) + headGUID = DoSpawnCreature(HEAD,rand()%6,rand()%6,0,0,TEMPSUMMON_DEAD_DESPAWN,0)->GetGUID(); + Unit* Head = Unit::GetUnit((*me), headGUID); + if (Head && Head->isAlive()) + { + Head->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //Head->CastSpell(Head,SPELL_HEAD_INVIS,false); + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_IMMUNE, true); + DoCast(me, SPELL_BODY_REGEN, true); + DoCast(Head, SPELL_FLYING_HEAD, true); + DoCast(me, SPELL_CONFUSE, false); //test + done_by->ProcDamageAndSpell(me,PROC_FLAG_KILL,PROC_FLAG_KILLED,PROC_EX_NONE,0); + whirlwind = urand(4000,8000); + regen = 0; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (withhead) + { + switch(Phase) + { + case 0: + { + if (!IsFlying) + { + if (say_timer <= diff) + { + say_timer = 3000; + Player *plr = SelectRandomPlayer(100.0f,false); + if (count < 3) + { + if (plr) + plr->Say(Text[count],0); + } + else + { + DoCast(me, SPELL_RHYME_BIG); + if (plr) + { + plr->Say(Text[count],0); + plr->HandleEmoteCommand(ANIM_EMOTE_SHOUT); + } + wp_reached = true; + IsFlying = true; + count = 0; + break; + } + ++count; + } else say_timer -= diff; + } + else + { + if (wp_reached) + { + wp_reached = false; + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MovePoint(id,FlightPoint[id].x,FlightPoint[id].y,FlightPoint[id].z); + } + } + } + break; + case 1: + if (burned) + break; + if (burn <= diff) + { + if (Creature *flame = me->SummonCreature(HELPER,Spawn[0].x,Spawn[0].y,Spawn[0].z,0,TEMPSUMMON_TIMED_DESPAWN,17000)) + CAST_AI(mob_wisp_invisAI, flame->AI())->SetType(2); + burned = true; + } else burn -= diff; + break; + case 2: + if (conflagrate <= diff) + { + if (Unit *plr = SelectRandomPlayer(30.0f)) + DoCast(plr, SPELL_CONFLAGRATION, false); + conflagrate = urand(10000,16000); + } else conflagrate -= diff; + break; + case 3: + if (summonadds <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUMMON_PUMPKIN); + SaySound(SAY_SPROUTING_PUMPKINS); + summonadds = urand(25000,35000); + } else summonadds -= diff; + break; + } + + if (laugh <= diff) + { + laugh = urand(11000,22000); + me->MonsterTextEmote(EMOTE_LAUGHS,NULL); + DoPlaySoundToSet(me, RandomLaugh[rand()%3]); + } else laugh -= diff; + + if (UpdateVictim()) + { + DoMeleeAttackIfReady(); + if (cleave <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + cleave = urand(2000,6000); //1 cleave per 2.0-6.0sec + } else cleave -= diff; + } + } + else + { + if (regen <= diff) + { + regen = 1000; //"body calls head" + if (me->GetHealth()/me->GetMaxHealth() == 1 && !returned) + { + if (Phase > 1) + --Phase; + else + Phase = 1; + Creature* Head = Unit::GetCreature((*me), headGUID); + if (Head && Head->isAlive()) + { + CAST_AI(mob_headAI, Head->AI())->Phase = Phase; + CAST_AI(mob_headAI, Head->AI())->Disappear(); + } + return; + } + } + else regen -= diff; + + if (whirlwind <= diff) + { + whirlwind = urand(4000,8000); + if (urand(0,1)) + { + me->RemoveAurasDueToSpell(SPELL_CONFUSE); + DoCast(me, SPELL_WHIRLWIND, true); + DoCast(me, SPELL_CONFUSE); + } else + me->RemoveAurasDueToSpell(SPELL_WHIRLWIND); + } else whirlwind -= diff; + } + } +}; + +void mob_headAI::Disappear() +{ + if (withbody) + return; + if (bodyGUID) + { + Creature *body = Unit::GetCreature((*me), bodyGUID); + if (body && body->isAlive()) + { + withbody = true; + me->RemoveAllAuras(); + body->RemoveAurasDueToSpell(SPELL_IMMUNE);//hack, SpellHit doesn't calls if body has immune aura + DoCast(body, SPELL_FLYING_HEAD); + me->SetHealth(me->GetMaxHealth()); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->MoveIdle(); + CAST_AI(boss_headless_horsemanAI, body->AI())->returned = true; + } + } +} + +struct mob_pulsing_pumpkinAI : public ScriptedAI +{ + mob_pulsing_pumpkinAI(Creature *c) : ScriptedAI(c) {} + + bool sprouted; + uint64 debuffGUID; + + void Reset() + { + float x, y, z; + me->GetPosition(x, y, z); //this visual aura some under ground + me->GetMap()->CreatureRelocation(me, x,y,z + 0.35f, 0.0f); + Despawn(); + Creature *debuff = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,14500); + if (debuff) + { + debuff->SetDisplayId(me->GetDisplayId()); + debuff->CastSpell(debuff,SPELL_PUMPKIN_AURA_GREEN,false); + CAST_AI(mob_wisp_invisAI, debuff->AI())->SetType(1); + debuffGUID = debuff->GetGUID(); + } + sprouted = false; + DoCast(me, SPELL_PUMPKIN_AURA, true); + DoCast(me, SPELL_SPROUTING); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); + } + + void EnterCombat(Unit * /*who*/){} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_SPROUTING) + { + sprouted = true; + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); + DoCast(me, SPELL_SPROUT_BODY, true); + me->UpdateEntry(PUMPKIN_FIEND); + DoStartMovement(me->getVictim()); + } + } + + void Despawn() + { + if (!debuffGUID) return; + Unit *debuff = Unit::GetUnit((*me),debuffGUID); + if (debuff) + debuff->SetVisibility(VISIBILITY_OFF); + debuffGUID = 0; + } + + void JustDied(Unit * /*killer*/) { if (!sprouted) Despawn(); } + + void MoveInLineOfSight(Unit *who) + { + if (!who || !who->isTargetableForAttack() || !me->IsHostileTo(who) || me->getVictim()) + return; + + me->AddThreat(who,0.0f); + if (sprouted) + DoStartMovement(who); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (sprouted && UpdateVictim()) + DoMeleeAttackIfReady(); + } +}; + +bool GOHello_go_loosely_turned_soil(Player* pPlayer, GameObject* soil) +{ + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (pInstance) + { + if (pInstance->GetData(DATA_HORSEMAN_EVENT) != NOT_STARTED) + return true; + pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); + } +/* if (soil->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER && plr->getLevel() > 64) + { + plr->PrepareQuestMenu(soil->GetGUID()); + plr->SendPreparedQuest(soil->GetGUID()); + } + if (plr->GetQuestStatus(11405) == QUEST_STATUS_INCOMPLETE && plr->getLevel() > 64) + { */ + pPlayer->AreaExploredOrEventHappens(11405); + if (Creature *horseman = soil->SummonCreature(HH_MOUNTED,FlightPoint[20].x,FlightPoint[20].y,FlightPoint[20].z,0,TEMPSUMMON_MANUAL_DESPAWN,0)) + { + CAST_AI(boss_headless_horsemanAI, horseman->AI())->PlayerGUID = pPlayer->GetGUID(); + CAST_AI(boss_headless_horsemanAI, horseman->AI())->FlyMode(); + } + //} + return true; +} + +CreatureAI* GetAI_mob_head(Creature* pCreature) +{ + return new mob_headAI (pCreature); +} + +CreatureAI* GetAI_boss_headless_horseman(Creature* pCreature) +{ + return new boss_headless_horsemanAI (pCreature); +} + +CreatureAI* GetAI_mob_pulsing_pumpkin(Creature* pCreature) +{ + return new mob_pulsing_pumpkinAI (pCreature); +} + +CreatureAI* GetAI_mob_wisp_invis(Creature* pCreature) +{ + return new mob_wisp_invisAI (pCreature); +} + +void AddSC_boss_headless_horseman() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_headless_horseman"; + newscript->GetAI = &GetAI_boss_headless_horseman; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_head"; + newscript->GetAI = &GetAI_mob_head; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_pulsing_pumpkin"; + newscript->GetAI = &GetAI_mob_pulsing_pumpkin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_wisp_invis"; + newscript->GetAI = &GetAI_mob_wisp_invis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_loosely_turned_soil"; + newscript->pGOHello = &GOHello_go_loosely_turned_soil; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp new file mode 100644 index 00000000000..e0db29aa240 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp @@ -0,0 +1,158 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Herod +SD%Complete: 95 +SDComment: Should in addition spawn Myrmidons in the hallway outside +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +#define SAY_AGGRO -1189000 +#define SAY_WHIRLWIND -1189001 +#define SAY_ENRAGE -1189002 +#define SAY_KILL -1189003 +#define EMOTE_ENRAGE -1189004 + +#define SPELL_RUSHINGCHARGE 8260 +#define SPELL_CLEAVE 15496 +#define SPELL_WHIRLWIND 8989 +#define SPELL_FRENZY 8269 + +#define ENTRY_SCARLET_TRAINEE 6575 +#define ENTRY_SCARLET_MYRMIDON 4295 + +struct boss_herodAI : public ScriptedAI +{ + boss_herodAI(Creature *c) : ScriptedAI(c) {} + + bool Enrage; + + uint32 Cleave_Timer; + uint32 Whirlwind_Timer; + + void Reset() + { + Enrage = false; + Cleave_Timer = 12000; + Whirlwind_Timer = 60000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_RUSHINGCHARGE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*killer*/) + { + for (uint8 i = 0; i < 20; ++i) + me->SummonCreature(ENTRY_SCARLET_TRAINEE, 1939.18, -431.58, 17.09, 6.22, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <30% hp goes Enraged + if (!Enrage && me->GetHealth()*100 / me->GetMaxHealth() <= 30 && !me->IsNonMeleeSpellCasted(false)) + { + DoScriptText(EMOTE_ENRAGE, me); + DoScriptText(SAY_ENRAGE, me); + DoCast(me, SPELL_FRENZY); + Enrage = true; + } + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 12000; + } else Cleave_Timer -= diff; + + // Whirlwind_Timer + if (Whirlwind_Timer <= diff) + { + DoScriptText(SAY_WHIRLWIND, me); + DoCast(me->getVictim(), SPELL_WHIRLWIND); + Whirlwind_Timer = 30000; + } else Whirlwind_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_herod(Creature* pCreature) +{ + return new boss_herodAI(pCreature); +} + +struct mob_scarlet_traineeAI : public npc_escortAI +{ + mob_scarlet_traineeAI(Creature *c) : npc_escortAI(c) + { + Start_Timer = urand(1000,6000); + } + + uint32 Start_Timer; + + void Reset() {} + void WaypointReached(uint32 /*uiPoint*/) {} + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (Start_Timer) + { + if (Start_Timer <= diff) + { + Start(true,true); + Start_Timer = 0; + } else Start_Timer -= diff; + } + + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_mob_scarlet_trainee(Creature* pCreature) +{ + return new mob_scarlet_traineeAI(pCreature); +} + +void AddSC_boss_herod() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_herod"; + newscript->GetAI = &GetAI_boss_herod; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_scarlet_trainee"; + newscript->GetAI = &GetAI_mob_scarlet_trainee; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp new file mode 100644 index 00000000000..b9b15f34508 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp @@ -0,0 +1,133 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Inquisitor_Fairbanks +SD%Complete: 100 +SDComment: TODO: if this guy not involved in some special event, remove (and let ACID script) +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +enum eSpells +{ + SPELL_CURSEOFBLOOD = 8282, + SPELL_DISPELMAGIC = 15090, + SPELL_FEAR = 12096, + SPELL_HEAL = 12039, + SPELL_POWERWORDSHIELD = 11647, + SPELL_SLEEP = 8399 +}; + +struct boss_high_inquisitor_fairbanksAI : public ScriptedAI +{ + boss_high_inquisitor_fairbanksAI(Creature *c) : ScriptedAI(c) {} + + uint32 CurseOfBlood_Timer; + uint32 DispelMagic_Timer; + uint32 Fear_Timer; + uint32 Heal_Timer; + uint32 Sleep_Timer; + uint32 Dispel_Timer; + bool PowerWordShield; + + void Reset() + { + CurseOfBlood_Timer = 10000; + DispelMagic_Timer = 30000; + Fear_Timer = 40000; + Heal_Timer = 30000; + Sleep_Timer = 30000; + Dispel_Timer = 20000; + PowerWordShield = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <25% hp cast Heal + if (me->GetHealth()*100 / me->GetMaxHealth() <= 25 && !me->IsNonMeleeSpellCasted(false) && Heal_Timer <= diff) + { + DoCast(me, SPELL_HEAL); + Heal_Timer = 30000; + } else Heal_Timer -= diff; + + //Fear_Timer + if (Fear_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_FEAR); + + Fear_Timer = 40000; + } else Fear_Timer -= diff; + + //Sleep_Timer + if (Sleep_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,0)) + DoCast(pTarget, SPELL_SLEEP); + + Sleep_Timer = 30000; + } else Sleep_Timer -= diff; + + //PowerWordShield_Timer + if (!PowerWordShield && me->GetHealth()*100 / me->GetMaxHealth() <= 25) + { + DoCast(me, SPELL_POWERWORDSHIELD); + PowerWordShield = true; + } + + //Dispel_Timer + if (Dispel_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_DISPELMAGIC); + + DispelMagic_Timer = 30000; + } else DispelMagic_Timer -= diff; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); + CurseOfBlood_Timer = 25000; + } else CurseOfBlood_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_high_inquisitor_fairbanks(Creature* pCreature) +{ + return new boss_high_inquisitor_fairbanksAI (pCreature); +} + +void AddSC_boss_high_inquisitor_fairbanks() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_high_inquisitor_fairbanks"; + newscript->GetAI = &GetAI_boss_high_inquisitor_fairbanks; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp new file mode 100644 index 00000000000..300e69611cd --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp @@ -0,0 +1,77 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Houndmaster_Loksey +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1189021, + SPELL_SUMMONSCARLETHOUND = 17164, + SPELL_BLOODLUST = 6742 +}; + +struct boss_houndmaster_lokseyAI : public ScriptedAI +{ + boss_houndmaster_lokseyAI(Creature *c) : ScriptedAI(c) {} + + uint32 BloodLust_Timer; + + void Reset() + { + BloodLust_Timer = 20000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BloodLust_Timer <= diff) + { + DoCast(me, SPELL_BLOODLUST); + BloodLust_Timer = 20000; + } else BloodLust_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_houndmaster_loksey(Creature* pCreature) +{ + return new boss_houndmaster_lokseyAI (pCreature); +} + +void AddSC_boss_houndmaster_loksey() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_houndmaster_loksey"; + newscript->GetAI = &GetAI_boss_houndmaster_loksey; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp new file mode 100644 index 00000000000..b4b84fc8059 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp @@ -0,0 +1,118 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Interrogator_Vishas +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "scarlet_monastery.h" + +enum eEnums +{ + SAY_AGGRO = -1189011, + SAY_HEALTH1 = -1189012, + SAY_HEALTH2 = -1189013, + SAY_KILL = -1189014, + SAY_TRIGGER_VORREL = -1189015, + + SPELL_SHADOWWORDPAIN = 2767, +}; + +struct boss_interrogator_vishasAI : public ScriptedAI +{ + boss_interrogator_vishasAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool Yell30; + bool Yell60; + uint32 ShadowWordPain_Timer; + + void Reset() + { + ShadowWordPain_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*Victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (!pInstance) + return; + + //Any other actions to do with vorrel? setStandState? + if (Unit *vorrel = Unit::GetUnit(*me,pInstance->GetData64(DATA_VORREL))) + DoScriptText(SAY_TRIGGER_VORREL, vorrel); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are low on hp Do sayings + if (!Yell60 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 60)) + { + DoScriptText(SAY_HEALTH1, me); + Yell60 = true; + } + + if (!Yell30 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 30)) + { + DoScriptText(SAY_HEALTH2, me); + Yell30 = true; + } + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 5000 + rand()%10000; + } else ShadowWordPain_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_interrogator_vishas(Creature* pCreature) +{ + return new boss_interrogator_vishasAI (pCreature); +} + +void AddSC_boss_interrogator_vishas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_interrogator_vishas"; + newscript->GetAI = &GetAI_boss_interrogator_vishas; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp new file mode 100644 index 00000000000..32b85e214a0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp @@ -0,0 +1,359 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mograine_And_Whitemane +SD%Complete: 90 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "scarlet_monastery.h" + +enum eEnums +{ + //Mograine says + SAY_MO_AGGRO = -1189005, + SAY_MO_KILL = -1189006, + SAY_MO_RESSURECTED = -1189007, + + //Whitemane says + SAY_WH_INTRO = -1189008, + SAY_WH_KILL = -1189009, + SAY_WH_RESSURECT = -1189010, + + //Mograine Spells + SPELL_CRUSADERSTRIKE = 14518, + SPELL_HAMMEROFJUSTICE = 5589, + SPELL_LAYONHANDS = 9257, + SPELL_RETRIBUTIONAURA = 8990, + + //Whitemanes Spells + SPELL_DEEPSLEEP = 9256, + SPELL_SCARLETRESURRECTION = 9232, + SPELL_DOMINATEMIND = 14515, + SPELL_HOLYSMITE = 9481, + SPELL_HEAL = 12039, + SPELL_POWERWORDSHIELD = 22187 +}; + +struct boss_scarlet_commander_mograineAI : public ScriptedAI +{ + boss_scarlet_commander_mograineAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiCrusaderStrike_Timer; + uint32 m_uiHammerOfJustice_Timer; + + bool m_bHasDied; + bool m_bHeal; + bool m_bFakeDeath; + + void Reset() + { + m_uiCrusaderStrike_Timer = 10000; + m_uiHammerOfJustice_Timer = 10000; + + //Incase wipe during phase that mograine fake death + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + + if (m_pInstance) + if (me->isAlive()) + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT,NOT_STARTED); + + m_bHasDied = false; + m_bHeal = false; + m_bFakeDeath = false; + } + + void JustReachedHome() + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT != NOT_STARTED)) + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, FAIL); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_MO_AGGRO, me); + DoCast(me, SPELL_RETRIBUTIONAURA); + + me->CallForHelp(VISIBLE_RANGE); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(SAY_MO_KILL, me); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) + { + if (uiDamage < me->GetHealth() || m_bHasDied || m_bFakeDeath) + return; + + if (!m_pInstance) + return; + + //On first death, fake death and open door, as well as initiate whitemane if exist + if (Unit* Whitemane = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_WHITEMANE))) + { + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS); + + Whitemane->GetMotionMaster()->MovePoint(1,1163.113370,1398.856812,32.527786); + + me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->MoveIdle(); + + me->SetHealth(0); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + me->ClearComboPointHolders(); + me->RemoveAllAuras(); + me->ClearAllReactives(); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_DEAD); + + m_bHasDied = true; + m_bFakeDeath = true; + + uiDamage = 0; + } + } + + void SpellHit(Unit* /*pWho*/, const SpellEntry* pSpell) + { + //When hit with ressurection say text + if (pSpell->Id == SPELL_SCARLETRESURRECTION) + { + DoScriptText(SAY_MO_RESSURECTED, me); + m_bFakeDeath = false; + + if (m_pInstance) + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, SPECIAL); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_bHasDied && !m_bHeal && m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL) + { + //On ressurection, stop fake death and heal whitemane and resume fight + if (Unit* Whitemane = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_WHITEMANE))) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(Whitemane, SPELL_LAYONHANDS); + + m_uiCrusaderStrike_Timer = 10000; + m_uiHammerOfJustice_Timer = 10000; + + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + + m_bHeal = true; + } + } + + //This if-check to make sure mograine does not attack while fake death + if (m_bFakeDeath) + return; + + //m_uiCrusaderStrike_Timer + if (m_uiCrusaderStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CRUSADERSTRIKE); + m_uiCrusaderStrike_Timer = 10000; + } else m_uiCrusaderStrike_Timer -= uiDiff; + + //m_uiHammerOfJustice_Timer + if (m_uiHammerOfJustice_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_HAMMEROFJUSTICE); + m_uiHammerOfJustice_Timer = 60000; + } else m_uiHammerOfJustice_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_high_inquisitor_whitemaneAI : public ScriptedAI +{ + boss_high_inquisitor_whitemaneAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiHeal_Timer; + uint32 m_uiPowerWordShield_Timer; + uint32 m_uiHolySmite_Timer; + uint32 m_uiWait_Timer; + + bool m_bCanResurrectCheck; + bool m_bCanResurrect; + + void Reset() + { + m_uiWait_Timer = 7000; + m_uiHeal_Timer = 10000; + m_uiPowerWordShield_Timer = 15000; + m_uiHolySmite_Timer = 6000; + + m_bCanResurrectCheck = false; + m_bCanResurrect = false; + + if (m_pInstance) + if (me->isAlive()) + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, NOT_STARTED); + } + + void AttackStart(Unit* pWho) + { + if (m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED) + return; + + ScriptedAI::AttackStart(pWho); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_WH_INTRO, me); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(SAY_WH_KILL, me); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_bCanResurrect) + { + //When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out + if (m_pInstance && m_uiWait_Timer <= uiDiff) + { + if (Unit* Mograine = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_MOGRAINE))) + { + DoCast(Mograine, SPELL_SCARLETRESURRECTION); + DoScriptText(SAY_WH_RESSURECT, me); + m_bCanResurrect = false; + } + } + else m_uiWait_Timer -= uiDiff; + } + + //Cast Deep sleep when health is less than 50% + if (!m_bCanResurrectCheck && me->GetHealth()*100 / me->GetMaxHealth() <= 50) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me->getVictim(), SPELL_DEEPSLEEP); + m_bCanResurrectCheck = true; + m_bCanResurrect = true; + return; + } + + //while in "resurrect-mode", don't do anything + if (m_bCanResurrect) + return; + + //If we are <75% hp cast healing spells at self or Mograine + if (m_uiHeal_Timer <= uiDiff) + { + Creature* pTarget = NULL; + + if (me->GetHealth() <= me->GetMaxHealth()*0.75f) + pTarget = me; + + if (m_pInstance) + { + if (Creature* pMograine = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_MOGRAINE))) + { + // checking m_bCanResurrectCheck prevents her healing Mograine while he is "faking death" + if (m_bCanResurrectCheck && pMograine->isAlive() && pMograine->GetHealth() <= pMograine->GetMaxHealth()*0.75f) + pTarget = pMograine; + } + } + + if (pTarget) + DoCast(pTarget, SPELL_HEAL); + + m_uiHeal_Timer = 13000; + } else m_uiHeal_Timer -= uiDiff; + + //m_uiPowerWordShield_Timer + if (m_uiPowerWordShield_Timer <= uiDiff) + { + DoCast(me, SPELL_POWERWORDSHIELD); + m_uiPowerWordShield_Timer = 15000; + } else m_uiPowerWordShield_Timer -= uiDiff; + + //m_uiHolySmite_Timer + if (m_uiHolySmite_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_HOLYSMITE); + m_uiHolySmite_Timer = 6000; + } else m_uiHolySmite_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_scarlet_commander_mograine(Creature* pCreature) +{ + return new boss_scarlet_commander_mograineAI (pCreature); +} + +CreatureAI* GetAI_boss_high_inquisitor_whitemane(Creature* pCreature) +{ + return new boss_high_inquisitor_whitemaneAI (pCreature); +} + +void AddSC_boss_mograine_and_whitemane() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_scarlet_commander_mograine"; + newscript->GetAI = &GetAI_boss_scarlet_commander_mograine; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_high_inquisitor_whitemane"; + newscript->GetAI = &GetAI_boss_high_inquisitor_whitemane; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp new file mode 100644 index 00000000000..5d0a3b3792f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp @@ -0,0 +1,101 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Scorn +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_LICHSLAP 28873 +#define SPELL_FROSTBOLTVOLLEY 8398 +#define SPELL_MINDFLAY 17313 +#define SPELL_FROSTNOVA 15531 + +struct boss_scornAI : public ScriptedAI +{ + boss_scornAI(Creature *c) : ScriptedAI(c) {} + + uint32 LichSlap_Timer; + uint32 FrostboltVolley_Timer; + uint32 MindFlay_Timer; + uint32 FrostNova_Timer; + + void Reset() + { + LichSlap_Timer = 45000; + FrostboltVolley_Timer = 30000; + MindFlay_Timer = 30000; + FrostNova_Timer = 30000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //LichSlap_Timer + if (LichSlap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LICHSLAP); + LichSlap_Timer = 45000; + } else LichSlap_Timer -= diff; + + //FrostboltVolley_Timer + if (FrostboltVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLTVOLLEY); + FrostboltVolley_Timer = 20000; + } else FrostboltVolley_Timer -= diff; + + //MindFlay_Timer + if (MindFlay_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MINDFLAY); + MindFlay_Timer = 20000; + } else MindFlay_Timer -= diff; + + //FrostNova_Timer + if (FrostNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTNOVA); + FrostNova_Timer = 15000; + } else FrostNova_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_scorn(Creature* pCreature) +{ + return new boss_scornAI (pCreature); +} + +void AddSC_boss_scorn() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_scorn"; + newscript->GetAI = &GetAI_boss_scorn; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp new file mode 100644 index 00000000000..33642d4511c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp @@ -0,0 +1,157 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Scarlet_Monastery +SD%Complete: 50 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "scarlet_monastery.h" + +#define ENTRY_PUMPKIN_SHRINE 186267 +#define ENTRY_HORSEMAN 23682 +#define ENTRY_HEAD 23775 +#define ENTRY_PUMPKIN 23694 + +#define MAX_ENCOUNTER 2 + +struct instance_scarlet_monastery : public ScriptedInstance +{ + instance_scarlet_monastery(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 PumpkinShrineGUID; + uint64 HorsemanGUID; + uint64 HeadGUID; + std::set HorsemanAdds; + + uint64 MograineGUID; + uint64 WhitemaneGUID; + uint64 VorrelGUID; + uint64 DoorHighInquisitorGUID; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + PumpkinShrineGUID = 0; + HorsemanGUID = 0; + HeadGUID = 0; + HorsemanAdds.clear(); + + MograineGUID = 0; + WhitemaneGUID = 0; + VorrelGUID = 0; + DoorHighInquisitorGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case ENTRY_PUMPKIN_SHRINE: PumpkinShrineGUID = pGo->GetGUID();break; + case 104600: DoorHighInquisitorGUID = pGo->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case ENTRY_HORSEMAN: HorsemanGUID = pCreature->GetGUID(); break; + case ENTRY_HEAD: HeadGUID = pCreature->GetGUID(); break; + case ENTRY_PUMPKIN: HorsemanAdds.insert(pCreature->GetGUID());break; + case 3976: MograineGUID = pCreature->GetGUID(); break; + case 3977: WhitemaneGUID = pCreature->GetGUID(); break; + case 3981: VorrelGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_MOGRAINE_AND_WHITE_EVENT: + if (data == IN_PROGRESS) + DoUseDoorOrButton(DoorHighInquisitorGUID); + if (data == FAIL) + DoUseDoorOrButton(DoorHighInquisitorGUID); + + m_auiEncounter[0] = data; + break; + case GAMEOBJECT_PUMPKIN_SHRINE: + HandleGameObject(PumpkinShrineGUID, false); + break; + case DATA_HORSEMAN_EVENT: + m_auiEncounter[1] = data; + if (data == DONE) + { + for (std::set::const_iterator itr = HorsemanAdds.begin(); itr != HorsemanAdds.end(); ++itr) + { + Creature* add = instance->GetCreature(*itr); + if (add && add->isAlive()) + add->Kill(add); + } + HorsemanAdds.clear(); + HandleGameObject(PumpkinShrineGUID, false); + } + break; + } + } + + uint64 GetData64(uint32 type) + { + switch(type) + { + //case GAMEOBJECT_PUMPKIN_SHRINE: return PumpkinShrineGUID; + //case DATA_HORSEMAN: return HorsemanGUID; + //case DATA_HEAD: return HeadGUID; + case DATA_MOGRAINE: return MograineGUID; + case DATA_WHITEMANE: return WhitemaneGUID; + case DATA_VORREL: return VorrelGUID; + case DATA_DOOR_WHITEMANE: return DoorHighInquisitorGUID; + } + return 0; + } + + uint32 GetData(uint32 type) + { + if (type == TYPE_MOGRAINE_AND_WHITE_EVENT) + return m_auiEncounter[0]; + if (type == DATA_HORSEMAN_EVENT) + return m_auiEncounter[1]; + return 0; + } +}; + +InstanceData* GetInstanceData_instance_scarlet_monastery(Map* pMap) +{ + return new instance_scarlet_monastery(pMap); +} + +void AddSC_instance_scarlet_monastery() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_scarlet_monastery"; + newscript->GetInstanceData = &GetInstanceData_instance_scarlet_monastery; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h b/src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h new file mode 100644 index 00000000000..2b6399ae3e4 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h @@ -0,0 +1,18 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SCARLET_M +#define DEF_SCARLET_M + +#define TYPE_MOGRAINE_AND_WHITE_EVENT 1 +#define DATA_MOGRAINE 2 +#define DATA_WHITEMANE 3 +#define DATA_DOOR_WHITEMANE 4 + +#define DATA_HORSEMAN_EVENT 5 +#define GAMEOBJECT_PUMPKIN_SHRINE 6 + +#define DATA_VORREL 7 +#endif + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp new file mode 100644 index 00000000000..50a9e204566 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp @@ -0,0 +1,225 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Darkmaster_Gandling +SD%Complete: 75 +SDComment: Doors missing in instance script. +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_ARCANEMISSILES 22272 +#define SPELL_SHADOWSHIELD 22417 //Not right ID. But 12040 is wrong either. +#define SPELL_CURSE 18702 + +#define ADD_1X 170.205 +#define ADD_1Y 99.413 +#define ADD_1Z 104.733 +#define ADD_1O 3.16 + +#define ADD_2X 170.813 +#define ADD_2Y 97.857 +#define ADD_2Z 104.713 +#define ADD_2O 3.16 + +#define ADD_3X 170.720 +#define ADD_3Y 100.900 +#define ADD_3Z 104.739 +#define ADD_3O 3.16 + +#define ADD_4X 171.866 +#define ADD_4Y 99.373 +#define ADD_4Z 104.732 +#define ADD_4O 3.16 + +struct boss_darkmaster_gandlingAI : public ScriptedAI +{ + boss_darkmaster_gandlingAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ArcaneMissiles_Timer; + uint32 ShadowShield_Timer; + uint32 Curse_Timer; + uint32 Teleport_Timer; + + void Reset() + { + ArcaneMissiles_Timer = 4500; + ShadowShield_Timer = 12000; + Curse_Timer = 2000; + Teleport_Timer = 16000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_GANDLING, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ArcaneMissiles_Timer + if (ArcaneMissiles_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANEMISSILES); + ArcaneMissiles_Timer = 8000; + } else ArcaneMissiles_Timer -= diff; + + //ShadowShield_Timer + if (ShadowShield_Timer <= diff) + { + DoCast(me, SPELL_SHADOWSHIELD); + ShadowShield_Timer = 14000 + rand()%14000; + } else ShadowShield_Timer -= diff; + + //Curse_Timer + if (Curse_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSE); + Curse_Timer = 15000 + rand()%12000; + } else Curse_Timer -= diff; + + //Teleporting Random Target to one of the six pre boss rooms and spawn 3-4 skeletons near the gamer. + //We will only telport if gandling has more than 3% of hp so teleported gamers can always loot. + if (me->GetHealth()*100 / me->GetMaxHealth() > 3) + { + if (Teleport_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + if (DoGetThreat(pTarget)) + DoModifyThreatPercent(pTarget, -100); + + Creature *Summoned = NULL; + switch(rand()%6) + { + case 0: + DoTeleportPlayer(pTarget, 250.0696,0.3921,84.8408,3.149); + Summoned = me->SummonCreature(16119,254.2325,0.3417,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,257.7133,4.0226,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,258.6702,-2.60656,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 1: + DoTeleportPlayer(pTarget, 181.4220,-91.9481,84.8410,1.608); + Summoned = me->SummonCreature(16119,184.0519,-73.5649,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,179.5951,-73.7045,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,180.6452,-78.2143,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,283.2274,-78.1518,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 2: + DoTeleportPlayer(pTarget, 95.1547,-1.8173,85.2289,0.043); + Summoned = me->SummonCreature(16119,100.9404,-1.8016,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,101.3729,0.4882,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,101.4596,-4.4740,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 3: + DoTeleportPlayer(pTarget, 250.0696,0.3921,72.6722,3.149); + Summoned = me->SummonCreature(16119,240.34481,0.7368,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,240.3633,-2.9520,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,240.6702,3.34949,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 4: + DoTeleportPlayer(pTarget, 181.4220,-91.9481,70.7734,1.608); + Summoned = me->SummonCreature(16119,184.0519,-73.5649,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,179.5951,-73.7045,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,180.6452,-78.2143,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,283.2274,-78.1518,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 5: + DoTeleportPlayer(pTarget, 106.1541,-1.8994,75.3663,0.043); + Summoned = me->SummonCreature(16119,115.3945,-1.5555,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,257.7133,1.8066,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,258.6702,-5.1001,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + } + } + Teleport_Timer = 20000 + rand()%15000; + } else Teleport_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_darkmaster_gandling(Creature* pCreature) +{ + return new boss_darkmaster_gandlingAI (pCreature); +} + +void AddSC_boss_darkmaster_gandling() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_darkmaster_gandling"; + newscript->GetAI = &GetAI_boss_darkmaster_gandling; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp new file mode 100644 index 00000000000..8bb9ec68aca --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp @@ -0,0 +1,58 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Death_knight_darkreaver +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +struct boss_death_knight_darkreaverAI : public ScriptedAI +{ + boss_death_knight_darkreaverAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (me->GetHealth() <= damage) + DoCast(me, 23261, true); //Summon Darkreaver's Fallen Charger + } + + void EnterCombat(Unit * /*who*/) + { + } +}; +CreatureAI* GetAI_boss_death_knight_darkreaver(Creature* pCreature) +{ + return new boss_death_knight_darkreaverAI (pCreature); +} + +void AddSC_boss_death_knight_darkreaver() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_death_knight_darkreaver"; + newscript->GetAI = &GetAI_boss_death_knight_darkreaver; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp new file mode 100644 index 00000000000..5ff01d48623 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Doctor_Theolen_Krastinov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +enum eEnums +{ + EMOTE_GENERIC_FRENZY_KILL = -1000001, + + SPELL_REND = 16509, + SPELL_BACKHAND = 18103, + SPELL_FRENZY = 8269 +}; + +struct boss_theolenkrastinovAI : public ScriptedAI +{ + boss_theolenkrastinovAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiRend_Timer; + uint32 m_uiBackhand_Timer; + uint32 m_uiFrenzy_Timer; + + void Reset() + { + m_uiRend_Timer = 8000; + m_uiBackhand_Timer = 9000; + m_uiFrenzy_Timer = 1000; + } + + void JustDied(Unit* /*pKiller*/) + { + ScriptedInstance* pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_DOCTORTHEOLENKRASTINOV_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //Rend_Timer + if (m_uiRend_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_REND); + m_uiRend_Timer = 10000; + } + else + m_uiRend_Timer -= uiDiff; + + //Backhand_Timer + if (m_uiBackhand_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_BACKHAND); + m_uiBackhand_Timer = 10000; + } + else + m_uiBackhand_Timer -= uiDiff; + + //Frenzy_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 26) + { + if (m_uiFrenzy_Timer <= uiDiff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); + + m_uiFrenzy_Timer = 120000; + } + else + m_uiFrenzy_Timer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_theolenkrastinov(Creature* pCreature) +{ + return new boss_theolenkrastinovAI (pCreature); +} + +void AddSC_boss_theolenkrastinov() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_doctor_theolen_krastinov"; + newscript->GetAI = &GetAI_boss_theolenkrastinov; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp new file mode 100644 index 00000000000..a038fc7a0b8 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Illucia_Barov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_CURSEOFAGONY 18671 +#define SPELL_SHADOWSHOCK 20603 +#define SPELL_SILENCE 15487 +#define SPELL_FEAR 6215 + +struct boss_illuciabarovAI : public ScriptedAI +{ + boss_illuciabarovAI(Creature *c) : ScriptedAI(c) {} + + uint32 CurseOfAgony_Timer; + uint32 ShadowShock_Timer; + uint32 Silence_Timer; + uint32 Fear_Timer; + + void Reset() + { + CurseOfAgony_Timer = 18000; + ShadowShock_Timer = 9000; + Silence_Timer = 5000; + Fear_Timer = 30000; + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_LADYILLUCIABAROV_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //CurseOfAgony_Timer + if (CurseOfAgony_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFAGONY); + CurseOfAgony_Timer = 30000; + } else CurseOfAgony_Timer -= diff; + + //ShadowShock_Timer + if (ShadowShock_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_SHADOWSHOCK); + + ShadowShock_Timer = 12000; + } else ShadowShock_Timer -= diff; + + //Silence_Timer + if (Silence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + Silence_Timer = 14000; + } else Silence_Timer -= diff; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + Fear_Timer = 30000; + } else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_illuciabarov(Creature* pCreature) +{ + return new boss_illuciabarovAI (pCreature); +} + +void AddSC_boss_illuciabarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_illucia_barov"; + newscript->GetAI = &GetAI_boss_illuciabarov; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp new file mode 100644 index 00000000000..c4c0f95d8d1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp @@ -0,0 +1,153 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_instructormalicia +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_CALLOFGRAVES 17831 +#define SPELL_CORRUPTION 11672 +#define SPELL_FLASHHEAL 10917 +#define SPELL_RENEW 10929 +#define SPELL_HEALINGTOUCH 9889 + +struct boss_instructormaliciaAI : public ScriptedAI +{ + boss_instructormaliciaAI(Creature *c) : ScriptedAI(c) {} + + uint32 CallOfGraves_Timer; + uint32 Corruption_Timer; + uint32 FlashHeal_Timer; + uint32 Renew_Timer; + uint32 HealingTouch_Timer; + uint32 FlashCounter; + uint32 TouchCounter; + + void Reset() + { + CallOfGraves_Timer = 4000; + Corruption_Timer = 8000; + FlashHeal_Timer = 38000; + Renew_Timer = 32000; + HealingTouch_Timer = 45000; + FlashCounter = 0; + TouchCounter = 0; + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_INSTRUCTORMALICIA_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //CallOfGraves_Timer + if (CallOfGraves_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CALLOFGRAVES); + CallOfGraves_Timer = 65000; + } else CallOfGraves_Timer -= diff; + + //Corruption_Timer + if (Corruption_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_CORRUPTION); + + Corruption_Timer = 24000; + } else Corruption_Timer -= diff; + + //Renew_Timer + if (Renew_Timer <= diff) + { + DoCast(me, SPELL_RENEW); + Renew_Timer = 10000; + } else Renew_Timer -= diff; + + //FlashHeal_Timer + if (FlashHeal_Timer <= diff) + { + DoCast(me, SPELL_FLASHHEAL); + + //5 Flashheals will be casted + if (FlashCounter < 2) + { + FlashHeal_Timer = 5000; + ++FlashCounter; + } + else + { + FlashCounter=0; + FlashHeal_Timer = 30000; + } + } else FlashHeal_Timer -= diff; + + //HealingTouch_Timer + if (HealingTouch_Timer <= diff) + { + DoCast(me, SPELL_HEALINGTOUCH); + + //3 Healingtouchs will be casted + if (HealingTouch_Timer < 2) + { + HealingTouch_Timer = 5500; + ++TouchCounter; + } + else + { + TouchCounter=0; + HealingTouch_Timer = 30000; + } + } else HealingTouch_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_instructormalicia(Creature* pCreature) +{ + return new boss_instructormaliciaAI (pCreature); +} + +void AddSC_boss_instructormalicia() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_instructor_malicia"; + newscript->GetAI = &GetAI_boss_instructormalicia; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp new file mode 100644 index 00000000000..f8d8520e394 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp @@ -0,0 +1,201 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_jandicebarov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CURSEOFBLOOD 24673 +//#define SPELL_ILLUSION 17773 + +//Spells of Illusion of Jandice Barov +#define SPELL_CLEAVE 15584 + +struct boss_jandicebarovAI : public ScriptedAI +{ + boss_jandicebarovAI(Creature *c) : ScriptedAI(c) {} + + uint32 CurseOfBlood_Timer; + uint32 Illusion_Timer; + //uint32 Illusioncounter; + uint32 Invisible_Timer; + bool Invisible; + + void Reset() + { + CurseOfBlood_Timer = 15000; + Illusion_Timer = 30000; + Invisible_Timer = 3000; //Too much too low? + Invisible = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonIllusions(Unit* victim) + { + if (Creature *Illusion = DoSpawnCreature(11439, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) + Illusion->AI()->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (Invisible && Invisible_Timer <= diff) + { + //Become visible again + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(11073); //Jandice Model + Invisible = false; + } else if (Invisible) + { + Invisible_Timer -= diff; + //Do nothing while invisible + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); + + //45 seconds + CurseOfBlood_Timer = 30000; + } else CurseOfBlood_Timer -= diff; + + //Illusion_Timer + if (!Invisible && Illusion_Timer <= diff) + { + + //Inturrupt any spell casting + me->InterruptNonMeleeSpells(false); + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(11686); // Invisible Model + DoModifyThreatPercent(me->getVictim(),-99); + + //Summon 10 Illusions attacking random gamers + Unit *pTarget = NULL; + for (uint8 i = 0; i < 10; ++i) + { + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + SummonIllusions(pTarget); + } + Invisible = true; + Invisible_Timer = 3000; + + //25 seconds until we should cast this agian + Illusion_Timer = 25000; + } else Illusion_Timer -= diff; + + // //Illusion_Timer + // if (Illusion_Timer <= diff) + // { + // //Cast + // DoCast(me->getVictim(), SPELL_ILLUSION); + // + // //3 Illusion will be summoned + // if (Illusioncounter < 3) + // { + // Illusion_Timer = 500; + // ++Illusioncounter; + // } + // else { + // //15 seconds until we should cast this again + // Illusion_Timer = 15000; + // Illusioncounter = 0; + // } + // + // } else Illusion_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +// Illusion of Jandice Barov Script + +struct mob_illusionofjandicebarovAI : public ScriptedAI +{ + mob_illusionofjandicebarovAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cleave_Timer; + + void Reset() + { + Cleave_Timer = 2000 + rand()%6000; + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_CLEAVE); + + //5-8 seconds + Cleave_Timer = 5000 + rand()%3000; + } else Cleave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jandicebarov(Creature* pCreature) +{ + return new boss_jandicebarovAI (pCreature); +} + +CreatureAI* GetAI_mob_illusionofjandicebarov(Creature* pCreature) +{ + return new mob_illusionofjandicebarovAI (pCreature); +} + +void AddSC_boss_jandicebarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_jandice_barov"; + newscript->GetAI = &GetAI_boss_jandicebarov; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_illusionofjandicebarov"; + newscript->GetAI = &GetAI_mob_illusionofjandicebarov; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp new file mode 100644 index 00000000000..c4ae5cc490e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp @@ -0,0 +1,120 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kormok +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWBOLTVOLLEY 20741 +#define SPELL_BONESHIELD 27688 + +struct boss_kormokAI : public ScriptedAI +{ + boss_kormokAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowVolley_Timer; + uint32 BoneShield_Timer; + uint32 Minion_Timer; + uint32 Mage_Timer; + bool Mages; + + void Reset() + { + ShadowVolley_Timer = 10000; + BoneShield_Timer = 2000; + Minion_Timer = 15000; + Mage_Timer = 0; + Mages = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonMinions(Unit* victim) + { + if (Creature *SummonedMinion = DoSpawnCreature(16119, irand(-7,7), irand(-7,7), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedMinion->AI()->AttackStart(victim); + } + + void SummonMages(Unit* victim) + { + if (Creature *SummonedMage = DoSpawnCreature(16120, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedMage->AI()->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLTVOLLEY); + ShadowVolley_Timer = 15000; + } else ShadowVolley_Timer -= diff; + + //BoneShield_Timer + if (BoneShield_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BONESHIELD); + BoneShield_Timer = 45000; + } else BoneShield_Timer -= diff; + + //Minion_Timer + if (Minion_Timer <= diff) + { + //Cast + SummonMinions(me->getVictim()); + SummonMinions(me->getVictim()); + SummonMinions(me->getVictim()); + SummonMinions(me->getVictim()); + + Minion_Timer = 12000; + } else Minion_Timer -= diff; + + //Summon 2 Bone Mages + if (!Mages && me->GetHealth()*100 / me->GetMaxHealth() < 26) + { + //Cast + SummonMages(me->getVictim()); + SummonMages(me->getVictim()); + Mages = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_kormok(Creature* pCreature) +{ + return new boss_kormokAI (pCreature); +} + +void AddSC_boss_kormok() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kormok"; + newscript->GetAI = &GetAI_boss_kormok; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp new file mode 100644 index 00000000000..0956a04d824 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp @@ -0,0 +1,99 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lord_Alexei_Barov +SD%Complete: 100 +SDComment: aura applied/defined in database +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_IMMOLATE 20294 // Old ID was 15570 +#define SPELL_VEILOFSHADOW 17820 + +struct boss_lordalexeibarovAI : public ScriptedAI +{ + boss_lordalexeibarovAI(Creature *c) : ScriptedAI(c) {} + + uint32 Immolate_Timer; + uint32 VeilofShadow_Timer; + + void Reset() + { + Immolate_Timer = 7000; + VeilofShadow_Timer = 15000; + + me->LoadCreaturesAddon(); + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_LORDALEXEIBAROV_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); + + Immolate_Timer = 12000; + } else Immolate_Timer -= diff; + + //VeilofShadow_Timer + if (VeilofShadow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VEILOFSHADOW); + VeilofShadow_Timer = 20000; + } else VeilofShadow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lordalexeibarov(Creature* pCreature) +{ + return new boss_lordalexeibarovAI (pCreature); +} + +void AddSC_boss_lordalexeibarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lord_alexei_barov"; + newscript->GetAI = &GetAI_boss_lordalexeibarov; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp new file mode 100644 index 00000000000..d3b75900202 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lorekeeper_Polkelt +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_VOLATILEINFECTION 24928 +#define SPELL_DARKPLAGUE 18270 +#define SPELL_CORROSIVEACID 23313 +#define SPELL_NOXIOUSCATALYST 18151 + +struct boss_lorekeeperpolkeltAI : public ScriptedAI +{ + boss_lorekeeperpolkeltAI(Creature *c) : ScriptedAI(c) {} + + uint32 VolatileInfection_Timer; + uint32 Darkplague_Timer; + uint32 CorrosiveAcid_Timer; + uint32 NoxiousCatalyst_Timer; + + void Reset() + { + VolatileInfection_Timer = 38000; + Darkplague_Timer = 8000; + CorrosiveAcid_Timer = 45000; + NoxiousCatalyst_Timer = 35000; + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_LOREKEEPERPOLKELT_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //VolatileInfection_Timer + if (VolatileInfection_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VOLATILEINFECTION); + VolatileInfection_Timer = 32000; + } else VolatileInfection_Timer -= diff; + + //Darkplague_Timer + if (Darkplague_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DARKPLAGUE); + Darkplague_Timer = 8000; + } else Darkplague_Timer -= diff; + + //CorrosiveAcid_Timer + if (CorrosiveAcid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVEACID); + CorrosiveAcid_Timer = 25000; + } else CorrosiveAcid_Timer -= diff; + + //NoxiousCatalyst_Timer + if (NoxiousCatalyst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_NOXIOUSCATALYST); + NoxiousCatalyst_Timer = 38000; + } else NoxiousCatalyst_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lorekeeperpolkelt(Creature* pCreature) +{ + return new boss_lorekeeperpolkeltAI (pCreature); +} + +void AddSC_boss_lorekeeperpolkelt() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lorekeeper_polkelt"; + newscript->GetAI = &GetAI_boss_lorekeeperpolkelt; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp new file mode 100644 index 00000000000..63837e04ad5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp @@ -0,0 +1,123 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ras_Frostwhisper +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FROSTBOLT 21369 +#define SPELL_ICEARMOR 18100 //This is actually a buff he gives himself +#define SPELL_FREEZE 18763 +#define SPELL_FEAR 26070 +#define SPELL_CHILLNOVA 18099 +#define SPELL_FROSTVOLLEY 8398 + +struct boss_rasfrostAI : public ScriptedAI +{ + boss_rasfrostAI(Creature *c) : ScriptedAI(c) {} + + uint32 IceArmor_Timer; + uint32 Frostbolt_Timer; + uint32 Freeze_Timer; + uint32 Fear_Timer; + uint32 ChillNova_Timer; + uint32 FrostVolley_Timer; + + void Reset() + { + IceArmor_Timer = 2000; + Frostbolt_Timer = 8000; + ChillNova_Timer = 12000; + Freeze_Timer = 18000; + FrostVolley_Timer = 24000; + Fear_Timer = 45000; + + DoCast(me, SPELL_ICEARMOR, true); + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //IceArmor_Timer + if (IceArmor_Timer <= diff) + { + DoCast(me, SPELL_ICEARMOR); + IceArmor_Timer = 180000; + } else IceArmor_Timer -= diff; + + //Frostbolt_Timer + if (Frostbolt_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_FROSTBOLT); + + Frostbolt_Timer = 8000; + } else Frostbolt_Timer -= diff; + + //Freeze_Timer + if (Freeze_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FREEZE); + Freeze_Timer = 24000; + } else Freeze_Timer -= diff; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + Fear_Timer = 30000; + } else Fear_Timer -= diff; + + //ChillNova_Timer + if (ChillNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CHILLNOVA); + ChillNova_Timer = 14000; + } else ChillNova_Timer -= diff; + + //FrostVolley_Timer + if (FrostVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTVOLLEY); + FrostVolley_Timer = 15000; + } else FrostVolley_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_rasfrost(Creature* pCreature) +{ + return new boss_rasfrostAI (pCreature); +} + +void AddSC_boss_rasfrost() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_boss_ras_frostwhisper"; + newscript->GetAI = &GetAI_boss_rasfrost; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp new file mode 100644 index 00000000000..6340f2b0e2d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_the_ravenian +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_TRAMPLE 15550 +#define SPELL_CLEAVE 20691 +#define SPELL_SUNDERINCLEAVE 25174 +#define SPELL_KNOCKAWAY 10101 + +struct boss_theravenianAI : public ScriptedAI +{ + boss_theravenianAI(Creature *c) : ScriptedAI(c) {} + + uint32 Trample_Timer; + uint32 Cleave_Timer; + uint32 SunderingCleave_Timer; + uint32 KnockAway_Timer; + bool HasYelled; + + void Reset() + { + Trample_Timer = 24000; + Cleave_Timer = 15000; + SunderingCleave_Timer = 40000; + KnockAway_Timer = 32000; + HasYelled = false; + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_THERAVENIAN_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Trample_Timer + if (Trample_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TRAMPLE); + Trample_Timer = 10000; + } else Trample_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //SunderingCleave_Timer + if (SunderingCleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDERINCLEAVE); + SunderingCleave_Timer = 20000; + } else SunderingCleave_Timer -= diff; + + //KnockAway_Timer + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + KnockAway_Timer = 12000; + } else KnockAway_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_theravenian(Creature* pCreature) +{ + return new boss_theravenianAI (pCreature); +} + +void AddSC_boss_theravenian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_ravenian"; + newscript->GetAI = &GetAI_boss_theravenian; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp new file mode 100644 index 00000000000..a38369faab0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vectus +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + EMOTE_GENERIC_FRENZY_KILL = -1000001, + + SPELL_FLAMESTRIKE = 18399, + SPELL_BLAST_WAVE = 16046, + SPELL_FIRESHIELD = 19626, + SPELL_FRENZY = 8269 //28371, +}; + +struct boss_vectusAI : public ScriptedAI +{ + boss_vectusAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiFireShield_Timer; + uint32 m_uiBlastWave_Timer; + uint32 m_uiFrenzy_Timer; + + void Reset() + { + m_uiFireShield_Timer = 2000; + m_uiBlastWave_Timer = 14000; + m_uiFrenzy_Timer = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //FireShield_Timer + if (m_uiFireShield_Timer <= uiDiff) + { + DoCast(me, SPELL_FIRESHIELD); + m_uiFireShield_Timer = 90000; + } + else + m_uiFireShield_Timer -= uiDiff; + + //BlastWave_Timer + if (m_uiBlastWave_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_BLAST_WAVE); + m_uiBlastWave_Timer = 12000; + } + else + m_uiBlastWave_Timer -= uiDiff; + + //Frenzy_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 25) + { + if (m_uiFrenzy_Timer <= uiDiff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); + + m_uiFrenzy_Timer = 24000; + } + else + m_uiFrenzy_Timer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vectus(Creature* pCreature) +{ + return new boss_vectusAI (pCreature); +} + +void AddSC_boss_vectus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vectus"; + newscript->GetAI = &GetAI_boss_vectus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp b/src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp new file mode 100644 index 00000000000..992849cff1b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp @@ -0,0 +1,146 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Scholomance +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define GO_GATE_KIRTONOS 175570 +#define GO_GATE_GANDLING 177374 +#define GO_GATE_MALICIA 177375 +#define GO_GATE_THEOLEN 177377 +#define GO_GATE_POLKELT 177376 +#define GO_GATE_RAVENIAN 177372 +#define GO_GATE_BAROV 177373 +#define GO_GATE_ILLUCIA 177371 + +#define MAX_ENCOUNTER 2 + +struct instance_scholomance : public ScriptedInstance +{ + instance_scholomance(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + //Lord Alexei Barov, Doctor Theolen Krastinov, The Ravenian, Lorekeeper Polkelt, Instructor Malicia and the Lady Illucia Barov. + bool IsBossDied[6]; + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 GateKirtonosGUID; + uint64 GateGandlingGUID; + uint64 GateMiliciaGUID; + uint64 GateTheolenGUID; + uint64 GatePolkeltGUID; + uint64 GateRavenianGUID; + uint64 GateBarovGUID; + uint64 GateIlluciaGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + GateKirtonosGUID = 0; + GateGandlingGUID = 0; + GateMiliciaGUID = 0; + GateTheolenGUID = 0; + GatePolkeltGUID = 0; + GateRavenianGUID = 0; + GateBarovGUID = 0; + GateIlluciaGUID = 0; + + for (uint8 i = 0; i < 6; ++i) + IsBossDied[i] = false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_GATE_KIRTONOS: GateKirtonosGUID = pGo->GetGUID(); break; + case GO_GATE_GANDLING: GateGandlingGUID = pGo->GetGUID(); break; + case GO_GATE_MALICIA: GateMiliciaGUID = pGo->GetGUID(); break; + case GO_GATE_THEOLEN: GateTheolenGUID = pGo->GetGUID(); break; + case GO_GATE_POLKELT: GatePolkeltGUID = pGo->GetGUID(); break; + case GO_GATE_RAVENIAN: GateRavenianGUID = pGo->GetGUID(); break; + case GO_GATE_BAROV: GateBarovGUID = pGo->GetGUID(); break; + case GO_GATE_ILLUCIA: GateIlluciaGUID = pGo->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_LORDALEXEIBAROV_DEATH: + IsBossDied[0] = true; + break; + case DATA_DOCTORTHEOLENKRASTINOV_DEATH: + IsBossDied[1] = true; + break; + case DATA_THERAVENIAN_DEATH: + IsBossDied[2] = true; + break; + case DATA_LOREKEEPERPOLKELT_DEATH: + IsBossDied[3] = true; + break; + case DATA_INSTRUCTORMALICIA_DEATH: + IsBossDied[4] = true; + break; + case DATA_LADYILLUCIABAROV_DEATH: + IsBossDied[5] = true; + break; + case TYPE_GANDLING: + m_auiEncounter[0] = data; + break; + case TYPE_KIRTONOS: + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + if (type == TYPE_GANDLING) + { + if (IsBossDied[0] && IsBossDied[1] && IsBossDied[2] && IsBossDied[3] && IsBossDied[4] && IsBossDied[5]) + { + m_auiEncounter[0] = IN_PROGRESS; + return IN_PROGRESS; + } + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_scholomance(Map* pMap) +{ + return new instance_scholomance(pMap); +} + +void AddSC_instance_scholomance() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_scholomance"; + newscript->GetInstanceData = &GetInstanceData_instance_scholomance; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/scholomance/scholomance.h b/src/server/scripts/EasternKingdoms/scholomance/scholomance.h new file mode 100644 index 00000000000..83ce26c9687 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/scholomance/scholomance.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SCHOLOMANCE_H +#define DEF_SCHOLOMANCE_H + +#define TYPE_GANDLING 1 +#define DATA_DOCTORTHEOLENKRASTINOV_DEATH 2 +#define DATA_INSTRUCTORMALICIA_DEATH 3 +#define DATA_LADYILLUCIABAROV_DEATH 4 +#define DATA_LORDALEXEIBAROV_DEATH 5 +#define DATA_LOREKEEPERPOLKELT_DEATH 6 +#define DATA_THERAVENIAN_DEATH 7 +#define TYPE_KIRTONOS 8 +#endif + diff --git a/src/server/scripts/EasternKingdoms/searing_gorge.cpp b/src/server/scripts/EasternKingdoms/searing_gorge.cpp new file mode 100644 index 00000000000..3ad51d033da --- /dev/null +++ b/src/server/scripts/EasternKingdoms/searing_gorge.cpp @@ -0,0 +1,169 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Searing_Gorge +SD%Complete: 80 +SDComment: Quest support: 3377, 3441 (More accurate info on Kalaran needed). Lothos Riftwaker teleport to Molten Core. +SDCategory: Searing Gorge +EndScriptData */ + +/* ContentData +npc_kalaran_windblade +npc_lothos_riftwaker +npc_zamael_lunthistle +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_kalaran_windblade +######*/ + +#define GOSSIP_HELLO_KW "Tell me what drives this vengance?" +#define GOSSIP_SELECT_KW1 "Continue please" +#define GOSSIP_SELECT_KW2 "Let me confer with my colleagues" + +bool GossipHello_npc_kalaran_windblade(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(3441) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_kalaran_windblade(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(1954, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(1955, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(3441); + break; + } + return true; +} + +/*###### +## npc_lothos_riftwaker +######*/ + +#define GOSSIP_HELLO_LR "Teleport me to the Molten Core" + +bool GossipHello_npc_lothos_riftwaker(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestRewardStatus(7487) || pPlayer->GetQuestRewardStatus(7848)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_LR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lothos_riftwaker(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->TeleportTo(409, 1096, -467, -104.6, 3.64); + } + + return true; +} + +/*###### +## npc_zamael_lunthistle +######*/ + +#define GOSSIP_HELLO_ZL "Tell me your story" +#define GOSSIP_SELECT_ZL1 "Please continue..." +#define GOSSIP_SELECT_ZL2 "Goodbye" + +bool GossipHello_npc_zamael_lunthistle(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(3377) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_ZL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(1920, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_zamael_lunthistle(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_ZL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(1921, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_ZL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(1922, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(3377); + break; + } + return true; +} + +/*###### +## +######*/ + +void AddSC_searing_gorge() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_kalaran_windblade"; + newscript->pGossipHello = &GossipHello_npc_kalaran_windblade; + newscript->pGossipSelect = &GossipSelect_npc_kalaran_windblade; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lothos_riftwaker"; + newscript->pGossipHello = &GossipHello_npc_lothos_riftwaker; + newscript->pGossipSelect = &GossipSelect_npc_lothos_riftwaker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_zamael_lunthistle"; + newscript->pGossipHello = &GossipHello_npc_zamael_lunthistle; + newscript->pGossipSelect = &GossipSelect_npc_zamael_lunthistle; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp new file mode 100644 index 00000000000..20959641889 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp @@ -0,0 +1,277 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shadowfang_Keep +SD%Complete: 90 +SDComment: +SDCategory: Shadowfang Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadowfang_keep.h" + +#define MAX_ENCOUNTER 4 + +enum eEnums +{ + SAY_BOSS_DIE_AD = -1033007, + SAY_BOSS_DIE_AS = -1033008, + SAY_ARCHMAGE = -1033009, + + NPC_ASH = 3850, + NPC_ADA = 3849, + NPC_ARCHMAGE_ARUGAL = 4275, + NPC_ARUGAL_VOIDWALKER = 4627, + + GO_COURTYARD_DOOR = 18895, //door to open when talking to NPC's + GO_SORCERER_DOOR = 18972, //door to open when Fenrus the Devourer + GO_ARUGAL_DOOR = 18971, //door to open when Wolf Master Nandos + + SPELL_ASHCROMBE_TELEPORT = 15742 +}; + +const Position SpawnLocation[] = +{ + {-148.199,2165.647,128.448,1.026}, + {-153.110,2168.620,128.448,1.026}, + {-145.905,2180.520,128.448,4.183}, + {-140.794,2178.037,128.448,4.090}, + {-138.640,2170.159,136.577,2.737} +}; +struct instance_shadowfang_keep : public ScriptedInstance +{ + instance_shadowfang_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 uiAshGUID; + uint64 uiAdaGUID; + uint64 uiArchmageArugalGUID; + + uint64 DoorCourtyardGUID; + uint64 DoorSorcererGUID; + uint64 DoorArugalGUID; + + uint8 uiPhase; + uint16 uiTimer; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + uiAshGUID = 0; + uiAdaGUID = 0; + uiArchmageArugalGUID = 0; + + DoorCourtyardGUID = 0; + DoorSorcererGUID = 0; + DoorArugalGUID = 0; + + uiPhase = 0; + uiTimer = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_ASH: uiAshGUID = pCreature->GetGUID(); break; + case NPC_ADA: uiAdaGUID = pCreature->GetGUID(); break; + case NPC_ARCHMAGE_ARUGAL: uiArchmageArugalGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_COURTYARD_DOOR: + DoorCourtyardGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + HandleGameObject(NULL, true, pGo); + break; + case GO_SORCERER_DOOR: + DoorSorcererGUID = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + HandleGameObject(NULL, true, pGo); + break; + case GO_ARUGAL_DOOR: + DoorArugalGUID = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(NULL, true, pGo); + break; + } + } + + void DoSpeech() + { + Creature* pAda = instance->GetCreature(uiAdaGUID); + Creature* pAsh = instance->GetCreature(uiAshGUID); + + if (pAda && pAda->isAlive() && pAsh && pAsh->isAlive()) + { + DoScriptText(SAY_BOSS_DIE_AD,pAda); + DoScriptText(SAY_BOSS_DIE_AS,pAsh); + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_FREE_NPC: + if (data == DONE) + DoUseDoorOrButton(DoorCourtyardGUID); + m_auiEncounter[0] = data; + break; + case TYPE_RETHILGORE: + if (data == DONE) + DoSpeech(); + m_auiEncounter[1] = data; + break; + case TYPE_FENRUS: + switch(data) + { + case DONE: + uiTimer = 1000; + uiPhase = 1; + break; + case 7: + DoUseDoorOrButton(DoorSorcererGUID); + break; + } + m_auiEncounter[2] = data; + break; + case TYPE_NANDOS: + if (data == DONE) + DoUseDoorOrButton(DoorArugalGUID); + m_auiEncounter[3] = data; + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_FREE_NPC: + return m_auiEncounter[0]; + case TYPE_RETHILGORE: + return m_auiEncounter[1]; + case TYPE_FENRUS: + return m_auiEncounter[2]; + case TYPE_NANDOS: + return m_auiEncounter[3]; + } + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void Update(uint32 uiDiff) + { + if (GetData(TYPE_FENRUS) != DONE) + return; + + Creature* pArchmage = instance->GetCreature(uiArchmageArugalGUID); + Creature* pSummon = NULL; + + if (!pArchmage || !pArchmage->isAlive()) + return; + + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + pSummon = pArchmage->SummonCreature(pArchmage->GetEntry(),SpawnLocation[4],TEMPSUMMON_TIMED_DESPAWN,10000); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pSummon->SetReactState(REACT_DEFENSIVE); + pSummon->CastSpell(pSummon,SPELL_ASHCROMBE_TELEPORT,true); + DoScriptText(SAY_ARCHMAGE,pSummon); + uiTimer = 2000; + uiPhase = 2; + break; + case 2: + pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[0],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[1],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[2],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + uiPhase = 0; + break; + + } + } else uiTimer -= uiDiff; + } + } +}; + +InstanceData* GetInstanceData_instance_shadowfang_keep(Map* pMap) +{ + return new instance_shadowfang_keep(pMap); +} + +void AddSC_instance_shadowfang_keep() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shadowfang_keep"; + newscript->GetInstanceData = &GetInstanceData_instance_shadowfang_keep; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp new file mode 100644 index 00000000000..23b8ad89160 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp @@ -0,0 +1,198 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Shadowfang_Keep +SD%Complete: 75 +SDComment: npc_shadowfang_prisoner using escortAI for movement to door. Might need additional code in case being attacked. Add proper texts/say(). +SDCategory: Shadowfang Keep +EndScriptData */ + +/* ContentData +npc_shadowfang_prisoner +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "shadowfang_keep.h" + +/*###### +## npc_shadowfang_prisoner +######*/ + +enum eEnums +{ + SAY_FREE_AS = -1033000, + SAY_OPEN_DOOR_AS = -1033001, + SAY_POST_DOOR_AS = -1033002, + SAY_FREE_AD = -1033003, + SAY_OPEN_DOOR_AD = -1033004, + SAY_POST1_DOOR_AD = -1033005, + SAY_POST2_DOOR_AD = -1033006, + + SPELL_UNLOCK = 6421, + NPC_ASH = 3850, + + SPELL_DARK_OFFERING = 7154 +}; + +#define GOSSIP_ITEM_DOOR "Thanks, I'll follow you to the door." + +struct npc_shadowfang_prisonerAI : public npc_escortAI +{ + npc_shadowfang_prisonerAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + uiNpcEntry = c->GetEntry(); + } + + ScriptedInstance *pInstance; + uint32 uiNpcEntry; + + void WaypointReached(uint32 uiPoint) + { + switch(uiPoint) + { + case 0: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_FREE_AS, me); + else + DoScriptText(SAY_FREE_AD, me); + break; + case 10: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_OPEN_DOOR_AS, me); + else + DoScriptText(SAY_OPEN_DOOR_AD, me); + break; + case 11: + if (uiNpcEntry == NPC_ASH) + DoCast(me, SPELL_UNLOCK); + break; + case 12: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_POST_DOOR_AS, me); + else + DoScriptText(SAY_POST1_DOOR_AD, me); + + if (pInstance) + pInstance->SetData(TYPE_FREE_NPC, DONE); + break; + case 13: + if (uiNpcEntry != NPC_ASH) + DoScriptText(SAY_POST2_DOOR_AD, me); + break; + } + } + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} +}; + +CreatureAI* GetAI_npc_shadowfang_prisoner(Creature* pCreature) +{ + return new npc_shadowfang_prisonerAI(pCreature); +} + +bool GossipHello_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && pInstance->GetData(TYPE_FREE_NPC) != DONE && pInstance->GetData(TYPE_RETHILGORE) == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DOOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_shadowfang_prisonerAI, pCreature->AI())) + pEscortAI->Start(false, false); + } + return true; +} + +struct npc_arugal_voidwalkerAI : public ScriptedAI +{ + npc_arugal_voidwalkerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiDarkOffering; + + void Reset() + { + uiDarkOffering = urand(290,10); + } + + void UpdateAI(uint32 const uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiDarkOffering <= uiDiff) + { + if (Creature* pFriend = me->FindNearestCreature(me->GetEntry(),25.0f,true)) + { + if (pFriend) + DoCast(pFriend,SPELL_DARK_OFFERING); + } + else + DoCast(me,SPELL_DARK_OFFERING); + uiDarkOffering = urand(4400,12500); + } else uiDarkOffering -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(TYPE_FENRUS, pInstance->GetData(TYPE_FENRUS) + 1); + } +}; + +CreatureAI* GetAI_npc_arugal_voidwalker(Creature* pCreature) +{ + return new npc_arugal_voidwalkerAI(pCreature); +} + +void AddSC_shadowfang_keep() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_shadowfang_prisoner"; + newscript->pGossipHello = &GossipHello_npc_shadowfang_prisoner; + newscript->pGossipSelect = &GossipSelect_npc_shadowfang_prisoner; + newscript->GetAI = &GetAI_npc_shadowfang_prisoner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_arugal_voidwalker"; + newscript->GetAI = &GetAI_npc_arugal_voidwalker; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h b/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h new file mode 100644 index 00000000000..a1a59789632 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHADOWFANG_H +#define DEF_SHADOWFANG_H + +enum eData +{ + TYPE_FREE_NPC = 1, + TYPE_RETHILGORE = 2, + TYPE_FENRUS = 3, + TYPE_NANDOS = 4 +}; + +#endif + diff --git a/src/server/scripts/EasternKingdoms/silvermoon_city.cpp b/src/server/scripts/EasternKingdoms/silvermoon_city.cpp new file mode 100644 index 00000000000..390f083be48 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/silvermoon_city.cpp @@ -0,0 +1,102 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Silvermoon_City +SD%Complete: 100 +SDComment: Quest support: 9685 +SDCategory: Silvermoon City +EndScriptData */ + +/* ContentData +npc_blood_knight_stillblade +EndContentData */ + +#include "ScriptedPch.h" + +/*####### +# npc_blood_knight_stillblade +#######*/ + +#define SAY_HEAL -1000334 + +#define QUEST_REDEEMING_THE_DEAD 9685 +#define SPELL_SHIMMERING_VESSEL 31225 +#define SPELL_REVIVE_SELF 32343 + +struct npc_blood_knight_stillbladeAI : public ScriptedAI +{ + npc_blood_knight_stillbladeAI(Creature *c) : ScriptedAI(c) {} + + uint32 lifeTimer; + bool spellHit; + + void Reset() + { + lifeTimer = 120000; + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetUInt32Value(UNIT_FIELD_BYTES_1,7); // lay down + spellHit = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void MoveInLineOfSight(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (me->IsStandState()) + { + if (lifeTimer <= diff) + me->AI()->EnterEvadeMode(); + else + lifeTimer -= diff; + } + } + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) + { + if ((Spellkind->Id == SPELL_SHIMMERING_VESSEL) && !spellHit && + (Hitter->GetTypeId() == TYPEID_PLAYER) && (CAST_PLR(Hitter)->IsActiveQuest(QUEST_REDEEMING_THE_DEAD))) + { + CAST_PLR(Hitter)->AreaExploredOrEventHappens(QUEST_REDEEMING_THE_DEAD); + DoCast(me, SPELL_REVIVE_SELF); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + //me->RemoveAllAuras(); + DoScriptText(SAY_HEAL, me); + spellHit = true; + } + } +}; + +CreatureAI* GetAI_npc_blood_knight_stillblade(Creature* pCreature) +{ + return new npc_blood_knight_stillbladeAI (pCreature); +} + +void AddSC_silvermoon_city() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "npc_blood_knight_stillblade"; + newscript->GetAI = &GetAI_npc_blood_knight_stillblade; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/silverpine_forest.cpp b/src/server/scripts/EasternKingdoms/silverpine_forest.cpp new file mode 100644 index 00000000000..dd67f048f32 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/silverpine_forest.cpp @@ -0,0 +1,385 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Silverpine_Forest +SD%Complete: 100 +SDComment: Quest support: 1886, 435, 452 +SDCategory: Silverpine Forest +EndScriptData */ + +/* ContentData +npc_astor_hadren +npc_deathstalker_erland +pyrewood_ambush +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_astor_hadren +######*/ + +#define GOSSIP_HAH "You're Astor Hadren, right?" +#define GOSSIP_SAH "You've got something I need, Astor. And I'll be taking it now." + +struct npc_astor_hadrenAI : public ScriptedAI +{ + npc_astor_hadrenAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + me->setFaction(68); + } + + void EnterCombat(Unit* /*who*/) + { + } + + void JustDied(Unit * /*who*/) + { + me->setFaction(68); + } +}; + +CreatureAI* GetAI_npc_astor_hadren(Creature* pCreature) +{ + return new npc_astor_hadrenAI(pCreature); +} + +bool GossipHello_npc_astor_hadren(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(1886) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HAH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(623, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_astor_hadren(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SAH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(624, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(21); + if (pPlayer) + CAST_AI(npc_astor_hadrenAI, pCreature->AI())->AttackStart(pPlayer); + break; + } + return true; +} + +/*###### +## npc_deathstalker_erland +######*/ + +enum eErland +{ + SAY_QUESTACCEPT = -1000306, + SAY_START = -1000307, + SAY_AGGRO_1 = -1000308, + SAY_AGGRO_2 = -1000309, + SAY_LAST = -1000310, + + SAY_THANKS = -1000311, + SAY_RANE = -1000312, + SAY_ANSWER = -1000313, + SAY_MOVE_QUINN = -1000314, + + SAY_GREETINGS = -1000315, + SAY_QUINN = -1000316, + SAY_ON_BYE = -1000317, + + QUEST_ESCORTING = 435, + NPC_RANE = 1950, + NPC_QUINN = 1951 +}; + +struct npc_deathstalker_erlandAI : public npc_escortAI +{ + npc_deathstalker_erlandAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 1: DoScriptText(SAY_START, me, pPlayer);break; + case 13: + DoScriptText(SAY_LAST, me, pPlayer); + pPlayer->GroupEventHappens(QUEST_ESCORTING, me); break; + case 14: DoScriptText(SAY_THANKS, me, pPlayer); break; + case 15: { + Unit* Rane = me->FindNearestCreature(NPC_RANE, 20); + if (Rane) + DoScriptText(SAY_RANE, Rane); + break;} + case 16: DoScriptText(SAY_ANSWER, me); break; + case 17: DoScriptText(SAY_MOVE_QUINN, me); break; + case 24: DoScriptText(SAY_GREETINGS, me); break; + case 25: { + Unit* Quinn = me->FindNearestCreature(NPC_QUINN, 20); + if (Quinn) + DoScriptText(SAY_QUINN, Quinn); + break;} + case 26: DoScriptText(SAY_ON_BYE, me, NULL); break; + + } + } + + void Reset() {} + + void EnterCombat(Unit* who) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me, who); + } +}; + +bool QuestAccept_npc_deathstalker_erland(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_ESCORTING) + { + DoScriptText(SAY_QUESTACCEPT, pCreature, pPlayer); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_deathstalker_erlandAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + } + + return true; +} + +CreatureAI* GetAI_npc_deathstalker_erlandAI(Creature* pCreature) +{ + return new npc_deathstalker_erlandAI(pCreature); +} + +/*###### +## pyrewood_ambush +#######*/ + +#define QUEST_PYREWOOD_AMBUSH 452 + +#define NPCSAY_INIT "Get ready, they'll be arriving any minute..." //not blizzlike +#define NPCSAY_END "Thanks for your help!" //not blizzlike + +static float PyrewoodSpawnPoints[3][4] = +{ + //pos_x pos_y pos_z orien + //outside + /* + {-400.85, 1513.64, 18.67, 0}, + {-397.32, 1514.12, 18.67, 0}, + {-397.44, 1511.09, 18.67, 0}, + */ + //door + {-396.17, 1505.86, 19.77, 0}, + {-396.91, 1505.77, 19.77, 0}, + {-397.94, 1504.74, 19.77, 0}, +}; + +#define WAIT_SECS 6000 + +struct pyrewood_ambushAI : public ScriptedAI +{ + pyrewood_ambushAI(Creature *c) : ScriptedAI(c), Summons(me) + { + QuestInProgress = false; + } + + uint32 Phase; + int8 KillCount; + uint32 WaitTimer; + uint64 PlayerGUID; + SummonList Summons; + + bool QuestInProgress; + + void Reset() + { + WaitTimer = WAIT_SECS; + + if (!QuestInProgress) //fix reset values (see UpdateVictim) + { + Phase = 0; + KillCount = 0; + PlayerGUID = 0; + Summons.DespawnAll(); + } + } + + void Aggro(Unit * /*who*/){} + + void JustSummoned(Creature *pSummoned) + { + Summons.Summon(pSummoned); + ++KillCount; + } + + void SummonedCreatureDespawn(Creature *pSummoned) + { + Summons.Despawn(pSummoned); + --KillCount; + } + + void SummonCreatureWithRandomTarget(uint32 creatureId, int position) + { + if (Creature *pSummoned = me->SummonCreature(creatureId, PyrewoodSpawnPoints[position][0], PyrewoodSpawnPoints[position][1], PyrewoodSpawnPoints[position][2], PyrewoodSpawnPoints[position][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000)) + { + Player *pPlayer = NULL; + Unit *pTarget = NULL; + if (PlayerGUID) + { + pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer) + pTarget = RAND((Unit*)me, (Unit*)pPlayer); + } else + pTarget = me; + + if (pTarget) + { + pSummoned->setFaction(168); + pSummoned->AddThreat(pTarget, 32.0f); + pSummoned->AI()->AttackStart(pTarget); + } + } + } + + void JustDied(Unit * /*pKiller*/) + { + if (PlayerGUID) + if (Player *pPlayer = Unit::GetPlayer(PlayerGUID)) + if (pPlayer->GetQuestStatus(QUEST_PYREWOOD_AMBUSH) == QUEST_STATUS_INCOMPLETE) + pPlayer->FailQuest(QUEST_PYREWOOD_AMBUSH); + } + + void UpdateAI(const uint32 diff) + { + //sLog.outString("DEBUG: p(%i) k(%i) d(%u) W(%i)", Phase, KillCount, diff, WaitTimer); + + if (!QuestInProgress) + return; + + if (KillCount && Phase < 6) + { + if (!UpdateVictim()) //reset() on target Despawn... + return; + + DoMeleeAttackIfReady(); + return; + } + + switch (Phase) + { + case 0: + if (WaitTimer == WAIT_SECS) + me->MonsterSay(NPCSAY_INIT, LANG_UNIVERSAL, 0); //no blizzlike + + if (WaitTimer <= diff) + { + WaitTimer -= diff; + return; + } + break; + case 1: + SummonCreatureWithRandomTarget(2060, 1); + break; + case 2: + SummonCreatureWithRandomTarget(2061, 2); + SummonCreatureWithRandomTarget(2062, 0); + break; + case 3: + SummonCreatureWithRandomTarget(2063, 1); + SummonCreatureWithRandomTarget(2064, 2); + SummonCreatureWithRandomTarget(2065, 0); + break; + case 4: + SummonCreatureWithRandomTarget(2066, 1); + SummonCreatureWithRandomTarget(2067, 0); + SummonCreatureWithRandomTarget(2068, 2); + break; + case 5: //end + if (PlayerGUID) + { + if (Player *pPlayer = Unit::GetPlayer(PlayerGUID)) + { + me->MonsterSay(NPCSAY_END, LANG_UNIVERSAL, 0); //not blizzlike + pPlayer->GroupEventHappens(QUEST_PYREWOOD_AMBUSH, me); + } + } + QuestInProgress = false; + Reset(); + break; + } + ++Phase; //prepare next phase + } +}; + +CreatureAI* GetAI_pyrewood_ambush(Creature *pCreature) +{ + return new pyrewood_ambushAI (pCreature); +} + +bool QuestAccept_pyrewood_ambush(Player *pPlayer, Creature *pCreature, const Quest *pQuest) +{ + if (pQuest->GetQuestId() == QUEST_PYREWOOD_AMBUSH && !CAST_AI(pyrewood_ambushAI, pCreature->AI())->QuestInProgress) + { + CAST_AI(pyrewood_ambushAI, pCreature->AI())->QuestInProgress = true; + CAST_AI(pyrewood_ambushAI, pCreature->AI())->Phase = 0; + CAST_AI(pyrewood_ambushAI, pCreature->AI())->KillCount = 0; + CAST_AI(pyrewood_ambushAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); + } + + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_silverpine_forest() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_astor_hadren"; + newscript->pGossipHello = &GossipHello_npc_astor_hadren; + newscript->pGossipSelect = &GossipSelect_npc_astor_hadren; + newscript->GetAI = &GetAI_npc_astor_hadren; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_deathstalker_erland"; + newscript->GetAI = &GetAI_npc_deathstalker_erlandAI; + newscript->pQuestAccept = &QuestAccept_npc_deathstalker_erland; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "pyrewood_ambush"; + newscript->GetAI = &GetAI_pyrewood_ambush; + newscript->pQuestAccept = &QuestAccept_pyrewood_ambush; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/stormwind_city.cpp b/src/server/scripts/EasternKingdoms/stormwind_city.cpp new file mode 100644 index 00000000000..36a7d116c3b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stormwind_city.cpp @@ -0,0 +1,696 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Stormwind_City +SD%Complete: 100 +SDComment: Quest support: 1640, 1447, 4185, 11223, 434. +SDCategory: Stormwind City +EndScriptData */ + +/* ContentData +npc_archmage_malin +npc_bartleby +npc_dashel_stonefist +npc_lady_katrana_prestor +npc_tyrion +npc_tyrion_spybot +npc_marzon_silent_blade +npc_lord_gregor_lescovar +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_archmage_malin +######*/ + +#define GOSSIP_ITEM_MALIN "Can you send me to Theramore? I have an urgent message for Lady Jaina from Highlord Bolvar." + +bool GossipHello_npc_archmage_malin(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(11223) == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(11223)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MALIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_archmage_malin(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, 42711, true); + } + + return true; +} + +/*###### +## npc_bartleby +######*/ + +enum eBartleby +{ + FACTION_ENEMY = 168, + QUEST_BEAT = 1640 +}; + +struct npc_bartlebyAI : public ScriptedAI +{ + npc_bartlebyAI(Creature *c) : ScriptedAI(c) + { + m_uiNormalFaction = c->getFaction(); + } + + uint32 m_uiNormalFaction; + + void Reset() + { + if (me->getFaction() != m_uiNormalFaction) + me->setFaction(m_uiNormalFaction); + } + + void AttackedBy(Unit* pAttacker) + { + if (me->getVictim()) + return; + + if (me->IsFriendlyTo(pAttacker)) + return; + + AttackStart(pAttacker); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > me->GetHealth() || ((me->GetHealth() - uiDamage)*100 / me->GetMaxHealth() < 15)) + { + //Take 0 damage + uiDamage = 0; + + if (pDoneBy->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(pDoneBy)->AreaExploredOrEventHappens(QUEST_BEAT); + EnterEvadeMode(); + } + } +}; + +bool QuestAccept_npc_bartleby(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_BEAT) + { + pCreature->setFaction(FACTION_ENEMY); + pCreature->AI()->AttackStart(pPlayer); + } + return true; +} + +CreatureAI* GetAI_npc_bartleby(Creature* pCreature) +{ + return new npc_bartlebyAI(pCreature); +} + +/*###### +## npc_dashel_stonefist +######*/ + +enum eDashel +{ + QUEST_MISSING_DIPLO_PT8 = 1447, + FACTION_HOSTILE = 168 +}; + +struct npc_dashel_stonefistAI : public ScriptedAI +{ + npc_dashel_stonefistAI(Creature *c) : ScriptedAI(c) + { + m_uiNormalFaction = c->getFaction(); + } + + uint32 m_uiNormalFaction; + + void Reset() + { + if (me->getFaction() != m_uiNormalFaction) + me->setFaction(m_uiNormalFaction); + } + + void AttackedBy(Unit* pAttacker) + { + if (me->getVictim()) + return; + + if (me->IsFriendlyTo(pAttacker)) + return; + + AttackStart(pAttacker); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > me->GetHealth() || ((me->GetHealth() - uiDamage)*100 / me->GetMaxHealth() < 15)) + { + uiDamage = 0; + + if (pDoneBy->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(pDoneBy)->AreaExploredOrEventHappens(QUEST_MISSING_DIPLO_PT8); + + EnterEvadeMode(); + } + } +}; + +bool QuestAccept_npc_dashel_stonefist(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT8) + { + pCreature->setFaction(FACTION_HOSTILE); + CAST_AI(npc_dashel_stonefistAI, pCreature->AI())->AttackStart(pPlayer); + } + return true; +} + +CreatureAI* GetAI_npc_dashel_stonefist(Creature* pCreature) +{ + return new npc_dashel_stonefistAI(pCreature); +} + +/*###### +## npc_lady_katrana_prestor +######*/ + +#define GOSSIP_ITEM_KAT_1 "Pardon the intrusion, Lady Prestor, but Highlord Bolvar suggested that I seek your advice." +#define GOSSIP_ITEM_KAT_2 "My apologies, Lady Prestor." +#define GOSSIP_ITEM_KAT_3 "Begging your pardon, Lady Prestor. That was not my intent." +#define GOSSIP_ITEM_KAT_4 "Thank you for your time, Lady Prestor." + +bool GossipHello_npc_lady_katrana_prestor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(4185) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(2693, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lady_katrana_prestor(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2694, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(2695, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(2696, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(4185); + break; + } + return true; +} + +/*###### +## npc_lord_gregor_lescovar +######*/ + +enum eLordGregorLescovar +{ + SAY_LESCOVAR_2 = -1000457, + SAY_GUARD_2 = -1000458, + SAY_LESCOVAR_3 = -1000459, + SAY_MARZON_1 = -1000460, + SAY_LESCOVAR_4 = -1000461, + SAY_TYRION_2 = -1000462, + SAY_MARZON_2 = -1000463, + + NPC_STORMWIND_ROYAL = 1756, + NPC_MARZON_BLADE = 1755, + NPC_TYRION = 7766, + + QUEST_THE_ATTACK = 434 +}; + +struct npc_lord_gregor_lescovarAI : public npc_escortAI +{ + npc_lord_gregor_lescovarAI(Creature* pCreature) : npc_escortAI(pCreature) + { + pCreature->RestoreFaction(); + } + + uint32 uiTimer; + uint32 uiPhase; + + uint64 MarzonGUID; + + void Reset() + { + uiTimer = 0; + uiPhase = 0; + + MarzonGUID = 0; + } + + void EnterEvadeMode() + { + me->DisappearAndDie(); + + if (Creature *pMarzon = Unit::GetCreature(*me, MarzonGUID)) + { + if (pMarzon->isAlive()) + pMarzon->DisappearAndDie(); + } + } + + void EnterCombat(Unit* pWho) + { + if (Creature *pMarzon = Unit::GetCreature(*me, MarzonGUID)) + { + if (pMarzon->isAlive() && !pMarzon->isInCombat()) + pMarzon->AI()->AttackStart(pWho); + } + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 14: + SetEscortPaused(true); + DoScriptText(SAY_LESCOVAR_2, me); + uiTimer = 3000; + uiPhase = 1; + break; + case 16: + SetEscortPaused(true); + if (Creature *pMarzon = me->SummonCreature(NPC_MARZON_BLADE,-8411.360352, 480.069733, 123.760895, 4.941504, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000)) + { + pMarzon->GetMotionMaster()->MovePoint(0,-8408.000977, 468.611450, 123.759903); + MarzonGUID = pMarzon->GetGUID(); + } + uiTimer = 2000; + uiPhase = 4; + break; + } + } + //TO-DO: We don't have movemaps, also we can't make 2 npcs walks to one point propperly (and we can not use escort ai, because they are 2 different spawns and with same entry), because of it we make them, disappear. + void DoGuardsDisappearAndDie() + { + std::list GuardList; + me->GetCreatureListWithEntryInGrid(GuardList,NPC_STORMWIND_ROYAL,8.0f); + if (!GuardList.empty()) + { + for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + { + if (Creature* pGuard = *itr) + pGuard->DisappearAndDie(); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + if (Creature* pGuard = me->FindNearestCreature(NPC_STORMWIND_ROYAL, 8.0f, true)) + DoScriptText(SAY_GUARD_2, pGuard); + uiTimer = 3000; + uiPhase = 2; + break; + case 2: + DoGuardsDisappearAndDie(); + uiTimer = 2000; + uiPhase = 3; + break; + case 3: + SetEscortPaused(false); + uiTimer = 0; + uiPhase = 0; + break; + case 4: + DoScriptText(SAY_LESCOVAR_3, me); + uiTimer = 0; + uiPhase = 0; + break; + case 5: + if (Creature *pMarzon = Unit::GetCreature(*me, MarzonGUID)) + DoScriptText(SAY_MARZON_1, pMarzon); + uiTimer = 3000; + uiPhase = 6; + break; + case 6: + DoScriptText(SAY_LESCOVAR_4, me); + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->AreaExploredOrEventHappens(QUEST_THE_ATTACK); + uiTimer = 2000; + uiPhase = 7; + break; + case 7: + if (Creature* pTyrion = me->FindNearestCreature(NPC_TYRION, 20.0f, true)) + DoScriptText(SAY_TYRION_2, pTyrion); + if (Creature *pMarzon = Unit::GetCreature(*me, MarzonGUID)) + pMarzon->setFaction(14); + me->setFaction(14); + uiTimer = 0; + uiPhase = 0; + break; + } + } else uiTimer -= uiDiff; + } + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_lord_gregor_lescovar(Creature* pCreature) +{ + return new npc_lord_gregor_lescovarAI(pCreature); +} + +/*###### +## npc_marzon_silent_blade +######*/ + +struct npc_marzon_silent_bladeAI : public ScriptedAI +{ + npc_marzon_silent_bladeAI(Creature* pCreature) : ScriptedAI(pCreature) + { + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + } + + void Reset() + { + me->RestoreFaction(); + } + + void EnterCombat(Unit* pWho) + { + DoScriptText(SAY_MARZON_2, me); + + if (me->isSummon()) + { + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + { + if (pSummoner && pSummoner->isAlive() && !pSummoner->isInCombat()) + CAST_CRE(pSummoner)->AI()->AttackStart(pWho); + } + } + } + + void EnterEvadeMode() + { + me->DisappearAndDie(); + + if (me->isSummon()) + { + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + { + if (pSummoner && pSummoner->isAlive()) + CAST_CRE(pSummoner)->DisappearAndDie(); + } + } + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (me->isSummon()) + { + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + { + CAST_AI(npc_lord_gregor_lescovarAI, CAST_CRE(pSummoner)->AI())->uiTimer = 2000; + CAST_AI(npc_lord_gregor_lescovarAI, CAST_CRE(pSummoner)->AI())->uiPhase = 5; + //me->ChangeOrient(0.0f, pSummoner); + } + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_marzon_silent_blade(Creature* pCreature) +{ + return new npc_marzon_silent_bladeAI(pCreature); +} + +/*###### +## npc_tyrion_spybot +######*/ + +enum eTyrionSpybot +{ + SAY_QUEST_ACCEPT_ATTACK = -1000499, + SAY_TYRION_1 = -1000450, + SAY_SPYBOT_1 = -1000451, + SAY_GUARD_1 = -1000452, + SAY_SPYBOT_2 = -1000453, + SAY_SPYBOT_3 = -1000454, + SAY_LESCOVAR_1 = -1000455, + SAY_SPYBOT_4 = -1000456, + + NPC_PRIESTESS_TYRIONA = 7779, + NPC_LORD_GREGOR_LESCOVAR = 1754, +}; + +struct npc_tyrion_spybotAI : public npc_escortAI +{ + npc_tyrion_spybotAI(Creature* pCreature) : npc_escortAI(pCreature) {} + + uint32 uiTimer; + uint32 uiPhase; + + void Reset() + { + uiTimer = 0; + uiPhase = 0; + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 1: + SetEscortPaused(true); + uiTimer = 2000; + uiPhase = 1; + break; + case 5: + SetEscortPaused(true); + DoScriptText(SAY_SPYBOT_1, me); + uiTimer = 2000; + uiPhase = 5; + break; + case 17: + SetEscortPaused(true); + DoScriptText(SAY_SPYBOT_3, me); + uiTimer = 3000; + uiPhase = 8; + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + DoScriptText(SAY_QUEST_ACCEPT_ATTACK, me); + uiTimer = 3000; + uiPhase = 2; + break; + case 2: + if (Creature* pTyrion = me->FindNearestCreature(NPC_TYRION,10.0f)) + DoScriptText(SAY_TYRION_1, pTyrion); + uiTimer = 3000; + uiPhase = 3; + break; + case 3: + me->UpdateEntry(NPC_PRIESTESS_TYRIONA, ALLIANCE); + uiTimer = 2000; + uiPhase = 4; + break; + case 4: + SetEscortPaused(false); + uiPhase = 0; + uiTimer = 0; + break; + case 5: + if (Creature* pGuard = me->FindNearestCreature(NPC_STORMWIND_ROYAL, 10.0f, true)) + DoScriptText(SAY_GUARD_1, pGuard); + uiTimer = 3000; + uiPhase = 6; + break; + case 6: + DoScriptText(SAY_SPYBOT_2, me); + uiTimer = 3000; + uiPhase = 7; + break; + case 7: + SetEscortPaused(false); + uiTimer = 0; + uiPhase = 0; + break; + case 8: + if (Creature* pLescovar = me->FindNearestCreature(NPC_LORD_GREGOR_LESCOVAR,10.0f)) + DoScriptText(SAY_LESCOVAR_1, pLescovar); + uiTimer = 3000; + uiPhase = 9; + break; + case 9: + DoScriptText(SAY_SPYBOT_4, me); + uiTimer = 3000; + uiPhase = 10; + break; + case 10: + if (Creature* pLescovar = me->FindNearestCreature(NPC_LORD_GREGOR_LESCOVAR,10.0f)) + { + if (Player* pPlayer = GetPlayerForEscort()) + { + CAST_AI(npc_lord_gregor_lescovarAI,pLescovar->AI())->Start(false, false, pPlayer->GetGUID()); + CAST_AI(npc_lord_gregor_lescovarAI, pLescovar->AI())->SetMaxPlayerDistance(200.0f); + } + } + me->DisappearAndDie(); + uiTimer = 0; + uiPhase = 0; + break; + } + } else uiTimer -= uiDiff; + } + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_tyrion_spybot(Creature* pCreature) +{ + return new npc_tyrion_spybotAI(pCreature); +} + +/*###### +## npc_tyrion +######*/ + +enum eTyrion +{ + NPC_TYRION_SPYBOT = 8856 +}; + +bool QuestAccept_npc_tyrion(Player* pPlayer, Creature* pCreature, Quest const *pQuest) +{ + if (pQuest->GetQuestId() == QUEST_THE_ATTACK) + { + if (Creature* pSpybot = pCreature->FindNearestCreature(NPC_TYRION_SPYBOT, 5.0f, true)) + { + CAST_AI(npc_tyrion_spybotAI,pSpybot->AI())->Start(false, false, pPlayer->GetGUID()); + CAST_AI(npc_tyrion_spybotAI,pSpybot->AI())->SetMaxPlayerDistance(200.0f); + } + return true; + } + return false; +} + +void AddSC_stormwind_city() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_archmage_malin"; + newscript->pGossipHello = &GossipHello_npc_archmage_malin; + newscript->pGossipSelect = &GossipSelect_npc_archmage_malin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bartleby"; + newscript->GetAI = &GetAI_npc_bartleby; + newscript->pQuestAccept = &QuestAccept_npc_bartleby; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dashel_stonefist"; + newscript->GetAI = &GetAI_npc_dashel_stonefist; + newscript->pQuestAccept = &QuestAccept_npc_dashel_stonefist; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lady_katrana_prestor"; + newscript->pGossipHello = &GossipHello_npc_lady_katrana_prestor; + newscript->pGossipSelect = &GossipSelect_npc_lady_katrana_prestor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tyrion"; + newscript->pQuestAccept = &QuestAccept_npc_tyrion; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tyrion_spybot"; + newscript->GetAI = &GetAI_npc_tyrion_spybot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lord_gregor_lescovar"; + newscript->GetAI = &GetAI_npc_lord_gregor_lescovar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_marzon_silent_blade"; + newscript->GetAI = &GetAI_npc_marzon_silent_blade; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/stranglethorn_vale.cpp b/src/server/scripts/EasternKingdoms/stranglethorn_vale.cpp new file mode 100644 index 00000000000..08d364d1808 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stranglethorn_vale.cpp @@ -0,0 +1,122 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Stranglethorn_Vale +SD%Complete: 100 +SDComment: Quest support: 592 +SDCategory: Stranglethorn Vale +EndScriptData */ + +/* ContentData +mob_yenniku +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## mob_yenniku +######*/ + +struct mob_yennikuAI : public ScriptedAI +{ + mob_yennikuAI(Creature *c) : ScriptedAI(c) + { + bReset = false; + } + + uint32 Reset_Timer; + bool bReset; + + void Reset() + { + Reset_Timer = 0; + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + //Yenniku's Release + if (!bReset && CAST_PLR(caster)->GetQuestStatus(592) == QUEST_STATUS_INCOMPLETE && spell->Id == 3607) + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); + me->CombatStop(); //stop combat + me->DeleteThreatList(); //unsure of this + me->setFaction(83); //horde generic + + bReset = true; + Reset_Timer = 60000; + } + } + return; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (bReset) + { + if (Reset_Timer <= diff) + { + EnterEvadeMode(); + bReset = false; + me->setFaction(28); //troll, bloodscalp + return; + } + else Reset_Timer -= diff; + + if (me->isInCombat() && me->getVictim()) + { + if (me->getVictim()->GetTypeId() == TYPEID_PLAYER) + { + Unit *victim = me->getVictim(); + if (CAST_PLR(victim)->GetTeam() == HORDE) + { + me->CombatStop(); + me->DeleteThreatList(); + } + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_yenniku(Creature* pCreature) +{ + return new mob_yennikuAI (pCreature); +} + +/*###### +## +######*/ + +void AddSC_stranglethorn_vale() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_yenniku"; + newscript->GetAI = &GetAI_mob_yenniku; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp new file mode 100644 index 00000000000..de17717e289 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp @@ -0,0 +1,190 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Baron_Rivendare +SD%Complete: 70 +SDComment: aura applied/defined in database +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SAY_0 "Intruders! More pawns of the Argent Dawn, no doubt. I already count one of their number among my prisoners. Withdraw from my domain before she is executed!" +#define SAY_1 "You're still here? Your foolishness is amusing! The Argent Dawn wench needn't suffer in vain. Leave at once and she shall be spared!" +#define SAY_2 "I shall take great pleasure in taking this poor wretch's life! It's not too late, she needn't suffer in vain. Turn back and her death shall be merciful!" +#define SAY_3 "May this prisoner's death serve as a warning. None shall defy the Scourge and live!" +#define SAY_4 "So you see fit to toy with the Lich King's creations? Ramstein, be sure to give the intruders a proper greeting." +#define SAY_5 "Time to take matters into my own hands. Come. Enter my domain and challenge the might of the Scourge!" + +#define ADD_1X 4017.403809 +#define ADD_1Y -3339.703369 +#define ADD_1Z 115.057655 +#define ADD_1O 5.487860 + +#define ADD_2X 4013.189209 +#define ADD_2Y -3351.808350 +#define ADD_2Z 115.052254 +#define ADD_2O 0.134280 + +#define ADD_3X 4017.738037 +#define ADD_3Y -3363.478016 +#define ADD_3Z 115.057274 +#define ADD_3O 0.723313 + +#define ADD_4X 4048.877197 +#define ADD_4Y -3363.223633 +#define ADD_4Z 115.054253 +#define ADD_4O 3.627735 + +#define ADD_5X 4051.777588 +#define ADD_5Y -3350.893311 +#define ADD_5Z 115.055351 +#define ADD_5O 3.066176 + +#define ADD_6X 4048.375977 +#define ADD_6Y -3339.966309 +#define ADD_6Z 115.055222 +#define ADD_6O 2.457497 + +#define SPELL_SHADOWBOLT 17393 +#define SPELL_CLEAVE 15284 +#define SPELL_MORTALSTRIKE 15708 + +#define SPELL_UNHOLY_AURA 17467 +#define SPELL_RAISEDEAD 17473 //triggers death pact (17471) + +#define SPELL_RAISE_DEAD1 17475 +#define SPELL_RAISE_DEAD2 17476 +#define SPELL_RAISE_DEAD3 17477 +#define SPELL_RAISE_DEAD4 17478 +#define SPELL_RAISE_DEAD5 17479 +#define SPELL_RAISE_DEAD6 17480 + +struct boss_baron_rivendareAI : public ScriptedAI +{ + boss_baron_rivendareAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ShadowBolt_Timer; + uint32 Cleave_Timer; + uint32 MortalStrike_Timer; + // uint32 RaiseDead_Timer; + uint32 SummonSkeletons_Timer; + + void Reset() + { + ShadowBolt_Timer = 5000; + Cleave_Timer = 8000; + MortalStrike_Timer = 12000; + // RaiseDead_Timer = 30000; + SummonSkeletons_Timer = 34000; + if (pInstance && pInstance->GetData(TYPE_RAMSTEIN) == DONE) + pInstance->SetData(TYPE_BARON,NOT_STARTED); + } + + void AttackStart(Unit* who) + { + if (pInstance)//can't use entercombat(), boss' dmg aura sets near players in combat, before entering the room's door + pInstance->SetData(TYPE_BARON,IN_PROGRESS); + ScriptedAI::AttackStart(who); + } + + void JustSummoned(Creature* summoned) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(pTarget); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_BARON,DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowBolt + if (ShadowBolt_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(me->getVictim(), SPELL_SHADOWBOLT); + + ShadowBolt_Timer = 10000; + } else ShadowBolt_Timer -= diff; + + //Cleave + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + //13 seconds until we should cast this again + Cleave_Timer = 7000 + (rand()%10000); + } else Cleave_Timer -= diff; + + //MortalStrike + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 10000 + (rand()%15000); + } else MortalStrike_Timer -= diff; + + //RaiseDead + // if (RaiseDead_Timer <= diff) + // { + // DoCast(me, SPELL_RAISEDEAD); + // RaiseDead_Timer = 45000; + // } else RaiseDead_Timer -= diff; + + //SummonSkeletons + if (SummonSkeletons_Timer <= diff) + { + me->SummonCreature(11197,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,29000); + + //34 seconds until we should cast this again + SummonSkeletons_Timer = 40000; + } else SummonSkeletons_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_baron_rivendare(Creature* pCreature) +{ + return new boss_baron_rivendareAI (pCreature); +} + +void AddSC_boss_baron_rivendare() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_baron_rivendare"; + newscript->GetAI = &GetAI_boss_baron_rivendare; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp new file mode 100644 index 00000000000..cff4fe3fbae --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp @@ -0,0 +1,127 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Baroness_Anastari +SD%Complete: 90 +SDComment: MC disabled +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_BANSHEEWAIL 16565 +#define SPELL_BANSHEECURSE 16867 +#define SPELL_SILENCE 18327 +//#define SPELL_POSSESS 17244 + +struct boss_baroness_anastariAI : public ScriptedAI +{ + boss_baroness_anastariAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 BansheeWail_Timer; + uint32 BansheeCurse_Timer; + uint32 Silence_Timer; + //uint32 Possess_Timer; + + void Reset() + { + BansheeWail_Timer = 1000; + BansheeCurse_Timer = 11000; + Silence_Timer = 13000; + //Possess_Timer = 35000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_BARONESS,IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //BansheeWail + if (BansheeWail_Timer <= diff) + { + if (rand()%100 < 95) + DoCast(me->getVictim(), SPELL_BANSHEEWAIL); + //4 seconds until we should cast this again + BansheeWail_Timer = 4000; + } else BansheeWail_Timer -= diff; + + //BansheeCurse + if (BansheeCurse_Timer <= diff) + { + if (rand()%100 < 75) + DoCast(me->getVictim(), SPELL_BANSHEECURSE); + //18 seconds until we should cast this again + BansheeCurse_Timer = 18000; + } else BansheeCurse_Timer -= diff; + + //Silence + if (Silence_Timer <= diff) + { + if (rand()%100 < 80) + DoCast(me->getVictim(), SPELL_SILENCE); + //13 seconds until we should cast this again + Silence_Timer = 13000; + } else Silence_Timer -= diff; + + //Possess + /* if (Possess_Timer <= diff) + { + //Cast + if (rand()%100 < 65) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget)DoCast(pTarget, SPELL_POSSESS); + } + //50 seconds until we should cast this again + Possess_Timer = 50000; + } else Possess_Timer -= diff; + */ + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_baroness_anastari(Creature* pCreature) +{ + return new boss_baroness_anastariAI (pCreature); +} + +void AddSC_boss_baroness_anastari() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_baroness_anastari"; + newscript->GetAI = &GetAI_boss_baroness_anastari; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp new file mode 100644 index 00000000000..c12f7b9ad04 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp @@ -0,0 +1,220 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_cannon_master_willey +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" + +//front, left +#define ADD_1X 3553.851807 +#define ADD_1Y -2945.885986 +#define ADD_1Z 125.001015 +#define ADD_1O 0.592007 +//front, right +#define ADD_2X 3559.206299 +#define ADD_2Y -2952.929932 +#define ADD_2Z 125.001015 +#define ADD_2O 0.592007 +//mid, left +#define ADD_3X 3552.417480 +#define ADD_3Y -2948.667236 +#define ADD_3Z 125.001015 +#define ADD_3O 0.592007 +//mid, right +#define ADD_4X 3555.651855 +#define ADD_4Y -2953.519043 +#define ADD_4Z 125.001015 +#define ADD_4O 0.592007 +//back, left +#define ADD_5X 3547.927246 +#define ADD_5Y -2950.977295 +#define ADD_5Z 125.001015 +#define ADD_5O 0.592007 +//back, mid +#define ADD_6X 3553.094697 +#define ADD_6Y -2952.123291 +#define ADD_6Z 125.001015 +#define ADD_6O 0.592007 +//back, right +#define ADD_7X 3552.727539 +#define ADD_7Y -2957.776123 +#define ADD_7Z 125.001015 +#define ADD_7O 0.592007 +//behind, left +#define ADD_8X 3547.156250 +#define ADD_8Y -2953.162354 +#define ADD_8Z 125.001015 +#define ADD_8O 0.592007 +//behind, right +#define ADD_9X 3550.202148 +#define ADD_9Y -2957.437744 +#define ADD_9Z 125.001015 +#define ADD_9O 0.592007 + +#define SPELL_KNOCKAWAY 10101 +#define SPELL_PUMMEL 15615 +#define SPELL_SHOOT 16496 +//#define SPELL_SUMMONCRIMSONRIFLEMAN 17279 + +struct boss_cannon_master_willeyAI : public ScriptedAI +{ + boss_cannon_master_willeyAI(Creature *c) : ScriptedAI(c) {} + + uint32 KnockAway_Timer; + uint32 Pummel_Timer; + uint32 Shoot_Timer; + uint32 SummonRifleman_Timer; + + void Reset() + { + Shoot_Timer = 1000; + Pummel_Timer = 7000; + KnockAway_Timer = 11000; + SummonRifleman_Timer = 15000; + } + + void JustDied(Unit* /*Victim*/) + { + me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Pummel + if (Pummel_Timer <= diff) + { + //Cast + if (rand()%100 < 90) //90% chance to cast + { + DoCast(me->getVictim(), SPELL_PUMMEL); + } + //12 seconds until we should cast this again + Pummel_Timer = 12000; + } else Pummel_Timer -= diff; + + //KnockAway + if (KnockAway_Timer <= diff) + { + //Cast + if (rand()%100 < 80) //80% chance to cast + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + } + //14 seconds until we should cast this again + KnockAway_Timer = 14000; + } else KnockAway_Timer -= diff; + + //Shoot + if (Shoot_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_SHOOT); + //1 seconds until we should cast this again + Shoot_Timer = 1000; + } else Shoot_Timer -= diff; + + //SummonRifleman + if (SummonRifleman_Timer <= diff) + { + //Cast + switch (rand()%9) + { + case 0: + me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 1: + me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 2: + me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 3: + me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 4: + me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 5: + me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 6: + me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 7: + me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 8: + me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + } + //30 seconds until we should cast this again + SummonRifleman_Timer = 30000; + } else SummonRifleman_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_cannon_master_willey(Creature* pCreature) +{ + return new boss_cannon_master_willeyAI (pCreature); +} + +void AddSC_boss_cannon_master_willey() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_cannon_master_willey"; + newscript->GetAI = &GetAI_boss_cannon_master_willey; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp new file mode 100644 index 00000000000..a8489a7f549 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp @@ -0,0 +1,217 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Dathrohan_Balnazzar +SD%Complete: 95 +SDComment: Possibly need to fix/improve summons after death +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + //Dathrohan spells + SPELL_CRUSADERSHAMMER = 17286, //AOE stun + SPELL_CRUSADERSTRIKE = 17281, + SPELL_HOLYSTRIKE = 17284, //weapon dmg +3 + + //Transform + SPELL_BALNAZZARTRANSFORM = 17288, //restore full HP/mana, trigger spell Balnazzar Transform Stun + + //Balnazzar spells + SPELL_SHADOWSHOCK = 17399, + SPELL_MINDBLAST = 17287, + SPELL_PSYCHICSCREAM = 13704, + SPELL_SLEEP = 12098, + SPELL_MINDCONTROL = 15690, + + NPC_DATHROHAN = 10812, + NPC_BALNAZZAR = 10813, + NPC_ZOMBIE = 10698 //probably incorrect +}; + +struct SummonDef +{ + float m_fX, m_fY, m_fZ, m_fOrient; +}; + +SummonDef m_aSummonPoint[]= +{ + {3444.156, -3090.626, 135.002, 2.240}, //G1 front, left + {3449.123, -3087.009, 135.002, 2.240}, //G1 front, right + {3446.246, -3093.466, 135.002, 2.240}, //G1 back left + {3451.160, -3089.904, 135.002, 2.240}, //G1 back, right + + {3457.995, -3080.916, 135.002, 3.784}, //G2 front, left + {3454.302, -3076.330, 135.002, 3.784}, //G2 front, right + {3460.975, -3078.901, 135.002, 3.784}, //G2 back left + {3457.338, -3073.979, 135.002, 3.784} //G2 back, right +}; + +struct boss_dathrohan_balnazzarAI : public ScriptedAI +{ + boss_dathrohan_balnazzarAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiCrusadersHammer_Timer; + uint32 m_uiCrusaderStrike_Timer; + uint32 m_uiMindBlast_Timer; + uint32 m_uiHolyStrike_Timer; + uint32 m_uiShadowShock_Timer; + uint32 m_uiPsychicScream_Timer; + uint32 m_uiDeepSleep_Timer; + uint32 m_uiMindControl_Timer; + bool m_bTransformed; + + void Reset() + { + m_uiCrusadersHammer_Timer = 8000; + m_uiCrusaderStrike_Timer = 12000; + m_uiMindBlast_Timer = 6000; + m_uiHolyStrike_Timer = 18000; + m_uiShadowShock_Timer = 4000; + m_uiPsychicScream_Timer = 16000; + m_uiDeepSleep_Timer = 20000; + m_uiMindControl_Timer = 10000; + m_bTransformed = false; + + if (me->GetEntry() == NPC_BALNAZZAR) + me->UpdateEntry(NPC_DATHROHAN); + } + + void JustDied(Unit* /*Victim*/) + { + static uint32 uiCount = sizeof(m_aSummonPoint)/sizeof(SummonDef); + + for (uint8 i=0; iSummonCreature(NPC_ZOMBIE, + m_aSummonPoint[i].m_fX, m_aSummonPoint[i].m_fY, m_aSummonPoint[i].m_fZ, m_aSummonPoint[i].m_fOrient, + TEMPSUMMON_TIMED_DESPAWN, HOUR*IN_MILISECONDS); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //START NOT TRANSFORMED + if (!m_bTransformed) + { + //MindBlast + if (m_uiMindBlast_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MINDBLAST); + m_uiMindBlast_Timer = 15000 + rand()%5000; + } else m_uiMindBlast_Timer -= uiDiff; + + //CrusadersHammer + if (m_uiCrusadersHammer_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CRUSADERSHAMMER); + m_uiCrusadersHammer_Timer = 12000; + } else m_uiCrusadersHammer_Timer -= uiDiff; + + //CrusaderStrike + if (m_uiCrusaderStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CRUSADERSTRIKE); + m_uiCrusaderStrike_Timer = 15000; + } else m_uiCrusaderStrike_Timer -= uiDiff; + + //HolyStrike + if (m_uiHolyStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_HOLYSTRIKE); + m_uiHolyStrike_Timer = 15000; + } else m_uiHolyStrike_Timer -= uiDiff; + + //BalnazzarTransform + if (me->GetHealth()*100 / me->GetMaxHealth() < 40) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + //restore hp, mana and stun + DoCast(me, SPELL_BALNAZZARTRANSFORM); + me->UpdateEntry(NPC_BALNAZZAR); + m_bTransformed = true; + } + } + else + { + //MindBlast + if (m_uiMindBlast_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MINDBLAST); + m_uiMindBlast_Timer = 15000 + rand()%5000; + } else m_uiMindBlast_Timer -= uiDiff; + + //ShadowShock + if (m_uiShadowShock_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SHADOWSHOCK); + m_uiShadowShock_Timer = 11000; + } else m_uiShadowShock_Timer -= uiDiff; + + //PsychicScream + if (m_uiPsychicScream_Timer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_PSYCHICSCREAM); + + m_uiPsychicScream_Timer = 20000; + } else m_uiPsychicScream_Timer -= uiDiff; + + //DeepSleep + if (m_uiDeepSleep_Timer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SLEEP); + + m_uiDeepSleep_Timer = 15000; + } else m_uiDeepSleep_Timer -= uiDiff; + + //MindControl + if (m_uiMindControl_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MINDCONTROL); + m_uiMindControl_Timer = 15000; + } else m_uiMindControl_Timer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_dathrohan_balnazzar(Creature* pCreature) +{ + return new boss_dathrohan_balnazzarAI (pCreature); +} + +void AddSC_boss_dathrohan_balnazzar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_dathrohan_balnazzar"; + newscript->GetAI = &GetAI_boss_dathrohan_balnazzar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp new file mode 100644 index 00000000000..89de7dbc207 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp @@ -0,0 +1,128 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Magistrate_Barthilas +SD%Complete: 70 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_DRAININGBLOW 16793 +#define SPELL_CROWDPUMMEL 10887 +#define SPELL_MIGHTYBLOW 14099 +#define SPELL_FURIOUS_ANGER 16791 + +#define MODEL_NORMAL 10433 +#define MODEL_HUMAN 3637 + +struct boss_magistrate_barthilasAI : public ScriptedAI +{ + boss_magistrate_barthilasAI(Creature *c) : ScriptedAI(c) {} + + uint32 DrainingBlow_Timer; + uint32 CrowdPummel_Timer; + uint32 MightyBlow_Timer; + uint32 FuriousAnger_Timer; + uint32 AngerCount; + + void Reset() + { + DrainingBlow_Timer = 20000; + CrowdPummel_Timer = 15000; + MightyBlow_Timer = 10000; + FuriousAnger_Timer = 5000; + AngerCount = 0; + + if (me->isAlive()) + me->SetDisplayId(MODEL_NORMAL); + else + me->SetDisplayId(MODEL_HUMAN); + } + + void MoveInLineOfSight(Unit *who) + { + //nothing to see here yet + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* /*Killer*/) + { + me->SetDisplayId(MODEL_HUMAN); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (FuriousAnger_Timer <= diff) + { + FuriousAnger_Timer = 4000; + if (AngerCount > 25) + return; + + ++AngerCount; + DoCast(me, SPELL_FURIOUS_ANGER, false); + } else FuriousAnger_Timer -= diff; + + //DrainingBlow + if (DrainingBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DRAININGBLOW); + DrainingBlow_Timer = 15000; + } else DrainingBlow_Timer -= diff; + + //CrowdPummel + if (CrowdPummel_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CROWDPUMMEL); + CrowdPummel_Timer = 15000; + } else CrowdPummel_Timer -= diff; + + //MightyBlow + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTYBLOW); + MightyBlow_Timer = 20000; + } else MightyBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_magistrate_barthilas(Creature* pCreature) +{ + return new boss_magistrate_barthilasAI (pCreature); +} + +void AddSC_boss_magistrate_barthilas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magistrate_barthilas"; + newscript->GetAI = &GetAI_boss_magistrate_barthilas; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp new file mode 100644 index 00000000000..0c1cf011d5e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp @@ -0,0 +1,108 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_maleki_the_pallid +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_FROSTBOLT 17503 +#define SPELL_DRAINLIFE 20743 +#define SPELL_DRAIN_MANA 17243 +#define SPELL_ICETOMB 16869 + +struct boss_maleki_the_pallidAI : public ScriptedAI +{ + boss_maleki_the_pallidAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Frostbolt_Timer; + uint32 IceTomb_Timer; + uint32 DrainLife_Timer; + + void Reset() + { + Frostbolt_Timer = 1000; + IceTomb_Timer = 16000; + DrainLife_Timer = 31000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_PALLID,IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frostbolt + if (Frostbolt_Timer <= diff) + { + if (rand()%100 < 90) + DoCast(me->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 3500; + } else Frostbolt_Timer -= diff; + + //IceTomb + if (IceTomb_Timer <= diff) + { + if (rand()%100 < 65) + DoCast(me->getVictim(), SPELL_ICETOMB); + IceTomb_Timer = 28000; + } else IceTomb_Timer -= diff; + + //DrainLife + if (DrainLife_Timer <= diff) + { + if (rand()%100 < 55) + DoCast(me->getVictim(), SPELL_DRAINLIFE); + DrainLife_Timer = 31000; + } else DrainLife_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_maleki_the_pallid(Creature* pCreature) +{ + return new boss_maleki_the_pallidAI (pCreature); +} + +void AddSC_boss_maleki_the_pallid() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_maleki_the_pallid"; + newscript->GetAI = &GetAI_boss_maleki_the_pallid; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp new file mode 100644 index 00000000000..ae7299071f4 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp @@ -0,0 +1,121 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Nerubenkan +SD%Complete: 70 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_ENCASINGWEBS 4962 +#define SPELL_PIERCEARMOR 6016 +#define SPELL_CRYPT_SCARABS 31602 +#define SPELL_RAISEUNDEADSCARAB 17235 + +struct boss_nerubenkanAI : public ScriptedAI +{ + boss_nerubenkanAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 EncasingWebs_Timer; + uint32 PierceArmor_Timer; + uint32 CryptScarabs_Timer; + uint32 RaiseUndeadScarab_Timer; + + void Reset() + { + CryptScarabs_Timer = 3000; + EncasingWebs_Timer = 7000; + PierceArmor_Timer = 19000; + RaiseUndeadScarab_Timer = 3000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_NERUB,IN_PROGRESS); + } + + void RaiseUndeadScarab(Unit* pVictim) + { + if (Creature* pUndeadScarab = DoSpawnCreature(10876, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000)) + if (pUndeadScarab->AI()) + pUndeadScarab->AI()->AttackStart(pVictim); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //EncasingWebs + if (EncasingWebs_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ENCASINGWEBS); + EncasingWebs_Timer = 30000; + } else EncasingWebs_Timer -= diff; + + //PierceArmor + if (PierceArmor_Timer <= diff) + { + if (urand(0,3) < 2) + DoCast(me->getVictim(), SPELL_PIERCEARMOR); + PierceArmor_Timer = 35000; + } else PierceArmor_Timer -= diff; + + //CryptScarabs_Timer + if (CryptScarabs_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CRYPT_SCARABS); + CryptScarabs_Timer = 20000; + } else CryptScarabs_Timer -= diff; + + //RaiseUndeadScarab + if (RaiseUndeadScarab_Timer <= diff) + { + RaiseUndeadScarab(me->getVictim()); + RaiseUndeadScarab_Timer = 16000; + } else RaiseUndeadScarab_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_nerubenkan(Creature* pCreature) +{ + return new boss_nerubenkanAI (pCreature); +} + +void AddSC_boss_nerubenkan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nerubenkan"; + newscript->GetAI = &GetAI_boss_nerubenkan; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp new file mode 100644 index 00000000000..905feb9fffc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp @@ -0,0 +1,157 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Silver_Hand_Bosses +SD%Complete: 40 +SDComment: Basic script to have support for Horde paladin epic mount (quest 9737). All 5 members of Order of the Silver Hand running this script (least for now) +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +/*##### +# Additional: +# Although this is a working solution, the correct would be in addition to check if Aurius is dead. +# Once player extinguish the eternal flame (cast spell 31497->start event 11206) Aurius should become hostile. +# Once Aurius is defeated, he should be the one summoning the ghosts. +#####*/ + +#define SH_GREGOR 17910 +#define SH_CATHELA 17911 +#define SH_NEMAS 17912 +#define SH_AELMAR 17913 +#define SH_VICAR 17914 +#define SH_QUEST_CREDIT 17915 + +#define SPELL_HOLY_LIGHT 25263 +#define SPELL_DIVINE_SHIELD 13874 + +struct boss_silver_hand_bossesAI : public ScriptedAI +{ + boss_silver_hand_bossesAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 HolyLight_Timer; + uint32 DivineShield_Timer; + + void Reset() + { + HolyLight_Timer = 20000; + DivineShield_Timer = 20000; + + if (pInstance) + { + switch(me->GetEntry()) + { + case SH_AELMAR: + pInstance->SetData(TYPE_SH_AELMAR, 0); + break; + case SH_CATHELA: + pInstance->SetData(TYPE_SH_CATHELA, 0); + break; + case SH_GREGOR: + pInstance->SetData(TYPE_SH_GREGOR, 0); + break; + case SH_NEMAS: + pInstance->SetData(TYPE_SH_NEMAS, 0); + break; + case SH_VICAR: + pInstance->SetData(TYPE_SH_VICAR, 0); + break; + } + } + } + + void EnterCombat(Unit* /*who*/) + { + } + + void JustDied(Unit* Killer) + { + if (pInstance) + { + switch(me->GetEntry()) + { + case SH_AELMAR: + pInstance->SetData(TYPE_SH_AELMAR, 2); + break; + case SH_CATHELA: + pInstance->SetData(TYPE_SH_CATHELA, 2); + break; + case SH_GREGOR: + pInstance->SetData(TYPE_SH_GREGOR, 2); + break; + case SH_NEMAS: + pInstance->SetData(TYPE_SH_NEMAS, 2); + break; + case SH_VICAR: + pInstance->SetData(TYPE_SH_VICAR, 2); + break; + } + if (pInstance->GetData(TYPE_SH_QUEST) && Killer->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(Killer)->KilledMonsterCredit(SH_QUEST_CREDIT,me->GetGUID()); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (HolyLight_Timer <= diff) + { + if (me->GetHealth()*5 < me->GetMaxHealth()) + { + DoCast(me, SPELL_HOLY_LIGHT); + HolyLight_Timer = 20000; + } + } else HolyLight_Timer -= diff; + + if (DivineShield_Timer <= diff) + { + if (me->GetHealth()*20 < me->GetMaxHealth()) + { + DoCast(me, SPELL_DIVINE_SHIELD); + DivineShield_Timer = 40000; + } + } else DivineShield_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_boss_silver_hand_bossesAI(Creature* pCreature) +{ + return new boss_silver_hand_bossesAI (pCreature); +} + +void AddSC_boss_order_of_silver_hand() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_silver_hand_bosses"; + newscript->GetAI = &GetAI_boss_silver_hand_bossesAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp new file mode 100644 index 00000000000..c04bae15468 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp @@ -0,0 +1,144 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_postmaster_malown +SD%Complete: 50 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" + +//Spell ID to summon this guy is 24627 "Summon Postmaster Malown" +//He should be spawned along with three other elites once the third postbox has been opened + +#define SAY_MALOWNED "You just got MALOWNED!" + +#define SPELL_WAILINGDEAD 7713 +#define SPELL_BACKHAND 6253 +#define SPELL_CURSEOFWEAKNESS 8552 +#define SPELL_CURSEOFTONGUES 12889 +#define SPELL_CALLOFTHEGRAVE 17831 + +struct boss_postmaster_malownAI : public ScriptedAI +{ + boss_postmaster_malownAI(Creature *c) : ScriptedAI(c) {} + + uint32 WailingDead_Timer; + uint32 Backhand_Timer; + uint32 CurseOfWeakness_Timer; + uint32 CurseOfTongues_Timer; + uint32 CallOfTheGrave_Timer; + bool HasYelled; + + void Reset() + { + WailingDead_Timer = 19000; //lasts 6 sec + Backhand_Timer = 8000; //2 sec stun + CurseOfWeakness_Timer = 20000; //lasts 2 mins + CurseOfTongues_Timer = 22000; + CallOfTheGrave_Timer = 25000; + HasYelled = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //WailingDead + if (WailingDead_Timer <= diff) + { + //Cast + if (rand()%100 < 65) //65% chance to cast + { + DoCast(me->getVictim(), SPELL_WAILINGDEAD); + } + //19 seconds until we should cast this again + WailingDead_Timer = 19000; + } else WailingDead_Timer -= diff; + + //Backhand + if (Backhand_Timer <= diff) + { + //Cast + if (rand()%100 < 45) //45% chance to cast + { + DoCast(me->getVictim(), SPELL_BACKHAND); + } + //8 seconds until we should cast this again + Backhand_Timer = 8000; + } else Backhand_Timer -= diff; + + //CurseOfWeakness + if (CurseOfWeakness_Timer <= diff) + { + //Cast + if (rand()%100 < 3) //3% chance to cast + { + DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); + } + //20 seconds until we should cast this again + CurseOfWeakness_Timer = 20000; + } else CurseOfWeakness_Timer -= diff; + + //CurseOfTongues + if (CurseOfTongues_Timer <= diff) + { + //Cast + if (rand()%100 < 3) //3% chance to cast + { + DoCast(me->getVictim(), SPELL_CURSEOFTONGUES); + } + //22 seconds until we should cast this again + CurseOfTongues_Timer = 22000; + } else CurseOfTongues_Timer -= diff; + + //CallOfTheGrave + if (CallOfTheGrave_Timer <= diff) + { + //Cast + if (rand()%100 < 5) //5% chance to cast + { + DoCast(me->getVictim(), SPELL_CALLOFTHEGRAVE); + } + //25 seconds until we should cast this again + CallOfTheGrave_Timer = 25000; + } else CallOfTheGrave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_postmaster_malown(Creature* pCreature) +{ + return new boss_postmaster_malownAI (pCreature); +} + +void AddSC_boss_postmaster_malown() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_postmaster_malown"; + newscript->GetAI = &GetAI_boss_postmaster_malown; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp new file mode 100644 index 00000000000..3a3ae60c9c9 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp @@ -0,0 +1,102 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Ramstein_The_Gorger +SD%Complete: 70 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_TRAMPLE 5568 +#define SPELL_KNOCKOUT 17307 + + #define C_MINDLESS_UNDEAD 11030 + +struct boss_ramstein_the_gorgerAI : public ScriptedAI +{ + boss_ramstein_the_gorgerAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Trample_Timer; + uint32 Knockout_Timer; + + void Reset() + { + Trample_Timer = 3000; + Knockout_Timer = 12000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + for (uint8 i = 0; i < 30; ++i) + { + if (Creature* mob = me->SummonCreature(C_MINDLESS_UNDEAD,3969.35+irand(-10,10),-3391.87+irand(-10,10),119.11,5.91,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000)) + mob->AI()->AttackStart(me->SelectNearestTarget(500)); + } + + if (pInstance) + pInstance->SetData(TYPE_RAMSTEIN,DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Trample + if (Trample_Timer <= diff) + { + DoCast(me, SPELL_TRAMPLE); + Trample_Timer = 7000; + } else Trample_Timer -= diff; + + //Knockout + if (Knockout_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKOUT); + Knockout_Timer = 10000; + } else Knockout_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ramstein_the_gorger(Creature* pCreature) +{ + return new boss_ramstein_the_gorgerAI (pCreature); +} + +void AddSC_boss_ramstein_the_gorger() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ramstein_the_gorger"; + newscript->GetAI = &GetAI_boss_ramstein_the_gorger; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp new file mode 100644 index 00000000000..f15eb59ba47 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp @@ -0,0 +1,83 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_timmy_the_cruel +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_SPAWN "TIMMY!" + +#define SPELL_RAVENOUSCLAW 17470 + +struct boss_timmy_the_cruelAI : public ScriptedAI +{ + boss_timmy_the_cruelAI(Creature *c) : ScriptedAI(c) {} + + uint32 RavenousClaw_Timer; + bool HasYelled; + + void Reset() + { + RavenousClaw_Timer = 10000; + HasYelled = false; + } + + void EnterCombat(Unit * /*who*/) + { + if (!HasYelled) + { + me->MonsterYell(SAY_SPAWN,LANG_UNIVERSAL,NULL); + HasYelled = true; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //RavenousClaw + if (RavenousClaw_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_RAVENOUSCLAW); + //15 seconds until we should cast this again + RavenousClaw_Timer = 15000; + } else RavenousClaw_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_timmy_the_cruel(Creature* pCreature) +{ + return new boss_timmy_the_cruelAI (pCreature); +} + +void AddSC_boss_timmy_the_cruel() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_timmy_the_cruel"; + newscript->GetAI = &GetAI_boss_timmy_the_cruel; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp b/src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp new file mode 100644 index 00000000000..ffeaa070a26 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp @@ -0,0 +1,458 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: instance_stratholme +SD%Complete: 50 +SDComment: In progress. Undead side 75% implemented. Save/load not implemented. +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define GO_SERVICE_ENTRANCE 175368 +#define GO_GAUNTLET_GATE1 175357 +#define GO_ZIGGURAT1 175380 //baroness +#define GO_ZIGGURAT2 175379 //nerub'enkan +#define GO_ZIGGURAT3 175381 //maleki +#define GO_ZIGGURAT4 175405 //rammstein +#define GO_ZIGGURAT5 175796 //baron +#define GO_PORT_GAUNTLET 175374 //port from gauntlet to slaugther +#define GO_PORT_SLAUGTHER 175373 //port at slaugther +#define GO_PORT_ELDERS 175377 //port at elders square + +#define C_CRYSTAL 10415 //three ziggurat crystals +#define C_BARON 10440 +#define C_YSIDA_TRIGGER 16100 + +#define C_RAMSTEIN 10439 +#define C_ABOM_BILE 10416 +#define C_ABOM_VENOM 10417 +#define C_BLACK_GUARD 10394 +#define C_YSIDA 16031 + +#define MAX_ENCOUNTER 6 + +struct instance_stratholme : public ScriptedInstance +{ + instance_stratholme(Map* pMap) : ScriptedInstance(pMap) {} + + uint32 Encounter[MAX_ENCOUNTER]; + + bool IsSilverHandDead[5]; + + uint32 BaronRun_Timer; + uint32 SlaugtherSquare_Timer; + + uint64 serviceEntranceGUID; + uint64 gauntletGate1GUID; + uint64 ziggurat1GUID; + uint64 ziggurat2GUID; + uint64 ziggurat3GUID; + uint64 ziggurat4GUID; + uint64 ziggurat5GUID; + uint64 portGauntletGUID; + uint64 portSlaugtherGUID; + uint64 portElderGUID; + + uint64 baronGUID; + uint64 ysidaTriggerGUID; + std::set crystalsGUID; + std::set abomnationGUID; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + Encounter[i] = NOT_STARTED; + + for (uint8 i = 0; i < 5; ++i) + IsSilverHandDead[i] = false; + + BaronRun_Timer = 0; + SlaugtherSquare_Timer = 0; + + serviceEntranceGUID = 0; + gauntletGate1GUID = 0; + ziggurat1GUID = 0; + ziggurat2GUID = 0; + ziggurat3GUID = 0; + ziggurat4GUID = 0; + ziggurat5GUID = 0; + portGauntletGUID = 0; + portSlaugtherGUID = 0; + portElderGUID = 0; + + baronGUID = 0; + ysidaTriggerGUID = 0; + crystalsGUID.clear(); + abomnationGUID.clear(); + } + + bool StartSlaugtherSquare() + { + //change to DONE when crystals implemented + if (Encounter[1] == IN_PROGRESS && Encounter[2] == IN_PROGRESS && Encounter[3] == IN_PROGRESS) + { + HandleGameObject(portGauntletGUID, true); + HandleGameObject(portSlaugtherGUID, true); + return true; + } + + debug_log("TSCR: Instance Stratholme: Cannot open slaugther square yet."); + return false; + } + + //if withRestoreTime true, then newState will be ignored and GO should be restored to original state after 10 seconds + void UpdateGoState(uint64 goGuid, uint32 newState, bool withRestoreTime) + { + if (!goGuid) + return; + + if (GameObject* pGo = instance->GetGameObject(goGuid)) + { + if (withRestoreTime) + pGo->UseDoorOrButton(10); + else + pGo->SetGoState((GOState)newState); + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case C_BARON: baronGUID = pCreature->GetGUID(); break; + case C_YSIDA_TRIGGER: ysidaTriggerGUID = pCreature->GetGUID(); break; + case C_CRYSTAL: crystalsGUID.insert(pCreature->GetGUID()); break; + case C_ABOM_BILE: + case C_ABOM_VENOM: abomnationGUID.insert(pCreature->GetGUID()); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_SERVICE_ENTRANCE: + serviceEntranceGUID = pGo->GetGUID(); + break; + case GO_GAUNTLET_GATE1: + //weird, but unless flag is set, client will not respond as expected. DB bug? + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_LOCKED); + gauntletGate1GUID = pGo->GetGUID(); + break; + case GO_ZIGGURAT1: + ziggurat1GUID = pGo->GetGUID(); + if (GetData(TYPE_BARONESS) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_ZIGGURAT2: + ziggurat2GUID = pGo->GetGUID(); + if (GetData(TYPE_NERUB) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_ZIGGURAT3: + ziggurat3GUID = pGo->GetGUID(); + if (GetData(TYPE_PALLID) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_ZIGGURAT4: + ziggurat4GUID = pGo->GetGUID(); + if (GetData(TYPE_BARON) == DONE || GetData(TYPE_RAMSTEIN) == DONE) + HandleGameObject(0, true, pGo); + break; + case GO_ZIGGURAT5: + ziggurat5GUID = pGo->GetGUID(); + if (GetData(TYPE_BARON) == DONE || GetData(TYPE_RAMSTEIN) == DONE) + HandleGameObject(0, true, pGo); + break; + case GO_PORT_GAUNTLET: + portGauntletGUID = pGo->GetGUID(); + if (GetData(TYPE_BARONESS) == IN_PROGRESS && GetData(TYPE_NERUB) == IN_PROGRESS && GetData(TYPE_PALLID) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_PORT_SLAUGTHER: + portSlaugtherGUID = pGo->GetGUID(); + if (GetData(TYPE_BARONESS) == IN_PROGRESS && GetData(TYPE_NERUB) == IN_PROGRESS && GetData(TYPE_PALLID) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_PORT_ELDERS: + portElderGUID = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_BARON_RUN: + switch(data) + { + case IN_PROGRESS: + if (Encounter[0] == IN_PROGRESS || Encounter[0] == FAIL) + break; + Encounter[0] = data; + BaronRun_Timer = 2700000; + debug_log("TSCR: Instance Stratholme: Baron run in progress."); + break; + case FAIL: + //may add code to remove aura from players, but in theory the time should be up already and removed. + Encounter[0] = data; + break; + case DONE: + Encounter[0] = data; + if (Creature* pYsidaT = instance->GetCreature(ysidaTriggerGUID)) + pYsidaT->SummonCreature(C_YSIDA, + pYsidaT->GetPositionX(),pYsidaT->GetPositionY(),pYsidaT->GetPositionZ(),pYsidaT->GetOrientation(), + TEMPSUMMON_TIMED_DESPAWN,1800000); + BaronRun_Timer = 0; + break; + } + break; + case TYPE_BARONESS: + Encounter[1] = data; + if (data == IN_PROGRESS) + HandleGameObject(ziggurat1GUID, true); + if (data == IN_PROGRESS) //change to DONE when crystals implemented + StartSlaugtherSquare(); + break; + case TYPE_NERUB: + Encounter[2] = data; + if (data == IN_PROGRESS) + HandleGameObject(ziggurat2GUID, true); + if (data == IN_PROGRESS) //change to DONE when crystals implemented + StartSlaugtherSquare(); + break; + case TYPE_PALLID: + Encounter[3] = data; + if (data == IN_PROGRESS) + HandleGameObject(ziggurat3GUID, true); + if (data == IN_PROGRESS) //change to DONE when crystals implemented + StartSlaugtherSquare(); + break; + case TYPE_RAMSTEIN: + if (data == IN_PROGRESS) + { + HandleGameObject(portGauntletGUID, false); + + uint32 count = abomnationGUID.size(); + for (std::set::const_iterator i = abomnationGUID.begin(); i != abomnationGUID.end(); ++i) + { + if (Creature* pAbom = instance->GetCreature(*i)) + { + if (!pAbom->isAlive()) + --count; + } + } + + if (!count) + { + //a bit itchy, it should close the door after 10 secs, but it doesn't. skipping it for now. + //UpdateGoState(ziggurat4GUID,0,true); + if (Creature* pBaron = instance->GetCreature(baronGUID)) + pBaron->SummonCreature(C_RAMSTEIN,4032.84,-3390.24,119.73,4.71,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000); + debug_log("TSCR: Instance Stratholme: Ramstein spawned."); + } + else + debug_log("TSCR: Instance Stratholme: %u Abomnation left to kill.",count); + } + + if (data == NOT_STARTED) + HandleGameObject(portGauntletGUID, true); + + if (data == DONE) + { + SlaugtherSquare_Timer = 300000; + debug_log("TSCR: Instance Stratholme: Slaugther event will continue in 5 minutes."); + } + Encounter[4] = data; + break; + case TYPE_BARON: + if (data == IN_PROGRESS) + { + HandleGameObject(ziggurat4GUID, false); + HandleGameObject(ziggurat5GUID, false); + if (GetData(TYPE_BARON_RUN) == IN_PROGRESS) + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if (pPlayer->HasAura(SPELL_BARON_ULTIMATUM)) + pPlayer->RemoveAurasDueToSpell(SPELL_BARON_ULTIMATUM); + + if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_DEAD_MAN_PLEA); + } + } + } + + SetData(TYPE_BARON_RUN,DONE); + } + } + if (data == DONE || data == NOT_STARTED) + { + HandleGameObject(ziggurat4GUID, true); + HandleGameObject(ziggurat5GUID, true); + } + if (data == DONE) + HandleGameObject(portGauntletGUID, true); + Encounter[5] = data; + break; + case TYPE_SH_AELMAR: + IsSilverHandDead[0] = (data) ? true : false; + break; + case TYPE_SH_CATHELA: + IsSilverHandDead[1] = (data) ? true : false; + break; + case TYPE_SH_GREGOR: + IsSilverHandDead[2] = (data) ? true : false; + break; + case TYPE_SH_NEMAS: + IsSilverHandDead[3] = (data) ? true : false; + break; + case TYPE_SH_VICAR: + IsSilverHandDead[4] = (data) ? true : false; + break; + } + if (data == DONE)SaveToDB(); + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << Encounter[0] << " " << Encounter[1] << " " << Encounter[2] << " " + << Encounter[3] << " " << Encounter[4] << " " << Encounter[5]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> Encounter[0] >> Encounter[1] >> Encounter[2] >> Encounter[3] + >> Encounter[4] >> Encounter[5]; + + // Do not reset 1, 2 and 3. they are not set to done, yet . + if (Encounter[0] == IN_PROGRESS) + Encounter[0] = NOT_STARTED; + if (Encounter[4] == IN_PROGRESS) + Encounter[4] = NOT_STARTED; + if (Encounter[5] == IN_PROGRESS) + Encounter[5] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_SH_QUEST: + if (IsSilverHandDead[0] && IsSilverHandDead[1] && IsSilverHandDead[2] && IsSilverHandDead[3] && IsSilverHandDead[4]) + return 1; + return 0; + case TYPE_BARON_RUN: + return Encounter[0]; + case TYPE_BARONESS: + return Encounter[1]; + case TYPE_NERUB: + return Encounter[2]; + case TYPE_PALLID: + return Encounter[3]; + case TYPE_RAMSTEIN: + return Encounter[4]; + case TYPE_BARON: + return Encounter[5]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_BARON: + return baronGUID; + case DATA_YSIDA_TRIGGER: + return ysidaTriggerGUID; + } + return 0; + } + + void Update(uint32 diff) + { + if (BaronRun_Timer) + { + if (BaronRun_Timer <= diff) + { + if (GetData(TYPE_BARON_RUN) != DONE) + SetData(TYPE_BARON_RUN, FAIL); + BaronRun_Timer = 0; + debug_log("TSCR: Instance Stratholme: Baron run event reached end. Event has state %u.",GetData(TYPE_BARON_RUN)); + } else BaronRun_Timer -= diff; + } + + if (SlaugtherSquare_Timer) + { + if (SlaugtherSquare_Timer <= diff) + { + if (Creature* pBaron = instance->GetCreature(baronGUID)) + { + for (uint8 i = 0; i < 4; ++i) + pBaron->SummonCreature(C_BLACK_GUARD,4032.84,-3390.24,119.73,4.71,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000); + + HandleGameObject(ziggurat4GUID, true); + HandleGameObject(ziggurat5GUID, true); + debug_log("TSCR: Instance Stratholme: Black guard sentries spawned. Opening gates to baron."); + } + SlaugtherSquare_Timer = 0; + } else SlaugtherSquare_Timer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_stratholme(Map* pMap) +{ + return new instance_stratholme(pMap); +} + +void AddSC_instance_stratholme() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_stratholme"; + newscript->GetInstanceData = &GetInstanceData_instance_stratholme; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp b/src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp new file mode 100644 index 00000000000..035fca68b95 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp @@ -0,0 +1,282 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Stratholme +SD%Complete: 100 +SDComment: Misc mobs for instance. pGo-script to apply aura and start event for quest 8945 +SDCategory: Stratholme +EndScriptData */ + +/* ContentData +go_gauntlet_gate +mob_freed_soul +mob_restless_soul +mobs_spectral_ghostly_citizen +EndContentData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +/*###### +## go_gauntlet_gate (this is the _first_ of the gauntlet gates, two exist) +######*/ + +bool GOHello_go_gauntlet_gate(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + + if (!pInstance) + return false; + + if (pInstance->GetData(TYPE_BARON_RUN) != NOT_STARTED) + return false; + + if (Group *pGroup = pPlayer->GetGroup()) + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* pGroupie = itr->getSource(); + if (!pGroupie) + continue; + + if (pGroupie->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && + !pGroupie->HasAura(SPELL_BARON_ULTIMATUM) && + pGroupie->GetMap() == pGo->GetMap()) + pGroupie->CastSpell(pGroupie,SPELL_BARON_ULTIMATUM,true); + } + } else if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && + !pPlayer->HasAura(SPELL_BARON_ULTIMATUM) && + pPlayer->GetMap() == pGo->GetMap()) + pPlayer->CastSpell(pPlayer,SPELL_BARON_ULTIMATUM,true); + + pInstance->SetData(TYPE_BARON_RUN,IN_PROGRESS); + return false; +} + +/*###### +## mob_freed_soul +######*/ + +//Possibly more of these quotes around. +#define SAY_ZAPPED0 -1329000 +#define SAY_ZAPPED1 -1329001 +#define SAY_ZAPPED2 -1329002 +#define SAY_ZAPPED3 -1329003 + +struct mob_freed_soulAI : public ScriptedAI +{ + mob_freed_soulAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + DoScriptText(RAND(SAY_ZAPPED0,SAY_ZAPPED1,SAY_ZAPPED2,SAY_ZAPPED3), me); + } + + void EnterCombat(Unit* /*who*/) {} +}; + +CreatureAI* GetAI_mob_freed_soul(Creature* pCreature) +{ + return new mob_freed_soulAI (pCreature); +} + +/*###### +## mob_restless_soul +######*/ + +#define SPELL_EGAN_BLASTER 17368 +#define SPELL_SOUL_FREED 17370 +#define QUEST_RESTLESS_SOUL 5282 +#define ENTRY_RESTLESS 11122 +#define ENTRY_FREED 11136 + +struct mob_restless_soulAI : public ScriptedAI +{ + mob_restless_soulAI(Creature *c) : ScriptedAI(c) {} + + uint64 Tagger; + uint32 Die_Timer; + bool Tagged; + + void Reset() + { + Tagger = 0; + Die_Timer = 5000; + Tagged = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + if (!Tagged && spell->Id == SPELL_EGAN_BLASTER && CAST_PLR(caster)->GetQuestStatus(QUEST_RESTLESS_SOUL) == QUEST_STATUS_INCOMPLETE) + { + Tagged = true; + Tagger = caster->GetGUID(); + } + } + } + + void JustSummoned(Creature *summoned) + { + summoned->CastSpell(summoned,SPELL_SOUL_FREED,false); + } + + void JustDied(Unit* /*Killer*/) + { + if (Tagged) + me->SummonCreature(ENTRY_FREED, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 300000); + } + + void UpdateAI(const uint32 diff) + { + if (Tagged) + { + if (Die_Timer <= diff) + { + if (Unit* pTemp = Unit::GetUnit(*me,Tagger)) + { + CAST_PLR(pTemp)->KilledMonsterCredit(ENTRY_RESTLESS, me->GetGUID()); + me->Kill(me); + } + } else Die_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_mob_restless_soul(Creature* pCreature) +{ + return new mob_restless_soulAI (pCreature); +} + +/*###### +## mobs_spectral_ghostly_citizen +######*/ + +enum eGhostlyCitizenSpells +{ + SPELL_HAUNTING_PHANTOM = 16336, + SPELL_SLAP = 6754 +}; + +struct mobs_spectral_ghostly_citizenAI : public ScriptedAI +{ + mobs_spectral_ghostly_citizenAI(Creature *c) : ScriptedAI(c) {} + + uint32 Die_Timer; + bool Tagged; + + void Reset() + { + Die_Timer = 5000; + Tagged = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (!Tagged && spell->Id == SPELL_EGAN_BLASTER) + Tagged = true; + } + + void JustDied(Unit* /*Killer*/) + { + if (Tagged) + { + for (uint32 i = 1; i <= 4; ++i) + { + //100%, 50%, 33%, 25% chance to spawn + if (urand(1,i) == 1) + DoSummon(ENTRY_RESTLESS, me, 20.0f, 600000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Tagged) + { + if (Die_Timer <= diff) + me->Kill(me); + else Die_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + switch(emote) + { + case TEXTEMOTE_DANCE: + EnterEvadeMode(); + break; + case TEXTEMOTE_RUDE: + if (me->IsWithinDistInMap(pPlayer, 5)) + DoCast(pPlayer, SPELL_SLAP, false); + else + me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE); + break; + case TEXTEMOTE_WAVE: + me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); + break; + case TEXTEMOTE_BOW: + me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); + break; + case TEXTEMOTE_KISS: + me->HandleEmoteCommand(EMOTE_ONESHOT_FLEX); + break; + } + } +}; + +CreatureAI* GetAI_mobs_spectral_ghostly_citizen(Creature* pCreature) +{ + return new mobs_spectral_ghostly_citizenAI (pCreature); +} + +void AddSC_stratholme() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_gauntlet_gate"; + newscript->pGOHello = &GOHello_go_gauntlet_gate; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_freed_soul"; + newscript->GetAI = &GetAI_mob_freed_soul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_restless_soul"; + newscript->GetAI = &GetAI_mob_restless_soul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mobs_spectral_ghostly_citizen"; + newscript->GetAI = &GetAI_mobs_spectral_ghostly_citizen; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/stratholme/stratholme.h b/src/server/scripts/EasternKingdoms/stratholme/stratholme.h new file mode 100644 index 00000000000..b9246091a7c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/stratholme/stratholme.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_STRATHOLME_H +#define DEF_STRATHOLME_H + +#define TYPE_BARON_RUN 1 +#define TYPE_BARONESS 2 +#define TYPE_NERUB 3 +#define TYPE_PALLID 4 +#define TYPE_RAMSTEIN 5 +#define TYPE_BARON 6 + +#define DATA_BARON 10 +#define DATA_YSIDA_TRIGGER 11 + +#define TYPE_SH_QUEST 20 +#define TYPE_SH_CATHELA 21 +#define TYPE_SH_GREGOR 22 +#define TYPE_SH_NEMAS 23 +#define TYPE_SH_VICAR 24 +#define TYPE_SH_AELMAR 25 + +#define QUEST_DEAD_MAN_PLEA 8945 +#define SPELL_BARON_ULTIMATUM 27861 +#endif + diff --git a/src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp new file mode 100644 index 00000000000..6fe65cf963d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp @@ -0,0 +1,204 @@ +/* Copyright (C) 2006 - 2009 kb_z + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Sunken_Temple +SD%Complete: 100 +SDComment:Place Holder +SDCategory: Sunken Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunken_temple.h" + +#define GO_ATALAI_STATUE1 148830 +#define GO_ATALAI_STATUE2 148831 +#define GO_ATALAI_STATUE3 148832 +#define GO_ATALAI_STATUE4 148833 +#define GO_ATALAI_STATUE5 148834 +#define GO_ATALAI_STATUE6 148835 +#define GO_ATALAI_IDOL 148836 + +#define GO_ATALAI_LIGHT1 148883 +#define GO_ATALAI_LIGHT2 148937 + +#define NPC_MALFURION_STORMRAGE 15362 + +struct instance_sunken_temple : public ScriptedInstance +{ + instance_sunken_temple(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + }; + + uint64 GOAtalaiStatue1; + uint64 GOAtalaiStatue2; + uint64 GOAtalaiStatue3; + uint64 GOAtalaiStatue4; + uint64 GOAtalaiStatue5; + uint64 GOAtalaiStatue6; + uint64 GOAtalaiIdol; + + uint32 State; + + bool s1; + bool s2; + bool s3; + bool s4; + bool s5; + bool s6; + + void Initialize() + { + GOAtalaiStatue1 = 0; + GOAtalaiStatue2 = 0; + GOAtalaiStatue3 = 0; + GOAtalaiStatue4 = 0; + GOAtalaiStatue5 = 0; + GOAtalaiStatue6 = 0; + GOAtalaiIdol = 0; + + State = 0; + + s1 = false; + s2 = false; + s3 = false; + s4 = false; + s5 = false; + s6 = false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_ATALAI_STATUE1: GOAtalaiStatue1 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE2: GOAtalaiStatue2 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE3: GOAtalaiStatue3 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE4: GOAtalaiStatue4 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE5: GOAtalaiStatue5 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE6: GOAtalaiStatue6 = pGo->GetGUID(); break; + case GO_ATALAI_IDOL: GOAtalaiIdol = pGo->GetGUID(); break; + } + } + + virtual void Update(uint32 /*diff*/) // correct order goes form 1-6 + { + switch(State) + { + case GO_ATALAI_STATUE1: + if (!s1 && !s2 && !s3 && !s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue1 = instance->GetGameObject(GOAtalaiStatue1)) + UseStatue(pAtalaiStatue1); + s1 = true; + State = 0; + }; + break; + case GO_ATALAI_STATUE2: + if (s1 && !s2 && !s3 && !s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue2 = instance->GetGameObject(GOAtalaiStatue2)) + UseStatue(pAtalaiStatue2); + s2 = true; + State = 0; + }; + break; + case GO_ATALAI_STATUE3: + if (s1 && s2 && !s3 && !s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue3 = instance->GetGameObject(GOAtalaiStatue3)) + UseStatue(pAtalaiStatue3); + s3 = true; + State = 0; + }; + break; + case GO_ATALAI_STATUE4: + if (s1 && s2 && s3 && !s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue4 = instance->GetGameObject(GOAtalaiStatue4)) + UseStatue(pAtalaiStatue4); + s4 = true; + State = 0; + } + break; + case GO_ATALAI_STATUE5: + if (s1 && s2 && s3 && s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue5 = instance->GetGameObject(GOAtalaiStatue5)) + UseStatue(pAtalaiStatue5); + s5 = true; + State = 0; + } + break; + case GO_ATALAI_STATUE6: + if (s1 && s2 && s3 && s4 && s5 && !s6) + { + if (GameObject *pAtalaiStatue6 = instance->GetGameObject(GOAtalaiStatue6)) + UseStatue(pAtalaiStatue6); + s6 = true; + State = 0; + } + break; + } + }; + + void UseStatue(GameObject* pGo) + { + pGo->SummonGameObject(GO_ATALAI_LIGHT1,pGo->GetPositionX(),pGo->GetPositionY(),pGo->GetPositionZ(),0,0,0,0,0,0); + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 4); + } + + /* + void UseLastStatue(GameObject* pGo) + { + AtalaiStatue1->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue1->GetPositionX(),AtalaiStatue1->GetPositionY(),AtalaiStatue1->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue2->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue2->GetPositionX(),AtalaiStatue2->GetPositionY(),AtalaiStatue2->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue3->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue3->GetPositionX(),AtalaiStatue3->GetPositionY(),AtalaiStatue3->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue4->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue4->GetPositionX(),AtalaiStatue4->GetPositionY(),AtalaiStatue4->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue5->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue5->GetPositionX(),AtalaiStatue5->GetPositionY(),AtalaiStatue5->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue6->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue6->GetPositionX(),AtalaiStatue6->GetPositionY(),AtalaiStatue6->GetPositionZ(),0,0,0,0,0,100000); + pGo->SummonGameObject(148838,-488.997,96.61,-189.019,-1.52,0,0,0,0,100000); + } + */ + + void SetData(uint32 type, uint32 data) + { + if (type == EVENT_STATE) + State = data; + } + + uint32 GetData(uint32 type) + { + if (type == EVENT_STATE) + return State; + return 0; + } +}; + +InstanceData* GetInstanceData_instance_sunken_temple(Map* pMap) +{ + return new instance_sunken_temple(pMap); +} + +void AddSC_instance_sunken_temple() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_sunken_temple"; + newscript->GetInstanceData = &GetInstanceData_instance_sunken_temple; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp b/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp new file mode 100644 index 00000000000..7f0ca126d78 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp @@ -0,0 +1,71 @@ +/* Copyright (C) 2006 - 2009 kb_z + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Sunken_Temple +SD%Complete: 100 +SDComment: Area Trigger + Puzzle event support +SDCategory: Sunken Temple +EndScriptData */ + +/* ContentData +at_malfurion_Stormrage_trigger +EndContentData */ + +#include "ScriptedPch.h" +#include "sunken_temple.h" + +/*##### +# at_malfurion_Stormrage_trigger +#####*/ + +bool AreaTrigger_at_malfurion_stormrage(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + if (ScriptedInstance* pInstance = pPlayer->GetInstanceData()) + { + if (!pPlayer->FindNearestCreature(15362,15)) + pPlayer->SummonCreature(15362, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), -1.52, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 100000); + return false; + } +return false; +} +/*##### +# go_atalai_statue +#####*/ + +bool GOHello_go_atalai_statue(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (!pInstance) + return false; + pInstance->SetData(EVENT_STATE,pGo->GetEntry()); + return false; +} + +void AddSC_sunken_temple() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "at_malfurion_stormrage"; + newscript->pAreaTrigger = &AreaTrigger_at_malfurion_stormrage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_atalai_statue"; + newscript->pGOHello = &GOHello_go_atalai_statue; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h b/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h new file mode 100644 index 00000000000..82245095c31 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2006 - 2009 kb_z + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SUNKEN_TEMPLE_H +#define DEF_SUNKEN_TEMPLE_H + +#define TROLLBOSS1_DEATH 1 +#define TROLLBOSS2_DEATH 2 +#define TROLLBOSS3_DEATH 3 +#define TROLLBOSS4_DEATH 4 +#define TROLLBOSS5_DEATH 5 +#define TROLLBOSS6_DEATH 6 +#define JAMMALAN_DEATH 7 +#define MORPHAZ_DEATH 8 +#define HAZZAS_DEATH 9 +#define ERANIKUS_DEATH 10 +#define ATALALARION_DEATH 11 //optional + +#define EVENT_STATE 1 +#endif + diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp new file mode 100644 index 00000000000..59e58d6df1a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp @@ -0,0 +1,349 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Brutallus +SD%Complete: 80 +SDComment: Find a way to start the intro, best code for the intro +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +enum Quotes +{ + YELL_INTRO = -1580017, + YELL_INTRO_BREAK_ICE = -1580018, + YELL_INTRO_CHARGE = -1580019, + YELL_INTRO_KILL_MADRIGOSA = -1580020, + YELL_INTRO_TAUNT = -1580021, + + YELL_MADR_ICE_BARRIER = -1580031, + YELL_MADR_INTRO = -1580032, + YELL_MADR_ICE_BLOCK = -1580033, + YELL_MADR_TRAP = -1580034, + YELL_MADR_DEATH = -1580035, + + YELL_AGGRO = -1580022, + YELL_KILL1 = -1580023, + YELL_KILL2 = -1580024, + YELL_KILL3 = -1580025, + YELL_LOVE1 = -1580026, + YELL_LOVE2 = -1580027, + YELL_LOVE3 = -1580028, + YELL_BERSERK = -1580029, + YELL_DEATH = -1580030 +}; + +enum Spells +{ + SPELL_METEOR_SLASH = 45150, + SPELL_BURN = 46394, + SPELL_STOMP = 45185, + SPELL_BERSERK = 26662, + SPELL_DUAL_WIELD = 42459, + + SPELL_INTRO_FROST_BLAST = 45203, + SPELL_INTRO_FROSTBOLT = 44843, + SPELL_INTRO_ENCAPSULATE = 45665, + SPELL_INTRO_ENCAPSULATE_CHANELLING = 45661 +}; + +#define FELMYST 25038 + +struct boss_brutallusAI : public ScriptedAI +{ + boss_brutallusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = true; + } + + ScriptedInstance* pInstance; + + uint32 SlashTimer; + uint32 BurnTimer; + uint32 StompTimer; + uint32 BerserkTimer; + + uint32 IntroPhase; + uint32 IntroPhaseTimer; + uint32 IntroFrostBoltTimer; + + bool Intro; + bool IsIntro; + bool Enraged; + + void Reset() + { + SlashTimer = 11000; + StompTimer = 30000; + BurnTimer = 60000; + BerserkTimer = 360000; + + IntroPhase = 0; + IntroPhaseTimer = 0; + IntroFrostBoltTimer = 0; + + IsIntro = false; + Enraged = false; + + DoCast(me, SPELL_DUAL_WIELD, true); + + if (pInstance) + pInstance->SetData(DATA_BRUTALLUS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_BRUTALLUS_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(YELL_KILL1,YELL_KILL2,YELL_KILL3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(YELL_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_BRUTALLUS_EVENT, DONE); + float x,y,z; + me->GetPosition(x,y,z); + me->SummonCreature(FELMYST, x,y, z+30, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0); + } + } + + void EnterEvadeMode() + { + if (!Intro) + ScriptedAI::EnterEvadeMode(); + } + + void StartIntro() + { + if (!Intro || IsIntro) + return; + error_log("Start Intro"); + Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0); + if (Madrigosa) + { + Madrigosa->Respawn(); + Madrigosa->setActive(true); + IsIntro = true; + Madrigosa->SetMaxHealth(me->GetMaxHealth()); + Madrigosa->SetHealth(me->GetMaxHealth()); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->Attack(Madrigosa, true); + Madrigosa->Attack(me, true); + }else + { + //Madrigosa not found, end intro + error_log("Madrigosa was not found"); + EndIntro(); + } + } + + void EndIntro() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Intro = false; + IsIntro = false; + error_log("End Intro"); + } + + void AttackStart(Unit* pWho) + { + if (!pWho || Intro || IsIntro) + return; + ScriptedAI::AttackStart(pWho); + } + + void DoIntro() + { + Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0); + if (!Madrigosa) + return; + + switch (IntroPhase) + { + case 0: + DoScriptText(YELL_MADR_ICE_BARRIER, Madrigosa); + IntroPhaseTimer = 7000; + ++IntroPhase; + break; + case 1: + me->SetInFront(Madrigosa); + Madrigosa->SetInFront(me); + DoScriptText(YELL_MADR_INTRO, Madrigosa, me); + IntroPhaseTimer = 9000; + ++IntroPhase; + break; + case 2: + DoScriptText(YELL_INTRO, me, Madrigosa); + IntroPhaseTimer = 13000; + ++IntroPhase; + break; + case 3: + DoCast(me, SPELL_INTRO_FROST_BLAST); + Madrigosa->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->AttackStop(); + Madrigosa->AttackStop(); + IntroFrostBoltTimer = 3000; + IntroPhaseTimer = 28000; + ++IntroPhase; + break; + case 4: + DoScriptText(YELL_INTRO_BREAK_ICE, me); + IntroPhaseTimer = 6000; + ++IntroPhase; + break; + case 5: + Madrigosa->CastSpell(me, SPELL_INTRO_ENCAPSULATE_CHANELLING, false); + DoScriptText(YELL_MADR_TRAP, Madrigosa); + DoCast(me, SPELL_INTRO_ENCAPSULATE); + IntroPhaseTimer = 11000; + ++IntroPhase; + break; + case 6: + DoScriptText(YELL_INTRO_CHARGE, me); + IntroPhaseTimer = 5000; + ++IntroPhase; + break; + case 7: + me->Kill(Madrigosa); + DoScriptText(YELL_MADR_DEATH, Madrigosa); + me->SetHealth(me->GetMaxHealth()); + me->AttackStop(); + IntroPhaseTimer = 4000; + ++IntroPhase; + break; + case 8: + DoScriptText(YELL_INTRO_KILL_MADRIGOSA, me); + me->SetOrientation(0.14f); + me->StopMoving(); + Madrigosa->setDeathState(CORPSE); + IntroPhaseTimer = 8000; + ++IntroPhase; + break; + case 9: + DoScriptText(YELL_INTRO_TAUNT, me); + IntroPhaseTimer = 5000; + ++IntroPhase; + break; + case 10: + EndIntro(); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who->isTargetableForAttack() || !me->IsHostileTo(who)) + return; + if (pInstance && Intro) + pInstance->SetData(DATA_BRUTALLUS_EVENT, SPECIAL); + + if (Intro && !IsIntro) + StartIntro(); + if (!Intro) + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + if (IsIntro) + { + if (IntroPhaseTimer <= diff) + DoIntro(); + else IntroPhaseTimer -= diff; + + if (IntroPhase == 3 + 1) + { + if (IntroFrostBoltTimer <= diff) + { + if (Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0)) + { + Madrigosa->CastSpell(me, SPELL_INTRO_FROSTBOLT, true); + IntroFrostBoltTimer = 2000; + } + } else IntroFrostBoltTimer -= diff; + } + if (!UpdateVictim()) + return; + DoMeleeAttackIfReady(); + } + + if (!UpdateVictim() || IsIntro) + return; + + if (SlashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_METEOR_SLASH); + SlashTimer = 11000; + } else SlashTimer -= diff; + + if (StompTimer <= diff) + { + DoScriptText(RAND(YELL_LOVE1,YELL_LOVE2,YELL_LOVE3), me); + DoCast(me->getVictim(), SPELL_STOMP); + StompTimer = 30000; + } else StompTimer -= diff; + + if (BurnTimer <= diff) + { + std::list pTargets; + SelectTargetList(pTargets, 10, SELECT_TARGET_RANDOM, 100, true); + for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) + if (!(*i)->HasAura(SPELL_BURN)) + { + (*i)->CastSpell((*i), SPELL_BURN, true); + break; + } + BurnTimer = urand(60000,180000); + } else BurnTimer -= diff; + + if (BerserkTimer < diff && !Enraged) + { + DoScriptText(YELL_BERSERK, me); + DoCast(me, SPELL_BERSERK); + Enraged = true; + } else BerserkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_brutallus(Creature* pCreature) +{ + return new boss_brutallusAI (pCreature); +} + +void AddSC_boss_brutallus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_brutallus"; + newscript->GetAI = &GetAI_boss_brutallus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp new file mode 100644 index 00000000000..602f12065fa --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp @@ -0,0 +1,762 @@ +/* Copyright (C) 2009 Trinity +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Eredar_Twins +SD%Complete: 100 +SDComment: +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +enum Quotes +{ + //Alytesh + YELL_CANFLAGRATION = -1580044, + YELL_SISTER_SACROLASH_DEAD = -1580045, + YELL_ALY_KILL_1 = -1580046, + YELL_ALY_KILL_2 = -1580047, + YELL_ALY_DEAD = -1580048, + YELL_BERSERK = -1580049, + + //Sacrolash + YELL_SHADOW_NOVA = -1580050, + YELL_SISTER_ALYTHESS_DEAD = -1580051, + YELL_SAC_KILL_1 = -1580052, + YELL_SAC_KILL_2 = -1580053, + SAY_SAC_DEAD = -1580054, + YELL_ENRAGE = -1580055, + + //Intro + YELL_INTRO_SAC_1 = -1580056, + YELL_INTRO_ALY_2 = -1580057, + YELL_INTRO_SAC_3 = -1580058, + YELL_INTRO_ALY_4 = -1580059, + YELL_INTRO_SAC_5 = -1580060, + YELL_INTRO_ALY_6 = -1580061, + YELL_INTRO_SAC_7 = -1580062, + YELL_INTRO_ALY_8 = -1580063, + + //Emote + EMOTE_SHADOW_NOVA = -1580064, + EMOTE_CONFLAGRATION = -1580065 +}; + +enum Spells +{ + //Lady Sacrolash spells + SPELL_DARK_TOUCHED = 45347, + SPELL_SHADOW_BLADES = 45248, //10 secs + SPELL_DARK_STRIKE = 45271, + SPELL_SHADOW_NOVA = 45329, //30-35 secs + SPELL_CONFOUNDING_BLOW = 45256, //25 secs + + //Shadow Image spells + SPELL_SHADOW_FURY = 45270, + SPELL_IMAGE_VISUAL = 45263, + + //Misc spells + SPELL_ENRAGE = 46587, + SPELL_EMPOWER = 45366, + SPELL_DARK_FLAME = 45345, + + //Grand Warlock Alythess spells + SPELL_PYROGENICS = 45230, //15secs + SPELL_FLAME_TOUCHED = 45348, + SPELL_CONFLAGRATION = 45342, //30-35 secs + SPELL_BLAZE = 45235, //on main target every 3 secs + SPELL_FLAME_SEAR = 46771, + SPELL_BLAZE_SUMMON = 45236, //187366 GO + SPELL_BLAZE_BURN = 45246 +}; + +struct boss_sacrolashAI : public ScriptedAI +{ + boss_sacrolashAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + bool SisterDeath; + bool Enraged; + + uint32 ShadowbladesTimer; + uint32 ShadownovaTimer; + uint32 ConfoundingblowTimer; + uint32 ShadowimageTimer; + uint32 ConflagrationTimer; + uint32 EnrageTimer; + + void Reset() + { + Enraged = false; + + if (pInstance) + { + Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); + if (Temp) + if (Temp->isDead()) + { + CAST_CRE(Temp)->Respawn(); + }else + { + if (Temp->getVictim()) + { + me->getThreatManager().addThreat(Temp->getVictim(),0.0f); + } + } + } + + if (!me->isInCombat()) + { + ShadowbladesTimer = 10000; + ShadownovaTimer = 30000; + ConfoundingblowTimer = 25000; + ShadowimageTimer = 20000; + ConflagrationTimer = 30000; + EnrageTimer = 360000; + + SisterDeath = false; + } + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * who) + { + DoZoneInCombat(); + + if (pInstance) + { + Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); + if (Temp && Temp->isAlive() && !(Temp->getVictim())) + CAST_CRE(Temp)->AI()->AttackStart(who); + } + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + if (rand()%4 == 0) + DoScriptText(RAND(YELL_SAC_KILL_1,YELL_SAC_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + // only if ALY death + if (SisterDeath) + { + DoScriptText(SAY_SAC_DEAD, me); + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, DONE); + } + else + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) + { + switch(spell->Id) + { + case SPELL_SHADOW_BLADES: + case SPELL_SHADOW_NOVA: + case SPELL_CONFOUNDING_BLOW: + case SPELL_SHADOW_FURY: + HandleTouchedSpells(pTarget, SPELL_DARK_TOUCHED); + break; + case SPELL_CONFLAGRATION: + HandleTouchedSpells(pTarget, SPELL_FLAME_TOUCHED); + break; + } + } + + void HandleTouchedSpells(Unit *pTarget, uint32 TouchedType) + { + switch(TouchedType) + { + case SPELL_FLAME_TOUCHED: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_DARK_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_DARK_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + } else pTarget->CastSpell(pTarget, SPELL_FLAME_TOUCHED, true); + } + break; + case SPELL_DARK_TOUCHED: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + } else pTarget->CastSpell(pTarget, SPELL_DARK_TOUCHED, true); + } + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!SisterDeath) + { + if (pInstance) + { + Unit* Temp = NULL; + Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); + if (Temp && Temp->isDead()) + { + DoScriptText(YELL_SISTER_ALYTHESS_DEAD, me); + DoCast(me, SPELL_EMPOWER); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + SisterDeath = true; + } + } + } + + if (!UpdateVictim()) + return; + + if (SisterDeath) + { + if (ConflagrationTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_CONFLAGRATION); + ConflagrationTimer = 30000+(rand()%5000); + } + } else ConflagrationTimer -= diff; + } + else + { + if (ShadownovaTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_SHADOW_NOVA); + + if (!SisterDeath) + { + if (pTarget) + DoScriptText(EMOTE_SHADOW_NOVA, me, pTarget); + DoScriptText(YELL_SHADOW_NOVA, me); + } + ShadownovaTimer = 30000+(rand()%5000); + } + } else ShadownovaTimer -=diff; + } + + if (ConfoundingblowTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_CONFOUNDING_BLOW); + ConfoundingblowTimer = 20000 + (rand()%5000); + } + } else ConfoundingblowTimer -=diff; + + if (ShadowimageTimer <= diff) + { + Unit *pTarget = NULL; + Creature* temp = NULL; + for (uint8 i = 0; i<3; ++i) + { + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + temp = DoSpawnCreature(MOB_SHADOW_IMAGE,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN,10000); + if (temp && pTarget) + { + temp->AddThreat(pTarget,1000000);//don't change target(healers) + temp->AI()->AttackStart(pTarget); + } + } + ShadowimageTimer = 20000; + } else ShadowimageTimer -=diff; + + if (ShadowbladesTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_SHADOW_BLADES); + ShadowbladesTimer = 10000; + } + } else ShadowbladesTimer -=diff; + + if (EnrageTimer < diff && !Enraged) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + DoScriptText(YELL_ENRAGE, me); + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else EnrageTimer -= diff; + + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + HandleTouchedSpells(me->getVictim(), SPELL_DARK_TOUCHED); + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + } +}; + +CreatureAI* GetAI_boss_sacrolash(Creature* pCreature) +{ + return new boss_sacrolashAI (pCreature); +}; + +struct boss_alythessAI : public Scripted_NoMovementAI +{ + boss_alythessAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); + IntroStepCounter = 10; + } + + ScriptedInstance *pInstance; + + bool SisterDeath; + bool Enraged; + + uint32 IntroStepCounter; + uint32 IntroYellTimer; + + uint32 ConflagrationTimer; + uint32 BlazeTimer; + uint32 PyrogenicsTimer; + uint32 ShadownovaTimer; + uint32 FlamesearTimer; + uint32 EnrageTimer; + + void Reset() + { + Enraged = false; + + if (pInstance) + { + Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); + if (Temp) + if (Temp->isDead()) + { + CAST_CRE(Temp)->Respawn(); + }else + { + if (Temp->getVictim()) + { + me->getThreatManager().addThreat(Temp->getVictim(),0.0f); + } + } + } + + if (!me->isInCombat()) + { + ConflagrationTimer = 45000; + BlazeTimer = 100; + PyrogenicsTimer = 15000; + ShadownovaTimer = 40000; + EnrageTimer = 360000; + FlamesearTimer = 15000; + IntroYellTimer = 10000; + + SisterDeath = false; + } + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * who) + { + DoZoneInCombat(); + + if (pInstance) + { + Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); + if (Temp && Temp->isAlive() && !(Temp->getVictim())) + CAST_CRE(Temp)->AI()->AttackStart(who); + } + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit *who) + { + if (!me->isInCombat()) + { + Scripted_NoMovementAI::AttackStart(who); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) + { + if (!me->isInCombat()) + { + DoStartNoMovement(who); + } + } + } + else if (IntroStepCounter == 10 && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 30)) + { + IntroStepCounter = 0; + } + } + + void KilledUnit(Unit * /*victim*/) + { + if (rand()%4 == 0) + { + DoScriptText(RAND(YELL_ALY_KILL_1,YELL_ALY_KILL_2), me); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (SisterDeath) + { + DoScriptText(YELL_ALY_DEAD, me); + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, DONE); + } + else + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) + { + switch(spell->Id) + { + + case SPELL_BLAZE: + pTarget->CastSpell(pTarget, SPELL_BLAZE_SUMMON, true); + case SPELL_CONFLAGRATION: + case SPELL_FLAME_SEAR: + HandleTouchedSpells(pTarget, SPELL_FLAME_TOUCHED); + break; + case SPELL_SHADOW_NOVA: + HandleTouchedSpells(pTarget, SPELL_DARK_TOUCHED); + break; + } + } + + void HandleTouchedSpells(Unit *pTarget, uint32 TouchedType) + { + switch(TouchedType) + { + case SPELL_FLAME_TOUCHED: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_DARK_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_DARK_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + }else + { + pTarget->CastSpell(pTarget, SPELL_FLAME_TOUCHED, true); + } + } + break; + case SPELL_DARK_TOUCHED: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + } else pTarget->CastSpell(pTarget, SPELL_DARK_TOUCHED, true); + } + break; + } + } + + uint32 IntroStep(uint32 step) + { + Creature* Sacrolash = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_SACROLASH) : 0); + switch (step) + { + case 0: return 0; + case 1: + if (Sacrolash) + DoScriptText(YELL_INTRO_SAC_1, Sacrolash); + return 1000; + case 2: DoScriptText(YELL_INTRO_ALY_2, me); return 1000; + case 3: + if (Sacrolash) + DoScriptText(YELL_INTRO_SAC_3, Sacrolash); + return 2000; + case 4: DoScriptText(YELL_INTRO_ALY_4, me); return 1000; + case 5: + if (Sacrolash) + DoScriptText(YELL_INTRO_SAC_5, Sacrolash); + return 2000; + case 6: DoScriptText(YELL_INTRO_ALY_6, me); return 1000; + case 7: + if (Sacrolash) + DoScriptText(YELL_INTRO_SAC_7, Sacrolash); + return 3000; + case 8: DoScriptText(YELL_INTRO_ALY_8, me); return 900000; + } + return 10000; + } + + void UpdateAI(const uint32 diff) + { + if (IntroStepCounter < 9) + { + if (IntroYellTimer <= diff) + { + IntroYellTimer = IntroStep(++IntroStepCounter); + } else IntroYellTimer -= diff; + } + + if (!SisterDeath) + { + if (pInstance) + { + Unit* Temp = NULL; + Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); + if (Temp && Temp->isDead()) + { + DoScriptText(YELL_SISTER_SACROLASH_DEAD, me); + DoCast(me, SPELL_EMPOWER); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + SisterDeath = true; + } + } + } + if (!me->getVictim()) + { + if (pInstance) + { + Creature* sisiter = Unit::GetCreature((*me),pInstance->GetData64(DATA_SACROLASH)); + if (sisiter && !sisiter->isDead() && sisiter->getVictim()) + { + me->AddThreat(sisiter->getVictim(),0.0f); + DoStartNoMovement(sisiter->getVictim()); + me->Attack(sisiter->getVictim(),false); + } + } + } + + if (!UpdateVictim()) + return; + + if (SisterDeath) + { + if (ShadownovaTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_SHADOW_NOVA); + ShadownovaTimer= 30000+(rand()%5000); + } + } else ShadownovaTimer -=diff; + } + else + { + if (ConflagrationTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_CONFLAGRATION); + ConflagrationTimer = 30000+(rand()%5000); + + if (!SisterDeath) + { + if (pTarget) + DoScriptText(EMOTE_CONFLAGRATION, me, pTarget); + DoScriptText(YELL_CANFLAGRATION, me); + } + + BlazeTimer = 4000; + } + } else ConflagrationTimer -= diff; + } + + if (FlamesearTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_FLAME_SEAR); + FlamesearTimer = 15000; + } + } else FlamesearTimer -=diff; + + if (PyrogenicsTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_PYROGENICS, true); + PyrogenicsTimer = 15000; + } + } else PyrogenicsTimer -= diff; + + if (BlazeTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me->getVictim(), SPELL_BLAZE); + BlazeTimer = 3800; + } + } else BlazeTimer -= diff; + + if (EnrageTimer < diff && !Enraged) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + DoScriptText(YELL_BERSERK, me); + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else EnrageTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_alythess(Creature* pCreature) +{ + return new boss_alythessAI (pCreature); +}; + +struct mob_shadow_imageAI : public ScriptedAI +{ + mob_shadow_imageAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowfuryTimer; + uint32 KillTimer; + uint32 DarkstrikeTimer; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + ShadowfuryTimer = 5000 + (rand()%15000); + DarkstrikeTimer = 3000; + KillTimer = 15000; + } + + void EnterCombat(Unit * /*who*/){} + + void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) + { + switch(spell->Id) + { + + case SPELL_SHADOW_FURY: + case SPELL_DARK_STRIKE: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + } else pTarget->CastSpell(pTarget,SPELL_DARK_TOUCHED,true); + } + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->HasAura(SPELL_IMAGE_VISUAL)) + DoCast(me, SPELL_IMAGE_VISUAL); + + if (KillTimer <= diff) + { + me->Kill(me); + KillTimer = 9999999; + } else KillTimer -= diff; + + if (!UpdateVictim()) + return; + + if (ShadowfuryTimer <= diff) + { + DoCast(me, SPELL_SHADOW_FURY); + ShadowfuryTimer = 10000; + } else ShadowfuryTimer -=diff; + + if (DarkstrikeTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + DoCast(me->getVictim(), SPELL_DARK_STRIKE); + } + DarkstrikeTimer = 3000; + } else DarkstrikeTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_shadow_image(Creature* pCreature) +{ + return new mob_shadow_imageAI (pCreature); +}; + +void AddSC_boss_eredar_twins() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sacrolash"; + newscript->GetAI = &GetAI_boss_sacrolash; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_alythess"; + newscript->GetAI = &GetAI_boss_alythess; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadow_image"; + newscript->GetAI = &GetAI_mob_shadow_image; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp new file mode 100644 index 00000000000..88ad2dbab11 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp @@ -0,0 +1,579 @@ +/* Copyright (C) 2009 Trinity +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Felmyst +SD%Complete: 0 +SDComment: +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +enum Yells +{ + YELL_BIRTH = -1580036, + YELL_KILL1 = -1580037, + YELL_KILL2 = -1580038, + YELL_BREATH = -1580039, + YELL_TAKEOFF = -1580040, + YELL_BERSERK = -1580041, + YELL_DEATH = -1580042, + YELL_KALECGOS = -1580043, // after felmyst's death spawned and say this +}; + +enum Spells +{ + //Aura + AURA_SUNWELL_RADIANCE = 45769, + AURA_NOXIOUS_FUMES = 47002, + + //Land phase + SPELL_CLEAVE = 19983, + SPELL_CORROSION = 45866, + SPELL_GAS_NOVA = 45855, + SPELL_ENCAPSULATE_CHANNEL = 45661, + // SPELL_ENCAPSULATE_EFFECT = 45665, + // SPELL_ENCAPSULATE_AOE = 45662, + + //Flight phase + SPELL_VAPOR_SELECT = 45391, // fel to player, force cast 45392, 50000y selete target + SPELL_VAPOR_SUMMON = 45392, // player summon vapor, radius around caster, 5y, + SPELL_VAPOR_FORCE = 45388, // vapor to fel, force cast 45389 + SPELL_VAPOR_CHANNEL = 45389, // fel to vapor, green beam channel + SPELL_VAPOR_TRIGGER = 45411, // linked to 45389, vapor to self, trigger 45410 and 46931 + SPELL_VAPOR_DAMAGE = 46931, // vapor damage, 4000 + SPELL_TRAIL_SUMMON = 45410, // vapor summon trail + SPELL_TRAIL_TRIGGER = 45399, // trail to self, trigger 45402 + SPELL_TRAIL_DAMAGE = 45402, // trail damage, 2000 + 2000 dot + SPELL_DEAD_SUMMON = 45400, // summon blazing dead, 5min + SPELL_DEAD_PASSIVE = 45415, + SPELL_FOG_BREATH = 45495, // fel to self, speed burst + SPELL_FOG_TRIGGER = 45582, // fog to self, trigger 45782 + SPELL_FOG_FORCE = 45782, // fog to player, force cast 45714 + SPELL_FOG_INFORM = 45714, // player let fel cast 45717, script effect + SPELL_FOG_CHARM = 45717, // fel to player + SPELL_FOG_CHARM2 = 45726, // link to 45717 + + SPELL_TRANSFORM_TRIGGER = 44885, // madrigosa to self, trigger 46350 + SPELL_TRANSFORM_VISUAL = 46350, // 46411stun? + SPELL_TRANSFORM_FELMYST = 45068, // become fel + SPELL_FELMYST_SUMMON = 45069, + + //Other + SPELL_BERSERK = 45078, + SPELL_CLOUD_VISUAL = 45212, + SPELL_CLOUD_SUMMON = 45884, +}; + +enum PhaseFelmyst +{ + PHASE_NONE, + PHASE_GROUND, + PHASE_FLIGHT, +}; + +enum EventFelmyst +{ + EVENT_NONE, + EVENT_BERSERK, + + EVENT_CLEAVE, + EVENT_CORROSION, + EVENT_GAS_NOVA, + EVENT_ENCAPSULATE, + EVENT_FLIGHT, + + EVENT_FLIGHT_SEQUENCE, + EVENT_SUMMON_DEAD, + EVENT_SUMMON_FOG, +}; + +struct boss_felmystAI : public ScriptedAI +{ + boss_felmystAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + + // wait for core patch be accepted + /*SpellEntry *TempSpell = GET_SPELL(SPELL_ENCAPSULATE_EFFECT); + if (TempSpell->SpellIconID == 2294) + TempSpell->SpellIconID = 2295; + TempSpell = GET_SPELL(SPELL_VAPOR_TRIGGER); + if ((TempSpell->Attributes & SPELL_ATTR_PASSIVE) == 0) + TempSpell->Attributes |= SPELL_ATTR_PASSIVE; + TempSpell = GET_SPELL(SPELL_FOG_CHARM2); + if ((TempSpell->Attributes & SPELL_ATTR_PASSIVE) == 0) + TempSpell->Attributes |= SPELL_ATTR_PASSIVE;*/ + } + + ScriptedInstance *pInstance; + PhaseFelmyst phase; + EventMap events; + + uint32 uiFlightCount; + uint32 uiBreathCount; + + float breathX, breathY; + + void Reset() + { + phase = PHASE_NONE; + + events.Reset(); + + uiFlightCount = 0; + + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + + DespawnSummons(MOB_VAPOR_TRAIL); + me->setActive(false); + + if (pInstance) + pInstance->SetData(DATA_FELMYST_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + events.ScheduleEvent(EVENT_BERSERK, 600000); + + me->setActive(true); + DoZoneInCombat(); + DoCast(me, AURA_SUNWELL_RADIANCE, true); + DoCast(me, AURA_NOXIOUS_FUMES, true); + EnterPhase(PHASE_GROUND); + + if (pInstance) + pInstance->SetData(DATA_FELMYST_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit *who) + { + if (phase != PHASE_FLIGHT) + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (phase != PHASE_FLIGHT) + ScriptedAI::MoveInLineOfSight(who); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(YELL_KILL1,YELL_KILL2), me); + } + + void JustRespawned() + { + DoScriptText(YELL_BIRTH, me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(YELL_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FELMYST_EVENT, DONE); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + // workaround for linked aura + /*if (spell->Id == SPELL_VAPOR_FORCE) + { + caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true); + }*/ + // workaround for mind control + if (spell->Id == SPELL_FOG_INFORM) + { + float x, y, z; + caster->GetPosition(x, y, z); + if (Unit* summon = me->SummonCreature(MOB_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) + { + summon->SetMaxHealth(caster->GetMaxHealth()); + summon->SetHealth(caster->GetMaxHealth()); + summon->CastSpell(summon, SPELL_FOG_CHARM, true); + summon->CastSpell(summon, SPELL_FOG_CHARM2, true); + } + me->DealDamage(caster, caster->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == MOB_DEAD) + { + summon->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); + DoZoneInCombat(summon); + summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true); + } + } + + void MovementInform(uint32, uint32) + { + if (phase == PHASE_FLIGHT) + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); + } + + void DamageTaken(Unit*, uint32 &damage) + { + if (phase != PHASE_GROUND && damage >= me->GetHealth()) + damage = 0; + } + + void EnterPhase(PhaseFelmyst NextPhase) + { + switch(NextPhase) + { + case PHASE_GROUND: + me->CastStop(SPELL_FOG_BREATH); + me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); + me->SetUnitMovementFlags(MOVEMENTFLAG_NONE); + me->SetSpeed(MOVE_RUN, 2.0); + + events.ScheduleEvent(EVENT_CLEAVE, urand(5000, 10000)); + events.ScheduleEvent(EVENT_CORROSION, urand(10000, 20000)); + events.ScheduleEvent(EVENT_GAS_NOVA, urand(15000, 20000)); + events.ScheduleEvent(EVENT_ENCAPSULATE, urand(20000, 25000)); + events.ScheduleEvent(EVENT_FLIGHT, 60000); + break; + case PHASE_FLIGHT: + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1000); + uiFlightCount = 0; + uiBreathCount = 0; + break; + } + phase = NextPhase; + } + + void HandleFlightSequence() + { + switch(uiFlightCount) + { + case 0: + //me->AttackStop(); + me->GetMotionMaster()->Clear(false); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->StopMoving(); + DoScriptText(YELL_TAKEOFF, me); + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 2000); + break; + case 1: + me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+1, me->GetPositionY(), me->GetPositionZ()+10); + break; + case 2: + { + Unit *pTarget = pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); + if (!pTarget) + pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); + + if (!pTarget) + { + EnterEvadeMode(); + return; + } + + Creature* Vapor = me->SummonCreature(MOB_VAPOR, pTarget->GetPositionX()-5+rand()%10, pTarget->GetPositionY()-5+rand()%10, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + if (Vapor) + { + Vapor->AI()->AttackStart(pTarget); + me->InterruptNonMeleeSpells(false); + DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug + Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true); + } + + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); + break; + } + case 3: + { + DespawnSummons(MOB_VAPOR_TRAIL); + //DoCast(me, SPELL_VAPOR_SELECT); need core support + + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); + if (!pTarget) + pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); + + if (!pTarget) + { + EnterEvadeMode(); + return; + } + + //pTarget->CastSpell(pTarget, SPELL_VAPOR_SUMMON, true); need core support + Creature* pVapor = me->SummonCreature(MOB_VAPOR, pTarget->GetPositionX()-5+rand()%10, pTarget->GetPositionY()-5+rand()%10, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + if (pVapor) + { + if (pVapor->AI()) + pVapor->AI()->AttackStart(pTarget); + me->InterruptNonMeleeSpells(false); + DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug + pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true); + } + + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); + break; + } + case 4: + DespawnSummons(MOB_VAPOR_TRAIL); + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); + break; + case 5: + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); + if (!pTarget) + pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); + + if (!pTarget) + { + EnterEvadeMode(); + return; + } + + breathX = pTarget->GetPositionX(); + breathY = pTarget->GetPositionY(); + float x, y, z; + pTarget->GetContactPoint(me, x, y, z, 70); + me->GetMotionMaster()->MovePoint(0, x, y, z+10); + break; + } + case 6: + me->SetOrientation(me->GetAngle(breathX, breathY)); + me->StopMoving(); + //DoTextEmote("takes a deep breath.", NULL); + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); + break; + case 7: + { + DoCast(me, SPELL_FOG_BREATH, true); + float x, y, z; + me->GetPosition(x, y, z); + x = 2 * breathX - x; + y = 2 * breathY - y; + me->GetMotionMaster()->MovePoint(0, x, y, z); + events.ScheduleEvent(EVENT_SUMMON_FOG, 1); + break; + } + case 8: + me->CastStop(SPELL_FOG_BREATH); + me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); + ++uiBreathCount; + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); + if (uiBreathCount < 3) + uiFlightCount = 4; + break; + case 9: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO)) + DoStartMovement(pTarget); + else + { + EnterEvadeMode(); + return; + } + break; + case 10: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + EnterPhase(PHASE_GROUND); + AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO)); + break; + } + ++uiFlightCount; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (phase == PHASE_FLIGHT && !me->IsInEvadeMode()) + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->IsNonMeleeSpellCasted(false)) + return; + + if (phase == PHASE_GROUND) + { + switch(events.ExecuteEvent()) + { + case EVENT_BERSERK: + DoScriptText(YELL_BERSERK, me); + DoCast(me, SPELL_BERSERK, true); + events.ScheduleEvent(EVENT_BERSERK, 10000); + break; + case EVENT_CLEAVE: + DoCast(me->getVictim(), SPELL_CLEAVE, false); + events.ScheduleEvent(EVENT_CLEAVE, urand(5000,10000)); + break; + case EVENT_CORROSION: + DoCast(me->getVictim(), SPELL_CORROSION, false); + events.ScheduleEvent(EVENT_CORROSION, urand(20000,30000)); + break; + case EVENT_GAS_NOVA: + DoCast(me, SPELL_GAS_NOVA, false); + events.ScheduleEvent(EVENT_GAS_NOVA, urand(20000,25000)); + break; + case EVENT_ENCAPSULATE: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true)) + DoCast(pTarget, SPELL_ENCAPSULATE_CHANNEL, false); + events.ScheduleEvent(EVENT_ENCAPSULATE, urand(25000,30000)); + break; + case EVENT_FLIGHT: + EnterPhase(PHASE_FLIGHT); + break; + default: + DoMeleeAttackIfReady(); + break; + } + } + + if (phase == PHASE_FLIGHT) + { + switch(events.ExecuteEvent()) + { + case EVENT_BERSERK: + DoScriptText(YELL_BERSERK, me); + DoCast(me, SPELL_BERSERK, true); + break; + case EVENT_FLIGHT_SEQUENCE: + HandleFlightSequence(); + break; + case EVENT_SUMMON_FOG: + { + float x, y, z; + me->GetPosition(x, y, z); + me->UpdateGroundPositionZ(x, y, z); + if (Creature *Fog = me->SummonCreature(MOB_VAPOR_TRAIL, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 10000)) + { + Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER); + Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true); + me->CastSpell(Fog, SPELL_FOG_FORCE, true); + } + } + events.ScheduleEvent(EVENT_SUMMON_FOG, 1000); + break; + } + } + } + + void DespawnSummons(uint32 entry) + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllCreaturesOfEntryInRange check(me, entry, 100); + Trinity::CreatureListSearcher searcher(me, templist, check); + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + cell.Visit(pair, cSearcher, *(me->GetMap())); + + for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) + { + if (entry == MOB_VAPOR_TRAIL && phase == PHASE_FLIGHT) + { + (*i)->GetPosition(x, y, z); + me->SummonCreature(MOB_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + } + (*i)->SetVisibility(VISIBILITY_OFF); + (*i)->setDeathState(JUST_DIED); + if ((*i)->getDeathState() == CORPSE) + (*i)->RemoveCorpse(); + } + } +}; + +struct mob_felmyst_vaporAI : public ScriptedAI +{ + mob_felmyst_vaporAI(Creature *c) : ScriptedAI(c) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetSpeed(MOVE_RUN, 0.8); + } + void Reset() {} + void EnterCombat(Unit* /*who*/) + { + DoZoneInCombat(); + //DoCast(me, SPELL_VAPOR_FORCE, true); core bug + } + void UpdateAI(const uint32 /*diff*/) + { + if (!me->getVictim()) + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + AttackStart(pTarget); + } +}; + +struct mob_felmyst_trailAI : public ScriptedAI +{ + mob_felmyst_trailAI(Creature *c) : ScriptedAI(c) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_TRAIL_TRIGGER, true); + me->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 0.01); // core bug + } + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_boss_felmyst(Creature* pCreature) +{ + return new boss_felmystAI(pCreature); +} + +CreatureAI* GetAI_mob_felmyst_vapor(Creature* pCreature) +{ + return new mob_felmyst_vaporAI(pCreature); +} + +CreatureAI* GetAI_mob_felmyst_trail(Creature* pCreature) +{ + return new mob_felmyst_trailAI(pCreature); +} + +void AddSC_boss_felmyst() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_felmyst"; + newscript->GetAI = &GetAI_boss_felmyst; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felmyst_vapor"; + newscript->GetAI = &GetAI_mob_felmyst_vapor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felmyst_trail"; + newscript->GetAI = &GetAI_mob_felmyst_trail; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp new file mode 100644 index 00000000000..146771325eb --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp @@ -0,0 +1,794 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kalecgos +SD%Complete: 95 +SDComment: +SDCategory: Sunwell_Plateau +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +enum Yells +{ + //Kalecgos dragon form + SAY_EVIL_AGGRO = -1580000, + SAY_EVIL_SPELL1 = -1580001, + SAY_EVIL_SPELL2 = -1580002, + SAY_EVIL_SLAY1 = -1580003, + SAY_EVIL_SLAY2 = -1580004, + SAY_EVIL_ENRAGE = -1580005, + + //Kalecgos humanoid form + SAY_GOOD_AGGRO = -1580006, + SAY_GOOD_NEAR_DEATH = -1580007, + SAY_GOOD_NEAR_DEATH2 = -1580008, + SAY_GOOD_PLRWIN = -1580009, + + //Sathrovarr + SAY_SATH_AGGRO = -1580010, + SAY_SATH_DEATH = -1580011, + SAY_SATH_SPELL1 = -1580012, + SAY_SATH_SPELL2 = -1580013, + SAY_SATH_SLAY1 = -1580014, + SAY_SATH_SLAY2 = -1580015, + SAY_SATH_ENRAGE = -1580016, +}; + +enum Spells +{ + AURA_SUNWELL_RADIANCE = 45769, + AURA_SPECTRAL_EXHAUSTION = 44867, + AURA_SPECTRAL_REALM = 46021, + AURA_SPECTRAL_INVISIBILITY = 44801, + AURA_DEMONIC_VISUAL = 44800, + + SPELL_SPECTRAL_BLAST = 44869, + SPELL_TELEPORT_SPECTRAL = 46019, + SPELL_ARCANE_BUFFET = 45018, + SPELL_FROST_BREATH = 44799, + SPELL_TAIL_LASH = 45122, + + SPELL_BANISH = 44836, + SPELL_TRANSFORM_KALEC = 44670, + SPELL_ENRAGE = 44807, + + SPELL_CORRUPTION_STRIKE = 45029, + SPELL_AGONY_CURSE = 45032, + SPELL_SHADOW_BOLT = 45031, + + SPELL_HEROIC_STRIKE = 45026, + SPELL_REVITALIZE = 45027 +}; + +enum SWPActions +{ + DO_ENRAGE = 1, + DO_BANISH = 2, +}; + +#define GO_FAILED "You are unable to use this currently." + +#define EMOTE_UNABLE_TO_FIND "is unable to find Kalecgos" + +#define FLY_X 1679 +#define FLY_Y 900 +#define FLY_Z 82 + +#define CENTER_X 1705 +#define CENTER_Y 930 +#define RADIUS 30 + +#define DRAGON_REALM_Z 53.079 +#define DEMON_REALM_Z -74.558 + +#define MAX_PLAYERS_IN_SPECTRAL_REALM 0 //over this, teleport object won't work, 0 disables check + +uint32 WildMagic[] = { 44978, 45001, 45002, 45004, 45006, 45010 }; + +struct boss_kalecgosAI : public ScriptedAI +{ + boss_kalecgosAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + SathGUID = 0; + DoorGUID = 0; + bJustReset = false; + me->setActive(true); + SpellEntry *TempSpell = GET_SPELL(SPELL_SPECTRAL_BLAST); + if (TempSpell) + TempSpell->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ENEMY; + } + + ScriptedInstance *pInstance; + + uint32 ArcaneBuffetTimer; + uint32 FrostBreathTimer; + uint32 WildMagicTimer; + uint32 SpectralBlastTimer; + uint32 TailLashTimer; + uint32 CheckTimer; + uint32 TalkTimer; + uint32 TalkSequence; + uint32 ResetTimer; + + bool isFriendly; + bool isEnraged; + bool isBanished; + bool bJustReset; + + uint64 SathGUID; + uint64 DoorGUID; + + void Reset() + { + if (pInstance) + { + SathGUID = pInstance->GetData64(DATA_SATHROVARR); + pInstance->SetData(DATA_KALECGOS_EVENT, NOT_STARTED); + } + + if (Creature *Sath = Unit::GetCreature(*me, SathGUID)) + Sath->AI()->EnterEvadeMode(); + + me->setFaction(14); + if (!bJustReset) //first reset at create + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetVisibility(VISIBILITY_ON); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + } + me->SetHealth(me->GetMaxHealth());//dunno why it does not resets health at evade.. + ArcaneBuffetTimer = 8000; + FrostBreathTimer = 15000; + WildMagicTimer = 10000; + TailLashTimer = 25000; + SpectralBlastTimer = urand(20000,25000); + CheckTimer = 1000; + ResetTimer = 30000; + + TalkTimer = 0; + TalkSequence = 0; + isFriendly = false; + isEnraged = false; + isBanished = false; + } + + void EnterEvadeMode() + { + bJustReset = true; + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + ScriptedAI::EnterEvadeMode(); + } + + void DoAction(const int32 param) + { + switch (param) + { + case DO_ENRAGE: + isEnraged = true; + me->CastSpell(me, SPELL_ENRAGE, true); + break; + case DO_BANISH: + isBanished = true; + me->CastSpell(me, SPELL_BANISH, true); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (TalkTimer) + { + if (!TalkSequence) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(); + ++TalkSequence; + } + if (TalkTimer <= diff) + { + if (isFriendly) + GoodEnding(); + else + BadEnding(); + ++TalkSequence; + } else TalkTimer -= diff; + } + else + { + if (bJustReset) + { + if (ResetTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetVisibility(VISIBILITY_ON); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + ResetTimer = 10000; + bJustReset = false; + } else ResetTimer -= diff; + return; + } + if (!UpdateVictim()) + return; + + if (CheckTimer <= diff) + { + if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75) + { + me->AI()->EnterEvadeMode(); + return; + } + if (HealthBelowPct(10) && !isEnraged) + { + if (Creature* Sath = Unit::GetCreature(*me, SathGUID)) + Sath->AI()->DoAction(DO_ENRAGE); + DoAction(DO_ENRAGE); + } + if (!isBanished && HealthBelowPct(1)) + { + if (Creature* Sath = Unit::GetCreature(*me, SathGUID)) + { + if (Sath->HasAura(SPELL_BANISH)) + { + Sath->DealDamage(Sath, Sath->GetHealth()); + return; + } + else + DoAction(DO_BANISH); + } + else + { + error_log("TSCR: Didn't find Shathrowar. Kalecgos event reseted."); + EnterEvadeMode(); + return; + } + } + CheckTimer = 1000; + } else CheckTimer -= diff; + + if (ArcaneBuffetTimer <= diff) + { + DoCastAOE(SPELL_ARCANE_BUFFET); + ArcaneBuffetTimer = 8000; + } else ArcaneBuffetTimer -= diff; + + if (FrostBreathTimer <= diff) + { + DoCastAOE(SPELL_FROST_BREATH); + FrostBreathTimer = 15000; + } else FrostBreathTimer -= diff; + + if (TailLashTimer <= diff) + { + DoCastAOE(SPELL_TAIL_LASH); + TailLashTimer = 15000; + } else TailLashTimer -= diff; + + if (WildMagicTimer <= diff) + { + DoCastAOE(WildMagic[rand()%6]); + WildMagicTimer = 20000; + } else WildMagicTimer -= diff; + + if (SpectralBlastTimer <= diff) + { + std::list &m_threatlist = me->getThreatManager().getThreatList(); + std::list targetList; + for (std::list::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) + if ((*itr)->getTarget() && (*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->GetGUID() != me->getVictim()->GetGUID() && !(*itr)->getTarget()->HasAura(AURA_SPECTRAL_EXHAUSTION) && (*itr)->getTarget()->GetPositionZ() > me->GetPositionZ()-5) + targetList.push_back((*itr)->getTarget()); + if (targetList.empty()) + { + SpectralBlastTimer = 1000; + return; + } + std::list::const_iterator i = targetList.begin(); + advance(i, rand()%targetList.size()); + if ((*i)) + { + (*i)->CastSpell((*i), SPELL_SPECTRAL_BLAST,true); + SpectralBlastTimer = 20000+rand()%5000; + } else SpectralBlastTimer = 1000; + } else SpectralBlastTimer -= diff; + + DoMeleeAttackIfReady(); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (bJustReset)//boss is invisible, don't attack + return; + + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius)) + AttackStart(who); + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = 0; + } + + void EnterCombat(Unit* /*who*/) + { + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_EVIL_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_KALECGOS_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_EVIL_SLAY1,SAY_EVIL_SLAY2), me); + } + + void MovementInform(uint32 type,uint32 /*id*/) + { + if (type != POINT_MOTION_TYPE) + return; + me->SetVisibility(VISIBILITY_OFF); + if (isFriendly) + { + me->setDeathState(JUST_DIED); + + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer) + ((InstanceMap*)me->GetMap())->PermBindAllPlayers(pPlayer); + } + } + } + else + { + me->GetMotionMaster()->MoveTargetedHome(); + TalkTimer = 1000; + } + } + + void GoodEnding() + { + switch(TalkSequence) + { + case 1: + me->setFaction(35); + TalkTimer = 1000; + break; + case 2: + DoScriptText(SAY_GOOD_PLRWIN, me); + TalkTimer = 10000; + break; + case 3: + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); + TalkTimer = 600000; + break; + default: + break; + } + } + + void BadEnding() + { + switch(TalkSequence) + { + case 1: + DoScriptText(SAY_EVIL_ENRAGE, me); + TalkTimer = 3000; + break; + case 2: + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); + TalkTimer = 15000; + break; + case 3: + EnterEvadeMode(); + break; + default: + break; + } + } +}; + +struct boss_sathrovarrAI : public ScriptedAI +{ + boss_sathrovarrAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + KalecGUID = 0; + KalecgosGUID = 0; + } + + ScriptedInstance *pInstance; + + uint32 CorruptionStrikeTimer; + uint32 AgonyCurseTimer; + uint32 ShadowBoltTimer; + uint32 CheckTimer; + uint32 ResetThreat; + + uint64 KalecGUID; + uint64 KalecgosGUID; + + bool isEnraged; + bool isBanished; + + void Reset() + { + me->SetHealth(me->GetMaxHealth());//dunno why it does not resets health at evade.. + me->setActive(true); + if (pInstance) + { + KalecgosGUID = pInstance->GetData64(DATA_KALECGOS_DRAGON); + pInstance->SetData(DATA_KALECGOS_EVENT, NOT_STARTED); + } + if (KalecGUID) + { + if (Creature* Kalec = Unit::GetCreature(*me, KalecGUID)) + Kalec->setDeathState(JUST_DIED); + KalecGUID = 0; + } + + ShadowBoltTimer = 7000 + rand()%3 * 1000; + AgonyCurseTimer = 20000; + CorruptionStrikeTimer = 13000; + CheckTimer = 1000; + ResetThreat = 1000; + isEnraged = false; + isBanished = false; + + me->CastSpell(me, AURA_DEMONIC_VISUAL, true); + TeleportAllPlayersBack(); + } + + void EnterCombat(Unit* /*who*/) + { + if (Creature *Kalec = me->SummonCreature(MOB_KALEC, me->GetPositionX() + 10, me->GetPositionY() + 5, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) + { + KalecGUID = Kalec->GetGUID(); + me->CombatStart(Kalec); + me->AddThreat(Kalec, 100.0f); + Kalec->setActive(true); + } + DoScriptText(SAY_SATH_AGGRO, me); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = 0; + } + + void KilledUnit(Unit *pTarget) + { + if (pTarget->GetGUID() == KalecGUID) + { + TeleportAllPlayersBack(); + if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) + { + CAST_AI(boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1; + CAST_AI(boss_kalecgosAI, Kalecgos->AI())->isFriendly = false; + } + EnterEvadeMode(); + return; + } + DoScriptText(RAND(SAY_SATH_SLAY1,SAY_SATH_SLAY2), me); + } + + void JustDied(Unit * /*killer*/) + { + DoScriptText(SAY_SATH_DEATH, me); + me->GetMap()->CreatureRelocation(me, me->GetPositionX(), me->GetPositionY(), DRAGON_REALM_Z, me->GetOrientation()); + TeleportAllPlayersBack(); + if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) + { + CAST_AI(boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1; + CAST_AI(boss_kalecgosAI, Kalecgos->AI())->isFriendly = true; + } + + if (pInstance) + pInstance->SetData(DATA_KALECGOS_EVENT, DONE); + } + + void TeleportAllPlayersBack() + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) return; + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->GetPositionZ() <= DRAGON_REALM_Z-5) + { + i->getSource()->RemoveAura(AURA_SPECTRAL_REALM); + i->getSource()->TeleportTo(me->GetMap()->GetId(),i->getSource()->GetPositionX(),i->getSource()->GetPositionY(),DRAGON_REALM_Z+5,i->getSource()->GetOrientation()); + } + } + } + + void DoAction(const int32 param) + { + switch (param) + { + case DO_ENRAGE: + isEnraged = true; + me->CastSpell(me, SPELL_ENRAGE, true); + break; + case DO_BANISH: + isBanished = true; + me->CastSpell(me, SPELL_BANISH, true); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) + me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); + if (!UpdateVictim()) + return; + + if (CheckTimer <= diff) + { + Creature *Kalec = Unit::GetCreature(*me, KalecGUID); + if (!Kalec || (Kalec && !Kalec->isAlive())) + { + if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) + Kalecgos->AI()->EnterEvadeMode(); + return; + } + if (HealthBelowPct(10) && !isEnraged) + { + if (Creature* Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) + Kalecgos->AI()->DoAction(DO_ENRAGE); + DoAction(DO_ENRAGE); + } + Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID); + if (Kalecgos) + { + if (!Kalecgos->isInCombat()) + { + me->AI()->EnterEvadeMode(); + return; + } + } + if (!isBanished && HealthBelowPct(1)) + { + if (Kalecgos) + { + if (Kalecgos->HasAura(SPELL_BANISH)) + { + me->DealDamage(me, me->GetHealth()); + return; + } + else + DoAction(DO_BANISH); + } + else + { + me->MonsterTextEmote(EMOTE_UNABLE_TO_FIND, NULL); + EnterEvadeMode(); + return; + } + } + CheckTimer = 1000; + } else CheckTimer -= diff; + + if (ResetThreat <= diff) + { + for (std::list::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) + { + if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + if (pUnit->GetPositionZ() > me->GetPositionZ()+5) + { + me->getThreatManager().modifyThreatPercent(pUnit,-100); + } + } + } + ResetThreat = 1000; + } else ResetThreat -= diff; + + if (ShadowBoltTimer <= diff) + { + if (!(rand()%5))DoScriptText(SAY_SATH_SPELL1, me); + DoCast(me, SPELL_SHADOW_BOLT); + ShadowBoltTimer = 7000+(rand()%3000); + } else ShadowBoltTimer -= diff; + + if (AgonyCurseTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!pTarget) pTarget = me->getVictim(); + DoCast(pTarget, SPELL_AGONY_CURSE); + AgonyCurseTimer = 20000; + } else AgonyCurseTimer -= diff; + + if (CorruptionStrikeTimer <= diff) + { + if (!(rand()%5))DoScriptText(SAY_SATH_SPELL2, me); + DoCast(me->getVictim(), SPELL_CORRUPTION_STRIKE); + CorruptionStrikeTimer = 13000; + } else CorruptionStrikeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_kalecAI : public ScriptedAI +{ + ScriptedInstance *pInstance; + + uint32 RevitalizeTimer; + uint32 HeroicStrikeTimer; + uint32 YellTimer; + uint32 YellSequence; + + uint64 SathGUID; + + bool isEnraged; // if demon is enraged + + boss_kalecAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() + { + if (pInstance) + SathGUID = pInstance->GetData64(DATA_SATHROVARR); + + RevitalizeTimer = 5000; + HeroicStrikeTimer = 3000; + YellTimer = 5000; + YellSequence = 0; + + isEnraged = false; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != SathGUID) + damage = 0; + else if (isEnraged) + damage *= 3; + } + + void UpdateAI(const uint32 diff) + { + if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) + me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); + if (!UpdateVictim()) + return; + + if (YellTimer <= diff) + { + switch(YellSequence) + { + case 0: + DoScriptText(SAY_GOOD_AGGRO, me); + ++YellSequence; + break; + case 1: + if (HealthBelowPct(50)) + { + DoScriptText(SAY_GOOD_NEAR_DEATH, me); + ++YellSequence; + } + break; + case 2: + if (HealthBelowPct(10)) + { + DoScriptText(SAY_GOOD_NEAR_DEATH2, me); + ++YellSequence; + } + break; + default: + break; + } + YellTimer = 5000; + } + + if (RevitalizeTimer <= diff) + { + DoCast(me, SPELL_REVITALIZE); + RevitalizeTimer = 5000; + } else RevitalizeTimer -= diff; + + if (HeroicStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HEROIC_STRIKE); + HeroicStrikeTimer = 2000; + } else HeroicStrikeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +bool GOkalecgos_teleporter(Player* pPlayer, GameObject* pGo) +{ + uint32 SpectralPlayers = 0; + Map* pMap = pGo->GetMap(); + if (!pMap->IsDungeon()) return true; + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->GetPositionZ() < DEMON_REALM_Z + 5) + ++SpectralPlayers; + } + if (pPlayer->HasAura(AURA_SPECTRAL_EXHAUSTION) || (MAX_PLAYERS_IN_SPECTRAL_REALM && SpectralPlayers >= MAX_PLAYERS_IN_SPECTRAL_REALM)) + pPlayer->GetSession()->SendNotification(GO_FAILED); + else + pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_SPECTRAL, true); + return true; +} + +CreatureAI* GetAI_boss_kalecgos(Creature* pCreature) +{ + return new boss_kalecgosAI (pCreature); +} + +CreatureAI* GetAI_boss_Sathrovarr(Creature* pCreature) +{ + return new boss_sathrovarrAI (pCreature); +} + +CreatureAI* GetAI_boss_kalec(Creature* pCreature) +{ + return new boss_kalecAI (pCreature); +} + +void AddSC_boss_kalecgos() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kalecgos"; + newscript->GetAI = &GetAI_boss_kalecgos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_sathrovarr"; + newscript->GetAI = &GetAI_boss_Sathrovarr; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_kalec"; + newscript->GetAI = &GetAI_boss_kalec; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "kalecgos_teleporter"; + newscript->pGOHello = &GOkalecgos_teleporter; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp new file mode 100644 index 00000000000..f1c3a769b28 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp @@ -0,0 +1,1408 @@ +/* Copyright (C) 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kiljaeden +SD%Complete: 80 +SDComment: Sinister Reflection Model, Armageddon Visual, SAY_KJ_SHADOWSPIKE3, Emote, End Sequence +SDCategory: Sunwell_Plateau +EndScriptData */ + +//TODO rewrite Armageddon + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" +#include + +/*** Speech and sounds***/ +enum Yells +{ + // These are used throughout Sunwell and Magisters(?). Players can hear this while running through the instances. + SAY_KJ_OFFCOMBAT1 = -1580066, + SAY_KJ_OFFCOMBAT2 = -1580067, + SAY_KJ_OFFCOMBAT3 = -1580068, + SAY_KJ_OFFCOMBAT4 = -1580069, + SAY_KJ_OFFCOMBAT5 = -1580070, + + // Encounter speech and sounds + SAY_KJ_EMERGE = -1580071, + SAY_KJ_SLAY1 = -1580072, + SAY_KJ_SLAY2 = -1580073, + SAY_KJ_REFLECTION1 = -1580074, + SAY_KJ_REFLECTION2 = -1580075, + SAY_KJ_DARKNESS1 = -1580076, + SAY_KJ_DARKNESS2 = -1580077, + SAY_KJ_DARKNESS3 = -1580078, + SAY_KJ_PHASE3 = -1580079, + SAY_KJ_PHASE4 = -1580080, + SAY_KJ_PHASE5 = -1580081, + SAY_KJ_DEATH = -1580093, + EMOTE_KJ_DARKNESS = -1580094, + + /*** Kalecgos - Anveena speech at the beginning of Phase 5; Anveena's sacrifice ***/ + SAY_KALECGOS_AWAKEN = -1580082, + SAY_ANVEENA_IMPRISONED = -1580083, + SAY_KALECGOS_LETGO = -1580084, + SAY_ANVEENA_LOST = -1580085, + SAY_KALECGOS_FOCUS = -1580086, + SAY_ANVEENA_KALEC = -1580087, + SAY_KALECGOS_FATE = -1580088, + SAY_ANVEENA_GOODBYE = -1580089, + SAY_KALECGOS_GOODBYE = -1580090, + SAY_KALECGOS_ENCOURAGE = -1580091, + + /*** Kalecgos says throughout the fight ***/ + SAY_KALECGOS_JOIN = -1580092, + SAY_KALEC_ORB_READY1 = -1580095, + SAY_KALEC_ORB_READY2 = -1580096, + SAY_KALEC_ORB_READY3 = -1580097, + SAY_KALEC_ORB_READY4 = -1580098 +}; + +/*** Spells used during the encounter ***/ +enum Spells +{ + /* Hand of the Deceiver's spells and cosmetics */ + SPELL_SHADOW_BOLT_VOLLEY = 45770, // ~30 yard range Shadow Bolt Volley for ~2k(?) damage + SPELL_SHADOW_INFUSION = 45772, // They gain this at 20% - Immunity to Stun/Silence and makes them look angry! + SPELL_FELFIRE_PORTAL = 46875, // Creates a portal that spawns Felfire Fiends (LIVE FOR THE SWARM!1 FOR THE OVERMIND!) + SPELL_SHADOW_CHANNELING = 46757, // Channeling animation out of combat + + /* Volatile Felfire Fiend's spells */ + SPELL_FELFIRE_FISSION = 45779, // Felfire Fiends explode when they die or get close to target. + + /* Kil'Jaeden's spells and cosmetics */ + SPELL_TRANS = 23188, // Surprisingly, this seems to be the right spell.. (Where is it used?) + SPELL_REBIRTH = 44200, // Emerge from the Sunwell + SPELL_SOUL_FLAY = 45442, // 9k Shadow damage over 3 seconds. Spammed throughout all the fight. + SPELL_SOUL_FLAY_SLOW = 47106, + SPELL_LEGION_LIGHTNING = 45664, // Chain Lightning, 4 targets, ~3k Shadow damage, 1.5k mana burn + SPELL_FIRE_BLOOM = 45641, // Places a debuff on 5 raid members, which causes them to deal 2k Fire damage to nearby allies and selves. MIGHT NOT WORK + SPELL_DESTROY_ALL_DRAKES = 46707, // when he use it? + + SPELL_SINISTER_REFLECTION = 45785, // Summon shadow copies of 5 raid members that fight against KJ's enemies//dont work + // 45892 // right one for SPELL_SINISTER_REFLECTION but no EffectScriptEffect + SPELL_COPY_WEAPON = 41055, // } + SPELL_COPY_WEAPON2 = 41054, // } + SPELL_COPY_OFFHAND = 45206, // }- Spells used in Sinister Reflection creation + SPELL_COPY_OFFHAND_WEAPON = 45205, // } + + SPELL_SHADOW_SPIKE = 46680, // Bombard random raid members with Shadow Spikes (Very similar to Void Reaver orbs) + SPELL_FLAME_DART = 45737, // Bombards the raid with flames every 3(?) seconds + SPELL_DARKNESS_OF_A_THOUSAND_SOULS = 46605, // Begins a 8-second channeling, after which he will deal 50'000 damage to the raid + SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE = 45657, + + /* Armageddon spells wrong visual */ + SPELL_ARMAGEDDON_TRIGGER = 45909, // Meteor spell trigger missile should cast Creature on himself + SPELL_ARMAGEDDON_VISUAL = 45911, // Does the hellfire visual to indicate where the meteor missle lands + SPELL_ARMAGEDDON_VISUAL2 = 45914, // Does the light visual to indicate where the meteor missle lands + SPELL_ARMAGEDDON_VISUAL3 = 24207, // This shouldn't correct but same as seen on the movie + SPELL_ARMAGEDDON_SUMMON_TRIGGER = 45921, // Summons the triggers that cast the spells on himself need random target select + SPELL_ARMAGEDDON_DAMAGE = 45915, // This does the area damage + + /* Shield Orb Spells*/ + SPELL_SHADOW_BOLT = 45680, //45679 would be correct but triggers to often //TODO fix console error + + /* Anveena's spells and cosmetics (Or, generally, everything that has "Anveena" in name) */ + SPELL_ANVEENA_PRISON = 46367, // She hovers locked within a bubble + SPELL_ANVEENA_ENERGY_DRAIN = 46410, // Sunwell energy glow animation (Control mob uses this) + SPELL_SACRIFICE_OF_ANVEENA = 46474, // This is cast on Kil'Jaeden when Anveena sacrifices herself into the Sunwell + + /* Sinister Reflection Spells */ + SPELL_SR_CURSE_OF_AGONY = 46190, + SPELL_SR_SHADOW_BOLT = 47076, + + SPELL_SR_EARTH_SHOCK = 47071, + + SPELL_SR_FIREBALL = 47074, + + SPELL_SR_HEMORRHAGE = 45897, + + SPELL_SR_HOLY_SHOCK = 38921, + SPELL_SR_HAMMER_OF_JUSTICE = 37369, + + SPELL_SR_HOLY_SMITE = 47077, + SPELL_SR_RENEW = 47079, + + SPELL_SR_SHOOT = 16496, + SPELL_SR_MULTI_SHOT = 48098, + SPELL_SR_WING_CLIP = 40652, + + SPELL_SR_WHIRLWIND = 17207, + + SPELL_SR_MOONFIRE = 47072, + //SPELL_SR_PLAGU STRIKE = 58843, Dk Spell! + + /*** Other Spells (used by players, etc) ***/ + SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT = 45839, // Possess the blue dragon from the orb to help the raid. + SPELL_ENTROPIUS_BODY = 46819, // Visual for Entropius at the Epilogue + SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated +}; + +/*** Error messages ***/ +#define ERROR_KJ_NOT_SUMMONED "TSCR ERROR: Unable to summon Kil'Jaeden for some reason" + +/*** Others ***/ +#define FLOOR_Z 28.050388 +#define SHIELD_ORB_Z 45.000 + +enum Phase +{ + PHASE_DECEIVERS = 1, // Fight 3 adds + PHASE_NORMAL = 2, // Kil'Jaeden emerges from the sunwell + PHASE_DARKNESS = 3, // At 85%, he gains few abilities; Kalecgos joins the fight + PHASE_ARMAGEDDON = 4, // At 55%, he gains even more abilities + PHASE_SACRIFICE = 5, // At 25%, Anveena sacrifices herself into the Sunwell; at this point he becomes enraged and has *significally* shorter cooldowns. +}; + +//Timers +enum KilJaedenTimers +{ + TIMER_SPEECH = 0, + + //Phase 2 Timer + TIMER_SOUL_FLAY = 1, + TIMER_LEGION_LIGHTNING = 2, + TIMER_FIRE_BLOOM = 3, + TIMER_SUMMON_SHILEDORB = 4, + + //Phase 3 Timer + TIMER_SHADOW_SPIKE = 5, + TIMER_FLAME_DART = 6, + TIMER_DARKNESS = 7, + TIMER_ORBS_EMPOWER = 8, + + //Phase 4 Timer + TIMER_ARMAGEDDON = 9 +}; + +// Locations of the Hand of Deceiver adds +Position DeceiverLocations[3]= +{ + {1682.045, 631.299, 5.936}, + {1684.099, 618.848, 0.589}, + {1694.170, 612.272, 1.416}, +}; + +// Locations, where Shield Orbs will spawn +float ShieldOrbLocations[4][2]= +{ + {1698.900, 627.870}, // middle pont of Sunwell + {12, 3.14}, // First one spawns northeast of KJ + {12, 3.14/0.7}, // Second one spawns southeast + {12, 3.14*3.8} // Third one spawns (?) +}; + +struct Speech +{ + int32 textid; + uint32 pCreature, timer; +}; + +// Timers +static Speech Speeches[]= +{ + //Kil Phase 1 -> Phase 2 + {SAY_KJ_EMERGE, DATA_KILJAEDEN, 0}, + {SAY_KALECGOS_JOIN, DATA_KALECGOS_KJ, 26000}, + //Kil Phase 2 -> Phase 3 + {SAY_KALECGOS_AWAKEN, DATA_KALECGOS_KJ, 10000}, + {SAY_ANVEENA_IMPRISONED, DATA_ANVEENA, 5000}, + {SAY_KJ_PHASE3, DATA_KILJAEDEN, 5000}, + //Kil Phase 3 -> Phase 4 + {SAY_KALECGOS_LETGO, DATA_KALECGOS_KJ, 10000}, + {SAY_ANVEENA_LOST, DATA_ANVEENA, 8000}, + {SAY_KJ_PHASE4, DATA_KILJAEDEN, 7000}, + //Kil Phase 4 -> Phase 5 + {SAY_KALECGOS_FOCUS, DATA_KALECGOS_KJ, 4000}, + {SAY_ANVEENA_KALEC, DATA_ANVEENA, 11000}, + {SAY_KALECGOS_FATE, DATA_KALECGOS_KJ, 2000}, + {SAY_ANVEENA_GOODBYE, DATA_ANVEENA, 6000}, + {SAY_KJ_PHASE5, DATA_KILJAEDEN, 5500}, + + // use in End sequence? + {SAY_KALECGOS_GOODBYE, DATA_KALECGOS_KJ, 12000}, +}; + +//AI for Kalecgos +struct boss_kalecgos_kjAI : public ScriptedAI +{ + boss_kalecgos_kjAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint8 OrbsEmpowered; + uint8 EmpowerCount; + + void Reset() + { + OrbsEmpowered = 0; + EmpowerCount = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setActive(true); + + for (uint8 i = 0; i < 4; ++i) + if (GameObject* pOrb = GetOrb(i)) + pOrb->SetGoType(GAMEOBJECT_TYPE_BUTTON); + } + + GameObject* GetOrb(int32 index) + { + if (!pInstance) + return NULL; + + switch(index) + { + case 0: + return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1)); + case 1: + return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2)); + case 2: + return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3)); + case 3: + return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4)); + } + + return NULL; + } + + void ResetOrbs() + { + me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); + for (uint8 i = 0; i < 4; ++i) + if (GameObject* pOrb = GetOrb(i)) + pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 0); + } + + void EmpowerOrb(bool all) + { + GameObject* pOrbEmpowered = GetOrb(OrbsEmpowered); + if (!pOrbEmpowered) + return; + + if (all) + { + me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); + for (uint8 i = 0; i < 4; ++i) + { + if (GameObject* pOrb = GetOrb(i)) + { + pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); + pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 35); + pOrb->setActive(true); + pOrb->Refresh(); + } + } + DoScriptText(SAY_KALECGOS_ENCOURAGE, me); + } + else + { + if (GameObject* pOrb = GetOrb(urand(0,3))) + { + pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); + pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 35); + pOrb->setActive(true); + pOrb->Refresh(); + + OrbsEmpowered = (OrbsEmpowered+1)%4; + + ++EmpowerCount; + switch(EmpowerCount) + { + case 1: DoScriptText(SAY_KALEC_ORB_READY1, me); break; + case 2: DoScriptText(SAY_KALEC_ORB_READY2, me); break; + case 3: DoScriptText(SAY_KALEC_ORB_READY3, me); break; + case 4: DoScriptText(SAY_KALEC_ORB_READY4, me); break; + } + } + } + } + + void UpdateAI(const uint32 diff) + { + } + + void SetRingOfBlueFlames() + { + me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); + for (uint8 i = 0; i < 4; ++i) + { + if (GameObject* pOrb = GetOrb(i)) + { + if (pOrb->GetUInt32Value(GAMEOBJECT_FACTION) == 35) + { + pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); + pOrb->setActive(true); + pOrb->Refresh(); + } + } + } + } +}; + +CreatureAI* GetAI_boss_kalecgos_kj(Creature* pCreature) +{ + return new boss_kalecgos_kjAI (pCreature); +} + +bool GOHello_go_orb_of_the_blue_flight(Player* pPlayer, GameObject* pGo) +{ + if (pGo->GetUInt32Value(GAMEOBJECT_FACTION) == 35) + { + ScriptedInstance* pInstance = pGo->GetInstanceData(); + pPlayer->SummonCreature(CREATURE_POWER_OF_THE_BLUE_DRAGONFLIGHT, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 121000); + pPlayer->CastSpell(pPlayer, SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT, false); + pGo->SetUInt32Value(GAMEOBJECT_FACTION, 0); + + if (Creature* pKalec = Unit::GetCreature(*pPlayer, pInstance->GetData64(DATA_KALECGOS_KJ))) + CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->SetRingOfBlueFlames(); + + pGo->Refresh(); + } + return true; +} + +//AI for Kil'jaeden Event Controller +struct mob_kiljaeden_controllerAI : public Scripted_NoMovementAI +{ + mob_kiljaeden_controllerAI(Creature* c) : Scripted_NoMovementAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + SummonList summons; + + bool bSummonedDeceivers; + bool bKiljaedenDeath; + + uint32 uiRandomSayTimer; + uint32 phase; + uint8 deceiverDeathCount; + + void InitializeAI() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->addUnitState(UNIT_STAT_STUNNED); + + ScriptedAI::InitializeAI(); + } + + void Reset() + { + phase = PHASE_DECEIVERS; + + if (Creature* pKalecKJ = Unit::GetCreature((*me), pInstance->GetData64(DATA_KALECGOS_KJ))) + CAST_AI(boss_kalecgos_kjAI, pKalecKJ->AI())->ResetOrbs(); + deceiverDeathCount = 0; + bSummonedDeceivers = false; + bKiljaedenDeath = false; + uiRandomSayTimer = 30000; + summons.DespawnAll(); + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + case CREATURE_HAND_OF_THE_DECEIVER: + summoned->CastSpell(summoned, SPELL_SHADOW_CHANNELING, false); + break; + case CREATURE_ANVEENA: + summoned->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + summoned->CastSpell(summoned, SPELL_ANVEENA_PRISON, true); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + break; + case CREATURE_KILJAEDEN: + summoned->CastSpell(summoned, SPELL_REBIRTH, false); + summoned->AddThreat(me->getVictim(), 1.0f); + break; + } + summons.Summon(summoned); + } + + void UpdateAI(const uint32 diff) + { + if (uiRandomSayTimer < diff) + { + if (pInstance && pInstance->GetData(DATA_MURU_EVENT) != DONE && pInstance->GetData(DATA_KILJAEDEN_EVENT) == NOT_STARTED) + DoScriptText(RAND(SAY_KJ_OFFCOMBAT1,SAY_KJ_OFFCOMBAT2,SAY_KJ_OFFCOMBAT3,SAY_KJ_OFFCOMBAT4,SAY_KJ_OFFCOMBAT5), me); + uiRandomSayTimer = 30000; + } else uiRandomSayTimer -= diff; + + if (!bSummonedDeceivers) + { + for (uint8 i = 0; i < 3; ++i) + me->SummonCreature(CREATURE_HAND_OF_THE_DECEIVER, DeceiverLocations[i], TEMPSUMMON_DEAD_DESPAWN, 0); + + DoSpawnCreature(CREATURE_ANVEENA, 0, 0, 40, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + DoCast(me, SPELL_ANVEENA_ENERGY_DRAIN); + bSummonedDeceivers = true; + } + + if (deceiverDeathCount > 2 && phase == PHASE_DECEIVERS) + { + me->RemoveAurasDueToSpell(SPELL_ANVEENA_ENERGY_DRAIN); + phase = PHASE_NORMAL; + DoSpawnCreature(CREATURE_KILJAEDEN, 0, 0,0, 0, TEMPSUMMON_MANUAL_DESPAWN, 0); + } + } +}; + +CreatureAI* GetAI_mob_kiljaeden_controller(Creature* pCreature) +{ + return new mob_kiljaeden_controllerAI (pCreature); +} + +//AI for Kil'jaeden +struct boss_kiljaedenAI : public Scripted_NoMovementAI +{ + boss_kiljaedenAI(Creature* c) : Scripted_NoMovementAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + SummonList summons; + + uint8 Phase; + uint8 ActiveTimers; + uint32 SpeechTimer; + + uint32 Timer[10]; + uint32 WaitTimer; + uint8 speechCount; + uint8 speechPhaseEnd; + + /* Boolean */ + bool IsInDarkness; + bool TimerIsDeactivated[10]; + bool IsWaiting; + bool OrbActivated; + bool SpeechBegins; + + void InitializeAI() + { + Scripted_NoMovementAI::InitializeAI(); + } + + void Reset() + { + TimerIsDeactivated[TIMER_SPEECH] = false; + Timer[TIMER_SPEECH] = 0; + + //Phase 2 Timer + Timer[TIMER_SOUL_FLAY] = 11000; + Timer[TIMER_LEGION_LIGHTNING] = 30000; + Timer[TIMER_FIRE_BLOOM] = 20000; + Timer[TIMER_SUMMON_SHILEDORB] = 35000; + + //Phase 3 Timer + Timer[TIMER_SHADOW_SPIKE] = 4000; + Timer[TIMER_FLAME_DART] = 3000; + Timer[TIMER_DARKNESS] = 45000; + Timer[TIMER_ORBS_EMPOWER] = 35000; + + //Phase 4 Timer + Timer[TIMER_ARMAGEDDON] = 2000; + + ActiveTimers = 5; + WaitTimer = 0; + speechCount = 0; + SpeechTimer = 0; + + Phase = PHASE_NORMAL; + + IsInDarkness = false; + IsWaiting = false; + OrbActivated = false; + SpeechBegins = true; + + if (pInstance) + { + if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ))) + pKalec->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); + } + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 12); + ChangeTimers(false, 0); + summons.DespawnAll(); + } + + void ChangeTimers(bool status, uint32 WTimer) + { + for (uint8 i = 1; i < ActiveTimers; ++i) + TimerIsDeactivated[i] = status; + + if (WTimer > 0) + { + IsWaiting = true; + WaitTimer = WTimer; + } + + if (OrbActivated) + TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true; + if (Timer[TIMER_SHADOW_SPIKE] == 0) + TimerIsDeactivated[TIMER_SHADOW_SPIKE] = true; + if (Phase == PHASE_SACRIFICE) + TimerIsDeactivated[TIMER_SUMMON_SHILEDORB] = true; + } + + void JustSummoned(Creature* summoned) + { + if (summoned->GetEntry() == CREATURE_ARMAGEDDON_TARGET) + { + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + // summoned->SetVisibility(VISIBILITY_OFF); //with this we cant see the armageddon visuals + } + else + summoned->SetLevel(me->getLevel()); + + summoned->setFaction(me->getFaction()); + summons.Summon(summoned); + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_KJ_DEATH, me); + summons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_KILJAEDEN_EVENT, DONE); + } + + void KilledUnit(Unit* victim) + { + DoScriptText(RAND(SAY_KJ_SLAY1,SAY_KJ_SLAY2), me); + } + + void EnterEvadeMode() + { + Scripted_NoMovementAI::EnterEvadeMode(); + summons.DespawnAll(); + + // Reset the controller + if (pInstance) + { + if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) + CAST_AI(mob_kiljaeden_controllerAI, pControl->AI())->Reset(); + } + } + + void EnterCombat(Unit* who) + { + DoZoneInCombat(); + } + + void EnterNextPhase() + { + SpeechBegins = true; + OrbActivated = false; + ChangeTimers(true, 0);//stop every cast Shadow spike will reactivate em all + TimerIsDeactivated[TIMER_SHADOW_SPIKE] = false; + Timer[TIMER_SHADOW_SPIKE] = 100; + // empowered orbs before darkness + Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(10000,40000); + Timer[TIMER_ORBS_EMPOWER] = (Phase == PHASE_SACRIFICE) ? 10000 : 5000; + } + + void CastSinisterReflection() + { + DoScriptText(RAND(SAY_KJ_REFLECTION1,SAY_KJ_REFLECTION2), me); + for (uint8 i = 0; i < 4; ++i) + { + float x,y,z; + Unit *pTarget; + for (uint8 z = 0; z < 6; ++z) + { + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0))break; + } + if (pTarget) + { + pTarget->GetPosition(x,y,z); + if (Creature* pSinisterReflection = me->SummonCreature(CREATURE_SINISTER_REFLECTION, x,y,z,0, TEMPSUMMON_CORPSE_DESPAWN, 0)) + { + pSinisterReflection->SetDisplayId(pTarget->GetDisplayId()); + pSinisterReflection->AI()->AttackStart(pTarget); + } + } + } + } + + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || Phase < PHASE_NORMAL) + return; + + if (IsWaiting) + { + if (WaitTimer <= diff) + { + IsWaiting = false; + ChangeTimers(false, 0); + } else WaitTimer -= diff; + } + + for (uint8 t = 0; t < ActiveTimers; ++t) + { + if (Timer[t] < diff && !TimerIsDeactivated[t]) + { + switch(t) + { + case TIMER_SPEECH: + if (SpeechBegins) + { + SpeechBegins=false; + switch(Phase) + { + case PHASE_NORMAL: + speechPhaseEnd=1; + break; + case PHASE_DARKNESS: + speechPhaseEnd=4; + break; + case PHASE_ARMAGEDDON: + speechPhaseEnd=7; + break; + case PHASE_SACRIFICE: + speechPhaseEnd=12; + break; + } + } + if (Speeches[speechCount].timer < SpeechTimer) + { + SpeechTimer = 0; + if (Creature* pSpeechCreature = Unit::GetCreature(*me, pInstance->GetData64(Speeches[speechCount].pCreature))) + DoScriptText(Speeches[speechCount].textid, pSpeechCreature); + if (speechCount == 12) + if (Creature* pAnveena = Unit::GetCreature(*me, pInstance->GetData64(DATA_ANVEENA))) + pAnveena->CastSpell(me, SPELL_SACRIFICE_OF_ANVEENA, false); + // ChangeTimers(true, 10000); // Kil should do an emote while screaming without attacking for 10 seconds + if (speechCount == speechPhaseEnd) + TimerIsDeactivated[TIMER_SPEECH]=true; + speechCount++; + } + SpeechTimer += diff; + break; + case TIMER_SOUL_FLAY: + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me->getVictim(), SPELL_SOUL_FLAY_SLOW, false); + DoCast(me->getVictim(), SPELL_SOUL_FLAY, false); + Timer[TIMER_SOUL_FLAY] = 3500; + } + break; + case TIMER_LEGION_LIGHTNING: + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit* pRandomPlayer; + + me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY); + for (uint8 z = 0; z < 6; ++z) + { + pRandomPlayer = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!pRandomPlayer->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) + break; + } + + if (pRandomPlayer) + DoCast(pRandomPlayer, SPELL_LEGION_LIGHTNING, false); + else + error_log("try to cast SPELL_LEGION_LIGHTNING on invalid target"); + + Timer[TIMER_LEGION_LIGHTNING] = (Phase == PHASE_SACRIFICE) ? 18000 : 30000; // 18 seconds in PHASE_SACRIFICE + Timer[TIMER_SOUL_FLAY] = 2500; + } + break; + case TIMER_FIRE_BLOOM: + if (!me->IsNonMeleeSpellCasted(false)) + { + me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY); + DoCastAOE(SPELL_FIRE_BLOOM, false); + Timer[TIMER_FIRE_BLOOM] = (Phase == PHASE_SACRIFICE) ? 25000 : 40000; // 25 seconds in PHASE_SACRIFICE + Timer[TIMER_SOUL_FLAY] = 1000; + } + break; + case TIMER_SUMMON_SHILEDORB: + for (uint8 i = 1; i < Phase; ++i) + { + float sx, sy; + sx = ShieldOrbLocations[0][0] + sin(ShieldOrbLocations[i][0]); + sy = ShieldOrbLocations[0][1] + sin(ShieldOrbLocations[i][1]); + me->SummonCreature(CREATURE_SHIELD_ORB, sx, sy, SHIELD_ORB_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + } + Timer[TIMER_SUMMON_SHILEDORB] = urand(30000,60000); // 30-60seconds cooldown + Timer[TIMER_SOUL_FLAY] = 2000; + break; + case TIMER_SHADOW_SPIKE: //Phase 3 + if (!me->IsNonMeleeSpellCasted(false)) + { + CastSinisterReflection(); + DoCastAOE(SPELL_SHADOW_SPIKE, false); + ChangeTimers(true, 30000); + Timer[TIMER_SHADOW_SPIKE] = 0; + TimerIsDeactivated[TIMER_SPEECH] = false; + } + break; + case TIMER_FLAME_DART: //Phase 3 + DoCastAOE(SPELL_FLAME_DART, false); + Timer[TIMER_FLAME_DART] = 3000; //TODO Timer + break; + case TIMER_DARKNESS: //Phase 3 + if (!me->IsNonMeleeSpellCasted(false)) + { + // Begins to channel for 8 seconds, then deals 50'000 damage to all raid members. + if (!IsInDarkness) + { + DoScriptText(EMOTE_KJ_DARKNESS, me); + DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS, false); + ChangeTimers(true, 9000); + Timer[TIMER_DARKNESS] = 8750; + TimerIsDeactivated[TIMER_DARKNESS] = false; + if (Phase == PHASE_SACRIFICE) + TimerIsDeactivated[TIMER_ARMAGEDDON] = false; + IsInDarkness = true; + } + else + { + Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(40000,70000); + IsInDarkness = false; + DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE); + DoScriptText(RAND(SAY_KJ_DARKNESS1,SAY_KJ_DARKNESS2,SAY_KJ_DARKNESS3), me); + } + Timer[TIMER_SOUL_FLAY] = 9000; + } + break; + case TIMER_ORBS_EMPOWER: //Phase 3 + if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ))) + { + switch (Phase) + { + case PHASE_SACRIFICE: + CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(true); + break; + default: + CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(false); + break; + } + } + OrbActivated = true; + TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true; + break; + case TIMER_ARMAGEDDON: //Phase 4 + Unit *pTarget; + for (uint8 z = 0; z < 6; ++z) + { + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break; + } + if (pTarget) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + me->SummonCreature(CREATURE_ARMAGEDDON_TARGET, x,y,z,0, TEMPSUMMON_TIMED_DESPAWN,15000); + } + Timer[TIMER_ARMAGEDDON] = 2000; // No, I'm not kidding + break; + } + } + } + DoMeleeAttackIfReady(); + //Time runs over! + for (uint8 i = 0; i < ActiveTimers; ++i) + if (!TimerIsDeactivated[i]) + { + Timer[i] -= diff; + if (((int32)Timer[i]) < 0) Timer[i] = 0; + } + + //Phase 3 + if (Phase <= PHASE_NORMAL && !IsInDarkness) + { + if (Phase == PHASE_NORMAL && HealthBelowPct(85)) + { + Phase = PHASE_DARKNESS; + ActiveTimers = 9; + EnterNextPhase(); + } + else return; + } + + //Phase 4 + if (Phase <= PHASE_DARKNESS && !IsInDarkness) + { + if (Phase == PHASE_DARKNESS && HealthBelowPct(55)) + { + Phase = PHASE_ARMAGEDDON; + ActiveTimers = 10; + EnterNextPhase(); + } + else return; + } + + //Phase 5 specific spells all we can + if (Phase <= PHASE_ARMAGEDDON && !IsInDarkness) + { + if (Phase == PHASE_ARMAGEDDON && HealthBelowPct(25)) + { + Phase = PHASE_SACRIFICE; + EnterNextPhase(); + } + else return; + } + } +}; + +CreatureAI* GetAI_boss_kiljaeden(Creature* pCreature) +{ + return new boss_kiljaedenAI (pCreature); +} + +//AI for Hand of the Deceiver +struct mob_hand_of_the_deceiverAI : public ScriptedAI +{ + mob_hand_of_the_deceiverAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ShadowBoltVolleyTimer; + uint32 FelfirePortalTimer; + + void Reset() + { + // TODO: Timers! + ShadowBoltVolleyTimer = urand(8000,14000); // So they don't all cast it in the same moment. + FelfirePortalTimer = 20000; + if (pInstance) + pInstance->SetData(DATA_KILJAEDEN_EVENT, NOT_STARTED); + } + + void JustSummoned(Creature* summoned) + { + summoned->setFaction(me->getFaction()); + summoned->SetLevel(me->getLevel()); + } + + void EnterCombat(Unit* who) + { + if (pInstance) + { + pInstance->SetData(DATA_KILJAEDEN_EVENT, IN_PROGRESS); + if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) + pControl->AddThreat(who, 1.0f); + } + me->InterruptNonMeleeSpells(true); + } + + void JustDied(Unit* killer) + { + if (!pInstance) + return; + + if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) + ++(CAST_AI(mob_kiljaeden_controllerAI, pControl->AI())->deceiverDeathCount); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + DoCast(me, SPELL_SHADOW_CHANNELING); + + if (!UpdateVictim()) + return; + + // Gain Shadow Infusion at 20% health + if (HealthBelowPct(20) && !me->HasAura(SPELL_SHADOW_INFUSION, 0)) + DoCast(me, SPELL_SHADOW_INFUSION, true); + + // Shadow Bolt Volley - Shoots Shadow Bolts at all enemies within 30 yards, for ~2k Shadow damage. + if (ShadowBoltVolleyTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); + ShadowBoltVolleyTimer = 12000; + } + else + ShadowBoltVolleyTimer -= diff; + + // Felfire Portal - Creatres a portal, that spawns Volatile Felfire Fiends, which do suicide bombing. + if (FelfirePortalTimer <= diff) + { + if (Creature* pPortal = DoSpawnCreature(CREATURE_FELFIRE_PORTAL, 0, 0,0, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) + { + std::list::iterator itr; + for (itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) + { + Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pUnit) + pPortal->AddThreat(pUnit, 1.0f); + } + } + FelfirePortalTimer = 20000; + } else FelfirePortalTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_hand_of_the_deceiver(Creature* pCreature) +{ + return new mob_hand_of_the_deceiverAI (pCreature); +} + +//AI for Felfire Portal +struct mob_felfire_portalAI : public Scripted_NoMovementAI +{ + mob_felfire_portalAI(Creature* c) : Scripted_NoMovementAI(c) {} + + uint32 uiSpawnFiendTimer; + + void Reset() + { + uiSpawnFiendTimer = 5000; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + } + + void JustSummoned(Creature* summoned) + { + summoned->setFaction(me->getFaction()); + summoned->SetLevel(me->getLevel()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiSpawnFiendTimer <= diff) + { + if (Creature* pFiend = DoSpawnCreature(CREATURE_VOLATILE_FELFIRE_FIEND, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) + pFiend->AddThreat(SelectUnit(SELECT_TARGET_RANDOM,0), 100000.0f); + uiSpawnFiendTimer = urand(4000,8000); + } else uiSpawnFiendTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_felfire_portal(Creature* pCreature) +{ + return new mob_felfire_portalAI (pCreature); +} + +//AI for Felfire Fiend +struct mob_volatile_felfire_fiendAI : public ScriptedAI +{ + mob_volatile_felfire_fiendAI(Creature* c) : ScriptedAI(c) {} + + uint32 uiExplodeTimer; + + bool bLockedTarget; + + void Reset() + { + uiExplodeTimer = 2000; + bLockedTarget = false; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage > me->GetHealth()) + DoCast(me, SPELL_FELFIRE_FISSION, true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!bLockedTarget) + { + me->AddThreat(me->getVictim(), 10000000.0f); + bLockedTarget = true; + } + + if (uiExplodeTimer) + { + if (uiExplodeTimer <= diff) + uiExplodeTimer = 0; + else uiExplodeTimer -= diff; + } + else if (me->IsWithinDistInMap(me->getVictim(), 3)) // Explode if it's close enough to it's target + { + DoCast(me->getVictim(), SPELL_FELFIRE_FISSION); + me->Kill(me); + } + } +}; + +CreatureAI* GetAI_mob_volatile_felfire_fiend(Creature* pCreature) +{ + return new mob_volatile_felfire_fiendAI (pCreature); +} + +//AI for Armageddon target +struct mob_armageddonAI : public Scripted_NoMovementAI +{ + mob_armageddonAI(Creature* c) : Scripted_NoMovementAI(c) {} + + uint8 spell; + uint32 uiTimer; + + void Reset() + { + spell = 0; + uiTimer = 0; + } + + void UpdateAI(const uint32 diff) + { + if (uiTimer <= diff) + { + switch(spell) + { + case 0: + DoCast(me, SPELL_ARMAGEDDON_VISUAL, true); + ++spell; + break; + case 1: + DoCast(me, SPELL_ARMAGEDDON_VISUAL2, true); + uiTimer = 9000; + ++spell; + break; + case 2: + DoCast(me, SPELL_ARMAGEDDON_TRIGGER, true); + ++spell; + uiTimer = 5000; + break; + case 3: + me->Kill(me); + me->RemoveCorpse(); + break; + } + } else uiTimer -=diff; + } +}; + +CreatureAI* GetAI_mob_armageddon(Creature* pCreature) +{ + return new mob_armageddonAI (pCreature); +} + +//AI for Shield Orbs +struct mob_shield_orbAI : public ScriptedAI +{ + mob_shield_orbAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bPointReached; + bool bClockwise; + uint32 uiTimer; + uint32 uiCheckTimer; + float x, y, r, c, mx, my; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + bPointReached = true; + uiTimer = urand(500,1000); + uiCheckTimer = 1000; + r = 17; + c = 0; + mx = ShieldOrbLocations[0][0]; + my = ShieldOrbLocations[0][1]; + bClockwise = urand(0,1); + } + + void UpdateAI(const uint32 diff) + { + if (bPointReached) + { + if (bClockwise) + { + y = my - r * sin(c); + x = mx - r * cos(c); + } + else + { + y = my + r * sin(c); + x = mx + r * cos(c); + } + bPointReached = false; + uiCheckTimer = 1000; + me->GetMotionMaster()->MovePoint(1,x, y, SHIELD_ORB_Z); + c += M_PI/32; + if (c >= 2*M_PI) c = 0; + } + else + { + if (uiCheckTimer <= diff) + { + DoTeleportTo(x,y,SHIELD_ORB_Z); + bPointReached = true; + } + else uiCheckTimer -= diff; + } + + if (uiTimer <= diff) + { + if (Unit* random = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0)) + DoCast(random, SPELL_SHADOW_BOLT, false); + uiTimer = urand(500,1000); + } else uiTimer -= diff; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + bPointReached = true; + } +}; + +CreatureAI* GetAI_mob_shield_orb(Creature* pCreature) +{ + return new mob_shield_orbAI (pCreature); +} + +//AI for Sinister Reflection +struct mob_sinster_reflectionAI : public ScriptedAI +{ + mob_sinster_reflectionAI(Creature* c) : ScriptedAI(c) {} + + uint8 victimClass; + uint32 uiTimer[3]; + + void Reset() + { + uiTimer[0] = 0; + uiTimer[1] = 0; + uiTimer[2] = 0; + victimClass = 0; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if ((victimClass == 0) && me->getVictim()) + { + victimClass = me->getVictim()->getClass(); + switch (victimClass) + { + case CLASS_DRUID: + break; + case CLASS_HUNTER: + break; + case CLASS_MAGE: + break; + case CLASS_WARLOCK: + break; + case CLASS_WARRIOR: + me->SetCanDualWield(true); + break; + case CLASS_PALADIN: + break; + case CLASS_PRIEST: + break; + case CLASS_SHAMAN: + me->SetCanDualWield(true); + break; + case CLASS_ROGUE: + me->SetCanDualWield(true); + break; + } + } + + switch(victimClass) { + case CLASS_DRUID: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_MOONFIRE, false); + uiTimer[1] = urand(2000,4000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_HUNTER: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_MULTI_SHOT, false); + uiTimer[1] = urand(8000,10000); + } + if (uiTimer[2] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_SHOOT, false); + uiTimer[2] = urand(4000,6000); + } + if (me->IsWithinMeleeRange(me->getVictim(), 6)) + { + if (uiTimer[0] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_MULTI_SHOT, false); + uiTimer[0] = urand(6000,8000); + } + DoMeleeAttackIfReady(); + } + break; + case CLASS_MAGE: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_FIREBALL, false); + uiTimer[1] = urand(2000,4000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_WARLOCK: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_SHADOW_BOLT, false); + uiTimer[1] = urand(3000,5000); + } + if (uiTimer[2] <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_SR_CURSE_OF_AGONY, true); + uiTimer[2] = urand(2000,4000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_WARRIOR: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_WHIRLWIND, false); + uiTimer[1] = urand(9000,11000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_PALADIN: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_HAMMER_OF_JUSTICE, false); + uiTimer[1] = urand(6000,8000); + } + if (uiTimer[2] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_HOLY_SHOCK, false); + uiTimer[2] = urand(2000,4000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_PRIEST: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_HOLY_SMITE, false); + uiTimer[1] = urand(4000,6000); + } + if (uiTimer[2] <= diff) + { + DoCast(me, SPELL_SR_RENEW, false); + uiTimer[2] = urand(6000,8000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_SHAMAN: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_EARTH_SHOCK, false); + uiTimer[1] = urand(4000,6000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_ROGUE: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_HEMORRHAGE, true); + uiTimer[1] = urand(4000,6000); + } + DoMeleeAttackIfReady(); + break; + } + debug_log("Sinister-Timer"); + for (uint8 i = 0; i < 3; ++i) + uiTimer[i] -= diff; + } +}; + +CreatureAI* GetAI_mob_sinster_reflection(Creature* pCreature) +{ + return new mob_sinster_reflectionAI (pCreature); +} + +void AddSC_boss_kiljaeden() +{ + Script* newscript; + + newscript = new Script; + newscript->pGOHello = &GOHello_go_orb_of_the_blue_flight; + newscript->Name = "go_orb_of_the_blue_flight"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_kalecgos_kj; + newscript->Name = "boss_kalecgos_kj"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_kiljaeden; + newscript->Name = "boss_kiljaeden"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_kiljaeden_controller; + newscript->Name = "mob_kiljaeden_controller"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_hand_of_the_deceiver; + newscript->Name = "mob_hand_of_the_deceiver"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_felfire_portal; + newscript->Name = "mob_felfire_portal"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_volatile_felfire_fiend; + newscript->Name = "mob_volatile_felfire_fiend"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_armageddon; + newscript->Name = "mob_armageddon"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_shield_orb; + newscript->Name = "mob_shield_orb"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_sinster_reflection; + newscript->Name = "mob_sinster_reflection"; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp new file mode 100644 index 00000000000..9dca453ade6 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp @@ -0,0 +1,640 @@ +/* Copyright (C) 2009 Trinity +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Muru +SD%Complete: 80 +SDComment: all sounds, black hole effect triggers to often (46228) +*/ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +// Muru & Entropius's spells +enum Spells +{ + SPELL_ENRAGE = 26662, + + // Muru's spells + SPELL_NEGATIVE_ENERGY = 46009, //(this trigger 46008) + SPELL_DARKNESS = 45999, + SPELL_OPEN_ALL_PORTALS = 46177, + SPELL_OPEN_PORTAL = 45977, + SPELL_OPEN_PORTAL_2 = 45976, + SPELL_SUMMON_BERSERKER = 46037, + SPELL_SUMNON_FURY_MAGE = 46038, + SPELL_SUMMON_VOID_SENTINEL = 45988, + SPELL_SUMMON_ENTROPIUS = 46217, + + // Entropius's spells + SPELL_DARKNESS_E = 46269, + SPELL_BLACKHOLE = 46282, + SPELL_NEGATIVE_ENERGY_E = 46284, + SPELL_ENTROPIUS_SPAWN = 46223, + + // Shadowsword Berserker's spells + SPELL_FLURRY = 46160, + SPELL_DUAL_WIELD = 29651, + + // Shadowsword Fury Mage's spells + SPELL_FEL_FIREBALL = 46101, + SPELL_SPELL_FURY = 46102, + + // Void Sentinel's spells + SPELL_SHADOW_PULSE = 46087, + SPELL_VOID_BLAST = 46161, + + // Void Spawn's spells + SPELL_SHADOW_BOLT_VOLLEY = 46082, + + //Dark Fiend Spells + SPELL_DARKFIEND_AOE = 45944, + SPELL_DARKFIEND_VISUAL = 45936, + SPELL_DARKFIEND_SKIN = 45934, + + //Black Hole Spells + SPELL_BLACKHOLE_SPAWN = 46242, + SPELL_BLACKHOLE_GROW = 46228 +}; + +enum BossTimers{ + TIMER_DARKNESS = 0, + TIMER_HUMANOIDES = 1, + TIMER_PHASE = 2, + TIMER_SENTINEL = 3 +}; + +float DarkFiends[8][4] = +{ + {1819.9, 609.80, 69.74, 1.94}, + {1829.39, 617.89, 69.73, 2.61}, + {1801.98, 633.62, 69.74, 5.71}, + {1830.88, 629.99, 69.73, 3.52}, + {1800.38, 621.41, 69.74, 0.22}, + {1808.3 , 612.45, 69.73, 1.02}, + {1823.9 , 639.69, 69.74, 4.12}, + {1811.85, 640.46, 69.73, 4.97} +}; + +float Humanoides[6][5] = +{ + {CREATURE_FURY_MAGE, 1780.16, 666.83, 71.19, 5.21}, + {CREATURE_FURY_MAGE, 1847.93, 600.30, 71.30, 2.57}, + {CREATURE_BERSERKER, 1779.97, 660.64, 71.19, 5.28}, + {CREATURE_BERSERKER, 1786.2 , 661.01, 71.19, 4.51}, + {CREATURE_BERSERKER, 1845.17, 602.63, 71.28, 2.43}, + {CREATURE_BERSERKER, 1842.91, 599.93, 71.23, 2.44} +}; + +uint32 EnrageTimer = 600000; +struct boss_entropiusAI : public ScriptedAI +{ + boss_entropiusAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + SummonList Summons; + + uint32 BlackHoleSummonTimer; + + void Reset() + { + BlackHoleSummonTimer = 15000; + DoCastAOE(SPELL_NEGATIVE_ENERGY_E, false); + + Summons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoCastAOE(SPELL_NEGATIVE_ENERGY_E, true); + DoCast(me, SPELL_ENTROPIUS_SPAWN, false); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + case CREATURE_DARK_FIENDS: + summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false); + break; + case CREATURE_DARKNESS: + summoned->addUnitState(UNIT_STAT_STUNNED); + float x,y,z,o; + summoned->GetHomePosition(x,y,z,o); + me->SummonCreature(CREATURE_DARK_FIENDS, x,y,z,o, TEMPSUMMON_CORPSE_DESPAWN, 0); + break; + } + summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); + Summons.Summon(summoned); + } + + void JustDied(Unit* /*killer*/) + { + Summons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (EnrageTimer < diff && !me->HasAura(SPELL_ENRAGE, 0)) + { + DoCast(me, SPELL_ENRAGE, false); + } else EnrageTimer -= diff; + + if (BlackHoleSummonTimer <= diff) + { + Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!random) + return; + + DoCast(random, SPELL_DARKNESS_E, false); + + random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!random) + return; + + random->CastSpell(random, SPELL_BLACKHOLE, false); + BlackHoleSummonTimer = 15000; + } else BlackHoleSummonTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_entropius(Creature* pCreature) +{ + return new boss_entropiusAI (pCreature); +} + +struct boss_muruAI : public Scripted_NoMovementAI +{ + boss_muruAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + SummonList Summons; + + uint8 Phase; + uint32 Timer[4]; + + bool DarkFiend; + + void Reset() + { + DarkFiend = false; + Phase = 1; + + EnrageTimer = 600000; + Timer[TIMER_DARKNESS] = 45000; + Timer[TIMER_HUMANOIDES] = 10000; + Timer[TIMER_PHASE] = 2000; + Timer[TIMER_SENTINEL] = 31500; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + Summons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoCastAOE(SPELL_NEGATIVE_ENERGY,false); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, IN_PROGRESS); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage > me->GetHealth() && Phase == 1) + { + damage = 0; + Phase = 2; + me->RemoveAllAuras(); + DoCast(me, SPELL_OPEN_ALL_PORTALS, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + if (Phase > 1 && Phase < 4) + damage = 0; + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + case BOSS_ENTROPIUS: + me->SetVisibility(VISIBILITY_OFF); + break; + case CREATURE_DARK_FIENDS: + summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false); + break; + } + summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); + Summons.Summon(summoned); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Phase == 3) + { + if (Timer[TIMER_PHASE] <= diff) + { + if (!pInstance) + return; + switch(pInstance->GetData(DATA_MURU_EVENT)) + { + case NOT_STARTED: + Reset(); + break; + case DONE: + Phase = 4; + me->DisappearAndDie(); + break; + } + Timer[TIMER_PHASE] = 3000; + } else Timer[TIMER_PHASE] -= diff; + return; + } + + if (EnrageTimer < diff && !me->HasAura(SPELL_ENRAGE, 0)) + { + DoCast(me, SPELL_ENRAGE, false); + } else EnrageTimer -= diff; + + for (uint8 i = 0; i < 4; ++i) + { + if (Timer[i] <= diff) + { + switch(i) + { + case TIMER_DARKNESS: + if (!DarkFiend) + { + DoCastAOE(SPELL_DARKNESS, false); + Timer[TIMER_DARKNESS] = 3000; + DarkFiend = true; + } + else + { + DarkFiend = false; + for (uint8 i = 0; i < 8; ++i) + me->SummonCreature(CREATURE_DARK_FIENDS,DarkFiends[i][0],DarkFiends[i][1],DarkFiends[i][2], DarkFiends[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + Timer[TIMER_DARKNESS] = 42000; + } + break; + case TIMER_HUMANOIDES: + for (uint8 i = 0; i < 6; ++i) + me->SummonCreature(Humanoides[i][0],Humanoides[i][1],Humanoides[i][2],Humanoides[i][3], Humanoides[i][4], TEMPSUMMON_CORPSE_DESPAWN, 0); + Timer[TIMER_HUMANOIDES] = 60000; + break; + case TIMER_PHASE: + me->RemoveAllAuras(); + DoCast(me, SPELL_SUMMON_ENTROPIUS, false); + Timer[TIMER_PHASE] = 3000; + Phase = 3; + return; + case TIMER_SENTINEL: + DoCastAOE(SPELL_OPEN_PORTAL_2, false); + Timer[TIMER_SENTINEL] = 30000; + break; + } + break; + } + } + + //Timer + for (uint8 i = 0; i < 4; ++i) + { + if (i != TIMER_PHASE)Timer[i] -= diff; + else if (Phase == 2) Timer[i] -= diff; + } + } +}; + +CreatureAI* GetAI_boss_muru(Creature* pCreature) +{ + return new boss_muruAI (pCreature); +} + +struct npc_muru_portalAI : public Scripted_NoMovementAI +{ + npc_muru_portalAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + SummonList Summons; + + bool SummonSentinel; + bool InAction; + + uint32 SummonTimer; + + void Reset() + { + SummonTimer = 5000; + + InAction = false; + SummonSentinel = false; + + me->addUnitState(UNIT_STAT_STUNNED); + + Summons.DespawnAll(); + } + + void JustSummoned(Creature* summoned) + { + if (pInstance) + if (Player* Target = Unit::GetPlayer(pInstance->GetData64(DATA_PLAYER_GUID))) + summoned->AI()->AttackStart(Target); + + Summons.Summon(summoned); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry* Spell) + { + float x,y,z,o; + me->GetHomePosition(x,y,z,o); + DoTeleportTo(x,y,z); + InAction = true; + switch(Spell->Id) + { + case SPELL_OPEN_ALL_PORTALS: + DoCastAOE(SPELL_OPEN_PORTAL, false); + break; + case SPELL_OPEN_PORTAL_2: + DoCastAOE(SPELL_OPEN_PORTAL, false); + SummonSentinel = true; + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!SummonSentinel) + { + if (InAction && pInstance && pInstance->GetData(DATA_MURU_EVENT) == NOT_STARTED) + Reset(); + return; + } + if (SummonTimer <= diff) + { + DoCastAOE(SPELL_SUMMON_VOID_SENTINEL, false); + SummonTimer = 5000; + SummonSentinel = false; + } else SummonTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_muru_portal(Creature* pCreature) +{ + return new npc_muru_portalAI (pCreature); +} + +struct npc_dark_fiendAI : public ScriptedAI +{ + npc_dark_fiendAI(Creature *c) : ScriptedAI(c) {} + + uint32 WaitTimer; + bool InAction; + + void Reset() + { + WaitTimer = 2000; + InAction = false; + + me->addUnitState(UNIT_STAT_STUNNED); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry* Spell) + { + for (uint8 i = 0; i < 3; ++i) + if (Spell->Effect[i] == 38) + me->DisappearAndDie(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (WaitTimer <= diff) + { + if (!InAction) + { + me->clearUnitState(UNIT_STAT_STUNNED); + DoCastAOE(SPELL_DARKFIEND_SKIN, false); + AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)); + InAction = true; + WaitTimer = 500; + } + else + { + + if (me->IsWithinDist(me->getVictim(), 5)) + { + DoCastAOE(SPELL_DARKFIEND_AOE, false); + me->DisappearAndDie(); + } + WaitTimer = 500; + } + } else WaitTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_dark_fiend(Creature* pCreature) +{ + return new npc_dark_fiendAI (pCreature); +} + +struct npc_void_sentinelAI : public ScriptedAI +{ + npc_void_sentinelAI(Creature *c) : ScriptedAI(c){} + + uint32 PulseTimer; + uint32 VoidBlastTimer; + + void Reset() + { + PulseTimer = 3000; + VoidBlastTimer = 45000; //is this a correct timer? + + float x,y,z,o; + me->GetHomePosition(x,y,z,o); + DoTeleportTo(x,y,71); + } + + void JustDied(Unit* /*killer*/) + { + for (uint8 i = 0; i < 8; ++i) + me->SummonCreature(CREATURE_VOID_SPAWN, me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(), rand()%6, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (PulseTimer <= diff) + { + DoCastAOE(SPELL_SHADOW_PULSE, true); + PulseTimer = 3000; + } else PulseTimer -= diff; + + if (VoidBlastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_VOID_BLAST, false); + VoidBlastTimer = 45000; + } else VoidBlastTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_void_sentinel(Creature* pCreature) +{ + return new npc_void_sentinelAI (pCreature); +} + +struct npc_blackholeAI : public ScriptedAI +{ + npc_blackholeAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 DespawnTimer; + uint32 SpellTimer; + uint8 Phase; + uint8 NeedForAHack; + + void Reset() + { + DespawnTimer = 15000; + SpellTimer = 5000; + Phase = 0; + + me->addUnitState(UNIT_STAT_STUNNED); + DoCastAOE(SPELL_BLACKHOLE_SPAWN, true); + } + + void UpdateAI(const uint32 diff) + { + if (SpellTimer <= diff) + { + Unit* Victim = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); + switch (NeedForAHack) + { + case 0: + me->clearUnitState(UNIT_STAT_STUNNED); + DoCastAOE(SPELL_BLACKHOLE_GROW, false); + if (Victim) + AttackStart(Victim); + SpellTimer = 700; + NeedForAHack = 2; + break; + case 1: + me->AddAura(SPELL_BLACKHOLE_GROW, me); + NeedForAHack = 2; + SpellTimer = 600; + break; + case 2: + SpellTimer = 400; + NeedForAHack = 3; + me->RemoveAura(SPELL_BLACKHOLE_GROW, 1); + break; + case 3: + SpellTimer = urand(400,900); + NeedForAHack = 1; + if (Unit* Temp = me->getVictim()) + { + if (Temp->GetPositionZ() > 73 && Victim) + AttackStart(Victim); + } else + return; + } + } else SpellTimer -= diff; + + if (DespawnTimer <= diff) + me->DisappearAndDie(); + else DespawnTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_blackhole(Creature* pCreature) +{ + return new npc_blackholeAI (pCreature); +} + +void AddSC_boss_muru() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_muru"; + newscript->GetAI = &GetAI_boss_muru; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_entropius"; + newscript->GetAI = &GetAI_boss_entropius; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_muru_portal"; + newscript->GetAI = &GetAI_npc_muru_portal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dark_fiend"; + newscript->GetAI = &GetAI_npc_dark_fiend; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_void_sentinel"; + newscript->GetAI = &GetAI_npc_void_sentinel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_blackhole"; + newscript->GetAI = &GetAI_npc_blackhole; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp new file mode 100644 index 00000000000..94b7bf4b735 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp @@ -0,0 +1,297 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +/* ScriptData +SDName: Instance_Sunwell_Plateau +SD%Complete: 25 +SDComment: VERIFY SCRIPT +SDCategory: Sunwell_Plateau +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +#define MAX_ENCOUNTER 6 + +/* Sunwell Plateau: +0 - Kalecgos and Sathrovarr +1 - Brutallus +2 - Felmyst +3 - Eredar Twins (Alythess and Sacrolash) +4 - M'uru +5 - Kil'Jaeden +*/ + +struct instance_sunwell_plateau : public ScriptedInstance +{ + instance_sunwell_plateau(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + /** Creatures **/ + uint64 Kalecgos_Dragon; + uint64 Kalecgos_Human; + uint64 Sathrovarr; + uint64 Brutallus; + uint64 Madrigosa; + uint64 Felmyst; + uint64 Alythess; + uint64 Sacrolash; + uint64 Muru; + uint64 KilJaeden; + uint64 KilJaedenController; + uint64 Anveena; + uint64 KalecgosKJ; + uint32 SpectralPlayers; + + /** GameObjects **/ + uint64 ForceField; // Kalecgos Encounter + uint64 KalecgosWall[2]; + uint64 FireBarrier; // Felmysts Encounter + uint64 MurusGate[2]; // Murus Encounter + + /*** Misc ***/ + uint32 SpectralRealmTimer; + std::vector SpectralRealmList; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + /*** Creatures ***/ + Kalecgos_Dragon = 0; + Kalecgos_Human = 0; + Sathrovarr = 0; + Brutallus = 0; + Madrigosa = 0; + Felmyst = 0; + Alythess = 0; + Sacrolash = 0; + Muru = 0; + KilJaeden = 0; + KilJaedenController = 0; + Anveena = 0; + KalecgosKJ = 0; + SpectralPlayers = 0; + + /*** GameObjects ***/ + ForceField = 0; + FireBarrier = 0; + MurusGate[0] = 0; + MurusGate[1] = 0; + KalecgosWall[0] = 0; + KalecgosWall[1] = 0; + + /*** Misc ***/ + SpectralRealmTimer = 5000; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* plr = itr->getSource(); + if (plr && !plr->HasAura(45839,0)) + return plr; + } + } + + debug_log("TSCR: Instance Sunwell Plateau: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 24850: Kalecgos_Dragon = pCreature->GetGUID(); break; + case 24891: Kalecgos_Human = pCreature->GetGUID(); break; + case 24892: Sathrovarr = pCreature->GetGUID(); break; + case 24882: Brutallus = pCreature->GetGUID(); break; + case 24895: Madrigosa = pCreature->GetGUID(); break; + case 25038: Felmyst = pCreature->GetGUID(); break; + case 25166: Alythess = pCreature->GetGUID(); break; + case 25165: Sacrolash = pCreature->GetGUID(); break; + case 25741: Muru = pCreature->GetGUID(); break; + case 25315: KilJaeden = pCreature->GetGUID(); break; + case 25608: KilJaedenController = pCreature->GetGUID(); break; + case 26046: Anveena = pCreature->GetGUID(); break; + case 25319: KalecgosKJ = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 188421: ForceField = pGo->GetGUID(); break; + case 188523: KalecgosWall[0] = pGo->GetGUID(); break; + case 188524: KalecgosWall[0] = pGo->GetGUID(); break; + case 188075: + if (m_auiEncounter[2] == DONE) + HandleGameObject(NULL, true, pGo); + FireBarrier = pGo->GetGUID(); + break; + case 187990: MurusGate[0] = pGo->GetGUID(); break; + case 188118: + if (m_auiEncounter[4] == DONE) + HandleGameObject(NULL, true, pGo); + MurusGate[1]= pGo->GetGUID(); + break; + } + } + + uint32 GetData(uint32 id) + { + switch(id) + { + case DATA_KALECGOS_EVENT: return m_auiEncounter[0]; + case DATA_BRUTALLUS_EVENT: return m_auiEncounter[1]; + case DATA_FELMYST_EVENT: return m_auiEncounter[2]; + case DATA_EREDAR_TWINS_EVENT: return m_auiEncounter[3]; + case DATA_MURU_EVENT: return m_auiEncounter[4]; + case DATA_KILJAEDEN_EVENT: return m_auiEncounter[5]; + } + return 0; + } + + uint64 GetData64(uint32 id) + { + switch(id) + { + case DATA_KALECGOS_DRAGON: return Kalecgos_Dragon; + case DATA_KALECGOS_HUMAN: return Kalecgos_Human; + case DATA_SATHROVARR: return Sathrovarr; + case DATA_GO_FORCEFIELD: return ForceField; + case DATA_BRUTALLUS: return Brutallus; + case DATA_MADRIGOSA: return Madrigosa; + case DATA_FELMYST: return Felmyst; + case DATA_ALYTHESS: return Alythess; + case DATA_SACROLASH: return Sacrolash; + case DATA_MURU: return Muru; + case DATA_KILJAEDEN: return KilJaeden; + case DATA_KILJAEDEN_CONTROLLER: return KilJaedenController; + case DATA_ANVEENA: return Anveena; + case DATA_KALECGOS_KJ: return KalecgosKJ; + case DATA_PLAYER_GUID: + Player* Target = GetPlayerInMap(); + return Target->GetGUID(); + } + return 0; + } + + void SetData(uint32 id, uint32 data) + { + switch(id) + { + case DATA_KALECGOS_EVENT: + { + if (data == NOT_STARTED || data == DONE) + { + HandleGameObject(ForceField,true); + HandleGameObject(KalecgosWall[0],true); + HandleGameObject(KalecgosWall[1],true); + } + else if (data == IN_PROGRESS) + { + HandleGameObject(ForceField,false); + HandleGameObject(KalecgosWall[0],false); + HandleGameObject(KalecgosWall[1],false); + } + m_auiEncounter[0] = data; + } + break; + case DATA_BRUTALLUS_EVENT: m_auiEncounter[1] = data; break; + case DATA_FELMYST_EVENT: + if (data == DONE) + HandleGameObject(FireBarrier, true); + m_auiEncounter[2] = data; break; + case DATA_EREDAR_TWINS_EVENT: m_auiEncounter[3] = data; break; + case DATA_MURU_EVENT: + switch(data) + { + case DONE: + HandleGameObject(MurusGate[0], true); + HandleGameObject(MurusGate[1], true); + break; + case IN_PROGRESS: + HandleGameObject(MurusGate[0], false); + HandleGameObject(MurusGate[1], false); + break; + case NOT_STARTED: + HandleGameObject(MurusGate[0], true); + HandleGameObject(MurusGate[1], false); + break; + } + m_auiEncounter[4] = data; break; + case DATA_KILJAEDEN_EVENT: m_auiEncounter[5] = data; break; + } + + if (data == DONE) + SaveToDB(); + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " + << m_auiEncounter[4] << " " << m_auiEncounter[5]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_sunwell_plateau(Map* pMap) +{ + return new instance_sunwell_plateau(pMap); +} + +void AddSC_instance_sunwell_plateau() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_sunwell_plateau"; + newscript->GetInstanceData = &GetInstanceData_instance_sunwell_plateau; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp new file mode 100644 index 00000000000..dbf67d5f26e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp @@ -0,0 +1,65 @@ +/* Copyright (C) 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Sunwell_Plateau +SD%Complete: 0 +SDComment: Placeholder, Epilogue after Kil'jaeden, Captain Selana Gossips +EndScriptData */ + +/* ContentData +npc_prophet_velen +npc_captain_selana +EndContentData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +/*###### +## npc_prophet_velen +######*/ + +enum ProphetSpeeches +{ + PROPHET_SAY1 = -1580099, + PROPHET_SAY2 = -1580100, + PROPHET_SAY3 = -1580101, + PROPHET_SAY4 = -1580102, + PROPHET_SAY5 = -1580103, + PROPHET_SAY6 = -1580104, + PROPHET_SAY7 = -1580105, + PROPHET_SAY8 = -1580106 +}; + +enum LiadrinnSpeeches +{ + LIADRIN_SAY1 = -1580107, + LIADRIN_SAY2 = -1580108, + LIADRIN_SAY3 = -1580109 +}; + +/*###### +## npc_captain_selana +######*/ + +#define CS_GOSSIP1 "Give me a situation report, Captain." +#define CS_GOSSIP2 "What went wrong?" +#define CS_GOSSIP3 "Why did they stop?" +#define CS_GOSSIP4 "Your insight is appreciated." + +void AddSC_sunwell_plateau() +{ +} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h new file mode 100644 index 00000000000..9f1a2480c96 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SUNWELLPLATEAU_H +#define DEF_SUNWELLPLATEAU_H + +/*** Encounters ***/ +enum Data +{ + DATA_KALECGOS_EVENT, + DATA_BRUTALLUS_EVENT, + DATA_FELMYST_EVENT, + DATA_EREDAR_TWINS_EVENT, + DATA_MURU_EVENT, + DATA_KILJAEDEN_EVENT, +}; + +enum Data64 +{ + /*** Creatures ***/ + DATA_KALECGOS_DRAGON, + DATA_KALECGOS_HUMAN, + DATA_SATHROVARR, + DATA_BRUTALLUS, + DATA_MADRIGOSA, + DATA_FELMYST, + DATA_ALYTHESS, + DATA_SACROLASH, + DATA_MURU, + DATA_KILJAEDEN, + DATA_KILJAEDEN_CONTROLLER, + DATA_ANVEENA, + DATA_KALECGOS_KJ, + + /*** GameObjects ***/ + DATA_GO_FORCEFIELD, + DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1, + DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2, + DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3, + DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4, + + /*** Misc ***/ + DATA_PLAYER_GUID, +}; + +enum Creatures +{ + BOSS_MURU = 25741, + BOSS_ENTROPIUS = 25840, + MOB_KALECGOS = 24850, + MOB_KALEC = 24891, + MOB_SATHROVARR = 24892, + + MOB_DEAD = 25268, + MOB_FLIGHT_LEFT = 25357, + MOB_FLIGHT_RIGHT = 25358, + MOB_DEATH_CLOUD = 25703, + MOB_VAPOR = 25265, + MOB_VAPOR_TRAIL = 25267, + + MOB_GRAND_WARLOCK_ALYTHESS = 25166, + MOB_SHADOW_IMAGE = 25214, + MOB_LADY_SACROLASH = 25165, + + CREATURE_ANVEENA = 26046, // Embodiment of the Sunwell + CREATURE_KALECGOS = 25319, // Helps the raid throughout the fight + CREATURE_PROPHET = 26246, // Outro + CREATURE_KILJAEDEN = 25315, // Give it to 'em KJ! + CREATURE_HAND_OF_THE_DECEIVER = 25588, // Adds found before KJ emerges + CREATURE_FELFIRE_PORTAL = 25603, // Portal spawned be Hand of the Deceivers + CREATURE_VOLATILE_FELFIRE_FIEND = 25598, // Fiends spawned by the above portal + CREATURE_ARMAGEDDON_TARGET = 25735, // This mob casts meteor on itself.. I think + CREATURE_SHIELD_ORB = 25502, // Shield orbs circle the room raining shadow bolts on raid + CREATURE_THE_CORE_OF_ENTROPIUS = 26262, // Used in the ending cinematic? + CREATURE_POWER_OF_THE_BLUE_DRAGONFLIGHT = 25653, // NPC that players possess when using the Orb of the Blue Dragonflight + CREATURE_SPIKE_TARGET1 = 30598, // Should summon these under Shadow Spike Channel on targets place + CREATURE_SPIKE_TARGET2 = 30614, + CREATURE_SINISTER_REFLECTION = 25708, // Sinister Relection spawnd on Phase swichtes + + CREATURE_DARKNESS = 25879, + CREATURE_DARK_FIENDS = 25744, + CREATURE_BERSERKER = 25798, + CREATURE_FURY_MAGE = 25799, + CREATURE_VOID_SENTINEL = 25772, + CREATURE_VOID_SPAWN = 25824, + CREATURE_BLACK_HOLE = 25855, +}; + +enum GameObjects +{ + GAMEOBJECT_ORB_OF_THE_BLUE_DRAGONFLIGHT = 188415, +}; + +#endif diff --git a/src/server/scripts/EasternKingdoms/tirisfal_glades.cpp b/src/server/scripts/EasternKingdoms/tirisfal_glades.cpp new file mode 100644 index 00000000000..8b6d73df704 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/tirisfal_glades.cpp @@ -0,0 +1,208 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Tirisfal_Glades +SD%Complete: 100 +SDComment: Quest support: 590, 1819 +SDCategory: Tirisfal Glades +EndScriptData */ + +/* ContentData +npc_calvin_montague +go_mausoleum_door +go_mausoleum_trigger +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_calvin_montague +######*/ + +enum eCalvin +{ + SAY_COMPLETE = -1000431, + SPELL_DRINK = 2639, // possibly not correct spell (but iconId is correct) + QUEST_590 = 590, + FACTION_HOSTILE = 168 +}; + +struct npc_calvin_montagueAI : public ScriptedAI +{ + npc_calvin_montagueAI(Creature* pCreature) : ScriptedAI(pCreature) { } + + uint32 m_uiPhase; + uint32 m_uiPhaseTimer; + uint64 m_uiPlayerGUID; + + void Reset() + { + m_uiPhase = 0; + m_uiPhaseTimer = 5000; + m_uiPlayerGUID = 0; + + me->RestoreFaction(); + + if (!me->HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE)) + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + void EnterCombat(Unit* /*who*/) {} + + void AttackedBy(Unit* pAttacker) + { + if (me->getVictim() || me->IsFriendlyTo(pAttacker)) + return; + + AttackStart(pAttacker); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > me->GetHealth() || ((me->GetHealth() - uiDamage)*100 / me->GetMaxHealth() < 15)) + { + uiDamage = 0; + + me->RestoreFaction(); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->CombatStop(true); + + m_uiPhase = 1; + + if (pDoneBy->GetTypeId() == TYPEID_PLAYER) + m_uiPlayerGUID = pDoneBy->GetGUID(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiPhase) + { + if (m_uiPhaseTimer <= uiDiff) + m_uiPhaseTimer = 7500; + else + { + m_uiPhaseTimer -= uiDiff; + return; + } + + switch(m_uiPhase) + { + case 1: + DoScriptText(SAY_COMPLETE, me); + ++m_uiPhase; + break; + case 2: + if (Player *pPlayer = Unit::GetPlayer(m_uiPlayerGUID)) + pPlayer->AreaExploredOrEventHappens(QUEST_590); + + DoCast(me, SPELL_DRINK, true); + ++m_uiPhase; + break; + case 3: + EnterEvadeMode(); + break; + } + + return; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_calvin_montague(Creature* pCreature) +{ + return new npc_calvin_montagueAI (pCreature); +} + +bool QuestAccept_npc_calvin_montague(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_590) + { + pCreature->setFaction(FACTION_HOSTILE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + CAST_AI(npc_calvin_montagueAI, pCreature->AI())->AttackStart(pPlayer); + } + return true; +} + +/*###### +## go_mausoleum_door +## go_mausoleum_trigger +######*/ + +enum eMausoleum +{ + QUEST_ULAG = 1819, + NPC_ULAG = 6390, + GO_TRIGGER = 104593, + GO_DOOR = 176594 +}; + +bool GOHello_go_mausoleum_door(Player* pPlayer, GameObject* /*pGo*/) +{ + if (pPlayer->GetQuestStatus(QUEST_ULAG) != QUEST_STATUS_INCOMPLETE) + return false; + + if (GameObject* pTrigger = pPlayer->FindNearestGameObject(GO_TRIGGER, 30.0f)) + { + pTrigger->SetGoState(GO_STATE_READY); + pPlayer->SummonCreature(NPC_ULAG, 2390.26, 336.47, 40.01, 2.26, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000); + return false; + } + + return false; +} + +bool GOHello_go_mausoleum_trigger(Player* pPlayer, GameObject* pGo) +{ + if (pPlayer->GetQuestStatus(QUEST_ULAG) != QUEST_STATUS_INCOMPLETE) + return false; + + if (GameObject* pDoor = pPlayer->FindNearestGameObject(GO_DOOR, 30.0f)) + { + pGo->SetGoState(GO_STATE_ACTIVE); + pDoor->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + return true; + } + + return false; +} + +void AddSC_tirisfal_glades() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_calvin_montague"; + newscript->GetAI = &GetAI_npc_calvin_montague; + newscript->pQuestAccept = &QuestAccept_npc_calvin_montague; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_mausoleum_door"; + newscript->pGOHello = &GOHello_go_mausoleum_door; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_mausoleum_trigger"; + newscript->pGOHello = &GOHello_go_mausoleum_trigger; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp new file mode 100644 index 00000000000..cd3bc5fc219 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp @@ -0,0 +1,497 @@ +/* Copyright (C) 2006,2007 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_archaedas +SD%Complete: 100 +SDComment: Archaedas is activated when 1 person (was 3, changed in 3.0.8) clicks on his altar. +Every 10 seconds he will awaken one of his minions along the wall. +At 66%, he will awaken the 6 Guardians. +At 33%, he will awaken the Vault Walkers +On his death the vault door opens. +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO "Who dares awaken Archaedas? Who dares the wrath of the makers!" +#define SOUND_AGGRO 5855 + +#define SAY_SUMMON "Awake ye servants, defend the discs!" +#define SOUND_SUMMON 5856 + +#define SAY_SUMMON2 "To my side, brothers. For the makers!" +#define SOUND_SUMMON2 5857 + +#define SAY_KILL "Reckless mortal." +#define SOUND_KILL 5858 + +#define SPELL_GROUND_TREMOR 6524 +#define SPELL_ARCHAEDAS_AWAKEN 10347 +#define SPELL_BOSS_OBJECT_VISUAL 11206 +#define SPELL_BOSS_AGGRO 10340 +#define SPELL_SUB_BOSS_AGGRO 11568 +#define SPELL_AWAKEN_VAULT_WALKER 10258 +#define SPELL_AWAKEN_EARTHEN_GUARDIAN 10252 + +struct boss_archaedasAI : public ScriptedAI +{ + boss_archaedasAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + uint32 Tremor_Timer; + int32 Awaken_Timer; + uint32 WallMinionTimer; + bool wakingUp; + + bool guardiansAwake; + bool vaultWalkersAwake; + ScriptedInstance* pInstance; + + void Reset() + { + Tremor_Timer = 60000; + Awaken_Timer = 0; + WallMinionTimer = 10000; + + wakingUp = false; + guardiansAwake = false; + vaultWalkersAwake = false; + + if (pInstance) + pInstance->SetData (NULL, 5); // respawn any dead minions + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + } + + void ActivateMinion (uint64 guid, bool flag) + { + Unit *minion = Unit::GetUnit(*me, guid); + + if (minion && minion->isAlive()) + { + DoCast (minion, SPELL_AWAKEN_VAULT_WALKER, flag); + minion->CastSpell(minion, SPELL_ARCHAEDAS_AWAKEN,true); + } + } + + void EnterCombat(Unit * /*who*/) + { + me->setFaction (14); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); + } + + void SpellHit (Unit* /*caster*/, const SpellEntry *spell) + { + // Being woken up from the altar, start the awaken sequence + if (spell == GetSpellStore()->LookupEntry(SPELL_ARCHAEDAS_AWAKEN)) { + me->MonsterYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_AGGRO); + Awaken_Timer = 4000; + wakingUp = true; + } + } + + void KilledUnit(Unit * /*victim*/) + { + me->MonsterYell(SAY_KILL,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + // we're still doing awaken animation + if (wakingUp && Awaken_Timer >= 0) { + Awaken_Timer -= diff; + return; // dont do anything until we are done + } else if (wakingUp && Awaken_Timer <= 0) { + wakingUp = false; + AttackStart(Unit::GetUnit(*me, pInstance->GetData64(0))); + return; // dont want to continue until we finish the AttackStart method + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + // wake a wall minion + if (WallMinionTimer <= diff) { + pInstance->SetData (NULL, 2); + + WallMinionTimer = 10000; + } else WallMinionTimer -= diff; + + //If we are <66 summon the guardians + if (!guardiansAwake && me->GetHealth()*100 / me->GetMaxHealth() <= 66) { + ActivateMinion(pInstance->GetData64(5),true); // EarthenGuardian1 + ActivateMinion(pInstance->GetData64(6),true); // EarthenGuardian2 + ActivateMinion(pInstance->GetData64(7),true); // EarthenGuardian3 + ActivateMinion(pInstance->GetData64(8),true); // EarthenGuardian4 + ActivateMinion(pInstance->GetData64(9),true); // EarthenGuardian5 + ActivateMinion(pInstance->GetData64(10),false); // EarthenGuardian6 + me->MonsterYell(SAY_SUMMON,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_SUMMON); + guardiansAwake = true; + } + + //If we are <33 summon the vault walkers + if (!vaultWalkersAwake && me->GetHealth()*100 / me->GetMaxHealth() <= 33) { + ActivateMinion(pInstance->GetData64(1),true); // VaultWalker1 + ActivateMinion(pInstance->GetData64(2),true); // VaultWalker2 + ActivateMinion(pInstance->GetData64(3),true); // VaultWalker3 + ActivateMinion(pInstance->GetData64(4),false); // VaultWalker4 + me->MonsterYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_SUMMON2); + vaultWalkersAwake = true; + } + + if (Tremor_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_GROUND_TREMOR); + + //45 seconds until we should cast this agian + Tremor_Timer = 45000; + } else Tremor_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied (Unit * /*killer*/) { + if (pInstance) + { + pInstance->SetData(NULL,3); // open the vault door + pInstance->SetData(NULL,4); // deactivate his minions + } + } + +}; + +CreatureAI* GetAI_boss_archaedas(Creature* pCreature) +{ + return new boss_archaedasAI (pCreature); +} + +/* ScriptData +SDName: mob_archaedas_minions +SD%Complete: 100 +SDComment: These mobs are initially frozen until Archaedas awakens them +one at a time. +EndScriptData */ + +#define SPELL_ARCHAEDAS_AWAKEN 10347 + +struct mob_archaedas_minionsAI : public ScriptedAI +{ + mob_archaedas_minionsAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + uint32 Arcing_Timer; + int32 Awaken_Timer; + bool wakingUp; + + bool amIAwake; + ScriptedInstance* pInstance; + + void Reset() + { + Arcing_Timer = 3000; + Awaken_Timer = 0; + + wakingUp = false; + amIAwake = false; + + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveAllAuras(); + } + + void EnterCombat(Unit * /*who*/) + { + me->setFaction (14); + me->RemoveAllAuras(); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + amIAwake = true; + } + + void SpellHit (Unit* /*caster*/, const SpellEntry *spell) { + // time to wake up, start animation + if (spell == GetSpellStore()->LookupEntry(SPELL_ARCHAEDAS_AWAKEN)){ + Awaken_Timer = 5000; + wakingUp = true; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (amIAwake) + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + // we're still in the awaken animation + if (wakingUp && Awaken_Timer >= 0) { + Awaken_Timer -= diff; + return; // dont do anything until we are done + } else if (wakingUp && Awaken_Timer <= 0) { + wakingUp = false; + amIAwake = true; + // AttackStart(Unit::GetUnit(*me, pInstance->GetData64(0))); // whoWokeArchaedasGUID + return; // dont want to continue until we finish the AttackStart method + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_archaedas_minions(Creature* pCreature) +{ + return new mob_archaedas_minionsAI (pCreature); +} + +/* ScriptData +SDName: go_altar_archaedas +SD%Complete: 100 +SDComment: Needs 1 person to activate the Archaedas script +SDCategory: Uldaman +EndScriptData */ + +#define OBJECT_ALTAR_OF_ARCHAEDAS 133234 + +#define NUMBER_NEEDED_TO_ACTIVATE 1 // as of patch 3.0.8 the altars can be opened by a single player (previously 3) + +#define SPELL_BOSS_OBJECT_VISUAL 11206 + +//uint64 altarOfArchaedasCount[5]; +//int32 altarOfArchaedasCounter=0; + +bool GOHello_go_altar_of_archaedas(Player* pPlayer, GameObject* /*pGo*/) +{ + //bool alreadyUsed; + //pGo->AddUse (); + + /* + alreadyUsed = false; + for (uint32 loop=0; loop<5; loop++) { + if (altarOfArchaedasCount[loop] == pPlayer->GetGUID()) alreadyUsed = true; + } + if (!alreadyUsed) + altarOfArchaedasCount[altarOfArchaedasCounter++] = pPlayer->GetGUID(); + */ + + pPlayer->CastSpell (pPlayer, SPELL_BOSS_OBJECT_VISUAL, false); + + /* + if (altarOfArchaedasCounter < NUMBER_NEEDED_TO_ACTIVATE) + return false; // not enough people yet + + // Check to make sure at least three people are still casting + uint8 count = 0; + Unit *pTarget; + for (uint8 x = 0; x <= 5; ++x) + { + pTarget = Unit::GetUnit(*pPlayer, altarOfArchaedasCount[x]); + if (!pTarget) + continue; + if (pTarget->IsNonMeleeSpellCasted(true)) + ++count; + if (count >= NUMBER_NEEDED_TO_ACTIVATE) + break; + } + + if (count < NUMBER_NEEDED_TO_ACTIVATE) + return false; // not enough people + */ + + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (!pInstance) + return false; + + pInstance->SetData(NULL,0); + pInstance->SetData64(0,pPlayer->GetGUID()); // activate archaedas + + return false; +} + +/* ScriptData +SDName: mob_stonekeepers +SD%Complete: 100 +SDComment: After activating the altar of the keepers, the stone keepers will +wake up one by one. +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SELF_DESTRUCT 9874 + +struct mob_stonekeepersAI : public ScriptedAI +{ + mob_stonekeepersAI(Creature *c) : ScriptedAI(c) + { + pInstance = (me->GetInstanceData()); + } + + ScriptedInstance* pInstance; + + void Reset() + { + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveAllAuras(); + } + + void EnterCombat(Unit * /*who*/) + { + me->setFaction (14); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + + void UpdateAI(const uint32 /*diff*/) + { + + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit * /*attacker*/) + { + DoCast (me, SPELL_SELF_DESTRUCT,true); + if (pInstance) + pInstance->SetData(NULL, 1); // activate next stonekeeper + } + +}; + +CreatureAI* GetAI_mob_stonekeepers(Creature* pCreature) +{ + return new mob_stonekeepersAI (pCreature); +} + +/* ScriptData +SDName: go_altar_of_the_keepers +SD%Complete: 100 +SDComment: Need 1 person to activate to open the altar. One by one the StoneKeepers will activate. After all four are dead than the door will open. +SDCategory: Uldaman +EndScriptData */ + +#define SPELL_BOSS_OBJECT_VISUAL 11206 + +#define NUMBER_NEEDED_TO_ACTIVATE 1 // as of patch 3.0.8 the altars can be opened by a single player (previously 3) + +//static uint64 altarOfTheKeeperCount[5]; +//static uint32 altarOfTheKeeperCounter=0; + +bool GOHello_go_altar_of_the_keepers(Player* pPlayer, GameObject* /*pGo*/) +{ + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (!pInstance) + return true; + + //bool alreadyUsed; + + //pGo->AddUse(); + + //alreadyUsed = false; + //for (uint32 loop=0; loop<5; ++loop) + //{ + // if (altarOfTheKeeperCount[loop] == pPlayer->GetGUID()) + //alreadyUsed = true; + //} + //if (!alreadyUsed && altarOfTheKeeperCounter < 5) + // altarOfTheKeeperCount[altarOfTheKeeperCounter++] = pPlayer->GetGUID(); + pPlayer->CastSpell (pPlayer, SPELL_BOSS_OBJECT_VISUAL, false); + + //if (altarOfTheKeeperCounter < NUMBER_NEEDED_TO_ACTIVATE) + //{ + //error_log("not enough people yet, altarOfTheKeeperCounter = %d", altarOfTheKeeperCounter); + // return false; // not enough people yet + //} +/* + // Check to make sure at least three people are still casting + uint8 count = 0; + Unit *pTarget; + for (uint8 x = 0; x < 5; ++x) + { + pTarget = Unit::GetUnit(*pPlayer, altarOfTheKeeperCount[x]); + //error_log("number of people currently activating it: %d", x+1); + if (!pTarget) + continue; + if (pTarget->IsNonMeleeSpellCasted(true)) + ++count; + if (count >= NUMBER_NEEDED_TO_ACTIVATE) + break; + } + + if (count < NUMBER_NEEDED_TO_ACTIVATE) + { + //error_log("still not enough people"); + return true; // not enough people + } +*/ + //error_log ("activating stone keepers"); + pInstance->SetData(NULL,1); // activate the Stone Keepers + return true; +} + +void AddSC_boss_archaedas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_archaedas"; + newscript->GetAI = &GetAI_boss_archaedas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_altar_of_archaedas"; + newscript->pGOHello = &GOHello_go_altar_of_archaedas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_archaedas_minions"; + newscript->GetAI = &GetAI_mob_archaedas_minions; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_altar_of_the_keepers"; + newscript->pGOHello = &GOHello_go_altar_of_the_keepers; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stonekeepers"; + newscript->GetAI = &GetAI_mob_stonekeepers; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp b/src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp new file mode 100644 index 00000000000..9b6d5dba642 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp @@ -0,0 +1,106 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ironaya +SD%Complete: 100 +SDComment: +SDCategory: Uldaman +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1070000 + +#define SPELL_ARCINGSMASH 8374 +#define SPELL_KNOCKAWAY 10101 +#define SPELL_WSTOMP 11876 + +struct boss_ironayaAI : public ScriptedAI +{ + boss_ironayaAI(Creature *c) : ScriptedAI(c) {} + + uint32 Arcing_Timer; + bool hasCastedWstomp; + bool hasCastedKnockaway; + + void Reset() + { + Arcing_Timer = 3000; + hasCastedKnockaway = false; + hasCastedWstomp = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //If we are <50% hp do knockaway ONCE + if (!hasCastedKnockaway && me->GetHealth()*2 < me->GetMaxHealth()) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); + + // current aggro target is knocked away pick new target + Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!Target || Target == me->getVictim()) + Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + + if (Target) + me->TauntApply(Target); + + //Shouldn't cast this agian + hasCastedKnockaway = true; + } + + //Arcing_Timer + if (Arcing_Timer <= diff) + { + DoCast(me, SPELL_ARCINGSMASH); + Arcing_Timer = 13000; + } else Arcing_Timer -= diff; + + if (!hasCastedWstomp && me->GetHealth()*4 < me->GetMaxHealth()) + { + DoCast(me, SPELL_WSTOMP); + hasCastedWstomp = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ironaya(Creature* pCreature) +{ + return new boss_ironayaAI (pCreature); +} + +void AddSC_boss_ironaya() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ironaya"; + newscript->GetAI = &GetAI_boss_ironaya; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp b/src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp new file mode 100644 index 00000000000..a519ad678b7 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp @@ -0,0 +1,300 @@ +/* Copyright (C) 2006,2007 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +#define SPELL_ARCHAEDAS_AWAKEN 10347 +#define SPELL_AWAKEN_VAULT_WALKER 10258 + +#define ARCHAEDAS_TEMPLE_DOOR 141869 +#define ALTAR_OF_ARCHAEDAS 133234 + +#define ALTAR_OF_THE_KEEPER_TEMPLE_DOOR 124367 +#define ALTAR_OF_THE_KEEPER_TEMPLE 130511 + +#define ANCIENT_VAULT_DOOR 124369 + +struct instance_uldaman : public ScriptedInstance +{ + instance_uldaman(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + }; + + void Initialize() + { + archaedasGUID = 0; + altarOfTheKeeperTempleDoor = 0; + archaedasTempleDoor = 0; + ancientVaultDoor = 0; + whoWokeArchaedasGUID = 0; + } + + uint64 archaedasGUID; + uint64 altarOfTheKeeperTempleDoor; + uint64 archaedasTempleDoor; + uint64 ancientVaultDoor; + uint64 whoWokeArchaedasGUID; + + std::vector stoneKeeper; + std::vector altarOfTheKeeperCount; + std::vector vaultWalker; + std::vector earthenGuardian; + std::vector archaedasWallMinions; // minions lined up around the wall + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch (pGo->GetEntry()) + { + case ALTAR_OF_THE_KEEPER_TEMPLE_DOOR: // lock the door + altarOfTheKeeperTempleDoor = pGo->GetGUID(); + break; + + case ARCHAEDAS_TEMPLE_DOOR: + archaedasTempleDoor = pGo->GetGUID(); + break; + + case ANCIENT_VAULT_DOOR: + pGo->SetGoState(GO_STATE_READY); + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33); + ancientVaultDoor = pGo->GetGUID(); + break; + } + } + + void SetFrozenState(Creature* pCreature) + { + pCreature->setFaction(35); + pCreature->RemoveAllAuras(); + //creature->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_ANIMATION_FROZEN); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + + void OpenDoor(uint64 guid) + { + GameObject* pGo = instance->GetGameObject(guid); + if (!pGo) + return; + + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33); + pGo->SetGoState(GO_STATE_ACTIVE); + } + + void ActivateStoneKeepers() + { + for (std::vector::const_iterator i = stoneKeeper.begin(); i != stoneKeeper.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || !pTarget->isAlive() || pTarget->getFaction() == 14) + continue; + pTarget->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); + pTarget->setFaction(14); + pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + return; // only want the first one we find + } + // if we get this far than all four are dead so open the door + SetData (NULL, 0); + } + + void ActivateWallMinions() + { + Creature *archaedas = instance->GetCreature(archaedasGUID); + if (!archaedas) + return; + + for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || !pTarget->isAlive() || pTarget->getFaction() == 14) + continue; + archaedas->CastSpell(pTarget, SPELL_AWAKEN_VAULT_WALKER, true); + pTarget->CastSpell(pTarget, SPELL_ARCHAEDAS_AWAKEN,true); + return; // only want the first one we find + } + } + + // used when Archaedas dies. All active minions must be despawned. + void DeActivateMinions() + { + // first despawn any aggroed wall minions + for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) + continue; + pTarget->setDeathState(JUST_DIED); + pTarget->RemoveCorpse(); + } + + // Vault Walkers + for (std::vector::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) + continue; + pTarget->setDeathState(JUST_DIED); + pTarget->RemoveCorpse(); + } + + // Earthen Guardians + for (std::vector::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) + continue; + pTarget->setDeathState(JUST_DIED); + pTarget->RemoveCorpse(); + } + } + + void ActivateArchaedas(uint64 target) + { + Creature *archaedas = instance->GetCreature(archaedasGUID); + if (!archaedas) + return; + + if (Unit *victim = Unit::GetUnit(*archaedas, target)) + { + archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN,false); + whoWokeArchaedasGUID = target; + } + } + + void RespawnMinions() + { + // first respawn any aggroed wall minions + for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (pTarget && pTarget->isDead()) + { + pTarget->Respawn(); + pTarget->GetMotionMaster()->MoveTargetedHome(); + SetFrozenState(pTarget); + } + } + + // Vault Walkers + for (std::vector::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (pTarget && pTarget->isDead()) + { + pTarget->Respawn(); + pTarget->GetMotionMaster()->MoveTargetedHome(); + SetFrozenState(pTarget); + } + } + + // Earthen Guardians + for (std::vector::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (pTarget && pTarget->isDead()) + { + pTarget->Respawn(); + pTarget->GetMotionMaster()->MoveTargetedHome(); + SetFrozenState(pTarget); + } + } + } + + void SetData (uint32 /*type*/, uint32 data) + { + //error_log ("SetData: data = %d", data); + if (data == 0) OpenDoor (altarOfTheKeeperTempleDoor); + if (data == 0) OpenDoor (archaedasTempleDoor); + if (data == 3) OpenDoor (ancientVaultDoor); + if (data == 1) ActivateStoneKeepers(); + if (data == 2) ActivateWallMinions(); + if (data == 4) DeActivateMinions(); + if (data == 5) RespawnMinions(); + } + + void SetData64 (uint32 type, uint64 data) + { + // Archaedas + if (type == 0) + { + ActivateArchaedas (data); + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) { + case 4857: // Stone Keeper + SetFrozenState (pCreature); + stoneKeeper.push_back(pCreature->GetGUID()); + break; + + case 7309: // Earthen Custodian + archaedasWallMinions.push_back(pCreature->GetGUID()); + break; + + case 7077: // Earthen Hallshaper + archaedasWallMinions.push_back(pCreature->GetGUID()); + break; + + case 7076: // Earthen Guardian + earthenGuardian.push_back(pCreature->GetGUID()); + break; + + case 10120: // Vault Walker + vaultWalker.push_back(pCreature->GetGUID()); + break; + + case 2748: // Archaedas + archaedasGUID = pCreature->GetGUID(); + break; + + } // end switch + } // end OnCreatureCreate + + uint64 GetData64 (uint32 identifier) + { + if (identifier == 0) return whoWokeArchaedasGUID; + if (identifier == 1) return vaultWalker[0]; // VaultWalker1 + if (identifier == 2) return vaultWalker[1]; // VaultWalker2 + if (identifier == 3) return vaultWalker[2]; // VaultWalker3 + if (identifier == 4) return vaultWalker[3]; // VaultWalker4 + + if (identifier == 5) return earthenGuardian[0]; + if (identifier == 6) return earthenGuardian[1]; + if (identifier == 7) return earthenGuardian[2]; + if (identifier == 8) return earthenGuardian[3]; + if (identifier == 9) return earthenGuardian[4]; + if (identifier == 10) return earthenGuardian[5]; + + return 0; + } // end GetData64 +}; + +InstanceData* GetInstanceData_instance_uldaman(Map* pMap) +{ + return new instance_uldaman(pMap); +} + +void AddSC_instance_uldaman() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_uldaman"; + newscript->GetInstanceData = &GetInstanceData_instance_uldaman; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp b/src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp new file mode 100644 index 00000000000..2bd8387efa5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Uldaman +SD%Complete: 100 +SDComment: Quest support: 2278 + 1 trash mob. +SDCategory: Uldaman +EndScriptData */ + +/* ContentData +mob_jadespine_basilisk +npc_lore_keeper_of_norgannon +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## mob_jadespine_basilisk +######*/ + +#define SPELL_CSLUMBER 3636 + +struct mob_jadespine_basiliskAI : public ScriptedAI +{ + mob_jadespine_basiliskAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cslumber_Timer; + + void Reset() + { + Cslumber_Timer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Cslumber_Timer + if (Cslumber_Timer <= diff) + { + //Cast + // DoCast(me->getVictim(), SPELL_CSLUMBER); + DoCast(me->getVictim(), SPELL_CSLUMBER, true); + + //Stop attacking target thast asleep and pick new target + Cslumber_Timer = 28000; + + Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!Target || Target == me->getVictim()) + Target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + + if (Target) + me->TauntApply(Target); + + } else Cslumber_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_jadespine_basilisk(Creature* pCreature) +{ + return new mob_jadespine_basiliskAI (pCreature); +} + +/*###### +## npc_lore_keeper_of_norgannon +######*/ + +#define GOSSIP_HELLO_KEEPER "Who are the Earthen?" +#define GOSSIP_SELECT_KEEPER1 "What is a \"subterranean being matrix\"?" +#define GOSSIP_SELECT_KEEPER2 "What are the anomalies you speak of?" +#define GOSSIP_SELECT_KEEPER3 "What is a resilient foundation of construction?" +#define GOSSIP_SELECT_KEEPER4 "So... the Earthen were made out of stone?" +#define GOSSIP_SELECT_KEEPER5 "Anything else I should know about the Earthen?" +#define GOSSIP_SELECT_KEEPER6 "I think I understand the Creators' design intent for the Earthen now. What are the Earthen's anomalies that you spoke of earlier?" +#define GOSSIP_SELECT_KEEPER7 "What high-stress environments would cause the Earthen to destabilize?" +#define GOSSIP_SELECT_KEEPER8 "What happens when the Earthen destabilize?" +#define GOSSIP_SELECT_KEEPER9 "Troggs?! Are the troggs you mention the same as the ones in the world today?" +#define GOSSIP_SELECT_KEEPER10 "You mentioned two results when the Earthen destabilize. What is the second?" +#define GOSSIP_SELECT_KEEPER11 "Dwarves!!! Now you're telling me that dwarves originally came from the Earthen?!" +#define GOSSIP_SELECT_KEEPER12 "These dwarves are the same ones today, yes? Do the dwarves maintain any other links to the Earthen?" +#define GOSSIP_SELECT_KEEPER13 "Who are the Creators?" +#define GOSSIP_SELECT_KEEPER14 "This is a lot to think about." +#define GOSSIP_SELECT_KEEPER15 "I will access the discs now." + +bool GossipHello_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(2278) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KEEPER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(1079, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(1080, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(1081, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(1082, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(1083, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(1084, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + pPlayer->SEND_GOSSIP_MENU(1085, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); + pPlayer->SEND_GOSSIP_MENU(1086, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+8: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); + pPlayer->SEND_GOSSIP_MENU(1087, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+9: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); + pPlayer->SEND_GOSSIP_MENU(1088, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+10: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+11); + pPlayer->SEND_GOSSIP_MENU(1089, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+12); + pPlayer->SEND_GOSSIP_MENU(1090, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+12: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+13); + pPlayer->SEND_GOSSIP_MENU(1091, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+13: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+14); + pPlayer->SEND_GOSSIP_MENU(1092, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+14: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+15); + pPlayer->SEND_GOSSIP_MENU(1093, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+15: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+16); + pPlayer->SEND_GOSSIP_MENU(1094, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+16: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(2278); + break; + } + return true; +} + +void AddSC_uldaman() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_jadespine_basilisk"; + newscript->GetAI = &GetAI_mob_jadespine_basilisk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lore_keeper_of_norgannon"; + newscript->pGossipHello = &GossipHello_npc_lore_keeper_of_norgannon; + newscript->pGossipSelect = &GossipSelect_npc_lore_keeper_of_norgannon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/undercity.cpp b/src/server/scripts/EasternKingdoms/undercity.cpp new file mode 100644 index 00000000000..22eb3241874 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/undercity.cpp @@ -0,0 +1,252 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Undercity +SD%Complete: 95 +SDComment: Quest support: 6628, 9180(post-event). +SDCategory: Undercity +EndScriptData */ + +/* ContentData +npc_lady_sylvanas_windrunner +npc_highborne_lamenter +npc_parqual_fintallas +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_lady_sylvanas_windrunner +######*/ + +#define SAY_LAMENT_END -1000196 +#define EMOTE_LAMENT_END -1000197 + +#define SOUND_CREDIT 10896 +#define ENTRY_HIGHBORNE_LAMENTER 21628 +#define ENTRY_HIGHBORNE_BUNNY 21641 + +#define SPELL_HIGHBORNE_AURA 37090 +#define SPELL_SYLVANAS_CAST 36568 +#define SPELL_RIBBON_OF_SOULS 34432 //the real one to use might be 37099 + +float HighborneLoc[4][3]= +{ + {1285.41, 312.47, 0.51}, + {1286.96, 310.40, 1.00}, + {1289.66, 309.66, 1.52}, + {1292.51, 310.50, 1.99}, +}; + +#define HIGHBORNE_LOC_Y -61.00 +#define HIGHBORNE_LOC_Y_NEW -55.50 + +struct npc_lady_sylvanas_windrunnerAI : public ScriptedAI +{ + npc_lady_sylvanas_windrunnerAI(Creature *c) : ScriptedAI(c) {} + + uint32 LamentEvent_Timer; + bool LamentEvent; + uint64 targetGUID; + + void Reset() + { + LamentEvent_Timer = 5000; + LamentEvent = false; + targetGUID = 0; + } + + void EnterCombat(Unit * /*who*/) {} + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == ENTRY_HIGHBORNE_BUNNY) + { + if (Unit *pTarget = Unit::GetUnit(*summoned,targetGUID)) + { + pTarget->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), me->GetPositionZ()+15.0,0); + pTarget->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), me->GetPositionZ()+15.0, 0.0f); + summoned->CastSpell(pTarget, SPELL_RIBBON_OF_SOULS, false); + } + + summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + targetGUID = summoned->GetGUID(); + } + } + + void UpdateAI(const uint32 diff) + { + if (LamentEvent) + { + if (LamentEvent_Timer <= diff) + { + DoSummon(ENTRY_HIGHBORNE_BUNNY, me, 10.0f, 3000, TEMPSUMMON_TIMED_DESPAWN); + + LamentEvent_Timer = 2000; + if (!me->HasAura(SPELL_SYLVANAS_CAST)) + { + DoScriptText(SAY_LAMENT_END, me); + DoScriptText(EMOTE_LAMENT_END, me); + LamentEvent = false; + } + } else LamentEvent_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_lady_sylvanas_windrunner(Creature* pCreature) +{ + return new npc_lady_sylvanas_windrunnerAI (pCreature); +} + +bool ChooseReward_npc_lady_sylvanas_windrunner(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest, uint32 /*slot*/) +{ + if (_Quest->GetQuestId() == 9180) + { + CAST_AI(npc_lady_sylvanas_windrunnerAI, pCreature->AI())->LamentEvent = true; + CAST_AI(npc_lady_sylvanas_windrunnerAI, pCreature->AI())->DoPlaySoundToSet(pCreature,SOUND_CREDIT); + pCreature->CastSpell(pCreature,SPELL_SYLVANAS_CAST,false); + + for (uint8 i = 0; i < 4; ++i) + pCreature->SummonCreature(ENTRY_HIGHBORNE_LAMENTER, HighborneLoc[i][0], HighborneLoc[i][1], HIGHBORNE_LOC_Y, HighborneLoc[i][2], TEMPSUMMON_TIMED_DESPAWN, 160000); + } + + return true; +} + +/*###### +## npc_highborne_lamenter +######*/ + +struct npc_highborne_lamenterAI : public ScriptedAI +{ + npc_highborne_lamenterAI(Creature *c) : ScriptedAI(c) {} + + uint32 EventMove_Timer; + uint32 EventCast_Timer; + bool EventMove; + bool EventCast; + + void Reset() + { + EventMove_Timer = 10000; + EventCast_Timer = 17500; + EventMove = true; + EventCast = true; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (EventMove) + { + if (EventMove_Timer <= diff) + { + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMonsterMoveWithSpeed(me->GetPositionX(),me->GetPositionY(),HIGHBORNE_LOC_Y_NEW,5000); + me->GetMap()->CreatureRelocation(me,me->GetPositionX(),me->GetPositionY(),HIGHBORNE_LOC_Y_NEW,me->GetOrientation()); + EventMove = false; + } else EventMove_Timer -= diff; + } + if (EventCast) + { + if (EventCast_Timer <= diff) + { + DoCast(me, SPELL_HIGHBORNE_AURA); + EventCast = false; + } else EventCast_Timer -= diff; + } + } +}; +CreatureAI* GetAI_npc_highborne_lamenter(Creature* pCreature) +{ + return new npc_highborne_lamenterAI (pCreature); +} + +/*###### +## npc_parqual_fintallas +######*/ + +#define SPELL_MARK_OF_SHAME 6767 + +#define GOSSIP_HPF1 "Gul'dan" +#define GOSSIP_HPF2 "Kel'Thuzad" +#define GOSSIP_HPF3 "Ner'zhul" + +bool GossipHello_npc_parqual_fintallas(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(6628) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasAura(SPELL_MARK_OF_SHAME)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HPF1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HPF2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HPF3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(5822, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(5821, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_parqual_fintallas(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer,SPELL_MARK_OF_SHAME,false); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(6628); + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_undercity() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_lady_sylvanas_windrunner"; + newscript->GetAI = &GetAI_npc_lady_sylvanas_windrunner; + newscript->pChooseReward = &ChooseReward_npc_lady_sylvanas_windrunner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_highborne_lamenter"; + newscript->GetAI = &GetAI_npc_highborne_lamenter; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_parqual_fintallas"; + newscript->pGossipHello = &GossipHello_npc_parqual_fintallas; + newscript->pGossipSelect = &GossipSelect_npc_parqual_fintallas; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/western_plaguelands.cpp b/src/server/scripts/EasternKingdoms/western_plaguelands.cpp new file mode 100644 index 00000000000..778bcea0b1e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/western_plaguelands.cpp @@ -0,0 +1,396 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Western_Plaguelands +SD%Complete: 90 +SDComment: Quest support: 5097, 5098, 5216, 5219, 5222, 5225, 5229, 5231, 5233, 5235. To obtain Vitreous Focuser (could use more spesifics about gossip items) +SDCategory: Western Plaguelands +EndScriptData */ + +/* ContentData +npcs_dithers_and_arbington +npc_myranda_the_hag +npc_the_scourge_cauldron +npc_andorhal_tower +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npcs_dithers_and_arbington +######*/ + +#define GOSSIP_HDA1 "What does the Felstone Field Cauldron need?" +#define GOSSIP_HDA2 "What does the Dalson's Tears Cauldron need?" +#define GOSSIP_HDA3 "What does the Writhing Haunt Cauldron need?" +#define GOSSIP_HDA4 "What does the Gahrron's Withering Cauldron need?" + +#define GOSSIP_SDA1 "Thanks, i need a Vitreous Focuser" + +bool GossipHello_npcs_dithers_and_arbington(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (pPlayer->GetQuestRewardStatus(5237) || pPlayer->GetQuestRewardStatus(5238)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HDA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HDA3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HDA4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(3985, pCreature->GetGUID()); + }else + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_dithers_and_arbington(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(3980, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(3981, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(3982, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(3983, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, 17529, false); + break; + } + return true; +} + +/*###### +## npc_myranda_the_hag +######*/ + +enum eMyranda +{ + QUEST_SUBTERFUGE = 5862, + QUEST_IN_DREAMS = 5944, + SPELL_SCARLET_ILLUSION = 17961 +}; + +#define GOSSIP_ITEM_ILLUSION "I am ready for the illusion, Myranda." + +bool GossipHello_npc_myranda_the_hag(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_SUBTERFUGE) == QUEST_STATUS_COMPLETE && + !pPlayer->GetQuestRewardStatus(QUEST_IN_DREAMS) && !pPlayer->HasAura(SPELL_SCARLET_ILLUSION)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ILLUSION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(4773, pCreature->GetGUID()); + return true; + } + else + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_myranda_the_hag(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_SCARLET_ILLUSION, false); + } + return true; +} + +/*###### +## npc_the_scourge_cauldron +######*/ + +struct npc_the_scourge_cauldronAI : public ScriptedAI +{ + npc_the_scourge_cauldronAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + + void EnterCombat(Unit* /*who*/) {} + + void DoDie() + { + //summoner dies here + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + //override any database `spawntimesecs` to prevent duplicated summons + uint32 rTime = me->GetRespawnDelay(); + if (rTime<600) + me->SetRespawnDelay(600); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || who->GetTypeId() != TYPEID_PLAYER) + return; + + if (who->GetTypeId() == TYPEID_PLAYER) + { + switch(me->GetAreaId()) + { + case 199: //felstone + if (CAST_PLR(who)->GetQuestStatus(5216) == QUEST_STATUS_INCOMPLETE || + CAST_PLR(who)->GetQuestStatus(5229) == QUEST_STATUS_INCOMPLETE) + { + me->SummonCreature(11075, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); + DoDie(); + } + break; + case 200: //dalson + if (CAST_PLR(who)->GetQuestStatus(5219) == QUEST_STATUS_INCOMPLETE || + CAST_PLR(who)->GetQuestStatus(5231) == QUEST_STATUS_INCOMPLETE) + { + me->SummonCreature(11077, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); + DoDie(); + } + break; + case 201: //gahrron + if (CAST_PLR(who)->GetQuestStatus(5225) == QUEST_STATUS_INCOMPLETE || + CAST_PLR(who)->GetQuestStatus(5235) == QUEST_STATUS_INCOMPLETE) + { + me->SummonCreature(11078, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoDie(); + } + break; + case 202: //writhing + if (CAST_PLR(who)->GetQuestStatus(5222) == QUEST_STATUS_INCOMPLETE || + CAST_PLR(who)->GetQuestStatus(5233) == QUEST_STATUS_INCOMPLETE) + { + me->SummonCreature(11076, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoDie(); + } + break; + } + } + } +}; +CreatureAI* GetAI_npc_the_scourge_cauldron(Creature* pCreature) +{ + return new npc_the_scourge_cauldronAI (pCreature); +} + +/*###### +## npcs_andorhal_tower +######*/ + +enum eAndorhalTower +{ + GO_BEACON_TORCH = 176093 +}; + +struct npc_andorhal_towerAI : public Scripted_NoMovementAI +{ + npc_andorhal_towerAI(Creature *c) : Scripted_NoMovementAI(c) {} + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER) + return; + + if (me->FindNearestGameObject(GO_BEACON_TORCH, 10.0f)) + CAST_PLR(pWho)->KilledMonsterCredit(me->GetEntry(), me->GetGUID()); + } +}; + +CreatureAI* GetAI_npc_andorhal_tower(Creature* pCreature) +{ + return new npc_andorhal_towerAI (pCreature); +} + +/*###### +## npc_anchorite_truuen +######*/ + +enum eTruuen +{ + NPC_GHOST_UTHER = 17233, + NPC_THEL_DANIS = 1854, + NPC_GHOUL = 1791, //ambush + + QUEST_TOMB_LIGHTBRINGER = 9446, + + SAY_WP_0 = -1999981, //Beware! We are attacked! + SAY_WP_1 = -1999982, //It must be the purity of the Mark of the Lightbringer that is drawing forth the Scourge to attack us. We must proceed with caution lest we be overwhelmed! + SAY_WP_2 = -1999983, //This land truly needs to be cleansed by the Light! Let us continue on to the tomb. It isn't far now... + SAY_WP_3 = -1999984, //Be welcome, friends! + SAY_WP_4 = -1999985, //Thank you for coming here in remembrance of me. Your efforts in recovering that symbol, while unnecessary, are certainly touching to an old man's heart. + SAY_WP_5 = -1999986, //Please, rise my friend. Keep the Blessing as a symbol of the strength of the Light and how heroes long gone might once again rise in each of us to inspire. + SAY_WP_6 = -1999987 //Thank you my friend for making this possible. This is a day that I shall never forget! I think I will stay a while. Please return to High Priestess MacDonnell at the camp. I know that she'll be keenly interested to know of what has transpired here. +}; + +struct npc_anchorite_truuenAI : public npc_escortAI +{ + npc_anchorite_truuenAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + uint32 m_uiChatTimer; + + uint64 UghostGUID; + uint64 TheldanisGUID; + + Creature* Ughost; + Creature* Theldanis; + + void Reset() + { + m_uiChatTimer = 7000; + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_GHOUL) + pSummoned->AI()->AttackStart(me); + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + switch (i) + { + case 8: + DoScriptText(SAY_WP_0, me); + me->SummonCreature(NPC_GHOUL, me->GetPositionX()+7.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); + me->SummonCreature(NPC_GHOUL, me->GetPositionX()+5.0f, me->GetPositionY()+5.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); + break; + case 9: + DoScriptText(SAY_WP_1, me); + break; + case 14: + me->SummonCreature(NPC_GHOUL, me->GetPositionX()+7.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); + me->SummonCreature(NPC_GHOUL, me->GetPositionX()+5.0f, me->GetPositionY()+5.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); + me->SummonCreature(NPC_GHOUL, me->GetPositionX()+10.0f, me->GetPositionY()+10.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); + me->SummonCreature(NPC_GHOUL, me->GetPositionX()+8.0f, me->GetPositionY()+8.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); + break; + case 15: + DoScriptText(SAY_WP_2, me); + case 21: + Theldanis = GetClosestCreatureWithEntry(me, NPC_THEL_DANIS, 150); + DoScriptText(SAY_WP_3, Theldanis); + break; + case 22: + break; + case 23: + Ughost = me->SummonCreature(NPC_GHOST_UTHER, 971.86,-1825.42 ,81.99 , 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + Ughost->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + DoScriptText(SAY_WP_4, Ughost, me); + m_uiChatTimer = 4000; + break; + case 24: + DoScriptText(SAY_WP_5, Ughost, me); + m_uiChatTimer = 4000; + break; + case 25: + DoScriptText(SAY_WP_6, Ughost, me); + m_uiChatTimer = 4000; + break; + case 26: + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_TOMB_LIGHTBRINGER, me); + break; + } + } + + void EnterCombat(Unit* /*pWho*/){} + + void JustDied(Unit* /*pKiller*/) + { + Player* pPlayer = GetPlayerForEscort(); + if (pPlayer) + pPlayer->FailQuest(QUEST_TOMB_LIGHTBRINGER); + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + DoMeleeAttackIfReady(); + if (HasEscortState(STATE_ESCORT_ESCORTING)) + m_uiChatTimer = 6000; + } +}; + +CreatureAI* GetAI_npc_anchorite_truuen(Creature* pCreature) +{ + return new npc_anchorite_truuenAI(pCreature); +} + +bool QuestAccept_npc_anchorite_truuen(Player* pPlayer, Creature* pCreature, Quest const *quest) +{ + npc_escortAI* pEscortAI = CAST_AI(npc_anchorite_truuenAI, pCreature->AI()); + + if (quest->GetQuestId() == QUEST_TOMB_LIGHTBRINGER) + pEscortAI->Start(true, true, pPlayer->GetGUID()); + return false; +} + +/*###### +## +######*/ + +void AddSC_western_plaguelands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npcs_dithers_and_arbington"; + newscript->pGossipHello = &GossipHello_npcs_dithers_and_arbington; + newscript->pGossipSelect = &GossipSelect_npcs_dithers_and_arbington; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_myranda_the_hag"; + newscript->pGossipHello = &GossipHello_npc_myranda_the_hag; + newscript->pGossipSelect = &GossipSelect_npc_myranda_the_hag; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_the_scourge_cauldron"; + newscript->GetAI = &GetAI_npc_the_scourge_cauldron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_andorhal_tower"; + newscript->GetAI = &GetAI_npc_andorhal_tower; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anchorite_truuen"; + newscript->GetAI = &GetAI_npc_anchorite_truuen; + newscript->pQuestAccept = &QuestAccept_npc_anchorite_truuen; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/westfall.cpp b/src/server/scripts/EasternKingdoms/westfall.cpp new file mode 100644 index 00000000000..6f2f439f7fb --- /dev/null +++ b/src/server/scripts/EasternKingdoms/westfall.cpp @@ -0,0 +1,263 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Westfall +SD%Complete: 90 +SDComment: Quest support: 155, 1651 +SDCategory: Westfall +EndScriptData */ + +/* ContentData +npc_daphne_stilwell +npc_defias_traitor +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_daphne_stilwell +######*/ + +enum eEnums +{ + SAY_DS_START = -1000293, + SAY_DS_DOWN_1 = -1000294, + SAY_DS_DOWN_2 = -1000295, + SAY_DS_DOWN_3 = -1000296, + SAY_DS_PROLOGUE = -1000297, + + SPELL_SHOOT = 6660, + QUEST_TOME_VALOR = 1651, + NPC_DEFIAS_RAIDER = 6180, + EQUIP_ID_RIFLE = 2511 +}; + +struct npc_daphne_stilwellAI : public npc_escortAI +{ + npc_daphne_stilwellAI(Creature* pCreature) : npc_escortAI(pCreature) {} + + uint32 uiWPHolder; + uint32 uiShootTimer; + + void Reset() + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + switch(uiWPHolder) + { + case 7: DoScriptText(SAY_DS_DOWN_1, me); break; + case 8: DoScriptText(SAY_DS_DOWN_2, me); break; + case 9: DoScriptText(SAY_DS_DOWN_3, me); break; + } + } + else + uiWPHolder = 0; + + uiShootTimer = 0; + } + + void WaypointReached(uint32 uiPoint) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + uiWPHolder = uiPoint; + + switch(uiPoint) + { + case 4: + SetEquipmentSlots(false, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE, EQUIP_ID_RIFLE); + me->SetSheath(SHEATH_STATE_RANGED); + me->HandleEmoteCommand(EMOTE_STATE_USESTANDING_NOSHEATHE); + break; + case 7: + me->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836, 1569.755, 54.267, 4.230, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697, 1569.124, 54.421, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237, 1568.307, 54.620, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 8: + me->SetSheath(SHEATH_STATE_RANGED); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836, 1569.755, 54.267, 4.230, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697, 1569.124, 54.421, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237, 1568.307, 54.620, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.037, 1570.213, 54.961, 4.283, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 9: + me->SetSheath(SHEATH_STATE_RANGED); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836, 1569.755, 54.267, 4.230, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697, 1569.124, 54.421, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237, 1568.307, 54.620, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.037, 1570.213, 54.961, 4.283, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_DEFIAS_RAIDER, -11449.018, 1570.738, 54.828, 4.220, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 10: + SetRun(false); + break; + case 11: + DoScriptText(SAY_DS_PROLOGUE, me); + break; + case 13: + SetEquipmentSlots(true); + me->SetSheath(SHEATH_STATE_UNARMED); + me->HandleEmoteCommand(EMOTE_STATE_USESTANDING_NOSHEATHE); + break; + case 17: + pPlayer->GroupEventHappens(QUEST_TOME_VALOR, me); + break; + } + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (me->Attack(pWho, false)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(pWho, 30.0f); + } + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->AI()->AttackStart(me); + } + + void Update(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + if (uiShootTimer <= diff) + { + uiShootTimer = 1500; + + if (!me->IsWithinDist(me->getVictim(), ATTACK_DISTANCE)) + DoCast(me->getVictim(), SPELL_SHOOT); + } else uiShootTimer -= diff; + } +}; + +bool QuestAccept_npc_daphne_stilwell(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_TOME_VALOR) + { + DoScriptText(SAY_DS_START, pCreature); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_daphne_stilwellAI, pCreature->AI())) + pEscortAI->Start(true, true, pPlayer->GetGUID()); + } + + return true; +} + +CreatureAI* GetAI_npc_daphne_stilwell(Creature* pCreature) +{ + return new npc_daphne_stilwellAI(pCreature); +} + +/*###### +## npc_defias_traitor +######*/ + +#define SAY_START -1000101 +#define SAY_PROGRESS -1000102 +#define SAY_END -1000103 +#define SAY_AGGRO_1 -1000104 +#define SAY_AGGRO_2 -1000105 + +#define QUEST_DEFIAS_BROTHERHOOD 155 + +struct npc_defias_traitorAI : public npc_escortAI +{ + npc_defias_traitorAI(Creature *c) : npc_escortAI(c) { Reset(); } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch (i) + { + case 35: + SetRun(false); + break; + case 36: + DoScriptText(SAY_PROGRESS, me, pPlayer); + break; + case 44: + DoScriptText(SAY_END, me, pPlayer); + { + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_DEFIAS_BROTHERHOOD,me); + } + break; + } + } + void EnterCombat(Unit* who) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me, who); + } + + void Reset() {} +}; + +bool QuestAccept_npc_defias_traitor(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_DEFIAS_BROTHERHOOD) + { + if (npc_escortAI* pEscortAI = CAST_AI(npc_defias_traitorAI, pCreature->AI())) + pEscortAI->Start(true, true, pPlayer->GetGUID()); + + DoScriptText(SAY_START, pCreature, pPlayer); + } + + return true; +} + +CreatureAI* GetAI_npc_defias_traitor(Creature* pCreature) +{ + return new npc_defias_traitorAI(pCreature); +} + +void AddSC_westfall() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_daphne_stilwell"; + newscript->GetAI = &GetAI_npc_daphne_stilwell; + newscript->pQuestAccept = &QuestAccept_npc_daphne_stilwell; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_defias_traitor"; + newscript->GetAI = &GetAI_npc_defias_traitor; + newscript->pQuestAccept = &QuestAccept_npc_defias_traitor; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/wetlands.cpp b/src/server/scripts/EasternKingdoms/wetlands.cpp new file mode 100644 index 00000000000..02f7abdf4c2 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/wetlands.cpp @@ -0,0 +1,168 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Wetlands +SD%Complete: 80 +SDComment: Quest support: 1249 +SDCategory: Wetlands +EndScriptData */ + +/* ContentData +npc_mikhail +npc_tapoke_slim_jahn +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_tapoke_slim_jahn +######*/ + +enum eTapokeSlim +{ + QUEST_MISSING_DIPLO_PT11 = 1249, + FACTION_ENEMY = 168, + SPELL_STEALTH = 1785, + SPELL_CALL_FRIENDS = 16457, //summons 1x friend + NPC_SLIMS_FRIEND = 4971, + NPC_TAPOKE_SLIM_JAHN = 4962 +}; + +struct npc_tapoke_slim_jahnAI : public npc_escortAI +{ + npc_tapoke_slim_jahnAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + bool m_bFriendSummoned; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + m_bFriendSummoned = false; + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 2: + if (me->HasStealthAura()) + me->RemoveAurasDueToSpell(SPELL_AURA_MOD_STEALTH); + + SetRun(); + me->setFaction(FACTION_ENEMY); + break; + } + } + + void Aggro(Unit* /*pWho*/) + { + Player* pPlayer = GetPlayerForEscort(); + + if (HasEscortState(STATE_ESCORT_ESCORTING) && !m_bFriendSummoned && pPlayer) + { + for (uint8 i = 0; i < 3; ++i) + DoCast(me, SPELL_CALL_FRIENDS, true); + + m_bFriendSummoned = true; + } + } + + void JustSummoned(Creature* pSummoned) + { + if (Player* pPlayer = GetPlayerForEscort()) + pSummoned->AI()->AttackStart(pPlayer); + } + + void AttackedBy(Unit* pAttacker) + { + if (me->getVictim()) + return; + + if (me->IsFriendlyTo(pAttacker)) + return; + + AttackStart(pAttacker); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) + { + if (me->GetHealth()*100 < me->GetMaxHealth()*20) + { + if (Player* pPlayer = GetPlayerForEscort()) + { + if (pPlayer->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(pPlayer)->GroupEventHappens(QUEST_MISSING_DIPLO_PT11, me); + + uiDamage = 0; + + me->RestoreFaction(); + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + + SetRun(false); + } + } + } +}; + +CreatureAI* GetAI_npc_tapoke_slim_jahn(Creature* pCreature) +{ + return new npc_tapoke_slim_jahnAI(pCreature); +} + +/*###### +## npc_mikhail +######*/ + +bool QuestAccept_npc_mikhail(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT11) + { + Creature* pSlim = pCreature->FindNearestCreature(NPC_TAPOKE_SLIM_JAHN, 25.0f); + + if (!pSlim) + return false; + + if (!pSlim->HasStealthAura()) + pSlim->CastSpell(pSlim, SPELL_STEALTH, true); + + if (npc_tapoke_slim_jahnAI* pEscortAI = CAST_AI(npc_tapoke_slim_jahnAI, pSlim->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + } + return false; +} + +/*###### +## AddSC +######*/ + +void AddSC_wetlands() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_tapoke_slim_jahn"; + newscript->GetAI = &GetAI_npc_tapoke_slim_jahn; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mikhail"; + newscript->pQuestAccept = &QuestAccept_npc_mikhail; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp new file mode 100644 index 00000000000..f516065cc03 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp @@ -0,0 +1,467 @@ +/* Copyright ?2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_Akilzon +SD%Complete: 75% +SDComment: Missing timer for Call Lightning and Sound ID's +SQLUpdate: +#Temporary fix for Soaring Eagles + +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" +#include "Weather.h" + +#define SPELL_STATIC_DISRUPTION 43622 +#define SPELL_STATIC_VISUAL 45265 +#define SPELL_CALL_LIGHTNING 43661 //Missing timer +#define SPELL_GUST_OF_WIND 43621 +#define SPELL_ELECTRICAL_STORM 43648 +#define SPELL_BERSERK 45078 +#define SPELL_ELECTRICAL_DAMAGE 43657 +#define SPELL_ELECTRICAL_OVERLOAD 43658 +#define SPELL_EAGLE_SWOOP 44732 + +//"Your death gonna be quick, strangers. You shoulda never have come to this place..." +#define SAY_ONAGGRO "I be da predator! You da prey..." +#define SAY_ONDEATH "You can't... kill... me spirit!" +#define SAY_ONSLAY1 "Ya got nothin'!" +#define SAY_ONSLAY2 "Stop your cryin'!" +#define SAY_ONSUMMON "Feed, me bruddahs!" +#define SAY_ONENRAGE "All you be doing is wasting my time!" +#define SOUND_ONAGGRO 12013 +#define SOUND_ONDEATH 12019 +#define SOUND_ONSLAY1 12017 +#define SOUND_ONSLAY2 12018 +#define SOUND_ONSUMMON 12014 +#define SOUND_ONENRAGE 12016 + +#define MOB_SOARING_EAGLE 24858 +#define SE_LOC_X_MAX 400 +#define SE_LOC_X_MIN 335 +#define SE_LOC_Y_MAX 1435 +#define SE_LOC_Y_MIN 1370 + +struct boss_akilzonAI : public ScriptedAI +{ + boss_akilzonAI(Creature *c) : ScriptedAI(c) + { + SpellEntry *TempSpell = GET_SPELL(SPELL_ELECTRICAL_DAMAGE); + if (TempSpell) + TempSpell->EffectBasePoints[1] = 49;//disable bugged lightning until fixed in core + pInstance = c->GetInstanceData(); + } + ScriptedInstance *pInstance; + + uint64 BirdGUIDs[8]; + uint64 TargetGUID; + uint64 CycloneGUID; + uint64 CloudGUID; + + uint32 StaticDisruption_Timer; + uint32 GustOfWind_Timer; + uint32 CallLighting_Timer; + uint32 ElectricalStorm_Timer; + uint32 SummonEagles_Timer; + uint32 Enrage_Timer; + + uint32 StormCount; + uint32 StormSequenceTimer; + + bool isRaining; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_AKILZONEVENT, NOT_STARTED); + + StaticDisruption_Timer = urand(10000,20000); //10 to 20 seconds (bosskillers) + GustOfWind_Timer = urand(20000,30000); //20 to 30 seconds(bosskillers) + CallLighting_Timer = urand(10000,20000); //totaly random timer. can't find any info on this + ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) + Enrage_Timer = 10*MINUTE*IN_MILISECONDS; //10 minutes till enrage(bosskillers) + SummonEagles_Timer = 99999; + + TargetGUID = 0; + CloudGUID = 0; + CycloneGUID = 0; + DespawnSummons(); + for (uint8 i = 0; i < 8; ++i) + BirdGUIDs[i] = 0; + + StormCount = 0; + StormSequenceTimer = 0; + + isRaining = false; + + SetWeather(WEATHER_STATE_FINE, 0.0f); + } + + void EnterCombat(Unit * /*who*/) + { + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + //DoZoneInCombat(); + if (pInstance) + pInstance->SetData(DATA_AKILZONEVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*Killer*/) + { + me->MonsterYell(SAY_ONDEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me, SOUND_ONDEATH); + if (pInstance) + pInstance->SetData(DATA_AKILZONEVENT, DONE); + DespawnSummons(); + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,1)) + { + case 0: + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONSLAY1); + break; + case 1: + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONSLAY2); + break; + } + } + + void DespawnSummons() + { + for (uint8 i = 0; i < 8; ++i) + { + Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]); + if (bird && bird->isAlive()) + { + bird->SetVisibility(VISIBILITY_OFF); + bird->setDeathState(JUST_DIED); + } + } + } + + void SetWeather(uint32 weather, float grade) + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) + return; + + WorldPacket data(SMSG_WEATHER, (4+4+4)); + data << uint32(weather) << float(grade) << uint8(0); + + pMap->SendToPlayers(&data); + } + + void HandleStormSequence(Unit *Cloud) // 1: begin, 2-9: tick, 10: end + { + if (StormCount < 10 && StormCount > 1) + { + // deal damage + int32 bp0 = 800; + for (uint8 i = 2; i < StormCount; ++i) + bp0 *= 2; + + CellPair p(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list tempUnitMap; + + { + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, 999); + Trinity::UnitListSearcher searcher(me, tempUnitMap, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + cell.Visit(p, world_unit_searcher, *(me->GetMap())); + cell.Visit(p, grid_unit_searcher, *(me->GetMap())); + } + //dealdamege + for (std::list::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i) + { + if (!Cloud->IsWithinDist(*i, 6, false)) + { + Cloud->CastCustomSpell(*i, 43137, &bp0, NULL, NULL, true, 0, 0, me->GetGUID()); + } + } + // visual + float x,y,z; + z = me->GetPositionZ(); + for (uint8 i = 0; i < 5+rand()%5; ++i) + { + x = 343+rand()%60; + y = 1380+rand()%60; + if (Unit *trigger = me->SummonTrigger(x, y, z, 0, 2000)) + { + trigger->setFaction(35); + trigger->SetMaxHealth(100000); + trigger->SetHealth(100000); + trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (Cloud) + Cloud->CastCustomSpell(trigger, /*43661*/43137, &bp0, NULL, NULL,true, 0, 0, Cloud->GetGUID()); + } + } + } + ++StormCount; + if (StormCount > 10) + { + StormCount = 0; // finish + SummonEagles_Timer = 5000; + me->InterruptNonMeleeSpells(false); + CloudGUID = 0; + if (Cloud) + Cloud->DealDamage(Cloud, Cloud->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + SetWeather(WEATHER_STATE_FINE, 0.0f); + isRaining = false; + } + StormSequenceTimer = 1000; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (StormCount) + { + Unit *pTarget = Unit::GetUnit(*me, CloudGUID); + if (!pTarget || !pTarget->isAlive()) + { + EnterEvadeMode(); + return; + } + else if (Unit* Cyclone = Unit::GetUnit(*me, CycloneGUID)) + Cyclone->CastSpell(pTarget, 25160, true); // keep casting or... + + if (StormSequenceTimer <= diff) + HandleStormSequence(pTarget); + else + StormSequenceTimer -= diff; + + return; + } + + if (Enrage_Timer <= diff) + { + me->MonsterYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONENRAGE); + DoCast(me, SPELL_BERSERK, true); + Enrage_Timer = 600000; + } else Enrage_Timer -= diff; + + if (StaticDisruption_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) pTarget = me->getVictim(); + TargetGUID = pTarget->GetGUID(); + DoCast(pTarget, SPELL_STATIC_DISRUPTION, false); + me->SetInFront(me->getVictim()); + StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s + + /*if (float dist = me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f) dist = 5.0f; + SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/ + } else StaticDisruption_Timer -= diff; + + if (GustOfWind_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) pTarget = me->getVictim(); + DoCast(pTarget, SPELL_GUST_OF_WIND); + GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers) + } else GustOfWind_Timer -= diff; + + if (CallLighting_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CALL_LIGHTNING); + CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this + } else CallLighting_Timer -= diff; + + if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000) + { + SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f); + isRaining = true; + } + + if (ElectricalStorm_Timer <= diff) { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); + if (!pTarget) + { + EnterEvadeMode(); + return; + } + pTarget->CastSpell(pTarget, 44007, true);//cloud visual + DoCast(pTarget, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual + float x,y,z; + pTarget->GetPosition(x,y,z); + if (pTarget) + { + pTarget->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + pTarget->SendMonsterMove(x,y,me->GetPositionZ()+15,0); + } + Unit *Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000); + if (Cloud) + { + CloudGUID = Cloud->GetGUID(); + Cloud->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + Cloud->StopMoving(); + Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + Cloud->setFaction(35); + Cloud->SetMaxHealth(9999999); + Cloud->SetHealth(9999999); + Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) + StormCount = 1; + StormSequenceTimer = 0; + } else ElectricalStorm_Timer -= diff; + + if (SummonEagles_Timer <= diff) + { + me->MonsterYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONSUMMON); + + float x, y, z; + me->GetPosition(x, y, z); + + for (uint8 i = 0; i < 8; ++i) + { + Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]); + if (!bird) //they despawned on die + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + x = pTarget->GetPositionX() + irand(-10,10); + y = pTarget->GetPositionY() + irand(-10,10); + z = pTarget->GetPositionZ() + urand(16,20); + if (z > 95) + z = 95 - urand(0,5); + } + Creature *pCreature = me->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (pCreature) + { + pCreature->AddThreat(me->getVictim(), 1.0f); + pCreature->AI()->AttackStart(me->getVictim()); + BirdGUIDs[i] = pCreature->GetGUID(); + } + } + } + SummonEagles_Timer = 999999; + } else SummonEagles_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soaring_eagleAI : public ScriptedAI +{ + mob_soaring_eagleAI(Creature *c) : ScriptedAI(c) {} + + uint32 EagleSwoop_Timer; + bool arrived; + uint32 TargetGUID; + + void Reset() + { + EagleSwoop_Timer = 5000 + rand()%5000; + arrived = true; + TargetGUID = 0; + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + } + + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + + void MoveInLineOfSight(Unit* /*who*/) {} + + void MovementInform(uint32, uint32) + { + arrived = true; + if (TargetGUID) + { + if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID)) + DoCast(pTarget, SPELL_EAGLE_SWOOP, true); + TargetGUID = 0; + me->SetSpeed(MOVE_RUN, 1.2f); + EagleSwoop_Timer = 5000 + rand()%5000; + } + } + + void UpdateAI(const uint32 diff) + { + if (EagleSwoop_Timer <= diff) + EagleSwoop_Timer = 0; + else + EagleSwoop_Timer -= diff; + + if (arrived) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + if (EagleSwoop_Timer) + { + x = pTarget->GetPositionX() + irand(-10,10); + y = pTarget->GetPositionY() + irand(-10,10); + z = pTarget->GetPositionZ() + urand(10,15); + if (z > 95) + z = 95 - urand(0,5); + } + else + { + pTarget->GetContactPoint(me, x, y, z); + z += 2; + me->SetSpeed(MOVE_RUN, 5.0f); + TargetGUID = pTarget->GetGUID(); + } + me->GetMotionMaster()->MovePoint(0, x, y, z); + arrived = false; + } + } + } +}; + +//Soaring Eagle +CreatureAI* GetAI_mob_soaring_eagle(Creature* pCreature) +{ + return new mob_soaring_eagleAI(pCreature); +} + +CreatureAI* GetAI_boss_akilzon(Creature* pCreature) +{ + return new boss_akilzonAI(pCreature); +} + +void AddSC_boss_akilzon() +{ + Script *newscript = NULL; + + newscript = new Script; + newscript->Name = "boss_akilzon"; + newscript->GetAI = &GetAI_boss_akilzon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_akilzon_eagle"; + newscript->GetAI = &GetAI_mob_soaring_eagle; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp new file mode 100644 index 00000000000..aee0a8a59ea --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp @@ -0,0 +1,401 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_Halazzi +SD%Complete: 80 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" +//#include "spell.h" + +#define YELL_AGGRO "Get on your knees and bow to da fang and claw!" +#define SOUND_AGGRO 12020 +#define YELL_SABER_ONE "You gonna leave in pieces!" +#define YELL_SABER_TWO "Me gonna carve ya now!" +#define YELL_SPLIT "Me gonna carve ya now!" +#define SOUND_SPLIT 12021 +#define YELL_MERGE "Spirit, come back to me!" +#define SOUND_MERGE 12022 +#define YELL_KILL_ONE "You cant fight the power!" +#define SOUND_KILL_ONE 12026 +#define YELL_KILL_TWO "You gonna fail!" +#define SOUND_KILL_TWO 12027 +#define YELL_DEATH "Chaga... choka'jinn." +#define SOUND_DEATH 12028 +#define YELL_BERSERK "Whatch you be doing? Pissin' yourselves..." +#define SOUND_BERSERK 12025 + +#define SPELL_DUAL_WIELD 29651 +#define SPELL_SABER_LASH 43267 +#define SPELL_FRENZY 43139 +#define SPELL_FLAMESHOCK 43303 +#define SPELL_EARTHSHOCK 43305 +#define SPELL_TRANSFORM_SPLIT 43142 +#define SPELL_TRANSFORM_SPLIT2 43573 +#define SPELL_TRANSFORM_MERGE 43271 +#define SPELL_SUMMON_LYNX 43143 +#define SPELL_SUMMON_TOTEM 43302 +#define SPELL_BERSERK 45078 + +#define MOB_SPIRIT_LYNX 24143 +#define SPELL_LYNX_FRENZY 43290 +#define SPELL_SHRED_ARMOR 43243 + +#define MOB_TOTEM 24224 +#define SPELL_LIGHTNING 43301 + +enum PhaseHalazzi +{ + PHASE_NONE = 0, + PHASE_LYNX = 1, + PHASE_SPLIT = 2, + PHASE_HUMAN = 3, + PHASE_MERGE = 4, + PHASE_ENRAGE = 5 +}; + +struct boss_halazziAI : public ScriptedAI +{ + boss_halazziAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + // need to find out what controls totem's spell cooldown + SpellEntry *TempSpell = GET_SPELL(SPELL_LIGHTNING); + if (TempSpell && TempSpell->CastingTimeIndex != 5) + TempSpell->CastingTimeIndex = 5; // 2000 ms casting time + } + + ScriptedInstance *pInstance; + + uint32 FrenzyTimer; + uint32 SaberlashTimer; + uint32 ShockTimer; + uint32 TotemTimer; + uint32 CheckTimer; + uint32 BerserkTimer; + + uint32 TransformCount; + + PhaseHalazzi Phase; + + uint64 LynxGUID; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_HALAZZIEVENT, NOT_STARTED); + + TransformCount = 0; + BerserkTimer = 600000; + CheckTimer = 1000; + + DoCast(me, SPELL_DUAL_WIELD, true); + + Phase = PHASE_NONE; + EnterPhase(PHASE_LYNX); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS); + + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_AGGRO); + + EnterPhase(PHASE_LYNX); + } + + void JustSummoned(Creature* summon) + { + summon->AI()->AttackStart(me->getVictim()); + if (summon->GetEntry() == MOB_SPIRIT_LYNX) + LynxGUID = summon->GetGUID(); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE) + damage = 0; + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (spell->Id == SPELL_TRANSFORM_SPLIT2) + EnterPhase(PHASE_HUMAN); + } + + void AttackStart(Unit *who) + { + if (Phase != PHASE_MERGE) ScriptedAI::AttackStart(who); + } + + void EnterPhase(PhaseHalazzi NextPhase) + { + switch(NextPhase) + { + case PHASE_LYNX: + case PHASE_ENRAGE: + if (Phase == PHASE_MERGE) + { + DoCast(me, SPELL_TRANSFORM_MERGE, true); + me->Attack(me->getVictim(), true); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + if (Creature *Lynx = Unit::GetCreature(*me, LynxGUID)) + Lynx->DisappearAndDie(); + me->SetMaxHealth(600000); + me->SetHealth(600000 - 150000 * TransformCount); + FrenzyTimer = 16000; + SaberlashTimer = 20000; + ShockTimer = 10000; + TotemTimer = 12000; + break; + case PHASE_SPLIT: + me->MonsterYell(YELL_SPLIT, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_SPLIT); + DoCast(me, SPELL_TRANSFORM_SPLIT, true); + break; + case PHASE_HUMAN: + //DoCast(me, SPELL_SUMMON_LYNX, true); + DoSpawnCreature(MOB_SPIRIT_LYNX, 5,5,0,0, TEMPSUMMON_CORPSE_DESPAWN, 0); + me->SetMaxHealth(400000); + me->SetHealth(400000); + ShockTimer = 10000; + TotemTimer = 12000; + break; + case PHASE_MERGE: + if (Unit *pLynx = Unit::GetUnit(*me, LynxGUID)) + { + me->MonsterYell(YELL_MERGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_MERGE); + pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pLynx->GetMotionMaster()->Clear(); + pLynx->GetMotionMaster()->MoveFollow(me, 0, 0); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(pLynx, 0, 0); + ++TransformCount; + } + break; + default: + break; + } + Phase = NextPhase; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BerserkTimer <= diff) + { + me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_BERSERK); + DoCast(me, SPELL_BERSERK, true); + BerserkTimer = 60000; + } else BerserkTimer -= diff; + + if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE) + { + if (SaberlashTimer <= diff) + { + // A tank with more than 490 defense skills should receive no critical hit + //DoCast(me, 41296, true); + DoCast(me->getVictim(), SPELL_SABER_LASH, true); + //me->RemoveAurasDueToSpell(41296); + SaberlashTimer = 30000; + } else SaberlashTimer -= diff; + + if (FrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + FrenzyTimer = urand(10000,15000); + } else FrenzyTimer -= diff; + + if (Phase == PHASE_LYNX) + if (CheckTimer <= diff) + { + if (me->GetHealth() * 4 < me->GetMaxHealth() * (3 - TransformCount)) + EnterPhase(PHASE_SPLIT); + CheckTimer = 1000; + } else CheckTimer -= diff; + } + + if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE) + { + if (TotemTimer <= diff) + { + DoCast(me, SPELL_SUMMON_TOTEM); + TotemTimer = 20000; + } else TotemTimer -= diff; + + if (ShockTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget->IsNonMeleeSpellCasted(false)) + DoCast(pTarget, SPELL_EARTHSHOCK); + else + DoCast(pTarget, SPELL_FLAMESHOCK); + ShockTimer = 10000 + rand()%5000; + } + } else ShockTimer -= diff; + + if (Phase == PHASE_HUMAN) + if (CheckTimer <= diff) + { + if (((me->GetHealth()*100) / me->GetMaxHealth() <= 20)/*me->GetHealth() * 10 < me->GetMaxHealth()*/) + EnterPhase(PHASE_MERGE); + else + { + Unit *Lynx = Unit::GetUnit(*me, LynxGUID); + if (Lynx && ((Lynx->GetHealth()*100) / Lynx->GetMaxHealth() <= 20)/*Lynx->GetHealth() * 10 < Lynx->GetMaxHealth()*/) + EnterPhase(PHASE_MERGE); + } + CheckTimer = 1000; + } else CheckTimer -= diff; + } + + if (Phase == PHASE_MERGE) + { + if (CheckTimer <= diff) + { + Unit *Lynx = Unit::GetUnit(*me, LynxGUID); + if (Lynx) + { + Lynx->GetMotionMaster()->MoveFollow(me, 0, 0); + me->GetMotionMaster()->MoveFollow(Lynx, 0, 0); + if (me->IsWithinDistInMap(Lynx, 6.0f)) + { + if (TransformCount < 3) + EnterPhase(PHASE_LYNX); + else + EnterPhase(PHASE_ENRAGE); + } + } + CheckTimer = 1000; + } else CheckTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,1)) + { + case 0: + me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL_ONE); + break; + + case 1: + me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL_TWO); + break; + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_HALAZZIEVENT, DONE); + + me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_DEATH); + } +}; + +// Spirits Lynx AI + +struct boss_spiritlynxAI : public ScriptedAI +{ + boss_spiritlynxAI(Creature *c) : ScriptedAI(c) {} + + uint32 FrenzyTimer; + uint32 shredder_timer; + + void Reset() + { + FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds + shredder_timer = 4000; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + damage = 0; + } + + void AttackStart(Unit *who) + { + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (FrenzyTimer <= diff) + { + DoCast(me, SPELL_LYNX_FRENZY); + FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds + } else FrenzyTimer -= diff; + + if (shredder_timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHRED_ARMOR); + shredder_timer = 4000; + } else shredder_timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_halazziAI(Creature* pCreature) +{ + return new boss_halazziAI (pCreature); +} + +CreatureAI* GetAI_boss_spiritlynxAI(Creature* pCreature) +{ + return new boss_spiritlynxAI (pCreature); +} + +void AddSC_boss_halazzi() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_halazzi"; + newscript->GetAI = &GetAI_boss_halazziAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_halazzi_lynx"; + newscript->GetAI = &GetAI_boss_spiritlynxAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp new file mode 100644 index 00000000000..7baa9292142 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp @@ -0,0 +1,907 @@ +/* Copyright ?2006,2007 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Hex_Lord_Malacrass +SD%Complete: +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" + +#define YELL_AGGRO "Da shadow gonna fall on you... " +#define SOUND_YELL_AGGRO 12041 +#define YELL_SPIRIT_BOLTS "Your soul gonna bleed!" +#define SOUND_YELL_SPIRIT_BOLTS 12047 +#define YELL_DRAIN_POWER "Darkness comin\' for you" +#define SOUND_YELL_DRAIN_POWER 12046 +#define YELL_KILL_ONE "Dis a nightmare ya don\' wake up from!" +#define SOUND_YELL_KILL_ONE 12043 +#define YELL_KILL_TWO "Azzaga choogo zinn!" +#define SOUND_YELL_KILL_TWO 12044 +#define YELL_DEATH "Dis not... da end of me..." +#define SOUND_YELL_DEATH 12051 + +#define SPELL_SPIRIT_BOLTS 43383 +#define SPELL_DRAIN_POWER 44131 +#define SPELL_SIPHON_SOUL 43501 + +#define MOB_TEMP_TRIGGER 23920 + +//Defines for various powers he uses after using soul drain + +//Druid +#define SPELL_DR_LIFEBLOOM 43421 +#define SPELL_DR_THORNS 43420 +#define SPELL_DR_MOONFIRE 43545 + +//Hunter +#define SPELL_HU_EXPLOSIVE_TRAP 43444 +#define SPELL_HU_FREEZING_TRAP 43447 +#define SPELL_HU_SNAKE_TRAP 43449 + +//Mage +#define SPELL_MG_FIREBALL 41383 +#define SPELL_MG_FROSTBOLT 43428 +#define SPELL_MG_FROST_NOVA 43426 +#define SPELL_MG_ICE_LANCE 43427 + +//Paladin +#define SPELL_PA_CONSECRATION 43429 +#define SPELL_PA_HOLY_LIGHT 43451 +#define SPELL_PA_AVENGING_WRATH 43430 + +//Priest +#define SPELL_PR_HEAL 41372 +#define SPELL_PR_MIND_CONTROL 43550 +#define SPELL_PR_MIND_BLAST 41374 +#define SPELL_PR_SW_DEATH 41375 +#define SPELL_PR_PSYCHIC_SCREAM 43432 +#define SPELL_PR_PAIN_SUPP 44416 + +//Rogue +#define SPELL_RO_BLIND 43433 +#define SPELL_RO_SLICE_DICE 43457 +#define SPELL_RO_WOUND_POISON 39665 + +//Shaman +#define SPELL_SH_FIRE_NOVA 43436 +#define SPELL_SH_HEALING_WAVE 43548 +#define SPELL_SH_CHAIN_LIGHT 43435 + +//Warlock +#define SPELL_WL_CURSE_OF_DOOM 43439 +#define SPELL_WL_RAIN_OF_FIRE 43440 +#define SPELL_WL_UNSTABLE_AFFL 35183 + +//Warrior +#define SPELL_WR_SPELL_REFLECT 43443 +#define SPELL_WR_WHIRLWIND 43442 +#define SPELL_WR_MORTAL_STRIKE 43441 + +#define ORIENT 1.5696 +#define POS_Y 921.2795 +#define POS_Z 33.8883 + +static float Pos_X[4] = {112.8827, 107.8827, 122.8827, 127.8827}; + +static uint32 AddEntryList[8]= +{ + 24240, //Alyson Antille + 24241, //Thurg + 24242, //Slither + 24243, //Lord Raadan + 24244, //Gazakroth + 24245, //Fenstalker + 24246, //Darkheart + 24247 //Koragg +}; + +enum AbilityTarget +{ + ABILITY_TARGET_SELF = 0, + ABILITY_TARGET_VICTIM = 1, + ABILITY_TARGET_ENEMY = 2, + ABILITY_TARGET_HEAL = 3, + ABILITY_TARGET_BUFF = 4, + ABILITY_TARGET_SPECIAL = 5 +}; + +struct PlayerAbilityStruct +{ + uint32 spell; + AbilityTarget target; + uint32 cooldown; +}; + +static PlayerAbilityStruct PlayerAbility[][3] = +{ + // 1 warrior + {{SPELL_WR_SPELL_REFLECT, ABILITY_TARGET_SELF, 10000}, + {SPELL_WR_WHIRLWIND, ABILITY_TARGET_SELF, 10000}, + {SPELL_WR_MORTAL_STRIKE, ABILITY_TARGET_VICTIM, 6000}}, + // 2 paladin + {{SPELL_PA_CONSECRATION, ABILITY_TARGET_SELF, 10000}, + {SPELL_PA_HOLY_LIGHT, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PA_AVENGING_WRATH, ABILITY_TARGET_SELF, 10000}}, + // 3 hunter + {{SPELL_HU_EXPLOSIVE_TRAP, ABILITY_TARGET_SELF, 10000}, + {SPELL_HU_FREEZING_TRAP, ABILITY_TARGET_SELF, 10000}, + {SPELL_HU_SNAKE_TRAP, ABILITY_TARGET_SELF, 10000}}, + // 4 rogue + {{SPELL_RO_WOUND_POISON, ABILITY_TARGET_VICTIM, 3000}, + {SPELL_RO_SLICE_DICE, ABILITY_TARGET_SELF, 10000}, + {SPELL_RO_BLIND, ABILITY_TARGET_ENEMY, 10000}}, + // 5 priest + {{SPELL_PR_PAIN_SUPP, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PR_HEAL, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PR_PSYCHIC_SCREAM, ABILITY_TARGET_SELF, 10000}}, + // 5* shadow priest + {{SPELL_PR_MIND_CONTROL, ABILITY_TARGET_ENEMY, 15000}, + {SPELL_PR_MIND_BLAST, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_PR_SW_DEATH, ABILITY_TARGET_ENEMY, 10000}}, + // 7 shaman + {{SPELL_SH_FIRE_NOVA, ABILITY_TARGET_SELF, 10000}, + {SPELL_SH_HEALING_WAVE, ABILITY_TARGET_HEAL, 10000}, + {SPELL_SH_CHAIN_LIGHT, ABILITY_TARGET_ENEMY, 8000}}, + // 8 mage + {{SPELL_MG_FIREBALL, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_MG_FROSTBOLT, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_MG_ICE_LANCE, ABILITY_TARGET_SPECIAL, 2000}}, + // 9 warlock + {{SPELL_WL_CURSE_OF_DOOM, ABILITY_TARGET_ENEMY, 10000}, + {SPELL_WL_RAIN_OF_FIRE, ABILITY_TARGET_ENEMY, 10000}, + {SPELL_WL_UNSTABLE_AFFL, ABILITY_TARGET_ENEMY, 10000}}, + // 11 druid + {{SPELL_DR_LIFEBLOOM, ABILITY_TARGET_HEAL, 10000}, + {SPELL_DR_THORNS, ABILITY_TARGET_SELF, 10000}, + {SPELL_DR_MOONFIRE, ABILITY_TARGET_ENEMY, 8000}} +}; + +struct boss_hexlord_addAI : public ScriptedAI +{ + ScriptedInstance* pInstance; + + boss_hexlord_addAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() {} + + void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} + + void UpdateAI(const uint32 /*diff*/) + { + if (pInstance && pInstance->GetData(DATA_HEXLORDEVENT) != IN_PROGRESS) + { + EnterEvadeMode(); + return; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_hex_lord_malacrassAI : public ScriptedAI +{ + boss_hex_lord_malacrassAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + SelectAddEntry(); + for (uint8 i = 0; i < 4; ++i) + AddGUID[i] = 0; + } + + ScriptedInstance *pInstance; + + uint64 AddGUID[4]; + uint32 AddEntry[4]; + + uint64 PlayerGUID; + + uint32 SpiritBolts_Timer; + uint32 DrainPower_Timer; + uint32 SiphonSoul_Timer; + uint32 PlayerAbility_Timer; + uint32 CheckAddState_Timer; + uint32 ResetTimer; + + uint32 PlayerClass; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_HEXLORDEVENT, NOT_STARTED); + + SpiritBolts_Timer = 20000; + DrainPower_Timer = 60000; + SiphonSoul_Timer = 100000; + PlayerAbility_Timer = 99999; + CheckAddState_Timer = 5000; + ResetTimer = 5000; + + SpawnAdds(); + + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 46916); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HEXLORDEVENT, IN_PROGRESS); + + DoZoneInCombat(); + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_AGGRO); + + for (uint8 i = 0; i < 4; ++i) + { + Unit* Temp = Unit::GetUnit((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + CAST_CRE(Temp)->AI()->AttackStart(me->getVictim()); + else + { + EnterEvadeMode(); + break; + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,1)) + { + case 0: + me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); + break; + case 1: + me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); + break; + } + } + + void JustDied(Unit* /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_HEXLORDEVENT, DONE); + + me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_DEATH); + + for (uint8 i = 0; i < 4 ; ++i) + { + Unit* Temp = Unit::GetUnit((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + Temp->DealDamage(Temp, Temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void SelectAddEntry() + { + std::vector AddList; + + for (uint8 i = 0; i < 8; ++i) + AddList.push_back(AddEntryList[i]); + + while (AddList.size() > 4) + AddList.erase(AddList.begin()+rand()%AddList.size()); + + uint8 i = 0; + for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr, ++i) + AddEntry[i] = *itr; + } + + void SpawnAdds() + { + for (uint8 i = 0; i < 4; ++i) + { + Creature *pCreature = (Unit::GetCreature((*me), AddGUID[i])); + if (!pCreature || !pCreature->isAlive()) + { + if (pCreature) pCreature->setDeathState(DEAD); + pCreature = me->SummonCreature(AddEntry[i], Pos_X[i], POS_Y, POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0); + if (pCreature) AddGUID[i] = pCreature->GetGUID(); + } + else + { + pCreature->AI()->EnterEvadeMode(); + pCreature->GetMap()->CreatureRelocation(me, Pos_X[i], POS_Y, POS_Z, ORIENT); + pCreature->StopMoving(); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ResetTimer <= diff) + { + if (me->IsWithinDist3d(119.223, 1035.45, 29.4481, 10)) + { + EnterEvadeMode(); + return; + } + ResetTimer = 5000; + } else ResetTimer -= diff; + + if (CheckAddState_Timer <= diff) + { + for (uint8 i = 0; i < 4; ++i) + if (Creature *pTemp = Unit::GetCreature(*me, AddGUID[i])) + if (pTemp->isAlive() && !pTemp->getVictim()) + pTemp->AI()->AttackStart(me->getVictim()); + + CheckAddState_Timer = 5000; + } else CheckAddState_Timer -= diff; + + if (DrainPower_Timer <= diff) + { + DoCast(me, SPELL_DRAIN_POWER, true); + me->MonsterYell(YELL_DRAIN_POWER, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_DRAIN_POWER); + DrainPower_Timer = urand(40000,55000); // must cast in 60 sec, or buff/debuff will disappear + } else DrainPower_Timer -= diff; + + if (SpiritBolts_Timer <= diff) + { + if (DrainPower_Timer < 12000) // channel 10 sec + SpiritBolts_Timer = 13000; // cast drain power first + else + { + DoCast(me, SPELL_SPIRIT_BOLTS, false); + me->MonsterYell(YELL_SPIRIT_BOLTS, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_SPIRIT_BOLTS); + SpiritBolts_Timer = 40000; + SiphonSoul_Timer = 10000; // ready to drain + PlayerAbility_Timer = 99999; + } + } else SpiritBolts_Timer -= diff; + + if (SiphonSoul_Timer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 70, true); + Unit *trigger = DoSpawnCreature(MOB_TEMP_TRIGGER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); + if (!pTarget || !trigger) + { + EnterEvadeMode(); + return; + } + else + { + trigger->SetDisplayId(11686); + trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + trigger->CastSpell(pTarget, SPELL_SIPHON_SOUL, true); + trigger->GetMotionMaster()->MoveChase(me); + + //DoCast(pTarget, SPELL_SIPHON_SOUL, true); + //me->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pTarget->GetGUID()); + //me->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SIPHON_SOUL); + + PlayerGUID = pTarget->GetGUID(); + PlayerAbility_Timer = urand(8000,10000); + PlayerClass = pTarget->getClass() - 1; + + if (PlayerClass == CLASS_DRUID-1) + PlayerClass = CLASS_DRUID; + else if (PlayerClass == CLASS_PRIEST-1 && pTarget->HasSpell(15473)) + PlayerClass = CLASS_PRIEST; // shadow priest + + SiphonSoul_Timer = 99999; // buff lasts 30 sec + } + } else SiphonSoul_Timer -= diff; + + if (PlayerAbility_Timer <= diff) + { + //Unit *pTarget = Unit::GetUnit(*me, PlayerGUID); + //if (pTarget && pTarget->isAlive()) + //{ + UseAbility(); + PlayerAbility_Timer = urand(8000,10000); + //} + } else PlayerAbility_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + void UseAbility() + { + uint8 random = urand(0,2); + Unit *pTarget = NULL; + switch(PlayerAbility[PlayerClass][random].target) + { + case ABILITY_TARGET_SELF: + pTarget = me; + break; + case ABILITY_TARGET_VICTIM: + pTarget = me->getVictim(); + break; + case ABILITY_TARGET_ENEMY: + default: + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + break; + case ABILITY_TARGET_HEAL: + pTarget = DoSelectLowestHpFriendly(50, 0); + break; + case ABILITY_TARGET_BUFF: + { + std::list templist = DoFindFriendlyMissingBuff(50, PlayerAbility[PlayerClass][random].spell); + if (!templist.empty()) + pTarget = *(templist.begin()); + } + break; + } + if (pTarget) + DoCast(pTarget, PlayerAbility[PlayerClass][random].spell, false); + } +}; + +#define SPELL_BLOODLUST 43578 +#define SPELL_CLEAVE 15496 + +struct boss_thurgAI : public boss_hexlord_addAI +{ + + boss_thurgAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 bloodlust_timer; + uint32 cleave_timer; + + void Reset() + { + bloodlust_timer = 15000; + cleave_timer = 10000; + + boss_hexlord_addAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (bloodlust_timer <= diff) + { + std::list templist = DoFindFriendlyMissingBuff(50, SPELL_BLOODLUST); + if (!templist.empty()) + { + if (Unit *pTarget = *(templist.begin())) + DoCast(pTarget, SPELL_BLOODLUST, false); + } + bloodlust_timer = 12000; + } else bloodlust_timer -= diff; + + if (cleave_timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE, false); + cleave_timer = 12000; //3 sec cast + } else cleave_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_FLASH_HEAL 43575 +#define SPELL_DISPEL_MAGIC 43577 + +struct boss_alyson_antilleAI : public boss_hexlord_addAI +{ + //Holy Priest + boss_alyson_antilleAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 flashheal_timer; + uint32 dispelmagic_timer; + + void Reset() + { + flashheal_timer = 2500; + dispelmagic_timer = 10000; + + //AcquireGUID(); + + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (flashheal_timer <= diff) + { + Unit *pTarget = DoSelectLowestHpFriendly(99, 30000); + if (pTarget) + { + if (pTarget->IsWithinDistInMap(me, 50)) + DoCast(pTarget, SPELL_FLASH_HEAL, false); + else + { + // bugged + //me->GetMotionMaster()->Clear(); + //me->GetMotionMaster()->MoveChase(pTarget, 20); + } + } + else + { + if (urand(0,1)) + pTarget = DoSelectLowestHpFriendly(50, 0); + else + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_DISPEL_MAGIC, false); + } + flashheal_timer = 2500; + } else flashheal_timer -= diff; + + /*if (dispelmagic_timer <= diff) + { + if (urand(0,1)) + { + Unit *pTarget = SelectTarget(); + + DoCast(pTarget, SPELL_DISPEL_MAGIC, false); + } + else + me->CastSpell(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DISPEL_MAGIC, false); + + dispelmagic_timer = 12000; + } else dispelmagic_timer -= diff;*/ + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_FIREBOLT 43584 + +struct boss_gazakrothAI : public boss_hexlord_addAI +{ + boss_gazakrothAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 firebolt_timer; + + void Reset() + { + firebolt_timer = 2000; + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (firebolt_timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBOLT, false); + firebolt_timer = 700; + } else firebolt_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_FLAME_BREATH 43582 +#define SPELL_THUNDERCLAP 43583 + +struct boss_lord_raadanAI : public boss_hexlord_addAI +{ + boss_lord_raadanAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 flamebreath_timer; + uint32 thunderclap_timer; + + void Reset() + { + flamebreath_timer = 8000; + thunderclap_timer = 13000; + + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (thunderclap_timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP, false); + thunderclap_timer = 12000; + } else thunderclap_timer -= diff; + + if (flamebreath_timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAME_BREATH, false); + flamebreath_timer = 12000; + } else flamebreath_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_PSYCHIC_WAIL 43590 + +struct boss_darkheartAI : public boss_hexlord_addAI +{ + boss_darkheartAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 psychicwail_timer; + + void Reset() + { + psychicwail_timer = 8000; + boss_hexlord_addAI::Reset(); + } + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (psychicwail_timer <= diff) + { + DoCast(me->getVictim(), SPELL_PSYCHIC_WAIL, false); + psychicwail_timer = 12000; + } else psychicwail_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_VENOM_SPIT 43579 + +struct boss_slitherAI : public boss_hexlord_addAI +{ + boss_slitherAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 venomspit_timer; + + void Reset() + { + venomspit_timer = 5000; + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (venomspit_timer <= diff) + { + if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(victim, SPELL_VENOM_SPIT, false); + venomspit_timer = 2500; + } else venomspit_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +//Fenstalker +#define SPELL_VOLATILE_INFECTION 43586 + +struct boss_fenstalkerAI : public boss_hexlord_addAI +{ + boss_fenstalkerAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 volatileinf_timer; + + void Reset() + { + volatileinf_timer = 15000; + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (volatileinf_timer <= diff) + { + // core bug + me->getVictim()->CastSpell(me->getVictim(),SPELL_VOLATILE_INFECTION, false); + volatileinf_timer = 12000; + } else volatileinf_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +//Koragg +#define SPELL_COLD_STARE 43593 +#define SPELL_MIGHTY_BLOW 43592 + +struct boss_koraggAI : public boss_hexlord_addAI +{ + boss_koraggAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 coldstare_timer; + uint32 mightyblow_timer; + + void Reset() + { + coldstare_timer = 15000; + mightyblow_timer = 10000; + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (mightyblow_timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, false); + mightyblow_timer = 12000; + } + if (coldstare_timer <= diff) + { + if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(victim, SPELL_COLD_STARE, false); + coldstare_timer = 12000; + } + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_boss_hex_lord_malacrass(Creature* pCreature) +{ + return new boss_hex_lord_malacrassAI (pCreature); +} + +CreatureAI* GetAI_boss_thurg(Creature* pCreature) +{ + return new boss_thurgAI (pCreature); +} + +CreatureAI* GetAI_boss_alyson_antille(Creature* pCreature) +{ + return new boss_alyson_antilleAI (pCreature); +} + +CreatureAI* GetAI_boss_gazakroth(Creature* pCreature) +{ + return new boss_gazakrothAI (pCreature); +} + +CreatureAI* GetAI_boss_lord_raadan(Creature* pCreature) +{ + return new boss_lord_raadanAI (pCreature); +} + +CreatureAI* GetAI_boss_darkheart(Creature* pCreature) +{ + return new boss_darkheartAI (pCreature); +} + +CreatureAI* GetAI_boss_slither(Creature* pCreature) +{ + return new boss_slitherAI (pCreature); +} + +CreatureAI* GetAI_boss_fenstalker(Creature* pCreature) +{ + return new boss_fenstalkerAI (pCreature); +} + +CreatureAI* GetAI_boss_koragg(Creature* pCreature) +{ + return new boss_koraggAI (pCreature); +} +void AddSC_boss_hex_lord_malacrass() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hexlord_malacrass"; + newscript->GetAI = &GetAI_boss_hex_lord_malacrass; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_thurg"; + newscript->GetAI = &GetAI_boss_thurg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_gazakroth"; + newscript->GetAI = &GetAI_boss_gazakroth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_raadan"; + newscript->GetAI = &GetAI_boss_lord_raadan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_darkheart"; + newscript->GetAI = &GetAI_boss_darkheart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_slither"; + newscript->GetAI = &GetAI_boss_slither; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fenstalker"; + newscript->GetAI = &GetAI_boss_fenstalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_koragg"; + newscript->GetAI = &GetAI_boss_koragg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_alyson_antille"; + newscript->GetAI = &GetAI_boss_alyson_antille; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp new file mode 100644 index 00000000000..9ac54976241 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp @@ -0,0 +1,687 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +*(at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Janalai +SD%Complete: 100 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" +#include "GridNotifiers.h" + +enum eEnums +{ + SAY_AGGRO = -1568000, + SAY_FIRE_BOMBS = -1568001, + SAY_SUMMON_HATCHER = -1568002, + SAY_ALL_EGGS = -1568003, + SAY_BERSERK = -1568004, + SAY_SLAY_1 = -1568005, + SAY_SLAY_2 = -1568006, + SAY_DEATH = -1568007, + SAY_EVENT_STRANGERS = -1568008, + SAY_EVENT_FRIENDS = -1568009, + +// Jan'alai + SPELL_FLAME_BREATH = 43140, + SPELL_FIRE_WALL = 43113, + SPELL_ENRAGE = 44779, + SPELL_SUMMON_PLAYERS = 43097, + SPELL_TELE_TO_CENTER = 43098, // coord + SPELL_HATCH_ALL = 43144, + SPELL_BERSERK = 45078, + +// -- Fire Bob Spells + SPELL_FIRE_BOMB_CHANNEL = 42621, // last forever + SPELL_FIRE_BOMB_THROW = 42628, // throw visual + SPELL_FIRE_BOMB_DUMMY = 42629, // bomb visual + SPELL_FIRE_BOMB_DAMAGE = 42630, + +// --Summons + MOB_AMANI_HATCHER = 23818, + MOB_HATCHLING = 23598, // 42493 + MOB_EGG = 23817, + MOB_FIRE_BOMB = 23920, + +// -- Hatcher Spells + SPELL_HATCH_EGG = 43734, // 42471 + +// -- Hatchling Spells + SPELL_FLAMEBUFFET = 43299 +}; + +const int area_dx = 44; +const int area_dy = 51; + +float JanalainPos[1][3] = +{ + {-33.93, 1149.27, 19} +}; + +float FireWallCoords[4][4] = +{ + {-10.13, 1149.27, 19, 3.1415}, + {-33.93, 1123.90, 19, 0.5*3.1415}, + {-54.80, 1150.08, 19, 0}, + {-33.93, 1175.68, 19, 1.5*3.1415} +}; + +float hatcherway[2][5][3] = +{ + { + {-87.46,1170.09,6}, + {-74.41,1154.75,6}, + {-52.74,1153.32,19}, + {-33.37,1172.46,19}, + {-33.09,1203.87,19} + }, + { + {-86.57,1132.85,6}, + {-73.94,1146.00,6}, + {-52.29,1146.51,19}, + {-33.57,1125.72,19}, + {-34.29,1095.22,19} + } +}; + +struct boss_janalaiAI : public ScriptedAI +{ + boss_janalaiAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + + SpellEntry *TempSpell = GET_SPELL(SPELL_HATCH_EGG); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) + { + TempSpell->EffectImplicitTargetA[0] = 1; + TempSpell->EffectImplicitTargetB[0] = 0; + } + } + + ScriptedInstance *pInstance; + + uint32 FireBreathTimer; + uint32 BombTimer; + uint32 BombSequenceTimer; + uint32 BombCount; + uint32 HatcherTimer; + uint32 EnrageTimer; + + bool noeggs; + bool enraged; + bool isBombing; + + bool isFlameBreathing; + + uint64 FireBombGUIDs[40]; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_JANALAIEVENT, NOT_STARTED); + + FireBreathTimer = 8000; + BombTimer = 30000; + BombSequenceTimer = 1000; + BombCount = 0; + HatcherTimer = 10000; + EnrageTimer = MINUTE*5*IN_MILISECONDS; + + noeggs = false; + isBombing =false; + enraged = false; + + isFlameBreathing = false; + + for (uint8 i = 0; i < 40; ++i) + FireBombGUIDs[i] = 0; + + HatchAllEggs(1); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_JANALAIEVENT, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_JANALAIEVENT, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, me); +// DoZoneInCombat(); + } + + void DamageDeal(Unit *pTarget, uint32 &damage) + { + if (isFlameBreathing) + { + if (!me->HasInArc(M_PI/6, pTarget)) + damage = 0; + } + } + + void FireWall() + { + uint8 WallNum; + Creature* wall = NULL; + for (uint8 i = 0; i < 4; ++i) + { + if (i == 0 || i == 2) + WallNum = 3; + else + WallNum = 2; + + for (uint8 j = 0; j < WallNum; j++) + { + if (WallNum == 3) + wall = me->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0],FireWallCoords[i][1]+5*(j-1),FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000); + else + wall = me->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0]-2+4*j,FireWallCoords[i][1],FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000); + if (wall) wall->CastSpell(wall, SPELL_FIRE_WALL, true); + } + } + } + + void SpawnBombs() + { + float dx, dy; + for (int i(0); i < 40; ++i) + { + dx = irand(-area_dx/2, area_dx/2); + dy = irand(-area_dy/2, area_dy/2); + + Creature* bomb = DoSpawnCreature(MOB_FIRE_BOMB, dx, dy, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); + if (bomb) FireBombGUIDs[i] = bomb->GetGUID(); + } + BombCount = 0; + } + + bool HatchAllEggs(uint32 uiAction) //1: reset, 2: isHatching all + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllCreaturesOfEntryInRange check(me, MOB_EGG, 100); + Trinity::CreatureListSearcher searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap())); + } + + //error_log("Eggs %d at middle", templist.size()); + if (!templist.size()) + return false; + + for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) + { + if (uiAction == 1) + (*i)->SetDisplayId(10056); + else if (uiAction == 2 &&(*i)->GetDisplayId() != 11686) + (*i)->CastSpell(*i, SPELL_HATCH_EGG, false); + } + return true; + } + + void Boom() + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllCreaturesOfEntryInRange check(me, MOB_FIRE_BOMB, 100); + Trinity::CreatureListSearcher searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap())); + } + for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) + { + (*i)->CastSpell(*i, SPELL_FIRE_BOMB_DAMAGE, true); + (*i)->RemoveAllAuras(); + } + } + + void HandleBombSequence() + { + if (BombCount < 40) + { + if (Unit *FireBomb = Unit::GetUnit((*me), FireBombGUIDs[BombCount])) + { + FireBomb->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(FireBomb, SPELL_FIRE_BOMB_THROW, true); + FireBomb->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + ++BombCount; + if (BombCount == 40) + { + BombSequenceTimer = 5000; + } else BombSequenceTimer = 100; + } + else + { + Boom(); + isBombing = false; + BombTimer = urand(20000,40000); + me->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_CHANNEL); + if (EnrageTimer <= 10000) + EnrageTimer = 0; + else + EnrageTimer -= 10000; + } + } + + void UpdateAI(const uint32 diff) + { + if (isFlameBreathing) + { + if (!me->IsNonMeleeSpellCasted(false)) + isFlameBreathing = false; + else + return; + } + + if (isBombing) + { + if (BombSequenceTimer <= diff) + HandleBombSequence(); + else + BombSequenceTimer -= diff; + return; + } + + if (!UpdateVictim()) + return; + + //enrage if under 25% hp before 5 min. + if (!enraged && me->GetHealth() * 4 < me->GetMaxHealth()) + EnrageTimer = 0; + + if (EnrageTimer <= diff) + { + if (!enraged) + { + DoCast(me, SPELL_ENRAGE, true); + enraged = true; + EnrageTimer = 300000; + } + else + { + DoScriptText(SAY_BERSERK, me); + DoCast(me, SPELL_BERSERK, true); + EnrageTimer = 300000; + } + } else EnrageTimer -= diff; + + if (BombTimer <= diff) + { + DoScriptText(SAY_FIRE_BOMBS, me); + + me->AttackStop(); + me->GetMotionMaster()->Clear(); + DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); + me->StopMoving(); + DoCast(me, SPELL_FIRE_BOMB_CHANNEL, false); + //DoTeleportPlayer(me, JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2], 0); + //DoCast(me, SPELL_TELE_TO_CENTER, true); + + FireWall(); + SpawnBombs(); + isBombing = true; + BombSequenceTimer = 100; + + //Teleport every Player into the middle + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) return; + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* i_pl = i->getSource()) + if (i_pl->isAlive()) + DoTeleportPlayer(i_pl, JanalainPos[0][0]-5+rand()%10, JanalainPos[0][1]-5+rand()%10, JanalainPos[0][2], 0); + //DoCast(Temp, SPELL_SUMMON_PLAYERS, true) // core bug, spell does not work if too far + return; + } else BombTimer -= diff; + + if (!noeggs) + { + if (100 * me->GetHealth() < 35 * me->GetMaxHealth()) + { + DoScriptText(SAY_ALL_EGGS, me); + + me->AttackStop(); + me->GetMotionMaster()->Clear(); + DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); + me->StopMoving(); + DoCast(me, SPELL_HATCH_ALL, false); + HatchAllEggs(2); + noeggs = true; + } + else if (HatcherTimer <= diff) + { + if (HatchAllEggs(0)) + { + DoScriptText(SAY_SUMMON_HATCHER, me); + me->SummonCreature(MOB_AMANI_HATCHER,hatcherway[0][0][0],hatcherway[0][0][1],hatcherway[0][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); + me->SummonCreature(MOB_AMANI_HATCHER,hatcherway[1][0][0],hatcherway[1][0][1],hatcherway[1][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); + HatcherTimer = 90000; + } + else + noeggs = true; + } else HatcherTimer -= diff; + } + + EnterEvadeIfOutOfCombatArea(diff); + + DoMeleeAttackIfReady(); + + if (FireBreathTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + me->AttackStop(); + me->GetMotionMaster()->Clear(); + DoCast(pTarget, SPELL_FLAME_BREATH, false); + me->StopMoving(); + isFlameBreathing = true; + } + FireBreathTimer = 8000; + } else FireBreathTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_janalaiAI(Creature* pCreature) +{ + return new boss_janalaiAI(pCreature); +} + +struct mob_janalai_firebombAI : public ScriptedAI +{ + mob_janalai_firebombAI(Creature *c) : ScriptedAI(c){} + + void Reset() {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_FIRE_BOMB_THROW) + DoCast(me, SPELL_FIRE_BOMB_DUMMY, true); + } + + void EnterCombat(Unit* /*who*/) {} + + void AttackStart(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_mob_janalai_firebombAI(Creature* pCreature) +{ + return new mob_janalai_firebombAI(pCreature); +} + +struct mob_amanishi_hatcherAI : public ScriptedAI +{ + mob_amanishi_hatcherAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 waypoint; + uint32 HatchNum; + uint32 WaitTimer; + + bool side; + bool hasChangedSide; + bool isHatching; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + side =(me->GetPositionY() < 1150); + waypoint = 0; + isHatching = false; + hasChangedSide = false; + WaitTimer = 1; + HatchNum = 0; + } + + bool HatchEggs(uint32 num) + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllCreaturesOfEntryInRange check(me, 23817, 50); + Trinity::CreatureListSearcher searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap())); + } + + //error_log("Eggs %d at %d", templist.size(), side); + + for (std::list::const_iterator i = templist.begin(); i != templist.end() && num > 0; ++i) + if ((*i)->GetDisplayId() != 11686) + { + (*i)->CastSpell(*i, SPELL_HATCH_EGG, false); + num--; + } + + return num == 0; // if num == 0, no more templist + } + + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void MovementInform(uint32, uint32) + { + if (waypoint == 5) + { + isHatching = true; + HatchNum = 1; + WaitTimer = 5000; + } + else + WaitTimer = 1; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance || !(pInstance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS)) + { + me->DisappearAndDie(); + return; + } + + if (!isHatching) + { + if (WaitTimer) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,hatcherway[side][waypoint][0],hatcherway[side][waypoint][1],hatcherway[side][waypoint][2]); + ++waypoint; + WaitTimer = 0; + } + } + else + { + if (WaitTimer <= diff) + { + if (HatchEggs(HatchNum)) + { + ++HatchNum; + WaitTimer = 10000; + } + else if (!hasChangedSide) + { + side = side ? 0 : 1; + isHatching = false; + waypoint = 3; + WaitTimer = 1; + hasChangedSide = true; + } + else + me->DisappearAndDie(); + + } else WaitTimer -= diff; + } + } +}; + +CreatureAI* GetAI_mob_amanishi_hatcherAI(Creature* pCreature) +{ + return new mob_amanishi_hatcherAI(pCreature); +} + +struct mob_hatchlingAI : public ScriptedAI +{ + mob_hatchlingAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 BuffetTimer; + + void Reset() + { + BuffetTimer = 7000; + if (me->GetPositionY() > 1150) + me->GetMotionMaster()->MovePoint(0, hatcherway[0][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[0][3][2]); + else + me->GetMotionMaster()->MovePoint(0,hatcherway[1][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[1][3][2]); + + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + } + + void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/} + + void UpdateAI(const uint32 diff) + { + if (!pInstance || !(pInstance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS)) + { + me->DisappearAndDie(); + return; + } + + if (!UpdateVictim()) + return; + + if (BuffetTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBUFFET, false); + BuffetTimer = 10000; + } else BuffetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_hatchlingAI(Creature* pCreature) +{ + return new mob_hatchlingAI(pCreature); +} + +struct mob_eggAI : public ScriptedAI +{ + mob_eggAI(Creature *c) : ScriptedAI(c){} + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_HATCH_EGG) + { + DoSpawnCreature(MOB_HATCHLING, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + me->SetDisplayId(11686); + } + } +}; + +CreatureAI* GetAI_mob_eggAI(Creature* pCreature) +{ + return new mob_eggAI(pCreature); +} + +void AddSC_boss_janalai() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_janalai"; + newscript->GetAI = &GetAI_boss_janalaiAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_janalai_firebomb"; + newscript->GetAI = &GetAI_mob_janalai_firebombAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_janalai_hatcher"; + newscript->GetAI = &GetAI_mob_amanishi_hatcherAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_janalai_hatchling"; + newscript->GetAI = &GetAI_mob_hatchlingAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_janalai_egg"; + newscript->GetAI = &GetAI_mob_eggAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp new file mode 100644 index 00000000000..ae5c6596d2d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp @@ -0,0 +1,451 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Nalorakk +SD%Complete: 100 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" +#include "GridNotifiers.h" + +//Trash Waves +float NalorakkWay[8][3] = +{ + { 18.569, 1414.512, 11.42},// waypoint 1 + {-17.264, 1419.551, 12.62}, + {-52.642, 1419.357, 27.31},// waypoint 2 + {-69.908, 1419.721, 27.31}, + {-79.929, 1395.958, 27.31}, + {-80.072, 1374.555, 40.87},// waypoint 3 + {-80.072, 1314.398, 40.87}, + {-80.072, 1295.775, 48.60} // waypoint 4 +}; + +#define YELL_NALORAKK_WAVE1 "Get da move on, guards! It be killin' time!" +#define SOUND_NALORAKK_WAVE1 12066 +#define YELL_NALORAKK_WAVE2 "Guards, go already! Who you more afraid of, dem... or me?" +#define SOUND_NALORAKK_WAVE2 12067 +#define YELL_NALORAKK_WAVE3 "Ride now! Ride out dere and bring me back some heads!" +#define SOUND_NALORAKK_WAVE3 12068 +#define YELL_NALORAKK_WAVE4 "I be losin' me patience! Go on: make dem wish dey was never born!" +#define SOUND_NALORAKK_WAVE4 12069 + +//Unimplemented SoundIDs +/* +#define SOUND_NALORAKK_EVENT1 12078 +#define SOUND_NALORAKK_EVENT2 12079 +*/ + +//General defines +#define YELL_AGGRO "You be dead soon enough!" +#define SOUND_YELL_AGGRO 12070 +#define YELL_KILL_ONE "Mua-ha-ha! Now whatchoo got to say?" +#define SOUND_YELL_KILL_ONE 12075 +#define YELL_KILL_TWO "Da Amani gonna rule again!" +#define SOUND_YELL_KILL_TWO 12076 +#define YELL_DEATH "I... be waitin' on da udda side...." +#define SOUND_YELL_DEATH 12077 +#define YELL_BERSERK "You had your chance, now it be too late!" //Never seen this being used, so just guessing from what I hear. +#define SOUND_YELL_BERSERK 12074 + +#define SPELL_BERSERK 45078 + +//Defines for Troll form +#define SPELL_BRUTALSWIPE 42384 +#define SPELL_MANGLE 42389 +#define SPELL_MANGLEEFFECT 44955 +#define SPELL_SURGE 42402 +#define SPELL_BEARFORM 42377 + +#define YELL_SURGE "I bring da pain!" +#define SOUND_YELL_SURGE 12071 + +#define YELL_SHIFTEDTOTROLL "Make way for Nalorakk!" +#define SOUND_YELL_TOTROLL 12073 + +//Defines for Bear form +#define SPELL_LACERATINGSLASH 42395 +#define SPELL_RENDFLESH 42397 +#define SPELL_DEAFENINGROAR 42398 + +#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!" +#define SOUND_YELL_TOBEAR 12072 + +struct boss_nalorakkAI : public ScriptedAI +{ + boss_nalorakkAI(Creature *c) : ScriptedAI(c) + { + MoveEvent = true; + MovePhase = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 BrutalSwipe_Timer; + uint32 Mangle_Timer; + uint32 Surge_Timer; + + uint32 LaceratingSlash_Timer; + uint32 RendFlesh_Timer; + uint32 DeafeningRoar_Timer; + + uint32 ShapeShift_Timer; + uint32 Berserk_Timer; + + bool inBearForm; + bool MoveEvent; + bool inMove; + uint32 MovePhase; + uint32 waitTimer; + + void Reset() + { + if (MoveEvent) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + inMove = false; + waitTimer = 0; + me->SetSpeed(MOVE_RUN,2); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + }else + { + (*me).GetMotionMaster()->MovePoint(0,NalorakkWay[7][0],NalorakkWay[7][1],NalorakkWay[7][2]); + } + + if (pInstance) + pInstance->SetData(DATA_NALORAKKEVENT, NOT_STARTED); + + Surge_Timer = 15000 + rand()%5000; + BrutalSwipe_Timer = 7000 + rand()%5000; + Mangle_Timer = 10000 + rand()%5000; + ShapeShift_Timer = 45000 + rand()%5000; + Berserk_Timer = 600000; + + inBearForm = false; + // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); // TODO: find the correct equipment id + } + + void SendAttacker(Unit *pTarget) + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllFriendlyCreaturesInGrid check(me); + Trinity::CreatureListSearcher searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap())); + } + + if (!templist.size()) + return; + + for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) + { + if ((*i) && me->IsWithinDistInMap((*i),25)) + { + (*i)->SetNoCallAssistance(true); + (*i)->AI()->AttackStart(pTarget); + } + } + } + + void AttackStart(Unit* who) + { + if (!MoveEvent) + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (!MoveEvent) + { + ScriptedAI::MoveInLineOfSight(who); + } + else + { + if (me->IsHostileTo(who)) + { + if (!inMove) + { + switch(MovePhase) + { + case 0: + if (me->IsWithinDistInMap(who, 50)) + { + me->MonsterYell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1); + + (*me).GetMotionMaster()->MovePoint(1,NalorakkWay[1][0],NalorakkWay[1][1],NalorakkWay[1][2]); + MovePhase ++; + inMove = true; + + SendAttacker(who); + } + break; + case 2: + if (me->IsWithinDistInMap(who, 40)) + { + me->MonsterYell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2); + + (*me).GetMotionMaster()->MovePoint(3,NalorakkWay[3][0],NalorakkWay[3][1],NalorakkWay[3][2]); + MovePhase ++; + inMove = true; + + SendAttacker(who); + } + break; + case 5: + if (me->IsWithinDistInMap(who, 40)) + { + me->MonsterYell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3); + + (*me).GetMotionMaster()->MovePoint(6,NalorakkWay[6][0],NalorakkWay[6][1],NalorakkWay[6][2]); + MovePhase ++; + inMove = true; + + SendAttacker(who); + } + break; + case 7: + if (me->IsWithinDistInMap(who, 50)) + { + SendAttacker(who); + + me->MonsterYell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + MoveEvent = false; + } + break; + } + } + } + } + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS); + + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_AGGRO); + DoZoneInCombat(); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_NALORAKKEVENT, DONE); + + me->MonsterYell(YELL_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me, SOUND_YELL_DEATH); + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,1)) + { + case 0: + me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); + break; + case 1: + me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); + break; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (MoveEvent) + { + if (type != POINT_MOTION_TYPE) + return; + + if (!inMove) + return; + + if (MovePhase != id) + return; + + switch(MovePhase) + { + case 2: + me->SetOrientation(3.1415*2); + inMove = false; + return; + case 1: + case 3: + case 4: + case 6: + MovePhase ++; + waitTimer = 1; + inMove = true; + return; + case 5: + me->SetOrientation(3.1415*0.5); + inMove = false; + return; + case 7: + me->SetOrientation(3.1415*0.5); + inMove = false; + return; + } + + } + } + + void UpdateAI(const uint32 diff) + { + if (waitTimer) + { + if (inMove) + if (waitTimer <= diff) + { + (*me).GetMotionMaster()->MovementExpired(); + (*me).GetMotionMaster()->MovePoint(MovePhase,NalorakkWay[MovePhase][0],NalorakkWay[MovePhase][1],NalorakkWay[MovePhase][2]); + waitTimer = 0; + } else waitTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_BERSERK); + Berserk_Timer = 600000; + } else Berserk_Timer -= diff; + + if (ShapeShift_Timer <= diff) + { + if (inBearForm) + { + // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); + me->MonsterYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_TOTROLL); + me->RemoveAurasDueToSpell(SPELL_BEARFORM); + Surge_Timer = 15000 + rand()%5000; + BrutalSwipe_Timer = 7000 + rand()%5000; + Mangle_Timer = 10000 + rand()%5000; + ShapeShift_Timer = 45000 + rand()%5000; + inBearForm = false; + } + else + { + // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0); + me->MonsterYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_TOBEAR); + DoCast(me, SPELL_BEARFORM, true); + LaceratingSlash_Timer = 2000; // dur 18s + RendFlesh_Timer = 3000; // dur 5s + DeafeningRoar_Timer = 5000 + rand()%5000; // dur 2s + ShapeShift_Timer = 20000 + rand()%5000; // dur 30s + inBearForm = true; + } + } else ShapeShift_Timer -= diff; + + if (!inBearForm) + { + if (BrutalSwipe_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BRUTALSWIPE); + BrutalSwipe_Timer = 7000 + rand()%5000; + } else BrutalSwipe_Timer -= diff; + + if (Mangle_Timer <= diff) + { + if (me->getVictim() && !me->getVictim()->HasAura(SPELL_MANGLEEFFECT)) + { + DoCast(me->getVictim(), SPELL_MANGLE); + Mangle_Timer = 1000; + } + else Mangle_Timer = 10000 + rand()%5000; + } else Mangle_Timer -= diff; + + if (Surge_Timer <= diff) + { + me->MonsterYell(YELL_SURGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_SURGE); + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true); + if (pTarget) + DoCast(pTarget, SPELL_SURGE); + Surge_Timer = 15000 + rand()%5000; + } else Surge_Timer -= diff; + } + else + { + if (LaceratingSlash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LACERATINGSLASH); + LaceratingSlash_Timer = 18000 + rand()%5000; + } else LaceratingSlash_Timer -= diff; + + if (RendFlesh_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_RENDFLESH); + RendFlesh_Timer = 5000 + rand()%5000; + } else RendFlesh_Timer -= diff; + + if (DeafeningRoar_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DEAFENINGROAR); + DeafeningRoar_Timer = 15000 + rand()%5000; + } else DeafeningRoar_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nalorakk(Creature* pCreature) +{ + return new boss_nalorakkAI (pCreature); +} + +void AddSC_boss_nalorakk() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nalorakk"; + newscript->GetAI = &GetAI_boss_nalorakk; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp new file mode 100644 index 00000000000..91cfa728f89 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp @@ -0,0 +1,623 @@ +/* Copyright (C) 2006,2007,2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_ZulJin +SD%Complete: 85% +SDComment: +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" + +//Speech +#define YELL_TRANSFORM_TO_LYNX "Let me introduce to you my new bruddahs: fang and claw!" +#define SOUND_TRANSFORM_TO_LYNX 12094 + +#define YELL_TRANSFORM_TO_BEAR "Got me some new tricks...like me bruddah bear!" +#define SOUND_TRANSFORM_TO_BEAR 12092 + +#define YELL_TRANSFORM_TO_DRAGONHAWK "Ya don' have to look to da sky to see da dragonhawk!" +#define SOUND_TRANSFORM_TO_DRAGONHAWK 12095 + +#define YELL_TRANSFORM_TO_EAGLE "Dere be no hidin' from da eagle!" +#define SOUND_TRANSFORM_TO_EAGLE 12093 + +#define YELL_KILL_ONE "Da Amani de chuka!" +#define SOUND_KILL_ONE 12098 + +#define YELL_KILL_TWO "Lot more gonna fall like you!" +#define SOUND_KILL_TWO 12099 + +#define YELL_FIRE_BREATH "Fire kill you just as quick!" +#define SOUND_FIRE_BRETH 12096 + +#define YELL_AGGRO "Nobody badduh dan me!" +#define SOUND_AGGRO 12091 + +#define YELL_BERSERK "You too slow! Me too strong!" +#define SOUND_BERSERK 12097 + +#define YELL_DEATH "Mebbe me fall...but da Amani empire...never gonna die..." +#define SOUND_DEATH 12100 + +//Still not used, need more info +#define YELL_INTRO "Everybody always wanna take from us. Now we gonna start takin' back. Anybody who get in our way...gonna drown in their own blood! De Amani empire be back now...seekin' vengeance. And we gonna start...with you!" +#define SOUND_INTRO 12090 + +//Spells: +//====== Troll Form +#define SPELL_WHIRLWIND 17207 +#define SPELL_GRIEVOUS_THROW 43093 // remove debuff after full healed +//====== Bear Form +#define SPELL_CREEPING_PARALYSIS 43095 // should cast on the whole raid +#define SPELL_OVERPOWER 43456 // use after melee attack dodged +//====== Eagle Form +#define SPELL_ENERGY_STORM 43983 // enemy area aura, trigger 42577 +#define SPELL_ZAP_INFORM 42577 +#define SPELL_ZAP_DAMAGE 43137 // 1250 damage +#define SPELL_SUMMON_CYCLONE 43112 // summon four feather vortex +#define CREATURE_FEATHER_VORTEX 24136 +#define SPELL_CYCLONE_VISUAL 43119 // trigger 43147 visual +#define SPELL_CYCLONE_PASSIVE 43120 // trigger 43121 (4y aoe) every second +//Lynx Form +#define SPELL_CLAW_RAGE_HASTE 42583 +#define SPELL_CLAW_RAGE_TRIGGER 43149 +#define SPELL_CLAW_RAGE_DAMAGE 43150 +#define SPELL_LYNX_RUSH_HASTE 43152 +#define SPELL_LYNX_RUSH_DAMAGE 43153 +//Dragonhawk Form +#define SPELL_FLAME_WHIRL 43213 // trigger two spells +#define SPELL_FLAME_BREATH 43215 +#define SPELL_SUMMON_PILLAR 43216 // summon 24187 +#define CREATURE_COLUMN_OF_FIRE 24187 +#define SPELL_PILLAR_TRIGGER 43218 // trigger 43217 + +//cosmetic +#define SPELL_SPIRIT_AURA 42466 +#define SPELL_SIPHON_SOUL 43501 + +//Transforms: +#define SPELL_SHAPE_OF_THE_BEAR 42594 // 15% dmg +#define SPELL_SHAPE_OF_THE_EAGLE 42606 +#define SPELL_SHAPE_OF_THE_LYNX 42607 // haste melee 30% +#define SPELL_SHAPE_OF_THE_DRAGONHAWK 42608 + +#define SPELL_BERSERK 45078 + +#define PHASE_BEAR 0 +#define PHASE_EAGLE 1 +#define PHASE_LYNX 2 +#define PHASE_DRAGONHAWK 3 +#define PHASE_TROLL 4 + +//coords for going for changing form +#define CENTER_X 120.148811 +#define CENTER_Y 703.713684 +#define CENTER_Z 45.111477 + +struct SpiritInfoStruct +{ + uint32 entry; + float x, y, z, orient; +}; + +static SpiritInfoStruct SpiritInfo[] = +{ + {23878, 147.87, 706.51, 45.11, 3.04}, + {23880, 88.95, 705.49, 45.11, 6.11}, + {23877, 137.23, 725.98, 45.11, 3.71}, + {23879, 104.29, 726.43, 45.11, 5.43} +}; + +struct TransformStruct +{ + uint32 sound; + char* text; + uint32 spell, unaura; +}; + +static TransformStruct Transform[] = +{ + {SOUND_TRANSFORM_TO_BEAR, YELL_TRANSFORM_TO_BEAR, SPELL_SHAPE_OF_THE_BEAR, SPELL_WHIRLWIND}, + {SOUND_TRANSFORM_TO_EAGLE, YELL_TRANSFORM_TO_EAGLE, SPELL_SHAPE_OF_THE_EAGLE, SPELL_SHAPE_OF_THE_BEAR}, + {SOUND_TRANSFORM_TO_LYNX, YELL_TRANSFORM_TO_LYNX, SPELL_SHAPE_OF_THE_LYNX, SPELL_SHAPE_OF_THE_EAGLE}, + {SOUND_TRANSFORM_TO_DRAGONHAWK, YELL_TRANSFORM_TO_DRAGONHAWK, SPELL_SHAPE_OF_THE_DRAGONHAWK, SPELL_SHAPE_OF_THE_LYNX} +}; + +struct boss_zuljinAI : public ScriptedAI +{ + boss_zuljinAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + ScriptedInstance *pInstance; + + uint64 SpiritGUID[4]; + uint64 ClawTargetGUID; + uint64 TankGUID; + + uint32 Phase; + uint32 health_20; + + uint32 Intro_Timer; + uint32 Berserk_Timer; + + uint32 Whirlwind_Timer; + uint32 Grievous_Throw_Timer; + + uint32 Creeping_Paralysis_Timer; + uint32 Overpower_Timer; + + uint32 Claw_Rage_Timer; + uint32 Lynx_Rush_Timer; + uint32 Claw_Counter; + uint32 Claw_Loop_Timer; + + uint32 Flame_Whirl_Timer; + uint32 Flame_Breath_Timer; + uint32 Pillar_Of_Fire_Timer; + + SummonList Summons; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_ZULJINEVENT, NOT_STARTED); + + Phase = 0; + + health_20 = me->GetMaxHealth()*0.2; + + Intro_Timer = 37000; + Berserk_Timer = 600000; + + Whirlwind_Timer = 7000; + Grievous_Throw_Timer = 8000; + + Creeping_Paralysis_Timer = 7000; + Overpower_Timer = 0; + + Claw_Rage_Timer = 5000; + Lynx_Rush_Timer = 14000; + Claw_Loop_Timer = 0; + Claw_Counter = 0; + + Flame_Whirl_Timer = 5000; + Flame_Breath_Timer = 6000; + Pillar_Of_Fire_Timer = 7000; + + ClawTargetGUID = 0; + TankGUID = 0; + + Summons.DespawnAll(); + + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 47174); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674); + //me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_ZULJINEVENT, IN_PROGRESS); + + DoZoneInCombat(); + + me->MonsterYell(YELL_INTRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me, SOUND_INTRO); + SpawnAdds(); + EnterPhase(0); + } + + void KilledUnit(Unit* /*victim*/) + { + if (Intro_Timer) + return; + + switch (urand(0,1)) + { + case 0: + me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL_ONE); + break; + case 1: + me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL_TWO); + break; + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ZULJINEVENT, DONE); + + me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_DEATH); + Summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE); + + if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[3])) + Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); + } + + void AttackStart(Unit *who) + { + if (Phase == 2) + AttackStartNoMove(who); + else + ScriptedAI::AttackStart(who); + } + + void DoMeleeAttackIfReady() + { + if (!me->IsNonMeleeSpellCasted(false)) + { + if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim())) + { + if (Phase == 1 && !Overpower_Timer) + { + uint32 health = me->getVictim()->GetHealth(); + me->AttackerStateUpdate(me->getVictim()); + if (me->getVictim() && health == me->getVictim()->GetHealth()) + { + DoCast(me->getVictim(), SPELL_OVERPOWER, false); + Overpower_Timer = 5000; + } + } else me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + } + + void SpawnAdds() + { + Creature *pCreature = NULL; + for (uint8 i = 0; i < 4; ++i) + { + pCreature = me->SummonCreature(SpiritInfo[i].entry, SpiritInfo[i].x, SpiritInfo[i].y, SpiritInfo[i].z, SpiritInfo[i].orient, TEMPSUMMON_DEAD_DESPAWN, 0); + if (pCreature) + { + pCreature->CastSpell(pCreature, SPELL_SPIRIT_AURA, true); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + SpiritGUID[i] = pCreature->GetGUID(); + } + } + } + + void DespawnAdds() + { + for (uint8 i = 0; i < 4; ++i) + { + Unit* Temp = NULL; + if (SpiritGUID[i]) + { + if (Temp = Unit::GetUnit(*me, SpiritGUID[i])) + { + Temp->SetVisibility(VISIBILITY_OFF); + Temp->setDeathState(DEAD); + } + } + SpiritGUID[i] = 0; + } + } + + void JustSummoned(Creature *summon) + { + Summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature *summon) + { + Summons.Despawn(summon); + } + + void EnterPhase(uint32 NextPhase) + { + switch(NextPhase) + { + case 0: + break; + case 1: + case 2: + case 3: + case 4: + DoTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, 100); + DoResetThreat(); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + me->RemoveAurasDueToSpell(Transform[Phase].unaura); + DoCast(me, Transform[Phase].spell); + me->MonsterYell(Transform[Phase].text, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, Transform[Phase].sound); + if (Phase > 0) + { + if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[Phase - 1])) + Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); + } + if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[NextPhase - 1])) + Temp->CastSpell(me, SPELL_SIPHON_SOUL, false); // should m cast on temp + if (NextPhase == 2) + { + me->GetMotionMaster()->Clear(); + DoCast(me, SPELL_ENERGY_STORM, true); // enemy aura + for (uint8 i = 0; i < 4; ++i) + { + Creature* Vortex = DoSpawnCreature(CREATURE_FEATHER_VORTEX, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Vortex) + { + Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true); + Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true); + Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Vortex->SetSpeed(MOVE_RUN, 1.0f); + Vortex->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + DoZoneInCombat(Vortex); + } + } + } + else + me->AI()->AttackStart(me->getVictim()); + if (NextPhase == 3) + { + me->RemoveAurasDueToSpell(SPELL_ENERGY_STORM); + Summons.DespawnEntry(CREATURE_FEATHER_VORTEX); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + break; + default: + break; + } + Phase = NextPhase; + } + + void UpdateAI(const uint32 diff) + { + if (!TankGUID) + { + if (!UpdateVictim()) + return; + + if (me->GetHealth() < health_20 * (4 - Phase)) + EnterPhase(Phase + 1); + } + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_BERSERK); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + switch (Phase) + { + case 0: + if (Intro_Timer) + { + if (Intro_Timer <= diff) + { + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_AGGRO); + Intro_Timer = 0; + } else Intro_Timer -= diff; + } + + if (Whirlwind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + Whirlwind_Timer = 15000 + rand()%5000; + } else Whirlwind_Timer -= diff; + + if (Grievous_Throw_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_GRIEVOUS_THROW, false); + Grievous_Throw_Timer = 10000; + } else Grievous_Throw_Timer -= diff; + break; + + case 1: + if (Creeping_Paralysis_Timer <= diff) + { + DoCast(me, SPELL_CREEPING_PARALYSIS); + Creeping_Paralysis_Timer = 20000; + } else Creeping_Paralysis_Timer -= diff; + + if (Overpower_Timer <= diff) + { + // implemented in DoMeleeAttackIfReady() + Overpower_Timer = 0; + } else Overpower_Timer -= diff; + break; + + case 2: + return; + + case 3: + if (Claw_Rage_Timer <= diff) + { + if (!TankGUID) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + TankGUID = me->getVictim()->GetGUID(); + me->SetSpeed(MOVE_RUN, 5.0f); + AttackStart(pTarget); // change victim + Claw_Rage_Timer = 0; + Claw_Loop_Timer = 500; + Claw_Counter = 0; + } + } + else if (!Claw_Rage_Timer) // do not do this when Lynx_Rush + { + if (Claw_Loop_Timer <= diff) + { + Unit *pTarget = me->getVictim(); + if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = Unit::GetUnit(*me, TankGUID); + if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + AttackStart(pTarget); + if (me->IsWithinMeleeRange(pTarget)) + { + DoCast(pTarget, SPELL_CLAW_RAGE_DAMAGE, true); + ++Claw_Counter; + if (Claw_Counter == 12) + { + Claw_Rage_Timer = 15000 + rand()%5000; + me->SetSpeed(MOVE_RUN, 1.2f); + AttackStart(Unit::GetUnit(*me, TankGUID)); + TankGUID = 0; + return; + } + else + Claw_Loop_Timer = 500; + } + } + else + { + EnterEvadeMode(); // if (pTarget) + return; + } + } else Claw_Loop_Timer -= diff; + } //if (TankGUID) + } else Claw_Rage_Timer -= diff; + + if (Lynx_Rush_Timer <= diff) + { + if (!TankGUID) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + TankGUID = me->getVictim()->GetGUID(); + me->SetSpeed(MOVE_RUN, 5.0f); + AttackStart(pTarget); // change victim + Lynx_Rush_Timer = 0; + Claw_Counter = 0; + } + } + else if (!Lynx_Rush_Timer) + { + Unit *pTarget = me->getVictim(); + if (!pTarget || !pTarget->isTargetableForAttack()) + { + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + AttackStart(pTarget); + } + if (pTarget) + { + if (me->IsWithinMeleeRange(pTarget)) + { + DoCast(pTarget, SPELL_LYNX_RUSH_DAMAGE, true); + ++Claw_Counter; + if (Claw_Counter == 9) + { + Lynx_Rush_Timer = 15000 + rand()%5000; + me->SetSpeed(MOVE_RUN, 1.2f); + AttackStart(Unit::GetUnit(*me, TankGUID)); + TankGUID = 0; + } + else + AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + } + } + else + { + EnterEvadeMode(); // if (pTarget) + return; + } + } //if (TankGUID) + } else Lynx_Rush_Timer -= diff; + + break; + case 4: + if (Flame_Whirl_Timer <= diff) + { + DoCast(me, SPELL_FLAME_WHIRL); + Flame_Whirl_Timer = 12000; + }Flame_Whirl_Timer -= diff; + + if (Pillar_Of_Fire_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SUMMON_PILLAR); + Pillar_Of_Fire_Timer = 10000; + } else Pillar_Of_Fire_Timer -= diff; + + if (Flame_Breath_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + me->SetInFront(pTarget); + DoCast(me, SPELL_FLAME_BREATH); + Flame_Breath_Timer = 10000; + } else Flame_Breath_Timer -= diff; + break; + + default: + break; + } + + if (!TankGUID) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_zuljin(Creature* pCreature) +{ + return new boss_zuljinAI (pCreature); +} + +struct feather_vortexAI : public ScriptedAI +{ + feather_vortexAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + + void EnterCombat(Unit * /*pTarget*/) {} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_ZAP_INFORM) + DoCast(caster, SPELL_ZAP_DAMAGE, true); + } + + void UpdateAI(const uint32 /*diff*/) + { + //if the vortex reach the target, it change his target to another player + if (me->IsWithinMeleeRange(me->getVictim())) + AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + } +}; + +CreatureAI* GetAI_feather_vortexAI(Creature* pCreature) +{ + return new feather_vortexAI (pCreature); +} + +void AddSC_boss_zuljin() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_zuljin"; + newscript->GetAI = &GetAI_boss_zuljin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_zuljin_vortex"; + newscript->GetAI = &GetAI_feather_vortexAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp new file mode 100644 index 00000000000..897330691a6 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp @@ -0,0 +1,320 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: instance_zulaman +SD%Complete: 80 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" + +#define MAX_ENCOUNTER 6 +#define RAND_VENDOR 2 + +//187021 //Harkor's Satchel +//186648 //Tanzar's Trunk +//186672 //Ashli's Bag +//186667 //Kraz's Package +// Chests spawn at bear/eagle/dragonhawk/lynx bosses +// The loots depend on how many bosses have been killed, but not the entries of the chests +// But we cannot add loots to gameobject, so we have to use the fixed loot_template +struct SHostageInfo +{ + uint32 npc, pGo; + float x, y, z, o; +}; + +static SHostageInfo HostageInfo[] = +{ + {23790, 186648, -57, 1343, 40.77, 3.2}, // bear + {23999, 187021, 400, 1414, 74.36, 3.3}, // eagle + {24001, 186672, -35, 1134, 18.71, 1.9}, // dragonhawk + {24024, 186667, 413, 1117, 6.32, 3.1} // lynx + +}; + +struct instance_zulaman : public ScriptedInstance +{ + instance_zulaman(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 HarkorsSatchelGUID; + uint64 TanzarsTrunkGUID; + uint64 AshlisBagGUID; + uint64 KrazsPackageGUID; + + uint64 HexLordGateGUID; + uint64 ZulJinGateGUID; + uint64 AkilzonDoorGUID; + uint64 ZulJinDoorGUID; + uint64 HalazziDoorGUID; + + uint32 QuestTimer; + uint16 BossKilled; + uint16 QuestMinute; + uint16 ChestLooted; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 RandVendor[RAND_VENDOR]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + HarkorsSatchelGUID = 0; + TanzarsTrunkGUID = 0; + AshlisBagGUID = 0; + KrazsPackageGUID = 0; + + HexLordGateGUID = 0; + ZulJinGateGUID = 0; + AkilzonDoorGUID = 0; + HalazziDoorGUID = 0; + ZulJinDoorGUID = 0; + + QuestTimer = 0; + QuestMinute = 21; + BossKilled = 0; + ChestLooted = 0; + + for (uint8 i = 0; i < RAND_VENDOR; ++i) + RandVendor[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 23578://janalai + case 23863://zuljin + case 24239://hexlord + case 23577://halazzi + case 23576://nalorakk + default: break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 186303: HalazziDoorGUID = pGo->GetGUID(); break; + case 186304: ZulJinGateGUID = pGo->GetGUID(); break; + case 186305: HexLordGateGUID = pGo->GetGUID(); break; + case 186858: AkilzonDoorGUID = pGo->GetGUID(); break; + case 186859: ZulJinDoorGUID = pGo->GetGUID(); break; + + case 187021: HarkorsSatchelGUID = pGo->GetGUID(); break; + case 186648: TanzarsTrunkGUID = pGo->GetGUID(); break; + case 186672: AshlisBagGUID = pGo->GetGUID(); break; + case 186667: KrazsPackageGUID = pGo->GetGUID(); break; + default: break; + + } + CheckInstanceStatus(); + } + + void SummonHostage(uint8 num) + { + if (!QuestMinute) + return; + + Map::PlayerList const &PlayerList = instance->GetPlayers(); + if (PlayerList.isEmpty()) + return; + + Map::PlayerList::const_iterator i = PlayerList.begin(); + if (Player* i_pl = i->getSource()) + { + if (Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0)) + { + Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + } + } + + void CheckInstanceStatus() + { + if (BossKilled >= 4) + HandleGameObject(HexLordGateGUID, true); + + if (BossKilled >= 5) + HandleGameObject(ZulJinGateGUID, true); + } + + std::string GetSaveData() + { + std::ostringstream ss; + ss << "S " << BossKilled << " " << ChestLooted << " " << QuestMinute; + char* data = new char[ss.str().length()+1]; + strcpy(data, ss.str().c_str()); + //error_log("TSCR: Zul'aman saved, %s.", data); + return data; + } + + void Load(const char* load) + { + if (!load) return; + std::istringstream ss(load); + //error_log("TSCR: Zul'aman loaded, %s.", ss.str().c_str()); + char dataHead; // S + uint16 data1, data2, data3; + ss >> dataHead >> data1 >> data2 >> data3; + //error_log("TSCR: Zul'aman loaded, %d %d %d.", data1, data2, data3); + if (dataHead == 'S') + { + BossKilled = data1; + ChestLooted = data2; + QuestMinute = data3; + } else error_log("TSCR: Zul'aman: corrupted save data."); + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_NALORAKKEVENT: + m_auiEncounter[0] = data; + if (data == DONE) + { + if (QuestMinute) + { + QuestMinute += 15; + DoUpdateWorldState(3106, QuestMinute); + } + SummonHostage(0); + } + break; + case DATA_AKILZONEVENT: + m_auiEncounter[1] = data; + HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS); + if (data == DONE) + { + if (QuestMinute) + { + QuestMinute += 10; + DoUpdateWorldState(3106, QuestMinute); + } + SummonHostage(1); + } + break; + case DATA_JANALAIEVENT: + m_auiEncounter[2] = data; + if (data == DONE) SummonHostage(2); + break; + case DATA_HALAZZIEVENT: + m_auiEncounter[3] = data; + HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS); + if (data == DONE) SummonHostage(3); + break; + case DATA_HEXLORDEVENT: + m_auiEncounter[4] = data; + if (data == IN_PROGRESS) + HandleGameObject(HexLordGateGUID, false); + else if (data == NOT_STARTED) + CheckInstanceStatus(); + break; + case DATA_ZULJINEVENT: + m_auiEncounter[5] = data; + HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS); + break; + case DATA_CHESTLOOTED: + ++ChestLooted; + SaveToDB(); + break; + case TYPE_RAND_VENDOR_1: + RandVendor[0] = data; + break; + case TYPE_RAND_VENDOR_2: + RandVendor[1] = data; + break; + } + + if (data == DONE) + { + ++BossKilled; + if (QuestMinute && BossKilled >= 4) + { + QuestMinute = 0; + DoUpdateWorldState(3104, 0); + } + CheckInstanceStatus(); + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_NALORAKKEVENT: return m_auiEncounter[0]; + case DATA_AKILZONEVENT: return m_auiEncounter[1]; + case DATA_JANALAIEVENT: return m_auiEncounter[2]; + case DATA_HALAZZIEVENT: return m_auiEncounter[3]; + case DATA_HEXLORDEVENT: return m_auiEncounter[4]; + case DATA_ZULJINEVENT: return m_auiEncounter[5]; + case DATA_CHESTLOOTED: return ChestLooted; + case TYPE_RAND_VENDOR_1: return RandVendor[0]; + case TYPE_RAND_VENDOR_2: return RandVendor[1]; + default: return 0; + } + } + + void Update(uint32 diff) + { + if (QuestMinute) + { + if (QuestTimer <= diff) + { + QuestMinute--; + SaveToDB(); + QuestTimer += 60000; + if (QuestMinute) + { + DoUpdateWorldState(3104, 1); + DoUpdateWorldState(3106, QuestMinute); + } else DoUpdateWorldState(3104, 0); + } + QuestTimer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_zulaman(Map* pMap) +{ + return new instance_zulaman(pMap); +} + +void AddSC_instance_zulaman() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_zulaman"; + newscript->GetInstanceData = &GetInstanceData_instance_zulaman; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp b/src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp new file mode 100644 index 00000000000..067ae687644 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp @@ -0,0 +1,192 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Zulaman +SD%Complete: 90 +SDComment: Forest Frog will turn into different NPC's. Workaround to prevent new entry from running this script +SDCategory: Zul'Aman +EndScriptData */ + +/* ContentData +npc_forest_frog +EndContentData */ + +#include "ScriptedPch.h" +#include "zulaman.h" + +/*###### +## npc_forest_frog +######*/ + +#define SPELL_REMOVE_AMANI_CURSE 43732 +#define SPELL_PUSH_MOJO 43923 +#define ENTRY_FOREST_FROG 24396 + +struct npc_forest_frogAI : public ScriptedAI +{ + npc_forest_frogAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() {} + + void EnterCombat(Unit * /*who*/) {} + + void DoSpawnRandom() + { + if (pInstance) + { + uint32 cEntry = 0; + switch(rand()%10) + { + case 0: cEntry = 24397; break; //Mannuth + case 1: cEntry = 24403; break; //Deez + case 2: cEntry = 24404; break; //Galathryn + case 3: cEntry = 24405; break; //Adarrah + case 4: cEntry = 24406; break; //Fudgerick + case 5: cEntry = 24407; break; //Darwen + case 6: cEntry = 24445; break; //Mitzi + case 7: cEntry = 24448; break; //Christian + case 8: cEntry = 24453; break; //Brennan + case 9: cEntry = 24455; break; //Hollee + } + + if (!pInstance->GetData(TYPE_RAND_VENDOR_1)) + if (rand()%10 == 1) cEntry = 24408; //Gunter + if (!pInstance->GetData(TYPE_RAND_VENDOR_2)) + if (rand()%10 == 1) cEntry = 24409; //Kyren + + if (cEntry) me->UpdateEntry(cEntry); + + if (cEntry == 24408) pInstance->SetData(TYPE_RAND_VENDOR_1,DONE); + if (cEntry == 24409) pInstance->SetData(TYPE_RAND_VENDOR_2,DONE); + } + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && me->GetEntry() == ENTRY_FOREST_FROG) + { + //increase or decrease chance of mojo? + if (rand()%99 == 50) DoCast(caster, SPELL_PUSH_MOJO, true); + else DoSpawnRandom(); + } + } +}; +CreatureAI* GetAI_npc_forest_frog(Creature* pCreature) +{ + return new npc_forest_frogAI (pCreature); +} + +/*###### +## npc_zulaman_hostage +######*/ + +#define GOSSIP_HOSTAGE1 "I am glad to help you." + +static uint32 HostageEntry[] = {23790, 23999, 24024, 24001}; +static uint32 ChestEntry[] = {186648, 187021, 186672, 186667}; + +struct npc_zulaman_hostageAI : public ScriptedAI +{ + npc_zulaman_hostageAI(Creature *c) : ScriptedAI(c) {IsLoot = false;} + bool IsLoot; + uint64 PlayerGUID; + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + void JustDied(Unit* /*who*/) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer) pPlayer->SendLoot(me->GetGUID(), LOOT_CORPSE); + } + void UpdateAI(const uint32 /*diff*/) + { + if (IsLoot) + DoCast(me, 7, false); + } +}; + +bool GossipHello_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HOSTAGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + pPlayer->CLOSE_GOSSIP_MENU(); + + if (!pCreature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) + return true; + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance) + { + //uint8 progress = pInstance->GetData(DATA_CHESTLOOTED); + pInstance->SetData(DATA_CHESTLOOTED, 0); + float x, y, z; + pCreature->GetPosition(x, y, z); + uint32 entry = pCreature->GetEntry(); + for (uint8 i = 0; i < 4; ++i) + { + if (HostageEntry[i] == entry) + { + pCreature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0); + break; + } + } + /*Creature* summon = pCreature->SummonCreature(HostageInfo[progress], x-2, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + if (summon) + { + CAST_AI(npc_zulaman_hostageAI, summon->AI())->PlayerGUID = pPlayer->GetGUID(); + CAST_AI(npc_zulaman_hostageAI, summon->AI())->IsLoot = true; + summon->SetDisplayId(10056); + summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + }*/ + } + return true; +} + +CreatureAI* GetAI_npc_zulaman_hostage(Creature* pCreature) +{ + return new npc_zulaman_hostageAI(pCreature); +} + +void AddSC_zulaman() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_forest_frog"; + newscript->GetAI = &GetAI_npc_forest_frog; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_zulaman_hostage"; + newscript->GetAI = &GetAI_npc_zulaman_hostage; + newscript->pGossipHello = &GossipHello_npc_zulaman_hostage; + newscript->pGossipSelect = &GossipSelect_npc_zulaman_hostage; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulaman/zulaman.h b/src/server/scripts/EasternKingdoms/zulaman/zulaman.h new file mode 100644 index 00000000000..6fb0ef173bd --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulaman/zulaman.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ZULAMAN_H +#define DEF_ZULAMAN_H + +#define DATA_NALORAKKEVENT 1 +#define DATA_AKILZONEVENT 2 +#define DATA_JANALAIEVENT 3 +#define DATA_HALAZZIEVENT 4 +#define DATA_HEXLORDEVENT 5 +#define DATA_ZULJINEVENT 6 +#define DATA_CHESTLOOTED 7 +#define TYPE_RAND_VENDOR_1 8 +#define TYPE_RAND_VENDOR_2 9 + +#endif + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp new file mode 100644 index 00000000000..cbbe6c4dc4c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp @@ -0,0 +1,278 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Arlokk +SD%Complete: 95 +SDComment: Wrong cleave and red aura is missing. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +bool GOHello_go_gong_of_bethekk(Player* /*pPlayer*/, GameObject* pGo) +{ + if (ScriptedInstance* m_pInstance = pGo->GetInstanceData()) + { + if (m_pInstance->GetData(TYPE_ARLOKK) == DONE || m_pInstance->GetData(TYPE_ARLOKK) == IN_PROGRESS) + return true; + + m_pInstance->SetData(TYPE_ARLOKK, IN_PROGRESS); + return true; + } + + return true; +} + +enum eEnums +{ + SAY_AGGRO = -1309011, + SAY_FEAST_PANTHER = -1309012, + SAY_DEATH = -1309013, + + SPELL_SHADOWWORDPAIN = 23952, + SPELL_GOUGE = 24698, + SPELL_MARK = 24210, + SPELL_CLEAVE = 26350, //Perhaps not right. Not a red aura... + SPELL_PANTHER_TRANSFORM = 24190, + + MODEL_ID_NORMAL = 15218, + MODEL_ID_PANTHER = 15215, + MODEL_ID_BLANK = 11686, + + NPC_ZULIAN_PROWLER = 15101 +}; + +struct boss_arlokkAI : public ScriptedAI +{ + boss_arlokkAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiShadowWordPain_Timer; + uint32 m_uiGouge_Timer; + uint32 m_uiMark_Timer; + uint32 m_uiCleave_Timer; + uint32 m_uiVanish_Timer; + uint32 m_uiVisible_Timer; + + uint32 m_uiSummon_Timer; + uint32 m_uiSummonCount; + + Unit* m_pMarkedTarget; + uint64 MarkedTargetGUID; + + bool m_bIsPhaseTwo; + bool m_bIsVanished; + + void Reset() + { + m_uiShadowWordPain_Timer = 8000; + m_uiGouge_Timer = 14000; + m_uiMark_Timer = 35000; + m_uiCleave_Timer = 4000; + m_uiVanish_Timer = 60000; + m_uiVisible_Timer = 6000; + + m_uiSummon_Timer = 5000; + m_uiSummonCount = 0; + + m_bIsPhaseTwo = false; + m_bIsVanished = false; + + MarkedTargetGUID = 0; + + me->SetDisplayId(MODEL_ID_NORMAL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_ARLOKK, NOT_STARTED); + + //we should be summoned, so despawn + me->ForcedDespawn(); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + me->SetDisplayId(MODEL_ID_NORMAL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (m_pInstance) + m_pInstance->SetData(TYPE_ARLOKK, DONE); + } + + void DoSummonPhanters() + { + if (Unit *pMarkedTarget = Unit::GetUnit(*me, MarkedTargetGUID)) + DoScriptText(SAY_FEAST_PANTHER, me, pMarkedTarget); + + me->SummonCreature(NPC_ZULIAN_PROWLER, -11532.7998, -1649.6734, 41.4800, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(NPC_ZULIAN_PROWLER, -11532.9970, -1606.4840, 41.2979, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + } + + void JustSummoned(Creature* pSummoned) + { + if (Unit *pMarkedTarget = Unit::GetUnit(*me, MarkedTargetGUID)) + pSummoned->AI()->AttackStart(pMarkedTarget); + + ++m_uiSummonCount; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (!m_bIsPhaseTwo) + { + if (m_uiShadowWordPain_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); + m_uiShadowWordPain_Timer = 15000; + } + else + m_uiShadowWordPain_Timer -= uiDiff; + + if (m_uiMark_Timer <= uiDiff) + { + Unit *pMarkedTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (pMarkedTarget) + { + DoCast(pMarkedTarget, SPELL_MARK); + MarkedTargetGUID = pMarkedTarget->GetGUID(); + } + else + error_log("TSCR: boss_arlokk could not accuire pMarkedTarget."); + + m_uiMark_Timer = 15000; + } + else + m_uiMark_Timer -= uiDiff; + } + else + { + //Cleave_Timer + if (m_uiCleave_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + m_uiCleave_Timer = 16000; + } + else + m_uiCleave_Timer -= uiDiff; + + //Gouge_Timer + if (m_uiGouge_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_GOUGE); + + DoModifyThreatPercent(me->getVictim(),-80); + + m_uiGouge_Timer = 17000+rand()%10000; + } + else + m_uiGouge_Timer -= uiDiff; + } + + if (m_uiSummonCount <= 30) + { + if (m_uiSummon_Timer <= uiDiff) + { + DoSummonPhanters(); + m_uiSummon_Timer = 5000; + } + else + m_uiSummon_Timer -= uiDiff; + } + + if (m_uiVanish_Timer <= uiDiff) + { + //Invisble Model + me->SetDisplayId(MODEL_ID_BLANK); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + me->AttackStop(); + DoResetThreat(); + + m_bIsVanished = true; + + m_uiVanish_Timer = 45000; + m_uiVisible_Timer = 6000; + } + else + m_uiVanish_Timer -= uiDiff; + + if (m_bIsVanished) + { + if (m_uiVisible_Timer <= uiDiff) + { + //The Panther Model + me->SetDisplayId(MODEL_ID_PANTHER); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); + me->UpdateDamagePhysical(BASE_ATTACK); + + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + AttackStart(pTarget); + + m_bIsPhaseTwo = true; + m_bIsVanished = false; + } + else + m_uiVisible_Timer -= uiDiff; + } + else + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_arlokk(Creature* pCreature) +{ + return new boss_arlokkAI (pCreature); +} + +void AddSC_boss_arlokk() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_gong_of_bethekk"; + newscript->pGOHello = &GOHello_go_gong_of_bethekk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_arlokk"; + newscript->GetAI = &GetAI_boss_arlokk; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp new file mode 100644 index 00000000000..0201235be70 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gahz'ranka +SD%Complete: 85 +SDComment: Massive Geyser with knockback not working. Spell buggy. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FROSTBREATH 16099 +#define SPELL_MASSIVEGEYSER 22421 //Not working. Cause its a summon... +#define SPELL_SLAM 24326 + +struct boss_gahzrankaAI : public ScriptedAI +{ + boss_gahzrankaAI(Creature *c) : ScriptedAI(c) {} + uint32 Frostbreath_Timer; + uint32 MassiveGeyser_Timer; + uint32 Slam_Timer; + + void Reset() + { + Frostbreath_Timer = 8000; + MassiveGeyser_Timer = 25000; + Slam_Timer = 17000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frostbreath_Timer + if (Frostbreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBREATH); + Frostbreath_Timer = 7000 + rand()%4000; + } else Frostbreath_Timer -= diff; + + //MassiveGeyser_Timer + if (MassiveGeyser_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MASSIVEGEYSER); + DoResetThreat(); + + MassiveGeyser_Timer = 22000 + rand()%10000; + } else MassiveGeyser_Timer -= diff; + + //Slam_Timer + if (Slam_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLAM); + Slam_Timer = 12000 + rand()%8000; + } else Slam_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gahzranka(Creature* pCreature) +{ + return new boss_gahzrankaAI (pCreature); +} + +void AddSC_boss_gahzranka() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gahzranka"; + newscript->GetAI = &GetAI_boss_gahzranka; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp new file mode 100644 index 00000000000..67de135674a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grilek +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SPELL_AVARTAR 24646 //The Enrage Spell +#define SPELL_GROUNDTREMOR 6524 + +struct boss_grilekAI : public ScriptedAI +{ + boss_grilekAI(Creature *c) : ScriptedAI(c) {} + + uint32 Avartar_Timer; + uint32 GroundTremor_Timer; + + void Reset() + { + Avartar_Timer = 15000 + rand()%10000; + GroundTremor_Timer = 8000 + rand()%8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Avartar_Timer + if (Avartar_Timer <= diff) + { + + DoCast(me, SPELL_AVARTAR); + Unit *pTarget = NULL; + + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-50); + if (pTarget) + AttackStart(pTarget); + + Avartar_Timer = 25000 + rand()%10000; + } else Avartar_Timer -= diff; + + //GroundTremor_Timer + if (GroundTremor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GROUNDTREMOR); + GroundTremor_Timer = 12000 + rand()%4000; + } else GroundTremor_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grilek(Creature* pCreature) +{ + return new boss_grilekAI (pCreature); +} + +void AddSC_boss_grilek() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grilek"; + newscript->GetAI = &GetAI_boss_grilek; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp new file mode 100644 index 00000000000..d7dd5020b74 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp @@ -0,0 +1,250 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hakkar +SD%Complete: 95 +SDComment: Blood siphon spell buggy cause of Core Issue. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309020 +#define SAY_FLEEING -1309021 +#define SAY_MINION_DESTROY -1309022 //where does it belong? +#define SAY_PROTECT_ALTAR -1309023 //where does it belong? + +#define SPELL_BLOODSIPHON 24322 +#define SPELL_CORRUPTEDBLOOD 24328 +#define SPELL_CAUSEINSANITY 24327 //Not working disabled. +#define SPELL_WILLOFHAKKAR 24178 +#define SPELL_ENRAGE 24318 + +// The Aspects of all High Priests +#define SPELL_ASPECT_OF_JEKLIK 24687 +#define SPELL_ASPECT_OF_VENOXIS 24688 +#define SPELL_ASPECT_OF_MARLI 24686 +#define SPELL_ASPECT_OF_THEKAL 24689 +#define SPELL_ASPECT_OF_ARLOKK 24690 + +struct boss_hakkarAI : public ScriptedAI +{ + boss_hakkarAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 BloodSiphon_Timer; + uint32 CorruptedBlood_Timer; + uint32 CauseInsanity_Timer; + uint32 WillOfHakkar_Timer; + uint32 Enrage_Timer; + + uint32 CheckJeklik_Timer; + uint32 CheckVenoxis_Timer; + uint32 CheckMarli_Timer; + uint32 CheckThekal_Timer; + uint32 CheckArlokk_Timer; + + uint32 AspectOfJeklik_Timer; + uint32 AspectOfVenoxis_Timer; + uint32 AspectOfMarli_Timer; + uint32 AspectOfThekal_Timer; + uint32 AspectOfArlokk_Timer; + + bool Enraged; + + void Reset() + { + BloodSiphon_Timer = 90000; + CorruptedBlood_Timer = 25000; + CauseInsanity_Timer = 17000; + WillOfHakkar_Timer = 17000; + Enrage_Timer = 600000; + + CheckJeklik_Timer = 1000; + CheckVenoxis_Timer = 2000; + CheckMarli_Timer = 3000; + CheckThekal_Timer = 4000; + CheckArlokk_Timer = 5000; + + AspectOfJeklik_Timer = 4000; + AspectOfVenoxis_Timer = 7000; + AspectOfMarli_Timer = 12000; + AspectOfThekal_Timer = 8000; + AspectOfArlokk_Timer = 18000; + + Enraged = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //BloodSiphon_Timer + if (BloodSiphon_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLOODSIPHON); + BloodSiphon_Timer = 90000; + } else BloodSiphon_Timer -= diff; + + //CorruptedBlood_Timer + if (CorruptedBlood_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORRUPTEDBLOOD); + CorruptedBlood_Timer = 30000 + rand()%15000; + } else CorruptedBlood_Timer -= diff; + + //CauseInsanity_Timer + /*if (CauseInsanity_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CAUSEINSANITY); + + CauseInsanity_Timer = 35000 + rand()%8000; + } else CauseInsanity_Timer -= diff;*/ + + //WillOfHakkar_Timer + if (WillOfHakkar_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_WILLOFHAKKAR); + + WillOfHakkar_Timer = 25000 + rand()%10000; + } else WillOfHakkar_Timer -= diff; + + if (!Enraged && Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else Enrage_Timer -= diff; + + //Checking if Jeklik is dead. If not we cast her Aspect + if (CheckJeklik_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_JEKLIK) != DONE) + { + if (AspectOfJeklik_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ASPECT_OF_JEKLIK); + AspectOfJeklik_Timer = 10000 + rand()%4000; + } else AspectOfJeklik_Timer -= diff; + } + } + CheckJeklik_Timer = 1000; + } else CheckJeklik_Timer -= diff; + + //Checking if Venoxis is dead. If not we cast his Aspect + if (CheckVenoxis_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_VENOXIS) != DONE) + { + if (AspectOfVenoxis_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ASPECT_OF_VENOXIS); + AspectOfVenoxis_Timer = 8000; + } else AspectOfVenoxis_Timer -= diff; + } + } + CheckVenoxis_Timer = 1000; + } else CheckVenoxis_Timer -= diff; + + //Checking if Marli is dead. If not we cast her Aspect + if (CheckMarli_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_MARLI) != DONE) + { + if (AspectOfMarli_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); + AspectOfMarli_Timer = 10000; + } else AspectOfMarli_Timer -= diff; + + } + } + CheckMarli_Timer = 1000; + } else CheckMarli_Timer -= diff; + + //Checking if Thekal is dead. If not we cast his Aspect + if (CheckThekal_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_THEKAL) != DONE) + { + if (AspectOfThekal_Timer <= diff) + { + DoCast(me, SPELL_ASPECT_OF_THEKAL); + AspectOfThekal_Timer = 15000; + } else AspectOfThekal_Timer -= diff; + } + } + CheckThekal_Timer = 1000; + } else CheckThekal_Timer -= diff; + + //Checking if Arlokk is dead. If yes we cast her Aspect + if (CheckArlokk_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_ARLOKK) != DONE) + { + if (AspectOfArlokk_Timer <= diff) + { + DoCast(me, SPELL_ASPECT_OF_ARLOKK); + DoResetThreat(); + + AspectOfArlokk_Timer = 10000 + rand()%5000; + } else AspectOfArlokk_Timer -= diff; + } + } + CheckArlokk_Timer = 1000; + } else CheckArlokk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_hakkar(Creature* pCreature) +{ + return new boss_hakkarAI (pCreature); +} + +void AddSC_boss_hakkar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hakkar"; + newscript->GetAI = &GetAI_boss_hakkar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp new file mode 100644 index 00000000000..ca67d0842c3 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hazzarah +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SPELL_MANABURN 26046 +#define SPELL_SLEEP 24664 + +struct boss_hazzarahAI : public ScriptedAI +{ + boss_hazzarahAI(Creature *c) : ScriptedAI(c) {} + + uint32 ManaBurn_Timer; + uint32 Sleep_Timer; + uint32 Illusions_Timer; + + void Reset() + { + ManaBurn_Timer = 4000 + rand()%6000; + Sleep_Timer = 10000 + rand()%8000; + Illusions_Timer = 10000 + rand()%8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ManaBurn_Timer + if (ManaBurn_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MANABURN); + ManaBurn_Timer = 8000 + rand()%8000; + } else ManaBurn_Timer -= diff; + + //Sleep_Timer + if (Sleep_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLEEP); + Sleep_Timer = 12000 + rand()%8000; + } else Sleep_Timer -= diff; + + //Illusions_Timer + if (Illusions_Timer <= diff) + { + //We will summon 3 illusions that will spawn on a random gamer and attack this gamer + //We will just use one model for the beginning + Unit *pTarget = NULL; + for (uint8 i = 0; i < 3; ++i) + { + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget) + return; + + Creature *Illusion = me->SummonCreature(15163,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,30000); + if (Illusion) + Illusion->AI()->AttackStart(pTarget); + } + + Illusions_Timer = 15000 + rand()%10000; + } else Illusions_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hazzarah(Creature* pCreature) +{ + return new boss_hazzarahAI (pCreature); +} + +void AddSC_boss_hazzarah() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hazzarah"; + newscript->GetAI = &GetAI_boss_hazzarah; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp new file mode 100644 index 00000000000..fae05fcf384 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp @@ -0,0 +1,291 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Jeklik +SD%Complete: 85 +SDComment: Problem in finding the right flying batriders for spawning and making them fly. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309002 +#define SAY_RAIN_FIRE -1309003 +#define SAY_DEATH -1309004 + +#define SPELL_CHARGE 22911 +#define SPELL_SONICBURST 23918 +#define SPELL_SCREECH 6605 +#define SPELL_SHADOW_WORD_PAIN 23952 +#define SPELL_MIND_FLAY 23953 +#define SPELL_CHAIN_MIND_FLAY 26044 //Right ID unknown. So disabled +#define SPELL_GREATERHEAL 23954 +#define SPELL_BAT_FORM 23966 + +// Batriders Spell + +#define SPELL_BOMB 40332 //Wrong ID but Magmadars bomb is not working... + +struct boss_jeklikAI : public ScriptedAI +{ + boss_jeklikAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 Charge_Timer; + uint32 SonicBurst_Timer; + uint32 Screech_Timer; + uint32 SpawnBats_Timer; + uint32 ShadowWordPain_Timer; + uint32 MindFlay_Timer; + uint32 ChainMindFlay_Timer; + uint32 GreaterHeal_Timer; + uint32 SpawnFlyingBats_Timer; + + bool PhaseTwo; + + void Reset() + { + Charge_Timer = 20000; + SonicBurst_Timer = 8000; + Screech_Timer = 13000; + SpawnBats_Timer = 60000; + ShadowWordPain_Timer = 6000; + MindFlay_Timer = 11000; + ChainMindFlay_Timer = 26000; + GreaterHeal_Timer = 50000; + SpawnFlyingBats_Timer = 10000; + + PhaseTwo = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_BAT_FORM); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_JEKLIK, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->getVictim() && me->isAlive()) + { + if ((me->GetHealth()*100 / me->GetMaxHealth() > 50)) + { + if (Charge_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_CHARGE); + AttackStart(pTarget); + } + + Charge_Timer = 15000 + rand()%15000; + } else Charge_Timer -= diff; + + if (SonicBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SONICBURST); + SonicBurst_Timer = 8000 + rand()%5000; + } else SonicBurst_Timer -= diff; + + if (Screech_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SCREECH); + Screech_Timer = 18000 + rand()%8000; + } else Screech_Timer -= diff; + + if (SpawnBats_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + Creature* Bat = NULL; + Bat = me->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + Bat = me->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + Bat = me->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + Bat = me->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + Bat = me->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + Bat = me->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + SpawnBats_Timer = 60000; + } else SpawnBats_Timer -= diff; + } + else + { + if (PhaseTwo) + { + if (PhaseTwo && ShadowWordPain_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); + ShadowWordPain_Timer = 12000 + rand()%6000; + } + }ShadowWordPain_Timer -=diff; + + if (MindFlay_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIND_FLAY); + MindFlay_Timer = 16000; + }MindFlay_Timer -=diff; + + if (ChainMindFlay_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me->getVictim(), SPELL_CHAIN_MIND_FLAY); + ChainMindFlay_Timer = 15000 + rand()%15000; + }ChainMindFlay_Timer -=diff; + + if (GreaterHeal_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_GREATERHEAL); + GreaterHeal_Timer = 25000 + rand()%10000; + }GreaterHeal_Timer -=diff; + + if (SpawnFlyingBats_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!pTarget) + return; + + Creature* FlyingBat = me->SummonCreature(14965, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (FlyingBat) + FlyingBat->AI()->AttackStart(pTarget); + + SpawnFlyingBats_Timer = 10000 + rand()%5000; + } else SpawnFlyingBats_Timer -=diff; + } + else + { + me->SetDisplayId(15219); + DoResetThreat(); + PhaseTwo = true; + } + } + + DoMeleeAttackIfReady(); + } + } +}; + +//Flying Bat +struct mob_batriderAI : public ScriptedAI +{ + mob_batriderAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 Bomb_Timer; + uint32 Check_Timer; + + void Reset() + { + Bomb_Timer = 2000; + Check_Timer = 1000; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI (const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Bomb_Timer + if (Bomb_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_BOMB); + Bomb_Timer = 5000; + } + } else Bomb_Timer -= diff; + + //Check_Timer + if (Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_JEKLIK) == DONE) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + return; + } + } + + Check_Timer = 1000; + } else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jeklik(Creature* pCreature) +{ + return new boss_jeklikAI (pCreature); +} + +CreatureAI* GetAI_mob_batrider(Creature* pCreature) +{ + return new mob_batriderAI (pCreature); +} + +void AddSC_boss_jeklik() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_jeklik"; + newscript->GetAI = &GetAI_boss_jeklik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_batrider"; + newscript->GetAI = &GetAI_mob_batrider; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp new file mode 100644 index 00000000000..58f91f85a95 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp @@ -0,0 +1,263 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Jin'do the Hexxer +SD%Complete: 85 +SDComment: Mind Control not working because of core bug. Shades visible for all. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309014 + +#define SPELL_BRAINWASHTOTEM 24262 +#define SPELL_POWERFULLHEALINGWARD 24309 //We will not use this spell. We will summon a totem by script cause the spell totems will not cast. +#define SPELL_HEX 24053 +#define SPELL_DELUSIONSOFJINDO 24306 +#define SPELL_SHADEOFJINDO 24308 //We will not use this spell. We will summon a shade by script. + +//Healing Ward Spell +#define SPELL_HEAL 38588 //Totems are not working right. Right heal spell ID is 24311 but this spell is not casting... + +//Shade of Jindo Spell +#define SPELL_SHADOWSHOCK 19460 +#define SPELL_INVISIBLE 24699 + +struct boss_jindoAI : public ScriptedAI +{ + boss_jindoAI(Creature *c) : ScriptedAI(c) {} + + uint32 BrainWashTotem_Timer; + uint32 HealingWard_Timer; + uint32 Hex_Timer; + uint32 Delusions_Timer; + uint32 Teleport_Timer; + + void Reset() + { + BrainWashTotem_Timer = 20000; + HealingWard_Timer = 16000; + Hex_Timer = 8000; + Delusions_Timer = 10000; + Teleport_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //BrainWashTotem_Timer + if (BrainWashTotem_Timer <= diff) + { + DoCast(me, SPELL_BRAINWASHTOTEM); + BrainWashTotem_Timer = 18000 + rand()%8000; + } else BrainWashTotem_Timer -= diff; + + //HealingWard_Timer + if (HealingWard_Timer <= diff) + { + //DoCast(me, SPELL_POWERFULLHEALINGWARD); + me->SummonCreature(14987, me->GetPositionX()+3, me->GetPositionY()-2, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,30000); + HealingWard_Timer = 14000 + rand()%6000; + } else HealingWard_Timer -= diff; + + //Hex_Timer + if (Hex_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HEX); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-80); + + Hex_Timer = 12000 + rand()%8000; + } else Hex_Timer -= diff; + + //Casting the delusion curse with a shade. So shade will attack the same target with the curse. + if (Delusions_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_DELUSIONSOFJINDO); + + Creature *Shade = me->SummonCreature(14986, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Shade) + Shade->AI()->AttackStart(pTarget); + } + + Delusions_Timer = 4000 + rand()%8000; + } else Delusions_Timer -= diff; + + //Teleporting a random gamer and spawning 9 skeletons that will attack this gamer + if (Teleport_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoTeleportPlayer(pTarget, -11583.7783,-1249.4278,77.5471,4.745); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(pTarget,-100); + + Creature *Skeletons; + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+2, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()-2, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+4, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()-4, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()+2, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()-2, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()+4, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()-4, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+3, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + } + + Teleport_Timer = 15000 + rand()%8000; + } else Teleport_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Healing Ward +struct mob_healing_wardAI : public ScriptedAI +{ + mob_healing_wardAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 Heal_Timer; + + ScriptedInstance *pInstance; + + void Reset() + { + Heal_Timer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI (const uint32 diff) + { + //Heal_Timer + if (Heal_Timer <= diff) + { + if (pInstance) + { + Unit *pJindo = Unit::GetUnit((*me), pInstance->GetData64(DATA_JINDO)); + if (pJindo) + DoCast(pJindo, SPELL_HEAL); + } + Heal_Timer = 3000; + } else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Shade of Jindo +struct mob_shade_of_jindoAI : public ScriptedAI +{ + mob_shade_of_jindoAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowShock_Timer; + + void Reset() + { + ShadowShock_Timer = 1000; + DoCast(me, SPELL_INVISIBLE, true); + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI (const uint32 diff) + { + + //ShadowShock_Timer + if (ShadowShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWSHOCK); + ShadowShock_Timer = 2000; + } else ShadowShock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jindo(Creature* pCreature) +{ + return new boss_jindoAI (pCreature); +} + +CreatureAI* GetAI_mob_healing_ward(Creature* pCreature) +{ + return new mob_healing_wardAI (pCreature); +} + +CreatureAI* GetAI_mob_shade_of_jindo(Creature* pCreature) +{ + return new mob_shade_of_jindoAI (pCreature); +} + +void AddSC_boss_jindo() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_jindo"; + newscript->GetAI = &GetAI_boss_jindo; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_healing_ward"; + newscript->GetAI = &GetAI_mob_healing_ward; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shade_of_jindo"; + newscript->GetAI = &GetAI_mob_shade_of_jindo; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp new file mode 100644 index 00000000000..4609605f3c1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp @@ -0,0 +1,333 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mandokir +SD%Complete: 90 +SDComment: Ohgan function needs improvements. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309015 +#define SAY_DING_KILL -1309016 +#define SAY_GRATS_JINDO -1309017 +#define SAY_WATCH -1309018 +#define SAY_WATCH_WHISPER -1309019 //is this text for real? easter egg? + +#define SPELL_CHARGE 24315 +#define SPELL_CLEAVE 20691 +#define SPELL_FEAR 29321 +#define SPELL_WHIRLWIND 24236 +#define SPELL_MORTAL_STRIKE 24573 +#define SPELL_ENRAGE 23537 +#define SPELL_WATCH 24314 +#define SPELL_LEVEL_UP 24312 + +//Ohgans Spells +#define SPELL_SUNDERARMOR 24317 + +struct boss_mandokirAI : public ScriptedAI +{ + boss_mandokirAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 KillCount; + uint32 Watch_Timer; + uint32 TargetInRange; + uint32 Cleave_Timer; + uint32 Whirlwind_Timer; + uint32 Fear_Timer; + uint32 MortalStrike_Timer; + uint32 Check_Timer; + float targetX; + float targetY; + float targetZ; + + ScriptedInstance *m_pInstance; + + bool endWatch; + bool someWatched; + bool RaptorDead; + bool CombatStart; + + uint64 WatchTarget; + + void Reset() + { + KillCount = 0; + Watch_Timer = 33000; + Cleave_Timer = 7000; + Whirlwind_Timer = 20000; + Fear_Timer = 1000; + MortalStrike_Timer = 1000; + Check_Timer = 1000; + + targetX = 0.0; + targetY = 0.0; + targetZ = 0.0; + TargetInRange = 0; + + WatchTarget = 0; + + someWatched = false; + endWatch = false; + RaptorDead = false; + CombatStart = false; + + DoCast(me, 23243); + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + { + ++KillCount; + + if (KillCount == 3) + { + DoScriptText(SAY_DING_KILL, me); + + if (m_pInstance) + { + uint64 JindoGUID = m_pInstance->GetData64(DATA_JINDO); + if (JindoGUID) + { + if (Unit* jTemp = Unit::GetUnit(*me,JindoGUID)) + { + if (jTemp->isAlive()) + DoScriptText(SAY_GRATS_JINDO, jTemp); + } + } + } + DoCast(me, SPELL_LEVEL_UP, true); + KillCount = 0; + } + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->getVictim() && me->isAlive()) + { + if (!CombatStart) + { + //At combat Start Mandokir is mounted so we must unmount it first + me->Unmount(); + + //And summon his raptor + me->SummonCreature(14988, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000); + CombatStart = true; + } + + if (Watch_Timer <= diff) //Every 20 Sec Mandokir will check this + { + if (WatchTarget) //If someone is watched and If the Position of the watched target is different from the one stored, or are attacking, mandokir will charge him + { + Unit* pUnit = Unit::GetUnit(*me, WatchTarget); + + if (pUnit && ( + targetX != pUnit->GetPositionX() || + targetY != pUnit->GetPositionY() || + targetZ != pUnit->GetPositionZ() || + pUnit->isInCombat())) + { + if (me->IsWithinMeleeRange(pUnit)) + { + DoCast(pUnit, 24316); + } + else + { + DoCast(pUnit, SPELL_CHARGE); + //me->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true,1); + AttackStart(pUnit); + } + } + } + someWatched = false; + Watch_Timer = 20000; + } else Watch_Timer -= diff; + + if ((Watch_Timer < 8000) && !someWatched) //8 sec(cast time + expire time) before the check for the watch effect mandokir will cast watch debuff on a random target + { + if (Unit* p = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoScriptText(SAY_WATCH, me, p); + DoCast(p, SPELL_WATCH); + WatchTarget = p->GetGUID(); + someWatched = true; + endWatch = true; + } + } + + if ((Watch_Timer < 1000) && endWatch) //1 sec before the debuf expire, store the target position + { + Unit* pUnit = Unit::GetUnit(*me, WatchTarget); + if (pUnit) + { + targetX = pUnit->GetPositionX(); + targetY = pUnit->GetPositionY(); + targetZ = pUnit->GetPositionZ(); + } + endWatch = false; + } + + if (!someWatched) + { + //Cleave + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //Whirlwind + if (Whirlwind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + Whirlwind_Timer = 18000; + } else Whirlwind_Timer -= diff; + + //If more then 3 targets in melee range mandokir will cast fear + if (Fear_Timer <= diff) + { + TargetInRange = 0; + + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit(*me, (*i)->getUnitGuid()); + if (pUnit && me->IsWithinMeleeRange(pUnit)) + ++TargetInRange; + } + + if (TargetInRange > 3) + DoCast(me->getVictim(), SPELL_FEAR); + + Fear_Timer = 4000; + } else Fear_Timer -=diff; + + //Mortal Strike if target below 50% hp + if (me->getVictim() && me->getVictim()->GetHealth() < me->getVictim()->GetMaxHealth()*0.5) + { + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + MortalStrike_Timer = 15000; + } else MortalStrike_Timer -= diff; + } + } + //Checking if Ohgan is dead. If yes Mandokir will enrage. + if (Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_OHGAN) == DONE) + { + if (!RaptorDead) + { + DoCast(me, SPELL_ENRAGE); + RaptorDead = true; + } + } + } + + Check_Timer = 1000; + } else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +//Ohgan +struct mob_ohganAI : public ScriptedAI +{ + mob_ohganAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 SunderArmor_Timer; + ScriptedInstance *m_pInstance; + + void Reset() + { + SunderArmor_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) {} + + void JustDied(Unit* /*Killer*/) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_OHGAN, DONE); + } + + void UpdateAI (const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //SunderArmor_Timer + if (SunderArmor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDERARMOR); + SunderArmor_Timer = 10000 + rand()%5000; + } else SunderArmor_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_mandokir(Creature* pCreature) +{ + return new boss_mandokirAI (pCreature); +} + +CreatureAI* GetAI_mob_ohgan(Creature* pCreature) +{ + return new mob_ohganAI (pCreature); +} + +void AddSC_boss_mandokir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_mandokir"; + newscript->GetAI = &GetAI_boss_mandokir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ohgan"; + newscript->GetAI = &GetAI_mob_ohgan; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp new file mode 100644 index 00000000000..77e9f9b929f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp @@ -0,0 +1,261 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Marli +SD%Complete: 80 +SDComment: Charging healers and casters not working. Perhaps wrong Spell Timers. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309005 +#define SAY_TRANSFORM -1309006 +#define SAY_SPIDER_SPAWN -1309007 +#define SAY_DEATH -1309008 + +#define SPELL_CHARGE 22911 +#define SPELL_ASPECT_OF_MARLI 24686 // A stun spell +#define SPELL_ENVOLWINGWEB 24110 +#define SPELL_POISONVOLLEY 24099 +#define SPELL_SPIDER_FORM 24084 + +//The Spider Spells +#define SPELL_LEVELUP 24312 //Not right Spell. + +struct boss_marliAI : public ScriptedAI +{ + boss_marliAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 SpawnStartSpiders_Timer; + uint32 PoisonVolley_Timer; + uint32 SpawnSpider_Timer; + uint32 Charge_Timer; + uint32 Aspect_Timer; + uint32 Transform_Timer; + uint32 TransformBack_Timer; + + bool Spawned; + bool PhaseTwo; + + void Reset() + { + SpawnStartSpiders_Timer = 1000; + PoisonVolley_Timer = 15000; + SpawnSpider_Timer = 30000; + Charge_Timer = 1500; + Aspect_Timer = 12000; + Transform_Timer = 45000; + TransformBack_Timer = 25000; + + Spawned = false; + PhaseTwo = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + if (m_pInstance) + m_pInstance->SetData(TYPE_MARLI, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->getVictim() && me->isAlive()) + { + if (PoisonVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISONVOLLEY); + PoisonVolley_Timer = 10000 + rand()%10000; + } else PoisonVolley_Timer -= diff; + + if (!PhaseTwo && Aspect_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); + Aspect_Timer = 13000 + rand()%5000; + } else Aspect_Timer -= diff; + + if (!Spawned && SpawnStartSpiders_Timer <= diff) + { + DoScriptText(SAY_SPIDER_SPAWN, me); + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget) + return; + + Creature *Spider = NULL; + + Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + + Spawned = true; + } else SpawnStartSpiders_Timer -= diff; + + if (SpawnSpider_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget) + return; + + Creature *Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + SpawnSpider_Timer = 12000 + rand()%5000; + } else SpawnSpider_Timer -= diff; + + if (!PhaseTwo && Transform_Timer <= diff) + { + DoScriptText(SAY_TRANSFORM, me); + DoCast(me, SPELL_SPIDER_FORM); + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); + me->UpdateDamagePhysical(BASE_ATTACK); + DoCast(me->getVictim(), SPELL_ENVOLWINGWEB); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-100); + + PhaseTwo = true; + Transform_Timer = urand(35000,60000); + } else Transform_Timer -= diff; + + if (PhaseTwo) + { + if (Charge_Timer <= diff) + { + Unit *pTarget = NULL; + int i = 0; + while (i < 3) // max 3 tries to get a random target with power_mana + { + ++i; + pTarget = SelectTarget(SELECT_TARGET_RANDOM,1, 100, true); // not aggro leader + if (pTarget && pTarget->getPowerType() == POWER_MANA) + i = 3; + } + if (pTarget) + { + DoCast(pTarget, SPELL_CHARGE); + //me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); + //me->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, true,1); + AttackStart(pTarget); + } + + Charge_Timer = 8000; + } else Charge_Timer -= diff; + + if (TransformBack_Timer <= diff) + { + me->SetDisplayId(15220); + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1))); + me->UpdateDamagePhysical(BASE_ATTACK); + + PhaseTwo = false; + TransformBack_Timer = urand(25000,40000); + } else TransformBack_Timer -= diff; + + } + + DoMeleeAttackIfReady(); + } + } +}; + +//Spawn of Marli +struct mob_spawn_of_marliAI : public ScriptedAI +{ + mob_spawn_of_marliAI(Creature *c) : ScriptedAI(c) {} + + uint32 LevelUp_Timer; + + void Reset() + { + LevelUp_Timer = 3000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI (const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //LevelUp_Timer + if (LevelUp_Timer <= diff) + { + DoCast(me, SPELL_LEVELUP); + LevelUp_Timer = 3000; + } else LevelUp_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_marli(Creature* pCreature) +{ + return new boss_marliAI (pCreature); +} + +CreatureAI* GetAI_mob_spawn_of_marli(Creature* pCreature) +{ + return new mob_spawn_of_marliAI (pCreature); +} + +void AddSC_boss_marli() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_marli"; + newscript->GetAI = &GetAI_boss_marli; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_spawn_of_marli"; + newscript->GetAI = &GetAI_mob_spawn_of_marli; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp new file mode 100644 index 00000000000..f7b01b26e19 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Renataki +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SPELL_AMBUSH 24337 +#define SPELL_THOUSANDBLADES 24649 + +#define EQUIP_ID_MAIN_HAND 0 //was item display id 31818, but this id does not exist + +struct boss_renatakiAI : public ScriptedAI +{ + boss_renatakiAI(Creature *c) : ScriptedAI(c) {} + + uint32 Invisible_Timer; + uint32 Ambush_Timer; + uint32 Visible_Timer; + uint32 Aggro_Timer; + uint32 ThousandBlades_Timer; + + bool Invisible; + bool Ambushed; + + void Reset() + { + Invisible_Timer = 8000 + rand()%10000; + Ambush_Timer = 3000; + Visible_Timer = 4000; + Aggro_Timer = 15000 + rand()%10000; + ThousandBlades_Timer = 4000 + rand()%4000; + + Invisible = false; + Ambushed = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Invisible_Timer + if (Invisible_Timer <= diff) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + me->SetDisplayId(11686); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Invisible = true; + + Invisible_Timer = 15000 + rand()%15000; + } else Invisible_Timer -= diff; + + if (Invisible) + { + if (Ambush_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + { + DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); + DoCast(pTarget, SPELL_AMBUSH); + } + + Ambushed = true; + Ambush_Timer = 3000; + } else Ambush_Timer -= diff; + } + + if (Ambushed) + { + if (Visible_Timer <= diff) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + + me->SetDisplayId(15268); + SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Invisible = false; + + Visible_Timer = 4000; + } else Visible_Timer -= diff; + } + + //Resetting some aggro so he attacks other gamers + if (!Invisible) + if (Aggro_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-50); + + if (pTarget) + AttackStart(pTarget); + + Aggro_Timer = 7000 + rand()%13000; + } else Aggro_Timer -= diff; + + if (!Invisible) + if (ThousandBlades_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THOUSANDBLADES); + ThousandBlades_Timer = 7000 + rand()%5000; + } else ThousandBlades_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_renataki(Creature* pCreature) +{ + return new boss_renatakiAI (pCreature); +} + +void AddSC_boss_renataki() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_renataki"; + newscript->GetAI = &GetAI_boss_renataki; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp new file mode 100644 index 00000000000..179700d36e7 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp @@ -0,0 +1,556 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Thekal +SD%Complete: 95 +SDComment: Almost finished. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309009 +#define SAY_DEATH -1309010 + +#define SPELL_MORTALCLEAVE 22859 +#define SPELL_SILENCE 23207 +#define SPELL_FRENZY 23342 +#define SPELL_FORCEPUNCH 24189 +#define SPELL_CHARGE 24408 +#define SPELL_ENRAGE 23537 +#define SPELL_SUMMONTIGERS 24183 +#define SPELL_TIGER_FORM 24169 +#define SPELL_RESURRECT 24173 //We will not use this spell. + +//Zealot Lor'Khan Spells +#define SPELL_SHIELD 25020 +#define SPELL_BLOODLUST 24185 +#define SPELL_GREATERHEAL 24208 +#define SPELL_DISARM 22691 + +//Zealot Lor'Khan Spells +#define SPELL_SWEEPINGSTRIKES 18765 +#define SPELL_SINISTERSTRIKE 15667 +#define SPELL_GOUGE 24698 +#define SPELL_KICK 15614 +#define SPELL_BLIND 21060 + +struct boss_thekalAI : public ScriptedAI +{ + boss_thekalAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 MortalCleave_Timer; + uint32 Silence_Timer; + uint32 Frenzy_Timer; + uint32 ForcePunch_Timer; + uint32 Charge_Timer; + uint32 Enrage_Timer; + uint32 SummonTigers_Timer; + uint32 Check_Timer; + uint32 Resurrect_Timer; + + ScriptedInstance *m_pInstance; + bool Enraged; + bool PhaseTwo; + bool WasDead; + + void Reset() + { + MortalCleave_Timer = 4000; + Silence_Timer = 9000; + Frenzy_Timer = 30000; + ForcePunch_Timer = 4000; + Charge_Timer = 12000; + Enrage_Timer = 32000; + SummonTigers_Timer = 25000; + Check_Timer = 10000; + Resurrect_Timer = 10000; + + Enraged = false; + PhaseTwo = false; + WasDead = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + if (m_pInstance) + m_pInstance->SetData(TYPE_THEKAL, DONE); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_THEKAL, NOT_STARTED); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Check_Timer for the death of LorKhan and Zath. + if (!WasDead && Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL) + { + //Resurrect LorKhan + if (Unit *pLorKhan = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_LORKHAN))) + { + pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pLorKhan->setFaction(14); + pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); + + m_pInstance->SetData(TYPE_LORKHAN, DONE); + } + } + + if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL) + { + //Resurrect Zath + Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH)); + if (pZath) + { + pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pZath->setFaction(14); + pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); + + m_pInstance->SetData(TYPE_ZATH, DONE); + } + } + } + + Check_Timer = 5000; + } else Check_Timer -= diff; + + if (!PhaseTwo && MortalCleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALCLEAVE); + MortalCleave_Timer = 15000 + rand()%5000; + } else MortalCleave_Timer -= diff; + + if (!PhaseTwo && Silence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + Silence_Timer = 20000 + rand()%5000; + } else Silence_Timer -= diff; + + if (!PhaseTwo && !WasDead && me->GetHealth() <= me->GetMaxHealth() * 0.05) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + me->AttackStop(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_THEKAL, SPECIAL); + + WasDead=true; + } + + //Thekal will transform to Tiger if he died and was not resurrected after 10 seconds. + if (!PhaseTwo && WasDead) + { + if (Resurrect_Timer <= diff) + { + DoCast(me, SPELL_TIGER_FORM); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetHealth(int(me->GetMaxHealth()*1.0)); + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40))); + me->UpdateDamagePhysical(BASE_ATTACK); + DoResetThreat(); + PhaseTwo = true; + } else Resurrect_Timer -= diff; + } + + if ((me->GetHealth()*100 / me->GetMaxHealth() == 100) && WasDead) + { + WasDead = false; + } + + if (PhaseTwo) + { + if (Charge_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_CHARGE); + DoResetThreat(); + AttackStart(pTarget); + } + + Charge_Timer = 15000 + rand()%7000; + } else Charge_Timer -= diff; + + if (Frenzy_Timer <= diff) + { + DoCast(me, SPELL_FRENZY); + Frenzy_Timer = 30000; + } else Frenzy_Timer -= diff; + + if (ForcePunch_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + ForcePunch_Timer = 16000 + rand()%5000; + } else ForcePunch_Timer -= diff; + + if (SummonTigers_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUMMONTIGERS); + SummonTigers_Timer = 10000 + rand()%4000; + } else SummonTigers_Timer -= diff; + + if ((me->GetHealth()*100 / me->GetMaxHealth() < 11) && !Enraged) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } + } + + DoMeleeAttackIfReady(); + + } +}; + +//Zealot Lor'Khan +struct mob_zealot_lorkhanAI : public ScriptedAI +{ + mob_zealot_lorkhanAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 Shield_Timer; + uint32 BloodLust_Timer; + uint32 GreaterHeal_Timer; + uint32 Disarm_Timer; + uint32 Check_Timer; + + bool FakeDeath; + + ScriptedInstance *m_pInstance; + + void Reset() + { + Shield_Timer = 1000; + BloodLust_Timer = 16000; + GreaterHeal_Timer = 32000; + Disarm_Timer = 6000; + Check_Timer = 10000; + + FakeDeath = false; + + if (m_pInstance) + m_pInstance->SetData(TYPE_LORKHAN, NOT_STARTED); + + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI (const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Shield_Timer + if (Shield_Timer <= diff) + { + DoCast(me, SPELL_SHIELD); + Shield_Timer = 61000; + } else Shield_Timer -= diff; + + //BloodLust_Timer + if (BloodLust_Timer <= diff) + { + DoCast(me, SPELL_BLOODLUST); + BloodLust_Timer = 20000+rand()%8000; + } else BloodLust_Timer -= diff; + + //Casting Greaterheal to Thekal or Zath if they are in meele range. + if (GreaterHeal_Timer <= diff) + { + if (m_pInstance) + { + Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL)); + Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH)); + + if (!pThekal || !pZath) + return; + + switch (urand(0,1)) + { + case 0: + if (me->IsWithinMeleeRange(pThekal)) + DoCast(pThekal, SPELL_GREATERHEAL); + break; + case 1: + if (me->IsWithinMeleeRange(pZath)) + DoCast(pZath, SPELL_GREATERHEAL); + break; + } + } + + GreaterHeal_Timer = 15000+rand()%5000; + } else GreaterHeal_Timer -= diff; + + //Disarm_Timer + if (Disarm_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DISARM); + Disarm_Timer = 15000+rand()%10000; + } else Disarm_Timer -= diff; + + //Check_Timer for the death of LorKhan and Zath. + if (!FakeDeath && Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL) + { + //Resurrect Thekal + if (Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL))) + { + pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pThekal->setFaction(14); + pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); + } + } + + if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL) + { + //Resurrect Zath + if (Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH))) + { + pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pZath->setFaction(14); + pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); + } + } + } + + Check_Timer = 5000; + } else Check_Timer -= diff; + + if (me->GetHealth() <= me->GetMaxHealth() * 0.05) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + me->setFaction(35); + me->AttackStop(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_LORKHAN, SPECIAL); + + FakeDeath = true; + } + + DoMeleeAttackIfReady(); + } +}; + +//Zealot Zath +struct mob_zealot_zathAI : public ScriptedAI +{ + mob_zealot_zathAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 SweepingStrikes_Timer; + uint32 SinisterStrike_Timer; + uint32 Gouge_Timer; + uint32 Kick_Timer; + uint32 Blind_Timer; + uint32 Check_Timer; + + bool FakeDeath; + + ScriptedInstance *m_pInstance; + + void Reset() + { + SweepingStrikes_Timer = 13000; + SinisterStrike_Timer = 8000; + Gouge_Timer = 25000; + Kick_Timer = 18000; + Blind_Timer = 5000; + Check_Timer = 10000; + + FakeDeath = false; + + if (m_pInstance) + m_pInstance->SetData(TYPE_ZATH, NOT_STARTED); + + me->SetStandState(UNIT_STAND_STATE_STAND); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI (const uint32 diff) + { + if (!UpdateVictim()) + return; + + //SweepingStrikes_Timer + if (SweepingStrikes_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SWEEPINGSTRIKES); + SweepingStrikes_Timer = 22000+rand()%4000; + } else SweepingStrikes_Timer -= diff; + + //SinisterStrike_Timer + if (SinisterStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SINISTERSTRIKE); + SinisterStrike_Timer = 8000+rand()%8000; + } else SinisterStrike_Timer -= diff; + + //Gouge_Timer + if (Gouge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GOUGE); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-100); + + Gouge_Timer = 17000+rand()%10000; + } else Gouge_Timer -= diff; + + //Kick_Timer + if (Kick_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KICK); + Kick_Timer = 15000+rand()%10000; + } else Kick_Timer -= diff; + + //Blind_Timer + if (Blind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLIND); + Blind_Timer = 10000+rand()%10000; + } else Blind_Timer -= diff; + + //Check_Timer for the death of LorKhan and Zath. + if (!FakeDeath && Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL) + { + //Resurrect LorKhan + if (Unit *pLorKhan = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_LORKHAN))) + { + pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pLorKhan->setFaction(14); + pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); + } + } + + if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL) + { + //Resurrect Thekal + if (Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL))) + { + pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pThekal->setFaction(14); + pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); + } + } + } + + Check_Timer = 5000; + } else Check_Timer -= diff; + + if (me->GetHealth() <= me->GetMaxHealth() * 0.05) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + me->setFaction(35); + me->AttackStop(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_ZATH, SPECIAL); + + FakeDeath = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thekal(Creature* pCreature) +{ + return new boss_thekalAI (pCreature); +} + +CreatureAI* GetAI_mob_zealot_lorkhan(Creature* pCreature) +{ + return new mob_zealot_lorkhanAI (pCreature); +} + +CreatureAI* GetAI_mob_zealot_zath(Creature* pCreature) +{ + return new mob_zealot_zathAI (pCreature); +} + +void AddSC_boss_thekal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_thekal"; + newscript->GetAI = &GetAI_boss_thekal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_zealot_lorkhan"; + newscript->GetAI = &GetAI_mob_zealot_lorkhan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_zealot_zath"; + newscript->GetAI = &GetAI_mob_zealot_zath; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp new file mode 100644 index 00000000000..ec1a7a142b5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp @@ -0,0 +1,199 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Venoxis +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_TRANSFORM -1309000 +#define SAY_DEATH -1309001 + +#define SPELL_HOLY_FIRE 23860 +#define SPELL_HOLY_WRATH 28883 //Not sure if this or 23979 +#define SPELL_VENOMSPIT 23862 +#define SPELL_HOLY_NOVA 23858 +#define SPELL_POISON_CLOUD 23861 +#define SPELL_SNAKE_FORM 23849 +#define SPELL_RENEW 23895 +#define SPELL_BERSERK 23537 +#define SPELL_DISPELL 23859 + +struct boss_venoxisAI : public ScriptedAI +{ + boss_venoxisAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 HolyFire_Timer; + uint32 HolyWrath_Timer; + uint32 VenomSpit_Timer; + uint32 Renew_Timer; + uint32 PoisonCloud_Timer; + uint32 HolyNova_Timer; + uint32 Dispell_Timer; + uint32 TargetInRange; + + bool PhaseTwo; + bool InBerserk; + + void Reset() + { + HolyFire_Timer = 10000; + HolyWrath_Timer = 60500; + VenomSpit_Timer = 5500; + Renew_Timer = 30500; + PoisonCloud_Timer = 2000; + HolyNova_Timer = 5000; + Dispell_Timer = 35000; + TargetInRange = 0; + + PhaseTwo = false; + InBerserk= false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + if (m_pInstance) + m_pInstance->SetData(TYPE_VENOXIS, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if ((me->GetHealth()*100 / me->GetMaxHealth() > 50)) + { + if (Dispell_Timer <= diff) + { + DoCast(me, SPELL_DISPELL); + Dispell_Timer = 15000 + rand()%15000; + } else Dispell_Timer -= diff; + + if (Renew_Timer <= diff) + { + DoCast(me, SPELL_RENEW); + Renew_Timer = 20000 + rand()%10000; + } else Renew_Timer -= diff; + + if (HolyWrath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HOLY_WRATH); + HolyWrath_Timer = 15000 + rand()%10000; + } else HolyWrath_Timer -= diff; + + if (HolyNova_Timer <= diff) + { + TargetInRange = 0; + for (uint8 i = 0; i < 10; ++i) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,i)) + if (me->IsWithinMeleeRange(pTarget)) + ++TargetInRange; + } + + if (TargetInRange > 1) + { + DoCast(me->getVictim(), SPELL_HOLY_NOVA); + HolyNova_Timer = 1000; + } + else + { + HolyNova_Timer = 2000; + } + + } else HolyNova_Timer -= diff; + + if (HolyFire_Timer < diff && TargetInRange < 3) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_HOLY_FIRE); + + HolyFire_Timer = 8000; + } else HolyFire_Timer -= diff; + } + else + { + if (!PhaseTwo) + { + DoScriptText(SAY_TRANSFORM, me); + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SNAKE_FORM); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 25))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 25))); + me->UpdateDamagePhysical(BASE_ATTACK); + DoResetThreat(); + PhaseTwo = true; + } + + if (PhaseTwo && PoisonCloud_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_CLOUD); + PoisonCloud_Timer = 15000; + }PoisonCloud_Timer -=diff; + + if (PhaseTwo && VenomSpit_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_VENOMSPIT); + + VenomSpit_Timer = 15000 + rand()%5000; + } else VenomSpit_Timer -= diff; + + if (PhaseTwo && (me->GetHealth()*100 / me->GetMaxHealth() < 11)) + { + if (!InBerserk) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_BERSERK); + InBerserk = true; + } + } + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_venoxis(Creature* pCreature) +{ + return new boss_venoxisAI (pCreature); +} + +void AddSC_boss_venoxis() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_venoxis"; + newscript->GetAI = &GetAI_boss_venoxis; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp new file mode 100644 index 00000000000..a71d7e0504a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Wushoolay +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SPELL_LIGHTNINGCLOUD 25033 +#define SPELL_LIGHTNINGWAVE 24819 + +struct boss_wushoolayAI : public ScriptedAI +{ + boss_wushoolayAI(Creature *c) : ScriptedAI(c) {} + + uint32 LightningCloud_Timer; + uint32 LightningWave_Timer; + + void Reset() + { + LightningCloud_Timer = 5000 + rand()%5000; + LightningWave_Timer = 8000 + rand()%8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //LightningCloud_Timer + if (LightningCloud_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LIGHTNINGCLOUD); + LightningCloud_Timer = 15000 + rand()%5000; + } else LightningCloud_Timer -= diff; + + //LightningWave_Timer + if (LightningWave_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_LIGHTNINGWAVE); + + LightningWave_Timer = 12000 + rand()%4000; + } else LightningWave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_wushoolay(Creature* pCreature) +{ + return new boss_wushoolayAI (pCreature); +} + +void AddSC_boss_wushoolay() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_wushoolay"; + newscript->GetAI = &GetAI_boss_wushoolay; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp new file mode 100644 index 00000000000..aaed1c6df3a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp @@ -0,0 +1,159 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_ZulGurub +SD%Complete: 80 +SDComment: Missing reset function after killing a boss for Ohgan, Thekal. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +struct instance_zulgurub : public ScriptedInstance +{ + instance_zulgurub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. + uint32 m_auiEncounter[MAX_ENCOUNTERS]; + + //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. + uint64 m_uiLorKhanGUID; + uint64 m_uiZathGUID; + uint64 m_uiThekalGUID; + uint64 m_uiJindoGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiLorKhanGUID = 0; + m_uiZathGUID = 0; + m_uiThekalGUID = 0; + m_uiJindoGUID = 0; + } + + bool IsEncounterInProgress() const + { + //not active in Zul'Gurub + return false; + } + + void OnCreatureCreate(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case 11347: m_uiLorKhanGUID = pCreature->GetGUID(); break; + case 11348: m_uiZathGUID = pCreature->GetGUID(); break; + case 14509: m_uiThekalGUID = pCreature->GetGUID(); break; + case 11380: m_uiJindoGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_ARLOKK: + m_auiEncounter[0] = uiData; + break; + + case TYPE_JEKLIK: + m_auiEncounter[1] = uiData; + break; + + case TYPE_VENOXIS: + m_auiEncounter[2] = uiData; + break; + + case TYPE_MARLI: + m_auiEncounter[3] = uiData; + break; + + case TYPE_THEKAL: + m_auiEncounter[4] = uiData; + break; + + case TYPE_LORKHAN: + m_auiEncounter[5] = uiData; + break; + + case TYPE_ZATH: + m_auiEncounter[6] = uiData; + break; + + case TYPE_OHGAN: + m_auiEncounter[7] = uiData; + break; + } + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_ARLOKK: + return m_auiEncounter[0]; + case TYPE_JEKLIK: + return m_auiEncounter[1]; + case TYPE_VENOXIS: + return m_auiEncounter[2]; + case TYPE_MARLI: + return m_auiEncounter[3]; + case TYPE_THEKAL: + return m_auiEncounter[4]; + case TYPE_LORKHAN: + return m_auiEncounter[5]; + case TYPE_ZATH: + return m_auiEncounter[6]; + case TYPE_OHGAN: + return m_auiEncounter[7]; + } + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_LORKHAN: + return m_uiLorKhanGUID; + case DATA_ZATH: + return m_uiZathGUID; + case DATA_THEKAL: + return m_uiThekalGUID; + case DATA_JINDO: + return m_uiJindoGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_zulgurub(Map* pMap) +{ + return new instance_zulgurub(pMap); +} + +void AddSC_instance_zulgurub() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_zulgurub"; + newscript->GetInstanceData = &GetInstanceData_instance_zulgurub; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h b/src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h new file mode 100644 index 00000000000..bf55a54c1d5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ZULGURUB_H +#define DEF_ZULGURUB_H + +enum eTypes +{ + MAX_ENCOUNTERS = 8, + + TYPE_ARLOKK = 1, + TYPE_JEKLIK = 2, + TYPE_VENOXIS = 3, + TYPE_MARLI = 4, + TYPE_OHGAN = 5, + TYPE_THEKAL = 6, + TYPE_ZATH = 7, + TYPE_LORKHAN = 8, + + DATA_JINDO = 10, + DATA_LORKHAN = 11, + DATA_THEKAL = 12, + DATA_ZATH = 13 +}; + +#endif + diff --git a/src/server/scripts/Examples/example_creature.cpp b/src/server/scripts/Examples/example_creature.cpp new file mode 100644 index 00000000000..856b680e2e6 --- /dev/null +++ b/src/server/scripts/Examples/example_creature.cpp @@ -0,0 +1,292 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Example_Creature +SD%Complete: 100 +SDComment: Short custom scripting example +SDCategory: Script Examples +EndScriptData */ + +#include "ScriptedPch.h" + +// **** This script is designed as an example for others to build on **** +// **** Please modify whatever you'd like to as this script is only for developement **** + +// **** Script Info **** +// This script is written in a way that it can be used for both friendly and hostile monsters +// Its primary purpose is to show just how much you can really do with scripts +// I recommend trying it out on both an agressive NPC and on friendly npc + +// **** Quick Info **** +// Functions with Handled Function marked above them are functions that are called automatically by the core +// Functions that are marked Custom Function are functions I've created to simplify code + +enum Yells +{ + //List of text id's. The text is stored in database, also in a localized version + //(if translation not exist for the textId, default english text will be used) + //Not required to define in this way, but simplify if changes are needed. + SAY_AGGRO = -1999900, + SAY_RANDOM_0 = -1999901, + SAY_RANDOM_1 = -1999902, + SAY_RANDOM_2 = -1999903, + SAY_RANDOM_3 = -1999904, + SAY_RANDOM_4 = -1999905, + SAY_BERSERK = -1999906, + SAY_PHASE = -1999907, + SAY_DANCE = -1999908, + SAY_SALUTE = -1999909, + SAY_EVADE = -1999910, +}; + +enum Spells +{ + // List of spells. + // Not required to define them in this way, but will make it easier to maintain in case spellId change + SPELL_BUFF = 25661, + SPELL_ONE = 12555, + SPELL_ONE_ALT = 24099, + SPELL_TWO = 10017, + SPELL_THREE = 26027, + SPELL_FRENZY = 23537, + SPELL_BERSERK = 32965, +}; + +enum eEnums +{ + // any other constants + FACTION_WORGEN = 24 +}; + +//List of gossip item texts. Items will appear in the gossip window. +#define GOSSIP_ITEM "I'm looking for a fight" + +struct example_creatureAI : public ScriptedAI +{ + //*** HANDLED FUNCTION *** + //This is the constructor, called only once when the Creature is first created + example_creatureAI(Creature *c) : ScriptedAI(c) {} + + //*** CUSTOM VARIABLES **** + //These variables are for use only by this individual script. + //Nothing else will ever call them but us. + + uint32 m_uiSayTimer; // Timer for random chat + uint32 m_uiRebuffTimer; // Timer for rebuffing + uint32 m_uiSpell1Timer; // Timer for spell 1 when in combat + uint32 m_uiSpell2Timer; // Timer for spell 1 when in combat + uint32 m_uiSpell3Timer; // Timer for spell 1 when in combat + uint32 m_uiBeserkTimer; // Timer until we go into Beserk (enraged) mode + uint32 m_uiPhase; // The current battle phase we are in + uint32 m_uiPhaseTimer; // Timer until phase transition + + //*** HANDLED FUNCTION *** + //This is called after spawn and whenever the core decides we need to evade + void Reset() + { + m_uiPhase = 1; // Start in phase 1 + m_uiPhaseTimer = 60000; // 60 seconds + m_uiSpell1Timer = 5000; // 5 seconds + m_uiSpell2Timer = urand(10000,20000); // between 10 and 20 seconds + m_uiSpell3Timer = 19000; // 19 seconds + m_uiBeserkTimer = 120000; // 2 minutes + + me->RestoreFaction(); + } + + //*** HANDLED FUNCTION *** + // Enter Combat called once per combat + void EnterCombat(Unit* pWho) + { + //Say some stuff + DoScriptText(SAY_AGGRO, me, pWho); + } + + //*** HANDLED FUNCTION *** + // Attack Start is called when victim change (including at start of combat) + // By default, attack pWho and start movement toward the victim. + //void AttackStart(Unit* pWho) + //{ + // ScriptedAI::AttackStart(pWho); + //} + + //*** HANDLED FUNCTION *** + // Called when going out of combat. Reset is called just after. + void EnterEvadeMode() + { + DoScriptText(SAY_EVADE, me); + } + + //*** HANDLED FUNCTION *** + //Our Receive emote function + void ReceiveEmote(Player* /*pPlayer*/, uint32 uiTextEmote) + { + me->HandleEmoteCommand(uiTextEmote); + + switch(uiTextEmote) + { + case TEXTEMOTE_DANCE: + DoScriptText(SAY_DANCE, me); + break; + case TEXTEMOTE_SALUTE: + DoScriptText(SAY_SALUTE, me); + break; + } + } + + //*** HANDLED FUNCTION *** + //Update AI is called Every single map update (roughly once every 50ms if a player is within the grid) + void UpdateAI(const uint32 uiDiff) + { + //Out of combat timers + if (!me->getVictim()) + { + //Random Say timer + if (m_uiSayTimer <= uiDiff) + { + //Random switch between 5 outcomes + DoScriptText(RAND(SAY_RANDOM_0,SAY_RANDOM_1,SAY_RANDOM_2,SAY_RANDOM_3,SAY_RANDOM_4), me); + + m_uiSayTimer = 45000; //Say something agian in 45 seconds + } + else + m_uiSayTimer -= uiDiff; + + //Rebuff timer + if (m_uiRebuffTimer <= uiDiff) + { + DoCast(me, SPELL_BUFF); + m_uiRebuffTimer = 900000; //Rebuff agian in 15 minutes + } + else + m_uiRebuffTimer -= uiDiff; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Spell 1 timer + if (m_uiSpell1Timer <= uiDiff) + { + //Cast spell one on our current target. + if (rand()%50 > 10) + DoCast(me->getVictim(), SPELL_ONE_ALT); + else if (me->IsWithinDist(me->getVictim(), 25.0f)) + DoCast(me->getVictim(), SPELL_ONE); + + m_uiSpell1Timer = 5000; + } + else + m_uiSpell1Timer -= uiDiff; + + //Spell 2 timer + if (m_uiSpell2Timer <= uiDiff) + { + //Cast spell two on our current target. + DoCast(me->getVictim(), SPELL_TWO); + m_uiSpell2Timer = 37000; + } + else + m_uiSpell2Timer -= uiDiff; + + //Beserk timer + if (m_uiPhase > 1) + { + //Spell 3 timer + if (m_uiSpell3Timer <= uiDiff) + { + //Cast spell one on our current target. + DoCast(me->getVictim(), SPELL_THREE); + + m_uiSpell3Timer = 19000; + } + else + m_uiSpell3Timer -= uiDiff; + + if (m_uiBeserkTimer <= uiDiff) + { + //Say our line then cast uber death spell + DoScriptText(SAY_BERSERK, me, me->getVictim()); + DoCast(me->getVictim(), SPELL_BERSERK); + + //Cast our beserk spell agian in 12 seconds if we didn't kill everyone + m_uiBeserkTimer = 12000; + } + else + m_uiBeserkTimer -= uiDiff; + } + else if (m_uiPhase == 1) //Phase timer + { + if (m_uiPhaseTimer <= uiDiff) + { + //Go to next phase + ++m_uiPhase; + DoScriptText(SAY_PHASE, me); + DoCast(me, SPELL_FRENZY); + } + else + m_uiPhaseTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +//This is the GetAI method used by all scripts that involve AI +//It is called every time a new Creature using this script is created +CreatureAI* GetAI_example_creature(Creature* pCreature) +{ + return new example_creatureAI (pCreature); +} + +//This function is called when the player clicks an option on the gossip menu +bool GossipSelect_example_creature(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + //Set our faction to hostile towards all + pCreature->setFaction(FACTION_WORGEN); + pCreature->AI()->AttackStart(pPlayer); + } + + return true; +} + +//This function is called when the player opens the gossip menu +bool GossipHello_example_creature(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + + return true; +} + +//This is the actual function called only once durring InitScripts() +//It must define all handled functions that are to be run in this script +void AddSC_example_creature() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "example_creature"; + newscript->GetAI = &GetAI_example_creature; + newscript->pGossipHello = &GossipHello_example_creature; + newscript->pGossipSelect = &GossipSelect_example_creature; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Examples/example_escort.cpp b/src/server/scripts/Examples/example_escort.cpp new file mode 100644 index 00000000000..bf2b454bf8e --- /dev/null +++ b/src/server/scripts/Examples/example_escort.cpp @@ -0,0 +1,229 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Example_Escort +SD%Complete: 100 +SDComment: Script used for testing escortAI +SDCategory: Script Examples +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +enum eEnums +{ + NPC_FELBOAR = 21878, + + SPELL_DEATH_COIL = 33130, + SPELL_ELIXIR_OF_FORTITUDE = 3593, + SPELL_BLUE_FIREWORK = 11540, + + SAY_AGGRO1 = -1999910, + SAY_AGGRO2 = -1999911, + SAY_WP_1 = -1999912, + SAY_WP_2 = -1999913, + SAY_WP_3 = -1999914, + SAY_WP_4 = -1999915, + SAY_DEATH_1 = -1999916, + SAY_DEATH_2 = -1999917, + SAY_DEATH_3 = -1999918, + SAY_SPELL = -1999919, + SAY_RAND_1 = -1999920, + SAY_RAND_2 = -1999921 +}; + +#define GOSSIP_ITEM_1 "Click to Test Escort(Attack, Run)" +#define GOSSIP_ITEM_2 "Click to Test Escort(NoAttack, Walk)" +#define GOSSIP_ITEM_3 "Click to Test Escort(NoAttack, Run)" + +struct example_escortAI : public npc_escortAI +{ + // CreatureAI functions + example_escortAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + uint32 m_uiDeathCoilTimer; + uint32 m_uiChatTimer; + + void JustSummoned(Creature* pSummoned) + { + pSummoned->AI()->AttackStart(me); + } + + // Pure Virtual Functions (Have to be implemented) + void WaypointReached(uint32 uiWP) + { + switch (uiWP) + { + case 1: + DoScriptText(SAY_WP_1, me); + break; + case 3: + DoScriptText(SAY_WP_2, me); + me->SummonCreature(NPC_FELBOAR, me->GetPositionX()+5.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + break; + case 4: + if (Player* pPlayer = GetPlayerForEscort()) + { + //pTmpPlayer is the target of the text + DoScriptText(SAY_WP_3, me, pPlayer); + //pTmpPlayer is the source of the text + DoScriptText(SAY_WP_4, pPlayer); + } + break; + } + } + + void EnterCombat(Unit* /*pWho*/) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (Player* pPlayer = GetPlayerForEscort()) + DoScriptText(SAY_AGGRO1, me, pPlayer); + } + else + DoScriptText(SAY_AGGRO2, me); + } + + void Reset() + { + m_uiDeathCoilTimer = 4000; + m_uiChatTimer = 4000; + } + + void JustDied(Unit* pKiller) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (Player* pPlayer = GetPlayerForEscort()) + { + // not a likely case, code here for the sake of example + if (pKiller == me) + { + DoScriptText(SAY_DEATH_1, me, pPlayer); + } + else + DoScriptText(SAY_DEATH_2, me, pPlayer); + } + } + else + DoScriptText(SAY_DEATH_3, me); + } + + void UpdateAI(const uint32 uiDiff) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(uiDiff); + + //Combat check + if (me->getVictim()) + { + if (m_uiDeathCoilTimer <= uiDiff) + { + DoScriptText(SAY_SPELL, me); + DoCast(me->getVictim(), SPELL_DEATH_COIL, false); + m_uiDeathCoilTimer = 4000; + } + else + m_uiDeathCoilTimer -= uiDiff; + } + else + { + //Out of combat but being escorted + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (m_uiChatTimer <= uiDiff) + { + if (me->HasAura(SPELL_ELIXIR_OF_FORTITUDE, 0)) + { + DoScriptText(SAY_RAND_1, me); + DoCast(me, SPELL_BLUE_FIREWORK, false); + } + else + { + DoScriptText(SAY_RAND_2, me); + DoCast(me, SPELL_ELIXIR_OF_FORTITUDE, false); + } + + m_uiChatTimer = 12000; + } + else + m_uiChatTimer -= uiDiff; + } + } + } +}; + +CreatureAI* GetAI_example_escort(Creature* pCreature) +{ + return new example_escortAI(pCreature); +} + +bool GossipHello_example_escort(Player* pPlayer, Creature* pCreature) +{ + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + pPlayer->PrepareGossipMenu(pCreature, 0); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + + pPlayer->SendPreparedGossip(pCreature); + + return true; +} + +bool GossipSelect_example_escort(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + npc_escortAI* pEscortAI = CAST_AI(example_escortAI, pCreature->AI()); + + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pEscortAI) + pEscortAI->Start(true, true, pPlayer->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pEscortAI) + pEscortAI->Start(false, false, pPlayer->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pEscortAI) + pEscortAI->Start(false, true, pPlayer->GetGUID()); + break; + default: + return false; // nothing defined -> trinity core handling + } + + return true; // no default handling -> prevent trinity core handling +} + +void AddSC_example_escort() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "example_escort"; + newscript->GetAI = &GetAI_example_escort; + newscript->pGossipHello = &GossipHello_example_escort; + newscript->pGossipSelect = &GossipSelect_example_escort; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Examples/example_gossip_codebox.cpp b/src/server/scripts/Examples/example_gossip_codebox.cpp new file mode 100644 index 00000000000..e208722784a --- /dev/null +++ b/src/server/scripts/Examples/example_gossip_codebox.cpp @@ -0,0 +1,99 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Example_Gossip_Codebox +SD%Complete: 100 +SDComment: Show a codebox in gossip option +SDCategory: Script Examples +EndScriptData */ + +#include "ScriptedPch.h" +#include + +enum eEnums +{ + SPELL_POLYMORPH = 12826, + SPELL_MARK_OF_THE_WILD = 26990, + + SAY_NOT_INTERESTED = -1999922, + SAY_WRONG = -1999923, + SAY_CORRECT = -1999924 +}; + +#define GOSSIP_ITEM_1 "A quiz: what's your name?" +#define GOSSIP_ITEM_2 "I'm not interested" + +//This function is called when the player opens the gossip menubool +bool GossipHello_example_gossip_codebox(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1, "", 0, true); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetGUID()); + + return true; +} + +//This function is called when the player clicks an option on the gossip menubool +bool GossipSelect_example_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + DoScriptText(SAY_NOT_INTERESTED, pCreature); + pPlayer->CLOSE_GOSSIP_MENU(); + } + + return true; +} + +bool GossipSelectWithCode_example_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode) +{ + if (uiSender == GOSSIP_SENDER_MAIN) + { + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + if (std::strcmp(sCode, pPlayer->GetName()) != 0) + { + DoScriptText(SAY_WRONG, pCreature); + pCreature->CastSpell(pPlayer, SPELL_POLYMORPH, true); + } + else + { + DoScriptText(SAY_CORRECT, pCreature); + pCreature->CastSpell(pPlayer, SPELL_MARK_OF_THE_WILD, true); + } + pPlayer->CLOSE_GOSSIP_MENU(); + + return true; + } + } + + return false; +} + +void AddSC_example_gossip_codebox() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "example_gossip_codebox"; + newscript->pGossipHello = &GossipHello_example_gossip_codebox; + newscript->pGossipSelect = &GossipSelect_example_gossip_codebox; + newscript->pGossipSelectWithCode = &GossipSelectWithCode_example_gossip_codebox; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Examples/example_misc.cpp b/src/server/scripts/Examples/example_misc.cpp new file mode 100644 index 00000000000..3c96cc0bae7 --- /dev/null +++ b/src/server/scripts/Examples/example_misc.cpp @@ -0,0 +1,69 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Example_Misc +SD%Complete: 100 +SDComment: Item, Areatrigger and other small code examples +SDCategory: Script Examples +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptMgr.h" + +enum eSay +{ + SAY_HI = -1999925 +}; + +bool AT_example_areatrigger(Player* pPlayer, const AreaTriggerEntry * /*pAt*/) +{ + DoScriptText(SAY_HI, pPlayer); + return true; +} + +extern void LoadDatabase(); +bool ItemUse_example_item(Player* /*pPlayer*/, Item* /*pItem*/, SpellCastTargets const& /*scTargets*/) +{ + sScriptMgr.LoadDatabase(); + return true; +} + +bool GOHello_example_go_teleporter(Player* pPlayer, GameObject* /*pGo*/) +{ + pPlayer->TeleportTo(0, 1807.07f, 336.105f, 70.3975f, 0.0f); + return false; +} + +void AddSC_example_misc() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "example_areatrigger"; + newscript->pAreaTrigger = &AT_example_areatrigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "example_item"; + newscript->pItemUse = &ItemUse_example_item; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "example_go_teleporter"; + newscript->pGOHello = &GOHello_example_go_teleporter; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/ashenvale.cpp b/src/server/scripts/Kalimdor/ashenvale.cpp new file mode 100644 index 00000000000..13e8f442048 --- /dev/null +++ b/src/server/scripts/Kalimdor/ashenvale.cpp @@ -0,0 +1,465 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Ashenvale +SD%Complete: 70 +SDComment: Quest support: 6544, 6482 +SDCategory: Ashenvale Forest +EndScriptData */ + +/* ContentData +npc_torek +npc_ruul_snowhoof +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*#### +# npc_torek +####*/ + +#define SAY_READY -1000106 +#define SAY_MOVE -1000107 +#define SAY_PREPARE -1000108 +#define SAY_WIN -1000109 +#define SAY_END -1000110 + +#define SPELL_REND 11977 +#define SPELL_THUNDERCLAP 8078 + +#define QUEST_TOREK_ASSULT 6544 + +#define ENTRY_SPLINTERTREE_RAIDER 12859 +#define ENTRY_DURIEL 12860 +#define ENTRY_SILVERWING_SENTINEL 12896 +#define ENTRY_SILVERWING_WARRIOR 12897 + +struct npc_torekAI : public npc_escortAI +{ + npc_torekAI(Creature *c) : npc_escortAI(c) {} + + uint32 Rend_Timer; + uint32 Thunderclap_Timer; + bool Completed; + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch (i) + { + case 1: + DoScriptText(SAY_MOVE, me, pPlayer); + break; + case 8: + DoScriptText(SAY_PREPARE, me, pPlayer); + break; + case 19: + //TODO: verify location and creatures amount. + me->SummonCreature(ENTRY_DURIEL,1776.73,-2049.06,109.83,1.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000); + me->SummonCreature(ENTRY_SILVERWING_SENTINEL,1774.64,-2049.41,109.83,1.40,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000); + me->SummonCreature(ENTRY_SILVERWING_WARRIOR,1778.73,-2049.50,109.83,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000); + break; + case 20: + DoScriptText(SAY_WIN, me, pPlayer); + Completed = true; + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_TOREK_ASSULT, me); + break; + case 21: + DoScriptText(SAY_END, me, pPlayer); + break; + } + } + + void Reset() + { + Rend_Timer = 5000; + Thunderclap_Timer = 8000; + Completed = false; + } + + void EnterCombat(Unit* /*who*/) + { + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + if (Rend_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REND); + Rend_Timer = 20000; + } else Rend_Timer -= diff; + + if (Thunderclap_Timer <= diff) + { + DoCast(me, SPELL_THUNDERCLAP); + Thunderclap_Timer = 30000; + } else Thunderclap_Timer -= diff; + } +}; + +bool QuestAccept_npc_torek(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_TOREK_ASSULT) + { + //TODO: find companions, make them follow Torek, at any time (possibly done by core/database in future?) + DoScriptText(SAY_READY, pCreature, pPlayer); + pCreature->setFaction(113); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_torekAI, pCreature->AI())) + pEscortAI->Start(true, true, pPlayer->GetGUID()); + } + + return true; +} + +CreatureAI* GetAI_npc_torek(Creature* pCreature) +{ + return new npc_torekAI(pCreature); +} + +/*#### +# npc_ruul_snowhoof +####*/ + +#define QUEST_FREEDOM_TO_RUUL 6482 +#define GO_CAGE 178147 + +struct npc_ruul_snowhoofAI : public npc_escortAI +{ + npc_ruul_snowhoofAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 0: { + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 20); + if (Cage) + Cage->SetGoState(GO_STATE_ACTIVE); + break;} + case 13: + me->SummonCreature(3922, 3449.218018, -587.825073, 174.978867, 4.714445, TEMPSUMMON_DEAD_DESPAWN, 60000); + me->SummonCreature(3921, 3446.384521, -587.830872, 175.186279, 4.714445, TEMPSUMMON_DEAD_DESPAWN, 60000); + me->SummonCreature(3926, 3444.218994, -587.835327, 175.380600, 4.714445, TEMPSUMMON_DEAD_DESPAWN, 60000); + break; + case 19: + me->SummonCreature(3922, 3508.344482, -492.024261, 186.929031, 4.145029, TEMPSUMMON_DEAD_DESPAWN, 60000); + me->SummonCreature(3921, 3506.265625, -490.531006, 186.740128, 4.239277, TEMPSUMMON_DEAD_DESPAWN, 60000); + me->SummonCreature(3926, 3503.682373, -489.393799, 186.629684, 4.349232, TEMPSUMMON_DEAD_DESPAWN, 60000); + break; + + case 21:{ + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_FREEDOM_TO_RUUL, me); + + break; } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void Reset() + { + GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 20); + if (Cage) + Cage->SetGoState(GO_STATE_READY); + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; + +bool QuestAccept_npc_ruul_snowhoof(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_FREEDOM_TO_RUUL) + { + pCreature->setFaction(113); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_ruul_snowhoofAI, (pCreature->AI()))) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_ruul_snowhoofAI(Creature* pCreature) +{ + return new npc_ruul_snowhoofAI(pCreature); +} + +enum eEnums +{ + SAY_MUG_START1 = -1800054, + SAY_MUG_START2 = -1800055, + SAY_MUG_BRAZIER = -1800056, + SAY_MUG_BRAZIER_WAIT = -1800057, + SAY_MUG_ON_GUARD = -1800058, + SAY_MUG_REST = -1800059, + SAY_MUG_DONE = -1800060, + SAY_MUG_GRATITUDE = -1800061, + SAY_MUG_PATROL = -1800062, + SAY_MUG_RETURN = -1800063, + + QUEST_VORSHA = 6641, + + GO_NAGA_BRAZIER = 178247, + + NPC_WRATH_RIDER = 3713, + NPC_WRATH_SORCERESS = 3717, + NPC_WRATH_RAZORTAIL = 3712, + + NPC_WRATH_PRIESTESS = 3944, + NPC_WRATH_MYRMIDON = 3711, + NPC_WRATH_SEAWITCH = 3715, + + NPC_VORSHA = 12940, + NPC_MUGLASH = 12717 +}; + +static float m_afFirstNagaCoord[3][3]= +{ + {3603.504150, 1122.631104, 1.635}, // rider + {3589.293945, 1148.664063, 5.565}, // sorceress + {3609.925537, 1168.759521, -1.168} // razortail +}; + +static float m_afSecondNagaCoord[3][3]= +{ + {3609.925537, 1168.759521, -1.168}, // witch + {3645.652100, 1139.425415, 1.322}, // priest + {3583.602051, 1128.405762, 2.347} // myrmidon +}; + +static float m_fVorshaCoord[]={3633.056885, 1172.924072, -5.388}; + + +struct npc_muglashAI : public npc_escortAI +{ + npc_muglashAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + uint32 m_uiWaveId; + uint32 m_uiEventTimer; + bool m_bIsBrazierExtinguished; + + void JustSummoned(Creature* pSummoned) + { + pSummoned->AI()->AttackStart(me); + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + switch(i) + { + case 0: + if (pPlayer) + DoScriptText(SAY_MUG_START2, me, pPlayer); + break; + case 24: + if (pPlayer) + DoScriptText(SAY_MUG_BRAZIER, me, pPlayer); + + if (GameObject* pGo = GetClosestGameObjectWithEntry(me, GO_NAGA_BRAZIER, INTERACTION_DISTANCE*2)) + { + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + SetEscortPaused(true); + } + break; + case 25: + DoScriptText(SAY_MUG_GRATITUDE, me); + + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_VORSHA, me); + break; + case 26: + DoScriptText(SAY_MUG_PATROL, me); + break; + case 27: + DoScriptText(SAY_MUG_RETURN, me); + break; + } + } + + void Aggro(Unit* /*pWho*/) + { + if (HasEscortState(STATE_ESCORT_PAUSED)) + { + if (urand(0, 1)) + DoScriptText(SAY_MUG_ON_GUARD, me); + return; + } + } + + void Reset() + { + m_uiEventTimer = 10000; + m_uiWaveId = 0; + m_bIsBrazierExtinguished = false; + } + + void JustDied(Unit* /*pKiller*/) + { + Player* pPlayer = GetPlayerForEscort(); + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (pPlayer) + { + pPlayer->FailQuest(QUEST_VORSHA); + } + } + } + + void DoWaveSummon() + { + switch(m_uiWaveId) + { + case 1: + me->SummonCreature(NPC_WRATH_RIDER, m_afFirstNagaCoord[0][0], m_afFirstNagaCoord[0][1], m_afFirstNagaCoord[0][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + me->SummonCreature(NPC_WRATH_SORCERESS, m_afFirstNagaCoord[1][0], m_afFirstNagaCoord[1][1], m_afFirstNagaCoord[1][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + me->SummonCreature(NPC_WRATH_RAZORTAIL, m_afFirstNagaCoord[2][0], m_afFirstNagaCoord[2][1], m_afFirstNagaCoord[2][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + break; + case 2: + me->SummonCreature(NPC_WRATH_PRIESTESS, m_afSecondNagaCoord[0][0], m_afSecondNagaCoord[0][1], m_afSecondNagaCoord[0][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + me->SummonCreature(NPC_WRATH_MYRMIDON, m_afSecondNagaCoord[1][0], m_afSecondNagaCoord[1][1], m_afSecondNagaCoord[1][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + me->SummonCreature(NPC_WRATH_SEAWITCH, m_afSecondNagaCoord[2][0], m_afSecondNagaCoord[2][1], m_afSecondNagaCoord[2][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + break; + case 3: + me->SummonCreature(NPC_VORSHA, m_fVorshaCoord[0], m_fVorshaCoord[1], m_fVorshaCoord[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + break; + case 4: + SetEscortPaused(false); + DoScriptText(SAY_MUG_DONE, me); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!me->getVictim()) + { + if (HasEscortState(STATE_ESCORT_PAUSED) && m_bIsBrazierExtinguished) + { + if (m_uiEventTimer < uiDiff) + { + ++m_uiWaveId; + DoWaveSummon(); + m_uiEventTimer = 10000; + } + else + m_uiEventTimer -= uiDiff; + } + return; + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_muglash(Creature* pCreature) +{ + return new npc_muglashAI(pCreature); +} + +bool QuestAccept_npc_muglash(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_VORSHA) + { + if (npc_muglashAI* pEscortAI = CAST_AI(npc_muglashAI, pCreature->AI())) + { + DoScriptText(SAY_MUG_START1, pCreature); + pCreature->setFaction(113); + + pEscortAI->Start(true, true, pPlayer->GetGUID()); + } + } + return true; +} + + +bool GOHello_go_naga_brazier(Player* /*pPlayer*/, GameObject* pGo) +{ + if (Creature* pCreature = GetClosestCreatureWithEntry(pGo, NPC_MUGLASH, INTERACTION_DISTANCE*2)) + { + if (npc_muglashAI* pEscortAI = CAST_AI(npc_muglashAI, pCreature->AI())) + { + DoScriptText(SAY_MUG_BRAZIER_WAIT, pCreature); + + pEscortAI->m_bIsBrazierExtinguished = true; + return false; + } + } + return true; +} + +void AddSC_ashenvale() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_torek"; + newscript->GetAI = &GetAI_npc_torek; + newscript->pQuestAccept = &QuestAccept_npc_torek; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ruul_snowhoof"; + newscript->GetAI = &GetAI_npc_ruul_snowhoofAI; + newscript->pQuestAccept = &QuestAccept_npc_ruul_snowhoof; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_muglash"; + newscript->GetAI = &GetAI_npc_muglash; + newscript->pQuestAccept = &QuestAccept_npc_muglash; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_naga_brazier"; + newscript->pGOHello = &GOHello_go_naga_brazier; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/azshara.cpp b/src/server/scripts/Kalimdor/azshara.cpp new file mode 100644 index 00000000000..937afe0ae5d --- /dev/null +++ b/src/server/scripts/Kalimdor/azshara.cpp @@ -0,0 +1,514 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Azshara +SD%Complete: 90 +SDComment: Quest support: 2744, 3141, 9364, 10994 +SDCategory: Azshara +EndScriptData */ + +/* ContentData +mobs_spitelashes +npc_loramus_thalipedes +mob_rizzle_sprysprocket +mob_depth_charge +EndContentData */ + +#include "ScriptedPch.h" +#include "World.h" +#include "WorldPacket.h" + +/*###### +## mobs_spitelashes +######*/ + +struct mobs_spitelashesAI : public ScriptedAI +{ + mobs_spitelashesAI(Creature *c) : ScriptedAI(c) {} + + uint32 morphtimer; + bool spellhit; + + void Reset() + { + morphtimer = 0; + spellhit = false; + } + + void EnterCombat(Unit * /*who*/) { } + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) + { + if (!spellhit && + Hitter->GetTypeId() == TYPEID_PLAYER && + CAST_PLR(Hitter)->GetQuestStatus(9364) == QUEST_STATUS_INCOMPLETE && + (Spellkind->Id == 118 || Spellkind->Id == 12824 || Spellkind->Id == 12825 || Spellkind->Id == 12826)) + { + spellhit=true; + DoCast(me, 29124); //become a sheep + } + } + + void UpdateAI(const uint32 diff) + { + // we mustn't remove the Creature in the same round in which we cast the summon spell, otherwise there will be no summons + if (spellhit && morphtimer >= 5000) + { + me->ForcedDespawn(); + return; + } + // walk 5 seconds before summoning + if (spellhit && morphtimer<5000) + { + morphtimer+=diff; + if (morphtimer >= 5000) + { + DoCast(me, 28406); //summon copies + DoCast(me, 6924); //visual explosion + } + } + if (!UpdateVictim()) + return; + + //TODO: add abilities for the different creatures + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mobs_spitelashes(Creature* pCreature) +{ + return new mobs_spitelashesAI (pCreature); +} + +/*###### +## npc_loramus_thalipedes +######*/ + +#define GOSSIP_HELLO_LT1 "Can you help me?" +#define GOSSIP_HELLO_LT2 "Tell me your story" +#define GOSSIP_SELECT_LT1 "Please continue" +#define GOSSIP_SELECT_LT2 "I do not understand" +#define GOSSIP_SELECT_LT3 "Indeed" +#define GOSSIP_SELECT_LT4 "I will do this with or your help, Loramus" +#define GOSSIP_SELECT_LT5 "Yes" + +bool GossipHello_npc_loramus_thalipedes(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(2744) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_LT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (pPlayer->GetQuestStatus(3141) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_LT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_loramus_thalipedes(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(2744); + break; + + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); + pPlayer->SEND_GOSSIP_MENU(1813, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+21: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); + pPlayer->SEND_GOSSIP_MENU(1814, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+22: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23); + pPlayer->SEND_GOSSIP_MENU(1815, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+23: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24); + pPlayer->SEND_GOSSIP_MENU(1816, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+24: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25); + pPlayer->SEND_GOSSIP_MENU(1817, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+25: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(3141); + break; + } + return true; +} + +/*#### +# mob_rizzle_sprysprocket +####*/ + +#define MOB_DEPTH_CHARGE 23025 +#define SPELL_RIZZLE_BLACKJACK 39865 +#define SPELL_RIZZLE_ESCAPE 39871 +#define SPELL_RIZZLE_FROST_GRENADE 40525 +#define SPELL_DEPTH_CHARGE_TRAP 38576 +#define SPELL_PERIODIC_DEPTH_CHARGE 39912 +#define SPELL_GIVE_SOUTHFURY_MOONSTONE 39886 + +#define SAY_RIZZLE_START -1000245 +#define SAY_RIZZLE_GRENADE -1000246 +#define SAY_RIZZLE_FINAL -1000247 + +#define GOSSIP_GET_MOONSTONE "Hand over the Southfury moonstone and I'll let you go." + +//next message must be send to player when Rizzle jump into river, not implemented +#define MSG_ESCAPE_NOTICE "Rizzle Sprysprocket takes the Southfury moonstone and escapes into the river. Follow her!" + +float WPs[58][4] = +{ +//pos_x pos_y pos_z orien +{3691.97, -3962.41, 35.9118, 3.67}, +{3675.02, -3960.49, 35.9118, 3.67}, +{3653.19, -3958.33, 33.9118, 3.59}, +{3621.12, -3958.51, 29.9118, 3.48}, +{3604.86, -3963, 29.9118, 3.48}, +{3569.94, -3970.25, 29.9118, 3.44}, +{3541.03, -3975.64, 29.9118, 3.41}, +{3510.84, -3978.71, 29.9118, 3.41}, +{3472.7, -3997.07, 29.9118, 3.35}, +{3439.15, -4014.55, 29.9118, 3.29}, +{3412.8, -4025.87, 29.9118, 3.25}, +{3384.95, -4038.04, 29.9118, 3.24}, +{3346.77, -4052.93, 29.9118, 3.22}, +{3299.56, -4071.59, 29.9118, 3.20}, +{3261.22, -4080.38, 30.9118, 3.19}, +{3220.68, -4083.09, 31.9118, 3.18}, +{3187.11, -4070.45, 33.9118, 3.16}, +{3162.78, -4062.75, 33.9118, 3.15}, +{3136.09, -4050.32, 33.9118, 3.07}, +{3119.47, -4044.51, 36.0363, 3.07}, +{3098.95, -4019.8, 33.9118, 3.07}, +{3073.07, -4011.42, 33.9118, 3.07}, +{3051.71, -3993.37, 33.9118, 3.02}, +{3027.52, -3978.6, 33.9118, 3.00}, +{3003.78, -3960.14, 33.9118, 2.98}, +{2977.99, -3941.98, 31.9118, 2.96}, +{2964.57, -3932.07, 30.9118, 2.96}, +{2947.9, -3921.31, 29.9118, 2.96}, +{2924.91, -3910.8, 29.9118, 2.94}, +{2903.04, -3896.42, 29.9118, 2.93}, +{2884.75, -3874.03, 29.9118, 2.90}, +{2868.19, -3851.48, 29.9118, 2.82}, +{2854.62, -3819.72, 29.9118, 2.80}, +{2825.53, -3790.4, 29.9118, 2.744}, +{2804.31, -3773.05, 29.9118, 2.71}, +{2769.78, -3763.57, 29.9118, 2.70}, +{2727.23, -3745.92, 30.9118, 2.69}, +{2680.12, -3737.49, 30.9118, 2.67}, +{2647.62, -3739.94, 30.9118, 2.66}, +{2616.6, -3745.75, 30.9118, 2.64}, +{2589.38, -3731.97, 30.9118, 2.61}, +{2562.94, -3722.35, 31.9118, 2.56}, +{2521.05, -3716.6, 31.9118, 2.55}, +{2485.26, -3706.67, 31.9118, 2.51}, +{2458.93, -3696.67, 31.9118, 2.51}, +{2432, -3692.03, 31.9118, 2.46}, +{2399.59, -3681.97, 31.9118, 2.45}, +{2357.75, -3666.6, 31.9118, 2.44}, +{2311.99, -3656.88, 31.9118, 2.94}, +{2263.41, -3649.55, 31.9118, 3.02}, +{2209.05, -3641.76, 31.9118, 2.99}, +{2164.83, -3637.64, 31.9118, 3.15}, +{2122.42, -3639, 31.9118, 3.21}, +{2075.73, -3643.59, 31.9118, 3.22}, +{2033.59, -3649.52, 31.9118, 3.42}, +{1985.22, -3662.99, 31.9118, 3.42}, +{1927.09, -3679.56, 33.9118, 3.42}, +{1873.57, -3695.32, 33.9118, 3.44} +}; + +struct mob_rizzle_sprysprocketAI : public ScriptedAI +{ + mob_rizzle_sprysprocketAI(Creature *c) : ScriptedAI(c) {} + + uint32 spellEscape_Timer; + uint32 Teleport_Timer; + uint32 Check_Timer; + uint32 Grenade_Timer; + uint32 Must_Die_Timer; + uint32 CurrWP; + + uint64 PlayerGUID; + + bool Must_Die; + bool Escape; + bool ContinueWP; + bool Reached; + + void Reset() + { + spellEscape_Timer = 1300; + Teleport_Timer = 3500; + Check_Timer = 10000; + Grenade_Timer = 30000; + Must_Die_Timer = 3000; + CurrWP = 0; + + PlayerGUID = 0; + + Must_Die = false; + Escape = false; + ContinueWP = false; + Reached = false; + } + + void UpdateAI(const uint32 diff) + { + if (Must_Die) + if (Must_Die_Timer <= diff) + { + me->ForcedDespawn(); + return; + } else Must_Die_Timer -= diff; + + if (!Escape) + { + if (!PlayerGUID) + return; + + if (spellEscape_Timer <= diff) + { + DoCast(me, SPELL_RIZZLE_ESCAPE, false); + spellEscape_Timer = 10000; + } else spellEscape_Timer -= diff; + + if (Teleport_Timer <= diff) + { + //temp solution - unit can't be teleported by core using spelleffect 5, only players + Map* pMap = me->GetMap(); + if (pMap) + { + pMap->CreatureRelocation(me, 3706.39, -3969.15, 35.9118, 0); + me->AI_SendMoveToPacket(3706.39, -3969.15, 35.9118, 0, 0, 0); + } + //begin swimming and summon depth charges + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + SendText(MSG_ESCAPE_NOTICE, pPlayer); + DoCast(me, SPELL_PERIODIC_DEPTH_CHARGE); + me->SetUnitMovementFlags(MOVEMENTFLAG_HOVER | MOVEMENTFLAG_SWIMMING); + me->SetSpeed(MOVE_RUN, 0.85f, true); + me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP][0], WPs[CurrWP][1], WPs[CurrWP][2]); + Escape = true; + } else Teleport_Timer -= diff; + + return; + } + + if (ContinueWP) + { + me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP][0], WPs[CurrWP][1], WPs[CurrWP][2]); + ContinueWP = false; + } + + if (Grenade_Timer <= diff) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer) + { + DoScriptText(SAY_RIZZLE_GRENADE, me, pPlayer); + DoCast(pPlayer, SPELL_RIZZLE_FROST_GRENADE, true); + } + Grenade_Timer = 30000; + } else Grenade_Timer -= diff; + + if (Check_Timer <= diff) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (!pPlayer) + { + me->ForcedDespawn(); + return; + } + + if (me->IsWithinDist(pPlayer, 10) && me->GetPositionX() > pPlayer->GetPositionX() && !Reached) + { + DoScriptText(SAY_RIZZLE_FINAL, me); + me->SetUInt32Value(UNIT_NPC_FLAGS, 1); + me->setFaction(35); + me->GetMotionMaster()->MoveIdle(); + me->RemoveAurasDueToSpell(SPELL_PERIODIC_DEPTH_CHARGE); + Reached = true; + } + + Check_Timer = 1000; + } else Check_Timer -= diff; + + } + + void SendText(const char *text, Player* pPlayer) + { + WorldPacket data(SMSG_SERVER_MESSAGE, 0); // guess size + data << text; + if (pPlayer) + pPlayer->GetSession()->SendPacket(&data); + } + + void AttackStart(Unit *who) + { + if (!who || PlayerGUID) + return; + + if (who->GetTypeId() == TYPEID_PLAYER && CAST_PLR(who)->GetQuestStatus(10994) == QUEST_STATUS_INCOMPLETE) + { + PlayerGUID = who->GetGUID(); + DoScriptText(SAY_RIZZLE_START, me); + DoCast(who, SPELL_RIZZLE_BLACKJACK, false); + return; + } + } + + void EnterCombat(Unit* /*who*/) {} + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 57) + { + me->ForcedDespawn(); + return; + } + + ++CurrWP; + ContinueWP = true; + } + +}; + +bool GossipHello_mob_rizzle_sprysprocket(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(10994) != QUEST_STATUS_INCOMPLETE) + return true; + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GET_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(10811, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_mob_rizzle_sprysprocket(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1 && pPlayer->GetQuestStatus(10994) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, SPELL_GIVE_SOUTHFURY_MOONSTONE, true); + CAST_AI(mob_rizzle_sprysprocketAI, pCreature->AI())->Must_Die_Timer = 3000; + CAST_AI(mob_rizzle_sprysprocketAI, pCreature->AI())->Must_Die = true; + } + return true; +} + +CreatureAI* GetAI_mob_rizzle_sprysprocket(Creature* pCreature) +{ + return new mob_rizzle_sprysprocketAI (pCreature); +} + +/*#### +# mob_depth_charge +####*/ + +struct mob_depth_chargeAI : public ScriptedAI +{ + mob_depth_chargeAI(Creature *c) : ScriptedAI(c) {} + + bool we_must_die; + uint32 must_die_timer; + + void Reset() + { + me->SetUnitMovementFlags(MOVEMENTFLAG_HOVER | MOVEMENTFLAG_SWIMMING); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + we_must_die = false; + must_die_timer = 1000; + } + + void UpdateAI(const uint32 diff) + { + if (we_must_die) + if (must_die_timer <= diff) + { + me->ForcedDespawn(); + } else must_die_timer -= diff; + return; + } + + void MoveInLineOfSight(Unit *who) + { + if (!who) + return; + + if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 5)) + { + DoCast(who, SPELL_DEPTH_CHARGE_TRAP); + we_must_die = true; + return; + } + } + + void AttackStart(Unit * /*who*/) + { + } + + void EnterCombat(Unit* /*who*/) + { + } +}; + +CreatureAI* GetAI_mob_depth_charge(Creature* pCreature) +{ + return new mob_depth_chargeAI (pCreature); +} + +void AddSC_azshara() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mobs_spitelashes"; + newscript->GetAI = &GetAI_mobs_spitelashes; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_loramus_thalipedes"; + newscript->pGossipHello = &GossipHello_npc_loramus_thalipedes; + newscript->pGossipSelect = &GossipSelect_npc_loramus_thalipedes; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_rizzle_sprysprocket"; + newscript->GetAI = &GetAI_mob_rizzle_sprysprocket; + newscript->pGossipHello = &GossipHello_mob_rizzle_sprysprocket; + newscript->pGossipSelect = &GossipSelect_mob_rizzle_sprysprocket; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_depth_charge"; + newscript->GetAI = &GetAI_mob_depth_charge; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/azuremyst_isle.cpp b/src/server/scripts/Kalimdor/azuremyst_isle.cpp new file mode 100644 index 00000000000..d31eaa9e84b --- /dev/null +++ b/src/server/scripts/Kalimdor/azuremyst_isle.cpp @@ -0,0 +1,718 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Azuremyst_Isle +SD%Complete: 75 +SDComment: Quest support: 9283, 9537, 9582, 9554, 9531, 9303(special flight path, proper model for mount missing). Injured Draenei cosmetic only, 9582. +SDCategory: Azuremyst Isle +EndScriptData */ + +/* ContentData +npc_draenei_survivor +npc_engineer_spark_overgrind +npc_injured_draenei +npc_magwin +npc_geezle +mob_nestlewood_owlkin +go_ravager_cage +npc_death_ravager +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include + +/*###### +## npc_draenei_survivor +######*/ + +enum eEnums +{ + SAY_HEAL1 = -1000176, + SAY_HEAL2 = -1000177, + SAY_HEAL3 = -1000178, + SAY_HEAL4 = -1000179, + + SAY_HELP1 = -1000180, + SAY_HELP2 = -1000181, + SAY_HELP3 = -1000182, + SAY_HELP4 = -1000183, + + SPELL_IRRIDATION = 35046, + SPELL_STUNNED = 28630 +}; + +struct npc_draenei_survivorAI : public ScriptedAI +{ + npc_draenei_survivorAI(Creature *c) : ScriptedAI(c) {} + + uint64 pCaster; + + uint32 SayThanksTimer; + uint32 RunAwayTimer; + uint32 SayHelpTimer; + + bool CanSayHelp; + + void Reset() + { + pCaster = 0; + + SayThanksTimer = 0; + RunAwayTimer = 0; + SayHelpTimer = 10000; + + CanSayHelp = true; + + DoCast(me, SPELL_IRRIDATION, true); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + me->SetHealth(int(me->GetMaxHealth()*.1)); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (CanSayHelp && who->GetTypeId() == TYPEID_PLAYER && me->IsFriendlyTo(who) && me->IsWithinDistInMap(who, 25.0f)) + { + //Random switch between 4 texts + DoScriptText(RAND(SAY_HELP1, SAY_HELP2, SAY_HELP3, SAY_HELP4), me, who); + + SayHelpTimer = 20000; + CanSayHelp = false; + } + } + + void SpellHit(Unit *Caster, const SpellEntry *Spell) + { + if (Spell->SpellFamilyFlags[2] & 0x080000000) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + + DoCast(me, SPELL_STUNNED, true); + + pCaster = Caster->GetGUID(); + + SayThanksTimer = 5000; + } + } + + void UpdateAI(const uint32 diff) + { + if (SayThanksTimer) + { + if (SayThanksTimer <= diff) + { + me->RemoveAurasDueToSpell(SPELL_IRRIDATION); + + if (Player* pPlayer = Unit::GetPlayer(pCaster)) + { + DoScriptText(RAND(SAY_HEAL1, SAY_HEAL2, SAY_HEAL3, SAY_HEAL4), me, pPlayer); + + pPlayer->TalkedToCreature(me->GetEntry(),me->GetGUID()); + } + + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, -4115.053711f, -13754.831055f, 73.508949f); + + RunAwayTimer = 10000; + SayThanksTimer = 0; + } else SayThanksTimer -= diff; + + return; + } + + if (RunAwayTimer) + { + if (RunAwayTimer <= diff) + me->ForcedDespawn(); + else + RunAwayTimer -= diff; + + return; + } + + if (SayHelpTimer <= diff) + { + CanSayHelp = true; + SayHelpTimer = 20000; + } else SayHelpTimer -= diff; + } +}; +CreatureAI* GetAI_npc_draenei_survivor(Creature* pCreature) +{ + return new npc_draenei_survivorAI (pCreature); +} + +/*###### +## npc_engineer_spark_overgrind +######*/ + +enum eOvergrind +{ + SAY_TEXT = -1000184, + SAY_EMOTE = -1000185, + ATTACK_YELL = -1000186, + + AREA_COVE = 3579, + AREA_ISLE = 3639, + QUEST_GNOMERCY = 9537, + FACTION_HOSTILE = 14, + SPELL_DYNAMITE = 7978 +}; + +#define GOSSIP_FIGHT "Traitor! You will be brought to justice!" + +struct npc_engineer_spark_overgrindAI : public ScriptedAI +{ + npc_engineer_spark_overgrindAI(Creature *c) : ScriptedAI(c) + { + NormFaction = c->getFaction(); + NpcFlags = c->GetUInt32Value(UNIT_NPC_FLAGS); + + if (c->GetAreaId() == AREA_COVE || c->GetAreaId() == AREA_ISLE) + IsTreeEvent = true; + } + + uint32 NormFaction; + uint32 NpcFlags; + + uint32 Dynamite_Timer; + uint32 Emote_Timer; + + bool IsTreeEvent; + + void Reset() + { + Dynamite_Timer = 8000; + Emote_Timer = 120000 + rand()%30000; + + me->setFaction(NormFaction); + me->SetUInt32Value(UNIT_NPC_FLAGS, NpcFlags); + + IsTreeEvent = false; + } + + void EnterCombat(Unit* who) + { + DoScriptText(ATTACK_YELL, me, who); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat() && !IsTreeEvent) + { + if (Emote_Timer <= diff) + { + DoScriptText(SAY_TEXT, me); + DoScriptText(SAY_EMOTE, me); + Emote_Timer = 120000 + rand()%30000; + } else Emote_Timer -= diff; + } + else if (IsTreeEvent) + return; + + if (!UpdateVictim()) + return; + + if (Dynamite_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DYNAMITE); + Dynamite_Timer = 8000; + } else Dynamite_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_engineer_spark_overgrind(Creature* pCreature) +{ + return new npc_engineer_spark_overgrindAI (pCreature); +} + +bool GossipHello_npc_engineer_spark_overgrind(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_GNOMERCY) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_engineer_spark_overgrind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(FACTION_HOSTILE); + CAST_AI(npc_engineer_spark_overgrindAI, pCreature->AI())->AttackStart(pPlayer); + } + return true; +} + +/*###### +## npc_injured_draenei +######*/ + +struct npc_injured_draeneiAI : public ScriptedAI +{ + npc_injured_draeneiAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + me->SetHealth(int(me->GetMaxHealth()*.15)); + switch (rand()%2) + { + case 0: me->SetStandState(UNIT_STAND_STATE_SIT); break; + case 1: me->SetStandState(UNIT_STAND_STATE_SLEEP); break; + } + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 /*diff*/) + { + } + +}; +CreatureAI* GetAI_npc_injured_draenei(Creature* pCreature) +{ + return new npc_injured_draeneiAI (pCreature); +} + +/*###### +## npc_magwin +######*/ + +enum eMagwin +{ + SAY_START = -1000111, + SAY_AGGRO = -1000112, + SAY_PROGRESS = -1000113, + SAY_END1 = -1000114, + SAY_END2 = -1000115, + EMOTE_HUG = -1000116, + + QUEST_A_CRY_FOR_SAY_HELP = 9528 +}; + +struct npc_magwinAI : public npc_escortAI +{ + npc_magwinAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 0: + DoScriptText(SAY_START, me, pPlayer); + break; + case 17: + DoScriptText(SAY_PROGRESS, me, pPlayer); + break; + case 28: + DoScriptText(SAY_END1, me, pPlayer); + break; + case 29: + DoScriptText(EMOTE_HUG, me, pPlayer); + DoScriptText(SAY_END2, me, pPlayer); + pPlayer->GroupEventHappens(QUEST_A_CRY_FOR_SAY_HELP,me); + break; + } + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me, who); + } + + void Reset() { } +}; + +bool QuestAccept_npc_magwin(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_A_CRY_FOR_SAY_HELP) + { + pCreature->setFaction(113); + if (npc_escortAI* pEscortAI = CAST_AI(npc_escortAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_magwinAI(Creature* pCreature) +{ + return new npc_magwinAI(pCreature); +} + +/*###### +## npc_geezle +######*/ + +enum eGeezle +{ + QUEST_TREES_COMPANY = 9531, + + SPELL_TREE_DISGUISE = 30298, + + GEEZLE_SAY_1 = -1100259, + SPARK_SAY_2 = -1100260, + SPARK_SAY_3 = -1100261, + GEEZLE_SAY_4 = -1100262, + SPARK_SAY_5 = -1100263, + SPARK_SAY_6 = -1100264, + GEEZLE_SAY_7 = -1100265, + + EMOTE_SPARK = -1100266, + + MOB_SPARK = 17243, + GO_NAGA_FLAG = 181694 +}; + +static float SparkPos[3] = {-5029.91, -11291.79, 8.096}; + +struct npc_geezleAI : public ScriptedAI +{ + npc_geezleAI(Creature *c) : ScriptedAI(c) {} + + uint64 SparkGUID; + + uint32 Step; + uint32 SayTimer; + + bool EventStarted; + + void Reset() + { + SparkGUID = 0; + Step = 0; + StartEvent(); + } + + void EnterCombat(Unit* /*who*/){} + + void StartEvent() + { + Step = 0; + EventStarted = true; + Creature* Spark = me->SummonCreature(MOB_SPARK, SparkPos[0], SparkPos[1], SparkPos[2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000); + if (Spark) + { + SparkGUID = Spark->GetGUID(); + Spark->setActive(true); + Spark->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + SayTimer = 8000; + } + + uint32 NextStep(uint32 Step) + { + Creature* Spark = Unit::GetCreature(*me, SparkGUID); + + switch(Step) + { + case 0: + if (Spark) + Spark->GetMotionMaster()->MovePoint(0, -5080.70, -11253.61, 0.56); + me->GetMotionMaster()->MovePoint(0, -5092.26, -11252, 0.71); + return 9000; // NPCs are walking up to fire + case 1: + DespawnNagaFlag(true); + DoScriptText(EMOTE_SPARK, Spark); + return 1000; + case 2: + DoScriptText(GEEZLE_SAY_1, me, Spark); + if (Spark) + { + Spark->SetInFront(me); + me->SetInFront(Spark); + } + return 5000; + case 3: DoScriptText(SPARK_SAY_2, Spark); return 7000; + case 4: DoScriptText(SPARK_SAY_3, Spark); return 8000; + case 5: DoScriptText(GEEZLE_SAY_4, me, Spark); return 8000; + case 6: DoScriptText(SPARK_SAY_5, Spark); return 9000; + case 7: DoScriptText(SPARK_SAY_6, Spark); return 8000; + case 8: DoScriptText(GEEZLE_SAY_7, me, Spark); return 2000; + case 9: + me->GetMotionMaster()->MoveTargetedHome(); + if (Spark) + Spark->GetMotionMaster()->MovePoint(0, SparkPos[0], SparkPos[1], SparkPos[2]); + CompleteQuest(); + return 9000; + case 10: + if (Spark) + Spark->DisappearAndDie(); + DespawnNagaFlag(false); + me->DisappearAndDie(); + default: return 99999999; + } + } + + // will complete Tree's company quest for all nearby players that are disguised as trees + void CompleteQuest() + { + float radius = 50.0f; + std::list players; + Trinity::AnyPlayerInObjectRangeCheck checker(me, radius); + Trinity::PlayerListSearcher searcher(me, players, checker); + me->VisitNearbyWorldObject(radius, searcher); + + for (std::list::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if ((*itr)->GetQuestStatus(QUEST_TREES_COMPANY) == QUEST_STATUS_INCOMPLETE + &&(*itr)->HasAura(SPELL_TREE_DISGUISE)) + { + (*itr)->KilledMonsterCredit(MOB_SPARK,0); + } + } + } + + void DespawnNagaFlag(bool despawn) + { + std::list FlagList; + me->GetGameObjectListWithEntryInGrid(FlagList,GO_NAGA_FLAG, 100.0f); + + if (!FlagList.empty()) + { + for (std::list::const_iterator itr = FlagList.begin(); itr != FlagList.end(); ++itr) + { + if (despawn) + { + (*itr)->SetLootState(GO_JUST_DEACTIVATED); + } + else + (*itr)->Respawn(); + } + } else error_log("SD2 ERROR: FlagList is empty!"); + } + + void UpdateAI(const uint32 diff) + { + if (SayTimer <= diff) + { + if (EventStarted) + { + SayTimer = NextStep(Step++); + } + } else SayTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_geezleAI(Creature* pCreature) +{ + return new npc_geezleAI(pCreature); +} + +/*###### +## mob_nestlewood_owlkin +######*/ + +enum eOwlkin +{ + SPELL_INOCULATE_OWLKIN = 29528, + ENTRY_OWLKIN = 16518, + ENTRY_OWLKIN_INOC = 16534 +}; + +struct npc_nestlewood_owlkinAI : public ScriptedAI +{ + npc_nestlewood_owlkinAI(Creature *c) : ScriptedAI(c) {} + + uint32 DespawnTimer; + + void Reset() + { + DespawnTimer = 0; + } + + void UpdateAI(const uint32 diff) + { + //timer gets adjusted by the triggered aura effect + if (DespawnTimer) + { + if (DespawnTimer <= diff) + { + //once we are able to, despawn us + me->ForcedDespawn(); + return; + } else DespawnTimer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_nestlewood_owlkinAI(Creature* pCreature) +{ + return new npc_nestlewood_owlkinAI (pCreature); +} + +bool EffectDummyCreature_npc_nestlewood_owlkin(Unit * /*pCaster*/, uint32 spellId, uint32 effIndex, Creature *pCreatureTarget) +{ + //always check spellid and effectindex + if (spellId == SPELL_INOCULATE_OWLKIN && effIndex == 0) + { + if (pCreatureTarget->GetEntry() != ENTRY_OWLKIN) + return true; + + pCreatureTarget->UpdateEntry(ENTRY_OWLKIN_INOC); + + //set despawn timer, since we want to remove Creature after a short time + CAST_AI(npc_nestlewood_owlkinAI, pCreatureTarget->AI())->DespawnTimer = 15000; + + //always return true when we are handling this spell and effect + return true; + } + return false; +} + +enum eRavegerCage +{ + NPC_DEATH_RAVAGER = 17556, + + SPELL_REND = 13443, + SPELL_ENRAGING_BITE = 30736, + + QUEST_STRENGTH_ONE = 9582 +}; + +bool go_ravager_cage(Player* pPlayer, GameObject* pGo) +{ + + if (pPlayer->GetQuestStatus(QUEST_STRENGTH_ONE) == QUEST_STATUS_INCOMPLETE) + { + if (Creature* ravager = pGo->FindNearestCreature(NPC_DEATH_RAVAGER, 5.0f, true)) + { + ravager->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + ravager->SetReactState(REACT_AGGRESSIVE); + ravager->AI()->AttackStart(pPlayer); + } + } + return true ; +} + +struct npc_death_ravagerAI : public ScriptedAI +{ + npc_death_ravagerAI(Creature *c) : ScriptedAI(c){} + + uint32 RendTimer; + uint32 EnragingBiteTimer; + + void Reset() + { + RendTimer = 30000; + EnragingBiteTimer = 20000; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (RendTimer <= diff) + { + DoCast(me->getVictim(), SPELL_REND); + RendTimer = 30000; + } + else RendTimer -= diff; + + if (EnragingBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ENRAGING_BITE); + EnragingBiteTimer = 15000; + } + else EnragingBiteTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_death_ravagerAI(Creature* pCreature) +{ + return new npc_death_ravagerAI(pCreature); +} + +void AddSC_azuremyst_isle() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_draenei_survivor"; + newscript->GetAI = &GetAI_npc_draenei_survivor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_engineer_spark_overgrind"; + newscript->GetAI = &GetAI_npc_engineer_spark_overgrind; + newscript->pGossipHello = &GossipHello_npc_engineer_spark_overgrind; + newscript->pGossipSelect = &GossipSelect_npc_engineer_spark_overgrind; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_injured_draenei"; + newscript->GetAI = &GetAI_npc_injured_draenei; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_magwin"; + newscript->GetAI = &GetAI_npc_magwinAI; + newscript->pQuestAccept = &QuestAccept_npc_magwin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_geezle"; + newscript->GetAI = &GetAI_npc_geezleAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_nestlewood_owlkin"; + newscript->GetAI = &GetAI_npc_nestlewood_owlkinAI; + newscript->pEffectDummyCreature = &EffectDummyCreature_npc_nestlewood_owlkin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="npc_death_ravager"; + newscript->GetAI = &GetAI_npc_death_ravagerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="go_ravager_cage"; + newscript->pGOHello = &go_ravager_cage; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp new file mode 100644 index 00000000000..a3fd42a0fe7 --- /dev/null +++ b/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp @@ -0,0 +1,252 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" +#include "ScriptedEscortAI.h" + +enum eSpells +{ + SPELL_BLESSING_OF_BLACKFATHOM = 8733, + SPELL_RAVAGE = 8391, + SPELL_FROST_NOVA = 865, + SPELL_FROST_BOLT_VOLLEY = 8398, + SPELL_TELEPORT_DARNASSUS = 9268 +}; + +#define GOSSIP_ITEM_MORRIDUNE "Please port me to Darnassus" + +const Position HomePosition = {-815.817,-145.299,-25.870, 0}; + +bool GoHello_blackfathom_altar(Player *pPlayer, GameObject* /*pGo*/) +{ + if (!pPlayer->HasAura(SPELL_BLESSING_OF_BLACKFATHOM)) + pPlayer->AddAura(SPELL_BLESSING_OF_BLACKFATHOM,pPlayer); + return true; +} + +bool GoHello_blackfathom_fire(Player * /*pPlayer*/, GameObject* pGo) +{ + ScriptedInstance *pInstance = pGo->GetInstanceData(); + + if (pInstance) + { + pGo->SetGoState(GO_STATE_ACTIVE); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pInstance->SetData(DATA_FIRE, pInstance->GetData(DATA_FIRE) + 1); + return true; + } + return false; +} + +struct npc_blackfathom_deeps_eventAI : public ScriptedAI +{ + npc_blackfathom_deeps_eventAI(Creature* pCreature) : ScriptedAI(pCreature) + { + if (pCreature->isSummon()) + { + pCreature->SetHomePosition(HomePosition); + AttackPlayer(); + } + + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiRavageTimer; + uint32 uiFrostNovaTimer; + uint32 uiFrostBoltVolleyTimer; + + bool bFlee; + + void Reset() + { + bFlee = false; + + uiRavageTimer = urand(5000,8000); + uiFrostNovaTimer = urand(9000,12000); + uiFrostBoltVolleyTimer = urand(2000,4000); + } + + void AttackPlayer() + { + Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + me->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(me); + me->AddThreat(pPlayer, 0.0f); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + switch (me->GetEntry()) + { + case NPC_AKU_MAI_SNAPJAW: + { + if (uiRavageTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_RAVAGE); + uiRavageTimer = urand(9000,14000); + } else uiRavageTimer -= uiDiff; + break; + } + case NPC_MURKSHALLOW_SOFTSHELL: + case NPC_BARBED_CRUSTACEAN: + { + if (!bFlee && HealthBelowPct(15)) + { + bFlee = true; + me->DoFleeToGetAssistance(); + } + break; + } + case NPC_AKU_MAI_SERVANT: + { + if (uiFrostBoltVolleyTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget) + DoCast(pTarget, SPELL_FROST_BOLT_VOLLEY); + } + uiFrostBoltVolleyTimer = urand(5000,8000); + } else uiFrostBoltVolleyTimer -= uiDiff; + if (uiFrostNovaTimer <= uiDiff) + { + DoCastAOE(SPELL_FROST_NOVA,false); + uiFrostNovaTimer = urand(25000,30000); + } else uiFrostNovaTimer -= uiDiff; + break; + } + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (me->isSummon()) //we are not a normal spawn. + if (pInstance) + pInstance->SetData(DATA_EVENT, pInstance->GetData(DATA_EVENT) + 1); + } +}; + +CreatureAI* GetAI_npc_blackfathom_deeps_event(Creature* pCreature) +{ + return new npc_blackfathom_deeps_eventAI (pCreature); +} + +enum eMorridune +{ + SAY_MORRIDUNE_1 = -1048003, + SAY_MORRIDUNE_2 = -1048004 +}; + +struct npc_morriduneAI : public npc_escortAI +{ + npc_morriduneAI(Creature* pCreature) : npc_escortAI(pCreature) + { + DoScriptText(SAY_MORRIDUNE_1,pCreature); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + Start(false,false,NULL); + } + + void WaypointReached(uint32 uiPoint) + { + switch(uiPoint) + { + case 4: + SetEscortPaused(true); + me->SetOrientation(1.775791); + me->SendMovementFlagUpdate(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + DoScriptText(SAY_MORRIDUNE_2,me); + break; + } + } +}; + +CreatureAI* GetAI_npc_morridune(Creature* pCreature) +{ + return new npc_morriduneAI (pCreature); +} + +bool GossipHello_npc_morridune(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MORRIDUNE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_morridune(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->TeleportTo(1,9952.239,2284.277,1341.394,1.595); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +void AddSC_blackfathom_deeps() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "go_blackfathom_altar"; + newscript->pGOHello = &GoHello_blackfathom_altar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_blackfathom_fire"; + newscript->pGOHello = &GoHello_blackfathom_fire; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_blackfathom_deeps_event"; + newscript->GetAI = &GetAI_npc_blackfathom_deeps_event; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_morridune"; + newscript->GetAI = &GetAI_npc_morridune; + newscript->pGossipHello = &GossipHello_npc_morridune; + newscript->pGossipSelect = &GossipSelect_npc_morridune; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h b/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h new file mode 100644 index 00000000000..e8bbab9f105 --- /dev/null +++ b/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BFD_H +#define DEF_BFD_H + +enum Data64 +{ + DATA_SHRINE1, + DATA_SHRINE2, + DATA_SHRINE3, + DATA_SHRINE4, + DATA_TWILIGHT_LORD_KELRIS, + DATA_SHRINE_OF_GELIHAST, + DATA_ALTAR_OF_THE_DEEPS, + DATA_MAINDOOR, +}; + +enum Data +{ + TYPE_GELIHAST, + TYPE_KELRIS, + TYPE_SHRINE, + TYPE_AKU_MAI, + DATA_FIRE, + DATA_EVENT +}; + +enum Creatures +{ + NPC_TWILIGHT_LORD_KELRIS = 4832, + NPC_LORGUS_JETT = 12902, + + NPC_AKU_MAI_SNAPJAW = 4825, + NPC_MURKSHALLOW_SOFTSHELL = 4977, + NPC_AKU_MAI_SERVANT = 4978, + NPC_BARBED_CRUSTACEAN = 4823, + + NPC_MORRIDUNE = 6729 +}; + +enum GameObjects +{ + GO_SHRINE_OF_GELIHAST = 103015, + GO_FIRE_OF_AKU_MAI_1 = 21118, + GO_FIRE_OF_AKU_MAI_2 = 21119, + GO_FIRE_OF_AKU_MAI_3 = 21120, + GO_FIRE_OF_AKU_MAI_4 = 21121, + GO_AKU_MAI_DOOR = 21117, + GO_ALTAR_OF_THE_DEEPS = 103016 +}; +#endif diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp new file mode 100644 index 00000000000..a4b7a160be8 --- /dev/null +++ b/src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp @@ -0,0 +1,94 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" + +enum Spells +{ + SPELL_POISON_CLOUD = 3815, + SPELL_FRENZIED_RAGE = 3490 +}; + +struct boss_aku_maiAI : public ScriptedAI +{ + boss_aku_maiAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiPoisonCloudTimer; + bool bIsEnraged; + + ScriptedInstance *pInstance; + + void Reset() + { + uiPoisonCloudTimer = urand(5000,9000); + bIsEnraged = false; + if (pInstance) + pInstance->SetData(TYPE_AKU_MAI, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(TYPE_AKU_MAI, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_AKU_MAI, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiPoisonCloudTimer < diff) + { + DoCastVictim(SPELL_POISON_CLOUD); + uiPoisonCloudTimer = urand(25000,50000); + } else uiPoisonCloudTimer -= diff; + + if (!bIsEnraged && HealthBelowPct(30)) + { + DoCast(me,SPELL_FRENZIED_RAGE); + bIsEnraged = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_aku_mai(Creature* pCreature) +{ + return new boss_aku_maiAI (pCreature); +} + +void AddSC_boss_aku_mai() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_aku_mai"; + newscript->GetAI = &GetAI_boss_aku_mai; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp new file mode 100644 index 00000000000..374a526f098 --- /dev/null +++ b/src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp @@ -0,0 +1,85 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" + +enum Spells +{ + SPELL_NET = 6533 +}; + +struct boss_gelihastAI : public ScriptedAI +{ + boss_gelihastAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiNetTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiNetTimer = urand(2000,4000); + if (pInstance) + pInstance->SetData(TYPE_GELIHAST, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(TYPE_GELIHAST, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_GELIHAST, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiNetTimer < diff) + { + DoCastVictim(SPELL_NET); + uiNetTimer = urand(4000,7000); + } else uiNetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_gelihast(Creature* pCreature) +{ + return new boss_gelihastAI (pCreature); +} + +void AddSC_boss_gelihast() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_gelihast"; + newscript->GetAI = &GetAI_boss_gelihast; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp new file mode 100644 index 00000000000..bd7e1014d1a --- /dev/null +++ b/src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp @@ -0,0 +1,108 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" + +enum Spells +{ + SPELL_MIND_BLAST = 15587, + SPELL_SLEEP = 8399, +}; + +//Id's from ACID +enum Yells +{ + SAY_AGGRO = -1048002, + SAY_SLEEP = -1048001, + SAY_DEATH = -1048000 +}; + +struct boss_kelrisAI : public ScriptedAI +{ + boss_kelrisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiMindBlastTimer; + uint32 uiSleepTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiMindBlastTimer = urand(2000,5000); + uiSleepTimer = urand(9000,12000); + if (pInstance) + pInstance->SetData(TYPE_KELRIS, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(TYPE_KELRIS, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + pInstance->SetData(TYPE_KELRIS, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiMindBlastTimer < diff) + { + DoCastVictim(SPELL_MIND_BLAST); + uiMindBlastTimer = urand(7000,9000); + } else uiMindBlastTimer -= diff; + + if (uiSleepTimer < diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(SAY_SLEEP, me); + DoCast(pTarget, SPELL_SLEEP); + } + uiSleepTimer = urand(15000,20000); + } else uiSleepTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kelris(Creature* pCreature) +{ + return new boss_kelrisAI (pCreature); +} + +void AddSC_boss_kelris() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_kelris"; + newscript->GetAI = &GetAI_boss_kelris; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp new file mode 100644 index 00000000000..a485684e699 --- /dev/null +++ b/src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp @@ -0,0 +1,259 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Blackfathom_Deeps +SD%Complete: 50 +SDComment: +SDCategory: Blackfathom Deeps +EndScriptData */ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" + +#define MAX_ENCOUNTER 4 + +/* Encounter 0 = Gelihast + Encounter 1 = Twilight Lord Kelris + Encounter 2 = Shrine event + Encounter 3 = Aku'Mai + */ + +const Position LorgusPosition[4] = +{ + { -458.500610, -38.343079, -33.474445 }, + { -469.423615, -88.400513, -39.265102 }, + { -622.354980, -10.350100, -22.777000 }, + { -759.640564, 16.658913, -29.159529 } +}; + +const Position SpawnsLocation[] = +{ + {-775.431, -153.853, -25.871, 3.207}, + {-775.404, -174.132, -25.871, 3.185}, + {-862.430, -154.937, -25.871, 0.060}, + {-862.193, -174.251, -25.871, 6.182}, + {-863.895, -458.899, -33.891, 5.637} +}; + +struct instance_blackfathom_deeps : public ScriptedInstance +{ + instance_blackfathom_deeps(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 m_uiTwilightLordKelrisGUID; + uint64 m_uiShrine1GUID; + uint64 m_uiShrine2GUID; + uint64 m_uiShrine3GUID; + uint64 m_uiShrine4GUID; + uint64 m_uiShrineOfGelihastGUID; + uint64 m_uiAltarOfTheDeepsGUID; + uint64 m_uiMainDoorGUID; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + uint8 m_uiCountFires; + uint8 uiDeathTimes; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiTwilightLordKelrisGUID = 0; + m_uiShrine1GUID = 0; + m_uiShrine2GUID = 0; + m_uiShrine3GUID = 0; + m_uiShrine4GUID = 0; + m_uiShrineOfGelihastGUID = 0; + m_uiAltarOfTheDeepsGUID = 0; + m_uiMainDoorGUID = 0; + m_uiCountFires = 0; + uiDeathTimes = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case NPC_TWILIGHT_LORD_KELRIS: + m_uiTwilightLordKelrisGUID = pCreature->GetGUID(); + break; + case NPC_LORGUS_JETT: + pCreature->SetHomePosition(LorgusPosition[urand(0,3)]); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_FIRE_OF_AKU_MAI_1: + m_uiShrine1GUID = pGo->GetGUID(); + break; + case GO_FIRE_OF_AKU_MAI_2: + m_uiShrine2GUID = pGo->GetGUID(); + break; + case GO_FIRE_OF_AKU_MAI_3: + m_uiShrine3GUID = pGo->GetGUID(); + break; + case GO_FIRE_OF_AKU_MAI_4: + m_uiShrine4GUID = pGo->GetGUID(); + break; + case GO_SHRINE_OF_GELIHAST: + m_uiShrineOfGelihastGUID = pGo->GetGUID(); + if (m_auiEncounter[0] != DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case GO_ALTAR_OF_THE_DEEPS: + m_uiAltarOfTheDeepsGUID = pGo->GetGUID(); + if (m_auiEncounter[3] != DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case GO_AKU_MAI_DOOR: + if (m_auiEncounter[2] == DONE) + HandleGameObject(NULL,true,pGo); + m_uiMainDoorGUID = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_GELIHAST: + m_auiEncounter[0] = uiData; + if (uiData == DONE) + if (GameObject *pGo = instance->GetGameObject(m_uiShrineOfGelihastGUID)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case TYPE_AKU_MAI: + m_auiEncounter[3] = uiData; + if (uiData == DONE) + if (GameObject *pGo = instance->GetGameObject(m_uiAltarOfTheDeepsGUID)) + { + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGo->SummonCreature(NPC_MORRIDUNE,SpawnsLocation[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + break; + case DATA_FIRE: + m_uiCountFires = uiData; + switch (m_uiCountFires) + { + case 1: + if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) + { + pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + break; + case 2: + if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) + { + for (uint8 i = 0; i < 2; ++i) + { + pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + } + break; + case 3: + if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) + { + pGO->SummonCreature(NPC_AKU_MAI_SERVANT, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_AKU_MAI_SERVANT, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + break; + case 4: + if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) + { + pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + break; + } + break; + case DATA_EVENT: + uiDeathTimes = uiData; + if (uiDeathTimes == 18) + HandleGameObject(m_uiMainDoorGUID,true); + break; + } + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_GELIHAST: + return m_auiEncounter[0]; + case TYPE_KELRIS: + return m_auiEncounter[1]; + case TYPE_SHRINE: + return m_auiEncounter[2]; + case TYPE_AKU_MAI: + return m_auiEncounter[3]; + case DATA_FIRE: + return m_uiCountFires; + case DATA_EVENT: + return uiDeathTimes; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_TWILIGHT_LORD_KELRIS: + return m_uiTwilightLordKelrisGUID; + case DATA_SHRINE1: + return m_uiShrine1GUID; + case DATA_SHRINE2: + return m_uiShrine2GUID; + case DATA_SHRINE3: + return m_uiShrine3GUID; + case DATA_SHRINE4: + return m_uiShrine4GUID; + case DATA_SHRINE_OF_GELIHAST: + return m_uiShrineOfGelihastGUID; + case DATA_MAINDOOR: + return m_uiMainDoorGUID; + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_blackfathom_deeps(Map* pMap) +{ + return new instance_blackfathom_deeps(pMap); +} + +void AddSC_instance_blackfathom_deeps() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blackfathom_deeps"; + newscript->GetInstanceData = &GetInstanceData_instance_blackfathom_deeps; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/bloodmyst_isle.cpp b/src/server/scripts/Kalimdor/bloodmyst_isle.cpp new file mode 100644 index 00000000000..108d03b8976 --- /dev/null +++ b/src/server/scripts/Kalimdor/bloodmyst_isle.cpp @@ -0,0 +1,149 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Bloodmyst_Isle +SD%Complete: 80 +SDComment: Quest support: 9670, 9756(gossip items text needed). +SDCategory: Bloodmyst Isle +EndScriptData */ + +/* ContentData +mob_webbed_creature +npc_captured_sunhawk_agent +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## mob_webbed_creature +######*/ + +//possible creatures to be spawned +const uint32 possibleSpawns[32] = {17322, 17661, 17496, 17522, 17340, 17352, 17333, 17524, 17654, 17348, 17339, 17345, 17359, 17353, 17336, 17550, 17330, 17701, 17321, 17680, 17325, 17320, 17683, 17342, 17715, 17334, 17341, 17338, 17337, 17346, 17344, 17327}; + +struct mob_webbed_creatureAI : public ScriptedAI +{ + mob_webbed_creatureAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + } + + void EnterCombat(Unit* /*who*/) + { + } + + void JustDied(Unit* Killer) + { + uint32 spawnCreatureID = 0; + + switch (urand(0,2)) + { + case 0: + spawnCreatureID = 17681; + if (Killer->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(Killer)->KilledMonsterCredit(spawnCreatureID, me->GetGUID()); + break; + case 1: + case 2: + spawnCreatureID = possibleSpawns[urand(0,30)]; + break; + } + + if (spawnCreatureID) + me->SummonCreature(spawnCreatureID, 0.0f, 0.0f, 0.0f, me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + } +}; +CreatureAI* GetAI_mob_webbed_creature(Creature* pCreature) +{ + return new mob_webbed_creatureAI (pCreature); +} + +/*###### +## npc_captured_sunhawk_agent +######*/ + +#define C_SUNHAWK_TRIGGER 17974 + +#define GOSSIP_HELLO_CSA "[PH] " +#define GOSSIP_SELECT_CSA1 "[PH] " +#define GOSSIP_SELECT_CSA2 "[PH] " +#define GOSSIP_SELECT_CSA3 "[PH] " +#define GOSSIP_SELECT_CSA4 "[PH] " +#define GOSSIP_SELECT_CSA5 "[PH] " + +bool GossipHello_npc_captured_sunhawk_agent(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->HasAura(31609) && pPlayer->GetQuestStatus(9756) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_CSA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(9136, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(9134, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_captured_sunhawk_agent(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(9137, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(9138, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(9139, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(9140, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(9141, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->TalkedToCreature(C_SUNHAWK_TRIGGER, pCreature->GetGUID()); + break; + } + return true; +} + +void AddSC_bloodmyst_isle() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_webbed_creature"; + newscript->GetAI = &GetAI_mob_webbed_creature; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_captured_sunhawk_agent"; + newscript->pGossipHello = &GossipHello_npc_captured_sunhawk_agent; + newscript->pGossipSelect = &GossipSelect_npc_captured_sunhawk_agent; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/boss_azuregos.cpp b/src/server/scripts/Kalimdor/boss_azuregos.cpp new file mode 100644 index 00000000000..8aeedfa199e --- /dev/null +++ b/src/server/scripts/Kalimdor/boss_azuregos.cpp @@ -0,0 +1,155 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Azuregos +SD%Complete: 90 +SDComment: Teleport not included, spell reflect not effecting dots (Core problem) +SDCategory: Azshara +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_TELEPORT -1000100 + +#define SPELL_MARKOFFROST 23182 +#define SPELL_MANASTORM 21097 +#define SPELL_CHILL 21098 +#define SPELL_FROSTBREATH 21099 +#define SPELL_REFLECT 22067 +#define SPELL_CLEAVE 8255 //Perhaps not right ID +#define SPELL_ENRAGE 23537 + +struct boss_azuregosAI : public ScriptedAI +{ + boss_azuregosAI(Creature *c) : ScriptedAI(c) {} + + uint32 MarkOfFrost_Timer; + uint32 ManaStorm_Timer; + uint32 Chill_Timer; + uint32 Breath_Timer; + uint32 Teleport_Timer; + uint32 Reflect_Timer; + uint32 Cleave_Timer; + uint32 Enrage_Timer; + bool Enraged; + + void Reset() + { + MarkOfFrost_Timer = 35000; + ManaStorm_Timer = 5000 + rand()%12000; + Chill_Timer = 10000 + rand()%20000; + Breath_Timer = 2000 + rand()%6000; + Teleport_Timer = 30000; + Reflect_Timer = 15000 + rand()%15000; + Cleave_Timer = 7000; + Enrage_Timer = 0; + Enraged = false; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Teleport_Timer <= diff) + { + DoScriptText(SAY_TELEPORT, me); + std::list& m_threatlist = me->getThreatManager().getThreatList(); + std::list::const_iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+3, pUnit->GetOrientation()); + } + } + + DoResetThreat(); + Teleport_Timer = 30000; + } else Teleport_Timer -= diff; + + // //MarkOfFrost_Timer + // if (MarkOfFrost_Timer <= diff) + // { + // DoCast(me->getVictim(), SPELL_MARKOFFROST); + // MarkOfFrost_Timer = 25000; + // } else MarkOfFrost_Timer -= diff; + + //Chill_Timer + if (Chill_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CHILL); + Chill_Timer = 13000 + rand()%12000; + } else Chill_Timer -= diff; + + //Breath_Timer + if (Breath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBREATH); + Breath_Timer = 10000 + rand()%5000; + } else Breath_Timer -= diff; + + //ManaStorm_Timer + if (ManaStorm_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_MANASTORM); + ManaStorm_Timer = 7500 + rand()%5000; + } else ManaStorm_Timer -= diff; + + //Reflect_Timer + if (Reflect_Timer <= diff) + { + DoCast(me, SPELL_REFLECT); + Reflect_Timer = 20000 + rand()%15000; + } else Reflect_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //Enrage_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 26 && !Enraged) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_azuregos(Creature* pCreature) +{ + return new boss_azuregosAI (pCreature); +} + +void AddSC_boss_azuregos() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_azuregos"; + newscript->GetAI = &GetAI_boss_azuregos; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp new file mode 100644 index 00000000000..287d3cf8e9b --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp @@ -0,0 +1,156 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* Script Data Start +SDName: Boss epoch +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro, consecutive attacks to a random target durin time wrap, adjust timers +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CURSE_OF_EXERTION = 52772, + SPELL_TIME_WARP = 52766, //Time slows down, reducing attack, casting and movement speed by 70% for 6 sec. + SPELL_TIME_STOP = 58848, //Stops time in a 50 yard sphere for 2 sec. + SPELL_WOUNDING_STRIKE = 52771, //Used only on the tank + H_SPELL_WOUNDING_STRIKE = 58830 +}; + +enum Yells +{ + SAY_INTRO = -1595000, //"Prince Arthas Menethil, on this day, a powerful darkness has taken hold of your soul. The death you are destined to visit upon others will this day be your own." + SAY_AGGRO = -1595001, //"We'll see about that, young prince." + SAY_TIME_WARP_1 = -1595002, //"Tick tock, tick tock..." + SAY_TIME_WARP_2 = -1595003, //"Not quick enough!" + SAY_TIME_WARP_3 = -1595004, //"Let's get this over with. " + SAY_SLAY_1 = -1595005, //"There is no future for you." + SAY_SLAY_2 = -1595006, //"This is the hour of our greatest triumph!" + SAY_SLAY_3 = -1595007, //"You were destined to fail. " + SAY_DEATH = -1595008 //"*gurgles*" +}; + +struct boss_epochAI : public ScriptedAI +{ + boss_epochAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint8 uiStep; + + uint32 uiStepTimer; + uint32 uiWoundingStrikeTimer; + uint32 uiTimeWarpTimer; + uint32 uiTimeStopTimer; + uint32 uiCurseOfExertionTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiStep = 1; + uiStepTimer = 26000; + uiCurseOfExertionTimer = 9300; + uiTimeWarpTimer = 25300; + uiTimeStopTimer = 21300; + uiWoundingStrikeTimer = 5300; + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiCurseOfExertionTimer < diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CURSE_OF_EXERTION); + uiCurseOfExertionTimer = 9300; + } else uiCurseOfExertionTimer -= diff; + + if (uiWoundingStrikeTimer < diff) + { + DoCastVictim(SPELL_WOUNDING_STRIKE); + uiWoundingStrikeTimer = 5300; + } else uiWoundingStrikeTimer -= diff; + + if (uiTimeStopTimer < diff) + { + DoCastAOE(SPELL_TIME_STOP); + uiTimeStopTimer = 21300; + } else uiTimeStopTimer -= diff; + + if (uiTimeWarpTimer < diff) + { + DoScriptText(RAND(SAY_TIME_WARP_1,SAY_TIME_WARP_2,SAY_TIME_WARP_3), me); + DoCastAOE(SPELL_TIME_WARP); + uiTimeWarpTimer = 25300; + } else uiTimeWarpTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_epoch(Creature* pCreature) +{ + return new boss_epochAI (pCreature); +} + +void AddSC_boss_epoch() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_epoch"; + newscript->GetAI = &GetAI_boss_epoch; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp new file mode 100644 index 00000000000..12cdf00f2a5 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp @@ -0,0 +1,88 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CORRUPTING_BLIGHT = 60588, + SPELL_VOID_STRIKE = 60590 +}; + +enum Yells +{ + SAY_AGGRO = -1595045, + SAY_FAIL = -1595046, + SAY_DEATH = -1595047 +}; + + +struct boss_infinite_corruptorAI : public ScriptedAI +{ + boss_infinite_corruptorAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, DONE); + } +}; + +CreatureAI* GetAI_boss_infinite_corruptor(Creature* pCreature) +{ + return new boss_infinite_corruptorAI(pCreature); +} + +void AddSC_boss_infinite_corruptor() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_infinite_corruptor"; + newscript->GetAI = &GetAI_boss_infinite_corruptor; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp new file mode 100644 index 00000000000..a39f3289a5a --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp @@ -0,0 +1,262 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss mal_ganis +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro & outro +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_mal_ganis' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CARRION_SWARM = 52720, //A cresting wave of chaotic magic splashes over enemies in front of the caster, dealing 3230 to 3570 Shadow damage and 380 to 420 Shadow damage every 3 sec. for 15 sec. + H_SPELL_CARRION_SWARM = 58852, + SPELL_MIND_BLAST = 52722, //Inflicts 4163 to 4837 Shadow damage to an enemy. + H_SPELL_MIND_BLAST = 58850, + SPELL_SLEEP = 52721, //Puts an enemy to sleep for up to 10 sec. Any damage caused will awaken the target. + H_SPELL_SLEEP = 58849, + SPELL_VAMPIRIC_TOUCH = 52723 //Heals the caster for half the damage dealt by a melee attack. +}; + +enum Yells +{ + SAY_INTRO_1 = -1595009, + SAY_INTRO_2 = -1595010, + SAY_AGGRO = -1595011, + SAY_KILL_1 = -1595012, + SAY_KILL_2 = -1595013, + SAY_KILL_3 = -1595014, + SAY_SLAY_1 = -1595015, + SAY_SLAY_2 = -1595016, + SAY_SLAY_3 = -1595017, + SAY_SLAY_4 = -1595018, + SAY_SLEEP_1 = -1595019, + SAY_SLEEP_2 = -1595020, + SAY_30HEALTH = -1595021, + SAY_15HEALTH = -1595022, + SAY_ESCAPE_SPEECH_1 = -1595023, + SAY_ESCAPE_SPEECH_2 = -1595024, + SAY_OUTRO = -1595025, +}; + +enum CombatPhases +{ + COMBAT, + OUTRO +}; + +struct boss_mal_ganisAI : public ScriptedAI +{ + boss_mal_ganisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiCarrionSwarmTimer; + uint32 uiMindBlastTimer; + uint32 uiVampiricTouchTimer; + uint32 uiSleepTimer; + + uint8 uiOutroStep; + uint32 uiOutroTimer; + + bool bYelled; + bool bYelled2; + + CombatPhases Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + bYelled = false; + bYelled2 = false; + Phase = COMBAT; + uiCarrionSwarmTimer = 6000; + uiMindBlastTimer = 11000; + uiVampiricTouchTimer = urand(10000,15000); + uiSleepTimer = urand(15000,20000); + uiOutroTimer = 1000; + + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, IN_PROGRESS); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = me->GetHealth()-1; + } + + void UpdateAI(const uint32 diff) + { + switch(Phase) + { + case COMBAT: + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bYelled && HealthBelowPct(30)) + { + DoScriptText(SAY_30HEALTH, me); + bYelled = true; + } + + if (!bYelled2 && HealthBelowPct(15)) + { + DoScriptText(SAY_15HEALTH, me); + bYelled2 = true; + } + + if (HealthBelowPct(1)) + { + //Handle Escape Event: Don't forget to add Player::RewardPlayerAndGroupAtEvent + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + uiOutroStep = 1; + Phase = OUTRO; + return; + } + + if (Creature* pArthas = me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0)) + if (pArthas->isDead()) + { + EnterEvadeMode(); + me->DisappearAndDie(); + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, FAIL); + } + + if (uiCarrionSwarmTimer < diff) + { + DoCastVictim(SPELL_CARRION_SWARM); + uiCarrionSwarmTimer = 7000; + } else uiCarrionSwarmTimer -= diff; + + if (uiMindBlastTimer < diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_MIND_BLAST); + uiMindBlastTimer = 6000; + } else uiMindBlastTimer -= diff; + + if (uiVampiricTouchTimer < diff) + { + DoCast(me, SPELL_VAMPIRIC_TOUCH); + uiVampiricTouchTimer = 32000; + } else uiVampiricTouchTimer -= diff; + + if (uiSleepTimer < diff) + { + DoScriptText(RAND(SAY_SLEEP_1,SAY_SLEEP_2), me); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SLEEP); + uiSleepTimer = urand(15000,20000); + } else uiSleepTimer -= diff; + + DoMeleeAttackIfReady(); + break; + case OUTRO: + if (uiOutroTimer < diff) + { + switch(uiOutroStep) + { + case 1: + DoScriptText(SAY_ESCAPE_SPEECH_1, me); + me->GetMotionMaster()->MoveTargetedHome(); + ++uiOutroStep; + uiOutroTimer = 8000; + break; + case 2: + me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0); + me->HandleEmoteCommand(29); + DoScriptText(SAY_ESCAPE_SPEECH_2, me); + ++uiOutroStep; + uiOutroTimer = 9000; + break; + case 3: + DoScriptText(SAY_OUTRO, me); + ++uiOutroStep; + uiOutroTimer = 16000; + break; + case 4: + me->HandleEmoteCommand(33); + ++uiOutroStep; + uiOutroTimer = 500; + break; + case 5: + me->SetVisibility(VISIBILITY_OFF); + me->Kill(me); + break; + + } + } else uiOutroTimer -= diff; + break; + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_MAL_GANIS_EVENT, DONE); + + // give achievement credit to players. criteria use spell 58630 which doesn't exist. + if (pInstance) + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 58630); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } +}; + +CreatureAI* GetAI_boss_mal_ganis(Creature* pCreature) +{ + return new boss_mal_ganisAI (pCreature); +} + +void AddSC_boss_mal_ganis() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_mal_ganis"; + newscript->GetAI = &GetAI_boss_mal_ganis; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp new file mode 100644 index 00000000000..eba9733c745 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp @@ -0,0 +1,140 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss meathook +SDAuthor: Tartalo +SD%Complete: 100 +SDComment: It may need timer adjustment +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CONSTRICTING_CHAINS = 52696, //Encases the targets in chains, dealing 1800 Physical damage every 1 sec. and stunning the target for 5 sec. + H_SPELL_CONSTRICTING_CHAINS = 58823, + SPELL_DISEASE_EXPULSION = 52666, //Meathook belches out a cloud of disease, dealing 1710 to 1890 Nature damage and interrupting the spell casting of nearby enemy targets for 4 sec. + H_SPELL_DISEASE_EXPULSION = 58824, + SPELL_FRENZY = 58841 //Increases the caster's Physical damage by 10% for 30 sec. +}; + +enum Yells +{ + SAY_AGGRO = -1595026, + SAY_SLAY_1 = -1595027, + SAY_SLAY_2 = -1595028, + SAY_SLAY_3 = -1595029, + SAY_SPAWN = -1595030, + SAY_DEATH = -1595031 +}; + +struct boss_meathookAI : public ScriptedAI +{ + boss_meathookAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + DoScriptText(SAY_SPAWN,me); + } + + uint32 uiChainTimer; + uint32 uiDiseaseTimer; + uint32 uiFrenzyTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiChainTimer = urand(12000,17000); //seen on video 13, 17, 15, 12, 16 + uiDiseaseTimer = urand(2000,4000); //approx 3s + uiFrenzyTimer = urand(21000,26000); //made it up + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiDiseaseTimer <= diff) + { + DoCastAOE(SPELL_DISEASE_EXPULSION); + uiDiseaseTimer = urand(1500,4000); + } else uiDiseaseTimer -= diff; + + if (uiFrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + uiFrenzyTimer = urand(21000,26000); + } else uiFrenzyTimer -= diff; + + if (uiChainTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CONSTRICTING_CHAINS); //anyone but the tank + uiChainTimer = urand(2000,4000); + } else uiChainTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_meathook(Creature* pCreature) +{ + return new boss_meathookAI (pCreature); +} + +void AddSC_boss_meathook() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_meathook"; + newscript->GetAI = &GetAI_boss_meathook; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp new file mode 100644 index 00000000000..da1c8098517 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp @@ -0,0 +1,170 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss salramm +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_salramm' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CURSE_OF_TWISTED_FLESH = 58845, + SPELL_EXPLODE_GHOUL = 52480, + H_SPELL_EXPLODE_GHOUL = 58825, + SPELL_SHADOW_BOLT = 57725, + H_SPELL_SHADOW_BOLT = 58828, + SPELL_STEAL_FLESH = 52708, + SPELL_SUMMON_GHOULS = 52451 +}; + +enum Yells +{ + SAY_AGGRO = -1595032, + SAY_SPAWN = -1595033, + SAY_SLAY_1 = -1595034, + SAY_SLAY_2 = -1595035, + SAY_SLAY_3 = -1595036, + SAY_DEATH = -1595037, + SAY_EXPLODE_GHOUL_1 = -1595038, + SAY_EXPLODE_GHOUL_2 = -1595039, + SAY_STEAL_FLESH_1 = -1595040, + SAY_STEAL_FLESH_2 = -1595041, + SAY_STEAL_FLESH_3 = -1595042, + SAY_SUMMON_GHOULS_1 = -1595043, + SAY_SUMMON_GHOULS_2 = -1595044 +}; + +struct boss_salrammAI : public ScriptedAI +{ + boss_salrammAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + DoScriptText(SAY_SPAWN,me); + } + + uint32 uiCurseFleshTimer; + uint32 uiExplodeGhoulTimer; + uint32 uiShadowBoltTimer; + uint32 uiStealFleshTimer; + uint32 uiSummonGhoulsTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiCurseFleshTimer = 30000; //30s DBM + uiExplodeGhoulTimer = urand(25000,28000); //approx 6 sec after summon ghouls + uiShadowBoltTimer = urand(8000,12000); // approx 10s + uiStealFleshTimer = 12345; + uiSummonGhoulsTimer = urand(19000,24000); //on a video approx 24s after aggro + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Curse of twisted flesh timer + if (uiCurseFleshTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSE_OF_TWISTED_FLESH); + uiCurseFleshTimer = 37000; + } else uiCurseFleshTimer -= diff; + + //Shadow bolt timer + if (uiShadowBoltTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + uiShadowBoltTimer = urand(8000,12000); + } else uiShadowBoltTimer -= diff; + + //Steal Flesh timer + if (uiStealFleshTimer <= diff) + { + DoScriptText(RAND(SAY_STEAL_FLESH_1,SAY_STEAL_FLESH_2,SAY_STEAL_FLESH_3), me); + if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(random_pTarget, SPELL_STEAL_FLESH); + uiStealFleshTimer = 10000; + } else uiStealFleshTimer -= diff; + + //Summon ghouls timer + if (uiSummonGhoulsTimer <= diff) + { + DoScriptText(RAND(SAY_SUMMON_GHOULS_1,SAY_SUMMON_GHOULS_2), me); + if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(random_pTarget, SPELL_SUMMON_GHOULS); + uiSummonGhoulsTimer = 10000; + } else uiSummonGhoulsTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_salramm(Creature* pCreature) +{ + return new boss_salrammAI (pCreature); +} + +void AddSC_boss_salramm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_salramm"; + newscript->GetAI = &GetAI_boss_salramm; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp new file mode 100644 index 00000000000..faaed2eb6db --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp @@ -0,0 +1,1210 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" +#include "ScriptedEscortAI.h" + +enum Says +{ + //First Act - Uther and Jaina Dialog + SAY_PHASE101 = -1595070, //Arthas + SAY_PHASE102 = -1595071, //Uther + SAY_PHASE103 = -1595072, //Arthas + SAY_PHASE104 = -1595073, //Arthas + SAY_PHASE105 = -1595074, //Uther + SAY_PHASE106 = -1595075, //Arthas + SAY_PHASE107 = -1595076, //Uther + SAY_PHASE108 = -1595077, //Arthas + SAY_PHASE109 = -1595078, //Arthas + SAY_PHASE110 = -1595079, //Uther + SAY_PHASE111 = -1595080, //Arthas + SAY_PHASE112 = -1595081, //Uther + SAY_PHASE113 = -1595082, //Jaina + SAY_PHASE114 = -1595083, //Arthas + SAY_PHASE115 = -1595084, //Uther + SAY_PHASE116 = -1595085, //Arthas + SAY_PHASE117 = -1595086, //Jaina + SAY_PHASE118 = -1595087, //Arthas + //Second Act - City Streets + SAY_PHASE201 = -1595088, //Arthas + SAY_PHASE202 = -1595089, //Cityman + SAY_PHASE203 = -1595090, //Arthas + SAY_PHASE204 = -1595091, //Crazyman + SAY_PHASE205 = -1595092, //Arthas + SAY_PHASE206 = -1595009, //Malganis + SAY_PHASE207 = -1595010, //Malganis + SAY_PHASE208 = -1595093, //Arthas + SAY_PHASE209 = -1595094, //Arthas + SAY_PHASE210 = -1595095, //Arthas + //Third Act - Town Hall + SAY_PHASE301 = -1595096, //Arthas + SAY_PHASE302 = -1595097, //Drakonian + SAY_PHASE303 = -1595098, //Arthas + SAY_PHASE304 = -1595099, //Arthas + SAY_PHASE305 = -1595100, //Drakonian + SAY_PHASE306 = -1595101, //Arthas + SAY_PHASE307 = -1595102, //Arthas + SAY_PHASE308 = -1595103, //Arthas + SAY_PHASE309 = -1595104, //Arthas + SAY_PHASE310 = -1595105, //Arthas + SAY_PHASE311 = -1595106, //Arthas + SAY_PHASE312 = -1595107, //Arthas + SAY_PHASE313 = -1595108, //Arthas + SAY_PHASE314 = -1595000, //Epoch + SAY_PHASE315 = -1595109, //Arthas + //Fourth Act - Fire Corridor + SAY_PHASE401 = -1595110, //Arthas + SAY_PHASE402 = -1595111, //Arthas + SAY_PHASE403 = -1595112, //Arthas + SAY_PHASE404 = -1595113, //Arthas + SAY_PHASE405 = -1595114, //Arthas + SAY_PHASE406 = -1595115, //Arthas + SAY_PHASE407 = -1595116, //Arthas + //Fifth Act - Mal'Ganis Fight + SAY_PHASE501 = -1595117, //Arthas + SAY_PHASE502 = -1595118, //Arthas + SAY_PHASE503 = -1595119, //Arthas + SAY_PHASE504 = -1595120, //Arthas +}; + +enum NPCs +{ + NPC_INFINITE_ADVERSARY = 27742, + NPC_INFINITE_HUNTER = 27743, + NPC_INFINITE_AGENT = 27744, + NPC_TIME_RIFT = 28409, + NPC_ZOMBIE = 27737, + NPC_GHOUL = 28249, + NPC_NECROMANCER = 28200, + NPC_STALKER = 28199, + NPC_FIEND = 27734, + NPC_GOLEM = 28201, + NPC_EGHOUL = 27729, + NPC_CONSTRUCT = 27736, + + NPC_INVIS_TARGET = 20562, + + NPC_KNIGHT_ESCORT = 27745, + NPC_PRIEST_ESCORT = 27747, + NPC_CITY_MAN = 28167, + NPC_CITY_MAN2 = 28169, + NPC_CITY_MAN3 = 31126, + NPC_CITY_MAN4 = 31127, +}; + +enum Spells +{ + SPELL_FEAR = 39176, + SPELL_ARTHAS_AURA = 52442, + SPELL_EXORCISM_N = 52445, + SPELL_EXORCISM_H = 58822, + SPELL_HOLY_LIGHT = 52444, +}; + +enum GossipMenuArthas +{ + GOSSIP_MENU_ARTHAS_1 = 100001, + GOSSIP_MENU_ARTHAS_2 = 100002, + GOSSIP_MENU_ARTHAS_3 = 100003, + GOSSIP_MENU_ARTHAS_4 = 100004, + GOSSIP_MENU_ARTHAS_5 = 100005 +}; + +enum +{ + ENCOUNTER_WAVES_NUMBER = 8, + ENCOUNTER_WAVES_MAX_SPAWNS = 5, + ENCOUNTER_DRACONIAN_NUMBER = 4, + ENCOUNTER_CHRONO_SPAWNS = 19 +}; + +// Locations for necromancers and add to spawn +float WavesLocations[ENCOUNTER_WAVES_NUMBER][ENCOUNTER_WAVES_MAX_SPAWNS][5]= +{ + { + {NPC_ZOMBIE, 2164.698975, 1255.392944, 135.040878, 0.490202}, + {NPC_ZOMBIE, 2183.501465, 1263.079102, 134.859055, 3.169981}, + {NPC_GHOUL, 2177.512939, 1247.313843, 135.846695, 1.696574}, + {NPC_GHOUL, 2171.991943, 1246.615845, 135.745026, 1.696574}, + {0, 0, 0, 0, 0} + }, + { + {NPC_GHOUL, 2254.434326, 1163.427612, 138.055038, 2.077358}, + {NPC_GHOUL, 2254.703613, 1158.867798, 138.212234, 2.345532}, + {NPC_GHOUL, 2257.615723, 1162.310913, 138.091202, 2.077358}, + {NPC_NECROMANCER, 2258.258057, 1157.250732, 138.272873, 2.387766}, + {0, 0, 0, 0, 0} + }, + { + {NPC_STALKER, 2348.120117, 1202.302490, 130.491104, 4.698538}, + {NPC_GHOUL, 2352.863525, 1207.819092, 130.424271, 4.949865}, + {NPC_GHOUL, 2343.593750, 1207.915039, 130.781311, 4.321547}, + {NPC_NECROMANCER, 2348.257324, 1212.202515, 130.670135, 4.450352}, + {0, 0, 0, 0, 0} + }, + { + {NPC_STALKER, 2139.825195, 1356.277100, 132.199615, 5.820131}, + {NPC_GHOUL, 2137.073486, 1362.464844, 132.271637, 5.820131}, + {NPC_GHOUL, 2134.075684, 1354.148071, 131.885864, 5.820131}, + {NPC_NECROMANCER, 2133.302246, 1358.907837, 132.037689, 5.820131}, + {0, 0, 0, 0, 0} + }, + { + {NPC_NECROMANCER, 2264.013428, 1174.055908, 138.093094, 2.860481}, + {NPC_GHOUL, 2264.207764, 1170.892700, 138.034973, 2.860481}, + {NPC_GHOUL, 2266.948975, 1176.898926, 137.976929, 2.860481}, + {NPC_STALKER, 2269.215576, 1170.109253, 137.742691, 2.860481}, + {NPC_FIEND, 2273.106689, 1176.101074, 137.880508, 2.860481} + }, + { + {NPC_GOLEM, 2349.701660, 1188.436646, 130.428864, 3.908642}, + {NPC_GHOUL, 2349.909180, 1194.582642, 130.417816, 3.577001}, + {NPC_EGHOUL, 2354.662598, 1185.692017, 130.552032, 3.577001}, + {NPC_EGHOUL, 2354.716797, 1191.614380, 130.539810, 3.577001}, + {0, 0, 0, 0, 0} + }, + { + {NPC_CONSTRUCT, 2145.212891, 1355.288086, 132.288773, 6.004838}, + {NPC_NECROMANCER, 2137.078613, 1357.612671, 132.173340, 6.004838}, + {NPC_EGHOUL, 2139.402100, 1352.541626, 132.127518, 5.812850}, + {NPC_EGHOUL, 2142.408447, 1360.760620, 132.321564, 5.812850}, + {0, 0, 0, 0, 0} + }, + { + {NPC_GHOUL, 2172.686279, 1259.618164, 134.391754, 1.865499}, + {NPC_FIEND, 2177.649170, 1256.061157, 135.096512, 1.849572}, + {NPC_CONSTRUCT, 2170.782959, 1253.594849, 134.973022, 1.849572}, + {NPC_NECROMANCER, 2175.595703, 1249.041992, 135.603531, 1.849572}, + {0, 0, 0, 0, 0} + } +}; + +// Locations for rifts to spawn and draconians to go +float RiftAndSpawnsLocations[ENCOUNTER_CHRONO_SPAWNS][5]= +{ + {NPC_TIME_RIFT, 2431.790039, 1190.670044, 148.076004, 0.187923}, + {NPC_INFINITE_ADVERSARY, 2433.857910, 1185.612061, 148.075974, 4.566168}, + {NPC_INFINITE_ADVERSARY, 2437.577881, 1188.241089, 148.075974, 0.196999}, + {NPC_INFINITE_AGENT, 2437.165527, 1192.294922, 148.075974, 0.169247}, + {NPC_INFINITE_HUNTER, 2434.989990, 1197.679565, 148.075974, 0.715971}, + {NPC_TIME_RIFT, 2403.954834, 1178.815430, 148.075943, 4.966126}, + {NPC_INFINITE_AGENT, 2403.676758, 1171.495850, 148.075607, 4.902797}, + {NPC_INFINITE_HUNTER, 2407.691162, 1172.162720, 148.075607, 4.963010}, + {NPC_TIME_RIFT, 2414.217041, 1133.446167, 148.076050, 1.706972}, + {NPC_INFINITE_ADVERSARY, 2416.024658, 1139.456177, 148.076431, 1.752129}, + {NPC_INFINITE_HUNTER, 2410.866699, 1139.680542, 148.076431, 1.752129}, + {NPC_TIME_RIFT, 2433.081543, 1099.869751, 148.076157, 1.809509}, + {NPC_INFINITE_ADVERSARY, 2426.947998, 1107.471680, 148.076019, 1.877580}, + {NPC_INFINITE_HUNTER, 2432.944580, 1108.896362, 148.208160, 2.199241}, + {NPC_TIME_RIFT, 2444.077637, 1114.366089, 148.076157, 3.049565}, + {NPC_INFINITE_ADVERSARY, 2438.190674, 1118.368164, 148.076172, 3.139232}, + {NPC_INFINITE_AGENT, 2435.861328, 1113.402954, 148.169327, 2.390271}, + {NPC_TIME_RIFT, 2463.131592, 1115.391724, 152.473129, 3.409651}, + {NPC_EPOCH, 2451.809326, 1112.901245, 149.220459, 3.363617} +}; + +struct npc_arthasAI : public npc_escortAI +{ + npc_arthasAI(Creature *pCreature) : npc_escortAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + + bool bStepping; + uint32 uiStep; + uint32 uiPhaseTimer; + uint32 uiGossipStep; + uint32 uiPlayerFaction; + uint32 uiBossEvent; + uint32 uiWave; + + uint64 uiUtherGUID; + uint64 uiJainaGUID; + uint64 uiCitymenGUID[2]; + uint64 uiWaveGUID[ENCOUNTER_WAVES_MAX_SPAWNS]; + uint64 uiInfiniteDraconianGUID[ENCOUNTER_DRACONIAN_NUMBER]; + uint64 uiStalkerGUID; + + uint64 uiBossGUID; //uiMeathookGUID || uiSalrammGUID + uint64 uiEpochGUID; + uint64 uiMalganisGUID; + uint64 uiInfiniteGUID; + + uint32 uiExorcismTimer; + + void Reset() + { + uiUtherGUID = 0; + uiJainaGUID = 0; + + for (uint8 i = 0; i < 2; ++i) + uiCitymenGUID[i] = 0; + + for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + uiWaveGUID[i] = 0; + + for (uint8 i = 0; i < ENCOUNTER_DRACONIAN_NUMBER; ++i) + uiInfiniteDraconianGUID[i] = 0; + + uiStalkerGUID = 0; + uiBossGUID = 0; + uiEpochGUID = 0; + uiMalganisGUID = 0; + uiInfiniteGUID = 0; + + if (pInstance) { + pInstance->SetData(DATA_ARTHAS_EVENT, NOT_STARTED); + switch(pInstance->GetData(DATA_ARTHAS_EVENT)) + { + case NOT_STARTED: + bStepping = true; + uiStep = 0; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + uiBossEvent = DATA_MEATHOOK_EVENT; + uiGossipStep = 0; + break; + } + uiPhaseTimer = 1000; + uiExorcismTimer = 7300; + uiWave = 0; + } + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_ARTHAS_AURA); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ARTHAS_EVENT, FAIL); + } + + void SpawnTimeRift(uint32 timeRiftID, uint64* guidVector) + { + me->SummonCreature((uint32)RiftAndSpawnsLocations[timeRiftID][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_DESPAWN,11000); + + for (uint32 i = timeRiftID+1; i < ENCOUNTER_CHRONO_SPAWNS; ++i) + { + if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_TIME_RIFT) break; + if (Creature* pTemp = me->SummonCreature((uint32)RiftAndSpawnsLocations[i][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + guidVector[i-timeRiftID-1] = pTemp->GetGUID(); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pTemp->SetReactState(REACT_PASSIVE); + pTemp->GetMotionMaster()->MovePoint(0, RiftAndSpawnsLocations[i][1],RiftAndSpawnsLocations[i][2],RiftAndSpawnsLocations[i][3]); + if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_EPOCH) + uiEpochGUID = pTemp->GetGUID(); + } + } + } + + void SpawnWaveGroup(uint32 waveID, uint64* guidVector) + { + for (uint32 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + { + if ((uint32)WavesLocations[waveID][i][0] == 0) break; + if (Creature* pTemp = me->SummonCreature((uint32)WavesLocations[waveID][i][0],WavesLocations[waveID][i][1],WavesLocations[waveID][i][2],WavesLocations[waveID][i][3],WavesLocations[waveID][i][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + guidVector[i] = pTemp->GetGUID(); + } + } + } + + void SetHoldState(bool bOnHold) + { + SetEscortPaused(bOnHold); + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhaseTimer = uiTimer; + ++uiStep; + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 0: + case 1: + case 3: + case 9: + case 10: + case 11: + case 22: + case 23: + case 26: + case 55: + case 56: + SetHoldState(true); + bStepping = true; + break; + case 7: + if (Unit* pCityman0 = me->SummonCreature(NPC_CITY_MAN,2091.977f,1275.021f,140.757f,0.558f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) + uiCitymenGUID[0] = pCityman0->GetGUID(); + if (Unit* pCityman1 = me->SummonCreature(NPC_CITY_MAN2,2093.514f,1275.842f,140.408f,3.801f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) + uiCitymenGUID[1] = pCityman1->GetGUID(); + break; + case 8: + uiGossipStep = 1; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + case 12: + SetRun(true); + DoScriptText(SAY_PHASE210, me); + if (Unit* pDisguised0 = me->SummonCreature(NPC_CITY_MAN3,2398.14f,1207.81f,134.04f,5.155249f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[0] = pDisguised0->GetGUID(); + if (Unit* pDisguised1 = me->SummonCreature(NPC_CITY_MAN4,2403.22f,1205.54f,134.04f,3.311264f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[1] = pDisguised1->GetGUID(); + + if (Unit* pDisguised2 = me->SummonCreature(NPC_CITY_MAN,2400.82f,1201.69f,134.01f,1.534082f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[2] = pDisguised2->GetGUID(); + pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); + pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[0]); + pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); + } + } + } + break; + case 20: + uiGossipStep = 2; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetRun(false); + SetHoldState(true); + break; + case 21: + DoScriptText(SAY_PHASE301, me); + break; + case 25: + SetRun(false); + SpawnTimeRift(0,&uiInfiniteDraconianGUID[0]); + DoScriptText(SAY_PHASE307,me); + break; + case 29: + SetRun(false); + SpawnTimeRift(5,&uiInfiniteDraconianGUID[0]); + SpawnTimeRift(8,&uiInfiniteDraconianGUID[2]); + DoScriptText(SAY_PHASE309,me); + SetHoldState(true); + bStepping = true; + break; + case 31: + SetRun(false); + SpawnTimeRift(11,&uiInfiniteDraconianGUID[0]); + SpawnTimeRift(14,&uiInfiniteDraconianGUID[2]); + DoScriptText(SAY_PHASE311,me); + SetHoldState(true); + bStepping = true; + break; + case 32: + DoScriptText(SAY_PHASE401,me); + break; + case 34: + DoScriptText(SAY_PHASE402,me); + break; + case 35: + DoScriptText(SAY_PHASE403,me); + break; + case 36: + if (pInstance) + { + GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SHKAF_GATE)); + pGate->SetGoState(GO_STATE_ACTIVE); + } + break; + case 45: + SetRun(true); + SetDespawnAtFar(false); + uiGossipStep = 4; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + case 47: + SetRun(false); + DoScriptText(SAY_PHASE405,me); + break; + case 48: + SetRun(true); + DoScriptText(SAY_PHASE406,me); + break; + case 53: + DoScriptText(SAY_PHASE407,me); + break; + case 54: + uiGossipStep = 5; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + } + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + DoMeleeAttackIfReady(); + + if (bStepping) + { + if (uiPhaseTimer <= diff) + { + switch(uiStep) + { + //After reset + case 0: + if (Unit* pJaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f)) + uiJainaGUID = pJaina->GetGUID(); + else if (Unit* pJaina = me->SummonCreature(NPC_JAINA,1895.48f,1292.66f,143.706f,0.023475f,TEMPSUMMON_DEAD_DESPAWN,180000)) + uiJainaGUID = pJaina->GetGUID(); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 0 + case 1: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + if (Unit* pUther = me->SummonCreature(NPC_UTHER,1794.357f,1272.183f,140.558f,1.37f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiUtherGUID = pUther->GetGUID(); + pUther->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pUther->GetMotionMaster()->MovePoint(0, 1897.018f, 1287.487f, 143.481f); + pUther->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiUtherGUID); + } + JumpToNextStep(17000); + break; + case 2: + DoScriptText(SAY_PHASE101, me); + JumpToNextStep(2000); + break; + case 3: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + { + DoScriptText(SAY_PHASE102, pUther); + } + JumpToNextStep(8000); + break; + case 4: + SetEscortPaused(false); + bStepping = false; + SetRun(false); + DoScriptText(SAY_PHASE103, me); + JumpToNextStep(0); + break; + //After waypoint 1 + case 5: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + pJaina->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + DoScriptText(SAY_PHASE104, me); + JumpToNextStep(10000); + break; + case 6: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE105, pUther); + JumpToNextStep(1000); + break; + case 7: + DoScriptText(SAY_PHASE106, me); + JumpToNextStep(4000); + break; + case 8: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE107, pUther); + JumpToNextStep(6000); + break; + case 9: + DoScriptText(SAY_PHASE108, me); + JumpToNextStep(4000); + break; + case 10: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE109, pUther); + JumpToNextStep(8000); + break; + case 11: + DoScriptText(SAY_PHASE110, me); + JumpToNextStep(4000); + break; + case 12: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE111, pUther); + JumpToNextStep(4000); + break; + case 13: + DoScriptText(SAY_PHASE112, me); + JumpToNextStep(11000); + break; + case 14: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + DoScriptText(SAY_PHASE113, pJaina); + JumpToNextStep(3000); + break; + case 15: + DoScriptText(SAY_PHASE114, me); + JumpToNextStep(9000); + break; + case 16: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE115, pUther); + JumpToNextStep(4000); + break; + case 17: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + { + pUther->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pUther->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); + } + JumpToNextStep(1000); + break; + case 18: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + { + me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); + pJaina->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pJaina->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); + } + JumpToNextStep(1000); + break; + case 19: + DoScriptText(SAY_PHASE116, me); + JumpToNextStep(1000); + break; + case 20: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + DoScriptText(SAY_PHASE117, pJaina); + JumpToNextStep(3000); + break; + case 21: + SetEscortPaused(false); + bStepping = false; + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After waypoint 3 + case 22: + DoScriptText(SAY_PHASE118, me); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); + JumpToNextStep(10000); + break; + case 23: + SetEscortPaused(false); + bStepping = false; + SetRun(true); + + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + pJaina->DisappearAndDie(); + + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + pUther->DisappearAndDie(); + + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After Gossip 1 (waypoint 8) + case 24: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2026.469f,1287.088f,143.596f,1.37f,TEMPSUMMON_TIMED_DESPAWN,14000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + JumpToNextStep(1000); + break; + case 25: + DoScriptText(SAY_PHASE201, me); + JumpToNextStep(12000); + break; + case 26: + SetEscortPaused(false); + bStepping = false; + SetRun(false); + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After waypoint 9 + case 27: + me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[0]); + if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) + { + pCityman->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + pCityman->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCityman->GetMotionMaster()->MovePoint(0, 2088.625f,1279.191f,140.743f); + } + JumpToNextStep(2000); + break; + case 28: + if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) + DoScriptText(SAY_PHASE202, pCityman); + JumpToNextStep(4000); + break; + case 29: + SetEscortPaused(false); + bStepping = false; + DoScriptText(SAY_PHASE203, me); + JumpToNextStep(0); + break; + //After waypoint 10 + case 30: + me->HandleEmoteCommand(37); + JumpToNextStep(1000); + break; + case 31: + SetEscortPaused(false); + bStepping = false; + if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) + { + DoScriptText(SAY_PHASE204, pCityman1); + pCityman1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pCityman0 = Unit::GetCreature(*me, uiCitymenGUID[0])) + pCityman0->Kill(pCityman0); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[1]); + } + JumpToNextStep(0); + break; + //After waypoint 11 + case 32: + me->HandleEmoteCommand(37); + JumpToNextStep(1000); + break; + case 33: + if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) + pCityman1->Kill(pCityman1); + JumpToNextStep(1000); + break; + case 34: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + DoScriptText(SAY_PHASE205, me); + JumpToNextStep(3000); + break; + case 35: + if (Unit* pStalkerM = me->SummonCreature(NPC_INVIS_TARGET,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + uiStalkerGUID = pStalkerM->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + JumpToNextStep(1000); + break; + case 36: + if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + if (Creature* pStalkerM = Unit::GetCreature(*me, uiStalkerGUID)) + pMalganis->CastSpell(pStalkerM,63793,false); + + uiMalganisGUID = pMalganis->GetGUID(); + DoScriptText(SAY_PHASE206, pMalganis); + pMalganis->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + pMalganis->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(11000); + break; + case 37: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + { + if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN, 100.0f)) + pZombie->UpdateEntry(NPC_ZOMBIE, 0); + else if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN2, 100.0f)) + pZombie->UpdateEntry(NPC_ZOMBIE, 0); + else //There's no one else to transform + uiStep++; + } + else + uiStep++; + uiPhaseTimer = 500; + break; + case 38: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + DoScriptText(SAY_PHASE207, pMalganis); + JumpToNextStep(17000); + break; + case 39: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + pMalganis->SetVisibility(VISIBILITY_OFF); + DoScriptText(SAY_PHASE208, me); + JumpToNextStep(7000); + break; + case 40: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + DoScriptText(SAY_PHASE209, me); + + uiBossEvent = DATA_MEATHOOK_EVENT; + if (pInstance) + pInstance->SetData(DATA_ARTHAS_EVENT, IN_PROGRESS); + + me->SetReactState(REACT_DEFENSIVE); + SetDespawnAtFar(false); + JumpToNextStep(5000); + break; + case 41: //Summon wave group + case 43: + case 45: + case 47: + case 51: + case 53: + case 55: + case 57: + if (pInstance->GetData(uiBossEvent) != DONE) + { + SpawnWaveGroup(uiWave, uiWaveGUID); + uiWave++; + } + JumpToNextStep(500); + break; + case 42: //Wait group to die + case 44: + case 46: + case 48: + case 52: + case 54: + case 56: + case 58: + if (pInstance->GetData(uiBossEvent) != DONE) + { + uint32 mobCounter = 0; + uint32 deadCounter = 0; + for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + { + if (uiWaveGUID[i] == 0) + break; + ++mobCounter; + Unit* pTemp = Unit::GetCreature(*me, uiWaveGUID[i]); + if (!pTemp || pTemp->isDead()) + ++deadCounter; + } + + if (mobCounter <= deadCounter) //If group is dead + JumpToNextStep(1000); + else + uiPhaseTimer = 1000; + } + else + JumpToNextStep(500); + break; + case 49: //Summon Boss + case 59: + if (pInstance->GetData(uiBossEvent) != DONE) + { + uint32 uiBossID = 0; + if (uiBossEvent == DATA_MEATHOOK_EVENT) + uiBossID = NPC_MEATHOOK; + else if (uiBossEvent == DATA_SALRAMM_EVENT) + uiBossID = NPC_SALRAMM; + + if (Unit* pBoss = me->SummonCreature(uiBossID,2232.19f,1331.933f,126.662f,3.15f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + uiBossGUID = pBoss->GetGUID(); + pBoss->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pBoss->GetMotionMaster()->MovePoint(0, 2194.110f,1332.00f,130.00f); + } + } + JumpToNextStep(30000); + break; + case 50: //Wait Boss death + case 60: + if (pInstance) + { + if (pInstance->GetData(uiBossEvent) == DONE) + { + JumpToNextStep(1000); + if (uiBossEvent == DATA_MEATHOOK_EVENT) + uiBossEvent = DATA_SALRAMM_EVENT; + else if (uiBossEvent == DATA_SALRAMM_EVENT) + { + SetHoldState(false); + bStepping = false; + uiBossEvent = DATA_EPOCH_EVENT; + } + } + else if (pInstance->GetData(uiBossEvent) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After Gossip 2 (waypoint 22) + case 61: + me->SetReactState(REACT_AGGRESSIVE); + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) + pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) + pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + JumpToNextStep(1000); + break; + case 62: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + DoScriptText(SAY_PHASE302, pDisguised0); + JumpToNextStep(7000); + break; + case 63: + DoScriptText(SAY_PHASE303, me); + SetHoldState(false); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 23 + case 64: + me->HandleEmoteCommand(54); + JumpToNextStep(1000); + break; + case 65: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + pDisguised0->HandleEmoteCommand(11); + JumpToNextStep(1000); + break; + case 66: + DoScriptText(SAY_PHASE304,me); + JumpToNextStep(2000); + break; + case 67: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + DoScriptText(SAY_PHASE305,pDisguised0); + JumpToNextStep(1000); + break; + case 68: + if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) + { + pDisguised2->UpdateEntry(NPC_INFINITE_HUNTER, 0); + //Make them unattackable + pDisguised2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised2->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 69: + if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) + { + pDisguised1->UpdateEntry(NPC_INFINITE_AGENT, 0); + //Make them unattackable + pDisguised1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised1->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 70: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + { + pDisguised0->UpdateEntry(NPC_INFINITE_ADVERSARY, 0); + //Make them unattackable + pDisguised0->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised0->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 71: + //After waypoint 26,29,31 + case 73: + case 75: + case 77: + //Make cratures attackable + for (uint32 i = 0; i< ENCOUNTER_DRACONIAN_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiInfiniteDraconianGUID[i])) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pTemp->SetReactState(REACT_AGGRESSIVE); + } + JumpToNextStep(5000); + break; + case 72: + case 74: + case 76: + if (me->isInCombat()) + uiPhaseTimer = 1000; + else + { + if (uiStep == 72) DoScriptText(SAY_PHASE308,me); + if (uiStep == 74) DoScriptText(SAY_PHASE308,me); + if (uiStep == 76) DoScriptText(SAY_PHASE310,me); + SetHoldState(false); + bStepping = false; + SetRun(true); + JumpToNextStep(2000); + } + break; + case 78: + if (me->isInCombat()) + uiPhaseTimer = 1000; + else + { + DoScriptText(SAY_PHASE312,me); + JumpToNextStep(5000); + } + break; + case 79: + DoScriptText(SAY_PHASE313,me); + JumpToNextStep(1000); + break; + case 80: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + { + SpawnTimeRift(17,&uiEpochGUID); + if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) + DoScriptText(SAY_PHASE314,pEpoch); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiEpochGUID); + } + JumpToNextStep(18000); + break; + case 81: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + DoScriptText(SAY_PHASE315, me); + JumpToNextStep(6000); + break; + case 82: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + { + if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) + { + //Make Epoch attackable + pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pEpoch->SetReactState(REACT_AGGRESSIVE); + } + + } + JumpToNextStep(1000); + break; + case 83: + if (pInstance) + { + if (pInstance->GetData(DATA_EPOCH_EVENT) == DONE) + { + uiGossipStep = 3; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + bStepping = false; + uiBossEvent = DATA_MAL_GANIS_EVENT; + JumpToNextStep(15000); + } + else if (pInstance->GetData(DATA_EPOCH_EVENT) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After Gossip 4 + case 84: + DoScriptText(SAY_PHASE404,me); + SetHoldState(false); + bStepping = false; + break; + //After Gossip 5 + case 85: + DoScriptText(SAY_PHASE501, me); + if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2296.665f,1502.362f,128.362f,4.961f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + uiMalganisGUID = pMalganis->GetGUID(); + pMalganis->SetReactState(REACT_PASSIVE); + } + if (pInstance) + { + GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAL_GANIS_GATE_1)); + pGate->SetGoState(GO_STATE_ACTIVE); + } + SetHoldState(false); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 55 + case 86: + DoScriptText(SAY_PHASE502, me); + JumpToNextStep(6000); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); + break; + case 87: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + { + pMalganis->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_6 | UNIT_FLAG_UNK_9 | UNIT_FLAG_UNK_15); + pMalganis->SetReactState(REACT_AGGRESSIVE); + } + JumpToNextStep(1000); + break; + case 88: + if (pInstance) + { + if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == DONE) + { + SetHoldState(false); + JumpToNextStep(1000); + } + else if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After waypoint 56 + case 89: + SetRun(true); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); + DoScriptText(SAY_PHASE503, me); + JumpToNextStep(7000); + break; + case 90: + if (pInstance) + { + pInstance->SetData(DATA_ARTHAS_EVENT, DONE); //Rewards: Achiev & Chest ;D + me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance->GetData64(DATA_MAL_GANIS_GATE_2)); //Look behind + } + DoScriptText(SAY_PHASE504, me); + bStepping = false; + break; + } + } else uiPhaseTimer -= diff; + } + + //Battling skills + if (!me->getVictim()) + return; + + if (uiExorcismTimer < diff) + { + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(target, SPELL_EXORCISM_N); + uiExorcismTimer = 7300; + } else uiExorcismTimer -= diff; + + if (HealthBelowPct(40)) + DoCast(me, SPELL_HOLY_LIGHT); + } +}; + +CreatureAI* GetAI_npc_arthas(Creature* pCreature) +{ + return new npc_arthasAI(pCreature); +} + +#define GOSSIP_ITEM_ARTHAS_0 "I'm ready to start Culling of Stratholme." +#define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready." +#define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness." +#define GOSSIP_ITEM_ARTHAS_3 "I'm ready." +#define GOSSIP_ITEM_ARTHAS_4 "For Lordaeron!" +#define GOSSIP_ITEM_ARTHAS_5 "I'm ready to battle the dreadlord, sire." + +bool GossipHello_npc_arthas(Player* pPlayer, Creature* pCreature) +{ + npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); + + if (pAI && pAI->bStepping == false) + { + switch (pAI->uiGossipStep) + { + case 0: //This one is a workaround since the very beggining of the script is wrong. + if (pPlayer->GetQuestStatus(13149) != QUEST_STATUS_COMPLETE) + return false; + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + break; + case 1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_1, pCreature->GetGUID()); + break; + case 2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_2, pCreature->GetGUID()); + break; + case 3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_3, pCreature->GetGUID()); + break; + case 4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_4, pCreature->GetGUID()); + break; + case 5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_5, pCreature->GetGUID()); + break; + default: + return false; + } + } + return true; +} + + +bool GossipSelect_npc_arthas(Player *pPlayer, Creature *pCreature, uint32 /*sender*/, uint32 action) +{ + npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); + + if (!pAI) + return false; + + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + pAI->Start(true,true,pPlayer->GetGUID(),0,false,false); + pAI->SetDespawnAtEnd(false); + pAI->bStepping = false; + pAI->uiStep = 1; + break; + case GOSSIP_ACTION_INFO_DEF+1: + pAI->bStepping = true; + pAI->uiStep = 24; + break; + case GOSSIP_ACTION_INFO_DEF+2: + pAI->SetHoldState(false); + pAI->bStepping = false; + pAI->uiStep = 61; + break; + case GOSSIP_ACTION_INFO_DEF+3: + pAI->SetHoldState(false); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pAI->bStepping = true; + pAI->uiStep = 84; + break; + case GOSSIP_ACTION_INFO_DEF+5: + pAI->bStepping = true; + pAI->uiStep = 85; + break; + } + pPlayer->CLOSE_GOSSIP_MENU(); + pAI->SetDespawnAtFar(true); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + return true; +} + +void AddSC_culling_of_stratholme() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_arthas"; + newscript->GetAI = &GetAI_npc_arthas; + newscript->pGossipHello = &GossipHello_npc_arthas; + newscript->pGossipSelect = &GossipSelect_npc_arthas; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h new file mode 100644 index 00000000000..4278ad46500 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h @@ -0,0 +1,68 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DEF_CULLING_OF_STRATHOLME_H +#define DEF_CULLING_OF_STRATHOLME_H + +enum Data +{ + DATA_MEATHOOK_EVENT, + DATA_SALRAMM_EVENT, + DATA_EPOCH_EVENT, + DATA_MAL_GANIS_EVENT, + DATA_INFINITE_EVENT, + DATA_ARTHAS_EVENT +}; + +enum Data64 +{ + DATA_ARTHAS, + DATA_MEATHOOK, + DATA_SALRAMM, + DATA_EPOCH, + DATA_MAL_GANIS, + DATA_INFINITE, + DATA_SHKAF_GATE, + DATA_MAL_GANIS_GATE_1, + DATA_MAL_GANIS_GATE_2, + DATA_EXIT_GATE, + DATA_MAL_GANIS_CHEST +}; + +enum Creatures +{ + NPC_MEATHOOK = 26529, + NPC_SALRAMM = 26530, + NPC_EPOCH = 26532, + NPC_MAL_GANIS = 26533, + NPC_INFINITE = 32273, + NPC_ARTHAS = 26499, + NPC_JAINA = 26497, + NPC_UTHER = 26528 +}; + +enum GameObjects +{ + GO_SHKAF_GATE = 188686, + GO_MALGANIS_GATE_1 = 187711, + GO_MALGANIS_GATE_2 = 187723, + GO_EXIT_GATE = 191788, + GO_MALGANIS_CHEST_N = 190663, + GO_MALGANIS_CHEST_H = 193597 +}; +#endif diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp new file mode 100644 index 00000000000..73742a1e748 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp @@ -0,0 +1,244 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +#define MAX_ENCOUNTER 5 + +/* Culling of Stratholme encounters: +0 - Meathook +1 - Salramm the Fleshcrafter +2 - Chrono-Lord Epoch +3 - Mal'Ganis +4 - Infinite Corruptor (Heroic only) +*/ + +struct instance_culling_of_stratholme : public ScriptedInstance +{ + instance_culling_of_stratholme(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiArthas; + uint64 uiMeathook; + uint64 uiSalramm; + uint64 uiEpoch; + uint64 uiMalGanis; + uint64 uiInfinite; + + uint64 uiShkafGate; + uint64 uiMalGanisGate1; + uint64 uiMalGanisGate2; + uint64 uiExitGate; + uint64 uiMalGanisChest; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_ARTHAS: + uiArthas = pCreature->GetGUID(); + break; + case NPC_MEATHOOK: + uiMeathook = pCreature->GetGUID(); + break; + case NPC_SALRAMM: + uiSalramm = pCreature->GetGUID(); + break; + case NPC_EPOCH: + uiEpoch = pCreature->GetGUID(); + break; + case NPC_MAL_GANIS: + uiMalGanis = pCreature->GetGUID(); + break; + case NPC_INFINITE: + uiInfinite = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_SHKAF_GATE: + uiShkafGate = pGo->GetGUID(); + break; + case GO_MALGANIS_GATE_1: + uiMalGanisGate1 = pGo->GetGUID(); + break; + case GO_MALGANIS_GATE_2: + uiMalGanisGate2 = pGo->GetGUID(); + break; + case GO_EXIT_GATE: + uiExitGate = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(uiExitGate,true); + break; + case GO_MALGANIS_CHEST_N: + case GO_MALGANIS_CHEST_H: + uiMalGanisChest = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MEATHOOK_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_SALRAMM_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_EPOCH_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_MAL_GANIS_EVENT: + m_auiEncounter[3] = data; + + switch(m_auiEncounter[3]) + { + case NOT_STARTED: + HandleGameObject(uiMalGanisGate2,true); + break; + case IN_PROGRESS: + HandleGameObject(uiMalGanisGate2,false); + break; + case DONE: + HandleGameObject(uiExitGate, true); + if (GameObject *pGo = instance->GetGameObject(uiMalGanisChest)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + } + break; + case DATA_INFINITE_EVENT: + m_auiEncounter[4] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_MEATHOOK_EVENT: return m_auiEncounter[0]; + case DATA_SALRAMM_EVENT: return m_auiEncounter[1]; + case DATA_EPOCH_EVENT: return m_auiEncounter[2]; + case DATA_MAL_GANIS_EVENT: return m_auiEncounter[3]; + case DATA_INFINITE_EVENT: return m_auiEncounter[4]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_ARTHAS: return uiArthas; + case DATA_MEATHOOK: return uiMeathook; + case DATA_SALRAMM: return uiSalramm; + case DATA_EPOCH: return uiEpoch; + case DATA_MAL_GANIS: return uiMalGanis; + case DATA_INFINITE: return uiInfinite; + case DATA_SHKAF_GATE: return uiShkafGate; + case DATA_MAL_GANIS_GATE_1: return uiMalGanisGate1; + case DATA_MAL_GANIS_GATE_2: return uiMalGanisGate2; + case DATA_EXIT_GATE: return uiExitGate; + case DATA_MAL_GANIS_CHEST: return uiMalGanisChest; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "C S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; + + if (dataHead1 == 'C' && dataHead2 == 'S') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap) +{ + return new instance_culling_of_stratholme(pMap); +} + +void AddSC_instance_culling_of_stratholme() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_culling_of_stratholme"; + newscript->GetInstanceData = &GetInstanceData_instance_culling_of_stratholme; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp new file mode 100644 index 00000000000..49cf7cd4433 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp @@ -0,0 +1,145 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Aeonus +SD%Complete: 80 +SDComment: Some spells not implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269012, + SAY_AGGRO = -1269013, + SAY_BANISH = -1269014, + SAY_SLAY1 = -1269015, + SAY_SLAY2 = -1269016, + SAY_DEATH = -1269017, + EMOTE_FRENZY = -1269018, + + SPELL_CLEAVE = 40504, + SPELL_TIME_STOP = 31422, + SPELL_ENRAGE = 37605, + SPELL_SAND_BREATH = 31473, + H_SPELL_SAND_BREATH = 39049 +}; + +struct boss_aeonusAI : public ScriptedAI +{ + boss_aeonusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SandBreath_Timer; + uint32 TimeStop_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + SandBreath_Timer = 15000+rand()%15000; + TimeStop_Timer = 10000+rand()%5000; + Frenzy_Timer = 30000+rand()%15000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_RIFT,DONE); + pInstance->SetData(TYPE_MEDIVH,DONE);//FIXME: later should be removed + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sand Breath + if (SandBreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SAND_BREATH); + SandBreath_Timer = 15000+rand()%10000; + } else SandBreath_Timer -= diff; + + //Time Stop + if (TimeStop_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIME_STOP); + TimeStop_Timer = 20000+rand()%15000; + } else TimeStop_Timer -= diff; + + //Frenzy + if (Frenzy_Timer <= diff) + { + DoScriptText(EMOTE_FRENZY, me); + DoCast(me, SPELL_ENRAGE); + Frenzy_Timer = 20000+rand()%15000; + } else Frenzy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_aeonus(Creature* pCreature) +{ + return new boss_aeonusAI (pCreature); +} + +void AddSC_boss_aeonus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_aeonus"; + newscript->GetAI = &GetAI_boss_aeonus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp new file mode 100644 index 00000000000..1f2b4a80612 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp @@ -0,0 +1,154 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Chrono_Lord_Deja +SD%Complete: 65 +SDComment: All abilities not implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269006, + SAY_AGGRO = -1269007, + SAY_BANISH = -1269008, + SAY_SLAY1 = -1269009, + SAY_SLAY2 = -1269010, + SAY_DEATH = -1269011, + + SPELL_ARCANE_BLAST = 31457, + H_SPELL_ARCANE_BLAST = 38538, + SPELL_ARCANE_DISCHARGE = 31472, + H_SPELL_ARCANE_DISCHARGE = 38539, + SPELL_TIME_LAPSE = 31467, + SPELL_ATTRACTION = 38540 //Not Implemented (Heroic mode) +}; + +struct boss_chrono_lord_dejaAI : public ScriptedAI +{ + boss_chrono_lord_dejaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 ArcaneBlast_Timer; + uint32 TimeLapse_Timer; + uint32 Attraction_Timer; + uint32 ArcaneDischarge_Timer; + + void Reset() + { + ArcaneBlast_Timer = 18000+rand()%5000; + TimeLapse_Timer = 10000+rand()%5000; + ArcaneDischarge_Timer = 20000+rand()%10000; + Attraction_Timer = 25000+rand()%10000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Arcane Blast + if (ArcaneBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BLAST); + ArcaneBlast_Timer = 15000+rand()%10000; + } else ArcaneBlast_Timer -= diff; + + //Arcane Discharge + if (ArcaneDischarge_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(pTarget, SPELL_ARCANE_DISCHARGE); + ArcaneDischarge_Timer = 20000+rand()%10000; + } else ArcaneDischarge_Timer -= diff; + + //Time Lapse + if (TimeLapse_Timer <= diff) + { + DoScriptText(SAY_BANISH, me); + DoCast(me, SPELL_TIME_LAPSE); + TimeLapse_Timer = 15000+rand()%10000; + } else TimeLapse_Timer -= diff; + + if (IsHeroic()) + { + if (Attraction_Timer <= diff) + { + DoCast(me, SPELL_ATTRACTION); + Attraction_Timer = 25000+rand()%10000; + } else Attraction_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_chrono_lord_deja(Creature* pCreature) +{ + return new boss_chrono_lord_dejaAI (pCreature); +} + +void AddSC_boss_chrono_lord_deja() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_chrono_lord_deja"; + newscript->GetAI = &GetAI_boss_chrono_lord_deja; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp new file mode 100644 index 00000000000..04b4b020ead --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Temporus +SD%Complete: 75 +SDComment: More abilities need to be implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269000, + SAY_AGGRO = -1269001, + SAY_BANISH = -1269002, + SAY_SLAY1 = -1269003, + SAY_SLAY2 = -1269004, + SAY_DEATH = -1269005, + + SPELL_HASTE = 31458, + SPELL_MORTAL_WOUND = 31464, + SPELL_WING_BUFFET = 31475, + H_SPELL_WING_BUFFET = 38593, + SPELL_REFLECT = 38592 //Not Implemented (Heroic mod) +}; + +struct boss_temporusAI : public ScriptedAI +{ + boss_temporusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Haste_Timer; + uint32 SpellReflection_Timer; + uint32 MortalWound_Timer; + uint32 WingBuffet_Timer; + + void Reset() + { + Haste_Timer = 15000+rand()%8000; + SpellReflection_Timer = 30000; + MortalWound_Timer = 8000; + WingBuffet_Timer = 25000+rand()%10000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Attack Haste + if (Haste_Timer <= diff) + { + DoCast(me, SPELL_HASTE); + Haste_Timer = 20000+rand()%5000; + } else Haste_Timer -= diff; + + //MortalWound_Timer + if (MortalWound_Timer <= diff) + { + DoCast(me, SPELL_MORTAL_WOUND); + MortalWound_Timer = 10000+rand()%10000; + } else MortalWound_Timer -= diff; + + //Wing ruffet + if (WingBuffet_Timer <= diff) + { + DoCast(me, SPELL_WING_BUFFET); + WingBuffet_Timer = 20000+rand()%10000; + } else WingBuffet_Timer -= diff; + + if (IsHeroic()) + { + if (SpellReflection_Timer <= diff) + { + DoCast(me, SPELL_REFLECT); + SpellReflection_Timer = 25000+rand()%10000; + } else SpellReflection_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_temporus(Creature* pCreature) +{ + return new boss_temporusAI (pCreature); +} + +void AddSC_boss_temporus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_temporus"; + newscript->GetAI = &GetAI_boss_temporus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp new file mode 100644 index 00000000000..b0432a9b57c --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp @@ -0,0 +1,404 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Dark_Portal +SD%Complete: 30 +SDComment: Misc NPC's and mobs for instance. Most here far from complete. +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +/* ContentData +npc_medivh_bm +npc_time_rift +npc_saat +EndContentData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +#define SAY_ENTER -1269020 //where does this belong? +#define SAY_INTRO -1269021 +#define SAY_WEAK75 -1269022 +#define SAY_WEAK50 -1269023 +#define SAY_WEAK25 -1269024 +#define SAY_DEATH -1269025 +#define SAY_WIN -1269026 +#define SAY_ORCS_ENTER -1269027 +#define SAY_ORCS_ANSWER -1269028 + +#define SPELL_CHANNEL 31556 +#define SPELL_PORTAL_RUNE 32570 //aura(portal on ground effect) + +#define SPELL_BLACK_CRYSTAL 32563 //aura +#define SPELL_PORTAL_CRYSTAL 32564 //summon + +#define SPELL_BANISH_PURPLE 32566 //aura +#define SPELL_BANISH_GREEN 32567 //aura + +#define SPELL_CORRUPT 31326 +#define SPELL_CORRUPT_AEONUS 37853 + +#define C_COUNCIL_ENFORCER 17023 + +struct npc_medivh_bmAI : public ScriptedAI +{ + npc_medivh_bmAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SpellCorrupt_Timer; + uint32 Check_Timer; + + bool Life75; + bool Life50; + bool Life25; + + void Reset() + { + SpellCorrupt_Timer = 0; + + if (!pInstance) + return; + + if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) + DoCast(me, SPELL_CHANNEL, true); + else if (me->HasAura(SPELL_CHANNEL)) + me->RemoveAura(SPELL_CHANNEL); + + DoCast(me, SPELL_PORTAL_RUNE, true); + } + + void MoveInLineOfSight(Unit *who) + { + if (!pInstance) + return; + + if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 10.0f)) + { + if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS || pInstance->GetData(TYPE_MEDIVH) == DONE) + return; + + DoScriptText(SAY_INTRO, me); + pInstance->SetData(TYPE_MEDIVH,IN_PROGRESS); + DoCast(me, SPELL_CHANNEL, false); + Check_Timer = 5000; + } + else if (who->GetTypeId() == TYPEID_UNIT && me->IsWithinDistInMap(who, 15.0f)) + { + if (pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) + return; + + uint32 entry = who->GetEntry(); + if (entry == C_ASSAS || entry == C_WHELP || entry == C_CHRON || entry == C_EXECU || entry == C_VANQU) + { + who->StopMoving(); + who->CastSpell(me,SPELL_CORRUPT,false); + } + else if (entry == C_AEONUS) + { + who->StopMoving(); + who->CastSpell(me,SPELL_CORRUPT_AEONUS,false); + } + } + } + + void AttackStart(Unit * /*who*/) + { + //if (pInstance && pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) + //return; + + //ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) {} + + void SpellHit(Unit* /*caster*/, const SpellEntry* spell) + { + if (SpellCorrupt_Timer) + return; + + if (spell->Id == SPELL_CORRUPT_AEONUS) + SpellCorrupt_Timer = 1000; + + if (spell->Id == SPELL_CORRUPT) + SpellCorrupt_Timer = 3000; + } + + void JustDied(Unit* Killer) + { + if (Killer->GetEntry() == me->GetEntry()) + return; + + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (SpellCorrupt_Timer) + { + if (SpellCorrupt_Timer <= diff) + { + pInstance->SetData(TYPE_MEDIVH,SPECIAL); + + if (me->HasAura(SPELL_CORRUPT_AEONUS)) + SpellCorrupt_Timer = 1000; + else if (me->HasAura(SPELL_CORRUPT)) + SpellCorrupt_Timer = 3000; + else + SpellCorrupt_Timer = 0; + } else SpellCorrupt_Timer -= diff; + } + + if (Check_Timer) + { + if (Check_Timer <= diff) + { + uint32 pct = pInstance->GetData(DATA_SHIELD); + + Check_Timer = 5000; + + if (Life25 && pct <= 25) + { + DoScriptText(SAY_WEAK25, me); + Life25 = false; + } + else if (Life50 && pct <= 50) + { + DoScriptText(SAY_WEAK50, me); + Life50 = false; + } + else if (Life75 && pct <= 75) + { + DoScriptText(SAY_WEAK75, me); + Life75 = false; + } + + //if we reach this it means event was running but at some point reset. + if (pInstance->GetData(TYPE_MEDIVH) == NOT_STARTED) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + me->Respawn(); + return; + } + + if (pInstance->GetData(TYPE_RIFT) == DONE) + { + DoScriptText(SAY_WIN, me); + Check_Timer = 0; + + if (me->HasAura(SPELL_CHANNEL)) + me->RemoveAura(SPELL_CHANNEL); + + //TODO: start the post-event here + pInstance->SetData(TYPE_MEDIVH,DONE); + } + } else Check_Timer -= diff; + } + + //if (!UpdateVictim()) + //return; + + //DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_medivh_bm(Creature* pCreature) +{ + return new npc_medivh_bmAI (pCreature); +} + +struct Wave +{ + uint32 PortalMob[4]; //spawns for portal waves (in order) +}; + +static Wave PortalWaves[]= +{ + {C_ASSAS, C_WHELP, C_CHRON, 0}, + {C_EXECU, C_CHRON, C_WHELP, C_ASSAS}, + {C_EXECU, C_VANQU, C_CHRON, C_ASSAS} +}; + +struct npc_time_riftAI : public ScriptedAI +{ + npc_time_riftAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 TimeRiftWave_Timer; + uint8 mRiftWaveCount; + uint8 mPortalCount; + uint8 mWaveId; + + void Reset() + { + + TimeRiftWave_Timer = 15000; + mRiftWaveCount = 0; + + if (!pInstance) + return; + + mPortalCount = pInstance->GetData(DATA_PORTAL_COUNT); + + if (mPortalCount < 6) + mWaveId = 0; + else if (mPortalCount > 12) + mWaveId = 2; + else mWaveId = 1; + + } + void EnterCombat(Unit * /*who*/) {} + + void DoSummonAtRift(uint32 creature_entry) + { + if (!creature_entry) + return; + + if (pInstance && pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) + { + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + return; + } + + Position pos; + me->GetRandomNearPosition(pos, 10.0f); + + //normalize Z-level if we can, if rift is not at ground level. + pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + + if (Unit *Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) + if (Unit *temp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_MEDIVH) : 0)) + Summon->AddThreat(temp,0.0f); + } + + void DoSelectSummon() + { + uint32 entry = 0; + + if ((mRiftWaveCount > 2 && mWaveId < 1) || mRiftWaveCount > 3) + mRiftWaveCount = 0; + + entry = PortalWaves[mWaveId].PortalMob[mRiftWaveCount]; + debug_log("TSCR: npc_time_rift: summoning wave Creature (Wave %u, Entry %u).",mRiftWaveCount,entry); + + ++mRiftWaveCount; + + if (entry == C_WHELP) + { + for (uint8 i = 0; i < 3; ++i) + DoSummonAtRift(entry); + } else DoSummonAtRift(entry); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (TimeRiftWave_Timer <= diff) + { + DoSelectSummon(); + TimeRiftWave_Timer = 15000; + } else TimeRiftWave_Timer -= diff; + + if (me->IsNonMeleeSpellCasted(false)) + return; + + debug_log("TSCR: npc_time_rift: not casting anylonger, i need to die."); + me->setDeathState(JUST_DIED); + + if (pInstance->GetData(TYPE_RIFT) == IN_PROGRESS) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } +}; + +CreatureAI* GetAI_npc_time_rift(Creature* pCreature) +{ + return new npc_time_riftAI (pCreature); +} + +#define SAY_SAAT_WELCOME -1269019 + +#define GOSSIP_ITEM_OBTAIN "[PH] Obtain Chrono-Beacon" +#define SPELL_CHRONO_BEACON 34975 +#define ITEM_CHRONO_BEACON 24289 + +bool GossipHello_npc_saat(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(10000, pCreature->GetGUID()); + return true; + } + else if (pPlayer->GetQuestRewardStatus(QUEST_OPENING_PORTAL) && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(10001, pCreature->GetGUID()); + return true; + } + + pPlayer->SEND_GOSSIP_MENU(10002, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_saat(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer,SPELL_CHRONO_BEACON,false); + } + return true; +} + +void AddSC_dark_portal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_medivh_bm"; + newscript->GetAI = &GetAI_npc_medivh_bm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_time_rift"; + newscript->GetAI = &GetAI_npc_time_rift; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_saat"; + newscript->pGossipHello = &GossipHello_npc_saat; + newscript->pGossipSelect = &GossipSelect_npc_saat; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h new file mode 100644 index 00000000000..7bfd8c917d7 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_DARKPORTAL_H +#define DEF_DARKPORTAL_H + +#define TYPE_MEDIVH 1 +#define TYPE_RIFT 2 + +#define DATA_MEDIVH 10 +#define DATA_PORTAL_COUNT 11 +#define DATA_SHIELD 12 + +#define WORLD_STATE_BM 2541 +#define WORLD_STATE_BM_SHIELD 2540 +#define WORLD_STATE_BM_RIFT 2784 + +#define QUEST_OPENING_PORTAL 10297 +#define QUEST_MASTER_TOUCH 9836 + +#define C_TIME_KEEPER 17918 +#define C_RKEEP 21104 +#define C_RLORD 17839 +#define C_DEJA 17879 +#define C_TEMPO 17880 +#define C_AEONUS 17881 +#define C_ASSAS 17835 +#define C_WHELP 21818 +#define C_CHRON 17892 +#define C_EXECU 18994 +#define C_VANQU 18995 + +#endif + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp new file mode 100644 index 00000000000..d1280230808 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp @@ -0,0 +1,346 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Dark_Portal +SD%Complete: 50 +SDComment: Quest support: 9836, 10297. Currently in progress. +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +#define MAX_ENCOUNTER 2 + +#define C_MEDIVH 15608 +#define C_TIME_RIFT 17838 + +#define SPELL_RIFT_CHANNEL 31387 + +#define RIFT_BOSS 1 + +inline uint32 RandRiftBoss() { return ((rand()%2) ? C_RKEEP : C_RLORD); } + +float PortalLocation[4][4]= +{ + {-2041.06, 7042.08, 29.99, 1.30}, + {-1968.18, 7042.11, 21.93, 2.12}, + {-1885.82, 7107.36, 22.32, 3.07}, + {-1928.11, 7175.95, 22.11, 3.44} +}; + +struct Wave +{ + uint32 PortalBoss; //protector of current portal + uint32 NextPortalTime; //time to next portal, or 0 if portal boss need to be killed +}; + +static Wave RiftWaves[]= +{ + {RIFT_BOSS, 0}, + {C_DEJA, 0}, + {RIFT_BOSS, 120000}, + {C_TEMPO, 140000}, + {RIFT_BOSS, 120000}, + {C_AEONUS, 0} +}; + +struct instance_dark_portal : public ScriptedInstance +{ + instance_dark_portal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint32 mRiftPortalCount; + uint32 mShieldPercent; + uint8 mRiftWaveCount; + uint8 mRiftWaveId; + + uint32 NextPortal_Timer; + + uint64 MedivhGUID; + uint8 CurrentRiftId; + + void Initialize() + { + MedivhGUID = 0; + Clear(); + } + + void Clear() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + mRiftPortalCount = 0; + mShieldPercent = 100; + mRiftWaveCount = 0; + mRiftWaveId = 0; + + CurrentRiftId = 0; + + NextPortal_Timer = 0; + } + + void InitWorldState(bool Enable = true) + { + DoUpdateWorldState(WORLD_STATE_BM,Enable ? 1 : 0); + DoUpdateWorldState(WORLD_STATE_BM_SHIELD, 100); + DoUpdateWorldState(WORLD_STATE_BM_RIFT, 0); + } + + bool IsEncounterInProgress() + { + if (GetData(TYPE_MEDIVH) == IN_PROGRESS) + return true; + + return false; + } + + void OnPlayerEnter(Player* pPlayer) + { + if (GetData(TYPE_MEDIVH) == IN_PROGRESS) + return; + + pPlayer->SendUpdateWorldState(WORLD_STATE_BM,0); + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == C_MEDIVH) + MedivhGUID = pCreature->GetGUID(); + } + + //what other conditions to check? + bool CanProgressEvent() + { + if (instance->GetPlayers().isEmpty()) + return false; + + return true; + } + + uint8 GetRiftWaveId() + { + switch(mRiftPortalCount) + { + case 6: + mRiftWaveId = 2; + return 1; + case 12: + mRiftWaveId = 4; + return 3; + case 18: + return 5; + default: + return mRiftWaveId; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_MEDIVH: + if (data == SPECIAL && m_auiEncounter[0] == IN_PROGRESS) + { + --mShieldPercent; + + DoUpdateWorldState(WORLD_STATE_BM_SHIELD, mShieldPercent); + + if (!mShieldPercent) + { + if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) + { + if (pMedivh->isAlive()) + { + pMedivh->DealDamage(pMedivh, pMedivh->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_auiEncounter[0] = FAIL; + m_auiEncounter[1] = NOT_STARTED; + } + } + } + } + else + { + if (data == IN_PROGRESS) + { + debug_log("TSCR: Instance Dark Portal: Starting event."); + InitWorldState(); + m_auiEncounter[1] = IN_PROGRESS; + NextPortal_Timer = 15000; + } + + if (data == DONE) + { + //this may be completed further out in the post-event + debug_log("TSCR: Instance Dark Portal: Event completed."); + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL); + + if (pPlayer->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH); + } + } + } + } + + m_auiEncounter[0] = data; + } + break; + case TYPE_RIFT: + if (data == SPECIAL) + { + if (mRiftPortalCount < 7) + NextPortal_Timer = 5000; + } + else + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_MEDIVH: + return m_auiEncounter[0]; + case TYPE_RIFT: + return m_auiEncounter[1]; + case DATA_PORTAL_COUNT: + return mRiftPortalCount; + case DATA_SHIELD: + return mShieldPercent; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + if (data == DATA_MEDIVH) + return MedivhGUID; + + return 0; + } + + Creature* SummonedPortalBoss(Creature* me) + { + uint32 entry = RiftWaves[GetRiftWaveId()].PortalBoss; + + if (entry == RIFT_BOSS) + entry = RandRiftBoss(); + + debug_log("TSCR: Instance Dark Portal: Summoning rift boss entry %u.",entry); + + Position pos; + me->GetRandomNearPosition(pos, 10.0f); + + //normalize Z-level if we can, if rift is not at ground level. + pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + + if (Creature *summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) + return summon; + + debug_log("TSCR: Instance Dark Portal: What just happened there? No boss, no loot, no fun..."); + return NULL; + } + + void DoSpawnPortal() + { + if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) + { + uint8 tmp = urand(0,2); + + if (tmp >= CurrentRiftId) + ++tmp; + + debug_log("TSCR: Instance Dark Portal: Creating Time Rift at locationId %i (old locationId was %u).",tmp,CurrentRiftId); + + CurrentRiftId = tmp; + + Creature *pTemp = pMedivh->SummonCreature(C_TIME_RIFT, + PortalLocation[tmp][0],PortalLocation[tmp][1],PortalLocation[tmp][2],PortalLocation[tmp][3], + TEMPSUMMON_CORPSE_DESPAWN,0); + if (pTemp) + { + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (Creature *pBoss = SummonedPortalBoss(pTemp)) + { + if (pBoss->GetEntry() == C_AEONUS) + pBoss->AddThreat(pMedivh,0.0f); + else + { + pBoss->AddThreat(pTemp,0.0f); + pTemp->CastSpell(pBoss,SPELL_RIFT_CHANNEL,false); + } + } + } + } + } + + void Update(uint32 diff) + { + if (m_auiEncounter[1] != IN_PROGRESS) + return; + + //add delay timer? + if (!CanProgressEvent()) + { + Clear(); + return; + } + + if (NextPortal_Timer) + { + if (NextPortal_Timer <= diff) + { + ++mRiftPortalCount; + + DoUpdateWorldState(WORLD_STATE_BM_RIFT, mRiftPortalCount); + + DoSpawnPortal(); + NextPortal_Timer = RiftWaves[GetRiftWaveId()].NextPortalTime; + } else NextPortal_Timer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_dark_portal(Map* pMap) +{ + return new instance_dark_portal(pMap); +} + +void AddSC_instance_dark_portal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_dark_portal"; + newscript->GetInstanceData = &GetInstanceData_instance_dark_portal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp new file mode 100644 index 00000000000..14ce4a59b37 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp @@ -0,0 +1,309 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_CARRION_SWARM 31306 +#define SPELL_SLEEP 31298 +#define SPELL_VAMPIRIC_AURA 38196 +#define SPELL_INFERNO 31299 + +#define SAY_ONDEATH "The clock... is still... ticking." +#define SOUND_ONDEATH 10982 + +#define SAY_ONSLAY1 "Your hopes are lost!" +#define SAY_ONSLAY2 "Scream for me!" +#define SAY_ONSLAY3 "Pity, no time for a slow death!" +#define SOUND_ONSLAY1 10981 +#define SOUND_ONSLAY2 11038 +#define SOUND_ONSLAY3 11039 + +#define SAY_SWARM1 "The swarm is eager to feed!" +#define SAY_SWARM2 "Pestilence upon you!" +#define SOUND_SWARM1 10979 +#define SOUND_SWARM2 11037 + +#define SAY_SLEEP1 "You look tired..." +#define SAY_SLEEP2 "Sweet dreams..." +#define SOUND_SLEEP1 10978 +#define SOUND_SLEEP2 11545 + +#define SAY_INFERNO1 "Let fire rain from above!" +#define SAY_INFERNO2 "Earth and sky shall burn!" +#define SOUND_INFERNO1 10980 +#define SOUND_INFERNO2 11036 + +#define SAY_ONAGGRO "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!" +#define SOUND_ONAGGRO 10977 + +struct boss_anetheronAI : public hyjal_trashAI +{ + boss_anetheronAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_SLEEP); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) + { + TempSpell->EffectImplicitTargetA[0] = 1; + TempSpell->EffectImplicitTargetB[0] = 0; + } + } + + uint32 SwarmTimer; + uint32 SleepTimer; + uint32 AuraTimer; + uint32 InfernoTimer; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + SwarmTimer = 45000; + SleepTimer = 60000; + AuraTimer = 5000; + InfernoTimer = 45000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, 0); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 4896.08, -1576.35, 1333.65); + AddWaypoint(1, 4898.68, -1615.02, 1329.48); + AddWaypoint(2, 4907.12, -1667.08, 1321.00); + AddWaypoint(3, 4963.18, -1699.35, 1340.51); + AddWaypoint(4, 4989.16, -1716.67, 1335.74); + AddWaypoint(5, 5026.27, -1736.89, 1323.02); + AddWaypoint(6, 5037.77, -1770.56, 1324.36); + AddWaypoint(7, 5067.23, -1789.95, 1321.17); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (SwarmTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CARRION_SWARM); + + SwarmTimer = urand(45000,60000); + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_SWARM1); + me->MonsterYell(SAY_SWARM1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_SWARM2); + me->MonsterYell(SAY_SWARM2, LANG_UNIVERSAL, 0); + break; + } + } else SwarmTimer -= diff; + + if (SleepTimer <= diff) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + pTarget->CastSpell(pTarget,SPELL_SLEEP,true); + } + SleepTimer = 60000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_SLEEP1); + me->MonsterYell(SAY_SLEEP1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_SLEEP2); + me->MonsterYell(SAY_SLEEP2, LANG_UNIVERSAL, 0); + break; + } + } else SleepTimer -= diff; + if (AuraTimer <= diff) + { + DoCast(me, SPELL_VAMPIRIC_AURA, true); + AuraTimer = urand(10000,20000); + } else AuraTimer -= diff; + if (InfernoTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_INFERNO); + InfernoTimer = 45000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_INFERNO1); + me->MonsterYell(SAY_INFERNO1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_INFERNO2); + me->MonsterYell(SAY_INFERNO2, LANG_UNIVERSAL, 0); + break; + } + } else InfernoTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_anetheron(Creature* pCreature) +{ + return new boss_anetheronAI (pCreature); +} + +#define SPELL_IMMOLATION 31303 +#define SPELL_INFERNO_EFFECT 31302 + +struct mob_towering_infernalAI : public ScriptedAI +{ + mob_towering_infernalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + AnetheronGUID = pInstance->GetData64(DATA_ANETHERON); + } + + uint32 ImmolationTimer; + uint32 CheckTimer; + uint64 AnetheronGUID; + ScriptedInstance* pInstance; + + void Reset() + { + DoCast(me, SPELL_INFERNO_EFFECT); + ImmolationTimer = 5000; + CheckTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + } + + void JustDied(Unit * /*victim*/) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) + AttackStart(who); + } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (AnetheronGUID) + { + Creature* boss = Unit::GetCreature((*me),AnetheronGUID); + if (!boss || (boss && boss->isDead())) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + return; + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (ImmolationTimer <= diff) + { + DoCast(me, SPELL_IMMOLATION); + ImmolationTimer = 5000; + } else ImmolationTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_towering_infernal(Creature* pCreature) +{ + return new mob_towering_infernalAI (pCreature); +} + +void AddSC_boss_anetheron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_anetheron"; + newscript->GetAI = &GetAI_boss_anetheron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_towering_infernal"; + newscript->GetAI = &GetAI_mob_towering_infernal; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp new file mode 100644 index 00000000000..8e1fa378e07 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp @@ -0,0 +1,635 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Archimonde +SD%Complete: 85 +SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented. +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "SpellAuras.h" +#include "hyjal_trash.h" + +//text id -1534018 are the text used when previous events complete. Not part of this script. +#define SAY_AGGRO -1534019 +#define SAY_DOOMFIRE1 -1534020 +#define SAY_DOOMFIRE2 -1534021 +#define SAY_AIR_BURST1 -1534022 +#define SAY_AIR_BURST2 -1534023 +#define SAY_SLAY1 -1534024 +#define SAY_SLAY2 -1534025 +#define SAY_SLAY3 -1534026 +#define SAY_ENRAGE -1534027 +#define SAY_DEATH -1534028 +#define SAY_SOUL_CHARGE1 -1534029 +#define SAY_SOUL_CHARGE2 -1534030 + +#define SPELL_DENOUEMENT_WISP 32124 +#define SPELL_ANCIENT_SPARK 39349 +#define SPELL_PROTECTION_OF_ELUNE 38528 + +#define SPELL_DRAIN_WORLD_TREE 39140 +#define SPELL_DRAIN_WORLD_TREE_2 39141 + +#define SPELL_FINGER_OF_DEATH 31984 +#define SPELL_HAND_OF_DEATH 35354 +#define SPELL_AIR_BURST 32014 +#define SPELL_GRIP_OF_THE_LEGION 31972 +#define SPELL_DOOMFIRE_STRIKE 31903 //summons two creatures +#define SPELL_DOOMFIRE_SPAWN 32074 +#define SPELL_DOOMFIRE 31945 +#define SPELL_SOUL_CHARGE_YELLOW 32045 +#define SPELL_SOUL_CHARGE_GREEN 32051 +#define SPELL_SOUL_CHARGE_RED 32052 +#define SPELL_UNLEASH_SOUL_YELLOW 32054 +#define SPELL_UNLEASH_SOUL_GREEN 32057 +#define SPELL_UNLEASH_SOUL_RED 32053 +#define SPELL_FEAR 31970 + +#define CREATURE_ARCHIMONDE 17968 +#define CREATURE_DOOMFIRE 18095 +#define CREATURE_DOOMFIRE_SPIRIT 18104 +#define CREATURE_ANCIENT_WISP 17946 +#define CREATURE_CHANNEL_TARGET 22418 + +#define NORDRASSIL_X 5503.713 +#define NORDRASSIL_Y -3523.436 +#define NORDRASSIL_Z 1608.781 + +struct mob_ancient_wispAI : public ScriptedAI +{ + mob_ancient_wispAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + ArchimondeGUID = 0; + } + + ScriptedInstance* pInstance; + uint64 ArchimondeGUID; + uint32 CheckTimer; + + void Reset() + { + CheckTimer = 1000; + + if (pInstance) + ArchimondeGUID = pInstance->GetData64(DATA_ARCHIMONDE); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void EnterCombat(Unit* /*who*/) {} + + void DamageTaken(Unit* /*done_by*/, uint32 &damage) { damage = 0; } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (Unit* Archimonde = Unit::GetUnit((*me), ArchimondeGUID)) + { + if ((((Archimonde->GetHealth()*100) / Archimonde->GetMaxHealth()) < 2) || !Archimonde->isAlive()) + DoCast(me, SPELL_DENOUEMENT_WISP); + else + DoCast(Archimonde, SPELL_ANCIENT_SPARK); + } + CheckTimer = 1000; + } else CheckTimer -= diff; + } +}; + +/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will + MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */ +struct mob_doomfireAI : public ScriptedAI +{ + mob_doomfireAI(Creature* c) : ScriptedAI(c) {} + + void Reset() { } + + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit* /*who*/) {} + void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } +}; + +/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or + travels in random directions if pTarget cannot be found. */ +struct mob_doomfire_targettingAI : public ScriptedAI +{ + mob_doomfire_targettingAI(Creature* c) : ScriptedAI(c) {} + + uint64 TargetGUID; + uint32 ChangeTargetTimer; + + void Reset() + { + TargetGUID = 0; + ChangeTargetTimer = 5000; + } + + void MoveInLineOfSight(Unit* who) + { + //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0 + //when UpdateAI needs it, it will be forced to select randomPoint + if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER) + TargetGUID = who->GetGUID(); + } + + void EnterCombat(Unit* /*who*/) {} + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } + + void UpdateAI(const uint32 diff) + { + if (ChangeTargetTimer <= diff) + { + if (Unit *temp = Unit::GetUnit(*me,TargetGUID)) + { + me->GetMotionMaster()->MoveFollow(temp,0.0f,0.0f); + TargetGUID = 0; + } + else + { + Position pos; + me->GetRandomNearPosition(pos, 40); + me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ); + } + + ChangeTargetTimer = 5000; + } else ChangeTargetTimer -= diff; + } +}; + +/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers. + The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the + hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then + select a random pTarget and cast the spell on them. However, if someone IS in melee range, and this + is NOT the main tank (creature's victim), then we aggro that player and they become the new victim. + For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will + randomly select it's pTarget to follow and then we create the random movement making it unpredictable. */ + +struct boss_archimondeAI : public hyjal_trashAI +{ + boss_archimondeAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 DoomfireSpiritGUID; + uint64 WorldTreeGUID; + + uint32 DrainNordrassilTimer; + uint32 FearTimer; + uint32 AirBurstTimer; + uint32 GripOfTheLegionTimer; + uint32 DoomfireTimer; + uint32 SoulChargeTimer; + uint32 SoulChargeCount; + uint32 MeleeRangeCheckTimer; + uint32 HandOfDeathTimer; + uint32 SummonWispTimer; + uint32 WispCount; + uint32 EnrageTimer; + uint32 CheckDistanceTimer; + + bool Enraged; + bool BelowTenPercent; + bool HasProtected; + bool IsChanneling; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); + + DoomfireSpiritGUID = 0; + damageTaken = 0; + WorldTreeGUID = 0; + + DrainNordrassilTimer = 0; + FearTimer = 42000; + AirBurstTimer = 30000; + GripOfTheLegionTimer = urand(5000,25000); + DoomfireTimer = 20000; + SoulChargeTimer = urand(2000,30000); + SoulChargeCount = 0; + MeleeRangeCheckTimer = 15000; + HandOfDeathTimer = 2000; + WispCount = 0; // When ~30 wisps are summoned, Archimonde dies + EnrageTimer = 600000; // 10 minutes + CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage + SummonWispTimer = 0; + + Enraged = false; + BelowTenPercent = false; + HasProtected = false; + IsChanneling = false; + } + + void EnterCombat(Unit * /*who*/) + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * victim) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + + if (victim && (victim->GetTypeId() == TYPEID_PLAYER)) + GainSoulCharge(CAST_PLR(victim)); + } + + void GainSoulCharge(Player* victim) + { + switch(victim->getClass()) + { + case CLASS_PRIEST: + case CLASS_PALADIN: + case CLASS_WARLOCK: + victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); + break; + case CLASS_MAGE: + case CLASS_ROGUE: + case CLASS_WARRIOR: + victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); + break; + case CLASS_DRUID: + case CLASS_SHAMAN: + case CLASS_HUNTER: + victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); + break; + } + + SoulChargeTimer = urand(2000,30000); + ++SoulChargeCount; + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, DONE); + } + + bool CanUseFingerOfDeath() + { + // First we check if our current victim is in melee range or not. + Unit* victim = me->getVictim(); + if (victim && me->IsWithinDistInMap(victim, me->GetAttackDistance(victim))) + return false; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + if (m_threatlist.empty()) + return false; + + std::list targets; + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + targets.push_back(pUnit); + } + + if (targets.empty()) + return false; + + targets.sort(Trinity::ObjectDistanceOrderPred(me)); + Unit *pTarget = targets.front(); + if (pTarget) + { + if (!me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) + return true; // Cast Finger of Death + else // This target is closest, he is our new tank + me->AddThreat(pTarget, me->getThreatManager().getThreat(me->getVictim())); + } + + return false; + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == CREATURE_ANCIENT_WISP) + summoned->AI()->AttackStart(me); + else + { + summoned->setFaction(me->getFaction()); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) + { + DoomfireSpiritGUID = summoned->GetGUID(); + } + + if (summoned->GetEntry() == CREATURE_DOOMFIRE) + { + summoned->CastSpell(summoned,SPELL_DOOMFIRE_SPAWN,false); + summoned->CastSpell(summoned,SPELL_DOOMFIRE,true,0,0,me->GetGUID()); + + if (Unit *DoomfireSpirit = Unit::GetUnit(*me, DoomfireSpiritGUID)) + { + summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit,0.0f,0.0f); + DoomfireSpiritGUID = 0; + } + } + } + + //this is code doing close to what the summoning spell would do (spell 31903) + void SummonDoomfire(Unit *pTarget) + { + me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, + pTarget->GetPositionX()+15.0,pTarget->GetPositionY()+15.0,pTarget->GetPositionZ(),0, + TEMPSUMMON_TIMED_DESPAWN, 27000); + + me->SummonCreature(CREATURE_DOOMFIRE, + pTarget->GetPositionX()-15.0,pTarget->GetPositionY()-15.0,pTarget->GetPositionZ(),0, + TEMPSUMMON_TIMED_DESPAWN, 27000); + } + + void UnleashSoulCharge() + { + me->InterruptNonMeleeSpells(false); + + bool HasCast = false; + uint32 chargeSpell = 0; + uint32 unleashSpell = 0; + + switch (urand(0,2)) + { + case 0: + chargeSpell = SPELL_SOUL_CHARGE_RED; + unleashSpell = SPELL_UNLEASH_SOUL_RED; + break; + case 1: + chargeSpell = SPELL_SOUL_CHARGE_YELLOW; + unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; + break; + case 2: + chargeSpell = SPELL_SOUL_CHARGE_GREEN; + unleashSpell = SPELL_UNLEASH_SOUL_GREEN; + break; + } + + if (me->HasAura(chargeSpell)) + { + me->RemoveAuraFromStack(chargeSpell); + DoCast(me->getVictim(), unleashSpell); + HasCast = true; + SoulChargeCount--; + } + + if (HasCast) + SoulChargeTimer = urand(2000,30000); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + { + if (pInstance) + { + // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. + if ((pInstance->GetData(DATA_AZGALOREVENT) < DONE) && ((me->GetVisibility() != VISIBILITY_OFF) || (me->getFaction() != 35))) + { + me->SetVisibility(VISIBILITY_OFF); + me->setFaction(35); + } + else if ((pInstance->GetData(DATA_AZGALOREVENT) >= DONE) && ((me->GetVisibility() != VISIBILITY_ON) || (me->getFaction() == 35))) + { + me->setFaction(1720); + me->SetVisibility(VISIBILITY_ON); + } + } + + if (DrainNordrassilTimer <= diff) + { + if (!IsChanneling) + { + Creature *temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 1200000); + + if (temp) + WorldTreeGUID = temp->GetGUID(); + + if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) + { + Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Nordrassil->SetDisplayId(11686); + DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); + IsChanneling = true; + } + } + + if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) + { + Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); + DrainNordrassilTimer = 1000; + } + } else DrainNordrassilTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !BelowTenPercent && !Enraged) + BelowTenPercent = true; + + if (!Enraged) + { + if (EnrageTimer <= diff) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) > 10) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + Enraged = true; + DoScriptText(SAY_ENRAGE, me); + } + } else EnrageTimer -= diff; + + if (CheckDistanceTimer <= diff) + { + // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature + Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000); + if (Check) + { + Check->SetVisibility(VISIBILITY_OFF); + + if (me->IsWithinDistInMap(Check, 75)) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + Enraged = true; + DoScriptText(SAY_ENRAGE, me); + } + } + CheckDistanceTimer = 5000; + } else CheckDistanceTimer -= diff; + } + + if (BelowTenPercent) + { + if (!HasProtected) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + + //all members of raid must get this buff + DoCast(me->getVictim(), SPELL_PROTECTION_OF_ELUNE); + HasProtected = true; + Enraged = true; + } + + if (SummonWispTimer <= diff) + { + DoSpawnCreature(CREATURE_ANCIENT_WISP, rand()%40, rand()%40, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SummonWispTimer = 1500; + ++WispCount; + } else SummonWispTimer -= diff; + + if (WispCount >= 30) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (Enraged) + { + if (HandOfDeathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HAND_OF_DEATH); + HandOfDeathTimer = 2000; + } else HandOfDeathTimer -= diff; + return; // Don't do anything after this point. + } + + if (SoulChargeCount) + { + if (SoulChargeTimer <= diff) + UnleashSoulCharge(); + else SoulChargeTimer -= diff; + } + + if (GripOfTheLegionTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); + GripOfTheLegionTimer = urand(5000,25000); + } else GripOfTheLegionTimer -= diff; + + if (AirBurstTimer <= diff) + { + if (urand(0,1)) + DoScriptText(SAY_AIR_BURST1, me); + else + DoScriptText(SAY_AIR_BURST2, me); + + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank + AirBurstTimer = urand(25000,40000); + } else AirBurstTimer -= diff; + + if (FearTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + FearTimer = 42000; + } else FearTimer -= diff; + + if (DoomfireTimer <= diff) + { + if (urand(0,1)) + DoScriptText(SAY_DOOMFIRE1, me); + else + DoScriptText(SAY_DOOMFIRE2, me); + + Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!temp) + temp = me->getVictim(); + + //replace with spell cast 31903 once implicitTarget 73 implemented + SummonDoomfire(temp); + + //supposedly three doomfire can be up at the same time + DoomfireTimer = 20000; + } else DoomfireTimer -= diff; + + if (MeleeRangeCheckTimer <= diff) + { + if (CanUseFingerOfDeath()) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); + MeleeRangeCheckTimer = 1000; + } + + MeleeRangeCheckTimer = 5000; + } else MeleeRangeCheckTimer -= diff; + + DoMeleeAttackIfReady(); + } + void WaypointReached(uint32 /*i*/){} +}; + +CreatureAI* GetAI_boss_archimonde(Creature* pCreature) +{ + return new boss_archimondeAI (pCreature); +} + +CreatureAI* GetAI_mob_doomfire(Creature* pCreature) +{ + return new mob_doomfireAI(pCreature); +} + +CreatureAI* GetAI_mob_doomfire_targetting(Creature* pCreature) +{ + return new mob_doomfire_targettingAI(pCreature); +} + +CreatureAI* GetAI_mob_ancient_wisp(Creature* pCreature) +{ + return new mob_ancient_wispAI(pCreature); +} + +void AddSC_boss_archimonde() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_archimonde"; + newscript->GetAI = &GetAI_boss_archimonde; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_doomfire"; + newscript->GetAI = &GetAI_mob_doomfire; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_doomfire_targetting"; + newscript->GetAI = &GetAI_mob_doomfire_targetting; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ancient_wisp"; + newscript->GetAI = &GetAI_mob_ancient_wisp; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp new file mode 100644 index 00000000000..69e37f7f740 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp @@ -0,0 +1,285 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_RAIN_OF_FIRE 31340 +#define SPELL_DOOM 31347 +#define SPELL_HOWL_OF_AZGALOR 31344 +#define SPELL_CLEAVE 31345 +#define SPELL_BERSERK 26662 + +#define SAY_ONDEATH "Your time is almost... up" +#define SOUND_ONDEATH 11002 + +#define SAY_ONSLAY1 "Reesh, hokta!" +#define SAY_ONSLAY2 "Don't fight it" +#define SAY_ONSLAY3 "No one is going to save you" +#define SOUND_ONSLAY1 11001 +#define SOUND_ONSLAY2 11048 +#define SOUND_ONSLAY3 11047 + +#define SAY_DOOM1 "Just a taste... of what awaits you" +#define SAY_DOOM2 "Suffer you despicable insect!" +#define SOUND_DOOM1 11046 +#define SOUND_DOOM2 11000 + +#define SAY_ONAGGRO "Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!" +#define SOUND_ONAGGRO 10999 + +struct boss_azgalorAI : public hyjal_trashAI +{ + boss_azgalorAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_HOWL_OF_AZGALOR); + if (TempSpell) + TempSpell->EffectRadiusIndex[0] = 12;//100yards instead of 50000?! + } + + uint32 RainTimer; + uint32 DoomTimer; + uint32 HowlTimer; + uint32 CleaveTimer; + uint32 EnrageTimer; + bool enraged; + + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + RainTimer = 20000; + DoomTimer = 50000; + HowlTimer = 30000; + CleaveTimer = 10000; + EnrageTimer = 600000; + enraged = false; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 5492.91, -2404.61, 1462.63); + AddWaypoint(1, 5531.76, -2460.87, 1469.55); + AddWaypoint(2, 5554.58, -2514.66, 1476.12); + AddWaypoint(3, 5554.16, -2567.23, 1479.90); + AddWaypoint(4, 5540.67, -2625.99, 1480.89); + AddWaypoint(5, 5508.16, -2659.2, 1480.15); + AddWaypoint(6, 5489.62, -2704.05, 1482.18); + AddWaypoint(7, 5457.04, -2726.26, 1485.10); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (RainTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,30,true), SPELL_RAIN_OF_FIRE); + RainTimer = 20000+rand()%15000; + } else RainTimer -= diff; + + if (DoomTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,100,true), SPELL_DOOM);//never on tank + DoomTimer = 45000+rand()%5000; + } else DoomTimer -= diff; + + if (HowlTimer <= diff) + { + DoCast(me, SPELL_HOWL_OF_AZGALOR); + HowlTimer = 30000; + } else HowlTimer -= diff; + + if (CleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + CleaveTimer = 10000+rand()%5000; + } else CleaveTimer -= diff; + + if (EnrageTimer < diff && !enraged) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_BERSERK, true); + enraged = true; + EnrageTimer = 600000; + } else EnrageTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_azgalor(Creature* pCreature) +{ + return new boss_azgalorAI (pCreature); +} + +#define SPELL_THRASH 12787 +#define SPELL_CRIPPLE 31406 +#define SPELL_WARSTOMP 31408 + +struct mob_lesser_doomguardAI : public hyjal_trashAI +{ + mob_lesser_doomguardAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + AzgalorGUID = pInstance->GetData64(DATA_AZGALOR); + } + + uint32 CrippleTimer; + uint32 WarstompTimer; + uint32 CheckTimer; + uint64 AzgalorGUID; + ScriptedInstance* pInstance; + + void Reset() + { + CrippleTimer = 50000; + WarstompTimer = 10000; + DoCast(me, SPELL_THRASH); + CheckTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + } + + void WaypointReached(uint32 /*i*/) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) + AttackStart(who); + } + + void JustDied(Unit * /*victim*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (AzgalorGUID) + { + Creature* boss = Unit::GetCreature((*me),AzgalorGUID); + if (!boss || (boss && boss->isDead())) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + return; + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (WarstompTimer <= diff) + { + DoCast(me, SPELL_WARSTOMP); + WarstompTimer = 10000+rand()%5000; + } else WarstompTimer -= diff; + + if (CrippleTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_CRIPPLE); + CrippleTimer = 25000+rand()%5000; + } else CrippleTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_lesser_doomguard(Creature* pCreature) +{ + return new mob_lesser_doomguardAI (pCreature); +} + +void AddSC_boss_azgalor() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_azgalor"; + newscript->GetAI = &GetAI_boss_azgalor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lesser_doomguard"; + newscript->GetAI = &GetAI_mob_lesser_doomguard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp new file mode 100644 index 00000000000..b52d22842e3 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp @@ -0,0 +1,197 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_CLEAVE 31436 +#define SPELL_WARSTOMP 31480 +#define SPELL_MARK 31447 + +#define SOUND_ONDEATH 11018 + +#define SAY_ONSLAY1 "Shaza-Kiel!" +#define SAY_ONSLAY2 "You... are nothing!" +#define SAY_ONSLAY3 "Miserable nuisance!" +#define SOUND_ONSLAY1 11017 +#define SOUND_ONSLAY2 11053 +#define SOUND_ONSLAY3 11054 + +#define SAY_MARK1 "Your death will be a painful one." +#define SAY_MARK2 "You... are marked." +#define SOUND_MARK1 11016 +#define SOUND_MARK2 11052 + +#define SAY_ONAGGRO "Cry for mercy! Your meaningless lives will soon be forfeit." +#define SOUND_ONAGGRO 11015 + +struct boss_kazrogalAI : public hyjal_trashAI +{ + boss_kazrogalAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_MARK); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) + { + TempSpell->EffectImplicitTargetA[0] = 1; + TempSpell->EffectImplicitTargetB[0] = 0; + } + } + + uint32 CleaveTimer; + uint32 WarStompTimer; + uint32 MarkTimer; + uint32 MarkTimerBase; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + CleaveTimer = 5000; + WarStompTimer = 15000; + MarkTimer = 45000; + MarkTimerBase = 45000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 5492.91, -2404.61, 1462.63); + AddWaypoint(1, 5531.76, -2460.87, 1469.55); + AddWaypoint(2, 5554.58, -2514.66, 1476.12); + AddWaypoint(3, 5554.16, -2567.23, 1479.90); + AddWaypoint(4, 5540.67, -2625.99, 1480.89); + AddWaypoint(5, 5508.16, -2659.2, 1480.15); + AddWaypoint(6, 5489.62, -2704.05, 1482.18); + AddWaypoint(7, 5457.04, -2726.26, 1485.10); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (CleaveTimer <= diff) + { + DoCast(me, SPELL_CLEAVE); + CleaveTimer = 6000+rand()%15000; + } else CleaveTimer -= diff; + + if (WarStompTimer <= diff) + { + DoCast(me, SPELL_WARSTOMP); + WarStompTimer = 60000; + } else WarStompTimer -= diff; + + if (me->HasAura(SPELL_MARK)) + me->RemoveAurasDueToSpell(SPELL_MARK); + if (MarkTimer <= diff) + { + //cast dummy, useful for bos addons + me->CastCustomSpell(me, SPELL_MARK, NULL, NULL, NULL, false, NULL, NULL, me->GetGUID()); + + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->getPowerType() == POWER_MANA) + { + pTarget->CastSpell(pTarget, SPELL_MARK,true);//only cast on mana users + } + } + MarkTimerBase -= 5000; + if (MarkTimerBase < 5500) + MarkTimerBase = 5500; + MarkTimer = MarkTimerBase; + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_MARK1); + me->MonsterYell(SAY_MARK1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_MARK2); + me->MonsterYell(SAY_MARK2, LANG_UNIVERSAL, NULL); + break; + } + } else MarkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kazrogal(Creature* pCreature) +{ + return new boss_kazrogalAI (pCreature); +} + +void AddSC_boss_kazrogal() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kazrogal"; + newscript->GetAI = &GetAI_boss_kazrogal; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp new file mode 100644 index 00000000000..7465b997117 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp @@ -0,0 +1,192 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_FROST_ARMOR 31256 +#define SPELL_DEATH_AND_DECAY 31258 + +#define SPELL_FROST_NOVA 31250 +#define SPELL_ICEBOLT 31249 + +#define SAY_ONDEATH "You have won this battle, but not... the... war" +#define SOUND_ONDEATH 11026 + +#define SAY_ONSLAY1 "All life must perish!" +#define SAY_ONSLAY2 "Victory to the Legion!" +#define SOUND_ONSLAY1 11025 +#define SOUND_ONSLAY2 11057 + +#define SAY_DECAY1 "Crumble and rot!" +#define SAY_DECAY2 "Ashes to ashes, dust to dust" +#define SOUND_DECAY1 11023 +#define SOUND_DECAY2 11055 + +#define SAY_NOVA1 "Succumb to the icy chill... of death!" +#define SAY_NOVA2 "It will be much colder in your grave" +#define SOUND_NOVA1 11024 +#define SOUND_NOVA2 11058 + +#define SAY_ONAGGRO "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!" +#define SOUND_ONAGGRO 11022 + +struct boss_rage_winterchillAI : public hyjal_trashAI +{ + boss_rage_winterchillAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + } + + uint32 FrostArmorTimer; + uint32 DecayTimer; + uint32 NovaTimer; + uint32 IceboltTimer; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + FrostArmorTimer = 37000; + DecayTimer = 45000; + NovaTimer = 15000; + IceboltTimer = 10000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0f); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, NULL); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 4896.08, -1576.35, 1333.65); + AddWaypoint(1, 4898.68, -1615.02, 1329.48); + AddWaypoint(2, 4907.12, -1667.08, 1321.00); + AddWaypoint(3, 4963.18, -1699.35, 1340.51); + AddWaypoint(4, 4989.16, -1716.67, 1335.74); + AddWaypoint(5, 5026.27, -1736.89, 1323.02); + AddWaypoint(6, 5037.77, -1770.56, 1324.36); + AddWaypoint(7, 5067.23, -1789.95, 1321.17); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (FrostArmorTimer <= diff) + { + DoCast(me, SPELL_FROST_ARMOR); + FrostArmorTimer = 40000+rand()%20000; + } else FrostArmorTimer -= diff; + if (DecayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_DEATH_AND_DECAY); + DecayTimer = 60000+rand()%20000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_DECAY1); + me->MonsterYell(SAY_DECAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_DECAY2); + me->MonsterYell(SAY_DECAY2, LANG_UNIVERSAL, NULL); + break; + } + } else DecayTimer -= diff; + if (NovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_NOVA); + NovaTimer = 30000+rand()%15000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_NOVA1); + me->MonsterYell(SAY_NOVA1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_NOVA2); + me->MonsterYell(SAY_NOVA2, LANG_UNIVERSAL, NULL); + break; + } + } else NovaTimer -= diff; + if (IceboltTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,40,true), SPELL_ICEBOLT); + IceboltTimer = 11000+rand()%20000; + } else IceboltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_rage_winterchill(Creature* pCreature) +{ + return new boss_rage_winterchillAI (pCreature); +} + +void AddSC_boss_rage_winterchill() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_rage_winterchill"; + newscript->GetAI = &GetAI_boss_rage_winterchill; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp new file mode 100644 index 00000000000..16a050939cc --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp @@ -0,0 +1,247 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Hyjal +SD%Complete: 80 +SDComment: gossip text id's unknown +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +/* ContentData +npc_jaina_proudmoore +npc_thrall +npc_tyrande_whisperwind +EndContentData */ + +#include "ScriptedPch.h" +#include "hyjalAI.h" + +#define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore." +#define GOSSIP_ITEM_ANETHERON "We are ready for whatever Archimonde might send our way, Lady Proudmoore." + +#define GOSSIP_ITEM_BEGIN_HORDE "I am with you, Thrall." +#define GOSSIP_ITEM_AZGALOR "We have nothing to fear." + +#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!" + +#define GOSSIP_ITEM_TYRANDE "Aid us in defending Nordrassil" +#define ITEM_TEAR_OF_GODDESS 24494 + +#define GOSSIP_ITEM_GM1 "[GM] Toggle Debug Timers" + +CreatureAI* GetAI_npc_jaina_proudmoore(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + + ai->Reset(); + ai->EnterEvadeMode(); + + ai->Spell[0].SpellId = SPELL_BLIZZARD; + ai->Spell[0].Cooldown = 15000 + rand()%20000; + ai->Spell[0].TargetType = TARGETTYPE_RANDOM; + + ai->Spell[1].SpellId = SPELL_PYROBLAST; + ai->Spell[1].Cooldown = 5500 + rand()%4000; + ai->Spell[1].TargetType = TARGETTYPE_RANDOM; + + ai->Spell[2].SpellId = SPELL_SUMMON_ELEMENTALS; + ai->Spell[2].Cooldown = 15000 + rand()%30000; + ai->Spell[2].TargetType = TARGETTYPE_SELF; + + return ai; +} + +bool GossipHello_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + if (ai->EventBegun) + return false; + + uint32 RageEncounter = ai->GetInstanceData(DATA_RAGEWINTERCHILLEVENT); + uint32 AnetheronEncounter = ai->GetInstanceData(DATA_ANETHERONEVENT); + if (RageEncounter == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + else if (RageEncounter == DONE && AnetheronEncounter == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + else if (RageEncounter == DONE && AnetheronEncounter == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + if (pPlayer->isGameMaster()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + ai->FirstBossDead = true; + ai->WaveCount = 9; + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + ai->Retreat(); + break; + case GOSSIP_ACTION_INFO_DEF: + ai->Debug = !ai->Debug; + debug_log("TSCR: HyjalAI - Debug mode has been toggled"); + break; + } + return true; +} + +CreatureAI* GetAI_npc_thrall(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + + ai->Reset(); + ai->EnterEvadeMode(); + + ai->Spell[0].SpellId = SPELL_CHAIN_LIGHTNING; + ai->Spell[0].Cooldown = 3000 + rand()%5000; + ai->Spell[0].TargetType = TARGETTYPE_VICTIM; + + ai->Spell[1].SpellId = SPELL_SUMMON_DIRE_WOLF; + ai->Spell[1].Cooldown = 6000 + rand()%35000; + ai->Spell[1].TargetType = TARGETTYPE_RANDOM; + + return ai; +} + +bool GossipHello_npc_thrall(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + if (ai->EventBegun) + return false; + + uint32 AnetheronEvent = ai->GetInstanceData(DATA_ANETHERONEVENT); + // Only let them start the Horde phases if Anetheron is dead. + if (AnetheronEvent == DONE && ai->GetInstanceData(DATA_ALLIANCE_RETREAT)) + { + uint32 KazrogalEvent = ai->GetInstanceData(DATA_KAZROGALEVENT); + uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); + if (KazrogalEvent == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + else if (KazrogalEvent == DONE && AzgalorEvent == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + else if (AzgalorEvent == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + } + + if (pPlayer->isGameMaster()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_thrall(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + ai->DeSpawnVeins();//despawn the alliance veins + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + ai->FirstBossDead = true; + ai->WaveCount = 9; + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + ai->Retreat(); + break; + case GOSSIP_ACTION_INFO_DEF: + ai->Debug = !ai->Debug; + debug_log("TSCR: HyjalAI - Debug mode has been toggled"); + break; + } + return true; +} + +CreatureAI* GetAI_npc_tyrande_whisperwind(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + ai->Reset(); + ai->EnterEvadeMode(); + return ai; +} + +bool GossipHello_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); + + // Only let them get item if Azgalor is dead. + if (AzgalorEvent == DONE && !pPlayer->HasItemCount(ITEM_TEAR_OF_GODDESS,1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TYRANDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_TEAR_OF_GODDESS, 1); + if (msg == EQUIP_ERR_OK) + { + Item* item = pPlayer->StoreNewItem(dest, ITEM_TEAR_OF_GODDESS, true); + if (item && pPlayer) + pPlayer->SendNewItem(item,1,true,false,true); + } + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + CAST_AI(hyjalAI, pCreature->AI()); + } + return true; +} + +void AddSC_hyjal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_jaina_proudmoore"; + newscript->GetAI = &GetAI_npc_jaina_proudmoore; + newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore; + newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thrall"; + newscript->GetAI = &GetAI_npc_thrall; + newscript->pGossipHello = &GossipHello_npc_thrall; + newscript->pGossipSelect = &GossipSelect_npc_thrall; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tyrande_whisperwind"; + newscript->pGossipHello = &GossipHello_npc_tyrande_whisperwind; + newscript->pGossipSelect = &GossipSelect_npc_tyrande_whisperwind; + newscript->GetAI = &GetAI_npc_tyrande_whisperwind; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h new file mode 100644 index 00000000000..bfc9a54dfd9 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_HYJAL_H +#define DEF_HYJAL_H + +#define ERROR_INST_DATA "TSCR: Instance data not set properly for Mount Hyjal. Encounters will be buggy." + +enum eTypes +{ + WORLD_STATE_WAVES = 2842, + WORLD_STATE_ENEMY = 2453, + WORLD_STATE_ENEMYCOUNT = 2454, + + DATA_ANETHERON = 1, + DATA_ANETHERONEVENT = 2, + DATA_ARCHIMONDE = 3, + DATA_ARCHIMONDEEVENT = 4, + DATA_AZGALOR = 5, + DATA_AZGALOREVENT = 6, + DATA_JAINAPROUDMOORE = 7, + DATA_KAZROGAL = 8, + DATA_KAZROGALEVENT = 9, + DATA_RAGEWINTERCHILL = 10, + DATA_RAGEWINTERCHILLEVENT = 11, + DATA_THRALL = 12, + DATA_TYRANDEWHISPERWIND = 13, + DATA_TRASH = 14, + DATA_RESET_TRASH_COUNT = 15, + DATA_ALLIANCE_RETREAT = 16, + DATA_HORDE_RETREAT = 17, + DATA_RAIDDAMAGE = 18, + DATA_RESET_RAIDDAMAGE = 19, + TYPE_RETREAT = 20 +}; +#endif + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp new file mode 100644 index 00000000000..3c12b54f3f4 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp @@ -0,0 +1,1157 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: HyjalAI +SD%Complete: 90 +SDComment: +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjalAI.h" +#include "hyjal_trash.h" +#include "MapManager.h" +#include "Language.h" +#include "Chat.h" +#include "Object.h" + +#define SPAWN_GARG_GATE 0 +#define SPAWN_WYRM_GATE 1 +#define SPAWN_NEAR_TOWER 2 + +#define YELL_HURRY "Hurry, we don't have much time" + +// Locations for summoning gargoyls and frost wyrms in special cases +float SpawnPointSpecial[3][3]= +{ + {5497.08, -2493.23, 1535.72}, //spawn point for the gargoyles near the horde gate + {5624.53, -2548.12, 1551.54}, //spawn point for the frost wyrm near the horde gate + {5604.41, -2811.98, 1547.77} //spawn point for the gargoyles and wyrms near the horde tower +}; + +// Locations for summoning waves in Alliance base +float AllianceBase[4][3]= +{ + {4928.48, -1526.38, 1326.83}, + {4923.54, -1514.29, 1327.98}, + {4928.41, -1510.35, 1327.99}, + {4938.35, -1521.00, 1326.69} +}; + +float JainaDummySpawn[2][4]= +{ + {5497.01, -2719.03, 1483.08, 2.90426}, + {5484.98, -2721.69, 1483.39, 6.00656} +}; + +// Locations for summoning waves in Horde base +float HordeBase[4][3]= +{ + {5458.01, -2340.27, 1459.60}, + {5466.01, -2334.69, 1460.06}, + {5468.45, -2355.13, 1459.99}, + {5479.06, -2344.16, 1461.74} +}; + +// Lady Jaina's waypoints when retreathing +float JainaWPs[2][3]= +{ + {5078.56, -1789.79, 1320.73},//next to the small stairs + {5037.38, -1778.39, 1322.61},//center of alliance base +}; + +float InfernalPos[8][3]=//spawn points for the infernals in the horde base +{ + {5453.59, -2764.52, 1493.50}, + {5478.4, -2781.77, 1497.52}, + {5506.09, -2780.53, 1496.32}, + {5532.1, -2763.42, 1492.37}, + {5544.16, -2733.99, 1487.14}, + {5536.19, -2708.18, 1480.01}, + {5510.16, -2691.75, 1479.66}, + {5482.39, -2689.19, 1481.09} +}; + +float InfernalSPWP[26][4]=//spawn points for the infernals in the horde base used in the cleaning wave +{ + {5490.96, -2718.72, 1482.96, 0.49773}, + {5449.51, -2723.32, 1485.69, 2.69685}, + {5520.83, -2624.68, 1483.82, 1.20459}, + {5558.28, -2629.26, 1485.76, 0.37992}, + {5567.97, -2758.69, 1494.10, 5.04125}, + {5384.90, -2793.47, 1503.90, 5.55412}, + {5495.33, -2814.06, 1501.56, 1.12055}, + {5472.63, -2929.39, 1538.31, 1.95777}, + {5334.72, -2952.29, 1534.34, 0.50869}, + {5398.36, -2872.46, 1512.38, 0.76787}, + {5514.39, -2768.63, 1492.30, 1.55721}, + {5598.91, -2703.75, 1495.64, 2.56644}, + {5467.80, -2655.93, 1482.27, 0.85819}, + {5399.83, -2985.24, 1545.04, 5.92559}, + {5232.13, -2967.05, 1553.09, 5.41351}, + {5272.02, -3082.52, 1567.09, 3.40681}, + {5343.26, -3120.71, 1582.92, 3.16727}, + {5371.26, -3175.24, 1587.41, 6.10466}, + {5434.67, -3177.91, 1579.25, 2.77850}, + {5237.39, -3149.25, 1593.59, 0.83855}, + {5202.15, -3016.64, 1566.28, 3.31256}, + {5302.54, -2914.37, 1528.53, 3.37146}, + {5439.04, -2834.81, 1508.80, 2.14231}, + {5421.33, -2771.04, 1494.28, 6.06223}, + {5549.76, -2692.93, 1482.68, 2.19414}, + {5459.78, -2755.71, 1490.68, 1.05139} +}; + +float VeinPos[14][8]=//spawn points of the ancient gem veins +{ + {5184.84, -1982.59, 1382.66, 2.58079, 0, 0, 0.960944, 0.276742}, //alliance + {5107.66, -2071.16, 1368.37, 2.65148, 0, 0, 0.970124, 0.242611}, //alliance + {5040.53, -2227.65, 1403.17, 3.35049, 0, 0, 0.99455, -0.104257}, //alliance + {5187.59, -2453.12, 1455.51, 5.87943, 0, 0, 0.20051, -0.979692}, //alliance + {5429.43, -2340.65, 1465.38, 4.7681, 0, 0, 0.687138, -0.726527}, //alliance + {5463.99, -2315.95, 1470.29, 1.52045, 0, 0, 0.689084, 0.724682}, //alliance + {5624.65, -2495.09, 1510.11, 0.0124869, 0, 0, 0.00624342, 0.999981}, //alliance + {5285.41, -3348.32, 1663.01, 1.57152, 0, 0, 0.707362, 0.706852}, //horde + {5417.69, -3372.52, 1656.31, 0.361993, 0, 0, 0.18001, 0.983665}, //horde + {5315.34, -3238.32, 1622.88, 3.03627, 0, 0, 0.998614, 0.0526347}, //horde + {5303.4, -3096.44, 1596.41, 1.72073, 0, 0, 0.758081, 0.65216}, //horde + {5265.13, -3177.27, 1616.22, 0.813604, 0, 0, 0.395674, 0.918391}, //horde + {5374.3, -3420.59, 1653.43, 1.45762, 0, 0, 0.665981, 0.745969}, //horde + {5441.54, -3321.59, 1651.55, 0.258306, 0, 0, 0.128794, 0.991671} //horde +}; + +float AllianceOverrunGargPos[5][4]=//gargoyle spawn points in the alliance overrun +{ + {5279.94, -2049.68, 1311.38, 0},//garg1 + {5289.15, -2219.06, 1291.12, 0},//garg2 + {5202.07, -2136.10, 1305.07, 2.8},//garg3 + {5071.52, -2425.63, 1454.48, 5.54},//garg4 + {5120.65, -2467.92, 1463.93, 2.54}//garg5 +}; + +float AllianceFirePos[92][8]=//spawn points for the fire visuals (GO) in the alliance base +{ + {5039.9, -1796.84, 1323.88, 2.59222, 0, 0, 0.962511, 0.271243}, + {5087.2, -1795.2, 1320.68, 1.03946, 0, 0, 0.496644, 0.867954}, + {5112.68, -1806.66, 1359.93, 1.37799, 0, 0, 0.63576, 0.771887}, + {5095.61, -1793.27, 1359.78, 0.580806, 0, 0, 0.286338, 0.958129}, + {5090.43, -1784.45, 1360.44, 0.796784, 0, 0, 0.387937, 0.921686}, + {5139.25, -1783.11, 1359.39, 3.30849, 0, 0, 0.99652, -0.0833509}, + {5112.16, -1763.72, 1361.35, 5.10312, 0, 0, 0.556388, -0.830922}, + {4981.18, -1793.98, 1335.7, 3.23072, 0, 0, 0.999007, -0.0445498}, + {4996.57, -1766.75, 1341.62, 3.5331, 0, 0, 0.980902, -0.194505}, + {4983.74, -1769.25, 1345.75, 3.79228, 0, 0, 0.947541, -0.319635}, + {4996.01, -1774.43, 1330.71, 3.07364, 0, 0, 0.999423, 0.0339693}, + {5094.2, -1726.13, 1330.55, 1.56175, 0, 0, 0.703901, 0.710298}, + {5079.82, -1721.24, 1336.26, 1.18868, 0, 0, 0.559964, 0.828517}, + {5077.68, -1717.15, 1327.78, 0.0145145, 0, 0, 0.00725717, 0.999974}, + {5122.27, -1738.22, 1341.67, 0.835256, 0, 0, 0.405593, 0.914054}, + {5131.88, -1741.15, 1335.25, 2.15472, 0, 0, 0.880712, 0.473653}, + {5196.93, -1772.99, 1345.2, 0.128397, 0, 0, 0.0641544, 0.99794}, + {5225.33, -1756.06, 1344.17, 3.04223, 0, 0, 0.998766, 0.0496599}, + {5224.84, -1767.05, 1360.06, 3.19538, 0, 0, 0.999638, -0.0268922}, + {5202.05, -1763.47, 1361.68, 2.59455, 0, 0, 0.962826, 0.270122}, + {5194.74, -1766.66, 1356.94, 0.0734191, 0, 0, 0.0367013, 0.999326}, + {5159.67, -1832.97, 1344.5, 5.17457, 0, 0, 0.526356, -0.850264}, + {5096.17, -1858.73, 1332.46, 5.30021, 0, 0, 0.471939, -0.881631}, + {5110.7, -1856.59, 1342.84, 5.97564, 0, 0, 0.153167, -0.9882}, + {5109.76, -1855.3, 1332.38, 4.89572, 0, 0, 0.639411, -0.768865}, + {5068.95, -1837.37, 1328.81, 2.61569, 0, 0, 0.965628, 0.25993}, + {5064.4, -1824.77, 1329.02, 2.16409, 0, 0, 0.88292, 0.469524}, + {5059.89, -1848.79, 1329.59, 0.0709955, 0, 0, 0.0354903, 0.99937}, + {5014.37, -1851.39, 1322.56, 4.66949, 0, 0, 0.722111, -0.691777}, + {5025.1, -1848.27, 1323.39, 4.44565, 0, 0, 0.794854, -0.606801}, + {4942.63, -1890.13, 1326.59, 3.28719, 0, 0, 0.997351, -0.0727343}, + {4937.95, -1888.71, 1352.41, 3.41678, 0, 0, 0.990549, -0.13716}, + {4922.48, -1881.92, 1352.41, 5.03077, 0, 0, 0.586075, -0.810257}, + {4915.35, -1894.32, 1351.24, 6.22457, 0, 0, 0.0293048, -0.999571}, + {4922.71, -1904.84, 1352.56, 1.37866, 0, 0, 0.63602, 0.771672}, + {4932.89, -1905.49, 1352.56, 1.89702, 0, 0, 0.812549, 0.582893}, + {5011.83, -1861.05, 1345.86, 4.43777, 0, 0, 0.797239, -0.603664}, + {5011.83, -1861.05, 1363.26, 4.748, 0, 0, 0.694406, -0.719583}, + {5021.46, -1858.35, 1342.17, 4.86188, 0, 0, 0.652329, -0.757936}, + {4995.02, -1698.3, 1370.38, 6.15779, 0, 0, 0.0626579, -0.998035}, + {5119.85, -1728.9, 1336.04, 5.87112, 0, 0, 0.204579, -0.97885}, + {5214.75, -1751.02, 1342.5, 5.08965, 0, 0, 0.561972, -0.827156}, + {5075.04, -1822.43, 1328.87, 3.99951, 0, 0, 0.9094, -0.415924}, + {5057.09, -1823.32, 1350.35, 3.88169, 0, 0, 0.93231, -0.361659}, + {4984.6, -1816.99, 1329.21, 3.05308, 0, 0, 0.999021, 0.0442417}, + {4983.35, -1811.55, 1356.82, 3.33975, 0, 0, 0.995096, -0.098917}, + {4984.11, -1825.73, 1350.76, 2.26375, 0, 0, 0.905211, 0.424962}, + {4968.47, -1786.46, 1354.09, 3.07663, 0, 0, 0.999473, 0.0324733}, + {5061.82, -1751.16, 1339.07, 5.94727, 0, 0, 0.167171, -0.985928}, + {5063.75, -1763, 1351.91, 0.759707, 0, 0, 0.370784, 0.928719}, + {5078.65, -1708.26, 1353.9, 1.27022, 0, 0, 0.593264, 0.805008}, + {4983.19, -1755.96, 1331.13, 4.28221, 0, 0, 0.841733, -0.539894}, + {4972.76, -1755.3, 1332.5, 4.21938, 0, 0, 0.858276, -0.513188}, + {4961.65, -1760.82, 1351.69, 3.56515, 0, 0, 0.977659, -0.210198}, + {5086.45, -1779.83, 1321.62, 6.23157, 0, 0, 0.0258051, -0.999667}, + {5063.15, -1756.74, 1328.56, 0.886926, 0, 0, 0.42907, 0.903271}, + {5042.45, -1800.61, 1323.88, 2.50093, 0, 0, 0.949131, 0.31488}, + {5084.74, -1725.35, 1327.89, 1.65034, 0, 0, 0.734663, 0.678432}, + {4993.25, -1758.1, 1331.07, 3.49995, 0, 0, 0.98399, -0.178223}, + {5078.53, -1867.85, 1348.91, 5.85612, 0, 0, 0.211913, -0.977288}, + {5080.74, -1869.73, 1333.18, 6.18206, 0, 0, 0.0505424, -0.998722}, + {5089.55, -1894.13, 1356.08, 1.52072, 0, 0, 0.689181, 0.724589}, + {5113.24, -1899.49, 1363.77, 1.50108, 0, 0, 0.682034, 0.731321}, + {4984.18, -1907.69, 1325.62, 3.82193, 0, 0, 0.942698, -0.333646}, + {5094.14, -2432.08, 1429.38, 4.70083, 0, 0, 0.711182, -0.703007}, + {5329.89, -2113.30, 1281.06, 5.60560, 0, 0, 0.332347, -0.943157}, + {5170.87, -2148.13, 1278.32, 1.63540, 0, 0, 0.729573, 0.683903 }, + {5132.94, -1960.25, 1367.8, 3.69787, 0, 0, 0.961568, -0.274566}, + {5280.82, -2351.55, 1431.57, 4.46913, 0, 0, 0.787677, -0.616088}, + {5176.78, -2121.43, 1295.27, 3.24153, 0, 0, 0.998752, -0.04995}, + {5332.75, -2101.41, 1296.37, 5.50350, 0, 0, 0.380043, -0.924969}, + {5265.70, -2050.27, 1287.57, 0.50051, 0, 0, 0.247655, 0.968848 }, + {5194.21, -2129.89, 1274.04, 3.08053, 0, 0, 0.999534, 0.0305272}, + {5225.81, -1985.50, 1364.15, 0.37247, 0, 0, 0.185163, 0.982708 }, + {5339.46, -2204.47, 1280.45, 0.99921, 0, 0, 0.479081, 0.877771 }, + {5269.63, -2020.57, 1299.62, 3.00201, 0, 0, 0.997566, 0.0697332}, + {5111.54, -2445.70, 1435.31, 2.70983, 0, 0, 0.976788, 0.214207 }, + {5111.24, -1901.14, 1355.33, 1.61028, 0, 0, 0.720929, 0.693009 }, + {5310.42, -2207.82, 1277.46, 0.50441, 0, 0, 0.249544, 0.968363 }, + {5150.81, -2042.13, 1394.3, 2.21031, 0, 0, 0.893534, 0.448995 }, + {5224.84, -2376.61, 1366.33, 5.0621, 0, 0, 0.573311, -0.819338}, + {5105.41, -2454.86, 1446.16, 4.64584, 0, 0, 0.730239, -0.683191}, + {5309.65, -2188.28, 1266.84, 5.56631, 0, 0, 0.350811, -0.936446}, + {5281.46, -2047.82, 1287.67, 2.44909, 0, 0, 0.940652, 0.339373 }, + {5325.45, -2189.41, 1309.6, 6.23783, 0, 0, 0.0226771, -0.999743}, + {5190.96, -2142.54, 1293.03, 6.25668, 0, 0, 0.0132544, -0.999912}, + {5089.99, -2467.49, 1441.8, 0.77381, 0, 0, 0.377326, 0.92608 }, + {5195.08, -2129.01, 1285.36, 3.55727, 0, 0, 0.978480, -0.206344}, + {5353.76, -2116.28, 1299.27, 6.17894, 0, 0, 0.0521006, -0.998642}, + {5271.14, -2037.38, 1299.24, 4.07879, 0, 0, 0.892201, -0.451638}, + {5332.5 , -2181.28, 1279.95, 4.6906, 0, 0, 0.714768, -0.699362}, + {5108.2 , -2429.84, 1427.73, 4.5194, 0, 0, 0.771943, -0.635691} +}; + +float HordeFirePos[65][8]=//spawn points for the fire visuals (GO) in the horde base +{ + {5524.11, -2612.73, 1483.38, 1.96198, 0, 0, 0.831047, 0.556202}, + {5514.42, -2617.19, 1505.77, 1.82453, 0, 0, 0.790892, 0.611956}, + {5510.21, -2624.77, 1485.34, 1.71065, 0, 0, 0.754783, 0.655974}, + {5570.72, -2619.04, 1487.62, 0.728898, 0, 0, 0.356435, 0.93432}, + {5570.29, -2639.37, 1487.31, 1.49308, 0, 0, 0.679104, 0.734042}, + {5583.56, -2637.2, 1503.78, 1.46559, 0, 0, 0.668951, 0.743307}, + {5571.53, -2626.81, 1510.99, 0.362107, 0, 0, 0.180066, 0.983654}, + {5545.97, -2659.62, 1489.64, 5.07055, 0, 0, 0.569845, -0.821752}, + {5557.44, -2675.91, 1482.58, 1.70118, 0, 0, 0.751671, 0.659539}, + {5594.98, -2742.31, 1495.51, 4.5993, 0, 0, 0.74594, -0.666013}, + {5599.65, -2755.6, 1505.05, 1.66896, 0, 0, 0.740947, 0.671564}, + {5565.95, -2774.75, 1499.48, 6.22425, 0, 0, 0.0294611, -0.999566}, + {5567.1, -2769.7, 1511.17, 5.99257, 0, 0, 0.144799, -0.989461}, + {5572.84, -2774.16, 1527.06, 0.836428, 0, 0, 0.406129, 0.913816}, + {5538.32, -2805.94, 1498.87, 4.30082, 0, 0, 0.836674, -0.547701}, + {5515.66, -2801.74, 1503.53, 5.57316, 0, 0, 0.347602, -0.937642}, + {5516.76, -2827.14, 1501.15, 0.35026, 0, 0, 0.174236, 0.984704}, + {5536.13, -2813.51, 1537.21, 4.51681, 0, 0, 0.772765, -0.634692}, + {5525.05, -2825.16, 1538.53, 0.489275, 0, 0, 0.242205, 0.970225}, + {5534.42, -2815.45, 1562.84, 4.62834, 0, 0, 0.736191, -0.676774}, + {5519.64, -2831.12, 1526.46, 0.611008, 0, 0, 0.300774, 0.953696}, + {5551.04, -2827.55, 1523.5, 3.35206, 0, 0, 0.994468, -0.10504}, + {5469.22, -2802.87, 1503.5, 4.99509, 0, 0, 0.600436, -0.799673}, + {5427.8, -2737.26, 1487.12, 1.78673, 0, 0, 0.779186, 0.626793}, + {5454.1, -2709.1, 1485.92, 3.03552, 0, 0, 0.998594, 0.0530137}, + {5436.3, -2718.2, 1506.02, 2.7567, 0, 0, 0.981539, 0.191261}, + {5412.6, -2740.55, 1510.79, 2.98446, 0, 0, 0.996915, 0.0784832}, + {5406.12, -2752.48, 1521.01, 2.05769, 0, 0, 0.856705, 0.515807}, + {5445.24, -2676.35, 1521.89, 2.91378, 0, 0, 0.99352, 0.113661}, + {5481.4, -2665.08, 1482.23, 4.30001, 0, 0, 0.836895, -0.547363}, + {5443.51, -2675.44, 1487.12, 2.90986, 0, 0, 0.993295, 0.115606}, + {5391.72, -2647.3, 1528.9, 3.76987, 0, 0, 0.951063, -0.308997}, + {5421.09, -2734.12, 1521.01, 2.70567, 0, 0, 0.97634, 0.216242}, + {5405.39, -2710.33, 1533.77, 2.51324, 0, 0, 0.951052, 0.309032}, + {5423.96, -2703.76, 1516.34, 2.79206, 0, 0, 0.984767, 0.173879}, + {5444.75, -2735.23, 1486.37, 2.22657, 0, 0, 0.897155, 0.441715}, + {5570.98, -2747.91, 1495.7, 5.14433, 0, 0, 0.53915, -0.84221}, + {5567.79, -2673.9, 1484.66, 2.72529, 0, 0, 0.978415, 0.20665}, + {5600.71, -2696.8, 1500.42, 0.443704, 0, 0, 0.220036, 0.975492}, + {5600.7, -2693.04, 1515.2, 5.16003, 0, 0, 0.532522, -0.846416}, + {5627.56, -2839.66, 1510.53, 5.41527, 0, 0, 0.420463, -0.907309}, + {5622.02, -2868.71, 1516.22, 2.25482, 0, 0, 0.903303, 0.429002}, + {5586.61, -2878.97, 1510.34, 4.55604, 0, 0, 0.76017, -0.649724}, + {5583.78, -2843.71, 1509.54, 5.35715, 0, 0, 0.44665, -0.894709}, + {5580.95, -2811.3, 1513.3, 3.57587, 0, 0, 0.976518, -0.215434}, + {5542.52, -2869.31, 1523.13, 5.23304, 0, 0, 0.501275, -0.865288}, + {5557.35, -2866.36, 1518.76, 4.48299, 0, 0, 0.783388, -0.621533}, + {5380.91, -2849.36, 1512.81, 3.90962, 0, 0, 0.927168, -0.374646}, + {5395.76, -2881.41, 1521.11, 4.28426, 0, 0, 0.84118, -0.540755}, + {5374.87, -2859.63, 1528.98, 3.30252, 0, 0, 0.996765, -0.0803745}, + {5356.07, -2854.66, 1520.34, 5.83933, 0, 0, 0.220108, -0.975475}, + {5363.01, -2975.72, 1539.02, 4.13738, 0, 0, 0.87859, -0.477576}, + {5336.85, -2980.74, 1561.24, 5.11126, 0, 0, 0.553001, -0.83318}, + {5335.23, -2974.62, 1540.05, 5.04451, 0, 0, 0.580496, -0.814263}, + {5422.37, -2998.87, 1549.98, 4.51831, 0, 0, 0.772288, -0.635272}, + {5405.54, -3014.6, 1562.16, 5.86761, 0, 0, 0.206298, -0.978489}, + {5427.96, -3019.4, 1561.58, 3.53498, 0, 0, 0.980718, -0.19543}, + {5348.12, -2977.84, 1582.47, 3.94025, 0, 0, 0.921323, -0.388799}, + {5331.12, -2993.71, 1576.14, 0.0642734, 0, 0, 0.0321311, 0.999484}, + {5321.63, -2986.55, 1552.2, 5.29503, 0, 0, 0.474219, -0.880407}, + {5292.1, -2914.36, 1529.52, 2.9742, 0, 0, 0.996499, 0.083601}, + {5281.77, -2926.5, 1530.62, 1.67829, 0, 0, 0.744071, 0.6681}, + {5287.19, -2909.94, 1543.49, 3.31192, 0, 0, 0.996376, -0.0850591}, + {5534.15, -2679.35, 1483.61, 0.428685, 0, 0, 0.212705, 0.977116}, + {5545.43, -2647.82, 1483.05, 5.38848, 0, 0, 0.432578, -0.901596} +}; + +hyjalAI::hyjalAI(Creature *c) : npc_escortAI(c), Summons(me) +{ + pInstance = c->GetInstanceData(); + VeinsSpawned[0] = false; + VeinsSpawned[1] = false; + for (uint8 i=0; i<14; ++i) + VeinGUID[i] = 0; + InfernalCount = 0; + TeleportTimer = 1000; + Overrun = false; + Teleported = false; + WaitForTeleport = false; + OverrunCounter = 0; + OverrunCounter2 = 0; + InfernalPoint = 0; + RespawnTimer = 10000; + DoRespawn = false; + DoHide = false; + MassTeleportTimer = 0; + DoMassTeleport = false; +} + +void hyjalAI::JustSummoned(Creature *summoned) +{ + Summons.Summon(summoned); +} + +void hyjalAI::SummonedCreatureDespawn(Creature* summoned) +{ + Summons.Despawn(summoned); +} + +void hyjalAI::Reset() +{ + IsDummy = false; + me->setActive(true); + // GUIDs + PlayerGUID = 0; + BossGUID[0] = 0; + BossGUID[1] = 0; + + // Timers + NextWaveTimer = 10000; + CheckTimer = 0; + RetreatTimer = 1000; + + // Misc + WaveCount = 0; + EnemyCount = 0; + + // Set faction properly based on Creature entry + switch(me->GetEntry()) + { + case JAINA: + Faction = 0; + DoCast(me, SPELL_BRILLIANCE_AURA, true); + break; + + case THRALL: + Faction = 1; + break; + + case TYRANDE: + Faction = 2; + break; + } + + //Bools + EventBegun = false; + FirstBossDead = false; + SecondBossDead = false; + Summon = false; + bRetreat = false; + Debug = false; + + //Flags + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + //Initialize spells + memset(Spell, 0, sizeof(Spell)); + + //Reset Instance Data for trash count + if (pInstance) + { + if ((!pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == JAINA) || (pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == THRALL)) + { + //Reset World States + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); + pInstance->SetData(DATA_RESET_TRASH_COUNT, 0); + } + } else error_log(ERROR_INST_DATA); + + //Visibility + DoHide = true; +} + +void hyjalAI::EnterEvadeMode() +{ + if (me->GetEntry() != JAINA) + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + me->LoadCreaturesAddon(); + + if (me->isAlive()) + me->GetMotionMaster()->MoveTargetedHome(); + + me->SetLootRecipient(NULL); +} + +void hyjalAI::EnterCombat(Unit * /*who*/) +{ + if (IsDummy)return; + for (uint8 i = 0; i < 3; ++i) + if (Spell[i].Cooldown) + SpellTimer[i] = Spell[i].Cooldown; + + Talk(ATTACKED); +} + +void hyjalAI::MoveInLineOfSight(Unit *who) +{ + if (IsDummy) + return; + + npc_escortAI::MoveInLineOfSight(who); +} + +void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) +{ + uint32 random = rand()%4; + float SpawnLoc[3]; + + for (uint8 i = 0; i < 3; ++i) + { + SpawnLoc[i] = Base[random][i]; + } + Creature* pCreature = NULL; + switch(entry) + { + case 17906: //GARGOYLE + + if (!FirstBossDead && (WaveCount == 1 || WaveCount == 3)) + {//summon at tower + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][1]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + if (pCreature) + CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; + }else{//summon at gate + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_GARG_GATE][0]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][1]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + } + break; + case 17907: //FROST_WYRM , + if (FirstBossDead && WaveCount == 1) //summon at gate + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_WYRM_GATE][0],SpawnPointSpecial[SPAWN_WYRM_GATE][1],SpawnPointSpecial[SPAWN_WYRM_GATE][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + else + { + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0], SpawnPointSpecial[SPAWN_NEAR_TOWER][1],SpawnPointSpecial[SPAWN_NEAR_TOWER][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + if (pCreature) + CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; + } + break; + case 17908: //GIANT_INFERNAL + ++InfernalCount; + if (InfernalCount > 7) + InfernalCount = 0; + pCreature = me->SummonCreature(entry, InfernalPos[InfernalCount][0], InfernalPos[InfernalCount][1], InfernalPos[InfernalCount][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + default: + pCreature = me->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + + } + + if (pCreature) + { + // Increment Enemy Count to be used in World States and instance script + ++EnemyCount; + + pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCreature->setActive(true); + switch(entry) + { + case NECROMANCER: + case ABOMINATION: + case GHOUL: + case BANSHEE: + case CRYPT_FIEND: + case GARGOYLE: + case FROST_WYRM: + case GIANT_INFERNAL: + case FEL_STALKER: + case RAGE_WINTERCHILL: + case ANETHERON: + case KAZROGAL: + case AZGALOR: + CAST_AI(hyjal_trashAI, pCreature->AI())->IsEvent = true; + break; + } + if (pInstance) + { + if (pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE) + pCreature->SetDisableReputationGain(true);//no repu for solo farming + } + // Check if Creature is a boss. + if (pCreature->isWorldBoss()) + { + if (!FirstBossDead) BossGUID[0] = pCreature->GetGUID(); + else BossGUID[1] = pCreature->GetGUID(); + CheckTimer = 5000; + } + } +} + +void hyjalAI::SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]) +{ + // 1 in 4 chance we give a rally yell. Not sure if the chance is offilike. + if (rand()%4 == 0) + Talk(RALLY); + + if (!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + InfernalCount = 0;//reset infernal count every new wave + + EnemyCount = pInstance->GetData(DATA_TRASH); + for (uint8 i = 0; i < 18; ++i) + { + if (wave[Count].Mob[i]) + SummonCreature(wave[Count].Mob[i], Base); + } + + if (!wave[Count].IsBoss) + { + uint32 stateValue = Count+1; + if (FirstBossDead) + stateValue -= 9; // Subtract 9 from it to give the proper wave number if we are greater than 8 + + // Set world state to our current wave number + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, stateValue); // Set world state to our current wave number + // Enable world state + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); // Enable world state + + pInstance->SetData(DATA_TRASH, EnemyCount); // Send data for instance script to update count + + if (!Debug) + NextWaveTimer = wave[Count].WaveTimer; + else + { + NextWaveTimer = 15000; + debug_log("TSCR: HyjalAI: debug mode is enabled. Next Wave in 15 seconds"); + } + } + else + { + // Set world state for waves to 0 to disable it. + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); + + // Set World State for enemies invading to 1. + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 1); + + Summon = false; + } + CheckTimer = 5000; +} + +void hyjalAI::StartEvent(Player* pPlayer) +{ + if (!pPlayer || IsDummy || !pInstance) + return; + + Talk(BEGIN); + + EventBegun = true; + Summon = true; + + NextWaveTimer = 15000; + CheckTimer = 5000; + PlayerGUID = pPlayer->GetGUID(); + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); + + DeSpawnVeins(); +} + +uint32 hyjalAI::GetInstanceData(uint32 Event) +{ + if (pInstance) + return pInstance->GetData(Event); + else error_log(ERROR_INST_DATA); + + return 0; +} + +void hyjalAI::Talk(uint32 id) +{ + std::list index; + for (uint8 i = 0; i < 9; ++i) + { + if (Faction == 0) // Alliance + { + if (JainaQuotes[i].id == id) + index.push_back(i); + } + else if (Faction == 1) // Horde + { + if (ThrallQuotes[i].id == id) + index.push_back(i); + } + } + + if (index.empty()) + return; // No quotes found, no use to continue + + uint8 ind = *(index.begin()) + rand()%index.size(); + + int32 YellId = 0; + if (Faction == 0) // Alliance + { + YellId = JainaQuotes[ind].textid; + } + else if (Faction == 1) // Horde + { + YellId = ThrallQuotes[ind].textid; + } + + if (YellId) + DoScriptText(YellId, me); +} + +void hyjalAI::Retreat() +{ + if (pInstance) + { + pInstance->SetData(TYPE_RETREAT,SPECIAL); + + if (Faction == 0) + { + pInstance->SetData(DATA_ALLIANCE_RETREAT, 1); + AddWaypoint(0,JainaWPs[0][0],JainaWPs[0][1],JainaWPs[0][2]); + AddWaypoint(1,JainaWPs[1][0],JainaWPs[1][1],JainaWPs[1][2]); + Start(false, false); + SetDespawnAtEnd(false);//move to center of alliance base + } + if (Faction == 1) + { + pInstance->SetData(DATA_HORDE_RETREAT, 1); + Creature* JainaDummy = me->SummonCreature(JAINA,JainaDummySpawn[0][0],JainaDummySpawn[0][1],JainaDummySpawn[0][2],JainaDummySpawn[0][3],TEMPSUMMON_TIMED_DESPAWN,60000); + if (JainaDummy) + { + JainaDummy->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + CAST_AI(hyjalAI, JainaDummy->AI())->IsDummy = true; + DummyGuid = JainaDummy->GetGUID(); + } + AddWaypoint(0,JainaDummySpawn[1][0],JainaDummySpawn[1][1],JainaDummySpawn[1][2]); + Start(false, false); + SetDespawnAtEnd(false);//move to center of alliance base + } + } + SpawnVeins(); + Overrun = true; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//cant talk after overrun event started +} + +void hyjalAI::SpawnVeins() +{ + if (Faction == 0) + { + if (VeinsSpawned[0])//prevent any buggers + return; + for (uint8 i = 0; i<7; ++i) + { + GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); + if (gem) + VeinGUID[i]=gem->GetGUID(); + } + VeinsSpawned[0] = true; + }else{ + if (VeinsSpawned[1]) + return; + for (uint8 i = 7; i<14; ++i) + { + GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); + if (gem) + VeinGUID[i]=gem->GetGUID(); + } + VeinsSpawned[1] = true; + } +} + +void hyjalAI::DeSpawnVeins() +{ + if (!pInstance) + return; + if (Faction == 1) + { + Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (!pUnit)return; + hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); + if (!ai)return; + for (uint8 i = 0; i<7; ++i) + { + if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) + gem->Delete(); + } + } else if (Faction) + { + Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_THRALL)); + if (!pUnit)return; + hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); + if (!ai)return; + for (uint8 i = 7; i<14; ++i) + { + if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) + gem->Delete(); + } + } +} + +void hyjalAI::UpdateAI(const uint32 diff) +{ + if (IsDummy) + { + if (MassTeleportTimer < diff && DoMassTeleport) + { + DoCast(me, SPELL_MASS_TELEPORT, false); + DoMassTeleport = false; + } else MassTeleportTimer -= diff; + return; + } + if (DoHide) + { + DoHide = false; + switch(me->GetEntry()) + { + case JAINA: + if (pInstance && pInstance->GetData(DATA_ALLIANCE_RETREAT)) + { + me->SetVisibility(VISIBILITY_OFF); + HideNearPos(me->GetPositionX(), me->GetPositionY()); + HideNearPos(5037.76, -1889.71); + for (uint8 i = 0; i < 92; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); + + } + else me->SetVisibility(VISIBILITY_ON); + break; + case THRALL: //thrall + if (pInstance && pInstance->GetData(DATA_HORDE_RETREAT)) + { + me->SetVisibility(VISIBILITY_OFF); + HideNearPos(me->GetPositionX(), me->GetPositionY()); + HideNearPos(5563, -2763.19); + HideNearPos(5542.2, -2629.36); + for (uint8 i = 0; i < 65; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); + + } + else me->SetVisibility(VISIBILITY_ON); + break; + } + } + if (DoRespawn) + { + if (RespawnTimer <= diff) + { + DoRespawn = false; + RespawnNearPos(me->GetPositionX(), me->GetPositionY()); + if (Faction == 0) + { + RespawnNearPos(5037.76, -1889.71); + } else if (Faction == 1) + { + RespawnNearPos(5563, -2763.19); + RespawnNearPos(5542.2, -2629.36); + } + me->SetVisibility(VISIBILITY_ON); + }else{ + RespawnTimer -= diff; + me->SetVisibility(VISIBILITY_OFF); + } + return; + } + if (Overrun) + DoOverrun(Faction, diff); + if (bRetreat) + { + if (RetreatTimer <= diff) + { + IsDummy = true; + bRetreat = false; + HideNearPos(me->GetPositionX(), me->GetPositionY()); + switch(me->GetEntry()) + { + case JAINA://jaina + HideNearPos(5037.76, -1889.71); + break; + case THRALL://thrall + HideNearPos(5563, -2763.19); + HideNearPos(5542.2, -2629.36); + HideNearPos(5603.75, -2853.12); + break; + } + me->SetVisibility(VISIBILITY_OFF); + } else RetreatTimer -= diff; + } + + if (!EventBegun) + return; + + if (Summon) + { + if (pInstance && EnemyCount) + { + EnemyCount = pInstance->GetData(DATA_TRASH); + if (!EnemyCount) + NextWaveTimer = 5000; + } + + if (NextWaveTimer <= diff) + { + if (Faction == 0) + SummonNextWave(AllianceWaves, WaveCount, AllianceBase); + else if (Faction == 1) + SummonNextWave(HordeWaves, WaveCount, HordeBase); + ++WaveCount; + } else NextWaveTimer -= diff; + } + + if (CheckTimer <= diff) + { + for (uint8 i = 0; i < 2; ++i) + { + if (BossGUID[i]) + { + Unit* pUnit = Unit::GetUnit((*me), BossGUID[i]); + if (pUnit && (!pUnit->isAlive())) + { + if (BossGUID[i] == BossGUID[0]) + { + Talk(INCOMING); + FirstBossDead = true; + } + else if (BossGUID[i] == BossGUID[1]) + { + Talk(SUCCESS); + SecondBossDead = true; + } + EventBegun = false; + CheckTimer = 0; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + BossGUID[i] = 0; + if (pInstance) + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); // Reset world state for enemies to disable it + } + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + if (!UpdateVictim()) + return; + + for (uint8 i = 0; i < 3; ++i) + { + if (Spell[i].SpellId) + { + if (SpellTimer[i] <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + Unit *pTarget = NULL; + + switch(Spell[i].TargetType) + { + case TARGETTYPE_SELF: pTarget = me; break; + case TARGETTYPE_RANDOM: pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); break; + case TARGETTYPE_VICTIM: pTarget = me->getVictim(); break; + } + + if (pTarget && pTarget->isAlive()) + { + DoCast(pTarget, Spell[i].SpellId); + SpellTimer[i] = Spell[i].Cooldown; + } + } else SpellTimer[i] -= diff; + } + } + + DoMeleeAttackIfReady(); +} +void hyjalAI::JustDied(Unit* /*killer*/) +{ + if (IsDummy)return; + me->Respawn(); + me->SetVisibility(VISIBILITY_OFF); + DoRespawn = true; + RespawnTimer = 120000; + Talk(DEATH); + Summons.DespawnAll();//despawn all wave's summons + if (pInstance) + {//reset encounter if boss is despawned (ex: thrall is killed, boss despawns, event stucks at inprogress) + if (pInstance->GetData(DATA_RAGEWINTERCHILLEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_ANETHERONEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_KAZROGALEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_AZGALOREVENT) == IN_PROGRESS) + pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); + pInstance->SetData(DATA_RESET_RAIDDAMAGE, NULL);//reset damage on die + } +} +void hyjalAI::HideNearPos(float x, float y) +{ + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + // First get all creatures. + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + // Get Creatures + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + (*itr)->SetVisibility(VISIBILITY_OFF); + (*itr)->setFaction(35);//make them friendly so mobs won't attack them + } + } +} +void hyjalAI::RespawnNearPos(float x, float y) +{ + CellPair p(Trinity::ComputeCellPair(x, y)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::RespawnDo u_do; + Trinity::WorldObjectWorker worker(me, u_do); + TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); + cell.Visit(p, obj_worker, *me->GetMap()); +} +void hyjalAI::WaypointReached(uint32 i) +{ + if (i == 1 || (i == 0 && me->GetEntry() == THRALL)) + { + me->MonsterYell(YELL_HURRY,0,0); + WaitForTeleport = true; + TeleportTimer = 20000; + if (me->GetEntry() == JAINA) + DoCast(me, SPELL_MASS_TELEPORT, false); + if (me->GetEntry() == THRALL && DummyGuid) + { + Unit* Dummy = Unit::GetUnit((*me),DummyGuid); + if (Dummy) + { + CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->DoMassTeleport = true; + CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->MassTeleportTimer = 20000; + Dummy->CastSpell(me, SPELL_MASS_TELEPORT, false); + } + } + //do some talking + //all alive guards walk near here + CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + // First get all creatures. + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive() && (*itr) != me && (*itr)->GetEntry() != JAINA) + { + if (!(*itr)->IsWithinDist(me, 60)) + (*itr)->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + float x, y, z; + (*itr)->SetDefaultMovementType(IDLE_MOTION_TYPE); + (*itr)->GetMotionMaster()->Initialize(); + float range = 10; + if (me->GetEntry() == THRALL)range = 20; + me->GetNearPoint(me, x, y, z, range, 0, me->GetAngle((*itr))); + (*itr)->GetMotionMaster()->MovePoint(0, x+irand(-5,5), y+irand(-5,5), me->GetPositionZ()); + } + } + } + } +} +void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) +{ + npc_escortAI::UpdateAI(diff); + if (WaitForTeleport) + { + if (TeleportTimer <= diff) + { + CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive()) + { + (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); + (*itr)->setFaction(35);//make them friendly so mobs won't attack them + (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + DoCast(me, SPELL_TELEPORT_VISUAL); + bRetreat = true; + RetreatTimer = 1000; + } + + WaitForTeleport = false; + Teleported = true; + }TeleportTimer -= diff; + } + if (!Teleported) + return; + Overrun = false;//execute once + switch(faction) + { + case 0://alliance + for (uint8 i = 0; i < 92; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); + + for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(GHOUL, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 3; ++i)//summon 3 abominations + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(ABOMINATION, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles + { + Creature* pUnit = me->SummonCreature(GARGOYLE, AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + pUnit->SetHomePosition(AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3]); + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + break; + case 1://horde + for (uint8 i = 0; i < 65; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); + + for (uint8 i = 0; i < 26; ++i)//summon infernals + { + Creature* pUnit = me->SummonCreature(GIANT_INFERNAL, InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + pUnit->SetHomePosition(InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3]); + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(GHOUL, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 5; ++i)//summon 5 abominations + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(ABOMINATION, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + break; + } +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h new file mode 100644 index 00000000000..5c75465b7b4 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h @@ -0,0 +1,248 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_HYJALAI_H +#define SC_HYJALAI_H + +#include "hyjal.h" +#include "ScriptedEscortAI.h" + +// Trash Mobs summoned in waves +#define NECROMANCER 17899//done +#define ABOMINATION 17898//done +#define GHOUL 17895//done +#define BANSHEE 17905//done +#define CRYPT_FIEND 17897//done +#define GARGOYLE 17906//done +#define FROST_WYRM 17907//done +#define GIANT_INFERNAL 17908//done +#define FEL_STALKER 17916//done + +#define JAINA 17772 +#define THRALL 17852 +#define TYRANDE 17948 + +#define ANCIENT_VEIN 185557 +#define FLAMEOBJECT 182592 + +// Bosses summoned after every 8 waves +#define RAGE_WINTERCHILL 17767 +#define ANETHERON 17808 +#define KAZROGAL 17888 +#define AZGALOR 17842 +#define ARCHIMONDE 17968 + +#define SPELL_TELEPORT_VISUAL 41232 +#define SPELL_MASS_TELEPORT 16807 + +//Spells for Jaina +#define SPELL_BRILLIANCE_AURA 31260 // The database must handle this spell via creature_addon(it should, but is removed in evade..) +#define SPELL_BLIZZARD 31266 +#define SPELL_PYROBLAST 31263 +#define SPELL_SUMMON_ELEMENTALS 31264 + +//Thrall spells +#define SPELL_CHAIN_LIGHTNING 31330 +#define SPELL_SUMMON_DIRE_WOLF 31331 + +struct Wave +{ + uint32 Mob[18]; // Stores Creature Entries to be summoned in Waves + uint32 WaveTimer; // The timer before the next wave is summoned + bool IsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that +}; + +static Wave AllianceWaves[]= // Waves that will be summoned in the Alliance Base +{ // Rage Winterchill Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron + {RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, + // Anetheron Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, GHOUL, GHOUL, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + // All 8 Waves are summoned, summon Anatheron + {ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} +}; + +static Wave HordeWaves[]= // Waves that are summoned in the Horde base +{ // Kaz'Rogal Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, + // All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor + {KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, + // Azgalor Wave 1-8 + {ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, FROST_WYRM, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, + {GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, 0, 0, 0, 0, 180000, false}, + {FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, + // All 8 Waves are summoned, summon Azgalor + {AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} +}; + +enum TargetType // Used in the spell cast system for the AI +{ + TARGETTYPE_SELF = 0, + TARGETTYPE_RANDOM = 1, + TARGETTYPE_VICTIM = 2, +}; + +struct Yells +{ + uint32 id; // Used to determine the type of yell (attack, rally, etc) + int32 textid; // The text id to be yelled +}; + +enum YellId +{ + ATTACKED = 0, // Used when attacked and set in combat + BEGIN = 1, // Used when the event is begun + INCOMING = 2, // Used to warn the raid that another wave phase is coming + RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned + FAILURE = 4, // Used when raid has failed (unsure where to place) + SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase + DEATH = 6, // Used on death +}; + +static Yells JainaQuotes[]= +{ + {ATTACKED, -1534000}, + {ATTACKED, -1534001}, + {INCOMING, -1534002}, + {BEGIN, -1534003}, + {RALLY, -1534004}, + {RALLY, -1534005}, + {FAILURE, -1534006}, + {SUCCESS, -1534007}, + {DEATH, -1534008}, +}; + +static Yells ThrallQuotes[]= +{ + {ATTACKED, -1534009}, + {ATTACKED, -1534010}, + {INCOMING, -1534011}, + {BEGIN, -1534012}, + {RALLY, -1534013}, + {RALLY, -1534014}, + {FAILURE, -1534015}, + {SUCCESS, -1534016}, + {DEATH, -1534017}, +}; + +struct hyjalAI : public npc_escortAI +{ + hyjalAI(Creature *c); + + void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat + + void EnterEvadeMode(); // Send creature back to spawn location and evade. + + void EnterCombat(Unit * /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack + + void UpdateAI(const uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells. + + void JustDied(Unit* /*killer*/); // Called on death, informs the raid that they have failed. + + void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal + { + Faction = _faction; + } + + void Retreat(); // "Teleport" (teleport visual + set invisible) all friendly creatures away from the base. + + void SpawnVeins(); + void DeSpawnVeins(); + void JustSummoned(Creature *summoned); + void SummonedCreatureDespawn(Creature* summoned); + void HideNearPos(float x, float y); + void RespawnNearPos(float x, float y); + void WaypointReached(uint32 i); + void DoOverrun(uint32 faction, const uint32 diff); + void MoveInLineOfSight(Unit *who); + + void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base + + // Summons the next wave, calls SummonCreature + void SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]); + + void StartEvent(Player* player); // Begins the event by gossip click + + uint32 GetInstanceData(uint32 Event); // Gets instance data for this instance, used to check if raid has gotten past a certain point and can access the next phase + + void Talk(uint32 id); // Searches for the appropriate yell and sound and uses it to inform the raid of various things + + public: + ScriptedInstance* pInstance; + + uint64 PlayerGUID; + uint64 BossGUID[2]; + uint64 VeinGUID[14]; + + uint32 NextWaveTimer; + uint32 WaveCount; + uint32 CheckTimer; + uint32 Faction; + uint32 EnemyCount; + uint32 RetreatTimer; + + bool EventBegun; + bool FirstBossDead; + bool SecondBossDead; + bool Summon; + bool bRetreat; + bool Debug; + bool VeinsSpawned[2]; + uint8 InfernalCount; + SummonList Summons; + bool Overrun; + bool Teleported; + bool WaitForTeleport; + uint32 TeleportTimer; + uint32 OverrunCounter; + uint32 OverrunCounter2; + uint32 InfernalPoint; + uint32 RespawnTimer; + bool DoRespawn; + bool DoHide; + bool IsDummy; + uint32 MassTeleportTimer; + bool DoMassTeleport; + uint64 DummyGuid; + + struct Spell + { + uint32 SpellId; + uint32 Cooldown; + uint32 TargetType; + }Spell[3]; + + private: + uint32 SpellTimer[3]; + //std::list CreatureList; +}; +#endif + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp new file mode 100644 index 00000000000..c4cf9ede397 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp @@ -0,0 +1,1440 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" +#include "hyjalAI.h" + +#define SPELL_METEOR 33814 //infernal visual +#define SPELL_IMMOLATION 37059 +#define SPELL_FLAME_BUFFET 31724 +#define NPC_TRIGGER 21987 //World Trigger (Tiny) +#define MODEL_INVIS 11686 //invisible model + +float HordeWPs[8][3]=//basic waypoints from spawn to leader +{ + {5492.91, -2404.61, 1462.63}, + {5531.76, -2460.87, 1469.55}, + {5554.58, -2514.66, 1476.12}, + {5554.16, -2567.23, 1479.90}, + {5540.67, -2625.99, 1480.89}, + {5508.16, -2659.20, 1480.15},//random rush starts from here + {5489.62, -2704.05, 1482.18}, + {5457.04, -2726.26, 1485.10} +}; +float AllianceWPs[8][3]=//basic waypoints from spawn to leader +{ + {4896.08, -1576.35, 1333.65}, + {4898.68, -1615.02, 1329.48}, + {4907.12, -1667.08, 1321.00}, + {4963.18, -1699.35, 1340.51}, + {4989.16, -1716.67, 1335.74},//first WP in the base, after the gate + {5026.27, -1736.89, 1323.02}, + {5037.77, -1770.56, 1324.36}, + {5067.23, -1789.95, 1321.17} +}; + +float FrostWyrmWPs[3][3]=//waypoints for the frost wyrms in horde base +{ + {5580.82, -2628.83, 1528.28}, + {5550.90, -2667.16, 1505.45}, + {5459.64, -2725.91, 1484.83} +}; + +float GargoyleWPs[3][3]=//waypoints for the gargoyles in horde base +{ + {5533.66, -2634.32, 1495.33}, + {5517.88, -2712.05, 1490.54}, + {5459.64, -2725.91, 1484.83} +}; + +float FlyPathWPs[3][3]=//waypoints for the gargoyls and frost wyrms in horde base in wave 1/3 +{ + {5531.96, -2772.83, 1516.68}, + {5498.32, -2734.84, 1497.01}, + {5456.67, -2725.48, 1493.08} +}; + +float AllianceOverrunWP[55][3]=//waypoints in the alliance base used in the end in the cleaning wave +{ + {4976.37,-1708.02,1339.43},//0spawn + {4994.83,-1725.52,1333.25},//1 start + {4982.92,-1753.7,1330.69},//2 end + {4996.75,-1721.47,1332.95},//3 start + {5015.74,-1755.05,1322.49},//4 + {4998.68,-1773.44,1329.59},//5 + {4994.83,-1725.52,1333.25},//6 start + {5022.8,-1735.46,1323.53},//7 + {5052.15,-1729.02,1320.88},//8 + {5082.43,-1726.29,1327.87},//9 + {4994.83,-1725.52,1333.25},//10 start + {5018.92,-1751.14,1322.19},//11 + {5040.09,-1792.09,1322.1},//12 + {4994.83,-1725.52,1333.25},//13 start + {5023.47,-1748.1,1322.51},//14 + {5013.43,-1842.39,1322.07},//15 + {4994.83,-1725.52,1333.25},//16 start + {5020.8,-1756.86,1322.2},//17 + {5019.53,-1824.6,1321.96},//18 + {5043.42,-1853.75,1324.52},//19 + {5053.02,-1864.13,1330.36},//20 + {5062.49,-1852.47,1330.49},//21 + {5015.27, -1738.77, 1324.83},//35//start 22 + {5027.97, -1775.25, 1321.87},//34 23 + {5015.94, -1821.24, 1321.86},//33 24 + {4983.25, -1857.4, 1320.48},//32 25 + {4981.51, -1883.7, 1322.34},//31 26 + {5002.33, -1893.98, 1325.88},//30 27 + {5049.32, -1886.54, 1331.69},//29 28 + {5089.68, -1846.88, 1328.99},//28 29 + {5127.90, -1825.14, 1335.58},//27 30 + {5163.27, -1789.08, 1337.04},//26 31 + {5138.97, -1755.88, 1334.57},//25 32 + {5096.63, -1742.22, 1329.61},//24 33 + {5065.81, -1729.43, 1325.66},//23 34 + {5049.32, -1726.31, 1320.64},//22 start + {5081.07, -1902.10, 1346.36},//36 abo start + {5107.65, -1912.03, 1356.49},//37 + {5132.83, -1927.07, 1362.42},//38 + {5147.78, -1954.41, 1365.98},//39 + {5164.96, -1966.48, 1367.04},//40 + {5189.04, -1961.06, 1367.90},//41 + {5212.27, -1975.30, 1365.58},//42 + {5221.82, -1994.18, 1364.97},//43 end1 + {5202.23, -1994.94, 1367.59},//44 end2 + {5279.94, -2049.68, 1311.38},//45 garg1 + {5289.15, -2219.06, 1291.12},//46 garg2 + {5202.07, -2136.10, 1305.07},//47 garg3 + {5071.52, -2425.63, 1454.48},//48 garg4 + {5120.65, -2467.92, 1463.93},//49 garg5 + {5283.04, -2043.26, 1300.11},//50 garg target1 + {5313.22, -2207.60, 1290.06},//51 garg target2 + {5180.41, -2121.87, 1292.62},//52 garg target3 + {5088.68, -2432.04, 1441.73},//53 garg target4 + {5111.26, -2454.73, 1449.63}//54 garg target5 + +}; + +float HordeOverrunWP[21][3]=//waypoints in the horde base used in the end in the cleaning wave +{ + {5490.72,-2702.94,1482.14},//0 start + {5469.77,-2741.34,1486.95}, + {5439.47,-2771.02,1494.59}, + {5408.85,-2811.92,1505.68}, + {5423.87,-2857.80,1515.55}, + {5428.19,-2898.15,1524.61}, + {5394.59,-2930.05,1528.23}, + {5351.11,-2935.80,1532.24}, + {5312.37,-2959.06,1536.21}, + {5264.93,-2989.80,1545.70}, + {5256.63,-3056.16,1559.24}, + {5267.32,-3119.55,1575.36}, + {5305.61,-3139.88,1586.38}, + {5330.56,-3135.37,1588.58}, + {5365.87,-3139.78,1583.96}, + {5389.39,-3163.57,1582.57},//15 end + {5500.86,-2669.89,1481.04},//16 start + {5472.08,-2715.14,1483.55}, + {5450.11,-2721.47,1485.61}, + {5433.25,-2712.93,1493.02},//19 end 1 + {5429.91,-2718.44,1493.42}//20 end 2 +}; + +hyjal_trashAI::hyjal_trashAI(Creature *c) : npc_escortAI(c) +{ + pInstance = c->GetInstanceData(); + IsEvent = false; + Delay = 0; + LastOverronPos = 0; + IsOverrun = false; + OverrunType = 0; + SetupOverrun = false; + faction = 0; + useFlyPath = false; + damageTaken = 0; + Reset(); +} + +void hyjal_trashAI::DamageTaken(Unit *done_by, uint32 &damage) +{ + if (done_by->GetTypeId() == TYPEID_PLAYER || (done_by->GetTypeId() == TYPEID_UNIT && CAST_CRE(done_by)->isPet())) + { + damageTaken += damage; + if (pInstance) + pInstance->SetData(DATA_RAIDDAMAGE,damage);//store raid's damage + } +} + +void hyjal_trashAI::UpdateAI(const uint32 /*diff*/) +{ + if (IsOverrun && !SetupOverrun) + { + SetupOverrun = true; + if (faction == 0) + { + if (me->GetEntry() == GARGOYLE) + { + DummyTarget[0] = AllianceOverrunWP[50+OverrunType][0]; //+OverrunType 0 - 4 + DummyTarget[1] = AllianceOverrunWP[50+OverrunType][1]; + DummyTarget[2] = AllianceOverrunWP[50+OverrunType][2]; + } + if (me->GetEntry() == ABOMINATION) + { + for (uint8 i = 0; i < 4; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); + AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); + AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); + AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); + AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); + AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); + AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); + + AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); + AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); + AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); + AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); + AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); + AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); + AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); + AddWaypoint(18, AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2]); + me->SetHomePosition(AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 18; + Start(true, true); + break; + case 1: + AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); + AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); + AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); + AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); + AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); + AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); + AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); + + AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); + AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); + AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); + AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); + AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); + AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); + AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); + AddWaypoint(18, AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2]); + me->SetHomePosition(AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 18; + Start(true, true); + break; + default: + for (uint8 i = 22; i < 36; ++i) + AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); + + SetDespawnAtEnd(true); + LastOverronPos = 17; + Start(true, true); + break; + } + } + if (me->GetEntry() == GHOUL) + { + for (uint8 i = 0; i < 4; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(4, AllianceOverrunWP[1][0]+irand(-3,3), AllianceOverrunWP[1][1]+irand(-3,3), AllianceOverrunWP[1][2]); + AddWaypoint(5, AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2]); + me->SetHomePosition(AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 5; + Start(true, true); + break; + case 1: + AddWaypoint(4, AllianceOverrunWP[3][0]+irand(-3,3), AllianceOverrunWP[3][1]+irand(-3,3), AllianceOverrunWP[3][2]); + AddWaypoint(5, AllianceOverrunWP[4][0]+irand(-3,3), AllianceOverrunWP[4][1]+irand(-3,3), AllianceOverrunWP[4][2]); + AddWaypoint(6, AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2]); + me->SetHomePosition(AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 2: + AddWaypoint(4, AllianceOverrunWP[6][0]+irand(-3,3), AllianceOverrunWP[6][1]+irand(-3,3), AllianceOverrunWP[6][2]); + AddWaypoint(5, AllianceOverrunWP[7][0]+irand(-3,3), AllianceOverrunWP[7][1]+irand(-3,3), AllianceOverrunWP[7][2]); + AddWaypoint(6, AllianceOverrunWP[8][0]+irand(-3,3), AllianceOverrunWP[8][1]+irand(-3,3), AllianceOverrunWP[8][2]); + AddWaypoint(7, AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2]); + me->SetHomePosition(AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 7; + Start(true, true); + break; + case 3: + AddWaypoint(4, AllianceOverrunWP[10][0]+irand(-3,3), AllianceOverrunWP[10][1]+irand(-3,3), AllianceOverrunWP[10][2]); + AddWaypoint(5, AllianceOverrunWP[11][0]+irand(-3,3), AllianceOverrunWP[11][1]+irand(-3,3), AllianceOverrunWP[11][2]); + AddWaypoint(6, AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2]); + me->SetHomePosition(AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 4: + AddWaypoint(4, AllianceOverrunWP[13][0]+irand(-3,3), AllianceOverrunWP[13][1]+irand(-3,3), AllianceOverrunWP[13][2]); + AddWaypoint(5, AllianceOverrunWP[14][0]+irand(-3,3), AllianceOverrunWP[14][1]+irand(-3,3), AllianceOverrunWP[14][2]); + AddWaypoint(6, AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2]); + me->SetHomePosition(AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 5: + AddWaypoint(4, AllianceOverrunWP[16][0]+irand(-3,3), AllianceOverrunWP[16][1]+irand(-3,3), AllianceOverrunWP[16][2]); + AddWaypoint(5, AllianceOverrunWP[17][0]+irand(-3,3), AllianceOverrunWP[17][1]+irand(-3,3), AllianceOverrunWP[17][2]); + AddWaypoint(6, AllianceOverrunWP[18][0]+irand(-3,3), AllianceOverrunWP[18][1]+irand(-3,3), AllianceOverrunWP[18][2]); + AddWaypoint(7, AllianceOverrunWP[19][0]+irand(-3,3), AllianceOverrunWP[19][1]+irand(-3,3), AllianceOverrunWP[19][2]); + AddWaypoint(8, AllianceOverrunWP[20][0]+irand(-3,3), AllianceOverrunWP[20][1]+irand(-3,3), AllianceOverrunWP[20][2]); + AddWaypoint(9, AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2]); + me->SetHomePosition(AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 9; + Start(true, true); + break; + default: + for (uint8 i = 22; i < 36; ++i) + AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 17; + Start(true, true); + break; + } + } + } + if (faction == 1) + { + if (me->GetEntry() == GHOUL) + { + for (uint8 i = 0; i < 6; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); + AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); + AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); + AddWaypoint(8, HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2]); + me->SetHomePosition(HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 8; + Start(true, true); + break; + case 1: + AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); + AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); + AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); + AddWaypoint(8, HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2]); + me->SetHomePosition(HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 8; + Start(true, true); + break; + default: + for (uint8 i = 0; i < 16; ++i) + AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 21; + Start(true, true); + break; + } + } + if (me->GetEntry() == ABOMINATION) + { + for (uint8 i = 0; i < 6; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-10,10), HordeWPs[i][1]+irand(-10,10), HordeWPs[i][2]); + for (uint8 i = 0; i < 16; ++i) + AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 21; + Start(true, true); + } + } + } +} + +void hyjal_trashAI::JustDied(Unit * /*victim*/) +{ + if (!pInstance) + return; + if (IsEvent && !me->isWorldBoss()) + pInstance->SetData(DATA_TRASH, 0);//signal trash is dead + + if ((pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE && !me->isWorldBoss()) || (damageTaken < me->GetMaxHealth()/4 && me->isWorldBoss())) + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);//no loot +} + +struct mob_giant_infernalAI : public hyjal_trashAI +{ + mob_giant_infernalAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + meteor = false;//call once! + CanMove = false; + Delay = rand()%30000; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(MODEL_INVIS); + pGo = false; + pos = 0; + Reset(); + } + + bool meteor; + bool CanMove; + bool WpEnabled; + bool pGo; + uint32 pos; + uint32 spawnTimer; + uint32 FlameBuffetTimer; + bool imol; + + void Reset() + { + spawnTimer = 2000; + FlameBuffetTimer= 2000; + imol = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 0 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Delay <= diff) + { + Delay=0; + }else{ + Delay-=diff; + return; + } + if (!meteor) + { + float x,y,z; + me->GetPosition(x,y,z); + Creature* trigger = me->SummonCreature(NPC_TRIGGER,x+8,y+8,z+25+rand()%10,me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,1000); + if (trigger) + { + trigger->SetVisibility(VISIBILITY_OFF); + trigger->setFaction(me->getFaction()); + trigger->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + trigger->CastSpell(me,SPELL_METEOR,true); + } + me->GetMotionMaster()->Clear(); + meteor = true; + } else if (!CanMove){ + if (spawnTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); + CanMove = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && !pInstance->GetData(DATA_HORDE_RETREAT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } else if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && pInstance->GetData(DATA_HORDE_RETREAT)){ + //do overrun + } + } + } else spawnTimer -= diff; + } + if (!CanMove)return; + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, HordeWPs[7][0]+irand(-3,3), HordeWPs[7][1]+irand(-3,3), HordeWPs[7][2]);//HordeWPs[7] infront of thrall + Start(true, true); + SetDespawnAtEnd(false); + } + } + } + + if (!UpdateVictim()) + return; + if (!imol) + { + DoCast(me, SPELL_IMMOLATION); + imol=true; + } + if (FlameBuffetTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAME_BUFFET, true); + FlameBuffetTimer = 7000; + } else FlameBuffetTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_giant_infernal(Creature* pCreature) +{ + return new mob_giant_infernalAI(pCreature); +} + +#define SPELL_DISEASE_CLOUD 31607 +#define SPELL_KNOCKDOWN 31610 + +struct mob_abominationAI : public hyjal_trashAI +{ + mob_abominationAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 KnockDownTimer; + uint32 pos; + void Reset() + { + KnockDownTimer = 10000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + if (i == LastOverronPos && IsOverrun) + { + if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) + { + me->setDeathState(DEAD); + me->RemoveCorpse(); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!me->HasAura(SPELL_DISEASE_CLOUD)) + DoCast(me, SPELL_DISEASE_CLOUD); + if (!UpdateVictim()) + return; + if (KnockDownTimer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + KnockDownTimer = 15000+rand()%10000; + } else KnockDownTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_abomination(Creature* pCreature) +{ + return new mob_abominationAI(pCreature); +} + +#define SPELL_FRENZY 31540 + +struct mob_ghoulAI : public hyjal_trashAI +{ + mob_ghoulAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 FrenzyTimer; + uint32 pos; + uint32 MoveTimer; + bool RandomMove; + void Reset() + { + FrenzyTimer = 5000+rand()%5000; + MoveTimer = 2000; + RandomMove = false; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + if (i == LastOverronPos && IsOverrun) + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); + if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) + { + me->setDeathState(DEAD); + me->RemoveCorpse(); + } + + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (FrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + FrenzyTimer = 15000+rand()%15000; + } else FrenzyTimer -= diff; + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_ghoul(Creature* pCreature) +{ + return new mob_ghoulAI(pCreature); +} + +#define SPELL_RAISE_DEAD_1 31617 +#define SPELL_RAISE_DEAD_2 31624 +#define SPELL_RAISE_DEAD_3 31625 +#define SPELL_SHADOW_BOLT 31627 + +struct mob_necromancerAI : public hyjal_trashAI +{ + mob_necromancerAI(Creature* c) : hyjal_trashAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + SummonList summons; + bool pGo; + uint32 ShadowBoltTimer; + uint32 pos; + void Reset() + { + ShadowBoltTimer = 1000+rand()%5000; + summons.DespawnAll(); + } + + void JustSummoned(Creature* summon) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true); + if (pTarget && summon) + summon->Attack(pTarget,false); + summons.Summon(summon); + } + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoSpawnCreature(17902,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + DoSpawnCreature(17902,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + case 1: + DoSpawnCreature(17903,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + DoSpawnCreature(17903,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + case 2: + DoSpawnCreature(RAND(17902,17903),3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(true, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(true, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (ShadowBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + ShadowBoltTimer = 20000+rand()%10000; + } else ShadowBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_necromancer(Creature* pCreature) +{ + return new mob_necromancerAI(pCreature); +} + +#define SPELL_BANSHEE_CURSE 31651 +#define SPELL_BANSHEE_WAIL 38183 +#define SPELL_ANTI_MAGIC_SHELL 31662 + +struct mob_bansheeAI : public hyjal_trashAI +{ + mob_bansheeAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 CourseTimer; + uint32 WailTimer; + uint32 ShellTimer; + uint32 pos; + void Reset() + { + CourseTimer = 20000+rand()%5000; + WailTimer = 15000+rand()%5000; + ShellTimer = 50000+rand()%10000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (CourseTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BANSHEE_CURSE); + CourseTimer = 20000+rand()%5000; + } else CourseTimer -= diff; + if (WailTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BANSHEE_WAIL); + WailTimer = 15000+rand()%5000; + } else WailTimer -= diff; + if (ShellTimer <= diff) + { + DoCast(me, SPELL_ANTI_MAGIC_SHELL); + ShellTimer = 50000+rand()%10000; + } else ShellTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_banshee(Creature* pCreature) +{ + return new mob_bansheeAI(pCreature); +} + +#define SPELL_WEB 28991 + +struct mob_crypt_fiendAI : public hyjal_trashAI +{ + mob_crypt_fiendAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 WebTimer; + uint32 pos; + void Reset() + { + WebTimer = 20000+rand()%5000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + + } + } + } + if (!UpdateVictim()) + return; + if (WebTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WEB); + WebTimer = 20000+rand()%5000; + } else WebTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_crypt_fiend(Creature* pCreature) +{ + return new mob_crypt_fiendAI(pCreature); +} + +#define SPELL_MANA_BURN 31729 + +struct mob_fel_stalkerAI : public hyjal_trashAI +{ + mob_fel_stalkerAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 ManaBurnTimer; + uint32 pos; + void Reset() + { + ManaBurnTimer = 9000+rand()%5000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + + } + } + } + if (!UpdateVictim()) + return; + if (ManaBurnTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MANA_BURN); + ManaBurnTimer = 9000+rand()%5000; + } else ManaBurnTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_fel_stalker(Creature* pCreature) +{ + return new mob_fel_stalkerAI(pCreature); +} + +#define SPELL_FROST_BREATH 31688 + +struct mob_frost_wyrmAI : public hyjal_trashAI +{ + mob_frost_wyrmAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 FrostBreathTimer; + uint32 pos; + uint32 MoveTimer; + + void Reset() + { + FrostBreathTimer = 5000; + MoveTimer = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 2 && pInstance && !IsOverrun) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + { + me->AddThreat(pTarget,0.0); + DoCast(pTarget, SPELL_FROST_BREATH, true); + } + } + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_TRASH, 0);//signal trash is dead + + float x,y,z; + me->GetPosition(x,y,z); + z = me->GetMap()->GetHeight(x, y, z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + me->GetMap()->CreatureRelocation(me, x,y,z,0); + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + { + CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); + npc_escortAI::UpdateAI(diff); + } + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (!useFlyPath) + { + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FrostWyrmWPs[i][0], FrostWyrmWPs[i][1], FrostWyrmWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else{//fly path FlyPathWPs + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (!me->IsWithinDist(me->getVictim(), 25)){ + if (MoveTimer <= diff) + { + me->GetMotionMaster()->MoveChase(me->getVictim()); + MoveTimer = 2000; + } else MoveTimer-=diff; + } + + if (FrostBreathTimer <= diff) + { + if (!me->IsWithinDist(me->getVictim(), 25)) + { + DoCast(me->getVictim(), SPELL_FROST_BREATH); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + FrostBreathTimer = 4000; + } + } else FrostBreathTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_frost_wyrm(Creature* pCreature) +{ + return new mob_frost_wyrmAI(pCreature); +} + +#define SPELL_GARGOYLE_STRIKE 31664 + +struct mob_gargoyleAI : public hyjal_trashAI +{ + mob_gargoyleAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + DummyTarget[0] = 0;DummyTarget[1] = 0;DummyTarget[2] = 0; + Reset(); + } + + bool pGo; + uint32 StrikeTimer; + uint32 pos; + uint32 MoveTimer; + float Zpos; + bool forcemove; + + void Reset() + { + forcemove = true; + Zpos = 10.0; + StrikeTimer = 2000+rand()%5000; + MoveTimer = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 2 && pInstance && !IsOverrun) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + { + me->AddThreat(pTarget,0.0); + DoCast(pTarget, SPELL_GARGOYLE_STRIKE, true); + } + } + } + + void JustDied(Unit *victim) + { + float x,y,z; + me->GetPosition(x,y,z); + z = me->GetMap()->GetHeight(x, y, z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + me->GetMap()->CreatureRelocation(me, x,y,z,0); + hyjal_trashAI::JustDied(victim); + } + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + { + CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); + npc_escortAI::UpdateAI(diff); + } + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (!useFlyPath) + { + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, GargoyleWPs[i][0]+irand(-10,10), GargoyleWPs[i][1]+irand(-10,10), GargoyleWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else{//fly path FlyPathWPs + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (IsOverrun && !UpdateVictim()) + { + if (faction == 0)//alliance + { + if (StrikeTimer <= diff) + { + me->CastSpell(DummyTarget[0],DummyTarget[1],DummyTarget[2],SPELL_GARGOYLE_STRIKE,false); + StrikeTimer = 2000+rand()%1000; + } else StrikeTimer -= diff; + } + } + if (!UpdateVictim()) + return; + if (!me->IsWithinDist(me->getVictim(), 20) || forcemove) + { + forcemove = false; + if (forcemove) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + me->Attack(pTarget,false); + } + if (MoveTimer <= diff) + { + float x,y,z; + me->getVictim()->GetPosition(x,y,z); + me->GetMotionMaster()->MovePoint(0,x,y,z+Zpos); + Zpos-=1.0; + if (Zpos <= 0)Zpos=0; + MoveTimer = 2000; + } else MoveTimer-=diff; + } + if (StrikeTimer <= diff) + { + if (me->IsWithinDist(me->getVictim(), 20)) + { + DoCast(me->getVictim(), SPELL_GARGOYLE_STRIKE); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + StrikeTimer = 2000+rand()%1000; + } else StrikeTimer=0; + } else StrikeTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_gargoyle(Creature* pCreature) +{ + return new mob_gargoyleAI(pCreature); +} + +#define SPELL_EXPLODING_SHOT 7896 + +struct alliance_riflemanAI : public Scripted_NoMovementAI +{ + alliance_riflemanAI(Creature *c) : Scripted_NoMovementAI(c) + { + Reset(); + } + + uint32 ExplodeTimer; + + void JustDied(Unit* /*who*/) + { + } + + void Reset() + { + ExplodeTimer = 5000+rand()%5000; + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && me->IsHostileTo(who)) + { + //float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, 30)) + AttackStart(who); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + if (ExplodeTimer <= diff) + { + if (!me->IsWithinDistInMap(me->getVictim(), 30)) + { + EnterEvadeMode(); + return; + } + int dmg = 500+rand()%700; + me->CastCustomSpell(me->getVictim(), SPELL_EXPLODING_SHOT, &dmg, 0, 0, false); + ExplodeTimer = 5000+rand()%5000; + } else ExplodeTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_alliance_rifleman(Creature* pCreature) +{ + return new alliance_riflemanAI(pCreature); +} + +void AddSC_hyjal_trash() +{ + Script *newscript = new Script; + newscript->Name = "mob_giant_infernal"; + newscript->GetAI = &GetAI_mob_giant_infernal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_abomination"; + newscript->GetAI = &GetAI_mob_abomination; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ghoul"; + newscript->GetAI = &GetAI_mob_ghoul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_necromancer"; + newscript->GetAI = &GetAI_mob_necromancer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_banshee"; + newscript->GetAI = &GetAI_mob_banshee; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crypt_fiend"; + newscript->GetAI = &GetAI_mob_crypt_fiend; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_stalker"; + newscript->GetAI = &GetAI_mob_fel_stalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_wyrm"; + newscript->GetAI = &GetAI_mob_frost_wyrm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_gargoyle"; + newscript->GetAI = &GetAI_mob_gargoyle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "alliance_rifleman"; + newscript->GetAI = &GetAI_alliance_rifleman; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h new file mode 100644 index 00000000000..21ee4bc06cc --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h @@ -0,0 +1,35 @@ + +#ifndef SC_HYJAL_TRASH_AI_H +#define SC_HYJAL_TRASH_AI_H + +#include "hyjal.h" +#include "ScriptedEscortAI.h" + +#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies + +struct hyjal_trashAI : public npc_escortAI +{ + hyjal_trashAI(Creature *c); + + void UpdateAI(const uint32 diff); + + void JustDied(Unit* /*killer*/); + + void DamageTaken(Unit *done_by, uint32 &damage); + + public: + ScriptedInstance* pInstance; + bool IsEvent; + uint32 Delay; + uint32 LastOverronPos; + bool IsOverrun; + bool SetupOverrun; + uint32 OverrunType; + uint8 faction; + bool useFlyPath; + uint32 damageTaken; + float DummyTarget[3]; + + //private: +}; +#endif diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp new file mode 100644 index 00000000000..e89d518c5bc --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp @@ -0,0 +1,324 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Mount_Hyjal +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +enum eEnums +{ + MAX_ENCOUNTER = 5, + + GO_ANCIENT_GEM = 185557 +}; +/* Battle of Mount Hyjal encounters: +0 - Rage Winterchill event +1 - Anetheron event +2 - Kaz'rogal event +3 - Azgalor event +4 - Archimonde event +*/ + +struct instance_mount_hyjal : public ScriptedInstance +{ + instance_mount_hyjal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + std::list m_uiAncientGemGUID; + + uint64 RageWinterchill; + uint64 Anetheron; + uint64 Kazrogal; + uint64 Azgalor; + uint64 Archimonde; + uint64 JainaProudmoore; + uint64 Thrall; + uint64 TyrandeWhisperwind; + uint64 HordeGate; + uint64 ElfGate; + + uint32 Trash; + + uint32 hordeRetreat; + uint32 allianceRetreat; + bool ArchiYell; + + uint32 RaidDamage; + + #define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more." + #define YELL_EFFORTS_NAME "Archimonde" + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiAncientGemGUID.clear(); + + RageWinterchill = 0; + Anetheron = 0; + Kazrogal = 0; + Azgalor = 0; + Archimonde = 0; + JainaProudmoore = 0; + Thrall = 0; + TyrandeWhisperwind = 0; + HordeGate = 0; + ElfGate = 0; + ArchiYell = false; + RaidDamage = 0; + + Trash = 0; + + hordeRetreat = 0; + allianceRetreat = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 182060: + HordeGate = pGo->GetGUID(); + if (allianceRetreat) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + case 182061: + ElfGate = pGo->GetGUID(); + if (hordeRetreat) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + case GO_ANCIENT_GEM: + m_uiAncientGemGUID.push_back(pGo->GetGUID()); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17767: RageWinterchill = pCreature->GetGUID(); break; + case 17808: Anetheron = pCreature->GetGUID(); break; + case 17888: Kazrogal = pCreature->GetGUID(); break; + case 17842: Azgalor = pCreature->GetGUID(); break; + case 17968: Archimonde = pCreature->GetGUID(); break; + case 17772: JainaProudmoore = pCreature->GetGUID(); break; + case 17852: Thrall = pCreature->GetGUID(); break; + case 17948: TyrandeWhisperwind = pCreature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_RAGEWINTERCHILL: return RageWinterchill; + case DATA_ANETHERON: return Anetheron; + case DATA_KAZROGAL: return Kazrogal; + case DATA_AZGALOR: return Azgalor; + case DATA_ARCHIMONDE: return Archimonde; + case DATA_JAINAPROUDMOORE: return JainaProudmoore; + case DATA_THRALL: return Thrall; + case DATA_TYRANDEWHISPERWIND: return TyrandeWhisperwind; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_RAGEWINTERCHILLEVENT: m_auiEncounter[0] = data; break; + case DATA_ANETHERONEVENT: + m_auiEncounter[1] = data; + break; + case DATA_KAZROGALEVENT: m_auiEncounter[2] = data; break; + case DATA_AZGALOREVENT: + { + m_auiEncounter[3] = data; + if (data == DONE) + { + if (ArchiYell)break; + ArchiYell = true; + + Creature* pCreature = instance->GetCreature(Azgalor); + if (pCreature) + { + Creature* pUnit = pCreature->SummonCreature(21987,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,10000); + + Map* pMap = pCreature->GetMap(); + if (pMap->IsDungeon() && pUnit) + { + pUnit->SetVisibility(VISIBILITY_OFF); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()) + { + WorldPacket data(SMSG_MESSAGECHAT, 200); + pUnit->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,YELL_EFFORTS,0,YELL_EFFORTS_NAME,i->getSource()->GetGUID()); + i->getSource()->GetSession()->SendPacket(&data); + + WorldPacket data2(SMSG_PLAY_SOUND, 4); + data2 << 10986; + i->getSource()->GetSession()->SendPacket(&data2); + } + } + } + } + } + } + break; + case DATA_ARCHIMONDEEVENT: m_auiEncounter[4] = data; break; + case DATA_RESET_TRASH_COUNT: Trash = 0; break; + + case DATA_TRASH: + if (data) Trash = data; + else Trash--; + DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash); + break; + case TYPE_RETREAT: + if (data == SPECIAL) + { + if (!m_uiAncientGemGUID.empty()) + { + for (std::list::const_iterator itr = m_uiAncientGemGUID.begin(); itr != m_uiAncientGemGUID.end(); ++itr) + { + //don't know how long it expected + DoRespawnGameObject(*itr,DAY); + } + } + } + break; + case DATA_ALLIANCE_RETREAT: + allianceRetreat = data; + HandleGameObject(HordeGate, true); + SaveToDB(); + break; + case DATA_HORDE_RETREAT: + hordeRetreat = data; + HandleGameObject(ElfGate, true); + SaveToDB(); + break; + case DATA_RAIDDAMAGE: + RaidDamage += data; + if (RaidDamage >= MINRAIDDAMAGE) + RaidDamage = MINRAIDDAMAGE; + break; + case DATA_RESET_RAIDDAMAGE: + RaidDamage = 0; + break; + } + + debug_log("TSCR: Instance Hyjal: Instance data updated for event %u (Data=%u)",type,data); + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] + << " " << allianceRetreat << " " << hordeRetreat + << " " << RaidDamage; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_RAGEWINTERCHILLEVENT: return m_auiEncounter[0]; + case DATA_ANETHERONEVENT: return m_auiEncounter[1]; + case DATA_KAZROGALEVENT: return m_auiEncounter[2]; + case DATA_AZGALOREVENT: return m_auiEncounter[3]; + case DATA_ARCHIMONDEEVENT: return m_auiEncounter[4]; + case DATA_TRASH: return Trash; + case DATA_ALLIANCE_RETREAT: return allianceRetreat; + case DATA_HORDE_RETREAT: return hordeRetreat; + case DATA_RAIDDAMAGE: return RaidDamage; + } + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4] >> allianceRetreat >> hordeRetreat >> RaidDamage; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_mount_hyjal(Map* pMap) +{ + return new instance_mount_hyjal(pMap); +} + +void AddSC_instance_mount_hyjal() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_hyjal"; + newscript->GetInstanceData = &GetInstanceData_instance_mount_hyjal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp new file mode 100644 index 00000000000..91c9e274b83 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Captain_Skarloc +SD%Complete: 75 +SDComment: Missing adds, missing waypoints to move up to Thrall once spawned + speech before enter combat. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define SAY_ENTER -1560000 +#define SAY_TAUNT1 -1560001 +#define SAY_TAUNT2 -1560002 +#define SAY_SLAY1 -1560003 +#define SAY_SLAY2 -1560004 +#define SAY_DEATH -1560005 + +#define SPELL_HOLY_LIGHT 29427 +#define SPELL_CLEANSE 29380 +#define SPELL_HAMMER_OF_JUSTICE 13005 +#define SPELL_HOLY_SHIELD 31904 +#define SPELL_DEVOTION_AURA 8258 +#define SPELL_CONSECRATION 38385 + +struct boss_captain_skarlocAI : public ScriptedAI +{ + boss_captain_skarlocAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Holy_Light_Timer; + uint32 Cleanse_Timer; + uint32 HammerOfJustice_Timer; + uint32 HolyShield_Timer; + uint32 DevotionAura_Timer; + uint32 Consecration_Timer; + + void Reset() + { + Holy_Light_Timer = 20000 + rand()%10000; + Cleanse_Timer = 10000; + HammerOfJustice_Timer = 20000 + rand()%15000; + HolyShield_Timer = 240000; + DevotionAura_Timer = 3000; + Consecration_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + //This is not correct. Should taunt Thrall before engage in combat + DoScriptText(SAY_TAUNT1, me); + DoScriptText(SAY_TAUNT2, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + pInstance->SetData(TYPE_THRALL_PART1, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Holy_Light + if (Holy_Light_Timer <= diff) + { + DoCast(me, SPELL_HOLY_LIGHT); + Holy_Light_Timer = 30000; + } else Holy_Light_Timer -= diff; + + //Cleanse + if (Cleanse_Timer <= diff) + { + DoCast(me, SPELL_CLEANSE); + Cleanse_Timer = 10000; + } else Cleanse_Timer -= diff; + + //Hammer of Justice + if (HammerOfJustice_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); + HammerOfJustice_Timer = 60000; + } else HammerOfJustice_Timer -= diff; + + //Holy Shield + if (HolyShield_Timer <= diff) + { + DoCast(me, SPELL_HOLY_SHIELD); + HolyShield_Timer = 240000; + } else HolyShield_Timer -= diff; + + //Devotion_Aura + if (DevotionAura_Timer <= diff) + { + DoCast(me, SPELL_DEVOTION_AURA); + DevotionAura_Timer = 45000 + rand()%10000; + } else DevotionAura_Timer -= diff; + + //Consecration + if (Consecration_Timer <= diff) + { + //DoCast(me->getVictim(), SPELL_CONSECRATION); + Consecration_Timer = 5000 + rand()%5000; + } else Consecration_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_captain_skarloc(Creature* pCreature) +{ + return new boss_captain_skarlocAI (pCreature); +} + +void AddSC_boss_captain_skarloc() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_captain_skarloc"; + newscript->GetAI = &GetAI_boss_captain_skarloc; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp new file mode 100644 index 00000000000..2c2ad96ddb7 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Epoch_Hunter +SD%Complete: 60 +SDComment: Missing spawns pre-event, missing speech to be coordinated with rest of escort event. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define SAY_ENTER1 -1560013 +#define SAY_ENTER2 -1560014 +#define SAY_ENTER3 -1560015 +#define SAY_AGGRO1 -1560016 +#define SAY_AGGRO2 -1560017 +#define SAY_SLAY1 -1560018 +#define SAY_SLAY2 -1560019 +#define SAY_BREATH1 -1560020 +#define SAY_BREATH2 -1560021 +#define SAY_DEATH -1560022 + +#define SPELL_SAND_BREATH 31914 +#define SPELL_IMPENDING_DEATH 31916 +#define SPELL_MAGIC_DISRUPTION_AURA 33834 +#define SPELL_WING_BUFFET 31475 + +struct boss_epoch_hunterAI : public ScriptedAI +{ + boss_epoch_hunterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SandBreath_Timer; + uint32 ImpendingDeath_Timer; + uint32 WingBuffet_Timer; + uint32 Mda_Timer; + + void Reset() + { + SandBreath_Timer = 8000 + rand()%8000; + ImpendingDeath_Timer = 25000 + rand()%5000; + WingBuffet_Timer = 35000; + Mda_Timer = 40000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2), me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + pInstance->SetData(TYPE_THRALL_PART4, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sand Breath + if (SandBreath_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me->getVictim(), SPELL_SAND_BREATH); + + DoScriptText(RAND(SAY_BREATH1,SAY_BREATH2), me); + + SandBreath_Timer = 10000 + rand()%10000; + } else SandBreath_Timer -= diff; + + if (ImpendingDeath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_IMPENDING_DEATH); + ImpendingDeath_Timer = 25000+rand()%5000; + } else ImpendingDeath_Timer -= diff; + + if (WingBuffet_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_WING_BUFFET); + WingBuffet_Timer = 25000+rand()%10000; + } else WingBuffet_Timer -= diff; + + if (Mda_Timer <= diff) + { + DoCast(me, SPELL_MAGIC_DISRUPTION_AURA); + Mda_Timer = 15000; + } else Mda_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_epoch_hunter(Creature* pCreature) +{ + return new boss_epoch_hunterAI (pCreature); +} + +void AddSC_boss_epoch_hunter() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_epoch_hunter"; + newscript->GetAI = &GetAI_boss_epoch_hunter; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp new file mode 100644 index 00000000000..dae0f5390b1 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp @@ -0,0 +1,190 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Luetenant_Drake +SD%Complete: 70 +SDComment: Missing proper code for patrolling area after being spawned. Script for GO (barrels) quest 10283 +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" +#include "ScriptedEscortAI.h" + +/*###### +## go_barrel_old_hillsbrad +######*/ + +bool GOHello_go_barrel_old_hillsbrad(Player* /*pPlayer*/, GameObject* pGO) +{ + if (ScriptedInstance* pInstance = pGO->GetInstanceData()) + { + if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE) + return false; + + pInstance->SetData(TYPE_BARREL_DIVERSION, IN_PROGRESS); + } + + return false; +} + +/*###### +## boss_lieutenant_drake +######*/ + +#define SAY_ENTER -1560006 +#define SAY_AGGRO -1560007 +#define SAY_SLAY1 -1560008 +#define SAY_SLAY2 -1560009 +#define SAY_MORTAL -1560010 +#define SAY_SHOUT -1560011 +#define SAY_DEATH -1560012 + +#define SPELL_WHIRLWIND 31909 +#define SPELL_HAMSTRING 9080 +#define SPELL_MORTAL_STRIKE 31911 +#define SPELL_FRIGHTENING_SHOUT 33789 + +struct Location +{ + uint32 wpId; + float x; + float y; + float z; +}; + +static Location DrakeWP[]= +{ + {0, 2125.84, 88.2535, 54.8830}, + {1, 2111.01, 93.8022, 52.6356}, + {2, 2106.70, 114.753, 53.1965}, + {3, 2107.76, 138.746, 52.5109}, + {4, 2114.83, 160.142, 52.4738}, + {5, 2125.24, 178.909, 52.7283}, + {6, 2151.02, 208.901, 53.1551}, + {7, 2177.00, 233.069, 52.4409}, + {8, 2190.71, 227.831, 53.2742}, + {9, 2178.14, 214.219, 53.0779}, + {10, 2154.99, 202.795, 52.6446}, + {11, 2132.00, 191.834, 52.5709}, + {12, 2117.59, 166.708, 52.7686}, + {13, 2093.61, 139.441, 52.7616}, + {14, 2086.29, 104.950, 52.9246}, + {15, 2094.23, 81.2788, 52.6946}, + {16, 2108.70, 85.3075, 53.3294}, + {17, 2125.50, 88.9481, 54.7953}, + {18, 2128.20, 70.9763, 64.4221} +}; + +struct boss_lieutenant_drakeAI : public ScriptedAI +{ + boss_lieutenant_drakeAI(Creature *c) : ScriptedAI(c) {} + + bool CanPatrol; + uint32 wpId; + + uint32 Whirlwind_Timer; + uint32 Fear_Timer; + uint32 MortalStrike_Timer; + uint32 ExplodingShout_Timer; + + void Reset() + { + CanPatrol = true; + wpId = 0; + + Whirlwind_Timer = 20000; + Fear_Timer = 30000; + MortalStrike_Timer = 45000; + ExplodingShout_Timer = 25000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + //TODO: make this work + if (CanPatrol && wpId == 0) + { + me->GetMotionMaster()->MovePoint(DrakeWP[0].wpId, DrakeWP[0].x, DrakeWP[0].y, DrakeWP[0].z); + ++wpId; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Whirlwind + if (Whirlwind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + Whirlwind_Timer = 20000+rand()%5000; + } else Whirlwind_Timer -= diff; + + //Fear + if (Fear_Timer <= diff) + { + DoScriptText(SAY_SHOUT, me); + DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); + Fear_Timer = 25000+rand()%10000; + } else Fear_Timer -= diff; + + //Mortal Strike + if (MortalStrike_Timer <= diff) + { + DoScriptText(SAY_MORTAL, me); + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + MortalStrike_Timer = 20000+rand()%10000; + } else MortalStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_lieutenant_drake(Creature* pCreature) +{ + return new boss_lieutenant_drakeAI (pCreature); +} + +void AddSC_boss_lieutenant_drake() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_barrel_old_hillsbrad"; + newscript->pGOHello = &GOHello_go_barrel_old_hillsbrad; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lieutenant_drake"; + newscript->GetAI = &GetAI_boss_lieutenant_drake; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp new file mode 100644 index 00000000000..fa0b7c14595 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp @@ -0,0 +1,238 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Old_Hillsbrad +SD%Complete: 75 +SDComment: If thrall escort fail, all parts will reset. In future, save sub-parts and continue from last known. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define MAX_ENCOUNTER 6 + +#define THRALL_ENTRY 17876 +#define TARETHA_ENTRY 18887 +#define EPOCH_ENTRY 18096 + +#define DRAKE_ENTRY 17848 + +#define QUEST_ENTRY_DIVERSION 10283 +#define LODGE_QUEST_TRIGGER 20155 + +struct instance_old_hillsbrad : public ScriptedInstance +{ + instance_old_hillsbrad(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 mBarrelCount; + uint32 mThrallEventCount; + + uint64 ThrallGUID; + uint64 TarethaGUID; + uint64 EpochGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + mBarrelCount = 0; + mThrallEventCount = 0; + ThrallGUID = 0; + TarethaGUID = 0; + EpochGUID = 0; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Old Hillsbrad: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void UpdateQuestCredit() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->KilledMonsterCredit(LODGE_QUEST_TRIGGER,0); + } + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case THRALL_ENTRY: + ThrallGUID = pCreature->GetGUID(); + break; + case TARETHA_ENTRY: + TarethaGUID = pCreature->GetGUID(); + break; + case EPOCH_ENTRY: + EpochGUID = pCreature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + Player* pPlayer = GetPlayerInMap(); + + if (!pPlayer) + { + debug_log("TSCR: Instance Old Hillsbrad: SetData (Type: %u Data %u) cannot find any player.", type, data); + return; + } + + switch(type) + { + case TYPE_BARREL_DIVERSION: + { + if (data == IN_PROGRESS) + { + if (mBarrelCount >= 5) + return; + + ++mBarrelCount; + DoUpdateWorldState(WORLD_STATE_OH, mBarrelCount); + + debug_log("TSCR: Instance Old Hillsbrad: go_barrel_old_hillsbrad count %u",mBarrelCount); + + m_auiEncounter[0] = IN_PROGRESS; + + if (mBarrelCount == 5) + { + UpdateQuestCredit(); + pPlayer->SummonCreature(DRAKE_ENTRY, 2128.43, 71.01, 64.42, 1.74, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000); + m_auiEncounter[0] = DONE; + } + } + break; + } + case TYPE_THRALL_EVENT: + { + if (data == FAIL) + { + if (mThrallEventCount <= 20) + { + ++mThrallEventCount; + m_auiEncounter[1] = NOT_STARTED; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); + m_auiEncounter[2] = NOT_STARTED; + m_auiEncounter[3] = NOT_STARTED; + m_auiEncounter[4] = NOT_STARTED; + m_auiEncounter[5] = NOT_STARTED; + } + else if (mThrallEventCount > 20) + { + m_auiEncounter[1] = data; + m_auiEncounter[2] = data; + m_auiEncounter[3] = data; + m_auiEncounter[4] = data; + m_auiEncounter[5] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); + } + } + else + m_auiEncounter[1] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall escort event adjusted to data %u.",data); + break; + } + case TYPE_THRALL_PART1: + m_auiEncounter[2] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part I adjusted to data %u.",data); + break; + case TYPE_THRALL_PART2: + m_auiEncounter[3] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part II adjusted to data %u.",data); + break; + case TYPE_THRALL_PART3: + m_auiEncounter[4] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part III adjusted to data %u.",data); + break; + case TYPE_THRALL_PART4: + m_auiEncounter[5] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part IV adjusted to data %u.",data); + break; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_BARREL_DIVERSION: + return m_auiEncounter[0]; + case TYPE_THRALL_EVENT: + return m_auiEncounter[1]; + case TYPE_THRALL_PART1: + return m_auiEncounter[2]; + case TYPE_THRALL_PART2: + return m_auiEncounter[3]; + case TYPE_THRALL_PART3: + return m_auiEncounter[4]; + case TYPE_THRALL_PART4: + return m_auiEncounter[5]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THRALL: + return ThrallGUID; + case DATA_TARETHA: + return TarethaGUID; + case DATA_EPOCH: + return EpochGUID; + } + return 0; + } +}; +InstanceData* GetInstanceData_instance_old_hillsbrad(Map* pMap) +{ + return new instance_old_hillsbrad(pMap); +} + +void AddSC_instance_old_hillsbrad() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_old_hillsbrad"; + newscript->GetInstanceData = &GetInstanceData_instance_old_hillsbrad; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp new file mode 100644 index 00000000000..08c63954db5 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp @@ -0,0 +1,658 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Old_Hillsbrad +SD%Complete: 40 +SDComment: Quest support: 10283, 10284. All friendly NPC's. Thrall waypoints fairly complete, missing many details, but possible to complete escort. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +/* ContentData +npc_erozion +npc_thrall_old_hillsbrad +npc_taretha +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "old_hillsbrad.h" + +#define QUEST_ENTRY_HILLSBRAD 10282 +#define QUEST_ENTRY_DIVERSION 10283 +#define QUEST_ENTRY_ESCAPE 10284 +#define QUEST_ENTRY_RETURN 10285 +#define ITEM_ENTRY_BOMBS 25853 + +#define GOSSIP_HELLO_EROZION1 "I need a pack of Incendiary Bombs." +#define GOSSIP_HELLO_EROZION2 "[PH] Teleport please, i'm tired." + +/*###### +## npc_erozion +######*/ + +bool GossipHello_npc_erozion(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance && pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE && !pPlayer->HasItemCount(ITEM_ENTRY_BOMBS,1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (!pPlayer->GetQuestRewardStatus(QUEST_ENTRY_RETURN) && pPlayer->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(9778, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_erozion(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_ENTRY_BOMBS, 1); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, ITEM_ENTRY_BOMBS, true); + } + pPlayer->SEND_GOSSIP_MENU(9515, pCreature->GetGUID()); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + } + return true; +} + +/*###### +## npc_thrall_old_hillsbrad +######*/ + +//Thrall texts +#define SAY_TH_START_EVENT_PART1 -1560023 +#define SAY_TH_ARMORY -1560024 +#define SAY_TH_SKARLOC_MEET -1560025 +#define SAY_TH_SKARLOC_TAUNT -1560026 +#define SAY_TH_START_EVENT_PART2 -1560027 +#define SAY_TH_MOUNTS_UP -1560028 +#define SAY_TH_CHURCH_END -1560029 +#define SAY_TH_MEET_TARETHA -1560030 +#define SAY_TH_EPOCH_WONDER -1560031 +#define SAY_TH_EPOCH_KILL_TARETHA -1560032 +#define SAY_TH_EVENT_COMPLETE -1560033 + +#define SAY_TH_RANDOM_LOW_HP1 -1560034 +#define SAY_TH_RANDOM_LOW_HP2 -1560035 + +#define SAY_TH_RANDOM_DIE1 -1560036 +#define SAY_TH_RANDOM_DIE2 -1560037 + +#define SAY_TH_RANDOM_AGGRO1 -1560038 +#define SAY_TH_RANDOM_AGGRO2 -1560039 +#define SAY_TH_RANDOM_AGGRO3 -1560040 +#define SAY_TH_RANDOM_AGGRO4 -1560041 + +#define SAY_TH_RANDOM_KILL1 -1560042 +#define SAY_TH_RANDOM_KILL2 -1560043 +#define SAY_TH_RANDOM_KILL3 -1560044 + +#define SAY_TH_LEAVE_COMBAT1 -1560045 +#define SAY_TH_LEAVE_COMBAT2 -1560046 +#define SAY_TH_LEAVE_COMBAT3 -1560047 + +//Taretha texts +#define SAY_TA_FREE -1560048 +#define SAY_TA_ESCAPED -1560049 + +//Misc for Thrall +#define SPELL_STRIKE 14516 +#define SPELL_SHIELD_BLOCK 12169 +#define SPELL_SUMMON_EROZION_IMAGE 33954 //if thrall dies during escort? + +#define SPEED_WALK (0.5f) +#define SPEED_RUN (1.0f) +#define SPEED_MOUNT (1.6f) + +#define THRALL_WEAPON_MODEL 22106 +#define THRALL_WEAPON_INFO 218169346 +#define THRALL_SHIELD_MODEL 18662 +#define THRALL_SHIELD_INFO 234948100 +#define THRALL_MODEL_UNEQUIPPED 17292 +#define THRALL_MODEL_EQUIPPED 18165 + +//Misc Creature entries +#define ENTRY_ARMORER 18764 +#define ENTRY_SCARLOC 17862 + +#define MOB_ENTRY_RIFLE 17820 +#define MOB_ENTRY_WARDEN 17833 +#define MOB_ENTRY_VETERAN 17860 +#define MOB_ENTRY_WATCHMAN 17814 +#define MOB_ENTRY_SENTRY 17815 + +#define MOB_ENTRY_BARN_GUARDSMAN 18092 +#define MOB_ENTRY_BARN_PROTECTOR 18093 +#define MOB_ENTRY_BARN_LOOKOUT 18094 + +#define MOB_ENTRY_CHURCH_GUARDSMAN 23175 +#define MOB_ENTRY_CHURCH_PROTECTOR 23179 +#define MOB_ENTRY_CHURCH_LOOKOUT 23177 + +#define MOB_ENTRY_INN_GUARDSMAN 23176 +#define MOB_ENTRY_INN_PROTECTOR 23180 +#define MOB_ENTRY_INN_LOOKOUT 23178 + +#define SKARLOC_MOUNT 18798 +#define SKARLOC_MOUNT_MODEL 18223 +#define EROZION_ENTRY 18723 +#define ENTRY_EPOCH 18096 + +//gossip items +#define GOSSIP_ID_START 9568 +#define GOSSIP_ID_SKARLOC1 9614 //I'm glad Taretha is alive. We now must find a way to free her... +#define GOSSIP_ITEM_SKARLOC1 "Taretha cannot see you, Thrall." +#define GOSSIP_ID_SKARLOC2 9579 //What do you mean by this? Is Taretha in danger? +#define GOSSIP_ITEM_SKARLOC2 "The situation is rather complicated, Thrall. It would be best for you to head into the mountains now, before more of Blackmoore's men show up. We'll make sure Taretha is safe." +#define GOSSIP_ID_SKARLOC3 9580 + +#define GOSSIP_ID_TARREN 9597 //tarren mill is beyond these trees +#define GOSSIP_ITEM_TARREN "We're ready, Thrall." + +#define GOSSIP_ID_COMPLETE 9578 //Thank you friends, I owe my freedom to you. Where is Taretha? I hoped to see her + +#define GOSSIP_ITEM_WALKING "[PH] Start walking." + +struct npc_thrall_old_hillsbradAI : public npc_escortAI +{ + npc_thrall_old_hillsbradAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + HadMount = false; + me->setActive(true); + } + + ScriptedInstance *pInstance; + + uint64 TarethaGUID; + + bool LowHp; + bool HadMount; + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch(i) + { + case 8: + SetRun(false); + me->SummonCreature(18764,2181.87,112.46,89.45,0.26,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 9: + DoScriptText(SAY_TH_ARMORY, me); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_MODEL); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_MODEL); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); + break; + case 10: + me->SetDisplayId(THRALL_MODEL_EQUIPPED); + break; + case 11: + SetRun(); + break; + case 15: + me->SummonCreature(MOB_ENTRY_RIFLE,2200.28,137.37,87.93,5.07,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2197.44,131.83,87.93,0.78,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2203.62,135.40,87.93,3.70,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2200.75,130.13,87.93,1.48,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 21: + me->SummonCreature(MOB_ENTRY_RIFLE,2135.80,154.01,67.45,4.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2144.36,151.87,67.74,4.46,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2142.12,154.41,67.12,4.56,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2138.08,155.38,67.24,4.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 25: + me->SummonCreature(MOB_ENTRY_RIFLE,2102.98,192.17,65.24,6.02,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2108.48,198.75,65.18,5.15,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2106.11,197.29,65.18,5.63,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2104.18,194.82,65.18,5.75,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 29: + DoScriptText(SAY_TH_SKARLOC_MEET, me); + me->SummonCreature(ENTRY_SCARLOC,2036.48,271.22,63.43,5.27,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + //temporary,skarloc should rather be triggered to walk up to thrall + break; + case 30: + SetEscortPaused(true); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetRun(false); + break; + case 31: + DoScriptText(SAY_TH_MOUNTS_UP, me); + DoMount(); + SetRun(); + break; + case 37: + //possibly regular patrollers? If so, remove this and let database handle them + me->SummonCreature(MOB_ENTRY_WATCHMAN,2124.26,522.16,56.87,3.99,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WATCHMAN,2121.69,525.37,57.11,4.01,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_SENTRY,2124.65,524.55,56.63,3.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 59: + me->SummonCreature(SKARLOC_MOUNT,2488.64,625.77,58.26,4.71,TEMPSUMMON_TIMED_DESPAWN,10000); + DoUnmount(); + HadMount = false; + SetRun(false); + break; + case 60: + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + //make horsie run off + SetEscortPaused(true); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(TYPE_THRALL_PART2, DONE); + SetRun(); + break; + case 64: + SetRun(false); + break; + case 68: + me->SummonCreature(MOB_ENTRY_BARN_PROTECTOR,2500.22,692.60,55.50,2.84,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_LOOKOUT,2500.13,696.55,55.51,3.38,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.55,693.64,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.94,695.81,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 71: + SetRun(); + break; + case 81: + SetRun(false); + break; + case 83: + me->SummonCreature(MOB_ENTRY_CHURCH_PROTECTOR,2627.33,646.82,56.03,4.28,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_LOOKOUT,2624.14,648.03,56.03,4.50,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2625.32,649.60,56.03,4.38,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2627.22,649.00,56.03,4.34,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + break; + case 84: + DoScriptText(SAY_TH_CHURCH_END, me); + SetRun(); + break; + case 91: + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + SetRun(false); + break; + case 93: + me->SummonCreature(MOB_ENTRY_INN_PROTECTOR,2652.71,660.31,61.93,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_LOOKOUT,2648.96,662.59,61.93,0.79,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2657.36,662.34,61.93,2.68,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2656.39,659.77,61.93,2.61,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 94: + if (uint64 TarethaGUID = pInstance->GetData64(DATA_TARETHA)) + { + if (Unit* Taretha = Unit::GetUnit((*me), TarethaGUID)) + DoScriptText(SAY_TA_ESCAPED, Taretha, me); + } + break; + case 95: + DoScriptText(SAY_TH_MEET_TARETHA, me); + pInstance->SetData(TYPE_THRALL_PART3,DONE); + SetEscortPaused(true); + break; + case 96: + DoScriptText(SAY_TH_EPOCH_WONDER, me); + break; + case 97: + DoScriptText(SAY_TH_EPOCH_KILL_TARETHA, me); + SetRun(); + break; + case 98: + //trigger epoch Yell("Thrall! Come outside and face your fate! ....") + //from here, thrall should not never be allowed to move to point 106 which he currently does. + break; + + case 106: + { + //trigger taretha to run down outside + if (Creature* Taretha = pInstance->instance->GetCreature(pInstance->GetData64(DATA_TARETHA))) + { + if (Player* pPlayer = GetPlayerForEscort()) + CAST_AI(npc_escortAI, (Taretha->AI()))->Start(false, true, pPlayer->GetGUID()); + } + + //kill credit Creature for quest + Map* pMap = me->GetMap(); + Map::PlayerList const& players = pMap->GetPlayers(); + if (!players.isEmpty() && pMap->IsDungeon()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->KilledMonsterCredit(20156,me->GetGUID()); + } + } + + //alot will happen here, thrall and taretha talk, erozion appear at spot to explain + me->SummonCreature(EROZION_ENTRY,2646.47,680.416,55.38,4.16,TEMPSUMMON_TIMED_DESPAWN,120000); + } + break; + case 108: + //last waypoint, just set Thrall invisible, respawn is turned off + me->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void Reset() + { + LowHp = false; + + if (HadMount) + DoMount(); + + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + DoUnmount(); + HadMount = false; + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + me->SetDisplayId(THRALL_MODEL_UNEQUIPPED); + } + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + DoScriptText(RAND(SAY_TH_LEAVE_COMBAT1,SAY_TH_LEAVE_COMBAT2,SAY_TH_LEAVE_COMBAT3), me); + } + } + void StartWP() + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetEscortPaused(false); + } + void DoMount() + { + me->Mount(SKARLOC_MOUNT_MODEL); + me->SetSpeed(MOVE_RUN,SPEED_MOUNT); + } + void DoUnmount() + { + me->Unmount(); + me->SetSpeed(MOVE_RUN,SPEED_RUN); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(RAND(SAY_TH_RANDOM_AGGRO1,SAY_TH_RANDOM_AGGRO2,SAY_TH_RANDOM_AGGRO3,SAY_TH_RANDOM_AGGRO4), me); + if (me->IsMounted()) + { + DoUnmount(); + HadMount = true; + } + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + //TODO: make Scarloc start into event instead, and not start attack directly + case MOB_ENTRY_BARN_GUARDSMAN: + case MOB_ENTRY_BARN_PROTECTOR: + case MOB_ENTRY_BARN_LOOKOUT: + case SKARLOC_MOUNT: + case EROZION_ENTRY: + break; + default: + summoned->AI()->AttackStart(me); + break; + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_TH_RANDOM_KILL1,SAY_TH_RANDOM_KILL2,SAY_TH_RANDOM_KILL3), me); + } + void JustDied(Unit *slayer) + { + if (pInstance) + pInstance->SetData(TYPE_THRALL_EVENT,FAIL); + + // Don't do a yell if he kills self (if player goes too far or at the end). + if (slayer == me) + return; + + DoScriptText(RAND(SAY_TH_RANDOM_DIE1,SAY_TH_RANDOM_DIE2), me); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + //TODO: add his abilities'n-crap here + if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) + { + DoScriptText(RAND(SAY_TH_RANDOM_LOW_HP1,SAY_TH_RANDOM_LOW_HP2), me); + LowHp = true; + } + } +}; + +CreatureAI* GetAI_npc_thrall_old_hillsbrad(Creature* pCreature) +{ + return new npc_thrall_old_hillsbradAI(pCreature); +} + +bool GossipHello_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + { + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + pPlayer->SendPreparedQuest(pCreature->GetGUID()); + } + + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance) + { + if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE && !pInstance->GetData(TYPE_THRALL_EVENT)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WALKING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START, pCreature->GetGUID()); + } + + if (pInstance->GetData(TYPE_THRALL_PART1) == DONE && !pInstance->GetData(TYPE_THRALL_PART2)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC1, pCreature->GetGUID()); + } + + if (pInstance->GetData(TYPE_THRALL_PART2) == DONE && !pInstance->GetData(TYPE_THRALL_PART3)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TARREN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_TARREN, pCreature->GetGUID()); + } + } + return true; +} + +bool GossipSelect_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pInstance) + { + pInstance->SetData(TYPE_THRALL_EVENT,IN_PROGRESS); + pInstance->SetData(TYPE_THRALL_PART1,IN_PROGRESS); + } + + DoScriptText(SAY_TH_START_EVENT_PART1, pCreature); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())) + pEscortAI->Start(true, true, pPlayer->GetGUID()); + + CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(100.0f);//not really needed, because it will not despawn if player is too far + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); + break; + + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC2, pCreature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+20: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC3, pCreature->GetGUID()); + pCreature->SummonCreature(SKARLOC_MOUNT,2038.81,270.26,63.20,5.41,TEMPSUMMON_TIMED_DESPAWN,12000); + if (pInstance) + pInstance->SetData(TYPE_THRALL_PART2,IN_PROGRESS); + + DoScriptText(SAY_TH_START_EVENT_PART2, pCreature); + + CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); + break; + + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pInstance) + pInstance->SetData(TYPE_THRALL_PART3,IN_PROGRESS); + CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); + break; + } + return true; +} + +/*###### +## npc_taretha +######*/ + +#define GOSSIP_ID_EPOCH1 9610 //Thank you for helping Thrall escape, friends. Now I only hope +#define GOSSIP_ITEM_EPOCH1 "Strange wizard?" +#define GOSSIP_ID_EPOCH2 9613 //Yes, friends. This man was no wizard of +#define GOSSIP_ITEM_EPOCH2 "We'll get you out. Taretha. Don't worry. I doubt the wizard would wander too far away." + +struct npc_tarethaAI : public npc_escortAI +{ + npc_tarethaAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void WaypointReached(uint32 i) + { + switch(i) + { + case 6: + DoScriptText(SAY_TA_FREE, me); + break; + case 7: + me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); + break; + } + } + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_taretha(Creature* pCreature) +{ + return new npc_tarethaAI(pCreature); +} + +bool GossipHello_npc_taretha(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance && pInstance->GetData(TYPE_THRALL_PART3) == DONE && pInstance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH1, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_taretha(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH2, pCreature->GetGUID()); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + { + pInstance->SetData(TYPE_THRALL_PART4,IN_PROGRESS); + if (pInstance->GetData64(DATA_EPOCH) == 0) + pCreature->SummonCreature(ENTRY_EPOCH,2639.13,698.55,65.43,4.59,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); + + if (uint64 ThrallGUID = pInstance->GetData64(DATA_THRALL)) + { + Creature* Thrall = (Unit::GetCreature((*pCreature), ThrallGUID)); + if (Thrall) + CAST_AI(npc_thrall_old_hillsbradAI, Thrall->AI())->StartWP(); + } + } + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_old_hillsbrad() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_erozion"; + newscript->pGossipHello = &GossipHello_npc_erozion; + newscript->pGossipSelect = &GossipSelect_npc_erozion; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thrall_old_hillsbrad"; + newscript->pGossipHello = &GossipHello_npc_thrall_old_hillsbrad; + newscript->pGossipSelect = &GossipSelect_npc_thrall_old_hillsbrad; + newscript->GetAI = &GetAI_npc_thrall_old_hillsbrad; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_taretha"; + newscript->pGossipHello = &GossipHello_npc_taretha; + newscript->pGossipSelect = &GossipSelect_npc_taretha; + newscript->GetAI = &GetAI_npc_taretha; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h new file mode 100644 index 00000000000..5c398cc2647 --- /dev/null +++ b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_OLD_HILLSBRAD_H +#define DEF_OLD_HILLSBRAD_H + +#define TYPE_BARREL_DIVERSION 1 +#define TYPE_THRALL_EVENT 2 +#define TYPE_THRALL_PART1 3 +#define TYPE_THRALL_PART2 4 +#define TYPE_THRALL_PART3 5 +#define TYPE_THRALL_PART4 6 +#define DATA_THRALL 7 +#define DATA_TARETHA 8 +#define DATA_EPOCH 9 +#define WORLD_STATE_OH 2436 +#endif + diff --git a/src/server/scripts/Kalimdor/darkshore.cpp b/src/server/scripts/Kalimdor/darkshore.cpp new file mode 100644 index 00000000000..26b42a86422 --- /dev/null +++ b/src/server/scripts/Kalimdor/darkshore.cpp @@ -0,0 +1,398 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Darkshore +SD%Complete: 100 +SDComment: Quest support: 731, 2078, 5321 +SDCategory: Darkshore +EndScriptData */ + +/* ContentData +npc_kerlonian +npc_prospector_remtravel +npc_threshwackonator +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "ScriptedFollowerAI.h" + +/*#### +# npc_kerlonian +####*/ + +enum eKerlonian +{ + SAY_KER_START = -1000434, + + EMOTE_KER_SLEEP_1 = -1000435, + EMOTE_KER_SLEEP_2 = -1000436, + EMOTE_KER_SLEEP_3 = -1000437, + + SAY_KER_SLEEP_1 = -1000438, + SAY_KER_SLEEP_2 = -1000439, + SAY_KER_SLEEP_3 = -1000440, + SAY_KER_SLEEP_4 = -1000441, + + EMOTE_KER_AWAKEN = -1000445, + + SAY_KER_ALERT_1 = -1000442, + SAY_KER_ALERT_2 = -1000443, + + SAY_KER_END = -1000444, + + SPELL_SLEEP_VISUAL = 25148, + SPELL_AWAKEN = 17536, + QUEST_SLEEPER_AWAKENED = 5321, + NPC_LILADRIS = 11219, //attackers entries unknown + FACTION_KER_ESCORTEE = 113 +}; + +//TODO: make concept similar as "ringo" -escort. Find a way to run the scripted attacks, _if_ player are choosing road. +struct npc_kerlonianAI : public FollowerAI +{ + npc_kerlonianAI(Creature* pCreature) : FollowerAI(pCreature) { } + + uint32 m_uiFallAsleepTimer; + + void Reset() + { + m_uiFallAsleepTimer = urand(10000, 45000); + } + + void MoveInLineOfSight(Unit *pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_LILADRIS) + { + if (me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE*5)) + { + if (Player* pPlayer = GetLeaderForFollower()) + { + if (pPlayer->GetQuestStatus(QUEST_SLEEPER_AWAKENED) == QUEST_STATUS_INCOMPLETE) + pPlayer->GroupEventHappens(QUEST_SLEEPER_AWAKENED, me); + + DoScriptText(SAY_KER_END, me); + } + + SetFollowComplete(); + } + } + } + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + if (HasFollowState(STATE_FOLLOW_INPROGRESS | STATE_FOLLOW_PAUSED) && pSpell->Id == SPELL_AWAKEN) + ClearSleeping(); + } + + void SetSleeping() + { + SetFollowPaused(true); + + DoScriptText(RAND(EMOTE_KER_SLEEP_1,EMOTE_KER_SLEEP_2,EMOTE_KER_SLEEP_3), me); + + DoScriptText(RAND(SAY_KER_SLEEP_1,SAY_KER_SLEEP_2,SAY_KER_SLEEP_3,SAY_KER_SLEEP_4), me); + + me->SetStandState(UNIT_STAND_STATE_SLEEP); + DoCast(me, SPELL_SLEEP_VISUAL, false); + } + + void ClearSleeping() + { + me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL); + me->SetStandState(UNIT_STAND_STATE_STAND); + + DoScriptText(EMOTE_KER_AWAKEN, me); + + SetFollowPaused(false); + } + + void UpdateFollowerAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + { + if (!HasFollowState(STATE_FOLLOW_INPROGRESS)) + return; + + if (!HasFollowState(STATE_FOLLOW_PAUSED)) + { + if (m_uiFallAsleepTimer <= uiDiff) + { + SetSleeping(); + m_uiFallAsleepTimer = urand(25000, 90000); + } + else + m_uiFallAsleepTimer -= uiDiff; + } + + return; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_kerlonian(Creature* pCreature) +{ + return new npc_kerlonianAI(pCreature); +} + +bool QuestAccept_npc_kerlonian(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_SLEEPER_AWAKENED) + { + if (npc_kerlonianAI* pKerlonianAI = CAST_AI(npc_kerlonianAI, pCreature->AI())) + { + pCreature->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_KER_START, pCreature, pPlayer); + pKerlonianAI->StartFollow(pPlayer, FACTION_KER_ESCORTEE, pQuest); + } + } + + return true; +} + +/*#### +# npc_prospector_remtravel +####*/ + +enum eRemtravel +{ + SAY_REM_START = -1000327, + SAY_REM_AGGRO = -1000328, + SAY_REM_RAMP1_1 = -1000329, + SAY_REM_RAMP1_2 = -1000330, + SAY_REM_BOOK = -1000331, + SAY_REM_TENT1_1 = -1000332, + SAY_REM_TENT1_2 = -1000333, + SAY_REM_MOSS = -1000334, + EMOTE_REM_MOSS = -1000335, + SAY_REM_MOSS_PROGRESS = -1000336, + SAY_REM_PROGRESS = -1000337, + SAY_REM_REMEMBER = -1000338, + EMOTE_REM_END = -1000339, + + FACTION_ESCORTEE = 10, + QUEST_ABSENT_MINDED_PT2 = 731, + NPC_GRAVEL_SCOUT = 2158, + NPC_GRAVEL_BONE = 2159, + NPC_GRAVEL_GEO = 2160 +}; + +struct npc_prospector_remtravelAI : public npc_escortAI +{ + npc_prospector_remtravelAI(Creature* pCreature) : npc_escortAI(pCreature) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 0: + DoScriptText(SAY_REM_START, me, pPlayer); + break; + case 5: + DoScriptText(SAY_REM_RAMP1_1, me, pPlayer); + break; + case 6: + DoSpawnCreature(NPC_GRAVEL_SCOUT, -10.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + DoSpawnCreature(NPC_GRAVEL_BONE, -10.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 9: + DoScriptText(SAY_REM_RAMP1_2, me, pPlayer); + break; + case 14: + //depend quest rewarded? + DoScriptText(SAY_REM_BOOK, me, pPlayer); + break; + case 15: + DoScriptText(SAY_REM_TENT1_1, me, pPlayer); + break; + case 16: + DoSpawnCreature(NPC_GRAVEL_SCOUT, -10.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + DoSpawnCreature(NPC_GRAVEL_BONE, -10.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 17: + DoScriptText(SAY_REM_TENT1_2, me, pPlayer); + break; + case 26: + DoScriptText(SAY_REM_MOSS, me, pPlayer); + break; + case 27: + DoScriptText(EMOTE_REM_MOSS, me, pPlayer); + break; + case 28: + DoScriptText(SAY_REM_MOSS_PROGRESS, me, pPlayer); + break; + case 29: + DoSpawnCreature(NPC_GRAVEL_SCOUT, -15.0f, 3.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + DoSpawnCreature(NPC_GRAVEL_BONE, -15.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + DoSpawnCreature(NPC_GRAVEL_GEO, -15.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 31: + DoScriptText(SAY_REM_PROGRESS, me, pPlayer); + break; + case 41: + DoScriptText(SAY_REM_REMEMBER, me, pPlayer); + break; + case 42: + DoScriptText(EMOTE_REM_END, me, pPlayer); + pPlayer->GroupEventHappens(QUEST_ABSENT_MINDED_PT2, me); + break; + } + } + + void Reset() {} + + void EnterCombat(Unit* who) + { + if (rand()%2) + DoScriptText(SAY_REM_AGGRO, me, who); + } + + void JustSummoned(Creature* /*pSummoned*/) + { + //unsure if it should be any + //pSummoned->AI()->AttackStart(me); + } +}; + +CreatureAI* GetAI_npc_prospector_remtravel(Creature* pCreature) +{ + return new npc_prospector_remtravelAI(pCreature); +} + +bool QuestAccept_npc_prospector_remtravel(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_ABSENT_MINDED_PT2) + { + if (npc_escortAI* pEscortAI = CAST_AI(npc_prospector_remtravelAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID()); + + pCreature->setFaction(FACTION_ESCORTEE); + } + + return true; +} + +/*#### +# npc_threshwackonator +####*/ + +enum eThreshwackonator +{ + EMOTE_START = -1000413, //signed for 4966 + SAY_AT_CLOSE = -1000414, //signed for 4966 + QUEST_GYROMAST_REV = 2078, + NPC_GELKAK = 6667, + FACTION_HOSTILE = 14 +}; + +#define GOSSIP_ITEM_INSERT_KEY "[PH] Insert key" + +struct npc_threshwackonatorAI : public FollowerAI +{ + npc_threshwackonatorAI(Creature* pCreature) : FollowerAI(pCreature) { } + + void Reset() { } + + void MoveInLineOfSight(Unit* pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_GELKAK) + { + if (me->IsWithinDistInMap(pWho, 10.0f)) + { + DoScriptText(SAY_AT_CLOSE, pWho); + DoAtEnd(); + } + } + } + + void DoAtEnd() + { + me->setFaction(FACTION_HOSTILE); + + if (Player* pHolder = GetLeaderForFollower()) + me->AI()->AttackStart(pHolder); + + SetFollowComplete(); + } +}; + +CreatureAI* GetAI_npc_threshwackonator(Creature* pCreature) +{ + return new npc_threshwackonatorAI(pCreature); +} + +bool GossipHello_npc_threshwackonator(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_GYROMAST_REV) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_INSERT_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_threshwackonator(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + if (npc_threshwackonatorAI* pThreshAI = CAST_AI(npc_threshwackonatorAI, pCreature->AI())) + { + DoScriptText(EMOTE_START, pCreature); + pThreshAI->StartFollow(pPlayer); + } + } + + return true; +} + +void AddSC_darkshore() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_kerlonian"; + newscript->GetAI = &GetAI_npc_kerlonian; + newscript->pQuestAccept = &QuestAccept_npc_kerlonian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_prospector_remtravel"; + newscript->GetAI = &GetAI_npc_prospector_remtravel; + newscript->pQuestAccept = &QuestAccept_npc_prospector_remtravel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_threshwackonator"; + newscript->GetAI = &GetAI_npc_threshwackonator; + newscript->pGossipHello = &GossipHello_npc_threshwackonator; + newscript->pGossipSelect = &GossipSelect_npc_threshwackonator; + newscript->pGossipSelect = &GossipSelect_npc_threshwackonator; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/desolace.cpp b/src/server/scripts/Kalimdor/desolace.cpp new file mode 100644 index 00000000000..6b3ec8071dd --- /dev/null +++ b/src/server/scripts/Kalimdor/desolace.cpp @@ -0,0 +1,259 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Desolace +SD%Complete: 100 +SDComment: Quest support: 5561 +SDCategory: Desolace +EndScriptData */ + +/* ContentData +npc_aged_dying_ancient_kodo +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +enum eDyingKodo +{ + // signed for 9999 + SAY_SMEED_HOME_1 = -1000348, + SAY_SMEED_HOME_2 = -1000349, + SAY_SMEED_HOME_3 = -1000350, + + QUEST_KODO = 5561, + + NPC_SMEED = 11596, + NPC_AGED_KODO = 4700, + NPC_DYING_KODO = 4701, + NPC_ANCIENT_KODO = 4702, + NPC_TAMED_KODO = 11627, + + SPELL_KODO_KOMBO_ITEM = 18153, + SPELL_KODO_KOMBO_PLAYER_BUFF = 18172, //spells here have unclear function, but using them at least for visual parts and checks + SPELL_KODO_KOMBO_DESPAWN_BUFF = 18377, + SPELL_KODO_KOMBO_GOSSIP = 18362 + +}; + +struct npc_aged_dying_ancient_kodoAI : public ScriptedAI +{ + npc_aged_dying_ancient_kodoAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + + uint32 m_uiDespawnTimer; + + void Reset() + { + m_uiDespawnTimer = 0; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (pWho->GetEntry() == NPC_SMEED) + { + if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) + return; + + if (me->IsWithinDistInMap(pWho, 10.0f)) + { + DoScriptText(RAND(SAY_SMEED_HOME_1,SAY_SMEED_HOME_2,SAY_SMEED_HOME_3), pWho); + + //spell have no implemented effect (dummy), so useful to notify spellHit + DoCast(me, SPELL_KODO_KOMBO_GOSSIP, true); + } + } + } + + void SpellHit(Unit* /*pCaster*/, SpellEntry const* pSpell) + { + if (pSpell->Id == SPELL_KODO_KOMBO_GOSSIP) + { + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_uiDespawnTimer = 60000; + } + } + + void UpdateAI(const uint32 diff) + { + //timer should always be == 0 unless we already updated entry of creature. Then not expect this updated to ever be in combat. + if (m_uiDespawnTimer && m_uiDespawnTimer <= diff) + { + if (!me->getVictim() && me->isAlive()) + { + Reset(); + me->setDeathState(JUST_DIED); + me->Respawn(); + return; + } + } else m_uiDespawnTimer -= diff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_aged_dying_ancient_kodo(Creature* pCreature) +{ + return new npc_aged_dying_ancient_kodoAI(pCreature); +} + +bool EffectDummyCreature_npc_aged_dying_ancient_kodo(Unit *pCaster, uint32 spellId, uint32 effIndex, Creature *pCreatureTarget) +{ + //always check spellid and effectindex + if (spellId == SPELL_KODO_KOMBO_ITEM && effIndex == 0) + { + //no effect if player/creature already have aura from spells + if (pCaster->HasAura(SPELL_KODO_KOMBO_PLAYER_BUFF) || pCreatureTarget->HasAura(SPELL_KODO_KOMBO_DESPAWN_BUFF)) + return true; + + if (pCreatureTarget->GetEntry() == NPC_AGED_KODO || + pCreatureTarget->GetEntry() == NPC_DYING_KODO || + pCreatureTarget->GetEntry() == NPC_ANCIENT_KODO) + { + pCaster->CastSpell(pCaster,SPELL_KODO_KOMBO_PLAYER_BUFF,true); + + pCreatureTarget->UpdateEntry(NPC_TAMED_KODO); + pCreatureTarget->CastSpell(pCreatureTarget,SPELL_KODO_KOMBO_DESPAWN_BUFF,false); + + if (pCreatureTarget->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + pCreatureTarget->GetMotionMaster()->MoveIdle(); + + pCreatureTarget->GetMotionMaster()->MoveFollow(pCaster, PET_FOLLOW_DIST, pCreatureTarget->GetFollowAngle()); + } + + //always return true when we are handling this spell and effect + return true; + } + return false; +} + +bool GossipHello_npc_aged_dying_ancient_kodo(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->HasAura(SPELL_KODO_KOMBO_PLAYER_BUFF) && pCreature->HasAura(SPELL_KODO_KOMBO_DESPAWN_BUFF)) + { + //the expected quest objective + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + + pPlayer->RemoveAurasDueToSpell(SPELL_KODO_KOMBO_PLAYER_BUFF); + pCreature->GetMotionMaster()->MoveIdle(); + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +/*###### +## go_iruxos. Quest 5381 +######*/ + +bool GOHello_go_iruxos(Player *pPlayer, GameObject* /*pGO*/) +{ + if (pPlayer->GetQuestStatus(5381) == QUEST_STATUS_INCOMPLETE) + pPlayer->SummonCreature(11876, pPlayer->GetInnPosX(),pPlayer->GetInnPosY(),pPlayer->GetInnPosZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + + return true; +} + +/*###### +## npc_dalinda_malem. Quest 1440 +######*/ + +#define QUEST_RETURN_TO_VAHLARRIEL 1440 + +struct npc_dalindaAI : public npc_escortAI +{ + npc_dalindaAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + switch (i) + { + case 1: + me->IsStandState(); + break; + case 15: + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_RETURN_TO_VAHLARRIEL, me); + break; + } + } + + void EnterCombat(Unit* /*pWho*/) { } + + void Reset() {} + + void JustDied(Unit* /*pKiller*/) + { + Player* pPlayer = GetPlayerForEscort(); + if (pPlayer) + pPlayer->FailQuest(QUEST_RETURN_TO_VAHLARRIEL); + return; + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + if (!UpdateVictim()) + return; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_dalinda(Creature* pCreature) +{ + return new npc_dalindaAI(pCreature); +} + +bool QuestAccept_npc_dalinda(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_RETURN_TO_VAHLARRIEL) + { + if (npc_escortAI* pEscortAI = CAST_AI(npc_dalindaAI, pCreature->AI())) + { + pEscortAI->Start(true, false, pPlayer->GetGUID()); + pCreature->setFaction(113); + } + } + return true; +} + +void AddSC_desolace() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_aged_dying_ancient_kodo"; + newscript->GetAI = &GetAI_npc_aged_dying_ancient_kodo; + newscript->pEffectDummyCreature = &EffectDummyCreature_npc_aged_dying_ancient_kodo; + newscript->pGossipHello = &GossipHello_npc_aged_dying_ancient_kodo; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_iruxos"; + newscript->pGOHello = &GOHello_go_iruxos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dalinda"; + newscript->GetAI = &GetAI_npc_dalinda; + newscript->pQuestAccept = &QuestAccept_npc_dalinda; + newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Kalimdor/durotar.cpp b/src/server/scripts/Kalimdor/durotar.cpp new file mode 100644 index 00000000000..9ca6074cad3 --- /dev/null +++ b/src/server/scripts/Kalimdor/durotar.cpp @@ -0,0 +1,103 @@ +/* Copyright (C) 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +#include "ScriptedPch.h" + +/*###### +##Quest 5441: Lazy Peons +##npc_lazy_peon +######*/ + +enum LazyPeonYells +{ + SAY_SPELL_HIT = -1999900 //Ow! OK, I''ll get back to work, $N!' +}; + +enum LazyPeon +{ + QUEST_LAZY_PEONS = 5441, + GO_LUMBERPILE = 175784, + SPELL_BUFF_SLEEP = 17743, + SPELL_AWAKEN_PEON = 19938 +}; + +struct npc_lazy_peonAI : public ScriptedAI +{ + npc_lazy_peonAI(Creature *c) : ScriptedAI(c) {} + + uint64 uiPlayerGUID; + + uint32 m_uiRebuffTimer; + bool work; + + void Reset () + { + uiPlayerGUID = 0; + work = false; + } + + void MovementInform(uint32 /*type*/, uint32 id) + { + if (id == 1) + work = true; + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_AWAKEN_PEON && caster->GetTypeId() == TYPEID_PLAYER + && CAST_PLR(caster)->GetQuestStatus(QUEST_LAZY_PEONS) == QUEST_STATUS_INCOMPLETE) + { + caster->ToPlayer()->KilledMonsterCredit(me->GetEntry(),me->GetGUID()); + DoScriptText(SAY_SPELL_HIT, me, caster); + me->RemoveAllAuras(); + if (GameObject* Lumberpile = me->FindNearestGameObject(GO_LUMBERPILE, 20)) + me->GetMotionMaster()->MovePoint(1,Lumberpile->GetPositionX()-1,Lumberpile->GetPositionY(),Lumberpile->GetPositionZ()); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (work == true) + me->HandleEmoteCommand(466); + if (m_uiRebuffTimer <= uiDiff) + { + DoCast(me, SPELL_BUFF_SLEEP); + m_uiRebuffTimer = 300000; //Rebuff agian in 5 minutes + } + else + m_uiRebuffTimer -= uiDiff; + if (!UpdateVictim()) + return; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_lazy_peon(Creature* pCreature) +{ + return new npc_lazy_peonAI(pCreature); +} + +void AddSC_durotar() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_lazy_peon"; + newscript->GetAI = &GetAI_npc_lazy_peon; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/src/server/scripts/Kalimdor/dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/dustwallow_marsh.cpp new file mode 100644 index 00000000000..a80c514eed7 --- /dev/null +++ b/src/server/scripts/Kalimdor/dustwallow_marsh.cpp @@ -0,0 +1,425 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Dustwallow_Marsh +SD%Complete: 95 +SDComment: Quest support: 11180, 558, 11126, 11142, 11180. Vendor Nat Pagle +SDCategory: Dustwallow Marsh +EndScriptData */ + +/* ContentData +mobs_risen_husk_spirit +npc_restless_apparition +npc_deserter_agitator +npc_lady_jaina_proudmoore +npc_nat_pagle +npc_private_hendel +npc_cassa_crimsonwing - handled by npc_taxi +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## mobs_risen_husk_spirit +######*/ + +enum eHuskSpirit +{ + QUEST_WHATS_HAUNTING_WITCH_HILL = 11180, + + SPELL_SUMMON_RESTLESS_APPARITION = 42511, + SPELL_CONSUME_FLESH = 37933, //Risen Husk + SPELL_INTANGIBLE_PRESENCE = 43127, //Risen Spirit + + NPC_RISEN_HUSK = 23555, + NPC_RISEN_SPIRIT = 23554, + NPC_RESTLESS_APPARITION = 23861 +}; + +struct mobs_risen_husk_spiritAI : public ScriptedAI +{ + mobs_risen_husk_spiritAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiConsumeFlesh_Timer; + uint32 m_uiIntangiblePresence_Timer; + + void Reset() + { + m_uiConsumeFlesh_Timer = 10000; + m_uiIntangiblePresence_Timer = 5000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_uiConsumeFlesh_Timer <= uiDiff) + { + if (me->GetEntry() == NPC_RISEN_HUSK) + DoCast(me->getVictim(), SPELL_CONSUME_FLESH); + + m_uiConsumeFlesh_Timer = 15000; + } + else + m_uiConsumeFlesh_Timer -= uiDiff; + + if (m_uiIntangiblePresence_Timer <= uiDiff) + { + if (me->GetEntry() == NPC_RISEN_SPIRIT) + DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); + + m_uiIntangiblePresence_Timer = 20000; + } + else + m_uiIntangiblePresence_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* pKiller) + { + if (pKiller->GetTypeId() == TYPEID_PLAYER) + if (CAST_PLR(pKiller)->GetQuestStatus(QUEST_WHATS_HAUNTING_WITCH_HILL) == QUEST_STATUS_INCOMPLETE) + { + DoCast(pKiller, SPELL_SUMMON_RESTLESS_APPARITION, true); + CAST_PLR(pKiller)->KilledMonsterCredit(NPC_RESTLESS_APPARITION,0); + } + } +}; + +CreatureAI* GetAI_mobs_risen_husk_spirit(Creature* pCreature) +{ + return new mobs_risen_husk_spiritAI (pCreature); +} + +/*###### +## npc_restless_apparition +######*/ + +enum eRestlessApparition +{ + SAY_RESTLESS_1 = -1000469, + SAY_RESTLESS_2 = -1000470, + SAY_RESTLESS_3 = -1000471 +}; + +struct npc_restless_apparitionAI : public ScriptedAI +{ + npc_restless_apparitionAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + void Reset() + { + DoScriptText(RAND(SAY_RESTLESS_1,SAY_RESTLESS_2,SAY_RESTLESS_3), me); + } +}; + +CreatureAI* GetAI_npc_restless_apparition(Creature* pCreature) +{ + return new npc_restless_apparitionAI (pCreature); +} + +/*###### +## npc_deserter_agitator +######*/ + +enum eAgitator +{ + QUEST_TRAITORS_AMONG_US = 11126, + FACTION_THER_DESERTER = 1883 +}; + +struct npc_deserter_agitatorAI : public ScriptedAI +{ + npc_deserter_agitatorAI(Creature* pCreature) : ScriptedAI(pCreature) { } + + void Reset() + { + me->RestoreFaction(); + } +}; + +CreatureAI* GetAI_npc_deserter_agitator(Creature* pCreature) +{ + return new npc_deserter_agitatorAI (pCreature); +} + +bool GossipHello_npc_deserter_agitator(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_TRAITORS_AMONG_US) == QUEST_STATUS_INCOMPLETE) + { + pCreature->setFaction(FACTION_THER_DESERTER); + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_lady_jaina_proudmoore +######*/ + +enum eLadyJaina +{ + QUEST_JAINAS_AUTOGRAPH = 558, + SPELL_JAINAS_AUTOGRAPH = 23122 +}; + +#define GOSSIP_ITEM_JAINA "I know this is rather silly but i have a young ward who is a bit shy and would like your autograph." + +bool GossipHello_npc_lady_jaina_proudmoore(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_JAINAS_AUTOGRAPH) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_JAINA, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lady_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_SENDER_INFO) + { + pPlayer->SEND_GOSSIP_MENU(7012, pCreature->GetGUID()); + pPlayer->CastSpell(pPlayer, SPELL_JAINAS_AUTOGRAPH, false); + } + return true; +} + +/*###### +## npc_nat_pagle +######*/ + +enum eNatPagle +{ + QUEST_NATS_MEASURING_TAPE = 8227 +}; + +bool GossipHello_npc_nat_pagle(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(QUEST_NATS_MEASURING_TAPE)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + pPlayer->SEND_GOSSIP_MENU(7640, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(7638, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_nat_pagle(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_private_hendel +######*/ + +enum eHendel +{ + // looks like all this text ids are wrong. + SAY_PROGRESS_1_TER = -1000411, // signed for 3568 + SAY_PROGRESS_2_HEN = -1000412, // signed for 3568 + SAY_PROGRESS_3_TER = -1000413, + SAY_PROGRESS_4_TER = -1000414, + EMOTE_SURRENDER = -1000415, + + QUEST_MISSING_DIPLO_PT16 = 1324, + FACTION_HOSTILE = 168, //guessed, may be different + + NPC_SENTRY = 5184, //helps hendel + NPC_JAINA = 4968, //appears once hendel gives up + NPC_TERVOSH = 4967 +}; + +//TODO: develop this further, end event not created +struct npc_private_hendelAI : public ScriptedAI +{ + npc_private_hendelAI(Creature* pCreature) : ScriptedAI(pCreature) { } + + void Reset() + { + me->RestoreFaction(); + } + + void AttackedBy(Unit* pAttacker) + { + if (me->getVictim()) + return; + + if (me->IsFriendlyTo(pAttacker)) + return; + + AttackStart(pAttacker); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > me->GetHealth() || ((me->GetHealth() - uiDamage)*100 / me->GetMaxHealth() < 20)) + { + uiDamage = 0; + + if (Player* pPlayer = pDoneBy->GetCharmerOrOwnerPlayerOrPlayerItself()) + pPlayer->GroupEventHappens(QUEST_MISSING_DIPLO_PT16, me); + + DoScriptText(EMOTE_SURRENDER, me); + EnterEvadeMode(); + } + } +}; + +bool QuestAccept_npc_private_hendel(Player* /*pPlayer*/, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT16) + pCreature->setFaction(FACTION_HOSTILE); + + return true; +} + +CreatureAI* GetAI_npc_private_hendel(Creature* pCreature) +{ + return new npc_private_hendelAI(pCreature); +} + +/*###### +## npc_zelfrax +######*/ + +const Position MovePosition = {-2967.030,-3872.1799,35.620}; + +enum eZelfrax +{ + SAY_ZELFRAX = -1000472, + SAY_ZELFRAX_2 = -1000473 +}; + +struct npc_zelfraxAI : public ScriptedAI +{ + npc_zelfraxAI(Creature* pCreature) : ScriptedAI(pCreature) + { + MoveToDock(); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (me->Attack(pWho, true)) + { + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + if (IsCombatMovement()) + me->GetMotionMaster()->MoveChase(pWho); + } + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + me->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); + SetCombatMovement(true); + + if (me->isInCombat()) + if (Unit* pUnit = me->getVictim()) + me->GetMotionMaster()->MoveChase(pUnit); + } + + void MoveToDock() + { + SetCombatMovement(false); + me->GetMotionMaster()->MovePoint(0,MovePosition); + DoScriptText(SAY_ZELFRAX,me); + DoScriptText(SAY_ZELFRAX_2,me); + } + + void UpdateAI(uint32 const /*uiDiff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_zelfrax(Creature* pCreature) +{ + return new npc_zelfraxAI(pCreature); +} + +void AddSC_dustwallow_marsh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mobs_risen_husk_spirit"; + newscript->GetAI = &GetAI_mobs_risen_husk_spirit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_restless_apparition"; + newscript->GetAI = &GetAI_npc_restless_apparition; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_deserter_agitator"; + newscript->GetAI = &GetAI_npc_deserter_agitator; + newscript->pGossipHello = &GossipHello_npc_deserter_agitator; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lady_jaina_proudmoore"; + newscript->pGossipHello = &GossipHello_npc_lady_jaina_proudmoore; + newscript->pGossipSelect = &GossipSelect_npc_lady_jaina_proudmoore; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_nat_pagle"; + newscript->pGossipHello = &GossipHello_npc_nat_pagle; + newscript->pGossipSelect = &GossipSelect_npc_nat_pagle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_private_hendel"; + newscript->GetAI = &GetAI_npc_private_hendel; + newscript->pQuestAccept = &QuestAccept_npc_private_hendel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_zelfrax"; + newscript->GetAI = &GetAI_npc_zelfrax; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/felwood.cpp b/src/server/scripts/Kalimdor/felwood.cpp new file mode 100644 index 00000000000..01da356a63e --- /dev/null +++ b/src/server/scripts/Kalimdor/felwood.cpp @@ -0,0 +1,90 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Felwood +SD%Complete: 95 +SDComment: Quest support: 4101, 4102 +SDCategory: Felwood +EndScriptData */ + +/* ContentData +npcs_riverbreeze_and_silversky +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npcs_riverbreeze_and_silversky +######*/ + +#define GOSSIP_ITEM_BEACON "Please make me a Cenarion Beacon" + +bool GossipHello_npcs_riverbreeze_and_silversky(Player* pPlayer, Creature* pCreature) +{ + uint32 eCreature = pCreature->GetEntry(); + + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (eCreature == 9528) + { + if (pPlayer->GetQuestRewardStatus(4101)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(2848, pCreature->GetGUID()); + } else if (pPlayer->GetTeam() == HORDE) + pPlayer->SEND_GOSSIP_MENU(2845, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(2844, pCreature->GetGUID()); + } + + if (eCreature == 9529) + { + if (pPlayer->GetQuestRewardStatus(4102)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(2849, pCreature->GetGUID()); + } else if (pPlayer->GetTeam() == ALLIANCE) + pPlayer->SEND_GOSSIP_MENU(2843, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(2842, pCreature->GetGUID()); + } + + return true; +} + +bool GossipSelect_npcs_riverbreeze_and_silversky(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, 15120, false); + } + return true; +} + +void AddSC_felwood() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npcs_riverbreeze_and_silversky"; + newscript->pGossipHello = &GossipHello_npcs_riverbreeze_and_silversky; + newscript->pGossipSelect = &GossipSelect_npcs_riverbreeze_and_silversky; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/feralas.cpp b/src/server/scripts/Kalimdor/feralas.cpp new file mode 100644 index 00000000000..2a87de1a67c --- /dev/null +++ b/src/server/scripts/Kalimdor/feralas.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Feralas +SD%Complete: 100 +SDComment: Quest support: 3520, 2767, Special vendor Gregan Brewspewer +SDCategory: Feralas +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_gregan_brewspewer +######*/ + +#define GOSSIP_HELLO "Buy somethin', will ya?" + +bool GossipHello_npc_gregan_brewspewer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor() && pPlayer->GetQuestStatus(3909) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(2433, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_gregan_brewspewer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + pPlayer->SEND_GOSSIP_MENU(2434, pCreature->GetGUID()); + } + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + return true; +} + +/*###### +## npc_oox22fe +######*/ + +enum eOOX +{ + //signed for 7806 + SAY_OOX_START = -1000287, + SAY_OOX_AGGRO1 = -1000288, + SAY_OOX_AGGRO2 = -1000289, + SAY_OOX_AMBUSH = -1000290, + SAY_OOX_END = -1000292, + + NPC_YETI = 7848, + NPC_GORILLA = 5260, + NPC_WOODPAW_REAVER = 5255, + NPC_WOODPAW_BRUTE = 5253, + NPC_WOODPAW_ALPHA = 5258, + NPC_WOODPAW_MYSTIC = 5254, + + QUEST_RESCUE_OOX22FE = 2767, + FACTION_ESCORTEE_A = 774, + FACTION_ESCORTEE_H = 775 +}; + +struct npc_oox22feAI : public npc_escortAI +{ + npc_oox22feAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void WaypointReached(uint32 i) + { + switch (i) + { + // First Ambush(3 Yetis) + case 11: + DoScriptText(SAY_OOX_AMBUSH, me); + me->SummonCreature(NPC_YETI, -4841.01, 1593.91, 73.42, 3.98, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + me->SummonCreature(NPC_YETI, -4837.61, 1568.58, 78.21, 3.13, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + me->SummonCreature(NPC_YETI, -4841.89, 1569.95, 76.53, 0.68, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + break; + //Second Ambush(3 Gorillas) + case 21: + DoScriptText(SAY_OOX_AMBUSH, me); + me->SummonCreature(NPC_GORILLA, -4595.81, 2005.99, 53.08, 3.74, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + me->SummonCreature(NPC_GORILLA, -4597.53, 2008.31, 52.70, 3.78, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + me->SummonCreature(NPC_GORILLA, -4599.37, 2010.59, 52.77, 3.84, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + break; + //Third Ambush(4 Gnolls) + case 30: + DoScriptText(SAY_OOX_AMBUSH, me); + me->SummonCreature(NPC_WOODPAW_REAVER, -4425.14, 2075.87, 47.77, 3.77, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + me->SummonCreature(NPC_WOODPAW_BRUTE , -4426.68, 2077.98, 47.57, 3.77, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + me->SummonCreature(NPC_WOODPAW_MYSTIC, -4428.33, 2080.24, 47.43, 3.87, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + me->SummonCreature(NPC_WOODPAW_ALPHA , -4430.04, 2075.54, 46.83, 3.81, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + break; + case 37: + DoScriptText(SAY_OOX_END, me); + // Award quest credit + if (Player* pPlayer = GetPlayerForEscort()) + { + pPlayer->GroupEventHappens(QUEST_RESCUE_OOX22FE, me); + } + break; + } + } + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + me->SetStandState(UNIT_STAND_STATE_DEAD); + } + + void EnterCombat(Unit* /*who*/) + { + //For an small probability the npc says something when he get aggro + if (urand(0,9) > 7) + DoScriptText(RAND(SAY_OOX_AGGRO1,SAY_OOX_AGGRO2), me); + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } +}; + +CreatureAI* GetAI_npc_oox22fe(Creature* pCreature) +{ + return new npc_oox22feAI(pCreature); +} + +bool QuestAccept_npc_oox22fe(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_RESCUE_OOX22FE) + { + DoScriptText(SAY_OOX_START, pCreature); + //change that the npc is not lying dead on the ground + pCreature->SetStandState(UNIT_STAND_STATE_STAND); + + if (pPlayer->GetTeam() == ALLIANCE) + pCreature->setFaction(FACTION_ESCORTEE_A); + + if (pPlayer->GetTeam() == HORDE) + pCreature->setFaction(FACTION_ESCORTEE_H); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_oox22feAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + + } + return true; +} + +/*###### +## npc_screecher_spirit +######*/ + +bool GossipHello_npc_screecher_spirit(Player* pPlayer, Creature* pCreature) +{ + pPlayer->SEND_GOSSIP_MENU(2039, pCreature->GetGUID()); + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_feralas() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_gregan_brewspewer"; + newscript->pGossipHello = &GossipHello_npc_gregan_brewspewer; + newscript->pGossipSelect = &GossipSelect_npc_gregan_brewspewer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_oox22fe"; + newscript->GetAI = &GetAI_npc_oox22fe; + newscript->pQuestAccept = &QuestAccept_npc_oox22fe; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_screecher_spirit"; + newscript->pGossipHello = &GossipHello_npc_screecher_spirit; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp b/src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp new file mode 100644 index 00000000000..6f6b9d1baa9 --- /dev/null +++ b/src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Celebras_the_Cursed +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_WRATH 21807 +#define SPELL_ENTANGLINGROOTS 12747 +#define SPELL_CORRUPT_FORCES 21968 + +struct celebras_the_cursedAI : public ScriptedAI +{ + celebras_the_cursedAI(Creature *c) : ScriptedAI(c) {} + + uint32 Wrath_Timer; + uint32 EntanglingRoots_Timer; + uint32 CorruptForces_Timer; + + void Reset() + { + Wrath_Timer = 8000; + EntanglingRoots_Timer = 2000; + CorruptForces_Timer = 30000; + } + + void EnterCombat(Unit * /*who*/) { } + + void JustDied(Unit* /*Killer*/) + { + me->SummonCreature(13716, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Wrath + if (Wrath_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + DoCast(pTarget, SPELL_WRATH); + Wrath_Timer = 8000; + } else Wrath_Timer -= diff; + + //EntanglingRoots + if (EntanglingRoots_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ENTANGLINGROOTS); + EntanglingRoots_Timer = 20000; + } else EntanglingRoots_Timer -= diff; + + //CorruptForces + if (CorruptForces_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_CORRUPT_FORCES); + CorruptForces_Timer = 20000; + } else CorruptForces_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_celebras_the_cursed(Creature* pCreature) +{ + return new celebras_the_cursedAI (pCreature); +} + +void AddSC_boss_celebras_the_cursed() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "celebras_the_cursed"; + newscript->GetAI = &GetAI_celebras_the_cursed; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp b/src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp new file mode 100644 index 00000000000..d5b03ff218f --- /dev/null +++ b/src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Landslide +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_KNOCKAWAY 18670 +#define SPELL_TRAMPLE 5568 +#define SPELL_LANDSLIDE 21808 + +struct boss_landslideAI : public ScriptedAI +{ + boss_landslideAI(Creature *c) : ScriptedAI(c) {} + + uint32 KnockAway_Timer; + uint32 Trample_Timer; + uint32 Landslide_Timer; + + void Reset() + { + KnockAway_Timer = 8000; + Trample_Timer = 2000; + Landslide_Timer = 0; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //KnockAway_Timer + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + KnockAway_Timer = 15000; + } else KnockAway_Timer -= diff; + + //Trample_Timer + if (Trample_Timer <= diff) + { + DoCast(me, SPELL_TRAMPLE); + Trample_Timer = 8000; + } else Trample_Timer -= diff; + + //Landslide + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + if (Landslide_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_LANDSLIDE); + Landslide_Timer = 60000; + } else Landslide_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_landslide(Creature* pCreature) +{ + return new boss_landslideAI (pCreature); +} + +void AddSC_boss_landslide() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_landslide"; + newscript->GetAI = &GetAI_boss_landslide; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp b/src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp new file mode 100644 index 00000000000..b49b1a5d71f --- /dev/null +++ b/src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp @@ -0,0 +1,131 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Noxxion +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_TOXICVOLLEY 21687 +#define SPELL_UPPERCUT 22916 + +struct boss_noxxionAI : public ScriptedAI +{ + boss_noxxionAI(Creature *c) : ScriptedAI(c) {} + + uint32 ToxicVolley_Timer; + uint32 Uppercut_Timer; + uint32 Adds_Timer; + uint32 Invisible_Timer; + bool Invisible; + + void Reset() + { + ToxicVolley_Timer = 7000; + Uppercut_Timer = 16000; + Adds_Timer = 19000; + Invisible_Timer = 15000; //Too much too low? + Invisible = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonAdds(Unit* pVictim) + { + if (Creature *Add = DoSpawnCreature(13456, irand(-7,7), irand(-7,7), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 90000)) + Add->AI()->AttackStart(pVictim); + } + + void UpdateAI(const uint32 diff) + { + if (Invisible && Invisible_Timer <= diff) + { + //Become visible again + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //Noxxion model + me->SetDisplayId(11172); + Invisible = false; + //me->m_canMove = true; + } else if (Invisible) + { + Invisible_Timer -= diff; + //Do nothing while invisible + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //ToxicVolley_Timer + if (ToxicVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TOXICVOLLEY); + ToxicVolley_Timer = 9000; + } else ToxicVolley_Timer -= diff; + + //Uppercut_Timer + if (Uppercut_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_UPPERCUT); + Uppercut_Timer = 12000; + } else Uppercut_Timer -= diff; + + //Adds_Timer + if (!Invisible && Adds_Timer <= diff) + { + //Inturrupt any spell casting + //me->m_canMove = true; + me->InterruptNonMeleeSpells(false); + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Invisible Model + me->SetDisplayId(11686); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + Invisible = true; + Invisible_Timer = 15000; + + Adds_Timer = 40000; + } else Adds_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_noxxion(Creature* pCreature) +{ + return new boss_noxxionAI (pCreature); +} + +void AddSC_boss_noxxion() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_noxxion"; + newscript->GetAI = &GetAI_boss_noxxion; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp b/src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp new file mode 100644 index 00000000000..963863e89c8 --- /dev/null +++ b/src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp @@ -0,0 +1,109 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Princess_Theradras +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_DUSTFIELD 21909 +#define SPELL_BOULDER 21832 +#define SPELL_THRASH 3391 +#define SPELL_REPULSIVEGAZE 21869 + +struct boss_ptheradrasAI : public ScriptedAI +{ + boss_ptheradrasAI(Creature *c) : ScriptedAI(c) {} + + uint32 Dustfield_Timer; + uint32 Boulder_Timer; + uint32 Thrash_Timer; + uint32 RepulsiveGaze_Timer; + + void Reset() + { + Dustfield_Timer = 8000; + Boulder_Timer = 2000; + Thrash_Timer = 5000; + RepulsiveGaze_Timer = 23000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*killer*/) + { + me->SummonCreature(12238,28.067,61.875,-123.405,4.67,TEMPSUMMON_TIMED_DESPAWN,600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Dustfield_Timer + if (Dustfield_Timer <= diff) + { + DoCast(me, SPELL_DUSTFIELD); + Dustfield_Timer = 14000; + } else Dustfield_Timer -= diff; + + //Boulder_Timer + if (Boulder_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + DoCast(pTarget, SPELL_BOULDER); + Boulder_Timer = 10000; + } else Boulder_Timer -= diff; + + //RepulsiveGaze_Timer + if (RepulsiveGaze_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REPULSIVEGAZE); + RepulsiveGaze_Timer = 20000; + } else RepulsiveGaze_Timer -= diff; + + //Thrash_Timer + if (Thrash_Timer <= diff) + { + DoCast(me, SPELL_THRASH); + Thrash_Timer = 18000; + } else Thrash_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ptheradras(Creature* pCreature) +{ + return new boss_ptheradrasAI (pCreature); +} + +void AddSC_boss_ptheradras() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_princess_theradras"; + newscript->GetAI = &GetAI_boss_ptheradras; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/moonglade.cpp b/src/server/scripts/Kalimdor/moonglade.cpp new file mode 100644 index 00000000000..16c78f20812 --- /dev/null +++ b/src/server/scripts/Kalimdor/moonglade.cpp @@ -0,0 +1,571 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Moonglade +SD%Complete: 100 +SDComment: Quest support: 30, 272, 5929, 5930, 10965. Special Flight Paths for Druid class. +SDCategory: Moonglade +EndScriptData */ + +/* ContentData +npc_bunthen_plainswind +npc_great_bear_spirit +npc_silva_filnaveth +npc_clintar_spirit +npc_clintar_dreamwalker +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_bunthen_plainswind +######*/ + +enum eBunthen +{ + QUEST_SEA_LION_HORDE = 30, + QUEST_SEA_LION_ALLY = 272, + TAXI_PATH_ID_ALLY = 315, + TAXI_PATH_ID_HORDE = 316 +}; + +#define GOSSIP_ITEM_THUNDER "I'd like to fly to Thunder Bluff." +#define GOSSIP_ITEM_AQ_END "Do you know where I can find Half Pendant of Aquatic Endurance?" + +bool GossipHello_npc_bunthen_plainswind(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->getClass() != CLASS_DRUID) + pPlayer->SEND_GOSSIP_MENU(4916, pCreature->GetGUID()); + else if (pPlayer->GetTeam() != HORDE) + { + if (pPlayer->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + pPlayer->SEND_GOSSIP_MENU(4917, pCreature->GetGUID()); + } + else if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == HORDE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THUNDER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (pPlayer->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + pPlayer->SEND_GOSSIP_MENU(4918, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_bunthen_plainswind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == HORDE) + pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID_HORDE); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->SEND_GOSSIP_MENU(5373, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(5376, pCreature->GetGUID()); + break; + } + return true; +} + +/*###### +## npc_great_bear_spirit +######*/ + +#define GOSSIP_BEAR1 "What do you represent, spirit?" +#define GOSSIP_BEAR2 "I seek to understand the importance of strength of the body." +#define GOSSIP_BEAR3 "I seek to understand the importance of strength of the heart." +#define GOSSIP_BEAR4 "I have heard your words, Great Bear Spirit, and I understand. I now seek your blessings to fully learn the way of the Claw." + +bool GossipHello_npc_great_bear_spirit(Player* pPlayer, Creature* pCreature) +{ + //ally or horde quest + if (pPlayer->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(4719, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(4718, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_great_bear_spirit(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(4721, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(4733, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(4734, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(4735, pCreature->GetGUID()); + if (pPlayer->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(5929); + if (pPlayer->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(5930); + break; + } + return true; +} + +/*###### +## npc_silva_filnaveth +######*/ + +#define GOSSIP_ITEM_RUTHERAN "I'd like to fly to Rut'theran Village." +#define GOSSIP_ITEM_AQ_AGI "Do you know where I can find Half Pendant of Aquatic Agility?" + +bool GossipHello_npc_silva_filnaveth(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->getClass() != CLASS_DRUID) + pPlayer->SEND_GOSSIP_MENU(4913, pCreature->GetGUID()); + else if (pPlayer->GetTeam() != ALLIANCE) + { + if (pPlayer->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + pPlayer->SEND_GOSSIP_MENU(4915, pCreature->GetGUID()); + } + else if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == ALLIANCE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTHERAN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (pPlayer->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + pPlayer->SEND_GOSSIP_MENU(4914, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_silva_filnaveth(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == ALLIANCE) + pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID_ALLY); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->SEND_GOSSIP_MENU(5374, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(5375, pCreature->GetGUID()); + break; + } + return true; +} + +/*###### +## npc_clintar_spirit +######*/ + +float Clintar_spirit_WP[41][5] = +{ + //pos_x pos_y pos_z orien waitTime +{7465.28, -3115.46, 439.327, 0.83, 4000}, +{7476.49, -3101, 443.457, 0.89, 0}, +{7486.57, -3085.59, 439.478, 1.07, 0}, +{7472.19, -3085.06, 443.142, 3.07, 0}, +{7456.92, -3085.91, 438.862, 3.24, 0}, +{7446.68, -3083.43, 438.245, 2.40, 0}, +{7446.17, -3080.21, 439.826, 1.10, 6000}, +{7452.41, -3085.8, 438.984, 5.78, 0}, +{7469.11, -3084.94, 443.048, 6.25, 0}, +{7483.79, -3085.44, 439.607, 6.25, 0}, +{7491.14, -3090.96, 439.983, 5.44, 0}, +{7497.62, -3098.22, 436.854, 5.44, 0}, +{7498.72, -3113.41, 434.596, 4.84, 0}, +{7500.06, -3122.51, 434.749, 5.17, 0}, +{7504.96, -3131.53, 434.475, 4.74, 0}, +{7504.31, -3133.53, 435.693, 3.84, 6000}, +{7504.55, -3133.27, 435.476, 0.68, 15000}, +{7501.99, -3126.01, 434.93, 1.83, 0}, +{7490.76, -3114.97, 434.431, 2.51, 0}, +{7479.64, -3105.51, 431.123, 1.83, 0}, +{7474.63, -3086.59, 428.994, 1.83, 2000}, +{7472.96, -3074.18, 427.566, 1.57, 0}, +{7472.25, -3063, 428.268, 1.55, 0}, +{7473.46, -3054.22, 427.588, 0.36, 0}, +{7475.08, -3053.6, 428.653, 0.36, 6000}, +{7474.66, -3053.56, 428.433, 3.19, 4000}, +{7471.81, -3058.84, 427.073, 4.29, 0}, +{7472.16, -3064.91, 427.772, 4.95, 0}, +{7471.56, -3085.36, 428.924, 4.72, 0}, +{7473.56, -3093.48, 429.294, 5.04, 0}, +{7478.94, -3104.29, 430.638, 5.23, 0}, +{7484.46, -3109.61, 432.769, 5.79, 0}, +{7490.23, -3111.08, 434.431, 0.02, 0}, +{7496.29, -3108, 434.783, 1.15, 0}, +{7497.46, -3100.66, 436.191, 1.50, 0}, +{7495.64, -3093.39, 438.349, 2.10, 0}, +{7492.44, -3086.01, 440.267, 1.38, 0}, +{7498.26, -3076.44, 440.808, 0.71, 0}, +{7506.4, -3067.35, 443.64, 0.77, 0}, +{7518.37, -3057.42, 445.584, 0.74, 0}, +{7517.51, -3056.3, 444.568, 2.49, 4500} +}; + +#define ASPECT_RAVEN 22915 + +#define ASPECT_RAVEN_SUMMON_X 7472.96 +#define ASPECT_RAVEN_SUMMON_Y -3074.18 +#define ASPECT_RAVEN_SUMMON_Z 427.566 +#define CLINTAR_SPIRIT_SUMMON_X 7459.2275 +#define CLINTAR_SPIRIT_SUMMON_Y -3122.5632 +#define CLINTAR_SPIRIT_SUMMON_Z 438.9842 +#define CLINTAR_SPIRIT_SUMMON_O 0.8594 + +//from -1000292 to -1000287 are signed for 7806. but all this texts ids wrong. +#define CLINTAR_SPIRIT_SAY_START -1000286 +#define CLINTAR_SPIRIT_SAY_UNDER_ATTACK_1 -1000287 +#define CLINTAR_SPIRIT_SAY_UNDER_ATTACK_2 -1000288 +#define CLINTAR_SPIRIT_SAY_GET_ONE -1000289 +#define CLINTAR_SPIRIT_SAY_GET_TWO -1000290 +#define CLINTAR_SPIRIT_SAY_GET_THREE -1000291 +#define CLINTAR_SPIRIT_SAY_GET_FINAL -1000292 + +struct npc_clintar_spiritAI : public npc_escortAI +{ +public: + npc_clintar_spiritAI(Creature *c) : npc_escortAI(c) {} + + uint32 Step; + uint32 CurrWP; + uint32 Event_Timer; + uint32 checkPlayer_Timer; + + uint64 PlayerGUID; + + bool Event_onWait; + + void Reset() + { + if (!PlayerGUID) + { + Step = 0; + CurrWP = 0; + Event_Timer = 0; + PlayerGUID = 0; + checkPlayer_Timer = 1000; + Event_onWait = false; + } + } + + void JustDied(Unit * /*killer*/) + { + if (!PlayerGUID) + return; + + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer && pPlayer->GetQuestStatus(10965) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->FailQuest(10965); + PlayerGUID = 0; + Reset(); + } + } + + void EnterEvadeMode() + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer && pPlayer->isInCombat() && pPlayer->getAttackerForHelper()) + { + AttackStart(pPlayer->getAttackerForHelper()); + return; + } + npc_escortAI::EnterEvadeMode(); + } + + void EnterCombat(Unit* who) + { + uint32 rnd = rand()%2; + switch(rnd) + { + case 0: DoScriptText(CLINTAR_SPIRIT_SAY_UNDER_ATTACK_1, me, who); break; + case 1: DoScriptText(CLINTAR_SPIRIT_SAY_UNDER_ATTACK_2, me, who); break; + } + } + + void StartEvent(Player* pPlayer) + { + if (!pPlayer) + return; + if (pPlayer->GetQuestStatus(10965) == QUEST_STATUS_INCOMPLETE) + { + for (uint8 i = 0; i < 41; ++i) + { + AddWaypoint(i, Clintar_spirit_WP[i][0], Clintar_spirit_WP[i][1], Clintar_spirit_WP[i][2], (uint32)Clintar_spirit_WP[i][4]); + } + PlayerGUID = pPlayer->GetGUID(); + Start(true,false,PlayerGUID); + } + return; + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (!PlayerGUID) + { + me->setDeathState(JUST_DIED); + return; + } + + if (!me->isInCombat() && !Event_onWait) + { + if (checkPlayer_Timer <= diff) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer && pPlayer->isInCombat() && pPlayer->getAttackerForHelper()) + AttackStart(pPlayer->getAttackerForHelper()); + checkPlayer_Timer = 1000; + } else checkPlayer_Timer -= diff; + } + + if (Event_onWait && Event_Timer <= diff) + { + + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (!pPlayer || (pPlayer && pPlayer->GetQuestStatus(10965) == QUEST_STATUS_NONE)) + { + me->setDeathState(JUST_DIED); + return; + } + + switch(CurrWP) + { + case 0: + switch(Step) + { + case 0: + me->Say(CLINTAR_SPIRIT_SAY_START,0,PlayerGUID); + Event_Timer = 8000; + Step = 1; + break; + case 1: + Event_onWait = false; + break; + } + break; + case 6: + switch(Step) + { + case 0: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); + Event_Timer = 5000; + Step = 1; + break; + case 1: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); + DoScriptText(CLINTAR_SPIRIT_SAY_GET_ONE, me, pPlayer); + Event_onWait = false; + break; + } + break; + case 15: + switch(Step) + { + case 0: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); + Event_Timer = 5000; + Step = 1; + break; + case 1: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); + Event_onWait = false; + break; + } + break; + case 16: + switch(Step) + { + case 0: + DoScriptText(CLINTAR_SPIRIT_SAY_GET_TWO, me, pPlayer); + Event_Timer = 15000; + Step = 1; + break; + case 1: + Event_onWait = false; + break; + } + break; + case 20: + switch(Step) + { + case 0: + { + Creature *mob = me->SummonCreature(ASPECT_RAVEN, ASPECT_RAVEN_SUMMON_X, ASPECT_RAVEN_SUMMON_Y, ASPECT_RAVEN_SUMMON_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); + if (mob) + { + mob->AddThreat(me,10000.0f); + mob->AI()->AttackStart(me); + } + Event_Timer = 2000; + Step = 1; + break; + } + case 1: + Event_onWait = false; + break; + } + break; + case 24: + switch(Step) + { + case 0: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); + Event_Timer = 5000; + Step = 1; + break; + case 1: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); + Event_onWait = false; + break; + } + break; + case 25: + switch(Step) + { + case 0: + DoScriptText(CLINTAR_SPIRIT_SAY_GET_THREE, me, pPlayer); + Event_Timer = 4000; + Step = 1; + break; + case 1: + Event_onWait = false; + break; + } + break; + case 40: + switch(Step) + { + case 0: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 2); + DoScriptText(CLINTAR_SPIRIT_SAY_GET_FINAL, me, pPlayer); + pPlayer->CompleteQuest(10965); + Event_Timer = 1500; + Step = 1; + break; + case 1: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); + Event_Timer = 3000; + Step = 2; + break; + case 2: + pPlayer->TalkedToCreature(me->GetEntry(), me->GetGUID()); + PlayerGUID = 0; + Reset(); + me->setDeathState(JUST_DIED); + break; + } + break; + default: + Event_onWait = false; + break; + } + + } else if (Event_onWait) Event_Timer -= diff; + } + + void WaypointReached(uint32 id) + { + CurrWP = id; + Event_Timer = 0; + Step = 0; + Event_onWait = true; + } +}; + +CreatureAI* GetAI_npc_clintar_spirit(Creature* pCreature) +{ + return new npc_clintar_spiritAI (pCreature); +} + +/*#### +# npc_clintar_dreamwalker +####*/ + +#define CLINTAR_SPIRIT 22916 + +bool QuestAccept_npc_clintar_dreamwalker(Player* pPlayer, Creature* pCreature, Quest const *quest) +{ + if (quest->GetQuestId() == 10965) + { + Creature *clintar_spirit = pCreature->SummonCreature(CLINTAR_SPIRIT, CLINTAR_SPIRIT_SUMMON_X, CLINTAR_SPIRIT_SUMMON_Y, CLINTAR_SPIRIT_SUMMON_Z, CLINTAR_SPIRIT_SUMMON_O, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 100000); + if (clintar_spirit) + CAST_AI(npc_clintar_spiritAI, clintar_spirit->AI())->StartEvent(pPlayer); + } + return true; +} + +/*#### +# +####*/ + +void AddSC_moonglade() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_bunthen_plainswind"; + newscript->pGossipHello = &GossipHello_npc_bunthen_plainswind; + newscript->pGossipSelect = &GossipSelect_npc_bunthen_plainswind; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_great_bear_spirit"; + newscript->pGossipHello = &GossipHello_npc_great_bear_spirit; + newscript->pGossipSelect = &GossipSelect_npc_great_bear_spirit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_silva_filnaveth"; + newscript->pGossipHello = &GossipHello_npc_silva_filnaveth; + newscript->pGossipSelect = &GossipSelect_npc_silva_filnaveth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_clintar_dreamwalker"; + newscript->pQuestAccept = &QuestAccept_npc_clintar_dreamwalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_clintar_spirit"; + newscript->GetAI = &GetAI_npc_clintar_spirit; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/mulgore.cpp b/src/server/scripts/Kalimdor/mulgore.cpp new file mode 100644 index 00000000000..c87e5e36dad --- /dev/null +++ b/src/server/scripts/Kalimdor/mulgore.cpp @@ -0,0 +1,316 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Mulgore +SD%Complete: 100 +SDComment: Support for quest: 11129, 772 +SDCategory: Mulgore +EndScriptData */ + +/* ContentData +npc_skorn_whitecloud +npc_kyle_frenzied +npc_plains_vision +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +# npc_skorn_whitecloud +######*/ + +#define GOSSIP_SW "Tell me a story, Skorn." + +bool GossipHello_npc_skorn_whitecloud(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (!pPlayer->GetQuestRewardStatus(770)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(522, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_skorn_whitecloud(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + pPlayer->SEND_GOSSIP_MENU(523, pCreature->GetGUID()); + + return true; +} + +/*##### +# npc_kyle_frenzied +######*/ + +enum eKyleFrenzied +{ + //emote signed for 7780 but propably thats wrong id. + EMOTE_SEE_LUNCH = -1000340, + EMOTE_EAT_LUNCH = -1000341, + EMOTE_DANCE = -1000342, + + SPELL_LUNCH = 42222, + NPC_KYLE_FRENZIED = 23616, + NPC_KYLE_FRIENDLY = 23622, + POINT_ID = 1 +}; + +struct npc_kyle_frenziedAI : public ScriptedAI +{ + npc_kyle_frenziedAI(Creature *c) : ScriptedAI(c) {} + + bool bEvent; + bool m_bIsMovingToLunch; + uint64 uiPlayerGUID; + uint32 uiEventTimer; + uint8 uiEventPhase; + + void Reset() + { + bEvent = false; + m_bIsMovingToLunch = false; + uiPlayerGUID = 0; + uiEventTimer = 5000; + uiEventPhase = 0; + + if (me->GetEntry() == NPC_KYLE_FRIENDLY) + me->UpdateEntry(NPC_KYLE_FRENZIED); + } + + void SpellHit(Unit* pCaster, SpellEntry const* pSpell) + { + if (!me->getVictim() && !bEvent && pSpell->Id == SPELL_LUNCH) + { + if (pCaster->GetTypeId() == TYPEID_PLAYER) + uiPlayerGUID = pCaster->GetGUID(); + + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + { + me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); + } + + bEvent = true; + DoScriptText(EMOTE_SEE_LUNCH, me); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_CREATURE_SPECIAL); + } + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE || !bEvent) + return; + + if (uiPointId == POINT_ID) + m_bIsMovingToLunch = false; + } + + void UpdateAI(const uint32 diff) + { + if (bEvent) + { + if (m_bIsMovingToLunch) + return; + + if (uiEventTimer <= diff) + { + uiEventTimer = 5000; + ++uiEventPhase; + + switch(uiEventPhase) + { + case 1: + if (Unit* pUnit = Unit::GetUnit(*me,uiPlayerGUID)) + { + if (GameObject* pGo = pUnit->GetGameObject(SPELL_LUNCH)) + { + m_bIsMovingToLunch = true; + me->GetMotionMaster()->MovePoint(POINT_ID, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ()); + } + } + break; + case 2: + DoScriptText(EMOTE_EAT_LUNCH, me); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USESTANDING); + break; + case 3: + if (Player* pUnit = Unit::GetPlayer(uiPlayerGUID)) + pUnit->TalkedToCreature(me->GetEntry(), me->GetGUID()); + + me->UpdateEntry(NPC_KYLE_FRIENDLY); + break; + case 4: + uiEventTimer = 30000; + DoScriptText(EMOTE_DANCE, me); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCESPECIAL); + break; + case 5: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + Reset(); + me->GetMotionMaster()->Clear(); + break; + } + } + else + uiEventTimer -= diff; + } + } +}; + +CreatureAI* GetAI_npc_kyle_frenzied(Creature* pCreature) +{ + return new npc_kyle_frenziedAI (pCreature); +} + +/*##### +# npc_plains_vision +######*/ + +float wp_plain_vision[50][3] = +{ + {-2226.32, -408.095, -9.36235}, + {-2203.04, -437.212, -5.72498}, + {-2163.91, -457.851, -7.09049}, + {-2123.87, -448.137, -9.29591}, + {-2104.66, -427.166, -6.49513}, + {-2101.48, -422.826, -5.3567}, + {-2097.56, -417.083, -7.16716}, + {-2084.87, -398.626, -9.88973}, + {-2072.71, -382.324, -10.2488}, + {-2054.05, -356.728, -6.22468}, + {-2051.8, -353.645, -5.35791}, + {-2049.08, -349.912, -6.15723}, + {-2030.6, -310.724, -9.59302}, + {-2002.15, -249.308, -10.8124}, + {-1972.85, -195.811, -10.6316}, + {-1940.93, -147.652, -11.7055}, + {-1888.06, -81.943, -11.4404}, + {-1837.05, -34.0109, -12.258}, + {-1796.12, -14.6462, -10.3581}, + {-1732.61, -4.27746, -10.0213}, + {-1688.94, -0.829945, -11.7103}, + {-1681.32, 13.0313, -9.48056}, + {-1677.04, 36.8349, -7.10318}, + {-1675.2, 68.559, -8.95384}, + {-1676.57, 89.023, -9.65104}, + {-1678.16, 110.939, -10.1782}, + {-1677.86, 128.681, -5.73869}, + {-1675.27, 144.324, -3.47916}, + {-1671.7, 163.169, -1.23098}, + {-1666.61, 181.584, 5.26145}, + {-1661.51, 196.154, 8.95252}, + {-1655.47, 210.811, 8.38727}, + {-1647.07, 226.947, 5.27755}, + {-1621.65, 232.91, 2.69579}, + {-1600.23, 237.641, 2.98539}, + {-1576.07, 242.546, 4.66541}, + {-1554.57, 248.494, 6.60377}, + {-1547.53, 259.302, 10.6741}, + {-1541.7, 269.847, 16.4418}, + {-1539.83, 278.989, 21.0597}, + {-1540.16, 290.219, 27.8247}, + {-1538.99, 298.983, 34.0032}, + {-1540.38, 307.337, 41.3557}, + {-1536.61, 314.884, 48.0179}, + {-1532.42, 323.277, 55.6667}, + {-1528.77, 329.774, 61.1525}, + {-1525.65, 333.18, 63.2161}, + {-1517.01, 350.713, 62.4286}, + {-1511.39, 362.537, 62.4539}, + {-1508.68, 366.822, 62.733} +}; + +struct npc_plains_visionAI : public ScriptedAI +{ + npc_plains_visionAI(Creature *c) : ScriptedAI(c) {} + + bool newWaypoint; + uint8 WayPointId; + uint8 amountWP; + + void Reset() + { + WayPointId = 0; + newWaypoint = true; + amountWP = 49; + } + + void EnterCombat(Unit* /*who*/){} + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id < amountWP) + { + ++WayPointId; + newWaypoint = true; + } + else + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (newWaypoint) + { + me->GetMotionMaster()->MovePoint(WayPointId, wp_plain_vision[WayPointId][0], wp_plain_vision[WayPointId][1], wp_plain_vision[WayPointId][2]); + newWaypoint = false; + } + } +}; + +CreatureAI* GetAI_npc_plains_vision(Creature* pCreature) +{ + return new npc_plains_visionAI (pCreature); +} + +/*##### +# +######*/ + +void AddSC_mulgore() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_skorn_whitecloud"; + newscript->pGossipHello = &GossipHello_npc_skorn_whitecloud; + newscript->pGossipSelect = &GossipSelect_npc_skorn_whitecloud; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_kyle_frenzied"; + newscript->GetAI = &GetAI_npc_kyle_frenzied; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_plains_vision"; + newscript->GetAI = &GetAI_npc_plains_vision; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp new file mode 100644 index 00000000000..2d351d6c6a2 --- /dev/null +++ b/src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp @@ -0,0 +1,500 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Onyxia +SD%Complete: 95 +SDComment: + Ground visual for Deep Breath effect; + Wing Buffet not ignoring armor; + Not summoning whelps on phase 3 (lacks info) + +SDCategory: Onyxia's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "onyxias_lair.h" + +enum eYells +{ + SAY_AGGRO = -1249000, + SAY_KILL = -1249001, + SAY_PHASE_2_TRANS = -1249002, + SAY_PHASE_3_TRANS = -1249003, + EMOTE_BREATH = -1249004, +}; + +enum eSpells +{ + // Phase 1 spells + SPELL_WING_BUFFET = 18500, + SPELL_FLAME_BREATH = 18435, + SPELL_CLEAVE = 68868, + SPELL_TAIL_SWEEP = 68867, + + // Phase 2 spells + SPELL_DEEP_BREATH = 23461, + SPELL_FIREBALL = 18392, + + //Not much choise about these. We have to make own defintion on the direction/start-end point + SPELL_BREATH_NORTH_TO_SOUTH = 17086, // 20x in "array" + SPELL_BREATH_SOUTH_TO_NORTH = 18351, // 11x in "array" + + SPELL_BREATH_EAST_TO_WEST = 18576, // 7x in "array" + SPELL_BREATH_WEST_TO_EAST = 18609, // 7x in "array" + + SPELL_BREATH_SE_TO_NW = 18564, // 12x in "array" + SPELL_BREATH_NW_TO_SE = 18584, // 12x in "array" + SPELL_BREATH_SW_TO_NE = 18596, // 12x in "array" + SPELL_BREATH_NE_TO_SW = 18617, // 12x in "array" + + //SPELL_BREATH = 21131, // 8x in "array", different initial cast than the other arrays + + // Phase 3 spells + SPELL_BELLOWING_ROAR = 18431, +}; + +struct sOnyxMove +{ + uint32 uiLocId; + uint32 uiLocIdEnd; + uint32 uiSpellId; + float fX, fY, fZ; +}; + +static sOnyxMove aMoveData[]= +{ + {0, 1, SPELL_BREATH_WEST_TO_EAST, -33.5561f, -182.682f, -56.9457f},//west + {1, 0, SPELL_BREATH_EAST_TO_WEST, -31.4963f, -250.123f, -55.1278f},//east + {2, 4, SPELL_BREATH_NW_TO_SE, 6.8951f, -180.246f, -55.896f},//north-west + {3, 5, SPELL_BREATH_NE_TO_SW, 10.2191f, -247.912f, -55.896f},//north-east + {4, 2, SPELL_BREATH_SE_TO_NW, -63.5156f, -240.096f, -55.477f},//south-east + {5, 3, SPELL_BREATH_SW_TO_NE, -58.2509f, -189.020f, -55.790f},//south-west + {6, 7, SPELL_BREATH_SOUTH_TO_NORTH, -65.8444f, -213.809f, -55.2985f},//south + {7, 6, SPELL_BREATH_NORTH_TO_SOUTH, 22.8763f, -217.152f, -55.0548f},//north +}; + +const Position MiddleRoomLocation = {-23.6155, -215.357, -55.7344}; + +static Position aSpawnLocations[3]= +{ + //Whelps + {-30.127, -254.463, -89.440}, + {-30.817, -177.106, -89.258}, + //Lair Guard + {-145.950, -212.831, -68.659} +}; + +struct boss_onyxiaAI : public ScriptedAI +{ + boss_onyxiaAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + SummonList Summons; + + uint32 m_uiPhase; + + uint32 m_uiFlameBreathTimer; + uint32 m_uiCleaveTimer; + uint32 m_uiTailSweepTimer; + uint32 m_uiWingBuffetTimer; + + uint32 m_uiMovePoint; + uint32 m_uiMovementTimer; + sOnyxMove* m_pPointData; + + uint32 m_uiFireballTimer; + uint32 m_uiWhelpTimer; + uint32 m_uiLairGuardTimer; + uint32 m_uiDeepBreathTimer; + + uint32 m_uiBellowingRoarTimer; + + uint8 m_uiSummonWhelpCount; + uint8 m_uiSummonLairGuardCount; + bool m_bIsMoving; + + void Reset() + { + if (!IsCombatMovement()) + SetCombatMovement(true); + + m_uiPhase = PHASE_START; + + m_uiFlameBreathTimer = urand(10000, 20000); + m_uiTailSweepTimer = urand(15000, 20000); + m_uiCleaveTimer = urand(2000, 5000); + m_uiWingBuffetTimer = urand(10000, 20000); + + m_uiMovePoint = urand(0, 5); + m_uiMovementTimer = 20000; + m_pPointData = GetMoveData(); + + m_uiFireballTimer = 15000; + m_uiWhelpTimer = 1000; + m_uiLairGuardTimer = 15000; + m_uiDeepBreathTimer = 85000; + + m_uiBellowingRoarTimer = 30000; + + Summons.DespawnAll(); + m_uiSummonWhelpCount = 0; + m_uiSummonLairGuardCount = 0; + m_bIsMoving = false; + + if (m_pInstance) + { + m_pInstance->SetData(DATA_ONYXIA, NOT_STARTED); + m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void EnterCombat(Unit* pWho) + { + DoScriptText(SAY_AGGRO, me); + me->SetInCombatWithZone(); + + if (m_pInstance) + { + m_pInstance->SetData(DATA_ONYXIA, IN_PROGRESS); + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + sLog.outBasic("[Onyxia] DoStartTimedAchievement(%u,%u)",ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void JustDied(Unit* killer) + { + if (m_pInstance) + m_pInstance->SetData(DATA_ONYXIA, DONE); + + Summons.DespawnAll(); + } + + void JustSummoned(Creature *pSummoned) + { + pSummoned->SetInCombatWithZone(); + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + pSummoned->AI()->AttackStart(pTarget); + + switch (pSummoned->GetEntry()) + { + case NPC_WHELP: + ++m_uiSummonWhelpCount; + break; + case NPC_LAIRGUARD: + pSummoned->setActive(true); + ++m_uiSummonLairGuardCount; + break; + } + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature *summon) + { + Summons.Despawn(summon); + } + + void KilledUnit(Unit* pVictim) + { + DoScriptText(SAY_KILL, me); + } + + void SpellHit(Unit *pCaster, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_BREATH_EAST_TO_WEST || + pSpell->Id == SPELL_BREATH_WEST_TO_EAST || + pSpell->Id == SPELL_BREATH_SE_TO_NW || + pSpell->Id == SPELL_BREATH_NW_TO_SE || + pSpell->Id == SPELL_BREATH_SW_TO_NE || + pSpell->Id == SPELL_BREATH_NE_TO_SW) + { + m_pPointData = GetMoveData(); + m_uiMovePoint = m_pPointData->uiLocIdEnd; + + me->SetSpeed(MOVE_FLIGHT, 1.5f); + me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type == POINT_MOTION_TYPE) + { + switch (id) + { + case 8: + m_pPointData = GetMoveData(); + if (m_pPointData) + { + me->SetSpeed(MOVE_FLIGHT, 1.0f); + me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); + } + break; + case 9: + me->GetMotionMaster()->MoveChase(me->getVictim()); + m_uiBellowingRoarTimer = 1000; + break; + default: + m_bIsMoving = false; + break; + } + } + } + + void SpellHitTarget(Unit* target, const SpellEntry* pSpell) + { + //Workaround - Couldn't find a way to group this spells (All Eruption) + if (((pSpell->Id >= 17086 && pSpell->Id <= 17095) || + (pSpell->Id == 17097) || + (pSpell->Id >= 18351 && pSpell->Id <= 18361) || + (pSpell->Id >= 18564 && pSpell->Id <= 18576) || + (pSpell->Id >= 18578 && pSpell->Id <= 18607) || + (pSpell->Id == 18609) || + (pSpell->Id >= 18611 && pSpell->Id <= 18628) || + (pSpell->Id >= 21132 && pSpell->Id <= 21133) || + (pSpell->Id >= 21135 && pSpell->Id <= 21139) || + (pSpell->Id >= 22191 && pSpell->Id <= 22202) || + (pSpell->Id >= 22267 && pSpell->Id <= 22268)) && + (target->GetTypeId() == TYPEID_PLAYER)) + { + if (m_pInstance) + { + m_pInstance->SetData(DATA_SHE_DEEP_BREATH_MORE, FAIL); + } + } + } + + sOnyxMove* GetMoveData() + { + uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); + + for (uint32 i = 0; i < uiMaxCount; ++i) + { + if (aMoveData[i].uiLocId == m_uiMovePoint) + return &aMoveData[i]; + } + + return NULL; + } + + void SetNextRandomPoint() + { + uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); + + int iTemp = rand()%(uiMaxCount-1); + + if (iTemp >= m_uiMovePoint) + ++iTemp; + + m_uiMovePoint = iTemp; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //Common to PHASE_START && PHASE_END + if (m_uiPhase == PHASE_START || m_uiPhase == PHASE_END) + { + //Specific to PHASE_START || PHASE_END + if (m_uiPhase == PHASE_START) + { + if (me->GetHealth()*100 / me->GetMaxHealth() < 60) + { + m_uiPhase = PHASE_BREATH; + + if (m_pInstance) + m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); + + SetCombatMovement(false); + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + me->SetFlying(true); + + DoScriptText(SAY_PHASE_2_TRANS, me); + + if (m_pPointData) + me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); + + m_uiWhelpTimer = 1000; + return; + } + } + else + { + if (m_uiBellowingRoarTimer <= uiDiff) + { + DoCastVictim(SPELL_BELLOWING_ROAR); + // Eruption + GameObject* pFloor = NULL; + Trinity::GameObjectInRangeCheck check(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 15); + Trinity::GameObjectLastSearcher searcher(me, pFloor, check); + me->VisitNearbyGridObject(30, searcher); + if (m_pInstance && pFloor) + m_pInstance->SetData64(DATA_FLOOR_ERUPTION_GUID, pFloor->GetGUID()); + m_uiBellowingRoarTimer = 30000; + } + else + m_uiBellowingRoarTimer -= uiDiff; + } + + if (m_uiFlameBreathTimer <= uiDiff) + { + DoCastVictim(SPELL_FLAME_BREATH); + m_uiFlameBreathTimer = urand(10000, 20000); + } + else + m_uiFlameBreathTimer -= uiDiff; + + if (m_uiTailSweepTimer <= uiDiff) + { + DoCastAOE(SPELL_TAIL_SWEEP); + m_uiTailSweepTimer = urand(15000, 20000); + } + else + m_uiTailSweepTimer -= uiDiff; + + if (m_uiCleaveTimer <= uiDiff) + { + DoCastVictim(SPELL_CLEAVE); + m_uiCleaveTimer = urand(2000, 5000); + } + else + m_uiCleaveTimer -= uiDiff; + + if (m_uiWingBuffetTimer <= uiDiff) + { + DoCastVictim(SPELL_WING_BUFFET); + m_uiWingBuffetTimer = urand(15000, 30000); + } + else + m_uiWingBuffetTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + else + { + if (me->GetHealth()*100 / me->GetMaxHealth() < 40) + { + m_uiPhase = PHASE_END; + if (m_pInstance) + m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); + DoScriptText(SAY_PHASE_3_TRANS, me); + + SetCombatMovement(true); + me->SetFlying(false); + m_bIsMoving = false; + me->GetMotionMaster()->MovePoint(9,me->GetHomePosition()); + return; + } + + if (m_uiDeepBreathTimer <= uiDiff) + { + if (!m_bIsMoving) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoScriptText(EMOTE_BREATH, me); + DoCast(me, m_pPointData->uiSpellId); + m_uiDeepBreathTimer = 70000; + } + } + else + m_uiDeepBreathTimer -= uiDiff; + + if (m_uiMovementTimer <= uiDiff) + { + if (!m_bIsMoving) + { + SetNextRandomPoint(); + m_pPointData = GetMoveData(); + + if (!m_pPointData) + return; + + me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); + m_bIsMoving = true; + m_uiMovementTimer = 25000; + } + } + else + m_uiMovementTimer -= uiDiff; + + if (m_uiFireballTimer <= uiDiff) + { + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FIREBALL); + + m_uiFireballTimer = 8000; + } + } + else + m_uiFireballTimer -= uiDiff; + + if (m_uiLairGuardTimer <= uiDiff) + { + me->SummonCreature(NPC_LAIRGUARD, aSpawnLocations[2].GetPositionX(), aSpawnLocations[2].GetPositionY(), aSpawnLocations[2].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); + if (m_uiSummonLairGuardCount >= RAID_MODE(1,2)) + { + m_uiSummonLairGuardCount = 0; + m_uiLairGuardTimer = 30000; + } + else + m_uiLairGuardTimer = 2000; + } + else + m_uiLairGuardTimer -= uiDiff; + + if (m_uiWhelpTimer <= uiDiff) + { + me->SummonCreature(NPC_WHELP, aSpawnLocations[0].GetPositionX(), aSpawnLocations[0].GetPositionY(), aSpawnLocations[0].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); + me->SummonCreature(NPC_WHELP, aSpawnLocations[1].GetPositionX(), aSpawnLocations[1].GetPositionY(), aSpawnLocations[1].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); + if (m_uiSummonWhelpCount >= RAID_MODE(20,40)) + { + m_uiSummonWhelpCount = 0; + m_uiWhelpTimer = 90000; + } + else + m_uiWhelpTimer = 500; + } + else + m_uiWhelpTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_boss_onyxiaAI(Creature* pCreature) +{ + return new boss_onyxiaAI (pCreature); +} + +void AddSC_boss_onyxia() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_onyxia"; + newscript->GetAI = &GetAI_boss_onyxiaAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp b/src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp new file mode 100644 index 00000000000..cfd66bf80f4 --- /dev/null +++ b/src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp @@ -0,0 +1,249 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Onyxias_Lair +SD%Complete: 100 +SDComment: +SDCategory: Onyxia's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "onyxias_lair.h" + +struct instance_onyxias_lair : public ScriptedInstance +{ + instance_onyxias_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + //Eruption is a BFS graph problem + //One map to remember all floor, one map to keep floor that still need to erupt and one queue to know what needs to be removed + std::map FloorEruptionGUID[2]; + std::queue FloorEruptionGUIDQueue; + + uint64 m_uiOnyxiasGUID; + uint32 m_uiOnyxiaLiftoffTimer; + uint32 m_uiManyWhelpsCounter; + uint32 m_uiEruptTimer; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + + bool m_bAchievManyWhelpsHandleIt; + bool m_bAchievSheDeepBreathMore; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiOnyxiasGUID = 0; + m_uiOnyxiaLiftoffTimer = 0; + m_uiManyWhelpsCounter = 0; + m_bAchievManyWhelpsHandleIt = false; + m_bAchievSheDeepBreathMore = true; + + m_uiEruptTimer = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + switch (pCreature->GetEntry()) + { + case NPC_ONYXIA: + m_uiOnyxiasGUID = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if ((pGo->GetGOInfo()->displayId == 4392 || pGo->GetGOInfo()->displayId == 4472) && pGo->GetGOInfo()->trap.spellId == 17731) + { + if (add) + FloorEruptionGUID[0].insert(std::make_pair(pGo->GetGUID(),0)); + else + FloorEruptionGUID[0].erase(pGo->GetGUID()); + return; + } + + switch(pGo->GetEntry()) + { + case GO_WHELP_SPAWNER: + Position pGoPos; + pGo->GetPosition(&pGoPos); + if (Creature* pTemp = pGo->SummonCreature(NPC_WHELP,pGoPos,TEMPSUMMON_CORPSE_DESPAWN)) + { + pTemp->SetInCombatWithZone(); + ++m_uiManyWhelpsCounter; + } + break; + } + } + + void FloorEruption(uint64 floorEruptedGUID) + { + if (GameObject *pFloorEruption = instance->GetGameObject(floorEruptedGUID)) + { + //THIS GOB IS A TRAP - What shall i do? =( + //Cast it spell? Copyed Heigan method + pFloorEruption->SendCustomAnim(); + pFloorEruption->CastSpell(NULL, Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL ? 17731 : 69294); //pFloorEruption->GetGOInfo()->trap.spellId + + //Get all immediatly nearby floors + std::list nearFloorList; + Trinity::GameObjectInRangeCheck check(pFloorEruption->GetPositionX(), pFloorEruption->GetPositionY(), pFloorEruption->GetPositionZ(), 15); + Trinity::GameObjectListSearcher searcher(pFloorEruption, nearFloorList, check); + pFloorEruption->VisitNearbyGridObject(999, searcher); + //remove all that are not present on FloorEruptionGUID[1] and update treeLen on each GUID + for (std::list::const_iterator itr = nearFloorList.begin(); itr != nearFloorList.end(); ++itr) + { + if (((*itr)->GetGOInfo()->displayId == 4392 || (*itr)->GetGOInfo()->displayId == 4472) && (*itr)->GetGOInfo()->trap.spellId == 17731) + { + uint64 nearFloorGUID = (*itr)->GetGUID(); + if (FloorEruptionGUID[1].find(nearFloorGUID) != FloorEruptionGUID[1].end() && (*FloorEruptionGUID[1].find(nearFloorGUID)).second == 0) + { + (*FloorEruptionGUID[1].find(nearFloorGUID)).second = (*FloorEruptionGUID[1].find(floorEruptedGUID)).second+1; + FloorEruptionGUIDQueue.push(nearFloorGUID); + } + } + } + } + FloorEruptionGUID[1].erase(floorEruptedGUID); + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case DATA_ONYXIA: + m_auiEncounter[0] = uiData; + if (uiData == IN_PROGRESS) + SetData(DATA_SHE_DEEP_BREATH_MORE, IN_PROGRESS); + break; + case DATA_ONYXIA_PHASE: + if (uiData == PHASE_BREATH) //Used to mark the liftoff phase + { + m_bAchievManyWhelpsHandleIt = false; + m_uiManyWhelpsCounter = 0; + m_uiOnyxiaLiftoffTimer = 10*IN_MILISECONDS; + } + break; + case DATA_SHE_DEEP_BREATH_MORE: + if (uiData == IN_PROGRESS) + { + m_bAchievSheDeepBreathMore = true; + } + else if (uiData == FAIL) + { + m_bAchievSheDeepBreathMore = false; + } + break; + } + + if (uiType < MAX_ENCOUNTER && uiData == DONE) + SaveToDB(); + } + + void SetData64(uint32 uiType, uint64 uiData) + { + switch(uiType) + { + case DATA_FLOOR_ERUPTION_GUID: + FloorEruptionGUID[1] = FloorEruptionGUID[0]; + FloorEruptionGUIDQueue.push(uiData); + m_uiEruptTimer = 2500; + break; + } + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case DATA_ONYXIA: + return m_auiEncounter[0]; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_ONYXIA_GUID: + return m_uiOnyxiasGUID; + } + + return 0; + } + + void Update(uint32 uiDiff) + { + if (GetData(DATA_ONYXIA) == IN_PROGRESS) + { + if (m_uiOnyxiaLiftoffTimer && m_uiOnyxiaLiftoffTimer <= uiDiff) + { + m_uiOnyxiaLiftoffTimer = 0; + if (m_uiManyWhelpsCounter >= 50) + m_bAchievManyWhelpsHandleIt = true; + } else m_uiOnyxiaLiftoffTimer -= uiDiff; + } + + if (!FloorEruptionGUIDQueue.empty()) + { + if (m_uiEruptTimer <= uiDiff) + { + uint32 treeHeight = 0; + do + { + treeHeight = (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second; + FloorEruption(FloorEruptionGUIDQueue.front()); + FloorEruptionGUIDQueue.pop(); + } while (!FloorEruptionGUIDQueue.empty() && (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second == treeHeight); + m_uiEruptTimer = 1000; + } + else + m_uiEruptTimer -= uiDiff; + } + } + + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* target = NULL, uint32 miscvalue1 = 0) + { + switch(criteria_id) + { + case ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER: // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s + case ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER: // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s + return m_bAchievManyWhelpsHandleIt; + case ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER: // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath + case ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER: // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath + return m_bAchievSheDeepBreathMore; + } + return false; + } +}; + +InstanceData* GetInstanceData_instance_onyxias_lair(Map* pMap) +{ + return new instance_onyxias_lair(pMap); +} + +void AddSC_instance_onyxias_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_onyxias_lair"; + newscript->GetInstanceData = &GetInstanceData_instance_onyxias_lair; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h b/src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h new file mode 100644 index 00000000000..cadd5b5a2d5 --- /dev/null +++ b/src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_ONYXIAS_LAIR_H +#define DEF_ONYXIAS_LAIR_H + +enum eData64 +{ + DATA_ONYXIA_GUID, + DATA_FLOOR_ERUPTION_GUID +}; + +enum eInstanceData +{ + DATA_ONYXIA, + MAX_ENCOUNTER, + + DATA_ONYXIA_PHASE, + DATA_SHE_DEEP_BREATH_MORE, + DATA_MANY_WHELPS_COUNT +}; + +enum eCreatures +{ + NPC_WHELP = 11262, + NPC_LAIRGUARD = 36561, + + NPC_ONYXIA = 10184 +}; + +enum eOnyxiaPhases +{ + PHASE_START = 1, + PHASE_BREATH = 2, + PHASE_END = 3 +}; + +enum eGameObjects +{ + GO_WHELP_SPAWNER = 176510, + GO_WHELP_EGG = 176511 +}; + +enum eAchievementData +{ + ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER = 12565, // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s + ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER = 12568, // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s + ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER = 12566, // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath + ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER = 12569, // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath + ACHIEV_TIMED_START_EVENT = 6601, // Timed event for achievement 4402, 4005: More Dots! (10,25 player) 5 min kill +}; +#endif diff --git a/src/server/scripts/Kalimdor/orgrimmar.cpp b/src/server/scripts/Kalimdor/orgrimmar.cpp new file mode 100644 index 00000000000..71fa4381e9d --- /dev/null +++ b/src/server/scripts/Kalimdor/orgrimmar.cpp @@ -0,0 +1,286 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Orgrimmar +SD%Complete: 100 +SDComment: Quest support: 2460, 5727, 6566 +SDCategory: Orgrimmar +EndScriptData */ + +/* ContentData +npc_neeru_fireblade npc_text + gossip options text missing +npc_shenthul +npc_thrall_warchief +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_neeru_fireblade +######*/ + +#define QUEST_5727 5727 + +#define GOSSIP_HNF "You may speak frankly, Neeru..." +#define GOSSIP_SNF "[PH] ..." +bool GossipHello_npc_neeru_fireblade(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_5727) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HNF, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(4513, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_neeru_fireblade(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SNF, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(4513, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(QUEST_5727); + break; + } + return true; +} + +/*###### +## npc_shenthul +######*/ + +enum eShenthul +{ + QUEST_SHATTERED_SALUTE = 2460 +}; + +struct npc_shenthulAI : public ScriptedAI +{ + npc_shenthulAI(Creature* c) : ScriptedAI(c) {} + + bool CanTalk; + bool CanEmote; + uint32 Salute_Timer; + uint32 Reset_Timer; + uint64 PlayerGUID; + + void Reset() + { + CanTalk = false; + CanEmote = false; + Salute_Timer = 6000; + Reset_Timer = 0; + PlayerGUID = 0; + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (CanEmote) + { + if (Reset_Timer <= diff) + { + if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) + { + if (pPlayer->GetTypeId() == TYPEID_PLAYER && pPlayer->GetQuestStatus(QUEST_SHATTERED_SALUTE) == QUEST_STATUS_INCOMPLETE) + pPlayer->FailQuest(QUEST_SHATTERED_SALUTE); + } + Reset(); + } else Reset_Timer -= diff; + } + + if (CanTalk && !CanEmote) + { + if (Salute_Timer <= diff) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + CanEmote = true; + Reset_Timer = 60000; + } else Salute_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + if (emote == TEXTEMOTE_SALUTE && pPlayer->GetQuestStatus(QUEST_SHATTERED_SALUTE) == QUEST_STATUS_INCOMPLETE) + { + if (CanEmote) + { + pPlayer->AreaExploredOrEventHappens(QUEST_SHATTERED_SALUTE); + Reset(); + } + } + } +}; + +CreatureAI* GetAI_npc_shenthul(Creature* pCreature) +{ + return new npc_shenthulAI (pCreature); +} + +bool QuestAccept_npc_shenthul(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_SHATTERED_SALUTE) + { + CAST_AI(npc_shenthulAI, pCreature->AI())->CanTalk = true; + CAST_AI(npc_shenthulAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); + } + return true; +} + +/*###### +## npc_thrall_warchief +######*/ + +#define QUEST_6566 6566 + +#define SPELL_CHAIN_LIGHTNING 16033 +#define SPELL_SHOCK 16034 + +#define GOSSIP_HTW "Please share your wisdom with me, Warchief." +#define GOSSIP_STW1 "What discoveries?" +#define GOSSIP_STW2 "Usurper?" +#define GOSSIP_STW3 "With all due respect, Warchief - why not allow them to be destroyed? Does this not strengthen our position?" +#define GOSSIP_STW4 "I... I did not think of it that way, Warchief." +#define GOSSIP_STW5 "I live only to serve, Warchief! My life is empty and meaningless without your guidance." +#define GOSSIP_STW6 "Of course, Warchief!" + +//TODO: verify abilities/timers +struct npc_thrall_warchiefAI : public ScriptedAI +{ + npc_thrall_warchiefAI(Creature* c) : ScriptedAI(c) {} + + uint32 ChainLightning_Timer; + uint32 Shock_Timer; + + void Reset() + { + ChainLightning_Timer = 2000; + Shock_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ChainLightning_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); + ChainLightning_Timer = 9000; + } else ChainLightning_Timer -= diff; + + if (Shock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHOCK); + Shock_Timer = 15000; + } else Shock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_thrall_warchief(Creature* pCreature) +{ + return new npc_thrall_warchiefAI (pCreature); +} + +bool GossipHello_npc_thrall_warchief(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_6566) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HTW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_thrall_warchief(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(5733, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(5734, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(5735, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(5736, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(5737, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + pPlayer->SEND_GOSSIP_MENU(5738, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(QUEST_6566); + break; + } + return true; +} + +void AddSC_orgrimmar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_neeru_fireblade"; + newscript->pGossipHello = &GossipHello_npc_neeru_fireblade; + newscript->pGossipSelect = &GossipSelect_npc_neeru_fireblade; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_shenthul"; + newscript->GetAI = &GetAI_npc_shenthul; + newscript->pQuestAccept = &QuestAccept_npc_shenthul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thrall_warchief"; + newscript->GetAI = &GetAI_npc_thrall_warchief; + newscript->pGossipHello = &GossipHello_npc_thrall_warchief; + newscript->pGossipSelect = &GossipSelect_npc_thrall_warchief; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp b/src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp new file mode 100644 index 00000000000..711c4f0b2c1 --- /dev/null +++ b/src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp @@ -0,0 +1,130 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Amnennar_the_coldbringer +SD%Complete: 100 +SDComment: +SDCategory: Razorfen Downs +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1129000 +#define SAY_SUMMON60 -1129001 +#define SAY_SUMMON30 -1129002 +#define SAY_HP -1129003 +#define SAY_KILL -1129004 + +#define SPELL_AMNENNARSWRATH 13009 +#define SPELL_FROSTBOLT 15530 +#define SPELL_FROST_NOVA 15531 +#define SPELL_FROST_SPECTRES 12642 + +struct boss_amnennar_the_coldbringerAI : public ScriptedAI +{ + boss_amnennar_the_coldbringerAI(Creature *c) : ScriptedAI(c) {} + + uint32 AmnenarsWrath_Timer; + uint32 FrostBolt_Timer; + uint32 FrostNova_Timer; + bool Spectrals60; + bool Spectrals30; + bool Hp; + + void Reset() + { + AmnenarsWrath_Timer = 8000; + FrostBolt_Timer = 1000; + FrostNova_Timer = 10000 + rand()%5000; + Spectrals30 = false; + Spectrals60 = false; + Hp = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit() + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //AmnenarsWrath_Timer + if (AmnenarsWrath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_AMNENNARSWRATH); + AmnenarsWrath_Timer = 12000; + } else AmnenarsWrath_Timer -= diff; + + //FrostBolt_Timer + if (FrostBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + FrostBolt_Timer = 8000; + } else FrostBolt_Timer -= diff; + + if (FrostNova_Timer <= diff) + { + DoCast(me, SPELL_FROST_NOVA); + FrostNova_Timer = 15000; + } else FrostNova_Timer -= diff; + + if (!Spectrals60 && me->GetHealth()*100 / me->GetMaxHealth() < 60) + { + DoScriptText(SAY_SUMMON60, me); + DoCast(me->getVictim(), SPELL_FROST_SPECTRES); + Spectrals60 = true; + } + + if (!Hp && me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + DoScriptText(SAY_HP, me); + Hp = true; + } + + if (!Spectrals30 && me->GetHealth()*100 / me->GetMaxHealth() < 30) + { + DoScriptText(SAY_SUMMON30, me); + DoCast(me->getVictim(), SPELL_FROST_SPECTRES); + Spectrals30 = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_amnennar_the_coldbringer(Creature* pCreature) +{ + return new boss_amnennar_the_coldbringerAI (pCreature); +} + +void AddSC_boss_amnennar_the_coldbringer() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_amnennar_the_coldbringer"; + newscript->GetAI = &GetAI_boss_amnennar_the_coldbringer; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp b/src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp new file mode 100644 index 00000000000..04904f08a57 --- /dev/null +++ b/src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "razorfen_downs.h" + +#define MAX_ENCOUNTER 1 + +struct instance_razorfen_downs : public ScriptedInstance +{ + instance_razorfen_downs(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + }; + + uint64 uiGongGUID; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint8 uiGongWaves; + + std::string str_data; + + void Initialize() + { + uiGongGUID = 0; + + uiGongWaves = 0; + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + saveStream << "T C " << m_auiEncounter[0] + << " " << uiGongWaves; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; + + if (dataHead1 == 'T' && dataHead2 == 'C') + { + m_auiEncounter[0] = data0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + uiGongWaves = data1; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*bAdd*/) + { + switch(pGo->GetEntry()) + { + case GO_GONG: + uiGongGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + break; + default: + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + if (uiType == DATA_GONG_WAVES) + { + uiGongWaves = uiData; + + switch(uiGongWaves) + { + case 9: + case 14: + if (GameObject* pGo = instance->GetGameObject(uiGongGUID)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + break; + case 1: + case 10: + case 16: + { + GameObject* pGo = instance->GetGameObject(uiGongGUID); + + if (!pGo) + return; + + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + + uint32 uiCreature = 0; + uint8 uiSummonTimes = 0; + + switch(uiGongWaves) + { + case 1: + uiCreature = CREATURE_TOMB_FIEND; + uiSummonTimes = 7; + break; + case 10: + uiCreature = CREATURE_TOMB_REAVER; + uiSummonTimes = 3; + break; + case 16: + uiCreature = CREATURE_TUTEN_KASH; + break; + default: + break; + } + + + if (Creature* pCreature = pGo->SummonCreature(uiCreature,2502.635,844.140,46.896,0.633)) + { + if (uiGongWaves == 10 || uiGongWaves == 1) + { + for (uint8 i = 0; i < uiSummonTimes; ++i) + { + if (Creature* pSummon = pGo->SummonCreature(uiCreature,2502.635 + float(irand(-5,5)),844.140 + float(irand(-5,5)),46.896,0.633)) + pSummon->GetMotionMaster()->MovePoint(0,2533.479 + float(irand(-5,5)),870.020 + float(irand(-5,5)),47.678); + } + } + pCreature->GetMotionMaster()->MovePoint(0,2533.479 + float(irand(-5,5)),870.020 + float(irand(-5,5)),47.678); + } + break; + } + default: + break; + } + } + + if (uiType == BOSS_TUTEN_KASH) + { + m_auiEncounter[0] = uiData; + + if (uiData == DONE) + SaveToDB(); + } + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case DATA_GONG_WAVES: + return uiGongWaves; + } + + return 0; + } + + uint64 GetData64(uint32 uiType) + { + switch(uiType) + { + case DATA_GONG: return uiGongGUID; + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_razorfen_downs(Map* pMap) +{ + return new instance_razorfen_downs(pMap); +} + +void AddSC_instance_razorfen_downs() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "instance_razorfen_downs"; + newscript->GetInstanceData = &GetInstanceData_instance_razorfen_downs; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp b/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp new file mode 100644 index 00000000000..3e8f4049a37 --- /dev/null +++ b/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp @@ -0,0 +1,165 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Razorfen_Downs +SD%Complete: 100 +SDComment: Support for Henry Stern(2 recipes) +SDCategory: Razorfen Downs +EndScriptData */ + +/* ContentData +npc_henry_stern +EndContentData */ + +#include "ScriptedPch.h" +#include "razorfen_downs.h" + +/*### +# npc_henry_stern +####*/ + +enum eEnums +{ + SPELL_GOLDTHORN_TEA = 13028, + SPELL_TEACHING_GOLDTHORN_TEA = 13029, + SPELL_MIGHT_TROLLS_BLOOD_POTION = 3451, + SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION = 13030, + GOSSIP_TEXT_TEA_ANSWER = 2114, + GOSSIP_TEXT_POTION_ANSWER = 2115, +}; + +#define GOSSIP_ITEM_TEA "Teach me the cooking recipe" +#define GOSSIP_ITEM_POTION "Teach me the alchemy recipe" + +bool GossipHello_npc_henry_stern (Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetBaseSkillValue(SKILL_COOKING) >= 175 && !pPlayer->HasSpell(SPELL_GOLDTHORN_TEA)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (pPlayer->GetBaseSkillValue(SKILL_ALCHEMY) >= 180 && !pPlayer->HasSpell(SPELL_MIGHT_TROLLS_BLOOD_POTION)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_POTION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_henry_stern (Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CastSpell(pPlayer, SPELL_TEACHING_GOLDTHORN_TEA, true); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_TEA_ANSWER, pCreature->GetGUID()); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF + 2) + { + pPlayer->CastSpell(pPlayer, SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION, true); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_POTION_ANSWER, pCreature->GetGUID()); + } + + return true; +} + +/*###### +## go_gong +######*/ + +bool GOHello_go_gong(Player* /*pPlayer*/, GameObject* pGO) +{ + //basic support, not blizzlike data is missing... + ScriptedInstance* pInstance = pGO->GetInstanceData(); + + if (pInstance) + { + pInstance->SetData(DATA_GONG_WAVES,pInstance->GetData(DATA_GONG_WAVES)+1); + return true; + } + + return false; +} + +enum eTombCreature +{ + SPELL_WEB = 745 +}; + +struct npc_tomb_creatureAI : public ScriptedAI +{ + npc_tomb_creatureAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiWebTimer; + + void Reset() + { + uiWebTimer = urand(5000,8000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //from acid + if (me->GetEntry() == CREATURE_TOMB_REAVER) + { + if (uiWebTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_WEB); + uiWebTimer = urand(7000,16000); + } else uiWebTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(DATA_GONG_WAVES,pInstance->GetData(DATA_GONG_WAVES)+1); + } +}; + +CreatureAI* GetAI_npc_tomb_creature(Creature* pCreature) +{ + return new npc_tomb_creatureAI (pCreature); +} + +void AddSC_razorfen_downs() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_henry_stern"; + newscript->pGossipHello = &GossipHello_npc_henry_stern; + newscript->pGossipSelect = &GossipSelect_npc_henry_stern; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_gong"; + newscript->pGOHello = &GOHello_go_gong; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tomb_creature"; + newscript->GetAI = &GetAI_npc_tomb_creature; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h b/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h new file mode 100644 index 00000000000..a67b4223c4a --- /dev/null +++ b/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_RAZORFEN_DOWNS_H +#define DEF_RAZORFEN_DOWNS_H + +enum eData +{ + BOSS_TUTEN_KASH, + DATA_GONG_WAVES +}; + +enum eData64 +{ + DATA_GONG +}; + +enum eGameObject +{ + GO_GONG = 148917 +}; + +enum eCreature +{ + CREATURE_TOMB_FIEND = 7349, + CREATURE_TOMB_REAVER = 7351, + CREATURE_TUTEN_KASH = 7355 +}; + +#endif diff --git a/src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp b/src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp new file mode 100644 index 00000000000..8a92d3d4d89 --- /dev/null +++ b/src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Razorfen_Kraul +SD%Complete: +SDComment: +SDCategory: Razorfen Kraul +EndScriptData */ + +#include "ScriptedPch.h" +#include "razorfen_kraul.h" + +#define WARD_KEEPERS_NR 2 + +struct instance_razorfen_kraul : public ScriptedInstance +{ + instance_razorfen_kraul(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 DoorWardGUID; + uint32 WardCheck_Timer; + int WardKeeperAlive; + + void Initialize() + { + WardKeeperAlive = 1; + WardCheck_Timer = 4000; + DoorWardGUID = 0; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + debug_log("TSCR: Instance Razorfen Kraul: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*apply*/) + { + switch(pGo->GetEntry()) + { + case 21099: DoorWardGUID = pGo->GetGUID(); break; + } + } + + void Update(uint32 diff) + { + if (WardCheck_Timer <= diff) + { + HandleGameObject(DoorWardGUID, WardKeeperAlive); + WardKeeperAlive = 0; + WardCheck_Timer = 4000; + }else + WardCheck_Timer -= diff; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_WARD_KEEPERS: + if (data == NOT_STARTED) + WardKeeperAlive = 1; + break; + } + } + +}; + +InstanceData* GetInstanceData_instance_razorfen_kraul(Map* pMap) +{ + return new instance_razorfen_kraul(pMap); +} + +void AddSC_instance_razorfen_kraul() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_razorfen_kraul"; + newscript->GetInstanceData = &GetInstanceData_instance_razorfen_kraul; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp b/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp new file mode 100644 index 00000000000..8470fa6c7ac --- /dev/null +++ b/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp @@ -0,0 +1,194 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Razorfen Kraul +SD%Complete: 100 +SDComment: Quest support: 1144 +SDCategory: Razorfen Kraul +EndScriptData */ + +/* ContentData +npc_willix +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "razorfen_kraul.h" + +#define SAY_READY -1047000 +#define SAY_POINT -1047001 +#define SAY_AGGRO1 -1047002 +#define SAY_BLUELEAF -1047003 +#define SAY_DANGER -1047004 +#define SAY_BAD -1047005 +#define SAY_THINK -1047006 +#define SAY_SOON -1047007 +#define SAY_FINALY -1047008 +#define SAY_WIN -1047009 +#define SAY_END -1047010 + +#define QUEST_WILLIX_THE_IMPORTER 1144 +#define ENTRY_BOAR 4514 +#define SPELL_QUILLBOAR_CHANNELING 7083 + +struct npc_willixAI : public npc_escortAI +{ + npc_willixAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch (i) + { + case 3: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + DoScriptText(SAY_POINT, me, pPlayer); + break; + case 4: + me->SummonCreature(ENTRY_BOAR, 2137.66, 1843.98, 48.08, 1.54, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + case 8: + DoScriptText(SAY_BLUELEAF, me, pPlayer); + break; + case 9: + DoScriptText(SAY_DANGER, me, pPlayer); + break; + case 13: + DoScriptText(SAY_BAD, me, pPlayer); + break; + case 14: + me->SummonCreature(ENTRY_BOAR, 2078.91, 1704.54, 56.77, 1.54, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + case 25: + DoScriptText(SAY_THINK, me, pPlayer); + break; + case 31: + DoScriptText(SAY_SOON, me, pPlayer); + break; + case 42: + DoScriptText(SAY_FINALY, me, pPlayer); + break; + case 43: + me->SummonCreature(ENTRY_BOAR, 1956.43, 1596.97, 81.75, 1.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + case 45: + DoScriptText(SAY_WIN, me, pPlayer); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(pPlayer)->GroupEventHappens(QUEST_WILLIX_THE_IMPORTER,me); + break; + case 46: + DoScriptText(SAY_END, me, pPlayer); + break; + } + } + + void Reset() {} + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO1, me, NULL); + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void JustDied(Unit* /*killer*/) + { + if (Player* pPlayer = GetPlayerForEscort()) + CAST_PLR(pPlayer)->FailQuest(QUEST_WILLIX_THE_IMPORTER); + } +}; + +bool QuestAccept_npc_willix(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_WILLIX_THE_IMPORTER) + { + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + DoScriptText(SAY_READY, pCreature, pPlayer); + pCreature->setFaction(113); + } + + return true; +} + +struct npc_deaths_head_ward_keeperAI : public ScriptedAI +{ + npc_deaths_head_ward_keeperAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 QuillboarChanneling_Timer; + + void Reset() + { + QuillboarChanneling_Timer = 1500; + } + + void UpdateAI(const uint32 diff) + { + if (!me->isAlive()) + return; + + if (pInstance) + pInstance->SetData(TYPE_WARD_KEEPERS, NOT_STARTED); + + if (QuillboarChanneling_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_QUILLBOAR_CHANNELING); + QuillboarChanneling_Timer = 1100; + } else QuillboarChanneling_Timer -= diff; + + } +}; + +CreatureAI* GetAI_npc_deaths_head_ward_keeper(Creature* pCreature) +{ + return new npc_deaths_head_ward_keeperAI(pCreature); +} + +CreatureAI* GetAI_npc_willix(Creature* pCreature) +{ + return new npc_willixAI(pCreature); +} + +void AddSC_razorfen_kraul() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_willix"; + newscript->GetAI = &GetAI_npc_willix; + newscript->pQuestAccept = &QuestAccept_npc_willix; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_deaths_head_ward_keeper"; + newscript->GetAI = &GetAI_npc_deaths_head_ward_keeper; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h b/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h new file mode 100644 index 00000000000..e2219986f63 --- /dev/null +++ b/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_RAZORFEN_KRAUL_H +#define DEF_RAZORFEN_KRAUL_H + +#define TYPE_WARD_KEEPERS 1 +#endif diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp new file mode 100644 index 00000000000..f6dc75558c8 --- /dev/null +++ b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp @@ -0,0 +1,125 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ayamiss +SD%Complete: 50 +SDComment: VERIFY SCRIPT +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +/* +To do: +make him fly from 70-100% +*/ + +enum Spells +{ + SPELL_STINGERSPRAY = 25749, + SPELL_POISONSTINGER = 25748, //only used in phase1 + SPELL_SUMMONSWARMER = 25844, //might be 25708 + SPELL_PARALYZE = 23414 //doesnt work correct (core) +}; + +struct boss_ayamissAI : public ScriptedAI +{ + boss_ayamissAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 STINGERSPRAY_Timer; + uint32 POISONSTINGER_Timer; + uint32 SUMMONSWARMER_Timer; + uint32 phase; + + ScriptedInstance *pInstance; + + void Reset() + { + STINGERSPRAY_Timer = 30000; + POISONSTINGER_Timer = 30000; + SUMMONSWARMER_Timer = 60000; + phase=1; + + if (pInstance) + pInstance->SetData(DATA_AYAMISS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_AYAMISS_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_AYAMISS_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If he is 70% start phase 2 + if (phase == 1 && me->GetHealth()*100 / me->GetMaxHealth() <= 70 && !me->IsNonMeleeSpellCasted(false)) + { + phase=2; + } + + //STINGERSPRAY_Timer (only in phase2) + if (phase == 2 && STINGERSPRAY_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STINGERSPRAY); + STINGERSPRAY_Timer = 30000; + } else STINGERSPRAY_Timer -= diff; + + //POISONSTINGER_Timer (only in phase1) + if (phase == 1 && POISONSTINGER_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISONSTINGER); + POISONSTINGER_Timer = 30000; + } else POISONSTINGER_Timer -= diff; + + //SUMMONSWARMER_Timer (only in phase1) + if (SUMMONSWARMER_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUMMONSWARMER); + SUMMONSWARMER_Timer = 60000; + } else SUMMONSWARMER_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ayamiss(Creature* pCreature) +{ + return new boss_ayamissAI (pCreature); +} + +void AddSC_boss_ayamiss() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ayamiss"; + newscript->GetAI = &GetAI_boss_ayamiss; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp new file mode 100644 index 00000000000..86a2c559543 --- /dev/null +++ b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp @@ -0,0 +1,72 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Buru +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Yells +{ + EMOTE_TARGET = -1509002 +}; + +struct boss_buruAI : public ScriptedAI +{ + boss_buruAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_BURU_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_BURU_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_BURU_EVENT, DONE); + } +}; +CreatureAI* GetAI_boss_buru(Creature* pCreature) +{ + return new boss_buruAI (pCreature); +} + +void AddSC_boss_buru() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_buru"; + newscript->GetAI = &GetAI_boss_buru; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp new file mode 100644 index 00000000000..44f11bf4b60 --- /dev/null +++ b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp @@ -0,0 +1,143 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kurinnaxx +SD%Complete: 100 +SDComment: VERIFY SCRIPT AND SQL +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Spells +{ + SPELL_MORTALWOUND = 25646, + SPELL_SANDTRAP = 25656, + SPELL_ENRAGE = 28798, + SPELL_SUMMON_PLAYER = 26446, + SPELL_TRASH = 3391, + SPELL_WIDE_SLASH = 25814 +}; + +struct boss_kurinnaxxAI : public ScriptedAI +{ + boss_kurinnaxxAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiMortalWoundTimer; + uint32 uiSandtrapTimer; + uint32 uiWideSlashTimer; + uint32 uiSummonPlayerTimer; + uint32 uiTrashTimer; + bool bIsEnraged; + + ScriptedInstance* pInstance; + + void Reset() + { + bIsEnraged = false; + uiMortalWoundTimer = urand(2000,7000); + uiSandtrapTimer = urand(20000,30000); + uiWideSlashTimer = urand(10000,15000); + uiTrashTimer = urand(20000,25000); + uiSummonPlayerTimer = urand(30000,40000); + + if (pInstance) + pInstance->SetData(DATA_KURINNAXX_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_KURINNAXX_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_KURINNAXX_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <30% cast enrage + if (!bIsEnraged && me->GetHealth()*100 / me->GetMaxHealth() <= 30 && !me->IsNonMeleeSpellCasted(false)) + { + bIsEnraged = true; + DoCast(me, SPELL_ENRAGE); + } + + //Mortal Wound spell + if (uiMortalWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALWOUND); + uiMortalWoundTimer = urand(2000,7000); + } else uiMortalWoundTimer -= diff; + + //Santrap spell + if (uiSandtrapTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SANDTRAP); + uiSandtrapTimer = 30000; + } else uiSandtrapTimer -= diff; + + //Wide Slash spell + if (uiWideSlashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WIDE_SLASH); + uiWideSlashTimer = urand(10000,15000); + } else uiWideSlashTimer -= diff; + + //Trash spell + if (uiTrashTimer <= diff) + { + DoCast(me, SPELL_TRASH); + uiTrashTimer = urand(20000,25000); + } else uiTrashTimer -= diff; + + //Summon Player spell + if (uiSummonPlayerTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SUMMON_PLAYER); + uiSummonPlayerTimer = urand(30000,40000); + } else uiSummonPlayerTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_kurinnaxx(Creature* pCreature) +{ + return new boss_kurinnaxxAI (pCreature); +} + +void AddSC_boss_kurinnaxx() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kurinnaxx"; + newscript->GetAI = &GetAI_boss_kurinnaxx; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp new file mode 100644 index 00000000000..1882adc8fbb --- /dev/null +++ b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp @@ -0,0 +1,162 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moam +SD%Complete: 90 +SDComment: TODO: Adjust timer, correct Stone phase buff +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Emotes +{ + EMOTE_AGGRO = -1509000, + EMOTE_MANA_FULL = -1509001 +}; + +enum Spells +{ + SPELL_TRAMPLE = 15550, + SPELL_DRAINMANA = 27256, //Doesn't exist ? + SPELL_ARCANEERUPTION = 25672, + SPELL_SUMMONMANA = 25681, //Summon Mana fiend. It only summons one so exec it three times + SPELL_GRDRSLEEP = 24360 //Greater Dreamless Sleep +}; + +enum Creatures +{ + CREATURE_MANA_FIEND = 15527 +}; + +enum CombatPhase +{ + NORMAL, + STONE +}; + +struct boss_moamAI : public ScriptedAI +{ + boss_moamAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiTrampleTimer; + uint32 uiDrainManaTimer; + uint32 uiPhaseTimer; + CombatPhase Phase; + + ScriptedInstance *pInstance; + + void Reset() + { + uiTrampleTimer = urand(3000,7000); + uiDrainManaTimer = urand(3000,7000); + uiPhaseTimer = 90000; + Phase = NORMAL; + me->SetPower(POWER_MANA,0); + + if (pInstance) + pInstance->SetData(DATA_MOAM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(EMOTE_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MOAM_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_MOAM_EVENT, DONE); + } + + void DrainMana() + { + for (uint8 i=0;i<6;++i) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + pTarget->ModifyPower(POWER_MANA, -500); + me->ModifyPower(POWER_MANA, 1000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Phase == NORMAL) + { + if (!UpdateVictim()) + return; + + //If we are 100%MANA cast Arcane Erruption + if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA)) + { + DoCast(me->getVictim(), SPELL_ARCANEERUPTION); + DoScriptText(EMOTE_MANA_FULL, me); + me->SetPower(POWER_MANA,0); + } + + //Trample Spell + if (uiTrampleTimer <= diff) + { + DoCast(me->getVictim(), SPELL_TRAMPLE); + uiTrampleTimer = urand(3000,7000); + } else uiTrampleTimer -= diff; + + //Drain Mana + if (uiDrainManaTimer <= diff) + { + DrainMana(); + uiDrainManaTimer = urand(3000,7000); + } else uiDrainManaTimer -= diff; + + DoMeleeAttackIfReady(); + + //After 90secs change phase + if (uiPhaseTimer <= diff) + { + Phase = STONE; + DoCast(me, SPELL_SUMMONMANA); + DoCast(me, SPELL_SUMMONMANA); + DoCast(me, SPELL_SUMMONMANA); + DoCast(me, SPELL_GRDRSLEEP); + } else uiPhaseTimer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_moam(Creature* pCreature) +{ + return new boss_moamAI (pCreature); +} + +void AddSC_boss_moam() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_moam"; + newscript->GetAI = &GetAI_boss_moam; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp new file mode 100644 index 00000000000..57ba8d9da7f --- /dev/null +++ b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp @@ -0,0 +1,79 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ossirian +SD%Complete: 0 +SDComment: Place holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Yells +{ + SAY_SURPREME2 = -1509019, + SAY_SURPREME3 = -1509020, + SAY_RAND_INTRO1 = -1509021, + SAY_RAND_INTRO2 = -1509022, + SAY_RAND_INTRO3 = -1509023, + SAY_RAND_INTRO4 = -1509024, //possibly old? + SAY_AGGRO = -1509025, + SAY_SLAY = -1509026, + SAY_DEATH = -1509027 +}; + +struct boss_ossirianAI : public ScriptedAI +{ + boss_ossirianAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_OSSIRIAN_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_OSSIRIAN_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_OSSIRIAN_EVENT, DONE); + } +}; +CreatureAI* GetAI_boss_ossirian(Creature* pCreature) +{ + return new boss_ossirianAI (pCreature); +} + +void AddSC_boss_ossirian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ossirian"; + newscript->GetAI = &GetAI_boss_ossirian; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp new file mode 100644 index 00000000000..5be60dc0ca0 --- /dev/null +++ b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Rajaxx +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Yells +{ + SAY_ANDOROV_INTRO = -1509003, + SAY_ANDOROV_ATTACK = -1509004, + SAY_WAVE3 = -1509005, + SAY_WAVE4 = -1509006, + SAY_WAVE5 = -1509007, + SAY_WAVE6 = -1509008, + SAY_WAVE7 = -1509009, + SAY_INTRO = -1509010, + SAY_UNK1 = -1509011, + SAY_UNK2 = -1509012, + SAY_UNK3 = -1509013, + SAY_UNK4 = -1509014, + SAY_DEAGGRO = -1509015, + SAY_KILLS_ANDOROV = -1509016, + SAY_COMPLETE_QUEST = -1509017 //Yell when realm complete quest 8743 for world event +}; + +struct boss_rajaxxAI : public ScriptedAI +{ + boss_rajaxxAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_RAJAXX_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_RAJAXX_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_RAJAXX_EVENT, DONE); + } +}; +CreatureAI* GetAI_boss_rajaxx(Creature* pCreature) +{ + return new boss_rajaxxAI (pCreature); +} + +void AddSC_boss_rajaxx() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_rajaxx"; + newscript->GetAI = &GetAI_boss_rajaxx; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp new file mode 100644 index 00000000000..ba7471bdbd2 --- /dev/null +++ b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp @@ -0,0 +1,213 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Ruins_of_Ahnqiraj +SD%Complete: 0 +SDComment: Place holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +#define MAX_ENCOUNTER 6 + +/* Ruins of Ahn'Qiraj encounters: +0 - Kurinnaxx +1 - General Rajaxx +2 - Moam +3 - Buru the Gorger +4 - Ayamiss the Hunter +5 - Ossirian the Unscarred */ + +struct instance_ruins_of_ahn_qiraj : public ScriptedInstance +{ + instance_ruins_of_ahn_qiraj(Map* pMap) : ScriptedInstance(pMap) { Initialize(); } + + uint64 uiKurinaxx; + uint64 uiRajaxx; + uint64 uiMoam; + uint64 uiBuru; + uint64 uiAyamiss; + uint64 uiOssirian; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + uiKurinaxx = 0; + uiRajaxx = 0; + uiMoam = 0; + uiBuru = 0; + uiAyamiss = 0; + uiOssirian = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case CREATURE_KURINAXX: + uiKurinaxx = pCreature->GetGUID(); + break; + case CREATURE_RAJAXX: + uiRajaxx = pCreature->GetGUID(); + break; + case CREATURE_MOAM: + uiMoam = pCreature->GetGUID(); + break; + case CREATURE_BURU: + uiBuru = pCreature->GetGUID(); + break; + case CREATURE_AYAMISS: + uiAyamiss = pCreature->GetGUID(); + break; + case CREATURE_OSSIRIAN: + uiOssirian = pCreature->GetGUID(); + break; + } + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_KURINNAXX_EVENT: return m_auiEncounter[0]; + case DATA_RAJAXX_EVENT: return m_auiEncounter[1]; + case DATA_MOAM_EVENT: return m_auiEncounter[2]; + case DATA_BURU_EVENT: return m_auiEncounter[3]; + case DATA_AYAMISS_EVENT: return m_auiEncounter[4]; + case DATA_OSSIRIAN_EVENT: return m_auiEncounter[5]; + } + + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch(identifier) + { + case DATA_KURINNAXX_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_RAJAXX_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_MOAM_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_BURU_EVENT: + m_auiEncounter[3] = data; + break; + case DATA_AYAMISS_EVENT: + m_auiEncounter[4] = data; + break; + case DATA_OSSIRIAN_EVENT: + m_auiEncounter[5] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint64 GetData64(uint32 uiIdentifier) + { + switch(uiIdentifier) + { + case DATA_KURINNAXX: return uiKurinaxx; + case DATA_RAJAXX: return uiRajaxx; + case DATA_MOAM: return uiMoam; + case DATA_BURU: return uiBuru; + case DATA_AYAMISS: return uiAyamiss; + case DATA_OSSIRIAN: return uiOssirian; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "R A " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + + if (dataHead1 == 'R' && dataHead2 == 'A') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + m_auiEncounter[5] = data5; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + } +}; + +InstanceData* GetInstanceData_instance_ruins_of_ahn_qiraj(Map* pMap) +{ + return new instance_ruins_of_ahn_qiraj(pMap); +} + +void AddSC_instance_ruins_of_ahnqiraj() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_ruins_of_ahnqiraj"; + newscript->GetInstanceData = &GetInstanceData_instance_ruins_of_ahn_qiraj; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h new file mode 100644 index 00000000000..33fd75d557a --- /dev/null +++ b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h @@ -0,0 +1,34 @@ +#ifndef DEF_RUINS_OF_AHNQIRAJ_H +#define DEF_RUINS_OF_AHNQIRAJ_H + +enum Data +{ + DATA_KURINNAXX_EVENT, + DATA_RAJAXX_EVENT, + DATA_MOAM_EVENT, + DATA_BURU_EVENT, + DATA_AYAMISS_EVENT, + DATA_OSSIRIAN_EVENT +}; + +enum Data64 +{ + DATA_KURINNAXX, + DATA_RAJAXX, + DATA_MOAM, + DATA_BURU, + DATA_AYAMISS, + DATA_OSSIRIAN +}; + +enum Bosses +{ + CREATURE_KURINAXX = 15348, + CREATURE_RAJAXX = 15341, + CREATURE_MOAM = 15340, + CREATURE_BURU = 15370, + CREATURE_AYAMISS = 15369, + CREATURE_OSSIRIAN = 15339 +}; + +#endif diff --git a/src/server/scripts/Kalimdor/silithus.cpp b/src/server/scripts/Kalimdor/silithus.cpp new file mode 100644 index 00000000000..6383284011f --- /dev/null +++ b/src/server/scripts/Kalimdor/silithus.cpp @@ -0,0 +1,1140 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Silithus +SD%Complete: 100 +SDComment: Quest support: 7785, 8304, 8507. +SDCategory: Silithus +EndScriptData */ + +/* ContentData +npc_highlord_demitrian +npcs_rutgar_and_frankal +quest_a_pawn_on_the_eternal_pawn +EndContentData */ + +#include "ScriptedPch.h" + +/*### +## npc_highlord_demitrian +###*/ + +#define GOSSIP_DEMITRIAN1 "What do you know of it?" +#define GOSSIP_DEMITRIAN2 "I am listening , Demitrian." +#define GOSSIP_DEMITRIAN3 "Continue, please." +#define GOSSIP_DEMITRIAN4 "A battle?" +#define GOSSIP_DEMITRIAN5 "" +#define GOSSIP_DEMITRIAN6 "Caught unaware? How?" +#define GOSSIP_DEMITRIAN7 "So what did Ragnaros do next?" + +bool GossipHello_npc_highlord_demitrian(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(7785) == QUEST_STATUS_NONE && + (pPlayer->HasItemCount(18563,1,false) || pPlayer->HasItemCount(18564,1,false))) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(6812, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_highlord_demitrian(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(6842, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(6843, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(6844, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(6867, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(6868, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(6869, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->SEND_GOSSIP_MENU(6870, pCreature->GetGUID()); + + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 19016, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, 19016, true); + break; + } + return true; +} + +/*### +## npcs_rutgar_and_frankal +###*/ + +//gossip item text best guess +#define GOSSIP_ITEM1 "I seek information about Natalia" + +#define GOSSIP_ITEM2 "That sounds dangerous!" +#define GOSSIP_ITEM3 "What did you do?" +#define GOSSIP_ITEM4 "Who?" +#define GOSSIP_ITEM5 "Women do that. What did she demand?" +#define GOSSIP_ITEM6 "What do you mean?" +#define GOSSIP_ITEM7 "What happened next?" + +#define GOSSIP_ITEM11 "Yes, please continue" +#define GOSSIP_ITEM12 "What language?" +#define GOSSIP_ITEM13 "The Priestess attacked you?!" +#define GOSSIP_ITEM14 "I should ask the monkey about this" +#define GOSSIP_ITEM15 "Then what..." + +//trigger creatures to kill +#define TRIGGER_RUTGAR 15222 +#define TRIGGER_FRANKAL 15221 + +bool GossipHello_npcs_rutgar_and_frankal(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(8304) == QUEST_STATUS_INCOMPLETE && + pCreature->GetEntry() == 15170 && + !pPlayer->GetReqKillOrCastCurrentCount(8304, TRIGGER_RUTGAR)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + if (pPlayer->GetQuestStatus(8304) == QUEST_STATUS_INCOMPLETE && + pCreature->GetEntry() == 15171 && + pPlayer->GetReqKillOrCastCurrentCount(8304, TRIGGER_RUTGAR)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); + + pPlayer->SEND_GOSSIP_MENU(7754, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_rutgar_and_frankal(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(7755, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(7756, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(7757, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(7758, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + pPlayer->SEND_GOSSIP_MENU(7759, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + pPlayer->SEND_GOSSIP_MENU(7760, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + pPlayer->SEND_GOSSIP_MENU(7761, pCreature->GetGUID()); + //'kill' our trigger to update quest status + pPlayer->KilledMonsterCredit(TRIGGER_RUTGAR, pCreature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF + 9: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + pPlayer->SEND_GOSSIP_MENU(7762, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 10: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + pPlayer->SEND_GOSSIP_MENU(7763, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + pPlayer->SEND_GOSSIP_MENU(7764, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + pPlayer->SEND_GOSSIP_MENU(7765, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); + pPlayer->SEND_GOSSIP_MENU(7766, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 14: + pPlayer->SEND_GOSSIP_MENU(7767, pCreature->GetGUID()); + //'kill' our trigger to update quest status + pPlayer->KilledMonsterCredit(TRIGGER_FRANKAL, pCreature->GetGUID()); + break; + } + return true; +} + +/*#### +# quest_a_pawn_on_the_eternal_board (Defines) +####*/ +enum eEternalBoard +{ + QUEST_A_PAWN_ON_THE_ETERNAL_BOARD = 8519, + + FACTION_HOSTILE = 14, + FACTION_FRIENDLY = 35, + + C_ANACHRONOS = 15381, + C_FANDRAL_STAGHELM = 15382, + C_ARYGOS = 15380, + C_MERITHRA = 15378, + C_CAELESTRASZ = 15379, + + ANACHRONOS_SAY_1 = -1350000, + ANACHRONOS_SAY_2 = -1350001, + ANACHRONOS_SAY_3 = -1350002, + ANACHRONOS_SAY_4 = -1350003, + ANACHRONOS_SAY_5 = -1350004, + ANACHRONOS_SAY_6 = -1350005, + ANACHRONOS_SAY_7 = -1350006, + ANACHRONOS_SAY_8 = -1350007, + ANACHRONOS_SAY_9 = -1350008, + ANACHRONOS_SAY_10 = -1350009, + ANACHRONOS_EMOTE_1 = -1350010, + ANACHRONOS_EMOTE_2 = -1350011, + ANACHRONOS_EMOTE_3 = -1350012, + + FANDRAL_SAY_1 = -1350013, + FANDRAL_SAY_2 = -1350014, + FANDRAL_SAY_3 = -1350015, + FANDRAL_SAY_4 = -1350016, + FANDRAL_SAY_5 = -1350017, + FANDRAL_SAY_6 = -1350018, + FANDRAL_EMOTE_1 = -1350019, + FANDRAL_EMOTE_2 = -1350020, + + CAELESTRASZ_SAY_1 = -1350021, + CAELESTRASZ_SAY_2 = -1350022, + CAELESTRASZ_YELL_1 = -1350023, + + ARYGOS_SAY_1 = -1350024, + ARYGOS_YELL_1 = -1350025, + ARYGOS_EMOTE_1 = -1350026, + + MERITHRA_SAY_1 = -1350027, + MERITHRA_SAY_2 = -1350028, + MERITHRA_YELL_1 = -1350029, + MERITHRA_EMOTE_1 = -1350030, + + GO_GATE_OF_AHN_QIRAJ = 176146, + GO_GLYPH_OF_AHN_QIRAJ = 176148, + GO_ROOTS_OF_AHN_QIRAJ = 176147 +}; +/*##### +# Quest: A Pawn on the Eternal Board +#####*/ + +/* ContentData +A Pawn on the Eternal Board - creatures, gameobjects and defines +mob_qiraj_war_spawn : Adds that are summoned in the Qiraj gates battle. +npc_anachronos_the_ancient : Creature that controls the event. +npc_anachronos_quest_trigger: controls the spawning of the BG War mobs. +go_crystalline_tear : GameObject that begins the event and hands out quest +TO DO: get correct spell IDs and timings for spells cast upon dragon transformations +TO DO: Dragons should use the HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF) after transformation,but for some unknown reason it doesnt work. +EndContentData */ + +#define QUEST_A_PAWN_ON_THE_ETERNAL_BOARD 8519 +#define EVENT_AREA_RADIUS 65 //65yds +#define EVENT_COOLDOWN 500000 //in ms. appear after event completed or failed (should be = Adds despawn time) + +struct QuestCinematic +{ + int32 TextId; + uint32 Creature, Timer; +}; + +// Creature 0 - Anachronos, 1 - Fandral, 2 - Arygos, 3 - Merithra, 4 - Caelestrasz +static QuestCinematic EventAnim[]= +{ + {ANACHRONOS_SAY_1, 0, 2000}, + {FANDRAL_SAY_1, 1, 4000}, + {MERITHRA_EMOTE_1, 3, 500}, + {MERITHRA_SAY_1, 3, 500}, + {ARYGOS_EMOTE_1, 2, 2000}, + {CAELESTRASZ_SAY_1, 4, 8000}, + {MERITHRA_SAY_2, 3, 6000}, + {NULL,3,2000}, + {MERITHRA_YELL_1, 3, 2500}, + {NULL, 3, 3000},//Morph + {NULL,3,4000},//EmoteLiftoff + {NULL, 3, 4000},// spell + {NULL, 3, 1250},//fly + {NULL, 3, 250},//remove flags + {ARYGOS_SAY_1, 2, 3000}, + {NULL,3,2000}, + {ARYGOS_YELL_1, 2, 3000}, + {NULL, 3, 3000},//Morph + {NULL,3,4000},//EmoteLiftoff + {NULL, 3, 4000},// spell + {NULL, 3, 1000},//fly + {NULL, 3, 1000},//remove flags + {CAELESTRASZ_SAY_2, 4, 5000}, + {NULL,3,3000}, + {CAELESTRASZ_YELL_1, 4, 3000}, + {NULL, 3, 3000},//Morph + {NULL,3,4000},//EmoteLiftoff + {NULL, 3, 2500},// spell + {ANACHRONOS_SAY_2, 0, 2000}, + {NULL, 3, 250},//fly + {NULL, 3, 25},//remove flags + {FANDRAL_SAY_2, 1, 3000}, + {ANACHRONOS_SAY_3, 0, 10000},//Both run through the armies + {NULL,3,2000},// Sands will stop + {NULL,3,8000},// Summon Gate + {ANACHRONOS_SAY_4, 0, 4000}, + {NULL, 0, 2000},//spell 1-> Arcane cosmetic (Mobs freeze) + {NULL, 0, 5000}, //Spell 2-> Arcane long cosmetic (barrier appears) (Barrier -> Glyphs) + {NULL, 0, 7000},//BarrieR + {NULL, 0, 4000},//Glyphs + {ANACHRONOS_SAY_5, 0, 2000}, + {NULL, 0, 4000},// Roots + {FANDRAL_SAY_3, 1, 3000},//Root Text + {FANDRAL_EMOTE_1, 1, 3000},//falls knee + {ANACHRONOS_SAY_6, 0, 3000}, + {ANACHRONOS_SAY_7, 0, 3000}, + {ANACHRONOS_SAY_8, 0, 8000}, + {ANACHRONOS_EMOTE_1, 0, 1000},//Give Scepter + {FANDRAL_SAY_4, 1, 3000}, + {FANDRAL_SAY_5, 1, 3000},//->Equip hammer~Scepter, throw it at door + {FANDRAL_EMOTE_2, 1, 3000},//Throw hammer at door. + {ANACHRONOS_SAY_9, 0, 3000}, + {FANDRAL_SAY_6, 1, 3000}, //fandral goes away + {ANACHRONOS_EMOTE_2, 0, 3000}, + {ANACHRONOS_EMOTE_3, 0, 3000}, + {NULL, 0, 2000}, + {NULL, 0, 2000}, + {NULL, 0, 4000}, + {ANACHRONOS_SAY_10, 0, 3000}, + {NULL, 0, 2000}, + {NULL, 0, 3000}, + {NULL, 0, 15000}, + {NULL, 0, 5000}, + {NULL, 0, 3500}, + {NULL, 0, 5000}, + {NULL, 0, 3500}, + {NULL, 0, 5000}, + {NULL, 0, NULL} +}; + +struct Location +{ + float x, y, z, o; +}; + +//Cordinates for Spawns +static Location SpawnLocation[]= +{ + {-8085, 1528, 2.61, 3.141592},//Kaldorei Infantry + {-8080, 1526, 2.61, 3.141592},//Kaldorei Infantry + {-8085, 1524, 2.61, 3.141592},//Kaldorei Infantry + {-8080, 1522, 2.61, 3.141592},//Kaldorei Infantry + {-8085, 1520, 2.61, 3.141592},//Kaldorei Infantry + + {-8085, 1524, 2.61, 3.141592},//Kaldorei Infantry + {-8080, 1522, 2.61, 3.141592},//Kaldorei Infantry + {-8085, 1520, 2.61, 3.141592},//Kaldorei Infantry + {-8080, 1518, 2.61, 3.141592},//Kaldorei Infantry + {-8085, 1516, 2.61, 3.141592},//Kaldorei Infantry + + {-8085, 1518, 2.61, 3.141592},//Kaldorei Infantry + {-8080, 1516, 2.61, 3.141592},//Kaldorei Infantry + {-8080, 1520, 2.61, 3.141592},//Kaldorei Infantry + {-8080, 1424, 2.61, 3.141592},//Kaldorei Infantry + {-8085, 1422, 2.61, 3.141592},//Kaldorei Infantry + // 2 waves of warriors + {-8082, 1528, 2.61, 3.141592},//Kaldorei Infantry + {-8078, 1525, 2.61, 3.141592},//Kaldorei Infantry + {-8082, 1524, 2.61, 3.141592},//Kaldorei Infantry + {-8078, 1526, 2.61, 3.141592},//Kaldorei Infantry + {-8082, 1527, 2.61, 3.141592},//Kaldorei Infantry + + {-8082, 1524, 2.61, 3.141592},//Kaldorei Infantry + {-8078, 1522, 2.61, 3.141592},//Kaldorei Infantry + {-8082, 1520, 2.61, 3.141592},//Kaldorei Infantry + {-8078, 1518, 2.61, 3.141592},//Kaldorei Infantry + {-8082, 1516, 2.61, 3.141592},//Kaldorei Infantry + + {-8082, 1523, 2.61, 3.141592},//Kaldorei Infantry + {-8078, 1521, 2.61, 3.141592},//Kaldorei Infantry + {-8082, 1528, 2.61, 3.141592},//Kaldorei Infantry + {-8078, 1519, 2.61, 3.141592},//Kaldorei Infantry + {-8082, 1526, 2.61, 3.141592},//Kaldorei Infantry + + {-8082, 1524, 2.61, 3.141592},//Kaldorei Infantry + {-8078, 1522, 2.61, 3.141592},//Kaldorei Infantry + {-8082, 1520, 2.61, 3.141592},//Kaldorei Infantry + {-8078, 1518, 2.61, 3.141592},//Kaldorei Infantry + {-8082, 1516, 2.61, 3.141592},//Kaldorei Infantry + + {-8088, 1510, 2.61, 0},//Anubisath Conqueror + {-8084, 1520, 2.61, 0},//Anubisath Conqueror + {-8088, 1530, 2.61, 0},//Anubisath Conqueror + + {-8080, 1513, 2.61, 0},//Qiraj Wasp + {-8082, 1523, 2.61, 0},//Qiraj Wasp + {-8085, 1518, 2.61, 0},//Qiraj Wasp + {-8082, 1516, 2.61, 0},//Qiraj Wasp + {-8085, 1520, 2.61, 0},//Qiraj Wasp + {-8080, 1528, 2.61, 0},//Qiraj Wasp + + {-8082, 1513, 2.61, 0},//Qiraj Wasp + {-8079, 1523, 2.61, 0},//Qiraj Wasp + {-8080, 1531, 2.61, 0},//Qiraj Wasp + {-8079, 1516, 2.61, 0},//Qiraj Wasp + {-8082, 1520, 2.61, 0},//Qiraj Wasp + {-8080, 1518, 2.61, 0},//Qiraj Wasp + + {-8081, 1514, 2.61, 0},//Qiraj Tank + {-8081, 1520, 2.61, 0},//Qiraj Tank + {-8081, 1526, 2.61, 0},//Qiraj Tank + {-8081, 1512, 2.61, 0},//Qiraj Tank + {-8082, 1520, 2.61, 0},//Qiraj Tank + {-8081, 1528, 2.61, 0},//Qiraj Tank + + {-8082, 1513, 2.61, 3.141592},//Anubisath Conqueror + {-8082, 1520, 2.61, 3.141592},//Anubisath Conqueror + {-8082, 1527, 2.61, 3.141592},//Anubisath Conqueror +}; + +struct WaveData +{ + uint8 SpawnCount, UsedSpawnPoint; + uint32 CreatureId, SpawnTimer, YellTimer, DespTimer; + int32 WaveTextId; +}; + +static WaveData WavesInfo[] = +{ + {30, 0, 15423, 0, 0,24000, NULL}, //Kaldorei Soldier + {3, 35, 15424, 0, 0,24000, NULL}, //Anubisath Conqueror + {12, 38, 15414, 0, 0,24000, NULL}, //Qiraji Wasps + {6, 50, 15422, 0, 0,24000, NULL}, //Qiraji Tanks + {15, 15, 15423, 0, 0,24000, NULL} //Kaldorei Soldier + +}; + +struct SpawnSpells +{ + uint32 Timer1, Timer2, SpellId; +}; + +static SpawnSpells SpawnCast[]=// +{ + {100000, 2000, 33652}, // Stop Time + {38500, 300000, 28528}, // Poison Cloud + {58000, 300000, 35871}, // Frost Debuff (need correct spell) + {80950, 300000, 42075}, // Fire Explosion (need correct spell however this one looks cool) +}; +/*##### +# npc_anachronos_the_ancient +######*/ +struct npc_anachronos_the_ancientAI : public ScriptedAI +{ + npc_anachronos_the_ancientAI(Creature* c) : ScriptedAI(c) {} + + uint32 AnimationTimer; + uint8 AnimationCount; + + uint64 AnachronosQuestTriggerGUID; + uint64 MerithraGUID; + uint64 ArygosGUID; + uint64 CaelestraszGUID; + uint64 FandralGUID; + uint64 PlayerGUID; + bool eventEnd; + + void Reset() + { + AnimationTimer = 1500; + AnimationCount = 0; + AnachronosQuestTriggerGUID = 0; + MerithraGUID = 0; + ArygosGUID = 0; + CaelestraszGUID = 0; + FandralGUID = 0; + PlayerGUID = 0; + eventEnd = false; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void HandleAnimation() + { + Player* plr = Unit::GetPlayer(PlayerGUID); + if (!plr) + return; + + Unit* Fandral = plr->FindNearestCreature(C_FANDRAL_STAGHELM, 100, me); + Unit* Arygos = plr->FindNearestCreature(C_ARYGOS, 100,me); + Unit* Caelestrasz = plr->FindNearestCreature(C_CAELESTRASZ, 100, me); + Unit* Merithra = plr->FindNearestCreature(C_MERITHRA, 100,me); + + if (!Fandral || !Arygos || !Caelestrasz || !Merithra) + return; + + Unit* mob; + AnimationTimer = EventAnim[AnimationCount].Timer; + if (eventEnd == false) + { + switch(AnimationCount) + { + case 0: + DoScriptText(ANACHRONOS_SAY_1, me , Fandral); + break; + case 1: + Fandral->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + DoScriptText(FANDRAL_SAY_1, Fandral,me); + break; + case 2: + Fandral->SetUInt64Value(UNIT_FIELD_TARGET,NULL); + DoScriptText(MERITHRA_EMOTE_1,Merithra); + break; + case 3: + DoScriptText(MERITHRA_SAY_1,Merithra); + break; + case 4: + DoScriptText(ARYGOS_EMOTE_1,Arygos); + break; + case 5: + Caelestrasz->SetUInt64Value(UNIT_FIELD_TARGET, Fandral->GetGUID()); + DoScriptText(CAELESTRASZ_SAY_1, Caelestrasz); + break; + case 6: + DoScriptText(MERITHRA_SAY_2, Merithra); + break; + case 7: + Caelestrasz->SetUInt64Value(UNIT_FIELD_TARGET, NULL); + Merithra->GetMotionMaster()->MoveCharge(-8065,1530,2.61,10); + break; + case 8: + DoScriptText(MERITHRA_YELL_1,Merithra); + break; + case 9: + Merithra->CastSpell(Merithra,25105,true); + break; + case 10: + Merithra->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + Merithra->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + Merithra->GetMotionMaster()->MoveCharge(-8065,1530,6.61,3); + break; + case 11: + Merithra->CastSpell(Merithra,24818,false); + break; + case 12: + Merithra->GetMotionMaster()->MoveCharge(-8100,1530,50,42); + break; + case 13: + break; + case 14: + DoScriptText(ARYGOS_SAY_1,Arygos); + Merithra->SetVisibility(VISIBILITY_OFF); + break; + case 15: + Arygos->GetMotionMaster()->MoveCharge(-8065,1530,2.61,10); + Merithra->GetMotionMaster()->MoveCharge(-8034.535,1535.14,2.61,42); + break; + case 16: + DoScriptText(ARYGOS_YELL_1, Arygos); + break; + case 17: + Arygos->CastSpell(Arygos,25107,true); + break; + case 18: + Arygos->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + Arygos->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + Arygos->GetMotionMaster()->MoveCharge(-8065,1530,6.61,42); + break; + case 19: + Arygos->CastSpell(Arygos,50505,false); + break; + case 20: + Arygos->GetMotionMaster()->MoveCharge(-8095,1530,50,42); + break; + case 21: + break; + case 22: + DoScriptText(CAELESTRASZ_SAY_2,Caelestrasz, Fandral); + break; + case 23: + Caelestrasz->GetMotionMaster()->MoveCharge(-8065,1530,2.61,10); + Arygos->SetVisibility(VISIBILITY_OFF); + Arygos->GetMotionMaster()->MoveCharge(-8034.535,1535.14,2.61,10); + break; + case 24: + DoScriptText(CAELESTRASZ_YELL_1, Caelestrasz); + break; + case 25: + Caelestrasz->CastSpell(Caelestrasz,25106,true); + break; + case 26: + Caelestrasz->HandleEmoteCommand(254); + Caelestrasz->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + Caelestrasz->GetMotionMaster()->MoveCharge(-8065,1530,7.61,4); + break; + case 27: + Caelestrasz->CastSpell(Caelestrasz,54293,false); + break; + case 28: + DoScriptText(ANACHRONOS_SAY_2,me, Fandral); + break; + case 29: + Caelestrasz->GetMotionMaster()->MoveCharge(-8095,1530,50,42); + DoScriptText(FANDRAL_SAY_2, Fandral, me); + break; + case 30: + break; + case 31: + DoScriptText(ANACHRONOS_SAY_3, me, Fandral); + break; + case 32: + Caelestrasz->SetVisibility(VISIBILITY_OFF); + Caelestrasz->GetMotionMaster()->MoveCharge(-8034.535,1535.14,2.61,42); + Fandral->GetMotionMaster()->MoveCharge(-8108,1529,2.77,8); + me->GetMotionMaster()->MoveCharge(-8113,1525,2.77,8); + break;//both run to the gate + case 33: + DoScriptText(ANACHRONOS_SAY_4, me); + Caelestrasz->GetMotionMaster()->MoveCharge(-8050,1473,65,15); + break; //Text: sands will stop + case 34: + DoCast(plr, 23017, true);//Arcane Channeling + break; + case 35: + me->CastSpell(-8088,1520.43,2.67,25158,true); + break; + case 36: + DoCast(plr, 25159, true); + break; + case 37: + me->SummonGameObject(GO_GATE_OF_AHN_QIRAJ,-8130,1525,17.5,0,0,0,0,0,0); + break; + case 38: + DoCast(plr, 25166, true); + me->SummonGameObject(GO_GLYPH_OF_AHN_QIRAJ,-8130,1525,17.5,0,0,0,0,0,0); + break; + case 39: + DoScriptText(ANACHRONOS_SAY_5, me, Fandral); + break; + case 40: + Fandral->CastSpell(me, 25167, true); + break; + case 41: + Fandral->SummonGameObject(GO_ROOTS_OF_AHN_QIRAJ,-8130,1525,17.5,0,0,0,0,0,0); + DoScriptText(FANDRAL_SAY_3, Fandral); + break; + case 42: + me->CastStop(); + DoScriptText(FANDRAL_EMOTE_1, Fandral); + break; + case 43: + Fandral->CastStop(); + break; + case 44: + DoScriptText(ANACHRONOS_SAY_6, me); + break; + case 45: + DoScriptText(ANACHRONOS_SAY_7, me); + break; + case 46: + DoScriptText(ANACHRONOS_SAY_8, me); + me->GetMotionMaster()->MoveCharge(-8110,1527,2.77,4); + break; + case 47: + DoScriptText(ANACHRONOS_EMOTE_1, me); + break; + case 48: + DoScriptText(FANDRAL_SAY_4,Fandral,me); + break; + case 49: + DoScriptText(FANDRAL_SAY_5,Fandral,me); + break; + case 50: + DoScriptText(FANDRAL_EMOTE_2,Fandral); + Fandral->CastSpell(-8127,1525,17.5,33806,true); + break; + case 51: + { + uint32 entries[4] = { 15423, 15424, 15414, 15422 }; + for (uint8 i = 0; i < 4; ++i) + { + mob = plr->FindNearestCreature(entries[i],50,me); + while (mob) + { + mob->RemoveFromWorld(); + mob = plr->FindNearestCreature(15423,50,me); + } + } + break; + } + case 52: + Fandral->GetMotionMaster()->MoveCharge(-8028.75, 1538.795, 2.61,4); + DoScriptText(ANACHRONOS_SAY_9, me,Fandral); + break; + case 53: + DoScriptText(FANDRAL_SAY_6,Fandral); + break; + case 54: + DoScriptText(ANACHRONOS_EMOTE_2,me); + break; + case 55: + Fandral->SetVisibility(VISIBILITY_OFF); + break; + case 56: + DoScriptText(ANACHRONOS_EMOTE_3, me); + me->GetMotionMaster()->MoveCharge(-8116,1522,3.65,4); + break; + case 57: + me->GetMotionMaster()->MoveCharge(-8116.7,1527,3.7,4); + break; + case 58: + me->GetMotionMaster()->MoveCharge(-8112.67,1529.9,2.86,4); + break; + case 59: + me->GetMotionMaster()->MoveCharge(-8117.99,1532.24,3.94,4); + break; + case 60: + if (plr) + DoScriptText(ANACHRONOS_SAY_10, me,plr); + me->GetMotionMaster()->MoveCharge(-8113.46,1524.16,2.89,4); + break; + case 61: + me->GetMotionMaster()->MoveCharge(-8057.1,1470.32,2.61,6); + if (plr->IsInRange(me,0,15)) + plr->GroupEventHappens(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD ,me); + break; + case 62: + me->SetDisplayId(15500); + break; + case 63: + me->HandleEmoteCommand(254); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + break; + case 64: + me->GetMotionMaster()->MoveCharge(-8000,1400,150,9); + break; + case 65: + me->SetVisibility(VISIBILITY_OFF); + if (Creature* AnachronosQuestTrigger = (Unit::GetCreature(*me, AnachronosQuestTriggerGUID))) + { + DoScriptText(ARYGOS_YELL_1,me); + AnachronosQuestTrigger->AI()->EnterEvadeMode(); + eventEnd=true; + } + break; + } + } + ++AnimationCount; + } + void UpdateAI(const uint32 diff) + { + if (AnimationTimer) + { + if (AnimationTimer <= diff) + HandleAnimation(); + else AnimationTimer -= diff; + } + if (AnimationCount < 65) + me->CombatStop(); + if (AnimationCount == 65 || eventEnd) + me->AI()->EnterEvadeMode(); + } +}; + +/*###### +# mob_qiraj_war_spawn +######*/ + +struct mob_qiraj_war_spawnAI : public ScriptedAI +{ + mob_qiraj_war_spawnAI(Creature* c) : ScriptedAI(c) {} + + uint64 MobGUID; + uint64 PlayerGUID; + uint32 SpellTimer1, SpellTimer2, SpellTimer3,SpellTimer4; + bool Timers; + bool hasTarget; + + void Reset() + { + MobGUID = 0; + PlayerGUID = 0; + Timers = false; + hasTarget = false; + } + + void EnterCombat(Unit* /*who*/) {} + void JustDied(Unit* slayer); + + void UpdateAI(const uint32 diff) + { + Unit *pTarget = NULL; + //Player* plr = me->GetPlayer(PlayerGUID); + + if (!Timers) + { + if (me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) //all but Kaldorei Soldiers + { + SpellTimer1 = SpawnCast[1].Timer1; + SpellTimer2 = SpawnCast[2].Timer1; + SpellTimer3 = SpawnCast[3].Timer1; + } + if (me->GetEntry() == 15423 || me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) + SpellTimer4 = SpawnCast[0].Timer1; + Timers = true; + } + if (me->GetEntry() == 15424 || me->GetEntry() == 15422|| me->GetEntry() == 15414) + { + if (SpellTimer1 <= diff) + { + DoCast(me, SpawnCast[1].SpellId); + DoCast(me, 24319); + SpellTimer1 = SpawnCast[1].Timer2; + } else SpellTimer1 -= diff; + if (SpellTimer2 <= diff) + { + DoCast(me, SpawnCast[2].SpellId); + SpellTimer2 = SpawnCast[2].Timer2; + } else SpellTimer2 -= diff; + if (SpellTimer3 <= diff) + { + DoCast(me, SpawnCast[3].SpellId); + SpellTimer3 = SpawnCast[3].Timer2; + } else SpellTimer3 -= diff; + } + if (me->GetEntry() == 15423 || me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) + { + if (SpellTimer4 <= diff) + { + me->RemoveAllAttackers(); + me->AttackStop(); + DoCast(me, 15533); + SpellTimer4 = SpawnCast[0].Timer2; + } else SpellTimer4 -= diff; + } + if (!hasTarget) + { + if (me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) + pTarget = me->FindNearestCreature(15423,20,true); + if (me->GetEntry() == 15423) + { + uint8 tar = urand(0,2); + + if (tar == 0) + pTarget = me->FindNearestCreature(15422,20,true); + else if (tar == 1) + pTarget = me->FindNearestCreature(15424,20,true); + else if (tar == 2) + pTarget = me->FindNearestCreature(15414,20,true); + } + hasTarget = true; + if (pTarget) + me->AI()->AttackStart(pTarget); + } + if (!(me->FindNearestCreature(15379,60))) + DoCast(me, 33652); + + if (!UpdateVictim()) + { + hasTarget = false; + return; + } + + DoMeleeAttackIfReady(); + } +}; + +/*##### +# npc_anachronos_quest_trigger +#####*/ + +struct npc_anachronos_quest_triggerAI : public ScriptedAI +{ + npc_anachronos_quest_triggerAI(Creature* c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + + uint32 WaveTimer; + uint32 AnnounceTimer; + + int8 LiveCount; + uint8 WaveCount; + + bool EventStarted; + bool Announced; + bool Failed; + + void Reset() + { + PlayerGUID = 0; + + WaveTimer = 2000; + AnnounceTimer = 1000; + LiveCount = 0; + WaveCount = 0; + + EventStarted = false; + Announced = false; + Failed = false; + + me->SetVisibility(VISIBILITY_OFF); + } + + void SummonNextWave() + { + //uint8 count = WavesInfo[WaveCount].SpawnCount; + uint8 locIndex = WavesInfo[WaveCount].UsedSpawnPoint; + srand(time(NULL));//initializing random seed + //uint8 KaldoreiSoldierCount = 0; + //uint8 AnubisathConquerorCount = 0; + //uint8 QirajiWaspCount = 0; + for (uint8 i = 0; i < 67; ++i) + { + Creature* Spawn = NULL; + float X = SpawnLocation[locIndex + i].x; + float Y = SpawnLocation[locIndex + i].y; + float Z = SpawnLocation[locIndex + i].z; + float O = SpawnLocation[locIndex + i].o; + uint32 desptimer = WavesInfo[WaveCount].DespTimer; + Spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, X, Y, Z, O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, desptimer); + + if (Spawn) + { + Spawn->LoadCreaturesAddon(); + if (Spawn->GetGUID() == 15423) + Spawn->SetUInt32Value(UNIT_FIELD_DISPLAYID,15427+rand()%4); + if (i >= 30) WaveCount = 1; + if (i >= 33) WaveCount = 2; + if (i >= 45) WaveCount = 3; + if (i >= 51) WaveCount = 4; + + if (WaveCount < 5) //1-4 Wave + { + CAST_AI(mob_qiraj_war_spawnAI, Spawn->AI())->MobGUID = me->GetGUID(); + CAST_AI(mob_qiraj_war_spawnAI, Spawn->AI())->PlayerGUID = PlayerGUID; + } + } + } + WaveTimer = WavesInfo[WaveCount].SpawnTimer; + AnnounceTimer = WavesInfo[WaveCount].YellTimer; + } + + void CheckEventFail() + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + if (!pPlayer) + return; + + if (Group *EventGroup = pPlayer->GetGroup()) + { + Player* GroupMember; + + uint8 GroupMemberCount = 0; + uint8 DeadMemberCount = 0; + uint8 FailedMemberCount = 0; + + const Group::MemberSlotList members = EventGroup->GetMemberSlots(); + + for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) + { + GroupMember = (Unit::GetPlayer(itr->guid)); + if (!GroupMember) + continue; + if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) == QUEST_STATUS_INCOMPLETE) + { + GroupMember->FailQuest(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD); + GroupMember->SetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD, QUEST_STATUS_NONE); + ++FailedMemberCount; + } + ++GroupMemberCount; + + if (GroupMember->isDead()) + ++DeadMemberCount; + } + + if (GroupMemberCount == FailedMemberCount || !pPlayer->IsWithinDistInMap(me, EVENT_AREA_RADIUS)) + Failed = true; //only so event can restart + } + } + + void LiveCounter() + { + --LiveCount; + if (!LiveCount) + Announced = false; + } + + void UpdateAI(const uint32 diff) + { + if (!PlayerGUID || !EventStarted) + return; + + if (WaveCount < 4) + { + if (!Announced && AnnounceTimer <= diff) + { + DoScriptText(WavesInfo[WaveCount].WaveTextId, me); + Announced = true; + } else AnnounceTimer -= diff; + + if (WaveTimer <= diff) + SummonNextWave(); + else WaveTimer -= diff; + } + CheckEventFail(); + if (WaveCount == 4 || Failed) + EnterEvadeMode(); + }; +}; +void mob_qiraj_war_spawnAI::JustDied(Unit* /*slayer*/) +{ + me->RemoveCorpse(); + if (Creature* Mob = (Unit::GetCreature(*me, MobGUID))) + CAST_AI(npc_anachronos_quest_triggerAI, Mob->AI())->LiveCounter(); + +}; +/*##### +# go_crystalline_tear +######*/ + +bool GOQuestAccept_GO_crystalline_tear(Player* plr, GameObject* go, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) + { + + if (Unit* Anachronos_Quest_Trigger = go->FindNearestCreature(15454, 100, plr)) + { + + Unit *Merithra = Anachronos_Quest_Trigger->SummonCreature(15378,-8034.535,1535.14,2.61,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); + Unit *Caelestrasz = Anachronos_Quest_Trigger->SummonCreature(15379,-8032.767, 1533.148,2.61, 1.5,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); + Unit *Arygos = Anachronos_Quest_Trigger->SummonCreature(15380,-8034.52, 1537.843, 2.61, 5.7,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); + /* Unit *Fandral = */ Anachronos_Quest_Trigger->SummonCreature(15382,-8028.462, 1535.843, 2.61, 3.141592,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); + Creature *Anachronos = Anachronos_Quest_Trigger->SummonCreature(15381,-8028.75, 1538.795, 2.61, 4,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); + + if (Merithra) + { + Merithra->SetUInt32Value(UNIT_NPC_FLAGS, 0); + Merithra->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + Merithra->SetUInt32Value(UNIT_FIELD_DISPLAYID,15420); + Merithra->setFaction(35); + } + + if (Caelestrasz) + { + Caelestrasz->SetUInt32Value(UNIT_NPC_FLAGS, 0); + Caelestrasz->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + Caelestrasz->SetUInt32Value(UNIT_FIELD_DISPLAYID,15419); + Caelestrasz->setFaction(35); + } + + if (Arygos) + { + Arygos->SetUInt32Value(UNIT_NPC_FLAGS, 0); + Arygos->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + Arygos->SetUInt32Value(UNIT_FIELD_DISPLAYID,15418); + Arygos->setFaction(35); + } + + if (Anachronos) + { + CAST_AI(npc_anachronos_the_ancientAI, Anachronos->AI())->PlayerGUID = plr->GetGUID(); + CAST_AI(npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->Failed=false; + CAST_AI(npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->PlayerGUID = plr->GetGUID(); + CAST_AI(npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->EventStarted=true; + CAST_AI(npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->Announced=true; + } + } + } + return true; +} + +CreatureAI* GetAI_npc_anachronos_quest_trigger(Creature* c) +{ + return new npc_anachronos_quest_triggerAI(c); +} + +CreatureAI* GetAI_mob_qiraj_war_spawn(Creature* c) +{ + return new mob_qiraj_war_spawnAI(c); +} + +CreatureAI* GetAI_npc_anachronos_the_ancient(Creature* c) +{ + return new npc_anachronos_the_ancientAI(c); +} + +void AddSC_silithus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_crystalline_tear"; + newscript->pGOQuestAccept = &GOQuestAccept_GO_crystalline_tear; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anachronos_quest_trigger"; + newscript->GetAI = &GetAI_npc_anachronos_quest_trigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anachronos_the_ancient"; + newscript->GetAI = &GetAI_npc_anachronos_the_ancient; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_qiraj_war_spawn"; + newscript->GetAI = &GetAI_mob_qiraj_war_spawn; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_highlord_demitrian"; + newscript->pGossipHello = &GossipHello_npc_highlord_demitrian; + newscript->pGossipSelect = &GossipSelect_npc_highlord_demitrian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npcs_rutgar_and_frankal"; + newscript->pGossipHello = &GossipHello_npcs_rutgar_and_frankal; + newscript->pGossipSelect = &GossipSelect_npcs_rutgar_and_frankal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/stonetalon_mountains.cpp b/src/server/scripts/Kalimdor/stonetalon_mountains.cpp new file mode 100644 index 00000000000..6e627948788 --- /dev/null +++ b/src/server/scripts/Kalimdor/stonetalon_mountains.cpp @@ -0,0 +1,172 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Stonetalon_Mountains +SD%Complete: 95 +SDComment: Quest support: 6627, 6523 +SDCategory: Stonetalon Mountains +EndScriptData */ + +/* ContentData +npc_braug_dimspirit +npc_kaya_flathoof +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_braug_dimspirit +######*/ + +#define GOSSIP_HBD1 "Ysera" +#define GOSSIP_HBD2 "Neltharion" +#define GOSSIP_HBD3 "Nozdormu" +#define GOSSIP_HBD4 "Alexstrasza" +#define GOSSIP_HBD5 "Malygos" + +bool GossipHello_npc_braug_dimspirit(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(6627) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(5820, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(5819, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_braug_dimspirit(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer,6766,false); + + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(6627); + } + return true; +} + +/*###### +## npc_kaya_flathoof +######*/ + +enum eKaya +{ + FACTION_ESCORTEE_H = 775, + + NPC_GRIMTOTEM_RUFFIAN = 11910, + NPC_GRIMTOTEM_BRUTE = 11912, + NPC_GRIMTOTEM_SORCERER = 11913, + + SAY_START = -1000357, + SAY_AMBUSH = -1000358, + SAY_END = -1000359, + + QUEST_PROTECT_KAYA = 6523 +}; + +struct npc_kaya_flathoofAI : public npc_escortAI +{ + npc_kaya_flathoofAI(Creature* c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 16: + DoScriptText(SAY_AMBUSH, me); + me->SummonCreature(NPC_GRIMTOTEM_BRUTE, -48.53, -503.34, -46.31, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_GRIMTOTEM_RUFFIAN, -38.85, -503.77, -45.90, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + me->SummonCreature(NPC_GRIMTOTEM_SORCERER, -36.37, -496.23, -45.71, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 18: me->SetInFront(pPlayer); + DoScriptText(SAY_END, me, pPlayer); + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_PROTECT_KAYA, me); + break; + } + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void Reset(){} +}; + +bool QuestAccept_npc_kaya_flathoof(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_PROTECT_KAYA) + { + if (npc_escortAI* pEscortAI = CAST_AI(npc_kaya_flathoofAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + + DoScriptText(SAY_START, pCreature); + pCreature->setFaction(113); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + return true; +} + +CreatureAI* GetAI_npc_kaya_flathoofAI(Creature* pCreature) +{ + return new npc_kaya_flathoofAI(pCreature); +} + +/*###### +## AddSC +######*/ + +void AddSC_stonetalon_mountains() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_braug_dimspirit"; + newscript->pGossipHello = &GossipHello_npc_braug_dimspirit; + newscript->pGossipSelect = &GossipSelect_npc_braug_dimspirit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_kaya_flathoof"; + newscript->GetAI = &GetAI_npc_kaya_flathoofAI; + newscript->pQuestAccept = &QuestAccept_npc_kaya_flathoof; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/tanaris.cpp b/src/server/scripts/Kalimdor/tanaris.cpp new file mode 100644 index 00000000000..bb82dea64cf --- /dev/null +++ b/src/server/scripts/Kalimdor/tanaris.cpp @@ -0,0 +1,635 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Tanaris +SD%Complete: 80 +SDComment: Quest support: 648, 1560, 2954, 4005, 10277, 10279(Special flight path). Noggenfogger vendor +SDCategory: Tanaris +EndScriptData */ + +/* ContentData +mob_aquementas +npc_custodian_of_time +npc_marin_noggenfogger +npc_steward_of_time +npc_stone_watcher_of_norgannon +npc_OOX17 +npc_tooga +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "ScriptedFollowerAI.h" + +/*###### +## mob_aquementas +######*/ + +#define AGGRO_YELL_AQUE -1000350 + +#define SPELL_AQUA_JET 13586 +#define SPELL_FROST_SHOCK 15089 + +struct mob_aquementasAI : public ScriptedAI +{ + mob_aquementasAI(Creature *c) : ScriptedAI(c) {} + + uint32 SendItem_Timer; + uint32 SwitchFaction_Timer; + bool isFriendly; + + uint32 FrostShock_Timer; + uint32 AquaJet_Timer; + + void Reset() + { + SendItem_Timer = 0; + SwitchFaction_Timer = 10000; + me->setFaction(35); + isFriendly = true; + + AquaJet_Timer = 5000; + FrostShock_Timer = 1000; + } + + void SendItem(Unit* receiver) + { + if (CAST_PLR(receiver)->HasItemCount(11169,1,false) && + CAST_PLR(receiver)->HasItemCount(11172,11,false) && + CAST_PLR(receiver)->HasItemCount(11173,1,false) && + !CAST_PLR(receiver)->HasItemCount(11522,1,true)) + { + ItemPosCountVec dest; + uint8 msg = CAST_PLR(receiver)->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 11522, 1, false); + if (msg == EQUIP_ERR_OK) + CAST_PLR(receiver)->StoreNewItem(dest, 11522, 1, true); + } + } + + void EnterCombat(Unit* who) + { + DoScriptText(AGGRO_YELL_AQUE, me, who); + } + + void UpdateAI(const uint32 diff) + { + if (isFriendly) + { + if (SwitchFaction_Timer <= diff) + { + me->setFaction(91); + isFriendly = false; + } else SwitchFaction_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + if (!isFriendly) + { + if (SendItem_Timer <= diff) + { + if (me->getVictim()->GetTypeId() == TYPEID_PLAYER) + SendItem(me->getVictim()); + SendItem_Timer = 5000; + } else SendItem_Timer -= diff; + } + + if (FrostShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_SHOCK); + FrostShock_Timer = 15000; + } else FrostShock_Timer -= diff; + + if (AquaJet_Timer <= diff) + { + DoCast(me, SPELL_AQUA_JET); + AquaJet_Timer = 15000; + } else AquaJet_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_aquementas(Creature* pCreature) +{ + return new mob_aquementasAI (pCreature); +} + +/*###### +## npc_custodian_of_time +######*/ + +#define WHISPER_CUSTODIAN_1 -1000217 +#define WHISPER_CUSTODIAN_2 -1000218 +#define WHISPER_CUSTODIAN_3 -1000219 +#define WHISPER_CUSTODIAN_4 -1000220 +#define WHISPER_CUSTODIAN_5 -1000221 +#define WHISPER_CUSTODIAN_6 -1000222 +#define WHISPER_CUSTODIAN_7 -1000223 +#define WHISPER_CUSTODIAN_8 -1000224 +#define WHISPER_CUSTODIAN_9 -1000225 +#define WHISPER_CUSTODIAN_10 -1000226 +#define WHISPER_CUSTODIAN_11 -1000227 +#define WHISPER_CUSTODIAN_12 -1000228 +#define WHISPER_CUSTODIAN_13 -1000229 +#define WHISPER_CUSTODIAN_14 -1000230 + +struct npc_custodian_of_timeAI : public npc_escortAI +{ + npc_custodian_of_timeAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player *pPlayer = GetPlayerForEscort(); + if (!pPlayer) + return; + + switch(i) + { + case 0: DoScriptText(WHISPER_CUSTODIAN_1, me, pPlayer); break; + case 1: DoScriptText(WHISPER_CUSTODIAN_2, me, pPlayer); break; + case 2: DoScriptText(WHISPER_CUSTODIAN_3, me, pPlayer); break; + case 3: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; + case 5: DoScriptText(WHISPER_CUSTODIAN_5, me, pPlayer); break; + case 6: DoScriptText(WHISPER_CUSTODIAN_6, me, pPlayer); break; + case 7: DoScriptText(WHISPER_CUSTODIAN_7, me, pPlayer); break; + case 8: DoScriptText(WHISPER_CUSTODIAN_8, me, pPlayer); break; + case 9: DoScriptText(WHISPER_CUSTODIAN_9, me, pPlayer); break; + case 10: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; + case 13: DoScriptText(WHISPER_CUSTODIAN_10, me, pPlayer); break; + case 14: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; + case 16: DoScriptText(WHISPER_CUSTODIAN_11, me, pPlayer); break; + case 17: DoScriptText(WHISPER_CUSTODIAN_12, me, pPlayer); break; + case 18: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; + case 22: DoScriptText(WHISPER_CUSTODIAN_13, me, pPlayer); break; + case 23: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; + case 24: + DoScriptText(WHISPER_CUSTODIAN_14, me, pPlayer); + DoCast(pPlayer, 34883); + // below here is temporary workaround, to be removed when spell works properly + pPlayer->AreaExploredOrEventHappens(10277); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + if (who->GetTypeId() == TYPEID_PLAYER) + { + if (who->HasAura(34877) && CAST_PLR(who)->GetQuestStatus(10277) == QUEST_STATUS_INCOMPLETE) + { + float Radius = 10.0; + if (me->IsWithinDistInMap(who, Radius)) + { + Start(false, false, who->GetGUID()); + } + } + } + } + + void EnterCombat(Unit* /*who*/) {} + void Reset() { } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_custodian_of_time(Creature* pCreature) +{ + return new npc_custodian_of_timeAI(pCreature); +} + +/*###### +## npc_marin_noggenfogger +######*/ + +bool GossipHello_npc_marin_noggenfogger(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(2662)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_marin_noggenfogger(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_steward_of_time +######*/ + +#define GOSSIP_ITEM_FLIGHT "Please take me to the master's lair." + +bool GossipHello_npc_steward_of_time(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(10279) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestRewardStatus(10279)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(9978, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(9977, pCreature->GetGUID()); + + return true; +} + +bool QuestAccept_npc_steward_of_time(Player* pPlayer, Creature* /*pCreature*/, Quest const *quest) +{ + if (quest->GetQuestId() == 10279) //Quest: To The Master's Lair + pPlayer->CastSpell(pPlayer,34891,true); //(Flight through Caverns) + + return false; +} + +bool GossipSelect_npc_steward_of_time(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + pPlayer->CastSpell(pPlayer,34891,true); //(Flight through Caverns) + + return true; +} + +/*###### +## npc_stone_watcher_of_norgannon +######*/ + +#define GOSSIP_ITEM_NORGANNON_1 "What function do you serve?" +#define GOSSIP_ITEM_NORGANNON_2 "What are the Plates of Uldum?" +#define GOSSIP_ITEM_NORGANNON_3 "Where are the Plates of Uldum?" +#define GOSSIP_ITEM_NORGANNON_4 "Excuse me? We've been \"reschedueled for visitations\"? What does that mean?!" +#define GOSSIP_ITEM_NORGANNON_5 "So, what's inside Uldum?" +#define GOSSIP_ITEM_NORGANNON_6 "I will return when i have the Plates of Uldum." + +bool GossipHello_npc_stone_watcher_of_norgannon(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(2954) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(1674, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_stone_watcher_of_norgannon(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(1675, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(1676, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(1677, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(1678, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(1679, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(2954); + break; + } + return true; +} + +/*###### +## npc_OOX17 +######*/ + +enum e00X17 +{ + //texts are signed for 7806 + SAY_OOX_START = -1000287, + SAY_OOX_AGGRO1 = -1000288, + SAY_OOX_AGGRO2 = -1000289, + SAY_OOX_AMBUSH = -1000290, + SAY_OOX17_AMBUSH_REPLY = -1000291, + SAY_OOX_END = -1000292, + + Q_OOX17 = 648, + SPAWN_FIRST = 7803, + SPAWN_SECOND_1 = 5617, + SPAWN_SECOND_2 = 7805 +}; + +struct npc_OOX17AI : public npc_escortAI +{ + npc_OOX17AI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) { + case 23: + me->SummonCreature(SPAWN_FIRST, -8350.96, -4445.79, 10.10, 6.20, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(SPAWN_FIRST, -8355.96, -4447.79, 10.10, 6.27, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(SPAWN_FIRST, -8353.96, -4442.79, 10.10, 6.08, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + DoScriptText(SAY_OOX_AMBUSH, me); + break; + + case 56: + me->SummonCreature(SPAWN_SECOND_1, -7510.07, -4795.50, 9.35, 6.06, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(SPAWN_SECOND_2, -7515.07, -4797.50, 9.35, 6.22, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(SPAWN_SECOND_2, -7518.07, -4792.50, 9.35, 6.22, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + DoScriptText(SAY_OOX_AMBUSH, me); + if (Unit* scoff = me->FindNearestCreature(SPAWN_SECOND_2, 30)) + DoScriptText(SAY_OOX17_AMBUSH_REPLY, scoff); + break; + + case 86: + if (pPlayer) + { + DoScriptText(SAY_OOX_END, me); + pPlayer->GroupEventHappens(Q_OOX17, me); + } + break; + } + } + + void Reset(){} + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(RAND(SAY_OOX_AGGRO1,SAY_OOX_AGGRO2), me); + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } +}; + +bool QuestAccept_npc_OOX17(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == Q_OOX17) + { + pCreature->setFaction(113); + pCreature->SetHealth(pCreature->GetMaxHealth()); + pCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + DoScriptText(SAY_OOX_START, pCreature); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_OOX17AI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_OOX17(Creature* pCreature) +{ + return new npc_OOX17AI(pCreature); +} + +/*#### +# npc_tooga +####*/ + +enum eTooga +{ + SAY_TOOG_THIRST = -1000391, + SAY_TOOG_WORRIED = -1000392, + SAY_TOOG_POST_1 = -1000393, + SAY_TORT_POST_2 = -1000394, + SAY_TOOG_POST_3 = -1000395, + SAY_TORT_POST_4 = -1000396, + SAY_TOOG_POST_5 = -1000397, + SAY_TORT_POST_6 = -1000398, + + QUEST_TOOGA = 1560, + NPC_TORTA = 6015, + + POINT_ID_TO_WATER = 1, + FACTION_TOOG_ESCORTEE = 113 +}; + +const float m_afToWaterLoc[] = {-7032.664551, -4906.199219, -1.606446}; + +struct npc_toogaAI : public FollowerAI +{ + npc_toogaAI(Creature* pCreature) : FollowerAI(pCreature) { } + + uint32 m_uiCheckSpeechTimer; + uint32 m_uiPostEventTimer; + uint32 m_uiPhasePostEvent; + + uint64 TortaGUID; + + void Reset() + { + m_uiCheckSpeechTimer = 2500; + m_uiPostEventTimer = 1000; + m_uiPhasePostEvent = 0; + + TortaGUID = 0; + } + + void MoveInLineOfSight(Unit *pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE | STATE_FOLLOW_POSTEVENT) && pWho->GetEntry() == NPC_TORTA) + { + if (me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) + { + if (Player* pPlayer = GetLeaderForFollower()) + { + if (pPlayer->GetQuestStatus(QUEST_TOOGA) == QUEST_STATUS_INCOMPLETE) + pPlayer->GroupEventHappens(QUEST_TOOGA, me); + } + + TortaGUID = pWho->GetGUID(); + SetFollowComplete(true); + } + } + } + + void MovementInform(uint32 uiMotionType, uint32 uiPointId) + { + FollowerAI::MovementInform(uiMotionType, uiPointId); + + if (uiMotionType != POINT_MOTION_TYPE) + return; + + if (uiPointId == POINT_ID_TO_WATER) + SetFollowComplete(); + } + + void UpdateFollowerAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + { + //we are doing the post-event, or... + if (HasFollowState(STATE_FOLLOW_POSTEVENT)) + { + if (m_uiPostEventTimer <= uiDiff) + { + m_uiPostEventTimer = 5000; + + Unit *pTorta = Unit::GetUnit(*me, TortaGUID); + if (!pTorta || !pTorta->isAlive()) + { + //something happened, so just complete + SetFollowComplete(); + return; + } + + switch(m_uiPhasePostEvent) + { + case 1: + DoScriptText(SAY_TOOG_POST_1, me); + break; + case 2: + DoScriptText(SAY_TORT_POST_2, pTorta); + break; + case 3: + DoScriptText(SAY_TOOG_POST_3, me); + break; + case 4: + DoScriptText(SAY_TORT_POST_4, pTorta); + break; + case 5: + DoScriptText(SAY_TOOG_POST_5, me); + break; + case 6: + DoScriptText(SAY_TORT_POST_6, pTorta); + me->GetMotionMaster()->MovePoint(POINT_ID_TO_WATER, m_afToWaterLoc[0], m_afToWaterLoc[1], m_afToWaterLoc[2]); + break; + } + + ++m_uiPhasePostEvent; + } + else + m_uiPostEventTimer -= uiDiff; + } + //...we are doing regular speech check + else if (HasFollowState(STATE_FOLLOW_INPROGRESS)) + { + if (m_uiCheckSpeechTimer <= uiDiff) + { + m_uiCheckSpeechTimer = 5000; + + if (urand(0,9) > 8) + DoScriptText(RAND(SAY_TOOG_THIRST,SAY_TOOG_WORRIED), me); + } + else + m_uiCheckSpeechTimer -= uiDiff; + } + + return; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_tooga(Creature* pCreature) +{ + return new npc_toogaAI(pCreature); +} + +bool QuestAccept_npc_tooga(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_TOOGA) + { + if (npc_toogaAI* pToogaAI = CAST_AI(npc_toogaAI, pCreature->AI())) + pToogaAI->StartFollow(pPlayer, FACTION_TOOG_ESCORTEE, pQuest); + } + + return true; +} + +void AddSC_tanaris() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_aquementas"; + newscript->GetAI = &GetAI_mob_aquementas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_custodian_of_time"; + newscript->GetAI = &GetAI_npc_custodian_of_time; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_marin_noggenfogger"; + newscript->pGossipHello = &GossipHello_npc_marin_noggenfogger; + newscript->pGossipSelect = &GossipSelect_npc_marin_noggenfogger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_steward_of_time"; + newscript->pGossipHello = &GossipHello_npc_steward_of_time; + newscript->pGossipSelect = &GossipSelect_npc_steward_of_time; + newscript->pQuestAccept = &QuestAccept_npc_steward_of_time; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_stone_watcher_of_norgannon"; + newscript->pGossipHello = &GossipHello_npc_stone_watcher_of_norgannon; + newscript->pGossipSelect = &GossipSelect_npc_stone_watcher_of_norgannon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_OOX17"; + newscript->GetAI = &GetAI_npc_OOX17; + newscript->pQuestAccept = &QuestAccept_npc_OOX17; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tooga"; + newscript->GetAI = &GetAI_npc_tooga; + newscript->pQuestAccept = &QuestAccept_npc_tooga; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/teldrassil.cpp b/src/server/scripts/Kalimdor/teldrassil.cpp new file mode 100644 index 00000000000..1607ab904a8 --- /dev/null +++ b/src/server/scripts/Kalimdor/teldrassil.cpp @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Teldrassil +SD%Complete: 100 +SDComment: Quest support: 938 +SDCategory: Teldrassil +EndScriptData */ + +/* ContentData +npc_mist +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedFollowerAI.h" + +/*#### +# npc_mist +####*/ + +enum eMist +{ + SAY_AT_HOME = -1000323, + EMOTE_AT_HOME = -1000324, + QUEST_MIST = 938, + NPC_ARYNIA = 3519, + FACTION_DARNASSUS = 79 +}; + +struct npc_mistAI : public FollowerAI +{ + npc_mistAI(Creature* pCreature) : FollowerAI(pCreature) { } + + void Reset() { } + + void MoveInLineOfSight(Unit *pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_ARYNIA) + { + if (me->IsWithinDistInMap(pWho, 10.0f)) + { + DoScriptText(SAY_AT_HOME, pWho); + DoComplete(); + } + } + } + + void DoComplete() + { + DoScriptText(EMOTE_AT_HOME, me); + + if (Player* pPlayer = GetLeaderForFollower()) + { + if (pPlayer->GetQuestStatus(QUEST_MIST) == QUEST_STATUS_INCOMPLETE) + pPlayer->GroupEventHappens(QUEST_MIST, me); + } + + //The follow is over (and for later development, run off to the woods before really end) + SetFollowComplete(); + } + + //call not needed here, no known abilities + /*void UpdateFollowerAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + }*/ +}; + +CreatureAI* GetAI_npc_mist(Creature* pCreature) +{ + return new npc_mistAI(pCreature); +} + +bool QuestAccept_npc_mist(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_MIST) + { + if (npc_mistAI* pMistAI = CAST_AI(npc_mistAI, pCreature->AI())) + pMistAI->StartFollow(pPlayer, FACTION_DARNASSUS, pQuest); + } + + return true; +} + +void AddSC_teldrassil() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_mist"; + newscript->GetAI = &GetAI_npc_mist; + newscript->pQuestAccept = &QuestAccept_npc_mist; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp new file mode 100644 index 00000000000..f6e3b0c741b --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp @@ -0,0 +1,346 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_kri, boss_yauj, boss_vem : The Bug Trio +SD%Complete: 100 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" + +#define SPELL_CLEAVE 26350 +#define SPELL_TOXIC_VOLLEY 25812 +#define SPELL_POISON_CLOUD 38718 //Only Spell with right dmg. +#define SPELL_ENRAGE 34624 //Changed cause 25790 is casted on gamers too. Same prob with old explosion of twin emperors. + +#define SPELL_CHARGE 26561 +#define SPELL_KNOCKBACK 26027 + +#define SPELL_HEAL 25807 +#define SPELL_FEAR 19408 + +struct boss_kriAI : public ScriptedAI +{ + boss_kriAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Cleave_Timer; + uint32 ToxicVolley_Timer; + uint32 Check_Timer; + + bool VemDead; + bool Death; + + void Reset() + { + Cleave_Timer = 4000 + rand()%4000; + ToxicVolley_Timer = 6000 + rand()%6000; + Check_Timer = 2000; + + VemDead = false; + Death = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + } + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 5000 + rand()%7000; + } else Cleave_Timer -= diff; + + //ToxicVolley_Timer + if (ToxicVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TOXIC_VOLLEY); + ToxicVolley_Timer = 10000 + rand()%5000; + } else ToxicVolley_Timer -= diff; + + if (me->GetHealth() <= me->GetMaxHealth() * 0.05 && !Death) + { + DoCast(me->getVictim(), SPELL_POISON_CLOUD); + Death = true; + } + + if (!VemDead) + { + //Checking if Vem is dead. If yes we will enrage. + if (Check_Timer <= diff) + { + if (pInstance && pInstance->GetData(DATA_VEMISDEAD)) + { + DoCast(me, SPELL_ENRAGE); + VemDead = true; + } + Check_Timer = 2000; + } else Check_Timer -=diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_vemAI : public ScriptedAI +{ + boss_vemAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Charge_Timer; + uint32 KnockBack_Timer; + uint32 Enrage_Timer; + + bool Enraged; + + void Reset() + { + Charge_Timer = 15000 + rand()%12000; + KnockBack_Timer = 8000 + rand()%12000; + Enrage_Timer = 120000; + + Enraged = false; + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_VEM_DEATH, 0); + if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Charge_Timer + if (Charge_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + { + DoCast(pTarget, SPELL_CHARGE); + //me->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, true,1); + AttackStart(pTarget); + } + + Charge_Timer = 8000 + rand()%8000; + } else Charge_Timer -= diff; + + //KnockBack_Timer + if (KnockBack_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKBACK); + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-80); + KnockBack_Timer = 15000 + rand()%10000; + } else KnockBack_Timer -= diff; + + //Enrage_Timer + if (!Enraged && Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else Charge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_yaujAI : public ScriptedAI +{ + boss_yaujAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Heal_Timer; + uint32 Fear_Timer; + uint32 Check_Timer; + + bool VemDead; + + void Reset() + { + Heal_Timer = 25000 + rand()%15000; + Fear_Timer = 12000 + rand()%12000; + Check_Timer = 2000; + + VemDead = false; + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + + for (uint8 i = 0; i < 10; ++i) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + Creature* Summoned = me->SummonCreature(15621,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,90000); + if (Summoned && pTarget) + Summoned->AI()->AttackStart(pTarget); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + DoResetThreat(); + Fear_Timer = 20000; + } else Fear_Timer -= diff; + + //Casting Heal to other twins or herself. + if (Heal_Timer <= diff) + { + if (pInstance) + { + Unit *pKri = Unit::GetUnit((*me), pInstance->GetData64(DATA_KRI)); + Unit *pVem = Unit::GetUnit((*me), pInstance->GetData64(DATA_VEM)); + + switch (urand(0,2)) + { + case 0: + if (pKri) + DoCast(pKri, SPELL_HEAL); + break; + case 1: + if (pVem) + DoCast(pVem, SPELL_HEAL); + break; + case 2: + DoCast(me, SPELL_HEAL); + break; + } + } + + Heal_Timer = 15000+rand()%15000; + } else Heal_Timer -= diff; + + //Checking if Vem is dead. If yes we will enrage. + if (Check_Timer <= diff) + { + if (!VemDead) + { + if (pInstance) + { + if (pInstance->GetData(DATA_VEMISDEAD)) + { + DoCast(me, SPELL_ENRAGE); + VemDead = true; + } + } + } + Check_Timer = 2000; + } else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_yauj(Creature* pCreature) +{ + return new boss_yaujAI (pCreature); +} + +CreatureAI* GetAI_boss_vem(Creature* pCreature) +{ + return new boss_vemAI (pCreature); +} + +CreatureAI* GetAI_boss_kri(Creature* pCreature) +{ + return new boss_kriAI (pCreature); +} + +void AddSC_bug_trio() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kri"; + newscript->GetAI = &GetAI_boss_kri; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_vem"; + newscript->GetAI = &GetAI_boss_vem; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_yauj"; + newscript->GetAI = &GetAI_boss_yauj; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp new file mode 100644 index 00000000000..3e42d16be3a --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp @@ -0,0 +1,1307 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Cthun +SD%Complete: 95 +SDComment: Darkglare tracking issue +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" + +/* + * This is a 2 phases events. Here follows an explanation of the main events and transition between phases and sub-phases. + * + * The first phase is the EYE phase: the Eye of C'Thun is active and C'thun is not active. + * During this phase, the "Eye of C'Thun" alternates between 2 sub-phases: + * - PHASE_EYE_GREEN_BEAM: + * 50 sec phase during which the Eye mainly casts its Green Beam every 3 sec. + * - PHASE_EYE_RED_BEAM: + * 35 sec phase during which the Eye casts its red beam every sec. + * This EYE phase ends when the "Eye of C'Thun" is killed. Then starts the CTHUN phase. + * + * The second phase is the CTHUN phase. The Eye of C'Thun is not active and C'Thun is active. + * This phase starts with the transformation of the Eye into C'Thun (PHASE_CTHUN_TRANSITION). + * After the transformation, C'Thun alternates between 2 sub-phases: + * - PHASE_CTHUN_STOMACH: + * - C'Thun is almost insensible to all damage (99% damage reduction). + * - It spawns 2 tentacles in its stomach. + * - C'Thun swallows players. + * - This sub-phase ends when the 2 tentacles are killed. Swallowed players are regurgitate. + * + * - PHASE_CTHUN_WEAK: + * - weakened C'Thun takes normal damage. + * - This sub-phase ends after 45 secs. + * + * This CTHUN phase ends when C'Thun is killed + * + * Note: + * - the current phase is stored in the instance data to be easily shared between the eye and cthun. + */ + +#define PI 3.14 + +enum Phases +{ + PHASE_NOT_STARTED = 0, + + // Main Phase 1 - EYE + PHASE_EYE_GREEN_BEAM = 1, + PHASE_EYE_RED_BEAM = 2, + + // Main Phase 2 - CTHUN + PHASE_CTHUN_TRANSITION = 3, + PHASE_CTHUN_STOMACH = 4, + PHASE_CTHUN_WEAK = 5, + + PHASE_CTHUN_DONE = 6, +}; + +enum Creatures +{ + MOB_CTHUN_PORTAL = 15896, + + //***** Main Phase 1 ******** + BOSS_EYE_OF_CTHUN = 15589, + MOB_CLAW_TENTACLE = 15725, + MOB_EYE_TENTACLE = 15726, + MOB_SMALL_PORTAL = 15904, + + //***** Main Phase 2 ******** + MOB_BODY_OF_CTHUN = 15809, + MOB_GIANT_CLAW_TENTACLE = 15728, + MOB_GIANT_EYE_TENTACLE = 15334, + MOB_FLESH_TENTACLE = 15802, + MOB_GIANT_PORTAL = 15910, +}; + +enum Spells +{ + //***** Main Phase 1 ******** + //Eye Spells + SPELL_FREEZE_ANIM = 16245, + SPELL_GREEN_BEAM = 26134, + SPELL_DARK_GLARE = 26029, + SPELL_RED_COLORATION = 22518, //Probably not the right spell but looks similar + + //Eye Tentacles Spells + SPELL_MIND_FLAY = 26143, + + //Claw Tentacles Spells + SPELL_GROUND_RUPTURE = 26139, + SPELL_HAMSTRING = 26141, + + //***** Main Phase 2 ****** + //Body spells + //#define SPELL_CARAPACE_CTHUN 26156 //Was removed from client dbcs + SPELL_TRANSFORM = 26232, + SPELL_PURPLE_COLORATION = 22581, //Probably not the right spell but looks similar + + //Eye Tentacles Spells + //SAME AS PHASE1 + + //Giant Claw Tentacles + SPELL_MASSIVE_GROUND_RUPTURE = 26100, + + //Also casts Hamstring + SPELL_THRASH = 3391, + + //Giant Eye Tentacles + //CHAIN CASTS "SPELL_GREEN_BEAM" + + //Stomach Spells + SPELL_MOUTH_TENTACLE = 26332, + SPELL_EXIT_STOMACH_KNOCKBACK = 25383, + SPELL_DIGESTIVE_ACID = 26476, +}; + +enum Actions +{ + ACTION_FLESH_TENTACLE_KILLED = 1, +}; + +enum Yells +{ + //Text emote + EMOTE_WEAKENED = -1531011, + + //****** Out of Combat ****** + // Random Wispers - No txt only sound + // The random sound is chosen by the client. + RANDOM_SOUND_WHISPER = 8663, +}; + +//Stomach Teleport positions +#define STOMACH_X -8562.0f +#define STOMACH_Y 2037.0f +#define STOMACH_Z -70.0f +#define STOMACH_O 5.05f + +//Flesh tentacle positions +const Position FleshTentaclePos[2] = +{ + { -8571.0f, 1990.0f, -98.0f, 1.22f}, + { -8525.0f, 1994.0f, -98.0f, 2.12f}, +}; + +//Kick out position +const Position KickPos = { -8545.0f, 1984.0f, -96.0f}; + +struct eye_of_cthunAI : public Scripted_NoMovementAI +{ + eye_of_cthunAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInst = c->GetInstanceData(); + if (!pInst) + error_log("TSCR: No Instance eye_of_cthunAI"); + } + + ScriptedInstance* pInst; + + //Global variables + uint32 PhaseTimer; + + //Eye beam phase + uint32 BeamTimer; + uint32 EyeTentacleTimer; + uint32 ClawTentacleTimer; + + //Dark Glare phase + uint32 DarkGlareTick; + uint32 DarkGlareTickTimer; + float DarkGlareAngle; + bool ClockWise; + + void Reset() + { + //Phase information + PhaseTimer = 50000; //First dark glare in 50 seconds + + //Eye beam phase 50 seconds + BeamTimer = 3000; + EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam + ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam) + + //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks) + DarkGlareTick = 0; + DarkGlareTickTimer = 1000; + DarkGlareAngle = 0; + ClockWise = false; + + //Reset flags + me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_ON); + + //Reset Phase + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); + + //to avoid having a following void zone + Creature* pPortal= me->FindNearestCreature(MOB_CTHUN_PORTAL, 10); + if (pPortal) + pPortal->SetReactState(REACT_PASSIVE); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); + } + + void SpawnEyeTentacle(float x, float y) + { + if (Creature* Spawned = DoSpawnCreature(MOB_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500)) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + if (Spawned->AI()) + Spawned->AI()->AttackStart(pTarget); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //No instance + if (!pInst) + return; + + uint32 currentPhase = pInst->GetData(DATA_CTHUN_PHASE); + if (currentPhase == PHASE_EYE_GREEN_BEAM || currentPhase == PHASE_EYE_RED_BEAM) + { + // EyeTentacleTimer + if (EyeTentacleTimer <= diff) + { + //Spawn the 8 Eye Tentacles in the corret spots + SpawnEyeTentacle(0, 20); //south + SpawnEyeTentacle(10, 10); //south west + SpawnEyeTentacle(20, 0); //west + SpawnEyeTentacle(10, -10); //north west + + SpawnEyeTentacle(0, -20); //north + SpawnEyeTentacle(-10, -10); //north east + SpawnEyeTentacle(-20, 0); // east + SpawnEyeTentacle(-10, 10); // south east + + EyeTentacleTimer = 45000; + } else EyeTentacleTimer -= diff; + } + + switch (currentPhase) + { + case PHASE_EYE_GREEN_BEAM: + //BeamTimer + if (BeamTimer <= diff) + { + //SPELL_GREEN_BEAM + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + me->InterruptNonMeleeSpells(false); + DoCast(pTarget, SPELL_GREEN_BEAM); + + //Correctly update our target + me->SetUInt64Value(UNIT_FIELD_TARGET, pTarget->GetGUID()); + } + + //Beam every 3 seconds + BeamTimer = 3000; + } else BeamTimer -= diff; + + //ClawTentacleTimer + if (ClawTentacleTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + Creature* Spawned = NULL; + + //Spawn claw tentacle on the random target + Spawned = me->SummonCreature(MOB_CLAW_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500); + + if (Spawned && Spawned->AI()) + Spawned->AI()->AttackStart(pTarget); + } + + //One claw tentacle every 12.5 seconds + ClawTentacleTimer = 12500; + } else ClawTentacleTimer -= diff; + + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch to Dark Beam + pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_RED_BEAM); + + me->InterruptNonMeleeSpells(false); + me->SetReactState(REACT_PASSIVE); + + //Remove any target + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Select random target for dark beam to start on + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + //Face our target + DarkGlareAngle = me->GetAngle(pTarget); + DarkGlareTickTimer = 1000; + DarkGlareTick = 0; + ClockWise = RAND(true, false); + } + + //Add red coloration to C'thun + DoCast(me, SPELL_RED_COLORATION, true); + + //Freeze animation + DoCast(me, SPELL_FREEZE_ANIM); + me->SetOrientation(DarkGlareAngle); + me->StopMoving(); + + //Darkbeam for 35 seconds + PhaseTimer = 35000; + } else PhaseTimer -= diff; + + break; + + case PHASE_EYE_RED_BEAM: + if (DarkGlareTick < 35) + if (DarkGlareTickTimer <= diff) + { + //Set angle and cast + if (ClockWise) + me->SetOrientation(DarkGlareAngle + ((float)DarkGlareTick*PI/35)); + else + me->SetOrientation(DarkGlareAngle - ((float)DarkGlareTick*PI/35)); + + me->StopMoving(); + + //Actual dark glare cast, maybe something missing here? + DoCast(me, SPELL_DARK_GLARE, false); + + //Increase tick + ++DarkGlareTick; + + //1 second per tick + DarkGlareTickTimer = 1000; + } else DarkGlareTickTimer -= diff; + + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch to Eye Beam + pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); + + BeamTimer = 3000; + ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam) + + me->InterruptNonMeleeSpells(false); + + //Remove Red coloration from c'thun + me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + + //set it back to aggressive + me->SetReactState(REACT_AGGRESSIVE); + + //Eye Beam for 50 seconds + PhaseTimer = 50000; + } else PhaseTimer -= diff; + + break; + + //Transition phase + case PHASE_CTHUN_TRANSITION: + //Remove any target + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + me->SetHealth(0); + me->SetVisibility(VISIBILITY_OFF); + break; + + //Dead phase + case PHASE_CTHUN_DONE: + Creature* pPortal= me->FindNearestCreature(MOB_CTHUN_PORTAL, 10); + if (pPortal) + pPortal->ForcedDespawn(); + + me->ForcedDespawn(); + break; + } + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + //No instance + if (!pInst) + return; + + switch (pInst->GetData(DATA_CTHUN_PHASE)) + { + case PHASE_EYE_GREEN_BEAM: + case PHASE_EYE_RED_BEAM: + //Only if it will kill + if (damage < me->GetHealth()) + return; + + //Fake death in phase 0 or 1 (green beam or dark glare phase) + me->InterruptNonMeleeSpells(false); + + //Remove Red coloration from c'thun + me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + + //Reset to normal emote state and prevent select and attack + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Remove Target field + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Death animation/respawning; + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_TRANSITION); + + me->SetHealth(0); + damage = 0; + + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + break; + + case PHASE_CTHUN_DONE: + //Allow death here + return; + + default: + //Prevent death in these phases + damage = 0; + return; + } + } +}; + +struct cthunAI : public Scripted_NoMovementAI +{ + cthunAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + + pInst = c->GetInstanceData(); + if (!pInst) + error_log("TSCR: No Instance eye_of_cthunAI"); + } + + ScriptedInstance* pInst; + + //Out of combat whisper timer + uint32 WisperTimer; + + //Global variables + uint32 PhaseTimer; + + //------------------- + + //Phase transition + uint64 HoldPlayer; + + //Body Phase + uint32 EyeTentacleTimer; + uint8 FleshTentaclesKilled; + uint32 GiantClawTentacleTimer; + uint32 GiantEyeTentacleTimer; + uint32 StomachAcidTimer; + uint32 StomachEnterTimer; + uint32 StomachEnterVisTimer; + uint64 StomachEnterTarget; + + //Stomach map, bool = true then in stomach + UNORDERED_MAP Stomach_Map; + + void Reset() + { + //One random wisper every 90 - 300 seconds + WisperTimer = 90000; + + //Phase information + PhaseTimer = 10000; //Emerge in 10 seconds + + //No hold player for transition + HoldPlayer = 0; + + //Body Phase + EyeTentacleTimer = 30000; + FleshTentaclesKilled = 0; + GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat) + GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat) + StomachAcidTimer = 4000; //Every 4 seconds + StomachEnterTimer = 10000; //Every 10 seconds + StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer + StomachEnterTarget = 0; //Target to be teleported to stomach + + //Clear players in stomach and outside + Stomach_Map.clear(); + + //Reset flags + me->RemoveAurasDueToSpell(SPELL_TRANSFORM); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_OFF); + + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void SpawnEyeTentacle(float x, float y) + { + Creature* Spawned; + Spawned = DoSpawnCreature(MOB_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500); + if (Spawned && Spawned->AI()) + if (Unit *pTarget = SelectRandomNotStomach()) + Spawned->AI()->AttackStart(pTarget); + } + + Unit* SelectRandomNotStomach() + { + if (Stomach_Map.empty()) + return NULL; + + UNORDERED_MAP::const_iterator i = Stomach_Map.begin(); + + std::list temp; + std::list::const_iterator j; + + //Get all players in map + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*me, i->first); + + //Only units out of stomach + if (pUnit && i->second == false) + temp.push_back(pUnit); + + ++i; + } + + if (temp.empty()) + return NULL; + + j = temp.begin(); + + //Get random but only if we have more than one unit on threat list + if (temp.size() > 1) + advance (j , rand() % (temp.size() - 1)); + + return (*j); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + { + //No target so we'll use this section to do our random wispers instance wide + //WisperTimer + if (WisperTimer <= diff) + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) return; + + //Play random sound to the zone + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) + { + if (Player* pPlr = itr->getSource()) + pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER,pPlr); + } + } + + //One random wisper every 90 - 300 seconds + WisperTimer = urand(90000,300000); + } else WisperTimer -= diff; + + return; + } + + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //No instance + if (!pInst) + return; + + uint32 currentPhase = pInst->GetData(DATA_CTHUN_PHASE); + if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK) + { + // EyeTentacleTimer + if (EyeTentacleTimer <= diff) + { + //Spawn the 8 Eye Tentacles in the corret spots + SpawnEyeTentacle(0, 20); //south + SpawnEyeTentacle(10, 10); //south west + SpawnEyeTentacle(20, 0); //west + SpawnEyeTentacle(10, -10); //north west + + SpawnEyeTentacle(0, -20); //north + SpawnEyeTentacle(-10, -10); //north east + SpawnEyeTentacle(-20, 0); // east + SpawnEyeTentacle(-10, 10); // south east + + EyeTentacleTimer = 30000; // every 30sec in phase 2 + } else EyeTentacleTimer -= diff; + } + + switch (currentPhase) + { + //Transition phase + case PHASE_CTHUN_TRANSITION: + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); + + //Switch to c'thun model + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_TRANSFORM, false); + me->SetHealth(me->GetMaxHealth()); + + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Emerging phase + //AttackStart(Unit::GetUnit(*me, HoldpPlayer)); + DoZoneInCombat(); + + //Place all units in threat list on outside of stomach + Stomach_Map.clear(); + + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + //Outside stomach + Stomach_Map[(*i)->getUnitGuid()] = false; + } + + //Spawn 2 flesh tentacles + FleshTentaclesKilled = 0; + + //Spawn flesh tentacle + for (uint8 i = 0; i < 2; i++) + { + Creature* spawned = me->SummonCreature(MOB_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); + if (!spawned) + ++FleshTentaclesKilled; + } + + PhaseTimer = 0; + } else PhaseTimer -= diff; + + break; + + //Body Phase + case PHASE_CTHUN_STOMACH: + //Remove Target field + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Weaken + if (FleshTentaclesKilled > 1) + { + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_WEAK); + + DoScriptText(EMOTE_WEAKENED, me); + PhaseTimer = 45000; + + DoCast(me, SPELL_PURPLE_COLORATION, true); + + UNORDERED_MAP::iterator i = Stomach_Map.begin(); + + //Kick all players out of stomach + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*me, i->first); + + //Only move units in stomach + if (pUnit && i->second == true) + { + //Teleport each player out + DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+10, rand()%6); + + //Cast knockback on them + DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); + + //Remove the acid debuff + pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); + + i->second = false; + } + ++i; + } + + return; + } + + //Stomach acid + if (StomachAcidTimer <= diff) + { + //Apply aura to all players in stomach + UNORDERED_MAP::iterator i = Stomach_Map.begin(); + + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*me, i->first); + + //Only apply to units in stomach + if (pUnit && i->second == true) + { + //Cast digestive acid on them + DoCast(pUnit, SPELL_DIGESTIVE_ACID, true); + + //Check if player should be kicked from stomach + if (pUnit->IsWithinDist3d(&KickPos, 15.0f)) + { + //Teleport each player out + DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+10, rand()%6); + + //Cast knockback on them + DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); + + //Remove the acid debuff + pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); + + i->second = false; + } + } + ++i; + } + + StomachAcidTimer = 4000; + } else StomachAcidTimer -= diff; + + //Stomach Enter Timer + if (StomachEnterTimer <= diff) + { + if (Unit *pTarget = SelectRandomNotStomach()) + { + //Set target in stomach + Stomach_Map[pTarget->GetGUID()] = true; + pTarget->InterruptNonMeleeSpells(false); + pTarget->CastSpell(pTarget, SPELL_MOUTH_TENTACLE, true, NULL, NULL, me->GetGUID()); + StomachEnterTarget = pTarget->GetGUID(); + StomachEnterVisTimer = 3800; + } + + StomachEnterTimer = 13800; + } else StomachEnterTimer -= diff; + + if (StomachEnterVisTimer && StomachEnterTarget) + if (StomachEnterVisTimer <= diff) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*me, StomachEnterTarget); + + if (pUnit) + { + DoTeleportPlayer(pUnit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O); + } + + StomachEnterTarget = 0; + StomachEnterVisTimer = 0; + } else StomachEnterVisTimer -= diff; + + //GientClawTentacleTimer + if (GiantClawTentacleTimer <= diff) + { + if (Unit *pTarget = SelectRandomNotStomach()) + { + //Spawn claw tentacle on the random target + if (Creature* spawned = me->SummonCreature(MOB_GIANT_CLAW_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500)) + if (spawned->AI()) + spawned->AI()->AttackStart(pTarget); + } + + //One giant claw tentacle every minute + GiantClawTentacleTimer = 60000; + } else GiantClawTentacleTimer -= diff; + + //GiantEyeTentacleTimer + if (GiantEyeTentacleTimer <= diff) + { + if (Unit *pTarget = SelectRandomNotStomach()) + { + //Spawn claw tentacle on the random target + if (Creature* spawned = me->SummonCreature(MOB_GIANT_EYE_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500)) + if (spawned->AI()) + spawned->AI()->AttackStart(pTarget); + } + + //One giant eye tentacle every minute + GiantEyeTentacleTimer = 60000; + } else GiantEyeTentacleTimer -= diff; + + break; + + //Weakened state + case PHASE_CTHUN_WEAK: + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); + + //Remove purple coloration + me->RemoveAurasDueToSpell(SPELL_PURPLE_COLORATION); + + //Spawn 2 flesh tentacles + FleshTentaclesKilled = 0; + + //Spawn flesh tentacle + for (uint8 i = 0; i < 2; i++) + { + Creature* spawned = me->SummonCreature(MOB_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); + if (!spawned) + ++FleshTentaclesKilled; + } + + PhaseTimer = 0; + } else PhaseTimer -= diff; + + break; + } + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + //No instance + if (!pInst) + return; + + switch (pInst->GetData(DATA_CTHUN_PHASE)) + { + case PHASE_CTHUN_STOMACH: + //Not weakened so reduce damage by 99% + damage /= 100; + if (damage == 0) + damage = 1; + + //Prevent death in non-weakened state + if (damage >= me->GetHealth()) + damage = 0; + + return; + + case PHASE_CTHUN_WEAK: + //Weakened - takes normal damage + return; + + default: + damage = 0; + break; + } + } + + void DoAction(const int32 param) + { + switch(param) + { + case ACTION_FLESH_TENTACLE_KILLED: + ++FleshTentaclesKilled; + break; + } + } +}; + +struct eye_tentacleAI : public Scripted_NoMovementAI +{ + eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + } + + uint32 MindflayTimer; + uint32 KillSelfTimer; + uint64 Portal; + + void JustDied(Unit* /*who*/) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + } + + void Reset() + { + //Mind flay half a second after we spawn + MindflayTimer = 500; + + //This prevents eyes from overlapping + KillSelfTimer = 35000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //KillSelfTimer + if (KillSelfTimer <= diff) + { + me->Kill(me); + return; + } else KillSelfTimer -= diff; + + //MindflayTimer + if (MindflayTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && !pTarget->HasAura(SPELL_DIGESTIVE_ACID)) + DoCast(pTarget, SPELL_MIND_FLAY); + + //Mindflay every 10 seconds + MindflayTimer = 10000; + } else MindflayTimer -= diff; + } +}; + +struct claw_tentacleAI : public Scripted_NoMovementAI +{ + claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + + if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + } + + uint32 GroundRuptureTimer; + uint32 HamstringTimer; + uint32 EvadeTimer; + uint64 Portal; + + void JustDied(Unit* /*who*/) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + } + + void Reset() + { + //First rupture should happen half a second after we spawn + GroundRuptureTimer = 500; + HamstringTimer = 2000; + EvadeTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //EvadeTimer + if (!me->IsWithinMeleeRange(me->getVictim())) + if (EvadeTimer <= diff) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + + //Dissapear and reappear at new position + me->SetVisibility(VISIBILITY_OFF); + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget) + { + me->Kill(me); + return; + } + + if (!pTarget->HasAura(SPELL_DIGESTIVE_ACID)) + { + me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); + if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + + GroundRuptureTimer = 500; + HamstringTimer = 2000; + EvadeTimer = 5000; + AttackStart(pTarget); + } + + me->SetVisibility(VISIBILITY_ON); + } else EvadeTimer -= diff; + + //GroundRuptureTimer + if (GroundRuptureTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); + GroundRuptureTimer = 30000; + } else GroundRuptureTimer -= diff; + + //HamstringTimer + if (HamstringTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + HamstringTimer = 5000; + } else HamstringTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct giant_claw_tentacleAI : public Scripted_NoMovementAI +{ + giant_claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + + if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + } + + uint32 GroundRuptureTimer; + uint32 ThrashTimer; + uint32 HamstringTimer; + uint32 EvadeTimer; + uint64 Portal; + + void JustDied(Unit* /*who*/) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + } + + void Reset() + { + //First rupture should happen half a second after we spawn + GroundRuptureTimer = 500; + HamstringTimer = 2000; + ThrashTimer = 5000; + EvadeTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //EvadeTimer + if (!me->IsWithinMeleeRange(me->getVictim())) + if (EvadeTimer <= diff) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + + //Dissapear and reappear at new position + me->SetVisibility(VISIBILITY_OFF); + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!pTarget) + { + me->Kill(me); + return; + } + + if (!pTarget->HasAura(SPELL_DIGESTIVE_ACID)) + { + me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); + if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + + GroundRuptureTimer = 500; + HamstringTimer = 2000; + ThrashTimer = 5000; + EvadeTimer = 5000; + AttackStart(pTarget); + } + + me->SetVisibility(VISIBILITY_ON); + + } else EvadeTimer -= diff; + + //GroundRuptureTimer + if (GroundRuptureTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); + GroundRuptureTimer = 30000; + } else GroundRuptureTimer -= diff; + + //ThrashTimer + if (ThrashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_THRASH); + ThrashTimer = 10000; + } else ThrashTimer -= diff; + + //HamstringTimer + if (HamstringTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + HamstringTimer = 10000; + } else HamstringTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct giant_eye_tentacleAI : public Scripted_NoMovementAI +{ + giant_eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + + if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + } + + uint32 BeamTimer; + uint64 Portal; + + void JustDied(Unit* /*who*/) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + } + + void Reset() + { + //Green Beam half a second after we spawn + BeamTimer = 500; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //BeamTimer + if (BeamTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && !pTarget->HasAura(SPELL_DIGESTIVE_ACID)) + DoCast(pTarget, SPELL_GREEN_BEAM); + + //Beam every 2 seconds + BeamTimer = 2100; + } else BeamTimer -= diff; + } +}; + +struct flesh_tentacleAI : public Scripted_NoMovementAI +{ + flesh_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + } + + void JustDied(Unit* /*killer*/) + { + if (CAST_SUM(me)) + if (Creature* pSummoner = CAST_CRE(CAST_SUM(me)->GetSummoner())) + if (pSummoner->AI()) + pSummoner->AI()->DoAction(ACTION_FLESH_TENTACLE_KILLED); + } +}; + +//GetAIs +CreatureAI* GetAI_eye_of_cthun(Creature* pCreature) +{ + return new eye_of_cthunAI (pCreature); +} + +CreatureAI* GetAI_cthun(Creature* pCreature) +{ + return new cthunAI (pCreature); +} + +CreatureAI* GetAI_eye_tentacle(Creature* pCreature) +{ + return new eye_tentacleAI (pCreature); +} + +CreatureAI* GetAI_claw_tentacle(Creature* pCreature) +{ + return new claw_tentacleAI (pCreature); +} + +CreatureAI* GetAI_giant_claw_tentacle(Creature* pCreature) +{ + return new giant_claw_tentacleAI (pCreature); +} + +CreatureAI* GetAI_giant_eye_tentacle(Creature* pCreature) +{ + return new giant_eye_tentacleAI (pCreature); +} + +CreatureAI* GetAI_flesh_tentacle(Creature* pCreature) +{ + return new flesh_tentacleAI (pCreature); +} + +void AddSC_boss_cthun() +{ + Script *newscript; + + //Eye + newscript = new Script; + newscript->Name = "boss_eye_of_cthun"; + newscript->GetAI = &GetAI_eye_of_cthun; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_cthun"; + newscript->GetAI = &GetAI_cthun; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_eye_tentacle"; + newscript->GetAI = &GetAI_eye_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_claw_tentacle"; + newscript->GetAI = &GetAI_claw_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_giant_claw_tentacle"; + newscript->GetAI = &GetAI_giant_claw_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_giant_eye_tentacle"; + newscript->GetAI = &GetAI_giant_eye_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_giant_flesh_tentacle"; + newscript->GetAI = &GetAI_flesh_tentacle; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp new file mode 100644 index 00000000000..32d5ec1c3df --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Fankriss +SD%Complete: 100 +SDComment: sound not implemented +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" + +#define SOUND_SENTENCE_YOU 8588 +#define SOUND_SERVE_TO 8589 +#define SOUND_LAWS 8590 +#define SOUND_TRESPASS 8591 +#define SOUND_WILL_BE 8592 + +#define SPELL_MORTAL_WOUND 28467 +#define SPELL_ROOT 28858 + +// Enrage for his spawns +#define SPELL_ENRAGE 28798 + +struct boss_fankrissAI : public ScriptedAI +{ + boss_fankrissAI(Creature *c) : ScriptedAI(c) {} + + uint32 MortalWound_Timer; + uint32 SpawnHatchlings_Timer; + uint32 SpawnSpawns_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Hatchling; + Creature* Spawn; + + void Reset() + { + MortalWound_Timer = 10000 + rand()%5000; + SpawnHatchlings_Timer = 6000 + rand()%6000; + SpawnSpawns_Timer = 15000 + rand()%30000; + } + + void SummonSpawn(Unit* victim) + { + if (!victim) + return; + + Rand = 10 + (rand()%10); + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = 10 + (rand()%10); + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Spawn = DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + if (Spawn) + Spawn->AI()->AttackStart(victim); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //MortalWound_Timer + if (MortalWound_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + MortalWound_Timer = 10000 + rand()%10000; + } else MortalWound_Timer -= diff; + + //Summon 1-3 Spawns of Fankriss at random time. + if (SpawnSpawns_Timer <= diff) + { + switch (urand(0,2)) + { + case 0: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + case 1: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + case 2: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + } + SpawnSpawns_Timer = 30000 + rand()%30000; + } else SpawnSpawns_Timer -= diff; + + // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer. + //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot. + if (me->GetHealth()*100 / me->GetMaxHealth() > 3) + { + if (SpawnHatchlings_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SPELL_ROOT); + + if (DoGetThreat(pTarget)) + DoModifyThreatPercent(pTarget, -100); + + switch(urand(0,2)) + { + case 0: + DoTeleportPlayer(pTarget, -8106.0142,1289.2900,-74.419533,5.112); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + break; + case 1: + DoTeleportPlayer(pTarget, -7990.135354,1155.1907,-78.849319,2.608); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + break; + case 2: + DoTeleportPlayer(pTarget,-8159.7753,1127.9064,-76.868660,0.675); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + break; + } + } + SpawnHatchlings_Timer = 45000 + rand()%15000; + } else SpawnHatchlings_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_fankriss(Creature* pCreature) +{ + return new boss_fankrissAI (pCreature); +} + +void AddSC_boss_fankriss() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_fankriss"; + newscript->GetAI = &GetAI_boss_fankriss; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp new file mode 100644 index 00000000000..f0e3a425edd --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp @@ -0,0 +1,148 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Huhuran +SD%Complete: 100 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_GENERIC_FRENZY_KILL -1000001 +#define EMOTE_GENERIC_BERSERK -1000004 + +#define SPELL_FRENZY 26051 +#define SPELL_BERSERK 26068 +#define SPELL_POISONBOLT 26052 +#define SPELL_NOXIOUSPOISON 26053 +#define SPELL_WYVERNSTING 26180 +#define SPELL_ACIDSPIT 26050 + +struct boss_huhuranAI : public ScriptedAI +{ + boss_huhuranAI(Creature *c) : ScriptedAI(c) {} + + uint32 Frenzy_Timer; + uint32 Wyvern_Timer; + uint32 Spit_Timer; + uint32 PoisonBolt_Timer; + uint32 NoxiousPoison_Timer; + uint32 FrenzyBack_Timer; + + bool Frenzy; + bool Berserk; + + void Reset() + { + Frenzy_Timer = 25000 + rand()%10000; + Wyvern_Timer = 18000 + rand()%10000; + Spit_Timer = 8000; + PoisonBolt_Timer = 4000; + NoxiousPoison_Timer = 10000 + rand()%10000; + FrenzyBack_Timer = 15000; + + Frenzy = false; + Berserk = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frenzy_Timer + if (!Frenzy && Frenzy_Timer <= diff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); + Frenzy = true; + PoisonBolt_Timer = 3000; + Frenzy_Timer = 25000 + rand()%10000; + } else Frenzy_Timer -= diff; + + // Wyvern Timer + if (Wyvern_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_WYVERNSTING); + Wyvern_Timer = 15000 + rand()%17000; + } else Wyvern_Timer -= diff; + + //Spit Timer + if (Spit_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ACIDSPIT); + Spit_Timer = 5000 + rand()%5000; + } else Spit_Timer -= diff; + + //NoxiousPoison_Timer + if (NoxiousPoison_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_NOXIOUSPOISON); + NoxiousPoison_Timer = 12000 + rand()%12000; + } else NoxiousPoison_Timer -= diff; + + //PoisonBolt only if frenzy or berserk + if (Frenzy || Berserk) + { + if (PoisonBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISONBOLT); + PoisonBolt_Timer = 3000; + } else PoisonBolt_Timer -= diff; + } + + //FrenzyBack_Timer + if (Frenzy && FrenzyBack_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + Frenzy = false; + FrenzyBack_Timer = 15000; + } else FrenzyBack_Timer -= diff; + + if (!Berserk && me->GetHealth()*100 / me->GetMaxHealth() < 31) + { + me->InterruptNonMeleeSpells(false); + DoScriptText(EMOTE_GENERIC_BERSERK, me); + DoCast(me, SPELL_BERSERK); + Berserk = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_huhuran(Creature* pCreature) +{ + return new boss_huhuranAI (pCreature); +} + +void AddSC_boss_huhuran() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_huhuran"; + newscript->GetAI = &GetAI_boss_huhuran; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp new file mode 100644 index 00000000000..1dd642c38f4 --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp @@ -0,0 +1,140 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ouro +SD%Complete: 85 +SDComment: No model for submerging. Currently just invisible. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" + +#define SPELL_SWEEP 26103 +#define SPELL_SANDBLAST 26102 +#define SPELL_GROUND_RUPTURE 26100 +#define SPELL_BIRTH 26262 //The Birth Animation + +#define SPELL_DIRTMOUND_PASSIVE 26092 + +struct boss_ouroAI : public ScriptedAI +{ + boss_ouroAI(Creature *c) : ScriptedAI(c) {} + + uint32 Sweep_Timer; + uint32 SandBlast_Timer; + uint32 Submerge_Timer; + uint32 Back_Timer; + uint32 ChangeTarget_Timer; + uint32 Spawn_Timer; + + bool Enrage; + bool Submerged; + + void Reset() + { + Sweep_Timer = 5000 + rand()%5000; + SandBlast_Timer = 20000 + rand()%15000; + Submerge_Timer = 90000 + rand()%60000; + Back_Timer = 30000 + rand()%15000; + ChangeTarget_Timer = 5000 + rand()%3000; + Spawn_Timer = 10000 + rand()%10000; + + Enrage = false; + Submerged = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoCast(me->getVictim(), SPELL_BIRTH); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sweep_Timer + if (!Submerged && Sweep_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SWEEP); + Sweep_Timer = 15000 + rand()%15000; + } else Sweep_Timer -= diff; + + //SandBlast_Timer + if (!Submerged && SandBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SANDBLAST); + SandBlast_Timer = 20000 + rand()%15000; + } else SandBlast_Timer -= diff; + + //Submerge_Timer + if (!Submerged && Submerge_Timer <= diff) + { + //Cast + me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(35); + DoCast(me, SPELL_DIRTMOUND_PASSIVE); + + Submerged = true; + Back_Timer = 30000 + rand()%15000; + } else Submerge_Timer -= diff; + + //ChangeTarget_Timer + if (Submerged && ChangeTarget_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (pTarget) + DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); + + ChangeTarget_Timer = 10000 + rand()%10000; + } else ChangeTarget_Timer -= diff; + + //Back_Timer + if (Submerged && Back_Timer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + + DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); + + Submerged = false; + Submerge_Timer = 60000 + rand()%60000; + } else Back_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ouro(Creature* pCreature) +{ + return new boss_ouroAI (pCreature); +} + +void AddSC_boss_ouro() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ouro"; + newscript->GetAI = &GetAI_boss_ouro; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp new file mode 100644 index 00000000000..282a25b7215 --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp @@ -0,0 +1,297 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Sartura +SD%Complete: 95 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1531008 +#define SAY_SLAY -1531009 +#define SAY_DEATH -1531010 + +#define SPELL_WHIRLWIND 26083 +#define SPELL_ENRAGE 28747 //Not sure if right ID. +#define SPELL_ENRAGEHARD 28798 + +//Guard Spell +#define SPELL_WHIRLWINDADD 26038 +#define SPELL_KNOCKBACK 26027 + +struct boss_sarturaAI : public ScriptedAI +{ + boss_sarturaAI(Creature *c) : ScriptedAI(c) {} + + uint32 WhirlWind_Timer; + uint32 WhirlWindRandom_Timer; + uint32 WhirlWindEnd_Timer; + uint32 AggroReset_Timer; + uint32 AggroResetEnd_Timer; + uint32 EnrageHard_Timer; + + bool Enraged; + bool EnragedHard; + bool WhirlWind; + bool AggroReset; + + void Reset() + { + WhirlWind_Timer = 30000; + WhirlWindRandom_Timer = 3000 + rand()%4000; + WhirlWindEnd_Timer = 15000; + AggroReset_Timer = 45000 + rand()%10000; + AggroResetEnd_Timer = 5000; + EnrageHard_Timer = 10*60000; + + WhirlWind = false; + AggroReset = false; + Enraged = false; + EnragedHard = false; + + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (WhirlWind) + { + if (WhirlWindRandom_Timer <= diff) + { + //Attack random Gamers + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget) + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + + WhirlWindRandom_Timer = 3000 + rand()%4000; + } else WhirlWindRandom_Timer -= diff; + + if (WhirlWindEnd_Timer <= diff) + { + WhirlWind = false; + WhirlWind_Timer = 25000 + rand()%15000; + } else WhirlWindEnd_Timer -= diff; + } + + if (!WhirlWind) + { + if (WhirlWind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + WhirlWind = true; + WhirlWindEnd_Timer = 15000; + } else WhirlWind_Timer -= diff; + + if (AggroReset_Timer <= diff) + { + //Attack random Gamers + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget) + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + + AggroReset = true; + AggroReset_Timer = 2000 + rand()%3000; + } else AggroReset_Timer -= diff; + + if (AggroReset) + { + if (AggroResetEnd_Timer <= diff) + { + AggroReset = false; + AggroResetEnd_Timer = 5000; + AggroReset_Timer = 35000 + rand()%10000; + } else AggroResetEnd_Timer -= diff; + } + + //If she is 20% enrage + if (!Enraged) + { + if (me->GetHealth()*100 / me->GetMaxHealth() <= 20 && !me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } + } + + //After 10 minutes hard enrage + if (!EnragedHard) + { + if (EnrageHard_Timer <= diff) + { + DoCast(me, SPELL_ENRAGEHARD); + EnragedHard = true; + } else EnrageHard_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + } +}; + +struct mob_sartura_royal_guardAI : public ScriptedAI +{ + mob_sartura_royal_guardAI(Creature *c) : ScriptedAI(c) {} + + uint32 WhirlWind_Timer; + uint32 WhirlWindRandom_Timer; + uint32 WhirlWindEnd_Timer; + uint32 AggroReset_Timer; + uint32 AggroResetEnd_Timer; + uint32 KnockBack_Timer; + + bool WhirlWind; + bool AggroReset; + + void Reset() + { + WhirlWind_Timer = 30000; + WhirlWindRandom_Timer = 3000 + rand()%4000; + WhirlWindEnd_Timer = 15000; + AggroReset_Timer = 45000 + rand()%10000; + AggroResetEnd_Timer = 5000; + KnockBack_Timer = 10000; + + WhirlWind = false; + AggroReset = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!WhirlWind && WhirlWind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWINDADD); + WhirlWind = true; + WhirlWind_Timer = 25000 + rand()%15000; + WhirlWindEnd_Timer = 15000; + } else WhirlWind_Timer -= diff; + + if (WhirlWind) + { + if (WhirlWindRandom_Timer <= diff) + { + //Attack random Gamers + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget) + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + + WhirlWindRandom_Timer = 3000 + rand()%4000; + } else WhirlWindRandom_Timer -= diff; + + if (WhirlWindEnd_Timer <= diff) + { + WhirlWind = false; + } else WhirlWindEnd_Timer -= diff; + } + + if (!WhirlWind) + { + if (AggroReset_Timer <= diff) + { + //Attack random Gamers + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget) + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + + AggroReset = true; + AggroReset_Timer = 2000 + rand()%3000; + } else AggroReset_Timer -= diff; + + if (KnockBack_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWINDADD); + KnockBack_Timer = 10000 + rand()%10000; + } else KnockBack_Timer -= diff; + } + + if (AggroReset) + { + if (AggroResetEnd_Timer <= diff) + { + AggroReset = false; + AggroResetEnd_Timer = 5000; + AggroReset_Timer = 30000 + rand()%10000; + } else AggroResetEnd_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_sartura(Creature* pCreature) +{ + return new boss_sarturaAI (pCreature); +} + +CreatureAI* GetAI_mob_sartura_royal_guard(Creature* pCreature) +{ + return new mob_sartura_royal_guardAI (pCreature); +} + +void AddSC_boss_sartura() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_sartura"; + newscript->GetAI = &GetAI_boss_sartura; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_sartura_royal_guard"; + newscript->GetAI = &GetAI_mob_sartura_royal_guard; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp new file mode 100644 index 00000000000..7e52bed750c --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp @@ -0,0 +1,298 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Skeram +SD%Complete: 75 +SDComment: Mind Control buggy. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" +#include "Group.h" + +#define SAY_AGGRO1 -1531000 +#define SAY_AGGRO2 -1531001 +#define SAY_AGGRO3 -1531002 +#define SAY_SLAY1 -1531003 +#define SAY_SLAY2 -1531004 +#define SAY_SLAY3 -1531005 +#define SAY_SPLIT -1531006 +#define SAY_DEATH -1531007 + +#define SPELL_ARCANE_EXPLOSION 25679 +#define SPELL_EARTH_SHOCK 26194 +#define SPELL_TRUE_FULFILLMENT4 26526 +#define SPELL_BLINK 28391 + +class ov_mycoordinates +{ + public: + float x,y,z,r; + ov_mycoordinates(float cx, float cy, float cz, float cr) + { + x = cx; y = cy; z = cz; r = cr; + } +}; + +struct boss_skeramAI : public ScriptedAI +{ + boss_skeramAI(Creature *c) : ScriptedAI(c) + { + IsImage = false; + } + + uint32 ArcaneExplosion_Timer; + uint32 EarthShock_Timer; + uint32 FullFillment_Timer; + uint32 Blink_Timer; + uint32 Invisible_Timer; + + bool Images75; + bool Images50; + bool Images25; + bool IsImage; + bool Invisible; + + void Reset() + { + ArcaneExplosion_Timer = 6000 + rand()%6000; + EarthShock_Timer = 2000; + FullFillment_Timer = 15000; + Blink_Timer = 8000 + rand()%12000; + Invisible_Timer = 500; + + Images75 = false; + Images50 = false; + Images25 = false; + Invisible = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + if (IsImage) + me->setDeathState(JUST_DIED); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit* /*Killer*/) + { + if (!IsImage) + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + if (IsImage || Images75) + return; + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 8000 + rand()%10000; + } else ArcaneExplosion_Timer -= diff; + + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + //Make sure our attack is ready and we arn't currently casting + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + }else + { + //EarthShock_Timer + if (EarthShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_EARTH_SHOCK); + EarthShock_Timer = 1000; + } else EarthShock_Timer -= diff; + } + + //Blink_Timer + if (Blink_Timer <= diff) + { + //DoCast(me, SPELL_BLINK); + switch (urand(0,2)) + { + case 0: + me->GetMap()->CreatureRelocation(me, -8340.782227,2083.814453,125.648788,0.0f); + DoResetThreat(); + break; + case 1: + me->GetMap()->CreatureRelocation(me, -8341.546875,2118.504639,133.058151,0.0f); + DoResetThreat(); + break; + case 2: + me->GetMap()->CreatureRelocation(me, -8318.822266,2058.231201,133.058151,0.0f); + DoResetThreat(); + break; + } + DoStopAttack(); + + Blink_Timer= 20000 + rand()%20000; + } else Blink_Timer -= diff; + + int procent = (int) (me->GetHealth()*100 / me->GetMaxHealth() +0.5); + + //Summoning 2 Images and teleporting to a random position on 75% health + if ((!Images75 && !IsImage) && (procent <= 75 && procent > 70)) + DoSplit(75); + + //Summoning 2 Images and teleporting to a random position on 50% health + if ((!Images50 && !IsImage) && + (procent <= 50 && procent > 45)) + DoSplit(50); + + //Summoning 2 Images and teleporting to a random position on 25% health + if ((!Images25 && !IsImage) && (procent <= 25 && procent > 20)) + DoSplit(25); + + //Invisible_Timer + if (Invisible) + { + if (Invisible_Timer <= diff) + { + //Making Skeram visible after telporting + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + Invisible_Timer = 2500; + Invisible = false; + } else Invisible_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void DoSplit(int atPercent /* 75 50 25 */) + { + DoScriptText(SAY_SPLIT, me); + + ov_mycoordinates *place1 = new ov_mycoordinates(-8340.782227,2083.814453,125.648788,0); + ov_mycoordinates *place2 = new ov_mycoordinates(-8341.546875,2118.504639,133.058151,0); + ov_mycoordinates *place3 = new ov_mycoordinates(-8318.822266,2058.231201,133.058151,0); + + ov_mycoordinates *bossc=place1, *i1=place2, *i2=place3; + + switch (urand(0,2)) + { + case 0: + bossc=place1; + i1=place2; + i2=place3; + break; + case 1: + bossc=place2; + i1=place1; + i2=place3; + break; + case 2: + bossc=place3; + i1=place1; + i2=place2; + break; + } + + for (uint16 i = 0; i < 41; ++i) + { + if (Player *pTarget = CAST_PLR(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))) + { + if (Group *pGrp = pTarget->GetGroup()) + for (uint8 ico = 0; ico < TARGETICONCOUNT; ++ico) + { + //if (grp->m_targetIcons[ico] == me->GetGUID()) -- private member :( + pGrp->SetTargetIcon(ico, 0, 0); + } + + break; + } + } + + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_OFF); + me->GetMap()->CreatureRelocation(me, bossc->x, bossc->y, bossc->z, bossc->r); + Invisible = true; + delete place1; + delete place2; + delete place3; + DoResetThreat(); + DoStopAttack(); + + switch (atPercent) + { + case 75: Images75 = true; break; + case 50: Images50 = true; break; + case 25: Images25 = true; break; + } + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + Creature *Image1 = me->SummonCreature(15263, i1->x, i1->y, i1->z, i1->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); + if (Image1) + { + Image1->SetMaxHealth(me->GetMaxHealth() / 5); + Image1->SetHealth(me->GetHealth() / 5); + if (pTarget) + Image1->AI()->AttackStart(pTarget); + CAST_AI(boss_skeramAI, Image1->AI())->IsImage = true; + } + + Creature *Image2 = me->SummonCreature(15263,i2->x, i2->y, i2->z, i2->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); + if (Image2) + { + Image2->SetMaxHealth(me->GetMaxHealth() / 5); + Image2->SetHealth(me->GetHealth() / 5); + if (pTarget) + Image2->AI()->AttackStart(pTarget); + CAST_AI(boss_skeramAI, Image2->AI())->IsImage = true; + } + Invisible = true; + } + +}; + +CreatureAI* GetAI_boss_skeram(Creature* pCreature) +{ + return new boss_skeramAI (pCreature); +} + +void AddSC_boss_skeram() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_skeram"; + newscript->GetAI = &GetAI_boss_skeram; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp new file mode 100644 index 00000000000..73f17485f7f --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp @@ -0,0 +1,596 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Twinemperors +SD%Complete: 95 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" +#include "WorldPacket.h" + +#include "Item.h" +#include "Spell.h" + +#define SPELL_HEAL_BROTHER 7393 +#define SPELL_TWIN_TELEPORT 800 // CTRA watches for this spell to start its teleport timer +#define SPELL_TWIN_TELEPORT_VISUAL 26638 // visual + +#define SPELL_EXPLODEBUG 804 +#define SPELL_MUTATE_BUG 802 + +#define SOUND_VN_DEATH 8660 //8660 - Death - Feel +#define SOUND_VN_AGGRO 8661 //8661 - Aggro - Let none +#define SOUND_VN_KILL 8662 //8661 - Kill - your fate + +#define SOUND_VL_AGGRO 8657 //8657 - Aggro - To Late +#define SOUND_VL_KILL 8658 //8658 - Kill - You will not +#define SOUND_VL_DEATH 8659 //8659 - Death + +#define PULL_RANGE 50 +#define ABUSE_BUG_RANGE 20 +#define SPELL_BERSERK 26662 +#define TELEPORTTIME 30000 + +#define SPELL_UPPERCUT 26007 +#define SPELL_UNBALANCING_STRIKE 26613 + +#define VEKLOR_DIST 20 // VL will not come to melee when attacking + +#define SPELL_SHADOWBOLT 26006 +#define SPELL_BLIZZARD 26607 +#define SPELL_ARCANEBURST 568 + +struct boss_twinemperorsAI : public ScriptedAI +{ + boss_twinemperorsAI(Creature *c): ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Heal_Timer; + uint32 Teleport_Timer; + bool AfterTeleport; + uint32 AfterTeleportTimer; + bool DontYellWhenDead; + uint32 Abuse_Bug_Timer, BugsTimer; + bool tspellcasted; + uint32 EnrageTimer; + + virtual bool IAmVeklor() = 0; + virtual void Reset() = 0; + virtual void CastSpellOnBug(Creature *pTarget) = 0; + + void TwinReset() + { + Heal_Timer = 0; // first heal immediately when they get close together + Teleport_Timer = TELEPORTTIME; + AfterTeleport = false; + tspellcasted = false; + AfterTeleportTimer = 0; + Abuse_Bug_Timer = 10000 + rand()%7000; + BugsTimer = 2000; + me->clearUnitState(UNIT_STAT_STUNNED); + DontYellWhenDead = false; + EnrageTimer = 15*60000; + } + + Creature *GetOtherBoss() + { + if (pInstance) + return Unit::GetCreature(*me, pInstance->GetData64(IAmVeklor() ? DATA_VEKNILASH : DATA_VEKLOR)); + else + return NULL; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + Unit *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + float dPercent = ((float)damage) / ((float)me->GetMaxHealth()); + int odmg = (int)(dPercent * ((float)pOtherBoss->GetMaxHealth())); + int ohealth = pOtherBoss->GetHealth()-odmg; + pOtherBoss->SetHealth(ohealth > 0 ? ohealth : 0); + if (ohealth <= 0) + { + pOtherBoss->setDeathState(JUST_DIED); + pOtherBoss->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + } + + void JustDied(Unit* /*Killer*/) + { + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + pOtherBoss->SetHealth(0); + pOtherBoss->setDeathState(JUST_DIED); + pOtherBoss->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + CAST_AI(boss_twinemperorsAI, pOtherBoss->AI())->DontYellWhenDead = true; + } + if (!DontYellWhenDead) // I hope AI is not threaded + DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_DEATH : SOUND_VN_DEATH); + } + + void KilledUnit(Unit* /*victim*/) + { + DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_KILL : SOUND_VN_KILL); + } + + void EnterCombat(Unit * who) + { + DoZoneInCombat(); + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + // TODO: we should activate the other boss location so he can start attackning even if nobody + // is near I dont know how to do that + ScriptedAI *otherAI = CAST_AI(ScriptedAI, pOtherBoss->AI()); + if (!pOtherBoss->isInCombat()) + { + DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_AGGRO : SOUND_VN_AGGRO); + otherAI->AttackStart(who); + otherAI->DoZoneInCombat(); + } + } + } + + void SpellHit(Unit *caster, const SpellEntry *entry) + { + if (caster == me) + return; + + Creature *pOtherBoss = GetOtherBoss(); + if (entry->Id != SPELL_HEAL_BROTHER || !pOtherBoss) + return; + + // add health so we keep same percentage for both brothers + uint32 mytotal = me->GetMaxHealth(), histotal = pOtherBoss->GetMaxHealth(); + float mult = ((float)mytotal) / ((float)histotal); + if (mult < 1) + mult = 1.0f/mult; + #define HEAL_BROTHER_AMOUNT 30000.0f + uint32 largerAmount = (uint32)((HEAL_BROTHER_AMOUNT * mult) - HEAL_BROTHER_AMOUNT); + + if (mytotal > histotal) + { + uint32 h = me->GetHealth()+largerAmount; + me->SetHealth(std::min(mytotal, h)); + } + else + { + uint32 h = pOtherBoss->GetHealth()+largerAmount; + pOtherBoss->SetHealth(std::min(histotal, h)); + } + } + + void TryHealBrother(uint32 diff) + { + if (IAmVeklor()) // this spell heals caster and the other brother so let VN cast it + return; + + if (Heal_Timer <= diff) + { + Unit *pOtherBoss = GetOtherBoss(); + if (pOtherBoss && pOtherBoss->IsWithinDist(me,60)) + { + DoCast(pOtherBoss, SPELL_HEAL_BROTHER); + Heal_Timer = 1000; + } + } else Heal_Timer -= diff; + } + + void TeleportToMyBrother() + { + if (!pInstance) + return; + + Teleport_Timer = TELEPORTTIME; + + if (IAmVeklor()) + return; // mechanics handled by veknilash so they teleport exactly at the same time and to correct coordinates + + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + //me->MonsterYell("Teleporting ...", LANG_UNIVERSAL, 0); + float other_x = pOtherBoss->GetPositionX(); + float other_y = pOtherBoss->GetPositionY(); + float other_z = pOtherBoss->GetPositionZ(); + float other_o = pOtherBoss->GetOrientation(); + + Map *thismap = me->GetMap(); + thismap->CreatureRelocation(pOtherBoss, me->GetPositionX(), + me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + thismap->CreatureRelocation(me, other_x, other_y, other_z, other_o); + + SetAfterTeleport(); + CAST_AI(boss_twinemperorsAI, pOtherBoss->AI())->SetAfterTeleport(); + } + } + + void SetAfterTeleport() + { + me->InterruptNonMeleeSpells(false); + DoStopAttack(); + DoResetThreat(); + DoCast(me, SPELL_TWIN_TELEPORT_VISUAL); + me->addUnitState(UNIT_STAT_STUNNED); + AfterTeleport = true; + AfterTeleportTimer = 2000; + tspellcasted = false; + } + + bool TryActivateAfterTTelep(uint32 diff) + { + if (AfterTeleport) + { + if (!tspellcasted) + { + me->clearUnitState(UNIT_STAT_STUNNED); + DoCast(me, SPELL_TWIN_TELEPORT); + me->addUnitState(UNIT_STAT_STUNNED); + } + + tspellcasted = true; + + if (AfterTeleportTimer <= diff) + { + AfterTeleport = false; + me->clearUnitState(UNIT_STAT_STUNNED); + if (Unit *nearu = me->SelectNearestTarget(100)) + { + //DoYell(nearu->GetName(), LANG_UNIVERSAL, 0); + AttackStart(nearu); + me->AddThreat(nearu, 10000); + } + return true; + } + else + { + AfterTeleportTimer -= diff; + // update important timers which would otherwise get skipped + if (EnrageTimer > diff) + EnrageTimer -= diff; + else + EnrageTimer = 0; + if (Teleport_Timer > diff) + Teleport_Timer -= diff; + else + Teleport_Timer = 0; + return false; + } + } + else + { + return true; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + float attackRadius = me->GetAttackDistance(who); + if (attackRadius < PULL_RANGE) + attackRadius = PULL_RANGE; + if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= /*CREATURE_Z_ATTACK_RANGE*/7 /*there are stairs*/) + { + //if (who->HasStealthAura()) + // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + } + + Creature *RespawnNearbyBugsAndGetOne() + { + std::list lUnitList; + me->GetCreatureListWithEntryInGrid(lUnitList,15316,150.0f); + me->GetCreatureListWithEntryInGrid(lUnitList,15317,150.0f); + + if (lUnitList.empty()) + return NULL; + + Creature *nearb = NULL; + + for (std::list::const_iterator iter = lUnitList.begin(); iter != lUnitList.end(); ++iter) + { + Creature *c = *iter; + if (c) + { + if (c->isDead()) + { + c->Respawn(); + c->setFaction(7); + c->RemoveAllAuras(); + } + if (c->IsWithinDistInMap(me, ABUSE_BUG_RANGE)) + { + if (!nearb || (rand()%4) == 0) + nearb = c; + } + } + } + return nearb; + } + + void HandleBugs(uint32 diff) + { + if (BugsTimer < diff || Abuse_Bug_Timer <= diff) + { + Creature *c = RespawnNearbyBugsAndGetOne(); + if (Abuse_Bug_Timer <= diff) + { + if (c) + { + CastSpellOnBug(c); + Abuse_Bug_Timer = 10000 + rand()%7000; + } + else + { + Abuse_Bug_Timer = 1000; + } + } + else + { + Abuse_Bug_Timer -= diff; + } + BugsTimer = 2000; + } + else + { + BugsTimer -= diff; + Abuse_Bug_Timer -= diff; + } + } + + void CheckEnrage(uint32 diff) + { + if (EnrageTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(true)) + { + DoCast(me, SPELL_BERSERK); + EnrageTimer = 60*60000; + } else EnrageTimer = 0; + } else EnrageTimer-=diff; + } +}; + +struct boss_veknilashAI : public boss_twinemperorsAI +{ + bool IAmVeklor() {return false;} + boss_veknilashAI(Creature *c) : boss_twinemperorsAI(c) {} + + uint32 UpperCut_Timer; + uint32 UnbalancingStrike_Timer; + uint32 Scarabs_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Summoned; + + void Reset() + { + TwinReset(); + UpperCut_Timer = 14000 + rand()%15000; + UnbalancingStrike_Timer = 8000 + rand()%10000; + Scarabs_Timer = 7000 + rand()%7000; + + //Added. Can be removed if its included in DB. + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + } + + void CastSpellOnBug(Creature *pTarget) + { + pTarget->setFaction(14); + pTarget->AI()->AttackStart(me->getThreatManager().getHostilTarget()); + pTarget->AddAura(SPELL_MUTATE_BUG, pTarget); + pTarget->SetHealth(pTarget->GetMaxHealth()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!TryActivateAfterTTelep(diff)) + return; + + //UnbalancingStrike_Timer + if (UnbalancingStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE); + UnbalancingStrike_Timer = 8000+rand()%12000; + } else UnbalancingStrike_Timer -= diff; + + if (UpperCut_Timer <= diff) + { + Unit* randomMelee = SelectTarget(SELECT_TARGET_RANDOM, 0, NOMINAL_MELEE_RANGE, true); + if (randomMelee) + DoCast(randomMelee, SPELL_UPPERCUT); + UpperCut_Timer = 15000+rand()%15000; + } else UpperCut_Timer -= diff; + + HandleBugs(diff); + + //Heal brother when 60yrds close + TryHealBrother(diff); + + //Teleporting to brother + if (Teleport_Timer <= diff) + { + TeleportToMyBrother(); + } else Teleport_Timer -= diff; + + CheckEnrage(diff); + + DoMeleeAttackIfReady(); + } +}; + +struct boss_veklorAI : public boss_twinemperorsAI +{ + bool IAmVeklor() {return true;} + boss_veklorAI(Creature *c) : boss_twinemperorsAI(c) {} + + uint32 ShadowBolt_Timer; + uint32 Blizzard_Timer; + uint32 ArcaneBurst_Timer; + uint32 Scorpions_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Summoned; + + void Reset() + { + TwinReset(); + ShadowBolt_Timer = 0; + Blizzard_Timer = 15000 + rand()%5000; + ArcaneBurst_Timer = 1000; + Scorpions_Timer = 7000 + rand()%7000; + + //Added. Can be removed if its included in DB. + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0); + } + + void CastSpellOnBug(Creature *pTarget) + { + pTarget->setFaction(14); + pTarget->AddAura(SPELL_EXPLODEBUG, pTarget); + pTarget->SetHealth(pTarget->GetMaxHealth()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // reset arcane burst after teleport - we need to do this because + // when VL jumps to VN's location there will be a warrior who will get only 2s to run away + // which is almost impossible + if (AfterTeleport) + ArcaneBurst_Timer = 5000; + if (!TryActivateAfterTTelep(diff)) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) + { + if (!me->IsWithinDist(me->getVictim(), 45.0f)) + me->GetMotionMaster()->MoveChase(me->getVictim(), VEKLOR_DIST, 0); + else + DoCast(me->getVictim(), SPELL_SHADOWBOLT); + ShadowBolt_Timer = 2000; + } else ShadowBolt_Timer -= diff; + + //Blizzard_Timer + if (Blizzard_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45, true); + if (pTarget) + DoCast(pTarget, SPELL_BLIZZARD); + Blizzard_Timer = 15000+rand()%15000; + } else Blizzard_Timer -= diff; + + if (ArcaneBurst_Timer <= diff) + { + Unit *mvic; + if ((mvic=SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) != NULL) + { + DoCast(mvic, SPELL_ARCANEBURST); + ArcaneBurst_Timer = 5000; + } + } else ArcaneBurst_Timer -= diff; + + HandleBugs(diff); + + //Heal brother when 60yrds close + TryHealBrother(diff); + + //Teleporting to brother + if (Teleport_Timer <= diff) + { + TeleportToMyBrother(); + } else Teleport_Timer -= diff; + + CheckEnrage(diff); + + //VL doesn't melee + //DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + // VL doesn't melee + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); + me->AddThreat(who, 0.0f); + } + } + } +}; + +CreatureAI* GetAI_boss_veknilash(Creature* pCreature) +{ + return new boss_veknilashAI (pCreature); +} + +CreatureAI* GetAI_boss_veklor(Creature* pCreature) +{ + return new boss_veklorAI (pCreature); +} + +void AddSC_boss_twinemperors() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_veknilash"; + newscript->GetAI = &GetAI_boss_veknilash; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_veklor"; + newscript->GetAI = &GetAI_boss_veklor; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp new file mode 100644 index 00000000000..f5e71a35bae --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp @@ -0,0 +1,30 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Viscidus +SD%Complete: 0 +SDComment: place holder +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_POISON_SHOCK 25993 +#define SPELL_POISONBOLT_VOLLEY 25991 + +#define SPELL_TOXIN_CLOUD 25989 + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp new file mode 100644 index 00000000000..1125a0c8623 --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp @@ -0,0 +1,166 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Temple_of_Ahnqiraj +SD%Complete: 80 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" + +struct instance_temple_of_ahnqiraj : public ScriptedInstance +{ + instance_temple_of_ahnqiraj(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + //If Vem is dead... + bool IsBossDied[3]; + + //Storing Skeram, Vem and Kri. + uint64 SkeramGUID; + uint64 VemGUID; + uint64 KriGUID; + uint64 VeklorGUID; + uint64 VeknilashGUID; + + uint32 BugTrioDeathCount; + + uint32 CthunPhase; + + void Initialize() + { + IsBossDied[0] = false; + IsBossDied[1] = false; + IsBossDied[2] = false; + + SkeramGUID = 0; + VemGUID = 0; + KriGUID = 0; + VeklorGUID = 0; + VeknilashGUID = 0; + + BugTrioDeathCount = 0; + + CthunPhase = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case 15263: SkeramGUID = pCreature->GetGUID(); break; + case 15544: VemGUID = pCreature->GetGUID(); break; + case 15511: KriGUID = pCreature->GetGUID(); break; + case 15276: VeklorGUID = pCreature->GetGUID(); break; + case 15275: VeknilashGUID = pCreature->GetGUID(); break; + } + } + + bool IsEncounterInProgress() const + { + //not active in AQ40 + return false; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_VEMISDEAD: + if (IsBossDied[0]) + return 1; + break; + + case DATA_VEKLORISDEAD: + if (IsBossDied[1]) + return 1; + break; + + case DATA_VEKNILASHISDEAD: + if (IsBossDied[2]) + return 1; + break; + + case DATA_BUG_TRIO_DEATH: + return BugTrioDeathCount; + + case DATA_CTHUN_PHASE: + return CthunPhase; + } + return 0; + } + + uint64 GetData64 (uint32 identifier) + { + switch(identifier) + { + case DATA_SKERAM: + return SkeramGUID; + case DATA_VEM: + return VemGUID; + case DATA_KRI: + return KriGUID; + case DATA_VEKLOR: + return VeklorGUID; + case DATA_VEKNILASH: + return VeknilashGUID; + } + return 0; + } // end GetData64 + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_VEM_DEATH: + IsBossDied[0] = true; + break; + + case DATA_BUG_TRIO_DEATH: + ++BugTrioDeathCount; + break; + + case DATA_VEKLOR_DEATH: + IsBossDied[1] = true; + break; + + case DATA_VEKNILASH_DEATH: + IsBossDied[2] = true; + break; + + case DATA_CTHUN_PHASE: + CthunPhase = data; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_temple_of_ahnqiraj(Map* pMap) +{ + return new instance_temple_of_ahnqiraj(pMap); +} + +void AddSC_instance_temple_of_ahnqiraj() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_temple_of_ahnqiraj"; + newscript->GetInstanceData = &GetInstanceData_instance_temple_of_ahnqiraj; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp new file mode 100644 index 00000000000..074f9ed68ae --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp @@ -0,0 +1,296 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: mob_anubisath_sentinel +SD%Complete: 95 +SDComment: Shadow storm is not properly implemented in core it should only pTarget ppl outside of melee range. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "WorldPacket.h" + +#include "Item.h" +#include "Player.h" +#include "Spell.h" + +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" + +#define SPELL_MENDING_BUFF 2147 + +#define SPELL_KNOCK_BUFF 21737 +#define SPELL_KNOCK 25778 +#define SPELL_MANAB_BUFF 812 +#define SPELL_MANAB 25779 + +#define SPELL_REFLECTAF_BUFF 13022 +#define SPELL_REFLECTSFr_BUFF 19595 +#define SPELL_THORNS_BUFF 25777 + +#define SPELL_THUNDER_BUFF 2834 +#define SPELL_THUNDER 8732 + +#define SPELL_MSTRIKE_BUFF 9347 +#define SPELL_MSTRIKE 24573 + +#define SPELL_STORM_BUFF 2148 +#define SPELL_STORM 26546 + +struct aqsentinelAI : public ScriptedAI +{ + uint32 ability; + int abselected; + + void selectAbility(int asel) + { + switch (asel) + { + case 0: ability = SPELL_MENDING_BUFF;break; + case 1: ability = SPELL_KNOCK_BUFF;break; + case 2: ability = SPELL_MANAB_BUFF;break; + case 3: ability = SPELL_REFLECTAF_BUFF;break; + case 4: ability = SPELL_REFLECTSFr_BUFF;break; + case 5: ability = SPELL_THORNS_BUFF;break; + case 6: ability = SPELL_THUNDER_BUFF;break; + case 7: ability = SPELL_MSTRIKE_BUFF;break; + case 8: ability = SPELL_STORM_BUFF;break; + } + } + + aqsentinelAI(Creature *c) : ScriptedAI(c) + { + ClearBuddyList(); + abselected = 0; // just initialization of variable + } + + uint64 NearbyGUID[3]; + + void ClearBuddyList() + { + NearbyGUID[0] = NearbyGUID[1] = NearbyGUID[2] = 0; + } + + void AddBuddyToList(uint64 CreatureGUID) + { + if (CreatureGUID == me->GetGUID()) + return; + + for (int i=0; i<3; ++i) + { + if (NearbyGUID[i] == CreatureGUID) + return; + if (!NearbyGUID[i]) + { + NearbyGUID[i] = CreatureGUID; + return; + } + } + } + + void GiveBuddyMyList(Creature *c) + { + aqsentinelAI *cai = CAST_AI(aqsentinelAI, (c)->AI()); + for (int i=0; i<3; ++i) + if (NearbyGUID[i] && NearbyGUID[i] != c->GetGUID()) + cai->AddBuddyToList(NearbyGUID[i]); + cai->AddBuddyToList(me->GetGUID()); + } + + void SendMyListToBuddies() + { + for (int i=0; i<3; ++i) + if (Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[i])) + GiveBuddyMyList(pNearby); + } + + void CallBuddiesToAttack(Unit *who) + { + for (int i=0; i<3; ++i) + { + Creature *c = Unit::GetCreature(*me, NearbyGUID[i]); + if (c) + { + if (!c->isInCombat()) + { + c->SetNoCallAssistance(true); + if (c->AI()) + c->AI()->AttackStart(who); + } + } + } + } + + void AddSentinelsNear(Unit * /*nears*/) + { + std::list assistList; + me->GetCreatureListWithEntryInGrid(assistList,15264,70.0f); + + if (assistList.empty()) + return; + + for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + AddBuddyToList((*iter)->GetGUID()); + } + + int pickAbilityRandom(bool *chosenAbilities) + { + for (int t = 0; t < 2; ++t) + { + for (int i = !t ? (rand()%9) : 0; i < 9; ++i) + { + if (!chosenAbilities[i]) + { + chosenAbilities[i] = true; + return i; + } + } + } + return 0; // should never happen + } + + void GetOtherSentinels(Unit *who) + { + bool *chosenAbilities = new bool[9]; + memset(chosenAbilities, 0, 9*sizeof(bool)); + selectAbility(pickAbilityRandom(chosenAbilities)); + + ClearBuddyList(); + AddSentinelsNear(me); + int bli; + for (bli = 0; bli < 3; ++bli) + { + if (!NearbyGUID[bli]) + break; + + Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[bli]); + if (!pNearby) + break; + + AddSentinelsNear(pNearby); + CAST_AI(aqsentinelAI, pNearby->AI())->gatherOthersWhenAggro = false; + CAST_AI(aqsentinelAI, pNearby->AI())->selectAbility(pickAbilityRandom(chosenAbilities)); + } + /*if (bli < 3) + DoYell("I dont have enough buddies.", LANG_NEUTRAL, 0);*/ + SendMyListToBuddies(); + CallBuddiesToAttack(who); + + delete[] chosenAbilities; + } + + bool gatherOthersWhenAggro; + + void Reset() + { + if (!me->isDead()) + { + for (int i=0; i<3; ++i) + { + if (!NearbyGUID[i]) + continue; + if (Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[i])) + { + if (pNearby->isDead()) + pNearby->Respawn(); + } + } + } + ClearBuddyList(); + gatherOthersWhenAggro = true; + } + + void GainSentinelAbility(uint32 id) + { + me->AddAura(id, me); + } + + void EnterCombat(Unit * who) + { + if (gatherOthersWhenAggro) + GetOtherSentinels(who); + + GainSentinelAbility(ability); + DoZoneInCombat(); + } + + void JustDied(Unit* /*who*/) + { + for (int ni=0; ni<3; ++ni) + { + Creature *sent = Unit::GetCreature(*me, NearbyGUID[ni]); + if (!sent) + continue; + if (sent->isDead()) + continue; + int h = sent->GetHealth() + (sent->GetMaxHealth() / 2); + if (h > sent->GetMaxHealth()) + h = sent->GetMaxHealth(); + sent->SetHealth(h); + CAST_AI(aqsentinelAI, sent->AI())->GainSentinelAbility(ability); + } + } + + Unit *GetHatedManaUser() const + { + std::list::const_iterator i; + for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit->getPowerType() == POWER_MANA) + return pUnit; + } + return NULL; + } + + Unit* GetAuraEffectTriggerTarget(uint32 spellId, uint8 /*effIndex*/) const + { + switch (spellId) + { + case SPELL_KNOCK_BUFF: + case SPELL_THUNDER_BUFF: + case SPELL_MSTRIKE_BUFF: + case SPELL_STORM_BUFF: + return me->getVictim(); + + case SPELL_MANAB_BUFF: + return GetHatedManaUser(); + + case SPELL_MENDING_BUFF: + case SPELL_REFLECTAF_BUFF: + case SPELL_REFLECTSFr_BUFF: + case SPELL_THORNS_BUFF: + default: + return me; + } + } +}; +CreatureAI* GetAI_mob_anubisath_sentinelAI(Creature* pCreature) +{ + return new aqsentinelAI (pCreature); +} + +void AddSC_mob_anubisath_sentinel() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_anubisath_sentinel"; + newscript->GetAI = &GetAI_mob_anubisath_sentinelAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h new file mode 100644 index 00000000000..5d545ed7c74 --- /dev/null +++ b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h @@ -0,0 +1,23 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_TEMPLE_OF_AHNQIRAJ_H +#define DEF_TEMPLE_OF_AHNQIRAJ_H + +#define DATA_SKERAM 1 +#define DATA_KRI 2 +#define DATA_VEM 3 +#define DATA_VEMISDEAD 4 +#define DATA_VEM_DEATH 5 +#define DATA_VEKLOR 6 +#define DATA_VEKLORISDEAD 7 +#define DATA_VEKLOR_DEATH 8 +#define DATA_VEKNILASH 9 +#define DATA_VEKNILASHISDEAD 10 +#define DATA_VEKNILASH_DEATH 11 +#define DATA_BUG_TRIO_DEATH 14 + +#define DATA_CTHUN_PHASE 20 +#endif + diff --git a/src/server/scripts/Kalimdor/the_barrens.cpp b/src/server/scripts/Kalimdor/the_barrens.cpp new file mode 100644 index 00000000000..04daac96877 --- /dev/null +++ b/src/server/scripts/Kalimdor/the_barrens.cpp @@ -0,0 +1,701 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: The_Barrens +SD%Complete: 90 +SDComment: Quest support: 863, 898, 1719, 2458, 4921, 6981, +SDCategory: Barrens +EndScriptData */ + +/* ContentData +npc_beaten_corpse +npc_gilthares +npc_sputtervalve +npc_taskmaster_fizzule +npc_twiggy_flathead +npc_wizzlecrank_shredder +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_beaten_corpse +######*/ + +#define GOSSIP_CORPSE "Examine corpse in detail..." + +enum eQuests +{ + QUEST_LOST_IN_BATTLE = 4921 +}; + +bool GossipHello_npc_beaten_corpse(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CORPSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(3557, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_beaten_corpse(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF +1) + { + pPlayer->SEND_GOSSIP_MENU(3558, pCreature->GetGUID()); + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + } + return true; +} + +/*###### +# npc_gilthares +######*/ + +enum eGilthares +{ + SAY_GIL_START = -1000370, + SAY_GIL_AT_LAST = -1000371, + SAY_GIL_PROCEED = -1000372, + SAY_GIL_FREEBOOTERS = -1000373, + SAY_GIL_AGGRO_1 = -1000374, + SAY_GIL_AGGRO_2 = -1000375, + SAY_GIL_AGGRO_3 = -1000376, + SAY_GIL_AGGRO_4 = -1000377, + SAY_GIL_ALMOST = -1000378, + SAY_GIL_SWEET = -1000379, + SAY_GIL_FREED = -1000380, + + QUEST_FREE_FROM_HOLD = 898, + AREA_MERCHANT_COAST = 391, + FACTION_ESCORTEE = 232 //guessed, possible not needed for this quest +}; + +struct npc_giltharesAI : public npc_escortAI +{ + npc_giltharesAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void Reset() { } + + void WaypointReached(uint32 uiPointId) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(uiPointId) + { + case 16: + DoScriptText(SAY_GIL_AT_LAST, me, pPlayer); + break; + case 17: + DoScriptText(SAY_GIL_PROCEED, me, pPlayer); + break; + case 18: + DoScriptText(SAY_GIL_FREEBOOTERS, me, pPlayer); + break; + case 37: + DoScriptText(SAY_GIL_ALMOST, me, pPlayer); + break; + case 47: + DoScriptText(SAY_GIL_SWEET, me, pPlayer); + break; + case 53: + DoScriptText(SAY_GIL_FREED, me, pPlayer); + pPlayer->GroupEventHappens(QUEST_FREE_FROM_HOLD, me); + break; + } + } + + void Aggro(Unit* pWho) + { + //not always use + if (rand()%4) + return; + + //only aggro text if not player and only in this area + if (pWho->GetTypeId() != TYPEID_PLAYER && me->GetAreaId() == AREA_MERCHANT_COAST) + { + //appears to be pretty much random (possible only if escorter not in combat with pWho yet?) + DoScriptText(RAND(SAY_GIL_AGGRO_1, SAY_GIL_AGGRO_2, SAY_GIL_AGGRO_3, SAY_GIL_AGGRO_4), me, pWho); + } + } +}; + +CreatureAI* GetAI_npc_gilthares(Creature* pCreature) +{ + return new npc_giltharesAI(pCreature); +} + +bool QuestAccept_npc_gilthares(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_FREE_FROM_HOLD) + { + pCreature->setFaction(FACTION_ESCORTEE); + pCreature->SetStandState(UNIT_STAND_STATE_STAND); + + DoScriptText(SAY_GIL_START, pCreature, pPlayer); + + if (npc_giltharesAI* pEscortAI = CAST_AI(npc_giltharesAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + } + return true; +} + +/*###### +## npc_sputtervalve +######*/ + +#define GOSSIP_SPUTTERVALVE "Can you tell me about this shard?" + +bool GossipHello_npc_sputtervalve(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(6981) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SPUTTERVALVE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_sputtervalve(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->SEND_GOSSIP_MENU(2013, pCreature->GetGUID()); + pPlayer->AreaExploredOrEventHappens(6981); + } + return true; +} + +/*###### +## npc_taskmaster_fizzule +######*/ + +enum eEnums +{ + FACTION_FRIENDLY_F = 35, + SPELL_FLARE = 10113, + SPELL_FOLLY = 10137, +}; + +struct npc_taskmaster_fizzuleAI : public ScriptedAI +{ + npc_taskmaster_fizzuleAI(Creature* c) : ScriptedAI(c) + { + factionNorm = c->getFaction(); + } + + uint32 factionNorm; + bool IsFriend; + uint32 Reset_Timer; + uint8 FlareCount; + + void Reset() + { + IsFriend = false; + Reset_Timer = 120000; + FlareCount = 0; + me->setFaction(factionNorm); + } + + void DoFriend() + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + + me->StopMoving(); + me->GetMotionMaster()->MoveIdle(); + + me->setFaction(FACTION_FRIENDLY_F); + me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_FLARE || spell->Id == SPELL_FOLLY) + { + ++FlareCount; + + if (FlareCount >= 2) + IsFriend = true; + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (IsFriend) + { + if (Reset_Timer <= diff) + { + EnterEvadeMode(); + return; + } else Reset_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void ReceiveEmote(Player* /*pPlayer*/, uint32 emote) + { + if (emote == TEXTEMOTE_SALUTE) + { + if (FlareCount >= 2) + { + if (me->getFaction() == FACTION_FRIENDLY_F) + return; + + DoFriend(); + } + } + } +}; + +CreatureAI* GetAI_npc_taskmaster_fizzule(Creature* pCreature) +{ + return new npc_taskmaster_fizzuleAI(pCreature); +} + +/*##### +## npc_twiggy_flathead +#####*/ + +enum eTwiggyFlathead +{ + NPC_BIG_WILL = 6238, + NPC_AFFRAY_CHALLENGER = 6240, + + SAY_BIG_WILL_READY = -1000123, + SAY_TWIGGY_FLATHEAD_BEGIN = -1000124, + SAY_TWIGGY_FLATHEAD_FRAY = -1000125, + SAY_TWIGGY_FLATHEAD_DOWN = -1000126, + SAY_TWIGGY_FLATHEAD_OVER = -1000127, +}; + +float AffrayChallengerLoc[6][4]= +{ + {-1683, -4326, 2.79, 0}, + {-1682, -4329, 2.79, 0}, + {-1683, -4330, 2.79, 0}, + {-1680, -4334, 2.79, 1.49}, + {-1674, -4326, 2.79, 3.49}, + {-1677, -4334, 2.79, 1.66} +}; + +struct npc_twiggy_flatheadAI : public ScriptedAI +{ + npc_twiggy_flatheadAI(Creature *c) : ScriptedAI(c) {} + + bool EventInProgress; + bool EventGrate; + bool EventBigWill; + bool Challenger_down[6]; + uint32 Wave; + uint32 Wave_Timer; + uint32 Challenger_checker; + uint64 PlayerGUID; + uint64 AffrayChallenger[6]; + uint64 BigWill; + + void Reset() + { + EventInProgress = false; + EventGrate = false; + EventBigWill = false; + Wave_Timer = 600000; + Challenger_checker = 0; + Wave = 0; + PlayerGUID = 0; + + for (uint8 i = 0; i < 6; ++i) + { + AffrayChallenger[i] = 0; + Challenger_down[i] = false; + } + BigWill = 0; + } + + void EnterCombat(Unit * /*who*/) { } + + void MoveInLineOfSight(Unit *who) + { + if (!who || (!who->isAlive())) return; + + if (me->IsWithinDistInMap(who, 10.0f) && (who->GetTypeId() == TYPEID_PLAYER) && CAST_PLR(who)->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE && !EventInProgress) + { + PlayerGUID = who->GetGUID(); + EventInProgress = true; + } + } + + void KilledUnit(Unit * /*victim*/) { } + + void UpdateAI(const uint32 diff) + { + if (EventInProgress) { + Player* pWarrior = NULL; + + if (PlayerGUID) + pWarrior = Unit::GetPlayer(PlayerGUID); + + if (!pWarrior) + return; + + if (!pWarrior->isAlive() && pWarrior->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE) { + EventInProgress = false; + DoScriptText(SAY_TWIGGY_FLATHEAD_DOWN, me); + pWarrior->FailQuest(1719); + + for (uint8 i = 0; i < 6; ++i) + { + if (AffrayChallenger[i]) + { + Creature* pCreature = Unit::GetCreature((*me), AffrayChallenger[i]); + if (pCreature) { + if (pCreature->isAlive()) + { + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->setDeathState(JUST_DIED); + } + } + } + AffrayChallenger[i] = 0; + Challenger_down[i] = false; + } + + if (BigWill) + { + Creature* pCreature = Unit::GetCreature((*me), BigWill); + if (pCreature) { + if (pCreature->isAlive()) { + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->setDeathState(JUST_DIED); + } + } + } + BigWill = 0; + } + + if (!EventGrate && EventInProgress) + { + float x,y,z; + pWarrior->GetPosition(x, y, z); + + if (x >= -1684 && x <= -1674 && y >= -4334 && y <= -4324) { + pWarrior->AreaExploredOrEventHappens(1719); + DoScriptText(SAY_TWIGGY_FLATHEAD_BEGIN, me); + + for (uint8 i = 0; i < 6; ++i) + { + Creature* pCreature = me->SummonCreature(NPC_AFFRAY_CHALLENGER, AffrayChallengerLoc[i][0], AffrayChallengerLoc[i][1], AffrayChallengerLoc[i][2], AffrayChallengerLoc[i][3], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); + if (!pCreature) + continue; + pCreature->setFaction(35); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + AffrayChallenger[i] = pCreature->GetGUID(); + } + Wave_Timer = 5000; + Challenger_checker = 1000; + EventGrate = true; + } + } + else if (EventInProgress) + { + if (Challenger_checker <= diff) + { + for (uint8 i = 0; i < 6; ++i) + { + if (AffrayChallenger[i]) + { + Creature* pCreature = Unit::GetCreature((*me), AffrayChallenger[i]); + if ((!pCreature || (!pCreature->isAlive())) && !Challenger_down[i]) + { + DoScriptText(SAY_TWIGGY_FLATHEAD_DOWN, me); + Challenger_down[i] = true; + } + } + } + Challenger_checker = 1000; + } else Challenger_checker -= diff; + + if (Wave_Timer <= diff) + { + if (AffrayChallenger[Wave] && Wave < 6 && !EventBigWill) + { + DoScriptText(SAY_TWIGGY_FLATHEAD_FRAY, me); + Creature* pCreature = Unit::GetCreature((*me), AffrayChallenger[Wave]); + if (pCreature && (pCreature->isAlive())) + { + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + pCreature->setFaction(14); + pCreature->AI()->AttackStart(pWarrior); + ++Wave; + Wave_Timer = 20000; + } + } + else if (Wave >= 6 && !EventBigWill) { + if (Creature* pCreature = me->SummonCreature(NPC_BIG_WILL, -1722, -4341, 6.12, 6.26, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 480000)) + { + BigWill = pCreature->GetGUID(); + //pCreature->GetMotionMaster()->MovePoint(0, -1693, -4343, 4.32); + //pCreature->GetMotionMaster()->MovePoint(1, -1684, -4333, 2.78); + pCreature->GetMotionMaster()->MovePoint(2, -1682, -4329, 2.79); + pCreature->HandleEmoteCommand(EMOTE_STATE_READYUNARMED); + EventBigWill = true; + Wave_Timer = 1000; + } + } + else if (Wave >= 6 && EventBigWill && BigWill) + { + Creature* pCreature = Unit::GetCreature((*me), BigWill); + if (!pCreature || !pCreature->isAlive()) + { + DoScriptText(SAY_TWIGGY_FLATHEAD_OVER, me); + EventInProgress = false; + EventBigWill = false; + EventGrate = false; + PlayerGUID = 0; + Wave = 0; + } + } + } else Wave_Timer -= diff; + } + } + } +}; + +CreatureAI* GetAI_npc_twiggy_flathead(Creature* pCreature) +{ + return new npc_twiggy_flatheadAI (pCreature); +} + +/*##### +## npc_wizzlecrank_shredder +#####*/ + +enum eEnums_Wizzlecrank +{ + SAY_START = -1000298, + SAY_STARTUP1 = -1000299, + SAY_STARTUP2 = -1000300, + SAY_MERCENARY = -1000301, + SAY_PROGRESS_1 = -1000302, + SAY_PROGRESS_2 = -1000303, + SAY_PROGRESS_3 = -1000304, + SAY_END = -1000305, + + QUEST_ESCAPE = 863, + FACTION_RATCHET = 637, + NPC_PILOT_WIZZ = 3451, + NPC_MERCENARY = 3282, +}; + +struct npc_wizzlecrank_shredderAI : public npc_escortAI +{ + npc_wizzlecrank_shredderAI(Creature* pCreature) : npc_escortAI(pCreature) + { + m_bIsPostEvent = false; + m_uiPostEventTimer = 1000; + m_uiPostEventCount = 0; + } + + bool m_bIsPostEvent; + uint32 m_uiPostEventTimer; + uint32 m_uiPostEventCount; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (me->getStandState() == UNIT_STAND_STATE_DEAD) + me->SetStandState(UNIT_STAND_STATE_STAND); + + m_bIsPostEvent = false; + m_uiPostEventTimer = 1000; + m_uiPostEventCount = 0; + } + } + + void WaypointReached(uint32 uiPointId) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(uiPointId) + { + case 0: + DoScriptText(SAY_STARTUP1, me); + break; + case 9: + SetRun(false); + break; + case 17: + if (Creature* pTemp = me->SummonCreature(NPC_MERCENARY, 1128.489f, -3037.611f, 92.701f, 1.472f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000)) + { + DoScriptText(SAY_MERCENARY, pTemp); + me->SummonCreature(NPC_MERCENARY, 1160.172f, -2980.168f, 97.313f, 3.690f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + } + break; + case 24: + m_bIsPostEvent = true; + break; + } + } + + void WaypointStart(uint32 uiPointId) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(uiPointId) + { + case 9: + DoScriptText(SAY_STARTUP2, me, pPlayer); + break; + case 18: + DoScriptText(SAY_PROGRESS_1, me, pPlayer); + SetRun(); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_PILOT_WIZZ) + me->SetStandState(UNIT_STAND_STATE_DEAD); + + if (pSummoned->GetEntry() == NPC_MERCENARY) + pSummoned->AI()->AttackStart(me); + } + + void UpdateEscortAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + { + if (m_bIsPostEvent) + { + if (m_uiPostEventTimer <= uiDiff) + { + switch(m_uiPostEventCount) + { + case 0: + DoScriptText(SAY_PROGRESS_2, me); + break; + case 1: + DoScriptText(SAY_PROGRESS_3, me); + break; + case 2: + DoScriptText(SAY_END, me); + break; + case 3: + if (Player* pPlayer = GetPlayerForEscort()) + { + pPlayer->GroupEventHappens(QUEST_ESCAPE, me); + me->SummonCreature(NPC_PILOT_WIZZ, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 180000); + } + break; + } + + ++m_uiPostEventCount; + m_uiPostEventTimer = 5000; + } + else + m_uiPostEventTimer -= uiDiff; + } + + return; + } + + DoMeleeAttackIfReady(); + } +}; + +bool QuestAccept_npc_wizzlecrank_shredder(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_ESCAPE) + { + pCreature->setFaction(FACTION_RATCHET); + if (npc_escortAI* pEscortAI = CAST_AI(npc_wizzlecrank_shredderAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_wizzlecrank_shredderAI(Creature* pCreature) +{ + return new npc_wizzlecrank_shredderAI(pCreature); +} + +void AddSC_the_barrens() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_beaten_corpse"; + newscript->pGossipHello = &GossipHello_npc_beaten_corpse; + newscript->pGossipSelect = &GossipSelect_npc_beaten_corpse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_gilthares"; + newscript->GetAI = &GetAI_npc_gilthares; + newscript->pQuestAccept = &QuestAccept_npc_gilthares; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_sputtervalve"; + newscript->pGossipHello = &GossipHello_npc_sputtervalve; + newscript->pGossipSelect = &GossipSelect_npc_sputtervalve; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_taskmaster_fizzule"; + newscript->GetAI = &GetAI_npc_taskmaster_fizzule; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_twiggy_flathead"; + newscript->GetAI = &GetAI_npc_twiggy_flathead; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_wizzlecrank_shredder"; + newscript->GetAI = &GetAI_npc_wizzlecrank_shredderAI; + newscript->pQuestAccept = &QuestAccept_npc_wizzlecrank_shredder; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/thousand_needles.cpp b/src/server/scripts/Kalimdor/thousand_needles.cpp new file mode 100644 index 00000000000..3f54a62dd0b --- /dev/null +++ b/src/server/scripts/Kalimdor/thousand_needles.cpp @@ -0,0 +1,454 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Thousand Needles +SD%Complete: 100 +SDComment: Support for Quest: 1950, 4770, 4904, 4966, 5151. +SDCategory: Thousand Needles +EndScriptData */ + +/* ContentData +npc_kanati +npc_lakota_windsong +npc_swiftmountain +npc_plucky +go_panther_cage +npc_enraged_panther +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*##### +# npc_kanati +######*/ + +enum eKanati +{ + SAY_KAN_START = -1000410, + + QUEST_PROTECT_KANATI = 4966, + NPC_GALAK_ASS = 10720 +}; + +const float m_afGalakLoc[]= {-4867.387695, -1357.353760, -48.226 }; + +struct npc_kanatiAI : public npc_escortAI +{ + npc_kanatiAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void Reset() { } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 0: + DoScriptText(SAY_KAN_START, me); + DoSpawnGalak(); + break; + case 1: + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->GroupEventHappens(QUEST_PROTECT_KANATI, me); + break; + } + } + + void DoSpawnGalak() + { + for (int i = 0; i < 3; ++i) + me->SummonCreature(NPC_GALAK_ASS, + m_afGalakLoc[0], m_afGalakLoc[1], m_afGalakLoc[2], 0.0f, + TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->AI()->AttackStart(me); + } +}; + +CreatureAI* GetAI_npc_kanati(Creature* pCreature) +{ + return new npc_kanatiAI(pCreature); +} + +bool QuestAccept_npc_kanati(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_PROTECT_KANATI) + { + if (npc_kanatiAI* pEscortAI = CAST_AI(npc_kanatiAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest, true); + } + return true; +} + +/*###### +# npc_lakota_windsong +######*/ + +enum eLakota +{ + SAY_LAKO_START = -1000365, + SAY_LAKO_LOOK_OUT = -1000366, + SAY_LAKO_HERE_COME = -1000367, + SAY_LAKO_MORE = -1000368, + SAY_LAKO_END = -1000369, + + QUEST_FREE_AT_LAST = 4904, + NPC_GRIM_BANDIT = 10758, + FACTION_ESCORTEE_LAKO = 232, //guessed + + ID_AMBUSH_1 = 0, + ID_AMBUSH_2 = 2, + ID_AMBUSH_3 = 4 +}; + +float m_afBanditLoc[6][6]= +{ + {-4905.479492, -2062.732666, 84.352}, + {-4915.201172, -2073.528320, 84.733}, + {-4878.883301, -1986.947876, 91.966}, + {-4877.503906, -1966.113403, 91.859}, + {-4767.985352, -1873.169189, 90.192}, + {-4788.861328, -1888.007813, 89.888} +}; + +struct npc_lakota_windsongAI : public npc_escortAI +{ + npc_lakota_windsongAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void Reset() { } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 8: + DoScriptText(SAY_LAKO_LOOK_OUT, me); + DoSpawnBandits(ID_AMBUSH_1); + break; + case 14: + DoScriptText(SAY_LAKO_HERE_COME, me); + DoSpawnBandits(ID_AMBUSH_2); + break; + case 21: + DoScriptText(SAY_LAKO_MORE, me); + DoSpawnBandits(ID_AMBUSH_3); + break; + case 45: + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->GroupEventHappens(QUEST_FREE_AT_LAST, me); + break; + } + } + + void DoSpawnBandits(int uiAmbushId) + { + for (int i = 0; i < 2; ++i) + me->SummonCreature(NPC_GRIM_BANDIT, + m_afBanditLoc[i+uiAmbushId][0], m_afBanditLoc[i+uiAmbushId][1], m_afBanditLoc[i+uiAmbushId][2], 0.0f, + TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + } +}; + +CreatureAI* GetAI_npc_lakota_windsong(Creature* pCreature) +{ + return new npc_lakota_windsongAI(pCreature); +} + +bool QuestAccept_npc_lakota_windsong(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_FREE_AT_LAST) + { + DoScriptText(SAY_LAKO_START, pCreature, pPlayer); + pCreature->setFaction(FACTION_ESCORTEE_LAKO); + + if (npc_lakota_windsongAI* pEscortAI = CAST_AI(npc_lakota_windsongAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + } + return true; +} + +/*###### +# npc_paoka_swiftmountain +######*/ + +enum ePacka +{ + SAY_START = -1000362, + SAY_WYVERN = -1000363, + SAY_COMPLETE = -1000364, + + QUEST_HOMEWARD = 4770, + NPC_WYVERN = 4107, + FACTION_ESCORTEE = 232 //guessed +}; + +float m_afWyvernLoc[3][3]= +{ + {-4990.606, -906.057, -5.343}, + {-4970.241, -927.378, -4.951}, + {-4985.364, -952.528, -5.199} +}; + +struct npc_paoka_swiftmountainAI : public npc_escortAI +{ + npc_paoka_swiftmountainAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void Reset() { } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 15: + DoScriptText(SAY_WYVERN, me); + DoSpawnWyvern(); + break; + case 26: + DoScriptText(SAY_COMPLETE, me); + break; + case 27: + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->GroupEventHappens(QUEST_HOMEWARD, me); + break; + } + } + + void DoSpawnWyvern() + { + for (int i = 0; i < 3; ++i) + me->SummonCreature(NPC_WYVERN, + m_afWyvernLoc[i][0], m_afWyvernLoc[i][1], m_afWyvernLoc[i][2], 0.0f, + TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + } +}; + +CreatureAI* GetAI_npc_paoka_swiftmountain(Creature* pCreature) +{ + return new npc_paoka_swiftmountainAI(pCreature); +} + +bool QuestAccept_npc_paoka_swiftmountain(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_HOMEWARD) + { + DoScriptText(SAY_START, pCreature, pPlayer); + pCreature->setFaction(FACTION_ESCORTEE); + + if (npc_paoka_swiftmountainAI* pEscortAI = CAST_AI(npc_paoka_swiftmountainAI,pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + } + return true; +} + +/*##### +# npc_plucky +######*/ + +#define GOSSIP_P "Please tell me the Phrase.." + +enum ePlucky +{ + FACTION_FRIENDLY = 35, + QUEST_SCOOP = 1950, + SPELL_PLUCKY_HUMAN = 9192, + SPELL_PLUCKY_CHICKEN = 9220 +}; + +struct npc_pluckyAI : public ScriptedAI +{ + npc_pluckyAI(Creature *c) : ScriptedAI(c) { m_uiNormFaction = c->getFaction(); } + + uint32 m_uiNormFaction; + uint32 m_uiResetTimer; + + void Reset() + { + m_uiResetTimer = 120000; + + if (me->getFaction() != m_uiNormFaction) + me->setFaction(m_uiNormFaction); + + if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + DoCast(me, SPELL_PLUCKY_CHICKEN, false); + } + + void ReceiveEmote(Player* pPlayer, uint32 uiTextEmote) + { + if (pPlayer->GetQuestStatus(QUEST_SCOOP) == QUEST_STATUS_INCOMPLETE) + { + if (uiTextEmote == TEXTEMOTE_BECKON) + { + me->setFaction(FACTION_FRIENDLY); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + DoCast(me, SPELL_PLUCKY_HUMAN, false); + } + } + + if (uiTextEmote == TEXTEMOTE_CHICKEN) + { + if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) + return; + else + { + me->setFaction(FACTION_FRIENDLY); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + DoCast(me, SPELL_PLUCKY_HUMAN, false); + me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) + { + if (m_uiResetTimer <= uiDiff) + { + if (!me->getVictim()) + EnterEvadeMode(); + else + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + return; + } + else + m_uiResetTimer -= uiDiff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_npc_plucky(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_SCOOP) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_P, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(738, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_plucky(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CompleteQuest(QUEST_SCOOP); + break; + } + return true; +} + +CreatureAI* GetAI_npc_plucky(Creature* pCreature) +{ + return new npc_pluckyAI(pCreature); +} + +enum ePantherCage +{ + ENRAGED_PANTHER = 10992 +}; + +bool go_panther_cage(Player* pPlayer, GameObject* pGo) +{ + + if (pPlayer->GetQuestStatus(5151) == QUEST_STATUS_INCOMPLETE) + { + if (Creature* panther = pGo->FindNearestCreature(ENRAGED_PANTHER, 5, true)) + { + panther->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + panther->SetReactState(REACT_AGGRESSIVE); + panther->AI()->AttackStart(pPlayer); + } + } + + return true ; +} + +struct npc_enraged_pantherAI : public ScriptedAI +{ + npc_enraged_pantherAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_enraged_panther(Creature* pCreature) +{ + return new npc_enraged_pantherAI(pCreature); +} + +void AddSC_thousand_needles() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_kanati"; + newscript->GetAI = &GetAI_npc_kanati; + newscript->pQuestAccept = &QuestAccept_npc_kanati; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lakota_windsong"; + newscript->GetAI = &GetAI_npc_lakota_windsong; + newscript->pQuestAccept = &QuestAccept_npc_lakota_windsong; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_paoka_swiftmountain"; + newscript->GetAI = &GetAI_npc_paoka_swiftmountain; + newscript->pQuestAccept = &QuestAccept_npc_paoka_swiftmountain; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_plucky"; + newscript->GetAI = &GetAI_npc_plucky; + newscript->pGossipHello = &GossipHello_npc_plucky; + newscript->pGossipSelect = &GossipSelect_npc_plucky; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="npc_enraged_panther"; + newscript->GetAI = &GetAI_npc_enraged_panther; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="go_panther_cage"; + newscript->pGOHello = &go_panther_cage; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/thunder_bluff.cpp b/src/server/scripts/Kalimdor/thunder_bluff.cpp new file mode 100644 index 00000000000..288f00946f0 --- /dev/null +++ b/src/server/scripts/Kalimdor/thunder_bluff.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Thunder_Bluff +SD%Complete: 100 +SDComment: Quest support: 925 +SDCategory: Thunder Bluff +EndScriptData */ + +#include "ScriptedPch.h" + +/*##### +# npc_cairne_bloodhoof +######*/ + +#define SPELL_BERSERKER_CHARGE 16636 +#define SPELL_CLEAVE 16044 +#define SPELL_MORTAL_STRIKE 16856 +#define SPELL_THUNDERCLAP 23931 +#define SPELL_UPPERCUT 22916 + +#define GOSSIP_HCB "I know this is rather silly but a young ward who is a bit shy would like your hoofprint." +//TODO: verify abilities/timers +struct npc_cairne_bloodhoofAI : public ScriptedAI +{ + npc_cairne_bloodhoofAI(Creature* c) : ScriptedAI(c) {} + + uint32 BerserkerCharge_Timer; + uint32 Cleave_Timer; + uint32 MortalStrike_Timer; + uint32 Thunderclap_Timer; + uint32 Uppercut_Timer; + + void Reset() + { + BerserkerCharge_Timer = 30000; + Cleave_Timer = 5000; + MortalStrike_Timer = 10000; + Thunderclap_Timer = 15000; + Uppercut_Timer = 10000; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BerserkerCharge_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + DoCast(pTarget, SPELL_BERSERKER_CHARGE); + BerserkerCharge_Timer = 25000; + } else BerserkerCharge_Timer -= diff; + + if (Uppercut_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_UPPERCUT); + Uppercut_Timer = 20000; + } else Uppercut_Timer -= diff; + + if (Thunderclap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + Thunderclap_Timer = 15000; + } else Thunderclap_Timer -= diff; + + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + MortalStrike_Timer = 15000; + } else MortalStrike_Timer -= diff; + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_cairne_bloodhoof(Creature* pCreature) +{ + return new npc_cairne_bloodhoofAI (pCreature); +} + +bool GossipHello_npc_cairne_bloodhoof(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(925) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HCB, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO); + + pPlayer->SEND_GOSSIP_MENU(7013, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_cairne_bloodhoof(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_SENDER_INFO) + { + pPlayer->CastSpell(pPlayer, 23123, false); + pPlayer->SEND_GOSSIP_MENU(7014, pCreature->GetGUID()); + } + return true; +} + +void AddSC_thunder_bluff() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_cairne_bloodhoof"; + newscript->GetAI = &GetAI_npc_cairne_bloodhoof; + newscript->pGossipHello = &GossipHello_npc_cairne_bloodhoof; + newscript->pGossipSelect = &GossipSelect_npc_cairne_bloodhoof; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/ungoro_crater.cpp b/src/server/scripts/Kalimdor/ungoro_crater.cpp new file mode 100644 index 00000000000..2be4a95eb4b --- /dev/null +++ b/src/server/scripts/Kalimdor/ungoro_crater.cpp @@ -0,0 +1,356 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Ungoro Crater +SD%Complete: 100 +SDComment: Support for Quest: 4245, 4491 +SDCategory: Ungoro Crater +EndScriptData */ + +/* ContentData +npc_a-me +npc_ringo +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "ScriptedFollowerAI.h" + +#define SAY_READY -1100200 +#define SAY_AGGRO1 -1100201 +#define SAY_SEARCH -1100202 +#define SAY_AGGRO2 -1100203 +#define SAY_AGGRO3 -1100204 +#define SAY_FINISH -1100205 + +#define SPELL_DEMORALIZINGSHOUT 13730 + +#define QUEST_CHASING_AME 4245 +#define ENTRY_TARLORD 6519 +#define ENTRY_TARLORD1 6519 +#define ENTRY_STOMPER 6513 + +struct npc_ameAI : public npc_escortAI +{ + npc_ameAI(Creature *c) : npc_escortAI(c) {} + + uint32 DEMORALIZINGSHOUT_Timer; + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch (i) + { + + case 19: + me->SummonCreature(ENTRY_STOMPER, -6391.69, -1730.49, -272.83, 4.96, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + DoScriptText(SAY_AGGRO1, me, pPlayer); + break; + case 28: + DoScriptText(SAY_SEARCH, me, pPlayer); + break; + case 38: + me->SummonCreature(ENTRY_TARLORD, -6370.75, -1382.84, -270.51, 6.06, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + DoScriptText(SAY_AGGRO2, me, pPlayer); + break; + case 49: + me->SummonCreature(ENTRY_TARLORD1, -6324.44, -1181.05, -270.17, 4.34, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + DoScriptText(SAY_AGGRO3, me, pPlayer); + break; + case 55: + DoScriptText(SAY_FINISH, me, pPlayer); + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_CHASING_AME,me); + break; + + } + } + + void Reset() + { + DEMORALIZINGSHOUT_Timer = 5000; + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void JustDied(Unit* /*killer*/) + { + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->FailQuest(QUEST_CHASING_AME); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + if (!UpdateVictim()) + return; + + if (DEMORALIZINGSHOUT_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DEMORALIZINGSHOUT); + DEMORALIZINGSHOUT_Timer = 70000; + } else DEMORALIZINGSHOUT_Timer -= diff; + + } +}; + +bool QuestAccept_npc_ame(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_CHASING_AME) + { + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); + DoScriptText(SAY_READY, pCreature, pPlayer); + pCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + // Change faction so mobs attack + pCreature->setFaction(113); + } + return true; +} + +CreatureAI* GetAI_npc_ame(Creature* pCreature) +{ + return new npc_ameAI(pCreature); +} + +/*#### +# npc_ringo +####*/ + +enum eRingo +{ + SAY_RIN_START_1 = -1000416, + SAY_RIN_START_2 = -1000417, + + SAY_FAINT_1 = -1000418, + SAY_FAINT_2 = -1000419, + SAY_FAINT_3 = -1000420, + SAY_FAINT_4 = -1000421, + + SAY_WAKE_1 = -1000422, + SAY_WAKE_2 = -1000423, + SAY_WAKE_3 = -1000424, + SAY_WAKE_4 = -1000425, + + SAY_RIN_END_1 = -1000426, + SAY_SPR_END_2 = -1000427, + SAY_RIN_END_3 = -1000428, + EMOTE_RIN_END_4 = -1000429, + EMOTE_RIN_END_5 = -1000430, + SAY_RIN_END_6 = -1000431, // signed for 6784 + SAY_SPR_END_7 = -1000432, + EMOTE_RIN_END_8 = -1000433, + + SPELL_REVIVE_RINGO = 15591, + QUEST_A_LITTLE_HELP = 4491, + NPC_SPRAGGLE = 9997, + FACTION_ESCORTEE = 113 +}; + +struct npc_ringoAI : public FollowerAI +{ + npc_ringoAI(Creature* pCreature) : FollowerAI(pCreature) { } + + uint32 m_uiFaintTimer; + uint32 m_uiEndEventProgress; + uint32 m_uiEndEventTimer; + + uint64 SpraggleGUID; + + void Reset() + { + m_uiFaintTimer = urand(30000, 60000); + m_uiEndEventProgress = 0; + m_uiEndEventTimer = 1000; + SpraggleGUID = 0; + } + + void MoveInLineOfSight(Unit *pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_SPRAGGLE) + { + if (me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) + { + if (Player* pPlayer = GetLeaderForFollower()) + { + if (pPlayer->GetQuestStatus(QUEST_A_LITTLE_HELP) == QUEST_STATUS_INCOMPLETE) + pPlayer->GroupEventHappens(QUEST_A_LITTLE_HELP, me); + } + + SpraggleGUID = pWho->GetGUID(); + SetFollowComplete(true); + } + } + } + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + if (HasFollowState(STATE_FOLLOW_INPROGRESS | STATE_FOLLOW_PAUSED) && pSpell->Id == SPELL_REVIVE_RINGO) + ClearFaint(); + } + + void SetFaint() + { + if (!HasFollowState(STATE_FOLLOW_POSTEVENT)) + { + SetFollowPaused(true); + + DoScriptText(RAND(SAY_FAINT_1,SAY_FAINT_2,SAY_FAINT_3,SAY_FAINT_4), me); + } + + //what does actually happen here? Emote? Aura? + me->SetStandState(UNIT_STAND_STATE_SLEEP); + } + + void ClearFaint() + { + me->SetStandState(UNIT_STAND_STATE_STAND); + + if (HasFollowState(STATE_FOLLOW_POSTEVENT)) + return; + + DoScriptText(RAND(SAY_WAKE_1,SAY_WAKE_2,SAY_WAKE_3,SAY_WAKE_4), me); + + SetFollowPaused(false); + } + + void UpdateFollowerAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + { + if (HasFollowState(STATE_FOLLOW_POSTEVENT)) + { + if (m_uiEndEventTimer <= uiDiff) + { + Unit *pSpraggle = Unit::GetUnit(*me, SpraggleGUID); + if (!pSpraggle || !pSpraggle->isAlive()) + { + SetFollowComplete(); + return; + } + + switch(m_uiEndEventProgress) + { + case 1: + DoScriptText(SAY_RIN_END_1, me); + m_uiEndEventTimer = 3000; + break; + case 2: + DoScriptText(SAY_SPR_END_2, pSpraggle); + m_uiEndEventTimer = 5000; + break; + case 3: + DoScriptText(SAY_RIN_END_3, me); + m_uiEndEventTimer = 1000; + break; + case 4: + DoScriptText(EMOTE_RIN_END_4, me); + SetFaint(); + m_uiEndEventTimer = 9000; + break; + case 5: + DoScriptText(EMOTE_RIN_END_5, me); + ClearFaint(); + m_uiEndEventTimer = 1000; + break; + case 6: + DoScriptText(SAY_RIN_END_6, me); + m_uiEndEventTimer = 3000; + break; + case 7: + DoScriptText(SAY_SPR_END_7, pSpraggle); + m_uiEndEventTimer = 10000; + break; + case 8: + DoScriptText(EMOTE_RIN_END_8, me); + m_uiEndEventTimer = 5000; + break; + case 9: + SetFollowComplete(); + break; + } + + ++m_uiEndEventProgress; + } + else + m_uiEndEventTimer -= uiDiff; + } + else if (HasFollowState(STATE_FOLLOW_INPROGRESS)) + { + if (!HasFollowState(STATE_FOLLOW_PAUSED)) + { + if (m_uiFaintTimer <= uiDiff) + { + SetFaint(); + m_uiFaintTimer = urand(60000, 120000); + } + else + m_uiFaintTimer -= uiDiff; + } + } + + return; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_ringo(Creature* pCreature) +{ + return new npc_ringoAI(pCreature); +} + +bool QuestAccept_npc_ringo(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_A_LITTLE_HELP) + { + if (npc_ringoAI* pRingoAI = CAST_AI(npc_ringoAI, pCreature->AI())) + { + pCreature->SetStandState(UNIT_STAND_STATE_STAND); + pRingoAI->StartFollow(pPlayer, FACTION_ESCORTEE, pQuest); + } + } + + return true; +} + +void AddSC_ungoro_crater() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_ame"; + newscript->GetAI = &GetAI_npc_ame; + newscript->pQuestAccept = &QuestAccept_npc_ame; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ringo"; + newscript->GetAI = &GetAI_npc_ringo; + newscript->pQuestAccept = &QuestAccept_npc_ringo; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp b/src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp new file mode 100644 index 00000000000..287b5db6d57 --- /dev/null +++ b/src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Wailing_Caverns +SD%Complete: 99 +SDComment: Everything seems to work, still need some checking +SDCategory: Wailing Caverns +EndScriptData */ + +#include "ScriptedPch.h" +#include "wailing_caverns.h" + +#define MAX_ENCOUNTER 9 + +struct instance_wailing_caverns : public ScriptedInstance +{ + instance_wailing_caverns(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + bool yelled; + uint64 NaralexGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + yelled = false; + NaralexGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == DATA_NARALEX) + NaralexGUID = pCreature->GetGUID(); + } + + void SetData(uint32 type, uint32 data) + { + switch (type) + { + case TYPE_LORD_COBRAHN: m_auiEncounter[0] = data;break; + case TYPE_LORD_PYTHAS: m_auiEncounter[1] = data;break; + case TYPE_LADY_ANACONDRA: m_auiEncounter[2] = data;break; + case TYPE_LORD_SERPENTIS: m_auiEncounter[3] = data;break; + case TYPE_NARALEX_EVENT: m_auiEncounter[4] = data;break; + case TYPE_NARALEX_PART1: m_auiEncounter[5] = data;break; + case TYPE_NARALEX_PART2: m_auiEncounter[6] = data;break; + case TYPE_NARALEX_PART3: m_auiEncounter[7] = data;break; + case TYPE_MUTANUS_THE_DEVOURER: m_auiEncounter[8] = data;break; + case TYPE_NARALEX_YELLED: yelled = true; break; + } + if (data == DONE)SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch (type) + { + case TYPE_LORD_COBRAHN: return m_auiEncounter[0]; + case TYPE_LORD_PYTHAS: return m_auiEncounter[1]; + case TYPE_LADY_ANACONDRA: return m_auiEncounter[2]; + case TYPE_LORD_SERPENTIS: return m_auiEncounter[3]; + case TYPE_NARALEX_EVENT: return m_auiEncounter[4]; + case TYPE_NARALEX_PART1: return m_auiEncounter[5]; + case TYPE_NARALEX_PART2: return m_auiEncounter[6]; + case TYPE_NARALEX_PART3: return m_auiEncounter[7]; + case TYPE_MUTANUS_THE_DEVOURER: return m_auiEncounter[8]; + case TYPE_NARALEX_YELLED: return yelled; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + if (data == DATA_NARALEX)return NaralexGUID; + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " + << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] >> m_auiEncounter[8]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] != DONE) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } + +}; + +InstanceData* GetInstanceData_instance_wailing_caverns(Map* pMap) +{ + return new instance_wailing_caverns(pMap); +} + +void AddSC_instance_wailing_caverns() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_wailing_caverns"; + newscript->GetInstanceData = &GetInstanceData_instance_wailing_caverns; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp b/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp new file mode 100644 index 00000000000..544c119fc93 --- /dev/null +++ b/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp @@ -0,0 +1,396 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Wailing Caverns +SD%Complete: 95 +SDComment: Need to add skill usage for Disciple of Naralex +SDCategory: Wailing Caverns +EndScriptData */ + +/* ContentData +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "wailing_caverns.h" + +/*###### +## npc_disciple_of_naralex +######*/ + +enum eEnums +{ + //say + SAY_MAKE_PREPARATIONS = -1043001, + SAY_TEMPLE_OF_PROMISE = -1043002, + SAY_MUST_CONTINUE = -1043003, + SAY_BANISH_THE_SPIRITS = -1043004, + SAY_CAVERNS_PURIFIED = -1043005, + SAY_BEYOND_THIS_CORRIDOR = -1043006, + SAY_EMERALD_DREAM = -1043007, + SAY_MUTANUS_THE_DEVOURER = -1043012, + SAY_NARALEX_AWAKES = -1043014, + SAY_THANK_YOU = -1043015, + SAY_FAREWELL = -1043016, + SAY_ATTACKED = -1043017, + //yell + SAY_AT_LAST = -1043000, + SAY_I_AM_AWAKE = -1043013, + //emote + EMOTE_AWAKENING_RITUAL = -1043008, + EMOTE_TROUBLED_SLEEP = -1043009, + EMOTE_WRITHE_IN_AGONY = -1043010, + EMOTE_HORRENDOUS_VISION = -1043011, + //spell + SPELL_MARK_OF_THE_WILD_RANK_2 = 5232, + SPELL_SERPENTINE_CLEANSING = 6270, + SPELL_NARALEXS_AWAKENING = 6271, + SPELL_FLIGHT_FORM = 33943, + //npc entry + NPC_DEVIATE_RAVAGER = 3636, + NPC_DEVIATE_VIPER = 5755, + NPC_DEVIATE_MOCCASIN = 5762, + NPC_NIGHTMARE_ECTOPLASM = 5763, + NPC_MUTANUS_THE_DEVOURER = 3654, +}; + +#define GOSSIP_ID_START_1 698 //Naralex sleeps again! +#define GOSSIP_ID_START_2 699 //The fanglords are dead! +#define GOSSIP_ITEM_NARALEX "Let the event begin!" +#define ACHIEVEMENT_WAILING_CAVERNS 630 + +struct npc_disciple_of_naralexAI : public npc_escortAI +{ + npc_disciple_of_naralexAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + eventTimer = 0; + currentEvent = 0; + eventProgress = 0; + me->setActive(true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + uint32 eventTimer; + uint32 currentEvent; + uint32 eventProgress; + ScriptedInstance *pInstance; + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch (i) + { + case 4: + eventProgress = 1; + currentEvent = TYPE_NARALEX_PART1; + pInstance->SetData(TYPE_NARALEX_PART1, IN_PROGRESS); + break; + case 5: + DoScriptText(SAY_MUST_CONTINUE, me); + pInstance->SetData(TYPE_NARALEX_PART1, DONE); + break; + case 11: + eventProgress = 1; + currentEvent = TYPE_NARALEX_PART2; + pInstance->SetData(TYPE_NARALEX_PART2, IN_PROGRESS); + break; + case 19: + DoScriptText(SAY_BEYOND_THIS_CORRIDOR, me); + break; + case 24: + eventProgress = 1; + currentEvent = TYPE_NARALEX_PART3; + pInstance->SetData(TYPE_NARALEX_PART3, IN_PROGRESS); + break; + } + } + + void Reset() + { + + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_ATTACKED, me, who); + } + + void JustDied(Unit * /*slayer*/) + { + if (pInstance) + { + pInstance->SetData(TYPE_NARALEX_EVENT, FAIL); + pInstance->SetData(TYPE_NARALEX_PART1, FAIL); + pInstance->SetData(TYPE_NARALEX_PART2, FAIL); + pInstance->SetData(TYPE_NARALEX_PART3, FAIL); + } + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void UpdateAI(const uint32 diff) + { + if (currentEvent != TYPE_NARALEX_PART3) + npc_escortAI::UpdateAI(diff); + + if (!pInstance) + return; + if (eventTimer <= diff) + { + eventTimer = 0; + if (pInstance->GetData(currentEvent) == IN_PROGRESS) + { + switch (currentEvent) + { + case TYPE_NARALEX_PART1: + if (eventProgress == 1) + { + ++eventProgress; + DoScriptText(SAY_TEMPLE_OF_PROMISE, me); + me->SummonCreature(NPC_DEVIATE_RAVAGER, -82.1763, 227.874, -93.3233, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + me->SummonCreature(NPC_DEVIATE_RAVAGER, -72.9506, 216.645, -93.6756, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + } + break; + case TYPE_NARALEX_PART2: + if (eventProgress == 1) + { + ++eventProgress; + DoScriptText(SAY_BANISH_THE_SPIRITS, me); + DoCast(me, SPELL_SERPENTINE_CLEANSING); + //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(false); + eventTimer = 30000; + me->SummonCreature(NPC_DEVIATE_VIPER, -61.5261, 273.676, -92.8442, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + me->SummonCreature(NPC_DEVIATE_VIPER, -58.4658, 280.799, -92.8393, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + me->SummonCreature(NPC_DEVIATE_VIPER, -50.002, 278.578, -92.8442, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + } + else + if (eventProgress == 2) + { + //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(true); + DoScriptText(SAY_CAVERNS_PURIFIED, me); + pInstance->SetData(TYPE_NARALEX_PART2, DONE); + if (me->HasAura(SPELL_SERPENTINE_CLEANSING)) + me->RemoveAura(SPELL_SERPENTINE_CLEANSING); + } + break; + case TYPE_NARALEX_PART3: + if (eventProgress == 1) + { + ++eventProgress; + eventTimer = 4000; + me->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(SAY_EMERALD_DREAM, me); + } + else + if (eventProgress == 2) + { + ++eventProgress; + eventTimer = 15000; + //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(false); + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoCast(naralex, SPELL_NARALEXS_AWAKENING, true); + DoScriptText(EMOTE_AWAKENING_RITUAL, me); + } + else + if (eventProgress == 3) + { + ++eventProgress; + eventTimer = 15000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoScriptText(EMOTE_TROUBLED_SLEEP, naralex); + me->SummonCreature(NPC_DEVIATE_MOCCASIN, 135.943, 199.701, -103.529, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_DEVIATE_MOCCASIN, 151.08, 221.13, -103.609, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_DEVIATE_MOCCASIN, 128.007, 227.428, -97.421, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + } + else + if (eventProgress == 4) + { + ++eventProgress; + eventTimer = 30000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoScriptText(EMOTE_WRITHE_IN_AGONY, naralex); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 133.413, 207.188, -102.469, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 142.857, 218.645, -102.905, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 105.102, 227.211, -102.752, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 153.372, 235.149, -102.826, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 149.524, 251.113, -102.558, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 136.208, 266.466, -102.977, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 126.167, 274.759, -102.962, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + } + else + if (eventProgress == 5) + { + ++eventProgress; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoScriptText(EMOTE_HORRENDOUS_VISION, naralex); + me->SummonCreature(NPC_MUTANUS_THE_DEVOURER, 150.872, 262.905, -103.503, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + DoScriptText(SAY_MUTANUS_THE_DEVOURER, me); + pInstance->SetData(TYPE_MUTANUS_THE_DEVOURER, IN_PROGRESS); + } + else + if (eventProgress == 6 && pInstance->GetData(TYPE_MUTANUS_THE_DEVOURER) == DONE) + { + ++eventProgress; + eventTimer = 3000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + { + AchievementEntry const *AchievWC = GetAchievementStore()->LookupEntry(ACHIEVEMENT_WAILING_CAVERNS); + if (AchievWC) + { + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievWC); + } + } + if (me->HasAura(SPELL_NARALEXS_AWAKENING)) + me->RemoveAura(SPELL_NARALEXS_AWAKENING); + naralex->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_I_AM_AWAKE, naralex); + } + DoScriptText(SAY_NARALEX_AWAKES, me); + } + else + if (eventProgress == 7) + { + ++eventProgress; + eventTimer = 6000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoScriptText(SAY_THANK_YOU, naralex); + } + else + if (eventProgress == 8) + { + ++eventProgress; + eventTimer = 8000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + { + DoScriptText(SAY_FAREWELL, naralex); + naralex->AddAura(SPELL_FLIGHT_FORM, naralex); + } + SetRun(); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->AddAura(SPELL_FLIGHT_FORM, me); + } + else + if (eventProgress == 9) + { + ++eventProgress; + eventTimer = 1500; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + naralex->GetMotionMaster()->MovePoint(25, naralex->GetPositionX(), naralex->GetPositionY(), naralex->GetPositionZ()); + } + else + if (eventProgress == 10) + { + ++eventProgress; + eventTimer = 2500; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + { + naralex->GetMotionMaster()->MovePoint(0, 117.095512, 247.107971, -96.167870); + naralex->GetMotionMaster()->MovePoint(1, 90.388809, 276.135406, -83.389801); + } + me->GetMotionMaster()->MovePoint(26, 117.095512, 247.107971, -96.167870); + me->GetMotionMaster()->MovePoint(27, 144.375443, 281.045837, -82.477135); + } + else + if (eventProgress == 11) + { + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + naralex->SetVisibility(VISIBILITY_OFF); + me->SetVisibility(VISIBILITY_OFF); + pInstance->SetData(TYPE_NARALEX_PART3, DONE); + } + break; + } + } + } else eventTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_disciple_of_naralex(Creature* pCreature) +{ + return new npc_disciple_of_naralexAI(pCreature); +} + +bool GossipHello_npc_disciple_of_naralex(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance *pInstance = pCreature->GetInstanceData(); + + if (pInstance) + { + pCreature->CastSpell(pPlayer, SPELL_MARK_OF_THE_WILD_RANK_2, true); + if ((pInstance->GetData(TYPE_LORD_COBRAHN) == DONE) && (pInstance->GetData(TYPE_LORD_PYTHAS) == DONE) && + (pInstance->GetData(TYPE_LADY_ANACONDRA) == DONE) && (pInstance->GetData(TYPE_LORD_SERPENTIS) == DONE)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NARALEX, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START_2, pCreature->GetGUID()); + + if (!pInstance->GetData(TYPE_NARALEX_YELLED)) + { + DoScriptText(SAY_AT_LAST, pCreature); + pInstance->SetData(TYPE_NARALEX_YELLED, 1); + } + } + else + { + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START_1, pCreature->GetGUID()); + } + } + return true; +} + +bool GossipSelect_npc_disciple_of_naralex(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + ScriptedInstance *pInstance = pCreature->GetInstanceData(); + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + if (pInstance) + pInstance->SetData(TYPE_NARALEX_EVENT, IN_PROGRESS); + + DoScriptText(SAY_MAKE_PREPARATIONS, pCreature); + + pCreature->setFaction(250); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); + } + return true; +} + +void AddSC_wailing_caverns() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_disciple_of_naralex"; + newscript->pGossipHello = &GossipHello_npc_disciple_of_naralex; + newscript->pGossipSelect = &GossipSelect_npc_disciple_of_naralex; + newscript->GetAI = &GetAI_npc_disciple_of_naralex; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h b/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h new file mode 100644 index 00000000000..6ef1a673c59 --- /dev/null +++ b/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_WAILING_CAVERNS_H +#define DEF_WAILING_CAVERNS_H + +enum eTypes +{ + TYPE_LORD_COBRAHN = 1, + TYPE_LORD_PYTHAS = 2, + TYPE_LADY_ANACONDRA = 3, + TYPE_LORD_SERPENTIS = 4, + TYPE_NARALEX_EVENT = 5, + TYPE_NARALEX_PART1 = 6, + TYPE_NARALEX_PART2 = 7, + TYPE_NARALEX_PART3 = 8, + TYPE_MUTANUS_THE_DEVOURER = 9, + TYPE_NARALEX_YELLED = 10, + + DATA_NARALEX = 3679, +}; + +#endif diff --git a/src/server/scripts/Kalimdor/winterspring.cpp b/src/server/scripts/Kalimdor/winterspring.cpp new file mode 100644 index 00000000000..a284f32aeaa --- /dev/null +++ b/src/server/scripts/Kalimdor/winterspring.cpp @@ -0,0 +1,168 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Winterspring +SD%Complete: 90 +SDComment: Quest support: 5126 (Loraxs' tale missing proper gossip items text). Vendor Rivern Frostwind. Obtain Cache of Mau'ari +SDCategory: Winterspring +EndScriptData */ + +/* ContentData +npc_lorax +npc_rivern_frostwind +npc_witch_doctor_mauari +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_lorax +######*/ + +#define GOSSIP_HL "Talk to me" + +#define GOSSIP_SL1 "What do you do here?" +#define GOSSIP_SL2 "I can help you" +#define GOSSIP_SL3 "What deal?" +#define GOSSIP_SL4 "Then what happened?" +#define GOSSIP_SL5 "He is not safe, i'll make sure of that." + +bool GossipHello_npc_lorax(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(5126) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lorax(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(3759, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(3760, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(3761, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(3762, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + pPlayer->SEND_GOSSIP_MENU(3763, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(5126); + break; + } + return true; +} + +/*###### +## npc_rivern_frostwind +######*/ + +bool GossipHello_npc_rivern_frostwind(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor() && pPlayer->GetReputationRank(589) == REP_EXALTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_rivern_frostwind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_witch_doctor_mauari +######*/ + +#define GOSSIP_HWDM "I'd like you to make me a new Cache of Mau'ari please." + +bool GossipHello_npc_witch_doctor_mauari(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestRewardStatus(975)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HWDM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(3377, pCreature->GetGUID()); + }else + pPlayer->SEND_GOSSIP_MENU(3375, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_witch_doctor_mauari(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, 16351, false); + } + + return true; +} + +void AddSC_winterspring() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_lorax"; + newscript->pGossipHello = &GossipHello_npc_lorax; + newscript->pGossipSelect = &GossipSelect_npc_lorax; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_rivern_frostwind"; + newscript->pGossipHello = &GossipHello_npc_rivern_frostwind; + newscript->pGossipSelect = &GossipSelect_npc_rivern_frostwind; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_witch_doctor_mauari"; + newscript->pGossipHello = &GossipHello_npc_witch_doctor_mauari; + newscript->pGossipSelect = &GossipSelect_npc_witch_doctor_mauari; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp b/src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp new file mode 100644 index 00000000000..530ef30f44c --- /dev/null +++ b/src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp @@ -0,0 +1,58 @@ + /* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" + +#define NPC_GAHZRILLA 7273 + +struct instance_zulfarrak : public ScriptedInstance +{ + instance_zulfarrak(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 GahzRillaEncounter; + + void Initialize() + { + GahzRillaEncounter = NOT_STARTED; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == NPC_GAHZRILLA) + { + if (GahzRillaEncounter >= IN_PROGRESS) + pCreature->DisappearAndDie(); + else + GahzRillaEncounter = IN_PROGRESS; + } + } +}; + +InstanceData* GetInstanceData_instance_zulfarrak(Map* pMap) +{ + return new instance_zulfarrak(pMap); +} + +void AddSC_instance_zulfarrak() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_zulfarrak"; + newscript->GetInstanceData = &GetInstanceData_instance_zulfarrak; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp b/src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp new file mode 100644 index 00000000000..2ca053c23b6 --- /dev/null +++ b/src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp @@ -0,0 +1,280 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Zulfarrak +SD%Complete: 50 +SDComment: Consider it temporary, no instance script made for this instance yet. +SDCategory: Zul'Farrak +EndScriptData */ + +/* ContentData +npc_sergeant_bly +npc_weegli_blastfuse +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_sergeant_bly +######*/ + +#define FACTION_HOSTILE 14 +#define FACTION_FRIENDLY 35 + +#define SPELL_SHIELD_BASH 11972 +#define SPELL_REVENGE 12170 + +#define GOSSIP_BLY "[PH] In that case, I will take my reward!" + +struct npc_sergeant_blyAI : public ScriptedAI +{ + npc_sergeant_blyAI(Creature *c) : ScriptedAI(c) + { + //pInstance = c->GetInstanceData(); + } + + //ScriptedInstance* pInstance; + + uint32 ShieldBash_Timer; + uint32 Revenge_Timer; //this is wrong, spell should never be used unless me->getVictim() dodge, parry or block attack. Trinity support required. + + void Reset() + { + ShieldBash_Timer = 5000; + Revenge_Timer = 8000; + + me->setFaction(FACTION_FRIENDLY); + + /*if (pInstance) + pInstance->SetData(0, NOT_STARTED);*/ + } + + void EnterCombat(Unit * /*who*/) + { + /*if (pInstance) + pInstance->SetData(0, IN_PROGRESS);*/ + } + + void JustDied(Unit * /*victim*/) + { + /*if (pInstance) + pInstance->SetData(0, DONE);*/ + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShieldBash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHIELD_BASH); + ShieldBash_Timer = 15000; + } else ShieldBash_Timer -= diff; + + if (Revenge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REVENGE); + Revenge_Timer = 10000; + } else Revenge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_sergeant_bly(Creature* pCreature) +{ + return new npc_sergeant_blyAI (pCreature); +} + +bool GossipHello_npc_sergeant_bly(Player* pPlayer, Creature* pCreature) +{ + /*if (pInstance->GetData(0) == DONE) + {*/ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(1517, pCreature->GetGUID()); + /*} + else if (pInstance->GetData(0) == IN_PROGRESS) + pPlayer->SEND_GOSSIP_MENU(1516, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(1515, pCreature->GetGUID());*/ + + return true; +} + +bool GossipSelect_npc_sergeant_bly(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(FACTION_HOSTILE); + CAST_AI(npc_sergeant_blyAI, pCreature->AI())->AttackStart(pPlayer); + } + return true; +} + +/*###### +## npc_weegli_blastfuse +######*/ + +#define SPELL_BOMB 8858 +#define SPELL_GOBLIN_LAND_MINE 21688 +#define SPELL_SHOOT 6660 +#define SPELL_WEEGLIS_BARREL 10772 + +#define GOSSIP_WEEGLI "[PH] Please blow up the door." + +struct npc_weegli_blastfuseAI : public ScriptedAI +{ + npc_weegli_blastfuseAI(Creature *c) : ScriptedAI(c) + { + //pInstance = c->GetInstanceData(); + } + + //ScriptedInstance* pInstance; + + void Reset() + { + /*if (pInstance) + pInstance->SetData(0, NOT_STARTED);*/ + } + + void EnterCombat(Unit * /*who*/) + { + /*if (pInstance) + pInstance->SetData(0, IN_PROGRESS);*/ + } + + void JustDied(Unit * /*victim*/) + { + /*if (pInstance) + pInstance->SetData(0, DONE);*/ + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_weegli_blastfuse(Creature* pCreature) +{ + return new npc_weegli_blastfuseAI (pCreature); +} + +bool GossipHello_npc_weegli_blastfuse(Player* pPlayer, Creature* pCreature) +{ + //event not implemented yet, this is only placeholder for future developement + /*if (pInstance->GetData(0) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEEGLI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(1514, pCreature->GetGUID());//if event can proceed to end + } + else if (pInstance->GetData(0) == IN_PROGRESS) + pPlayer->SEND_GOSSIP_MENU(1513, pCreature->GetGUID());//if event are in progress + else*/ + pPlayer->SEND_GOSSIP_MENU(1511, pCreature->GetGUID()); //if event not started + return true; +} + +bool GossipSelect_npc_weegli_blastfuse(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + //here we make him run to door, set the charge and run away off to nowhere + } + return true; +} + +/*###### +## go_shallow_grave +######*/ + +enum { + ZOMBIE = 7286, + DEAD_HERO = 7276, + ZOMBIE_CHANCE = 65, + DEAD_HERO_CHANCE = 10 +}; + +bool GOHello_go_shallow_grave(Player* /*pPlayer*/, GameObject* pGo) +{ + // randomly summon a zombie or dead hero the first time a grave is used + if (pGo->GetUseCount() == 0) + { + uint32 randomchance = urand(0,100); + if (randomchance < ZOMBIE_CHANCE) + pGo->SummonCreature(ZOMBIE, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + else if ((randomchance-ZOMBIE_CHANCE) < DEAD_HERO_CHANCE) + pGo->SummonCreature(DEAD_HERO, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + } + pGo->AddUse(); + return false; +} + +/*###### +## at_zumrah +######*/ + +enum { + ZUMRAH_ID = 7271, + ZUMRAH_HOSTILE_FACTION = 37 +}; + +bool AreaTrigger_at_zumrah(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + Creature* Zumrah = pPlayer->FindNearestCreature(ZUMRAH_ID, 30.0f); + + if (!Zumrah) + return false; + + Zumrah->setFaction(ZUMRAH_HOSTILE_FACTION); + Zumrah->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + return true; +} + +void AddSC_zulfarrak() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sergeant_bly"; + newscript->GetAI = &GetAI_npc_sergeant_bly; + newscript->pGossipHello = &GossipHello_npc_sergeant_bly; + newscript->pGossipSelect = &GossipSelect_npc_sergeant_bly; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_weegli_blastfuse"; + newscript->GetAI = &GetAI_npc_weegli_blastfuse; + newscript->pGossipHello = &GossipHello_npc_weegli_blastfuse; + newscript->pGossipSelect = &GossipSelect_npc_weegli_blastfuse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_shallow_grave"; + newscript->pGOHello = &GOHello_go_shallow_grave; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_zumrah"; + newscript->pAreaTrigger = &AreaTrigger_at_zumrah; + newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h new file mode 100644 index 00000000000..240ad77c74d --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_AHNKAHET_H +#define DEF_AHNKAHET_H + +enum Data64 +{ + DATA_ELDER_NADOX, + DATA_PRINCE_TALDARAM, + DATA_JEDOGA_SHADOWSEEKER, + DATA_HERALD_VOLAZJ, + DATA_AMANITAR, + DATA_SPHERE1, + DATA_SPHERE2, + DATA_PRINCE_TALDARAM_PLATFORM, + DATA_PL_JEDOGA_TARGET, + DATA_ADD_JEDOGA_OPFER, + DATA_ADD_JEDOGA_INITIAND +}; + +enum Data +{ + DATA_ELDER_NADOX_EVENT, + DATA_PRINCE_TALDARAM_EVENT, + DATA_JEDOGA_SHADOWSEEKER_EVENT, + DATA_HERALD_VOLAZJ_EVENT, + DATA_AMANITAR_EVENT, + DATA_SPHERE1_EVENT, + DATA_SPHERE2_EVENT, + DATA_JEDOGA_TRIGGER_SWITCH, + DATA_JEDOGA_RESET_INITIANDS, + DATA_INITIAND_KILLED, + DATA_ALL_INITIAND_DEAD +}; + +#endif diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp new file mode 100644 index 00000000000..51c4bce0c2d --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp @@ -0,0 +1,226 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Comment: Find correct mushrooms spell to make them visible - buffs of the mushrooms not ever applied to the users... + */ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +enum Spells +{ + SPELL_BASH = 57094, // Victim + SPELL_ENTANGLING_ROOTS = 57095, // Random Victim 100Y + SPELL_MINI = 57055, // Self + SPELL_VENOM_BOLT_VOLLEY = 57088, // Random Victim 100Y + SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS = 56648, // Killer 3Y + SPELL_POISONOUS_MUSHROOM_POISON_CLOUD = 57061, // Self - Duration 8 Sec + SPELL_POISONOUS_MUSHROOM_VISUAL_AREA = 61566, // Self + SPELL_POISONOUS_MUSHROOM_VISUAL_AURA = 56741, // Self + SPELL_PUTRID_MUSHROOM = 31690, // To make the mushrooms visible +}; + +enum Creatures +{ + NPC_HEALTHY_MUSHROOM = 30391, + NPC_POISONOUS_MUSHROOM = 30435 +}; + +struct boss_amanitarAI : public ScriptedAI +{ + boss_amanitarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + bFirstTime = true; + } + + ScriptedInstance* pInstance; + + uint32 uiRootTimer; + uint32 uiBashTimer; + uint32 uiBoltTimer; + uint32 uiSpawnTimer; + + bool bFirstTime; + + void Reset() + { + uiRootTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); + uiBashTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); + uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + uiSpawnTimer = 0; + + me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + + if (pInstance) + { + pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); + if (!bFirstTime) + pInstance->SetData(DATA_AMANITAR_EVENT, FAIL); + else + bFirstTime = false; + } + } + + void JustDied(Unit * /*Killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_AMANITAR_EVENT, DONE); + pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_AMANITAR_EVENT, IN_PROGRESS); + + DoCast(me, SPELL_MINI, false); + } + + void SpawnAdds() + { + for (uint8 i = 0; i < 30; ++i) + { + Unit* victim = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (victim) + { + Position pos; + victim->GetPosition(&pos); + me->GetRandomNearPosition(pos, float(urand(5,80))); + me->SummonCreature(NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILISECONDS); + me->GetRandomNearPosition(pos, float(urand(5,80))); + me->SummonCreature(NPC_HEALTHY_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILISECONDS); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiSpawnTimer <= diff) + { + SpawnAdds(); + uiSpawnTimer = urand(35*IN_MILISECONDS,40*IN_MILISECONDS); + } else uiSpawnTimer -= diff; + + if (uiRootTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ENTANGLING_ROOTS); + uiRootTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiRootTimer -= diff; + + if (uiBashTimer <= diff) + { + DoCastVictim(SPELL_BASH); + uiBashTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiBashTimer -= diff; + + if (uiBoltTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_VENOM_BOLT_VOLLEY); + uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_amanitar_mushroomsAI : public Scripted_NoMovementAI +{ + mob_amanitar_mushroomsAI(Creature* c) : Scripted_NoMovementAI(c) {} + + uint32 uiAuraTimer; + uint32 uiDeathTimer; + + void Reset() + { + DoCast(me, SPELL_PUTRID_MUSHROOM, true); // Hack, to make the mushrooms visible, can't find orig. spell... + + if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) + DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true); + + uiAuraTimer = 0; + uiDeathTimer = 30*IN_MILISECONDS; + } + + void JustDied(Unit *killer) + { + if (!killer) + return; + + if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && killer->GetTypeId() == TYPEID_PLAYER) + { + me->InterruptNonMeleeSpells(false); + DoCast(killer, SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, false); + } + } + + void EnterCombat(Unit * /*who*/) {} + void AttackStart(Unit * /*victim*/) {} + + void UpdateAI(const uint32 diff) + { + if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) + { + if (uiAuraTimer <= diff) + { + DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AREA, true); + DoCast(me, SPELL_POISONOUS_MUSHROOM_POISON_CLOUD, false); + uiAuraTimer = 7*IN_MILISECONDS; + } else uiAuraTimer -= diff; + } + if (uiDeathTimer <= diff) + me->DisappearAndDie(); + else uiDeathTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_amanitar(Creature* pCreature) +{ + return new boss_amanitarAI (pCreature); +} + +CreatureAI* GetAI_mob_amanitar_mushrooms(Creature *pCreature) +{ + return new mob_amanitar_mushroomsAI (pCreature); +} + +void AddSC_boss_amanitar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_amanitar"; + newscript->GetAI = &GetAI_boss_amanitar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_amanitar_mushrooms"; + newscript->GetAI = &GetAI_mob_amanitar_mushrooms; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp new file mode 100644 index 00000000000..2215d91c749 --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp @@ -0,0 +1,283 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +bool DeadAhnkaharGuardian; // needed for achievement: Respect Your Elders(2038) + +enum Achievements +{ + ACHIEV_RESPECT_YOUR_ELDERS = 2038 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1619014, + SAY_SLAY_1 = -1619015, + SAY_SLAY_2 = -1619016, + SAY_SLAY_3 = -1619017, + SAY_DEATH = -1619018, + SAY_EGG_SAC_1 = -1619019, + SAY_EGG_SAC_2 = -1619020 +}; + +enum Spells +{ + SPELL_BROOD_PLAGUE = 56130, + H_SPELL_BROOD_PLAGUE = 59467, + H_SPELL_BROOD_RAGE = 59465, + SPELL_ENRAGE = 26662, // Enraged if too far away from home + SPELL_SUMMON_SWARMERS = 56119, //2x 30178 -- 2x every 10secs + SPELL_SUMMON_SWARM_GUARD = 56120, //1x 30176 -- every 25secs +}; + +enum Creatures +{ + MOB_AHNKAHAR_SWARMER = 30178, + MOB_AHNKAHAR_GUARDIAN_ENTRY = 30176 +}; + +#define EMOTE_HATCHES "An Ahn'kahar Guardian hatches!" + +struct boss_elder_nadoxAI : public ScriptedAI +{ + boss_elder_nadoxAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiPlagueTimer; + uint32 uiRagueTimer; + + uint32 uiSwarmerSpawnTimer; + uint32 uiGuardSpawnTimer; + uint32 uiEnragueTimer; + + bool bGuardSpawned; + + ScriptedInstance *pInstance; + + void Reset() + { + uiPlagueTimer = 13*IN_MILISECONDS; + uiRagueTimer = 20*IN_MILISECONDS; + + uiSwarmerSpawnTimer = 10*IN_MILISECONDS; + uiGuardSpawnTimer = 25*IN_MILISECONDS; + + uiEnragueTimer = 5*IN_MILISECONDS; + + DeadAhnkaharGuardian = false; + bGuardSpawned = false; + + if (pInstance) + pInstance->SetData(DATA_ELDER_NADOX_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_DEATH,me); + + if (pInstance) + pInstance->SetData(DATA_ELDER_NADOX_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_SLAY_3,me); //SAY_SLAY_3 on death? + + if (pInstance) + { + pInstance->SetData(DATA_ELDER_NADOX_EVENT, DONE); + if (IsHeroic() && !DeadAhnkaharGuardian) + pInstance->DoCompleteAchievement(ACHIEV_RESPECT_YOUR_ELDERS); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiPlagueTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BROOD_PLAGUE); + uiPlagueTimer = 15*IN_MILISECONDS; + } else uiPlagueTimer -= diff; + + if (IsHeroic()) + if (uiRagueTimer <= diff) + { + if (Creature *pSwarmer = me->FindNearestCreature(MOB_AHNKAHAR_SWARMER, 35)) + { + DoCast(pSwarmer, H_SPELL_BROOD_RAGE, true); + uiRagueTimer = 15*IN_MILISECONDS; + } + } else uiRagueTimer -= diff; + + if (uiSwarmerSpawnTimer <= diff) + { + DoCast(me, SPELL_SUMMON_SWARMERS, true); + DoCast(me, SPELL_SUMMON_SWARMERS); + if (urand(1,3) == 3) // 33% chance of dialog + DoScriptText(RAND(SAY_EGG_SAC_1,SAY_EGG_SAC_2), me); + + uiSwarmerSpawnTimer = 10*IN_MILISECONDS; + } else uiSwarmerSpawnTimer -= diff; + + if (!bGuardSpawned && uiGuardSpawnTimer <= diff) + { + me->MonsterTextEmote(EMOTE_HATCHES,me->GetGUID(),true); + DoCast(me, SPELL_SUMMON_SWARM_GUARD); + bGuardSpawned = true; + } else uiGuardSpawnTimer -= diff; + + if (uiEnragueTimer <= diff) + { + if (me->HasAura(SPELL_ENRAGE,0)) + return; + + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + if (z < 24) + if (!me->IsNonMeleeSpellCasted(false)) + DoCast(me, SPELL_ENRAGE, true); + + uiEnragueTimer = 5*IN_MILISECONDS; + } else uiEnragueTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_elder_nadox(Creature* pCreature) +{ + return new boss_elder_nadoxAI(pCreature); +} + +enum AddSpells +{ + SPELL_SPRINT = 56354, + SPELL_GUARDIAN_AURA = 56151 +}; + +struct mob_ahnkahar_nerubianAI : public ScriptedAI +{ + mob_ahnkahar_nerubianAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 uiSprintTimer; + + void Reset() + { + if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) //magic numbers are bad! + DoCast(me, SPELL_GUARDIAN_AURA, true); + uiSprintTimer = 10*IN_MILISECONDS; + } + + void JustDied(Unit * /*killer*/) + { + if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) + DeadAhnkaharGuardian = true; + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) + me->RemoveAurasDueToSpell(SPELL_GUARDIAN_AURA); + + if (pInstance) + { + if (pInstance->GetData(DATA_ELDER_NADOX_EVENT) != IN_PROGRESS) + { + me->DisappearAndDie(); + } + } + + if (!UpdateVictim()) + return; + + if (uiSprintTimer <= diff) + { + DoCast(me, SPELL_SPRINT); + uiSprintTimer = 25*IN_MILISECONDS; + } else uiSprintTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//HACK: No, AI. Replace with proper db content? +struct mob_nadox_eggsAI : public Scripted_NoMovementAI +{ + mob_nadox_eggsAI(Creature* c) : Scripted_NoMovementAI(c) + { + c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + c->UpdateAllStats(); + } + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*victim*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_mob_ahnkahar_nerubian(Creature* pCreature) +{ + return new mob_ahnkahar_nerubianAI(pCreature); +} + +CreatureAI* GetAI_mob_nadox_eggs(Creature* _Creature) +{ + return new mob_nadox_eggsAI(_Creature); +} + +void AddSC_boss_elder_nadox() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_elder_nadox"; + newscript->GetAI = &GetAI_boss_elder_nadox; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ahnkahar_nerubian"; + newscript->GetAI = &GetAI_mob_ahnkahar_nerubian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nadox_eggs"; + newscript->GetAI = &GetAI_mob_nadox_eggs; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp new file mode 100644 index 00000000000..16c291d6484 --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp @@ -0,0 +1,328 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Comment: Missing AI for Twisted Visages + */ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +enum Spells +{ + SPELL_INSANITY = 57496, //Dummy + INSANITY_VISUAL = 57561, + SPELL_INSANITY_TARGET = 57508, + SPELL_MIND_FLAY = 57941, + SPELL_SHADOW_BOLT_VOLLEY = 57942, + SPELL_SHIVER = 57949, + SPELL_CLONE_PLAYER = 57507, //casted on player during insanity + SPELL_INSANITY_PHASING_1 = 57508, + SPELL_INSANITY_PHASING_2 = 57509, + SPELL_INSANITY_PHASING_3 = 57510, + SPELL_INSANITY_PHASING_4 = 57511, + SPELL_INSANITY_PHASING_5 = 57512 +}; + +enum Creatures +{ + MOB_TWISTED_VISAGE = 30625 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1619030, + SAY_SLAY_1 = -1619031, + SAY_SLAY_2 = -1619032, + SAY_SLAY_3 = -1619033, + SAY_DEATH_1 = -1619034, + SAY_DEATH_2 = -1619035, + SAY_PHASE = -1619036 +}; + +enum Achievements +{ + ACHIEV_QUICK_DEMISE_START_EVENT = 20382, +}; + +struct boss_volazjAI : public ScriptedAI +{ + boss_volazjAI(Creature* pCreature) : ScriptedAI(pCreature),Summons(me) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 uiMindFlayTimer; + uint32 uiShadowBoltVolleyTimer; + uint32 uiShiverTimer; + uint32 insanityHandled; + SummonList Summons; + + // returns the percentage of health after taking the given damage. + uint32 GetHealthPct(uint32 damage) + { + if (damage > me->GetHealth()) + return 0; + return 100*(me->GetHealth()-damage)/me->GetMaxHealth(); + } + + void DamageTaken(Unit * /*pAttacker*/, uint32 &damage) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + damage = 0; + + if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)|| + (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33)) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_INSANITY, false); + } + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (spell->Id == SPELL_INSANITY) + { + // Not good target or too many players + if (pTarget->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4) + return; + // First target - start channel visual and set self as unnattackable + if (!insanityHandled) + { + // Channel visual + DoCast(me, INSANITY_VISUAL, true); + // Unattackable + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(true, UNIT_STAT_STUNNED); + } + // phase mask + pTarget->CastSpell(pTarget, SPELL_INSANITY_TARGET+insanityHandled, true); + // summon twisted party members for this target + Map::PlayerList const &players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player *plr = i->getSource(); + if (!plr || !plr->isAlive()) + continue; + // Summon clone + if (Unit *summon = me->SummonCreature(MOB_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,0)) + { + // required for correct visual + // Fixme: allow mirror image query to send other guid to get rid of minion status + summon->SetUInt64Value(UNIT_FIELD_CREATEDBY, plr->GetGUID()); + // clone + plr->CastSpell(summon, SPELL_CLONE_PLAYER, true); + // set phase + summon->SetPhaseMask((1<<(4+insanityHandled)),true); + } + } + ++insanityHandled; + } + } + + void ResetPlayersPhaseMask() + { + Map::PlayerList const &players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player* pPlayer = i->getSource(); + pPlayer->RemoveAurasDueToSpell(GetSpellForPhaseMask(pPlayer->GetPhaseMask())); + } + } + + void Reset() + { + uiMindFlayTimer = 8*IN_MILISECONDS; + uiShadowBoltVolleyTimer = 5*IN_MILISECONDS; + uiShiverTimer = 15*IN_MILISECONDS; + + if (pInstance) + { + pInstance->SetData(DATA_HERALD_VOLAZJ, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); + } + + // Visible for all players in insanity + me->SetPhaseMask((1|16|32|64|128|256),true); + // Used for Insanity handling + insanityHandled = 0; + + ResetPlayersPhaseMask(); + + // Cleanup + Summons.DespawnAll(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + { + pInstance->SetData(DATA_HERALD_VOLAZJ, IN_PROGRESS); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); + } + } + + void JustSummoned(Creature *summon) + { + Summons.Summon(summon); + } + + uint32 GetSpellForPhaseMask(uint32 phase) + { + uint32 spell = 0; + switch (phase) + { + case 16: + spell = SPELL_INSANITY_PHASING_1; + break; + case 32: + spell = SPELL_INSANITY_PHASING_2; + break; + case 64: + spell = SPELL_INSANITY_PHASING_3; + break; + case 128: + spell = SPELL_INSANITY_PHASING_4; + break; + case 256: + spell = SPELL_INSANITY_PHASING_5; + break; + } + return spell; + } + + void SummonedCreatureDespawn(Creature *summon) + { + uint32 phase= summon->GetPhaseMask(); + uint32 nextPhase = 0; + Summons.Despawn(summon); + + // Check if all summons in this phase killed + for (SummonList::const_iterator iter = Summons.begin(); iter != Summons.end(); ++iter) + { + if (Creature *visage = Unit::GetCreature(*me, *iter)) + { + // Not all are dead + if (phase == visage->GetPhaseMask()) + return; + else + nextPhase = visage->GetPhaseMask(); + } + } + + // Roll Insanity + uint32 spell = GetSpellForPhaseMask(phase); + uint32 spell2 = GetSpellForPhaseMask(nextPhase); + Map* pMap = me->GetMap(); + if (!pMap) + return; + + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->HasAura(spell)) + { + pPlayer->RemoveAurasDueToSpell(spell); + if (spell2) // if there is still some different mask cast spell for it + pPlayer->CastSpell(pPlayer, spell2, true); + } + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (insanityHandled) + { + if (!Summons.empty()) + return; + + insanityHandled = 0; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STAT_STUNNED); + me->RemoveAurasDueToSpell(INSANITY_VISUAL); + } + + if (uiMindFlayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MIND_FLAY); + uiMindFlayTimer = 20*IN_MILISECONDS; + } else uiMindFlayTimer -= diff; + + if (uiShadowBoltVolleyTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); + uiShadowBoltVolleyTimer = 5*IN_MILISECONDS; + } else uiShadowBoltVolleyTimer -= diff; + + if (uiShiverTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHIVER); + uiShiverTimer = 15*IN_MILISECONDS; + } else uiShiverTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH_1, me); + + if (pInstance) + pInstance->SetData(DATA_HERALD_VOLAZJ, DONE); + + Summons.DespawnAll(); + ResetPlayersPhaseMask(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_volazj(Creature* pCreature) +{ + return new boss_volazjAI (pCreature); +} + +void AddSC_boss_volazj() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_volazj"; + newscript->GetAI = &GetAI_boss_volazj; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp new file mode 100644 index 00000000000..eb8046f63cd --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp @@ -0,0 +1,588 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Comment: Complete - BUT THE TRIGGER NEEDS DATA WHETHER THE PRISON OF TALDARAM IS OFFLINE ! + */ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +enum Yells +{ + TEXT_AGGRO = -1619000, + TEXT_SACRIFICE_1_1 = -1619001, + TEXT_SACRIFICE_1_2 = -1619002, + TEXT_SACRIFICE_2_1 = -1619003, + TEXT_SACRIFICE_2_2 = -1619004, + TEXT_SLAY_1 = -1619005, + TEXT_SLAY_2 = -1619006, + TEXT_SLAY_3 = -1619007, + TEXT_DEATH = -1619008, + TEXT_PREACHING_1 = -1619009, + TEXT_PREACHING_2 = -1619010, + TEXT_PREACHING_3 = -1619011, + TEXT_PREACHING_4 = -1619012, + TEXT_PREACHING_5 = -1619013 +}; + +enum Spells +{ + SPELL_SPHERE_VISUAL = 56075, + SPELL_GIFT_OF_THE_HERALD = 56219, + SPELL_CYCLONE_STRIKE = 56855, // Self + SPELL_CYCLONE_STRIKE_H = 60030, + SPELL_LIGHTNING_BOLT = 56891, // 40Y + SPELL_LIGHTNING_BOLT_H = 60032, // 40Y + SPELL_THUNDERSHOCK = 56926, // 30Y + SPELL_THUNDERSHOCK_H = 60029 // 30Y +}; + +enum Creatures +{ + NPC_JEDOGA_CONTROLLER = 30181 +}; + +const Position JedogaPosition[2] = +{ + {372.330994f, -705.278015f, -0.624178f, 5.427970f}, + {372.330994f, -705.278015f, -16.179716f, 5.427970f} +}; + +struct boss_jedoga_shadowseekerAI : public ScriptedAI +{ + boss_jedoga_shadowseekerAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + bFirstTime = true; + bPreDone = false; + } + + ScriptedInstance* pInstance; + + uint32 uiOpFerTimer; + uint32 uiCycloneTimer; + uint32 uiBoltTimer; + uint32 uiThunderTimer; + + bool bPreDone; + bool bOpFerok; + bool bOnGround; + bool bOpFerokFail; + bool bCanDown; + + bool bFirstTime; + + void Reset() + { + uiOpFerTimer = urand(15*IN_MILISECONDS,20*IN_MILISECONDS); + + uiCycloneTimer = 3*IN_MILISECONDS; + uiBoltTimer = 7*IN_MILISECONDS; + uiThunderTimer = 12*IN_MILISECONDS; + + bOpFerok = false; + bOpFerokFail = false; + bOnGround = false; + bCanDown = false; + + if (pInstance) + { + if (!bFirstTime) + pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, FAIL); + + pInstance->SetData64(DATA_PL_JEDOGA_TARGET, 0); + pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); + pInstance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); + } + MoveUp(); + + bFirstTime = false; + } + + void EnterCombat(Unit* who) + { + if (!pInstance || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) + return; + + DoScriptText(TEXT_AGGRO, me); + me->SetInCombatWithZone(); + pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit* who) + { + if (!who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) + return; + + ScriptedAI::AttackStart(who); + } + + void KilledUnit(Unit* Victim) + { + if (!Victim || Victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(RAND(TEXT_SLAY_1, TEXT_SLAY_2, TEXT_SLAY_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(TEXT_DEATH, me); + if (pInstance) + pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, DONE); + } + + void MoveInLineOfSight(Unit* who) + { + if (!pInstance || !who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) + return; + + if (!bPreDone && who->GetTypeId() == TYPEID_PLAYER && me->GetDistance(who) < 100.0f) + { + DoScriptText(RAND(TEXT_PREACHING_1, TEXT_PREACHING_2, TEXT_PREACHING_3, TEXT_PREACHING_4, TEXT_PREACHING_5), me); + bPreDone = true; + } + + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS || !bOnGround) + return; + + if (!me->getVictim() && who->isTargetableForAttack() && me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + if (!me->getVictim()) + { + who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (me->GetMap()->IsDungeon()) + { + who->SetInCombatWith(me); + me->AddThreat(who, 0.0f); + } + } + } + } + + void MoveDown() + { + if (!pInstance) + return; + + bOpFerokFail = false; + + pInstance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 0); + me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); +/* me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); + me->SendMonsterMove(JedogaPosition[1], MOVEFLAG_JUMP, 0); + me->Relocate(JedogaPosition[1][0], JedogaPosition[1][1], JedogaPosition[1][2], JedogaPosition[1][3]); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); +*/ + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + + bOnGround = true; + + if (UpdateVictim()) + { + AttackStart(me->getVictim()); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + else + { + if (Unit* pTarget = Unit::GetUnit(*me, pInstance->GetData64(DATA_PL_JEDOGA_TARGET))) + { + AttackStart(pTarget); + pInstance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) + EnterCombat(pTarget); + } + else if (!me->isInCombat()) + EnterEvadeMode(); + } + } + + void MoveUp() + { + if (!pInstance) + return; + + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + + me->AttackStop(); + me->RemoveAllAuras(); + me->LoadCreaturesAddon(); + me->GetMotionMaster()->MovePoint(0, JedogaPosition[0]); +/* me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); + me->SendMonsterMove(JedogaPosition[0][0], JedogaPosition[0][1], JedogaPosition[0][2], 0, MOVEFLAG_JUMP, 0); + me->Relocate(JedogaPosition[0][0], JedogaPosition[0][1], JedogaPosition[0][2], JedogaPosition[0][3]); + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); +*/ + + pInstance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 1); + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) OpferRufen(); + + bOnGround = false; + uiOpFerTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } + + void OpferRufen() + { + if (!pInstance) + return; + + uint64 opfer = pInstance->GetData64(DATA_ADD_JEDOGA_INITIAND); + + if (opfer) + { + DoScriptText(RAND(TEXT_SACRIFICE_1_1, TEXT_SACRIFICE_1_2), me); + pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, opfer); + } else + bCanDown = true; + } + + void Opfern() + { + DoScriptText(RAND(TEXT_SACRIFICE_2_1, TEXT_SACRIFICE_2_2), me); + + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_GIFT_OF_THE_HERALD, false); + + bOpFerok = false; + bCanDown = true; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && pInstance->GetData(DATA_ALL_INITIAND_DEAD)) + MoveDown(); + + if (bOpFerok && !bOnGround && !bCanDown) Opfern(); + + if (bOpFerokFail && !bOnGround && !bCanDown) + bCanDown = true; + + if (bCanDown) + { + MoveDown(); + bCanDown = false; + } + + if (bOnGround) + { + if (!UpdateVictim()) + return; + + if (uiCycloneTimer <= diff) + { + DoCast(me, SPELL_CYCLONE_STRIKE, false); + uiCycloneTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiCycloneTimer -= diff; + + if (uiBoltTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + me->CastSpell(pTarget, DUNGEON_MODE(SPELL_LIGHTNING_BOLT, SPELL_LIGHTNING_BOLT_H), false); + + uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiBoltTimer -= diff; + + if (uiThunderTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + me->CastSpell(pTarget, DUNGEON_MODE(SPELL_THUNDERSHOCK, SPELL_THUNDERSHOCK_H), false); + + uiThunderTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiThunderTimer -= diff; + + if (uiOpFerTimer <= diff) + MoveUp(); + else + uiOpFerTimer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +struct mob_jedoga_initiandAI : public ScriptedAI +{ + mob_jedoga_initiandAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 bCheckTimer; + + bool bWalking; + + void Reset() + { + if (!pInstance) + return; + + bWalking = false; + bCheckTimer = 2*IN_MILISECONDS; + + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) + { + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + } + else + { + DoCast(me, SPELL_SPHERE_VISUAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + } + } + + void JustDied(Unit* Killer) + { + if (!Killer || !pInstance) return; + + if (bWalking) + { + Creature* boss = me->GetMap()->GetCreature(pInstance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); + if (boss && !CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok) CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = true; + + if (Killer->GetTypeId() == TYPEID_PLAYER) pInstance->SetData(DATA_INITIAND_KILLED, 1); + pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); + + bWalking = false; + } + if (Killer->GetTypeId() == TYPEID_PLAYER) pInstance->SetData64(DATA_PL_JEDOGA_TARGET, Killer->GetGUID()); + } + + void EnterCombat(Unit* who) + { + if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) return; + } + + void AttackStart(Unit* victim) + { + if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !victim) return; + + ScriptedAI::AttackStart(victim); + } + + void MoveInLineOfSight(Unit* who) + { + if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE || !pInstance) return; + + switch(uiPointId) + { + case 1: + { + Creature* boss = me->GetMap()->GetCreature(pInstance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); + if (boss) + { + CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok = true; + CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = false; + me->Kill(me); + } + } + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance && bCheckTimer <= diff) + { + if (me->GetGUID() == pInstance->GetData64(DATA_ADD_JEDOGA_OPFER) && !bWalking) + { + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + + float distance = me->GetDistance(JedogaPosition[1]); + + if (distance < 9.0f) + me->SetSpeed(MOVE_WALK, 0.5f, true); + else if (distance < 15.0f) + me->SetSpeed(MOVE_WALK, 0.75f, true); + else if (distance < 20.0f) + me->SetSpeed(MOVE_WALK, 1.0f, true); + + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); + bWalking = true; + } + if (!bWalking) + { + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && me->HasAura(SPELL_SPHERE_VISUAL)) + { + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + } + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS && !me->HasAura(SPELL_SPHERE_VISUAL)) + { + DoCast(me, SPELL_SPHERE_VISUAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + } + } + bCheckTimer = 2*IN_MILISECONDS; + } else bCheckTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +// ------------------------------------------------------------------------------------------------------------ +// Jedogas Aufseher - Entry: 30181 +// ------------------------------------------------------------------------------------------------------------ +enum AufseherSpell +{ + SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1 = 60342, + SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2 = 56312 +}; + +struct npc_jedogas_aufseher_triggerAI : public Scripted_NoMovementAI +{ + npc_jedogas_aufseher_triggerAI(Creature* c) : Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); +// c->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); +// c->setFaction(35); + bRemoved = false; + bRemoved2 = false; + bCasted = false; + bCasted2 = false; + } + + ScriptedInstance* pInstance; + + bool bRemoved; + bool bRemoved2; + bool bCasted; + bool bCasted2; + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*victim*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 /*diff*/) + { + if (!pInstance) + return; + + if (!bRemoved && me->GetPositionX() > 440.0f) + { + if (pInstance->GetData(DATA_PRINCE_TALDARAM_EVENT) == DONE) + { + me->InterruptNonMeleeSpells(true); + bRemoved = true; + return; + } + if (!bCasted) + { + DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1, false); + bCasted = true; + } + } + if (!bRemoved2 && me->GetPositionX() < 440.0f) + { + if (!bCasted2 && pInstance->GetData(DATA_JEDOGA_TRIGGER_SWITCH)) + { + DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2, false); + bCasted2 = true; + } + if (bCasted2 && !pInstance->GetData(DATA_JEDOGA_TRIGGER_SWITCH)) + { + me->InterruptNonMeleeSpells(true); + bCasted2 = false; + } + if (!bRemoved2 && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == DONE) + { + me->InterruptNonMeleeSpells(true); + bRemoved2 = true; + } + } + } +}; + +CreatureAI* GetAI_boss_jedoga_shadowseeker(Creature* pCreature) +{ + return new boss_jedoga_shadowseekerAI (pCreature); +} + +CreatureAI* GetAI_mob_jedoga_initiand(Creature* pCreature) +{ + return new mob_jedoga_initiandAI (pCreature); +} + +CreatureAI* GetAI_npc_jedogas_aufseher_trigger(Creature* pCreature) +{ + return new npc_jedogas_aufseher_triggerAI (pCreature); +} + +void AddSC_boss_jedoga_shadowseeker() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_jedoga_shadowseeker"; + newscript->GetAI = &GetAI_boss_jedoga_shadowseeker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_jedoga_initiand"; + newscript->GetAI = &GetAI_mob_jedoga_initiand; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jedogas_aufseher_trigger"; + newscript->GetAI = &GetAI_npc_jedogas_aufseher_trigger; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp new file mode 100644 index 00000000000..93a66ccfbca --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +enum Spells +{ + SPELL_BLOODTHIRST = 55968, //Trigger Spell + add aura + SPELL_CONJURE_FLAME_SPHERE = 55931, + SPELL_FLAME_SPHERE_SUMMON_1 = 55895,// 1x 30106 + H_SPELL_FLAME_SPHERE_SUMMON_1 = 59511,// 1x 31686 + H_SPELL_FLAME_SPHERE_SUMMON_2 = 59512,// 1x 31687 + SPELL_FLAME_SPHERE_SPAWN_EFFECT = 55891, + SPELL_FLAME_SPHERE_VISUAL = 55928, + SPELL_FLAME_SPHERE_PERIODIC = 55926, + H_SPELL_FLAME_SPHERE_PERIODIC = 59508, + SPELL_FLAME_SPHERE_DEATH_EFFECT = 55947, + SPELL_BEAM_VISUAL = 60342, + SPELL_EMBRACE_OF_THE_VAMPYR = 55959, + H_SPELL_EMBRACE_OF_THE_VAMPYR = 59513, + SPELL_VANISH = 55964, + CREATURE_FLAME_SPHERE = 30106, + H_CREATURE_FLAME_SPHERE_1 = 31686, + H_CREATURE_FLAME_SPHERE_2 = 31687 +}; +enum Misc +{ + DATA_EMBRACE_DMG = 20000, + H_DATA_EMBRACE_DMG = 40000, + DATA_SPHERE_DISTANCE = 15 +}; +#define DATA_SPHERE_ANGLE_OFFSET 0.7 +#define DATA_GROUND_POSITION_Z 11.4 + +enum Yells +{ + SAY_AGGRO = -1619021, + SAY_SLAY_1 = -1619022, + SAY_SLAY_2 = -1619023, + SAY_DEATH = -1619024, + SAY_FEED_1 = -1619025, + SAY_FEED_2 = -1619026, + SAY_VANISH_1 = -1619027, + SAY_VANISH_2 = -1619028 +}; +enum CombatPhase +{ + NORMAL, + CASTING_FLAME_SPHERES, + JUST_VANISHED, + VANISHED, + FEEDING +}; +enum GameObjects +{ + GO_SPHERE1 = 193093, + GO_SPHERE2 = 193094 +}; + +struct boss_taldaramAI : public ScriptedAI +{ + boss_taldaramAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + uint32 uiBloodthirstTimer; + uint32 uiVanishTimer; + uint32 uiWaitTimer; + uint32 uiEmbraceTimer; + uint32 uiEmbraceTakenDamage; + uint32 uiFlamesphereTimer; + uint32 uiPhaseTimer; + + uint64 uiEmbraceTarget; + + CombatPhase Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + uiBloodthirstTimer = 10*IN_MILISECONDS; + uiVanishTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); + uiEmbraceTimer = 20*IN_MILISECONDS; + uiFlamesphereTimer = 5*IN_MILISECONDS; + uiEmbraceTakenDamage = 0; + Phase = NORMAL; + uiPhaseTimer = 0; + uiEmbraceTarget = 0; + if (pInstance) + pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, IN_PROGRESS); + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + if (uiPhaseTimer <= diff) + { + switch (Phase) + { + case CASTING_FLAME_SPHERES: + { + Creature* pSpheres[3]; + + //DoCast(me, SPELL_FLAME_SPHERE_SUMMON_1); + pSpheres[0] = DoSpawnCreature(CREATURE_FLAME_SPHERE, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); + Unit *pSphereTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pSphereTarget && pSpheres[0]) + { + float angle,x,y; + angle = pSpheres[0]->GetAngle(pSphereTarget); + x = pSpheres[0]->GetPositionX() + DATA_SPHERE_DISTANCE * cos(angle); + y = pSpheres[0]->GetPositionY() + DATA_SPHERE_DISTANCE * sin(angle); + pSpheres[0]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[0]->GetPositionZ()); + } + if (IsHeroic()) + { + //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_1); + pSpheres[1] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_1, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); + //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_2); + pSpheres[2] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_2, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); + if (pSphereTarget && pSpheres[1] && pSpheres[2]) + { + float angle,x,y; + angle = pSpheres[1]->GetAngle(pSphereTarget) + DATA_SPHERE_ANGLE_OFFSET; + x = pSpheres[1]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * cos(angle); + y = pSpheres[1]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * sin(angle); + pSpheres[1]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[1]->GetPositionZ()); + angle = pSpheres[2]->GetAngle(pSphereTarget) - DATA_SPHERE_ANGLE_OFFSET; + x = pSpheres[2]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * cos(angle); + y = pSpheres[2]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * sin(angle); + pSpheres[2]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[2]->GetPositionZ()); + } + } + + Phase = NORMAL; + uiPhaseTimer = 0; + break; + } + case JUST_VANISHED: + if (Unit *pEmbraceTarget = GetEmbraceTarget()) + { + me->GetMotionMaster()->Clear(); + me->SetSpeed(MOVE_WALK, 2.0f, true); + me->GetMotionMaster()->MoveChase(pEmbraceTarget); + } + Phase = VANISHED; + uiPhaseTimer = 1300; + break; + case VANISHED: + if (Unit *pEmbraceTarget = GetEmbraceTarget()) + DoCast(pEmbraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR); + me->GetMotionMaster()->Clear(); + me->SetSpeed(MOVE_WALK, 1.0f, true); + me->GetMotionMaster()->MoveChase(me->getVictim()); + Phase = FEEDING; + uiPhaseTimer = 20*IN_MILISECONDS; + break; + case FEEDING: + Phase = NORMAL; + uiPhaseTimer = 0; + uiEmbraceTarget = 0; + break; + case NORMAL: + if (uiBloodthirstTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BLOODTHIRST); + uiBloodthirstTimer = 10*IN_MILISECONDS; + } else uiBloodthirstTimer -= diff; + + if (uiFlamesphereTimer <= diff) + { + DoCast(me, SPELL_CONJURE_FLAME_SPHERE); + Phase = CASTING_FLAME_SPHERES; + uiPhaseTimer = 3*IN_MILISECONDS + diff; + uiFlamesphereTimer = 15*IN_MILISECONDS; + } else uiFlamesphereTimer -= diff; + + if (uiVanishTimer <= diff) + { + //Count alive players + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + // exclude pets & totems + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + target_list.push_back(pTarget); + pTarget = NULL; + } + //He only vanishes if there are 3 or more alive players + if (target_list.size() > 2) + { + DoScriptText(RAND(SAY_VANISH_1,SAY_VANISH_2), me); + DoCast(me, SPELL_VANISH); + Phase = JUST_VANISHED; + uiPhaseTimer = 500; + if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + uiEmbraceTarget = pEmbraceTarget->GetGUID(); + + } + uiVanishTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); + } else uiVanishTimer -= diff; + + DoMeleeAttackIfReady(); + break; + } + } else uiPhaseTimer -= diff; + } + + void DamageTaken(Unit* /*done_by*/, uint32 &damage) + { + Unit* pEmbraceTarget = GetEmbraceTarget(); + + if (Phase == FEEDING && pEmbraceTarget && pEmbraceTarget->isAlive()) + { + uiEmbraceTakenDamage += damage; + if (uiEmbraceTakenDamage > DUNGEON_MODE(DATA_EMBRACE_DMG, H_DATA_EMBRACE_DMG)) + { + Phase = NORMAL; + uiPhaseTimer = 0; + uiEmbraceTarget = 0; + me->CastStop(); + } + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + Unit* pEmbraceTarget = GetEmbraceTarget(); + if (Phase == FEEDING && pEmbraceTarget && victim == pEmbraceTarget) + { + Phase = NORMAL; + uiPhaseTimer = 0; + uiEmbraceTarget = 0; + } + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + bool CheckSpheres() + { + if (!pInstance) + return false; + + uint64 uiSphereGuids[2]; + uiSphereGuids[0] = pInstance->GetData64(DATA_SPHERE1); + uiSphereGuids[1] = pInstance->GetData64(DATA_SPHERE2); + + for (uint8 i=0; i < 2; ++i) + { + GameObject *pSpheres = pInstance->instance->GetGameObject(uiSphereGuids[i]); + if (!pSpheres) + return false; + if (pSpheres->GetGoState() != GO_STATE_ACTIVE) + return false; + } + RemovePrison(); + return true; + } + + Unit* GetEmbraceTarget() + { + if (!uiEmbraceTarget) + return NULL; + + return Unit::GetUnit(*me, uiEmbraceTarget); + } + + void RemovePrison() + { + if (!pInstance) + return; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAurasDueToSpell(SPELL_BEAM_VISUAL); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation()); + uint64 prison_GUID = pInstance->GetData64(DATA_PRINCE_TALDARAM_PLATFORM); + pInstance->HandleGameObject(prison_GUID,true); + } +}; + +struct mob_taldaram_flamesphereAI : public ScriptedAI +{ + mob_taldaram_flamesphereAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiDespawnTimer; + ScriptedInstance* pInstance; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->setFaction(16); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + DoCast(me, SPELL_FLAME_SPHERE_VISUAL); + DoCast(me, SPELL_FLAME_SPHERE_SPAWN_EFFECT); + DoCast(me, SPELL_FLAME_SPHERE_PERIODIC); + uiDespawnTimer = 10*IN_MILISECONDS; + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void JustDied(Unit* /*who*/) + { + DoCast(me, SPELL_FLAME_SPHERE_DEATH_EFFECT); + } + + void UpdateAI(const uint32 diff) + { + if (uiDespawnTimer <= diff) + me->DisappearAndDie(); + else + uiDespawnTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_taldaram(Creature* pCreature) +{ + return new boss_taldaramAI (pCreature); +} + +CreatureAI* GetAI_mob_taldaram_flamesphere(Creature* pCreature) +{ + return new mob_taldaram_flamesphereAI (pCreature); +} + +bool GOHello_prince_taldaram_sphere(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + + Creature *pPrinceTaldaram = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_PRINCE_TALDARAM) : 0); + if (pPrinceTaldaram && pPrinceTaldaram->isAlive()) + { + // maybe these are hacks :( + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + switch(pGO->GetEntry()) + { + case GO_SPHERE1: pInstance->SetData(DATA_SPHERE1_EVENT,IN_PROGRESS); break; + case GO_SPHERE2: pInstance->SetData(DATA_SPHERE2_EVENT,IN_PROGRESS); break; + } + + CAST_AI(boss_taldaramAI, pPrinceTaldaram->AI())->CheckSpheres(); + } + return true; +} + +void AddSC_boss_taldaram() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_taldaram"; + newscript->GetAI = &GetAI_boss_taldaram; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_taldaram_flamesphere"; + newscript->GetAI = &GetAI_mob_taldaram_flamesphere; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "prince_taldaram_sphere"; + newscript->pGOHello = &GOHello_prince_taldaram_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp new file mode 100644 index 00000000000..4e6e3ec8c9f --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp @@ -0,0 +1,313 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +/* Ahn'kahet encounters: +0 - Elder Nadox +1 - Prince Taldaram +2 - Jedoga Shadowseeker +3 - Herald Volazj +4 - Amanitar (Heroic only) +*/ + +#define MAX_ENCOUNTER 5 + +enum Achievements +{ + ACHIEV_VOLUNTEER_WORK = 2056 +}; + +struct instance_ahnkahet : public ScriptedInstance +{ + instance_ahnkahet(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 Elder_Nadox; + uint64 Prince_Taldaram; + uint64 Jedoga_Shadowseeker; + uint64 Herald_Volazj; + uint64 Amanitar; + + uint64 Prince_TaldaramSpheres[2]; + uint64 Prince_TaldaramPlatform; + uint64 Prince_TaldaramGate; + + std::set InitiandGUIDs; + uint64 JedogaSacrifices; + uint64 JedogaTarget; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 spheres[2]; + + uint8 InitiandCnt, + switchtrigger, + initiandkilled; + + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + InitiandGUIDs.clear(); + + Elder_Nadox =0; + Prince_Taldaram =0; + Jedoga_Shadowseeker =0; + Herald_Volazj =0; + Amanitar =0; + + spheres[0] = NOT_STARTED; + spheres[1] = NOT_STARTED; + + InitiandCnt = 0; + switchtrigger = 0; + initiandkilled = 0; + JedogaSacrifices = 0; + JedogaTarget = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 29309: Elder_Nadox = pCreature->GetGUID(); break; + case 29308: Prince_Taldaram = pCreature->GetGUID(); break; + case 29310: Jedoga_Shadowseeker = pCreature->GetGUID(); break; + case 29311: Herald_Volazj = pCreature->GetGUID(); break; + case 30258: Amanitar = pCreature->GetGUID(); break; + case 30114: InitiandGUIDs.insert(pCreature->GetGUID()); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 193564: Prince_TaldaramPlatform = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) HandleGameObject(NULL,true,pGo); break; + case 193093: Prince_TaldaramSpheres[0] = pGo->GetGUID(); + if (spheres[0] == IN_PROGRESS) + { + pGo->SetGoState(GO_STATE_ACTIVE); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + else pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case 193094: Prince_TaldaramSpheres[1] = pGo->GetGUID(); + if (spheres[1] == IN_PROGRESS) + { + pGo->SetGoState(GO_STATE_ACTIVE); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + else pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case 192236: Prince_TaldaramGate = pGo->GetGUID(); // Web gate past Prince Taldaram + if (m_auiEncounter[1] == DONE)HandleGameObject(NULL,true,pGo);break; + } + } + + void SetData64(uint32 idx, uint64 guid) + { + switch(idx) + { + case DATA_ADD_JEDOGA_OPFER: JedogaSacrifices = guid; break; + case DATA_PL_JEDOGA_TARGET: JedogaTarget = guid; break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_ELDER_NADOX: return Elder_Nadox; + case DATA_PRINCE_TALDARAM: return Prince_Taldaram; + case DATA_JEDOGA_SHADOWSEEKER: return Jedoga_Shadowseeker; + case DATA_HERALD_VOLAZJ: return Herald_Volazj; + case DATA_AMANITAR: return Amanitar; + case DATA_SPHERE1: return Prince_TaldaramSpheres[0]; + case DATA_SPHERE2: return Prince_TaldaramSpheres[1]; + case DATA_PRINCE_TALDARAM_PLATFORM: return Prince_TaldaramPlatform; + case DATA_ADD_JEDOGA_INITIAND: + { + std::vector vInitiands; + vInitiands.clear(); + for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (cr && cr->isAlive()) + vInitiands.push_back(*itr); + } + if (vInitiands.empty()) + return 0; + uint8 j = urand(0,vInitiands.size() -1); + return vInitiands[j]; + } + case DATA_ADD_JEDOGA_OPFER: return JedogaSacrifices; + case DATA_PL_JEDOGA_TARGET: return JedogaTarget; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_ELDER_NADOX_EVENT: m_auiEncounter[0] = data; break; + case DATA_PRINCE_TALDARAM_EVENT: + if (data == DONE) + HandleGameObject(Prince_TaldaramGate,true); + m_auiEncounter[1] = data; + break; + case DATA_JEDOGA_SHADOWSEEKER_EVENT: + m_auiEncounter[2] = data; + if (data == DONE) + { + for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (cr && cr->isAlive()) + { + cr->SetVisibility(VISIBILITY_OFF); + cr->setDeathState(JUST_DIED); + cr->RemoveCorpse(); + } + } + if (!initiandkilled && instance->IsHeroic()) + DoCompleteAchievement(ACHIEV_VOLUNTEER_WORK); + } + break; + case DATA_HERALD_VOLAZJ_EVENT: m_auiEncounter[3] = data; break; + case DATA_AMANITAR_EVENT: m_auiEncounter[4] = data; break; + case DATA_SPHERE1_EVENT: spheres[0] = data; break; + case DATA_SPHERE2_EVENT: spheres[1] = data; break; + case DATA_JEDOGA_TRIGGER_SWITCH: switchtrigger = data; break; + case DATA_INITIAND_KILLED: initiandkilled = data; break; + case DATA_JEDOGA_RESET_INITIANDS: + for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (cr) + { + cr->Respawn(); + if (!cr->IsInEvadeMode()) cr->AI()->EnterEvadeMode(); + } + } + break; + } + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_ELDER_NADOX_EVENT: return m_auiEncounter[0]; + case DATA_PRINCE_TALDARAM_EVENT: return m_auiEncounter[1]; + case DATA_JEDOGA_SHADOWSEEKER_EVENT: return m_auiEncounter[2]; + case DATA_HERALD_VOLAZJ: return m_auiEncounter[3]; + case DATA_AMANITAR_EVENT: return m_auiEncounter[4]; + case DATA_SPHERE1_EVENT: return spheres[0]; + case DATA_SPHERE2_EVENT: return spheres[1]; + case DATA_ALL_INITIAND_DEAD: + for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (!cr || (cr && cr->isAlive())) return 0; + } + return 1; + case DATA_JEDOGA_TRIGGER_SWITCH: return switchtrigger; + case DATA_INITIAND_KILLED: return initiandkilled; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "A K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " + << spheres[0] << " " << spheres[1]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5, data6; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6; + + if (dataHead1 == 'A' && dataHead2 == 'K') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + spheres[0] = data5; + spheres[1] = data6; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_ahnkahet(Map* pMap) +{ + return new instance_ahnkahet(pMap); +} + +void AddSC_instance_ahnkahet() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_ahnkahet"; + newscript->GetInstanceData = &GetInstanceData_instance_ahnkahet; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h new file mode 100644 index 00000000000..4113885b6f4 --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_AZJOL_NERUB_H +#define DEF_AZJOL_NERUB_H + +enum Data64 +{ + DATA_KRIKTHIR_THE_GATEWATCHER, + DATA_HADRONOX, + DATA_ANUBARAK, + DATA_WATCHER_GASHRA, + DATA_WATCHER_SILTHIK, + DATA_WATCHER_NARJIL +}; +enum Data +{ + DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, + DATA_HADRONOX_EVENT, + DATA_ANUBARAK_EVENT +}; + +#endif diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp new file mode 100644 index 00000000000..6de6578f7bb --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp @@ -0,0 +1,360 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +//SQL: UPDATE creature_template SET mechanic_immune_mask = 1073741823 WHERE name like "anub'arak%"; + +enum Spells +{ + SPELL_CARRION_BEETLES = 53520, + SPELL_SUMMON_CARRION_BEETLES = 53521, + SPELL_LEECHING_SWARM = 53467, + SPELL_POUND = 53472, + SPELL_POUND_H = 59433, + SPELL_SUBMERGE = 53421, + SPELL_IMPALE_DMG = 53454, + SPELL_IMPALE_DMG_H = 59446, + SPELL_IMPALE_SHAKEGROUND = 53455, + SPELL_IMPALE_SPIKE = 53539, //this is not the correct visual effect + //SPELL_IMPALE_TARGET = 53458, +}; + +enum Creatures +{ + CREATURE_GUARDIAN = 29216, + CREATURE_VENOMANCER = 29217, + CREATURE_DATTER = 29213, + CREATURE_IMPALE_TARGET = 89, + DISPLAY_INVISIBLE = 11686 +}; + +// not in db +enum Yells +{ + SAY_INTRO = -1601010, + SAY_AGGRO = -1601000, + SAY_SLAY_1 = -1601001, + SAY_SLAY_2 = -1601002, + SAY_SLAY_3 = -1601003, + SAY_LOCUST_1 = -1601005, + SAY_LOCUST_2 = -1601006, + SAY_LOCUST_3 = -1601007, + SAY_SUBMERGE_1 = -1601008, + SAY_SUBMERGE_2 = -1601009, + SAY_DEATH = -1601004 +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 20381, +}; + +enum Phases +{ + PHASE_MELEE = 0, + PHASE_UNDERGROUND = 1, + IMPALE_PHASE_TARGET = 0, + IMPALE_PHASE_ATTACK = 1, + IMPALE_PHASE_DMG = 2 +}; + +const Position SpawnPoint[2] = +{ + { 550.7, 282.8, 224.3 }, + { 551.1, 229.4, 224.3 }, +}; + +const Position SpawnPointGuardian[2] = +{ + { 550.348633, 316.006805, 234.2947 }, + { 550.188660, 324.264557, 237.7412 }, +}; + +struct boss_anub_arakAI : public ScriptedAI +{ + boss_anub_arakAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + bool bChanneling; + bool bGuardianSummoned; + bool bVenomancerSummoned; + bool bDatterSummoned; + uint8 uiPhase; + uint32 uiUndergroundPhase; + uint32 uiCarrionBeetlesTimer; + uint32 uiLeechingSwarmTimer; + uint32 uiPoundTimer; + uint32 uiSubmergeTimer; + uint32 uiUndergroundTimer; + uint32 uiVenomancerTimer; + uint32 uiDatterTimer; + + uint32 uiImpaleTimer; + uint32 uiImpalePhase; + uint64 uiImpaleTarget; + + SummonList lSummons; + + void Reset() + { + uiCarrionBeetlesTimer = 8*IN_MILISECONDS; + uiLeechingSwarmTimer = 20*IN_MILISECONDS; + uiImpaleTimer = 9*IN_MILISECONDS; + uiPoundTimer = 15*IN_MILISECONDS; + + uiPhase = PHASE_MELEE; + uiUndergroundPhase = 0; + bChanneling = false; + uiImpalePhase = IMPALE_PHASE_TARGET; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAura(SPELL_SUBMERGE); + + lSummons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_ANUBARAK_EVENT, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + Creature* DoSummonImpaleTarget(Unit *pTarget) + { + Position targetPos; + pTarget->GetPosition(&targetPos); + + if (TempSummon* pImpaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILISECONDS)) + { + uiImpaleTarget = pImpaleTarget->GetGUID(); + pImpaleTarget->SetReactState(REACT_PASSIVE); + pImpaleTarget->SetDisplayId(DISPLAY_INVISIBLE); + pImpaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + return pImpaleTarget; + } + + return NULL; + } + + void EnterCombat(Unit * /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + pInstance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + switch (uiPhase) + { + case PHASE_UNDERGROUND: + if (uiImpaleTimer <= diff) + { + switch(uiImpalePhase) + { + case IMPALE_PHASE_TARGET: + if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) + pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SHAKEGROUND, true); + uiImpaleTimer = 3*IN_MILISECONDS; + uiImpalePhase = IMPALE_PHASE_ATTACK; + } + break; + case IMPALE_PHASE_ATTACK: + if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) + { + pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SPIKE, false); + pImpaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND); + } + uiImpalePhase = IMPALE_PHASE_DMG; + uiImpaleTimer = 1*IN_MILISECONDS; + break; + case IMPALE_PHASE_DMG: + if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) + me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_IMPALE_DMG, SPELL_IMPALE_DMG_H), true); + uiImpalePhase = IMPALE_PHASE_TARGET; + uiImpaleTimer = 9*IN_MILISECONDS; + break; + } + } else uiImpaleTimer -= diff; + + if (!bGuardianSummoned) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Guardian = me->SummonCreature(CREATURE_GUARDIAN,SpawnPointGuardian[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Guardian->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Guardian); + } + } + bGuardianSummoned = true; + } + + if (!bVenomancerSummoned) + { + if (uiVenomancerTimer <= diff) + { + if (uiUndergroundPhase > 1) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Venomancer = me->SummonCreature(CREATURE_VENOMANCER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Venomancer->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Venomancer); + } + } + bVenomancerSummoned = true; + } + } else uiVenomancerTimer -= diff; + } + + if (!bDatterSummoned) + { + if (uiDatterTimer <= diff) + { + if (uiUndergroundPhase > 2) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Datter = me->SummonCreature(CREATURE_DATTER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Datter->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Datter); + } + } + bDatterSummoned = true; + } + } else uiDatterTimer -= diff; + } + + if (uiUndergroundTimer <= diff) + { + me->RemoveAura(SPELL_SUBMERGE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + uiPhase = PHASE_MELEE; + } else uiUndergroundTimer -= diff; + break; + + case PHASE_MELEE: + if (((uiUndergroundPhase == 0 && HealthBelowPct(75)) + || (uiUndergroundPhase == 1 && HealthBelowPct(50)) + || (uiUndergroundPhase == 2 && HealthBelowPct(25))) + && !me->hasUnitState(UNIT_STAT_CASTING)) + { + bGuardianSummoned = false; + bVenomancerSummoned = false; + bDatterSummoned = false; + + uiUndergroundTimer = 40*IN_MILISECONDS; + uiVenomancerTimer = 25*IN_MILISECONDS; + uiDatterTimer = 32*IN_MILISECONDS; + + uiImpalePhase = 0; + uiImpaleTimer = 9*IN_MILISECONDS; + + DoCast(me, SPELL_SUBMERGE, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + + uiPhase = PHASE_UNDERGROUND; + ++uiUndergroundPhase; + } + + if (bChanneling == true) + { + for (uint8 i = 0; i < 8; ++i) + DoCast(me->getVictim(), SPELL_SUMMON_CARRION_BEETLES, true); + bChanneling = false; + } + else if (uiCarrionBeetlesTimer <= diff) + { + bChanneling = true; + DoCastVictim(SPELL_CARRION_BEETLES); + uiCarrionBeetlesTimer = 25*IN_MILISECONDS; + } else uiCarrionBeetlesTimer -= diff; + + if (uiLeechingSwarmTimer <= diff) + { + DoCast(me, SPELL_LEECHING_SWARM, true); + uiLeechingSwarmTimer = 19*IN_MILISECONDS; + } else uiLeechingSwarmTimer -= diff; + + if (uiPoundTimer <= diff) + { + if (Unit *target = me->getVictim()) + { + if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) + me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_POUND, SPELL_POUND_H), false); + } + uiPoundTimer = 16.5*IN_MILISECONDS; + } else uiPoundTimer -= diff; + + DoMeleeAttackIfReady(); + break; + } + } + + void JustDied(Unit * /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + lSummons.DespawnAll(); + if (pInstance) + pInstance->SetData(DATA_ANUBARAK_EVENT, DONE); + } + + void KilledUnit(Unit *pVictim) + { + if (pVictim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustSummoned(Creature* summon) + { + lSummons.Summon(summon); + } +}; + +CreatureAI* GetAI_boss_anub_arak(Creature *pCreature) +{ + return new boss_anub_arakAI (pCreature); +} + +void AddSC_boss_anub_arak() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_anub_arak"; + newscript->GetAI = &GetAI_boss_anub_arak; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp new file mode 100644 index 00000000000..0fc4e87d7c5 --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* +* Comment: No Waves atm and the doors spells are crazy... +* +* When your group enters the main room (the one after the bridge), you will notice a group of 3 Nerubians. +* When you engage them, 2 more groups like this one spawn behind the first one - it is important to pull the first group back, +* so you don't aggro all 3. Hadronox will be under you, fighting Nerubians. +* +* This is the timed gauntlet - waves of non-elite spiders +* will spawn from the 3 doors located a little above the main room, and will then head down to fight Hadronox. After clearing the +* main room, it is recommended to just stay in it, kill the occasional non-elites that will attack you instead of the boss, and wait for +* Hadronox to make his way to you. When Hadronox enters the main room, she will web the doors, and no more non-elites will spawn. +*/ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +enum Spells +{ + SPELL_ACID_CLOUD = 53400, // Victim + SPELL_LEECH_POISON = 53030, // Victim + SPELL_PIERCE_ARMOR = 53418, // Victim + SPELL_WEB_GRAB = 57731, // Victim + SPELL_WEB_FRONT_DOORS = 53177, // Self + SPELL_WEB_SIDE_DOORS = 53185, // Self + H_SPELL_ACID_CLOUD = 59419, + H_SPELL_LEECH_POISON = 59417, + H_SPELL_WEB_GRAB = 59421 +}; + +struct boss_hadronoxAI : public ScriptedAI +{ + boss_hadronoxAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + fMaxDistance = 50.0f; + bFirstTime = true; + } + + ScriptedInstance* pInstance; + + uint32 uiAcidTimer; + uint32 uiLeechTimer; + uint32 uiPierceTimer; + uint32 uiGrabTimer; + uint32 uiDoorsTimer; + uint32 uiCheckDistanceTimer; + + bool bFirstTime; + + float fMaxDistance; + + void Reset() + { + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 9.0f); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 9.0f); + + uiAcidTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); + uiLeechTimer = urand(3*IN_MILISECONDS,9*IN_MILISECONDS); + uiPierceTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); + uiGrabTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); + uiDoorsTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + uiCheckDistanceTimer = 2*IN_MILISECONDS; + + if (pInstance && (pInstance->GetData(DATA_HADRONOX_EVENT) != DONE && !bFirstTime)) + pInstance->SetData(DATA_HADRONOX_EVENT, FAIL); + + bFirstTime = false; + } + + //when Hadronox kills any enemy (that includes a party member) she will regain 10% of her HP if the target had Leech Poison on + void KilledUnit(Unit* Victim) + { + // not sure if this aura check is correct, I think it is though + if (!Victim || !Victim->HasAura(DUNGEON_MODE(SPELL_LEECH_POISON, H_SPELL_LEECH_POISON)) || !me->isAlive()) + return; + + uint32 health = me->GetMaxHealth()/10; + + if ((me->GetHealth()+health) >= me->GetMaxHealth()) + me->SetHealth(me->GetMaxHealth()); + else + me->SetHealth(me->GetHealth()+health); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_HADRONOX_EVENT, DONE); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HADRONOX_EVENT, IN_PROGRESS); + me->SetInCombatWithZone(); + } + + void CheckDistance(float dist, const uint32 uiDiff) + { + if (!me->isInCombat()) + return; + + float x=0.0f, y=0.0f, z=0.0f; + me->GetRespawnCoord(x,y,z); + + if (uiCheckDistanceTimer <= uiDiff) + uiCheckDistanceTimer = 5*IN_MILISECONDS; + else + { + uiCheckDistanceTimer -= uiDiff; + return; + } + if (me->IsInEvadeMode() || !me->getVictim()) + return; + if (me->GetDistance(x,y,z) > dist) + EnterEvadeMode(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) return; + + // Without he comes up through the air to players on the bridge after krikthir if players crossing this bridge! + CheckDistance(fMaxDistance, diff); + + if (me->HasAura(SPELL_WEB_FRONT_DOORS) || me->HasAura(SPELL_WEB_SIDE_DOORS)) + { + if (IsCombatMovement()) + SetCombatMovement(false); + } + else if (!IsCombatMovement()) + SetCombatMovement(true); + + if (uiPierceTimer <= diff) + { + DoCast(me->getVictim(), SPELL_PIERCE_ARMOR); + uiPierceTimer = 8*IN_MILISECONDS; + } else uiPierceTimer -= diff; + + if (uiAcidTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ACID_CLOUD); + + uiAcidTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiAcidTimer -= diff; + + if (uiLeechTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_LEECH_POISON); + + uiLeechTimer = urand(11*IN_MILISECONDS,14*IN_MILISECONDS); + } else uiLeechTimer -= diff; + + if (uiGrabTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) // Draws all players (and attacking Mobs) to itself. + DoCast(pTarget, SPELL_WEB_GRAB); + + uiGrabTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiGrabTimer -= diff; + + if (uiDoorsTimer <= diff) + { + //DoCast(me, RAND(SPELL_WEB_FRONT_DOORS, SPELL_WEB_SIDE_DOORS)); + uiDoorsTimer = urand(30*IN_MILISECONDS,60*IN_MILISECONDS); + } else uiDoorsTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_hadronox(Creature* pCreature) +{ + return new boss_hadronoxAI (pCreature); +} + +void AddSC_boss_hadronox() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_hadronox"; + newscript->GetAI = &GetAI_boss_hadronox; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp new file mode 100644 index 00000000000..4863bdcb032 --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp @@ -0,0 +1,553 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: Find in the future best timers and the event is not implemented. + */ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +enum Spells +{ + SPELL_MIND_FLAY = 52586, + H_SPELL_MIND_FLAY = 59367, + SPELL_CURSE_OF_FATIGUE = 52592, + H_SPELL_CURSE_OF_FATIGUE = 59368, + SPELL_FRENZY = 28747, //maybe 53361 + SPELL_SUMMON_SKITTERING_SWARMER = 52438, //AOE Effect 140, maybe 52439 + SPELL_SUMMON_SKITTERING_SWARMER_1 = 52439, //Summon 3x 28735 + H_SPELL_ACID_SPLASH = 59363, + SPELL_ACID_SPLASH = 52446, + SPELL_CHARGE = 16979,//maybe is another spell + SPELL_BACKSTAB = 52540, + SPELL_SHADOW_BOLT = 52534, + H_SPELL_SHADOW_BOLT = 59357, + SPELL_SHADOW_NOVA = 52535, + H_SPELL_SHADOW_NOVA = 59358, + SPELL_STRIKE = 52532, + SPELL_CLEAVE = 49806, + SPELL_ENRAGE = 52470, + SPELL_INFECTED_BITE = 52469, + H_SPELL_INFECTED_BITE = 59364, + SPELL_WEB_WRAP = 52086,//the spell is not working properly + SPELL_BLINDING_WEBS = 52524, + H_SPELL_BLINDING_WEBS = 59365, + SPELL_POSION_SPRAY = 52493, + H_SPELL_POSION_SPRAY = 59366 +}; + +enum Mobs +{ + MOB_SKITTERING_SWARMER = 28735, + MOB_SKITTERING_SWARMER_CONTROLLER = 32593, + MOB_SKITTERING_INFECTIOR = 28736 +}; + +enum Yells +{ + SAY_AGGRO = -1601011, + SAY_SLAY_1 = -1601012, + SAY_SLAY_2 = -1601013, + SAY_DEATH = -1601014, + //Not in db + SAY_SEND_GROUP_1 = -1601020, + SAY_SEND_GROUP_2 = -1601021, + SAY_SEND_GROUP_3 = -1601022, + SAY_SWARM_1 = -1601015, + SAY_SWARM_2 = -1601016, + SAY_PREFIGHT_1 = -1601017, + SAY_PREFIGHT_2 = -1601018, + SAY_PREFIGHT_3 = -1601019 +}; + +enum Misc +{ + ACHIEV_WATH_HIM_DIE = 1296 +}; + +const Position SpawnPoint[] = +{ + { 566.164, 682.087, 769.079, 2.21657 }, + { 529.042, 706.941, 777.298, 1.0821 }, + { 489.975, 671.239, 772.131, 0.261799 }, + { 488.556, 692.95, 771.764, 4.88692 }, + { 553.34, 640.387, 777.419, 1.20428 }, + { 517.486, 706.398, 777.335, 5.35816 }, + { 504.01, 637.693, 777.479, 0.506145 }, + { 552.625, 706.408, 777.177, 3.4383 } +}; +struct boss_krik_thirAI : public ScriptedAI +{ + boss_krik_thirAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiMindFlayTimer; + uint32 uiCurseFatigueTimer; + uint32 uiSummonTimer; + + void Reset() + { + uiMindFlayTimer = 15*IN_MILISECONDS; + uiCurseFatigueTimer = 12*IN_MILISECONDS; + + if (pInstance) + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + Summon(); + uiSummonTimer = 15*IN_MILISECONDS; + + if (pInstance) + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, IN_PROGRESS); + } + + void Summon() + { + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiSummonTimer <= diff) + { + Summon(); + uiSummonTimer = 15*IN_MILISECONDS; + } else uiSummonTimer -= diff; + + if (uiMindFlayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MIND_FLAY); + uiMindFlayTimer = 15*IN_MILISECONDS; + } else uiMindFlayTimer -= diff; + + if (uiCurseFatigueTimer <= diff) + { + //WowWiki say "Curse of Fatigue-Kirk'thir will cast Curse of Fatigue on 2-3 targets periodically." + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + Unit *pTarget_1 = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + + DoCast(pTarget, SPELL_CURSE_OF_FATIGUE); + DoCast(pTarget_1, SPELL_CURSE_OF_FATIGUE); + + uiCurseFatigueTimer = 10*IN_MILISECONDS; + } else uiCurseFatigueTimer -= diff; + + if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10)) + DoCast(me, SPELL_FRENZY, true); + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DONE); + //Achievement: Watch him die + Creature *pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_GASHRA)); + if (!pAdd || !pAdd->isAlive()) + return; + + pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_SILTHIK)); + if (!pAdd || !pAdd->isAlive()) + return; + + pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_NARJIL)); + if (!pAdd || !pAdd->isAlive()) + return; + + pInstance->DoCompleteAchievement(ACHIEV_WATH_HIM_DIE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustSummoned(Creature* summoned) + { + summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); + } +}; + +struct npc_skittering_infectorAI : public ScriptedAI +{ + npc_skittering_infectorAI(Creature *c) : ScriptedAI(c) {} + + void JustDied(Unit* /*killer*/) + { + //The spell is not working propperly + DoCast(me->getVictim(),SPELL_ACID_SPLASH, true); + } + +}; + +struct npc_anub_ar_skirmisherAI : public ScriptedAI +{ + npc_anub_ar_skirmisherAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiChargeTimer; + uint32 uiBackstabTimer; + + void Reset() + { + uiChargeTimer = 11*IN_MILISECONDS; + uiBackstabTimer = 7*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiChargeTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoResetThreat(); + me->AddThreat(pTarget,1.0f); + DoCast(pTarget, SPELL_CHARGE, true); + } + uiChargeTimer = 15*IN_MILISECONDS; + } else uiChargeTimer -= diff; + + if (uiBackstabTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BACKSTAB); + uiBackstabTimer = 12*IN_MILISECONDS; + } else uiBackstabTimer -= diff; + + DoMeleeAttackIfReady(); + + } +}; + +struct npc_anub_ar_shadowcasterAI : public ScriptedAI +{ + npc_anub_ar_shadowcasterAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiShadowBoltTimer; + uint32 uiShadowNovaTimer; + + void Reset() + { + uiShadowBoltTimer = 6*IN_MILISECONDS; + uiShadowNovaTimer = 15*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiShadowBoltTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SHADOW_BOLT, true); + uiShadowBoltTimer = 15*IN_MILISECONDS; + } else uiShadowBoltTimer -= diff; + + if (uiShadowNovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_NOVA, true); + uiShadowNovaTimer = 17*IN_MILISECONDS; + } else uiShadowNovaTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_anub_ar_warriorAI : public ScriptedAI +{ + npc_anub_ar_warriorAI(Creature *c) : ScriptedAI(c){} + + uint32 uiCleaveTimer; + uint32 uiStrikeTimer; + + void Reset() + { + uiCleaveTimer = 11*IN_MILISECONDS; + uiStrikeTimer = 6*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STRIKE, true); + uiStrikeTimer = 15*IN_MILISECONDS; + } else uiStrikeTimer -= diff; + + if (uiCleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE, true); + uiCleaveTimer = 17*IN_MILISECONDS; + } else uiCleaveTimer -= diff; + + DoMeleeAttackIfReady(); + + } + +}; + +struct npc_watcher_gashraAI : public ScriptedAI +{ + npc_watcher_gashraAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_ENRAGE, true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + uiWebWrapTimer = 17*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 15*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_watcher_narjilAI : public ScriptedAI +{ + npc_watcher_narjilAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + uint32 uiBindingWebsTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + uiBindingWebsTimer = 17*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + uiWebWrapTimer = 15*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 11*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + if (uiBindingWebsTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BLINDING_WEBS, true); + uiBindingWebsTimer = 17*IN_MILISECONDS; + } else uiBindingWebsTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_watcher_silthikAI : public ScriptedAI +{ + npc_watcher_silthikAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + uint32 uiPoisonSprayTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + uiPoisonSprayTimer = 15*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + + uiWebWrapTimer = 15*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 15*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + if (uiPoisonSprayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POSION_SPRAY, true); + uiPoisonSprayTimer = 17*IN_MILISECONDS; + } else uiPoisonSprayTimer -= diff; + + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_boss_krik_thir(Creature* pCreature) +{ + return new boss_krik_thirAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_skirmisher (Creature* pCreature) +{ + return new npc_anub_ar_skirmisherAI (pCreature); +} + +CreatureAI* GetAI_npc_skittering_infector (Creature* pCreature) +{ + return new npc_skittering_infectorAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_shadowcaster (Creature* pCreature) +{ + return new npc_anub_ar_shadowcasterAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_warrior (Creature* pCreature) +{ + return new npc_anub_ar_warriorAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_gashra (Creature* pCreature) +{ + return new npc_watcher_gashraAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_narjil (Creature* pCreature) +{ + return new npc_watcher_narjilAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_silthik (Creature* pCreature) +{ + return new npc_watcher_silthikAI (pCreature); +} + +void AddSC_boss_krik_thir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_krik_thir"; + newscript->GetAI = &GetAI_boss_krik_thir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_skittering_infector"; + newscript->GetAI = &GetAI_npc_skittering_infector; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_skirmisher"; + newscript->GetAI = &GetAI_npc_anub_ar_skirmisher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_shadowcaster"; + newscript->GetAI = &GetAI_npc_anub_ar_shadowcaster; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_gashra"; + newscript->GetAI = &GetAI_npc_watcher_gashra; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_warrior"; + newscript->GetAI = &GetAI_npc_anub_ar_warrior; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_silthik"; + newscript->GetAI = &GetAI_npc_watcher_silthik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_narjil"; + newscript->GetAI = &GetAI_npc_watcher_narjil; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp new file mode 100644 index 00000000000..d12dbd604ba --- /dev/null +++ b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +#define MAX_ENCOUNTER 3 + +/* Azjol Nerub encounters: +0 - Krik'thir the Gatewatcher +1 - Hadronox +2 - Anub'arak +*/ + +struct instance_azjol_nerub : public ScriptedInstance +{ + instance_azjol_nerub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiKrikthir; + uint64 uiHadronox; + uint64 uiAnubarak; + uint64 uiWatcherGashra; + uint64 uiWatcherSilthik; + uint64 uiWatcherNarjil; + uint64 uiAnubarakDoor[3]; + + uint64 uiKrikthirDoor; + + uint32 auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&auiEncounter, 0, sizeof(auiEncounter)); + memset(&uiAnubarakDoor, 0, sizeof(uiAnubarakDoor)); + + uiKrikthir = 0; + uiHadronox = 0; + uiAnubarak = 0; + uiWatcherGashra = 0; + uiWatcherSilthik = 0; + uiWatcherNarjil = 0; + uiKrikthirDoor = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 28684: uiKrikthir = pCreature->GetGUID(); break; + case 28921: uiHadronox = pCreature->GetGUID(); break; + case 29120: uiAnubarak = pCreature->GetGUID(); break; + case 28730: uiWatcherGashra = pCreature->GetGUID(); break; + case 28731: uiWatcherSilthik = pCreature->GetGUID(); break; + case 28729: uiWatcherNarjil = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch (pGo->GetEntry()) + { + case 192395: + uiKrikthirDoor = pGo->GetGUID(); + if (auiEncounter[0] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 192396: + uiAnubarakDoor[0] = pGo->GetGUID(); + break; + case 192397: + uiAnubarakDoor[1] = pGo->GetGUID(); + break; + case 192398: + uiAnubarakDoor[2] = pGo->GetGUID(); + break; + } + } + + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_KRIKTHIR_THE_GATEWATCHER: return uiKrikthir; + case DATA_HADRONOX: return uiHadronox; + case DATA_ANUBARAK: return uiAnubarak; + case DATA_WATCHER_GASHRA: return uiWatcherGashra; + case DATA_WATCHER_SILTHIK: return uiWatcherSilthik; + case DATA_WATCHER_NARJIL: return uiWatcherNarjil; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: + auiEncounter[0] = data; + if (data == DONE) + HandleGameObject(uiKrikthirDoor,true); + break; + case DATA_HADRONOX_EVENT: + auiEncounter[1] = data; + break; + case DATA_ANUBARAK_EVENT: + auiEncounter[2] = data; + if (data == IN_PROGRESS) + for (uint8 i = 0; i < 3; ++i) + HandleGameObject(uiAnubarakDoor[i], false); + else if (data == NOT_STARTED || data == DONE) + for (uint8 i = 0; i < 3; ++i) + HandleGameObject(uiAnubarakDoor[i], true); + break; + } + + if (data == DONE) + { + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: return auiEncounter[0]; + case DATA_HADRONOX_EVENT: return auiEncounter[1]; + case DATA_ANUBARAK_EVENT: return auiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "A N " << auiEncounter[0] << " " << auiEncounter[1] << " " + << auiEncounter[2]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0,data1,data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; + + if (dataHead1 == 'A' && dataHead2 == 'N') + { + auiEncounter[0] = data0; + auiEncounter[1] = data1; + auiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (auiEncounter[i] == IN_PROGRESS) + auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_azjol_nerub(Map* pMap) +{ + return new instance_azjol_nerub(pMap); +} + +void AddSC_instance_azjol_nerub() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_azjol_nerub"; + newscript->GetInstanceData = &GetInstanceData_instance_azjol_nerub; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/borean_tundra.cpp b/src/server/scripts/Northrend/borean_tundra.cpp new file mode 100644 index 00000000000..19d82dc9044 --- /dev/null +++ b/src/server/scripts/Northrend/borean_tundra.cpp @@ -0,0 +1,2323 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Borean_Tundra +SD%Complete: 100 +SDComment: Quest support: 11708. Taxi vendors. +SDCategory: Borean Tundra +EndScriptData */ + +/* ContentData +npc_iruk +npc_corastrasza +npc_jenny +npc_sinkhole_kill_credit +npc_khunok_the_behemoth +npc_scourge_prisoner +mob_nerubar_victim +npc_keristrasza +npc_nesingwary_trapper +npc_lurgglbr +npc_nexus_drake_hatchling +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "ScriptedFollowerAI.h" + +/*###### +## npc_sinkhole_kill_credit +######*/ + +enum eSinkhole +{ + SPELL_SET_CART = 46797, + SPELL_EXPLODE_CART = 46799, + SPELL_SUMMON_CART = 46798, + SPELL_SUMMON_WORM = 46800, +}; + +struct npc_sinkhole_kill_creditAI : public ScriptedAI +{ + npc_sinkhole_kill_creditAI(Creature* c) : ScriptedAI(c){} + + uint32 uiPhaseTimer; + uint8 Phase; + uint64 casterGuid; + + void Reset() + { + uiPhaseTimer = 500; + Phase = 0; + casterGuid = 0; + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (Phase) + return; + + if (spell->Id == SPELL_SET_CART && caster->GetTypeId() == TYPEID_PLAYER + && CAST_PLR(caster)->GetQuestStatus(11897) == QUEST_STATUS_INCOMPLETE) + { + Phase = 1; + casterGuid = caster->GetGUID(); + } + } + + void EnterCombat(Unit* /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (!Phase) + return; + + if (uiPhaseTimer <= diff) + { + switch (Phase) + { + case 1: + DoCast(me, SPELL_EXPLODE_CART, true); + DoCast(me, SPELL_SUMMON_CART, true); + if (GameObject* cart = me->FindNearestGameObject(188160,3)) + cart->SetUInt32Value(GAMEOBJECT_FACTION, 14); + uiPhaseTimer = 3000; + Phase = 2; + break; + case 2: + if (GameObject* cart = me->FindNearestGameObject(188160,3)) + cart->UseDoorOrButton(); + DoCast(me, SPELL_EXPLODE_CART, true); + uiPhaseTimer = 3000; + Phase = 3; + break; + case 3: + DoCast(me, SPELL_EXPLODE_CART, true); + uiPhaseTimer = 2000; + Phase = 4; + case 5: + DoCast(me, SPELL_SUMMON_WORM, true); + if (Unit* worm = me->FindNearestCreature(26250, 3)) + { + worm->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + worm->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); + } + uiPhaseTimer = 1000; + Phase = 6; + break; + case 6: + DoCast(me, SPELL_EXPLODE_CART, true); + if (Unit* worm = me->FindNearestCreature(26250, 3)) + { + me->Kill(worm); + worm->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + uiPhaseTimer = 2000; + Phase = 7; + break; + case 7: + DoCast(me, SPELL_EXPLODE_CART, true); + if (Player *caster = Unit::GetPlayer(casterGuid)) + caster->KilledMonster(me->GetCreatureInfo(),me->GetGUID()); + uiPhaseTimer = 5000; + Phase = 8; + break; + case 8: + EnterEvadeMode(); + break; + } + } else uiPhaseTimer -= diff; + + } + +}; + +CreatureAI* GetAI_npc_sinkhole_kill_credit(Creature* pCreature) +{ + return new npc_sinkhole_kill_creditAI(pCreature); +} + +/*###### +## npc_khunok_the_behemoth +######*/ + +struct npc_khunok_the_behemothAI : public ScriptedAI +{ + npc_khunok_the_behemothAI(Creature *c) : ScriptedAI(c) {} + + void MoveInLineOfSight(Unit *who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (who->GetTypeId() != TYPEID_UNIT) + return; + + if (who->GetEntry() == 25861 && me->IsWithinDistInMap(who, 10.0f)) + { + if (Unit *owner = who->GetOwner()) + { + if (owner->GetTypeId() == TYPEID_PLAYER) + { + owner->CastSpell(owner, 46231, true); + CAST_CRE(who)->ForcedDespawn(); + } + } + } + } +}; + +CreatureAI* GetAI_npc_khunok_the_behemoth(Creature* pCreature) +{ + return new npc_khunok_the_behemothAI(pCreature); +} + +/*###### +## npc_keristrasza +######*/ + +enum eKeristrasza +{ + SPELL_TELEPORT_TO_SARAGOSA = 46772 +}; + +#define GOSSIP_HELLO_KERI "I am prepared to face Saragosa!" + +bool GossipHello_npc_keristrasza(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(11957) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KERI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_keristrasza(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_TO_SARAGOSA, true); + } + + return true; +} + +/*###### +## npc_corastrasza +######*/ + +#define GOSSIP_ITEM_C_1 "I... I think so..." + +enum eCorastrasza +{ + SPELL_SUMMON_WYRMREST_SKYTALON = 61240, + SPELL_WYRMREST_SKYTALON_RIDE_PERIODIC = 61244, + + QUEST_ACES_HIGH_DAILY = 13414, + QUEST_ACES_HIGH = 13413 +}; + +bool GossipHello_npc_corastrasza(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_ACES_HIGH) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_ACES_HIGH_DAILY) == QUEST_STATUS_INCOMPLETE) //It's the same dragon for both quests. + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_C_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_corastrasza(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + pPlayer->CastSpell(pPlayer, SPELL_SUMMON_WYRMREST_SKYTALON, true); + pPlayer->CastSpell(pPlayer, SPELL_WYRMREST_SKYTALON_RIDE_PERIODIC, true); + + } + + return true; +} + +/*###### +## npc_iruk +######*/ + +#define GOSSIP_ITEM_I "" + +enum eIruk +{ + QUEST_SPIRITS_WATCH_OVER_US = 11961, + SPELL_CREATURE_TOTEM_OF_ISSLIRUK = 46816, + GOSSIP_TEXT_I = 12585 +}; + +bool GossipHello_npc_iruk(Player* pPlayer, Creature* pCreature) +{ + + if (pPlayer->GetQuestStatus(QUEST_SPIRITS_WATCH_OVER_US) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_I, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_I, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_iruk(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CastSpell(pPlayer, SPELL_CREATURE_TOTEM_OF_ISSLIRUK, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + + } + return true; +} +/*###### +## mob_nerubar_victim +######*/ + +#define WARSONG_PEON 25270 + +const uint32 nerubarVictims[3] = +{ + 45526, 45527, 45514 +}; +struct mob_nerubar_victimAI : public ScriptedAI +{ + mob_nerubar_victimAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void JustDied(Unit* Killer) + { + if (Killer->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(Killer)->GetQuestStatus(11611) == QUEST_STATUS_INCOMPLETE) + { + uint8 uiRand = urand(0,99); + if (uiRand < 25) + { + Killer->CastSpell(me,45532,true); + CAST_PLR(Killer)->KilledMonsterCredit(WARSONG_PEON, 0); + } + else if (uiRand < 75) + Killer->CastSpell(me, nerubarVictims[urand(0,2)], true); + } + } + } +}; +CreatureAI* GetAI_mob_nerubar_victim(Creature *pCreature) +{ + return new mob_nerubar_victimAI (pCreature); +} +/*###### +## npc_scourge_prisoner +######*/ + +enum eScourgePrisoner +{ + GO_SCOURGE_CAGE = 187867 +}; + +struct npc_scourge_prisonerAI : public ScriptedAI +{ + npc_scourge_prisonerAI(Creature* pCreature) : ScriptedAI (pCreature){} + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + + if (GameObject* pGO = me->FindNearestGameObject(GO_SCOURGE_CAGE,5.0f)) + if (pGO->GetGoState() == GO_STATE_ACTIVE) + pGO->SetGoState(GO_STATE_READY); + } + +}; +CreatureAI* GetAI_npc_scourge_prisoner(Creature* pCreature) +{ + return new npc_scourge_prisonerAI(pCreature); +} + +/*###### +## npc_jenny +######*/ +enum eJenny +{ + QUEST_LOADER_UP = 11881, + + NPC_FEZZIX_GEARTWIST = 25849, + NPC_JENNY = 25969, + + SPELL_GIVE_JENNY_CREDIT = 46358, + SPELL_CRATES_CARRIED = 46340, + SPELL_DROP_CRATE = 46342 +}; + +struct npc_jennyAI : public ScriptedAI +{ + npc_jennyAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + bool setCrateNumber; + + void Reset() + { + if (!setCrateNumber) + setCrateNumber = true; + + me->SetReactState(REACT_PASSIVE); + + switch (CAST_PLR(me->GetOwner())->GetTeamId()) + { + case TEAM_ALLIANCE: + me->setFaction(FACTION_ESCORT_A_NEUTRAL_ACTIVE); + break; + default: + case TEAM_HORDE: + me->setFaction(FACTION_ESCORT_H_NEUTRAL_ACTIVE); + break; + } + } + + void DamageTaken(Unit* /*pDone_by*/, uint32& /*uiDamage*/) + { + DoCast(me, SPELL_DROP_CRATE, true); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (setCrateNumber) + { + me->AddAura(SPELL_CRATES_CARRIED,me); + setCrateNumber = false; + } + + if (!setCrateNumber && !me->HasAura(SPELL_CRATES_CARRIED)) + me->DisappearAndDie(); + + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_npc_jenny(Creature *pCreature) +{ + return new npc_jennyAI (pCreature); +} + +/*###### +## npc_fezzix_geartwist +######*/ + +struct npc_fezzix_geartwistAI : public ScriptedAI +{ + npc_fezzix_geartwistAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + void MoveInLineOfSight(Unit* pWho) + { + ScriptedAI::MoveInLineOfSight(pWho); + + if (pWho->GetTypeId() != TYPEID_UNIT) + return; + + if (pWho->GetEntry() == NPC_JENNY && me->IsWithinDistInMap(pWho, 10.0f)) + { + if (Unit* pOwner = pWho->GetOwner()) + { + if (pOwner->GetTypeId() == TYPEID_PLAYER) + { + if (pWho->HasAura(SPELL_CRATES_CARRIED)) + { + pOwner->CastSpell(pOwner, SPELL_GIVE_JENNY_CREDIT, true); // Maybe is not working. + CAST_PLR(pOwner)->CompleteQuest(QUEST_LOADER_UP); + CAST_CRE(pWho)->DisappearAndDie(); + } + } + } + } + } +}; + +CreatureAI* GetAI_npc_fezzix_geartwist(Creature* pCreature) +{ + return new npc_fezzix_geartwistAI(pCreature); +} + +/*###### +## npc_nesingwary_trapper +######*/ + +enum eNesingwaryTrapper +{ + GO_HIGH_QUALITY_FUR = 187983, + + GO_CARIBOU_TRAP_1 = 187982, + GO_CARIBOU_TRAP_2 = 187995, + GO_CARIBOU_TRAP_3 = 187996, + GO_CARIBOU_TRAP_4 = 187997, + GO_CARIBOU_TRAP_5 = 187998, + GO_CARIBOU_TRAP_6 = 187999, + GO_CARIBOU_TRAP_7 = 188000, + GO_CARIBOU_TRAP_8 = 188001, + GO_CARIBOU_TRAP_9 = 188002, + GO_CARIBOU_TRAP_10 = 188003, + GO_CARIBOU_TRAP_11 = 188004, + GO_CARIBOU_TRAP_12 = 188005, + GO_CARIBOU_TRAP_13 = 188006, + GO_CARIBOU_TRAP_14 = 188007, + GO_CARIBOU_TRAP_15 = 188008, + + SPELL_TRAPPED = 46104, +}; + +#define CaribouTrapsNum 15 +const uint32 CaribouTraps[CaribouTrapsNum] = +{ + GO_CARIBOU_TRAP_1, GO_CARIBOU_TRAP_2, GO_CARIBOU_TRAP_3, GO_CARIBOU_TRAP_4, GO_CARIBOU_TRAP_5, + GO_CARIBOU_TRAP_6, GO_CARIBOU_TRAP_7, GO_CARIBOU_TRAP_8, GO_CARIBOU_TRAP_9, GO_CARIBOU_TRAP_10, + GO_CARIBOU_TRAP_11, GO_CARIBOU_TRAP_12, GO_CARIBOU_TRAP_13, GO_CARIBOU_TRAP_14, GO_CARIBOU_TRAP_15, +}; +//#define SAY_NESINGWARY_1 -1571008 + +struct npc_nesingwary_trapperAI : public ScriptedAI +{ + npc_nesingwary_trapperAI(Creature *c) : ScriptedAI(c) { c->SetVisibility(VISIBILITY_OFF); } + + uint64 go_caribouGUID; + uint8 Phase; + uint32 uiPhaseTimer; + + void Reset() + { + me->SetVisibility(VISIBILITY_OFF); + uiPhaseTimer = 2500; + Phase = 1; + go_caribouGUID = 0; + } + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void JustDied(Unit * /*who*/) + { + if (GameObject *go_caribou = me->GetMap()->GetGameObject(go_caribouGUID)) + go_caribou->SetLootState(GO_JUST_DEACTIVATED); + + if (TempSummon *summon = me->ToTempSummon()) + if (summon->isSummon()) + if (Unit *pTemp = summon->GetSummoner()) + if (pTemp->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(pTemp)->KilledMonsterCredit(me->GetEntry(),0); + + if (GameObject *go_caribou = me->GetMap()->GetGameObject(go_caribouGUID)) + go_caribou->SetGoState(GO_STATE_READY); + } + + void UpdateAI(const uint32 diff) + { + if (uiPhaseTimer <= diff) + { + switch (Phase) + { + case 1: + me->SetVisibility(VISIBILITY_ON); + uiPhaseTimer = 2000; + Phase = 2; + break; + + case 2: + if (GameObject *go_fur = me->FindNearestGameObject(GO_HIGH_QUALITY_FUR, 11.0f)) + me->GetMotionMaster()->MovePoint(0, go_fur->GetPositionX(), go_fur->GetPositionY(), go_fur->GetPositionZ()); + uiPhaseTimer = 1500; + Phase = 3; + break; + case 3: + //DoScriptText(SAY_NESINGWARY_1, me); + uiPhaseTimer = 2000; + Phase = 4; + break; + case 4: + me->HandleEmoteCommand(EMOTE_ONESHOT_LOOT); + uiPhaseTimer = 1000; + Phase = 5; + break; + case 5: + me->HandleEmoteCommand(EMOTE_ONESHOT_NONE); + uiPhaseTimer = 500; + Phase = 6; + break; + case 6: + if (GameObject *go_fur = me->FindNearestGameObject(GO_HIGH_QUALITY_FUR, 11.0f)) + go_fur->Delete(); + uiPhaseTimer = 500; + Phase = 7; + break; + + case 7: + { + GameObject *go_caribou = NULL; + for (uint8 i = 0; i < CaribouTrapsNum; ++i) + { + go_caribou = me->FindNearestGameObject(CaribouTraps[i], 5.0f); + if (go_caribou) + { + go_caribou->SetGoState(GO_STATE_ACTIVE); + go_caribouGUID = go_caribou->GetGUID(); + break; + } + } + Phase = 8; + uiPhaseTimer = 1000; + } + break; + case 8: + DoCast(me, SPELL_TRAPPED, true); + Phase = 0; + break; + } + } else uiPhaseTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_nesingwary_trapper(Creature *pCreature) +{ + return new npc_nesingwary_trapperAI (pCreature); +} + +/*###### +## npc_lurgglbr +######*/ + +enum eLurgglbr +{ + QUEST_ESCAPE_WINTERFIN_CAVERNS = 11570, + + GO_CAGE = 187369, + + FACTION_ESCORTEE_A = 774, + FACTION_ESCORTEE_H = 775, +}; + +/*#define SAY_WP_1_LUR_START -1571004 +#define SAY_WP_1_LUR_END -1571005 +#define SAY_WP_41_LUR_START -1571006 +#define SAY_WP_41_LUR_END -1571007*/ + +struct npc_lurgglbrAI : public npc_escortAI +{ + npc_lurgglbrAI(Creature* pCreature) : npc_escortAI(pCreature){} + + uint32 IntroTimer; + uint32 IntroPhase; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + IntroTimer = 0; + IntroPhase = 0; + } + } + + void WaypointReached(uint32 i) + { + switch (i) + { + case 0: + IntroPhase = 1; + IntroTimer = 2000; + break; + case 41: + IntroPhase = 4; + IntroTimer = 2000; + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (IntroPhase) + { + if (IntroTimer <= diff) + { + switch(IntroPhase) + { + case 1: + //DoScriptText(SAY_WP_1_LUR_START,me); + IntroPhase = 2; + IntroTimer = 7500; + break; + case 2: + //DoScriptText(SAY_WP_1_LUR_END,me); + IntroPhase = 3; + IntroTimer = 7500; + break; + case 3: + me->SetReactState(REACT_AGGRESSIVE); + IntroPhase = 0; + IntroTimer = 0; + break; + case 4: + //DoScriptText(SAY_WP_41_LUR_START,me); + IntroPhase = 5; + IntroTimer = 8000; + break; + case 5: + //DoScriptText(SAY_WP_41_LUR_END,me); + IntroPhase = 6; + IntroTimer = 2500; + break; + + case 6: + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->AreaExploredOrEventHappens(QUEST_ESCAPE_WINTERFIN_CAVERNS); + IntroPhase = 7; + IntroTimer = 2500; + break; + + case 7: + me->ForcedDespawn(); + IntroPhase = 0; + IntroTimer = 0; + break; + } + } else IntroTimer -= diff; + } + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_npc_lurgglbr(Creature* pCreature) +{ + return new npc_lurgglbrAI(pCreature); +} + +bool QuestAccept_npc_lurgglbr(Player* pPlayer, Creature* pCreature, Quest const *pQuest) +{ + if (pQuest->GetQuestId() == QUEST_ESCAPE_WINTERFIN_CAVERNS) + { + if (GameObject* pGo = pCreature->FindNearestGameObject(GO_CAGE, 5.0f)) + { + pGo->SetRespawnTime(0); + pGo->SetGoType(GAMEOBJECT_TYPE_BUTTON); + pGo->UseDoorOrButton(20); + } + + if (npc_escortAI* pEscortAI = CAST_AI(npc_lurgglbrAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + + switch (pPlayer->GetTeam()) + { + case ALLIANCE: + pCreature->setFaction(FACTION_ESCORTEE_A); + break; + default: + case HORDE: + pCreature->setFaction(FACTION_ESCORTEE_H); + break; + } + + return true; + } + return false; +} + +/*###### +## npc_nexus_drake_hatchling +######*/ + +enum eNexusDrakeHatchling +{ + SPELL_DRAKE_HARPOON = 46607, + SPELL_RED_DRAGONBLOOD = 46620, + SPELL_DRAKE_HATCHLING_SUBDUED = 46691, + SPELL_SUBDUED = 46675, + + NPC_RAELORASZ = 26117, + + QUEST_DRAKE_HUNT = 11919, + QUEST_DRAKE_HUNT_D = 11940 +}; + +struct npc_nexus_drake_hatchlingAI : public FollowerAI //The spell who makes the npc follow the player is missing, also we can use FollowerAI! +{ + npc_nexus_drake_hatchlingAI(Creature *c) : FollowerAI(c) {} + + uint64 HarpoonerGUID; + bool WithRedDragonBlood; + + void Reset() + { + WithRedDragonBlood = false; + HarpoonerGUID = 0; + } + + void EnterCombat(Unit* pWho) + { + if (me->canAttack(pWho)) + AttackStart(pWho); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_DRAKE_HARPOON && caster->GetTypeId() == TYPEID_PLAYER) + { + HarpoonerGUID = caster->GetGUID(); + DoCast(me, SPELL_RED_DRAGONBLOOD, true); + } + WithRedDragonBlood = true; + } + + void MoveInLineOfSight(Unit *pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (!HarpoonerGUID) + return; + + if (me->HasAura(SPELL_SUBDUED) && pWho->GetEntry() == NPC_RAELORASZ) + { + if (me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) + { + if (Player *pHarpooner = Unit::GetPlayer(HarpoonerGUID)) + { + pHarpooner->KilledMonsterCredit(26175,0); + pHarpooner->RemoveAura(SPELL_DRAKE_HATCHLING_SUBDUED); + SetFollowComplete(); + HarpoonerGUID = 0; + me->DisappearAndDie(); + } + } + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (WithRedDragonBlood && HarpoonerGUID && !me->HasAura(SPELL_RED_DRAGONBLOOD)) + { + if (Player *pHarpooner = Unit::GetPlayer(HarpoonerGUID)) + { + EnterEvadeMode(); + StartFollow(pHarpooner, 35, NULL); + + DoCast(me, SPELL_SUBDUED, true); + pHarpooner->CastSpell(pHarpooner, SPELL_DRAKE_HATCHLING_SUBDUED, true); + + me->AttackStop(); + WithRedDragonBlood = false; + } + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_nexus_drake_hatchling(Creature* pCreature) +{ + return new npc_nexus_drake_hatchlingAI(pCreature); +} + +/*###### +## npc_thassarian +######*/ + +enum eThassarian +{ + QUEST_LAST_RITES = 12019, + + SPELL_TRANSFORM_VALANAR = 46753, + SPELL_STUN = 46957, + SPELL_SHADOW_BOLT = 15537, + + NPC_IMAGE_LICH_KING = 26203, + NPC_COUNSELOR_TALBOT = 25301, + NPC_PRINCE_VALANAR = 28189, + NPC_GENERAL_ARLOS = 25250, + NPC_LERYSSA = 25251, + + SAY_TALBOT_1 = -1571004, + SAY_LICH_1 = -1571005, + SAY_TALBOT_2 = -1571006, + SAY_THASSARIAN_1 = -1571007, + SAY_THASSARIAN_2 = -1571008, + SAY_LICH_2 = -1571009, + SAY_THASSARIAN_3 = -1571010, + SAY_TALBOT_3 = -1571011, + SAY_LICH_3 = -1571012, + SAY_TALBOT_4 = -1571013, + SAY_ARLOS_1 = -1571014, + SAY_ARLOS_2 = -1571015, + SAY_LERYSSA_1 = -1571016, + SAY_THASSARIAN_4 = -1571017, + SAY_LERYSSA_2 = -1571018, + SAY_THASSARIAN_5 = -1571019, + SAY_LERYSSA_3 = -1571020, + SAY_THASSARIAN_6 = -1571021, + SAY_LERYSSA_4 = -1571022, + SAY_THASSARIAN_7 = -1571023, +}; + +#define GOSSIP_ITEM_T "Let's do this, Thassarian. It's now or never." + +struct npc_thassarianAI : public npc_escortAI +{ + npc_thassarianAI(Creature* pCreature) : npc_escortAI(pCreature) + { + } + + uint64 uiArthas; + uint64 uiTalbot; + uint64 uiLeryssa; + uint64 uiArlos; + + bool bArthasInPosition; + bool bArlosInPosition; + bool bLeryssaInPosition; + bool bTalbotInPosition; + + uint32 uiPhase; + uint32 uiPhaseTimer; + + void Reset() + { + me->RestoreFaction(); + me->RemoveStandFlags(UNIT_STAND_STATE_SIT); + + uiArthas = 0; + uiTalbot = 0; + uiLeryssa = 0; + uiArlos = 0; + + bArthasInPosition = false; + bArlosInPosition = false; + bLeryssaInPosition = false; + bTalbotInPosition = false; + + uiPhase = 0; + uiPhaseTimer = 0; + } + + void WaypointReached(uint32 uiPointId) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(uiPointId) + { + case 3: + SetEscortPaused(true); + if (Creature *pArthas = me->SummonCreature(NPC_IMAGE_LICH_KING, 3730.313, 3518.689, 473.324, 1.562, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) + { + uiArthas = pArthas->GetGUID(); + pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pArthas->SetReactState(REACT_PASSIVE); + pArthas->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pArthas->GetMotionMaster()->MovePoint(0, 3737.374756,3564.841309,477.433014); + } + if (Creature *pTalbot = me->SummonCreature(NPC_COUNSELOR_TALBOT, 3747.23, 3614.936, 473.321, 4.462012, TEMPSUMMON_CORPSE_TIMED_DESPAWN,120000)) + { + uiTalbot = pTalbot->GetGUID(); + pTalbot->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTalbot->GetMotionMaster()->MovePoint(0, 3738.000977,3568.882080,477.433014); + } + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + + case 4: + SetEscortPaused(true); + uiPhase = 7; + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (bArthasInPosition && bTalbotInPosition) + { + uiPhase = 1; + bArthasInPosition = false; + bTalbotInPosition = false; + } + + if (bArlosInPosition && bLeryssaInPosition) + { + bArlosInPosition = false; + bLeryssaInPosition = false; + DoScriptText(SAY_THASSARIAN_1, me); + SetEscortPaused(false); + } + + if (uiPhaseTimer <= uiDiff) + { + Creature* pTalbot = me->GetCreature(*me, uiTalbot); + Creature* pArthas = me->GetCreature(*me, uiArthas); + switch (uiPhase) + { + case 1: + if (pTalbot) + pTalbot->SetStandState(UNIT_STAND_STATE_KNEEL); + uiPhaseTimer = 3000; + ++uiPhase; + break; + + case 2: + if (pTalbot) + { + pTalbot->UpdateEntry(NPC_PRINCE_VALANAR,ALLIANCE); + pTalbot->setFaction(14); + pTalbot->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTalbot->SetReactState(REACT_PASSIVE); + } + uiPhaseTimer = 5000; + ++uiPhase; + break; + + case 3: + if (pTalbot) + DoScriptText(SAY_TALBOT_1, pTalbot); + uiPhaseTimer = 5000; + ++uiPhase; + break; + + case 4: + if (pArthas) + DoScriptText(SAY_LICH_1, pArthas); + uiPhaseTimer = 5000; + ++uiPhase; + break; + + case 5: + if (pTalbot) + DoScriptText(SAY_TALBOT_2, pTalbot); + uiPhaseTimer = 5000; + ++uiPhase; + break; + + case 6: + if (Creature* pArlos = me->SummonCreature(NPC_GENERAL_ARLOS, 3745.527100, 3615.655029, 473.321533, 4.447805, TEMPSUMMON_CORPSE_TIMED_DESPAWN,120000)) + { + uiArlos = pArlos->GetGUID(); + pArlos->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pArlos->GetMotionMaster()->MovePoint(0, 3735.570068, 3572.419922, 477.441010); + } + if (Creature *pLeryssa = me->SummonCreature(NPC_LERYSSA, 3749.654541, 3614.959717, 473.323486, 4.524959, TEMPSUMMON_CORPSE_TIMED_DESPAWN,120000)) + { + uiLeryssa = pLeryssa->GetGUID(); + pLeryssa->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pLeryssa->SetReactState(REACT_PASSIVE); + pLeryssa->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pLeryssa->GetMotionMaster()->MovePoint(0, 3741.969971, 3571.439941, 477.441010); + } + uiPhaseTimer = 2000; + uiPhase = 0; + break; + + case 7: + DoScriptText(SAY_THASSARIAN_2, me); + uiPhaseTimer = 5000; + ++uiPhase; + break; + + case 8: + if (pArthas && pTalbot) + { + pArthas->SetInFront(me); //The client doesen't update with the new orientation :l + pTalbot->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_LICH_2, pArthas); + } + uiPhaseTimer = 5000; + uiPhase = 9; + break; + + case 9: + DoScriptText(SAY_THASSARIAN_3, me); + uiPhaseTimer = 5000; + uiPhase = 10; + break; + + case 10: + if (pTalbot) + DoScriptText(SAY_TALBOT_3, pTalbot); + uiPhaseTimer = 5000; + uiPhase = 11; + break; + + case 11: + if (pArthas) + DoScriptText(SAY_LICH_3, pArthas); + uiPhaseTimer = 5000; + uiPhase = 12; + break; + + case 12: + if (pTalbot) + DoScriptText(SAY_TALBOT_4, pTalbot); + uiPhaseTimer = 2000; + uiPhase = 13; + break; + + case 13: + if (pArthas) + pArthas->RemoveFromWorld(); + ++uiPhase; + break; + + case 14: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pTalbot) + { + pTalbot->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTalbot->SetReactState(REACT_AGGRESSIVE); + pTalbot->CastSpell(me, SPELL_SHADOW_BOLT, false); + } + uiPhaseTimer = 1500; + ++uiPhase; + break; + + case 15: + me->SetReactState(REACT_AGGRESSIVE); + AttackStart(pTalbot); + uiPhase = 0; + break; + + case 16: + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + uiPhaseTimer = 20000; + ++uiPhase; + break; + + case 17: + if (Creature* pLeryssa = me->GetCreature(*me, uiLeryssa)) + pLeryssa->RemoveFromWorld(); + if (Creature* pArlos= me->GetCreature(*me, uiArlos)) + pArlos->RemoveFromWorld(); + if (pTalbot) + pTalbot->RemoveFromWorld(); + me->RemoveStandFlags(UNIT_STAND_STATE_SIT); + SetEscortPaused(false); + uiPhaseTimer = 0; + uiPhase = 0; + } + } else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (Creature* pTalbot = me->GetCreature(*me, uiTalbot)) + pTalbot->RemoveFromWorld(); + + if (Creature* pLeryssa = me->GetCreature(*me, uiLeryssa)) + pLeryssa->RemoveFromWorld(); + + if (Creature* pArlos = me->GetCreature(*me, uiArlos)) + pArlos->RemoveFromWorld(); + + if (Creature* pArthas = me->GetCreature(*me, uiArthas)) + pArthas->RemoveFromWorld(); + } +}; + +bool GossipHello_npc_thassarian(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_LAST_RITES) == QUEST_STATUS_INCOMPLETE && pCreature->GetAreaId() == 4125) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_T, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_thassarian(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(200.0f); + break; + } + return true; +} + +CreatureAI* GetAI_npc_thassarian(Creature *pCreature) +{ + return new npc_thassarianAI (pCreature); +} + +/*###### +## npc_image_lich_king +######*/ + +struct npc_image_lich_kingAI : public ScriptedAI +{ + npc_image_lich_kingAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + void Reset() + { + me->RestoreFaction(); + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (me->isSummon()) + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + CAST_AI(npc_thassarianAI,CAST_CRE(pSummoner)->AI())->bArthasInPosition = true; + } +}; + +CreatureAI* GetAI_npc_image_lich_king(Creature* pCreature) +{ + return new npc_image_lich_kingAI (pCreature); +} + +/*###### +## npc_general_arlos +######*/ + +struct npc_general_arlosAI : public ScriptedAI +{ + npc_general_arlosAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + me->addUnitState(UNIT_STAT_STUNNED); + me->CastSpell(me, SPELL_STUN, true); + if (me->isSummon()) + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + CAST_AI(npc_thassarianAI,CAST_CRE(pSummoner)->AI())->bArlosInPosition = true; + } +}; + +CreatureAI* GetAI_npc_general_arlos(Creature *pCreature) +{ + return new npc_general_arlosAI(pCreature); +} + +/*###### +## npc_counselor_talbot +######*/ + +enum eCounselorTalbot +{ + SPELL_DEFLECTION = 51009, + SPELL_SOUL_BLAST = 50992, +}; + +struct npc_counselor_talbotAI : public ScriptedAI +{ + npc_counselor_talbotAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pCreature->RestoreFaction(); + } + + uint64 LeryssaGUID; + uint64 ArlosGUID; + + bool bCheck; + + uint32 uiShadowBoltTimer; + uint32 uiDeflectionTimer; + uint32 uiSoulBlastTimer; + + void Reset() + { + LeryssaGUID = 0; + ArlosGUID = 0; + bCheck = false; + uiShadowBoltTimer = urand(5000,12000); + uiDeflectionTimer = urand(20000,25000); + uiSoulBlastTimer = urand (12000,18000); + } + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (me->isSummon()) + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + CAST_AI(npc_thassarianAI,CAST_CRE(pSummoner)->AI())->bTalbotInPosition = true; + } + + void UpdateAI(const uint32 uiDiff) + { + if (bCheck) + { + if (Creature *pLeryssa = me->FindNearestCreature(NPC_LERYSSA, 50.0f, true)) + LeryssaGUID = pLeryssa->GetGUID(); + if (Creature *pArlos = me->FindNearestCreature(NPC_GENERAL_ARLOS, 50.0f, true)) + ArlosGUID = pArlos->GetGUID(); + bCheck = false; + } + + if (!UpdateVictim()) + return; + + if (me->GetAreaId() == 4125) + { + if (uiShadowBoltTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + uiShadowBoltTimer = urand(5000,12000); + } else uiShadowBoltTimer -= uiDiff; + + if (uiDeflectionTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_DEFLECTION); + uiDeflectionTimer = urand(20000,25000); + } else uiDeflectionTimer -= uiDiff; + + if (uiSoulBlastTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SOUL_BLAST); + uiSoulBlastTimer = urand (12000,18000); + } else uiSoulBlastTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* pKiller) + { + if (!LeryssaGUID || !ArlosGUID) + return; + + Creature *pLeryssa = Unit::GetCreature(*me, LeryssaGUID); + Creature *pArlos = Unit::GetCreature(*me, ArlosGUID); + if (!pLeryssa || !pArlos) + return; + + DoScriptText(SAY_ARLOS_1, pArlos); + DoScriptText(SAY_ARLOS_2, pArlos); + DoScriptText(SAY_LERYSSA_1, pLeryssa); + pArlos->Kill(pArlos, false); + pLeryssa->RemoveAura(SPELL_STUN); + pLeryssa->clearUnitState(UNIT_STAT_STUNNED); + pLeryssa->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pLeryssa->GetMotionMaster()->MovePoint(0,3722.114502, 3564.201660, 477.441437); + + if (pKiller->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(pKiller)->RewardPlayerAndGroupAtEvent(NPC_PRINCE_VALANAR, 0); + } +}; + +CreatureAI* GetAI_npc_counselor_talbot(Creature* pCreature) +{ + return new npc_counselor_talbotAI (pCreature); +} + +/*###### +## npc_leryssa +######*/ + +struct npc_leryssaAI : public ScriptedAI +{ + npc_leryssaAI(Creature* pCreature) : ScriptedAI(pCreature) + { + bDone = false; + Phase = 0; + uiPhaseTimer = 0; + + pCreature->RemoveStandFlags(UNIT_STAND_STATE_SIT); + } + + bool bDone; + + uint32 Phase; + uint32 uiPhaseTimer; + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (!bDone) + { + if (Creature* pTalbot = me->FindNearestCreature(NPC_PRINCE_VALANAR, 50.0f, true)) + CAST_AI(npc_counselor_talbotAI, pTalbot->AI())->bCheck = true; + + me->addUnitState(UNIT_STAT_STUNNED); + me->CastSpell(me, SPELL_STUN, true); + + if (me->isSummon()) + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + CAST_AI(npc_thassarianAI,CAST_CRE(pSummoner)->AI())->bLeryssaInPosition = true; + bDone = true; + } + else + { + me->SetStandState(UNIT_STAND_STATE_SIT); + if (me->isSummon()) + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + pSummoner->SetStandState(UNIT_STAND_STATE_SIT); + uiPhaseTimer = 1500; + Phase = 1; + } + } + + void UpdateAI(const uint32 uiDiff) + { + ScriptedAI::UpdateAI(uiDiff); + + if (uiPhaseTimer <= uiDiff) + { + switch (Phase) + { + case 1: + if (me->isSummon()) + if (Unit* pThassarian = CAST_SUM(me)->GetSummoner()) + DoScriptText(SAY_THASSARIAN_4, pThassarian); + uiPhaseTimer = 5000; + ++Phase; + break; + case 2: + DoScriptText(SAY_LERYSSA_2, me); + uiPhaseTimer = 5000; + ++Phase; + break; + case 3: + if (me->isSummon()) + if (Unit* pThassarian = CAST_SUM(me)->GetSummoner()) + DoScriptText(SAY_THASSARIAN_5, pThassarian); + uiPhaseTimer = 5000; + ++Phase; + break; + case 4: + DoScriptText(SAY_LERYSSA_3, me); + uiPhaseTimer = 5000; + ++Phase; + break; + case 5: + if (me->isSummon()) + if (Unit* pThassarian = CAST_SUM(me)->GetSummoner()) + DoScriptText(SAY_THASSARIAN_6, pThassarian); + uiPhaseTimer = 5000; + ++Phase; + break; + + case 6: + DoScriptText(SAY_LERYSSA_4, me); + uiPhaseTimer = 5000; + ++Phase; + break; + case 7: + if (me->isSummon()) + if (Unit* pThassarian = CAST_SUM(me)->GetSummoner()) + { + DoScriptText(SAY_THASSARIAN_7, pThassarian); + CAST_AI(npc_thassarianAI,CAST_CRE(pThassarian)->AI())->uiPhase = 16; + } + uiPhaseTimer = 5000; + Phase = 0; + break; + } + } else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_leryssa(Creature *pCreature) +{ + return new npc_leryssaAI (pCreature); +} + +/*###### +## npc_beryl_sorcerer +######*/ + +enum eBerylSorcerer +{ + NPC_CAPTURED_BERLY_SORCERER = 25474, + NPC_LIBRARIAN_DONATHAN = 25262, + + SPELL_ARCANE_CHAINS = 45611, + SPELL_COSMETIC_CHAINS = 54324, + SPELL_COSMETIC_ENSLAVE_CHAINS_SELF = 45631 +}; + +struct npc_beryl_sorcererAI : public FollowerAI +{ + npc_beryl_sorcererAI(Creature* pCreature) : FollowerAI(pCreature) {} + + bool bEnslaved; + + void Reset() + { + me->SetReactState(REACT_AGGRESSIVE); + bEnslaved = false; + } + + void EnterCombat(Unit* pWho) + { + if (me->canAttack(pWho)) + AttackStart(pWho); + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_ARCANE_CHAINS && pCaster->GetTypeId() == TYPEID_PLAYER && me->GetHealth()*100 / me->GetMaxHealth() <= 50 && !bEnslaved) + { + EnterEvadeMode(); //We make sure that the npc is not attacking the player! + me->SetReactState(REACT_PASSIVE); + StartFollow(CAST_PLR(pCaster), NULL, NULL); + me->UpdateEntry(NPC_CAPTURED_BERLY_SORCERER, TEAM_NEUTRAL); + DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF, true); + CAST_PLR(pCaster)->KilledMonsterCredit(NPC_CAPTURED_BERLY_SORCERER, 0); + bEnslaved = true; + } + } + + void MoveInLineOfSight(Unit* pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (pWho->GetEntry() == NPC_LIBRARIAN_DONATHAN && me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) + { + SetFollowComplete(); + me->DisappearAndDie(); + } + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_beryl_sorcerer(Creature* pCreature) +{ + return new npc_beryl_sorcererAI(pCreature); +} + +/*###### +## npc_imprisoned_beryl_sorcerer +######*/ + +enum eImprisionedBerylSorcerer +{ + SPELL_NEURAL_NEEDLE = 45634, + + NPC_IMPRISONED_BERYL_SORCERER = 25478, + + SAY_IMPRISIONED_BERYL_1 = -1571024, + SAY_IMPRISIONED_BERYL_2 = -1571025, + SAY_IMPRISIONED_BERYL_3 = -1571026, + SAY_IMPRISIONED_BERYL_4 = -1571027, + SAY_IMPRISIONED_BERYL_5 = -1571028, + SAY_IMPRISIONED_BERYL_6 = -1571029, + SAY_IMPRISIONED_BERYL_7 = -1571030, +}; + +struct npc_imprisoned_beryl_sorcererAI : public ScriptedAI +{ + npc_imprisoned_beryl_sorcererAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint64 CasterGUID; + + uint32 uiStep; + uint32 uiPhase; + + void Reset() + { + uiStep = 1; + uiPhase = 0; + CasterGUID = NULL; + } + + void EnterCombat(Unit* /*pWho*/) + { + } + + void SpellHit(Unit* pUnit, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_NEURAL_NEEDLE && pUnit->GetTypeId() == TYPEID_PLAYER) + { + ++uiPhase; + CasterGUID = pUnit->GetGUID(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + ScriptedAI::UpdateAI(uiDiff); + + if (!me->HasAura(SPELL_COSMETIC_ENSLAVE_CHAINS_SELF)) + DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF); + + if (me->GetReactState() != REACT_PASSIVE) + me->SetReactState(REACT_PASSIVE); + + switch (uiPhase) + { + case 1: + if (uiStep == 1) + { + DoScriptText(SAY_IMPRISIONED_BERYL_1, me); + uiStep = 2; + } + break; + + case 2: + if (uiStep == 2) + { + DoScriptText(SAY_IMPRISIONED_BERYL_2, me); + uiStep = 3; + } + break; + + case 3: + if (uiStep == 3) + { + DoScriptText(SAY_IMPRISIONED_BERYL_3, me); + uiStep = 4; + } + break; + + case 4: + if (uiStep == 4) + { + DoScriptText(SAY_IMPRISIONED_BERYL_4, me); + uiStep = 5; + } + break; + + case 5: + if (uiStep == 5) + { + if (Player *pCaster = Unit::GetPlayer(CasterGUID)) + { + DoScriptText(SAY_IMPRISIONED_BERYL_5, me); + pCaster->KilledMonsterCredit(25478,0); + uiStep = 6; + } + } + break; + + case 6: + if (uiStep == 6) + { + DoScriptText(SAY_IMPRISIONED_BERYL_6, me); + uiStep = 7; + } + break; + + case 7: + if (uiStep == 7) + { + DoScriptText(SAY_IMPRISIONED_BERYL_7, me); + uiStep = 1; + uiPhase = 0; + } + break; + } + } +}; + +CreatureAI* GetAI_npc_imprisoned_beryl_sorcerer(Creature* pCreature) +{ + return new npc_imprisoned_beryl_sorcererAI(pCreature); +} + +/*###### +## npc_mootoo_the_younger +######*/ +enum Script_Texts_Mootoo_the_Younger +{ + SAY_1 =-1750040, + SAY_2 =-1750041, + SAY_3 =-1750042, + SAY_4 =-1750043, + SAY_5 =-1750044 +}; +enum Mootoo_the_Younger_Entries +{ + NPC_MOOTOO_THE_YOUNGER =25504, + QUEST_ESCAPING_THE_MIST =11664 +}; +bool QuestAccept_npc_mootoo_the_younger(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_ESCAPING_THE_MIST) + { + switch (pPlayer->GetTeam()) + { + case ALLIANCE: + pCreature->setFaction(FACTION_ESCORTEE_A); + break; + case HORDE: + pCreature->setFaction(FACTION_ESCORTEE_H); + break; + } + DoScriptText(SAY_1, pCreature); + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + } + return true; +} +struct npc_mootoo_the_youngerAI : public npc_escortAI +{ + npc_mootoo_the_youngerAI(Creature *c) : npc_escortAI(c) {} + + void Reset() + { + SetDespawnAtFar(false); + } + + void JustDied(Unit* /*killer*/) + { + if (Player* pPlayer=GetPlayerForEscort()) + pPlayer->FailQuest(QUEST_ESCAPING_THE_MIST); + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 10: + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + DoScriptText(SAY_2, me); + break; + case 12: + DoScriptText(SAY_3, me); + me->HandleEmoteCommand(EMOTE_ONESHOT_LOOT); + break; + case 16: + DoScriptText(SAY_4, me); + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + break; + case 20: + me->SetPhaseMask(1,true); + DoScriptText(SAY_5, me); + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_ESCAPING_THE_MIST, me); + SetRun(true); + break; + } + } +}; +CreatureAI* GetAI_npc_mootoo_the_younger(Creature* pCreature) +{ + return new npc_mootoo_the_youngerAI(pCreature); +} + +/*###### +## npc_bonker_togglevolt +######*/ + +enum Bonker_Togglevolt_Entries +{ + NPC_BONKER_TOGGLEVOLT =25589, + QUEST_GET_ME_OUTA_HERE =11673 +}; +enum Script_Texts_Bonker_Togglevolt +{ + SAY_bonker_1 =-1700002, + SAY_bonker_2 =-1700003 +}; + +bool QuestAccept_npc_bonker_togglevolt(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_GET_ME_OUTA_HERE) + { + switch (pPlayer->GetTeam()) + { + case ALLIANCE: + pCreature->setFaction(FACTION_ESCORTEE_A); + break; + case HORDE: + pCreature->setFaction(FACTION_ESCORTEE_H); + break; + } + DoScriptText(SAY_bonker_2, pCreature, pPlayer); + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, true, pPlayer->GetGUID()); + } + return true; +} +struct npc_bonker_togglevoltAI : public npc_escortAI +{ + npc_bonker_togglevoltAI(Creature *c) : npc_escortAI(c) {} + uint32 Bonker_agro; + + void Reset() + { + Bonker_agro=0; + SetDespawnAtFar(false); + } + + void JustDied(Unit* /*killer*/) + { + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->FailQuest(QUEST_ESCAPING_THE_MIST); + } + + void UpdateEscortAI(const uint32 /*diff*/) + { + if (GetAttack() && UpdateVictim()) + { + if (Bonker_agro == 0) + { + DoScriptText(SAY_bonker_1,me); + Bonker_agro++; + } + DoMeleeAttackIfReady(); + } + else Bonker_agro=0; + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 29: + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_GET_ME_OUTA_HERE, me); + break; + } + } +}; + +CreatureAI* GetAI_npc_bonker_togglevolt(Creature* pCreature) +{ + return new npc_bonker_togglevoltAI(pCreature); +} + +/*###### +## Help Those That Cannot Help Themselves, Quest 11876 +######*/ + +enum eHelpThemselves +{ + QUEST_CANNOT_HELP_THEMSELVES = 11876, + GO_MAMMOTH_TRAP_1 = 188022, + GO_MAMMOTH_TRAP_2 = 188024, + GO_MAMMOTH_TRAP_3 = 188025, + GO_MAMMOTH_TRAP_4 = 188026, + GO_MAMMOTH_TRAP_5 = 188027, + GO_MAMMOTH_TRAP_6 = 188028, + GO_MAMMOTH_TRAP_7 = 188029, + GO_MAMMOTH_TRAP_8 = 188030, + GO_MAMMOTH_TRAP_9 = 188031, + GO_MAMMOTH_TRAP_10 = 188032, + GO_MAMMOTH_TRAP_11 = 188033, + GO_MAMMOTH_TRAP_12 = 188034, + GO_MAMMOTH_TRAP_13 = 188035, + GO_MAMMOTH_TRAP_14 = 188036, + GO_MAMMOTH_TRAP_15 = 188037, + GO_MAMMOTH_TRAP_16 = 188038, + GO_MAMMOTH_TRAP_17 = 188039, + GO_MAMMOTH_TRAP_18 = 188040, + GO_MAMMOTH_TRAP_19 = 188041, + GO_MAMMOTH_TRAP_20 = 188042, + GO_MAMMOTH_TRAP_21 = 188043, + GO_MAMMOTH_TRAP_22 = 188044, +}; + +#define MammothTrapsNum 22 +const uint32 MammothTraps[MammothTrapsNum] = +{ + GO_MAMMOTH_TRAP_1, GO_MAMMOTH_TRAP_2, GO_MAMMOTH_TRAP_3, GO_MAMMOTH_TRAP_4, GO_MAMMOTH_TRAP_5, + GO_MAMMOTH_TRAP_6, GO_MAMMOTH_TRAP_7, GO_MAMMOTH_TRAP_8, GO_MAMMOTH_TRAP_9, GO_MAMMOTH_TRAP_10, + GO_MAMMOTH_TRAP_11, GO_MAMMOTH_TRAP_12, GO_MAMMOTH_TRAP_13, GO_MAMMOTH_TRAP_14, GO_MAMMOTH_TRAP_15, + GO_MAMMOTH_TRAP_16, GO_MAMMOTH_TRAP_17, GO_MAMMOTH_TRAP_18, GO_MAMMOTH_TRAP_19, GO_MAMMOTH_TRAP_20, + GO_MAMMOTH_TRAP_21, GO_MAMMOTH_TRAP_22 +}; + +struct npc_trapped_mammoth_calfAI : public ScriptedAI +{ + npc_trapped_mammoth_calfAI(Creature* c) : ScriptedAI(c) {} + + uint32 uiTimer; + bool bStarted; + + void Reset() + { + uiTimer = 1500; + bStarted = false; + + GameObject* pTrap; + for (uint8 i = 0; i < MammothTrapsNum; ++i) + { + pTrap = me->FindNearestGameObject(MammothTraps[i],11.0f); + if (pTrap) + { + pTrap->SetGoState(GO_STATE_ACTIVE); + return; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (bStarted) + { + if (uiTimer <= diff) + { + Position pos; + me->GetRandomNearPosition(pos, 10.0f); + me->GetMotionMaster()->MovePoint(0,pos); + bStarted = false; + } + else uiTimer -= diff; + } + } + + void DoAction(const int32 param) + { + if (param == 1) + bStarted = true; + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + + if (uiType != POINT_MOTION_TYPE) + return; + me->DisappearAndDie(); + GameObject* pTrap; + for (uint8 i = 0; i < MammothTrapsNum; ++i) + { + pTrap = me->FindNearestGameObject(MammothTraps[i],11.0f); + if (pTrap) + { + pTrap->SetLootState(GO_JUST_DEACTIVATED); + return; + } + } + } +}; + +CreatureAI* GetAI_npc_trapped_mammoth_calf(Creature* pCreature) +{ + return new npc_trapped_mammoth_calfAI(pCreature); +} + +/*###### +## Quest 11653: Hah... You're Not So Big Now! +######*/ + +enum eNotSoBig +{ + QUEST_YOU_RE_NOT_SO_BIG_NOW = 11653, + SPELL_AURA_NOTSOBIG_1 = 45672, + SPELL_AURA_NOTSOBIG_2 = 45673, + SPELL_AURA_NOTSOBIG_3 = 45677, + SPELL_AURA_NOTSOBIG_4 = 45681 +}; + +struct npc_magmoth_crusherAI : public ScriptedAI +{ + npc_magmoth_crusherAI(Creature* c) : ScriptedAI(c) {} + + void JustDied(Unit *pKiller) + { + if (pKiller->GetTypeId() == TYPEID_PLAYER && + CAST_PLR(pKiller)->GetQuestStatus(QUEST_YOU_RE_NOT_SO_BIG_NOW) == QUEST_STATUS_INCOMPLETE && + (me->HasAura(SPELL_AURA_NOTSOBIG_1) || me->HasAura(SPELL_AURA_NOTSOBIG_2) || + me->HasAura(SPELL_AURA_NOTSOBIG_3) || me->HasAura(SPELL_AURA_NOTSOBIG_4))) + { + Quest const* qInfo = objmgr.GetQuestTemplate(QUEST_YOU_RE_NOT_SO_BIG_NOW); + if (qInfo) + CAST_PLR(pKiller)->KilledMonsterCredit(qInfo->ReqCreatureOrGOId[0],0); + } + } +}; + +CreatureAI* GetAI_npc_magmoth_crusher(Creature* pCreature) +{ + return new npc_magmoth_crusherAI(pCreature); +} + +/*###### +## Quest 11608: Bury Those Cockroaches! +######*/ + +#define QUEST_BURY_THOSE_COCKROACHES 11608 +#define SPELL_SEAFORIUM_DEPTH_CHARGE_EXPLOSION 45502 + +struct npc_seaforium_depth_chargeAI : public ScriptedAI +{ + npc_seaforium_depth_chargeAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiExplosionTimer; + void Reset() + { + uiExplosionTimer = urand(5000,10000); + } + void UpdateAI(const uint32 diff) + { + if (uiExplosionTimer < diff) + { + DoCast(SPELL_SEAFORIUM_DEPTH_CHARGE_EXPLOSION); + for (uint8 i = 0; i < 4; ++i) + { + if (Creature* cCredit = me->FindNearestCreature(25402 + i, 10.0f))//25402-25405 credit markers + { + if (Unit* uOwner = me->GetOwner(true)) + { + Player* pOwner = uOwner->ToPlayer(); + if (pOwner && pOwner->GetQuestStatus(QUEST_BURY_THOSE_COCKROACHES) == QUEST_STATUS_INCOMPLETE) + pOwner->KilledMonsterCredit(cCredit->GetEntry(),cCredit->GetGUID()); + } + } + } + me->Kill(me); + return; + } else uiExplosionTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_seaforium_depth_charge(Creature* pCreature) +{ + return new npc_seaforium_depth_chargeAI(pCreature); +} + +/*###### +## Help Those That Cannot Help Themselves, Quest 11876 +######*/ + +enum eValiancekeepcannons +{ + GO_VALIANCE_KEEP_CANNON_1 = 187560, + GO_VALIANCE_KEEP_CANNON_2 = 188692 +}; + +struct npc_valiance_keep_cannoneerAI : public ScriptedAI +{ + npc_valiance_keep_cannoneerAI(Creature* c) : ScriptedAI(c) {} + + uint32 uiTimer; + + void Reset() + { + uiTimer = urand(13000,18000); + } + + void UpdateAI(const uint32 diff) + { + if (uiTimer <= diff) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + GameObject* pCannon = me->FindNearestGameObject(GO_VALIANCE_KEEP_CANNON_1,10); + if (!pCannon) + pCannon = me->FindNearestGameObject(GO_VALIANCE_KEEP_CANNON_2,10); + if (pCannon) + pCannon->Use(me); + uiTimer = urand(13000,18000); + } + else uiTimer -= diff; + + if (!UpdateVictim()) + return; + } + +}; + +CreatureAI* GetAI_npc_valiance_keep_cannoneer(Creature* pCreature) +{ + return new npc_valiance_keep_cannoneerAI(pCreature); +} + +/******************************************************* + * npc_warmage_coldarra + *******************************************************/ + +enum Spells +{ + SPELL_TRANSITUS_SHIELD_BEAM = 48310 +}; + +enum NPCs +{ + NPC_TRANSITUS_SHIELD_DUMMY = 27306, + NPC_WARMAGE_HOLLISTER = 27906, + NPC_WARMAGE_CALANDRA = 27173, + NPC_WARMAGE_WATKINS = 27904 +}; + +struct npc_warmage_coldarraAI : public Scripted_NoMovementAI +{ + npc_warmage_coldarraAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature){} + + uint32 m_uiTimer; //Timer until recast + + void Reset() + { + m_uiTimer = 0; + } + + void Aggro(Unit* /*pWho*/) {} + + void AttackStart(Unit* /*pWho*/) {} + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiTimer <= uiDiff) + { + std::list orbList; + GetCreatureListWithEntryInGrid(orbList, me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f); + + switch(me->GetEntry()) + { + case NPC_WARMAGE_HOLLISTER: + { + if (!orbList.empty()) + { + for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) + { + if (Creature* pOrb = *itr) + if (pOrb->GetPositionY() > 6680) + DoCast(pOrb,SPELL_TRANSITUS_SHIELD_BEAM); + } + } + m_uiTimer = urand(90000,120000); + } + break; + case NPC_WARMAGE_CALANDRA: + { + if (!orbList.empty()) + { + for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) + { + if (Creature* pOrb = *itr) + if ((pOrb->GetPositionY() < 6680) && (pOrb->GetPositionY() > 6630)) + DoCast(pOrb,SPELL_TRANSITUS_SHIELD_BEAM); + } + } + m_uiTimer = urand(90000,120000); + } + break; + case NPC_WARMAGE_WATKINS: + { + if (!orbList.empty()) + { + for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) + { + if (Creature* pOrb = *itr) + if (pOrb->GetPositionY() < 6630) + DoCast(pOrb,SPELL_TRANSITUS_SHIELD_BEAM); + } + } + m_uiTimer = urand(90000,120000); + } + break; + } + } + else m_uiTimer -= uiDiff; + + ScriptedAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_npc_warmage_coldarra(Creature* pCreature) +{ + return new npc_warmage_coldarraAI(pCreature); +} + +void AddSC_borean_tundra() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sinkhole_kill_credit"; + newscript->GetAI = &GetAI_npc_sinkhole_kill_credit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_khunok_the_behemoth"; + newscript->GetAI = &GetAI_npc_khunok_the_behemoth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_keristrasza"; + newscript->pGossipHello = &GossipHello_npc_keristrasza; + newscript->pGossipSelect = &GossipSelect_npc_keristrasza; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_corastrasza"; + newscript->pGossipHello = &GossipHello_npc_corastrasza; + newscript->pGossipSelect = &GossipSelect_npc_corastrasza; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_iruk"; + newscript->pGossipHello = &GossipHello_npc_iruk; + newscript->pGossipSelect = &GossipSelect_npc_iruk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nerubar_victim"; + newscript->GetAI = &GetAI_mob_nerubar_victim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_scourge_prisoner"; + newscript->GetAI = &GetAI_npc_scourge_prisoner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jenny"; + newscript->GetAI = &GetAI_npc_jenny; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_fezzix_geartwist"; + newscript->GetAI = &GetAI_npc_fezzix_geartwist; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_nesingwary_trapper"; + newscript->GetAI = &GetAI_npc_nesingwary_trapper; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lurgglbr"; + newscript->GetAI = &GetAI_npc_lurgglbr; + newscript->pQuestAccept = &QuestAccept_npc_lurgglbr; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_nexus_drake_hatchling"; + newscript->GetAI = &GetAI_npc_nexus_drake_hatchling; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thassarian"; + newscript->GetAI = &GetAI_npc_thassarian; + newscript->pGossipHello = &GossipHello_npc_thassarian; + newscript->pGossipSelect = &GossipSelect_npc_thassarian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_image_lich_king"; + newscript->GetAI = &GetAI_npc_image_lich_king; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_counselor_talbot"; + newscript->GetAI = &GetAI_npc_counselor_talbot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_leryssa"; + newscript->GetAI = &GetAI_npc_leryssa; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_general_arlos"; + newscript->GetAI = &GetAI_npc_general_arlos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_beryl_sorcerer"; + newscript->GetAI = &GetAI_npc_beryl_sorcerer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_imprisoned_beryl_sorcerer"; + newscript->GetAI = &GetAI_npc_imprisoned_beryl_sorcerer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mootoo_the_younger"; + newscript->GetAI = &GetAI_npc_mootoo_the_younger; + newscript->pQuestAccept=&QuestAccept_npc_mootoo_the_younger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bonker_togglevolt"; + newscript->GetAI = &GetAI_npc_bonker_togglevolt; + newscript->pQuestAccept=&QuestAccept_npc_bonker_togglevolt; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_trapped_mammoth_calf"; + newscript->GetAI = &GetAI_npc_trapped_mammoth_calf; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_magmoth_crusher"; + newscript->GetAI = &GetAI_npc_magmoth_crusher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_seaforium_depth_charge"; + newscript->GetAI = &GetAI_npc_seaforium_depth_charge; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_valiance_keep_cannoneer"; + newscript->GetAI = &GetAI_npc_valiance_keep_cannoneer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_warmage_coldarra"; + newscript->GetAI = &GetAI_npc_warmage_coldarra; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp new file mode 100644 index 00000000000..c33ea69fa2d --- /dev/null +++ b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Argent Challenge Encounter. +SD%Complete: 50 % +SDComment: AI for Argent Soldiers are not implemented. AI from bosses need more improvements. +SDCategory: Trial of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" +#include "ScriptedEscortAI.h" + +enum eSpells +{ + //Eadric + SPELL_EADRIC_ACHIEVEMENT = 68197, + SPELL_HAMMER_JUSTICE = 66863, + SPELL_HAMMER_RIGHTEOUS = 66867, + SPELL_RADIANCE = 66935, + SPELL_VENGEANCE = 66865, + + //Paletress + SPELL_SMITE = 66536, + SPELL_SMITE_H = 67674, + SPELL_HOLY_FIRE = 66538, + SPELL_HOLY_FIRE_H = 67676, + SPELL_RENEW = 66537, + SPELL_RENEW_H = 67675, + SPELL_HOLY_NOVA = 66546, + SPELL_SHIELD = 66515, + SPELL_CONFESS = 66680, + SPELL_SUMMON_MEMORY = 66545, + + //Memory + SPELL_OLD_WOUNDS = 66620, + SPELL_OLD_WOUNDS_H = 67679, + SPELL_SHADOWS_PAST = 66619, + SPELL_SHADOWS_PAST_H = 67678, + SPELL_WAKING_NIGHTMARE = 66552, + SPELL_WAKING_NIGHTMARE_H = 67677 +}; + +struct boss_eadricAI : public ScriptedAI +{ + boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + pCreature->SetReactState(REACT_PASSIVE); + pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint32 uiVenganceTimer; + uint32 uiRadianceTimer; + uint32 uiHammerJusticeTimer; + uint32 uiResetTimer; + + bool bDone; + + void Reset() + { + uiVenganceTimer = 10000; + uiRadianceTimer = 16000; + uiHammerJusticeTimer = 25000; + uiResetTimer = 5000; + + bDone = false; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + damage = 0; + EnterEvadeMode(); + me->setFaction(35); + bDone = true; + } + } + + void MovementInform(uint32 MovementType, uint32 /*Data*/) + { + if (MovementType != POINT_MOTION_TYPE) + return; + + if (pInstance) + pInstance->SetData(BOSS_ARGENT_CHALLENGE_E, DONE); + + me->DisappearAndDie(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (bDone && uiResetTimer <= uiDiff) + { + me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); + bDone = false; + } else uiResetTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + if (uiHammerJusticeTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + { + DoCast(pTarget, SPELL_HAMMER_JUSTICE); + DoCast(pTarget, SPELL_HAMMER_RIGHTEOUS); + } + } + uiHammerJusticeTimer = 25000; + } else uiHammerJusticeTimer -= uiDiff; + + if (uiVenganceTimer <= uiDiff) + { + DoCast(me,SPELL_VENGEANCE); + + uiVenganceTimer = 10000; + } else uiVenganceTimer -= uiDiff; + + if (uiRadianceTimer <= uiDiff) + { + DoCastAOE(SPELL_RADIANCE); + + uiRadianceTimer = 16000; + } else uiRadianceTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_eadric(Creature* pCreature) +{ + return new boss_eadricAI(pCreature); +} + +struct boss_paletressAI : public ScriptedAI +{ + boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + MemoryGUID = 0; + pCreature->SetReactState(REACT_PASSIVE); + pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pCreature->RestoreFaction(); + } + + ScriptedInstance* pInstance; + + Creature* pMemory; + uint64 MemoryGUID; + + bool bHealth; + bool bDone; + + uint32 uiHolyFireTimer; + uint32 uiHolySmiteTimer; + uint32 uiRenewTimer; + uint32 uiResetTimer; + + void Reset() + { + me->RemoveAllAuras(); + + uiHolyFireTimer = urand(9000,12000); + uiHolySmiteTimer = urand(5000,7000); + uiRenewTimer = urand(2000,5000); + + uiResetTimer = 7000; + + bHealth = false; + bDone = false; + + if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) + if (pMemory->isAlive()) + pMemory->RemoveFromWorld(); + } + + void SetData(uint32 uiId, uint32 /*uiValue*/) + { + if (uiId == 1) + me->RemoveAura(SPELL_SHIELD); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + damage = 0; + EnterEvadeMode(); + me->setFaction(35); + bDone = true; + } + } + + void MovementInform(uint32 MovementType, uint32 Point) + { + if (MovementType != POINT_MOTION_TYPE || Point != 0) + return; + + if (pInstance) + pInstance->SetData(BOSS_ARGENT_CHALLENGE_P, DONE); + + me->DisappearAndDie(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (bDone && uiResetTimer <= uiDiff) + { + me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); + bDone = false; + } else uiResetTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + if (uiHolyFireTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_HOLY_FIRE); + } + if (me->HasAura(SPELL_SHIELD)) + uiHolyFireTimer = 13000; + else + uiHolyFireTimer = urand(9000,12000); + } else uiHolyFireTimer -= uiDiff; + + if (uiHolySmiteTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_SMITE); + } + if (me->HasAura(SPELL_SHIELD)) + uiHolySmiteTimer = 9000; + else + uiHolySmiteTimer = urand(5000,7000); + } else uiHolySmiteTimer -= uiDiff; + + if (me->HasAura(SPELL_SHIELD)) + if (uiRenewTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + uint8 uiTarget = urand(0,1); + switch(uiTarget) + { + case 0: + DoCast(me,SPELL_RENEW); + break; + case 1: + if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) + if (pMemory->isAlive()) + DoCast(pMemory, SPELL_RENEW); + break; + } + uiRenewTimer = urand(15000,17000); + } else uiRenewTimer -= uiDiff; + + + if (!bHealth && me->GetHealth()*100 / me->GetMaxHealth() <= 25) + { + me->InterruptNonMeleeSpells(true); + DoCastAOE(SPELL_HOLY_NOVA,false); + DoCast(me, SPELL_SHIELD); + DoCastAOE(SPELL_SUMMON_MEMORY,false); + DoCastAOE(SPELL_CONFESS,false); + + bHealth = true; + } + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* pSummon) + { + MemoryGUID = pSummon->GetGUID(); + } +}; + +CreatureAI* GetAI_boss_paletress(Creature* pCreature) +{ + return new boss_paletressAI(pCreature); +} + +struct npc_memoryAI : public ScriptedAI +{ + npc_memoryAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiOldWoundsTimer; + uint32 uiShadowPastTimer; + uint32 uiWakingNightmare; + + void Reset() + { + uiOldWoundsTimer = 12000; + uiShadowPastTimer = 5000; + uiWakingNightmare = 7000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiOldWoundsTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, SPELL_OLD_WOUNDS); + } + uiOldWoundsTimer = 12000; + }else uiOldWoundsTimer -= uiDiff; + + if (uiWakingNightmare <= uiDiff) + { + DoCast(me, SPELL_WAKING_NIGHTMARE); + uiWakingNightmare = 7000; + }else uiWakingNightmare -= uiDiff; + + if (uiShadowPastTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_SHADOWS_PAST); + } + uiShadowPastTimer = 5000; + }else uiShadowPastTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (me->isSummon()) + { + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + { + if (pSummoner && pSummoner->isAlive()) + CAST_CRE(pSummoner)->AI()->SetData(1,0); + } + } + } +}; + +CreatureAI* GetAI_npc_memory(Creature* pCreature) +{ + return new npc_memoryAI(pCreature); +} + +// THIS AI NEEDS MORE IMPROVEMENTS +struct npc_argent_soldierAI : public npc_escortAI +{ + npc_argent_soldierAI(Creature* pCreature) : npc_escortAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + me->SetReactState(REACT_DEFENSIVE); + SetDespawnAtEnd(false); + uiWaypoint = 0; + } + + ScriptedInstance* pInstance; + + uint8 uiWaypoint; + + void WaypointReached(uint32 uiPoint) + { + if (uiPoint == 0) + { + switch(uiWaypoint) + { + case 0: + me->SetOrientation(5.81); + break; + case 1: + me->SetOrientation(4.60); + break; + case 2: + me->SetOrientation(2.79); + break; + } + + me->SendMovementFlagUpdate(); + } + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch(me->GetEntry()) + { + case NPC_ARGENT_LIGHWIELDER: + switch(uiType) + { + case 0: + AddWaypoint(0,712.14,628.42,411.88); + break; + case 1: + AddWaypoint(0,742.44,650.29,411.79); + break; + case 2: + AddWaypoint(0,783.33,615.29,411.84); + break; + } + break; + case NPC_ARGENT_MONK: + switch(uiType) + { + case 0: + AddWaypoint(0,713.12,632.97,411.90); + break; + case 1: + AddWaypoint(0,746.73,650.24,411.56); + break; + case 2: + AddWaypoint(0,781.32,610.54,411.82); + break; + } + break; + case NPC_PRIESTESS: + switch(uiType) + { + case 0: + AddWaypoint(0,715.06,637.07,411.91); + break; + case 1: + AddWaypoint(0,750.72,650.20,411.77); + break; + case 2: + AddWaypoint(0,779.77,607.03,411.81); + break; + } + break; + } + + Start(false,true,0); + uiWaypoint = uiType; + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(DATA_ARGENT_SOLDIER_DEFEATED,pInstance->GetData(DATA_ARGENT_SOLDIER_DEFEATED) + 1); + } +}; + +CreatureAI* GetAI_npc_argent_soldier(Creature* pCreature) +{ + return new npc_argent_soldierAI(pCreature); +} + +void AddSC_boss_argent_challenge() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_eadric"; + NewScript->GetAI = &GetAI_boss_eadric; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_paletress"; + NewScript->GetAI = &GetAI_boss_paletress; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_memory"; + NewScript->GetAI = &GetAI_npc_memory; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_argent_soldier"; + NewScript->GetAI = &GetAI_npc_argent_soldier; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp new file mode 100644 index 00000000000..e1f4586ca6c --- /dev/null +++ b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Black Knight +SD%Complete: 80% +SDComment: missing yells. not sure about timers. +SDCategory: Trial of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "trial_of_the_champion.h" + +enum eSpells +{ + //phase 1 + SPELL_PLAGUE_STRIKE = 67884, + SPELL_PLAGUE_STRIKE_2 = 67724, + SPELL_ICY_TOUCH_H = 67881, + SPELL_ICY_TOUCH = 67718, + SPELL_DEATH_RESPITE = 67745, + SPELL_DEATH_RESPITE_2 = 68306, + SPELL_DEATH_RESPITE_3 = 66798, + SPELL_OBLITERATE_H = 67883, + SPELL_OBLITERATE = 67725, + //in this phase should rise herald (the spell is missing) + + //phase 2 - During this phase, the Black Knight will use the same abilities as in phase 1, except for Death's Respite + SPELL_ARMY_DEAD = 67761, + SPELL_DESECRATION = 67778, + SPELL_DESECRATION_2 = 67778, + SPELL_GHOUL_EXPLODE = 67751, + + //phase 3 + SPELL_DEATH_BITE_H = 67875, + SPELL_DEATH_BITE = 67808, + SPELL_MARKED_DEATH = 67882, + SPELL_MARKED_DEATH_2 = 67823, + + SPELL_BLACK_KNIGHT_RES = 67693, + + SPELL_LEAP = 67749, + SPELL_LEAP_H = 67880 +}; + +enum eModels +{ + MODEL_SKELETON = 29846, + MODEL_GHOST = 21300 +}; + +enum ePhases +{ + PHASE_UNDEAD = 1, + PHASE_SKELETON = 2, + PHASE_GHOST = 3 +}; + +struct boss_black_knightAI : public ScriptedAI +{ + boss_black_knightAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + std::list SummonList; + + bool bEventInProgress; + bool bEvent; + bool bSummonArmy; + bool bDeathArmyDone; + + uint8 uiPhase; + + uint32 uiPlagueStrikeTimer; + uint32 uiIcyTouchTimer; + uint32 uiDeathRespiteTimer; + uint32 uiObliterateTimer; + uint32 uiDesecration; + uint32 uiResurrectTimer; + uint32 uiDeathArmyCheckTimer; + uint32 uiGhoulExplodeTimer; + uint32 uiDeathBiteTimer; + uint32 uiMarkedDeathTimer; + + void Reset() + { + RemoveSummons(); + me->SetDisplayId(me->GetNativeDisplayId()); + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + + bEventInProgress = false; + bEvent = false; + bSummonArmy = false; + bDeathArmyDone = false; + + uiPhase = PHASE_UNDEAD; + + uiIcyTouchTimer = urand(5000,9000); + uiPlagueStrikeTimer = urand(10000,13000); + uiDeathRespiteTimer = urand(15000,16000); + uiObliterateTimer = urand(17000,19000); + uiDesecration = urand(15000,16000); + uiDeathArmyCheckTimer = 7000; + uiResurrectTimer = 4000; + uiGhoulExplodeTimer = 8000; + uiDeathBiteTimer = urand (2000,4000); + uiMarkedDeathTimer = urand (5000,7000); + } + + void RemoveSummons() + { + if (SummonList.empty()) + return; + + for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + if (pTemp) + pTemp->DisappearAndDie(); + } + SummonList.clear(); + } + + void JustSummoned(Creature* pSummon) + { + SummonList.push_back(pSummon->GetGUID()); + pSummon->AI()->AttackStart(me->getVictim()); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (bEventInProgress) + if (uiResurrectTimer <= uiDiff) + { + me->SetHealth(me->GetMaxHealth()); + DoCast(me,SPELL_BLACK_KNIGHT_RES,true); + uiPhase++; + uiResurrectTimer = 4000; + bEventInProgress = false; + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + } else uiResurrectTimer -= uiDiff; + + switch(uiPhase) + { + case PHASE_UNDEAD: + case PHASE_SKELETON: + { + if (uiIcyTouchTimer <= uiDiff) + { + DoCastVictim(SPELL_ICY_TOUCH); + uiIcyTouchTimer = urand(5000,7000); + } else uiIcyTouchTimer -= uiDiff; + if (uiPlagueStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_ICY_TOUCH); + uiPlagueStrikeTimer = urand(12000,15000); + } else uiPlagueStrikeTimer -= uiDiff; + if (uiObliterateTimer <= uiDiff) + { + DoCastVictim(SPELL_OBLITERATE); + uiObliterateTimer = urand(17000,19000); + } else uiObliterateTimer -= uiDiff; + switch(uiPhase) + { + case PHASE_UNDEAD: + { + if (uiDeathRespiteTimer <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_DEATH_RESPITE); + } + uiDeathRespiteTimer = urand(15000,16000); + } else uiDeathRespiteTimer -= uiDiff; + break; + } + case PHASE_SKELETON: + { + if (!bSummonArmy) + { + bSummonArmy = true; + me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + DoCast(me, SPELL_ARMY_DEAD); + } + if (!bDeathArmyDone) + if (uiDeathArmyCheckTimer <= uiDiff) + { + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + uiDeathArmyCheckTimer = 0; + bDeathArmyDone = true; + } else uiDeathArmyCheckTimer -= uiDiff; + if (uiDesecration <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_DESECRATION); + } + uiDesecration = urand(15000,16000); + } else uiDesecration -= uiDiff; + if (uiGhoulExplodeTimer <= uiDiff) + { + DoCast(me, SPELL_GHOUL_EXPLODE); + uiGhoulExplodeTimer = 8000; + } else uiGhoulExplodeTimer -= uiDiff; + break; + } + break; + } + break; + } + case PHASE_GHOST: + { + if (uiDeathBiteTimer <= uiDiff) + { + DoCastAOE(SPELL_DEATH_BITE); + uiDeathBiteTimer = urand (2000, 4000); + } else uiDeathBiteTimer -= uiDiff; + if (uiMarkedDeathTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_MARKED_DEATH); + } + uiMarkedDeathTimer = urand (5000, 7000); + } else uiMarkedDeathTimer -= uiDiff; + break; + } + } + + if (!me->hasUnitState(UNIT_STAT_ROOT) && !me->GetHealth()*100 / me->GetMaxHealth() <= 0) + DoMeleeAttackIfReady(); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) + { + if (uiDamage > me->GetHealth() && uiPhase <= PHASE_SKELETON) + { + uiDamage = 0; + me->SetHealth(0); + me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + RemoveSummons(); + switch(uiPhase) + { + case PHASE_UNDEAD: + me->SetDisplayId(MODEL_SKELETON); + break; + case PHASE_SKELETON: + me->SetDisplayId(MODEL_GHOST); + break; + } + bEventInProgress = true; + } + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_BLACK_KNIGHT,DONE); + } +}; + +CreatureAI* GetAI_boss_black_knight(Creature *pCreature) +{ + return new boss_black_knightAI (pCreature); +} + +struct npc_risen_ghoulAI : public ScriptedAI +{ + npc_risen_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiAttackTimer; + + void Reset() + { + uiAttackTimer = 3500; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiAttackTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, (SPELL_LEAP)); + } + uiAttackTimer = 3500; + } else uiAttackTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_risen_ghoul(Creature* pCreature) +{ + return new npc_risen_ghoulAI(pCreature); +} + +struct npc_black_knight_skeletal_gryphonAI : public npc_escortAI +{ + npc_black_knight_skeletal_gryphonAI(Creature* pCreature) : npc_escortAI(pCreature) + { + Start(false,true,0,NULL); + } + + void WaypointReached(uint32 /*i*/) + { + + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + } + +}; + +CreatureAI* GetAI_npc_black_knight_skeletal_gryphon(Creature* pCreature) +{ + return new npc_black_knight_skeletal_gryphonAI(pCreature); +} + +void AddSC_boss_black_knight() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_black_knight"; + NewScript->GetAI = &GetAI_boss_black_knight; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_risen_ghoul"; + NewScript->GetAI = &GetAI_npc_risen_ghoul; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_black_knight_skeletal_gryphon"; + NewScript->GetAI = &GetAI_npc_black_knight_skeletal_gryphon; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp new file mode 100644 index 00000000000..4bf8143a210 --- /dev/null +++ b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp @@ -0,0 +1,993 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_grand_champions +SD%Complete: 50 % +SDComment: Is missing the ai to make the npcs look for a new mount and use it. +SDCategory: Trial Of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "Vehicle.h" +#include "trial_of_the_champion.h" + +enum eSpells +{ + //Vehicle + SPELL_CHARGE = 63010, + SPELL_SHIELD_BREAKER = 68504, + SPELL_SHIELD = 66482, + + // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior + SPELL_MORTAL_STRIKE = 68783, + SPELL_MORTAL_STRIKE_H = 68784, + SPELL_BLADESTORM = 63784, + SPELL_INTERCEPT = 67540, + SPELL_ROLLING_THROW = 47115, //not implemented in the AI yet... + + // Ambrose Boltspark && Eressea Dawnsinger || Mage + SPELL_FIREBALL = 66042, + SPELL_FIREBALL_H = 68310, + SPELL_BLAST_WAVE = 66044, + SPELL_BLAST_WAVE_H = 68312, + SPELL_HASTE = 66045, + SPELL_POLYMORPH = 66043, + SPELL_POLYMORPH_H = 68311, + + // Colosos && Runok Wildmane || Shaman + SPELL_CHAIN_LIGHTNING = 67529, + SPELL_CHAIN_LIGHTNING_H = 68319, + SPELL_EARTH_SHIELD = 67530, + SPELL_HEALING_WAVE = 67528, + SPELL_HEALING_WAVE_H = 68318, + SPELL_HEX_OF_MENDING = 67534, + + // Jaelyne Evensong && Zul'tore || Hunter + SPELL_DISENGAGE = 68340, //not implemented in the AI yet... + SPELL_LIGHTNING_ARROWS = 66083, + SPELL_MULTI_SHOT = 66081, + SPELL_SHOOT = 65868, + SPELL_SHOOT_H = 67988, + + // Lana Stouthammer Evensong && Deathstalker Visceri || Rouge + SPELL_EVISCERATE = 67709, + SPELL_EVISCERATE_H = 68317, + SPELL_FAN_OF_KNIVES = 67706, + SPELL_POISON_BOTTLE = 67701 +}; + +enum eSeat +{ + SEAT_ID_0 = 0 +}; + +struct Point +{ + float x,y,z; +}; + +const Point MovementPoint[] = +{ + {746.84,623.15,411.41}, + {747.96,620.29,411.09}, + {750.23,618.35,411.09} +}; + +void AggroAllPlayers(Creature* pTemp) +{ + Map::PlayerList const &PlList = pTemp->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(pTemp); + pTemp->AddThreat(pPlayer, 0.0f); + } + } + } +} + +bool GrandChampionsOutVehicle(Creature* me) +{ + ScriptedInstance* pInstance = me->GetInstanceData(); + + if (!pInstance) + return false; + + Creature* pGrandChampion1 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_1)); + Creature* pGrandChampion2 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_2)); + Creature* pGrandChampion3 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_3)); + + if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) + { + if (!pGrandChampion1->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && + !pGrandChampion2->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && + !pGrandChampion3->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return true; + } + + return false; +} + +/* +* Generic AI for vehicles used by npcs in ToC, it needs more improvements. * +* Script Complete: 25%. * +*/ + +struct generic_vehicleAI_toc5AI : public npc_escortAI +{ + generic_vehicleAI_toc5AI(Creature* pCreature) : npc_escortAI(pCreature) + { + SetDespawnAtEnd(false); + uiWaypointPath = 0; + + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiChargeTimer; + uint32 uiShieldBreakerTimer; + uint32 uiBuffTimer; + + uint32 uiWaypointPath; + + void Reset() + { + uiChargeTimer = 5000; + uiShieldBreakerTimer = 8000; + uiBuffTimer = urand(30000,60000); + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch(uiType) + { + case 1: + AddWaypoint(0,747.36,634.07,411.572); + AddWaypoint(1,780.43,607.15,411.82); + AddWaypoint(2,785.99,599.41,411.92); + AddWaypoint(3,778.44,601.64,411.79); + uiWaypointPath = 1; + break; + case 2: + AddWaypoint(0,747.35,634.07,411.57); + AddWaypoint(1,768.72,581.01,411.92); + AddWaypoint(2,763.55,590.52,411.71); + uiWaypointPath = 2; + break; + case 3: + AddWaypoint(0,747.35,634.07,411.57); + AddWaypoint(1,784.02,645.33,412.39); + AddWaypoint(2,775.67,641.91,411.91); + uiWaypointPath = 3; + break; + } + + if (uiType <= 3) + Start(false,true,0,NULL); + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 2: + if (pInstance && uiWaypointPath == 3 || uiWaypointPath == 2) + pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); + break; + case 3: + if (pInstance) + pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); + break; + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoCastSpellShield(); + } + + void DoCastSpellShield() + { + for (uint8 i = 0; i < 3; ++i) + DoCast(me,SPELL_SHIELD,true); + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + if (uiBuffTimer <= uiDiff) + { + if (!me->HasAura(SPELL_SHIELD)) + DoCastSpellShield(); + + uiBuffTimer = urand(30000,45000); + }else uiBuffTimer -= uiDiff; + + if (uiChargeTimer <= uiDiff) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) + { + DoResetThreat(); + me->AddThreat(pPlayer,1.0f); + DoCast(pPlayer, SPELL_CHARGE); + break; + } + } + } + uiChargeTimer = 5000; + }else uiChargeTimer -= uiDiff; + + //dosen't work at all + if (uiShieldBreakerTimer <= uiDiff) + { + Vehicle *pVehicle = me->GetVehicleKit(); + if (!pVehicle) + return; + + if (Unit* pPassenger = pVehicle->GetPassenger(SEAT_ID_0)) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,10.0f,30.0f,false)) + { + pPassenger->CastSpell(pPlayer,SPELL_SHIELD_BREAKER,true); + break; + } + } + } + } + uiShieldBreakerTimer = 7000; + }else uiShieldBreakerTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_generic_vehicleAI_toc5(Creature* pCreature) +{ + return new generic_vehicleAI_toc5AI(pCreature); +} + +// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior +struct boss_warrior_toc5AI : public ScriptedAI +{ + boss_warrior_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiBladeStormTimer; + uint32 uiInterceptTimer; + uint32 uiMortalStrikeTimer; + uint32 uiAttackTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiBladeStormTimer = urand(15000,20000); + uiInterceptTimer = 7000; + uiMortalStrikeTimer = urand(8000,12000); + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiInterceptTimer <= uiDiff) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) + { + DoResetThreat(); + me->AddThreat(pPlayer,5.0f); + DoCast(pPlayer,SPELL_INTERCEPT); + break; + } + } + } + uiInterceptTimer = 7000; + } else uiInterceptTimer -= uiDiff; + + if (uiBladeStormTimer <= uiDiff) + { + DoCastVictim(SPELL_BLADESTORM); + uiBladeStormTimer = urand(15000,20000); + } else uiBladeStormTimer -= uiDiff; + + if (uiMortalStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_MORTAL_STRIKE); + uiMortalStrikeTimer = urand(8000,12000); + } else uiMortalStrikeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_warrior_toc5(Creature* pCreature) +{ + return new boss_warrior_toc5AI(pCreature); +} + +// Ambrose Boltspark && Eressea Dawnsinger || Mage +struct boss_mage_toc5AI : public ScriptedAI +{ + boss_mage_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiFireBallTimer; + uint32 uiBlastWaveTimer; + uint32 uiHasteTimer; + uint32 uiPolymorphTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiFireBallTimer = 5000; + uiPolymorphTimer = 8000; + uiBlastWaveTimer = 12000; + uiHasteTimer = 22000; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (uiFireBallTimer <= uiDiff) + { + if (me->getVictim()) + DoCastVictim(SPELL_FIREBALL); + uiFireBallTimer = 5000; + } else uiFireBallTimer -= uiDiff; + + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiFireBallTimer <= uiDiff) + { + DoCastVictim(SPELL_FIREBALL); + uiFireBallTimer = 5000; + } else uiFireBallTimer -= uiDiff; + + if (uiPolymorphTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_POLYMORPH); + uiPolymorphTimer = 8000; + } else uiPolymorphTimer -= uiDiff; + + if (uiBlastWaveTimer <= uiDiff) + { + DoCastAOE(SPELL_BLAST_WAVE,false); + uiBlastWaveTimer = 13000; + } else uiBlastWaveTimer -= uiDiff; + + if (uiHasteTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + + DoCast(me,SPELL_HASTE); + uiHasteTimer = 22000; + } else uiHasteTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_mage_toc5(Creature* pCreature) +{ + return new boss_mage_toc5AI(pCreature); +} + +// Colosos && Runok Wildmane || Shaman +struct boss_shaman_toc5AI : public ScriptedAI +{ + boss_shaman_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiChainLightningTimer; + uint32 uiEartShieldTimer; + uint32 uiHealingWaveTimer; + uint32 uiHexMendingTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiChainLightningTimer = 16000; + uiHealingWaveTimer = 12000; + uiEartShieldTimer = urand(30000,35000); + uiHexMendingTimer = urand(20000,25000); + } + + void EnterCombat(Unit* pWho) + { + DoCast(me,SPELL_EARTH_SHIELD); + DoCast(pWho,SPELL_HEX_OF_MENDING); + }; + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiChainLightningTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_CHAIN_LIGHTNING); + + uiChainLightningTimer = 16000; + } else uiChainLightningTimer -= uiDiff; + + if (uiHealingWaveTimer <= uiDiff) + { + bool bChance = urand(0,1); + + if (!bChance) + { + if (Unit* pFriend = DoSelectLowestHpFriendly(40)) + DoCast(pFriend,SPELL_HEALING_WAVE); + } else + DoCast(me,SPELL_HEALING_WAVE); + + uiHealingWaveTimer = 12000; + } else uiHealingWaveTimer -= uiDiff; + + if (uiEartShieldTimer <= uiDiff) + { + DoCast(me,SPELL_EARTH_SHIELD); + + uiEartShieldTimer = urand(30000,35000); + } else uiEartShieldTimer -= uiDiff; + + if (uiHexMendingTimer <= uiDiff) + { + DoCastVictim(SPELL_HEX_OF_MENDING,true); + + uiHexMendingTimer = urand(20000,25000); + } else uiHexMendingTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_shaman_toc5(Creature* pCreature) +{ + return new boss_shaman_toc5AI(pCreature); +} + +// Jaelyne Evensong && Zul'tore || Hunter +struct boss_hunter_toc5AI : public ScriptedAI +{ + boss_hunter_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiShootTimer; + uint32 uiMultiShotTimer; + uint32 uiLightningArrowsTimer; + + uint64 uiTargetGUID; + + bool bShoot; + bool bDone; + bool bHome; + + void Reset() + { + uiShootTimer = 12000; + uiMultiShotTimer = 0; + uiLightningArrowsTimer = 7000; + + uiTargetGUID = 0; + + bShoot = false; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiLightningArrowsTimer <= uiDiff) + { + DoCastAOE(SPELL_LIGHTNING_ARROWS,false); + uiLightningArrowsTimer = 7000; + } else uiLightningArrowsTimer -= uiDiff; + + if (uiShootTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_FARTHEST,0,30.0f)) + { + uiTargetGUID = pTarget->GetGUID(); + DoCast(pTarget, SPELL_SHOOT); + } + uiShootTimer = 12000; + uiMultiShotTimer = 3000; + bShoot = true; + } else uiShootTimer -= uiDiff; + + if (bShoot && uiMultiShotTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + Unit* pTarget = Unit::GetUnit(*me, uiTargetGUID); + + if (pTarget && me->IsInRange(pTarget,5.0f,30.0f,false)) + { + DoCast(pTarget,SPELL_MULTI_SHOT); + } else + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,5.0f,30.0f,false)) + { + DoCast(pTarget,SPELL_MULTI_SHOT); + break; + } + } + } + } + bShoot = false; + } else uiMultiShotTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_hunter_toc5(Creature* pCreature) +{ + return new boss_hunter_toc5AI(pCreature); +} + +// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge +struct boss_rouge_toc5AI : public ScriptedAI +{ + boss_rouge_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + uint32 uiEviscerateTimer; + uint32 uiFanKivesTimer; + uint32 uiPosionBottleTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiEviscerateTimer = 8000; + uiFanKivesTimer = 14000; + uiPosionBottleTimer = 19000; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + } else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiEviscerateTimer <= uiDiff) + { + DoCast(me->getVictim(),SPELL_EVISCERATE); + uiEviscerateTimer = 8000; + } else uiEviscerateTimer -= uiDiff; + + if (uiFanKivesTimer <= uiDiff) + { + DoCastAOE(SPELL_FAN_OF_KNIVES,false); + uiFanKivesTimer = 14000; + } else uiFanKivesTimer -= uiDiff; + + if (uiPosionBottleTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_POISON_BOTTLE); + uiPosionBottleTimer = 19000; + } else uiPosionBottleTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_rouge_toc5(Creature* pCreature) +{ + return new boss_rouge_toc5AI(pCreature); +} + +void AddSC_boss_grand_champions() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "generic_vehicleAI_toc5"; + NewScript->GetAI = &GetAI_generic_vehicleAI_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_warrior_toc5"; + NewScript->GetAI = &GetAI_boss_warrior_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_mage_toc5"; + NewScript->GetAI = &GetAI_boss_mage_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_shaman_toc5"; + NewScript->GetAI = &GetAI_boss_shaman_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_hunter_toc5"; + NewScript->GetAI = &GetAI_boss_hunter_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_rouge_toc5"; + NewScript->GetAI = &GetAI_boss_rouge_toc5; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp new file mode 100644 index 00000000000..04b671ec11c --- /dev/null +++ b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* ScriptData +SDName: Instance Trial of the Champion +SDComment: +SDCategory: Trial Of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" + +#define MAX_ENCOUNTER 4 + +struct instance_trial_of_the_champion : public ScriptedInstance +{ + instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint8 uiMovementDone; + uint8 uiGrandChampionsDeaths; + uint8 uiArgentSoldierDeaths; + + uint64 uiAnnouncerGUID; + uint64 uiMainGateGUID; + uint64 uiGrandChampionVehicle1GUID; + uint64 uiGrandChampionVehicle2GUID; + uint64 uiGrandChampionVehicle3GUID; + uint64 uiGrandChampion1GUID; + uint64 uiGrandChampion2GUID; + uint64 uiGrandChampion3GUID; + uint64 uiChampionLootGUID; + uint64 uiArgentChampionGUID; + + std::list VehicleList; + + std::string str_data; + + bool bDone; + + void Initialize() + { + uiMovementDone = 0; + uiGrandChampionsDeaths = 0; + uiArgentSoldierDeaths = 0; + + uiAnnouncerGUID = 0; + uiMainGateGUID = 0; + uiGrandChampionVehicle1GUID = 0; + uiGrandChampionVehicle2GUID = 0; + uiGrandChampionVehicle3GUID = 0; + uiGrandChampion1GUID = 0; + uiGrandChampion2GUID = 0; + uiGrandChampion3GUID = 0; + uiChampionLootGUID = 0; + uiArgentChampionGUID = 0; + + bDone = false; + + VehicleList.clear(); + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + } + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + uint32 TeamInInstance = 0; + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + TeamInInstance = pPlayer->GetTeam(); + } + + switch(pCreature->GetEntry()) + { + // Champions + case VEHICLE_MOKRA_SKILLCRUSHER_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT, ALLIANCE); + break; + case VEHICLE_ERESSEA_DAWNSINGER_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_AMBROSE_BOLTSPARK_MOUNT, ALLIANCE); + break; + case VEHICLE_RUNOK_WILDMANE_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_COLOSOS_MOUNT, ALLIANCE); + break; + case VEHICLE_ZUL_TORE_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_EVENSONG_MOUNT, ALLIANCE); + break; + case VEHICLE_DEATHSTALKER_VESCERI_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_LANA_STOUTHAMMER_MOUNT, ALLIANCE); + break; + // Coliseum Announcer || Just NPC_JAEREN must be spawned. + case NPC_JAEREN: + uiAnnouncerGUID = pCreature->GetGUID(); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_ARELAS,ALLIANCE); + break; + case VEHICLE_ARGENT_WARHORSE: + case VEHICLE_ARGENT_BATTLEWORG: + VehicleList.push_back(pCreature->GetGUID()); + break; + case NPC_EADRIC: + case NPC_PALETRESS: + uiArgentChampionGUID = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGO, bool /*bAdd*/) + { + switch(pGO->GetEntry()) + { + case GO_MAIN_GATE: + uiMainGateGUID = pGO->GetGUID(); + break; + case GO_CHAMPIONS_LOOT: + case GO_CHAMPIONS_LOOT_H: + uiChampionLootGUID = pGO->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case DATA_MOVEMENT_DONE: + uiMovementDone = uiData; + if (uiMovementDone == 3) + { + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + pAnnouncer->AI()->SetData(DATA_IN_POSITION,0); + } + break; + case BOSS_GRAND_CHAMPIONS: + m_auiEncounter[0] = uiData; + if (uiData == IN_PROGRESS) + { + for (std::list::const_iterator itr = VehicleList.begin(); itr != VehicleList.end(); ++itr) + if (Creature* pSummon = instance->GetCreature(*itr)) + pSummon->RemoveFromWorld(); + }else if (uiData == DONE) + { + ++uiGrandChampionsDeaths; + if (uiGrandChampionsDeaths == 3) + { + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + } + } + break; + case DATA_ARGENT_SOLDIER_DEFEATED: + uiArgentSoldierDeaths = uiData; + if (uiArgentSoldierDeaths == 9) + { + if (Creature* pBoss = instance->GetCreature(uiArgentChampionGUID)) + { + pBoss->GetMotionMaster()->MovePoint(0,746.88,618.74,411.06); + pBoss->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pBoss->SetReactState(REACT_AGGRESSIVE); + } + } + break; + case BOSS_ARGENT_CHALLENGE_E: + m_auiEncounter[1] = uiData; + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + break; + case BOSS_ARGENT_CHALLENGE_P: + m_auiEncounter[2] = uiData; + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + break; + } + + if (uiData == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 uiData) + { + switch(uiData) + { + case BOSS_GRAND_CHAMPIONS: return m_auiEncounter[0]; + case BOSS_ARGENT_CHALLENGE_E: return m_auiEncounter[1]; + case BOSS_ARGENT_CHALLENGE_P: return m_auiEncounter[2]; + case BOSS_BLACK_KNIGHT: return m_auiEncounter[3]; + + case DATA_MOVEMENT_DONE: return uiMovementDone; + case DATA_ARGENT_SOLDIER_DEFEATED: return uiArgentSoldierDeaths; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_ANNOUNCER: return uiAnnouncerGUID; + case DATA_MAIN_GATE: return uiMainGateGUID; + + case DATA_GRAND_CHAMPION_1: return uiGrandChampion1GUID; + case DATA_GRAND_CHAMPION_2: return uiGrandChampion2GUID; + case DATA_GRAND_CHAMPION_3: return uiGrandChampion3GUID; + } + + return 0; + } + + void SetData64(uint32 uiType, uint64 uiData) + { + switch(uiType) + { + case DATA_GRAND_CHAMPION_1: + uiGrandChampion1GUID = uiData; + break; + case DATA_GRAND_CHAMPION_2: + uiGrandChampion2GUID = uiData; + break; + case DATA_GRAND_CHAMPION_3: + uiGrandChampion3GUID = uiData; + break; + } + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + saveStream << "T C " << m_auiEncounter[0] + << " " << m_auiEncounter[1] + << " " << m_auiEncounter[2] + << " " << m_auiEncounter[3] + << " " << uiGrandChampionsDeaths + << " " << uiMovementDone; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + + if (dataHead1 == 'T' && dataHead2 == 'C') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + uiGrandChampionsDeaths = data4; + uiMovementDone = data5; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_trial_of_the_champion(Map* pMap) +{ + return new instance_trial_of_the_champion(pMap); +} + +void AddSC_instance_trial_of_the_champion() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_trial_of_the_champion"; + newscript->GetInstanceData = &GetInstanceData_instance_trial_of_the_champion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp new file mode 100644 index 00000000000..090b64b96cc --- /dev/null +++ b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Trial Of the Champion +SD%Complete: +SDComment: +SDCategory: trial_of_the_champion +EndScriptData */ + +/* ContentData +npc_announcer_toc5 +EndContentData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" +#include "Vehicle.h" + +#define GOSSIP_START_EVENT1 "I'm ready to start challenge." +#define GOSSIP_START_EVENT2 "I'm ready for the next challenge." + +#define ORIENTATION 4.714 + +/*###### +## npc_announcer_toc5 +######*/ + +const Position SpawnPosition = {746.261,657.401,411.681,4.65}; + +struct npc_announcer_toc5AI : public ScriptedAI +{ + npc_announcer_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + uiSummonTimes = 0; + uiPosition = 0; + uiLesserChampions = 0; + + uiFirstBoss = 0; + uiSecondBoss = 0; + uiThirdBoss = 0; + + uiArgentChampion = 0; + + uiPhase = 0; + uiTimer = 0; + + uiVehicle1GUID = 0; + uiVehicle2GUID = 0; + uiVehicle3GUID = 0; + + Champion1List.clear(); + Champion2List.clear(); + Champion3List.clear(); + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + SetGrandChampionsForEncounter(); + SetArgentChampion(); + } + + ScriptedInstance* pInstance; + + uint8 uiSummonTimes; + uint8 uiPosition; + uint8 uiLesserChampions; + + uint32 uiArgentChampion; + + uint32 uiFirstBoss; + uint32 uiSecondBoss; + uint32 uiThirdBoss; + + uint32 uiPhase; + uint32 uiTimer; + + uint64 uiVehicle1GUID; + uint64 uiVehicle2GUID; + uint64 uiVehicle3GUID; + + uint64 uiGrandChampionBoss1; + + std::list Champion1List; + std::list Champion2List; + std::list Champion3List; + + void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) + { + uiTimer = uiTimerStep; + if (bNextStep) + ++uiPhase; + else + uiPhase = uiPhaseStep; + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch (uiType) + { + case DATA_START: + DoSummonGrandChampion(uiFirstBoss); + NextStep(10000,false,1); + break; + case DATA_IN_POSITION: //movement done. + me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); + if (GameObject* pGO = GameObject::GetGameObject(*me, pInstance->GetData64(DATA_MAIN_GATE))) + pInstance->HandleGameObject(pGO->GetGUID(),false); + NextStep(10000,false,3); + break; + case DATA_LESSER_CHAMPIONS_DEFEATED: + { + ++uiLesserChampions; + std::list TempList; + if (uiLesserChampions == 3 || uiLesserChampions == 6) + { + switch(uiLesserChampions) + { + case 3: + TempList = Champion2List; + break; + case 6: + TempList = Champion3List; + break; + } + + for (std::list::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr) + if (Creature* pSummon = Unit::GetCreature(*me, *itr)) + AggroAllPlayers(pSummon); + }else if (uiLesserChampions == 9) + StartGrandChampionsAttack(); + + break; + } + } + } + + void StartGrandChampionsAttack() + { + Creature* pGrandChampion1 = Unit::GetCreature(*me, uiVehicle1GUID); + Creature* pGrandChampion2 = Unit::GetCreature(*me, uiVehicle2GUID); + Creature* pGrandChampion3 = Unit::GetCreature(*me, uiVehicle3GUID); + + if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) + { + AggroAllPlayers(pGrandChampion1); + AggroAllPlayers(pGrandChampion2); + AggroAllPlayers(pGrandChampion3); + } + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (uiPointId == 1) + { + me->SetOrientation(ORIENTATION); + me->SendMovementFlagUpdate(); + } + } + + void DoSummonGrandChampion(uint32 uiBoss) + { + ++uiSummonTimes; + uint32 VEHICLE_TO_SUMMON1 = 0; + uint32 VEHICLE_TO_SUMMON2 = 0; + switch(uiBoss) + { + case 0: + VEHICLE_TO_SUMMON1 = VEHICLE_MOKRA_SKILLCRUSHER_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_ORGRIMMAR_WOLF; + break; + case 1: + VEHICLE_TO_SUMMON1 = VEHICLE_ERESSEA_DAWNSINGER_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_SILVERMOON_HAWKSTRIDER; + break; + case 2: + VEHICLE_TO_SUMMON1 = VEHICLE_RUNOK_WILDMANE_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_THUNDER_BLUFF_KODO; + break; + case 3: + VEHICLE_TO_SUMMON1 = VEHICLE_ZUL_TORE_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_DARKSPEAR_RAPTOR; + break; + case 4: + VEHICLE_TO_SUMMON1 = VEHICLE_DEATHSTALKER_VESCERI_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_FORSAKE_WARHORSE; + break; + default: + return; + } + + if (Creature* pBoss = me->SummonCreature(VEHICLE_TO_SUMMON1,SpawnPosition)) + { + switch(uiSummonTimes) + { + case 1: + { + uiVehicle1GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss1 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle1GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss1 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_1,uiVehicle1GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_1,uiGrandChampionBoss1); + } + pBoss->AI()->SetData(1,0); + break; + } + case 2: + { + uiVehicle2GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss2 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle2GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss2 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_2,uiVehicle2GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_2,uiGrandChampionBoss2); + } + pBoss->AI()->SetData(2,0); + break; + } + case 3: + { + uiVehicle3GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss3 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle3GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss3 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_3,uiVehicle3GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_3,uiGrandChampionBoss3); + } + pBoss->AI()->SetData(3,0); + break; + } + default: + return; + } + + for (uint8 i = 0; i < 3; ++i) + { + if (Creature* pAdd = me->SummonCreature(VEHICLE_TO_SUMMON2,SpawnPosition,TEMPSUMMON_CORPSE_DESPAWN)) + { + switch(uiSummonTimes) + { + case 1: + Champion1List.push_back(pAdd->GetGUID()); + break; + case 2: + Champion2List.push_back(pAdd->GetGUID()); + break; + case 3: + Champion3List.push_back(pAdd->GetGUID()); + break; + } + + switch(i) + { + case 0: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI); + break; + case 1: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2); + break; + case 2: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2 + M_PI); + break; + } + } + + } + } + } + + void DoStartArgentChampionEncounter() + { + me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); + + if (Creature* pBoss = me->SummonCreature(uiArgentChampion,SpawnPosition)) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_LIGHWIELDER,SpawnPosition)) + pTrash->AI()->SetData(i,0); + if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_MONK,SpawnPosition)) + pTrash->AI()->SetData(i,0); + if (Creature* pTrash = me->SummonCreature(NPC_PRIESTESS,SpawnPosition)) + pTrash->AI()->SetData(i,0); + } + } + } + + void SetGrandChampionsForEncounter() + { + uiFirstBoss = urand(0,4); + + while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss) + { + uiSecondBoss = urand(0,4); + uiThirdBoss = urand(0,4); + } + } + + void SetArgentChampion() + { + uint8 uiTempBoss = urand(0,1); + + switch(uiTempBoss) + { + case 0: + uiArgentChampion = NPC_EADRIC; + break; + case 1: + uiArgentChampion = NPC_PALETRESS; + break; + } + } + + void StartEncounter() + { + if (!pInstance) + return; + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + if (pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) + { + if (pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED) + { + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) + me->AI()->SetData(DATA_START,0); + + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE) + DoStartArgentChampionEncounter(); + } + + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) + me->SummonCreature(VEHICLE_BLACK_KNIGHT,769.834,651.915,447.035,0); + } + } + + void AggroAllPlayers(Creature* pTemp) + { + Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + pTemp->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(pTemp); + pTemp->AddThreat(pPlayer, 0.0f); + } + } + } + } + + + void UpdateAI(const uint32 uiDiff) + { + ScriptedAI::UpdateAI(uiDiff); + + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + DoSummonGrandChampion(uiSecondBoss); + NextStep(10000,true); + break; + case 2: + DoSummonGrandChampion(uiThirdBoss); + NextStep(0,false); + break; + case 3: + if (!Champion1List.empty()) + { + for (std::list::const_iterator itr = Champion1List.begin(); itr != Champion1List.end(); ++itr) + if (Creature* pSummon = Unit::GetCreature(*me, *itr)) + AggroAllPlayers(pSummon); + NextStep(0,false); + } + break; + } + } else uiTimer -= uiDiff; + + if (!UpdateVictim()) + return; + } + + void JustSummoned(Creature* pSummon) + { + if (pInstance && pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) + { + pSummon->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pSummon->SetReactState(REACT_PASSIVE); + } + } + + void SummonedCreatureDespawn(Creature* pSummon) + { + switch(pSummon->GetEntry()) + { + case VEHICLE_DARNASSIA_NIGHTSABER: + case VEHICLE_EXODAR_ELEKK: + case VEHICLE_STORMWIND_STEED: + case VEHICLE_GNOMEREGAN_MECHANOSTRIDER: + case VEHICLE_IRONFORGE_RAM: + case VEHICLE_FORSAKE_WARHORSE: + case VEHICLE_THUNDER_BLUFF_KODO: + case VEHICLE_ORGRIMMAR_WOLF: + case VEHICLE_SILVERMOON_HAWKSTRIDER: + case VEHICLE_DARKSPEAR_RAPTOR: + me->AI()->SetData(DATA_LESSER_CHAMPIONS_DEFEATED,0); + break; + } + } +}; + +CreatureAI* GetAI_npc_announcer_toc5(Creature* pCreature) +{ + return new npc_announcer_toc5AI(pCreature); +} + +bool GossipHello_npc_announcer_toc5(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && + pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && + pInstance->GetData(BOSS_BLACK_KNIGHT) == DONE && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) + return false; + + if (pInstance && + pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED && + pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + else if (pInstance) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_announcer_toc5(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_announcer_toc5AI, pCreature->AI())->StartEncounter(); + } + + return true; +} + +void AddSC_trial_of_the_champion() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "npc_announcer_toc5"; + NewScript->GetAI = &GetAI_npc_announcer_toc5; + NewScript->pGossipHello = &GossipHello_npc_announcer_toc5; + NewScript->pGossipSelect = &GossipSelect_npc_announcer_toc5; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h new file mode 100644 index 00000000000..221c7c0412f --- /dev/null +++ b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_TOC_H +#define DEF_TOC_H + + +enum eData +{ + BOSS_GRAND_CHAMPIONS, + BOSS_ARGENT_CHALLENGE_E, + BOSS_ARGENT_CHALLENGE_P, + BOSS_BLACK_KNIGHT, + DATA_MOVEMENT_DONE, + DATA_LESSER_CHAMPIONS_DEFEATED, + DATA_START, + DATA_IN_POSITION, + DATA_ARGENT_SOLDIER_DEFEATED +}; + +enum Data64 +{ + DATA_ANNOUNCER, + DATA_MAIN_GATE, + + DATA_GRAND_CHAMPION_VEHICLE_1, + DATA_GRAND_CHAMPION_VEHICLE_2, + DATA_GRAND_CHAMPION_VEHICLE_3, + + DATA_GRAND_CHAMPION_1, + DATA_GRAND_CHAMPION_2, + DATA_GRAND_CHAMPION_3 +}; + +enum eNpcs +{ + // Horde Champions + NPC_MOKRA = 35572, + NPC_ERESSEA = 35569, + NPC_RUNOK = 35571, + NPC_ZULTORE = 35570, + NPC_VISCERI = 35617, + + // Alliance Champions + NPC_JACOB = 34705, + NPC_AMBROSE = 34702, + NPC_COLOSOS = 34701, + NPC_JAELYNE = 34657, + NPC_LANA = 34703, + + NPC_EADRIC = 35119, + NPC_PALETRESS = 34928, + + NPC_ARGENT_LIGHWIELDER = 35309, + NPC_ARGENT_MONK = 35305, + NPC_PRIESTESS = 35307, + + NPC_BLACK_KNIGHT = 35451, + + NPC_RISEN_JAEREN = 35545, + NPC_RISEN_ARELAS = 35564, + + NPC_JAEREN = 35004, + NPC_ARELAS = 35005 +}; + +enum eGameObjects +{ + GO_MAIN_GATE = 195647, + + GO_CHAMPIONS_LOOT = 195709, + GO_CHAMPIONS_LOOT_H = 195710, + + GO_EADRIC_LOOT = 195374, + GO_EADRIC_LOOT_H = 195375, + + GO_PALETRESS_LOOT = 195323, + GO_PALETRESS_LOOT_H = 195324 +}; + +enum eVehicles +{ + //Grand Champions Alliance Vehicles + VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT = 35637, + VEHICLE_AMBROSE_BOLTSPARK_MOUNT = 35633, + VEHICLE_COLOSOS_MOUNT = 35768, + VEHICLE_EVENSONG_MOUNT = 34658, + VEHICLE_LANA_STOUTHAMMER_MOUNT = 35636, + //Faction Champions (ALLIANCE) + VEHICLE_DARNASSIA_NIGHTSABER = 33298, + VEHICLE_EXODAR_ELEKK = 33416, + VEHICLE_STORMWIND_STEED = 33297, + VEHICLE_GNOMEREGAN_MECHANOSTRIDER = 33301, + VEHICLE_IRONFORGE_RAM = 33408, + //Grand Champions Horde Vehicles + VEHICLE_MOKRA_SKILLCRUSHER_MOUNT = 35638, + VEHICLE_ERESSEA_DAWNSINGER_MOUNT = 35635, + VEHICLE_RUNOK_WILDMANE_MOUNT = 35640, + VEHICLE_ZUL_TORE_MOUNT = 35641, + VEHICLE_DEATHSTALKER_VESCERI_MOUNT = 35634, + //Faction Champions (HORDE) + VEHICLE_FORSAKE_WARHORSE = 33414, + VEHICLE_THUNDER_BLUFF_KODO = 33300, + VEHICLE_ORGRIMMAR_WOLF = 33409, + VEHICLE_SILVERMOON_HAWKSTRIDER = 33418, + VEHICLE_DARKSPEAR_RAPTOR = 33299, + + VEHICLE_ARGENT_WARHORSE = 35644, + VEHICLE_ARGENT_BATTLEWORG = 36558, + + VEHICLE_BLACK_KNIGHT = 35491 +}; + +#endif diff --git a/src/server/scripts/Northrend/crystalsong_forest.cpp b/src/server/scripts/Northrend/crystalsong_forest.cpp new file mode 100644 index 00000000000..208e9dea5b5 --- /dev/null +++ b/src/server/scripts/Northrend/crystalsong_forest.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: CrystalSongForest +SDAuthor: Malcrom +SD%Complete: 99% +SDComment: +SDCategory: CrystalsongForest +Script Data End */ + +#include "ScriptedPch.h" + +/******************************************************* + * npc_warmage_violetstand + *******************************************************/ + +enum Spells +{ + SPELL_TRANSITUS_SHIELD_BEAM = 48310 +}; + +enum NPCs +{ + NPC_TRANSITUS_SHIELD_DUMMY = 27306, + NPC_WARMAGE_SARINA = 32369, + NPC_WARMAGE_HALISTER = 32371, + NPC_WARMAGE_ILSUDRIA = 32372 +}; + +struct npc_warmage_violetstandAI : public Scripted_NoMovementAI +{ + npc_warmage_violetstandAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature){} + + uint64 uiTargetGUID; + + void Reset() + { + uiTargetGUID = 0; + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + if (me->GetEntry() == NPC_WARMAGE_SARINA) + { + if (!uiTargetGUID) + { + std::list orbList; + GetCreatureListWithEntryInGrid(orbList, me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f); + if (!orbList.empty()) + { + for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) + { + if (Creature* pOrb = *itr) + { + if (pOrb->GetPositionY() < 1000) + { + uiTargetGUID = pOrb->GetGUID(); + break; + } + } + } + } + } + }else + { + if (!uiTargetGUID) + if (Creature* pOrb = GetClosestCreatureWithEntry(me,NPC_TRANSITUS_SHIELD_DUMMY,32.0f)) + uiTargetGUID = pOrb->GetGUID(); + + } + + if (Creature* pOrb = me->GetCreature(*me,uiTargetGUID)) + DoCast(pOrb,SPELL_TRANSITUS_SHIELD_BEAM); + + } +}; + +CreatureAI* GetAI_npc_warmage_violetstand(Creature* pCreature) +{ + return new npc_warmage_violetstandAI(pCreature); +} + +void AddSC_crystalsong_forest() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_warmage_violetstand"; + newscript->GetAI = &GetAI_npc_warmage_violetstand; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/src/server/scripts/Northrend/dalaran.cpp b/src/server/scripts/Northrend/dalaran.cpp new file mode 100644 index 00000000000..7d5e76ffe35 --- /dev/null +++ b/src/server/scripts/Northrend/dalaran.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Dalaran +SDAuthor: WarHead, MaXiMiUS +SD%Complete: 99% +SDComment: For what is 63990+63991? Same function but don't work correct... +SDCategory: Dalaran +Script Data End */ + +#include "ScriptedPch.h" + +/******************************************************* + * npc_mageguard_dalaran + *******************************************************/ + +enum Spells +{ + SPELL_TRESPASSER_A = 54028, + SPELL_TRESPASSER_H = 54029 +}; + +enum NPCs // All outdoor guards are within 35.0f of these NPCs +{ + NPC_APPLEBOUGH_A = 29547, + NPC_SWEETBERRY_H = 29715, +}; + +struct npc_mageguard_dalaranAI : public Scripted_NoMovementAI +{ + npc_mageguard_dalaranAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_NORMAL, true); + pCreature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + } + + void Reset(){} + + void Aggro(Unit* /*pWho*/){} + + void AttackStart(Unit* /*pWho*/){} + + void MoveInLineOfSight(Unit *pWho) + { + if (!pWho || !pWho->IsInWorld() || pWho->GetZoneId() != 4395) + return; + + if (!me->IsWithinDist(pWho, 65.0f, false)) + return; + + Player *pPlayer = pWho->GetCharmerOrOwnerPlayerOrPlayerItself(); + + if (!pPlayer || pPlayer->isGameMaster() || pPlayer->IsBeingTeleported()) + return; + + switch (me->GetEntry()) + { + case 29254: + if (pPlayer->GetTeam() == HORDE) // Horde unit found in Alliance area + if (GetClosestCreatureWithEntry(me, NPC_APPLEBOUGH_A, 32.0f)) + { + if (me->isInBackInMap(pWho, 12.0f)) // In my line of sight, "outdoors", and behind me + DoCast(pWho, SPELL_TRESPASSER_A); // Teleport the Horde unit out + } + else // In my line of sight, and "indoors" + DoCast(pWho, SPELL_TRESPASSER_A); // Teleport the Horde unit out + break; + case 29255: + if (pPlayer->GetTeam() == ALLIANCE) // Alliance unit found in Horde area + if (GetClosestCreatureWithEntry(me, NPC_SWEETBERRY_H, 32.0f)) + { + if (me->isInBackInMap(pWho, 12.0f)) // In my line of sight, "outdoors", and behind me + DoCast(pWho, SPELL_TRESPASSER_H); // Teleport the Alliance unit out + } + else // In my line of sight, and "indoors" + DoCast(pWho, SPELL_TRESPASSER_H); // Teleport the Alliance unit out + break; + } + me->SetOrientation(me->GetHomePosition().GetOrientation()); + return; + } + + void UpdateAI(const uint32 /*diff*/){} +}; + +CreatureAI* GetAI_npc_mageguard_dalaran(Creature* pCreature) +{ + return new npc_mageguard_dalaranAI(pCreature); +} + +/*###### +## npc_hira_snowdawn +######*/ + +enum eHiraSnowdawn +{ + SPELL_COLD_WEATHER_FLYING = 54197 +}; + +#define GOSSIP_TEXT_TRAIN_HIRA "I seek training to ride a steed." + +bool GossipHello_npc_hira_snowdawn(Player* pPlayer, Creature* pCreature) +{ + if (!pCreature->isVendor() || !pCreature->isTrainer()) + return false; + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_TRAIN_HIRA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + if (pPlayer->getLevel() >= 80 && pPlayer->HasSpell(SPELL_COLD_WEATHER_FLYING)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_hira_snowdawn(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRAIN) + pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); + + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +void AddSC_dalaran() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_mageguard_dalaran"; + newscript->GetAI = &GetAI_npc_mageguard_dalaran; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_hira_snowdawn"; + newscript->pGossipHello = &GossipHello_npc_hira_snowdawn; + newscript->pGossipSelect = &GossipSelect_npc_hira_snowdawn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/dragonblight.cpp b/src/server/scripts/Northrend/dragonblight.cpp new file mode 100644 index 00000000000..4f26ec1de1a --- /dev/null +++ b/src/server/scripts/Northrend/dragonblight.cpp @@ -0,0 +1,272 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Dragonblight +SD%Complete: 100 +SDComment: +SDCategory: Dragonblight +EndScriptData */ + +/* ContentData +npc_alexstrasza_wr_gate +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +enum eEnums +{ + QUEST_RETURN_TO_AG_A = 12499, + QUEST_RETURN_TO_AG_H = 12500, + MOVIE_ID_GATES = 14 +}; + +#define GOSSIP_ITEM_WHAT_HAPPENED "Alexstrasza, can you show me what happened here?" + +bool GossipHello_npc_alexstrasza_wr_gate(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestRewardStatus(QUEST_RETURN_TO_AG_A) || pPlayer->GetQuestRewardStatus(QUEST_RETURN_TO_AG_H)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WHAT_HAPPENED, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_alexstrasza_wr_gate(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->SendMovieStart(MOVIE_ID_GATES); + } + + return true; +} + +/*###### +## npc_inquisitor_hallard. Quest 12321 +######*/ + + +enum eInquisitor +{ + NPC_GODFREY = 27577, + SPELL_HOLY_FIRE = 39323, + + SAY_WP_0 = -1800014, + SAY_WP_1 = -1800015, + SAY_WP_2 = -1800016, + SAY_WP_3 = -1800017, + SAY_WP_4 = -1800018, + SAY_WP_5 = -1800019, + SAY_WP_6 = -1800020, + SAY_WP_7 = -1800021, + SAY_WP_8 = -1800022, + SAY_WP_9 = -1800023, + SAY_WP_10 = -1800024, + SAY_WP_11 = -1800025, + SAY_WP_12 = -1800026, + SAY_WP_13 = -1800027, + SAY_WP_14 = -1800028, + SAY_WP_15 = -1800029, + SAY_WP_16 = -1800030, + SAY_WP_17 = -1800031, + SAY_WP_18 = -1800032, + SAY_WP_19 = -1800033, + SAY_WP_20 = -1800034, + SAY_WP_21 = -1800035, + SAY_WP_22 = -1800036, + SAY_WP_23 = -1800037, + SAY_WP_24 = -1800038, + SAY_WP_25 = -1800039, + SAY_WP_26 = -1800040, + SAY_WP_27 = -1800041 +}; + +#define QUEST_A_RIGHTEOUS_SERMON 12321 + +struct npc_inquisitor_hallardAI : public npc_escortAI +{ + npc_inquisitor_hallardAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + bool Completed; + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + if (!pPlayer) + return; + Creature* Godfrey = me->FindNearestCreature(NPC_GODFREY, 50, true); + if (!Godfrey) + return; + switch (i) + { + case 1: + DoScriptText(SAY_WP_1, me, Godfrey); + me->SetUInt64Value(UNIT_FIELD_TARGET, Godfrey->GetGUID()); + me->HandleEmoteCommand(5); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + case 2: + Godfrey->HandleEmoteCommand(434); + DoScriptText(SAY_WP_2, me, Godfrey); + me->HandleEmoteCommand(15); + break; + case 3: + DoScriptText(SAY_WP_3, me, Godfrey); + me->HandleEmoteCommand(1); + break; + case 4: + DoScriptText(SAY_WP_4, Godfrey); + break; + case 5: + DoScriptText(SAY_WP_5, Godfrey); + break; + case 6: + DoScriptText(SAY_WP_6, Godfrey); + break; + case 7: + DoScriptText(SAY_WP_7, me, Godfrey); + me->HandleEmoteCommand(1); + break; + case 8: + DoScriptText(SAY_WP_8, me, Godfrey); + me->HandleEmoteCommand(16); + break; + case 9: + DoScriptText(SAY_WP_9, me, Godfrey); + me->HandleEmoteCommand(5); + break; + case 10: + DoScriptText(SAY_WP_10, me, Godfrey); + DoCast(Godfrey, SPELL_HOLY_FIRE); + break; + case 11: + Godfrey->HandleEmoteCommand(434); + DoScriptText(SAY_WP_11, Godfrey); + break; + case 12: + DoScriptText(SAY_WP_12, me, Godfrey); + DoCast(Godfrey, SPELL_HOLY_FIRE); + break; + case 13: + DoScriptText(SAY_WP_13, me, Godfrey); + DoCast(Godfrey, SPELL_HOLY_FIRE); + break; + case 14: + Godfrey->HandleEmoteCommand(434); + DoScriptText(SAY_WP_14, Godfrey); + break; + case 15: + DoScriptText(SAY_WP_15, me, Godfrey); + DoCast(Godfrey, SPELL_HOLY_FIRE); + break; + case 16: + DoScriptText(SAY_WP_16, me, Godfrey); + break; + case 17: + DoScriptText(SAY_WP_17, me, Godfrey); + break; + case 18: + DoScriptText(SAY_WP_18, Godfrey); + break; + case 19: + DoScriptText(SAY_WP_19, me, Godfrey); + break; + case 20: + DoScriptText(SAY_WP_20, Godfrey); + break; + case 21: + DoScriptText(SAY_WP_21, Godfrey); + break; + case 22: + DoScriptText(SAY_WP_22, me, Godfrey); + break; + case 23: + DoScriptText(SAY_WP_23, Godfrey); + break; + case 24: + DoScriptText(SAY_WP_24, Godfrey); + break; + case 25: + DoScriptText(SAY_WP_25, me, Godfrey); + break; + case 26: + DoScriptText(SAY_WP_26, me); + me->SetUInt64Value(UNIT_FIELD_TARGET, pPlayer->GetGUID()); + break; + case 27: + DoScriptText(SAY_WP_27, me, Godfrey); + me->SetUInt64Value(UNIT_FIELD_TARGET, Godfrey->GetGUID()); + Completed = true; + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_A_RIGHTEOUS_SERMON, me); + break; + } + } + + void Reset() + { + Completed = false; + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; + +bool QuestAccept_npc_inquisitor_hallard(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_A_RIGHTEOUS_SERMON) + { + DoScriptText(SAY_WP_0, pCreature, pPlayer); + if (npc_escortAI* pEscortAI = CAST_AI(npc_inquisitor_hallardAI, pCreature->AI())) + { + pEscortAI->Start(true, false, pPlayer->GetGUID(), 0, true); + pCreature->GetMotionMaster()->MovePoint(0, 3801.543, -679.350, 213.75); + } + } + return true; +} + +CreatureAI* GetAI_npc_inquisitor_hallard(Creature* pCreature) +{ + return new npc_inquisitor_hallardAI(pCreature); +} + +void AddSC_dragonblight() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_alexstrasza_wr_gate"; + newscript->pGossipHello = &GossipHello_npc_alexstrasza_wr_gate; + newscript->pGossipSelect = &GossipSelect_npc_alexstrasza_wr_gate; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_inquisitor_hallard"; + newscript->GetAI = &GetAI_npc_inquisitor_hallard; + newscript->pQuestAccept = &QuestAccept_npc_inquisitor_hallard; + newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp b/src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp new file mode 100644 index 00000000000..ba64a4748dd --- /dev/null +++ b/src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2008 - 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: MAYBE need more improve the "Raptor Call". + */ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +enum eSpells +{ + SPELL_BELLOWING_ROAR = 22686, // fears the group, can be resisted/dispelled + SPELL_GRIEVOUS_BITE = 48920, + SPELL_MANGLING_SLASH = 48873, //casted on the current tank, adds debuf + SPELL_FEARSOME_ROAR = 48849, + H_SPELL_FEARSOME_ROAR = 59422, //Not stacking, debuff + SPELL_PIERCING_SLASH = 48878, //debuff -->Armor reduced by 75% + SPELL_RAPTOR_CALL = 59416, //dummy + SPELL_GUT_RIP = 49710, + SPELL_REND = 13738 +}; + +enum eArchivements +{ + ACHIEV_BETTER_OFF_DRED = 2039 +}; + +enum Creatures +{ + NPC_RAPTOR_1 = 26641, + NPC_RAPTOR_2 = 26628 +}; + +struct boss_dredAI : public ScriptedAI +{ + boss_dredAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBellowingRoarTimer; + uint32 uiGrievousBiteTimer; + uint32 uiManglingSlashTimer; + uint32 uiFearsomeRoarTimer; + uint32 uiPiercingSlashTimer; + uint32 uiRaptorCallTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + { + pInstance->SetData(DATA_DRED_EVENT,NOT_STARTED); + pInstance->SetData(DATA_KING_DRED_ACHIEV, 0); + } + + uiBellowingRoarTimer = 33*IN_MILISECONDS; + uiGrievousBiteTimer = 20*IN_MILISECONDS; + uiManglingSlashTimer = 18.5*IN_MILISECONDS; + uiFearsomeRoarTimer = urand(10*IN_MILISECONDS,20*IN_MILISECONDS); + uiPiercingSlashTimer = 17*IN_MILISECONDS; + uiRaptorCallTimer = urand(20*IN_MILISECONDS,25*IN_MILISECONDS); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_DRED_EVENT,IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBellowingRoarTimer < diff) + { + DoCastAOE(SPELL_BELLOWING_ROAR, false); + uiBellowingRoarTimer = 40*IN_MILISECONDS; + } else uiBellowingRoarTimer -=diff; + + if (uiGrievousBiteTimer < diff) + { + DoCastVictim(SPELL_GRIEVOUS_BITE ,false); + uiGrievousBiteTimer = 20*IN_MILISECONDS; + } else uiGrievousBiteTimer -=diff; + + if (uiManglingSlashTimer < diff) + { + DoCastVictim(SPELL_MANGLING_SLASH,false); + uiManglingSlashTimer = 20*IN_MILISECONDS; + } else uiManglingSlashTimer -=diff; + + if (uiFearsomeRoarTimer < diff) + { + DoCastAOE(SPELL_FEARSOME_ROAR,false); + uiFearsomeRoarTimer = urand(16*IN_MILISECONDS,18*IN_MILISECONDS); + } else uiFearsomeRoarTimer -=diff; + + if (uiPiercingSlashTimer < diff) + { + DoCastVictim(SPELL_PIERCING_SLASH,false); + uiPiercingSlashTimer = 20*IN_MILISECONDS; + } else uiPiercingSlashTimer -=diff; + + if (uiRaptorCallTimer < diff) + { + DoCastVictim(SPELL_RAPTOR_CALL,false); + + float x,y,z; + + me->GetClosePoint(x,y,z,me->GetObjectSize()/3,10.0f); + me->SummonCreature(RAND(NPC_RAPTOR_1,NPC_RAPTOR_2),x,y,z,0,TEMPSUMMON_DEAD_DESPAWN,1*IN_MILISECONDS); + + uiRaptorCallTimer = urand(20*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiRaptorCallTimer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_DRED_EVENT,DONE); + + if (IsHeroic() && pInstance->GetData(DATA_KING_DRED_ACHIEV) == 6) + pInstance->DoCompleteAchievement(ACHIEV_BETTER_OFF_DRED); + } + } +}; + +CreatureAI* GetAI_boss_dred(Creature* pCreature) +{ + return new boss_dredAI (pCreature); +} + +struct npc_drakkari_gutripperAI : public ScriptedAI +{ + npc_drakkari_gutripperAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 GutRipTimer; + + void Reset() + { + GutRipTimer = urand(10000,15000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (GutRipTimer < diff) + { + DoCastVictim(SPELL_GUT_RIP,false); + GutRipTimer = urand(10000,15000); + }else GutRipTimer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (IsHeroic() && pInstance->GetData(DATA_DRED_EVENT) == IN_PROGRESS && pInstance->GetData(DATA_KING_DRED_ACHIEV) < 6) + { + pInstance->SetData(DATA_KING_DRED_ACHIEV, pInstance->GetData(DATA_KING_DRED_ACHIEV) + 1); + } + } + } +}; + +CreatureAI* GetAI_npc_drakkari_gutripper(Creature* pCreature) +{ + return new npc_drakkari_gutripperAI (pCreature); +} + +struct npc_drakkari_scytheclawAI : public ScriptedAI +{ + npc_drakkari_scytheclawAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiRendTimer; + + void Reset() + { + uiRendTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiRendTimer < diff) + { + DoCastVictim(SPELL_REND,false); + uiRendTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + }else uiRendTimer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (IsHeroic() && pInstance->GetData(DATA_DRED_EVENT) == IN_PROGRESS && pInstance->GetData(DATA_KING_DRED_ACHIEV) < 6) + { + pInstance->SetData(DATA_KING_DRED_ACHIEV, pInstance->GetData(DATA_KING_DRED_ACHIEV) + 1); + } + } + } +}; + +CreatureAI* GetAI_npc_drakkari_scytheclaw(Creature* pCreature) +{ + return new npc_drakkari_scytheclawAI (pCreature); +} + +void AddSC_boss_dred() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_drakkari_gutripper"; + newscript->GetAI = &GetAI_npc_drakkari_gutripper; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_drakkari_scytheclaw"; + newscript->GetAI = &GetAI_npc_drakkari_scytheclaw; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_dred"; + newscript->GetAI = &GetAI_boss_dred; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp b/src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp new file mode 100644 index 00000000000..5e8792c352d --- /dev/null +++ b/src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp @@ -0,0 +1,328 @@ +/* +* Copyright (C) 2008 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +enum Spells +{ + SPELL_ARCANE_BLAST = 49198, + H_SPELL_ARCANE_BLAST = 59909, + SPELL_ARCANE_FIELD = 47346, + SPELL_BLIZZARD = 49034, + H_SPELL_BLIZZARD = 59854, + SPELL_FROSTBOLT = 49037, + H_SPELL_FROSTBOLT = 59855, + SPELL_WRATH_OF_MISERY = 50089, + H_SPELL_WRATH_OF_MISERY = 59856, + SPELL_SUMMON_MINIONS = 59910 //Summons an army of Fetid Troll Corpses to assist the caster. +}; +//not in db +enum Yells +{ + SAY_AGGRO = -1600000, + SAY_KILL = -1600001, + SAY_DEATH = -1600002, + SAY_NECRO_ADD = -1600003, + SAY_REUBBLE_1 = -1600004, + SAY_REUBBLE_2 = -1600005 +}; +enum Creatures +{ + CREATURE_RISEN_SHADOWCASTER = 27600, + CREATURE_FETID_TROLL_CORPSE = 27598, + CREATURE_HULKING_CORPSE = 27597, + CREATURE_CRYSTAL_HANDLER = 26627 +}; +enum CombatPhase +{ + IDLE, + PHASE_1, + PHASE_2 +}; +enum Achievements +{ + ACHIEV_OH_NOVOS = 2057 +}; + +static Position AddSpawnPoint = { -379.20, -816.76, 59.70 }; +static Position CrystalHandlerSpawnPoint = { -326.626343, -709.956604, 27.813314 }; +static Position AddDestinyPoint = { -379.314545, -772.577637, 28.58837 }; + +struct boss_novosAI : public Scripted_NoMovementAI +{ + boss_novosAI(Creature *c) : Scripted_NoMovementAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiTimer; + uint32 uiCrystalHandlerTimer; + + bool bAchiev; + + SummonList lSummons; + + std::list luiCrystals; + + CombatPhase Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + Phase = IDLE; + luiCrystals.clear(); + bAchiev = true; + me->CastStop(); + lSummons.DespawnAll(); + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (pInstance) + { + pInstance->SetData(DATA_NOVOS_EVENT, NOT_STARTED); + luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_1)); + luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_2)); + luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_3)); + luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_4)); + for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) + { + if (GameObject* pTemp = pInstance->instance->GetGameObject(*itr)) + pTemp->SetGoState(GO_STATE_READY); + } + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + Phase = PHASE_1; + uiCrystalHandlerTimer = 30*IN_MILISECONDS; + uiTimer = 1*IN_MILISECONDS; + DoCast(SPELL_ARCANE_FIELD); + if (pInstance) + { + for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) + { + if (GameObject *pTemp = pInstance->instance->GetGameObject(*itr)) + pTemp->SetGoState(GO_STATE_ACTIVE); + } + pInstance->SetData(DATA_NOVOS_EVENT, IN_PROGRESS); + } + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void UpdateAI(const uint32 diff) + { + switch (Phase) + { + case PHASE_1: + if (uiTimer <= diff) + { + Creature *pSummon = me->SummonCreature(RAND(CREATURE_FETID_TROLL_CORPSE,CREATURE_HULKING_CORPSE,CREATURE_RISEN_SHADOWCASTER), AddSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); + pSummon->GetMotionMaster()->MovePoint(0, AddDestinyPoint); + //If spell is casted stops casting arcane field so no spell casting + //DoCast(me, SPELL_SUMMON_MINIONS); + uiTimer = 3*IN_MILISECONDS; + } else uiTimer -= diff; + if (uiCrystalHandlerTimer <= diff) + { + DoScriptText(SAY_NECRO_ADD, me); + Creature *pCrystalHandler = me->SummonCreature(CREATURE_CRYSTAL_HANDLER, CrystalHandlerSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); + pCrystalHandler->GetMotionMaster()->MovePoint(0, AddDestinyPoint); + uiCrystalHandlerTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiCrystalHandlerTimer -= diff; + break; + case PHASE_2: + if (uiTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, DUNGEON_MODE(RAND(SPELL_ARCANE_BLAST,SPELL_BLIZZARD,SPELL_FROSTBOLT,SPELL_WRATH_OF_MISERY), + RAND(H_SPELL_ARCANE_BLAST,H_SPELL_BLIZZARD,H_SPELL_FROSTBOLT,H_SPELL_WRATH_OF_MISERY))); + uiTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); + } else uiTimer -= diff; + break; + } + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + { + pInstance->SetData(DATA_NOVOS_EVENT, DONE); + + if (IsHeroic() && bAchiev) + pInstance->DoCompleteAchievement(ACHIEV_OH_NOVOS); + } + lSummons.DespawnAll(); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(SAY_KILL, me); + } + + void JustSummoned(Creature *summon) + { + lSummons.Summon(summon); + } + + void RemoveCrystal() + { + if (!luiCrystals.empty()) + { + if (pInstance) + if (GameObject *pTemp = pInstance->instance->GetGameObject(luiCrystals.back())) + pTemp->SetGoState(GO_STATE_READY); + luiCrystals.pop_back(); + } + if (luiCrystals.empty()) + { + me->CastStop(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Phase = PHASE_2; + uiTimer = 1*IN_MILISECONDS; + } + } + + Unit* GetRandomTarget() + { + return SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + } +}; + +enum CrystalHandlerSpells +{ + SPELL_FLASH_OF_DARKNESS = 49668, + H_SPELL_FLASH_OF_DARKNESS = 59004 +}; + +struct mob_crystal_handlerAI : public ScriptedAI +{ + mob_crystal_handlerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiFlashOfDarknessTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiFlashOfDarknessTimer = 5*IN_MILISECONDS; + } + + void JustDied(Unit* /*killer*/) + { + if (Creature* pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) + CAST_AI(boss_novosAI,pNovos->AI())->RemoveCrystal(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiFlashOfDarknessTimer <= diff) + { + DoCast(me->getVictim(), DUNGEON_MODE(SPELL_FLASH_OF_DARKNESS,H_SPELL_FLASH_OF_DARKNESS)); + uiFlashOfDarknessTimer = 5*IN_MILISECONDS; + } else uiFlashOfDarknessTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || id != 0) + return; + if (Creature *pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) + if (Unit *pTarget = CAST_AI(boss_novosAI, pNovos->AI())->GetRandomTarget()) + AttackStart(pTarget); + } +}; + +struct mob_novos_minionAI : public ScriptedAI +{ + mob_novos_minionAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || id !=0) + return; + if (Creature* pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) + { + CAST_AI(boss_novosAI, pNovos->AI())->bAchiev = false; + if (Unit *pTarget = CAST_AI(boss_novosAI, pNovos->AI())->GetRandomTarget()) + AttackStart(pTarget); + } + } +}; + +CreatureAI* GetAI_boss_novos(Creature* pCreature) +{ + return new boss_novosAI (pCreature); +} + +CreatureAI* GetAI_mob_crystal_handler(Creature* pCreature) +{ + return new mob_crystal_handlerAI (pCreature); +} + +CreatureAI* GetAI_mob_novos_minion(Creature* pCreature) +{ + return new mob_novos_minionAI (pCreature); +} + +void AddSC_boss_novos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_novos"; + newscript->GetAI = &GetAI_boss_novos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crystal_handler"; + newscript->GetAI = &GetAI_mob_crystal_handler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_novos_minion"; + newscript->GetAI = &GetAI_mob_novos_minion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp b/src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp new file mode 100644 index 00000000000..1e60dfc6135 --- /dev/null +++ b/src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp @@ -0,0 +1,260 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +enum Spells +{ + //skeletal spells (phase 1) + SPELL_CURSE_OF_LIFE = 49527, + H_SPELL_CURSE_OF_LIFE = 59972, + SPELL_RAIN_OF_FIRE = 49518, + H_SPELL_RAIN_OF_FIRE = 59971, + SPELL_SHADOW_VOLLEY = 49528, + H_SPELL_SHADOW_VOLLEY = 59973, + SPELL_DECAY_FLESH = 49356, //casted at end of phase 1, starts phase 2 + //flesh spells (phase 2) + SPELL_GIFT_OF_THARON_JA = 52509, + SPELL_EYE_BEAM = 49544, + H_SPELL_EYE_BEAM = 59965, + SPELL_LIGHTNING_BREATH = 49537, + H_SPELL_LIGHTNING_BREATH = 59963, + SPELL_POISON_CLOUD = 49548, + H_SPELL_POISON_CLOUD = 59969, + SPELL_RETURN_FLESH = 53463, //Channeled spell ending phase two and returning to phase 1. This ability will stun the party for 6 seconds. + SPELL_ACHIEVEMENT_CHECK = 61863, +}; + +enum Yells +{ + SAY_AGGRO = -1600011, + SAY_KILL_1 = -1600012, + SAY_KILL_2 = -1600013, + SAY_FLESH_1 = -1600014, + SAY_FLESH_2 = -1600015, + SAY_SKELETON_1 = -1600016, + SAY_SKELETON_2 = -1600017, + SAY_DEATH = -1600018 +}; +enum Models +{ + MODEL_FLESH = 27073, + MODEL_SKELETON = 27511 +}; +enum CombatPhase +{ + SKELETAL, + GOING_FLESH, + FLESH, + GOING_SKELETAL +}; + +struct boss_tharon_jaAI : public ScriptedAI +{ + boss_tharon_jaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiPhaseTimer; + uint32 uiCurseOfLifeTimer; + uint32 uiRainOfFireTimer; + uint32 uiShadowVolleyTimer; + uint32 uiEyeBeamTimer; + uint32 uiLightningBreathTimer; + uint32 uiPoisonCloudTimer; + + CombatPhase Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + uiPhaseTimer = 20*IN_MILISECONDS; + uiCurseOfLifeTimer = 1*IN_MILISECONDS; + uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); + uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); + Phase = SKELETAL; + me->SetDisplayId(me->GetNativeDisplayId()); + if (pInstance) + pInstance->SetData(DATA_THARON_JA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_THARON_JA_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + switch (Phase) + { + case SKELETAL: + if (uiCurseOfLifeTimer < diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CURSE_OF_LIFE); + uiCurseOfLifeTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiCurseOfLifeTimer -= diff; + + if (uiShadowVolleyTimer < diff) + { + DoCastVictim(SPELL_SHADOW_VOLLEY); + uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); + } else uiShadowVolleyTimer -= diff; + + if (uiRainOfFireTimer < diff) + { + DoCastAOE(SPELL_RAIN_OF_FIRE); + uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); + } else uiRainOfFireTimer -= diff; + + if (uiPhaseTimer < diff) + { + DoCast(SPELL_DECAY_FLESH); + Phase = GOING_FLESH; + uiPhaseTimer = 6*IN_MILISECONDS; + } else uiPhaseTimer -= diff; + + DoMeleeAttackIfReady(); + break; + case GOING_FLESH: + if (uiPhaseTimer < diff) + { + DoScriptText(RAND(SAY_FLESH_1,SAY_FLESH_2),me); + me->SetDisplayId(MODEL_FLESH); + std::list& threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + Unit *pTemp = Unit::GetUnit((*me),(*itr)->getUnitGuid()); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) + { + me->AddAura(SPELL_GIFT_OF_THARON_JA,pTemp); + pTemp->SetDisplayId(MODEL_SKELETON); + } + } + uiPhaseTimer = 20*IN_MILISECONDS; + uiLightningBreathTimer = urand(3*IN_MILISECONDS,4*IN_MILISECONDS); + uiEyeBeamTimer = urand(4*IN_MILISECONDS,8*IN_MILISECONDS); + uiPoisonCloudTimer = urand(6*IN_MILISECONDS,7*IN_MILISECONDS); + Phase = FLESH; + } else uiPhaseTimer -= diff; + break; + case FLESH: + if (uiLightningBreathTimer < diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_LIGHTNING_BREATH); + uiLightningBreathTimer = urand(6*IN_MILISECONDS,7*IN_MILISECONDS); + } else uiLightningBreathTimer -= diff; + + if (uiEyeBeamTimer < diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_EYE_BEAM); + uiEyeBeamTimer = urand(4*IN_MILISECONDS,6*IN_MILISECONDS); + } else uiEyeBeamTimer -= diff; + + if (uiPoisonCloudTimer < diff) + { + DoCastAOE(SPELL_POISON_CLOUD); + uiPoisonCloudTimer = urand(10*IN_MILISECONDS,12*IN_MILISECONDS); + } else uiPoisonCloudTimer -= diff; + + if (uiPhaseTimer < diff) + { + DoCast(SPELL_RETURN_FLESH); + Phase = GOING_SKELETAL; + uiPhaseTimer = 6*IN_MILISECONDS; + } else uiPhaseTimer -= diff; + DoMeleeAttackIfReady(); + break; + case GOING_SKELETAL: + if (uiPhaseTimer < diff) + { + DoScriptText(RAND(SAY_SKELETON_1,SAY_SKELETON_2), me); + me->DeMorph(); + Phase = SKELETAL; + uiPhaseTimer = 20*IN_MILISECONDS; + uiCurseOfLifeTimer = 1*IN_MILISECONDS; + uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); + uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); + std::list& threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + Unit *pTemp = Unit::GetUnit((*me),(*itr)->getUnitGuid()); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) + { + if (pTemp->HasAura(SPELL_GIFT_OF_THARON_JA)) + pTemp->RemoveAura(SPELL_GIFT_OF_THARON_JA); + pTemp->DeMorph(); + } + } + } else uiPhaseTimer -= diff; + break; + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2),me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH,me); + + if (pInstance) + { + // clean morph on players + Map::PlayerList const &PlayerList = pInstance->instance->GetPlayers(); + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player *pPlayer = i->getSource()) + pPlayer->DeMorph(); + // cast is not rewarding the achievement. + // DoCast(SPELL_ACHIEVEMENT_CHECK); + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, SPELL_ACHIEVEMENT_CHECK); + + pInstance->SetData(DATA_THARON_JA_EVENT, DONE); + } + } +}; + +CreatureAI* GetAI_boss_tharon_ja(Creature* pCreature) +{ + return new boss_tharon_jaAI (pCreature); +} + +void AddSC_boss_tharon_ja() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_tharon_ja"; + newscript->GetAI = &GetAI_boss_tharon_ja; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp b/src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp new file mode 100644 index 00000000000..03eac73385d --- /dev/null +++ b/src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: TODO: spawn troll waves + */ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +enum Spells +{ + SPELL_INFECTED_WOUND = 49637, + SPELL_CRUSH = 49639, + SPELL_CORPSE_EXPLODE = 49555, + SPELL_CONSUME = 49380, + SPELL_CONSUME_AURA = 49381, + //Heroic spells + H_SPELL_CORPSE_EXPLODE = 59807, + H_SPELL_CONSUME = 59803, + H_SPELL_CONSUME_AURA = 59805, +}; +enum Yells +{ + SAY_AGGRO = -1600006, + SAY_KILL = -1600007, + SAY_CONSUME = -1600008, + SAY_EXPLODE = -1600009, + SAY_DEATH = -1600010 +}; +enum Achievements +{ + ACHIEV_CONSUMPTION_JUNCTION = 2151 +}; +enum Creatures +{ + NPC_DRAKKARI_INVADER_1 = 27753, + NPC_DRAKKARI_INVADER_2 = 27709 +}; + +Position AddSpawnPoint = { -260.493011, -622.968018, 26.605301, 3.036870 }; + +struct boss_trollgoreAI : public ScriptedAI +{ + boss_trollgoreAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiConsumeTimer; + uint32 uiAuraCountTimer; + uint32 uiCrushTimer; + uint32 uiInfectedWoundTimer; + uint32 uiExplodeCorpseTimer; + uint32 uiSpawnTimer; + + bool bAchiev; + + SummonList lSummons; + + ScriptedInstance* pInstance; + + void Reset() + { + uiConsumeTimer = 15*IN_MILISECONDS; + uiAuraCountTimer = 15.5*IN_MILISECONDS; + uiCrushTimer = urand(1*IN_MILISECONDS,5*IN_MILISECONDS); + uiInfectedWoundTimer = urand(60*IN_MILISECONDS,10*IN_MILISECONDS); + uiExplodeCorpseTimer = 3*IN_MILISECONDS; + uiSpawnTimer = urand(30*IN_MILISECONDS,40*IN_MILISECONDS); + + bAchiev = IsHeroic(); + + lSummons.DespawnAll(); + + me->RemoveAura(DUNGEON_MODE(SPELL_CONSUME_AURA,H_SPELL_CONSUME_AURA)); + + if (pInstance) + pInstance->SetData(DATA_TROLLGORE_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_TROLLGORE_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiSpawnTimer <= diff) + { + uint32 spawnNumber = urand(2,DUNGEON_MODE(3,5)); + for (uint8 i = 0; i < spawnNumber; ++i) + DoSummon(RAND(NPC_DRAKKARI_INVADER_1,NPC_DRAKKARI_INVADER_2), AddSpawnPoint, 0, TEMPSUMMON_DEAD_DESPAWN); + uiSpawnTimer = urand(30*IN_MILISECONDS,40*IN_MILISECONDS); + } else uiSpawnTimer -= diff; + + if (uiConsumeTimer <= diff) + { + DoScriptText(SAY_CONSUME, me); + DoCast(SPELL_CONSUME); + uiConsumeTimer = 15*IN_MILISECONDS; + } else uiConsumeTimer -= diff; + + if (bAchiev) + { + Aura *pConsumeAura = me->GetAura(DUNGEON_MODE(SPELL_CONSUME_AURA,H_SPELL_CONSUME_AURA)); + if (pConsumeAura && pConsumeAura->GetStackAmount() > 9) + bAchiev = false; + } + + if (uiCrushTimer <= diff) + { + DoCastVictim(SPELL_CRUSH); + uiCrushTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiCrushTimer -= diff; + + if (uiInfectedWoundTimer <= diff) + { + DoCastVictim(SPELL_INFECTED_WOUND); + uiInfectedWoundTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); + } else uiInfectedWoundTimer -= diff; + + if (uiExplodeCorpseTimer <= diff) + { + DoCast(SPELL_CORPSE_EXPLODE); + DoScriptText(SAY_EXPLODE, me); + uiExplodeCorpseTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); + } else uiExplodeCorpseTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + lSummons.DespawnAll(); + + if (pInstance) + { + if (bAchiev) + pInstance->DoCompleteAchievement(ACHIEV_CONSUMPTION_JUNCTION); + pInstance->SetData(DATA_TROLLGORE_EVENT, DONE); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(SAY_KILL, me); + } + + void JustSummoned(Creature* summon) + { + lSummons.push_back(summon->GetGUID()); + if (summon->AI()) + summon->AI()->AttackStart(me); + } +}; + +CreatureAI* GetAI_boss_trollgore(Creature* pCreature) +{ + return new boss_trollgoreAI (pCreature); +} + +void AddSC_boss_trollgore() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_trollgore"; + newscript->GetAI = &GetAI_boss_trollgore; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h b/src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h new file mode 100644 index 00000000000..597971d17dd --- /dev/null +++ b/src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h @@ -0,0 +1,40 @@ +/* +* Copyright (C) 2008 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DEF_DRAK_THARON_H +#define DEF_DRAK_THARON_H +enum Data +{ + DATA_TROLLGORE_EVENT, + DATA_NOVOS_EVENT, + DATA_DRED_EVENT, + DATA_THARON_JA_EVENT, + DATA_KING_DRED_ACHIEV +}; +enum Data64 +{ + DATA_TROLLGORE, + DATA_NOVOS, + DATA_DRED, + DATA_THARON_JA, + DATA_NOVOS_CRYSTAL_1, + DATA_NOVOS_CRYSTAL_2, + DATA_NOVOS_CRYSTAL_3, + DATA_NOVOS_CRYSTAL_4 +}; +#endif diff --git a/src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp b/src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp new file mode 100644 index 00000000000..9f4d2ee52a2 --- /dev/null +++ b/src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +#define MAX_ENCOUNTER 4 + +/* Drak'Tharon Keep encounters: +0 - Trollgore +1 - Novos +2 - King Dred +3 - Tharon Ja +*/ + +enum Creatures +{ + NPC_TROLLGORE = 26630, + NPC_NOVOS = 26631, + NPC_KING_DRED = 27483, + NPC_THARON_JA = 26632 +}; +enum GameObjects +{ + GO_NOVOS_CRYSTAL_1 = 189299, + GO_NOVOS_CRYSTAL_2 = 189300, + GO_NOVOS_CRYSTAL_3 = 189301, + GO_NOVOS_CRYSTAL_4 = 189302 +}; + +struct instance_drak_tharon : public ScriptedInstance +{ + instance_drak_tharon(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint8 uiDredAchievCounter; + + uint64 uiTrollgore; + uint64 uiNovos; + uint64 uiDred; + uint64 uiTharonJa; + + uint64 uiNovosCrystal1; + uint64 uiNovosCrystal2; + uint64 uiNovosCrystal3; + uint64 uiNovosCrystal4; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + + std::string str_data; + + void Initialize() + { + uiTrollgore = 0; + uiNovos = 0; + uiDred = 0; + uiTharonJa = 0; + uiNovosCrystal1 = 0; + uiNovosCrystal2 = 0; + uiNovosCrystal3 = 0; + uiNovosCrystal4 = 0; + uiDredAchievCounter = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_NOVOS_CRYSTAL_1: + uiNovosCrystal1 = pGo->GetGUID(); + break; + case GO_NOVOS_CRYSTAL_2: + uiNovosCrystal2 = pGo->GetGUID(); + break; + case GO_NOVOS_CRYSTAL_3: + uiNovosCrystal3 = pGo->GetGUID(); + break; + case GO_NOVOS_CRYSTAL_4: + uiNovosCrystal4 = pGo->GetGUID(); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_TROLLGORE: + uiTrollgore = pCreature->GetGUID(); + break; + case NPC_NOVOS: + uiNovos = pCreature->GetGUID(); + break; + case NPC_KING_DRED: + uiDred = pCreature->GetGUID(); + break; + case NPC_THARON_JA: + uiTharonJa = pCreature->GetGUID(); + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_TROLLGORE: return uiTrollgore; + case DATA_NOVOS: return uiNovos; + case DATA_DRED: return uiDred; + case DATA_THARON_JA: return uiTharonJa; + case DATA_NOVOS_CRYSTAL_1: return uiNovosCrystal1; + case DATA_NOVOS_CRYSTAL_2: return uiNovosCrystal2; + case DATA_NOVOS_CRYSTAL_3: return uiNovosCrystal3; + case DATA_NOVOS_CRYSTAL_4: return uiNovosCrystal4; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_TROLLGORE_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_NOVOS_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_DRED_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_THARON_JA_EVENT: + m_auiEncounter[3] = data; + break; + + case DATA_KING_DRED_ACHIEV: + uiDredAchievCounter = data; + break; + } + + if (data == DONE) + { + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch (type) + { + case DATA_TROLLGORE_EVENT: return m_auiEncounter[0]; + case DATA_NOVOS_EVENT: return m_auiEncounter[1]; + case DATA_DRED_EVENT: return m_auiEncounter[2]; + case DATA_THARON_JA_EVENT: return m_auiEncounter[3]; + case DATA_KING_DRED_ACHIEV: return uiDredAchievCounter; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::string str_data; + + std::ostringstream saveStream; + saveStream << "D K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0,data1,data2,data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'D' && dataHead2 == 'K') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_drak_tharon(Map* pMap) +{ + return new instance_drak_tharon(pMap); +} + +void AddSC_instance_drak_tharon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_drak_tharon"; + newscript->GetInstanceData = &GetInstanceData_instance_drak_tharon; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp new file mode 100644 index 00000000000..59db2842735 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp @@ -0,0 +1,263 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +/* + * TODO: + * - Fix Soul Storm spell and remove work around. + */ + +enum Yells +{ + SAY_AGGRO = -1632001, + SAY_SLAY_1 = -1632002, + SAY_SLAY_2 = -1632003, + SAY_DEATH = -1632004, + SAY_SOUL_STORM = -1632005, + SAY_CORRUPT_SOUL = -1632006, +}; + +enum Spells +{ + SPELL_MAGIC_S_BANE = 68793, + SPELL_CORRUPT_SOUL = 68839, + SPELL_CONSUME_SOUL = 68858, + SPELL_TELEPORT = 68988, + SPELL_FEAR = 68950, + SPELL_SOULSTORM = 68872, + SPELL_SOULSTORM_AURA = 68921, + SPELL_SHADOW_BOLT = 70043, +}; + +enum Events +{ + EVENT_NONE, + EVENT_SHADOW_BOLT, + EVENT_MAGIC_BANE, + EVENT_CORRUPT_SOUL, + EVENT_SOUL_STORM, + EVENT_SOUL_STORM_AURA, + EVENT_FEAR, +}; + +enum CombatPhases +{ + PHASE_1, + PHASE_2 +}; + +struct boss_bronjahmAI : public ScriptedAI +{ + boss_bronjahmAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + CombatPhases phase; + + void Reset() + { + phase = PHASE_1; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + events.Reset(); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); + events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); + events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + // Cast aura spell on all players farther than 10y + void ApplySoulStorm() + { + std::list targetList; + + SelectTargetList(targetList, 100, SELECT_TARGET_TOPAGGRO, -10.0f); + if (targetList.empty()) + return; + + for (std::list::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr) + { + Unit* pUnit = (*itr); + if (pUnit && pUnit->isAlive()) + me->CastSpell(pUnit, SPELL_SOULSTORM_AURA, true); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (phase == PHASE_1 && HealthBelowPct(30)) + { + phase = PHASE_2; + DoCast(me,SPELL_TELEPORT); + me->GetMotionMaster()->Clear(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + events.CancelEvent(EVENT_CORRUPT_SOUL); + events.ScheduleEvent(EVENT_SOUL_STORM, 1000); + events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); + return; + } + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CORRUPT_SOUL: + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + DoScriptText(SAY_CORRUPT_SOUL, me); + DoCast(pTarget,SPELL_CORRUPT_SOUL); + } + events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); + break; + case EVENT_SOUL_STORM: + DoScriptText(SAY_SOUL_STORM, me); + // DoCast(me, SPELL_SOULSTORM); bug: put the aura without the limit of 10 yards. + events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); + break; + case EVENT_SOUL_STORM_AURA: + ApplySoulStorm(); + events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); + break; + case EVENT_FEAR: + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget,SPELL_FEAR); + events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); + break; + case EVENT_SHADOW_BOLT: + DoCastVictim(SPELL_SHADOW_BOLT); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); + break; + case EVENT_MAGIC_BANE: + DoCastVictim(SPELL_MAGIC_S_BANE); + events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bronjahm(Creature* pCreature) +{ + return new boss_bronjahmAI(pCreature); +} + +struct mob_corrupted_soul_fragmentAI : public ScriptedAI +{ + mob_corrupted_soul_fragmentAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCheckTimer; + + void Reset() + { + uiCheckTimer = 0; // first check is immediate + } + + void UpdateAI(const uint32 diff) + { + if (uiCheckTimer <= diff) + { + if (pInstance) + { + Creature* pBronjham = Unit::GetCreature(*me, pInstance->GetData64(DATA_BRONJAHM)); + if (pBronjham && pBronjham->isAlive()) + { + if (me->IsWithinMeleeRange(pBronjham)) + { + pBronjham->CastSpell(pBronjham, SPELL_CONSUME_SOUL, true); + me->ForcedDespawn(); + } + else + { + Position pos; + pBronjham->GetPosition(&pos); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, pos); + } + } + else + me->ForcedDespawn(); + } + uiCheckTimer = 500; + } + else + uiCheckTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_corrupted_soul_fragment(Creature* pCreature) +{ + return new mob_corrupted_soul_fragmentAI(pCreature); +} + +void AddSC_boss_bronjahm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_bronjahm"; + newscript->GetAI = &GetAI_boss_bronjahm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_corrupted_soul_fragment"; + newscript->GetAI = &GetAI_mob_corrupted_soul_fragment; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp new file mode 100644 index 00000000000..6811ba953e2 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp @@ -0,0 +1,349 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +/* + * TODO: + * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing). + * - Fix outro npc movement + */ + +#define PI 3.1415f + +enum Yells +{ + SAY_FACE_ANGER_AGGRO = -1632010, + SAY_FACE_DESIRE_AGGRO = -1632011, + SAY_FACE_ANGER_SLAY_1 = -1632012, + SAY_FACE_SORROW_SLAY_1 = -1632013, + SAY_FACE_DESIRE_SLAY_1 = -1632014, + SAY_FACE_ANGER_SLAY_2 = -1632015, + SAY_FACE_SORROW_SLAY_2 = -1632016, + SAY_FACE_DESIRE_SLAY_2 = -1632017, + SAY_FACE_SORROW_DEATH = -1632019, + SAY_FACE_DESIRE_DEATH = -1632020, + EMOTE_MIRRORED_SOUL = -1632021, + EMOTE_UNLEASH_SOUL = -1632022, + SAY_FACE_ANGER_UNLEASH_SOUL = -1632023, + SAY_FACE_SORROW_UNLEASH_SOUL = -1632024, + SAY_FACE_DESIRE_UNLEASH_SOUL = -1632025, + EMOTE_WAILING_SOUL = -1632026, + SAY_FACE_ANGER_WAILING_SOUL = -1632027, + SAY_FACE_DESIRE_WAILING_SOUL = -1632028, + + SAY_JAINA_OUTRO = -1632029, + SAY_SYLVANAS_OUTRO = -1632030, +}; + +enum Spells +{ + SPELL_PHANTOM_BLAST = 68982, + H_SPELL_PHANTOM_BLAST = 70322, + SPELL_MIRRORED_SOUL = 69051, + SPELL_WELL_OF_SOULS = 68820, + SPELL_WELL_OF_SOULS_VIS = 68854, + SPELL_UNLEASHED_SOULS = 68939, + SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase + SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual + SPELL_WAILING_SOULS = 68873, // the actual spell + H_SPELL_WAILING_SOULS = 70324, +// 68871,68873,68875,68876,68899,68912,70324, +// 68899 trigger 68871 +}; + +enum Events +{ + EVENT_NONE, + EVENT_PHANTOM_BLAST, + EVENT_MIRRORED_SOUL, + EVENT_WELL_OF_SOULS, + EVENT_UNLEASHED_SOULS, + EVENT_WAILING_SOULS, + EVENT_WAILING_SOULS_TICK, + EVENT_FACE_ANGER, +}; + +enum eEnum +{ + ACHIEV_THREE_FACED = 4523, + DISPLAY_ANGER = 30148, + DISPLAY_SORROW = 30149, + DISPLAY_DESIRE = 30150, +}; + +struct +{ + uint32 entry[2]; + Position movePosition; +} outroPositions[] = +{ + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5590.47, 2427.79, 705.935, 0.802851 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5593.59, 2428.34, 705.935, 0.977384 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2429.31, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2421.12, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.43, 2426.53, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.55, 2418.36, 705.935, 1.15192 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5598, 2429.14, 705.935, 1.0472 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5594.04, 2424.87, 705.935, 1.15192 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5597.89, 2421.54, 705.935, 0.610865 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5598.57, 2434.62, 705.935, 1.13446 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5585.46, 2417.99, 705.935, 1.06465 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5605.81, 2428.42, 705.935, 0.820305 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5591.61, 2412.66, 705.935, 0.925025 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5593.9, 2410.64, 705.935, 0.872665 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5586.76, 2416.73, 705.935, 0.942478 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5592.23, 2419.14, 705.935, 0.855211 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5594.61, 2416.87, 705.935, 0.907571 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5589.77, 2421.03, 705.935, 0.855211 } }, + + { NPC_KORELN, NPC_LORALEN, { 5602.58, 2435.95, 705.935, 0.959931 } }, + { NPC_ELANDRA, NPC_KALIRA, { 5606.13, 2433.16, 705.935, 0.785398 } }, + { NPC_JAINA_PART2, NPC_SYLVANAS_PART2, { 5606.12, 2436.6, 705.935, 0.890118 } }, + + { 0, 0, { 0, 0, 0, 0 } } +}; + +struct boss_devourer_of_soulsAI : public ScriptedAI +{ + boss_devourer_of_soulsAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + bool bThreeFaceAchievement; + + ScriptedInstance* pInstance; + EventMap events; + + // wailing soul event + float beamAngle; + float beamAngleDiff; + int8 wailingSoulTick; + + uint64 uiMirroredSoulTarget; + + void Reset() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetDisplayId(DISPLAY_ANGER); + me->SetReactState(REACT_AGGRESSIVE); + + events.Reset(); + + bThreeFaceAchievement = true; + uiMirroredSoulTarget = 0; + + if (pInstance) + pInstance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS); + + DoScriptText(RAND(SAY_FACE_ANGER_AGGRO,SAY_FACE_DESIRE_AGGRO), me); + + events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); + events.ScheduleEvent(EVENT_MIRRORED_SOUL, 8000); + events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000); + events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000); + events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + if (uiMirroredSoulTarget && me->HasAura(SPELL_MIRRORED_SOUL)) + { + if (Player *pPlayer = Unit::GetPlayer(uiMirroredSoulTarget)) + { + if (Aura *pAura = pPlayer->GetAura(SPELL_MIRRORED_SOUL)) + { + int32 mirrorDamage = (uiDamage * 45)/100; + me->CastCustomSpell(pPlayer, 69034, &mirrorDamage, 0, 0, true); +// me->DealDamage(pPlayer, (uiDamage * 45)/100, 0, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); + } + else + uiMirroredSoulTarget = 0; + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_FACE_ANGER_SLAY_1,SAY_FACE_SORROW_SLAY_1,SAY_FACE_DESIRE_SLAY_1, + SAY_FACE_ANGER_SLAY_2,SAY_FACE_SORROW_SLAY_2,SAY_FACE_DESIRE_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + Position spawnPoint = { 5618.139, 2451.873, 705.854 }; + + DoScriptText(RAND(SAY_FACE_SORROW_DEATH,SAY_FACE_DESIRE_DEATH), me); + + if (pInstance) + { + pInstance->SetData(DATA_DEVOURER_EVENT, DONE); + + if (bThreeFaceAchievement && IsHeroic()) + pInstance->DoCompleteAchievement(ACHIEV_THREE_FACED); + + int32 entryIndex; + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + entryIndex = 0; + else + entryIndex = 1; + + for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i) + { + if (Creature *pSummon = me->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint, TEMPSUMMON_DEAD_DESPAWN)) + { + pSummon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition); + + if (pSummon->GetEntry() == NPC_JAINA_PART2) + DoScriptText(SAY_JAINA_OUTRO, pSummon); + else if (pSummon->GetEntry() == NPC_SYLVANAS_PART2) + DoScriptText(SAY_SYLVANAS_OUTRO, pSummon); + } + } + } + } + + void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry *pSpell) + { + if (pSpell->Id == H_SPELL_PHANTOM_BLAST) + bThreeFaceAchievement = false; + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_PHANTOM_BLAST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, SPELL_PHANTOM_BLAST); + events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); + break; + case EVENT_MIRRORED_SOUL: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) + { + uiMirroredSoulTarget = pTarget->GetGUID(); + DoCast(pTarget, SPELL_MIRRORED_SOUL); + DoScriptText(EMOTE_MIRRORED_SOUL, me); + } + events.ScheduleEvent(EVENT_MIRRORED_SOUL, urand(15000,30000)); + break; + case EVENT_WELL_OF_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_WELL_OF_SOULS); + events.ScheduleEvent(EVENT_WELL_OF_SOULS, 20000); + break; + case EVENT_UNLEASHED_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_UNLEASHED_SOULS); + me->SetDisplayId(DISPLAY_SORROW); + DoScriptText(RAND(SAY_FACE_ANGER_UNLEASH_SOUL,SAY_FACE_SORROW_UNLEASH_SOUL,SAY_FACE_DESIRE_UNLEASH_SOUL), me); + DoScriptText(EMOTE_UNLEASH_SOUL, me); + events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 30000); + events.ScheduleEvent(EVENT_FACE_ANGER, 5000); + break; + case EVENT_FACE_ANGER: + me->SetDisplayId(DISPLAY_ANGER); + break; + + case EVENT_WAILING_SOULS: + me->SetDisplayId(DISPLAY_DESIRE); + DoScriptText(RAND(SAY_FACE_ANGER_WAILING_SOUL,SAY_FACE_DESIRE_WAILING_SOUL), me); + DoScriptText(EMOTE_WAILING_SOUL, me); + DoCast(me, SPELL_WAILING_SOULS_STARTING); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->SetOrientation(me->GetAngle(pTarget)); + DoCast(me, SPELL_WAILING_SOULS_BEAM); + } + + beamAngle = me->GetOrientation(); + + beamAngleDiff = PI/30.0f; // PI/2 in 15 sec = PI/30 per tick + if (RAND(true,false)) + beamAngleDiff = -beamAngleDiff; + + me->InterruptNonMeleeSpells(false); + me->SetReactState(REACT_PASSIVE); + + //Remove any target + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + me->GetMotionMaster()->Clear(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + wailingSoulTick = 15; + events.DelayEvents(18000); // no other events during wailing souls + events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3000); // first one after 3 secs. + break; + + case EVENT_WAILING_SOULS_TICK: + beamAngle += beamAngleDiff; + me->SetOrientation(beamAngle); + me->StopMoving(); + + DoCast(me, SPELL_WAILING_SOULS); + + if (--wailingSoulTick) + events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 1000); + else + { + me->SetReactState(REACT_AGGRESSIVE); + me->SetDisplayId(DISPLAY_ANGER); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->GetMotionMaster()->MoveChase(me->getVictim()); + events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); + } + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_devourer_of_souls(Creature* pCreature) +{ + return new boss_devourer_of_soulsAI(pCreature); +} + +void AddSC_boss_devourer_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_devourer_of_souls"; + newscript->GetAI = &GetAI_boss_devourer_of_souls; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp new file mode 100644 index 00000000000..5c85da69898 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp @@ -0,0 +1,899 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +enum Spells +{ + //Spiteful Apparition + SPELL_SPITE = 68895, + H_SPELL_SPITE = 70212, + + //Spectral Warden + SPELL_VEIL_OF_SHADOWS = 69633, + SPELL_WAIL_OF_SOULS = 69148, + H_SPELL_WAIL_OF_SOULS = 70210, + + //Soulguard Watchman + SPELL_SHROUD_OF_RUNES = 69056, + SPELL_UNHOLY_RAGE = 69053, + + //Soulguard Reaper + SPELL_FROST_NOVA = 69060, + H_SPELL_FROST_NOVA = 70209, + SPELL_SHADOW_LANCE = 69058, + + //Soulguard Bonecaster + SPELL_BONE_VOLLEY = 69080, + H_SPELL_BONE_VOLLEY = 70206, + SPELL_RAISE_DEAD = 69562, + SPELL_SHIELD_OF_BONES = 69069, + H_SPELL_SHIELD_OF_BONES = 70207, + + //Soulguard Animator + // Raise dead 69562 + SPELL_SHADOW_BOLT = 69068, + H_SPELL_SHADOW_BOLT = 70208, + SPELL_SOUL_SICKNESS = 69131, + SPELL_SOUL_SIPHON = 69128, + + //Soulguard Adept + //Raise dead 69562 + //Shadow Bolt 69068/70208 + SPELL_DRAIN_LIFE = 69066, + H_SPELL_DRAIN_LIFE = 70213, + SPELL_SHADOW_MEND = 69564, + H_SPELL_SHADOW_MEND = 70205, + + //Soul Horror + SPELL_SOUL_STRIKE = 69088, + H_SPELL_SOUL_STRIKE = 70211, +}; + +enum Events +{ + EVENT_NONE, + + // Jaina/Sylvanas Intro + EVENT_INTRO_1, + EVENT_INTRO_2, + EVENT_INTRO_3, + EVENT_INTRO_4, + EVENT_INTRO_5, + EVENT_INTRO_6, + EVENT_INTRO_7, + EVENT_INTRO_8, + + //Spiteful Apparition + EVENT_SPITE, + + //Spectral Warden + EVENT_VEIL_OF_SHADOWS, + EVENT_WAIL_OF_SOULS, + + //Soulguard Watchman + EVENT_SHROUD_OF_RUNES, + EVENT_UNHOLY_RAGE, + + //Soulguard Reaper + EVENT_FROST_NOVA, + EVENT_SHADOW_LANCE, + + //Soulguard Bonecaster + EVENT_BONE_VOLLEY, + EVENT_RAISE_DEAD, + EVENT_SHIELD_OF_BONES, + + //Soulguard Animator + EVENT_SHADOW_BOLT, + EVENT_SOUL_SICKNESS, + EVENT_SOUL_SIPHON, + + //Soulguard Adept + EVENT_DRAIN_LIFE, + EVENT_SHADOW_MEND, + + //Soul Horror + EVENT_SOUL_STRIKE, +}; + +/****************************************SYLVANAS************************************/ +#define GOSSIP_SYLVANAS_ITEM "What would you have of me, Banshee Queen?" +#define GOSSIP_JAINA_ITEM "What would you have of me, my lady?" + +enum Yells +{ + SAY_JAINA_INTRO_1 = -1632040, + SAY_JAINA_INTRO_2 = -1632041, + SAY_JAINA_INTRO_3 = -1632042, + SAY_JAINA_INTRO_4 = -1632043, + SAY_JAINA_INTRO_5 = -1632044, + SAY_JAINA_INTRO_6 = -1632045, + SAY_JAINA_INTRO_7 = -1632046, + SAY_JAINA_INTRO_8 = -1632047, + + SAY_SYLVANAS_INTRO_1 = -1632050, + SAY_SYLVANAS_INTRO_2 = -1632051, + SAY_SYLVANAS_INTRO_3 = -1632052, + SAY_SYLVANAS_INTRO_4 = -1632053, + SAY_SYLVANAS_INTRO_5 = -1632054, + SAY_SYLVANAS_INTRO_6 = -1632055, +}; + +enum eSylvanas +{ + GOSSIP_SPEECHINTRO = 13525, + ACTION_INTRO, +}; + +enum Phase +{ + PHASE_NORMAL, + PHASE_INTRO, +}; + +struct npc_sylvanas_fosAI: public ScriptedAI +{ + npc_sylvanas_fosAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + ScriptedInstance* pInstance; + + EventMap events; + Phase phase; + + void Reset() + { + events.Reset(); + phase = PHASE_NORMAL; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_INTRO: + { + phase = PHASE_INTRO; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.Reset(); + events.ScheduleEvent(EVENT_INTRO_1, 1000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_INTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_INTRO_1: + DoScriptText(SAY_SYLVANAS_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_2, 11500); + break; + + case EVENT_INTRO_2: + DoScriptText(SAY_SYLVANAS_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_3, 10500); + break; + + case EVENT_INTRO_3: + DoScriptText(SAY_SYLVANAS_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_4, 9500); + break; + + case EVENT_INTRO_4: + DoScriptText(SAY_SYLVANAS_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_5, 10500); + break; + + case EVENT_INTRO_5: + DoScriptText(SAY_SYLVANAS_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_6, 9500); + break; + + case EVENT_INTRO_6: + DoScriptText(SAY_SYLVANAS_INTRO_6, me); + // End of Intro + phase = PHASE_NORMAL; + break; + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + //if (me->hasUnitState(UNIT_STAT_CASTING)) + // return; + + //while (uint32 eventId = events.ExecuteEvent()) + //{ + // switch(eventId) + // { + // } + //} + + DoMeleeAttackIfReady(); + } +}; + +struct npc_jaina_fosAI: public ScriptedAI +{ + npc_jaina_fosAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + ScriptedInstance* pInstance; + + EventMap events; + Phase phase; + + void Reset() + { + events.Reset(); + phase = PHASE_NORMAL; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_INTRO: + { + phase = PHASE_INTRO; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.Reset(); + events.ScheduleEvent(EVENT_INTRO_1, 1000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_INTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_INTRO_1: + DoScriptText(SAY_JAINA_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_2, 8000); + break; + + case EVENT_INTRO_2: + DoScriptText(SAY_JAINA_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_3, 8500); + break; + + case EVENT_INTRO_3: + DoScriptText(SAY_JAINA_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_4, 8000); + break; + + case EVENT_INTRO_4: + DoScriptText(SAY_JAINA_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_5, 10000); + break; + + case EVENT_INTRO_5: + DoScriptText(SAY_JAINA_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_6, 8000); + break; + + case EVENT_INTRO_6: + DoScriptText(SAY_JAINA_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_7, 12000); + break; + + case EVENT_INTRO_7: + DoScriptText(SAY_JAINA_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_8, 8000); + break; + + case EVENT_INTRO_8: + DoScriptText(SAY_JAINA_INTRO_8, me); + // End of Intro + phase = PHASE_NORMAL; + break; + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + //if (me->hasUnitState(UNIT_STAT_CASTING)) + // return; + + //while (uint32 eventId = events.ExecuteEvent()) + //{ + // switch(eventId) + // { + // } + //} + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->GetEntry() == NPC_JAINA_PART1) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_JAINA_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + else + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SYLVANAS_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_INTRO); + break; + } + + return true; +} + +struct mob_spiteful_apparitionAI: public ScriptedAI +{ + mob_spiteful_apparitionAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SPITE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SPITE: + DoCast(me->getVictim(), SPELL_SPITE); + events.RescheduleEvent(EVENT_SPITE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_spectral_wardenAI: public ScriptedAI +{ + mob_spectral_wardenAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_VEIL_OF_SHADOWS, 5000); + events.ScheduleEvent(EVENT_WAIL_OF_SOULS, 10000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_VEIL_OF_SHADOWS: + DoCast(me->getVictim(), SPELL_VEIL_OF_SHADOWS); + events.RescheduleEvent(EVENT_VEIL_OF_SHADOWS, 10000); + return; + case EVENT_WAIL_OF_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_WAIL_OF_SOULS); + events.RescheduleEvent(EVENT_WAIL_OF_SOULS, 5000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_watchmanAI: public ScriptedAI +{ + mob_soulguard_watchmanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHROUD_OF_RUNES, 1000); + events.ScheduleEvent(EVENT_UNHOLY_RAGE, 1000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHROUD_OF_RUNES: + DoCast(me, SPELL_SHROUD_OF_RUNES); + events.RescheduleEvent(EVENT_SHROUD_OF_RUNES, 5000); + return; + case EVENT_UNHOLY_RAGE: + DoCast(me, SPELL_UNHOLY_RAGE); + events.RescheduleEvent(EVENT_UNHOLY_RAGE, 99999); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_reaperAI: public ScriptedAI +{ + mob_soulguard_reaperAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROST_NOVA, 8000); + events.ScheduleEvent(EVENT_SHADOW_LANCE, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROST_NOVA: + DoCast(me, SPELL_FROST_NOVA); + events.RescheduleEvent(EVENT_FROST_NOVA, 9600); + return; + case EVENT_SHADOW_LANCE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_LANCE); + events.RescheduleEvent(EVENT_SHADOW_LANCE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_bonecasterAI: public ScriptedAI +{ + mob_soulguard_bonecasterAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BONE_VOLLEY, 6000); + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHIELD_OF_BONES, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BONE_VOLLEY: + DoCastAOE(SPELL_BONE_VOLLEY); + events.RescheduleEvent(EVENT_BONE_VOLLEY, 7000); + return; + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHIELD_OF_BONES: + DoCast(me, SPELL_SHIELD_OF_BONES); + events.RescheduleEvent(EVENT_SHIELD_OF_BONES, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_animatorAI: public ScriptedAI +{ + mob_soulguard_animatorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 5000); + events.ScheduleEvent(EVENT_SOUL_SICKNESS, 8000); + events.ScheduleEvent(EVENT_SOUL_SIPHON, 10000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); + return; + case EVENT_SOUL_SICKNESS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SOUL_SICKNESS); + events.RescheduleEvent(EVENT_SOUL_SICKNESS, 10000); + return; + case EVENT_SOUL_SIPHON: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SOUL_SIPHON); + events.RescheduleEvent(EVENT_SOUL_SIPHON, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_adeptAI: public ScriptedAI +{ + mob_soulguard_adeptAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 8000); + events.ScheduleEvent(EVENT_DRAIN_LIFE, 7000); + events.ScheduleEvent(EVENT_SHADOW_MEND, 35000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 4000); + return; + case EVENT_DRAIN_LIFE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DRAIN_LIFE); + events.RescheduleEvent(EVENT_DRAIN_LIFE, 9000); + return; + case EVENT_SHADOW_MEND: + DoCast(me, SPELL_SHADOW_MEND); + events.RescheduleEvent(EVENT_SHADOW_MEND, 20000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soul_horrorAI: public ScriptedAI +{ + mob_soul_horrorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SOUL_STRIKE, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SOUL_STRIKE: + DoCast(me->getVictim(), SPELL_SOUL_STRIKE); + events.RescheduleEvent(EVENT_SOUL_STRIKE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_jaina_fosAI(Creature* pCreature) +{ + return new npc_jaina_fosAI(pCreature); +}; + +CreatureAI* GetAI_npc_sylvanas_fosAI(Creature* pCreature) +{ + return new npc_sylvanas_fosAI(pCreature); +}; + +CreatureAI* GetAI_mob_spiteful_apparitionAI(Creature* pCreature) +{ + return new mob_spiteful_apparitionAI(pCreature); +} + +CreatureAI* GetAI_mob_spectral_wardenAI(Creature* pCreature) +{ + return new mob_spectral_wardenAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_watchmanAI(Creature* pCreature) +{ + return new mob_soulguard_watchmanAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_reaperAI(Creature* pCreature) +{ + return new mob_soulguard_reaperAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_bonecasterAI(Creature* pCreature) +{ + return new mob_soulguard_bonecasterAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_animatorAI(Creature* pCreature) +{ + return new mob_soulguard_animatorAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_adeptAI(Creature* pCreature) +{ + return new mob_soulguard_adeptAI(pCreature); +} + +CreatureAI* GetAI_mob_soul_horrorAI(Creature* pCreature) +{ + return new mob_soul_horrorAI(pCreature); +} + +void AddSC_forge_of_souls() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sylvanas_fos"; + newscript->GetAI = &GetAI_npc_sylvanas_fosAI; + newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_fos"; + newscript->GetAI = &GetAI_npc_jaina_fosAI; + newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_spiteful_apparition"; + newscript->GetAI = &GetAI_mob_spiteful_apparitionAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_spectral_warden"; + newscript->GetAI = &GetAI_mob_spectral_wardenAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_watchman"; + newscript->GetAI = &GetAI_mob_soulguard_watchmanAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_reaper"; + newscript->GetAI = &GetAI_mob_soulguard_reaperAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_bonecaster"; + newscript->GetAI = &GetAI_mob_soulguard_bonecasterAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_animator"; + newscript->GetAI = &GetAI_mob_soulguard_animatorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_adept"; + newscript->GetAI = &GetAI_mob_soulguard_adeptAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soul_horror"; + newscript->GetAI = &GetAI_mob_soul_horrorAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h new file mode 100644 index 00000000000..e0479eb4d2b --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_FORGE_OF_SOULS_H +#define DEF_FORGE_OF_SOULS_H + +enum Data +{ + DATA_BRONJAHM_EVENT, + DATA_DEVOURER_EVENT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_BRONJAHM, + DATA_DEVOURER, +}; + +enum Creatures +{ + CREATURE_BRONJAHM = 36497, + CREATURE_DEVOURER = 36502, + + NPC_SYLVANAS_PART1 = 37596, + NPC_SYLVANAS_PART2 = 38161, + NPC_JAINA_PART1 = 37597, + NPC_JAINA_PART2 = 38160, + NPC_KALIRA = 37583, + NPC_ELANDRA = 37774, + NPC_LORALEN = 37779, + NPC_KORELN = 37582, + NPC_CHAMPION_1_HORDE = 37584, + NPC_CHAMPION_2_HORDE = 37587, + NPC_CHAMPION_3_HORDE = 37588, + NPC_CHAMPION_1_ALLIANCE = 37496, + NPC_CHAMPION_2_ALLIANCE = 37497, +}; +#endif diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp new file mode 100644 index 00000000000..67a6cdb4579 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp @@ -0,0 +1,168 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +#define MAX_ENCOUNTER 2 + +/* Forge of Souls encounters: +0- Bronjahm, The Godfather of Souls +1- The Devourer of Souls +*/ + +struct instance_forge_of_souls : public ScriptedInstance +{ + instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiBronjahm; + uint64 uiDevourer; + + uint32 uiEncounter[MAX_ENCOUNTER]; + uint32 uiTeamInInstance; + + void Initialize() + { + uiBronjahm = 0; + uiDevourer = 0; + + uiTeamInInstance = 0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + + if (!players.isEmpty()) + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + + switch(pCreature->GetEntry()) + { + case CREATURE_BRONJAHM: + uiBronjahm = pCreature->GetGUID(); + break; + case CREATURE_DEVOURER: + uiDevourer = pCreature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_BRONJAHM_EVENT: + uiEncounter[0] = data; + break; + case DATA_DEVOURER_EVENT: + uiEncounter[1] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_BRONJAHM_EVENT: return uiEncounter[0]; + case DATA_DEVOURER_EVENT: return uiEncounter[1]; + case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_BRONJAHM: return uiBronjahm; + case DATA_DEVOURER: return uiBronjahm; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "F S " << uiEncounter[0] << " " << uiEncounter[1]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; + + if (dataHead1 == 'F' && dataHead2 == 'S') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap) +{ + return new instance_forge_of_souls(pMap); +} + +void AddSC_instance_forge_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_forge_of_souls"; + newscript->GetInstanceData = &GetInstanceData_instance_forge_of_souls; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp new file mode 100644 index 00000000000..c9978faca6e --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_AGGRO = -1668050, + SAY_SLAY_1 = -1668051, + SAY_SLAY_2 = -1668052, + SAY_DEATH = -1668053, + SAY_IMPENDING_DESPAIR = -1668054, + SAY_DEFILING_HORROR = -1668055, +}; + +enum Spells +{ + SPELL_QUIVERING_STRIKE = 72422, + SPELL_IMPENDING_DESPAIR = 72426, + SPELL_DEFILING_HORROR = 72435, + SPELL_HOPELESSNESS = 72395, + H_SPELL_HOPELESSNESS = 72390, // TODO: not in dbc. Add in DB. +}; + +enum Events +{ + EVENT_NONE, + EVENT_QUIVERING_STRIKE, + EVENT_IMPENDING_DESPAIR, + EVENT_DEFILING_HORROR, +}; + +struct boss_falricAI : public boss_horAI +{ + boss_falricAI(Creature *pCreature) : boss_horAI(pCreature) {} + + uint8 uiHopelessnessCount; + + void Reset() + { + boss_horAI::Reset(); + + uiHopelessnessCount = 0; + + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000); + events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000); + events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_QUIVERING_STRIKE: + DoCast(SPELL_QUIVERING_STRIKE); + events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000); + break; + case EVENT_IMPENDING_DESPAIR: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + { + DoScriptText(SAY_IMPENDING_DESPAIR, me); + DoCast(pTarget, SPELL_IMPENDING_DESPAIR); + } + events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000); + break; + case EVENT_DEFILING_HORROR: + DoCast(SPELL_DEFILING_HORROR); + events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. + break; + } + + if ((uiHopelessnessCount < 1 && HealthBelowPct(66)) + || (uiHopelessnessCount < 2 && HealthBelowPct(33)) + || (uiHopelessnessCount < 3 && HealthBelowPct(10))) + { + uiHopelessnessCount++; + DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS,H_SPELL_HOPELESSNESS)); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_falric(Creature* pCreature) +{ + return new boss_falricAI(pCreature); +} + +void AddSC_boss_falric() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_falric"; + newscript->GetAI = &GetAI_boss_falric; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp new file mode 100644 index 00000000000..95fb2737ce9 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp @@ -0,0 +1,133 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_AGGRO = -1668060, + SAY_SLAY_1 = -1668061, + SAY_SLAY_2 = -1668062, + SAY_DEATH = -1668063, + SAY_CORRUPTED_FLESH_1 = -1668064, + SAY_CORRUPTED_FLESH_2 = -1668065, +}; + +enum Spells +{ + SPELL_OBLITERATE = 72360, + SPELL_WELL_OF_CORRUPTION = 72362, + SPELL_CORRUPTED_FLESH = 72363, + SPELL_SHARED_SUFFERING = 72368, +}; + +enum Events +{ + EVENT_NONE, + EVENT_OBLITERATE, + EVENT_WELL_OF_CORRUPTION, + EVENT_CORRUPTED_FLESH, + EVENT_SHARED_SUFFERING, +}; + +struct boss_marwynAI : public boss_horAI +{ + boss_marwynAI(Creature *pCreature) : boss_horAI(pCreature) {} + + void Reset() + { + boss_horAI::Reset(); + + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_OBLITERATE, 30000); // TODO Check timer + events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); + events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); + events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); // TODO Check timer + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_OBLITERATE: + DoCast(SPELL_OBLITERATE); + events.ScheduleEvent(EVENT_OBLITERATE, 30000); + break; + case EVENT_WELL_OF_CORRUPTION: + DoCast(SPELL_WELL_OF_CORRUPTION); + events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); + break; + case EVENT_CORRUPTED_FLESH: + DoScriptText(RAND(SAY_CORRUPTED_FLESH_1,SAY_CORRUPTED_FLESH_2), me); + DoCast(SPELL_CORRUPTED_FLESH); + events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); + break; + case EVENT_SHARED_SUFFERING: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHARED_SUFFERING); + events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_marwyn(Creature* pCreature) +{ + return new boss_marwynAI(pCreature); +} + +void AddSC_boss_marwyn() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_marwyn"; + newscript->GetAI = &GetAI_boss_marwyn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp new file mode 100644 index 00000000000..fb3d3d5d752 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp @@ -0,0 +1,1022 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_JAINA_INTRO_1 = -1668001, + SAY_JAINA_INTRO_2 = -1668002, + SAY_JAINA_INTRO_3 = -1668003, + SAY_JAINA_INTRO_4 = -1668004, + SAY_UTHER_INTRO_A2_1 = -1668005, + SAY_JAINA_INTRO_5 = -1668006, + SAY_UTHER_INTRO_A2_2 = -1668007, + SAY_JAINA_INTRO_6 = -1668008, + SAY_UTHER_INTRO_A2_3 = -1668009, + SAY_JAINA_INTRO_7 = -1668010, + SAY_UTHER_INTRO_A2_4 = -1668011, + SAY_JAINA_INTRO_8 = -1668012, + SAY_UTHER_INTRO_A2_5 = -1668013, + SAY_JAINA_INTRO_9 = -1668014, + SAY_UTHER_INTRO_A2_6 = -1668015, + SAY_UTHER_INTRO_A2_7 = -1668016, + SAY_JAINA_INTRO_10 = -1668017, + SAY_UTHER_INTRO_A2_8 = -1668018, + SAY_JAINA_INTRO_11 = -1668019, + SAY_UTHER_INTRO_A2_9 = -1668020, + + SAY_SYLVANAS_INTRO_1 = -1668021, + SAY_SYLVANAS_INTRO_2 = -1668022, + SAY_SYLVANAS_INTRO_3 = -1668023, + SAY_UTHER_INTRO_H2_1 = -1668024, + SAY_SYLVANAS_INTRO_4 = -1668025, + SAY_UTHER_INTRO_H2_2 = -1668026, + SAY_SYLVANAS_INTRO_5 = -1668027, + SAY_UTHER_INTRO_H2_3 = -1668028, + SAY_SYLVANAS_INTRO_6 = -1668029, + SAY_UTHER_INTRO_H2_4 = -1668030, + SAY_SYLVANAS_INTRO_7 = -1668031, + SAY_UTHER_INTRO_H2_5 = -1668032, + SAY_UTHER_INTRO_H2_6 = -1668033, + SAY_SYLVANAS_INTRO_8 = -1668034, + SAY_UTHER_INTRO_H2_7 = -1668035, + + SAY_LK_INTRO_1 = -1668036, + SAY_LK_INTRO_2 = -1668037, + SAY_LK_INTRO_3 = -1668038, + SAY_FALRIC_INTRO_1 = -1668039, + SAY_MARWYN_INTRO_1 = -1668040, + SAY_FALRIC_INTRO_2 = -1668041, + + SAY_JAINA_INTRO_END = -1668042, + SAY_SYLVANAS_INTRO_END = -1668043, +}; + +enum Events +{ + EVENT_NONE, + + EVENT_START_INTRO, + EVENT_SKIP_INTRO, + + EVENT_INTRO_A2_1, + EVENT_INTRO_A2_2, + EVENT_INTRO_A2_3, + EVENT_INTRO_A2_4, + EVENT_INTRO_A2_5, + EVENT_INTRO_A2_6, + EVENT_INTRO_A2_7, + EVENT_INTRO_A2_8, + EVENT_INTRO_A2_9, + EVENT_INTRO_A2_10, + EVENT_INTRO_A2_11, + EVENT_INTRO_A2_12, + EVENT_INTRO_A2_13, + EVENT_INTRO_A2_14, + EVENT_INTRO_A2_15, + EVENT_INTRO_A2_16, + EVENT_INTRO_A2_17, + EVENT_INTRO_A2_18, + EVENT_INTRO_A2_19, + + EVENT_INTRO_H2_1, + EVENT_INTRO_H2_2, + EVENT_INTRO_H2_3, + EVENT_INTRO_H2_4, + EVENT_INTRO_H2_5, + EVENT_INTRO_H2_6, + EVENT_INTRO_H2_7, + EVENT_INTRO_H2_8, + EVENT_INTRO_H2_9, + EVENT_INTRO_H2_10, + EVENT_INTRO_H2_11, + EVENT_INTRO_H2_12, + EVENT_INTRO_H2_13, + EVENT_INTRO_H2_14, + EVENT_INTRO_H2_15, + + EVENT_INTRO_LK_1, + EVENT_INTRO_LK_2, + EVENT_INTRO_LK_3, + EVENT_INTRO_LK_4, + EVENT_INTRO_LK_5, + EVENT_INTRO_LK_6, + EVENT_INTRO_LK_7, + EVENT_INTRO_LK_8, + EVENT_INTRO_LK_9, + + EVENT_INTRO_END, +}; + +enum eEnum +{ + ACTION_START_INTRO, + ACTION_SKIP_INTRO, + + QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710, + QUEST_DELIVRANCE_FROM_THE_PIT_H2 = 24712, + QUEST_WRATH_OF_THE_LICH_KING_A2 = 24500, + QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802, +}; + +static Position HallsofReflectionLocs[]= +{ + {5283.234863, 1990.946777, 707.695679, 0.929097}, // 2 Loralen Follows + {5408.031250, 2102.918213, 707.695251, 0.792756}, // 9 Sylvanas Follows + {5401.866699, 2110.837402, 707.695251, 0.800610}, // 10 Loralen follows +}; + +static Position SpawnPos = {5262.540527, 1949.693726, 707.695007, 0.808736}; // Jaina/Sylvanas Beginning Position +static Position MoveThronePos = {5306.952148, 1998.499023, 709.341431, 1.277278}; // Jaina/Sylvanas walks to throne +static Position UtherSpawnPos = {5308.310059, 2003.857178, 709.341431, 4.650315}; +static Position LichKingSpawnPos = {5362.917480, 2062.307129, 707.695374, 3.945812}; +static Position LichKingMoveThronePos = {5312.080566, 2009.172119, 709.341431, 3.973301}; // Lich King walks to throne +static Position LichKingMoveAwayPos = {5400.069824, 2102.7131689, 707.69525, 0.843803}; // Lich King walks away + +// AI of Part1: handle the intro till start of gauntlet event. +struct npc_jaina_or_sylvanas_horAI : public ScriptedAI +{ + npc_jaina_or_sylvanas_horAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint64 uiUther; + uint64 uiLichKing; + + EventMap events; + + void Reset() + { + events.Reset(); + + uiUther = 0; + uiLichKing = 0; + + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetVisibility(VISIBILITY_ON); + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_START_INTRO: + events.ScheduleEvent(EVENT_START_INTRO, 0); + break; + case ACTION_SKIP_INTRO: + events.ScheduleEvent(EVENT_SKIP_INTRO, 0); + break; + } + } + + void UpdateAI(const uint32 diff) + { + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_START_INTRO: + me->GetMotionMaster()->MovePoint(0, MoveThronePos); + // Begining of intro is differents between factions as the speech sequence and timers are differents. + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + events.ScheduleEvent(EVENT_INTRO_A2_1, 0); + else + events.ScheduleEvent(EVENT_INTRO_H2_1, 0); + break; + + // A2 Intro Events + case EVENT_INTRO_A2_1: + DoScriptText(SAY_JAINA_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_A2_2, 5000); + break; + case EVENT_INTRO_A2_2: + DoScriptText(SAY_JAINA_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_A2_3, 10000); + break; + case EVENT_INTRO_A2_3: + // TODO: she's doing some kind of spell casting emote + pInstance->HandleGameObject(pInstance->GetData64(DATA_FROSTMOURNE), true); + events.ScheduleEvent(EVENT_INTRO_A2_4, 10000); + break; + case EVENT_INTRO_A2_4: + // spawn UTHER during speach 2 + if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pUther->GetMotionMaster()->MoveIdle(); + pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas + uiUther = pUther->GetGUID(); + } + events.ScheduleEvent(EVENT_INTRO_A2_5, 2000); + break; + case EVENT_INTRO_A2_5: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_1, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_6, 3000); + break; + case EVENT_INTRO_A2_6: + DoScriptText(SAY_JAINA_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_A2_7, 6000); + break; + case EVENT_INTRO_A2_7: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_2, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_8, 6500); + break; + case EVENT_INTRO_A2_8: + DoScriptText(SAY_JAINA_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_A2_9, 2000); + break; + case EVENT_INTRO_A2_9: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_3, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_10, 9000); + break; + case EVENT_INTRO_A2_10: + DoScriptText(SAY_JAINA_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_A2_11, 5000); + break; + case EVENT_INTRO_A2_11: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_4, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_12, 11000); + break; + case EVENT_INTRO_A2_12: + DoScriptText(SAY_JAINA_INTRO_8, me); + events.ScheduleEvent(EVENT_INTRO_A2_13, 4000); + break; + case EVENT_INTRO_A2_13: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_5, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_14, 12500); + break; + case EVENT_INTRO_A2_14: + DoScriptText(SAY_JAINA_INTRO_9, me); + events.ScheduleEvent(EVENT_INTRO_A2_15, 10000); + break; + case EVENT_INTRO_A2_15: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_6, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_16, 22000); + break; + case EVENT_INTRO_A2_16: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_7, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_17, 4000); + break; + case EVENT_INTRO_A2_17: + DoScriptText(SAY_JAINA_INTRO_10, me); + events.ScheduleEvent(EVENT_INTRO_A2_18, 2000); + break; + case EVENT_INTRO_A2_18: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); + DoScriptText(SAY_UTHER_INTRO_A2_8, pUther); + } + events.ScheduleEvent(EVENT_INTRO_A2_19, 11000); + break; + case EVENT_INTRO_A2_19: + DoScriptText(SAY_JAINA_INTRO_11, me); + events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + break; + + // H2 Intro Events + case EVENT_INTRO_H2_1: + DoScriptText(SAY_SYLVANAS_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_H2_2, 8000); + break; + case EVENT_INTRO_H2_2: + DoScriptText(SAY_SYLVANAS_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_H2_3, 6000); + break; + case EVENT_INTRO_H2_3: + DoScriptText(SAY_SYLVANAS_INTRO_3, me); + // TODO: she's doing some kind of spell casting emote + events.ScheduleEvent(EVENT_INTRO_H2_4, 6000); + break; + case EVENT_INTRO_H2_4: + // spawn UTHER during speach 2 + if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pUther->GetMotionMaster()->MoveIdle(); + pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas + uiUther = pUther->GetGUID(); + } + events.ScheduleEvent(EVENT_INTRO_H2_5, 2000); + break; + case EVENT_INTRO_H2_5: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_1, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_6, 11000); + break; + case EVENT_INTRO_H2_6: + DoScriptText(SAY_SYLVANAS_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_H2_7, 3000); + break; + case EVENT_INTRO_H2_7: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_2, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_8, 6000); + break; + case EVENT_INTRO_H2_8: + DoScriptText(SAY_SYLVANAS_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_H2_9, 5000); + break; + case EVENT_INTRO_H2_9: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_3, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_10, 19000); + break; + case EVENT_INTRO_H2_10: + DoScriptText(SAY_SYLVANAS_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_H2_11, 1500); + break; + case EVENT_INTRO_H2_11: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_4, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_12, 19500); + break; + case EVENT_INTRO_H2_12: + DoScriptText(SAY_SYLVANAS_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_H2_13, 2000); + break; + case EVENT_INTRO_H2_13: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); + DoScriptText(SAY_UTHER_INTRO_H2_5, pUther); + } + events.ScheduleEvent(EVENT_INTRO_H2_14, 12000); + break; + case EVENT_INTRO_H2_14: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_6, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_15, 8000); + break; + case EVENT_INTRO_H2_15: + DoScriptText(SAY_SYLVANAS_INTRO_8, me); + events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + break; + + // Remaining Intro Events common for both faction + case EVENT_INTRO_LK_1: + // Spawn LK in front of door, and make him move to the sword. + if (Creature* pLichKing = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pLichKing->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); + pLichKing->SetReactState(REACT_PASSIVE); + uiLichKing = pLichKing->GetGUID(); + } + + if (Creature* pUther = me->GetCreature(*me, uiUther)) + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + DoScriptText(SAY_UTHER_INTRO_A2_9, pUther); + else + DoScriptText(SAY_UTHER_INTRO_H2_7, pUther); + + events.ScheduleEvent(EVENT_INTRO_LK_2, 11000); + break; + + case EVENT_INTRO_LK_2: + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + DoScriptText(SAY_LK_INTRO_1, pLichKing); + events.ScheduleEvent(EVENT_INTRO_LK_3, 2000); + break; + + case EVENT_INTRO_LK_3: + // The Lich King banishes Uther to the abyss. + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->DisappearAndDie(); + uiUther = 0; + } + + // He steps forward and removes the runeblade from the heap of skulls. + + events.ScheduleEvent(EVENT_INTRO_LK_4, 4000); + break; + + case EVENT_INTRO_LK_4: + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + DoScriptText(SAY_LK_INTRO_2, pLichKing); + events.ScheduleEvent(EVENT_INTRO_LK_5, 10000); + break; + + case EVENT_INTRO_LK_5: + // summon Falric and Marwyn. then go back to the door + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + pFalric->SetVisibility(VISIBILITY_ON); + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + pMarwyn->SetVisibility(VISIBILITY_ON); + + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + { + pLichKing->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + DoScriptText(SAY_LK_INTRO_3, pLichKing); + } + + events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); + break; + + case EVENT_INTRO_LK_6: + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + DoScriptText(SAY_FALRIC_INTRO_1, pFalric); + + events.ScheduleEvent(EVENT_INTRO_LK_7, 2000); + break; + + case EVENT_INTRO_LK_7: + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + DoScriptText(SAY_MARWYN_INTRO_1, pMarwyn); + + events.ScheduleEvent(EVENT_INTRO_LK_8, 2000); + break; + + case EVENT_INTRO_LK_8: + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + DoScriptText(SAY_FALRIC_INTRO_2, pFalric); + + events.ScheduleEvent(EVENT_INTRO_LK_9, 5000); + break; + + case EVENT_INTRO_LK_9: + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + DoScriptText(SAY_JAINA_INTRO_END, me); + else + DoScriptText(SAY_SYLVANAS_INTRO_END, me); + + me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + // TODO: Loralen/Koreln shall run also + events.ScheduleEvent(EVENT_INTRO_END, 10000); + break; + + case EVENT_INTRO_END: + if (pInstance) + pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave + + // Loralen or Koreln disappearAndDie() + me->DisappearAndDie(); + break; + + case EVENT_SKIP_INTRO: + // TODO: implement + + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + pFalric->SetVisibility(VISIBILITY_ON); + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + pMarwyn->SetVisibility(VISIBILITY_ON); + + me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + // TODO: Loralen/Koreln shall run also + + events.ScheduleEvent(EVENT_INTRO_END, 15000); + break; + } + } +}; + +bool GossipHello_npc_sylvanas_hor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_H2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + // once last quest is completed, she offers this shortcut of the starting event + if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_H2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Dark Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + + return true; +} + +bool GossipHello_npc_jaina_hor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_A2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + // once last quest of the series is completed, she offers this shortcut of the starting event + if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_A2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "My Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_or_sylvanas_hor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_START_INTRO); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_SKIP_INTRO); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + } + + return true; +} + +enum TrashSpells +{ + // Ghostly Priest + SPELL_SHADOW_WORD_PAIN = 72318, + SPELL_CIRCLE_OF_DESTRUCTION = 72320, + SPELL_COWER_IN_FEAR = 72321, + SPELL_DARK_MENDING = 72322, + + // Phantom Mage + SPELL_FIREBALL = 72163, + SPELL_FLAMESTRIKE = 72169, + SPELL_FROSTBOLT = 72166, + SPELL_CHAINS_OF_ICE = 72121, + SPELL_HALLUCINATION = 72342, + + // Phantom Hallucination (same as phantom mage + HALLUCINATION_2 when dies) + SPELL_HALLUCINATION_2 = 72344, + + // Shadowy Mercenary + SPELL_SHADOW_STEP = 72326, + SPELL_DEADLY_POISON = 72329, + SPELL_ENVENOMED_DAGGER_THROW = 72333, + SPELL_KIDNEY_SHOT = 72335, + + // Spectral Footman + SPELL_SPECTRAL_STRIKE = 72198, + SPELL_SHIELD_BASH = 72194, + SPELL_TORTURED_ENRAGE = 72203, + + // Tortured Rifleman + SPELL_SHOOT = 72208, + SPELL_CURSED_ARROW = 72222, + SPELL_FROST_TRAP = 72215, + SPELL_ICE_SHOT = 72268, +}; + +enum TrashEvents +{ + EVENT_TRASH_NONE, + + // Ghostly Priest + EVENT_SHADOW_WORD_PAIN, + EVENT_CIRCLE_OF_DESTRUCTION, + EVENT_COWER_IN_FEAR, + EVENT_DARK_MENDING, + + // Phantom Mage + EVENT_FIREBALL, + EVENT_FLAMESTRIKE, + EVENT_FROSTBOLT, + EVENT_CHAINS_OF_ICE, + EVENT_HALLUCINATION, + + // Shadowy Mercenary + EVENT_SHADOW_STEP, + EVENT_DEADLY_POISON, + EVENT_ENVENOMED_DAGGER_THROW, + EVENT_KIDNEY_SHOT, + + // Spectral Footman + EVENT_SPECTRAL_STRIKE, + EVENT_SHIELD_BASH, + EVENT_TORTURED_ENRAGE, + + // Tortured Rifleman + EVENT_SHOOT, + EVENT_CURSED_ARROW, + EVENT_FROST_TRAP, + EVENT_ICE_SHOT, +}; + +struct npc_ghostly_priestAI: public ScriptedAI +{ + npc_ghostly_priestAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); // TODO: adjust timers + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_WORD_PAIN: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); + return; + case EVENT_CIRCLE_OF_DESTRUCTION: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CIRCLE_OF_DESTRUCTION); + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + return; + case EVENT_COWER_IN_FEAR: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_COWER_IN_FEAR); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + return; + case EVENT_DARK_MENDING: + // find an ally with missing HP + if (Unit *pTarget = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000,50000))) + { + DoCast(pTarget, SPELL_DARK_MENDING); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + else + { + // no friendly unit with missing hp. re-check in just 5 sec. + events.ScheduleEvent(EVENT_DARK_MENDING, 5000); + } + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_phantom_mageAI: public ScriptedAI +{ + npc_phantom_mageAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FIREBALL, 3000); // TODO: adjust timers + events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000); + events.ScheduleEvent(EVENT_FROSTBOLT, 9000); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000); + events.ScheduleEvent(EVENT_HALLUCINATION, 40000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FIREBALL: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 15000); + return; + case EVENT_FLAMESTRIKE: + DoCast(SPELL_FLAMESTRIKE); + events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); + return; + case EVENT_FROSTBOLT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_FROSTBOLT); + events.ScheduleEvent(EVENT_FROSTBOLT, 15000); + return; + case EVENT_CHAINS_OF_ICE: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CHAINS_OF_ICE); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); + return; + case EVENT_HALLUCINATION: + DoCast(SPELL_HALLUCINATION); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_phantom_hallucinationAI: public npc_phantom_mageAI +{ + npc_phantom_hallucinationAI(Creature *c) : npc_phantom_mageAI(c) + { + } + + void JustDied(Unit * /*pWho*/) + { + DoCast(SPELL_HALLUCINATION_2); + } +}; + +struct npc_shadowy_mercenaryAI: public ScriptedAI +{ + npc_shadowy_mercenaryAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); // TODO: adjust timers + events.ScheduleEvent(EVENT_DEADLY_POISON, 5000); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_STEP: + DoCast(SPELL_SHADOW_STEP); + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); + return; + case EVENT_DEADLY_POISON: + DoCast(me->getVictim(), SPELL_DEADLY_POISON); + events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); + return; + case EVENT_ENVENOMED_DAGGER_THROW: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_ENVENOMED_DAGGER_THROW); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + return; + case EVENT_KIDNEY_SHOT: + DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_spectral_footmanAI: public ScriptedAI +{ + npc_spectral_footmanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); // TODO: adjust timers + events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SPECTRAL_STRIKE: + DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); + return; + case EVENT_SHIELD_BASH: + DoCast(me->getVictim(), SPELL_SHIELD_BASH); + events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); + return; + case EVENT_TORTURED_ENRAGE: + DoCast(SPELL_TORTURED_ENRAGE); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_tortured_riflemanAI : public ScriptedAI +{ + npc_tortured_riflemanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHOOT, 2000); // TODO: adjust timers + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + events.ScheduleEvent(EVENT_FROST_TRAP, 1000); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHOOT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHOOT); + events.ScheduleEvent(EVENT_SHOOT, 2000); + return; + case EVENT_CURSED_ARROW: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CURSED_ARROW); + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + return; + case EVENT_FROST_TRAP: + DoCast(SPELL_FROST_TRAP); + events.ScheduleEvent(EVENT_FROST_TRAP, 30000); + return; + case EVENT_ICE_SHOT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_ICE_SHOT); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_jaina_or_sylvanas_horAI(Creature* pCreature) +{ + return new npc_jaina_or_sylvanas_horAI(pCreature); +} + +CreatureAI* GetAI_npc_ghostly_priestAI(Creature* pCreature) +{ + return new npc_ghostly_priestAI(pCreature); +} + +CreatureAI* GetAI_npc_phantom_mageAI(Creature* pCreature) +{ + return new npc_phantom_mageAI(pCreature); +} + +CreatureAI* GetAI_npc_phantom_hallucinationAI(Creature* pCreature) +{ + return new npc_phantom_hallucinationAI(pCreature); +} + +CreatureAI* GetAI_npc_shadowy_mercenaryAI(Creature* pCreature) +{ + return new npc_shadowy_mercenaryAI(pCreature); +} + +CreatureAI* GetAI_npc_spectral_footmanAI(Creature* pCreature) +{ + return new npc_spectral_footmanAI(pCreature); +} + +CreatureAI* GetAI_npc_tortured_riflemanAI(Creature* pCreature) +{ + return new npc_tortured_riflemanAI(pCreature); +} + +void AddSC_halls_of_reflection() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sylvanas_hor_part1"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; + newscript->pGossipHello = &GossipHello_npc_sylvanas_hor; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_hor_part1"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; + newscript->pGossipHello = &GossipHello_npc_jaina_hor; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ghostly_priest"; + newscript->GetAI = &GetAI_npc_ghostly_priestAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_phantom_mage"; + newscript->GetAI = &GetAI_npc_phantom_mageAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_phantom_hallucination"; + newscript->GetAI = &GetAI_npc_phantom_hallucinationAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_shadowy_mercenary"; + newscript->GetAI = &GetAI_npc_shadowy_mercenaryAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_spectral_footman"; + newscript->GetAI = &GetAI_npc_spectral_footmanAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tortured_rifleman"; + newscript->GetAI = &GetAI_npc_tortured_riflemanAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h new file mode 100644 index 00000000000..46ae0cb283c --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h @@ -0,0 +1,156 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_HALLS_OF_REFLECTION_H +#define DEF_HALLS_OF_REFLECTION_H + +enum Data +{ + DATA_FALRIC_EVENT, + DATA_MARWYN_EVENT, + DATA_LICHKING_EVENT, + DATA_WAVE_COUNT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_FALRIC, + DATA_MARWYN, + DATA_LICHKING, + DATA_FROSTMOURNE, +}; + +enum Creatures +{ + NPC_FALRIC = 38112, + NPC_MARWYN = 38113, + NPC_LICH_KING_EVENT = 37226, + NPC_LICH_KING_BOSS = 36954, + + NPC_UTHER = 37225, + NPC_JAINA_PART1 = 37221, + NPC_JAINA_PART2 = 36955, + NPC_SYLVANAS_PART1 = 37223, + NPC_SYLVANAS_PART2 = 37554, + + NPC_WAVE_MERCENARY = 38177, + NPC_WAVE_FOOTMAN = 38173, + NPC_WAVE_RIFLEMAN = 38176, + NPC_WAVE_PRIEST = 38175, + NPC_WAVE_MAGE = 38172, +}; + +enum GameObjects +{ + GO_FROSTMOURNE = 202302, + GO_FROSTMOURNE_ALTAR = 202236, + GO_FRONT_DOOR = 201976, + GO_ARTHAS_DOOR = 197341, +}; + +enum HorWorldStates +{ + WORLD_STATE_HOR = 4884, + WORLD_STATE_HOR_WAVE_COUNT = 4882, +}; + +// Common actions from Instance Script to Boss Script +enum Actions +{ + ACTION_ENTER_COMBAT, +}; + +// Base class for FALRIC and MARWYN +// handled the summonList and the notification events to/from the InstanceData +struct boss_horAI : ScriptedAI +{ + boss_horAI(Creature *pCreature) : ScriptedAI(pCreature), summons(pCreature) + { + pInstance = me->GetInstanceData(); + } + + InstanceData* pInstance; + EventMap events; + SummonList summons; + + void Reset() + { + events.Reset(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + } + + void DamageTaken(Unit *pWho, uint32 &uiDamage) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + uiDamage = 0; + } + + void DoAction(const int32 actionID) + { + switch(actionID) + { + case ACTION_ENTER_COMBAT: // called by InstanceData when boss shall enter in combat. + // Just in case. Should have been done by InstanceData + me->SetVisibility(VISIBILITY_ON); + + // Reset flags + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + + if (Unit *pUnit = me->SelectNearestTarget()) + AttackStart(pUnit); + + DoZoneInCombat(); + break; + } + } + + void JustSummoned(Creature *pSummoned) + { + summons.Summon(pSummoned); + + if (Unit *pUnit = pSummoned->SelectNearestTarget()) + { + if (pSummoned->AI()) + pSummoned->AI()->AttackStart(pUnit); + else + { + pSummoned->GetMotionMaster()->MoveChase(pUnit); + pSummoned->Attack(pUnit, true); + } + } + + if (pSummoned->AI()) + pSummoned->AI()->DoZoneInCombat(); + } + + void SummonedCreatureDespawn(Creature *pSummoned) + { + summons.Despawn(pSummoned); + if (summons.empty()) + { + if (pSummoned->isAlive()) + pInstance->SetData(DATA_WAVE_COUNT, NOT_STARTED); + else + pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); + } + } +}; + +#endif diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp new file mode 100644 index 00000000000..7a5d2479b7c --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp @@ -0,0 +1,431 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +#define MAX_ENCOUNTER 3 + +/* Halls of Reflection encounters: +0- Falric +1- Marwyn +2- The Lich King +*/ + +enum eEnum +{ + ENCOUNTER_WAVE_MERCENARY = 6, + ENCOUNTER_WAVE_FOOTMAN = 10, + ENCOUNTER_WAVE_RIFLEMAN = 6, + ENCOUNTER_WAVE_PRIEST = 6, + ENCOUNTER_WAVE_MAGE = 6, +}; + +enum Events +{ + EVENT_NONE, + EVENT_NEXT_WAVE, + EVENT_START_LICH_KING, +}; + +static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] = +{ + {5277.74,2016.88,707.778,5.96903}, + {5295.88,2040.34,707.778,5.07891}, + {5320.37,1980.13,707.778,2.00713}, + {5280.51,1997.84,707.778,0.296706}, + {5302.45,2042.22,707.778,4.90438}, + {5306.57,1977.47,707.778,1.50098}, +}; + +static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] = +{ + {5312.75,2037.12,707.778,4.59022}, + {5309.58,2042.67,707.778,4.69494}, + {5275.08,2008.72,707.778,6.21337}, + {5279.65,2004.66,707.778,0.069813}, + {5275.48,2001.14,707.778,0.174533}, + {5316.7,2041.55,707.778,4.50295}, +}; + +static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] = +{ + {5302.25,1972.41,707.778,1.37881}, + {5311.03,1972.23,707.778,1.64061}, + {5277.36,1993.23,707.778,0.401426}, + {5318.7,2036.11,707.778,4.2237}, + {5335.72,1996.86,707.778,2.74017}, + {5299.43,1979.01,707.778,1.23918}, +}; + +static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] = +{ + {5306.06,2037,707.778,4.81711}, + {5344.15,2007.17,707.778,3.15905}, + {5337.83,2010.06,707.778,3.22886}, + {5343.29,1999.38,707.778,2.9147}, + {5340.84,1992.46,707.778,2.75762}, + {5325.07,1977.6,707.778,2.07694}, + {5336.6,2017.28,707.778,3.47321}, + {5313.82,1978.15,707.778,1.74533}, + {5280.63,2012.16,707.778,6.05629}, + {5322.96,2040.29,707.778,4.34587}, +}; + +static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] = +{ + {5343.47,2015.95,707.778,3.49066}, + {5337.86,2003.4,707.778,2.98451}, + {5319.16,1974,707.778,1.91986}, + {5299.25,2036,707.778,5.02655}, + {5295.64,1973.76,707.778,1.18682}, + {5282.9,2019.6,707.778,5.88176}, +}; + +struct instance_halls_of_reflection : public ScriptedInstance +{ + instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiFalric; + uint64 uiMarwyn; + uint64 uiLichKingEvent; + uint64 uiJainaPart1; + uint64 uiSylvanasPart1; + + uint64 uiFrostmourne; + uint64 uiFrostmourneAltar; + uint64 uiArthasDoor; + uint64 uiFrontDoor; + + uint32 uiEncounter[MAX_ENCOUNTER]; + uint32 uiTeamInInstance; + uint32 uiWaveCount; + bool bIntroDone; + + EventMap events; + + void Initialize() + { + events.Reset(); + + uiFalric = 0; + uiMarwyn = 0; + uiLichKingEvent = 0; + uiJainaPart1 = 0; + uiSylvanasPart1 = 0; + + uiFrostmourne = 0; + uiFrostmourneAltar = 0; + uiArthasDoor = 0; + uiFrontDoor = 0; + uiTeamInInstance = 0; + uiWaveCount = 0; + bIntroDone = false; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + if (!add) + return; + + Map::PlayerList const &players = instance->GetPlayers(); + if (!players.isEmpty()) + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + + switch(pCreature->GetEntry()) + { + case NPC_FALRIC: + uiFalric = pCreature->GetGUID(); + break; + case NPC_MARWYN: + uiMarwyn = pCreature->GetGUID(); + break; + case NPC_LICH_KING_EVENT: + uiLichKingEvent = pCreature->GetGUID(); + break; + case NPC_JAINA_PART1: + uiJainaPart1 = pCreature->GetGUID(); + break; + case NPC_SYLVANAS_PART1: + uiSylvanasPart1 = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (!add) + return; + + // TODO: init state depending on encounters + switch(pGo->GetEntry()) + { + case GO_FROSTMOURNE: + uiFrostmourne = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, false, pGo); + break; + case GO_FROSTMOURNE_ALTAR: + uiFrostmourneAltar = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, true, pGo); + break; + case GO_FRONT_DOOR: + uiFrontDoor = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, true, pGo); + break; + case GO_ARTHAS_DOOR: + uiArthasDoor = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + + if (uiEncounter[1] == DONE) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + if (type == DATA_WAVE_COUNT && data == SPECIAL) + { + bIntroDone = true; + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + return; + } + + + if (uiWaveCount && data == NOT_STARTED) + DoWipe(); + + switch(type) + { + case DATA_FALRIC_EVENT: + uiEncounter[0] = data; + if (data == DONE) + events.ScheduleEvent(EVENT_NEXT_WAVE, 60000); + break; + case DATA_MARWYN_EVENT: + uiEncounter[1] = data; + if (data == DONE) + HandleGameObject(uiArthasDoor, true); + break; + case DATA_LICHKING_EVENT: + uiEncounter[2] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_FALRIC_EVENT: return uiEncounter[0]; + case DATA_MARWYN_EVENT: return uiEncounter[1]; + case DATA_LICHKING_EVENT: return uiEncounter[2]; + case DATA_WAVE_COUNT: return uiWaveCount; + case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_FALRIC: return uiFalric; + case DATA_MARWYN: return uiMarwyn; + case DATA_LICHKING: return uiLichKingEvent; + case DATA_FROSTMOURNE: return uiFrostmourne; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H R 1 " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 version; + uint16 data0, data1, data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2; + + if (dataHead1 == 'H' && dataHead2 == 'R') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + uiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + if (uiEncounter[0] == DONE || uiEncounter[1] == DONE) + bIntroDone = true; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void AddWave() + { + DoUpdateWorldState(WORLD_STATE_HOR, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); + + switch(uiWaveCount) + { + case 1: + case 2: + case 3: + case 4: + if (Creature *pFalric = instance->GetCreature(uiFalric)) + SpawnWave(pFalric); + break; + case 5: + if (GetData(DATA_FALRIC_EVENT) == DONE) + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + else if (Creature *pFalric = instance->GetCreature(uiFalric)) + if (pFalric->AI()) + pFalric->AI()->DoAction(ACTION_ENTER_COMBAT); + break; + case 6: + case 7: + case 8: + case 9: + if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) + SpawnWave(pMarwyn); + break; + case 10: + if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit! + if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) + if (pMarwyn->AI()) + pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT); + break; + } + } + + // Wipe has been detected. Perform cleanup and reset. + void DoWipe() + { + uiWaveCount = 0; + events.Reset(); + DoUpdateWorldState(WORLD_STATE_HOR, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); + HandleGameObject(uiFrontDoor, true); + + // TODO + // in case of wipe, the event is normally restarted by jumping into the center of the room. + // As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted. + if (Creature* pJaina = instance->GetCreature(uiJainaPart1)) + pJaina->Respawn(); + if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1)) + pSylvanas->Respawn(); + + if (Creature* pFalric = instance->GetCreature(uiFalric)) + pFalric->SetVisibility(VISIBILITY_OFF); + if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) + pMarwyn->SetVisibility(VISIBILITY_OFF); + } + + // spawn a wave on behalf of the summoner. + void SpawnWave(Creature *pSummoner) + { + uint32 index; + + pSummoner->SetVisibility(VISIBILITY_ON); + + // TODO: do composition at random. # of spawn also depends on uiWaveCount + // As of now, it is just one of each. + index = urand(0,ENCOUNTER_WAVE_MERCENARY-1); + pSummoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_FOOTMAN-1); + pSummoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_RIFLEMAN-1); + pSummoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_PRIEST-1); + pSummoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_MAGE-1); + pSummoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + } + + void Update(uint32 diff) + { + if (!instance->HavePlayers()) + return; + + events.Update(diff); + + switch(uint32 eventId = events.ExecuteEvent()) + { + case EVENT_NEXT_WAVE: + uiWaveCount++; + AddWave(); + break; + case EVENT_START_LICH_KING: + // TODO + break; + } + } +}; + +InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap) +{ + return new instance_halls_of_reflection(pMap); +} + +void AddSC_instance_halls_of_reflection() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_reflection"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_reflection; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp new file mode 100644 index 00000000000..25c78c4a0d3 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp @@ -0,0 +1,209 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +enum Yells +{ + SAY_AGGRO = -1658001, + SAY_SLAY_1 = -1658002, + SAY_SLAY_2 = -1658003, + SAY_DEATH = -1658004, + SAY_PHASE2 = -1658005, + SAY_PHASE3 = -1658006, + + SAY_TYRANNUS_DEATH = -1659007, +}; + +enum eEvents +{ + EVENT_NONE, + EVENT_PERMAFROST, + EVENT_THROW_SARONITE, + EVENT_CHILLINGWAVE, + EVENT_DEEPFREEZE, +}; + +enum Spells +{ + SPELL_PERMAFROST = 70326, + SPELL_PERMAFROST_TRIGGER = 68786, // triggered by PERMAFROST. Used to check aura + SPELL_THROW_SARONITE = 68788, + SPELL_THUNDERING_STOMP = 68771, + SPELL_CHILLING_WAVE = 68778, + H_SPELL_CHILLING_WAVE = 70333, + SPELL_DEEP_FREEZE = 70381, + H_SPELL_DEEP_FREEZE = 72930, + SPELL_FORGE_MACE = 68785, + H_SPELL_FORGE_MACE = 70335, + SPELL_FORGE_BLADE = 68774, + H_SPELL_FORGE_BLADE = 70334, +}; + +enum eEnums +{ + EQUIP_ID_SWORD = 49345, + EQUIP_ID_MACE = 49344, + ACHIEV_DOESNT_GO_TO_ELEVEN = 4524, +}; + +struct boss_garfrostAI : public ScriptedAI +{ + boss_garfrostAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + bool phase2; + bool phase3; + bool bAchievement; + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + phase2 = false; + phase3 = false; + bAchievement = true; + + if (pInstance) + pInstance->SetData(DATA_GARFROST_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_PERMAFROST); + + if (pInstance) + pInstance->SetData(DATA_GARFROST_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_THROW_SARONITE, 45000); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& /*uiDamage*/) + { + if (HealthBelowPct(66) && !phase2) + { + phase2 = true; + DoCast(me, SPELL_THUNDERING_STOMP); + // TODO: should go to a forge + DoCast(me, SPELL_FORGE_BLADE); + // TODO: should equip when spell completes + SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + events.ScheduleEvent(EVENT_CHILLINGWAVE, 10000); + } + + if (HealthBelowPct(33) && !phase3) + { + phase3 = true; + DoCast(me, SPELL_THUNDERING_STOMP); + // TODO: should go to a forge + DoCast(me, SPELL_FORGE_MACE); + // TODO: should equip when spell completes + SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + events.CancelEvent(EVENT_CHILLINGWAVE); // cast only in phase 2. + events.ScheduleEvent(EVENT_DEEPFREEZE, 10000); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + { + if (Creature *pTyrannus = me->GetCreature(*me, pInstance->GetData64(DATA_TYRANNUS))) + DoScriptText(SAY_TYRANNUS_DEATH, pTyrannus); + + pInstance->SetData(DATA_GARFROST_EVENT, DONE); + if (IsHeroic() && bAchievement) + pInstance->DoCompleteAchievement(ACHIEV_DOESNT_GO_TO_ELEVEN); + } + } + + void SpellHitTarget(Unit* pTarget, const SpellEntry *spell) + { + if (spell->Id == SPELL_PERMAFROST_TRIGGER && bAchievement) + { + if (Aura *pAura = pTarget->GetAura(SPELL_PERMAFROST_TRIGGER)) + if (pAura->GetStackAmount() > 10) + bAchievement = false; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_THROW_SARONITE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_THROW_SARONITE); + events.RescheduleEvent(EVENT_THROW_SARONITE, 35000); + return; + case EVENT_DEEPFREEZE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DEEP_FREEZE); + events.RescheduleEvent(EVENT_DEEPFREEZE, 35000); + return; + case EVENT_CHILLINGWAVE: + DoCastAOE(SPELL_CHILLING_WAVE); + events.RescheduleEvent(EVENT_CHILLINGWAVE, 40000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_garfrost(Creature* pCreature) +{ + return new boss_garfrostAI (pCreature); +} + +void AddSC_boss_garfrost() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_garfrost"; + newscript->GetAI = &GetAI_boss_garfrost; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp new file mode 100644 index 00000000000..8b8b03a3d4e --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp @@ -0,0 +1,482 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/* + * SDComment: Spell Explosive barrage is not working. + */ + +enum Spells +{ + SPELL_PURSUED = 68987, + SPELL_CONFUSION = 69029, + SPELL_EXPLOSIVE_BARRAGE = 69263, + SPELL_MIGHTY_KICK = 69021, + SPELL_POISON_NOVA = 68989, + H_SPELL_POISON_NOVA = 70434, + SPELL_SHADOW_BOLT = 69028, + SPELL_TOXIC_WASTE = 69024, + H_SPELL_TOXIC_WASTE = 70436, +}; + +enum Yells +{ + // Krick + SAY_KRICK_AGGRO = -1658010, + SAY_KRICK_SLAY_1 = -1658011, + SAY_KRICK_SLAY_2 = -1658012, + SAY_KRICK_BARRAGE_1 = -1658013, + SAY_KRICK_BARRAGE_2 = -1658014, + SAY_KRICK_POISON_NOVA = -1658015, + SAY_KRICK_CHASE_1 = -1658016, + SAY_KRICK_CHASE_2 = -1658017, + SAY_KRICK_CHASE_3 = -1658018, + + // Ick + SAY_ICK_POISON_NOVA = -1658020, + SAY_ICK_CHASE_1 = -1658021, + + // OUTRO + SAY_KRICK_OUTRO_1 = -1658030, + SAY_JAYNA_OUTRO_2 = -1658031, + SAY_SYLVANAS_OUTRO_2 = -1658032, + SAY_KRICK_OUTRO_3 = -1658033, + SAY_JAYNA_OUTRO_4 = -1658034, + SAY_SYLVANAS_OUTRO_4 = -1658035, + SAY_KRICK_OUTRO_5 = -1658036, + SAY_TYRANNUS_OUTRO_7 = -1658037, + SAY_KRICK_OUTRO_8 = -1658038, + SAY_TYRANNUS_OUTRO_9 = -1658039, + SAY_JAYNA_OUTRO_10 = -1658040, + SAY_SYLVANAS_OUTRO_10 = -1658041, +}; + +enum Events +{ + EVENT_NONE, + EVENT_PURSUE, + EVENT_MIGHTY_KICK, + EVENT_POISON_NOVA, + EVENT_EXPLOSIVE_BARRAGE, + EVENT_END_EXPLOSIVE_BARRAGE, + + // Krick + EVENT_SHADOW_BOLT, + EVENT_TOXIC_WASTE, + + // Krick OUTRO + EVENT_OUTRO_1, + EVENT_OUTRO_2, + EVENT_OUTRO_3, + EVENT_OUTRO_4, + EVENT_OUTRO_5, + EVENT_OUTRO_6, + EVENT_OUTRO_7, + EVENT_OUTRO_8, + EVENT_OUTRO_9, + EVENT_OUTRO_10, + EVENT_OUTRO_11, + EVENT_OUTRO_12, + EVENT_OUTRO_END, +}; + +enum KrickPhase +{ + PHASE_COMBAT, + PHASE_OUTRO, +}; + +enum Actions +{ + ACTION_OUTRO, +}; + +enum Misc +{ + SEAT_KRICK = 0, + + // events GCD. Shall not be 0. + GCD_1 = 1, +}; + +// Krick is the Gnome. +// Ick is the Mount +// Common Events are handled/triggered by Ick that "drive" Krick through DoAction. + +struct boss_ickAI : public ScriptedAI +{ + boss_ickAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, NOT_STARTED); + } + + Creature* GetKrick() + { + return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_KRICK) : 0); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, IN_PROGRESS); + + Creature* pKrick = GetKrick(); + if (!pKrick) + pKrick = me->SummonCreature(CREATURE_KRICK, *me, TEMPSUMMON_MANUAL_DESPAWN); + + if (pKrick) + DoScriptText(SAY_KRICK_AGGRO, pKrick); + + events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000, GCD_1); + events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); + events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); + events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 35000); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + } + + void EnterEvadeMode() + { + me->GetMotionMaster()->Clear(); + ScriptedAI::EnterEvadeMode(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (Creature* pKrick = GetKrick()) + { + if (pKrick->AI()) + pKrick->AI()->DoAction(ACTION_OUTRO); + } + + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + return; + + if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch(events.ExecuteEvent()) + { + case EVENT_PURSUE: + if (Creature* pKrick = GetKrick()) + DoScriptText(RAND(SAY_KRICK_CHASE_1,SAY_KRICK_CHASE_2,SAY_KRICK_CHASE_3), pKrick); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->Attack(pTarget,false); + DoScriptText(SAY_ICK_CHASE_1, me, pTarget); + DoCast(pTarget, SPELL_PURSUED); + } + + DoCast(SPELL_CONFUSION); + events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); + return; + + case EVENT_MIGHTY_KICK: + DoCast(me->getVictim(), SPELL_MIGHTY_KICK); + events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000, GCD_1); + return; + + case EVENT_POISON_NOVA: + if (Creature* pKrick = GetKrick()) + DoScriptText(SAY_KRICK_POISON_NOVA, pKrick); + + DoScriptText(SAY_ICK_POISON_NOVA, me); + DoCastAOE(SPELL_POISON_NOVA); + events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); + return; + + case EVENT_TOXIC_WASTE: + DoCast(me->getVictim(), SPELL_TOXIC_WASTE); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + return; + + case EVENT_SHADOW_BOLT: + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + return; + + case EVENT_EXPLOSIVE_BARRAGE: + if (Creature *pKrick = GetKrick()) + { + DoScriptText(SAY_KRICK_BARRAGE_1, pKrick); + DoScriptText(SAY_KRICK_BARRAGE_2, pKrick); + } + + DoCastAOE(SPELL_EXPLOSIVE_BARRAGE); + me->GetMotionMaster()->MoveIdle(); + events.DelayEvents(20000, GCD_1); // 2 sec cast + 18 sec + events.ScheduleEvent(EVENT_END_EXPLOSIVE_BARRAGE, 20000); + return; + + case EVENT_END_EXPLOSIVE_BARRAGE: + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 25000); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_krickAI : public ScriptedAI +{ + boss_krickAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + KrickPhase phase; + uint64 uiNpcOutroDialog; + uint64 uiTyrannus; + + void Reset() + { + uiNpcOutroDialog = 0; + uiTyrannus = 0; + phase = PHASE_COMBAT; + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_OFF); + } + + Creature* GetIck() + { + return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ICK) : 0); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_KRICK_SLAY_1,SAY_KRICK_SLAY_2), me); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + // if killed whatever the reason, it breaks the outro + uiDamage = 0; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_OUTRO: + { + Position pos; + if (Creature* pIck = GetIck()) + { + // TODO: tele on Ick then run some distance. + pIck->GetNearPosition(pos, 5.0f, 3.14); + me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0.0f); + } + me->SetVisibility(VISIBILITY_ON); + + Creature* pJainaOrSylvanas = me->GetCreature(*me, pInstance->GetData64(DATA_JAINA_SYLVANAS_1)); + if (pJainaOrSylvanas) { + Position pos; + me->GetNearPosition(pos, 5.0f, 0); + pJainaOrSylvanas->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), + pos.GetAngle(me->GetPositionX(), me->GetPositionY())); + } + else { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + pJainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); + else + pJainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); + } + + if (pJainaOrSylvanas) + { + pJainaOrSylvanas->SetOrientation(pJainaOrSylvanas->GetAngle(me->GetPositionX(), me->GetPositionY())); + me->SetOrientation(me->GetAngle(pJainaOrSylvanas->GetPositionX(), pJainaOrSylvanas->GetPositionY())); + uiNpcOutroDialog = pJainaOrSylvanas->GetGUID(); + } + + phase = PHASE_OUTRO; + events.Reset(); + events.ScheduleEvent(EVENT_OUTRO_1, 1000); + break; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_OUTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_OUTRO_1: + { + DoScriptText(SAY_KRICK_OUTRO_1, me); + events.ScheduleEvent(EVENT_OUTRO_2, 14000); + break; + } + case EVENT_OUTRO_2: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_2, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_2, pNpcDialog); + } + events.ScheduleEvent(EVENT_OUTRO_3, 8500); + break; + } + case EVENT_OUTRO_3: + DoScriptText(SAY_KRICK_OUTRO_3, me); + events.ScheduleEvent(EVENT_OUTRO_4, 12000); + break; + case EVENT_OUTRO_4: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_4, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_4, pNpcDialog); + } + events.ScheduleEvent(EVENT_OUTRO_5, 8000); + break; + } + case EVENT_OUTRO_5: + DoScriptText(SAY_KRICK_OUTRO_5, me); + events.ScheduleEvent(EVENT_OUTRO_6, 4000); + break; + case EVENT_OUTRO_6: + // TODO spawn Tyrannus at some distance and MovePoint near-by (flying on rimefang) + // store uiTyrannus + // Adjust timer so tyrannus has time to come + uiTyrannus = (pInstance ? pInstance->GetData64(DATA_TYRANNUS) : 0); + events.ScheduleEvent(EVENT_OUTRO_7, 1); + break; + case EVENT_OUTRO_7: + if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) + DoScriptText(SAY_TYRANNUS_OUTRO_7, pTyrannus); + events.ScheduleEvent(EVENT_OUTRO_8, 7000); + break; + case EVENT_OUTRO_8: + DoScriptText(SAY_KRICK_OUTRO_8, me); + // TODO: Tyrannus starts killing Krick. + // there shall be some visual spell effect + events.ScheduleEvent(EVENT_OUTRO_9, 6000); + break; + case EVENT_OUTRO_9: + // tyrannus kills krick + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetHealth(0); + + if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) + DoScriptText(SAY_TYRANNUS_OUTRO_9, pTyrannus); + + events.ScheduleEvent(EVENT_OUTRO_10, 12000); + break; + case EVENT_OUTRO_10: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_10, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_10, pNpcDialog); + } + + // End of OUTRO. for now... + events.ScheduleEvent(EVENT_OUTRO_END, 8000); + break; + } + case EVENT_OUTRO_END: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + pNpcDialog->DisappearAndDie(); + + me->DisappearAndDie(); + break; + } + } + return; + } + } +}; + +CreatureAI* GetAI_boss_ick(Creature* pCreature) +{ + return new boss_ickAI(pCreature); +} + +CreatureAI* GetAI_boss_krick(Creature* pCreature) +{ + return new boss_krickAI(pCreature); +} + +void AddSC_boss_ick() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ick"; + newscript->GetAI = &GetAI_boss_ick; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_krick"; + newscript->GetAI = &GetAI_boss_krick; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp new file mode 100644 index 00000000000..55ffa0b4e4b --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp @@ -0,0 +1,273 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/* + * SDComment: TODO: + * - implement aura for spell Overlord Brand. + * - Intro/Outro + * - improve script of Rimefang + */ + +enum Yells +{ + SAY_AMBUSH_1 = -1658050, + SAY_AMBUSH_2 = -1658051, + SAY_GAUNTLET_START = -1658052, + SAY_INTRO_1 = -1658053, + SAY_INTRO_2 = -1658054, + + SAY_AGGRO = -1658055, + SAY_SLAY_1 = -1658056, + SAY_SLAY_2 = -1658057, + SAY_DEATH = -1658058, + SAY_MARK_RIMEFANG_1 = -1658059, + SAY_MARK_RIMEFANG_2 = -1658060, + SAY_DARK_MIGHT_1 = -1658061, + SAY_DARK_MIGHT_2 = -1658062, + + SAY_GORKUN_OUTRO_1 = -1658063, + SAY_GORKUN_OUTRO_2 = -1658064, + SAY_JAYNA_OUTRO_3 = -1658065, + SAY_SYLVANAS_OUTRO_3 = -1658066, + SAY_JAYNA_OUTRO_4 = -1658067, + SAY_SYLVANAS_OUTRO_4 = -1658068, + SAY_JAYNA_OUTRO_5 = -1658069, +}; + +enum Spells +{ + SPELL_FORCEFUL_SMASH = 69155, + H_SPELL_FORCEFUL_SMASH = 69627, + SPELL_OVERLORDS_BRAND = 69172, + SPELL_DARK_MIGHT = 69167, + H_SPELL_DARK_MIGHT = 69629, + SPELL_HOARFROST = 69246, + SPELL_MARK_OF_RIMEFANG = 69275, + SPELL_ICY_BLAST = 69233, + H_SPELL_ICY_BLAST = 69646, + SPELL_ICY_BLAST_2 = 69238, + H_SPELL_ICY_BLAST_2 = 69628, +}; + +enum Events +{ + EVENT_NONE, + EVENT_FORCEFUL_SMASH, + EVENT_OVERLORDS_BRAND, + EVENT_DARK_MIGHT, + + // Rimefang + EVENT_MARK_OF_RIMEFANG, + EVENT_HOARFROST, + EVENT_ICY_BLAST, + EVENT_ICY_BLAST_2, +}; + +enum Misc +{ + SEAT_TYRANNUS = 0 +}; + +struct boss_tyrannusAI : public ScriptedAI +{ + boss_tyrannusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_TYRANNUS_EVENT, NOT_STARTED); + } + + Creature* GetRimefang() + { + return me->GetCreature(*me, pInstance->GetData64(DATA_RIMEFANG)); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + me->ExitVehicle(); + + // restore health if any damage done during intro + me->SetHealth(me->GetMaxHealth()); + + if (pInstance) + pInstance->SetData(DATA_TYRANNUS_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); + events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 35000); + events.ScheduleEvent(EVENT_DARK_MIGHT, 40000); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_TYRANNUS_EVENT, DONE); + if (Creature* pRimefang = GetRimefang()) + pRimefang->ForcedDespawn(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FORCEFUL_SMASH: + DoCast(me->getVictim(), SPELL_FORCEFUL_SMASH); + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); + return; + case EVENT_OVERLORDS_BRAND: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_OVERLORDS_BRAND); + events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 45000); + return; + case EVENT_DARK_MIGHT: + DoScriptText(SAY_DARK_MIGHT_1, me); + DoScriptText(SAY_DARK_MIGHT_2, me); + DoCast(me, SPELL_DARK_MIGHT); + events.ScheduleEvent(EVENT_DARK_MIGHT, 60000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_rimefangAI : public ScriptedAI +{ + boss_rimefangAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 25000); + events.ScheduleEvent(EVENT_ICY_BLAST, 35000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_MARK_OF_RIMEFANG: + DoScriptText(SAY_MARK_RIMEFANG_1, me); + DoScriptText(SAY_MARK_RIMEFANG_2, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MARK_OF_RIMEFANG); + events.ScheduleEvent(EVENT_HOARFROST, 5000); + return; + case EVENT_HOARFROST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_HOARFROST); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 20000); + return; + case EVENT_ICY_BLAST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ICY_BLAST); + events.ScheduleEvent(EVENT_ICY_BLAST_2, 5000); + return; + case EVENT_ICY_BLAST_2: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget->getVictim(), SPELL_ICY_BLAST_2); + events.ScheduleEvent(EVENT_ICY_BLAST, 30000); + return; + } + } + } +}; + +CreatureAI* GetAI_boss_tyrannus(Creature* pCreature) +{ + return new boss_tyrannusAI(pCreature); +} + +CreatureAI* GetAI_boss_rimefang(Creature* pCreature) +{ + return new boss_rimefangAI(pCreature); +} + +void AddSC_boss_tyrannus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_tyrannus"; + newscript->GetAI = &GetAI_boss_tyrannus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="boss_rimefang"; + newscript->GetAI = &GetAI_boss_rimefang; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp new file mode 100644 index 00000000000..8512eca24c1 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp @@ -0,0 +1,236 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +#define MAX_ENCOUNTER 3 + +/* Pit of Saron encounters: +0- Forgemaster Garfrost +1- Krick and Ick +2- Scourgelord Tyrannus +*/ + +struct instance_pit_of_saron : public ScriptedInstance +{ + instance_pit_of_saron(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiKrick; + uint64 uiIck; + uint64 uiGarfrost; + uint64 uiTyrannus; + uint64 uiRimefang; + + uint64 uiJainaOrSylvanas1; + uint64 uiJainaOrSylvanas2; + + uint32 uiTeamInInstance; + uint32 uiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + + uiGarfrost = 0; + uiKrick = 0; + uiIck = 0; + uiTyrannus = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + } + + switch(pCreature->GetEntry()) + { + case CREATURE_KRICK: + uiKrick = pCreature->GetGUID(); + break; + + case CREATURE_ICK: + uiIck = pCreature->GetGUID(); + break; + + case CREATURE_GARFROST: + uiGarfrost = pCreature->GetGUID(); + break; + + case CREATURE_TYRANNUS: + uiTyrannus = pCreature->GetGUID(); + break; + + case CREATURE_RIMEFANG: + uiRimefang = pCreature->GetGUID(); + break; + + case NPC_SYLVANAS_PART1: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); + uiJainaOrSylvanas1 = pCreature->GetGUID(); + break; + case NPC_SYLVANAS_PART2: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); + uiJainaOrSylvanas2 = pCreature->GetGUID(); + break; + case NPC_KILARA: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_ELANDRA, ALLIANCE); + break; + case NPC_KORALEN: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_KORLAEN, ALLIANCE); + break; + case NPC_CHAMPION_1_HORDE: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_2_HORDE: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_GARFROST: return uiGarfrost; + case DATA_KRICK: return uiKrick; + case DATA_ICK: return uiIck; + case DATA_TYRANNUS: return uiTyrannus; + case DATA_RIMEFANG: return uiRimefang; + + case DATA_JAINA_SYLVANAS_1: return uiJainaOrSylvanas1; + case DATA_JAINA_SYLVANAS_2: return uiJainaOrSylvanas2; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_GARFROST_EVENT: + uiEncounter[0] = data; + break; + case DATA_TYRANNUS_EVENT: + uiEncounter[1] = data; + break; + case DATA_KRICKANDICK_EVENT: + uiEncounter[2] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_GARFROST_EVENT: return uiEncounter[0]; + case DATA_TYRANNUS_EVENT: return uiEncounter[1]; + case DATA_KRICKANDICK_EVENT: return uiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::string str_data; + + std::ostringstream saveStream; + saveStream << "P S " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; + + if (dataHead1 == 'P' && dataHead2 == 'S') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + uiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_pit_of_saron(Map* pMap) +{ + return new instance_pit_of_saron(pMap); +} + +void AddSC_instance_pit_of_saron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_pit_of_saron"; + newscript->GetInstanceData = &GetInstanceData_instance_pit_of_saron; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp new file mode 100644 index 00000000000..bc53efc7033 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp @@ -0,0 +1,1101 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/***************************************SPELLS*************************************/ +// Ymirjar Wrathbringer +#define SPELL_BLIGHT DUNGEON_MODE(69603,70285) + +//Ymirjar Skycaller +#define SPELL_FROSTBLADE 70291 +#define SPELL_GLACIAL_STRIKE 70292 + +//Ymirjar Flamebearer +#define SPELL_FIREBALL DUNGEON_MODE(69583,70282) +#define SPELL_HELLFIRE DUNGEON_MODE(69586,70283) +#define SPELL_TACTICAL_BLINK 69584 + +//Ymirjar Deathbringer +#define SPELL_EMPOWERED_SHADOW_BOLT DUNGEON_MODE(69528,70281) +#define SPELL_SUMMON_UNDEAD 69516 + +//Wrathbone Laborer +#define SPELL_BLINDING_DIRT 70302 +#define SPELL_PUNCTURE_WOUND DUNGEON_MODE(70278,70279) +#define SPELL_SHOVELLED DUNGEON_MODE(69572,70280) + +//Wrathbone Coldwraith +#define SPELL_FREEZING_CIRCLE DUNGEON_MODE(69574,70276) +#define SPELL_FROSTBOLT DUNGEON_MODE(69573,70277) + +//Stonespine Gargoyle +#define SPELL_GARGOYLE_STRIKE DUNGEON_MODE(69520,70275) +#define SPELL_STONEFORM 69575 + +// Plagueborn Horror +#define SPELL_BLIGHT_BOMB 69582 +#define SPELL_PUSTULANT_FLESH DUNGEON_MODE(69581,70273) +#define SPELL_TOXIC_WASTE 70274 + +//Iceborn Proto-Drake +#define SPELL_FROST_BREATH DUNGEON_MODE(69527,70272) + +//Hungering Ghoul +#define SPELL_DEVOUR_FLESH 70393 + +//Fallen Warrior +#define SPELL_ARCING_SLICE 69579 +#define SPELL_DEMORALIZING_SHOUT 61044 +#define SPELL_SHIELD_BLOCK 69580 + +//Deathwhisper Torturer +#define SPELL_BLACK_BRAND 70392 +#define SPELL_CURSE_OF_AGONY 70391 + +//Deathwhisper Shadowcaster +#define SPELL_SHADOW_BOLT DUNGEON_MODE(70386,70387) + +//Deathwhisper Necrolyte +#define SPELL_CONVERSION_BEAM DUNGEON_MODE(69578,70269) +#define SPELL_SHADOW_BOLT_2 DUNGEON_MODE(69577,70270) + +//Wrathbone Sorcerer +#define SPELL_SHADOW_BOLT_3 DUNGEON_MODE(70386,70387) + +//Geist Ambusher +#define SPELL_LEAPING_FACE_MAUL DUNGEON_MODE(69504,70271) + +/****************************************EVENTS************************************/ +enum eEvents +{ + EVENT_NONE, + + // Ymirjar Wrathbringer + EVENT_BLIGHT, + + // Ymirjar Skycaller + EVENT_FROSTBLADE, + EVENT_GLACIAL_STRIKE, + + // Ymirjar Flamebearer + EVENT_FIREBALL, + EVENT_HELLFIRE, + EVENT_TACTICAL_BLINK, + + //Ymirjar Deathbringer + EVENT_EMPOWERED_SHADOW_BOLT, + EVENT_SUMMON_UNDEAD, + + //Wrathbone Laborer + EVENT_BLINDING_DIRT, + EVENT_PUNCTURE_WOUND, + EVENT_SHOVELLED, + + //Wrathbone Coldwraith + EVENT_FREEZING_CIRCLE, + EVENT_FROSTBOLT, + + //Stonespine Gargoyle + EVENT_GARGOYLE_STRIKE, + EVENT_STONEFORM, + + //Plagueborn Horror + EVENT_BLIGHT_BOMB, + EVENT_PUSTULANT_FLESH, + EVENT_TOXIC_WASTE, + + //Iceborn Proto-Drake + EVENT_FROST_BREATH, + + //Hungering Ghoul + EVENT_DEVOUR_FLESH, + + //Fallen Warrior + EVENT_ARCING_SLICE, + EVENT_DEMORALIZING_SHOUT, + EVENT_SHIELD_BLOCK, + + //Deathwhisper Torturer + EVENT_BLACK_BRAND, + EVENT_CURSE_OF_AGONY, + + //Deathwhisper Shadowcaster + EVENT_SHADOW_BOLT, + + //Deathwhisper Necrolyte + EVENT_CONVERSION_BEAM, + EVENT_SHADOW_BOLT_2, + + EVENT_SHADOW_BOLT_3, + + //Geist Ambusher + EVENT_LEAPING_FACE_MAUL, +}; + +/****************************************AI****************************************/ +struct mob_ymirjar_wrathbringerAI : public ScriptedAI +{ + mob_ymirjar_wrathbringerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLIGHT, 7000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLIGHT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLIGHT); + events.RescheduleEvent(EVENT_BLIGHT, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_skyCallerAI: public ScriptedAI +{ + mob_ymirjar_skyCallerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROSTBLADE, 1); + events.ScheduleEvent(EVENT_GLACIAL_STRIKE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_GLACIAL_STRIKE: + DoCast(me->getVictim(), SPELL_GLACIAL_STRIKE); + events.RescheduleEvent(EVENT_GLACIAL_STRIKE, 8000); + return; + case EVENT_FROSTBLADE: + DoCast(me, SPELL_FROSTBLADE); + events.CancelEvent(EVENT_FROSTBLADE); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_flamebearerAI: public ScriptedAI +{ + mob_ymirjar_flamebearerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FIREBALL, 4000); + events.ScheduleEvent(EVENT_HELLFIRE, 8000); + events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FIREBALL: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FIREBALL); + events.RescheduleEvent(EVENT_FIREBALL, 5000); + return; + case EVENT_HELLFIRE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_HELLFIRE); + events.RescheduleEvent(EVENT_HELLFIRE, 10000); + return; + case EVENT_TACTICAL_BLINK: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_TACTICAL_BLINK); + events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_deathbringerAI: public ScriptedAI +{ + mob_ymirjar_deathbringerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_EMPOWERED_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_EMPOWERED_SHADOW_BOLT); + events.RescheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_laborerAI: public ScriptedAI +{ + mob_wrathbone_laborerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); + events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + events.ScheduleEvent(EVENT_SHOVELLED, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLINDING_DIRT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLINDING_DIRT); + events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); + return; + case EVENT_PUNCTURE_WOUND: + DoCast(me->getVictim(), SPELL_PUNCTURE_WOUND); + events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + return; + case EVENT_SHOVELLED: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHOVELLED); + events.RescheduleEvent(EVENT_SHOVELLED, 7000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_coldwraithAI: public ScriptedAI +{ + mob_wrathbone_coldwraithAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FREEZING_CIRCLE, 9000); + events.ScheduleEvent(EVENT_FROSTBOLT, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FREEZING_CIRCLE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FREEZING_CIRCLE); + events.RescheduleEvent(EVENT_FREEZING_CIRCLE, 9000); + return; + case EVENT_FROSTBOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FROSTBOLT); + events.RescheduleEvent(EVENT_FROSTBOLT, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_stonespine_gargoyleAI: public ScriptedAI +{ + mob_stonespine_gargoyleAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_GARGOYLE_STRIKE, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_GARGOYLE_STRIKE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_GARGOYLE_STRIKE); + events.RescheduleEvent(EVENT_GARGOYLE_STRIKE, 6000); + return; + case EVENT_STONEFORM: + if (HealthBelowPct(10)) + DoCast(me, SPELL_STONEFORM); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_plagueborn_horrorAI: public ScriptedAI +{ + mob_plagueborn_horrorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLIGHT_BOMB, 999999); + events.ScheduleEvent(EVENT_PUSTULANT_FLESH, 5000); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLIGHT_BOMB: + if (HealthBelowPct(15)) + DoCast(me, SPELL_BLIGHT_BOMB); + return; + case EVENT_PUSTULANT_FLESH: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_PUSTULANT_FLESH); + events.RescheduleEvent(EVENT_PUSTULANT_FLESH, 10000); + return; + case EVENT_TOXIC_WASTE: + DoCast(me, SPELL_TOXIC_WASTE); + events.RescheduleEvent(EVENT_TOXIC_WASTE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_iceborn_protodrakeAI: public ScriptedAI +{ + mob_iceborn_protodrakeAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROST_BREATH, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROST_BREATH: + DoCast(me->getVictim(), SPELL_FROST_BREATH); + events.RescheduleEvent(EVENT_FROST_BREATH, 10000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_hungering_ghoulAI: public ScriptedAI +{ + mob_hungering_ghoulAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_DEVOUR_FLESH, 4000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_DEVOUR_FLESH: + DoCast(me->getVictim(), SPELL_DEVOUR_FLESH); + events.RescheduleEvent(EVENT_DEVOUR_FLESH, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_fallen_warriorAI: public ScriptedAI +{ + mob_fallen_warriorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_ARCING_SLICE, 8000); + events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); + events.ScheduleEvent(EVENT_SHIELD_BLOCK, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ARCING_SLICE: + DoCast(me->getVictim(), SPELL_ARCING_SLICE); + events.RescheduleEvent(EVENT_ARCING_SLICE, 10000); + return; + case EVENT_DEMORALIZING_SHOUT: + DoCast(me, SPELL_DEMORALIZING_SHOUT); + events.RescheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); + return; + case EVENT_SHIELD_BLOCK: + DoCast(me->getVictim(), SPELL_SHIELD_BLOCK); + events.RescheduleEvent(EVENT_SHIELD_BLOCK, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_torturerAI: public ScriptedAI +{ + mob_deathwhisper_torturerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLACK_BRAND, 10000); + events.ScheduleEvent(EVENT_CURSE_OF_AGONY, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLACK_BRAND: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLACK_BRAND); + events.RescheduleEvent(EVENT_BLACK_BRAND, 10000); + return; + case EVENT_CURSE_OF_AGONY: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CURSE_OF_AGONY); + events.RescheduleEvent(EVENT_CURSE_OF_AGONY, 13000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_shadowcasterAI: public ScriptedAI +{ + mob_deathwhisper_shadowcasterAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_BOLT, 3000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_necrolyteAI: public ScriptedAI +{ + mob_deathwhisper_necrolyteAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_CONVERSION_BEAM, 12000); + events.ScheduleEvent(EVENT_SHADOW_BOLT_2, 4000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CONVERSION_BEAM: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CONVERSION_BEAM); + events.RescheduleEvent(EVENT_CONVERSION_BEAM, 12000); + return; + case EVENT_SHADOW_BOLT_2: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT_2); + events.RescheduleEvent(EVENT_SHADOW_BOLT_2, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_sorcererAI: public ScriptedAI +{ + mob_wrathbone_sorcererAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_BOLT_3, 3000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_BOLT_3: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT_3); + events.RescheduleEvent(EVENT_SHADOW_BOLT_3, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_geist_ambusherAI: public ScriptedAI +{ + mob_geist_ambusherAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + //Only here so when I figure out how to make it cast on an NPC i can do that. + events.ScheduleEvent(EVENT_LEAPING_FACE_MAUL, 99999); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + //Should only be used on NPCs + case EVENT_LEAPING_FACE_MAUL: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_LEAPING_FACE_MAUL); + events.CancelEvent(EVENT_LEAPING_FACE_MAUL); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_ymirjar_wrathbringerAI(Creature* pCreature) +{ + return new mob_ymirjar_wrathbringerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_skyCallerAI(Creature* pCreature) +{ + return new mob_ymirjar_skyCallerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_flamebearerAI(Creature* pCreature) +{ + return new mob_ymirjar_flamebearerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_deathbringerAI(Creature* pCreature) +{ + return new mob_ymirjar_deathbringerAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_laborerAI(Creature* pCreature) +{ + return new mob_wrathbone_laborerAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_coldwraithAI(Creature* pCreature) +{ + return new mob_wrathbone_coldwraithAI(pCreature); +} + +CreatureAI* GetAI_mob_stonespine_gargoyleAI(Creature* pCreature) +{ + return new mob_stonespine_gargoyleAI(pCreature); +} + +CreatureAI* GetAI_mob_plagueborn_horrorAI(Creature* pCreature) +{ + return new mob_plagueborn_horrorAI(pCreature); +} + +CreatureAI* GetAI_mob_iceborn_protodrakeAI(Creature* pCreature) +{ + return new mob_iceborn_protodrakeAI(pCreature); +} + +CreatureAI* GetAI_mob_hungering_ghoulAI(Creature* pCreature) +{ + return new mob_hungering_ghoulAI(pCreature); +} + +CreatureAI* GetAI_mob_fallen_warriorAI(Creature* pCreature) +{ + return new mob_fallen_warriorAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_torturerAI(Creature* pCreature) +{ + return new mob_deathwhisper_torturerAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_shadowcasterAI(Creature* pCreature) +{ + return new mob_deathwhisper_shadowcasterAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_necrolyteAI(Creature* pCreature) +{ + return new mob_deathwhisper_necrolyteAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_sorcererAI(Creature* pCreature) +{ + return new mob_wrathbone_sorcererAI(pCreature); +} + +CreatureAI* GetAI_mob_geist_ambusherAI(Creature* pCreature) +{ + return new mob_geist_ambusherAI(pCreature); +} + +void AddSC_pit_of_saron() +{ + Script *newscript; + newscript = new Script; + newscript->Name="mob_ymirjar_wrathbringer"; + newscript->GetAI = &GetAI_mob_ymirjar_wrathbringerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_skycaller"; + newscript->GetAI = &GetAI_mob_ymirjar_skyCallerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_flamebearer"; + newscript->GetAI = &GetAI_mob_ymirjar_flamebearerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_deathbringer"; + newscript->GetAI = &GetAI_mob_ymirjar_deathbringerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_laborer"; + newscript->GetAI = &GetAI_mob_wrathbone_laborerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_coldwraith"; + newscript->GetAI = &GetAI_mob_wrathbone_coldwraithAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_stonespine_gargoyle"; + newscript->GetAI = &GetAI_mob_stonespine_gargoyleAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_plagueborn_horror"; + newscript->GetAI = &GetAI_mob_plagueborn_horrorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_iceborn_protodrake"; + newscript->GetAI = &GetAI_mob_iceborn_protodrakeAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_hungering_ghoul"; + newscript->GetAI = &GetAI_mob_hungering_ghoulAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_fallen_warrior"; + newscript->GetAI = &GetAI_mob_fallen_warriorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_torturer"; + newscript->GetAI = &GetAI_mob_deathwhisper_torturerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_shadowcaster"; + newscript->GetAI = &GetAI_mob_deathwhisper_shadowcasterAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_necrolyte"; + newscript->GetAI = &GetAI_mob_deathwhisper_necrolyteAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_sorcerer"; + newscript->GetAI = &GetAI_mob_wrathbone_sorcererAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_geist_ambusher"; + newscript->GetAI = &GetAI_mob_geist_ambusherAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h new file mode 100644 index 00000000000..4a221d17518 --- /dev/null +++ b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_PIT_OF_SARON_H +#define DEF_PIT_OF_SARON_H + +enum Data +{ + DATA_GARFROST_EVENT, + DATA_KRICKANDICK_EVENT, + DATA_TYRANNUS_EVENT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_GARFROST, + DATA_KRICK, + DATA_ICK, + DATA_TYRANNUS, + DATA_RIMEFANG, + + DATA_JAINA_SYLVANAS_1, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. + DATA_JAINA_SYLVANAS_2, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. +}; + +enum Creatures +{ + CREATURE_GARFROST = 36494, + CREATURE_KRICK = 36477, + CREATURE_ICK = 36476, + CREATURE_TYRANNUS = 36658, + CREATURE_RIMEFANG = 36661, + + NPC_SYLVANAS_PART1 = 36990, + NPC_SYLVANAS_PART2 = 38189, + NPC_JAINA_PART1 = 36993, + NPC_JAINA_PART2 = 38188, + NPC_KILARA = 37583, + NPC_ELANDRA = 37774, + NPC_KORALEN = 37779, + NPC_KORLAEN = 37582, + NPC_CHAMPION_1_HORDE = 37584, + NPC_CHAMPION_2_HORDE = 37587, + NPC_CHAMPION_3_HORDE = 37588, + NPC_CHAMPION_1_ALLIANCE = 37496, + NPC_CHAMPION_2_ALLIANCE = 37497, +}; + +#endif diff --git a/src/server/scripts/Northrend/grizzly_hills.cpp b/src/server/scripts/Northrend/grizzly_hills.cpp new file mode 100644 index 00000000000..4b6d65a9764 --- /dev/null +++ b/src/server/scripts/Northrend/grizzly_hills.cpp @@ -0,0 +1,625 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Grizzly_Hills +SD%Complete: 80 +SDComment: Quest support: 12231, 12247 +SDCategory: Grizzly Hills +EndScriptData */ + +/* ContentData +npc_orsonn_and_kodian +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +#define GOSSIP_ITEM1 "You're free to go Orsonn, but first tell me what's wrong with the furbolg." +#define GOSSIP_ITEM2 "What happened then?" +#define GOSSIP_ITEM3 "Thank you, Son of Ursoc. I'll see what can be done." +#define GOSSIP_ITEM4 "Who was this stranger?" +#define GOSSIP_ITEM5 "Thank you, Kodian. I'll do what I can." + +enum eEnums +{ + GOSSIP_TEXTID_ORSONN1 = 12793, + GOSSIP_TEXTID_ORSONN2 = 12794, + GOSSIP_TEXTID_ORSONN3 = 12796, + + GOSSIP_TEXTID_KODIAN1 = 12797, + GOSSIP_TEXTID_KODIAN2 = 12798, + + NPC_ORSONN = 27274, + NPC_KODIAN = 27275, + + //trigger creatures + NPC_ORSONN_CREDIT = 27322, + NPC_KODIAN_CREDIT = 27321, + + QUEST_CHILDREN_OF_URSOC = 12247, + QUEST_THE_BEAR_GODS_OFFSPRING = 12231 +}; + +bool GossipHello_npc_orsonn_and_kodian(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_CHILDREN_OF_URSOC) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_THE_BEAR_GODS_OFFSPRING) == QUEST_STATUS_INCOMPLETE) + { + switch(pCreature->GetEntry()) + { + case NPC_ORSONN: + if (!pPlayer->GetReqKillOrCastCurrentCount(QUEST_CHILDREN_OF_URSOC, NPC_ORSONN_CREDIT) || !pPlayer->GetReqKillOrCastCurrentCount(QUEST_THE_BEAR_GODS_OFFSPRING, NPC_ORSONN_CREDIT)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN1, pCreature->GetGUID()); + return true; + } + break; + case NPC_KODIAN: + if (!pPlayer->GetReqKillOrCastCurrentCount(QUEST_CHILDREN_OF_URSOC, NPC_KODIAN_CREDIT) || !pPlayer->GetReqKillOrCastCurrentCount(QUEST_THE_BEAR_GODS_OFFSPRING, NPC_KODIAN_CREDIT)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_KODIAN1, pCreature->GetGUID()); + return true; + } + break; + } + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_orsonn_and_kodian(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN2, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN3, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->TalkedToCreature(NPC_ORSONN_CREDIT, pCreature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_KODIAN2, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->TalkedToCreature(NPC_KODIAN_CREDIT, pCreature->GetGUID()); + break; + } + + return true; +} + +/*###### +## Quest 12027: Mr. Floppy's Perilous Adventure +######*/ + +enum eFloppy +{ + NPC_MRFLOPPY = 26589, + NPC_HUNGRY_WORG = 26586, + NPC_RAVENOUS_WORG = 26590, //RWORG + NPC_EMILY = 26588, + + QUEST_PERILOUS_ADVENTURE = 12027, + + SPELL_MRFLOPPY = 47184, //vehicle aura + + SAY_WORGHAGGRO1 = -1800001, //Um... I think one of those wolves is back... + SAY_WORGHAGGRO2 = -1800002, //He's going for Mr. Floppy! + SAY_WORGRAGGRO3 = -1800003, //Oh, no! Look, it's another wolf, and it's a biiiiiig one! + SAY_WORGRAGGRO4 = -1800004, //He's gonna eat Mr. Floppy! You gotta help Mr. Floppy! You just gotta! + SAY_RANDOMAGGRO = -1800005, //There's a big meanie attacking Mr. Floppy! Help! + SAY_VICTORY1 = -1800006, //Let's get out of here before more wolves find us! + SAY_VICTORY2 = -1800007, //Don't go toward the light, Mr. Floppy! + SAY_VICTORY3 = -1800008, //Mr. Floppy, you're ok! Thank you so much for saving Mr. Floppy! + SAY_VICTORY4 = -1800009, //I think I see the camp! We're almost home, Mr. Floppy! Let's go! + TEXT_EMOTE_WP1 = -1800010, //Mr. Floppy revives + TEXT_EMOTE_AGGRO = -1800011, //The Ravenous Worg chomps down on Mr. Floppy + SAY_QUEST_ACCEPT = -1800012, //Are you ready, Mr. Floppy? Stay close to me and watch out for those wolves! + SAY_QUEST_COMPLETE = -1800013 //Thank you for helping me get back to the camp. Go tell Walter that I'm safe now! +}; + +//emily +struct npc_emilyAI : public npc_escortAI +{ + npc_emilyAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + uint32 m_uiChatTimer; + + uint64 RWORGGUID; + uint64 MrfloppyGUID; + + bool Completed; + + void JustSummoned(Creature* pSummoned) + { + if (Creature* Mrfloppy = GetClosestCreatureWithEntry(me, NPC_MRFLOPPY, 50.0f)) + pSummoned->AI()->AttackStart(Mrfloppy); + else + pSummoned->AI()->AttackStart(me->getVictim()); + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + if (!pPlayer) + return; + switch (i) + { + case 9: + if (Creature *Mrfloppy = GetClosestCreatureWithEntry(me, NPC_MRFLOPPY, 100.0f)) + MrfloppyGUID = Mrfloppy->GetGUID(); + break; + case 10: + if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) + { + DoScriptText(SAY_WORGHAGGRO1, me); + me->SummonCreature(NPC_HUNGRY_WORG,me->GetPositionX()+5,me->GetPositionY()+2,me->GetPositionZ()+1,3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); + } + break; + case 11: + if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) + Mrfloppy->GetMotionMaster()->MoveFollow(me, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + break; + case 17: + if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) + Mrfloppy->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + DoScriptText(SAY_WORGRAGGRO3, me); + if (Creature *RWORG = me->SummonCreature(NPC_RAVENOUS_WORG,me->GetPositionX()+10,me->GetPositionY()+8,me->GetPositionZ()+2,3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000)) + { + RWORG->setFaction(35); + RWORGGUID = RWORG->GetGUID(); + } + break; + case 18: + if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) + { + if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) + RWORG->GetMotionMaster()->MovePoint(0, Mrfloppy->GetPositionX(), Mrfloppy->GetPositionY(), Mrfloppy->GetPositionZ()); + DoCast(Mrfloppy,SPELL_MRFLOPPY); + } + break; + case 19: + if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) + { + if (Mrfloppy->HasAura(SPELL_MRFLOPPY, 0)) + { + if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) + Mrfloppy->EnterVehicle(RWORG); + } + } + break; + case 20: + if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) + RWORG->HandleEmoteCommand(34); + break; + case 21: + if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) + { + if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) + { + RWORG->Kill(Mrfloppy); + Mrfloppy->ExitVehicle(); + RWORG->setFaction(14); + RWORG->GetMotionMaster()->MovePoint(0, RWORG->GetPositionX()+10,RWORG->GetPositionY()+80,RWORG->GetPositionZ()); + DoScriptText(SAY_VICTORY2, me); + } + } + break; + case 22: + if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) + { + if (Mrfloppy->isDead()) + { + if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) + RWORG->DisappearAndDie(); + me->GetMotionMaster()->MovePoint(0, Mrfloppy->GetPositionX(), Mrfloppy->GetPositionY(), Mrfloppy->GetPositionZ()); + Mrfloppy->setDeathState(ALIVE); + Mrfloppy->GetMotionMaster()->MoveFollow(me, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + DoScriptText(SAY_VICTORY3, me); + } + } + break; + case 24: + if (pPlayer) + { + Completed = true; + pPlayer->GroupEventHappens(QUEST_PERILOUS_ADVENTURE, me); + DoScriptText(SAY_QUEST_COMPLETE, me, pPlayer); + } + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 25: + DoScriptText(SAY_VICTORY4, me); + break; + case 27: + me->DisappearAndDie(); + if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) + Mrfloppy->DisappearAndDie(); + break; + } + } + + void EnterCombat(Unit* /*Who*/) + { + DoScriptText(SAY_RANDOMAGGRO, me); + } + + void Reset() + { + m_uiChatTimer = 4000; + MrfloppyGUID = 0; + RWORGGUID = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (m_uiChatTimer <= uiDiff) + { + m_uiChatTimer = 12000; + } + else + m_uiChatTimer -= uiDiff; + } + } +}; + +bool QuestAccept_npc_emily(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_PERILOUS_ADVENTURE) + { + DoScriptText(SAY_QUEST_ACCEPT, pCreature); + if (Creature* Mrfloppy = GetClosestCreatureWithEntry(pCreature, NPC_MRFLOPPY, 180.0f)) + { + Mrfloppy->GetMotionMaster()->MoveFollow(pCreature, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + } + + if (npc_escortAI* pEscortAI = CAST_AI(npc_emilyAI, (pCreature->AI()))) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_emily(Creature* pCreature) +{ + return new npc_emilyAI(pCreature); +} + +//mrfloppy + +struct npc_mrfloppyAI : public ScriptedAI +{ + npc_mrfloppyAI(Creature *c) : ScriptedAI(c) {} + + uint64 EmilyGUID; + uint64 RWORGGUID; + uint64 HWORGGUID; + + void Reset() {} + + void EnterCombat(Unit* Who) + { + if (Creature* Emily = GetClosestCreatureWithEntry(me, NPC_EMILY, 50.0f)) + { + switch(Who->GetEntry()) + { + case NPC_HUNGRY_WORG: + DoScriptText(SAY_WORGHAGGRO2, Emily); + break; + case NPC_RAVENOUS_WORG: + DoScriptText(SAY_WORGRAGGRO4, Emily); + break; + default: + DoScriptText(SAY_RANDOMAGGRO, Emily); + } + } + } + + void EnterEvadeMode() {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_npc_mrfloppy(Creature* pCreature) +{ + return new npc_mrfloppyAI(pCreature); +} + +// Outhouse Bunny + +enum eOuthouseBunny +{ + SPELL_OUTHOUSE_GROANS = 48382, + SPELL_CAMERA_SHAKE = 47533, + SPELL_DUST_FIELD = 48329 +}; + +enum eSounds +{ + SOUND_FEMALE = 12671, + SOUND_MALE = 12670 +}; +struct npc_outhouse_bunnyAI : public ScriptedAI +{ + npc_outhouse_bunnyAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint8 m_counter; + uint8 m_gender; + + void Reset() + { + m_counter = 0; + m_gender = 0; + } + + void SetData(uint32 uiType, uint32 uiData) + { + if (uiType == 1) + m_gender = uiData; + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_OUTHOUSE_GROANS) + { + ++m_counter; + if (m_counter < 5) + DoCast(pCaster, SPELL_CAMERA_SHAKE, true); + else + m_counter = 0; + DoCast(me, SPELL_DUST_FIELD, true); + switch (m_gender) + { + case GENDER_FEMALE: DoPlaySoundToSet(me, SOUND_FEMALE); break; + case GENDER_MALE: DoPlaySoundToSet(me, SOUND_MALE); break; + } + } + } +}; + +CreatureAI* GetAI_npc_outhouse_bunny(Creature* pCreature) +{ + return new npc_outhouse_bunnyAI (pCreature); +} + +// Tallhorn Stage + +enum etallhornstage +{ + OBJECT_HAUNCH = 188665 +}; + +struct npc_tallhorn_stagAI : public ScriptedAI +{ + npc_tallhorn_stagAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint8 m_uiPhase; + + void Reset() + { + m_uiPhase = 1; + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (m_uiPhase == 1) + { + if (GameObject* haunch = me->FindNearestGameObject(OBJECT_HAUNCH, 2.0f)) + { + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + } + m_uiPhase = 0; + } + } +}; + +CreatureAI* GetAI_npc_tallhorn_stag(Creature* pCreature) +{ + return new npc_tallhorn_stagAI (pCreature); +} + +// Amberpine Woodsman + +enum eamberpinewoodsman +{ + TALLHORN_STAG = 26363 +}; + +struct npc_amberpine_woodsmanAI : public ScriptedAI +{ + npc_amberpine_woodsmanAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint8 m_uiPhase; + uint32 m_uiTimer; + + void Reset() + { + m_uiTimer = 0; + m_uiPhase = 1; + } + + void UpdateAI(const uint32 uiDiff) + { + // call this each update tick? + if (Creature* stag = me->FindNearestCreature(TALLHORN_STAG, 0.2f)) + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USESTANDING); + } + else + if (m_uiPhase) + { + if (m_uiTimer <= uiDiff) + { + switch(m_uiPhase) + { + case 1: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_LOOT); + m_uiTimer = 3000; + m_uiPhase = 2; + break; + case 2: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACK1H); + m_uiTimer = 4000; + m_uiPhase = 1; + break; + } + } + else + m_uiTimer -= uiDiff; + } + ScriptedAI::UpdateAI(uiDiff); + + UpdateVictim(); + } +}; + +/*###### +## Quest 12288: Overwhelmed! +######*/ + +enum eSkirmisher +{ + SPELL_RENEW_SKIRMISHER = 48812, + CREDIT_NPC = 27466, + + RANDOM_SAY_1 = -1800044, //Ahh..better.. + RANDOM_SAY_2 = -1800045, //Whoa.. i nearly died there. Thank you, $Race! + RANDOM_SAY_3 = -1800046 //Thank you. $Class! +}; + +struct npc_wounded_skirmisherAI : public ScriptedAI +{ + npc_wounded_skirmisherAI(Creature *c) : ScriptedAI(c) {} + + uint64 uiPlayerGUID; + + uint32 DespawnTimer; + + void Reset () + { + DespawnTimer = 5000; + uiPlayerGUID = 0; + } + + void MovementInform(uint32, uint32 id) + { + if (id == 1) + me->ForcedDespawn(DespawnTimer); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_RENEW_SKIRMISHER && caster->GetTypeId() == TYPEID_PLAYER + && caster->ToPlayer()->GetQuestStatus(12288) == QUEST_STATUS_INCOMPLETE) + { + caster->ToPlayer()->KilledMonsterCredit(CREDIT_NPC, 0); + DoScriptText(RAND(RANDOM_SAY_1,RANDOM_SAY_2,RANDOM_SAY_3),caster); + if(me->IsStandState()) + me->GetMotionMaster()->MovePoint(1, me->GetPositionX()+7, me->GetPositionY()+7, me->GetPositionZ()); + else + { + me->SetStandState(UNIT_STAND_STATE_STAND); + me->ForcedDespawn(DespawnTimer); + } + + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_wounded_skirmisher(Creature* pCreature) +{ + return new npc_wounded_skirmisherAI(pCreature); +} + +CreatureAI* GetAI_npc_amberpine_woodsman(Creature* pCreature) +{ + return new npc_amberpine_woodsmanAI (pCreature); +} + +void AddSC_grizzly_hills() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_orsonn_and_kodian"; + newscript->pGossipHello = &GossipHello_npc_orsonn_and_kodian; + newscript->pGossipSelect = &GossipSelect_npc_orsonn_and_kodian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_emily"; + newscript->GetAI = &GetAI_npc_emily; + newscript->pQuestAccept = &QuestAccept_npc_emily; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mrfloppy"; + newscript->GetAI = &GetAI_npc_mrfloppy; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_outhouse_bunny"; + newscript->GetAI = &GetAI_npc_outhouse_bunny; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tallhorn_stag"; + newscript->GetAI = &GetAI_npc_tallhorn_stag; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_amberpine_woodsman"; + newscript->GetAI = &GetAI_npc_amberpine_woodsman; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_wounded_skirmisher"; + newscript->GetAI = &GetAI_npc_wounded_skirmisher; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp new file mode 100644 index 00000000000..04603c68813 --- /dev/null +++ b/src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: The event with the Living Mojos is not implemented, just is done that when one of the mojos around the boss take damage will make the boss enter in combat! + */ + +#include "ScriptedPch.h" +#include "gundrak.h" + +enum Spells +{ + SPELL_EMERGE = 54850, + SPELL_MIGHTY_BLOW = 54719, + SPELL_MERGE = 54878, + SPELL_SURGE = 54801, + SPELL_FREEZE_ANIM = 16245, + SPELL_MOJO_PUDDLE = 55627, + H_SPELL_MOJO_PUDDLE = 58994, + SPELL_MOJO_WAVE = 55626, + H_SPELL_MOJO_WAVE = 58993 +}; + +struct boss_drakkari_colossusAI : public ScriptedAI +{ + boss_drakkari_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bHealth; + bool bHealth1; + + uint32 MightyBlowTimer; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, NOT_STARTED); + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->clearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); + me->SetReactState(REACT_PASSIVE); + MightyBlowTimer = 10*IN_MILISECONDS; + bHealth = false; + bHealth1 = false; + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, IN_PROGRESS); + } + + void CreatureState(Creature* pWho, bool bRestore = false) + { + if (!pWho) + return; + + if (bRestore) + { + pWho->clearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); + pWho->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pWho == me) + me->RemoveAura(SPELL_FREEZE_ANIM); + }else + { + pWho->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pWho->addUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); + if (pWho == me) + DoCast(me,SPELL_FREEZE_ANIM); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bHealth && HealthBelowPct(50) && !HealthBelowPct(5)) + { + CreatureState(me, false); + DoCast(me,SPELL_FREEZE_ANIM); + DoCast(me,SPELL_EMERGE); + bHealth = true; + } + + if (!bHealth1 && HealthBelowPct(5)) + { + DoCast(me,SPELL_EMERGE); + CreatureState(me, false); + bHealth1 = true; + me->RemoveAllAuras(); + } + + if (MightyBlowTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, true); + MightyBlowTimer = 10*IN_MILISECONDS; + } else MightyBlowTimer -= diff; + + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, DONE); + } + + void JustSummoned(Creature* pSummon) + { + if (HealthBelowPct(5)) + pSummon->DealDamage(pSummon, pSummon->GetHealth() * 0.5 , NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + pSummon->AI()->AttackStart(me->getVictim()); + } +}; + +struct boss_drakkari_elementalAI : public ScriptedAI +{ + boss_drakkari_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiSurgeTimer; + + bool bGoToColossus; + + void Reset() + { + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->CreatureState(me, true); + uiSurgeTimer = 7*IN_MILISECONDS; + bGoToColossus = false; + } + + void EnterEvadeMode() + { + me->RemoveFromWorld(); + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + { + CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->CreatureState(pColossus, true); + CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->bHealth1 = false; + } + me->RemoveFromWorld(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bGoToColossus && HealthBelowPct(50)) + { + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + { + if (!CAST_AI(boss_drakkari_colossusAI,pColossus->AI())->HealthBelowPct(6)) + { + me->InterruptNonMeleeSpells(true); + DoCast(pColossus, SPELL_MERGE); + bGoToColossus = true; + } + } + } + + if (uiSurgeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SURGE); + uiSurgeTimer = 7*IN_MILISECONDS; + } else uiSurgeTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + pColossus->Kill(pColossus); + } +}; + +struct npc_living_mojoAI : public ScriptedAI +{ + npc_living_mojoAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiMojoWaveTimer; + uint32 uiMojoPuddleTimer; + + void Reset() + { + uiMojoWaveTimer = 2*IN_MILISECONDS; + uiMojoPuddleTimer = 7*IN_MILISECONDS; + } + + void EnterCombat(Unit* /*who*/) + { + + //Check if the npc is near of Drakkari Colossus. + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + { + if (pColossus->isAlive() && me->IsInRange3d(pColossus->GetHomePosition().GetPositionX(),pColossus->GetHomePosition().GetPositionY(),pColossus->GetHomePosition().GetPositionZ(),0.0f,17.0f)) + me->SetReactState(REACT_PASSIVE); + else + me->SetReactState(REACT_AGGRESSIVE); + } + } + + void DamageTaken(Unit* pDone_by, uint32& /*uiDamage*/) + { + if (me->HasReactState(REACT_PASSIVE)) + { + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + { + if (pColossus->isAlive() && !pColossus->isInCombat()) + { + pColossus->RemoveAura(SPELL_FREEZE_ANIM); + pColossus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pColossus->SetReactState(REACT_AGGRESSIVE); + if (pDone_by && pDone_by->isAlive()) + pColossus->AI()->AttackStart(pDone_by); + EnterEvadeMode(); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiMojoWaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MOJO_WAVE); + uiMojoWaveTimer = 15*IN_MILISECONDS; + } else uiMojoWaveTimer -= diff; + + if (uiMojoPuddleTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MOJO_PUDDLE); + uiMojoPuddleTimer = 18*IN_MILISECONDS; + } else uiMojoPuddleTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_drakkari_colossus(Creature* pCreature) +{ + return new boss_drakkari_colossusAI (pCreature); +} + +CreatureAI* GetAI_boss_drakkari_elemental(Creature* pCreature) +{ + return new boss_drakkari_elementalAI (pCreature); +} + +CreatureAI* GetAI_npc_living_mojo(Creature* pCreature) +{ + return new npc_living_mojoAI (pCreature); +} + +void AddSC_boss_drakkari_colossus() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_drakkari_colossus"; + newscript->GetAI = &GetAI_boss_drakkari_colossus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_drakkari_elemental"; + newscript->GetAI = &GetAI_boss_drakkari_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_living_mojo"; + newscript->GetAI = &GetAI_npc_living_mojo; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/gundrak/boss_eck.cpp b/src/server/scripts/Northrend/gundrak/boss_eck.cpp new file mode 100644 index 00000000000..3bf1a33da5a --- /dev/null +++ b/src/server/scripts/Northrend/gundrak/boss_eck.cpp @@ -0,0 +1,168 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +enum Spells +{ + SPELL_ECK_BERSERK = 55816, //Eck goes berserk, increasing his attack speed by 150% and all damage he deals by 500%. + SPELL_ECK_BITE = 55813, //Eck bites down hard, inflicting 150% of his normal damage to an enemy. + SPELL_ECK_SPIT = 55814, //Eck spits toxic bile at enemies in a cone in front of him, inflicting 2970 Nature damage and draining 220 mana every 1 sec for 3 sec. + SPELL_ECK_SPRING_1 = 55815, //Eck leaps at a distant target. --> Drops aggro and charges a random player. Tank can simply taunt him back. + SPELL_ECK_SPRING_2 = 55837 //Eck leaps at a distant target. +}; + +static Position EckSpawnPoint = { 1643.877930, 936.278015, 107.204948, 0.668432 }; + +struct boss_eckAI : public ScriptedAI +{ + boss_eckAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBerserkTimer; + uint32 uiBiteTimer; + uint32 uiSpitTimer; + uint32 uiSpringTimer; + + bool bBerserk; + + ScriptedInstance* pInstance; + + void Reset() + { + uiBerserkTimer = urand(60*IN_MILISECONDS,90*IN_MILISECONDS); //60-90 secs according to wowwiki + uiBiteTimer = 5*IN_MILISECONDS; + uiSpitTimer = 10*IN_MILISECONDS; + uiSpringTimer = 8*IN_MILISECONDS; + + bBerserk = false; + + if (pInstance) + pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ECK_BITE); + uiBiteTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); + } else uiBiteTimer -= diff; + + if (uiSpitTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ECK_SPIT); + uiSpitTimer = urand(6*IN_MILISECONDS,14*IN_MILISECONDS); + } else uiSpitTimer -= diff; + + if (uiSpringTimer <= diff) + { + Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, RAND(SPELL_ECK_SPRING_1, SPELL_ECK_SPRING_2)); + uiSpringTimer = urand(5*IN_MILISECONDS,10*IN_MILISECONDS); + } + } else uiSpringTimer -= diff; + + //Berserk on timer or 20% of health + if (!bBerserk) + { + if (uiBerserkTimer <= diff) + { + DoCast(me, SPELL_ECK_BERSERK); + bBerserk = true; + } + else + { + uiBerserkTimer -= diff; + if (HealthBelowPct(20)) + { + DoCast(me, SPELL_ECK_BERSERK); + bBerserk = true; + } + } + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, DONE); + } +}; + +CreatureAI* GetAI_boss_eck(Creature* pCreature) +{ + return new boss_eckAI (pCreature); +} + +struct npc_ruins_dwellerAI : public ScriptedAI +{ + npc_ruins_dwellerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void JustDied(Unit * /*who*/) + { + if (pInstance) + { + pInstance->SetData64(DATA_RUIN_DWELLER_DIED,me->GetGUID()); + if (pInstance->GetData(DATA_ALIVE_RUIN_DWELLERS) == 0) + me->SummonCreature(CREATURE_ECK, EckSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300*IN_MILISECONDS); + } + } +}; + +CreatureAI* GetAI_npc_ruins_dweller(Creature* pCreature) +{ + return new npc_ruins_dwellerAI (pCreature); +} + +void AddSC_boss_eck() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_eck"; + newscript->GetAI = &GetAI_boss_eck; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ruins_dweller"; + newscript->GetAI = &GetAI_npc_ruins_dweller; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp b/src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp new file mode 100644 index 00000000000..c87a6600783 --- /dev/null +++ b/src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp @@ -0,0 +1,288 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +//Spells +enum Spells +{ + SPELL_ENRAGE = 55285, + H_SPELL_ENRAGE = 59828, + SPELL_IMPALING_CHARGE = 54956, + H_SPELL_IMPALING_CHARGE = 59827, + SPELL_STOMP = 55292, + H_SPELL_STOMP = 59829, + SPELL_PUNCTURE = 55276, + H_SPELL_PUNCTURE = 59826, + SPELL_STAMPEDE = 55218, + SPELL_WHIRLING_SLASH = 55250, + H_SPELL_WHIRLING_SLASH = 59824, + SPELL_ECK_RESIDUE = 55817 +}; + +//Yells +enum Yells +{ + SAY_AGGRO = -1604000, + SAY_SLAY_1 = -1604001, + SAY_SLAY_2 = -1604002, + SAY_SLAY_3 = -1604003, + SAY_DEATH = -1604004, + SAY_SUMMON_RHINO_1 = -1604005, + SAY_SUMMON_RHINO_2 = -1604006, + SAY_SUMMON_RHINO_3 = -1604007, + SAY_TRANSFORM_1 = -1604008, //Phase change + SAY_TRANSFORM_2 = -1604009 +}; + +enum Achievements +{ + ACHIEV_WHAT_THE_ECK = 1864, + ACHIEV_SHARE_THE_LOVE = 2152 +}; + +enum Displays +{ + DISPLAY_RHINO = 26265, + DISPLAY_TROLL = 27061 +}; + +enum CombatPhase +{ + TROLL, + RHINO +}; + +struct boss_gal_darahAI : public ScriptedAI +{ + boss_gal_darahAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiStampedeTimer; + uint32 uiWhirlingSlashTimer; + uint32 uiPunctureTimer; + uint32 uiEnrageTimer; + uint32 uiImpalingChargeTimer; + uint32 uiStompTimer; + uint32 uiTransformationTimer; + std::set lImpaledPlayers; + + CombatPhase Phase; + + uint8 uiPhaseCounter; + + bool bStartOfTransformation; + + ScriptedInstance* pInstance; + + void Reset() + { + uiStampedeTimer = 10*IN_MILISECONDS; + uiWhirlingSlashTimer = 21*IN_MILISECONDS; + uiPunctureTimer = 10*IN_MILISECONDS; + uiEnrageTimer = 15*IN_MILISECONDS; + uiImpalingChargeTimer = 21*IN_MILISECONDS; + uiStompTimer = 25*IN_MILISECONDS; + uiTransformationTimer = 9*IN_MILISECONDS; + uiPhaseCounter = 0; + + lImpaledPlayers.clear(); + + bStartOfTransformation = true; + + Phase = TROLL; + + me->SetDisplayId(DISPLAY_TROLL); + + if (pInstance) + pInstance->SetData(DATA_GAL_DARAH_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_GAL_DARAH_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + switch (Phase) + { + case TROLL: + if (uiPhaseCounter == 2) + { + if (uiTransformationTimer <= diff) + { + me->SetDisplayId(DISPLAY_RHINO); + Phase = RHINO; + uiPhaseCounter = 0; + DoScriptText(SAY_TRANSFORM_1, me); + uiTransformationTimer = 5*IN_MILISECONDS; + bStartOfTransformation = true; + me->clearUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); + me->SetReactState(REACT_AGGRESSIVE); + } + else + { + uiTransformationTimer -= diff; + + if (bStartOfTransformation) + { + bStartOfTransformation = false; + me->addUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); + me->SetReactState(REACT_PASSIVE); + } + } + } + else + { + if (uiStampedeTimer <= diff) + { + DoCast(me, SPELL_STAMPEDE); + DoScriptText(RAND(SAY_SUMMON_RHINO_1,SAY_SUMMON_RHINO_2,SAY_SUMMON_RHINO_3),me); + uiStampedeTimer = 15*IN_MILISECONDS; + } else uiStampedeTimer -= diff; + + if (uiWhirlingSlashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLING_SLASH); + uiWhirlingSlashTimer = 21*IN_MILISECONDS; + ++uiPhaseCounter; + } else uiWhirlingSlashTimer -= diff; + } + break; + case RHINO: + if (uiPhaseCounter == 2) + { + if (uiTransformationTimer <= diff) + { + me->SetDisplayId(DISPLAY_TROLL); + Phase = TROLL; + uiPhaseCounter = 0; + DoScriptText(SAY_TRANSFORM_2, me); + uiTransformationTimer = 9*IN_MILISECONDS; + bStartOfTransformation = true; + me->clearUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); + me->SetReactState(REACT_AGGRESSIVE); + } + else + { + uiTransformationTimer -= diff; + + if (bStartOfTransformation) + { + bStartOfTransformation = false; + me->addUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); + me->SetReactState(REACT_PASSIVE); + } + } + } + else + { + if (uiPunctureTimer <= diff) + { + DoCast(me->getVictim(), SPELL_PUNCTURE); + uiPunctureTimer = 8*IN_MILISECONDS; + } else uiPunctureTimer -= diff; + + if (uiEnrageTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ENRAGE); + uiEnrageTimer = 20*IN_MILISECONDS; + } else uiEnrageTimer -= diff; + + if (uiStompTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STOMP); + uiStompTimer = 20*IN_MILISECONDS; + } else uiStompTimer -= diff; + + if (uiImpalingChargeTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_IMPALING_CHARGE); + lImpaledPlayers.insert(pTarget->GetGUID()); + } + uiImpalingChargeTimer = 31*IN_MILISECONDS; + ++uiPhaseCounter; + } else uiImpalingChargeTimer -= diff; + } + break; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic()) + { + if (lImpaledPlayers.size() == 5) + pInstance->DoCompleteAchievement(ACHIEV_SHARE_THE_LOVE); + + AchievementEntry const *achievWhatTheEck = GetAchievementStore()->LookupEntry(ACHIEV_WHAT_THE_ECK); + if (achievWhatTheEck) + { + Map::PlayerList const &players = pInstance->instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (itr->getSource()->HasAura(SPELL_ECK_RESIDUE)) + itr->getSource()->CompletedAchievement(achievWhatTheEck); + } + } + + pInstance->SetData(DATA_GAL_DARAH_EVENT, DONE); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_gal_darah(Creature* pCreature) +{ + return new boss_gal_darahAI (pCreature); +} + +void AddSC_boss_gal_darah() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_gal_darah"; + newscript->GetAI = &GetAI_boss_gal_darah; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/gundrak/boss_moorabi.cpp b/src/server/scripts/Northrend/gundrak/boss_moorabi.cpp new file mode 100644 index 00000000000..84a7d8bc654 --- /dev/null +++ b/src/server/scripts/Northrend/gundrak/boss_moorabi.cpp @@ -0,0 +1,175 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +enum eSpells +{ + SPELL_DETERMINED_STAB = 55104, + SPELL_GROUND_TREMOR = 55142, + SPELL_NUMBING_SHOUT = 55106, + SPELL_DETERMINED_GORE = 55102, + H_SPELL_DETERMINED_GORE = 59444, + SPELL_QUAKE = 55101, + SPELL_NUMBING_ROAR = 55100, + SPELL_MOJO_FRENZY = 55163, + SPELL_TRANSFORMATION = 55098, //Periodic, The caster transforms into a powerful mammoth, increasing Physical damage done by 25% and granting immunity to Stun effects. +}; + +enum eArchivements +{ + ACHIEV_LESS_RABI = 2040 +}; + +enum eSays +{ + SAY_AGGRO = -1604010, + //SAY_SLAY_1 = -1604011, // not in db + SAY_SLAY_2 = -1604012, + SAY_SLAY_3 = -1604013, + SAY_DEATH = -1604014, + SAY_TRANSFORM = -1604015, + SAY_QUAKE = -1604016, + EMOTE_TRANSFORM = -1604017 +}; + +struct boss_moorabiAI : public ScriptedAI +{ + boss_moorabiAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bPhase; + + uint32 uiNumblingShoutTimer; + uint32 uiGroundTremorTimer; + uint32 uiDeterminedStabTimer; + uint32 uiTransformationTImer; + + void Reset() + { + uiGroundTremorTimer = 18*IN_MILISECONDS; + uiNumblingShoutTimer = 10*IN_MILISECONDS; + uiDeterminedStabTimer = 20*IN_MILISECONDS; + uiTransformationTImer = 12*IN_MILISECONDS; + bPhase = false; + + if (pInstance) + pInstance->SetData(DATA_MOORABI_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_MOJO_FRENZY, true); + + if (pInstance) + pInstance->SetData(DATA_MOORABI_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bPhase && me->HasAura(SPELL_TRANSFORMATION)) + { + bPhase = true; + me->RemoveAura(SPELL_MOJO_FRENZY); + } + + if (uiGroundTremorTimer <= uiDiff) + { + DoScriptText(SAY_QUAKE, me); + if (bPhase) + DoCast(me->getVictim(), SPELL_QUAKE, true); + else + DoCast(me->getVictim(), SPELL_GROUND_TREMOR, true); + uiGroundTremorTimer = 10*IN_MILISECONDS; + } else uiGroundTremorTimer -= uiDiff; + + if (uiNumblingShoutTimer <= uiDiff) + { + if (bPhase) + DoCast(me->getVictim(), SPELL_NUMBING_ROAR, true); + else + DoCast(me->getVictim(), SPELL_NUMBING_SHOUT, true); + uiNumblingShoutTimer = 10*IN_MILISECONDS; + } else uiNumblingShoutTimer -=uiDiff; + + if (uiDeterminedStabTimer <= uiDiff) + { + if (bPhase) + DoCast(me->getVictim(), SPELL_DETERMINED_GORE); + else + DoCast(me->getVictim(), SPELL_DETERMINED_STAB, true); + uiDeterminedStabTimer = 8*IN_MILISECONDS; + } else uiDeterminedStabTimer -=uiDiff; + + if (!bPhase && uiTransformationTImer <= uiDiff) + { + DoScriptText(EMOTE_TRANSFORM, me); + DoScriptText(SAY_TRANSFORM, me); + DoCast(me, SPELL_TRANSFORMATION, false); + uiTransformationTImer = 10*IN_MILISECONDS; + } else uiTransformationTImer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_MOORABI_EVENT, DONE); + + if (IsHeroic() && !bPhase) + pInstance->DoCompleteAchievement(ACHIEV_LESS_RABI); + } + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim == me) + return; + + DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_moorabi(Creature *pCreature) +{ + return new boss_moorabiAI(pCreature); +} + +void AddSC_boss_moorabi() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_moorabi"; + newscript->GetAI = &GetAI_boss_moorabi; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp b/src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp new file mode 100644 index 00000000000..1014beaeddd --- /dev/null +++ b/src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp @@ -0,0 +1,266 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +//Spells +enum Spells +{ + SPELL_POISON_NOVA = 55081, + H_SPELL_POISON_NOVA = 59842, + SPELL_POWERFULL_BITE = 48287, + H_SPELL_POWERFULL_BITE = 59840, + SPELL_VENOM_BOLT = 54970, + H_SPELL_VENOM_BOLT = 59839 +}; + +//Yell +enum Yells +{ + SAY_AGGRO = -1604017, + SAY_SLAY_1 = -1604018, + SAY_SLAY_2 = -1604019, + SAY_SLAY_3 = -1604020, + SAY_DEATH = -1604021, + SAY_SUMMON_SNAKES = -1604022, + SAY_SUMMON_CONSTRICTORS = -1604023 +}; + +//Creatures +enum Creatures +{ + CREATURE_SNAKE = 29680, + CREATURE_CONSTRICTORS = 29713 +}; + +//Creatures' spells +enum ConstrictorSpells +{ + SPELL_GRIP_OF_SLAD_RAN = 55093, + SPELL_VENOMOUS_BITE = 54987, + H_SPELL_VENOMOUS_BITE = 58996 +}; + +static Position SpawnLoc[]= +{ + {1783.81, 646.637, 133.948, 3.71755}, + {1775.03, 606.586, 134.165, 1.43117}, + {1717.39, 630.041, 129.282, 5.96903}, + {1765.66, 646.542, 134.02, 5.11381}, + {1716.76, 635.159, 129.282, 0.191986} +}; + +struct boss_slad_ranAI : public ScriptedAI +{ + boss_slad_ranAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiPoisonNovaTimer; + uint32 uiPowerfullBiteTimer; + uint32 uiVenomBoltTimer; + uint32 uiSpawnTimer; + + uint8 uiPhase; + + SummonList lSummons; + + ScriptedInstance* pInstance; + + void Reset() + { + uiPoisonNovaTimer = 10*IN_MILISECONDS; + uiPowerfullBiteTimer = 3*IN_MILISECONDS; + uiVenomBoltTimer = 15*IN_MILISECONDS; + uiSpawnTimer = 5*IN_MILISECONDS; + uiPhase = 0; + + lSummons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_SLAD_RAN_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_SLAD_RAN_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiPoisonNovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_NOVA); + uiPoisonNovaTimer = 15*IN_MILISECONDS; + } else uiPoisonNovaTimer -= diff; + + if (uiPowerfullBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POWERFULL_BITE); + uiPowerfullBiteTimer = 10*IN_MILISECONDS; + } else uiPowerfullBiteTimer -= diff; + + if (uiVenomBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_VENOM_BOLT); + uiVenomBoltTimer = 10*IN_MILISECONDS; + } else uiVenomBoltTimer -= diff; + + if (uiPhase) + { + if (uiSpawnTimer <= diff) + { + if (uiPhase == 1) + for (uint8 i = 0; i < DUNGEON_MODE(3, 5); ++i) + me->SummonCreature(CREATURE_SNAKE, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); + if (uiPhase == 2) + for (uint8 i = 0; i < DUNGEON_MODE(3, 5); ++i) + me->SummonCreature(CREATURE_CONSTRICTORS, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); + uiSpawnTimer = 5*IN_MILISECONDS; + } else uiSpawnTimer -= diff; + } + + if (uiPhase == 0 && HealthBelowPct(30)) + { + DoScriptText(SAY_SUMMON_SNAKES,me); + uiPhase = 1; + } + + if (uiPhase == 1 && HealthBelowPct(25)) + { + DoScriptText(SAY_SUMMON_CONSTRICTORS,me); + uiPhase = 2; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_SLAD_RAN_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustSummoned(Creature* summoned) + { + summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); + lSummons.Summon(summoned); + } +}; + +struct mob_slad_ran_constrictorAI : public ScriptedAI +{ + mob_slad_ran_constrictorAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiGripOfSladRanTimer; + + void Reset() + { + uiGripOfSladRanTimer = 1*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + if (uiGripOfSladRanTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GRIP_OF_SLAD_RAN); + uiGripOfSladRanTimer = 5*IN_MILISECONDS; + } else uiGripOfSladRanTimer -= diff; + } + + ScriptedInstance* pInstance; +}; + +struct mob_slad_ran_viperAI : public ScriptedAI +{ + mob_slad_ran_viperAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiVenomousBiteTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiVenomousBiteTimer = 2*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiVenomousBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_VENOMOUS_BITE); + uiVenomousBiteTimer = 10*IN_MILISECONDS; + } else uiVenomousBiteTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_slad_ran(Creature* pCreature) +{ + return new boss_slad_ranAI (pCreature); +} + +CreatureAI* GetAI_mob_slad_ran_constrictor(Creature* pCreature) +{ + return new mob_slad_ran_constrictorAI (pCreature); +} + +CreatureAI* GetAI_mob_slad_ran_viper(Creature* pCreature) +{ + return new mob_slad_ran_viperAI (pCreature); +} + +void AddSC_boss_slad_ran() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_slad_ran"; + newscript->GetAI = &GetAI_boss_slad_ran; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_slad_ran_constrictor"; + newscript->GetAI = &GetAI_mob_slad_ran_constrictor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_slad_ran_viper"; + newscript->GetAI = &GetAI_mob_slad_ran_viper; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/gundrak/gundrak.h b/src/server/scripts/Northrend/gundrak/gundrak.h new file mode 100644 index 00000000000..a443aa4e698 --- /dev/null +++ b/src/server/scripts/Northrend/gundrak/gundrak.h @@ -0,0 +1,54 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DEF_GUNDRAK_H +#define DEF_GUNDRAK_H + +enum Data +{ + DATA_SLAD_RAN_EVENT, + DATA_MOORABI_EVENT, + DATA_DRAKKARI_COLOSSUS_EVENT, + DATA_GAL_DARAH_EVENT, + DATA_ECK_THE_FEROCIOUS_EVENT, + DATA_ALIVE_RUIN_DWELLERS +}; + +enum Data64 +{ + DATA_SLAD_RAN_ALTAR, + DATA_MOORABI_ALTAR, + DATA_DRAKKARI_COLOSSUS_ALTAR, + DATA_SLAD_RAN_STATUE, + DATA_MOORABI_STATUE, + DATA_DRAKKARI_COLOSSUS_STATUE, + DATA_DRAKKARI_COLOSSUS, + DATA_RUIN_DWELLER_DIED +}; + +enum mainCreatures +{ + CREATURE_RUIN_DWELLER = 29920, + CREATURE_SLAD_RAN = 29304, + CREATURE_MOORABI = 29305, + CREATURE_GALDARAH = 29306, + CREATURE_DRAKKARICOLOSSUS = 29307, + CREATURE_ECK = 29932 +}; + +#endif diff --git a/src/server/scripts/Northrend/gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/gundrak/instance_gundrak.cpp new file mode 100644 index 00000000000..4dd896f74f2 --- /dev/null +++ b/src/server/scripts/Northrend/gundrak/instance_gundrak.cpp @@ -0,0 +1,536 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +#define MAX_ENCOUNTER 5 + +/* GunDrak encounters: +0 - Slad'Ran +1 - Moorabi +2 - Drakkari Colossus +3 - Gal'Darah +4 - Eck the Ferocious +*/ + +struct instance_gundrak : public ScriptedInstance +{ + instance_gundrak(Map* pMap) : ScriptedInstance(pMap) + { + bHeroicMode = pMap->IsHeroic(); + Initialize(); + }; + + bool bHeroicMode; + bool spawnSupport; + + uint32 timer; + uint32 phase; + uint64 toActivate; + + uint64 uiSladRan; + uint64 uiMoorabi; + uint64 uiDrakkariColossus; + uint64 uiGalDarah; + uint64 uiEckTheFerocious; + + uint64 uiSladRanAltar; + uint64 uiMoorabiAltar; + uint64 uiDrakkariColossusAltar; + uint64 uiSladRanStatue; + uint64 uiMoorabiStatue; + uint64 uiDrakkariColossusStatue; + uint64 uiGalDarahStatue; + uint64 uiEckTheFerociousDoor; + uint64 uiEckTheFerociousDoorBehind; + uint64 uiGalDarahDoor1; + uint64 uiGalDarahDoor2; + uint64 uiBridge; + uint64 uiCollision; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + GOState uiSladRanStatueState; + GOState uiMoorabiStatueState; + GOState uiDrakkariColossusStatueState; + GOState uiGalDarahStatueState; + GOState uiBridgeState; + GOState uiCollisionState; + + std::set DwellerGUIDs; + + std::string str_data; + + void Initialize() + { + spawnSupport = false; + + timer = 0; + phase = 0; + toActivate = 0; + + uiSladRan = 0; + uiMoorabi = 0; + uiDrakkariColossus = 0; + uiGalDarah = 0; + uiEckTheFerocious = 0; + + uiSladRanAltar = 0; + uiMoorabiAltar = 0; + uiDrakkariColossusAltar = 0; + + uiSladRanStatue = 0; + uiMoorabiStatue = 0; + uiDrakkariColossusStatue = 0; + uiGalDarahStatue = 0; + + uiEckTheFerociousDoor = 0; + uiEckTheFerociousDoorBehind = 0; + uiGalDarahDoor1 = 0; + uiGalDarahDoor2 = 0; + + uiBridge = 0; + uiCollision = 0; + + uiSladRanStatueState = GO_STATE_ACTIVE; + uiMoorabiStatueState = GO_STATE_ACTIVE; + uiDrakkariColossusStatueState = GO_STATE_ACTIVE; + uiGalDarahStatueState = GO_STATE_READY; + uiBridgeState = GO_STATE_ACTIVE; + uiCollisionState = GO_STATE_READY; + + DwellerGUIDs.clear(); + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case CREATURE_SLAD_RAN: uiSladRan = pCreature->GetGUID(); break; + case CREATURE_MOORABI: uiMoorabi = pCreature->GetGUID(); break; + case CREATURE_GALDARAH: uiGalDarah = pCreature->GetGUID(); break; + case CREATURE_DRAKKARICOLOSSUS: uiDrakkariColossus = pCreature->GetGUID(); break; + case CREATURE_ECK: uiEckTheFerocious = pCreature->GetGUID(); break; + case CREATURE_RUIN_DWELLER: + if (pCreature->isAlive()) + DwellerGUIDs.insert(pCreature->GetGUID()); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 192518: + uiSladRanAltar = pGo->GetGUID(); + // Make sure that they start out as unusuable + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + if (m_auiEncounter[0] == DONE) + { + if (uiSladRanStatueState == GO_STATE_ACTIVE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + else + { + ++phase; + pGo->SetGoState(GO_STATE_ACTIVE); + } + } + break; + case 192519: + uiMoorabiAltar = pGo->GetGUID(); + // Make sure that they start out as unusuable + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + if (m_auiEncounter[0] == DONE) + { + if (uiMoorabiStatueState == GO_STATE_ACTIVE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + else + { + ++phase; + pGo->SetGoState(GO_STATE_ACTIVE); + } + } + break; + case 192520: + uiDrakkariColossusAltar = pGo->GetGUID(); + // Make sure that they start out as unusuable + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + if (m_auiEncounter[0] == DONE) + { + if (uiDrakkariColossusStatueState == GO_STATE_ACTIVE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + else + { + ++phase; + pGo->SetGoState(GO_STATE_ACTIVE); + } + } + break; + case 192564: + uiSladRanStatue = pGo->GetGUID(); + pGo->SetGoState(uiSladRanStatueState); + break; + case 192565: + uiMoorabiStatue = pGo->GetGUID(); + pGo->SetGoState(uiMoorabiStatueState); + break; + case 192566: + uiGalDarahStatue = pGo->GetGUID(); + pGo->SetGoState(uiGalDarahStatueState); + break; + case 192567: + uiDrakkariColossusStatue = pGo->GetGUID(); + pGo->SetGoState(uiDrakkariColossusStatueState); + break; + case 192632: + uiEckTheFerociousDoor = pGo->GetGUID(); + if (bHeroicMode && m_auiEncounter[1] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 192569: + uiEckTheFerociousDoorBehind = pGo->GetGUID(); + if (bHeroicMode && m_auiEncounter[4] == DONE) + HandleGameObject(NULL,true,pGo); + case 193208: + uiGalDarahDoor1 = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 193209: + uiGalDarahDoor2 = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 193188: + uiBridge = pGo->GetGUID(); + pGo->SetGoState(uiBridgeState); + break; + case 192633: + uiCollision = pGo->GetGUID(); + pGo->SetGoState(uiCollisionState); + + // Can't spawn here with SpawnGameObject because pGo isn't added to world yet... + if (uiCollisionState == GO_STATE_ACTIVE_ALTERNATIVE) + spawnSupport = true; + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_SLAD_RAN_EVENT: + m_auiEncounter[0] = data; + if (data == DONE) + { + GameObject* pGo = instance->GetGameObject(uiSladRanAltar); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + } + break; + case DATA_MOORABI_EVENT: + m_auiEncounter[1] = data; + if (data == DONE) + { + GameObject* pGo = instance->GetGameObject(uiMoorabiAltar); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + if (bHeroicMode) + HandleGameObject(uiEckTheFerociousDoor,true); + } + break; + case DATA_DRAKKARI_COLOSSUS_EVENT: + m_auiEncounter[2] = data; + if (data == DONE) + { + GameObject* pGo = instance->GetGameObject(uiDrakkariColossusAltar); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + } + break; + case DATA_GAL_DARAH_EVENT: + m_auiEncounter[3] = data; + if (data == DONE) + { + HandleGameObject(uiGalDarahDoor1,true); + HandleGameObject(uiGalDarahDoor2,true); + } + break; + case DATA_ECK_THE_FEROCIOUS_EVENT: + m_auiEncounter[4] = data; + if (bHeroicMode && data == DONE) + HandleGameObject(uiEckTheFerociousDoorBehind,true); + break; + } + + if (data == DONE) + SaveToDB(); + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_RUIN_DWELLER_DIED) + DwellerGUIDs.erase(data); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_SLAD_RAN_EVENT: return m_auiEncounter[0]; + case DATA_MOORABI_EVENT: return m_auiEncounter[1]; + case DATA_GAL_DARAH_EVENT: return m_auiEncounter[2]; + case DATA_DRAKKARI_COLOSSUS_EVENT: return m_auiEncounter[3]; + case DATA_ECK_THE_FEROCIOUS_EVENT: return m_auiEncounter[4]; + case DATA_ALIVE_RUIN_DWELLERS: return DwellerGUIDs.size(); + } + + return 0; + } + + uint64 GetData64(uint32 type) + { + switch(type) + { + case DATA_SLAD_RAN_ALTAR: return uiSladRanAltar; + case DATA_MOORABI_ALTAR: return uiMoorabiAltar; + case DATA_DRAKKARI_COLOSSUS_ALTAR: return uiDrakkariColossusAltar; + case DATA_SLAD_RAN_STATUE: return uiSladRanStatue; + case DATA_MOORABI_STATUE: return uiMoorabiStatue; + case DATA_DRAKKARI_COLOSSUS_STATUE: return uiDrakkariColossusStatue; + case DATA_DRAKKARI_COLOSSUS: return uiDrakkariColossus; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "G D " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " + << (uiSladRanStatue ? GetObjState(uiSladRanStatue) : GO_STATE_ACTIVE) << " " << (uiMoorabiStatue ? GetObjState(uiMoorabiStatue) : GO_STATE_ACTIVE) << " " + << (uiDrakkariColossusStatue ? GetObjState(uiDrakkariColossusStatue) : GO_STATE_ACTIVE) << " " << (uiGalDarahStatue ? GetObjState(uiGalDarahStatue) : GO_STATE_READY) << " " + << (uiBridge ? GetObjState(uiBridge) : GO_STATE_ACTIVE) << " " << (uiCollision ? GetObjState(uiCollision) : GO_STATE_READY); + + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 + >> data4 >> data5 >> data6 >> data7 >> data8 >> data9 >> data10; + + if (dataHead1 == 'G' && dataHead2 == 'D') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + uiSladRanStatueState = GOState(data5); + uiMoorabiStatueState = GOState(data6); + uiDrakkariColossusStatueState = GOState(data7); + uiGalDarahStatueState = GOState(data8); + uiBridgeState = GOState(data9); + uiCollisionState = GOState(data10); + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + bool QueueActivation(uint64 guid, uint32 time) + { + if (timer) + return false; + + toActivate = guid; + timer = time; + phase++; + return true; + } + + void Update(uint32 diff) + { + // Spawn the support for the bridge if necessary + if (spawnSupport) + { + if (GameObject* pCollision = instance->GetGameObject(uiCollision)) + pCollision->SummonGameObject(192743, pCollision->GetPositionX(), pCollision->GetPositionY(), pCollision->GetPositionZ(), pCollision->GetOrientation(), 0, 0, 0, 0, 0); + spawnSupport = false; + } + + // If there is nothing to activate, then return + if (!toActivate) + return; + + if (timer < diff) + { + timer = 0; + if (toActivate == uiBridge) + { + toActivate = 0; + GameObject* pBridge = instance->GetGameObject(uiBridge); + GameObject* pCollision = instance->GetGameObject(uiCollision); + GameObject* pSladRanStatue = instance->GetGameObject(uiSladRanStatue); + GameObject* pMoorabiStatue = instance->GetGameObject(uiMoorabiStatue); + GameObject* pDrakkariColossusStatue = instance->GetGameObject(uiDrakkariColossusStatue); + GameObject* pGalDarahStatue = instance->GetGameObject(uiGalDarahStatue); + + if (pBridge && pCollision && pSladRanStatue && pMoorabiStatue && pDrakkariColossusStatue && pGalDarahStatue) + { + pBridge->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pCollision->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pSladRanStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pMoorabiStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pDrakkariColossusStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pGalDarahStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + + // Add the GO that solidifies the bridge so you can walk on it + spawnSupport = true; + SaveToDB(); + } + } + else + { + uint32 spell = 0; + GameObject* pAltar = NULL; + if (toActivate == uiSladRanStatue) + { + spell = 57071; + pAltar = instance->GetGameObject(uiSladRanAltar); + } else if (toActivate == uiMoorabiStatue) + { + spell = 57068; + pAltar = instance->GetGameObject(uiMoorabiAltar); + } else if (toActivate == uiDrakkariColossusStatue) + { + spell = 57072; + pAltar = instance->GetGameObject(uiDrakkariColossusAltar); + } + + // This is a workaround to make the beam cast properly. The caster should be ID 30298 but since the spells + // all are with scripted target for that same ID, it will hit itself. + if (pAltar) + if (Creature* trigger = pAltar->SummonCreature(18721, pAltar->GetPositionX(), pAltar->GetPositionY(), pAltar->GetPositionZ() + 3, pAltar->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 5000)) + { + // Set the trigger model to invisible + trigger->SetDisplayId(11686); + trigger->CastSpell(trigger, spell, false); + } + + if (GameObject* statueGO = instance->GetGameObject(toActivate)) + statueGO->SetGoState(GO_STATE_READY); + + toActivate = 0; + + if (phase == 3) + QueueActivation(uiBridge, 3000); + else + SaveToDB(); // Don't save in between last statue and bridge turning in case of crash leading to stuck instance + } + } else timer -= diff; + } + + GOState GetObjState(uint64 guid) + { + if (GameObject* go = instance->GetGameObject(guid)) + return go->GetGoState(); + return GO_STATE_ACTIVE; + } +}; + +bool GOHello_altar(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + uint64 uiStatue = 0; + + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + if (pInstance) + { + switch(pGO->GetEntry()) + { + case 192518: uiStatue = pInstance->GetData64(DATA_SLAD_RAN_STATUE); break; + case 192519: uiStatue = pInstance->GetData64(DATA_MOORABI_STATUE); break; + case 192520: uiStatue = pInstance->GetData64(DATA_DRAKKARI_COLOSSUS_STATUE); break; + } + if (((instance_gundrak*)pInstance)->QueueActivation(uiStatue, 3500)) + { + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + } + return true; + } + return false; +} + +InstanceData* GetInstanceData_instance_gundrak(Map* pMap) +{ + return new instance_gundrak(pMap); +} + +void AddSC_instance_gundrak() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_gundrak"; + newscript->GetInstanceData = &GetInstanceData_instance_gundrak; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_gundrak_altar"; + newscript->pGOHello = &GOHello_altar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/howling_fjord.cpp b/src/server/scripts/Northrend/howling_fjord.cpp new file mode 100644 index 00000000000..172501e2faa --- /dev/null +++ b/src/server/scripts/Northrend/howling_fjord.cpp @@ -0,0 +1,338 @@ +/* Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Sholazar_Basin +SD%Complete: 100 +SDComment: Quest support: 11253, 11241. +SDCategory: howling_fjord +EndScriptData */ + +/* ContentData +npc_plaguehound_tracker +npc_apothecary_hanes +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_apothecary_hanes +######*/ +enum Entries +{ + NPC_APOTHECARY_HANES = 23784, + FACTION_ESCORTEE_A = 774, + FACTION_ESCORTEE_H = 775, + NPC_HANES_FIRE_TRIGGER = 23968, + QUEST_TRAIL_OF_FIRE = 11241, + SPELL_COSMETIC_LOW_POLY_FIRE = 56274 +}; + +bool QuestAccept_npc_apothecary_hanes(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_TRAIL_OF_FIRE) + { + switch (pPlayer->GetTeam()) + { + case ALLIANCE: + pCreature->setFaction(FACTION_ESCORTEE_A); + break; + case HORDE: + pCreature->setFaction(FACTION_ESCORTEE_H); + break; + } + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + } + return true; +} + +struct npc_Apothecary_HanesAI : public npc_escortAI +{ + npc_Apothecary_HanesAI(Creature* pCreature) : npc_escortAI(pCreature){} + uint32 PotTimer; + + void Reset () + { + SetDespawnAtFar(false); + PotTimer = 10000; //10 sec cooldown on potion + } + + void JustDied(Unit* /*killer*/) + { + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->FailQuest(QUEST_TRAIL_OF_FIRE); + } + + void UpdateEscortAI(const uint32 diff) + { + if (HealthBelowPct(75)) + { + if (PotTimer <= diff) + { + DoCast(me, 17534, true); + PotTimer = 10000; + } else PotTimer -= diff; + } + if (GetAttack() && UpdateVictim()) + DoMeleeAttackIfReady(); + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + if (!pPlayer) + return; + switch(i) + { + case 1: + me->SetReactState(REACT_AGGRESSIVE); + SetRun(true); + break; + case 23: + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_TRAIL_OF_FIRE, me); + me->ForcedDespawn(); + break; + case 5: + if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) + Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); + SetRun(false); + break; + case 6: + if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) + Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); + SetRun(true); + break; + case 8: + if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) + Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); + SetRun(false); + break; + case 9: + if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) + Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); + break; + case 10: + SetRun(true); + break; + case 13: + SetRun(false); + break; + case 14: + if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) + Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); + SetRun(true); + break; + } + } +}; +CreatureAI* GetAI_npc_apothecary_hanes(Creature* pCreature) +{ + return new npc_Apothecary_HanesAI(pCreature); +} +/*###### +## npc_plaguehound_tracker +######*/ + +enum ePlaguehound +{ + QUEST_SNIFF_OUT_ENEMY = 11253 +}; + +struct npc_plaguehound_trackerAI : public npc_escortAI +{ + npc_plaguehound_trackerAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void Reset() + { + InitScriptData(); + } + + void InitScriptData() + { + Player* pPlayer = NULL; + if (me->isSummon()) + if (Unit* summoner = CAST_SUM(me)->GetSummoner()) + if (summoner->GetTypeId() == TYPEID_PLAYER) + pPlayer = CAST_PLR(summoner); + + if (!pPlayer) + return; + + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + Start(false, false, pPlayer->GetGUID()); + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = NULL; + if (me->isSummon()) + if (Unit* summoner = CAST_SUM(me)->GetSummoner()) + if (summoner->GetTypeId() == TYPEID_PLAYER) + pPlayer = CAST_PLR(summoner); + + if (!pPlayer) + return; + + switch(i) + { + case 26: + me->ForcedDespawn(); + break; + } + } +}; + +CreatureAI* GetAI_npc_plaguehound_tracker(Creature* pCreature) +{ + return new npc_plaguehound_trackerAI(pCreature); +} + +/*###### +## npc_razael_and_lyana +######*/ + +#define GOSSIP_RAZAEL_REPORT "High Executor Anselm wants a report on the situation." +#define GOSSIP_LYANA_REPORT "High Executor Anselm requests your report." + +enum eRazael +{ + QUEST_REPORTS_FROM_THE_FIELD = 11221, + NPC_RAZAEL = 23998, + NPC_LYANA = 23778, + GOSSIP_TEXTID_RAZAEL1 = 11562, + GOSSIP_TEXTID_RAZAEL2 = 11564, + GOSSIP_TEXTID_LYANA1 = 11586, + GOSSIP_TEXTID_LYANA2 = 11588 +}; + +bool GossipHello_npc_razael_and_lyana(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_REPORTS_FROM_THE_FIELD) == QUEST_STATUS_INCOMPLETE) + switch (pCreature->GetEntry()) + { + case NPC_RAZAEL: + if (!pPlayer->GetReqKillOrCastCurrentCount(QUEST_REPORTS_FROM_THE_FIELD, NPC_RAZAEL)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_RAZAEL_REPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RAZAEL1, pCreature->GetGUID()); + return true; + } + break; + case NPC_LYANA: + if (!pPlayer->GetReqKillOrCastCurrentCount(QUEST_REPORTS_FROM_THE_FIELD, NPC_LYANA)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LYANA_REPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LYANA1, pCreature->GetGUID()); + return true; + } + break; + } + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_razael_and_lyana(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RAZAEL2, pCreature->GetGUID()); + pPlayer->TalkedToCreature(NPC_RAZAEL, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LYANA2, pCreature->GetGUID()); + pPlayer->TalkedToCreature(NPC_LYANA, pCreature->GetGUID()); + break; + } + return true; +} + +/*###### +## npc_mcgoyver +######*/ + +#define GOSSIP_ITEM_MG_I "Walt sent me to pick up some dark iron ingots." +#define GOSSIP_ITEM_MG_II "Yarp." + +enum eMcGoyver +{ + QUEST_WE_CAN_REBUILD_IT = 11483, + + SPELL_CREATURE_DARK_IRON_INGOTS = 44512, + SPELL_TAXI_EXPLORERS_LEAGUE = 44280, + + GOSSIP_TEXTID_MCGOYVER = 12193 +}; + +bool GossipHello_npc_mcgoyver(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_WE_CAN_REBUILD_IT) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MG_I, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_mcgoyver(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MG_II, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_MCGOYVER, pCreature->GetGUID()); + pPlayer->CastSpell(pPlayer, SPELL_CREATURE_DARK_IRON_INGOTS, true); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CastSpell(pPlayer, SPELL_TAXI_EXPLORERS_LEAGUE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +void AddSC_howling_fjord() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_apothecary_hanes"; + newscript->GetAI = &GetAI_npc_apothecary_hanes; + newscript->pQuestAccept = &QuestAccept_npc_apothecary_hanes; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_plaguehound_tracker"; + newscript->GetAI = &GetAI_npc_plaguehound_tracker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_razael_and_lyana"; + newscript->pGossipHello = &GossipHello_npc_razael_and_lyana; + newscript->pGossipSelect = &GossipSelect_npc_razael_and_lyana; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mcgoyver"; + newscript->pGossipHello = &GossipHello_npc_mcgoyver; + newscript->pGossipSelect = &GossipSelect_npc_mcgoyver; + newscript->RegisterSelf(); + } diff --git a/src/server/scripts/Northrend/icecrown.cpp b/src/server/scripts/Northrend/icecrown.cpp new file mode 100644 index 00000000000..76608bdb73d --- /dev/null +++ b/src/server/scripts/Northrend/icecrown.cpp @@ -0,0 +1,422 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Icecrown +SD%Complete: 100 +SDComment: Quest support: 12807 +SDCategory: Icecrown +EndScriptData */ + +/* ContentData +npc_arete +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_arete +######*/ + +#define GOSSIP_ARETE_ITEM1 "Lord-Commander, I would hear your tale." +#define GOSSIP_ARETE_ITEM2 "" +#define GOSSIP_ARETE_ITEM3 "I thought that they now called themselves the Scarlet Onslaught?" +#define GOSSIP_ARETE_ITEM4 "Where did the grand admiral go?" +#define GOSSIP_ARETE_ITEM5 "That's fine. When do I start?" +#define GOSSIP_ARETE_ITEM6 "Let's finish this!" +#define GOSSIP_ARETE_ITEM7 "That's quite a tale, Lord-Commander." + +enum eArete +{ + GOSSIP_TEXTID_ARETE1 = 13525, + GOSSIP_TEXTID_ARETE2 = 13526, + GOSSIP_TEXTID_ARETE3 = 13527, + GOSSIP_TEXTID_ARETE4 = 13528, + GOSSIP_TEXTID_ARETE5 = 13529, + GOSSIP_TEXTID_ARETE6 = 13530, + GOSSIP_TEXTID_ARETE7 = 13531, + + QUEST_THE_STORY_THUS_FAR = 12807 +}; + +bool GossipHello_npc_arete(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_THE_STORY_THUS_FAR) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE1, pCreature->GetGUID()); + return true; + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_arete(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE2, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE3, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE4, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE5, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE6, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE7, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(QUEST_THE_STORY_THUS_FAR); + break; + } + + return true; +} + +/*###### +## npc_dame_evniki_kapsalis +######*/ + +enum eDameEnvikiKapsalis +{ + TITLE_CRUSADER = 123 +}; + +bool GossipHello_npc_dame_evniki_kapsalis(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->HasTitle(TITLE_CRUSADER)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_dame_evniki_kapsalis(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + return true; +} + +/*###### +## npc_squire_david +######*/ + +enum eSquireDavid +{ + QUEST_THE_ASPIRANT_S_CHALLENGE_H = 13680, + QUEST_THE_ASPIRANT_S_CHALLENGE_A = 13679, + + NPC_ARGENT_VALIANT = 33448, + + GOSSIP_TEXTID_SQUIRE = 14407 +}; + +#define GOSSIP_SQUIRE_ITEM_1 "I am ready to fight!" +#define GOSSIP_SQUIRE_ITEM_2 "How do the Argent Crusader raiders fight?" + +bool GossipHello_npc_squire_david(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_H) == QUEST_STATUS_INCOMPLETE || + pPlayer->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_A) == QUEST_STATUS_INCOMPLETE)//We need more info about it. + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + } + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SQUIRE, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_squire_david(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->SummonCreature(NPC_ARGENT_VALIANT,8575.451,952.472,547.554,0.38); + } + //else + //pPlayer->SEND_GOSSIP_MENU(???, pCreature->GetGUID()); Missing text + return true; +} + +/*###### +## npc_argent_valiant +######*/ + +enum eArgentValiant +{ + SPELL_CHARGE = 63010, + SPELL_SHIELD_BREAKER = 65147, + + NPC_ARGENT_VALIANT_CREDIT = 24108 +}; + +struct npc_argent_valiantAI : public ScriptedAI +{ + npc_argent_valiantAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pCreature->GetMotionMaster()->MovePoint(0,8599.258,963.951,547.553); + pCreature->setFaction(35); //wrong faction in db? + } + + uint32 uiChargeTimer; + uint32 uiShieldBreakerTimer; + + void Reset() + { + uiChargeTimer = 7000; + uiShieldBreakerTimer = 10000; + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + me->setFaction(14); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage > me->GetHealth() && pDoneBy->GetTypeId() == TYPEID_PLAYER) + { + uiDamage = 0; + CAST_PLR(pDoneBy)->KilledMonsterCredit(NPC_ARGENT_VALIANT_CREDIT,0); + me->setFaction(35); + me->ForcedDespawn(5000); + me->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + EnterEvadeMode(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiChargeTimer <= uiDiff) + { + DoCastVictim(SPELL_CHARGE); + uiChargeTimer = 7000; + } else uiChargeTimer -= uiDiff; + + if (uiShieldBreakerTimer <= uiDiff) + { + DoCastVictim(SPELL_SHIELD_BREAKER); + uiShieldBreakerTimer = 10000; + } else uiShieldBreakerTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_argent_valiant(Creature* pCreature) +{ + return new npc_argent_valiantAI (pCreature); +} + +/*###### +## npc_argent_tournament_post +######*/ + +enum eArgentTournamentPost +{ + SPELL_ROPE_BEAM = 63413, + NPC_GORMOK_THE_IMPALER = 35469, + NPC_ICEHOWL = 35470 +}; + +struct npc_argent_tournament_postAI : public ScriptedAI +{ + npc_argent_tournament_postAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + if (Creature* pTarget = me->FindNearestCreature(NPC_GORMOK_THE_IMPALER, 6.0f)) + DoCast(pTarget, SPELL_ROPE_BEAM); + + if (Creature* pTarget2 = me->FindNearestCreature(NPC_ICEHOWL, 6.0f)) + DoCast(pTarget2, SPELL_ROPE_BEAM); + + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_npc_argent_tournament_post(Creature* pCreature) +{ + return new npc_argent_tournament_postAI (pCreature); +} + +/*###### +## npc_alorah_and_grimmin +######*/ + +enum ealorah_and_grimmin +{ + SPELL_CHAIN = 68341, + NPC_FJOLA_LIGHTBANE = 36065, + NPC_EYDIS_DARKBANE = 36066, + NPC_PRIESTESS_ALORAH = 36101, + NPC_PRIEST_GRIMMIN = 36102 +}; + +struct npc_alorah_and_grimminAI : public ScriptedAI +{ + npc_alorah_and_grimminAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + bool uiCast; + + void Reset() + { + uiCast = false; + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (uiCast) + return; + uiCast = true; + Creature* pTarget = NULL; + + switch(me->GetEntry()) + { + case NPC_PRIESTESS_ALORAH: + pTarget = me->FindNearestCreature(NPC_EYDIS_DARKBANE, 10.0f); + break; + case NPC_PRIEST_GRIMMIN: + pTarget = me->FindNearestCreature(NPC_FJOLA_LIGHTBANE, 10.0f); + break; + } + if (pTarget) + DoCast(pTarget, SPELL_CHAIN); + + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_npc_alorah_and_grimmin(Creature* pCreature) +{ + return new npc_alorah_and_grimminAI (pCreature); +} + +/*###### +## npc_guardian_pavilion +######*/ + +enum eGuardianPavilion +{ + SPELL_TRESPASSER_H = 63987, + AREA_SUNREAVER_PAVILION = 4676, + + AREA_SILVER_COVENANT_PAVILION = 4677, + SPELL_TRESPASSER_A = 63986, +}; + +struct npc_guardian_pavilionAI : public Scripted_NoMovementAI +{ + npc_guardian_pavilionAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) {} + + void MoveInLineOfSight(Unit* pWho) + { + if (me->GetAreaId() != AREA_SUNREAVER_PAVILION && me->GetAreaId() != AREA_SILVER_COVENANT_PAVILION) + return; + + if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER || !me->IsHostileTo(pWho) || !me->isInBackInMap(pWho, 5.0f)) + return; + + if (pWho->HasAura(SPELL_TRESPASSER_H) || pWho->HasAura(SPELL_TRESPASSER_A)) + return; + + if (pWho->ToPlayer()->GetTeamId() == TEAM_ALLIANCE) + pWho->CastSpell(pWho, SPELL_TRESPASSER_H, true); + else + pWho->CastSpell(pWho, SPELL_TRESPASSER_A, true); + + } +}; + +CreatureAI* GetAI_npc_guardian_pavilion(Creature* pCreature) +{ + return new npc_guardian_pavilionAI (pCreature); +} + +void AddSC_icecrown() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_arete"; + newscript->pGossipHello = &GossipHello_npc_arete; + newscript->pGossipSelect = &GossipSelect_npc_arete; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dame_evniki_kapsalis"; + newscript->pGossipHello = &GossipHello_npc_dame_evniki_kapsalis; + newscript->pGossipSelect = &GossipSelect_npc_dame_evniki_kapsalis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_squire_david"; + newscript->pGossipHello = &GossipHello_npc_squire_david; + newscript->pGossipSelect = &GossipSelect_npc_squire_david; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_argent_valiant"; + newscript->GetAI = &GetAI_npc_argent_valiant; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_argent_tournament_post"; + newscript->GetAI = &GetAI_npc_argent_tournament_post; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_alorah_and_grimmin"; + newscript->GetAI = &GetAI_npc_alorah_and_grimmin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_guardian_pavilion"; + newscript->GetAI = &GetAI_npc_guardian_pavilion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp new file mode 100644 index 00000000000..896eb068eb6 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp @@ -0,0 +1,185 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SAY_GREET RAND(-1533000,-1533004,-1533005,-1533006,-1533007) +#define SAY_AGGRO RAND(-1533001,-1533002,-1533003) +#define SAY_SLAY -1533008 + +#define MOB_CRYPT_GUARD 16573 + +const Position GuardSummonPos = {3333.72, -3476.30, 287.1, 6.2801}; + +enum Events +{ + EVENT_NONE, + EVENT_IMPALE, + EVENT_LOCUST, + EVENT_SPAWN_GUARDIAN_NORMAL, + EVENT_BERSERK, +}; + +enum Spells +{ + SPELL_IMPALE_10 = 28783, + SPELL_IMPALE_25 = 56090, + SPELL_LOCUST_SWARM_10 = 28785, + SPELL_LOCUST_SWARM_25 = 54021, + SPELL_SUMMON_CORPSE_SCARABS_PLR = 29105, // This spawns 5 corpse scarabs on top of player + SPELL_SUMMON_CORPSE_SCARABS_MOB = 28864, // This spawns 10 corpse scarabs on top of dead guards + SPELL_BERSERK = 27680, +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 9891, +}; + +struct boss_anubrekhanAI : public BossAI +{ + boss_anubrekhanAI(Creature *c) : BossAI(c, BOSS_ANUBREKHAN) {} + + bool hasTaunted; + + void Reset() + { + _Reset(); + + hasTaunted = false; + + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + { + Position pos; + + // respawn guard using home position, + // otherwise, after a wipe, they respawn where boss was at wipe moment. + pos = me->GetHomePosition(); + pos.m_positionY -= 10.0f; + me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); + + pos = me->GetHomePosition(); + pos.m_positionY += 10.0f; + me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); + } + } + + void KilledUnit(Unit* victim) + { + //Force the player to spawn corpse scarabs via spell, TODO: Check percent chance for scarabs, 20% at the moment + if (!(rand()%5)) + if (victim->GetTypeId() == TYPEID_PLAYER) + victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, NULL, NULL, me->GetGUID()); + + DoScriptText(SAY_SLAY, me); + } + + void JustDied(Unit *) + { + _JustDied(); + + // start achievement timer (kill Maexna within 20 min) + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO, me); + events.ScheduleEvent(EVENT_IMPALE, 10000 + rand()%10000); + events.ScheduleEvent(EVENT_LOCUST, 90000); + events.ScheduleEvent(EVENT_BERSERK, 600000); + + if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000,20000)); + } + + void MoveInLineOfSight(Unit *who) + { + if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(SAY_GREET, me); + hasTaunted = true; + } + ScriptedAI::MoveInLineOfSight(who); + } + + void SummonedCreatureDespawn(Creature *summon) + { + BossAI::SummonedCreatureDespawn(summon); + + // check if it is an actual killed guard + if (!me->isAlive() || summon->isAlive() || summon->GetEntry() != MOB_CRYPT_GUARD) + return; + + summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, NULL, NULL, me->GetGUID()); + } + + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || !CheckInRoom()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_IMPALE: + //Cast Impale on a random target + //Do NOT cast it when we are afflicted by locust swarm + if (!me->HasAura(RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25))) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_IMPALE_10,SPELL_IMPALE_25)); + events.ScheduleEvent(EVENT_IMPALE, urand(10000,20000)); + break; + case EVENT_LOCUST: + // TODO : Add Text + DoCast(me, RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25)); + DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); + events.ScheduleEvent(EVENT_LOCUST, 90000); + break; + case EVENT_SPAWN_GUARDIAN_NORMAL: + // TODO : Add Text + DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); + break; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK, true); + events.ScheduleEvent(EVENT_BERSERK, 600000); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_anubrekhan(Creature* pCreature) +{ + return new boss_anubrekhanAI (pCreature); +} + +void AddSC_boss_anubrekhan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_anubrekhan"; + newscript->GetAI = &GetAI_boss_anubrekhan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp new file mode 100644 index 00000000000..aa5a940eb8f --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Yells +{ + SAY_GREET = -1533009, + SAY_AGGRO_1 = -1533010, + SAY_AGGRO_2 = -1533011, + SAY_AGGRO_3 = -1533012, + SAY_AGGRO_4 = -1533013, + SAY_SLAY_1 = -1533014, + SAY_SLAY_2 = -1533015, + SAY_DEATH = -1533016 +}; +//#define SOUND_RANDOM_AGGRO 8955 //soundId containing the 4 aggro sounds, we not using this + +enum Spells +{ + SPELL_POISON_BOLT_VOLLEY = 28796, + H_SPELL_POISON_BOLT_VOLLEY = 54098, + SPELL_RAIN_OF_FIRE = 28794, + H_SPELL_RAIN_OF_FIRE = 54099, + SPELL_FRENZY = 28798, + H_SPELL_FRENZY = 54100, + SPELL_WIDOWS_EMBRACE = 28732, + H_SPELL_WIDOWS_EMBRACE = 54097 +}; + +enum Events +{ + EVENT_NONE, + EVENT_POISON, + EVENT_FIRE, + EVENT_FRENZY +}; + +enum Achievements +{ + ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10 = 1997, + ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25 = 2140 +}; + +struct boss_faerlinaAI : public BossAI +{ + boss_faerlinaAI(Creature *c) : BossAI(c, BOSS_FAERLINA), greet(false) {} + + bool greet; + bool doDelayFrenzy; + bool bAchievement; + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4), me); + events.ScheduleEvent(EVENT_POISON, urand(10000,15000)); + events.ScheduleEvent(EVENT_FIRE, urand(6000,18000)); + events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000)); + } + + void Reset() + { + doDelayFrenzy = false; + bAchievement = true; + _Reset(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!greet && who->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(SAY_GREET, me); + greet = true; + } + BossAI::MoveInLineOfSight(who); + } + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%3)) + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + + if (instance && bAchievement) + instance->DoCompleteAchievement(RAID_MODE(ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10,ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25)); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (doDelayFrenzy && !me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE, H_SPELL_WIDOWS_EMBRACE))) + { + doDelayFrenzy = false; + DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY), true); + } + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_POISON: + if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE))) + DoCastAOE(RAID_MODE(SPELL_POISON_BOLT_VOLLEY,H_SPELL_POISON_BOLT_VOLLEY)); + events.ScheduleEvent(EVENT_POISON, urand(8000,15000)); + break; + case EVENT_FIRE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_RAIN_OF_FIRE, H_SPELL_RAIN_OF_FIRE)); + events.ScheduleEvent(EVENT_FIRE, urand(6000,18000)); + break; + case EVENT_FRENZY: + // TODO : Add Text + if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE))) + DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY)); + else + doDelayFrenzy = true; + + events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000)); + break; + } + } + + DoMeleeAttackIfReady(); + } + + void SpellHit(Unit* caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_WIDOWS_EMBRACE || spell->Id == H_SPELL_WIDOWS_EMBRACE) + { + // TODO : Add Text + bAchievement = false; + doDelayFrenzy = true; + me->Kill(caster); + } + } +}; + +CreatureAI* GetAI_boss_faerlina(Creature* pCreature) +{ + return new boss_faerlinaAI (pCreature); +} + +struct mob_faerlina_addAI : public ScriptedAI +{ + mob_faerlina_addAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) { + me->ApplySpellImmune(0, IMMUNITY_MECHANIC, SPELL_EFFECT_BIND, true); + me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true); + } + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance && getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + { + if (Creature *pFaerlina = pInstance->instance->GetCreature(pInstance->GetData64(DATA_FAERLINA))) + DoCast(pFaerlina, SPELL_WIDOWS_EMBRACE); + } + } +}; + +CreatureAI* GetAI_mob_faerlina_add(Creature* pCreature) +{ + return new mob_faerlina_addAI (pCreature); +} + +void AddSC_boss_faerlina() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_faerlina"; + newscript->GetAI = &GetAI_boss_faerlina; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_faerlina_add"; + newscript->GetAI = &GetAI_mob_faerlina_add; + newscript->RegisterSelf(); +} + + diff --git a/src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp new file mode 100644 index 00000000000..f04b39040db --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp @@ -0,0 +1,397 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Horsemen +{ + HORSEMEN_THANE, + HORSEMEN_LADY, + HORSEMEN_BARON, + HORSEMEN_SIR, +}; + +enum Events +{ + EVENT_NONE, + EVENT_MARK, + EVENT_CAST, + EVENT_BERSERK, +}; + +const Position WaypointPositions[12] = +{ + // Thane waypoints + {2542.3, -2984.1, 241.49, 5.362}, + {2547.6, -2999.4, 241.34, 5.049}, + {2542.9, -3015.0, 241.35, 4.654}, + // Lady waypoints + {2498.3, -2961.8, 241.28, 3.267}, + {2487.7, -2959.2, 241.28, 2.890}, + {2469.4, -2947.6, 241.28, 2.576}, + // Baron waypoints + {2553.8, -2968.4, 241.33, 5.757}, + {2564.3, -2972.5, 241.33, 5.890}, + {2583.9, -2971.67, 241.35, 0.008}, + // Sir waypoints + {2534.5, -2921.7, 241.53, 1.363}, + {2523.5, -2902.8, 241.28, 2.095}, + {2517.8, -2896.6, 241.28, 2.315}, +}; + +const uint32 MOB_HORSEMEN[] = {16064, 16065, 30549, 16063}; +const uint32 SPELL_MARK[] = {28832, 28833, 28834, 28835}; +#define SPELL_PRIMARY(i) RAID_MODE(SPELL_PRIMARY_N[i],SPELL_PRIMARY_H[i]) +const uint32 SPELL_PRIMARY_N[] = {28884, 28863, 28882, 28883}; +const uint32 SPELL_PRIMARY_H[] = {57467, 57463, 57369, 57466}; +#define SPELL_SECONDARY(i) RAID_MODE(SPELL_SECONDARY_N[i],SPELL_SECONDARY_H[i]) +const uint32 SPELL_SECONDARY_N[]= {0, 57374, 0, 57376}; +const uint32 SPELL_SECONDARY_H[]= {0, 57464, 0, 57465}; +const uint32 SPELL_PUNISH[] = {0, 57381, 0, 57377}; +#define SPELL_BERSERK 26662 + +// used by 16063,16064,16065,30549, but signed for 16063 +const int32 SAY_AGGRO[] = {-1533051, -1533044, -1533065, -1533058}; +const int32 SAY_TAUNT[3][4] ={ {-1533052, -1533045, -1533071, -1533059}, + {-1533053, -1533046, -1533072, -1533060}, + {-1533054, -1533047, -1533073, -1533061},}; +const int32 SAY_SPECIAL[] = {-1533055, -1533048, -1533070, -1533062}; +const int32 SAY_SLAY[] = {-1533056, -1533049, -1533068, -1533063}; +const int32 SAY_DEATH[] = {-1533057, -1533050, -1533074, -1533064}; + +#define SAY_BARON_AGGRO RAND(-1533065,-1533066,-1533067) +#define SAY_BARON_SLAY RAND(-1533068,-1533069) + +struct boss_four_horsemenAI : public BossAI +{ + boss_four_horsemenAI(Creature *c) : BossAI(c, BOSS_HORSEMEN) + { + id = Horsemen(0); + for (uint8 i = 0; i < 4; ++i) + if (me->GetEntry() == MOB_HORSEMEN[i]) + id = Horsemen(i); + caster = (id == HORSEMEN_LADY || id == HORSEMEN_SIR); + } + + Horsemen id; + uint64 uiEventStarterGUID; + uint8 nextWP; + uint32 punishTimer; + bool caster; + bool nextMovementStarted; + bool movementCompleted; + bool movementStarted; + bool encounterActionAttack; + bool encounterActionReset; + bool doDelayPunish; + + void Reset() + { + if (!encounterActionReset) + DoEncounterAction(NULL, false, true, false); + + if (instance) + instance->SetData(DATA_HORSEMEN0 + id, NOT_STARTED); + + me->SetReactState(REACT_AGGRESSIVE); + uiEventStarterGUID = 0; + nextWP = 0; + punishTimer = 2000; + nextMovementStarted = false; + movementCompleted = false; + movementStarted = false; + encounterActionAttack = false; + encounterActionReset = false; + doDelayPunish = false; + _Reset(); + } + + bool DoEncounterAction(Unit *who, bool attack, bool reset, bool checkAllDead) + { + if (!instance) + return false; + + Creature *Thane = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_THANE))); + Creature *Lady = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_LADY))); + Creature *Baron = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_BARON))); + Creature *Sir = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_SIR))); + + if (Thane && Lady && Baron && Sir) + { + if (attack && who) + { + CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionAttack = true; + CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionAttack = true; + CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionAttack = true; + CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionAttack = true; + + CAST_AI(boss_four_horsemenAI, Thane->AI())->AttackStart(who); + CAST_AI(boss_four_horsemenAI, Lady->AI())->AttackStart(who); + CAST_AI(boss_four_horsemenAI, Baron->AI())->AttackStart(who); + CAST_AI(boss_four_horsemenAI, Sir->AI())->AttackStart(who); + } + + if (reset) + { + if (instance->GetBossState(BOSS_HORSEMEN) != NOT_STARTED) + { + if (!Thane->isAlive()) + Thane->Respawn(); + + if (!Lady->isAlive()) + Lady->Respawn(); + + if (!Baron->isAlive()) + Baron->Respawn(); + + if (!Sir->isAlive()) + Sir->Respawn(); + + CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionReset = true; + CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionReset = true; + CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionReset = true; + CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionReset = true; + + CAST_AI(boss_four_horsemenAI, Thane->AI())->EnterEvadeMode(); + CAST_AI(boss_four_horsemenAI, Lady->AI())->EnterEvadeMode(); + CAST_AI(boss_four_horsemenAI, Baron->AI())->EnterEvadeMode(); + CAST_AI(boss_four_horsemenAI, Sir->AI())->EnterEvadeMode(); + } + } + + if (checkAllDead) + return !Thane->isAlive() && !Lady->isAlive() && !Baron->isAlive() && !Sir->isAlive(); + } + return false; + } + + void BeginFourHorsemenMovement() + { + movementStarted = true; + me->SetReactState(REACT_PASSIVE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true); + + switch(id) + { + case HORSEMEN_THANE: + me->GetMotionMaster()->MovePoint(0, WaypointPositions[0]); + break; + case HORSEMEN_LADY: + me->GetMotionMaster()->MovePoint(3, WaypointPositions[3]); + break; + case HORSEMEN_BARON: + me->GetMotionMaster()->MovePoint(6, WaypointPositions[6]); + break; + case HORSEMEN_SIR: + me->GetMotionMaster()->MovePoint(9, WaypointPositions[9]); + break; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 2 || id == 5 || id == 8 || id == 11) + { + movementCompleted = true; + me->SetReactState(REACT_AGGRESSIVE); + + Unit *eventStarter = Unit::GetUnit(*me, uiEventStarterGUID); + + if (eventStarter && me->canAttack(eventStarter)) + AttackStart(eventStarter); + else if (!UpdateVictim()) + { + EnterEvadeMode(); + return; + } + + if (caster) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + } + + return; + } + + nextMovementStarted = false; + nextWP = id + 1; + } + + // switch to "who" if nearer than current target. + void SelectNearestTarget(Unit *who) + { + if (me->getVictim() && me->GetDistanceOrder(who, me->getVictim()) && me->canAttack(who)) + { + me->getThreatManager().modifyThreatPercent(me->getVictim(), -100); + me->AddThreat(who, 1000000.0f); + } + } + + void MoveInLineOfSight(Unit *who) + { + BossAI::MoveInLineOfSight(who); + if (caster) + SelectNearestTarget(who); + } + + void AttackStart(Unit *who) + { + if (!movementCompleted && !movementStarted) + { + uiEventStarterGUID = who->GetGUID(); + BeginFourHorsemenMovement(); + + if (!encounterActionAttack) + DoEncounterAction(who, true, false, false); + } + else if (movementCompleted && movementStarted) + { + if (caster) + me->Attack(who, false); + else + BossAI::AttackStart(who); + } + } + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%5)) + { + if (id == HORSEMEN_BARON) + DoScriptText(SAY_BARON_SLAY, me); + else + DoScriptText(SAY_SLAY[id], me); + } + } + + void JustDied(Unit* /*killer*/) + { + events.Reset(); + summons.DespawnAll(); + + if (instance) + instance->SetData(DATA_HORSEMEN0 + id, DONE); + + if (instance && DoEncounterAction(NULL, false, false, true)) + { + instance->SetBossState(BOSS_HORSEMEN, DONE); + instance->SaveToDB(); + + // Achievements related to the 4-horsemen are given through spell 59450 which does not exist. + // There is thus no way it can be given by casting the spell on the players. + instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59450); + } + + DoScriptText(SAY_DEATH[id], me); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + + if (id == HORSEMEN_BARON) + DoScriptText(SAY_BARON_AGGRO, me); + else + DoScriptText(SAY_AGGRO[id], me); + + events.ScheduleEvent(EVENT_MARK, 15000); + events.ScheduleEvent(EVENT_CAST, 20000+rand()%5000); + events.ScheduleEvent(EVENT_BERSERK, 15*100*1000); + } + + void UpdateAI(const uint32 diff) + { + if (nextWP && movementStarted && !movementCompleted && !nextMovementStarted) + { + nextMovementStarted = true; + me->GetMotionMaster()->MovePoint(nextWP, WaypointPositions[nextWP]); + } + + if (!UpdateVictim() || !CheckInRoom() || !movementCompleted) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_MARK: + if (!(rand()%5)) + DoScriptText(SAY_SPECIAL[id], me); + DoCastAOE(SPELL_MARK[id]); + events.ScheduleEvent(EVENT_MARK, 15000); + break; + case EVENT_CAST: + if (!(rand()%5)) + DoScriptText(SAY_TAUNT[rand()%3][id], me); + + if (caster) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) + DoCast(pTarget, SPELL_PRIMARY(id)); + } + else + DoCast(me->getVictim(), SPELL_PRIMARY(id)); + + events.ScheduleEvent(EVENT_CAST, 15000); + break; + case EVENT_BERSERK: + DoScriptText(SAY_SPECIAL[id], me); + DoCast(me, EVENT_BERSERK); + break; + } + } + + if (punishTimer <= diff) + { + if (doDelayPunish) + { + DoCastAOE(SPELL_PUNISH[id], true); + doDelayPunish = false; + } + punishTimer = 2000; + } else punishTimer -= diff; + + if (!caster) + DoMeleeAttackIfReady(); + else if ((!DoSpellAttackIfReady(SPELL_SECONDARY(id)) || !me->IsWithinLOSInMap(me->getVictim())) && movementCompleted && !doDelayPunish) + doDelayPunish = true; + } +}; + +CreatureAI* GetAI_four_horsemen(Creature* pCreature) +{ + return new boss_four_horsemenAI (pCreature); +} + +void AddSC_boss_four_horsemen() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_four_horsemen"; + newscript->GetAI = &GetAI_four_horsemen; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/naxxramas/boss_gluth.cpp new file mode 100644 index 00000000000..ab6fa6c46d3 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_gluth.cpp @@ -0,0 +1,147 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SPELL_MORTAL_WOUND 25646 +#define SPELL_ENRAGE RAID_MODE(28371,54427) +#define SPELL_DECIMATE RAID_MODE(28374,54426) +#define SPELL_BERSERK 26662 +#define SPELL_INFECTED_WOUND 29306 + +#define MOB_ZOMBIE 16360 + +const Position PosSummon[3] = +{ + {3267.9, -3172.1, 297.42, 0.94}, + {3253.2, -3132.3, 297.42, 0}, + {3308.3, -3185.8, 297.42, 1.58}, +}; + +enum Events +{ + EVENT_NONE, + EVENT_WOUND, + EVENT_ENRAGE, + EVENT_DECIMATE, + EVENT_BERSERK, + EVENT_SUMMON, +}; + +#define EMOTE_NEARBY " spots a nearby zombie to devour!" + +struct boss_gluthAI : public BossAI +{ + boss_gluthAI(Creature *c) : BossAI(c, BOSS_GLUTH) + { + // Do not let Gluth be affected by zombies' debuff + me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true); + } + + void MoveInLineOfSight(Unit *who) + { + if (who->GetEntry() == MOB_ZOMBIE && me->IsWithinDistInMap(who, 7)) + { + SetGazeOn(who); + // TODO: use a script text + me->MonsterTextEmote(EMOTE_NEARBY, 0, true); + } + else + BossAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + events.ScheduleEvent(EVENT_WOUND, 10000); + events.ScheduleEvent(EVENT_ENRAGE, 15000); + events.ScheduleEvent(EVENT_DECIMATE, 105000); + events.ScheduleEvent(EVENT_BERSERK, 8*60000); + events.ScheduleEvent(EVENT_SUMMON, 15000); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == MOB_ZOMBIE) + summon->AI()->AttackStart(me); + summons.Summon(summon); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictimWithGaze() || !CheckInRoom()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_WOUND: + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + events.ScheduleEvent(EVENT_WOUND, 10000); + break; + case EVENT_ENRAGE: + // TODO : Add missing text + DoCast(me, SPELL_ENRAGE); + events.ScheduleEvent(EVENT_ENRAGE, 15000); + break; + case EVENT_DECIMATE: + // TODO : Add missing text + DoCastAOE(SPELL_DECIMATE); + events.ScheduleEvent(EVENT_DECIMATE, 105000); + break; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + events.ScheduleEvent(EVENT_BERSERK, 5*60000); + break; + case EVENT_SUMMON: + for (uint32 i = 0; i < RAID_MODE(1,2); ++i) + DoSummon(MOB_ZOMBIE, PosSummon[rand()%3]); + events.ScheduleEvent(EVENT_SUMMON, 10000); + break; + } + } + + if (me->getVictim() && me->getVictim()->GetEntry() == MOB_ZOMBIE) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->Kill(me->getVictim()); + me->ModifyHealth(me->GetMaxHealth() * 0.05f); + } + } + else + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_gluth(Creature* pCreature) +{ + return new boss_gluthAI (pCreature); +} + +void AddSC_boss_gluth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gluth"; + newscript->GetAI = &GetAI_boss_gluth; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Northrend/naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/naxxramas/boss_gothik.cpp new file mode 100644 index 00000000000..d958ff24951 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_gothik.cpp @@ -0,0 +1,582 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Yells +{ + SAY_SPEECH = -1533040, + SAY_KILL = -1533041, + SAY_DEATH = -1533042, + SAY_TELEPORT = -1533043 +}; +//Gothik +enum Spells +{ + SPELL_HARVEST_SOUL = 28679, + SPELL_SHADOW_BOLT = 29317, + H_SPELL_SHADOW_BOLT = 56405, + SPELL_INFORM_LIVE_TRAINEE = 27892, + SPELL_INFORM_LIVE_KNIGHT = 27928, + SPELL_INFORM_LIVE_RIDER = 27935, + SPELL_INFORM_DEAD_TRAINEE = 27915, + SPELL_INFORM_DEAD_KNIGHT = 27931, + SPELL_INFORM_DEAD_RIDER = 27937 +}; +enum Creatures +{ + MOB_LIVE_TRAINEE = 16124, + MOB_LIVE_KNIGHT = 16125, + MOB_LIVE_RIDER = 16126, + MOB_DEAD_TRAINEE = 16127, + MOB_DEAD_KNIGHT = 16148, + MOB_DEAD_RIDER = 16150, + MOB_DEAD_HORSE = 16149 +}; + +struct Waves { uint32 entry, time, mode; }; +// wave setups are not the same in heroic and normal difficulty, +// mode is 0 only normal, 1 both and 2 only heroic +// but this is handled in DoGothikSummon function +const Waves waves[] = +{ + {MOB_LIVE_TRAINEE, 20000, 1}, + {MOB_LIVE_TRAINEE, 20000, 1}, + {MOB_LIVE_TRAINEE, 10000, 1}, + {MOB_LIVE_KNIGHT, 10000, 1}, + {MOB_LIVE_TRAINEE, 15000, 1}, + {MOB_LIVE_KNIGHT, 5000, 1}, + {MOB_LIVE_TRAINEE, 20000, 1}, + {MOB_LIVE_TRAINEE, 0, 1}, + {MOB_LIVE_KNIGHT, 10000, 1}, + {MOB_LIVE_TRAINEE, 10000, 2}, + {MOB_LIVE_RIDER, 10000, 0}, + {MOB_LIVE_RIDER, 5000, 2}, + {MOB_LIVE_TRAINEE, 5000, 0}, + {MOB_LIVE_TRAINEE, 15000, 2}, + {MOB_LIVE_KNIGHT, 15000, 0}, + {MOB_LIVE_TRAINEE, 0, 0}, + {MOB_LIVE_RIDER, 10000, 1}, + {MOB_LIVE_KNIGHT, 10000, 1}, + {MOB_LIVE_TRAINEE, 10000, 0}, + {MOB_LIVE_RIDER, 10000, 2}, + {MOB_LIVE_TRAINEE, 0, 2}, + {MOB_LIVE_RIDER, 5000, 1}, + {MOB_LIVE_TRAINEE, 0, 2}, + {MOB_LIVE_KNIGHT, 5000, 1}, + {MOB_LIVE_RIDER, 0, 2}, + {MOB_LIVE_TRAINEE, 20000, 1}, + {MOB_LIVE_RIDER, 0, 1}, + {MOB_LIVE_KNIGHT, 0, 1}, + {MOB_LIVE_TRAINEE, 25000, 2}, + {MOB_LIVE_TRAINEE, 15000, 0}, + {MOB_LIVE_TRAINEE, 25000, 0}, + {0, 0, 1}, +}; + +#define POS_Y_GATE -3360.78f +#define POS_Y_WEST -3285.0f +#define POS_Y_EAST -3434.0f +#define POS_X_NORTH 2750.49f +#define POS_X_SOUTH 2633.84f + +#define IN_LIVE_SIDE(who) (who->GetPositionY() < POS_Y_GATE) + +enum Events +{ + EVENT_NONE, + EVENT_SUMMON, + EVENT_HARVEST, + EVENT_BOLT, + EVENT_TELEPORT +}; +enum Pos +{ + POS_LIVE = 6, + POS_DEAD = 5 +}; + +const Position PosSummonLive[POS_LIVE] = +{ + {2669.7, -3428.76, 268.56, 1.6}, + {2692.1, -3428.76, 268.56, 1.6}, + {2714.4, -3428.76, 268.56, 1.6}, + {2669.7, -3431.67, 268.56, 1.6}, + {2692.1, -3431.67, 268.56, 1.6}, + {2714.4, -3431.67, 268.56, 1.6}, +}; + +const Position PosSummonDead[POS_DEAD] = +{ + {2725.1, -3310.0, 268.85, 3.4}, + {2699.3, -3322.8, 268.60, 3.3}, + {2733.1, -3348.5, 268.84, 3.1}, + {2682.8, -3304.2, 268.85, 3.9}, + {2664.8, -3340.7, 268.23, 3.7}, +}; + +const float PosGroundLiveSide[4] = {2691.2, -3387.0, 267.68, 1.52}; +const float PosGroundDeadSide[4] = {2693.5, -3334.6, 267.68, 4.67}; +const float PosPlatform[4] = {2640.5, -3360.6, 285.26, 0}; + +// Predicate function to check that the r efzr unit is NOT on the same side as the source. +struct NotOnSameSide : public std::unary_function { + bool m_inLiveSide; + NotOnSameSide(Unit *pSource) : m_inLiveSide(IN_LIVE_SIDE(pSource)) {} + bool operator() (const Unit *pTarget) { + return (m_inLiveSide != IN_LIVE_SIDE(pTarget)); + } +}; + +struct boss_gothikAI : public BossAI +{ + boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK) {} + + uint32 waveCount; + typedef std::vector TriggerVct; + TriggerVct liveTrigger, deadTrigger; + bool mergedSides; + bool phaseTwo; + bool thirtyPercentReached; + + std::vector LiveTriggerGUID; + std::vector DeadTriggerGUID; + + void Reset() + { + LiveTriggerGUID.clear(); + DeadTriggerGUID.clear(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); + me->SetReactState(REACT_PASSIVE); + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); + _Reset(); + mergedSides = false; + phaseTwo = false; + thirtyPercentReached = false; + } + + void EnterCombat(Unit * /*who*/) + { + for (uint32 i = 0; i < POS_LIVE; ++i) + if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonLive[i])) + LiveTriggerGUID.push_back(trigger->GetGUID()); + for (uint32 i = 0; i < POS_DEAD; ++i) + if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonDead[i])) + DeadTriggerGUID.push_back(trigger->GetGUID()); + + if (LiveTriggerGUID.size() < POS_LIVE || DeadTriggerGUID.size() < POS_DEAD) + { + error_log("Script Gothik: cannot summon triggers!"); + EnterEvadeMode(); + return; + } + + _EnterCombat(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); + waveCount = 0; + events.ScheduleEvent(EVENT_SUMMON, 30000); + DoTeleportTo(PosPlatform); + DoScriptText(SAY_SPEECH, me); + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_READY); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == WORLD_TRIGGER) + summon->setActive(true); + else if (!mergedSides) + { + summon->AI()->DoAction(me->HasReactState(REACT_PASSIVE) ? 1 : 0); + summon->AI()->EnterEvadeMode(); + } + else + { + summon->AI()->DoAction(0); + summon->AI()->DoZoneInCombat(); + } + summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature *summon) + { + summons.Despawn(summon); + } + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*Killer*/) + { + LiveTriggerGUID.clear(); + DeadTriggerGUID.clear(); + _JustDied(); + DoScriptText(SAY_DEATH, me); + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); + } + + void DoGothikSummon(uint32 entry) + { + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + { + switch(entry) + { + case MOB_LIVE_TRAINEE: + { + if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[0])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1); + if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[1])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1); + if (Creature *LiveTrigger2 = Unit::GetCreature(*me, LiveTriggerGUID[2])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger2, 1); + break; + } + case MOB_LIVE_KNIGHT: + { + if (Creature *LiveTrigger3 = Unit::GetCreature(*me, LiveTriggerGUID[3])) + DoSummon(MOB_LIVE_KNIGHT, LiveTrigger3, 1); + if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[5])) + DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1); + break; + } + case MOB_LIVE_RIDER: + { + if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1); + break; + } + } + } + else + { + switch(entry) + { + case MOB_LIVE_TRAINEE: + { + if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1); + if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1); + break; + } + case MOB_LIVE_KNIGHT: + { + if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1); + break; + } + case MOB_LIVE_RIDER: + { + if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1); + break; + } + } + } + } + + bool CheckGroupSplitted() + { + bool checklife = false; + bool checkdead = false; + + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->isAlive() && + i->getSource()->GetPositionX() <= POS_X_NORTH && + i->getSource()->GetPositionX() >= POS_X_SOUTH && + i->getSource()->GetPositionY() <= POS_Y_GATE && + i->getSource()->GetPositionY() >= POS_Y_EAST) + { + checklife = true; + } + else if (i->getSource() && i->getSource()->isAlive() && + i->getSource()->GetPositionX() <= POS_X_NORTH && + i->getSource()->GetPositionX() >= POS_X_SOUTH && + i->getSource()->GetPositionY() >= POS_Y_GATE && + i->getSource()->GetPositionY() <= POS_Y_WEST) + { + checkdead = true; + } + + if (checklife && checkdead) + return true; + } + } + } + + return false; + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + uint32 spellId = 0; + switch(spell->Id) + { + case SPELL_INFORM_LIVE_TRAINEE: spellId = SPELL_INFORM_DEAD_TRAINEE; break; + case SPELL_INFORM_LIVE_KNIGHT: spellId = SPELL_INFORM_DEAD_KNIGHT; break; + case SPELL_INFORM_LIVE_RIDER: spellId = SPELL_INFORM_DEAD_RIDER; break; + } + if (spellId && me->isInCombat()) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST); + if (Creature *pRandomDeadTrigger = Unit::GetCreature(*me, DeadTriggerGUID[rand() % POS_DEAD])) + me->CastSpell(pRandomDeadTrigger, spellId, true); + } + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (!me->isInCombat()) + return; + + switch(spell->Id) + { + case SPELL_INFORM_DEAD_TRAINEE: + DoSummon(MOB_DEAD_TRAINEE, pTarget, 0); + break; + case SPELL_INFORM_DEAD_KNIGHT: + DoSummon(MOB_DEAD_KNIGHT, pTarget, 0); + break; + case SPELL_INFORM_DEAD_RIDER: + DoSummon(MOB_DEAD_RIDER, pTarget, 1.0f); + DoSummon(MOB_DEAD_HORSE, pTarget, 1.0f); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateCombatState() || !CheckInRoom()) + return; + + events.Update(diff); + + if (!thirtyPercentReached && HealthBelowPct(30) && phaseTwo) + { + thirtyPercentReached = true; + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); + } + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SUMMON: + if (waves[waveCount].entry) + { + if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) + DoGothikSummon(waves[waveCount].entry); + else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) + DoGothikSummon(waves[waveCount].entry); + else if (waves[waveCount].mode == 1) + DoGothikSummon(waves[waveCount].entry); + + // if group is not splitted, open gate and merge both sides at ~ 2 minutes (wave 11) + if (waveCount == 11) + { + if (!CheckGroupSplitted()) + { + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); + summons.DoAction(0, 0); + summons.DoZoneInCombat(); + mergedSides = true; + } + } + + if (waves[waveCount].mode == 1) + events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); + else if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) + events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); + else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) + events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); + else + events.ScheduleEvent(EVENT_SUMMON, 0); + + ++waveCount; + } + else + { + phaseTwo = true; + DoScriptText(SAY_TELEPORT, me); + DoTeleportTo(PosGroundLiveSide); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + summons.DoAction(0, 0); + summons.DoZoneInCombat(); + events.ScheduleEvent(EVENT_BOLT, 1000); + events.ScheduleEvent(EVENT_HARVEST, urand(3000,15000)); + events.ScheduleEvent(EVENT_TELEPORT, 20000); + } + break; + case EVENT_BOLT: + DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BOLT, H_SPELL_SHADOW_BOLT)); + events.ScheduleEvent(EVENT_BOLT, 1000); + break; + case EVENT_HARVEST: + DoCast(me->getVictim(), SPELL_HARVEST_SOUL, true); + events.ScheduleEvent(EVENT_HARVEST, urand(20000,25000)); + break; + case EVENT_TELEPORT: + if (!thirtyPercentReached) + { + me->AttackStop(); + if (IN_LIVE_SIDE(me)) + { + DoTeleportTo(PosGroundDeadSide); + } + else + { + DoTeleportTo(PosGroundLiveSide); + } + + me->getThreatManager().resetAggro(NotOnSameSide(me)); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0)) + { + me->getThreatManager().addThreat(pTarget, 100.0f); + AttackStart(pTarget); + } + + events.ScheduleEvent(EVENT_TELEPORT, 20000); + } + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_gothik_minionAI : public CombatAI +{ + mob_gothik_minionAI(Creature *c) : CombatAI(c) + { + liveSide = IN_LIVE_SIDE(me); + } + + bool liveSide; + bool gateClose; + + bool isOnSameSide(const Unit *pWho) + { + return (liveSide == IN_LIVE_SIDE(pWho)); + } + + void DoAction(const int32 param) + { + gateClose = param; + } + + void DamageTaken(Unit *attacker, uint32 &damage) + { + if (gateClose && !isOnSameSide(attacker)) + damage = 0; + } + + void JustDied(Unit * /*killer*/) + { + if (me->isSummon()) + { + if (Unit *owner = CAST_SUM(me)->GetSummoner()) + CombatAI::JustDied(owner); + } + } + + void EnterEvadeMode() + { + if (!gateClose) + { + CombatAI::EnterEvadeMode(); + return; + } + + if (!_EnterEvadeMode()) + return; + + Map* pMap = me->GetMap(); + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->isAlive() && isOnSameSide(i->getSource())) + { + AttackStart(i->getSource()); + return; + } + } + } + } + + me->GetMotionMaster()->MoveIdle(); + Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (gateClose && (!isOnSameSide(me) || me->getVictim() && !isOnSameSide(me->getVictim()))) + { + EnterEvadeMode(); + return; + } + + CombatAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_boss_gothik(Creature* pCreature) +{ + return new boss_gothikAI (pCreature); +} + +CreatureAI* GetAI_mob_gothik_minion(Creature* pCreature) +{ + return new mob_gothik_minionAI (pCreature); +} + +void AddSC_boss_gothik() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gothik"; + newscript->GetAI = &GetAI_boss_gothik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_gothik_minion"; + newscript->GetAI = &GetAI_mob_gothik_minion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp new file mode 100644 index 00000000000..7df01e18483 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SPELL_BOMBARD_SLIME 28280 + +#define SPELL_POISON_CLOUD 28240 +#define SPELL_MUTATING_INJECTION 28169 +#define SPELL_SLIME_SPRAY RAID_MODE(28157,54364) +#define SPELL_BERSERK 26662 +#define SPELL_POISON_CLOUD_ADD 59116 + +#define EVENT_BERSERK 1 +#define EVENT_CLOUD 2 +#define EVENT_INJECT 3 +#define EVENT_SPRAY 4 + +#define MOB_FALLOUT_SLIME 16290 + +struct boss_grobbulusAI : public BossAI +{ + boss_grobbulusAI(Creature *c) : BossAI(c, BOSS_GROBBULUS) + { + me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_POISON_CLOUD_ADD, true); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + events.ScheduleEvent(EVENT_CLOUD, 15000); + events.ScheduleEvent(EVENT_INJECT, 20000); + events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure + events.ScheduleEvent(EVENT_BERSERK, 12*60000); + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (spell->Id == uint32(SPELL_SLIME_SPRAY)) + { + if (TempSummon *slime = me->SummonCreature(MOB_FALLOUT_SLIME, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) + DoZoneInCombat(slime); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CLOUD: + DoCastAOE(SPELL_POISON_CLOUD); + events.ScheduleEvent(EVENT_CLOUD, 15000); + return; + case EVENT_BERSERK: + DoCastAOE(SPELL_BERSERK); + return; + case EVENT_SPRAY: + DoCastAOE(SPELL_SLIME_SPRAY); + events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); + return; + case EVENT_INJECT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + if (!pTarget->HasAura(SPELL_MUTATING_INJECTION)) + DoCast(pTarget, SPELL_MUTATING_INJECTION); + events.ScheduleEvent(EVENT_INJECT, 8000 + 12000 * ((float)me->GetHealth() / me->GetMaxHealth())); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_grobbulus_poison_cloudAI : public Scripted_NoMovementAI +{ + npc_grobbulus_poison_cloudAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + Reset(); + } + + uint32 Cloud_Timer; + + void Reset() + { + Cloud_Timer = 1000; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void UpdateAI(const uint32 diff) + { + if (Cloud_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLOUD_ADD); + Cloud_Timer = 10000; + } else Cloud_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_grobbulus(Creature* pCreature) +{ + return new boss_grobbulusAI (pCreature); +} + +CreatureAI* GetAI_npc_grobbulus_poison_cloud(Creature* pCreature) +{ + return new npc_grobbulus_poison_cloudAI(pCreature); +} + +void AddSC_boss_grobbulus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grobbulus"; + newscript->GetAI = &GetAI_boss_grobbulus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_grobbulus_poison_cloud"; + newscript->GetAI = &GetAI_npc_grobbulus_poison_cloud; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/naxxramas/boss_heigan.cpp new file mode 100644 index 00000000000..1de9c0e00c8 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_heigan.cpp @@ -0,0 +1,149 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SAY_AGGRO RAND(-1533109,-1533110,-1533111) +#define SAY_SLAY -1533112 +#define SAY_TAUNT RAND(-1533113,-1533114,-1533115,-1533116,-1533117) +#define SAY_DEATH -1533118 + +#define SPELL_SPELL_DISRUPTION 29310 +#define SPELL_DECREPIT_FEVER RAID_MODE(29998,55011) +#define SPELL_PLAGUE_CLOUD 29350 + +enum Events +{ + EVENT_NONE, + EVENT_DISRUPT, + EVENT_FEVER, + EVENT_ERUPT, + EVENT_PHASE, +}; + +enum Phases +{ + PHASE_FIGHT = 1, + PHASE_DANCE, +}; + +struct boss_heiganAI : public BossAI +{ + boss_heiganAI(Creature *c) : BossAI(c, BOSS_HEIGAN) {} + + uint32 eruptSection; + bool eruptDirection; + Phases phase; + + void KilledUnit(Unit* /*Victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_SLAY, me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO, me); + EnterPhase(PHASE_FIGHT); + } + + void EnterPhase(Phases newPhase) + { + phase = newPhase; + events.Reset(); + eruptSection = 3; + if (phase == PHASE_FIGHT) + { + events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000)); + events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000)); + events.ScheduleEvent(EVENT_PHASE, 90000); + events.ScheduleEvent(EVENT_ERUPT, 15000); + } + else + { + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + me->NearTeleportTo(x, y, z, o); + DoCastAOE(SPELL_PLAGUE_CLOUD); + events.ScheduleEvent(EVENT_PHASE, 45000); + events.ScheduleEvent(EVENT_ERUPT, 8000); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || !CheckInRoom()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_DISRUPT: + DoCastAOE(SPELL_SPELL_DISRUPTION); + events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000)); + break; + case EVENT_FEVER: + DoCastAOE(SPELL_DECREPIT_FEVER); + events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000)); + break; + case EVENT_PHASE: + // TODO : Add missing texts for both phase switches + EnterPhase(phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT); + break; + case EVENT_ERUPT: + instance->SetData(DATA_HEIGAN_ERUPT, eruptSection); + TeleportCheaters(); + + if (eruptSection == 0) + eruptDirection = true; + else if (eruptSection == 3) + eruptDirection = false; + + eruptDirection ? ++eruptSection : --eruptSection; + + events.ScheduleEvent(EVENT_ERUPT, phase == PHASE_FIGHT ? 10000 : 3000); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_heigan(Creature* pCreature) +{ + return new boss_heiganAI (pCreature); +} + +void AddSC_boss_heigan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_heigan"; + newscript->GetAI = &GetAI_boss_heigan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp b/src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp new file mode 100644 index 00000000000..4eb72a3780e --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp @@ -0,0 +1,179 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Highlord_Mograine +SD%Complete: 100 +SDComment: SCRIPT OBSOLETE +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//All horsemen +#define SPELL_SHIELDWALL 29061 +#define SPELL_BESERK 26662 + +// highlord mograine +#define SPELL_MARK_OF_MOGRAINE 28834 +#define SPELL_RIGHTEOUS_FIRE 28882 // Applied as a 25% chance on melee hit to proc. me->GetVictim() + +#define SAY_TAUNT1 "Enough prattling. Let them come! We shall grind their bones to dust." +#define SAY_TAUNT2 "Conserve your anger! Harness your rage! You will all have outlets for your frustration soon enough." +#define SAY_TAUNT3 "Life is meaningless. It is in death that we are truly tested." +#define SAY_AGGRO1 "You seek death?" +#define SAY_AGGRO2 "None shall pass!" +#define SAY_AGGRO3 "Be still!" +#define SAY_SLAY1 "You will find no peace in death." +#define SAY_SLAY2 "The master's will is done." +#define SAY_SPECIAL "Bow to the might of the Highlord!" +#define SAY_DEATH "I... am... released! Perhaps it's not too late to - noo! I need... more time..." + +#define SOUND_TAUNT1 8842 +#define SOUND_TAUNT2 8843 +#define SOUND_TAUNT3 8844 +#define SOUND_AGGRO1 8835 +#define SOUND_AGGRO2 8836 +#define SOUND_AGGRO3 8837 +#define SOUND_SLAY1 8839 +#define SOUND_SLAY2 8840 +#define SOUND_SPECIAL 8841 +#define SOUND_DEATH 8838 + +#define SPIRIT_OF_MOGRAINE 16775 + +struct TRINITY_DLL_DECL boss_highlord_mograineAI : public ScriptedAI +{ + boss_highlord_mograineAI(Creature *c) : ScriptedAI(c) {} + + uint32 Mark_Timer; + uint32 RighteousFire_Timer; + bool ShieldWall1; + bool ShieldWall2; + + void Reset() + { + Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. + RighteousFire_Timer = 2000; // applied approx 1 out of 4 attacks + ShieldWall1 = true; + ShieldWall2 = true; + } + + void InitialYell() + { + if (!me->isInCombat()) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_AGGRO3); + break; + } + } + } + + void KilledUnit() + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_SLAY2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + InitialYell(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Mark of Mograine + if (Mark_Timer < diff) + { + DoCast(me->getVictim(),SPELL_MARK_OF_MOGRAINE); + Mark_Timer = 12000; + }else Mark_Timer -= diff; + + // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds + if (ShieldWall1 && (me->GetHealth()*100 / me->GetMaxHealth()) < 50) + { + if (ShieldWall1) + { + DoCast(me,SPELL_SHIELDWALL); + ShieldWall1 = false; + } + } + if (ShieldWall2 && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) + { + if (ShieldWall2) + { + DoCast(me,SPELL_SHIELDWALL); + ShieldWall2 = false; + } + } + + // Righteous Fire + if (RighteousFire_Timer < diff) + { + if (rand()%4 == 1) // 1/4 + { + DoCast(me->getVictim(),SPELL_RIGHTEOUS_FIRE); + } + RighteousFire_Timer = 2000; + }else RighteousFire_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_highlord_mograine(Creature* pCreature) +{ + return new boss_highlord_mograineAI (pCreature); +} + +void AddSC_boss_highlord_mograine() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_highlord_mograine"; + newscript->GetAI = &GetAI_boss_highlord_mograine; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp new file mode 100644 index 00000000000..bfcd0636298 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp @@ -0,0 +1,706 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_KelThuzad +SD%Complete: 80% +SDComment: VERIFY SCRIPT +SDCategory: Naxxramas +EndScriptData */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Yells +{ + //when shappiron dies. dialog between kel and lich king (in this order) + SAY_SAPP_DIALOG1 = -1533084, //not used + SAY_SAPP_DIALOG2_LICH = -1533085, //not used + SAY_SAPP_DIALOG3 = -1533086, //not used + SAY_SAPP_DIALOG4_LICH = -1533087, //not used + SAY_SAPP_DIALOG5 = -1533088, //not used + SAY_CAT_DIED = -1533089, //when cat dies, not used + //when each of the 4 wing bosses dies + SAY_TAUNT1 = -1533090, //not used + SAY_TAUNT2 = -1533091, //not used + SAY_TAUNT3 = -1533092, //not used + SAY_TAUNT4 = -1533093, //not used + SAY_SUMMON_MINIONS = -1533105, //start of phase 1 + SAY_AGGRO_1 = -1533094, //start of phase 2 + SAY_AGGRO_2 = -1533095, + SAY_AGGRO_3 = -1533096, + SAY_SLAY_1 = -1533097, + SAY_SLAY_2 = -1533098, + SAY_DEATH = -1533099, + SAY_CHAIN_1 = -1533100, + SAY_CHAIN_2 = -1533101, + SAY_FROST_BLAST = -1533102, + SAY_SPECIAL_1 = -1533106, + SAY_SPECIAL_2 = -1533107, + SAY_SPECIAL_3 = -1533108, + SAY_REQUEST_AID = -1533103, //start of phase 3 + SAY_ANSWER_REQUEST = -1533104 //lich king answer +}; +enum Event +{ + EVENT_NONE, + EVENT_BOLT, + EVENT_NOVA, + EVENT_CHAIN, + EVENT_CHAINED_SPELL, + EVENT_DETONATE, + EVENT_FISSURE, + EVENT_BLAST, + + EVENT_WASTE, + EVENT_ABOMIN, + EVENT_WEAVER, + EVENT_ICECROWN, + EVENT_TRIGGER, + + EVENT_PHASE, +}; + +enum Spells +{ + SPELL_FROST_BOLT = 28478, + H_SPELL_FROST_BOLT = 55802, + SPELL_FROST_BOLT_AOE = 28479, + H_SPELL_FROST_BOLT_AOE = 55807, + SPELL_SHADOW_FISURE = 27810, + SPELL_VOID_BLAST = 27812, + SPELL_MANA_DETONATION = 27819, + SPELL_FROST_BLAST = 27808, + SPELL_CHAINS_OF_KELTHUZAD = 28410, //28408 script effect + SPELL_KELTHUZAD_CHANNEL = 29423, + SPELL_BERSERK = 28498, + + //spells for chained + //warlock + SPELL_CURSE_OF_AGONY = 47864, + SPELL_SHADOW_BOLT = 47809, + //shaman + SPELL_EARTH_SHOCK = 49231, + SPELL_HEALING_WAVE = 49273, + //mage + SPELL_FROST_FIREBOLT = 47610, + SPELL_ARCANE_MISSILES = 42846, + //rogue + SPELL_HEMORRHAGE = 48660, + SPELL_MUTILATE = 48666, + //paladin + SPELL_HOLY_SHOCK = 48825, + SPELL_HAMMER_OF_JUSTICE = 10308, + //priest + SPELL_VAMPIRIC_TOUCH = 48160, + SPELL_RENEW = 48068, + //hunter + SPELL_MULTI_SHOT = 49048, + SPELL_VOLLEY = 58434, + //warrior + SPELL_BLADESTORM = 46924, + SPELL_CLEAVE = 47520, + //druid + SPELL_MOONFIRE = 48463, + SPELL_LIFEBLOOM = 48451, + //death knight + SPELL_PLAGUE_STRIKE = 49921, + SPELL_HOWLING_BLAST = 51411, +}; + +enum Creatures +{ + NPC_WASTE = 16427, // Soldiers of the Frozen Wastes + NPC_ABOMINATION = 16428, // Unstoppable Abominations + NPC_WEAVER = 16429, // Soul Weavers + NPC_ICECROWN = 16441 // Guardians of Icecrown +}; + +const Position Pos[12] = +{ + {3783.272705, -5062.697266, 143.711203, 3.617599}, //LEFT_FAR + {3730.291260, -5027.239258, 143.956909, 4.461900}, //LEFT_MIDDLE + {3757.6, -5172.0, 143.7, 1.97}, //WINDOW_PORTAL05 + {3759.355225, -5174.128418, 143.802383, 2.170104}, //RIGHT_FAR + {3700.724365, -5185.123047, 143.928024, 1.309310}, //RIGHT_MIDDLE + {3700.86, -5181.29, 143.928024, 1.42}, //WINDOW_PORTAL04 + {3754.431396, -5080.727734, 142.036316, 3.736189}, //LEFT_FAR + {3724.396484, -5061.330566, 142.032700, 4.564785}, //LEFT_MIDDLE + {3732.02, -5028.53, 143.92, 4.49}, //WINDOW_PORTAL02 + {3687.571777, -5126.831055, 142.017807, 0.604023}, //RIGHT_FAR + {3707.990733, -5151.450195, 142.032562, 1.376855}, //RIGHT_MIDDLE + {3782.76, -5062.97, 143.79, 3.82}, //WINDOW_PORTAL03 +}; + +//creatures in corners +//Unstoppable Abominations +#define MAX_ABOMINATIONS 21 +const Position PosAbominations[MAX_ABOMINATIONS] = +{ + {3755.52, -5155.22, 143.480, 2.0}, + {3744.35, -5164.03, 143.590, 2.00}, + {3749.28, -5159.04, 143.190, 2.0}, + {3774.47, -5076.28, 143.528, 2.15912}, + {3765.94, -5074.15, 143.186, 3.77233}, + {3763.15, -5063.36, 143.694, 3.77233}, + {3737.81, -5045.69, 143.709, 4.9033}, + {3728.13, -5045.01, 143.355, 1.45069}, + {3721.56, -5048.35, 143.542, 1.45069}, + {3689.55, -5049.66, 143.637, 5.2104}, + {3681.71, -5053.03, 143.242, 2.47957}, + {3677.64, -5061.44, 143.358, 2.47957}, + {3654.2, -5090.87, 143.469, 1.0313}, + {3650.39, -5097.45, 143.496, 2.5047}, + {3658.7, -5103.59, 143.607, 3.3278}, + {3659.02, -5133.97, 143.624, 3.84538}, + {3666.33, -5139.34, 143.183, 3.84538}, + {3669.74, -5149.63, 143.678, 0.528643}, + {3695.53, -5169.53, 143.671, 2.11908}, + {3701.98, -5166.51, 143.395, 1.24257}, + {3709.62, -5169.15, 143.576, 5.97695}, +}; + +//Soldiers of the Frozen Wastes +#define MAX_WASTES 49 +const Position PosWastes[MAX_WASTES] = +{ + {3754.41, -5147.24, 143.204, 2.0}, + {3754.68, -5156.17, 143.418, 2.0}, + {3757.91, -5160.12, 143.503, 2.0}, + {3752.67, -5164.6, 143.395, 2.0}, + {3745.42, -5164.47, 143.565, 2.74587}, + {3741.2, -5155.92, 143.17, 5.29134}, + {3746.57, -5148.82, 143.176, 5.07772}, + {3778.14, -5070.1, 143.568, 3.16208}, + {3775.09, -5078.97, 143.65, 2.81022}, + {3773.54, -5083.47, 143.758, 3.21549}, + {3765, -5078.29, 143.176, 4.36688}, + {3766.94, -5072.63, 143.184, 5.27951}, + {3762.68, -5064.94, 143.635, 3.95297}, + {3769.9, -5059.94, 143.74, 3.36549}, + {3736.33, -5042.18, 143.643, 5.9471}, + {3727.51, -5040.58, 143.502, 0.871859}, + {3719.89, -5049.64, 143.58, 4.75172}, + {3720.69, -5044.43, 143.662, 1.87245}, + {3725.69, -5048.99, 143.363, 2.48271}, + {3732.33, -5054.01, 143.44, 3.59405}, + {3738.09, -5051.06, 143.718, 4.70931}, + {3682.76, -5063.5, 143.175, 0.636238}, + {3686.7, -5060.58, 143.18, 0.636238}, + {3682.45, -5057.21, 143.184, 5.61252}, + {3677.57, -5053.34, 143.369, 1.52531}, + {3677.3, -5062.26, 143.369, 2.73482}, + {3691.21, -5053.02, 143.421, 5.93218}, + {3685.22, -5053.34, 143.314, 4.70303}, + {3652.11, -5088.47, 143.555, 0.793317}, + {3648.23, -5093.21, 143.311, 1.18837}, + {3648.14, -5100.11, 143.632, 2.12221}, + {3653.88, -5099.7, 143.558, 3.04348}, + {3661.23, -5100.33, 143.42, 4.08335}, + {3663.49, -5092.77, 143.346, 4.47134}, + {3661.85, -5087.99, 143.571, 1.0148}, + {3664.56, -5149.01, 143.532, 0.0762528}, + {3665.01, -5142.04, 143.201, 1.72009}, + {3671.15, -5142.92, 143.174, 4.81535}, + {3670.18, -5134.38, 143.177, 5.37534}, + {3664.33, -5131.69, 143.262, 5.39576}, + {3658.21, -5133.63, 143.662, 1.3863}, + {3659.7, -5144.49, 143.363, 2.32328}, + {3705.71, -5179.63, 143.746, 1.06743}, + {3696.77, -5177.45, 143.759, 5.36748}, + {3700.97, -5173.13, 143.52, 3.26575}, + {3708.53, -5172.19, 143.573, 3.26575}, + {3712.49, -5167.62, 143.657, 5.63295}, + {3704.89, -5161.84, 143.239, 5.63295}, + {3695.66, -5164.63, 143.674, 1.54416}, +}; + +//Soul Weavers +#define MAX_WEAVERS 7 +const Position PosWeavers[MAX_WEAVERS] = +{ + {3752.45, -5168.35, 143.562, 1.6094}, + {3772.2, -5070.04, 143.329, 1.93686}, + {3732.28, -5032.88, 143.771, 3.08355}, + {3689.05, -5055.7, 143.172, 6.09554}, + {3649.45, -5093.17, 143.299, 2.51805}, + {3659.7, -5144.49, 143.363, 4.08806}, + {3704.71, -5175.96, 143.597, 3.36549}, +}; + +// predicate function to select not charmed target +struct NotCharmedTargetSelector : public std::unary_function { + NotCharmedTargetSelector() {} + + bool operator() (const Unit *pTarget) { + return (!pTarget->isCharmed()); + } +}; + +struct boss_kelthuzadAI : public BossAI +{ + boss_kelthuzadAI(Creature* c) : BossAI(c, BOSS_KELTHUZAD), spawns(c) + { + uiFaction = me->getFaction(); + } + + uint32 Phase; + uint32 uiGuardiansOfIcecrownTimer; + uint32 uiFaction; + + uint8 nGuardiansOfIcecrownCount; + uint8 nAbomination; + uint8 nWeaver; + + std::map chained; + + uint64 PortalsGUID[4]; + uint64 KTTriggerGUID; + + SummonList spawns; // adds spawn by the trigger. kept in separated list (i.e. not in summons) + + void Reset() + { + _Reset(); + + PortalsGUID[0] = PortalsGUID[1] = PortalsGUID[2] = PortalsGUID[3] = 0; + KTTriggerGUID = 0; + + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + std::map::const_iterator itr; + for (itr = chained.begin(); itr != chained.end(); ++itr) + { + if (Player* charmed = Unit::GetPlayer((*itr).first)) + charmed->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + } + + chained.clear(); + spawns.DespawnAll(); + + FindGameObjects(); + + if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID)) + { + pKTTrigger->ResetDoorOrButton(); + pKTTrigger->SetPhaseMask(1, true); + } + + for (uint8 i = 0; i <= 3; ++i) + { + if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) + { + if (!((pPortal->getLootState() == GO_READY) || (pPortal->getLootState() == GO_NOT_READY))) + pPortal->ResetDoorOrButton(); + } + } + + nGuardiansOfIcecrownCount = 0; + uiGuardiansOfIcecrownTimer = 5000; //5 seconds for summoning each Guardian of Icecrown in phase 3 + + Phase = 0; + nAbomination = 0; + nWeaver = 0; + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + + std::map::const_iterator itr; + for (itr = chained.begin(); itr != chained.end(); ++itr) + { + if (Player* pPlayer = Unit::GetPlayer((*itr).first)) + pPlayer->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + } + chained.clear(); + } + + void EnterCombat(Unit* /*who*/) + { + me->setFaction(uiFaction); + + _EnterCombat(); + FindGameObjects(); + for (uint8 i = 0; i <= 3; ++i) + { + if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) + pPortal->ResetDoorOrButton(); + } + DoCast(me, SPELL_KELTHUZAD_CHANNEL, false); + DoScriptText(SAY_SUMMON_MINIONS, me); + Phase = 1; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4); + events.ScheduleEvent(EVENT_TRIGGER, 5000); + events.ScheduleEvent(EVENT_WASTE, 15000); + events.ScheduleEvent(EVENT_ABOMIN, 30000); + events.ScheduleEvent(EVENT_WEAVER, 50000); + events.ScheduleEvent(EVENT_PHASE, 228000); + } + + void FindGameObjects() + { + PortalsGUID[0] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL01) : 0; + PortalsGUID[1] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL02) : 0; + PortalsGUID[2] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL03) : 0; + PortalsGUID[3] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL04) : 0; + KTTriggerGUID = instance ? instance->GetData64(DATA_KELTHUZAD_TRIGGER) : 0; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateCombatState()) + return; + + events.Update(diff); + + if (Phase == 1) + { + while (uint32 eventId = events.GetEvent()) + { + switch(eventId) + { + case EVENT_WASTE: + DoSummon(NPC_WASTE, Pos[RAND(0,3,6,9)]); + events.RepeatEvent(urand(2000,5000)); + break; + case EVENT_ABOMIN: + if (nAbomination < 8) + { + DoSummon(NPC_ABOMINATION, Pos[RAND(1,4,7,10)]); + nAbomination++; + events.RepeatEvent(20000); + } + else + events.PopEvent(); + break; + case EVENT_WEAVER: + if (nWeaver < 8) + { + DoSummon(NPC_WEAVER, Pos[RAND(0,3,6,9)]); + nWeaver++; + events.RepeatEvent(25000); + } + else + events.PopEvent(); + break; + case EVENT_TRIGGER: + if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID)) + pKTTrigger->SetPhaseMask(2, true); + events.PopEvent(); + break; + case EVENT_PHASE: + events.Reset(); + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + spawns.DespawnAll(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->CastStop(); + + DoStartMovement(me->getVictim()); + events.ScheduleEvent(EVENT_BOLT, urand(5000,10000)); + events.ScheduleEvent(EVENT_NOVA, 15000); + events.ScheduleEvent(EVENT_DETONATE, urand(30000,40000)); + events.ScheduleEvent(EVENT_FISSURE, urand(10000,30000)); + events.ScheduleEvent(EVENT_BLAST, urand(60000,120000)); + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + events.ScheduleEvent(EVENT_CHAIN, urand(30000,60000)); + Phase = 2; + break; + default: + events.PopEvent(); + break; + } + } + } + else + { + //start phase 3 when we are 45% health + if (Phase != 3) + { + if (HealthBelowPct(45)) + { + Phase = 3 ; + DoScriptText(SAY_REQUEST_AID, me); + //here Lich King should respond to KelThuzad but I don't know which Creature to make talk + //so for now just make Kelthuzad says it. + DoScriptText(SAY_ANSWER_REQUEST, me); + + for (uint8 i = 0; i <= 3; ++i) + { + if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) + { + if (pPortal->getLootState() == GO_READY) + pPortal->UseDoorOrButton(); + } + } + } + } + else if (nGuardiansOfIcecrownCount < RAID_MODE(2,4)) + { + if (uiGuardiansOfIcecrownTimer <= diff) + { + // TODO : Add missing text + if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2,5,8,11)])) + pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2); + ++nGuardiansOfIcecrownCount; + uiGuardiansOfIcecrownTimer = 5000; + } + else uiGuardiansOfIcecrownTimer -= diff; + } + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (uint32 eventId = events.GetEvent()) + { + switch(eventId) + { + case EVENT_BOLT: + DoCastVictim(RAID_MODE(SPELL_FROST_BOLT,H_SPELL_FROST_BOLT)); + events.RepeatEvent(urand(5000,10000)); + break; + case EVENT_NOVA: + DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE,H_SPELL_FROST_BOLT_AOE)); + events.RepeatEvent(urand(15000,30000)); + break; + case EVENT_CHAIN: + { + uint32 count = urand(1,3); + for (uint8 i = 1; i <= count; i++) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true); + if (pTarget && !pTarget->isCharmed() && (chained.find(pTarget->GetGUID()) == chained.end())) + { + DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD); + float scale = pTarget->GetFloatValue(OBJECT_FIELD_SCALE_X); + chained.insert(std::make_pair(pTarget->GetGUID(), scale)); + pTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2); + events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm + } + } + if (!chained.empty()) + DoScriptText(RAND(SAY_CHAIN_1,SAY_CHAIN_2), me); + events.RepeatEvent(urand(100000,180000)); + break; + } + case EVENT_CHAINED_SPELL: + { + std::map::iterator itr; + for (itr = chained.begin(); itr != chained.end();) + { + if (Unit* player = Unit::GetPlayer((*itr).first)) + { + if (!player->isCharmed()) + { + player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + std::map::iterator next = itr; + ++next; + chained.erase(itr); + itr = next; + continue; + } + + if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector())) + { + switch(player->getClass()) + { + case CLASS_DRUID: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_MOONFIRE, false); + else + player->CastSpell(me, SPELL_LIFEBLOOM, false); + break; + case CLASS_HUNTER: + player->CastSpell(pTarget, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false); + break; + case CLASS_MAGE: + player->CastSpell(pTarget, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false); + break; + case CLASS_WARLOCK: + player->CastSpell(pTarget, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true); + break; + case CLASS_WARRIOR: + player->CastSpell(pTarget, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false); + break; + case CLASS_PALADIN: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_HAMMER_OF_JUSTICE, false); + else + player->CastSpell(me, SPELL_HOLY_SHOCK, false); + break; + case CLASS_PRIEST: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_VAMPIRIC_TOUCH, false); + else + player->CastSpell(me, SPELL_RENEW, false); + break; + case CLASS_SHAMAN: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_EARTH_SHOCK, false); + else + player->CastSpell(me, SPELL_HEALING_WAVE, false); + break; + case CLASS_ROGUE: + player->CastSpell(pTarget, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false); + break; + case CLASS_DEATH_KNIGHT: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_PLAGUE_STRIKE, true); + else + player->CastSpell(pTarget, SPELL_HOWLING_BLAST, true); + break; + } + } + } + ++itr; + } + + if (chained.empty()) + events.PopEvent(); + else + events.RepeatEvent(5000); + + break; + } + case EVENT_DETONATE: + { + std::vector unitList; + std::list *threatList = &me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr) + { + if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER + && (*itr)->getTarget()->getPowerType() == POWER_MANA + && (*itr)->getTarget()->GetPower(POWER_MANA)) + unitList.push_back((*itr)->getTarget()); + } + + if (!unitList.empty()) + { + std::vector::const_iterator itr = unitList.begin(); + advance(itr, rand()%unitList.size()); + DoCast(*itr, SPELL_MANA_DETONATION); + DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2,SAY_SPECIAL_3), me); + } + + events.RepeatEvent(urand(20000,50000)); + break; + } + case EVENT_FISSURE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_FISURE); + events.RepeatEvent(urand(10000,45000)); + break; + case EVENT_BLAST: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1,0), 0, true)) + DoCast(pTarget, SPELL_FROST_BLAST); + if (rand()%2) + DoScriptText(SAY_FROST_BLAST, me); + events.RepeatEvent(urand(30000,90000)); + break; + default: + events.PopEvent(); + break; + } + } + + DoMeleeAttackIfReady(); + } + } +}; + +CreatureAI* GetAI_boss_kelthuzadAI(Creature* pCreature) +{ + return new boss_kelthuzadAI (pCreature); +} + +bool AreaTrigger_at_kelthuzad_center(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + if (pPlayer->isGameMaster()) + return false; + + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (!pInstance || pInstance->IsEncounterInProgress() || pInstance->GetBossState(BOSS_KELTHUZAD) == DONE) + return false; + + Creature* pKelthuzad = CAST_CRE(Unit::GetUnit(*pPlayer, pInstance->GetData64(DATA_KELTHUZAD))); + if (!pKelthuzad) + return false; + + boss_kelthuzadAI* pKelthuzadAI = CAST_AI(boss_kelthuzadAI, pKelthuzad->AI()); + if (!pKelthuzadAI) + return false; + + pKelthuzadAI->AttackStart(pPlayer); + if (GameObject* trigger = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_TRIGGER))) + { + if (trigger->getLootState() == GO_READY) + trigger->UseDoorOrButton(); + + // Note: summon must be done by trigger and not by KT. + // Otherwise, they attack immediately as KT is in combat. + for (uint8 i = 0; i <= MAX_ABOMINATIONS; ++i) + { + if (Creature* sum = trigger->SummonCreature(NPC_ABOMINATION, PosAbominations[i])) + { + pKelthuzadAI->spawns.Summon(sum); + sum->GetMotionMaster()->MoveRandom(9.0f); + sum->SetReactState(REACT_DEFENSIVE); + } + } + for (uint8 i = 0; i <= MAX_WASTES; ++i) + { + if (Creature* sum = trigger->SummonCreature(NPC_WASTE, PosWastes[i])) + { + pKelthuzadAI->spawns.Summon(sum); + sum->GetMotionMaster()->MoveRandom(5.0f); + sum->SetReactState(REACT_DEFENSIVE); + } + } + for (uint8 i = 0; i <= MAX_WEAVERS; ++i) + { + if (Creature* sum = trigger->SummonCreature(NPC_WEAVER, PosWeavers[i])) + { + pKelthuzadAI->spawns.Summon(sum); + sum->GetMotionMaster()->MoveRandom(9.0f); + sum->SetReactState(REACT_DEFENSIVE); + } + } + } + + return true; +} + +void AddSC_boss_kelthuzad() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kelthuzad"; + newscript->GetAI = &GetAI_boss_kelthuzadAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_kelthuzad_center"; + newscript->pAreaTrigger = &AreaTrigger_at_kelthuzad_center; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp new file mode 100644 index 00000000000..0b0c8f5e4c5 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Spells +{ + SPELL_NECROTIC_AURA = 55593, + SPELL_SUMMON_SPORE = 29234, + SPELL_DEATHBLOOM = 29865, + H_SPELL_DEATHBLOOM = 55053, + SPELL_INEVITABLE_DOOM = 29204, + H_SPELL_INEVITABLE_DOOM = 55052 +}; + +enum Events +{ + EVENT_NONE, + EVENT_AURA, + EVENT_BLOOM, + EVENT_DOOM, +}; + +struct boss_loathebAI : public BossAI +{ + boss_loathebAI(Creature *c) : BossAI(c, BOSS_LOATHEB) {} + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + events.ScheduleEvent(EVENT_AURA, 10000); + events.ScheduleEvent(EVENT_BLOOM, 5000); + events.ScheduleEvent(EVENT_DOOM, 120000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_AURA: + DoCastAOE(SPELL_NECROTIC_AURA); + events.ScheduleEvent(EVENT_AURA, 20000); + break; + case EVENT_BLOOM: + // TODO : Add missing text + DoCastAOE(SPELL_SUMMON_SPORE, true); + DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM,H_SPELL_DEATHBLOOM)); + events.ScheduleEvent(EVENT_BLOOM, 30000); + break; + case EVENT_DOOM: + DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM,H_SPELL_INEVITABLE_DOOM)); + events.ScheduleEvent(EVENT_DOOM, events.GetTimer() < 5*60000 ? 30000 : 15000); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_loatheb(Creature* pCreature) +{ + return new boss_loathebAI (pCreature); +} + +enum SporeSpells +{ + SPELL_FUNGAL_CREEP = 29232 +}; + +struct mob_loatheb_sporeAI : public ScriptedAI +{ + mob_loatheb_sporeAI(Creature *c) : ScriptedAI(c) {} + + void JustDied(Unit* killer) + { + DoCast(killer, SPELL_FUNGAL_CREEP); + } +}; + +CreatureAI* GetAI_mob_loatheb_spore(Creature* pCreature) +{ + return new mob_loatheb_sporeAI (pCreature); +} + +void AddSC_boss_loatheb() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_loatheb"; + newscript->GetAI = &GetAI_boss_loatheb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_loatheb_spore"; + newscript->GetAI = &GetAI_mob_loatheb_spore; + newscript->RegisterSelf(); + + // Fungal Creep + //GetAISpellInfo(29232)->condition = AICOND_DIE; +} + diff --git a/src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp new file mode 100644 index 00000000000..71d9cb86102 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Spells +{ + SPELL_WEB_WRAP = 28622, + SPELL_WEB_SPRAY_10 = 29484, + SPELL_WEB_SPRAY_25 = 54125, + SPELL_POISON_SHOCK_10 = 28741, + SPELL_POISON_SHOCK_25 = 54122, + SPELL_NECROTIC_POISON_10 = 28776, + SPELL_NECROTIC_POISON_25 = 54121, + SPELL_FRENZY_10 = 54123, + SPELL_FRENZY_25 = 54124, +}; + +enum Creatures +{ + MOB_WEB_WRAP = 16486, + MOB_SPIDERLING = 17055, +}; + +#define MAX_POS_WRAP 3 +const Position PosWrap[MAX_POS_WRAP] = +{ + {3546.796, -3869.082, 296.450, 0.0}, + {3531.271, -3847.424, 299.450, 0.0}, + {3497.067, -3843.384, 302.384, 0.0}, +}; + +enum Events +{ + EVENT_NONE, + EVENT_SPRAY, + EVENT_SHOCK, + EVENT_POISON, + EVENT_WRAP, + EVENT_SUMMON, + EVENT_FRENZY, +}; + +struct boss_maexxnaAI : public BossAI +{ + boss_maexxnaAI(Creature *c) : BossAI(c, BOSS_MAEXXNA) {} + + bool enraged; + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + enraged = false; + events.ScheduleEvent(EVENT_WRAP, 20000); + events.ScheduleEvent(EVENT_SPRAY, 40000); + events.ScheduleEvent(EVENT_SHOCK, urand(5000,10000)); + events.ScheduleEvent(EVENT_POISON, urand(10000,15000)); + events.ScheduleEvent(EVENT_SUMMON, 30000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || !CheckInRoom()) + return; + + if (!enraged && HealthBelowPct(30)) + { + enraged = true; + events.ScheduleEvent(EVENT_FRENZY, 0); // will be cast immediately + } + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_WRAP: + // TODO : Add missing text + for (uint8 i = 0; i < RAID_MODE(1,2); ++i) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP)) + { + pTarget->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25)); + uint8 pos = rand()%MAX_POS_WRAP; + pTarget->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20); + if (Creature *wrap = DoSummon(MOB_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN)) + wrap->AI()->SetGUID(pTarget->GetGUID()); + } + } + events.ScheduleEvent(EVENT_WRAP, 40000); + break; + case EVENT_SPRAY: + DoCastAOE(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25)); + events.ScheduleEvent(EVENT_SPRAY, 40000); + break; + case EVENT_SHOCK: + DoCastAOE(RAID_MODE(SPELL_POISON_SHOCK_10,SPELL_POISON_SHOCK_25)); + events.ScheduleEvent(EVENT_SHOCK, urand(10000,20000)); + break; + case EVENT_POISON: + DoCast(me->getVictim(), RAID_MODE(SPELL_NECROTIC_POISON_10,SPELL_NECROTIC_POISON_25)); + events.ScheduleEvent(EVENT_POISON, urand(10000, 20000)); + break; + case EVENT_FRENZY: + DoCast(me, RAID_MODE(SPELL_FRENZY_10,SPELL_FRENZY_25), true); + events.ScheduleEvent(EVENT_FRENZY, 600000); + break; + case EVENT_SUMMON: + // TODO : Add missing text + uint8 amount = urand(8,10); + for (uint8 i = 0; i < amount; ++i) + DoSummon(MOB_SPIDERLING, me, 0, TEMPSUMMON_CORPSE_DESPAWN); + events.ScheduleEvent(EVENT_SUMMON, 40000); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_webwrapAI : public NullCreatureAI +{ + mob_webwrapAI(Creature *c) : NullCreatureAI(c), victimGUID(0) {} + + uint64 victimGUID; + + void SetGUID(const uint64 &guid, int32 /*param*/) + { + victimGUID = guid; + if (me->m_spells[0] && victimGUID) + if (Unit *victim = Unit::GetUnit(*me, victimGUID)) + victim->CastSpell(victim, me->m_spells[0], true, NULL, NULL, me->GetGUID()); + } + + void JustDied(Unit * /*killer*/) + { + if (me->m_spells[0] && victimGUID) + if (Unit *victim = Unit::GetUnit(*me, victimGUID)) + victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID()); + } +}; + +CreatureAI* GetAI_boss_maexxna(Creature* pCreature) +{ + return new boss_maexxnaAI (pCreature); +} + +CreatureAI* GetAI_mob_webwrap(Creature* pCreature) +{ + return new mob_webwrapAI (pCreature); +} + +void AddSC_boss_maexxna() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_maexxna"; + newscript->GetAI = &GetAI_boss_maexxna; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_webwrap"; + newscript->GetAI = &GetAI_mob_webwrap; + newscript->RegisterSelf(); + +} + diff --git a/src/server/scripts/Northrend/naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/naxxramas/boss_noth.cpp new file mode 100644 index 00000000000..b0cd4018955 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_noth.cpp @@ -0,0 +1,212 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SAY_AGGRO RAND(-1533075,-1533076,-1533077) +#define SAY_SUMMON -1533078 +#define SAY_SLAY RAND(-1533079,-1533080) +#define SAY_DEATH -1533081 + +#define SOUND_DEATH 8848 + +#define SPELL_CURSE_PLAGUEBRINGER RAID_MODE(29213,54835) +#define SPELL_BLINK RAND(29208,29209,29210,29211) +#define SPELL_CRIPPLE RAID_MODE(29212,54814) +#define SPELL_TELEPORT 29216 + +#define MOB_WARRIOR 16984 +#define MOB_CHAMPION 16983 +#define MOB_GUARDIAN 16981 + +// Teleport position of Noth on his balcony +#define TELE_X 2631.370 +#define TELE_Y -3529.680 +#define TELE_Z 274.040 +#define TELE_O 6.277 + +#define MAX_SUMMON_POS 5 + +const float SummonPos[MAX_SUMMON_POS][4] = +{ + {2728.12, -3544.43, 261.91, 6.04}, + {2729.05, -3544.47, 261.91, 5.58}, + {2728.24, -3465.08, 264.20, 3.56}, + {2704.11, -3456.81, 265.53, 4.51}, + {2663.56, -3464.43, 262.66, 5.20}, +}; + +enum Events +{ + EVENT_NONE, + EVENT_BERSERK, + EVENT_CURSE, + EVENT_BLINK, + EVENT_WARRIOR, + EVENT_BALCONY, + EVENT_WAVE, + EVENT_GROUND, +}; + +struct boss_nothAI : public BossAI +{ + boss_nothAI(Creature *c) : BossAI(c, BOSS_NOTH) {} + + uint32 waveCount, balconyCount; + + void Reset() + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + _Reset(); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO, me); + balconyCount = 0; + EnterPhaseGround(); + } + + void EnterPhaseGround() + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoZoneInCombat(); + if (me->getThreatManager().isThreatListEmpty()) + EnterEvadeMode(); + else + { + events.ScheduleEvent(EVENT_BALCONY, 110000); + events.ScheduleEvent(EVENT_CURSE, 10000+rand()%15000); + events.ScheduleEvent(EVENT_WARRIOR, 30000); + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + events.ScheduleEvent(EVENT_BLINK, 20000 + rand()%20000); + } + } + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_SLAY, me); + } + + void JustSummoned(Creature *summon) + { + summons.Summon(summon); + summon->setActive(true); + summon->AI()->DoZoneInCombat(); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + } + + void SummonUndead(uint32 entry, uint32 num) + { + for (uint32 i = 0; i < num; ++i) + { + uint32 pos = rand()%MAX_SUMMON_POS; + me->SummonCreature(entry, SummonPos[pos][0], SummonPos[pos][1], SummonPos[pos][2], + SummonPos[pos][3], TEMPSUMMON_CORPSE_DESPAWN, 60000); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateCombatState() || !CheckInRoom()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CURSE: + DoCastAOE(SPELL_CURSE_PLAGUEBRINGER); + events.ScheduleEvent(EVENT_CURSE, 50000 + rand()%10000); + return; + case EVENT_WARRIOR: + DoScriptText(SAY_SUMMON, me); + SummonUndead(MOB_WARRIOR, RAID_MODE(2,3)); + events.ScheduleEvent(EVENT_WARRIOR, 30000); + return; + case EVENT_BLINK: + DoCastAOE(SPELL_CRIPPLE, true); + DoCastAOE(SPELL_BLINK); + DoResetThreat(); + events.ScheduleEvent(EVENT_BLINK, 40000); + return; + case EVENT_BALCONY: + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->AttackStop(); + me->RemoveAllAuras(); + me->NearTeleportTo(TELE_X, TELE_Y, TELE_Z, TELE_O); + events.Reset(); + events.ScheduleEvent(EVENT_WAVE, 2000 + rand()%3000); + waveCount = 0; + return; + case EVENT_WAVE: + DoScriptText(SAY_SUMMON, me); + switch(balconyCount) + { + case 0: SummonUndead(MOB_CHAMPION, RAID_MODE(2,4)); break; + case 1: SummonUndead(MOB_CHAMPION, RAID_MODE(1,2)); + SummonUndead(MOB_GUARDIAN, RAID_MODE(1,2)); break; + case 2: SummonUndead(MOB_GUARDIAN, RAID_MODE(2,4)); break; + default:SummonUndead(MOB_CHAMPION, RAID_MODE(5,10)); + SummonUndead(MOB_GUARDIAN, RAID_MODE(5,10));break; + } + ++waveCount; + events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, 30000 + rand()%15000); + return; + case EVENT_GROUND: + { + ++balconyCount; + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + me->NearTeleportTo(x, y, z, o); + events.ScheduleEvent(EVENT_BALCONY, 110000); + EnterPhaseGround(); + return; + } + } + } + + if (me->HasReactState(REACT_AGGRESSIVE)) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_noth(Creature* pCreature) +{ + return new boss_nothAI (pCreature); +} + +void AddSC_boss_noth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_noth"; + newscript->GetAI = &GetAI_boss_noth; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp new file mode 100644 index 00000000000..e4472b299ce --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp @@ -0,0 +1,159 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Spells +{ + SPELL_HATEFUL_STRIKE = 41926, + H_SPELL_HATEFUL_STRIKE = 59192, + SPELL_FRENZY = 28131, + SPELL_BERSERK = 26662, + SPELL_SLIME_BOLT = 32309, +}; + +enum Yells +{ + SAY_AGGRO_1 = -1533017, + SAY_AGGRO_2 = -1533018, + SAY_SLAY = -1533019, + SAY_DEATH = -1533020, + EMOTE_BERSERK = -1533021, + EMOTE_ENRAGE = -1533022, +}; + +enum Events +{ + EVENT_NONE, + EVENT_BERSERK, + EVENT_HATEFUL, + EVENT_SLIME +}; + +enum +{ + ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT = 10286, +}; + +struct boss_patchwerkAI : public BossAI +{ + boss_patchwerkAI(Creature *c) : BossAI(c, BOSS_PATCHWERK) {} + + bool Enraged; + + void Reset() + { + _Reset(); + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); + } + + void KilledUnit(Unit* /*Victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_SLAY, me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + Enraged = false; + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me); + events.ScheduleEvent(EVENT_HATEFUL, 1200); + events.ScheduleEvent(EVENT_BERSERK, 360000); + + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_HATEFUL: + { + //Cast Hateful strike on the player with the highest + //amount of HP within melee distance + uint32 MostHP = 0; + Unit* pMostHPTarget = NULL; + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit *pTarget = (*i)->getTarget(); + if (pTarget->isAlive() && pTarget->GetHealth() > MostHP && me->IsWithinMeleeRange(pTarget)) + { + MostHP = pTarget->GetHealth(); + pMostHPTarget = pTarget; + } + } + + if (pMostHPTarget) + DoCast(pMostHPTarget, RAID_MODE(SPELL_HATEFUL_STRIKE,H_SPELL_HATEFUL_STRIKE), true); + + events.ScheduleEvent(EVENT_HATEFUL, 1200); + break; + } + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK, true); + DoScriptText(EMOTE_BERSERK, me); + events.ScheduleEvent(EVENT_SLIME, 2000); + break; + case EVENT_SLIME: + DoCast(me->getVictim(), SPELL_SLIME_BOLT); + events.ScheduleEvent(EVENT_SLIME, 2000); + break; + } + } + + if (!Enraged && HealthBelowPct(5)) + { + DoCast(me, SPELL_FRENZY, true); + DoScriptText(EMOTE_ENRAGE, me); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_patchwerk(Creature* pCreature) +{ + return new boss_patchwerkAI (pCreature); +} + +void AddSC_boss_patchwerk() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_patchwerk"; + newscript->GetAI = &GetAI_boss_patchwerk; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp new file mode 100644 index 00000000000..d507df86e83 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +//Razuvious - NO TEXT sound only +//8852 aggro01 - Hah hah, I'm just getting warmed up! +//8853 aggro02 Stand and fight! +//8854 aggro03 Show me what you've got! +//8861 slay1 - You should've stayed home! +//8863 slay2- +//8858 cmmnd3 - You disappoint me, students! +//8855 cmmnd1 - Do as I taught you! +//8856 cmmnd2 - Show them no mercy! +//8859 cmmnd4 - The time for practice is over! Show me what you've learned! +//8861 Sweep the leg! Do you have a problem with that? +//8860 death - An honorable... death... +//8947 - Aggro Mixed? - ? + +#define SOUND_AGGRO RAND(8852,8853,8854) +#define SOUND_SLAY RAND(8861,8863) +#define SOUND_COMMND RAND(8855,8856,8858,8859,8861) +#define SOUND_DEATH 8860 +#define SOUND_AGGROMIX 8847 + +#define SPELL_UNBALANCING_STRIKE 26613 +#define SPELL_DISRUPTING_SHOUT RAID_MODE(29107,55543) +#define SPELL_JAGGED_KNIFE 55550 +#define SPELL_HOPELESS 29125 + +enum Events +{ + EVENT_NONE, + EVENT_STRIKE, + EVENT_SHOUT, + EVENT_KNIFE, + EVENT_COMMAND, +}; + +struct boss_razuviousAI : public BossAI +{ + boss_razuviousAI(Creature *c) : BossAI(c, BOSS_RAZUVIOUS) {} + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%3)) + DoPlaySoundToSet(me, SOUND_SLAY); + } + + void DamageTaken(Unit* pDone_by, uint32& uiDamage) + { + // Damage done by the controlled Death Knight understudies should also count toward damage done by players + if (pDone_by->GetTypeId() == TYPEID_UNIT && (pDone_by->GetEntry() == 16803 || pDone_by->GetEntry() == 29941)) + { + me->LowerPlayerDamageReq(uiDamage); + } + } + + void JustDied(Unit* /*killer*/) + { + _JustDied(); + DoPlaySoundToSet(me, SOUND_DEATH); + me->CastSpell(me, SPELL_HOPELESS, true); // TODO: this may affect other creatures + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoPlaySoundToSet(me, SOUND_AGGRO); + events.ScheduleEvent(EVENT_STRIKE, 30000); + events.ScheduleEvent(EVENT_SHOUT, 25000); + events.ScheduleEvent(EVENT_COMMAND, 40000); + events.ScheduleEvent(EVENT_KNIFE, 10000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_STRIKE: + DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE); + events.ScheduleEvent(EVENT_STRIKE, 30000); + return; + case EVENT_SHOUT: + DoCastAOE(SPELL_DISRUPTING_SHOUT); + events.ScheduleEvent(EVENT_SHOUT, 25000); + return; + case EVENT_KNIFE: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) + DoCast(pTarget, SPELL_JAGGED_KNIFE); + events.ScheduleEvent(EVENT_KNIFE, 10000); + return; + case EVENT_COMMAND: + DoPlaySoundToSet(me, SOUND_COMMND); + events.ScheduleEvent(EVENT_COMMAND, 40000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_razuvious(Creature* pCreature) +{ + return new boss_razuviousAI (pCreature); +} + +void AddSC_boss_razuvious() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_razuvious"; + newscript->GetAI = &GetAI_boss_razuvious; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp new file mode 100644 index 00000000000..d75b3ab78b0 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define EMOTE_BREATH -1533082 +#define EMOTE_ENRAGE -1533083 + +#define SPELL_FROST_AURA RAID_MODE(28531,55799) +#define SPELL_CLEAVE 19983 +#define SPELL_TAIL_SWEEP RAID_MODE(55697,55696) +#define SPELL_SUMMON_BLIZZARD 28560 +#define SPELL_LIFE_DRAIN RAID_MODE(28542,55665) +#define SPELL_ICEBOLT 28522 +#define SPELL_FROST_BREATH 29318 +#define SPELL_FROST_EXPLOSION 28524 +#define SPELL_FROST_MISSILE 30101 +#define SPELL_BERSERK 26662 +#define SPELL_DIES 29357 + +#define SPELL_CHILL RAID_MODE(28547,55699) + +#define MOB_BLIZZARD 16474 +#define GO_ICEBLOCK 181247 + +#define ACHIEVEMENT_THE_HUNDRED_CLUB RAID_MODE(2146, 2147) +#define MAX_FROST_RESISTANCE 100 + +enum Phases +{ + PHASE_NULL = 0, + PHASE_BIRTH, + PHASE_GROUND, + PHASE_FLIGHT, +}; + +enum Events +{ + EVENT_NONE, + EVENT_BERSERK, + EVENT_CLEAVE, + EVENT_TAIL, + EVENT_DRAIN, + EVENT_BLIZZARD, + EVENT_FLIGHT, + EVENT_LIFTOFF, + EVENT_ICEBOLT, + EVENT_BREATH, + EVENT_EXPLOSION, + EVENT_LAND, + EVENT_GROUND, + EVENT_BIRTH, +}; + +typedef std::map IceBlockMap; + +struct boss_sapphironAI : public BossAI +{ + boss_sapphironAI(Creature* c) : BossAI(c, BOSS_SAPPHIRON) + , phase(PHASE_NULL) + { + pMap = me->GetMap(); + } + + Phases phase; + uint32 iceboltCount; + IceBlockMap iceblocks; + + bool CanTheHundredClub; // needed for achievement: The Hundred Club(2146, 2147) + uint32 CheckFrostResistTimer; + Map* pMap; + + void InitializeAI() + { + float x, y, z; + me->GetPosition(x, y, z); + me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + + ScriptedAI::InitializeAI(); + } + + void Reset() + { + _Reset(); + + if (phase == PHASE_FLIGHT) + ClearIceBlock(); + + phase = PHASE_NULL; + + CanTheHundredClub = true; + CheckFrostResistTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + + me->CastSpell(me, SPELL_FROST_AURA, true); + + events.ScheduleEvent(EVENT_BERSERK, 15*60000); + EnterPhaseGround(); + + CheckPlayersFrostResist(); + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (spell->Id == SPELL_ICEBOLT) + { + IceBlockMap::iterator itr = iceblocks.find(pTarget->GetGUID()); + if (itr != iceblocks.end() && !itr->second) + { + if (GameObject *iceblock = me->SummonGameObject(GO_ICEBLOCK, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, 0, 0, 0, 0, 25000)) + itr->second = iceblock->GetGUID(); + } + } + } + + void JustDied(Unit* /*who*/) + { + _JustDied(); + me->CastSpell(me, SPELL_DIES, true); + + CheckPlayersFrostResist(); + if (CanTheHundredClub) + { + AchievementEntry const *AchievTheHundredClub = GetAchievementStore()->LookupEntry(ACHIEVEMENT_THE_HUNDRED_CLUB); + if (AchievTheHundredClub) + { + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievTheHundredClub); + } + } + } + } + + void MovementInform(uint32, uint32 id) + { + if (id == 1) + events.ScheduleEvent(EVENT_LIFTOFF, 0); + } + + void DoAction(const int32 param) + { + if (param == DATA_SAPPHIRON_BIRTH) + { + phase = PHASE_BIRTH; + events.ScheduleEvent(EVENT_BIRTH, 23000); + } + } + + void CheckPlayersFrostResist() + { + if (CanTheHundredClub && pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (itr->getSource()->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE) + { + CanTheHundredClub = false; + break; + } + } + } + } + + void EnterPhaseGround() + { + phase = PHASE_GROUND; + me->SetReactState(REACT_AGGRESSIVE); + events.SetPhase(PHASE_GROUND); + events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_BLIZZARD, 5000+rand()%5000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_FLIGHT, 45000); + } + + void ClearIceBlock() + { + for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr) + { + if (Player* pPlayer = Unit::GetPlayer(itr->first)) + pPlayer->RemoveAura(SPELL_ICEBOLT); + if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second)) + pGo->Delete(); + } + iceblocks.clear(); + } + + void UpdateAI(const uint32 diff) + { + if (!phase) + return; + + events.Update(diff); + + if (phase != PHASE_BIRTH && !UpdateCombatState() || !CheckInRoom()) + return; + + if (CanTheHundredClub) + { + if (CheckFrostResistTimer <= diff) + { + CheckPlayersFrostResist(); + CheckFrostResistTimer = (rand() % 5 + 5) * 1000; + } else CheckFrostResistTimer -= diff; + } + + if (phase == PHASE_GROUND) + { + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BERSERK: + DoScriptText(EMOTE_ENRAGE, me); + DoCast(me, SPELL_BERSERK); + return; + case EVENT_CLEAVE: + DoCast(me->getVictim(), SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); + return; + case EVENT_TAIL: + DoCastAOE(SPELL_TAIL_SWEEP); + events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); + return; + case EVENT_DRAIN: + DoCastAOE(SPELL_LIFE_DRAIN); + events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); + return; + case EVENT_BLIZZARD: + { + //DoCastAOE(SPELL_SUMMON_BLIZZARD); + if (Creature *pSummon = DoSummon(MOB_BLIZZARD, me, 0.0f, urand(25000,30000), TEMPSUMMON_TIMED_DESPAWN)) + pSummon->GetMotionMaster()->MoveRandom(40); + events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20000,7000), 0, PHASE_GROUND); + break; + } + case EVENT_FLIGHT: + phase = PHASE_FLIGHT; + events.SetPhase(PHASE_FLIGHT); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + me->GetMotionMaster()->MovePoint(1, x, y, z); + return; + } + } + + DoMeleeAttackIfReady(); + } + else + { + if (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_LIFTOFF: + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMovementFlagUpdate(); + events.ScheduleEvent(EVENT_ICEBOLT, 1500); + iceboltCount = RAID_MODE(2,3); + return; + case EVENT_ICEBOLT: + { + std::vector targets; + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT)) + targets.push_back((*i)->getTarget()); + + if (targets.empty()) + iceboltCount = 0; + else + { + std::vector::const_iterator itr = targets.begin(); + advance(itr, rand()%targets.size()); + iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0)); + DoCast(*itr, SPELL_ICEBOLT); + --iceboltCount; + } + + if (iceboltCount) + events.ScheduleEvent(EVENT_ICEBOLT, 1000); + else + events.ScheduleEvent(EVENT_BREATH, 1000); + return; + } + case EVENT_BREATH: + { + DoScriptText(EMOTE_BREATH, me); + DoCastAOE(SPELL_FROST_MISSILE); + events.ScheduleEvent(EVENT_EXPLOSION, 8000); + return; + } + case EVENT_EXPLOSION: + CastExplosion(); + ClearIceBlock(); + events.ScheduleEvent(EVENT_LAND, 3000); + return; + case EVENT_LAND: + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMovementFlagUpdate(); + events.ScheduleEvent(EVENT_GROUND, 1500); + return; + case EVENT_GROUND: + EnterPhaseGround(); + return; + case EVENT_BIRTH: + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + return; + } + }//if (uint32 eventId = events.ExecuteEvent()) + }//if (phase == PHASE_GROUND) + } + + void CastExplosion() + { + DoZoneInCombat(); // make sure everyone is in threatlist + std::vector targets; + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit *pTarget = (*i)->getTarget(); + if (pTarget->GetTypeId() != TYPEID_PLAYER) + continue; + + if (pTarget->HasAura(SPELL_ICEBOLT)) + { + pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); + targets.push_back(pTarget); + continue; + } + + for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr) + { + if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second)) + { + if (pGo->IsInBetween(me, pTarget, 2.0f) + && me->GetExactDist2d(pTarget->GetPositionX(), pTarget->GetPositionY()) - me->GetExactDist2d(pGo->GetPositionX(), pGo->GetPositionY()) < 5.0f) + { + pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); + targets.push_back(pTarget); + break; + } + } + } + } + + me->CastSpell(me, SPELL_FROST_EXPLOSION, true); + + for (std::vector::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + (*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false); + } +}; + +CreatureAI* GetAI_boss_sapphiron(Creature* pCreature) +{ + return new boss_sapphironAI (pCreature); +} + +void AddSC_boss_sapphiron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_sapphiron"; + newscript->GetAI = &GetAI_boss_sapphiron; + newscript->RegisterSelf(); + + // Chill + GetAISpellInfo(28547)->cooldown = 1000; + GetAISpellInfo(55699)->cooldown = 1000; +} diff --git a/src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp new file mode 100644 index 00000000000..350cd450510 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2008 - 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +//Stalagg +enum StalaggYells +{ + SAY_STAL_AGGRO = -1533023, //not used + SAY_STAL_SLAY = -1533024, //not used + SAY_STAL_DEATH = -1533025 //not used +}; + +enum StalagSpells +{ + SPELL_POWERSURGE = 28134, + H_SPELL_POWERSURGE = 54529, + SPELL_MAGNETIC_PULL = 28338, + SPELL_STALAGG_TESLA = 28097 +}; + +//Feugen +enum FeugenYells +{ + SAY_FEUG_AGGRO = -1533026, //not used + SAY_FEUG_SLAY = -1533027, //not used + SAY_FEUG_DEATH = -1533028 //not used +}; + +enum FeugenSpells +{ + SPELL_STATICFIELD = 28135, + H_SPELL_STATICFIELD = 54528, + SPELL_FEUGEN_TESLA = 28109 +}; + +// Thaddius DoAction +enum ThaddiusActions +{ + ACTION_FEUGEN_RESET, + ACTION_FEUGEN_DIED, + ACTION_STALAGG_RESET, + ACTION_STALAGG_DIED +}; + +//generic +#define C_TESLA_COIL 16218 //the coils (emotes "Tesla Coil overloads!") + +//Thaddius +enum ThaddiusYells +{ + SAY_GREET = -1533029, //not used + SAY_AGGRO_1 = -1533030, + SAY_AGGRO_2 = -1533031, + SAY_AGGRO_3 = -1533032, + SAY_SLAY = -1533033, + SAY_ELECT = -1533034, //not used + SAY_DEATH = -1533035, + SAY_SCREAM1 = -1533036, //not used + SAY_SCREAM2 = -1533037, //not used + SAY_SCREAM3 = -1533038, //not used + SAY_SCREAM4 = -1533039 //not used +}; + +enum ThaddiusSpells +{ + SPELL_POLARITY_SHIFT = 28089, + SPELL_BALL_LIGHTNING = 28299, + SPELL_CHAIN_LIGHTNING = 28167, + H_SPELL_CHAIN_LIGHTNING = 54531, + SPELL_BERSERK = 27680 +}; + +enum Events +{ + EVENT_NONE, + EVENT_SHIFT, + EVENT_CHAIN, + EVENT_BERSERK, +}; + +struct boss_thaddiusAI : public BossAI +{ + boss_thaddiusAI(Creature *c) : BossAI(c, BOSS_THADDIUS) + { + // init is a bit tricky because thaddius shall track the life of both adds, but not if there was a wipe + // and, in particular, if there was a crash after both adds were killed (should not respawn) + + // Moreover, the adds may not yet be spawn. So just track down the status if mob is spawn + // and each mob will send its status at reset (meaning that it is alive) + checkFeugenAlive = false; + if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN))) + checkFeugenAlive = pFeugen->isAlive(); + + checkStalaggAlive = false; + if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG))) + checkStalaggAlive = pStalagg->isAlive(); + + if (!checkFeugenAlive && !checkStalaggAlive) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + me->SetReactState(REACT_AGGRESSIVE); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + me->SetReactState(REACT_PASSIVE); + } + } + + bool checkStalaggAlive; + bool checkFeugenAlive; + uint32 uiAddsTimer; + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_SLAY, me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + } + + void DoAction(const int32 action) + { + switch(action) + { + case ACTION_FEUGEN_RESET: + checkFeugenAlive = true; + break; + case ACTION_FEUGEN_DIED: + checkFeugenAlive = false; + break; + case ACTION_STALAGG_RESET: + checkStalaggAlive = true; + break; + case ACTION_STALAGG_DIED: + checkStalaggAlive = false; + break; + } + + if (!checkFeugenAlive && !checkStalaggAlive) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + // REACT_AGGRESSIVE only reset when he takes damage. + DoZoneInCombat(); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + me->SetReactState(REACT_PASSIVE); + } + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + events.ScheduleEvent(EVENT_SHIFT, 30000); + events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000)); + events.ScheduleEvent(EVENT_BERSERK, 360000); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 & /*uiDamage*/) + { + me->SetReactState(REACT_AGGRESSIVE); + } + + void UpdateAI(const uint32 diff) + { + if (checkFeugenAlive && checkStalaggAlive) + uiAddsTimer = 0; + + if (checkStalaggAlive != checkFeugenAlive) + { + uiAddsTimer += diff; + if (uiAddsTimer > 5000) + { + if (!checkStalaggAlive) + { + if (instance) + if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG))) + pStalagg->Respawn(); + } + else + { + if (instance) + if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN))) + pFeugen->Respawn(); + } + } + } + + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHIFT: + DoCastAOE(SPELL_POLARITY_SHIFT); + events.ScheduleEvent(EVENT_SHIFT, 30000); + return; + case EVENT_CHAIN: + DoCast(me->getVictim(), RAID_MODE(SPELL_CHAIN_LIGHTNING, H_SPELL_CHAIN_LIGHTNING)); + events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000)); + return; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + return; + } + } + + if (events.GetTimer() > 15000 && !me->IsWithinMeleeRange(me->getVictim())) + DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); + else + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thaddius(Creature* pCreature) +{ + return new boss_thaddiusAI (pCreature); +} + +struct mob_stalaggAI : public ScriptedAI +{ + mob_stalaggAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 powerSurgeTimer; + uint32 magneticPullTimer; + + void Reset() + { + if (pInstance) + if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) + if (pThaddius->AI()) + pThaddius->AI()->DoAction(ACTION_STALAGG_RESET); + powerSurgeTimer = urand(20000,25000); + magneticPullTimer = 20000; + } + + void EnterCombat(Unit * /*pWho*/) + { + DoCast(SPELL_STALAGG_TESLA); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) + if (pThaddius->AI()) + pThaddius->AI()->DoAction(ACTION_STALAGG_DIED); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (magneticPullTimer <= uiDiff) + { + if (Creature *pFeugen = me->GetCreature(*me, pInstance->GetData64(DATA_FEUGEN))) + { + Unit* pStalaggVictim = me->getVictim(); + Unit* pFeugenVictim = pFeugen->getVictim(); + + if (pFeugenVictim && pStalaggVictim) + { + // magnetic pull is not working. So just jump. + + // reset aggro to be sure that feugen will not follow the jump + pFeugen->getThreatManager().modifyThreatPercent(pFeugenVictim, -100); + pFeugenVictim->JumpTo(me, 0.3f); + + me->getThreatManager().modifyThreatPercent(pStalaggVictim, -100); + pStalaggVictim->JumpTo(pFeugen, 0.3f); + } + } + + magneticPullTimer = 20000; + } + else magneticPullTimer -= uiDiff; + + if (powerSurgeTimer <= uiDiff) + { + DoCast(me, RAID_MODE(SPELL_POWERSURGE, H_SPELL_POWERSURGE)); + powerSurgeTimer = urand(15000,20000); + } else powerSurgeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_stalagg(Creature* pCreature) +{ + return new mob_stalaggAI(pCreature); +} + +struct mob_feugenAI : public ScriptedAI +{ + mob_feugenAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 staticFieldTimer; + + void Reset() + { + if (pInstance) + if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) + if (pThaddius->AI()) + pThaddius->AI()->DoAction(ACTION_FEUGEN_RESET); + staticFieldTimer = 5000; + } + + void EnterCombat(Unit * /*pWho*/) + { + DoCast(SPELL_FEUGEN_TESLA); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) + if (pThaddius->AI()) + pThaddius->AI()->DoAction(ACTION_FEUGEN_DIED); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (staticFieldTimer <= uiDiff) + { + DoCast(me, RAID_MODE(SPELL_STATICFIELD, H_SPELL_STATICFIELD)); + staticFieldTimer = 5000; + } else staticFieldTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_feugen(Creature* pCreature) +{ + return new mob_feugenAI(pCreature); +} + +void AddSC_boss_thaddius() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_thaddius"; + newscript->GetAI = &GetAI_boss_thaddius; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stalagg"; + newscript->GetAI = &GetAI_mob_stalagg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_feugen"; + newscript->GetAI = &GetAI_mob_feugen; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp new file mode 100644 index 00000000000..706789a73f1 --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp @@ -0,0 +1,324 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +const DoorData doorData[] = +{ + {181126, BOSS_ANUBREKHAN,DOOR_TYPE_ROOM, BOUNDARY_S}, + {181195, BOSS_ANUBREKHAN,DOOR_TYPE_PASSAGE, 0}, + {194022, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0}, + {181209, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0}, + {181209, BOSS_MAEXXNA, DOOR_TYPE_ROOM, BOUNDARY_SW}, + {181200, BOSS_NOTH, DOOR_TYPE_ROOM, BOUNDARY_N}, + {181201, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_E}, + {181202, BOSS_NOTH, DOOR_TYPE_PASSAGE, 0}, + {181202, BOSS_HEIGAN, DOOR_TYPE_ROOM, BOUNDARY_N}, + {181203, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_E}, + {181241, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, 0}, + {181241, BOSS_LOATHEB, DOOR_TYPE_ROOM, BOUNDARY_W}, + {181123, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE, 0}, + {181123, BOSS_GROBBULUS, DOOR_TYPE_ROOM, 0}, + {181120, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NW}, + {181121, BOSS_GLUTH, DOOR_TYPE_PASSAGE, 0}, + {181121, BOSS_THADDIUS, DOOR_TYPE_ROOM, 0}, + {181124, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE, 0}, + {181124, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_N}, + {181125, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_S}, + {181119, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, 0}, + {181119, BOSS_HORSEMEN, DOOR_TYPE_ROOM, BOUNDARY_NE}, + {181225, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE, BOUNDARY_W}, + {181228, BOSS_KELTHUZAD, DOOR_TYPE_ROOM, BOUNDARY_S}, + {0, 0, DOOR_TYPE_ROOM, 0}, // EOF +}; + +const MinionData minionData[] = +{ + //{16573, BOSS_ANUBREKHAN}, there is no spawn point in db, so we do not add them here + {16506, BOSS_FAERLINA}, + {16803, BOSS_RAZUVIOUS}, + {16063, BOSS_HORSEMEN}, + {16064, BOSS_HORSEMEN}, + {16065, BOSS_HORSEMEN}, + {30549, BOSS_HORSEMEN}, + {0, 0,} +}; + +enum eEnums +{ + GO_HORSEMEN_CHEST_HERO = 193426, + GO_HORSEMEN_CHEST = 181366, //four horsemen event, DoRespawnGameObject() when event == DONE + GO_GOTHIK_GATE = 181170, + GO_KELTHUZAD_PORTAL01 = 181402, + GO_KELTHUZAD_PORTAL02 = 181403, + GO_KELTHUZAD_PORTAL03 = 181404, + GO_KELTHUZAD_PORTAL04 = 181405, + GO_KELTHUZAD_TRIGGER = 181444, + + SPELL_ERUPTION = 29371 +}; + +const float HeiganPos[2] = {2796, -3707}; +const float HeiganEruptionSlope[3] = +{ + (-3685 - HeiganPos[1]) /(2724 - HeiganPos[0]), + (-3647 - HeiganPos[1]) /(2749 - HeiganPos[0]), + (-3637 - HeiganPos[1]) /(2771 - HeiganPos[0]), +}; + +// 0 H x +// 1 ^ +// 2 | +// 3 y<--o +inline uint32 GetEruptionSection(float x, float y) +{ + y -= HeiganPos[1]; + if (y < 1.0f) + return 0; + + x -= HeiganPos[0]; + if (x > -1.0f) + return 3; + + float slope = y/x; + for (uint32 i = 0; i < 3; ++i) + if (slope > HeiganEruptionSlope[i]) + return i; + return 3; +} + +struct instance_naxxramas : public InstanceData +{ + instance_naxxramas(Map* pMap) : InstanceData(pMap) + { + SetBossNumber(MAX_BOSS_NUMBER); + LoadDoorData(doorData); + LoadMinionData(minionData); + } + + std::set HeiganEruptionGUID[4]; + uint64 GothikGateGUID; + uint64 HorsemenChestGUID; + uint64 SapphironGUID; + uint64 uiFaerlina; + uint64 uiThane; + uint64 uiLady; + uint64 uiBaron; + uint64 uiSir; + + uint64 uiThaddius; + uint64 uiFeugen; + uint64 uiStalagg; + + uint64 uiKelthuzad; + uint64 uiKelthuzadTrigger; + uint64 uiPortals[4]; + + time_t minHorsemenDiedTime; + time_t maxHorsemenDiedTime; + + void OnCreatureCreate(Creature* pCreature, bool add) + { + switch(pCreature->GetEntry()) + { + case 15989: SapphironGUID = add ? pCreature->GetGUID() : 0; return; + case 15953: uiFaerlina = pCreature->GetGUID(); return; + case 16064: uiThane = pCreature->GetGUID(); return; + case 16065: uiLady = pCreature->GetGUID(); return; + case 30549: uiBaron = pCreature->GetGUID(); return; + case 16063: uiSir = pCreature->GetGUID(); return; + case 15928: uiThaddius = pCreature->GetGUID(); return; + case 15930: uiFeugen = pCreature->GetGUID(); return; + case 15929: uiStalagg = pCreature->GetGUID(); return; + case 15990: uiKelthuzad = pCreature->GetGUID(); return; + } + + AddMinion(pCreature, add); + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (pGo->GetGOInfo()->displayId == 6785 || pGo->GetGOInfo()->displayId == 1287) + { + uint32 section = GetEruptionSection(pGo->GetPositionX(), pGo->GetPositionY()); + if (add) + HeiganEruptionGUID[section].insert(pGo->GetGUID()); + else + HeiganEruptionGUID[section].erase(pGo->GetGUID()); + return; + } + + switch(pGo->GetEntry()) + { + case GO_BIRTH: + if (!add && SapphironGUID) + { + if (Creature *pSapphiron = instance->GetCreature(SapphironGUID)) + pSapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH); + return; + } + case GO_GOTHIK_GATE: GothikGateGUID = add ? pGo->GetGUID() : 0; break; + case GO_HORSEMEN_CHEST: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break; + case GO_HORSEMEN_CHEST_HERO: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break; + case GO_KELTHUZAD_PORTAL01: uiPortals[0] = pGo->GetGUID(); break; + case GO_KELTHUZAD_PORTAL02: uiPortals[1] = pGo->GetGUID(); break; + case GO_KELTHUZAD_PORTAL03: uiPortals[2] = pGo->GetGUID(); break; + case GO_KELTHUZAD_PORTAL04: uiPortals[3] = pGo->GetGUID(); break; + case GO_KELTHUZAD_TRIGGER: uiKelthuzadTrigger = pGo->GetGUID(); break; + } + + AddDoor(pGo, add); + } + + void SetData(uint32 id, uint32 value) + { + switch(id) + { + case DATA_HEIGAN_ERUPT: + HeiganErupt(value); + break; + case DATA_GOTHIK_GATE: + if (GameObject *pGothikGate = instance->GetGameObject(GothikGateGUID)) + pGothikGate->SetGoState(GOState(value)); + break; + + case DATA_HORSEMEN0: + case DATA_HORSEMEN1: + case DATA_HORSEMEN2: + case DATA_HORSEMEN3: + if (value == NOT_STARTED) + { + minHorsemenDiedTime = 0; + maxHorsemenDiedTime = 0; + } + else if (value == DONE) + { + time_t now = time(NULL); + + if (minHorsemenDiedTime == 0) + minHorsemenDiedTime = now; + + maxHorsemenDiedTime = now; + } + break; + } + } + + uint64 GetData64(uint32 id) + { + switch(id) + { + case DATA_FAERLINA: + return uiFaerlina; + case DATA_THANE: + return uiThane; + case DATA_LADY: + return uiLady; + case DATA_BARON: + return uiBaron; + case DATA_SIR: + return uiSir; + case DATA_THADDIUS: + return uiThaddius; + case DATA_FEUGEN: + return uiFeugen; + case DATA_STALAGG: + return uiStalagg; + case DATA_KELTHUZAD: + return uiKelthuzad; + case DATA_KELTHUZAD_PORTAL01: + return uiPortals[0]; + case DATA_KELTHUZAD_PORTAL02: + return uiPortals[1]; + case DATA_KELTHUZAD_PORTAL03: + return uiPortals[2]; + case DATA_KELTHUZAD_PORTAL04: + return uiPortals[3]; + case DATA_KELTHUZAD_TRIGGER: + return uiKelthuzadTrigger; + } + return 0; + } + + bool SetBossState(uint32 id, EncounterState state) + { + if (!InstanceData::SetBossState(id, state)) + return false; + + if (id == BOSS_HORSEMEN && state == DONE) + { + if (GameObject *pHorsemenChest = instance->GetGameObject(HorsemenChestGUID)) + pHorsemenChest->SetRespawnTime(pHorsemenChest->GetRespawnDelay()); + } + + return true; + } + + void HeiganErupt(uint32 section) + { + for (uint32 i = 0; i < 4; ++i) + { + if (i == section) + continue; + + for (std::set::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr) + { + if (GameObject *pHeiganEruption = instance->GetGameObject(*itr)) + { + pHeiganEruption->SendCustomAnim(); + pHeiganEruption->CastSpell(NULL, SPELL_ERUPTION); + } + } + } + } + + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/) + { + switch(criteria_id) + { + case 7600: // Criteria for achievement 2176: And They Would All Go Down Together 15sec of each other 10-man + if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) + return true; + return false; + case 7601: // Criteria for achievement 2177: And They Would All Go Down Together 15sec of each other 25-man + if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) + return true; + return false; + case 13233: // Criteria for achievement 2186: The Immortal (25-man) + // TODO. + break; + case 13237: // Criteria for achievement 2187: The Undying (10-man) + // TODO. + break; + } + return false; + } +}; + +InstanceData* GetInstanceData_instance_naxxramas(Map* pMap) +{ + return new instance_naxxramas(pMap); +} + +void AddSC_instance_naxxramas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_naxxramas"; + newscript->GetInstanceData = &GetInstanceData_instance_naxxramas; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/naxxramas/naxxramas.h b/src/server/scripts/Northrend/naxxramas/naxxramas.h new file mode 100644 index 00000000000..9b1fac2ff5b --- /dev/null +++ b/src/server/scripts/Northrend/naxxramas/naxxramas.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008 - 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_NAXXRAMAS_H +#define DEF_NAXXRAMAS_H + +enum Encounter +{ + BOSS_ANUBREKHAN, + BOSS_FAERLINA, + BOSS_MAEXXNA, + BOSS_NOTH, + BOSS_HEIGAN, + BOSS_LOATHEB, + BOSS_PATCHWERK, + BOSS_GROBBULUS, + BOSS_GLUTH, + BOSS_THADDIUS, + BOSS_RAZUVIOUS, + BOSS_GOTHIK, + BOSS_HORSEMEN, + BOSS_SAPPHIRON, + BOSS_KELTHUZAD, + MAX_BOSS_NUMBER +}; + +enum Data +{ + DATA_HEIGAN_ERUPT, + DATA_GOTHIK_GATE, + DATA_SAPPHIRON_BIRTH, + + DATA_HORSEMEN0, + DATA_HORSEMEN1, + DATA_HORSEMEN2, + DATA_HORSEMEN3, +}; + +enum Data64 +{ + DATA_FAERLINA, + DATA_THANE, + DATA_LADY, + DATA_BARON, + DATA_SIR, + DATA_THADDIUS, + DATA_FEUGEN, + DATA_STALAGG, + DATA_KELTHUZAD, + DATA_KELTHUZAD_PORTAL01, + DATA_KELTHUZAD_PORTAL02, + DATA_KELTHUZAD_PORTAL03, + DATA_KELTHUZAD_PORTAL04, + DATA_KELTHUZAD_TRIGGER, +}; + +#define GO_BIRTH 181356 + +#endif + diff --git a/src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp b/src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp new file mode 100644 index 00000000000..bbb1df2731d --- /dev/null +++ b/src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp @@ -0,0 +1,175 @@ +/* Script Data Start +SDName: Boss malygos +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +//Spells +#define SPELL_ARCANE_BREATH_N 56272 +#define SPELL_ARCANE_BREATH_H 60072 +#define SPELL_ARCANE_PULSE 57432 +#define SPELL_ARCANE_STORM_1 57459 +#define SPELL_ARCANE_STORM_2 61693 +#define SPELL_ARCANE_STORM_3 61694 +#define SPELL_STATIC_FIELD 57430 +#define SPELL_SURGE_OF_POWER_1 56505 +#define SPELL_SURGE_OF_POWER_2 57407 +#define SPELL_SURGE_OF_POWER_3 60936 +#define SPELL_VORTEX 56105 + +//Dragon "mounts" spells in Phase3 +//they use Rugelike energy +#define SPELL_DMOUNT_FLAME_SPIKE 56091 //maybe not accurate +#define SPELL_DMOUNT_ENGULF_IN_FLAMES 61621 +#define SPELL_DMOUNT_REVIVIFY 57090 +#define SPELL_DMOUNT_LIFE_BURST 57143 +#define SPELL_DMOUNT_FLAME_SHIELD 57108 +//#define SPELL_DMOUNT_UNKNOWN XYZ //Increases your drake's flight speed by 500%. + +//not in db +//Yell +//-->Other +#define SAY_ANTI_MAGIC_SHELL -1616000 +#define SAY_BREATH_ATTACK -1616001 +#define SAY_HIGH_DAMAGE_MODE -1616002 +#define SAY_MAGIC_BLAST -1616003 +//--> Generic Spells +#define SAY_GENERIC_SPELL_1 -1616004 +#define SAY_GENERIC_SPELL_2 -1616005 +#define SAY_GENERIC_SPELL_3 -1616006 +#define SAY_DEATH -1616007 +//--> Prefight +#define SAY_PREFIGHT_1 -1616008 +#define SAY_PREFIGHT_2 -1616009 +#define SAY_PREFIGHT_3 -1616010 +#define SAY_PREFIGHT_4 -1616011 +#define SAY_PREFIGHT_5 -1616012 +//--> Phase1 +#define SAY_PHASE1_AGGRO -1616013 +#define SAY_PHASE1_END -1616014 +#define SAY_PHASE1_SLAY_1 -1616015 +#define SAY_PHASE1_SLAY_2 -1616016 +#define SAY_PHASE1_SLAY_3 -1616017 + +//--> Phase2 at 50% HP, + +/*Malygos himself is not targetable during this phase, it will end when the adds he spawns are all killed. However, he does continue to play a part in the encounter. +During this phase he drops anti-magic zones onto the ground the raid MUST stand inside of, it reduces magical damage taken by 50%. They shrink over time, so it's important that your raid moves to each new one he drops. +Throughout the phase, he will deep breath doing ~4k damage per second, unless you are standing inside of the anti-magic zone. +The way the fight works during this phase is there are NPCs riding around on disks in the room. There are two types of mobs, Lords and Scions. +The Lords will move down onto the group, and need to be tanked (They will one-shot a non-tank). After they die, they drop a disk that a raid member can mount onto, which allows them to fly, to attack the Scions that do not come down to the ground. +It is recommended to let melee take the first disks, then ranged. As those mobs die, they also drop disks, which allows the rest of your dps to get onto them. +The Scions will continually cast Arcane Blast on random targets on the floor, which is mitigated by the anti-magic zones. While mounted on a disk, you will not take damage. +After all of the NPCs riding on the disks die, the players on the disks need to dismount as Phase 3 is about to begin.*/ + +//not in db +#define SAY_PHASE2_AGGRO -1616018 +#define SAY_PHASE2_END -1616019 +#define SAY_PHASE2_SLAY_1 -1616020 +#define SAY_PHASE2_SLAY_2 -1616021 +#define SAY_PHASE2_SLAY_3 -1616022 +//--> Phase3 Malygos destroys the floor, encounter continues on dragon "mounts" +#define SAY_PHASE3_INTRO -1616023 +#define SAY_PHASE3_AGGRO -1616024 +#define SAY_PHASE3_SLAY_1 -1616025 +#define SAY_PHASE3_SLAY_2 -1616026 +#define SAY_PHASE3_SLAY_3 -1616027 +#define SAY_PHASE3_BIG_ATTACK -1616028 + +enum +{ + ACHIEV_TIMED_START_EVENT = 20387, +}; + +struct boss_malygosAI : public ScriptedAI +{ + boss_malygosAI(Creature *c) : ScriptedAI(c) + { + instance = me->GetInstanceData(); + } + + InstanceData *instance; + + uint32 phase; + uint32 enrage; + + void Reset() + { + phase = 1; + enrage = 615000; //Source Deadly Boss Mod + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void EnterCombat(Unit* /*who*/) + { + if (phase == 1) + { + DoScriptText(SAY_PHASE1_AGGRO, me); + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + if (phase == 2) + DoScriptText(SAY_PHASE1_AGGRO, me); + if (phase == 3) + DoScriptText(SAY_PHASE1_AGGRO, me); + } + + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (phase == 1 && HealthBelowPct(50)) { + phase = 2; + //spawn adds + //set malygos unatackable untill all adds spawned dead + //start phase3 + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + if (phase == 1) + DoScriptText(RAND(SAY_PHASE1_SLAY_1,SAY_PHASE1_SLAY_2,SAY_PHASE1_SLAY_3), me); + if (phase == 2) + DoScriptText(RAND(SAY_PHASE2_SLAY_1,SAY_PHASE2_SLAY_2,SAY_PHASE2_SLAY_3), me); + if (phase == 3) + DoScriptText(RAND(SAY_PHASE3_SLAY_1,SAY_PHASE3_SLAY_2,SAY_PHASE3_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_malygos(Creature* pCreature) +{ + return new boss_malygosAI (pCreature); +} + +void AddSC_boss_malygos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_malygos"; + newscript->GetAI = &GetAI_boss_malygos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h b/src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h new file mode 100644 index 00000000000..caa82a92e95 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h @@ -0,0 +1,4 @@ +#ifndef DEF_EYE_OF_ETERNITY_H +#define DEF_EYE_OF_ETERNITY_H + +#endif diff --git a/src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp new file mode 100644 index 00000000000..d93ec415b42 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp @@ -0,0 +1,21 @@ +#include "ScriptedPch.h" +#include "eye_of_eternity.h" + +struct instance_eye_of_eternity : public ScriptedInstance +{ + instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; +}; + +InstanceData* GetInstanceData_instance_eye_of_eternity(Map* pMap) +{ + return new instance_eye_of_eternity(pMap); +} + +void AddSC_instance_eye_of_eternity() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_eye_of_eternity"; + newscript->GetInstanceData = &GetInstanceData_instance_eye_of_eternity; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp b/src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp new file mode 100644 index 00000000000..02c39dc1232 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp @@ -0,0 +1,253 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + //Spells + SPELL_SPARK = 47751, + H_SPELL_SPARK = 57062, + SPELL_RIFT_SHIELD = 47748, + SPELL_CHARGE_RIFT = 47747, //Works wrong (affect players, not rifts) + SPELL_CREATE_RIFT = 47743, //Don't work, using WA + SPELL_ARCANE_ATTRACTION = 57063, //No idea, when it's used +}; + +enum Adds +{ + MOB_CRAZED_MANA_WRAITH = 26746, + MOB_CHAOTIC_RIFT = 26918 +}; +enum Yells +{ + //Yell + SAY_AGGRO = -1576010, + SAY_DEATH = -1576011, + SAY_RIFT = -1576012, + SAY_SHIELD = -1576013 +}; + +enum Achievs +{ + ACHIEV_CHAOS_THEORY = 2037 +}; + +const Position RiftLocation[6] = +{ + {652.64, -273.70, -8.75}, + {634.45, -265.94, -8.44}, + {620.73, -281.17, -9.02}, + {626.10, -304.67, -9.44}, + {639.87, -314.11, -9.49}, + {651.72, -297.44, -9.37} +}; + +struct boss_anomalusAI : public ScriptedAI +{ + boss_anomalusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint8 Phase; + uint32 uiSparkTimer; + uint32 uiCreateRiftTimer; + uint64 uiChaoticRiftGUID; + + bool bDeadChaoticRift; // needed for achievement: Chaos Theory(2037) + + void Reset() + { + Phase = 0; + uiSparkTimer = 5*IN_MILISECONDS; + uiChaoticRiftGUID = 0; + + bDeadChaoticRift = false; + + if (pInstance) + pInstance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && !bDeadChaoticRift) + pInstance->DoCompleteAchievement(ACHIEV_CHAOS_THEORY); + pInstance->SetData(DATA_ANOMALUS_EVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetDistance(me->GetHomePosition()) > 60.0f) + { + //Not blizzlike, hack to avoid an exploit + EnterEvadeMode(); + return; + } + + if (me->HasAura(SPELL_RIFT_SHIELD)) + { + if (uiChaoticRiftGUID) + { + Unit* Rift = Unit::GetUnit((*me), uiChaoticRiftGUID); + if (Rift && Rift->isDead()) + { + me->RemoveAurasDueToSpell(SPELL_RIFT_SHIELD); + uiChaoticRiftGUID = 0; + } + return; + } + } else + uiChaoticRiftGUID = 0; + + if ((Phase == 0) && HealthBelowPct(50)) + { + Phase = 1; + DoScriptText(SAY_SHIELD, me); + DoCast(me, SPELL_RIFT_SHIELD); + Creature* Rift = me->SummonCreature(MOB_CHAOTIC_RIFT, RiftLocation[urand(0,5)], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); + if (Rift) + { + //DoCast(Rift, SPELL_CHARGE_RIFT); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Rift->AI()->AttackStart(pTarget); + uiChaoticRiftGUID = Rift->GetGUID(); + DoScriptText(SAY_RIFT , me); + } + } + + + if (uiSparkTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SPARK); + uiSparkTimer = 5*IN_MILISECONDS; + } else uiSparkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_anomalus(Creature* pCreature) +{ + return new boss_anomalusAI (pCreature); +} + +enum RiftSpells +{ + SPELL_CHAOTIC_ENERGY_BURST = 47688, + SPELL_CHARGED_CHAOTIC_ENERGY_BURST = 47737, + SPELL_ARCANEFORM = 48019 //Chaotic Rift visual +}; + +struct mob_chaotic_riftAI : public Scripted_NoMovementAI +{ + mob_chaotic_riftAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiChaoticEnergyBurstTimer; + uint32 uiSummonCrazedManaWraithTimer; + + void Reset() + { + uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; + uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; + //me->SetDisplayId(25206); //For some reason in DB models for ally and horde are different. + //Model for ally (1126) does not show auras. Horde model works perfect. + //Set model to horde number + DoCast(me, SPELL_ARCANEFORM, false); + } + + void JustDied(Unit * /*killer*/) + { + if (Creature* pAnomalus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0)) + CAST_AI(boss_anomalusAI,pAnomalus->AI())->bDeadChaoticRift = true; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiChaoticEnergyBurstTimer <= diff) + { + Unit* pAnomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + if (pAnomalus && pAnomalus->HasAura(SPELL_RIFT_SHIELD)) + DoCast(pTarget, SPELL_CHARGED_CHAOTIC_ENERGY_BURST); + else + DoCast(pTarget, SPELL_CHAOTIC_ENERGY_BURST); + uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; + } else uiChaoticEnergyBurstTimer -= diff; + + if (uiSummonCrazedManaWraithTimer <= diff) + { + Creature* Wraith = me->SummonCreature(MOB_CRAZED_MANA_WRAITH, me->GetPositionX()+1, me->GetPositionY()+1, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); + if (Wraith) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Wraith->AI()->AttackStart(pTarget); + Unit* Anomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); + if (Anomalus && Anomalus->HasAura(SPELL_RIFT_SHIELD)) + uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; + else + uiSummonCrazedManaWraithTimer = 10*IN_MILISECONDS; + } else uiSummonCrazedManaWraithTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_chaotic_rift(Creature* pCreature) +{ + return new mob_chaotic_riftAI (pCreature); +} + +void AddSC_boss_anomalus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_anomalus"; + newscript->GetAI = &GetAI_boss_anomalus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_chaotic_rift"; + newscript->GetAI = &GetAI_mob_chaotic_rift; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp new file mode 100644 index 00000000000..ff633c55eac --- /dev/null +++ b/src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp @@ -0,0 +1,247 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + //Spells + SPELL_FROZEN_PRISON = 47854, + SPELL_TAIL_SWEEP = 50155, + SPELL_CRYSTAL_CHAINS = 50997, + SPELL_ENRAGE = 8599, + SPELL_CRYSTALFIRE_BREATH = 48096, + H_SPELL_CRYSTALFIRE_BREATH = 57091, + SPELL_CRYSTALIZE = 48179, + SPELL_INTENSE_COLD = 48094, + SPELL_INTENSE_COLD_TRIGGERED = 48095 +}; +enum Yells +{ + //Yell + SAY_AGGRO = -1576040, + SAY_SLAY = -1576041, + SAY_ENRAGE = -1576042, + SAY_DEATH = -1576043, + SAY_CRYSTAL_NOVA = -1576044 +}; +enum Achievements +{ + ACHIEV_INTENSE_COLD = 2036 +}; +enum Misc +{ + DATA_CONTAINMENT_SPHERES = 3 +}; + +struct boss_keristraszaAI : public ScriptedAI +{ + boss_keristraszaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCrystalfireBreathTimer; + uint32 uiCrystalChainsCrystalizeTimer; + uint32 uiTailSweepTimer; + bool bEnrage; + + uint64 auiContainmentSphereGUIDs[DATA_CONTAINMENT_SPHERES]; + + uint32 uiCheckIntenseColdTimer; + bool bMoreThanTwoIntenseCold; // needed for achievement: Intense Cold(2036) + + void Reset() + { + uiCrystalfireBreathTimer = 14*IN_MILISECONDS; + uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); + uiTailSweepTimer = 5*IN_MILISECONDS; + bEnrage = false; + + uiCheckIntenseColdTimer = 2*IN_MILISECONDS; + bMoreThanTwoIntenseCold = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + + RemovePrison(CheckContainmentSpheres()); + + if (pInstance) + pInstance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCastAOE(SPELL_INTENSE_COLD); + + if (pInstance) + pInstance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && !bMoreThanTwoIntenseCold) + pInstance->DoCompleteAchievement(ACHIEV_INTENSE_COLD); + pInstance->SetData(DATA_KERISTRASZA_EVENT, DONE); + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_SLAY, me); + } + + bool CheckContainmentSpheres(bool remove_prison = false) + { + if (!pInstance) + return false; + + auiContainmentSphereGUIDs[0] = pInstance->GetData64(ANOMALUS_CONTAINMET_SPHERE); + auiContainmentSphereGUIDs[1] = pInstance->GetData64(ORMOROKS_CONTAINMET_SPHERE); + auiContainmentSphereGUIDs[2] = pInstance->GetData64(TELESTRAS_CONTAINMET_SPHERE); + + GameObject *ContainmentSpheres[DATA_CONTAINMENT_SPHERES]; + + for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i) + { + ContainmentSpheres[i] = pInstance->instance->GetGameObject(auiContainmentSphereGUIDs[i]); + if (!ContainmentSpheres[i]) + return false; + if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE) + return false; + } + if (remove_prison) + RemovePrison(true); + return true; + } + + void RemovePrison(bool remove) + { + if (remove) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (me->HasAura(SPELL_FROZEN_PRISON)) + me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(me, SPELL_FROZEN_PRISON, false); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiCheckIntenseColdTimer < diff && !bMoreThanTwoIntenseCold) + { + std::list ThreatList = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER) + continue; + + Aura *AuraIntenseCold = pTarget->GetAura(SPELL_INTENSE_COLD_TRIGGERED); + if (AuraIntenseCold && AuraIntenseCold->GetStackAmount() > 2) + { + bMoreThanTwoIntenseCold = true; + break; + } + } + uiCheckIntenseColdTimer = 2*IN_MILISECONDS; + } else uiCheckIntenseColdTimer -= diff; + + if (!bEnrage && HealthBelowPct(25)) + { + DoScriptText(SAY_ENRAGE, me); + DoCast(me, SPELL_ENRAGE); + bEnrage = true; + } + + if (uiCrystalfireBreathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CRYSTALFIRE_BREATH); + uiCrystalfireBreathTimer = 14*IN_MILISECONDS; + } else uiCrystalfireBreathTimer -= diff; + + if (uiTailSweepTimer <= diff) + { + DoCast(me, SPELL_TAIL_SWEEP); + uiTailSweepTimer = 5*IN_MILISECONDS; + } else uiTailSweepTimer -= diff; + + if (uiCrystalChainsCrystalizeTimer <= diff) + { + DoScriptText(SAY_CRYSTAL_NOVA, me); + if (IsHeroic()) + DoCast(me, SPELL_CRYSTALIZE); + else if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CRYSTAL_CHAINS); + uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); + } else uiCrystalChainsCrystalizeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_keristrasza(Creature* pCreature) +{ + return new boss_keristraszaAI (pCreature); +} + +bool GOHello_containment_sphere(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + + Creature *pKeristrasza = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_KERISTRASZA) : 0); + if (pKeristrasza && pKeristrasza->isAlive()) + { + // maybe these are hacks :( + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + CAST_AI(boss_keristraszaAI, pKeristrasza->AI())->CheckContainmentSpheres(true); + } + return true; +} + +void AddSC_boss_keristrasza() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_keristrasza"; + newscript->GetAI = &GetAI_boss_keristrasza; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "containment_sphere"; + newscript->pGOHello = &GOHello_containment_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp b/src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp new file mode 100644 index 00000000000..0bf9fb07bb7 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp @@ -0,0 +1,327 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + SPELL_ICE_NOVA = 47772, + H_SPELL_ICE_NOVA = 56935, + SPELL_FIREBOMB = 47773, + H_SPELL_FIREBOMB = 56934, + SPELL_GRAVITY_WELL = 47756, + SPELL_TELESTRA_BACK = 47714, + + SPELL_FIRE_MAGUS_VISUAL = 47705, + SPELL_FROST_MAGUS_VISUAL = 47706, + SPELL_ARCANE_MAGUS_VISUAL = 47704 +}; +enum Creatures +{ + MOB_FIRE_MAGUS = 26928, + MOB_FROST_MAGUS = 26930, + MOB_ARCANE_MAGUS = 26929 +}; +enum Yells +{ + SAY_AGGRO = -1576000, + SAY_KILL = -1576001, + SAY_DEATH = -1576002, + SAY_MERGE = -1576003, + SAY_SPLIT_1 = -1576004, + SAY_SPLIT_2 = -1576005, +}; +enum Achievements +{ + ACHIEV_SPLIT_PERSONALITY = 2150, + ACHIEV_TIMER = 5*IN_MILISECONDS +}; + +const Position CenterOfRoom = {504.80, 89.07, -16.12, 6.27}; + +struct boss_magus_telestraAI : public ScriptedAI +{ + boss_magus_telestraAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 uiFireMagusGUID; + uint64 uiFrostMagusGUID; + uint64 uiArcaneMagusGUID; + + bool bFireMagusDead; + bool bFrostMagusDead; + bool bArcaneMagusDead; + bool bIsWaitingToAppear; + bool bIsAchievementTimerRunning; + + uint32 uiIsWaitingToAppearTimer; + uint32 uiIceNovaTimer; + uint32 uiFireBombTimer; + uint32 uiGravityWellTimer; + uint32 uiCooldown; + uint32 uiAchievementTimer; + + uint8 Phase; + uint8 uiAchievementProgress; + + void Reset() + { + Phase = 0; + //These times are probably wrong + uiIceNovaTimer = 7*IN_MILISECONDS; + uiFireBombTimer = 0; + uiGravityWellTimer = 15*IN_MILISECONDS; + uiCooldown = 0; + + uiFireMagusGUID = 0; + uiFrostMagusGUID = 0; + uiArcaneMagusGUID = 0; + + uiAchievementProgress = 0; + uiAchievementTimer = 0; + + bIsAchievementTimerRunning = false; + bIsWaitingToAppear = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + if (pInstance) + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && uiAchievementProgress == 2) + pInstance->DoCompleteAchievement(ACHIEV_SPLIT_PERSONALITY); + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE); + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + uint64 SplitPersonality(uint32 entry) + { + if (Creature* Summoned = me->SummonCreature(entry, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS)) + { + switch (entry) + { + case MOB_FIRE_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_FIRE_MAGUS_VISUAL, false); + break; + } + case MOB_FROST_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_FROST_MAGUS_VISUAL, false); + break; + } + case MOB_ARCANE_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_ARCANE_MAGUS_VISUAL, false); + break; + } + } + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Summoned->AI()->AttackStart(pTarget); + return Summoned->GetGUID(); + } + return 0; + } + + void SummonedCreatureDespawn(Creature *summon) + { + if (summon->isAlive()) + return; + + if (summon->GetGUID() == uiFireMagusGUID) + { + bFireMagusDead = true; + bIsAchievementTimerRunning = true; + } + else if (summon->GetGUID() == uiFrostMagusGUID) + { + bFrostMagusDead = true; + bIsAchievementTimerRunning = true; + } + else if (summon->GetGUID() == uiArcaneMagusGUID) + { + bArcaneMagusDead = true; + bIsAchievementTimerRunning = true; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (bIsWaitingToAppear) + { + me->StopMoving(); + me->AttackStop(); + if (uiIsWaitingToAppearTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + bIsWaitingToAppear = false; + } else uiIsWaitingToAppearTimer -= diff; + return; + } + + if ((Phase == 1) ||(Phase == 3)) + { + if (bIsAchievementTimerRunning) + uiAchievementTimer += diff; + if (bFireMagusDead && bFrostMagusDead && bArcaneMagusDead) + { + if (uiAchievementTimer <= ACHIEV_TIMER) + uiAchievementProgress +=1; + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, CenterOfRoom.GetPositionX(), CenterOfRoom.GetPositionY(), CenterOfRoom.GetPositionZ(), CenterOfRoom.GetOrientation()); + DoCast(me, SPELL_TELESTRA_BACK); + me->SetVisibility(VISIBILITY_ON); + if (Phase == 1) + Phase = 2; + if (Phase == 3) + Phase = 4; + uiFireMagusGUID = 0; + uiFrostMagusGUID = 0; + uiArcaneMagusGUID = 0; + bIsWaitingToAppear = true; + uiIsWaitingToAppearTimer = 4*IN_MILISECONDS; + DoScriptText(SAY_MERGE, me); + bIsAchievementTimerRunning = false; + uiAchievementTimer = 0; + } + else + return; + } + + if ((Phase == 0) && HealthBelowPct(50)) + { + Phase = 1; + me->CastStop(); + me->RemoveAllAuras(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); + uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); + uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); + bFireMagusDead = false; + bFrostMagusDead = false; + bArcaneMagusDead = false; + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + return; + } + + if (IsHeroic() && (Phase == 2) && HealthBelowPct(10)) + { + Phase = 3; + me->CastStop(); + me->RemoveAllAuras(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); + uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); + uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); + bFireMagusDead = false; + bFrostMagusDead = false; + bArcaneMagusDead = false; + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + return; + } + + if (uiCooldown) + { + if (uiCooldown <= diff) + uiCooldown = 0; + else + { + uiCooldown -= diff; + return; + } + } + + if (uiIceNovaTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_ICE_NOVA, false); + uiCooldown = 1.5*IN_MILISECONDS; + } + uiIceNovaTimer = 15*IN_MILISECONDS; + } else uiIceNovaTimer -= diff; + + if (uiGravityWellTimer <= diff) + { + if (Unit *pTarget = me->getVictim()) + { + DoCast(pTarget, SPELL_GRAVITY_WELL); + uiCooldown = 6*IN_MILISECONDS; + } + uiGravityWellTimer = 15*IN_MILISECONDS; + } else uiGravityWellTimer -= diff; + + if (uiFireBombTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_FIREBOMB, false); + uiCooldown = 2*IN_MILISECONDS; + } + uiFireBombTimer = 2*IN_MILISECONDS; + } else uiFireBombTimer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_magus_telestra(Creature* pCreature) +{ + return new boss_magus_telestraAI (pCreature); +} + +void AddSC_boss_magus_telestra() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_magus_telestra"; + newscript->GetAI = &GetAI_boss_magus_telestra; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp new file mode 100644 index 00000000000..1304f95c7ac --- /dev/null +++ b/src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp @@ -0,0 +1,298 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + SPELL_CRYSTAL_SPIKES = 47958, //Don't work, using walkaround + H_SPELL_CRYSTAL_SPIKES = 57082, //Don't work, using walkaround + SPELL_CRYSTALL_SPIKE_DAMAGE = 47944, + H_SPELL_CRYSTALL_SPIKE_DAMAGE = 57067, + SPELL_CRYSTAL_SPIKE_PREVISUAL = 50442, + MOB_CRYSTAL_SPIKE = 27099, + SPELL_SPELL_REFLECTION = 47981, + SPELL_TRAMPLE = 48016, + H_SPELL_TRAMPLE = 57066, + SPELL_FRENZY = 48017, + SPELL_SUMMON_CRYSTALLINE_TANGLER = 61564, //summons npc 32665 + SPELL_ROOTS = 28858 //proper spell id is unknown +}; +enum Yells +{ + SAY_AGGRO = -1576020, + SAY_DEATH = -1576021, + SAY_REFLECT = -1576022, + SAY_CRYSTAL_SPIKES = -1576023, + SAY_KILL = -1576024 +}; +enum Creatures +{ + MOB_CRYSTALLINE_TANGLER = 32665 +}; + +#define SPIKE_DISTANCE 5.0f + +struct boss_ormorokAI : public ScriptedAI +{ + boss_ormorokAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bFrenzy; + bool bCrystalSpikes; + uint8 uiCrystalSpikesCount; + float fBaseX; + float fBaseY; + float fBaseZ; + float fBaseO; + float fSpikeXY[4][2]; + + uint32 uiCrystalSpikesTimer; + uint32 uiCrystalSpikesTimer2; + uint32 uiTrampleTimer; + uint32 uiFrenzyTimer; + uint32 uiSpellReflectionTimer; + uint32 uiSummonCrystallineTanglerTimer; + + void Reset() + { + uiCrystalSpikesTimer = 12*IN_MILISECONDS; + uiTrampleTimer = 10*IN_MILISECONDS; + uiSpellReflectionTimer = 30*IN_MILISECONDS; + uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; + bFrenzy = false; + bCrystalSpikes = false; + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + return; + } + if (bCrystalSpikes) + if (uiCrystalSpikesTimer2 <= diff) + { + fSpikeXY[0][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); + fSpikeXY[0][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); + fSpikeXY[1][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); + fSpikeXY[1][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); + fSpikeXY[2][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); + fSpikeXY[2][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); + fSpikeXY[3][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); + fSpikeXY[3][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); + for (uint8 i = 0; i < 4; ++i) + me->SummonCreature(MOB_CRYSTAL_SPIKE, fSpikeXY[i][0], fSpikeXY[i][1], fBaseZ, 0, TEMPSUMMON_TIMED_DESPAWN, 7*IN_MILISECONDS); + if (++uiCrystalSpikesCount >= 13) + bCrystalSpikes = false; + uiCrystalSpikesTimer2 = 200; + } else uiCrystalSpikesTimer2 -= diff; + + if (!bFrenzy && (me->GetHealth() < me->GetMaxHealth() * 0.25)) + { + DoCast(me, SPELL_FRENZY); + bFrenzy = true; + } + + if (uiTrampleTimer <= diff) + { + DoCast(me, SPELL_TRAMPLE); + uiTrampleTimer = 10*IN_MILISECONDS; + } else uiTrampleTimer -= diff; + + if (uiSpellReflectionTimer <= diff) + { + DoScriptText(SAY_REFLECT, me); + DoCast(me, SPELL_SPELL_REFLECTION); + uiSpellReflectionTimer = 30*IN_MILISECONDS; + } else uiSpellReflectionTimer -= diff; + + if (uiCrystalSpikesTimer <= diff) + { + DoScriptText(SAY_CRYSTAL_SPIKES, me); + bCrystalSpikes = true; + uiCrystalSpikesCount = 1; + uiCrystalSpikesTimer2 = 0; + fBaseX = me->GetPositionX(); + fBaseY = me->GetPositionY(); + fBaseZ = me->GetPositionZ(); + fBaseO = me->GetOrientation(); + uiCrystalSpikesTimer = 20*IN_MILISECONDS; + } else uiCrystalSpikesTimer -= diff; + + if (IsHeroic() && (uiSummonCrystallineTanglerTimer <= diff)) + { + Creature* Crystalline_Tangler = me->SummonCreature(MOB_CRYSTALLINE_TANGLER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + if (Crystalline_Tangler) + { + Unit *pTarget = NULL; + uint8 Healer = 0; + for (uint8 j = 1; j <= 4; j++) + { + switch (j) + { + case 1: Healer = CLASS_PRIEST; break; + case 2: Healer = CLASS_PALADIN; break; + case 3: Healer = CLASS_DRUID; break; + case 4: Healer = CLASS_SHAMAN; break; + } + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pTemp = Unit::GetUnit((*me),(*i)->getUnitGuid()); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && pTemp->getClass() == Healer) + { + pTarget = pTemp; + break; + } + } + if (pTarget) + break; + } + if (!pTarget) + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Crystalline_Tangler->AI()->AttackStart(pTarget); + Crystalline_Tangler->getThreatManager().addThreat(pTarget, 1000000000.0f); + } + } + uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; + } else uiSummonCrystallineTanglerTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_crystal_spikeAI : public Scripted_NoMovementAI +{ + mob_crystal_spikeAI(Creature *c) : Scripted_NoMovementAI(c) + { + } + + uint32 SpellCrystalSpikeDamageTimer; + uint32 SpellCrystalSpikePrevisualTimer; + + void Reset() + { + SpellCrystalSpikeDamageTimer = 3.7*IN_MILISECONDS; + SpellCrystalSpikePrevisualTimer = 1*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (SpellCrystalSpikePrevisualTimer <= diff) + { + DoCast(me, SPELL_CRYSTAL_SPIKE_PREVISUAL); + SpellCrystalSpikePrevisualTimer = 10*IN_MILISECONDS; + } else SpellCrystalSpikePrevisualTimer -= diff; + + if (SpellCrystalSpikeDamageTimer <= diff) + { + DoCast(me, SPELL_CRYSTALL_SPIKE_DAMAGE); + SpellCrystalSpikeDamageTimer = 10*IN_MILISECONDS; + } else SpellCrystalSpikeDamageTimer -= diff; + } +}; + +struct mob_crystalline_tanglerAI : public ScriptedAI +{ + mob_crystalline_tanglerAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiRootsTimer; + + void Reset() + { + uiRootsTimer = 1*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (uiRootsTimer <= diff) + { + if (me->IsWithinDist(me->getVictim(), 5.0f, false)) + { + DoCast(me->getVictim(), SPELL_ROOTS); + uiRootsTimer = 15*IN_MILISECONDS; + } + } else uiRootsTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_crystal_spike(Creature* pCreature) +{ + return new mob_crystal_spikeAI (pCreature); +} + +CreatureAI* GetAI_mob_crystalline_tangler(Creature* pCreature) +{ + return new mob_crystalline_tanglerAI (pCreature); +} + +CreatureAI* GetAI_boss_ormorok(Creature* pCreature) +{ + return new boss_ormorokAI (pCreature); +} + +void AddSC_boss_ormorok() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ormorok"; + newscript->GetAI = &GetAI_boss_ormorok; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crystal_spike"; + newscript->GetAI = &GetAI_mob_crystal_spike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crystalline_tangler"; + newscript->GetAI = &GetAI_mob_crystalline_tangler; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp b/src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp new file mode 100644 index 00000000000..4bd9f55a013 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp @@ -0,0 +1,58 @@ +/* Script Data Start +SDName: Boss Commander Kolurg +SDAuthor: LordVanMartin +SD%Complete: +SDComment: Only Alliance Heroic +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_commander_kolurg' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +#define SPELL_BATTLE_SHOUT 31403 +#define SPELL_CHARGE 60067 +#define SPELL_FRIGHTENING_SHOUT 19134 +#define SPELL_WHIRLWIND_1 38619 +#define SPELL_WHIRLWIND_2 38618 + +//not used +//Yell +#define SAY_AGGRO -1576024 +#define SAY_KILL -1576025 +#define SAY_DEATH -1576026 + +struct boss_commander_kolurgAI : public ScriptedAI +{ + boss_commander_kolurgAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) {} +}; + +CreatureAI* GetAI_boss_commander_kolurg(Creature* pCreature) +{ + return new boss_commander_kolurgAI (pCreature); +} + +void AddSC_boss_commander_kolurg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_commander_kolurg"; + newscript->GetAI = &GetAI_boss_commander_kolurg; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp b/src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp new file mode 100644 index 00000000000..ef02baa38e6 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp @@ -0,0 +1,64 @@ +/* Script Data Start +SDName: Boss Commander Stoutbeard +SDAuthor: LordVanMartin +SD%Complete: +SDComment: Only Horde Heroic +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_commander_stoutbeard' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +#define SPELL_BATTLE_SHOUT 31403 +#define SPELL_CHARGE 60067 +#define SPELL_FRIGHTENING_SHOUT 19134 +#define SPELL_WHIRLWIND_1 38619 +#define SPELL_WHIRLWIND_2 38618 + +//not used +//Yell +#define SAY_AGGRO -1576021 +#define SAY_KILL -1576022 +#define SAY_DEATH -1576023 + +struct boss_commander_stoutbeardAI : public ScriptedAI +{ + boss_commander_stoutbeardAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + } +}; + +CreatureAI* GetAI_boss_commander_stoutbeard(Creature* pCreature) +{ + return new boss_commander_stoutbeardAI (pCreature); +} + +void AddSC_boss_commander_stoutbeard() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_commander_stoutbeard"; + newscript->GetAI = &GetAI_boss_commander_stoutbeard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp b/src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp new file mode 100644 index 00000000000..db70245e3a4 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp @@ -0,0 +1,259 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +#define NUMBER_OF_ENCOUNTERS 4 + +enum Factions +{ + FACTION_HOSTILE_FOR_ALL = 16 +}; + +struct instance_nexus : public ScriptedInstance +{ + instance_nexus(Map *pMap) : ScriptedInstance(pMap) { Initialize(); } + + uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS]; + + uint64 Anomalus; + uint64 Keristrasza; + + uint64 AnomalusContainmentSphere; + uint64 OrmoroksContainmentSphere; + uint64 TelestrasContainmentSphere; + + std::string strInstData; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Anomalus = 0; + Keristrasza = 0; + } + + void OnCreatureCreate(Creature *pCreature, bool /*bAdd*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + uint32 TeamInInstance = 0; + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + TeamInInstance = pPlayer->GetTeam(); + } + switch (pCreature->GetEntry()) + { + case 26763: + Anomalus = pCreature->GetGUID(); + break; + case 26723: + Keristrasza = pCreature->GetGUID(); + break; + // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. + case 26800: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26799, HORDE); + break; + } + case 26802: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26801, HORDE); + break; + } + case 26805: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26803, HORDE); + break; + } + case 27949: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(27947, HORDE); + break; + } + case 26796: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26798, HORDE); + break; + } + } + } + + void OnGameObjectCreate(GameObject *pGo, bool /*bAdd*/) + { + switch (pGo->GetEntry()) + { + case 188527: + { + AnomalusContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + case 188528: + { + OrmoroksContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + case 188526: + { + TelestrasContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + } + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0]; + case DATA_ANOMALUS_EVENT: return m_auiEncounter[1]; + case DATA_ORMOROK_EVENT: return m_auiEncounter[2]; + case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3]; + } + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch (identifier) + { + case DATA_MAGUS_TELESTRA_EVENT: + { + if (data == DONE) + { + GameObject *Sphere = instance->GetGameObject(TelestrasContainmentSphere); + if (Sphere) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[0] = data; + break; + } + case DATA_ANOMALUS_EVENT: + { + if (data == DONE) + { + if (GameObject *Sphere = instance->GetGameObject(AnomalusContainmentSphere)) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[1] = data; + break; + } + case DATA_ORMOROK_EVENT: + { + if (data == DONE) + { + if (GameObject *Sphere = instance->GetGameObject(OrmoroksContainmentSphere)) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[2] = data; + break; + } + case DATA_KERISTRASZA_EVENT: + m_auiEncounter[3] = data; + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3]; + + strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint64 GetData64(uint32 uiIdentifier) + { + switch(uiIdentifier) + { + case DATA_ANOMALUS: return Anomalus; + case DATA_KERISTRASZA: return Keristrasza; + case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere; + case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere; + case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere; + } + return 0; + } + + std::string GetSaveData() + { + return strInstData; + } + + void Load(const char *chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + + for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData *GetInstanceData_instance_nexus(Map *pMap) +{ + return new instance_nexus(pMap); +} + +void AddSC_instance_nexus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_nexus"; + newscript->GetInstanceData = &GetInstanceData_instance_nexus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/nexus/nexus.h b/src/server/scripts/Northrend/nexus/nexus/nexus.h new file mode 100644 index 00000000000..66902bece30 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/nexus/nexus.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_NEXUS_H +#define DEF_NEXUS_H + +enum eTypes +{ + DATA_MAGUS_TELESTRA_EVENT, + DATA_ANOMALUS_EVENT, + DATA_ORMOROK_EVENT, + DATA_KERISTRASZA_EVENT, + + DATA_ANOMALUS, + DATA_KERISTRASZA, + + ANOMALUS_CONTAINMET_SPHERE, + ORMOROKS_CONTAINMET_SPHERE, + TELESTRAS_CONTAINMET_SPHERE +}; + +#endif diff --git a/src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp b/src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp new file mode 100644 index 00000000000..7d276206339 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp @@ -0,0 +1,218 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + SPELL_MAGIC_PULL = 51336, + SPELL_MAGIC_PULL_EFFECT = 50770, + SPELL_THUNDERING_STOMP = 50774, + SPELL_THUNDERING_STOMP_H = 59370, + SPELL_UNSTABLE_SPHERE_PASSIVE = 50756, + SPELL_UNSTABLE_SPHERE_PULSE = 50757, + SPELL_UNSTABLE_SPHERE_TIMER = 50758, + NPC_UNSTABLE_SPHERE = 28166, +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1578000, + SAY_KILL_1 = -1578001, + SAY_KILL_2 = -1578002, + SAY_KILL_3 = -1578003, + SAY_DEATH = -1578004, + SAY_PULL_1 = -1578005, + SAY_PULL_2 = -1578006, + SAY_PULL_3 = -1578007, + SAY_PULL_4 = -1578008, + SAY_STOMP_1 = -1578009, + SAY_STOMP_2 = -1578010, + SAY_STOMP_3 = -1578011 +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 18153, +}; + +struct boss_drakosAI : public ScriptedAI +{ + boss_drakosAI(Creature* pCreature) : ScriptedAI(pCreature), lSummons(me) + { + pInstance = pCreature->GetInstanceData(); + } + + uint32 uiMagicPullTimer; + uint32 uiStompTimer; + uint32 uiBombSummonTimer; + + bool bPostPull; + + ScriptedInstance* pInstance; + SummonList lSummons; + + void Reset() + { + lSummons.DespawnAll(); + uiMagicPullTimer = 15000; + uiStompTimer = 17000; + uiBombSummonTimer = 2000; + + bPostPull = false; + + if (pInstance) + pInstance->SetData(DATA_DRAKOS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_DRAKOS_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature* pSummon) + { + lSummons.Summon(pSummon); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBombSummonTimer <= uiDiff) + { + Position pPosition; + me->GetPosition(&pPosition); + + if (bPostPull) + { + for (uint8 uiI = 0; uiI >= 3; uiI++) + { + me->GetRandomNearPosition(pPosition, float(urand(0,10))); + me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); + } + } + else + { + me->GetRandomNearPosition(pPosition, float(urand(0,10))); + me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); + } + + uiBombSummonTimer = 2000; + } else uiBombSummonTimer -= uiDiff; + + if (uiMagicPullTimer <= uiDiff) + { + DoCast(SPELL_MAGIC_PULL); + + bPostPull = true; + + uiMagicPullTimer = 15000; + } else uiMagicPullTimer -= uiDiff; + + if (uiStompTimer <= uiDiff) + { + DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2,SAY_STOMP_3), me); + DoCast(SPELL_THUNDERING_STOMP); + uiStompTimer = 17000; + } else uiStompTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_DRAKOS_EVENT, DONE); + // start achievement timer (kill Eregos within 20 min) + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + lSummons.DespawnAll(); + } + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); + } +}; + +CreatureAI* GetAI_boss_drakos(Creature* pCreature) +{ + return new boss_drakosAI (pCreature); +} + +struct npc_unstable_sphereAI : public ScriptedAI +{ + npc_unstable_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiPulseTimer; + uint32 uiDeathTimer; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MoveRandom(40.0f); + + me->AddAura(SPELL_UNSTABLE_SPHERE_PASSIVE, me); + me->AddAura(SPELL_UNSTABLE_SPHERE_TIMER, me); + + uiPulseTimer = 3000; + uiDeathTimer = 19000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiPulseTimer <= uiDiff) + { + DoCast(SPELL_UNSTABLE_SPHERE_PULSE); + uiPulseTimer = 3*IN_MILISECONDS; + } else uiPulseTimer -= uiDiff; + + if (uiDeathTimer <= uiDiff) + me->DisappearAndDie(); + else uiDeathTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_unstable_sphere(Creature* pCreature) +{ + return new npc_unstable_sphereAI (pCreature); +} + +void AddSC_boss_drakos() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_drakos"; + newscript->GetAI = &GetAI_boss_drakos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_unstable_sphere"; + newscript->GetAI = &GetAI_npc_unstable_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp b/src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp new file mode 100644 index 00000000000..94fb90ab206 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp @@ -0,0 +1,129 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +//Types of drake mounts: Ruby(Tank), Amber(DPS), Emerald(Healer) +//Two Repeating phases + +enum Spells +{ + SPELL_ARCANE_BARRAGE = 50804, + H_SPELL_ARCANE_BARRAGE = 59381, + SPELL_ARCANE_VOLLEY = 51153, + H_SPELL_ARCANE_VOLLEY = 59382, + SPELL_ENRAGED_ASSAULT = 51170, + SPELL_PLANAR_ANOMALIES = 57959, + SPELL_PLANAR_SHIFT = 51162, +}; +/*Ruby Drake , +(npc 27756) (item 37860) +(summoned by spell Ruby Essence = 37860 ---> Call Amber Drake == 49462 ---> Summon 27756) +*/ +enum RubyDrake +{ + NPC_RUBY_DRAKE_VEHICLE = 27756, + SPELL_RIDE_RUBY_DRAKE_QUE = 49463, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49464 + SPELL_RUBY_DRAKE_SADDLE = 49464, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_RUBY_SEARING_WRATH = 50232, //(60 yds) - Instant - Breathes a stream of fire at an enemy dragon, dealing 6800 to 9200 Fire damage and then jumping to additional dragons within 30 yards. Each jump increases the damage by 50%. Affects up to 5 total targets + SPELL_RUBY_EVASIVE_AURA = 50248, //Instant - Allows the Ruby Drake to generate Evasive Charges when hit by hostile attacks and spells. + SPELL_RUBY_EVASIVE_MANEUVERS = 50240, //Instant - 5 sec. cooldown - Allows your drake to dodge all incoming attacks and spells. Requires Evasive Charges to use. Each attack or spell dodged while this ability is active burns one Evasive Charge. Lasts 30 sec. or until all charges are exhausted. + //you do not have acces to until you kill Mage-Lord Urom + SPELL_RUBY_MARTYR = 50253 //Instant - 10 sec. cooldown - Redirect all harmful spells cast at friendly drakes to yourself for 10 sec. +}; +/*Amber Drake, +(npc 27755) (item 37859) +(summoned by spell Amber Essence = 37859 ---> Call Amber Drake == 49461 ---> Summon 27755) +*/ +enum AmberDrake +{ + NPC_AMBER_DRAKE_VEHICLE = 27755, + SPELL_RIDE_AMBER_DRAKE_QUE = 49459, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49460 + SPELL_AMBER_DRAKE_SADDLE = 49460, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_AMBER_SHOCK_LANCE = 49840, //(60 yds) - Instant - Deals 4822 to 5602 Arcane damage and detonates all Shock Charges on an enemy dragon. Damage is increased by 6525 for each detonated. +// SPELL_AMBER_STOP_TIME //Instant - 1 min cooldown - Halts the passage of time, freezing all enemy dragons in place for 10 sec. This attack applies 5 Shock Charges to each affected target. + //you do not have access to until you kill the Mage-Lord Urom. + SPELL_AMBER_TEMPORAL_RIFT = 49592 //(60 yds) - Channeled - Channels a temporal rift on an enemy dragon for 10 sec. While trapped in the rift, all damage done to the target is increased by 100%. In addition, for every 15,000 damage done to a target affected by Temporal Rift, 1 Shock Charge is generated. +}; +/*Emerald Drake, +(npc 27692) (item 37815), + (summoned by spell Emerald Essence = 37815 ---> Call Emerald Drake == 49345 ---> Summon 27692) +*/ +enum EmeraldDrake +{ + NPC_EMERALD_DRAKE_VEHICLE = 27692, + SPELL_RIDE_EMERALD_DRAKE_QUE = 49427, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49346 + SPELL_EMERALD_DRAKE_SADDLE = 49346, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_EMERALD_LEECHING_POISON = 50328, //(60 yds) - Instant - Poisons the enemy dragon, leeching 1300 to the caster every 2 sec. for 12 sec. Stacks up to 3 times. + SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, //(60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25,000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec. + // you do not have access to until you kill the Mage-Lord Urom + SPELL_EMERALD_DREAM_FUNNEL = 50344 //(60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels. +}; + +struct boss_eregosAI : public ScriptedAI +{ + boss_eregosAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, DONE); + } +}; + +CreatureAI* GetAI_boss_eregos(Creature* pCreature) +{ + return new boss_eregosAI (pCreature); +} + +void AddSC_boss_eregos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_eregos"; + newscript->GetAI = &GetAI_boss_eregos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp b/src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp new file mode 100644 index 00000000000..29435441d00 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp @@ -0,0 +1,356 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Urom +SD%Complete: 80 +SDComment: Is not working SPELL_ARCANE_SHIELD. SPELL_FROSTBOMB has some issues, the damage aura should not stack. +SDCategory: Instance Script +EndScriptData */ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + + SPELL_ARCANE_SHIELD = 53813, //Dummy --> Channeled, shields the caster from damage. + SPELL_EMPOWERED_ARCANE_EXPLOSION = 51110, + SPELL_EMPOWERED_ARCANE_EXPLOSION_2 = 59377, + SPELL_FROSTBOMB = 51103, //Urom throws a bomb, hitting its target with the highest aggro which inflict directly 650 frost damage and drops a frost zone on the ground. This zone deals 650 frost damage per second and reduce the movement speed by 35%. Lasts 1 minute. + SPELL_SUMMON_MENAGERIE = 50476, //Summons an assortment of creatures and teleports the caster to safety. + SPELL_SUMMON_MENAGERIE_2 = 50495, + SPELL_SUMMON_MENAGERIE_3 = 50496, + SPELL_TELEPORT = 51112, //Teleports to the center of Oculus + SPELL_TIME_BOMB = 51121, //Deals arcane damage to a random player, and after 6 seconds, deals zone damage to nearby equal to the health missing of the target afflicted by the debuff. + SPELL_TIME_BOMB_2 = 59376 +}; + +enum Yells +{ + SAY_AGGRO_1 = -1578000, + SAY_AGGRO_2 = -1578001, + SAY_AGGRO_3 = -1578002, + SAY_AGGRO_4 = -1578003, + SAY_TELEPORT = -1578004, +}; + +enum eCreature +{ + NPC_PHANTASMAL_CLOUDSCRAPER = 27645, + NPC_PHANTASMAL_MAMMOTH = 27642, + NPC_PHANTASMAL_WOLF = 27644, + + NPC_PHANTASMAL_AIR = 27650, + NPC_PHANTASMAL_FIRE = 27651, + NPC_PHANTASMAL_WATER = 27653, + + NPC_PHANTASMAL_MURLOC = 27649, + NPC_PHANTASMAL_NAGAL = 27648, + NPC_PHANTASMAL_OGRE = 27647 +}; + +struct Summons +{ + uint32 uiEntry[4]; +}; + +static Summons Group[]= +{ + {NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_MAMMOTH,NPC_PHANTASMAL_WOLF}, + {NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_WATER,NPC_PHANTASMAL_FIRE}, + {NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_NAGAL,NPC_PHANTASMAL_MURLOC} +}; + +static uint32 TeleportSpells[]= +{ + SPELL_SUMMON_MENAGERIE,SPELL_SUMMON_MENAGERIE_2,SPELL_SUMMON_MENAGERIE_3 +}; + +static int32 SayAggro[]= +{ + SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4 +}; + +struct boss_uromAI : public ScriptedAI +{ + boss_uromAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + float x,y; + + bool bCanCast; + bool bCanGoBack; + + uint8 uiGroup[3]; + + uint32 uiTeleportTimer; + uint32 uiArcaneExplosionTimer; + uint32 uiCastArcaneExplosionTimer; + uint32 uiFrostBombTimer; + uint32 uiTimeBombTimer; + + void Reset() + { + if (pInstance && pInstance->GetData(DATA_VAROS_EVENT) != DONE) + DoCast(SPELL_ARCANE_SHIELD); + + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, NOT_STARTED); + + if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) == 0) + { + uiGroup[0] = 0; + uiGroup[1] = 0; + uiGroup[2] = 0; + } + + x,y = 0.0f; + bCanCast = false; + bCanGoBack = false; + + me->GetMotionMaster()->MoveIdle(); + + uiTeleportTimer = urand(30000,35000); + uiArcaneExplosionTimer = 9000; + uiCastArcaneExplosionTimer = 2000; + uiFrostBombTimer = urand(5000,8000); + uiTimeBombTimer = urand(20000,25000); + } + + void EnterCombat(Unit* pWho) + { + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, IN_PROGRESS); + + SetGroups(); + SummonGroups(); + CastTeleport(); + + if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) != 3) + pInstance->SetData(DATA_UROM_PLATAFORM,pInstance->GetData(DATA_UROM_PLATAFORM)+1); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (me->GetPositionZ() > 518.63) + DoStartNoMovement(pWho); + + if (me->GetPositionZ() < 518.63) + { + if (me->Attack(pWho, true)) + { + DoScriptText(SayAggro[3],me); + + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(pWho, 0,0); + } + } + } + + void SetGroups() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) != 0) + return; + + while (uiGroup[0] == uiGroup[1] || uiGroup[0] == uiGroup[2] || uiGroup[1] == uiGroup[2]) + { + uiGroup[0] = urand(0,2); + uiGroup[1] = urand(0,2); + uiGroup[2] = urand(0,2); + } + } + + void SetPosition(uint8 uiI) + { + switch(uiI) + { + case 0: + x = me->GetPositionX() + 4; + y = me->GetPositionY() - 4; + break; + case 1: + x = me->GetPositionX() + 4; + y = me->GetPositionY() + 4; + break; + case 2: + x = me->GetPositionX() - 4; + y = me->GetPositionY() + 4; + break; + case 3: + x = me->GetPositionX() - 4; + y = me->GetPositionY() - 4; + break; + default: + break; + } + } + + void SummonGroups() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) + return; + + for (uint8 uiI = 0; uiI < 4 ; uiI++) + { + SetPosition(uiI); + me->SummonCreature(Group[uiGroup[pInstance->GetData(DATA_UROM_PLATAFORM)]].uiEntry[uiI],x,y,me->GetPositionZ(),me->GetOrientation()); + } + } + + void CastTeleport() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) + return; + + DoScriptText(SayAggro[pInstance->GetData(DATA_UROM_PLATAFORM)],me); + DoCast(TeleportSpells[pInstance->GetData(DATA_UROM_PLATAFORM)]); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) < 2) + return; + + if (uiTeleportTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(false); + DoScriptText(SAY_TELEPORT,me); + me->GetMotionMaster()->MoveIdle(); + DoCast(SPELL_TELEPORT); + uiTeleportTimer = urand(30000,35000); + + } else uiTeleportTimer -= uiDiff; + + if (bCanCast && !me->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION)) + { + if (uiCastArcaneExplosionTimer <= uiDiff) + { + bCanCast = false; + bCanGoBack = true; + DoCastAOE(SPELL_EMPOWERED_ARCANE_EXPLOSION); + uiCastArcaneExplosionTimer = 2000; + }else uiCastArcaneExplosionTimer -= uiDiff; + } + + if (bCanGoBack) + { + if (uiArcaneExplosionTimer <= uiDiff) + { + Position pPos; + me->getVictim()->GetPosition(&pPos); + + me->NearTeleportTo(pPos.GetPositionX(),pPos.GetPositionY(),pPos.GetPositionZ(),pPos.GetOrientation()); + me->GetMotionMaster()->MoveChase(me->getVictim(),0,0); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + + bCanCast = false; + bCanGoBack = false; + uiArcaneExplosionTimer = 9000; + } else uiArcaneExplosionTimer -= uiDiff; + } + + if (!me->IsNonMeleeSpellCasted(false, true, true)) + { + if (uiFrostBombTimer <= uiDiff) + { + DoCastVictim(SPELL_FROSTBOMB); + uiFrostBombTimer = urand(5000,8000); + } else uiFrostBombTimer -= uiDiff; + + if (uiTimeBombTimer <= uiDiff) + { + if (Unit* pUnit = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pUnit,SPELL_TIME_BOMB); + + uiTimeBombTimer = urand(20000,25000); + } else uiTimeBombTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, DONE); + } + + void JustSummoned(Creature* pSummon) + { + pSummon->SetInCombatWithZone(); + } + + void LeaveCombat() + { + me->RemoveAllAuras(); + me->CombatStop(false); + me->DeleteThreatList(); + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + switch(pSpell->Id) + { + case SPELL_SUMMON_MENAGERIE: + me->SetHomePosition(968.66,1042.53,527.32,0.077); + LeaveCombat(); + break; + case SPELL_SUMMON_MENAGERIE_2: + me->SetHomePosition(1164.02,1170.85,527.321,3.66); + LeaveCombat(); + break; + case SPELL_SUMMON_MENAGERIE_3: + me->SetHomePosition(1118.31,1080.377,508.361,4.25); + LeaveCombat(); + break; + case SPELL_TELEPORT: + me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE); // with out it the npc will fall down while is casting + bCanCast = true; + break; + default: + break; + } + } +}; + +CreatureAI* GetAI_boss_urom(Creature* pCreature) +{ + return new boss_uromAI (pCreature); +} + +void AddSC_boss_urom() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_urom"; + newscript->GetAI = &GetAI_boss_urom; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp b/src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp new file mode 100644 index 00000000000..79034250a43 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + SPELL_ENERGIZE_CORES = 50785, //Damage 5938 to 6562, effec2 Triggers 54069, effect3 Triggers 56251 + SPELL_ENERGIZE_CORES_TRIGGER_1 = 54069, + SPELL_ENERGIZE_CORES_TRIGGER_2 = 56251, + SPELL_ENERGIZE_CORES_2 = 59372, //Damage 9025 to 9975, effect2 Triggers 54069, effect 56251 + SPELL_CALL_AZURE_RING_CAPTAIN = 51002, //Effect Send Event (12229) + SPELL_CALL_AZURE_RING_CAPTAIN_2 = 51006, //Effect Send Event (10665) + SPELL_CALL_AZURE_RING_CAPTAIN_3 = 51007, //Effect Send Event (18454) + SPELL_CALL_AZURE_RING_CAPTAIN_4 = 51008, //Effect Send Event (18455) + SPELL_CALL_AMPLIFY_MAGIC = 51054, + SPELL_CALL_AMPLIFY_MAGIC_2 = 59371 +}; +//not in db +enum Yells +{ + SAY_AGGRO = -1578022, + SAY_KILL_1 = -1578023, + SAY_KILL_2 = -1578024, + SAY_DEATH = -1578025, + SAY_STRIKE_1 = -1578026, + SAY_STRIKE_2 = -1578027, + SAY_STRIKE_3 = -1578028, + SAY_SPAWN = -1578029 +}; + +struct boss_varosAI : public ScriptedAI +{ + boss_varosAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, NOT_STARTED); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, IN_PROGRESS); + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, DONE); + } + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } +}; + +CreatureAI* GetAI_boss_varos(Creature* pCreature) +{ + return new boss_varosAI (pCreature); +} + +void AddSC_boss_varos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_varos"; + newscript->GetAI = &GetAI_boss_varos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp b/src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp new file mode 100644 index 00000000000..49be2385a3c --- /dev/null +++ b/src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +#define MAX_ENCOUNTER 4 + +/* The Occulus encounters: +0 - Drakos the Interrogator +1 - Varos Cloudstrider +2 - Mage-Lord Urom +3 - Ley-Guardian Eregos */ + +struct instance_oculus : public ScriptedInstance +{ + instance_oculus(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiDrakos; + uint64 uiVaros; + uint64 uiUrom; + uint64 uiEregos; + + uint8 uiPlataformUrom; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + std::list GameObjectList; + + void Initialize() + { + uiPlataformUrom = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case CREATURE_DRAKOS: + uiDrakos = pCreature->GetGUID(); + break; + case CREATURE_VAROS: + uiVaros = pCreature->GetGUID(); + break; + case CREATURE_UROM: + uiUrom = pCreature->GetGUID(); + break; + case CREATURE_EREGOS: + uiEregos = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGO, bool bAdd) + { + if (pGO->GetEntry() == GO_DRAGON_CAGE_DOOR) + { + if (DATA_DRAKOS_EVENT == DONE) + pGO->SetGoState(GO_STATE_ACTIVE); + else + pGO->SetGoState(GO_STATE_READY); + + GameObjectList.push_back(pGO->GetGUID()); + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_DRAKOS_EVENT: + m_auiEncounter[0] = data; + if (data == DONE) + OpenCageDoors(); + break; + case DATA_VAROS_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_UROM_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_EREGOS_EVENT: + m_auiEncounter[3] = data; + break; + case DATA_UROM_PLATAFORM: + uiPlataformUrom = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_DRAKOS_EVENT: return m_auiEncounter[0]; + case DATA_VAROS_EVENT: return m_auiEncounter[1]; + case DATA_UROM_EVENT: return m_auiEncounter[2]; + case DATA_EREGOS_EVENT: return m_auiEncounter[3]; + case DATA_UROM_PLATAFORM: return uiPlataformUrom; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_DRAKOS: return uiDrakos; + case DATA_VAROS: return uiVaros; + case DATA_UROM: return uiUrom; + case DATA_EREGOS: return uiEregos; + } + + return 0; + } + + void OpenCageDoors() + { + if (GameObjectList.empty()) + return; + + for (std::list::const_iterator itr = GameObjectList.begin(); itr != GameObjectList.end(); ++itr) + { + if (GameObject* pGO = instance->GetGameObject(*itr)) + pGO->SetGoState(GO_STATE_ACTIVE); + } + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "T O " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'T' && dataHead2 == 'O') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_oculus(Map* pMap) +{ + return new instance_oculus(pMap); +} + +void AddSC_instance_oculus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_oculus"; + newscript->GetInstanceData = &GetInstanceData_instance_oculus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/oculus/oculus.cpp b/src/server/scripts/Northrend/nexus/oculus/oculus.cpp new file mode 100644 index 00000000000..685583532d5 --- /dev/null +++ b/src/server/scripts/Northrend/nexus/oculus/oculus.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2006 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +#define GOSSIP_ITEM_DRAKES "So where do we go from here?" +#define GOSSIP_ITEM_BELGARISTRASZ1 "I want to fly on the wings of the Red Flight" +#define GOSSIP_ITEM_BELGARISTRASZ2 "What abilities do Ruby Drakes have?" +#define GOSSIP_ITEM_VERDISA1 "I want to fly on the wings of the Green Flight" +#define GOSSIP_ITEM_VERDISA2 "What abilities do Emerald Drakes have?" +#define GOSSIP_ITEM_ETERNOS1 "I want to fly on the wings of the Bronze Flight" +#define GOSSIP_ITEM_ETERNOS2 "What abilities do Amber Drakes have?" + +#define HAS_ESSENCE(a) ((a)->HasItemCount(ITEM_EMERALD_ESSENCE,1) || (a)->HasItemCount(ITEM_AMBER_ESSENCE,1) || (a)->HasItemCount(ITEM_RUBY_ESSENCE,1)) + +enum Drakes +{ + GOSSIP_TEXTID_DRAKES = 13267, + GOSSIP_TEXTID_BELGARISTRASZ1 = 12916, + GOSSIP_TEXTID_BELGARISTRASZ2 = 13466, + GOSSIP_TEXTID_BELGARISTRASZ3 = 13254, + GOSSIP_TEXTID_VERDISA1 = 1, + GOSSIP_TEXTID_VERDISA2 = 1, + GOSSIP_TEXTID_VERDISA3 = 1, + GOSSIP_TEXTID_ETERNOS1 = 1, + GOSSIP_TEXTID_ETERNOS2 = 1, + GOSSIP_TEXTID_ETERNOS3 = 13256, + + ITEM_EMERALD_ESSENCE = 37815, + ITEM_AMBER_ESSENCE = 37859, + ITEM_RUBY_ESSENCE = 37860, + + NPC_VERDISA = 27657, + NPC_BELGARISTRASZ = 27658, + NPC_ETERNOS = 27659 +}; + +bool GossipHello_npc_oculus_drake(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->GetInstanceData()->GetData(DATA_DRAKOS_EVENT) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DRAKES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DRAKES, pCreature->GetGUID()); + } + + return true; +} + +bool GossipSelect_npc_oculus_drake(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(pCreature->GetEntry()) + { + case NPC_VERDISA: //Verdisa + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_EMERALD_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_EMERALD_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA3, pCreature->GetGUID()); + break; + } + break; + case NPC_BELGARISTRASZ: //Belgaristrasz + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_RUBY_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_RUBY_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ3, pCreature->GetGUID()); + break; + } + break; + case NPC_ETERNOS: //Eternos + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_AMBER_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_AMBER_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS3, pCreature->GetGUID()); + break; + } + break; + } + + return true; +} + +void AddSC_oculus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_oculus_drake"; + newscript->pGossipHello = &GossipHello_npc_oculus_drake; + newscript->pGossipSelect = &GossipSelect_npc_oculus_drake; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/nexus/oculus/oculus.h b/src/server/scripts/Northrend/nexus/oculus/oculus.h new file mode 100644 index 00000000000..b212c9b8b6a --- /dev/null +++ b/src/server/scripts/Northrend/nexus/oculus/oculus.h @@ -0,0 +1,34 @@ +#ifndef DEF_OCULUS_H +#define DEF_OCULUS_H + +enum Data +{ + DATA_DRAKOS_EVENT, + DATA_VAROS_EVENT, + DATA_UROM_EVENT, + DATA_EREGOS_EVENT, + DATA_UROM_PLATAFORM +}; + +enum Data64 +{ + DATA_DRAKOS, + DATA_VAROS, + DATA_UROM, + DATA_EREGOS +}; + +enum Bosses +{ + CREATURE_DRAKOS = 27654, + CREATURE_VAROS = 27447, + CREATURE_UROM = 27655, + CREATURE_EREGOS = 27656 +}; + +enum GameObjects +{ + GO_DRAGON_CAGE_DOOR = 193995 +}; + +#endif diff --git a/src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp new file mode 100644 index 00000000000..3e24aaeb6c0 --- /dev/null +++ b/src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp @@ -0,0 +1,1421 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "obsidian_sanctum.h" + +enum eEnums +{ + //Sartharion Yell + SAY_SARTHARION_AGGRO = -1615018, + SAY_SARTHARION_BERSERK = -1615019, + SAY_SARTHARION_BREATH = -1615020, + SAY_SARTHARION_CALL_SHADRON = -1615021, + SAY_SARTHARION_CALL_TENEBRON = -1615022, + SAY_SARTHARION_CALL_VESPERON = -1615023, + SAY_SARTHARION_DEATH = -1615024, + SAY_SARTHARION_SPECIAL_1 = -1615025, + SAY_SARTHARION_SPECIAL_2 = -1615026, + SAY_SARTHARION_SPECIAL_3 = -1615027, + SAY_SARTHARION_SPECIAL_4 = -1615028, + SAY_SARTHARION_SLAY_1 = -1615029, + SAY_SARTHARION_SLAY_2 = -1615030, + SAY_SARTHARION_SLAY_3 = -1615031, + + WHISPER_LAVA_CHURN = -1615032, + + WHISPER_SHADRON_DICIPLE = -1615008, + WHISPER_VESPERON_DICIPLE = -1615041, + WHISPER_HATCH_EGGS = -1615017, + WHISPER_OPEN_PORTAL = -1615042, // whisper, shared by two dragons + + //Sartharion Spells + SPELL_BERSERK = 61632, // Increases the caster's attack speed by 150% and all damage it deals by 500% for 5 min. + SPELL_CLEAVE = 56909, // Inflicts 35% weapon damage to an enemy and its nearest allies, affecting up to 10 targets. + SPELL_FLAME_BREATH = 56908, // Inflicts 8750 to 11250 Fire damage to enemies in a cone in front of the caster. + SPELL_FLAME_BREATH_H = 58956, // Inflicts 10938 to 14062 Fire damage to enemies in a cone in front of the caster. + SPELL_TAIL_LASH = 56910, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec. + SPELL_TAIL_LASH_H = 58957, // A sweeping tail strike hits all enemies behind the caster, inflicting 4375 to 5625 damage and stunning them for 2 sec. + SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%. + SPELL_LAVA_STRIKE = 57571, // (Real spell casted should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572) + SPELL_TWILIGHT_REVENGE = 60639, + + SPELL_PYROBUFFET = 56916, // currently used for hard enrage after 15 minutes + SPELL_PYROBUFFET_RANGE = 58907, // possibly used when player get too far away from dummy creatures (2x Creature entry 30494) + + SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO + SPELL_TWILIGHT_SHIFT = 57874, // Twilight Shift Aura + SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase + SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave) + + //Mini bosses common spells + SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase + + //Miniboses (Vesperon, Shadron, Tenebron) + SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster. + SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster. + + SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec. + SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec. + + //Vesperon + //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times + NPC_ACOLYTE_OF_VESPERON = 31219, // Acolyte of Vesperon + SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%. + SPELL_TWILIGHT_TORMENT_VESP = 57948, // (Shadow only) trigger 57935 then 57988 + SPELL_TWILIGHT_TORMENT_VESP_ACO = 58853, // (Fire and Shadow) trigger 58835 then 57988 + + //Shadron + //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times + NPC_ACOLYTE_OF_SHADRON = 31218, // Acolyte of Shadron + SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%. + SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron + SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion + SPELL_VOID_BLAST = 57581, // Twilight Fissure + SPELL_VOID_BLAST_H = 59128, + + //Tenebron + //in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708 + SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%. + //Tenebron, dummy spell + SPELL_SUMMON_TWILIGHT_WHELP = 58035, // doesn't work, will spawn NPC_TWILIGHT_WHELP + SPELL_SUMMON_SARTHARION_TWILIGHT_WHELP = 58826, // doesn't work, will spawn NPC_SHARTHARION_TWILIGHT_WHELP + + SPELL_HATCH_EGGS_H = 59189, + SPELL_HATCH_EGGS = 58542, + SPELL_HATCH_EGGS_EFFECT_H = 59190, + SPELL_HATCH_EGGS_EFFECT = 58685, + NPC_TWILIHT_WHELP = 31214, + NPC_TWILIGHT_EGG = 30882, + + //Whelps + NPC_TWILIGHT_WHELP = 30890, + NPC_SHARTHARION_TWILIGHT_WHELP = 31214, + SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s + + //flame tsunami + SPELL_FLAME_TSUNAMI = 57494, // the visual dummy + SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction + SPELL_FLAME_TSUNAMI_DMG_AURA = 57492, // periodic damage, npc has this aura + + NPC_FLAME_TSUNAMI = 30616, // for the flame waves + NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike + + //using these custom points for dragons start and end + POINT_ID_INIT = 100, + POINT_ID_LAND = 200, + + //Achievements + ACHIEV_TWILIGHT_ASSIST = 2049, + H_ACHIEV_TWILIGHT_ASSIST = 2052, + ACHIEV_TWILIGHT_DUO = 2050, + H_ACHIEV_TWILIGHT_DUO = 2053, + ACHIEV_TWILIGHT_ZONE = 2051, + H_ACHIEV_TWILIGHT_ZONE = 2054 +}; + +struct Waypoint +{ + float m_fX, m_fY, m_fZ; +}; +struct Location +{ + float x,y,z; +}; +struct Locations +{ + float x,y,z; +}; + +//each dragons special points. First where fly to before connect to connon, second where land point is. +Waypoint m_aTene[]= +{ + {3212.854, 575.597, 109.856}, //init + {3246.425, 565.367, 61.249} //end +}; + +Waypoint m_aShad[]= +{ + {3293.238, 472.223, 106.968}, + {3271.669, 526.907, 61.931} +}; + +Waypoint m_aVesp[]= +{ + {3193.310, 472.861, 102.697}, + {3227.268, 533.238, 59.995} +}; + +#define MAX_WAYPOINT 6 +//points around raid "isle", counter clockwise. should probably be adjusted to be more alike +Waypoint m_aDragonCommon[MAX_WAYPOINT]= +{ + {3214.012, 468.932, 98.652}, + {3244.950, 468.427, 98.652}, + {3283.520, 496.869, 98.652}, + {3287.316, 555.875, 98.652}, + {3250.479, 585.827, 98.652}, + {3209.969, 566.523, 98.652} +}; +static Location FlameRight1Spawn = { 3197.59, 495.336, 57.8462 }; +static Location FlameRight1Direction = { 3289.28, 521.569, 55.1526 }; +static Location FlameRight2Spawn = { 3201.94, 543.324, 56.7209 }; +static Location FlameRight2Direction = { 3288.98, 549.291, 55.1232 }; +static Location FlameLeft1Spawn = { 3290.24, 521.725, 55.1238 }; +static Location FlameLeft1Direction = { 3199.94, 516.891, 57.5112 }; +static Location FlameLeft2Spawn = { 3290.33, 586.51, 55.063 }; +static Location FlameLeft2Direction = { 3195.03, 479.135, 55.6331 }; + +static Location AcolyteofShadron = { 3363.92, 534.703, 97.2683 }; +static Location AcolyteofShadron2 = { 3246.57, 551.263, 58.6164 }; +static Location AcolyteofVesperon = { 3145.68, 520.71, 89.7 }; +static Location AcolyteofVesperon2 = { 3246.57, 551.263, 58.6164 }; + +Locations TwilightEggs[] = +{ + {3219.28, 669.121 , 88.5549}, + {3221.55, 682.852 , 90.5361}, + {3239.77, 685.94 , 90.3168}, + {3250.33, 669.749 , 88.7637}, + {3246.6, 642.365 , 84.8752}, + {3233.68, 653.117 , 85.7051} +}; +Locations TwilightEggsSarth[] = +{ + {3261.75, 539.14 , 58.6082}, + {3257.41, 512.939 , 58.5432}, + {3231.04, 498.281 , 58.6439} +}; + +/*###### +## Boss Sartharion +######*/ + +struct boss_sartharionAI : public ScriptedAI +{ + boss_sartharionAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool m_bIsBerserk; + bool m_bIsSoftEnraged; + + uint32 m_uiEnrageTimer; + bool m_bIsHardEnraged; + + uint32 m_uiTenebronTimer; + uint32 m_uiShadronTimer; + uint32 m_uiVesperonTimer; + + uint32 m_uiFlameTsunamiTimer; + uint32 m_uiFlameBreathTimer; + uint32 m_uiTailSweepTimer; + uint32 m_uiCleaveTimer; + uint32 m_uiLavaStrikeTimer; + + bool m_bHasCalledTenebron; + bool m_bHasCalledShadron; + bool m_bHasCalledVesperon; + + uint32 achievProgress; + + void Reset() + { + m_bIsBerserk = false; + m_bIsSoftEnraged = false; + + m_uiEnrageTimer = 15*MINUTE*IN_MILISECONDS; + m_bIsHardEnraged = false; + + m_uiTenebronTimer = 30000; + m_uiShadronTimer = 75000; + m_uiVesperonTimer = 120000; + + m_uiFlameTsunamiTimer = 30000; + m_uiFlameBreathTimer = 20000; + m_uiTailSweepTimer = 20000; + m_uiCleaveTimer = 7000; + m_uiLavaStrikeTimer = 5000; + + m_bHasCalledTenebron = false; + m_bHasCalledShadron = false; + m_bHasCalledVesperon = false; + + if (me->HasAura(SPELL_TWILIGHT_REVENGE)) + me->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE); + + me->ResetLootMode(); + + achievProgress = 0; + } + + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(TYPE_SARTHARION_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_SARTHARION_AGGRO,me); + DoZoneInCombat(); + + if (pInstance) + { + pInstance->SetData(TYPE_SARTHARION_EVENT, IN_PROGRESS); + FetchDragons(); + } + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_SARTHARION_DEATH,me); + + if (pInstance) + { + if (achievProgress >= 1) + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_ASSIST,H_ACHIEV_TWILIGHT_ASSIST)); + else if (achievProgress >= 2) + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_DUO,H_ACHIEV_TWILIGHT_DUO)); + else if (achievProgress == 3) + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_ZONE,H_ACHIEV_TWILIGHT_ZONE)); + + pInstance->SetData(TYPE_SARTHARION_EVENT, DONE); + } + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SARTHARION_SLAY_1,SAY_SARTHARION_SLAY_2,SAY_SARTHARION_SLAY_3), me); + } + + // me->ResetLootMode() is called from Reset() + // AddDrakeLootMode() should only ever be called from FetchDragons(), which is called from Aggro() + void AddDrakeLootMode() + { + if (me->HasLootMode(LOOT_MODE_HARD_MODE_2)) // Has two Drake loot modes + me->AddLootMode(LOOT_MODE_HARD_MODE_3); // Add 3rd Drake loot mode + else if (me->HasLootMode(LOOT_MODE_HARD_MODE_1)) // Has one Drake loot mode + me->AddLootMode(LOOT_MODE_HARD_MODE_2); // Add 2nd Drake loot mode + else // Has no Drake loot modes + me->AddLootMode(LOOT_MODE_HARD_MODE_1); // Add 1st Drake loot mode + } + + void FetchDragons() + { + if (!pInstance) + return; + Creature* pFetchTene = Unit::GetCreature(*me, pInstance->GetData64(DATA_TENEBRON)); + Creature* pFetchShad = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON)); + Creature* pFetchVesp = Unit::GetCreature(*me, pInstance->GetData64(DATA_VESPERON)); + + //if at least one of the dragons are alive and are being called + bool bCanUseWill = false; + + if (pFetchTene && pFetchTene->isAlive() && !pFetchTene->getVictim()) + { + bCanUseWill = true; + pFetchTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ); + + if (!pFetchTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pFetchTene->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + if (pFetchShad && pFetchShad->isAlive() && !pFetchShad->getVictim()) + { + bCanUseWill = true; + pFetchShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ); + + if (!pFetchShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pFetchShad->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + if (pFetchVesp && pFetchVesp->isAlive() && !pFetchVesp->getVictim()) + { + bCanUseWill = true; + pFetchVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ); + + if (!pFetchVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pFetchVesp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + if (bCanUseWill) + DoCast(me, SPELL_WILL_OF_SARTHARION); + } + + void CallDragon(uint32 uiDataId) + { + if (pInstance) + { + if (Creature *pTemp = Unit::GetCreature(*me,pInstance->GetData64(uiDataId))) + { + if (pTemp->isAlive() && !pTemp->getVictim()) + { + if (pTemp->HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE)) + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + if (pTemp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + int32 iTextId = 0; + AddDrakeLootMode(); + + achievProgress++; + + switch(pTemp->GetEntry()) + { + case NPC_TENEBRON: + iTextId = SAY_SARTHARION_CALL_TENEBRON; + pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aTene[1].m_fX, m_aTene[1].m_fY, m_aTene[1].m_fZ); + break; + case NPC_SHADRON: + iTextId = SAY_SARTHARION_CALL_SHADRON; + pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aShad[1].m_fX, m_aShad[1].m_fY, m_aShad[1].m_fZ); + break; + case NPC_VESPERON: + iTextId = SAY_SARTHARION_CALL_VESPERON; + pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aVesp[1].m_fX, m_aVesp[1].m_fY, m_aVesp[1].m_fZ); + break; + } + + DoScriptText(iTextId, me); + } + } + } + } + + void SendFlameTsunami() + { + if (Map* pMap = me->GetMap()) + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource() && i->getSource()->isAlive()) + DoScriptText(WHISPER_LAVA_CHURN, me, i->getSource()); + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + Unit* pTene = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_TENEBRON) : 0); + Unit* pShad = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SHADRON) : 0); + Unit* pVesp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_VESPERON) : 0); + + //spell will target dragons, if they are still alive at 35% + if (!m_bIsBerserk && (me->GetHealth()*100 / me->GetMaxHealth()) <= 35 + && ((pTene && pTene->isAlive()) || (pShad && pShad->isAlive()) || (pVesp && pVesp->isAlive()))) + { + DoScriptText(SAY_SARTHARION_BERSERK, me); + DoCast(me, SPELL_BERSERK); + m_bIsBerserk = true; + } + + //soft enrage + if (!m_bIsSoftEnraged && (me->GetHealth()*100 / me->GetMaxHealth()) <= 10) + { + // TODO + m_bIsSoftEnraged = true; + } + + // hard enrage + if (!m_bIsHardEnraged) + { + if (m_uiEnrageTimer <= uiDiff) + { + DoCast(me, SPELL_PYROBUFFET, true); + m_bIsHardEnraged = true; + } + else + m_uiEnrageTimer -= uiDiff; + } + + // flame tsunami + if (m_uiFlameTsunamiTimer <= uiDiff) + { + SendFlameTsunami(); + switch(urand(0,1)) + { + case 0: + { + if (Creature *Right1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight1Spawn.x, FlameRight1Spawn.y , FlameRight1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) + Right1->GetMotionMaster()->MovePoint(0, FlameRight1Direction.x, FlameRight1Direction.y, FlameRight1Direction.z); + if (Creature *Right2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight2Spawn.x, FlameRight2Spawn.y , FlameRight2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) + Right2->GetMotionMaster()->MovePoint(0, FlameRight2Direction.x, FlameRight2Direction.y, FlameRight2Direction.z); + break; + } + case 1: + { + if (Creature *Left1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft1Spawn.x, FlameLeft1Spawn.y , FlameLeft1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) + Left1->GetMotionMaster()->MovePoint(0, FlameLeft1Direction.x, FlameLeft1Direction.y, FlameLeft1Direction.z); + if (Creature *Left2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft2Spawn.x, FlameLeft2Spawn.y , FlameLeft2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) + Left2->GetMotionMaster()->MovePoint(0, FlameLeft2Direction.x, FlameLeft2Direction.y, FlameLeft2Direction.z); + break; + } + } + + m_uiFlameTsunamiTimer = 30000; + } + else + m_uiFlameTsunamiTimer -= uiDiff; + + // flame breath + if (m_uiFlameBreathTimer <= uiDiff) + { + DoScriptText(SAY_SARTHARION_BREATH, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_FLAME_BREATH, SPELL_FLAME_BREATH_H)); + m_uiFlameBreathTimer = urand(25000,35000); + } + else + m_uiFlameBreathTimer -= uiDiff; + + // Tail Sweep + if (m_uiTailSweepTimer <= uiDiff) + { + DoCast(me->getVictim(), RAID_MODE(SPELL_TAIL_LASH, SPELL_TAIL_LASH_H)); + m_uiTailSweepTimer = urand(15000,20000); + } + else + m_uiTailSweepTimer -= uiDiff; + + // Cleave + if (m_uiCleaveTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + m_uiCleaveTimer = urand(7000,10000); + } + else + m_uiCleaveTimer -= uiDiff; + + // Lavas Strike + if (m_uiLavaStrikeTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_LAVA_STRIKE); + + if (urand(0,4) == 4) + DoScriptText(RAND(SAY_SARTHARION_SPECIAL_1,SAY_SARTHARION_SPECIAL_2,SAY_SARTHARION_SPECIAL_3), me); + } + m_uiLavaStrikeTimer = urand(5000,20000); + } + else + m_uiLavaStrikeTimer -= uiDiff; + + // call tenebron + if (!m_bHasCalledTenebron && m_uiTenebronTimer <= uiDiff) + { + CallDragon(DATA_TENEBRON); + m_bHasCalledTenebron = true; + } + else + m_uiTenebronTimer -= uiDiff; + + // call shadron + if (!m_bHasCalledShadron && m_uiShadronTimer <= uiDiff) + { + CallDragon(DATA_SHADRON); + m_bHasCalledShadron = true; + } + else + m_uiShadronTimer -= uiDiff; + + // call vesperon + if (!m_bHasCalledVesperon && m_uiVesperonTimer <= uiDiff) + { + CallDragon(DATA_VESPERON); + m_bHasCalledVesperon = true; + } + else + m_uiVesperonTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(uiDiff); + } +}; + +CreatureAI* GetAI_boss_sartharion(Creature* pCreature) +{ + return new boss_sartharionAI(pCreature); +} + +enum TeneText +{ + SAY_TENEBRON_AGGRO = -1615009, + SAY_TENEBRON_SLAY_1 = -1615010, + SAY_TENEBRON_SLAY_2 = -1615011, + SAY_TENEBRON_DEATH = -1615012, + SAY_TENEBRON_BREATH = -1615013, + SAY_TENEBRON_RESPOND = -1615014, + SAY_TENEBRON_SPECIAL_1 = -1615015, + SAY_TENEBRON_SPECIAL_2 = -1615016 +}; + +enum ShadText +{ + SAY_SHADRON_AGGRO = -1615000, + SAY_SHADRON_SLAY_1 = -1615001, + SAY_SHADRON_SLAY_2 = -1615002, + SAY_SHADRON_DEATH = -1615003, + SAY_SHADRON_BREATH = -1615004, + SAY_SHADRON_RESPOND = -1615005, + SAY_SHADRON_SPECIAL_1 = -1615006, + SAY_SHADRON_SPECIAL_2 = -1615007 +}; + +enum VespText +{ + SAY_VESPERON_AGGRO = -1615033, + SAY_VESPERON_SLAY_1 = -1615034, + SAY_VESPERON_SLAY_2 = -1615035, + SAY_VESPERON_DEATH = -1615036, + SAY_VESPERON_BREATH = -1615037, + SAY_VESPERON_RESPOND = -1615038, + SAY_VESPERON_SPECIAL_1 = -1615039, + SAY_VESPERON_SPECIAL_2 = -1615040 +}; + +//to control each dragons common abilities +struct dummy_dragonAI : public ScriptedAI +{ + dummy_dragonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 m_uiWaypointId; + uint32 m_uiMoveNextTimer; + int32 m_iPortalRespawnTime; + bool m_bCanMoveFree; + + void Reset() + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (GameObject* TwilightPortal = GameObject::GetGameObject((*me), pInstance->GetData64(GO_TWILIGHT_PORTAL))) + TwilightPortal->SetGoState(GO_STATE_READY); + + m_uiWaypointId = 0; + m_uiMoveNextTimer = 500; + m_iPortalRespawnTime = 30000; + m_bCanMoveFree = false; + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (!pInstance || uiType != POINT_MOTION_TYPE) + return; + + debug_log("dummy_dragonAI: %s reached point %u", me->GetName(), uiPointId); + + //if healers messed up the raid and we was already initialized + if (pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + { + EnterEvadeMode(); + return; + } + + //this is end, if we reach this, don't do much + if (uiPointId == POINT_ID_LAND) + { + me->GetMotionMaster()->Clear(); + m_bCanMoveFree = false; + return; + } + + //get amount of common points + uint32 uiCommonWPCount = sizeof(m_aDragonCommon)/sizeof(Waypoint); + + //increase + m_uiWaypointId = uiPointId+1; + + //if we have reached a point bigger or equal to count, it mean we must reset to point 0 + if (m_uiWaypointId >= uiCommonWPCount) + { + if (!m_bCanMoveFree) + m_bCanMoveFree = true; + + m_uiWaypointId = 0; + } + + m_uiMoveNextTimer = 500; + } + + //used when open portal and spawn mobs in phase + void DoRaidWhisper(int32 iTextId) + { + Map* pMap = me->GetMap(); + + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + DoScriptText(iTextId, me, i->getSource()); + } + } + } + + //"opens" the portal and does the "opening" whisper + void OpenPortal() + { + int32 iTextId = 0; + + //there are 4 portal spawn locations, each are expected to be spawned with negative spawntimesecs in database + + //using a grid search here seem to be more efficient than caching all four guids + //in instance script and calculate range to each. + GameObject* pPortal = me->FindNearestGameObject(GO_TWILIGHT_PORTAL,50.0f); + if (GameObject* TwilightPortal = GameObject::GetGameObject((*me), pInstance->GetData64(GO_TWILIGHT_PORTAL))) + TwilightPortal->SetGoState(GO_STATE_ACTIVE); + + switch(me->GetEntry()) + { + case NPC_TENEBRON: + { + iTextId = WHISPER_HATCH_EGGS; + if (pInstance && pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[0].x, TwilightEggs[0].y, TwilightEggs[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + else + me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggsSarth[0].x, TwilightEggsSarth[0].y, TwilightEggsSarth[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + break; + } + case NPC_SHADRON: + { + iTextId = WHISPER_OPEN_PORTAL; + if (pInstance && !pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron.x, AcolyteofShadron.y , AcolyteofShadron.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + else + me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2.x, AcolyteofShadron2.y , AcolyteofShadron2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + + break; + } + case NPC_VESPERON: + { + if (pInstance && !pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon.x, AcolyteofVesperon.y , AcolyteofVesperon.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + else + me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon2.x, AcolyteofVesperon2.y , AcolyteofVesperon2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + + iTextId = WHISPER_OPEN_PORTAL; + break; + } + } + + DoRaidWhisper(iTextId); + + //By using SetRespawnTime() we will actually "spawn" the object with our defined time. + //Once time is up, portal will disappear again. + if (pPortal && !pPortal->isSpawned()) + pPortal->SetRespawnTime(m_iPortalRespawnTime); + + //Unclear what are expected to happen if one drake has a portal open already + //Refresh respawnTime so time again are set to 30secs? + } + + void JustDied(Unit* /*pKiller*/) + { + int32 iTextId = 0; + uint32 uiSpellId = 0; + + switch(me->GetEntry()) + { + case NPC_TENEBRON: + iTextId = SAY_TENEBRON_DEATH; + uiSpellId = SPELL_POWER_OF_TENEBRON; + break; + case NPC_SHADRON: + iTextId = SAY_SHADRON_DEATH; + uiSpellId = SPELL_POWER_OF_SHADRON; + break; + case NPC_VESPERON: + iTextId = SAY_VESPERON_DEATH; + uiSpellId = SPELL_POWER_OF_VESPERON; + break; + } + + DoScriptText(iTextId, me); + + me->RemoveOwnedAura(uiSpellId); + + if (pInstance) + { + // not if solo mini-boss fight + if (pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + return; + + // Twilight Revenge to main boss + if (Unit* pSartharion = Unit::GetUnit((*me), pInstance->GetData64(DATA_SARTHARION))) + if (pSartharion->isAlive()) + DoCast(pSartharion, SPELL_TWILIGHT_REVENGE, true); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_bCanMoveFree && m_uiMoveNextTimer) + { + if (m_uiMoveNextTimer <= uiDiff) + { + if (m_uiWaypointId < MAX_WAYPOINT) + me->GetMotionMaster()->MovePoint(m_uiWaypointId, + m_aDragonCommon[m_uiWaypointId].m_fX, m_aDragonCommon[m_uiWaypointId].m_fY, m_aDragonCommon[m_uiWaypointId].m_fZ); + + debug_log("dummy_dragonAI: %s moving to point %u", me->GetName(), m_uiWaypointId); + m_uiMoveNextTimer = 0; + } + else + m_uiMoveNextTimer -= uiDiff; + } + } +}; + +/*###### +## Mob Tenebron +######*/ + +struct mob_tenebronAI : public dummy_dragonAI +{ + mob_tenebronAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} + + uint32 m_uiShadowBreathTimer; + uint32 m_uiShadowFissureTimer; + uint32 m_uiHatchEggTimer; + + void Reset() + { + m_uiShadowBreathTimer = 20000; + m_uiShadowFissureTimer = 5000; + m_uiHatchEggTimer = 30000; + } + + void Aggro(Unit* /*pWho*/) + { + DoScriptText(SAY_TENEBRON_AGGRO, me); + DoZoneInCombat(); + DoCast(me, SPELL_POWER_OF_TENEBRON); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_TENEBRON_SLAY_1,SAY_TENEBRON_SLAY_2), me); + /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + achievProgress = 1;*/ + } + + void UpdateAI(const uint32 uiDiff) + { + //if no target, update dummy and return + if (!UpdateVictim()) + { + dummy_dragonAI::UpdateAI(uiDiff); + return; + } + + // shadow fissure + if (m_uiShadowFissureTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE)); + + m_uiShadowFissureTimer = urand(15000,20000); + } + else + m_uiShadowFissureTimer -= uiDiff; + + // Hach Egg + if (m_uiHatchEggTimer <= uiDiff) + { + OpenPortal(); + m_uiHatchEggTimer = 30000; + } + else + m_uiHatchEggTimer -= uiDiff; + + // shadow breath + if (m_uiShadowBreathTimer <= uiDiff) + { + DoScriptText(SAY_TENEBRON_BREATH, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); + m_uiShadowBreathTimer = urand(20000,25000); + } + else + m_uiShadowBreathTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_tenebron(Creature* pCreature) +{ + return new mob_tenebronAI(pCreature); +} + +/*###### +## Mob Shadron +######*/ + +struct mob_shadronAI : public dummy_dragonAI +{ + mob_shadronAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} + + uint32 m_uiShadowBreathTimer; + uint32 m_uiShadowFissureTimer; + uint32 m_uiAcolyteShadronTimer; + + void Reset() + { + m_uiShadowBreathTimer = 20000; + m_uiShadowFissureTimer = 5000; + m_uiAcolyteShadronTimer = 60000; + + if (me->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) + me->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); + + if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) + me->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); + } + + void Aggro(Unit* /*pWho*/) + { + DoScriptText(SAY_SHADRON_AGGRO,me); + DoZoneInCombat(); + DoCast(me, SPELL_POWER_OF_SHADRON); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SHADRON_SLAY_1,SAY_SHADRON_SLAY_2), me); + /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + achievProgress = 2;*/ + } + + void UpdateAI(const uint32 uiDiff) + { + //if no target, update dummy and return + if (!UpdateVictim()) + { + dummy_dragonAI::UpdateAI(uiDiff); + return; + } + + // shadow fissure + if (m_uiShadowFissureTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H)); + + m_uiShadowFissureTimer = urand(15000,20000); + } + else + m_uiShadowFissureTimer -= uiDiff; + + // Portal Event + if (m_uiAcolyteShadronTimer <= uiDiff) + { + if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) + return; + + OpenPortal(); + m_uiAcolyteShadronTimer = urand(60000,65000); + } + else + m_uiAcolyteShadronTimer -= uiDiff; + + // shadow breath + if (m_uiShadowBreathTimer <= uiDiff) + { + DoScriptText(SAY_SHADRON_BREATH, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); + m_uiShadowBreathTimer = urand(20000,25000); + } + else + m_uiShadowBreathTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_shadron(Creature* pCreature) +{ + return new mob_shadronAI(pCreature); +} + +/*###### +## Mob Vesperon +######*/ + +struct mob_vesperonAI : public dummy_dragonAI +{ + mob_vesperonAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} + + uint32 m_uiShadowBreathTimer; + uint32 m_uiShadowFissureTimer; + uint32 m_uiAcolyteVesperonTimer; + + void Reset() + { + m_uiShadowBreathTimer = 20000; + m_uiShadowFissureTimer = 5000; + m_uiAcolyteVesperonTimer = 60000; + } + + void Aggro(Unit* /*pWho*/) + { + DoScriptText(SAY_VESPERON_AGGRO,me); + DoZoneInCombat(); + DoCast(me, SPELL_POWER_OF_VESPERON); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_VESPERON_SLAY_1,SAY_VESPERON_SLAY_2), me); + /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + achievProgress = 3;*/ + } + + void UpdateAI(const uint32 uiDiff) + { + //if no target, update dummy and return + if (!UpdateVictim()) + { + dummy_dragonAI::UpdateAI(uiDiff); + return; + } + + // shadow fissure + if (m_uiShadowFissureTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H)); + + m_uiShadowFissureTimer = urand(15000,20000); + } + else + m_uiShadowFissureTimer -= uiDiff; + + // Portal Event + if (m_uiAcolyteVesperonTimer <= uiDiff) + { + OpenPortal(); + DoCast(me->getVictim(), SPELL_TWILIGHT_TORMENT_VESP); + m_uiAcolyteVesperonTimer = urand(60000,70000); + } + else + m_uiAcolyteVesperonTimer -= uiDiff; + + // shadow breath + if (m_uiShadowBreathTimer <= uiDiff) + { + DoScriptText(SAY_VESPERON_BREATH, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); + m_uiShadowBreathTimer = urand(20000,25000); + } + else + m_uiShadowBreathTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_vesperon(Creature* pCreature) +{ + return new mob_vesperonAI(pCreature); +} + +/*###### +## Mob Acolyte of Shadron +######*/ + +struct mob_acolyte_of_shadronAI : public ScriptedAI +{ + mob_acolyte_of_shadronAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 uiShiftEffectTimer; + + void Reset() + { + uiShiftEffectTimer = 1000; + if (pInstance) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true); + + Creature* pSartharion = Unit::GetCreature(*me, pInstance->GetData64(DATA_SARTHARION)); + if (Creature* pShadron = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON))) + //if not solo figth, buff main boss, else place debuff on mini-boss. both spells TARGET_SCRIPT + if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + pSartharion->CastSpell(me, SPELL_GIFT_OF_TWILIGTH_SAR, true); + else + { + pShadron->CastSpell(me, SPELL_GIFT_OF_TWILIGTH_SHA,true); + pShadron->AddThreat(pTarget, 100.0f); + AttackStart(pShadron->getVictim()); + } + } + me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER,me); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + //Creature* pDebuffTarget = NULL; + Map *map = me->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT,0) && !i->getSource()->getVictim()) + { + i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_SHIFT_REMOVAL_ALL,true); + i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_RESIDUE,true); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); + } + } + } + + if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + { + //not solo fight, so main boss has deduff + Creature* pDebuffTarget = Unit::GetCreature(*me, pInstance->GetData64(DATA_SARTHARION)); + if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SAR)) + pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SAR); + } + else + { + //event not in progress, then solo fight and must remove debuff mini-boss + Creature* pDebuffTarget = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON)); + if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) + pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); + } + } + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_acolyte_of_shadron(Creature* pCreature) +{ + return new mob_acolyte_of_shadronAI(pCreature); +} + +/*###### +## Mob Acolyte of Vesperon +######*/ + +struct mob_acolyte_of_vesperonAI : public ScriptedAI +{ + mob_acolyte_of_vesperonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + { + me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER,me); + } + DoCast(me, SPELL_TWILIGHT_TORMENT_VESP_ACO); + } + + void JustDied(Unit* /*pKiller*/) + { + // remove twilight torment on Vesperon + if (pInstance) + { + Creature* pVesperon = Unit::GetCreature(*me, pInstance->GetData64(DATA_VESPERON)); + + if (pVesperon && pVesperon->isAlive() && pVesperon->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) + pVesperon->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); + + Map *map = me->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT,0) && !i->getSource()->getVictim()) + { + i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_SHIFT_REMOVAL_ALL,true); + i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_RESIDUE,true); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); + } + if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_TORMENT_VESP,0) && !i->getSource()->getVictim()) + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); + } + } + + } + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_acolyte_of_vesperon(Creature* pCreature) +{ + return new mob_acolyte_of_vesperonAI(pCreature); +} + +/*###### +## Mob Twilight Eggs +######*/ + +struct mob_twilight_eggsAI : public Scripted_NoMovementAI +{ + mob_twilight_eggsAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + uint32 m_uiFadeArmorTimer; + uint32 m_uiHatchEggTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + m_uiHatchEggTimer = 20000; + m_uiFadeArmorTimer = 1000; + } + void SpawnWhelps() + { + if (!pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + else + me->SummonCreature(NPC_SHARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + me->DealDamage(me, me->GetHealth()); + } + void UpdateAI(const uint32 uiDiff) + { + if (m_uiHatchEggTimer <= uiDiff) + { + SpawnWhelps(); + } + else + m_uiHatchEggTimer -= uiDiff; + } + void AttackStart(Unit* /*pWho*/) {} + void MoveInLineOfSight(Unit* /*pWho*/) {} +}; + +CreatureAI* GetAI_mob_twilight_eggs(Creature* pCreature) +{ + return new mob_twilight_eggsAI(pCreature); +} + +/*###### +## Flame Tzunami +######*/ +struct npc_flame_tsunamiAI : public ScriptedAI +{ + npc_flame_tsunamiAI(Creature* pCreature) : ScriptedAI(pCreature) + { + me->HasAura(SPELL_FLAME_TSUNAMI_DMG_AURA); + DoCast(me, SPELL_FLAME_TSUNAMI); + } + + uint32 Tsunami_Timer; + + void Reset() + { + Tsunami_Timer = 100; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void UpdateAI(const uint32 diff) + { + if (Tsunami_Timer <= diff) + { + DoCast(me, SPELL_FLAME_TSUNAMI_DMG_AURA); + Tsunami_Timer = 1000; + } else Tsunami_Timer -= diff; + } +}; +// Twilight Fissure +struct npc_twilight_fissureAI : public Scripted_NoMovementAI +{ + npc_twilight_fissureAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + Reset(); + } + + uint32 VoidBlast_Timer; + + void Reset() + { + VoidBlast_Timer = 5000; + } + + void UpdateAI(const uint32 diff) + { + if (VoidBlast_Timer <= diff) + { + DoCast(me->getVictim(), RAID_MODE(SPELL_VOID_BLAST, SPELL_VOID_BLAST_H)); + VoidBlast_Timer = 9000; + me->Kill(me); + } else VoidBlast_Timer -= diff; + } +}; + + +CreatureAI* GetAI_npc_flame_tsunami(Creature* pCreature) +{ + return new npc_flame_tsunamiAI(pCreature); +} + +CreatureAI* GetAI_npc_twilight_fissure(Creature* pCreature) +{ + return new npc_twilight_fissureAI(pCreature); +} + +/*###### +## Mob Twilight Whelps +######*/ + +struct mob_twilight_whelpAI : public ScriptedAI +{ + mob_twilight_whelpAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 m_uiFadeArmorTimer; + + void Reset() + { + m_uiFadeArmorTimer = 1000; + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // twilight torment + if (m_uiFadeArmorTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_FADE_ARMOR); + m_uiFadeArmorTimer = urand(5000,10000); + } + else + m_uiFadeArmorTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_twilight_whelp(Creature* pCreature) +{ + return new mob_twilight_whelpAI(pCreature); +} + +void AddSC_boss_sartharion() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sartharion"; + newscript->GetAI = &GetAI_boss_sartharion; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vesperon"; + newscript->GetAI = &GetAI_mob_vesperon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadron"; + newscript->GetAI = &GetAI_mob_shadron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tenebron"; + newscript->GetAI = &GetAI_mob_tenebron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_acolyte_of_shadron"; + newscript->GetAI = &GetAI_mob_acolyte_of_shadron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_acolyte_of_vesperon"; + newscript->GetAI = &GetAI_mob_acolyte_of_vesperon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_twilight_eggs"; + newscript->GetAI = &GetAI_mob_twilight_eggs; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_flame_tsunami"; + newscript->GetAI = &GetAI_npc_flame_tsunami; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_twilight_fissure"; + newscript->GetAI = &GetAI_npc_twilight_fissure; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_twilight_whelp"; + newscript->GetAI = &GetAI_mob_twilight_whelp; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp b/src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp new file mode 100644 index 00000000000..7ef8e03c779 --- /dev/null +++ b/src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp @@ -0,0 +1,97 @@ +#include "ScriptedPch.h" +#include "obsidian_sanctum.h" + +#define MAX_ENCOUNTER 1 + +/* Obsidian Sanctum encounters: +0 - Sartharion +*/ + +struct instance_obsidian_sanctum : public ScriptedInstance +{ + instance_obsidian_sanctum(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 m_uiSartharionGUID; + uint64 m_uiTenebronGUID; + uint64 m_uiShadronGUID; + uint64 m_uiVesperonGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiSartharionGUID = 0; + m_uiTenebronGUID = 0; + m_uiShadronGUID = 0; + m_uiVesperonGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_SARTHARION: + m_uiSartharionGUID = pCreature->GetGUID(); + break; + //three dragons below set to active state once created. + //we must expect bigger raid to encounter main boss, and then three dragons must be active due to grid differences + case NPC_TENEBRON: + m_uiTenebronGUID = pCreature->GetGUID(); + pCreature->setActive(true); + break; + case NPC_SHADRON: + m_uiShadronGUID = pCreature->GetGUID(); + pCreature->setActive(true); + break; + case NPC_VESPERON: + m_uiVesperonGUID = pCreature->GetGUID(); + pCreature->setActive(true); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + if (uiType == TYPE_SARTHARION_EVENT) + m_auiEncounter[0] = uiData; + } + + uint32 GetData(uint32 uiType) + { + if (uiType == TYPE_SARTHARION_EVENT) + return m_auiEncounter[0]; + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_SARTHARION: + return m_uiSartharionGUID; + case DATA_TENEBRON: + return m_uiTenebronGUID; + case DATA_SHADRON: + return m_uiShadronGUID; + case DATA_VESPERON: + return m_uiVesperonGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_obsidian_sanctum(Map* pMap) +{ + return new instance_obsidian_sanctum(pMap); +} + +void AddSC_instance_obsidian_sanctum() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_obsidian_sanctum"; + newscript->GetInstanceData = &GetInstanceData_instance_obsidian_sanctum; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h b/src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h new file mode 100644 index 00000000000..59013174795 --- /dev/null +++ b/src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h @@ -0,0 +1,20 @@ +#ifndef DEF_OBSIDIAN_SANCTUM_H +#define DEF_OBSIDIAN_SANCTUM_H + +enum eTypes +{ + TYPE_SARTHARION_EVENT = 1, + + DATA_SARTHARION = 10, + DATA_TENEBRON = 11, + DATA_SHADRON = 12, + DATA_VESPERON = 13, + + NPC_SARTHARION = 28860, + NPC_TENEBRON = 30452, + NPC_SHADRON = 30451, + NPC_VESPERON = 30449, + GO_TWILIGHT_PORTAL = 193988 +}; + +#endif diff --git a/src/server/scripts/Northrend/sholazar_basin.cpp b/src/server/scripts/Northrend/sholazar_basin.cpp new file mode 100644 index 00000000000..b5df8998b4a --- /dev/null +++ b/src/server/scripts/Northrend/sholazar_basin.cpp @@ -0,0 +1,449 @@ +/* Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Sholazar_Basin +SD%Complete: 100 +SDComment: Quest support: 12570, 12573, 12621. +SDCategory: Sholazar_Basin +EndScriptData */ + +/* ContentData +npc_injured_rainspeaker_oracle +npc_vekjik +avatar_of_freya +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_injured_rainspeaker_oracle +######*/ + +#define GOSSIP_ITEM1 "I am ready to travel to your village now." + +enum eRainspeaker +{ + SAY_START_IRO = -1571000, + SAY_QUEST_ACCEPT_IRO = -1571001, + SAY_END_IRO = -1571002, + + QUEST_FORTUNATE_MISUNDERSTANDINGS = 12570, + FACTION_ESCORTEE_A = 774, + FACTION_ESCORTEE_H = 775 +}; + +struct npc_injured_rainspeaker_oracleAI : public npc_escortAI +{ + npc_injured_rainspeaker_oracleAI(Creature* c) : npc_escortAI(c) { c_guid = c->GetGUID(); } + + uint64 c_guid; + + void Reset() + { + me->RestoreFaction(); + // if we will have other way to assign this to only one npc remove this part + if (GUID_LOPART(me->GetGUID()) != 101030) + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 1: SetRun(); break; + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_JUMPING); + me->SetSpeed(MOVE_SWIM, 0.85f, true); + me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); + break; + case 19: + me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); + break; + case 28: + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->GroupEventHappens(QUEST_FORTUNATE_MISUNDERSTANDINGS, me); + // me->RestoreFaction(); + DoScriptText(SAY_END_IRO,me); + SetRun(false); + break; + } + } + + void JustDied(Unit* /*killer*/) + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + if (Player* pPlayer = GetPlayerForEscort()) + { + if (pPlayer->GetQuestStatus(QUEST_FORTUNATE_MISUNDERSTANDINGS) != QUEST_STATUS_COMPLETE) + pPlayer->FailQuest(QUEST_FORTUNATE_MISUNDERSTANDINGS); + } + } +}; + +bool GossipHello_npc_injured_rainspeaker_oracle(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_FORTUNATE_MISUNDERSTANDINGS) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_injured_rainspeaker_oracle(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(35.0f); + pCreature->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); + DoScriptText(SAY_START_IRO, pCreature); + + switch (pPlayer->GetTeam()){ + case ALLIANCE: + pCreature->setFaction(FACTION_ESCORTEE_A); + break; + case HORDE: + pCreature->setFaction(FACTION_ESCORTEE_H); + break; + } + } + return true; +} + +bool QuestAccept_npc_injured_rainspeaker_oracle(Player* /*pPlayer*/, Creature* pCreature, Quest const * /*_Quest*/) +{ + DoScriptText(SAY_QUEST_ACCEPT_IRO, pCreature); + return false; +} + +CreatureAI* GetAI_npc_injured_rainspeaker_oracle(Creature* pCreature) +{ + return new npc_injured_rainspeaker_oracleAI(pCreature); +} + +/*###### +## npc_vekjik +######*/ + +#define GOSSIP_VEKJIK_ITEM1 "Shaman Vekjik, I have spoken with the big-tongues and they desire peace. I have brought this offering on their behalf." +#define GOSSIP_VEKJIK_ITEM2 "No no... I had no intentions of betraying your people. I was only defending myself. it was all a misunderstanding." + +enum eVekjik +{ + GOSSIP_TEXTID_VEKJIK1 = 13137, + GOSSIP_TEXTID_VEKJIK2 = 13138, + + SAY_TEXTID_VEKJIK1 = -1000208, + + SPELL_FREANZYHEARTS_FURY = 51469, + + QUEST_MAKING_PEACE = 12573 +}; + +bool GossipHello_npc_vekjik(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_MAKING_PEACE) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VEKJIK_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VEKJIK1, pCreature->GetGUID()); + return true; + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_vekjik(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VEKJIK_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VEKJIK2, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + DoScriptText(SAY_TEXTID_VEKJIK1, pCreature, pPlayer); + pPlayer->AreaExploredOrEventHappens(QUEST_MAKING_PEACE); + pCreature->CastSpell(pPlayer, SPELL_FREANZYHEARTS_FURY, false); + break; + } + + return true; +} + +/*###### +## avatar_of_freya +######*/ + +#define GOSSIP_ITEM_AOF1 "I want to stop the Scourge as much as you do. How can I help?" +#define GOSSIP_ITEM_AOF2 "You can trust me. I am no friend of the Lich King." +#define GOSSIP_ITEM_AOF3 "I will not fail." + +enum eFreya +{ + QUEST_FREYA_PACT = 12621, + + SPELL_FREYA_CONVERSATION = 52045, + + GOSSIP_TEXTID_AVATAR1 = 13303, + GOSSIP_TEXTID_AVATAR2 = 13304, + GOSSIP_TEXTID_AVATAR3 = 13305 +}; + +bool GossipHello_npc_avatar_of_freya(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_FREYA_PACT) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR1, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_avatar_of_freya(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR2, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR3, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CastSpell(pPlayer, SPELL_FREYA_CONVERSATION, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +/*###### +## npc_geezle +######*/ + +struct npc_bushwhackerAI : public ScriptedAI +{ + npc_bushwhackerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + MoveToSummoner(); + } + + void MoveToSummoner() + { + if (me->isSummon()) + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + if (pSummoner) + me->GetMotionMaster()->MovePoint(0,pSummoner->GetPositionX(),pSummoner->GetPositionY(),pSummoner->GetPositionZ()); + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_bushwhacker(Creature* pCreature) +{ + return new npc_bushwhackerAI(pCreature); +} + +/*###### +## npc_engineer_helice +######*/ + +enum eEnums +{ + SPELL_EXPLODE_CRYSTAL = 62487, + SPELL_FLAMES = 64561, + + SAY_WP_7 = -1800047, + SAY_WP_6 = -1800048, + SAY_WP_5 = -1800049, + SAY_WP_4 = -1800050, + SAY_WP_3 = -1800051, + SAY_WP_2 = -1800052, + SAY_WP_1 = -1800053, + + QUEST_DISASTER = 12688 +}; + +struct npc_engineer_heliceAI : public npc_escortAI +{ + npc_engineer_heliceAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + uint32 m_uiChatTimer; + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + switch (i) + { + case 0: + DoScriptText(SAY_WP_2, me); + break; + case 1: + DoScriptText(SAY_WP_3, me); + me->CastSpell(5918.33, 5372.91, -98.770, SPELL_EXPLODE_CRYSTAL, true); + me->SummonGameObject(184743, 5918.33, 5372.91, -98.770, 0, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN); //approx 3 to 4 seconds + me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); + break; + case 2: + DoScriptText(SAY_WP_4, me); + break; + case 7: + DoScriptText(SAY_WP_5, me); + break; + case 8: + me->CastSpell(5887.37, 5379.39, -91.289, SPELL_EXPLODE_CRYSTAL, true); + me->SummonGameObject(184743, 5887.37, 5379.39, -91.289, 0, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN); //approx 3 to 4 seconds + me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); + break; + case 9: + DoScriptText(SAY_WP_6, me); + break; + case 13: + if (pPlayer) + { + pPlayer->GroupEventHappens(QUEST_DISASTER, me); + DoScriptText(SAY_WP_7, me); + } + break; + } + } + + void Reset() + { + m_uiChatTimer = 4000; + } + void JustDied(Unit* /*pKiller*/) + { + Player* pPlayer = GetPlayerForEscort(); + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (pPlayer) + pPlayer->FailQuest(QUEST_DISASTER); + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (m_uiChatTimer <= uiDiff) + { + m_uiChatTimer = 12000; + } + else + m_uiChatTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_engineer_helice(Creature* pCreature) +{ + return new npc_engineer_heliceAI(pCreature); +} + +bool QuestAccept_npc_engineer_helice(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_DISASTER) + { + if (npc_engineer_heliceAI* pEscortAI = CAST_AI(npc_engineer_heliceAI, pCreature->AI())) + { + pCreature->GetMotionMaster()->MoveJumpTo(0, 0.4, 0.4); + pCreature->setFaction(113); + + pEscortAI->Start(false, false, pPlayer->GetGUID()); + DoScriptText(SAY_WP_1, pCreature); + } + } + return true; +} + +void AddSC_sholazar_basin() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "npc_injured_rainspeaker_oracle"; + newscript->GetAI = &GetAI_npc_injured_rainspeaker_oracle; + newscript->pGossipHello = &GossipHello_npc_injured_rainspeaker_oracle; + newscript->pGossipSelect = &GossipSelect_npc_injured_rainspeaker_oracle; + newscript->pQuestAccept = &QuestAccept_npc_injured_rainspeaker_oracle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_vekjik"; + newscript->pGossipHello = &GossipHello_npc_vekjik; + newscript->pGossipSelect = &GossipSelect_npc_vekjik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_avatar_of_freya"; + newscript->pGossipHello = &GossipHello_npc_avatar_of_freya; + newscript->pGossipSelect = &GossipSelect_npc_avatar_of_freya; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bushwhacker"; + newscript->GetAI = &GetAI_npc_bushwhacker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_engineer_helice"; + newscript->GetAI = &GetAI_npc_engineer_helice; + newscript->pQuestAccept = &QuestAccept_npc_engineer_helice; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/storm_peaks.cpp b/src/server/scripts/Northrend/storm_peaks.cpp new file mode 100644 index 00000000000..9275e24bd2f --- /dev/null +++ b/src/server/scripts/Northrend/storm_peaks.cpp @@ -0,0 +1,491 @@ +/* Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_agnetta_tyrsdottar +######*/ + +#define SAY_AGGRO -1571003 +#define GOSSIP_AGNETTA "Skip the warmup, sister... or are you too scared to face soemeone your own size?" + +enum eAgnetta +{ + QUEST_ITS_THAT_YOUR_GOBLIN = 12969, + FACTION_HOSTILE_AT1 = 45 +}; + +struct npc_agnetta_tyrsdottarAI : public ScriptedAI +{ + npc_agnetta_tyrsdottarAI(Creature* pCreature) : ScriptedAI(pCreature) { } + + void Reset() + { + me->RestoreFaction(); + } +}; + +CreatureAI* GetAI_npc_agnetta_tyrsdottar(Creature* pCreature) +{ + return new npc_agnetta_tyrsdottarAI(pCreature); +} + +bool GossipHello_npc_agnetta_tyrsdottar(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_ITS_THAT_YOUR_GOBLIN) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AGNETTA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(13691, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_agnetta_tyrsdottar(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + DoScriptText(SAY_AGGRO, pCreature); + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(FACTION_HOSTILE_AT1); + pCreature->AI()->AttackStart(pPlayer); + } + + return true; +} + +/*###### +## npc_frostborn_scout +######*/ + +#define GOSSIP_ITEM1 "Are you okay? I've come to take you back to Frosthold if you can stand." +#define GOSSIP_ITEM2 "I'm sorry that I didn't get here sooner. What happened?" +#define GOSSIP_ITEM3 "I'll go get some help. Hang in there." + +enum eFrostbornScout +{ + QUEST_MISSING_SCOUTS = 12864 +}; + +bool GossipHello_npc_frostborn_scout(Player* pPlayer, Creature* pCreature) +{ + + if (pPlayer->GetQuestStatus(QUEST_MISSING_SCOUTS) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->PlayerTalkClass->SendGossipMenu(13611, pCreature->GetGUID()); + } + + return true; +} + +bool GossipSelect_npc_frostborn_scout(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->PlayerTalkClass->SendGossipMenu(13612, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->PlayerTalkClass->SendGossipMenu(13613, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->PlayerTalkClass->SendGossipMenu(13614, pCreature->GetGUID()); + pPlayer->AreaExploredOrEventHappens(QUEST_MISSING_SCOUTS); + break; + } + + return true; +} + +/*###### +## npc_thorim +######*/ + +#define GOSSIP_HN "Thorim?" +#define GOSSIP_SN1 "Can you tell me what became of Sif?" +#define GOSSIP_SN2 "He did more than that, Thorim. He controls Ulduar now." +#define GOSSIP_SN3 "It needn't end this way." + +enum eThorim +{ + QUEST_SIBLING_RIVALRY = 13064, + NPC_THORIM = 29445, + GOSSIP_TEXTID_THORIM1 = 13799, + GOSSIP_TEXTID_THORIM2 = 13801, + GOSSIP_TEXTID_THORIM3 = 13802, + GOSSIP_TEXTID_THORIM4 = 13803 +}; + +bool GossipHello_npc_thorim(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_SIBLING_RIVALRY) == QUEST_STATUS_INCOMPLETE) { + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM1, pCreature->GetGUID()); + return true; + } + return false; +} + +bool GossipSelect_npc_thorim(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM2, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM3, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM4, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CompleteQuest(QUEST_SIBLING_RIVALRY); + break; + } + return true; +} + +/*###### +## npc_goblin_prisoner +######*/ + +enum eGoblinPrisoner +{ + GO_RUSTY_CAGE = 191544 +}; + +struct npc_goblin_prisonerAI : public ScriptedAI +{ + npc_goblin_prisonerAI(Creature* pCreature) : ScriptedAI (pCreature){} + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + + if (GameObject* pGO = me->FindNearestGameObject(GO_RUSTY_CAGE,5.0f)) + { + if (pGO->GetGoState() == GO_STATE_ACTIVE) + pGO->SetGoState(GO_STATE_READY); + } + } + +}; + +CreatureAI* GetAI_npc_goblin_prisoner(Creature* pCreature) +{ + return new npc_goblin_prisonerAI(pCreature); +} + +/*###### +## npc_victorious_challenger +######*/ + +#define GOSSIP_CHALLENGER "Let's do this, sister." + +enum eVictoriousChallenger +{ + QUEST_TAKING_ALL_CHALLENGERS = 12971, + QUEST_DEFENDING_YOUR_TITLE = 13423, + + SPELL_SUNDER_ARMOR = 11971, + SPELL_REND_VC = 11977 +}; + +struct npc_victorious_challengerAI : public ScriptedAI +{ + npc_victorious_challengerAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 SunderArmorTimer; + uint32 RendTimer; + + void Reset() + { + me->RestoreFaction(); + + SunderArmorTimer = 10000; + RendTimer = 15000; + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (RendTimer < diff) + { + DoCast(me->getVictim(), SPELL_REND_VC, true); + RendTimer = 15000; + }else RendTimer -= diff; + + if (SunderArmorTimer < diff) + { + DoCast(me->getVictim(), SPELL_SUNDER_ARMOR, true); + SunderArmorTimer = 10000; + }else SunderArmorTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void KilledUnit(Unit* /*victim*/) + { + me->RestoreFaction(); + } + +}; + +bool GossipHello_npc_victorious_challenger(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_TAKING_ALL_CHALLENGERS) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_DEFENDING_YOUR_TITLE) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CHALLENGER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; + } + + return false; +} + +bool GossipSelect_npc_victorious_challenger(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(14); + pCreature->AI()->AttackStart(pPlayer); + } + + return true; +} + +CreatureAI* GetAI_npc_victorious_challenger(Creature* pCreature) +{ + return new npc_victorious_challengerAI(pCreature); +} + +/*###### +## npc_loklira_crone +######*/ + +#define GOSSIP_LOKLIRACRONE "Tell me about this proposal" +#define GOSSIP_LOKLIRACRONE1 "What happened then?" +#define GOSSIP_LOKLIRACRONE2 "You want me to take part in the Hyldsmeet to end the war?" +#define GOSSIP_LOKLIRACRONE3 "Very well. I'll take part in this competition." + +enum eLokliraCrone +{ + QUEST_HYLDSMEET = 12970, + + GOSSIP_TEXTID_LOK1 = 13778, + GOSSIP_TEXTID_LOK2 = 13779, + GOSSIP_TEXTID_LOK3 = 13780 +}; + +bool GossipHello_npc_loklira_crone(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_HYLDSMEET) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; + } + return false; +} + +bool GossipSelect_npc_loklira_crone(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK1, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK2, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK3, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CompleteQuest(QUEST_HYLDSMEET); + break; + } + return true; +} + +///////////////////// +///npc_injured_goblin +///////////////////// + +enum eInjuredGoblin +{ + QUEST_BITTER_DEPARTURE = 12832, + SAY_QUEST_ACCEPT = -1800042, + SAY_END_WP_REACHED = -1800043 +}; + +#define GOSSIP_ITEM_1 "I am ready, lets get you out of here" + +struct npc_injured_goblinAI : public npc_escortAI +{ + npc_injured_goblinAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + switch (i) + { + case 26: + DoScriptText(SAY_END_WP_REACHED, me, pPlayer); + break; + case 27: + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_BITTER_DEPARTURE, me); + break; + } + } + + void EnterCombat(Unit* /*pWho*/) {} + + void Reset() {} + + void JustDied(Unit* /*pKiller*/) + { + Player* pPlayer = GetPlayerForEscort(); + if (HasEscortState(STATE_ESCORT_ESCORTING) && pPlayer) + pPlayer->FailQuest(QUEST_BITTER_DEPARTURE); + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + if (!UpdateVictim()) + return; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_injured_goblin(Creature* pCreature) +{ + return new npc_injured_goblinAI(pCreature); +} + +bool GossipHello_npc_injured_goblin(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_BITTER_DEPARTURE) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->PlayerTalkClass->SendGossipMenu(9999999, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(999999, pCreature->GetGUID()); + return true; +} + +bool QuestAccept_npc_injured_goblin(Player* /*pPlayer*/, Creature* pCreature, Quest const *quest) +{ + if (quest->GetQuestId() == QUEST_BITTER_DEPARTURE) + DoScriptText(SAY_QUEST_ACCEPT, pCreature); + + return false; +} + +bool GossipSelect_npc_injured_goblin(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + npc_escortAI* pEscortAI = CAST_AI(npc_injured_goblinAI, pCreature->AI()); + + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pEscortAI->Start(true, true, pPlayer->GetGUID()); + pCreature->setFaction(113); + } + return true; +} + + +void AddSC_storm_peaks() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_agnetta_tyrsdottar"; + newscript->GetAI = &GetAI_npc_agnetta_tyrsdottar; + newscript->pGossipHello = &GossipHello_npc_agnetta_tyrsdottar; + newscript->pGossipSelect = &GossipSelect_npc_agnetta_tyrsdottar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_frostborn_scout"; + newscript->pGossipHello = &GossipHello_npc_frostborn_scout; + newscript->pGossipSelect = &GossipSelect_npc_frostborn_scout; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thorim"; + newscript->pGossipHello = &GossipHello_npc_thorim; + newscript->pGossipSelect = &GossipSelect_npc_thorim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_goblin_prisoner"; + newscript->GetAI = &GetAI_npc_goblin_prisoner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_victorious_challenger"; + newscript->GetAI = &GetAI_npc_victorious_challenger; + newscript->pGossipHello = &GossipHello_npc_victorious_challenger; + newscript->pGossipSelect = &GossipSelect_npc_victorious_challenger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_loklira_crone"; + newscript->pGossipHello = &GossipHello_npc_loklira_crone; + newscript->pGossipSelect = &GossipSelect_npc_loklira_crone; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_injured_goblin"; + newscript->GetAI = &GetAI_npc_injured_goblin; + newscript->pGossipHello = &GossipHello_npc_injured_goblin; + newscript->pGossipSelect = &GossipSelect_npc_injured_goblin; + newscript->pQuestAccept = &QuestAccept_npc_injured_goblin; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp new file mode 100644 index 00000000000..c2da2a24e71 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp @@ -0,0 +1,432 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss General Bjarngrim +SD%Complete: 70% +SDComment: Waypoint needed, we expect boss to always have 2x Stormforged Lieutenant following +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + //Yell + SAY_AGGRO = -1602000, + SAY_SLAY_1 = -1602001, + SAY_SLAY_2 = -1602002, + SAY_SLAY_3 = -1602003, + SAY_DEATH = -1602004, + SAY_BATTLE_STANCE = -1602005, + EMOTE_BATTLE_STANCE = -1602006, + SAY_BERSEKER_STANCE = -1602007, + EMOTE_BERSEKER_STANCE = -1602008, + SAY_DEFENSIVE_STANCE = -1602009, + EMOTE_DEFENSIVE_STANCE = -1602010, + + SPELL_DEFENSIVE_STANCE = 53790, + //SPELL_DEFENSIVE_AURA = 41105, + SPELL_SPELL_REFLECTION = 36096, + SPELL_PUMMEL = 12555, + SPELL_KNOCK_AWAY = 52029, + SPELL_IRONFORM = 52022, + + SPELL_BERSEKER_STANCE = 53791, + //SPELL_BERSEKER_AURA = 41107, + SPELL_INTERCEPT = 58769, + SPELL_WHIRLWIND = 52027, + SPELL_CLEAVE = 15284, + + SPELL_BATTLE_STANCE = 53792, + //SPELL_BATTLE_AURA = 41106, + SPELL_MORTAL_STRIKE = 16856, + SPELL_SLAM = 52026, + + //OTHER SPELLS + //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other + //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above + + NPC_STORMFORGED_LIEUTENANT = 29240, + SPELL_ARC_WELD = 59085, + SPELL_RENEW_STEEL_N = 52774, + SPELL_RENEW_STEEL_H = 59160, + + EQUIP_SWORD = 37871, + EQUIP_SHIELD = 35642, + EQUIP_MACE = 43623, + + STANCE_DEFENSIVE = 0, + STANCE_BERSERKER = 1, + STANCE_BATTLE = 2 +}; + +/*###### +## boss_bjarngrim +######*/ + +struct boss_bjarngrimAI : public ScriptedAI +{ + boss_bjarngrimAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + m_uiStance = STANCE_DEFENSIVE; + memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID)); + } + + ScriptedInstance* m_pInstance; + + bool m_bIsChangingStance; + + uint8 m_uiChargingStatus; + uint8 m_uiStance; + + uint32 m_uiCharge_Timer; + uint32 m_uiChangeStance_Timer; + + uint32 m_uiReflection_Timer; + uint32 m_uiKnockAway_Timer; + uint32 m_uiPummel_Timer; + uint32 m_uiIronform_Timer; + + uint32 m_uiIntercept_Timer; + uint32 m_uiWhirlwind_Timer; + uint32 m_uiCleave_Timer; + + uint32 m_uiMortalStrike_Timer; + uint32 m_uiSlam_Timer; + + uint64 m_auiStormforgedLieutenantGUID[2]; + + void Reset() + { + m_bIsChangingStance = false; + + m_uiChargingStatus = 0; + m_uiCharge_Timer = 1000; + + m_uiChangeStance_Timer = 20000 + rand()%5000; + + m_uiReflection_Timer = 8000; + m_uiKnockAway_Timer = 20000; + m_uiPummel_Timer = 10000; + m_uiIronform_Timer = 25000; + + m_uiIntercept_Timer = 5000; + m_uiWhirlwind_Timer = 10000; + m_uiCleave_Timer = 8000; + + m_uiMortalStrike_Timer = 8000; + m_uiSlam_Timer = 10000; + + for (uint8 i = 0; i < 2; ++i) + { + if (Creature* pStormforgedLieutenant = (Unit::GetCreature((*me), m_auiStormforgedLieutenantGUID[i]))) + { + if (!pStormforgedLieutenant->isAlive()) + pStormforgedLieutenant->Respawn(); + } + } + + if (m_uiStance != STANCE_DEFENSIVE) + { + DoRemoveStanceAura(m_uiStance); + DoCast(me, SPELL_DEFENSIVE_STANCE); + m_uiStance = STANCE_DEFENSIVE; + } + + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + //must get both lieutenants here and make sure they are with him + me->CallForHelp(30.0f); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, DONE); + } + + //TODO: remove when removal is done by the core + void DoRemoveStanceAura(uint8 uiStance) + { + switch(uiStance) + { + case STANCE_DEFENSIVE: + me->RemoveAurasDueToSpell(SPELL_DEFENSIVE_STANCE); + break; + case STANCE_BERSERKER: + me->RemoveAurasDueToSpell(SPELL_BERSEKER_STANCE); + break; + case STANCE_BATTLE: + me->RemoveAurasDueToSpell(SPELL_BATTLE_STANCE); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // Change stance + if (m_uiChangeStance_Timer <= uiDiff) + { + //wait for current spell to finish before change stance + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoRemoveStanceAura(m_uiStance); + + int uiTempStance = rand()%(3-1); + + if (uiTempStance >= m_uiStance) + ++uiTempStance; + + m_uiStance = uiTempStance; + + switch(m_uiStance) + { + case STANCE_DEFENSIVE: + DoScriptText(SAY_DEFENSIVE_STANCE, me); + DoScriptText(EMOTE_DEFENSIVE_STANCE, me); + DoCast(me, SPELL_DEFENSIVE_STANCE); + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); + break; + case STANCE_BERSERKER: + DoScriptText(SAY_BERSEKER_STANCE, me); + DoScriptText(EMOTE_BERSEKER_STANCE, me); + DoCast(me, SPELL_BERSEKER_STANCE); + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); + break; + case STANCE_BATTLE: + DoScriptText(SAY_BATTLE_STANCE, me); + DoScriptText(EMOTE_BATTLE_STANCE, me); + DoCast(me, SPELL_BATTLE_STANCE); + SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + break; + } + + m_uiChangeStance_Timer = 20000 + rand()%5000; + return; + } + else + m_uiChangeStance_Timer -= uiDiff; + + switch(m_uiStance) + { + case STANCE_DEFENSIVE: + { + if (m_uiReflection_Timer <= uiDiff) + { + DoCast(me, SPELL_SPELL_REFLECTION); + m_uiReflection_Timer = 8000 + rand()%1000; + } + else + m_uiReflection_Timer -= uiDiff; + + if (m_uiKnockAway_Timer <= uiDiff) + { + DoCast(me, SPELL_KNOCK_AWAY); + m_uiKnockAway_Timer = 20000 + rand()%1000; + } + else + m_uiKnockAway_Timer -= uiDiff; + + if (m_uiPummel_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_PUMMEL); + m_uiPummel_Timer = 10000 + rand()%1000; + } + else + m_uiPummel_Timer -= uiDiff; + + if (m_uiIronform_Timer <= uiDiff) + { + DoCast(me, SPELL_IRONFORM); + m_uiIronform_Timer = 25000 + rand()%1000; + } + else + m_uiIronform_Timer -= uiDiff; + + break; + } + case STANCE_BERSERKER: + { + if (m_uiIntercept_Timer <= uiDiff) + { + //not much point is this, better random target and more often? + DoCast(me->getVictim(), SPELL_INTERCEPT); + m_uiIntercept_Timer = 45000 + rand()%1000; + } + else + m_uiIntercept_Timer -= uiDiff; + + if (m_uiWhirlwind_Timer <= uiDiff) + { + DoCast(me, SPELL_WHIRLWIND); + m_uiWhirlwind_Timer = 10000 + rand()%1000; + } + else + m_uiWhirlwind_Timer -= uiDiff; + + if (m_uiCleave_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + m_uiCleave_Timer = 8000 + rand()%1000; + } + else + m_uiCleave_Timer -= uiDiff; + + break; + } + case STANCE_BATTLE: + { + if (m_uiMortalStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + m_uiMortalStrike_Timer = 20000 + rand()%1000; + } + else + m_uiMortalStrike_Timer -= uiDiff; + + if (m_uiSlam_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SLAM); + m_uiSlam_Timer = 15000 + rand()%1000; + } + else + m_uiSlam_Timer -= uiDiff; + + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## mob_stormforged_lieutenant +######*/ + +struct mob_stormforged_lieutenantAI : public ScriptedAI +{ + mob_stormforged_lieutenantAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiArcWeld_Timer; + uint32 m_uiRenewSteel_Timer; + + void Reset() + { + m_uiArcWeld_Timer = 20000 + rand()%1000; + m_uiRenewSteel_Timer = 10000 + rand()%1000; + } + + void EnterCombat(Unit* pWho) + { + if (m_pInstance) + { + if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) + { + if (pBjarngrim->isAlive() && !pBjarngrim->getVictim()) + pBjarngrim->AI()->AttackStart(pWho); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_uiArcWeld_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_ARC_WELD); + m_uiArcWeld_Timer = 20000 + rand()%1000; + } + else + m_uiArcWeld_Timer -= uiDiff; + + if (m_uiRenewSteel_Timer <= uiDiff) + { + if (m_pInstance) + { + if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) + { + if (pBjarngrim->isAlive()) + DoCast(pBjarngrim, SPELL_RENEW_STEEL_N); + } + } + m_uiRenewSteel_Timer = 10000 + rand()%4000; + } + else + m_uiRenewSteel_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bjarngrim(Creature* pCreature) +{ + return new boss_bjarngrimAI(pCreature); +} + +CreatureAI* GetAI_mob_stormforged_lieutenant(Creature* pCreature) +{ + return new mob_stormforged_lieutenantAI(pCreature); +} + +void AddSC_boss_bjarngrim() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_bjarngrim"; + newscript->GetAI = &GetAI_boss_bjarngrim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stormforged_lieutenant"; + newscript->GetAI = &GetAI_mob_stormforged_lieutenant; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp new file mode 100644 index 00000000000..ecf61188b3e --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp @@ -0,0 +1,388 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: Timer check pending + */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum Spells +{ + SPELL_BALL_LIGHTNING = 52780, + H_SPELL_BALL_LIGHTNING = 59800, + SPELL_STATIC_OVERLOAD = 52658, + H_SPELL_STATIC_OVERLOAD = 59795, + + SPELL_DISPERSE = 52770, + SPELL_SUMMON_SPARK = 52746, + SPELL_SPARK_DESPAWN = 52776, + + //Spark of Ionar + SPELL_SPARK_VISUAL_TRIGGER = 52667, + H_SPELL_SPARK_VISUAL_TRIGGER = 59833 +}; + +enum Yells +{ + SAY_AGGRO = -1602011, + SAY_SLAY_1 = -1602012, + SAY_SLAY_2 = -1602013, + SAY_SLAY_3 = -1602014, + SAY_DEATH = -1602015, + SAY_SPLIT_1 = -1602016, + SAY_SPLIT_2 = -1602017 +}; + +enum Creatures +{ + NPC_SPARK_OF_IONAR = 28926 +}; + +enum Misc +{ + DATA_MAX_SPARKS = 5, + DATA_MAX_SPARK_DISTANCE = 90, // Distance to boss - prevent runs through the whole instance + DATA_POINT_CALLBACK = 0 +}; + +/*###### +## Boss Ionar +######*/ + +struct boss_ionarAI : public ScriptedAI +{ + boss_ionarAI(Creature *pCreature) : ScriptedAI(pCreature), lSparkList(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + SummonList lSparkList; + + bool bIsSplitPhase; + bool bHasDispersed; + + uint32 uiSplitTimer; + + uint32 uiStaticOverloadTimer; + uint32 uiBallLightningTimer; + + uint32 uiDisperseHealth; + + void Reset() + { + lSparkList.DespawnAll(); + + bIsSplitPhase = true; + bHasDispersed = false; + + uiSplitTimer = 25*IN_MILISECONDS; + + uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); + uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); + + uiDisperseHealth = 45 + urand(0,10); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + if (me->GetVisibility() == VISIBILITY_OFF) + me->SetVisibility(VISIBILITY_ON); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + lSparkList.DespawnAll(); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + //make sparks come back + void CallBackSparks() + { + //should never be empty here, but check + if (lSparkList.empty()) + return; + + Position pos; + me->GetPosition(&pos); + + for (std::list::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) + { + if (Creature* pSpark = Unit::GetCreature(*me, *itr)) + { + if (pSpark->isAlive()) + { + pSpark->SetSpeed(MOVE_RUN, 2.0f); + pSpark->GetMotionMaster()->Clear(); + pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); + } + else + pSpark->ForcedDespawn(); + } + } + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + if (me->GetVisibility() == VISIBILITY_OFF) + uiDamage = 0; + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) + { + lSparkList.Summon(pSummoned); + + pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER,H_SPELL_SPARK_VISUAL_TRIGGER), true); + + Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + pSummoned->SetInCombatWith(pTarget); + pSummoned->GetMotionMaster()->Clear(); + pSummoned->GetMotionMaster()->MoveFollow(pTarget, 0.0f, 0.0f); + } + } + } + + void SummonedCreatureDespawn(Creature *pSummoned) + { + if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) + lSparkList.Despawn(pSummoned); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // Splitted + if (me->GetVisibility() == VISIBILITY_OFF) + { + if (uiSplitTimer <= uiDiff) + { + uiSplitTimer = 2.5*IN_MILISECONDS; + + // Return sparks to where Ionar splitted + if (bIsSplitPhase) + { + CallBackSparks(); + bIsSplitPhase = false; + } + // Lightning effect and restore Ionar + else if (lSparkList.empty()) + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + DoCast(me, SPELL_SPARK_DESPAWN, false); + + uiSplitTimer = 25*IN_MILISECONDS; + bIsSplitPhase = true; + + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + } + else + uiSplitTimer -= uiDiff; + + return; + } + + if (uiStaticOverloadTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_STATIC_OVERLOAD); + + uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); + } + else + uiStaticOverloadTimer -= uiDiff; + + if (uiBallLightningTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); + uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); + } + else + uiBallLightningTimer -= uiDiff; + + // Health check + if (!bHasDispersed && HealthBelowPct(uiDisperseHealth)) + { + bHasDispersed = true; + + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me, SPELL_DISPERSE, true); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ionar(Creature* pCreature) +{ + return new boss_ionarAI(pCreature); +} + +bool EffectDummyCreature_boss_ionar(Unit* /*pCaster*/, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_DISPERSE && uiEffIndex == 0) + { + if (pCreatureTarget->GetEntry() != NPC_IONAR) + return true; + + for (uint8 i = 0; i < DATA_MAX_SPARKS; ++i) + pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true); + + pCreatureTarget->AttackStop(); + pCreatureTarget->SetVisibility(VISIBILITY_OFF); + pCreatureTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + pCreatureTarget->GetMotionMaster()->Clear(); + pCreatureTarget->GetMotionMaster()->MoveIdle(); + + //always return true when we are handling this spell and effect + return true; + } + return false; +} + +/*###### +## mob_spark_of_ionar +######*/ + +struct mob_spark_of_ionarAI : public ScriptedAI +{ + mob_spark_of_ionarAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCheckTimer; + + void Reset() + { + uiCheckTimer = 2*IN_MILISECONDS; + me->SetReactState(REACT_PASSIVE); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE || !pInstance) + return; + + if (uiPointId == DATA_POINT_CALLBACK) + me->ForcedDespawn(); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + uiDamage = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + // Despawn if the encounter is not running + if (pInstance && pInstance->GetData(TYPE_IONAR) != IN_PROGRESS) + { + me->ForcedDespawn(); + return; + } + + // Prevent them to follow players through the whole instance + if (uiCheckTimer <= uiDiff) + { + if (pInstance) + { + Creature* pIonar = pInstance->instance->GetCreature(pInstance->GetData64(DATA_IONAR)); + if (pIonar && pIonar->isAlive()) + { + if (me->GetDistance(pIonar) > DATA_MAX_SPARK_DISTANCE) + { + Position pos; + pIonar->GetPosition(&pos); + + me->SetSpeed(MOVE_RUN, 2.0f); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); + } + } + else + me->ForcedDespawn(); + } + uiCheckTimer = 2*IN_MILISECONDS; + } + else + uiCheckTimer -= uiDiff; + + // No melee attack at all! + } +}; + +CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature) +{ + return new mob_spark_of_ionarAI(pCreature); +} + +void AddSC_boss_ionar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ionar"; + newscript->GetAI = &GetAI_boss_ionar; + newscript->pEffectDummyCreature = &EffectDummyCreature_boss_ionar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_spark_of_ionar"; + newscript->GetAI = &GetAI_mob_spark_of_ionar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp new file mode 100644 index 00000000000..f08c19efca2 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp @@ -0,0 +1,222 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Loken +SD%Complete: 60% +SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414) +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + ACHIEV_TIMELY_DEATH_START_EVENT = 20384, + + SAY_AGGRO = -1602018, + SAY_INTRO_1 = -1602019, + SAY_INTRO_2 = -1602020, + SAY_SLAY_1 = -1602021, + SAY_SLAY_2 = -1602022, + SAY_SLAY_3 = -1602023, + SAY_DEATH = -1602024, + SAY_NOVA_1 = -1602025, + SAY_NOVA_2 = -1602026, + SAY_NOVA_3 = -1602027, + SAY_75HEALTH = -1602028, + SAY_50HEALTH = -1602029, + SAY_25HEALTH = -1602030, + EMOTE_NOVA = -1602031, + + SPELL_ARC_LIGHTNING = 52921, + SPELL_LIGHTNING_NOVA_N = 52960, + SPELL_LIGHTNING_NOVA_H = 59835, + + SPELL_PULSING_SHOCKWAVE_N = 52961, + SPELL_PULSING_SHOCKWAVE_H = 59836, + SPELL_PULSING_SHOCKWAVE_AURA = 59414 +}; + +/*###### +## Boss Loken +######*/ + +struct boss_lokenAI : public ScriptedAI +{ + boss_lokenAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + bool m_bIsAura; + + uint32 m_uiArcLightning_Timer; + uint32 m_uiLightningNova_Timer; + uint32 m_uiPulsingShockwave_Timer; + uint32 m_uiResumePulsingShockwave_Timer; + + uint32 m_uiHealthAmountModifier; + + void Reset() + { + m_bIsAura = false; + + m_uiArcLightning_Timer = 15000; + m_uiLightningNova_Timer = 20000; + m_uiPulsingShockwave_Timer = 2000; + m_uiResumePulsingShockwave_Timer = 15000; + + m_uiHealthAmountModifier = 1; + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS); + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); + } + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_LOKEN, DONE); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_bIsAura) + { + // workaround for PULSING_SHOCKWAVE + if (m_uiPulsingShockwave_Timer <= uiDiff) + { + Map* pMap = me->GetMap(); + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack()) + { + int32 dmg; + float m_fDist = me->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()); + + dmg = DUNGEON_MODE(100, 150); // need to correct damage + if (m_fDist > 1.0f) // Further from 1 yard + dmg *= m_fDist; + + me->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false); + } + } + m_uiPulsingShockwave_Timer = 2000; + } else m_uiPulsingShockwave_Timer -= uiDiff; + } + else + { + if (m_uiResumePulsingShockwave_Timer <= uiDiff) + { + //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement? + DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); + + DoCast(me, SPELL_PULSING_SHOCKWAVE_N); // need core support + m_bIsAura = true; + m_uiResumePulsingShockwave_Timer = 0; + } + else + m_uiResumePulsingShockwave_Timer -= uiDiff; + } + + if (m_uiArcLightning_Timer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ARC_LIGHTNING); + + m_uiArcLightning_Timer = 15000 + rand()%1000; + } + else + m_uiArcLightning_Timer -= uiDiff; + + if (m_uiLightningNova_Timer <= uiDiff) + { + DoScriptText(RAND(SAY_NOVA_1,SAY_NOVA_2,SAY_NOVA_3), me); + DoScriptText(EMOTE_NOVA, me); + DoCast(me, SPELL_LIGHTNING_NOVA_N); + + m_bIsAura = false; + m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura + m_uiLightningNova_Timer = 20000 + rand()%1000; + } + else + m_uiLightningNova_Timer -= uiDiff; + + // Health check + if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(25*m_uiHealthAmountModifier))) + { + switch(m_uiHealthAmountModifier) + { + case 1: DoScriptText(SAY_75HEALTH, me); break; + case 2: DoScriptText(SAY_50HEALTH, me); break; + case 3: DoScriptText(SAY_25HEALTH, me); break; + } + + ++m_uiHealthAmountModifier; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_loken(Creature* pCreature) +{ + return new boss_lokenAI(pCreature); +} + +void AddSC_boss_loken() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_loken"; + newscript->GetAI = &GetAI_boss_loken; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp new file mode 100644 index 00000000000..184050e3103 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp @@ -0,0 +1,478 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Volkhan +SD%Complete: 60% +SDComment: Not considered complete. Some events may fail and need further development +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + SAY_AGGRO = -1602032, + SAY_SLAY_1 = -1602033, + SAY_SLAY_2 = -1602034, + SAY_SLAY_3 = -1602035, + SAY_DEATH = -1602036, + SAY_STOMP_1 = -1602037, + SAY_STOMP_2 = -1602038, + SAY_FORGE_1 = -1602039, + SAY_FORGE_2 = -1602040, + EMOTE_TO_ANVIL = -1602041, + EMOTE_SHATTER = -1602042, + + SPELL_HEAT_N = 52387, + SPELL_HEAT_H = 59528, + SPELL_SHATTERING_STOMP_N = 52237, + SPELL_SHATTERING_STOMP_H = 59529, + + //unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on: + SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil + SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss + + //SPELL_TEMPER_VISUAL = 52661, //summons GO + + SPELL_SUMMON_MOLTEN_GOLEM = 52405, + + //Molten Golem + SPELL_BLAST_WAVE = 23113, + SPELL_IMMOLATION_STRIKE_N = 52433, + SPELL_IMMOLATION_STRIKE_H = 59530, + SPELL_SHATTER_N = 52429, + SPELL_SHATTER_H = 59527, + + NPC_VOLKHAN_ANVIL = 28823, + NPC_MOLTEN_GOLEM = 28695, + NPC_BRITTLE_GOLEM = 28681, + + POINT_ID_ANVIL = 0, + MAX_GOLEM = 2, + + ACHIEVEMENT_SHATTER_RESISTANT = 2042 +}; + +/*###### +## Boss Volkhan +######*/ + +struct boss_volkhanAI : public ScriptedAI +{ + boss_volkhanAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + std::list m_lGolemGUIDList; + + bool m_bHasTemper; + bool m_bIsStriking; + bool m_bCanShatterGolem; + + uint8 GolemsShattered; + uint32 m_uiPause_Timer; + uint32 m_uiShatteringStomp_Timer; + uint32 m_uiShatter_Timer; + + uint32 m_uiHealthAmountModifier; + + void Reset() + { + m_bIsStriking = false; + m_bHasTemper = false; + m_bCanShatterGolem = false; + + m_uiPause_Timer = 3500; + m_uiShatteringStomp_Timer = 0; + m_uiShatter_Timer = 5000; + GolemsShattered = 0; + + m_uiHealthAmountModifier = 1; + + DespawnGolem(); + m_lGolemGUIDList.clear(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); + } + + void AttackStart(Unit* pWho) + { + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + if (!m_bHasTemper) + me->GetMotionMaster()->MoveChase(pWho); + } + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + DespawnGolem(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, DONE); + + if (IsHeroic() && GolemsShattered < 5) + { + AchievementEntry const *AchievShatterResistant = GetAchievementStore()->LookupEntry(ACHIEVEMENT_SHATTER_RESISTANT); + if (AchievShatterResistant) + { + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievShatterResistant); + } + } + } + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void DespawnGolem() + { + if (m_lGolemGUIDList.empty()) + return; + + for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + } + + m_lGolemGUIDList.clear(); + } + + void ShatterGolem() + { + if (m_lGolemGUIDList.empty()) + return; + + for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + // only shatter brittle golems + if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM) + { + pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false); + GolemsShattered += 1; + } + } + } + } + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_TEMPER_DUMMY) + m_bIsStriking = true; + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_MOLTEN_GOLEM) + { + m_lGolemGUIDList.push_back(pSummoned->GetGUID()); + + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + + //why healing when just summoned? + pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, me->GetGUID()); + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_bIsStriking) + { + if (m_uiPause_Timer <= uiDiff) + { + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + { + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + + m_bHasTemper = false; + m_bIsStriking = false; + m_uiPause_Timer = 3500; + } + else + m_uiPause_Timer -= uiDiff; + + return; + } + + // When to start shatter? After 60, 40 or 20% hp? + if (!m_bHasTemper && m_uiHealthAmountModifier >= 3) + { + if (m_uiShatteringStomp_Timer <= uiDiff) + { + //should he stomp even if he has no brittle golem to shatter? + + DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2), me); + + DoCast(me, SPELL_SHATTERING_STOMP_N); + + DoScriptText(EMOTE_SHATTER, me); + + m_uiShatteringStomp_Timer = 30000; + m_bCanShatterGolem = true; + } + else + m_uiShatteringStomp_Timer -= uiDiff; + } + + // Shatter Golems 3 seconds after Shattering Stomp + if (m_bCanShatterGolem) + { + if (m_uiShatter_Timer <= uiDiff) + { + ShatterGolem(); + m_uiShatter_Timer = 3000; + m_bCanShatterGolem = false; + } + else + m_uiShatter_Timer -= uiDiff; + } + + // Health check + if (!m_bCanShatterGolem && (me->GetHealth()*100 / me->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier))) + { + ++m_uiHealthAmountModifier; + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoScriptText(RAND(SAY_FORGE_1,SAY_FORGE_2), me); + + m_bHasTemper = true; + + DoCast(me, SPELL_TEMPER, false); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_volkhan(Creature* pCreature) +{ + return new boss_volkhanAI(pCreature); +} + +bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_TEMPER_DUMMY && uiEffIndex == 0) + { + if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN) + return true; + + for (uint8 i = 0; i < MAX_GOLEM; ++i) + { + pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true); + } + + //always return true when we are handling this spell and effect + return true; + } + + return false; +} + +/*###### +## npc_volkhan_anvil +######*/ + +bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_TEMPER && uiEffIndex == 0) + { + if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL) + return true; + + Creature *cre = CAST_CRE(pCaster); + + DoScriptText(EMOTE_TO_ANVIL, pCaster); + + float fX, fY, fZ; + pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE); + + pCaster->AttackStop(); + + if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + pCaster->GetMotionMaster()->MovementExpired(); + + cre->GetMap()->CreatureRelocation(cre, fX, fY, fZ, pCreatureTarget->GetOrientation()); + cre->SendMonsterMove(fX, fY, fZ, 0, cre->GetUnitMovementFlags(), 1); + + pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); + + //always return true when we are handling this spell and effect + return true; + } + + return false; +} + +/*###### +## mob_molten_golem +######*/ + +struct mob_molten_golemAI : public ScriptedAI +{ + mob_molten_golemAI(Creature *pCreature) : ScriptedAI(pCreature) + { + } + + bool m_bIsFrozen; + + uint32 m_uiBlast_Timer; + uint32 m_uiDeathDelay_Timer; + uint32 m_uiImmolation_Timer; + + void Reset() + { + m_bIsFrozen = false; + + m_uiBlast_Timer = 20000; + m_uiDeathDelay_Timer = 0; + m_uiImmolation_Timer = 5000; + } + + void AttackStart(Unit* pWho) + { + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + if (!m_bIsFrozen) + me->GetMotionMaster()->MoveChase(pWho); + } + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) + { + if (uiDamage > me->GetHealth()) + { + me->UpdateEntry(NPC_BRITTLE_GOLEM); + me->SetHealth(1); + uiDamage = 0; + me->RemoveAllAuras(); + me->AttackStop(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + m_bIsFrozen = true; + } + } + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + //this is the dummy effect of the spells + if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H) + { + if (me->GetEntry() == NPC_BRITTLE_GOLEM) + me->ForcedDespawn(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target or if we are frozen + if (!UpdateVictim() || m_bIsFrozen) + return; + + if (m_uiBlast_Timer <= uiDiff) + { + DoCast(me, SPELL_BLAST_WAVE); + m_uiBlast_Timer = 20000; + } + else + m_uiBlast_Timer -= uiDiff; + + if (m_uiImmolation_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_IMMOLATION_STRIKE_N); + m_uiImmolation_Timer = 5000; + } + else + m_uiImmolation_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_molten_golem(Creature* pCreature) +{ + return new mob_molten_golemAI(pCreature); +} + +void AddSC_boss_volkhan() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_volkhan"; + newscript->GetAI = &GetAI_boss_volkhan; + newscript->pEffectDummyCreature = &EffectDummyCreature_boss_volkhan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_volkhan_anvil"; + newscript->pEffectDummyCreature = &EffectDummyCreature_npc_volkhan_anvil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_molten_golem"; + newscript->GetAI = &GetAI_mob_molten_golem; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h b/src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h new file mode 100644 index 00000000000..d9739fdf888 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_HALLS_OF_LIGHTNING_H +#define DEF_HALLS_OF_LIGHTNING_H + +enum eTypes +{ + MAX_ENCOUNTER = 4, + + DATA_BJARNGRIM = 1, + DATA_IONAR = 2, + DATA_LOKEN = 3, + DATA_VOLKHAN = 4, + + TYPE_BJARNGRIM = 10, + TYPE_IONAR = 11, + TYPE_LOKEN = 12, + TYPE_VOLKHAN = 13, + + NPC_BJARNGRIM = 28586, + NPC_VOLKHAN = 28587, + NPC_IONAR = 28546, + NPC_LOKEN = 28923, + + GO_BJARNGRIM_DOOR = 191416, //_doors10 + GO_VOLKHAN_DOOR = 191325, //_doors07 + GO_IONAR_DOOR = 191326, //_doors05 + GO_LOKEN_DOOR = 191324, //_doors02 + GO_LOKEN_THRONE = 192654 +}; + +#endif diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp new file mode 100644 index 00000000000..46cd5c9cccc --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp @@ -0,0 +1,248 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Halls_of_Lightning +SD%Complete: 90% +SDComment: All ready. +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +/* Halls of Lightning encounters: +0 - General Bjarngrim +1 - Volkhan +2 - Ionar +3 - Loken +*/ + +struct instance_halls_of_lightning : public ScriptedInstance +{ + instance_halls_of_lightning(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 m_uiGeneralBjarngrimGUID; + uint64 m_uiIonarGUID; + uint64 m_uiLokenGUID; + uint64 m_uiVolkhanGUID; + + uint64 m_uiBjarngrimDoorGUID; + uint64 m_uiVolkhanDoorGUID; + uint64 m_uiIonarDoorGUID; + uint64 m_uiLokenDoorGUID; + uint64 m_uiLokenGlobeGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiGeneralBjarngrimGUID = 0; + m_uiVolkhanGUID = 0; + m_uiIonarGUID = 0; + m_uiLokenGUID = 0; + + m_uiBjarngrimDoorGUID = 0; + m_uiVolkhanDoorGUID = 0; + m_uiIonarDoorGUID = 0; + m_uiLokenDoorGUID = 0; + m_uiLokenGlobeGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_BJARNGRIM: + m_uiGeneralBjarngrimGUID = pCreature->GetGUID(); + break; + case NPC_VOLKHAN: + m_uiVolkhanGUID = pCreature->GetGUID(); + break; + case NPC_IONAR: + m_uiIonarGUID = pCreature->GetGUID(); + break; + case NPC_LOKEN: + m_uiLokenGUID = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_BJARNGRIM_DOOR: + m_uiBjarngrimDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_VOLKHAN_DOOR: + m_uiVolkhanDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_IONAR_DOOR: + m_uiIonarDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_LOKEN_DOOR: + m_uiLokenDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_LOKEN_THRONE: + m_uiLokenGlobeGUID = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_BJARNGRIM: + if (uiData == DONE) + DoUseDoorOrButton(m_uiBjarngrimDoorGUID); + m_auiEncounter[0] = uiData; + break; + case TYPE_VOLKHAN: + if (uiData == DONE) + DoUseDoorOrButton(m_uiVolkhanDoorGUID); + m_auiEncounter[1] = uiData; + break; + case TYPE_IONAR: + if (uiData == DONE) + DoUseDoorOrButton(m_uiIonarDoorGUID); + m_auiEncounter[2] = uiData; + break; + case TYPE_LOKEN: + if (uiData == DONE) + { + DoUseDoorOrButton(m_uiLokenDoorGUID); + + //Appears to be type 5 GO with animation. Need to figure out how this work, code below only placeholder + if (GameObject* pGlobe = instance->GetGameObject(m_uiLokenGlobeGUID)) + pGlobe->SetGoState(GO_STATE_ACTIVE); + } + m_auiEncounter[3] = uiData; + break; + } + + if (uiData == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_BJARNGRIM: + return m_auiEncounter[0]; + case TYPE_VOLKHAN: + return m_auiEncounter[1]; + case TYPE_IONAR: + return m_auiEncounter[2]; + case TYPE_LOKEN: + return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_BJARNGRIM: + return m_uiGeneralBjarngrimGUID; + case DATA_VOLKHAN: + return m_uiVolkhanGUID; + case DATA_IONAR: + return m_uiIonarGUID; + case DATA_LOKEN: + return m_uiLokenGUID; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H L " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'H' && dataHead2 == 'L') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_halls_of_lightning(Map* pMap) +{ + return new instance_halls_of_lightning(pMap); +} + +void AddSC_instance_halls_of_lightning() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_lightning"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_lightning; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp new file mode 100644 index 00000000000..0674b7c79eb --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp @@ -0,0 +1,148 @@ +/* Script Data Start +SDName: Boss krystallus +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_krystallus' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_BOULDER_TOSS = 50843, + H_SPELL_BOULDER_TOSS = 59742, + SPELL_GROUND_SPIKE = 59750, + SPELL_GROUND_SLAM = 50827, + SPELL_SHATTER = 50810, + H_SPELL_SHATTER = 61546, + SPELL_STOMP = 48131, + H_SPELL_STOMP = 59744 +}; + +enum Yells +{ + SAY_AGGRO = -1599007, + SAY_KILL = -1599008, + SAY_DEATH = -1599009, + SAY_SHATTER = -1599010 +}; + +struct boss_krystallusAI : public ScriptedAI +{ + boss_krystallusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBoulderTossTimer; + uint32 uiGroundSpikeTimer; + uint32 uiGroundSlamTimer; + uint32 uiShatterTimer; + uint32 uiStompTimer; + + bool bIsSlam; + + ScriptedInstance* pInstance; + + void Reset() + { + bIsSlam = false; + + uiBoulderTossTimer = 3000 + rand()%6000; + uiGroundSpikeTimer = 9000 + rand()%5000; + uiGroundSlamTimer = 15000 + rand()%3000; + uiStompTimer = 20000 + rand()%9000; + uiShatterTimer = 0; + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, NOT_STARTED); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBoulderTossTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BOULDER_TOSS); + uiBoulderTossTimer = 9000 + rand()%6000; + } else uiBoulderTossTimer -= diff; + + if (uiGroundSpikeTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_GROUND_SPIKE); + uiGroundSpikeTimer = 12000 + rand()%5000; + } else uiGroundSpikeTimer -= diff; + + if (uiStompTimer <= diff) + { + DoCast(me, SPELL_STOMP); + uiStompTimer = 20000 + rand()%9000; + } else uiStompTimer -= diff; + + if (uiGroundSlamTimer <= diff) + { + DoCast(me, SPELL_GROUND_SLAM); + bIsSlam = true; + uiShatterTimer = 10000; + uiGroundSlamTimer = 15000 + rand()%3000; + } else uiGroundSlamTimer -= diff; + + if (bIsSlam) + { + if (uiShatterTimer <= diff) + { + DoCast(me, SPELL_SHATTER); + bIsSlam = false; + } else uiShatterTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(SAY_KILL, me); + } +}; + +CreatureAI* GetAI_boss_krystallus(Creature* pCreature) +{ + return new boss_krystallusAI (pCreature); +} + +void AddSC_boss_krystallus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_krystallus"; + newscript->GetAI = &GetAI_boss_krystallus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp new file mode 100644 index 00000000000..b3c3c675347 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp @@ -0,0 +1,166 @@ +/* Script Data Start +SDName: Boss maiden_of_grief +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_maiden_of_grief' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_PARTING_SORROW = 59723, + SPELL_STORM_OF_GRIEF_N = 50752, + SPELL_STORM_OF_GRIEF_H = 59772, + SPELL_SHOCK_OF_SORROW_N = 50760, + SPELL_SHOCK_OF_SORROW_H = 59726, + SPELL_PILLAR_OF_WOE_N = 50761, + SPELL_PILLAR_OF_WOE_H = 59727 +}; + +enum Yells +{ + SAY_AGGRO = -1599000, + SAY_SLAY_1 = -1599001, + SAY_SLAY_2 = -1599002, + SAY_SLAY_3 = -1599003, + SAY_SLAY_4 = -1599004, + SAY_DEATH = -1599005, + SAY_STUN = -1599006 +}; + +enum Achievements +{ + ACHIEV_GOOD_GRIEF_START_EVENT = 20383, +}; + +struct boss_maiden_of_griefAI : public ScriptedAI +{ + boss_maiden_of_griefAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 PartingSorrowTimer; + uint32 StormOfGriefTimer; + uint32 ShockOfSorrowTimer; + uint32 PillarOfWoeTimer; + + void Reset() + { + PartingSorrowTimer = 25000 + rand()%5000; + StormOfGriefTimer = 10000; + ShockOfSorrowTimer = 20000+rand()%5000; + PillarOfWoeTimer = 5000 + rand()%10000; + + if (pInstance) + { + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAIDEN_DOOR))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, IN_PROGRESS); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (IsHeroic()) + { + if (PartingSorrowTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget) + DoCast(pTarget, SPELL_PARTING_SORROW); + + PartingSorrowTimer = 30000 + rand()%10000; + } else PartingSorrowTimer -= diff; + } + + if (StormOfGriefTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STORM_OF_GRIEF_N, true); + StormOfGriefTimer = 15000 + rand()%5000; + } else StormOfGriefTimer -= diff; + + if (ShockOfSorrowTimer <= diff) + { + DoResetThreat(); + DoScriptText(SAY_STUN, me); + DoCast(me, SPELL_SHOCK_OF_SORROW_N); + ShockOfSorrowTimer = 20000 + rand()%10000; + } else ShockOfSorrowTimer -= diff; + + if (PillarOfWoeTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if (pTarget) + DoCast(pTarget, SPELL_PILLAR_OF_WOE_N); + else + DoCast(me->getVictim(), SPELL_PILLAR_OF_WOE_N); + + PillarOfWoeTimer = 5000 + rand()%20000; + } else PillarOfWoeTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } +}; + +CreatureAI* GetAI_boss_maiden_of_grief(Creature* pCreature) +{ + return new boss_maiden_of_griefAI (pCreature); +} + +void AddSC_boss_maiden_of_grief() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_maiden_of_grief"; + newscript->GetAI = &GetAI_boss_maiden_of_grief; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp new file mode 100644 index 00000000000..68c3e34e6bf --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp @@ -0,0 +1,300 @@ +/* Script Data Start +SDName: Boss sjonnir +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_sjonnir' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_LIGHTING_RING = 51849, //Periodic Trigger (interval 2s) spell = 50841 + H_SPELL_LIGHTING_RING = 59861, //Periodic Trigger (interval 2s) spell = 59849 + SPELL_LIGHTING_RING_1 = 50840, //Periodic Trigger (interval 2s) spell = 50841 + H_SPELL_LIGHTING_RING_1 = 59848, //Periodic Trigger (interval 2s) spell = 59849 + SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835 + H_SPELL_STATIC_CHARGE = 59846, //Periodic Trigger 2s interval, spell =50847 + SPELL_CHAIN_LIGHTING = 50830, + H_SPELL_CHAIN_LIGHTING = 59844, + SPELL_LIGHTING_SHIELD = 50831, + H_SPELL_LIGHTING_SHIELD = 59845, + SPELL_FRENZY = 28747 +}; + +enum Yells +{ + SAY_AGGRO = -1599011, + SAY_SLAY_1 = -1599012, + SAY_SLAY_2 = -1599013, + SAY_SLAY_3 = -1599014, + SAY_DEATH = -1599015 +}; + +#define EMOTE_GENERIC_FRENZY -1000002 + +enum SjonnirCreatures +{ + CREATURE_FORGED_IRON_TROGG = 27979, + CREATURE_MALFORMED_OOZE = 27981, + CREATURE_FORGED_IRON_DWARF = 27982, + CREATURE_IRON_SLUDGE = 28165 +}; + +enum Misc +{ + DATA_TIME_BEFORE_OOZE = 150000, //2min 30 secs + ACHIEV_ABUSE_THE_OOZE = 2155 +}; + +struct Locations +{ + float x, y, z; +}; + +static Locations PipeLocations[] = +{ + {1295.44, 734.07, 200.3}, //left + {1297.7, 595.6, 199.9} //right +}; + +static Locations CenterPoint = {1295.21, 667.157, 189.691}; + +struct boss_sjonnirAI : public ScriptedAI +{ + boss_sjonnirAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + bool bIsFrenzy; + + uint32 uiChainLightningTimer; + uint32 uiLightningShieldTimer; + uint32 uiStaticChargeTimer; + uint32 uiLightningRingTimer; + uint32 uiSummonTimer; + uint32 uiFrenzyTimer; + uint32 uiEncounterTimer; + uint32 uiKilledIronSludges; + + SummonList lSummons; + + ScriptedInstance* pInstance; + + void Reset() + { + bIsFrenzy = false; + + uiEncounterTimer = 0; + uiChainLightningTimer = 3000 + rand()%5000; + uiLightningShieldTimer = 20000 + rand()%5000; + uiStaticChargeTimer = 20000 + rand()%5000; + uiLightningRingTimer = 30000 + rand()%5000; + uiSummonTimer = 5000; + uiFrenzyTimer = 300000; //5 minutes + uiKilledIronSludges = 0; + + lSummons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_SJONNIR_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + uiEncounterTimer = 0; + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SJONNIR_DOOR))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + pInstance->SetData(DATA_SJONNIR_EVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiChainLightningTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CHAIN_LIGHTING); + uiChainLightningTimer = 10000 + rand()%5000; + } else uiChainLightningTimer -= diff; + + if (uiLightningShieldTimer <= diff) + { + DoCast(me, SPELL_LIGHTING_SHIELD); + uiLightningShieldTimer -= diff; + } + + if (uiStaticChargeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STATIC_CHARGE); + uiStaticChargeTimer = 20000 + rand()%5000; + } uiStaticChargeTimer -= diff; + + if (uiLightningRingTimer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_LIGHTING_RING); + uiLightningRingTimer = 30000 + rand()%5000; + } else uiLightningRingTimer -= diff; + + if (uiSummonTimer <= diff) + { + uint32 uiSummonPipe = rand()%2; + me->SummonCreature(uiEncounterTimer > DATA_TIME_BEFORE_OOZE ? CREATURE_MALFORMED_OOZE : + RAND(CREATURE_FORGED_IRON_DWARF,CREATURE_FORGED_IRON_TROGG), + PipeLocations[uiSummonPipe].x, PipeLocations[uiSummonPipe].y, PipeLocations[uiSummonPipe].z, 0.0f, + TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + uiSummonTimer = 20000; + } else uiSummonTimer -= diff; + + if (!bIsFrenzy) + { + if (uiFrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + bIsFrenzy = true; + } + else uiFrenzyTimer -= diff; + } + + uiEncounterTimer +=diff; + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* summon) + { + summon->GetMotionMaster()->MovePoint(0, CenterPoint.x, CenterPoint.y, CenterPoint.z); + /*if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + summon->AI()->AttackStart(pTarget);*/ + lSummons.Summon(summon); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + lSummons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_SJONNIR_EVENT, DONE); + if (IsHeroic() && uiKilledIronSludges > 4) + pInstance->DoCompleteAchievement(ACHIEV_ABUSE_THE_OOZE); + } + } + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void KilledIronSludge() + { + ++uiKilledIronSludges; + } +}; + +CreatureAI* GetAI_boss_sjonnir(Creature* pCreature) +{ + return new boss_sjonnirAI (pCreature); +} + +struct mob_malformed_oozeAI : public ScriptedAI +{ + mob_malformed_oozeAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiMergeTimer; + + void Reset() + { + uiMergeTimer = 10000; + } + + void UpdateAI(const uint32 diff) + { + if (uiMergeTimer <= diff) + { + if (Creature* pTemp = me->FindNearestCreature(CREATURE_MALFORMED_OOZE, 3.0f, true)) + { + DoSpawnCreature(CREATURE_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + pTemp->DisappearAndDie(); + me->DisappearAndDie(); + } + uiMergeTimer = 3000; + } else uiMergeTimer -= diff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_malformed_ooze(Creature* pCreature) +{ + return new mob_malformed_oozeAI(pCreature); +} + +struct mob_iron_sludgeAI : public ScriptedAI +{ + mob_iron_sludgeAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + if (Creature* pSjonnir = Unit::GetCreature(*me, pInstance->GetData64(DATA_SJONNIR))) + CAST_AI(boss_sjonnirAI, pSjonnir->AI())->KilledIronSludge(); + } +}; + +CreatureAI* GetAI_mob_iron_sludge(Creature* pCreature) +{ + return new mob_iron_sludgeAI(pCreature); +} + +void AddSC_boss_sjonnir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sjonnir"; + newscript->GetAI = &GetAI_boss_sjonnir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_malformed_ooze"; + newscript->GetAI = &GetAI_mob_malformed_ooze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_iron_sludge"; + newscript->GetAI = &GetAI_mob_iron_sludge; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp new file mode 100644 index 00000000000..8febdaab879 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp @@ -0,0 +1,724 @@ +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "halls_of_stone.h" + +enum Texts +{ + SAY_KILL_1 = -1599016, + SAY_KILL_2 = -1599017, + SAY_KILL_3 = -1599018, + SAY_LOW_HEALTH = -1599019, + SAY_DEATH = -1599020, + SAY_PLAYER_DEATH_1 = -1599021, + SAY_PLAYER_DEATH_2 = -1599022, + SAY_PLAYER_DEATH_3 = -1599023, + SAY_ESCORT_START = -1599024, + + SAY_SPAWN_DWARF = -1599025, + SAY_SPAWN_TROGG = -1599026, + SAY_SPAWN_OOZE = -1599027, + SAY_SPAWN_EARTHEN = -1599028, + + SAY_EVENT_INTRO_1 = -1599029, + SAY_EVENT_INTRO_2 = -1599030, + SAY_EVENT_INTRO_3_ABED = -1599031, + + SAY_EVENT_A_1 = -1599032, + SAY_EVENT_A_2_KADD = -1599033, + SAY_EVENT_A_3 = -1599034, + + SAY_EVENT_B_1 = -1599035, + SAY_EVENT_B_2_MARN = -1599036, + SAY_EVENT_B_3 = -1599037, + + SAY_EVENT_C_1 = -1599038, + SAY_EVENT_C_2_ABED = -1599039, + SAY_EVENT_C_3 = -1599040, + + SAY_EVENT_D_1 = -1599041, + SAY_EVENT_D_2_ABED = -1599042, + SAY_EVENT_D_3 = -1599043, + SAY_EVENT_D_4_ABED = -1599044, + + SAY_EVENT_END_01 = -1599045, + SAY_EVENT_END_02 = -1599046, + SAY_EVENT_END_03_ABED = -1599047, + SAY_EVENT_END_04 = -1599048, + SAY_EVENT_END_05_ABED = -1599049, + SAY_EVENT_END_06 = -1599050, + SAY_EVENT_END_07_ABED = -1599051, + SAY_EVENT_END_08 = -1599052, + SAY_EVENT_END_09_KADD = -1599053, + SAY_EVENT_END_10 = -1599054, + SAY_EVENT_END_11_KADD = -1599055, + SAY_EVENT_END_12 = -1599056, + SAY_EVENT_END_13_KADD = -1599057, + SAY_EVENT_END_14 = -1599058, + SAY_EVENT_END_15_MARN = -1599059, + SAY_EVENT_END_16 = -1599060, + SAY_EVENT_END_17_MARN = -1599061, + SAY_EVENT_END_18 = -1599062, + SAY_EVENT_END_19_MARN = -1599063, + SAY_EVENT_END_20 = -1599064, + SAY_EVENT_END_21_ABED = -1599065, + + SAY_VICTORY_SJONNIR_1 = -1599066, + SAY_VICTORY_SJONNIR_2 = -1599067, + + SAY_ENTRANCE_MEET = -1599068, + + TEXT_ID_START = 13100, + TEXT_ID_PROGRESS = 13101 +}; + +enum BrannCreatures +{ + CREATURE_TRIBUNAL_OF_THE_AGES = 28234, + CREATURE_BRANN_BRONZEBEARD = 28070, + CREATURE_DARK_MATTER_TARGET = 28237, + CREATURE_SEARING_GAZE_TARGET = 28265, + CREATURE_DARK_RUNE_PROTECTOR = 27983, + CREATURE_DARK_RUNE_STORMCALLER = 27984, + CREATURE_IRON_GOLEM_CUSTODIAN = 27985, +}; + +enum Spells +{ + SPELL_STEALTH = 58506, + //Kadrak + SPELL_GLARE_OF_THE_TRIBUNAL = 50988, + H_SPELL_GLARE_OF_THE_TRIBUNAL = 59868, + //Marnak + SPELL_DARK_MATTER = 51012, + H_SPELL_DARK_MATTER = 59868, + //Abedneum + SPELL_SEARING_GAZE = 51136, + H_SPELL_SEARING_GAZE = 59867 +}; + +enum Quests +{ + QUEST_HALLS_OF_STONE = 13207 +}; + +enum Achievements +{ + ACHIEV_BRANN_SPANKIN_NEW = 2154 +}; + +#define GOSSIP_ITEM_START "Brann, it would be our honor!" +#define GOSSIP_ITEM_PROGRESS "Let's move Brann, enough of the history lessons!" + +static Position SpawnLocations[]= +{ + {946.992, 397.016, 208.374}, + {960.748, 382.944, 208.374}, +}; + +struct mob_tribuna_controllerAI : public ScriptedAI +{ + mob_tribuna_controllerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + SetCombatMovement(false); + } + + ScriptedInstance* pInstance; + + uint32 uiKaddrakEncounterTimer; + uint32 uiMarnakEncounterTimer; + uint32 uiAbedneumEncounterTimer; + + bool bKaddrakActivated; + bool bMarnakActivated; + bool bAbedneumActivated; + + std::list KaddrakGUIDList; + + void Reset() + { + uiKaddrakEncounterTimer = 1500; + uiMarnakEncounterTimer = 10000; + uiAbedneumEncounterTimer = 10000; + + bKaddrakActivated = false; + bMarnakActivated = false; + bAbedneumActivated = false; + + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); + } + + KaddrakGUIDList.clear(); + } + + void UpdateFacesList() + { + /*GetCreatureListWithEntryInGrid(lKaddrakGUIDList, me, CREATURE_KADDRAK, 50.0f); + if (!lKaddrakGUIDList.empty()) + { + uint32 uiPositionCounter = 0; + for (std::list::const_iterator itr = lKaddrakGUIDList.begin(); itr != lKaddrakGUIDList.end(); ++itr) + { + if ((*itr)->isAlive()) + { + if (uiPositionCounter == 0) + { + (*itr)->GetMap()->CreatureRelocation((*itr), 927.265, 333.200, 218.780, (*itr)->GetOrientation()); + (*itr)->SendMonsterMove(927.265, 333.200, 218.780, 0, (*itr)->GetMovementFlags(), 1); + } + else + { + (*itr)->GetMap()->CreatureRelocation((*itr), 921.745, 328.076, 218.780, (*itr)->GetOrientation()); + (*itr)->SendMonsterMove(921.745, 328.076, 218.780, 0, (*itr)->GetMovementFlags(), 1); + } + } + ++uiPositionCounter; + } + }*/ + } + + void UpdateAI(const uint32 diff) + { + if (bKaddrakActivated) + { + if (uiKaddrakEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (!KaddrakGUIDList.empty()) + for (std::list::const_iterator itr = KaddrakGUIDList.begin(); itr != KaddrakGUIDList.end(); ++itr) + { + if (Creature *pKaddrak = Unit::GetCreature(*me, *itr)) + { + if (pKaddrak->isAlive()) + pKaddrak->CastSpell(pTarget, DUNGEON_MODE(SPELL_GLARE_OF_THE_TRIBUNAL, H_SPELL_GLARE_OF_THE_TRIBUNAL), true); + } + } + uiKaddrakEncounterTimer = 1500; + } else uiKaddrakEncounterTimer -= diff; + } + if (bMarnakActivated) + { + if (uiMarnakEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature* pSummon = me->SummonCreature(CREATURE_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) + { + pSummon->SetDisplayId(11686); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_DARK_MATTER, H_SPELL_DARK_MATTER), true); + } + } + uiMarnakEncounterTimer = 30000 + rand()%1000; + } else uiMarnakEncounterTimer -= diff; + } + if (bAbedneumActivated) + { + if (uiAbedneumEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature* pSummon = me->SummonCreature(CREATURE_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) + { + pSummon->SetDisplayId(11686); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_SEARING_GAZE, H_SPELL_SEARING_GAZE), true); + } + } + uiAbedneumEncounterTimer = 30000 + rand()%1000; + } else uiAbedneumEncounterTimer -= diff; + } + } +}; + +struct npc_brann_hosAI : public npc_escortAI +{ + npc_brann_hosAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiStep; + uint32 uiPhaseTimer; + + uint64 uiControllerGUID; + std::list lDwarfGUIDList; + + ScriptedInstance* pInstance; + + bool bIsBattle; + bool bIsLowHP; + bool bHasBeenDamaged; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + bIsLowHP = false; + bIsBattle = false; + bHasBeenDamaged = false; + uiStep = 0; + uiPhaseTimer = 0; + uiControllerGUID = 0; + + DespawnDwarf(); + + if (pInstance) + pInstance->SetData(DATA_BRANN_EVENT, NOT_STARTED); + } + } + + void DespawnDwarf() + { + if (lDwarfGUIDList.empty()) + return; + for (std::list::const_iterator itr = lDwarfGUIDList.begin(); itr != lDwarfGUIDList.end(); ++itr) + { + Creature* pTemp = Unit::GetCreature(*me, pInstance ? (*itr) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + lDwarfGUIDList.clear(); + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 7: + if (Creature* pCreature = GetClosestCreatureWithEntry(me, CREATURE_TRIBUNAL_OF_THE_AGES, 100.0f)) + { + if (!pCreature->isAlive()) + pCreature->Respawn(); + CAST_AI(mob_tribuna_controllerAI, pCreature->AI())->UpdateFacesList(); + uiControllerGUID = pCreature->GetGUID(); + } + break; + case 13: + DoScriptText(SAY_EVENT_INTRO_1, me); + SetEscortPaused(true); + JumpToNextStep(20000); + break; + case 17: + DoScriptText(SAY_EVENT_INTRO_2, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_TRIBUNAL_CONSOLE),true); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + SetEscortPaused(true); + JumpToNextStep(8500); + break; + case 18: + SetEscortPaused(true); + break; + } + } + + void SpawnDwarf(uint32 uiType) + { + switch(uiType) + { + case 1: + { + uint32 uiSpawnNumber = DUNGEON_MODE(2,3); + for (uint8 i = 0; i < uiSpawnNumber; ++i) + me->SummonCreature(CREATURE_DARK_RUNE_PROTECTOR, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + } + case 2: + for (uint8 i = 0; i < 2; ++i) + me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + case 3: + me->SummonCreature(CREATURE_IRON_GOLEM_CUSTODIAN, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + lDwarfGUIDList.push_back(pSummoned->GetGUID()); + pSummoned->AddThreat(me, 0.0f); + pSummoned->AI()->AttackStart(me); + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhaseTimer = uiTimer; + ++uiStep; + } + + void StartWP() + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetEscortPaused(false); + uiStep = 1; + Start(); + } + + void DamageTaken(Unit* /*done_by*/, uint32 & /*damage*/) + { + if (!bHasBeenDamaged) + bHasBeenDamaged = true; + } + + void UpdateEscortAI(const uint32 uiDiff) + { + if (uiPhaseTimer <= uiDiff) + { + switch(uiStep) + { + case 1: + if (pInstance) + { + if (pInstance->GetData(DATA_BRANN_EVENT) != NOT_STARTED) + return; + pInstance->SetData(DATA_BRANN_EVENT, IN_PROGRESS); + } + bIsBattle = false; + DoScriptText(SAY_ESCORT_START, me); + SetRun(true); + JumpToNextStep(0); + break; + case 3: + SetEscortPaused(false); + JumpToNextStep(0); + break; + case 5: + if (pInstance) + if (Creature* pTemp = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM)))) + DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp); + JumpToNextStep(8500); + break; + case 6: + DoScriptText(SAY_EVENT_A_1, me); + JumpToNextStep(6500); + break; + case 7: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_A_2_KADD, pTemp); + JumpToNextStep(12500); + break; + case 8: + DoScriptText(SAY_EVENT_A_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bKaddrakActivated = true; + JumpToNextStep(5000); + break; + case 9: + me->SetReactState(REACT_PASSIVE); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 10: + DoScriptText(SAY_EVENT_B_1, me); + JumpToNextStep(6000); + break; + case 11: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_B_2_MARN, pTemp); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 12: + DoScriptText(SAY_EVENT_B_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bMarnakActivated = true; + JumpToNextStep(10000); + break; + case 13: + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 14: + SpawnDwarf(2); + JumpToNextStep(20000); + break; + case 15: + DoScriptText(SAY_EVENT_C_1, me); + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 16: + SpawnDwarf(2); + JumpToNextStep(20000); + break; + case 17: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_C_2_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 18: + DoScriptText(SAY_EVENT_C_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bAbedneumActivated = true; + JumpToNextStep(5000); + break; + case 19: + SpawnDwarf(2); + JumpToNextStep(10000); + break; + case 20: + SpawnDwarf(1); + JumpToNextStep(15000); + break; + case 21: + DoScriptText(SAY_EVENT_D_1, me); + SpawnDwarf(3); + JumpToNextStep(20000); + break; + case 22: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_D_2_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(5000); + break; + case 23: + SpawnDwarf(2); + JumpToNextStep(15000); + break; + case 24: + DoScriptText(SAY_EVENT_D_3, me); + SpawnDwarf(3); + JumpToNextStep(5000); + break; + case 25: + SpawnDwarf(1); + JumpToNextStep(5000); + break; + case 26: + SpawnDwarf(2); + JumpToNextStep(10000); + break; + case 27: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_D_4_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 28: + me->SetReactState(REACT_DEFENSIVE); + DoScriptText(SAY_EVENT_END_01, me); + me->SetStandState(UNIT_STAND_STATE_STAND); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + bIsBattle = true; + SetEscortPaused(false); + JumpToNextStep(6500); + break; + case 29: + DoScriptText(SAY_EVENT_END_02, me); + if (pInstance) + { + pInstance->SetData(DATA_BRANN_EVENT, DONE); + + // Achievement criteria is with spell 59046 which does not exist. + // There is thus no way it can be given by casting the spell on the players. + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59046); + + if (!bHasBeenDamaged) + pInstance->DoCompleteAchievement(ACHIEV_BRANN_SPANKIN_NEW); + } + + JumpToNextStep(5500); + break; + case 30: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_03_ABED, pTemp); + JumpToNextStep(8500); + break; + case 31: + DoScriptText(SAY_EVENT_END_04, me); + JumpToNextStep(11500); + break; + case 32: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_05_ABED, pTemp); + JumpToNextStep(11500); + break; + case 33: + DoScriptText(SAY_EVENT_END_06, me); + JumpToNextStep(4500); + break; + case 34: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_07_ABED, pTemp); + JumpToNextStep(22500); + break; + case 35: + DoScriptText(SAY_EVENT_END_08, me); + JumpToNextStep(7500); + break; + case 36: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_09_KADD, pTemp); + JumpToNextStep(18500); + break; + case 37: + DoScriptText(SAY_EVENT_END_10, me); + JumpToNextStep(5500); + break; + case 38: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_11_KADD, pTemp); + JumpToNextStep(20500); + break; + case 39: + DoScriptText(SAY_EVENT_END_12, me); + JumpToNextStep(2500); + break; + case 40: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_13_KADD, pTemp); + JumpToNextStep(19500); + break; + case 41: + DoScriptText(SAY_EVENT_END_14, me); + JumpToNextStep(10500); + break; + case 42: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_15_MARN, pTemp); + JumpToNextStep(6500); + break; + case 43: + DoScriptText(SAY_EVENT_END_16, me); + JumpToNextStep(6500); + break; + case 44: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_17_MARN, pTemp); + JumpToNextStep(25500); + break; + case 45: + DoScriptText(SAY_EVENT_END_18, me); + JumpToNextStep(23500); + break; + case 46: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_19_MARN, pTemp); + JumpToNextStep(3500); + break; + case 47: + DoScriptText(SAY_EVENT_END_20, me); + JumpToNextStep(8500); + break; + case 48: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_21_ABED, pTemp); + JumpToNextStep(5500); + break; + case 49: + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); + } + Player* pPlayer = GetPlayerForEscort(); + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, me); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + JumpToNextStep(180000); + break; + } + case 50: + SetEscortPaused(false); + break; + } + } else uiPhaseTimer -= uiDiff; + + if (!bIsLowHP && HealthBelowPct(30)) + { + DoScriptText(SAY_LOW_HEALTH, me); + bIsLowHP = true; + } + else if (bIsLowHP && !HealthBelowPct(30)) + bIsLowHP = false; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_brann_hos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1 || uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_brann_hosAI, pCreature->AI())->StartWP(); + } + + return true; +} + +CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature) +{ + return new mob_tribuna_controllerAI(pCreature); +} + +CreatureAI* GetAI_npc_brann_hos(Creature* pCreature) +{ + return new npc_brann_hosAI(pCreature); +} + +void AddSC_halls_of_stone() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_brann_hos"; + newscript->GetAI = &GetAI_npc_brann_hos; + newscript->pGossipHello = &GossipHello_npc_brann_hos; + newscript->pGossipSelect = &GossipSelect_npc_brann_hos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tribuna_controller"; + newscript->GetAI = &GetAI_mob_tribuna_controller; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h b/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h new file mode 100644 index 00000000000..b61e7057ddc --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h @@ -0,0 +1,48 @@ +#ifndef DEF_HALLS_OF_STONE_H +#define DEF_HALLS_OF_STONE_H +enum Data +{ + DATA_KRYSTALLUS_EVENT, + DATA_MAIDEN_OF_GRIEF_EVENT, + DATA_SJONNIR_EVENT, + DATA_BRANN_EVENT +}; +enum Data64 +{ + DATA_KRYSTALLUS, + DATA_MAIDEN_OF_GRIEF, + DATA_SJONNIR, + DATA_KADDRAK, + DATA_MARNAK, + DATA_ABEDNEUM, + DATA_GO_TRIBUNAL_CONSOLE, + DATA_GO_KADDRAK, + DATA_GO_MARNAK, + DATA_GO_ABEDNEUM, + DATA_GO_SKY_FLOOR, + DATA_SJONNIR_DOOR, + DATA_MAIDEN_DOOR +}; +enum Creatures +{ + CREATURE_MAIDEN = 27975, + CREATURE_KRYSTALLUS = 27977, + CREATURE_SJONNIR = 27978, + CREATURE_MARNAK = 30897, + CREATURE_KADDRAK = 30898, + CREATURE_ABEDNEUM = 30899, + CREATURE_BRANN = 28070 +}; +enum GameObjects +{ + GO_ABEDNEUM = 191669, + GO_MARNAK = 192170, + GO_KADDRAK = 192171, + GO_MAIDEN_DOOR = 191292, + GO_BRANN_DOOR = 191295, + GO_SJONNIR_DOOR = 191296, + GO_TRIBUNAL_CONSOLE = 193907, + GO_TRIBUNAL_CHEST = 190586, + GO_TRIBUNAL_CHEST_HERO = 193996 +}; +#endif diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp new file mode 100644 index 00000000000..69bb3779e70 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp @@ -0,0 +1,254 @@ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +#define MAX_ENCOUNTER 4 + +/* Halls of Stone encounters: +0- Krystallus +1- Maiden of Grief +2- Escort Event +3- Sjonnir The Ironshaper +*/ + +struct instance_halls_of_stone : public ScriptedInstance +{ + instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiMaidenOfGrief; + uint64 uiKrystallus; + uint64 uiSjonnir; + + uint64 uiKaddrak; + uint64 uiAbedneum; + uint64 uiMarnak; + uint64 uiBrann; + + uint64 uiMaidenOfGriefDoor; + uint64 uiSjonnirDoor; + uint64 uiBrannDoor; + uint64 uiTribunalConsole; + uint64 uiTribunalChest; + uint64 uiTribunalSkyFloor; + uint64 uiKaddrakGo; + uint64 uiAbedneumGo; + uint64 uiMarnakGo; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + std::string str_data; + + void Initialize() + { + uiMaidenOfGrief = 0; + uiKrystallus = 0; + uiSjonnir = 0; + + uiKaddrak = 0; + uiMarnak = 0; + uiAbedneum = 0; + uiBrann = 0; + + uiMaidenOfGriefDoor = 0; + uiSjonnirDoor = 0; + uiBrannDoor = 0; + uiKaddrakGo = 0; + uiMarnakGo = 0; + uiAbedneumGo = 0; + uiTribunalConsole = 0; + uiTribunalChest = 0; + uiTribunalSkyFloor = 0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + m_auiEncounter[i] = NOT_STARTED; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case CREATURE_MAIDEN: uiMaidenOfGrief = pCreature->GetGUID(); break; + case CREATURE_KRYSTALLUS: uiKrystallus = pCreature->GetGUID(); break; + case CREATURE_SJONNIR: uiSjonnir = pCreature->GetGUID(); break; + case CREATURE_MARNAK: uiMarnak = pCreature->GetGUID(); break; + case CREATURE_KADDRAK: uiKaddrak = pCreature->GetGUID(); break; + case CREATURE_ABEDNEUM: uiAbedneum = pCreature->GetGUID(); break; + case CREATURE_BRANN: uiBrann = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_ABEDNEUM: + uiAbedneumGo = pGo->GetGUID(); + break; + case GO_MARNAK: + uiMarnakGo = pGo->GetGUID(); + break; + case GO_KADDRAK: + uiKaddrakGo = pGo->GetGUID(); + break; + case GO_MAIDEN_DOOR: + uiMaidenOfGriefDoor = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_BRANN_DOOR: + uiBrannDoor = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_SJONNIR_DOOR: + uiSjonnirDoor = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_TRIBUNAL_CONSOLE: + uiTribunalConsole = pGo->GetGUID(); + break; + case GO_TRIBUNAL_CHEST: + case GO_TRIBUNAL_CHEST_HERO: + uiTribunalChest = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + case 191527: + uiTribunalSkyFloor = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAIDEN_OF_GRIEF_EVENT: + m_auiEncounter[1] = data; + if (m_auiEncounter[1] == DONE) + HandleGameObject(uiBrannDoor,true); + break; + case DATA_KRYSTALLUS_EVENT: + m_auiEncounter[0] = data; + if (m_auiEncounter[0] == DONE) + HandleGameObject(uiMaidenOfGriefDoor,true); + break; + case DATA_SJONNIR_EVENT: + m_auiEncounter[3] = data; + break; + case DATA_BRANN_EVENT: + m_auiEncounter[2] = data; + if (m_auiEncounter[2] == DONE) + { + HandleGameObject(uiSjonnirDoor,true); + GameObject *pGo = instance->GetGameObject(uiTribunalChest); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + } + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_KRYSTALLUS_EVENT: return m_auiEncounter[0]; + case DATA_MAIDEN_OF_GRIEF_EVENT: return m_auiEncounter[1]; + case DATA_SJONNIR_EVENT: return m_auiEncounter[2]; + case DATA_BRANN_EVENT: return m_auiEncounter[3]; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MAIDEN_OF_GRIEF: return uiMaidenOfGrief; + case DATA_KRYSTALLUS: return uiKrystallus; + case DATA_SJONNIR: return uiSjonnir; + case DATA_KADDRAK: return uiKaddrak; + case DATA_MARNAK: return uiMarnak; + case DATA_ABEDNEUM: return uiAbedneum; + case DATA_GO_TRIBUNAL_CONSOLE: return uiTribunalConsole; + case DATA_GO_KADDRAK: return uiKaddrakGo; + case DATA_GO_ABEDNEUM: return uiAbedneumGo; + case DATA_GO_MARNAK: return uiMarnakGo; + case DATA_GO_SKY_FLOOR: return uiTribunalSkyFloor; + case DATA_SJONNIR_DOOR: return uiSjonnirDoor; + case DATA_MAIDEN_DOOR: return uiMaidenOfGriefDoor; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'H' && dataHead2 == 'S') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_halls_of_stone(Map* pMap) +{ + return new instance_halls_of_stone(pMap); +} + +void AddSC_instance_halls_of_stone() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_stone"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_stone; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp new file mode 100644 index 00000000000..e944543fb9e --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2008 - 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +#define GAMEOBJECT_GIVE_OF_THE_OBSERVER 194821 + +enum Spells +{ + SPELL_ASCEND = 64487, + SPELL_BERSERK = 47008, + SPELL_BIG_BANG = 64443, + H_SPELL_BIG_BANG = 64584, + SPELL_COSMIC_SMASH = 62301, + H_SPELL_COSMIC_SMASH = 64598, + SPELL_PHASE_PUNCH = 64412, + SPELL_QUANTUM_STRIKE = 64395, + H_SPELL_QUANTUM_STRIKE = 64592, + SPELL_BLACK_HOLE_EXPLOSION = 64122, + SPELL_ARCANE_BARAGE = 64599, + H_SPELL_ARCANE_BARAGE = 64607 +}; + +enum Creatures +{ + CREATURE_COLLAPSING_STAR = 32955, + CREATURE_BLACK_HOLE = 32953, + CREATURE_LIVING_CONSTELLATION = 33052, + CREATURE_DARK_MATTER = 33089 +}; + +#define NORDRASSIL_X 1614.288574 +#define NORDRASSIL_Y -320.713287 +#define NORDRASSIL_Z 417.321167 +#define NORDRASSIL_X 1614.276245 +#define NORDRASSIL_Y -287.016632 +#define NORDRASSIL_Z 417.321106 +#define NORDRASSIL_X 1650.428467 +#define NORDRASSIL_Y -292.331390 +#define NORDRASSIL_Z 417.321167 +#define NORDRASSIL_X 1649.501831 +#define NORDRASSIL_Y -324.609222 +#define NORDRASSIL_Z 417.322174 + +enum Yells +{ + SAY_AGGRO = -1603000, + SAY_SLAY_1 = -1603001, + SAY_SLAY_2 = -1603002, + SAY_ENGADED_FOR_FIRTS_TIME = -1603003, + SAY_PHASE_2 = -1603004, + SAY_SUMMON_COLLAPSING_STAR = -1603005, + SAY_DEATH_1 = -1603006, + SAY_DEATH_2 = -1603007, + SAY_DEATH_3 = -1603008, + SAY_DEATH_4 = -1603009, + SAY_DEATH_5 = -1603010, + SAY_BERSERK = -1603011, + SAY_BIG_BANG_1 = -1603012, + SAY_BIG_BANG_2 = -1603013, + SAY_TIMER_1 = -1603014, + SAY_TIMER_2 = -1603015, + SAY_TIMER_3 = -1603016, + SAY_SUMMON_1 = -1603017, + SAY_SUMMON_2 = -1603018, + SAY_SUMMON_3 = -1603019, +}; + +struct boss_algalonAI : public ScriptedAI +{ + boss_algalonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Summon = false; // not in reset. intro speech done only once. + } + + ScriptedInstance* pInstance; + + std::list m_lCollapsingStarGUIDList; + + uint32 Phase; + uint32 Ascend_Timer; + uint32 Berserk_Timer; + uint32 BigBang_Timer; + uint32 CosmicSmash_Timer; + uint32 PhasePunch_Timer; + uint32 QuantumStrike_Timer; + uint32 CollapsingStar_Timer; + uint32 uiPhase_timer; + uint32 uiStep; + + uint64 BlackHoleGUID; + + bool Enrage; + bool Summon; + + void EnterCombat(Unit* who) + { + if (Summon) + { + DoScriptText(SAY_AGGRO, me); + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + DoZoneInCombat(who->ToCreature()); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + uiStep = 1; + } + + if (pInstance) + pInstance->SetData(TYPE_ALGALON, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void Reset() + { + Phase = 1; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pInstance) + pInstance->SetData(TYPE_ALGALON, NOT_STARTED); + + BlackHoleGUID = 0; + + uiPhase_timer = 0; + Ascend_Timer = 480000; //8 minutes + QuantumStrike_Timer = 4000 + rand()%10000; + Berserk_Timer = 360000; //6 minutes + CollapsingStar_Timer = urand(15000, 20000); //Spawns between 15 to 20 seconds + BigBang_Timer = 90000; + PhasePunch_Timer = 8000; + CosmicSmash_Timer = urand(30000, 60000); + Enrage = false; + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhase_timer = uiTimer; + ++uiStep; + } + + void DespawnCollapsingStar() + { + if (m_lCollapsingStarGUIDList.empty()) + return; + + for (std::list::const_iterator itr = m_lCollapsingStarGUIDList.begin(); itr != m_lCollapsingStarGUIDList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + } + m_lCollapsingStarGUIDList.clear(); + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == CREATURE_COLLAPSING_STAR) + { + Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (me->getVictim()) + pSummoned->AI()->AttackStart(pTarget ? pTarget : me->getVictim()); + m_lCollapsingStarGUIDList.push_back(pSummoned->GetGUID()); + } + } + + void SummonCollapsingStar(Unit* target) + { + DoScriptText(SAY_SUMMON_COLLAPSING_STAR, me); + me->SummonCreature(CREATURE_COLLAPSING_STAR,target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN, 100000); + me->SummonCreature(CREATURE_BLACK_HOLE,target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN, 27000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Phase == 1 && HealthBelowPct(20)) + { + Phase = 2; + DoScriptText(SAY_PHASE_2, me); + } + + if (HealthBelowPct(2)) + { + me->SummonGameObject(GAMEOBJECT_GIVE_OF_THE_OBSERVER, 1634.258667, -295.101166,417.321381,0,0,0,0,0,0); + + // All of them. or random? + DoScriptText(SAY_DEATH_1, me); + DoScriptText(SAY_DEATH_2, me); + DoScriptText(SAY_DEATH_3, me); + DoScriptText(SAY_DEATH_4, me); + DoScriptText(SAY_DEATH_5, me); + + me->DisappearAndDie(); + + if (pInstance) + pInstance->SetData(TYPE_ALGALON, DONE); + + return; + } + + if (Phase == 1) + { + if (!Summon) + { + if (uiPhase_timer <= diff) + { + switch(uiStep) + { + case 1: + DoScriptText(SAY_SUMMON_1, me); + JumpToNextStep(3000); + break; + case 2: + DoScriptText(SAY_SUMMON_2, me); + JumpToNextStep(3000); + break; + case 3: + DoScriptText(SAY_SUMMON_3, me); + JumpToNextStep(3000); + break; + case 4: + DoScriptText(SAY_ENGADED_FOR_FIRTS_TIME, me); + JumpToNextStep(3000); + break; + case 5: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + Summon = true; + break; + } + } else uiPhase_timer -= diff; + + return; + } + + if (QuantumStrike_Timer <= diff) + { + DoCast(me->getVictim(), RAID_MODE(SPELL_QUANTUM_STRIKE,H_SPELL_QUANTUM_STRIKE), true); + + QuantumStrike_Timer = urand(4000, 14000); + } else QuantumStrike_Timer -= diff; + + if (BigBang_Timer <= diff) + { + DoScriptText(RAND(SAY_BIG_BANG_1,SAY_BIG_BANG_2), me); + DoCast(me->getVictim(), RAID_MODE(SPELL_BIG_BANG,H_SPELL_BIG_BANG), true); + + BigBang_Timer = 90000; + } else BigBang_Timer -= diff; + + if (Ascend_Timer <= diff) + { + DoCast(me->getVictim(),SPELL_ASCEND, true); + + Ascend_Timer = 480000; + } else Ascend_Timer -= diff; + + if (PhasePunch_Timer <= diff) + { + DoCast(me->getVictim(),SPELL_PHASE_PUNCH, true); + + PhasePunch_Timer = 8000; + } else PhasePunch_Timer -= diff; + + if (CosmicSmash_Timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), RAID_MODE(SPELL_COSMIC_SMASH,H_SPELL_COSMIC_SMASH), true); + + CosmicSmash_Timer = urand(30000, 60000); + } else CosmicSmash_Timer -= diff; + + if (Berserk_Timer <= diff) + { + DoScriptText(SAY_BERSERK, me); + DoCast(me->getVictim(),SPELL_BERSERK, true); + + Berserk_Timer = 360000; + } else Berserk_Timer -= diff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } + + if (Phase == 2) + { + if (Enrage) + { + if (Ascend_Timer <= diff) + { + DoCast(me, SPELL_ASCEND); + DoScriptText(SAY_BERSERK, me); + Ascend_Timer = urand(360000,365000); + Enrage = false; + } else Ascend_Timer -= diff; + } + } + + DoMeleeAttackIfReady(); + } +}; + +//Collapsing Star +struct mob_collapsing_starAI : public ScriptedAI +{ + mob_collapsing_starAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 BlackHoleExplosion_Timer; + + void Reset() + { + BlackHoleExplosion_Timer = 0; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BlackHoleExplosion_Timer <= diff) + { + me->CastSpell(me, SPELL_BLACK_HOLE_EXPLOSION, false); + BlackHoleExplosion_Timer = 0; + } else BlackHoleExplosion_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_algalon(Creature* pCreature) +{ + return new boss_algalonAI(pCreature); +} + +CreatureAI* GetAI_mob_collapsing_star(Creature* pCreature) +{ + return new mob_collapsing_starAI(pCreature); +} + +void AddSC_boss_Algalon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_algalon"; + newscript->GetAI = &GetAI_boss_algalon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_collapsing_star"; + newscript->GetAI = &GetAI_mob_collapsing_star; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp new file mode 100644 index 00000000000..8d3ae4d3431 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Assembly of Iron encounter +SD%Complete: 60% +SDComment: Runes need DB support, chain lightning won't cast, supercharge won't cast (pTarget error?) - it worked before during debugging. +SDCategory: Ulduar - Ulduar +EndScriptData */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +// Any boss +#define SPELL_SUPERCHARGE 61920 +#define SPELL_BERSERK 47008 // Hard enrage, don't know the correct ID. + +// Steelbreaker +#define SPELL_HIGH_VOLTAGE 61890 +#define SPELL_HIGH_VOLTAGE_H 63498 +#define SPELL_FUSION_PUNCH 61903 +#define SPELL_FUSION_PUNCH_H 63493 +#define SPELL_STATIC_DISRUPTION 44008 +#define SPELL_STATIC_DISRUPTION_H 63494 +#define SPELL_OVERWHELMING_POWER_H 61888 +#define SPELL_OVERWHELMING_POWER 64637 +#define SPELL_ELECTRICAL_CHARGE 61902 + +// Runemaster Molgeim +#define SPELL_SHIELD_OF_RUNES 62274 +#define SPELL_SHIELD_OF_RUNES_H 63489 +#define SPELL_RUNE_OF_POWER 64320 +#define SPELL_RUNE_OF_DEATH 62269 +#define SPELL_RUNE_OF_SUMMONING 62273 +#define SPELL_LIGHTNING_BLAST 62054 +#define SPELL_LIGHTNING_BLAST_H 63491 +#define CREATURE_RUNE_OF_SUMMONING 33051 + +// Stormcaller Brundir +#define SPELL_CHAIN_LIGHTNING_N 61879 +#define SPELL_CHAIN_LIGHTNING_H 63479 +#define SPELL_OVERLOAD 61869 +#define SPELL_OVERLOAD_H 63481 +#define SPELL_LIGHTNING_WHIRL 61915 +#define SPELL_LIGHTNING_WHIRL_H 63483 +#define SPELL_LIGHTNING_TENDRILS 61887 +#define SPELL_LIGHTNING_TENDRILS_H 63486 +#define SPELL_STORMSHIELD 64187 + +enum Events +{ + EVENT_NONE, + EVENT_ENRAGE, + // Steelbreaker + EVENT_FUSION_PUNCH, + EVENT_STATIC_DISRUPTION, + EVENT_OVERWHELMING_POWER, + // Molgeim + EVENT_RUNE_OF_POWER, + EVENT_SHIELD_OF_RUNES, + EVENT_RUNE_OF_DEATH, + EVENT_RUNE_OF_SUMMONING, + EVENT_LIGHTNING_BLAST, + // Brundir + EVENT_CHAIN_LIGHTNING, + EVENT_OVERLOAD, + EVENT_LIGHTNING_WHIRL, + EVENT_LIGHTNING_TENDRILS, + EVENT_STORMSHIELD, +}; + +enum Yells +{ + SAY_STEELBREAKER_AGGRO = -1603020, + SAY_STEELBREAKER_SLAY_1 = -1603021, + SAY_STEELBREAKER_SLAY_2 = -1603022, + SAY_STEELBREAKER_POWER = -1603023, + SAY_STEELBREAKER_DEATH_1 = -1603024, + SAY_STEELBREAKER_DEATH_2 = -1603025, + SAY_STEELBREAKER_BERSERK = -1603026, + + SAY_MOLGEIM_AGGRO = -1603030, + SAY_MOLGEIM_SLAY_1 = -1603031, + SAY_MOLGEIM_SLAY_2 = -1603032, + SAY_MOLGEIM_RUNE_DEATH = -1603033, + SAY_MOLGEIM_SUMMON = -1603034, + SAY_MOLGEIM_DEATH_1 = -1603035, + SAY_MOLGEIM_DEATH_2 = -1603036, + SAY_MOLGEIM_BERSERK = -1603037, + + SAY_BRUNDIR_AGGRO = -1603040, + SAY_BRUNDIR_SLAY_1 = -1603041, + SAY_BRUNDIR_SLAY_2 = -1603042, + SAY_BRUNDIR_SPECIAL = -1603043, + SAY_BRUNDIR_FLIGHT = -1603044, + SAY_BRUNDIR_DEATH_1 = -1603045, + SAY_BRUNDIR_DEATH_2 = -1603046, + SAY_BRUNDIR_BERSERK = -1603047, +}; + +bool IsEncounterComplete(ScriptedInstance* pInstance, Creature* me) +{ + if (!pInstance || !me) + return false; + + for (uint8 i = 0; i < 3; ++i) + { + uint64 guid = pInstance->GetData64(DATA_STEELBREAKER+i); + if (!guid) + return false; + + if (Creature *boss = Unit::GetCreature(*me, guid)) + { + if (boss->isAlive()) + return false; + } + else + return false; + } + return true; +} + +struct boss_steelbreakerAI : public ScriptedAI +{ + boss_steelbreakerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() + { + events.Reset(); + phase = 0; + me->RemoveAllAuras(); + if (pInstance) + pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); + } + + EventMap events; + ScriptedInstance* pInstance; + uint32 phase; + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_STEELBREAKER_AGGRO, me); + DoZoneInCombat(); + DoCast(me, RAID_MODE(SPELL_HIGH_VOLTAGE, SPELL_HIGH_VOLTAGE_H)); + events.ScheduleEvent(EVENT_ENRAGE, 900000); + UpdatePhase(); + } + + void UpdatePhase() + { + ++phase; + events.SetPhase(phase); + events.RescheduleEvent(EVENT_FUSION_PUNCH, 15000); + if (phase >= 2) + events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 30000); + if (phase >= 3) + events.RescheduleEvent(EVENT_OVERWHELMING_POWER, rand()%5000); + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + if (Creature* Brundir = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0)) + if (Brundir->isAlive()) + Brundir->SetHealth(Brundir->GetMaxHealth()); + + if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0)) + if (Molgeim->isAlive()) + Molgeim->SetHealth(Molgeim->GetMaxHealth()); + + DoCast(SPELL_SUPERCHARGE); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(RAND(SAY_STEELBREAKER_DEATH_1,SAY_STEELBREAKER_DEATH_2), me); + if (IsEncounterComplete(pInstance, me) && pInstance) + pInstance->SetData(TYPE_ASSEMBLY, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_STEELBREAKER_SLAY_1,SAY_STEELBREAKER_SLAY_2), me); + + if (phase == 3) + DoCast(me, SPELL_ELECTRICAL_CHARGE); + } + + void SpellHit(Unit * /*from*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_SUPERCHARGE) + UpdatePhase(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ENRAGE: + DoScriptText(SAY_STEELBREAKER_BERSERK, me); + DoCast(SPELL_BERSERK); + break; + case EVENT_FUSION_PUNCH: + DoCast(me->getVictim(), RAID_MODE(SPELL_FUSION_PUNCH, SPELL_FUSION_PUNCH_H)); + events.ScheduleEvent(EVENT_FUSION_PUNCH, urand(13000, 22000)); + break; + case EVENT_STATIC_DISRUPTION: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, RAID_MODE(SPELL_STATIC_DISRUPTION, SPELL_STATIC_DISRUPTION_H)); + events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(20000, 40000)); + break; + case EVENT_OVERWHELMING_POWER: + DoScriptText(SAY_STEELBREAKER_POWER, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_OVERWHELMING_POWER, SPELL_OVERWHELMING_POWER_H)); + events.ScheduleEvent(EVENT_OVERWHELMING_POWER, RAID_MODE(60000, 35000)); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_runemaster_molgeimAI : public ScriptedAI +{ + boss_runemaster_molgeimAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() + { + if (pInstance) + pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); + events.Reset(); + me->RemoveAllAuras(); + phase = 0; + } + + ScriptedInstance* pInstance; + EventMap events; + uint32 phase; + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_MOLGEIM_AGGRO, me); + DoZoneInCombat(); + events.ScheduleEvent(EVENT_ENRAGE, 900000); + UpdatePhase(); + } + + void UpdatePhase() + { + ++phase; + events.SetPhase(phase); + events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27000); + events.RescheduleEvent(EVENT_RUNE_OF_POWER, 60000); + if (phase >= 2) + events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 30000); + if (phase >= 3) + events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0)) + if (Steelbreaker->isAlive()) + Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth()); + + if (Creature* Brundir = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0)) + if (Brundir->isAlive()) + Brundir->SetHealth(Brundir->GetMaxHealth()); + + DoCast(me, SPELL_SUPERCHARGE); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(RAND(SAY_MOLGEIM_DEATH_1,SAY_MOLGEIM_DEATH_2), me); + if (IsEncounterComplete(pInstance, me) && pInstance) + pInstance->SetData(TYPE_ASSEMBLY, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_MOLGEIM_SLAY_1,SAY_MOLGEIM_SLAY_2), me); + } + + void SpellHit(Unit * /*from*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_SUPERCHARGE) + UpdatePhase(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ENRAGE: + DoScriptText(SAY_MOLGEIM_BERSERK, me); + DoCast(SPELL_BERSERK); + break; + case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly + { + Unit *pTarget = DoSelectLowestHpFriendly(60); + if (!pTarget || (pTarget && !pTarget->isAlive())) + pTarget = me; + DoCast(pTarget, SPELL_RUNE_OF_POWER); + events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000); + break; + } + case EVENT_SHIELD_OF_RUNES: + DoCast(me, RAID_MODE(SPELL_SHIELD_OF_RUNES, SPELL_SHIELD_OF_RUNES_H)); + events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, urand(27000,34000)); + break; + case EVENT_RUNE_OF_DEATH: + DoScriptText(SAY_MOLGEIM_RUNE_DEATH, me); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_RUNE_OF_DEATH); + events.ScheduleEvent(EVENT_RUNE_OF_DEATH, urand(30000,40000)); + break; + case EVENT_RUNE_OF_SUMMONING: + DoScriptText(SAY_MOLGEIM_SUMMON, me); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_RUNE_OF_SUMMONING); + events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_lightning_elementalAI : public ScriptedAI +{ + mob_lightning_elementalAI(Creature *c) : ScriptedAI(c) + { + Charge(); + } + + void Charge() + { + Unit* pTarget = me->SelectNearestTarget(); + me->AddThreat(pTarget, 5000000.0f); + AttackStart(pTarget); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!me->isInCombat()) + return; + + if (!UpdateVictim()) + return; + + if (me->IsWithinMeleeRange(me->getVictim())) + { + DoCast(me->getVictim(), RAID_MODE(SPELL_LIGHTNING_BLAST, SPELL_LIGHTNING_BLAST_H)); + me->Kill(me); // hack until spell works + } + + me->GetMotionMaster()->MoveChase(me->getVictim()); // needed at every update? + } +}; + +struct mob_rune_of_summoningAI : public ScriptedAI +{ + mob_rune_of_summoningAI(Creature *c) : ScriptedAI(c) + { + SummonLightningElemental(); + } + + void SummonLightningElemental() + { + me->SummonCreature(CREATURE_RUNE_OF_SUMMONING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN); + me->DealDamage(me, me->GetHealth()); + } +}; + +struct boss_stormcaller_brundirAI : public ScriptedAI +{ + boss_stormcaller_brundirAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() + { + if (pInstance) + pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); + me->RemoveAllAuras(); + events.Reset(); + phase = 0; + } + + EventMap events; + ScriptedInstance* pInstance; + uint32 phase; + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_BRUNDIR_AGGRO, me); + DoZoneInCombat(); + events.ScheduleEvent(EVENT_ENRAGE, 900000); + UpdatePhase(); + } + + void UpdatePhase() + { + ++phase; + events.SetPhase(phase); + events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000,17000)); + events.RescheduleEvent(EVENT_OVERLOAD, urand(60000,125000)); + if (phase >= 2) + events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000,40000)); + if (phase >= 3) + { + DoCast(me, SPELL_STORMSHIELD); + events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, urand(40000,80000)); + } + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0)) + if (Steelbreaker->isAlive()) + Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth()); + + if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0)) + if (Molgeim->isAlive()) + Molgeim->SetHealth(Molgeim->GetMaxHealth()); + + DoCast(SPELL_SUPERCHARGE); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(RAND(SAY_BRUNDIR_DEATH_1,SAY_BRUNDIR_DEATH_2), me); + if (IsEncounterComplete(pInstance, me) && pInstance) + pInstance->SetData(TYPE_ASSEMBLY, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_BRUNDIR_SLAY_1,SAY_BRUNDIR_SLAY_2), me); + } + + void SpellHit(Unit * /*from*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_SUPERCHARGE) + UpdatePhase(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ENRAGE: + DoScriptText(SAY_BRUNDIR_BERSERK, me); + DoCast(SPELL_BERSERK); + break; + case EVENT_CHAIN_LIGHTNING: + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, RAID_MODE(SPELL_CHAIN_LIGHTNING_N , SPELL_CHAIN_LIGHTNING_H)); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000,17000)); + break; + case EVENT_OVERLOAD: + DoCast(RAID_MODE(SPELL_OVERLOAD , SPELL_OVERLOAD_H)); + events.ScheduleEvent(EVENT_OVERLOAD, urand(60000,125000)); + break; + case EVENT_LIGHTNING_WHIRL: + DoCast(RAID_MODE(SPELL_LIGHTNING_WHIRL , SPELL_LIGHTNING_WHIRL_H)); + events.ScheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000,40000)); + break; + case EVENT_LIGHTNING_TENDRILS: + DoCast(RAID_MODE(SPELL_LIGHTNING_TENDRILS, SPELL_LIGHTNING_TENDRILS_H)); + events.DelayEvents(15000, 5000); + DoResetThreat(); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_steelbreaker(Creature* pCreature) +{ + return new boss_steelbreakerAI (pCreature); +} + +CreatureAI* GetAI_boss_runemaster_molgeim(Creature* pCreature) +{ + return new boss_runemaster_molgeimAI (pCreature); +} + +CreatureAI* GetAI_boss_stormcaller_brundir(Creature* pCreature) +{ + return new boss_stormcaller_brundirAI (pCreature); +} + +CreatureAI* GetAI_mob_lightning_elemental(Creature* pCreature) +{ + return new mob_lightning_elementalAI (pCreature); +} + +CreatureAI* GetAI_mob_rune_of_summoning(Creature* pCreature) +{ + return new mob_rune_of_summoningAI (pCreature); +} + +void AddSC_boss_assembly_of_iron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_steelbreaker"; + newscript->GetAI = &GetAI_boss_steelbreaker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_runemaster_molgeim"; + newscript->GetAI = &GetAI_boss_runemaster_molgeim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_stormcaller_brundir"; + newscript->GetAI = &GetAI_boss_stormcaller_brundir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lightning_elemental"; + newscript->GetAI = &GetAI_mob_lightning_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_rune_of_summoning"; + newscript->GetAI = &GetAI_mob_rune_of_summoning; + newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp new file mode 100644 index 00000000000..41c0f317f4e --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +//boss_auriaya +#define SPELL_TERRIFYING_SCREECH 64386 +#define SPELL_SETINEL_BLAST 64679 +#define SPELL_SONIC_SCREECH 64422 +#define SPELL_SUMMON_SWARMING_GUARDIAN 64397 + +enum Yells +{ + SAY_AGGRO = -1603050, + SAY_SLAY_1 = -1603051, + SAY_SLAY_2 = -1603052, + SAY_DEATH = -1603053, + SAY_BERSERK = -1603054, +}; + +struct boss_auriaya_AI : public BossAI +{ + boss_auriaya_AI(Creature *pCreature) : BossAI(pCreature, TYPE_AURIAYA) + { + } + + uint32 TERRIFYING_SCREECH_Timer; + uint32 SONIC_SCREECH_Timer; + + void Reset() + { + _Reset(); + TERRIFYING_SCREECH_Timer = 180000; + SONIC_SCREECH_Timer = 30000; + } + + void EnterCombat(Unit* /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO,me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (TERRIFYING_SCREECH_Timer <= diff) + { + DoCast(SPELL_TERRIFYING_SCREECH); + TERRIFYING_SCREECH_Timer = 180000; + } else TERRIFYING_SCREECH_Timer -= diff; + + if (SONIC_SCREECH_Timer <= diff) + { + DoCastVictim(SPELL_SONIC_SCREECH); + SONIC_SCREECH_Timer = 30000; + } else SONIC_SCREECH_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_auriaya(Creature* pCreature) +{ + return new boss_auriaya_AI (pCreature); +} + +void AddSC_boss_auriaya() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_auriaya"; + newscript->GetAI = &GetAI_boss_auriaya; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp new file mode 100644 index 00000000000..b50f12805a4 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp @@ -0,0 +1,574 @@ +/* + * Copyright (C) 2008 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: Tower Event support is not finished, there is missing code on triggers and + * Lore Keeper and Brann Bronzebeard are not scripted yet. Lore Keeper's script + * should activate the hard mode so is not possible to play hard-mode yet. Add a call to + * Leviathan's DoAction(0) from Lore Keeper's script to activate hard-mode + */ + +#include "ScriptedPch.h" +#include "ulduar.h" +#include "Vehicle.h" + +enum Spells +{ + SPELL_PURSUED = 62374, + SPELL_GATHERING_SPEED = 62375, + SPELL_BATTERING_RAM = 62376, + SPELL_FLAME_VENTS = 62396, + SPELL_MISSILE_BARRAGE = 62400, + SPELL_SYSTEMS_SHUTDOWN = 62475, + + SPELL_FLAME_CANNON = 62395, +// SPELL_FLAME_CANNON = 64692, trigger the same spell + + SPELL_OVERLOAD_CIRCUIT = 62399, + SPELL_SEARING_FLAME = 62402, + SPELL_BLAZE = 62292, + SPELL_SMOKE_TRAIL = 63575, + SPELL_ELECTROSHOCK = 62522, + //TOWER BUFF SPELLS + SPELL_THORIM_S_HAMMER = 62912, // Tower of Storms + SPELL_MIMIRON_S_INFERNO = 62910, // Tower of Flames + SPELL_HODIR_S_FURY = 62297, // Tower of Frost + SPELL_FREYA_S_WARD = 62906 // Tower of Nature +}; + +enum Creatures +{ + MOB_MECHANOLIFT = 33214, + MOB_LIQUID = 33189, + MOB_CONTAINER = 33218, +}; + +enum Events +{ + EVENT_NONE, + EVENT_PURSUE, + EVENT_MISSILE, + EVENT_VENT, + EVENT_SPEED, + EVENT_SUMMON, + EVENT_THORIM_S_HAMMER, // Tower of Storms + EVENT_MIMIRON_S_INFERNO, // Tower of Flames + EVENT_HODIR_S_FURY, // Tower of Frost + EVENT_FREYA_S_WARD // Tower of Nature +}; + +enum Seats +{ + SEAT_PLAYER = 0, + SEAT_TURRET = 1, + SEAT_DEVICE = 2, +}; + +enum Yells +{ + SAY_AGGRO = -1603060, + SAY_SLAY = -1603061, + SAY_DEATH = -1603062, + SAY_TARGET_1 = -1603063, + SAY_TARGET_2 = -1603064, + SAY_TARGET_3 = -1603065, + SAY_HARDMODE = -1603066, + SAY_TOWER_NONE = -1603067, + SAY_TOWER_FROST = -1603068, + SAY_TOWER_FLAME = -1603069, + SAY_TOWER_NATURE = -1603070, + SAY_TOWER_STORM = -1603071, + SAY_PLAYER_RIDING = -1603072, + SAY_OVERLOAD_1 = -1603073, + SAY_OVERLOAD_2 = -1603074, + SAY_OVERLOAD_3 = -1603075, +}; + +enum eAchievementData +{ + //ACHIEV_CHAMPION_OF_ULDUAR = 10042, + //ACHIEV_CONQUEROR_OF_ULDUAR = 10352, + ACHIEV_10_NUKED_FROM_ORBIT = 10058, + ACHIEV_25_NUKED_FROM_ORBIT = 10060, + ACHIEV_10_ORBITAL_BOMBARDMENT = 10056, + ACHIEV_25_ORBITAL_BOMBARDMENT = 10061, + ACHIEV_10_ORBITAL_DEVASTATION = 10057, + ACHIEV_25_ORBITAL_DEVASTATION = 10059, + ACHIEV_10_ORBIT_UARY = 10218, + ACHIEV_25_ORBIT_UARY = 10219, + ACHIEV_10_SHUTOUT = 10054, + ACHIEV_25_SHUTOUT = 10055, + ACHIEV_10_SIEGE_OF_ULDUAR = 9999, + ACHIEV_25_SIEGE_OF_ULDUAR = 10003, + //ACHIEV_10_THREE_CAR_GARAGE = 10046, 10047, 10048, + //ACHIEV_25_THREE_CAR_GARAGE = 10049, 10050, 10051, + ACHIEV_10_UNBROKEN = 10044, + ACHIEV_25_UNBROKEN = 10045, +}; + +static Position Center[]= +{ + {354.8771, -12.90240, 409.803650}, +}; + +struct boss_flame_leviathanAI : public BossAI +{ + boss_flame_leviathanAI(Creature* pCreature) : BossAI(pCreature, TYPE_LEVIATHAN), vehicle(pCreature->GetVehicleKit()) + { + assert(vehicle); + + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + Vehicle* vehicle; + uint8 uiActiveTowers; + + void Reset() + { + _Reset(); + assert(vehicle); + uiActiveTowers = 0; + me->SetReactState(REACT_AGGRESSIVE); + } + + void EnterCombat(Unit* /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO, me); + me->SetReactState(REACT_DEFENSIVE); + events.ScheduleEvent(EVENT_PURSUE, 0); + events.ScheduleEvent(EVENT_MISSILE, 1500); + events.ScheduleEvent(EVENT_VENT, 20000); + events.ScheduleEvent(EVENT_SPEED, 15000); + events.ScheduleEvent(EVENT_SUMMON, 0); + + if (Creature *turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET))) + turret->AI()->DoZoneInCombat(); + } + + // TODO: effect 0 and effect 1 may be on different target + void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_PURSUED) + AttackStart(pTarget); + } + + void JustDied(Unit* /*victim*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + if (pInstance) + { + if (uiActiveTowers) + { + switch (uiActiveTowers) + { + case 4: + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBIT_UARY, ACHIEV_25_ORBIT_UARY)); + break; + case 3: + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_NUKED_FROM_ORBIT, ACHIEV_25_NUKED_FROM_ORBIT)); + break; + case 2: + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBITAL_DEVASTATION, ACHIEV_25_ORBITAL_DEVASTATION)); + break; + case 1: + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBITAL_BOMBARDMENT, ACHIEV_25_ORBITAL_BOMBARDMENT)); + break; + } + } + } + } + + void SpellHit(Unit* /*caster*/, const SpellEntry* pSpell) + { + if (pSpell->Id == 62472) + vehicle->InstallAllAccessories(); + else if (pSpell->Id == SPELL_ELECTROSHOCK) + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + return; + + if (me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + uint32 eventId = events.GetEvent(); + if (!me->getVictim()) + eventId = EVENT_PURSUE; + + switch(eventId) + { + case 0: break; // this is a must + case EVENT_PURSUE: + DoCastAOE(SPELL_PURSUED, true); + //events.RepeatEvent(35000); // this should not be used because eventId may be overriden + events.RescheduleEvent(EVENT_PURSUE, 35000); + if (!me->getVictim()) // all siege engines and demolishers are dead + UpdateVictim(); // begin to kill other things + return; + case EVENT_MISSILE: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_MISSILE_BARRAGE); + events.RepeatEvent(1500); + return; + case EVENT_VENT: + DoCastAOE(SPELL_FLAME_VENTS); + events.RepeatEvent(20000); + return; + case EVENT_SPEED: + DoCastAOE(SPELL_GATHERING_SPEED); + events.RepeatEvent(15000); + return; + case EVENT_SUMMON: + if (summons.size() < 15) // 4seat+1turret+10lift + if (Creature* pLift = DoSummonFlyer(MOB_MECHANOLIFT, me, urand(20,40), 50, 0)) + pLift->GetMotionMaster()->MoveRandom(100); + events.RepeatEvent(2000); + return; + case EVENT_THORIM_S_HAMMER: // Tower of Storms + DoCast(me, SPELL_THORIM_S_HAMMER); + events.RepeatEvent(urand(60000, 120000)); + return; + case EVENT_MIMIRON_S_INFERNO: // Tower of Flames + DoCast(me->getVictim(), SPELL_MIMIRON_S_INFERNO); + events.RepeatEvent(urand(60000, 120000)); + return; + case EVENT_HODIR_S_FURY: // Tower of Frost + DoCast(me->getVictim(), SPELL_HODIR_S_FURY); + events.RepeatEvent(urand(60000, 120000)); + return; + case EVENT_FREYA_S_WARD: // Tower of Nature + DoCast(me, SPELL_FREYA_S_WARD); + events.RepeatEvent(urand(60000, 120000)); + return; + default: + events.PopEvent(); + break; + } + DoSpellAttackIfReady(SPELL_BATTERING_RAM); + } + + void DoAction(const int32 uiAction) + { + // Start encounter + if (uiAction == 10) + { + me->GetMotionMaster()->MovePoint(0, Center[0]); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + return; + } + /* + Tower event triggers + General TODO: + Yells + + Actions: + DoAction(0): Activate hard-mode. Buff up leviathan's AP & health, schedule all the tower spells. + Should be triggered on Lore Keeper's script + DoAction(1-4): A tower have been destroyed, debuff leviathan's AP & health + DoAction(1); Tower of Storms has been destroyed, deschedule spell Thorim's Hammer + DoAction(2): Tower of Flames has been destroyed, deschedule spell Mimiron's Inferno + DoAction(3): Tower of Frost has been destroyed, deschedule spell Hodir's Fury + DoAction(4): Tower of Nature has been destroyed, deschedule spell Freya's Ward + */ + + if (uiAction) // Tower destruction, debuff leviathan AP & health + { + --uiActiveTowers; + } + + switch (uiAction) + { + case 0: // Activate hard-mode + events.ScheduleEvent(EVENT_THORIM_S_HAMMER, urand(30000,60000)); + events.ScheduleEvent(EVENT_MIMIRON_S_INFERNO, urand(30000,60000)); + events.ScheduleEvent(EVENT_HODIR_S_FURY, urand(30000,60000)); + events.ScheduleEvent(EVENT_FREYA_S_WARD, urand(30000,60000)); + uiActiveTowers=4; + break; + case 1: // Tower of Storms destroyed + events.CancelEvent(EVENT_THORIM_S_HAMMER); + break; + case 2: // Tower of Flames destroyed + events.CancelEvent(EVENT_MIMIRON_S_INFERNO); + break; + case 3: // Tower of Frost destroyed + events.CancelEvent(EVENT_HODIR_S_FURY); + break; + case 4: // Tower of Nature destroyed + events.CancelEvent(EVENT_FREYA_S_WARD); + break; + } + } +}; + +//#define BOSS_DEBUG + +struct boss_flame_leviathan_seatAI : public PassiveAI +{ + boss_flame_leviathan_seatAI(Creature *c) : PassiveAI(c), vehicle(c->GetVehicleKit()) + { + assert(vehicle); +#ifdef BOSS_DEBUG + me->SetReactState(REACT_AGGRESSIVE); +#endif + } + + Vehicle* vehicle; + +#ifdef BOSS_DEBUG + void MoveInLineOfSight(Unit *who) + { + if (who->GetTypeId() == TYPEID_PLAYER && CAST_PLR(who)->isGameMaster() + && !who->GetVehicle() && vehicle->GetPassenger(SEAT_TURRET)) + who->EnterVehicle(vehicle, SEAT_PLAYER); + } +#endif + + void PassengerBoarded(Unit* who, int8 seatId, bool apply) + { + if (!me->GetVehicle()) + return; + + if (seatId == SEAT_PLAYER) + { + if (!apply) + return; + + if (Creature* turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET))) + { + turret->setFaction(me->GetVehicleBase()->getFaction()); + turret->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable + turret->AI()->AttackStart(who); + } + if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) + { + device->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + device->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + else if (seatId == SEAT_TURRET) + { + if (apply) + return; + + if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) + { + device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + device->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable + } + } + } +}; + +struct boss_flame_leviathan_defense_turretAI : public TurretAI +{ + boss_flame_leviathan_defense_turretAI(Creature *c) : TurretAI(c) {} + + void DamageTaken(Unit* who, uint32 &damage) + { + if (!CanAIAttack(who)) + damage = 0; + } + + bool CanAIAttack(const Unit *who) const + { + if (who->GetTypeId() != TYPEID_PLAYER || !who->GetVehicle() || who->GetVehicleBase()->GetEntry() != 33114) + return false; + return true; + } +}; + +struct boss_flame_leviathan_overload_deviceAI : public PassiveAI +{ + boss_flame_leviathan_overload_deviceAI(Creature* pCreature) : PassiveAI(pCreature) {} + + void DoAction(const int32 param) + { + if (param == EVENT_SPELLCLICK) + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (me->GetVehicle()) + { + if (Unit* pPlayer = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) + { + pPlayer->ExitVehicle(); + me->GetVehicleBase()->CastSpell(pPlayer, SPELL_SMOKE_TRAIL, true); + if (Unit* leviathan = me->GetVehicleBase()->GetVehicleBase()) + pPlayer->GetMotionMaster()->MoveKnockbackFrom(leviathan->GetPositionX(), leviathan->GetPositionY(), 30, 30); + } + } + } + } +}; + +struct boss_flame_leviathan_safety_containerAI : public PassiveAI +{ + boss_flame_leviathan_safety_containerAI(Creature *c) : PassiveAI(c) {} + + void MovementInform(uint32 /*type*/, uint32 id) + { + if (id == me->GetEntry()) + { + if (Creature* pLiquid = DoSummon(MOB_LIQUID, me, 0)) + pLiquid->CastSpell(pLiquid, 62494, true); + me->DisappearAndDie(); // this will relocate creature to sky + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!me->GetVehicle() && me->isSummon() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) + me->GetMotionMaster()->MoveFall(409.8f, me->GetEntry()); + } +}; + +struct spell_pool_of_tarAI : public TriggerAI +{ + spell_pool_of_tarAI(Creature *c) : TriggerAI(c) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void DamageTaken(Unit * /*who*/, uint32 &damage) + { + damage = 0; + } + + void SpellHit(Unit* /*caster*/, const SpellEntry *spell) + { + if (spell->SchoolMask & SPELL_SCHOOL_MASK_FIRE && !me->HasAura(SPELL_BLAZE)) + me->CastSpell(me, SPELL_BLAZE, true); + } +}; + +struct npc_colossusAI : public ScriptedAI +{ + npc_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance *pInstance; + Position pPos; + + void JustDied(Unit* /*Who*/) + { + if (me->GetHomePosition().IsInDist(Center,50.f)) + { + if (pInstance) + pInstance->SetData(TYPE_COLOSSUS,pInstance->GetData(TYPE_COLOSSUS)+1); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_boss_flame_leviathan(Creature* pCreature) +{ + return new boss_flame_leviathanAI (pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan_seat(Creature* pCreature) +{ + return new boss_flame_leviathan_seatAI (pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan_defense_turret(Creature* pCreature) +{ + return new boss_flame_leviathan_defense_turretAI (pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan_overload_device(Creature* pCreature) +{ + return new boss_flame_leviathan_overload_deviceAI (pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan_safety_containerAI(Creature* pCreature) +{ + return new boss_flame_leviathan_safety_containerAI(pCreature); +} + +CreatureAI* GetAI_spell_pool_of_tar(Creature* pCreature) +{ + return new spell_pool_of_tarAI (pCreature); +} + +CreatureAI* GetAI_npc_colossus(Creature* pCreature) +{ + return new npc_colossusAI(pCreature); +} + +void AddSC_boss_flame_leviathan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_flame_leviathan"; + newscript->GetAI = &GetAI_boss_flame_leviathan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_flame_leviathan_seat"; + newscript->GetAI = &GetAI_boss_flame_leviathan_seat; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_flame_leviathan_defense_turret"; + newscript->GetAI = &GetAI_boss_flame_leviathan_defense_turret; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_flame_leviathan_overload_device"; + newscript->GetAI = &GetAI_boss_flame_leviathan_overload_device; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_flame_leviathan_safety_container"; + newscript->GetAI = &GetAI_boss_flame_leviathan_safety_containerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "spell_pool_of_tar"; + newscript->GetAI = &GetAI_spell_pool_of_tar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_colossus"; + newscript->GetAI = &GetAI_npc_colossus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp new file mode 100644 index 00000000000..ee995878a0e --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO = -1603180, + SAY_AGGRO_WITH_ELDER = -1603181, + SAY_SLAY_1 = -1603182, + SAY_SLAY_2 = -1603183, + SAY_DEATH = -1603184, + SAY_BERSERK = -1603185, + SAY_SUMMON_CONSERVATOR = -1603186, + SAY_SUMMON_TRIO = -1603187, + SAY_SUMMON_LASHERS = -1603188, + SAY_YS_HELP = -1603189, + + // Elder Brightleaf + SAY_BRIGHTLEAF_AGGRO = -1603190, + SAY_BRIGHTLEAF_SLAY_1 = -1603191, + SAY_BRIGHTLEAF_SLAY_2 = -1603192, + SAY_BRIGHTLEAF_DEATH = -1603193, + + // Elder Ironbranch + SAY_IRONBRANCH_AGGRO = -1603194, + SAY_IRONBRANCH_SLAY_1 = -1603195, + SAY_IRONBRANCH_SLAY_2 = -1603196, + SAY_IRONBRANCH_DEATH = -1603197, + + // Elder Stonebark + SAY_STONEBARK_AGGRO = -1603198, + SAY_STONEBARK_SLAY_1 = -1603199, + SAY_STONEBARK_SLAY_2 = -1603200, + SAY_STONEBARK_DEATH = -1603201, +}; + +enum +{ + // Con-speed-atory timed achievement. + // TODO Should be started when 1st trash is killed. + ACHIEV_CON_SPEED_ATORY_START_EVENT = 21597, + SPELL_ACHIEVEMENT_CHECK = 65074, + + // Lumberjacked timed achievement. + // TODO should be started when 1st elder is killed. + // Spell should be casted when 3rd elder is killed. + ACHIEV_LUMBERJACKED = 21686, + SPELL_LUMBERJACKED_ACHIEVEMENT_CHECK = 65296, +}; + +struct boss_freyaAI : public BossAI +{ + boss_freyaAI(Creature* pCreature) : BossAI(pCreature, TYPE_FREYA) + { + } + + void Reset() + { + _Reset(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + + // cast is not rewarding the achievement. + // DoCast(SPELL_ACHIEVEMENT_CHECK); + instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_ACHIEVEMENT_CHECK); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + _EnterCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; +//SPELLS TODO: + +// + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_freya(Creature* pCreature) +{ + return new boss_freyaAI(pCreature); +} + +void AddSC_boss_freya() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_freya"; + newscript->GetAI = &GetAI_boss_freya; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp new file mode 100644 index 00000000000..f84c638d3e3 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO = -1603290, + SAY_SLAY_1 = -1603291, + SAY_SLAY_2 = -1603292, + SAY_KITE = -1603293, + SAY_DEATH = -1603294, + SAY_BERSERK = -1603295, + SAY_HARDMODE_ON = -1603296, +}; diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp new file mode 100644 index 00000000000..6facd8ac639 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO = -1603210, + SAY_SLAY_1 = -1603211, + SAY_SLAY_2 = -1603212, + SAY_FLASH_FREEZE = -1603213, + SAY_STALACTITE = -1603214, + SAY_DEATH = -1603215, + SAY_BERSERK = -1603216, + SAY_YS_HELP = -1603217, + SAY_HARD_MODE_MISSED = -1603218, +}; + +struct boss_hodirAI : public BossAI +{ + boss_hodirAI(Creature *pCreature) : BossAI(pCreature, TYPE_HODIR) + { + } + + void Reset() + { + _Reset(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + _EnterCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; +//SPELLS TODO: + +// + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_hodir(Creature* pCreature) +{ + return new boss_hodirAI(pCreature); +} + +void AddSC_boss_hodir() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hodir"; + newscript->GetAI = &GetAI_boss_hodir; + newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp new file mode 100644 index 00000000000..05f9ecd3c66 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +#define SPELL_FLAME_JETS 62680 +#define SPELL_SCORCH 62546 +#define SPELL_SLAG_POT 62717 + +enum Yells +{ + SAY_AGGRO = -1603220, + SAY_SLAY_1 = -1603221, + SAY_SLAY_2 = -1603222, + SAY_DEATH = -1603223, + SAY_SUMMON = -1603224, + SAY_SLAG_POT = -1603225, + SAY_SCORCH_1 = -1603226, + SAY_SCORCH_2 = -1603227, + SAY_BERSERK = -1603228, +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 20951, +}; + +struct boss_ignis_AI : public BossAI +{ + boss_ignis_AI(Creature *pCreature) : BossAI(pCreature, TYPE_IGNIS) {} + + uint32 uiFlameJetsTimer; + uint32 uiScorchTimer; + uint32 uiSlagPotTimer; + + void Reset() + { + _Reset(); + uiFlameJetsTimer = 32000; + uiScorchTimer = 100; + uiSlagPotTimer = 100; + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO,me); + _EnterCombat(); + + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetPositionY() < 150 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(false); + me->GetMotionMaster()->MoveTargetedHome(); + } + + if (uiFlameJetsTimer <= diff) + { + DoCast(SPELL_FLAME_JETS); + uiFlameJetsTimer = 25000; + } else uiFlameJetsTimer -= diff; + + if (uiScorchTimer <= diff) + { + DoScriptText(RAND(SAY_SCORCH_1,SAY_SCORCH_2), me); + DoCast(SPELL_SCORCH); + uiScorchTimer = 20000; + } else uiScorchTimer -= diff; + + if (uiSlagPotTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(SAY_SLAG_POT, me); + DoCast(pTarget, SPELL_SLAG_POT); + } + uiSlagPotTimer = 30000; + } else uiSlagPotTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ignis(Creature* pCreature) +{ + return new boss_ignis_AI (pCreature); +} +void AddSC_boss_ignis() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ignis"; + newscript->GetAI = &GetAI_boss_ignis; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp new file mode 100644 index 00000000000..2080b458a1b --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" +#include "Vehicle.h" + +#define SPELL_ARM_DEAD_DAMAGE RAID_MODE(63629,63979) +#define SPELL_TWO_ARM_SMASH RAID_MODE(63356,64003) +#define SPELL_ONE_ARM_SMASH RAID_MODE(63573,64006) +#define SPELL_STONE_SHOUT RAID_MODE(63716,64005) +#define SPELL_PETRIFY_BREATH RAID_MODE(62030,63980) + +#define SPELL_STONE_GRIP RAID_MODE(62166,63981) +#define SPELL_ARM_SWEEP RAID_MODE(63766,63983) + +enum Events +{ + EVENT_NONE = 0, + EVENT_SMASH, + EVENT_GRIP, + EVENT_SWEEP, +}; + +enum Yells +{ + SAY_AGGRO = -1603230, + SAY_SLAY_1 = -1603231, + SAY_SLAY_2 = -1603232, + SAY_LEFT_ARM_GONE = -1603233, + SAY_RIGHT_ARM_GONE = -1603234, + SAY_SHOCKWAVE = -1603235, + SAY_GRAB_PLAYER = -1603236, + SAY_DEATH = -1603237, + SAY_BERSERK = -1603238, +}; + +enum +{ + ACHIEV_DISARMED_START_EVENT = 21687, +}; + +struct boss_kologarnAI : public BossAI +{ + boss_kologarnAI(Creature *pCreature) : BossAI(pCreature, TYPE_KOLOGARN), vehicle(pCreature->GetVehicleKit()), + left(false), right(false) + { + assert(vehicle); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); // i think this is a hack, but there is no other way to disable his rotation + } + + Vehicle *vehicle; + bool left, right; + + void AttackStart(Unit *who) + { + me->Attack(who, true); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void KilledUnit(Unit* /*who*/) + { + DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_2), me); + } + + void PassengerBoarded(Unit *who, int8 /*seatId*/, bool apply) + { + if (who->GetTypeId() == TYPEID_UNIT) + { + if (who->GetEntry() == 32933) + left = apply; + else if (who->GetEntry() == 32934) + right = apply; + + if (!apply && instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT); + + who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + CAST_CRE(who)->SetReactState(REACT_PASSIVE); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + _EnterCombat(); + events.ScheduleEvent(EVENT_SMASH, 5000); + events.ScheduleEvent(EVENT_SWEEP, 10000); + events.ScheduleEvent(EVENT_GRIP, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + // TODO: because we are using hack, he is stunned and cannot cast, so we use triggered for every spell + switch(events.GetEvent()) + { + case EVENT_NONE: + break; + case EVENT_SMASH: + if (left && right) + DoCastVictim(SPELL_TWO_ARM_SMASH, true); + else if (left || right) + DoCastVictim(SPELL_ONE_ARM_SMASH, true); + events.RepeatEvent(15000); + break; + case EVENT_SWEEP: + if (left) + DoCastAOE(SPELL_ARM_SWEEP, true); + events.RepeatEvent(15000); + break; + case EVENT_GRIP: + if (right) + DoCastAOE(SPELL_STONE_GRIP, true); + events.RepeatEvent(15000); + break; + default: + events.PopEvent(); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kologarn(Creature* pCreature) +{ + return new boss_kologarnAI (pCreature); +} + +void AddSC_boss_kologarn() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kologarn"; + newscript->GetAI = &GetAI_boss_kologarn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp new file mode 100644 index 00000000000..2b9994d5d9b --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO = -1603240, + SAY_HARDMODE_ON = -1603241, + SAY_MKII_ACTIVATE = -1603242, + SAY_MKII_SLAY_1 = -1603243, + SAY_MKII_SLAY_2 = -1603244, + SAY_MKII_DEATH = -1603245, + SAY_VX001_ACTIVATE = -1603246, + SAY_VX001_SLAY_1 = -1603247, + SAY_VX001_SLAY_2 = -1603248, + SAY_VX001_DEATH = -1603249, + SAY_AERIAL_ACTIVATE = -1603250, + SAY_AERIAL_SLAY_1 = -1603251, + SAY_AERIAL_SLAY_2 = -1603252, + SAY_AERIAL_DEATH = -1603253, + SAY_V07TRON_ACTIVATE = -1603254, + SAY_V07TRON_SLAY_1 = -1603255, + SAY_V07TRON_SLAY_2 = -1603256, + SAY_V07TRON_DEATH = -1603257, + SAY_BERSERK = -1603258, + SAY_YS_HELP = -1603259, +}; diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp new file mode 100644 index 00000000000..c61f1046474 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: razorscale +SDAuthor: MaXiMiUS +SD%Complete: 65 +EndScriptData */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +//not in db +#define SAY_AGGRO -2000000 +#define SAY_KILL -2000001 +#define SAY_PHASE_2_TRANS -2000002 +#define SAY_PHASE_3_TRANS -2000003 +#define EMOTE_BREATH -2000004 + +enum Spells +{ + SPELL_FLAMEBUFFET = 64016, + SPELL_FIREBALL = 62796, + + SPELL_WINGBUFFET = 62666, + SPELL_FLAMEBREATH = 63317, + SPELL_FUSEARMOR = 64771, + SPELL_DEVOURINGFLAME = 63014 +}; + +enum Mobs +{ + NPC_DARK_RUNE_SENTINEL = 33846 +}; + +struct boss_razorscaleAI : public BossAI +{ + boss_razorscaleAI(Creature *pCreature) : BossAI(pCreature, TYPE_RAZORSCALE) {} + + uint8 Phase; + + uint32 FlameBreathTimer; + uint32 FuseArmorTimer; + uint32 DevouringFlameTimer; + uint32 FlameBuffetTimer; + uint32 SummonAddsTimer; + uint32 WingBuffetTimer; + uint32 FireballTimer; + //uint32 StunTimer; + //uint32 CastSpellsTimer; + + bool InitialSpawn; + bool IsFlying; + + void Reset() + { + Phase = 1; + + FlyPhase(Phase, 0); + + FlameBreathTimer = 20000; + DevouringFlameTimer = 2000; + FuseArmorTimer = 15000; + FlameBuffetTimer = 3000; + SummonAddsTimer = 45000; + WingBuffetTimer = 17000; + FireballTimer = 18000; + //StunTimer = 30000; + //CastSpellsTimer = 0; + + InitialSpawn = true; + IsFlying = true; + + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + } + + void JustDied(Unit* /*Killer*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetPositionY() > -60 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(false); + me->GetMotionMaster()->MoveTargetedHome(); + } + + // Victim is not controlled by a player (should never happen) + if (me->getVictim() && !me->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) + me->Kill(me->getVictim()); + + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 99 && Phase == 1) // TODO: Only land (exit Phase 1) if brought down with harpoon guns! This is important! + { + Phase = 2; + DoScriptText(SAY_PHASE_2_TRANS, me); // Audio: "Move quickly! She won't remain grounded for long!" + } + + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 33 && Phase == 2) // Health under 33%, Razorscale can't fly anymore. + { + Phase = 3; + DoScriptText(SAY_PHASE_3_TRANS, me); // "Razorscale lands permanently!" + // TODO: Cast Devouring Flame on all harpoon guns simultaneously, briefly after Phase 3 starts (lasts until the harpoon guns are destroyed) + } + + /* + if (Phase == 2 && CastSpellsTimer > 0) // 5 seconds of spell casting, after stun breaks, during Phase 2 + { + if (CastSpellsTimer <= diff) // 5 seconds are up + Phase = 1; // Return to phase 1 + else + CastSpellsTimer -= diff; + }*/ + + FlyPhase(Phase, diff); + + if (Phase >= 2) // Ground Phase (Phase 3 = permanent ground phase) + { + if (FuseArmorTimer <= diff) + { + DoCastVictim(SPELL_FUSEARMOR); + FuseArmorTimer = 10000; + } else FuseArmorTimer -= diff; + + if (WingBuffetTimer <= diff) + { + DoCast(SPELL_WINGBUFFET); + WingBuffetTimer = urand(7000,14000); + } else WingBuffetTimer -= diff; + + if (FireballTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) + { + me->SetInFront(pTarget); + DoCast(pTarget, SPELL_FIREBALL); + } + + FireballTimer = 18000; + } else FireballTimer -= diff; + + if (FlameBreathTimer <= diff) + { + DoScriptText(EMOTE_BREATH, me); // TODO: "Razorscale takes a deep breath..." + DoCastVictim(SPELL_FLAMEBREATH); + FlameBreathTimer = 15000; + WingBuffetTimer = 0; + } else FlameBreathTimer -= diff; + + if (Phase == 3) + { + if (FlameBuffetTimer <= diff) + { + DoScriptText(EMOTE_BREATH, me); + std::list pTargets; + SelectTargetList(pTargets, RAID_MODE(3,9), SELECT_TARGET_RANDOM, 100, true); + uint8 i = 0; + for (std::list::const_iterator itr = pTargets.begin(); itr != pTargets.end();) + { + if (me->HasInArc(M_PI, *itr)) + { + DoCast(*itr, SPELL_FLAMEBUFFET, true); + ++i; + } + if (++itr == pTargets.end() || i == RAID_MODE(3,9)) + { + AttackStart(*--itr); // seems to attack targets randomly during perma-ground phase.. + break; + } + } + FlameBuffetTimer = 25000; + } else FlameBuffetTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + else if (Phase == 1) //Flying Phase + { + if (InitialSpawn) + SummonAdds(); + + InitialSpawn = false; + + if (FireballTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) + { + me->SetInFront(pTarget); + DoCast(pTarget, SPELL_FIREBALL); + } + + FireballTimer = 18000; + } else FireballTimer -= diff; + + if (DevouringFlameTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) + { + me->SetInFront(pTarget); + DoCast(pTarget, SPELL_DEVOURINGFLAME); + } + + DevouringFlameTimer = 10000; + } else DevouringFlameTimer -= diff; + + if (SummonAddsTimer <= diff) + SummonAdds(); + else SummonAddsTimer -= diff; + } + } + + void SummonAdds() + { + // TODO: Adds will come in waves from mole machines. One mole can spawn a Dark Rune Watcher + // with 1-2 Guardians, or a lone Sentinel. Up to 4 mole machines can spawn adds at any given time. + uint8 random = urand(1,4); + for (uint8 i = 0; i < random; ++i) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) + { + float x = std::max(500.0f, std::min(650.0f, pTarget->GetPositionX() + irand(-20,20))); // Safe range is between 500 and 650 + float y = std::max(-235.0f, std::min(-145.0f, pTarget->GetPositionY() + irand(-20,20))); // Safe range is between -235 and -145 + float z = me->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); // Ground level + // TODO: Spawn drillers, then spawn adds 5 seconds later + if (Creature *pAdd = me->SummonCreature(NPC_DARK_RUNE_SENTINEL, x, y, z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)) + pAdd->AI()->AttackStart(pTarget); + } + } + SummonAddsTimer = 45000; + } + + void FlyPhase(uint8 Phase, const uint32 /*diff*/) + { + const float x = 587.54; + const float y = -174.92; + const float GroundLevel = me->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); + const float FlightHeight = GroundLevel + 4.0f; // TODO: Fly out of range of attacks (442 is sufficient height for this), minus ~(10*number of harpoon gun chains attached to Razorscale) + + if (Phase == 1) // Always flying during Phase 1 + IsFlying = true; + + me->SetFlying(IsFlying); + me->SendMovementFlagUpdate(); + me->SetSpeed(MOVE_WALK, IsFlying ? 7.0f : 2.5f, IsFlying); + + if (Phase == 1) // Flying Phase + { + if (me->GetPositionZ() > FlightHeight) // Correct height, stop moving + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + else // Incorrect height + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->GetMotionMaster()->MovePoint(0, x, y, FlightHeight + 0.5f); // Fly to slightly above (x, y, FlightHeight) + } + } + else // Ground Phases + { + const float CurrentGroundLevel = me->GetBaseMap()->GetHeight(me->GetPositionX(), me->GetPositionY(), MAX_HEIGHT); + //if (StunTimer == 30000) // Only fly around if not stunned. + //{ + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + if (IsFlying && me->GetPositionZ() > CurrentGroundLevel) // Fly towards the ground + me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), CurrentGroundLevel); + // TODO: Swoop up just before landing + else + IsFlying = false; // Landed, no longer flying + //} + + //if (!IsFlying &&Phase == 2 && CastSpellsTimer == 0 && StunTimer >= diff) // No longer flying, non-permanent ground phase, and not casting spells + //{ + // TODO: Add stun here. 30 second stun after Razorscale is grounded by harpoon guns + //StunTimer -= diff; + //} + //else if (StunTimer != 30000 && (StunTimer < 0 || Phase == 3)) // Stun is active, and needs to end. Note: Stun breaks instantly if Phase 3 starts + //{ + // TODO: Remove stun here. + //DoCast(SPELL_WINGBUFFET); // "Used in the beginning of the phase." + //WingBuffetTimer = urand(7000,14000); + //StunTimer = 30000; // Reinitialize the stun timer + //if (Phase == 2) // Non-permanent ground phase + // CastSpellsTimer = 5000; // Five seconds of casting before returning to Phase 1 + //} + } + } +}; + +CreatureAI* GetAI_boss_razorscale(Creature* pCreature) +{ + return new boss_razorscaleAI (pCreature); +} + +void AddSC_boss_razorscale() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_razorscale"; + newscript->GetAI = &GetAI_boss_razorscale; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp new file mode 100644 index 00000000000..bbab077e10e --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO_1 = -1603270, + SAY_AGGRO_2 = -1603271, + SAY_SPECIAL_1 = -1603272, + SAY_SPECIAL_2 = -1603273, + SAY_SPECIAL_3 = -1603274, + SAY_JUMPDOWN = -1603275, + SAY_SLAY_1 = -1603276, + SAY_SLAY_2 = -1603277, + SAY_BERSERK = -1603278, + SAY_WIPE = -1603279, + SAY_DEATH = -1603280, + SAY_END_NORMAL_1 = -1603281, + SAY_END_NORMAL_2 = -1603282, + SAY_END_NORMAL_3 = -1603283, + SAY_END_HARD_1 = -1603284, + SAY_END_HARD_2 = -1603285, + SAY_END_HARD_3 = -1603286, + SAY_YS_HELP = -1603287, +}; + +struct boss_thorimAI : public BossAI +{ + boss_thorimAI(Creature* pCreature) : BossAI(pCreature, TYPE_THORIM) + { + } + + void Reset() + { + _Reset(); + } + + void EnterEvadeMode() + { + DoScriptText(SAY_WIPE, me); + _EnterEvadeMode(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me); + _EnterCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; +//SPELLS TODO: + +// + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_thorim(Creature* pCreature) +{ + return new boss_thorimAI(pCreature); +} + +void AddSC_boss_thorim() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_thorim"; + newscript->GetAI = &GetAI_boss_thorim; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp new file mode 100644 index 00000000000..58123951d2f --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp @@ -0,0 +1,850 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + TODO: + Add achievments + Boombot explosion only hurt allies to the npc at the moment + Boombot explosion visual + Test the enrage timer + Fix gravity bomb - tractor beam. + Fix void zone spell + If the boss is to close to a scrap pile -> no summon + make the life sparks visible... +*/ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Spells +{ + SPELL_TYMPANIC_TANTRUM = 62776, + SPELL_SEARING_LIGHT_10 = 63018, + SPELL_SEARING_LIGHT_25 = 65121, + + SPELL_GRAVITY_BOMB_10 = 63024, + SPELL_GRAVITY_BOMB_25 = 63234, + SPELL_GRAVITY_BOMB_AURA_10 = 63025, + SPELL_GRAVITY_BOMB_AURA_25 = 63233, + + SPELL_HEARTBREAK_10 = 65737, + SPELL_HEARTBREAK_25 = 64193, + + SPELL_ENRAGE = 26662, + + //------------------VOID ZONE-------------------- + SPELL_VOID_ZONE_10 = 64203, + SPELL_VOID_ZONE_25 = 64235, + + // Life Spark + SPELL_STATIC_CHARGED_10 = 64227, + SPELL_STATIC_CHARGED_25 = 64236, + SPELL_SHOCK = 64230, + + //----------------XT-002 HEART------------------- + SPELL_EXPOSED_HEART = 63849, + + //---------------XM-024 PUMMELLER---------------- + SPELL_ARCING_SMASH = 8374, + SPELL_TRAMPLE = 5568, + SPELL_UPPERCUT = 10966, + + //------------------BOOMBOT----------------------- + SPELL_BOOM = 62834, +}; + +enum Timers +{ + TIMER_TYMPANIC_TANTRUM_MIN = 32000, + TIMER_TYMPANIC_TANTRUM_MAX = 36000, + TIMER_SEARING_LIGHT = 20000, + TIMER_SPAWN_LIFE_SPARK = 9000, + TIMER_GRAVITY_BOMB = 20000, + TIMER_HEART_PHASE = 30000, + TIMER_ENRAGE = 600000, + TIMER_GRAVITY_BOMB_AURA = 8900, + + TIMER_VOID_ZONE = 3000, + + // Life Spark + TIMER_SHOCK = 12000, + + // Pummeller + // Timers may be off + TIMER_ARCING_SMASH = 27000, + TIMER_TRAMPLE = 22000, + TIMER_UPPERCUT = 17000, + + TIMER_SPAWN_ADD = 12000, +}; + +enum Creatures +{ + NPC_VOID_ZONE = 34001, + NPC_LIFE_SPARK = 34004, + NPC_XT002_HEART = 33329, + NPC_XS013_SCRAPBOT = 33343, + NPC_XM024_PUMMELLER = 33344, + NPC_XE321_BOOMBOT = 33346, +}; + +enum Actions +{ + ACTION_ENTER_HARD_MODE = 0, +}; + +enum XT002Data +{ + DATA_TRANSFERED_HEALTH = 0, +}; + +enum Yells +{ + SAY_AGGRO = -1603300, + SAY_HEART_OPENED = -1603301, + SAY_HEART_CLOSED = -1603302, + SAY_TYMPANIC_TANTRUM = -1603303, + SAY_SLAY_1 = -1603304, + SAY_SLAY_2 = -1603305, + SAY_BERSERK = -1603306, + SAY_DEATH = -1603307, + SAY_SUMMON = -1603308, +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 21027, +}; + +//#define GRAVITY_BOMB_DMG_MIN_10 11700 +//#define GRAVITY_BOMB_DMG_MAX_10 12300 +//#define GRAVITY_BOMB_DMG_MIN_25 14625 +//#define GRAVITY_BOMB_DMG_MAX_25 15375 +//#define GRAVITY_BOMB_RADIUS 12 + +//#define VOID_ZONE_DMG_10 5000 +//#define VOID_ZONE_DMG_25 7500 +//#define VOID_ZONE_RADIUS + + +/************************************************ +-----------------SPAWN LOCATIONS----------------- +************************************************/ +//Shared Z-level +#define SPAWN_Z 412 +//Lower right +#define LR_X 796 +#define LR_Y -94 +//Lower left +#define LL_X 796 +#define LL_Y 57 +//Upper right +#define UR_X 890 +#define UR_Y -82 +//Upper left +#define UL_X 894 +#define UL_Y 62 + +/*------------------------------------------------------- + * + * XT-002 DECONSTRUCTOR + * + *///---------------------------------------------------- +struct boss_xt002_AI : public BossAI +{ + boss_xt002_AI(Creature *pCreature) : BossAI(pCreature, TYPE_XT002) + { + } + + uint32 uiSearingLightTimer; + uint32 uiSpawnLifeSparkTimer; + uint32 uiGravityBombTimer; + uint32 uiGravityBombAuraTimer; + uint32 uiTympanicTantrumTimer; + uint32 uiHeartPhaseTimer; + uint32 uiSpawnAddTimer; + uint32 uiEnrageTimer; + + bool searing_light_active; + uint64 uiSearingLightTarget; + + bool gravity_bomb_active; + uint64 uiGravityBombTarget; + + uint8 phase; + uint8 heart_exposed; + bool enraged; + + uint32 transferHealth; + bool enterHardMode; + bool hardMode; + + void Reset() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + + //Makes XT-002 to cast a light bomb 10 seconds after aggro. + uiSearingLightTimer = TIMER_SEARING_LIGHT/2; + uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; + uiGravityBombTimer = TIMER_GRAVITY_BOMB; + uiGravityBombAuraTimer = TIMER_GRAVITY_BOMB_AURA; + uiHeartPhaseTimer = TIMER_HEART_PHASE; + uiSpawnAddTimer = TIMER_SPAWN_ADD; + uiEnrageTimer = TIMER_ENRAGE; + + //Tantrum is casted a bit slower the first time. + uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX) * 2; + + searing_light_active = false; + gravity_bomb_active = false; + enraged = false; + hardMode = false; + enterHardMode = false; + + phase = 1; + heart_exposed = 0; + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + _EnterCombat(); + + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void DoAction(const int32 action) + { + switch (action) + { + case ACTION_ENTER_HARD_MODE: + if (!hardMode) + { + hardMode = true; + + // Enter hard mode + enterHardMode = true; + + // set max health + me->SetHealth(me->GetMaxHealth()); + + // Get his heartbreak buff + me->CastSpell(me, RAID_MODE(SPELL_HEARTBREAK_10, SPELL_HEARTBREAK_25), true); + } + break; + } + } + + void SetData(uint32 id, uint32 value) + { + switch(id) + { + case DATA_TRANSFERED_HEALTH: + transferHealth = value; + break; + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (enterHardMode) + { + SetPhaseOne(); + enterHardMode = false; + } + + // Handles spell casting. These spells only occur during phase 1 and hard mode + if (phase == 1 || hardMode) + { + if (uiSearingLightTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, RAID_MODE(SPELL_SEARING_LIGHT_10, SPELL_SEARING_LIGHT_25)); + uiSearingLightTarget = pTarget->GetGUID(); + } + uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; + if (hardMode) + searing_light_active = true; + uiSearingLightTimer = TIMER_SEARING_LIGHT; + } else uiSearingLightTimer -= diff; + + if (uiGravityBombTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, RAID_MODE(SPELL_GRAVITY_BOMB_10,SPELL_GRAVITY_BOMB_25)); + uiGravityBombTarget = pTarget->GetGUID(); + } + uiGravityBombTimer = TIMER_GRAVITY_BOMB; + gravity_bomb_active = true; + } else uiGravityBombTimer -= diff; + + if (uiTympanicTantrumTimer <= 0) + { + DoScriptText(SAY_TYMPANIC_TANTRUM, me); + DoCast(SPELL_TYMPANIC_TANTRUM); + uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX); + } else uiTympanicTantrumTimer -= diff; + } + + if (!hardMode) + { + if (phase == 1) + { + if (HealthBelowPct(75) && heart_exposed == 0) + { + exposeHeart(); + } + else if (HealthBelowPct(50) && heart_exposed == 1) + { + exposeHeart(); + } + else if (HealthBelowPct(25) && heart_exposed == 2) + { + exposeHeart(); + } + + DoMeleeAttackIfReady(); + } + else + { + //Stop moving + me->StopMoving(); + + //Start summoning adds + if (uiSpawnAddTimer <= diff) + { + DoScriptText(SAY_SUMMON, me); + + // Spawn Pummeller + switch (rand() % 4) + { + case 0: me->SummonCreature(NPC_XM024_PUMMELLER, LR_X, LR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 1: me->SummonCreature(NPC_XM024_PUMMELLER, LL_X, LL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 2: me->SummonCreature(NPC_XM024_PUMMELLER, UR_X, UR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 3: me->SummonCreature(NPC_XM024_PUMMELLER, UL_X, UL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + } + + // Spawn 5 Bombs + for (int8 n = 0; n < 5; n++) + { + //Some randomes are added so they wont spawn in a pile + switch(rand() % 4) + { + case 0: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(LR_X - 3, LR_X + 3), irand(LR_Y - 3, LR_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 1: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(LL_X - 3, LL_X + 3), irand(LL_Y - 3, LL_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 2: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(UR_X - 3, UR_X + 3), irand(UR_Y - 3, UR_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 3: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(UL_X - 3, UL_X + 3), irand(UL_Y - 3, UL_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + } + } + + //Spawn 5 Scrapbots + switch (rand() % 4) + { + case 0: me->SummonCreature(NPC_XE321_BOOMBOT, LR_X, LR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 1: me->SummonCreature(NPC_XE321_BOOMBOT, LL_X, LL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 2: me->SummonCreature(NPC_XE321_BOOMBOT, UR_X, UR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 3: me->SummonCreature(NPC_XE321_BOOMBOT, UL_X, UL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + } + + uiSpawnAddTimer = TIMER_SPAWN_ADD; + } else uiSpawnAddTimer -= diff; + + // Is the phase over? + if (uiHeartPhaseTimer <= diff) + { + DoScriptText(SAY_HEART_CLOSED, me); + SetPhaseOne(); + } + else + uiHeartPhaseTimer -= diff; + } + } + else + { + // Adding life sparks when searing light debuff runs out if hard mode + if (searing_light_active) + { + if (uiSpawnLifeSparkTimer <= diff) + { + if (Unit *pSearingLightTarget = me->GetUnit(*me, uiSearingLightTarget)) + pSearingLightTarget->SummonCreature(NPC_LIFE_SPARK, pSearingLightTarget->GetPositionX(), pSearingLightTarget->GetPositionY(), pSearingLightTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; + searing_light_active = false; + } else uiSpawnLifeSparkTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + if (gravity_bomb_active) + { + if (uiGravityBombAuraTimer <= diff) + { + if (Unit *pGravityBombTarget = me->GetUnit(*me, uiGravityBombTarget)) + { + pGravityBombTarget->RemoveAurasDueToSpell(RAID_MODE(SPELL_GRAVITY_BOMB_10,SPELL_GRAVITY_BOMB_25)); + if (hardMode) + { + //Remains spawned for 3 minutes + pGravityBombTarget->SummonCreature(NPC_VOID_ZONE, pGravityBombTarget->GetPositionX(), pGravityBombTarget->GetPositionY(), pGravityBombTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); + } + } + + gravity_bomb_active = false; + uiGravityBombAuraTimer = TIMER_GRAVITY_BOMB_AURA; + //gravityBomb(); + } else uiGravityBombAuraTimer -= diff; + } + + //Enrage stuff + if (!enraged) + if (uiEnrageTimer <= diff) + { + DoScriptText(SAY_BERSERK, me); + DoCast(me, SPELL_ENRAGE); + enraged = true; + } else uiEnrageTimer -= diff; + } + + void exposeHeart() + { + //Make untargetable + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + + //Summon the heart npc + me->SummonCreature(NPC_XT002_HEART, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 7, 0, TEMPSUMMON_TIMED_DESPAWN, TIMER_HEART_PHASE); + + // Start "end of phase 2 timer" + uiHeartPhaseTimer = TIMER_HEART_PHASE; + + //Phase 2 has offically started + phase = 2; + heart_exposed++; + + //Reset the add spawning timer + uiSpawnAddTimer = TIMER_SPAWN_ADD; + + DoScriptText(SAY_HEART_OPENED, me); + } + + void SetPhaseOne() + { + uiSearingLightTimer = TIMER_SEARING_LIGHT / 2; + uiGravityBombTimer = TIMER_GRAVITY_BOMB; + uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX); + uiSpawnAddTimer = TIMER_SPAWN_ADD; + + if (!hardMode) + me->ModifyHealth(-((int32)transferHealth)); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + phase = 1; + } + + // TODO: put in comment and kept for reference. The spell should be fixed properly in spell system, if necessary. + ////Have to do this the custom way since the original spell messes up player movement + //void gravityBomb() + //{ + // uint32 maxDamage = RAID_MODE(GRAVITY_BOMB_DMG_MAX_10, GRAVITY_BOMB_DMG_MAX_25); + // uint32 minDamage = RAID_MODE(GRAVITY_BOMB_DMG_MIN_10, GRAVITY_BOMB_DMG_MIN_25); + // uint16 range = GRAVITY_BOMB_RADIUS; + // Map* pMap = me->GetMap(); + // if (pMap && pMap->IsDungeon()) + // { + // Map::PlayerList const &PlayerList = pMap->GetPlayers(); + // for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + // { + // //If a player is within the range of the spell + // if (i->getSource() && i->getSource()->GetDistance2d(pGravityBombTarget) <= range) + // { + // //Deal damage to the victim + // int32 damage = urand(minDamage, maxDamage); + // i->getSource()->ModifyHealth(-damage); + // me->SendSpellNonMeleeDamageLog(i->getSource(), SPELL_GRAVITY_BOMB_AURA_10, damage, SPELL_SCHOOL_MASK_SHADOW, 0, 0, false, 0); + + // //Replacing the tractor beam effect + // i->getSource()->JumpTo(pGravityBombTarget, 5); + // } + // } + // } + //} +}; + +CreatureAI* GetAI_boss_xt002(Creature* pCreature) +{ + return new boss_xt002_AI(pCreature); +} + +/*------------------------------------------------------- + * + * XT-002 HEART + * + *///---------------------------------------------------- +struct mob_xt002_heartAI : public ScriptedAI +{ + mob_xt002_heartAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_EXPOSED_HEART); + } + + ScriptedInstance* m_pInstance; + + void JustDied(Unit * /*victim*/) + { + if (m_pInstance) + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + if (pXT002->AI()) + pXT002->AI()->DoAction(ACTION_ENTER_HARD_MODE); + + //removes the aura + me->RemoveAurasDueToSpell(SPELL_EXPOSED_HEART); + } + + void DamageTaken(Unit * /*pDone*/, uint32 &damage) + { + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + if (pXT002->AI()) + { + uint32 health = me->GetHealth(); + health -= damage; + if (health < 0) + health = 0; + + pXT002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetMaxHealth() - health); + } + } +}; + +CreatureAI* GetAI_mob_xt002_heart(Creature* pCreature) +{ + return new mob_xt002_heartAI(pCreature); +} + +/*------------------------------------------------------- + * + * XS-013 SCRAPBOT + * + *///---------------------------------------------------- +struct mob_scrapbotAI : public ScriptedAI +{ + mob_scrapbotAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = me->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + me->GetMotionMaster()->MoveChase(pXT002); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + { + if (me->GetDistance2d(pXT002) <= 0.5) + { + // TODO Send raid message + + // Increase health with 1 percent + pXT002->ModifyHealth(pXT002->GetMaxHealth() * 0.01); + + // Despawns the scrapbot + me->ForcedDespawn(); + } + } + } +}; + +CreatureAI* GetAI_mob_scrapbot(Creature* pCreature) +{ + return new mob_scrapbotAI(pCreature); +} + +/*------------------------------------------------------- + * + * XM-024 PUMMELLER + * + *///---------------------------------------------------- +struct mob_pummellerAI : public ScriptedAI +{ + mob_pummellerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + int32 uiArcingSmashTimer; + int32 uiTrampleTimer; + int32 uiUppercutTimer; + + void Reset() + { + uiArcingSmashTimer = TIMER_ARCING_SMASH; + uiTrampleTimer = TIMER_TRAMPLE; + uiUppercutTimer = TIMER_UPPERCUT; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->IsWithinMeleeRange(me->getVictim())) + { + if (uiArcingSmashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCING_SMASH); + uiArcingSmashTimer = TIMER_ARCING_SMASH; + } else uiArcingSmashTimer -= diff; + + if (uiTrampleTimer <= diff) + { + DoCast(me->getVictim(), SPELL_TRAMPLE); + uiTrampleTimer = TIMER_TRAMPLE; + } else uiTrampleTimer -= diff; + + if (uiUppercutTimer <= diff) + { + DoCast(me->getVictim(), SPELL_UPPERCUT); + uiUppercutTimer = TIMER_UPPERCUT; + } else uiUppercutTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_pummeller(Creature* pCreature) +{ + return new mob_pummellerAI(pCreature); +} + +/*------------------------------------------------------- + * + * XE-321 BOOMBOT + * + *///---------------------------------------------------- +struct mob_boombotAI : public ScriptedAI +{ + mob_boombotAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + me->GetMotionMaster()->MoveChase(pXT002); + } + + void JustDied(Unit * /*killer*/) + { + DoCast(SPELL_BOOM); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + { + if (me->GetDistance2d(pXT002) <= 0.5) + { + //Explosion + DoCast(me, SPELL_BOOM); + + //Despawns the boombot + me->ForcedDespawn(); + } + } + } +}; + +CreatureAI* GetAI_mob_boombot(Creature* pCreature) +{ + return new mob_boombotAI(pCreature); +} + +/*------------------------------------------------------- + * + * VOID ZONE + * + *///---------------------------------------------------- +struct mob_void_zoneAI : public ScriptedAI +{ + mob_void_zoneAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + + ScriptedInstance* m_pInstance; + uint32 uiVoidZoneTimer; + + void Reset() + { + uiVoidZoneTimer = TIMER_VOID_ZONE; + } + + void UpdateAI(const uint32 diff) + { + if (uiVoidZoneTimer <= diff) + { + //voidZone(); + uiVoidZoneTimer = TIMER_VOID_ZONE; + } else uiVoidZoneTimer -= diff; + } + + // TODO: put in comment and kept for reference. The spell should be fixed properly in spell system, if necessary. + //void voidZone() + //{ + // Map* pMap = me->GetMap(); + // if (pMap && pMap->IsDungeon()) + // { + // Map::PlayerList const &PlayerList = pMap->GetPlayers(); + // for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + // { + // // If a player is within the range of the spell + // if (i->getSource() && i->getSource()->GetDistance2d(me) <= 16) + // { + // // Deal damage to the victim + // int32 damage = RAID_MODE(VOID_ZONE_DMG_10, VOID_ZONE_DMG_25); + // me->DealDamage(i->getSource(), damage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); + // } + // } + // } + //} +}; + +CreatureAI* GetAI_mob_void_zone(Creature* pCreature) +{ + return new mob_void_zoneAI(pCreature); +} + +/*------------------------------------------------------- + * + * LIFE SPARK + * + *///---------------------------------------------------- +struct mob_life_sparkAI : public ScriptedAI +{ + mob_life_sparkAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + uint32 uiShockTimer; + + void Reset() + { + DoCast(me, RAID_MODE(SPELL_STATIC_CHARGED_10, SPELL_STATIC_CHARGED_25)); + uiShockTimer = 0; // first one is immediate. + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiShockTimer <= diff) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + DoCast(me->getVictim(), SPELL_SHOCK); + uiShockTimer = TIMER_SHOCK; + } + } + else uiShockTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_life_spark(Creature* pCreature) +{ + return new mob_life_sparkAI(pCreature); +} + +void AddSC_boss_xt002() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_xt002"; + newscript->GetAI = &GetAI_boss_xt002; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_xt002_heart"; + newscript->GetAI = &GetAI_mob_xt002_heart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_scrapbot"; + newscript->GetAI = &GetAI_mob_scrapbot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_pummeller"; + newscript->GetAI = &GetAI_mob_pummeller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_boombot"; + newscript->GetAI = &GetAI_mob_boombot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_void_zone"; + newscript->GetAI = &GetAI_mob_void_zone; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_life_spark"; + newscript->GetAI = &GetAI_mob_life_spark; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp new file mode 100644 index 00000000000..8f42f289204 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Sara_Yells +{ + SAY_SARA_PREFIGHT_1 = -1603310, + SAY_SARA_PREFIGHT_2 = -1603311, + SAY_SARA_AGGRO_1 = -1603312, + SAY_SARA_AGGRO_2 = -1603313, + SAY_SARA_AGGRO_3 = -1603314, + SAY_SARA_SLAY_1 = -1603315, + SAY_SARA_SLAY_2 = -1603316, + WHISP_SARA_INSANITY = -1603317, + SAY_SARA_PHASE2_1 = -1603318, + SAY_SARA_PHASE2_2 = -1603319, +}; + +enum YoggSaron_Yells +{ + SAY_PHASE2_1 = -1603330, + SAY_PHASE2_2 = -1603331, + SAY_PHASE2_3 = -1603332, + SAY_PHASE2_4 = -1603333, + SAY_PHASE2_5 = -1603334, + SAY_PHASE3 = -1603335, + SAY_VISION = -1603336, + SAY_SLAY_1 = -1603337, + SAY_SLAY_2 = -1603338, + WHISP_INSANITY_1 = -1603339, + WHISP_INSANITY_2 = -1603340, + SAY_DEATH = -1603341, +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 21001, +}; diff --git a/src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp new file mode 100644 index 00000000000..692dbf72473 --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum eGameObjects +{ + GO_KOLOGARN_CHEST_HERO = 195047, + GO_KOLOGARN_CHEST = 195046, + GO_THORIM_CHEST_HERO = 194315, + GO_THORIM_CHEST = 194314, + GO_HODIR_CHEST_HERO = 194308, + GO_HODIR_CHEST = 194307, + GO_FREYA_CHEST_HERO = 194325, + GO_FREYA_CHEST = 194324, + GO_LEVIATHAN_DOOR = 194905, + GO_LEVIATHAN_GATE = 194630 +}; + +struct instance_ulduar : public ScriptedInstance +{ + instance_ulduar(Map* pMap) : ScriptedInstance(pMap) { Initialize(); }; + + uint32 uiEncounter[MAX_ENCOUNTER]; + std::string m_strInstData; + uint8 flag; + + uint64 uiLeviathanGUID; + uint64 uiIgnisGUID; + uint64 uiRazorscaleGUID; + uint64 uiXT002GUID; + uint64 uiAssemblyGUIDs[3]; + uint64 uiKologarnGUID; + uint64 uiAuriayaGUID; + uint64 uiMimironGUID; + uint64 uiHodirGUID; + uint64 uiThorimGUID; + uint64 uiFreyaGUID; + uint64 uiVezaxGUID; + uint64 uiYoggSaronGUID; + uint64 uiAlgalonGUID; + uint64 uiLeviathanDoor[7]; + uint64 uiLeviathanGateGUID; + + uint64 uiKologarnChestGUID; + uint64 uiThorimChestGUID; + uint64 uiHodirChestGUID; + uint64 uiFreyaChestGUID; + + void Initialize() + { + uiLeviathanGUID = 0; + uiIgnisGUID = 0; + uiRazorscaleGUID = 0; + uiXT002GUID = 0; + uiKologarnGUID = 0; + uiAuriayaGUID = 0; + uiMimironGUID = 0; + uiHodirGUID = 0; + uiThorimGUID = 0; + uiFreyaGUID = 0; + uiVezaxGUID = 0; + uiYoggSaronGUID = 0; + uiAlgalonGUID = 0; + uiKologarnChestGUID = 0; + uiKologarnChestGUID = 0; + uiHodirChestGUID = 0; + uiFreyaChestGUID = 0; + uiLeviathanGateGUID = 0; + flag = 0; + + memset(&uiEncounter, 0, sizeof(uiEncounter)); + memset(&uiAssemblyGUIDs, 0, sizeof(uiAssemblyGUIDs)); + memset(&uiLeviathanDoor, 0, sizeof(uiLeviathanDoor)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (uiEncounter[i] == IN_PROGRESS) + return true; + } + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_LEVIATHAN: + uiLeviathanGUID = pCreature->GetGUID(); + break; + case NPC_IGNIS: + uiIgnisGUID = pCreature->GetGUID(); + break; + case NPC_RAZORSCALE: + uiRazorscaleGUID = pCreature->GetGUID(); + break; + case NPC_XT002: + uiXT002GUID = pCreature->GetGUID(); + break; + + // Assembly of Iron + case NPC_STEELBREAKER: + uiAssemblyGUIDs[0] = pCreature->GetGUID(); + break; + case NPC_MOLGEIM: + uiAssemblyGUIDs[1] = pCreature->GetGUID(); + break; + case NPC_BRUNDIR: + uiAssemblyGUIDs[2] = pCreature->GetGUID(); + break; + + case NPC_KOLOGARN: + uiKologarnGUID = pCreature->GetGUID(); + break; + case NPC_AURIAYA: + uiAuriayaGUID = pCreature->GetGUID(); + break; + case NPC_MIMIRON: + uiMimironGUID = pCreature->GetGUID(); + break; + case NPC_HODIR: + uiHodirGUID = pCreature->GetGUID(); + break; + case NPC_THORIM: + uiThorimGUID = pCreature->GetGUID(); + break; + case NPC_FREYA: + uiFreyaGUID = pCreature->GetGUID(); + break; + case NPC_VEZAX: + uiVezaxGUID = pCreature->GetGUID(); + break; + case NPC_YOGGSARON: + uiYoggSaronGUID = pCreature->GetGUID(); + break; + case NPC_ALGALON: + uiAlgalonGUID = pCreature->GetGUID(); + break; + } + + } + + void OnGameObjectCreate(GameObject* pGO, bool add) + { + switch(pGO->GetEntry()) + { + case GO_KOLOGARN_CHEST_HERO: + case GO_KOLOGARN_CHEST: + uiKologarnChestGUID = add ? pGO->GetGUID() : NULL; + break; + case GO_THORIM_CHEST_HERO: + case GO_THORIM_CHEST: + uiThorimChestGUID = add ? pGO->GetGUID() : NULL; + break; + case GO_HODIR_CHEST_HERO: + case GO_HODIR_CHEST: + uiHodirChestGUID = add ? pGO->GetGUID() : NULL; + break; + case GO_FREYA_CHEST_HERO: + case GO_FREYA_CHEST: + uiFreyaChestGUID = add ? pGO->GetGUID() : NULL; + break; + case GO_LEVIATHAN_DOOR: + uiLeviathanDoor[flag] = pGO->GetGUID(); + HandleGameObject(NULL, true, pGO); + flag++; + if (flag == 7) + flag =0; + break; + case GO_LEVIATHAN_GATE: + uiLeviathanGateGUID = pGO->GetGUID(); + HandleGameObject(NULL, false, pGO); + break; + } + } + + void ProcessEvent(GameObject* pGO, uint32 uiEventId) + { + // Flame Leviathan's Tower Event triggers + Creature* pFlameLeviathan = instance->GetCreature(NPC_LEVIATHAN); + if (pFlameLeviathan && pFlameLeviathan->isAlive()) //No leviathan, no event triggering ;) + switch(uiEventId) + { + case EVENT_TOWER_OF_STORM_DESTROYED: + pFlameLeviathan->AI()->DoAction(1); + break; + case EVENT_TOWER_OF_FROST_DESTROYED: + pFlameLeviathan->AI()->DoAction(2); + break; + case EVENT_TOWER_OF_FLAMES_DESTROYED: + pFlameLeviathan->AI()->DoAction(3); + break; + case EVENT_TOWER_OF_NATURE_DESTROYED: + pFlameLeviathan->AI()->DoAction(4); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + if (type != TYPE_COLOSSUS) + uiEncounter[type] = data; + + switch(type) + { + /*case TYPE_IGNIS: + case TYPE_RAZORSCALE: + case TYPE_XT002: + case TYPE_ASSEMBLY: + case TYPE_AURIAYA: + case TYPE_MIMIRON: + case TYPE_VEZAX: + case TYPE_YOGGSARON: + break;*/ + case TYPE_LEVIATHAN: + if (data == IN_PROGRESS) + { + for (uint8 uiI = 0; uiI < 7; uiI++) + HandleGameObject(uiLeviathanDoor[uiI],false); + } + else + { + for (uint8 uiI = 0; uiI < 7; uiI++) + HandleGameObject(uiLeviathanDoor[uiI],true); + } + break; + case TYPE_KOLOGARN: + if (data == DONE) + if (GameObject* pGO = instance->GetGameObject(uiKologarnChestGUID)) + pGO->SetRespawnTime(pGO->GetRespawnDelay()); + break; + case TYPE_HODIR: + if (data == DONE) + if (GameObject* pGO = instance->GetGameObject(uiHodirChestGUID)) + pGO->SetRespawnTime(pGO->GetRespawnDelay()); + break; + case TYPE_THORIM: + if (data == DONE) + if (GameObject* pGO = instance->GetGameObject(uiThorimChestGUID)) + pGO->SetRespawnTime(pGO->GetRespawnDelay()); + break; + case TYPE_FREYA: + if (data == DONE) + if (GameObject* pGO = instance->GetGameObject(uiFreyaChestGUID)) + pGO->SetRespawnTime(pGO->GetRespawnDelay()); + break; + case TYPE_COLOSSUS: + if (data == 2) + { + if (Creature* pBoss = instance->GetCreature(uiLeviathanGUID)) + pBoss->AI()->DoAction(10); + if (GameObject* pGate = instance->GetGameObject(uiLeviathanGateGUID)) + pGate->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + } + break; + default: + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + saveStream << uiEncounter[i] << " "; + + m_strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case TYPE_LEVIATHAN: return uiLeviathanGUID; + case TYPE_IGNIS: return uiIgnisGUID; + case TYPE_RAZORSCALE: return uiRazorscaleGUID; + case TYPE_XT002: return uiXT002GUID; + case TYPE_KOLOGARN: return uiKologarnGUID; + case TYPE_AURIAYA: return uiAuriayaGUID; + case TYPE_MIMIRON: return uiMimironGUID; + case TYPE_HODIR: return uiMimironGUID; + case TYPE_THORIM: return uiThorimGUID; + case TYPE_FREYA: return uiFreyaGUID; + case TYPE_VEZAX: return uiVezaxGUID; + case TYPE_YOGGSARON: return uiYoggSaronGUID; + case TYPE_ALGALON: return uiAlgalonGUID; + + // Assembly of Iron + case DATA_STEELBREAKER: return uiAssemblyGUIDs[0]; + case DATA_MOLGEIM: return uiAssemblyGUIDs[1]; + case DATA_BRUNDIR: return uiAssemblyGUIDs[2]; + } + + return 0; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_LEVIATHAN: + case TYPE_IGNIS: + case TYPE_RAZORSCALE: + case TYPE_XT002: + case TYPE_ASSEMBLY: + case TYPE_KOLOGARN: + case TYPE_AURIAYA: + case TYPE_MIMIRON: + case TYPE_HODIR: + case TYPE_THORIM: + case TYPE_FREYA: + case TYPE_VEZAX: + case TYPE_YOGGSARON: + case TYPE_ALGALON: + case TYPE_COLOSSUS: + return uiEncounter[type]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "U U " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2] << " " << uiEncounter[3] + << uiEncounter[4] << " " << uiEncounter[5] << " " << uiEncounter[6] << " " << uiEncounter[7] + << uiEncounter[8] << " " << uiEncounter[9] << " " << uiEncounter[10] << " " << uiEncounter[11] + << uiEncounter[12] << " " << uiEncounter[13] << " " << uiEncounter[14]; + + m_strInstData = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return m_strInstData; + } + + void Load(const char* strIn) + { + if (!strIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(strIn); + + char dataHead1, dataHead2; + uint32 data0, data1, data2, data3, data4, data5, data6, + data7, data8, data9, data10, data11, data12, data13, data14; + + std::istringstream loadStream(strIn); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6 + >> data7 >> data8 >> data9 >> data10 >> data11 >> data12 >> data13 >> data14; + + if (dataHead1 == 'U' && dataHead2 == 'U') + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + loadStream >> uiEncounter[i]; + + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + } + } + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_ulduar(Map* pMap) +{ + return new instance_ulduar(pMap); +} + +void AddSC_instance_ulduar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_ulduar"; + newscript->GetInstanceData = &GetInstanceData_instance_ulduar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/ulduar.h b/src/server/scripts/Northrend/ulduar/ulduar/ulduar.h new file mode 100644 index 00000000000..cb11bcb579c --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/ulduar.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_ULDUAR_H +#define DEF_ULDUAR_H + +enum eTypes +{ + MAX_ENCOUNTER = 15, + + TYPE_LEVIATHAN = 0, + TYPE_IGNIS = 1, + TYPE_RAZORSCALE = 2, + TYPE_XT002 = 3, + TYPE_ASSEMBLY = 4, + TYPE_KOLOGARN = 5, + TYPE_AURIAYA = 6, + TYPE_MIMIRON = 7, + TYPE_HODIR = 8, + TYPE_THORIM = 9, + TYPE_FREYA = 10, + TYPE_VEZAX = 11, + TYPE_YOGGSARON = 12, + TYPE_ALGALON = 13, + TYPE_COLOSSUS = 14, + + DATA_STEELBREAKER = 20, + DATA_MOLGEIM = 21, + DATA_BRUNDIR = 22, + DATA_RUNEMASTER_MOLGEIM = 23, + DATA_STORMCALLER_BRUNDIR = 24, + + NPC_LEVIATHAN = 33113, + NPC_IGNIS = 33118, + NPC_RAZORSCALE = 33186, + NPC_XT002 = 33293, + NPC_STEELBREAKER = 32867, + NPC_MOLGEIM = 32927, + NPC_BRUNDIR = 32857, + NPC_KOLOGARN = 32930, + NPC_AURIAYA = 33515, + NPC_MIMIRON = 33350, + NPC_HODIR = 32845, + NPC_THORIM = 32865, + NPC_FREYA = 32906, + NPC_VEZAX = 33271, + NPC_YOGGSARON = 33288, + NPC_ALGALON = 32871, + + EVENT_TOWER_OF_STORM_DESTROYED = 21031, + EVENT_TOWER_OF_FROST_DESTROYED = 21032, + EVENT_TOWER_OF_FLAMES_DESTROYED = 21033, + EVENT_TOWER_OF_NATURE_DESTROYED = 21030 +}; + +#endif diff --git a/src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp b/src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp new file mode 100644 index 00000000000..44f9e86b69c --- /dev/null +++ b/src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp @@ -0,0 +1,92 @@ +#include "ScriptedPch.h" +#include "ulduar.h" + +/* +The teleporter appears to be active and stable. + +- Expedition Base Camp +- Formation Grounds +- Colossal Forge +- Scrapyard +- Antechamber of Ulduar +- Shattered Walkway +- Conservatory of Life +*/ + +#define BASE_CAMP 200 +#define GROUNDS 201 +#define FORGE 202 +#define SCRAPYARD 203 +#define ANTECHAMBER 204 +#define WALKWAY 205 +#define CONSERVATORY 206 + +bool GoHello_ulduar_teleporter(Player *pPlayer, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + if (!pInstance) return true; + + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Expedition Base Camp", GOSSIP_SENDER_MAIN, BASE_CAMP); + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Formation Grounds", GOSSIP_SENDER_MAIN, GROUNDS); + if (pInstance->GetData(TYPE_LEVIATHAN) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Colossal Forge", GOSSIP_SENDER_MAIN, FORGE); + if (pInstance->GetData(TYPE_XT002) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Scrapyard", GOSSIP_SENDER_MAIN, SCRAPYARD); + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Antechamber of Ulduar", GOSSIP_SENDER_MAIN, ANTECHAMBER); + if (pInstance->GetData(TYPE_KOLOGARN) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Shattered Walkway", GOSSIP_SENDER_MAIN, WALKWAY); + if (pInstance->GetData(TYPE_AURIAYA) == DONE) + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Conservatory of Life", GOSSIP_SENDER_MAIN, CONSERVATORY); + } + } + } + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pGO->GetGUID()); + + return true; +} + +bool GOSelect_ulduar_teleporter(Player *pPlayer, GameObject * /*pGO*/, uint32 sender, uint32 action) +{ + if (sender != GOSSIP_SENDER_MAIN) return true; + if (!pPlayer->getAttackers().empty()) return true; + + switch(action) + { + case BASE_CAMP: + pPlayer->TeleportTo(603, -706.122, -92.6024, 429.876, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case GROUNDS: + pPlayer->TeleportTo(603, 131.248, -35.3802, 409.804, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case FORGE: + pPlayer->TeleportTo(603, 553.233, -12.3247, 409.679, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case SCRAPYARD: + pPlayer->TeleportTo(603, 926.292, -11.4635, 418.595, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case ANTECHAMBER: + pPlayer->TeleportTo(603, 1498.09, -24.246, 420.967, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case WALKWAY: + pPlayer->TeleportTo(603, 1859.45, -24.1, 448.9, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case CONSERVATORY: + pPlayer->TeleportTo(603, 2086.27, -24.3134, 421.239, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + } + + return true; +} + +void AddSC_ulduar_teleporter() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "ulduar_teleporter"; + newscript->pGOHello = &GoHello_ulduar_teleporter; + newscript->pGOSelect = &GOSelect_ulduar_teleporter; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp new file mode 100644 index 00000000000..77f824c48d5 --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ingvar_The_Plunderer +SD%Complete: 95 +SDComment: Some Problems with Annhylde Movement, Blizzlike Timers +SDCategory: Udgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum Yells +{ + //Yells Ingvar + YELL_AGGRO_1 = -1574005, + YELL_AGGRO_2 = -1574006, + + YELL_DEAD_1 = -1574007, + YELL_DEAD_2 = -1574008, + + YELL_KILL_1 = -1574009, + YELL_KILL_2 = -1574010, +}; + +enum Creatures +{ + MOB_INGVAR_HUMAN = 23954, + MOB_ANNHYLDE_THE_CALLER = 24068, + MOB_INGVAR_UNDEAD = 23980, +}; + +enum Spells +{ + //Ingvar Spells human form + SPELL_CLEAVE = 42724, + SPELL_SMASH = 42669, + H_SPELL_SMASH = 59706, + SPELL_STAGGERING_ROAR = 42708, + H_SPELL_STAGGERING_ROAR = 59708, + SPELL_ENRAGE = 42705, + H_SPELL_ENRAGE = 59707, + + SPELL_INGVAR_FEIGN_DEATH = 42795, + SPELL_SUMMON_BANSHEE = 42912, + SPELL_SCOURG_RESURRECTION = 42863, // Spawn resurrect effect around Ingvar + + //Ingvar Spells undead form + SPELL_DARK_SMASH = 42723, + SPELL_DREADFUL_ROAR = 42729, + H_SPELL_DREADFUL_ROAR = 59734, + SPELL_WOE_STRIKE = 42730, + H_SPELL_WOE_STRIKE = 59735, + + ENTRY_THROW_TARGET = 23996, + SPELL_SHADOW_AXE_SUMMON = 42749 +}; + +struct boss_ingvar_the_plundererAI : public ScriptedAI +{ + boss_ingvar_the_plundererAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bIsUndead; + bool bEventInProgress; + + uint32 uiCleaveTimer; + uint32 uiSmashTimer; + uint32 uiEnrageTimer; + uint32 uiRoarTimer; + uint32 uiSpawnResTimer; + + void Reset() + { + if (bIsUndead) + me->UpdateEntry(MOB_INGVAR_HUMAN); + + bIsUndead = false; + bEventInProgress = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + + uiCleaveTimer = 2000; + uiSmashTimer = 5000; + uiEnrageTimer = 10000; + uiRoarTimer = 15000; + + uiSpawnResTimer = 3000; + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, NOT_STARTED); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth() && !bIsUndead) + { + //DoCast(me, SPELL_INGVAR_FEIGN_DEATH, true); // Dont work ??? + // visuel hack + me->SetHealth(0); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + // visuel hack end + + bEventInProgress = true; + bIsUndead = true; + + DoScriptText(YELL_DEAD_1,me); + } + + if (bEventInProgress) + { + damage = 0; + } + } + + void StartZombiePhase() + { + bIsUndead = true; + bEventInProgress = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->UpdateEntry(MOB_INGVAR_UNDEAD); + me->SetInCombatWith(me->getVictim()); + me->GetMotionMaster()->MoveChase(me->getVictim()); + + DoScriptText(YELL_AGGRO_2,me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO_1,me); + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(YELL_DEAD_2,me); + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + if (bIsUndead) + DoScriptText(YELL_KILL_1,me); + else + DoScriptText(YELL_KILL_2,me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (bEventInProgress) + { + if (uiSpawnResTimer) + if (uiSpawnResTimer <= diff) + { + DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position + // DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ? + uiSpawnResTimer = 0; + } else uiSpawnResTimer -= diff; + + return; + } + + if (uiCleaveTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me->getVictim(), SPELL_WOE_STRIKE); + else + DoCast(me->getVictim(), SPELL_CLEAVE); + uiCleaveTimer = rand()%5000 + 2000; + } + } else uiCleaveTimer -= diff; + + if (uiSmashTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me->getVictim(), SPELL_DARK_SMASH); + else + DoCast(me->getVictim(), SPELL_SMASH); + uiSmashTimer = 10000; + } + } else uiSmashTimer -= diff; + + if (!bIsUndead) + { + if (uiEnrageTimer <= diff) + { + DoCast(me, SPELL_ENRAGE); + uiEnrageTimer = 10000; + } else uiEnrageTimer -= diff; + } else // In Undead form used to summon weapon + { + if (uiEnrageTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + // Spawn target for Axe + Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + if (pTarget) + { + me->SummonCreature(ENTRY_THROW_TARGET,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,2000); + + DoCast(me, SPELL_SHADOW_AXE_SUMMON); + } + uiEnrageTimer = 30000; + } + } else uiEnrageTimer -= diff; + } + + if (uiRoarTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me, SPELL_DREADFUL_ROAR); + else + DoCast(me, SPELL_STAGGERING_ROAR); + uiRoarTimer = 10000; + } + } else uiRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ingvar_the_plunderer(Creature* pCreature) +{ + return new boss_ingvar_the_plundererAI(pCreature); +} + +enum eSpells +{ +//we don't have that text in db so comment it until we get this text +// YELL_RESSURECT = -1574025, + +//Spells for Annhylde + SPELL_SCOURG_RESURRECTION_HEAL = 42704, //Heal Max + DummyAura + SPELL_SCOURG_RESURRECTION_BEAM = 42857, //Channeling Beam of Annhylde + SPELL_SCOURG_RESURRECTION_DUMMY = 42862, //Some Emote Dummy? + SPELL_INGVAR_TRANSFORM = 42796 +}; + +struct mob_annhylde_the_callerAI : public ScriptedAI +{ + mob_annhylde_the_callerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + float x,y,z; + ScriptedInstance* pInstance; + uint32 uiResurectTimer; + uint32 uiResurectPhase; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_HOVER); + me->SetSpeed(MOVE_SWIM , 1.0f); + me->SetSpeed(MOVE_RUN , 1.0f); + me->SetSpeed(MOVE_WALK , 1.0f); + //me->SetSpeed(MOVE_FLIGHT , 1.0f); + + me->GetPosition(x,y,z); + DoTeleportTo(x+1,y,z+30); + + Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + me->GetMotionMaster()->MovePoint(1,x,y,z+15); + +// DoScriptText(YELL_RESSURECT,me); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + Unit* ingvar = Unit::GetUnit((*me), pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + switch (id) + { + case 1: + ingvar->RemoveAura(SPELL_SUMMON_BANSHEE); + ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_DUMMY,true); + DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); + uiResurectTimer = 8000; + uiResurectPhase = 1; + break; + case 2: + me->SetVisibility(VISIBILITY_OFF); + me->DealDamage(me,me->GetHealth()); + me->RemoveCorpse(); + break; + } + } + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit * /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (uiResurectTimer) + if (uiResurectTimer <= diff) + { + if (uiResurectPhase == 1) + { + Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + ingvar->SetStandState(UNIT_STAND_STATE_STAND); + ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_HEAL,false); + } + uiResurectTimer = 3000; + uiResurectPhase = 2; + } + else if (uiResurectPhase == 2) + { + if (Creature* ingvar = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0)) + { + ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); + + if (boss_ingvar_the_plundererAI* pAI = CAST_AI(boss_ingvar_the_plundererAI, ingvar->AI())) + pAI->StartZombiePhase(); + + me->GetMotionMaster()->MovePoint(2,x+1,y,z+30); + ++uiResurectPhase; + uiResurectTimer = 0; + } + } + + } else uiResurectTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_annhylde_the_caller(Creature* pCreature) +{ + return new mob_annhylde_the_callerAI (pCreature); +} + +enum eShadowAxe +{ + SPELL_SHADOW_AXE_DAMAGE = 42750, + H_SPELL_SHADOW_AXE_DAMAGE = 59719 +}; + +struct mob_ingvar_throw_dummyAI : public ScriptedAI +{ + mob_ingvar_throw_dummyAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 uiDespawnTimer; + + void Reset() + { + Unit *pTarget = me->FindNearestCreature(ENTRY_THROW_TARGET,50); + if (pTarget) + { + DoCast(me, SPELL_SHADOW_AXE_DAMAGE); + float x,y,z; + pTarget->GetPosition(x,y,z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + } + uiDespawnTimer = 7000; + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit * /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (uiDespawnTimer <= diff) + { + me->DealDamage(me,me->GetHealth()); + me->RemoveCorpse(); + uiDespawnTimer = 0; + } else uiDespawnTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_ingvar_throw_dummy(Creature* pCreature) +{ + return new mob_ingvar_throw_dummyAI (pCreature); +} + +void AddSC_boss_ingvar_the_plunderer() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ingvar_the_plunderer"; + newscript->GetAI = &GetAI_boss_ingvar_the_plunderer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_annhylde_the_caller"; + newscript->GetAI = &GetAI_mob_annhylde_the_caller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ingvar_throw_dummy"; + newscript->GetAI = &GetAI_mob_ingvar_throw_dummy; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp new file mode 100644 index 00000000000..d69f0eee846 --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Prince_Keleseth +SD%Complete: 90 +SDComment: Needs Prince Movements, Needs adjustments to blizzlike timers, Needs Shadowbolt castbar, Needs right Ressurect Visual, Needs Some Heroic Spells +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum eEnums +{ + ACHIEVEMENT_ON_THE_ROCKS = 1919, + + SPELL_SHADOWBOLT = 43667, + SPELL_SHADOWBOLT_HEROIC = 59389, + SPELL_FROST_TOMB = 48400, + SPELL_FROST_TOMB_SUMMON = 42714, + SPELL_DECREPIFY = 42702, + SPELL_SCOURGE_RESSURRECTION = 42704, + CREATURE_FROSTTOMB = 23965, + CREATURE_SKELETON = 23970, + + SAY_AGGRO = -1574000, + SAY_FROST_TOMB = -1574001, + SAY_SKELETONS = -1574002, + SAY_KILL = -1574003, + SAY_DEATH = -1574004 +}; + +#define SKELETONSPAWN_Z 42.8668 + +float SkeletonSpawnPoint[5][5]= +{ + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, +}; + +float AttackLoc[3]={197.636, 194.046, 40.8164}; + +bool ShatterFrostTomb; // needed for achievement: On The Rocks(1919) + +struct mob_frost_tombAI : public ScriptedAI +{ + mob_frost_tombAI(Creature *c) : ScriptedAI(c) + { + FrostTombGUID = 0; + } + + uint64 FrostTombGUID; + + void SetPrisoner(Unit* uPrisoner) + { + FrostTombGUID = uPrisoner->GetGUID(); + } + + void Reset(){ FrostTombGUID = 0; } + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void JustDied(Unit *killer) + { + if (killer->GetGUID() != me->GetGUID()) + ShatterFrostTomb = true; + + if (FrostTombGUID) + { + Unit* FrostTomb = Unit::GetUnit((*me),FrostTombGUID); + if (FrostTomb) + FrostTomb->RemoveAurasDueToSpell(SPELL_FROST_TOMB); + } + } + + void UpdateAI(const uint32 /*diff*/) + { + Unit* temp = Unit::GetUnit((*me),FrostTombGUID); + if ((temp && temp->isAlive() && !temp->HasAura(SPELL_FROST_TOMB)) || !temp) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } +}; + +struct boss_kelesethAI : public ScriptedAI +{ + boss_kelesethAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 FrostTombTimer; + uint32 SummonSkeletonsTimer; + uint32 RespawnSkeletonsTimer; + uint32 ShadowboltTimer; + uint64 SkeletonGUID[5]; + bool Skeletons; + bool RespawnSkeletons; + + void Reset() + { + ShadowboltTimer = 0; + Skeletons = false; + + ShatterFrostTomb = false; + + ResetTimer(); + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (IsHeroic() && !ShatterFrostTomb) + { + AchievementEntry const *AchievOnTheRocks = GetAchievementStore()->LookupEntry(ACHIEVEMENT_ON_THE_ROCKS); + if (AchievOnTheRocks) + { + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievOnTheRocks); + } + } + } + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); + } + + void ResetTimer(uint32 inc = 0) + { + SummonSkeletonsTimer = 5000 + inc; + FrostTombTimer = 28000 + inc; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowboltTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + me->CastSpell(pTarget, DUNGEON_MODE(SPELL_SHADOWBOLT, SPELL_SHADOWBOLT_HEROIC), true); + ShadowboltTimer = 10000; + } else ShadowboltTimer -= diff; + + if (!Skeletons) + if ((SummonSkeletonsTimer <= diff)) + { + Creature* Skeleton; + DoScriptText(SAY_SKELETONS, me); + for (uint8 i = 0; i < 5; ++i) + { + Skeleton = me->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1] , SKELETONSPAWN_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); + if (Skeleton) + { + Skeleton->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Skeleton->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY() , me->GetPositionZ()); + Skeleton->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Skeleton); + } + } + Skeletons = true; + } else SummonSkeletonsTimer -= diff; + + if (FrostTombTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (pTarget->isAlive()) + { + //DoCast(pTarget, SPELL_FROST_TOMB_SUMMON, true); + if (Creature *pChains = me->SummonCreature(CREATURE_FROSTTOMB, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) + { + CAST_AI(mob_frost_tombAI, pChains->AI())->SetPrisoner(pTarget); + pChains->CastSpell(pTarget, SPELL_FROST_TOMB, true); + + DoScriptText(SAY_FROST_TOMB, me); + } + } + FrostTombTimer = 15000; + } else FrostTombTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_vrykul_skeletonAI : public ScriptedAI +{ + mob_vrykul_skeletonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 Respawn_Time; + uint64 Target_Guid; + uint32 Decrepify_Timer; + + bool isDead; + + void Reset() + { + Respawn_Time = 12000; + Decrepify_Timer = urand(10000,20000); + isDead = false; + } + + void EnterCombat(Unit * /*who*/){} + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() == me->GetGUID()) + return; + + if (damage >= me->GetHealth()) + { + PretendToDie(); + damage = 0; + } + } + + void PretendToDie() + { + isDead = true; + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + }; + + void Resurrect() + { + isDead = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_SCOURGE_RESSURRECTION, true); + + if (me->getVictim()) + { + me->GetMotionMaster()->MoveChase(me->getVictim()); + me->AI()->AttackStart(me->getVictim()); + } + else + me->GetMotionMaster()->Initialize(); + }; + + void UpdateAI(const uint32 diff) + { + if (pInstance && pInstance->GetData(DATA_PRINCEKELESETH_EVENT) == IN_PROGRESS) + { + if (isDead) + { + if (Respawn_Time <= diff) + { + Resurrect(); + Respawn_Time = 12000; + } else Respawn_Time -= diff; + } + else + { + if (!UpdateVictim()) + return; + + if (Decrepify_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DECREPIFY); + Decrepify_Timer = 30000; + } else Decrepify_Timer -= diff; + + DoMeleeAttackIfReady(); + } + }else + { + if (me->isAlive()) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + } +}; + +CreatureAI* GetAI_mob_frost_tomb(Creature* pCreature) +{ + return new mob_frost_tombAI(pCreature); +} + +CreatureAI* GetAI_boss_keleseth(Creature* pCreature) +{ + return new boss_kelesethAI (pCreature); +} + +CreatureAI* GetAI_mob_vrykul_skeleton(Creature* pCreature) +{ + return new mob_vrykul_skeletonAI (pCreature); +} + +void AddSC_boss_keleseth() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_keleseth"; + newscript->GetAI = &GetAI_boss_keleseth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_tomb"; + newscript->GetAI = &GetAI_mob_frost_tomb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vrykul_skeleton"; + newscript->GetAI = &GetAI_mob_vrykul_skeleton; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp new file mode 100644 index 00000000000..2146d37635b --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Skarvald_Dalronn +SD%Complete: 95 +SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum eEnums +{ + //signed for 24200, but used by 24200,27390 + YELL_SKARVALD_AGGRO = -1574011, + YELL_SKARVALD_DAL_DIED = -1574012, + YELL_SKARVALD_SKA_DIEDFIRST = -1574013, + YELL_SKARVALD_KILL = -1574014, + YELL_SKARVALD_DAL_DIEDFIRST = -1574015, + + //signed for 24201, but used by 24201,27389 + YELL_DALRONN_AGGRO = -1574016, + YELL_DALRONN_SKA_DIED = -1574017, + YELL_DALRONN_DAL_DIEDFIRST = -1574018, + YELL_DALRONN_KILL = -1574019, + YELL_DALRONN_SKA_DIEDFIRST = -1574020, + +//Spells of Skarvald and his Ghost + MOB_SKARVALD_THE_CONSTRUCTOR = 24200, + SPELL_CHARGE = 43651, + SPELL_STONE_STRIKE = 48583, + SPELL_SUMMON_SKARVALD_GHOST = 48613, + MOB_SKARVALD_GHOST = 27390, +//Spells of Dalronn and his Ghost + MOB_DALRONN_THE_CONTROLLER = 24201, + SPELL_SHADOW_BOLT = 43649, + H_SPELL_SHADOW_BOLT = 59575, + H_SPELL_SUMMON_SKELETONS = 52611, + SPELL_DEBILITATE = 43650, + SPELL_SUMMON_DALRONN_GHOST = 48612, + MOB_DALRONN_GHOST = 27389 +}; + +struct boss_skarvald_the_constructorAI : public ScriptedAI +{ + boss_skarvald_the_constructorAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool ghost; + uint32 Charge_Timer; + uint32 StoneStrike_Timer; + uint32 Response_Timer; + uint32 Check_Timer; + bool Dalronn_isDead; + + void Reset() + { + Charge_Timer = 5000; + StoneStrike_Timer = 10000; + Dalronn_isDead = false; + Check_Timer = 5000; + + ghost = (me->GetEntry() == MOB_SKARVALD_GHOST); + if (!ghost && pInstance) + { + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn && dalronn->isDead()) + CAST_CRE(dalronn)->Respawn(); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit * who) + { + if (!ghost && pInstance) + { + DoScriptText(YELL_SKARVALD_AGGRO,me); + + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn && dalronn->isAlive() && !dalronn->getVictim()) + dalronn->getThreatManager().addThreat(who,0.0f); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* Killer) + { + if (!ghost && pInstance) + { + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn) + { + if (dalronn->isDead()) + { + DoScriptText(YELL_SKARVALD_DAL_DIED,me); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); + } + else + { + DoScriptText(YELL_SKARVALD_SKA_DIEDFIRST,me); + + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true); + Creature* temp = me->SummonCreature(MOB_SKARVALD_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); + if (temp) + { + temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(Killer); + } + } + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + if (!ghost) + { + DoScriptText(YELL_SKARVALD_KILL,me); + } + } + + void UpdateAI(const uint32 diff) + { + if (ghost) + { + if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (!UpdateVictim()) + return; + + if (!ghost) + { + if (Check_Timer) + if (Check_Timer <= diff) + { + Check_Timer = 5000; + Unit* dalronn = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_DALRONN) : 0); + if (dalronn && dalronn->isDead()) + { + Dalronn_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } + } else Check_Timer -= diff; + + if (Response_Timer) + if (Dalronn_isDead) + if (Response_Timer <= diff) + { + DoScriptText(YELL_SKARVALD_DAL_DIEDFIRST,me); + + Response_Timer = 0; + } else Response_Timer -= diff; + } + + if (Charge_Timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE); + Charge_Timer = 5000+rand()%5000; + } else Charge_Timer -= diff; + + if (StoneStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STONE_STRIKE); + StoneStrike_Timer = 5000+rand()%5000; + } else StoneStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_skarvald_the_constructor(Creature* pCreature) +{ + return new boss_skarvald_the_constructorAI (pCreature); +} + +struct boss_dalronn_the_controllerAI : public ScriptedAI +{ + boss_dalronn_the_controllerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool ghost; + uint32 ShadowBolt_Timer; + uint32 Debilitate_Timer; + uint32 Summon_Timer; + + uint32 Response_Timer; + uint32 Check_Timer; + uint32 AggroYell_Timer; + bool Skarvald_isDead; + + void Reset() + { + ShadowBolt_Timer = 1000; + Debilitate_Timer = 5000; + Summon_Timer = 10000; + Check_Timer = 5000; + Skarvald_isDead = false; + AggroYell_Timer = 0; + + ghost = me->GetEntry() == MOB_DALRONN_GHOST; + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald && skarvald->isDead()) + CAST_CRE(skarvald)->Respawn(); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit * who) + { + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald && skarvald->isAlive() && !skarvald->getVictim()) + skarvald->getThreatManager().addThreat(who,0.0f); + + AggroYell_Timer = 5000; + + if (pInstance) + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* Killer) + { + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald) + if (skarvald->isDead()) + { + DoScriptText(YELL_DALRONN_SKA_DIED,me); + + if (pInstance) + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); + } + else + { + DoScriptText(YELL_DALRONN_DAL_DIEDFIRST,me); + + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true); + Creature* temp = me->SummonCreature(MOB_DALRONN_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); + if (temp) + { + temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(Killer); + } + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + if (!ghost) + { + DoScriptText(YELL_DALRONN_KILL,me); + } + } + + void UpdateAI(const uint32 diff) + { + if (ghost) + { + if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (!UpdateVictim()) + return; + + if (AggroYell_Timer) + if (AggroYell_Timer <= diff) + { + DoScriptText(YELL_DALRONN_AGGRO,me); + + AggroYell_Timer = 0; + } else AggroYell_Timer -= diff; + + if (!ghost) + { + if (Check_Timer) + if (Check_Timer <= diff) + { + Check_Timer = 5000; + Unit* skarvald = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SKARVALD) : 0); + if (skarvald && skarvald->isDead()) + { + Skarvald_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } + } else Check_Timer -= diff; + + if (Response_Timer) + if (Skarvald_isDead) + if (Response_Timer <= diff) + { + DoScriptText(YELL_DALRONN_SKA_DIEDFIRST,me); + + Response_Timer = 0; + } else Response_Timer -= diff; + } + + if (ShadowBolt_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells + } + } else ShadowBolt_Timer -= diff; + + if (Debilitate_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DEBILITATE); + Debilitate_Timer = 5000+rand()%5000; + } + } else Debilitate_Timer -= diff; + + if (IsHeroic()) + if (Summon_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, H_SPELL_SUMMON_SKELETONS); + Summon_Timer = (rand()%10000) + 20000; + } + } else Summon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_dalronn_the_controller(Creature* pCreature) +{ + return new boss_dalronn_the_controllerAI (pCreature); +} + +void AddSC_boss_skarvald_dalronn() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_skarvald_the_constructor"; + newscript->GetAI = &GetAI_boss_skarvald_the_constructor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_dalronn_the_controller"; + newscript->GetAI = &GetAI_boss_dalronn_the_controller; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp new file mode 100644 index 00000000000..03f97b1d27e --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Utgarde_Keep +SD%Complete: 90 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Utgarde Keep Scripts +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +#define MAX_ENCOUNTER 3 + +#define ENTRY_BELLOW_1 186688 +#define ENTRY_BELLOW_2 186689 +#define ENTRY_BELLOW_3 186690 + +#define ENTRY_FORGEFIRE_1 186692 +#define ENTRY_FORGEFIRE_2 186693 +#define ENTRY_FORGEFIRE_3 186691 + +#define ENTRY_GLOWING_ANVIL_1 186609 +#define ENTRY_GLOWING_ANVIL_2 186610 +#define ENTRY_GLOWING_ANVIL_3 186611 + +#define ENTRY_GIANT_PORTCULLIS_1 186756 +#define ENTRY_GIANT_PORTCULLIS_2 186694 + +/* Utgarde Keep encounters: +0 - Prince Keleseth +1 - Skarvald Dalronn +2 - Ingvar the Plunderer +*/ + +struct instance_utgarde_keep : public ScriptedInstance +{ + instance_utgarde_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 Keleseth; + uint64 Skarvald; + uint64 Dalronn; + uint64 Ingvar; + + uint64 forge_bellow[3]; + uint64 forge_fire[3]; + uint64 forge_anvil[3]; + uint64 portcullis[2]; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 forge_event[3]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Keleseth = 0; + Skarvald = 0; + Dalronn = 0; + Ingvar = 0; + + for (uint8 i = 0; i < 3; ++i) + { + forge_bellow[i] = 0; + forge_fire[i] = 0; + forge_anvil[i] = 0; + forge_event[i] = NOT_STARTED; + } + + portcullis[0] = 0; + portcullis[1] = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 23953: Keleseth = pCreature->GetGUID(); break; + case 24201: Dalronn = pCreature->GetGUID(); break; + case 24200: Skarvald = pCreature->GetGUID(); break; + case 23954: Ingvar = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + //door and object id + case ENTRY_BELLOW_1: forge_bellow[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_BELLOW_2: forge_bellow[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_BELLOW_3: forge_bellow[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_1: forge_fire[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_2: forge_fire[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_3: forge_fire[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_1: forge_anvil[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_2: forge_anvil[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_3: forge_anvil[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GIANT_PORTCULLIS_1: portcullis[0] = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GIANT_PORTCULLIS_2: portcullis[1] = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_PRINCEKELESETH: return Keleseth; + case DATA_DALRONN: return Dalronn; + case DATA_SKARVALD: return Skarvald; + case DATA_INGVAR: return Ingvar; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_PRINCEKELESETH_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_SKARVALD_DALRONN_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_INGVAR_EVENT: + if (data == DONE) + { + HandleGameObject(portcullis[0], true); + HandleGameObject(portcullis[1], true); + } + m_auiEncounter[2] = data; + break; + case EVENT_FORGE_1: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[0],false); + HandleGameObject(forge_fire[0],false); + HandleGameObject(forge_anvil[0],false); + }else + { + HandleGameObject(forge_bellow[0],true); + HandleGameObject(forge_fire[0],true); + HandleGameObject(forge_anvil[0],true); + } + forge_event[0] = data; + break; + case EVENT_FORGE_2: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[1],false); + HandleGameObject(forge_fire[1],false); + HandleGameObject(forge_anvil[1],false); + }else + { + HandleGameObject(forge_bellow[1],true); + HandleGameObject(forge_fire[1],true); + HandleGameObject(forge_anvil[1],true); + } + forge_event[1] = data; + break; + case EVENT_FORGE_3: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[2],false); + HandleGameObject(forge_fire[2],false); + HandleGameObject(forge_anvil[2],false); + }else + { + HandleGameObject(forge_bellow[2],true); + HandleGameObject(forge_fire[2],true); + HandleGameObject(forge_anvil[2],true); + } + forge_event[2] = data; + break; + } + + if (data == DONE) + { + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_PRINCEKELESETH_EVENT: return m_auiEncounter[0]; + case DATA_SKARVALD_DALRONN_EVENT: return m_auiEncounter[1]; + case DATA_INGVAR_EVENT: return m_auiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "U K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << forge_event[0] << " " << forge_event[1] << " " << forge_event[2]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + + if (dataHead1 == 'U' && dataHead2 == 'K') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + forge_event[0] = data3; + forge_event[1] = data4; + forge_event[2] = data5; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_utgarde_keep(Map* pMap) +{ + return new instance_utgarde_keep(pMap); +} + +void AddSC_instance_utgarde_keep() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_utgarde_keep"; + newscript->GetInstanceData = &GetInstanceData_instance_utgarde_keep; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp new file mode 100644 index 00000000000..95825aa49b6 --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +uint32 entry_search[3] = +{ + 186609, + 186610, + 186611 +}; + +struct npc_dragonflayer_forge_masterAI : public ScriptedAI +{ + npc_dragonflayer_forge_masterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + fm_Type = 0; + } + + ScriptedInstance* pInstance; + uint8 fm_Type; + + void Reset() + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + CheckForge(); + } + + void CheckForge() + { + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,me->isAlive() ? NOT_STARTED : DONE); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,me->isAlive() ? NOT_STARTED : DONE); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,me->isAlive() ? NOT_STARTED : DONE); + break; + } + } + } + + void JustDied(Unit * /*killer*/) + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,DONE); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,DONE); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,DONE); + break; + } + } + } + + void EnterCombat(Unit * /*who*/) + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,IN_PROGRESS); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,IN_PROGRESS); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,IN_PROGRESS); + break; + } + } + me->SetUInt32Value(UNIT_NPC_EMOTESTATE ,EMOTE_ONESHOT_NONE); + } + + uint8 GetForgeMasterType() + { + float diff = 30.0f; + int near_f = 0; + + for (uint8 i = 0; i < 3 ; ++i) + { + GameObject* temp; + temp = me->FindNearestGameObject(entry_search[i],30); + if (temp) + { + if (me->IsWithinDist(temp,diff,false)) + { + near_f = i + 1; + diff = me->GetDistance2d(temp); + + } + } + } + + switch (near_f) + { + case 1: return 1; + case 2: return 2; + case 3: return 3; + default: return 0; + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (fm_Type == 0) + fm_Type = GetForgeMasterType(); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_dragonflayer_forge_master(Creature* pCreature) +{ + return new npc_dragonflayer_forge_masterAI(pCreature); +} + +void AddSC_utgarde_keep() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_dragonflayer_forge_master"; + newscript->GetAI = &GetAI_npc_dragonflayer_forge_master; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h new file mode 100644 index 00000000000..b630e156564 --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_UTGARDE_KEEP_H +#define DEF_UTGARDE_KEEP_H + +#define DATA_PRINCEKELESETH 1 +#define DATA_SKARVALD 3 +#define DATA_DALRONN 4 +#define DATA_INGVAR 6 + +#define DATA_PRINCEKELESETH_EVENT 2 +#define DATA_SKARVALD_DALRONN_EVENT 5 +#define DATA_INGVAR_EVENT 7 + +#define EVENT_FORGE_1 8 +#define EVENT_FORGE_2 9 +#define EVENT_FORGE_3 10 + +#endif diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp new file mode 100644 index 00000000000..297fe37b7d8 --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp @@ -0,0 +1,830 @@ +/* Script Data Start +SDName: Boss palehoof +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_palehoof' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_ARCING_SMASH = 48260, + SPELL_IMPALE = 48261, + H_SPELL_IMPALE = 59268, + SPELL_WITHERING_ROAR = 48256, + H_SPELL_WITHERING_ROAR = 59267, + SPELL_FREEZE = 16245 +}; + +//Orb spells +enum OrbSpells +{ + SPELL_ORB_VISUAL = 48044, + SPELL_ORB_CHANNEL = 48048 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1575000, + SAY_SLAY_1 = -1575001, + SAY_SLAY_2 = -1575002, + SAY_DEATH = -1575003 +}; + +enum Creatures +{ + MOB_STASIS_CONTROLLER = 26688 +}; + +struct Locations +{ + float x, y, z; +}; + +struct Locations moveLocs[]= +{ + {261.6,-449.3,109.5}, + {263.3,-454.0,109.5}, + {291.5,-450.4,109.5}, + {291.5,-454.0,109.5}, + {310.0,-453.4,109.5}, + {238.6,-460.7,109.5} +}; + +enum Phase +{ + PHASE_FRENZIED_WORGEN, + PHASE_RAVENOUS_FURLBORG, + PHASE_MASSIVE_JORMUNGAR, + PHASE_FEROCIOUS_RHINO, + PHASE_GORTOK_PALEHOOF, + PHASE_NONE +}; + +struct boss_palehoofAI : public ScriptedAI +{ + boss_palehoofAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiArcingSmashTimer; + uint32 uiImpaleTimer; + uint32 uiWhiteringRoarTimer; + uint32 uiWaitingTimer; + Phase currentPhase; + uint8 AddCount; + bool DoneAdds[4]; + + ScriptedInstance *pInstance; + + void Reset() + { + uiArcingSmashTimer = 15000; + uiImpaleTimer = 12000; + uiWhiteringRoarTimer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + for (uint32 i=0;i<4;i++) + DoneAdds[i]=false; + AddCount=0; + + currentPhase=PHASE_NONE; + + if (pInstance) + { + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, NOT_STARTED); + + Creature* pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GORTOK_PALEHOOF_SPHERE)); + if (pGo) + { + pGo->SetGoState(GO_STATE_READY); + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void UpdateAI(const uint32 diff) + { + if (currentPhase != PHASE_GORTOK_PALEHOOF) + return; + //Return since we have no target + if (!UpdateVictim()) + return; + + Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->DisappearAndDie(); + + if (uiArcingSmashTimer <= diff) + { + DoCast(me, SPELL_ARCING_SMASH); + uiArcingSmashTimer = urand(13000,17000); + } else uiArcingSmashTimer -= diff; + + if (uiImpaleTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_IMPALE); + uiImpaleTimer = urand(8000,12000); + } else uiImpaleTimer -= diff; + + if (uiWhiteringRoarTimer <= diff) + { + DoCast(me, SPELL_WITHERING_ROAR); + uiWhiteringRoarTimer = urand(8000,12000); + } else uiWhiteringRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, DONE); + Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->DisappearAndDie(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void NextPhase() + { + if (currentPhase == PHASE_NONE) + { + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); + me->SummonCreature(MOB_STASIS_CONTROLLER,moveLocs[5].x,moveLocs[5].y,moveLocs[5].z,0,TEMPSUMMON_CORPSE_DESPAWN); + } + Phase move = PHASE_NONE; + if (AddCount >= DUNGEON_MODE(2,4)) + move = PHASE_GORTOK_PALEHOOF; + else + { + //select random not yet defeated add + uint8 next = urand(0,3); + for (uint8 i=0; i < 16; i++) + { + if (!DoneAdds[i%4] && next == 0) + { + move = (Phase)(i%4); + break; + } else if (!DoneAdds[i%4] && next > 0) + --next; + } + ++AddCount; + DoneAdds[move] = true; + move = (Phase)(move%4); + } + //send orb to summon spot + Creature *pOrb = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pOrb && pOrb->isAlive()) + { + if (currentPhase == PHASE_NONE) + pOrb->CastSpell(me,SPELL_ORB_VISUAL,true); + pOrb->GetMotionMaster()->MovePoint(move,moveLocs[move].x,moveLocs[move].y,moveLocs[move].z); + } + currentPhase = move; + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_boss_palehoof(Creature* pCreature) +{ + return new boss_palehoofAI (pCreature); +} + +//ravenous furbolg's spells +enum RavenousSpells +{ + SPELL_CHAIN_LIGHTING = 48140, + H_SPELL_CHAIN_LIGHTING = 59273, + SPELL_CRAZED = 48139, + SPELL_TERRIFYING_ROAR = 48144 +}; + +struct mob_ravenous_furbolgAI : public ScriptedAI +{ + mob_ravenous_furbolgAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiChainLightingTimer; + uint32 uiCrazedTimer; + uint32 uiTerrifyingRoarTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiChainLightingTimer = 5000; + uiCrazedTimer = 10000; + uiTerrifyingRoarTimer = 15000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiChainLightingTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTING); + uiChainLightingTimer = 5000 + rand()%5000; + } else uiChainLightingTimer -= diff; + + if (uiCrazedTimer <= diff) + { + DoCast(me, SPELL_CRAZED); + uiCrazedTimer = 8000 + rand()%4000; + } else uiCrazedTimer -= diff; + + if (uiTerrifyingRoarTimer <= diff) + { + DoCast(me, SPELL_TERRIFYING_ROAR); + uiTerrifyingRoarTimer = 10000 + rand()%10000; + } else uiTerrifyingRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_ravenous_furbolg(Creature* pCreature) +{ + return new mob_ravenous_furbolgAI (pCreature); +} + +//frenzied worgen's spells +enum FrenziedSpells +{ + SPELL_MORTAL_WOUND = 48137, + H_SPELL_MORTAL_WOUND = 59265, + SPELL_ENRAGE_1 = 48138, + SPELL_ENRAGE_2 = 48142 +}; + +struct mob_frenzied_worgenAI : public ScriptedAI +{ + mob_frenzied_worgenAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiMortalWoundTimer; + uint32 uiEnrage1Timer; + uint32 uiEnrage2Timer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiMortalWoundTimer = 5000; + uiEnrage1Timer = 15000; + uiEnrage2Timer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiMortalWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + uiMortalWoundTimer = 3000 + rand()%4000; + } else uiMortalWoundTimer -= diff; + + if (uiEnrage1Timer <= diff) + { + DoCast(me, SPELL_ENRAGE_1); + uiEnrage1Timer = 15000; + } else uiEnrage1Timer -= diff; + + if (uiEnrage2Timer <= diff) + { + DoCast(me, SPELL_ENRAGE_2); + uiEnrage2Timer = 10000; + } else uiEnrage2Timer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + if (pInstance) + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance->GetData64(DATA_GORTOK_PALEHOOF)); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_frenzied_worgen(Creature* pCreature) +{ + return new mob_frenzied_worgenAI (pCreature); +} + +//ferocious rhino's spells +enum FerociousSpells +{ + SPELL_GORE = 48130, + H_SPELL_GORE = 59264, + SPELL_GRIEVOUS_WOUND = 48105, + H_SPELL_GRIEVOUS_WOUND = 59263, + SPELL_STOMP = 48131 +}; + +struct mob_ferocious_rhinoAI : public ScriptedAI +{ + mob_ferocious_rhinoAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiStompTimer; + uint32 uiGoreTimer; + uint32 uiGrievousWoundTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiStompTimer = 10000; + uiGoreTimer = 15000; + uiGrievousWoundTimer = 20000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiStompTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STOMP); + uiStompTimer = 8000 + rand()%4000; + } else uiStompTimer -= diff; + + if (uiGoreTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GORE); + uiGoreTimer = 13000 + rand()%4000; + } else uiGoreTimer -= diff; + + if (uiGrievousWoundTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_GRIEVOUS_WOUND); + uiGrievousWoundTimer = 18000 + rand()%4000; + } else uiGrievousWoundTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_ferocious_rhino(Creature* pCreature) +{ + return new mob_ferocious_rhinoAI (pCreature); +} + +//massive jormungar's spells +enum MassiveSpells +{ + SPELL_ACID_SPIT = 48132, + SPELL_ACID_SPLATTER = 48136, + H_SPELL_ACID_SPLATTER = 59272, + SPELL_POISON_BREATH = 48133, + H_SPELL_POISON_BREATH = 59271 +}; + +enum MassiveAdds +{ + CREATURE_JORMUNGAR_WORM = 27228 +}; + +struct mob_massive_jormungarAI : public ScriptedAI +{ + mob_massive_jormungarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiAcidSpitTimer; + uint32 uiAcidSplatterTimer; + uint32 uiPoisonBreathTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiAcidSpitTimer = 3000; + uiAcidSplatterTimer = 12000; + uiPoisonBreathTimer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiAcidSpitTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ACID_SPIT); + uiAcidSpitTimer = 2000 + rand()%2000; + } else uiAcidSpitTimer -= diff; + + if (uiAcidSplatterTimer <= diff) + { + DoCast(me, SPELL_POISON_BREATH); + uiAcidSplatterTimer = 10000 + rand()%4000; + } else uiAcidSplatterTimer -= diff; + + if (uiPoisonBreathTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_POISON_BREATH); + uiPoisonBreathTimer = 8000 + rand()%4000; + } else uiPoisonBreathTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI,pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_massive_jormungar(Creature* pCreature) +{ + return new mob_massive_jormungarAI (pCreature); +} + + +struct mob_palehoof_orbAI : public ScriptedAI +{ + mob_palehoof_orbAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 SummonTimer; + Phase currentPhase; + + void Reset() + { + currentPhase=PHASE_NONE; + SummonTimer=5000; + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL); + me->SetSpeed(MOVE_FLIGHT , 0.5f); + } + + void UpdateAI(const uint32 diff) + { + if (currentPhase == PHASE_NONE) + return; + + if (SummonTimer <= diff) + { + if (currentPhase<5&¤tPhase >= 0) + { + Creature *pNext = NULL; + switch(currentPhase) + { + case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; + case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; + case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; + case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; + case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; + } + + if (pNext) + { + pNext->RemoveAurasDueToSpell(SPELL_FREEZE); + pNext->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + pNext->SetStandState(UNIT_STAND_STATE_STAND); + pNext->SetInCombatWithZone(); + pNext->Attack(pNext->SelectNearestTarget(100),true); + + } + currentPhase=PHASE_NONE; + } + } else SummonTimer-=diff; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + if (id<0 || id>4) + return; + Creature *pNext = NULL; + switch(id) + { + case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; + case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; + case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; + case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; + case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; + } + if (pNext) + DoCast(pNext, SPELL_ORB_CHANNEL, false); + currentPhase=(Phase)id; + SummonTimer=5000; + } +}; + +CreatureAI* GetAI_mob_palehoof_orb(Creature* pCreature) +{ + return new mob_palehoof_orbAI (pCreature); +} + + + +bool GOHello_palehoof_sphere(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + + Creature *pPalehoof = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + { + // maybe these are hacks :( + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + return true; +} + + + +void AddSC_boss_palehoof() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_palehoof"; + newscript->GetAI = &GetAI_boss_palehoof; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ravenous_furbolg"; + newscript->GetAI = &GetAI_mob_ravenous_furbolg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frenzied_worgen"; + newscript->GetAI = &GetAI_mob_frenzied_worgen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ferocious_rhino"; + newscript->GetAI = &GetAI_mob_ferocious_rhino; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_massive_jormungar"; + newscript->GetAI = &GetAI_mob_massive_jormungar; + newscript->RegisterSelf(); + + + newscript = new Script; + newscript->Name = "mob_palehoof_orb"; + newscript->GetAI = &GetAI_mob_palehoof_orb; + newscript->RegisterSelf(); + + + newscript = new Script; + newscript->Name = "go_palehoof_sphere"; + newscript->pGOHello=&GOHello_palehoof_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp new file mode 100644 index 00000000000..a75eb3465be --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp @@ -0,0 +1,477 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Boss_Skadi +SDAuthor: LordVanMartin, JohnHoliver +SD%Complete: 90% +SDComment: + After Unmount() he appears to still be flying even with SetFlying(false) + +SDCategory: Utgarde Pinnacle +Script Data End */ + +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +//Yell +enum eYells +{ + SAY_AGGRO = -1575004, + SAY_KILL_1 = -1575005, + SAY_KILL_2 = -1575006, + EMOTE_RANGE = -1575007, //Skadi + SAY_DEATH = -1575008, + SAY_DRAKE_DEATH = -1575009, + EMOTE_BREATH = -1575010, //Grauf + SAY_DRAKE_BREATH_1 = -1575011, + SAY_DRAKE_BREATH_2 = -1575012, + SAY_DRAKE_BREATH_3 = -1575013, +}; + +static Position SpawnLoc = {468.931, -513.555, 104.723}; +static Position Location[]= +{ + // Boss + {341.740997, -516.955017, 104.66900}, // 0 + {293.299, -505.95, 142.03}, // 1 + {301.664, -535.164, 146.097}, // 2 + {521.031006, -544.667847, 128.80064}, // 3 + {477.311981, -509.296814, 104.72308}, // 4 + {341.740997, -516.955017, 104.66900}, // 5 + {341.740997, -516.955017, 104.66900}, // 6 + {341.740997, -516.955017, 104.66900}, // 7 + // Triggers Left + {469.661, -484.546, 104.712}, // 8 + {483.315, -485.028, 104.718}, // 9 + {476.87, -487.994, 104.735}, //10 + {477.512, -497.772, 104.728}, //11 + {486.287, -500.759, 104.722}, //12 + {480.1, -503.895, 104.722}, //13 + {472.391, -505.103, 104.723}, //14 + {478.885, -510.803, 104.723}, //15 + {489.529, -508.615, 104.723}, //16 + {484.272, -508.589, 104.723}, //17 + {465.328, -506.495, 104.427}, //18 + {456.885, -508.104, 104.447}, //19 + {450.177, -507.989, 105.247}, //20 + {442.273, -508.029, 104.813}, //21 + {434.225, -508.19, 104.787}, //22 + {423.902, -508.525, 104.274}, //23 + {414.551, -508.645, 105.136}, //24 + {405.787, -508.755, 104.988}, //25 + {398.812, -507.224, 104.82}, //26 + {389.702, -506.846, 104.729}, //27 + {381.856, -506.76, 104.756}, //28 + {372.881, -507.254, 104.779}, //29 + {364.978, -508.182, 104.673}, //30 + {357.633, -508.075, 104.647}, //31 + {350.008, -506.826, 104.588}, //32 + {341.69, -506.77, 104.499}, //33 + {335.31, -505.745, 105.18}, //34 + {471.178, -510.74, 104.723}, //35 + {461.759, -510.365, 104.199}, //36 + {424.07287, -510.082916, 104.711082}, //37 + // Triggers Right + {489.46, -513.297, 105.413}, //38 + {485.706, -517.175, 104.724}, //39 + {480.98, -519.313, 104.724}, //40 + {475.05, -520.52, 104.724}, //41 + {482.97, -512.099, 104.724}, //42 + {477.082, -514.172, 104.724}, //43 + {468.991, -516.691, 104.724}, //44 + {461.722, -517.063, 104.627}, //45 + {455.88, -517.681, 104.707}, //46 + {450.499, -519.099, 104.701}, //47 + {444.889, -518.963, 104.82}, //48 + {440.181, -518.893, 104.861}, //49 + {434.393, -518.758, 104.891}, //50 + {429.328, -518.583, 104.904}, //51 + {423.844, -518.394, 105.004}, //52 + {418.707, -518.266, 105.135}, //53 + {413.377, -518.085, 105.153}, //54 + {407.277, -517.844, 104.893}, //55 + {401.082, -517.443, 104.723}, //56 + {394.933, -514.64, 104.724}, //57 + {388.917, -514.688, 104.734}, //58 + {383.814, -515.834, 104.73}, //59 + {377.887, -518.653, 104.777}, //60 + {371.376, -518.289, 104.781}, //61 + {365.669, -517.822, 104.758}, //62 + {359.572, -517.314, 104.706}, //63 + {353.632, -517.146, 104.647}, //64 + {347.998, -517.038, 104.538}, //65 + {341.803, -516.98, 104.584}, //66 + {335.879, -516.674, 104.628}, //67 + {329.871, -515.92, 104.711}, //68 + // Breach Zone + {485.4577, -511.2515, 115.3011}, //69 + {435.1892, -514.5232, 118.6719}, //70 + {413.9327, -540.9407, 138.2614}, //71 +}; + +enum eCombatPhase +{ + FLYING, + SKADI +}; + +enum eSpells +{ + //Skadi Spells + SPELL_CRUSH = 50234, + SPELL_POISONED_SPEAR = 50225, //isn't being casted =/ + SPELL_WHIRLWIND = 50228, //random target, but not the tank approx. every 20s + SPELL_RAPID_FIRE = 56570, + SPELL_HARPOON_DAMAGE = 56578, + SPELL_FREEZING_CLOUD = 47579, +}; + +enum eCreature +{ + CREATURE_YMIRJAR_WARRIOR = 26690, + CREATURE_YMIRJAR_WITCH_DOCTOR = 26691, + CREATURE_YMIRJAR_HARPOONER = 26692, + CREATURE_GRAUF = 26893, + CREATURE_TRIGGER = 28351, + DATA_MOUNT = 27043, +}; + +enum eAchievments +{ + ACHIEV_TIMED_START_EVENT = 17726, +}; + +struct boss_skadiAI : public ScriptedAI +{ + boss_skadiAI(Creature *c) : ScriptedAI(c), Summons(me) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + SummonList Summons; + uint64 m_uiGraufGUID; + std::vector triggersGUID; + + uint32 m_uiCrushTimer; + uint32 m_uiPoisonedSpearTimer; + uint32 m_uiWhirlwindTimer; + uint32 m_uiWaypointId; + uint32 m_uiMovementTimer; + uint32 m_uiMountTimer; + uint32 m_uiSummonTimer; + uint8 m_uiSpellHitCount; + bool m_bSaidEmote; + + eCombatPhase Phase; + + void Reset() + { + triggersGUID.clear(); + + m_uiCrushTimer = 8000; + m_uiPoisonedSpearTimer = 10000; + m_uiWhirlwindTimer = 20000; + m_uiMountTimer = 3000; + m_uiWaypointId = 0; + m_bSaidEmote = false; + m_uiSpellHitCount = 0; + + Phase = SKADI; + + Summons.DespawnAll(); + me->SetSpeed(MOVE_FLIGHT, 3.0f); + if ((Unit::GetCreature((*me), m_uiGraufGUID) == NULL) && !me->IsMounted()) + me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); + if (m_pInstance) + { + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, NOT_STARTED); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void JustReachedHome() + { + me->SetFlying(false); + me->Unmount(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + if (Unit::GetCreature((*me), m_uiGraufGUID) == NULL) + me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + Phase = FLYING; + + m_uiMovementTimer = 1000; + m_uiSummonTimer = 10000; + me->SetInCombatWithZone(); + if (m_pInstance) + { + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, IN_PROGRESS); + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + me->GetMotionMaster()->MoveJump(Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 5.0f, 10.0f); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + m_uiMountTimer = 1000; + Summons.DespawnEntry(CREATURE_GRAUF); + } + } + + void JustSummoned(Creature* pSummoned) + { + switch (pSummoned->GetEntry()) + { + case CREATURE_GRAUF: + m_uiGraufGUID = pSummoned->GetGUID(); + break; + case CREATURE_YMIRJAR_WARRIOR: + case CREATURE_YMIRJAR_WITCH_DOCTOR: + case CREATURE_YMIRJAR_HARPOONER: + pSummoned->setActive(true); + pSummoned->SetInCombatWithZone(); + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + break; + case CREATURE_TRIGGER: + pSummoned->CastSpell((Unit*)NULL, SPELL_FREEZING_CLOUD, true); + pSummoned->ForcedDespawn(10*IN_MILISECONDS); + break; + } + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature* pSummoned) + { + if (pSummoned->GetEntry() == CREATURE_GRAUF) + m_uiGraufGUID = 0; + Summons.Despawn(pSummoned); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_HARPOON_DAMAGE) + { + m_uiSpellHitCount++; + if (m_uiSpellHitCount >= 5) + { + Phase = SKADI; + me->SetFlying(false); + me->Unmount(); + if(Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILISECONDS)) + { + pGrauf->GetMotionMaster()->MoveFall(0); + pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); + } + sLog.outBasic("[Skadi] Fly off"); + me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + DoScriptText(SAY_DRAKE_DEATH, me); + m_uiCrushTimer = 8000; + m_uiPoisonedSpearTimer = 10000; + m_uiWhirlwindTimer = 20000; + me->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); + } + } + } + + + void UpdateAI(const uint32 diff) + { + switch(Phase) + { + case FLYING: + if (!UpdateVictim()) + return; + + if (me->GetPositionX() >= 519) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + if (!m_bSaidEmote) + { + DoScriptText(EMOTE_RANGE, me); + m_bSaidEmote = true; + } + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + m_bSaidEmote = false; + } + + if (m_uiMountTimer && m_uiMountTimer <= diff) + { + me->Mount(DATA_MOUNT); + me->SetFlying(true); + m_uiMountTimer = 0; + } else m_uiMountTimer -= diff; + + if (m_uiSummonTimer <= diff) + { + SpawnMobs(); + m_uiSummonTimer = 25000; + } else m_uiSummonTimer -= diff; + + if (m_uiMovementTimer <= diff) + { + switch(m_uiWaypointId) + { + case 0: + me->GetMotionMaster()->MovePoint(0, Location[1].GetPositionX(), Location[1].GetPositionY(), Location[1].GetPositionZ()); + m_uiMovementTimer = 5000; + break; + case 1: + me->GetMotionMaster()->MovePoint(0, Location[2].GetPositionX(), Location[2].GetPositionY(), Location[2].GetPositionZ()); + m_uiMovementTimer = 2000; + break; + case 2: + me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); + m_uiMovementTimer = 15000; + break; + case 3: + me->GetMotionMaster()->MovePoint(0, Location[69].GetPositionX(), Location[69].GetPositionY(), Location[69].GetPositionZ()); + DoScriptText(RAND(SAY_DRAKE_BREATH_1,SAY_DRAKE_BREATH_2), me); + DoScriptText(EMOTE_BREATH, me); + m_uiMovementTimer = 2500; + break; + case 4: + me->GetMotionMaster()->MovePoint(0, Location[70].GetPositionX(), Location[70].GetPositionY(), Location[70].GetPositionZ()); + m_uiMovementTimer = 2000; + SpawnTrigger(); + break; + case 5: + me->GetMotionMaster()->MovePoint(0, Location[71].GetPositionX(), Location[71].GetPositionY(), Location[71].GetPositionZ()); + m_uiMovementTimer = 3000; + break; + case 6: + me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); + m_uiWaypointId = 2; + m_uiMovementTimer = 15000; + break; + } + m_uiWaypointId++; + } else m_uiMovementTimer -= diff; + break; + case SKADI: + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_uiCrushTimer <= diff) + { + DoCastVictim(SPELL_CRUSH); + m_uiCrushTimer = 8000; + } else m_uiCrushTimer -= diff; + + if (m_uiPoisonedSpearTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_POISONED_SPEAR); + m_uiPoisonedSpearTimer = 10000; + } else m_uiPoisonedSpearTimer -= diff; + + if (m_uiWhirlwindTimer <= diff) + { + DoCastAOE(SPELL_WHIRLWIND); + m_uiWhirlwindTimer = 20000; + } else m_uiWhirlwindTimer -= diff; + + DoMeleeAttackIfReady(); + break; + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + Summons.DespawnAll(); + if (m_pInstance) + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void SpawnMobs() + { + for (uint8 i = 0; i < DUNGEON_MODE(5,6); ++i) + { + switch (urand(0,2)) + { + case 0: me->SummonCreature(CREATURE_YMIRJAR_WARRIOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + case 1: me->SummonCreature(CREATURE_YMIRJAR_WITCH_DOCTOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + case 2: me->SummonCreature(CREATURE_YMIRJAR_HARPOONER, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + } + } + } + + void SpawnTrigger() + { + uint8 iStart,iEnd; + switch (urand(0,1)) + { + case 0: + iStart = 8; + iEnd = 37; + break; + case 1: + iStart = 38; + iEnd = 68; + break; + } + for(uint32 i = iStart; i < iEnd; ++i) + me->SummonCreature(CREATURE_TRIGGER,Location[i]); + } +}; + +bool GOHello_go_harpoon_launcher(Player *pPlayer, GameObject *pGO) +{ + ScriptedInstance* m_pInstance; + m_pInstance = (ScriptedInstance*)pGO->GetInstanceData(); + if (!m_pInstance) return false; + + if (Creature* pSkadi = Unit::GetCreature((*pGO),m_pInstance->GetData64(DATA_SKADI_THE_RUTHLESS))) + { + pPlayer->CastSpell(pSkadi,SPELL_RAPID_FIRE, true); + } + return false; +} + +CreatureAI* GetAI_boss_skadi(Creature* pCreature) +{ + return new boss_skadiAI (pCreature); +} + +void AddSC_boss_skadi() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_skadi"; + newscript->GetAI = &GetAI_boss_skadi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_harpoon_launcher"; + newscript->pGOHello = &GOHello_go_harpoon_launcher; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp new file mode 100644 index 00000000000..aae1015ddab --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp @@ -0,0 +1,408 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_CALL_FLAMES = 48258, + SPELL_RITUAL_OF_THE_SWORD = 48276, //Effect #1 Teleport, Effect #2 Dummy + SPELL_SINSTER_STRIKE = 15667, + H_SPELL_SINSTER_STRIKE = 59409, + SPELL_SVALA_TRANSFORMING1 = 54140, + SPELL_SVALA_TRANSFORMING2 = 54205 +}; +//not in db +enum Yells +{ + SAY_DIALOG_WITH_ARTHAS_1 = -1575015, + SAY_DIALOG_WITH_ARTHAS_2 = -1575016, + SAY_DIALOG_WITH_ARTHAS_3 = -1575017, + SAY_AGGRO = -1575018, + SAY_SLAY_1 = -1575019, + SAY_SLAY_2 = -1575020, + SAY_SLAY_3 = -1575021, + SAY_DEATH = -1575022, + SAY_SACRIFICE_PLAYER_1 = -1575023, + SAY_SACRIFICE_PLAYER_2 = -1575024, + SAY_SACRIFICE_PLAYER_3 = -1575025, + SAY_SACRIFICE_PLAYER_4 = -1575026, + SAY_SACRIFICE_PLAYER_5 = -1575027, + SAY_DIALOG_OF_ARTHAS_1 = -1575028, + SAY_DIALOG_OF_ARTHAS_2 = -1575029 +}; +enum Creatures +{ + CREATURE_ARTHAS = 24266, // Image of Arthas + CREATURE_SVALA_SORROWGRAVE = 26668, // Svala after transformation + CREATURE_SVALA = 29281, // Svala before transformation + CREATURE_RITUAL_CHANNELER = 27281 +}; +enum ChannelerSpells +{ + //ritual channeler's spells + SPELL_PARALYZE = 48278, + SPELL_SHADOWS_IN_THE_DARK = 59407 +}; +enum Misc +{ + DATA_SVALA_DISPLAY_ID = 25944 +}; +enum IntroPhase +{ + IDLE, + INTRO, + FINISHED +}; +enum CombatPhase +{ + NORMAL, + SACRIFICING +}; + +static Position RitualChannelerPos[]= +{ + {296.42, -355.01, 90.94}, + {302.36, -352.01, 90.54}, + {291.39, -350.89, 90.54} +}; +static Position ArthasPos = { 295.81, -366.16, 92.57, 1.58 }; +static Position SvalaPos = { 296.632, -346.075, 90.6307, 1.58 }; + +struct boss_svalaAI : public ScriptedAI +{ + boss_svalaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiIntroTimer; + + uint8 uiIntroPhase; + + IntroPhase Phase; + + TempSummon* pArthas; + uint64 uiArthasGUID; + + ScriptedInstance* pInstance; + + void Reset() + { + Phase = IDLE; + uiIntroTimer = 1*IN_MILISECONDS; + uiIntroPhase = 0; + uiArthasGUID = 0; + + if (pInstance) + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (Phase == IDLE && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && me->IsWithinDistInMap(pWho, 40)) + { + Phase = INTRO; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Creature *pArthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pArthas->SetFloatValue(OBJECT_FIELD_SCALE_X, 5); + uiArthasGUID = pArthas->GetGUID(); + } + } + } + + void AttackStart(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (Phase != INTRO) + return; + + if (uiIntroTimer <= diff) + { + Creature *pArthas = Unit::GetCreature(*me, uiArthasGUID); + if (!pArthas) + return; + + switch (uiIntroPhase) + { + case 0: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_1, me); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 1: + DoScriptText(SAY_DIALOG_OF_ARTHAS_1, pArthas); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 2: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_2, me); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 3: + DoScriptText(SAY_DIALOG_OF_ARTHAS_2, pArthas); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 4: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_3, me); + DoCast(me, SPELL_SVALA_TRANSFORMING1); + ++uiIntroPhase; + uiIntroTimer = 2.8*IN_MILISECONDS; + break; + case 5: + DoCast(me, SPELL_SVALA_TRANSFORMING2); + ++uiIntroPhase; + uiIntroTimer = 200; + break; + case 6: + if (Creature* pSvalaSorrowgrave = me->SummonCreature(CREATURE_SVALA_SORROWGRAVE, SvalaPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60*IN_MILISECONDS)) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(DATA_SVALA_DISPLAY_ID); + pArthas->ToTempSummon()->UnSummon(); + uiArthasGUID = 0; + Phase = FINISHED; + } + else + Reset(); + break; + } + } else uiIntroTimer -= diff; + } +}; + +struct mob_ritual_channelerAI : public Scripted_NoMovementAI +{ + mob_ritual_channelerAI(Creature *c) :Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + DoCast(me, SPELL_SHADOWS_IN_THE_DARK); + } + + // called by svala sorrowgrave to set guid of victim + void DoAction(uint32 /*action*/) + { + if (pInstance) + if (Unit *pVictim = me->GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER))) + DoCast(pVictim, SPELL_PARALYZE); + } + + void EnterCombat(Unit* /*who*/) + { + } +}; + +struct boss_svala_sorrowgraveAI : public ScriptedAI +{ + boss_svala_sorrowgraveAI(Creature *c) : ScriptedAI(c), summons(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiSinsterStrikeTimer; + uint32 uiCallFlamesTimer; + uint32 uiRitualOfSwordTimer; + uint32 uiSacrificeTimer; + + CombatPhase Phase; + + SummonList summons; + + bool bSacrificed; + + ScriptedInstance* pInstance; + + void Reset() + { + uiSinsterStrikeTimer = 7*IN_MILISECONDS; + uiCallFlamesTimer = 10*IN_MILISECONDS; + uiRitualOfSwordTimer = 20*IN_MILISECONDS; + uiSacrificeTimer = 8*IN_MILISECONDS; + + bSacrificed = false; + + Phase = NORMAL; + + DoTeleportTo(296.632, -346.075, 90.6307); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + + summons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); + pInstance->SetData64(DATA_SACRIFICED_PLAYER,0); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature *summon) + { + summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature *summon) + { + summons.Despawn(summon); + } + + void UpdateAI(const uint32 diff) + { + if (Phase == NORMAL) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiSinsterStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); + uiSinsterStrikeTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); + } else uiSinsterStrikeTimer -= diff; + + if (uiCallFlamesTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_CALL_FLAMES); + uiCallFlamesTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); + } + } else uiCallFlamesTimer -= diff; + + if (!bSacrificed) + if (uiRitualOfSwordTimer <= diff) + { + if (Unit* pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(RAND(SAY_SACRIFICE_PLAYER_1,SAY_SACRIFICE_PLAYER_2,SAY_SACRIFICE_PLAYER_3,SAY_SACRIFICE_PLAYER_4,SAY_SACRIFICE_PLAYER_5),me); + DoCast(pSacrificeTarget, SPELL_RITUAL_OF_THE_SWORD); + //Spell doesn't teleport + DoTeleportPlayer(pSacrificeTarget, 296.632, -346.075, 90.63, 4.6); + me->SetUnitMovementFlags(MOVEMENTFLAG_FLY_MODE); + DoTeleportTo(296.632, -346.075, 120.85); + Phase = SACRIFICING; + if (pInstance) + { + pInstance->SetData64(DATA_SACRIFICED_PLAYER,pSacrificeTarget->GetGUID()); + + for (uint8 i = 0; i < 3; ++i) + if (Creature* pSummon = me->SummonCreature(CREATURE_RITUAL_CHANNELER, RitualChannelerPos[i], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) + pSummon->AI()->DoAction(0); + } + + bSacrificed = true; + } + } else uiRitualOfSwordTimer -= diff; + + DoMeleeAttackIfReady(); + } + else //SACRIFICING + { + if (uiSacrificeTimer <= diff) + { + Unit* pSacrificeTarget = pInstance ? Unit::GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER)) : NULL; + if (pInstance && !summons.empty() && pSacrificeTarget && pSacrificeTarget->isAlive()) + me->Kill(pSacrificeTarget, false); // durability damage? + + //go down + Phase = NORMAL; + pSacrificeTarget = NULL; + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + me->GetMotionMaster()->MoveChase(pTarget); + + uiSacrificeTimer = 8*IN_MILISECONDS; + } + else uiSacrificeTimer -= diff; + } + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* pKiller) + { + if (pInstance) + { + Creature* pSvala = Unit::GetCreature((*me), pInstance->GetData64(DATA_SVALA)); + if (pSvala && pSvala->isAlive()) + pKiller->Kill(pSvala); + + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); + } + DoScriptText(SAY_DEATH, me); + } +}; + +CreatureAI* GetAI_boss_svala(Creature* pCreature) +{ + return new boss_svalaAI (pCreature); +} + +CreatureAI* GetAI_mob_ritual_channeler(Creature* pCreature) +{ + return new mob_ritual_channelerAI(pCreature); +} + +CreatureAI* GetAI_boss_svala_sorrowgrave(Creature* pCreature) +{ + return new boss_svala_sorrowgraveAI(pCreature); +} + +void AddSC_boss_svala() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_svala"; + newscript->GetAI = &GetAI_boss_svala; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ritual_channeler"; + newscript->GetAI = &GetAI_mob_ritual_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_svala_sorrowgrave"; + newscript->GetAI = &GetAI_boss_svala_sorrowgrave; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp new file mode 100644 index 00000000000..1a650f94101 --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp @@ -0,0 +1,367 @@ +/* Script Data Start +SDName: Boss ymiron +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_ymiron' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_BANE = 48294, + H_SPELL_BANE = 59301, + SPELL_DARK_SLASH = 48292, + SPELL_FETID_ROT = 48291, + H_SPELL_FETID_ROT = 59300, + SPELL_SCREAMS_OF_THE_DEAD = 51750, + SPELL_SPIRIT_BURST = 48529, + H_SPELL_SPIRIT_BURST = 59305, + SPELL_SPIRIT_STRIKE = 48423, + H_SPELL_SPIRIT_STRIKE = 59304, + SPELL_ANCESTORS_VENGEANCE = 16939, + + SPELL_SUMMON_AVENGING_SPIRIT = 48592, + SPELL_SUMMON_SPIRIT_FOUNT = 48386, + + SPELL_CHANNEL_SPIRIT_TO_YMIRON = 48316, + SPELL_CHANNEL_YMIRON_TO_SPIRIT = 48307, + + SPELL_SPIRIT_FOUNT = 48380, + H_SPELL_SPIRIT_FOUNT = 59320 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1575028, + SAY_SLAY_1 = -1575029, + SAY_SLAY_2 = -1575030, + SAY_SLAY_3 = -1575031, + SAY_SLAY_4 = -1575032, + SAY_DEATH = -1575033, + SAY_SUMMON_BJORN = -1575034, + SAY_SUMMON_HALDOR = -1575035, + SAY_SUMMON_RANULF = -1575036, + SAY_SUMMON_TORGYN = -1575037 +}; + +enum Creatures +{ + CREATURE_BJORN = 27303, + CREATURE_BJORN_VISUAL = 27304, + CREATURE_HALDOR = 27307, + CREATURE_HALDOR_VISUAL = 27310, + CREATURE_RANULF = 27308, + CREATURE_RANULF_VISUAL = 27311, + CREATURE_TORGYN = 27309, + CREATURE_TORGYN_VISUAL = 27312, + CREATURE_SPIRIT_FOUNT = 27339, + CREATURE_AVENGING_SPIRIT = 27386 +}; + +struct ActiveBoatStruct +{ + uint32 npc; + int32 say; + float MoveX,MoveY,MoveZ,SpawnX,SpawnY,SpawnZ,SpawnO; +}; + +static ActiveBoatStruct ActiveBot[4] = +{ + {CREATURE_BJORN_VISUAL, SAY_SUMMON_BJORN, 404.379, -335.335, 104.756, 413.594, -335.408, 107.995, 3.157}, + {CREATURE_HALDOR_VISUAL, SAY_SUMMON_HALDOR, 380.813, -335.069, 104.756, 369.994, -334.771, 107.995, 6.232}, + {CREATURE_RANULF_VISUAL, SAY_SUMMON_RANULF, 381.546, -314.362, 104.756, 370.841, -314.426, 107.995, 6.232}, + {CREATURE_TORGYN_VISUAL, SAY_SUMMON_TORGYN, 404.310, -314.761, 104.756, 413.992, -314.703, 107.995, 3.157} +}; + +struct boss_ymironAI : public ScriptedAI +{ + boss_ymironAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + srand(time(NULL)); + for (int i = 0; i < 4; ++i) + m_uiActiveOrder[i] = i; + for (int i = 0; i < 3; ++i) + { + int r = i + (rand()%(4-i)); + int temp = m_uiActiveOrder[i]; + m_uiActiveOrder[i] = m_uiActiveOrder[r]; + m_uiActiveOrder[r] = temp; + } + } + + bool m_bIsWalking; + bool m_bIsPause; + bool m_bIsActiveWithBJORN; + bool m_bIsActiveWithHALDOR; + bool m_bIsActiveWithRANULF; + bool m_bIsActiveWithTORGYN; + + uint8 m_uiActiveOrder[4]; + uint8 m_uiActivedNumber; + + uint32 m_uiFetidRot_Timer; + uint32 m_uiBane_Timer; + uint32 m_uiDarkSlash_Timer; + uint32 m_uiAncestors_Vengeance_Timer; + + uint32 m_uiAbility_BJORN_Timer; + uint32 m_uiAbility_HALDOR_Timer; + uint32 m_uiAbility_RANULF_Timer; + uint32 m_uiAbility_TORGYN_Timer; + + uint32 m_uiPause_Timer; + uint32 m_uiHealthAmountModifier; + uint32 m_uiHealthAmountMultipler; + + uint64 m_uiActivedCreatureGUID; + uint64 m_uiOrbGUID; + + ScriptedInstance *pInstance; + + void Reset() + { + m_bIsPause = false; + m_bIsActiveWithBJORN = false; + m_bIsActiveWithHALDOR = false; + m_bIsActiveWithRANULF = false; + m_bIsActiveWithTORGYN = false; + + m_uiFetidRot_Timer = urand(8000,13000); + m_uiBane_Timer = urand(18000,23000); + m_uiDarkSlash_Timer = urand(28000,33000); + m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(60000,45000); + m_uiPause_Timer = 0; + + m_uiAbility_BJORN_Timer = 0; + m_uiAbility_HALDOR_Timer = 0; + m_uiAbility_RANULF_Timer = 0; + m_uiAbility_TORGYN_Timer = 0; + + m_uiActivedNumber = 0; + m_uiHealthAmountModifier = 1; + m_uiHealthAmountMultipler = DUNGEON_MODE(20,25); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (m_bIsWalking) + { + if (m_uiPause_Timer <= diff) + { + DoScriptText(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].say, me); + DoCast(me, SPELL_CHANNEL_YMIRON_TO_SPIRIT); // should be on spirit + if (Creature* pTemp = me->SummonCreature(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].npc, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnX, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnY, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnZ, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnO, TEMPSUMMON_CORPSE_DESPAWN, 0)) + { + m_uiActivedCreatureGUID = pTemp->GetGUID(); + pTemp->CastSpell(me, SPELL_CHANNEL_SPIRIT_TO_YMIRON, true); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + switch(m_uiActiveOrder[m_uiActivedNumber]) + { + case 0: m_bIsActiveWithBJORN = true; break; + case 1: m_bIsActiveWithHALDOR = true; break; + case 2: m_bIsActiveWithRANULF = true; break; + case 3: m_bIsActiveWithTORGYN = true; break; + } + } + + m_bIsPause = true; + m_bIsWalking = false; + m_uiPause_Timer = 3000; + } else m_uiPause_Timer -= diff; + return; + } + else if (m_bIsPause) + { + if (m_uiPause_Timer <= diff) + { + m_uiAbility_BJORN_Timer = 5000; + m_uiAbility_HALDOR_Timer = 5000; + m_uiAbility_RANULF_Timer = 5000; + m_uiAbility_TORGYN_Timer = 5000; + + m_bIsPause = false; + m_uiPause_Timer = 0; + } else m_uiPause_Timer -= diff; + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!m_bIsPause) + { + // Normal spells ------------------------------------------------------------------------ + if (m_uiBane_Timer <= diff) + { + DoCast(me, SPELL_BANE); + m_uiBane_Timer = urand(20000,25000); + } else m_uiBane_Timer -= diff; + + if (m_uiFetidRot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FETID_ROT); + m_uiFetidRot_Timer = urand(10000,15000); + } else m_uiFetidRot_Timer -= diff; + + if (m_uiDarkSlash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DARK_SLASH); + m_uiDarkSlash_Timer = urand(30000,35000); + } else m_uiDarkSlash_Timer -= diff; + + if (m_uiAncestors_Vengeance_Timer <= diff) + { + DoCast(me, SPELL_ANCESTORS_VENGEANCE); + m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(urand(60000,65000),urand(45000,50000)); + } else m_uiAncestors_Vengeance_Timer -= diff; + + // Abilities ------------------------------------------------------------------------------ + if (m_bIsActiveWithBJORN && m_uiAbility_BJORN_Timer <= diff) + { + //DoCast(me, SPELL_SUMMON_SPIRIT_FOUNT); // works fine, but using summon has better control + if (Creature* pTemp = me->SummonCreature(CREATURE_SPIRIT_FOUNT, 385+rand()%10, -330+rand()%10, 104.756, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) + { + pTemp->SetSpeed(MOVE_RUN, 0.4f); + pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SPIRIT_FOUNT, H_SPELL_SPIRIT_FOUNT), true); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetDisplayId(11686); + //pTemp->GetMotionMaster()->MoveChase(me->getVictim()); + m_uiOrbGUID = pTemp->GetGUID(); + } + m_bIsActiveWithBJORN = false; // only one orb + } else m_uiAbility_BJORN_Timer -= diff; + + if (m_bIsActiveWithHALDOR && m_uiAbility_HALDOR_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SPIRIT_STRIKE); + m_uiAbility_HALDOR_Timer = 5000; // overtime + } else m_uiAbility_HALDOR_Timer -= diff; + + if (m_bIsActiveWithRANULF && m_uiAbility_RANULF_Timer <= diff) + { + DoCast(me, SPELL_SPIRIT_BURST); + m_uiAbility_RANULF_Timer = 10000; // overtime + } else m_uiAbility_RANULF_Timer -= diff; + + if (m_bIsActiveWithTORGYN && m_uiAbility_TORGYN_Timer <= diff) + { + float x,y,z; + x = me->GetPositionX()-5; + y = me->GetPositionY()-5; + z = me->GetPositionZ(); + for (uint8 i = 0; i < 4; ++i) + { + //DoCast(me, SPELL_SUMMON_AVENGING_SPIRIT); // works fine, but using summon has better control + if (Creature* pTemp = me->SummonCreature(CREATURE_AVENGING_SPIRIT, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + pTemp->AddThreat(pTarget, 0.0f); + pTemp->AI()->AttackStart(pTarget); + } + } + } + m_uiAbility_TORGYN_Timer = 15000; // overtime + } else m_uiAbility_TORGYN_Timer -= diff; + + // Health check ----------------------------------------------------------------------------- + if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(m_uiHealthAmountMultipler * m_uiHealthAmountModifier))) + { + uint8 m_uiOrder = m_uiHealthAmountModifier - 1; + ++m_uiHealthAmountModifier; + + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_SCREAMS_OF_THE_DEAD); + me->GetMotionMaster()->Clear(); + me->StopMoving(); + me->AttackStop(); + me->GetMotionMaster()->MovePoint(0, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveX, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveY, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveZ); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + m_bIsActiveWithBJORN = false; + m_bIsActiveWithHALDOR = false; + m_bIsActiveWithRANULF = false; + m_bIsActiveWithTORGYN = false; + + m_uiBane_Timer += 8000; + m_uiFetidRot_Timer += 8000; + m_uiDarkSlash_Timer += 8000; + m_uiAncestors_Vengeance_Timer += 8000; + + m_uiActivedNumber = m_uiOrder; + m_bIsWalking = true; + m_uiPause_Timer = 2000; + return; + } + DoMeleeAttackIfReady(); + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } + + void DespawnBoatGhosts(uint64& m_uiCreatureGUID) + { + if (m_uiCreatureGUID) + if (Creature* pTemp = Unit::GetCreature(*me, m_uiCreatureGUID)) + pTemp->DisappearAndDie(); + + m_uiCreatureGUID = 0; + } +}; + +CreatureAI* GetAI_boss_ymiron(Creature* pCreature) +{ + return new boss_ymironAI(pCreature); +} + +void AddSC_boss_ymiron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ymiron"; + newscript->GetAI = &GetAI_boss_ymiron; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp new file mode 100644 index 00000000000..cf042867707 --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp @@ -0,0 +1,241 @@ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +#define MAX_ENCOUNTER 4 + +/* Utgarde Pinnacle encounters: +0 - Svala Sorrowgrave +1 - Gortok Palehoof +2 - Skadi the Ruthless +3 - King Ymiron +*/ + +enum GameObjects +{ + ENTRY_SKADI_THE_RUTHLESS_DOOR = 192173, + ENTRY_KING_YMIRON_DOOR = 192174, + ENTRY_GORK_PALEHOOF_SPHERE = 188593 +}; + +struct instance_pinnacle : public ScriptedInstance +{ + instance_pinnacle(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiSvalaSorrowgrave; + uint64 uiGortokPalehoof; + uint64 uiSkadiTheRuthless; + uint64 uiKingYmiron; + + uint64 uiSkadiTheRuthlessDoor; + uint64 uiKingYmironDoor; + uint64 uiGortokPalehoofSphere; + + uint64 uiFrenziedWorgen; + uint64 uiRavenousFurbolg; + uint64 uiFerociousRhino; + uint64 uiMassiveJormungar; + uint64 uiPalehoofOrb; + + uint64 uiSvala; + uint64 uiSacrificedPlayer; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + std::string str_data; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + m_auiEncounter[i] = NOT_STARTED; + + uiSvalaSorrowgrave = 0; + uiGortokPalehoof = 0; + uiSkadiTheRuthless = 0; + uiKingYmiron = 0; + + uiSkadiTheRuthlessDoor = 0; + uiKingYmironDoor = 0; + uiGortokPalehoofSphere = 0; + + uiFrenziedWorgen = 0; + uiRavenousFurbolg = 0; + uiFerociousRhino = 0; + uiMassiveJormungar = 0; + uiPalehoofOrb = 0; + + uiSvala = 0; + uiSacrificedPlayer = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case BOSS_SVALA_SORROWGRAVE: uiSvalaSorrowgrave = pCreature->GetGUID(); break; + case BOSS_GORTOK_PALEHOOF: uiGortokPalehoof = pCreature->GetGUID(); break; + case BOSS_SKADI_RUTHLESS: uiSkadiTheRuthless = pCreature->GetGUID(); break; + case BOSS_KING_YMIRON: uiKingYmiron = pCreature->GetGUID(); break; + case MOB_FRENZIED_WORGEN: uiFrenziedWorgen = pCreature->GetGUID(); break; + case MOB_RAVENOUS_FURBOLG: uiRavenousFurbolg = pCreature->GetGUID(); break; + case MOB_MASSIVE_JORMUNGAR: uiMassiveJormungar = pCreature->GetGUID(); break; + case MOB_FEROCIOUS_RHINO: uiFerociousRhino = pCreature->GetGUID(); break; + case MOB_SVALA: uiSvala = pCreature->GetGUID(); break; + case MOB_PALEHOOF_ORB: uiPalehoofOrb = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case ENTRY_SKADI_THE_RUTHLESS_DOOR: + uiSkadiTheRuthlessDoor = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) HandleGameObject(NULL,true,pGo); + break; + case ENTRY_KING_YMIRON_DOOR: + uiKingYmironDoor = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) HandleGameObject(NULL,true,pGo); + break; + case ENTRY_GORK_PALEHOOF_SPHERE: + uiGortokPalehoofSphere = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + { + HandleGameObject(NULL,true,pGo); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_SVALA_SORROWGRAVE_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_GORTOK_PALEHOOF_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_SKADI_THE_RUTHLESS_EVENT: + if (data == DONE) + HandleGameObject(uiSkadiTheRuthlessDoor,true); + m_auiEncounter[2] = data; + break; + case DATA_KING_YMIRON_EVENT: + if (data == DONE) + HandleGameObject(uiKingYmironDoor,true); + m_auiEncounter[3] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_SACRIFICED_PLAYER) + uiSacrificedPlayer = data; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_SVALA_SORROWGRAVE_EVENT: return m_auiEncounter[0]; + case DATA_GORTOK_PALEHOOF_EVENT: return m_auiEncounter[1]; + case DATA_SKADI_THE_RUTHLESS_EVENT: return m_auiEncounter[2]; + case DATA_KING_YMIRON_EVENT: return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_SVALA_SORROWGRAVE: return uiSvalaSorrowgrave; + case DATA_GORTOK_PALEHOOF: return uiGortokPalehoof; + case DATA_SKADI_THE_RUTHLESS: return uiSkadiTheRuthless; + case DATA_KING_YMIRON: return uiKingYmiron; + case DATA_MOB_FRENZIED_WORGEN: return uiFrenziedWorgen; + case DATA_MOB_RAVENOUS_FURBOLG: return uiRavenousFurbolg; + case DATA_MOB_MASSIVE_JORMUNGAR: return uiMassiveJormungar; + case DATA_MOB_FEROCIOUS_RHINO: return uiFerociousRhino; + case DATA_MOB_ORB: return uiPalehoofOrb; + case DATA_SVALA: return uiSvala; + case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "U P " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'U' && dataHead2 == 'P') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_utgarde_pinnacle(Map* pMap) +{ + return new instance_pinnacle(pMap); +} + +void AddSC_instance_utgarde_pinnacle() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_utgarde_pinnacle"; + newscript->GetInstanceData = &GetInstanceData_instance_utgarde_pinnacle; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h new file mode 100644 index 00000000000..a51d7aceda0 --- /dev/null +++ b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h @@ -0,0 +1,42 @@ +#ifndef DEF_PINNACLE_H +#define DEF_PINNACLE_H + +enum Data +{ + DATA_SVALA_SORROWGRAVE_EVENT, + DATA_GORTOK_PALEHOOF_EVENT, + DATA_SKADI_THE_RUTHLESS_EVENT, + DATA_KING_YMIRON_EVENT +}; +enum Data64 +{ + DATA_SVALA, + DATA_SVALA_SORROWGRAVE, + DATA_GORTOK_PALEHOOF, + DATA_SKADI_THE_RUTHLESS, + DATA_MOB_GRAUF, + DATA_KING_YMIRON, + DATA_MOB_FRENZIED_WORGEN, + DATA_MOB_RAVENOUS_FURBOLG, + DATA_MOB_MASSIVE_JORMUNGAR, + DATA_MOB_FEROCIOUS_RHINO, + DATA_MOB_ORB, + DATA_GORTOK_PALEHOOF_SPHERE, + DATA_SACRIFICED_PLAYER +}; + +enum eCreatures +{ + BOSS_SVALA_SORROWGRAVE = 26668, + BOSS_GORTOK_PALEHOOF = 26687, + BOSS_SKADI_RUTHLESS = 26693, + BOSS_KING_YMIRON = 26861, + MOB_FRENZIED_WORGEN = 26683, + MOB_RAVENOUS_FURBOLG = 26684, + MOB_MASSIVE_JORMUNGAR = 26685, + MOB_FEROCIOUS_RHINO = 26686, + MOB_SVALA = 29281, + MOB_PALEHOOF_ORB = 26688, +}; + +#endif diff --git a/src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp b/src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp new file mode 100644 index 00000000000..11d432e94c6 --- /dev/null +++ b/src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2009-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*** SQL START *** +UPDATE `creature_template` SET `ScriptName`='boss_archavon' WHERE `entry`='31125'; +UPDATE `creature_template` SET `ScriptName`='mob_archavon_warder' WHERE `entry`='32353'; +*** SQL END ***/ + +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +#define EMOTE_BERSERK -1590002 + +//Spells Archavon +#define SPELL_ROCK_SHARDS 58678 +#define SPELL_CRUSHING_LEAP RAID_MODE(58960,60894)//Instant (10-80yr range) -- Leaps at an enemy, inflicting 8000 Physical damage, knocking all nearby enemies away, and creating a cloud of choking debris. +#define SPELL_STOMP RAID_MODE(58663,60880) +#define SPELL_IMPALE RAID_MODE(58666,60882) //Lifts an enemy off the ground with a spiked fist, inflicting 47125 to 52875 Physical damage and 9425 to 10575 additional damage each second for 8 sec. +#define SPELL_BERSERK 47008 +//Spells Archavon Warders +#define SPELL_ROCK_SHOWER RAID_MODE(60919,60923) +#define SPELL_SHIELD_CRUSH RAID_MODE(60897,60899) +#define SPELL_WHIRL RAID_MODE(60902,60916) + +//4 Warders spawned +#define ARCHAVON_WARDER 32353 //npc 32353 + +//Yell +#define SAY_LEAP "Archavon the Stone Watcher lunges for $N!" //$N should be the target + +#define EVENT_ROCK_SHARDS 1 //15s cd +#define EVENT_CHOKING_CLOUD 2 //30s cd +#define EVENT_STOMP 3 //45s cd +#define EVENT_IMPALE 4 +#define EVENT_BERSERK 5 //300s cd + +//mob +#define EVENT_ROCK_SHOWER 5 //set = 20s cd,unkown cd +#define EVENT_SHIELD_CRUSH 6 //set = 30s cd +#define EVENT_WHIRL 8 //set= 10s cd + +struct boss_archavonAI : public ScriptedAI +{ + boss_archavonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit* /*Victim*/) {} + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); + events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); + events.ScheduleEvent(EVENT_STOMP, 45000); + events.ScheduleEvent(EVENT_BERSERK, 300000); + + if (pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, IN_PROGRESS); + } + + // Below UpdateAI may need review/debug. + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ROCK_SHARDS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ROCK_SHARDS); + events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); + return; + case EVENT_CHOKING_CLOUD: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CRUSHING_LEAP, true); //10y~80y, ignore range + events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); + return; + case EVENT_STOMP: + DoCast(me->getVictim(), SPELL_STOMP); + events.ScheduleEvent(EVENT_IMPALE, 3000); + events.ScheduleEvent(EVENT_STOMP, 45000); + return; + case EVENT_IMPALE: + DoCast(me->getVictim(), SPELL_IMPALE); + return; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + DoScriptText(EMOTE_BERSERK, me); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Mob Archavon Warder +######*/ +struct mob_archavon_warderAI : public ScriptedAI //npc 32353 +{ + mob_archavon_warderAI(Creature *c) : ScriptedAI(c) {} + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + events.ScheduleEvent(EVENT_ROCK_SHOWER, 2000); + events.ScheduleEvent(EVENT_SHIELD_CRUSH, 20000); + events.ScheduleEvent(EVENT_WHIRL, 7500); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ROCK_SHOWER: + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ROCK_SHOWER); + events.ScheduleEvent(EVENT_ROCK_SHARDS, 6000); + return; + } + case EVENT_SHIELD_CRUSH: + DoCast(me->getVictim(), SPELL_SHIELD_CRUSH); + events.ScheduleEvent(EVENT_SHIELD_CRUSH, 20000); + return; + case EVENT_WHIRL: + DoCast(me->getVictim(), SPELL_WHIRL); + events.ScheduleEvent(EVENT_WHIRL, 8000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_archavon_warder(Creature* pCreature) +{ + return new mob_archavon_warderAI(pCreature); +} + +CreatureAI* GetAI_boss_archavon(Creature* pCreature) +{ + return new boss_archavonAI (pCreature); +} + +void AddSC_boss_archavon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_archavon"; + newscript->GetAI = &GetAI_boss_archavon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_archavon_warder"; + newscript->GetAI = &GetAI_mob_archavon_warder; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp b/src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp new file mode 100644 index 00000000000..92a0331708e --- /dev/null +++ b/src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2009-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +//Emalon spells +#define SPELL_CHAIN_LIGHTNING RAID_MODE(64213, 64215) +#define SPELL_LIGHTNING_NOVA RAID_MODE(64216, 65279) +#define SPELL_OVERCHARGE 64218 //Casted every 45 sec on a random Tempest Minion +#define SPELL_BERSERK 26662 + +//Tempest Minion spells +#define SPELL_SHOCK 64363 +#define SPELL_OVERCHARGED 64217 +#define SPELL_OVERCHARGED_BLAST 64219 //Casted when Overcharged reaches 10 stacks. Mob dies after that + +//Emotes +#define EMOTE_OVERCHARGE -1590000 +#define EMOTE_MINION_RESPAWN -1590001 +#define EMOTE_BERSERK -1590002 + +//Events +#define EVENT_CHAIN_LIGHTNING 1 +#define EVENT_LIGHTNING_NOVA 2 +#define EVENT_OVERCHARGE 3 +#define EVENT_BERSERK 4 +#define EVENT_SHOCK 5 + +//Creatures +#define MOB_TEMPEST_MINION 33998 + +#define MAX_TEMPEST_MINIONS 4 + +struct Position TempestMinions[MAX_TEMPEST_MINIONS] = +{ + {-203.980103, -281.287720, 91.650223, 1.598807}, + {-233.489410, -281.139282, 91.652412, 1.598807}, + {-233.267578, -297.104645, 91.681915, 1.598807}, + {-203.842529, -297.097015, 91.745163, 1.598807} +}; + +/*###### +## Emalon the Storm Watcher +######*/ +struct boss_emalonAI : public BossAI +{ + boss_emalonAI(Creature *c) : BossAI(c, DATA_EMALON_EVENT) + { + } + + void Reset() + { + _Reset(); + + for (uint8 i = 0; i < MAX_TEMPEST_MINIONS; ++i) + me->SummonCreature(MOB_TEMPEST_MINION, TempestMinions[i], TEMPSUMMON_CORPSE_DESPAWN, 0); + } + + void JustSummoned(Creature *summoned) + { + BossAI::JustSummoned(summoned); + + if (me->getVictim() && summoned->AI()) + summoned->AI()->AttackStart(me->getVictim()); + } + + void EnterCombat(Unit * who) + { + if (!summons.empty()) + { + for (std::list::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) + { + Creature *minion = Unit::GetCreature(*me, *itr); + if (minion && minion->isAlive() && !minion->getVictim() && minion->AI()) + minion->AI()->AttackStart(who); + } + } + + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 5000); + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 40000); + events.ScheduleEvent(EVENT_BERSERK, 360000); + events.ScheduleEvent(EVENT_OVERCHARGE, 45000); + + _EnterCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CHAIN_LIGHTNING: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 25000); + break; + case EVENT_LIGHTNING_NOVA: + DoCastAOE(SPELL_LIGHTNING_NOVA, false); + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 40000); + break; + case EVENT_OVERCHARGE: + if (!summons.empty()) + { + std::list::const_iterator itr = summons.begin(); + std::advance(itr, urand(0, summons.size()-1)); + Creature *minion = Unit::GetCreature(*me, *itr); + if (minion && minion->isAlive()) + { + minion->CastSpell(me, SPELL_OVERCHARGED, true); + minion->SetHealth(minion->GetMaxHealth()); + DoScriptText(EMOTE_OVERCHARGE, me); + events.ScheduleEvent(EVENT_OVERCHARGE, 45000); + } + } + break; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + DoScriptText(EMOTE_BERSERK, me); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Tempest Minion +######*/ +struct mob_tempest_minionAI : public ScriptedAI +{ + mob_tempest_minionAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + EventMap events; + + uint32 uiOverchargedTimer; + + void Reset() + { + events.Reset(); + + uiOverchargedTimer = 0; + } + + void JustDied(Unit* /*Killer*/) + { + if (Creature *pEmalon = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EMALON) : 0)) + { + if (pEmalon->isAlive()) + { + pEmalon->SummonCreature(MOB_TEMPEST_MINION, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoScriptText(EMOTE_MINION_RESPAWN, me); + } + } + } + + void EnterCombat(Unit * who) + { + DoZoneInCombat(); + events.ScheduleEvent(EVENT_SHOCK, 20000); + + if (Creature *pEmalon = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EMALON) : 0)) + { + if (!pEmalon->getVictim() && pEmalon->AI()) + pEmalon->AI()->AttackStart(who); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (Aura *overchargedAura = me->GetAura(SPELL_OVERCHARGED)) + { + if (overchargedAura->GetStackAmount() < 10) + { + if (uiOverchargedTimer <= diff) + { + DoCast(me, SPELL_OVERCHARGED); + uiOverchargedTimer = 2000; + } else uiOverchargedTimer -=diff; + } + else + { + if (overchargedAura->GetStackAmount() == 10) + { + DoCast(me, SPELL_OVERCHARGED_BLAST); + me->ForcedDespawn(); + DoScriptText(EMOTE_MINION_RESPAWN, me); + } + } + } + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHOCK: + DoCast(me->getVictim(), SPELL_SHOCK); + events.ScheduleEvent(EVENT_SHOCK, 20000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_tempest_minion(Creature *_Creature) +{ + return new mob_tempest_minionAI (_Creature); +} + +CreatureAI* GetAI_boss_emalon(Creature *_Creature) +{ + return new boss_emalonAI (_Creature); +} + +void AddSC_boss_emalon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_emalon"; + newscript->GetAI = &GetAI_boss_emalon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tempest_minion"; + newscript->GetAI = &GetAI_mob_tempest_minion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp b/src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp new file mode 100644 index 00000000000..61843647136 --- /dev/null +++ b/src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2009-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*** SQL START *** +UPDATE `creature_template` SET `ScriptName`='boss_koralon' WHERE `entry`='35013'; +UPDATE `creature_template` SET `ScriptName`='mob_flame_warder' WHERE `entry`='35143'; +*** SQL END ***/ + +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +enum Events +{ + EVENT_NONE, + + // Koralon + EVENT_BURNING_BREATH, + EVENT_BURNING_FURY, + EVENT_FLAME_CINDER_A, + EVENT_METEOR_FISTS_A, + EVENT_METEOR_FISTS_B, + + // Flame Warder + EVENT_FW_LAVA_BIRST, + EVENT_FW_METEOR_FISTS_A, + EVENT_FW_METEOR_FISTS_B, +}; + +enum Spells +{ + // Spells Koralon + SPELL_BURNING_BREATH = 66665, + SPELL_BURNING_BREATH_H = 67328, + SPELL_BURNING_FURY = 66721, + SPELL_FLAME_CINDER_A = 66684, + SPELL_FLAME_CINDER_A_H = 67332, + SPELL_FLAME_CINDER_B = 66681, // don't know the real relation to SPELL_FLAME_CINDER_A atm. + SPELL_METEOR_FISTS_A = 66725, + SPELL_METEOR_FISTS_A_H = 66765, + SPELL_METEOR_FISTS_B = 67333, + SPELL_METEOR_FISTS_B_H = 68161, + + // Spells Flame Warder + SPELL_FW_LAVA_BIRST = 66813, + SPELL_FW_LAVA_BIRST_H = 67330, + SPELL_FW_METEOR_FISTS_A = 66808, + SPELL_FW_METEOR_FISTS_A_H = 66809, + SPELL_FW_METEOR_FISTS_B = 67331, + SPELL_FW_METEOR_FISTS_B_H = 68160, +}; + +struct boss_koralonAI : public ScriptedAI +{ + boss_koralonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_KORALON_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit* /*Victim*/) {} + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_KORALON_EVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + + DoCast(me, SPELL_BURNING_FURY); + + events.ScheduleEvent(EVENT_BURNING_FURY, 20000); // TODO check timer + events.ScheduleEvent(EVENT_BURNING_BREATH, 15000); // 1st after 15sec, then every 45sec + events.ScheduleEvent(EVENT_METEOR_FISTS_A, 75000); // 1st after 75sec, then every 45sec + events.ScheduleEvent(EVENT_FLAME_CINDER_A, 30000); // TODO check timer + + if (pInstance) + pInstance->SetData(DATA_KORALON_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BURNING_FURY: + DoCast(me, SPELL_BURNING_FURY); + events.ScheduleEvent(EVENT_BURNING_FURY, 20000); + return; + case EVENT_BURNING_BREATH: + DoCast(me, RAID_MODE(SPELL_BURNING_BREATH,SPELL_BURNING_BREATH_H)); + events.ScheduleEvent(EVENT_BURNING_BREATH, 45000); + return; + case EVENT_METEOR_FISTS_A: + DoCast(me, RAID_MODE(SPELL_METEOR_FISTS_A,SPELL_METEOR_FISTS_A_H)); + events.ScheduleEvent(EVENT_METEOR_FISTS_B, 1500); + return; + case EVENT_METEOR_FISTS_B: + DoCast(me, RAID_MODE(SPELL_METEOR_FISTS_B,SPELL_METEOR_FISTS_B_H)); + events.ScheduleEvent(EVENT_METEOR_FISTS_A, 45000); + return; + case EVENT_FLAME_CINDER_A: + DoCast(me, RAID_MODE(SPELL_FLAME_CINDER_A,SPELL_FLAME_CINDER_A_H)); + events.ScheduleEvent(EVENT_FLAME_CINDER_A, 30000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Mob Flame Warder +######*/ +struct mob_flame_warderAI : public ScriptedAI +{ + mob_flame_warderAI(Creature *c) : ScriptedAI(c) {} + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + + events.ScheduleEvent(EVENT_FW_LAVA_BIRST, 5000); + events.ScheduleEvent(EVENT_FW_METEOR_FISTS_A, 10000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FW_LAVA_BIRST: + DoCast(me->getVictim(), RAID_MODE(SPELL_FW_LAVA_BIRST,SPELL_FW_LAVA_BIRST_H)); + events.ScheduleEvent(EVENT_FW_LAVA_BIRST, 15000); + return; + case EVENT_FW_METEOR_FISTS_A: + DoCast(me, RAID_MODE(SPELL_FW_METEOR_FISTS_A,SPELL_FW_METEOR_FISTS_A_H)); + events.ScheduleEvent(EVENT_FW_METEOR_FISTS_B, 1500); + return; + case EVENT_FW_METEOR_FISTS_B: + DoCast(me, RAID_MODE(SPELL_FW_METEOR_FISTS_B,SPELL_FW_METEOR_FISTS_B_H)); + events.ScheduleEvent(EVENT_FW_METEOR_FISTS_A, 20000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_koralon(Creature* pCreature) +{ + return new boss_koralonAI (pCreature); +} + +CreatureAI* GetAI_mob_flame_warder(Creature* pCreature) +{ + return new mob_flame_warderAI (pCreature); +} + +void AddSC_boss_koralon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_koralon"; + newscript->GetAI = &GetAI_boss_koralon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flame_warder"; + newscript->GetAI = &GetAI_mob_flame_warder; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp b/src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp new file mode 100644 index 00000000000..2e16f9211d2 --- /dev/null +++ b/src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2009-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*** SQL START *** +UPDATE `creature_template` SET `ScriptName`='boss_toravon' WHERE `entry`='38433'; +UPDATE `creature_template` SET `ScriptName`='mob_frost_warder' WHERE `entry`='38482'; +UPDATE `creature_template` SET `ScriptName`='mob_frozen_orb_stalker' WHERE `entry`='38461'; +UPDATE `creature_template` SET `ScriptName`='mob_frozen_orb' WHERE `entry`='38456'; +*** SQL END ***/ + +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +// Spells Toravon +#define SPELL_FREEZING_GROUND RAID_MODE(72090,72104) // don't know cd... using 20 secs. +#define SPELL_FROZEN_ORB RAID_MODE(72091,72095) +#define SPELL_WHITEOUT RAID_MODE(72034,72096) // Every 38 sec. cast. (after SPELL_FROZEN_ORB) +#define SPELL_FROZEN_MALLET 71993 + +// Spells Frost Warder +#define SPELL_FROST_BLAST RAID_MODE(72123,72124) // don't know cd... using 20 secs. +#define SPELL_FROZEN_MALLET 72122 + +// Spell Frozen Orb +#define SPELL_FROZEN_ORB_DMG 72081 // priodic dmg aura +#define SPELL_FROZEN_ORB_AURA 72067 // make visible + +// Spell Frozen Orb Stalker +#define SPELL_FROZEN_ORB_SUMMON 72093 // summon orb + +// Events boss +#define EVENT_FREEZING_GROUND 1 +#define EVENT_FROZEN_ORB 2 +#define EVENT_WHITEOUT 3 + +// Events mob +#define EVENT_FROST_BLAST 4 + +// Mob Frozen Orb +#define MOB_FROZEN_ORB 38456 // 1 in 10 mode and 3 in 25 mode + +struct boss_toravonAI : public ScriptedAI +{ + boss_toravonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_TORAVON_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit* /*Victim*/) {} + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_TORAVON_EVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + + DoCast(me, SPELL_FROZEN_MALLET); + + events.ScheduleEvent(EVENT_FROZEN_ORB, 11000); + events.ScheduleEvent(EVENT_WHITEOUT, 13000); + events.ScheduleEvent(EVENT_FREEZING_GROUND, 15000); + + if (pInstance) + pInstance->SetData(DATA_TORAVON_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROZEN_ORB: + DoCast(me, SPELL_FROZEN_ORB); + events.ScheduleEvent(EVENT_FROZEN_ORB, 38000); + return; + case EVENT_WHITEOUT: + DoCast(me, SPELL_WHITEOUT); + events.ScheduleEvent(EVENT_WHITEOUT, 38000); + return; + case EVENT_FREEZING_GROUND: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FREEZING_GROUND); + events.ScheduleEvent(EVENT_FREEZING_GROUND, 20000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Mob Frost Warder +######*/ +struct mob_frost_warderAI : public ScriptedAI +{ + mob_frost_warderAI(Creature *c) : ScriptedAI(c) {} + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + + DoCast(me, SPELL_FROZEN_MALLET); + + events.ScheduleEvent(EVENT_FROST_BLAST, 5000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROST_BLAST: + DoCast(me->getVictim(), SPELL_FROST_BLAST); + events.ScheduleEvent(EVENT_FROST_BLAST, 20000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + + +/*###### +## Mob Frozen Orb +######*/ +struct mob_frozen_orbAI : public ScriptedAI +{ + mob_frozen_orbAI(Creature *c) : ScriptedAI(c) {} + + bool done; + uint32 killtimer; + + void Reset() + { + done = false; + killtimer = 60000; // if after this time there is no victim -> destroy! + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!done) + { + DoCast(me, SPELL_FROZEN_ORB_AURA, true); + DoCast(me, SPELL_FROZEN_ORB_DMG, true); + done = true; + } + + if (killtimer <= diff) + { + if (!UpdateVictim()) + me->ForcedDespawn(); + killtimer = 10000; + } + else + killtimer -= diff; + } +}; + +/*###### +## Mob Frozen Orb Stalker +######*/ +struct mob_frozen_orb_stalkerAI : public Scripted_NoMovementAI +{ + mob_frozen_orb_stalkerAI(Creature* c) : Scripted_NoMovementAI(c) + { + c->SetVisibility(VISIBILITY_OFF); + c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); + c->SetReactState(REACT_PASSIVE); + + pInstance = c->GetInstanceData(); + spawned = false; + } + + ScriptedInstance *pInstance; + bool spawned; + + void UpdateAI(const uint32 /*diff*/) + { + if (spawned) + return; + + spawned = true; + if (!pInstance) + return; + + Unit* pToravon = me->GetCreature(*me, pInstance->GetData64(DATA_TORAVON)); + if (!pToravon) + return; + + uint8 num_orbs = RAID_MODE(1, 3); + for (uint8 i=0; iGetNearPoint(pToravon, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 10.0f, 0.0f); + me->SetPosition(pos, true); + DoCast(me, SPELL_FROZEN_ORB_SUMMON); + } + } +}; + +CreatureAI* GetAI_boss_toravon(Creature* pCreature) +{ + return new boss_toravonAI (pCreature); +} + +CreatureAI* GetAI_mob_frost_warder(Creature* pCreature) +{ + return new mob_frost_warderAI (pCreature); +} + +CreatureAI* GetAI_mob_frozen_orb(Creature* pCreature) +{ + return new mob_frozen_orbAI (pCreature); +} + +CreatureAI* GetAI_mob_frozen_orb_stalker(Creature* pCreature) +{ + return new mob_frozen_orb_stalkerAI (pCreature); +} + +void AddSC_boss_toravon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_toravon"; + newscript->GetAI = &GetAI_boss_toravon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_warder"; + newscript->GetAI = &GetAI_mob_frost_warder; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frozen_orb"; + newscript->GetAI = &GetAI_mob_frozen_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frozen_orb_stalker"; + newscript->GetAI = &GetAI_mob_frozen_orb_stalker; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp b/src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp new file mode 100644 index 00000000000..a7183921cce --- /dev/null +++ b/src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp @@ -0,0 +1,143 @@ +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +#define ENCOUNTERS 4 + +/* Vault of Archavon encounters: +1 - Archavon the Stone Watcher event +2 - Emalon the Storm Watcher event +3 - Koralon the Flame Watcher event +4 - Toravon the Ice Watcher event +*/ + +struct instance_archavon : public ScriptedInstance +{ + instance_archavon(Map *Map) : ScriptedInstance(Map) {}; + + uint32 uiEncounters[ENCOUNTERS]; + + uint64 uiArchavon; + uint64 uiEmalon; + uint64 uiKoralon; + uint64 uiToravon; + + void Initialize() + { + uiArchavon = 0; + uiEmalon = 0; + uiKoralon = 0; + uiToravon = 0; + + for (uint8 i = 0; i < ENCOUNTERS; i++) + uiEncounters[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < ENCOUNTERS; i++) + if (uiEncounters[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, bool /*add*/) + { + switch(creature->GetEntry()) + { + case CREATURE_ARCHAVON: uiArchavon = creature->GetGUID(); break; + case CREATURE_EMALON: uiEmalon = creature->GetGUID(); break; + case CREATURE_KORALON: uiKoralon = creature->GetGUID(); break; + case CREATURE_TORAVON: uiToravon = creature->GetGUID(); break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_ARCHAVON_EVENT: return uiEncounters[0]; + case DATA_EMALON_EVENT: return uiEncounters[1]; + case DATA_KORALON_EVENT: return uiEncounters[2]; + case DATA_TORAVON_EVENT: return uiEncounters[3]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_ARCHAVON: return uiArchavon; + case DATA_EMALON: return uiEmalon; + case DATA_KORALON: return uiKoralon; + case DATA_TORAVON: return uiToravon; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_ARCHAVON_EVENT: uiEncounters[0] = data; break; + case DATA_EMALON_EVENT: uiEncounters[1] = data; break; + case DATA_KORALON_EVENT: uiEncounters[2] = data; break; + case DATA_TORAVON_EVENT: uiEncounters[3] = data; break; + } + + if (data == DONE) + SaveToDB(); + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << uiEncounters[0] << " " << uiEncounters[1] << " " << uiEncounters[2] << " " << uiEncounters[3]; + + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream stream(in); + stream >> uiEncounters[0] >> uiEncounters[1] >> uiEncounters[2] >> uiEncounters[3]; + + for (uint8 i = 0; i < ENCOUNTERS; ++i) + if (uiEncounters[i] == IN_PROGRESS) + uiEncounters[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_archavon(Map* map) +{ + return new instance_archavon(map); +} + +void AddSC_instance_archavon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_archavon"; + newscript->GetInstanceData = &GetInstanceData_instance_archavon; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h b/src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h new file mode 100644 index 00000000000..6aa642ff701 --- /dev/null +++ b/src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h @@ -0,0 +1,28 @@ +#ifndef DEF_ARCHAVON_H +#define DEF_ARCHAVON_H + +enum Creatures +{ + CREATURE_ARCHAVON = 31125, + CREATURE_EMALON = 33993, + CREATURE_KORALON = 35013, + CREATURE_TORAVON = 38433, +}; + +enum Data +{ + DATA_ARCHAVON_EVENT, + DATA_EMALON_EVENT, + DATA_KORALON_EVENT, + DATA_TORAVON_EVENT, +}; + +enum Data64 +{ + DATA_ARCHAVON, + DATA_EMALON, + DATA_KORALON, + DATA_TORAVON, +}; + +#endif diff --git a/src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp new file mode 100644 index 00000000000..589e69a6f18 --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp @@ -0,0 +1,156 @@ +/* Script Data Start +SDName: Boss cyanigosa +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_ARCANE_VACUUM = 58694, + SPELL_BLIZZARD = 58693, + H_SPELL_BLIZZARD = 59369, + SPELL_MANA_DESTRUCTION = 59374, + SPELL_TAIL_SWEEP = 58690, + H_SPELL_TAIL_SWEEP = 59283, + SPELL_UNCONTROLLABLE_ENERGY = 58688, + H_SPELL_UNCONTROLLABLE_ENERGY = 59281, + SPELL_TRANSFORM = 58668 +}; + +enum Yells +{ + SAY_AGGRO = -1608000, + SAY_SLAY_1 = -1608001, + SAY_SLAY_2 = -1608002, + SAY_SLAY_3 = -1608003, + SAY_DEATH = -1608004, + SAY_SPAWN = -1608005, + SAY_DISRUPTION = -1608006, + SAY_BREATH_ATTACK = -1608007, + SAY_SPECIAL_ATTACK_1 = -1608008, + SAY_SPECIAL_ATTACK_2 = -1608009 +}; + +struct boss_cyanigosaAI : public ScriptedAI +{ + boss_cyanigosaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiArcaneVacuumTimer; + uint32 uiBlizzardTimer; + uint32 uiManaDestructionTimer; + uint32 uiTailSweepTimer; + uint32 uiUncontrollableEnergyTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiArcaneVacuumTimer = 10000; + uiBlizzardTimer = 15000; + uiManaDestructionTimer = 30000; + uiTailSweepTimer = 20000; + uiUncontrollableEnergyTimer = 25000; + if (pInstance) + pInstance->SetData(DATA_CYANIGOSA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_TRANSFORM); + + if (pInstance) + pInstance->SetData(DATA_CYANIGOSA_EVENT, IN_PROGRESS); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (pInstance && pInstance->GetData(DATA_REMOVE_NPC) == 1) + { + me->ForcedDespawn(); + pInstance->SetData(DATA_REMOVE_NPC, 0); + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiArcaneVacuumTimer <= diff) + { + DoCast(SPELL_ARCANE_VACUUM); + uiArcaneVacuumTimer = 10000; + } else uiArcaneVacuumTimer -= diff; + + if (uiBlizzardTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BLIZZARD); + uiBlizzardTimer = 15000; + } else uiBlizzardTimer -= diff; + + if (uiTailSweepTimer <= diff) + { + DoCast(SPELL_TAIL_SWEEP); + uiTailSweepTimer = 20000; + } else uiTailSweepTimer -= diff; + + if (uiUncontrollableEnergyTimer <= diff) + { + DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY); + uiUncontrollableEnergyTimer = 25000; + } else uiUncontrollableEnergyTimer -= diff; + + if (IsHeroic()) + if (uiManaDestructionTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_MANA_DESTRUCTION); + uiManaDestructionTimer = 30000; + } else uiManaDestructionTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_CYANIGOSA_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_cyanigosa(Creature* pCreature) +{ + return new boss_cyanigosaAI (pCreature); +} + +void AddSC_boss_cyanigosa() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_cyanigosa"; + newscript->GetAI = &GetAI_boss_cyanigosa; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/boss_erekem.cpp b/src/server/scripts/Northrend/violet_hold/boss_erekem.cpp new file mode 100644 index 00000000000..a9cc7393af4 --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/boss_erekem.cpp @@ -0,0 +1,329 @@ +/* Script Data Start +SDName: Boss erekem +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_BLOODLUST = 54516, + SPELL_BREAK_BONDS = 59463, + SPELL_CHAIN_HEAL = 54481, + H_SPELL_CHAIN_HEAL = 59473, + SPELL_EARTH_SHIELD = 54479, + H_SPELL_EARTH_SHIELD = 59471, + SPELL_EARTH_SHOCK = 54511, + SPELL_LIGHTNING_BOLT = 53044, + SPELL_STORMSTRIKE = 51876 +}; + +enum Yells +{ + SAY_AGGRO = -1608010, + SAY_SLAY_1 = -1608011, + SAY_SLAY_2 = -1608012, + SAY_SLAY_3 = -1608013, + SAY_DEATH = -1608014, + SAY_SPAWN = -1608015, + SAY_ADD_KILLED = -1608016, + SAY_BOTH_ADDS_KILLED = -1608017 +}; + +struct boss_erekemAI : public ScriptedAI +{ + boss_erekemAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBloodlustTimer; + uint32 uiChainHealTimer; + uint32 uiEarthShockTimer; + uint32 uiLightningBoltTimer; + uint32 uiEarthShieldTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiBloodlustTimer = 15000; + uiChainHealTimer = 0; + uiEarthShockTimer = urand(2000,8000); + uiLightningBoltTimer = urand(5000,10000); + uiEarthShieldTimer = 20000; + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + + if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + { + if (!pGuard1->isAlive()) + pGuard1->Respawn(); + } + if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + { + if (!pGuard2->isAlive()) + pGuard2->Respawn(); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + + if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + { + pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + if (!pGuard1->getVictim() && pGuard1->AI()) + pGuard1->AI()->AttackStart(pWho); + } + if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + { + pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + if (!pGuard2->getVictim() && pGuard2->AI()) + pGuard2->AI()->AttackStart(pWho); + } + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_EARTH_SHIELD); + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_EREKEM_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //spam stormstrike in hc mode if spawns are dead + if (IsHeroic()) + { + if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + { + if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + { + if (!pGuard1->isAlive() && !pGuard2->isAlive()) + DoCast(me->getVictim(), SPELL_STORMSTRIKE); + } + } + } + + if (uiEarthShieldTimer <= diff) + { + DoCast(me, SPELL_EARTH_SHIELD); + uiEarthShieldTimer = 20000; + } else uiEarthShieldTimer -= diff; + + if (uiChainHealTimer <= diff) + { + if (uint64 TargetGUID = GetChainHealTargetGUID()) + { + if (Creature *pTarget = Unit::GetCreature(*me, TargetGUID)) + DoCast(pTarget, SPELL_CHAIN_HEAL); + + //If one of the adds is dead spawn heals faster + Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0); + Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0); + uiChainHealTimer = ((pGuard1 && !pGuard1->isAlive()) || (pGuard2 && !pGuard2->isAlive()) ? 3000 : 8000) + rand()%3000; + } + } else uiChainHealTimer -= diff; + + if (uiBloodlustTimer <= diff) + { + DoCast(me, SPELL_BLOODLUST); + uiBloodlustTimer = urand(35000,45000); + } else uiBloodlustTimer -= diff; + + if (uiEarthShockTimer <= diff) + { + DoCast(me->getVictim(), SPELL_EARTH_SHOCK); + uiEarthShockTimer = urand(8000,13000); + } else uiEarthShockTimer -= diff; + + if (uiLightningBoltTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_LIGHTNING_BOLT); + uiLightningBoltTimer = urand(18000,24000); + } else uiLightningBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + uint64 GetChainHealTargetGUID() + { + if (HealthBelowPct(85)) + return me->GetGUID(); + + Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0); + if (pGuard1 && pGuard1->isAlive() && (pGuard1->GetHealth()*100 <= pGuard1->GetMaxHealth() * 75)) + return pGuard1->GetGUID(); + + Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0); + if (pGuard2 && pGuard2->isAlive() && (pGuard2->GetHealth()*100 <= pGuard2->GetMaxHealth() * 75)) + return pGuard2->GetGUID(); + + return 0; + } +}; + +CreatureAI* GetAI_boss_erekem(Creature* pCreature) +{ + return new boss_erekemAI (pCreature); +} + +enum GuardSpells +{ + SPELL_GUSHING_WOUND = 39215, + SPELL_HOWLING_SCREECH = 54462, + SPELL_STRIKE = 14516 +}; + +struct mob_erekem_guardAI : public ScriptedAI +{ + mob_erekem_guardAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiGushingWoundTimer; + uint32 uiHowlingScreechTimer; + uint32 uiStrikeTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiStrikeTimer = urand(4000,8000); + uiHowlingScreechTimer = urand(8000,13000); + uiGushingWoundTimer = urand(1000,3000); + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + + if (uiStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STRIKE); + uiStrikeTimer = urand(4000,8000); + } else uiStrikeTimer -= diff; + + if (uiHowlingScreechTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HOWLING_SCREECH); + uiHowlingScreechTimer = urand(8000,13000); + } else uiHowlingScreechTimer -= diff; + + if (uiGushingWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GUSHING_WOUND); + uiGushingWoundTimer = urand(7000,12000); + } else uiGushingWoundTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_erekem_guard(Creature* pCreature) +{ + return new mob_erekem_guardAI (pCreature); +} + +void AddSC_boss_erekem() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_erekem"; + newscript->GetAI = &GetAI_boss_erekem; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_erekem_guard"; + newscript->GetAI = &GetAI_mob_erekem_guard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp b/src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp new file mode 100644 index 00000000000..a28bfdffb7c --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp @@ -0,0 +1,394 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Boss ichoron +SDAuthor: ckegg +SD%Complete: 80% +SDComment: TODO: better spawn location for adds +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_DRAINED = 59820, + SPELL_FRENZY = 54312, + SPELL_FRENZY_H = 59522, + SPELL_PROTECTIVE_BUBBLE = 54306, + SPELL_WATER_BLAST = 54237, + SPELL_WATER_BLAST_H = 59520, + SPELL_WATER_BOLT_VOLLEY = 54241, + SPELL_WATER_BOLT_VOLLEY_H = 59521, + SPELL_SPLASH = 59516, +}; + +enum IchoronCreatures +{ + NPC_ICHOR_GLOBULE = 29321, +}; + +enum Yells +{ + SAY_AGGRO = -1608018, + SAY_SLAY_1 = -1608019, + SAY_SLAY_2 = -1608020, + SAY_SLAY_3 = -1608021, + SAY_DEATH = -1608022, + SAY_SPAWN = -1608023, + SAY_ENRAGE = -1608024, + SAY_SHATTER = -1608025, + SAY_BUBBLE = -1608026 +}; + +enum Achievements +{ + ACHIEVEMENT_DEHYDRATION = 2041, +}; + +enum Actions +{ + ACTION_WATER_ELEMENT_HIT = 1, + ACTION_WATER_ELEMENT_KILLED = 2, +}; + +// TODO get those positions from spawn of creature 29326 +#define MAX_SPAWN_LOC 5 +static Position SpawnLoc[MAX_SPAWN_LOC]= +{ + {1840.64, 795.407, 44.079, 1.676}, + {1886.24, 757.733, 47.750, 5.201}, + {1877.91, 845.915, 43.417, 3.560}, + {1918.97, 850.645, 47.225, 4.136}, + {1935.50, 796.224, 52.492, 4.224}, +}; + +struct boss_ichoronAI : public ScriptedAI +{ + boss_ichoronAI(Creature* pCreature) : ScriptedAI(pCreature), m_waterElements(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + bool bIsExploded; + bool bIsFrenzy; + bool bAchievement; + + uint32 uiBubbleCheckerTimer; + uint32 uiWaterBoltVolleyTimer; + + ScriptedInstance* pInstance; + + SummonList m_waterElements; + + void Reset() + { + bIsExploded = false; + bIsFrenzy = false; + bAchievement = true; + uiBubbleCheckerTimer = 1000; + uiWaterBoltVolleyTimer = urand(10000, 15000); + + me->SetVisibility(VISIBILITY_ON); + DespawnWaterElements(); + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + DoCast(me, SPELL_PROTECTIVE_BUBBLE); + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ICHORON_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void DoAction(const int32 param) + { + if (!me->isAlive()) + return; + + switch(param) + { + case ACTION_WATER_ELEMENT_HIT: + me->SetHealth(me->GetHealth() + me->GetMaxHealth() * 0.01); + + if (bIsExploded) + DoExplodeCompleted(); + + bAchievement = false; + break; + case ACTION_WATER_ELEMENT_KILLED: + uint32 damage = (me->GetMaxHealth()*3)/100; + me->SetHealth(me->GetHealth() - damage); + me->LowerPlayerDamageReq(damage); + break; + } + } + + void DespawnWaterElements() + { + m_waterElements.DespawnAll(); + } + + // call when explode shall stop. + // either when "hit" by a bubble, or when there is no bubble left. + void DoExplodeCompleted() + { + bIsExploded = false; + + if (!HealthBelowPct(25)) + { + DoScriptText(SAY_BUBBLE, me); + DoCast(me, SPELL_PROTECTIVE_BUBBLE, true); + } + + me->SetVisibility(VISIBILITY_ON); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + + void MoveInLineOfSight(Unit* /*pWho*/) {} + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded) + { + DoScriptText(SAY_ENRAGE, me); + DoCast(me, SPELL_FRENZY, true); + bIsFrenzy = true; + } + + if (!bIsFrenzy) + { + if (uiBubbleCheckerTimer <= uiDiff) + { + if (!bIsExploded) + { + if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE, 0)) + { + DoScriptText(SAY_SHATTER, me); + DoCast(me, SPELL_WATER_BLAST); + DoCast(me, SPELL_DRAINED); + bIsExploded = true; + me->AttackStop(); + me->SetVisibility(VISIBILITY_OFF); + for (uint8 i = 0; i < 10; i++) + { + int tmp = urand(0, MAX_SPAWN_LOC-1); + me->SummonCreature(NPC_ICHOR_GLOBULE, SpawnLoc[tmp], TEMPSUMMON_CORPSE_DESPAWN); + } + } + } + else + { + bool bIsWaterElementsAlive = false; + if (!m_waterElements.empty()) + { + for (std::list::const_iterator itr = m_waterElements.begin(); itr != m_waterElements.end(); ++itr) + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + if (pTemp->isAlive()) + { + bIsWaterElementsAlive = true; + break; + } + } + + if (!bIsWaterElementsAlive) + DoExplodeCompleted(); + } + uiBubbleCheckerTimer = 1000; + } + else uiBubbleCheckerTimer -= uiDiff; + } + + if (!bIsExploded) + { + if (uiWaterBoltVolleyTimer <= uiDiff) + { + DoCast(me, SPELL_WATER_BOLT_VOLLEY); + uiWaterBoltVolleyTimer = urand(10000, 15000); + } + else uiWaterBoltVolleyTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (bIsExploded) + { + bIsExploded = false; + me->SetVisibility(VISIBILITY_ON); + } + + DespawnWaterElements(); + + if (pInstance) + { + if (IsHeroic() && bAchievement) + pInstance->DoCompleteAchievement(ACHIEVEMENT_DEHYDRATION); + + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->SetSpeed(MOVE_RUN, 0.3f); + pSummoned->GetMotionMaster()->MoveFollow(me, 0, 0); + m_waterElements.push_back(pSummoned->GetGUID()); + } + + + void SummonedCreatureDespawn(Creature *pSummoned) + { + m_waterElements.remove(pSummoned->GetGUID()); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_ichoron(Creature* pCreature) +{ + return new boss_ichoronAI (pCreature); +} + +struct mob_ichor_globuleAI : public ScriptedAI +{ + mob_ichor_globuleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiRangeCheck_Timer; + + void Reset() + { + uiRangeCheck_Timer = 1000; + } + + void AttackStart(Unit* /*pWho*/) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiRangeCheck_Timer < uiDiff) + { + if (pInstance) + { + if (Creature* pIchoron = Unit::GetCreature(*me, pInstance->GetData64(DATA_ICHORON))) + { + if (me->IsWithinDist(pIchoron, 2.0f , false)) + { + if (pIchoron->AI()) + pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT); + me->ForcedDespawn(); + } + } + } + uiRangeCheck_Timer = 1000; + } + else uiRangeCheck_Timer -= uiDiff; + } + + void JustDied(Unit* /*pKiller*/) + { + DoCast(me, SPELL_SPLASH); + if (Creature* pIchoron = Unit::GetCreature(*me, pInstance->GetData64(DATA_ICHORON))) + if (pIchoron->AI()) + pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED); + } +}; + +CreatureAI* GetAI_mob_ichor_globule(Creature* pCreature) +{ + return new mob_ichor_globuleAI (pCreature); +} + +void AddSC_boss_ichoron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ichoron"; + newscript->GetAI = &GetAI_boss_ichoron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ichor_globule"; + newscript->GetAI = &GetAI_mob_ichor_globule; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp b/src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp new file mode 100644 index 00000000000..d8cd3a4962f --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp @@ -0,0 +1,155 @@ +/* Script Data Start +SDName: Boss lavanthor +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_CAUTERIZING_FLAMES = 59466, //Only in heroic + SPELL_FIREBOLT = 54235, + H_SPELL_FIREBOLT = 59468, + SPELL_FLAME_BREATH = 54282, + H_SPELL_FLAME_BREATH = 59469, + SPELL_LAVA_BURN = 54249, + H_SPELL_LAVA_BURN = 59594 +}; + +struct boss_lavanthorAI : public ScriptedAI +{ + boss_lavanthorAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiFireboltTimer; + uint32 uiFlameBreathTimer; + uint32 uiLavaBurnTimer; + uint32 uiCauterizingFlamesTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiFireboltTimer = 1000; + uiFlameBreathTimer = 5000; + uiLavaBurnTimer = 10000; + uiCauterizingFlamesTimer = 3000; + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_LAVANTHOR_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiFireboltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBOLT); + uiFireboltTimer = urand(5000,13000); + } else uiFireboltTimer -= diff; + + if (uiFlameBreathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAME_BREATH); + uiFlameBreathTimer = urand(10000,15000); + } else uiFlameBreathTimer -= diff; + + if (uiLavaBurnTimer <= diff) + { + DoCast(me->getVictim(), SPELL_LAVA_BURN); + uiLavaBurnTimer = urand(15000,23000); + } + + if (IsHeroic()) + { + if (uiCauterizingFlamesTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CAUTERIZING_FLAMES); + uiCauterizingFlamesTimer = urand(10000,16000); + } else uiCauterizingFlamesTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } +}; + +CreatureAI* GetAI_boss_lavanthor(Creature* pCreature) +{ + return new boss_lavanthorAI (pCreature); +} + +void AddSC_boss_lavanthor() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_lavanthor"; + newscript->GetAI = &GetAI_boss_lavanthor; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/boss_moragg.cpp b/src/server/scripts/Northrend/violet_hold/boss_moragg.cpp new file mode 100644 index 00000000000..6d283c7bfb4 --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/boss_moragg.cpp @@ -0,0 +1,133 @@ +/* Script Data Start +SDName: Boss moragg +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "violet_hold.h" + +//Spells +enum Spells +{ + SPELL_CORROSIVE_SALIVA = 54527, + SPELL_OPTIC_LINK = 54396 +}; + +struct boss_moraggAI : public ScriptedAI +{ + boss_moraggAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiOpticLinkTimer; + uint32 uiCorrosiveSalivaTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiOpticLinkTimer = 10000; + uiCorrosiveSalivaTimer = 5000; + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MORAGG_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiOpticLinkTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_OPTIC_LINK); + uiOpticLinkTimer = 15000; + } else uiOpticLinkTimer -= diff; + + if (uiCorrosiveSalivaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVE_SALIVA); + uiCorrosiveSalivaTimer = 10000; + } else uiCorrosiveSalivaTimer -= diff; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT,13); + } + } + } +}; + +CreatureAI* GetAI_boss_moragg(Creature* pCreature) +{ + return new boss_moraggAI (pCreature); +} + +void AddSC_boss_moragg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_moragg"; + newscript->GetAI = &GetAI_boss_moragg; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp b/src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp new file mode 100644 index 00000000000..2633705c1b7 --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp @@ -0,0 +1,307 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Boss xevozz +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_ARCANE_BARRAGE_VOLLEY = 54202, + SPELL_ARCANE_BARRAGE_VOLLEY_H = 59483, + SPELL_ARCANE_BUFFET = 54226, + SPELL_ARCANE_BUFFET_H = 59485, + SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102, + SPELL_SUMMON_ETHEREAL_SPHERE_2 = 54137, + SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138, +}; + +enum NPCs +{ + NPC_ETHEREAL_SPHERE = 29271, + //NPC_ETHEREAL_SPHERE2 = 32582, // heroic only? +}; + +enum CreatureSpells +{ + SPELL_ARCANE_POWER = 54160, + H_SPELL_ARCANE_POWER = 59474, + SPELL_SUMMON_PLAYERS = 54164, + SPELL_POWER_BALL_VISUAL = 54141, +}; + +enum Yells +{ + SAY_AGGRO = -1608027, + SAY_SLAY_1 = -1608028, + SAY_SLAY_2 = -1608029, + SAY_SLAY_3 = -1608030, + SAY_DEATH = -1608031, + SAY_SPAWN = -1608032, + SAY_CHARGED = -1608033, + SAY_REPEAT_SUMMON_1 = -1608034, + SAY_REPEAT_SUMMON_2 = -1608035, + SAY_SUMMON_ENERGY = -1608036 +}; + +struct boss_xevozzAI : public ScriptedAI +{ + boss_xevozzAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiSummonEtherealSphere_Timer; + uint32 uiArcaneBarrageVolley_Timer; + uint32 uiArcaneBuffet_Timer; + + void Reset() + { + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + + uiSummonEtherealSphere_Timer = urand(10000, 12000); + uiArcaneBarrageVolley_Timer = urand(20000, 22000); + uiArcaneBuffet_Timer = uiSummonEtherealSphere_Timer + urand(5000, 6000); + DespawnSphere(); + } + + void DespawnSphere() + { + std::list assistList; + GetCreatureListWithEntryInGrid(assistList,me, NPC_ETHEREAL_SPHERE ,150.0f); + + if (assistList.empty()) + return; + + for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + { + if (Creature* pSphere = *iter) + pSphere->Kill(pSphere, false); + } + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->SetSpeed(MOVE_RUN, 0.5f); + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + pSummoned->AddThreat(pTarget, 0.00f); + pSummoned->AI()->AttackStart(pTarget); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_XEVOZZ_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void MoveInLineOfSight(Unit* /*pWho*/) {} + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiArcaneBarrageVolley_Timer < uiDiff) + { + DoCast(me, SPELL_ARCANE_BARRAGE_VOLLEY); + uiArcaneBarrageVolley_Timer = urand(20000, 22000); + } + else uiArcaneBarrageVolley_Timer -= uiDiff; + + if (uiArcaneBuffet_Timer) + if (uiArcaneBuffet_Timer < uiDiff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BUFFET); + uiArcaneBuffet_Timer = 0; + } + else uiArcaneBuffet_Timer -= uiDiff; + + if (uiSummonEtherealSphere_Timer < uiDiff) + { + DoScriptText(SAY_SPAWN, me); + DoCast(me, SPELL_SUMMON_ETHEREAL_SPHERE_1); + if (IsHeroic()) // extra one for heroic + me->SummonCreature(NPC_ETHEREAL_SPHERE, me->GetPositionX()-5+rand()%10, me->GetPositionY()-5+rand()%10, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 40000); + + uiSummonEtherealSphere_Timer = urand(45000, 47000); + uiArcaneBuffet_Timer = urand(5000, 6000); + } + else uiSummonEtherealSphere_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + DespawnSphere(); + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } + void KilledUnit(Unit* pVictim) + { + if (pVictim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_xevozz(Creature* pCreature) +{ + return new boss_xevozzAI (pCreature); +} + +struct mob_ethereal_sphereAI : public ScriptedAI +{ + mob_ethereal_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiSummonPlayers_Timer; + uint32 uiRangeCheck_Timer; + + void Reset() + { + uiSummonPlayers_Timer = urand(33000, 35000); + uiRangeCheck_Timer = 1000; + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!me->HasAura(SPELL_POWER_BALL_VISUAL)) + DoCast(me, SPELL_POWER_BALL_VISUAL); + + if (uiRangeCheck_Timer < uiDiff) + { + if (pInstance) + { + if (Creature* pXevozz = Unit::GetCreature(*me, pInstance->GetData64(DATA_XEVOZZ))) + { + float fDistance = me->GetDistance2d(pXevozz); + if (fDistance <= 3) + DoCast(pXevozz, SPELL_ARCANE_POWER); + else + DoCast(me, 35845); //Is it blizzlike? + } + } + uiRangeCheck_Timer = 1000; + } + else uiRangeCheck_Timer -= uiDiff; + + if (uiSummonPlayers_Timer < uiDiff) + { + DoCast(me, SPELL_SUMMON_PLAYERS); // not working right + + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->isAlive()) + DoTeleportPlayer(i->getSource(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), i->getSource()->GetOrientation()); + } + + uiSummonPlayers_Timer = urand(33000, 35000); + } + else uiSummonPlayers_Timer -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_ethereal_sphere(Creature* pCreature) +{ + return new mob_ethereal_sphereAI (pCreature); +} + +void AddSC_boss_xevozz() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_xevozz"; + newscript->GetAI = &GetAI_boss_xevozz; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ethereal_sphere"; + newscript->GetAI = &GetAI_mob_ethereal_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp b/src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp new file mode 100644 index 00000000000..da75ed94fc2 --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp @@ -0,0 +1,178 @@ +/* Script Data Start +SDName: Boss zuramat +SD%Complete: +SDComment: The phasemask for the voids dosen't work. +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_SHROUD_OF_DARKNESS = 54524, + H_SPELL_SHROUD_OF_DARKNESS = 59745, + SPELL_SUMMON_VOID_SENTRY = 54369, + SPELL_VOID_SHIFT = 54361, + H_SPELL_VOID_SHIFT = 59743, + + SPELL_ZURAMAT_ADD_2 = 54342, + H_SPELL_ZURAMAT_ADD_2 = 59747 +}; + +enum ZuramatCreatures +{ + CREATURE_VOID_SENTRY = 29364 +}; + +enum Yells +{ + SAY_AGGRO = -1608037, + SAY_SLAY_1 = -1608038, + SAY_SLAY_2 = -1608039, + SAY_SLAY_3 = -1608040, + SAY_DEATH = -1608041, + SAY_SPAWN = -1608042, + SAY_SHIELD = -1608043, + SAY_WHISPER = -1608044 +}; + +struct boss_zuramatAI : public ScriptedAI +{ + boss_zuramatAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 SpellVoidShiftTimer; + uint32 SpellSummonVoidTimer; + uint32 SpellShroudOfDarknessTimer; + + void Reset() + { + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + + SpellShroudOfDarknessTimer = 22000; + SpellVoidShiftTimer = 15000; + SpellSummonVoidTimer = 12000; + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ZURAMAT_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (SpellSummonVoidTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SUMMON_VOID_SENTRY, false); + SpellSummonVoidTimer = 20000; + } else SpellSummonVoidTimer -=diff; + + if (SpellVoidShiftTimer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_VOID_SHIFT); + SpellVoidShiftTimer = 20000; + } else SpellVoidShiftTimer -=diff; + + if (SpellShroudOfDarknessTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHROUD_OF_DARKNESS); + SpellShroudOfDarknessTimer = 20000; + } else SpellShroudOfDarknessTimer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustSummoned(Creature* summon) + { + summon->AI()->AttackStart(me->getVictim()); + summon->AI()->DoCastAOE(SPELL_ZURAMAT_ADD_2); + summon->SetPhaseMask(17,true); + } +}; + +CreatureAI* GetAI_boss_zuramat(Creature* pCreature) +{ + return new boss_zuramatAI (pCreature); +} + +void AddSC_boss_zuramat() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_zuramat"; + newscript->GetAI = &GetAI_boss_zuramat; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp b/src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp new file mode 100644 index 00000000000..781511f940b --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp @@ -0,0 +1,528 @@ +#include "ScriptedPch.h" +#include "violet_hold.h" + +#define MAX_ENCOUNTER 3 + +/* Violet Hold encounters: +0 - First boss +1 - Second boss +2 - Cyanigosa*/ + +/* Violet hold bosses: +1 - Moragg +2 - Erekem +3 - Ichoron +4 - Lavanthor +5 - Xevozz +6 - Zuramat +7 - Cyanigosa */ + +enum GameObjects +{ + GO_MAIN_DOOR = 191723, + GO_XEVOZZ_DOOR = 191556, + GO_LAVANTHOR_DOOR = 191566, + GO_ICHORON_DOOR = 191722, + GO_ZURAMAT_DOOR = 191565, + GO_EREKEM_DOOR = 191564, + GO_EREKEM_GUARD_1_DOOR = 191563, + GO_EREKEM_GUARD_2_DOOR = 191562, + GO_MORAGG_DOOR = 191606, + GO_INTRO_ACTIVATION_CRYSTAL = 193615, + GO_ACTIVATION_CRYSTAL = 193611 +}; + +const Position PortalLocation[] = +{ + {1936.07, 803.198, 53.3749, 3.12414}, + {1877.51, 850.104, 44.6599, 4.7822 }, + {1890.64, 753.471, 48.7224, 1.71042}, + {1908.31, 809.657, 38.7037, 3.08701}, + {1918.37, 853.437, 47.1624, 4.12294}, + {1927.61, 758.436, 51.4533, 2.20891} +}; + +struct instance_violet_hold : public ScriptedInstance +{ + instance_violet_hold(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiMoragg; + uint64 uiErekem; + uint64 uiErekemGuard[2]; + uint64 uiIchoron; + uint64 uiLavanthor; + uint64 uiXevozz; + uint64 uiZuramat; + uint64 uiCyanigosa; + uint64 uiSinclari; + + uint64 uiMoraggCell; + uint64 uiErekemCell; + uint64 uiErekemLeftGuardCell; + uint64 uiErekemRightGuardCell; + uint64 uiIchoronCell; + uint64 uiLavanthorCell; + uint64 uiXevozzCell; + uint64 uiZuramatCell; + uint64 uiMainDoor; + + uint64 uiActivationCrystal[3]; + + uint32 uiActivationTimer; + + uint8 uiWaveCount; + uint8 uiLocation; + uint8 uiFirstBoss; + uint8 uiSecondBoss; + uint8 uiRemoveNpc; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + uint8 uiCountErekemGuards; + uint8 uiCountActivationCrystals; + + bool bActive; + bool bWiped; + + std::string str_data; + + void Initialize() + { + uiMoragg = 0; + uiErekem = 0; + uiIchoron = 0; + uiLavanthor = 0; + uiXevozz = 0; + uiZuramat = 0; + uiCyanigosa = 0; + uiSinclari = 0; + + uiMoraggCell = 0; + uiErekemCell = 0; + uiErekemGuard[0] = 0; + uiErekemGuard[1] = 0; + uiIchoronCell = 0; + uiLavanthorCell = 0; + uiXevozzCell = 0; + uiZuramatCell = 0; + uiMainDoor = 0; + uiRemoveNpc = 0; + + uiWaveCount = 0; + uiLocation = urand(0,5); + uiFirstBoss = 0; + uiSecondBoss = 0; + uiCountErekemGuards = 0; + uiCountActivationCrystals = 0; + + uiActivationTimer = 5000; + + bActive = false; + bWiped = false; + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + switch(pCreature->GetEntry()) + { + case CREATURE_XEVOZZ: + uiXevozz = pCreature->GetGUID(); + break; + case CREATURE_LAVANTHOR: + uiLavanthor = pCreature->GetGUID(); + break; + case CREATURE_ICHORON: + uiIchoron = pCreature->GetGUID(); + break; + case CREATURE_ZURAMAT: + uiZuramat = pCreature->GetGUID(); + break; + case CREATURE_EREKEM: + uiErekem = pCreature->GetGUID(); + break; + case CREATURE_EREKEM_GUARD: + if (uiCountErekemGuards < 2) + { + uiErekemGuard[uiCountErekemGuards++] = pCreature->GetGUID(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + } + break; + case CREATURE_MORAGG: + uiMoragg = pCreature->GetGUID(); + break; + case CREATURE_CYANIGOSA: + uiCyanigosa = pCreature->GetGUID(); + break; + case CREATURE_SINCLARI: + uiSinclari = pCreature->GetGUID(); + break; + } + + if (add && (pCreature->GetGUID() == uiFirstBoss || pCreature->GetGUID() == uiSecondBoss)) + { + pCreature->AllLootRemovedFromCorpse(); + pCreature->RemoveLootMode(1); + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_EREKEM_GUARD_1_DOOR: + uiErekemLeftGuardCell = pGo->GetGUID(); + break; + case GO_EREKEM_GUARD_2_DOOR: + uiErekemRightGuardCell = pGo->GetGUID(); + break; + case GO_EREKEM_DOOR: + uiErekemCell = pGo->GetGUID(); + break; + case GO_ZURAMAT_DOOR: + uiZuramatCell = pGo->GetGUID(); + break; + case GO_LAVANTHOR_DOOR: + uiLavanthorCell = pGo->GetGUID(); + break; + case GO_MORAGG_DOOR: + uiMoraggCell = pGo->GetGUID(); + break; + case GO_ICHORON_DOOR: + uiIchoronCell = pGo->GetGUID(); + break; + case GO_XEVOZZ_DOOR: + uiXevozzCell = pGo->GetGUID(); + break; + case GO_MAIN_DOOR: + uiMainDoor = pGo->GetGUID(); + break; + case GO_ACTIVATION_CRYSTAL: + if (uiCountActivationCrystals < 3) + uiActivationCrystal[uiCountActivationCrystals++] = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_1ST_BOSS_EVENT: + m_auiEncounter[0] = data; + if (data == DONE) + SaveToDB(); + break; + case DATA_2ND_BOSS_EVENT: + m_auiEncounter[1] = data; + if (data == DONE) + SaveToDB(); + break; + case DATA_CYANIGOSA_EVENT: + m_auiEncounter[2] = data; + if (data == DONE) + { + SaveToDB(); + if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) + pMainDoor->SetGoState(GO_STATE_ACTIVE); + } + break; + case DATA_WAVE_COUNT: + uiWaveCount = data; + bActive = true; + break; + case DATA_REMOVE_NPC: + uiRemoveNpc = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_1ST_BOSS_EVENT: return m_auiEncounter[0]; + case DATA_2ND_BOSS_EVENT: return m_auiEncounter[1]; + case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2]; + case DATA_WAVE_COUNT: return uiWaveCount; + case DATA_REMOVE_NPC: return uiRemoveNpc; + } + + return 0; + } + + void SpawnPortal() + { + if (Creature *pSinclari = instance->GetCreature(uiSinclari)) + if (Creature *pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL,PortalLocation[uiLocation],TEMPSUMMON_CORPSE_DESPAWN)) + uiLocation = (uiLocation+urand(1,5))%6; + } + + void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true) + { + Creature* pBoss = NULL; + + switch(uiBoss) + { + case BOSS_MORAGG: + HandleGameObject(uiMoraggCell,bForceRespawn); + pBoss = instance->GetCreature(uiMoragg); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + case BOSS_EREKEM: + HandleGameObject(uiErekemCell, bForceRespawn); + HandleGameObject(uiErekemRightGuardCell, bForceRespawn); + HandleGameObject(uiErekemLeftGuardCell, bForceRespawn); + + pBoss = instance->GetCreature(uiErekem); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + + if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0])) + { + if (bForceRespawn) + pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + else + pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + } + + if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1])) + { + if (bForceRespawn) + pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + else + pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + } + break; + case BOSS_ICHORON: + HandleGameObject(uiIchoronCell,bForceRespawn); + pBoss = instance->GetCreature(uiIchoron); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + case BOSS_LAVANTHOR: + HandleGameObject(uiLavanthorCell,bForceRespawn); + pBoss = instance->GetCreature(uiLavanthor); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + case BOSS_XEVOZZ: + HandleGameObject(uiXevozzCell,bForceRespawn); + pBoss = instance->GetCreature(uiXevozz); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + case BOSS_ZURAMAT: + HandleGameObject(uiZuramatCell,bForceRespawn); + pBoss = instance->GetCreature(uiZuramat); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + } + + if (!bForceRespawn && pBoss) + { + if (pBoss->isDead()) + { + // respawn but avoid to be looted again + pBoss->Respawn(); + pBoss->RemoveLootMode(1); + } + pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + SetData(DATA_WAVE_COUNT,0); + uiWaveCount = 0; + } + } + + void AddWave() + { + DoUpdateWorldState(WORLD_STATE_VH, 1); + DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, uiWaveCount); + DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); // TODO + + switch(uiWaveCount) + { + case 6: + if (uiFirstBoss == 0) + uiFirstBoss = urand(1,6); + StartBossEncounter(uiFirstBoss); + break; + case 12: + if (uiSecondBoss == 0) + do + { + uiSecondBoss = urand(1,6); + } while (uiSecondBoss == uiFirstBoss); + StartBossEncounter(uiSecondBoss); + break; + case 18: + { + Creature *pSinclari = instance->GetCreature(uiSinclari); + if (pSinclari) + pSinclari->SummonCreature(CREATURE_CYANIGOSA,PortalLocation[0],TEMPSUMMON_DEAD_DESPAWN); + break; + } + case 1: + { + if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) + pMainDoor->SetGoState(GO_STATE_READY); + } + default: + if (!bWiped) + SpawnPortal(); + bWiped = false; + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MORAGG: return uiMoragg; + case DATA_EREKEM: return uiErekem; + case DATA_EREKEM_GUARD_1: return uiErekemGuard[0]; + case DATA_EREKEM_GUARD_2: return uiErekemGuard[1]; + case DATA_ICHORON: return uiIchoron; + case DATA_LAVANTHOR: return uiLavanthor; + case DATA_XEVOZZ: return uiXevozz; + case DATA_ZURAMAT: return uiZuramat; + case DATA_CYANIGOSA: return uiCyanigosa; + case DATA_MORAGG_CELL: return uiMoraggCell; + case DATA_EREKEM_CELL: return uiErekemCell; + case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell; + case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell; + case DATA_ICHORON_CELL: return uiIchoronCell; + case DATA_LAVANTHOR_CELL: return uiLavanthorCell; + case DATA_XEVOZZ_CELL: return uiXevozzCell; + case DATA_ZURAMAT_CELL: return uiZuramatCell; + case DATA_MAIN_DOOR: return uiMainDoor; + case DATA_SINCLARI: return uiSinclari; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "V H " << (uint16)m_auiEncounter[0] + << " " << (uint16)m_auiEncounter[1] + << " " << (uint16)m_auiEncounter[2] + << " " << (uint16)uiFirstBoss + << " " << (uint16)uiSecondBoss; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; + + if (dataHead1 == 'V' && dataHead2 == 'H') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + uiFirstBoss = data3; + uiSecondBoss = data4; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + bool CheckWipe() + { + Map::PlayerList const &players = instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + return false; + } + + return true; + } + + void Update(uint32 diff) + { + if (!instance->HavePlayers()) + return; + + if (bActive) + { + if (uiActivationTimer < diff) + { + AddWave(); + bActive = false; + uiActivationTimer = 5000; + } else uiActivationTimer -= diff; + } + + if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) + if (pMainDoor->GetGoState() != GO_STATE_ACTIVE && CheckWipe()) + { + SetData(DATA_REMOVE_NPC, 1); + StartBossEncounter(uiFirstBoss, false); + StartBossEncounter(uiSecondBoss, false); + bWiped = true; + if (Creature* pSinclari = instance->GetCreature(uiSinclari)) + { + pSinclari->DisappearAndDie(); + pSinclari->Respawn(true); + } + + if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) + pMainDoor->SetGoState(GO_STATE_ACTIVE); + SetData(DATA_WAVE_COUNT, 0); + } + } +}; + +InstanceData* GetInstanceData_instance_violet_hold(Map* pMap) +{ + return new instance_violet_hold(pMap); +} + +void AddSC_instance_violet_hold() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_violet_hold"; + newscript->GetInstanceData = &GetInstanceData_instance_violet_hold; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/violet_hold.cpp b/src/server/scripts/Northrend/violet_hold/violet_hold.cpp new file mode 100644 index 00000000000..49883b5dbf3 --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/violet_hold.cpp @@ -0,0 +1,274 @@ +#include "ScriptedPch.h" +#include "violet_hold.h" + +#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay." +#define GOSSIP_ITEM_1 "Activate the crystals when we get in trouble, right" +#define SPAWN_TIME 20000 + +enum PortalCreatures +{ + CREATURE_AZURE_INVADER = 30661, + CREATURE_AZURE_SPELLBREAKER = 30662, + CREATURE_AZURE_BINDER = 30663, + CREATURE_AZURE_MAGE_SLAYER = 30664, + CREATURE_AZURE_CAPTAIN = 30666, + CREATURE_AZURE_SORCEROR = 30667, + CREATURE_AZURE_RAIDER = 30668, + CREATURE_AZURE_STALKER = 32191 +}; + +enum Spells +{ + SPELL_PORTAL_CHANNEL = 58012 +}; + +enum eSinclari +{ + NPC_VIOLET_HOLD_GUARD = 30659, + + SAY_SINCLARI_1 = -1608045, +}; + +const Position DoorPosition = { 1828.300049, 797.309021, 46.135502, 1.48353}; +const Position MovePosition = { 1806.955566, 803.851807, 44.363323}; + +struct npc_sinclariAI : public ScriptedAI +{ + npc_sinclariAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiTimer; + + void Reset() + { + uiPhase = 0; + uiTimer = 0; + + me->SetVisibility(VISIBILITY_ON); + me->SetReactState(REACT_AGGRESSIVE); + + std::list GuardList; + me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); + if (!GuardList.empty()) + { + for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + { + if (Creature* pGuard = *itr) + { + pGuard->DisappearAndDie(); + pGuard->Respawn(); + pGuard->SetVisibility(VISIBILITY_ON); + pGuard->SetReactState(REACT_AGGRESSIVE); + } + } + } + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (pInstance) + { + pInstance->SetData(DATA_WAVE_COUNT,1); + pInstance->SetData(DATA_REMOVE_NPC,0); // might not have been reset after a wipe on a boss. + } + + //She should not be despawned, she will be used by the instance to summon some npcs + me->SetVisibility(VISIBILITY_OFF); + me->SetReactState(REACT_PASSIVE); + } + + void UpdateAI(const uint32 uiDiff) + { + ScriptedAI::UpdateAI(uiDiff); + + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + DoScriptText(SAY_SINCLARI_1, me); + uiTimer = 4000; + uiPhase = 2; + break; + case 2: + { + std::list GuardList; + me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); + if (!GuardList.empty()) + for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + { + if (Creature* pGuard = *itr) + { + pGuard->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pGuard->GetMotionMaster()->MovePoint(0, MovePosition); + } + } + uiTimer = 6000; + uiPhase = 3; + break; + } + case 3: + { + std::list GuardList; + me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); + if (!GuardList.empty()) + for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + { + if (Creature* pGuard = *itr) + { + pGuard->SetVisibility(VISIBILITY_OFF); + pGuard->SetReactState(REACT_PASSIVE); + } + } + uiTimer = 2000; + uiPhase = 4; + break; + } + case 4: + me->GetMotionMaster()->MovePoint(0, MovePosition); + uiTimer = 0; + uiPhase = 0; + break; + } + } + else uiTimer -= uiDiff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_sinclari(Creature* pCreature) +{ + return new npc_sinclariAI(pCreature); +} + +bool GossipHello_npc_sinclari(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance && pInstance->GetData(DATA_CYANIGOSA_EVENT) != DONE && pInstance->GetData(DATA_WAVE_COUNT) == 0 && pPlayer) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_1,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_START_EVENT,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(13853, pCreature->GetGUID()); + }else + pPlayer->SEND_GOSSIP_MENU(13910, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_sinclari(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + if (pPlayer) + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_sinclariAI, (pCreature->AI()))->uiPhase = 1; + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->SEND_GOSSIP_MENU(13854, pCreature->GetGUID()); + break; + } + return true; +} + +struct npc_teleportation_portalAI : public ScriptedAI +{ + npc_teleportation_portalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiSpawnTimer; + bool bPortalGuardianOrKeeperSpawn; + + ScriptedInstance *pInstance; + + void Reset() + { + uiSpawnTimer = 10000; + bPortalGuardianOrKeeperSpawn = false; + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (pInstance && pInstance->GetData(DATA_REMOVE_NPC) == 1) + { + me->ForcedDespawn(); + pInstance->SetData(DATA_REMOVE_NPC, 0); + } + + if (uiSpawnTimer <= diff) + { + if (bPortalGuardianOrKeeperSpawn) + { + uint8 k = pInstance->GetData(DATA_WAVE_COUNT) < 12 ? 2 : 3; + for (uint8 i = 0; i < k; ++i) + { + uint32 entry = RAND(CREATURE_AZURE_CAPTAIN,CREATURE_AZURE_RAIDER,CREATURE_AZURE_STALKER,CREATURE_AZURE_SORCEROR); + if (Creature* pSummon = DoSummon(entry, me, 2.0f, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) + pSummon->GetMotionMaster()->MovePoint(0, DoorPosition); + } + } + else + { + bPortalGuardianOrKeeperSpawn = true; + uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER); + if (Creature *pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) + me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false); + } + uiSpawnTimer = SPAWN_TIME; + } else uiSpawnTimer -= diff; + + if (bPortalGuardianOrKeeperSpawn && !me->IsNonMeleeSpellCasted(false)) + { + me->Kill(me, false); + me->RemoveCorpse(); + return; + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_WAVE_COUNT,pInstance->GetData(DATA_WAVE_COUNT)+1); + } +}; + +CreatureAI* GetAI_npc_teleportation_portal(Creature *pCreature) +{ + return new npc_teleportation_portalAI(pCreature); +} + +void AddSC_violet_hold() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sinclari_vh"; + newscript->GetAI = &GetAI_npc_sinclari; + newscript->pGossipHello = &GossipHello_npc_sinclari; + newscript->pGossipSelect = &GossipSelect_npc_sinclari; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_teleportation_portal_vh"; + newscript->GetAI = &GetAI_npc_teleportation_portal; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/violet_hold/violet_hold.h b/src/server/scripts/Northrend/violet_hold/violet_hold.h new file mode 100644 index 00000000000..4476d5e823a --- /dev/null +++ b/src/server/scripts/Northrend/violet_hold/violet_hold.h @@ -0,0 +1,71 @@ +#ifndef DEF_VIOLET_HOLD_H +#define DEF_VIOLET_HOLD_H + +enum Creatures +{ + CREATURE_TELEPORTATION_PORTAL = 31011, + CREATURE_PORTAL_GUARDIAN = 30660, + CREATURE_PORTAL_KEEPER = 30695, + CREATURE_XEVOZZ = 29266, + CREATURE_LAVANTHOR = 29312, + CREATURE_ICHORON = 29313, + CREATURE_ZURAMAT = 29314, + CREATURE_EREKEM = 29315, + CREATURE_EREKEM_GUARD = 29395, + CREATURE_MORAGG = 29316, + CREATURE_CYANIGOSA = 31134, + CREATURE_SINCLARI = 30658 +}; + +enum Data +{ + DATA_1ST_BOSS_EVENT, + DATA_2ND_BOSS_EVENT, + DATA_CYANIGOSA_EVENT, + DATA_WAVE_COUNT, + DATA_REMOVE_NPC +}; + +enum Data64 +{ + DATA_MORAGG, + DATA_EREKEM, + DATA_EREKEM_GUARD_1, + DATA_EREKEM_GUARD_2, + DATA_ICHORON, + DATA_LAVANTHOR, + DATA_XEVOZZ, + DATA_ZURAMAT, + DATA_CYANIGOSA, + DATA_MORAGG_CELL, + DATA_EREKEM_CELL, + DATA_EREKEM_LEFT_GUARD_CELL, + DATA_EREKEM_RIGHT_GUARD_CELL, + DATA_ICHORON_CELL, + DATA_LAVANTHOR_CELL, + DATA_XEVOZZ_CELL, + DATA_ZURAMAT_CELL, + DATA_MAIN_DOOR, + DATA_SINCLARI +}; + +enum Bosses +{ + BOSS_NONE, // 0 used as marker for not yet randomized + BOSS_MORAGG, + BOSS_EREKEM, + BOSS_ICHORON, + BOSS_LAVANTHOR, + BOSS_XEVOZZ, + BOSS_ZURAMAT, + BOSS_CYANIGOSA +}; + +enum VHWorldStates +{ + WORLD_STATE_VH = 3816, + WORLD_STATE_VH_PRISON_STATE = 3815, + WORLD_STATE_VH_WAVE_COUNT = 3810, +}; + +#endif diff --git a/src/server/scripts/Northrend/zuldrak.cpp b/src/server/scripts/Northrend/zuldrak.cpp new file mode 100644 index 00000000000..a821ea4ffae --- /dev/null +++ b/src/server/scripts/Northrend/zuldrak.cpp @@ -0,0 +1,1403 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*#### +## npc_drakuru_shackles +####*/ + +enum eDrakuruShackles +{ + SPELL_LEFT_CHAIN = 59951, + SPELL_RIGHT_CHAIN = 59952, + SPELL_UNLOCK_SHACKLE = 55083, + SPELL_FREE_RAGECLAW = 55223, + + NPC_RAGECLAW = 29686 +}; + +struct npc_drakuru_shacklesAI : public ScriptedAI +{ + npc_drakuru_shacklesAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint64 RageclawGUID; + + void Reset() + { + RageclawGUID = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + float x, y, z; + me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 0.1f); + + if (Unit* summon = me->SummonCreature(NPC_RAGECLAW, x, y, z, + 0, TEMPSUMMON_DEAD_DESPAWN, 1000)) + { + RageclawGUID = summon->GetGUID(); + LockRageclaw(); + } + } + + void LockRageclaw() + { + Unit *Rageclaw = Unit::GetCreature(*me, RageclawGUID); + // pointer check not needed + me->SetInFront(Rageclaw); + Rageclaw->SetInFront(me); + + DoCast(Rageclaw, SPELL_LEFT_CHAIN, true); + DoCast(Rageclaw, SPELL_RIGHT_CHAIN, true); + } + + void UnlockRageclaw(Unit* pWho) + { + if (!pWho) + return; + + Creature *Rageclaw = Unit::GetCreature(*me, RageclawGUID); + // pointer check not needed + DoCast(Rageclaw, SPELL_FREE_RAGECLAW, true); + + me->setDeathState(DEAD); + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_UNLOCK_SHACKLE) + { + if (Creature *Rageclaw = Unit::GetCreature(*me, RageclawGUID)) + UnlockRageclaw(pCaster); + else + me->setDeathState(JUST_DIED); + } + } +}; + + +CreatureAI* GetAI_npc_drakuru_shackles(Creature* pCreature) +{ + return new npc_drakuru_shacklesAI (pCreature); +} + +/*#### +## npc_captured_rageclaw +####*/ + +enum eRageclaw +{ + SPELL_UNSHACKLED = 55085, + SPELL_KNEEL = 39656 +}; + +const char * SAY_RAGECLAW_1 = "I poop on you, trollses!"; +const char * SAY_RAGECLAW_2 = "ARRRROOOOGGGGAAAA!"; +const char * SAY_RAGECLAW_3 = "No more mister nice wolvar!"; + +#define SAY_RAGECLAW RAND(SAY_RAGECLAW_1,SAY_RAGECLAW_2,SAY_RAGECLAW_3) + +struct npc_captured_rageclawAI : public ScriptedAI +{ + npc_captured_rageclawAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 DespawnTimer; + bool Despawn; + + void Reset() + { + Despawn = false; + DespawnTimer = 0; + me->setFaction(35); + DoCast(me, SPELL_KNEEL, true); // Little Hack for kneel - Thanks Illy :P + } + + void MoveInLineOfSight(Unit * /*who*/){} + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_FREE_RAGECLAW) + { + me->RemoveAurasDueToSpell(SPELL_LEFT_CHAIN); + + me->RemoveAurasDueToSpell(SPELL_RIGHT_CHAIN); + + me->RemoveAurasDueToSpell(SPELL_KNEEL); + + me->setFaction(me->GetCreatureInfo()->faction_H); + + DoCast(me, SPELL_UNSHACKLED, true); + me->MonsterSay(SAY_RAGECLAW, LANG_UNIVERSAL, NULL); + me->GetMotionMaster()->MoveRandom(10); + + DespawnTimer = 10000; + Despawn = true; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (UpdateVictim()) + { + DoMeleeAttackIfReady(); + return; + } + + if (!Despawn) + return; + + if (DespawnTimer <= uiDiff) + me->DisappearAndDie(); + else DespawnTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_captured_rageclaw(Creature* pCreature) +{ + return new npc_captured_rageclawAI (pCreature); +} + +/*#### +## npc_gymer +####*/ + +#define GOSSIP_ITEM_G "I'm ready, Gymer. Let's go!" + +enum eGymer +{ + QUEST_STORM_KING_VENGEANCE = 12919, + SPELL_GYMER = 55568 +}; + +bool GossipHello_npc_gymer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_STORM_KING_VENGEANCE) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_G, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(13640, pCreature->GetGUID()); + } + + return true; +} + +bool GossipSelect_npc_gymer(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_GYMER, true); + } + + return true; +} + +/*#### +## npc_gurgthock +####*/ + +enum eGurgthock +{ + QUEST_AMPHITHEATER_ANGUISH_TUSKARRMAGEDDON = 12935, + QUEST_AMPHITHEATER_ANGUISH_KORRAK_BLOODRAGER = 12936, + QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_2 = 12954, + QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_1 = 12932, + QUEST_AMPHITHEATER_ANGUISH_MAGNATAUR = 12933, + QUEST_AMPHITHEATER_ANGUISH_FROM_BEYOND = 12934, + + NPC_ORINOKO_TUSKBREAKER = 30020, + NPC_KORRAK_BLOODRAGER = 30023, + NPC_YGGDRAS = 30014, + NPC_STINKBEARD = 30017, + NPC_AZ_BARIN = 30026, // air + NPC_DUKE_SINGEN = 30019, // fire + NPC_ERATHIUS = 30025, // earth + NPC_GARGORAL = 30024, // water + NPC_FIEND_WATER = 30044, + NPC_FIEND_AIR = 30045, + NPC_FIEND_FIRE = 30042, + NPC_FIEND_EARTH = 30043, + + SAY_QUEST_ACCEPT_TUSKARRMAGEDON = -1571031, + SAY_QUEST_ACCEPT_KORRAK_1 = -1571033, + SAY_QUEST_ACCEPT_KORRAK_2 = -1571034, + SAY_QUEST_ACCEPT_MAGNATAUR = -1571035, + + EMOTE_YGGDRAS_SPAWN = -1571039, + SAY_STINKBEARD_SPAWN = -1571040, + SAY_GURGTHOCK_ELEMENTAL_SPAWN = -1571041, + + SPELL_CRASHING_WAVE = 55909, // water + SPELL_SHOCKWAVE = 55918, // earth + SPELL_BLAST_OF_AIR = 55912, // air + SPELL_MAGMA_WAVE = 55916, // fire + + SPELL_ORB_OF_WATER = 55888, // fiend of water spell + SPELL_ORB_OF_STORMS = 55882, // fiend of air spell + SPELL_BOULDER = 55886, // fiend of earth spell + SPELL_ORB_OF_FLAME = 55872, // fiend of fire spell +}; + +struct BossAndAdd +{ + uint32 uiBoss; + uint32 uiAdd; + uint32 uiSpell; + uint32 uiAddSpell; +}; + +static BossAndAdd Boss[]= +{ + {NPC_GARGORAL,NPC_FIEND_WATER,SPELL_CRASHING_WAVE,SPELL_ORB_OF_WATER}, + {NPC_AZ_BARIN,NPC_FIEND_AIR,SPELL_BLAST_OF_AIR,SPELL_ORB_OF_STORMS}, + {NPC_DUKE_SINGEN,NPC_FIEND_FIRE,SPELL_MAGMA_WAVE,SPELL_ORB_OF_FLAME}, + {NPC_ERATHIUS,NPC_FIEND_EARTH,SPELL_SHOCKWAVE,SPELL_BOULDER}, +}; + +const Position SpawnPosition[] = +{ + {5754.692, -2939.46, 286.276123, 5.156380}, // stinkbeard || orinoko || korrak + {5762.054199, -2954.385010, 273.826955, 5.108289}, //yggdras + {5776.855, -2989.77979, 272.96814, 5.194} // elementals +}; + +const Position AddSpawnPosition[] = +{ + {5722.487, -3010.75, 312.751648, 0.478}, // caster location + {5724.983, -2969.89551, 286.359619, 0.478}, + {5733.76025, -3000.34644, 286.359619, 0.478}, + {5739.8125, -2981.524, 290.7671, 0.478}, // caster location + {5742.101, -2950.75586, 286.2643, 5.21}, + {5743.305, -3011.29736, 290.7671, 0.478}, // caster location + {5744.417, -3025.528, 286.35965, 0.478}, + {5763.189, -3029.67529, 290.7671, 0.478}, + {5769.401, -2935.121, 286.335754, 5.21}, + {5793.061, -2934.593, 286.359619, 3.53}, + {5797.32129, -2955.26855, 290.7671, 3.53}, // caster location + {5813.94531, -2956.74683, 286.359619, 3.53}, + {5816.85547, -2974.476, 290.7671, 3.53}, // caster location + {5820.30859, -3002.83716, 290.7671, 3.53}, // caster location + {5828.50244, -2981.737, 286.359619, 3.53}, + {5828.899, -2960.15479, 312.751648, 3.53}, // caster location +}; + + +struct npc_gurgthockAI : public ScriptedAI +{ + npc_gurgthockAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint64 SummonGUID; + uint64 uiPlayerGUID; + + uint32 uiTimer; + uint32 uiPhase; + uint32 uiRemoveFlagTimer; + uint32 uiQuest; + uint8 uiBossRandom; + + bool bRemoveFlag; + + void Reset() + { + SummonGUID = 0; + uiPlayerGUID = 0; + + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + uiTimer = 0; + uiPhase = 0; + uiQuest = 0; + uiRemoveFlagTimer = 5000; + + uiBossRandom = 0; + + bRemoveFlag = false; + } + + void SetGUID(const uint64 &guid, int32 id) + { + uiPlayerGUID = guid; + } + + void SetData(uint32 uiId, uint32 uiValue) + { + bRemoveFlag = true; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + + switch(uiId) + { + case 1: + switch(uiValue) + { + case QUEST_AMPHITHEATER_ANGUISH_TUSKARRMAGEDDON: + DoScriptText(SAY_QUEST_ACCEPT_TUSKARRMAGEDON, me); + uiPhase = 1; + uiTimer = 4000; + break; + case QUEST_AMPHITHEATER_ANGUISH_KORRAK_BLOODRAGER: + DoScriptText(SAY_QUEST_ACCEPT_KORRAK_1, me); + uiPhase = 3; + uiTimer = 3000; + break; + case QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_2: + case QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_1: + uiPhase = 6; + uiTimer = 3000; + break; + case QUEST_AMPHITHEATER_ANGUISH_MAGNATAUR: + uiTimer = 5000; + uiPhase = 7; + break; + case QUEST_AMPHITHEATER_ANGUISH_FROM_BEYOND: + uiTimer = 2000; + uiPhase = 12; + break; + } + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + ScriptedAI::UpdateAI(uiDiff); + + if (bRemoveFlag) + if (uiRemoveFlagTimer <= uiDiff) + { + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + bRemoveFlag = false; + + uiRemoveFlagTimer = 10000; + } else uiRemoveFlagTimer -= uiDiff; + + if (uiPhase) + { + Player* pPlayer = me->GetPlayer(uiPlayerGUID); + + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + if (Creature* pSummon = me->SummonCreature(NPC_ORINOKO_TUSKBREAKER, SpawnPosition[0], TEMPSUMMON_CORPSE_DESPAWN, 1000)) + SummonGUID = pSummon->GetGUID(); + uiPhase = 2; + uiTimer = 4000; + break; + case 2: + if (Creature* pSummon = Unit::GetCreature(*me, SummonGUID)) + pSummon->GetMotionMaster()->MoveJump(5776.319824, -2981.005371, 273.100037, 10.0f, 20.0f); + uiPhase = 0; + SummonGUID = 0; + break; + case 3: + DoScriptText(SAY_QUEST_ACCEPT_KORRAK_2, me); + uiTimer = 3000; + uiPhase = 4; + break; + case 4: + if (Creature* pSummon = me->SummonCreature(NPC_KORRAK_BLOODRAGER, SpawnPosition[0], TEMPSUMMON_CORPSE_DESPAWN, 1000)) + SummonGUID = pSummon->GetGUID(); + uiTimer = 3000; + uiPhase = 0; + break; + case 6: + { + if (!pPlayer) + return; + + std::string sText = ("The grand Amphitheater of Anguish awaits, " + std::string(pPlayer->GetName()) + ". Remember, once a battle starts you have to stay in the area. WIN OR DIE!"); + + me->MonsterSay(sText.c_str(),LANG_UNIVERSAL,0); + uiTimer = 5000; + uiPhase = 9; + } + break; + case 7: + { + if (!pPlayer) + return; + + std::string sText = ("Prepare to make you stand, " + std::string(pPlayer->GetName()) + "! Get in the Amphitheater and stand ready! Remember, you and your opponent must stay in the arena at all times or you will be disqualified!"); + me->MonsterSay(sText.c_str(),LANG_UNIVERSAL,0); + uiTimer = 3000; + uiPhase = 8; + } + break; + case 8: + DoScriptText(SAY_QUEST_ACCEPT_MAGNATAUR, me); + uiTimer = 5000; + uiPhase = 11; + break; + case 9: + { + if (!pPlayer) + return; + + std::string sText = ("Here we are once again, ladies and gentlemen. The epic struggle between life and death in the Amphitheater of Anguish! For this round we have " + std::string(pPlayer->GetName()) + " versus the hulking jormungar, Yg... Yggd? Yggdoze? Who comes up with these names?! " + std::string(pPlayer->GetName()) + " versus big worm!"); + me->MonsterYell(sText.c_str(),LANG_UNIVERSAL,0); + uiTimer = 10000; + uiPhase = 10; + } + break; + case 10: + me->SummonCreature(NPC_YGGDRAS, SpawnPosition[1], TEMPSUMMON_CORPSE_DESPAWN, 1000); + DoScriptText(EMOTE_YGGDRAS_SPAWN,me); + uiPhase = 0; + break; + case 11: + if (Creature* pCreature = me->SummonCreature(NPC_STINKBEARD, SpawnPosition[0], TEMPSUMMON_CORPSE_DESPAWN, 1000)) + DoScriptText(SAY_STINKBEARD_SPAWN,pCreature); + uiPhase = 0; + break; + case 12: + { + if (!pPlayer) + return; + + std::string sText = ("Prepare to make you stand, " + std::string(pPlayer->GetName()) + "! Get in the Amphitheater and stand ready! Remember, you and your opponent must stay in the arena at all times or you will be disqualified!"); + me->MonsterSay(sText.c_str(),LANG_UNIVERSAL,0); + uiTimer = 5000; + uiPhase = 13; + } + break; + case 13: + DoScriptText(SAY_GURGTHOCK_ELEMENTAL_SPAWN,me); + uiTimer = 3000; + uiPhase = 14; + break; + case 14: + uiBossRandom = urand(0,3); + if (Creature* pCreature = me->SummonCreature(Boss[uiBossRandom].uiBoss,SpawnPosition[2],TEMPSUMMON_CORPSE_DESPAWN, 1000)) + pCreature->AI()->SetData(1,uiBossRandom); + uiPhase = 0; + break; + } + }else uiTimer -= uiDiff; + } + } +}; + +bool QuestAccept_npc_gurgthock(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + switch (pQuest->GetQuestId()) + { + case QUEST_AMPHITHEATER_ANGUISH_TUSKARRMAGEDDON: + pCreature->AI()->SetData(1, pQuest->GetQuestId()); + break; + case QUEST_AMPHITHEATER_ANGUISH_KORRAK_BLOODRAGER: + pCreature->AI()->SetData(1, pQuest->GetQuestId()); + break; + case QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_2: + case QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_1: + pCreature->AI()->SetData(1, pQuest->GetQuestId()); + break; + case QUEST_AMPHITHEATER_ANGUISH_MAGNATAUR: + pCreature->AI()->SetData(1, pQuest->GetQuestId()); + break; + case QUEST_AMPHITHEATER_ANGUISH_FROM_BEYOND: + pCreature->AI()->SetData(1, pQuest->GetQuestId()); + break; + } + + pCreature->AI()->SetGUID(pPlayer->GetGUID()); + + return false; +} + +CreatureAI* GetAI_npc_gurgthock(Creature* pCreature) +{ + return new npc_gurgthockAI(pCreature); +} + +/*#### +## npc_orinoko_tuskbreaker +####*/ + +enum eOrinokoTuskbreaker +{ + SPELL_BATTLE_SHOUT = 32064, + SPELL_FISHY_SCENT = 55937, + SPELL_IMPALE = 55929, + SPELL_SUMMON_WHISKER = 55946, + + NPC_WHISKER = 30113, + NPC_HUNGRY_PENGUIN = 30110, + + SAY_CALL_FOR_HELP = -1571032 +}; + +struct npc_orinoko_tuskbreakerAI : public ScriptedAI +{ + npc_orinoko_tuskbreakerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + } + + bool bSummoned; + bool bBattleShout; + bool bFishyScent; + + uint32 uiBattleShoutTimer; + uint32 uiFishyScentTimer; + + uint64 AffectedGUID; + uint64 uiWhisker; + + void Reset() + { + bSummoned = false; + bBattleShout = false; + bFishyScent = false; + uiBattleShoutTimer = 0; + uiFishyScentTimer = 20000; + uiWhisker = 0; + AffectedGUID = 0; + } + + void EnterEvadeMode() + { + if (Creature *pWhisker = me->GetCreature(*me, uiWhisker)) + pWhisker->RemoveFromWorld(); + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if (uiType != POINT_MOTION_TYPE) + return; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + me->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + uiBattleShoutTimer = 7000; + } + + void EnterCombat(Unit* pWho) + { + DoCast(pWho, SPELL_IMPALE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (!bBattleShout && uiBattleShoutTimer <= uiDiff) + { + DoCast(me, SPELL_BATTLE_SHOUT); + bBattleShout = true; + } else uiBattleShoutTimer -= uiDiff; + + if (uiFishyScentTimer <= uiDiff) + { + if (Unit *pAffected = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pAffected, SPELL_FISHY_SCENT); + AffectedGUID = pAffected->GetGUID(); + } + uiFishyScentTimer = 20000; + } else uiFishyScentTimer -= uiDiff; + + if (!bSummoned && me->GetHealth()*100 / me->GetMaxHealth() <= 50) + { + DoScriptText(SAY_CALL_FOR_HELP ,me); + //DoCast(me->getVictim(), SPELL_SUMMON_WHISKER); petai is not working correctly??? + + if (Creature *pWhisker = me->SummonCreature(NPC_WHISKER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) + uiWhisker = pWhisker->GetGUID(); + bSummoned = true; + } + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* pSummon) + { + switch(pSummon->GetEntry()) + { + case NPC_WHISKER: + pSummon->AI()->AttackStart(me->getVictim()); + break; + case NPC_HUNGRY_PENGUIN: + if (Unit *pAffected = Unit::GetUnit(*me, AffectedGUID)) + { + if (pAffected->isAlive()) + pSummon->AI()->AttackStart(pAffected); + } + break; + } + } + + void JustDied(Unit* pKiller) + { + if (uiWhisker) + if (Creature *pWhisker = me->GetCreature(*me, uiWhisker)) + pWhisker->RemoveFromWorld(); + + if (pKiller->GetTypeId() == TYPEID_PLAYER) + pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_TUSKARRMAGEDDON, pKiller); + + } +}; + +CreatureAI* GetAI_npc_orinoko_tuskbreaker(Creature* pCreature) +{ + return new npc_orinoko_tuskbreakerAI(pCreature); +} + +/*#### +## npc_korrak_bloodrager +####*/ + +enum eKorrakBloodrager +{ + SPELL_GROW = 55948, + SPELL_CHARGE = 24193, + SPELL_UPPERCUT = 30471, + SPELL_ENRAGE = 42745 +}; + +struct npc_korrak_bloodragerAI : public npc_escortAI +{ + npc_korrak_bloodragerAI(Creature* pCreature) : npc_escortAI(pCreature) + { + Start(true,true, 0, NULL); + SetDespawnAtEnd(false); + } + + uint32 uiChargeTimer; + uint32 uiUppercutTimer; + + bool bEnrage; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + uiChargeTimer = 15000; + uiUppercutTimer = 12000; + bEnrage = false; + } + + void WaypointReached(uint32 uiI) + { + switch(uiI) + { + case 6: + me->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(), 0); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + break; + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoCast(me, SPELL_GROW); + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + if (uiUppercutTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_NEAREST, 0)) + DoCast(pTarget, SPELL_UPPERCUT); + uiUppercutTimer = 12000; + } else uiUppercutTimer -= uiDiff; + + if (uiChargeTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_FARTHEST, 0)) + DoCast(pTarget, SPELL_CHARGE); + uiChargeTimer = 15000; + } else uiChargeTimer -= uiDiff; + + if (!bEnrage && me->GetHealth()*100 / me->GetMaxHealth() <= 20) + { + DoCast(me, SPELL_ENRAGE); + bEnrage = true; + } + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* pKiller) + { + if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()) + pPlayer->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_KORRAK_BLOODRAGER, pKiller); + } +}; + +CreatureAI* GetAI_npc_korrak_bloodrager(Creature* pCreature) +{ + return new npc_korrak_bloodragerAI(pCreature); +} + +/*#### +## npc_yggdras +####*/ + +enum eYggdras +{ + SPELL_CLEAVE = 40504, + SPELL_CORRODE_FLESH = 57076, + SPELL_JORMUNGAR_SPAWN = 55859 +}; + +struct npc_yggdrasAI : public ScriptedAI +{ + npc_yggdrasAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiCleaveTimer; + uint32 uiCorrodeFleshTimer; + + void Reset() + { + uiCleaveTimer = 9000; + uiCorrodeFleshTimer = 6000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (me->getVictim()->GetPositionZ() >= 286.276) + { + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + if (pUnit->GetPositionZ() <= 286.276) + { + me->getThreatManager().resetAllAggro(); + me->AddThreat(pUnit,5.0f); + break; + } + EnterEvadeMode(); + } + } + } + + if (uiCleaveTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + uiCleaveTimer = 9000; + } else uiCleaveTimer -= uiDiff; + + if (uiCorrodeFleshTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CORRODE_FLESH); + uiCorrodeFleshTimer = 6000; + } else uiCorrodeFleshTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* pKiller) + { + if (Unit* pSummoner = me->ToTempSummon()->GetSummoner()) + { + std::string sText = (std::string(pKiller->GetName()) + " has defeated Yg.. Yggg-really big worm!"); + pSummoner->MonsterYell(sText.c_str(),LANG_UNIVERSAL,0); + } + + + if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()) + { + pPlayer->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_1, pKiller); + pPlayer->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_2, pKiller); + } + + for (uint8 i = 0; i < 3; ++i) + DoCast(pKiller, SPELL_JORMUNGAR_SPAWN, true); + } +}; + +CreatureAI* GetAI_npc_yggdras(Creature* pCreature) +{ + return new npc_yggdrasAI(pCreature); +} + +enum eStinkbeard +{ + SPELL_ENRAGE_STINKBEARD = 50420, + SPELL_KNOCK_AWAY = 31389, + SPELL_STINKY_BEARD = 55867, + SPELL_THUNDERBLADE = 55866, + SPELL_THUNDERCLAP = 15588 +}; + +/*#### +## npc_stinkbeard +####*/ + +struct npc_stinkbeardAI : public npc_escortAI +{ + npc_stinkbeardAI(Creature* pCreature) : npc_escortAI(pCreature) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + Start(true,true, 0, NULL); + SetDespawnAtEnd(false); + } + + uint32 uiKnockAwayTimer; + uint32 uiStinkyBeardTimer; + + bool bEnrage; + bool bThunderClap; + + void Reset() + { + me->AddAura(SPELL_THUNDERBLADE,me); + uiKnockAwayTimer = 10000; + uiStinkyBeardTimer = 15000; + bEnrage = false; + bThunderClap = false; + } + + void WaypointReached(uint32 uiI) + { + switch(uiI) + { + case 7: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + if (Unit* victim = me->getVictim()) + { + if (victim->GetPositionZ() >= 286.276) + { + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + if (pUnit->GetPositionZ() <= 286.276) + { + me->getThreatManager().resetAllAggro(); + me->AddThreat(pUnit,5.0f); + break; + } + EnterEvadeMode(); + } + } + } + } + + if (bThunderClap && me->GetHealth()*100 / me->GetMaxHealth() <= 10) + { + DoCastAOE(SPELL_THUNDERCLAP); + bThunderClap = true; + } + + if (uiKnockAwayTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, SPELL_KNOCK_AWAY); + } + uiKnockAwayTimer = 10000; + } else uiKnockAwayTimer -= uiDiff; + + if (uiStinkyBeardTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, SPELL_STINKY_BEARD); + } + uiStinkyBeardTimer = 15000; + } else uiStinkyBeardTimer -= uiDiff; + + if (!bEnrage && me->GetHealth()*100 / me->GetMaxHealth() <= 20) + { + DoCast(me, SPELL_ENRAGE_STINKBEARD); + bEnrage = true; + } + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* pKiller) + { + if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()) + pPlayer->GetCharmerOrOwnerPlayerOrPlayerItself()->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_MAGNATAUR, pKiller); + + std::string sText = ("And with AUTHORITY, " + std::string(pKiller->GetName()) + " dominates the magnataur lord! Stinkbeard's clan is gonna miss him back home in the Dragonblight!"); + me->MonsterYell(sText.c_str(),LANG_UNIVERSAL,0); + } +}; + +CreatureAI* GetAI_npc_stinkbeard(Creature* pCreature) +{ + return new npc_stinkbeardAI(pCreature); +} + +/*#### +## npc_elemental_lord +####*/ + +struct npc_elemental_lordAI : public ScriptedAI +{ + npc_elemental_lordAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + std::list SummonList; + + uint32 uiElementalSpellTimer; + + uint8 uiBossRandom; + uint32 uiSpellEntry; + + bool bAddAttack; + + void Reset() + { + uiBossRandom = 0; + uiSpellEntry = 0; + uiElementalSpellTimer = urand(5000,8000); + + bAddAttack = false; + } + + void SetData(uint32 uiData, uint32 uiValue) + { + if (uiData == 1) + { + uiBossRandom = uiValue; + SummonAdds(); + } + } + + void SummonAdds() + { + if (!Boss[uiBossRandom].uiAdd) + return; + + SummonList.clear(); + + for (uint8 uiI = 0; uiI < 16 ; uiI++) + { + if (Creature* pSummon = me->SummonCreature(Boss[uiBossRandom].uiAdd,AddSpawnPosition[uiI])) + { + pSummon->AI()->SetData(1,uiBossRandom); + SummonList.push_back(pSummon->GetGUID()); + } + } + + } + + void EnterCombat(Unit* pUnit) + { + if (!SummonList.empty()) + for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + pTemp->m_CombatDistance = 100.0f; // ugly hack? we are not in a instance sorry. :( + pTemp->AI()->AttackStart(pUnit); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (me->getVictim()->GetPositionZ() >= 286.276) + { + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + if (pUnit->GetPositionZ() <= 286.276) + { + me->getThreatManager().resetAllAggro(); + me->AddThreat(pUnit,5.0f); + break; + } + EnterEvadeMode(); + } + } + } + + if (uiElementalSpellTimer <= uiDiff) + { + DoCastVictim(Boss[uiBossRandom].uiSpell); + + uiElementalSpellTimer = urand(5000,8000); + } else uiElementalSpellTimer -= uiDiff; + + if (!bAddAttack && me->GetHealth()*100 / me->GetMaxHealth() <= 20) + { + if (!SummonList.empty()) + for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + if (pTemp->GetPositionZ() >= 287.00f) + continue; + + if (pTemp->getVictim()) + pTemp->GetMotionMaster()->MoveChase(pTemp->getVictim()); + } + } + + bAddAttack = true; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* pKiller) + { + if (!SummonList.empty()) + for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + pTemp->ForcedDespawn(); + } + + if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()) + pPlayer->GetCharmerOrOwnerPlayerOrPlayerItself()->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_FROM_BEYOND, pKiller); + + std::string sText = (std::string(pKiller->GetName()) + " is victorious once more!"); + + if (Unit* pSummoner = me->ToTempSummon()->GetSummoner()) + pSummoner->MonsterYell(sText.c_str(),LANG_UNIVERSAL,0); + } +}; + +CreatureAI* GetAI_npc_elemental_lord(Creature* pCreature) +{ + return new npc_elemental_lordAI(pCreature); +} + +/*#### +## npc_fiend_elemental +####*/ + +struct npc_fiend_elementalAI : public ScriptedAI +{ + npc_fiend_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiMissleTimer; + uint32 uiSpell; + + void Reset() + { + if (me->GetPositionZ() >= 287.0f) + me->GetMotionMaster()->MoveIdle(); + + uiSpell = 0; + uiMissleTimer = urand(2000,7000); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + AttackStartNoMove(pWho); + } + + void SetData(uint32 uiData, uint32 uiValue) + { + if (uiData == 1) + uiSpell = Boss[uiValue].uiAddSpell; + + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (me->GetPositionZ() >= 287.0f) + if (uiMissleTimer <= uiDiff) + { + DoCast(me,uiSpell); // this spell is not supported ... YET! + uiMissleTimer = urand(2000,7000); + + } else uiMissleTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_fiend_elemental(Creature* pCreature) +{ + return new npc_fiend_elementalAI(pCreature); +} + +/*#### +## npc_released_offspring_harkoa +####*/ + +struct npc_released_offspring_harkoaAI : public ScriptedAI +{ + npc_released_offspring_harkoaAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + void Reset() + { + float x, y, z; + me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 25.0f); + me->GetMotionMaster()->MovePoint(0, x, y, z); + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + me->DisappearAndDie(); + } +}; + +CreatureAI* GetAI_npc_released_offspring_harkoa(Creature* pCreature) +{ + return new npc_released_offspring_harkoaAI(pCreature); +} + +/*###### +## npc_crusade_recruit +######*/ + +enum eCrusade_recruit +{ + SPELL_QUEST_CREDIT = 50633, + + QUEST_TROLL_PATROL_INTESTINAL_FORTITUDE = 12509, + + GOSSIP_CRUSADE_TEXT = 13069, + + SAY_RECRUIT_1 = -1571036, + SAY_RECRUIT_2 = -1571037, + SAY_RECRUIT_3 = -1571038 +}; + +#define GOSSIP_ITEM_1 "Get out there and make those Scourge wish they were never reborn!" + +struct npc_crusade_recruitAI : public ScriptedAI +{ + npc_crusade_recruitAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint8 m_uiPhase; //The current phase we are in + uint32 m_uiTimer; //Timer until phase transition + float m_heading; //Store creature heading + + void Reset() + { + m_uiTimer = 0; + m_uiPhase = 0; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_COWER); + m_heading = me->GetOrientation(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiPhase) + { + if (m_uiTimer <= uiDiff) + { + switch(m_uiPhase) + { + case 1: + // say random text + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + DoScriptText(RAND(SAY_RECRUIT_1,SAY_RECRUIT_2,SAY_RECRUIT_3), me); + m_uiTimer = 3000; + m_uiPhase = 2; + break; + case 2: + // walk forward + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->MovePoint(0,me->GetPositionX() + (cos(m_heading) * 10), me->GetPositionY() + (sin(m_heading) * 10), me->GetPositionZ()); + m_uiTimer = 5000; + m_uiPhase = 3; + break; + case 3: + // despawn + me->DisappearAndDie(); + m_uiTimer = 0; + m_uiPhase = 0; + break; + } + } + else + m_uiTimer -= uiDiff; + } + ScriptedAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_npc_crusade_recruit(Creature* pCreature) +{ + return new npc_crusade_recruitAI (pCreature); +} + +bool GossipHello_npc_crusade_recruit(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_TROLL_PATROL_INTESTINAL_FORTITUDE) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_CRUSADE_TEXT, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_crusade_recruit(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF +1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, SPELL_QUEST_CREDIT, true); + CAST_AI(npc_crusade_recruitAI, (pCreature->AI()))->m_uiPhase = 1; + pCreature->SetInFront(pPlayer); + pCreature->SendMovementFlagUpdate(); + } + + return true; +} + +/*###### +## Quest 12916: Our Only Hope! +## go_scourge_enclosure +######*/ + +enum eScourgeEnclosure +{ + QUEST_OUR_ONLY_HOPE = 12916, + NPC_GYMER_DUMMY = 29928 //from quest template +}; + +bool GOHello_go_scourge_enclosure(Player* pPlayer, GameObject* pGO) +{ + if (pPlayer->GetQuestStatus(QUEST_OUR_ONLY_HOPE) == QUEST_STATUS_INCOMPLETE) + { + Creature* pGymerDummy = pGO->FindNearestCreature(NPC_GYMER_DUMMY,20.0f); + if (pGymerDummy) + { + pGO->UseDoorOrButton(); + pPlayer->KilledMonsterCredit(pGymerDummy->GetEntry(),pGymerDummy->GetGUID()); + pGymerDummy->CastSpell(pGymerDummy, 55529, true); + pGymerDummy->DisappearAndDie(); + } + } + return true; +} + +void AddSC_zuldrak() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_drakuru_shackles"; + newscript->GetAI = &GetAI_npc_drakuru_shackles; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_captured_rageclaw"; + newscript->GetAI = &GetAI_npc_captured_rageclaw; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_gymer"; + newscript->pGossipHello = &GossipHello_npc_gymer; + newscript->pGossipSelect = &GossipSelect_npc_gymer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_gurgthock"; + newscript->GetAI = &GetAI_npc_gurgthock; + newscript->pQuestAccept = &QuestAccept_npc_gurgthock; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_orinoko_tuskbreaker"; + newscript->GetAI = &GetAI_npc_orinoko_tuskbreaker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_korrak_bloodrager"; + newscript->GetAI = &GetAI_npc_korrak_bloodrager; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_yggdras"; + newscript->GetAI = &GetAI_npc_yggdras; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_stinkbeard"; + newscript->GetAI = &GetAI_npc_stinkbeard; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_released_offspring_harkoa"; + newscript->GetAI = &GetAI_npc_released_offspring_harkoa; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_crusade_recruit"; + newscript->GetAI = &GetAI_npc_crusade_recruit; + newscript->pGossipHello = &GossipHello_npc_crusade_recruit; + newscript->pGossipSelect = &GossipSelect_npc_crusade_recruit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_elemental_lord"; + newscript->GetAI = &GetAI_npc_elemental_lord; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_fiend_elemental"; + newscript->GetAI = &GetAI_npc_fiend_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_scourge_enclosure"; + newscript->pGOHello = &GOHello_go_scourge_enclosure; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp b/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp new file mode 100644 index 00000000000..bfde95ffcb0 --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp @@ -0,0 +1,348 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Exarch_Maladaar +SD%Complete: 95 +SDComment: Most of event implemented, some adjustments to timers remain and possibly make some better code for switching his dark side in to better "images" of player. +SDCategory: Auchindoun, Auchenai Crypts +EndScriptData */ + +/* ContentData +mob_stolen_soul +boss_exarch_maladaar +mob_avatar_of_martyred +EndContentData */ + +#include "ScriptedPch.h" + +#define SPELL_MOONFIRE 37328 +#define SPELL_FIREBALL 37329 +#define SPELL_MIND_FLAY 37330 +#define SPELL_HEMORRHAGE 37331 +#define SPELL_FROSTSHOCK 37332 +#define SPELL_CURSE_OF_AGONY 37334 +#define SPELL_MORTAL_STRIKE 37335 +#define SPELL_FREEZING_TRAP 37368 +#define SPELL_HAMMER_OF_JUSTICE 37369 + +struct mob_stolen_soulAI : public ScriptedAI +{ + mob_stolen_soulAI(Creature *c) : ScriptedAI(c) {} + + uint8 myClass; + uint32 Class_Timer; + + void Reset() + { + Class_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { } + + void SetMyClass(uint8 myclass) + { + myClass = myclass; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Class_Timer <= diff) + { + switch (myClass) + { + case CLASS_WARRIOR: + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + Class_Timer = 6000; + break; + case CLASS_PALADIN: + DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); + Class_Timer = 6000; + break; + case CLASS_HUNTER: + DoCast(me->getVictim(), SPELL_FREEZING_TRAP); + Class_Timer = 20000; + break; + case CLASS_ROGUE: + DoCast(me->getVictim(), SPELL_HEMORRHAGE); + Class_Timer = 10000; + break; + case CLASS_PRIEST: + DoCast(me->getVictim(), SPELL_MIND_FLAY); + Class_Timer = 5000; + break; + case CLASS_SHAMAN: + DoCast(me->getVictim(), SPELL_FROSTSHOCK); + Class_Timer = 8000; + break; + case CLASS_MAGE: + DoCast(me->getVictim(), SPELL_FIREBALL); + Class_Timer = 5000; + break; + case CLASS_WARLOCK: + DoCast(me->getVictim(), SPELL_CURSE_OF_AGONY); + Class_Timer = 20000; + break; + case CLASS_DRUID: + DoCast(me->getVictim(), SPELL_MOONFIRE); + Class_Timer = 10000; + break; + } + } else Class_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_stolen_soul(Creature* pCreature) +{ + return new mob_stolen_soulAI (pCreature); +} + +#define SAY_INTRO -1558000 +#define SAY_SUMMON -1558001 + +#define SAY_AGGRO_1 -1558002 +#define SAY_AGGRO_2 -1558003 +#define SAY_AGGRO_3 -1558004 + +#define SAY_ROAR -1558005 +#define SAY_SOUL_CLEAVE -1558006 + +#define SAY_SLAY_1 -1558007 +#define SAY_SLAY_2 -1558008 + +#define SAY_DEATH -1558009 + +#define SPELL_RIBBON_OF_SOULS 32422 +#define SPELL_SOUL_SCREAM 32421 + +#define SPELL_STOLEN_SOUL 32346 +#define SPELL_STOLEN_SOUL_VISUAL 32395 + +#define SPELL_SUMMON_AVATAR 32424 + +#define ENTRY_STOLEN_SOUL 18441 + +struct boss_exarch_maladaarAI : public ScriptedAI +{ + boss_exarch_maladaarAI(Creature *c) : ScriptedAI(c) + { + HasTaunted = false; + } + + uint32 soulmodel; + uint64 soulholder; + uint8 soulclass; + + uint32 Fear_timer; + uint32 Ribbon_of_Souls_timer; + uint32 StolenSoul_Timer; + + bool HasTaunted; + bool Avatar_summoned; + + void Reset() + { + soulmodel = 0; + soulholder = 0; + soulclass = 0; + + Fear_timer = 15000 + rand()% 5000; + Ribbon_of_Souls_timer = 5000; + StolenSoul_Timer = 25000 + rand()% 10000; + + Avatar_summoned = false; + } + + void MoveInLineOfSight(Unit *who) + { + if (!HasTaunted && me->IsWithinDistInMap(who, 150.0)) + { + DoScriptText(SAY_INTRO, me); + HasTaunted = true; + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == ENTRY_STOLEN_SOUL) + { + //SPELL_STOLEN_SOUL_VISUAL has shapeshift effect, but not implemented feature in Trinity for this spell. + summoned->CastSpell(summoned,SPELL_STOLEN_SOUL_VISUAL,false); + summoned->SetDisplayId(soulmodel); + summoned->setFaction(me->getFaction()); + + if (Unit *pTarget = Unit::GetUnit(*me,soulholder)) + { + + CAST_AI(mob_stolen_soulAI, summoned->AI())->SetMyClass(soulclass); + summoned->AI()->AttackStart(pTarget); + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + //When Exarch Maladar is defeated D'ore appear. + me->SummonCreature(19412, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!Avatar_summoned && ((me->GetHealth()*100) / me->GetMaxHealth() < 25)) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(SAY_SUMMON, me); + + DoCast(me, SPELL_SUMMON_AVATAR); + Avatar_summoned = true; + StolenSoul_Timer = 15000 + rand()% 15000; + } + + if (StolenSoul_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + uint32 i = urand(1,2); + if (i == 1) + DoScriptText(SAY_ROAR, me); + else + DoScriptText(SAY_SOUL_CLEAVE, me); + + soulmodel = pTarget->GetDisplayId(); + soulholder = pTarget->GetGUID(); + soulclass = pTarget->getClass(); + + DoCast(pTarget, SPELL_STOLEN_SOUL); + me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); + + StolenSoul_Timer = 20000 + rand()% 10000; + } else StolenSoul_Timer = 1000; + } + } else StolenSoul_Timer -= diff; + + if (Ribbon_of_Souls_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_RIBBON_OF_SOULS); + + Ribbon_of_Souls_timer = 5000 + (rand()%20 * 1000); + } else Ribbon_of_Souls_timer -= diff; + + if (Fear_timer <= diff) + { + DoCast(me, SPELL_SOUL_SCREAM); + Fear_timer = 15000 + rand()% 15000; + } else Fear_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_exarch_maladaar(Creature* pCreature) +{ + return new boss_exarch_maladaarAI (pCreature); +} + +#define SPELL_AV_MORTAL_STRIKE 16856 +#define SPELL_AV_SUNDER_ARMOR 16145 + +struct mob_avatar_of_martyredAI : public ScriptedAI +{ + mob_avatar_of_martyredAI(Creature *c) : ScriptedAI(c) {} + + uint32 Mortal_Strike_timer; + + void Reset() + { + Mortal_Strike_timer = 10000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Mortal_Strike_timer <= diff) + { + DoCast(me->getVictim(), SPELL_AV_MORTAL_STRIKE); + Mortal_Strike_timer = 10000 + rand()%20 * 1000; + } else Mortal_Strike_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_avatar_of_martyred(Creature* pCreature) +{ + return new mob_avatar_of_martyredAI (pCreature); +} + +void AddSC_boss_exarch_maladaar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_exarch_maladaar"; + newscript->GetAI = &GetAI_boss_exarch_maladaar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_avatar_of_martyred"; + newscript->GetAI = &GetAI_mob_avatar_of_martyred; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stolen_soul"; + newscript->GetAI = &GetAI_mob_stolen_soul; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp new file mode 100644 index 00000000000..c13e2905171 --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp @@ -0,0 +1,211 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +Name: Boss_Shirrak_the_dead_watcher +%Complete: 80 +Comment: InhibitMagic should stack slower far from the boss, proper Visual for Focus Fire, heroic implemented +Category: Auchindoun, Auchenai Crypts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_INHIBITMAGIC 32264 +#define SPELL_ATTRACTMAGIC 32265 +#define N_SPELL_CARNIVOROUSBITE 36383 +#define H_SPELL_CARNIVOROUSBITE 39382 +#define SPELL_CARNIVOROUSBITE DUNGEON_MODE(N_SPELL_CARNIVOROUSBITE, H_SPELL_CARNIVOROUSBITE) + +#define ENTRY_FOCUS_FIRE 18374 + +#define N_SPELL_FIERY_BLAST 32302 +#define H_SPELL_FIERY_BLAST 38382 +#define SPELL_FIERY_BLAST DUNGEON_MODE(N_SPELL_FIERY_BLAST, H_SPELL_FIERY_BLAST) +#define SPELL_FOCUS_FIRE_VISUAL 42075 //need to find better visual + +#define EMOTE_FOCUSES_ON "focuses on " + +struct boss_shirrak_the_dead_watcherAI : public ScriptedAI +{ + boss_shirrak_the_dead_watcherAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Inhibitmagic_Timer; + uint32 Attractmagic_Timer; + uint32 Carnivorousbite_Timer; + uint32 FocusFire_Timer; + + uint64 FocusedTargetGUID; + + void Reset() + { + Inhibitmagic_Timer = 0; + Attractmagic_Timer = 28000; + Carnivorousbite_Timer = 10000; + FocusFire_Timer = 17000; + FocusedTargetGUID = 0; + } + + void EnterCombat(Unit * /*who*/) + { } + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == ENTRY_FOCUS_FIRE) + { + summoned->CastSpell(summoned,SPELL_FOCUS_FIRE_VISUAL,false); + summoned->setFaction(me->getFaction()); + summoned->SetLevel(me->getLevel()); + summoned->addUnitState(UNIT_STAT_ROOT); + + if (Unit *pFocusedTarget = Unit::GetUnit(*me, FocusedTargetGUID)) + summoned->AI()->AttackStart(pFocusedTarget); + } + } + + void UpdateAI(const uint32 diff) + { + //Inhibitmagic_Timer + if (Inhibitmagic_Timer <= diff) + { + float dist; + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* i_pl = i->getSource()) + if (i_pl->isAlive() && (dist = i_pl->IsWithinDist(me, 45))) + { + i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC); + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 35) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 25) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 15) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + } + Inhibitmagic_Timer = 3000+(rand()%1000); + } else Inhibitmagic_Timer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Attractmagic_Timer + if (Attractmagic_Timer <= diff) + { + DoCast(me, SPELL_ATTRACTMAGIC); + Attractmagic_Timer = 30000; + Carnivorousbite_Timer = 1500; + } else Attractmagic_Timer -= diff; + + //Carnivorousbite_Timer + if (Carnivorousbite_Timer <= diff) + { + DoCast(me, SPELL_CARNIVOROUSBITE); + Carnivorousbite_Timer = 10000; + } else Carnivorousbite_Timer -= diff; + + //FocusFire_Timer + if (FocusFire_Timer <= diff) + { + // Summon Focus Fire & Emote + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + { + FocusedTargetGUID = pTarget->GetGUID(); + me->SummonCreature(ENTRY_FOCUS_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,5500); + + // TODO: Find better way to handle emote + // Emote + std::string *emote = new std::string(EMOTE_FOCUSES_ON); + emote->append(pTarget->GetName()); + emote->append("!"); + const char* text = emote->c_str(); + me->MonsterTextEmote(text, 0, true); + delete emote; + } + FocusFire_Timer = 15000+(rand()%5000); + } else FocusFire_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shirrak_the_dead_watcher(Creature* pCreature) +{ + return new boss_shirrak_the_dead_watcherAI (pCreature); +} + +struct mob_focus_fireAI : public ScriptedAI +{ + mob_focus_fireAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 FieryBlast_Timer; + bool fiery1, fiery2; + + void Reset() + { + FieryBlast_Timer = 3000+(rand()%1000); + fiery1 = fiery2 = true; + } + + void EnterCombat(Unit * /*who*/) + { } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FieryBlast_Timer + if (fiery2 && FieryBlast_Timer <= diff) + { + DoCast(me, SPELL_FIERY_BLAST); + + if (fiery1) fiery1 = false; + else if (fiery2) fiery2 = false; + + FieryBlast_Timer = 1000; + } else FieryBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_focus_fire(Creature* pCreature) +{ + return new mob_focus_fireAI (pCreature); +} + +void AddSC_boss_shirrak_the_dead_watcher() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shirrak_the_dead_watcher"; + newscript->GetAI = &GetAI_boss_shirrak_the_dead_watcher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_focus_fire"; + newscript->GetAI = &GetAI_mob_focus_fire; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp b/src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp new file mode 100644 index 00000000000..5b15178c33e --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp @@ -0,0 +1,358 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_NexusPrince_Shaffar +SD%Complete: 80 +SDComment: Need more tuning of spell timers, it should not be as linear fight as current. Also should possibly find a better way to deal with his three initial beacons to make sure all aggro. +SDCategory: Auchindoun, Mana Tombs +EndScriptData */ + +/* ContentData +boss_nexusprince_shaffar +mob_ethereal_beacon +EndContentData */ + +#include "ScriptedPch.h" + +enum ePrince +{ + SAY_INTRO = -1557000, + SAY_AGGRO_1 = -1557001, + SAY_AGGRO_2 = -1557002, + SAY_AGGRO_3 = -1557003, + SAY_SLAY_1 = -1557004, + SAY_SLAY_2 = -1557005, + SAY_SUMMON = -1557006, + SAY_DEAD = -1557007, + + SPELL_BLINK = 34605, + SPELL_FROSTBOLT = 32364, + SPELL_FIREBALL = 32363, + SPELL_FROSTNOVA = 32365, + + SPELL_ETHEREAL_BEACON = 32371, // Summons NPC_BEACON + SPELL_ETHEREAL_BEACON_VISUAL = 32368, + + NPC_BEACON = 18431, + NPC_SHAFFAR = 18344, + + NR_INITIAL_BEACONS = 3 +}; + +struct boss_nexusprince_shaffarAI : public ScriptedAI +{ + boss_nexusprince_shaffarAI(Creature *c) : ScriptedAI(c), summons(me) { HasTaunted = false; } + + uint32 Blink_Timer; + uint32 Beacon_Timer; + uint32 FireBall_Timer; + uint32 Frostbolt_Timer; + uint32 FrostNova_Timer; + + SummonList summons; + + bool HasTaunted; + bool CanBlink; + + void Reset() + { + Blink_Timer = 1500; + Beacon_Timer = 10000; + FireBall_Timer = 8000; + Frostbolt_Timer = 4000; + FrostNova_Timer = 15000; + + CanBlink = false; + + float dist = 8.0f; + float posX, posY, posZ, angle; + me->GetHomePosition(posX, posY, posZ, angle); + + me->SummonCreature(NPC_BEACON, posX - dist, posY - dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + me->SummonCreature(NPC_BEACON, posX - dist, posY + dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + me->SummonCreature(NPC_BEACON, posX + dist, posY, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + } + + void EnterEvadeMode() + { + summons.DespawnAll(); + ScriptedAI::EnterEvadeMode(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!HasTaunted && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 100.0f)) + { + DoScriptText(SAY_INTRO, me); + HasTaunted = true; + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + DoZoneInCombat(); + summons.DoZoneInCombat(); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == NPC_BEACON) + { + summoned->CastSpell(summoned,SPELL_ETHEREAL_BEACON_VISUAL,false); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(pTarget); + } + + summons.Summon(summoned); + } + + void SummonedCreatureDespawn(Creature *summon) + { + summons.Despawn(summon); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEAD, me); + summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (FrostNova_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoCast(me, SPELL_FROSTNOVA); + FrostNova_Timer = 17500 + rand()%7500; + CanBlink = true; + } else FrostNova_Timer -= diff; + + if (Frostbolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 4500 + rand()%1500; + } else Frostbolt_Timer -= diff; + + if (FireBall_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL); + FireBall_Timer = 4500 + rand()%1500; + } else FireBall_Timer -= diff; + + if (CanBlink) + { + if (Blink_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + //expire movement, will prevent from running right back to victim after cast + //(but should MoveChase be used again at a certain time or should he not move?) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + + DoCast(me, SPELL_BLINK); + Blink_Timer = 1000 + rand()%1500; + CanBlink = false; + } else Blink_Timer -= diff; + } + + if (Beacon_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + if (!urand(0,3)) + DoScriptText(SAY_SUMMON, me); + + DoCast(me, SPELL_ETHEREAL_BEACON, true); + + Beacon_Timer = 10000; + } else Beacon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nexusprince_shaffar(Creature* pCreature) +{ + return new boss_nexusprince_shaffarAI (pCreature); +} + +enum eEnums +{ + SPELL_ARCANE_BOLT = 15254, + SPELL_ETHEREAL_APPRENTICE = 32372 // Summon 18430 +}; + +struct mob_ethereal_beaconAI : public ScriptedAI +{ + mob_ethereal_beaconAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Apprentice_Timer; + uint32 ArcaneBolt_Timer; + uint32 Check_Timer; + + void KillSelf() + { + me->Kill(me); + } + + void Reset() + { + Apprentice_Timer = DUNGEON_MODE(20000, 10000); + ArcaneBolt_Timer = 1000; + Check_Timer = 1000; + } + + void EnterCombat(Unit * who) + { + // Send Shaffar to fight + Creature* Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); + if (!Shaffar || Shaffar->isDead()) + { + KillSelf(); + return; + } + if (!Shaffar->isInCombat()) + Shaffar->AI()->AttackStart(who); + } + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(me->getVictim()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Check_Timer <= diff) + { + Creature *Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); + if (!Shaffar || Shaffar->isDead() || !Shaffar->isInCombat()) + { + KillSelf(); + return; + } + Check_Timer = 1000; + } else Check_Timer -= diff; + + if (ArcaneBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BOLT); + ArcaneBolt_Timer = 2000 + rand()%2500; + } else ArcaneBolt_Timer -= diff; + + if (Apprentice_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoCast(me, SPELL_ETHEREAL_APPRENTICE, true); + me->ForcedDespawn(); + return; + } else Apprentice_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_ethereal_beacon(Creature* pCreature) +{ + return new mob_ethereal_beaconAI (pCreature); +} + +enum eEthereal +{ + SPELL_ETHEREAL_APPRENTICE_FIREBOLT = 32369, + SPELL_ETHEREAL_APPRENTICE_FROSTBOLT = 32370 +}; + +struct mob_ethereal_apprenticeAI : public ScriptedAI +{ + mob_ethereal_apprenticeAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cast_Timer; + + bool isFireboltTurn; + + void Reset() + { + Cast_Timer = 3000; + isFireboltTurn = true; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Cast_Timer <= diff) + { + if (isFireboltTurn) + { + DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FIREBOLT, true); + isFireboltTurn = false; + }else{ + DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FROSTBOLT, true); + isFireboltTurn = true; + } + Cast_Timer = 3000; + } else Cast_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_ethereal_apprentice(Creature* pCreature) +{ + return new mob_ethereal_apprenticeAI (pCreature); +} + +void AddSC_boss_nexusprince_shaffar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_nexusprince_shaffar"; + newscript->GetAI = &GetAI_boss_nexusprince_shaffar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ethereal_beacon"; + newscript->GetAI = &GetAI_mob_ethereal_beacon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ethereal_apprentice"; + newscript->GetAI = &GetAI_mob_ethereal_apprentice; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp b/src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp new file mode 100644 index 00000000000..51ec2e83b46 --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp @@ -0,0 +1,126 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Pandemonius +SD%Complete: 75 +SDComment: Not known how void blast is done (amount of rapid cast seems to be related to players in party). All mobs remaining in surrounding area should aggro when engaged. +SDCategory: Auchindoun, Mana Tombs +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1557008 +#define SAY_AGGRO_2 -1557009 +#define SAY_AGGRO_3 -1557010 + +#define SAY_KILL_1 -1557011 +#define SAY_KILL_2 -1557012 + +#define SAY_DEATH -1557013 + +#define EMOTE_DARK_SHELL -1557014 + +#define SPELL_VOID_BLAST 32325 +#define H_SPELL_VOID_BLAST 38760 +#define SPELL_DARK_SHELL 32358 +#define H_SPELL_DARK_SHELL 38759 + +struct boss_pandemoniusAI : public ScriptedAI +{ + boss_pandemoniusAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 VoidBlast_Timer; + uint32 DarkShell_Timer; + uint32 VoidBlast_Counter; + + void Reset() + { + VoidBlast_Timer = 8000+rand()%15000; + DarkShell_Timer = 20000; + VoidBlast_Counter = 0; + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (VoidBlast_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_VOID_BLAST); + VoidBlast_Timer = 500; + ++VoidBlast_Counter; + } + + if (VoidBlast_Counter == 5) + { + VoidBlast_Timer = 15000+rand()%10000; + VoidBlast_Counter = 0; + } + } else VoidBlast_Timer -= diff; + + if (!VoidBlast_Counter) + { + if (DarkShell_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(EMOTE_DARK_SHELL, me); + + DoCast(me, SPELL_DARK_SHELL); + DarkShell_Timer = 20000; + } else DarkShell_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_pandemonius(Creature* pCreature) +{ + return new boss_pandemoniusAI (pCreature); +} + +void AddSC_boss_pandemonius() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_pandemonius"; + newscript->GetAI = &GetAI_boss_pandemonius; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp b/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp new file mode 100644 index 00000000000..9628fa1a98f --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp @@ -0,0 +1,414 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Darkweaver_Syth +SD%Complete: 85 +SDComment: Shock spells/times need more work. Heroic partly implemented. +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_SUMMON -1556000 + +#define SAY_AGGRO_1 -1556001 +#define SAY_AGGRO_2 -1556002 +#define SAY_AGGRO_3 -1556003 + +#define SAY_SLAY_1 -1556004 +#define SAY_SLAY_2 -1556005 + +#define SAY_DEATH -1556006 + +#define SPELL_FROST_SHOCK 21401 //37865 +#define SPELL_FLAME_SHOCK 34354 +#define SPELL_SHADOW_SHOCK 30138 +#define SPELL_ARCANE_SHOCK 37132 + +#define SPELL_CHAIN_LIGHTNING 15659 //15305 + +#define SPELL_SUMMON_SYTH_FIRE 33537 // Spawns 19203 +#define SPELL_SUMMON_SYTH_ARCANE 33538 // Spawns 19205 +#define SPELL_SUMMON_SYTH_FROST 33539 // Spawns 19204 +#define SPELL_SUMMON_SYTH_SHADOW 33540 // Spawns 19206 + +#define SPELL_FLAME_BUFFET DUNGEON_MODE(33526, 38141) +#define SPELL_ARCANE_BUFFET DUNGEON_MODE(33527, 38138) +#define SPELL_FROST_BUFFET DUNGEON_MODE(33528, 38142) +#define SPELL_SHADOW_BUFFET DUNGEON_MODE(33529, 38143) + +struct boss_darkweaver_sythAI : public ScriptedAI +{ + boss_darkweaver_sythAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 flameshock_timer; + uint32 arcaneshock_timer; + uint32 frostshock_timer; + uint32 shadowshock_timer; + uint32 chainlightning_timer; + + bool summon90; + bool summon50; + bool summon10; + + void Reset() + { + flameshock_timer = 2000; + arcaneshock_timer = 4000; + frostshock_timer = 6000; + shadowshock_timer = 8000; + chainlightning_timer = 15000; + + summon90 = false; + summon50 = false; + summon10 = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustSummoned(Creature *summoned) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(pTarget); + } + + void SythSummoning() + { + DoScriptText(SAY_SUMMON, me); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me, SPELL_SUMMON_SYTH_ARCANE, true); //front + DoCast(me, SPELL_SUMMON_SYTH_FIRE, true); //back + DoCast(me, SPELL_SUMMON_SYTH_FROST, true); //left + DoCast(me, SPELL_SUMMON_SYTH_SHADOW, true); //right + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 90) && !summon90) + { + SythSummoning(); + summon90 = true; + } + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 50) && !summon50) + { + SythSummoning(); + summon50 = true; + } + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 10) && !summon10) + { + SythSummoning(); + summon10 = true; + } + + if (flameshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_SHOCK); + + flameshock_timer = 10000 + rand()%5000; + } else flameshock_timer -= diff; + + if (arcaneshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_SHOCK); + + arcaneshock_timer = 10000 + rand()%5000; + } else arcaneshock_timer -= diff; + + if (frostshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_SHOCK); + + frostshock_timer = 10000 + rand()%5000; + } else frostshock_timer -= diff; + + if (shadowshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_SHOCK); + + shadowshock_timer = 10000 + rand()%5000; + } else shadowshock_timer -= diff; + + if (chainlightning_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + + chainlightning_timer = 25000; + } else chainlightning_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_darkweaver_syth(Creature* pCreature) +{ + return new boss_darkweaver_sythAI (pCreature); +} + +/* ELEMENTALS */ + +struct mob_syth_fireAI : public ScriptedAI +{ + mob_syth_fireAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 flameshock_timer; + uint32 flamebuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + flameshock_timer = 2500; + flamebuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (flameshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_SHOCK); + + flameshock_timer = 5000; + } else flameshock_timer -= diff; + + if (flamebuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_BUFFET); + + flamebuffet_timer = 5000; + } else flamebuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_fire(Creature* pCreature) +{ + return new mob_syth_fireAI (pCreature); +} + +struct mob_syth_arcaneAI : public ScriptedAI +{ + mob_syth_arcaneAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 arcaneshock_timer; + uint32 arcanebuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); + arcaneshock_timer = 2500; + arcanebuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (arcaneshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_SHOCK); + + arcaneshock_timer = 5000; + } else arcaneshock_timer -= diff; + + if (arcanebuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_BUFFET); + + arcanebuffet_timer = 5000; + } else arcanebuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_arcane(Creature* pCreature) +{ + return new mob_syth_arcaneAI (pCreature); +} + +struct mob_syth_frostAI : public ScriptedAI +{ + mob_syth_frostAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 frostshock_timer; + uint32 frostbuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + frostshock_timer = 2500; + frostbuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (frostshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_SHOCK); + + frostshock_timer = 5000; + } else frostshock_timer -= diff; + + if (frostbuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_BUFFET); + + frostbuffet_timer = 5000; + } else frostbuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_frost(Creature* pCreature) +{ + return new mob_syth_frostAI (pCreature); +} + +struct mob_syth_shadowAI : public ScriptedAI +{ + mob_syth_shadowAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 shadowshock_timer; + uint32 shadowbuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + shadowshock_timer = 2500; + shadowbuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (shadowshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_SHOCK); + + shadowshock_timer = 5000; + } else shadowshock_timer -= diff; + + if (shadowbuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_BUFFET); + + shadowbuffet_timer = 5000; + } else shadowbuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_shadow(Creature* pCreature) +{ + return new mob_syth_shadowAI (pCreature); +} + +void AddSC_boss_darkweaver_syth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_darkweaver_syth"; + newscript->GetAI = &GetAI_boss_darkweaver_syth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_fire"; + newscript->GetAI = &GetAI_mob_syth_arcane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_arcane"; + newscript->GetAI = &GetAI_mob_syth_arcane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_frost"; + newscript->GetAI = &GetAI_mob_syth_frost; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_shadow"; + newscript->GetAI = &GetAI_mob_syth_shadow; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp new file mode 100644 index 00000000000..32b97293ca3 --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp @@ -0,0 +1,213 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Talon_King_Ikiss +SD%Complete: 80 +SDComment: Heroic supported. Some details missing, but most are spell related. +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "sethekk_halls.h" + +#define SAY_INTRO -1556007 + +#define SAY_AGGRO_1 -1556008 +#define SAY_AGGRO_2 -1556009 +#define SAY_AGGRO_3 -1556010 + +#define SAY_SLAY_1 -1556011 +#define SAY_SLAY_2 -1556012 +#define SAY_DEATH -1556013 +#define EMOTE_ARCANE_EXP -1556015 + +#define SPELL_BLINK 38194 +#define SPELL_BLINK_TELEPORT 38203 +#define SPELL_MANA_SHIELD 38151 +#define SPELL_ARCANE_BUBBLE 9438 +#define H_SPELL_SLOW 35032 + +#define SPELL_POLYMORPH 38245 +#define H_SPELL_POLYMORPH 43309 + +#define SPELL_ARCANE_VOLLEY 35059 +#define H_SPELL_ARCANE_VOLLEY 40424 + +#define SPELL_ARCANE_EXPLOSION 38197 +#define H_SPELL_ARCANE_EXPLOSION 40425 + +struct boss_talon_king_ikissAI : public ScriptedAI +{ + boss_talon_king_ikissAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ArcaneVolley_Timer; + uint32 Sheep_Timer; + uint32 Blink_Timer; + uint32 Slow_Timer; + + bool ManaShield; + bool Blink; + bool Intro; + + void Reset() + { + ArcaneVolley_Timer = 5000; + Sheep_Timer = 8000; + Blink_Timer = 35000; + Slow_Timer = 15000+rand()%15000; + Blink = false; + Intro = false; + ManaShield = false; + } + + void MoveInLineOfSight(Unit *who) + { + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!Intro && me->IsWithinDistInMap(who, 100)) + { + Intro = true; + DoScriptText(SAY_INTRO, me); + } + + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_IKISSDOOREVENT, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Blink) + { + DoCast(me, SPELL_ARCANE_EXPLOSION); + DoCast(me, SPELL_ARCANE_BUBBLE, true); + Blink = false; + } + + if (ArcaneVolley_Timer <= diff) + { + DoCast(me, SPELL_ARCANE_VOLLEY); + ArcaneVolley_Timer = 7000+rand()%5000; + } else ArcaneVolley_Timer -= diff; + + if (Sheep_Timer <= diff) + { + Unit *pTarget; + + //second top aggro target in normal, random target in heroic correct? + if (IsHeroic()) + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + else + pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + + if (pTarget) + DoCast(pTarget, SPELL_POLYMORPH); + Sheep_Timer = 15000+rand()%2500; + } else Sheep_Timer -= diff; + + //may not be correct time to cast + if (!ManaShield && ((me->GetHealth()*100) / me->GetMaxHealth() < 20)) + { + DoCast(me, SPELL_MANA_SHIELD); + ManaShield = true; + } + + if (IsHeroic()) + { + if (Slow_Timer <= diff) + { + DoCast(me, H_SPELL_SLOW); + Slow_Timer = 15000+rand()%25000; + } else Slow_Timer -= diff; + } + + if (Blink_Timer <= diff) + { + DoScriptText(EMOTE_ARCANE_EXP, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + //Spell doesn't work, but we use for visual effect at least + DoCast(pTarget, SPELL_BLINK); + + float X = pTarget->GetPositionX(); + float Y = pTarget->GetPositionY(); + float Z = pTarget->GetPositionZ(); + + DoTeleportTo(X,Y,Z); + + DoCast(pTarget, SPELL_BLINK_TELEPORT); + Blink = true; + } + Blink_Timer = 35000+rand()%5000; + } else Blink_Timer -= diff; + + if (!Blink) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_talon_king_ikiss(Creature* pCreature) +{ + return new boss_talon_king_ikissAI (pCreature); +} + +void AddSC_boss_talon_king_ikiss() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_talon_king_ikiss"; + newscript->GetAI = &GetAI_boss_talon_king_ikiss; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp b/src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp new file mode 100644 index 00000000000..ee27da3cff5 --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance - Sethekk Halls +SD%Complete: 50 +SDComment: Instance Data for Sethekk Halls instance +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "sethekk_halls.h" + +enum eEnums +{ + NPC_ANZU = 23035, + IKISS_DOOR = 177203, +}; + +struct instance_sethekk_halls : public ScriptedInstance +{ + instance_sethekk_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 AnzuEncounter; + uint64 m_uiIkissDoorGUID; + + void Initialize() + { + AnzuEncounter = NOT_STARTED; + m_uiIkissDoorGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == NPC_ANZU) + { + if (AnzuEncounter >= IN_PROGRESS) + pCreature->DisappearAndDie(); + else + AnzuEncounter = IN_PROGRESS; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + if (pGo->GetEntry() == IKISS_DOOR) + m_uiIkissDoorGUID = pGo->GetGUID(); + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_IKISSDOOREVENT: + if (data == DONE) + DoUseDoorOrButton(m_uiIkissDoorGUID,DAY*IN_MILISECONDS); + break; + case TYPE_ANZU_ENCOUNTER: + AnzuEncounter = data; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_sethekk_halls(Map* pMap) +{ + return new instance_sethekk_halls(pMap); +} + +void AddSC_instance_sethekk_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_sethekk_halls"; + newscript->GetInstanceData = &GetInstanceData_instance_sethekk_halls; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h b/src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h new file mode 100644 index 00000000000..79a6cd4952d --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SETHEKK_HALLS_H +#define DEF_SETHEKK_HALLS_H + +enum eTypes +{ + DATA_IKISSDOOREVENT = 1, + TYPE_ANZU_ENCOUNTER = 2, +}; +#endif + diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp new file mode 100644 index 00000000000..2bb6a717a5a --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ambassador_Hellmaw +SD%Complete: 80 +SDComment: Enrage spell missing/not known +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "shadow_labyrinth.h" + +enum eEnums +{ + SAY_INTRO = -1555000, + SAY_AGGRO1 = -1555001, + SAY_AGGRO2 = -1555002, + SAY_AGGRO3 = -1555003, + SAY_HELP = -1555004, + SAY_SLAY1 = -1555005, + SAY_SLAY2 = -1555006, + SAY_DEATH = -1555007, + + SPELL_BANISH = 30231, + SPELL_CORROSIVE_ACID = 33551, + SPELL_FEAR = 33547, + SPELL_ENRAGE = 34970 +}; + +struct boss_ambassador_hellmawAI : public npc_escortAI +{ + boss_ambassador_hellmawAI(Creature* pCreature) : npc_escortAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 EventCheck_Timer; + uint32 CorrosiveAcid_Timer; + uint32 Fear_Timer; + uint32 Enrage_Timer; + bool Intro; + bool IsBanished; + bool Enraged; + + void Reset() + { + EventCheck_Timer = 5000; + CorrosiveAcid_Timer = 5000 + rand()%5000; + Fear_Timer = 25000 + rand()%5000; + Enrage_Timer = 180000; + Intro = false; + IsBanished = true; + Enraged = false; + + if (m_pInstance && me->isAlive()) + { + if (m_pInstance->GetData(TYPE_OVERSEER) != DONE) + DoCast(me, SPELL_BANISH, true); + } + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_HELLMAW, FAIL); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (me->HasAura(SPELL_BANISH)) + return; + + npc_escortAI::MoveInLineOfSight(pWho); + } + + void WaypointReached(uint32 /*i*/) + { + } + + void DoIntro() + { + if (me->HasAura(SPELL_BANISH)) + me->RemoveAurasDueToSpell(SPELL_BANISH); + + IsBanished = false; + Intro = true; + + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_HELLMAW) != FAIL) + { + DoScriptText(SAY_INTRO, me); + Start(true, false, 0, NULL, false, true); + } + + m_pInstance->SetData(TYPE_HELLMAW, IN_PROGRESS); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_HELLMAW, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!Intro && !HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (EventCheck_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_OVERSEER) == DONE) + { + DoIntro(); + return; + } + } + EventCheck_Timer = 5000; + return; + } + else + { + EventCheck_Timer -= diff; + return; + } + } + + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + if (me->HasAura(SPELL_BANISH, 0)) + { + EnterEvadeMode(); + return; + } + + if (CorrosiveAcid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVE_ACID); + CorrosiveAcid_Timer = 15000 + rand()%10000; + } else CorrosiveAcid_Timer -= diff; + + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 20000 + rand()%15000; + } else Fear_Timer -= diff; + + if (IsHeroic()) + { + if (!Enraged && Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else Enrage_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_ambassador_hellmaw(Creature* pCreature) +{ + return new boss_ambassador_hellmawAI(pCreature); +} + +void AddSC_boss_ambassador_hellmaw() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ambassador_hellmaw"; + newscript->GetAI = &GetAI_boss_ambassador_hellmaw; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp new file mode 100644 index 00000000000..52c60ae0d0e --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp @@ -0,0 +1,169 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Blackheart_the_Inciter +SD%Complete: 75 +SDComment: Incite Chaos not functional since core lacks Mind Control support +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define SPELL_INCITE_CHAOS 33676 +#define SPELL_INCITE_CHAOS_B 33684 //debuff applied to each member of party +#define SPELL_CHARGE 33709 +#define SPELL_WAR_STOMP 33707 + +#define SAY_INTRO1 -1555008 //not used +#define SAY_INTRO2 -1555009 //not used +#define SAY_INTRO3 -1555010 //not used +#define SAY_AGGRO1 -1555011 +#define SAY_AGGRO2 -1555012 +#define SAY_AGGRO3 -1555013 +#define SAY_SLAY1 -1555014 +#define SAY_SLAY2 -1555015 +#define SAY_HELP -1555016 //not used +#define SAY_DEATH -1555017 + +//below, not used +#define SAY2_INTRO1 -1555018 +#define SAY2_INTRO2 -1555019 +#define SAY2_INTRO3 -1555020 +#define SAY2_AGGRO1 -1555021 +#define SAY2_AGGRO2 -1555022 +#define SAY2_AGGRO3 -1555023 +#define SAY2_SLAY1 -1555024 +#define SAY2_SLAY2 -1555025 +#define SAY2_HELP -1555026 +#define SAY2_DEATH -1555027 + +struct boss_blackheart_the_inciterAI : public ScriptedAI +{ + boss_blackheart_the_inciterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + bool InciteChaos; + uint32 InciteChaos_Timer; + uint32 InciteChaosWait_Timer; + uint32 Charge_Timer; + uint32 Knockback_Timer; + + void Reset() + { + InciteChaos = false; + InciteChaos_Timer = 20000; + InciteChaosWait_Timer = 15000; + Charge_Timer = 5000; + Knockback_Timer = 15000; + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (InciteChaos) + { + if (InciteChaosWait_Timer <= diff) + { + InciteChaos = false; + InciteChaosWait_Timer = 15000; + } else InciteChaosWait_Timer -= diff; + + return; + } + + if (InciteChaos_Timer <= diff) + { + DoCast(me, SPELL_INCITE_CHAOS); + + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + pTarget->CastSpell(pTarget,SPELL_INCITE_CHAOS_B,true); + } + + DoResetThreat(); + InciteChaos = true; + InciteChaos_Timer = 40000; + return; + } else InciteChaos_Timer -= diff; + + //Charge_Timer + if (Charge_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CHARGE); + Charge_Timer = 15000 + rand()%10000; + } else Charge_Timer -= diff; + + //Knockback_Timer + if (Knockback_Timer <= diff) + { + DoCast(me, SPELL_WAR_STOMP); + Knockback_Timer = 18000 + rand()%6000; + } else Knockback_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_blackheart_the_inciter(Creature* pCreature) +{ + return new boss_blackheart_the_inciterAI (pCreature); +} + +void AddSC_boss_blackheart_the_inciter() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_blackheart_the_inciter"; + newscript->GetAI = &GetAI_boss_blackheart_the_inciter; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp new file mode 100644 index 00000000000..8b63b765b47 --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp @@ -0,0 +1,313 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grandmaster_Vorpil +SD%Complete: 100 +SDComment: +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define SAY_INTRO -1555028 +#define SAY_AGGRO1 -1555029 +#define SAY_AGGRO2 -1555030 +#define SAY_AGGRO3 -1555031 +#define SAY_HELP -1555032 +#define SAY_SLAY1 -1555033 +#define SAY_SLAY2 -1555034 +#define SAY_DEATH -1555035 + +#define SPELL_RAIN_OF_FIRE 33617 +#define H_SPELL_RAIN_OF_FIRE 39363 + +#define SPELL_DRAW_SHADOWS 33563 +#define SPELL_SHADOWBOLT_VOLLEY 33841 +#define SPELL_BANISH 38791 + +#define MOB_VOID_TRAVELER 19226 +#define SPELL_SACRIFICE 33587 +#define SPELL_SHADOW_NOVA 33846 +#define SPELL_EMPOWERING_SHADOWS 33783 +#define H_SPELL_EMPOWERING_SHADOWS 39364 + +#define MOB_VOID_PORTAL 19224 +#define SPELL_VOID_PORTAL_VISUAL 33569 + +float VorpilPosition[3] = {-252.8820,-264.3030,17.1}; + +float VoidPortalCoords[5][3] = +{ + {-283.5894, -239.5718, 12.7}, + {-306.5853, -258.4539, 12.7}, + {-295.8789, -269.0899, 12.7}, + {-209.3401, -262.7564, 17.1}, + {-261.4533, -297.3298, 17.1} +}; + +struct mob_voidtravelerAI : public ScriptedAI +{ + mob_voidtravelerAI(Creature *c) : ScriptedAI(c) + { + } + + uint64 VorpilGUID; + uint32 move; + bool sacrificed; + + void Reset() + { + VorpilGUID = 0; + move = 0; + sacrificed = false; + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (!VorpilGUID) + { + me->Kill(me); + return; + } + if (move <= diff) + { + Creature *Vorpil = Unit::GetCreature(*me, VorpilGUID); + if (!Vorpil) + { + VorpilGUID = 0; + return; + } + + if (sacrificed) + { + me->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), Vorpil); + Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth()/25); + DoCast(me, SPELL_SHADOW_NOVA, true); + me->Kill(me); + return; + } + me->GetMotionMaster()->MoveFollow(Vorpil,0,0); + if (me->IsWithinDist(Vorpil, 3)) + { + DoCast(me, SPELL_SACRIFICE, false); + sacrificed = true; + move = 500; + return; + } + if (!Vorpil->isInCombat() || Vorpil->isDead()) + { + me->Kill(me); + return; + } + move = 1000; + } else move -= diff; + } +}; +CreatureAI* GetAI_mob_voidtraveler(Creature* pCreature) +{ + return new mob_voidtravelerAI (pCreature); +} + +struct boss_grandmaster_vorpilAI : public ScriptedAI +{ + boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = false; + } + + ScriptedInstance *pInstance; + bool Intro, HelpYell; + bool sumportals; + + uint32 ShadowBoltVolley_Timer; + uint32 DrawShadows_Timer; + uint32 summonTraveler_Timer; + uint32 banish_Timer; + uint64 PortalsGuid[5]; + + void Reset() + { + ShadowBoltVolley_Timer = 7000 + rand()%7000; + DrawShadows_Timer = 45000; + summonTraveler_Timer = 90000; + banish_Timer = 17000; + HelpYell = false; + destroyPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED); + } + + void summonPortals() + { + if (!sumportals) + { + for (uint8 i = 0; i < 5; ++i) + { + Creature *Portal = NULL; + Portal = me->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000); + if (Portal) + { + PortalsGuid[i] = Portal->GetGUID(); + Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false); + } + } + sumportals = true; + summonTraveler_Timer = 5000; + } + } + + void destroyPortals() + { + if (sumportals) + { + for (uint8 i = 0; i < 5; ++i) + { + Unit *Portal = Unit::GetUnit((*me), PortalsGuid[i]); + if (Portal && Portal->isAlive()) + Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + PortalsGuid[i] = 0; + } + sumportals = false; + } + } + + void spawnVoidTraveler() + { + int pos = urand(0,4); + me->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,5000); + if (!HelpYell) + { + DoScriptText(SAY_HELP, me); + HelpYell = true; + } + } + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == MOB_VOID_TRAVELER) + CAST_AI(mob_voidtravelerAI, summoned->AI())->VorpilGUID = me->GetGUID(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + destroyPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + summonPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS); + } + + void MoveInLineOfSight(Unit *who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (!Intro && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 100) && me->IsHostileTo(who)) + { + DoScriptText(SAY_INTRO, me); + Intro = true; + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOWBOLT_VOLLEY); + ShadowBoltVolley_Timer = 15000 + rand()%15000; + } else ShadowBoltVolley_Timer -= diff; + + if (IsHeroic() && banish_Timer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,false); + if (pTarget) + { + DoCast(pTarget, SPELL_BANISH); + banish_Timer = 16000; + } + } else banish_Timer -= diff; + + if (DrawShadows_Timer <= diff) + { + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* i_pl = i->getSource()) + if (i_pl->isAlive() && !i_pl->HasAura(SPELL_BANISH)) + i_pl->TeleportTo(me->GetMapId(), VorpilPosition[0],VorpilPosition[1],VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT); + + me->GetMap()->CreatureRelocation(me, VorpilPosition[0],VorpilPosition[1],VorpilPosition[2],0.0f); + DoCast(me, SPELL_DRAW_SHADOWS, true); + + DoCast(me, SPELL_RAIN_OF_FIRE); + + ShadowBoltVolley_Timer = 6000; + DrawShadows_Timer = 30000; + } else DrawShadows_Timer -= diff; + + if (summonTraveler_Timer <= diff) + { + spawnVoidTraveler(); + summonTraveler_Timer = 10000; + //enrage at 20% + if ((me->GetHealth()*5) < me->GetMaxHealth()) + summonTraveler_Timer = 5000; + } else summonTraveler_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grandmaster_vorpil(Creature* pCreature) +{ + return new boss_grandmaster_vorpilAI (pCreature); +} + +void AddSC_boss_grandmaster_vorpil() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grandmaster_vorpil"; + newscript->GetAI = &GetAI_boss_grandmaster_vorpil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_voidtraveler"; + newscript->GetAI = &GetAI_mob_voidtraveler; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp new file mode 100644 index 00000000000..14bf249c3b5 --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Murmur +SD%Complete: 90 +SDComment: Timers may be incorrect +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define EMOTE_SONIC_BOOM -1555036 + +#define SPELL_SONIC_BOOM_CAST DUNGEON_MODE(33923, 38796) +#define SPELL_SONIC_BOOM_EFFECT DUNGEON_MODE(33666, 38795) +#define SPELL_RESONANCE 33657 +#define SPELL_MURMURS_TOUCH DUNGEON_MODE(33711, 38794) +#define SPELL_MAGNETIC_PULL 33689 +#define SPELL_SONIC_SHOCK 38797 +#define SPELL_THUNDERING_STORM 39365 + +struct boss_murmurAI : public ScriptedAI +{ + boss_murmurAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 SonicBoom_Timer; + uint32 MurmursTouch_Timer; + uint32 Resonance_Timer; + uint32 MagneticPull_Timer; + uint32 SonicShock_Timer; + uint32 ThunderingStorm_Timer; + bool SonicBoom; + + void Reset() + { + SonicBoom_Timer = 30000; + MurmursTouch_Timer = 8000 + rand()%12000; + Resonance_Timer = 5000; + MagneticPull_Timer = 15000 + rand()%15000; + ThunderingStorm_Timer = 15000; + SonicShock_Timer = 10000; + SonicBoom = false; + + //database should have `RegenHealth`=0 to prevent regen + uint32 hp = (me->GetMaxHealth()*40)/100; + if (hp) me->SetHealth(hp); + me->ResetPlayerDamageReq(); + } + + void SonicBoomEffect() + { + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + //Not do anything without aura, spell can be resisted! + if (pTarget->HasAura(SPELL_SONIC_BOOM_CAST) && me->IsWithinDistInMap(pTarget, 34.0f)) + { + //This will be wrong calculation. Also, comments suggest it must deal damage + pTarget->SetHealth(uint32(pTarget->GetMaxHealth() - pTarget->GetMaxHealth() * 0.8)); + } + } + } + } + + void EnterCombat(Unit * /*who*/) { } + + // Sonic Boom instant damage (needs core fix instead of this) + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (pTarget && pTarget->isAlive() && spell && spell->Id == uint32(SPELL_SONIC_BOOM_EFFECT)) + me->DealDamage(pTarget,(pTarget->GetHealth()*90)/100,NULL,SPELL_DIRECT_DAMAGE,SPELL_SCHOOL_MASK_NATURE,spell); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target or casting + if (!UpdateVictim() || me->IsNonMeleeSpellCasted(false)) + return; + + // Sonic Boom + if (SonicBoom) + { + DoCast(me, SPELL_SONIC_BOOM_EFFECT, true); + SonicBoomEffect(); + + SonicBoom = false; + Resonance_Timer = 1500; + } + if (SonicBoom_Timer <= diff) + { + DoScriptText(EMOTE_SONIC_BOOM, me); + DoCast(me, SPELL_SONIC_BOOM_CAST); + SonicBoom_Timer = 30000; + SonicBoom = true; + return; + } else SonicBoom_Timer -= diff; + + // Murmur's Touch + if (MurmursTouch_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,80,true)) + DoCast(pTarget, SPELL_MURMURS_TOUCH); + MurmursTouch_Timer = 25000 + rand()%10000; + } else MurmursTouch_Timer -= diff; + + // Resonance + if (!SonicBoom && !(me->IsWithinMeleeRange(me->getVictim()))) + { + if (Resonance_Timer <= diff) + { + DoCast(me, SPELL_RESONANCE); + Resonance_Timer = 5000; + } else Resonance_Timer -= diff; + } + + // Magnetic Pull + if (MagneticPull_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + if (pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + { + DoCast(pTarget, SPELL_MAGNETIC_PULL); + MagneticPull_Timer = 15000+rand()%15000; + return; + } + MagneticPull_Timer = 500; + } else MagneticPull_Timer -= diff; + + if (IsHeroic()) + { + // Thundering Storm + if (ThunderingStorm_Timer <= diff) + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) + if (pTarget->isAlive() && !me->IsWithinDist(pTarget, 35, false)) + DoCast(pTarget, SPELL_THUNDERING_STORM, true); + ThunderingStorm_Timer = 15000; + } else ThunderingStorm_Timer -= diff; + + // Sonic Shock + if (SonicShock_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,20,false)) + if (pTarget->isAlive()) + DoCast(pTarget, SPELL_SONIC_SHOCK); + SonicShock_Timer = 10000+rand()%10000; + } else SonicShock_Timer -= diff; + } + + // Select nearest most aggro target if top aggro too far + if (!me->isAttackReady()) + return; + if (!me->IsWithinMeleeRange(me->getVictim())) + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) + if (pTarget->isAlive() && me->IsWithinMeleeRange(pTarget)) + { + me->TauntApply(pTarget); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_murmur(Creature* pCreature) +{ + return new boss_murmurAI (pCreature); +} + +void AddSC_boss_murmur() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_murmur"; + newscript->GetAI = &GetAI_boss_murmur; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp new file mode 100644 index 00000000000..78340e5e132 --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp @@ -0,0 +1,227 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shadow_Labyrinth +SD%Complete: 85 +SDComment: Some cleanup left along with save +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define MAX_ENCOUNTER 5 + +#define REFECTORY_DOOR 183296 //door opened when blackheart the inciter dies +#define SCREAMING_HALL_DOOR 183295 //door opened when grandmaster vorpil dies + +/* Shadow Labyrinth encounters: +1 - Ambassador Hellmaw event +2 - Blackheart the Inciter event +3 - Grandmaster Vorpil event +4 - Murmur event +*/ + +struct instance_shadow_labyrinth : public ScriptedInstance +{ + instance_shadow_labyrinth(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 m_uiRefectoryDoorGUID; + uint64 m_uiScreamingHallDoorGUID; + + uint64 m_uiGrandmasterVorpil; + uint32 m_uiFelOverseerCount; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiRefectoryDoorGUID = 0; + m_uiScreamingHallDoorGUID = 0; + + m_uiGrandmasterVorpil = 0; + m_uiFelOverseerCount = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case REFECTORY_DOOR: + m_uiRefectoryDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case SCREAMING_HALL_DOOR: + m_uiScreamingHallDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 18732: + m_uiGrandmasterVorpil = pCreature->GetGUID(); + break; + case 18796: + if (pCreature->isAlive()) + { + ++m_uiFelOverseerCount; + debug_log("TSCR: Shadow Labyrinth: counting %u Fel Overseers.",m_uiFelOverseerCount); + } + break; + } + } + + void SetData(uint32 type, uint32 uiData) + { + switch(type) + { + case TYPE_HELLMAW: + m_auiEncounter[0] = uiData; + break; + + case TYPE_OVERSEER: + if (uiData != DONE) + { + error_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER did not expect other data than DONE"); + return; + } + if (m_uiFelOverseerCount) + { + --m_uiFelOverseerCount; + + if (m_uiFelOverseerCount) + debug_log("TSCR: Shadow Labyrinth: %u Fel Overseers left to kill.",m_uiFelOverseerCount); + else + { + m_auiEncounter[1] = DONE; + debug_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER == DONE"); + } + } + break; + + case DATA_BLACKHEARTTHEINCITEREVENT: + if (uiData == DONE) + DoUseDoorOrButton(m_uiRefectoryDoorGUID); + m_auiEncounter[2] = uiData; + break; + + case DATA_GRANDMASTERVORPILEVENT: + if (uiData == DONE) + DoUseDoorOrButton(m_uiScreamingHallDoorGUID); + m_auiEncounter[3] = uiData; + break; + + case DATA_MURMUREVENT: + m_auiEncounter[4] = uiData; + break; + } + + if (uiData == DONE) + { + if (type == TYPE_OVERSEER && m_uiFelOverseerCount != 0) + return; + + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HELLMAW: return m_auiEncounter[0]; + case TYPE_OVERSEER: return m_auiEncounter[1]; + case DATA_GRANDMASTERVORPILEVENT: return m_auiEncounter[3]; + case DATA_MURMUREVENT: return m_auiEncounter[4]; + } + return false; + } + + uint64 GetData64(uint32 identifier) + { + if (identifier == DATA_GRANDMASTERVORPIL) + return m_uiGrandmasterVorpil; + + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_shadow_labyrinth(Map* pMap) +{ + return new instance_shadow_labyrinth(pMap); +} + +void AddSC_instance_shadow_labyrinth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shadow_labyrinth"; + newscript->GetInstanceData = &GetInstanceData_instance_shadow_labyrinth; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h new file mode 100644 index 00000000000..a78955368bf --- /dev/null +++ b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHADOW_LABYRINTH_H +#define DEF_SHADOW_LABYRINTH_H + +#define TYPE_HELLMAW 1 +#define TYPE_OVERSEER 2 +#define DATA_BLACKHEARTTHEINCITEREVENT 3 +#define DATA_GRANDMASTERVORPILEVENT 4 +#define DATA_MURMUREVENT 5 +#define DATA_GRANDMASTERVORPIL 6 +#endif + diff --git a/src/server/scripts/Outland/black_temple/black_temple.cpp b/src/server/scripts/Outland/black_temple/black_temple.cpp new file mode 100644 index 00000000000..c1e7f19fbb1 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/black_temple.cpp @@ -0,0 +1,69 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Black_Temple +SD%Complete: 95 +SDComment: Spirit of Olum: Player Teleporter to Seer Kanai Teleport after defeating Naj'entus and Supremus. TODO: Find proper gossip. +SDCategory: Black Temple +EndScriptData */ + +/* ContentData +npc_spirit_of_olum +EndContentData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +/*### +# npc_spirit_of_olum +####*/ + +#define SPELL_TELEPORT 41566 // s41566 - Teleport to Ashtongue NPC's +#define GOSSIP_OLUM1 "Teleport me to the other Ashtongue Deathsworn" + +bool GossipHello_npc_spirit_of_olum(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && (pInstance->GetData(DATA_SUPREMUSEVENT) >= DONE) && (pInstance->GetData(DATA_HIGHWARLORDNAJENTUSEVENT) >= DONE)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_OLUM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_spirit_of_olum(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + pPlayer->CLOSE_GOSSIP_MENU(); + + pPlayer->InterruptNonMeleeSpells(false); + pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, false); + return true; +} + +void AddSC_black_temple() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_spirit_of_olum"; + newscript->pGossipHello = &GossipHello_npc_spirit_of_olum; + newscript->pGossipSelect = &GossipSelect_npc_spirit_of_olum; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/black_temple.h b/src/server/scripts/Outland/black_temple/black_temple.h new file mode 100644 index 00000000000..b7432cd5b20 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/black_temple.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BLACK_TEMPLE_H +#define DEF_BLACK_TEMPLE_H + +enum eTypes +{ + DATA_AKAMA = 1, + DATA_AKAMA_SHADE = 2, + DATA_GURTOGGBLOODBOILEVENT = 3, + DATA_HIGHWARLORDNAJENTUS = 4, + DATA_HIGHWARLORDNAJENTUSEVENT = 5, + DATA_ILLIDANSTORMRAGE = 6, + DATA_ILLIDANSTORMRAGEEVENT = 7, + DATA_ILLIDARICOUNCILEVENT = 8, + DATA_ILLIDARICOUNCIL = 9, + DATA_LADYMALANDE = 10, + DATA_HIGHNETHERMANCERZEREVOR = 11, + DATA_GATHIOSTHESHATTERER = 12, + DATA_VERASDARKSHADOW = 13, + DATA_MOTHERSHAHRAZEVENT = 14, + DATA_RELIQUARYOFSOULSEVENT = 15, + DATA_SHADEOFAKAMA = 16, + DATA_SHADEOFAKAMAEVENT = 17, + DATA_SUPREMUS = 18, + DATA_SUPREMUSEVENT = 19, + DATA_TERONGOREFIENDEVENT = 20, + DATA_GAMEOBJECT_NAJENTUS_GATE = 21, + DATA_GAMEOBJECT_ILLIDAN_GATE = 22, + DATA_GAMEOBJECT_ILLIDAN_DOOR_R = 23, + DATA_GAMEOBJECT_ILLIDAN_DOOR_L = 24, + DATA_GAMEOBJECT_SUPREMUS_DOORS = 25, + DATA_BLOOD_ELF_COUNCIL_VOICE = 26 +}; + +#endif + diff --git a/src/server/scripts/Outland/black_temple/boss_bloodboil.cpp b/src/server/scripts/Outland/black_temple/boss_bloodboil.cpp new file mode 100644 index 00000000000..1093ce06cb8 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/boss_bloodboil.cpp @@ -0,0 +1,332 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Bloodboil +SD%Complete: 80 +SDComment: Bloodboil not working correctly, missing enrage +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +//Speech'n'Sound +#define SAY_AGGRO -1564029 +#define SAY_SLAY1 -1564030 +#define SAY_SLAY2 -1564031 +#define SAY_SPECIAL1 -1564032 +#define SAY_SPECIAL2 -1564033 +#define SAY_ENRAGE1 -1564034 +#define SAY_ENRAGE2 -1564035 +#define SAY_DEATH -1564036 + +//Spells +#define SPELL_ACID_GEYSER 40630 +#define SPELL_ACIDIC_WOUND 40481 +#define SPELL_ARCING_SMASH 40599 +#define SPELL_BLOODBOIL 42005 // This spell is AoE whereas it shouldn't be +#define SPELL_FEL_ACID 40508 +#define SPELL_FEL_RAGE_SELF 40594 +#define SPELL_FEL_RAGE_TARGET 40604 +#define SPELL_FEL_RAGE_2 40616 +#define SPELL_FEL_RAGE_3 41625 +#define SPELL_BEWILDERING_STRIKE 40491 +#define SPELL_EJECT1 40486 // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) +#define SPELL_EJECT2 40597 // 1000 Physical damage + Stun (used in phase 2?) +#define SPELL_TAUNT_GURTOGG 40603 +#define SPELL_INSIGNIFIGANCE 40618 +#define SPELL_BERSERK 45078 + +//This is used to sort the players by distance in preparation for the Bloodboil cast. + +struct boss_gurtogg_bloodboilAI : public ScriptedAI +{ + boss_gurtogg_bloodboilAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 TargetGUID; + + float TargetThreat; + + uint32 BloodboilTimer; + uint32 BloodboilCount; + uint32 AcidGeyserTimer; + uint32 AcidicWoundTimer; + uint32 ArcingSmashTimer; + uint32 EnrageTimer; + uint32 FelAcidTimer; + uint32 EjectTimer; + uint32 BewilderingStrikeTimer; + uint32 PhaseChangeTimer; + + bool Phase1; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, NOT_STARTED); + + TargetGUID = 0; + + TargetThreat = 0; + + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidGeyserTimer = 1000; + AcidicWoundTimer = 6000; + ArcingSmashTimer = 19000; + EnrageTimer = 600000; + FelAcidTimer = 25000; + EjectTimer = 10000; + BewilderingStrikeTimer = 15000; + PhaseChangeTimer = 60000; + + Phase1 = true; + + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited. + void CastBloodboil() + { + // Get the Threat List + std::list m_threatlist = me->getThreatManager().getThreatList(); + + if (!m_threatlist.size()) // He doesn't have anyone in his threatlist, useless to continue + return; + + std::list targets; + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //only on alive players + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + targets.push_back(pTarget); + } + + //Sort the list of players + targets.sort(Trinity::ObjectDistanceOrderPred(me, false)); + //Resize so we only get top 5 + targets.resize(5); + + //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp + /*SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(SPELL_BLOODBOIL); + if (spellInfo) + { + for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + { + Unit *pTarget = *itr; + if (!pTarget) return; + for (uint32 i = 0; i<3; ++i) + { + uint8 eff = spellInfo->Effect[i]; + if (eff >= TOTAL_SPELL_EFFECTS) + continue; + + Aura *Aur = new Aura(spellInfo, i, pTarget, pTarget, pTarget); + pTarget->AddAura(Aur); + } + } + }*/ + } + + void RevertThreatOnTarget(uint64 guid) + { + Unit* pUnit = NULL; + pUnit = Unit::GetUnit((*me), guid); + if (pUnit) + { + if (DoGetThreat(pUnit)) + DoModifyThreatPercent(pUnit, -100); + if (TargetThreat) + me->AddThreat(pUnit, TargetThreat); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ArcingSmashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCING_SMASH); + ArcingSmashTimer = 10000; + } else ArcingSmashTimer -= diff; + + if (FelAcidTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FEL_ACID); + FelAcidTimer = 25000; + } else FelAcidTimer -= diff; + + if (!me->HasAura(SPELL_BERSERK)) + { + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + DoScriptText(RAND(SAY_ENRAGE1,SAY_ENRAGE2), me); + } else EnrageTimer -= diff; + } + + if (Phase1) + { + if (BewilderingStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BEWILDERING_STRIKE); + float mt_threat = DoGetThreat(me->getVictim()); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1)) + me->AddThreat(pTarget, mt_threat); + BewilderingStrikeTimer = 20000; + } else BewilderingStrikeTimer -= diff; + + if (EjectTimer <= diff) + { + DoCast(me->getVictim(), SPELL_EJECT1); + DoModifyThreatPercent(me->getVictim(), -40); + EjectTimer = 15000; + } else EjectTimer -= diff; + + if (AcidicWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ACIDIC_WOUND); + AcidicWoundTimer = 10000; + } else AcidicWoundTimer -= diff; + + if (BloodboilTimer <= diff) + { + if (BloodboilCount < 5) // Only cast it five times. + { + //CastBloodboil(); // Causes issues on windows, so is commented out. + DoCast(me->getVictim(), SPELL_BLOODBOIL); + ++BloodboilCount; + BloodboilTimer = 10000*BloodboilCount; + } + } else BloodboilTimer -= diff; + } + + if (!Phase1) + { + if (AcidGeyserTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ACID_GEYSER); + AcidGeyserTimer = 30000; + } else AcidGeyserTimer -= diff; + + if (EjectTimer <= diff) + { + DoCast(me->getVictim(), SPELL_EJECT2); + EjectTimer = 15000; + } else EjectTimer -= diff; + } + + if (PhaseChangeTimer <= diff) + { + if (Phase1) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget && pTarget->isAlive()) + { + Phase1 = false; + + TargetThreat = DoGetThreat(pTarget); + TargetGUID = pTarget->GetGUID(); + pTarget->CastSpell(me, SPELL_TAUNT_GURTOGG, true); + if (DoGetThreat(pTarget)) + DoModifyThreatPercent(pTarget, -100); + me->AddThreat(pTarget, 50000000.0f); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + // If VMaps are disabled, this spell can call the whole instance + DoCast(me, SPELL_INSIGNIFIGANCE, true); + DoCast(pTarget, SPELL_FEL_RAGE_TARGET, true); + DoCast(pTarget, SPELL_FEL_RAGE_2, true); + /* These spells do not work, comment them out for now. + DoCast(pTarget, SPELL_FEL_RAGE_2, true); + DoCast(pTarget, SPELL_FEL_RAGE_3, true);*/ + + //Cast this without triggered so that it appears in combat logs and shows visual. + DoCast(me, SPELL_FEL_RAGE_SELF); + + DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); + + AcidGeyserTimer = 1000; + PhaseChangeTimer = 30000; + } + } else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage + { + if (TargetGUID) + RevertThreatOnTarget(TargetGUID); + TargetGUID = 0; + Phase1 = true; + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidicWoundTimer += 2000; + ArcingSmashTimer += 2000; + FelAcidTimer += 2000; + EjectTimer += 2000; + PhaseChangeTimer = 60000; + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); + } + } else PhaseChangeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_gurtogg_bloodboil(Creature* pCreature) +{ + return new boss_gurtogg_bloodboilAI (pCreature); +} + +void AddSC_boss_gurtogg_bloodboil() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gurtogg_bloodboil"; + newscript->GetAI = &GetAI_boss_gurtogg_bloodboil; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/boss_illidan.cpp b/src/server/scripts/Outland/black_temple/boss_illidan.cpp new file mode 100644 index 00000000000..b8e09c0e08e --- /dev/null +++ b/src/server/scripts/Outland/black_temple/boss_illidan.cpp @@ -0,0 +1,2248 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_illidan_stormrage +SD%Complete: 90 +SDComment: Somewhat of a workaround for Parasitic Shadowfiend, unable to summon GOs for Cage Trap. +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +#define GETGO(obj, guid) GameObject* obj = pInstance->instance->GetGameObject(guid) +#define GETUNIT(unit, guid) Unit* unit = Unit::GetUnit(*me, guid) +#define GETCRE(cre, guid) Creature* cre = Unit::GetCreature(*me, guid) +#define HPPCT(unit) unit->GetHealth()*100 / unit->GetMaxHealth() + +/************* Quotes and Sounds ***********************/ +// Gossip for when a player clicks Akama +#define GOSSIP_ITEM "We are ready to face Illidan" + +// Yells for/by Akama +#define SAY_AKAMA_BEWARE "Be wary friends, The Betrayer meditates in the court just beyond." +#define SOUND_AKAMA_BEWARE 11388 +#define SAY_AKAMA_MINION "Come, my minions. Deal with this traitor as he deserves!" +#define SOUND_AKAMA_MINION 11465 +#define SAY_AKAMA_LEAVE "I'll deal with these mongrels. Strike now, friends! Strike at the betrayer!" +#define SOUND_AKAMA_LEAVE 11390 + +// Self explanatory +const char* SAY_KILL1 = "Who shall be next to taste my blades?!"; +#define SOUND_KILL1 11473 +const char* SAY_KILL2 = "This is too easy!"; +#define SOUND_KILL2 11472 + +// I think I'll fly now and let my subordinates take you on +#define SAY_TAKEOFF "I will not be touched by rabble such as you!" +#define SOUND_TAKEOFF 11479 +#define SAY_SUMMONFLAMES "Behold the flames of Azzinoth!" +#define SOUND_SUMMONFLAMES 11480 + +// When casting Eye Blast. Demon Fire will be appear on places that he casts this +#define SAY_EYE_BLAST "Stare into the eyes of the Betrayer!" +#define SOUND_EYE_BLAST 11481 + +// kk, I go big, dark and demon on you. +#define SAY_MORPH "Behold the power... of the demon within!" +#define SOUND_MORPH 11475 + +// I KILL! +#define SAY_ENRAGE "You've wasted too much time mortals, now you shall fall!" +#define SOUND_ENRAGE 11474 + +/************** Spells *************/ +// Normal Form +#define SPELL_SHEAR 37335 // 41032 is bugged, cannot be block/dodge/parry// Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5 second cast +#define SPELL_FLAME_CRASH 40832 // Summons an invis/unselect passive mob that has an aura of flame in a circle around him. +#define SPELL_DRAW_SOUL 40904 // 5k Shadow Damage in front of him. Heals Illidan for 100k health (script effect) +#define SPELL_PARASITIC_SHADOWFIEND 41917 // DoT of 3k Shadow every 2 seconds. Lasts 10 seconds. (Script effect: Summon 2 parasites once the debuff has ticked off) +#define SPELL_PARASITIC_SHADOWFIEND2 41914 // Used by Parasitic +#define SPELL_SUMMON_PARASITICS 41915 // Summons 2 Parasitic Shadowfiends on the target. It's supposed to be cast as soon as the Parasitic Shadowfiend debuff is gone, but the spells aren't linked :( +#define SPELL_AGONIZING_FLAMES 40932 // 4k fire damage initial to target and anyone w/i 5 yards. PHASE 3 ONLY +#define SPELL_ENRAGE 40683 // Increases damage by 50% and attack speed by 30%. 20 seconds, PHASE 5 ONLY +// Flying (Phase 2) +#define SPELL_THROW_GLAIVE 39635 // Throws a glaive on the ground +#define SPELL_THROW_GLAIVE2 39849 // Animation for the above spell +#define SPELL_GLAIVE_RETURNS 39873 // Glaive flies back to Illidan +#define SPELL_FIREBALL 40598 // 2.5k-3.5k damage in 10 yard radius. 2 second cast time. +#define SPELL_DARK_BARRAGE 40585 // 10 second channeled spell, 3k shadow damage per second. +// Demon Form +#define SPELL_DEMON_TRANSFORM_1 40511 // First phase of animations for transforming into Dark Illidan (fall to ground) +#define SPELL_DEMON_TRANSFORM_2 40398 // Second phase of animations (kneel) +#define SPELL_DEMON_TRANSFORM_3 40510 // Final phase of animations (stand up and roar) +#define SPELL_DEMON_FORM 40506 // Transforms into Demon Illidan. Has an Aura of Dread on him. +#define SPELL_SHADOW_BLAST 41078 // 8k - 11k Shadow Damage. Targets highest threat. Has a splash effect, damaging anyone in 20 yards of the target. +#define SPELL_FLAME_BURST 41126 // Hurls fire at entire raid for ~3.5k damage every 10 seconds. Resistable. (Does not work: Script effect) +#define SPELL_FLAME_BURST_EFFECT 41131 // The actual damage. Have each player cast it on itself (workaround) +// Other Illidan spells +#define SPELL_KNEEL 39656 // Before beginning encounter, this is how he appears (talking to skully). +#define SPELL_SHADOW_PRISON 40647 // Illidan casts this spell to immobilize entire raid when he summons Maiev. +#define SPELL_DEATH 41220 // This spell doesn't do anything except stun Illidan and set him on his knees. +#define SPELL_BERSERK 45078 // Damage increased by 500%, attack speed by 150% +#define SPELL_DUAL_WIELD 42459 +//Phase Normal spells +#define SPELL_FLAME_CRASH_EFFECT 40836 // Firey blue ring of circle that the other flame crash summons +#define SPELL_SUMMON_SHADOWDEMON 41117 // Summon four shadowfiends +#define SPELL_SHADOWFIEND_PASSIVE 41913 // Passive aura for shadowfiends +#define SPELL_SHADOW_DEMON_PASSIVE 41079 // Adds the "shadowform" aura to Shadow Demons. +#define SPELL_CONSUME_SOUL 41080 // Once the Shadow Demons reach their target, they use this to kill them +#define SPELL_PARALYZE 41083 // Shadow Demons cast this on their target +#define SPELL_PURPLE_BEAM 39123 // Purple Beam connecting Shadow Demon to their target +//Phase Flight spells +#define SPELL_AZZINOTH_CHANNEL 39857 // Glaives cast it on Flames. Not sure if this is the right spell. +#define SPELL_EYE_BLAST_TRIGGER 40017 // This summons Demon Form every few seconds and deals ~20k damage in its radius +#define SPELL_EYE_BLAST 39908 // This does the blue flamey animation. +#define SPELL_BLAZE_EFFECT 40610 // Green flame on the ground, triggers damage (5k) every few seconds +#define SPELL_BLAZE_SUMMON 40637 // Summons the Blaze creature +#define SPELL_DEMON_FIRE 40029 // Blue fire trail left by Eye Blast. Deals 2k per second if players stand on it. +#define SPELL_FLAME_BLAST 40631 // Flames of Azzinoth use this. Frontal cone AoE 7k-9k damage. +#define SPELL_CHARGE 41581 //40602 // Flames of Azzinoth charges whoever is too far from them. They enrage after this. For simplicity, we'll use the same enrage as Illidan. +#define SPELL_FLAME_ENRAGE 45078 +//Akama spells +#define SPELL_AKAMA_DOOR_CHANNEL 41268 // Akama's channel spell on the door before the Temple Summit +#define SPELL_DEATHSWORN_DOOR_CHANNEL 41269 // Olum and Udalo's channel spell on the door before the Temple Summit +#define SPELL_AKAMA_DOOR_FAIL 41271 // Not sure where this is really used... +#define SPELL_HEALING_POTION 40535 // Akama uses this to heal himself to full. +#define SPELL_CHAIN_LIGHTNING 40536 // 6938 to 8062 for 5 targets +//Maiev spells +#define SPELL_CAGE_TRAP_DUMMY 40761 // Put this in DB for cage trap GO. +#define SPELL_CAGED 40695 // Caged Trap triggers will cast this on Illidan if he is within 3 yards +#define SPELL_CAGE_TRAP_SUMMON 40694 // Summons a Cage Trap GO (bugged) on the ground along with a Cage Trap Disturb Trigger mob (working) +#define SPELL_CAGE_TRAP_BEAM 40713 // 8 Triggers on the ground in an octagon cast spells like this on Illidan 'caging him' +#define SPELL_TELEPORT_VISUAL 41232 // Teleport visual for Maiev +#define SPELL_SHADOW_STRIKE 40685 // 4375 to 5625 every 3 seconds for 12 seconds +#define SPELL_THROW_DAGGER 41152 // 5400 to 6600 damage, need dagger +#define SPELL_FAN_BLADES 39954 // bugged visual + +// Other defines +#define CENTER_X 676.740 +#define CENTER_Y 305.297 +#define CENTER_Z 353.192 + +#define FLAME_ENRAGE_DISTANCE 30 +#define FLAME_CHARGE_DISTANCE 50 + +#define EQUIP_ID_MAIN_HAND 32837 +#define EQUIP_ID_OFF_HAND 32838 + +/**** Creature Summon and Recognition IDs ****/ +enum CreatureEntry +{ + EMPTY = 0, + AKAMA = 22990, + ILLIDAN_STORMRAGE = 22917, + BLADE_OF_AZZINOTH = 22996, + FLAME_OF_AZZINOTH = 22997, + MAIEV_SHADOWSONG = 23197, + SHADOW_DEMON = 23375, + DEMON_FIRE = 23069, + FLAME_CRASH = 23336, + ILLIDAN_DOOR_TRIGGER = 23412, + SPIRIT_OF_OLUM = 23411, + SPIRIT_OF_UDALO = 23410, + ILLIDARI_ELITE = 23226, + PARASITIC_SHADOWFIEND = 23498, + CAGE_TRAP_TRIGGER = 23292, +}; + +/*** Phase Names ***/ +enum PhaseIllidan +{ + PHASE_ILLIDAN_NULL = 0, + PHASE_NORMAL = 1, + PHASE_FLIGHT = 2, + PHASE_NORMAL_2 = 3, + PHASE_DEMON = 4, + PHASE_NORMAL_MAIEV = 5, + PHASE_TALK_SEQUENCE = 6, + PHASE_FLIGHT_SEQUENCE = 7, + PHASE_TRANSFORM_SEQUENCE = 8, + PHASE_ILLIDAN_MAX = 9, +};//Maiev uses the same phase + +enum PhaseAkama +{ + PHASE_AKAMA_NULL = 0, + PHASE_CHANNEL = 1, + PHASE_WALK = 2, + PHASE_TALK = 3, + PHASE_FIGHT_ILLIDAN = 4, + PHASE_FIGHT_MINIONS = 5, + PHASE_RETURN = 6, +}; + +enum EventIllidan +{ + EVENT_NULL = 0, + EVENT_BERSERK = 1, + //normal phase + EVENT_TAUNT = 2, + EVENT_SHEAR = 3, + EVENT_FLAME_CRASH = 4, + EVENT_PARASITIC_SHADOWFIEND = 5, + EVENT_PARASITE_CHECK = 6, + EVENT_DRAW_SOUL = 7, + EVENT_AGONIZING_FLAMES = 8, + EVENT_TRANSFORM_NORMAL = 9, + EVENT_ENRAGE = 10, + //flight phase + EVENT_FIREBALL = 2, + EVENT_DARK_BARRAGE = 3, + EVENT_EYE_BLAST = 4, + EVENT_MOVE_POINT = 5, + //demon phase + EVENT_SHADOW_BLAST = 2, + EVENT_FLAME_BURST = 3, + EVENT_SHADOWDEMON = 4, + EVENT_TRANSFORM_DEMON = 5, + //sequence phase + EVENT_TALK_SEQUENCE = 2, + EVENT_FLIGHT_SEQUENCE = 2, + EVENT_TRANSFORM_SEQUENCE = 2, +}; + +enum EventMaiev +{ + EVENT_MAIEV_NULL = 0, + EVENT_MAIEV_STEALTH = 1, + EVENT_MAIEV_TAUNT = 2, + EVENT_MAIEV_SHADOW_STRIKE = 3, + EVENT_MAIEV_THROW_DAGGER = 4, + EVENT_MAIEV_TRAP = 4, +}; + +static EventIllidan MaxTimer[]= +{ + EVENT_NULL, + EVENT_DRAW_SOUL, + EVENT_MOVE_POINT, + EVENT_TRANSFORM_NORMAL, + EVENT_TRANSFORM_DEMON, + EVENT_ENRAGE, + EVENT_TALK_SEQUENCE, + EVENT_FLIGHT_SEQUENCE, + EVENT_TRANSFORM_SEQUENCE +}; + +struct Yells +{ + uint32 sound; + char* text; + uint32 pCreature, timer, emote; + bool Talk; +}; + +static Yells Conversation[]= +{ + {11463, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.", ILLIDAN_STORMRAGE, 8000, 0, true}, + {0, NULL, ILLIDAN_STORMRAGE, 5000, 396, true}, + {11389, "We've come to end your reign, Illidan. My people and all of Outland shall be free!", AKAMA, 7000, 25, true}, + {0, NULL, AKAMA, 5000, 66, true}, + {11464, "Boldly said. But I remain unconvinced.", ILLIDAN_STORMRAGE, 8000, 396, true}, + {11380, "The time has come! The moment is at hand!", AKAMA, 3000, 22, true}, + {0, NULL, AKAMA, 2000, 15, true}, + {11466, "You are not prepared!", ILLIDAN_STORMRAGE, 3000, 406, true}, + {0, NULL, EMPTY, 1000, 0, true}, + {0, NULL, EMPTY, 0, 0, false},//9 + {11476, "Is this it, mortals? Is this all the fury you can muster?", ILLIDAN_STORMRAGE, 8000, 0, true}, + {11491, "Their fury pales before mine, Illidan. We have some unsettled business between us.", MAIEV_SHADOWSONG, 8000, 5, true}, + {11477, "Maiev... How is this even possible?", ILLIDAN_STORMRAGE, 5000, 1, true}, + {11492, "Ah... my long hunt is finally over. Today, Justice will be done!", MAIEV_SHADOWSONG, 8000, 15, true}, + {11470, "Feel the hatred of ten thousand years!", ILLIDAN_STORMRAGE, 1000, 0, false},//14 + {11496, "Ahh... It is finished. You are beaten.", MAIEV_SHADOWSONG, 6000, 0, true},//15 + {11478, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..", ILLIDAN_STORMRAGE, 30000, 65, true}, // Emote dead for now. Kill him later + {11497, "He is right. I feel nothing... I am nothing... Farewell, champions.", MAIEV_SHADOWSONG, 9000, 0, true}, + {11498, NULL, MAIEV_SHADOWSONG, 5000, 0, true}, + {11498, NULL, EMPTY, 1000, 0, true},//19 Maiev disappear + {11387, "The Light will fill these dismal halls once again. I swear it.", AKAMA, 8000, 0, true}, + {0, NULL, EMPTY, 1000, 0, false}//21 +}; + +static Yells RandomTaunts[]= +{ + {11467, "I can feel your hatred.", ILLIDAN_STORMRAGE, 0, 0, false}, + {11468, "Give in to your fear!", ILLIDAN_STORMRAGE, 0, 0, false}, + {11469, "You know nothing of power!", ILLIDAN_STORMRAGE, 0, 0, false}, + {11471, "Such... arrogance!", ILLIDAN_STORMRAGE, 0, 0, false} +}; + +static Yells MaievTaunts[]= +{ + {11493, "That is for Naisha!", MAIEV_SHADOWSONG, 0, false}, + {11494, "Bleed as I have bled!", MAIEV_SHADOWSONG, 0, 0, false}, + {11495, "There shall be no prison for you this time!", MAIEV_SHADOWSONG, 0, 0, false}, + {11500, "Meet your end, demon!", MAIEV_SHADOWSONG, 0, 0, false} +}; + +struct Locations +{ + float x, y, z; +}; + +static Locations HoverPosition[]= +{ + {657, 340, 355}, + {657, 275, 355}, + {705, 275, 355}, + {705, 340, 355} +}; + +static Locations GlaivePosition[]= +{ + {695.105, 305.303, 354.256}, + {659.338, 305.303, 354.256},//the distance between two glaives is 36 + {700.105, 305.303, 354.256}, + {664.338, 305.303, 354.256} +}; + +static Locations EyeBlast[]= +{ + {677, 350, 354},//start point, pass through glaive point + {677, 260, 354} +}; + +static Locations AkamaWP[]= +{ + {770.01, 304.50, 312.29}, // Bottom of the first stairs, at the doors + {780.66, 304.50, 319.74}, // Top of the first stairs + {790.13, 319.68, 319.76}, // Bottom of the second stairs (left from the entrance) + {787.17, 347.38, 341.42}, // Top of the second stairs + {781.34, 350.31, 341.44}, // Bottom of the third stairs + {762.60, 361.06, 353.60}, // Top of the third stairs + {756.35, 360.52, 353.27}, // Before the door-thingy + {743.82, 342.21, 353.00}, // Somewhere further + {732.69, 305.13, 353.00}, // In front of Illidan - (8) + {738.11, 365.44, 353.00}, // in front of the door-thingy (the other one!) + {792.18, 366.62, 341.42}, // Down the first flight of stairs + {796.84, 304.89, 319.76}, // Down the second flight of stairs + {782.01, 304.55, 319.76} // Final location - back at the initial gates. This is where he will fight the minions! (12) +}; +// 755.762, 304.0747, 312.1769 -- This is where Akama should be spawned +static Locations SpiritSpawns[]= +{ + {755.5426, 309.9156, 312.2129}, + {755.5426, 298.7923, 312.0834} +}; + +struct Animation // For the demon transformation +{ + uint32 aura, unaura, timer, size, displayid, phase; + bool equip; +}; + +static Animation DemonTransformation[]= +{ + {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, true}, + {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, true}, + {0, 0, 3000, 1073741824, 21322, 6, false},//stunned, cannot cast demon form + {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, false}, + {SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 4, false}, + {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, false}, + {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, false}, + {0, SPELL_DEMON_FORM, 3000, 1069547520, 21135, 6, false}, + {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, true}, + {0, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 8, true} +}; + +#define EMOTE_SETS_GAZE_ON "sets its gaze on $N!" +#define EMOTE_UNABLE_TO_SUMMON "is unable to summon Maiev Shadowsong and enter Phase 4. Resetting Encounter." + +/************************************** Illidan's AI ***************************************/ +struct boss_illidan_stormrageAI : public ScriptedAI +{ + boss_illidan_stormrageAI(Creature* c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + DoCast(me, SPELL_DUAL_WIELD, true); + + SpellEntry *TempSpell = GET_SPELL(SPELL_SHADOWFIEND_PASSIVE); + if (TempSpell) + TempSpell->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends + } + + ScriptedInstance* pInstance; + + PhaseIllidan Phase; + EventIllidan Event; + uint32 Timer[EVENT_ENRAGE + 1]; + + uint32 TalkCount; + uint32 TransformCount; + uint32 FlightCount; + + uint32 HoverPoint; + + uint64 AkamaGUID; + uint64 MaievGUID; + uint64 FlameGUID[2]; + uint64 GlaiveGUID[2]; + + SummonList Summons; + + void Reset(); + + void JustSummoned(Creature* summon); + + void SummonedCreatureDespawn(Creature* summon) + { + if (summon->GetCreatureInfo()->Entry == FLAME_OF_AZZINOTH) + { + for (uint8 i = 0; i < 2; ++i) + if (summon->GetGUID() == FlameGUID[i]) + FlameGUID[i] = 0; + + if (!FlameGUID[0] && !FlameGUID[1] && Phase != PHASE_ILLIDAN_NULL) + { + me->InterruptNonMeleeSpells(true); + EnterPhase(PHASE_FLIGHT_SEQUENCE); + } + } + Summons.Despawn(summon); + } + + void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) + { + if (FlightCount == 7) //change hover point + { + if (me->getVictim()) + { + me->SetInFront(me->getVictim()); + me->StopMoving(); + } + EnterPhase(PHASE_FLIGHT); + } + else // handle flight sequence + Timer[EVENT_FLIGHT_SEQUENCE] = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + me->setActive(true); + DoZoneInCombat(); + } + + void AttackStart(Unit *who) + { + if (!who || Phase >= PHASE_TALK_SEQUENCE) + return; + + if (Phase == PHASE_FLIGHT || Phase == PHASE_DEMON) + AttackStartNoMove(who); + else + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit *) {} + + void JustDied(Unit * /*killer*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (!pInstance) + return; + + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, DONE); // Completed + + for (uint8 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L + 1; ++i) + pInstance->HandleGameObject(pInstance->GetData64(i), true); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) return; + // TODO: Find better way to handle emote + switch (urand(0,1)) + { + case 0: + me->MonsterYell(SAY_KILL1, LANG_UNIVERSAL, victim->GetGUID()); + DoPlaySoundToSet(me, SOUND_KILL1); + break; + case 1: + me->MonsterYell(SAY_KILL2, LANG_UNIVERSAL, victim->GetGUID()); + DoPlaySoundToSet(me, SOUND_KILL2); + break; + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = 0; + if (done_by->GetGUID() == MaievGUID) + done_by->AddThreat(me, -(3*(float)damage)/4); // do not let maiev tank him + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades! + { + if (!me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) + SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + else + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + } + } + + void DeleteFromThreatList(uint64 TargetGUID) + { + for (std::list::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) + { + if ((*itr)->getUnitGuid() == TargetGUID) + { + (*itr)->removeReference(); + break; + } + } + } + + void Talk(uint32 count) + { + Timer[EVENT_TALK_SEQUENCE] = Conversation[count].timer; + + Creature* pCreature = NULL; + if (Conversation[count].pCreature == ILLIDAN_STORMRAGE) + pCreature = me; + else if (Conversation[count].pCreature == AKAMA) + pCreature = (Unit::GetCreature((*me), AkamaGUID)); + else if (Conversation[count].pCreature == MAIEV_SHADOWSONG) + pCreature = (Unit::GetCreature((*me), MaievGUID)); + + if (pCreature) + { + if (Conversation[count].emote) + pCreature->HandleEmoteCommand(Conversation[count].emote); // Make the Creature do some animation! + if (Conversation[count].text) + pCreature->MonsterYell(Conversation[count].text, LANG_UNIVERSAL, 0); // Have the Creature yell out some text + if (Conversation[count].sound) + DoPlaySoundToSet(pCreature, Conversation[count].sound); // Play some sound on the creature + } + } + + void EnterPhase(PhaseIllidan NextPhase); + void CastEyeBlast(); + void SummonFlamesOfAzzinoth(); + void SummonMaiev(); + void HandleTalkSequence(); + void HandleFlightSequence() + { + switch(FlightCount) + { + case 1://lift off + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + me->StopMoving(); + me->MonsterYell(SAY_TAKEOFF, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_TAKEOFF); + Timer[EVENT_FLIGHT_SEQUENCE] = 3000; + break; + case 2://move to center + me->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); //+5, for SPELL_THROW_GLAIVE bug + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 3://throw one glaive + { + uint8 i=1; + Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Glaive) + { + GlaiveGUID[i] = Glaive->GetGUID(); + Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Glaive->SetDisplayId(11686); + Glaive->setFaction(me->getFaction()); + DoCast(Glaive, SPELL_THROW_GLAIVE2); + } + } + Timer[EVENT_FLIGHT_SEQUENCE] = 700; + break; + case 4://throw another + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + { + uint8 i=0; + Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Glaive) + { + GlaiveGUID[i] = Glaive->GetGUID(); + Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Glaive->SetDisplayId(11686); + Glaive->setFaction(me->getFaction()); + DoCast(Glaive, SPELL_THROW_GLAIVE, true); + } + } + Timer[EVENT_FLIGHT_SEQUENCE] = 5000; + break; + case 5://summon flames + SummonFlamesOfAzzinoth(); + Timer[EVENT_FLIGHT_SEQUENCE] = 3000; + break; + case 6://fly to hover point + me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 7://return to center + me->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 8://glaive return + for (uint8 i = 0; i < 2; ++i) + { + if (GlaiveGUID[i]) + { + Unit* Glaive = Unit::GetUnit((*me), GlaiveGUID[i]); + if (Glaive) + { + Glaive->CastSpell(me, SPELL_GLAIVE_RETURNS, false); // Make it look like the Glaive flies back up to us + Glaive->SetDisplayId(11686); // disappear but not die for now + } + } + } + Timer[EVENT_FLIGHT_SEQUENCE] = 2000; + break; + case 9://land + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->StopMoving(); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + for (uint8 i = 0; i < 2; ++i) + { + if (GlaiveGUID[i]) + { + if (GETUNIT(Glaive, GlaiveGUID[i])) + { + Glaive->SetVisibility(VISIBILITY_OFF); + Glaive->setDeathState(JUST_DIED); // Despawn the Glaive + } + GlaiveGUID[i] = 0; + } + } + Timer[EVENT_FLIGHT_SEQUENCE] = 2000; + break; + case 10://attack + DoResetThreat(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + EnterPhase(PHASE_NORMAL_2); + break; + default: + break; + } + ++FlightCount; + } + + void HandleTransformSequence() + { + if (DemonTransformation[TransformCount].unaura) + me->RemoveAurasDueToSpell(DemonTransformation[TransformCount].unaura); + + if (DemonTransformation[TransformCount].aura) + DoCast(me, DemonTransformation[TransformCount].aura, true); + + if (DemonTransformation[TransformCount].displayid) + me->SetDisplayId(DemonTransformation[TransformCount].displayid); // It's morphin time! + + if (DemonTransformation[TransformCount].equip) + { + // Requip warglaives if needed + SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + } + else + { + // Unequip warglaives if needed + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + } + + switch(TransformCount) + { + case 2: + DoResetThreat(); + break; + case 4: + EnterPhase(PHASE_DEMON); + break; + case 7: + DoResetThreat(); + break; + case 9: + if (MaievGUID) + EnterPhase(PHASE_NORMAL_MAIEV); // Depending on whether we summoned Maiev, we switch to either phase 5 or 3 + else + EnterPhase(PHASE_NORMAL_2); + break; + default: + break; + } + if (Phase == PHASE_TRANSFORM_SEQUENCE) + Timer[EVENT_TRANSFORM_SEQUENCE] = DemonTransformation[TransformCount].timer; + ++TransformCount; + } + + void UpdateAI(const uint32 diff) + { + if ((!UpdateVictim()) && Phase < PHASE_TALK_SEQUENCE) + return; + + Event = EVENT_NULL; + for (uint32 i = 1; i <= MaxTimer[Phase]; ++i) + { + if (Timer[i]) // Event is enabled + if (Timer[i] <= diff) + { + if (!Event) // No event with higher priority + Event = (EventIllidan)i; + } + else Timer[i] -= diff; + } + + switch(Phase) + { + case PHASE_NORMAL: + if (HPPCT(me) < 65) + EnterPhase(PHASE_FLIGHT_SEQUENCE); + break; + + case PHASE_NORMAL_2: + if (HPPCT(me) < 30) + EnterPhase(PHASE_TALK_SEQUENCE); + break; + + case PHASE_NORMAL_MAIEV: + if (HPPCT(me) < 1) + EnterPhase(PHASE_TALK_SEQUENCE); + break; + + case PHASE_TALK_SEQUENCE: + if (Event == EVENT_TALK_SEQUENCE) + HandleTalkSequence(); + break; + + case PHASE_FLIGHT_SEQUENCE: + if (Event == EVENT_FLIGHT_SEQUENCE) + HandleFlightSequence(); + break; + + case PHASE_TRANSFORM_SEQUENCE: + if (Event == EVENT_TRANSFORM_SEQUENCE) + HandleTransformSequence(); + break; + } + + if (me->IsNonMeleeSpellCasted(false)) + return; + + if (Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV && !me->HasAura(SPELL_CAGED)) + { + switch(Event) + { + //PHASE_NORMAL + case EVENT_BERSERK: + me->MonsterYell(SAY_ENRAGE, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_ENRAGE); + DoCast(me, SPELL_BERSERK, true); + Timer[EVENT_BERSERK] = 5000;//The buff actually lasts forever. + break; + + case EVENT_TAUNT: + { + uint32 random = rand()%4; + char* yell = RandomTaunts[random].text; + uint32 soundid = RandomTaunts[random].sound; + if (yell) + me->MonsterYell(yell, LANG_UNIVERSAL, 0); + if (soundid) + DoPlaySoundToSet(me, soundid); + } + Timer[EVENT_TAUNT] = 25000 + rand()%10000; + break; + + case EVENT_SHEAR: + // no longer exists in 3.0.2 + //DoCast(me->getVictim(), SPELL_SHEAR); + Timer[EVENT_SHEAR] = 25000 + (rand()%16 * 1000); + break; + + case EVENT_FLAME_CRASH: + DoCast(me->getVictim(), SPELL_FLAME_CRASH); + Timer[EVENT_FLAME_CRASH] = 30000 + rand()%10000; + break; + + case EVENT_PARASITIC_SHADOWFIEND: + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true)) + DoCast(pTarget, SPELL_PARASITIC_SHADOWFIEND, true); + Timer[EVENT_PARASITIC_SHADOWFIEND] = 35000 + rand()%10000; + } + break; + + case EVENT_PARASITE_CHECK: + Timer[EVENT_PARASITE_CHECK] = 0; + break; + + case EVENT_DRAW_SOUL: + DoCast(me->getVictim(), SPELL_DRAW_SOUL); + Timer[EVENT_DRAW_SOUL] = 50000 + rand()%10000; + break; + + //PHASE_NORMAL_2 + case EVENT_AGONIZING_FLAMES: + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES); + Timer[EVENT_AGONIZING_FLAMES] = 0; + break; + + case EVENT_TRANSFORM_NORMAL: + EnterPhase(PHASE_TRANSFORM_SEQUENCE); + break; + + //PHASE_NORMAL_MAIEV + case EVENT_ENRAGE: + DoCast(me, SPELL_ENRAGE); + Timer[EVENT_ENRAGE] = 0; + break; + + default: + break; + } + DoMeleeAttackIfReady(); + } + + if (Phase == PHASE_FLIGHT) + { + switch(Event) + { + case EVENT_FIREBALL: + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL); + Timer[EVENT_FIREBALL] = 3000; + break; + + case EVENT_DARK_BARRAGE: + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE); + Timer[EVENT_DARK_BARRAGE] = 0; + break; + + case EVENT_EYE_BLAST: + CastEyeBlast(); + Timer[EVENT_EYE_BLAST] = 0; + break; + + case EVENT_MOVE_POINT: + Phase = PHASE_FLIGHT_SEQUENCE; + Timer[EVENT_FLIGHT_SEQUENCE] = 0;//do not start Event when changing hover point + HoverPoint += (rand()%3 + 1); + if (HoverPoint > 3) + HoverPoint -= 4; + me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); + break; + + default: + break; + } + } + + if (Phase == PHASE_DEMON) + { + switch(Event) + { + case EVENT_SHADOW_BLAST: + me->GetMotionMaster()->Clear(false); + if (!me->IsWithinDistInMap(me->getVictim(), 50)||!me->IsWithinLOSInMap(me->getVictim())) + me->GetMotionMaster()->MoveChase(me->getVictim(), 30); + else + me->GetMotionMaster()->MoveIdle(); + DoCast(me->getVictim(), SPELL_SHADOW_BLAST); + Timer[EVENT_SHADOW_BLAST] = 4000; + break; + case EVENT_SHADOWDEMON: + DoCast(me, SPELL_SUMMON_SHADOWDEMON); + Timer[EVENT_SHADOWDEMON] = 0; + Timer[EVENT_FLAME_BURST] += 10000; + break; + case EVENT_FLAME_BURST: + DoCast(me, SPELL_FLAME_BURST); + Timer[EVENT_FLAME_BURST] = 15000; + break; + case EVENT_TRANSFORM_DEMON: + EnterPhase(PHASE_TRANSFORM_SEQUENCE); + break; + default: + break; + } + } + } +}; + +/********************************** End of Illidan AI ******************************************/ + +struct flame_of_azzinothAI : public ScriptedAI +{ + flame_of_azzinothAI(Creature *c) : ScriptedAI(c) {} + + uint32 FlameBlastTimer; + uint32 CheckTimer; + uint64 GlaiveGUID; + + void Reset() + { + FlameBlastTimer = 15000; + CheckTimer = 5000; + GlaiveGUID = 0; + } + + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + + void ChargeCheck() + { + Unit *pTarget = SelectTarget(SELECT_TARGET_FARTHEST, 0, 200, false); + if (pTarget && (!me->IsWithinCombatRange(pTarget, FLAME_CHARGE_DISTANCE))) + { + me->AddThreat(pTarget, 5000000.0f); + AttackStart(pTarget); + DoCast(pTarget, SPELL_CHARGE); + me->MonsterTextEmote(EMOTE_SETS_GAZE_ON, pTarget->GetGUID()); + } + } + + void EnrageCheck() + { + if (GETUNIT(Glaive, GlaiveGUID)) + { + if (!me->IsWithinDistInMap(Glaive, FLAME_ENRAGE_DISTANCE)) + { + Glaive->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_FLAME_ENRAGE, true); + DoResetThreat(); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget && pTarget->isAlive()) + { + me->AddThreat(me->getVictim(), 5000000.0f); + AttackStart(me->getVictim()); + } + } + else if (!me->HasAura(SPELL_AZZINOTH_CHANNEL)) + { + Glaive->CastSpell(me, SPELL_AZZINOTH_CHANNEL, false); + me->RemoveAurasDueToSpell(SPELL_FLAME_ENRAGE); + } + } + } + + void SetGlaiveGUID(uint64 guid){ GlaiveGUID = guid; } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (FlameBlastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BLAZE_SUMMON, true); //appear at victim + DoCast(me->getVictim(), SPELL_FLAME_BLAST); + FlameBlastTimer = 15000; //10000 is official-like? + DoZoneInCombat(); //in case someone is revived + } else FlameBlastTimer -= diff; + + if (CheckTimer <= diff) + { + ChargeCheck(); + EnrageCheck(); + CheckTimer = 1000; + } else CheckTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +/******* Functions and vars for Akama's AI ******/ +struct npc_akama_illidanAI : public ScriptedAI +{ + npc_akama_illidanAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + JustCreated = true; + } + bool JustCreated; + ScriptedInstance* pInstance; + + PhaseAkama Phase; + bool Event; + uint32 Timer; + + uint64 IllidanGUID; + uint64 ChannelGUID; + uint64 SpiritGUID[2]; + uint64 GateGUID; + uint64 DoorGUID[2]; + + uint32 ChannelCount; + uint32 WalkCount; + uint32 TalkCount; + uint32 Check_Timer; + + void Reset() + { + WalkCount = 0; + if (pInstance) + { + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); + + IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); + GateGUID = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_GATE); + DoorGUID[0] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_R); + DoorGUID[1] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_L); + + if (JustCreated)//close all doors at create + { + pInstance->HandleGameObject(GateGUID, false); + + for (uint8 i = 0; i < 2; ++i) + pInstance->HandleGameObject(DoorGUID[i], false); + //JustCreated = false; + }else + {//open all doors, raid wiped + pInstance->HandleGameObject(GateGUID, true); + WalkCount = 1;//skip first wp + for (uint8 i = 0; i < 2; ++i) + pInstance->HandleGameObject(DoorGUID[i], true); + } + } + else + { + IllidanGUID = 0; + GateGUID = 0; + DoorGUID[0] = 0; + DoorGUID[1] = 0; + } + + ChannelGUID = 0; + SpiritGUID[0] = 0; + SpiritGUID[1] = 0; + + Phase = PHASE_AKAMA_NULL; + Timer = 0; + + ChannelCount = 0; + TalkCount = 0; + Check_Timer = 5000; + + KillAllElites(); + + me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values.. + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->setActive(false); + me->SetVisibility(VISIBILITY_OFF); + } + + // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit + void EnterEvadeMode() + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void MovementInform(uint32 MovementType, uint32 /*Data*/) + { + if (MovementType == POINT_MOTION_TYPE) + Timer = 1; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage > me->GetHealth() || done_by->GetGUID() != IllidanGUID) + damage = 0; + } + + void KillAllElites() + { + std::list& threatList = me->getThreatManager().getThreatList(); + std::vector eliteList; + for (std::list::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->GetEntry() == ILLIDARI_ELITE) + eliteList.push_back(pUnit); + } + for (std::vector::const_iterator itr = eliteList.begin(); itr != eliteList.end(); ++itr) + (*itr)->setDeathState(JUST_DIED); + EnterEvadeMode(); + } + + void BeginTalk() + { + if (!pInstance) + return; + + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, IN_PROGRESS); + for (uint8 i = 0; i < 2; ++i) + pInstance->HandleGameObject(DoorGUID[i], false); + if (GETCRE(Illidan, IllidanGUID)) + { + Illidan->RemoveAurasDueToSpell(SPELL_KNEEL); + me->SetInFront(Illidan); + Illidan->SetInFront(me); + me->GetMotionMaster()->MoveIdle(); + Illidan->GetMotionMaster()->MoveIdle(); + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->AkamaGUID = me->GetGUID(); + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->EnterPhase(PHASE_TALK_SEQUENCE); + } + } + + void BeginChannel() + { + me->setActive(true); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + if (!JustCreated) + return; + float x, y, z; + if (GETGO(Gate, GateGUID)) + Gate->GetPosition(x, y, z); + else + return;//if door not spawned, don't crash server + + if (Creature* Channel = me->SummonCreature(ILLIDAN_DOOR_TRIGGER, x, y, z+5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) + { + ChannelGUID = Channel->GetGUID(); + Channel->SetDisplayId(11686); // Invisible but spell visuals can still be seen. + DoCast(Channel, SPELL_AKAMA_DOOR_FAIL); + } + + for (uint8 i = 0; i < 2; ++i) + if (Creature* Spirit = me->SummonCreature(i ? SPIRIT_OF_OLUM : SPIRIT_OF_UDALO, SpiritSpawns[i].x, SpiritSpawns[i].y, SpiritSpawns[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) + { + Spirit->SetVisibility(VISIBILITY_OFF); + SpiritGUID[i] = Spirit->GetGUID(); + } + } + + void BeginWalk() + { + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->SetSpeed(MOVE_RUN, 1.0f); + me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); + } + + void EnterPhase(PhaseAkama NextPhase) + { + if (!pInstance) + return; + switch(NextPhase) + { + case PHASE_CHANNEL: + BeginChannel(); + Timer = 5000; + ChannelCount = 0; + break; + case PHASE_WALK: + if (Phase == PHASE_CHANNEL) + WalkCount = 0; + else if (Phase == PHASE_TALK) + { + if (GETCRE(Illidan, IllidanGUID)) + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); + EnterEvadeMode(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + ++WalkCount; + } + JustCreated = false; + BeginWalk(); + Timer = 0; + break; + case PHASE_TALK: + if (Phase == PHASE_WALK) + { + BeginTalk(); + Timer = 0; + } + else if (Phase == PHASE_FIGHT_ILLIDAN) + { + Timer = 1; + TalkCount = 0; + } + break; + case PHASE_FIGHT_ILLIDAN: + if (GETUNIT(Illidan, IllidanGUID)) + { + me->AddThreat(Illidan, 10000000.0f); + me->GetMotionMaster()->MoveChase(Illidan); + } + Timer = 30000; //chain lightning + break; + case PHASE_FIGHT_MINIONS: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Timer = 10000 + rand()%6000;//summon minion + break; + case PHASE_RETURN: + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + KillAllElites(); + WalkCount = 0; + BeginWalk(); + Timer = 1; + break; + default: + break; + } + Phase = NextPhase; + Event = false; + } + + void HandleTalkSequence() + { + switch(TalkCount) + { + case 0: + if (GETCRE(Illidan, IllidanGUID)) + { + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->Timer[EVENT_TAUNT] += 30000; + Illidan->MonsterYell(SAY_AKAMA_MINION, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(Illidan, SOUND_AKAMA_MINION); + } + Timer = 8000; + break; + case 1: + me->MonsterYell(SAY_AKAMA_LEAVE, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_AKAMA_LEAVE); + Timer = 3000; + break; + case 2: + EnterPhase(PHASE_WALK); + break; + } + ++TalkCount; + } + + void HandleChannelSequence() + { + Unit* Channel = NULL, *Spirit[2]; + if (ChannelCount <= 5) + { + Channel = Unit::GetUnit((*me), ChannelGUID); + Spirit[0] = Unit::GetUnit((*me), SpiritGUID[0]); + Spirit[1] = Unit::GetUnit((*me), SpiritGUID[1]); + if (!Channel || !Spirit[0] || !Spirit[1]) + return; + } + + switch(ChannelCount) + { + case 0: // channel failed + me->InterruptNonMeleeSpells(true); + Timer = 2000; + break; + case 1: // spirit appear + Spirit[0]->SetVisibility(VISIBILITY_ON); + Spirit[1]->SetVisibility(VISIBILITY_ON); + Timer = 2000; + break; + case 2: // spirit help + DoCast(Channel, SPELL_AKAMA_DOOR_CHANNEL); + Spirit[0]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); + Spirit[1]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); + Timer = 5000; + break; + case 3: //open the gate + me->InterruptNonMeleeSpells(true); + Spirit[0]->InterruptNonMeleeSpells(true); + Spirit[1]->InterruptNonMeleeSpells(true); + if (pInstance) + pInstance->HandleGameObject(GateGUID, true); + Timer = 2000; + break; + case 4: + me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + Timer = 2000; + break; + case 5: + me->MonsterYell(SAY_AKAMA_BEWARE, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_AKAMA_BEWARE); + Channel->setDeathState(JUST_DIED); + Spirit[0]->SetVisibility(VISIBILITY_OFF); + Spirit[1]->SetVisibility(VISIBILITY_OFF); + Timer = 3000; + break; + case 6: + EnterPhase(PHASE_WALK); + break; + default: + break; + } + ++ChannelCount; + } + + void HandleWalkSequence() + { + switch(WalkCount) + { + case 6: + for (uint8 i = 0; i < 2; ++i) + if (pInstance) + pInstance->HandleGameObject(DoorGUID[i], true); + break; + case 8: + if (Phase == PHASE_WALK) + EnterPhase(PHASE_TALK); + else + EnterPhase(PHASE_FIGHT_ILLIDAN); + break; + case 12: + EnterPhase(PHASE_FIGHT_MINIONS); + break; + } + + if (Phase == PHASE_WALK) + { + Timer = 0; + ++WalkCount; + me->GetMotionMaster()->MovePoint(WalkCount, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); + } + } + + void UpdateAI(const uint32 diff) + { + if (me->GetVisibility() == VISIBILITY_OFF) + { + if (Check_Timer <= diff) + { + if (pInstance && pInstance->GetData(DATA_ILLIDARICOUNCILEVENT) == DONE) + me->SetVisibility(VISIBILITY_ON); + + Check_Timer = 5000; + } else Check_Timer -= diff; + } + Event = false; + if (Timer) + { + if (Timer <= diff) + Event = true; + else Timer -= diff; + } + + if (Event) + { + switch(Phase) + { + case PHASE_CHANNEL: + if (JustCreated) + HandleChannelSequence(); + else{ + EnterPhase(PHASE_WALK); + } + break; + case PHASE_TALK: + HandleTalkSequence(); + break; + case PHASE_WALK: + case PHASE_RETURN: + HandleWalkSequence(); + break; + case PHASE_FIGHT_ILLIDAN: + { + GETUNIT(Illidan, IllidanGUID); + if (Illidan && HPPCT(Illidan) < 90) + EnterPhase(PHASE_TALK); + else + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); + Timer = 30000; + } + } + break; + case PHASE_FIGHT_MINIONS: + { + float x, y, z; + me->GetPosition(x, y, z); + Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); + //Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); + if (Elite) + { + Elite->AI()->AttackStart(me); + Elite->AddThreat(me, 1000000.0f); + AttackStart(Elite); + me->AddThreat(Elite, 1000000.0f); + } + Timer = 10000 + rand()%6000; + GETUNIT(Illidan, IllidanGUID); + if (Illidan && HPPCT(Illidan) < 10) + EnterPhase(PHASE_RETURN); + } + break; + default: + break; + } + } + + if (!UpdateVictim()) + return; + + if (me->GetHealth()*100 / me->GetMaxHealth() < 20) + DoCast(me, SPELL_HEALING_POTION); + + DoMeleeAttackIfReady(); + } +}; + +struct boss_maievAI : public ScriptedAI +{ + boss_maievAI(Creature *c) : ScriptedAI(c) {}; + + uint64 IllidanGUID; + + PhaseIllidan Phase; + EventMaiev Event; + uint32 Timer[5]; + uint32 MaxTimer; + + void Reset() + { + MaxTimer = 0; + Phase = PHASE_NORMAL_MAIEV; + IllidanGUID = 0; + Timer[EVENT_MAIEV_STEALTH] = 0; + Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; + Timer[EVENT_MAIEV_SHADOW_STRIKE] = 30000; + SetEquipmentSlots(false, 44850, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, 45738); + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + void EnterEvadeMode() {} + void GetIllidanGUID(uint64 guid) { IllidanGUID = guid; } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != IllidanGUID) + damage = 0; + else + { + GETUNIT(Illidan, IllidanGUID); + if (Illidan && Illidan->getVictim() == me) + damage = me->GetMaxHealth()/10; + if (damage >= me->GetHealth()) + damage = 0; + } + } + + void AttackStart(Unit *who) + { + if (!who || Timer[EVENT_MAIEV_STEALTH]) + return; + + if (Phase == PHASE_TALK_SEQUENCE) + AttackStartNoMove(who); + else if (Phase == PHASE_DEMON || Phase == PHASE_TRANSFORM_SEQUENCE) + { + GETUNIT(Illidan, IllidanGUID); + if (Illidan && me->IsWithinDistInMap(Illidan, 25)) + BlinkToPlayer();//Do not let dread aura hurt her. + AttackStartNoMove(who); + } + else + ScriptedAI::AttackStart(who); + } + + void DoAction(const int32 param) + { + if (param > PHASE_ILLIDAN_NULL && param < PHASE_ILLIDAN_MAX) + EnterPhase(PhaseIllidan(param)); + } + + void EnterPhase(PhaseIllidan NextPhase)//This is in fact Illidan's phase. + { + switch(NextPhase) + { + case PHASE_TALK_SEQUENCE: + if (Timer[EVENT_MAIEV_STEALTH]) + { + me->SetHealth(me->GetMaxHealth()); + me->SetVisibility(VISIBILITY_ON); + Timer[EVENT_MAIEV_STEALTH] = 0; + } + me->InterruptNonMeleeSpells(false); + me->GetMotionMaster()->Clear(false); + me->AttackStop(); + me->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); + MaxTimer = 0; + break; + case PHASE_TRANSFORM_SEQUENCE: + MaxTimer = 4; + Timer[EVENT_MAIEV_TAUNT] += 10000; + Timer[EVENT_MAIEV_THROW_DAGGER] = 2000; + break; + case PHASE_DEMON: + break; + case PHASE_NORMAL_MAIEV: + MaxTimer = 4; + Timer[EVENT_MAIEV_TAUNT] += 10000; + Timer[EVENT_MAIEV_TRAP] = 22000; + break; + default: + break; + } + if (Timer[EVENT_MAIEV_STEALTH]) + MaxTimer = 1; + Phase = NextPhase; + } + + void BlinkTo(float x, float y, float z) + { + me->AttackStop(); + me->InterruptNonMeleeSpells(false); + me->GetMotionMaster()->Clear(false); + DoTeleportTo(x, y, z); + DoCast(me, SPELL_TELEPORT_VISUAL, true); + } + + void BlinkToPlayer() + { + if (GETCRE(Illidan, IllidanGUID)) + { + Unit *pTarget = CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (!pTarget || !me->IsWithinDistInMap(pTarget, 80) || Illidan->IsWithinDistInMap(pTarget, 20)) + { + uint8 pos = rand()%4; + BlinkTo(HoverPosition[pos].x, HoverPosition[pos].y, HoverPosition[pos].z); + } + else + { + float x, y, z; + pTarget->GetPosition(x, y, z); + BlinkTo(x, y, z); + } + } + } + + void UpdateAI(const uint32 diff) + { + if ((!UpdateVictim()) + && !Timer[EVENT_MAIEV_STEALTH]) + return; + + Event = EVENT_MAIEV_NULL; + for (uint8 i = 1; i <= MaxTimer; ++i) + if (Timer[i]) + { + if (Timer[i] <= diff) + Event = (EventMaiev)i; + else Timer[i] -= diff; + } + + switch(Event) + { + case EVENT_MAIEV_STEALTH: + { + me->SetHealth(me->GetMaxHealth()); + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Timer[EVENT_MAIEV_STEALTH] = 0; + BlinkToPlayer(); + EnterPhase(Phase); + } + break; + case EVENT_MAIEV_TAUNT: + { + uint32 random = rand()%4; + char* text = MaievTaunts[random].text; + uint32 sound = MaievTaunts[random].sound; + me->MonsterYell(text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, sound); + Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; + } + break; + case EVENT_MAIEV_SHADOW_STRIKE: + DoCast(me->getVictim(), SPELL_SHADOW_STRIKE); + Timer[EVENT_MAIEV_SHADOW_STRIKE] = 60000; + break; + case EVENT_MAIEV_TRAP: + if (Phase == PHASE_NORMAL_MAIEV) + { + BlinkToPlayer(); + DoCast(me, SPELL_CAGE_TRAP_SUMMON); + Timer[EVENT_MAIEV_TRAP] = 22000; + } + else + { + if (!me->IsWithinDistInMap(me->getVictim(), 40)) + me->GetMotionMaster()->MoveChase(me->getVictim(), 30); + DoCast(me->getVictim(), SPELL_THROW_DAGGER); + Timer[EVENT_MAIEV_THROW_DAGGER] = 2000; + } + break; + default: + break; + } + + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (GETCRE(Illidan, IllidanGUID)) + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); + me->AttackStop(); + Timer[EVENT_MAIEV_STEALTH] = 60000; //reappear after 1 minute + MaxTimer = 1; + } + + if (Phase == PHASE_NORMAL_MAIEV) + DoMeleeAttackIfReady(); + } +}; + +bool GossipSelect_npc_akama_at_illidan(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) // Time to begin the Event + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_akama_illidanAI, pCreature->AI())->EnterPhase(PHASE_CHANNEL); + } + return true; +} + +bool GossipHello_npc_akama_at_illidan(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(10465, pCreature->GetGUID()); + + return true; +} + +struct cage_trap_triggerAI : public ScriptedAI +{ + cage_trap_triggerAI(Creature *c) : ScriptedAI(c) {} + + uint64 IllidanGUID; + uint32 DespawnTimer; + + bool Active; + bool SummonedBeams; + + void Reset() + { + IllidanGUID = 0; + + Active = false; + SummonedBeams = false; + + DespawnTimer = 0; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/){} + + void MoveInLineOfSight(Unit *who) + { + if (!Active) + return; + + if (who && (who->GetTypeId() != TYPEID_PLAYER)) + { + if (who->GetEntry() == ILLIDAN_STORMRAGE) // Check if who is Illidan + { + if (!IllidanGUID && me->IsWithinDistInMap(who, 3) && (!who->HasAura(SPELL_CAGED))) + { + IllidanGUID = who->GetGUID(); + who->CastSpell(who, SPELL_CAGED, true); + DespawnTimer = 5000; + if (who->HasAura(SPELL_ENRAGE)) + who->RemoveAurasDueToSpell(SPELL_ENRAGE); // Dispel his enrage + //if (GameObject* CageTrap = pInstance->instance->GetGameObject(pInstance->GetData64(CageTrapGUID))) + // CageTrap->SetLootState(GO_JUST_DEACTIVATED); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (DespawnTimer) + if (DespawnTimer <= diff) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else DespawnTimer -= diff; + + //if (IllidanGUID && !SummonedBeams) + //{ + // if (Unit* Illidan = Unit::GetUnit(*me, IllidanGUID) + // { + // //TODO: Find proper spells and properly apply 'caged' Illidan effect + // } + //} + } +}; + +bool GOHello_cage_trap(Player* pPlayer, GameObject* pGo) +{ + float x, y, z; + pPlayer->GetPosition(x, y, z); + + // Grid search for nearest live Creature of entry 23304 within 10 yards + if (Creature* pTrigger = pGo->FindNearestCreature(23304, 10.0f)) + CAST_AI(cage_trap_triggerAI, pTrigger->AI())->Active = true; + pGo->SetGoState(GO_STATE_ACTIVE); + return true; +} + +struct shadow_demonAI : public ScriptedAI +{ + shadow_demonAI(Creature *c) : ScriptedAI(c) {} + + uint64 TargetGUID; + + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + + void Reset() + { + TargetGUID = 0; + DoCast(me, SPELL_SHADOW_DEMON_PASSIVE, true); + } + + void JustDied(Unit * /*killer*/) + { + if (Unit *pTarget = Unit::GetUnit((*me), TargetGUID)) + pTarget->RemoveAurasDueToSpell(SPELL_PARALYZE); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) return; + + if (me->getVictim()->GetTypeId() != TYPEID_PLAYER) return; // Only cast the below on players. + + if (!me->getVictim()->HasAura(SPELL_PARALYZE)) + { + TargetGUID = me->getVictim()->GetGUID(); + me->AddThreat(me->getVictim(), 10000000.0f); + DoCast(me->getVictim(), SPELL_PURPLE_BEAM, true); + DoCast(me->getVictim(), SPELL_PARALYZE, true); + } + // Kill our target if we're very close. + if (me->IsWithinDistInMap(me->getVictim(), 3)) + DoCast(me->getVictim(), SPELL_CONSUME_SOUL); + } +}; + +// Shadowfiends interact with Illidan, setting more targets in Illidan's hashmap +struct mob_parasitic_shadowfiendAI : public ScriptedAI +{ + mob_parasitic_shadowfiendAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint64 IllidanGUID; + uint32 CheckTimer; + + void Reset() + { + if (pInstance) + IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); + else + IllidanGUID = 0; + + CheckTimer = 5000; + DoCast(me, SPELL_SHADOWFIEND_PASSIVE, true); + } + + void EnterCombat(Unit* /*who*/) { DoZoneInCombat(); } + + void DoMeleeAttackIfReady() + { + if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim())) + { + if (!me->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND) + && !me->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) + { + if (Creature* illidan = Unit::GetCreature((*me),IllidanGUID))//summon only in 1. phase + if (CAST_AI(boss_illidan_stormrageAI, illidan->AI())->Phase == PHASE_NORMAL) + me->CastSpell(me->getVictim(), SPELL_PARASITIC_SHADOWFIEND2, true, 0, 0, IllidanGUID); //do not stack + } + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->getVictim()) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) + AttackStart(pTarget); + else + { + me->SetVisibility(VISIBILITY_OFF); + me->setDeathState(JUST_DIED); + return; + } + } + + if (CheckTimer <= diff) + { + GETUNIT(Illidan, IllidanGUID); + if (!Illidan || CAST_CRE(Illidan)->IsInEvadeMode()) + { + me->SetVisibility(VISIBILITY_OFF); + me->setDeathState(JUST_DIED); + return; + } else CheckTimer = 5000; + } else CheckTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct blade_of_azzinothAI : public NullCreatureAI +{ + blade_of_azzinothAI(Creature* c) : NullCreatureAI(c) {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_THROW_GLAIVE2 || spell->Id == SPELL_THROW_GLAIVE) + me->SetDisplayId(21431);//appear when hit by Illidan's glaive + } +}; + +void boss_illidan_stormrageAI::Reset() +{ + if (pInstance) + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); + + if (AkamaGUID) + { + if (GETCRE(Akama, AkamaGUID)) + { + if (!Akama->isAlive()) + Akama->Respawn(); + else + { + CAST_AI(npc_akama_illidanAI, Akama->AI())->EnterEvadeMode(); + Akama->GetMotionMaster()->MoveTargetedHome(); + CAST_AI(npc_akama_illidanAI, Akama->AI())->Reset(); + } + } + AkamaGUID = 0; + } + + MaievGUID = 0; + for (uint8 i = 0; i < 2; ++i) + { + FlameGUID[i] = 0; + GlaiveGUID[i] = 0; + } + + Phase = PHASE_ILLIDAN_NULL; + Event = EVENT_NULL; + Timer[EVENT_BERSERK] = 1500000; + + HoverPoint = 0; + TalkCount = 0; + FlightCount = 0; + TransformCount = 0; + + me->SetDisplayId(21135); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->setActive(false); + Summons.DespawnAll(); +} + +void boss_illidan_stormrageAI::JustSummoned(Creature* summon) +{ + Summons.Summon(summon); + switch(summon->GetEntry()) + { + case PARASITIC_SHADOWFIEND: + { + if (Phase == PHASE_TALK_SEQUENCE) + { + summon->SetVisibility(VISIBILITY_OFF); + summon->setDeathState(JUST_DIED); + return; + } + Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true); + if (!pTarget || pTarget->HasAura(SPELL_PARASITIC_SHADOWFIEND) + || pTarget->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true); + if (pTarget) + summon->AI()->AttackStart(pTarget); + } + break; + case SHADOW_DEMON: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) // only on players. + { + summon->AddThreat(pTarget, 5000000.0f); + summon->AI()->AttackStart(pTarget); + } + break; + case MAIEV_SHADOWSONG: + { + summon->SetVisibility(VISIBILITY_OFF); // Leave her invisible until she has to talk + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + MaievGUID = summon->GetGUID(); + CAST_AI(boss_maievAI, summon->AI())->GetIllidanGUID(me->GetGUID()); + summon->AI()->DoAction(PHASE_TALK_SEQUENCE); + } + break; + case FLAME_OF_AZZINOTH: + { + summon->AI()->AttackStart(summon->SelectNearestTarget(999)); + } + break; + default: + break; + } +} + +void boss_illidan_stormrageAI::HandleTalkSequence() +{ + switch(TalkCount) + { + case 0: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + break; + case 8: + // Equip our warglaives! + SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 9: + if (GETCRE(Akama, AkamaGUID)) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->AddThreat(Akama, 100.0f); + CAST_AI(npc_akama_illidanAI, Akama->AI())->EnterPhase(PHASE_FIGHT_ILLIDAN); + EnterPhase(PHASE_NORMAL); + } + break; + case 10: + SummonMaiev(); + break; + case 11: + if (GETUNIT(Maiev, MaievGUID)) + { + Maiev->SetVisibility(VISIBILITY_ON); // Maiev is now visible + Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); // onoz she looks like she teleported! + Maiev->SetInFront(me); // Have her face us + me->SetInFront(Maiev); // Face her, so it's not rude =P + Maiev->GetMotionMaster()->MoveIdle(); + me->GetMotionMaster()->MoveIdle(); + } + break; + case 14: + if (GETCRE(Maiev, MaievGUID)) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + Maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + Maiev->AddThreat(me, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE + Maiev->AI()->AttackStart(me); // Force Maiev to attack us. + EnterPhase(PHASE_NORMAL_MAIEV); + } + break; + case 15: + DoCast(me, SPELL_DEATH); // Animate his kneeling + stun him + Summons.DespawnAll(); + break; + case 17: + if (GETUNIT(Akama, AkamaGUID)) + { + if (!me->IsWithinDistInMap(Akama, 15)) + { + float x, y, z; + me->GetPosition(x, y, z); + x += 10; y += 10; + Akama->GetMotionMaster()->Clear(false); + //Akama->GetMotionMaster()->MoveIdle(); + Akama->GetMap()->CreatureRelocation(me, x, y, z, 0.0f); + Akama->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_NONE, 0);//Illidan must not die until Akama arrives. + Akama->GetMotionMaster()->MoveChase(me); + } + } + break; + case 19: // Make Maiev leave + if (GETUNIT(Maiev, MaievGUID)) + { + Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); + Maiev->setDeathState(JUST_DIED); + me->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); + } + break; + case 21: // Kill ourself. + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + break; + default: + break; + } + if (Phase == PHASE_TALK_SEQUENCE) + Talk(TalkCount); // This function does most of the talking + ++TalkCount; +} + +void boss_illidan_stormrageAI::CastEyeBlast() +{ + me->InterruptNonMeleeSpells(false); + + me->MonsterYell(SAY_EYE_BLAST, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_EYE_BLAST); + + float distx, disty, dist[2]; + for (uint8 i = 0; i < 2; ++i) + { + distx = EyeBlast[i].x - HoverPosition[HoverPoint].x; + disty = EyeBlast[i].y - HoverPosition[HoverPoint].y; + dist[i] = distx * distx + disty * disty; + } + Locations initial = EyeBlast[dist[0] < dist[1] ? 0 : 1]; + for (uint8 i = 0; i < 2; ++i) + { + distx = GlaivePosition[i].x - HoverPosition[HoverPoint].x; + disty = GlaivePosition[i].y - HoverPosition[HoverPoint].y; + dist[i] = distx * distx + disty * disty; + } + Locations final = GlaivePosition[dist[0] < dist[1] ? 0 : 1]; + + final.x = 2 * final.x - initial.x; + final.y = 2 * final.y - initial.y; + + Creature* Trigger = me->SummonCreature(23069, initial.x, initial.y, initial.z, 0, TEMPSUMMON_TIMED_DESPAWN, 13000); + if (!Trigger) return; + + Trigger->SetSpeed(MOVE_WALK, 3); + Trigger->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z); + + //Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetUInt64Value(UNIT_FIELD_TARGET, Trigger->GetGUID()); + DoCast(Trigger, SPELL_EYE_BLAST); +} + +void boss_illidan_stormrageAI::SummonFlamesOfAzzinoth() +{ + me->MonsterYell(SAY_SUMMONFLAMES, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_SUMMONFLAMES); + + for (uint8 i = 0; i < 2; ++i) + { + if (GETUNIT(Glaive, GlaiveGUID[i])) + { + Creature* Flame = me->SummonCreature(FLAME_OF_AZZINOTH, GlaivePosition[i+2].x, GlaivePosition[i+2].y, GlaivePosition[i+2].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + if (Flame) + { + Flame->setFaction(me->getFaction()); // Just in case the database has it as a different faction + Flame->SetMeleeDamageSchool(SPELL_SCHOOL_FIRE); + FlameGUID[i] = Flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase + CAST_AI(flame_of_azzinothAI, Flame->AI())->SetGlaiveGUID(GlaiveGUID[i]); + Glaive->CastSpell(Flame, SPELL_AZZINOTH_CHANNEL, false); // Glaives do some random Beam type channel on it. + } + } + } +} + +void boss_illidan_stormrageAI::SummonMaiev() +{ + DoCast(me, SPELL_SHADOW_PRISON, true); + DoCast(me, 40403, true); + if (!MaievGUID) // If Maiev cannot be summoned, reset the encounter and post some errors to the console. + { + EnterEvadeMode(); + me->MonsterTextEmote(EMOTE_UNABLE_TO_SUMMON, 0); + error_log("SD2 ERROR: Unable to summon Maiev Shadowsong (entry: 23197). Check your database to see if you have the proper SQL for Maiev Shadowsong (entry: 23197)"); + } +} + +void boss_illidan_stormrageAI::EnterPhase(PhaseIllidan NextPhase) +{ + DoZoneInCombat(); + switch(NextPhase) + { + case PHASE_NORMAL: + case PHASE_NORMAL_2: + case PHASE_NORMAL_MAIEV: + AttackStart(me->getVictim()); + Timer[EVENT_TAUNT] = 32000; + Timer[EVENT_SHEAR] = 10000 + rand()%15 * 1000; + Timer[EVENT_FLAME_CRASH] = 20000; + Timer[EVENT_PARASITIC_SHADOWFIEND] = 25000; + Timer[EVENT_PARASITE_CHECK] = 0; + Timer[EVENT_DRAW_SOUL] = 30000; + if (NextPhase == PHASE_NORMAL) + break; + Timer[EVENT_AGONIZING_FLAMES] = 35000; + Timer[EVENT_TRANSFORM_NORMAL] = 60000; + if (NextPhase == PHASE_NORMAL_2) + break; + Timer[EVENT_ENRAGE] = 30000 + rand()%10 * 1000; + break; + case PHASE_FLIGHT: + Timer[EVENT_FIREBALL] = 1000; + if (!(rand()%4)) + Timer[EVENT_DARK_BARRAGE] = 10000; + Timer[EVENT_EYE_BLAST] = 10000 + rand()%15 * 1000; + Timer[EVENT_MOVE_POINT] = 20000 + rand()%20 * 1000; + break; + case PHASE_DEMON: + Timer[EVENT_SHADOW_BLAST] = 1000; + Timer[EVENT_FLAME_BURST] = 10000; + Timer[EVENT_SHADOWDEMON] = 30000; + Timer[EVENT_TRANSFORM_DEMON] = 60000; + AttackStart(me->getVictim()); + break; + case PHASE_TALK_SEQUENCE: + Timer[EVENT_TALK_SEQUENCE] = 100; + me->RemoveAllAuras(); + me->InterruptNonMeleeSpells(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->Clear(false); + me->AttackStop(); + break; + case PHASE_FLIGHT_SEQUENCE: + if (Phase == PHASE_NORMAL) //lift off + { + FlightCount = 1; + Timer[EVENT_FLIGHT_SEQUENCE] = 1; + me->RemoveAllAuras(); + me->InterruptNonMeleeSpells(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->Clear(false); + me->AttackStop(); + } + else //land + Timer[EVENT_FLIGHT_SEQUENCE] = 2000; + break; + case PHASE_TRANSFORM_SEQUENCE: + if (Phase == PHASE_DEMON) + Timer[EVENT_TRANSFORM_SEQUENCE] = 500; + else + { + TransformCount = 0; + Timer[EVENT_TRANSFORM_SEQUENCE] = 500; + me->MonsterYell(SAY_MORPH, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_MORPH); + } + me->GetMotionMaster()->Clear(); + me->AttackStop(); + break; + default: + break; + } + if (MaievGUID) + { + GETCRE(Maiev, MaievGUID); + if (Maiev && Maiev->isAlive()) + Maiev->AI()->DoAction(NextPhase); + } + Phase = NextPhase; + Event = EVENT_NULL; +} + +CreatureAI* GetAI_boss_illidan_stormrage(Creature* pCreature) +{ + return new boss_illidan_stormrageAI (pCreature); +} + +CreatureAI* GetAI_npc_akama_at_illidan(Creature* pCreature) +{ + return new npc_akama_illidanAI(pCreature); +} + +CreatureAI* GetAI_boss_maiev(Creature* pCreature) +{ + return new boss_maievAI (pCreature); +} + +CreatureAI* GetAI_mob_flame_of_azzinoth(Creature* pCreature) +{ + return new flame_of_azzinothAI (pCreature); +} + +CreatureAI* GetAI_cage_trap_trigger(Creature* pCreature) +{ + return new cage_trap_triggerAI (pCreature); +} + +CreatureAI* GetAI_shadow_demon(Creature* pCreature) +{ + return new shadow_demonAI (pCreature); +} + +CreatureAI* GetAI_blade_of_azzinoth(Creature* pCreature) +{ + return new blade_of_azzinothAI (pCreature); +} + +CreatureAI* GetAI_parasitic_shadowfiend(Creature* pCreature) +{ + return new mob_parasitic_shadowfiendAI (pCreature); +} + +void AddSC_boss_illidan() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_illidan_stormrage"; + newscript->GetAI = &GetAI_boss_illidan_stormrage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_akama_illidan"; + newscript->GetAI = &GetAI_npc_akama_at_illidan; + newscript->pGossipHello = &GossipHello_npc_akama_at_illidan; + newscript->pGossipSelect = &GossipSelect_npc_akama_at_illidan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_maiev_shadowsong"; + newscript->GetAI = &GetAI_boss_maiev; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flame_of_azzinoth"; + newscript->GetAI = &GetAI_mob_flame_of_azzinoth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_blade_of_azzinoth"; + newscript->GetAI = &GetAI_blade_of_azzinoth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "gameobject_cage_trap"; + newscript->pGOHello = &GOHello_cage_trap; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_cage_trap_trigger"; + newscript->GetAI = &GetAI_cage_trap_trigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadow_demon"; + newscript->GetAI = &GetAI_shadow_demon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_parasitic_shadowfiend"; + newscript->GetAI = &GetAI_parasitic_shadowfiend; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp new file mode 100644 index 00000000000..5949fc46511 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp @@ -0,0 +1,302 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mother_Shahraz +SD%Complete: 80 +SDComment: Saber Lash missing, Fatal Attraction slightly incorrect; need to damage only if affected players are within range of each other +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +//Speech'n'Sounds +#define SAY_TAUNT1 -1564018 +#define SAY_TAUNT2 -1564019 +#define SAY_TAUNT3 -1564020 +#define SAY_AGGRO -1564021 +#define SAY_SPELL1 -1564022 +#define SAY_SPELL2 -1564023 +#define SAY_SPELL3 -1564024 +#define SAY_SLAY1 -1564025 +#define SAY_SLAY2 -1564026 +#define SAY_ENRAGE -1564027 +#define SAY_DEATH -1564028 + +//Spells +#define SPELL_BEAM_SINISTER 40859 +#define SPELL_BEAM_VILE 40860 +#define SPELL_BEAM_WICKED 40861 +#define SPELL_BEAM_SINFUL 40827 +#define SPELL_ATTRACTION 40871 +#define SPELL_SILENCING_SHRIEK 40823 +#define SPELL_ENRAGE 23537 +#define SPELL_SABER_LASH 40810//43267 +#define SPELL_SABER_LASH_IMM 43690 +#define SPELL_TELEPORT_VISUAL 40869 +#define SPELL_BERSERK 45078 + +uint32 PrismaticAuras[]= +{ + 40880, // Shadow + 40882, // Fire + 40883, // Nature + 40891, // Arcane + 40896, // Frost + 40897, // Holy +}; + +struct Locations +{ + float x,y,z; +}; + +static Locations TeleportPoint[]= +{ + {959.996, 212.576, 193.843}, + {932.537, 231.813, 193.838}, + {958.675, 254.767, 193.822}, + {946.955, 201.316, 192.535}, + {944.294, 149.676, 197.551}, + {930.548, 284.888, 193.367}, + {965.997, 278.398, 195.777} +}; + +struct boss_shahrazAI : public ScriptedAI +{ + boss_shahrazAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 TargetGUID[3]; + uint32 BeamTimer; + uint32 BeamCount; + uint32 CurrentBeam; + uint32 PrismaticShieldTimer; + uint32 FatalAttractionTimer; + uint32 FatalAttractionExplodeTimer; + uint32 ShriekTimer; + uint32 SaberTimer; + uint32 RandomYellTimer; + uint32 EnrageTimer; + uint32 ExplosionCount; + + bool Enraged; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, NOT_STARTED); + + for (uint8 i = 0; i<3; ++i) + TargetGUID[i] = 0; + + BeamTimer = 20000; // Timers may be incorrect + BeamCount = 0; + CurrentBeam = 0; // 0 - Sinister, 1 - Vile, 2 - Wicked, 3 - Sinful + PrismaticShieldTimer = 0; + FatalAttractionTimer = 60000; + FatalAttractionExplodeTimer = 70000; + ShriekTimer = 30000; + SaberTimer = 35000; + RandomYellTimer = 70000 + rand()%41 * 1000; + EnrageTimer = 600000; + ExplosionCount = 0; + + Enraged = false; + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, IN_PROGRESS); + + DoZoneInCombat(); + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + void TeleportPlayers() + { + uint32 random = rand()%7; + float X = TeleportPoint[random].x; + float Y = TeleportPoint[random].y; + float Z = TeleportPoint[random].z; + for (uint8 i = 0; i < 3; ++i) + { + Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + TargetGUID[i] = pUnit->GetGUID(); + pUnit->CastSpell(pUnit, SPELL_TELEPORT_VISUAL, true); + DoTeleportPlayer(pUnit, X, Y, Z, pUnit->GetOrientation()); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !Enraged) + { + Enraged = true; + DoCast(me, SPELL_ENRAGE, true); + DoScriptText(SAY_ENRAGE, me); + } + + //Randomly cast one beam. + if (BeamTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!pTarget || !pTarget->isAlive()) + return; + + BeamTimer = 9000; + + switch(CurrentBeam) + { + case 0: + DoCast(pTarget, SPELL_BEAM_SINISTER); + break; + case 1: + DoCast(pTarget, SPELL_BEAM_VILE); + break; + case 2: + DoCast(pTarget, SPELL_BEAM_WICKED); + break; + case 3: + DoCast(pTarget, SPELL_BEAM_SINFUL); + break; + } + ++BeamCount; + uint32 Beam = CurrentBeam; + if (BeamCount > 3) + while (CurrentBeam == Beam) + CurrentBeam = rand()%3; + + } else BeamTimer -= diff; + + // Random Prismatic Shield every 15 seconds. + if (PrismaticShieldTimer <= diff) + { + uint32 random = rand()%6; + if (PrismaticAuras[random]) + DoCast(me, PrismaticAuras[random]); + PrismaticShieldTimer = 15000; + } else PrismaticShieldTimer -= diff; + + // Select 3 random targets (can select same target more than once), teleport to a random location then make them cast explosions until they get away from each other. + if (FatalAttractionTimer <= diff) + { + ExplosionCount = 0; + + TeleportPlayers(); + + DoScriptText(RAND(SAY_SPELL2,SAY_SPELL3), me); + FatalAttractionExplodeTimer = 2000; + FatalAttractionTimer = 40000 + rand()%31 * 1000; + } else FatalAttractionTimer -= diff; + + if (FatalAttractionExplodeTimer <= diff) + { + // Just make them explode three times... they're supposed to keep exploding while they are in range, but it'll take too much code. I'll try to think of an efficient way for it later. + if (ExplosionCount < 3) + { + for (uint8 i = 0; i < 3; ++i) + { + Unit* pUnit = NULL; + if (TargetGUID[i]) + { + pUnit = Unit::GetUnit((*me), TargetGUID[i]); + if (pUnit) + pUnit->CastSpell(pUnit, SPELL_ATTRACTION, true); + TargetGUID[i] = 0; + } + } + + ++ExplosionCount; + FatalAttractionExplodeTimer = 1000; + } + else + { + FatalAttractionExplodeTimer = FatalAttractionTimer + 2000; + ExplosionCount = 0; + } + } else FatalAttractionExplodeTimer -= diff; + + if (ShriekTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCING_SHRIEK); + ShriekTimer = 25000+rand()%10 * 1000; + } else ShriekTimer -= diff; + + if (SaberTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SABER_LASH); + SaberTimer = 25000+rand()%10 * 1000; + } else SaberTimer -= diff; + + //Enrage + if (!me->HasAura(SPELL_BERSERK)) + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + DoScriptText(SAY_ENRAGE, me); + } else EnrageTimer -= diff; + + //Random taunts + if (RandomYellTimer <= diff) + { + DoScriptText(RAND(SAY_TAUNT1,SAY_TAUNT2,SAY_TAUNT3), me); + RandomYellTimer = 60000 + rand()%91 * 1000; + } else RandomYellTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shahraz(Creature* pCreature) +{ + return new boss_shahrazAI (pCreature); +} + +void AddSC_boss_mother_shahraz() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_mother_shahraz"; + newscript->GetAI = &GetAI_boss_shahraz; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp new file mode 100644 index 00000000000..3e019a8dc35 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp @@ -0,0 +1,690 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Reliquary_of_Souls +SD%Complete: 90 +SDComment: +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" +#include "Spell.h" + +//Sound'n'speech +//Suffering +#define SUFF_SAY_FREED -1564047 +#define SUFF_SAY_AGGRO -1564048 +#define SUFF_SAY_SLAY1 -1564049 +#define SUFF_SAY_SLAY2 -1564050 +#define SUFF_SAY_SLAY3 -1564051 +#define SUFF_SAY_RECAP -1564052 +#define SUFF_SAY_AFTER -1564053 +#define SUFF_EMOTE_ENRAGE -1564054 + +//Desire +#define DESI_SAY_FREED -1564055 +#define DESI_SAY_SLAY1 -1564056 +#define DESI_SAY_SLAY2 -1564057 +#define DESI_SAY_SLAY3 -1564058 +#define DESI_SAY_SPEC -1564059 +#define DESI_SAY_RECAP -1564060 +#define DESI_SAY_AFTER -1564061 + +//Anger +#define ANGER_SAY_FREED -1564062 +#define ANGER_SAY_FREED2 -1564063 +#define ANGER_SAY_SLAY1 -1564064 +#define ANGER_SAY_SLAY2 -1564065 +#define ANGER_SAY_SPEC -1564066 +#define ANGER_SAY_BEFORE -1564067 +#define ANGER_SAY_DEATH -1564068 + +//Spells +#define AURA_OF_SUFFERING 41292 +#define AURA_OF_SUFFERING_ARMOR 42017 // linked aura, need core support +#define ESSENCE_OF_SUFFERING_PASSIVE 41296 // periodic trigger 41294 +#define ESSENCE_OF_SUFFERING_PASSIVE2 41623 +#define SPELL_FIXATE_TARGET 41294 // dummy, select target +#define SPELL_FIXATE_TAUNT 41295 // force taunt +#define SPELL_ENRAGE 41305 +#define SPELL_SOUL_DRAIN 41303 + +#define AURA_OF_DESIRE 41350 +#define AURA_OF_DESIRE_DAMAGE 41352 +#define SPELL_RUNE_SHIELD 41431 +#define SPELL_DEADEN 41410 +#define SPELL_SOUL_SHOCK 41426 + +#define AURA_OF_ANGER 41337 +#define SPELL_SELF_SEETHE 41364 // force cast 41520 +#define SPELL_ENEMY_SEETHE 41520 +#define SPELL_SOUL_SCREAM 41545 +#define SPELL_SPITE_TARGET 41376 // cast 41377 after 6 sec +#define SPELL_SPITE_DAMAGE 41377 + +#define ENSLAVED_SOUL_PASSIVE 41535 +#define SPELL_SOUL_RELEASE 41542 +#define SPELL_SUBMERGE 37550 //dropout 'head' + +#define CREATURE_ENSLAVED_SOUL 23469 +#define NUMBER_ENSLAVED_SOUL 8 + +struct Position2d +{ + float x,y; +}; + +static Position2d Coords[]= +{ + {450.4, 212.3}, + {542.1, 212.3}, + {542.1, 168.3}, + {542.1, 137.4}, + {450.4, 137.4}, + {450.4, 168.3} +}; + +struct npc_enslaved_soulAI : public ScriptedAI +{ + npc_enslaved_soulAI(Creature *c) : ScriptedAI(c) {} + + uint64 ReliquaryGUID; + + void Reset() {ReliquaryGUID = 0;} + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, ENSLAVED_SOUL_PASSIVE, true); + DoZoneInCombat(); + } + + void JustDied(Unit *killer); +}; + +struct boss_reliquary_of_soulsAI : public ScriptedAI +{ + boss_reliquary_of_soulsAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EssenceGUID = 0; + } + + ScriptedInstance* pInstance; + + uint64 EssenceGUID; + + uint32 Phase; + uint32 Counter; + uint32 Timer; + + uint32 SoulCount; + uint32 SoulDeathCount; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, NOT_STARTED); + + if (EssenceGUID) + { + if (Creature* Essence = Unit::GetCreature(*me, EssenceGUID)) + { + Essence->ForcedDespawn(); + } + EssenceGUID = 0; + } + + Phase = 0; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + me->RemoveAurasDueToSpell(SPELL_SUBMERGE); + } + + void EnterCombat(Unit* who) + { + me->AddThreat(who, 10000.0f); + DoZoneInCombat(); + if (pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, IN_PROGRESS); + + Phase = 1; + Counter = 0; + Timer = 0; + } + + bool SummonSoul() + { + uint32 random = rand()%6; + float x = Coords[random].x; + float y = Coords[random].y; + Creature* Soul = me->SummonCreature(CREATURE_ENSLAVED_SOUL, x, y, me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0); + if (!Soul) return false; + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + CAST_AI(npc_enslaved_soulAI, Soul->AI())->ReliquaryGUID = me->GetGUID(); + Soul->AI()->AttackStart(pTarget); + } else EnterEvadeMode(); + return true; + } + + void MergeThreatList(Creature *pTarget) + { + if (!pTarget) + return; + + std::list& m_threatlist = pTarget->getThreatManager().getThreatList(); + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit) + { + DoModifyThreatPercent(pUnit, -100); + float threat = pTarget->getThreatManager().getThreat(pUnit); + me->AddThreat(pUnit, threat); // This makes it so that the unit has the same amount of threat in Reliquary's threatlist as in the target creature's (One of the Essences). + } + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!Phase) + return; + + if (me->getThreatManager().getThreatList().empty()) // Reset if event is begun and we don't have a threatlist + { + EnterEvadeMode(); + return; + } + + Creature* Essence = NULL; + if (EssenceGUID) + { + Essence = Unit::GetCreature(*me, EssenceGUID); + if (!Essence) + { + EnterEvadeMode(); + return; + } + } + + if (Timer <= diff) + { + switch(Counter) + { + case 0: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); // I R ANNNGRRRY! + DoStartNoMovement(me); + Timer = 3000; + break; + case 1: + Timer = 2800; + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_SUBMERGE); // Release the cube + DoCast(me, SPELL_SUBMERGE); + DoStartNoMovement(me); + break; + case 2: + Timer = 5000; + if (Creature* Summon = DoSpawnCreature(23417+Phase, 0, 0, 0, 0, TEMPSUMMON_DEAD_DESPAWN, 0)) + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED); // Ribs: open + Summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_TOPAGGRO, 0)); + EssenceGUID = Summon->GetGUID(); + DoStartNoMovement(me); + } else EnterEvadeMode(); + break; + case 3: + Timer = 1000; + if (Phase == 3) + { + if (!Essence->isAlive()) + DoCast(me, 7, true); + else return; + } + else + { + if (Essence->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + { + MergeThreatList(Essence); + Essence->RemoveAllAuras(); + Essence->DeleteThreatList(); + Essence->GetMotionMaster()->MoveFollow(me,0.0f,0.0f); + } else return; + } + break; + case 4: + Timer = 1500; + if (Essence->IsWithinDistInMap(me, 10)) + { + Essence->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); //rotate and disappear + Timer = 2000; + me->RemoveAurasDueToSpell(SPELL_SUBMERGE); + } + else + { + MergeThreatList(Essence); + Essence->RemoveAllAuras(); + Essence->DeleteThreatList(); + Essence->GetMotionMaster()->MoveFollow(me, 0, 0); + return; + } + break; + case 5: + if (Phase == 1) + { + DoScriptText(SUFF_SAY_AFTER, Essence); + } + else + { + DoScriptText(DESI_SAY_AFTER, Essence); + } + Essence->ForcedDespawn(); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE,0); + EssenceGUID = 0; + SoulCount = 0; + SoulDeathCount = 0; + Timer = 3000; + break; + case 6: + if (SoulCount < NUMBER_ENSLAVED_SOUL) + { + if (SummonSoul()) + ++SoulCount; + Timer = 500; + return; + } + break; + case 7: + if (SoulDeathCount >= SoulCount) + { + Counter = 1; + ++Phase; + Timer = 5000; + } + return; + default: + break; + } + ++Counter; + } else Timer -= diff; + } +}; + +struct boss_essence_of_sufferingAI : public ScriptedAI +{ + boss_essence_of_sufferingAI(Creature *c) : ScriptedAI(c) {} + + uint64 StatAuraGUID; + + uint32 AggroYellTimer; + uint32 FixateTimer; + uint32 EnrageTimer; + uint32 SoulDrainTimer; + uint32 AuraTimer; + + void Reset() + { + StatAuraGUID = 0; + + AggroYellTimer = 5000; + FixateTimer = 8000; + EnrageTimer = 30000; + SoulDrainTimer = 45000; + AuraTimer = 5000; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + damage = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->Yell(SUFF_SAY_RECAP,LANG_UNIVERSAL,0); + DoScriptText(SUFF_SAY_RECAP, me); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + { + DoScriptText(SUFF_SAY_FREED, me); + DoZoneInCombat(); + DoCast(me, AURA_OF_SUFFERING, true); // linked aura need core support + DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE, true); + DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE2, true); + } + else return; + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SUFF_SAY_SLAY1,SUFF_SAY_SLAY2,SUFF_SAY_SLAY3), me); + } + + void CastFixate() + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + if (m_threatlist.empty()) + return; // No point continuing if empty threatlist. + std::list targets; + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) // Only alive players + targets.push_back(pUnit); + } + if (targets.empty()) + return; // No targets added for some reason. No point continuing. + targets.sort(Trinity::ObjectDistanceOrderPred(me)); // Sort players by distance. + targets.resize(1); // Only need closest target. + Unit *pTarget = targets.front(); // Get the first target. + if (pTarget) + pTarget->CastSpell(me, SPELL_FIXATE_TAUNT, true); + DoResetThreat(); + me->AddThreat(pTarget,1000000); + } + + void UpdateAI(const uint32 diff) + { + if (me->isInCombat()) + { + //Supposed to be cast on nearest target + if (FixateTimer <= diff) + { + CastFixate(); + FixateTimer = 5000; + if (!(rand()%16)) + { + DoScriptText(SUFF_SAY_AGGRO, me); + } + } else FixateTimer -= diff; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_ENRAGE); + EnrageTimer = 60000; + DoScriptText(SUFF_EMOTE_ENRAGE, me); + } else EnrageTimer -= diff; + + if (SoulDrainTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SOUL_DRAIN); + SoulDrainTimer = 60000; + } else SoulDrainTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_essence_of_desireAI : public ScriptedAI +{ + boss_essence_of_desireAI(Creature *c) : ScriptedAI(c) {} + + uint32 RuneShieldTimer; + uint32 DeadenTimer; + uint32 SoulShockTimer; + + void Reset() + { + RuneShieldTimer = 60000; + DeadenTimer = 30000; + SoulShockTimer = 5000; + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_CONFUSE, true); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by == me) + return; + + if (damage >= me->GetHealth()) + { + damage = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoScriptText(SUFF_SAY_RECAP, me); + } + else + { + int32 bp0 = damage / 2; + me->CastCustomSpell(done_by, AURA_OF_DESIRE_DAMAGE, &bp0, NULL, NULL, true); + } + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)) + for (uint8 i = 0; i < 3; ++i) + if (spell->Effect[i] == SPELL_EFFECT_INTERRUPT_CAST) + if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_SOUL_SHOCK + || me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_DEADEN) + me->InterruptSpell(CURRENT_GENERIC_SPELL, false); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(DESI_SAY_FREED, me); + DoZoneInCombat(); + DoCast(me, AURA_OF_DESIRE, true); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(DESI_SAY_SLAY1,DESI_SAY_SLAY2,DESI_SAY_SLAY3), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (RuneShieldTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_RUNE_SHIELD, true); + SoulShockTimer += 2000; + DeadenTimer += 2000; + RuneShieldTimer = 60000; + } else RuneShieldTimer -= diff; + + if (SoulShockTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOUL_SHOCK); + SoulShockTimer = 5000; + } else SoulShockTimer -= diff; + + if (DeadenTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me->getVictim(), SPELL_DEADEN); + DeadenTimer = 25000 + rand()%10000; + if (!(rand()%2)) + { + DoScriptText(DESI_SAY_SPEC, me); + } + } else DeadenTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_essence_of_angerAI : public ScriptedAI +{ + boss_essence_of_angerAI(Creature *c) : ScriptedAI(c) {} + + uint64 AggroTargetGUID; + + uint32 CheckTankTimer; + uint32 SoulScreamTimer; + uint32 SpiteTimer; + + std::list SpiteTargetGUID; + + bool CheckedAggro; + + void Reset() + { + AggroTargetGUID = 0; + + CheckTankTimer = 5000; + SoulScreamTimer = 10000; + SpiteTimer = 30000; + + SpiteTargetGUID.clear(); + + CheckedAggro = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(ANGER_SAY_FREED,ANGER_SAY_FREED2), me); + + DoZoneInCombat(); + DoCast(me, AURA_OF_ANGER, true); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(ANGER_SAY_DEATH, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(ANGER_SAY_SLAY1,ANGER_SAY_SLAY2), me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!CheckedAggro) + { + AggroTargetGUID = me->getVictim()->GetGUID(); + CheckedAggro = true; + } + + if (CheckTankTimer <= diff) + { + if (me->getVictim()->GetGUID() != AggroTargetGUID) + { + DoScriptText(ANGER_SAY_BEFORE, me); + DoCast(me, SPELL_SELF_SEETHE, true); + AggroTargetGUID = me->getVictim()->GetGUID(); + } + CheckTankTimer = 2000; + } else CheckTankTimer -= diff; + + if (SoulScreamTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOUL_SCREAM); + SoulScreamTimer = 9000 + rand()%2000; + if (!(rand()%3)) + { + DoScriptText(ANGER_SAY_SPEC, me); + } + } else SoulScreamTimer -= diff; + + if (SpiteTimer <= diff) + { + DoCast(me, SPELL_SPITE_TARGET); + SpiteTimer = 30000; + DoScriptText(ANGER_SAY_SPEC, me); + } else SpiteTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void npc_enslaved_soulAI::JustDied(Unit * /*killer*/) +{ + if (ReliquaryGUID) + if (Creature *Reliquary = (Unit::GetCreature((*me), ReliquaryGUID))) + ++(CAST_AI(boss_reliquary_of_soulsAI, Reliquary->AI())->SoulDeathCount); + + DoCast(me, SPELL_SOUL_RELEASE, true); +} + +CreatureAI* GetAI_boss_reliquary_of_souls(Creature* pCreature) +{ + return new boss_reliquary_of_soulsAI (pCreature); +} + +CreatureAI* GetAI_boss_essence_of_suffering(Creature* pCreature) +{ + return new boss_essence_of_sufferingAI (pCreature); +} + +CreatureAI* GetAI_boss_essence_of_desire(Creature* pCreature) +{ + return new boss_essence_of_desireAI (pCreature); +} + +CreatureAI* GetAI_boss_essence_of_anger(Creature* pCreature) +{ + return new boss_essence_of_angerAI (pCreature); +} + +CreatureAI* GetAI_npc_enslaved_soul(Creature* pCreature) +{ + return new npc_enslaved_soulAI (pCreature); +} + +void AddSC_boss_reliquary_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_reliquary_of_souls"; + newscript->GetAI = &GetAI_boss_reliquary_of_souls; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_essence_of_suffering"; + newscript->GetAI = &GetAI_boss_essence_of_suffering; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_essence_of_desire"; + newscript->GetAI = &GetAI_boss_essence_of_desire; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_essence_of_anger"; + newscript->GetAI = &GetAI_boss_essence_of_anger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_enslaved_soul"; + newscript->GetAI = &GetAI_npc_enslaved_soul; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp new file mode 100644 index 00000000000..94f88d5715c --- /dev/null +++ b/src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp @@ -0,0 +1,871 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shade_of_Akama +SD%Complete: 90 +SDComment: Seems to be complete. +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +#define SAY_DEATH -1564013 +#define SAY_LOW_HEALTH -1564014 +// Ending cinematic text +#define SAY_FREE -1564015 +#define SAY_BROKEN_FREE_01 -1564016 +#define SAY_BROKEN_FREE_02 -1564017 + +#define GOSSIP_ITEM "We are ready to fight alongside you, Akama" + +struct Location +{ + float x, y, o, z; +}; + +static Location ChannelerLocations[]= +{ + {463.161285, 401.219757, 3.141592}, + {457.377625, 391.227661, 2.106461}, + {446.012421, 391.227661, 1.071904}, + {439.533783, 401.219757, 0.000000}, + {446.012421, 411.211853, 5.210546}, + {457.377625, 411.211853, 4.177494} +}; + +static Location SpawnLocations[]= +{ + {498.652740, 461.728119, 0}, + {498.505003, 339.619324, 0} +}; + +static Location AkamaWP[]= +{ + {482.352448, 401.162720, 0, 112.783928}, + {469.597443, 402.264404, 0, 118.537910} +}; + +static Location BrokenCoords[]= +{ + {541.375916, 401.439575, M_PI, 112.783997}, // The place where Akama channels + {534.130005, 352.394531, 2.164150, 112.783737}, // Behind a 'pillar' which is behind the east alcove + {499.621185, 341.534729, 1.652856, 112.783730}, // East Alcove + {499.151093, 461.036438, 4.770888, 112.78370}, // West Alcove +}; + +static Location BrokenWP[]= +{ + {492.491638, 400.744690, 3.122336, 112.783737}, + {494.335724, 382.221771, 2.676230, 112.783737}, + {489.555939, 373.507202, 2.416263, 112.783737}, + {491.136353, 427.868774, 3.519748, 112.783737}, +}; + +// Locations +#define Z1 118.543144 +#define Z2 120.783768 +#define Z_SPAWN 113.537949 +#define AGGRO_X 482.793182 +#define AGGRO_Y 401.270172 +#define AGGRO_Z 112.783928 +#define AKAMA_X 514.583984 +#define AKAMA_Y 400.601013 +#define AKAMA_Z 112.783997 + +// Spells +#define SPELL_VERTEX_SHADE_BLACK 39833 +#define SPELL_SHADE_SOUL_CHANNEL 40401 +#define SPELL_DESTRUCTIVE_POISON 40874 +#define SPELL_LIGHTNING_BOLT 42024 +#define SPELL_AKAMA_SOUL_CHANNEL 40447 +#define SPELL_AKAMA_SOUL_RETRIEVE 40902 +#define AKAMA_SOUL_EXPEL 40855 +#define SPELL_SHADE_SOUL_CHANNEL_2 40520 + +// Channeler entry +#define CREATURE_CHANNELER 23421 +#define CREATURE_SORCERER 23215 +#define CREATURE_DEFENDER 23216 +#define CREATURE_BROKEN 23319 + +const uint32 spawnEntries[4]= { 23523, 23318, 23524 }; + +struct mob_ashtongue_channelerAI : public ScriptedAI +{ + mob_ashtongue_channelerAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;} + + uint64 ShadeGUID; + + void Reset() {} + void JustDied(Unit* /*killer*/); + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +struct mob_ashtongue_sorcererAI : public ScriptedAI +{ + mob_ashtongue_sorcererAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;} + + uint64 ShadeGUID; + uint32 CheckTimer; + bool StartBanishing; + + void Reset() + { + StartBanishing = false; + CheckTimer = 5000; + } + + void JustDied(Unit* /*killer*/); + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (StartBanishing) + return; + + if (CheckTimer <= diff) + { + Creature* Shade = Unit::GetCreature((*me), ShadeGUID); + if (Shade && Shade->isAlive() && me->isAlive()) + { + if (me->IsWithinDist(Shade, 20,false)) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL, true); + DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL_2, true); + + StartBanishing = true; + } + } + CheckTimer = 2000; + } else CheckTimer -= diff; + } +}; + +struct boss_shade_of_akamaAI : public ScriptedAI +{ + boss_shade_of_akamaAI(Creature* c) : ScriptedAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + AkamaGUID = pInstance ? pInstance->GetData64(DATA_AKAMA_SHADE) : 0; + me->setActive(true);//if view distance is too low + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + ScriptedInstance* pInstance; + + std::list Channelers; + std::list Sorcerers; + uint64 AkamaGUID; + + uint32 SorcererCount; + uint32 DeathCount; + + uint32 ReduceHealthTimer; + uint32 SummonTimer; + uint32 ResetTimer; + uint32 DefenderTimer; // They are on a flat 15 second timer, independant of the other summon Creature timer. + + bool IsBanished; + bool HasKilledAkama; + bool reseting; + bool GridSearcherSucceeded; + bool HasKilledAkamaAndReseting; + SummonList summons; + + void Reset() + { + reseting = true; + HasKilledAkamaAndReseting = false; + + GridSearcherSucceeded = false; + + Sorcerers.clear(); + summons.DespawnAll();//despawn all adds + + if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) + { + Akama->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//turn gossip on so players can restart the event + if (Akama->isDead()) + { + Akama->Respawn();//respawn akama if dead + Akama->AI()->EnterEvadeMode(); + } + } + SorcererCount = 0; + DeathCount = 0; + + SummonTimer = 10000; + ReduceHealthTimer = 0; + ResetTimer = 60000; + DefenderTimer = 15000; + + IsBanished = true; + HasKilledAkama = false; + + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //me->GetMotionMaster()->Clear(); + //me->GetMotionMaster()->MoveIdle(); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); + + if (pInstance) + pInstance->SetData(DATA_SHADEOFAKAMAEVENT, NOT_STARTED); + + reseting = false; + } + void JustDied(Unit* /*killer*/) + { + summons.DespawnAll(); + } + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524) + summons.Summon(summon); + } + void SummonedCreatureDespawn(Creature *summon) + { + if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524) + summons.Despawn(summon); + } + + void MoveInLineOfSight(Unit * /*who*/) + { + if (!GridSearcherSucceeded) + { + FindChannelers(); + + if (!Channelers.empty()) + { + for (std::list::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) + { + Creature* Channeler = (Unit::GetCreature(*me, *itr)); + if (Channeler) + { + if (Channeler->isDead()) + { + Channeler->RemoveCorpse(); + Channeler->Respawn(); + } + + Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true); + Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL_2, true); + Channeler->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + GridSearcherSucceeded = true; + } + } + } else error_log("SD2 ERROR: No Channelers are stored in the list. This encounter will not work properly"); + } + } + + void AttackStart(Unit* who) + { + if (!who || IsBanished) return; + + if (who->isTargetableForAttack() && who != me) + DoStartMovement(who); + } + + void IncrementDeathCount(uint64 guid = 0) // If guid is set, will remove it from list of sorcerer + { + if (reseting) + return; + + debug_log("TSCR: Increasing Death Count for Shade of Akama encounter"); + ++DeathCount; + me->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2); + if (guid) + { + if (Sorcerers.empty()) + error_log("SD2 ERROR: Shade of Akama - attempt to remove guid %u from Sorcerers list but list is already empty", guid); + else Sorcerers.remove(guid); + } + } + + void SummonCreature() + { + uint32 random = rand()%2; + float X = SpawnLocations[random].x; + float Y = SpawnLocations[random].y; + // max of 6 sorcerers can be summoned + if ((rand()%3 == 0) && (DeathCount > 0) && (SorcererCount < 7)) + { + Creature* Sorcerer = me->SummonCreature(CREATURE_SORCERER, X, Y, Z_SPAWN, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + if (Sorcerer) + { + CAST_AI(mob_ashtongue_sorcererAI, Sorcerer->AI())->ShadeGUID = me->GetGUID(); + Sorcerer->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Sorcerer->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + Sorcerer->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + Sorcerers.push_back(Sorcerer->GetGUID()); + --DeathCount; + ++SorcererCount; + } + } + else + { + for (uint8 i = 0; i < 3; ++i) + { + Creature* Spawn = me->SummonCreature(spawnEntries[i], X, Y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); + if (Spawn) + { + Spawn->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Spawn->GetMotionMaster()->MovePoint(0, AGGRO_X, AGGRO_Y, AGGRO_Z); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + Spawn->AI()->AttackStart(pTarget); + } + } + } + } + + void FindChannelers() + { + std::list ChannelerList; + me->GetCreatureListWithEntryInGrid(ChannelerList,CREATURE_CHANNELER,50.0f); + + if (!ChannelerList.empty()) + { + for (std::list::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr) + { + CAST_AI(mob_ashtongue_channelerAI, (*itr)->AI())->ShadeGUID = me->GetGUID(); + Channelers.push_back((*itr)->GetGUID()); + debug_log("TSCR: Shade of Akama Grid Search found channeler %u. Adding to list", (*itr)->GetGUID()); + } + } + else error_log("SD2 ERROR: Grid Search was unable to find any channelers. Shade of Akama encounter will be buggy"); + } + + void SetSelectableChannelers() + { + if (Channelers.empty()) + { + error_log("SD2 ERROR: Channeler List is empty, Shade of Akama encounter will be buggy"); + return; + } + + for (std::list::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) + if (Creature* Channeler = (Unit::GetCreature(*me, *itr))) + Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void SetAkamaGUID(uint64 guid) { AkamaGUID = guid; } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + return; + + if (IsBanished) + { + // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check + if (me->getThreatManager().getThreatList().size() < 2) + { + EnterEvadeMode(); + return; + } + + if (DefenderTimer <= diff) + { + uint32 ran = rand()%2; + Creature* Defender = me->SummonCreature(CREATURE_DEFENDER, SpawnLocations[ran].x, SpawnLocations[ran].y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); + if (Defender) + { + Defender->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + bool move = true; + if (AkamaGUID) + { + if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) + { + float x, y, z; + Akama->GetPosition(x,y,z); + // They move towards AKama + Defender->GetMotionMaster()->MovePoint(0, x, y, z); + Defender->AI()->AttackStart(Akama); + } else move = false; + } else move = false; + if (!move) + Defender->GetMotionMaster()->MovePoint(0, AKAMA_X, AKAMA_Y, AKAMA_Z); + } + DefenderTimer = 15000; + } else DefenderTimer -= diff; + + if (SummonTimer <= diff) + { + SummonCreature(); + SummonTimer = 35000; + } else SummonTimer -= diff; + + if (DeathCount >= 6) + { + if (AkamaGUID) + { + Creature* Akama = Unit::GetCreature((*me), AkamaGUID); + if (Akama && Akama->isAlive()) + { + IsBanished = false; + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveChase(Akama); + Akama->GetMotionMaster()->Clear(); + // Shade should move to Akama, not the other way around + Akama->GetMotionMaster()->MoveIdle(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Crazy amount of threat + me->AddThreat(Akama, 10000000.0f); + Akama->AddThreat(me, 10000000.0f); + me->Attack(Akama, true); + Akama->Attack(me, true); + } + } + } + } + else // No longer banished, let's fight Akama now + { + if (ReduceHealthTimer <= diff) + { + if (AkamaGUID) + { + Creature* Akama = Unit::GetCreature((*me), AkamaGUID); + if (Akama && Akama->isAlive()) + { + //10 % less health every few seconds. + me->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + ReduceHealthTimer = 12000; + } + } + } else ReduceHealthTimer -= diff; + + if (HasKilledAkama) + { + if (!HasKilledAkamaAndReseting)//do not let players kill Shade if Akama is dead and Shade is waiting for ResetTimer!! event would bug + { + HasKilledAkamaAndReseting = true; + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(); + //me->SetHealth(me->GetMaxHealth()); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->MoveTargetedHome(); + } + if (ResetTimer <= diff) + { + EnterEvadeMode();// Reset a little while after killing Akama, evade and respawn Akama + return; + } else ResetTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + } +}; + +void mob_ashtongue_channelerAI::JustDied(Unit* /*killer*/) +{ + Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); + if (Shade && Shade->isAlive()) + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(); + else error_log("SD2 ERROR: Channeler dead but unable to increment DeathCount for Shade of Akama."); +} + +void mob_ashtongue_sorcererAI::JustDied(Unit* /*killer*/) +{ + Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); + if (Shade && Shade->isAlive()) + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(me->GetGUID()); + else error_log("SD2 ERROR: Sorcerer dead but unable to increment DeathCount for Shade of Akama."); +} + +struct npc_akamaAI : public ScriptedAI +{ + npc_akamaAI(Creature* c) : ScriptedAI(c), summons(me) + { + ShadeHasDied = false; + StartCombat = false; + pInstance = c->GetInstanceData(); + ShadeGUID = pInstance ? pInstance->GetData64(DATA_SHADEOFAKAMA) : NOT_STARTED; + me->setActive(true); + EventBegun = false; + CastSoulRetrieveTimer = 0; + SoulRetrieveTimer = 0; + SummonBrokenTimer = 0; + EndingTalkCount = 0; + WayPointId = 0; + BrokenSummonIndex = 0; + BrokenList.clear(); + HasYelledOnce = false; + } + + ScriptedInstance* pInstance; + + uint64 ShadeGUID; + + uint32 DestructivePoisonTimer; + uint32 LightningBoltTimer; + uint32 CheckTimer; + uint32 CastSoulRetrieveTimer; + uint32 SoulRetrieveTimer; + uint32 SummonBrokenTimer; + uint32 EndingTalkCount; + uint32 WayPointId; + uint32 BrokenSummonIndex; + + std::list BrokenList; + + bool EventBegun; + bool ShadeHasDied; + bool StartCombat; + bool HasYelledOnce; + SummonList summons; + + void Reset() + { + DestructivePoisonTimer = 15000; + LightningBoltTimer = 10000; + CheckTimer = 2000; + + if (!EventBegun) + { + me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has very very strange values + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + summons.DespawnAll(); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == CREATURE_BROKEN) + summons.Summon(summon); + } + void SummonedCreatureDespawn(Creature *summon) + { + if (summon->GetEntry() == CREATURE_BROKEN) + summons.Despawn(summon); + } + + void EnterCombat(Unit* /*who*/) {} + + void BeginEvent(Player* pl) + { + if (!pInstance) + return; + + ShadeGUID = pInstance->GetData64(DATA_SHADEOFAKAMA); + if (!ShadeGUID) + return; + + Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); + if (Shade) + { + pInstance->SetData(DATA_SHADEOFAKAMAEVENT, IN_PROGRESS); + // Prevent players from trying to restart event + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->SetAkamaGUID(me->GetGUID()); + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->SetSelectableChannelers(); + Shade->AddThreat(me, 1000000.0f); + me->CombatStart(Shade); + Shade->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + Shade->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (pl) Shade->AddThreat(pl, 1.0f); + DoZoneInCombat(Shade); + EventBegun = true; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + switch(id) + { + case 0: ++WayPointId; break; + + case 1: + if (Creature* Shade = Unit::GetCreature(*me, ShadeGUID)) + { + me->SetUInt64Value(UNIT_FIELD_TARGET, ShadeGUID); + DoCast(Shade, SPELL_AKAMA_SOUL_RETRIEVE); + EndingTalkCount = 0; + SoulRetrieveTimer = 16000; + } + break; + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + EventBegun = false; + ShadeHasDied = false; + StartCombat = false; + CastSoulRetrieveTimer = 0; + SoulRetrieveTimer = 0; + SummonBrokenTimer = 0; + EndingTalkCount = 0; + WayPointId = 0; + BrokenSummonIndex = 0; + BrokenList.clear(); + HasYelledOnce = false; + Creature* Shade = Unit::GetCreature((*me), ShadeGUID); + if (Shade && Shade->isAlive()) + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->HasKilledAkama = true; + summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!EventBegun) + return; + + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 15 && !HasYelledOnce) + { + DoScriptText(SAY_LOW_HEALTH, me); + HasYelledOnce = true; + } + + if (ShadeGUID && !StartCombat) + { + Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); + if (Shade && Shade->isAlive()) + { + if (CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IsBanished) + { + if (CastSoulRetrieveTimer <= diff) + { + DoCast(Shade, SPELL_AKAMA_SOUL_CHANNEL); + CastSoulRetrieveTimer = 500; + } else CastSoulRetrieveTimer -= diff; + } + else + { + me->InterruptNonMeleeSpells(false); + StartCombat = true; + } + } + } + + if (ShadeHasDied && (WayPointId == 1)) + { + if (pInstance) + pInstance->SetData(DATA_SHADEOFAKAMAEVENT, DONE); + me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[1].x, AkamaWP[1].y, AkamaWP[1].z); + ++WayPointId; + } + + if (!ShadeHasDied && StartCombat) + { + if (CheckTimer <= diff) + { + if (ShadeGUID) + { + Creature* Shade = Unit::GetCreature((*me), ShadeGUID); + if (Shade && !Shade->isAlive()) + { + ShadeHasDied = true; + WayPointId = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z); + } + if (Shade && Shade->isAlive()) + { + if (Shade->getThreatManager().getThreatList().size() < 2) + Shade->AI()->EnterEvadeMode(); + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + } + + if (SummonBrokenTimer && BrokenSummonIndex < 4) + { + if (SummonBrokenTimer <= diff) + { + for (uint8 i = 0; i < 4; ++i) + { + float x = BrokenCoords[BrokenSummonIndex].x + (i*5); + float y = BrokenCoords[BrokenSummonIndex].y + (1*5); + float z = BrokenCoords[BrokenSummonIndex].z; + float o = BrokenCoords[BrokenSummonIndex].o; + Creature* Broken = me->SummonCreature(CREATURE_BROKEN, x, y, z, o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000); + if (Broken) + { + float wx = BrokenWP[BrokenSummonIndex].x + (i*5); + float wy = BrokenWP[BrokenSummonIndex].y + (i*5); + float wz = BrokenWP[BrokenSummonIndex].z; + Broken->GetMotionMaster()->MovePoint(0, wx, wy, wz); + Broken->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + BrokenList.push_back(Broken->GetGUID()); + } + } + ++BrokenSummonIndex; + SummonBrokenTimer = 1000; + } else SummonBrokenTimer -= diff; + } + + if (SoulRetrieveTimer) + if (SoulRetrieveTimer <= diff) + { + switch(EndingTalkCount) + { + case 0: + me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + ++EndingTalkCount; + SoulRetrieveTimer = 2000; + SummonBrokenTimer = 1; + break; + case 1: + DoScriptText(SAY_FREE, me); + ++EndingTalkCount; + SoulRetrieveTimer = 25000; + break; + case 2: + if (!BrokenList.empty()) + { + bool Yelled = false; + for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if (Creature* pUnit = Unit::GetCreature(*me, *itr)) + { + if (!Yelled) + { + DoScriptText(SAY_BROKEN_FREE_01, pUnit); + Yelled = true; + } + pUnit->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + } + } + ++EndingTalkCount; + SoulRetrieveTimer = 1500; + break; + case 3: + if (!BrokenList.empty()) + { + for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if (Creature* pUnit = Unit::GetCreature(*me, *itr)) + // This is the incorrect spell, but can't seem to find the right one. + pUnit->CastSpell(pUnit, 39656, true); + } + ++EndingTalkCount; + SoulRetrieveTimer = 5000; + break; + case 4: + if (!BrokenList.empty()) + { + for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if (Creature* pUnit = Unit::GetCreature((*me), *itr)) + pUnit->MonsterYell(SAY_BROKEN_FREE_02, LANG_UNIVERSAL, 0); + } + SoulRetrieveTimer = 0; + break; + } + } else SoulRetrieveTimer -= diff; + + if (!UpdateVictim()) + return; + + if (DestructivePoisonTimer <= diff) + { + Creature* Shade = Unit::GetCreature((*me), ShadeGUID); + if (Shade && Shade->isAlive()) + DoCast(Shade, SPELL_DESTRUCTIVE_POISON); + DestructivePoisonTimer = 15000; + } else DestructivePoisonTimer -= diff; + + if (LightningBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); + LightningBoltTimer = 10000; + } else LightningBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shade_of_akama(Creature* pCreature) +{ + return new boss_shade_of_akamaAI (pCreature); +} + +CreatureAI* GetAI_mob_ashtongue_channeler(Creature* pCreature) +{ + return new mob_ashtongue_channelerAI (pCreature); +} + +CreatureAI* GetAI_mob_ashtongue_sorcerer(Creature* pCreature) +{ + return new mob_ashtongue_sorcererAI (pCreature); +} + +CreatureAI* GetAI_npc_akama_shade(Creature* pCreature) +{ + return new npc_akamaAI (pCreature); +} + +bool GossipSelect_npc_akama(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_akamaAI, pCreature->AI())->BeginEvent(pPlayer); + } + + return true; +} + +bool GossipHello_npc_akama(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->isAlive()) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + } + + return true; +} + +void AddSC_boss_shade_of_akama() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shade_of_akama"; + newscript->GetAI = &GetAI_boss_shade_of_akama; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ashtongue_channeler"; + newscript->GetAI = &GetAI_mob_ashtongue_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ashtongue_sorcerer"; + newscript->GetAI = &GetAI_mob_ashtongue_sorcerer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_akama_shade"; + newscript->GetAI = &GetAI_npc_akama_shade; + newscript->pGossipHello = &GossipHello_npc_akama; + newscript->pGossipSelect = &GossipSelect_npc_akama; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/boss_supremus.cpp b/src/server/scripts/Outland/black_temple/boss_supremus.cpp new file mode 100644 index 00000000000..bc1ea3ec673 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/boss_supremus.cpp @@ -0,0 +1,296 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Supremus +SD%Complete: 95 +SDComment: Need to implement molten punch +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +#define EMOTE_NEW_TARGET -1564010 +#define EMOTE_PUNCH_GROUND -1564011 //DoScriptText(EMOTE_PUNCH_GROUND, me); +#define EMOTE_GROUND_CRACK -1564012 + +//Spells +#define SPELL_MOLTEN_PUNCH 40126 +#define SPELL_HATEFUL_STRIKE 41926 +#define SPELL_MOLTEN_FLAME 40980 +#define SPELL_VOLCANIC_ERUPTION 40117 +#define SPELL_VOLCANIC_SUMMON 40276 +#define SPELL_BERSERK 45078 + +#define CREATURE_VOLCANO 23085 +#define CREATURE_STALKER 23095 + +#define PHASE_STRIKE 1 +#define PHASE_CHASE 2 + +#define EVENT_BERSERK 1 +#define EVENT_SWITCH_PHASE 2 +#define EVENT_FLAME 3 +#define EVENT_VOLCANO 4 +#define EVENT_SWITCH_TARGET 5 +#define EVENT_HATEFUL_STRIKE 6 + +#define GCD_CAST 1 + +struct molten_flameAI : public NullCreatureAI +{ + molten_flameAI(Creature *c) : NullCreatureAI(c) {} + + void InitializeAI() + { + float x, y, z; + me->GetNearPoint(me, x, y, z, 1, 100, M_PI*2*rand_norm()); + me->GetMotionMaster()->MovePoint(0, x, y, z); + me->SetVisibility(VISIBILITY_OFF); + me->CastSpell(me,SPELL_MOLTEN_FLAME,true); + } +}; + +struct boss_supremusAI : public ScriptedAI +{ + boss_supremusAI(Creature *c) : ScriptedAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + SummonList summons; + uint32 phase; + + void Reset() + { + if (pInstance) + { + if (me->isAlive()) + { + pInstance->SetData(DATA_SUPREMUSEVENT, NOT_STARTED); + //ToggleDoors(true); + } + //else ToggleDoors(false); + } + + phase = 0; + + events.Reset(); + summons.DespawnAll(); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_SUPREMUSEVENT, IN_PROGRESS); + + ChangePhase(); + events.ScheduleEvent(EVENT_BERSERK, 900000, GCD_CAST); + events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST); + } + + void ChangePhase() + { + if (!phase || phase == PHASE_CHASE) + { + phase = PHASE_STRIKE; + summons.DoAction(EVENT_VOLCANO, 0); + events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); + me->SetSpeed(MOVE_RUN, 1.2f); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); + } + else + { + phase = PHASE_CHASE; + events.ScheduleEvent(EVENT_VOLCANO, 5000, GCD_CAST, PHASE_CHASE); + events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); + me->SetSpeed(MOVE_RUN, 0.9f); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + DoResetThreat(); + DoZoneInCombat(); + events.SetPhase(phase); + events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000, GCD_CAST); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_SUPREMUSEVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GAMEOBJECT_SUPREMUS_DOORS), true); + } + summons.DespawnAll(); + } + + void JustSummoned(Creature *summon) {summons.Summon(summon);} + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + + Unit* CalculateHatefulStrikeTarget() + { + uint32 health = 0; + Unit *pTarget = NULL; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + std::list::const_iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && me->IsWithinMeleeRange(pUnit)) + { + if (pUnit->GetHealth() > health) + { + health = pUnit->GetHealth(); + pTarget = pUnit; + } + } + } + + return pTarget; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK, true); + break; + case EVENT_FLAME: + DoCast(me, SPELL_MOLTEN_PUNCH); + events.DelayEvents(1500, GCD_CAST); + events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST); + break; + case EVENT_HATEFUL_STRIKE: + if (Unit *pTarget = CalculateHatefulStrikeTarget()) + DoCast(pTarget, SPELL_HATEFUL_STRIKE); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); + break; + case EVENT_SWITCH_TARGET: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + { + DoResetThreat(); + me->AddThreat(pTarget, 5000000.0f); + DoScriptText(EMOTE_NEW_TARGET, me); + } + events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); + break; + case EVENT_VOLCANO: + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true); + if (!pTarget) pTarget = me->getVictim(); + if (pTarget) + { + //DoCast(pTarget, SPELL_VOLCANIC_SUMMON);//movement bugged + me->SummonCreature(CREATURE_VOLCANO,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); + DoScriptText(EMOTE_GROUND_CRACK, me); + events.DelayEvents(1500, GCD_CAST); + } + events.ScheduleEvent(EVENT_VOLCANO, 10000, GCD_CAST, PHASE_CHASE); + return; + } + case EVENT_SWITCH_PHASE: + ChangePhase(); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_volcanoAI : public Scripted_NoMovementAI +{ + npc_volcanoAI(Creature *c) : Scripted_NoMovementAI(c) {} + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //DoCast(me, SPELL_VOLCANIC_ERUPTION); + me->SetReactState(REACT_PASSIVE); + wait = 3000; + } + uint32 wait; + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void DoAction(const uint32 /*info*/) + { + me->RemoveAura(SPELL_VOLCANIC_ERUPTION); + } + + void UpdateAI(const uint32 diff) + { + if (wait <= diff)//wait 3secs before casting + { + DoCast(me, SPELL_VOLCANIC_ERUPTION); + wait = 60000; + } + else wait -= diff; + } + +}; + +CreatureAI* GetAI_boss_supremus(Creature* pCreature) +{ + return new boss_supremusAI (pCreature); +} + +CreatureAI* GetAI_molten_flame(Creature* pCreature) +{ + return new molten_flameAI (pCreature); +} + +CreatureAI* GetAI_npc_volcano(Creature* pCreature) +{ + return new npc_volcanoAI (pCreature); +} + +void AddSC_boss_supremus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_supremus"; + newscript->GetAI = &GetAI_boss_supremus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "molten_flame"; + newscript->GetAI = &GetAI_molten_flame; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_volcano"; + newscript->GetAI = &GetAI_npc_volcano; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp new file mode 100644 index 00000000000..670edc4d869 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp @@ -0,0 +1,508 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Teron_Gorefiend +SD%Complete: 60 +SDComment: Requires Mind Control support for Ghosts. +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + + //Speech'n'sound +#define SAY_INTRO -1564037 +#define SAY_AGGRO -1564038 +#define SAY_SLAY1 -1564039 +#define SAY_SLAY2 -1564040 +#define SAY_SPELL1 -1564041 +#define SAY_SPELL2 -1564042 +#define SAY_SPECIAL1 -1564043 +#define SAY_SPECIAL2 -1564044 +#define SAY_ENRAGE -1564045 +#define SAY_DEATH -1564046 + +//Spells +#define SPELL_INCINERATE 40239 +#define SPELL_CRUSHING_SHADOWS 40243 +#define SPELL_SHADOWBOLT 40185 +#define SPELL_PASSIVE_SHADOWFORM 40326 +#define SPELL_SHADOW_OF_DEATH 40251 +#define SPELL_BERSERK 45078 + +#define SPELL_ATROPHY 40327 // Shadowy Constructs use this when they get within melee range of a player + +#define CREATURE_DOOM_BLOSSOM 23123 +#define CREATURE_SHADOWY_CONSTRUCT 23111 + +struct mob_doom_blossomAI : public ScriptedAI +{ + mob_doom_blossomAI(Creature *c) : ScriptedAI(c) {} + + uint32 CheckTeronTimer; + uint32 ShadowBoltTimer; + uint64 TeronGUID; + + void Reset() + { + CheckTeronTimer = 5000; + ShadowBoltTimer = 12000; + TeronGUID = 0; + } + + void EnterCombat(Unit * /*who*/) { } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void Despawn() + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + } + + void UpdateAI(const uint32 diff) + { + if (CheckTeronTimer <= diff) + { + if (TeronGUID) + { + DoZoneInCombat(); + + Creature* Teron = (Unit::GetCreature((*me), TeronGUID)); + if ((Teron) && (!Teron->isAlive() || Teron->IsInEvadeMode())) + Despawn(); + } + else + Despawn(); + + CheckTeronTimer = 5000; + } else CheckTeronTimer -= diff; + + if (ShadowBoltTimer < diff && me->isInCombat()) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOWBOLT); + ShadowBoltTimer = 10000; + } else ShadowBoltTimer -= diff; + return; + } + + void SetTeronGUID(uint64 guid){ TeronGUID = guid; } +}; + +struct mob_shadowy_constructAI : public ScriptedAI +{ + mob_shadowy_constructAI(Creature* c) : ScriptedAI(c) {} + + uint64 GhostGUID; + uint64 TeronGUID; + + uint32 CheckPlayerTimer; + uint32 CheckTeronTimer; + + void Reset() + { + GhostGUID = 0; + TeronGUID = 0; + + CheckPlayerTimer = 2000; + CheckTeronTimer = 5000; + } + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (!who || (!who->isAlive()) || (who->GetGUID() == GhostGUID)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + +/* Comment it out for now. NOTE TO FUTURE DEV: UNCOMMENT THIS OUT ONLY AFTER MIND CONTROL IS IMPLEMENTED + void DamageTaken(Unit* done_by, uint32 &damage) + { + if (done_by->GetGUID() != GhostGUID) + damage = 0; // Only the ghost can deal damage. + } + */ + + void CheckPlayers() + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + if (m_threatlist.empty()) + return; // No threat list. Don't continue. + std::list::const_iterator itr = m_threatlist.begin(); + std::list targets; + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + targets.push_back(pUnit); + } + targets.sort(Trinity::ObjectDistanceOrderPred(me)); + Unit *pTarget = targets.front(); + if (pTarget && me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) + { + DoCast(pTarget, SPELL_ATROPHY); + me->AI()->AttackStart(pTarget); + } + } + + void UpdateAI(const uint32 diff) + { + if (CheckPlayerTimer <= diff) + { + CheckPlayers(); + CheckPlayerTimer = 3000; + } else CheckPlayerTimer -= diff; + + if (CheckTeronTimer <= diff) + { + Creature* Teron = (Unit::GetCreature((*me), TeronGUID)); + if (!Teron || !Teron->isAlive() || Teron->IsInEvadeMode()) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + CheckTeronTimer = 5000; + } else CheckTeronTimer -= diff; + } +}; + +struct boss_teron_gorefiendAI : public ScriptedAI +{ + boss_teron_gorefiendAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 IncinerateTimer; + uint32 SummonDoomBlossomTimer; + uint32 EnrageTimer; + uint32 CrushingShadowsTimer; + uint32 ShadowOfDeathTimer; + uint32 SummonShadowsTimer; + uint32 RandomYellTimer; + uint32 AggroTimer; + + uint64 AggroTargetGUID; + uint64 GhostGUID; // Player that gets killed by Shadow of Death and gets turned into a ghost + + bool Intro; + bool Done; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, NOT_STARTED); + + IncinerateTimer = 20000 + rand()%11000; + SummonDoomBlossomTimer = 12000; + EnrageTimer = 600000; + CrushingShadowsTimer = 22000; + SummonShadowsTimer = 60000; + RandomYellTimer = 50000; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Start off unattackable so that the intro is done properly + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + AggroTimer = 20000; + AggroTargetGUID = 0; + Intro = false; + Done = false; + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit* pWho) + { + if (!Intro && pWho->GetTypeId() == TYPEID_PLAYER && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && pWho->isInAccessiblePlaceFor(me)) + { + if (me->IsWithinDistInMap(pWho, VISIBLE_RANGE) && me->IsWithinLOSInMap(pWho)) + { + if (pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, IN_PROGRESS); + + me->GetMotionMaster()->Clear(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoScriptText(SAY_INTRO, me); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + AggroTargetGUID = pWho->GetGUID(); + Intro = true; + } + } + if (Done) + ScriptedAI::MoveInLineOfSight(pWho); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + float CalculateRandomLocation(float Loc, uint32 radius) + { + float coord = Loc; + switch (urand(0,1)) + { + case 0: + coord += rand()%radius; + break; + case 1: + coord -= rand()%radius; + break; + } + return coord; + } + + void SetThreatList(Creature* Blossom) + { + if (!Blossom) return; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + std::list::const_iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + { + float threat = DoGetThreat(pUnit); + Blossom->AddThreat(pUnit, threat); + } + } + } + + void MindControlGhost() + { + /************************************************************************/ + /** NOTE FOR FUTURE DEVELOPER: PROPERLY IMPLEMENT THE GHOST PORTION *****/ + /** ONLY AFTER TrinIty FULLY IMPLEMENTS MIND CONTROL ABILITIES *****/ + /** THE CURRENT CODE IN THIS FUNCTION IS ONLY THE BEGINNING OF *****/ + /** WHAT IS FULLY NECESSARY FOR GOREFIEND TO BE 100% COMPLETE *****/ + /************************************************************************/ + + Unit* Ghost = NULL; + if (GhostGUID) + Ghost = Unit::GetUnit((*me), GhostGUID); + if (Ghost && Ghost->isAlive() && Ghost->HasAura(SPELL_SHADOW_OF_DEATH)) + { + /*float x,y,z; + Ghost->GetPosition(x,y,z); + Creature* control = me->SummonCreature(CREATURE_GHOST, x, y, z, 0, TEMPSUMMON_TIMED_DESAWN, 30000); + if (control) + { + CAST_PLR(Ghost)->Possess(control); + Ghost->DealDamage(Ghost, Ghost->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, + false); + }*/ + for (uint8 i = 0; i < 4; ++i) + { + Creature* Construct = NULL; + float X = CalculateRandomLocation(Ghost->GetPositionX(), 10); + float Y = CalculateRandomLocation(Ghost->GetPositionY(), 10); + Construct = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, Y, Ghost->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + if (Construct) + { + Construct->CastSpell(Construct, SPELL_PASSIVE_SHADOWFORM, true); + SetThreatList(Construct); // Use same function as Doom Blossom to set Threat List. + CAST_AI(mob_shadowy_constructAI, Construct->AI())->GhostGUID = GhostGUID; + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) // someone's trying to solo. + pTarget = me->getVictim(); + + if (pTarget) + Construct->GetMotionMaster()->MoveChase(pTarget); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Intro && !Done) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoScriptText(SAY_AGGRO, me); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + Done = true; + if (AggroTargetGUID) + { + Unit* pUnit = Unit::GetUnit((*me), AggroTargetGUID); + if (pUnit) + AttackStart(pUnit); + + DoZoneInCombat(); + } + else + { + EnterEvadeMode(); + return; + } + } else AggroTimer -= diff; + } + + if (!UpdateVictim() || !Done) + return; + + if (SummonShadowsTimer <= diff) + { + //MindControlGhost(); + + for (uint8 i = 0; i < 2; ++i) + { + Creature* Shadow = NULL; + float X = CalculateRandomLocation(me->GetPositionX(), 10); + Shadow = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 0); + if (Shadow) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget) + Shadow->AI()->AttackStart(pTarget); + } + } + SummonShadowsTimer = 60000; + } else SummonShadowsTimer -= diff; + + if (SummonDoomBlossomTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float X = CalculateRandomLocation(pTarget->GetPositionX(), 20); + float Y = CalculateRandomLocation(pTarget->GetPositionY(), 20); + float Z = pTarget->GetPositionZ(); + Z = me->GetMap()->GetHeight(X, Y, Z); + Creature* DoomBlossom = me->SummonCreature(CREATURE_DOOM_BLOSSOM, X, Y, Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + if (DoomBlossom) + { + DoomBlossom->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoomBlossom->setFaction(me->getFaction()); + DoomBlossom->AddThreat(pTarget, 1.0f); + CAST_AI(mob_doom_blossomAI, DoomBlossom->AI())->SetTeronGUID(me->GetGUID()); + pTarget->CombatStart(DoomBlossom); + SetThreatList(DoomBlossom); + SummonDoomBlossomTimer = 35000; + } + } + } else SummonDoomBlossomTimer -= diff; + + if (IncinerateTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget) + { + DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); + DoCast(pTarget, SPELL_INCINERATE); + IncinerateTimer = 20000 + rand()%31 * 1000; + } + } else IncinerateTimer -= diff; + + if (CrushingShadowsTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, SPELL_CRUSHING_SHADOWS); + CrushingShadowsTimer = 10000 + rand()%16 * 1000; + } else CrushingShadowsTimer -= diff; + + /*** NOTE FOR FUTURE DEV: UNCOMMENT BELOW ONLY IF MIND CONTROL IS FULLY IMPLEMENTED **/ + /*if (ShadowOfDeathTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SPELL_SHADOW_OF_DEATH); + GhostGUID = pTarget->GetGUID(); + ShadowOfDeathTimer = 30000; + SummonShadowsTimer = 53000; // Make it VERY close but slightly less so that we can check if the aura is still on the player + } + } else ShadowOfDeathTimer -= diff;*/ + + if (RandomYellTimer <= diff) + { + DoScriptText(RAND(SAY_SPELL1,SAY_SPELL2), me); + RandomYellTimer = 50000 + rand()%51 * 1000; + } else RandomYellTimer -= diff; + + if (!me->HasAura(SPELL_BERSERK)) + { + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + DoScriptText(SAY_ENRAGE, me); + } else EnrageTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_doom_blossom(Creature* pCreature) +{ + return new mob_doom_blossomAI(pCreature); +} + +CreatureAI* GetAI_mob_shadowy_construct(Creature* pCreature) +{ + return new mob_shadowy_constructAI(pCreature); +} + +CreatureAI* GetAI_boss_teron_gorefiend(Creature* pCreature) +{ + return new boss_teron_gorefiendAI (pCreature); +} + +void AddSC_boss_teron_gorefiend() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_doom_blossom"; + newscript->GetAI = &GetAI_mob_doom_blossom; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadowy_construct"; + newscript->GetAI = &GetAI_mob_shadowy_construct; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_teron_gorefiend"; + newscript->GetAI = &GetAI_boss_teron_gorefiend; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp new file mode 100644 index 00000000000..7d94b4b36a0 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp @@ -0,0 +1,226 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warlord_Najentus +SD%Complete: 95 +SDComment: +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +enum eEnums +{ + SAY_AGGRO = -1564000, + SAY_NEEDLE1 = -1564001, + SAY_NEEDLE2 = -1564002, + SAY_SLAY1 = -1564003, + SAY_SLAY2 = -1564004, + SAY_SPECIAL1 = -1564005, + SAY_SPECIAL2 = -1564006, + SAY_ENRAGE1 = -1564007, //is this text actually in use? + SAY_ENRAGE2 = -1564008, + SAY_DEATH = -1564009, + + //Spells + SPELL_NEEDLE_SPINE = 39992, + SPELL_TIDAL_BURST = 39878, + SPELL_TIDAL_SHIELD = 39872, + SPELL_IMPALING_SPINE = 39837, + SPELL_CREATE_NAJENTUS_SPINE = 39956, + SPELL_HURL_SPINE = 39948, + SPELL_BERSERK = 26662, + + GOBJECT_SPINE = 185584, + + EVENT_BERSERK = 1, + EVENT_YELL = 2, + EVENT_NEEDLE = 3, + EVENT_SPINE = 4, + EVENT_SHIELD = 5, + + GCD_CAST = 1, + GCD_YELL = 2 +}; + +struct boss_najentusAI : public ScriptedAI +{ + boss_najentusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + uint64 SpineTargetGUID; + + void Reset() + { + events.Reset(); + + SpineTargetGUID = 0; + + if (pInstance) + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(rand()%2 ? SAY_SLAY1 : SAY_SLAY2, me); + events.DelayEvents(5000, GCD_YELL); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_HURL_SPINE && me->HasAura(SPELL_TIDAL_SHIELD)) + { + me->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD); + DoCast(me, SPELL_TIDAL_BURST, true); + ResetTimer(); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + events.ScheduleEvent(EVENT_BERSERK, 480000, GCD_CAST); + events.ScheduleEvent(EVENT_YELL, 45000 + (rand()%76)*1000, GCD_YELL); + ResetTimer(); + } + + bool RemoveImpalingSpine() + { + if (!SpineTargetGUID) return false; + Unit *pTarget = Unit::GetUnit(*me, SpineTargetGUID); + if (pTarget && pTarget->HasAura(SPELL_IMPALING_SPINE)) + pTarget->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE); + SpineTargetGUID=0; + return true; + } + + void ResetTimer(uint32 inc = 0) + { + events.RescheduleEvent(EVENT_NEEDLE, 10000 + inc, GCD_CAST); + events.RescheduleEvent(EVENT_SPINE, 20000 + inc, GCD_CAST); + events.RescheduleEvent(EVENT_SHIELD, 60000 + inc); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHIELD: + DoCast(me, SPELL_TIDAL_SHIELD, true); + ResetTimer(45000); + break; + case EVENT_BERSERK: + DoScriptText(SAY_ENRAGE2, me); + DoCast(me, SPELL_BERSERK, true); + events.DelayEvents(15000, GCD_YELL); + break; + case EVENT_SPINE: + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) pTarget = me->getVictim(); + if (pTarget) + { + DoCast(pTarget, SPELL_IMPALING_SPINE, true); + SpineTargetGUID = pTarget->GetGUID(); + //must let target summon, otherwise you cannot click the spine + pTarget->SummonGameObject(GOBJECT_SPINE, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 30); + DoScriptText(rand()%2 ? SAY_NEEDLE1 : SAY_NEEDLE2, me); + events.DelayEvents(1500, GCD_CAST); + events.DelayEvents(15000, GCD_YELL); + } + events.ScheduleEvent(EVENT_SPINE, 21000, GCD_CAST); + return; + } + case EVENT_NEEDLE: + { + //DoCast(me, SPELL_NEEDLE_SPINE, true); + std::list pTargets; + SelectTargetList(pTargets, 3, SELECT_TARGET_RANDOM, 80, true); + for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) + DoCast(*i, 39835, true); + events.ScheduleEvent(EVENT_NEEDLE, urand(15000,25000), GCD_CAST); + events.DelayEvents(1500, GCD_CAST); + return; + } + case EVENT_YELL: + DoScriptText(RAND(SAY_SPECIAL1, SAY_SPECIAL2), me); + events.ScheduleEvent(EVENT_YELL, urand(25000,100000), GCD_YELL); + events.DelayEvents(15000, GCD_YELL); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +bool GOHello_go_najentus_spine(Player* pPlayer, GameObject* pGo) +{ + if (ScriptedInstance* pInstance = pGo->GetInstanceData()) + if (Creature* Najentus = Unit::GetCreature(*pGo, pInstance->GetData64(DATA_HIGHWARLORDNAJENTUS))) + if (CAST_AI(boss_najentusAI, Najentus->AI())->RemoveImpalingSpine()) + { + pPlayer->CastSpell(pPlayer, SPELL_CREATE_NAJENTUS_SPINE, true); + pGo->Delete(); + } + return true; +} + +CreatureAI* GetAI_boss_najentus(Creature* pCreature) +{ + return new boss_najentusAI (pCreature); +} + +void AddSC_boss_najentus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_najentus"; + newscript->GetAI = &GetAI_boss_najentus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_najentus_spine"; + newscript->pGOHello = &GOHello_go_najentus_spine; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/illidari_council.cpp b/src/server/scripts/Outland/black_temple/illidari_council.cpp new file mode 100644 index 00000000000..82cc2876b5a --- /dev/null +++ b/src/server/scripts/Outland/black_temple/illidari_council.cpp @@ -0,0 +1,874 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Illidari_Council +SD%Complete: 95 +SDComment: Circle of Healing not working properly. +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +//Speech'n'Sounds +#define SAY_GATH_SLAY -1564085 +#define SAY_GATH_SLAY_COMNT -1564089 +#define SAY_GATH_DEATH -1564093 +#define SAY_GATH_SPECIAL1 -1564077 +#define SAY_GATH_SPECIAL2 -1564081 + +#define SAY_VERA_SLAY -1564086 +#define SAY_VERA_COMNT -1564089 //signed for 22949 +#define SAY_VERA_DEATH -1564094 +#define SAY_VERA_SPECIAL1 -1564078 +#define SAY_VERA_SPECIAL2 -1564082 + +#define SAY_MALA_SLAY -1564087 +#define SAY_MALA_COMNT -1564090 +#define SAY_MALA_DEATH -1564095 +#define SAY_MALA_SPECIAL1 -1564079 +#define SAY_MALA_SPECIAL2 -1564083 + +#define SAY_ZERE_SLAY -1564088 +#define SAY_ZERE_COMNT -1564091 +#define SAY_ZERE_DEATH -1564096 +#define SAY_ZERE_SPECIAL1 -1564080 +#define SAY_ZERE_SPECIAL2 -1564084 + +#define ERROR_INST_DATA "SD2 ERROR: Instance Data for Black Temple not set properly; Illidari Council event will not function properly." + +#define AKAMAID 23089 + +struct CouncilYells +{ + int32 entry; + uint32 timer; +}; + +static CouncilYells CouncilAggro[]= +{ + {-1564069, 5000}, // Gathios + {-1564070, 5500}, // Veras + {-1564071, 5000}, // Malande + {-1564072, 0}, // Zerevor +}; + +// Need to get proper timers for this later +static CouncilYells CouncilEnrage[]= +{ + {-1564073, 2000}, // Gathios + {-1564074, 6000}, // Veras + {-1564075, 5000}, // Malande + {-1564076, 0}, // Zerevor +}; + +// High Nethermancer Zerevor's spells +#define SPELL_FLAMESTRIKE 41481 +#define SPELL_BLIZZARD 41482 +#define SPELL_ARCANE_BOLT 41483 +#define SPELL_ARCANE_EXPLOSION 41524 +#define SPELL_DAMPEN_MAGIC 41478 + +// Lady Malande's spells +#define SPELL_EMPOWERED_SMITE 41471 +#define SPELL_CIRCLE_OF_HEALING 41455 +#define SPELL_REFLECTIVE_SHIELD 41475 +#define SPELL_DIVINE_WRATH 41472 +#define SPELL_HEAL_VISUAL 24171 + +// Gathios the Shatterer's spells +#define SPELL_BLESS_PROTECTION 41450 +#define SPELL_BLESS_SPELLWARD 41451 +#define SPELL_CONSECRATION 41541 +#define SPELL_HAMMER_OF_JUSTICE 41468 +#define SPELL_SEAL_OF_COMMAND 41469 +#define SPELL_SEAL_OF_BLOOD 41459 +#define SPELL_CHROMATIC_AURA 41453 +#define SPELL_DEVOTION_AURA 41452 + +// Veras Darkshadow's spells +#define SPELL_DEADLY_POISON 41485 +#define SPELL_ENVENOM 41487 +#define SPELL_VANISH 41479 + +#define SPELL_BERSERK 45078 + +struct mob_blood_elf_council_voice_triggerAI : public ScriptedAI +{ + mob_blood_elf_council_voice_triggerAI(Creature* c) : ScriptedAI(c) + { + for (uint8 i = 0; i < 4; ++i) + Council[i] = 0; + } + + uint64 Council[4]; + + uint32 EnrageTimer; + uint32 AggroYellTimer; + + uint8 YellCounter; // Serves as the counter for both the aggro and enrage yells + + bool EventStarted; + + void Reset() + { + EnrageTimer = 900000; // 15 minutes + AggroYellTimer = 500; + + YellCounter = 0; + + EventStarted = false; + } + + // finds and stores the GUIDs for each Council member using instance data system. + void LoadCouncilGUIDs() + { + if (ScriptedInstance* pInstance = me->GetInstanceData()) + { + Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[1] = pInstance->GetData64(DATA_VERASDARKSHADOW); + Council[2] = pInstance->GetData64(DATA_LADYMALANDE); + Council[3] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + } else error_log(ERROR_INST_DATA); + } + + void EnterCombat(Unit* /*who*/) {} + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!EventStarted) + return; + + if (YellCounter > 3) + return; + + if (AggroYellTimer) + { + if (AggroYellTimer <= diff) + { + if (Unit* pMember = Unit::GetUnit(*me, Council[YellCounter])) + { + DoScriptText(CouncilAggro[YellCounter].entry, pMember); + AggroYellTimer = CouncilAggro[YellCounter].timer; + } + ++YellCounter; + if (YellCounter > 3) + YellCounter = 0; // Reuse for Enrage Yells + } else AggroYellTimer -= diff; + } + + if (EnrageTimer) + { + if (EnrageTimer <= diff) + { + if (Unit* pMember = Unit::GetUnit(*me, Council[YellCounter])) + { + pMember->CastSpell(pMember, SPELL_BERSERK, true); + DoScriptText(CouncilEnrage[YellCounter].entry, pMember); + EnrageTimer = CouncilEnrage[YellCounter].timer; + } + ++YellCounter; + } else EnrageTimer -= diff; + } + } +}; + +struct mob_illidari_councilAI : public ScriptedAI +{ + mob_illidari_councilAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i = 0; i < 4; ++i) + Council[i] = 0; + } + + ScriptedInstance* pInstance; + + uint64 Council[4]; + + uint32 CheckTimer; + uint32 EndEventTimer; + + uint8 DeathCount; + + bool EventBegun; + + void Reset() + { + CheckTimer = 2000; + EndEventTimer = 0; + + DeathCount = 0; + + Creature* pMember = NULL; + for (uint8 i = 0; i < 4; ++i) + { + pMember = Unit::GetCreature((*me), Council[i]); + if (!pMember) + continue; + + if (!pMember->isAlive()) + { + pMember->RemoveCorpse(); + pMember->Respawn(); + } + pMember->AI()->EnterEvadeMode(); + } + + if (pInstance) + { + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, NOT_STARTED); + if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + VoiceTrigger->AI()->EnterEvadeMode(); + } + + EventBegun = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(11686); + } + + void EnterCombat(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void StartEvent(Unit *pTarget) + { + if (!pInstance) + return; + + if (pTarget && pTarget->isAlive()) + { + Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + Council[2] = pInstance->GetData64(DATA_LADYMALANDE); + Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); + + // Start the event for the Voice Trigger + if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + { + CAST_AI(mob_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->LoadCouncilGUIDs(); + CAST_AI(mob_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->EventStarted = true; + } + + for (uint8 i = 0; i < 4; ++i) + { + Unit* Member = NULL; + if (Council[i]) + { + Member = Unit::GetUnit((*me), Council[i]); + if (Member && Member->isAlive()) + CAST_CRE(Member)->AI()->AttackStart(pTarget); + } + } + + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, IN_PROGRESS); + + EventBegun = true; + } + } + + void UpdateAI(const uint32 diff) + { + if (!EventBegun) return; + + if (EndEventTimer) + { + if (EndEventTimer <= diff) + { + if (DeathCount > 3) + { + if (pInstance) + { + if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, DONE); + //me->SummonCreature(AKAMAID,746.466980f,304.394989f,311.90208f,6.272870f,TEMPSUMMON_DEAD_DESPAWN,0); + } + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + + Creature* pMember = (Unit::GetCreature(*me, Council[DeathCount])); + if (pMember && pMember->isAlive()) + pMember->DealDamage(pMember, pMember->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + ++DeathCount; + EndEventTimer = 1500; + } else EndEventTimer -= diff; + } + + if (CheckTimer) + { + if (CheckTimer <= diff) + { + uint8 EvadeCheck = 0; + for (uint8 i = 0; i < 4; ++i) + { + if (Council[i]) + { + if (Creature* Member = (Unit::GetCreature((*me), Council[i]))) + { + // This is the evade/death check. + if (Member->isAlive() && !Member->getVictim()) + ++EvadeCheck; //If all members evade, we reset so that players can properly reset the event + else if (!Member->isAlive()) // If even one member dies, kill the rest, set instance data, and kill self. + { + EndEventTimer = 1000; + CheckTimer = 0; + return; + } + } + } + } + + if (EvadeCheck > 3) + Reset(); + + CheckTimer = 2000; + } else CheckTimer -= diff; + } + + } +}; + +struct boss_illidari_councilAI : public ScriptedAI +{ + boss_illidari_councilAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i = 0; i < 4; ++i) + Council[i] = 0; + LoadedGUIDs = false; + } + + uint64 Council[4]; + + ScriptedInstance* pInstance; + + bool LoadedGUIDs; + + void EnterCombat(Unit* who) + { + if (pInstance) + { + Creature* Controller = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ILLIDARICOUNCIL))); + if (Controller) + CAST_AI(mob_illidari_councilAI, Controller->AI())->StartEvent(who); + } + else + { + error_log(ERROR_INST_DATA); + EnterEvadeMode(); + return; + } + DoZoneInCombat(); + // Load GUIDs on first aggro because the Creature guids are only set as the creatures are created in world- + // this means that for each pCreature, it will attempt to LoadGUIDs even though some of the other creatures are + // not in world, and thus have no GUID set in the instance data system. Putting it in aggro ensures that all the creatures + // have been loaded and have their GUIDs set in the instance data system. + if (!LoadedGUIDs) + LoadGUIDs(); + } + + void EnterEvadeMode() + { + for (uint8 i = 0; i < 4; ++i) + { + if (Unit* pUnit = Unit::GetUnit(*me, Council[i])) + if (pUnit != me && pUnit->getVictim()) + { + AttackStart(pUnit->getVictim()); + return; + } + } + ScriptedAI::EnterEvadeMode(); + } + + void DamageTaken(Unit* done_by, uint32 &damage) + { + if (done_by == me) + return; + + damage /= 4; + for (uint8 i = 0; i < 4; ++i) + { + if (Creature* pUnit = Unit::GetCreature(*me, Council[i])) + if (pUnit != me && damage < pUnit->GetHealth()) + { + pUnit->SetHealth(pUnit->GetHealth() - damage); + pUnit->LowerPlayerDamageReq(damage); + } + } + } + + void LoadGUIDs() + { + if (!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + Council[0] = pInstance->GetData64(DATA_LADYMALANDE); + Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + Council[2] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); + + LoadedGUIDs = true; + } +}; + +struct boss_gathios_the_shattererAI : public boss_illidari_councilAI +{ + boss_gathios_the_shattererAI(Creature *c) : boss_illidari_councilAI(c) {} + + uint32 ConsecrationTimer; + uint32 HammerOfJusticeTimer; + uint32 SealTimer; + uint32 AuraTimer; + uint32 BlessingTimer; + + void Reset() + { + ConsecrationTimer = 40000; + HammerOfJusticeTimer = 10000; + SealTimer = 40000; + AuraTimer = 90000; + BlessingTimer = 60000; + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_GATH_SLAY, me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_GATH_DEATH, me); + } + + Unit* SelectCouncilMember() + { + Unit* pUnit = me; + uint32 member = 0; // He chooses Lady Malande most often + + if (rand()%10 == 0) // But there is a chance he picks someone else. + member = urand(1, 3); + + if (member != 2) // No need to create another pointer to us using Unit::GetUnit + pUnit = Unit::GetUnit((*me), Council[member]); + return pUnit; + } + + void CastAuraOnCouncil() + { + uint32 spellid = 0; + switch (urand(0,1)) + { + case 0: spellid = SPELL_DEVOTION_AURA; break; + case 1: spellid = SPELL_CHROMATIC_AURA; break; + } + for (uint8 i = 0; i < 4; ++i) + { + Unit* pUnit = Unit::GetUnit((*me), Council[i]); + if (pUnit) + pUnit->CastSpell(pUnit, spellid, true, 0, 0, me->GetGUID()); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BlessingTimer <= diff) + { + if (Unit* pUnit = SelectCouncilMember()) + { + switch (urand(0,1)) + { + case 0: DoCast(pUnit, SPELL_BLESS_SPELLWARD); break; + case 1: DoCast(pUnit, SPELL_BLESS_PROTECTION); break; + } + } + BlessingTimer = 60000; + } else BlessingTimer -= diff; + + if (ConsecrationTimer <= diff) + { + DoCast(me, SPELL_CONSECRATION); + ConsecrationTimer = 40000; + } else ConsecrationTimer -= diff; + + if (HammerOfJusticeTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + // is in ~10-40 yd range + if (me->IsInRange(pTarget, 10.0f, 40.0f, false)) + { + DoCast(pTarget, SPELL_HAMMER_OF_JUSTICE); + HammerOfJusticeTimer = 20000; + } + } + } else HammerOfJusticeTimer -= diff; + + if (SealTimer <= diff) + { + switch (urand(0,1)) + { + case 0: DoCast(me, SPELL_SEAL_OF_COMMAND); break; + case 1: DoCast(me, SPELL_SEAL_OF_BLOOD); break; + } + SealTimer = 40000; + } else SealTimer -= diff; + + if (AuraTimer <= diff) + { + CastAuraOnCouncil(); + AuraTimer = 90000; + } else AuraTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_high_nethermancer_zerevorAI : public boss_illidari_councilAI +{ + boss_high_nethermancer_zerevorAI(Creature *c) : boss_illidari_councilAI(c) {} + + uint32 BlizzardTimer; + uint32 FlamestrikeTimer; + uint32 ArcaneBoltTimer; + uint32 DampenMagicTimer; + uint32 Cooldown; + uint32 ArcaneExplosionTimer; + + void Reset() + { + BlizzardTimer = 30000 + rand()%61 * 1000; + FlamestrikeTimer = 30000 + rand()%61 * 1000; + ArcaneBoltTimer = 10000; + DampenMagicTimer = 2000; + ArcaneExplosionTimer = 14000; + Cooldown = 0; + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_ZERE_SLAY, me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_ZERE_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Cooldown) + { + if (Cooldown <= diff) Cooldown = 0; + else + { + Cooldown -= diff; + return; // Don't cast any other spells if global cooldown is still ticking + } + } + + if (DampenMagicTimer <= diff) + { + DoCast(me, SPELL_DAMPEN_MAGIC); + Cooldown = 1000; + DampenMagicTimer = 67200; // almost 1,12 minutes + ArcaneBoltTimer += 1000; // Give the Mage some time to spellsteal Dampen. + } else DampenMagicTimer -= diff; + + if (ArcaneExplosionTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); + Cooldown = 1000; + ArcaneExplosionTimer = 14000; + } else ArcaneExplosionTimer -= diff; + + if (ArcaneBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BOLT); + ArcaneBoltTimer = 3000; + Cooldown = 2000; + } else ArcaneBoltTimer -= diff; + + if (BlizzardTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_BLIZZARD); + BlizzardTimer = 45000 + rand()%46 * 1000; + FlamestrikeTimer += 10000; + Cooldown = 1000; + } + } else BlizzardTimer -= diff; + + if (FlamestrikeTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_FLAMESTRIKE); + FlamestrikeTimer = 55000 + rand()%46 * 1000; + BlizzardTimer += 10000; + Cooldown = 2000; + } + } else FlamestrikeTimer -= diff; + } +}; + +struct boss_lady_malandeAI : public boss_illidari_councilAI +{ + boss_lady_malandeAI(Creature *c) : boss_illidari_councilAI(c) {} + + uint32 EmpoweredSmiteTimer; + uint32 CircleOfHealingTimer; + uint32 DivineWrathTimer; + uint32 ReflectiveShieldTimer; + + void Reset() + { + EmpoweredSmiteTimer = 38000; + CircleOfHealingTimer = 20000; + DivineWrathTimer = 40000; + ReflectiveShieldTimer = 0; + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_MALA_SLAY, me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_MALA_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (EmpoweredSmiteTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_EMPOWERED_SMITE); + EmpoweredSmiteTimer = 38000; + } + } else EmpoweredSmiteTimer -= diff; + + if (CircleOfHealingTimer <= diff) + { + DoCast(me, SPELL_CIRCLE_OF_HEALING); + CircleOfHealingTimer = 60000; + } else CircleOfHealingTimer -= diff; + + if (DivineWrathTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_DIVINE_WRATH); + DivineWrathTimer = 40000 + rand()%41 * 1000; + } + } else DivineWrathTimer -= diff; + + if (ReflectiveShieldTimer <= diff) + { + DoCast(me, SPELL_REFLECTIVE_SHIELD); + ReflectiveShieldTimer = 65000; + } else ReflectiveShieldTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_veras_darkshadowAI : public boss_illidari_councilAI +{ + boss_veras_darkshadowAI(Creature *c) : boss_illidari_councilAI(c) {} + + uint64 EnvenomTargetGUID; + + uint32 DeadlyPoisonTimer; + uint32 VanishTimer; + uint32 AppearEnvenomTimer; + + bool HasVanished; + + void Reset() + { + EnvenomTargetGUID = 0; + + DeadlyPoisonTimer = 20000; + VanishTimer = 60000 + rand()%61 * 1000; + AppearEnvenomTimer = 150000; + + HasVanished = false; + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_VERA_SLAY, me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_VERA_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!HasVanished) + { + if (DeadlyPoisonTimer <= diff) + { + DoCast(me->getVictim(), SPELL_DEADLY_POISON); + DeadlyPoisonTimer = 15000 + rand()%31 * 1000; + } else DeadlyPoisonTimer -= diff; + + if (AppearEnvenomTimer <= diff) // Cast Envenom. This is cast 4 seconds after Vanish is over + { + DoCast(me->getVictim(), SPELL_ENVENOM); + AppearEnvenomTimer = 90000; + } else AppearEnvenomTimer -= diff; + + if (VanishTimer <= diff) // Disappear and stop attacking, but follow a random unit + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + VanishTimer = 30000; + AppearEnvenomTimer= 28000; + HasVanished = true; + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoResetThreat(); + // Chase a unit. Check before DoMeleeAttackIfReady prevents from attacking + me->AddThreat(pTarget, 500000.0f); + me->GetMotionMaster()->MoveChase(pTarget); + } + } else VanishTimer -= diff; + + DoMeleeAttackIfReady(); + } + else + { + if (VanishTimer <= diff) // Become attackable and poison current target + { + Unit *pTarget = me->getVictim(); + DoCast(pTarget, SPELL_DEADLY_POISON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoResetThreat(); + me->AddThreat(pTarget, 3000.0f); // Make Veras attack his target for a while, he will cast Envenom 4 seconds after. + DeadlyPoisonTimer += 6000; + VanishTimer = 90000; + AppearEnvenomTimer = 4000; + HasVanished = false; + } else VanishTimer -= diff; + + if (AppearEnvenomTimer <= diff) // Appear 2 seconds before becoming attackable (Shifting out of vanish) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + me->SetVisibility(VISIBILITY_ON); + AppearEnvenomTimer = 6000; + } else AppearEnvenomTimer -= diff; + } + } +}; + +CreatureAI* GetAI_mob_blood_elf_council_voice_trigger(Creature* c) +{ + return new mob_blood_elf_council_voice_triggerAI(c); +} + +CreatureAI* GetAI_mob_illidari_council(Creature* pCreature) +{ + return new mob_illidari_councilAI (pCreature); +} + +CreatureAI* GetAI_boss_gathios_the_shatterer(Creature* pCreature) +{ + return new boss_gathios_the_shattererAI (pCreature); +} + +CreatureAI* GetAI_boss_lady_malande(Creature* pCreature) +{ + return new boss_lady_malandeAI (pCreature); +} + +CreatureAI* GetAI_boss_veras_darkshadow(Creature* pCreature) +{ + return new boss_veras_darkshadowAI (pCreature); +} + +CreatureAI* GetAI_boss_high_nethermancer_zerevor(Creature* pCreature) +{ + return new boss_high_nethermancer_zerevorAI (pCreature); +} + +void AddSC_boss_illidari_council() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_illidari_council"; + newscript->GetAI = &GetAI_mob_illidari_council; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_blood_elf_council_voice_trigger"; + newscript->GetAI = &GetAI_mob_blood_elf_council_voice_trigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_gathios_the_shatterer"; + newscript->GetAI = &GetAI_boss_gathios_the_shatterer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lady_malande"; + newscript->GetAI = &GetAI_boss_lady_malande; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_veras_darkshadow"; + newscript->GetAI = &GetAI_boss_veras_darkshadow; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_high_nethermancer_zerevor"; + newscript->GetAI = &GetAI_boss_high_nethermancer_zerevor; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/black_temple/instance_black_temple.cpp b/src/server/scripts/Outland/black_temple/instance_black_temple.cpp new file mode 100644 index 00000000000..88e25026a13 --- /dev/null +++ b/src/server/scripts/Outland/black_temple/instance_black_temple.cpp @@ -0,0 +1,346 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Black_Temple +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Black Temple Scripts +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +#define MAX_ENCOUNTER 9 + +/* Black Temple encounters: +0 - High Warlord Naj'entus event +1 - Supremus Event +2 - Shade of Akama Event +3 - Teron Gorefiend Event +4 - Gurtogg Bloodboil Event +5 - Reliquary Of Souls Event +6 - Mother Shahraz Event +7 - Illidari Council Event +8 - Illidan Stormrage Event +*/ + +struct instance_black_temple : public ScriptedInstance +{ + instance_black_temple(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 Najentus; + uint64 Akama; // This is the Akama that starts the Illidan encounter. + uint64 Akama_Shade; // This is the Akama that starts the Shade of Akama encounter. + uint64 ShadeOfAkama; + uint64 Supremus; + uint64 LadyMalande; + uint64 GathiosTheShatterer; + uint64 HighNethermancerZerevor; + uint64 VerasDarkshadow; + uint64 IllidariCouncil; + uint64 BloodElfCouncilVoice; + uint64 IllidanStormrage; + + uint64 NajentusGate; + uint64 MainTempleDoors; + uint64 ShadeOfAkamaDoor; + uint64 CommonDoor;//Teron + uint64 TeronDoor; + uint64 GuurtogDoor; + uint64 MotherDoor; + uint64 TempleDoor;//Befor mother + uint64 CouncilDoor; + uint64 SimpleDoor;//council + uint64 IllidanGate; + uint64 IllidanDoor[2]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Najentus = 0; + Akama = 0; + Akama_Shade = 0; + ShadeOfAkama = 0; + Supremus = 0; + LadyMalande = 0; + GathiosTheShatterer = 0; + HighNethermancerZerevor = 0; + VerasDarkshadow = 0; + IllidariCouncil = 0; + BloodElfCouncilVoice = 0; + IllidanStormrage = 0; + + NajentusGate = 0; + MainTempleDoors = 0; + ShadeOfAkamaDoor= 0; + CommonDoor = 0;//teron + TeronDoor = 0; + GuurtogDoor = 0; + MotherDoor = 0; + TempleDoor = 0; + SimpleDoor = 0;//Bycouncil + CouncilDoor = 0; + IllidanGate = 0; + IllidanDoor[0] = 0; + IllidanDoor[1] = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Black Temple: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 22887: Najentus = pCreature->GetGUID(); break; + case 23089: Akama = pCreature->GetGUID(); break; + case 22990: Akama_Shade = pCreature->GetGUID(); break; + case 22841: ShadeOfAkama = pCreature->GetGUID(); break; + case 22898: Supremus = pCreature->GetGUID(); break; + case 22917: IllidanStormrage = pCreature->GetGUID(); break; + case 22949: GathiosTheShatterer = pCreature->GetGUID(); break; + case 22950: HighNethermancerZerevor = pCreature->GetGUID(); break; + case 22951: LadyMalande = pCreature->GetGUID(); break; + case 22952: VerasDarkshadow = pCreature->GetGUID(); break; + case 23426: IllidariCouncil = pCreature->GetGUID(); break; + case 23499: BloodElfCouncilVoice = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 185483: NajentusGate = pGo->GetGUID();// Gate past Naj'entus (at the entrance to Supermoose's courtyards) + if (m_auiEncounter[0] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185882: MainTempleDoors = pGo->GetGUID();// Main Temple Doors - right past Supermoose (Supremus) + if (m_auiEncounter[1] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185478: ShadeOfAkamaDoor = pGo->GetGUID();break; + case 185480: CommonDoor = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE)HandleGameObject(NULL,true,pGo);break; + case 186153: TeronDoor = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185892: GuurtogDoor = pGo->GetGUID(); + if (m_auiEncounter[4] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185479: TempleDoor = pGo->GetGUID(); + if (m_auiEncounter[5] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185482: MotherDoor = pGo->GetGUID(); + if (m_auiEncounter[6] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185481: CouncilDoor = pGo->GetGUID(); + if (m_auiEncounter[7] == DONE)HandleGameObject(NULL,true,pGo);break; + case 186152: SimpleDoor = pGo->GetGUID(); + if (m_auiEncounter[7] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185905: IllidanGate = pGo->GetGUID(); break; // Gate leading to Temple Summit + case 186261: IllidanDoor[0] = pGo->GetGUID(); break; // Right door at Temple Summit + case 186262: IllidanDoor[1] = pGo->GetGUID(); break; // Left door at Temple Summit + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_HIGHWARLORDNAJENTUS: return Najentus; + case DATA_AKAMA: return Akama; + case DATA_AKAMA_SHADE: return Akama_Shade; + case DATA_SHADEOFAKAMA: return ShadeOfAkama; + case DATA_SUPREMUS: return Supremus; + case DATA_ILLIDANSTORMRAGE: return IllidanStormrage; + case DATA_GATHIOSTHESHATTERER: return GathiosTheShatterer; + case DATA_HIGHNETHERMANCERZEREVOR: return HighNethermancerZerevor; + case DATA_LADYMALANDE: return LadyMalande; + case DATA_VERASDARKSHADOW: return VerasDarkshadow; + case DATA_ILLIDARICOUNCIL: return IllidariCouncil; + case DATA_GAMEOBJECT_NAJENTUS_GATE: return NajentusGate; + case DATA_GAMEOBJECT_ILLIDAN_GATE: return IllidanGate; + case DATA_GAMEOBJECT_ILLIDAN_DOOR_R: return IllidanDoor[0]; + case DATA_GAMEOBJECT_ILLIDAN_DOOR_L: return IllidanDoor[1]; + case DATA_GAMEOBJECT_SUPREMUS_DOORS: return MainTempleDoors; + case DATA_BLOOD_ELF_COUNCIL_VOICE: return BloodElfCouncilVoice; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_HIGHWARLORDNAJENTUSEVENT: + if (data == DONE) + { + HandleGameObject(NajentusGate, true); + } + m_auiEncounter[0] = data;break; + case DATA_SUPREMUSEVENT: + if (data == DONE) + { + HandleGameObject(NajentusGate, true); + } + m_auiEncounter[1] = data; break; + case DATA_SHADEOFAKAMAEVENT: + if (data == IN_PROGRESS) + { + HandleGameObject(ShadeOfAkamaDoor, false); + } else HandleGameObject(ShadeOfAkamaDoor, true); + m_auiEncounter[2] = data; break; + case DATA_TERONGOREFIENDEVENT: + if (data == IN_PROGRESS) + { + HandleGameObject(TeronDoor, false); + HandleGameObject(CommonDoor, false); + }else + { + HandleGameObject(TeronDoor, true); + HandleGameObject(CommonDoor, true); + } + m_auiEncounter[3] = data; break; + case DATA_GURTOGGBLOODBOILEVENT: + if (data == DONE) + { + HandleGameObject(GuurtogDoor, true); + } + m_auiEncounter[4] = data; break; + case DATA_RELIQUARYOFSOULSEVENT: + if (data == DONE) + { + HandleGameObject(TempleDoor, true); + } + m_auiEncounter[5] = data; break; + case DATA_MOTHERSHAHRAZEVENT: + if (data == DONE) + { + HandleGameObject(MotherDoor, true); + } + m_auiEncounter[6] = data; break; + case DATA_ILLIDARICOUNCILEVENT: + if (data == IN_PROGRESS) + { + HandleGameObject(CouncilDoor, false); + HandleGameObject(SimpleDoor, false); + }else + { + HandleGameObject(CouncilDoor, true); + HandleGameObject(SimpleDoor, true); + } + m_auiEncounter[7] = data; break; + case DATA_ILLIDANSTORMRAGEEVENT: m_auiEncounter[8] = data; break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] + << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " << m_auiEncounter[7] + << " " << m_auiEncounter[8]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_HIGHWARLORDNAJENTUSEVENT: return m_auiEncounter[0]; + case DATA_SUPREMUSEVENT: return m_auiEncounter[1]; + case DATA_SHADEOFAKAMAEVENT: return m_auiEncounter[2]; + case DATA_TERONGOREFIENDEVENT: return m_auiEncounter[3]; + case DATA_GURTOGGBLOODBOILEVENT: return m_auiEncounter[4]; + case DATA_RELIQUARYOFSOULSEVENT: return m_auiEncounter[5]; + case DATA_MOTHERSHAHRAZEVENT: return m_auiEncounter[6]; + case DATA_ILLIDARICOUNCILEVENT: return m_auiEncounter[7]; + case DATA_ILLIDANSTORMRAGEEVENT: return m_auiEncounter[8]; + } + + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] + >> m_auiEncounter[3] >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] + >> m_auiEncounter[7] >> m_auiEncounter[8]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_black_temple(Map* pMap) +{ + return new instance_black_temple(pMap); +} + +void AddSC_instance_black_temple() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_black_temple"; + newscript->GetInstanceData = &GetInstanceData_instance_black_temple; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/blades_edge_mountains.cpp b/src/server/scripts/Outland/blades_edge_mountains.cpp new file mode 100644 index 00000000000..f5b4539edaf --- /dev/null +++ b/src/server/scripts/Outland/blades_edge_mountains.cpp @@ -0,0 +1,525 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Blades_Edge_Mountains +SD%Complete: 90 +SDComment: Quest support: 10503, 10504, 10556, 10609, 10682, 10821, 10980. Ogri'la->Skettis Flight. (npc_daranelle needs bit more work before consider complete) +SDCategory: Blade's Edge Mountains +EndScriptData */ + +/* ContentData +mobs_bladespire_ogre +mobs_nether_drake +npc_daranelle +npc_overseer_nuaar +npc_saikkal_the_elder +go_legion_obelisk +EndContentData */ + +#include "ScriptedPch.h" + +//Support for quest: You're Fired! (10821) +bool obelisk_one, obelisk_two, obelisk_three, obelisk_four, obelisk_five; + +#define LEGION_OBELISK_ONE 185193 +#define LEGION_OBELISK_TWO 185195 +#define LEGION_OBELISK_THREE 185196 +#define LEGION_OBELISK_FOUR 185197 +#define LEGION_OBELISK_FIVE 185198 + +/*###### +## mobs_bladespire_ogre +######*/ + +//TODO: add support for quest 10512 + Creature abilities +struct mobs_bladespire_ogreAI : public ScriptedAI +{ + mobs_bladespire_ogreAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mobs_bladespire_ogre(Creature* pCreature) +{ + return new mobs_bladespire_ogreAI (pCreature); +} + +/*###### +## mobs_nether_drake +######*/ + +enum eNetherdrake +{ + SAY_NIHIL_1 = -1000169, //signed for 5955 + SAY_NIHIL_2 = -1000170, //signed for 5955 + SAY_NIHIL_3 = -1000171, //signed for 5955 + SAY_NIHIL_4 = -1000172, //signed for 20021, used by 20021,21817,21820,21821,21823 + SAY_NIHIL_INTERRUPT = -1000173, //signed for 20021, used by 20021,21817,21820,21821,21823 + + ENTRY_WHELP = 20021, + ENTRY_PROTO = 21821, + ENTRY_ADOLE = 21817, + ENTRY_MATUR = 21820, + ENTRY_NIHIL = 21823, + + SPELL_T_PHASE_MODULATOR = 37573, + + SPELL_ARCANE_BLAST = 38881, + SPELL_MANA_BURN = 38884, + SPELL_INTANGIBLE_PRESENCE = 36513 +}; + +struct mobs_nether_drakeAI : public ScriptedAI +{ + mobs_nether_drakeAI(Creature *c) : ScriptedAI(c) {} + + bool IsNihil; + uint32 NihilSpeech_Timer; + uint32 NihilSpeech_Phase; + + uint32 ArcaneBlast_Timer; + uint32 ManaBurn_Timer; + uint32 IntangiblePresence_Timer; + + void Reset() + { + IsNihil = false; + NihilSpeech_Timer = 3000; + NihilSpeech_Phase = 0; + + ArcaneBlast_Timer = 7500; + ManaBurn_Timer = 10000; + IntangiblePresence_Timer = 15000; + } + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + //in case Creature was not summoned (not expected) + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 0) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + me->SetHealth(0); + } + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_T_PHASE_MODULATOR && caster->GetTypeId() == TYPEID_PLAYER) + { + const uint32 entry_list[4] = {ENTRY_PROTO, ENTRY_ADOLE, ENTRY_MATUR, ENTRY_NIHIL}; + int cid = rand()%(4-1); + + if (entry_list[cid] == me->GetEntry()) + ++cid; + + //we are nihil, so say before transform + if (me->GetEntry() == ENTRY_NIHIL) + { + DoScriptText(SAY_NIHIL_INTERRUPT, me); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + IsNihil = false; + } + + if (me->UpdateEntry(entry_list[cid])) + { + if (entry_list[cid] == ENTRY_NIHIL) + { + EnterEvadeMode(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + IsNihil = true; + }else + AttackStart(caster); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (IsNihil) + { + if (NihilSpeech_Timer <= diff) + { + switch(NihilSpeech_Phase) + { + case 0: + DoScriptText(SAY_NIHIL_1, me); + ++NihilSpeech_Phase; + break; + case 1: + DoScriptText(SAY_NIHIL_2, me); + ++NihilSpeech_Phase; + break; + case 2: + DoScriptText(SAY_NIHIL_3, me); + ++NihilSpeech_Phase; + break; + case 3: + DoScriptText(SAY_NIHIL_4, me); + ++NihilSpeech_Phase; + break; + case 4: + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //take off to location above + me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+50.0f, me->GetPositionY(), me->GetPositionZ()+50.0f); + ++NihilSpeech_Phase; + break; + } + NihilSpeech_Timer = 5000; + } else NihilSpeech_Timer -=diff; + + //anything below here is not interesting for Nihil, so skip it + return; + } + + if (!UpdateVictim()) + return; + + if (IntangiblePresence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); + IntangiblePresence_Timer = 15000+rand()%15000; + } else IntangiblePresence_Timer -= diff; + + if (ManaBurn_Timer <= diff) + { + Unit *pTarget = me->getVictim(); + if (pTarget && pTarget->getPowerType() == POWER_MANA) + DoCast(pTarget, SPELL_MANA_BURN); + ManaBurn_Timer = 8000+rand()%8000; + } else ManaBurn_Timer -= diff; + + if (ArcaneBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BLAST); + ArcaneBlast_Timer = 2500+rand()%5000; + } else ArcaneBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mobs_nether_drake(Creature* pCreature) +{ + return new mobs_nether_drakeAI (pCreature); +} + +/*###### +## npc_daranelle +######*/ + +enum eDaranelle +{ + SAY_SPELL_INFLUENCE = -1000174, + SPELL_LASHHAN_CHANNEL = 36904 +}; + +struct npc_daranelleAI : public ScriptedAI +{ + npc_daranelleAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (who->GetTypeId() == TYPEID_PLAYER) + { + if (who->HasAura(SPELL_LASHHAN_CHANNEL) && me->IsWithinDistInMap(who, 10.0f)) + { + DoScriptText(SAY_SPELL_INFLUENCE, me, who); + //TODO: Move the below to updateAI and run if this statement == true + DoCast(who, 37028, true); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } +}; + +CreatureAI* GetAI_npc_daranelle(Creature* pCreature) +{ + return new npc_daranelleAI (pCreature); +} + +/*###### +## npc_overseer_nuaar +######*/ + +#define GOSSIP_HELLO_ON "Overseer, I am here to negotiate on behalf of the Cenarion Expedition." + +bool GossipHello_npc_overseer_nuaar(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(10682) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_ON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(10532, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_overseer_nuaar(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->SEND_GOSSIP_MENU(10533, pCreature->GetGUID()); + pPlayer->AreaExploredOrEventHappens(10682); + } + return true; +} + +/*###### +## npc_saikkal_the_elder +######*/ + +#define GOSSIP_HELLO_STE "Yes... yes, it's me." +#define GOSSIP_SELECT_STE "Yes elder. Tell me more of the book." + +bool GossipHello_npc_saikkal_the_elder(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(10980) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_STE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(10794, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_saikkal_the_elder(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_STE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(10795, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + pPlayer->SEND_GOSSIP_MENU(10796, pCreature->GetGUID()); + break; + } + return true; +} + +/*###### +## go_legion_obelisk +######*/ + +bool GOHello_go_legion_obelisk(Player* pPlayer, GameObject* pGo) +{ + if (pPlayer->GetQuestStatus(10821) == QUEST_STATUS_INCOMPLETE) + { + switch(pGo->GetEntry()) + { + case LEGION_OBELISK_ONE: + obelisk_one = true; + break; + case LEGION_OBELISK_TWO: + obelisk_two = true; + break; + case LEGION_OBELISK_THREE: + obelisk_three = true; + break; + case LEGION_OBELISK_FOUR: + obelisk_four = true; + break; + case LEGION_OBELISK_FIVE: + obelisk_five = true; + break; + } + + if (obelisk_one == true && obelisk_two == true && obelisk_three == true && obelisk_four == true && obelisk_five == true) + { + pGo->SummonCreature(19963,2943.40f,4778.20f,284.49f,0.94f,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); + //reset global var + obelisk_one = false; + obelisk_two = false; + obelisk_three = false; + obelisk_four = false; + obelisk_five = false; + } + } + + return true; +} + + +/*###### +## npc_bloodmaul_brutebane +######*/ + + +enum eBloodmaul +{ + NPC_OGRE_BRUTE = 19995, + NPC_QUEST_CREDIT = 21241, + GO_KEG = 184315 +}; + +struct npc_bloodmaul_brutebaneAI : public ScriptedAI +{ + npc_bloodmaul_brutebaneAI(Creature *c) : ScriptedAI(c) + { + if(Creature* Ogre = me->FindNearestCreature(NPC_OGRE_BRUTE, 50, true)) + { + Ogre->SetReactState(REACT_DEFENSIVE); + Ogre->GetMotionMaster()->MovePoint(1, me->GetPositionX()-1, me->GetPositionY()+1, me->GetPositionZ()); + } + } + + uint64 OgreGUID; + + void Reset() + { + OgreGUID = 0; + } + + void UpdateAI(const uint32 /*uiDiff*/) {} +}; + +CreatureAI* GetAI_npc_bloodmaul_brutebane(Creature* pCreature) +{ + return new npc_bloodmaul_brutebaneAI (pCreature); +} + +/*###### +## npc_ogre_brute +######*/ + +struct npc_ogre_bruteAI : public ScriptedAI +{ + npc_ogre_bruteAI(Creature *c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + + void Reset() + { + PlayerGUID = 0; + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || (!who->isAlive())) return; + + if (me->IsWithinDistInMap(who, 50.0f) && (who->GetTypeId() == TYPEID_PLAYER) && who->ToPlayer()->GetQuestStatus(10512) == QUEST_STATUS_INCOMPLETE) + { + PlayerGUID = who->GetGUID(); + } + } + + void MovementInform(uint32 /*type*/, uint32 id) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (id == 1) + { + GameObject* Keg = me->FindNearestGameObject(GO_KEG, 20); + if (Keg) + Keg->Delete(); + me->HandleEmoteCommand(7); + me->SetReactState(REACT_AGGRESSIVE); + me->GetMotionMaster()->MoveTargetedHome(); + Creature* Credit = me->FindNearestCreature(NPC_QUEST_CREDIT, 50, true); + if (pPlayer && Credit) + pPlayer->KilledMonster(Credit->GetCreatureInfo(), Credit->GetGUID()); + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_ogre_brute(Creature* pCreature) +{ + return new npc_ogre_bruteAI(pCreature); +} + +/*###### +## AddSC +######*/ + +void AddSC_blades_edge_mountains() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mobs_bladespire_ogre"; + newscript->GetAI = &GetAI_mobs_bladespire_ogre; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mobs_nether_drake"; + newscript->GetAI = &GetAI_mobs_nether_drake; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_daranelle"; + newscript->GetAI = &GetAI_npc_daranelle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_overseer_nuaar"; + newscript->pGossipHello = &GossipHello_npc_overseer_nuaar; + newscript->pGossipSelect = &GossipSelect_npc_overseer_nuaar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_saikkal_the_elder"; + newscript->pGossipHello = &GossipHello_npc_saikkal_the_elder; + newscript->pGossipSelect = &GossipSelect_npc_saikkal_the_elder; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_legion_obelisk"; + newscript->pGOHello = &GOHello_go_legion_obelisk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bloodmaul_brutebane"; + newscript->GetAI = &GetAI_npc_bloodmaul_brutebane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ogre_brute"; + newscript->GetAI = &GetAI_npc_ogre_brute; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp new file mode 100644 index 00000000000..9e9538f2d23 --- /dev/null +++ b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Doomlord_Kazzak +SD%Complete: 70 +SDComment: Using incorrect spell for Mark of Kazzak +SDCategory: Hellfire Peninsula +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_INTRO -1000147 +#define SAY_AGGRO1 -1000148 +#define SAY_AGGRO2 -1000149 +#define SAY_SURPREME1 -1000154 +#define SAY_SURPREME2 -1000149 +#define SAY_KILL1 -1000150 +#define SAY_KILL2 -1000151 +#define SAY_KILL3 -1000152 +#define SAY_DEATH -1000155 +#define EMOTE_FRENZY -1000151 +#define SAY_RAND1 -1000158 +#define SAY_RAND2 -1000157 + +#define SPELL_SHADOWVOLLEY 32963 +#define SPELL_CLEAVE 31779 +#define SPELL_THUNDERCLAP 36706 +#define SPELL_VOIDBOLT 39329 +#define SPELL_MARKOFKAZZAK 32960 +#define SPELL_ENRAGE 32964 +#define SPELL_CAPTURESOUL 32966 +#define SPELL_TWISTEDREFLECTION 21063 + +struct boss_doomlordkazzakAI : public ScriptedAI +{ + boss_doomlordkazzakAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowVolley_Timer; + uint32 Cleave_Timer; + uint32 ThunderClap_Timer; + uint32 VoidBolt_Timer; + uint32 MarkOfKazzak_Timer; + uint32 Enrage_Timer; + uint32 Twisted_Reflection_Timer; + + void Reset() + { + ShadowVolley_Timer = 6000 + rand()%4000; + Cleave_Timer = 7000; + ThunderClap_Timer = 14000 + rand()%4000; + VoidBolt_Timer = 30000; + MarkOfKazzak_Timer = 25000; + Enrage_Timer = 60000; + Twisted_Reflection_Timer = 33000; // Timer may be incorrect + } + + void JustRespawned() + { + DoScriptText(SAY_INTRO, me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2), me); + } + + void KilledUnit(Unit* victim) + { + // When Kazzak kills a player (not pets/totems), he regens some health + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoCast(me, SPELL_CAPTURESOUL); + + DoScriptText(RAND(SAY_KILL1,SAY_KILL2,SAY_KILL3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWVOLLEY); + ShadowVolley_Timer = 4000 + rand()%2000; + } else ShadowVolley_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 8000 + rand()%4000; + } else Cleave_Timer -= diff; + + //ThunderClap_Timer + if (ThunderClap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + ThunderClap_Timer = 10000 + rand()%4000; + } else ThunderClap_Timer -= diff; + + //VoidBolt_Timer + if (VoidBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VOIDBOLT); + VoidBolt_Timer = 15000 + rand()%3000; + } else VoidBolt_Timer -= diff; + + //MarkOfKazzak_Timer + if (MarkOfKazzak_Timer <= diff) + { + Unit* victim = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (victim->GetPower(POWER_MANA)) + { + DoCast(victim, SPELL_MARKOFKAZZAK); + MarkOfKazzak_Timer = 20000; + } + } else MarkOfKazzak_Timer -= diff; + + //Enrage_Timer + if (Enrage_Timer <= diff) + { + DoScriptText(EMOTE_FRENZY, me); + DoCast(me, SPELL_ENRAGE); + Enrage_Timer = 30000; + } else Enrage_Timer -= diff; + + if (Twisted_Reflection_Timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_TWISTEDREFLECTION); + Twisted_Reflection_Timer = 15000; + } else Twisted_Reflection_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_doomlordkazzak(Creature* pCreature) +{ + return new boss_doomlordkazzakAI (pCreature); +} + +void AddSC_boss_doomlordkazzak() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_doomlord_kazzak"; + newscript->GetAI = &GetAI_boss_doomlordkazzak; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/boss_doomwalker.cpp b/src/server/scripts/Outland/boss_doomwalker.cpp new file mode 100644 index 00000000000..60bcd7ee373 --- /dev/null +++ b/src/server/scripts/Outland/boss_doomwalker.cpp @@ -0,0 +1,178 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Doomwalker +SD%Complete: 100 +SDComment: +SDCategory: Shadowmoon Valley +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1000159 +#define SAY_EARTHQUAKE_1 -1000160 +#define SAY_EARTHQUAKE_2 -1000161 +#define SAY_OVERRUN_1 -1000162 +#define SAY_OVERRUN_2 -1000163 +#define SAY_SLAY_1 -1000164 +#define SAY_SLAY_2 -1000165 +#define SAY_SLAY_3 -1000166 +#define SAY_DEATH -1000167 + +#define SPELL_EARTHQUAKE 32686 +#define SPELL_SUNDER_ARMOR 33661 +#define SPELL_CHAIN_LIGHTNING 33665 +#define SPELL_OVERRUN 32636 +#define SPELL_ENRAGE 33653 +#define SPELL_MARK_DEATH 37128 +#define SPELL_AURA_DEATH 37131 + +struct boss_doomwalkerAI : public ScriptedAI +{ + boss_doomwalkerAI(Creature *c) : ScriptedAI(c) {} + + uint32 Chain_Timer; + uint32 Enrage_Timer; + uint32 Overrun_Timer; + uint32 Quake_Timer; + uint32 Armor_Timer; + + bool InEnrage; + + void Reset() + { + Enrage_Timer = 0; + Armor_Timer = 5000 + rand()%8000; + Chain_Timer = 10000 + rand()%20000; + Quake_Timer = 25000 + rand()%10000; + Overrun_Timer = 30000 + rand()%15000; + + InEnrage = false; + } + + void KilledUnit(Unit* Victim) + { + Victim->CastSpell(Victim,SPELL_MARK_DEATH,0); + + if (rand()%5) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void MoveInLineOfSight(Unit *who) + { + if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsHostileTo(who)) + { + if (who->HasAura(SPELL_MARK_DEATH,0)) + { + who->CastSpell(who,SPELL_AURA_DEATH,1); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Spell Enrage, when hp <= 20% gain enrage + if (((me->GetHealth()*100)/ me->GetMaxHealth()) <= 20) + { + if (Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enrage_Timer = 6000; + InEnrage = true; + } else Enrage_Timer -= diff; + } + + //Spell Overrun + if (Overrun_Timer <= diff) + { + DoScriptText(RAND(SAY_OVERRUN_1,SAY_OVERRUN_2), me); + + DoCast(me->getVictim(), SPELL_OVERRUN); + Overrun_Timer = 25000 + rand()%15000; + } else Overrun_Timer -= diff; + + //Spell Earthquake + if (Quake_Timer <= diff) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_EARTHQUAKE_1,SAY_EARTHQUAKE_2), me); + + //remove enrage before casting earthquake because enrage + earthquake = 16000dmg over 8sec and all dead + if (InEnrage) + me->RemoveAura(SPELL_ENRAGE); + + DoCast(me, SPELL_EARTHQUAKE); + Quake_Timer = 30000 + rand()%25000; + } else Quake_Timer -= diff; + + //Spell Chain Lightning + if (Chain_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + + Chain_Timer = 7000 + rand()%20000; + } else Chain_Timer -= diff; + + //Spell Sunder Armor + if (Armor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDER_ARMOR); + Armor_Timer = 10000 + rand()%15000; + } else Armor_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_doomwalker(Creature* pCreature) +{ + return new boss_doomwalkerAI (pCreature); +} + +void AddSC_boss_doomwalker() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_doomwalker"; + newscript->GetAI = &GetAI_boss_doomwalker; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp new file mode 100644 index 00000000000..69a969adda0 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp @@ -0,0 +1,746 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Fathomlord_Karathress +SD%Complete: 70 +SDComment: Cyclone workaround +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedEscortAI.h" + +#define SAY_AGGRO -1548021 +#define SAY_GAIN_BLESSING -1548022 +#define SAY_GAIN_ABILITY1 -1548023 +#define SAY_GAIN_ABILITY2 -1548024 +#define SAY_GAIN_ABILITY3 -1548025 +#define SAY_SLAY1 -1548026 +#define SAY_SLAY2 -1548027 +#define SAY_SLAY3 -1548028 +#define SAY_DEATH -1548029 + +//Karathress spells +#define SPELL_CATACLYSMIC_BOLT 38441 +#define SPELL_POWER_OF_SHARKKIS 38455 +#define SPELL_POWER_OF_TIDALVESS 38452 +#define SPELL_POWER_OF_CARIBDIS 38451 +#define SPELL_ENRAGE 24318 +#define SPELL_SEAR_NOVA 38445 +#define SPELL_BLESSING_OF_THE_TIDES 38449 + +//Sharkkis spells +#define SPELL_LEECHING_THROW 29436 +#define SPELL_THE_BEAST_WITHIN 38373 +#define SPELL_MULTISHOT 38366 +#define SPELL_SUMMON_FATHOM_LURKER 38433 +#define SPELL_SUMMON_FATHOM_SPOREBAT 38431 +#define SPELL_PET_ENRAGE 19574 + +//Tidalvess spells +#define SPELL_FROST_SHOCK 38234 +#define SPELL_SPITFIRE_TOTEM 38236 +#define SPELL_POISON_CLEANSING_TOTEM 38306 +// Spell obsolete +// #define SPELL_POISON_CLEANSING_EFFECT 8167 +#define SPELL_EARTHBIND_TOTEM 38304 +#define SPELL_EARTHBIND_TOTEM_EFFECT 6474 +#define SPELL_WINDFURY_WEAPON 38184 + +//Caribdis Spells +#define SPELL_WATER_BOLT_VOLLEY 38335 +#define SPELL_TIDAL_SURGE 38358 +#define SPELL_TIDAL_SURGE_FREEZE 38357 +#define SPELL_HEAL 38330 +#define SPELL_SUMMON_CYCLONE 38337 +#define SPELL_CYCLONE_CYCLONE 29538 + +//Yells and Quotes +#define SAY_GAIN_BLESSING_OF_TIDES "Your overconfidence will be your undoing! Guards, lend me your strength!" +#define SOUND_GAIN_BLESSING_OF_TIDES 11278 +#define SAY_MISC "Alana be'lendor!" //don't know what use this +#define SOUND_MISC 11283 + +//Summoned Unit GUIDs +#define CREATURE_CYCLONE 22104 +#define CREATURE_FATHOM_SPOREBAT 22120 +#define CREATURE_FATHOM_LURKER 22119 +#define CREATURE_SPITFIRE_TOTEM 22091 +#define CREATURE_EARTHBIND_TOTEM 22486 +#define CREATURE_POISON_CLEANSING_TOTEM 22487 + +//entry and position for Seer Olum +#define SEER_OLUM 22820 +#define OLUM_X 446.78f +#define OLUM_Y -542.76f +#define OLUM_Z -7.54773f +#define OLUM_O 0.401581f + +//Fathom-Lord Karathress AI +struct boss_fathomlord_karathressAI : public ScriptedAI +{ + boss_fathomlord_karathressAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Advisors[0] = 0; + Advisors[1] = 0; + Advisors[2] = 0; + } + + ScriptedInstance* pInstance; + + uint32 CataclysmicBolt_Timer; + uint32 Enrage_Timer; + uint32 SearNova_Timer; + + bool BlessingOfTides; + + uint64 Advisors[3]; + + void Reset() + { + CataclysmicBolt_Timer = 10000; + Enrage_Timer = 600000; //10 minutes + SearNova_Timer = 20000+rand()%40000; // 20 - 60 seconds + + BlessingOfTides = false; + + if (pInstance) + { + uint64 RAdvisors[3]; + RAdvisors[0] = pInstance->GetData64(DATA_SHARKKIS); + RAdvisors[1] = pInstance->GetData64(DATA_TIDALVESS); + RAdvisors[2] = pInstance->GetData64(DATA_CARIBDIS); + //Respawn of the 3 Advisors + Creature* pAdvisor = NULL; + for (int i=0; i<3; ++i) + + if (RAdvisors[i]) + { + pAdvisor = (Unit::GetCreature((*me), RAdvisors[i])); + if (pAdvisor && !pAdvisor->isAlive()) + { + pAdvisor->Respawn(); + pAdvisor->AI()->EnterEvadeMode(); + pAdvisor->GetMotionMaster()->MoveTargetedHome(); + } + } + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + } + + void EventSharkkisDeath() + { + DoScriptText(SAY_GAIN_ABILITY1, me); + DoCast(me, SPELL_POWER_OF_SHARKKIS); + } + + void EventTidalvessDeath() + { + DoScriptText(SAY_GAIN_ABILITY2, me); + DoCast(me, SPELL_POWER_OF_TIDALVESS); + } + + void EventCaribdisDeath() + { + DoScriptText(SAY_GAIN_ABILITY3, me); + DoCast(me, SPELL_POWER_OF_CARIBDIS); + } + + void GetAdvisors() + { + if (!pInstance) + return; + + Advisors[0] = pInstance->GetData64(DATA_SHARKKIS); + Advisors[1] = pInstance->GetData64(DATA_TIDALVESS); + Advisors[2] = pInstance->GetData64(DATA_CARIBDIS); + } + + void StartEvent(Unit *who) + { + if (!pInstance) + return; + + GetAdvisors(); + + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); + + //support for quest 10944 + me->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 3600000); + } + + void EnterCombat(Unit * who) + { + StartEvent(who); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + GetAdvisors(); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //CataclysmicBolt_Timer + if (CataclysmicBolt_Timer <= diff) + { + //select a random unit other than the main tank + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + + //if there aren't other units, cast on the tank + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget) + DoCast(pTarget, SPELL_CATACLYSMIC_BOLT); + CataclysmicBolt_Timer = 10000; + } else CataclysmicBolt_Timer -= diff; + + //SearNova_Timer + if (SearNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SEAR_NOVA); + SearNova_Timer = 20000+rand()%40000; + } else SearNova_Timer -= diff; + + //Enrage_Timer + if (Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enrage_Timer = 90000; + } else Enrage_Timer -= diff; + + //Blessing of Tides Trigger + if ((me->GetHealth()*100 / me->GetMaxHealth()) <= 75 && !BlessingOfTides) + { + BlessingOfTides = true; + bool continueTriggering = false; + Creature* Advisor; + for (uint8 i = 0; i < 4; ++i) + if (Advisors[i]) + { + Advisor = (Unit::GetCreature(*me, Advisors[i])); + if (Advisor && Advisor->isAlive()) + { + continueTriggering = true; + break; + } + } + if (continueTriggering) + { + DoCast(me, SPELL_BLESSING_OF_THE_TIDES); + me->MonsterYell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_GAIN_BLESSING_OF_TIDES); + } + } + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Sharkkis AI +struct boss_fathomguard_sharkkisAI : public ScriptedAI +{ + boss_fathomguard_sharkkisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 LeechingThrow_Timer; + uint32 TheBeastWithin_Timer; + uint32 Multishot_Timer; + uint32 Pet_Timer; + + bool pet; + + uint64 SummonedPet; + + void Reset() + { + LeechingThrow_Timer = 20000; + TheBeastWithin_Timer = 30000; + Multishot_Timer = 15000; + Pet_Timer = 10000; + + pet = false; + + Creature *Pet = Unit::GetCreature(*me, SummonedPet); + if (Pet && Pet->isAlive()) + { + Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + SummonedPet = 0; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //LeechingThrow_Timer + if (LeechingThrow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LEECHING_THROW); + LeechingThrow_Timer = 20000; + } else LeechingThrow_Timer -= diff; + + //Multishot_Timer + if (Multishot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MULTISHOT); + Multishot_Timer = 20000; + } else Multishot_Timer -= diff; + + //TheBeastWithin_Timer + if (TheBeastWithin_Timer <= diff) + { + DoCast(me, SPELL_THE_BEAST_WITHIN); + Creature *Pet = Unit::GetCreature(*me, SummonedPet); + if (Pet && Pet->isAlive()) + { + Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); + } + TheBeastWithin_Timer = 30000; + } else TheBeastWithin_Timer -= diff; + + //Pet_Timer + if (Pet_Timer < diff && pet == false) + { + pet = true; + //uint32 spell_id; + uint32 pet_id; + if (!urand(0,1)) + { + //spell_id = SPELL_SUMMON_FATHOM_LURKER; + pet_id = CREATURE_FATHOM_LURKER; + } + else + { + //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; + pet_id = CREATURE_FATHOM_SPOREBAT; + } + //DoCast(me, spell_id, true); + Creature *Pet = DoSpawnCreature(pet_id,0,0,0,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (Pet && pTarget) + { + Pet->AI()->AttackStart(pTarget); + SummonedPet = Pet->GetGUID(); + } + } else Pet_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Tidalvess AI +struct boss_fathomguard_tidalvessAI : public ScriptedAI +{ + boss_fathomguard_tidalvessAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 FrostShock_Timer; + uint32 Spitfire_Timer; + uint32 PoisonCleansing_Timer; + uint32 Earthbind_Timer; + + void Reset() + { + FrostShock_Timer = 25000; + Spitfire_Timer = 60000; + PoisonCleansing_Timer = 30000; + Earthbind_Timer = 45000; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + if (!me->isAlive() && Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventTidalvessDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + DoCast(me, SPELL_WINDFURY_WEAPON); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + if (!me->HasAura(SPELL_WINDFURY_WEAPON)) + { + DoCast(me, SPELL_WINDFURY_WEAPON); + } + + //FrostShock_Timer + if (FrostShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_SHOCK); + FrostShock_Timer = 25000+rand()%5000; + } else FrostShock_Timer -= diff; + + //Spitfire_Timer + if (Spitfire_Timer <= diff) + { + DoCast(me, SPELL_SPITFIRE_TOTEM); + Unit *SpitfireTotem = Unit::GetUnit(*me, CREATURE_SPITFIRE_TOTEM); + if (SpitfireTotem) + { + CAST_CRE(SpitfireTotem)->AI()->AttackStart(me->getVictim()); + } + Spitfire_Timer = 60000; + } else Spitfire_Timer -= diff; + + //PoisonCleansing_Timer + if (PoisonCleansing_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLEANSING_TOTEM); + PoisonCleansing_Timer = 30000; + } else PoisonCleansing_Timer -= diff; + + //Earthbind_Timer + if (Earthbind_Timer <= diff) + { + DoCast(me, SPELL_EARTHBIND_TOTEM); + Earthbind_Timer = 45000; + } else Earthbind_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Caribdis AI +struct boss_fathomguard_caribdisAI : public ScriptedAI +{ + boss_fathomguard_caribdisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 WaterBoltVolley_Timer; + uint32 TidalSurge_Timer; + uint32 Heal_Timer; + uint32 Cyclone_Timer; + + void Reset() + { + WaterBoltVolley_Timer = 35000; + TidalSurge_Timer = 15000+rand()%5000; + Heal_Timer = 55000; + Cyclone_Timer = 30000+rand()%10000; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + if (!me->isAlive() && Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventCaribdisDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //WaterBoltVolley_Timer + if (WaterBoltVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WATER_BOLT_VOLLEY); + WaterBoltVolley_Timer = 30000; + } else WaterBoltVolley_Timer -= diff; + + //TidalSurge_Timer + if (TidalSurge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIDAL_SURGE); + // Hacky way to do it - won't trigger elseways + me->getVictim()->CastSpell(me->getVictim(), SPELL_TIDAL_SURGE_FREEZE, true); + TidalSurge_Timer = 15000+rand()%5000; + } else TidalSurge_Timer -= diff; + + //Cyclone_Timer + if (Cyclone_Timer <= diff) + { + //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work + Cyclone_Timer = 30000+rand()%10000; + Creature *Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000); + if (Cyclone) + { + CAST_CRE(Cyclone)->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); + Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Cyclone->setFaction(me->getFaction()); + Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Cyclone->AI()->AttackStart(pTarget); + } + } + } else Cyclone_Timer -= diff; + + //Heal_Timer + if (Heal_Timer <= diff) + { + // It can be cast on any of the mobs + Unit *pUnit = NULL; + + while (pUnit == NULL || !pUnit->isAlive()) + { + pUnit = selectAdvisorUnit(); + } + + if (pUnit && pUnit->isAlive()) + DoCast(pUnit, SPELL_HEAL); + Heal_Timer = 60000; + } else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + Unit* selectAdvisorUnit() + { + Unit* pUnit = NULL; + if (pInstance) + { + switch(rand()%4) + { + case 0: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESS)); + break; + case 1: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_SHARKKIS)); + break; + case 2: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_TIDALVESS)); + break; + case 3: + pUnit = me; + break; + } + } else pUnit = me; + + return pUnit; + } +}; + +CreatureAI* GetAI_boss_fathomlord_karathress(Creature* pCreature) +{ + return new boss_fathomlord_karathressAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_sharkkis(Creature* pCreature) +{ + return new boss_fathomguard_sharkkisAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_tidalvess(Creature* pCreature) +{ + return new boss_fathomguard_tidalvessAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_caribdis(Creature* pCreature) +{ + return new boss_fathomguard_caribdisAI (pCreature); +} + +void AddSC_boss_fathomlord_karathress() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_fathomlord_karathress"; + newscript->GetAI = &GetAI_boss_fathomlord_karathress; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_sharkkis"; + newscript->GetAI = &GetAI_boss_fathomguard_sharkkis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_tidalvess"; + newscript->GetAI = &GetAI_boss_fathomguard_tidalvess; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_caribdis"; + newscript->GetAI = &GetAI_boss_fathomguard_caribdis; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp new file mode 100644 index 00000000000..923fdf55f80 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp @@ -0,0 +1,379 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hydross_The_Unstable +SD%Complete: 90 +SDComment: Some details and adjustments left to do, probably nothing major. Spawns may be spawned in different way/location. +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define SAY_AGGRO -1548000 +#define SAY_SWITCH_TO_CLEAN -1548001 +#define SAY_CLEAN_SLAY1 -1548002 +#define SAY_CLEAN_SLAY2 -1548003 +#define SAY_CLEAN_DEATH -1548004 +#define SAY_SWITCH_TO_CORRUPT -1548005 +#define SAY_CORRUPT_SLAY1 -1548006 +#define SAY_CORRUPT_SLAY2 -1548007 +#define SAY_CORRUPT_DEATH -1548008 + +#define SWITCH_RADIUS 18 + +#define MODEL_CORRUPT 20609 +#define MODEL_CLEAN 20162 + +#define SPELL_WATER_TOMB 38235 +#define SPELL_MARK_OF_HYDROSS1 38215 +#define SPELL_MARK_OF_HYDROSS2 38216 +#define SPELL_MARK_OF_HYDROSS3 38217 +#define SPELL_MARK_OF_HYDROSS4 38218 +#define SPELL_MARK_OF_HYDROSS5 38231 +#define SPELL_MARK_OF_HYDROSS6 40584 +#define SPELL_MARK_OF_CORRUPTION1 38219 +#define SPELL_MARK_OF_CORRUPTION2 38220 +#define SPELL_MARK_OF_CORRUPTION3 38221 +#define SPELL_MARK_OF_CORRUPTION4 38222 +#define SPELL_MARK_OF_CORRUPTION5 38230 +#define SPELL_MARK_OF_CORRUPTION6 40583 +#define SPELL_VILE_SLUDGE 38246 +#define SPELL_ENRAGE 27680 //this spell need verification +#define SPELL_SUMMON_WATER_ELEMENT 36459 //not in use yet(in use ever?) +#define SPELL_ELEMENTAL_SPAWNIN 25035 +#define SPELL_BLUE_BEAM 40227 //channeled Hydross Beam Helper (not in use yet) + +#define ENTRY_PURE_SPAWN 22035 +#define ENTRY_TAINTED_SPAWN 22036 +#define ENTRY_BEAM_DUMMY 21934 + +#define HYDROSS_X -239.439 +#define HYDROSS_Y -363.481 + +#define SPAWN_X_DIFF1 6.934003 +#define SPAWN_Y_DIFF1 -11.255012 +#define SPAWN_X_DIFF2 -6.934003 +#define SPAWN_Y_DIFF2 11.255012 +#define SPAWN_X_DIFF3 -12.577011 +#define SPAWN_Y_DIFF3 -4.72702 +#define SPAWN_X_DIFF4 12.577011 +#define SPAWN_Y_DIFF4 4.72702 + +struct boss_hydross_the_unstableAI : public ScriptedAI +{ + boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 beams[2]; + uint32 PosCheck_Timer; + uint32 MarkOfHydross_Timer; + uint32 MarkOfCorruption_Timer; + uint32 WaterTomb_Timer; + uint32 VileSludge_Timer; + uint32 MarkOfHydross_Count; + uint32 MarkOfCorruption_Count; + uint32 EnrageTimer; + bool CorruptedForm; + bool beam; + SummonList Summons; + + void Reset() + { + DeSummonBeams(); + beams[0] = 0; + beams[1] = 0; + PosCheck_Timer = 2500; + MarkOfHydross_Timer = 15000; + MarkOfCorruption_Timer = 15000; + WaterTomb_Timer = 7000; + VileSludge_Timer = 7000; + MarkOfHydross_Count = 0; + MarkOfCorruption_Count = 0; + EnrageTimer = 600000; + + CorruptedForm = false; + me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + + me->SetDisplayId(MODEL_CLEAN); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); + beam = false; + Summons.DespawnAll(); + } + + void SummonBeams() + { + Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-258.333,-356.34,22.0499,5.90835,TEMPSUMMON_CORPSE_DESPAWN,0); + if (beamer) + { + beamer->CastSpell(me,SPELL_BLUE_BEAM,true); + beamer->SetDisplayId(11686); //invisible + beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + beams[0]=beamer->GetGUID(); + } + beamer = beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-219.918,-371.308,22.0042,2.73072,TEMPSUMMON_CORPSE_DESPAWN,0); + if (beamer) + { + beamer->CastSpell(me,SPELL_BLUE_BEAM,true); + beamer->SetDisplayId(11686); //invisible + beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + beams[1]=beamer->GetGUID(); + } + } + void DeSummonBeams() + { + for (uint8 i=0; i<2; ++i) + { + Creature* mob = Unit::GetCreature(*me,beams[i]); + if (mob) + { + mob->setDeathState(DEAD); + mob->RemoveCorpse(); + } + } + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + if (CorruptedForm) + { + DoScriptText(RAND(SAY_CORRUPT_SLAY1,SAY_CORRUPT_SLAY2), me); + } + else + { + DoScriptText(RAND(SAY_CLEAN_SLAY1,SAY_CLEAN_SLAY2), me); + } + } + + void JustSummoned(Creature* summoned) + { + if (summoned->GetEntry() == ENTRY_PURE_SPAWN) + { + summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); + Summons.Summon(summoned); + } + if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN) + { + summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); + Summons.Summon(summoned); + } + } + + void SummonedCreatureDespawn(Creature *summon) + { + Summons.Despawn(summon); + } + + void JustDied(Unit * /*victim*/) + { + if (CorruptedForm) + DoScriptText(SAY_CORRUPT_DEATH, me); + else + DoScriptText(SAY_CLEAN_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, DONE); + Summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!beam) + { + SummonBeams(); + beam=true; + } + //Return since we have no target + if (!UpdateVictim()) + return; + + // corrupted form + if (CorruptedForm) + { + //MarkOfCorruption_Timer + if (MarkOfCorruption_Timer <= diff) + { + if (MarkOfCorruption_Count <= 5) + { + uint32 mark_spell = 0; + + switch (MarkOfCorruption_Count) + { + case 0: mark_spell = SPELL_MARK_OF_CORRUPTION1; break; + case 1: mark_spell = SPELL_MARK_OF_CORRUPTION2; break; + case 2: mark_spell = SPELL_MARK_OF_CORRUPTION3; break; + case 3: mark_spell = SPELL_MARK_OF_CORRUPTION4; break; + case 4: mark_spell = SPELL_MARK_OF_CORRUPTION5; break; + case 5: mark_spell = SPELL_MARK_OF_CORRUPTION6; break; + } + + DoCast(me->getVictim(), mark_spell); + + if (MarkOfCorruption_Count < 5) + ++MarkOfCorruption_Count; + } + + MarkOfCorruption_Timer = 15000; + } else MarkOfCorruption_Timer -= diff; + + //VileSludge_Timer + if (VileSludge_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_VILE_SLUDGE); + + VileSludge_Timer = 15000; + } else VileSludge_Timer -= diff; + + //PosCheck_Timer + if (PosCheck_Timer <= diff) + { + if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) + { + // switch to clean form + me->SetDisplayId(MODEL_CLEAN); + CorruptedForm = false; + MarkOfHydross_Count = 0; + + DoScriptText(SAY_SWITCH_TO_CLEAN, me); + DoResetThreat(); + SummonBeams(); + + // spawn 4 adds + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + } + + PosCheck_Timer = 2500; + } else PosCheck_Timer -=diff; + } + // clean form + else + { + //MarkOfHydross_Timer + if (MarkOfHydross_Timer <= diff) + { + if (MarkOfHydross_Count <= 5) + { + uint32 mark_spell = NULL; + + switch(MarkOfHydross_Count) + { + case 0: mark_spell = SPELL_MARK_OF_HYDROSS1; break; + case 1: mark_spell = SPELL_MARK_OF_HYDROSS2; break; + case 2: mark_spell = SPELL_MARK_OF_HYDROSS3; break; + case 3: mark_spell = SPELL_MARK_OF_HYDROSS4; break; + case 4: mark_spell = SPELL_MARK_OF_HYDROSS5; break; + case 5: mark_spell = SPELL_MARK_OF_HYDROSS6; break; + } + + DoCast(me->getVictim(), mark_spell); + + if (MarkOfHydross_Count < 5) + ++MarkOfHydross_Count; + } + + MarkOfHydross_Timer = 15000; + } else MarkOfHydross_Timer -= diff; + + //WaterTomb_Timer + if (WaterTomb_Timer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget) + DoCast(pTarget, SPELL_WATER_TOMB); + + WaterTomb_Timer = 7000; + } else WaterTomb_Timer -= diff; + + //PosCheck_Timer + if (PosCheck_Timer <= diff) + { + if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) + { + // switch to corrupted form + me->SetDisplayId(MODEL_CORRUPT); + MarkOfCorruption_Count = 0; + CorruptedForm = true; + + DoScriptText(SAY_SWITCH_TO_CORRUPT, me); + DoResetThreat(); + DeSummonBeams(); + + // spawn 4 adds + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + } + + PosCheck_Timer = 2500; + } else PosCheck_Timer -=diff; + } + + //EnrageTimer + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_ENRAGE); + EnrageTimer = 60000; + } else EnrageTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hydross_the_unstable(Creature* pCreature) +{ + return new boss_hydross_the_unstableAI (pCreature); +} + +void AddSC_boss_hydross_the_unstable() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hydross_the_unstable"; + newscript->GetAI = &GetAI_boss_hydross_the_unstable; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp new file mode 100644 index 00000000000..2f0485d0e6c --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp @@ -0,0 +1,1039 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA + */ + +/* ScriptData +SDName: Boss_Lady_Vashj +SD%Complete: 99 +SDComment: Missing blizzlike Shield Generators coords +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedSimpleAI.h" +#include "Spell.h" + +#define SAY_INTRO -1548042 +#define SAY_AGGRO1 -1548043 +#define SAY_AGGRO2 -1548044 +#define SAY_AGGRO3 -1548045 +#define SAY_AGGRO4 -1548046 +#define SAY_PHASE1 -1548047 +#define SAY_PHASE2 -1548048 +#define SAY_PHASE3 -1548049 +#define SAY_BOWSHOT1 -1548050 +#define SAY_BOWSHOT2 -1548051 +#define SAY_SLAY1 -1548052 +#define SAY_SLAY2 -1548053 +#define SAY_SLAY3 -1548054 +#define SAY_DEATH -1548055 + +#define SPELL_SURGE 38044 +#define SPELL_MULTI_SHOT 38310 +#define SPELL_SHOCK_BLAST 38509 +#define SPELL_ENTANGLE 38316 +#define SPELL_STATIC_CHARGE_TRIGGER 38280 +#define SPELL_FORKED_LIGHTNING 40088 +#define SPELL_SHOOT 40873 +#define SPELL_POISON_BOLT 40095 +#define SPELL_TOXIC_SPORES 38575 +#define SPELL_MAGIC_BARRIER 38112 + +#define MIDDLE_X 30.134 +#define MIDDLE_Y -923.65 +#define MIDDLE_Z 42.9 + +#define SPOREBAT_X 30.977156 +#define SPOREBAT_Y -925.297761 +#define SPOREBAT_Z 77.176567 +#define SPOREBAT_O 5.223932 + +#define SHIED_GENERATOR_CHANNEL 19870 +#define ENCHANTED_ELEMENTAL 21958 +#define TAINTED_ELEMENTAL 22009 +#define COILFANG_STRIDER 22056 +#define COILFANG_ELITE 22055 +#define TOXIC_SPOREBAT 22140 +#define TOXIC_SPORES_TRIGGER 22207 + +#define TEXT_NOT_INITIALIZED "Instance script not initialized" +#define TEXT_ALREADY_DEACTIVATED "Already deactivated" + +float ElementPos[8][4] = +{ + {8.3, -835.3, 21.9, 5}, + {53.4, -835.3, 21.9, 4.5}, + {96, -861.9, 21.8, 4}, + {96, -986.4, 21.4, 2.5}, + {54.4, -1010.6, 22, 1.8}, + {9.8, -1012, 21.7, 1.4}, + {-35, -987.6, 21.5, 0.8}, + {-58.9, -901.6, 21.5, 6} +}; + +float ElementWPPos[8][3] = +{ + {71.700752, -883.905884, 41.097168}, + {45.039848, -868.022827, 41.097015}, + {14.585141, -867.894470, 41.097061}, + {-25.415508, -906.737732, 41.097061}, + {-11.801594, -963.405884, 41.097067}, + {14.556657, -979.051514, 41.097137}, + {43.466549, -979.406677, 41.097027}, + {69.945908, -964.663940, 41.097054} +}; + +float SporebatWPPos[8][3] = +{ + {31.6,-896.3,59.1}, + {9.1, -913.9, 56}, + {5.2, -934.4, 52.4}, + {20.7, -946.9, 49.7}, + {41, -941.9, 51}, + {47.7, -927.3, 55}, + {42.2, -912.4, 51.7}, + {27, -905.9, 50} +}; + +float CoilfangElitePos[3][4] = +{ + {28.84, -923.28, 42.9, 6}, + {31.183281, -953.502625, 41.523602, 1.640957}, + {58.895180, -923.124268, 41.545307, 3.152848} +}; + +float CoilfangStriderPos[3][4] = +{ + {66.427010, -948.778503, 41.262245, 2.584220}, + {7.513962, -959.538208, 41.300422, 1.034629}, + {-12.843201, -907.798401, 41.239620, 6.087094} +}; + +float ShieldGeneratorChannelPos[4][4] = +{ + {49.6262, -902.181, 43.0975, 3.95683}, + {10.988, -901.616, 42.5371, 5.4373}, + {10.3859, -944.036, 42.5446, 0.779888}, + {49.3126, -943.398, 42.5501, 2.40174} +}; + +//Lady Vashj AI +struct boss_lady_vashjAI : public ScriptedAI +{ + boss_lady_vashjAI (Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = false; + JustCreated = true; + c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //set it only once on Creature create (no need do intro if wiped) + } + + ScriptedInstance *pInstance; + + uint64 ShieldGeneratorChannel[4]; + + uint32 AggroTimer; + uint32 ShockBlast_Timer; + uint32 Entangle_Timer; + uint32 StaticCharge_Timer; + uint32 ForkedLightning_Timer; + uint32 Check_Timer; + uint32 EnchantedElemental_Timer; + uint32 TaintedElemental_Timer; + uint32 CoilfangElite_Timer; + uint32 CoilfangStrider_Timer; + uint32 SummonSporebat_Timer; + uint32 SummonSporebat_StaticTimer; + uint8 EnchantedElemental_Pos; + uint8 Phase; + + bool Entangle; + bool Intro; + bool CanAttack; + bool JustCreated; + + void Reset() + { + AggroTimer = 19000; + ShockBlast_Timer = 1+rand()%60000; + Entangle_Timer = 30000; + StaticCharge_Timer = 10000+rand()%15000; + ForkedLightning_Timer = 2000; + Check_Timer = 15000; + EnchantedElemental_Timer = 5000; + TaintedElemental_Timer = 50000; + CoilfangElite_Timer = 45000+rand()%5000; + CoilfangStrider_Timer = 60000+rand()%10000; + SummonSporebat_Timer = 10000; + SummonSporebat_StaticTimer = 30000; + EnchantedElemental_Pos = 0; + Phase = 0; + + Entangle = false; + if (JustCreated) + { + CanAttack = false; + JustCreated = false; + } else CanAttack = true; + + Unit *remo; + for (uint8 i = 0; i < 4; ++i) + { + remo = Unit::GetUnit(*me, ShieldGeneratorChannel[i]); + if (remo) + remo->setDeathState(JUST_DIED); + } + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED); + ShieldGeneratorChannel[0] = 0; + ShieldGeneratorChannel[1] = 0; + ShieldGeneratorChannel[2] = 0; + ShieldGeneratorChannel[3] = 0; + + me->SetCorpseDelay(1000*60*60); + } + + //Called when a tainted elemental dies + void EventTaintedElementalDeath() + { + //the next will spawn 50 seconds after the previous one's death + if (TaintedElemental_Timer > 50000) + TaintedElemental_Timer = 50000; + } + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, DONE); + } + + void StartEvent() + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3,SAY_AGGRO4), me); + + Phase = 1; + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + //remove old tainted cores to prevent cheating in phase 2 + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* i_pl = i->getSource()) + { + i_pl->DestroyItemCount(31088, 1, true); + } + } + } + StartEvent();//this is EnterCombat(), so were are 100% in combat, start the event + + if (Phase != 2) + AttackStart(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (!Intro) + { + Intro = true; + DoScriptText(SAY_INTRO, me); + } + if (!CanAttack) + return; + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) + { + //if (who->HasStealthAura()) + // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!me->isInCombat())//AttackStart() sets UNIT_FLAG_IN_COMBAT, so this msut be before attacking + StartEvent(); + + if (Phase != 2) + AttackStart(who); + } + } + } + + void CastShootOrMultishot() + { + switch (urand(0,1)) + { + case 0: + //Shoot + //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. + DoCast(me->getVictim(), SPELL_SHOOT); + break; + case 1: + //Multishot + //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. + DoCast(me->getVictim(), SPELL_MULTI_SHOT); + break; + } + if (rand()%3) + { + DoScriptText(RAND(SAY_BOWSHOT1,SAY_BOWSHOT2), me); + } + } + + void UpdateAI(const uint32 diff) + { + if (!CanAttack && Intro) + { + if (AggroTimer <= diff) + { + CanAttack = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer=19000; + }else + { + AggroTimer-=diff; + return; + } + } + //to prevent abuses during phase 2 + if (Phase == 2 && !me->getVictim() && me->isInCombat()) + { + EnterEvadeMode(); + return; + } + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Phase == 1 || Phase == 3) + { + //ShockBlast_Timer + if (ShockBlast_Timer <= diff) + { + //Shock Burst + //Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. + DoCast(me->getVictim(), SPELL_SHOCK_BLAST); + me->TauntApply(me->getVictim()); + + ShockBlast_Timer = 1000+rand()%14000; //random cooldown + } else ShockBlast_Timer -= diff; + + //StaticCharge_Timer + if (StaticCharge_Timer <= diff) + { + //Static Charge + //Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. + Unit *pTarget = NULL; + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true); + + if (pTarget && !pTarget->HasAura(SPELL_STATIC_CHARGE_TRIGGER)) + //cast Static Charge every 2 seconds for 20 seconds + DoCast(pTarget, SPELL_STATIC_CHARGE_TRIGGER); + + StaticCharge_Timer = 10000+rand()%20000; //blizzlike + } else StaticCharge_Timer -= diff; + + //Entangle_Timer + if (Entangle_Timer <= diff) + { + if (!Entangle) + { + //Entangle + //Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. + DoCast(me->getVictim(), SPELL_ENTANGLE); + Entangle = true; + Entangle_Timer = 10000; + } + else + { + CastShootOrMultishot(); + Entangle = false; + Entangle_Timer = 20000+rand()%5000; + } + } else Entangle_Timer -= diff; + + //Phase 1 + if (Phase == 1) + { + //Start phase 2 + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 70) + { + //Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. + Phase = 2; + + me->GetMotionMaster()->Clear(); + DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + + Creature *pCreature; + for (uint8 i = 0; i < 4; ++i) + { + pCreature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0], ShieldGeneratorChannelPos[i][1], ShieldGeneratorChannelPos[i][2], ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + if (pCreature) + ShieldGeneratorChannel[i] = pCreature->GetGUID(); + } + DoScriptText(SAY_PHASE2, me); + } + } + //Phase 3 + else + { + //SummonSporebat_Timer + if (SummonSporebat_Timer <= diff) + { + Creature *Sporebat = NULL; + Sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (Sporebat) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Sporebat->AI()->AttackStart(pTarget); + } + + //summon sporebats faster and faster + if (SummonSporebat_StaticTimer > 1000) + SummonSporebat_StaticTimer -= 1000; + + SummonSporebat_Timer = SummonSporebat_StaticTimer; + + if (SummonSporebat_Timer < 5000) + SummonSporebat_Timer = 5000; + + } else SummonSporebat_Timer -= diff; + } + + //Melee attack + DoMeleeAttackIfReady(); + + //Check_Timer - used to check if somebody is in melee range + if (Check_Timer <= diff) + { + bool InMeleeRange = false; + Unit *pTarget; + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //if in melee range + if (pTarget && pTarget->IsWithinDistInMap(me, 5)) + { + InMeleeRange = true; + break; + } + } + + //if nobody is in melee range + if (!InMeleeRange) + CastShootOrMultishot(); + + Check_Timer = 5000; + } else Check_Timer -= diff; + } + //Phase 2 + else + { + //ForkedLightning_Timer + if (ForkedLightning_Timer <= diff) + { + //Forked Lightning + //Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (!pTarget) + pTarget = me->getVictim(); + + DoCast(pTarget, SPELL_FORKED_LIGHTNING); + + ForkedLightning_Timer = 2000+rand()%6000; //blizzlike + } else ForkedLightning_Timer -= diff; + + //EnchantedElemental_Timer + if (EnchantedElemental_Timer <= diff) + { + Creature *Elemental; + Elemental = me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (EnchantedElemental_Pos == 7) + EnchantedElemental_Pos = 0; + else + ++EnchantedElemental_Pos; + + EnchantedElemental_Timer = 10000+rand()%5000; + } else EnchantedElemental_Timer -= diff; + + //TaintedElemental_Timer + if (TaintedElemental_Timer <= diff) + { + Creature *Tain_Elemental; + uint32 pos = rand()%8; + Tain_Elemental = me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN, 0); + + TaintedElemental_Timer = 120000; + } else TaintedElemental_Timer -= diff; + + //CoilfangElite_Timer + if (CoilfangElite_Timer <= diff) + { + uint32 pos = rand()%3; + Creature* CoilfangElite = NULL; + CoilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (CoilfangElite) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + CoilfangElite->AI()->AttackStart(pTarget); + else if (me->getVictim()) + CoilfangElite->AI()->AttackStart(me->getVictim()); + } + CoilfangElite_Timer = 45000+rand()%5000; + } else CoilfangElite_Timer -= diff; + + //CoilfangStrider_Timer + if (CoilfangStrider_Timer <= diff) + { + uint32 pos = rand()%3; + Creature* CoilfangStrider = NULL; + CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (CoilfangStrider) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + CoilfangStrider->AI()->AttackStart(pTarget); + else if (me->getVictim()) + CoilfangStrider->AI()->AttackStart(me->getVictim()); + } + CoilfangStrider_Timer = 60000+rand()%10000; + } else CoilfangStrider_Timer -= diff; + + //Check_Timer + if (Check_Timer <= diff) + { + //Start Phase 3 + if (pInstance && pInstance->GetData(DATA_CANSTARTPHASE3)) + { + //set life 50% + me->SetHealth(me->GetMaxHealth()/2); + + me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); + + DoScriptText(SAY_PHASE3, me); + + Phase = 3; + + //return to the tank + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + Check_Timer = 1000; + } else Check_Timer -= diff; + } + } +}; + +//Enchanted Elemental +//If one of them reaches Vashj he will increase her damage done by 5%. +struct mob_enchanted_elementalAI : public ScriptedAI +{ + mob_enchanted_elementalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 move; + uint32 phase; + float x, y, z; + + uint64 VashjGUID; + + void Reset() + { + me->SetSpeed(MOVE_WALK,0.6);//walk + me->SetSpeed(MOVE_RUN,0.6);//run + move = 0; + phase = 1; + + VashjGUID = 0; + + for (int i = 0; i<8; ++i)//search for nearest waypoint (up on stairs) + { + if (!x || !y || !z) + { + x = ElementWPPos[i][0]; + y = ElementWPPos[i][1]; + z = ElementWPPos[i][2]; + } + else + { + if (me->GetDistance(ElementWPPos[i][0],ElementWPPos[i][1],ElementWPPos[i][2]) < me->GetDistance(x,y,z)) + { + x = ElementWPPos[i][0]; + y = ElementWPPos[i][1]; + z = ElementWPPos[i][2]; + } + } + } + if (pInstance) + VashjGUID = pInstance->GetData64(DATA_LADYVASHJ); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (!VashjGUID) + return; + + if (move <= diff) + { + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + if (phase == 1) + me->GetMotionMaster()->MovePoint(0, x, y, z); + if (phase == 1 && me->IsWithinDist3d(x,y,z, 0.1)) + phase = 2; + if (phase == 2) + { + me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + phase = 3; + } + if (phase == 3) + { + me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + if (me->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) + DoCast(me, SPELL_SURGE); + } + if (Creature *Vashj = Unit::GetCreature(*me, VashjGUID)) + { + if (!Vashj->isInCombat() || CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase != 2 || Vashj->isDead()) + { + //call Unsummon() + me->Kill(me); + } + } + move = 1000; + } else move -= diff; + } +}; + +//Tainted Elemental +//This mob has 7,900 life, doesn't move, and shoots Poison Bolts at one person anywhere in the area, doing 3,000 nature damage and placing a posion doing 2,000 damage every 2 seconds. He will switch targets often, or sometimes just hang on a single player, but there is nothing you can do about it except heal the damage and kill the Tainted Elemental +struct mob_tainted_elementalAI : public ScriptedAI +{ + mob_tainted_elementalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 PoisonBolt_Timer; + uint32 Despawn_Timer; + + void Reset() + { + PoisonBolt_Timer = 5000+rand()%5000; + Despawn_Timer = 30000; + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + { + Creature *Vashj = NULL; + Vashj = (Unit::GetCreature((*me), pInstance->GetData64(DATA_LADYVASHJ))); + + if (Vashj) + CAST_AI(boss_lady_vashjAI, Vashj->AI())->EventTaintedElementalDeath(); + } + } + + void EnterCombat(Unit * who) + { + me->AddThreat(who, 0.1f); + } + + void UpdateAI(const uint32 diff) + { + //PoisonBolt_Timer + if (PoisonBolt_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget && pTarget->IsWithinDistInMap(me, 30)) + DoCast(pTarget, SPELL_POISON_BOLT); + + PoisonBolt_Timer = 5000+rand()%5000; + } else PoisonBolt_Timer -= diff; + + //Despawn_Timer + if (Despawn_Timer <= diff) + { + //call Unsummon() + me->setDeathState(DEAD); + + //to prevent crashes + Despawn_Timer = 1000; + } else Despawn_Timer -= diff; + } +}; + +//Toxic Sporebat +//Toxic Spores: Used in Phase 3 by the Spore Bats, it creates a contaminated green patch of ground, dealing about 2775-3225 nature damage every second to anyone who stands in it. +struct mob_toxic_sporebatAI : public ScriptedAI +{ + mob_toxic_sporebatAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EnterEvadeMode(); + } + + ScriptedInstance *pInstance; + + uint32 movement_timer; + uint32 ToxicSpore_Timer; + uint32 bolt_timer; + uint32 Check_Timer; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->setFaction(14); + movement_timer = 0; + ToxicSpore_Timer = 5000; + bolt_timer = 5500; + Check_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + + } + + void MoveInLineOfSight(Unit * /*who*/) + { + + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + movement_timer = 0; + } + + void UpdateAI (const uint32 diff) + { + //Random movement + if (movement_timer <= diff) + { + uint32 rndpos = rand()%8; + me->GetMotionMaster()->MovePoint(1,SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]); + movement_timer = 6000; + } else movement_timer -= diff; + + //toxic spores + if (bolt_timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); + if (trig) + { + trig->setFaction(14); + trig->CastSpell(trig, SPELL_TOXIC_SPORES,true); + } + } + bolt_timer = 10000+rand()%5000; + } + else bolt_timer -= diff; + + //Check_Timer + if (Check_Timer <= diff) + { + if (pInstance) + { + //check if vashj is death + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); + if (!Vashj || (Vashj && !Vashj->isAlive()) || (Vashj && CAST_AI(boss_lady_vashjAI, CAST_CRE(Vashj)->AI())->Phase != 3)) + { + //remove + me->setDeathState(DEAD); + me->RemoveCorpse(); + me->setFaction(35); + } + } + + Check_Timer = 1000; + } else Check_Timer -= diff; + } +}; + +//Coilfang Elite +//It's an elite Naga mob with 170,000 HP. It does about 5000 damage on plate, and has a nasty cleave hitting for about 7500 damage +CreatureAI* GetAI_mob_coilfang_elite(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 31345; //Cleave + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].CooldownRandomAddition = 5000; + ai->Spell[0].First_Cast = 5000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_RANDOM; + + ai->EnterEvadeMode(); + + return ai; +} + +//Coilfang Strider +//It hits plate for about 8000 damage, has a Mind Blast spell doing about 3000 shadow damage, and a Psychic Scream Aura, which fears everybody in a 8 yard range of it every 2-3 seconds , for 5 seconds and increasing their movement speed by 150% during the fear. +CreatureAI* GetAI_mob_coilfang_strider(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 41374; //Mind Blast + ai->Spell[0].Cooldown = 30000; + ai->Spell[0].CooldownRandomAddition = 10000; + ai->Spell[0].First_Cast = 8000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + //Scream aura not implemented + + ai->EnterEvadeMode(); + + return ai; +} + +struct mob_shield_generator_channelAI : public ScriptedAI +{ + mob_shield_generator_channelAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 Check_Timer; + bool Casted; + void Reset() + { + Check_Timer = 0; + Casted = false; + me->SetDisplayId(11686); //invisible + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI (const uint32 diff) + { + if (!pInstance) + return; + + if (Check_Timer <= diff) + { + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); + + if (Vashj && Vashj->isAlive()) + { + //start visual channel + if (!Casted || !Vashj->HasAura(SPELL_MAGIC_BARRIER)) + { + DoCast(Vashj, SPELL_MAGIC_BARRIER, true); + Casted = true; + } + } + Check_Timer = 1000; + } else Check_Timer -= diff; + } +}; + +bool ItemUse_item_tainted_core(Player* pPlayer, Item* /*_Item*/, SpellCastTargets const& targets) +{ + ScriptedInstance *pInstance = pPlayer->GetInstanceData(); + + if (!pInstance) + { + pPlayer->GetSession()->SendNotification(TEXT_NOT_INITIALIZED); + return true; + } + + Creature *Vashj = NULL; + Vashj = (Unit::GetCreature((*pPlayer), pInstance->GetData64(DATA_LADYVASHJ))); + if (Vashj && CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase == 2) + { + if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT) + { + uint32 identifier; + uint8 channel_identifier; + switch(targets.getGOTarget()->GetEntry()) + { + case 185052: + identifier = DATA_SHIELDGENERATOR1; + channel_identifier = 0; + break; + case 185053: + identifier = DATA_SHIELDGENERATOR2; + channel_identifier = 1; + break; + case 185051: + identifier = DATA_SHIELDGENERATOR3; + channel_identifier = 2; + break; + case 185054: + identifier = DATA_SHIELDGENERATOR4; + channel_identifier = 3; + break; + default: + return true; + } + + if (pInstance->GetData(identifier)) + { + pPlayer->GetSession()->SendNotification(TEXT_ALREADY_DEACTIVATED); + return true; + } + + //get and remove channel + Unit *Channel = NULL; + Channel = Unit::GetCreature(*Vashj, CAST_AI(boss_lady_vashjAI, Vashj->AI())->ShieldGeneratorChannel[channel_identifier]); + if (Channel) + { + //call Unsummon() + Channel->setDeathState(JUST_DIED); + } + + pInstance->SetData(identifier, 1); + + //remove this item + pPlayer->DestroyItemCount(31088, 1, true); + return true; + } + else if (targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT) + return false; + else if (targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) + { + pPlayer->DestroyItemCount(31088, 1, true); + pPlayer->CastSpell(targets.getUnitTarget(), 38134, true); + return true; + } + } + return true; +} + +CreatureAI* GetAI_boss_lady_vashj(Creature* pCreature) +{ + return new boss_lady_vashjAI (pCreature); +} + +CreatureAI* GetAI_mob_enchanted_elemental(Creature* pCreature) +{ + return new mob_enchanted_elementalAI (pCreature); +} + +CreatureAI* GetAI_mob_tainted_elemental(Creature* pCreature) +{ + return new mob_tainted_elementalAI (pCreature); +} + +CreatureAI* GetAI_mob_toxic_sporebat(Creature* pCreature) +{ + return new mob_toxic_sporebatAI (pCreature); +} + +CreatureAI* GetAI_mob_shield_generator_channel(Creature* pCreature) +{ + return new mob_shield_generator_channelAI (pCreature); +} + +void AddSC_boss_lady_vashj() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lady_vashj"; + newscript->GetAI = &GetAI_boss_lady_vashj; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_enchanted_elemental"; + newscript->GetAI = &GetAI_mob_enchanted_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tainted_elemental"; + newscript->GetAI = &GetAI_mob_tainted_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toxic_sporebat"; + newscript->GetAI = &GetAI_mob_toxic_sporebat; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_elite"; + newscript->GetAI = &GetAI_mob_coilfang_elite; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_strider"; + newscript->GetAI = &GetAI_mob_coilfang_strider; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shield_generator_channel"; + newscript->GetAI = &GetAI_mob_shield_generator_channel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_tainted_core"; + newscript->pItemUse = &ItemUse_item_tainted_core; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp new file mode 100644 index 00000000000..61c9ed9d527 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp @@ -0,0 +1,787 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Leotheras_The_Blind +SD%Complete: 80 +SDComment: Possesion Support +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +// --- Spells used by Leotheras The Blind +#define SPELL_WHIRLWIND 37640 +#define SPELL_CHAOS_BLAST 37674 +#define SPELL_BERSERK 26662 +#define SPELL_INSIDIOUS_WHISPER 37676 +#define SPELL_DUAL_WIELD 42459 + +// --- Spells used in banish phase --- +#define BANISH_BEAM 38909 +#define AURA_BANISH 37833 + +// --- Spells used by Greyheart Spellbinders +#define SPELL_EARTHSHOCK 39076 +#define SPELL_MINDBLAST 37531 + +// --- Spells used by Inner Demons and Creature ID +#define INNER_DEMON_ID 21857 +#define AURA_DEMONIC_ALIGNMENT 37713 +#define SPELL_SHADOWBOLT 39309 +#define SPELL_SOUL_LINK 38007 +#define SPELL_CONSUMING_MADNESS 37749 //not supported by core yet + +//Misc. +#define MODEL_DEMON 20125 +#define MODEL_NIGHTELF 20514 +#define DEMON_FORM 21875 +#define MOB_SPELLBINDER 21806 + +#define SAY_AGGRO -1548009 +#define SAY_SWITCH_TO_DEMON -1548010 +#define SAY_INNER_DEMONS -1548011 +#define SAY_DEMON_SLAY1 -1548012 +#define SAY_DEMON_SLAY2 -1548013 +#define SAY_DEMON_SLAY3 -1548014 +#define SAY_NIGHTELF_SLAY1 -1548015 +#define SAY_NIGHTELF_SLAY2 -1548016 +#define SAY_NIGHTELF_SLAY3 -1548017 +#define SAY_FINAL_FORM -1548018 +#define SAY_FREE -1548019 +#define SAY_DEATH -1548020 + +struct mob_inner_demonAI : public ScriptedAI +{ + mob_inner_demonAI(Creature *c) : ScriptedAI(c) + { + victimGUID = 0; + } + + uint32 ShadowBolt_Timer; + + uint32 Link_Timer; + uint64 victimGUID; + + void Reset() + { + ShadowBolt_Timer = 10000; + Link_Timer = 1000; + } + void JustDied(Unit * /*victim*/) + { + Unit* pUnit = Unit::GetUnit((*me),victimGUID); + if (pUnit && pUnit->HasAura(SPELL_INSIDIOUS_WHISPER)) + pUnit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID()) + { + damage = 0; + DoModifyThreatPercent(done_by, -100); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (!victimGUID) return; + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (me->getVictim()->GetGUID() != victimGUID) + { + DoModifyThreatPercent(me->getVictim(), -100); + Unit* owner = Unit::GetUnit((*me),victimGUID); + if (owner && owner->isAlive()) + { + me->AddThreat(owner,999999); + AttackStart(owner); + } else if (owner && owner->isDead()) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + } + + if (Link_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOUL_LINK, true); + Link_Timer = 1000; + } else Link_Timer -= diff; + + if (!me->HasAura(AURA_DEMONIC_ALIGNMENT)) + DoCast(me, AURA_DEMONIC_ALIGNMENT, true); + + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLT, false); + ShadowBolt_Timer = 10000; + } else ShadowBolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +//Original Leotheras the Blind AI +struct boss_leotheras_the_blindAI : public ScriptedAI +{ + boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c) + { + c->GetPosition(x,y,z); + pInstance = c->GetInstanceData(); + Demon = 0; + + for (uint8 i = 0; i < 3; ++i)//clear guids + SpellBinderGUID[i] = 0; + } + + ScriptedInstance *pInstance; + + uint32 Whirlwind_Timer; + uint32 ChaosBlast_Timer; + uint32 SwitchToDemon_Timer; + uint32 SwitchToHuman_Timer; + uint32 Berserk_Timer; + uint32 InnerDemons_Timer; + uint32 BanishTimer; + + bool DealDamage; + bool NeedThreatReset; + bool DemonForm; + bool IsFinalForm; + bool EnrageUsed; + float x,y,z; + + uint64 InnderDemon[5]; + uint32 InnerDemon_Count; + uint64 Demon; + uint64 SpellBinderGUID[3]; + + void Reset() + { + CheckChannelers(); + BanishTimer = 1000; + Whirlwind_Timer = 15000; + ChaosBlast_Timer = 1000; + SwitchToDemon_Timer = 45000; + SwitchToHuman_Timer = 60000; + Berserk_Timer = 600000; + InnerDemons_Timer = 30000; + me->SetCanDualWield(true); + DealDamage = true; + DemonForm = false; + IsFinalForm = false; + NeedThreatReset = false; + EnrageUsed = false; + InnerDemon_Count = 0; + me->SetSpeed(MOVE_RUN, 2.0f, true); + me->SetDisplayId(MODEL_NIGHTELF); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + DoCast(me, SPELL_DUAL_WIELD, true); + me->SetCorpseDelay(1000*60*60); + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED); + } + + void CheckChannelers(/*bool DoEvade = true*/) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Creature *add = Unit::GetCreature(*me,SpellBinderGUID[i])) + add->DisappearAndDie(); + + float nx = x; + float ny = y; + float o = 2.4f; + if (i == 0) {nx += 10; ny -= 5; o=2.5f;} + if (i == 1) {nx -= 8; ny -= 7; o=0.9f;} + if (i == 2) {nx -= 3; ny += 9; o=5.0f;} + Creature* binder = me->SummonCreature(MOB_SPELLBINDER,nx,ny,z,o,TEMPSUMMON_DEAD_DESPAWN,0); + if (binder) + SpellBinderGUID[i] = binder->GetGUID(); + + } + } + void MoveInLineOfSight(Unit *who) + { + if (me->HasAura(AURA_BANISH)) + return; + + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius)) + { + // Check first that object is in an angle in front of this one before LoS check + if (me->HasInArc(M_PI/2.0f, who) && me->IsWithinLOSInMap(who)) + { + AttackStart(who); + } + } + } + } + + void StartEvent() + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, IN_PROGRESS); + } + + void CheckBanish() + { + uint8 AliveChannelers = 0; + for (uint8 i = 0; i < 3; ++i) + { + Unit *add = Unit::GetUnit(*me,SpellBinderGUID[i]); + if (add && add->isAlive()) + ++AliveChannelers; + } + + // channelers == 0 remove banish aura + if (AliveChannelers == 0 && me->HasAura(AURA_BANISH)) + { + // removing banish aura + me->RemoveAurasDueToSpell(AURA_BANISH); + + // Leotheras is getting immune again + me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); + + // changing model to bloodelf + me->SetDisplayId(MODEL_NIGHTELF); + + // and reseting equipment + me->LoadEquipment(me->GetEquipmentId()); + + if (pInstance && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + Unit *victim = NULL; + victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); + if (victim) + me->getThreatManager().addThreat(victim, 1); + StartEvent(); + } + } + else if (AliveChannelers != 0 && !me->HasAura(AURA_BANISH)) + { + // channelers != 0 apply banish aura + // removing Leotheras banish immune to apply AURA_BANISH + me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); + DoCast(me, AURA_BANISH); + + // changing model + me->SetDisplayId(MODEL_DEMON); + + // and removing weapons + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + } + } + + //Despawn all Inner Demon summoned + void DespawnDemon() + { + for (uint8 i=0; i<5; ++i) + { + if (InnderDemon[i]) + { + //delete creature + Creature* pCreature = Unit::GetCreature((*me), InnderDemon[i]); + if (pCreature && pCreature->isAlive()) + { + pCreature->ForcedDespawn(); + } + InnderDemon[i] = 0; + } + } + + InnerDemon_Count = 0; + } + + void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core + { + for (uint8 i=0; i<5; ++i) + { + if (InnderDemon[i] > 0) + { + Creature* pUnit = Unit::GetCreature((*me), InnderDemon[i]); + if (pUnit && pUnit->isAlive()) + { + Unit* pUnit_pTarget = Unit::GetUnit(*pUnit, CAST_AI(mob_inner_demonAI, pUnit->AI())->victimGUID); + if (pUnit_pTarget && pUnit_pTarget->isAlive()) + { + pUnit->CastSpell(pUnit_pTarget, SPELL_CONSUMING_MADNESS, true); + DoModifyThreatPercent(pUnit_pTarget, -100); + } + } + } + } + } + + void KilledUnit(Unit * victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + if (DemonForm) + { + DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); + } + else + { + DoScriptText(RAND(SAY_NIGHTELF_SLAY1,SAY_NIGHTELF_SLAY2,SAY_NIGHTELF_SLAY3), me); + } + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + //despawn copy + if (Demon) + { + if (Creature* pDemon = Unit::GetCreature(*me, Demon)) + pDemon->ForcedDespawn(); + } + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + if (me->HasAura(AURA_BANISH)) + return; + + me->LoadEquipment(me->GetEquipmentId()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (me->HasAura(AURA_BANISH) || !UpdateVictim()) + { + if (BanishTimer <= diff) + { + CheckBanish();//no need to check every update tick + BanishTimer = 1000; + } else BanishTimer -= diff; + return; + } + if (me->HasAura(SPELL_WHIRLWIND)) + if (Whirlwind_Timer <= diff) + { + Unit *newTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (newTarget) + { + DoResetThreat(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,newTarget->GetPositionX(),newTarget->GetPositionY(),newTarget->GetPositionZ()); + } + Whirlwind_Timer = 2000; + } else Whirlwind_Timer -= diff; + + // reseting after changing forms and after ending whirlwind + if (NeedThreatReset && !me->HasAura(SPELL_WHIRLWIND)) + { + // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding) + if (DemonForm) + InnerDemons_Timer = 30000; + else + Whirlwind_Timer = 15000; + + NeedThreatReset = false; + DoResetThreat(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + + //Enrage_Timer (10 min) + if (Berserk_Timer < diff && !EnrageUsed) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_BERSERK); + EnrageUsed = true; + } else Berserk_Timer -= diff; + + if (!DemonForm) + { + //Whirldind Timer + if (!me->HasAura(SPELL_WHIRLWIND)) + { + if (Whirlwind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + // while whirlwinding this variable is used to countdown target's change + Whirlwind_Timer = 2000; + NeedThreatReset = true; + } else Whirlwind_Timer -= diff; + } + //Switch_Timer + + if (!IsFinalForm) + if (SwitchToDemon_Timer <= diff) + { + //switch to demon form + me->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0); + me->SetDisplayId(MODEL_DEMON); + DoScriptText(SAY_SWITCH_TO_DEMON, me); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + DemonForm = true; + NeedThreatReset = true; + SwitchToDemon_Timer = 45000; + } else SwitchToDemon_Timer -= diff; + DoMeleeAttackIfReady(); + } + else + { + //ChaosBlast_Timer + if (!me->getVictim()) + return; + if (me->IsWithinDist(me->getVictim(), 30)) + me->StopMoving(); + if (ChaosBlast_Timer <= diff) + { + // will cast only when in range of spell + if (me->IsWithinDist(me->getVictim(), 30)) + { + //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); + int damage = 100; + me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); + } + ChaosBlast_Timer = 3000; + } else ChaosBlast_Timer -= diff; + //Summon Inner Demon + if (InnerDemons_Timer <= diff) + { + std::list& ThreatList = me->getThreatManager().getThreatList(); + std::vector TargetList; + for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) + { + Unit *tempTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->getVictim()->GetGUID() && TargetList.size()<5) + TargetList.push_back(tempTarget); + } + //SpellEntry *spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); + for (std::vector::const_iterator itr = TargetList.begin(); itr != TargetList.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive()) + { + Creature * demon = me->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (demon) + { + demon->AI()->AttackStart((*itr)); + CAST_AI(mob_inner_demonAI, demon->AI())->victimGUID = (*itr)->GetGUID(); + + (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); + + if (InnerDemon_Count > 4) + InnerDemon_Count = 0; + + //Safe storing of creatures + InnderDemon[InnerDemon_Count] = demon->GetGUID(); + + //Update demon count + ++InnerDemon_Count; + } + } + } + DoScriptText(SAY_INNER_DEMONS, me); + + InnerDemons_Timer = 999999; + } else InnerDemons_Timer -= diff; + + //Switch_Timer + if (SwitchToHuman_Timer <= diff) + { + //switch to nightelf form + me->SetDisplayId(MODEL_NIGHTELF); + me->LoadEquipment(me->GetEquipmentId()); + + CastConsumingMadness(); + DespawnDemon(); + + DemonForm = false; + NeedThreatReset = true; + + SwitchToHuman_Timer = 60000; + } else SwitchToHuman_Timer -= diff; + } + + if (!IsFinalForm && (me->GetHealth()*100 / me->GetMaxHealth()) < 15) + { + //at this point he divides himself in two parts + CastConsumingMadness(); + DespawnDemon(); + Creature *Copy = NULL; + Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000); + if (Copy) + { + Demon = Copy->GetGUID(); + if (me->getVictim()) + Copy->AI()->AttackStart(me->getVictim()); + } + //set nightelf final form + IsFinalForm = true; + DemonForm = false; + + DoScriptText(SAY_FINAL_FORM, me); + me->SetDisplayId(MODEL_NIGHTELF); + me->LoadEquipment(me->GetEquipmentId()); + } + } +}; + +//Leotheras the Blind Demon Form AI +struct boss_leotheras_the_blind_demonformAI : public ScriptedAI +{ + boss_leotheras_the_blind_demonformAI(Creature *c) : ScriptedAI(c) {} + + uint32 ChaosBlast_Timer; + bool DealDamage; + + void Reset() + { + ChaosBlast_Timer = 1000; + DealDamage = true; + } + + void StartEvent() + { + DoScriptText(SAY_FREE, me); + } + + void KilledUnit(Unit * victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) + DoCast(me, 8149, true); + } + + void EnterCombat(Unit * /*who*/) + { + StartEvent(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + //ChaosBlast_Timer + if (me->IsWithinDist(me->getVictim(), 30)) + me->StopMoving(); + + if (ChaosBlast_Timer <= diff) + { + // will cast only when in range od spell + if (me->IsWithinDist(me->getVictim(), 30)) + { + //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); + int damage = 100; + me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); + ChaosBlast_Timer = 3000; + } + } else ChaosBlast_Timer -= diff; + + //Do NOT deal any melee damage to the target. + } +}; +struct mob_greyheart_spellbinderAI : public ScriptedAI +{ + mob_greyheart_spellbinderAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + leotherasGUID = 0; + AddedBanish = false; + } + + ScriptedInstance *pInstance; + + uint64 leotherasGUID; + + uint32 Mindblast_Timer; + uint32 Earthshock_Timer; + + bool AddedBanish; + + void Reset() + { + Mindblast_Timer = 3000 + rand()%5000; + Earthshock_Timer = 5000 + rand()%5000; + + if (pInstance) + { + pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, 0); + Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); + if (leotheras && leotheras->isAlive()) + CAST_AI(boss_leotheras_the_blindAI, leotheras->AI())->CheckChannelers(/*false*/); + } + } + + void EnterCombat(Unit * who) + { + me->InterruptNonMeleeSpells(false); + if (pInstance) + pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID()); + } + + void JustRespawned() + { + AddedBanish = false; + Reset(); + } + + void CastChanneling() + { + if (!me->isInCombat() && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + { + if (leotherasGUID) + { + Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); + if (leotheras && leotheras->isAlive()) + DoCast(leotheras, BANISH_BEAM); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance) + { + if (!leotherasGUID) + leotherasGUID = pInstance->GetData64(DATA_LEOTHERAS); + + if (!me->isInCombat() && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + Unit *victim = NULL; + victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); + if (victim) + AttackStart(victim); + } + } + + if (!UpdateVictim()) + { + CastChanneling(); + return; + } + + if (pInstance && !pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + EnterEvadeMode(); + return; + } + + if (Mindblast_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (pTarget)DoCast(pTarget, SPELL_MINDBLAST); + + Mindblast_Timer = 10000 + rand()%5000; + } else Mindblast_Timer -= diff; + + if (Earthshock_Timer <= diff) + { + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) + { + if (Player* i_pl = itr->getSource()) + { + bool isCasting = false; + for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) + if (i_pl->GetCurrentSpell(i)) + isCasting = true; + + if (isCasting) + { + DoCast(i_pl, SPELL_EARTHSHOCK); + break; + } + } + } + Earthshock_Timer = 8000 + rand()%7000; + } else Earthshock_Timer -= diff; + DoMeleeAttackIfReady(); + } + + void JustDied(Unit * /*killer*/) {} +}; +CreatureAI* GetAI_boss_leotheras_the_blind(Creature* pCreature) +{ + return new boss_leotheras_the_blindAI (pCreature); +} + +CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature* pCreature) +{ + return new boss_leotheras_the_blind_demonformAI (pCreature); +} + +CreatureAI* GetAI_mob_greyheart_spellbinder(Creature* pCreature) +{ + return new mob_greyheart_spellbinderAI (pCreature); +} + +CreatureAI* GetAI_mob_inner_demon(Creature* pCreature) +{ + return new mob_inner_demonAI (pCreature); +} +void AddSC_boss_leotheras_the_blind() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_leotheras_the_blind"; + newscript->GetAI = &GetAI_boss_leotheras_the_blind; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_leotheras_the_blind_demonform"; + newscript->GetAI = &GetAI_boss_leotheras_the_blind_demonform; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_greyheart_spellbinder"; + newscript->GetAI = &GetAI_mob_greyheart_spellbinder; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_inner_demon"; + newscript->GetAI = &GetAI_mob_inner_demon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp new file mode 100644 index 00000000000..b1c0c10bcce --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp @@ -0,0 +1,458 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_the_lurker_below +SD%Complete: 80 +SDComment: Coilfang Frenzy, find out how could we fishing in the strangepool +SDCategory: The Lurker Below +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedSimpleAI.h" +#include "Spell.h" + +#define SPELL_SPOUT 37433 +#define SPELL_SPOUT_ANIM 42835 +#define SPELL_SPOUT_BREATH 37431 +#define SPELL_KNOCKBACK 19813 +#define SPELL_GEYSER 37478 +#define SPELL_WHIRL 37660 +#define SPELL_WATERBOLT 37138 +#define SPELL_SUBMERGE 37550 +#define SPELL_EMERGE 20568 + +#define EMOTE_SPOUT "The Lurker Below takes a deep breath." + +#define SPOUT_DIST 100 + +#define MOB_COILFANG_GUARDIAN 21873 +#define MOB_COILFANG_AMBUSHER 21865 + +//Ambusher spells +#define SPELL_SPREAD_SHOT 37790 +#define SPELL_SHOOT 37770 + +//Guardian spells +#define SPELL_ARCINGSMASH 38761 // Wrong SpellId. Can't find the right one. +#define SPELL_HAMSTRING 26211 + +float AddPos[9][3] = +{ + {2.8553810, -459.823914, -19.182686}, //MOVE_AMBUSHER_1 X, Y, Z + {12.400000, -466.042267, -19.182686}, //MOVE_AMBUSHER_2 X, Y, Z + {51.366653, -460.836060, -19.182686}, //MOVE_AMBUSHER_3 X, Y, Z + {62.597980, -457.433044, -19.182686}, //MOVE_AMBUSHER_4 X, Y, Z + {77.607452, -384.302765, -19.182686}, //MOVE_AMBUSHER_5 X, Y, Z + {63.897900, -378.984924, -19.182686}, //MOVE_AMBUSHER_6 X, Y, Z + {34.447250, -387.333618, -19.182686}, //MOVE_GUARDIAN_1 X, Y, Z + {14.388216, -423.468018, -19.625271}, //MOVE_GUARDIAN_2 X, Y, Z + {42.471519, -445.115295, -19.769423} //MOVE_GUARDIAN_3 X, Y, Z +}; + +struct boss_the_lurker_belowAI : public Scripted_NoMovementAI +{ + boss_the_lurker_belowAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + SpellEntry *TempSpell = GET_SPELL(SPELL_SPOUT_ANIM); + if (TempSpell) + { + TempSpell->Effect[0] = 0;//remove all spell effect, only anim is needed + TempSpell->Effect[1] = 0; + TempSpell->Effect[2] = 0; + } + } + + ScriptedInstance* pInstance; + SummonList Summons; + + bool Spawned; + bool Submerged; + bool InRange; + bool CanStartEvent; + uint32 RotTimer; + uint32 SpoutAnimTimer; + uint32 WaterboltTimer; + uint32 SpoutTimer; + uint32 WhirlTimer; + uint32 PhaseTimer; + uint32 GeyserTimer; + uint32 CheckTimer; + uint32 WaitTimer; + uint32 WaitTimer2; + + bool CheckCanStart()//check if players fished + { + if (pInstance && pInstance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) + return false; + return true; + } + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); + SpoutAnimTimer = 1000; + RotTimer = 0; + WaterboltTimer = 15000;//give time to get in range when fight starts + SpoutTimer = 45000; + WhirlTimer = 18000;//after avery spout + PhaseTimer = 120000; + GeyserTimer = rand()%5000 + 15000; + CheckTimer = 15000;//give time to get in range when fight starts + WaitTimer = 60000;//never reached + WaitTimer2 = 60000;//never reached + + Submerged = true;//will be false at combat start + Spawned = false; + InRange = false; + CanStartEvent = false; + + Summons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_THELURKERBELOWEVENT, NOT_STARTED); + pInstance->SetData(DATA_STRANGE_POOL, NOT_STARTED); + } + DoCast(me, SPELL_SUBMERGE);//submerge anim + me->SetVisibility(VISIBILITY_OFF);//we start invis under water, submerged + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_THELURKERBELOWEVENT, DONE); + + Summons.DespawnAll(); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + pInstance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS); + Scripted_NoMovementAI::EnterCombat(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (!CanStartEvent)//boss is invisible, don't attack + return; + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius)) + { + AttackStart(who); + } + } + } + + void MovementInform(uint32 type, uint32 /*id*/) + { + if (type == ROTATE_MOTION_TYPE) + me->SetReactState(REACT_AGGRESSIVE); + } + + void UpdateAI(const uint32 diff) + { + if (!CanStartEvent)//boss is invisible, don't attack + { + if (CheckCanStart()) + { + if (Submerged) + { + me->SetVisibility(VISIBILITY_ON); + Submerged = false; + WaitTimer2 = 500; + } + if (!Submerged && WaitTimer2 <= diff)//wait 500ms before emerge anim + { + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); + DoCast(me, SPELL_EMERGE, false); + WaitTimer2 = 60000;//never reached + WaitTimer = 3000; + } else WaitTimer2 -= diff; + + if (WaitTimer <= diff)//wait 3secs for emerge anim, then attack + { + WaitTimer = 3000; + CanStartEvent=true;//fresh fished from pool + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } else WaitTimer -= diff; + } + return; + } + + if (me->getThreatManager().getThreatList().empty())//check if should evade + { + if (me->isInCombat()) + EnterEvadeMode(); + return; + } + if (!Submerged) + { + if (PhaseTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUBMERGE); + PhaseTimer = 60000;//60secs submerged + Submerged = true; + } else PhaseTimer-=diff; + + if (SpoutTimer <= diff) + { + me->MonsterTextEmote(EMOTE_SPOUT,0,true); + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MoveRotate(20000, rand()%2 ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); + SpoutTimer = 45000; + WhirlTimer = 20000;//whirl directly after spout + RotTimer = 20000; + return; + } else SpoutTimer -= diff; + + //Whirl directly after a Spout and at random times + if (WhirlTimer <= diff) + { + WhirlTimer = 18000; + DoCast(me, SPELL_WHIRL); + } else WhirlTimer -= diff; + + if (CheckTimer <= diff)//check if there are players in melee range + { + InRange = false; + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (me->IsWithinMeleeRange(i->getSource())) + InRange = true; + } + } + CheckTimer = 2000; + } else CheckTimer -= diff; + + if (RotTimer) + { + Map* pMap = me->GetMap(); + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->isAlive() && me->HasInArc((double)diff/20000*(double)M_PI*2,i->getSource()) && me->IsWithinDist(i->getSource(), SPOUT_DIST) && !i->getSource()->IsInWater()) + DoCast(i->getSource(), SPELL_SPOUT, true);//only knock back palyers in arc, in 100yards, not in water + } + } + + if (SpoutAnimTimer <= diff) + { + DoCast(me, SPELL_SPOUT_ANIM, true); + SpoutAnimTimer = 1000; + } else SpoutAnimTimer -= diff; + + if (RotTimer <= diff) + { + RotTimer = 0; + } else RotTimer -= diff; + return; + } + + if (GeyserTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (!pTarget && me->getVictim()) + pTarget = me->getVictim(); + if (pTarget) + DoCast(pTarget, SPELL_GEYSER, true); + GeyserTimer = rand()%5000 + 15000; + } else GeyserTimer -= diff; + + if (!InRange)//if on players in melee range cast Waterbolt + { + if (WaterboltTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget && me->getVictim()) + pTarget = me->getVictim(); + if (pTarget) + DoCast(pTarget, SPELL_WATERBOLT, true); + WaterboltTimer = 3000; + } else WaterboltTimer -= diff; + } + + if (!UpdateCombatState()) + return; + + DoMeleeAttackIfReady(); + + }else//submerged + { + if (PhaseTimer <= diff) + { + Submerged = false; + me->InterruptNonMeleeSpells(false);//shouldn't be any + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); + DoCast(me, SPELL_EMERGE, true); + Spawned = false; + SpoutTimer = 3000; // directly cast Spout after emerging! + PhaseTimer = 120000; + return; + } else PhaseTimer-=diff; + + if (me->getThreatManager().getThreatList().empty())//check if should evade + { + EnterEvadeMode(); + return; + } + if (!me->isInCombat()) + DoZoneInCombat(); + + if (!Spawned) + { + me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + //spawn adds + for (uint8 i = 0; i < 9; ++i) + { + Creature* Summoned; + if (i < 6) + Summoned = me->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + else Summoned = me->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (Summoned) + Summons.Summon(Summoned); + } + Spawned = true; + } + } + } + }; + +CreatureAI* GetAI_mob_coilfang_guardian(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_ARCINGSMASH; + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].First_Cast = 5000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->Spell[1].Enabled = true; + ai->Spell[1].Spell_Id = SPELL_HAMSTRING; + ai->Spell[1].Cooldown = 10000; + ai->Spell[1].First_Cast = 2000; + ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; + + return ai; +} + +struct mob_coilfang_ambusherAI : public Scripted_NoMovementAI +{ + mob_coilfang_ambusherAI(Creature *c) : Scripted_NoMovementAI(c) + { + SpellEntry *TempSpell = GET_SPELL(SPELL_SHOOT); + if (TempSpell) + TempSpell->Effect[0] = 2;//change spell effect from weapon % dmg to simple phisical dmg + } + + uint32 MultiShotTimer; + uint32 ShootBowTimer; + + void Reset() + { + MultiShotTimer = 10000; + ShootBowTimer = 4000; + + } + + void EnterCombat(Unit * /*who*/) + { + + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who) && me->IsWithinDistInMap(who, 45)) + { + AttackStart(who); + } + } + + void UpdateAI(const uint32 diff) + { + if (MultiShotTimer <= diff) + { + if (me->getVictim()) + DoCast(me->getVictim(), SPELL_SPREAD_SHOT, true); + + MultiShotTimer = 10000+rand()%10000; + ShootBowTimer += 1500;//add global cooldown + } else MultiShotTimer -= diff; + + if (ShootBowTimer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + int bp0 = 1100; + if (pTarget) + me->CastCustomSpell(pTarget,SPELL_SHOOT,&bp0,NULL,NULL,true); + ShootBowTimer = 4000+rand()%5000; + MultiShotTimer += 1500;//add global cooldown + } else ShootBowTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_coilfang_ambusher(Creature* pCreature) +{ + return new mob_coilfang_ambusherAI (pCreature); +} + +CreatureAI* GetAI_boss_the_lurker_below(Creature* pCreature) +{ + return new boss_the_lurker_belowAI (pCreature); +} + +void AddSC_boss_the_lurker_below() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_lurker_below"; + newscript->GetAI = &GetAI_boss_the_lurker_below; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_guardian"; + newscript->GetAI = &GetAI_mob_coilfang_guardian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_ambusher"; + newscript->GetAI = &GetAI_mob_coilfang_ambusher; + newscript->RegisterSelf(); +} + + diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp new file mode 100644 index 00000000000..14c87aee141 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp @@ -0,0 +1,369 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Morogrim_Tidewalker +SD%Complete: 90 +SDComment: Water globules don't explode properly, remove hacks +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define SAY_AGGRO -1548030 +#define SAY_SUMMON1 -1548031 +#define SAY_SUMMON2 -1548032 +#define SAY_SUMMON_BUBL1 -1548033 +#define SAY_SUMMON_BUBL2 -1548034 +#define SAY_SLAY1 -1548035 +#define SAY_SLAY2 -1548036 +#define SAY_SLAY3 -1548037 +#define SAY_DEATH -1548038 +#define EMOTE_WATERY_GRAVE -1548039 +#define EMOTE_EARTHQUAKE -1548040 +#define EMOTE_WATERY_GLOBULES -1548041 + +#define SPELL_TIDAL_WAVE 37730 +#define SPELL_WATERY_GRAVE 38049 +#define SPELL_EARTHQUAKE 37764 +#define SPELL_WATERY_GRAVE_EXPLOSION 37852 + +#define WATERY_GRAVE_X1 334.64 +#define WATERY_GRAVE_Y1 -728.89 +#define WATERY_GRAVE_Z1 -14.42 +#define WATERY_GRAVE_X2 365.51 +#define WATERY_GRAVE_Y2 -737.14 +#define WATERY_GRAVE_Z2 -14.44 +#define WATERY_GRAVE_X3 366.19 +#define WATERY_GRAVE_Y3 -709.59 +#define WATERY_GRAVE_Z3 -14.36 +#define WATERY_GRAVE_X4 372.93 +#define WATERY_GRAVE_Y4 -690.96 +#define WATERY_GRAVE_Z4 -14.44 + +#define SPELL_WATERY_GRAVE_1 38023 +#define SPELL_WATERY_GRAVE_2 38024 +#define SPELL_WATERY_GRAVE_3 38025 +#define SPELL_WATERY_GRAVE_4 37850 + +#define SPELL_SUMMON_WATER_GLOBULE_1 37854 +#define SPELL_SUMMON_WATER_GLOBULE_2 37858 +#define SPELL_SUMMON_WATER_GLOBULE_3 37860 +#define SPELL_SUMMON_WATER_GLOBULE_4 37861 + +/*#define SPELL_SUMMON_MURLOC_A6 39813 +#define SPELL_SUMMON_MURLOC_A7 39814 +#define SPELL_SUMMON_MURLOC_A8 39815 +#define SPELL_SUMMON_MURLOC_A9 39816 +#define SPELL_SUMMON_MURLOC_A10 39817 + +#define SPELL_SUMMON_MURLOC_B6 39818 +#define SPELL_SUMMON_MURLOC_B7 39819 +#define SPELL_SUMMON_MURLOC_B8 39820 +#define SPELL_SUMMON_MURLOC_B9 39821 +#define SPELL_SUMMON_MURLOC_B10 39822*/ + +float MurlocCords[10][5] = +{ + {21920, 424.36, -715.4, -7.14, 0.124}, + {21920, 425.13, -719.3, -7.14, 0.124}, + {21920, 425.05, -724.23, -7.14, 0.124}, + {21920, 424.91, -728.68, -7.14, 0.124}, + {21920, 424.84, -732.18, -7.14, 0.124}, + {21920, 321.05, -734.2, -13.15, 0.124}, + {21920, 321.05, -729.4, -13.15, 0.124}, + {21920, 321.05, -724.03, -13.15, 0.124}, + {21920, 321.05, -718.73, -13.15, 0.124}, + {21920, 321.05, -714.24, -13.15, 0.124} +}; + +//Creatures +#define WATER_GLOBULE 21913 +#define TIDEWALKER_LURKER 21920 + +//Morogrim Tidewalker AI +struct boss_morogrim_tidewalkerAI : public ScriptedAI +{ + boss_morogrim_tidewalkerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + Map::PlayerList const *PlayerList; + + uint32 TidalWave_Timer; + uint32 WateryGrave_Timer; + uint32 Earthquake_Timer; + uint32 WateryGlobules_Timer; + uint32 globulespell[4]; + int8 Playercount; + int8 counter; + + bool Earthquake; + bool Phase2; + + void Reset() + { + TidalWave_Timer = 10000; + WateryGrave_Timer = 30000; + Earthquake_Timer = 40000; + WateryGlobules_Timer = 0; + globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1; + globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2; + globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3; + globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4; + + Earthquake = false; + Phase2 = false; + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); + } + + void StartEvent() + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + PlayerList = &me->GetMap()->GetPlayers(); + Playercount = PlayerList->getSize(); + StartEvent(); + } + + void ApplyWateryGrave(Unit* pPlayer, uint8 i) + { + switch(i) + { + case 0: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_1, true); break; + case 1: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_2, true); break; + case 2: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_3, true); break; + case 3: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_4, true); break; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Earthquake_Timer + if (Earthquake_Timer <= diff) + { + if (!Earthquake) + { + DoCast(me->getVictim(), SPELL_EARTHQUAKE); + Earthquake = true; + Earthquake_Timer = 10000; + } + else + { + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + + for (uint8 i = 0; i < 10; ++i) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + Creature* Murloc = me->SummonCreature(MurlocCords[i][0],MurlocCords[i][1],MurlocCords[i][2],MurlocCords[i][3],MurlocCords[i][4], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); + if (pTarget && Murloc) + Murloc->AI()->AttackStart(pTarget); + } + DoScriptText(EMOTE_EARTHQUAKE, me); + Earthquake = false; + Earthquake_Timer = 40000+rand()%5000; + } + } else Earthquake_Timer -= diff; + + //TidalWave_Timer + if (TidalWave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIDAL_WAVE); + TidalWave_Timer = 20000; + } else TidalWave_Timer -= diff; + + if (!Phase2) + { + //WateryGrave_Timer + if (WateryGrave_Timer <= diff) + { + //Teleport 4 players under the waterfalls + Unit *pTarget; + using std::set; + setlist; + set::const_iterator itr; + for (uint8 i = 0; i < 4; ++i) + { + counter = 0; + do + { + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only + if (counter < Playercount) + break; + if (pTarget) + itr = list.find(pTarget->GetGUID()); + ++counter; + } while (itr != list.end()); + + if (pTarget) + { + list.insert(pTarget->GetGUID()); + ApplyWateryGrave(pTarget, i); + } + } + + DoScriptText(RAND(SAY_SUMMON_BUBL1,SAY_SUMMON_BUBL2), me); + + DoScriptText(EMOTE_WATERY_GRAVE, me); + WateryGrave_Timer = 30000; + } else WateryGrave_Timer -= diff; + + //Start Phase2 + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) + Phase2 = true; + } + else + { + //WateryGlobules_Timer + if (WateryGlobules_Timer <= diff) + { + Unit* pGlobuleTarget; + using std::set; + setglobulelist; + set::const_iterator itr; + for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD + { + counter = 0; + do { + pGlobuleTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); + if (pGlobuleTarget) + itr = globulelist.find(pGlobuleTarget->GetGUID()); + if (counter > Playercount) + break; + ++counter; + } while (itr != globulelist.end()); + if (pGlobuleTarget) + globulelist.insert(pGlobuleTarget->GetGUID()); + pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true); + } + DoScriptText(EMOTE_WATERY_GLOBULES, me); + WateryGlobules_Timer = 25000; + } else WateryGlobules_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +//Water Globule AI +#define SPELL_GLOBULE_EXPLOSION 37871 + +struct mob_water_globuleAI : public ScriptedAI +{ + mob_water_globuleAI(Creature *c) : ScriptedAI(c) {} + + uint32 Check_Timer; + + void Reset() + { + Check_Timer = 1000; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + //no attack radius check - it attacks the first target that moves in his los + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Check_Timer <= diff) + { + if (me->IsWithinDistInMap(me->getVictim(), 5)) + { + DoCast(me->getVictim(), SPELL_GLOBULE_EXPLOSION); + + //despawn + me->ForcedDespawn(); + return; + } + Check_Timer = 500; + } else Check_Timer -= diff; + + //do NOT deal any melee damage to the target. + } +}; + +CreatureAI* GetAI_boss_morogrim_tidewalker(Creature* pCreature) +{ + return new boss_morogrim_tidewalkerAI (pCreature); +} +CreatureAI* GetAI_mob_water_globule(Creature* pCreature) +{ + return new mob_water_globuleAI (pCreature); +} + +void AddSC_boss_morogrim_tidewalker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_morogrim_tidewalker"; + newscript->GetAI = &GetAI_boss_morogrim_tidewalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_water_globule"; + newscript->GetAI = &GetAI_mob_water_globule; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp new file mode 100644 index 00000000000..c80afae15c7 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp @@ -0,0 +1,398 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Serpent_Shrine +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Serpent Shrine Scripts +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define MAX_ENCOUNTER 6 +#define SPELL_SCALDINGWATER 37284 +#define MOB_COILFANG_FRENZY 21508 +#define TRASHMOB_COILFANG_PRIESTESS 21220 //6*2 +#define TRASHMOB_COILFANG_SHATTERER 21301 //6*3 + +#define MIN_KILLS 30 + +//NOTE: there are 6 platforms +//there should be 3 shatterers and 2 priestess on all platforms, total of 30 elites, else it won't work! +//delete all other elites not on platforms! these mobs should only be on those platforms nowhere else. + +/* Serpentshrine cavern encounters: +0 - Hydross The Unstable event +1 - Leotheras The Blind Event +2 - The Lurker Below Event +3 - Fathom-Lord Karathress Event +4 - Morogrim Tidewalker Event +5 - Lady Vashj Event +*/ + +bool GOHello_go_bridge_console(Player* /*pPlayer*/, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + + if (!pInstance) + return false; + + if (pInstance) + pInstance->SetData(DATA_CONTROL_CONSOLE, DONE); + + return true; +} + +struct instance_serpentshrine_cavern : public ScriptedInstance +{ + instance_serpentshrine_cavern(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 LurkerBelow; + uint64 Sharkkis; + uint64 Tidalvess; + uint64 Caribdis; + uint64 LadyVashj; + uint64 Karathress; + uint64 KarathressEvent_Starter; + uint64 LeotherasTheBlind; + uint64 LeotherasEventStarter; + + uint64 ControlConsole; + uint64 BridgePart[3]; + uint32 StrangePool; + uint32 FishingTimer; + uint32 LurkerSubEvent; + uint32 WaterCheckTimer; + uint32 FrenzySpawnTimer; + uint32 Water; + uint32 TrashCount; + + bool ShieldGeneratorDeactivated[4]; + uint32 m_auiEncounter[MAX_ENCOUNTER]; + bool DoSpawnFrenzy; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + LurkerBelow = 0; + Sharkkis = 0; + Tidalvess = 0; + Caribdis = 0; + LadyVashj = 0; + Karathress = 0; + KarathressEvent_Starter = 0; + LeotherasTheBlind = 0; + LeotherasEventStarter = 0; + + ControlConsole = 0; + BridgePart[0] = 0; + BridgePart[1] = 0; + BridgePart[2] = 0; + StrangePool = 0; + Water = WATERSTATE_FRENZY; + + ShieldGeneratorDeactivated[0] = false; + ShieldGeneratorDeactivated[1] = false; + ShieldGeneratorDeactivated[2] = false; + ShieldGeneratorDeactivated[3] = false; + FishingTimer = 1000; + LurkerSubEvent = 0; + WaterCheckTimer = 500; + FrenzySpawnTimer = 2000; + DoSpawnFrenzy = false; + TrashCount = 0; + + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void Update (uint32 diff) + { + //Lurker Fishing event + if (LurkerSubEvent == LURKER_FISHING) + { + if (FishingTimer <= diff) + { + LurkerSubEvent = LURKER_HOOKED; + SetData(DATA_STRANGE_POOL, IN_PROGRESS);//just fished, signal Lurker script to emerge and start fight, we use IN_PROGRESS so it won't get saved and lurker will be alway invis at start if server restarted + } else FishingTimer -= diff; + } + //Water checks + if (WaterCheckTimer <= diff) + { + if (TrashCount >= MIN_KILLS) + Water = WATERSTATE_SCALDING; + else + Water = WATERSTATE_FRENZY; + + Map::PlayerList const &PlayerList = instance->GetPlayers(); + if (PlayerList.isEmpty()) + return; + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isAlive() && /*i->getSource()->GetPositionZ() <= -21.434931f*/pPlayer->IsInWater()) + { + if (Water == WATERSTATE_SCALDING) + { + + if (!pPlayer->HasAura(SPELL_SCALDINGWATER)) + { + pPlayer->CastSpell(pPlayer, SPELL_SCALDINGWATER,true); + } + } else if (Water == WATERSTATE_FRENZY) + { + //spawn frenzy + if (DoSpawnFrenzy) + { + if (Creature* frenzy = pPlayer->SummonCreature(MOB_COILFANG_FRENZY,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ(),pPlayer->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,2000)) + { + frenzy->Attack(pPlayer,false); + frenzy->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); + } + DoSpawnFrenzy = false; + } + } + } + if (!pPlayer->IsInWater()) + pPlayer->RemoveAurasDueToSpell(SPELL_SCALDINGWATER); + } + + } + WaterCheckTimer = 500;//remove stress from core + } else WaterCheckTimer -= diff; + if (FrenzySpawnTimer <= diff) + { + DoSpawnFrenzy = true; + FrenzySpawnTimer = 2000; + } else FrenzySpawnTimer -= diff; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 184568: + ControlConsole = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184203: + BridgePart[0] = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184204: + BridgePart[1] = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184205: + BridgePart[2] = pGo->GetGUID(); + pGo->setActive(true); + break; + case GAMEOBJECT_FISHINGNODE_ENTRY://no way checking if fish is hooked, so we create a timed event + if (LurkerSubEvent == LURKER_NOT_STARTED) + { + FishingTimer = 10000+rand()%30000;//random time before lurker emerges + LurkerSubEvent = LURKER_FISHING; + } + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 21212: LadyVashj = pCreature->GetGUID(); break; + case 21214: Karathress = pCreature->GetGUID(); break; + case 21966: Sharkkis = pCreature->GetGUID(); break; + case 21217: LurkerBelow = pCreature->GetGUID(); break; + case 21965: Tidalvess = pCreature->GetGUID(); break; + case 21964: Caribdis = pCreature->GetGUID(); break; + case 21215: LeotherasTheBlind = pCreature->GetGUID(); break; + /*case TRASHMOB_COILFANG_PRIESTESS: + case TRASHMOB_COILFANG_SHATTERER: + if (pCreature->isAlive()) + ++TrashCount; + break;*/ + } + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_KARATHRESSEVENT_STARTER) + KarathressEvent_Starter = data; + if (type == DATA_LEOTHERAS_EVENT_STARTER) + LeotherasEventStarter = data; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_THELURKERBELOW: return LurkerBelow; + case DATA_SHARKKIS: return Sharkkis; + case DATA_TIDALVESS: return Tidalvess; + case DATA_CARIBDIS: return Caribdis; + case DATA_LADYVASHJ: return LadyVashj; + case DATA_KARATHRESS: return Karathress; + case DATA_KARATHRESSEVENT_STARTER: return KarathressEvent_Starter; + case DATA_LEOTHERAS: return LeotherasTheBlind; + case DATA_LEOTHERAS_EVENT_STARTER: return LeotherasEventStarter; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_STRANGE_POOL: + { + StrangePool = data; + if (data == NOT_STARTED) + LurkerSubEvent = LURKER_NOT_STARTED; + } + break; + case DATA_CONTROL_CONSOLE: + if (data == DONE) + { + HandleGameObject(BridgePart[0], true); + HandleGameObject(BridgePart[0], true); + HandleGameObject(BridgePart[0], true); + } + ControlConsole = data;break; + case DATA_TRASH : + { + if (data == 1 && TrashCount < MIN_KILLS) + ++TrashCount;//+1 died + SaveToDB(); + break; + } + case DATA_WATER : Water = data;break; + case DATA_HYDROSSTHEUNSTABLEEVENT: m_auiEncounter[0] = data; break; + case DATA_LEOTHERASTHEBLINDEVENT: m_auiEncounter[1] = data; break; + case DATA_THELURKERBELOWEVENT: m_auiEncounter[2] = data; break; + case DATA_KARATHRESSEVENT: m_auiEncounter[3] = data; break; + case DATA_MOROGRIMTIDEWALKEREVENT: m_auiEncounter[4] = data; break; + //Lady Vashj + case DATA_LADYVASHJEVENT: + if (data == NOT_STARTED) + { + ShieldGeneratorDeactivated[0] = false; + ShieldGeneratorDeactivated[1] = false; + ShieldGeneratorDeactivated[2] = false; + ShieldGeneratorDeactivated[3] = false; + } + m_auiEncounter[5] = data; break; + case DATA_SHIELDGENERATOR1:ShieldGeneratorDeactivated[0] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR2:ShieldGeneratorDeactivated[1] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR3:ShieldGeneratorDeactivated[2] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR4:ShieldGeneratorDeactivated[3] = (data) ? true : false; break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_HYDROSSTHEUNSTABLEEVENT: return m_auiEncounter[0]; + case DATA_LEOTHERASTHEBLINDEVENT: return m_auiEncounter[1]; + case DATA_THELURKERBELOWEVENT: return m_auiEncounter[2]; + case DATA_KARATHRESSEVENT: return m_auiEncounter[3]; + case DATA_MOROGRIMTIDEWALKEREVENT: return m_auiEncounter[4]; + //Lady Vashj + case DATA_LADYVASHJEVENT: return m_auiEncounter[5]; + case DATA_SHIELDGENERATOR1: return ShieldGeneratorDeactivated[0]; + case DATA_SHIELDGENERATOR2: return ShieldGeneratorDeactivated[1]; + case DATA_SHIELDGENERATOR3: return ShieldGeneratorDeactivated[2]; + case DATA_SHIELDGENERATOR4: return ShieldGeneratorDeactivated[3]; + case DATA_CANSTARTPHASE3: + if (ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3])return 1;break; + case DATA_STRANGE_POOL: return StrangePool; + case DATA_WATER: return Water; + } + return 0; + } + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << TrashCount; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> TrashCount; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_serpentshrine_cavern(Map* pMap) +{ + return new instance_serpentshrine_cavern(pMap); +} + +void AddSC_instance_serpentshrine_cavern() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_serpent_shrine"; + newscript->GetInstanceData = &GetInstanceData_instance_serpentshrine_cavern; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_bridge_console"; + newscript->pGOHello = &GOHello_go_bridge_console; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h new file mode 100644 index 00000000000..adfa39dc7e0 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SERPENT_SHRINE_H +#define DEF_SERPENT_SHRINE_H +enum LurkerEventState +{ + LURKER_NOT_STARTED = 0, + LURKER_FISHING = 1, + LURKER_HOOKED = 2 +}; +enum WaterEventState +{ + WATERSTATE_NONE = 0, + WATERSTATE_FRENZY = 1, + WATERSTATE_SCALDING = 2 +}; +#define DATA_CANSTARTPHASE3 1 +#define DATA_CARIBDIS 2 +#define DATA_HYDROSSTHEUNSTABLEEVENT 3 +#define DATA_KARATHRESS 4 +#define DATA_KARATHRESSEVENT 5 +#define DATA_KARATHRESSEVENT_STARTER 6 +#define DATA_LADYVASHJ 7 +#define DATA_LADYVASHJEVENT 8 +#define DATA_LEOTHERASTHEBLINDEVENT 9 +#define DATA_MOROGRIMTIDEWALKEREVENT 10 +#define DATA_SHARKKIS 11 +#define DATA_SHIELDGENERATOR1 12 +#define DATA_SHIELDGENERATOR2 13 +#define DATA_SHIELDGENERATOR3 14 +#define DATA_SHIELDGENERATOR4 15 +#define DATA_THELURKERBELOW 16 +#define DATA_THELURKERBELOWEVENT 17 +#define DATA_TIDALVESS 18 +#define DATA_FATHOMLORDKARATHRESSEVENT 19 +#define DATA_LEOTHERAS 20 +#define DATA_LEOTHERAS_EVENT_STARTER 21 +#define DATA_CONTROL_CONSOLE 22 +#define DATA_STRANGE_POOL 23 +#define DATA_WATER 24 +#define DATA_TRASH 25 +#endif + diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp new file mode 100644 index 00000000000..8e1b438bdc5 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp @@ -0,0 +1,187 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hydromancer_Thespia +SD%Complete: 80 +SDComment: Needs additional adjustments (when instance script is adjusted) +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +/* ContentData +boss_hydromancer_thespia +mob_coilfang_waterelemental +EndContentData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_SUMMON -1545000 +#define SAY_AGGRO_1 -1545001 +#define SAY_AGGRO_2 -1545002 +#define SAY_AGGRO_3 -1545003 +#define SAY_SLAY_1 -1545004 +#define SAY_SLAY_2 -1545005 +#define SAY_DEAD -1545006 + +#define SPELL_LIGHTNING_CLOUD 25033 +#define SPELL_LUNG_BURST 31481 +#define SPELL_ENVELOPING_WINDS 31718 + +struct boss_thespiaAI : public ScriptedAI +{ + boss_thespiaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 LightningCloud_Timer; + uint32 LungBurst_Timer; + uint32 EnvelopingWinds_Timer; + + void Reset() + { + LightningCloud_Timer = 15000; + LungBurst_Timer = 7000; + EnvelopingWinds_Timer = 9000; + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, NOT_STARTED); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEAD, me); + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //LightningCloud_Timer + if (LightningCloud_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LIGHTNING_CLOUD); + + //cast twice in Heroic mode + if (IsHeroic()) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LIGHTNING_CLOUD); + + LightningCloud_Timer = 15000+rand()%10000; + } else LightningCloud_Timer -=diff; + + //LungBurst_Timer + if (LungBurst_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LUNG_BURST); + LungBurst_Timer = 7000+rand()%5000; + } else LungBurst_Timer -=diff; + + //EnvelopingWinds_Timer + if (EnvelopingWinds_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ENVELOPING_WINDS); + + //cast twice in Heroic mode + if (IsHeroic()) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ENVELOPING_WINDS); + EnvelopingWinds_Timer = 10000+rand()%5000; + } else EnvelopingWinds_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_WATER_BOLT_VOLLEY 34449 +#define H_SPELL_WATER_BOLT_VOLLEY 37924 + +struct mob_coilfang_waterelementalAI : public ScriptedAI +{ + mob_coilfang_waterelementalAI(Creature *c) : ScriptedAI(c) {} + + uint32 WaterBoltVolley_Timer; + + void Reset() + { + WaterBoltVolley_Timer = 3000+rand()%3000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (WaterBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_WATER_BOLT_VOLLEY); + WaterBoltVolley_Timer = 7000+rand()%5000; + } else WaterBoltVolley_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thespiaAI(Creature* pCreature) +{ + return new boss_thespiaAI (pCreature); +} + +CreatureAI* GetAI_mob_coilfang_waterelementalAI(Creature* pCreature) +{ + return new mob_coilfang_waterelementalAI (pCreature); +} + +void AddSC_boss_hydromancer_thespia() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_hydromancer_thespia"; + newscript->GetAI = &GetAI_boss_thespiaAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_waterelemental"; + newscript->GetAI = &GetAI_mob_coilfang_waterelementalAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp new file mode 100644 index 00000000000..f2da4058e44 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp @@ -0,0 +1,264 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mekgineer_Steamrigger +SD%Complete: 60 +SDComment: Mechanics' interrrupt heal doesn't work very well, also a proper movement needs to be implemented -> summon further away and move towards pTarget to repair. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +/* ContentData +boss_mekgineer_steamrigger +mob_steamrigger_mechanic +EndContentData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_MECHANICS -1545007 +#define SAY_AGGRO_1 -1545008 +#define SAY_AGGRO_2 -1545009 +#define SAY_AGGRO_3 -1545010 +#define SAY_AGGRO_4 -1545011 +#define SAY_SLAY_1 -1545012 +#define SAY_SLAY_2 -1545013 +#define SAY_SLAY_3 -1545014 +#define SAY_DEATH -1545015 + +#define SPELL_SUPER_SHRINK_RAY 31485 +#define SPELL_SAW_BLADE 31486 +#define SPELL_ELECTRIFIED_NET 35107 +#define H_SPELL_ENRAGE 1 //corrent enrage spell not known + +#define ENTRY_STREAMRIGGER_MECHANIC 17951 + +struct boss_mekgineer_steamriggerAI : public ScriptedAI +{ + boss_mekgineer_steamriggerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Shrink_Timer; + uint32 Saw_Blade_Timer; + uint32 Electrified_Net_Timer; + bool Summon75; + bool Summon50; + bool Summon25; + + void Reset() + { + Shrink_Timer = 20000; + Saw_Blade_Timer = 15000; + Electrified_Net_Timer = 10000; + + Summon75 = false; + Summon50 = false; + Summon25 = false; + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, NOT_STARTED); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, IN_PROGRESS); + } + + //no known summon spells exist + void SummonMechanichs() + { + DoScriptText(SAY_MECHANICS, me); + + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + + if (rand()%2) + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,-7,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + if (rand()%2) + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,7,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Shrink_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUPER_SHRINK_RAY); + Shrink_Timer = 20000; + } else Shrink_Timer -= diff; + + if (Saw_Blade_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_SAW_BLADE); + else + DoCast(me->getVictim(), SPELL_SAW_BLADE); + + Saw_Blade_Timer = 15000; + } else Saw_Blade_Timer -= diff; + + if (Electrified_Net_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ELECTRIFIED_NET); + Electrified_Net_Timer = 10000; + } + else Electrified_Net_Timer -= diff; + + if (!Summon75) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 75) + { + SummonMechanichs(); + Summon75 = true; + } + } + + if (!Summon50) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) + { + SummonMechanichs(); + Summon50 = true; + } + } + + if (!Summon25) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) + { + SummonMechanichs(); + Summon25 = true; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_mekgineer_steamrigger(Creature* pCreature) +{ + return new boss_mekgineer_steamriggerAI (pCreature); +} + +#define SPELL_DISPEL_MAGIC 17201 +#define SPELL_REPAIR 31532 +#define H_SPELL_REPAIR 37936 + +#define MAX_REPAIR_RANGE (13.0f) //we should be at least at this range for repair +#define MIN_REPAIR_RANGE (7.0f) //we can stop movement at this range to repair but not required + +struct mob_steamrigger_mechanicAI : public ScriptedAI +{ + mob_steamrigger_mechanicAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Repair_Timer; + + void Reset() + { + Repair_Timer = 2000; + } + + void MoveInLineOfSight(Unit* /*who*/) + { + //react only if attacked + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (Repair_Timer <= diff) + { + if (pInstance && pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER) && pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) + { + if (Unit* pMekgineer = Unit::GetUnit((*me), pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER))) + { + if (me->IsWithinDistInMap(pMekgineer, MAX_REPAIR_RANGE)) + { + //are we already channeling? Doesn't work very well, find better check? + if (!me->GetUInt32Value(UNIT_CHANNEL_SPELL)) + { + //me->GetMotionMaster()->MovementExpired(); + //me->GetMotionMaster()->MoveIdle(); + + DoCast(me, SPELL_REPAIR, true); + } + Repair_Timer = 5000; + } + else + { + //me->GetMotionMaster()->MovementExpired(); + //me->GetMotionMaster()->MoveFollow(pMekgineer,0,0); + } + } + } else Repair_Timer = 5000; + } else Repair_Timer -= diff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_steamrigger_mechanic(Creature* pCreature) +{ + return new mob_steamrigger_mechanicAI (pCreature); +} + +void AddSC_boss_mekgineer_steamrigger() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_mekgineer_steamrigger"; + newscript->GetAI = &GetAI_boss_mekgineer_steamrigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_steamrigger_mechanic"; + newscript->GetAI = &GetAI_mob_steamrigger_mechanic; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp new file mode 100644 index 00000000000..f46956dda81 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp @@ -0,0 +1,204 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warlord_Kalithres +SD%Complete: 65 +SDComment: Contains workarounds regarding warlord's rage spells not acting as expected. Both scripts here require review and fine tuning. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_INTRO -1545016 +#define SAY_REGEN -1545017 +#define SAY_AGGRO1 -1545018 +#define SAY_AGGRO2 -1545019 +#define SAY_AGGRO3 -1545020 +#define SAY_SLAY1 -1545021 +#define SAY_SLAY2 -1545022 +#define SAY_DEATH -1545023 + +#define SPELL_SPELL_REFLECTION 31534 +#define SPELL_IMPALE 39061 +#define SPELL_WARLORDS_RAGE 37081 +#define SPELL_WARLORDS_RAGE_NAGA 31543 + +#define SPELL_WARLORDS_RAGE_PROC 36453 + +struct mob_naga_distillerAI : public ScriptedAI +{ + mob_naga_distillerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + //hack, due to really weird spell behaviour :( + if (pInstance) + { + if (pInstance->GetData(TYPE_DISTILLER) == IN_PROGRESS) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + } + + void EnterCombat(Unit * /*who*/) { } + + void StartRageGen(Unit * /*caster*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + DoCast(me, SPELL_WARLORDS_RAGE_NAGA, true); + + if (pInstance) + pInstance->SetData(TYPE_DISTILLER,IN_PROGRESS); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (me->GetHealth() <= damage) + if (pInstance) + pInstance->SetData(TYPE_DISTILLER,DONE); + } +}; + +struct boss_warlord_kalithreshAI : public ScriptedAI +{ + boss_warlord_kalithreshAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Reflection_Timer; + uint32 Impale_Timer; + uint32 Rage_Timer; + bool CanRage; + + void Reset() + { + Reflection_Timer = 10000; + Impale_Timer = 7000+rand()%7000; + Rage_Timer = 45000; + CanRage = false; + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + //hack :( + if (spell->Id == SPELL_WARLORDS_RAGE_PROC) + if (pInstance) + if (pInstance->GetData(TYPE_DISTILLER) == DONE) + me->RemoveAurasDueToSpell(SPELL_WARLORDS_RAGE_PROC); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Rage_Timer <= diff) + { + if (Creature* distiller = me->FindNearestCreature(17954, 100.0f)) + { + DoScriptText(SAY_REGEN, me); + DoCast(me, SPELL_WARLORDS_RAGE); + CAST_AI(mob_naga_distillerAI, distiller->AI())->StartRageGen(me); + } + Rage_Timer = 3000+rand()%15000; + } else Rage_Timer -= diff; + + //Reflection_Timer + if (Reflection_Timer <= diff) + { + DoCast(me, SPELL_SPELL_REFLECTION); + Reflection_Timer = 15000+rand()%10000; + } else Reflection_Timer -= diff; + + //Impale_Timer + if (Impale_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_IMPALE); + + Impale_Timer = 7500+rand()%5000; + } else Impale_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_naga_distiller(Creature* pCreature) +{ + return new mob_naga_distillerAI (pCreature); +} + +CreatureAI* GetAI_boss_warlord_kalithresh(Creature* pCreature) +{ + return new boss_warlord_kalithreshAI (pCreature); +} + +void AddSC_boss_warlord_kalithresh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_naga_distiller"; + newscript->GetAI = &GetAI_mob_naga_distiller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_warlord_kalithresh"; + newscript->GetAI = &GetAI_boss_warlord_kalithresh; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp new file mode 100644 index 00000000000..188a23738f5 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp @@ -0,0 +1,231 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Steam_Vault +SD%Complete: 80 +SDComment: Instance script and access panel GO +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define MAX_ENCOUNTER 4 + +#define MAIN_CHAMBERS_DOOR 183049 +#define ACCESS_PANEL_HYDRO 184125 +#define ACCESS_PANEL_MEK 184126 + +/* Steam Vaults encounters: +1 - Hydromancer Thespia Event +2 - Mekgineer Steamrigger Event +3 - Warlord Kalithresh Event +*/ + +bool GOHello_go_main_chambers_access_panel(Player* /*pPlayer*/, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + + if (!pInstance) + return false; + + if (pGo->GetEntry() == ACCESS_PANEL_HYDRO && (pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == DONE || pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL)) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA,SPECIAL); + + if (pGo->GetEntry() == ACCESS_PANEL_MEK && (pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == DONE || pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL)) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER,SPECIAL); + + return true; +} + +struct instance_steam_vault : public ScriptedInstance +{ + instance_steam_vault(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 ThespiaGUID; + uint64 MekgineerGUID; + uint64 KalithreshGUID; + + uint64 MainChambersDoor; + uint64 AccessPanelHydro; + uint64 AccessPanelMek; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + ThespiaGUID = 0; + MekgineerGUID = 0; + KalithreshGUID = 0; + MainChambersDoor = 0; + AccessPanelHydro = 0; + AccessPanelMek = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17797: ThespiaGUID = pCreature->GetGUID(); break; + case 17796: MekgineerGUID = pCreature->GetGUID(); break; + case 17798: KalithreshGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case MAIN_CHAMBERS_DOOR: MainChambersDoor = pGo->GetGUID(); break; + case ACCESS_PANEL_HYDRO: AccessPanelHydro = pGo->GetGUID(); break; + case ACCESS_PANEL_MEK: AccessPanelMek = pGo->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_HYDROMANCER_THESPIA: + if (data == SPECIAL) + { + HandleGameObject(AccessPanelHydro, true); + + if (GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL) + HandleGameObject(MainChambersDoor, true); + + debug_log("TSCR: Instance Steamvault: Access panel used."); + } + m_auiEncounter[0] = data; + break; + case TYPE_MEKGINEER_STEAMRIGGER: + if (data == SPECIAL) + { + HandleGameObject(AccessPanelMek, true); + + if (GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL) + HandleGameObject(MainChambersDoor, true); + + debug_log("TSCR: Instance Steamvault: Access panel used."); + } + m_auiEncounter[1] = data; + break; + case TYPE_WARLORD_KALITHRESH: + m_auiEncounter[2] = data; + break; + case TYPE_DISTILLER: + m_auiEncounter[3] = data; + break; + } + + if (data == DONE || data == SPECIAL) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HYDROMANCER_THESPIA: + return m_auiEncounter[0]; + case TYPE_MEKGINEER_STEAMRIGGER: + return m_auiEncounter[1]; + case TYPE_WARLORD_KALITHRESH: + return m_auiEncounter[2]; + case TYPE_DISTILLER: + return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THESPIA: + return ThespiaGUID; + case DATA_MEKGINEERSTEAMRIGGER: + return MekgineerGUID; + case DATA_KALITRESH: + return KalithreshGUID; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_steam_vault(Map* pMap) +{ + return new instance_steam_vault(pMap); +} + +void AddSC_instance_steam_vault() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_main_chambers_access_panel"; + newscript->pGOHello = &GOHello_go_main_chambers_access_panel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "instance_steam_vault"; + newscript->GetInstanceData = &GetInstanceData_instance_steam_vault; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h new file mode 100644 index 00000000000..4b407ac4816 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_STEAM_VAULT_H +#define DEF_STEAM_VAULT_H + +#define TYPE_HYDROMANCER_THESPIA 1 +#define TYPE_MEKGINEER_STEAMRIGGER 2 +#define TYPE_WARLORD_KALITHRESH 3 +#define TYPE_DISTILLER 4 + +#define DATA_MEKGINEERSTEAMRIGGER 5 +#define DATA_KALITRESH 6 +#define DATA_THESPIA 7 +#endif + diff --git a/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp b/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp new file mode 100644 index 00000000000..fcfcc1b1a90 --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp @@ -0,0 +1,154 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hungarfen +SD%Complete: 95 +SDComment: Need confirmation if spell data are same in both modes. Summons should have faster rate in heroic +SDCategory: Coilfang Resevoir, Underbog +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FOUL_SPORES 31673 +#define SPELL_ACID_GEYSER 38739 + +struct boss_hungarfenAI : public ScriptedAI +{ + boss_hungarfenAI(Creature *c) : ScriptedAI(c) + { + } + + bool Root; + uint32 Mushroom_Timer; + uint32 AcidGeyser_Timer; + + void Reset() + { + Root = false; + Mushroom_Timer = 5000; // 1 mushroom after 5s, then one per 10s. This should be different in heroic mode + AcidGeyser_Timer = 10000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) + { + if (!Root) + { + DoCast(me, SPELL_FOUL_SPORES); + Root = true; + } + } + + if (Mushroom_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + me->SummonCreature(17990, pTarget->GetPositionX()+(rand()%8), pTarget->GetPositionY()+(rand()%8), pTarget->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); + else + me->SummonCreature(17990, me->GetPositionX()+(rand()%8), me->GetPositionY()+(rand()%8), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); + + Mushroom_Timer = 10000; + } else Mushroom_Timer -= diff; + + if (AcidGeyser_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ACID_GEYSER); + AcidGeyser_Timer = 10000+rand()%7500; + } else AcidGeyser_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hungarfen(Creature* pCreature) +{ + return new boss_hungarfenAI (pCreature); +} + +#define SPELL_SPORE_CLOUD 34168 +#define SPELL_PUTRID_MUSHROOM 31690 +#define SPELL_GROW 31698 + +struct mob_underbog_mushroomAI : public ScriptedAI +{ + mob_underbog_mushroomAI(Creature *c) : ScriptedAI(c) {} + + bool Stop; + uint32 Grow_Timer; + uint32 Shrink_Timer; + + void Reset() + { + Stop = false; + Grow_Timer = 0; + Shrink_Timer = 20000; + + DoCast(me, SPELL_PUTRID_MUSHROOM, true); + DoCast(me, SPELL_SPORE_CLOUD, true); + } + + void MoveInLineOfSight(Unit * /*who*/) {} + + void AttackStart(Unit* /*who*/) {} + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (Stop) + return; + + if (Grow_Timer <= diff) + { + DoCast(me, SPELL_GROW); + Grow_Timer = 3000; + } else Grow_Timer -= diff; + + if (Shrink_Timer <= diff) + { + me->RemoveAurasDueToSpell(SPELL_GROW); + Stop = true; + } else Shrink_Timer -= diff; + } +}; +CreatureAI* GetAI_mob_underbog_mushroom(Creature* pCreature) +{ + return new mob_underbog_mushroomAI (pCreature); +} + +void AddSC_boss_hungarfen() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_hungarfen"; + newscript->GetAI = &GetAI_boss_hungarfen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_underbog_mushroom"; + newscript->GetAI = &GetAI_mob_underbog_mushroom; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp b/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp new file mode 100644 index 00000000000..3a78660389b --- /dev/null +++ b/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp @@ -0,0 +1,185 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_the_black_stalker +SD%Complete: 95 +SDComment: Timers may be incorrect +SDCategory: Coilfang Resevoir, Underbog +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_LEVITATE 31704 +#define SPELL_SUSPENSION 31719 +#define SPELL_LEVITATION_PULSE 31701 +#define SPELL_MAGNETIC_PULL 31705 +#define SPELL_CHAIN_LIGHTNING 31717 +#define SPELL_STATIC_CHARGE 31715 +#define SPELL_SUMMON_SPORE_STRIDER 38755 + +#define ENTRY_SPORE_STRIDER 22299 + +struct boss_the_black_stalkerAI : public ScriptedAI +{ + boss_the_black_stalkerAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 SporeStriders_Timer; + uint32 Levitate_Timer; + uint32 ChainLightning_Timer; + uint32 StaticCharge_Timer; + uint64 LevitatedTarget; + uint32 LevitatedTarget_Timer; + bool InAir; + uint32 check_Timer; + std::list Striders; + + void Reset() + { + Levitate_Timer = 12000; + ChainLightning_Timer = 6000; + StaticCharge_Timer = 10000; + SporeStriders_Timer = 10000+rand()%5000; + check_Timer = 5000; + LevitatedTarget = 0; + LevitatedTarget_Timer = 0; + Striders.clear(); + } + + void EnterCombat(Unit * /*who*/) {} + + void JustSummoned(Creature *summon) + { + if (summon && summon->GetEntry() == ENTRY_SPORE_STRIDER) + { + Striders.push_back(summon->GetGUID()); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + summon->AI()->AttackStart(pTarget); + else + if (me->getVictim()) + summon->AI()->AttackStart(me->getVictim()); + } + } + + void JustDied(Unit * /*who*/) + { + for (std::list::const_iterator i = Striders.begin(); i != Striders.end(); ++i) + if (Creature *strider = Unit::GetCreature(*me, *i)) + strider->DisappearAndDie(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Evade if too far + if (check_Timer <= diff) + { + float x,y,z,o; + me->GetHomePosition(x,y,z,o); + if (!me->IsWithinDist3d(x,y,z, 60)) + { + EnterEvadeMode(); + return; + } + check_Timer = 1000; + } else check_Timer -= diff; + + // Spore Striders + if (IsHeroic() && SporeStriders_Timer <= diff) + { + DoCast(me, SPELL_SUMMON_SPORE_STRIDER); + SporeStriders_Timer = 10000+rand()%5000; + } else SporeStriders_Timer -= diff; + + // Levitate + if (LevitatedTarget) + { + if (LevitatedTarget_Timer <= diff) + { + if (Unit *pTarget = Unit::GetUnit(*me, LevitatedTarget)) + { + if (!pTarget->HasAura(SPELL_LEVITATE)) + { + LevitatedTarget = 0; + return; + } + if (InAir) + { + pTarget->AddAura(SPELL_SUSPENSION, pTarget); + LevitatedTarget = 0; + } + else + { + pTarget->CastSpell(pTarget, SPELL_MAGNETIC_PULL, true); + InAir = true; + LevitatedTarget_Timer = 1500; + } + } + else + LevitatedTarget = 0; + } else LevitatedTarget_Timer -= diff; + } + if (Levitate_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + DoCast(pTarget, SPELL_LEVITATE); + LevitatedTarget = pTarget->GetGUID(); + LevitatedTarget_Timer = 2000; + InAir = false; + } + Levitate_Timer = 12000+rand()%3000; + } else Levitate_Timer -= diff; + + // Chain Lightning + if (ChainLightning_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + ChainLightning_Timer = 7000; + } else ChainLightning_Timer -= diff; + + // Static Charge + if (StaticCharge_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true)) + DoCast(pTarget, SPELL_STATIC_CHARGE); + StaticCharge_Timer = 10000; + } else StaticCharge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_the_black_stalker(Creature* pCreature) +{ + return new boss_the_black_stalkerAI (pCreature); +} + +void AddSC_boss_the_black_stalker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_the_black_stalker"; + newscript->GetAI = &GetAI_boss_the_black_stalker; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp b/src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp new file mode 100644 index 00000000000..a07ac910598 --- /dev/null +++ b/src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp @@ -0,0 +1,255 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gruul +SD%Complete: 60 +SDComment: Ground Slam need further development (knock back effect and shatter effect must be added to the core) +SDCategory: Gruul's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "gruuls_lair.h" + +enum eEnums +{ + SAY_AGGRO = -1565010, + SAY_SLAM1 = -1565011, + SAY_SLAM2 = -1565012, + SAY_SHATTER1 = -1565013, + SAY_SHATTER2 = -1565014, + SAY_SLAY1 = -1565015, + SAY_SLAY2 = -1565016, + SAY_SLAY3 = -1565017, + SAY_DEATH = -1565018, + + EMOTE_GROW = -1565019, + + SPELL_GROWTH = 36300, + SPELL_CAVE_IN = 36240, + SPELL_GROUND_SLAM = 33525, //AoE Ground Slam applying Ground Slam to everyone with a script effect (most likely the knock back, we can code it to a set knockback) + SPELL_REVERBERATION = 36297, + SPELL_SHATTER = 33654, + + SPELL_SHATTER_EFFECT = 33671, + SPELL_HURTFUL_STRIKE = 33813, + SPELL_STONED = 33652, //Spell is self cast by target + + SPELL_MAGNETIC_PULL = 28337, + SPELL_KNOCK_BACK = 24199, //Knockback spell until correct implementation is made +}; + +struct boss_gruulAI : public ScriptedAI +{ + boss_gruulAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 m_uiGrowth_Timer; + uint32 m_uiCaveIn_Timer; + uint32 m_uiCaveIn_StaticTimer; + uint32 m_uiGroundSlamTimer; + uint32 m_uiHurtfulStrike_Timer; + uint32 m_uiReverberation_Timer; + + bool m_bPerformingGroundSlam; + + void Reset() + { + m_uiGrowth_Timer= 30000; + m_uiCaveIn_Timer= 27000; + m_uiCaveIn_StaticTimer = 30000; + m_uiGroundSlamTimer= 35000; + m_bPerformingGroundSlam= false; + m_uiHurtfulStrike_Timer= 8000; + m_uiReverberation_Timer= 60000+45000; + + if (pInstance) + pInstance->SetData(DATA_GRUULEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_GRUULEVENT, IN_PROGRESS); + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_GRUULEVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GRUULDOOR), true); // Open the encounter door + } + } + + void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) + { + //This to emulate effect1 (77) of SPELL_GROUND_SLAM, knock back to any direction + //It's initially wrong, since this will cause fall damage, which is by comments, not intended. + if (pSpell->Id == SPELL_GROUND_SLAM) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + switch (urand(0,1)) + { + case 0: pTarget->CastSpell(pTarget, SPELL_MAGNETIC_PULL, true, NULL, NULL, me->GetGUID()); break; + case 1: pTarget->CastSpell(pTarget, SPELL_KNOCK_BACK, true, NULL, NULL, me->GetGUID()); break; + } + } + } + + //this part should be in the core + if (pSpell->Id == SPELL_SHATTER) + { + //this spell must have custom handling in the core, dealing damage based on distance + pTarget->CastSpell(pTarget, SPELL_SHATTER_EFFECT, true); + + if (pTarget->HasAura(SPELL_STONED)) + pTarget->RemoveAurasDueToSpell(SPELL_STONED); + + //clear this, if we are still performing + if (m_bPerformingGroundSlam) + { + m_bPerformingGroundSlam = false; + + //and correct movement, if not already + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + { + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // Growth + // Gruul can cast this spell up to 30 times + if (m_uiGrowth_Timer <= uiDiff) + { + DoScriptText(EMOTE_GROW, me); + DoCast(me, SPELL_GROWTH); + m_uiGrowth_Timer = 30000; + } + else + m_uiGrowth_Timer -= uiDiff; + + if (m_bPerformingGroundSlam) + { + if (m_uiGroundSlamTimer <= uiDiff) + { + m_uiGroundSlamTimer =120000; + m_uiHurtfulStrike_Timer= 8000; + + if (m_uiReverberation_Timer < 10000) //Give a little time to the players to undo the damage from shatter + m_uiReverberation_Timer += 10000; + + DoCast(me, SPELL_SHATTER); + } + else + m_uiGroundSlamTimer -= uiDiff; + } + else + { + // Hurtful Strike + if (m_uiHurtfulStrike_Timer <= uiDiff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + + if (pTarget && me->IsWithinMeleeRange(me->getVictim())) + DoCast(pTarget, SPELL_HURTFUL_STRIKE); + else + DoCast(me->getVictim(), SPELL_HURTFUL_STRIKE); + + m_uiHurtfulStrike_Timer= 8000; + } + else + m_uiHurtfulStrike_Timer -= uiDiff; + + // Reverberation + if (m_uiReverberation_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_REVERBERATION, true); + m_uiReverberation_Timer = 15000 + rand()%10000; + } + else + m_uiReverberation_Timer -= uiDiff; + + // Cave In + if (m_uiCaveIn_Timer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CAVE_IN); + + if (m_uiCaveIn_StaticTimer >= 4000) + m_uiCaveIn_StaticTimer -= 2000; + + m_uiCaveIn_Timer = m_uiCaveIn_StaticTimer; + } + else + m_uiCaveIn_Timer -= uiDiff; + + // Ground Slam, Gronn Lord's Grasp, Stoned, Shatter + if (m_uiGroundSlamTimer <= uiDiff) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + + m_bPerformingGroundSlam= true; + m_uiGroundSlamTimer = 10000; + + DoCast(me, SPELL_GROUND_SLAM); + } + else + m_uiGroundSlamTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + } +}; + +CreatureAI* GetAI_boss_gruul(Creature* pCreature) +{ + return new boss_gruulAI (pCreature); +} + +void AddSC_boss_gruul() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gruul"; + newscript->GetAI = &GetAI_boss_gruul; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp b/src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp new file mode 100644 index 00000000000..482af86225c --- /dev/null +++ b/src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp @@ -0,0 +1,783 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_King_Maulgar +SD%Complete: 90 +SDComment: Correct timers, after whirlwind melee attack bug, prayer of healing +SDCategory: Gruul's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "gruuls_lair.h" + +#define SAY_AGGRO -1565000 +#define SAY_ENRAGE -1565001 +#define SAY_OGRE_DEATH1 -1565002 +#define SAY_OGRE_DEATH2 -1565003 +#define SAY_OGRE_DEATH3 -1565004 +#define SAY_OGRE_DEATH4 -1565005 +#define SAY_SLAY1 -1565006 +#define SAY_SLAY2 -1565007 +#define SAY_SLAY3 -1565008 +#define SAY_DEATH -1565009 + +// High King Maulgar +#define SPELL_ARCING_SMASH 39144 +#define SPELL_MIGHTY_BLOW 33230 +#define SPELL_WHIRLWIND 33238 +#define SPELL_BERSERKER_C 26561 +#define SPELL_ROAR 16508 +#define SPELL_FLURRY 33232 +#define SPELL_DUAL_WIELD 29651 //used in phase + +// Olm the Summoner +#define SPELL_DARK_DECAY 33129 +#define SPELL_DEATH_COIL 33130 +#define SPELL_SUMMON_WFH 33131 + +//Kiggler the Craed +#define SPELL_GREATER_POLYMORPH 33173 +#define SPELL_LIGHTNING_BOLT 36152 +#define SPELL_ARCANE_SHOCK 33175 +#define SPELL_ARCANE_EXPLOSION 33237 + +//Blindeye the Seer +#define SPELL_GREATER_PW_SHIELD 33147 +#define SPELL_HEAL 33144 +#define SPELL_PRAYER_OH 33152 + +//Krosh Firehand +#define SPELL_GREATER_FIREBALL 33051 +#define SPELL_SPELLSHIELD 33054 +#define SPELL_BLAST_WAVE 33061 + +bool CheckAllBossDied(ScriptedInstance* pInstance, Creature* me) +{ + if (!pInstance || !me) + return false; + + uint64 MaulgarGUID = 0; + uint64 KigglerGUID = 0; + uint64 BlindeyeGUID = 0; + uint64 OlmGUID = 0; + uint64 KroshGUID = 0; + + Creature* Maulgar = NULL; + Creature* Kiggler = NULL; + Creature* Blindeye = NULL; + Creature* Olm = NULL; + Creature* Krosh = NULL; + + MaulgarGUID = pInstance->GetData64(DATA_MAULGAR); + KigglerGUID = pInstance->GetData64(DATA_KIGGLERTHECRAZED); + BlindeyeGUID = pInstance->GetData64(DATA_BLINDEYETHESEER); + OlmGUID = pInstance->GetData64(DATA_OLMTHESUMMONER); + KroshGUID = pInstance->GetData64(DATA_KROSHFIREHAND); + + Maulgar = (Unit::GetCreature((*me), MaulgarGUID)); + Kiggler = (Unit::GetCreature((*me), KigglerGUID)); + Blindeye = (Unit::GetCreature((*me), BlindeyeGUID)); + Olm = (Unit::GetCreature((*me), OlmGUID)); + Krosh = (Unit::GetCreature((*me), KroshGUID)); + + if (!Maulgar || !Kiggler || !Blindeye || !Olm || !Krosh) + return false; + + if (!Maulgar->isAlive() && !Kiggler->isAlive() && !Blindeye->isAlive() && !Olm->isAlive() && !Krosh->isAlive()) + return true; + + return false; +} + +//High King Maulgar AI +struct boss_high_king_maulgarAI : public ScriptedAI +{ + boss_high_king_maulgarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i = 0; i < 4; ++i) + Council[i] = 0; + } + + ScriptedInstance* pInstance; + + uint32 ArcingSmash_Timer; + uint32 MightyBlow_Timer; + uint32 Whirlwind_Timer; + uint32 Charging_Timer; + uint32 Roar_Timer; + + bool Phase2; + + uint64 Council[4]; + + void Reset() + { + ArcingSmash_Timer = 10000; + MightyBlow_Timer = 40000; + Whirlwind_Timer = 30000; + Charging_Timer = 0; + Roar_Timer = 0; + + DoCast(me, SPELL_DUAL_WIELD, false); + + Phase2 = false; + + Creature *pCreature = NULL; + for (uint8 i = 0; i < 4; ++i) + { + if (Council[i]) + { + pCreature = (Unit::GetCreature((*me), Council[i])); + if (pCreature && !pCreature->isAlive()) + { + pCreature->Respawn(); + pCreature->AI()->EnterEvadeMode(); + } + } + } + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + + void AddDeath() + { + DoScriptText(RAND(SAY_OGRE_DEATH1,SAY_OGRE_DEATH2,SAY_OGRE_DEATH3,SAY_OGRE_DEATH4), me); + } + + void EnterCombat(Unit *who) + { + StartEvent(who); + } + + void GetCouncil() + { + if (pInstance) + { + //get council member's guid to respawn them if needed + Council[0] = pInstance->GetData64(DATA_KIGGLERTHECRAZED); + Council[1] = pInstance->GetData64(DATA_BLINDEYETHESEER); + Council[2] = pInstance->GetData64(DATA_OLMTHESUMMONER); + Council[3] = pInstance->GetData64(DATA_KROSHFIREHAND); + } + } + + void StartEvent(Unit *who) + { + if (!pInstance) + return; + + GetCouncil(); + + DoScriptText(SAY_AGGRO, me); + + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + GetCouncil(); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //ArcingSmash_Timer + if (ArcingSmash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCING_SMASH); + ArcingSmash_Timer = 10000; + } else ArcingSmash_Timer -= diff; + + //Whirlwind_Timer + if (Whirlwind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + Whirlwind_Timer = 55000; + } else Whirlwind_Timer -= diff; + + //MightyBlow_Timer + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTY_BLOW); + MightyBlow_Timer = 30000+rand()%10000; + } else MightyBlow_Timer -= diff; + + //Entering Phase 2 + if (!Phase2 && (me->GetHealth()*100 / me->GetMaxHealth()) < 50) + { + Phase2 = true; + DoScriptText(SAY_ENRAGE, me); + + DoCast(me, SPELL_DUAL_WIELD, true); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + } + + if (Phase2) + { + //Charging_Timer + if (Charging_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + AttackStart(pTarget); + DoCast(pTarget, SPELL_BERSERKER_C); + } + Charging_Timer = 20000; + } else Charging_Timer -= diff; + + //Intimidating Roar + if (Roar_Timer <= diff) + { + DoCast(me, SPELL_ROAR); + Roar_Timer = 40000+(rand()%10000); + } else Roar_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +//Olm The Summoner AI +struct boss_olm_the_summonerAI : public ScriptedAI +{ + boss_olm_the_summonerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 DarkDecay_Timer; + uint32 Summon_Timer; + uint32 DeathCoil_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + DarkDecay_Timer = 10000; + Summon_Timer = 15000; + DeathCoil_Timer = 20000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(pWho, 30.0f); + } + } + + void EnterCombat(Unit *who) + { + if (pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + Creature *Maulgar = NULL; + Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); + + if (Maulgar) + CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //DarkDecay_Timer + if (DarkDecay_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DARK_DECAY); + DarkDecay_Timer = 20000; + } else DarkDecay_Timer -= diff; + + //Summon_Timer + if (Summon_Timer <= diff) + { + DoCast(me, SPELL_SUMMON_WFH); + Summon_Timer = 30000; + } else Summon_Timer -= diff; + + //DeathCoil Timer /need correct timer + if (DeathCoil_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_DEATH_COIL); + DeathCoil_Timer = 20000; + } else DeathCoil_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Kiggler The Crazed AI +struct boss_kiggler_the_crazedAI : public ScriptedAI +{ + boss_kiggler_the_crazedAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 GreaterPolymorph_Timer; + uint32 LightningBolt_Timer; + uint32 ArcaneShock_Timer; + uint32 ArcaneExplosion_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreaterPolymorph_Timer = 5000; + LightningBolt_Timer = 10000; + ArcaneShock_Timer = 20000; + ArcaneExplosion_Timer = 30000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + if (pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + Creature *Maulgar = NULL; + Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); + + if (Maulgar) + CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //GreaterPolymorph_Timer + if (GreaterPolymorph_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_GREATER_POLYMORPH); + + GreaterPolymorph_Timer = 15000 + rand()%5000; + } else GreaterPolymorph_Timer -= diff; + + //LightningBolt_Timer + if (LightningBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); + LightningBolt_Timer = 15000; + } else LightningBolt_Timer -= diff; + + //ArcaneShock_Timer + if (ArcaneShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_SHOCK); + ArcaneShock_Timer = 20000; + } else ArcaneShock_Timer -= diff; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 30000; + } else ArcaneExplosion_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Blindeye The Seer AI +struct boss_blindeye_the_seerAI : public ScriptedAI +{ + boss_blindeye_the_seerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 GreaterPowerWordShield_Timer; + uint32 Heal_Timer; + uint32 PrayerofHealing_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreaterPowerWordShield_Timer = 5000; + Heal_Timer = 25000 + rand()%15000; + PrayerofHealing_Timer = 45000 + rand()%10000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + Creature *Maulgar = NULL; + Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); + + if (Maulgar) + CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //GreaterPowerWordShield_Timer + if (GreaterPowerWordShield_Timer <= diff) + { + DoCast(me, SPELL_GREATER_PW_SHIELD); + GreaterPowerWordShield_Timer = 40000; + } else GreaterPowerWordShield_Timer -= diff; + + //Heal_Timer + if (Heal_Timer <= diff) + { + DoCast(me, SPELL_HEAL); + Heal_Timer = 15000 + rand()%25000; + } else Heal_Timer -= diff; + + //PrayerofHealing_Timer + if (PrayerofHealing_Timer <= diff) + { + DoCast(me, SPELL_PRAYER_OH); + PrayerofHealing_Timer = 35000 + rand()%15000; + } else PrayerofHealing_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Krosh Firehand AI +struct boss_krosh_firehandAI : public ScriptedAI +{ + boss_krosh_firehandAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 GreaterFireball_Timer; + uint32 SpellShield_Timer; + uint32 BlastWave_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreaterFireball_Timer = 1000; + SpellShield_Timer = 5000; + BlastWave_Timer = 20000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + Creature *Maulgar = NULL; + Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); + + if (Maulgar) + CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //GreaterFireball_Timer + if (GreaterFireball_Timer < diff || me->IsWithinDist(me->getVictim(), 30)) + { + DoCast(me->getVictim(), SPELL_GREATER_FIREBALL); + GreaterFireball_Timer = 2000; + } else GreaterFireball_Timer -= diff; + + //SpellShield_Timer + if (SpellShield_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me->getVictim(), SPELL_SPELLSHIELD); + SpellShield_Timer = 30000; + } else SpellShield_Timer -= diff; + + //BlastWave_Timer + if (BlastWave_Timer <= diff) + { + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //15 yard radius minimum + if (pTarget && pTarget->IsWithinDist(me, 15,false)) + target_list.push_back(pTarget); + pTarget = NULL; + } + if (target_list.size()) + pTarget = *(target_list.begin()+rand()%target_list.size()); + + me->InterruptNonMeleeSpells(false); + DoCast(pTarget, SPELL_BLAST_WAVE); + BlastWave_Timer = 60000; + } else BlastWave_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_high_king_maulgar(Creature* pCreature) +{ + return new boss_high_king_maulgarAI (pCreature); +} + +CreatureAI* GetAI_boss_olm_the_summoner(Creature* pCreature) +{ + return new boss_olm_the_summonerAI (pCreature); +} + +CreatureAI *GetAI_boss_kiggler_the_crazed(Creature* pCreature) +{ + return new boss_kiggler_the_crazedAI (pCreature); +} + +CreatureAI *GetAI_boss_blindeye_the_seer(Creature* pCreature) +{ + return new boss_blindeye_the_seerAI (pCreature); +} + +CreatureAI *GetAI_boss_krosh_firehand(Creature* pCreature) +{ + return new boss_krosh_firehandAI (pCreature); +} + +void AddSC_boss_high_king_maulgar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_high_king_maulgar"; + newscript->GetAI = &GetAI_boss_high_king_maulgar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_kiggler_the_crazed"; + newscript->GetAI = &GetAI_boss_kiggler_the_crazed; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_blindeye_the_seer"; + newscript->GetAI = &GetAI_boss_blindeye_the_seer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_olm_the_summoner"; + newscript->GetAI = &GetAI_boss_olm_the_summoner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_krosh_firehand"; + newscript->GetAI = &GetAI_boss_krosh_firehand; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/gruuls_lair/gruuls_lair.h b/src/server/scripts/Outland/gruuls_lair/gruuls_lair.h new file mode 100644 index 00000000000..7003dcb1e26 --- /dev/null +++ b/src/server/scripts/Outland/gruuls_lair/gruuls_lair.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_GRUULS_LAIR_H +#define DEF_GRUULS_LAIR_H + +#define DATA_BLINDEYETHESEER 1 +#define DATA_GRUULEVENT 2 +#define DATA_KIGGLERTHECRAZED 3 +#define DATA_KROSHFIREHAND 4 +#define DATA_MAULGAREVENT 5 +#define DATA_MAULGAREVENT_TANK 6 +#define DATA_OLMTHESUMMONER 7 +#define DATA_MAULGARDOOR 8 +#define DATA_GRUULDOOR 9 +#define DATA_MAULGAR 10 + +#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Gruul's Lair instance (map 565). Encounters will be buggy." +#endif + diff --git a/src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp b/src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp new file mode 100644 index 00000000000..bb790a5d4ea --- /dev/null +++ b/src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp @@ -0,0 +1,193 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Gruuls_Lair +SD%Complete: 100 +SDComment: +SDCategory: Gruul's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "gruuls_lair.h" + +#define MAX_ENCOUNTER 2 + +/* Gruuls Lair encounters: +1 - High King Maulgar event +2 - Gruul event +*/ + +struct instance_gruuls_lair : public ScriptedInstance +{ + instance_gruuls_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 MaulgarEvent_Tank; + uint64 KigglerTheCrazed; + uint64 BlindeyeTheSeer; + uint64 OlmTheSummoner; + uint64 KroshFirehand; + uint64 Maulgar; + + uint64 MaulgarDoor; + uint64 GruulDoor; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + MaulgarEvent_Tank = 0; + KigglerTheCrazed = 0; + BlindeyeTheSeer = 0; + OlmTheSummoner = 0; + KroshFirehand = 0; + Maulgar = 0; + + MaulgarDoor = 0; + GruulDoor = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 18835: KigglerTheCrazed = pCreature->GetGUID(); break; + case 18836: BlindeyeTheSeer = pCreature->GetGUID(); break; + case 18834: OlmTheSummoner = pCreature->GetGUID(); break; + case 18832: KroshFirehand = pCreature->GetGUID(); break; + case 18831: Maulgar = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 184468: + MaulgarDoor = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) HandleGameObject(NULL, true, pGo); + break; + case 184662: GruulDoor = pGo->GetGUID(); break; + } + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_MAULGAREVENT_TANK) + MaulgarEvent_Tank = data; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MAULGAREVENT_TANK: return MaulgarEvent_Tank; + case DATA_KIGGLERTHECRAZED: return KigglerTheCrazed; + case DATA_BLINDEYETHESEER: return BlindeyeTheSeer; + case DATA_OLMTHESUMMONER: return OlmTheSummoner; + case DATA_KROSHFIREHAND: return KroshFirehand; + case DATA_MAULGARDOOR: return MaulgarDoor; + case DATA_GRUULDOOR: return GruulDoor; + case DATA_MAULGAR: return Maulgar; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAULGAREVENT: + if (data == DONE) HandleGameObject(MaulgarDoor, true); + m_auiEncounter[0] = data; break; + case DATA_GRUULEVENT: + if (data == IN_PROGRESS) HandleGameObject(GruulDoor, false); + else HandleGameObject(GruulDoor, true); + m_auiEncounter[1] = data; break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_MAULGAREVENT: return m_auiEncounter[0]; + case DATA_GRUULEVENT: return m_auiEncounter[1]; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_gruuls_lair(Map* pMap) +{ + return new instance_gruuls_lair(pMap); +} + +void AddSC_instance_gruuls_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_gruuls_lair"; + newscript->GetInstanceData = &GetInstanceData_instance_gruuls_lair; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h new file mode 100644 index 00000000000..b845c66823f --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BLOOD_FURNACE_H +#define DEF_BLOOD_FURNACE_H + +#define DATA_THE_MAKER 1 +#define DATA_BROGGOK 2 +#define DATA_KELIDAN_THE_MAKER 3 +#define TYPE_THE_MAKER_EVENT 4 +#define TYPE_BROGGOK_EVENT 5 +#define TYPE_KELIDAN_THE_BREAKER_EVENT 6 +#define DATA_DOOR1 7 +#define DATA_DOOR2 8 +#define DATA_DOOR3 9 +#define DATA_DOOR4 10 +#define DATA_DOOR5 11 +#define DATA_DOOR6 12 +#define DATA_PRISON_CELL1 13 +#define DATA_PRISON_CELL2 14 +#define DATA_PRISON_CELL3 15 +#define DATA_PRISON_CELL4 16 +#define DATA_PRISON_CELL5 17 +#define DATA_PRISON_CELL6 18 +#define DATA_PRISON_CELL7 19 +#define DATA_PRISON_CELL8 20 +#endif + diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp new file mode 100644 index 00000000000..d5fb9bdba49 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp @@ -0,0 +1,131 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Broggok +SD%Complete: 70 +SDComment: pre-event not made +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eEnums +{ + SAY_AGGRO = -1542008, + + SPELL_SLIME_SPRAY = 30913, + SPELL_POISON_CLOUD = 30916, + SPELL_POISON_BOLT = 30917, + + SPELL_POISON = 30914 +}; + +struct boss_broggokAI : public ScriptedAI +{ + boss_broggokAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AcidSpray_Timer; + uint32 PoisonSpawn_Timer; + uint32 PoisonBolt_Timer; + + void Reset() + { + AcidSpray_Timer = 10000; + PoisonSpawn_Timer = 5000; + PoisonBolt_Timer = 7000; + if (pInstance) + { + pInstance->SetData(TYPE_BROGGOK_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + pInstance->SetData(TYPE_BROGGOK_EVENT, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), false); + } + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(16); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->CastSpell(summoned,SPELL_POISON,false,0,0,me->GetGUID()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AcidSpray_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLIME_SPRAY); + AcidSpray_Timer = 4000+rand()%8000; + } else AcidSpray_Timer -=diff; + + if (PoisonBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_BOLT); + PoisonBolt_Timer = 4000+rand()%8000; + } else PoisonBolt_Timer -=diff; + + if (PoisonSpawn_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLOUD); + PoisonSpawn_Timer = 20000; + } else PoisonSpawn_Timer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*who*/) + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR5), true); + pInstance->SetData(TYPE_BROGGOK_EVENT, DONE); + } + } + +}; + +CreatureAI* GetAI_boss_broggok(Creature* pCreature) +{ + return new boss_broggokAI (pCreature); +} + +void AddSC_boss_broggok() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_broggok"; + newscript->GetAI = &GetAI_boss_broggok; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp new file mode 100644 index 00000000000..a44ad9cc3c8 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp @@ -0,0 +1,356 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kelidan_The_Breaker +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +/* ContentData +boss_kelidan_the_breaker +mob_shadowmoon_channeler +EndContentData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eKelidan +{ + SAY_WAKE = -1542000, + SAY_ADD_AGGRO_1 = -1542001, + SAY_ADD_AGGRO_2 = -1542002, + SAY_ADD_AGGRO_3 = -1542003, + SAY_KILL_1 = -1542004, + SAY_KILL_2 = -1542005, + SAY_NOVA = -1542006, + SAY_DIE = -1542007, + + SPELL_CORRUPTION = 30938, + SPELL_EVOCATION = 30935, + + SPELL_FIRE_NOVA = 33132, + H_SPELL_FIRE_NOVA = 37371, + + SPELL_SHADOW_BOLT_VOLLEY = 28599, + H_SPELL_SHADOW_BOLT_VOLLEY = 40070, + + SPELL_BURNING_NOVA = 30940, + SPELL_VORTEX = 37370, + + ENTRY_KELIDAN = 17377, + ENTRY_CHANNELER = 17653 +}; + +const float ShadowmoonChannelers[5][4]= +{ + {302,-87,-24.4,0.157}, + {321,-63.5,-24.6,4.887}, + {346,-74.5,-24.6,3.595}, + {344,-103.5,-24.5,2.356}, + {316,-109,-24.6,1.257} +}; + +struct boss_kelidan_the_breakerAI : public ScriptedAI +{ + boss_kelidan_the_breakerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i=0; i<5; ++i) + Channelers[i] = 0; + } + + ScriptedInstance* pInstance; + + uint32 ShadowVolley_Timer; + uint32 BurningNova_Timer; + uint32 Firenova_Timer; + uint32 Corruption_Timer; + uint32 check_Timer; + bool Firenova; + bool addYell; + uint64 Channelers[5]; + + void Reset() + { + ShadowVolley_Timer = 1000; + BurningNova_Timer = 15000; + Corruption_Timer = 5000; + check_Timer = 0; + Firenova = false; + addYell = false; + SummonChannelers(); + if (pInstance) + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_WAKE, me); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoStartMovement(who); + if (pInstance) + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void ChannelerEngaged(Unit* who) + { + if (who && !addYell) + { + addYell = true; + DoScriptText(RAND(SAY_ADD_AGGRO_1,SAY_ADD_AGGRO_2,SAY_ADD_AGGRO_3), me); + } + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (who && channeler && !channeler->isInCombat()) + channeler->AI()->AttackStart(who); + } + } + + void ChannelerDied(Unit* killer) + { + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (channeler && channeler->isAlive()) + return; + } + + if (killer) + me->AI()->AttackStart(killer); + } + + uint64 GetChanneled(Creature *channeler1) + { + SummonChannelers(); + if (!channeler1) return NULL; + uint8 i; + for (i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (channeler && channeler->GetGUID() == channeler1->GetGUID()) + break; + } + return Channelers[(i+2)%5]; + } + + void SummonChannelers() + { + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (!channeler || channeler->isDead()) + channeler = me->SummonCreature(ENTRY_CHANNELER,ShadowmoonChannelers[i][0],ShadowmoonChannelers[i][1],ShadowmoonChannelers[i][2],ShadowmoonChannelers[i][3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,300000); + if (channeler) + Channelers[i] = channeler->GetGUID(); + else + Channelers[i] = 0; + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR1), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR6), true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (check_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + DoCast(me, SPELL_EVOCATION); + check_Timer = 5000; + } else check_Timer -= diff; + return; + } + + if (Firenova) + { + if (Firenova_Timer <= diff) + { + DoCast(me, SPELL_FIRE_NOVA, true); + Firenova = false; + ShadowVolley_Timer = 2000; + } else Firenova_Timer -=diff; + + return; + } + + if (ShadowVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); + ShadowVolley_Timer = 5000+rand()%8000; + } else ShadowVolley_Timer -=diff; + + if (Corruption_Timer <= diff) + { + DoCast(me, SPELL_CORRUPTION); + Corruption_Timer = 30000+rand()%20000; + } else Corruption_Timer -=diff; + + if (BurningNova_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(SAY_NOVA, me); + + if (SpellEntry *nova = GET_SPELL(SPELL_BURNING_NOVA)) + { + if (Aura * aura = Aura::TryCreate(nova, me, me)) + aura->ApplyForTargets(); + } + + if (IsHeroic()) + DoTeleportAll(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + + BurningNova_Timer = 20000+rand()%8000; + Firenova_Timer= 5000; + Firenova = true; + } else BurningNova_Timer -=diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_kelidan_the_breaker(Creature* pCreature) +{ + return new boss_kelidan_the_breakerAI (pCreature); +} + +/*###### +## mob_shadowmoon_channeler +######*/ + +enum eShadowmoon +{ + SPELL_SHADOW_BOLT = 12739, + H_SPELL_SHADOW_BOLT = 15472, + + SPELL_MARK_OF_SHADOW = 30937, + SPELL_CHANNELING = 39123 +}; + +struct mob_shadowmoon_channelerAI : public ScriptedAI +{ + mob_shadowmoon_channelerAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 ShadowBolt_Timer; + uint32 MarkOfShadow_Timer; + uint32 check_Timer; + + void Reset() + { + ShadowBolt_Timer = 1000+rand()%1000; + MarkOfShadow_Timer = 5000+rand()%2000; + check_Timer = 0; + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + } + + void EnterCombat(Unit* who) + { + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerEngaged(who); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoStartMovement(who); + } + + void JustDied(Unit* Killer) + { + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerDied(Killer); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (check_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + { + uint64 channeler = CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->GetChanneled(me); + if (Unit *channeled = Unit::GetUnit(*me, channeler)) + DoCast(channeled, SPELL_CHANNELING); + } + check_Timer = 5000; + } else check_Timer -= diff; + return; + } + + if (MarkOfShadow_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MARK_OF_SHADOW); + MarkOfShadow_Timer = 15000+rand()%5000; + } else MarkOfShadow_Timer -=diff; + + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 5000+rand()%1000; + } else ShadowBolt_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_shadowmoon_channeler(Creature* pCreature) +{ + return new mob_shadowmoon_channelerAI (pCreature); +} + +void AddSC_boss_kelidan_the_breaker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_kelidan_the_breaker"; + newscript->GetAI = &GetAI_boss_kelidan_the_breaker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadowmoon_channeler"; + newscript->GetAI = &GetAI_mob_shadowmoon_channeler; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp new file mode 100644 index 00000000000..45219b6509b --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_The_Maker +SD%Complete: 80 +SDComment: Mind control no support +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eEnums +{ + SAY_AGGRO_1 = -1542009, + SAY_AGGRO_2 = -1542010, + SAY_AGGRO_3 = -1542011, + SAY_KILL_1 = -1542012, + SAY_KILL_2 = -1542013, + SAY_DIE = -1542014, + + SPELL_ACID_SPRAY = 38153, // heroic 38973 ??? 38153 + SPELL_EXPLODING_BREAKER = 30925, + SPELL_KNOCKDOWN = 20276, + SPELL_DOMINATION = 25772 // ??? +}; + +struct boss_the_makerAI : public ScriptedAI +{ + boss_the_makerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AcidSpray_Timer; + uint32 ExplodingBreaker_Timer; + uint32 Domination_Timer; + uint32 Knockdown_Timer; + + void Reset() + { + AcidSpray_Timer = 15000; + ExplodingBreaker_Timer = 6000; + Domination_Timer = 120000; + Knockdown_Timer = 10000; + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), false); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR3), true); + + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AcidSpray_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ACID_SPRAY); + AcidSpray_Timer = 15000+rand()%8000; + } else AcidSpray_Timer -=diff; + + if (ExplodingBreaker_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_EXPLODING_BREAKER); + ExplodingBreaker_Timer = 4000+rand()%8000; + } else ExplodingBreaker_Timer -=diff; + + /* // Disabled until Core Support for mind control + if (domination_timer_timer <= diff) + { + Unit *pTarget; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(pTarget, SPELL_DOMINATION); + + domination_timer = 120000; + } else domination_timer -=diff; + */ + + if (Knockdown_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + Knockdown_Timer = 4000+rand()%8000; + } else Knockdown_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_the_makerAI(Creature* pCreature) +{ + return new boss_the_makerAI (pCreature); +} + +void AddSC_boss_the_maker() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_maker"; + newscript->GetAI = &GetAI_boss_the_makerAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp new file mode 100644 index 00000000000..3a2eb8ba5ee --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp @@ -0,0 +1,232 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Blood_Furnace +SD%Complete: 85 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +#define ENTRY_SEWER1 181823 +#define ENTRY_SEWER2 181766 +#define MAX_ENCOUNTER 3 + +struct instance_blood_furnace : public ScriptedInstance +{ + instance_blood_furnace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 The_MakerGUID; + uint64 BroggokGUID; + uint64 Kelidan_The_BreakerGUID; + + uint64 Door1GUID; + uint64 Door2GUID; + uint64 Door3GUID; + uint64 Door4GUID; + uint64 Door5GUID; + uint64 Door6GUID; + + uint64 PrisonCell1GUID; + uint64 PrisonCell2GUID; + uint64 PrisonCell3GUID; + uint64 PrisonCell4GUID; + uint64 PrisonCell5GUID; + uint64 PrisonCell6GUID; + uint64 PrisonCell7GUID; + uint64 PrisonCell8GUID; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + The_MakerGUID = 0; + BroggokGUID = 0; + Kelidan_The_BreakerGUID = 0; + + Door1GUID = 0; + Door2GUID = 0; + Door3GUID = 0; + Door4GUID = 0; + Door5GUID = 0; + Door6GUID = 0; + + PrisonCell1GUID = 0; + PrisonCell2GUID = 0; + PrisonCell3GUID = 0; + PrisonCell4GUID = 0; + PrisonCell5GUID = 0; + PrisonCell6GUID = 0; + PrisonCell7GUID = 0; + PrisonCell8GUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + if (!add) + return; + + switch(pCreature->GetEntry()) + { + case 17381: The_MakerGUID = pCreature->GetGUID(); break; + case 17380: BroggokGUID = pCreature->GetGUID(); break; + case 17377: Kelidan_The_BreakerGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (!add) + return; + + if (pGo->GetEntry() == 181766) //Final exit door + Door1GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181811) //The Maker Front door + Door2GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181812) //The Maker Rear door + Door3GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181822) //Broggok Front door + Door4GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181819) //Broggok Rear door + Door5GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181823) //Kelidan exit door + Door6GUID = pGo->GetGUID(); + + if (pGo->GetEntry() == 181813) //The Maker prison cell front right + PrisonCell1GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181814) //The Maker prison cell back right + PrisonCell2GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181816) //The Maker prison cell front left + PrisonCell3GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181815) //The Maker prison cell back left + PrisonCell4GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181821) //Broggok prison cell front right + PrisonCell5GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181818) //Broggok prison cell back right + PrisonCell6GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181820) //Broggok prison cell front left + PrisonCell7GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181817) //Broggok prison cell back left + PrisonCell8GUID = pGo->GetGUID(); + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THE_MAKER: return The_MakerGUID; + case DATA_BROGGOK: return BroggokGUID; + case DATA_KELIDAN_THE_MAKER: return Kelidan_The_BreakerGUID; + case DATA_DOOR1: return Door1GUID; + case DATA_DOOR2: return Door2GUID; + case DATA_DOOR3: return Door3GUID; + case DATA_DOOR4: return Door4GUID; + case DATA_DOOR5: return Door5GUID; + case DATA_DOOR6: return Door6GUID; + case DATA_PRISON_CELL1: return PrisonCell1GUID; + case DATA_PRISON_CELL2: return PrisonCell2GUID; + case DATA_PRISON_CELL3: return PrisonCell3GUID; + case DATA_PRISON_CELL4: return PrisonCell4GUID; + case DATA_PRISON_CELL5: return PrisonCell5GUID; + case DATA_PRISON_CELL6: return PrisonCell6GUID; + case DATA_PRISON_CELL7: return PrisonCell7GUID; + case DATA_PRISON_CELL8: return PrisonCell8GUID; + } + + return 0; + } + + void SetData(uint32 /*type*/, uint32 data) + { + switch(data) + { + case TYPE_THE_MAKER_EVENT: m_auiEncounter[0] = data; break; + case TYPE_BROGGOK_EVENT: m_auiEncounter[1] = data; break; + case TYPE_KELIDAN_THE_BREAKER_EVENT: m_auiEncounter[2] = data; break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_THE_MAKER_EVENT: return m_auiEncounter[0]; + case TYPE_BROGGOK_EVENT: return m_auiEncounter[1]; + case TYPE_KELIDAN_THE_BREAKER_EVENT: return m_auiEncounter[2]; + } + + return 0; + } + + const char* Save() + { + return str_data.c_str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS || m_auiEncounter[i] == FAIL) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_blood_furnace(Map* pMap) +{ + return new instance_blood_furnace(pMap); +} + +void AddSC_instance_blood_furnace() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blood_furnace"; + newscript->GetInstanceData = &GetInstanceData_instance_blood_furnace; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp new file mode 100644 index 00000000000..d6c0b2fd401 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Omar_The_Unscarred +SD%Complete: 90 +SDComment: Temporary solution for orbital/shadow whip-ability. Needs more core support before making it more proper. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1543009 +#define SAY_AGGRO_2 -1543010 +#define SAY_AGGRO_3 -1543011 +#define SAY_SUMMON -1543012 +#define SAY_CURSE -1543013 +#define SAY_KILL_1 -1543014 +#define SAY_DIE -1543015 +#define SAY_WIPE -1543016 + +#define SPELL_ORBITAL_STRIKE 30637 +#define SPELL_SHADOW_WHIP 30638 +#define SPELL_TREACHEROUS_AURA 30695 +#define H_SPELL_BANE_OF_TREACHERY 37566 +#define SPELL_DEMONIC_SHIELD 31901 +#define SPELL_SHADOW_BOLT 30686 +#define H_SPELL_SHADOW_BOLT 39297 +#define SPELL_SUMMON_FIENDISH_HOUND 30707 + +struct boss_omor_the_unscarredAI : public ScriptedAI +{ + boss_omor_the_unscarredAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 OrbitalStrike_Timer; + uint32 ShadowWhip_Timer; + uint32 Aura_Timer; + uint32 DemonicShield_Timer; + uint32 Shadowbolt_Timer; + uint32 Summon_Timer; + uint32 SummonedCount; + uint64 PlayerGUID; + bool CanPullBack; + + void Reset() + { + DoScriptText(SAY_WIPE, me); + + OrbitalStrike_Timer = 25000; + ShadowWhip_Timer = 2000; + Aura_Timer = 10000; + DemonicShield_Timer = 1000; + Shadowbolt_Timer = 2000; + Summon_Timer = 10000; + SummonedCount = 0; + PlayerGUID = 0; + CanPullBack = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(SAY_KILL_1, me); + } + + void JustSummoned(Creature* summoned) + { + DoScriptText(SAY_SUMMON, me); + + if (Unit* random = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(random); + + ++SummonedCount; + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //only two may be wrong, perhaps increase timer and spawn periodically instead. + if (SummonedCount < 2) + { + if (Summon_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUMMON_FIENDISH_HOUND); + Summon_Timer = 15000+rand()%15000; + } else Summon_Timer -= diff; + } + + if (CanPullBack) + { + if (ShadowWhip_Timer <= diff) + { + if (Player* temp = Unit::GetPlayer(PlayerGUID)) + { + //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) + if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) + { + me->InterruptNonMeleeSpells(false); + DoCast(temp, SPELL_SHADOW_WHIP); + } + } + PlayerGUID = 0; + ShadowWhip_Timer = 2000; + CanPullBack = false; + } else ShadowWhip_Timer -= diff; + } + else if (OrbitalStrike_Timer <= diff) + { + Unit* temp = NULL; + if (me->IsWithinMeleeRange(me->getVictim())) + temp = me->getVictim(); + else temp = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (temp && temp->GetTypeId() == TYPEID_PLAYER) + { + DoCast(temp, SPELL_ORBITAL_STRIKE); + OrbitalStrike_Timer = 14000+rand()%2000; + PlayerGUID = temp->GetGUID(); + + if (PlayerGUID) + CanPullBack = true; + } + } else OrbitalStrike_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) + { + if (DemonicShield_Timer <= diff) + { + DoCast(me, SPELL_DEMONIC_SHIELD); + DemonicShield_Timer = 15000; + } else DemonicShield_Timer -= diff; + } + + if (Aura_Timer <= diff) + { + DoScriptText(SAY_CURSE, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_TREACHEROUS_AURA); + Aura_Timer = 8000+rand()%8000; + } + } else Aura_Timer -= diff; + + if (Shadowbolt_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget) + pTarget = me->getVictim(); + + DoCast(pTarget, SPELL_SHADOW_BOLT); + Shadowbolt_Timer = 4000+rand()%2500; + } + } else Shadowbolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_omor_the_unscarredAI(Creature* pCreature) +{ + return new boss_omor_the_unscarredAI (pCreature); +} + +void AddSC_boss_omor_the_unscarred() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_omor_the_unscarred"; + newscript->GetAI = &GetAI_boss_omor_the_unscarredAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp new file mode 100644 index 00000000000..181911f77a4 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp @@ -0,0 +1,467 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +Name: Boss_Vazruden_the_Herald +%Complete: 90 +Comment: +Category: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FIREBALL DUNGEON_MODE(34653, 36920) +#define SPELL_CONE_OF_FIRE DUNGEON_MODE(30926, 36921) +#define SPELL_SUMMON_LIQUID_FIRE DUNGEON_MODE(23971, 30928) +#define SPELL_BELLOWING_ROAR 39427 +#define SPELL_REVENGE DUNGEON_MODE(19130, 40392) +#define SPELL_KIDNEY_SHOT 30621 +#define SPELL_FIRE_NOVA_VISUAL 19823 + +#define ENTRY_HELLFIRE_SENTRY 17517 +#define ENTRY_VAZRUDEN_HERALD 17307 +#define ENTRY_VAZRUDEN 17537 +#define ENTRY_NAZAN 17536 +#define ENTRY_LIQUID_FIRE 22515 +#define ENTRY_REINFORCED_FEL_IRON_CHEST DUNGEON_MODE(185168, 185169) + +#define SAY_INTRO -1543017 +#define SAY_WIPE -1543018 +#define SAY_AGGRO_1 -1543019 +#define SAY_AGGRO_2 -1543020 +#define SAY_AGGRO_3 -1543021 +#define SAY_KILL_1 -1543022 +#define SAY_KILL_2 -1543023 +#define SAY_DIE -1543024 +#define EMOTE -1543025 + +#define PATH_ENTRY 2081 + +const float VazrudenMiddle[3] = {-1406.5, 1746.5, 81.2}; +const float VazrudenRing[2][3] = +{ + {-1430, 1705, 112}, + {-1377, 1760, 112} +}; + +struct boss_nazanAI : public ScriptedAI +{ + boss_nazanAI(Creature *c) : ScriptedAI(c) + { + VazrudenGUID = 0; + flight = true; + } + + uint32 Fireball_Timer; + uint32 ConeOfFire_Timer; + uint32 BellowingRoar_Timer; + uint32 Fly_Timer; + uint32 Turn_Timer; + uint32 UnsummonCheck; + bool flight; + uint64 VazrudenGUID; + SpellEntry *liquid_fire; + + void Reset() + { + Fireball_Timer = 4000; + Fly_Timer = 45000; + Turn_Timer = 0; + UnsummonCheck = 5000; + } + + void EnterCombat(Unit* /*who*/) {} + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == ENTRY_LIQUID_FIRE) + { + summoned->SetLevel(me->getLevel()); + summoned->setFaction(me->getFaction()); + summoned->CastSpell(summoned,SPELL_SUMMON_LIQUID_FIRE,true); + summoned->CastSpell(summoned,SPELL_FIRE_NOVA_VISUAL,true); + } + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry* entry) + { + if (pTarget && entry->Id == uint32(SPELL_FIREBALL)) + me->SummonCreature(ENTRY_LIQUID_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),pTarget->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,30000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (UnsummonCheck < diff && me->isAlive()) + me->DisappearAndDie(); + else + UnsummonCheck -= diff; + return; + } + + if (Fireball_Timer <= diff) + { + if (Unit *victim = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(victim, SPELL_FIREBALL, true); + Fireball_Timer = urand(4000,7000); + } else Fireball_Timer -= diff; + + if (flight) // phase 1 - the flight + { + Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); + if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) + { + flight = false; + BellowingRoar_Timer = 6000; + ConeOfFire_Timer = 12000; + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->Clear(); + if (Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) + me->AI()->AttackStart(victim); + DoStartMovement(me->getVictim()); + DoScriptText(EMOTE, me); + return; + } else Fly_Timer -= diff; + + if (Turn_Timer <= diff) + { + uint32 waypoint = (Fly_Timer/10000)%2; + if (me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) + me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); + Turn_Timer = 10000; + } else Turn_Timer -= diff; + } + else // phase 2 - land fight + { + if (ConeOfFire_Timer <= diff) + { + DoCast(me, SPELL_CONE_OF_FIRE); + ConeOfFire_Timer = 12000; + Fireball_Timer = 4000; + } else ConeOfFire_Timer -= diff; + + if (IsHeroic()) + if (BellowingRoar_Timer <= diff) + { + DoCast(me, SPELL_BELLOWING_ROAR); + BellowingRoar_Timer = 45000; + } else BellowingRoar_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +struct boss_vazrudenAI : public ScriptedAI +{ + boss_vazrudenAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Revenge_Timer; + bool WipeSaid; + uint32 UnsummonCheck; + + void Reset() + { + Revenge_Timer = 4000; + UnsummonCheck = 2000; + WipeSaid = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void KilledUnit(Unit* who) + { + if (who && who->GetEntry() != ENTRY_VAZRUDEN) + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* who) + { + if (who && who != me) + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (UnsummonCheck < diff && me->isAlive()) + { + if (!WipeSaid) + { + DoScriptText(SAY_WIPE, me); + WipeSaid = true; + } + me->DisappearAndDie(); + } else UnsummonCheck -= diff; + return; + } + + if (Revenge_Timer <= diff) + { + if (Unit *victim = me->getVictim()) + DoCast(victim, SPELL_REVENGE); + Revenge_Timer = 5000; + } else Revenge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_vazruden_the_heraldAI : public ScriptedAI +{ + boss_vazruden_the_heraldAI(Creature *c) : ScriptedAI(c) + { + summoned = false; + sentryDown = false; + NazanGUID = 0; + VazrudenGUID = 0; + } + + uint32 phase; + uint32 waypoint; + uint32 check; + bool sentryDown; + uint64 NazanGUID; + uint64 VazrudenGUID; + bool summoned; + + void Reset() + { + phase = 0; + waypoint = 0; + check = 0; + UnsummonAdds(); + me->GetMotionMaster()->MovePath(PATH_ENTRY, true); + } + + void UnsummonAdds() + { + if (summoned) + { + Creature *Nazan = Unit::GetCreature(*me, NazanGUID); + if (!Nazan) + Nazan = me->FindNearestCreature(ENTRY_NAZAN, 5000); + if (Nazan) + { + Nazan->DisappearAndDie(); + NazanGUID = 0; + } + + Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); + if (!Vazruden) + Vazruden = me->FindNearestCreature(ENTRY_VAZRUDEN, 5000); + if (Vazruden) + { + Vazruden->DisappearAndDie(); + VazrudenGUID = 0; + } + summoned = false; + me->clearUnitState(UNIT_STAT_ROOT); + me->SetVisibility(VISIBILITY_ON); + } + } + + void SummonAdds() + { + if (!summoned) + { + if (Creature* Vazruden = me->SummonCreature(ENTRY_VAZRUDEN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) + VazrudenGUID = Vazruden->GetGUID(); + if (Creature* Nazan = me->SummonCreature(ENTRY_NAZAN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) + NazanGUID = Nazan->GetGUID(); + summoned = true; + me->SetVisibility(VISIBILITY_OFF); + me->addUnitState(UNIT_STAT_ROOT); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (phase == 0) + { + phase = 1; + check = 0; + DoScriptText(SAY_INTRO, me); + } + } + + void JustSummoned(Creature *summoned) + { + if (!summoned) return; + Unit *victim = me->getVictim(); + if (summoned->GetEntry() == ENTRY_NAZAN) + { + CAST_AI(boss_nazanAI, summoned->AI())->VazrudenGUID = VazrudenGUID; + summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + summoned->SetSpeed(MOVE_FLIGHT, 2.5); + if (victim) + AttackStartNoMove(victim); + } + else if (victim) + summoned->AI()->AttackStart(victim); + } + + void SentryDownBy(Unit* killer) + { + if (sentryDown) + { + AttackStartNoMove(killer); + sentryDown = false; + } + else + sentryDown = true; + } + + void UpdateAI(const uint32 diff) + { + switch(phase) + { + case 0: // circle around the platform + return; + break; + case 1: // go to the middle and begin the fight + if (check <= diff) + { + if (!me->IsWithinDist3d(VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],5)) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2]); + check = 1000; + } + else + { + SummonAdds(); + phase = 2; + return; + } + } else check -= diff; + break; + default: // adds do the job now + if (check <= diff) + { + Creature *Nazan = Unit::GetCreature(*me, NazanGUID); + Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); + if (Nazan && Nazan->isAlive() || Vazruden && Vazruden->isAlive()) + { + if (Nazan && Nazan->getVictim() || Vazruden && Vazruden->getVictim()) + return; + else + { + UnsummonAdds(); + EnterEvadeMode(); + return; + } + } + else + { + me->SummonGameObject(ENTRY_REINFORCED_FEL_IRON_CHEST,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,0,0,0,0,0); + me->SetLootRecipient(NULL); // don't think this is necessary.. + me->Kill(me); + } + check = 2000; + } else check -= diff; + break; + } + } +}; + +struct mob_hellfire_sentryAI : public ScriptedAI +{ + mob_hellfire_sentryAI(Creature *c) : ScriptedAI(c) {} + + uint32 KidneyShot_Timer; + + void Reset() + { + KidneyShot_Timer = urand(3000,7000); + } + + void EnterCombat(Unit* /*who*/) {} + + void JustDied(Unit* who) + { + if (Creature *herald = me->FindNearestCreature(ENTRY_VAZRUDEN_HERALD,150)) + CAST_AI(boss_vazruden_the_heraldAI, herald->AI())->SentryDownBy(who); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (KidneyShot_Timer <= diff) + { + if (Unit *victim = me->getVictim()) + DoCast(victim, SPELL_KIDNEY_SHOT); + KidneyShot_Timer = 20000; + } else KidneyShot_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vazruden_the_herald(Creature* pCreature) +{ + return new boss_vazruden_the_heraldAI (pCreature); +} + +CreatureAI* GetAI_boss_vazruden(Creature* pCreature) +{ + return new boss_vazrudenAI (pCreature); +} + +CreatureAI* GetAI_boss_nazan(Creature* pCreature) +{ + return new boss_nazanAI (pCreature); +} + +CreatureAI* GetAI_mob_hellfire_sentry(Creature* pCreature) +{ + return new mob_hellfire_sentryAI (pCreature); +} + +void AddSC_boss_vazruden_the_herald() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vazruden_the_herald"; + newscript->GetAI = &GetAI_boss_vazruden_the_herald; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_vazruden"; + newscript->GetAI = &GetAI_boss_vazruden; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_nazan"; + newscript->GetAI = &GetAI_boss_nazan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_hellfire_sentry"; + newscript->GetAI = &GetAI_mob_hellfire_sentry; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp new file mode 100644 index 00000000000..f0e813d3890 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp @@ -0,0 +1,156 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Watchkeeper_Gargolmar +SD%Complete: 80 +SDComment: Missing adds to heal him. Surge should be used on pTarget furthest away, not random. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_TAUNT -1543000 +#define SAY_HEAL -1543001 +#define SAY_SURGE -1543002 +#define SAY_AGGRO_1 -1543003 +#define SAY_AGGRO_2 -1543004 +#define SAY_AGGRO_3 -1543005 +#define SAY_KILL_1 -1543006 +#define SAY_KILL_2 -1543007 +#define SAY_DIE -1543008 + +#define SPELL_MORTAL_WOUND 30641 +#define H_SPELL_MORTAL_WOUND 36814 +#define SPELL_SURGE 34645 +#define SPELL_RETALIATION 22857 + +struct boss_watchkeeper_gargolmarAI : public ScriptedAI +{ + boss_watchkeeper_gargolmarAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Surge_Timer; + uint32 MortalWound_Timer; + uint32 Retaliation_Timer; + + bool HasTaunted; + bool YelledForHeal; + + void Reset() + { + Surge_Timer = 5000; + MortalWound_Timer = 4000; + Retaliation_Timer = 0; + + HasTaunted = false; + YelledForHeal = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void MoveInLineOfSight(Unit* who) + { + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (!HasTaunted && me->IsWithinDistInMap(who, 60.0f)) + { + DoScriptText(SAY_TAUNT, me); + HasTaunted = true; + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (MortalWound_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + MortalWound_Timer = 5000+rand()%8000; + } else MortalWound_Timer -= diff; + + if (Surge_Timer <= diff) + { + DoScriptText(SAY_SURGE, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SURGE); + + Surge_Timer = 5000+rand()%8000; + } else Surge_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) + { + if (Retaliation_Timer <= diff) + { + DoCast(me, SPELL_RETALIATION); + Retaliation_Timer = 30000; + } else Retaliation_Timer -= diff; + } + + if (!YelledForHeal) + { + if ((me->GetHealth()*100) / me->GetMaxHealth() < 40) + { + DoScriptText(SAY_HEAL, me); + YelledForHeal = true; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_watchkeeper_gargolmarAI(Creature* pCreature) +{ + return new boss_watchkeeper_gargolmarAI (pCreature); +} + +void AddSC_boss_watchkeeper_gargolmar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_watchkeeper_gargolmar"; + newscript->GetAI = &GetAI_boss_watchkeeper_gargolmarAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h new file mode 100644 index 00000000000..599aa237774 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h @@ -0,0 +1,16 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_RAMPARTS_H +#define DEF_RAMPARTS_H + +#define MAX_ENCOUNTER 2 + +enum eTypes +{ + TYPE_VAZRUDEN = 1, + TYPE_NAZAN = 2 +}; + +#endif diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp new file mode 100644 index 00000000000..29c58675e9c --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp @@ -0,0 +1,84 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Hellfire_Ramparts +SD%Complete: 50 +SDComment: +SDCategory: Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" +#include "hellfire_ramparts.h" + +struct instance_ramparts : public ScriptedInstance +{ + instance_ramparts(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 m_uiChestNGUID; + uint64 m_uiChestHGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiChestNGUID = 0; + m_uiChestHGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 185168: m_uiChestNGUID = pGo->GetGUID(); break; + case 185169: m_uiChestHGUID = pGo->GetGUID(); break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + debug_log("TSCR: Instance Ramparts: SetData received for type %u with data %u",uiType,uiData); + + switch(uiType) + { + case TYPE_VAZRUDEN: + if (uiData == DONE && m_auiEncounter[1] == DONE) + DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); + m_auiEncounter[0] = uiData; + break; + case TYPE_NAZAN: + if (uiData == DONE && m_auiEncounter[0] == DONE) + DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); + m_auiEncounter[1] = uiData; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_ramparts(Map* pMap) +{ + return new instance_ramparts(pMap); +} + +void AddSC_instance_ramparts() +{ + Script* pNewScript; + pNewScript = new Script; + pNewScript->Name = "instance_ramparts"; + pNewScript->GetInstanceData = &GetInstanceData_instance_ramparts; + pNewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp new file mode 100644 index 00000000000..5fb381f4065 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp @@ -0,0 +1,570 @@ +/* Copyright(C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +*(at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Magtheridon +SD%Complete: 60 +SDComment: In Development +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "magtheridons_lair.h" + +struct Yell +{ + int32 id; +}; + +static Yell RandomTaunt[]= +{ + {-1544000}, + {-1544001}, + {-1544002}, + {-1544003}, + {-1544004}, + {-1544005}, +}; + +#define SAY_FREED -1544006 +#define SAY_AGGRO -1544007 +#define SAY_BANISH -1544008 +#define SAY_CHAMBER_DESTROY -1544009 +#define SAY_PLAYER_KILLED -1544010 +#define SAY_DEATH -1544011 + +#define EMOTE_BERSERK -1544012 +#define EMOTE_BLASTNOVA -1544013 +#define EMOTE_BEGIN -1544014 + +#define MOB_MAGTHERIDON 17257 +#define MOB_ROOM 17516 +#define MOB_CHANNELLER 17256 +#define MOB_ABYSSAL 17454 + +#define SPELL_BLASTNOVA 30616 +#define SPELL_CLEAVE 30619 +#define SPELL_QUAKE_TRIGGER 30657 // must be cast with 30561 as the proc spell +#define SPELL_QUAKE_KNOCKBACK 30571 +#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 +#define SPELL_BLAZE_TRAP 30542 +#define SPELL_DEBRIS_KNOCKDOWN 36449 +#define SPELL_DEBRIS_VISUAL 30632 +#define SPELL_DEBRIS_DAMAGE 30631 // core bug, does not support target 8 +#define SPELL_CAMERA_SHAKE 36455 +#define SPELL_BERSERK 27680 + +#define SPELL_SHADOW_CAGE 30168 +#define SPELL_SHADOW_GRASP 30410 +#define SPELL_SHADOW_GRASP_VISUAL 30166 +#define SPELL_MIND_EXHAUSTION 44032 //Casted by the cubes when channeling ends + +#define SPELL_SHADOW_CAGE_C 30205 +#define SPELL_SHADOW_GRASP_C 30207 + +#define SPELL_SHADOW_BOLT_VOLLEY 30510 +#define SPELL_DARK_MENDING 30528 +#define SPELL_FEAR 30530 //39176 +#define SPELL_BURNING_ABYSSAL 30511 +#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 + +#define SPELL_FIRE_BLAST 37110 + +// count of clickers needed to interrupt blast nova +#define CLICKERS_COUNT 5 + +typedef std::map CubeMap; + +struct mob_abyssalAI : public ScriptedAI +{ + mob_abyssalAI(Creature *c) : ScriptedAI(c) + { + trigger = 0; + Despawn_Timer = 60000; + } + + uint32 FireBlast_Timer; + uint32 Despawn_Timer; + uint32 trigger; + + void Reset() + { + FireBlast_Timer = 6000; + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (trigger == 2 && spell->Id == SPELL_BLAZE_TARGET) + { + DoCast(me, SPELL_BLAZE_TRAP, true); + me->SetVisibility(VISIBILITY_OFF); + Despawn_Timer = 130000; + } + } + + void SetTrigger(uint32 _trigger) + { + trigger = _trigger; + me->SetDisplayId(11686); + if (trigger == 1) //debris + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_DEBRIS_VISUAL, true); + FireBlast_Timer = 5000; + Despawn_Timer = 10000; + } + } + + void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} + void AttackStart(Unit *who) {if (!trigger) ScriptedAI::AttackStart(who);} + void MoveInLineOfSight(Unit *who) {if (!trigger) ScriptedAI::MoveInLineOfSight(who);} + + void UpdateAI(const uint32 diff) + { + if (trigger) + { + if (trigger == 1) + { + if (FireBlast_Timer <= diff) + { + DoCast(me, SPELL_DEBRIS_DAMAGE, true); + trigger = 3; + } else FireBlast_Timer -= diff; + } + return; + } + + if (Despawn_Timer <= diff) + { + me->ForcedDespawn(); + } else Despawn_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (FireBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRE_BLAST); + FireBlast_Timer = 5000+rand()%10000; + } else FireBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_magtheridonAI : public ScriptedAI +{ + boss_magtheridonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + + // target 7, random target with certain entry spell, need core fix + SpellEntry *TempSpell; + TempSpell = GET_SPELL(SPELL_BLAZE_TARGET); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 6) + { + TempSpell->EffectImplicitTargetA[0] = 6; + TempSpell->EffectImplicitTargetB[0] = 0; + } + TempSpell = GET_SPELL(SPELL_QUAKE_TRIGGER); + if (TempSpell && TempSpell->EffectTriggerSpell[0] != SPELL_QUAKE_KNOCKBACK) + { + TempSpell->EffectTriggerSpell[0] = SPELL_QUAKE_KNOCKBACK; + } + } + + CubeMap Cube; + + ScriptedInstance* pInstance; + + uint32 Berserk_Timer; + uint32 Quake_Timer; + uint32 Cleave_Timer; + uint32 BlastNova_Timer; + uint32 Blaze_Timer; + uint32 Debris_Timer; + uint32 RandChat_Timer; + + bool Phase3; + bool NeedCheckCube; + + void Reset() + { + Berserk_Timer = 1320000; + Quake_Timer = 40000; + Debris_Timer = 10000; + Blaze_Timer = 10000+rand()%20000; + BlastNova_Timer = 60000; + Cleave_Timer = 15000; + RandChat_Timer = 90000; + + Phase3 = false; + NeedCheckCube = false; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->addUnitState(UNIT_STAT_STUNNED); + DoCast(me, SPELL_SHADOW_CAGE_C, true); + } + + void JustReachedHome() + { + if (pInstance) + { + pInstance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED); + pInstance->SetData(DATA_COLLAPSE, false); + } + } + + void SetClicker(uint64 cubeGUID, uint64 clickerGUID) + { + // to avoid multiclicks from 1 cube + if (uint64 guid = Cube[cubeGUID]) + DebuffClicker(Unit::GetUnit(*me, guid)); + Cube[cubeGUID] = clickerGUID; + NeedCheckCube = true; + } + + //function to interrupt channeling and debuff clicker with mind exh(used if second person clicks with same cube or after dispeling/ending shadow grasp DoT) + void DebuffClicker(Unit *clicker) + { + if (!clicker || !clicker->isAlive()) + return; + + clicker->RemoveAurasDueToSpell(SPELL_SHADOW_GRASP); // cannot interrupt triggered spells + clicker->InterruptNonMeleeSpells(false); + clicker->CastSpell(clicker, SPELL_MIND_EXHAUSTION, true); + } + + void NeedCheckCubeStatus() + { + uint32 ClickerNum = 0; + // now checking if every clicker has debuff from manticron(it is dispelable atm rev 6110 : S) + // if not - apply mind exhaustion and delete from clicker's list + for (CubeMap::iterator i = Cube.begin(); i != Cube.end(); ++i) + { + Unit *clicker = Unit::GetUnit(*me, (*i).second); + if (!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP)) + { + DebuffClicker(clicker); + (*i).second = 0; + } else ++ClickerNum; + } + + // if 5 clickers from other cubes apply shadow cage + if (ClickerNum >= CLICKERS_COUNT && !me->HasAura(SPELL_SHADOW_CAGE)) + { + DoScriptText(SAY_BANISH, me); + DoCast(me, SPELL_SHADOW_CAGE, true); + } + else if (ClickerNum < CLICKERS_COUNT && me->HasAura(SPELL_SHADOW_CAGE)) + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); + + if (!ClickerNum) NeedCheckCube = false; + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_PLAYER_KILLED, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_MAGTHERIDON_EVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void AttackStart(Unit *who) + { + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS); + DoZoneInCombat(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); + + DoScriptText(SAY_FREED, me); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + { + if (RandChat_Timer <= diff) + { + DoScriptText(RandomTaunt[rand()%6].id, me); + RandChat_Timer = 90000; + } else RandChat_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + if (NeedCheckCube) NeedCheckCubeStatus(); + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + DoScriptText(EMOTE_BERSERK, me); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 10000; + } else Cleave_Timer -= diff; + + if (BlastNova_Timer <= diff) + { + // to avoid earthquake interruption + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + { + DoScriptText(EMOTE_BLASTNOVA, me); + DoCast(me, SPELL_BLASTNOVA); + BlastNova_Timer = 60000; + } + } else BlastNova_Timer -= diff; + + if (Quake_Timer <= diff) + { + // to avoid blastnova interruption + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_QUAKE_TRIGGER, true); + Quake_Timer = 50000; + } + } else Quake_Timer -= diff; + + if (Blaze_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (summon) + { + CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(2); + DoCast(summon, SPELL_BLAZE_TARGET, true); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + Blaze_Timer = 20000 + rand()%20000; + } else Blaze_Timer -= diff; + + if (!Phase3 && me->GetHealth()*10 < me->GetMaxHealth()*3 + && !me->IsNonMeleeSpellCasted(false) // blast nova + && !me->hasUnitState(UNIT_STAT_STUNNED)) // shadow cage and earthquake + { + Phase3 = true; + DoScriptText(SAY_CHAMBER_DESTROY, me); + DoCast(me, SPELL_CAMERA_SHAKE, true); + DoCast(me, SPELL_DEBRIS_KNOCKDOWN, true); + + if (pInstance) + pInstance->SetData(DATA_COLLAPSE, true); + } + + if (Phase3) + { + if (Debris_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (summon) CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(1); + } + Debris_Timer = 10000; + } else Debris_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_hellfire_channelerAI : public ScriptedAI +{ + mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c) + { + pInstance =me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ShadowBoltVolley_Timer; + uint32 DarkMending_Timer; + uint32 Fear_Timer; + uint32 Infernal_Timer; + + uint32 Check_Timer; + + void Reset() + { + ShadowBoltVolley_Timer = 8000 + rand()%2000; + DarkMending_Timer = 10000; + Fear_Timer = 15000 + rand()%5000; + Infernal_Timer = 10000 + rand()%40000; + + Check_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS); + + me->InterruptNonMeleeSpells(false); + DoZoneInCombat(); + } + + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED); + + DoCast(me, SPELL_SHADOW_GRASP_C, false); + } + + void JustSummoned(Creature *summon) + { + summon->AI()->AttackStart(me->getVictim()); + } + + void DamageTaken(Unit*, uint32 &damage) + { + if (damage >= me->GetHealth()) + DoCast(me, SPELL_SOUL_TRANSFER, true); + } + + void JustDied(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); + ShadowBoltVolley_Timer = 10000 + rand()%10000; + } else ShadowBoltVolley_Timer -= diff; + + if (DarkMending_Timer <= diff) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) + DoCast(me, SPELL_DARK_MENDING); + DarkMending_Timer = 10000 +(rand() % 10000); + } else DarkMending_Timer -= diff; + + if (Fear_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_FEAR); + Fear_Timer = 25000 + rand()%15000; + } else Fear_Timer -= diff; + + if (Infernal_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BURNING_ABYSSAL, true); + Infernal_Timer = 30000 + rand()%10000; + } else Infernal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Manticron Cube +bool GOHello_go_Manticron_Cube(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + if (!pInstance) + return true; + if (pInstance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) return true; + Creature *Magtheridon =Unit::GetCreature(*pGo, pInstance->GetData64(DATA_MAGTHERIDON)); + if (!Magtheridon || !Magtheridon->isAlive()) return true; + + // if exhausted or already channeling return + if (pPlayer->HasAura(SPELL_MIND_EXHAUSTION) || pPlayer->HasAura(SPELL_SHADOW_GRASP)) + return true; + + pPlayer->InterruptNonMeleeSpells(false); + pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP, true); + pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP_VISUAL, false); + CAST_AI(boss_magtheridonAI, Magtheridon->AI())->SetClicker(pGo->GetGUID(), pPlayer->GetGUID()); + return true; +} + +CreatureAI* GetAI_boss_magtheridon(Creature* pCreature) +{ + return new boss_magtheridonAI(pCreature); +} + +CreatureAI* GetAI_mob_hellfire_channeler(Creature* pCreature) +{ + return new mob_hellfire_channelerAI(pCreature); +} + +CreatureAI* GetAI_mob_abyssalAI(Creature* pCreature) +{ + return new mob_abyssalAI(pCreature); +} + +void AddSC_boss_magtheridon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magtheridon"; + newscript->GetAI = &GetAI_boss_magtheridon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_hellfire_channeler"; + newscript->GetAI = &GetAI_mob_hellfire_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_manticron_cube"; + newscript->pGOHello = &GOHello_go_Manticron_Cube; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_abyssal"; + newscript->GetAI = &GetAI_mob_abyssalAI; + newscript->RegisterSelf(); + +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp new file mode 100644 index 00000000000..d5b459a1fa1 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp @@ -0,0 +1,254 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Magtheridons_Lair +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "magtheridons_lair.h" + +#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 +#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 + +#define CHAMBER_CENTER_X -15.14 +#define CHAMBER_CENTER_Y 1.8 +#define CHAMBER_CENTER_Z -0.4 + +#define MAX_ENCOUNTER 2 + +#define EMOTE_BONDS_WEAKEN "'s bonds begin to weaken!" + +struct instance_magtheridons_lair : public ScriptedInstance +{ + instance_magtheridons_lair(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + } + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 MagtheridonGUID; + std::set ChannelerGUID; + uint64 DoorGUID; + std::set ColumnGUID; + + uint32 CageTimer; + uint32 RespawnTimer; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + MagtheridonGUID = 0; + ChannelerGUID.clear(); + DoorGUID = 0; + ColumnGUID.clear(); + + CageTimer = 0; + RespawnTimer = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17257: + MagtheridonGUID = pCreature->GetGUID(); + break; + case 17256: + ChannelerGUID.insert(pCreature->GetGUID()); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 181713: + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 0); + break; + case 183847: + DoorGUID = pGo->GetGUID(); + break; + case 184653: // hall + case 184634: // six columns + case 184635: + case 184636: + case 184637: + case 184638: + case 184639: + ColumnGUID.insert(pGo->GetGUID()); + break; + } + } + + uint64 GetData64(uint32 type) + { + switch(type) + { + case DATA_MAGTHERIDON: + return MagtheridonGUID; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAGTHERIDON_EVENT: + m_auiEncounter[0] = data; + if (data == NOT_STARTED) + RespawnTimer = 10000; + if (data != IN_PROGRESS) + HandleGameObject(DoorGUID, true); + break; + case DATA_CHANNELER_EVENT: + switch(data) + { + case NOT_STARTED: // Reset all channelers once one is reset. + if (m_auiEncounter[1] != NOT_STARTED) + { + m_auiEncounter[1] = NOT_STARTED; + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + if (Creature *Channeler = instance->GetCreature(*i)) + { + if (Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); + } + } + CageTimer = 0; + HandleGameObject(DoorGUID, true); + } + break; + case IN_PROGRESS: // Event start. + if (m_auiEncounter[1] != IN_PROGRESS) + { + m_auiEncounter[1] = IN_PROGRESS; + // Let all five channelers aggro. + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + Creature *Channeler = instance->GetCreature(*i); + if (Channeler && Channeler->isAlive()) + Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); + } + // Release Magtheridon after two minutes. + Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); + if (Magtheridon && Magtheridon->isAlive()) + { + Magtheridon->MonsterTextEmote(EMOTE_BONDS_WEAKEN, 0); + CageTimer = 120000; + } + HandleGameObject(DoorGUID, false); + } + break; + case DONE: // Add buff and check if all channelers are dead. + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + Creature *Channeler = instance->GetCreature(*i); + if (Channeler && Channeler->isAlive()) + { + //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); + data = IN_PROGRESS; + break; + } + } + break; + } + m_auiEncounter[1] = data; + break; + case DATA_COLLAPSE: + // true - collapse / false - reset + for (std::set::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) + DoUseDoorOrButton(*i); + break; + default: + break; + } + } + + uint32 GetData(uint32 type) + { + if (type == DATA_MAGTHERIDON_EVENT) + return m_auiEncounter[0]; + return 0; + } + + void Update(uint32 diff) + { + if (CageTimer) + { + if (CageTimer <= diff) + { + Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); + if (Magtheridon && Magtheridon->isAlive()) + { + Magtheridon->clearUnitState(UNIT_STAT_STUNNED); + Magtheridon->AI()->AttackStart(Magtheridon->SelectNearestTarget(999)); + } + CageTimer = 0; + } else CageTimer -= diff; + } + + if (RespawnTimer) + { + if (RespawnTimer <= diff) + { + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + if (Creature *Channeler = instance->GetCreature(*i)) + { + if (Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); + } + } + RespawnTimer = 0; + } else RespawnTimer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_magtheridons_lair(Map* pMap) +{ + return new instance_magtheridons_lair(pMap); +} + +void AddSC_instance_magtheridons_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_magtheridons_lair"; + newscript->GetInstanceData = &GetInstanceData_instance_magtheridons_lair; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h new file mode 100644 index 00000000000..1b3e525fc54 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MAGTHERIDONS_LAIR_H +#define DEF_MAGTHERIDONS_LAIR_H + +#define DATA_MAGTHERIDON_EVENT 1 +#define DATA_MAGTHERIDON 3 +#define DATA_CHANNELER_EVENT 2 +#define DATA_COLLAPSE 6 +#define DATA_CHANNELER 9 +#endif + diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp new file mode 100644 index 00000000000..e3ded52edc9 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp @@ -0,0 +1,396 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grand_Warlock_Nethekurse +SD%Complete: 75 +SDComment: encounter not fully completed. missing part where boss kill minions. +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_grand_warlock_nethekurse +mob_fel_orc_convert +mob_lesser_shadow_fissure +EndContentData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +struct Say +{ + int32 id; +}; + +static Say PeonAttacked[]= +{ + {-1540001}, + {-1540002}, + {-1540003}, + {-1540004}, +}; +static Say PeonDies[]= +{ + {-1540005}, + {-1540006}, + {-1540007}, + {-1540008}, +}; + +#define SAY_INTRO -1540000 +#define SAY_TAUNT_1 -1540009 +#define SAY_TAUNT_2 -1540010 +#define SAY_TAUNT_3 -1540011 +#define SAY_AGGRO_1 -1540012 +#define SAY_AGGRO_2 -1540013 +#define SAY_AGGRO_3 -1540014 +#define SAY_SLAY_1 -1540015 +#define SAY_SLAY_2 -1540016 +#define SAY_DIE -1540017 + +#define SPELL_DEATH_COIL 30500 +#define SPELL_DARK_SPIN 30502 // core bug spell attack caster :D +#define SPELL_SHADOW_FISSURE 30496 // Summon the ShadowFissure NPC + +#define SPELL_SHADOW_CLEAVE 30495 +#define H_SPELL_SHADOW_SLAM 35953 + +#define SPELL_HEMORRHAGE 30478 + +#define SPELL_CONSUMPTION 30497 +#define SPELL_TEMPORARY_VISUAL 39312 // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should + +struct boss_grand_warlock_nethekurseAI : public ScriptedAI +{ + boss_grand_warlock_nethekurseAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool IntroOnce; + bool IsIntroEvent; + bool IsMainEvent; + bool SpinOnce; + //bool HasTaunted; + bool Phase; + + uint32 PeonEngagedCount; + uint32 PeonKilledCount; + + uint32 IntroEvent_Timer; + uint32 DeathCoil_Timer; + uint32 ShadowFissure_Timer; + uint32 Cleave_Timer; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + IsIntroEvent = false; + IntroOnce = false; + IsMainEvent = false; + //HasTaunted = false; + SpinOnce = false; + Phase = false; + + PeonEngagedCount = 0; + PeonKilledCount = 0; + + IntroEvent_Timer = 90000; //how long before getting bored and kills his minions? + DeathCoil_Timer = 20000; + ShadowFissure_Timer = 8000; + Cleave_Timer = 5000; + } + + void DoYellForPeonAggro() + { + if (PeonEngagedCount >= 4) + return; + + DoScriptText(PeonAttacked[PeonEngagedCount].id, me); + ++PeonEngagedCount; + } + + void DoYellForPeonDeath() + { + if (PeonKilledCount >= 4) + return; + + DoScriptText(PeonDies[PeonKilledCount].id, me); + ++PeonKilledCount; + + if (PeonKilledCount == 4) + { + IsIntroEvent = false; + IsMainEvent = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void DoTauntPeons() + { + DoScriptText(RAND(SAY_TAUNT_1,SAY_TAUNT_2,SAY_TAUNT_3), me); + + //TODO: kill the peons first + IsIntroEvent = false; + PeonEngagedCount = 4; + PeonKilledCount = 4; + IsMainEvent = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackStart(Unit* who) + { + if (IsIntroEvent || !IsMainEvent) + return; + + if (me->Attack(who, true)) + { + if (Phase) + DoStartNoMovement(who); + else + DoStartMovement(who); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!IntroOnce && me->IsWithinDistInMap(who, 50.0f)) + { + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(SAY_INTRO, me); + IntroOnce = true; + IsIntroEvent = true; + + if (pInstance) + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + + if (IsIntroEvent || !IsMainEvent) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(16); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //triggered spell of consumption does not properly show it's SpellVisual, wrong spellid? + summoned->CastSpell(summoned,SPELL_TEMPORARY_VISUAL,true); + summoned->CastSpell(summoned,SPELL_CONSUMPTION,false,0,0,me->GetGUID()); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_NETHEKURSE,DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_NETHEKURSE_DOOR), true); + } + + void UpdateAI(const uint32 diff) + { + if (IsIntroEvent) + { + if (!pInstance) + return; + + if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) + { + if (IntroEvent_Timer <= diff) + DoTauntPeons(); + else + IntroEvent_Timer -= diff; + } + } + + if (!UpdateVictim()) + return; + + if (!IsMainEvent) + return; + + if (Phase) + { + if (!SpinOnce) + { + DoCast(me->getVictim(), SPELL_DARK_SPIN); + SpinOnce = true; + } + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_CLEAVE); + Cleave_Timer = 6000+rand()%2500; + } else Cleave_Timer -= diff; + } + else + { + if (ShadowFissure_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_FISSURE); + ShadowFissure_Timer = urand(7500,15000); + } else ShadowFissure_Timer -= diff; + + if (DeathCoil_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_DEATH_COIL); + DeathCoil_Timer = urand(15000,20000); + } else DeathCoil_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) + Phase = true; + + DoMeleeAttackIfReady(); + } + } +}; + +struct mob_fel_orc_convertAI : public ScriptedAI +{ + mob_fel_orc_convertAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 Hemorrhage_Timer; + + void Reset() + { + me->SetNoCallAssistance(true); //we don't want any assistance (WE R HEROZ!) + Hemorrhage_Timer = 3000; + } + + void MoveInLineOfSight(Unit * /*who*/) + { + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + { + if (pInstance->GetData64(DATA_NETHEKURSE)) + { + Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE)); + if (pKurse && me->IsWithinDist(pKurse, 45.0f)) + { + CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonAggro(); + + if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) + return; + else + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + } + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + if (pInstance->GetData(TYPE_NETHEKURSE) != IN_PROGRESS) + return; + if (pInstance->GetData64(DATA_NETHEKURSE)) + if (Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE))) + CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonDeath(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Hemorrhage_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HEMORRHAGE); + Hemorrhage_Timer = 15000; + } else Hemorrhage_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//NOTE: this Creature are also summoned by other spells, for different creatures +struct mob_lesser_shadow_fissureAI : public ScriptedAI +{ + mob_lesser_shadow_fissureAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + void MoveInLineOfSight(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void EnterCombat(Unit* /*who*/) {} +}; + +CreatureAI* GetAI_boss_grand_warlock_nethekurse(Creature* pCreature) +{ + return new boss_grand_warlock_nethekurseAI (pCreature); +} + +CreatureAI* GetAI_mob_fel_orc_convert(Creature* pCreature) +{ + return new mob_fel_orc_convertAI (pCreature); +} + +CreatureAI* GetAI_mob_lesser_shadow_fissure(Creature* pCreature) +{ + return new mob_lesser_shadow_fissureAI (pCreature); +} + +void AddSC_boss_grand_warlock_nethekurse() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_grand_warlock_nethekurse"; + newscript->GetAI = &GetAI_boss_grand_warlock_nethekurse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_orc_convert"; + newscript->GetAI = &GetAI_mob_fel_orc_convert; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lesser_shadow_fissure"; + newscript->GetAI = &GetAI_mob_lesser_shadow_fissure; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp new file mode 100644 index 00000000000..6fa1c9efe33 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp @@ -0,0 +1,404 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warbringer_Omrogg +SD%Complete: 85 +SDComment: Heroic enabled. Spell timing may need additional tweaks +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +mob_omrogg_heads +boss_warbringer_omrogg +EndContentData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +enum eEnums +{ + YELL_DIE_L = -1540039, + YELL_DIE_R = -1540040, + EMOTE_ENRAGE = -1540041, + + SPELL_BLAST_WAVE = 30600, + SPELL_FEAR = 30584, + SPELL_THUNDERCLAP = 30633, + + SPELL_BURNING_MAUL = 30598, + H_SPELL_BURNING_MAUL = 36056, + + NPC_LEFT_HEAD = 19523, + NPC_RIGHT_HEAD = 19524 +}; + +struct Yell +{ + int32 id; + uint32 creature; +}; + +static Yell GoCombat[]= +{ + {-1540018, NPC_LEFT_HEAD}, + {-1540019, NPC_LEFT_HEAD}, + {-1540020, NPC_LEFT_HEAD}, +}; +static Yell GoCombatDelay[]= +{ + {-1540021, NPC_RIGHT_HEAD}, + {-1540022, NPC_RIGHT_HEAD}, + {-1540023, NPC_RIGHT_HEAD}, +}; + +static Yell Threat[]= +{ + {-1540024, NPC_LEFT_HEAD}, + {-1540025, NPC_RIGHT_HEAD}, + {-1540026, NPC_LEFT_HEAD}, + {-1540027, NPC_LEFT_HEAD}, +}; +static Yell ThreatDelay1[]= +{ + {-1540028, NPC_RIGHT_HEAD}, + {-1540029, NPC_LEFT_HEAD}, + {-1540030, NPC_RIGHT_HEAD}, + {-1540031, NPC_RIGHT_HEAD}, +}; +static Yell ThreatDelay2[]= +{ + {-1540032, NPC_LEFT_HEAD}, + {-1540033, NPC_RIGHT_HEAD}, + {-1540034, NPC_LEFT_HEAD}, + {-1540035, NPC_LEFT_HEAD}, +}; + +static Yell Killing[]= +{ + {-1540036, NPC_LEFT_HEAD}, + {-1540037, NPC_RIGHT_HEAD}, +}; +static Yell KillingDelay[]= +{ + {-1540038, NPC_RIGHT_HEAD}, + {-1000000, NPC_LEFT_HEAD}, +}; + +struct mob_omrogg_headsAI : public ScriptedAI +{ + mob_omrogg_headsAI(Creature *c) : ScriptedAI(c) {} + + bool DeathYell; + uint32 Death_Timer; + + void Reset() + { + Death_Timer = 4000; + DeathYell = false; + } + void EnterCombat(Unit* /*who*/) {} + + void DoDeathYell() + { + DeathYell = true; + } + + void UpdateAI(const uint32 diff) + { + if (!DeathYell) + return; + + if (Death_Timer <= diff) + { + DoScriptText(YELL_DIE_R, me); + Death_Timer = false; + me->setDeathState(JUST_DIED); + } else Death_Timer -= diff; + } +}; + +struct boss_warbringer_omroggAI : public ScriptedAI +{ + boss_warbringer_omroggAI(Creature *c) : ScriptedAI(c) + { + LeftHeadGUID = 0; + RightHeadGUID = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 LeftHeadGUID; + uint64 RightHeadGUID; + int iaggro; + int ithreat; + int ikilling; + + bool AggroYell; + bool ThreatYell; + bool ThreatYell2; + bool KillingYell; + + uint32 Delay_Timer; + uint32 BlastWave_Timer; + uint32 BlastCount; + uint32 Fear_Timer; + uint32 BurningMaul_Timer; + uint32 ThunderClap_Timer; + uint32 ResetThreat_Timer; + + void Reset() + { + if (Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) + { + pLeftHead->setDeathState(JUST_DIED); + LeftHeadGUID = 0; + } + + if (Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID)) + { + pRightHead->setDeathState(JUST_DIED); + RightHeadGUID = 0; + } + + AggroYell = false; + ThreatYell = false; + ThreatYell2 = false; + KillingYell = false; + + Delay_Timer = 4000; + BlastWave_Timer = 0; + BlastCount = 0; + Fear_Timer = 8000; + BurningMaul_Timer = 25000; + ThunderClap_Timer = 15000; + ResetThreat_Timer = 30000; + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, NOT_STARTED); //End boss can use this later. O'mrogg must be defeated(DONE) or he will come to aid. + } + + void DoYellForThreat() + { + Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit *pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + ithreat = rand()%4; + + Unit *source = (pLeftHead->GetEntry() == Threat[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(Threat[ithreat].id, source); + + Delay_Timer = 3500; + ThreatYell = true; + } + + void EnterCombat(Unit * /*who*/) + { + me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + + if (Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) + { + iaggro = rand()%3; + + DoScriptText(GoCombat[iaggro].id, pLeftHead); + + Delay_Timer = 3500; + AggroYell = true; + } + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, IN_PROGRESS); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == NPC_LEFT_HEAD) + LeftHeadGUID = summoned->GetGUID(); + + if (summoned->GetEntry() == NPC_RIGHT_HEAD) + RightHeadGUID = summoned->GetGUID(); + + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->SetVisibility(VISIBILITY_OFF); + } + + void KilledUnit(Unit* /*victim*/) + { + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + ikilling = rand()%2; + + Unit *source = (pLeftHead->GetEntry() == Killing[ikilling].creature ? pLeftHead : pRightHead); + + switch(ikilling) + { + case 0: + DoScriptText(Killing[ikilling].id, source); + Delay_Timer = 3500; + KillingYell = true; + break; + case 1: + DoScriptText(Killing[ikilling].id, source); + KillingYell = false; + break; + } + } + + void JustDied(Unit* /*Killer*/) + { + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + DoScriptText(YELL_DIE_L, pLeftHead); + + CAST_AI(mob_omrogg_headsAI, CAST_CRE(pRightHead)->AI())->DoDeathYell(); + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (Delay_Timer <= diff) + { + Delay_Timer = 3500; + + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + if (AggroYell) + { + DoScriptText(GoCombatDelay[iaggro].id, pRightHead); + AggroYell = false; + } + + if (ThreatYell2) + { + Unit *source = (pLeftHead->GetEntry() == ThreatDelay2[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(ThreatDelay2[ithreat].id, source); + ThreatYell2 = false; + } + + if (ThreatYell) + { + Unit *source = (pLeftHead->GetEntry() == ThreatDelay1[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(ThreatDelay1[ithreat].id, source); + ThreatYell = false; + ThreatYell2 = true; + } + + if (KillingYell) + { + Unit *source = (pLeftHead->GetEntry() == KillingDelay[ikilling].creature ? pLeftHead : pRightHead); + + DoScriptText(KillingDelay[ikilling].id, source); + KillingYell = false; + } + } else Delay_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (BlastCount && BlastWave_Timer <= diff) + { + DoCast(me, SPELL_BLAST_WAVE); + BlastWave_Timer = 5000; + ++BlastCount; + + if (BlastCount == 3) + BlastCount = 0; + } else BlastWave_Timer -= diff; + + if (BurningMaul_Timer <= diff) + { + DoScriptText(EMOTE_ENRAGE, me); + DoCast(me, SPELL_BURNING_MAUL); + BurningMaul_Timer = 40000; + BlastWave_Timer = 16000; + BlastCount = 1; + } else BurningMaul_Timer -= diff; + + if (ResetThreat_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoYellForThreat(); + DoResetThreat(); + me->AddThreat(pTarget, 0.0f); + } + ResetThreat_Timer = 25000+rand()%15000; + } else ResetThreat_Timer -= diff; + + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 15000+rand()%20000; + } else Fear_Timer -= diff; + + if (ThunderClap_Timer <= diff) + { + DoCast(me, SPELL_THUNDERCLAP); + ThunderClap_Timer = 15000+rand()%15000; + } else ThunderClap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_warbringer_omrogg(Creature* pCreature) +{ + return new boss_warbringer_omroggAI (pCreature); +} + +CreatureAI* GetAI_mob_omrogg_heads(Creature* pCreature) +{ + return new mob_omrogg_headsAI (pCreature); +} + +void AddSC_boss_warbringer_omrogg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_warbringer_omrogg"; + newscript->GetAI = &GetAI_boss_warbringer_omrogg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_omrogg_heads"; + newscript->GetAI = &GetAI_mob_omrogg_heads; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp new file mode 100644 index 00000000000..b108077518a --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp @@ -0,0 +1,288 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warchief_Kargath_Bladefist +SD%Complete: 90 +SDComment: +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_warchief_kargath_bladefist +EndContentData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO1 -1540042 +#define SAY_AGGRO2 -1540043 +#define SAY_AGGRO3 -1540044 +#define SAY_SLAY1 -1540045 +#define SAY_SLAY2 -1540046 +#define SAY_DEATH -1540047 + +#define SPELL_BLADE_DANCE 30739 +#define H_SPELL_CHARGE 25821 + +#define TARGET_NUM 5 + +#define MOB_SHATTERED_ASSASSIN 17695 +#define MOB_HEARTHEN_GUARD 17621 +#define MOB_SHARPSHOOTER_GUARD 17622 +#define MOB_REAVER_GUARD 17623 + +float AssassEntrance[3] = {275.136,-84.29,2.3}; // y -8 +float AssassExit[3] = {184.233,-84.29,2.3}; // y -8 +float AddsEntrance[3] = {306.036,-84.29,1.93}; + +struct boss_warchief_kargath_bladefistAI : public ScriptedAI +{ + boss_warchief_kargath_bladefistAI(Creature *c) : ScriptedAI(c) + { + } + + std::vector adds; + std::vector assassins; + + uint32 Charge_timer; + uint32 Blade_Dance_Timer; + uint32 Summon_Assistant_Timer; + uint32 resetcheck_timer; + uint32 Wait_Timer; + + uint32 Assassins_Timer; + + uint32 summoned; + bool InBlade; + + uint32 target_num; + + void Reset() + { + removeAdds(); + + me->SetSpeed(MOVE_RUN,2); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + summoned = 2; + InBlade = false; + Wait_Timer = 0; + + Charge_timer = 0; + Blade_Dance_Timer = 45000; + Summon_Assistant_Timer = 30000; + Assassins_Timer = 5000; + resetcheck_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void JustSummoned(Creature *summoned) + { + switch(summoned->GetEntry()) + { + case MOB_HEARTHEN_GUARD: + case MOB_SHARPSHOOTER_GUARD: + case MOB_REAVER_GUARD: + summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0)); + adds.push_back(summoned->GetGUID()); + break; + case MOB_SHATTERED_ASSASSIN: + assassins.push_back(summoned->GetGUID()); + break; + } + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + removeAdds(); + } + + void MovementInform(uint32 type, uint32 id) + { + if (InBlade) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id != 1) + return; + + if (target_num > 0) // to prevent loops + { + Wait_Timer = 1; + DoCast(me, SPELL_BLADE_DANCE, true); + target_num--; + } + } + } + + void removeAdds() + { + for (std::vector::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) + { + Unit* temp = Unit::GetUnit((*me),*itr); + if (temp && temp->isAlive()) + { + (*temp).GetMotionMaster()->Clear(true); + me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CAST_CRE(temp)->RemoveCorpse(); + } + } + adds.clear(); + + for (std::vector::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) + { + Unit* temp = Unit::GetUnit((*me),*itr); + if (temp && temp->isAlive()) + { + (*temp).GetMotionMaster()->Clear(true); + me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CAST_CRE(temp)->RemoveCorpse(); + } + } + assassins.clear(); + } + void SpawnAssassin() + { + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]+8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]-8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]+8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]-8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Assassins_Timer) + if (Assassins_Timer <= diff) + { + SpawnAssassin(); + Assassins_Timer = 0; + } else Assassins_Timer -= diff; + + if (InBlade) + { + if (Wait_Timer) + if (Wait_Timer <= diff) + { + if (target_num <= 0) + { + // stop bladedance + InBlade = false; + me->SetSpeed(MOVE_RUN,2); + me->GetMotionMaster()->MoveChase(me->getVictim()); + Blade_Dance_Timer = 30000; + Wait_Timer = 0; + if (IsHeroic()) + Charge_timer = 5000; + } + else + { + //move in bladedance + float x,y,randx,randy; + randx = (rand()%40); + randy = (rand()%40); + x = 210+ randx ; + y = -60- randy ; + me->GetMotionMaster()->MovePoint(1,x,y,me->GetPositionZ()); + Wait_Timer = 0; + } + } else Wait_Timer -= diff; + } + else + { + if (Blade_Dance_Timer) + if (Blade_Dance_Timer <= diff) + { + target_num = TARGET_NUM; + Wait_Timer = 1; + InBlade = true; + Blade_Dance_Timer = 0; + me->SetSpeed(MOVE_RUN,4); + return; + } else Blade_Dance_Timer -= diff; + + if (Charge_timer) + if (Charge_timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), H_SPELL_CHARGE); + Charge_timer = 0; + } else Charge_timer -= diff; + + if (Summon_Assistant_Timer <= diff) + { + for (uint8 i = 0; i < summoned; ++i) + { + switch (urand(0,2)) + { + case 0: me->SummonCreature(MOB_HEARTHEN_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + case 1: me->SummonCreature(MOB_SHARPSHOOTER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + case 2: me->SummonCreature(MOB_REAVER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + } + } + if (urand(0,9) < 2) + ++summoned; + Summon_Assistant_Timer = urand(25000,35000); + } else Summon_Assistant_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + if (resetcheck_timer <= diff) + { + uint32 tempx,tempy; + tempx = uint32(me->GetPositionX()); + tempy = uint32(me->GetPositionY()); + if (tempx > 255 || tempx < 205) + { + EnterEvadeMode(); + return; + } + resetcheck_timer = 5000; + } else resetcheck_timer -= diff; + } +}; + +CreatureAI* GetAI_boss_warchief_kargath_bladefist(Creature* pCreature) +{ + return new boss_warchief_kargath_bladefistAI (pCreature); +} + +void AddSC_boss_warchief_kargath_bladefist() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_warchief_kargath_bladefist"; + newscript->GetAI = &GetAI_boss_warchief_kargath_bladefist; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp new file mode 100644 index 00000000000..c29df4d6411 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shattered_Halls +SD%Complete: 50 +SDComment: currently missing info about door. instance not complete +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +#define MAX_ENCOUNTER 2 + +#define DOOR_NETHEKURSE 1 + +struct instance_shattered_halls : public ScriptedInstance +{ + instance_shattered_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 nethekurseGUID; + uint64 nethekurseDoorGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + nethekurseGUID = 0; + nethekurseDoorGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case DOOR_NETHEKURSE: nethekurseDoorGUID = pGo->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 16807: nethekurseGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_NETHEKURSE: + m_auiEncounter[0] = data; + break; + case TYPE_OMROGG: + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_NETHEKURSE: + return m_auiEncounter[0]; + case TYPE_OMROGG: + return m_auiEncounter[1]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_NETHEKURSE: + return nethekurseGUID; + case DATA_NETHEKURSE_DOOR: + return nethekurseDoorGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_shattered_halls(Map* pMap) +{ + return new instance_shattered_halls(pMap); +} + +void AddSC_instance_shattered_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shattered_halls"; + newscript->GetInstanceData = &GetInstanceData_instance_shattered_halls; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h new file mode 100644 index 00000000000..cbfa23ec4e0 --- /dev/null +++ b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHATTERED_H +#define DEF_SHATTERED_H + +#define TYPE_NETHEKURSE 1 +#define DATA_NETHEKURSE 2 +#define DATA_NETHEKURSE_DOOR 3 + +#define TYPE_OMROGG 4 +#endif + diff --git a/src/server/scripts/Outland/hellfire_peninsula.cpp b/src/server/scripts/Outland/hellfire_peninsula.cpp new file mode 100644 index 00000000000..fce8ac6f59e --- /dev/null +++ b/src/server/scripts/Outland/hellfire_peninsula.cpp @@ -0,0 +1,522 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Hellfire_Peninsula +SD%Complete: 100 +SDComment: Quest support: 9375, 9410, 9418, 10129, 10146, 10162, 10163, 10340, 10346, 10347, 10382 (Special flight paths) +SDCategory: Hellfire Peninsula +EndScriptData */ + +/* ContentData +npc_aeranas +npc_ancestral_wolf +go_haaleshi_altar +npc_naladu +npc_tracy_proudwell +npc_trollbane +npc_wounded_blood_elf +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_aeranas +######*/ + +enum eAeranas +{ + SAY_SUMMON = -1000138, + SAY_FREE = -1000139, + + FACTION_HOSTILE = 16, + FACTION_FRIENDLY = 35, + + SPELL_ENVELOPING_WINDS = 15535, + SPELL_SHOCK = 12553, + + C_AERANAS = 17085 +}; + +struct npc_aeranasAI : public ScriptedAI +{ + npc_aeranasAI(Creature* c) : ScriptedAI(c) {} + + uint32 Faction_Timer; + uint32 EnvelopingWinds_Timer; + uint32 Shock_Timer; + + void Reset() + { + Faction_Timer = 8000; + EnvelopingWinds_Timer = 9000; + Shock_Timer = 5000; + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + me->setFaction(FACTION_FRIENDLY); + + DoScriptText(SAY_SUMMON, me); + } + + void UpdateAI(const uint32 diff) + { + if (Faction_Timer) + { + if (Faction_Timer <= diff) + { + me->setFaction(FACTION_HOSTILE); + Faction_Timer = 0; + } else Faction_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 30) + { + me->setFaction(FACTION_FRIENDLY); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + DoScriptText(SAY_FREE, me); + return; + } + + if (Shock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHOCK); + Shock_Timer = 10000; + } else Shock_Timer -= diff; + + if (EnvelopingWinds_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ENVELOPING_WINDS); + EnvelopingWinds_Timer = 25000; + } else EnvelopingWinds_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_aeranas(Creature* pCreature) +{ + return new npc_aeranasAI (pCreature); +} + +/*###### +## npc_ancestral_wolf +######*/ + +enum eAncestralWolf +{ + EMOTE_WOLF_LIFT_HEAD = -1000496, + EMOTE_WOLF_HOWL = -1000497, + SAY_WOLF_WELCOME = -1000498, + + SPELL_ANCESTRAL_WOLF_BUFF = 29981, + + NPC_RYGA = 17123 +}; + +struct npc_ancestral_wolfAI : public npc_escortAI +{ + npc_ancestral_wolfAI(Creature* pCreature) : npc_escortAI(pCreature) + { + if (pCreature->GetOwner() && pCreature->GetOwner()->GetTypeId() == TYPEID_PLAYER) + Start(false, false, pCreature->GetOwner()->GetGUID()); + else + error_log("TRINITY: npc_ancestral_wolf can not obtain owner or owner is not a player."); + + pCreature->SetSpeed(MOVE_WALK, 1.5f); + Reset(); + } + + Unit* pRyga; + + void Reset() + { + pRyga = NULL; + DoCast(me, SPELL_ANCESTRAL_WOLF_BUFF, true); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pRyga && pWho->GetTypeId() == TYPEID_UNIT && pWho->GetEntry() == NPC_RYGA && me->IsWithinDistInMap(pWho, 15.0f)) + pRyga = pWho; + + npc_escortAI::MoveInLineOfSight(pWho); + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 0: + DoScriptText(EMOTE_WOLF_LIFT_HEAD, me); + break; + case 2: + DoScriptText(EMOTE_WOLF_HOWL, me); + break; + case 50: + if (pRyga && pRyga->isAlive() && !pRyga->isInCombat()) + DoScriptText(SAY_WOLF_WELCOME, pRyga); + break; + } + } +}; + +CreatureAI* GetAI_npc_ancestral_wolf(Creature* pCreature) +{ + return new npc_ancestral_wolfAI(pCreature); +} + +/*###### +## go_haaleshi_altar +######*/ + +bool GOHello_go_haaleshi_altar(Player* /*pPlayer*/, GameObject* pGo) +{ + pGo->SummonCreature(C_AERANAS,-1321.79, 4043.80, 116.24, 1.25, TEMPSUMMON_TIMED_DESPAWN, 180000); + return false; +} + +/*###### +## npc_naladu +######*/ + +#define GOSSIP_NALADU_ITEM1 "Why don't you escape?" + +enum eNaladu +{ + GOSSIP_TEXTID_NALADU1 = 9788 +}; + +bool GossipHello_npc_naladu(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_NALADU_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_naladu(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_NALADU1, pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_tracy_proudwell +######*/ + +#define GOSSIP_TEXT_REDEEM_MARKS "I have marks to redeem!" +#define GOSSIP_TRACY_PROUDWELL_ITEM1 "I heard that your dog Fei Fei took Klatu's prayer beads..." +#define GOSSIP_TRACY_PROUDWELL_ITEM2 "" + +enum eTracy +{ + GOSSIP_TEXTID_TRACY_PROUDWELL1 = 10689, + QUEST_DIGGING_FOR_PRAYER_BEADS = 10916 +}; + +bool GossipHello_npc_tracy_proudwell(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_REDEEM_MARKS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (pPlayer->GetQuestStatus(QUEST_DIGGING_FOR_PRAYER_BEADS) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TRACY_PROUDWELL_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_tracy_proudwell(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TRACY_PROUDWELL_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TRACY_PROUDWELL1, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + } + + return true; +} + +/*###### +## npc_trollbane +######*/ + +#define GOSSIP_TROLLBANE_ITEM1 "Tell me of the Sons of Lothar." +#define GOSSIP_TROLLBANE_ITEM2 "" +#define GOSSIP_TROLLBANE_ITEM3 "Tell me of your homeland." + +enum eTrollbane +{ + GOSSIP_TEXTID_TROLLBANE1 = 9932, + GOSSIP_TEXTID_TROLLBANE2 = 9933, + GOSSIP_TEXTID_TROLLBANE3 = 8772 +}; + +bool GossipHello_npc_trollbane(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TROLLBANE_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TROLLBANE_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_trollbane(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TROLLBANE_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TROLLBANE1, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TROLLBANE2, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TROLLBANE3, pCreature->GetGUID()); + break; + } + + return true; +} + +/*###### +## npc_wounded_blood_elf +######*/ + +enum eWoundedBloodElf +{ + SAY_ELF_START = -1000117, + SAY_ELF_SUMMON1 = -1000118, + SAY_ELF_RESTING = -1000119, + SAY_ELF_SUMMON2 = -1000120, + SAY_ELF_COMPLETE = -1000121, + SAY_ELF_AGGRO = -1000122, + + QUEST_ROAD_TO_FALCON_WATCH = 9375 +}; + +struct npc_wounded_blood_elfAI : public npc_escortAI +{ + npc_wounded_blood_elfAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch (i) + { + case 0: + DoScriptText(SAY_ELF_START, me, pPlayer); + break; + case 9: + DoScriptText(SAY_ELF_SUMMON1, me, pPlayer); + // Spawn two Haal'eshi Talonguard + DoSpawnCreature(16967, -15, -15, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + DoSpawnCreature(16967, -17, -17, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 13: + DoScriptText(SAY_ELF_RESTING, me, pPlayer); + break; + case 14: + DoScriptText(SAY_ELF_SUMMON2, me, pPlayer); + // Spawn two Haal'eshi Windwalker + DoSpawnCreature(16966, -15, -15, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + DoSpawnCreature(16966, -17, -17, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 27: + DoScriptText(SAY_ELF_COMPLETE, me, pPlayer); + // Award quest credit + pPlayer->GroupEventHappens(QUEST_ROAD_TO_FALCON_WATCH,me); + break; + } + } + + void Reset() { } + + void EnterCombat(Unit* /*who*/) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + DoScriptText(SAY_ELF_AGGRO, me); + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } +}; + +CreatureAI* GetAI_npc_wounded_blood_elf(Creature* pCreature) +{ + return new npc_wounded_blood_elfAI(pCreature); +} + +bool QuestAccept_npc_wounded_blood_elf(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_ROAD_TO_FALCON_WATCH) + { + if (npc_escortAI* pEscortAI = CAST_AI(npc_wounded_blood_elfAI, pCreature->AI())) + pEscortAI->Start(true, false, pPlayer->GetGUID()); + + // Change faction so mobs attack + pCreature->setFaction(775); + } + + return true; +} + +/*###### +## npc_fel_guard_hound +######*/ + +enum eFelGuard +{ + SPELL_SUMMON_POO = 37688, + + NPC_DERANGED_HELBOAR = 16863 +}; + +struct npc_fel_guard_houndAI : public ScriptedAI +{ + npc_fel_guard_houndAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiCheckTimer; + uint64 uiHelboarGUID; + + void Reset() + { + uiCheckTimer = 5000; //check for creature every 5 sec + uiHelboarGUID = 0; + } + + void MovementInform(uint32 uiType, uint32 uiId) + { + if (uiType != POINT_MOTION_TYPE || uiId != 1) + return; + + if (Creature* pHelboar = me->GetCreature(*me,uiHelboarGUID)) + { + pHelboar->RemoveCorpse(); + DoCast(SPELL_SUMMON_POO); + + if (Player* pOwner = me->GetCharmerOrOwnerPlayerOrPlayerItself()) + me->GetMotionMaster()->MoveFollow(pOwner,0.0f,0.0f); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiCheckTimer <= uiDiff) + { + if (Creature* pHelboar = me->FindNearestCreature(NPC_DERANGED_HELBOAR, 10.0f, false)) + { + if (pHelboar->GetGUID() != uiHelboarGUID && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE && !me->FindCurrentSpellBySpellId(SPELL_SUMMON_POO)) + { + uiHelboarGUID = pHelboar->GetGUID(); + me->GetMotionMaster()->MovePoint(1,pHelboar->GetPositionX(),pHelboar->GetPositionY(),pHelboar->GetPositionZ()); + } + } + uiCheckTimer = 5000; + }else uiCheckTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_fel_guard_hound(Creature* pCreature) +{ + return new npc_fel_guard_houndAI(pCreature); +} + +void AddSC_hellfire_peninsula() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_aeranas"; + newscript->GetAI = &GetAI_npc_aeranas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ancestral_wolf"; + newscript->GetAI = &GetAI_npc_ancestral_wolf; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_haaleshi_altar"; + newscript->pGOHello = &GOHello_go_haaleshi_altar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_naladu"; + newscript->pGossipHello = &GossipHello_npc_naladu; + newscript->pGossipSelect = &GossipSelect_npc_naladu; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tracy_proudwell"; + newscript->pGossipHello = &GossipHello_npc_tracy_proudwell; + newscript->pGossipSelect = &GossipSelect_npc_tracy_proudwell; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_trollbane"; + newscript->pGossipHello = &GossipHello_npc_trollbane; + newscript->pGossipSelect = &GossipSelect_npc_trollbane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_wounded_blood_elf"; + newscript->GetAI = &GetAI_npc_wounded_blood_elf; + newscript->pQuestAccept = &QuestAccept_npc_wounded_blood_elf; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="npc_fel_guard_hound"; + newscript->GetAI = &GetAI_npc_fel_guard_hound; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/nagrand.cpp b/src/server/scripts/Outland/nagrand.cpp new file mode 100644 index 00000000000..700ba2cc120 --- /dev/null +++ b/src/server/scripts/Outland/nagrand.cpp @@ -0,0 +1,886 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Nagrand +SD%Complete: 90 +SDComment: Quest support: 9849, 9868, 9918, 9874, 9991, 10107, 10108, 10044, 10172, 10646, 10085, 10987. TextId's unknown for altruis_the_sufferer and greatmother_geyah (npc_text) +SDCategory: Nagrand +EndScriptData */ + +/* ContentData +mob_shattered_rumbler +mob_lump +mob_sunspring_villager +npc_altruis_the_sufferer +npc_greatmother_geyah +npc_lantresor_of_the_blade +npc_maghar_captive +npc_creditmarker_visit_with_ancestors +mob_sparrowhawk +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## mob_shattered_rumbler - this should be done with ACID +######*/ + +struct mob_shattered_rumblerAI : public ScriptedAI +{ + bool Spawn; + + mob_shattered_rumblerAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + Spawn = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) + { + if (Spellkind->Id == 32001 && !Spawn) + { + float x = me->GetPositionX(); + float y = me->GetPositionY(); + float z = me->GetPositionZ(); + + Hitter->SummonCreature(18181,x+(0.7 * (rand()%30)),y+(rand()%5),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + Hitter->SummonCreature(18181,x+(rand()%5),y-(rand()%5),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + Hitter->SummonCreature(18181,x-(rand()%5),y+(0.5 *(rand()%60)),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + me->setDeathState(CORPSE); + Spawn = true; + } + return; + } +}; +CreatureAI* GetAI_mob_shattered_rumbler(Creature* pCreature) +{ + return new mob_shattered_rumblerAI (pCreature); +} + +/*###### +## mob_lump +######*/ + +#define SPELL_VISUAL_SLEEP 16093 +#define SPELL_SPEAR_THROW 32248 + +#define LUMP_SAY0 -1000190 +#define LUMP_SAY1 -1000191 + +#define LUMP_DEFEAT -1000192 + +#define GOSSIP_HL "I need answers, ogre!" +#define GOSSIP_SL1 "Why are Boulderfist out this far? You know that this is Kurenai territory." +#define GOSSIP_SL2 "And you think you can just eat anything you want? You're obviously trying to eat the Broken of Telaar." +#define GOSSIP_SL3 "This means war, Lump! War I say!" + +struct mob_lumpAI : public ScriptedAI +{ + mob_lumpAI(Creature *c) : ScriptedAI(c) + { + bReset = false; + } + + uint32 Reset_Timer; + uint32 Spear_Throw_Timer; + bool bReset; + + void Reset() + { + Reset_Timer = 60000; + Spear_Throw_Timer = 2000; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackedBy(Unit* pAttacker) + { + if (me->getVictim()) + return; + + if (me->IsFriendlyTo(pAttacker)) + return; + + AttackStart(pAttacker); + } + + void DamageTaken(Unit *done_by, uint32 & damage) + { + if (done_by->GetTypeId() == TYPEID_PLAYER && (me->GetHealth() - damage)*100 / me->GetMaxHealth() < 30) + { + if (!bReset && CAST_PLR(done_by)->GetQuestStatus(9918) == QUEST_STATUS_INCOMPLETE) + { + //Take 0 damage + damage = 0; + + CAST_PLR(done_by)->AttackStop(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + me->setFaction(1080); //friendly + me->SetStandState(UNIT_STAND_STATE_SIT); + DoScriptText(LUMP_DEFEAT, me); + + bReset = true; + } + } + } + + void EnterCombat(Unit * /*who*/) + { + if (me->HasAura(SPELL_VISUAL_SLEEP)) + me->RemoveAura(SPELL_VISUAL_SLEEP); + + if (!me->IsStandState()) + me->SetStandState(UNIT_STAND_STATE_STAND); + + DoScriptText(RAND(LUMP_SAY0,LUMP_SAY1), me); + } + + void UpdateAI(const uint32 diff) + { + //check if we waiting for a reset + if (bReset) + { + if (Reset_Timer <= diff) + { + EnterEvadeMode(); + bReset = false; + me->setFaction(1711); //hostile + return; + } + else Reset_Timer -= diff; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Spear_Throw_Timer + if (Spear_Throw_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SPEAR_THROW); + Spear_Throw_Timer = 20000; + } else Spear_Throw_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_lump(Creature* pCreature) +{ + return new mob_lumpAI(pCreature); +} + +bool GossipHello_mob_lump(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(9918) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(9352, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_mob_lump(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(9353, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(9354, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(9355, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->SEND_GOSSIP_MENU(9356, pCreature->GetGUID()); + pPlayer->TalkedToCreature(18354, pCreature->GetGUID()); + break; + } + return true; +} + +/*#### +# mob_sunspring_villager - should be done with ACID +####*/ + +struct mob_sunspring_villagerAI : public ScriptedAI +{ + mob_sunspring_villagerAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + me->SetStandState(UNIT_STAND_STATE_DEAD); + } + + void EnterCombat(Unit * /*who*/) {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == 32146) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + } + } +}; +CreatureAI* GetAI_mob_sunspring_villager(Creature* pCreature) +{ + return new mob_sunspring_villagerAI (pCreature); +} + +/*###### +## npc_altruis_the_sufferer +######*/ + +#define GOSSIP_HATS1 "I see twisted steel and smell sundered earth." +#define GOSSIP_HATS2 "Well...?" +#define GOSSIP_HATS3 "[PH] Story about Illidan's Pupil" + +#define GOSSIP_SATS1 "Legion?" +#define GOSSIP_SATS2 "And now?" +#define GOSSIP_SATS3 "How do you see them now?" +#define GOSSIP_SATS4 "Forge camps?" +#define GOSSIP_SATS5 "Ok." +#define GOSSIP_SATS6 "[PH] Story done" + +bool GossipHello_npc_altruis_the_sufferer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + //gossip before obtaining Survey the Land + if (pPlayer->GetQuestStatus(9991) == QUEST_STATUS_NONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); + + //gossip when Survey the Land is incomplete (technically, after the flight) + if (pPlayer->GetQuestStatus(9991) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); + + //wowwiki.com/Varedis + if (pPlayer->GetQuestStatus(10646) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+30); + + pPlayer->SEND_GOSSIP_MENU(9419, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_altruis_the_sufferer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+10: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + pPlayer->SEND_GOSSIP_MENU(9420, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + pPlayer->SEND_GOSSIP_MENU(9421, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+12: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + pPlayer->SEND_GOSSIP_MENU(9422, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+13: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); + pPlayer->SEND_GOSSIP_MENU(9423, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+14: + pPlayer->SEND_GOSSIP_MENU(9424, pCreature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+20: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); + pPlayer->SEND_GOSSIP_MENU(9427, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+21: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(9991); + break; + + case GOSSIP_ACTION_INFO_DEF+30: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31); + pPlayer->SEND_GOSSIP_MENU(384, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+31: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(10646); + break; + } + return true; +} + +bool QuestAccept_npc_altruis_the_sufferer(Player* pPlayer, Creature* /*pCreature*/, Quest const * /*quest*/) +{ + if (!pPlayer->GetQuestRewardStatus(9991)) //Survey the Land, q-id 9991 + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(532); //TaxiPath 532 + } + return true; +} + +/*###### +## npc_greatmother_geyah +######*/ + +#define GOSSIP_HGG1 "Hello, Greatmother. Garrosh told me that you wanted to speak with me." +#define GOSSIP_HGG2 "Garrosh is beyond redemption, Greatmother. I fear that in helping the Mag'har, I have convinced Garrosh that he is unfit to lead." + +#define GOSSIP_SGG1 "You raised all of the orcs here, Greatmother?" +#define GOSSIP_SGG2 "Do you believe that?" +#define GOSSIP_SGG3 "What can be done? I have tried many different things. I have done my best to help the people of Nagrand. Each time I have approached Garrosh, he has dismissed me." +#define GOSSIP_SGG4 "Left? How can you choose to leave?" +#define GOSSIP_SGG5 "What is this duty?" +#define GOSSIP_SGG6 "Is there anything I can do for you, Greatmother?" +#define GOSSIP_SGG7 "I have done all that I could, Greatmother. I thank you for your kind words." +#define GOSSIP_SGG8 "Greatmother, you are the mother of Durotan?" +#define GOSSIP_SGG9 "Greatmother, I never had the honor. Durotan died long before my time, but his heroics are known to all on my world. The orcs of Azeroth reside in a place known as Durotar, named after your son. And ... (You take a moment to breathe and think through what you are about to tell the Greatmother.)" +#define GOSSIP_SGG10 "It is my Warchief, Greatmother. The leader of my people. From my world. He ... He is the son of Durotan. He is your grandchild." +#define GOSSIP_SGG11 "I will return to Azeroth at once, Greatmother." + +//all the textId's for the below is unknown, but i do believe the gossip item texts are proper. +bool GossipHello_npc_greatmother_geyah(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(10044) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HGG1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + } + else if (pPlayer->GetQuestStatus(10172) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HGG2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + } + else + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_greatmother_geyah(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 7: + pPlayer->AreaExploredOrEventHappens(10044); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + + case GOSSIP_ACTION_INFO_DEF + 10: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 11: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 12: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 13: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 14: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 15: + pPlayer->AreaExploredOrEventHappens(10172); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +/*###### +## npc_lantresor_of_the_blade +######*/ + +#define GOSSIP_HLB "I have killed many of your ogres, Lantresor. I have no fear." +#define GOSSIP_SLB1 "Should I know? You look like an orc to me." +#define GOSSIP_SLB2 "And the other half?" +#define GOSSIP_SLB3 "I have heard of your kind, but I never thought to see the day when I would meet a half-breed." +#define GOSSIP_SLB4 "My apologies. I did not mean to offend. I am here on behalf of my people." +#define GOSSIP_SLB5 "My people ask that you pull back your Boulderfist ogres and cease all attacks on our territories. In return, we will also pull back our forces." +#define GOSSIP_SLB6 "We will fight you until the end, then, Lantresor. We will not stand idly by as you pillage our towns and kill our people." +#define GOSSIP_SLB7 "What do I need to do?" + +bool GossipHello_npc_lantresor_of_the_blade(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(10107) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10108) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HLB, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(9361, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lantresor_of_the_blade(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(9362, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(9363, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(9364, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(9365, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + pPlayer->SEND_GOSSIP_MENU(9366, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + pPlayer->SEND_GOSSIP_MENU(9367, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + pPlayer->SEND_GOSSIP_MENU(9368, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->SEND_GOSSIP_MENU(9369, pCreature->GetGUID()); + if (pPlayer->GetQuestStatus(10107) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(10107); + if (pPlayer->GetQuestStatus(10108) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(10108); + break; + } + return true; +} + +/*##### +## npc_maghar_captive +#####*/ + +enum eMagharCaptive +{ + SAY_MAG_START = -1000482, + SAY_MAG_NO_ESCAPE = -1000483, + SAY_MAG_MORE = -1000484, + SAY_MAG_MORE_REPLY = -1000485, + SAY_MAG_LIGHTNING = -1000486, + SAY_MAG_SHOCK = -1000487, + SAY_MAG_COMPLETE = -1000488, + + SPELL_CHAIN_LIGHTNING = 16006, + SPELL_EARTHBIND_TOTEM = 15786, + SPELL_FROST_SHOCK = 12548, + SPELL_HEALING_WAVE = 12491, + + QUEST_TOTEM_KARDASH_H = 9868, + + NPC_MURK_RAIDER = 18203, + NPC_MURK_BRUTE = 18211, + NPC_MURK_SCAVENGER = 18207, + NPC_MURK_PUTRIFIER = 18202 +}; + +static float m_afAmbushA[]= {-1568.805786, 8533.873047, 1.958}; +static float m_afAmbushB[]= {-1491.554321, 8506.483398, 1.248}; + +struct npc_maghar_captiveAI : public npc_escortAI +{ + npc_maghar_captiveAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); } + + uint32 m_uiChainLightningTimer; + uint32 m_uiHealTimer; + uint32 m_uiFrostShockTimer; + + void Reset() + { + m_uiChainLightningTimer = 1000; + m_uiHealTimer = 0; + m_uiFrostShockTimer = 6000; + } + + void Aggro(Unit* /*pWho*/) + { + DoCast(me, SPELL_EARTHBIND_TOTEM, false); + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 7: + DoScriptText(SAY_MAG_MORE, me); + + if (Creature* pTemp = me->SummonCreature(NPC_MURK_PUTRIFIER, m_afAmbushB[0], m_afAmbushB[1], m_afAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000)) + DoScriptText(SAY_MAG_MORE_REPLY, pTemp); + + me->SummonCreature(NPC_MURK_PUTRIFIER, m_afAmbushB[0]-2.5f, m_afAmbushB[1]-2.5f, m_afAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + + me->SummonCreature(NPC_MURK_SCAVENGER, m_afAmbushB[0]+2.5f, m_afAmbushB[1]+2.5f, m_afAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(NPC_MURK_SCAVENGER, m_afAmbushB[0]+2.5f, m_afAmbushB[1]-2.5f, m_afAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + case 16: + DoScriptText(SAY_MAG_COMPLETE, me); + + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->GroupEventHappens(QUEST_TOTEM_KARDASH_H, me); + + SetRun(); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_MURK_BRUTE) + DoScriptText(SAY_MAG_NO_ESCAPE, pSummoned); + + if (pSummoned->isTotem()) + return; + + pSummoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pSummoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + pSummoned->AI()->AttackStart(me); + + } + + void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_CHAIN_LIGHTNING) + { + if (rand()%10) + return; + + DoScriptText(SAY_MAG_LIGHTNING, me); + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + if (!me->getVictim()) + return; + + if (m_uiChainLightningTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); + m_uiChainLightningTimer = urand(7000, 14000); + } + else + m_uiChainLightningTimer -= uiDiff; + + if (me->GetHealth()*100 < me->GetMaxHealth()*30) + { + if (m_uiHealTimer <= uiDiff) + { + DoCast(me, SPELL_HEALING_WAVE); + m_uiHealTimer = 5000; + } + else + m_uiHealTimer -= uiDiff; + } + + if (m_uiFrostShockTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_FROST_SHOCK); + m_uiFrostShockTimer = urand(7500, 15000); + } + else + m_uiFrostShockTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +bool QuestAccept_npc_maghar_captive(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_TOTEM_KARDASH_H) + { + if (npc_maghar_captiveAI* pEscortAI = dynamic_cast(pCreature->AI())) + { + pCreature->SetStandState(UNIT_STAND_STATE_STAND); + pCreature->setFaction(232); + + pEscortAI->Start(true, false, pPlayer->GetGUID(), pQuest); + + DoScriptText(SAY_MAG_START, pCreature); + + pCreature->SummonCreature(NPC_MURK_RAIDER, m_afAmbushA[0]+2.5f, m_afAmbushA[1]-2.5f, m_afAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + pCreature->SummonCreature(NPC_MURK_PUTRIFIER, m_afAmbushA[0]-2.5f, m_afAmbushA[1]+2.5f, m_afAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + pCreature->SummonCreature(NPC_MURK_BRUTE, m_afAmbushA[0], m_afAmbushA[1], m_afAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + } + } + return true; +} + +CreatureAI* GetAI_npc_maghar_captive(Creature* pCreature) +{ + return new npc_maghar_captiveAI(pCreature); +} + +/*###### +## npc_creditmarker_visist_with_ancestors +######*/ + +struct npc_creditmarker_visit_with_ancestorsAI : public ScriptedAI +{ + npc_creditmarker_visit_with_ancestorsAI(Creature* c) : ScriptedAI(c) {} + + void Reset() {} + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (!who) + return; + + if (who->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(who)->GetQuestStatus(10085) == QUEST_STATUS_INCOMPLETE) + { + uint32 creditMarkerId = me->GetEntry(); + if ((creditMarkerId >= 18840) && (creditMarkerId <= 18843)) + { + // 18840: Sunspring, 18841: Laughing, 18842: Garadar, 18843: Bleeding + if (!CAST_PLR(who)->GetReqKillOrCastCurrentCount(10085, creditMarkerId)) + CAST_PLR(who)->KilledMonsterCredit(creditMarkerId, me->GetGUID()); + } + } + } + } +}; + +CreatureAI* GetAI_npc_creditmarker_visit_with_ancestors(Creature* pCreature) +{ + return new npc_creditmarker_visit_with_ancestorsAI (pCreature); +} + +/*###### +## mob_sparrowhawk +######*/ + +#define SPELL_SPARROWHAWK_NET 39810 +#define SPELL_ITEM_CAPTIVE_SPARROWHAWK 39812 + +struct mob_sparrowhawkAI : public ScriptedAI +{ + + mob_sparrowhawkAI(Creature *c) : ScriptedAI(c) {} + + uint32 Check_Timer; + uint64 PlayerGUID; + bool fleeing; + + void Reset() + { + me->RemoveAurasDueToSpell(SPELL_SPARROWHAWK_NET); + Check_Timer = 1000; + PlayerGUID = 0; + fleeing = false; + } + void AttackStart(Unit *who) + { + if (PlayerGUID) + return; + + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (!who || PlayerGUID) + return; + + if (!PlayerGUID && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 30) && CAST_PLR(who)->GetQuestStatus(10987) == QUEST_STATUS_INCOMPLETE) + { + PlayerGUID = who->GetGUID(); + return; + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + if (Check_Timer <= diff) + { + if (PlayerGUID) + { + if (fleeing && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != FLEEING_MOTION_TYPE) + fleeing = false; + + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer && me->IsWithinDistInMap(pPlayer, 30)) + { + if (!fleeing) + { + me->DeleteThreatList(); + me->GetMotionMaster()->MoveFleeing(pPlayer); + fleeing = true; + } + } + else if (fleeing) + { + me->GetMotionMaster()->MovementExpired(false); + PlayerGUID = 0; + fleeing = false; + } + } + Check_Timer = 1000; + } else Check_Timer -= diff; + + if (PlayerGUID) + return; + + ScriptedAI::UpdateAI(diff); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + if (spell->Id == SPELL_SPARROWHAWK_NET && CAST_PLR(caster)->GetQuestStatus(10987) == QUEST_STATUS_INCOMPLETE) + { + DoCast(caster, SPELL_ITEM_CAPTIVE_SPARROWHAWK, true); + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + return; + } +}; + +CreatureAI* GetAI_mob_sparrowhawk(Creature* pCreature) +{ + return new mob_sparrowhawkAI (pCreature); +} + +/*#### +# +####*/ + +void AddSC_nagrand() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_shattered_rumbler"; + newscript->GetAI = &GetAI_mob_shattered_rumbler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lump"; + newscript->GetAI = &GetAI_mob_lump; + newscript->pGossipHello = &GossipHello_mob_lump; + newscript->pGossipSelect = &GossipSelect_mob_lump; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_sunspring_villager"; + newscript->GetAI = &GetAI_mob_sunspring_villager; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_altruis_the_sufferer"; + newscript->pGossipHello = &GossipHello_npc_altruis_the_sufferer; + newscript->pGossipSelect = &GossipSelect_npc_altruis_the_sufferer; + newscript->pQuestAccept = &QuestAccept_npc_altruis_the_sufferer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_greatmother_geyah"; + newscript->pGossipHello = &GossipHello_npc_greatmother_geyah; + newscript->pGossipSelect = &GossipSelect_npc_greatmother_geyah; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lantresor_of_the_blade"; + newscript->pGossipHello = &GossipHello_npc_lantresor_of_the_blade; + newscript->pGossipSelect = &GossipSelect_npc_lantresor_of_the_blade; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_maghar_captive"; + newscript->GetAI = &GetAI_npc_maghar_captive; + newscript->pQuestAccept = &QuestAccept_npc_maghar_captive; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_creditmarker_visit_with_ancestors"; + newscript->GetAI = &GetAI_npc_creditmarker_visit_with_ancestors; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_sparrowhawk"; + newscript->GetAI = &GetAI_mob_sparrowhawk; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/netherstorm.cpp b/src/server/scripts/Outland/netherstorm.cpp new file mode 100644 index 00000000000..efe18ad1908 --- /dev/null +++ b/src/server/scripts/Outland/netherstorm.cpp @@ -0,0 +1,925 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Netherstorm +SD%Complete: 75 +SDComment: Quest support: 10337, 10438, 10652 (special flight paths), 10299,10321,10322,10323,10329,10330,10338,10365(Shutting Down Manaforge), 10198 +SDCategory: Netherstorm +EndScriptData */ + +/* ContentData +npc_manaforge_control_console +go_manaforge_control_console +npc_commander_dawnforge +npc_bessy +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_manaforge_control_console +######*/ + +//used by 20209,20417,20418,20440, signed for 20209 +#define EMOTE_START -1000211 +#define EMOTE_60 -1000212 +#define EMOTE_30 -1000213 +#define EMOTE_10 -1000214 +#define EMOTE_COMPLETE -1000215 +#define EMOTE_ABORT -1000216 + +#define ENTRY_BNAAR_C_CONSOLE 20209 +#define ENTRY_CORUU_C_CONSOLE 20417 +#define ENTRY_DURO_C_CONSOLE 20418 +#define ENTRY_ARA_C_CONSOLE 20440 + +#define ENTRY_SUNFURY_TECH 20218 +#define ENTRY_SUNFURY_PROT 20436 + +#define ENTRY_ARA_TECH 20438 +#define ENTRY_ARA_ENGI 20439 +#define ENTRY_ARA_GORKLONN 20460 + +#define SPELL_DISABLE_VISUAL 35031 +#define SPELL_INTERRUPT_1 35016 //ACID mobs should cast this +#define SPELL_INTERRUPT_2 35176 //ACID mobs should cast this (Manaforge Ara-version) + +struct npc_manaforge_control_consoleAI : public ScriptedAI +{ + npc_manaforge_control_consoleAI(Creature *c) : ScriptedAI(c) {} + + uint32 Event_Timer; + uint32 Wave_Timer; + uint32 Phase; + bool Wave; + uint64 someplayer; + uint64 goConsole; + Creature* add; + + void Reset() + { + Event_Timer = 3000; + Wave_Timer = 0; + Phase = 1; + Wave = false; + someplayer = 0; + goConsole = 0; + add = NULL; + } + + void EnterCombat(Unit * /*who*/) {} + + /*void SpellHit(Unit *caster, const SpellEntry *spell) + { + //we have no way of telling the Creature was hit by spell -> got aura applied after 10-12 seconds + //then no way for the mobs to actually stop the shutdown as intended. + if (spell->Id == SPELL_INTERRUPT_1) + DoSay("Silence! I kill you!",LANG_UNIVERSAL, NULL); + }*/ + + void JustDied(Unit* /*killer*/) + { + DoScriptText(EMOTE_ABORT, me); + + if (someplayer) + { + Unit* p = Unit::GetUnit((*me),someplayer); + if (p && p->GetTypeId() == TYPEID_PLAYER) + { + switch(me->GetEntry()) + { + case ENTRY_BNAAR_C_CONSOLE: + CAST_PLR(p)->FailQuest(10299); + CAST_PLR(p)->FailQuest(10329); + break; + case ENTRY_CORUU_C_CONSOLE: + CAST_PLR(p)->FailQuest(10321); + CAST_PLR(p)->FailQuest(10330); + break; + case ENTRY_DURO_C_CONSOLE: + CAST_PLR(p)->FailQuest(10322); + CAST_PLR(p)->FailQuest(10338); + break; + case ENTRY_ARA_C_CONSOLE: + CAST_PLR(p)->FailQuest(10323); + CAST_PLR(p)->FailQuest(10365); + break; + } + } + } + + if (goConsole) + { + if (GameObject* pGo = GameObject::GetGameObject((*me),goConsole)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + } + } + + void DoWaveSpawnForCreature(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case ENTRY_BNAAR_C_CONSOLE: + if (rand()%2) + { + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2933.68,4162.55,164.00,1.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2927.36,4212.97,164.00); + } + else + { + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2927.36,4212.97,164.00,4.94,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2933.68,4162.55,164.00); + } + Wave_Timer = 30000; + break; + case ENTRY_CORUU_C_CONSOLE: + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2445.21,2765.26,134.49,3.93,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2424.21,2740.15,133.81); + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2429.86,2731.85,134.53,1.31,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2435.37,2766.04,133.81); + Wave_Timer = 20000; + break; + case ENTRY_DURO_C_CONSOLE: + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2986.80,2205.36,165.37,3.74,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2985.15,2197.32,164.79); + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2952.91,2191.20,165.32,0.22,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2060.01,2185.27,164.67); + Wave_Timer = 15000; + break; + case ENTRY_ARA_C_CONSOLE: + if (rand()%2) + { + add = me->SummonCreature(ENTRY_ARA_TECH,4035.11,4038.97,194.27,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); + add = me->SummonCreature(ENTRY_ARA_TECH,4033.66,4036.79,194.28,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); + add = me->SummonCreature(ENTRY_ARA_TECH,4037.13,4037.30,194.23,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); + } + else + { + add = me->SummonCreature(ENTRY_ARA_TECH,3099.59,4049.30,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); + add = me->SummonCreature(ENTRY_ARA_TECH,3999.72,4046.75,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); + add = me->SummonCreature(ENTRY_ARA_TECH,3996.81,4048.26,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); + } + Wave_Timer = 15000; + break; + } + } + void DoFinalSpawnForCreature(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case ENTRY_BNAAR_C_CONSOLE: + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2946.52,4201.42,163.47,3.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2927.49,4192.81,163.00); + break; + case ENTRY_CORUU_C_CONSOLE: + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2453.88,2737.85,133.27,2.59,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2441.62,2735.32,134.49,1.97,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2450.73,2754.50,134.49,3.29,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); + break; + case ENTRY_DURO_C_CONSOLE: + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2956.18,2202.85,165.32,5.45,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); + add = me->SummonCreature(ENTRY_SUNFURY_TECH,2975.30,2211.50,165.32,4.55,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); + add = me->SummonCreature(ENTRY_SUNFURY_PROT,2965.02,2217.45,164.16,4.96,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); + break; + case ENTRY_ARA_C_CONSOLE: + add = me->SummonCreature(ENTRY_ARA_ENGI,3994.51,4020.46,192.18,0.91,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,4008.35,4035.04,192.70); + add = me->SummonCreature(ENTRY_ARA_GORKLONN,4021.56,4059.35,193.59,4.44,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); + if (add) add->GetMotionMaster()->MovePoint(0,4016.62,4039.89,193.46); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (Event_Timer <= diff) + { + switch(Phase) + { + case 1: + if (someplayer) + { + Unit* u = Unit::GetUnit((*me), someplayer); + if (u && u->GetTypeId() == TYPEID_PLAYER) DoScriptText(EMOTE_START, me, u); + } + Event_Timer = 60000; + Wave = true; + ++Phase; + break; + case 2: + DoScriptText(EMOTE_60, me); + Event_Timer = 30000; + ++Phase; + break; + case 3: + DoScriptText(EMOTE_30, me); + Event_Timer = 20000; + DoFinalSpawnForCreature(me); + ++Phase; + break; + case 4: + DoScriptText(EMOTE_10, me); + Event_Timer = 10000; + Wave = false; + ++Phase; + break; + case 5: + DoScriptText(EMOTE_COMPLETE, me); + if (someplayer) + { + Unit* u = Unit::GetUnit((*me),someplayer); + if (u && u->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(u)->KilledMonsterCredit(me->GetEntry(),me->GetGUID()); + DoCast(me, SPELL_DISABLE_VISUAL); + } + if (goConsole) + { + if (GameObject* pGo = GameObject::GetGameObject((*me),goConsole)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + } + ++Phase; + break; + } + } else Event_Timer -= diff; + + if (Wave) + { + if (Wave_Timer <= diff) + { + DoWaveSpawnForCreature(me); + } else Wave_Timer -= diff; + } + } +}; +CreatureAI* GetAI_npc_manaforge_control_console(Creature* pCreature) +{ + return new npc_manaforge_control_consoleAI (pCreature); +} + +/*###### +## go_manaforge_control_console +######*/ + +//TODO: clean up this workaround when Trinity adds support to do it properly (with gossip selections instead of instant summon) +bool GOHello_go_manaforge_control_console(Player* pPlayer, GameObject* pGo) +{ + if (pGo->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + { + pPlayer->PrepareQuestMenu(pGo->GetGUID()); + pPlayer->SendPreparedQuest(pGo->GetGUID()); + } + + Creature* manaforge = NULL; + + switch(pGo->GetAreaId()) + { + case 3726: //b'naar + if ((pPlayer->GetQuestStatus(10299) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10329) == QUEST_STATUS_INCOMPLETE) && + pPlayer->HasItemCount(29366,1)) + manaforge = pPlayer->SummonCreature(ENTRY_BNAAR_C_CONSOLE,2918.95,4189.98,161.88,0.34,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); + break; + case 3730: //coruu + if ((pPlayer->GetQuestStatus(10321) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10330) == QUEST_STATUS_INCOMPLETE) && + pPlayer->HasItemCount(29396,1)) + manaforge = pPlayer->SummonCreature(ENTRY_CORUU_C_CONSOLE,2426.77,2750.38,133.24,2.14,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); + break; + case 3734: //duro + if ((pPlayer->GetQuestStatus(10322) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10338) == QUEST_STATUS_INCOMPLETE) && + pPlayer->HasItemCount(29397,1)) + manaforge = pPlayer->SummonCreature(ENTRY_DURO_C_CONSOLE,2976.48,2183.29,163.20,1.85,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); + break; + case 3722: //ara + if ((pPlayer->GetQuestStatus(10323) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10365) == QUEST_STATUS_INCOMPLETE) && + pPlayer->HasItemCount(29411,1)) + manaforge = pPlayer->SummonCreature(ENTRY_ARA_C_CONSOLE,4013.71,4028.76,192.10,1.25,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); + break; + } + + if (manaforge) + { + CAST_AI(npc_manaforge_control_consoleAI, manaforge->AI())->someplayer = pPlayer->GetGUID(); + CAST_AI(npc_manaforge_control_consoleAI, manaforge->AI())->goConsole = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + } + return true; +} + +/*###### +## npc_commander_dawnforge +######*/ + +// The Speech of Dawnforge, Ardonis & Pathaleon +#define SAY_COMMANDER_DAWNFORGE_1 -1000128 +#define SAY_ARCANIST_ARDONIS_1 -1000129 +#define SAY_COMMANDER_DAWNFORGE_2 -1000130 +#define SAY_PATHALEON_CULATOR_IMAGE_1 -1000131 +#define SAY_COMMANDER_DAWNFORGE_3 -1000132 +#define SAY_PATHALEON_CULATOR_IMAGE_2 -1000133 +#define SAY_PATHALEON_CULATOR_IMAGE_2_1 -1000134 +#define SAY_PATHALEON_CULATOR_IMAGE_2_2 -1000135 +#define SAY_COMMANDER_DAWNFORGE_4 -1000136 +#define SAY_ARCANIST_ARDONIS_2 -1000136 +#define SAY_COMMANDER_DAWNFORGE_5 -1000137 + +#define QUEST_INFO_GATHERING 10198 +#define SPELL_SUNFURY_DISGUISE 34603 + +// Entries of Arcanist Ardonis, Commander Dawnforge, Pathaleon the Curators Image +const uint32 CreatureEntry[3] = +{ + 19830, // Ardonis + 19831, // Dawnforge + 21504 // Pathaleon +}; + +struct npc_commander_dawnforgeAI : public ScriptedAI +{ + npc_commander_dawnforgeAI(Creature *c) : ScriptedAI(c) { Reset (); } + + uint64 PlayerGUID; + uint64 ardonisGUID; + uint64 pathaleonGUID; + + uint32 Phase; + uint32 PhaseSubphase; + uint32 Phase_Timer; + bool isEvent; + + float angle_dawnforge; + float angle_ardonis; + + void Reset() + { + PlayerGUID = 0; + ardonisGUID = 0; + pathaleonGUID = 0; + + Phase = 1; + PhaseSubphase = 0; + Phase_Timer = 4000; + isEvent = false; + } + + void EnterCombat(Unit * /*who*/) { } + + void JustSummoned(Creature *summoned) + { + pathaleonGUID = summoned->GetGUID(); + } + + // Emote Ardonis and Pathaleon + void Turn_to_Pathaleons_Image() + { + Creature *ardonis = Unit::GetCreature(*me,ardonisGUID); + Creature *pathaleon = Unit::GetCreature(*me,pathaleonGUID); + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + if (!ardonis || !pathaleon || !pPlayer) + return; + + //Calculate the angle to Pathaleon + angle_dawnforge = me->GetAngle(pathaleon->GetPositionX(), pathaleon->GetPositionY()); + angle_ardonis = ardonis->GetAngle(pathaleon->GetPositionX(), pathaleon->GetPositionY()); + + //Turn Dawnforge and update + me->SetOrientation(angle_dawnforge); + me->SendUpdateToPlayer(pPlayer); + //Turn Ardonis and update + ardonis->SetOrientation(angle_ardonis); + ardonis->SendUpdateToPlayer(pPlayer); + + //Set them to kneel + me->SetStandState(UNIT_STAND_STATE_KNEEL); + ardonis->SetStandState(UNIT_STAND_STATE_KNEEL); + } + + //Set them back to each other + void Turn_to_eachother() + { + if (Unit *ardonis = Unit::GetUnit(*me,ardonisGUID)) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + if (!pPlayer) + return; + + angle_dawnforge = me->GetAngle(ardonis->GetPositionX(), ardonis->GetPositionY()); + angle_ardonis = ardonis->GetAngle(me->GetPositionX(), me->GetPositionY()); + + //Turn Dawnforge and update + me->SetOrientation(angle_dawnforge); + me->SendUpdateToPlayer(pPlayer); + //Turn Ardonis and update + ardonis->SetOrientation(angle_ardonis); + ardonis->SendUpdateToPlayer(pPlayer); + + //Set state + me->SetStandState(UNIT_STAND_STATE_STAND); + ardonis->SetStandState(UNIT_STAND_STATE_STAND); + } + } + + bool CanStartEvent(Player* pPlayer) + { + if (!isEvent) + { + Creature* ardonis = me->FindNearestCreature(CreatureEntry[0], 10.0f); + if (!ardonis) + return false; + + ardonisGUID = ardonis->GetGUID(); + PlayerGUID = pPlayer->GetGUID(); + + isEvent = true; + + Turn_to_eachother(); + return true; + } + + debug_log("TSCR: npc_commander_dawnforge event already in progress, need to wait."); + return false; + } + + void UpdateAI(const uint32 diff) + { + //Is event even running? + if (!isEvent) + return; + + //Phase timing + if (Phase_Timer >= diff) + { + Phase_Timer -= diff; + return; + } + + Unit *ardonis = Unit::GetUnit(*me,ardonisGUID); + Unit *pathaleon = Unit::GetUnit(*me,pathaleonGUID); + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + if (!ardonis || !pPlayer) + { + Reset(); + return; + } + + if (Phase > 4 && !pathaleon) + { + Reset(); + return; + } + + //Phase 1 Dawnforge say + switch (Phase) + { + case 1: + DoScriptText(SAY_COMMANDER_DAWNFORGE_1, me); + ++Phase; + Phase_Timer = 16000; + break; + //Phase 2 Ardonis say + case 2: + DoScriptText(SAY_ARCANIST_ARDONIS_1, ardonis); + ++Phase; + Phase_Timer = 16000; + break; + //Phase 3 Dawnforge say + case 3: + DoScriptText(SAY_COMMANDER_DAWNFORGE_2, me); + ++Phase; + Phase_Timer = 16000; + break; + //Phase 4 Pathaleon spawns up to phase 9 + case 4: + //spawn pathaleon's image + me->SummonCreature(CreatureEntry[2], 2325.851563, 2799.534668, 133.084229, 6.038996, TEMPSUMMON_TIMED_DESPAWN, 90000); + ++Phase; + Phase_Timer = 500; + break; + //Phase 5 Pathaleon say + case 5: + DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_1, pathaleon); + ++Phase; + Phase_Timer = 6000; + break; + //Phase 6 + case 6: + switch(PhaseSubphase) + { + //Subphase 1: Turn Dawnforge and Ardonis + case 0: + Turn_to_Pathaleons_Image(); + ++PhaseSubphase; + Phase_Timer = 8000; + break; + //Subphase 2 Dawnforge say + case 1: + DoScriptText(SAY_COMMANDER_DAWNFORGE_3, me); + PhaseSubphase = 0; + ++Phase; + Phase_Timer = 8000; + break; + } + break; + //Phase 7 Pathaleons say 3 Sentence, every sentence need a subphase + case 7: + switch(PhaseSubphase) + { + //Subphase 1 + case 0: + DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2, pathaleon); + ++PhaseSubphase; + Phase_Timer = 12000; + break; + //Subphase 2 + case 1: + DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2_1, pathaleon); + ++PhaseSubphase; + Phase_Timer = 16000; + break; + //Subphase 3 + case 2: + DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2_2, pathaleon); + PhaseSubphase = 0; + ++Phase; + Phase_Timer = 10000; + break; + } + break; + //Phase 8 Dawnforge & Ardonis say + case 8: + DoScriptText(SAY_COMMANDER_DAWNFORGE_4, me); + DoScriptText(SAY_ARCANIST_ARDONIS_2, ardonis); + ++Phase; + Phase_Timer = 4000; + break; + //Phase 9 Pathaleons Despawn, Reset Dawnforge & Ardonis angle + case 9: + Turn_to_eachother(); + //hide pathaleon, unit will despawn shortly + pathaleon->SetVisibility(VISIBILITY_OFF); + PhaseSubphase = 0; + ++Phase; + Phase_Timer = 3000; + break; + //Phase 10 Dawnforge say + case 10: + DoScriptText(SAY_COMMANDER_DAWNFORGE_5, me); + pPlayer->AreaExploredOrEventHappens(QUEST_INFO_GATHERING); + Reset(); + break; + } + } +}; + +CreatureAI* GetAI_npc_commander_dawnforge(Creature* pCreature) +{ + return new npc_commander_dawnforgeAI(pCreature); +} + +bool AreaTrigger_at_commander_dawnforge(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + //if player lost aura or not have at all, we should not try start event. + if (!pPlayer->HasAura(SPELL_SUNFURY_DISGUISE)) + return false; + + if (pPlayer->isAlive() && pPlayer->GetQuestStatus(QUEST_INFO_GATHERING) == QUEST_STATUS_INCOMPLETE) + { + Creature* Dawnforge = pPlayer->FindNearestCreature(CreatureEntry[1], 30.0f); + + if (!Dawnforge) + return false; + + if (CAST_AI(npc_commander_dawnforgeAI, Dawnforge->AI())->CanStartEvent(pPlayer)) + return true; + } + return false; +} + +/*###### +## npc_professor_dabiri +######*/ + +#define SPELL_PHASE_DISTRUPTOR 35780 +#define GOSSIP_ITEM "I need a new phase distruptor, Professor" +#define WHISPER_DABIRI -1000302 + +#define QUEST_DIMENSIUS 10439 +#define QUEST_ON_NETHERY_WINGS 10438 + +bool GossipHello_npc_professor_dabiri(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_ON_NETHERY_WINGS) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(29778, 1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_professor_dabiri(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pCreature->CastSpell(pPlayer, SPELL_PHASE_DISTRUPTOR, false); + pPlayer->CLOSE_GOSSIP_MENU(); + } + + return true; +} + +bool QuestAccept_npc_professor_dabiri(Player* pPlayer, Creature* pCreature, Quest const *quest) +{ + if (quest->GetQuestId() == QUEST_DIMENSIUS) + DoScriptText(WHISPER_DABIRI, pCreature, pPlayer); + + return true; +} + +/*###### +## mob_phase_hunter +######*/ + +#define QUEST_RECHARGING_THE_BATTERIES 10190 + +#define NPC_PHASE_HUNTER_ENTRY 18879 +#define NPC_DRAINED_PHASE_HUNTER_ENTRY 19595 + +#define EMOTE_WEAK -1000303 + +// Spells +#define SPELL_RECHARGING_BATTERY 34219 +#define SPELL_PHASE_SLIP 36574 +#define SPELL_MANA_BURN 13321 +#define SPELL_MATERIALIZE 34804 +#define SPELL_DE_MATERIALIZE 34814 + +struct mob_phase_hunterAI : public ScriptedAI +{ + mob_phase_hunterAI(Creature *c) : ScriptedAI(c) {} + + bool Weak; + bool Materialize; + bool Drained; + uint8 WeakPercent; + float HpPercent; + + Player *pPlayer; + uint64 PlayerGUID; + + uint32 ManaBurnTimer; + + void Reset() + { + Weak = false; + Materialize = false; + Drained = false; + WeakPercent = 25 + (rand() % 16); // 25-40 + HpPercent = 0.0f; + + PlayerGUID = 0; + + ManaBurnTimer = 5000 + (rand() % 3 * 1000); // 5-8 sec cd + + if (me->GetEntry() == NPC_DRAINED_PHASE_HUNTER_ENTRY) + me->UpdateEntry(NPC_PHASE_HUNTER_ENTRY); + } + + void EnterCombat(Unit * who) + { + if (who->GetTypeId() == TYPEID_PLAYER) + PlayerGUID = who->GetGUID(); + } + + void SpellHit(Unit * /*caster*/, const SpellEntry * /*spell*/) + { + DoCast(me, SPELL_DE_MATERIALIZE); + } + + void UpdateAI(const uint32 diff) + { + if (!Materialize) + { + DoCast(me, SPELL_MATERIALIZE); + Materialize = true; + } + + if (me->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED) || me->hasUnitState(UNIT_STAT_ROOT)) // if the mob is rooted/slowed by spells eg.: Entangling Roots, Frost Nova, Hamstring, Crippling Poison, etc. => remove it + DoCast(me, SPELL_PHASE_SLIP); + + if (!UpdateVictim()) + return; + + // some code to cast spell Mana Burn on random target which has mana + if (ManaBurnTimer <= diff) + { + std::list AggroList = me->getThreatManager().getThreatList(); + std::list UnitsWithMana; + + for (std::list::const_iterator itr = AggroList.begin(); itr != AggroList.end(); ++itr) + { + if (Unit *pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + if (pUnit->GetCreateMana() > 0) + UnitsWithMana.push_back(pUnit); + } + } + if (!UnitsWithMana.empty()) + { + std::list::const_iterator it = UnitsWithMana.begin(); + std::advance(it, rand() % UnitsWithMana.size()); + DoCast(*it, SPELL_MANA_BURN); + ManaBurnTimer = 8000 + (rand() % 10 * 1000); // 8-18 sec cd + } + else + ManaBurnTimer = 3500; + } else ManaBurnTimer -= diff; + + if (Player *pPlayer = Unit::GetPlayer(PlayerGUID)) // start: support for quest 10190 + { + if (!Weak && me->GetHealth() < (me->GetMaxHealth() / 100 * WeakPercent) + && pPlayer->GetQuestStatus(QUEST_RECHARGING_THE_BATTERIES) == QUEST_STATUS_INCOMPLETE) + { + DoScriptText(EMOTE_WEAK, me); + Weak = true; + } + if (Weak && !Drained && me->HasAura(SPELL_RECHARGING_BATTERY)) + { + Drained = true; + HpPercent = float(me->GetHealth()) / float(me->GetMaxHealth()); + + me->UpdateEntry(NPC_DRAINED_PHASE_HUNTER_ENTRY); + + me->SetHealth(me->GetMaxHealth() * HpPercent); + me->LowerPlayerDamageReq(me->GetMaxHealth() - me->GetHealth()); + me->SetInCombatWith(pPlayer); + } + } // end: support for quest 10190 + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_phase_hunter(Creature* pCreature) +{ + return new mob_phase_hunterAI (pCreature); +} + +/*###### +## npc_bessy +######*/ + +#define Q_ALMABTRIEB 10337 +#define N_THADELL 20464 +#define SPAWN_FIRST 20512 +#define SPAWN_SECOND 19881 +#define SAY_THADELL_1 -1000304 +#define SAY_THADELL_2 -1000305 + +struct npc_bessyAI : public npc_escortAI +{ + + npc_bessyAI(Creature *c) : npc_escortAI(c) {} + + void JustDied(Unit* /*killer*/) + { + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->FailQuest(Q_ALMABTRIEB); + } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 3: //first spawn + me->SummonCreature(SPAWN_FIRST, 2449.67, 2183.11, 96.85, 6.20, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(SPAWN_FIRST, 2449.53, 2184.43, 96.36, 6.27, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(SPAWN_FIRST, 2449.85, 2186.34, 97.57, 6.08, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + + case 7: + me->SummonCreature(SPAWN_SECOND, 2309.64, 2186.24, 92.25, 6.06, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(SPAWN_SECOND, 2309.25, 2183.46, 91.75, 6.22, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + + case 12: + if (pPlayer) + pPlayer->GroupEventHappens(Q_ALMABTRIEB, me); + if (Unit* Thadell = me->FindNearestCreature(N_THADELL, 30)) + DoScriptText(SAY_THADELL_1, me); break; + case 13: + if (Unit* Thadell = me->FindNearestCreature(N_THADELL, 30)) + DoScriptText(SAY_THADELL_2, me, pPlayer); break; + } + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void Reset() + { + me->RestoreFaction(); + } + +}; + +bool QuestAccept_npc_bessy(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == Q_ALMABTRIEB) + { + pCreature->setFaction(113); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_bessy(Creature* pCreature) +{ + return new npc_bessyAI(pCreature); +} + +/*###### +## +######*/ + +void AddSC_netherstorm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_manaforge_control_console"; + newscript->pGOHello = &GOHello_go_manaforge_control_console; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_manaforge_control_console"; + newscript->GetAI = &GetAI_npc_manaforge_control_console; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_commander_dawnforge"; + newscript->GetAI = &GetAI_npc_commander_dawnforge; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_commander_dawnforge"; + newscript->pAreaTrigger = &AreaTrigger_at_commander_dawnforge; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_professor_dabiri"; + newscript->pGossipHello = &GossipHello_npc_professor_dabiri; + newscript->pGossipSelect = &GossipSelect_npc_professor_dabiri; + newscript->pQuestAccept = &QuestAccept_npc_professor_dabiri; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phase_hunter"; + newscript->GetAI = &GetAI_mob_phase_hunter; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bessy"; + newscript->GetAI = &GetAI_npc_bessy; + newscript->pQuestAccept = &QuestAccept_npc_bessy; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/shadowmoon_valley.cpp b/src/server/scripts/Outland/shadowmoon_valley.cpp new file mode 100644 index 00000000000..0e2eb34f0fe --- /dev/null +++ b/src/server/scripts/Outland/shadowmoon_valley.cpp @@ -0,0 +1,1828 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Shadowmoon_Valley +SD%Complete: 100 +SDComment: Quest support: 10519, 10583, 10601, 10814, 10804, 10854, 10458, 10481, 10480, 11082, 10781, 10451. Vendor Drake Dealer Hurlunk. +SDCategory: Shadowmoon Valley +EndScriptData */ + +/* ContentData +mob_mature_netherwing_drake +mob_enslaved_netherwing_drake +npc_drake_dealer_hurlunk +npcs_flanis_swiftwing_and_kagrosh +npc_murkblood_overseer +npc_neltharaku +npc_karynaku +npc_oronok_tornheart +npc_overlord_morghor +npc_earthmender_wilda +mob_torloth_the_magnificent +mob_illidari_spawn +npc_lord_illidan_stormrage +go_crystal_prison +npc_enraged_spirit +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*##### +# mob_mature_netherwing_drake +#####*/ + +enum eMatureNetherwing +{ + SAY_JUST_EATEN = -1000222, + + SPELL_PLACE_CARCASS = 38439, + SPELL_JUST_EATEN = 38502, + SPELL_NETHER_BREATH = 38467, + POINT_ID = 1, + + GO_CARCASS = 185155, + + QUEST_KINDNESS = 10804, + NPC_EVENT_PINGER = 22131 +}; + +struct mob_mature_netherwing_drakeAI : public ScriptedAI +{ + mob_mature_netherwing_drakeAI(Creature* c) : ScriptedAI(c) { } + + uint64 uiPlayerGUID; + + bool bCanEat; + bool bIsEating; + + uint32 EatTimer; + uint32 CastTimer; + + void Reset() + { + uiPlayerGUID = 0; + + bCanEat = false; + bIsEating = false; + + EatTimer = 5000; + CastTimer = 5000; + } + + void SpellHit(Unit* pCaster, SpellEntry const* pSpell) + { + if (bCanEat || bIsEating) + return; + + if (pCaster->GetTypeId() == TYPEID_PLAYER && pSpell->Id == SPELL_PLACE_CARCASS && !me->HasAura(SPELL_JUST_EATEN)) + { + uiPlayerGUID = pCaster->GetGUID(); + bCanEat = true; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == POINT_ID) + { + bIsEating = true; + EatTimer = 7000; + me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); + } + } + + void UpdateAI(const uint32 diff) + { + if (bCanEat || bIsEating) + { + if (EatTimer <= diff) + { + if (bCanEat && !bIsEating) + { + if (Unit* pUnit = Unit::GetUnit(*me, uiPlayerGUID)) + { + if (GameObject* pGo = pUnit->FindNearestGameObject(GO_CARCASS, 10)) + { + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); + + me->GetMotionMaster()->MovePoint(POINT_ID, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ()); + } + } + bCanEat = false; + } + else if (bIsEating) + { + DoCast(me, SPELL_JUST_EATEN); + DoScriptText(SAY_JUST_EATEN, me); + + if (Player* pPlr = Unit::GetPlayer(uiPlayerGUID)) + { + pPlr->KilledMonsterCredit(NPC_EVENT_PINGER, me->GetGUID()); + + if (GameObject* pGo = pPlr->FindNearestGameObject(GO_CARCASS, 10)) + pGo->Delete(); + } + + Reset(); + me->GetMotionMaster()->Clear(); + } + } + else + EatTimer -= diff; + + return; + } + + if (!UpdateVictim()) + return; + + if (CastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_NETHER_BREATH); + CastTimer = 5000; + } else CastTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_mature_netherwing_drake(Creature* pCreature) +{ + return new mob_mature_netherwing_drakeAI(pCreature); +} + +/*### +# mob_enslaved_netherwing_drake +####*/ + +#define FACTION_DEFAULT 62 +#define FACTION_FRIENDLY 1840 // Not sure if this is correct, it was taken off of Mordenai. + +#define SPELL_HIT_FORCE_OF_NELTHARAKU 38762 +#define SPELL_FORCE_OF_NELTHARAKU 38775 + +#define CREATURE_DRAGONMAW_SUBJUGATOR 21718 +#define CREATURE_ESCAPE_DUMMY 22317 + +struct mob_enslaved_netherwing_drakeAI : public ScriptedAI +{ + mob_enslaved_netherwing_drakeAI(Creature* c) : ScriptedAI(c) + { + PlayerGUID = 0; + Tapped = false; + Reset(); + } + + uint64 PlayerGUID; + uint32 FlyTimer; + bool Tapped; + + void Reset() + { + if (!Tapped) + me->setFaction(FACTION_DEFAULT); + + FlyTimer = 10000; + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetVisibility(VISIBILITY_ON); + } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if (!caster) + return; + + if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_HIT_FORCE_OF_NELTHARAKU && !Tapped) + { + Tapped = true; + PlayerGUID = caster->GetGUID(); + + me->setFaction(FACTION_FRIENDLY); + DoCast(caster, SPELL_FORCE_OF_NELTHARAKU, true); + + Unit* Dragonmaw = me->FindNearestCreature(CREATURE_DRAGONMAW_SUBJUGATOR, 50); + + if (Dragonmaw) + { + me->AddThreat(Dragonmaw, 100000.0f); + AttackStart(Dragonmaw); + } + + HostileReference* ref = me->getThreatManager().getOnlineContainer().getReferenceByTarget(caster); + if (ref) + ref->removeReference(); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + { + if (PlayerGUID) + { + Unit* plr = Unit::GetUnit((*me), PlayerGUID); + if (plr) + DoCast(plr, SPELL_FORCE_OF_NELTHARAKU, true); + + PlayerGUID = 0; + } + me->SetVisibility(VISIBILITY_OFF); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (Tapped) + if (FlyTimer <= diff) + { + Tapped = false; + if (PlayerGUID) + { + Player* plr = Unit::GetPlayer(PlayerGUID); + if (plr && plr->GetQuestStatus(10854) == QUEST_STATUS_INCOMPLETE) + { + DoCast(plr, SPELL_FORCE_OF_NELTHARAKU, true); + /* + float x,y,z; + me->GetPosition(x,y,z); + + float dx,dy,dz; + me->GetRandomPoint(x, y, z, 20, dx, dy, dz); + dz += 20; // so it's in the air, not ground*/ + + Position pos; + if (Unit* EscapeDummy = me->FindNearestCreature(CREATURE_ESCAPE_DUMMY, 30)) + EscapeDummy->GetPosition(&pos); + else + { + me->GetRandomNearPosition(pos, 20); + pos.m_positionZ += 25; + } + + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->GetMotionMaster()->MovePoint(1, pos); + } + } + } else FlyTimer -= diff; + return; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_enslaved_netherwing_drake(Creature* pCreature) +{ + return new mob_enslaved_netherwing_drakeAI(pCreature); +} + +/*##### +# mob_dragonmaw_peon +#####*/ + +struct mob_dragonmaw_peonAI : public ScriptedAI +{ + mob_dragonmaw_peonAI(Creature* c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + bool Tapped; + uint32 PoisonTimer; + + void Reset() + { + PlayerGUID = 0; + Tapped = false; + PoisonTimer = 0; + } + + void SpellHit(Unit* caster, const SpellEntry* spell) + { + if (!caster) + return; + + if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == 40468 && !Tapped) + { + PlayerGUID = caster->GetGUID(); + + Tapped = true; + float x, y, z; + caster->GetClosePoint(x, y, z, me->GetObjectSize()); + + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->MovePoint(1, x, y, z); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id) + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_EAT); + PoisonTimer = 15000; + } + } + + void UpdateAI(const uint32 diff) + { + if (PoisonTimer) + if (PoisonTimer <= diff) + { + if (PlayerGUID) + { + Player* plr = Unit::GetPlayer(PlayerGUID); + if (plr && plr->GetQuestStatus(11020) == QUEST_STATUS_INCOMPLETE) + plr->KilledMonsterCredit(23209, me->GetGUID()); + } + PoisonTimer = 0; + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } else PoisonTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_dragonmaw_peon(Creature* pCreature) +{ + return new mob_dragonmaw_peonAI(pCreature); +} + +/*###### +## npc_drake_dealer_hurlunk +######*/ + +bool GossipHello_npc_drake_dealer_hurlunk(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isVendor() && pPlayer->GetReputationRank(1015) == REP_EXALTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_drake_dealer_hurlunk(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_flanis_swiftwing_and_kagrosh +######*/ + +#define GOSSIP_HSK1 "Take Flanis's Pack" +#define GOSSIP_HSK2 "Take Kagrosh's Pack" + +bool GossipHello_npcs_flanis_swiftwing_and_kagrosh(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(10583) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(30658,1,true)) + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HSK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if (pPlayer->GetQuestStatus(10601) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(30659,1,true)) + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HSK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_flanis_swiftwing_and_kagrosh(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30658, 1, false); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, 30658, 1, true); + pPlayer->PlayerTalkClass->ClearMenus(); + } + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30659, 1, false); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, 30659, 1, true); + pPlayer->PlayerTalkClass->ClearMenus(); + } + } + return true; +} + +/*###### +## npc_murkblood_overseer +######*/ + +#define QUEST_11082 11082 + +#define GOSSIP_HMO "I am here for you, overseer." +#define GOSSIP_SMO1 "How dare you question an overseer of the Dragonmaw!" +#define GOSSIP_SMO2 "Who speaks of me? What are you talking about, broken?" +#define GOSSIP_SMO3 "Continue please." +#define GOSSIP_SMO4 "Who are these bidders?" +#define GOSSIP_SMO5 "Well... yes." + +bool GossipHello_npc_murkblood_overseer(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_11082) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HMO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_murkblood_overseer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + //correct id not known + pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); + pCreature->CastSpell(pPlayer,41121,false); + pPlayer->AreaExploredOrEventHappens(QUEST_11082); + break; + } + return true; +} + +/*###### +## npc_neltharaku +######*/ + +#define GOSSIP_HN "I am listening, dragon" +#define GOSSIP_SN1 "But you are dragons! How could orcs do this to you?" +#define GOSSIP_SN2 "Your mate?" +#define GOSSIP_SN3 "I have battled many beasts, dragon. I will help you." + +bool GossipHello_npc_neltharaku(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(10814) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(10613, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_neltharaku(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(10614, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(10615, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(10616, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(10814); + break; + } + return true; +} + +/*###### +## npc_oronok +######*/ + +#define GOSSIP_ORONOK1 "I am ready to hear your story, Oronok." +#define GOSSIP_ORONOK2 "How do I find the cipher?" +#define GOSSIP_ORONOK3 "How do you know all of this?" +#define GOSSIP_ORONOK4 "Yet what? What is it, Oronok?" +#define GOSSIP_ORONOK5 "Continue, please." +#define GOSSIP_ORONOK6 "So what of the cipher now? And your boys?" +#define GOSSIP_ORONOK7 "I will find your boys and the cipher, Oronok." + +bool GossipHello_npc_oronok_tornheart(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (pPlayer->GetQuestStatus(10519) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(10312, pCreature->GetGUID()); + }else + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_oronok_tornheart(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(10313, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(10314, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(10315, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(10316, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(10317, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(10318, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(10519); + break; + } + return true; +} + +/*#### +# npc_karynaku +####*/ + +enum eKarynaku +{ + QUEST_ALLY_OF_NETHER = 10870, + + TAXI_PATH_ID = 649 +}; + +bool QuestAccept_npc_karynaku(Player* pPlayer, Creature* /*pCreature*/, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_ALLY_OF_NETHER) + pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID); //pPlayer->ActivateTaxiPathTo(649); + + return true; +} + +/*#### +# npc_overlord_morghor +####*/ + +#define QUEST_LORD_ILLIDAN_STORMRAGE 11108 + +#define C_ILLIDAN 22083 +#define C_YARZILL 23141 + +#define SPELL_ONE 39990 // Red Lightning Bolt +#define SPELL_TWO 41528 // Mark of Stormrage +#define SPELL_THREE 40216 // Dragonaw Faction +#define SPELL_FOUR 42016 // Dragonaw Trasform + +#define OVERLORD_SAY_1 -1100206 +#define OVERLORD_SAY_2 -1100207 +#define OVERLORD_SAY_3 -1100208 //signed for 28315 +#define OVERLORD_SAY_4 -1100209 +#define OVERLORD_SAY_5 -1100210 +#define OVERLORD_SAY_6 -1100211 + +#define OVERLORD_YELL_1 -1000212 +#define OVERLORD_YELL_2 -1000213 + +#define LORD_ILLIDAN_SAY_1 -1100214 +#define LORD_ILLIDAN_SAY_2 -1100215 +#define LORD_ILLIDAN_SAY_3 -1100216 +#define LORD_ILLIDAN_SAY_4 -1100217 +#define LORD_ILLIDAN_SAY_5 -1100218 +#define LORD_ILLIDAN_SAY_6 -1100219 +#define LORD_ILLIDAN_SAY_7 -1100220 + +#define YARZILL_THE_MERC_SAY -1100221 + +struct npc_overlord_morghorAI : public ScriptedAI +{ + npc_overlord_morghorAI(Creature *c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + uint64 IllidanGUID; + + uint32 ConversationTimer; + uint32 Step; + + bool Event; + + void Reset() + { + PlayerGUID = 0; + IllidanGUID = 0; + + ConversationTimer = 0; + Step = 0; + + Event = false; + me->SetUInt32Value(UNIT_NPC_FLAGS, 2); + } + + void StartEvent() + { + me->SetUInt32Value(UNIT_NPC_FLAGS, 0); + me->SetUInt32Value(UNIT_FIELD_BYTES_1,0); + Unit* Illidan = me->SummonCreature(C_ILLIDAN, -5107.83, 602.584, 85.2393, 4.92598, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Illidan) + { + IllidanGUID = Illidan->GetGUID(); + Illidan->SetVisibility(VISIBILITY_OFF); + } + if (PlayerGUID) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer) + DoScriptText(OVERLORD_SAY_1, me, pPlayer); + } + ConversationTimer = 4200; + Step = 0; + Event = true; + } + + uint32 NextStep(uint32 Step) + { + Unit* plr = Unit::GetUnit((*me), PlayerGUID); + + Unit* Illi = Unit::GetUnit((*me), IllidanGUID); + + if (!plr || !Illi) + { + EnterEvadeMode(); + return 0; + } + + switch(Step) + { + case 0: return 0; break; + case 1: me->GetMotionMaster()->MovePoint(0, -5104.41, 595.297, 85.6838); return 9000; break; + case 2: DoScriptText(OVERLORD_YELL_1, me, plr); return 4500; break; + case 3: me->SetInFront(plr); return 3200; break; + case 4: DoScriptText(OVERLORD_SAY_2, me, plr); return 2000; break; + case 5: Illi->SetVisibility(VISIBILITY_ON); + Illi->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); return 350; break; + case 6: + Illi->CastSpell(Illi, SPELL_ONE, true); + Illi->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + me->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); + return 2000; break; + case 7: DoScriptText(OVERLORD_YELL_2, me); return 4500; break; + case 8: me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); return 2500; break; + case 9: DoScriptText(OVERLORD_SAY_3, me); return 6500; break; + case 10: DoScriptText(LORD_ILLIDAN_SAY_1, Illi); return 5000; break; + case 11: DoScriptText(OVERLORD_SAY_4, me, plr); return 6000; break; + case 12: DoScriptText(LORD_ILLIDAN_SAY_2, Illi); return 5500; break; + case 13: DoScriptText(LORD_ILLIDAN_SAY_3, Illi); return 4000; break; + case 14: Illi->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); return 1500; break; + case 15: DoScriptText(LORD_ILLIDAN_SAY_4, Illi); return 1500; break; + case 16: + if (plr) + { + Illi->CastSpell(plr, SPELL_TWO, true); + plr->RemoveAurasDueToSpell(SPELL_THREE); + plr->RemoveAurasDueToSpell(SPELL_FOUR); + return 5000; + }else{ + CAST_PLR(plr)->FailQuest(QUEST_LORD_ILLIDAN_STORMRAGE); Step = 30; return 100; + } + break; + case 17: DoScriptText(LORD_ILLIDAN_SAY_5, Illi); return 5000; break; + case 18: DoScriptText(LORD_ILLIDAN_SAY_6, Illi); return 5000; break; + case 19: DoScriptText(LORD_ILLIDAN_SAY_7, Illi); return 5000; break; + case 20: + Illi->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + Illi->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + return 500; break; + case 21: DoScriptText(OVERLORD_SAY_5, me); return 500; break; + case 22: + Illi->SetVisibility(VISIBILITY_OFF); + Illi->setDeathState(JUST_DIED); + return 1000; break; + case 23: me->SetUInt32Value(UNIT_FIELD_BYTES_1,0); return 2000; break; + case 24: me->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); return 5000; break; + case 25: DoScriptText(OVERLORD_SAY_6, me); return 2000; break; + case 26: + if (plr) + CAST_PLR(plr)->GroupEventHappens(QUEST_LORD_ILLIDAN_STORMRAGE, me); + return 6000; break; + case 27: + { + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + if (Yarzill) + Yarzill->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); + return 500; } + break; + case 28: + plr->RemoveAurasDueToSpell(SPELL_TWO); + plr->RemoveAurasDueToSpell(41519); + plr->CastSpell(plr, SPELL_THREE, true); + plr->CastSpell(plr, SPELL_FOUR, true); + return 1000; break; + case 29: + { + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + if (Yarzill) + DoScriptText(YARZILL_THE_MERC_SAY, Yarzill, plr); + return 5000; } + break; + case 30: + { + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + if (Yarzill) + Yarzill->SetUInt64Value(UNIT_FIELD_TARGET, 0); + return 5000; } + break; + case 31: + { + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + if (Yarzill) + Yarzill->CastSpell(plr, 41540, true); + return 1000;} +break; + case 32: me->GetMotionMaster()->MovePoint(0, -5085.77, 577.231, 86.6719); return 5000; break; + case 33: Reset(); return 100; break; + + default : return 0; + } + } + + void UpdateAI(const uint32 diff) + { + if (!ConversationTimer) + return; + + if (ConversationTimer <= diff) + { + if (Event && IllidanGUID && PlayerGUID) + { + ConversationTimer = NextStep(++Step); + } + } else ConversationTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_overlord_morghor(Creature* pCreature) +{ +return new npc_overlord_morghorAI(pCreature); +} + +bool QuestAccept_npc_overlord_morghor(Player* pPlayer, Creature* pCreature, const Quest *_Quest) +{ + if (_Quest->GetQuestId() == QUEST_LORD_ILLIDAN_STORMRAGE) + { + CAST_AI(npc_overlord_morghorAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); + CAST_AI(npc_overlord_morghorAI, pCreature->AI())->StartEvent(); + return true; + } + return false; +} + +/*#### +# npc_earthmender_wilda +####*/ + +enum eEarthmender +{ + SAY_WIL_START = -1000381, + SAY_WIL_AGGRO1 = -1000382, + SAY_WIL_AGGRO2 = -1000383, + SAY_WIL_PROGRESS1 = -1000384, + SAY_WIL_PROGRESS2 = -1000385, + SAY_WIL_FIND_EXIT = -1000386, + SAY_WIL_PROGRESS4 = -1000387, + SAY_WIL_PROGRESS5 = -1000388, + SAY_WIL_JUST_AHEAD = -1000389, + SAY_WIL_END = -1000390, + + SPELL_CHAIN_LIGHTNING = 16006, + SPELL_EARTHBING_TOTEM = 15786, + SPELL_FROST_SHOCK = 12548, + SPELL_HEALING_WAVE = 12491, + + QUEST_ESCAPE_COILSCAR = 10451, + NPC_COILSKAR_ASSASSIN = 21044, + FACTION_EARTHEN = 1726 //guessed +}; + +struct npc_earthmender_wildaAI : public npc_escortAI +{ + npc_earthmender_wildaAI(Creature* pCreature) : npc_escortAI(pCreature) { } + + uint32 m_uiHealingTimer; + + void Reset() + { + m_uiHealingTimer = 0; + } + + void WaypointReached(uint32 uiPointId) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(uiPointId) + { + case 13: + DoScriptText(SAY_WIL_PROGRESS1, me, pPlayer); + DoSpawnAssassin(); + break; + case 14: + DoSpawnAssassin(); + break; + case 15: + DoScriptText(SAY_WIL_FIND_EXIT, me, pPlayer); + break; + case 19: + DoRandomSay(); + break; + case 20: + DoSpawnAssassin(); + break; + case 26: + DoRandomSay(); + break; + case 27: + DoSpawnAssassin(); + break; + case 33: + DoRandomSay(); + break; + case 34: + DoSpawnAssassin(); + break; + case 37: + DoRandomSay(); + break; + case 38: + DoSpawnAssassin(); + break; + case 39: + DoScriptText(SAY_WIL_JUST_AHEAD, me, pPlayer); + break; + case 43: + DoRandomSay(); + break; + case 44: + DoSpawnAssassin(); + break; + case 50: + DoScriptText(SAY_WIL_END, me, pPlayer); + + if (Player* pPlayer = GetPlayerForEscort()) + pPlayer->GroupEventHappens(QUEST_ESCAPE_COILSCAR, me); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_COILSKAR_ASSASSIN) + pSummoned->AI()->AttackStart(me); + } + + //this is very unclear, random say without no real relevance to script/event + void DoRandomSay() + { + DoScriptText(RAND(SAY_WIL_PROGRESS2,SAY_WIL_PROGRESS4,SAY_WIL_PROGRESS5), me); + } + + void DoSpawnAssassin() + { + //unknown where they actually appear + DoSummon(NPC_COILSKAR_ASSASSIN, me, 15.0f, 5000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT); + } + + void Aggro(Unit* pWho) + { + //don't always use + if (rand()%5) + return; + + //only aggro text if not player + if (pWho->GetTypeId() != TYPEID_PLAYER) + { + //appears to be random + if (urand(0,1)) + DoScriptText(RAND(SAY_WIL_AGGRO1, SAY_WIL_AGGRO2), pWho); + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + //TODO: add more abilities + if (me->GetHealth()*100 / me->GetMaxHealth() <= 30) + { + if (m_uiHealingTimer <= uiDiff) + { + DoCast(me, SPELL_HEALING_WAVE); + m_uiHealingTimer = 15000; + } + else + m_uiHealingTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_earthmender_wilda(Creature* pCreature) +{ + return new npc_earthmender_wildaAI(pCreature); +} + +bool QuestAccept_npc_earthmender_wilda(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_ESCAPE_COILSCAR) + { + DoScriptText(SAY_WIL_START, pCreature, pPlayer); + pCreature->setFaction(FACTION_EARTHEN); + + if (npc_earthmender_wildaAI* pEscortAI = CAST_AI(npc_earthmender_wildaAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); + } + return true; +} + +/*##### +# Quest: Battle of the crimson watch +#####*/ + +/* ContentData +Battle of the crimson watch - creatures, gameobjects and defines +mob_illidari_spawn : Adds that are summoned in the Crimson Watch battle. +mob_torloth_the_magnificent : Final Creature that players have to face before quest is completed +npc_lord_illidan_stormrage : Creature that controls the event. +go_crystal_prison : GameObject that begins the event and hands out quest +EndContentData */ + +#define END_TEXT -1000366 //signed for 10646 + +#define QUEST_BATTLE_OF_THE_CRIMSON_WATCH 10781 +#define EVENT_AREA_RADIUS 65 //65yds +#define EVENT_COOLDOWN 30000 //in ms. appear after event completed or failed (should be = Adds despawn time) + +struct TorlothCinematic +{ + int32 TextId; + uint32 pCreature, Timer; +}; + +// Creature 0 - Torloth, 1 - Illidan +static TorlothCinematic TorlothAnim[]= +{ + {-1000367, 0, 2000}, + {-1000368, 1, 7000}, + {-1000369, 0, 3000}, + {NULL, 0, 2000}, // Torloth stand + {-1000370, 0, 1000}, + {NULL, 0, 3000}, + {NULL, 0, NULL} +}; + +struct Location +{ + float x, y, z, o; +}; + +//Cordinates for Spawns +static Location SpawnLocation[]= +{ + //Cords used for: + {-4615.8556, 1342.2532, 139.9, 1.612},//Illidari Soldier + {-4598.9365, 1377.3182, 139.9, 3.917},//Illidari Soldier + {-4598.4697, 1360.8999, 139.9, 2.427},//Illidari Soldier + {-4589.3599, 1369.1061, 139.9, 3.165},//Illidari Soldier + {-4608.3477, 1386.0076, 139.9, 4.108},//Illidari Soldier + {-4633.1889, 1359.8033, 139.9, 0.949},//Illidari Soldier + {-4623.5791, 1351.4574, 139.9, 0.971},//Illidari Soldier + {-4607.2988, 1351.6099, 139.9, 2.416},//Illidari Soldier + {-4633.7764, 1376.0417, 139.9, 5.608},//Illidari Soldier + {-4600.2461, 1369.1240, 139.9, 3.056},//Illidari Mind Breaker + {-4631.7808, 1367.9459, 139.9, 0.020},//Illidari Mind Breaker + {-4600.2461, 1369.1240, 139.9, 3.056},//Illidari Highlord + {-4631.7808, 1367.9459, 139.9, 0.020},//Illidari Highlord + {-4615.5586, 1353.0031, 139.9, 1.540},//Illidari Highlord + {-4616.4736, 1384.2170, 139.9, 4.971},//Illidari Highlord + {-4627.1240, 1378.8752, 139.9, 2.544} //Torloth The Magnificent +}; + +struct WaveData +{ + uint8 SpawnCount, UsedSpawnPoint; + uint32 CreatureId, SpawnTimer,YellTimer; + int32 WaveTextId; +}; + +static WaveData WavesInfo[]= +{ + {9, 0, 22075, 10000, 7000, -1000371}, //Illidari Soldier + {2, 9, 22074, 10000, 7000, -1000372}, //Illidari Mind Breaker + {4, 11, 19797, 10000, 7000, -1000373}, //Illidari Highlord + {1, 15, 22076, 10000, 7000, -1000374} //Torloth The Magnificent +}; + +struct SpawnSpells +{ + uint32 Timer1, Timer2, SpellId; +}; + +static SpawnSpells SpawnCast[]= +{ + {10000, 15000, 35871}, // Illidari Soldier Cast - Spellbreaker + {10000, 10000, 38985}, // Illidari Mind Breake Cast - Focused Bursts + {35000, 35000, 22884}, // Illidari Mind Breake Cast - Psychic Scream + {20000, 20000, 17194}, // Illidari Mind Breake Cast - Mind Blast + {8000, 15000, 38010}, // Illidari Highlord Cast - Curse of Flames + {12000, 20000, 16102}, // Illidari Highlord Cast - Flamestrike + {10000, 15000, 15284}, // Torloth the Magnificent Cast - Cleave + {18000, 20000, 39082}, // Torloth the Magnificent Cast - Shadowfury + {25000, 28000, 33961} // Torloth the Magnificent Cast - Spell Reflection +}; + +/*###### +# mob_illidari_spawn +######*/ + +struct mob_illidari_spawnAI : public ScriptedAI +{ + mob_illidari_spawnAI(Creature* c) : ScriptedAI(c) {} + + uint64 LordIllidanGUID; + uint32 SpellTimer1, SpellTimer2, SpellTimer3; + bool Timers; + + void Reset() + { + LordIllidanGUID = 0; + Timers = false; + } + + void EnterCombat(Unit* /*who*/) {} + void JustDied(Unit* slayer); + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!Timers) + { + if (me->GetEntry() == 22075)//Illidari Soldier + { + SpellTimer1 = SpawnCast[0].Timer1 + (rand()%4 * 1000); + } + if (me->GetEntry() == 22074)//Illidari Mind Breaker + { + SpellTimer1 = SpawnCast[1].Timer1 + (rand()%10 * 1000); + SpellTimer2 = SpawnCast[2].Timer1 + (rand()%4 * 1000); + SpellTimer3 = SpawnCast[3].Timer1 + (rand()%4 * 1000); + } + if (me->GetEntry() == 19797)// Illidari Highlord + { + SpellTimer1 = SpawnCast[4].Timer1 + (rand()%4 * 1000); + SpellTimer2 = SpawnCast[5].Timer1 + (rand()%4 * 1000); + } + Timers = true; + } + //Illidari Soldier + if (me->GetEntry() == 22075) + { + if (SpellTimer1 <= diff) + { + DoCast(me->getVictim(), SpawnCast[0].SpellId);//Spellbreaker + SpellTimer1 = SpawnCast[0].Timer2 + (rand()%5 * 1000); + } else SpellTimer1 -= diff; + } + //Illidari Mind Breaker + if (me->GetEntry() == 22074) + { + if (SpellTimer1 <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SpawnCast[1].SpellId); //Focused Bursts + SpellTimer1 = SpawnCast[1].Timer2 + (rand()%5 * 1000); + } else SpellTimer1 = 2000; + } + } else SpellTimer1 -= diff; + + if (SpellTimer2 <= diff) + { + DoCast(me->getVictim(), SpawnCast[2].SpellId);//Psychic Scream + SpellTimer2 = SpawnCast[2].Timer2 + (rand()%13 * 1000); + } else SpellTimer2 -= diff; + + if (SpellTimer3 <= diff) + { + DoCast(me->getVictim(), SpawnCast[3].SpellId);//Mind Blast + SpellTimer3 = SpawnCast[3].Timer2 + (rand()%8 * 1000); + } else SpellTimer3 -= diff; + } + //Illidari Highlord + if (me->GetEntry() == 19797) + { + if (SpellTimer1 <= diff) + { + DoCast(me->getVictim(), SpawnCast[4].SpellId);//Curse Of Flames + SpellTimer1 = SpawnCast[4].Timer2 + (rand()%10 * 1000); + } else SpellTimer1 -= diff; + + if (SpellTimer2 <= diff) + { + DoCast(me->getVictim(), SpawnCast[5].SpellId);//Flamestrike + SpellTimer2 = SpawnCast[5].Timer2 + (rand()%7 * 13000); + } else SpellTimer2 -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +# mob_torloth_the_magnificent +#####*/ + +struct mob_torloth_the_magnificentAI : public ScriptedAI +{ + mob_torloth_the_magnificentAI(Creature* c) : ScriptedAI(c) {} + + uint32 AnimationTimer, SpellTimer1, SpellTimer2, SpellTimer3; + + uint8 AnimationCount; + + uint64 LordIllidanGUID; + uint64 AggroTargetGUID; + + bool Timers; + + void Reset() + { + AnimationTimer = 4000; + AnimationCount = 0; + LordIllidanGUID = 0; + AggroTargetGUID = 0; + Timers = false; + + me->addUnitState(UNIT_STAT_ROOT); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + } + + void EnterCombat(Unit* /*who*/){} + + void HandleAnimation() + { + Creature* pCreature = me; + + if (TorlothAnim[AnimationCount].pCreature == 1) + { + pCreature = (Unit::GetCreature(*me, LordIllidanGUID)); + + if (!pCreature) + return; + } + + if (TorlothAnim[AnimationCount].TextId) + DoScriptText(TorlothAnim[AnimationCount].TextId, pCreature); + + AnimationTimer = TorlothAnim[AnimationCount].Timer; + + switch(AnimationCount) + { + case 0: + me->SetUInt32Value(UNIT_FIELD_BYTES_1,8); + break; + case 3: + me->RemoveFlag(UNIT_FIELD_BYTES_1,8); + break; + case 5: + if (Player* AggroTarget = (Unit::GetPlayer(AggroTargetGUID))) + { + me->SetUInt64Value(UNIT_FIELD_TARGET, AggroTarget->GetGUID()); + me->AddThreat(AggroTarget, 1); + me->HandleEmoteCommand(EMOTE_ONESHOT_POINT); + } + break; + case 6: + if (Player* AggroTarget = (Unit::GetPlayer(AggroTargetGUID))) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->clearUnitState(UNIT_STAT_ROOT); + + float x, y, z; + AggroTarget->GetPosition(x,y,z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + } + break; + } + ++AnimationCount; + } + + void UpdateAI(const uint32 diff) + { + if (AnimationTimer) + { + if (AnimationTimer <= diff) + { + HandleAnimation(); + } else AnimationTimer -= diff; + } + + if (AnimationCount < 6) + { + me->CombatStop(); + } else if (!Timers) + { + + SpellTimer1 = SpawnCast[6].Timer1; + SpellTimer2 = SpawnCast[7].Timer1; + SpellTimer3 = SpawnCast[8].Timer1; + Timers = true; + } + + if (Timers) + { + if (SpellTimer1 <= diff) + { + DoCast(me->getVictim(), SpawnCast[6].SpellId);//Cleave + SpellTimer1 = SpawnCast[6].Timer2 + (rand()%10 * 1000); + } else SpellTimer1 -= diff; + + if (SpellTimer2 <= diff) + { + DoCast(me->getVictim(), SpawnCast[7].SpellId);//Shadowfury + SpellTimer2 = SpawnCast[7].Timer2 + (rand()%5 * 1000); + } else SpellTimer2 -= diff; + + if (SpellTimer3 <= diff) + { + DoCast(me, SpawnCast[8].SpellId); + SpellTimer3 = SpawnCast[8].Timer2 + (rand()%7 * 1000);//Spell Reflection + } else SpellTimer3 -= diff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* slayer) + { + if (slayer) + switch(slayer->GetTypeId()) + { + case TYPEID_UNIT: + if (Unit *owner = slayer->GetOwner()) + if (owner->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(owner)->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, me); + break; + + case TYPEID_PLAYER: + CAST_PLR(slayer)->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, me); + break; + } + + if (Creature* LordIllidan = (Unit::GetCreature(*me, LordIllidanGUID))) + { + DoScriptText(END_TEXT, LordIllidan, slayer); + LordIllidan->AI()->EnterEvadeMode(); + } + } +}; + +/*##### +# npc_lord_illidan_stormrage +#####*/ + +struct npc_lord_illidan_stormrageAI : public ScriptedAI +{ + npc_lord_illidan_stormrageAI(Creature* c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + + uint32 WaveTimer; + uint32 AnnounceTimer; + + int8 LiveCount; + uint8 WaveCount; + + bool EventStarted; + bool Announced; + bool Failed; + + void Reset() + { + PlayerGUID = 0; + + WaveTimer = 10000; + AnnounceTimer = 7000; + LiveCount = 0; + WaveCount = 0; + + EventStarted = false; + Announced = false; + Failed = false; + + me->SetVisibility(VISIBILITY_OFF); + } + + void EnterCombat(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + + void SummonNextWave() + { + uint8 count = WavesInfo[WaveCount].SpawnCount; + uint8 locIndex = WavesInfo[WaveCount].UsedSpawnPoint; + srand(time(NULL));//initializing random seed + uint8 FelguardCount = 0; + uint8 DreadlordCount = 0; + + for (uint8 i = 0; i < count; ++i) + { + Creature* Spawn = NULL; + float X = SpawnLocation[locIndex + i].x; + float Y = SpawnLocation[locIndex + i].y; + float Z = SpawnLocation[locIndex + i].z; + float O = SpawnLocation[locIndex + i].o; + Spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, X, Y, Z, O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + ++LiveCount; + + if (Spawn) + { + Spawn->LoadCreaturesAddon(); + + if (WaveCount == 0)//1 Wave + { + if (rand()%3 == 1 && FelguardCount<2) + { + Spawn->SetDisplayId(18654); + ++FelguardCount; + } + else if (DreadlordCount < 3) + { + Spawn->SetDisplayId(19991); + ++DreadlordCount; + } + else if (FelguardCount<2) + { + Spawn->SetDisplayId(18654); + ++FelguardCount; + } + } + + if (WaveCount < 3)//1-3 Wave + { + if (PlayerGUID) + { + if (Player* pTarget = Unit::GetPlayer(PlayerGUID)) + { + float x, y, z; + pTarget->GetPosition(x,y,z); + Spawn->GetMotionMaster()->MovePoint(0,x, y, z); + } + } + CAST_AI(mob_illidari_spawnAI, Spawn->AI())->LordIllidanGUID = me->GetGUID(); + } + + if (WavesInfo[WaveCount].CreatureId == 22076) // Torloth + { + CAST_AI(mob_torloth_the_magnificentAI, Spawn->AI())->LordIllidanGUID = me->GetGUID(); + if (PlayerGUID) + CAST_AI(mob_torloth_the_magnificentAI, Spawn->AI())->AggroTargetGUID = PlayerGUID; + } + } + } + ++WaveCount; + WaveTimer = WavesInfo[WaveCount].SpawnTimer; + AnnounceTimer = WavesInfo[WaveCount].YellTimer; + } + + void CheckEventFail() + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + if (!pPlayer) + return; + + if (Group *EventGroup = pPlayer->GetGroup()) + { + Player* GroupMember; + + uint8 GroupMemberCount = 0; + uint8 DeadMemberCount = 0; + uint8 FailedMemberCount = 0; + + const Group::MemberSlotList members = EventGroup->GetMemberSlots(); + + for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) + { + GroupMember = (Unit::GetPlayer(itr->guid)); + if (!GroupMember) + continue; + if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) + { + GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); + GroupMember->SetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, QUEST_STATUS_NONE); + ++FailedMemberCount; + } + ++GroupMemberCount; + + if (GroupMember->isDead()) + { + ++DeadMemberCount; + } + } + + if (GroupMemberCount == FailedMemberCount) + { + Failed = true; + } + + if (GroupMemberCount == DeadMemberCount) + { + for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) + { + GroupMember = Unit::GetPlayer(itr->guid); + + if (GroupMember && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) + { + GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); + GroupMember->SetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, QUEST_STATUS_NONE); + } + } + Failed = true; + } + } else if (pPlayer->isDead() || !pPlayer->IsWithinDistInMap(me, EVENT_AREA_RADIUS)) + { + pPlayer->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); + Failed = true; + } + } + + void LiveCounter() + { + --LiveCount; + if (!LiveCount) + Announced = false; + } + + void UpdateAI(const uint32 diff) + { + if (!PlayerGUID || !EventStarted) + return; + + if (!LiveCount && WaveCount < 4) + { + if (!Announced && AnnounceTimer <= diff) + { + DoScriptText(WavesInfo[WaveCount].WaveTextId, me); + Announced = true; + } else AnnounceTimer -= diff; + + if (WaveTimer <= diff) + { + SummonNextWave(); + } else WaveTimer -= diff; + } + CheckEventFail(); + + if (Failed) + EnterEvadeMode(); + } +}; + +void mob_illidari_spawnAI::JustDied(Unit * /*slayer*/) +{ + me->RemoveCorpse(); + if (Creature* LordIllidan = (Unit::GetCreature(*me, LordIllidanGUID))) + if (LordIllidan) + CAST_AI(npc_lord_illidan_stormrageAI, LordIllidan->AI())->LiveCounter(); +} + +/*##### +# go_crystal_prison +######*/ + +bool GOQuestAccept_GO_crystal_prison(Player* plr, GameObject* /*go*/, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_BATTLE_OF_THE_CRIMSON_WATCH) + { + Creature* Illidan = plr->FindNearestCreature(22083, 50); + + if (Illidan && !CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted) + { + CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->PlayerGUID = plr->GetGUID(); + CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->LiveCount = 0; + CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted=true; + } + } + return true; +} + +CreatureAI* GetAI_npc_lord_illidan_stormrage(Creature* c) +{ + return new npc_lord_illidan_stormrageAI(c); +} + +CreatureAI* GetAI_mob_illidari_spawn(Creature* c) +{ + return new mob_illidari_spawnAI(c); +} + +CreatureAI* GetAI_mob_torloth_the_magnificent(Creature* c) +{ + return new mob_torloth_the_magnificentAI(c); +} + +/*#### +# npc_enraged_spirits +####*/ + +/* QUESTS */ +#define QUEST_ENRAGED_SPIRITS_FIRE_EARTH 10458 +#define QUEST_ENRAGED_SPIRITS_AIR 10481 +#define QUEST_ENRAGED_SPIRITS_WATER 10480 + +/* Totem */ +#define ENTRY_TOTEM_OF_SPIRITS 21071 +#define RADIUS_TOTEM_OF_SPIRITS 15 + +/* SPIRITS */ +#define ENTRY_ENRAGED_EARTH_SPIRIT 21050 +#define ENTRY_ENRAGED_FIRE_SPIRIT 21061 +#define ENTRY_ENRAGED_AIR_SPIRIT 21060 +#define ENTRY_ENRAGED_WATER_SPIRIT 21059 + +/* SOULS */ +#define ENTRY_EARTHEN_SOUL 21073 +#define ENTRY_FIERY_SOUL 21097 +#define ENTRY_ENRAGED_AIRY_SOUL 21116 +#define ENTRY_ENRAGED_WATERY_SOUL 21109 // wrong model + +/* SPELL KILLCREDIT - not working!?! - using KilledMonsterCredit */ +#define SPELL_EARTHEN_SOUL_CAPTURED_CREDIT 36108 +#define SPELL_FIERY_SOUL_CAPTURED_CREDIT 36117 +#define SPELL_AIRY_SOUL_CAPTURED_CREDIT 36182 +#define SPELL_WATERY_SOUL_CAPTURED_CREDIT 36171 + +/* KilledMonsterCredit Workaround */ +#define CREDIT_FIRE 21094 +#define CREDIT_WATER 21095 +#define CREDIT_AIR 21096 +#define CREDIT_EARTH 21092 + +/* Captured Spell/Buff */ +#define SPELL_SOUL_CAPTURED 36115 + +/* Factions */ +#define ENRAGED_SOUL_FRIENDLY 35 +#define ENRAGED_SOUL_HOSTILE 14 + +struct npc_enraged_spiritAI : public ScriptedAI +{ + npc_enraged_spiritAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + + void EnterCombat(Unit * /*who*/){} + + void JustDied(Unit* /*killer*/) + { + // always spawn spirit on death + // if totem around + // move spirit to totem and cast kill count + uint32 entry = 0; + uint32 credit = 0; + + switch(me->GetEntry()) { + case ENTRY_ENRAGED_FIRE_SPIRIT: + entry = ENTRY_FIERY_SOUL; + //credit = SPELL_FIERY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_FIRE; + break; + case ENTRY_ENRAGED_EARTH_SPIRIT: + entry = ENTRY_EARTHEN_SOUL; + //credit = SPELL_EARTHEN_SOUL_CAPTURED_CREDIT; + credit = CREDIT_EARTH; + break; + case ENTRY_ENRAGED_AIR_SPIRIT: + entry = ENTRY_ENRAGED_AIRY_SOUL; + //credit = SPELL_AIRY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_AIR; + break; + case ENTRY_ENRAGED_WATER_SPIRIT: + entry = ENTRY_ENRAGED_WATERY_SOUL; + //credit = SPELL_WATERY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_WATER; + break; + } + + // Spawn Soul on Kill ALWAYS! + Creature* Summoned = NULL; + Unit* totemOspirits = NULL; + + if (entry != 0) + Summoned = DoSpawnCreature(entry, 0, 0, 1, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000); + + // FIND TOTEM, PROCESS QUEST + if (Summoned) + { + totemOspirits = me->FindNearestCreature(ENTRY_TOTEM_OF_SPIRITS, RADIUS_TOTEM_OF_SPIRITS); + if (totemOspirits) + { + Summoned->setFaction(ENRAGED_SOUL_FRIENDLY); + Summoned->GetMotionMaster()->MovePoint(0,totemOspirits->GetPositionX(), totemOspirits->GetPositionY(), Summoned->GetPositionZ()); + + Unit* Owner = totemOspirits->GetOwner(); + if (Owner && Owner->GetTypeId() == TYPEID_PLAYER) + // DoCast(Owner, credit); -- not working! + CAST_PLR(Owner)->KilledMonsterCredit(credit, Summoned->GetGUID()); + DoCast(totemOspirits, SPELL_SOUL_CAPTURED); + } + } + } +}; + +CreatureAI* GetAI_npc_enraged_spirit(Creature* pCreature) +{ +return new npc_enraged_spiritAI(pCreature); +} + +/*##### +# +######*/ + +void AddSC_shadowmoon_valley() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_mature_netherwing_drake"; + newscript->GetAI = &GetAI_mob_mature_netherwing_drake; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_enslaved_netherwing_drake"; + newscript->GetAI = &GetAI_mob_enslaved_netherwing_drake; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dragonmaw_peon"; + newscript->GetAI = &GetAI_mob_dragonmaw_peon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_drake_dealer_hurlunk"; + newscript->pGossipHello = &GossipHello_npc_drake_dealer_hurlunk; + newscript->pGossipSelect = &GossipSelect_npc_drake_dealer_hurlunk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npcs_flanis_swiftwing_and_kagrosh"; + newscript->pGossipHello = &GossipHello_npcs_flanis_swiftwing_and_kagrosh; + newscript->pGossipSelect = &GossipSelect_npcs_flanis_swiftwing_and_kagrosh; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_murkblood_overseer"; + newscript->pGossipHello = &GossipHello_npc_murkblood_overseer; + newscript->pGossipSelect = &GossipSelect_npc_murkblood_overseer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_neltharaku"; + newscript->pGossipHello = &GossipHello_npc_neltharaku; + newscript->pGossipSelect = &GossipSelect_npc_neltharaku; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_karynaku"; + newscript->pQuestAccept = &QuestAccept_npc_karynaku; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_oronok_tornheart"; + newscript->pGossipHello = &GossipHello_npc_oronok_tornheart; + newscript->pGossipSelect = &GossipSelect_npc_oronok_tornheart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_overlord_morghor"; + newscript->GetAI = &GetAI_npc_overlord_morghor; + newscript->pQuestAccept = &QuestAccept_npc_overlord_morghor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_earthmender_wilda"; + newscript->GetAI = &GetAI_npc_earthmender_wilda; + newscript->pQuestAccept = &QuestAccept_npc_earthmender_wilda; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lord_illidan_stormrage"; + newscript->GetAI = &GetAI_npc_lord_illidan_stormrage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_crystal_prison"; + newscript->pGOQuestAccept = &GOQuestAccept_GO_crystal_prison; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_illidari_spawn"; + newscript->GetAI = &GetAI_mob_illidari_spawn; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_torloth_the_magnificent"; + newscript->GetAI = &GetAI_mob_torloth_the_magnificent; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_enraged_spirit"; + newscript->GetAI = &GetAI_npc_enraged_spirit; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/shattrath_city.cpp b/src/server/scripts/Outland/shattrath_city.cpp new file mode 100644 index 00000000000..6acc050db48 --- /dev/null +++ b/src/server/scripts/Outland/shattrath_city.cpp @@ -0,0 +1,673 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Shattrath_City +SD%Complete: 100 +SDComment: Quest support: 10004, 10009, 10211, 10231. Flask vendors, Teleport to Caverns of Time +SDCategory: Shattrath City +EndScriptData */ + +/* ContentData +npc_raliq_the_drunk +npc_salsalabim +npc_shattrathflaskvendors +npc_zephyr +npc_kservant +npc_dirty_larry +npc_ishanah +npc_khadgar +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npc_raliq_the_drunk +######*/ + +#define GOSSIP_RALIQ "You owe Sim'salabim money. Hand them over or die!" + +enum eRaliq +{ + SPELL_UPPERCUT = 10966, + QUEST_CRACK_SKULLS = 10009, + FACTION_HOSTILE_RD = 45 +}; + +struct npc_raliq_the_drunkAI : public ScriptedAI +{ + npc_raliq_the_drunkAI(Creature* c) : ScriptedAI(c) + { + m_uiNormFaction = c->getFaction(); + } + + uint32 m_uiNormFaction; + uint32 Uppercut_Timer; + + void Reset() + { + Uppercut_Timer = 5000; + me->RestoreFaction(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Uppercut_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_UPPERCUT); + Uppercut_Timer = 15000; + } else Uppercut_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_raliq_the_drunk(Creature* pCreature) +{ + return new npc_raliq_the_drunkAI (pCreature); +} + +bool GossipHello_npc_raliq_the_drunk(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_RALIQ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(9440, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_raliq_the_drunk(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(FACTION_HOSTILE_RD); + pCreature->AI()->AttackStart(pPlayer); + } + return true; +} + +/*###### +# npc_salsalabim +######*/ + +#define FACTION_HOSTILE_SA 90 +#define FACTION_FRIENDLY_SA 35 +#define QUEST_10004 10004 + +#define SPELL_MAGNETIC_PULL 31705 + +struct npc_salsalabimAI : public ScriptedAI +{ + npc_salsalabimAI(Creature* c) : ScriptedAI(c) {} + + uint32 MagneticPull_Timer; + + void Reset() + { + MagneticPull_Timer = 15000; + me->RestoreFaction(); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetTypeId() == TYPEID_PLAYER) + if ((me->GetHealth()-damage)*100 / me->GetMaxHealth() < 20) + { + CAST_PLR(done_by)->GroupEventHappens(QUEST_10004,me); + damage = 0; + EnterEvadeMode(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (MagneticPull_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MAGNETIC_PULL); + MagneticPull_Timer = 15000; + } else MagneticPull_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_salsalabim(Creature* pCreature) +{ + return new npc_salsalabimAI (pCreature); +} + +bool GossipHello_npc_salsalabim(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE) + { + pCreature->setFaction(FACTION_HOSTILE_SA); + pCreature->AI()->AttackStart(pPlayer); + } + else + { + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + } + return true; +} + +/* +################################################## +Shattrath City Flask Vendors provides flasks to people exalted with 3 factions: +Haldor the Compulsive +Arcanist Xorith +Both sell special flasks for use in Outlands 25man raids only, +purchasable for one Mark of Illidari each +Purchase requires exalted reputation with Scryers/Aldor, Cenarion Expedition and The Sha'tar +################################################## +*/ + +bool GossipHello_npc_shattrathflaskvendors(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->GetEntry() == 23484) + { + // Aldor vendor + if (pCreature->isVendor() && (pPlayer->GetReputationRank(932) == REP_EXALTED) && (pPlayer->GetReputationRank(935) == REP_EXALTED) && (pPlayer->GetReputationRank(942) == REP_EXALTED)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + pPlayer->SEND_GOSSIP_MENU(11085, pCreature->GetGUID()); + } + else + { + pPlayer->SEND_GOSSIP_MENU(11083, pCreature->GetGUID()); + } + } + + if (pCreature->GetEntry() == 23483) + { + // Scryers vendor + if (pCreature->isVendor() && (pPlayer->GetReputationRank(934) == REP_EXALTED) && (pPlayer->GetReputationRank(935) == REP_EXALTED) && (pPlayer->GetReputationRank(942) == REP_EXALTED)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + pPlayer->SEND_GOSSIP_MENU(11085, pCreature->GetGUID()); + } + else + { + pPlayer->SEND_GOSSIP_MENU(11084, pCreature->GetGUID()); + } + } + + return true; +} + +bool GossipSelect_npc_shattrathflaskvendors(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +# npc_zephyr +######*/ + +#define GOSSIP_HZ "Take me to the Caverns of Time." + +bool GossipHello_npc_zephyr(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetReputationRank(989) >= REP_REVERED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HZ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_zephyr(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + pPlayer->CastSpell(pPlayer,37778,false); + + return true; +} + +/*###### +# npc_kservant +######*/ + +#define SAY1 -1000234 +#define WHISP1 -1000235 +#define WHISP2 -1000236 +#define WHISP3 -1000237 +#define WHISP4 -1000238 +#define WHISP5 -1000239 +#define WHISP6 -1000240 +#define WHISP7 -1000241 +#define WHISP8 -1000242 +#define WHISP9 -1000243 +#define WHISP10 -1000244 +#define WHISP11 -1000245 +#define WHISP12 -1000246 +#define WHISP13 -1000247 +#define WHISP14 -1000248 +#define WHISP15 -1000249 +#define WHISP16 -1000250 +#define WHISP17 -1000251 +#define WHISP18 -1000252 +#define WHISP19 -1000253 +#define WHISP20 -1000254 +#define WHISP21 -1000255 + +struct npc_kservantAI : public npc_escortAI +{ +public: + npc_kservantAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 0: DoScriptText(SAY1, me, pPlayer); break; + case 4: DoScriptText(WHISP1, me, pPlayer); break; + case 6: DoScriptText(WHISP2, me, pPlayer); break; + case 7: DoScriptText(WHISP3, me, pPlayer); break; + case 8: DoScriptText(WHISP4, me, pPlayer); break; + case 17: DoScriptText(WHISP5, me, pPlayer); break; + case 18: DoScriptText(WHISP6, me, pPlayer); break; + case 19: DoScriptText(WHISP7, me, pPlayer); break; + case 33: DoScriptText(WHISP8, me, pPlayer); break; + case 34: DoScriptText(WHISP9, me, pPlayer); break; + case 35: DoScriptText(WHISP10, me, pPlayer); break; + case 36: DoScriptText(WHISP11, me, pPlayer); break; + case 43: DoScriptText(WHISP12, me, pPlayer); break; + case 44: DoScriptText(WHISP13, me, pPlayer); break; + case 49: DoScriptText(WHISP14, me, pPlayer); break; + case 50: DoScriptText(WHISP15, me, pPlayer); break; + case 51: DoScriptText(WHISP16, me, pPlayer); break; + case 52: DoScriptText(WHISP17, me, pPlayer); break; + case 53: DoScriptText(WHISP18, me, pPlayer); break; + case 54: DoScriptText(WHISP19, me, pPlayer); break; + case 55: DoScriptText(WHISP20, me, pPlayer); break; + case 56: DoScriptText(WHISP21, me, pPlayer); + if (pPlayer) + pPlayer->GroupEventHappens(10211,me); + break; + } + } + + void MoveInLineOfSight(Unit* pWho) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + if (pWho->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(pWho)->GetQuestStatus(10211) == QUEST_STATUS_INCOMPLETE) + { + float Radius = 10.0; + if (me->IsWithinDistInMap(pWho, Radius)) + { + Start(false, false, pWho->GetGUID()); + } + } + } + } + + void Reset() {} +}; +CreatureAI* GetAI_npc_kservantAI(Creature* pCreature) +{ + return new npc_kservantAI(pCreature); +} + +/*###### +# npc_dirty_larry +######*/ + +#define GOSSIP_BOOK "Ezekiel said that you might have a certain book..." + +#define SAY_1 -1000274 +#define SAY_2 -1000275 +#define SAY_3 -1000276 +#define SAY_4 -1000277 +#define SAY_5 -1000278 +#define SAY_GIVEUP -1000279 + +#define QUEST_WBI 10231 +#define NPC_CREEPJACK 19726 +#define NPC_MALONE 19725 + +struct npc_dirty_larryAI : public ScriptedAI +{ + npc_dirty_larryAI(Creature* c) : ScriptedAI(c) {} + + bool Event; + bool Attack; + bool Done; + + uint64 PlayerGUID; + + uint32 SayTimer; + uint32 Step; + + void Reset() + { + Event = false; + Attack = false; + Done = false; + + PlayerGUID = 0; + SayTimer = 0; + Step = 0; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->setFaction(1194); + Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); + if (Creepjack) + { + CAST_CRE(Creepjack)->AI()->EnterEvadeMode(); + Creepjack->setFaction(1194); + Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); + if (Malone) + { + CAST_CRE(Malone)->AI()->EnterEvadeMode(); + Malone->setFaction(1194); + Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + uint32 NextStep(uint32 Step) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + switch(Step) + { + case 0:{ me->SetInFront(pPlayer); + Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); + if (Creepjack) + Creepjack->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); + if (Malone) + Malone->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); }return 2000; + case 1: DoScriptText(SAY_1, me, pPlayer); return 3000; + case 2: DoScriptText(SAY_2, me, pPlayer); return 5000; + case 3: DoScriptText(SAY_3, me, pPlayer); return 2000; + case 4: DoScriptText(SAY_4, me, pPlayer); return 2000; + case 5: DoScriptText(SAY_5, me, pPlayer); return 2000; + case 6: Attack = true; return 2000; + default: return 0; + } + } + + void EnterCombat(Unit* /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (SayTimer <= diff) + { + if (Event) + SayTimer = NextStep(++Step); + } else SayTimer -= diff; + + if (Attack) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pPlayer) + { + Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); + if (Creepjack) + { + Creepjack->Attack(pPlayer, true); + Creepjack->setFaction(14); + Creepjack->GetMotionMaster()->MoveChase(pPlayer); + Creepjack->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); + if (Malone) + { + Malone->Attack(pPlayer, true); + Malone->setFaction(14); + Malone->GetMotionMaster()->MoveChase(pPlayer); + Malone->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + DoStartMovement(pPlayer); + AttackStart(pPlayer); + } + Attack = false; + } + + if ((me->GetHealth()*100)/me->GetMaxHealth() < 5 && !Done) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAllAuras(); + + Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); + if (Creepjack) + { + CAST_CRE(Creepjack)->AI()->EnterEvadeMode(); + Creepjack->setFaction(1194); + Creepjack->GetMotionMaster()->MoveTargetedHome(); + Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); + if (Malone) + { + CAST_CRE(Malone)->AI()->EnterEvadeMode(); + Malone->setFaction(1194); + Malone->GetMotionMaster()->MoveTargetedHome(); + Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + me->setFaction(1194); + Done = true; + DoScriptText(SAY_GIVEUP, me, NULL); + me->DeleteThreatList(); + me->CombatStop(); + me->GetMotionMaster()->MoveTargetedHome(); + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer) + CAST_PLR(pPlayer)->GroupEventHappens(QUEST_WBI, me); + } + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_npc_dirty_larry(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_WBI) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BOOK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_dirty_larry(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + CAST_AI(npc_dirty_larryAI, pCreature->AI())->Event = true; + CAST_AI(npc_dirty_larryAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); + pPlayer->CLOSE_GOSSIP_MENU(); + } + + return true; +} + +CreatureAI* GetAI_npc_dirty_larryAI(Creature* pCreature) +{ + return new npc_dirty_larryAI (pCreature); +} + +/*###### +# npc_ishanah +######*/ + +#define ISANAH_GOSSIP_1 "Who are the Sha'tar?" +#define ISANAH_GOSSIP_2 "Isn't Shattrath a draenei city? Why do you allow others here?" + +bool GossipHello_npc_ishanah(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_ishanah(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + pPlayer->SEND_GOSSIP_MENU(9458, pCreature->GetGUID()); + else if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + pPlayer->SEND_GOSSIP_MENU(9459, pCreature->GetGUID()); + + return true; +} + +/*###### +# npc_khadgar +######*/ + +#define KHADGAR_GOSSIP_1 "I've heard your name spoken only in whispers, mage. Who are you?" +#define KHADGAR_GOSSIP_2 "Go on, please." +#define KHADGAR_GOSSIP_3 "I see." //6th too this +#define KHADGAR_GOSSIP_4 "What did you do then?" +#define KHADGAR_GOSSIP_5 "What happened next?" +#define KHADGAR_GOSSIP_7 "There was something else I wanted to ask you." + +bool GossipHello_npc_khadgar(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (!pPlayer->hasQuest(10211)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(9243, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_khadgar(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(9876, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(9877, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(9878, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(9879, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(9880, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + pPlayer->SEND_GOSSIP_MENU(9881, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(9243, pCreature->GetGUID()); + break; + } + return true; +} + +void AddSC_shattrath_city() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_raliq_the_drunk"; + newscript->GetAI = &GetAI_npc_raliq_the_drunk; + newscript->pGossipHello = &GossipHello_npc_raliq_the_drunk; + newscript->pGossipSelect = &GossipSelect_npc_raliq_the_drunk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_salsalabim"; + newscript->GetAI = &GetAI_npc_salsalabim; + newscript->pGossipHello = &GossipHello_npc_salsalabim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_shattrathflaskvendors"; + newscript->pGossipHello = &GossipHello_npc_shattrathflaskvendors; + newscript->pGossipSelect = &GossipSelect_npc_shattrathflaskvendors; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_zephyr"; + newscript->pGossipHello = &GossipHello_npc_zephyr; + newscript->pGossipSelect = &GossipSelect_npc_zephyr; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_kservant"; + newscript->GetAI = &GetAI_npc_kservantAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dirty_larry"; + newscript->GetAI = &GetAI_npc_dirty_larryAI; + newscript->pGossipHello = &GossipHello_npc_dirty_larry; + newscript->pGossipSelect = &GossipSelect_npc_dirty_larry; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ishanah"; + newscript->pGossipHello = &GossipHello_npc_ishanah; + newscript->pGossipSelect = &GossipSelect_npc_ishanah; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_khadgar"; + newscript->pGossipHello = &GossipHello_npc_khadgar; + newscript->pGossipSelect = &GossipSelect_npc_khadgar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp new file mode 100644 index 00000000000..69dbc877d89 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp @@ -0,0 +1,520 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Arcatraz +SD%Complete: 60 +SDComment: Warden Mellichar, event controller for Skyriss event. Millhouse Manastorm. TODO: make better combatAI for Millhouse. +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +/* ContentData +npc_millhouse_manastorm +npc_warden_mellichar +mob_zerekethvoidzone +EndContentData */ + +#include "ScriptedPch.h" +#include "arcatraz.h" + +/*##### +# npc_millhouse_manastorm +#####*/ + +#define SAY_INTRO_1 -1552010 +#define SAY_INTRO_2 -1552011 +#define SAY_WATER -1552012 +#define SAY_BUFFS -1552013 +#define SAY_DRINK -1552014 +#define SAY_READY -1552015 +#define SAY_KILL_1 -1552016 +#define SAY_KILL_2 -1552017 +#define SAY_PYRO -1552018 +#define SAY_ICEBLOCK -1552019 +#define SAY_LOWHP -1552020 +#define SAY_DEATH -1552021 +#define SAY_COMPLETE -1552022 + +#define SPELL_CONJURE_WATER 36879 +#define SPELL_ARCANE_INTELLECT 36880 +#define SPELL_ICE_ARMOR 36881 + +#define SPELL_ARCANE_MISSILES 33833 +#define SPELL_CONE_OF_COLD 12611 +#define SPELL_FIRE_BLAST 13341 +#define SPELL_FIREBALL 14034 +#define SPELL_FROSTBOLT 15497 +#define SPELL_PYROBLAST 33975 + +struct npc_millhouse_manastormAI : public ScriptedAI +{ + npc_millhouse_manastormAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 EventProgress_Timer; + uint32 Phase; + bool Init; + bool LowHp; + + uint32 Pyroblast_Timer; + uint32 Fireball_Timer; + + void Reset() + { + EventProgress_Timer = 2000; + LowHp = false; + Init = false; + Phase = 1; + + Pyroblast_Timer = 1000; + Fireball_Timer = 2500; + + if (pInstance) + { + if (pInstance->GetData(TYPE_WARDEN_2) == DONE) + Init = true; + + if (pInstance->GetData(TYPE_HARBINGERSKYRISS) == DONE) + { + DoScriptText(SAY_COMPLETE, me); + } + } + } + + void AttackStart(Unit* pWho) + { + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(pWho, 25.0f); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + /*for questId 10886 (heroic mode only) + if (pInstance && pInstance->GetData(TYPE_HARBINGERSKYRISS) != DONE) + ->FailQuest();*/ + } + + void UpdateAI(const uint32 diff) + { + if (!Init) + { + if (EventProgress_Timer <= diff) + { + if (Phase < 8) + { + switch(Phase) + { + case 1: + DoScriptText(SAY_INTRO_1, me); + EventProgress_Timer = 18000; + break; + case 2: + DoScriptText(SAY_INTRO_2, me); + EventProgress_Timer = 18000; + break; + case 3: + DoScriptText(SAY_WATER, me); + DoCast(me, SPELL_CONJURE_WATER); + EventProgress_Timer = 7000; + break; + case 4: + DoScriptText(SAY_BUFFS, me); + DoCast(me, SPELL_ICE_ARMOR); + EventProgress_Timer = 7000; + break; + case 5: + DoScriptText(SAY_DRINK, me); + DoCast(me, SPELL_ARCANE_INTELLECT); + EventProgress_Timer = 7000; + break; + case 6: + DoScriptText(SAY_READY, me); + EventProgress_Timer = 6000; + break; + case 7: + if (pInstance) + pInstance->SetData(TYPE_WARDEN_2,DONE); + Init = true; + break; + } + ++Phase; + } + } else EventProgress_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) + { + DoScriptText(SAY_LOWHP, me); + LowHp = true; + } + + if (Pyroblast_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoScriptText(SAY_PYRO, me); + + DoCast(me->getVictim(), SPELL_PYROBLAST); + Pyroblast_Timer = 40000; + } else Pyroblast_Timer -=diff; + + if (Fireball_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL); + Fireball_Timer = 4000; + } else Fireball_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_millhouse_manastorm(Creature* pCreature) +{ + return new npc_millhouse_manastormAI (pCreature); +} + +/*##### +# npc_warden_mellichar +#####*/ + +#define YELL_INTRO1 -1552023 +#define YELL_INTRO2 -1552024 +#define YELL_RELEASE1 -1552025 +#define YELL_RELEASE2A -1552026 +#define YELL_RELEASE2B -1552027 +#define YELL_RELEASE3 -1552028 +#define YELL_RELEASE4 -1552029 +#define YELL_WELCOME -1552030 + +//phase 2(acid mobs) +#define ENTRY_TRICKSTER 20905 +#define ENTRY_PH_HUNTER 20906 +//phase 3 +#define ENTRY_MILLHOUSE 20977 +//phase 4(acid mobs) +#define ENTRY_AKKIRIS 20908 +#define ENTRY_SULFURON 20909 +//phase 5(acid mobs) +#define ENTRY_TW_DRAK 20910 +#define ENTRY_BL_DRAK 20911 +//phase 6 +#define ENTRY_SKYRISS 20912 + +//TARGET_SCRIPT +#define SPELL_TARGET_ALPHA 36856 +#define SPELL_TARGET_BETA 36854 +#define SPELL_TARGET_DELTA 36857 +#define SPELL_TARGET_GAMMA 36858 +#define SPELL_TARGET_OMEGA 36852 +#define SPELL_BUBBLE_VISUAL 36849 + +struct npc_warden_mellicharAI : public ScriptedAI +{ + npc_warden_mellicharAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool IsRunning; + bool CanSpawn; + + uint32 EventProgress_Timer; + uint32 Phase; + + void Reset() + { + IsRunning = false; + CanSpawn = false; + + EventProgress_Timer = 22000; + Phase = 1; + + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + DoCast(me, SPELL_TARGET_OMEGA); + + if (pInstance) + pInstance->SetData(TYPE_HARBINGERSKYRISS,NOT_STARTED); + } + + void AttackStart(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (IsRunning) + return; + + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + float attackRadius = me->GetAttackDistance(who)/10; + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + EnterCombat(who); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_INTRO1, me); + DoCast(me, SPELL_BUBBLE_VISUAL); + + if (pInstance) + { + pInstance->SetData(TYPE_HARBINGERSKYRISS,IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), false); + IsRunning = true; + } + } + + bool CanProgress() + { + if (pInstance) + { + if (Phase == 7 && pInstance->GetData(TYPE_WARDEN_4) == DONE) + return true; + if (Phase == 6 && pInstance->GetData(TYPE_WARDEN_3) == DONE) + return true; + if (Phase == 5 && pInstance->GetData(TYPE_WARDEN_2) == DONE) + return true; + if (Phase == 4) + return true; + if (Phase == 3 && pInstance->GetData(TYPE_WARDEN_1) == DONE) + return true; + if (Phase == 2 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS) + return true; + if (Phase == 1 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS) + return true; + return false; + } + return false; + } + + void DoPrepareForPhase() + { + if (pInstance) + { + me->InterruptNonMeleeSpells(true); + me->RemoveAurasByType(SPELL_AURA_DUMMY); + + switch(Phase) + { + case 2: + DoCast(me, SPELL_TARGET_ALPHA); + pInstance->SetData(TYPE_WARDEN_1,IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), false); + break; + case 3: + DoCast(me, SPELL_TARGET_BETA); + pInstance->SetData(TYPE_WARDEN_2,IN_PROGRESS); + break; + case 5: + DoCast(me, SPELL_TARGET_DELTA); + pInstance->SetData(TYPE_WARDEN_3,IN_PROGRESS); + break; + case 6: + DoCast(me, SPELL_TARGET_GAMMA); + pInstance->SetData(TYPE_WARDEN_4,IN_PROGRESS); + break; + case 7: + pInstance->SetData(TYPE_WARDEN_5,IN_PROGRESS); + break; + } + CanSpawn = true; + } + } + + void UpdateAI(const uint32 diff) + { + if (!IsRunning) + return; + + if (EventProgress_Timer <= diff) + { + if (pInstance) + { + if (pInstance->GetData(TYPE_HARBINGERSKYRISS) == FAIL) + { + Reset(); + return; + } + } + + if (CanSpawn) + { + //continue beam omega pod, unless we are about to summon skyriss + if (Phase != 7) + DoCast(me, SPELL_TARGET_OMEGA); + + switch(Phase) + { + case 2: + switch (urand(0,1)) + { + case 0: me->SummonCreature(ENTRY_TRICKSTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: me->SummonCreature(ENTRY_PH_HUNTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 3: + me->SummonCreature(ENTRY_MILLHOUSE,413.292,-148.378,42.56,6.27,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + break; + case 4: + DoScriptText(YELL_RELEASE2B, me); + break; + case 5: + switch (urand(0,1)) + { + case 0: me->SummonCreature(ENTRY_AKKIRIS,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: me->SummonCreature(ENTRY_SULFURON,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 6: + switch (urand(0,1)) + { + case 0: me->SummonCreature(ENTRY_TW_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: me->SummonCreature(ENTRY_BL_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 7: + me->SummonCreature(ENTRY_SKYRISS,445.763,-191.639,44.64,1.60,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoScriptText(YELL_WELCOME, me); + break; + } + CanSpawn = false; + ++Phase; + } + if (CanProgress()) + { + switch(Phase) + { + case 1: + DoScriptText(YELL_INTRO2, me); + EventProgress_Timer = 10000; + ++Phase; + break; + case 2: + DoScriptText(YELL_RELEASE1, me); + DoPrepareForPhase(); + EventProgress_Timer = 7000; + break; + case 3: + DoScriptText(YELL_RELEASE2A, me); + DoPrepareForPhase(); + EventProgress_Timer = 10000; + break; + case 4: + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 5: + DoScriptText(YELL_RELEASE3, me); + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 6: + DoScriptText(YELL_RELEASE4, me); + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 7: + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + } + } + } else EventProgress_Timer -= diff; + } +}; +CreatureAI* GetAI_npc_warden_mellichar(Creature* pCreature) +{ + return new npc_warden_mellicharAI (pCreature); +} + +/*##### +# mob_zerekethvoidzone (this script probably not needed in future -> `creature_template_addon`.`auras`='36120 0') +#####*/ + +#define SPELL_VOID_ZONE_DAMAGE 36120 + +struct mob_zerekethvoidzoneAI : public ScriptedAI +{ + mob_zerekethvoidzoneAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + me->SetUInt32Value(UNIT_NPC_FLAGS,0); + me->setFaction(16); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + DoCast(me, SPELL_VOID_ZONE_DAMAGE); + } + + void EnterCombat(Unit* /*who*/) {} +}; +CreatureAI* GetAI_mob_zerekethvoidzoneAI(Creature* pCreature) +{ + return new mob_zerekethvoidzoneAI (pCreature); +} + +void AddSC_arcatraz() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_millhouse_manastorm"; + newscript->GetAI = &GetAI_npc_millhouse_manastorm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_warden_mellichar"; + newscript->GetAI = &GetAI_npc_warden_mellichar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_zerekethvoidzone"; + newscript->GetAI = &GetAI_mob_zerekethvoidzoneAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h b/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h new file mode 100644 index 00000000000..3f8dee8bbd0 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ARCATRAZ_H +#define DEF_ARCATRAZ_H + +#define TYPE_ZEREKETH 1 +#define TYPE_DALLIAH 2 +#define TYPE_SOCCOTHRATES 3 +#define TYPE_HARBINGERSKYRISS 4 +#define TYPE_WARDEN_1 5 +#define TYPE_WARDEN_2 6 +#define TYPE_WARDEN_3 7 +#define TYPE_WARDEN_4 8 +#define TYPE_WARDEN_5 9 +#define DATA_MELLICHAR 10 +#define TYPE_SHIELD_OPEN 11 +#define DATA_SPHERE_SHIELD 12 +#endif + diff --git a/src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp b/src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp new file mode 100644 index 00000000000..6576974f3ff --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp @@ -0,0 +1,293 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Harbinger_Skyriss +SD%Complete: 45 +SDComment: CombatAI not fully implemented. Timers will need adjustments. Need more docs on how event fully work. Reset all event and force start over if fail at one point? +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +/* ContentData +boss_harbinger_skyriss +boss_harbinger_skyriss_illusion +EndContentData */ + +#include "ScriptedPch.h" +#include "arcatraz.h" + +#define SAY_INTRO -1552000 +#define SAY_AGGRO -1552001 +#define SAY_KILL_1 -1552002 +#define SAY_KILL_2 -1552003 +#define SAY_MIND_1 -1552004 +#define SAY_MIND_2 -1552005 +#define SAY_FEAR_1 -1552006 +#define SAY_FEAR_2 -1552007 +#define SAY_IMAGE -1552008 +#define SAY_DEATH -1552009 + +#define SPELL_FEAR 39415 + +#define SPELL_MIND_REND 36924 +#define H_SPELL_MIND_REND 39017 + +#define SPELL_DOMINATION 37162 +#define H_SPELL_DOMINATION 39019 + +#define H_SPELL_MANA_BURN 39020 + +#define SPELL_66_ILLUSION 36931 //entry 21466 +#define SPELL_33_ILLUSION 36932 //entry 21467 + +struct boss_harbinger_skyrissAI : public ScriptedAI +{ + boss_harbinger_skyrissAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = false; + } + + ScriptedInstance *pInstance; + + bool Intro; + bool IsImage33; + bool IsImage66; + + uint32 Intro_Phase; + uint32 Intro_Timer; + uint32 MindRend_Timer; + uint32 Fear_Timer; + uint32 Domination_Timer; + uint32 ManaBurn_Timer; + + void Reset() + { + if (!Intro) + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); + + IsImage33 = false; + IsImage66 = false; + + Intro_Phase = 1; + Intro_Timer = 5000; + MindRend_Timer = 3000; + Fear_Timer = 15000; + Domination_Timer = 30000; + ManaBurn_Timer = 25000; + } + + void MoveInLineOfSight(Unit *who) + { + if (!Intro) + { + return; + } + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) {} + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + pInstance->SetData(TYPE_HARBINGERSKYRISS,DONE); + } + + void JustSummoned(Creature *summon) + { + if (!summon) + return; + if (IsImage66) + summon->SetHealth((summon->GetMaxHealth()*33)/100); + else + summon->SetHealth((summon->GetMaxHealth()*66)/100); + if (me->getVictim()) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + summon->AI()->AttackStart(pTarget); + } + + void KilledUnit(Unit* victim) + { + //won't yell killing pet/other unit + if (victim->GetEntry() == 21436) + return; + + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void DoSplit(uint32 val) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoScriptText(SAY_IMAGE, me); + + if (val == 66) + DoCast(me, SPELL_66_ILLUSION); + else + DoCast(me, SPELL_33_ILLUSION); + } + + void UpdateAI(const uint32 diff) + { + if (!Intro) + { + if (!pInstance) + return; + + if (Intro_Timer <= diff) + { + switch(Intro_Phase) + { + case 1: + DoScriptText(SAY_INTRO, me); + pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), true); + ++Intro_Phase; + Intro_Timer = 25000; + break; + case 2: + DoScriptText(SAY_AGGRO, me); + if (Unit *mellic = Unit::GetUnit(*me,pInstance->GetData64(DATA_MELLICHAR))) + { + //should have a better way to do this. possibly spell exist. + mellic->setDeathState(JUST_DIED); + mellic->SetHealth(0); + pInstance->SetData(TYPE_SHIELD_OPEN,IN_PROGRESS); + } + ++Intro_Phase; + Intro_Timer = 3000; + break; + case 3: + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); + Intro = true; + break; + } + } else Intro_Timer -=diff; + } + + if (!UpdateVictim()) + return; + + if (!IsImage66 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 66)) + { + DoSplit(66); + IsImage66 = true; + } + if (!IsImage33 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 33)) + { + DoSplit(33); + IsImage33 = true; + } + + if (MindRend_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_MIND_REND); + else + DoCast(me->getVictim(), SPELL_MIND_REND); + + MindRend_Timer = 8000; + } else MindRend_Timer -=diff; + + if (Fear_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoScriptText(RAND(SAY_FEAR_1,SAY_FEAR_2), me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_FEAR); + else + DoCast(me->getVictim(), SPELL_FEAR); + + Fear_Timer = 25000; + } else Fear_Timer -=diff; + + if (Domination_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoScriptText(RAND(SAY_MIND_1,SAY_MIND_2), me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_DOMINATION); + else + DoCast(me->getVictim(), SPELL_DOMINATION); + + Domination_Timer = 16000+rand()%16000; + } else Domination_Timer -=diff; + + if (IsHeroic()) + { + if (ManaBurn_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, H_SPELL_MANA_BURN); + + ManaBurn_Timer = 16000+rand()%16000; + } else ManaBurn_Timer -=diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_harbinger_skyriss(Creature* pCreature) +{ + return new boss_harbinger_skyrissAI (pCreature); +} + +#define SPELL_MIND_REND_IMAGE 36929 +#define H_SPELL_MIND_REND_IMAGE 39021 + +struct boss_harbinger_skyriss_illusionAI : public ScriptedAI +{ + boss_harbinger_skyriss_illusionAI(Creature *c) : ScriptedAI(c) + { + } + + void Reset() { } + + void EnterCombat(Unit * /*who*/) { } +}; + +CreatureAI* GetAI_boss_harbinger_skyriss_illusion(Creature* pCreature) +{ + return new boss_harbinger_skyriss_illusionAI (pCreature); +} + +void AddSC_boss_harbinger_skyriss() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_harbinger_skyriss"; + newscript->GetAI = &GetAI_boss_harbinger_skyriss; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_harbinger_skyriss_illusion"; + newscript->GetAI = &GetAI_boss_harbinger_skyriss_illusion; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp b/src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp new file mode 100644 index 00000000000..d16975e2af6 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp @@ -0,0 +1,240 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Arcatraz +SD%Complete: 80 +SDComment: Mainly Harbringer Skyriss event +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +#include "ScriptedPch.h" +#include "arcatraz.h" + +#define MAX_ENCOUNTER 9 + +#define CONTAINMENT_CORE_SECURITY_FIELD_ALPHA 184318 //door opened when Wrath-Scryer Soccothrates dies +#define CONTAINMENT_CORE_SECURITY_FIELD_BETA 184319 //door opened when Dalliah the Doomsayer dies +#define POD_ALPHA 183961 //pod first boss wave +#define POD_BETA 183963 //pod second boss wave +#define POD_DELTA 183964 //pod third boss wave +#define POD_GAMMA 183962 //pod fourth boss wave +#define POD_OMEGA 183965 //pod fifth boss wave +#define WARDENS_SHIELD 184802 // warden shield +#define SEAL_SPHERE 184802 //shield 'protecting' mellichar + +#define MELLICHAR 20904 //skyriss will kill this unit + +/* Arcatraz encounters: +1 - Zereketh the Unbound event +2 - Dalliah the Doomsayer event +3 - Wrath-Scryer Soccothrates event +4 - Harbinger Skyriss event, 5 sub-events +*/ + +struct instance_arcatraz : public ScriptedInstance +{ + instance_arcatraz(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 Containment_Core_Security_Field_AlphaGUID; + uint64 Containment_Core_Security_Field_BetaGUID; + uint64 Pod_AlphaGUID; + uint64 Pod_GammaGUID; + uint64 Pod_BetaGUID; + uint64 Pod_DeltaGUID; + uint64 Pod_OmegaGUID; + uint64 Wardens_ShieldGUID; + uint64 GoSphereGUID; + uint64 MellicharGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Containment_Core_Security_Field_AlphaGUID = 0; + Containment_Core_Security_Field_BetaGUID = 0; + Pod_AlphaGUID = 0; + Pod_GammaGUID = 0; + Pod_BetaGUID = 0; + Pod_DeltaGUID = 0; + Pod_OmegaGUID = 0; + Wardens_ShieldGUID = 0; + GoSphereGUID = 0; + MellicharGUID = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case CONTAINMENT_CORE_SECURITY_FIELD_ALPHA: Containment_Core_Security_Field_AlphaGUID = pGo->GetGUID(); break; + case CONTAINMENT_CORE_SECURITY_FIELD_BETA: Containment_Core_Security_Field_BetaGUID = pGo->GetGUID(); break; + case POD_ALPHA: Pod_AlphaGUID = pGo->GetGUID(); break; + case POD_GAMMA: Pod_GammaGUID = pGo->GetGUID(); break; + case POD_BETA: Pod_BetaGUID = pGo->GetGUID(); break; + case POD_DELTA: Pod_DeltaGUID = pGo->GetGUID(); break; + case POD_OMEGA: Pod_OmegaGUID = pGo->GetGUID(); break; + case SEAL_SPHERE: GoSphereGUID = pGo->GetGUID(); break; + //case WARDENS_SHIELD: Wardens_ShieldGUID = pGo->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == MELLICHAR) + MellicharGUID = pCreature->GetGUID(); + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_ZEREKETH: + m_auiEncounter[0] = data; + break; + + case TYPE_DALLIAH: + if (data == DONE) + { + if (GameObject *pGo = instance->GetGameObject(Containment_Core_Security_Field_BetaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[1] = data; + break; + + case TYPE_SOCCOTHRATES: + if (data == DONE) + { + if (GameObject *pGo = instance->GetGameObject(Containment_Core_Security_Field_AlphaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[2] = data; + break; + + case TYPE_HARBINGERSKYRISS: + if (data == NOT_STARTED || data == FAIL) + { + m_auiEncounter[4] = NOT_STARTED; + m_auiEncounter[5] = NOT_STARTED; + m_auiEncounter[6] = NOT_STARTED; + m_auiEncounter[7] = NOT_STARTED; + m_auiEncounter[8] = NOT_STARTED; + } + m_auiEncounter[3] = data; + break; + + case TYPE_WARDEN_1: + if (data == IN_PROGRESS) + if (GameObject *pGo = instance->GetGameObject(Pod_AlphaGUID)) + pGo->UseDoorOrButton(); + m_auiEncounter[4] = data; + break; + + case TYPE_WARDEN_2: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Pod_BetaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[5] = data; + break; + + case TYPE_WARDEN_3: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Pod_DeltaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[6] = data; + break; + + case TYPE_WARDEN_4: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Pod_GammaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[7] = data; + break; + + case TYPE_WARDEN_5: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Pod_OmegaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[8] = data; + break; + + case TYPE_SHIELD_OPEN: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Wardens_ShieldGUID)) + pGo->UseDoorOrButton(); + } + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HARBINGERSKYRISS: return m_auiEncounter[3]; + case TYPE_WARDEN_1: return m_auiEncounter[4]; + case TYPE_WARDEN_2: return m_auiEncounter[5]; + case TYPE_WARDEN_3: return m_auiEncounter[6]; + case TYPE_WARDEN_4: return m_auiEncounter[7]; + case TYPE_WARDEN_5: return m_auiEncounter[8]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_MELLICHAR: return MellicharGUID; + case DATA_SPHERE_SHIELD: return GoSphereGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_arcatraz(Map* pMap) +{ + return new instance_arcatraz(pMap); +} + +void AddSC_instance_arcatraz() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_arcatraz"; + newscript->GetInstanceData = &GetInstanceData_instance_arcatraz; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp b/src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp new file mode 100644 index 00000000000..1a077036298 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp @@ -0,0 +1,191 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Botanist_Freywinn +SD%Complete: 90 +SDComment: some strange visual related to tree form(if aura lost before normal duration end). possible make summon&transform -process smoother(transform after delay) +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1553000 +#define SAY_KILL_1 -1553001 +#define SAY_KILL_2 -1553002 +#define SAY_TREE_1 -1553003 +#define SAY_TREE_2 -1553004 +#define SAY_DEATH -1553005 + +#define SPELL_TRANQUILITY 34550 +#define SPELL_TREE_FORM 34551 + +#define SPELL_SUMMON_FRAYER 34557 +#define ENTRY_FRAYER 19953 + +#define SPELL_PLANT_WHITE 34759 +#define SPELL_PLANT_GREEN 34761 +#define SPELL_PLANT_BLUE 34762 +#define SPELL_PLANT_RED 34763 + +struct boss_high_botanist_freywinnAI : public ScriptedAI +{ + boss_high_botanist_freywinnAI(Creature *c) : ScriptedAI(c) {} + + std::list Adds_List; + + uint32 SummonSeedling_Timer; + uint32 TreeForm_Timer; + uint32 MoveCheck_Timer; + uint32 DeadAddsCount; + bool MoveFree; + + void Reset() + { + Adds_List.clear(); + + SummonSeedling_Timer = 6000; + TreeForm_Timer = 30000; + MoveCheck_Timer = 1000; + DeadAddsCount = 0; + MoveFree = true; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == ENTRY_FRAYER) + Adds_List.push_back(summoned->GetGUID()); + } + + void DoSummonSeedling() + { + switch(rand()%4) + { + case 0: DoCast(me, SPELL_PLANT_WHITE); break; + case 1: DoCast(me, SPELL_PLANT_GREEN); break; + case 2: DoCast(me, SPELL_PLANT_BLUE); break; + case 3: DoCast(me, SPELL_PLANT_RED); break; + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (TreeForm_Timer <= diff) + { + DoScriptText(RAND(SAY_TREE_1,SAY_TREE_2), me); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + me->RemoveAllAuras(); + + DoCast(me, SPELL_SUMMON_FRAYER, true); + DoCast(me, SPELL_TRANQUILITY, true); + DoCast(me, SPELL_TREE_FORM, true); + + me->GetMotionMaster()->MoveIdle(); + MoveFree = false; + + TreeForm_Timer = 75000; + } else TreeForm_Timer -= diff; + + if (!MoveFree) + { + if (MoveCheck_Timer <= diff) + { + if (!Adds_List.empty()) + { + for (std::list::iterator itr = Adds_List.begin(); itr != Adds_List.end(); ++itr) + { + if (Unit *temp = Unit::GetUnit(*me,*itr)) + { + if (!temp->isAlive()) + { + Adds_List.erase(itr); + ++DeadAddsCount; + break; + } + } + } + } + + if (DeadAddsCount < 3 && TreeForm_Timer-30000 <= diff) + DeadAddsCount = 3; + + if (DeadAddsCount >= 3) + { + Adds_List.clear(); + DeadAddsCount = 0; + + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + MoveFree = true; + } + MoveCheck_Timer = 500; + } + else MoveCheck_Timer -= diff; + + return; + } + + /*if (me->HasAura(SPELL_TREE_FORM,0) || me->HasAura(SPELL_TRANQUILITY,0)) + return;*/ + + //one random seedling every 5 secs, but not in tree form + if (SummonSeedling_Timer <= diff) + { + DoSummonSeedling(); + SummonSeedling_Timer = 6000; + } else SummonSeedling_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_high_botanist_freywinn(Creature* pCreature) +{ + return new boss_high_botanist_freywinnAI (pCreature); +} + +void AddSC_boss_high_botanist_freywinn() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_high_botanist_freywinn"; + newscript->GetAI = &GetAI_boss_high_botanist_freywinn; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp b/src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp new file mode 100644 index 00000000000..cbf21c2f992 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Laj +SD%Complete: 90 +SDComment: Immunities are wrong, must be adjusted to use resistance from creature_templates. Most spells require database support. +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_SUMMON -1553006 + +#define SPELL_ALLERGIC_REACTION 34697 +#define SPELL_TELEPORT_SELF 34673 + +#define SPELL_SUMMON_LASHER_1 34681 +#define SPELL_SUMMON_FLAYER_1 34682 +#define SPELL_SUMMON_LASHER_2 34684 +#define SPELL_SUMMON_FLAYER_2 34685 +#define SPELL_SUMMON_LASHER_3 34686 +#define SPELL_SUMMON_FLAYER_4 34687 +#define SPELL_SUMMON_LASHER_4 34688 +#define SPELL_SUMMON_FLAYER_3 34690 + +#define MODEL_DEFAULT 13109 +#define MODEL_ARCANE 14213 +#define MODEL_FIRE 13110 +#define MODEL_FROST 14112 +#define MODEL_NATURE 14214 + +struct boss_lajAI : public ScriptedAI +{ + boss_lajAI(Creature *c) : ScriptedAI(c) {} + + bool CanSummon; + uint32 Teleport_Timer; + uint32 Summon_Timer; + uint32 Transform_Timer; + uint32 Allergic_Timer; + + void Reset() + { + me->SetDisplayId(MODEL_DEFAULT); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + + CanSummon = false; + Teleport_Timer = 20000; + Summon_Timer = 2500; + Transform_Timer = 30000; + Allergic_Timer = 5000; + } + + void DoTransform() + { + switch(rand()%5) + { + case 0: + me->SetDisplayId(MODEL_DEFAULT); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 1: + me->SetDisplayId(MODEL_ARCANE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 2: + me->SetDisplayId(MODEL_FIRE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 3: + me->SetDisplayId(MODEL_FROST); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 4: + me->SetDisplayId(MODEL_NATURE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + break; + } + } + + void DoSummons() + { + switch(rand()%4) + { + case 0: + DoCast(me, SPELL_SUMMON_LASHER_1, true); + DoCast(me, SPELL_SUMMON_FLAYER_1, true); + break; + case 1: + DoCast(me, SPELL_SUMMON_LASHER_2, true); + DoCast(me, SPELL_SUMMON_FLAYER_2, true); + break; + case 2: + DoCast(me, SPELL_SUMMON_LASHER_3, true); + DoCast(me, SPELL_SUMMON_FLAYER_3, true); + break; + case 3: + DoCast(me, SPELL_SUMMON_LASHER_4, true); + DoCast(me, SPELL_SUMMON_FLAYER_4, true); + break; + } + CanSummon = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustSummoned(Creature *summon) + { + if (summon && me->getVictim()) + summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (CanSummon) + { + if (Summon_Timer <= diff) + { + DoScriptText(EMOTE_SUMMON, me); + DoSummons(); + Summon_Timer = 2500; + } else Summon_Timer -= diff; + } + + if (Allergic_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ALLERGIC_REACTION); + Allergic_Timer = 25000+rand()%15000; + } else Allergic_Timer -= diff; + + if (Teleport_Timer <= diff) + { + DoCast(me, SPELL_TELEPORT_SELF); + Teleport_Timer = 30000+rand()%10000; + CanSummon = true; + } else Teleport_Timer -= diff; + + if (Transform_Timer <= diff) + { + DoTransform(); + Transform_Timer = 25000+rand()%15000; + } else Transform_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_laj(Creature* pCreature) +{ + return new boss_lajAI (pCreature); +} + +void AddSC_boss_laj() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_laj"; + newscript->GetAI = &GetAI_boss_laj; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp new file mode 100644 index 00000000000..48eb03c16d3 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp @@ -0,0 +1,216 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Warp_Splinter +SD%Complete: 80 +SDComment: Includes Sapling (need some better control with these). +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "ScriptedPch.h" + +/*##### +# mob_treant (Sapling) +#####*/ + +#define SPELL_HEAL_FATHER 6262 + +struct mob_treantAI : public ScriptedAI +{ + mob_treantAI (Creature *c) : ScriptedAI(c) + { + WarpGuid = 0; + } + + uint64 WarpGuid; + uint32 check_Timer; + + void Reset() + { + check_Timer = 0; + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (WarpGuid && check_Timer <= diff) + { + if (Unit *Warp = Unit::GetUnit(*me, WarpGuid)) + { + if (me->IsWithinMeleeRange(Warp,2.5f)) + { + int32 CurrentHP_Treant = (int32)me->GetHealth(); + Warp->CastCustomSpell(Warp,SPELL_HEAL_FATHER,&CurrentHP_Treant, 0, 0, true,0 ,0, me->GetGUID()); + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + me->GetMotionMaster()->MoveFollow(Warp,0,0); + } + check_Timer = 1000; + } else check_Timer -= diff; + return; + } + + if (me->getVictim()->GetGUID() != WarpGuid) + DoMeleeAttackIfReady(); + } +}; + +/*##### +# boss_warp_splinter +#####*/ + +#define SAY_AGGRO -1553007 +#define SAY_SLAY_1 -1553008 +#define SAY_SLAY_2 -1553009 +#define SAY_SUMMON_1 -1553010 +#define SAY_SUMMON_2 -1553011 +#define SAY_DEATH -1553012 + +#define WAR_STOMP 34716 +#define SUMMON_TREANTS 34727 // DBC: 34727, 34731, 34733, 34734, 34736, 34739, 34741 (with Ancestral Life spell 34742) // won't work (guardian summon) +#define ARCANE_VOLLEY DUNGEON_MODE(36705, 39133) + +#define CREATURE_TREANT 19949 + +#define TREANT_SPAWN_DIST 50 //50 yards from Warp Splinter's spawn point + +float treant_pos[6][3] = +{ + {24.301233, 427.221100, -27.060635}, + {16.795492, 359.678802, -27.355425}, + {53.493484, 345.381470, -26.196192}, + {61.867096, 439.362732, -25.921030}, + {109.861877, 423.201630, -27.356019}, + {106.780159, 355.582581, -27.593357} +}; + +struct boss_warp_splinterAI : public ScriptedAI +{ + boss_warp_splinterAI(Creature *c) : ScriptedAI(c) + { + Treant_Spawn_Pos_X = c->GetPositionX(); + Treant_Spawn_Pos_Y = c->GetPositionY(); + } + + uint32 War_Stomp_Timer; + uint32 Summon_Treants_Timer; + uint32 Arcane_Volley_Timer; + + float Treant_Spawn_Pos_X; + float Treant_Spawn_Pos_Y; + + void Reset() + { + War_Stomp_Timer = 25000 + rand()%15000; + Summon_Treants_Timer = 45000; + Arcane_Volley_Timer = 8000 + rand()%12000; + + me->SetSpeed(MOVE_RUN, 0.7f, true); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void SummonTreants() + { + for (uint8 i = 0; i < 6; ++i) + { + float angle = (M_PI / 3) * i; + + float X = Treant_Spawn_Pos_X + TREANT_SPAWN_DIST * cos(angle); + float Y = Treant_Spawn_Pos_Y + TREANT_SPAWN_DIST * sin(angle); + float O = - me->GetAngle(X,Y); + + if (Creature *pTreant = me->SummonCreature(CREATURE_TREANT,treant_pos[i][0],treant_pos[i][1],treant_pos[i][2],O,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,25000)) + CAST_AI(mob_treantAI, pTreant->AI())->WarpGuid = me->GetGUID(); + } + DoScriptText(RAND(SAY_SUMMON_1,SAY_SUMMON_2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Check for War Stomp + if (War_Stomp_Timer <= diff) + { + DoCast(me->getVictim(), WAR_STOMP); + War_Stomp_Timer = 25000 + rand()%15000; + } else War_Stomp_Timer -= diff; + + //Check for Arcane Volley + if (Arcane_Volley_Timer <= diff) + { + DoCast(me->getVictim(), ARCANE_VOLLEY); + Arcane_Volley_Timer = 20000 + rand()%15000; + } else Arcane_Volley_Timer -= diff; + + //Check for Summon Treants + if (Summon_Treants_Timer <= diff) + { + SummonTreants(); + Summon_Treants_Timer = 45000; + } else Summon_Treants_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_warp_splinter(Creature* pCreature) +{ + return new boss_warp_splinterAI (pCreature); +} + +CreatureAI* GetAI_mob_treant(Creature* pCreature) +{ + return new mob_treantAI (pCreature); +} + +void AddSC_boss_warp_splinter() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_warp_splinter"; + newscript->GetAI = &GetAI_boss_warp_splinter; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_warp_splinter_treant"; + newscript->GetAI = &GetAI_mob_treant; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp new file mode 100644 index 00000000000..af5f1bd95c1 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp @@ -0,0 +1,523 @@ +/* Copyright(C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +*(at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_alar +SD%Complete: 95 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define SPELL_FLAME_BUFFET 34121 // Flame Buffet - every 1,5 secs in phase 1 if there is no victim in melee range and after Dive Bomb in phase 2 with same conditions +#define SPELL_FLAME_QUILLS 34229 // Randomly after changing position in phase after watching tonns of movies, set probability 20% +#define SPELL_REBIRTH 34342 // Rebirth - beginning of second phase(after loose all health in phase 1) +#define SPELL_REBIRTH_2 35369 // Rebirth(another, without healing to full HP) - after Dive Bomb in phase 2 +#define SPELL_MELT_ARMOR 35410 // Melt Armor - every 60 sec in phase 2 +#define SPELL_CHARGE 35412 // Charge - 30 sec cooldown +#define SPELL_DIVE_BOMB_VISUAL 35367 // Bosskillers says 30 sec cooldown, wowwiki says 30 sec colldown, DBM and BigWigs addons says ~47 sec +#define SPELL_DIVE_BOMB 35181 // after watching tonns of movies, set cooldown to 40+rand()%5. +#define SPELL_BERSERK 45078 // 10 minutes after phase 2 starts(id is wrong, but proper id is unknown) + +#define CREATURE_EMBER_OF_ALAR 19551 // Al'ar summons one Ember of Al'ar every position change in phase 1 and two after Dive Bomb. Also in phase 2 when Ember of Al'ar dies, boss loose 3% health. +#define SPELL_EMBER_BLAST 34133 // When Ember of Al'ar dies, it casts Ember Blast + +#define CREATURE_FLAME_PATCH_ALAR 20602 // Flame Patch - every 30 sec in phase 2 +#define SPELL_FLAME_PATCH 35380 // + +static float waypoint[6][3] = +{ + {340.15, 58.65, 17.71}, + {388.09, 31.54, 20.18}, + {388.18, -32.85, 20.18}, + {340.29, -60.19, 17.72}, + {332, 0.01, 39}, // better not use the same xy coord + {331, 0.01, -2.39} +}; + +enum WaitEventType +{ + WE_NONE = 0, + WE_DUMMY = 1, + WE_PLATFORM = 2, + WE_QUILL = 3, + WE_DIE = 4, + WE_REVIVE = 5, + WE_CHARGE = 6, + WE_METEOR = 7, + WE_DIVE = 8, + WE_LAND = 9, + WE_SUMMON = 10 +}; + +struct boss_alarAI : public ScriptedAI +{ + boss_alarAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + DefaultMoveSpeedRate = c->GetSpeedRate(MOVE_RUN); + } + + ScriptedInstance *pInstance; + + WaitEventType WaitEvent; + uint32 WaitTimer; + + bool AfterMoving; + + uint32 Platforms_Move_Timer; + uint32 DiveBomb_Timer; + uint32 MeltArmor_Timer; + uint32 Charge_Timer; + uint32 FlamePatch_Timer; + uint32 Berserk_Timer; + + float DefaultMoveSpeedRate; + + bool Phase1; + bool ForceMove; + uint32 ForceTimer; + + int8 cur_wp; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, NOT_STARTED); + + Berserk_Timer = 1200000; + Platforms_Move_Timer = 0; + + Phase1 = true; + WaitEvent = WE_NONE; + WaitTimer = 0; + AfterMoving = false; + ForceMove = false; + ForceTimer = 5000; + + cur_wp = 4; + + me->SetDisplayId(me->GetNativeDisplayId()); + me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + //me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + //me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->setActive(false); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, IN_PROGRESS); + + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); // after enterevademode will be set walk movement + DoZoneInCombat(); + me->setActive(true); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, DONE); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + summon->AI()->AttackStart(pTarget); + } + + void MoveInLineOfSight(Unit * /*who*/) {} + + void AttackStart(Unit* who) + { + if (Phase1) + AttackStartNoMove(who); + else + ScriptedAI::AttackStart(who); + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth() && Phase1) + { + damage = 0; + if (!WaitEvent) + { + WaitEvent = WE_DIE; + WaitTimer = 0; + me->SetHealth(0); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->AttackStop(); + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + me->SetSpeed(MOVE_RUN, 5.0f); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]); + } + } + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (spell->Id == SPELL_DIVE_BOMB_VISUAL) + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + me->SetDisplayId(11686); + //me->SendUpdateObjectToAllExcept(NULL); + } + } + + void MovementInform(uint32 type, uint32 /*id*/) + { + if (type == POINT_MOTION_TYPE) + { + WaitTimer = 1; + AfterMoving = true; + ForceMove = false; + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) // sometimes isincombat but !incombat, faction bug? + return; + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + if (ForceMove) + { + if (ForceTimer <= diff) + { + me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); + ForceTimer = 5000; + } else ForceTimer -= diff; + + } + if (WaitEvent) + { + if (WaitTimer) + { + if (WaitTimer <= diff) + { + if (AfterMoving) + { + me->GetMotionMaster()->MoveIdle(); + AfterMoving = false; + } + + switch(WaitEvent) + { + case WE_PLATFORM: + Platforms_Move_Timer = 30000+rand()%5000; + break; + case WE_QUILL: + DoCast(me, SPELL_FLAME_QUILLS, true); + Platforms_Move_Timer = 1; + WaitTimer = 10000; + WaitEvent = WE_DUMMY; + return; + case WE_DIE: + ForceMove = false; + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + WaitTimer = 5000; + WaitEvent = WE_REVIVE; + return; + case WE_REVIVE: + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); + me->SetHealth(me->GetMaxHealth()); + me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoZoneInCombat(); + DoCast(me, SPELL_REBIRTH, true); + MeltArmor_Timer = 60000; + Charge_Timer = 7000; + DiveBomb_Timer = 40000+rand()%5000; + FlamePatch_Timer = 30000; + Phase1 = false; + break; + case WE_METEOR: + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + DoCast(me, SPELL_DIVE_BOMB_VISUAL, false); + WaitEvent = WE_DIVE; + WaitTimer = 4000; + return; + case WE_DIVE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL); + DoCast(pTarget, SPELL_DIVE_BOMB, true); + float dist = 3.0f; + if (me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f)) + dist = 5.0f; + WaitTimer = 1000 + floor(dist / 80 * 1000.0f); + me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f); + me->StopMoving(); + WaitEvent = WE_LAND; + } + else + { + EnterEvadeMode(); + return; + } + case WE_LAND: + WaitEvent = WE_SUMMON; + WaitTimer = 2000; + return; + case WE_SUMMON: + for (uint8 i = 0; i < 2; ++i) + DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(me->GetNativeDisplayId()); + DoCast(me, SPELL_REBIRTH_2, true); + break; + case WE_DUMMY: + default: + break; + } + + WaitEvent = WE_NONE; + WaitTimer = 0; + } else WaitTimer -= diff; + } + return; + } + + if (Phase1) + { + if (me->getThreatManager().getThreatList().empty()) + { + EnterEvadeMode(); + return; + } + + if (Platforms_Move_Timer <= diff) + { + if (cur_wp == 4) + { + cur_wp = 0; + WaitEvent = WE_PLATFORM; + } + else + { + if (urand(0,4)) // next platform + { + DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (cur_wp == 3) + cur_wp = 0; + else + ++cur_wp; + WaitEvent = WE_PLATFORM; + } + else // flame quill + { + cur_wp = 4; + WaitEvent = WE_QUILL; + } + } + ForceMove = true; + ForceTimer = 5000; + me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); + WaitTimer = 0; + return; + } else Platforms_Move_Timer -= diff; + } + else + { + if (Charge_Timer <= diff) + { + Unit *pTarget= SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + if (pTarget) + DoCast(pTarget, SPELL_CHARGE); + Charge_Timer = 30000; + } else Charge_Timer -= diff; + + if (MeltArmor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MELT_ARMOR); + MeltArmor_Timer = 60000; + } else MeltArmor_Timer -= diff; + + if (DiveBomb_Timer <= diff) + { + me->AttackStop(); + me->GetMotionMaster()->MovePoint(6, waypoint[4][0], waypoint[4][1], waypoint[4][2]); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 50); + WaitEvent = WE_METEOR; + WaitTimer = 0; + DiveBomb_Timer = 40000+rand()%5000; + return; + } else DiveBomb_Timer -= diff; + + if (FlamePatch_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + Creature* Summoned = me->SummonCreature(CREATURE_FLAME_PATCH_ALAR, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000); + if (Summoned) + { + Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Summoned->SetFloatValue(OBJECT_FIELD_SCALE_X, Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); + Summoned->SetDisplayId(11686); + Summoned->setFaction(me->getFaction()); + Summoned->SetLevel(me->getLevel()); + Summoned->CastSpell(Summoned, SPELL_FLAME_PATCH, false); + } + } + FlamePatch_Timer = 30000; + } else FlamePatch_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void DoMeleeAttackIfReady() + { + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + else + { + Unit *pTarget = NULL; + pTarget = me->SelectNearestTargetInAttackDistance(5); + if (pTarget) + me->AI()->AttackStart(pTarget); + else + { + DoCast(me, SPELL_FLAME_BUFFET, true); + me->setAttackTimer(BASE_ATTACK, 1500); + } + } + } + } +}; + +CreatureAI* GetAI_boss_alar(Creature* pCreature) +{ + return new boss_alarAI(pCreature); +} + +struct mob_ember_of_alarAI : public ScriptedAI +{ + mob_ember_of_alarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + c->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + c->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + } + + ScriptedInstance *pInstance; + bool toDie; + + void Reset() {toDie = false;} + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + void EnterEvadeMode() {me->setDeathState(JUST_DIED);} + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage >= me->GetHealth() && pKiller != me && !toDie) + { + damage = 0; + DoCast(me, SPELL_EMBER_BLAST, true); + me->SetDisplayId(11686); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (pInstance && pInstance->GetData(DATA_ALAREVENT) == 2) + { + if (Unit* Alar = Unit::GetUnit((*me), pInstance->GetData64(DATA_ALAR))) + { + int AlarHealth = Alar->GetHealth() - Alar->GetMaxHealth()*0.03; + if (AlarHealth > 0) + Alar->SetHealth(AlarHealth); + else + Alar->SetHealth(1); + } + } + toDie = true; + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + if (toDie) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + //me->SetVisibility(VISIBILITY_OFF); + } + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_mob_ember_of_alar(Creature* pCreature) +{ + return new mob_ember_of_alarAI(pCreature); +} + +struct mob_flame_patch_alarAI : public ScriptedAI +{ + mob_flame_patch_alarAI(Creature *c) : ScriptedAI(c) {} + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_mob_flame_patch_alar(Creature* pCreature) +{ + return new mob_flame_patch_alarAI(pCreature); +} + +void AddSC_boss_alar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_alar"; + newscript->GetAI = &GetAI_boss_alar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ember_of_alar"; + newscript->GetAI = &GetAI_mob_ember_of_alar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flame_patch_alar"; + newscript->GetAI = &GetAI_mob_flame_patch_alar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp new file mode 100644 index 00000000000..e9e217a5c62 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp @@ -0,0 +1,466 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Astromancer +SD%Complete: 80 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +enum eEnums +{ + SAY_AGGRO = -1550007, + SAY_SUMMON1 = -1550008, + SAY_SUMMON2 = -1550009, + SAY_KILL1 = -1550010, + SAY_KILL2 = -1550011, + SAY_KILL3 = -1550012, + SAY_DEATH = -1550013, + SAY_VOIDA = -1550014, + SAY_VOIDB = -1550015, + + SPELL_ARCANE_MISSILES = 33031, + SPELL_WRATH_OF_THE_ASTROMANCER = 42783, + SPELL_BLINDING_LIGHT = 33009, + SPELL_FEAR = 34322, + SPELL_VOID_BOLT = 39329, + + SPELL_SPOTLIGHT = 25824, + NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT = 18928, + + NPC_SOLARIUM_AGENT = 18925, + NPC_SOLARIUM_PRIEST = 18806, + + MODEL_HUMAN = 18239, + MODEL_VOIDWALKER = 18988, + + SPELL_SOLARIUM_GREAT_HEAL = 33387, + SPELL_SOLARIUM_HOLY_SMITE = 25054, + SPELL_SOLARIUM_ARCANE_TORRENT = 33390, + + WV_ARMOR = 31000 +}; + +const float CENTER_X = 432.909f; +const float CENTER_Y = -373.424f; +const float CENTER_Z = 17.9608f; +const float CENTER_O = 1.06421f; +const float SMALL_PORTAL_RADIUS = 12.6f; +const float LARGE_PORTAL_RADIUS = 26.0f; +const float PORTAL_Z = 17.005f; + + // x, y, z, o +static float SolarianPos[4] = {432.909, -373.424, 17.9608, 1.06421}; + +struct boss_high_astromancer_solarianAI : public ScriptedAI +{ + boss_high_astromancer_solarianAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + + defaultarmor = c->GetArmor(); + defaultsize = c->GetFloatValue(OBJECT_FIELD_SCALE_X); + } + + ScriptedInstance *pInstance; + SummonList Summons; + + uint8 Phase; + + uint32 ArcaneMissiles_Timer; + uint32 m_uiWrathOfTheAstromancer_Timer; + uint32 BlindingLight_Timer; + uint32 Fear_Timer; + uint32 VoidBolt_Timer; + uint32 Phase1_Timer; + uint32 Phase2_Timer; + uint32 Phase3_Timer; + uint32 AppearDelay_Timer; + uint32 defaultarmor; + uint32 Wrath_Timer; + + float defaultsize; + float Portals[3][3]; + + bool AppearDelay; + bool BlindingLight; + + void Reset() + { + ArcaneMissiles_Timer = 2000; + m_uiWrathOfTheAstromancer_Timer = 15000; + BlindingLight_Timer = 41000; + Fear_Timer = 20000; + VoidBolt_Timer = 10000; + Phase1_Timer = 50000; + Phase2_Timer = 10000; + Phase3_Timer = 15000; + AppearDelay_Timer = 2000; + BlindingLight = false; + AppearDelay = false; + Wrath_Timer = 20000+rand()%5000;//twice in phase one + Phase = 1; + Wrath_Timer = 20000+rand()%5000;//twice in phase one + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); + + me->SetArmor(defaultarmor); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + me->SetDisplayId(MODEL_HUMAN); + + Summons.DespawnAll(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2,SAY_KILL3), me); + } + + void JustDied(Unit * /*victim*/) + { + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + me->SetDisplayId(MODEL_HUMAN); + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); + } + + void SummonMinion(uint32 entry, float x, float y, float z) + { + Creature* Summoned = me->SummonCreature(entry, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (Summoned) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Summoned->AI()->AttackStart(pTarget); + + Summons.Summon(Summoned); + } + } + + float Portal_X(float radius) + { + if (urand(0,1)) + radius = -radius; + + return radius * (float)(rand()%100)/100.0f + CENTER_X; + } + + float Portal_Y(float x, float radius) + { + float z = RAND(1, -1); + + return (z*sqrt(radius*radius - (x - CENTER_X)*(x - CENTER_X)) + CENTER_Y); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AppearDelay) + { + me->StopMoving(); + me->AttackStop(); + if (AppearDelay_Timer <= diff) + { + AppearDelay = false; + if (Phase == 2) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_OFF); + } + AppearDelay_Timer = 2000; + } else AppearDelay_Timer -= diff; + } + + if (Phase == 1) + { + if (BlindingLight_Timer <= diff) + { + BlindingLight = true; + BlindingLight_Timer = 45000; + } else BlindingLight_Timer -= diff; + + if (Wrath_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER, true); + Wrath_Timer = 20000+rand()%5000; + } else Wrath_Timer -= diff; + + if (ArcaneMissiles_Timer <= diff) + { + if (BlindingLight) + { + DoCast(me->getVictim(), SPELL_BLINDING_LIGHT); + BlindingLight = false; + }else{ + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (!me->HasInArc(2.5f, pTarget)) + pTarget = me->getVictim(); + + if (pTarget) + DoCast(pTarget, SPELL_ARCANE_MISSILES); + } + ArcaneMissiles_Timer = 3000; + } else ArcaneMissiles_Timer -= diff; + + if (m_uiWrathOfTheAstromancer_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + + //Target the tank ? + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER); + m_uiWrathOfTheAstromancer_Timer = 25000; + } + else + m_uiWrathOfTheAstromancer_Timer = 1000; + } else m_uiWrathOfTheAstromancer_Timer -= diff; + + //Phase1_Timer + if (Phase1_Timer <= diff) + { + Phase = 2; + Phase1_Timer = 50000; + //After these 50 seconds she portals to the middle of the room and disappears, leaving 3 light portals behind. + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, CENTER_X, CENTER_Y, CENTER_Z, CENTER_O); + for (uint8 i=0; i <= 2; ++i) + { + if (!i) + { + Portals[i][0] = Portal_X(SMALL_PORTAL_RADIUS); + Portals[i][1] = Portal_Y(Portals[i][0], SMALL_PORTAL_RADIUS); + Portals[i][2] = CENTER_Z; + } + else + { + Portals[i][0] = Portal_X(LARGE_PORTAL_RADIUS); + Portals[i][1] = Portal_Y(Portals[i][0], LARGE_PORTAL_RADIUS); + Portals[i][2] = PORTAL_Z; + } + } + if ((abs(Portals[2][0] - Portals[1][0]) < 7) && (abs(Portals[2][1] - Portals[1][1]) < 7)) + { + int i=1; + if (abs(CENTER_X + 26.0f - Portals[2][0]) < 7) + i = -1; + Portals[2][0] = Portals[2][0]+7*i; + Portals[2][1] = Portal_Y(Portals[2][0], LARGE_PORTAL_RADIUS); + } + for (int i=0; i <= 2; ++i) + { + if (Creature* Summoned = me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O, TEMPSUMMON_TIMED_DESPAWN, Phase2_Timer+Phase3_Timer+AppearDelay_Timer+1700)) + { + Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Summoned->CastSpell(Summoned, SPELL_SPOTLIGHT, false); + } + } + AppearDelay = true; + } else Phase1_Timer-=diff; + } + else if (Phase == 2) + { + //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. + me->AttackStop(); + me->StopMoving(); + if (Phase2_Timer <= diff) + { + Phase = 3; + for (int i=0; i <= 2; ++i) + for (int j=1; j <= 4; j++) + SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); + + DoScriptText(SAY_SUMMON1, me); + Phase2_Timer = 10000; + } else Phase2_Timer -= diff; + } + else if (Phase == 3) + { + me->AttackStop(); + me->StopMoving(); + + //Check Phase3_Timer + if (Phase3_Timer <= diff) + { + Phase = 1; + + //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. + int i = rand()%3; + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); + + for (int j=0; j <= 2; j++) + if (j != i) + SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + DoScriptText(SAY_SUMMON2, me); + AppearDelay = true; + Phase3_Timer = 15000; + } else Phase3_Timer -= diff; + } + else if (Phase == 4) + { + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 20000; + } else Fear_Timer -= diff; + + //VoidBolt_Timer + if (VoidBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VOID_BOLT); + VoidBolt_Timer = 10000; + } else VoidBolt_Timer -= diff; + } + + //When Solarian reaches 20% she will transform into a huge void walker. + if (Phase != 4 && ((me->GetHealth()*100 / me->GetMaxHealth())<20)) + { + Phase = 4; + + //To make sure she wont be invisible or not selecatble + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + DoScriptText(SAY_VOIDA, me); + DoScriptText(SAY_VOIDB, me); + me->SetArmor(WV_ARMOR); + me->SetDisplayId(MODEL_VOIDWALKER); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize*2.5f); + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_solarium_priestAI : public ScriptedAI +{ + mob_solarium_priestAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 healTimer; + uint32 holysmiteTimer; + uint32 aoesilenceTimer; + + void Reset() + { + healTimer = 9000; + holysmiteTimer = 1; + aoesilenceTimer = 15000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (healTimer <= diff) + { + Unit *pTarget = NULL; + + switch (urand(0,1)) + { + case 0: + if (pInstance) + pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_ASTROMANCER)); + break; + case 1: + pTarget = me; + break; + } + + if (pTarget) + { + DoCast(pTarget, SPELL_SOLARIUM_GREAT_HEAL); + healTimer = 9000; + } + } else healTimer -= diff; + + if (holysmiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARIUM_HOLY_SMITE); + holysmiteTimer = 4000; + } else holysmiteTimer -= diff; + + if (aoesilenceTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARIUM_ARCANE_TORRENT); + aoesilenceTimer = 13000; + } else aoesilenceTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_solarium_priest(Creature* pCreature) +{ + return new mob_solarium_priestAI (pCreature); +} + +CreatureAI* GetAI_boss_high_astromancer_solarian(Creature* pCreature) +{ + return new boss_high_astromancer_solarianAI (pCreature); +} + +void AddSC_boss_high_astromancer_solarian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_high_astromancer_solarian"; + newscript->GetAI = &GetAI_boss_high_astromancer_solarian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_solarium_priest"; + newscript->GetAI = &GetAI_mob_solarium_priest; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp new file mode 100644 index 00000000000..05681fb7539 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp @@ -0,0 +1,1498 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kaelthas +SD%Complete: 60 +SDComment: SQL, weapon scripts, mind control, need correct spells(interruptible/uninterruptible), phoenix spawn location & animation, phoenix behaviour & spawn during gravity lapse +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" +#include "WorldPacket.h" + +enum eEnums +{ + //kael'thas Speech + SAY_INTRO = -1550016, + SAY_INTRO_CAPERNIAN = -1550017, + SAY_INTRO_TELONICUS = -1550018, + SAY_INTRO_THALADRED = -1550019, + SAY_INTRO_SANGUINAR = -1550020, + SAY_PHASE2_WEAPON = -1550021, + SAY_PHASE3_ADVANCE = -1550022, + SAY_PHASE4_INTRO2 = -1550023, + SAY_PHASE5_NUTS = -1550024, + SAY_SLAY1 = -1550025, + SAY_SLAY2 = -1550026, + SAY_SLAY3 = -1550027, + SAY_MINDCONTROL1 = -1550028, + SAY_MINDCONTROL2 = -1550029, + SAY_GRAVITYLAPSE1 = -1550030, + SAY_GRAVITYLAPSE2 = -1550031, + SAY_SUMMON_PHOENIX1 = -1550032, + SAY_SUMMON_PHOENIX2 = -1550033, + SAY_DEATH = -1550034, + + //Thaladred the Darkener speech + SAY_THALADRED_AGGRO = -1550035, + SAY_THALADRED_DEATH = -1550036, + EMOTE_THALADRED_GAZE = -1550037, + + //Lord Sanguinar speech + SAY_SANGUINAR_AGGRO = -1550038, + SAY_SANGUINAR_DEATH = -1550039, + + //Grand Astromancer Capernian speech + SAY_CAPERNIAN_AGGRO = -1550040, + SAY_CAPERNIAN_DEATH = -1550041, + + //Master Engineer Telonicus speech + SAY_TELONICUS_AGGRO = -1550042, + SAY_TELONICUS_DEATH = -1550043, + + //Phase 2 spells + SPELL_SUMMON_WEAPONS = 36976, + SPELL_SUMMON_WEAPONA = 36958, + SPELL_SUMMON_WEAPONB = 36959, + SPELL_SUMMON_WEAPONC = 36960, + SPELL_SUMMON_WEAPOND = 36961, + SPELL_SUMMON_WEAPONE = 36962, + SPELL_SUMMON_WEAPONF = 36963, + SPELL_SUMMON_WEAPONG = 36964, + SPELL_RES_VISUAL = 24171, + + //Phase 4 spells + SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell + SPELL_PYROBLAST = 36819, + SPELL_FLAME_STRIKE = 36735, + SPELL_FLAME_STRIKE_VIS = 36730, + SPELL_FLAME_STRIKE_DMG = 36731, + SPELL_ARCANE_DISRUPTION = 36834, + SPELL_SHOCK_BARRIER = 36815, + SPELL_PHOENIX_ANIMATION = 36723, + SPELL_MIND_CONTROL = 32830, + + //Phase 5 spells + SPELL_EXPLODE = 36092, + SPELL_FULLPOWER = 36187, + SPELL_KNOCKBACK = 11027, + SPELL_GRAVITY_LAPSE = 34480, + SPELL_GRAVITY_LAPSE_AURA = 39432, + SPELL_NETHER_BEAM = 35873, + + //Thaladred the Darkener spells + SPELL_PSYCHIC_BLOW = 10689, + SPELL_SILENCE = 30225, + //Lord Sanguinar spells + SPELL_BELLOWING_ROAR = 40636, + //Grand Astromancer Capernian spells + + SPELL_CAPERNIAN_FIREBALL = 36971, + SPELL_CONFLAGRATION = 37018, + SPELL_ARCANE_EXPLOSION = 36970, + //Master Engineer Telonicus spells + SPELL_BOMB = 37036, + SPELL_REMOTE_TOY = 37027, + //Nether Vapor spell + SPELL_NETHER_VAPOR = 35859, + //Phoenix spell + SPELL_BURN = 36720, + SPELL_EMBER_BLAST = 34341, + SPELL_REBIRTH = 41587, + + //Creature IDs + NPC_PHOENIX = 21362, + NPC_PHOENIX_EGG = 21364, + + //Phoenix egg and phoenix model + MODEL_ID_PHOENIX = 19682, + MODEL_ID_PHOENIX_EGG = 20245, + + MAX_ADVISORS = 4 +}; + +uint32 m_auiSpellSummonWeapon[]= +{ + SPELL_SUMMON_WEAPONA, SPELL_SUMMON_WEAPONB, SPELL_SUMMON_WEAPONC, SPELL_SUMMON_WEAPOND, + SPELL_SUMMON_WEAPONE, SPELL_SUMMON_WEAPONF, SPELL_SUMMON_WEAPONG +}; + +const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target +const float KAEL_VISIBLE_RANGE = 50.0f; + +const float afGravityPos[3] = {795.0f, 0.0f, 70.0f}; + +#define TIME_PHASE_2_3 120000 +#define TIME_PHASE_3_4 180000 + +//Base AI for Advisors +struct advisorbase_ai : public ScriptedAI +{ + advisorbase_ai(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + m_bDoubled_Health = false; + } + + ScriptedInstance* m_pInstance; + bool FakeDeath; + bool m_bDoubled_Health; + uint32 DelayRes_Timer; + uint64 DelayRes_Target; + + void Reset() + { + if (m_bDoubled_Health) + { + me->SetMaxHealth(me->GetMaxHealth() / 2); + m_bDoubled_Health = false; + } + + FakeDeath = false; + DelayRes_Timer = 0; + DelayRes_Target = 0; + + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //reset encounter + if (m_pInstance && (m_pInstance->GetData(DATA_KAELTHASEVENT) == 1 || m_pInstance->GetData(DATA_KAELTHASEVENT) == 3)) + if (Creature *Kaelthas = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_KAELTHAS))) + Kaelthas->AI()->EnterEvadeMode(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void Revive(Unit* /*Target*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // double health for phase 3 + me->SetMaxHealth(me->GetMaxHealth() * 2); + m_bDoubled_Health = true; + me->SetHealth(me->GetMaxHealth()); + me->SetStandState(UNIT_STAND_STATE_STAND); + + DoCast(me, SPELL_RES_VISUAL, false); + DelayRes_Timer = 2000; + } + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage < me->GetHealth()) + return; + + //Prevent glitch if in fake death + if (FakeDeath && m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) + { + damage = 0; + return; + } + + //Don't really die in phase 1 & 3, only die after that + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) + { + //prevent death + damage = 0; + FakeDeath = true; + + me->InterruptNonMeleeSpells(false); + me->SetHealth(0); + me->StopMoving(); + me->ClearComboPointHolders(); + me->RemoveAllAurasOnDeath(); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->ClearAllReactives(); + me->SetUInt64Value(UNIT_FIELD_TARGET,0); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + JustDied(pKiller); + } + } + + void UpdateAI(const uint32 diff) + { + if (DelayRes_Timer) + { + if (DelayRes_Timer <= diff) + { + DelayRes_Timer = 0; + FakeDeath = false; + + Unit* Target = Unit::GetUnit((*me), DelayRes_Target); + if (!Target) + Target = me->getVictim(); + + DoResetThreat(); + AttackStart(Target); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(Target); + me->AddThreat(Target, 0.0f); + } else DelayRes_Timer -= diff; + } + } + +}; + +//Kael'thas AI +struct boss_kaelthasAI : public ScriptedAI +{ + boss_kaelthasAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me) + { + m_pInstance = pCreature->GetInstanceData(); + memset(&m_auiAdvisorGuid, 0, sizeof(m_auiAdvisorGuid)); + } + + ScriptedInstance* m_pInstance; + + uint32 Fireball_Timer; + uint32 ArcaneDisruption_Timer; + uint32 Phoenix_Timer; + uint32 ShockBarrier_Timer; + uint32 GravityLapse_Timer; + uint32 GravityLapse_Phase; + uint32 NetherBeam_Timer; + uint32 NetherVapor_Timer; + uint32 FlameStrike_Timer; + uint32 MindControl_Timer; + uint32 Phase; + uint32 PhaseSubphase; //generic + uint32 Phase_Timer; //generic timer + uint32 PyrosCasted; + + bool InGravityLapse; + bool IsCastingFireball; + bool ChainPyros; + + SummonList summons; + + uint64 m_auiAdvisorGuid[MAX_ADVISORS]; + + void Reset() + { + Fireball_Timer = 5000+rand()%10000; + ArcaneDisruption_Timer = 45000; + MindControl_Timer = 40000; + Phoenix_Timer = 50000; + ShockBarrier_Timer = 60000; + FlameStrike_Timer = 30000; + GravityLapse_Timer = 20000; + GravityLapse_Phase = 0; + NetherBeam_Timer = 8000; + NetherVapor_Timer = 10000; + PyrosCasted = 0; + Phase = 0; + InGravityLapse = false; + IsCastingFireball = false; + ChainPyros = false; + + if (me->isInCombat()) + PrepareAdvisors(); + + summons.DespawnAll(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 0); + } + + void PrepareAdvisors() + { + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + if (Creature *pCreature = Unit::GetCreature((*me), m_auiAdvisorGuid[i])) + { + pCreature->Respawn(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->setFaction(me->getFaction()); + pCreature->AI()->EnterEvadeMode(); + } + } + } + + void StartEvent() + { + if (!m_pInstance) + return; + + m_auiAdvisorGuid[0] = m_pInstance->GetData64(DATA_THALADREDTHEDARKENER); + m_auiAdvisorGuid[1] = m_pInstance->GetData64(DATA_LORDSANGUINAR); + m_auiAdvisorGuid[2] = m_pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN); + m_auiAdvisorGuid[3] = m_pInstance->GetData64(DATA_MASTERENGINEERTELONICUS); + + if (!m_auiAdvisorGuid[0] || !m_auiAdvisorGuid[1] || !m_auiAdvisorGuid[2] || !m_auiAdvisorGuid[3]) + { + error_log("TSCR: Kael'Thas One or more advisors missing, Skipping Phases 1-3"); + + DoScriptText(SAY_PHASE4_INTRO2, me); + + Phase = 4; + + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + AttackStart(pTarget); + + } + else + { + PrepareAdvisors(); + + DoScriptText(SAY_INTRO, me); + + m_pInstance->SetData(DATA_KAELTHASEVENT, 1); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + PhaseSubphase = 0; + Phase_Timer = 23000; + Phase = 1; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!me->hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() && + me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + if (!me->getVictim() && Phase >= 4) + { + who->RemoveAurasDueToSpell(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (me->GetMap()->IsDungeon()) + { + if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) + StartEvent(); + + who->SetInCombatWith(me); + me->AddThreat(who, 0.0f); + } + } + } + } + + void Aggro(Unit * /*who*/) + { + if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) + StartEvent(); + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustSummoned(Creature* pSummoned) + { + // if not phoenix, then it's one of the 7 weapons + if (pSummoned->GetEntry() != NPC_PHOENIX) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + + summons.Summon(pSummoned); + } + } + + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + + void JustDied(Unit* /*Killer*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + DoScriptText(SAY_DEATH, me); + + summons.DespawnAll(); + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 0); + + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + if (Unit* pAdvisor = Unit::GetUnit((*me), m_auiAdvisorGuid[i])) + pAdvisor->Kill(pAdvisor); + } + } + + void UpdateAI(const uint32 diff) + { + //Phase 1 + switch (Phase) + { + case 1: + { + Unit *pTarget = NULL; + Creature* Advisor = NULL; + + //Subphase switch + switch(PhaseSubphase) + { + //Subphase 1 - Start + case 0: + if (Phase_Timer <= diff) + { + DoScriptText(SAY_INTRO_THALADRED, me); + + //start advisor within 7 seconds + Phase_Timer = 7000; + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 1 - Unlock advisor + case 1: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 2 - Start + case 2: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_SANGUINAR, me); + + //start advisor within 12.5 seconds + Phase_Timer = 12500; + ++PhaseSubphase; + } + break; + + //Subphase 2 - Unlock advisor + case 3: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 3 - Start + case 4: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_CAPERNIAN, me); + + //start advisor within 7 seconds + Phase_Timer = 7000; + ++PhaseSubphase; + } + break; + + //Subphase 3 - Unlock advisor + case 5: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 4 - Start + case 6: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_TELONICUS, me); + + //start advisor within 8.4 seconds + Phase_Timer = 8400; + ++PhaseSubphase; + } + break; + + //Subphase 4 - Unlock advisor + case 7: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + Phase_Timer = 3000; + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //End of phase 1 + case 8: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + Phase = 2; + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 2); + + DoScriptText(SAY_PHASE2_WEAPON, me); + + PhaseSubphase = 0; + Phase_Timer = 3500; + DoCast(me, SPELL_SUMMON_WEAPONS); + } + break; + } + } + break; + + case 2: + { + if (PhaseSubphase == 0) + { + if (Phase_Timer <= diff) + { + PhaseSubphase = 1; + } else Phase_Timer -= diff; + } + + //Spawn weapons + if (PhaseSubphase == 1) + { + DoCast(me, SPELL_SUMMON_WEAPONS, false); + + uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32); + + for (uint32 i = 0; i < uiMaxWeapon; ++i) + DoCast(me, m_auiSpellSummonWeapon[i], true); + + PhaseSubphase = 2; + Phase_Timer = TIME_PHASE_2_3; + } + + if (PhaseSubphase == 2) + { + if (Phase_Timer <= diff) + { + DoScriptText(SAY_PHASE3_ADVANCE, me); + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 3); + Phase = 3; + PhaseSubphase = 0; + } else Phase_Timer -= diff; + } + } + break; + + case 3: + { + if (PhaseSubphase == 0) + { + //Respawn advisors + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + Creature *Advisor; + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + Advisor = Unit::GetCreature((*me), m_auiAdvisorGuid[i]); + + if (!Advisor) + error_log("SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); + else + CAST_AI(advisorbase_ai, Advisor->AI())->Revive(pTarget); + } + + PhaseSubphase = 1; + Phase_Timer = TIME_PHASE_3_4; + } + + if (Phase_Timer <= diff) + { + DoScriptText(SAY_PHASE4_INTRO2, me); + Phase = 4; + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + + // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. + DoResetThreat(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + AttackStart(pTarget); + + Phase_Timer = 30000; + } else Phase_Timer -= diff; + } + break; + + case 4: + case 5: + case 6: + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Fireball_Timer + if (!InGravityLapse && !ChainPyros && Phase != 5) + { + if (Fireball_Timer <= diff) + { + if (!IsCastingFireball) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + //interruptable + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); + int32 dmg = 20000+rand()%5000; + me->CastCustomSpell(me->getVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); + IsCastingFireball = true; + Fireball_Timer = 2500; + } + } + else + { + //apply resistance + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); + IsCastingFireball = false; + Fireball_Timer = 5000+rand()%10000; + } + } else Fireball_Timer -= diff; + + //ArcaneDisruption_Timer + if (ArcaneDisruption_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_DISRUPTION, true); + ArcaneDisruption_Timer = 60000; + } else ArcaneDisruption_Timer -= diff; + + if (FlameStrike_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_FLAME_STRIKE); + + FlameStrike_Timer = 30000; + } else FlameStrike_Timer -= diff; + + if (MindControl_Timer <= diff) + { + if (me->getThreatManager().getThreatList().size() >= 2) + for (uint32 i = 0; i < 3; ++i) + { + debug_log("SD2: Kael'Thas mind control not supported."); + //DoCast(pUnit, SPELL_MIND_CONTROL); + } + + MindControl_Timer = 60000; + } else MindControl_Timer -= diff; + } + + //Phoenix_Timer + if (Phoenix_Timer <= diff) + { + DoCast(me, SPELL_PHOENIX_ANIMATION); + DoScriptText(RAND(SAY_SUMMON_PHOENIX1,SAY_SUMMON_PHOENIX2), me); + + Phoenix_Timer = 60000; + } else Phoenix_Timer -= diff; + + //Phase 4 specific spells + if (Phase == 4) + { + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + Phase = 5; + Phase_Timer = 10000; + + DoScriptText(SAY_PHASE5_NUTS, me); + + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); + me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, 0, 0); + + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_FULLPOWER); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + //ShockBarrier_Timer + if (ShockBarrier_Timer <= diff) + { + DoCast(me, SPELL_SHOCK_BARRIER); + ChainPyros = true; + PyrosCasted = 0; + ShockBarrier_Timer = 60000; + } else ShockBarrier_Timer -= diff; + + //Chain Pyros (3 of them max) + if (ChainPyros && !me->IsNonMeleeSpellCasted(false)) + { + if (PyrosCasted < 3) + { + DoCast(me->getVictim(), SPELL_PYROBLAST); + ++PyrosCasted; + } + else + { + ChainPyros = false; + Fireball_Timer = 2500; + ArcaneDisruption_Timer = 60000; + } + } + } + + if (Phase == 5) + { + if (Phase_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + me->RemoveAurasDueToSpell(SPELL_FULLPOWER); + + DoCast(me, SPELL_EXPLODE); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Phase = 6; + AttackStart(me->getVictim()); + } else Phase_Timer -= diff; + } + + //Phase 5 + if (Phase == 6) + { + + //GravityLapse_Timer + if (GravityLapse_Timer <= diff) + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + switch (GravityLapse_Phase) + { + case 0: + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); + me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, MOVEMENTFLAG_NONE, 0); + + // 1) Kael'thas will portal the whole raid right into his body + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + //Use work around packet to prevent player from being dropped from combat + DoTeleportPlayer(pUnit, afGravityPos[0], afGravityPos[1], afGravityPos[2], pUnit->GetOrientation()); + } + } + + GravityLapse_Timer = 500; + ++GravityLapse_Phase; + InGravityLapse = true; + ShockBarrier_Timer = 1000; + NetherBeam_Timer = 5000; + break; + + case 1: + DoScriptText(RAND(SAY_GRAVITYLAPSE1,SAY_GRAVITYLAPSE2), me); + + // 2) At that point he will put a Gravity Lapse debuff on everyone + for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) + { + if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) + { + DoCast(pUnit, SPELL_KNOCKBACK, true); + //Gravity lapse - needs an exception in Spell system to work + + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); + + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + GravityLapse_Timer = 10000; + ++GravityLapse_Phase; + break; + + case 2: + //Cast nether vapor aura on self + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_NETHER_VAPOR); + + GravityLapse_Timer = 20000; + ++GravityLapse_Phase; + break; + + case 3: + //Remove flight + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) + { + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + + me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); + InGravityLapse = false; + GravityLapse_Timer = 60000; + GravityLapse_Phase = 0; + AttackStart(me->getVictim()); + break; + } + } else GravityLapse_Timer -= diff; + + if (InGravityLapse) + { + //ShockBarrier_Timer + if (ShockBarrier_Timer <= diff) + { + DoCast(me, SPELL_SHOCK_BARRIER); + ShockBarrier_Timer = 20000; + } else ShockBarrier_Timer -= diff; + + //NetherBeam_Timer + if (NetherBeam_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_NETHER_BEAM); + + NetherBeam_Timer = 4000; + } else NetherBeam_Timer -= diff; + } + } + + if (!InGravityLapse) + DoMeleeAttackIfReady(); + } + } + } +}; + +//Thaladred the Darkener AI +struct boss_thaladred_the_darkenerAI : public advisorbase_ai +{ + boss_thaladred_the_darkenerAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Gaze_Timer; + uint32 Silence_Timer; + uint32 PsychicBlow_Timer; + + void Reset() + { + Gaze_Timer = 100; + Silence_Timer = 20000; + PsychicBlow_Timer = 10000; + + advisorbase_ai::Reset(); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_THALADRED_AGGRO, me); + me->AddThreat(who, 5000000.0f); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_THALADRED_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Gaze_Timer + if (Gaze_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoResetThreat(); + me->AddThreat(pTarget, 5000000.0f); + DoScriptText(EMOTE_THALADRED_GAZE, me, pTarget); + Gaze_Timer = 8500; + } + } else Gaze_Timer -= diff; + + //Silence_Timer + if (Silence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + Silence_Timer = 20000; + } else Silence_Timer -= diff; + + //PsychicBlow_Timer + if (PsychicBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PSYCHIC_BLOW); + PsychicBlow_Timer = 20000+rand()%5000; + } else PsychicBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Lord Sanguinar AI +struct boss_lord_sanguinarAI : public advisorbase_ai +{ + boss_lord_sanguinarAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Fear_Timer; + + void Reset() + { + Fear_Timer = 20000; + advisorbase_ai::Reset(); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_SANGUINAR_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_SANGUINAR_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); + Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds + } else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Grand Astromancer Capernian AI +struct boss_grand_astromancer_capernianAI : public advisorbase_ai +{ + boss_grand_astromancer_capernianAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Fireball_Timer; + uint32 Conflagration_Timer; + uint32 ArcaneExplosion_Timer; + uint32 Yell_Timer; + bool Yell; + + void Reset() + { + Fireball_Timer = 2000; + Conflagration_Timer = 20000; + ArcaneExplosion_Timer = 5000; + Yell_Timer = 2000; + Yell = false; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_CAPERNIAN_DEATH, me); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(who, CAPERNIAN_DISTANCE); + } + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Yell_Timer + if (!Yell) + { + if (Yell_Timer <= diff) + { + DoScriptText(SAY_CAPERNIAN_AGGRO, me); + Yell = true; + } else Yell_Timer -= diff; + } + + //Fireball_Timer + if (Fireball_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CAPERNIAN_FIREBALL); + Fireball_Timer = 4000; + } else Fireball_Timer -= diff; + + //Conflagration_Timer + if (Conflagration_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget && me->IsWithinDistInMap(pTarget, 30)) + DoCast(pTarget, SPELL_CONFLAGRATION); + else + DoCast(me->getVictim(), SPELL_CONFLAGRATION); + + Conflagration_Timer = 10000+rand()%5000; + } else Conflagration_Timer -= diff; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + bool InMeleeRange = false; + Unit *pTarget = NULL; + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + //if in melee range + if (pUnit && pUnit->IsWithinDistInMap(me, 5)) + { + InMeleeRange = true; + pTarget = pUnit; + break; + } + } + + if (InMeleeRange) + DoCast(pTarget, SPELL_ARCANE_EXPLOSION); + + ArcaneExplosion_Timer = 4000+rand()%2000; + } else ArcaneExplosion_Timer -= diff; + + //Do NOT deal any melee damage. + } +}; + +//Master Engineer Telonicus AI +struct boss_master_engineer_telonicusAI : public advisorbase_ai +{ + boss_master_engineer_telonicusAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Bomb_Timer; + uint32 RemoteToy_Timer; + + void Reset() + { + Bomb_Timer = 10000; + RemoteToy_Timer = 5000; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_TELONICUS_DEATH, me); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_TELONICUS_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, do nothing + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Bomb_Timer + if (Bomb_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BOMB); + Bomb_Timer = 25000; + } else Bomb_Timer -= diff; + + //RemoteToy_Timer + if (RemoteToy_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_REMOTE_TOY); + + RemoteToy_Timer = 10000+rand()%5000; + } else RemoteToy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Flame Strike AI +struct mob_kael_flamestrikeAI : public Scripted_NoMovementAI +{ + mob_kael_flamestrikeAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) {} + + uint32 Timer; + bool Casting; + bool KillSelf; + + void Reset() + { + Timer = 5000; + Casting = false; + KillSelf = false; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + } + + void MoveInLineOfSight(Unit * /*who*/) {} + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!Casting) + { + DoCast(me, SPELL_FLAME_STRIKE_VIS); + Casting = true; + } + + //Timer + if (Timer <= diff) + { + if (!KillSelf) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_FLAME_STRIKE_DMG); + } else me->Kill(me); + + KillSelf = true; + Timer = 1000; + } else Timer -= diff; + } +}; + +//Phoenix AI +struct mob_phoenix_tkAI : public ScriptedAI +{ + mob_phoenix_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 Cycle_Timer; + + void Reset() + { + Cycle_Timer = 2000; + DoCast(me, SPELL_BURN, true); + } + + void JustDied(Unit* /*killer*/) + { + //is this spell in use anylonger? + //DoCast(me, SPELL_EMBER_BLAST, true); + me->SummonCreature(NPC_PHOENIX_EGG,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,16000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Cycle_Timer <= diff) + { + //spell Burn should possible do this, but it doesn't, so do this for now. + uint32 dmg = urand(4500,5500); + if (me->GetHealth() > dmg) + me->SetHealth(uint32(me->GetHealth()-dmg)); + Cycle_Timer = 2000; + } else Cycle_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Phoenix Egg AI +struct mob_phoenix_egg_tkAI : public ScriptedAI +{ + mob_phoenix_egg_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 Rebirth_Timer; + + void Reset() + { + Rebirth_Timer = 15000; + } + + //ignore any + void MoveInLineOfSight(Unit* /*who*/) {} + + void AttackStart(Unit* who) + { + if (me->Attack(who, false)) + { + me->SetInCombatWith(who); + who->SetInCombatWith(me); + + DoStartNoMovement(who); + } + } + + void JustSummoned(Creature* summoned) + { + summoned->AddThreat(me->getVictim(), 0.0f); + summoned->CastSpell(summoned,SPELL_REBIRTH,false); + } + + void UpdateAI(const uint32 diff) + { + if (!Rebirth_Timer) + return; + + if (Rebirth_Timer <= diff) + { + me->SummonCreature(NPC_PHOENIX,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,5000); + Rebirth_Timer = 0; + } else Rebirth_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_kaelthas(Creature* pCreature) +{ + return new boss_kaelthasAI(pCreature); +} + +CreatureAI* GetAI_boss_thaladred_the_darkener(Creature* pCreature) +{ + return new boss_thaladred_the_darkenerAI(pCreature); +} + +CreatureAI* GetAI_boss_lord_sanguinar(Creature* pCreature) +{ + return new boss_lord_sanguinarAI(pCreature); +} + +CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature* pCreature) +{ + return new boss_grand_astromancer_capernianAI(pCreature); +} + +CreatureAI* GetAI_boss_master_engineer_telonicus(Creature* pCreature) +{ + return new boss_master_engineer_telonicusAI(pCreature); +} + +CreatureAI* GetAI_mob_kael_flamestrike(Creature* pCreature) +{ + return new mob_kael_flamestrikeAI(pCreature); +} + +CreatureAI* GetAI_mob_phoenix_tk(Creature* pCreature) +{ + return new mob_phoenix_tkAI(pCreature); +} + +CreatureAI* GetAI_mob_phoenix_egg_tk(Creature* pCreature) +{ + return new mob_phoenix_egg_tkAI(pCreature); +} + +void AddSC_boss_kaelthas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kaelthas"; + newscript->GetAI = &GetAI_boss_kaelthas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_thaladred_the_darkener"; + newscript->GetAI = &GetAI_boss_thaladred_the_darkener; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_sanguinar"; + newscript->GetAI = &GetAI_boss_lord_sanguinar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_grand_astromancer_capernian"; + newscript->GetAI = &GetAI_boss_grand_astromancer_capernian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_master_engineer_telonicus"; + newscript->GetAI = &GetAI_boss_master_engineer_telonicus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_kael_flamestrike"; + newscript->GetAI = &GetAI_mob_kael_flamestrike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phoenix_tk"; + newscript->GetAI = &GetAI_mob_phoenix_tk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phoenix_egg_tk"; + newscript->GetAI = &GetAI_mob_phoenix_egg_tk; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp new file mode 100644 index 00000000000..e1b60b20948 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp @@ -0,0 +1,179 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Void_Reaver +SD%Complete: 90 +SDComment: Should reset if raid are out of room. +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +enum eEnums +{ + SAY_AGGRO = -1550000, + SAY_SLAY1 = -1550001, + SAY_SLAY2 = -1550002, + SAY_SLAY3 = -1550003, + SAY_DEATH = -1550004, + SAY_POUNDING1 = -1550005, + SAY_POUNDING2 = -1550006, + + SPELL_POUNDING = 34162, + SPELL_ARCANE_ORB = 34172, + SPELL_KNOCK_AWAY = 25778, + SPELL_BERSERK = 27680 +}; + +struct boss_void_reaverAI : public ScriptedAI +{ + boss_void_reaverAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Pounding_Timer; + uint32 ArcaneOrb_Timer; + uint32 KnockAway_Timer; + uint32 Berserk_Timer; + + bool Enraged; + + void Reset() + { + Pounding_Timer = 15000; + ArcaneOrb_Timer = 3000; + KnockAway_Timer = 30000; + Berserk_Timer = 600000; + + Enraged = false; + + if (pInstance && me->isAlive()) + pInstance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Pounding + if (Pounding_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POUNDING); + + DoScriptText(RAND(SAY_POUNDING1,SAY_POUNDING2), me); + Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000) + } else Pounding_Timer -= diff; + + // Arcane Orb + if (ArcaneOrb_Timer <= diff) + { + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (!pTarget) + continue; + + // exclude pets & totems + if (pTarget->GetTypeId() != TYPEID_PLAYER) + continue; + + //18 yard radius minimum + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive() && !pTarget->IsWithinDist(me, 18, false)) + target_list.push_back(pTarget); + pTarget = NULL; + } + + if (target_list.size()) + pTarget = *(target_list.begin()+rand()%target_list.size()); + else + pTarget = me->getVictim(); + + if (pTarget) + me->CastSpell(pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(), SPELL_ARCANE_ORB, false, NULL, NULL, NULL, pTarget); + + ArcaneOrb_Timer = 3000; + } else ArcaneOrb_Timer -= diff; + + // Single Target knock back, reduces aggro + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCK_AWAY); + + //Drop 25% aggro + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-25); + + KnockAway_Timer = 30000; + } else KnockAway_Timer -= diff; + + //Berserk + if (Berserk_Timer < diff && !Enraged) + { + DoCast(me, SPELL_BERSERK); + Enraged = true; + } else Berserk_Timer -= diff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_void_reaver(Creature* pCreature) +{ + return new boss_void_reaverAI (pCreature); +} + +void AddSC_boss_void_reaver() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_void_reaver"; + newscript->GetAI = &GetAI_boss_void_reaver; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp new file mode 100644 index 00000000000..59c72071238 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp @@ -0,0 +1,176 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_The_Eye +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define MAX_ENCOUNTER 5 + +/* The Eye encounters: +0 - Kael'thas event +1 - Al' ar event +2 - Solarian Event +3 - Void Reaver event +*/ + +struct instance_the_eye : public ScriptedInstance +{ + instance_the_eye(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 ThaladredTheDarkener; + uint64 LordSanguinar; + uint64 GrandAstromancerCapernian; + uint64 MasterEngineerTelonicus; + uint64 Kaelthas; + uint64 Astromancer; + uint64 Alar; + + uint8 KaelthasEventPhase; + uint8 AlarEventPhase; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + ThaladredTheDarkener = 0; + LordSanguinar = 0; + GrandAstromancerCapernian = 0; + MasterEngineerTelonicus = 0; + Kaelthas = 0; + Astromancer = 0; + Alar = 0; + + KaelthasEventPhase = 0; + AlarEventPhase = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 20064: ThaladredTheDarkener = pCreature->GetGUID(); break; + case 20063: MasterEngineerTelonicus = pCreature->GetGUID(); break; + case 20062: GrandAstromancerCapernian = pCreature->GetGUID(); break; + case 20060: LordSanguinar = pCreature->GetGUID(); break; + case 19622: Kaelthas = pCreature->GetGUID(); break; + case 18805: Astromancer = pCreature->GetGUID(); break; + case 19514: Alar = pCreature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_THALADREDTHEDARKENER: return ThaladredTheDarkener; + case DATA_LORDSANGUINAR: return LordSanguinar; + case DATA_GRANDASTROMANCERCAPERNIAN: return GrandAstromancerCapernian; + case DATA_MASTERENGINEERTELONICUS: return MasterEngineerTelonicus; + case DATA_KAELTHAS: return Kaelthas; + case DATA_ASTROMANCER: return Astromancer; + case DATA_ALAR: return Alar; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_ALAREVENT: AlarEventPhase = data; m_auiEncounter[0] = data; break; + case DATA_HIGHASTROMANCERSOLARIANEVENT: m_auiEncounter[1] = data; break; + case DATA_VOIDREAVEREVENT: m_auiEncounter[2] = data; break; + case DATA_KAELTHASEVENT: KaelthasEventPhase = data; m_auiEncounter[3] = data; break; + } + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_ALAREVENT: return AlarEventPhase; + case DATA_HIGHASTROMANCERSOLARIANEVENT: return m_auiEncounter[1]; + case DATA_VOIDREAVEREVENT: return m_auiEncounter[2]; + case DATA_KAELTHASEVENT: return KaelthasEventPhase; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_the_eye(Map* pMap) +{ + return new instance_the_eye(pMap); +} + +void AddSC_instance_the_eye() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_the_eye"; + newscript->GetInstanceData = &GetInstanceData_instance_the_eye; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp new file mode 100644 index 00000000000..97021fdc031 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: The_Eye +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +/* ContentData +mob_crystalcore_devastator +EndContentData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define SPELL_COUNTERCHARGE 35035 +#define SPELL_KNOCKAWAY 22893 + +struct mob_crystalcore_devastatorAI : public ScriptedAI +{ + mob_crystalcore_devastatorAI(Creature *c) : ScriptedAI(c) {} + + uint32 Knockaway_Timer; + uint32 Countercharge_Timer; + + void Reset() + { + Countercharge_Timer = 9000; + Knockaway_Timer = 25000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Check if we have a current target + //Knockaway_Timer + if (Knockaway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); + + // current aggro target is knocked away pick new target + Unit* pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!pTarget || pTarget == me->getVictim()) + pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + + if (pTarget) + me->TauntApply(pTarget); + + Knockaway_Timer = 23000; + } else Knockaway_Timer -= diff; + + //Countercharge_Timer + if (Countercharge_Timer <= diff) + { + DoCast(me, SPELL_COUNTERCHARGE); + Countercharge_Timer = 45000; + } else Countercharge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_crystalcore_devastator(Creature* pCreature) +{ + return new mob_crystalcore_devastatorAI (pCreature); +} + +void AddSC_the_eye() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_crystalcore_devastator"; + newscript->GetAI = &GetAI_mob_crystalcore_devastator; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h b/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h new file mode 100644 index 00000000000..d0d3ea09061 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h @@ -0,0 +1,20 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_THE_EYE_H +#define DEF_THE_EYE_H + +#define DATA_ALAREVENT 1 +#define DATA_ASTROMANCER 2 +#define DATA_GRANDASTROMANCERCAPERNIAN 3 +#define DATA_HIGHASTROMANCERSOLARIANEVENT 4 +#define DATA_KAELTHAS 5 +#define DATA_KAELTHASEVENT 6 +#define DATA_LORDSANGUINAR 7 +#define DATA_MASTERENGINEERTELONICUS 8 +#define DATA_THALADREDTHEDARKENER 10 +#define DATA_VOIDREAVEREVENT 11 +#define DATA_ALAR 12 +#endif + diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp new file mode 100644 index 00000000000..b9c365eda65 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp @@ -0,0 +1,39 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gatewatcher_Gyrokill +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +//not used +#define SAY_AGGRO -1554000 +#define SAY_SAW_ATTACK1 -1554001 +#define SAY_SAW_ATTACK2 -1554002 +#define SAY_SLAY1 -1554003 +#define SAY_SLAY2 -1554004 +#define SAY_DEATH -1554005 + +#define SPELL_STREAM_OF_MACHINE_FLUID 35311 +#define SPELL_SAW_BLADE 35318 +#define H_SPELL_SAW_BLADE 39192 +#define SPELL_SHADOW_POWER 35322 +#define H_SPELL_SHADOW_POWER 39193 + diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp new file mode 100644 index 00000000000..50c3a6171ce --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp @@ -0,0 +1,130 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Gatewatcher_Ironhand +SD%Complete: 75 +SDComment: +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1554006 +#define SAY_HAMMER_1 -1554007 +#define SAY_HAMMER_2 -1554008 +#define SAY_SLAY_1 -1554009 +#define SAY_SLAY_2 -1554010 +#define SAY_DEATH_1 -1554011 +#define EMOTE_HAMMER -1554012 + +// Spells to be casted +#define SPELL_SHADOW_POWER 35322 +#define H_SPELL_SHADOW_POWER 39193 +#define SPELL_HAMMER_PUNCH 35326 +#define SPELL_JACKHAMMER 35327 +#define H_SPELL_JACKHAMMER 39194 +#define SPELL_STREAM_OF_MACHINE_FLUID 35311 + +// Gatewatcher Iron-Hand AI +struct boss_gatewatcher_iron_handAI : public ScriptedAI +{ + boss_gatewatcher_iron_handAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Shadow_Power_Timer; + uint32 Jackhammer_Timer; + uint32 Stream_of_Machine_Fluid_Timer; + + void Reset() + { + Shadow_Power_Timer = 25000; + Jackhammer_Timer = 45000; + Stream_of_Machine_Fluid_Timer = 55000; + + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO_1, me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH_1, me); + //TODO: Add door check/open code + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Shadow Power + if (Shadow_Power_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_POWER); + Shadow_Power_Timer = 20000 + rand()%8000; + } else Shadow_Power_Timer -= diff; + + //Jack Hammer + if (Jackhammer_Timer <= diff) + { + //TODO: expect cast this about 5 times in a row (?), announce it by emote only once + DoScriptText(EMOTE_HAMMER, me); + DoCast(me->getVictim(), SPELL_JACKHAMMER); + + //chance to yell, but not same time as emote (after spell in fact casted) + if (rand()%2) + return; + + DoScriptText(RAND(SAY_HAMMER_1,SAY_HAMMER_2), me); + Jackhammer_Timer = 30000; + } else Jackhammer_Timer -= diff; + + //Stream of Machine Fluid + if (Stream_of_Machine_Fluid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STREAM_OF_MACHINE_FLUID); + Stream_of_Machine_Fluid_Timer = 35000 + rand()%15000; + } else Stream_of_Machine_Fluid_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gatewatcher_iron_hand(Creature* pCreature) +{ + return new boss_gatewatcher_iron_handAI (pCreature); +} + +void AddSC_boss_gatewatcher_iron_hand() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gatewatcher_iron_hand"; + newscript->GetAI = &GetAI_boss_gatewatcher_iron_hand; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp new file mode 100644 index 00000000000..ededec0196d --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp @@ -0,0 +1,245 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Nethermancer_Sepethrea +SD%Complete: 90 +SDComment: Need adjustments to initial summons +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" +#include "mechanar.h" + +#define SAY_AGGRO -1554013 +#define SAY_SUMMON -1554014 +#define SAY_DRAGONS_BREATH_1 -1554015 +#define SAY_DRAGONS_BREATH_2 -1554016 +#define SAY_SLAY1 -1554017 +#define SAY_SLAY2 -1554018 +#define SAY_DEATH -1554019 + +#define SPELL_SUMMON_RAGIN_FLAMES 35275 +#define H_SPELL_SUMMON_RAGIN_FLAMES 39084 + +#define SPELL_FROST_ATTACK 35263 +#define SPELL_ARCANE_BLAST 35314 +#define SPELL_DRAGONS_BREATH 35250 +#define SPELL_KNOCKBACK 37317 +#define SPELL_SOLARBURN 35267 + +struct boss_nethermancer_sepethreaAI : public ScriptedAI +{ + boss_nethermancer_sepethreaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 frost_attack_Timer; + uint32 arcane_blast_Timer; + uint32 dragons_breath_Timer; + uint32 knockback_Timer; + uint32 solarburn_Timer; + + void Reset() + { + frost_attack_Timer = 7000 + rand()%3000; + arcane_blast_Timer = 12000 + rand()%6000; + dragons_breath_Timer = 18000 + rand()%4000; + knockback_Timer = 22000 + rand()%6000; + solarburn_Timer = 30000; + + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, me); + DoCast(who, SPELL_SUMMON_RAGIN_FLAMES); + DoScriptText(SAY_SUMMON, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frost Attack + if (frost_attack_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_ATTACK); + frost_attack_Timer = 7000 + rand()%3000; + } else frost_attack_Timer -= diff; + + //Arcane Blast + if (arcane_blast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BLAST); + arcane_blast_Timer = 15000; + } else arcane_blast_Timer -= diff; + + //Dragons Breath + if (dragons_breath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DRAGONS_BREATH); + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_DRAGONS_BREATH_1,SAY_DRAGONS_BREATH_2), me); + } + dragons_breath_Timer = 12000 + rand()%10000; + } else dragons_breath_Timer -= diff; + + //Knockback + if (knockback_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKBACK); + knockback_Timer = 15000 + rand()%10000; + } else knockback_Timer -= diff; + + //Solarburn + if (solarburn_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARBURN); + solarburn_Timer = 30000; + } else solarburn_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nethermancer_sepethrea(Creature* pCreature) +{ + return new boss_nethermancer_sepethreaAI (pCreature); +} + +#define SPELL_INFERNO 35268 +#define H_SPELL_INFERNO 39346 +#define SPELL_FIRE_TAIL 35278 + +struct mob_ragin_flamesAI : public ScriptedAI +{ + mob_ragin_flamesAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 inferno_Timer; + uint32 flame_timer; + uint32 Check_Timer; + + bool onlyonce; + + void Reset() + { + inferno_Timer = 10000; + flame_timer = 500; + Check_Timer = 2000; + onlyonce = false; + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); + } + + void EnterCombat(Unit* /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Check_Timer + if (Check_Timer <= diff) + { + if (pInstance) + { + if (pInstance->GetData(DATA_NETHERMANCER_EVENT) != IN_PROGRESS) + { + //remove + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } + } + Check_Timer = 1000; + } else Check_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (!onlyonce) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + me->GetMotionMaster()->MoveChase(pTarget); + onlyonce = true; + } + + if (inferno_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_INFERNO); + me->TauntApply(me->getVictim()); + inferno_Timer = 10000; + } else inferno_Timer -= diff; + + if (flame_timer <= diff) + { + DoCast(me, SPELL_FIRE_TAIL); + flame_timer = 500; + } else flame_timer -=diff; + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_mob_ragin_flames(Creature* pCreature) +{ + return new mob_ragin_flamesAI (pCreature); +} +void AddSC_boss_nethermancer_sepethrea() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nethermancer_sepethrea"; + newscript->GetAI = &GetAI_boss_nethermancer_sepethrea; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ragin_flames"; + newscript->GetAI = &GetAI_mob_ragin_flames; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp new file mode 100644 index 00000000000..c0c06704db7 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp @@ -0,0 +1,246 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss Pathaleon the Calculator +SD%Complete: 50 +SDComment: Event missing. Script for himself 99% blizzlike. +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1554020 +#define SAY_DOMINATION_1 -1554021 +#define SAY_DOMINATION_2 -1554022 +#define SAY_SUMMON -1554023 +#define SAY_ENRAGE -1554024 +#define SAY_SLAY_1 -1554025 +#define SAY_SLAY_2 -1554026 +#define SAY_DEATH -1554027 + +// Spells to be casted +#define SPELL_MANA_TAP 36021 +#define SPELL_ARCANE_TORRENT 36022 +#define SPELL_DOMINATION 35280 +#define H_SPELL_ARCANE_EXPLOSION 15453 +#define SPELL_FRENZY 36992 + +#define SPELL_SUMMON_NETHER_WRAITH_1 35285 //Spells work, but not implemented +#define SPELL_SUMMON_NETHER_WRAITH_2 35286 +#define SPELL_SUMMON_NETHER_WRAITH_3 35287 +#define SPELL_SUMMON_NETHER_WRAITH_4 35288 + +// Add Spells +#define SPELL_DETONATION 35058 +#define SPELL_ARCANE_MISSILES 35034 + +struct boss_pathaleon_the_calculatorAI : public ScriptedAI +{ + boss_pathaleon_the_calculatorAI(Creature *c) : ScriptedAI(c), summons(me) + { + } + + uint32 Summon_Timer; + SummonList summons; + uint32 ManaTap_Timer; + uint32 ArcaneTorrent_Timer; + uint32 Domination_Timer; + uint32 ArcaneExplosion_Timer; + + bool Enraged; + + uint32 Counter; + + void Reset() + { + Summon_Timer = 30000; + ManaTap_Timer = 12000 + rand()%8000; + ArcaneTorrent_Timer = 16000 + rand()%9000; + Domination_Timer = 25000 + rand()%15000; + ArcaneExplosion_Timer = 8000 + rand()%5000; + + Enraged = false; + + Counter = 0; + summons.DespawnAll(); + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + summons.DespawnAll(); + } + + void JustSummoned(Creature *summon) {summons.Summon(summon);} + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Summon_Timer <= diff) + { + for (uint8 i = 0; i < 3; ++i) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + Creature* Wraith = me->SummonCreature(21062,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + if (pTarget && Wraith) + Wraith->AI()->AttackStart(pTarget); + } + DoScriptText(SAY_SUMMON, me); + Summon_Timer = 30000 + rand()%15000; + } else Summon_Timer -= diff; + + if (ManaTap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MANA_TAP); + ManaTap_Timer = 14000 + rand()%8000; + } else ManaTap_Timer -= diff; + + if (ArcaneTorrent_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_TORRENT); + ArcaneTorrent_Timer = 12000 + rand()%6000; + } else ArcaneTorrent_Timer -= diff; + + if (Domination_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + DoScriptText(RAND(SAY_DOMINATION_1,SAY_DOMINATION_2), me); + + DoCast(pTarget, SPELL_DOMINATION); + } + Domination_Timer = 25000 + rand()%5000; + } else Domination_Timer -= diff; + + //Only casting if Heroic Mode is used + if (IsHeroic()) + { + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), H_SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 10000 + rand()%4000; + } else ArcaneExplosion_Timer -= diff; + } + + if (!Enraged && me->GetHealth()*100 / me->GetMaxHealth() < 21) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(SAY_ENRAGE, me); + Enraged = true; + + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_pathaleon_the_calculator(Creature* pCreature) +{ + return new boss_pathaleon_the_calculatorAI (pCreature); +} + +struct mob_nether_wraithAI : public ScriptedAI +{ + mob_nether_wraithAI(Creature *c) : ScriptedAI(c) {} + + uint32 ArcaneMissiles_Timer; + uint32 Detonation_Timer; + uint32 Die_Timer; + bool Detonation; + + void Reset() + { + ArcaneMissiles_Timer = 1000 + rand()%3000; + Detonation_Timer = 20000; + Die_Timer = 2200; + Detonation = false; + + } + + void EnterCombat(Unit* /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ArcaneMissiles_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_ARCANE_MISSILES); + else + DoCast(me->getVictim(), SPELL_ARCANE_MISSILES); + + ArcaneMissiles_Timer = 5000 + rand()%5000; + } else ArcaneMissiles_Timer -=diff; + + if (!Detonation) + { + if (Detonation_Timer <= diff) + { + DoCast(me, SPELL_DETONATION); + Detonation = true; + } else Detonation_Timer -= diff; + } + + if (Detonation) + { + if (Die_Timer <= diff) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } else Die_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_mob_nether_wraith(Creature* pCreature) +{ + return new mob_nether_wraithAI (pCreature); +} + +void AddSC_boss_pathaleon_the_calculator() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_pathaleon_the_calculator"; + newscript->GetAI = &GetAI_boss_pathaleon_the_calculator; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nether_wraith"; + newscript->GetAI = &GetAI_mob_nether_wraith; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp new file mode 100644 index 00000000000..c70da24ea3f --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Mechanar +SD%Complete: 100 +SDComment: +SDCategory: Mechanar +EndScriptData */ + +#include "ScriptedPch.h" +#include "mechanar.h" + +#define MAX_ENCOUNTER 1 + +struct instance_mechanar : public ScriptedInstance +{ + instance_mechanar(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_NETHERMANCER_EVENT: return m_auiEncounter[0]; + } + + return false; + } + + uint64 GetData64 (uint32 /*identifier*/) + { + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_NETHERMANCER_EVENT: m_auiEncounter[0] = data; break; + } + } +}; + +InstanceData* GetInstanceData_instance_mechanar(Map* pMap) +{ + return new instance_mechanar(pMap); +} + +void AddSC_instance_mechanar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_mechanar"; + newscript->GetInstanceData = &GetInstanceData_instance_mechanar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h b/src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h new file mode 100644 index 00000000000..d1b53eebf53 --- /dev/null +++ b/src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h @@ -0,0 +1,6 @@ +#ifndef DEF_MECHANAR_H +#define DEF_MECHANAR_H + +#define DATA_NETHERMANCER_EVENT 1 +#endif + diff --git a/src/server/scripts/Outland/terokkar_forest.cpp b/src/server/scripts/Outland/terokkar_forest.cpp new file mode 100644 index 00000000000..d593fdd8ca9 --- /dev/null +++ b/src/server/scripts/Outland/terokkar_forest.cpp @@ -0,0 +1,680 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Terokkar_Forest +SD%Complete: 85 +SDComment: Quest support: 9889, 10009, 10873, 10896, 10898, 11096, 10052, 10051. Skettis->Ogri'la Flight +SDCategory: Terokkar Forest +EndScriptData */ + +/* ContentData +mob_unkor_the_ruthless +mob_infested_root_walker +mob_rotting_forest_rager +mob_netherweb_victim +npc_floon +npc_isla_starmane +npc_slim +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## mob_unkor_the_ruthless +######*/ + +#define SAY_SUBMIT -1000194 + +#define FACTION_HOSTILE 45 +#define FACTION_FRIENDLY 35 +#define QUEST_DONTKILLTHEFATONE 9889 + +#define SPELL_PULVERIZE 2676 +//#define SPELL_QUID9889 32174 + +struct mob_unkor_the_ruthlessAI : public ScriptedAI +{ + mob_unkor_the_ruthlessAI(Creature* c) : ScriptedAI(c) {} + + bool CanDoQuest; + uint32 UnkorUnfriendly_Timer; + uint32 Pulverize_Timer; + + void Reset() + { + CanDoQuest = false; + UnkorUnfriendly_Timer = 0; + Pulverize_Timer = 3000; + me->SetStandState(UNIT_STAND_STATE_STAND); + me->setFaction(FACTION_HOSTILE); + } + + void EnterCombat(Unit * /*who*/) {} + + void DoNice() + { + DoScriptText(SAY_SUBMIT, me); + me->setFaction(FACTION_FRIENDLY); + me->SetStandState(UNIT_STAND_STATE_SIT); + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + UnkorUnfriendly_Timer = 60000; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetTypeId() == TYPEID_PLAYER) + if ((me->GetHealth()-damage)*100 / me->GetMaxHealth() < 30) + { + if (Group* pGroup = CAST_PLR(done_by)->GetGroup()) + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *pGroupie = itr->getSource(); + if (pGroupie && + pGroupie->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && + pGroupie->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, 18260) == 10) + { + pGroupie->AreaExploredOrEventHappens(QUEST_DONTKILLTHEFATONE); + if (!CanDoQuest) + CanDoQuest = true; + } + } + } else + if (CAST_PLR(done_by)->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && + CAST_PLR(done_by)->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, 18260) == 10) + { + CAST_PLR(done_by)->AreaExploredOrEventHappens(QUEST_DONTKILLTHEFATONE); + CanDoQuest = true; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (CanDoQuest) + { + if (!UnkorUnfriendly_Timer) + { + //DoCast(me, SPELL_QUID9889); //not using spell for now + DoNice(); + } + else + { + if (UnkorUnfriendly_Timer <= diff) + { + EnterEvadeMode(); + return; + } else UnkorUnfriendly_Timer -= diff; + } + } + + if (!UpdateVictim()) + return; + + if (Pulverize_Timer <= diff) + { + DoCast(me, SPELL_PULVERIZE); + Pulverize_Timer = 9000; + } else Pulverize_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_unkor_the_ruthless(Creature* pCreature) +{ + return new mob_unkor_the_ruthlessAI (pCreature); +} + +/*###### +## mob_infested_root_walker +######*/ + +struct mob_infested_root_walkerAI : public ScriptedAI +{ + mob_infested_root_walkerAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + void EnterCombat(Unit * /*who*/) { } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by && done_by->GetTypeId() == TYPEID_PLAYER) + if (me->GetHealth() <= damage) + if (rand()%100 < 75) + //Summon Wood Mites + DoCast(me, 39130, true); + } +}; +CreatureAI* GetAI_mob_infested_root_walker(Creature* pCreature) +{ + return new mob_infested_root_walkerAI (pCreature); +} + +/*###### +## mob_skywing +######*/ +struct npc_skywingAI : public npc_escortAI +{ +public: + npc_skywingAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + if (!pPlayer) + return; + + switch(i) + { + case 8: + pPlayer->AreaExploredOrEventHappens(10898); + break; + } + } + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + if (who->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(who)->GetQuestStatus(10898) == QUEST_STATUS_INCOMPLETE) + { + float Radius = 10.0; + if (me->IsWithinDistInMap(who, Radius)) + { + Start(false, false, who->GetGUID()); + } + } + } + } + + void Reset() {} + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_skywingAI(Creature* pCreature) +{ + return new npc_skywingAI(pCreature); +} + +/*###### +## mob_rotting_forest_rager +######*/ + +struct mob_rotting_forest_ragerAI : public ScriptedAI +{ + mob_rotting_forest_ragerAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + void EnterCombat(Unit * /*who*/) { } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetTypeId() == TYPEID_PLAYER) + if (me->GetHealth() <= damage) + if (rand()%100 < 75) + //Summon Lots of Wood Mights + DoCast(me, 39134, true); + } +}; +CreatureAI* GetAI_mob_rotting_forest_rager(Creature* pCreature) +{ + return new mob_rotting_forest_ragerAI (pCreature); +} + +/*###### +## mob_netherweb_victim +######*/ + +#define QUEST_TARGET 22459 +//#define SPELL_FREE_WEBBED 38950 + +const uint32 netherwebVictims[6] = +{ + 18470, 16805, 21242, 18452, 22482, 21285 +}; +struct mob_netherweb_victimAI : public ScriptedAI +{ + mob_netherweb_victimAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + void EnterCombat(Unit * /*who*/) { } + void MoveInLineOfSight(Unit * /*who*/) { } + + void JustDied(Unit* Killer) + { + if (Killer->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(Killer)->GetQuestStatus(10873) == QUEST_STATUS_INCOMPLETE) + { + if (rand()%100 < 25) + { + me->SummonCreature(QUEST_TARGET, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + CAST_PLR(Killer)->KilledMonsterCredit(QUEST_TARGET, me->GetGUID()); + } + else + me->SummonCreature(netherwebVictims[rand()%6], 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + + if (rand()%100 < 75) + me->SummonCreature(netherwebVictims[rand()%6], 0.0f, 0.0f, 0.0f,0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + me->SummonCreature(netherwebVictims[rand()%6], 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + } + } + } +}; +CreatureAI* GetAI_mob_netherweb_victim(Creature* pCreature) +{ + return new mob_netherweb_victimAI (pCreature); +} + +/*###### +## npc_floon +######*/ + +#define GOSSIP_FLOON1 "You owe Sim'salabim money. Hand them over or die!" +#define GOSSIP_FLOON2 "Hand over the money or die...again!" + +enum eFloon +{ + SAY_FLOON_ATTACK = -1000195, + + SPELL_SILENCE = 6726, + SPELL_FROSTBOLT = 9672, + SPELL_FROST_NOVA = 11831, + + FACTION_HOSTILE_FL = 1738, + QUEST_CRACK_SKULLS = 10009 +}; + +struct npc_floonAI : public ScriptedAI +{ + npc_floonAI(Creature* c) : ScriptedAI(c) + { + m_uiNormFaction = c->getFaction(); + } + + uint32 m_uiNormFaction; + uint32 Silence_Timer; + uint32 Frostbolt_Timer; + uint32 FrostNova_Timer; + + void Reset() + { + Silence_Timer = 2000; + Frostbolt_Timer = 4000; + FrostNova_Timer = 9000; + if (me->getFaction() != m_uiNormFaction) + me->setFaction(m_uiNormFaction); + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Silence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + Silence_Timer = 30000; + } else Silence_Timer -= diff; + + if (FrostNova_Timer <= diff) + { + DoCast(me, SPELL_FROST_NOVA); + FrostNova_Timer = 20000; + } else FrostNova_Timer -= diff; + + if (Frostbolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 5000; + } else Frostbolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_floon(Creature* pCreature) +{ + return new npc_floonAI (pCreature); +} + +bool GossipHello_npc_floon(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FLOON1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(9442, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_floon(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FLOON2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(9443, pCreature->GetGUID()); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(FACTION_HOSTILE_FL); + DoScriptText(SAY_FLOON_ATTACK, pCreature, pPlayer); + pCreature->AI()->AttackStart(pPlayer); + } + return true; +} + +/*###### +## npc_isla_starmane +######*/ + +#define SAY_PROGRESS_1 -1100353 +#define SAY_PROGRESS_2 -1100354 +#define SAY_PROGRESS_3 -1100355 +#define SAY_PROGRESS_4 -1100356 + +#define QUEST_EFTW_H 10052 +#define QUEST_EFTW_A 10051 +#define GO_CAGE 182794 +#define SPELL_CAT 32447 + +struct npc_isla_starmaneAI : public npc_escortAI +{ + npc_isla_starmaneAI(Creature* c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 0: + { + GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 10); + if (Cage) + Cage->SetGoState(GO_STATE_ACTIVE); + } + break; + case 2: DoScriptText(SAY_PROGRESS_1, me, pPlayer); break; + case 5: DoScriptText(SAY_PROGRESS_2, me, pPlayer); break; + case 6: DoScriptText(SAY_PROGRESS_3, me, pPlayer); break; + case 29:DoScriptText(SAY_PROGRESS_4, me, pPlayer); + if (pPlayer) + { + if (pPlayer->GetTeam() == ALLIANCE) + pPlayer->GroupEventHappens(QUEST_EFTW_A, me); + else if (pPlayer->GetTeam() == HORDE) + pPlayer->GroupEventHappens(QUEST_EFTW_H, me); + } + me->SetInFront(pPlayer); break; + case 30: me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); break; + case 31: DoCast(me, SPELL_CAT); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); break; + } + } + + void Reset() + { + me->RestoreFaction(); + } + + void JustDied(Unit* /*killer*/) + { + if (Player* pPlayer = GetPlayerForEscort()) + { + if (pPlayer->GetTeam() == ALLIANCE) + pPlayer->FailQuest(QUEST_EFTW_A); + else if (pPlayer->GetTeam() == HORDE) + pPlayer->FailQuest(QUEST_EFTW_H); + } + } +}; + +bool QuestAccept_npc_isla_starmane(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_EFTW_H || quest->GetQuestId() == QUEST_EFTW_A) + { + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + pCreature->setFaction(113); + } + return true; +} + +CreatureAI* GetAI_npc_isla_starmaneAI(Creature* pCreature) +{ + return new npc_isla_starmaneAI(pCreature); +} + +/*###### +## go_skull_pile +######*/ +#define GOSSIP_S_DARKSCREECHER_AKKARAI "Summon Darkscreecher Akkarai" +#define GOSSIP_S_KARROG "Summon Karrog" +#define GOSSIP_S_GEZZARAK_THE_HUNTRESS "Summon Gezzarak the Huntress" +#define GOSSIP_S_VAKKIZ_THE_WINDRAGER "Summon Vakkiz the Windrager" + +bool GossipHello_go_skull_pile(Player* pPlayer, GameObject* pGo) +{ + if ((pPlayer->GetQuestStatus(11885) == QUEST_STATUS_INCOMPLETE) || pPlayer->GetQuestRewardStatus(11885)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_DARKSCREECHER_AKKARAI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_KARROG, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_GEZZARAK_THE_HUNTRESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_VAKKIZ_THE_WINDRAGER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + } + + pPlayer->SEND_GOSSIP_MENU(pGo->GetGOInfo()->questgiver.gossipID, pGo->GetGUID()); + return true; +} + +void SendActionMenu_go_skull_pile(Player* pPlayer, GameObject* /*pGo*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->CastSpell(pPlayer,40642,false); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->CastSpell(pPlayer,40640,false); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->CastSpell(pPlayer,40632,false); + break; + case GOSSIP_ACTION_INFO_DEF + 4: + pPlayer->CastSpell(pPlayer,40644,false); + break; + } +} + +bool GossipSelect_go_skull_pile(Player* pPlayer, GameObject* pGo, uint32 uiSender, uint32 uiAction) +{ + switch(uiSender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_go_skull_pile(pPlayer, pGo, uiAction); break; + } + return true; +} + +/*###### +## npc_slim +######*/ + +enum eSlim +{ + FACTION_CONSORTIUM = 933 +}; + +bool GossipHello_npc_slim(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isVendor() && pPlayer->GetReputationRank(FACTION_CONSORTIUM) >= REP_FRIENDLY) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + pPlayer->SEND_GOSSIP_MENU(9896, pCreature->GetGUID()); + } + else + pPlayer->SEND_GOSSIP_MENU(9895, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_slim(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*######## +####npc_akuno +#####*/ + +enum eAkuno +{ + QUEST_ESCAPING_THE_TOMB = 10887, + NPC_CABAL_SKRIMISHER = 21661 +}; + +struct npc_akunoAI : public npc_escortAI +{ + npc_akunoAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 3: + me->SummonCreature(NPC_CABAL_SKRIMISHER,-2795.99,5420.33,-34.53,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(NPC_CABAL_SKRIMISHER,-2793.55,5412.79,-34.53,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + case 11: + if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) + pPlayer->GroupEventHappens(QUEST_ESCAPING_THE_TOMB,me); + break; + } + } + + void JustSummoned(Creature* summon) + { + summon->AI()->AttackStart(me); + } +}; + +bool QuestAccept_npc_akuno(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_ESCAPING_THE_TOMB) + { + if (npc_akunoAI* pEscortAI = CAST_AI(npc_akunoAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID()); + + if (pPlayer->GetTeamId() == TEAM_ALLIANCE) + pCreature->setFaction(FACTION_ESCORT_A_NEUTRAL_PASSIVE); + else + pCreature->setFaction(FACTION_ESCORT_H_NEUTRAL_PASSIVE); + } + return true; +} + +CreatureAI* GetAI_npc_akuno(Creature* pCreature) +{ + return new npc_akunoAI(pCreature); +} + +void AddSC_terokkar_forest() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_unkor_the_ruthless"; + newscript->GetAI = &GetAI_mob_unkor_the_ruthless; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_infested_root_walker"; + newscript->GetAI = &GetAI_mob_infested_root_walker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_rotting_forest_rager"; + newscript->GetAI = &GetAI_mob_rotting_forest_rager; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_netherweb_victim"; + newscript->GetAI = &GetAI_mob_netherweb_victim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_floon"; + newscript->GetAI = &GetAI_npc_floon; + newscript->pGossipHello = &GossipHello_npc_floon; + newscript->pGossipSelect = &GossipSelect_npc_floon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_isla_starmane"; + newscript->GetAI = &GetAI_npc_isla_starmaneAI; + newscript->pQuestAccept = &QuestAccept_npc_isla_starmane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_skull_pile"; + newscript->pGOHello = &GossipHello_go_skull_pile; + newscript->pGOSelect = &GossipSelect_go_skull_pile; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_skywing"; + newscript->GetAI = &GetAI_npc_skywingAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_slim"; + newscript->pGossipHello = &GossipHello_npc_slim; + newscript->pGossipSelect = &GossipSelect_npc_slim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_akuno"; + newscript->GetAI = &GetAI_npc_akuno; + newscript->pQuestAccept = &QuestAccept_npc_akuno; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/zangarmarsh.cpp b/src/server/scripts/Outland/zangarmarsh.cpp new file mode 100644 index 00000000000..5a07165595b --- /dev/null +++ b/src/server/scripts/Outland/zangarmarsh.cpp @@ -0,0 +1,424 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Zangarmarsh +SD%Complete: 100 +SDComment: Quest support: 9752, 9785, 9803, 10009. Mark Of ... buffs. +SDCategory: Zangarmarsh +EndScriptData */ + +/* ContentData +npcs_ashyen_and_keleth +npc_cooshcoosh +npc_elder_kuruti +npc_mortog_steamhead +npc_kayra_longmane +npc_timothy_daniels +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +/*###### +## npcs_ashyen_and_keleth +######*/ + +#define GOSSIP_ITEM_BLESS_ASH "Grant me your mark, wise ancient." +#define GOSSIP_ITEM_BLESS_KEL "Grant me your mark, mighty ancient." +//signed for 17900 but used by 17900,17901 +#define GOSSIP_REWARD_BLESS -1000359 +//#define TEXT_BLESSINGS "" + +bool GossipHello_npcs_ashyen_and_keleth(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetReputationRank(942) > REP_NEUTRAL) + { + if (pCreature->GetEntry() == 17900) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BLESS_ASH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if (pCreature->GetEntry() == 17901) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BLESS_KEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + } + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npcs_ashyen_and_keleth(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pCreature->setPowerType(POWER_MANA); + pCreature->SetMaxPower(POWER_MANA,200); //set a "fake" mana value, we can't depend on database doing it in this case + pCreature->SetPower(POWER_MANA,200); + + if (pCreature->GetEntry() == 17900) //check which Creature we are dealing with + { + switch (pPlayer->GetReputationRank(942)) + { //mark of lore + case REP_FRIENDLY: + pCreature->CastSpell(pPlayer, 31808, true); + DoScriptText(GOSSIP_REWARD_BLESS, pCreature); + break; + case REP_HONORED: + pCreature->CastSpell(pPlayer, 31810, true); + DoScriptText(GOSSIP_REWARD_BLESS, pCreature); + break; + case REP_REVERED: + pCreature->CastSpell(pPlayer, 31811, true); + DoScriptText(GOSSIP_REWARD_BLESS, pCreature); + break; + case REP_EXALTED: + pCreature->CastSpell(pPlayer, 31815, true); + DoScriptText(GOSSIP_REWARD_BLESS, pCreature); + break; + } + } + + if (pCreature->GetEntry() == 17901) + { + switch (pPlayer->GetReputationRank(942)) //mark of war + { + case REP_FRIENDLY: + pCreature->CastSpell(pPlayer, 31807, true); + DoScriptText(GOSSIP_REWARD_BLESS, pCreature); + break; + case REP_HONORED: + pCreature->CastSpell(pPlayer, 31812, true); + DoScriptText(GOSSIP_REWARD_BLESS, pCreature); + break; + case REP_REVERED: + pCreature->CastSpell(pPlayer, 31813, true); + DoScriptText(GOSSIP_REWARD_BLESS, pCreature); + break; + case REP_EXALTED: + pCreature->CastSpell(pPlayer, 31814, true); + DoScriptText(GOSSIP_REWARD_BLESS, pCreature); + break; + } + } + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + } + return true; +} + +/*###### +## npc_cooshcoosh +######*/ + +#define GOSSIP_COOSH "You owe Sim'salabim money. Hand them over or die!" + +enum eCooshhooosh +{ + SPELL_LIGHTNING_BOLT = 9532, + QUEST_CRACK_SKULLS = 10009, + FACTION_HOSTILE_CO = 45 +}; + +struct npc_cooshcooshAI : public ScriptedAI +{ + npc_cooshcooshAI(Creature* c) : ScriptedAI(c) + { + m_uiNormFaction = c->getFaction(); + } + + uint32 m_uiNormFaction; + uint32 LightningBolt_Timer; + + void Reset() + { + LightningBolt_Timer = 2000; + if (me->getFaction() != m_uiNormFaction) + me->setFaction(m_uiNormFaction); + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (LightningBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); + LightningBolt_Timer = 5000; + } else LightningBolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_cooshcoosh(Creature* pCreature) +{ + return new npc_cooshcooshAI (pCreature); +} + +bool GossipHello_npc_cooshcoosh(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_COOSH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(9441, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_cooshcoosh(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(FACTION_HOSTILE_CO); + pCreature->AI()->AttackStart(pPlayer); + } + return true; +} + +/*###### +## npc_elder_kuruti +######*/ + +#define GOSSIP_ITEM_KUR1 "Greetings, elder. It is time for your people to end their hostility towards the draenei and their allies." +#define GOSSIP_ITEM_KUR2 "I did not mean to deceive you, elder. The draenei of Telredor thought to approach you in a way that would seem familiar to you." +#define GOSSIP_ITEM_KUR3 "I will tell them. Farewell, elder." + +bool GossipHello_npc_elder_kuruti(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(9803) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(9226, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_elder_kuruti(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(9227, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(9229, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + if (!pPlayer->HasItemCount(24573,1)) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 24573, 1, false); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, 24573, true); + } + else + pPlayer->SendEquipError(msg,NULL,NULL); + } + pPlayer->SEND_GOSSIP_MENU(9231, pCreature->GetGUID()); + break; + } + } + return true; +} + +/*###### +## npc_mortog_steamhead +######*/ + +bool GossipHello_npc_mortog_steamhead(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isVendor() && pPlayer->GetReputationRank(942) == REP_EXALTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_mortog_steamhead(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + { + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + } + return true; +} + +/*###### +## npc_kayra_longmane +######*/ + +enum eKayra +{ + SAY_START = -1000343, + SAY_AMBUSH1 = -1000344, + SAY_PROGRESS = -1000345, + SAY_AMBUSH2 = -1000346, + SAY_NEAR_END = -1000347, + SAY_END = -1000348, //this is signed for 10646 + + QUEST_ESCAPE_FROM = 9752, + NPC_SLAVEBINDER = 18042 +}; + +struct npc_kayra_longmaneAI : public npc_escortAI +{ + npc_kayra_longmaneAI(Creature* c) : npc_escortAI(c) {} + + void Reset() { } + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch(i) + { + case 4: + DoScriptText(SAY_AMBUSH1, me, pPlayer); + DoSpawnCreature(NPC_SLAVEBINDER, -10.0f, -5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + DoSpawnCreature(NPC_SLAVEBINDER, -8.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 5: + DoScriptText(SAY_PROGRESS, me, pPlayer); + SetRun(); + break; + case 16: + DoScriptText(SAY_AMBUSH2, me, pPlayer); + DoSpawnCreature(NPC_SLAVEBINDER, -10.0f, -5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + DoSpawnCreature(NPC_SLAVEBINDER, -8.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + break; + case 17: + SetRun(false); + DoScriptText(SAY_NEAR_END, me, pPlayer); + break; + case 25: + DoScriptText(SAY_END, me, pPlayer); + pPlayer->GroupEventHappens(QUEST_ESCAPE_FROM, me); + break; + } + } +}; + +bool QuestAccept_npc_kayra_longmane(Player* pPlayer, Creature* pCreature, Quest const* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_ESCAPE_FROM) + { + DoScriptText(SAY_START, pCreature, pPlayer); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_kayra_longmaneAI, pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID()); + } + return true; +} + +CreatureAI* GetAI_npc_kayra_longmaneAI(Creature* pCreature) +{ + return new npc_kayra_longmaneAI(pCreature); +} + +/*###### +## npc_timothy_daniels +######*/ + +#define GOSSIP_TIMOTHY_DANIELS_ITEM1 "Specialist, eh? Just what kind of specialist are you, anyway?" +#define GOSSIP_TEXT_BROWSE_POISONS "Let me browse your reagents and poison supplies." + +enum eTimothy +{ + GOSSIP_TEXTID_TIMOTHY_DANIELS1 = 9239 +}; + +bool GossipHello_npc_timothy_daniels(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_POISONS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TIMOTHY_DANIELS_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_timothy_daniels(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TIMOTHY_DANIELS1, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + } + + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_zangarmarsh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npcs_ashyen_and_keleth"; + newscript->pGossipHello = &GossipHello_npcs_ashyen_and_keleth; + newscript->pGossipSelect = &GossipSelect_npcs_ashyen_and_keleth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_cooshcoosh"; + newscript->GetAI = &GetAI_npc_cooshcoosh; + newscript->pGossipHello = &GossipHello_npc_cooshcoosh; + newscript->pGossipSelect = &GossipSelect_npc_cooshcoosh; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_elder_kuruti"; + newscript->pGossipHello = &GossipHello_npc_elder_kuruti; + newscript->pGossipSelect = &GossipSelect_npc_elder_kuruti; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mortog_steamhead"; + newscript->pGossipHello = &GossipHello_npc_mortog_steamhead; + newscript->pGossipSelect = &GossipSelect_npc_mortog_steamhead; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_kayra_longmane"; + newscript->GetAI = &GetAI_npc_kayra_longmaneAI; + newscript->pQuestAccept = &QuestAccept_npc_kayra_longmane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_timothy_daniels"; + newscript->pGossipHello = &GossipHello_npc_timothy_daniels; + newscript->pGossipSelect = &GossipSelect_npc_timothy_daniels; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/World/areatrigger_scripts.cpp b/src/server/scripts/World/areatrigger_scripts.cpp new file mode 100644 index 00000000000..9a75263d35c --- /dev/null +++ b/src/server/scripts/World/areatrigger_scripts.cpp @@ -0,0 +1,285 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Areatrigger_Scripts +SD%Complete: 100 +SDComment: Scripts for areatriggers +SDCategory: Areatrigger +EndScriptData */ + +/* ContentData +at_aldurthar_gate q13315/q13351 +at_coilfang_waterfall 4591 +at_legion_teleporter 4560 Teleporter TO Invasion Point: Cataclysm +at_ravenholdt +at_warsong_slaughterhouse +at_warsong_grainery +at_torp_farm +at_warsong_farms q11686 +at_stormwright_shelf q12741 +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## AreaTrigger_at_aldurthar_gate +######*/ + +enum eAldurtharGate +{ + TRIGGER_SOUTH = 5284, + + TRIGGER_CENTRAL = 5285, + TRIGGER_NORTH = 5286, + TRIGGER_NORTHWEST = 5287, + + NPC_SOUTH_GATE = 32195, + NPC_CENTRAL_GATE = 32196, + NPC_NORTH_GATE = 32197, + NPC_NORTHWEST_GATE = 32199 +}; + +bool AreaTrigger_at_aldurthar_gate(Player* pPlayer, const AreaTriggerEntry* pAt) +{ + switch(pAt->id) + { + case TRIGGER_SOUTH: pPlayer->KilledMonsterCredit(NPC_SOUTH_GATE, 0); break; + case TRIGGER_CENTRAL: pPlayer->KilledMonsterCredit(NPC_CENTRAL_GATE, 0); break; + case TRIGGER_NORTH: pPlayer->KilledMonsterCredit(NPC_NORTH_GATE, 0); break; + case TRIGGER_NORTHWEST: pPlayer->KilledMonsterCredit(NPC_NORTHWEST_GATE, 0); break; + } + return true; +} + +/*###### +## at_coilfang_waterfall +######*/ + +enum eCoilfangGOs +{ + GO_COILFANG_WATERFALL = 184212 +}; + +bool AreaTrigger_at_coilfang_waterfall(Player *pPlayer, const AreaTriggerEntry * /*pAt*/) +{ + if (GameObject* pGo = GetClosestGameObjectWithEntry(pPlayer, GO_COILFANG_WATERFALL, 35.0f)) + if (pGo->getLootState() == GO_READY) + pGo->UseDoorOrButton(); + + return false; +} + +/*##### +## at_legion_teleporter +#####*/ + +enum eLegionTeleporter +{ + SPELL_TELE_A_TO = 37387, + QUEST_GAINING_ACCESS_A = 10589, + + SPELL_TELE_H_TO = 37389, + QUEST_GAINING_ACCESS_H = 10604 +}; + +bool AreaTrigger_at_legion_teleporter(Player *pPlayer, const AreaTriggerEntry * /*pAt*/) +{ + if (pPlayer->isAlive() && !pPlayer->isInCombat()) + { + if (pPlayer->GetTeam() == ALLIANCE && pPlayer->GetQuestRewardStatus(QUEST_GAINING_ACCESS_A)) + { + pPlayer->CastSpell(pPlayer, SPELL_TELE_A_TO, false); + return true; + } + + if (pPlayer->GetTeam() == HORDE && pPlayer->GetQuestRewardStatus(QUEST_GAINING_ACCESS_H)) + { + pPlayer->CastSpell(pPlayer, SPELL_TELE_H_TO, false); + return true; + } + + return false; + } + return false; +} + +enum eRavenholdt +{ + QUEST_MANOR_RAVENHOLDT = 6681, + NPC_RAVENHOLDT = 13936 +}; + +bool AreaTrigger_at_ravenholdt(Player* pPlayer, const AreaTriggerEntry* /*pAt*/) +{ + if (pPlayer->GetQuestStatus(QUEST_MANOR_RAVENHOLDT) == QUEST_STATUS_INCOMPLETE) + pPlayer->KilledMonsterCredit(NPC_RAVENHOLDT, 0); + + return false; +} + +/*###### +## at_warsong_farms +######*/ + +enum eWarsongFarms +{ + QUEST_THE_WARSONG_FARMS = 11686, + + NPC_CREDIT_SLAUGHTERHOUSE = 25672, + NPC_CREDIT_GRAINERY = 25669, + NPC_CREDIT_TORP_FARM = 25671, + + AT_SLAUGHTERHOUSE = 4873, + AT_GRAINERY = 4871, + AT_TORP_FARM = 4872 +}; + +bool AreaTrigger_at_warsong_farms(Player* pPlayer, const AreaTriggerEntry* pAt) +{ + if (!pPlayer->isDead() && pPlayer->GetQuestStatus(QUEST_THE_WARSONG_FARMS) == QUEST_STATUS_INCOMPLETE) + { + switch(pAt->id) + { + case AT_SLAUGHTERHOUSE: pPlayer->KilledMonsterCredit(NPC_CREDIT_SLAUGHTERHOUSE, 0); break; + case AT_GRAINERY: pPlayer->KilledMonsterCredit(NPC_CREDIT_GRAINERY, 0); break; + case AT_TORP_FARM: pPlayer->KilledMonsterCredit(NPC_CREDIT_TORP_FARM, 0); break; + } + } + return true; + } + +/*###### +## at_stormwright_shelf +######*/ + +enum eStormwrightShelf +{ + QUEST_STRENGTH_OF_THE_TEMPEST = 12741, + + SPELL_CREATE_TRUE_POWER_OF_THE_TEMPEST = 53067 +}; + +bool AreaTrigger_at_stormwright_shelf(Player* pPlayer, const AreaTriggerEntry* /*pAt*/) +{ + if (!pPlayer->isDead() && pPlayer->GetQuestStatus(QUEST_STRENGTH_OF_THE_TEMPEST) == QUEST_STATUS_INCOMPLETE) + pPlayer->CastSpell(pPlayer, SPELL_CREATE_TRUE_POWER_OF_THE_TEMPEST, false); + + return true; +} + +/*###### +## at_scent_larkorwi +######*/ + +enum eScentLarkorwi +{ + QUEST_SCENT_OF_LARKORWI = 4291, + NPC_LARKORWI_MATE = 9683 +}; + +bool AreaTrigger_at_scent_larkorwi(Player* pPlayer, const AreaTriggerEntry* /*pAt*/) +{ + if (!pPlayer->isDead() && pPlayer->GetQuestStatus(QUEST_SCENT_OF_LARKORWI) == QUEST_STATUS_INCOMPLETE) + { + if (!pPlayer->FindNearestCreature(NPC_LARKORWI_MATE,15)) + pPlayer->SummonCreature(NPC_LARKORWI_MATE, pPlayer->GetPositionX()+5, pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 3.3, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 100000); + } + + return false; +} + +/*##### +## at_last_rites +#####*/ + +enum eAtLastRites +{ + QUEST_LAST_RITES = 12019 +}; + +bool AreaTrigger_at_last_rites(Player* pPlayer, const AreaTriggerEntry* pAt) +{ + if (pPlayer->GetQuestStatus(QUEST_LAST_RITES) != QUEST_STATUS_INCOMPLETE) + return false; + + WorldLocation pPosition; + + switch(pAt->id) + { + case 5332: + case 5338: + pPosition = WorldLocation(571,3733.68,3563.25,290.812,3.665192); + break; + case 5334: + pPosition = WorldLocation(571,3802.38,3585.95,49.5765,0); + break; + case 5340: + pPosition = WorldLocation(571,3687.91,3577.28,473.342,0); + break; + default: + return false; + } + + pPlayer->TeleportTo(pPosition); + + return false; +} + +void AddSC_areatrigger_scripts() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "at_aldurthar_gate"; + newscript->pAreaTrigger = &AreaTrigger_at_aldurthar_gate; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_coilfang_waterfall"; + newscript->pAreaTrigger = &AreaTrigger_at_coilfang_waterfall; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_legion_teleporter"; + newscript->pAreaTrigger = &AreaTrigger_at_legion_teleporter; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_ravenholdt"; + newscript->pAreaTrigger = &AreaTrigger_at_ravenholdt; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_warsong_farms"; + newscript->pAreaTrigger = &AreaTrigger_at_warsong_farms; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_stormwright_shelf"; + newscript->pAreaTrigger = &AreaTrigger_at_stormwright_shelf; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_scent_larkorwi"; + newscript->pAreaTrigger = &AreaTrigger_at_scent_larkorwi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_last_rites"; + newscript->pAreaTrigger = &AreaTrigger_at_last_rites; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/World/boss_emeriss.cpp b/src/server/scripts/World/boss_emeriss.cpp new file mode 100644 index 00000000000..3dc14969786 --- /dev/null +++ b/src/server/scripts/World/boss_emeriss.cpp @@ -0,0 +1,144 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Emeriss +SD%Complete: 90 +SDComment: Teleport function & Mark of Nature missing +SDCategory: Bosses +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1000401, + SAY_CASTCORRUPTION = -1000402, //signed for 6182 + + SPELL_SLEEP = 24777, + SPELL_NOXIOUSBREATH = 24818, + SPELL_TAILSWEEP = 15847, + //SPELL_MARKOFNATURE = 25040, // Not working + SPELL_VOLATILEINFECTION = 24928, + SPELL_CORRUPTIONOFEARTH = 24910 +}; + +struct boss_emerissAI : public ScriptedAI +{ + boss_emerissAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiSleep_Timer; + uint32 m_uiNoxiousBreath_Timer; + uint32 m_uiTailSweep_Timer; + //uint32 m_uiMarkOfNature_Timer; + uint32 m_uiVolatileInfection_Timer; + uint32 m_uiCorruptionsCasted; + + void Reset() + { + m_uiSleep_Timer = 15000 + rand()%5000; + m_uiNoxiousBreath_Timer = 8000; + m_uiTailSweep_Timer = 4000; + //m_uiMarkOfNature_Timer = 45000; + m_uiVolatileInfection_Timer = 12000; + m_uiCorruptionsCasted = 0; + } + + void Aggro(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sleep_Timer + if (m_uiSleep_Timer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SLEEP); + + m_uiSleep_Timer = 8000 + rand()%8000; + } + else + m_uiSleep_Timer -= uiDiff; + + //NoxiousBreath_Timer + if (m_uiNoxiousBreath_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); + m_uiNoxiousBreath_Timer = 14000 + rand()%6000; + } + else + m_uiNoxiousBreath_Timer -= uiDiff; + + //Tailsweep every 2 seconds + if (m_uiTailSweep_Timer <= uiDiff) + { + DoCast(me, SPELL_TAILSWEEP); + m_uiTailSweep_Timer = 2000; + } + else + m_uiTailSweep_Timer -= uiDiff; + + //MarkOfNature_Timer + //if (m_uiMarkOfNature_Timer <= uiDiff) + //{ + // DoCast(me->getVictim(), SPELL_MARKOFNATURE); + // m_uiMarkOfNature_Timer = 45000; + //} + //else + // m_uiMarkOfNature_Timer -= uiDiff; + + //VolatileInfection_Timer + if (m_uiVolatileInfection_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_VOLATILEINFECTION); + m_uiVolatileInfection_Timer = 7000 + rand()%5000; + } + else + m_uiVolatileInfection_Timer -= uiDiff; + + //CorruptionofEarth_Timer + //CorruptionofEarth at 75%, 50% and 25% + if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(25*m_uiCorruptionsCasted))) + { + ++m_uiCorruptionsCasted; // prevent casting twice on same hp + DoScriptText(SAY_CASTCORRUPTION, me); + DoCast(me->getVictim(), SPELL_CORRUPTIONOFEARTH); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_emeriss(Creature* pCreature) +{ + return new boss_emerissAI (pCreature); +} + +void AddSC_boss_emeriss() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_emeriss"; + newscript->GetAI = &GetAI_boss_emeriss; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/World/boss_lethon.cpp b/src/server/scripts/World/boss_lethon.cpp new file mode 100644 index 00000000000..cc316223a2f --- /dev/null +++ b/src/server/scripts/World/boss_lethon.cpp @@ -0,0 +1,25 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Lethon +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Bosses +EndScriptData */ + +#include "ScriptedPch.h" + diff --git a/src/server/scripts/World/boss_taerar.cpp b/src/server/scripts/World/boss_taerar.cpp new file mode 100644 index 00000000000..079f7b387a8 --- /dev/null +++ b/src/server/scripts/World/boss_taerar.cpp @@ -0,0 +1,263 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Taerar +SD%Complete: 70 +SDComment: Mark of Nature & Teleport NYI. Fix the way to be banished. +SDCategory: Bosses +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1000399, //signed for 20021 + SAY_SUMMONSHADE = -1000400, //signed for 20021 + + //Spells of Taerar + SPELL_SLEEP = 24777, + SPELL_NOXIOUSBREATH = 24818, + SPELL_TAILSWEEP = 15847, + // SPELL_MARKOFNATURE = 25040, // Not working + SPELL_ARCANEBLAST = 24857, + SPELL_BELLOWINGROAR = 22686, + + SPELL_SUMMONSHADE_1 = 24841, + SPELL_SUMMONSHADE_2 = 24842, + SPELL_SUMMONSHADE_3 = 24843, + + //Spells of Shades of Taerar + SPELL_POSIONCLOUD = 24840, + SPELL_POSIONBREATH = 20667 +}; + +uint32 m_auiSpellSummonShade[]= +{ + SPELL_SUMMONSHADE_1, SPELL_SUMMONSHADE_2, SPELL_SUMMONSHADE_3 +}; + +struct boss_taerarAI : public ScriptedAI +{ + boss_taerarAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiSleep_Timer; + uint32 m_uiNoxiousBreath_Timer; + uint32 m_uiTailSweep_Timer; + //uint32 m_uiMarkOfNature_Timer; + uint32 m_uiArcaneBlast_Timer; + uint32 m_uiBellowingRoar_Timer; + uint32 m_uiShades_Timer; + uint32 m_uiShadesSummoned; + + bool m_bShades; + + void Reset() + { + m_uiSleep_Timer = 15000 + rand()%5000; + m_uiNoxiousBreath_Timer = 8000; + m_uiTailSweep_Timer = 4000; + //m_uiMarkOfNature_Timer = 45000; + m_uiArcaneBlast_Timer = 12000; + m_uiBellowingRoar_Timer = 30000; + m_uiShades_Timer = 60000; //The time that Taerar is banished + m_uiShadesSummoned = 0; + + m_bShades = false; + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustSummoned(Creature* pSummoned) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_bShades && m_uiShades_Timer <= uiDiff) + { + //Become unbanished again + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_bShades = false; + } + else if (m_bShades) + { + m_uiShades_Timer -= uiDiff; + //Do nothing while banished + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sleep_Timer + if (m_uiSleep_Timer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SLEEP); + + m_uiSleep_Timer = 8000 + rand()%7000; + } + else + m_uiSleep_Timer -= uiDiff; + + //NoxiousBreath_Timer + if (m_uiNoxiousBreath_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); + m_uiNoxiousBreath_Timer = 14000 + rand()%6000; + } + else + m_uiNoxiousBreath_Timer -= uiDiff; + + //Tailsweep every 2 seconds + if (m_uiTailSweep_Timer <= uiDiff) + { + DoCast(me, SPELL_TAILSWEEP); + m_uiTailSweep_Timer = 2000; + } + else + m_uiTailSweep_Timer -= uiDiff; + + //MarkOfNature_Timer + //if (m_uiMarkOfNature_Timer <= uiDiff) + //{ + // DoCast(me->getVictim(), SPELL_MARKOFNATURE); + // m_uiMarkOfNature_Timer = 45000; + //} + //else + // m_uiMarkOfNature_Timer -= uiDiff; + + //ArcaneBlast_Timer + if (m_uiArcaneBlast_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_ARCANEBLAST); + m_uiArcaneBlast_Timer = 7000 + rand()%5000; + } + else + m_uiArcaneBlast_Timer -= uiDiff; + + //BellowingRoar_Timer + if (m_uiBellowingRoar_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_BELLOWINGROAR); + m_uiBellowingRoar_Timer = 20000 + rand()%10000; + } + else + m_uiBellowingRoar_Timer -= uiDiff; + + //Summon 3 Shades at 75%, 50% and 25% (if bShades is true we already left in line 117, no need to check here again) + if (!m_bShades && (me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(25*m_uiShadesSummoned))) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + //Inturrupt any spell casting + me->InterruptNonMeleeSpells(false); + + //horrible workaround, need to fix + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + DoScriptText(SAY_SUMMONSHADE, me); + + int iSize = sizeof(m_auiSpellSummonShade) / sizeof(uint32); + + for (int i = 0; i < iSize; ++i) + DoCast(pTarget, m_auiSpellSummonShade[i], true); + + ++m_uiShadesSummoned; // prevent casting twice at same health + m_bShades = true; + } + m_uiShades_Timer = 60000; + } + + DoMeleeAttackIfReady(); + } +}; + +// Shades of Taerar Script +struct boss_shadeoftaerarAI : public ScriptedAI +{ + boss_shadeoftaerarAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiPoisonCloud_Timer; + uint32 m_uiPosionBreath_Timer; + + void Reset() + { + m_uiPoisonCloud_Timer = 8000; + m_uiPosionBreath_Timer = 12000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //PoisonCloud_Timer + if (m_uiPoisonCloud_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_POSIONCLOUD); + m_uiPoisonCloud_Timer = 30000; + } + else + m_uiPoisonCloud_Timer -= uiDiff; + + //PosionBreath_Timer + if (m_uiPosionBreath_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_POSIONBREATH); + m_uiPosionBreath_Timer = 12000; + } + else + m_uiPosionBreath_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_taerar(Creature* pCreature) +{ + return new boss_taerarAI (pCreature); +} + +CreatureAI* GetAI_boss_shadeoftaerar(Creature* pCreature) +{ + return new boss_shadeoftaerarAI (pCreature); +} + +void AddSC_boss_taerar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_taerar"; + newscript->GetAI = &GetAI_boss_taerar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_shade_of_taerar"; + newscript->GetAI = &GetAI_boss_shadeoftaerar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/World/boss_ysondre.cpp b/src/server/scripts/World/boss_ysondre.cpp new file mode 100644 index 00000000000..50b8f724e68 --- /dev/null +++ b/src/server/scripts/World/boss_ysondre.cpp @@ -0,0 +1,203 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Ysondre +SD%Complete: 90 +SDComment: Mark of Nature & Teleport missing +SDCategory: Bosses +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1000360, //signed for 17969 + SAY_SUMMONDRUIDS = -1000361, //signed for 17969 + + SPELL_SLEEP = 24777, + SPELL_NOXIOUSBREATH = 24818, + SPELL_TAILSWEEP = 15847, + //SPELL_MARKOFNATURE = 25040, // Not working + SPELL_LIGHTNINGWAVE = 24819, + SPELL_SUMMONDRUIDS = 24795, + + SPELL_SUMMON_PLAYER = 24776, + + //druid spells + SPELL_MOONFIRE = 21669 +}; + +// Ysondre script +struct boss_ysondreAI : public ScriptedAI +{ + boss_ysondreAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 m_uiSleep_Timer; + uint32 m_uiNoxiousBreath_Timer; + uint32 m_uiTailSweep_Timer; + //uint32 m_uiMarkOfNature_Timer; + uint32 m_uiLightningWave_Timer; + uint32 m_uiSummonDruidModifier; + + void Reset() + { + m_uiSleep_Timer = 15000 + rand()%5000; + m_uiNoxiousBreath_Timer = 8000; + m_uiTailSweep_Timer = 4000; + //m_uiMarkOfNature_Timer = 45000; + m_uiLightningWave_Timer = 12000; + m_uiSummonDruidModifier = 0; + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustSummoned(Creature* pSummoned) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //Sleep_Timer + if (m_uiSleep_Timer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SLEEP); + + m_uiSleep_Timer = 8000 + rand()%7000; + } + else + m_uiSleep_Timer -= uiDiff; + + //NoxiousBreath_Timer + if (m_uiNoxiousBreath_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); + m_uiNoxiousBreath_Timer = 14000 + rand()%6000; + } + else + m_uiNoxiousBreath_Timer -= uiDiff; + + //Tailsweep every 2 seconds + if (m_uiTailSweep_Timer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_TAILSWEEP); + + m_uiTailSweep_Timer = 2000; + } + else + m_uiTailSweep_Timer -= uiDiff; + + //MarkOfNature_Timer + //if (m_uiMarkOfNature_Timer <= uiDiff) + //{ + // DoCast(me->getVictim(), SPELL_MARKOFNATURE); + // m_uiMarkOfNature_Timer = 45000; + //} + //else + // m_uiMarkOfNature_Timer -= uiDiff; + + //LightningWave_Timer + if (m_uiLightningWave_Timer <= uiDiff) + { + //Cast LIGHTNINGWAVE on a Random target + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_LIGHTNINGWAVE); + + m_uiLightningWave_Timer = 7000 + rand()%5000; + } + else + m_uiLightningWave_Timer -= uiDiff; + + //Summon Druids + if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(25*m_uiSummonDruidModifier))) + { + DoScriptText(SAY_SUMMONDRUIDS, me); + + for (int i = 0; i < 10; ++i) + DoCast(me, SPELL_SUMMONDRUIDS, true); + + ++m_uiSummonDruidModifier; + } + + DoMeleeAttackIfReady(); + } +}; + +// Summoned druid script +struct mob_dementeddruidsAI : public ScriptedAI +{ + mob_dementeddruidsAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiMoonFire_Timer; + + void Reset() + { + m_uiMoonFire_Timer = 3000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //MoonFire_Timer + if (m_uiMoonFire_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MOONFIRE); + m_uiMoonFire_Timer = 5000; + } + else + m_uiMoonFire_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ysondre(Creature* pCreature) +{ + return new boss_ysondreAI (pCreature); +} + +CreatureAI* GetAI_mob_dementeddruids(Creature* pCreature) +{ + return new mob_dementeddruidsAI (pCreature); +} + +void AddSC_boss_ysondre() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ysondre"; + newscript->GetAI = &GetAI_boss_ysondre; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dementeddruids"; + newscript->GetAI = &GetAI_mob_dementeddruids; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp new file mode 100644 index 00000000000..6f06ac78fd7 --- /dev/null +++ b/src/server/scripts/World/go_scripts.cpp @@ -0,0 +1,1182 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 > +* Copyright (C) 2006 - 20010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: GO_Scripts +SD%Complete: 100 +SDComment: Quest support: 4285,4287,4288(crystal pylons), 4296, 6481, 10990, 10991, 10992, Field_Repair_Bot->Teaches spell 22704. Barov_journal->Teaches spell 26089,12843,12982, 2936. Soulwell +SDCategory: Game Objects +EndScriptData */ + +/* ContentData +go_cat_figurine (the "trap" version of GO, two different exist) +go_northern_crystal_pylon +go_eastern_crystal_pylon +go_western_crystal_pylon +go_barov_journal +go_ethereum_prison +go_ethereum_stasis +go_sacred_fire_of_life +go_shrine_of_the_birds +go_southfury_moonstone +go_field_repair_bot_74A +go_orb_of_command +go_resonite_cask +go_tablet_of_madness +go_tablet_of_the_seven +go_tele_to_dalaran_crystal +go_tele_to_violet_stand +go_rusty_cage +go_scourge_cage +go_jotunheim_cage +go_table_theka +go_soulwell +go_bashir_crystalforge +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## go_cat_figurine +######*/ + +enum eCatFigurine +{ + SPELL_SUMMON_GHOST_SABER = 5968, +}; + +bool GOHello_go_cat_figurine(Player *pPlayer, GameObject * /*pGO*/) +{ + pPlayer->CastSpell(pPlayer,SPELL_SUMMON_GHOST_SABER,true); + return false; +} + +/*###### +## go_crystal_pylons (3x) +######*/ + +bool GOHello_go_northern_crystal_pylon(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + { + pPlayer->PrepareQuestMenu(pGO->GetGUID()); + pPlayer->SendPreparedQuest(pGO->GetGUID()); + } + + if (pPlayer->GetQuestStatus(4285) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(4285); + + return true; +} + +bool GOHello_go_eastern_crystal_pylon(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + { + pPlayer->PrepareQuestMenu(pGO->GetGUID()); + pPlayer->SendPreparedQuest(pGO->GetGUID()); + } + + if (pPlayer->GetQuestStatus(4287) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(4287); + + return true; +} + +bool GOHello_go_western_crystal_pylon(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) + { + pPlayer->PrepareQuestMenu(pGO->GetGUID()); + pPlayer->SendPreparedQuest(pGO->GetGUID()); + } + + if (pPlayer->GetQuestStatus(4288) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(4288); + + return true; +} + +/*###### +## go_barov_journal +######*/ + +bool GOHello_go_barov_journal(Player *pPlayer, GameObject * /*pGO*/) +{ + if (pPlayer->HasSkill(SKILL_TAILORING) && pPlayer->GetBaseSkillValue(SKILL_TAILORING) >= 280 && !pPlayer->HasSpell(26086)) + { + pPlayer->CastSpell(pPlayer,26095,false); + } + return true; +} + +/*###### +## go_field_repair_bot_74A +######*/ + +bool GOHello_go_field_repair_bot_74A(Player *pPlayer, GameObject * /*pGO*/) +{ + if (pPlayer->HasSkill(SKILL_ENGINERING) && pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 300 && !pPlayer->HasSpell(22704)) + { + pPlayer->CastSpell(pPlayer,22864,false); + } + return true; +} + +/*###### +## go_gilded_brazier (Paladin First Trail quest (9678)) +######*/ + +enum eGildedBrazier +{ + NPC_STILLBLADE = 17716, +}; + +bool GOHello_go_gilded_brazier(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER) + { + if (pPlayer->GetQuestStatus(9678) == QUEST_STATUS_INCOMPLETE) + { + if (Creature* Stillblade = pPlayer->SummonCreature(NPC_STILLBLADE, 8106.11, -7542.06, 151.775, 3.02598, TEMPSUMMON_DEAD_DESPAWN, 60000)) + Stillblade->AI()->AttackStart(pPlayer); + } + } + return true; +} + +/*###### +## go_orb_of_command +######*/ + +bool GOHello_go_orb_of_command(Player *pPlayer, GameObject * /*pGO*/) +{ + if (pPlayer->GetQuestRewardStatus(7761)) + pPlayer->CastSpell(pPlayer,23460,true); + + return true; +} + +/*###### +## go_tablet_of_madness +######*/ + +bool GOHello_go_tablet_of_madness(Player *pPlayer, GameObject * /*pGO*/) +{ + if (pPlayer->HasSkill(SKILL_ALCHEMY) && pPlayer->GetSkillValue(SKILL_ALCHEMY) >= 300 && !pPlayer->HasSpell(24266)) + { + pPlayer->CastSpell(pPlayer,24267,false); + } + return true; +} + +/*###### +## go_tablet_of_the_seven +######*/ + +//TODO: use gossip option ("Transcript the Tablet") instead, if Trinity adds support. +bool GOHello_go_tablet_of_the_seven(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) + return true; + + if (pPlayer->GetQuestStatus(4296) == QUEST_STATUS_INCOMPLETE) + pPlayer->CastSpell(pPlayer,15065,false); + + return true; +} + +/*##### +## go_jump_a_tron +######*/ + +bool GOHello_go_jump_a_tron(Player *pPlayer, GameObject * /*pGO*/) +{ + if (pPlayer->GetQuestStatus(10111) == QUEST_STATUS_INCOMPLETE) + pPlayer->CastSpell(pPlayer,33382,true); + + return true; +} + +/*###### +## go_ethereum_prison +######*/ + +enum eEthereumPrison +{ + SPELL_REP_LC = 39456, + SPELL_REP_SHAT = 39457, + SPELL_REP_CE = 39460, + SPELL_REP_CON = 39474, + SPELL_REP_KT = 39475, + SPELL_REP_SPOR = 39476 +}; + +const uint32 NpcPrisonEntry[] = +{ + 22810, 22811, 22812, 22813, 22814, 22815, //good guys + 20783, 20784, 20785, 20786, 20788, 20789, 20790 //bad guys +}; + +bool GOHello_go_ethereum_prison(Player *pPlayer, GameObject *pGO) +{ + int Random = rand() % (sizeof(NpcPrisonEntry) / sizeof(uint32)); + + if (Creature* pCreature = pPlayer->SummonCreature(NpcPrisonEntry[Random], + pGO->GetPositionX(), pGO->GetPositionY(), pGO->GetPositionZ(), pGO->GetAngle(pPlayer), + TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + if (!pCreature->IsHostileTo(pPlayer)) + { + uint32 Spell = 0; + + if (FactionTemplateEntry const* pFaction = pCreature->getFactionTemplateEntry()) + { + switch(pFaction->faction) + { + case 1011: Spell = SPELL_REP_LC; break; + case 935: Spell = SPELL_REP_SHAT; break; + case 942: Spell = SPELL_REP_CE; break; + case 933: Spell = SPELL_REP_CON; break; + case 989: Spell = SPELL_REP_KT; break; + case 970: Spell = SPELL_REP_SPOR; break; + } + + if (Spell) + pCreature->CastSpell(pPlayer, Spell, false); + else + error_log("TSCR: go_ethereum_prison summoned Creature (entry %u) but faction (%u) are not expected by script.", pCreature->GetEntry(), pCreature->getFaction()); + } + } + } + + return false; +} + +/*###### +## go_ethereum_stasis +######*/ + +const uint32 NpcStasisEntry[] = +{ + 22825, 20888, 22827, 22826, 22828 +}; + +bool GOHello_go_ethereum_stasis(Player *pPlayer, GameObject *pGO) +{ + int Random = rand() % (sizeof(NpcStasisEntry) / sizeof(uint32)); + + pPlayer->SummonCreature(NpcStasisEntry[Random], + pGO->GetPositionX(), pGO->GetPositionY(), pGO->GetPositionZ(), pGO->GetAngle(pPlayer), + TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + + return false; +} + +/*###### +## go_resonite_cask +######*/ + +enum eResoniteCask +{ + NPC_GOGGEROC = 11920 +}; + +bool GOHello_go_resonite_cask(Player * /*pPlayer*/, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER) + pGO->SummonCreature(NPC_GOGGEROC, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000); + + return false; +} + +/*###### +## go_sacred_fire_of_life +######*/ + +#define NPC_ARIKARA 10882 + +bool GOHello_go_sacred_fire_of_life(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER) + pPlayer->SummonCreature(NPC_ARIKARA, -5008.338, -2118.894, 83.657, 0.874, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + + return true; +} + +/*###### +## go_shrine_of_the_birds +######*/ + +enum eShrineOfTheBirds +{ + NPC_HAWK_GUARD = 22992, + NPC_EAGLE_GUARD = 22993, + NPC_FALCON_GUARD = 22994, + GO_SHRINE_HAWK = 185551, + GO_SHRINE_EAGLE = 185547, + GO_SHRINE_FALCON = 185553 +}; + +bool GOHello_go_shrine_of_the_birds(Player *pPlayer, GameObject *pGO) +{ + uint32 BirdEntry = 0; + + float fX, fY, fZ; + pGO->GetClosePoint(fX, fY, fZ, pGO->GetObjectSize(), INTERACTION_DISTANCE); + + switch(pGO->GetEntry()) + { + case GO_SHRINE_HAWK: + BirdEntry = NPC_HAWK_GUARD; + break; + case GO_SHRINE_EAGLE: + BirdEntry = NPC_EAGLE_GUARD; + break; + case GO_SHRINE_FALCON: + BirdEntry = NPC_FALCON_GUARD; + break; + } + + if (BirdEntry) + pPlayer->SummonCreature(BirdEntry, fX, fY, fZ, pGO->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + + return false; +} + +/*###### +## go_southfury_moonstone +######*/ + +enum eSouthfury +{ + NPC_RIZZLE = 23002, + SPELL_BLACKJACK = 39865, //stuns player + SPELL_SUMMON_RIZZLE = 39866 + +}; + +bool GOHello_go_southfury_moonstone(Player *pPlayer, GameObject * /*pGO*/) +{ + //implicitTarget=48 not implemented as of writing this code, and manual summon may be just ok for our purpose + //pPlayer->CastSpell(pPlayer,SPELL_SUMMON_RIZZLE,false); + + if (Creature* pCreature = pPlayer->SummonCreature(NPC_RIZZLE, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0)) + pCreature->CastSpell(pPlayer,SPELL_BLACKJACK,false); + + return false; +} + +/*###### +## go_tele_to_dalaran_crystal +######*/ + +enum eDalaranCrystal +{ + QUEST_LEARN_LEAVE_RETURN = 12790, + QUEST_TELE_CRYSTAL_FLAG = 12845 +}; + +#define GO_TELE_TO_DALARAN_CRYSTAL_FAILED "This teleport crystal cannot be used until the teleport crystal in Dalaran has been used at least once." + +bool GOHello_go_tele_to_dalaran_crystal(Player *pPlayer, GameObject * /*pGO*/) +{ + if (pPlayer->GetQuestRewardStatus(QUEST_TELE_CRYSTAL_FLAG)) + { + return false; + } + else + pPlayer->GetSession()->SendNotification(GO_TELE_TO_DALARAN_CRYSTAL_FAILED); + + return true; +} + +/*###### +## go_tele_to_violet_stand +######*/ + +bool GOHello_go_tele_to_violet_stand(Player *pPlayer, GameObject * /*pGO*/) +{ + if (pPlayer->GetQuestRewardStatus(QUEST_LEARN_LEAVE_RETURN) || pPlayer->GetQuestStatus(QUEST_LEARN_LEAVE_RETURN) == QUEST_STATUS_INCOMPLETE) + return false; + + return true; +} + +/*###### +## go_fel_crystalforge +######*/ + +#define GOSSIP_FEL_CRYSTALFORGE_TEXT 31000 +#define GOSSIP_FEL_CRYSTALFORGE_ITEM_TEXT_RETURN 31001 +#define GOSSIP_FEL_CRYSTALFORGE_ITEM_1 "Purchase 1 Unstable Flask of the Beast for the cost of 10 Apexis Shards" +#define GOSSIP_FEL_CRYSTALFORGE_ITEM_5 "Purchase 5 Unstable Flask of the Beast for the cost of 50 Apexis Shards" +#define GOSSIP_FEL_CRYSTALFORGE_ITEM_RETURN "Use the fel crystalforge to make another purchase." + +enum eFelCrystalforge +{ + SPELL_CREATE_1_FLASK_OF_BEAST = 40964, + SPELL_CREATE_5_FLASK_OF_BEAST = 40965, +}; + +bool GOHello_go_fel_crystalforge(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) /* != GAMEOBJECT_TYPE_QUESTGIVER) */ + pPlayer->PrepareQuestMenu(pGO->GetGUID()); /* return true*/ + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_FEL_CRYSTALFORGE_TEXT, pGO->GetGUID()); + + return true; +} + +bool GOSelect_go_fel_crystalforge(Player *pPlayer, GameObject *pGO, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->CastSpell(pPlayer,SPELL_CREATE_1_FLASK_OF_BEAST,false); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_RETURN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_FEL_CRYSTALFORGE_ITEM_TEXT_RETURN, pGO->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->CastSpell(pPlayer,SPELL_CREATE_5_FLASK_OF_BEAST,false); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_RETURN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_FEL_CRYSTALFORGE_ITEM_TEXT_RETURN, pGO->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_FEL_CRYSTALFORGE_TEXT, pGO->GetGUID()); + break; + } + return true; +} + +/*###### +## go_bashir_crystalforge +######*/ + +#define GOSSIP_BASHIR_CRYSTALFORGE_TEXT 31100 +#define GOSSIP_BASHIR_CRYSTALFORGE_ITEM_TEXT_RETURN 31101 +#define GOSSIP_BASHIR_CRYSTALFORGE_ITEM_1 "Purchase 1 Unstable Flask of the Sorcerer for the cost of 10 Apexis Shards" +#define GOSSIP_BASHIR_CRYSTALFORGE_ITEM_5 "Purchase 5 Unstable Flask of the Sorcerer for the cost of 50 Apexis Shards" +#define GOSSIP_BASHIR_CRYSTALFORGE_ITEM_RETURN "Use the bashir crystalforge to make another purchase." + +enum eBashirCrystalforge +{ + SPELL_CREATE_1_FLASK_OF_SORCERER = 40968, + SPELL_CREATE_5_FLASK_OF_SORCERER = 40970, +}; + +bool GOHello_go_bashir_crystalforge(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) /* != GAMEOBJECT_TYPE_QUESTGIVER) */ + pPlayer->PrepareQuestMenu(pGO->GetGUID()); /* return true*/ + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_BASHIR_CRYSTALFORGE_TEXT, pGO->GetGUID()); + + return true; +} + +bool GOSelect_go_bashir_crystalforge(Player *pPlayer, GameObject *pGO, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->CastSpell(pPlayer,SPELL_CREATE_1_FLASK_OF_SORCERER,false); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_RETURN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_BASHIR_CRYSTALFORGE_ITEM_TEXT_RETURN, pGO->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->CastSpell(pPlayer,SPELL_CREATE_5_FLASK_OF_SORCERER,false); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_RETURN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_BASHIR_CRYSTALFORGE_ITEM_TEXT_RETURN, pGO->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_BASHIR_CRYSTALFORGE_TEXT, pGO->GetGUID()); + break; + } + return true; +} + +/*###### +## matrix_punchograph +######*/ + +enum eMatrixPunchograph +{ + ITEM_WHITE_PUNCH_CARD = 9279, + ITEM_YELLOW_PUNCH_CARD = 9280, + ITEM_BLUE_PUNCH_CARD = 9282, + ITEM_RED_PUNCH_CARD = 9281, + ITEM_PRISMATIC_PUNCH_CARD = 9316, + SPELL_YELLOW_PUNCH_CARD = 11512, + SPELL_BLUE_PUNCH_CARD = 11525, + SPELL_RED_PUNCH_CARD = 11528, + SPELL_PRISMATIC_PUNCH_CARD = 11545, + MATRIX_PUNCHOGRAPH_3005_A = 142345, + MATRIX_PUNCHOGRAPH_3005_B = 142475, + MATRIX_PUNCHOGRAPH_3005_C = 142476, + MATRIX_PUNCHOGRAPH_3005_D = 142696, +}; + +bool GOHello_go_matrix_punchograph(Player *pPlayer, GameObject *pGO) +{ + switch(pGO->GetEntry()) + { + case MATRIX_PUNCHOGRAPH_3005_A: + if (pPlayer->HasItemCount(ITEM_WHITE_PUNCH_CARD, 1)) + { + pPlayer->DestroyItemCount(ITEM_WHITE_PUNCH_CARD, 1, true); + pPlayer->CastSpell(pPlayer,SPELL_YELLOW_PUNCH_CARD,true); + } + break; + case MATRIX_PUNCHOGRAPH_3005_B: + if (pPlayer->HasItemCount(ITEM_YELLOW_PUNCH_CARD, 1)) + { + pPlayer->DestroyItemCount(ITEM_YELLOW_PUNCH_CARD, 1, true); + pPlayer->CastSpell(pPlayer,SPELL_BLUE_PUNCH_CARD,true); + } + break; + case MATRIX_PUNCHOGRAPH_3005_C: + if (pPlayer->HasItemCount(ITEM_BLUE_PUNCH_CARD, 1)) + { + pPlayer->DestroyItemCount(ITEM_BLUE_PUNCH_CARD, 1, true); + pPlayer->CastSpell(pPlayer,SPELL_RED_PUNCH_CARD,true); + } + break; + case MATRIX_PUNCHOGRAPH_3005_D: + if (pPlayer->HasItemCount(ITEM_RED_PUNCH_CARD, 1)) + { + pPlayer->DestroyItemCount(ITEM_RED_PUNCH_CARD, 1, true); + pPlayer->CastSpell(pPlayer, SPELL_PRISMATIC_PUNCH_CARD, true); + } + break; + default: + break; + } + return false; +} + +/*###### +## go_rusty_cage +######*/ + +enum eRustyCage +{ + NPC_GOBLIN_PRISIONER = 29466 +}; + +bool GOHello_go_rusty_cage(Player *pPlayer, GameObject *pGO) +{ + if (Creature *pGoblinPrisoner = pGO->FindNearestCreature(NPC_GOBLIN_PRISIONER, 5.0f, true)) + { + pGO->SetGoState(GO_STATE_ACTIVE); + pPlayer->KilledMonsterCredit(NPC_GOBLIN_PRISIONER, pGoblinPrisoner->GetGUID()); + pGoblinPrisoner->DisappearAndDie(); + } + + return true; +} + +/*###### +## go_scourge_cage +######*/ + +enum eScourgeCage +{ + NPC_SCOURGE_PRISONER = 25610 +}; + +bool GOHello_go_scourge_cage(Player *pPlayer, GameObject *pGO) +{ + if (Creature *pNearestPrisoner = pGO->FindNearestCreature(NPC_SCOURGE_PRISONER, 5.0f, true)) + { + pGO->SetGoState(GO_STATE_ACTIVE); + pPlayer->KilledMonsterCredit(NPC_SCOURGE_PRISONER, pNearestPrisoner->GetGUID()); + pNearestPrisoner->DisappearAndDie(); + } + + return true; +} + +/*###### +## go_arcane_prison +######*/ + +enum eArcanePrison +{ + QUEST_PRISON_BREAK = 11587, + SPELL_ARCANE_PRISONER_KILL_CREDIT = 45456 +}; + +bool GOHello_go_arcane_prison(Player *pPlayer, GameObject *pGO) +{ + if (pPlayer->GetQuestStatus(QUEST_PRISON_BREAK) == QUEST_STATUS_INCOMPLETE) + { + pGO->SummonCreature(25318, 3485.089844, 6115.7422188, 70.966812, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + pPlayer->CastSpell(pPlayer, SPELL_ARCANE_PRISONER_KILL_CREDIT, true); + return true; + } else + return false; +} + +/*###### +## go_blood_filled_orb +######*/ + +#define NPC_ZELEMAR 17830 + +bool GOHello_go_blood_filled_orb(Player *pPlayer, GameObject *pGO) +{ + if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER) + pPlayer->SummonCreature(NPC_ZELEMAR, -369.746, 166.759, -21.50, 5.235, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + + return true; +} + +/*###### +## go_jotunheim_cage +######*/ + +enum eJotunheimCage +{ + NPC_EBON_BLADE_PRISONER_HUMAN = 30186, + NPC_EBON_BLADE_PRISONER_NE = 30194, + NPC_EBON_BLADE_PRISONER_TROLL = 30196, + NPC_EBON_BLADE_PRISONER_ORC = 30195, + + SPELL_SUMMON_BLADE_KNIGHT_H = 56207, + SPELL_SUMMON_BLADE_KNIGHT_NE = 56209, + SPELL_SUMMON_BLADE_KNIGHT_ORC = 56212, + SPELL_SUMMON_BLADE_KNIGHT_TROLL = 56214 +}; + +bool GOHello_go_jotunheim_cage(Player* pPlayer, GameObject* pGO) +{ + Creature* pPrisoner = pGO->FindNearestCreature(NPC_EBON_BLADE_PRISONER_HUMAN, 5.0f, true); + if (!pPrisoner) + { + pPrisoner = pGO->FindNearestCreature(NPC_EBON_BLADE_PRISONER_TROLL, 5.0f, true); + if (!pPrisoner) + { + pPrisoner = pGO->FindNearestCreature(NPC_EBON_BLADE_PRISONER_ORC, 5.0f, true); + if (!pPrisoner) + pPrisoner = pGO->FindNearestCreature(NPC_EBON_BLADE_PRISONER_NE, 5.0f, true); + } + } + if (!pPrisoner || !pPrisoner->isAlive()) + return false; + + pPrisoner->DisappearAndDie(); + pPlayer->KilledMonsterCredit(NPC_EBON_BLADE_PRISONER_HUMAN, 0); + switch(pPrisoner->GetEntry()) + { + case NPC_EBON_BLADE_PRISONER_HUMAN: + pPlayer->CastSpell(pPlayer,SPELL_SUMMON_BLADE_KNIGHT_H,true); + break; + case NPC_EBON_BLADE_PRISONER_NE: + pPlayer->CastSpell(pPlayer,SPELL_SUMMON_BLADE_KNIGHT_NE,true); + break; + case NPC_EBON_BLADE_PRISONER_TROLL: + pPlayer->CastSpell(pPlayer,SPELL_SUMMON_BLADE_KNIGHT_TROLL,true); + break; + case NPC_EBON_BLADE_PRISONER_ORC: + pPlayer->CastSpell(pPlayer,SPELL_SUMMON_BLADE_KNIGHT_ORC,true); + break; + } + return true; +} +enum eTableTheka +{ + GOSSIP_TABLE_THEKA = 1653, + + QUEST_SPIDER_GOLD = 2936 +}; + +bool GOHello_go_table_theka(Player* pPlayer, GameObject* pGO) +{ + if (pPlayer->GetQuestStatus(QUEST_SPIDER_GOLD) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_SPIDER_GOLD); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TABLE_THEKA, pGO->GetGUID()); + + return true; +} + +/*###### +## go_inconspicuous_landmark +######*/ + +enum eInconspicuousLandmark +{ + SPELL_SUMMON_PIRATES_TREASURE_AND_TRIGGER_MOB = 11462, + ITEM_CUERGOS_KEY = 9275, +}; + +bool GOHello_go_inconspicuous_landmark(Player *pPlayer, GameObject* /*pGO*/) +{ + if (pPlayer->HasItemCount(ITEM_CUERGOS_KEY,1)) + return false; + + pPlayer->CastSpell(pPlayer,SPELL_SUMMON_PIRATES_TREASURE_AND_TRIGGER_MOB,true); + + return true; +} + +/*###### +## go_soulwell +######*/ + +bool GOHello_go_soulwell(Player *pPlayer, GameObject* pGO) +{ + Unit *caster = pGO->GetOwner(false); + if (!caster || caster->GetTypeId() != TYPEID_PLAYER) + return true; + + if (!pPlayer->IsInSameRaidWith(static_cast(caster))) + return true; + + // Repeating this at every use is ugly and inefficient. But as long as we don't have proper + // GO scripting with at least On Create and On Update events, the other options are no less + // ugly and hacky. + uint32 newSpell = 0; + if (pGO->GetEntry() == 193169) // Soulwell for rank 2 + { + if (caster->HasAura(18693)) // Improved Healthstone rank 2 + newSpell = 58898; + else if (caster->HasAura(18692)) // Improved Healthstone rank 1 + newSpell = 58896; + else newSpell = 58890; + } + else if (pGO->GetEntry() == 181621) // Soulwell for rank 1 + { + if (caster->HasAura(18693)) // Improved Healthstone rank 2 + newSpell = 34150; + else if (caster->HasAura(18692)) // Improved Healthstone rank 1 + newSpell = 34149; + else newSpell = 34130; + } + + pGO->AddUse(); + pPlayer->CastSpell(pPlayer, newSpell, true); + return true; +} + +/*###### +## Quest 11255: Prisoners of Wyrmskull +## go_dragonflayer_cage +######*/ + +enum ePrisonersOfWyrmskull +{ + QUEST_PRISONERS_OF_WYRMSKULL = 11255, + NPC_PRISONER_PRIEST = 24086, + NPC_PRISONER_MAGE = 24088, + NPC_PRISONER_WARRIOR = 24089, + NPC_PRISONER_PALADIN = 24090 +}; + +bool GOHello_go_dragonflayer_cage(Player *pPlayer, GameObject *pGO) +{ + if (pPlayer->GetQuestStatus(QUEST_PRISONERS_OF_WYRMSKULL) != QUEST_STATUS_INCOMPLETE) + return true; + + Creature* pPrisoner = pGO->FindNearestCreature(NPC_PRISONER_PRIEST, 2.0f); + if (!pPrisoner) + { + pPrisoner = pGO->FindNearestCreature(NPC_PRISONER_MAGE, 2.0f); + if (!pPrisoner) + { + pPrisoner = pGO->FindNearestCreature(NPC_PRISONER_WARRIOR, 2.0f); + if (!pPrisoner) + pPrisoner = pGO->FindNearestCreature(NPC_PRISONER_PALADIN, 2.0f); + } + } + + if (!pPrisoner || !pPrisoner->isAlive()) + return true; + + Quest const* qInfo = objmgr.GetQuestTemplate(QUEST_PRISONERS_OF_WYRMSKULL); + if (qInfo) + { + //TODO: prisoner should help player for a short period of time + pPlayer->KilledMonsterCredit(qInfo->ReqCreatureOrGOId[0],0); + pPrisoner->DisappearAndDie(); + } + return true; +} + +/*###### +## Quest 11560: Oh Noes, the Tadpoles! +## go_tadpole_cage +######*/ + +enum eTadpoles +{ + QUEST_OH_NOES_THE_TADPOLES = 11560, + NPC_WINTERFIN_TADPOLE = 25201 +}; + +bool GOHello_go_tadpole_cage(Player *pPlayer, GameObject *pGO) +{ + if (pPlayer->GetQuestStatus(QUEST_OH_NOES_THE_TADPOLES) == QUEST_STATUS_INCOMPLETE) + { + Creature *pTadpole = pGO->FindNearestCreature(NPC_WINTERFIN_TADPOLE,1.0f); + if (pTadpole) + { + pGO->UseDoorOrButton(); + pTadpole->DisappearAndDie(); + pPlayer->KilledMonsterCredit(NPC_WINTERFIN_TADPOLE,0); + //FIX: Summon minion tadpole + } + } + return true; +} + +/*###### +## Quest 14096 & 14142: You've Really Done It This Time, Kul +## go_black_cage +######*/ + +enum eReallyDoneItThisTime +{ + QUEST_ALLIANCE_YOU_VE_REALLY_DONE_IT_THIS_TIME_KUL = 14096, + QUEST_HORDE_YOU_VE_REALLY_DONE_IT_THIS_TIME_KUL = 14142, + NPC_CAPTIVE_ASPIRANT = 34716, + NPC_KUL = 34956 +}; + +bool GOHello_go_black_cage(Player *pPlayer, GameObject *pGO) +{ + if ((pPlayer->GetTeamId() == TEAM_ALLIANCE && pPlayer->GetQuestStatus(QUEST_ALLIANCE_YOU_VE_REALLY_DONE_IT_THIS_TIME_KUL) == QUEST_STATUS_INCOMPLETE) || + (pPlayer->GetTeamId() == TEAM_HORDE && pPlayer->GetQuestStatus(QUEST_HORDE_YOU_VE_REALLY_DONE_IT_THIS_TIME_KUL) == QUEST_STATUS_INCOMPLETE)) + { + Creature *pPrisoner = pGO->FindNearestCreature(NPC_CAPTIVE_ASPIRANT,1.0f); + if (!pPrisoner) + pPrisoner = pGO->FindNearestCreature(NPC_KUL,1.0f); + if (pPrisoner) + { + pGO->UseDoorOrButton(); + pPrisoner->DisappearAndDie(); + pPlayer->KilledMonsterCredit(pPrisoner->GetEntry(),0); + } + } + return true; +} + +/*###### +## go_amberpine_outhouse +######*/ + +#define GOSSIP_USE_OUTHOUSE "Use the outhouse." +#define GO_ANDERHOLS_SLIDER_CIDER_NOT_FOUND "Quest item Anderhol's Slider Cider not found." + +enum eAmberpineOuthouse +{ + ITEM_ANDERHOLS_SLIDER_CIDER = 37247, + NPC_OUTHOUSE_BUNNY = 27326, + QUEST_DOING_YOUR_DUTY = 12227, + SPELL_INDISPOSED = 53017, + SPELL_INDISPOSED_III = 48341, + SPELL_CREATE_AMBERSEEDS = 48330, + GOSSIP_OUTHOUSE_INUSE = 12775, + GOSSIP_OUTHOUSE_VACANT = 12779 +}; + +bool GOHello_go_amberpine_outhouse(Player *pPlayer, GameObject *pGO) +{ + if (pPlayer->GetQuestStatus(QUEST_DOING_YOUR_DUTY) == QUEST_STATUS_INCOMPLETE || + (pPlayer->GetQuestStatus(QUEST_DOING_YOUR_DUTY) == QUEST_STATUS_COMPLETE)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_USE_OUTHOUSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_OUTHOUSE_VACANT, pGO->GetGUID()); + return true; + } + else + pPlayer->SEND_GOSSIP_MENU(GOSSIP_OUTHOUSE_INUSE, pGO->GetGUID()); + return true; +} + +bool GOSelect_go_amberpine_outhouse(Player *pPlayer, GameObject *pGO, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF +1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + Creature* pTarget = GetClosestCreatureWithEntry(pPlayer, NPC_OUTHOUSE_BUNNY, 3.0f); + if (pTarget) + { + pTarget->AI()->SetData(1,pPlayer->getGender()); + pGO->CastSpell(pTarget, SPELL_INDISPOSED_III); + } + pGO->CastSpell(pPlayer, SPELL_INDISPOSED); + if (pPlayer->HasItemCount(ITEM_ANDERHOLS_SLIDER_CIDER,1)) + pGO->CastSpell(pPlayer, SPELL_CREATE_AMBERSEEDS); + return true; + } + else + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->GetSession()->SendNotification(GO_ANDERHOLS_SLIDER_CIDER_NOT_FOUND); + return false; +} + +/*###### +## Quest 9544: The Prophecy of Akida +######*/ + +enum eProphecy +{ + QUEST_PROPHECY_OF_AKIDA = 9544, + NPC_STILLPINE_CAPTIVE = 17375 +}; + +bool GOHello_go_stillpine_cage(Player *pPlayer, GameObject *pGO) +{ + if (pPlayer->GetQuestStatus(QUEST_PROPHECY_OF_AKIDA) == QUEST_STATUS_INCOMPLETE) + if (Creature *pPrisoner = pGO->FindNearestCreature(NPC_STILLPINE_CAPTIVE,1.0f)) + { + pGO->UseDoorOrButton(); + pPrisoner->DisappearAndDie(); + pPlayer->KilledMonsterCredit(pPrisoner->GetEntry(),0); + } + return true; +} + +/*###### +## Quest 1126: Hive in the Tower +######*/ + +enum eHives +{ + QUEST_HIVE_IN_THE_TOWER = 9544, + NPC_HIVE_AMBUSHER = 13301 +}; + +bool GOHello_go_hive_pod(Player *pPlayer, GameObject *pGO) +{ + pPlayer->SendLoot(pGO->GetGUID(), LOOT_CORPSE); + pGO->SummonCreature(NPC_HIVE_AMBUSHER,pGO->GetPositionX()+1,pGO->GetPositionY(),pGO->GetPositionZ(),pGO->GetAngle(pPlayer),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + pGO->SummonCreature(NPC_HIVE_AMBUSHER,pGO->GetPositionX(),pGO->GetPositionY()+1,pGO->GetPositionZ(),pGO->GetAngle(pPlayer),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); + return true; +} + +bool GOHello_go_massive_seaforium_charge(Player* pPlayer, GameObject *pGo) +{ + pGo->SetLootState(GO_JUST_DEACTIVATED); + return true; +} + +void AddSC_go_scripts() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_cat_figurine"; + newscript->pGOHello = &GOHello_go_cat_figurine; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_northern_crystal_pylon"; + newscript->pGOHello = &GOHello_go_northern_crystal_pylon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_eastern_crystal_pylon"; + newscript->pGOHello = &GOHello_go_eastern_crystal_pylon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_western_crystal_pylon"; + newscript->pGOHello = &GOHello_go_western_crystal_pylon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_barov_journal"; + newscript->pGOHello = &GOHello_go_barov_journal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_field_repair_bot_74A"; + newscript->pGOHello = &GOHello_go_field_repair_bot_74A; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_gilded_brazier"; + newscript->pGOHello = &GOHello_go_gilded_brazier; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_orb_of_command"; + newscript->pGOHello = &GOHello_go_orb_of_command; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_shrine_of_the_birds"; + newscript->pGOHello = &GOHello_go_shrine_of_the_birds; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_southfury_moonstone"; + newscript->pGOHello = &GOHello_go_southfury_moonstone; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_tablet_of_madness"; + newscript->pGOHello = &GOHello_go_tablet_of_madness; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_tablet_of_the_seven"; + newscript->pGOHello = &GOHello_go_tablet_of_the_seven; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_jump_a_tron"; + newscript->pGOHello = &GOHello_go_jump_a_tron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_ethereum_prison"; + newscript->pGOHello = &GOHello_go_ethereum_prison; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_ethereum_stasis"; + newscript->pGOHello = &GOHello_go_ethereum_stasis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_resonite_cask"; + newscript->pGOHello = &GOHello_go_resonite_cask; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_sacred_fire_of_life"; + newscript->pGOHello = &GOHello_go_sacred_fire_of_life; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_tele_to_dalaran_crystal"; + newscript->pGOHello = &GOHello_go_tele_to_dalaran_crystal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_tele_to_violet_stand"; + newscript->pGOHello = &GOHello_go_tele_to_violet_stand; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_fel_crystalforge"; + newscript->pGOHello = &GOHello_go_fel_crystalforge; + newscript->pGOSelect = &GOSelect_go_fel_crystalforge; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_bashir_crystalforge"; + newscript->pGOHello = &GOHello_go_bashir_crystalforge; + newscript->pGOSelect = &GOSelect_go_bashir_crystalforge; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_matrix_punchograph"; + newscript->pGOHello = &GOHello_go_matrix_punchograph; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_rusty_cage"; + newscript->pGOHello = &GOHello_go_rusty_cage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_scourge_cage"; + newscript->pGOHello = &GOHello_go_scourge_cage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_arcane_prison"; + newscript->pGOHello = &GOHello_go_arcane_prison; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_blood_filled_orb"; + newscript->pGOHello = &GOHello_go_blood_filled_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_jotunheim_cage"; + newscript->pGOHello = &GOHello_go_jotunheim_cage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_table_theka"; + newscript->pGOHello = &GOHello_go_table_theka; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_inconspicuous_landmark"; + newscript->pGOHello = &GOHello_go_inconspicuous_landmark; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_soulwell"; + newscript->pGOHello = &GOHello_go_soulwell; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_tadpole_cage"; + newscript->pGOHello = &GOHello_go_tadpole_cage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_dragonflayer_cage"; + newscript->pGOHello = &GOHello_go_dragonflayer_cage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_black_cage"; + newscript->pGOHello = &GOHello_go_black_cage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_stillpine_cage"; + newscript->pGOHello = &GOHello_go_stillpine_cage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_amberpine_outhouse"; + newscript->pGOHello = &GOHello_go_amberpine_outhouse; + newscript->pGOSelect = &GOSelect_go_amberpine_outhouse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_hive_pod"; + newscript->pGOHello = &GOHello_go_hive_pod; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_massive_seaforium_charge"; + newscript->pGOHello = &GOHello_go_massive_seaforium_charge; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/World/guards.cpp b/src/server/scripts/World/guards.cpp new file mode 100644 index 00000000000..5faf9c73f7d --- /dev/null +++ b/src/server/scripts/World/guards.cpp @@ -0,0 +1,227 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Guards +SD%Complete: 100 +SDComment: All Guard gossip data, quite some npc_text-id's still missing, adding constantly as new id's are known. CombatAI should be organized better for future. +SDCategory: Guards +EndScriptData */ + +/* ContentData +guard_generic +guard_orgrimmar +guard_shattrath_aldor +guard_shattrath_scryer +guard_stormwind +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedGuardAI.h" + +/******************************************************* + * guard_generic + *******************************************************/ + +CreatureAI* GetAI_guard_generic(Creature* pCreature) +{ + return new guardAI (pCreature); +} + +/******************************************************* + * guard_orgrimmar + *******************************************************/ + +CreatureAI* GetAI_guard_orgrimmar(Creature* pCreature) +{ + return new guardAI_orgrimmar (pCreature); +} + +/******************************************************* + * guard_shattrath_aldor + *******************************************************/ + +#define SPELL_BANISHED_SHATTRATH_A 36642 +#define SPELL_BANISHED_SHATTRATH_S 36671 +#define SPELL_BANISH_TELEPORT 36643 +#define SPELL_EXILE 39533 + +struct guard_shattrath_aldorAI : public guardAI +{ + guard_shattrath_aldorAI(Creature *c) : guardAI(c) {} + + uint32 Exile_Timer; + uint32 Banish_Timer; + uint64 PlayerGUID; + bool CanTeleport; + + void Reset() + { + Banish_Timer = 5000; + Exile_Timer = 8500; + PlayerGUID = 0; + CanTeleport = false; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (CanTeleport) + { + if (Exile_Timer <= diff) + { + if (Unit* temp = Unit::GetUnit(*me,PlayerGUID)) + { + temp->CastSpell(temp,SPELL_EXILE,true); + temp->CastSpell(temp,SPELL_BANISH_TELEPORT,true); + } + PlayerGUID = 0; + Exile_Timer = 8500; + CanTeleport = false; + } else Exile_Timer -= diff; + } + else if (Banish_Timer <= diff) + { + Unit* temp = me->getVictim(); + if (temp && temp->GetTypeId() == TYPEID_PLAYER) + { + DoCast(temp, SPELL_BANISHED_SHATTRATH_A); + Banish_Timer = 9000; + PlayerGUID = temp->GetGUID(); + if (PlayerGUID) + CanTeleport = true; + } + } else Banish_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_guard_shattrath_aldor(Creature* pCreature) +{ + return new guard_shattrath_aldorAI (pCreature); +} + +/******************************************************* + * guard_shattrath_scryer + *******************************************************/ + +struct guard_shattrath_scryerAI : public guardAI +{ + guard_shattrath_scryerAI(Creature *c) : guardAI(c) {} + + uint32 Exile_Timer; + uint32 Banish_Timer; + uint64 PlayerGUID; + bool CanTeleport; + + void Reset() + { + Banish_Timer = 5000; + Exile_Timer = 8500; + PlayerGUID = 0; + CanTeleport = false; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (CanTeleport) + { + if (Exile_Timer <= diff) + { + if (Unit* temp = Unit::GetUnit(*me,PlayerGUID)) + { + temp->CastSpell(temp,SPELL_EXILE,true); + temp->CastSpell(temp,SPELL_BANISH_TELEPORT,true); + } + PlayerGUID = 0; + Exile_Timer = 8500; + CanTeleport = false; + } else Exile_Timer -= diff; + } + else if (Banish_Timer <= diff) + { + Unit* temp = me->getVictim(); + if (temp && temp->GetTypeId() == TYPEID_PLAYER) + { + DoCast(temp, SPELL_BANISHED_SHATTRATH_S); + Banish_Timer = 9000; + PlayerGUID = temp->GetGUID(); + if (PlayerGUID) + CanTeleport = true; + } + } else Banish_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_guard_shattrath_scryer(Creature* pCreature) +{ + return new guard_shattrath_scryerAI (pCreature); +} + +/******************************************************* + * guard_stormwind + *******************************************************/ + +CreatureAI* GetAI_guard_stormwind(Creature* pCreature) +{ + return new guardAI_stormwind (pCreature); +} + +/******************************************************* + * AddSC + *******************************************************/ + +void AddSC_guards() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "guard_generic"; + newscript->GetAI = &GetAI_guard_generic; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "guard_orgrimmar"; + newscript->GetAI = &GetAI_guard_orgrimmar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "guard_shattrath_aldor"; + newscript->GetAI = &GetAI_guard_shattrath_aldor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "guard_shattrath_scryer"; + newscript->GetAI = &GetAI_guard_shattrath_scryer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "guard_stormwind"; + newscript->GetAI = &GetAI_guard_stormwind; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp new file mode 100644 index 00000000000..dbf5f3c1a84 --- /dev/null +++ b/src/server/scripts/World/item_scripts.cpp @@ -0,0 +1,479 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Item_Scripts +SD%Complete: 100 +SDComment: Items for a range of different items. See content below (in script) +SDCategory: Items +EndScriptData */ + +/* ContentData +item_draenei_fishing_net(i23654) Hacklike implements chance to spawn item or creature +item_nether_wraith_beacon(i31742) Summons creatures for quest Becoming a Spellfire Tailor (q10832) +item_flying_machine(i34060,i34061) Engineering crafted flying machines +item_gor_dreks_ointment(i30175) Protecting Our Own(q10488) +item_only_for_flight Items which should only useable while flying +EndContentData */ + +#include "ScriptedPch.h" +#include "Spell.h" + +/*##### +# item_only_for_flight +#####*/ + +enum eOnlyForFlight +{ + SPELL_ARCANE_CHARGES = 45072 +}; + +bool ItemUse_item_only_for_flight(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/) +{ + uint32 itemId = pItem->GetEntry(); + bool disabled = false; + + //for special scripts + switch(itemId) + { + case 24538: + if (pPlayer->GetAreaId() != 3628) + disabled = true; + break; + case 34489: + if (pPlayer->GetZoneId() != 4080) + disabled = true; + break; + case 34475: + if (const SpellEntry* pSpellInfo = GetSpellStore()->LookupEntry(SPELL_ARCANE_CHARGES)) + Spell::SendCastResult(pPlayer, pSpellInfo, 1, SPELL_FAILED_NOT_ON_GROUND); + break; + } + + // allow use in flight only + if (pPlayer->isInFlight() && !disabled) + return false; + + // error + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,pItem,NULL); + return true; +} + +/*##### +# item_draenei_fishing_net +#####*/ + +//This is just a hack and should be removed from here. +//Creature/Item are in fact created before spell are sucessfully casted, without any checks at all to ensure proper/expected behavior. +bool ItemUse_item_draenei_fishing_net(Player* pPlayer, Item* /*pItem*/, SpellCastTargets const& /*targets*/) +{ + //if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT && + //targets.getGOTarget()->GetGOInfo()->type == GAMEOBJECT_TYPE_SPELL_FOCUS && targets.getGOTarget()->GetEntry() == 181616) + //{ + if (pPlayer->GetQuestStatus(9452) == QUEST_STATUS_INCOMPLETE) + { + if (urand(0,99) < 35) + { + Creature *Murloc = pPlayer->SummonCreature(17102, pPlayer->GetPositionX(), pPlayer->GetPositionY()+20, pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); + if (Murloc) + Murloc->AI()->AttackStart(pPlayer); + } + else + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 23614, 1); + if (msg == EQUIP_ERR_OK) + { + if (Item* item = pPlayer->StoreNewItem(dest,23614,true)) + pPlayer->SendNewItem(item,1,false,true); + } else + pPlayer->SendEquipError(msg,NULL,NULL); + } + } + //} + return false; +} + +/*##### +# item_nether_wraith_beacon +#####*/ + +bool ItemUse_item_nether_wraith_beacon(Player* pPlayer, Item* /*pItem*/, SpellCastTargets const& /*targets*/) +{ + if (pPlayer->GetQuestStatus(10832) == QUEST_STATUS_INCOMPLETE) + { + Creature *Nether; + Nether = pPlayer->SummonCreature(22408, pPlayer->GetPositionX(), pPlayer->GetPositionY()+20, pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); + Nether = pPlayer->SummonCreature(22408, pPlayer->GetPositionX(), pPlayer->GetPositionY()-20, pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); + if (Nether) + Nether->AI()->AttackStart(pPlayer); + } + return false; +} + +/*##### +# item_flying_machine +#####*/ + +bool ItemUse_item_flying_machine(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/) +{ + uint32 itemId = pItem->GetEntry(); + if (itemId == 34060) + if (pPlayer->GetBaseSkillValue(SKILL_RIDING) >= 225) + return false; + + if (itemId == 34061) + if (pPlayer->GetBaseSkillValue(SKILL_RIDING) == 300) + return false; + + debug_log("TSCR: Player attempt to use item %u, but did not meet riding requirement",itemId); + pPlayer->SendEquipError(EQUIP_ERR_ERR_CANT_EQUIP_SKILL,pItem,NULL); + return true; +} + +/*##### +# item_gor_dreks_ointment +#####*/ + +bool ItemUse_item_gor_dreks_ointment(Player *pPlayer, Item *pItem, SpellCastTargets const& targets) +{ + if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT && + targets.getUnitTarget()->GetEntry() == 20748 && !targets.getUnitTarget()->HasAura(32578)) + return false; + + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,pItem,NULL); + return true; +} + +/*##### +# item_incendiary_explosives +#####*/ + +bool ItemUse_item_incendiary_explosives(Player *pPlayer, Item *pItem, SpellCastTargets const & /*targets*/) +{ + if (pPlayer->FindNearestCreature(26248,15) || pPlayer->FindNearestCreature(26249,15)) + return false; + else + { + pPlayer->SendEquipError(EQUIP_ERR_OUT_OF_RANGE,pItem,NULL); + return true; + } +} + +/*##### +# item_mysterious_egg +#####*/ + +bool ItemExpire_item_mysterious_egg(Player *pPlayer, ItemPrototype const * /*pItemProto*/) +{ + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 39883, 1); // Cracked Egg + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, 39883, true, Item::GenerateItemRandomPropertyId(39883)); + + return true; +} + +/*##### +# item_disgusting_jar +#####*/ + +bool ItemExpire_item_disgusting_jar(Player *pPlayer, ItemPrototype const * /*pItemProto*/) +{ + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 44718, 1); // Ripe Disgusting Jar + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, 44718, true, Item::GenerateItemRandomPropertyId(44718)); + + return true; +} + +/*##### +# item_harvesters_gift +#####*/ +#define GHOULS 28845 +bool ItemUse_item_harvesters_gift(Player* pPlayer, Item* /*pItem*/, SpellCastTargets const& /*targets*/) +{ + std::list MinionList; + pPlayer->GetAllMinionsByEntry(MinionList,GHOULS); + + if (pPlayer->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE) + { + if (!MinionList.empty()) + { + if (MinionList.size() < 5) + return false; + else + { + //This should be sent to the player as red text. + pPlayer->Say("You have created enough ghouls. Return to Gothik the Harvester at Death's Breach.",LANG_UNIVERSAL); + return true; + } + } + else + return false; + } + return true; +} + +/*##### +# item_pile_fake_furs +#####*/ + +enum ePileFakeFur +{ + GO_CARIBOU_TRAP_1 = 187982, + GO_CARIBOU_TRAP_2 = 187995, + GO_CARIBOU_TRAP_3 = 187996, + GO_CARIBOU_TRAP_4 = 187997, + GO_CARIBOU_TRAP_5 = 187998, + GO_CARIBOU_TRAP_6 = 187999, + GO_CARIBOU_TRAP_7 = 188000, + GO_CARIBOU_TRAP_8 = 188001, + GO_CARIBOU_TRAP_9 = 188002, + GO_CARIBOU_TRAP_10 = 188003, + GO_CARIBOU_TRAP_11 = 188004, + GO_CARIBOU_TRAP_12 = 188005, + GO_CARIBOU_TRAP_13 = 188006, + GO_CARIBOU_TRAP_14 = 188007, + GO_CARIBOU_TRAP_15 = 188008, + GO_HIGH_QUALITY_FUR = 187983, + NPC_NESINGWARY_TRAPPER = 25835 +}; + +#define CaribouTrapsNum 15 +const uint32 CaribouTraps[CaribouTrapsNum] = +{ + GO_CARIBOU_TRAP_1, GO_CARIBOU_TRAP_2, GO_CARIBOU_TRAP_3, GO_CARIBOU_TRAP_4, GO_CARIBOU_TRAP_5, + GO_CARIBOU_TRAP_6, GO_CARIBOU_TRAP_7, GO_CARIBOU_TRAP_8, GO_CARIBOU_TRAP_9, GO_CARIBOU_TRAP_10, + GO_CARIBOU_TRAP_11, GO_CARIBOU_TRAP_12, GO_CARIBOU_TRAP_13, GO_CARIBOU_TRAP_14, GO_CARIBOU_TRAP_15, +}; + + +bool ItemUse_item_pile_fake_furs(Player *pPlayer, Item * /*pItem*/, SpellCastTargets const & /*targets*/) +{ + GameObject *pGo = NULL; + for (uint8 i = 0; i < CaribouTrapsNum; ++i) + { + pGo = pPlayer->FindNearestGameObject(CaribouTraps[i], 5.0f); + if (pGo) + break; + } + + if (!pGo) + return false; + + if (pGo->FindNearestCreature(NPC_NESINGWARY_TRAPPER, 10.0f, true) || pGo->FindNearestCreature(NPC_NESINGWARY_TRAPPER, 10.0f, false) || pGo->FindNearestGameObject(GO_HIGH_QUALITY_FUR, 2.0f)) + return true; + + float x, y, z; + pGo->GetClosePoint(x, y, z, pGo->GetObjectSize() / 3, 7.0f); + pGo->SummonGameObject(GO_HIGH_QUALITY_FUR, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, 0, 0, 0, 0, 1000); + if (TempSummon* summon = pPlayer->SummonCreature(NPC_NESINGWARY_TRAPPER, x, y, z, pGo->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1000)) + { + summon->SetVisibility(VISIBILITY_OFF); + summon->SetReactState(REACT_PASSIVE); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + return false; +} + +/*##### +# item_petrov_cluster_bombs +#####*/ + +enum ePetrovClusterBombs +{ + SPELL_PETROV_BOMB = 42406, + AREA_ID_SHATTERED_STRAITS = 4064, + ZONE_ID_HOWLING = 495 +}; + +bool ItemUse_item_petrov_cluster_bombs(Player* pPlayer, Item* pItem, const SpellCastTargets & /*pTargets*/) +{ + if (pPlayer->GetZoneId() != ZONE_ID_HOWLING) + return false; + + if (!pPlayer->GetTransport() || pPlayer->GetAreaId() != AREA_ID_SHATTERED_STRAITS) + { + pPlayer->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); + + if (const SpellEntry* pSpellInfo = GetSpellStore()->LookupEntry(SPELL_PETROV_BOMB)) + Spell::SendCastResult(pPlayer, pSpellInfo, 1, SPELL_FAILED_NOT_HERE); + + return true; + } + + return false; +} + +/*###### +# item_dehta_trap_smasher +# For quest 11876, Help Those That Cannot Help Themselves +######*/ +enum eHelpThemselves +{ + QUEST_CANNOT_HELP_THEMSELVES = 11876, + NPC_TRAPPED_MAMMOTH_CALF = 25850, + GO_MAMMOTH_TRAP_1 = 188022, + GO_MAMMOTH_TRAP_2 = 188024, + GO_MAMMOTH_TRAP_3 = 188025, + GO_MAMMOTH_TRAP_4 = 188026, + GO_MAMMOTH_TRAP_5 = 188027, + GO_MAMMOTH_TRAP_6 = 188028, + GO_MAMMOTH_TRAP_7 = 188029, + GO_MAMMOTH_TRAP_8 = 188030, + GO_MAMMOTH_TRAP_9 = 188031, + GO_MAMMOTH_TRAP_10 = 188032, + GO_MAMMOTH_TRAP_11 = 188033, + GO_MAMMOTH_TRAP_12 = 188034, + GO_MAMMOTH_TRAP_13 = 188035, + GO_MAMMOTH_TRAP_14 = 188036, + GO_MAMMOTH_TRAP_15 = 188037, + GO_MAMMOTH_TRAP_16 = 188038, + GO_MAMMOTH_TRAP_17 = 188039, + GO_MAMMOTH_TRAP_18 = 188040, + GO_MAMMOTH_TRAP_19 = 188041, + GO_MAMMOTH_TRAP_20 = 188042, + GO_MAMMOTH_TRAP_21 = 188043, + GO_MAMMOTH_TRAP_22 = 188044, +}; + +#define MammothTrapsNum 22 +const uint32 MammothTraps[MammothTrapsNum] = +{ + GO_MAMMOTH_TRAP_1, GO_MAMMOTH_TRAP_2, GO_MAMMOTH_TRAP_3, GO_MAMMOTH_TRAP_4, GO_MAMMOTH_TRAP_5, + GO_MAMMOTH_TRAP_6, GO_MAMMOTH_TRAP_7, GO_MAMMOTH_TRAP_8, GO_MAMMOTH_TRAP_9, GO_MAMMOTH_TRAP_10, + GO_MAMMOTH_TRAP_11, GO_MAMMOTH_TRAP_12, GO_MAMMOTH_TRAP_13, GO_MAMMOTH_TRAP_14, GO_MAMMOTH_TRAP_15, + GO_MAMMOTH_TRAP_16, GO_MAMMOTH_TRAP_17, GO_MAMMOTH_TRAP_18, GO_MAMMOTH_TRAP_19, GO_MAMMOTH_TRAP_20, + GO_MAMMOTH_TRAP_21, GO_MAMMOTH_TRAP_22 +}; + +bool ItemUse_item_dehta_trap_smasher(Player* pPlayer, Item* /*pItem*/, const SpellCastTargets & /*pTargets*/) +{ + if (pPlayer->GetQuestStatus(QUEST_CANNOT_HELP_THEMSELVES) != QUEST_STATUS_INCOMPLETE) + return false; + + Creature* pMammoth; + pMammoth = pPlayer->FindNearestCreature(NPC_TRAPPED_MAMMOTH_CALF,5.0f); + if (!pMammoth) + return false; + + GameObject* pTrap; + for (uint8 i = 0; i < MammothTrapsNum; ++i) + { + pTrap = pPlayer->FindNearestGameObject(MammothTraps[i],11.0f); + if (pTrap) + { + pMammoth->AI()->DoAction(1); + pTrap->SetGoState(GO_STATE_READY); + pPlayer->KilledMonsterCredit(NPC_TRAPPED_MAMMOTH_CALF,0); + return true; + } + } + return false; +} + +enum TheEmissary +{ + QUEST_THE_EMISSARY = 11626, + NPC_LEVIROTH = 26452 +}; + +bool ItemUse_item_Trident_of_Nazjan(Player* pPlayer, Item* pItem, const SpellCastTargets & /*pTargets*/) +{ + if (pPlayer->GetQuestStatus(QUEST_THE_EMISSARY) == QUEST_STATUS_INCOMPLETE) + { + if (Creature* pLeviroth = pPlayer->FindNearestCreature(NPC_LEVIROTH, 10.0f)) // spell range + { + pLeviroth->AI()->AttackStart(pPlayer); + return false; + } else + pPlayer->SendEquipError(EQUIP_ERR_OUT_OF_RANGE, pItem, NULL); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW ,pItem, NULL); + return true; +} + +void AddSC_item_scripts() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "item_only_for_flight"; + newscript->pItemUse = &ItemUse_item_only_for_flight; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_draenei_fishing_net"; + newscript->pItemUse = &ItemUse_item_draenei_fishing_net; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_nether_wraith_beacon"; + newscript->pItemUse = &ItemUse_item_nether_wraith_beacon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_flying_machine"; + newscript->pItemUse = &ItemUse_item_flying_machine; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_gor_dreks_ointment"; + newscript->pItemUse = &ItemUse_item_gor_dreks_ointment; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_incendiary_explosives"; + newscript->pItemUse = &ItemUse_item_incendiary_explosives; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_mysterious_egg"; + newscript->pItemExpire = &ItemExpire_item_mysterious_egg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_disgusting_jar"; + newscript->pItemExpire = &ItemExpire_item_disgusting_jar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_harvesters_gift"; + newscript->pItemUse = &ItemUse_item_harvesters_gift; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_pile_fake_furs"; + newscript->pItemUse = &ItemUse_item_pile_fake_furs; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_petrov_cluster_bombs"; + newscript->pItemUse = &ItemUse_item_petrov_cluster_bombs; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_dehta_trap_smasher"; + newscript->pItemUse = &ItemUse_item_dehta_trap_smasher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_Trident_of_Nazjan"; + newscript->pItemUse = &ItemUse_item_Trident_of_Nazjan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/World/mob_generic_creature.cpp b/src/server/scripts/World/mob_generic_creature.cpp new file mode 100644 index 00000000000..3ab515d8206 --- /dev/null +++ b/src/server/scripts/World/mob_generic_creature.cpp @@ -0,0 +1,228 @@ + +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Generic_Creature +SD%Complete: 80 +SDComment: Should be replaced with core based AI +SDCategory: Creatures +EndScriptData */ + +#include "ScriptedPch.h" + +#define GENERIC_CREATURE_COOLDOWN 5000 + +struct generic_creatureAI : public ScriptedAI +{ + generic_creatureAI(Creature *c) : ScriptedAI(c) {} + + uint32 GlobalCooldown; //This variable acts like the global cooldown that players have (1.5 seconds) + uint32 BuffTimer; //This variable keeps track of buffs + bool IsSelfRooted; + + void Reset() + { + GlobalCooldown = 0; + BuffTimer = 0; //Rebuff as soon as we can + IsSelfRooted = false; + } + + void EnterCombat(Unit *who) + { + if (!me->IsWithinMeleeRange(who)) + { + IsSelfRooted = true; + } + } + + void UpdateAI(const uint32 diff) + { + //Always decrease our global cooldown first + if (GlobalCooldown > diff) + GlobalCooldown -= diff; + else GlobalCooldown = 0; + + //Buff timer (only buff when we are alive and not in combat + if (!me->isInCombat() && me->isAlive()) + if (BuffTimer <= diff) + { + //Find a spell that targets friendly and applies an aura (these are generally buffs) + SpellEntry const *info = SelectSpell(me, 0, 0, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_AURA); + + if (info && !GlobalCooldown) + { + //Cast the buff spell + DoCastSpell(me, info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + + //Set our timer to 10 minutes before rebuff + BuffTimer = 600000; + }//Try agian in 30 seconds + else BuffTimer = 30000; + } else BuffTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + //Make sure our attack is ready and we arn't currently casting + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + bool Healing = false; + SpellEntry const *info = NULL; + + //Select a healing spell if less than 30% hp + if (me->GetHealth()*100 / me->GetMaxHealth() < 30) + info = SelectSpell(me, 0, 0, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); + + //No healing spell available, select a hostile spell + if (info) Healing = true; + else info = SelectSpell(me->getVictim(), 0, 0, SELECT_TARGET_ANY_ENEMY, 0, 0, 0, 0, SELECT_EFFECT_DONTCARE); + + //50% chance if elite or higher, 20% chance if not, to replace our white hit with a spell + if (info && (rand() % (me->GetCreatureInfo()->rank > 1 ? 2 : 5) == 0) && !GlobalCooldown) + { + //Cast the spell + if (Healing)DoCastSpell(me, info); + else DoCastSpell(me->getVictim(), info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + } + else me->AttackerStateUpdate(me->getVictim()); + + me->resetAttackTimer(); + } + } + else + { + //Only run this code if we arn't already casting + if (!me->IsNonMeleeSpellCasted(false)) + { + bool Healing = false; + SpellEntry const *info = NULL; + + //Select a healing spell if less than 30% hp ONLY 33% of the time + if (me->GetHealth()*100 / me->GetMaxHealth() < 30 && rand() % 3 == 0) + info = SelectSpell(me, 0, 0, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); + + //No healing spell available, See if we can cast a ranged spell (Range must be greater than ATTACK_DISTANCE) + if (info) Healing = true; + else info = SelectSpell(me->getVictim(), 0, 0, SELECT_TARGET_ANY_ENEMY, 0, 0, NOMINAL_MELEE_RANGE, 0, SELECT_EFFECT_DONTCARE); + + //Found a spell, check if we arn't on cooldown + if (info && !GlobalCooldown) + { + //If we are currently moving stop us and set the movement generator + if (!IsSelfRooted) + { + IsSelfRooted = true; + } + + //Cast spell + if (Healing) DoCastSpell(me,info); + else DoCastSpell(me->getVictim(),info); + + //Set our global cooldown + GlobalCooldown = GENERIC_CREATURE_COOLDOWN; + + }//If no spells available and we arn't moving run to target + else if (IsSelfRooted) + { + //Cancel our current spell and then allow movement agian + me->InterruptNonMeleeSpells(false); + IsSelfRooted = false; + } + } + } + } +}; + +CreatureAI* GetAI_generic_creature(Creature* pCreature) +{ + return new generic_creatureAI (pCreature); +} + +struct trigger_periodicAI : public NullCreatureAI +{ + trigger_periodicAI(Creature* c) : NullCreatureAI(c) + { + spell = me->m_spells[0] ? GetSpellStore()->LookupEntry(me->m_spells[0]) : NULL; + interval = me->GetAttackTime(BASE_ATTACK); + timer = interval; + } + + uint32 timer, interval; + const SpellEntry * spell; + + void UpdateAI(const uint32 diff) + { + if (timer <= diff) + { + if (spell) + me->CastSpell(me, spell, true); + timer = interval; + } + else + timer -= diff; + } +}; + +struct trigger_deathAI : public NullCreatureAI +{ + trigger_deathAI(Creature* c) : NullCreatureAI(c) {} + void JustDied(Unit *killer) + { + if (me->m_spells[0]) + me->CastSpell(killer, me->m_spells[0], true); + } +}; + +CreatureAI* GetAI_trigger_periodic(Creature* pCreature) +{ + return new trigger_periodicAI (pCreature); +} + +CreatureAI* GetAI_trigger_death(Creature* pCreature) +{ + return new trigger_deathAI (pCreature); +} + +void AddSC_generic_creature() +{ + Script *newscript; + /*newscript = new Script; + newscript->Name = "generic_creature"; + newscript->GetAI = &GetAI_generic_creature; + newscript->RegisterSelf();*/ + + newscript = new Script; + newscript->Name = "trigger_periodic"; + newscript->GetAI = &GetAI_trigger_periodic; + newscript->RegisterSelf(); + + /*newscript = new Script; + newscript->Name = "trigger_death"; + newscript->GetAI = &GetAI_trigger_death; + newscript->RegisterSelf();*/ +} + diff --git a/src/server/scripts/World/npc_innkeeper.cpp b/src/server/scripts/World/npc_innkeeper.cpp new file mode 100644 index 00000000000..9bda7a53516 --- /dev/null +++ b/src/server/scripts/World/npc_innkeeper.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Npc_Innkeeper +SDAuthor: WarHead +SD%Complete: 99% +SDComment: Complete +SDCategory: NPCs +EndScriptData */ + +#include "ScriptedPch.h" + +#define HALLOWEEN_EVENTID 12 +#define SPELL_TRICK_OR_TREATED 24755 +#define SPELL_TREAT 24715 + +#define LOCALE_TRICK_OR_TREAT_0 "Trick or Treat!" +#define LOCALE_TRICK_OR_TREAT_2 "Des bonbons ou des blagues!" +#define LOCALE_TRICK_OR_TREAT_3 "Süßes oder Saures!" +#define LOCALE_TRICK_OR_TREAT_6 "¡Truco o trato!" + +#define LOCALE_INNKEEPER_0 "Make this inn my home." +#define LOCALE_INNKEEPER_3 "Ich möchte dieses Gasthaus zu meinem Heimatort machen." + +bool GossipHello_npc_innkeeper(Player *pPlayer, Creature *pCreature) +{ + if (IsEventActive(HALLOWEEN_EVENTID) && !pPlayer->HasAura(SPELL_TRICK_OR_TREATED)) + { + char* localizedEntry; + switch (pPlayer->GetSession()->GetSessionDbcLocale()) + { + case LOCALE_frFR: localizedEntry = LOCALE_TRICK_OR_TREAT_2; break; + case LOCALE_deDE: localizedEntry = LOCALE_TRICK_OR_TREAT_3; break; + case LOCALE_esES: localizedEntry = LOCALE_TRICK_OR_TREAT_6; break; + case LOCALE_enUS: default: localizedEntry = LOCALE_TRICK_OR_TREAT_0; + } + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, localizedEntry, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+HALLOWEEN_EVENTID); + } + + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (pCreature->isInnkeeper()) + { + char* localizedEntry; + switch (pPlayer->GetSession()->GetSessionDbcLocale()) + { + case LOCALE_deDE: localizedEntry = LOCALE_INNKEEPER_3; break; + case LOCALE_enUS: default: localizedEntry = LOCALE_INNKEEPER_0; + } + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_INTERACT_1, localizedEntry, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INN); + } + + pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_innkeeper(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+HALLOWEEN_EVENTID && IsEventActive(HALLOWEEN_EVENTID) && !pPlayer->HasAura(SPELL_TRICK_OR_TREATED)) + { + pPlayer->CastSpell(pPlayer, SPELL_TRICK_OR_TREATED, true); + + if (urand(0, 1)) + pPlayer->CastSpell(pPlayer, SPELL_TREAT, true); + else + { + uint32 trickspell = 0; + switch (urand(0, 13)) + { + case 0: trickspell = 24753; break; // cannot cast, random 30sec + case 1: trickspell = 24713; break; // lepper gnome costume + case 2: trickspell = 24735; break; // male ghost costume + case 3: trickspell = 24736; break; // female ghostcostume + case 4: trickspell = 24710; break; // male ninja costume + case 5: trickspell = 24711; break; // female ninja costume + case 6: trickspell = 24708; break; // male pirate costume + case 7: trickspell = 24709; break; // female pirate costume + case 8: trickspell = 24723; break; // skeleton costume + case 9: trickspell = 24753; break; // Trick + case 10: trickspell = 24924; break; // Hallow's End Candy + case 11: trickspell = 24925; break; // Hallow's End Candy + case 12: trickspell = 24926; break; // Hallow's End Candy + case 13: trickspell = 24927; break; // Hallow's End Candy + } + pPlayer->CastSpell(pPlayer, trickspell, true); + } + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + } + + pPlayer->CLOSE_GOSSIP_MENU(); + + switch (uiAction) + { + case GOSSIP_ACTION_TRADE: pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); break; + case GOSSIP_ACTION_INN: pPlayer->SetBindPoint(pCreature->GetGUID()); break; + } + return true; +} + +void AddSC_npc_innkeeper() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "npc_innkeeper"; + newscript->pGossipHello = &GossipHello_npc_innkeeper; + newscript->pGossipSelect = &GossipSelect_npc_innkeeper; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/World/npc_professions.cpp b/src/server/scripts/World/npc_professions.cpp new file mode 100644 index 00000000000..ed22225d0d4 --- /dev/null +++ b/src/server/scripts/World/npc_professions.cpp @@ -0,0 +1,1342 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Npc_Professions +SD%Complete: 80 +SDComment: Provides learn/unlearn/relearn-options for professions. Not supported: Unlearn engineering, re-learn engineering, re-learn leatherworking. +SDCategory: NPCs +EndScriptData */ + +#include "ScriptedPch.h" + +/* +A few notes for future developement: +- A full implementation of gossip for GO's is required. They must have the same scripting capabilities as creatures. Basically, +there is no difference here (except that default text is chosen with `gameobject_template`.`data3` (for GO type2, different dataN for a few others) +- It's possible blacksmithing still require some tweaks and adjustments due to the way we _have_ to use reputation. +*/ + +/* +-- UPDATE `gameobject_template` SET `ScriptName` = 'go_soothsaying_for_dummies' WHERE `entry` = 177226; +*/ + +/*### +# to be removed from here (->ncp_text). This is data for database projects. +###*/ +#define TALK_MUST_UNLEARN_WEAPON "You must forget your weapon type specialty before I can help you. Go to Everlook in Winterspring and seek help there." + +#define TALK_HAMMER_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the hammersmith." +#define TALK_AXE_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the axesmith." +#define TALK_SWORD_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the swordsmith." + +#define TALK_HAMMER_UNLEARN "Forgetting your Hammersmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Hammersmithing to create!" +#define TALK_AXE_UNLEARN "Forgetting your Axesmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Axesmithing to create!" +#define TALK_SWORD_UNLEARN "Forgetting your Swordsmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Swordsmithing to create!" + +/*### +# generic defines +###*/ + +#define GOSSIP_SENDER_LEARN 50 +#define GOSSIP_SENDER_UNLEARN 51 +#define GOSSIP_SENDER_CHECK 52 + +/*### +# gossip item and box texts +###*/ + +#define GOSSIP_LEARN_POTION "Please teach me how to become a Master of Potions, Lauranna" +#define GOSSIP_UNLEARN_POTION "I wish to unlearn Potion Mastery" +#define GOSSIP_LEARN_TRANSMUTE "Please teach me how to become a Master of Transmutations, Zarevhi" +#define GOSSIP_UNLEARN_TRANSMUTE "I wish to unlearn Transmutation Mastery" +#define GOSSIP_LEARN_ELIXIR "Please teach me how to become a Master of Elixirs, Lorokeem" +#define GOSSIP_UNLEARN_ELIXIR "I wish to unlearn Elixir Mastery" + +#define BOX_UNLEARN_ALCHEMY_SPEC "Do you really want to unlearn your alchemy specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_WEAPON_LEARN "Please teach me how to become a Weaponsmith" +#define GOSSIP_WEAPON_UNLEARN "I wish to unlearn the art of Weaponsmithing" +#define GOSSIP_ARMOR_LEARN "Please teach me how to become a Armorsmith" +#define GOSSIP_ARMOR_UNLEARN "I wish to unlearn the art of Armorsmithing" + +#define GOSSIP_UNLEARN_SMITH_SPEC "I wish to unlearn my blacksmith specialty" +#define BOX_UNLEARN_ARMORORWEAPON "Do you really want to unlearn your blacksmith specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_LEARN_HAMMER "Please teach me how to become a Hammersmith, Lilith" +#define GOSSIP_UNLEARN_HAMMER "I wish to unlearn Hammersmithing" +#define GOSSIP_LEARN_AXE "Please teach me how to become a Axesmith, Kilram" +#define GOSSIP_UNLEARN_AXE "I wish to unlearn Axesmithing" +#define GOSSIP_LEARN_SWORD "Please teach me how to become a Swordsmith, Seril" +#define GOSSIP_UNLEARN_SWORD "I wish to unlearn Swordsmithing" + +#define BOX_UNLEARN_WEAPON_SPEC "Do you really want to unlearn your weaponsmith specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_LEARN_DRAGON "I am absolutely certain that i want to learn dragonscale leatherworking" +#define GOSSIP_UNLEARN_DRAGON "I wish to unlearn Dragonscale Leatherworking" +#define GOSSIP_LEARN_ELEMENTAL "I am absolutely certain that i want to learn elemental leatherworking" +#define GOSSIP_UNLEARN_ELEMENTAL "I wish to unlearn Elemental Leatherworking" +#define GOSSIP_LEARN_TRIBAL "I am absolutely certain that i want to learn tribal leatherworking" +#define GOSSIP_UNLEARN_TRIBAL "I wish to unlearn Tribal Leatherworking" + +#define BOX_UNLEARN_LEATHER_SPEC "Do you really want to unlearn your leatherworking specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_LEARN_SPELLFIRE "Please teach me how to become a Spellcloth tailor" +#define GOSSIP_UNLEARN_SPELLFIRE "I wish to unlearn Spellfire Tailoring" +#define GOSSIP_LEARN_MOONCLOTH "Please teach me how to become a Mooncloth tailor" +#define GOSSIP_UNLEARN_MOONCLOTH "I wish to unlearn Mooncloth Tailoring" +#define GOSSIP_LEARN_SHADOWEAVE "Please teach me how to become a Shadoweave tailor" +#define GOSSIP_UNLEARN_SHADOWEAVE "I wish to unlearn Shadoweave Tailoring" + +#define BOX_UNLEARN_TAILOR_SPEC "Do you really want to unlearn your tailoring specialty and lose all associated recipes? \n Cost: " + +#define GOSSIP_LEARN_GOBLIN "I am absolutely certain that i want to learn Goblin engineering" +#define GOSSIP_LEARN_GNOMISH "I am absolutely certain that i want to learn Gnomish engineering" + +/*### +# spells defines +###*/ + +#define S_WEAPON 9787 +#define S_ARMOR 9788 +#define S_HAMMER 17040 +#define S_AXE 17041 +#define S_SWORD 17039 + +#define S_LEARN_WEAPON 9789 +#define S_LEARN_ARMOR 9790 +#define S_LEARN_HAMMER 39099 +#define S_LEARN_AXE 39098 +#define S_LEARN_SWORD 39097 + +#define S_UNLEARN_WEAPON 36436 +#define S_UNLEARN_ARMOR 36435 +#define S_UNLEARN_HAMMER 36441 +#define S_UNLEARN_AXE 36439 +#define S_UNLEARN_SWORD 36438 + +#define S_REP_ARMOR 17451 +#define S_REP_WEAPON 17452 + +#define REP_ARMOR 46 +#define REP_WEAPON 289 +#define REP_HAMMER 569 +#define REP_AXE 570 +#define REP_SWORD 571 + +#define S_DRAGON 10656 +#define S_ELEMENTAL 10658 +#define S_TRIBAL 10660 + +#define S_LEARN_DRAGON 10657 +#define S_LEARN_ELEMENTAL 10659 +#define S_LEARN_TRIBAL 10661 + +#define S_UNLEARN_DRAGON 36434 +#define S_UNLEARN_ELEMENTAL 36328 +#define S_UNLEARN_TRIBAL 36433 + +#define S_GOBLIN 20222 +#define S_GNOMISH 20219 + +#define S_LEARN_GOBLIN 20221 +#define S_LEARN_GNOMISH 20220 + +#define S_SPELLFIRE 26797 +#define S_MOONCLOTH 26798 +#define S_SHADOWEAVE 26801 + +#define S_LEARN_SPELLFIRE 26796 +#define S_LEARN_MOONCLOTH 26799 +#define S_LEARN_SHADOWEAVE 26800 + +#define S_UNLEARN_SPELLFIRE 41299 +#define S_UNLEARN_MOONCLOTH 41558 +#define S_UNLEARN_SHADOWEAVE 41559 + +#define S_TRANSMUTE 28672 +#define S_ELIXIR 28677 +#define S_POTION 28675 + +#define S_LEARN_TRANSMUTE 28674 +#define S_LEARN_ELIXIR 28678 +#define S_LEARN_POTION 28676 + +#define S_UNLEARN_TRANSMUTE 41565 +#define S_UNLEARN_ELIXIR 41564 +#define S_UNLEARN_POTION 41563 + +/*### +# formulas to calculate unlearning cost +###*/ + +int32 DoLearnCost(Player* /*pPlayer*/) //tailor, alchemy +{ + return 200000; +} + +int32 DoHighUnlearnCost(Player* /*pPlayer*/) //tailor, alchemy +{ + return 1500000; +} + +int32 DoMedUnlearnCost(Player* pPlayer) //blacksmith, leatherwork +{ + uint8 level = pPlayer->getLevel(); + if (level < 51) + return 250000; + else if (level < 66) + return 500000; + else + return 1000000; +} + +int32 DoLowUnlearnCost(Player* pPlayer) //blacksmith +{ + uint8 level = pPlayer->getLevel(); + if (level < 66) + return 50000; + else + return 100000; +} + +/*### +# unlearning related profession spells +###*/ + +bool EquippedOk(Player* pPlayer, uint32 spellId) +{ + SpellEntry const* spell = GetSpellStore()->LookupEntry(spellId); + + if (!spell) + return false; + + for (uint8 i = 0; i < 3; ++i) + { + uint32 reqSpell = spell->EffectTriggerSpell[i]; + if (!reqSpell) + continue; + + Item* pItem; + for (uint8 j = EQUIPMENT_SLOT_START; j < EQUIPMENT_SLOT_END; ++j) + { + pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, j); + if (pItem) + if (pItem->GetProto()->RequiredSpell == reqSpell) + { + //player has item equipped that require specialty. Not allow to unlearn, player has to unequip first + debug_log("TSCR: player attempt to unlearn spell %u, but item %u is equipped.",reqSpell,pItem->GetProto()->ItemId); + return false; + } + } + } + return true; +} + +void ProfessionUnlearnSpells(Player* pPlayer, uint32 type) +{ + switch (type) + { + case 36436: // S_UNLEARN_WEAPON + pPlayer->removeSpell(36125); // Light Earthforged Blade + pPlayer->removeSpell(36128); // Light Emberforged Hammer + pPlayer->removeSpell(36126); // Light Skyforged Axe + break; + case 36435: // S_UNLEARN_ARMOR + pPlayer->removeSpell(36122); // Earthforged Leggings + pPlayer->removeSpell(36129); // Heavy Earthforged Breastplate + pPlayer->removeSpell(36130); // Stormforged Hauberk + pPlayer->removeSpell(34533); // Breastplate of Kings + pPlayer->removeSpell(34529); // Nether Chain Shirt + pPlayer->removeSpell(34534); // Bulwark of Kings + pPlayer->removeSpell(36257); // Bulwark of the Ancient Kings + pPlayer->removeSpell(36256); // Embrace of the Twisting Nether + pPlayer->removeSpell(34530); // Twisting Nether Chain Shirt + pPlayer->removeSpell(36124); // Windforged Leggings + break; + case 36441: // S_UNLEARN_HAMMER + pPlayer->removeSpell(36262); // Dragonstrike + pPlayer->removeSpell(34546); // Dragonmaw + pPlayer->removeSpell(34545); // Drakefist Hammer + pPlayer->removeSpell(36136); // Lavaforged Warhammer + pPlayer->removeSpell(34547); // Thunder + pPlayer->removeSpell(34567); // Deep Thunder + pPlayer->removeSpell(36263); // Stormherald + pPlayer->removeSpell(36137); // Great Earthforged Hammer + break; + case 36439: // S_UNLEARN_AXE + pPlayer->removeSpell(36260); // Wicked Edge of the Planes + pPlayer->removeSpell(34562); // Black Planar Edge + pPlayer->removeSpell(34541); // The Planar Edge + pPlayer->removeSpell(36134); // Stormforged Axe + pPlayer->removeSpell(36135); // Skyforged Great Axe + pPlayer->removeSpell(36261); // Bloodmoon + pPlayer->removeSpell(34543); // Lunar Crescent + pPlayer->removeSpell(34544); // Mooncleaver + break; + case 36438: // S_UNLEARN_SWORD + pPlayer->removeSpell(36258); // Blazefury + pPlayer->removeSpell(34537); // Blazeguard + pPlayer->removeSpell(34535); // Fireguard + pPlayer->removeSpell(36131); // Windforged Rapier + pPlayer->removeSpell(36133); // Stoneforged Claymore + pPlayer->removeSpell(34538); // Lionheart Blade + pPlayer->removeSpell(34540); // Lionheart Champion + pPlayer->removeSpell(36259); // Lionheart Executioner + break; + case 36434: // S_UNLEARN_DRAGON + pPlayer->removeSpell(36076); // Dragonstrike Leggings + pPlayer->removeSpell(36079); // Golden Dragonstrike Breastplate + pPlayer->removeSpell(35576); // Ebon Netherscale Belt + pPlayer->removeSpell(35577); // Ebon Netherscale Bracers + pPlayer->removeSpell(35575); // Ebon Netherscale Breastplate + pPlayer->removeSpell(35582); // Netherstrike Belt + pPlayer->removeSpell(35584); // Netherstrike Bracers + pPlayer->removeSpell(35580); // Netherstrike Breastplate + break; + case 36328: // S_UNLEARN_ELEMENTAL + pPlayer->removeSpell(36074); // Blackstorm Leggings + pPlayer->removeSpell(36077); // Primalstorm Breastplate + pPlayer->removeSpell(35590); // Primalstrike Belt + pPlayer->removeSpell(35591); // Primalstrike Bracers + pPlayer->removeSpell(35589); // Primalstrike Vest + break; + case 36433: // S_UNLEARN_TRIBAL + pPlayer->removeSpell(35585); // Windhawk Hauberk + pPlayer->removeSpell(35587); // Windhawk Belt + pPlayer->removeSpell(35588); // Windhawk Bracers + pPlayer->removeSpell(36075); // Wildfeather Leggings + pPlayer->removeSpell(36078); // Living Crystal Breastplate + break; + case 41299: // S_UNLEARN_SPELLFIRE + pPlayer->removeSpell(26752); // Spellfire Belt + pPlayer->removeSpell(26753); // Spellfire Gloves + pPlayer->removeSpell(26754); // Spellfire Robe + break; + case 41558: // S_UNLEARN_MOONCLOTH + pPlayer->removeSpell(26760); // Primal Mooncloth Belt + pPlayer->removeSpell(26761); // Primal Mooncloth Shoulders + pPlayer->removeSpell(26762); // Primal Mooncloth Robe + break; + case 41559: // S_UNLEARN_SHADOWEAVE + pPlayer->removeSpell(26756); // Frozen Shadoweave Shoulders + pPlayer->removeSpell(26757); // Frozen Shadoweave Boots + pPlayer->removeSpell(26758); // Frozen Shadoweave Robe + break; + } +} + +/*### +# start menues alchemy +###*/ + +bool HasAlchemySpell(Player* pPlayer) +{ + if (pPlayer->HasSpell(S_TRANSMUTE) || pPlayer->HasSpell(S_ELIXIR) || pPlayer->HasSpell(S_POTION)) + return true; + return false; +} + +bool GossipHello_npc_prof_alchemy(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + if (pCreature->isTrainer()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + uint32 eCreature = pCreature->GetEntry(); + + if (pPlayer->HasSkill(SKILL_ALCHEMY) && pPlayer->GetBaseSkillValue(SKILL_ALCHEMY) >= 350 && pPlayer->getLevel() > 67) + { + if (pPlayer->GetQuestRewardStatus(10899) || pPlayer->GetQuestRewardStatus(10902) || pPlayer->GetQuestRewardStatus(10897)) + { + switch (eCreature) + { + case 22427: //Zarevhi + if (!HasAlchemySpell(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1); + if (pPlayer->HasSpell(S_TRANSMUTE)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); + break; + case 19052: //Lorokeem + if (!HasAlchemySpell(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2); + if (pPlayer->HasSpell(S_ELIXIR)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5); + break; + case 17909: //Lauranna Thar'well + if (!HasAlchemySpell(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_POTION, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3); + if (pPlayer->HasSpell(S_POTION)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 6); + break; + } + } + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +void SendActionMenu_npc_prof_alchemy(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + case GOSSIP_ACTION_TRAIN: + pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); + break; + //Learn Alchemy + case GOSSIP_ACTION_INFO_DEF + 1: + if (!pPlayer->HasSpell(S_TRANSMUTE) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_LEARN_TRANSMUTE, true); + pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if (!pPlayer->HasSpell(S_ELIXIR) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_LEARN_ELIXIR, true); + pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + if (!pPlayer->HasSpell(S_POTION) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_LEARN_POTION, true); + pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + //Unlearn Alchemy + case GOSSIP_ACTION_INFO_DEF + 4: + if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) + { + pCreature->CastSpell(pPlayer, S_UNLEARN_TRANSMUTE, true); + pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 5: + if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) + { + pCreature->CastSpell(pPlayer, S_UNLEARN_ELIXIR, true); + pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) + { + pCreature->CastSpell(pPlayer, S_UNLEARN_POTION, true); + pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } +} + +void SendConfirmLearn_npc_prof_alchemy(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction) + { + uint32 eCreature = pCreature->GetEntry(); + switch(eCreature) + { + case 22427: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 19052: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 17909: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_POTION, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + } + } +} + +void SendConfirmUnlearn_npc_prof_alchemy(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction) + { + uint32 eCreature = pCreature->GetEntry(); + switch(eCreature) + { + case 22427: //Zarevhi + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 19052: //Lorokeem + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 17909: //Lauranna Thar'well + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + } + } +} + +bool GossipSelect_npc_prof_alchemy(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiSender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_alchemy(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_alchemy(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_alchemy(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_alchemy(pPlayer, pCreature, uiAction); break; + } + return true; +} + +/*### +# start menues blacksmith +###*/ + +bool HasWeaponSub(Player* pPlayer) +{ + if (pPlayer->HasSpell(S_HAMMER) || pPlayer->HasSpell(S_AXE) || pPlayer->HasSpell(S_SWORD)) + return true; + return false; +} + +bool GossipHello_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + if (pCreature->isTrainer()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + uint32 eCreature = pCreature->GetEntry(); + //WEAPONSMITH & ARMORSMITH + if (pPlayer->GetBaseSkillValue(SKILL_BLACKSMITHING) >= 225) + { + switch (eCreature) + { + case 11145: //Myolor Sunderfury + case 11176: //Krathok Moltenfist + if (!pPlayer->HasSpell(S_ARMOR) && !pPlayer->HasSpell(S_WEAPON) && pPlayer->GetReputationRank(REP_ARMOR) >= REP_FRIENDLY) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARMOR_LEARN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + if (!pPlayer->HasSpell(S_WEAPON) && !pPlayer->HasSpell(S_ARMOR) && pPlayer->GetReputationRank(REP_WEAPON) >= REP_FRIENDLY) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEAPON_LEARN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + break; + case 11146: //Ironus Coldsteel + case 11178: //Borgosh Corebender + if (pPlayer->HasSpell(S_WEAPON)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEAPON_UNLEARN, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 3); + break; + case 5164: //Grumnus Steelshaper + case 11177: //Okothos Ironrager + if (pPlayer->HasSpell(S_ARMOR)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARMOR_UNLEARN, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); + break; + } + } + //WEAPONSMITH SPEC + if (pPlayer->HasSpell(S_WEAPON) && pPlayer->getLevel() > 49 && pPlayer->GetBaseSkillValue(SKILL_BLACKSMITHING) >= 250) + { + switch (eCreature) + { + case 11191: //Lilith the Lithe + if (!HasWeaponSub(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_HAMMER, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 5); + if (pPlayer->HasSpell(S_HAMMER)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_HAMMER, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 8); + break; + case 11192: //Kilram + if (!HasWeaponSub(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_AXE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 6); + if (pPlayer->HasSpell(S_AXE)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_AXE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 9); + break; + case 11193: //Seril Scourgebane + if (!HasWeaponSub(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SWORD, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 7); + if (pPlayer->HasSpell(S_SWORD)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_SWORD, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 10); + break; + } + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +void SendActionMenu_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + case GOSSIP_ACTION_TRAIN: + pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); + break; + //Learn Armor/Weapon + case GOSSIP_ACTION_INFO_DEF + 1: + if (!pPlayer->HasSpell(S_ARMOR)) + { + pPlayer->CastSpell(pPlayer, S_LEARN_ARMOR, true); + //_Creature->CastSpell(pPlayer, S_REP_ARMOR, true); + } + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if (!pPlayer->HasSpell(S_WEAPON)) + { + pPlayer->CastSpell(pPlayer, S_LEARN_WEAPON, true); + //_Creature->CastSpell(pPlayer, S_REP_WEAPON, true); + } + pPlayer->CLOSE_GOSSIP_MENU(); + break; + //Unlearn Armor/Weapon + case GOSSIP_ACTION_INFO_DEF + 3: + if (HasWeaponSub(pPlayer)) + { + //unknown textID (TALK_MUST_UNLEARN_WEAPON) + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + } + else if (EquippedOk(pPlayer,S_UNLEARN_WEAPON)) + { + if (pPlayer->GetMoney() >= DoLowUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_WEAPON, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_WEAPON); + pPlayer->ModifyMoney(-DoLowUnlearnCost(pPlayer)); + pCreature->CastSpell(pPlayer, S_REP_ARMOR, true); + pPlayer->CLOSE_GOSSIP_MENU(); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } + else + { + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + } + break; + case GOSSIP_ACTION_INFO_DEF + 4: + if (EquippedOk(pPlayer,S_UNLEARN_ARMOR)) + { + if (pPlayer->GetMoney() >= DoLowUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_ARMOR, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_ARMOR); + pPlayer->ModifyMoney(-DoLowUnlearnCost(pPlayer)); + pCreature->CastSpell(pPlayer, S_REP_WEAPON, true); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + //Learn Hammer/Axe/Sword + case GOSSIP_ACTION_INFO_DEF + 5: + pPlayer->CastSpell(pPlayer, S_LEARN_HAMMER, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + pPlayer->CastSpell(pPlayer, S_LEARN_AXE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 7: + pPlayer->CastSpell(pPlayer, S_LEARN_SWORD, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + //Unlearn Hammer/Axe/Sword + case GOSSIP_ACTION_INFO_DEF + 8: + if (EquippedOk(pPlayer,S_UNLEARN_HAMMER)) + { + if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_HAMMER, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_HAMMER); + pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 9: + if (EquippedOk(pPlayer,S_UNLEARN_AXE)) + { + if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_AXE, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_AXE); + pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 10: + if (EquippedOk(pPlayer,S_UNLEARN_SWORD)) + { + if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_SWORD, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_SWORD); + pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } +} + +void SendConfirmLearn_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction) + { + uint32 eCreature = pCreature->GetEntry(); + switch(eCreature) + { + case 11191: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_HAMMER, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID (TALK_HAMMER_LEARN) + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 11192: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_AXE, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID (TALK_AXE_LEARN) + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 11193: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SWORD, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID (TALK_SWORD_LEARN) + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + } + } +} + +void SendConfirmUnlearn_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction) + { + uint32 eCreature = pCreature->GetEntry(); + switch(eCreature) + { + case 11146: //Ironus Coldsteel + case 11178: //Borgosh Corebender + case 5164: //Grumnus Steelshaper + case 11177: //Okothos Ironrager + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SMITH_SPEC, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_ARMORORWEAPON, DoLowUnlearnCost(pPlayer),false); + //unknown textID (TALK_UNLEARN_AXEORWEAPON) + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + + case 11191: + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_HAMMER, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(pPlayer),false); + //unknown textID (TALK_HAMMER_UNLEARN) + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 11192: + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_AXE, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(pPlayer),false); + //unknown textID (TALK_AXE_UNLEARN) + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 11193: + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SWORD, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(pPlayer),false); + //unknown textID (TALK_SWORD_UNLEARN) + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + } + } +} + +bool GossipSelect_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiSender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_blacksmith(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_blacksmith(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_blacksmith(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_blacksmith(pPlayer, pCreature, uiAction); break; + } + return true; +} + +/*bool QuestComplete_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, Quest const *_Quest) +{ + if ((_Quest->GetQuestId() == 5283) || (_Quest->GetQuestId() == 5301)) //armorsmith + pCreature->CastSpell(pPlayer, 17451, true); + + if ((_Quest->GetQuestId() == 5284) || (_Quest->GetQuestId() == 5302)) //weaponsmith + pCreature->CastSpell(pPlayer, 17452, true); + + return true; +}*/ + +/*### +# engineering trinkets +###*/ + +enum eEngineeringTrinkets +{ + NPC_ZAP = 14742, + NPC_JHORDY = 14743, + NPC_KABLAM = 21493, + NPC_SMILES = 21494, + + SPELL_LEARN_TO_EVERLOOK = 23490, + SPELL_LEARN_TO_GADGET = 23491, + SPELL_LEARN_TO_AREA52 = 36956, + SPELL_LEARN_TO_TOSHLEY = 36957, + + SPELL_TO_EVERLOOK = 23486, + SPELL_TO_GADGET = 23489, + SPELL_TO_AREA52 = 36954, + SPELL_TO_TOSHLEY = 36955, + + ITEM_GNOMISH_CARD = 10790, + ITEM_GOBLIN_CARD = 10791 +}; + +#define GOSSIP_ITEM_ZAP "[PH] Unknown" +#define GOSSIP_ITEM_JHORDY "I must build a beacon for this marvelous device!" +#define GOSSIP_ITEM_KABLAM "[PH] Unknown" +#define GOSSIP_ITEM_SMILES "[PH] Unknown" + +bool GossipHello_npc_engineering_tele_trinket(Player* pPlayer, Creature* pCreature) +{ + uint32 NpcTextId = 0; + std::string GossipItem; + bool CanLearn = false; + + if (pPlayer->HasSkill(SKILL_ENGINERING)) + { + switch(pCreature->GetEntry()) + { + case NPC_ZAP: + NpcTextId = 7249; + if (pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 260 && pPlayer->HasSpell(S_GOBLIN)) + { + if (!pPlayer->HasSpell(SPELL_TO_EVERLOOK)) + { + CanLearn = true; + GossipItem = GOSSIP_ITEM_ZAP; + } + else if (pPlayer->HasSpell(SPELL_TO_EVERLOOK)) + NpcTextId = 0; + } + break; + case NPC_JHORDY: + NpcTextId = 7251; + if (pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 260 && pPlayer->HasSpell(S_GNOMISH)) + { + if (!pPlayer->HasSpell(SPELL_TO_GADGET)) + { + CanLearn = true; + GossipItem = GOSSIP_ITEM_JHORDY; + } + else if (pPlayer->HasSpell(SPELL_TO_GADGET)) + NpcTextId = 7252; + } + break; + case NPC_KABLAM: + NpcTextId = 10365; + if (pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 350 && pPlayer->HasSpell(S_GOBLIN)) + { + if (!pPlayer->HasSpell(SPELL_TO_AREA52)) + { + CanLearn = true; + GossipItem = GOSSIP_ITEM_KABLAM; + } + else if (pPlayer->HasSpell(SPELL_TO_AREA52)) + NpcTextId = 0; + } + break; + case NPC_SMILES: + NpcTextId = 10363; + if (pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 350 && pPlayer->HasSpell(S_GNOMISH)) + { + if (!pPlayer->HasSpell(SPELL_TO_TOSHLEY)) + { + CanLearn = true; + GossipItem = GOSSIP_ITEM_SMILES; + } + else if (pPlayer->HasSpell(SPELL_TO_TOSHLEY)) + NpcTextId = 0; + } + break; + } + } + + if (CanLearn) + { + if (pPlayer->HasItemCount(ITEM_GOBLIN_CARD,1) || pPlayer->HasItemCount(ITEM_GNOMISH_CARD,1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GossipItem, pCreature->GetEntry(), GOSSIP_ACTION_INFO_DEF+1); + } + + pPlayer->SEND_GOSSIP_MENU(NpcTextId ? NpcTextId : pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_engineering_tele_trinket(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + pPlayer->CLOSE_GOSSIP_MENU(); + + if (uiSender != pCreature->GetEntry()) + return true; + + switch(uiSender) + { + case NPC_ZAP: + pPlayer->CastSpell(pPlayer, SPELL_LEARN_TO_EVERLOOK, false); + break; + case NPC_JHORDY: + pPlayer->CastSpell(pPlayer, SPELL_LEARN_TO_GADGET, false); + break; + case NPC_KABLAM: + pPlayer->CastSpell(pPlayer, SPELL_LEARN_TO_AREA52, false); + break; + case NPC_SMILES: + pPlayer->CastSpell(pPlayer, SPELL_LEARN_TO_TOSHLEY, false); + break; + } + + return true; +} + +/*### +# start menues leatherworking +###*/ + +bool GossipHello_npc_prof_leather(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + if (pCreature->isTrainer()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + uint32 eCreature = pCreature->GetEntry(); + + if (pPlayer->HasSkill(SKILL_LEATHERWORKING) && pPlayer->GetBaseSkillValue(SKILL_LEATHERWORKING) >= 250 && pPlayer->getLevel() > 49) + { + switch (eCreature) + { + case 7866: //Peter Galen + case 7867: //Thorkaf Dragoneye + if (pPlayer->HasSpell(S_DRAGON)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_DRAGON, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 1); + break; + case 7868: //Sarah Tanner + case 7869: //Brumn Winterhoof + if (pPlayer->HasSpell(S_ELEMENTAL)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_ELEMENTAL, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 2); + break; + case 7870: //Caryssia Moonhunter + case 7871: //Se'Jib + if (pPlayer->HasSpell(S_TRIBAL)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_TRIBAL, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 3); + break; + } + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +void SendActionMenu_npc_prof_leather(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + case GOSSIP_ACTION_TRAIN: + pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); + break; + //Unlearn Leather + case GOSSIP_ACTION_INFO_DEF + 1: + if (EquippedOk(pPlayer,S_UNLEARN_DRAGON)) + { + if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_DRAGON, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_DRAGON); + pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if (EquippedOk(pPlayer,S_UNLEARN_ELEMENTAL)) + { + if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_ELEMENTAL, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_ELEMENTAL); + pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + if (EquippedOk(pPlayer,S_UNLEARN_TRIBAL)) + { + if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_TRIBAL, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_TRIBAL); + pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } +} + +void SendConfirmUnlearn_npc_prof_leather(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction) + { + uint32 eCreature = pCreature->GetEntry(); + switch(eCreature) + { + case 7866: //Peter Galen + case 7867: //Thorkaf Dragoneye + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_DRAGON, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 7868: //Sarah Tanner + case 7869: //Brumn Winterhoof + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_ELEMENTAL, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 7870: //Caryssia Moonhunter + case 7871: //Se'Jib + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_TRIBAL, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + } + } +} + +bool GossipSelect_npc_prof_leather(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiSender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_leather(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_leather(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_leather(pPlayer, pCreature, uiAction); break; + } + return true; +} + +/*### +# start menues tailoring +###*/ + +bool HasTailorSpell(Player* pPlayer) +{ + if (pPlayer->HasSpell(S_MOONCLOTH) || pPlayer->HasSpell(S_SHADOWEAVE) || pPlayer->HasSpell(S_SPELLFIRE)) + return true; + return false; +} + +bool GossipHello_npc_prof_tailor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + if (pCreature->isTrainer()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + uint32 eCreature = pCreature->GetEntry(); + //TAILORING SPEC + if (pPlayer->HasSkill(SKILL_TAILORING) && pPlayer->GetBaseSkillValue(SKILL_TAILORING) >= 350 && pPlayer->getLevel() > 59) + { + if (pPlayer->GetQuestRewardStatus(10831) || pPlayer->GetQuestRewardStatus(10832) || pPlayer->GetQuestRewardStatus(10833)) + { + switch (eCreature) + { + case 22213: //Gidge Spellweaver + if (!HasTailorSpell(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SPELLFIRE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1); + if (pPlayer->HasSpell(S_SPELLFIRE)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_SPELLFIRE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); + break; + case 22208: //Nasmara Moonsong + if (!HasTailorSpell(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_MOONCLOTH, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2); + if (pPlayer->HasSpell(S_MOONCLOTH)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_MOONCLOTH, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5); + break; + case 22212: //Andrion Darkspinner + if (!HasTailorSpell(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SHADOWEAVE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3); + if (pPlayer->HasSpell(S_SHADOWEAVE)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_SHADOWEAVE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 6); + break; + } + } + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +void SendActionMenu_npc_prof_tailor(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + case GOSSIP_ACTION_TRAIN: + pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); + break; + //Learn Tailor + case GOSSIP_ACTION_INFO_DEF + 1: + if (!pPlayer->HasSpell(S_SPELLFIRE) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_LEARN_SPELLFIRE, true); + pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if (!pPlayer->HasSpell(S_MOONCLOTH) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_LEARN_MOONCLOTH, true); + pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + if (!pPlayer->HasSpell(S_SHADOWEAVE) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_LEARN_SHADOWEAVE, true); + pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + //Unlearn Tailor + case GOSSIP_ACTION_INFO_DEF + 4: + if (EquippedOk(pPlayer,S_UNLEARN_SPELLFIRE)) + { + if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_SPELLFIRE, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_SPELLFIRE); + pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 5: + if (EquippedOk(pPlayer,S_UNLEARN_MOONCLOTH)) + { + if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_MOONCLOTH, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_MOONCLOTH); + pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + case GOSSIP_ACTION_INFO_DEF + 6: + if (EquippedOk(pPlayer,S_UNLEARN_SHADOWEAVE)) + { + if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) + { + pPlayer->CastSpell(pPlayer, S_UNLEARN_SHADOWEAVE, true); + ProfessionUnlearnSpells(pPlayer, S_UNLEARN_SHADOWEAVE); + pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); + } else + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); + } else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } +} + +void SendConfirmLearn_npc_prof_tailor(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction) + { + uint32 eCreature = pCreature->GetEntry(); + switch(eCreature) + { + case 22213: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SPELLFIRE, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 22208: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_MOONCLOTH, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 22212: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SHADOWEAVE, GOSSIP_SENDER_CHECK, uiAction); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + } + } +} + +void SendConfirmUnlearn_npc_prof_tailor(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction) + { + uint32 eCreature = pCreature->GetEntry(); + switch(eCreature) + { + case 22213: //Gidge Spellweaver + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SPELLFIRE, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 22208: //Nasmara Moonsong + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_MOONCLOTH, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case 22212: //Andrion Darkspinner + pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SHADOWEAVE, GOSSIP_SENDER_CHECK, uiAction,BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(pPlayer),false); + //unknown textID () + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + } + } +} + +bool GossipSelect_npc_prof_tailor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiSender) + { + case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_tailor(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_tailor(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_tailor(pPlayer, pCreature, uiAction); break; + case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_tailor(pPlayer, pCreature, uiAction); break; + } + return true; +} + +/*### +# start menues for GO (engineering and leatherworking) +###*/ + +/*bool GOHello_go_soothsaying_for_dummies(Player* pPlayer, GameObject* pGo) +{ + pPlayer->PlayerTalkClass->GetGossipMenu()->AddMenuItem(0,GOSSIP_LEARN_DRAGON, GOSSIP_SENDER_INFO, GOSSIP_ACTION_INFO_DEF, "", 0); + + pPlayer->SEND_GOSSIP_MENU(5584, pGo->GetGUID()); + + return true; +}*/ + +/*### +# +###*/ + +void AddSC_npc_professions() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_prof_alchemy"; + newscript->pGossipHello = &GossipHello_npc_prof_alchemy; + newscript->pGossipSelect = &GossipSelect_npc_prof_alchemy; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_prof_blacksmith"; + newscript->pGossipHello = &GossipHello_npc_prof_blacksmith; + newscript->pGossipSelect = &GossipSelect_npc_prof_blacksmith; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_engineering_tele_trinket"; + newscript->pGossipHello = &GossipHello_npc_engineering_tele_trinket; + newscript->pGossipSelect = &GossipSelect_npc_engineering_tele_trinket; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_prof_leather"; + newscript->pGossipHello = &GossipHello_npc_prof_leather; + newscript->pGossipSelect = &GossipSelect_npc_prof_leather; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_prof_tailor"; + newscript->pGossipHello = &GossipHello_npc_prof_tailor; + newscript->pGossipSelect = &GossipSelect_npc_prof_tailor; + newscript->RegisterSelf(); + + /*newscript = new Script; + newscript->Name = "go_soothsaying_for_dummies"; + newscript->pGOHello = &GOHello_go_soothsaying_for_dummies; + //newscript->pGossipSelect = &GossipSelect_go_soothsaying_for_dummies; + newscript->RegisterSelf();*/ +} + diff --git a/src/server/scripts/World/npc_taxi.cpp b/src/server/scripts/World/npc_taxi.cpp new file mode 100644 index 00000000000..2a8efd4e0cb --- /dev/null +++ b/src/server/scripts/World/npc_taxi.cpp @@ -0,0 +1,326 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Npc_Taxi +SD%Complete: 0% +SDComment: To be used for taxi NPCs that are located globally. +SDCategory: NPCs +EndScriptData +*/ + +#include "ScriptedPch.h" + +#define GOSSIP_SUSURRUS "I am ready." +#define GOSSIP_NETHER_DRAKE "I'm ready to fly! Take me up, dragon!" +#define GOSSIP_BRAZEN "I am ready to go to Durnholde Keep." +#define GOSSIP_IRONWING "I'd like to take a flight around Stormwind Harbor." +#define GOSSIP_DABIREE1 "Fly me to Murketh and Shaadraz Gateways" +#define GOSSIP_DABIREE2 "Fly me to Shatter Point" +#define GOSSIP_WINDBELLOW1 "Fly me to The Abyssal Shelf" +#define GOSSIP_WINDBELLOW2 "Fly me to Honor Point" +#define GOSSIP_BRACK1 "Fly me to Murketh and Shaadraz Gateways" +#define GOSSIP_BRACK2 "Fly me to The Abyssal Shelf" +#define GOSSIP_BRACK3 "Fly me to Spinebreaker Post" +#define GOSSIP_IRENA "Fly me to Skettis please" +#define GOSSIP_CLOUDBREAKER1 "Speaking of uiAction, I've been ordered to undertake an air strike." +#define GOSSIP_CLOUDBREAKER2 "I need to intercept the Dawnblade reinforcements." +#define GOSSIP_DRAGONHAWK "" +#define GOSSIP_VERONIA "Fly me to Manaforge Coruu please" +#define GOSSIP_DEESAK "Fly me to Ogri'la please" +#define GOSSIP_AFRASASTRASZ1 "I would like to take a flight to the ground, Lord Of Afrasastrasz." +#define GOSSIP_AFRASASTRASZ2 "My Lord, I must go to the upper floor of the temple." +#define GOSSIP_TARIOLSTRASZ1 "My Lord, I must go to the upper floor of the temple." +#define GOSSIP_TARIOLSTRASZ2 "Can you spare a drake to travel to Lord Of Afrasastrasz, in the middle of the temple?" +#define GOSSIP_TORASTRASZA1 "I would like to see Lord Of Afrasastrasz, in the middle of the temple." +#define GOSSIP_TORASTRASZA2 "Yes, Please. I would like to return to the ground floor of the temple." +#define GOSSIP_CAMILLE1 "I need to fly to the Windrunner Official business!" +#define GOSSIP_CAMILLE2 "" +#define GOSSIP_CRIMSONWING "" +#define GOSSIP_THRICESTAR1 "Do you think I could take a ride on one of those flying machines?" +#define GOSSIP_THRICESTAR2 "Kara, I need to be flown out the Dens of Dying to find Bixie." +#define GOSSIP_WILLIAMKEILAR1 "Take me to Northpass Tower." +#define GOSSIP_WILLIAMKEILAR2 "Take me to Eastwall Tower." +#define GOSSIP_WILLIAMKEILAR3 "Take me to Crown Guard Tower." + +bool GossipHello_npc_taxi(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + switch(pCreature->GetEntry()) { + case 17435: // Azuremyst Isle - Susurrus + if (pPlayer->HasItemCount(23843,1,true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SUSURRUS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + break; + case 20903: // Netherstorm - Protectorate Nether Drake + if (pPlayer->GetQuestStatus(10438) == QUEST_STATUS_INCOMPLETE && pPlayer->HasItemCount(29778,1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_NETHER_DRAKE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + break; + case 18725: // Old Hillsbrad Foothills - Brazen + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRAZEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + break; + case 29154: // Stormwind City - Thargold Ironwing + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_IRONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + break; + case 19409: // Hellfire Peninsula - Wing Commander Dabir'ee + //Mission: The Murketh and Shaadraz Gateways + if (pPlayer->GetQuestStatus(10146) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DABIREE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + + //Shatter Point + if (!pPlayer->GetQuestRewardStatus(10340)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DABIREE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + break; + case 20235: // Hellfire Peninsula - Gryphoneer Windbellow + //Mission: The Abyssal Shelf || Return to the Abyssal Shelf + if (pPlayer->GetQuestStatus(10163) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10346) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WINDBELLOW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + + //Go to the Front + if (pPlayer->GetQuestStatus(10382) != QUEST_STATUS_NONE && !pPlayer->GetQuestRewardStatus(10382)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WINDBELLOW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + break; + case 19401: // Hellfire Peninsula - Wing Commander Brack + //Mission: The Murketh and Shaadraz Gateways + if (pPlayer->GetQuestStatus(10129) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + + //Mission: The Abyssal Shelf || Return to the Abyssal Shelf + if (pPlayer->GetQuestStatus(10162) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10347) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + + //Spinebreaker Post + if (pPlayer->GetQuestStatus(10242) == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(10242)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + break; + case 23413: // Blade's Edge Mountains - Skyguard Handler Irena + if (pPlayer->GetReputationRank(1031) >= REP_HONORED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_IRENA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + break; + case 25059: // Isle of Quel'Danas - Ayren Cloudbreaker + if (pPlayer->GetQuestStatus(11532) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(11533) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + + if (pPlayer->GetQuestStatus(11542) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(11543) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + break; + case 25236: // Isle of Quel'Danas - Unrestrained Dragonhawk + if (pPlayer->GetQuestStatus(11542) == QUEST_STATUS_COMPLETE || pPlayer->GetQuestStatus(11543) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DRAGONHAWK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); + break; + case 20162: // Netherstorm - Veronia + //Behind Enemy Lines + if (pPlayer->GetQuestStatus(10652) && !pPlayer->GetQuestRewardStatus(10652)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VERONIA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15); + break; + case 23415: // Terokkar Forest - Skyguard Handler Deesak + if (pPlayer->GetReputationRank(1031) >= REP_HONORED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEESAK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 16); + break; + case 27575: // Dragonblight - Lord Afrasastrasz + // middle -> ground + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AFRASASTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 17); + // middle -> top + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AFRASASTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 18); + break; + case 26443: // Dragonblight - Tariolstrasz //need to check if quests are required before gossip available (12123, 12124) + // ground -> top + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TARIOLSTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 19); + // ground -> middle + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TARIOLSTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 20); + break; + case 26949: // Dragonblight - Torastrasza + // top -> middle + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); + // top -> ground + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); + break; + case 23816: // Howling Fjord - Bat Handler Camille + if (!pPlayer->GetQuestRewardStatus(11229)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CAMILLE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23); + if (pPlayer->GetQuestStatus(11170) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CAMILLE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24); + break; + case 23704: // Dustwallow Marsh - Cassa Crimsonwing + if (pPlayer->GetQuestStatus(11142) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CRIMSONWING,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+25); + break; + case 26602: + if (pCreature->isTaxi()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TAXI, GOSSIP_THRICESTAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26); + if (pPlayer->GetQuestStatus(11692) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_THRICESTAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 27); + break; + case 17209: + pPlayer->SetTaxiCheater(true); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 28); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 29); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 30); + break; + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_taxi(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) { + case GOSSIP_ACTION_INFO_DEF: + //spellId is correct, however it gives flight a somewhat funny effect //TaxiPath 506. + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,32474,true); + break; + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(627); //TaxiPath 627 (possibly 627+628(152->153->154->155)) + break; + case GOSSIP_ACTION_INFO_DEF + 2: + if (!pPlayer->HasItemCount(25853,1)) { + pPlayer->SEND_GOSSIP_MENU(9780, pCreature->GetGUID()); + } else { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(534); //TaxiPath 534 + } + break; + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,53335,true); //TaxiPath 1041 (Stormwind Harbor) + break; + case GOSSIP_ACTION_INFO_DEF + 4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,33768,true); //TaxiPath 585 (Gateways Murket and Shaadraz) + break; + case GOSSIP_ACTION_INFO_DEF + 5: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,35069,true); //TaxiPath 612 (Taxi - Hellfire Peninsula - Expedition Point to Shatter Point) + break; + case GOSSIP_ACTION_INFO_DEF + 6: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,33899,true); //TaxiPath 589 (Aerial Assault Flight (Alliance)) + break; + case GOSSIP_ACTION_INFO_DEF + 7: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,35065,true); //TaxiPath 607 (Taxi - Hellfire Peninsula - Shatter Point to Beach Head) + break; + case GOSSIP_ACTION_INFO_DEF + 8: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,33659,true); //TaxiPath 584 (Gateways Murket and Shaadraz) + break; + case GOSSIP_ACTION_INFO_DEF + 9: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,33825,true); //TaxiPath 587 (Aerial Assault Flight (Horde)) + break; + case GOSSIP_ACTION_INFO_DEF + 10: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,34578,true); //TaxiPath 604 (Taxi - Reaver's Fall to Spinebreaker Ridge) + break; + case GOSSIP_ACTION_INFO_DEF + 11: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,41278,true); //TaxiPath 706 + break; + case GOSSIP_ACTION_INFO_DEF + 12: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,45071,true); //TaxiPath 779 + break; + case GOSSIP_ACTION_INFO_DEF + 13: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,45113,true); //TaxiPath 784 + break; + case GOSSIP_ACTION_INFO_DEF + 14: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,45353,true); //TaxiPath 788 + break; + case GOSSIP_ACTION_INFO_DEF + 15: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,34905,true); //TaxiPath 606 + break; + case GOSSIP_ACTION_INFO_DEF + 16: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,41279,true); //TaxiPath 705 (Taxi - Skettis to Skyguard Outpost) + break; + case GOSSIP_ACTION_INFO_DEF + 17: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(882); + break; + case GOSSIP_ACTION_INFO_DEF + 18: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(881); + break; + case GOSSIP_ACTION_INFO_DEF + 19: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(878); + break; + case GOSSIP_ACTION_INFO_DEF + 20: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(883); + break; + case GOSSIP_ACTION_INFO_DEF + 21: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(880); + break; + case GOSSIP_ACTION_INFO_DEF + 22: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(879); + break; + case GOSSIP_ACTION_INFO_DEF + 23: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,43074,true); //TaxiPath 736 + break; + case GOSSIP_ACTION_INFO_DEF + 24: + pPlayer->CLOSE_GOSSIP_MENU(); + //pPlayer->ActivateTaxiPathTo(738); + pPlayer->CastSpell(pPlayer, 43136, false); + break; + case GOSSIP_ACTION_INFO_DEF + 25: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,42295,true); + break; + case GOSSIP_ACTION_INFO_DEF + 26: + pPlayer->GetSession()->SendTaxiMenu(pCreature); + break; + case GOSSIP_ACTION_INFO_DEF + 27: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, 51446, false); + break; + case GOSSIP_ACTION_INFO_DEF + 28: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(494); + break; + case GOSSIP_ACTION_INFO_DEF + 29: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(495); + break; + case GOSSIP_ACTION_INFO_DEF + 30: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(496); + break; + } + + return true; +} + +void AddSC_npc_taxi() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_taxi"; + newscript->pGossipHello = &GossipHello_npc_taxi; + newscript->pGossipSelect = &GossipSelect_npc_taxi; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp new file mode 100644 index 00000000000..cfd1b7698fc --- /dev/null +++ b/src/server/scripts/World/npcs_special.cpp @@ -0,0 +1,2600 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Npcs_Special +SD%Complete: 100 +SDComment: To be used for special NPCs that are located globally. +SDCategory: NPCs +EndScriptData +*/ + +/* ContentData +npc_air_force_bots 80% support for misc (invisible) guard bots in areas where player allowed to fly. Summon guards after a preset time if tagged by spell +npc_lunaclaw_spirit 80% support for quests 6001/6002 (Body and Heart) +npc_chicken_cluck 100% support for quest 3861 (Cluck!) +npc_dancing_flames 100% midsummer event NPC +npc_guardian 100% guardianAI used to prevent players from accessing off-limits areas. Not in use by SD2 +npc_garments_of_quests 80% NPC's related to all Garments of-quests 5621, 5624, 5625, 5648, 565 +npc_injured_patient 100% patients for triage-quests (6622 and 6624) +npc_doctor 100% Gustaf Vanhowzen and Gregory Victor, quest 6622 and 6624 (Triage) +npc_kingdom_of_dalaran_quests Misc NPC's gossip option related to quests 12791, 12794 and 12796 +npc_mount_vendor 100% Regular mount vendors all over the world. Display gossip if player doesn't meet the requirements to buy +npc_rogue_trainer 80% Scripted trainers, so they are able to offer item 17126 for class quest 6681 +npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given +npc_snake_trap_serpents 80% AI for snakes that summoned by Snake Trap +npc_shadowfiend 100% restore 5% of owner's mana when shadowfiend die from damage +npc_locksmith 75% list of keys needs to be confirmed +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "ObjectMgr.h" +#include "ScriptMgr.h" +#include "World.h" + +/*######## +# npc_air_force_bots +#########*/ + +enum SpawnType +{ + SPAWNTYPE_TRIPWIRE_ROOFTOP, // no warning, summon Creature at smaller range + SPAWNTYPE_ALARMBOT, // cast guards mark and summon npc - if player shows up with that buff duration < 5 seconds attack +}; + +struct SpawnAssociation +{ + uint32 m_uiThisCreatureEntry; + uint32 m_uiSpawnedCreatureEntry; + SpawnType m_SpawnType; +}; + +enum eEnums +{ + SPELL_GUARDS_MARK = 38067, + AURA_DURATION_TIME_LEFT = 5000 +}; + +const float RANGE_TRIPWIRE = 15.0f; +const float RANGE_GUARDS_MARK = 50.0f; + +SpawnAssociation m_aSpawnAssociations[] = +{ + {2614, 15241, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Alliance) + {2615, 15242, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Horde) + {21974, 21976, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Area 52) + {21993, 15242, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Horde - Bat Rider) + {21996, 15241, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Alliance - Gryphon) + {21997, 21976, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Goblin - Area 52 - Zeppelin) + {21999, 15241, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Alliance) + {22001, 15242, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Horde) + {22002, 15242, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Ground (Horde) + {22003, 15241, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Ground (Alliance) + {22063, 21976, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Goblin - Area 52) + {22065, 22064, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Ethereal - Stormspire) + {22066, 22067, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Scryer - Dragonhawk) + {22068, 22064, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Ethereal - Stormspire) + {22069, 22064, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Stormspire) + {22070, 22067, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Scryer) + {22071, 22067, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Scryer) + {22078, 22077, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Aldor) + {22079, 22077, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Aldor - Gryphon) + {22080, 22077, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Aldor) + {22086, 22085, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Sporeggar) + {22087, 22085, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Sporeggar - Spore Bat) + {22088, 22085, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Sporeggar) + {22090, 22089, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Toshley's Station - Flying Machine) + {22124, 22122, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Cenarion) + {22125, 22122, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Cenarion - Stormcrow) + {22126, 22122, SPAWNTYPE_ALARMBOT} //Air Force Trip Wire - Rooftop (Cenarion Expedition) +}; + +struct npc_air_force_botsAI : public ScriptedAI +{ + npc_air_force_botsAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pSpawnAssoc = NULL; + m_uiSpawnedGUID = 0; + + // find the correct spawnhandling + static uint32 uiEntryCount = sizeof(m_aSpawnAssociations)/sizeof(SpawnAssociation); + + for (uint8 i=0; iGetEntry()) + { + m_pSpawnAssoc = &m_aSpawnAssociations[i]; + break; + } + } + + if (!m_pSpawnAssoc) + error_db_log("TCSR: Creature template entry %u has ScriptName npc_air_force_bots, but it's not handled by that script", pCreature->GetEntry()); + else + { + CreatureInfo const* spawnedTemplate = GetCreatureTemplateStore(m_pSpawnAssoc->m_uiSpawnedCreatureEntry); + + if (!spawnedTemplate) + { + m_pSpawnAssoc = NULL; + error_db_log("TCSR: Creature template entry %u does not exist in DB, which is required by npc_air_force_bots", m_pSpawnAssoc->m_uiSpawnedCreatureEntry); + return; + } + } + } + + SpawnAssociation* m_pSpawnAssoc; + uint64 m_uiSpawnedGUID; + + void Reset() {} + + Creature* SummonGuard() + { + Creature* pSummoned = me->SummonCreature(m_pSpawnAssoc->m_uiSpawnedCreatureEntry, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000); + + if (pSummoned) + m_uiSpawnedGUID = pSummoned->GetGUID(); + else + { + error_db_log("TCSR: npc_air_force_bots: wasn't able to spawn Creature %u", m_pSpawnAssoc->m_uiSpawnedCreatureEntry); + m_pSpawnAssoc = NULL; + } + + return pSummoned; + } + + Creature* GetSummonedGuard() + { + Creature* pCreature = Unit::GetCreature(*me, m_uiSpawnedGUID); + + if (pCreature && pCreature->isAlive()) + return pCreature; + + return NULL; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_pSpawnAssoc) + return; + + if (pWho->isTargetableForAttack() && me->IsHostileTo(pWho)) + { + Player* pPlayerTarget = pWho->GetTypeId() == TYPEID_PLAYER ? CAST_PLR(pWho) : NULL; + + // airforce guards only spawn for players + if (!pPlayerTarget) + return; + + Creature* pLastSpawnedGuard = m_uiSpawnedGUID == 0 ? NULL : GetSummonedGuard(); + + // prevent calling Unit::GetUnit at next MoveInLineOfSight call - speedup + if (!pLastSpawnedGuard) + m_uiSpawnedGUID = 0; + + switch(m_pSpawnAssoc->m_SpawnType) + { + case SPAWNTYPE_ALARMBOT: + { + if (!pWho->IsWithinDistInMap(me, RANGE_GUARDS_MARK)) + return; + + Aura* pMarkAura = pWho->GetAura(SPELL_GUARDS_MARK); + if (pMarkAura) + { + // the target wasn't able to move out of our range within 25 seconds + if (!pLastSpawnedGuard) + { + pLastSpawnedGuard = SummonGuard(); + + if (!pLastSpawnedGuard) + return; + } + + if (pMarkAura->GetDuration() < AURA_DURATION_TIME_LEFT) + { + if (!pLastSpawnedGuard->getVictim()) + pLastSpawnedGuard->AI()->AttackStart(pWho); + } + } + else + { + if (!pLastSpawnedGuard) + pLastSpawnedGuard = SummonGuard(); + + if (!pLastSpawnedGuard) + return; + + pLastSpawnedGuard->CastSpell(pWho, SPELL_GUARDS_MARK, true); + } + break; + } + case SPAWNTYPE_TRIPWIRE_ROOFTOP: + { + if (!pWho->IsWithinDistInMap(me, RANGE_TRIPWIRE)) + return; + + if (!pLastSpawnedGuard) + pLastSpawnedGuard = SummonGuard(); + + if (!pLastSpawnedGuard) + return; + + // ROOFTOP only triggers if the player is on the ground + if (!pPlayerTarget->IsFlying()) + { + if (!pLastSpawnedGuard->getVictim()) + pLastSpawnedGuard->AI()->AttackStart(pWho); + } + break; + } + } + } + } +}; + +CreatureAI* GetAI_npc_air_force_bots(Creature* pCreature) +{ + return new npc_air_force_botsAI(pCreature); +} + +/*###### +## npc_lunaclaw_spirit +######*/ + +enum +{ + QUEST_BODY_HEART_A = 6001, + QUEST_BODY_HEART_H = 6002, + + TEXT_ID_DEFAULT = 4714, + TEXT_ID_PROGRESS = 4715 +}; + +#define GOSSIP_ITEM_GRANT "You have thought well, spirit. I ask you to grant me the strength of your body and the strength of your heart." + +bool GossipHello_npc_lunaclaw_spirit(Player *pPlayer, Creature *pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_BODY_HEART_A) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_BODY_HEART_H) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GRANT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(TEXT_ID_DEFAULT, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_lunaclaw_spirit(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->SEND_GOSSIP_MENU(TEXT_ID_PROGRESS, pCreature->GetGUID()); + pPlayer->AreaExploredOrEventHappens(pPlayer->GetTeam() == ALLIANCE ? QUEST_BODY_HEART_A : QUEST_BODY_HEART_H); + } + return true; +} + +/*######## +# npc_chicken_cluck +#########*/ + +#define EMOTE_HELLO -1070004 +#define EMOTE_CLUCK_TEXT -1070006 + +#define QUEST_CLUCK 3861 +#define FACTION_FRIENDLY 35 +#define FACTION_CHICKEN 31 + +struct npc_chicken_cluckAI : public ScriptedAI +{ + npc_chicken_cluckAI(Creature *c) : ScriptedAI(c) {} + + uint32 ResetFlagTimer; + + void Reset() + { + ResetFlagTimer = 120000; + me->setFaction(FACTION_CHICKEN); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + // Reset flags after a certain time has passed so that the next player has to start the 'event' again + if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) + { + if (ResetFlagTimer <= diff) + { + EnterEvadeMode(); + return; + } else ResetFlagTimer -= diff; + } + + if (UpdateVictim()) + DoMeleeAttackIfReady(); + } + + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + switch(emote) + { + case TEXTEMOTE_CHICKEN: + if (pPlayer->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE && rand()%30 == 1) + { + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + me->setFaction(FACTION_FRIENDLY); + DoScriptText(EMOTE_HELLO, me); + } + break; + case TEXTEMOTE_CHEER: + if (pPlayer->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_COMPLETE) + { + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + me->setFaction(FACTION_FRIENDLY); + DoScriptText(EMOTE_CLUCK_TEXT, me); + } + break; + } + } +}; + +CreatureAI* GetAI_npc_chicken_cluck(Creature* pCreature) +{ + return new npc_chicken_cluckAI(pCreature); +} + +bool QuestAccept_npc_chicken_cluck(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest) +{ + if (_Quest->GetQuestId() == QUEST_CLUCK) + CAST_AI(npc_chicken_cluckAI, pCreature->AI())->Reset(); + + return true; +} + +bool QuestComplete_npc_chicken_cluck(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest) +{ + if (_Quest->GetQuestId() == QUEST_CLUCK) + CAST_AI(npc_chicken_cluckAI, pCreature->AI())->Reset(); + + return true; +} + +/*###### +## npc_dancing_flames +######*/ + +#define SPELL_BRAZIER 45423 +#define SPELL_SEDUCTION 47057 +#define SPELL_FIERY_AURA 45427 + +struct npc_dancing_flamesAI : public ScriptedAI +{ + npc_dancing_flamesAI(Creature *c) : ScriptedAI(c) {} + + bool active; + uint32 can_iteract; + + void Reset() + { + active = true; + can_iteract = 3500; + DoCast(me, SPELL_BRAZIER, true); + DoCast(me, SPELL_FIERY_AURA, false); + float x, y, z; + me->GetPosition(x,y,z); + me->Relocate(x,y,z + 0.94f); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE); + WorldPacket data; //send update position to client + me->BuildHeartBeatMsg(&data); + me->SendMessageToSet(&data,true); + } + + void UpdateAI(const uint32 diff) + { + if (!active) + { + if (can_iteract <= diff){ + active = true; + can_iteract = 3500; + me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE); + } else can_iteract -= diff; + } + } + + void EnterCombat(Unit* /*who*/){} + + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + if (me->IsWithinLOS(pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ()) && me->IsWithinDistInMap(pPlayer,30.0f)) + { + me->SetInFront(pPlayer); + active = false; + + WorldPacket data; + me->BuildHeartBeatMsg(&data); + me->SendMessageToSet(&data,true); + switch(emote) + { + case TEXTEMOTE_KISS: me->HandleEmoteCommand(EMOTE_ONESHOT_SHY); break; + case TEXTEMOTE_WAVE: me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); break; + case TEXTEMOTE_BOW: me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); break; + case TEXTEMOTE_JOKE: me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); break; + case TEXTEMOTE_DANCE: + { + if (!pPlayer->HasAura(SPELL_SEDUCTION)) + DoCast(pPlayer, SPELL_SEDUCTION, true); + } + break; + } + } + } +}; + +CreatureAI* GetAI_npc_dancing_flames(Creature* pCreature) +{ + return new npc_dancing_flamesAI(pCreature); +} + +/*###### +## Triage quest +######*/ + +//signed for 9623 +#define SAY_DOC1 -1000201 +#define SAY_DOC2 -1000202 +#define SAY_DOC3 -1000203 + +#define DOCTOR_ALLIANCE 12939 +#define DOCTOR_HORDE 12920 +#define ALLIANCE_COORDS 7 +#define HORDE_COORDS 6 + +struct Location +{ + float x, y, z, o; +}; + +static Location AllianceCoords[]= +{ + {-3757.38, -4533.05, 14.16, 3.62}, // Top-far-right bunk as seen from entrance + {-3754.36, -4539.13, 14.16, 5.13}, // Top-far-left bunk + {-3749.54, -4540.25, 14.28, 3.34}, // Far-right bunk + {-3742.10, -4536.85, 14.28, 3.64}, // Right bunk near entrance + {-3755.89, -4529.07, 14.05, 0.57}, // Far-left bunk + {-3749.51, -4527.08, 14.07, 5.26}, // Mid-left bunk + {-3746.37, -4525.35, 14.16, 5.22}, // Left bunk near entrance +}; + +//alliance run to where +#define A_RUNTOX -3742.96 +#define A_RUNTOY -4531.52 +#define A_RUNTOZ 11.91 + +static Location HordeCoords[]= +{ + {-1013.75, -3492.59, 62.62, 4.34}, // Left, Behind + {-1017.72, -3490.92, 62.62, 4.34}, // Right, Behind + {-1015.77, -3497.15, 62.82, 4.34}, // Left, Mid + {-1019.51, -3495.49, 62.82, 4.34}, // Right, Mid + {-1017.25, -3500.85, 62.98, 4.34}, // Left, front + {-1020.95, -3499.21, 62.98, 4.34} // Right, Front +}; + +//horde run to where +#define H_RUNTOX -1016.44 +#define H_RUNTOY -3508.48 +#define H_RUNTOZ 62.96 + +const uint32 AllianceSoldierId[3] = +{ + 12938, // 12938 Injured Alliance Soldier + 12936, // 12936 Badly injured Alliance Soldier + 12937 // 12937 Critically injured Alliance Soldier +}; + +const uint32 HordeSoldierId[3] = +{ + 12923, //12923 Injured Soldier + 12924, //12924 Badly injured Soldier + 12925 //12925 Critically injured Soldier +}; + +/*###### +## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor) +######*/ + +struct npc_doctorAI : public ScriptedAI +{ + npc_doctorAI(Creature *c) : ScriptedAI(c) {} + + uint64 PlayerGUID; + + uint32 SummonPatient_Timer; + uint32 SummonPatientCount; + uint32 PatientDiedCount; + uint32 PatientSavedCount; + + bool Event; + + std::list Patients; + std::vector Coordinates; + + void Reset() + { + PlayerGUID = 0; + + SummonPatient_Timer = 10000; + SummonPatientCount = 0; + PatientDiedCount = 0; + PatientSavedCount = 0; + + Patients.clear(); + Coordinates.clear(); + + Event = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void BeginEvent(Player* pPlayer); + void PatientDied(Location* Point); + void PatientSaved(Creature* soldier, Player* pPlayer, Location* Point); + void UpdateAI(const uint32 diff); + + void EnterCombat(Unit* /*who*/){} +}; + +/*##### +## npc_injured_patient (handles all the patients, no matter Horde or Alliance) +#####*/ + +struct npc_injured_patientAI : public ScriptedAI +{ + npc_injured_patientAI(Creature *c) : ScriptedAI(c) {} + + uint64 Doctorguid; + Location* Coord; + + void Reset() + { + Doctorguid = 0; + Coord = NULL; + + //no select + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //no regen health + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + + //to make them lay with face down + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + + uint32 mobId = me->GetEntry(); + + switch (mobId) + { //lower max health + case 12923: + case 12938: //Injured Soldier + me->SetHealth(uint32(me->GetMaxHealth()*.75)); + break; + case 12924: + case 12936: //Badly injured Soldier + me->SetHealth(uint32(me->GetMaxHealth()*.50)); + break; + case 12925: + case 12937: //Critically injured Soldier + me->SetHealth(uint32(me->GetMaxHealth()*.25)); + break; + } + } + + void EnterCombat(Unit* /*who*/){} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER && me->isAlive() && spell->Id == 20804) + { + if ((CAST_PLR(caster)->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (CAST_PLR(caster)->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)) + if (Doctorguid) + if (Creature* Doctor = Unit::GetCreature(*me, Doctorguid)) + CAST_AI(npc_doctorAI, Doctor->AI())->PatientSaved(me, CAST_PLR(caster), Coord); + + //make not selectable + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //regen health + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + + //stand up + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); + + DoScriptText(RAND(SAY_DOC1,SAY_DOC2,SAY_DOC3), me); + + uint32 mobId = me->GetEntry(); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + switch (mobId) + { + case 12923: + case 12924: + case 12925: + me->GetMotionMaster()->MovePoint(0, H_RUNTOX, H_RUNTOY, H_RUNTOZ); + break; + case 12936: + case 12937: + case 12938: + me->GetMotionMaster()->MovePoint(0, A_RUNTOX, A_RUNTOY, A_RUNTOZ); + break; + } + } + } + + void UpdateAI(const uint32 /*diff*/) + { + //lower HP on every world tick makes it a useful counter, not officlone though + if (me->isAlive() && me->GetHealth() > 6) + { + me->SetHealth(uint32(me->GetHealth()-5)); + } + + if (me->isAlive() && me->GetHealth() <= 6) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setDeathState(JUST_DIED); + me->SetFlag(UNIT_DYNAMIC_FLAGS, 32); + + if (Doctorguid) + { + if (Creature* Doctor = Unit::GetCreature((*me), Doctorguid)) + CAST_AI(npc_doctorAI, Doctor->AI())->PatientDied(Coord); + } + } + } +}; + +CreatureAI* GetAI_npc_injured_patient(Creature* pCreature) +{ + return new npc_injured_patientAI (pCreature); +} + +/* +npc_doctor (continue) +*/ + +void npc_doctorAI::BeginEvent(Player* pPlayer) +{ + PlayerGUID = pPlayer->GetGUID(); + + SummonPatient_Timer = 10000; + SummonPatientCount = 0; + PatientDiedCount = 0; + PatientSavedCount = 0; + + switch(me->GetEntry()) + { + case DOCTOR_ALLIANCE: + for (uint8 i = 0; i < ALLIANCE_COORDS; ++i) + Coordinates.push_back(&AllianceCoords[i]); + break; + case DOCTOR_HORDE: + for (uint8 i = 0; i < HORDE_COORDS; ++i) + Coordinates.push_back(&HordeCoords[i]); + break; + } + + Event = true; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); +} + +void npc_doctorAI::PatientDied(Location* Point) +{ + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer && ((pPlayer->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (pPlayer->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))) + { + ++PatientDiedCount; + + if (PatientDiedCount > 5 && Event) + { + if (pPlayer->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) + pPlayer->FailQuest(6624); + else if (pPlayer->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE) + pPlayer->FailQuest(6622); + + Reset(); + return; + } + + Coordinates.push_back(Point); + } + else + // If no player or player abandon quest in progress + Reset(); +} + +void npc_doctorAI::PatientSaved(Creature* /*soldier*/, Player* pPlayer, Location* Point) +{ + if (pPlayer && PlayerGUID == pPlayer->GetGUID()) + { + if ((pPlayer->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (pPlayer->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)) + { + ++PatientSavedCount; + + if (PatientSavedCount == 15) + { + if (!Patients.empty()) + { + std::list::const_iterator itr; + for (itr = Patients.begin(); itr != Patients.end(); ++itr) + { + if (Creature* Patient = Unit::GetCreature((*me), *itr)) + Patient->setDeathState(JUST_DIED); + } + } + + if (pPlayer->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(6624); + else if (pPlayer->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(6622); + + Reset(); + return; + } + + Coordinates.push_back(Point); + } + } +} + +void npc_doctorAI::UpdateAI(const uint32 diff) +{ + if (Event && SummonPatientCount >= 20) + { + Reset(); + return; + } + + if (Event) + { + if (SummonPatient_Timer <= diff) + { + Creature* Patient = NULL; + Location* Point = NULL; + + if (Coordinates.empty()) + return; + + std::vector::iterator itr = Coordinates.begin()+rand()%Coordinates.size(); + uint32 patientEntry = 0; + + switch(me->GetEntry()) + { + case DOCTOR_ALLIANCE: patientEntry = AllianceSoldierId[rand()%3]; break; + case DOCTOR_HORDE: patientEntry = HordeSoldierId[rand()%3]; break; + default: + error_log("TSCR: Invalid entry for Triage doctor. Please check your database"); + return; + } + + Point = *itr; + + Patient = me->SummonCreature(patientEntry, Point->x, Point->y, Point->z, Point->o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + + if (Patient) + { + //303, this flag appear to be required for client side item->spell to work (TARGET_SINGLE_FRIEND) + Patient->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + Patients.push_back(Patient->GetGUID()); + CAST_AI(npc_injured_patientAI, Patient->AI())->Doctorguid = me->GetGUID(); + + if (Point) + CAST_AI(npc_injured_patientAI, Patient->AI())->Coord = Point; + + Coordinates.erase(itr); + } + SummonPatient_Timer = 10000; + ++SummonPatientCount; + } else SummonPatient_Timer -= diff; + } +} + +bool QuestAccept_npc_doctor(Player* pPlayer, Creature* pCreature, Quest const *quest) +{ + if ((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622)) + CAST_AI(npc_doctorAI, pCreature->AI())->BeginEvent(pPlayer); + + return true; +} + +CreatureAI* GetAI_npc_doctor(Creature* pCreature) +{ + return new npc_doctorAI (pCreature); +} + +/*###### +## npc_garments_of_quests +######*/ + +//TODO: get text for each NPC + +enum eGarments +{ + SPELL_LESSER_HEAL_R2 = 2052, + SPELL_FORTITUDE_R1 = 1243, + + QUEST_MOON = 5621, + QUEST_LIGHT_1 = 5624, + QUEST_LIGHT_2 = 5625, + QUEST_SPIRIT = 5648, + QUEST_DARKNESS = 5650, + + ENTRY_SHAYA = 12429, + ENTRY_ROBERTS = 12423, + ENTRY_DOLF = 12427, + ENTRY_KORJA = 12430, + ENTRY_DG_KEL = 12428, + + //used by 12429,12423,12427,12430,12428, but signed for 12429 + SAY_COMMON_HEALED = -1000164, + SAY_DG_KEL_THANKS = -1000165, + SAY_DG_KEL_GOODBYE = -1000166, + SAY_ROBERTS_THANKS = -1000167, + SAY_ROBERTS_GOODBYE = -1000168, + SAY_KORJA_THANKS = -1000169, + SAY_KORJA_GOODBYE = -1000170, + SAY_DOLF_THANKS = -1000171, + SAY_DOLF_GOODBYE = -1000172, + SAY_SHAYA_THANKS = -1000173, + SAY_SHAYA_GOODBYE = -1000174, //signed for 21469 +}; + +struct npc_garments_of_questsAI : public npc_escortAI +{ + npc_garments_of_questsAI(Creature *c) : npc_escortAI(c) {Reset();} + + uint64 caster; + + bool bIsHealed; + bool bCanRun; + + uint32 RunAwayTimer; + + void Reset() + { + caster = 0; + + bIsHealed = false; + bCanRun = false; + + RunAwayTimer = 5000; + + me->SetStandState(UNIT_STAND_STATE_KNEEL); + //expect database to have RegenHealth=0 + me->SetHealth(int(me->GetMaxHealth()*0.7)); + } + + void EnterCombat(Unit * /*who*/) {} + + void SpellHit(Unit* pCaster, const SpellEntry *Spell) + { + if (Spell->Id == SPELL_LESSER_HEAL_R2 || Spell->Id == SPELL_FORTITUDE_R1) + { + //not while in combat + if (me->isInCombat()) + return; + + //nothing to be done now + if (bIsHealed && bCanRun) + return; + + if (pCaster->GetTypeId() == TYPEID_PLAYER) + { + switch(me->GetEntry()) + { + case ENTRY_SHAYA: + if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_MOON) == QUEST_STATUS_INCOMPLETE) + { + if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) + { + DoScriptText(SAY_SHAYA_THANKS,me,pCaster); + bCanRun = true; + } + else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) + { + caster = pCaster->GetGUID(); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_COMMON_HEALED,me,pCaster); + bIsHealed = true; + } + } + break; + case ENTRY_ROBERTS: + if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_LIGHT_1) == QUEST_STATUS_INCOMPLETE) + { + if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) + { + DoScriptText(SAY_ROBERTS_THANKS,me,pCaster); + bCanRun = true; + } + else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) + { + caster = pCaster->GetGUID(); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_COMMON_HEALED,me,pCaster); + bIsHealed = true; + } + } + break; + case ENTRY_DOLF: + if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_LIGHT_2) == QUEST_STATUS_INCOMPLETE) + { + if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) + { + DoScriptText(SAY_DOLF_THANKS,me,pCaster); + bCanRun = true; + } + else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) + { + caster = pCaster->GetGUID(); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_COMMON_HEALED,me,pCaster); + bIsHealed = true; + } + } + break; + case ENTRY_KORJA: + if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_SPIRIT) == QUEST_STATUS_INCOMPLETE) + { + if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) + { + DoScriptText(SAY_KORJA_THANKS,me,pCaster); + bCanRun = true; + } + else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) + { + caster = pCaster->GetGUID(); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_COMMON_HEALED,me,pCaster); + bIsHealed = true; + } + } + break; + case ENTRY_DG_KEL: + if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_DARKNESS) == QUEST_STATUS_INCOMPLETE) + { + if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) + { + DoScriptText(SAY_DG_KEL_THANKS,me,pCaster); + bCanRun = true; + } + else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) + { + caster = pCaster->GetGUID(); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_COMMON_HEALED,me,pCaster); + bIsHealed = true; + } + } + break; + } + + //give quest credit, not expect any special quest objectives + if (bCanRun) + CAST_PLR(pCaster)->TalkedToCreature(me->GetEntry(),me->GetGUID()); + } + } + } + + void WaypointReached(uint32 /*uiPoint*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (bCanRun && !me->isInCombat()) + { + if (RunAwayTimer <= diff) + { + if (Unit *pUnit = Unit::GetUnit(*me,caster)) + { + switch(me->GetEntry()) + { + case ENTRY_SHAYA: DoScriptText(SAY_SHAYA_GOODBYE,me,pUnit); break; + case ENTRY_ROBERTS: DoScriptText(SAY_ROBERTS_GOODBYE,me,pUnit); break; + case ENTRY_DOLF: DoScriptText(SAY_DOLF_GOODBYE,me,pUnit); break; + case ENTRY_KORJA: DoScriptText(SAY_KORJA_GOODBYE,me,pUnit); break; + case ENTRY_DG_KEL: DoScriptText(SAY_DG_KEL_GOODBYE,me,pUnit); break; + } + + Start(false,true,true); + } + else + EnterEvadeMode(); //something went wrong + + RunAwayTimer = 30000; + } else RunAwayTimer -= diff; + } + + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_garments_of_quests(Creature* pCreature) +{ + return new npc_garments_of_questsAI(pCreature); +} + +/*###### +## npc_guardian +######*/ + +#define SPELL_DEATHTOUCH 5 + +struct npc_guardianAI : public ScriptedAI +{ + npc_guardianAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + if (me->isAttackReady()) + { + DoCast(me->getVictim(), SPELL_DEATHTOUCH, true); + me->resetAttackTimer(); + } + } +}; + +CreatureAI* GetAI_npc_guardian(Creature* pCreature) +{ + return new npc_guardianAI (pCreature); +} + +/*###### +## npc_kingdom_of_dalaran_quests +######*/ + +enum eKingdomDalaran +{ + SPELL_TELEPORT_DALARAN = 53360, + ITEM_KT_SIGNET = 39740, + QUEST_MAGICAL_KINGDOM_A = 12794, + QUEST_MAGICAL_KINGDOM_H = 12791, + QUEST_MAGICAL_KINGDOM_N = 12796 +}; + +#define GOSSIP_ITEM_TELEPORT_TO "I am ready to be teleported to Dalaran." + +bool GossipHello_npc_kingdom_of_dalaran_quests(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->HasItemCount(ITEM_KT_SIGNET,1) && (!pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_A) || + !pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_H) || !pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_N))) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT_TO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_kingdom_of_dalaran_quests(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,SPELL_TELEPORT_DALARAN,false); + } + return true; +} + +/*###### +## npc_mount_vendor +######*/ + +bool GossipHello_npc_mount_vendor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + bool canBuy; + canBuy = false; + uint32 vendor = pCreature->GetEntry(); + uint8 race = pPlayer->getRace(); + + switch (vendor) + { + case 384: //Katie Hunter + case 1460: //Unger Statforth + case 2357: //Merideth Carlson + case 4885: //Gregor MacVince + if (pPlayer->GetReputationRank(72) != REP_EXALTED && race != RACE_HUMAN) + pPlayer->SEND_GOSSIP_MENU(5855, pCreature->GetGUID()); + else canBuy = true; + break; + case 1261: //Veron Amberstill + if (pPlayer->GetReputationRank(47) != REP_EXALTED && race != RACE_DWARF) + pPlayer->SEND_GOSSIP_MENU(5856, pCreature->GetGUID()); + else canBuy = true; + break; + case 3362: //Ogunaro Wolfrunner + if (pPlayer->GetReputationRank(76) != REP_EXALTED && race != RACE_ORC) + pPlayer->SEND_GOSSIP_MENU(5841, pCreature->GetGUID()); + else canBuy = true; + break; + case 3685: //Harb Clawhoof + if (pPlayer->GetReputationRank(81) != REP_EXALTED && race != RACE_TAUREN) + pPlayer->SEND_GOSSIP_MENU(5843, pCreature->GetGUID()); + else canBuy = true; + break; + case 4730: //Lelanai + if (pPlayer->GetReputationRank(69) != REP_EXALTED && race != RACE_NIGHTELF) + pPlayer->SEND_GOSSIP_MENU(5844, pCreature->GetGUID()); + else canBuy = true; + break; + case 4731: //Zachariah Post + if (pPlayer->GetReputationRank(68) != REP_EXALTED && race != RACE_UNDEAD_PLAYER) + pPlayer->SEND_GOSSIP_MENU(5840, pCreature->GetGUID()); + else canBuy = true; + break; + case 7952: //Zjolnir + if (pPlayer->GetReputationRank(530) != REP_EXALTED && race != RACE_TROLL) + pPlayer->SEND_GOSSIP_MENU(5842, pCreature->GetGUID()); + else canBuy = true; + break; + case 7955: //Milli Featherwhistle + if (pPlayer->GetReputationRank(54) != REP_EXALTED && race != RACE_GNOME) + pPlayer->SEND_GOSSIP_MENU(5857, pCreature->GetGUID()); + else canBuy = true; + break; + case 16264: //Winaestra + if (pPlayer->GetReputationRank(911) != REP_EXALTED && race != RACE_BLOODELF) + pPlayer->SEND_GOSSIP_MENU(10305, pCreature->GetGUID()); + else canBuy = true; + break; + case 17584: //Torallius the Pack Handler + if (pPlayer->GetReputationRank(930) != REP_EXALTED && race != RACE_DRAENEI) + pPlayer->SEND_GOSSIP_MENU(10239, pCreature->GetGUID()); + else canBuy = true; + break; + } + + if (canBuy) + { + if (pCreature->isVendor()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_mount_vendor(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_rogue_trainer +######*/ + +#define GOSSIP_HELLO_ROGUE1 "I wish to unlearn my talents" +#define GOSSIP_HELLO_ROGUE2 "" +#define GOSSIP_HELLO_ROGUE3 "Purchase a Dual Talent Specialization." + +bool GossipHello_npc_rogue_trainer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isTrainer()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + if (pCreature->isCanTrainingAndResetTalentsOf(pPlayer)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE1, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_UNLEARNTALENTS); + + if (!(pPlayer->GetSpecsCount() == 1 && pCreature->isCanTrainingAndResetTalentsOf(pPlayer) && !(pPlayer->getLevel() < sWorld.getConfig(CONFIG_MIN_DUALSPEC_LEVEL)))) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE3, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_LEARNDUALSPEC); + + if (pPlayer->getClass() == CLASS_ROGUE && pPlayer->getLevel() >= 24 && !pPlayer->HasItemCount(17126,1) && !pPlayer->GetQuestRewardStatus(6681)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_ROGUE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(5996, pCreature->GetGUID()); + } else + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_rogue_trainer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,21100,false); + break; + case GOSSIP_ACTION_TRAIN: + pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); + break; + case GOSSIP_OPTION_UNLEARNTALENTS: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->SendTalentWipeConfirm(pCreature->GetGUID()); + break; + case GOSSIP_OPTION_LEARNDUALSPEC: + if (pPlayer->GetSpecsCount() == 1 && !(pPlayer->getLevel() < sWorld.getConfig(CONFIG_MIN_DUALSPEC_LEVEL))) + { + if (pPlayer->GetMoney() < 10000000) + { + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); + pPlayer->PlayerTalkClass->CloseGossip(); + break; + } + else + { + pPlayer->ModifyMoney(-10000000); + + // Cast spells that teach dual spec + // Both are also ImplicitTarget self and must be cast by player + pPlayer->CastSpell(pPlayer,63680,true,NULL,NULL,pPlayer->GetGUID()); + pPlayer->CastSpell(pPlayer,63624,true,NULL,NULL,pPlayer->GetGUID()); + + // Should show another Gossip text with "Congratulations..." + pPlayer->PlayerTalkClass->CloseGossip(); + } + } + break; + } + return true; +} + +/*###### +## npc_sayge +######*/ + +#define SPELL_DMG 23768 //dmg +#define SPELL_RES 23769 //res +#define SPELL_ARM 23767 //arm +#define SPELL_SPI 23738 //spi +#define SPELL_INT 23766 //int +#define SPELL_STM 23737 //stm +#define SPELL_STR 23735 //str +#define SPELL_AGI 23736 //agi +#define SPELL_FORTUNE 23765 //faire fortune + +#define GOSSIP_HELLO_SAYGE "Yes" +#define GOSSIP_SENDACTION_SAYGE1 "Slay the Man" +#define GOSSIP_SENDACTION_SAYGE2 "Turn him over to liege" +#define GOSSIP_SENDACTION_SAYGE3 "Confiscate the corn" +#define GOSSIP_SENDACTION_SAYGE4 "Let him go and have the corn" +#define GOSSIP_SENDACTION_SAYGE5 "Execute your friend painfully" +#define GOSSIP_SENDACTION_SAYGE6 "Execute your friend painlessly" +#define GOSSIP_SENDACTION_SAYGE7 "Let your friend go" +#define GOSSIP_SENDACTION_SAYGE8 "Confront the diplomat" +#define GOSSIP_SENDACTION_SAYGE9 "Show not so quiet defiance" +#define GOSSIP_SENDACTION_SAYGE10 "Remain quiet" +#define GOSSIP_SENDACTION_SAYGE11 "Speak against your brother openly" +#define GOSSIP_SENDACTION_SAYGE12 "Help your brother in" +#define GOSSIP_SENDACTION_SAYGE13 "Keep your brother out without letting him know" +#define GOSSIP_SENDACTION_SAYGE14 "Take credit, keep gold" +#define GOSSIP_SENDACTION_SAYGE15 "Take credit, share the gold" +#define GOSSIP_SENDACTION_SAYGE16 "Let the knight take credit" +#define GOSSIP_SENDACTION_SAYGE17 "Thanks" + +bool GossipHello_npc_sayge(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->HasSpellCooldown(SPELL_INT) || + pPlayer->HasSpellCooldown(SPELL_ARM) || + pPlayer->HasSpellCooldown(SPELL_DMG) || + pPlayer->HasSpellCooldown(SPELL_RES) || + pPlayer->HasSpellCooldown(SPELL_STR) || + pPlayer->HasSpellCooldown(SPELL_AGI) || + pPlayer->HasSpellCooldown(SPELL_STM) || + pPlayer->HasSpellCooldown(SPELL_SPI)) + pPlayer->SEND_GOSSIP_MENU(7393, pCreature->GetGUID()); + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_SAYGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(7339, pCreature->GetGUID()); + } + + return true; +} + +void SendAction_npc_sayge(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(7340, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE5, GOSSIP_SENDER_MAIN+1, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE6, GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE7, GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(7341, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE8, GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE9, GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE10, GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(7361, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE11, GOSSIP_SENDER_MAIN+6, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE12, GOSSIP_SENDER_MAIN+7, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE13, GOSSIP_SENDER_MAIN+8, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(7362, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE14, GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE15, GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE16, GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(7363, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE17, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(7364, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pCreature->CastSpell(pPlayer, SPELL_FORTUNE, false); + pPlayer->SEND_GOSSIP_MENU(7365, pCreature->GetGUID()); + break; + } +} + +bool GossipSelect_npc_sayge(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiSender) + { + case GOSSIP_SENDER_MAIN: + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + case GOSSIP_SENDER_MAIN+1: + pCreature->CastSpell(pPlayer, SPELL_DMG, false); + pPlayer->AddSpellCooldown(SPELL_DMG,0,time(NULL) + 7200); + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + case GOSSIP_SENDER_MAIN+2: + pCreature->CastSpell(pPlayer, SPELL_RES, false); + pPlayer->AddSpellCooldown(SPELL_RES,0,time(NULL) + 7200); + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + case GOSSIP_SENDER_MAIN+3: + pCreature->CastSpell(pPlayer, SPELL_ARM, false); + pPlayer->AddSpellCooldown(SPELL_ARM,0,time(NULL) + 7200); + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + case GOSSIP_SENDER_MAIN+4: + pCreature->CastSpell(pPlayer, SPELL_SPI, false); + pPlayer->AddSpellCooldown(SPELL_SPI,0,time(NULL) + 7200); + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + case GOSSIP_SENDER_MAIN+5: + pCreature->CastSpell(pPlayer, SPELL_INT, false); + pPlayer->AddSpellCooldown(SPELL_INT,0,time(NULL) + 7200); + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + case GOSSIP_SENDER_MAIN+6: + pCreature->CastSpell(pPlayer, SPELL_STM, false); + pPlayer->AddSpellCooldown(SPELL_STM,0,time(NULL) + 7200); + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + case GOSSIP_SENDER_MAIN+7: + pCreature->CastSpell(pPlayer, SPELL_STR, false); + pPlayer->AddSpellCooldown(SPELL_STR,0,time(NULL) + 7200); + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + case GOSSIP_SENDER_MAIN+8: + pCreature->CastSpell(pPlayer, SPELL_AGI, false); + pPlayer->AddSpellCooldown(SPELL_AGI,0,time(NULL) + 7200); + SendAction_npc_sayge(pPlayer, pCreature, uiAction); + break; + } + return true; +} + +struct npc_steam_tonkAI : public ScriptedAI +{ + npc_steam_tonkAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + + void OnPossess(bool apply) + { + if (apply) + { + // Initialize the action bar without the melee attack command + me->InitCharmInfo(); + me->GetCharmInfo()->InitEmptyActionBar(false); + + me->SetReactState(REACT_PASSIVE); + } + else + me->SetReactState(REACT_AGGRESSIVE); + } + +}; + +CreatureAI* GetAI_npc_steam_tonk(Creature* pCreature) +{ + return new npc_steam_tonkAI(pCreature); +} + +#define SPELL_TONK_MINE_DETONATE 25099 + +struct npc_tonk_mineAI : public ScriptedAI +{ + npc_tonk_mineAI(Creature *c) : ScriptedAI(c) + { + me->SetReactState(REACT_PASSIVE); + } + + uint32 ExplosionTimer; + + void Reset() + { + ExplosionTimer = 3000; + } + + void EnterCombat(Unit * /*who*/) {} + void AttackStart(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (ExplosionTimer <= diff) + { + DoCast(me, SPELL_TONK_MINE_DETONATE, true); + me->setDeathState(DEAD); // unsummon it + } else + ExplosionTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_tonk_mine(Creature* pCreature) +{ + return new npc_tonk_mineAI(pCreature); +} + +/*#### +## npc_brewfest_reveler +####*/ + +struct npc_brewfest_revelerAI : public ScriptedAI +{ + npc_brewfest_revelerAI(Creature* c) : ScriptedAI(c) {} + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + if (!IsHolidayActive(HOLIDAY_BREWFEST)) + return; + + if (emote == TEXTEMOTE_DANCE) + me->CastSpell(pPlayer, 41586, false); + } +}; + +CreatureAI* GetAI_npc_brewfest_reveler(Creature* pCreature) +{ + return new npc_brewfest_revelerAI(pCreature); +} + +/*#### +## npc_winter_reveler +####*/ + +struct npc_winter_revelerAI : public ScriptedAI +{ + npc_winter_revelerAI(Creature* c) : ScriptedAI(c) {} + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + if (!IsHolidayActive(HOLIDAY_FEAST_OF_WINTER_VEIL)) + return; + //TODO: check auralist. + if (pPlayer->HasAura(26218)) + return; + + if (emote == TEXTEMOTE_KISS) + { + me->CastSpell(me, 26218, false); + pPlayer->CastSpell(pPlayer, 26218, false); + switch (urand(0,2)) + { + case 0: me->CastSpell(pPlayer, 26207, false); break; + case 1: me->CastSpell(pPlayer, 26206, false); break; + case 2: me->CastSpell(pPlayer, 45036, false); break; + } + } + } +}; + +CreatureAI* GetAI_npc_winter_reveler(Creature* pCreature) +{ + return new npc_winter_revelerAI(pCreature); +} + + +/*#### +## npc_snake_trap_serpents +####*/ + +#define SPELL_MIND_NUMBING_POISON 25810 //Viper +#define SPELL_DEADLY_POISON 34655 //Venomous Snake +#define SPELL_CRIPPLING_POISON 30981 //Viper + +#define VENOMOUS_SNAKE_TIMER 1500 +#define VIPER_TIMER 3000 + +#define C_VIPER 19921 + +#define RAND 5 + +struct npc_snake_trap_serpentsAI : public ScriptedAI +{ + npc_snake_trap_serpentsAI(Creature *c) : ScriptedAI(c) {} + + uint32 SpellTimer; + bool IsViper; + bool Spawn; + + void EnterCombat(Unit * /*who*/) {} + + void Reset() + { + Spawn = true; + SpellTimer = 0; + + CreatureInfo const *Info = me->GetCreatureInfo(); + + if (Info->Entry == C_VIPER) + IsViper = true; + else + IsViper = false; + + //Add delta to make them not all hit the same time + uint32 delta = (rand() % 7) * 100; + me->SetStatFloatValue(UNIT_FIELD_BASEATTACKTIME, Info->baseattacktime + delta); + me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER , Info->attackpower); + } + + //Redefined for random target selection: + void MoveInLineOfSight(Unit *who) + { + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + if (!(rand() % RAND)) + { + me->setAttackTimer(BASE_ATTACK, (rand() % 10) * 100); + SpellTimer = (rand() % 10) * 100; + AttackStart(who); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Spawn) + { + Spawn = false; + // Start attacking attacker of owner on first ai update after spawn - move in line of sight may choose better target + if (!me->getVictim() && me->isSummon()) + if (Unit * Owner = CAST_SUM(me)->GetSummoner()) + if (Owner->getAttackerForHelper()) + AttackStart(Owner->getAttackerForHelper()); + } + + if (!me->getVictim()) + { + if (me->isInCombat()) + DoStopAttack(); + return; + } + + if (SpellTimer <= diff) + { + if (IsViper) //Viper + { + if (urand(0,2) == 0) //33% chance to cast + { + uint32 spell; + if (urand(0,1) == 0) + spell = SPELL_MIND_NUMBING_POISON; + else + spell = SPELL_CRIPPLING_POISON; + + DoCast(me->getVictim(), spell); + } + + SpellTimer = VIPER_TIMER; + } + else //Venomous Snake + { + if (urand(0,2) == 0) //33% chance to cast + DoCast(me->getVictim(), SPELL_DEADLY_POISON); + SpellTimer = VENOMOUS_SNAKE_TIMER + (rand() %5)*100; + } + } else SpellTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_snake_trap_serpents(Creature* pCreature) +{ + return new npc_snake_trap_serpentsAI(pCreature); +} + +#define SAY_RANDOM_MOJO0 "Now that's what I call froggy-style!" +#define SAY_RANDOM_MOJO1 "Your lily pad or mine?" +#define SAY_RANDOM_MOJO2 "This won't take long, did it?" +#define SAY_RANDOM_MOJO3 "I thought you'd never ask!" +#define SAY_RANDOM_MOJO4 "I promise not to give you warts..." +#define SAY_RANDOM_MOJO5 "Feelin' a little froggy, are ya?" +#define SAY_RANDOM_MOJO6a "Listen, " +#define SAY_RANDOM_MOJO6b ", I know of a little swamp not too far from here...." +#define SAY_RANDOM_MOJO7 "There's just never enough Mojo to go around..." + +struct mob_mojoAI : public ScriptedAI +{ + mob_mojoAI(Creature *c) : ScriptedAI(c) {Reset();} + uint32 hearts; + uint64 victimGUID; + void Reset() + { + victimGUID = 0; + hearts = 15000; + if (Unit* own = me->GetOwner()) + me->GetMotionMaster()->MoveFollow(own,0,0); + } + void Aggro(Unit * /*who*/){} + void UpdateAI(const uint32 diff) + { + if (me->HasAura(20372)) + { + if (hearts <= diff) + { + me->RemoveAurasDueToSpell(20372); + hearts = 15000; + } hearts -= diff; + } + } + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + me->HandleEmoteCommand(emote); + Unit* own = me->GetOwner(); + if (!own || own->GetTypeId() != TYPEID_PLAYER || CAST_PLR(own)->GetTeam() != pPlayer->GetTeam()) + return; + if (emote == TEXTEMOTE_KISS) + { + std::string whisp = ""; + switch (rand()%8) + { + case 0:whisp.append(SAY_RANDOM_MOJO0);break; + case 1:whisp.append(SAY_RANDOM_MOJO1);break; + case 2:whisp.append(SAY_RANDOM_MOJO2);break; + case 3:whisp.append(SAY_RANDOM_MOJO3);break; + case 4:whisp.append(SAY_RANDOM_MOJO4);break; + case 5:whisp.append(SAY_RANDOM_MOJO5);break; + case 6: + whisp.append(SAY_RANDOM_MOJO6a); + whisp.append(pPlayer->GetName()); + whisp.append(SAY_RANDOM_MOJO6b); + break; + case 7:whisp.append(SAY_RANDOM_MOJO7);break; + } + me->MonsterWhisper(whisp.c_str(),pPlayer->GetGUID()); + if (victimGUID) + { + Player* victim = Unit::GetPlayer(victimGUID); + if (victim) + victim->RemoveAura(43906);//remove polymorph frog thing + } + me->AddAura(43906,pPlayer);//add polymorph frog thing + victimGUID = pPlayer->GetGUID(); + DoCast(me, 20372, true);//tag.hearts + me->GetMotionMaster()->MoveFollow(pPlayer,0,0); + hearts = 15000; + } + } +}; + +CreatureAI* GetAI_mob_mojo(Creature* pCreature) +{ + return new mob_mojoAI (pCreature); +} + +struct npc_mirror_image : CasterAI +{ + npc_mirror_image(Creature *c) : CasterAI(c) {} + + void InitializeAI() + { + CasterAI::InitializeAI(); + Unit * owner = me->GetOwner(); + if (!owner) + return; + // Inherit Master's Threat List (not yet implemented) + owner->CastSpell((Unit*)NULL, 58838, true); + // here mirror image casts on summoner spell (not present in client dbc) 49866 + // here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcasted by mirror images (stats related?) + // Clone Me! + owner->CastSpell(me, 45204, false); + } + + // Do not reload Creature templates on evade mode enter - prevent visual lost + void EnterEvadeMode() + { + if (me->IsInEvadeMode() || !me->isAlive()) + return; + + Unit *owner = me->GetCharmerOrOwner(); + + me->CombatStop(true); + if (owner && !me->hasUnitState(UNIT_STAT_FOLLOW)) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE); + } + } +}; + +CreatureAI* GetAI_npc_mirror_image(Creature* pCreature) +{ + return new npc_mirror_image (pCreature); +} + +struct npc_ebon_gargoyleAI : CasterAI +{ + npc_ebon_gargoyleAI(Creature *c) : CasterAI(c) {} + + int despawnTimer; + + void InitializeAI() + { + CasterAI::InitializeAI(); + Unit * owner = me->GetOwner(); + if (!owner) + return; + // Not needed to be despawned now + despawnTimer = 0; + // Find victim of Summon Gargoyle spell + std::list targets; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30); + Trinity::UnitListSearcher searcher(me, targets, u_check); + me->VisitNearbyObject(30, searcher); + for (std::list::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) + if ((*iter)->GetAura(49206,owner->GetGUID())) + { + me->Attack((*iter),false); + break; + } + } + + void JustDied(Unit * /*killer*/) + { + // Stop Feeding Gargoyle when it dies + if (Unit *owner = me->GetOwner()) + owner->RemoveAurasDueToSpell(50514); + } + + // Fly away when dismissed + void SpellHit(Unit *source, const SpellEntry *spell) + { + if (spell->Id != 50515 || !me->isAlive()) + return; + + Unit *owner = me->GetOwner(); + + if (!owner || owner != source) + return; + + // Stop Fighting + me->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, true); + // Sanctuary + me->CastSpell(me, 54661, true); + me->SetReactState(REACT_PASSIVE); + + // Fly Away + me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE|MOVEMENTFLAG_ASCEND|MOVEMENTFLAG_FLYING); + me->SetSpeed(MOVE_FLIGHT, 0.75f, true); + me->SetSpeed(MOVE_RUN, 0.75f, true); + float x = me->GetPositionX() + 20 * cos(me->GetOrientation()); + float y = me->GetPositionY() + 20 * sin(me->GetOrientation()); + float z = me->GetPositionZ() + 40; + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MovePoint(0, x, y, z); + + // Despawn as soon as possible + despawnTimer = 4 * IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (despawnTimer > 0) + { + if (despawnTimer > diff) + despawnTimer -= diff; + else + { + me->ForcedDespawn(); + } + return; + } + CasterAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_ebon_gargoyle(Creature* pCreature) +{ + return new npc_ebon_gargoyleAI (pCreature); +} + +struct npc_lightwellAI : public PassiveAI +{ + npc_lightwellAI(Creature *c) : PassiveAI(c) {} + + void Reset() + { + DoCast(me, 59907, false); // Spell for Lightwell Charges + } +}; + +CreatureAI* GetAI_npc_lightwellAI(Creature* pCreature) +{ + return new npc_lightwellAI (pCreature); +} + +struct npc_training_dummy : Scripted_NoMovementAI +{ + npc_training_dummy(Creature *c) : Scripted_NoMovementAI(c) + { + m_Entry = c->GetEntry(); + } + + uint64 m_Entry; + uint32 ResetTimer; + uint32 DespawnTimer; + void Reset() + { + me->SetControlled(true,UNIT_STAT_STUNNED);//disable rotate + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave + me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_STUN, true); + ResetTimer = 10000; + DespawnTimer = 15000; + } + + void EnterEvadeMode() + { + if (!_EnterEvadeMode()) + return; + + Reset(); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + ResetTimer = 10000; + damage = 0; + } + + void EnterCombat(Unit * /*who*/) + { + if (m_Entry != 2674 && m_Entry != 2673) + return; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + me->SetControlled(true,UNIT_STAT_STUNNED);//disable rotate + + if (m_Entry != 2674 && m_Entry != 2673) + { + if (ResetTimer <= diff) + { + EnterEvadeMode(); + ResetTimer = 10000; + } + else + ResetTimer -= diff; + return; + } + else + { + if (DespawnTimer <= diff) + me->ForcedDespawn(); + else + DespawnTimer -= diff; + } + } + void MoveInLineOfSight(Unit * /*who*/){return;} +}; + +CreatureAI* GetAI_npc_training_dummy(Creature* pCreature) +{ + return new npc_training_dummy (pCreature); +} + +/*###### +# npc_shadowfiend +######*/ +#define GLYPH_OF_SHADOWFIEND_MANA 58227 +#define GLYPH_OF_SHADOWFIEND 58228 + +struct npc_shadowfiendAI : public ScriptedAI +{ + npc_shadowfiendAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (me->isSummon()) + if (Unit* pOwner = CAST_SUM(me)->GetSummoner()) + { + if (pOwner->HasAura(GLYPH_OF_SHADOWFIEND)) + if (damage >= me->GetHealth()) + pOwner->CastSpell(pOwner,GLYPH_OF_SHADOWFIEND_MANA,true); + } + } + + void UpdateAI(const uint32 /*diff*/) + { + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_shadowfiend(Creature* pCreature) +{ + return new npc_shadowfiendAI(pCreature); +} + +/*###### +# npc_wormhole +######*/ + +#define GOSSIP_ENGINEERING1 "Borean Tundra." +#define GOSSIP_ENGINEERING2 "Howling Fjord." +#define GOSSIP_ENGINEERING3 "Sholazar Basin." +#define GOSSIP_ENGINEERING4 "Icecrown." +#define GOSSIP_ENGINEERING5 "Storm Peaks." + +enum eWormhole +{ + SPELL_HOWLING_FJORD = 67838, + SPELL_SHOLAZAR_BASIN = 67835, + SPELL_ICECROWN = 67836, + SPELL_STORM_PEAKS = 67837, + + TEXT_WORMHOLE = 907 +}; + +bool GossipHello_npc_wormhole(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isSummon()) + { + if (pPlayer == CAST_SUM(pCreature)->GetSummoner()) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + + pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_WORMHOLE, pCreature->GetGUID()); + } + } + return true; +} + +bool GossipSelect_npc_wormhole(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + bool roll = urand(0,1); + + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: //Borean Tundra + pPlayer->CLOSE_GOSSIP_MENU(); + if (roll) //At the moment we don't have chance on spell_target_position table so we hack this + pPlayer->TeleportTo(571, 4305.505859, 5450.839844, 63.005806, 0.627286); + else + pPlayer->TeleportTo(571, 3201.936279, 5630.123535, 133.658798, 3.855272); + break; + case GOSSIP_ACTION_INFO_DEF + 2: //Howling Fjord + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_HOWLING_FJORD, true); + break; + case GOSSIP_ACTION_INFO_DEF + 3: //Sholazar Basin + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_SHOLAZAR_BASIN, true); + break; + case GOSSIP_ACTION_INFO_DEF + 4: //Icecrown + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_ICECROWN, true); + break; + case GOSSIP_ACTION_INFO_DEF + 5: //Storm peaks + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_STORM_PEAKS, true); + break; + } + return true; +} + +/*###### +## npc_pet_trainer +######*/ + +enum ePetTrainer +{ + TEXT_ISHUNTER = 5838, + TEXT_NOTHUNTER = 5839, + TEXT_PETINFO = 13474, + TEXT_CONFIRM = 7722 +}; + +#define GOSSIP_PET1 "How do I train my pet?" +#define GOSSIP_PET2 "I wish to untrain my pet." +#define GOSSIP_PET_CONFIRM "Yes, please do." + +bool GossipHello_npc_pet_trainer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->getClass() == CLASS_HUNTER) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if (pPlayer->GetPet() && pPlayer->GetPet()->getPetType() == HUNTER_PET) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_ISHUNTER, pCreature->GetGUID()); + return true; + } + pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_NOTHUNTER, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_pet_trainer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_PETINFO, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET_CONFIRM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_CONFIRM, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 3: + { + pPlayer->ResetPetTalents(); + pPlayer->CLOSE_GOSSIP_MENU(); + } + break; + } + return true; +} + +/*###### +## npc_locksmith +######*/ + +enum eLockSmith +{ + QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ = 10704, + QUEST_DARK_IRON_LEGACY = 3802, + QUEST_THE_KEY_TO_SCHOLOMANCE_A = 5505, + QUEST_THE_KEY_TO_SCHOLOMANCE_H = 5511, + QUEST_HOTTER_THAN_HELL_A = 10758, + QUEST_HOTTER_THAN_HELL_H = 10764, + QUEST_RETURN_TO_KHAGDAR = 9837, + QUEST_CONTAINMENT = 13159, + + ITEM_ARCATRAZ_KEY = 31084, + ITEM_SHADOWFORGE_KEY = 11000, + ITEM_SKELETON_KEY = 13704, + ITEM_SHATTERED_HALLS_KEY = 28395, + ITEM_THE_MASTERS_KEY = 24490, + ITEM_VIOLET_HOLD_KEY = 42482, + + SPELL_ARCATRAZ_KEY = 54881, + SPELL_SHADOWFORGE_KEY = 54882, + SPELL_SKELETON_KEY = 54883, + SPELL_SHATTERED_HALLS_KEY = 54884, + SPELL_THE_MASTERS_KEY = 54885, + SPELL_VIOLET_HOLD_KEY = 67253 +}; + +#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz." +#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths." +#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance." +#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls." +#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan." +#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold." + + +bool GossipHello_npc_locksmith(Player* pPlayer, Creature* pCreature) +{ + + // Arcatraz Key + if (pPlayer->GetQuestRewardStatus(QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ) && !pPlayer->HasItemCount(ITEM_ARCATRAZ_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ARCATRAZ_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +1); + + // Shadowforge Key + if (pPlayer->GetQuestRewardStatus(QUEST_DARK_IRON_LEGACY) && !pPlayer->HasItemCount(ITEM_SHADOWFORGE_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHADOWFORGE_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +2); + + // Skeleton Key + if ((pPlayer->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_A) || pPlayer->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_H)) && + !pPlayer->HasItemCount(ITEM_SKELETON_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SKELETON_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +3); + + // Shatered Halls Key + if ((pPlayer->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_A) || pPlayer->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_H)) && + !pPlayer->HasItemCount(ITEM_SHATTERED_HALLS_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHATTERED_HALLS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +4); + + // Master's Key + if (pPlayer->GetQuestRewardStatus(QUEST_RETURN_TO_KHAGDAR) && !pPlayer->HasItemCount(ITEM_THE_MASTERS_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_THE_MASTERS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +5); + + // Violet Hold Key + if (pPlayer->GetQuestRewardStatus(QUEST_CONTAINMENT) && !pPlayer->HasItemCount(ITEM_VIOLET_HOLD_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_VIOLET_HOLD_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +6); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_locksmith(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_ARCATRAZ_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_SHADOWFORGE_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_SKELETON_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_SHATTERED_HALLS_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_THE_MASTERS_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_VIOLET_HOLD_KEY, false); + break; + } + return true; +} + +/*###### +## npc_tabard_vendor +######*/ + +enum +{ + QUEST_TRUE_MASTERS_OF_LIGHT = 9737, + QUEST_THE_UNWRITTEN_PROPHECY = 9762, + QUEST_INTO_THE_BREACH = 10259, + QUEST_BATTLE_OF_THE_CRIMSON_WATCH = 10781, + QUEST_SHARDS_OF_AHUNE = 11972, + + ACHIEVEMENT_EXPLORE_NORTHREND = 45, + ACHIEVEMENT_TWENTYFIVE_TABARDS = 1021, + ACHIEVEMENT_THE_LOREMASTER_A = 1681, + ACHIEVEMENT_THE_LOREMASTER_H = 1682, + + ITEM_TABARD_OF_THE_HAND = 24344, + ITEM_TABARD_OF_THE_BLOOD_KNIGHT = 25549, + ITEM_TABARD_OF_THE_PROTECTOR = 28788, + ITEM_OFFERING_OF_THE_SHATAR = 31408, + ITEM_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI = 31404, + ITEM_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI = 31405, + ITEM_TABARD_OF_THE_SUMMER_SKIES = 35279, + ITEM_TABARD_OF_THE_SUMMER_FLAMES = 35280, + ITEM_TABARD_OF_THE_ACHIEVER = 40643, + ITEM_LOREMASTERS_COLORS = 43300, + ITEM_TABARD_OF_THE_EXPLORER = 43348, + + SPELL_TABARD_OF_THE_BLOOD_KNIGHT = 54974, + SPELL_TABARD_OF_THE_HAND = 54976, + SPELL_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI = 54977, + SPELL_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI = 54982, + SPELL_TABARD_OF_THE_ACHIEVER = 55006, + SPELL_TABARD_OF_THE_PROTECTOR = 55008, + SPELL_LOREMASTERS_COLORS = 58194, + SPELL_TABARD_OF_THE_EXPLORER = 58224, + SPELL_TABARD_OF_SUMMER_SKIES = 62768, + SPELL_TABARD_OF_SUMMER_FLAMES = 62769 +}; + +#define GOSSIP_LOST_TABARD_OF_BLOOD_KNIGHT "I've lost my Tabard of Blood Knight." +#define GOSSIP_LOST_TABARD_OF_THE_HAND "I've lost my Tabard of the Hand." +#define GOSSIP_LOST_TABARD_OF_THE_PROTECTOR "I've lost my Tabard of the Protector." +#define GOSSIP_LOST_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI "I've lost my Green Trophy Tabard of the Illidari." +#define GOSSIP_LOST_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI "I've lost my Purple Trophy Tabard of the Illidari." +#define GOSSIP_LOST_TABARD_OF_SUMMER_SKIES "I've lost my Tabard of Summer Skies." +#define GOSSIP_LOST_TABARD_OF_SUMMER_FLAMES "I've lost my Tabard of Summer Flames." +#define GOSSIP_LOST_LOREMASTERS_COLORS "I've lost my Loremaster's Colors." +#define GOSSIP_LOST_TABARD_OF_THE_EXPLORER "I've lost my Tabard of the Explorer." +#define GOSSIP_LOST_TABARD_OF_THE_ACHIEVER "I've lost my Tabard of the Achiever." + +bool GossipHello_npc_tabard_vendor(Player* pPlayer, Creature* pCreature) +{ + bool m_bLostBloodKnight = false; + bool m_bLostHand = false; + bool m_bLostProtector = false; + bool m_bLostIllidari = false; + bool m_bLostSummer = false; + + //Tabard of the Blood Knight + if (pPlayer->GetQuestRewardStatus(QUEST_TRUE_MASTERS_OF_LIGHT) && !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_BLOOD_KNIGHT, 1, true)) + m_bLostBloodKnight = true; + + //Tabard of the Hand + if (pPlayer->GetQuestRewardStatus(QUEST_THE_UNWRITTEN_PROPHECY) && !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_HAND, 1, true)) + m_bLostHand = true; + + //Tabard of the Protector + if (pPlayer->GetQuestRewardStatus(QUEST_INTO_THE_BREACH) && !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_PROTECTOR, 1, true)) + m_bLostProtector = true; + + //Green Trophy Tabard of the Illidari + //Purple Trophy Tabard of the Illidari + if (pPlayer->GetQuestRewardStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) && + (!pPlayer->HasItemCount(ITEM_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, 1, true) && + !pPlayer->HasItemCount(ITEM_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, 1, true) && + !pPlayer->HasItemCount(ITEM_OFFERING_OF_THE_SHATAR, 1, true))) + m_bLostIllidari = true; + + //Tabard of Summer Skies + //Tabard of Summer Flames + if (pPlayer->GetQuestRewardStatus(QUEST_SHARDS_OF_AHUNE) && + !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_SUMMER_SKIES, 1, true) && + !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_SUMMER_FLAMES, 1, true)) + m_bLostSummer = true; + + if (m_bLostBloodKnight || m_bLostHand || m_bLostProtector || m_bLostIllidari || m_bLostSummer) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (m_bLostBloodKnight) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_BLOOD_KNIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +1); + + if (m_bLostHand) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_THE_HAND, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +2); + + if (m_bLostProtector) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_THE_PROTECTOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + + if (m_bLostIllidari) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + } + + if (m_bLostSummer) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_SUMMER_SKIES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_SUMMER_FLAMES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + } + + pPlayer->SEND_GOSSIP_MENU(13583, pCreature->GetGUID()); + } + else + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_tabard_vendor(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_THE_BLOOD_KNIGHT, false); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_THE_HAND, false); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_THE_PROTECTOR, false); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, false); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, false); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_SUMMER_SKIES, false); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_SUMMER_FLAMES, false); + break; + } + return true; +} + +/*###### +## npc_experience +######*/ + +#define EXP_COST 100000//10 00 00 copper (10golds) +#define GOSSIP_TEXT_EXP 14736 +#define GOSSIP_XP_OFF "I no longer wish to gain experience." +#define GOSSIP_XP_ON "I wish to start gaining experience again." + + +bool GossipHello_npc_experience(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_XP_OFF, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_XP_ON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_EXP, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_experience(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + bool noXPGain = pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); + bool doSwitch = false; + + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1://xp off + { + if (!noXPGain)//does gain xp + doSwitch = true;//switch to don't gain xp + } + break; + case GOSSIP_ACTION_INFO_DEF + 2://xp on + { + if (noXPGain)//doesn't gain xp + doSwitch = true;//switch to gain xp + } + break; + } + if (doSwitch) + { + if (pPlayer->GetMoney() < EXP_COST) + pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); + else if (noXPGain) + { + pPlayer->ModifyMoney(-EXP_COST); + pPlayer->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); + } + else if (!noXPGain) + { + pPlayer->ModifyMoney(-EXP_COST); + pPlayer->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); + } + } + pPlayer->PlayerTalkClass->CloseGossip(); + return true; +} + +void AddSC_npcs_special() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_air_force_bots"; + newscript->GetAI = &GetAI_npc_air_force_bots; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lunaclaw_spirit"; + newscript->pGossipHello = &GossipHello_npc_lunaclaw_spirit; + newscript->pGossipSelect = &GossipSelect_npc_lunaclaw_spirit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_chicken_cluck"; + newscript->GetAI = &GetAI_npc_chicken_cluck; + newscript->pQuestAccept = &QuestAccept_npc_chicken_cluck; + newscript->pQuestComplete = &QuestComplete_npc_chicken_cluck; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dancing_flames"; + newscript->GetAI = &GetAI_npc_dancing_flames; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_injured_patient"; + newscript->GetAI = &GetAI_npc_injured_patient; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_doctor"; + newscript->GetAI = &GetAI_npc_doctor; + newscript->pQuestAccept = &QuestAccept_npc_doctor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_garments_of_quests"; + newscript->GetAI = &GetAI_npc_garments_of_quests; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_guardian"; + newscript->GetAI = &GetAI_npc_guardian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_kingdom_of_dalaran_quests"; + newscript->pGossipHello = &GossipHello_npc_kingdom_of_dalaran_quests; + newscript->pGossipSelect = &GossipSelect_npc_kingdom_of_dalaran_quests; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mount_vendor"; + newscript->pGossipHello = &GossipHello_npc_mount_vendor; + newscript->pGossipSelect = &GossipSelect_npc_mount_vendor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_rogue_trainer"; + newscript->pGossipHello = &GossipHello_npc_rogue_trainer; + newscript->pGossipSelect = &GossipSelect_npc_rogue_trainer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_sayge"; + newscript->pGossipHello = &GossipHello_npc_sayge; + newscript->pGossipSelect = &GossipSelect_npc_sayge; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_steam_tonk"; + newscript->GetAI = &GetAI_npc_steam_tonk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tonk_mine"; + newscript->GetAI = &GetAI_npc_tonk_mine; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_winter_reveler"; + newscript->GetAI = &GetAI_npc_winter_reveler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_brewfest_reveler"; + newscript->GetAI = &GetAI_npc_winter_reveler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_snake_trap_serpents"; + newscript->GetAI = &GetAI_npc_snake_trap_serpents; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mirror_image"; + newscript->GetAI = &GetAI_npc_mirror_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ebon_gargoyle"; + newscript->GetAI = &GetAI_npc_ebon_gargoyle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lightwell"; + newscript->GetAI = &GetAI_npc_lightwellAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_mojo"; + newscript->GetAI = &GetAI_mob_mojo; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_training_dummy"; + newscript->GetAI = &GetAI_npc_training_dummy; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_shadowfiend"; + newscript->GetAI = &GetAI_npc_shadowfiend; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_wormhole"; + newscript->pGossipHello = &GossipHello_npc_wormhole; + newscript->pGossipSelect = &GossipSelect_npc_wormhole; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_pet_trainer"; + newscript->pGossipHello = &GossipHello_npc_pet_trainer; + newscript->pGossipSelect = &GossipSelect_npc_pet_trainer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_locksmith"; + newscript->pGossipHello = &GossipHello_npc_locksmith; + newscript->pGossipSelect = &GossipSelect_npc_locksmith; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tabard_vendor"; + newscript->pGossipHello = &GossipHello_npc_tabard_vendor; + newscript->pGossipSelect = &GossipSelect_npc_tabard_vendor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_experience"; + newscript->pGossipHello = &GossipHello_npc_experience; + newscript->pGossipSelect = &GossipSelect_npc_experience; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/custom/custom_example.cpp b/src/server/scripts/custom/custom_example.cpp deleted file mode 100644 index 0e230ba901d..00000000000 --- a/src/server/scripts/custom/custom_example.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Custom_Example -SD%Complete: 100 -SDComment: Short custom scripting example -SDCategory: Script Examples -EndScriptData */ - -#include "precompiled.h" - -// **** This script is designed as an example for others to build on **** -// **** Please modify whatever you'd like to as this script is only for developement **** - -// **** Script Info **** -// This script is written in a way that it can be used for both friendly and hostile monsters -// Its primary purpose is to show just how much you can really do with scripts -// I recommend trying it out on both an agressive NPC and on friendly npc - -// **** Quick Info **** -// Functions with Handled Function marked above them are functions that are called automatically by the core -// Functions that are marked Custom Function are functions I've created to simplify code - -#define SPELL_BUFF 25661 -#define SPELL_ONE 12555 -#define SPELL_ONE_ALT 24099 -#define SPELL_TWO 10017 -#define SPELL_THREE 26027 -#define SPELL_ENRAGE 23537 -#define SPELL_BESERK 32309 - -#define SAY_AGGRO "Let the games begin." -#define SAY_RANDOM_0 "I see endless suffering. I see torment. I see rage. I see everything." -#define SAY_RANDOM_1 "Muahahahaha" -#define SAY_RANDOM_2 "These mortal infedels my lord, they have invaded your sanctum and seek to steal your secrets." -#define SAY_RANDOM_3 "You are already dead." -#define SAY_RANDOM_4 "Where to go? What to do? So many choices that all end in pain, end in death." -#define SAY_BESERK "$N, I sentance you to death!" -#define SAY_PHASE "The suffering has just begun!" - -#define GOSSIP_ITEM "I'm looking for a fight" -#define SAY_DANCE "I always thought I was a good dancer" -#define SAY_SALUTE "Move out Soldier!" - -struct TRINITY_DLL_DECL custom_exampleAI : public ScriptedAI -{ - //*** HANDLED FUNCTION *** - //This is the constructor, called only once when the Creature is first created - custom_exampleAI(Creature *c) : ScriptedAI(c) {} - - //*** CUSTOM VARIABLES **** - //These variables are for use only by this individual script. - //Nothing else will ever call them but us. - - uint32 Say_Timer; //Timer for random chat - uint32 Rebuff_Timer; //Timer for rebuffing - uint32 Spell_1_Timer; //Timer for spell 1 when in combat - uint32 Spell_2_Timer; //Timer for spell 1 when in combat - uint32 Spell_3_Timer; //Timer for spell 1 when in combat - uint32 Beserk_Timer; //Timer until we go into Beserk (enraged) mode - uint32 Phase; //The current battle phase we are in - uint32 Phase_Timer; //Timer until phase transition - - //*** HANDLED FUNCTION *** - //This is called whenever the core decides we need to evade - void Reset() - { - Phase = 1; //Start in phase 1 - Phase_Timer = 60000; //60 seconds - Spell_1_Timer = 5000; //5 seconds - Spell_2_Timer = 37000; //37 seconds - Spell_3_Timer = 19000; //19 seconds - Beserk_Timer = 120000; //2 minutes - } - - //*** HANDLED FUNCTION *** - //Attack Start is called whenever someone hits us. - void Aggro(Unit *who) - { - //Say some stuff - DoSay(SAY_AGGRO,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,8280); - } - - //*** HANDLED FUNCTION *** - //Update AI is called Every single map update (roughly once every 100ms if a player is within the grid) - void UpdateAI(const uint32 diff) - { - //Out of combat timers - if (!me->getVictim()) - { - //Random Say timer - if (Say_Timer < diff) - { - //Random switch between 5 outcomes - switch (rand()%5) - { - case 0: - DoYell(SAY_RANDOM_0,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,8831); //8831 is the index of the sound we are playing. You find these numbers in SoundEntries.dbc - break; - - case 1: - DoYell(SAY_RANDOM_1,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,8818); - break; - - case 2: - DoYell(SAY_RANDOM_2,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,8041); - break; - - case 3: - DoYell(SAY_RANDOM_3,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,8581); - break; - - case 4: - DoYell(SAY_RANDOM_4,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,8791); - break; - } - - Say_Timer = 45000; //Say something agian in 45 seconds - }else Say_Timer -= diff; - - //Rebuff timer - if (Rebuff_Timer < diff) - { - DoCast(me,SPELL_BUFF); - Rebuff_Timer = 900000; //Rebuff agian in 15 minutes - }else Rebuff_Timer -= diff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Spell 1 timer - if (Spell_1_Timer < diff) - { - //Cast spell one on our current target. - if (rand()%50 > 10) - DoCast(me->getVictim(),SPELL_ONE_ALT); - else if (me->IsWithinDist(me->getVictim(), 25)) - DoCast(me->getVictim(),SPELL_ONE); - - Spell_1_Timer = 5000; - }else Spell_1_Timer -= diff; - - //Spell 2 timer - if (Spell_2_Timer < diff) - { - //Cast spell one on our current target. - DoCast(me->getVictim(),SPELL_TWO); - - Spell_2_Timer = 37000; - }else Spell_2_Timer -= diff; - - //Spell 3 timer - if (Phase > 1) - if (Spell_3_Timer < diff) - { - //Cast spell one on our current target. - DoCast(me->getVictim(),SPELL_THREE); - - Spell_3_Timer = 19000; - }else Spell_3_Timer -= diff; - - //Beserk timer - if (Phase > 1) - if (Beserk_Timer < diff) - { - //Say our line then cast uber death spell - DoPlaySoundToSet(me,8588); - DoYell(SAY_BESERK,LANG_UNIVERSAL,me->getVictim()); - DoCast(me->getVictim(),SPELL_BESERK); - - //Cast our beserk spell agian in 12 seconds if we didn't kill everyone - Beserk_Timer = 12000; - }else Beserk_Timer -= diff; - - //Phase timer - if (Phase == 1) - if (Phase_Timer < diff) - { - //Go to next phase - Phase++; - DoYell(SAY_PHASE,LANG_UNIVERSAL,NULL); - DoCast(me,SPELL_ENRAGE); - }else Phase_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//This is the GetAI method used by all scripts that involve AI -//It is called every time a new Creature using this script is created -CreatureAI* GetAI_custom_example(Creature* pCreature) -{ - return new custom_exampleAI (pCreature); -} - -//This function is called when the player clicks an option on the gossip menu -void SendDefaultMenu_custom_example(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time - { - //Set our faction to hostile twoards all - pCreature->setFaction(24); - pCreature->Attack(pPlayer, true); - pPlayer->PlayerTalkClass->CloseGossip(); - } -} - -//This function is called when the player clicks an option on the gossip menu -bool GossipSelect_custom_example(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiSender == GOSSIP_SENDER_MAIN) - SendDefaultMenu_custom_example(pPlayer, pCreature, uiAction); - - return true; -} - -//This function is called when the player opens the gossip menu -bool GossipHello_custom_example(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetGUID()); - - return true; -} - -//Our Recive emote function -bool ReceiveEmote_custom_example(Player* pPlayer, Creature* pCreature, uint32 emote) -{ - pCreature->HandleEmoteCommand(emote); - - if (emote == TEXTEMOTE_DANCE) - ((custom_exampleAI*)_Creature->AI())->DoSay(SAY_DANCE,LANG_UNIVERSAL,NULL); - - if (emote == TEXTEMOTE_SALUTE) - ((custom_exampleAI*)_Creature->AI())->DoSay(SAY_SALUTE,LANG_UNIVERSAL,NULL); - - return true; -} - -//This is the actual function called only once durring InitScripts() -//It must define all handled functions that are to be run in this script -//For example if you want this Script to handle Emotes you must include -//newscript->ReciveEmote = My_Emote_Function; -void AddSC_custom_example() -{ - Script *newscript; - - newscript = new Script; - newscript->Name="custom_example"; - newscript->GetAI = &GetAI_custom_example; - newscript->pGossipHello = &GossipHello_custom_example; - newscript->pGossipSelect = &GossipSelect_custom_example; - newscript->pReceiveEmote = &ReceiveEmote_custom_example; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/custom/custom_gossip_codebox.cpp b/src/server/scripts/custom/custom_gossip_codebox.cpp deleted file mode 100644 index a00d2b7031f..00000000000 --- a/src/server/scripts/custom/custom_gossip_codebox.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Custom_Gossip_Codebox -SD%Complete: 100 -SDComment: Show a codebox in gossip option -SDCategory: Script Examples -EndScriptData */ - -#include "precompiled.h" -#include - -#define GOSSIP_ITEM_EXTENDED "A quiz: what's your name?" -#define GOSSIP_ITEM "I'm not interested" - -#define SAY_NOT_INTERESTED "Normal select, guess you're not interested." -#define SAY_WRONG "Wrong!" -#define SAY_RIGHT "You're right, you are allowed to see my inner secrets." - -//This function is called when the player opens the gossip menubool -bool GossipHello_custom_gossip_codebox(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1, "", 0, true); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetGUID()); - return true; -} - -//This function is called when the player clicks an option on the gossip menubool -bool GossipSelect_custom_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pCreature->Say(SAY_NOT_INTERESTED, LANG_UNIVERSAL, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - } - return true; -} - -bool GossipSelectWithCode_custom_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode) -{ - if (uiSender == GOSSIP_SENDER_MAIN) - { - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - if (std::strcmp(sCode, pPlayer->GetName())!=0) - { - pCreature->Say(SAY_WRONG, LANG_UNIVERSAL, 0); - pCreature->CastSpell(pPlayer, 12826, true); - } - else - { - pCreature->Say(SAY_RIGHT, LANG_UNIVERSAL, 0); - pCreature->CastSpell(pPlayer, 26990, true); - } - pPlayer->CLOSE_GOSSIP_MENU(); - return true; - } - } - return false; -} - -void AddSC_custom_gossip_codebox() -{ - Script *newscript; - - newscript = new Script; - newscript->Name="custom_gossip_codebox"; - newscript->pGossipHello = &GossipHello_custom_gossip_codebox; - newscript->pGossipSelect = &GossipSelect_custom_gossip_codebox; - newscript->pGossipSelectWithCode = &GossipSelectWithCode_custom_gossip_codebox; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/custom/npc_acherus_taxi.cpp b/src/server/scripts/custom/npc_acherus_taxi.cpp deleted file mode 100644 index 6e00e365e8e..00000000000 --- a/src/server/scripts/custom/npc_acherus_taxi.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "ScriptedPch.h" -#include "WorldPacket.h" - -#define GOSSIP_FLIGHT "I need a ride" - -bool GossipHello_npc_acherus_taxi(Player *pPlayer, Creature *pCreature) -{ - pPlayer->SetTaxiCheater(true); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(9978, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_acherus_taxi(Player *pPlayer, Creature * /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - if (pPlayer->GetPositionZ() >= 316) - pPlayer->GetSession()->SendDoFlight(24446, 1053); - else - pPlayer->GetSession()->SendDoFlight(24446, 1054); - } - return true; -} - -void AddSC_npc_acherus_taxi() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_acherus_taxi"; - newscript->pGossipHello = &GossipHello_npc_acherus_taxi; - newscript->pGossipSelect = &GossipSelect_npc_acherus_taxi; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/custom/npc_wyrmresttempel_taxi.cpp b/src/server/scripts/custom/npc_wyrmresttempel_taxi.cpp deleted file mode 100644 index d4c2cb5ab74..00000000000 --- a/src/server/scripts/custom/npc_wyrmresttempel_taxi.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "ScriptedPch.h" -#include "WorldPacket.h" - -#define GOSSIP_UP "My Lord, I must go to the upper floor of the temple." -#define GOSSIP_DOWN "I would like to take a flight to the ground, Lord Afrasastrasz." -#define GOSSIP_MIDDLE "Can you spare a drake to travel to Lord Afrasastrasz, in the middle of the temple?" -#define GOSSIP_TOP "Please, Let me take one of these dragons to the top floor of the temple." -#define GOSSIP_BOTTOM "Yes, Please. I would like to return to the ground floor of the temple." -#define GOSSIP_ONEDOWN "I would like to see Lord Afrasastrasz, in the middle of the temple." - -bool GossipHello_npc_wyrmresttempel_middle_taxi(Player* pPlayer, Creature* pCreature) -{ -pPlayer->SetTaxiCheater(true); - -pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); -pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DOWN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(12887, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_wyrmresttempel_middle_taxi(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->GetSession()->SendDoFlight(6376, 881); - } - - if (uiAction == GOSSIP_ACTION_INFO_DEF + 2) - { - pPlayer->GetSession()->SendDoFlight(6376, 882); - - } -return true; -} - -bool GossipHello_npc_wyrmresttempel_bottom_taxi(Player* pPlayer, Creature* pCreature) -{ -pPlayer->SetTaxiCheater(true); - -pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TOP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); -pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MIDDLE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(12713, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_wyrmresttempel_bottom_taxi(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 4) - { - pPlayer->GetSession()->SendDoFlight(6376, 878); - } - - if (uiAction == GOSSIP_ACTION_INFO_DEF + 3) - { - pPlayer->GetSession()->SendDoFlight(6376, 883); - - } -return true; -} - -bool GossipHello_npc_wyrmresttempel_top_taxi(Player* pPlayer, Creature* pCreature) -{ -pPlayer->SetTaxiCheater(true); - -pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BOTTOM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); -pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ONEDOWN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - pPlayer->SEND_GOSSIP_MENU(12714, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_wyrmresttempel_top_taxi(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 5) - { - pPlayer->GetSession()->SendDoFlight(6376, 879); - } - - if (uiAction == GOSSIP_ACTION_INFO_DEF + 6) - - { - pPlayer->GetSession()->SendDoFlight(6376, 880); - - } -return true; -} - -void AddSC_npc_wyrmresttempel_taxi() -{ - Script *newscript; - -newscript = new Script; -newscript->Name = "npc_wyrmresttempelmiddle_taxi"; -newscript->pGossipHello = &GossipHello_npc_wyrmresttempel_middle_taxi; -newscript->pGossipSelect = &GossipSelect_npc_wyrmresttempel_middle_taxi; -newscript->RegisterSelf(); - -newscript = new Script; -newscript->Name = "npc_wyrmresttempelbottom_taxi"; -newscript->pGossipHello = &GossipHello_npc_wyrmresttempel_bottom_taxi; -newscript->pGossipSelect = &GossipSelect_npc_wyrmresttempel_bottom_taxi; -newscript->RegisterSelf(); - -newscript = new Script; -newscript->Name = "npc_wyrmresttempeltop_taxi"; -newscript->pGossipHello = &GossipHello_npc_wyrmresttempel_top_taxi; -newscript->pGossipSelect = &GossipSelect_npc_wyrmresttempel_top_taxi; -newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/custom/on_events.cpp b/src/server/scripts/custom/on_events.cpp deleted file mode 100644 index 94e54a07fba..00000000000 --- a/src/server/scripts/custom/on_events.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include "ScriptedPch.h" -#include - -//This function is called when the player logs in (every login) -void OnLogin(Player * /*pPlayer*/) -{ - -} - -//This function is called when the player logs out -void OnLogout(Player * /*pPlayer*/) -{ - -} - -//This function is called when the player kills another player -void OnPVPKill(Player * /*killer*/, Player * /*killed*/) -{ - -} - -//This function is called when a players AreaID changes -void OnAreaChange(Player * /*pPlayer*/, AreaTableEntry const * /*pArea*/) -{ - -} - -//This is called when a player kills a creature (non pvp) -void OnCreatureKill(Player * /*pPlayer*/, Creature * /*pCreature*/) -{ - -} - -//This function is called when a player has a money exchange -int32 OnGetMoney(Player * /*pPlayer*/, int32 amount) -{ - return amount; -} - -//This function is called whenever a player gets XP -uint32 OnGetXP(Player * /*pPlayer*/, uint32 amount) -{ - return amount; -} - -//This function is called when a player clicks a GO Object -bool OnGoClick(Player * /*pPlayer*/, GameObject * /*pGameObject*/) -{ - return true; -} - -//This function is called when a player clicks and item -bool OnItemClick(Player * /*pPlayer*/, Item * /*pItem*/) -{ - return true; -} - -//This function is called when a player opens an item (like a clam) -bool OnItemOpen(Player * /*pPlayer*/, Item * /*pItem*/) -{ - return true; -} - -//This function is called when a player sends a chat message -bool OnPlayerChat(Player * /*pPlayer*/, const char * /*text*/) -{ - return true; -} - -//this function is called when the server starts -void OnServerStartup() -{ - -} -//this function is called when the server shuts down -void OnServerShutdown() -{ - -} - -//this function is called when a player casts a spell -bool OnSpellCast(Unit * /*pUnitTarget*/, Item * /*pItemTarget*/, GameObject * /*pGoTarget*/, uint32 /*i*/, SpellEntry const * /*spell*/) -{ - return true; -} - - void AddSC_onevents() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "scripted_on_events"; - newscript->pOnLogin = &OnLogin; - newscript->pOnLogout = &OnLogout; - newscript->pOnPVPKill = &OnPVPKill; - newscript->pOnAreaChange = &OnAreaChange; - newscript->pOnCreatureKill = &OnCreatureKill; - newscript->pOnGetMoney = &OnGetMoney; - newscript->pOnGetXP = &OnGetXP; - newscript->pOnGoClick = &OnGoClick; - newscript->pOnItemClick = &OnItemClick; - newscript->pOnItemOpen = &OnItemOpen; - newscript->pOnPlayerChat = &OnPlayerChat; - newscript->pOnServerShutdown = &OnServerShutdown; - newscript->pOnServerStartup = &OnServerStartup; - newscript->pOnSpellCast = &OnSpellCast; - - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/custom/test.cpp b/src/server/scripts/custom/test.cpp deleted file mode 100644 index aa9e6879075..00000000000 --- a/src/server/scripts/custom/test.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Test -SD%Complete: 100 -SDComment: Script used for testing escortAI -SDCategory: Script Examples -EndScriptData */ - -#include "precompiled.h" -#include "escort_ai.h" - -#define SAY_WALK "Hmm a nice day for a walk alright" -#define SAY_ATTACK "Wild Felboar attack!" -#define SAY_TIME_TO_GO "Time for me to go! See ya around $N!" -#define SAY_BYE "Bye Bye!" -#define SAY_AGGRO1 "Help $N! I'm under attack!" -#define SAY_AGGRO2 "Die scum!" -#define WHISPER_TOO_FAR "How dare you leave me like that! I hate you! =*(" -#define SAY_DIE1 "...no...how could you let me die $N" -#define SAY_DIE2 "ugh..." -#define SAY_DEATHCOIL "Taste death!" -#define SAY_FIREWORKS "Fireworks!" -#define SAY_BUFF "Hmm, I think I could use a buff" - -#define GOSSIP_TEXT1 "Click to Test Escort(Attack, Defend, Run)" -#define GOSSIP_TEXT2 "Click to Test Escort(NoAttack, NoDefend, Walk)" -#define GOSSIP_TEXT3 "Click to Test Escort(NoAttack, Defend, Walk)" - -struct TRINITY_DLL_DECL npc_testAI : public npc_escortAI -{ - public: - - // CreatureAI functions - npc_testAI(Creature *c) : npc_escortAI(c) {} - - uint32 DeathCoilTimer; - uint32 ChatTimer; - - // Pure Virtual Functions - void WaypointReached(uint32 i) - { - switch (i) - { - case 1: - me->Say(SAY_WALK, LANG_UNIVERSAL, 0); - break; - - case 3: - { - me->Say(SAY_ATTACK, LANG_UNIVERSAL, 0); - Creature* temp = me->SummonCreature(21878, me->GetPositionX()+5, me->GetPositionY()+7, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); - if (temp) - temp->AI()->AttackStart(me); - } - break; - - case 4: - { - me->Say(SAY_TIME_TO_GO, LANG_UNIVERSAL, PlayerGUID); - me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); - - Unit* temp = Unit::GetUnit(*me, PlayerGUID); - if (temp) - { - temp->MonsterSay(SAY_BYE, LANG_UNIVERSAL, 0); - temp->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); - } - } - break; - } - } - - void Aggro(Unit*) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - me->Say(SAY_AGGRO1, LANG_UNIVERSAL, PlayerGUID); - else me->Say(SAY_AGGRO2, LANG_UNIVERSAL, 0); - } - - void Reset() - { - DeathCoilTimer = 4000; - ChatTimer = 4000; - } - - void JustDied(Unit* killer) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - //killer = me when player got to far from creature - if (killer == me) - { - Unit *pTemp = Unit::GetUnit(*me,PlayerGUID); - if (pTemp) - DoWhisper(WHISPER_TOO_FAR, pTemp); - } - else me->Say(SAY_DIE1, LANG_UNIVERSAL, PlayerGUID); - } - else me->Say(SAY_DIE2, LANG_UNIVERSAL, 0); - } - - void UpdateAI(const uint32 diff) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - - //Combat check - if (me->isInCombat() && me->getVictim()) - { - if (DeathCoilTimer < diff) - { - me->Say(SAY_DEATHCOIL, LANG_UNIVERSAL, 0); - me->CastSpell(me->getVictim(), 33130, false); - - DeathCoilTimer = 4000; - }else DeathCoilTimer -= diff; - }else - { - //Out of combat but being escorted - if (HasEscortState(STATE_ESCORT_ESCORTING)) - if (ChatTimer < diff) - { - if (me->HasAura(3593, 0)) - { - me->Say(SAY_FIREWORKS, LANG_UNIVERSAL, 0); - me->CastSpell(me, 11540, false); - }else - { - me->Say(SAY_BUFF, LANG_UNIVERSAL, 0); - me->CastSpell(me, 3593, false); - } - - ChatTimer = 12000; - }else ChatTimer -= diff; - } - } -}; - -CreatureAI* GetAI_test(Creature* pCreature) -{ - npc_testAI* testAI = new npc_testAI(pCreature); - - testAI->AddWaypoint(0, 1231, -4419, 23); - testAI->AddWaypoint(1, 1198, -4440, 23, 0); - testAI->AddWaypoint(2, 1208, -4392, 23); - testAI->AddWaypoint(3, 1231, -4419, 23, 5000); - testAI->AddWaypoint(4, 1208, -4392, 23, 5000); - - return (CreatureAI*)testAI; -} - -bool GossipHello_npc_test(Player* pPlayer, Creature* pCreature) -{ - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - pCreature->prepareGossipMenu(pPlayer,0); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEXT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEXT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEXT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - - pCreature->sendPreparedGossip(pPlayer); - return true; -} - -bool GossipSelect_npc_test(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - ((npc_escortAI*)(pCreature->AI()))->Start(true, true, pPlayer->GetGUID()); - - return true; // prevent Trinity core handling - } - - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - ((npc_escortAI*)(pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); - - return true; // prevent Trinity core handling - } - - if (uiAction == GOSSIP_ACTION_INFO_DEF+3) - { - pPlayer->CLOSE_GOSSIP_MENU(); - ((npc_escortAI*)(pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); - - return true; // prevent Trinity core handling - } - return false; -} - -void AddSC_test() -{ - Script *newscript; - newscript = new Script; - newscript->Name="test"; - newscript->GetAI = &GetAI_test; - newscript->pGossipHello = &GossipHello_npc_test; - newscript->pGossipSelect = &GossipSelect_npc_test; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/alterac_mountains.cpp b/src/server/scripts/eastern_kingdoms/alterac_mountains.cpp deleted file mode 100644 index 8695a73131c..00000000000 --- a/src/server/scripts/eastern_kingdoms/alterac_mountains.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Alterac_Mountains -SD%Complete: 0 -SDComment: Placeholder -SDCategory: Alterac Mountains -EndScriptData */ - -/* ContentData -EndContentData */ - -#include "ScriptedPch.h" - -/*void AddSC_alterac_mountains() -{ - Script *newscript; -}*/ diff --git a/src/server/scripts/eastern_kingdoms/alterac_valley/alterac_valley.cpp b/src/server/scripts/eastern_kingdoms/alterac_valley/alterac_valley.cpp deleted file mode 100644 index a61fc21d5ba..00000000000 --- a/src/server/scripts/eastern_kingdoms/alterac_valley/alterac_valley.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_CHARGE = 22911, - SPELL_CLEAVE = 40504, - SPELL_DEMORALIZING_SHOUT = 23511, - SPELL_ENRAGE = 8599, - SPELL_WHIRLWIND1 = 15589, - SPELL_WHIRLWIND2 = 13736, - SPELL_NORTH_MARSHAL = 45828, - SPELL_SOUTH_MARSHAL = 45829, - SPELL_STONEHEARTH_MARSHAL = 45830, - SPELL_ICEWING_MARSHAL = 45831, - SPELL_ICEBLOOD_WARMASTER = 45822, - SPELL_TOWER_POINT_WARMASTER = 45823, - SPELL_WEST_FROSTWOLF_WARMASTER = 45824, - SPELL_EAST_FROSTWOLF_WARMASTER = 45826 -}; - -enum Creatures -{ - NPC_NORTH_MARSHAL = 14762, - NPC_SOUTH_MARSHAL = 14763, - NPC_ICEWING_MARSHAL = 14764, - NPC_STONEHEARTH_MARSHAL = 14765, - NPC_EAST_FROSTWOLF_WARMASTER = 14772, - NPC_ICEBLOOD_WARMASTER = 14773, - NPC_TOWER_POINT_WARMASTER = 14776, - NPC_WEST_FROSTWOLF_WARMASTER = 14777 -}; - -struct mob_av_marshal_or_warmasterAI : public ScriptedAI -{ - mob_av_marshal_or_warmasterAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiChargeTimer; - uint32 uiCleaveTimer; - uint32 uiDemoralizingShoutTimer; - uint32 uiWhirlwind1Timer; - uint32 uiWhirlwind2Timer; - uint32 uiEnrageTimer; - uint32 uiResetTimer; - - bool bHasAura; - - void Reset() - { - uiChargeTimer = urand(2*IN_MILISECONDS,12*IN_MILISECONDS); - uiCleaveTimer = urand(1*IN_MILISECONDS,11*IN_MILISECONDS); - uiDemoralizingShoutTimer = urand(2*IN_MILISECONDS,2*IN_MILISECONDS); - uiWhirlwind1Timer = urand(1*IN_MILISECONDS,12*IN_MILISECONDS); - uiWhirlwind2Timer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); - uiEnrageTimer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); - uiResetTimer = 5*IN_MILISECONDS; - - bHasAura = false; - } - - void JustRespawned() - { - Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!bHasAura) - { - switch(me->GetEntry()) - { - case NPC_NORTH_MARSHAL: - DoCast(me,SPELL_NORTH_MARSHAL); - break; - case NPC_SOUTH_MARSHAL: - DoCast(me,SPELL_SOUTH_MARSHAL); - break; - case NPC_STONEHEARTH_MARSHAL: - DoCast(me,SPELL_STONEHEARTH_MARSHAL); - break; - case NPC_ICEWING_MARSHAL: - DoCast(me,SPELL_ICEWING_MARSHAL); - break; - case NPC_EAST_FROSTWOLF_WARMASTER: - DoCast(me,SPELL_EAST_FROSTWOLF_WARMASTER); - break; - case NPC_WEST_FROSTWOLF_WARMASTER: - DoCast(me,SPELL_WEST_FROSTWOLF_WARMASTER); - break; - case NPC_ICEBLOOD_WARMASTER: - DoCast(me,SPELL_ICEBLOOD_WARMASTER); - break; - case NPC_TOWER_POINT_WARMASTER: - DoCast(me,SPELL_TOWER_POINT_WARMASTER); - break; - } - - bHasAura = true; - } - - if (!UpdateVictim()) - return; - - if (uiChargeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CHARGE); - uiChargeTimer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiChargeTimer -= diff; - - if (uiCleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = urand(10*IN_MILISECONDS,16*IN_MILISECONDS); - } else uiCleaveTimer -= diff; - - if (uiDemoralizingShoutTimer <= diff) - { - DoCast(me->getVictim(), SPELL_DEMORALIZING_SHOUT); - uiDemoralizingShoutTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiDemoralizingShoutTimer -= diff; - - if (uiWhirlwind1Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND1); - uiWhirlwind1Timer = urand(6*IN_MILISECONDS,20*IN_MILISECONDS); - } else uiWhirlwind1Timer -= diff; - - if (uiWhirlwind2Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND2); - uiWhirlwind2Timer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiWhirlwind2Timer -= diff; - - if (uiEnrageTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ENRAGE); - uiEnrageTimer = urand(10*IN_MILISECONDS,30*IN_MILISECONDS); - }else uiEnrageTimer -= diff; - - - // check if creature is not outside of building - if (uiResetTimer <= diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - EnterEvadeMode(); - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_av_marshal_or_warmaster(Creature *_Creature) -{ - return new mob_av_marshal_or_warmasterAI (_Creature); -} - -void AddSC_alterac_valley() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_av_marshal_or_warmaster"; - newscript->GetAI = &GetAI_mob_av_marshal_or_warmaster; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/alterac_valley/boss_balinda.cpp b/src/server/scripts/eastern_kingdoms/alterac_valley/boss_balinda.cpp deleted file mode 100644 index ce2a81c864a..00000000000 --- a/src/server/scripts/eastern_kingdoms/alterac_valley/boss_balinda.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_ARCANE_EXPLOSION = 46608, - SPELL_CONE_OF_COLD = 38384, - SPELL_FIREBALL = 46988, - SPELL_FROSTBOLT = 46987 -}; - -enum Yells -{ - YELL_AGGRO = -2100019, - YELL_EVADE = -2100020 -}; - -enum Creatures -{ - NPC_WATER_ELEMENTAL = 25040 -}; - -enum WaterElementalSpells -{ - SPELL_WATERBOLT = 46983 -}; - -struct mob_water_elementalAI : public ScriptedAI -{ - mob_water_elementalAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWaterBoltTimer; - uint64 uiBalindaGUID; - uint32 uiResetTimer; - - void Reset() - { - uiWaterBoltTimer = 3*IN_MILISECONDS; - uiResetTimer = 5*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWaterBoltTimer < diff) - { - DoCast(me->getVictim(), SPELL_WATERBOLT); - uiWaterBoltTimer = 5*IN_MILISECONDS; - } else uiWaterBoltTimer -= diff; - - // check if creature is not outside of building - if (uiResetTimer < diff) - { - if (Creature *pBalinda = Unit::GetCreature(*me, uiBalindaGUID)) - if (me->GetDistance2d(pBalinda->GetHomePosition().GetPositionX(), pBalinda->GetHomePosition().GetPositionY()) > 50) - EnterEvadeMode(); - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_balindaAI : public ScriptedAI -{ - boss_balindaAI(Creature *c) : ScriptedAI(c), Summons(me) {} - - uint32 uiArcaneExplosionTimer; - uint32 uiConeOfColdTimer; - uint32 uiFireBoltTimer; - uint32 uiFrostboltTimer; - uint32 uiResetTimer; - uint32 uiWaterElementalTimer; - - SummonList Summons; - - void Reset() - { - uiArcaneExplosionTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); - uiConeOfColdTimer = 8*IN_MILISECONDS; - uiFireBoltTimer = 1*IN_MILISECONDS; - uiFrostboltTimer = 4*IN_MILISECONDS; - uiResetTimer = 5*IN_MILISECONDS; - uiWaterElementalTimer = 0; - - Summons.DespawnAll(); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - } - - void JustRespawned() - { - Reset(); - } - - void JustSummoned(Creature* summoned) - { - ((mob_water_elementalAI*)summoned->AI())->uiBalindaGUID = me->GetGUID(); - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); - summoned->setFaction(me->getFaction()); - Summons.Summon(summoned); - } - - void JustDied(Unit* /*Killer*/) - { - Summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWaterElementalTimer < diff) - { - if (Summons.empty()) - me->SummonCreature(NPC_WATER_ELEMENTAL, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45*IN_MILISECONDS); - uiWaterElementalTimer = 50*IN_MILISECONDS; - } else uiWaterElementalTimer -= diff; - - if (uiArcaneExplosionTimer < diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); - uiArcaneExplosionTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiArcaneExplosionTimer -= diff; - - if (uiConeOfColdTimer < diff) - { - DoCast(me->getVictim(), SPELL_CONE_OF_COLD); - uiConeOfColdTimer = urand(10*IN_MILISECONDS,20*IN_MILISECONDS); - } else uiConeOfColdTimer -= diff; - - if (uiFireBoltTimer < diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL); - uiFireBoltTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); - } else uiFireBoltTimer -= diff; - - if (uiFrostboltTimer < diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - uiFrostboltTimer = urand(4*IN_MILISECONDS,12*IN_MILISECONDS); - } else uiFrostboltTimer -= diff; - - - // check if creature is not outside of building - if (uiResetTimer < diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - { - EnterEvadeMode(); - DoScriptText(YELL_EVADE, me); - } - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_balinda(Creature *_Creature) -{ - return new boss_balindaAI (_Creature); -} - -CreatureAI* GetAI_mob_water_elemental(Creature *_Creature) -{ - return new mob_water_elementalAI (_Creature); -} - -void AddSC_boss_balinda() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_balinda"; - newscript->GetAI = &GetAI_boss_balinda; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_water_elemental"; - newscript->GetAI = &GetAI_mob_water_elemental; - newscript->RegisterSelf(); -}; \ No newline at end of file diff --git a/src/server/scripts/eastern_kingdoms/alterac_valley/boss_drekthar.cpp b/src/server/scripts/eastern_kingdoms/alterac_valley/boss_drekthar.cpp deleted file mode 100644 index 6477ebe5eaf..00000000000 --- a/src/server/scripts/eastern_kingdoms/alterac_valley/boss_drekthar.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_WHIRLWIND = 15589, - SPELL_WHIRLWIND2 = 13736, - SPELL_KNOCKDOWN = 19128, - SPELL_FRENZY = 8269, - SPELL_SWEEPING_STRIKES = 18765, // not sure - SPELL_CLEAVE = 20677, // not sure - SPELL_WINDFURY = 35886, // not sure - SPELL_STORMPIKE = 51876 // not sure -}; - -enum Yells -{ - YELL_AGGRO = -1810000, - YELL_EVADE = -1810001, - YELL_RESPAWN = -1810002, - YELL_RANDOM1 = -1810003, - YELL_RANDOM2 = -1810004, - YELL_RANDOM3 = -1810005, - YELL_RANDOM4 = -1810006, - YELL_RANDOM5 = -1810007 -}; - -struct boss_drektharAI : public ScriptedAI -{ - boss_drektharAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWhirlwindTimer; - uint32 uiWhirlwind2Timer; - uint32 uiKnockdownTimer; - uint32 uiFrenzyTimer; - uint32 uiYellTimer; - uint32 uiResetTimer; - - void Reset() - { - uiWhirlwindTimer = urand(1*IN_MILISECONDS,20*IN_MILISECONDS); - uiWhirlwind2Timer = urand(1*IN_MILISECONDS,20*IN_MILISECONDS); - uiKnockdownTimer = 12*IN_MILISECONDS; - uiFrenzyTimer = 6*IN_MILISECONDS; - uiResetTimer = 5*IN_MILISECONDS; - uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds - } - - void Aggro(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - } - - void JustRespawned() - { - Reset(); - DoScriptText(YELL_RESPAWN, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWhirlwindTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - uiWhirlwindTimer = urand(8*IN_MILISECONDS,18*IN_MILISECONDS); - } else uiWhirlwindTimer -= diff; - - if (uiWhirlwind2Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND2); - uiWhirlwind2Timer = urand(7*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiWhirlwind2Timer -= diff; - - if (uiKnockdownTimer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - uiKnockdownTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiKnockdownTimer -= diff; - - if (uiFrenzyTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FRENZY); - uiFrenzyTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiFrenzyTimer -= diff; - - if (uiYellTimer <= diff) - { - DoScriptText(RAND(YELL_RANDOM1,YELL_RANDOM2,YELL_RANDOM3,YELL_RANDOM4,YELL_RANDOM5), me); - uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds - } else uiYellTimer -= diff; - - // check if creature is not outside of building - if (uiResetTimer <= diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - { - EnterEvadeMode(); - DoScriptText(YELL_EVADE, me); - } - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - - -CreatureAI* GetAI_boss_drekthar(Creature *_Creature) -{ - return new boss_drektharAI (_Creature); -} - -void AddSC_boss_drekthar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_drekthar"; - newscript->GetAI = &GetAI_boss_drekthar; - newscript->RegisterSelf(); -} \ No newline at end of file diff --git a/src/server/scripts/eastern_kingdoms/alterac_valley/boss_galvangar.cpp b/src/server/scripts/eastern_kingdoms/alterac_valley/boss_galvangar.cpp deleted file mode 100644 index a12b9f267f9..00000000000 --- a/src/server/scripts/eastern_kingdoms/alterac_valley/boss_galvangar.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_CLEAVE = 15284, - SPELL_FRIGHTENING_SHOUT = 19134, - SPELL_WHIRLWIND1 = 15589, - SPELL_WHIRLWIND2 = 13736, - SPELL_MORTAL_STRIKE = 16856 -}; - -enum Yells -{ - YELL_AGGRO = -1810021, - YELL_EVADE = -1810022 -}; - -struct boss_galvangarAI : public ScriptedAI -{ - boss_galvangarAI(Creature *c) : ScriptedAI(c) {} - - - uint32 uiCleaveTimer; - uint32 uiFrighteningShoutTimer; - uint32 uiWhirlwind1Timer; - uint32 uiWhirlwind2Timer; - uint32 uiMortalStrikeTimer; - uint32 uiResetTimer; - - - void Reset() - { - uiCleaveTimer = urand(1*IN_MILISECONDS,9*IN_MILISECONDS); - uiFrighteningShoutTimer = urand(2*IN_MILISECONDS,19*IN_MILISECONDS); - uiWhirlwind1Timer = urand(1*IN_MILISECONDS,13*IN_MILISECONDS); - uiWhirlwind2Timer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); - uiMortalStrikeTimer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); - uiResetTimer = 5*IN_MILISECONDS; - } - - void Aggro(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - } - - void JustRespawned() - { - Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiCleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = urand(10*IN_MILISECONDS,16*IN_MILISECONDS); - } else uiCleaveTimer -= diff; - - if (uiFrighteningShoutTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); - uiFrighteningShoutTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiFrighteningShoutTimer -= diff; - - if (uiWhirlwind1Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND1); - uiWhirlwind1Timer = urand(6*IN_MILISECONDS,10*IN_MILISECONDS); - } else uiWhirlwind1Timer -= diff; - - if (uiWhirlwind2Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND2); - uiWhirlwind2Timer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiWhirlwind2Timer -= diff; - - if (uiMortalStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - uiMortalStrikeTimer = urand(10*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiMortalStrikeTimer -= diff; - - // check if creature is not outside of building - if (uiResetTimer <= diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - { - EnterEvadeMode(); - DoScriptText(YELL_EVADE, me); - } - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_galvangar(Creature *_Creature) -{ - return new boss_galvangarAI (_Creature); -} - -void AddSC_boss_galvangar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_galvangar"; - newscript->GetAI = &GetAI_boss_galvangar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/alterac_valley/boss_vanndar.cpp b/src/server/scripts/eastern_kingdoms/alterac_valley/boss_vanndar.cpp deleted file mode 100644 index 785827bc5d9..00000000000 --- a/src/server/scripts/eastern_kingdoms/alterac_valley/boss_vanndar.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -enum Yells -{ - YELL_AGGRO = -1810008, - YELL_EVADE = -1810009, - YELL_RESPAWN1 = -1810010, - YELL_RESPAWN2 = -1810011, - YELL_RANDOM1 = -1810012, - YELL_RANDOM2 = -1810013, - YELL_RANDOM3 = -1810014, - YELL_RANDOM4 = -1810015, - YELL_RANDOM5 = -1810016, - YELL_RANDOM6 = -1810017, - YELL_RANDOM7 = -1810018 -}; - -enum Spells -{ - SPELL_AVATAR = 19135, - SPELL_THUNDERCLAP = 15588, - SPELL_STORMBOLT = 20685 // not sure -}; - -struct boss_vanndarAI : public ScriptedAI -{ - boss_vanndarAI(Creature *c) : ScriptedAI(c) {} - - - uint32 uiAvatarTimer; - uint32 uiThunderclapTimer; - uint32 uiStormboltTimer; - uint32 uiResetTimer; - uint32 uiYellTimer; - - - void Reset() - { - uiAvatarTimer = 3*IN_MILISECONDS; - uiThunderclapTimer = 4*IN_MILISECONDS; - uiStormboltTimer = 6*IN_MILISECONDS; - uiResetTimer = 5*IN_MILISECONDS; - uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } - - void Aggro(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - } - - void JustRespawned() - { - Reset(); - DoScriptText(RAND(YELL_RESPAWN1,YELL_RESPAWN2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiAvatarTimer <= diff) - { - DoCast(me->getVictim(), SPELL_AVATAR); - uiAvatarTimer = urand(15*IN_MILISECONDS,20*IN_MILISECONDS); - } else uiAvatarTimer -= diff; - - if (uiThunderclapTimer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - uiThunderclapTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiThunderclapTimer -= diff; - - if (uiStormboltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STORMBOLT); - uiStormboltTimer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiStormboltTimer -= diff; - - if (uiYellTimer <= diff) - { - DoScriptText(RAND(YELL_RANDOM1,YELL_RANDOM2,YELL_RANDOM3,YELL_RANDOM4,YELL_RANDOM5,YELL_RANDOM6,YELL_RANDOM7), me); - uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds - } else uiYellTimer -= diff; - - // check if creature is not outside of building - if (uiResetTimer <= diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - { - EnterEvadeMode(); - DoScriptText(YELL_EVADE, me); - } - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vanndar(Creature *_Creature) -{ - return new boss_vanndarAI (_Creature); -} - -void AddSC_boss_vanndar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vanndar"; - newscript->GetAI = &GetAI_boss_vanndar; - newscript->RegisterSelf(); -} \ No newline at end of file diff --git a/src/server/scripts/eastern_kingdoms/arathi_highlands.cpp b/src/server/scripts/eastern_kingdoms/arathi_highlands.cpp deleted file mode 100644 index 86edbc2ed9d..00000000000 --- a/src/server/scripts/eastern_kingdoms/arathi_highlands.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Arathi Highlands -SD%Complete: 100 -SDComment: Quest support: 665 -SDCategory: Arathi Highlands -EndScriptData */ - -/* ContentData -npc_professor_phizzlethorpe -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_professor_phizzlethorpe -######*/ - -enum eEnums -{ - SAY_PROGRESS_1 = -1000264, - SAY_PROGRESS_2 = -1000265, - SAY_PROGRESS_3 = -1000266, - EMOTE_PROGRESS_4 = -1000267, - SAY_AGGRO = -1000268, - SAY_PROGRESS_5 = -1000269, - SAY_PROGRESS_6 = -1000270, - SAY_PROGRESS_7 = -1000271, - EMOTE_PROGRESS_8 = -1000272, - SAY_PROGRESS_9 = -1000273, - - QUEST_SUNKEN_TREASURE = 665, - MOB_VENGEFUL_SURGE = 2776 -}; - -struct npc_professor_phizzlethorpeAI : public npc_escortAI -{ - npc_professor_phizzlethorpeAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 uiPointId) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(uiPointId) - { - case 4:DoScriptText(SAY_PROGRESS_2, me, pPlayer);break; - case 5:DoScriptText(SAY_PROGRESS_3, me, pPlayer);break; - case 8:DoScriptText(EMOTE_PROGRESS_4, me);break; - case 9: - { - me->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96, -2142.49, 20.15, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - me->SummonCreature(MOB_VENGEFUL_SURGE, -2052.96, -2142.49, 20.15, 1.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - break; - } - case 10:DoScriptText(SAY_PROGRESS_5, me, pPlayer);break; - case 11: - DoScriptText(SAY_PROGRESS_6, me, pPlayer); - SetRun(); - break; - case 19:DoScriptText(SAY_PROGRESS_7, me, pPlayer); break; - case 20: - DoScriptText(EMOTE_PROGRESS_8, me); - DoScriptText(SAY_PROGRESS_9, me, pPlayer); - if (pPlayer) - CAST_PLR(pPlayer)->GroupEventHappens(QUEST_SUNKEN_TREASURE, me); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->AI()->AttackStart(me); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - } -}; - -bool QuestAccept_npc_professor_phizzlethorpe(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_SUNKEN_TREASURE) - { - DoScriptText(SAY_PROGRESS_1, pCreature, pPlayer); - if (npc_escortAI* pEscortAI = CAST_AI(npc_professor_phizzlethorpeAI, (pCreature->AI()))) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); - - pCreature->setFaction(113); - } - return true; -} - -CreatureAI* GetAI_npc_professor_phizzlethorpeAI(Creature* pCreature) -{ - return new npc_professor_phizzlethorpeAI(pCreature); -} - -void AddSC_arathi_highlands() -{ - Script * newscript; - - newscript = new Script; - newscript->Name = "npc_professor_phizzlethorpe"; - newscript->GetAI = &GetAI_npc_professor_phizzlethorpeAI; - newscript->pQuestAccept = &QuestAccept_npc_professor_phizzlethorpe; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp deleted file mode 100644 index e04fa8444b2..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp +++ /dev/null @@ -1,1338 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Blackrock_Depths -SD%Complete: 95 -SDComment: Quest support: 4001, 4342, 7604, 4322. Vendor Lokhtos Darkbargainer. Need to rewrite the Jail Break support -SDCategory: Blackrock Depths -EndScriptData */ - -/* ContentData -go_shadowforge_brazier -at_ring_of_law -npc_grimstone -mob_phalanx -npc_kharan_mighthammer -npc_lokhtos_darkbargainer -npc_dughal_stormwing -npc_marshal_windsor -npc_marshal_reginald_windsor -npc_tobias_seecher -npc_rocknot -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "blackrock_depths.h" - -/*###### -+## go_shadowforge_brazier -+######*/ - -bool GOHello_go_shadowforge_brazier(Player* /*pPlayer*/, GameObject* pGo) -{ - if (ScriptedInstance* pInstance = pGo->GetInstanceData()) - { - if (pInstance->GetData(TYPE_LYCEUM) == IN_PROGRESS) - pInstance->SetData(TYPE_LYCEUM, DONE); - else - pInstance->SetData(TYPE_LYCEUM, IN_PROGRESS); - // If used brazier open linked doors (North or South) - if (pGo->GetGUID() == pInstance->GetData64(DATA_SF_BRAZIER_N)) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GOLEM_DOOR_N), true); - else if (pGo->GetGUID() == pInstance->GetData64(DATA_SF_BRAZIER_S)) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GOLEM_DOOR_S), true); - } - return false; -} - -/*###### -## npc_grimstone -######*/ - -enum eGrimstone -{ - NPC_GRIMSTONE = 10096, - NPC_THELDREN = 16059, - - //4 or 6 in total? 1+2+1 / 2+2+2 / 3+3. Depending on this, code should be changed. - MAX_MOB_AMOUNT = 4 -}; - -uint32 RingMob[]= -{ - 8925, // Dredge Worm - 8926, // Deep Stinger - 8927, // Dark Screecher - 8928, // Burrowing Thundersnout - 8933, // Cave Creeper - 8932, // Borer Beetle -}; - -uint32 RingBoss[]= -{ - 9027, // Gorosh - 9028, // Grizzle - 9029, // Eviscerator - 9030, // Ok'thor - 9031, // Anub'shiah - 9032, // Hedrum -}; - -bool AreaTrigger_at_ring_of_law(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - if (ScriptedInstance* pInstance = pPlayer->GetInstanceData()) - { - if (pInstance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || pInstance->GetData(TYPE_RING_OF_LAW) == DONE) - return false; - - pInstance->SetData(TYPE_RING_OF_LAW,IN_PROGRESS); - pPlayer->SummonCreature(NPC_GRIMSTONE,625.559,-205.618,-52.735,2.609,TEMPSUMMON_DEAD_DESPAWN,0); - - return false; - } - return false; -} - -/*###### -## npc_grimstone -######*/ - -enum GrimstoneTexts -{ - SCRIPT_TEXT1 = -1000000, - SCRIPT_TEXT2 = -1000001, - SCRIPT_TEXT3 = -1000002, - SCRIPT_TEXT4 = -1000003, - SCRIPT_TEXT5 = -1000004, - SCRIPT_TEXT6 = -1000005 -}; - -//TODO: implement quest part of event (different end boss) -struct npc_grimstoneAI : public npc_escortAI -{ - npc_grimstoneAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - MobSpawnId = rand()%6; - } - - ScriptedInstance* pInstance; - - uint8 EventPhase; - uint32 Event_Timer; - - uint8 MobSpawnId; - uint8 MobCount; - uint32 MobDeath_Timer; - - uint64 RingMobGUID[4]; - uint64 RingBossGUID; - - bool CanWalk; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - EventPhase = 0; - Event_Timer = 1000; - - MobCount = 0; - MobDeath_Timer = 0; - - for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) - RingMobGUID[i] = 0; - - RingBossGUID = 0; - - CanWalk = false; - } - - //TODO: move them to center - void SummonRingMob() - { - if (Creature* tmp = me->SummonCreature(RingMob[MobSpawnId],608.960,-235.322,-53.907,1.857,TEMPSUMMON_DEAD_DESPAWN,0)) - RingMobGUID[MobCount] = tmp->GetGUID(); - - ++MobCount; - - if (MobCount == MAX_MOB_AMOUNT) - MobDeath_Timer = 2500; - } - - //TODO: move them to center - void SummonRingBoss() - { - if (Creature* tmp = me->SummonCreature(RingBoss[rand()%6],644.300,-175.989,-53.739,3.418,TEMPSUMMON_DEAD_DESPAWN,0)) - RingBossGUID = tmp->GetGUID(); - - MobDeath_Timer = 2500; - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 0: - DoScriptText(SCRIPT_TEXT1, me);//2 - CanWalk = false; - Event_Timer = 5000; - break; - case 1: - DoScriptText(SCRIPT_TEXT2, me);//4 - CanWalk = false; - Event_Timer = 5000; - break; - case 2: - CanWalk = false; - break; - case 3: - DoScriptText(SCRIPT_TEXT3, me);//5 - break; - case 4: - DoScriptText(SCRIPT_TEXT4, me);//6 - CanWalk = false; - Event_Timer = 5000; - break; - case 5: - if (pInstance) - { - pInstance->SetData(TYPE_RING_OF_LAW,DONE); - debug_log("TSCR: npc_grimstone: event reached end and set complete."); - } - break; - } - } - - void HandleGameObject(uint32 id, bool open) - { - pInstance->HandleGameObject(pInstance->GetData64(id), open); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (MobDeath_Timer) - { - if (MobDeath_Timer <= diff) - { - MobDeath_Timer = 2500; - - if (RingBossGUID) - { - Creature *boss = Unit::GetCreature(*me,RingBossGUID); - if (boss && !boss->isAlive() && boss->isDead()) - { - RingBossGUID = 0; - Event_Timer = 5000; - MobDeath_Timer = 0; - return; - } - return; - } - - for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) - { - Creature *mob = Unit::GetCreature(*me,RingMobGUID[i]); - if (mob && !mob->isAlive() && mob->isDead()) - { - RingMobGUID[i] = 0; - --MobCount; - - //seems all are gone, so set timer to continue and discontinue this - if (!MobCount) - { - Event_Timer = 5000; - MobDeath_Timer = 0; - } - } - } - } else MobDeath_Timer -= diff; - } - - if (Event_Timer) - { - if (Event_Timer <= diff) - { - switch(EventPhase) - { - case 0: - DoScriptText(SCRIPT_TEXT5, me);//1 - HandleGameObject(DATA_ARENA4, false); - Start(false, false); - CanWalk = true; - Event_Timer = 0; - break; - case 1: - CanWalk = true; - Event_Timer = 0; - break; - case 2: - Event_Timer = 2000; - break; - case 3: - HandleGameObject(DATA_ARENA1, true); - Event_Timer = 3000; - break; - case 4: - CanWalk = true; - me->SetVisibility(VISIBILITY_OFF); - SummonRingMob(); - Event_Timer = 8000; - break; - case 5: - SummonRingMob(); - SummonRingMob(); - Event_Timer = 8000; - break; - case 6: - SummonRingMob(); - Event_Timer = 0; - break; - case 7: - me->SetVisibility(VISIBILITY_ON); - HandleGameObject(DATA_ARENA1, false); - DoScriptText(SCRIPT_TEXT6, me);//4 - CanWalk = true; - Event_Timer = 0; - break; - case 8: - HandleGameObject(DATA_ARENA2, true); - Event_Timer = 5000; - break; - case 9: - me->SetVisibility(VISIBILITY_OFF); - SummonRingBoss(); - Event_Timer = 0; - break; - case 10: - //if quest, complete - HandleGameObject(DATA_ARENA2, false); - HandleGameObject(DATA_ARENA3, true); - HandleGameObject(DATA_ARENA4, true); - CanWalk = true; - Event_Timer = 0; - break; - } - ++EventPhase; - } else Event_Timer -= diff; - } - - if (CanWalk) - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_grimstone(Creature* pCreature) -{ - return new npc_grimstoneAI(pCreature); -} - -/*###### -## mob_phalanx -######*/ - -enum PhalanxSpells -{ - SPELL_THUNDERCLAP = 8732, - SPELL_FIREBALLVOLLEY = 22425, - SPELL_MIGHTYBLOW = 14099 -}; - -struct mob_phalanxAI : public ScriptedAI -{ - mob_phalanxAI(Creature *c) : ScriptedAI(c) {} - - uint32 ThunderClap_Timer; - uint32 FireballVolley_Timer; - uint32 MightyBlow_Timer; - - void Reset() - { - ThunderClap_Timer = 12000; - FireballVolley_Timer =0; - MightyBlow_Timer = 15000; - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ThunderClap_Timer - if (ThunderClap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - ThunderClap_Timer = 10000; - } else ThunderClap_Timer -= diff; - - //FireballVolley_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - if (FireballVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALLVOLLEY); - FireballVolley_Timer = 15000; - } else FireballVolley_Timer -= diff; - } - - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTYBLOW); - MightyBlow_Timer = 10000; - } else MightyBlow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_mob_phalanx(Creature* pCreature) -{ - return new mob_phalanxAI (pCreature); -} - -/*###### -## npc_kharan_mighthammer -######*/ - -enum KharamQuests -{ - QUEST_4001 = 4001, - QUEST_4342 = 4342 -}; - -#define GOSSIP_ITEM_KHARAN_1 "I need to know where the princess are, Kharan!" -#define GOSSIP_ITEM_KHARAN_2 "All is not lost, Kharan!" - -#define GOSSIP_ITEM_KHARAN_3 "Gor'shak is my friend, you can trust me." -#define GOSSIP_ITEM_KHARAN_4 "Not enough, you need to tell me more." -#define GOSSIP_ITEM_KHARAN_5 "So what happened?" -#define GOSSIP_ITEM_KHARAN_6 "Continue..." -#define GOSSIP_ITEM_KHARAN_7 "So you suspect that someone on the inside was involved? That they were tipped off?" -#define GOSSIP_ITEM_KHARAN_8 "Continue with your story please." -#define GOSSIP_ITEM_KHARAN_9 "Indeed." -#define GOSSIP_ITEM_KHARAN_10 "The door is open, Kharan. You are a free man." - -bool GossipHello_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_4001) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - if (pPlayer->GetQuestStatus(4342) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - - if (pPlayer->GetTeam() == HORDE) - pPlayer->SEND_GOSSIP_MENU(2473, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(2474, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(2475, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(2476, pCreature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(2477, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(2478, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(2479, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - pPlayer->SEND_GOSSIP_MENU(2480, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); - pPlayer->SEND_GOSSIP_MENU(2481, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+8: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); - pPlayer->SEND_GOSSIP_MENU(2482, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+9: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pPlayer->GetTeam() == HORDE) - pPlayer->AreaExploredOrEventHappens(QUEST_4001); - else - pPlayer->AreaExploredOrEventHappens(QUEST_4342); - break; - } - return true; -} - -/*###### -## npc_lokhtos_darkbargainer -######*/ - -enum LokhtosItems -{ - ITEM_THRORIUM_BROTHERHOOD_CONTRACT = 18628, - ITEM_SULFURON_INGOT = 17203 -}; - -enum LokhtosQuests -{ - QUEST_A_BINDING_CONTRACT = 7604 -}; - -enum LokhtosSpells -{ - SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059 -}; - -#define GOSSIP_ITEM_SHOW_ACCESS "Show me what I have access to, Lothos." -#define GOSSIP_ITEM_GET_CONTRACT "Get Thorium Brotherhood Contract" - -bool GossipHello_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor() && pPlayer->GetReputationRank(59) >= REP_FRIENDLY) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_ITEM_SHOW_ACCESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - if (pPlayer->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 && - !pPlayer->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) && - pPlayer->HasItemCount(ITEM_SULFURON_INGOT, 1)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GET_CONTRACT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - } - - if (pPlayer->GetReputationRank(59) < REP_FRIENDLY) - pPlayer->SEND_GOSSIP_MENU(3673, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(3677, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false); - } - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_dughal_stormwing -######*/ - -enum DughalQuests -{ - QUEST_JAIL_BREAK = 4322 -}; - -#define SAY_DUGHAL_FREE "Thank you, $N! I'm free!!!" -#define GOSSIP_DUGHAL "You're free, Dughal! Get out of here!" - -/* -struct npc_dughal_stormwingAI : public npc_escortAI -{ - npc_dughal_stormwingAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - switch(i) - { - case 0:me->Say(SAY_DUGHAL_FREE, LANG_UNIVERSAL, PlayerGUID); break; - case 1:pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_OBJECTIVE_COMPLETED);break; - case 2: - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_ENDED); - break; - } - } - - void EnterCombat(Unit* who) {} - void Reset() {} - - void JustDied(Unit* killer) - { - if (IsBeingEscorted && killer == me) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_ENDED); - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_ENDED) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_dughal_stormwing(Creature* pCreature) -{ - npc_dughal_stormwingAI* dughal_stormwingAI = new npc_dughal_stormwingAI(pCreature); - - dughal_stormwingAI->AddWaypoint(0, 280.42,-82.86, -77.12,0); - dughal_stormwingAI->AddWaypoint(1, 287.64,-87.01, -76.79,0); - dughal_stormwingAI->AddWaypoint(2, 354.63,-64.95, -67.53,0); - - return dughal_stormwingAI; -} -bool GossipHello_npc_dughal_stormwing(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUGHAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2846, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_dughal_stormwing(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, true, pPlayer->GetGUID()); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_IN_PROGRESS); - } - return true; -} - */ -/*###### -## npc_marshal_windsor -######*/ - -#define SAY_WINDSOR_AGGRO1 "You locked up the wrong Marshal. Prepare to be destroyed!" -#define SAY_WINDSOR_AGGRO2 "I bet you're sorry now, aren't you !?!!" -#define SAY_WINDSOR_AGGRO3 "You better hold me back $N or they are going to feel some prison house beatings." -#define SAY_WINDSOR_1 "Let's get a move on. My gear should be in the storage area up this way..." -#define SAY_WINDSOR_4_1 "Check that cell, $N. If someone is alive in there, we need to get them out." -#define SAY_WINDSOR_4_2 "Get him out of there!" -#define SAY_WINDSOR_4_3 "Good work! We're almost there, $N. This way." -#define SAY_WINDSOR_6 "This is it, $N. My stuff should be in that room. Cover me, I'm going in!" -#define SAY_WINDSOR_9 "Ah, there it is!" -#define MOB_ENTRY_REGINALD_WINDSOR 9682 - -Player* pPlayerStart; -/* -struct npc_marshal_windsorAI : public npc_escortAI -{ - npc_marshal_windsorAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 1: - me->Say(SAY_WINDSOR_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 7: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_WINDSOR_4_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 10: - me->setFaction(534); - break; - case 12: - me->Say(SAY_WINDSOR_6, LANG_UNIVERSAL, PlayerGUID); - pInstance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_IN_PROGRESS); - break; - case 13: - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK - break; - case 14: - pInstance->SetData(DATA_GATE_SR,0); - me->setFaction(11); - break; - case 16: - me->Say(SAY_WINDSOR_9, LANG_UNIVERSAL, PlayerGUID); - break; - case 17: - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK - break; - case 18: - pInstance->SetData(DATA_GATE_SC,0); - break; - case 19: - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SummonCreature(MOB_ENTRY_REGINALD_WINDSOR,403.61,-51.71,-63.92,3.600434,TEMPSUMMON_DEAD_DESPAWN ,0); - pInstance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_ENDED); - break; - } - } - - void EnterCombat(Unit* who) - { - switch (urand(0,2)) - { - case 0: me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); break; - case 1: me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); break; - case 2: me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); break; - } - } - - void Reset() {} - - void JustDied(Unit *slayer) - { - pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_FAILED); - } - - void UpdateAI(const uint32 diff) - { - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if (pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) - SetEscortPaused(false); - if (!pInstance->GetData(DATA_GATE_D) && pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_NOT_STARTED) - { - me->Say(SAY_WINDSOR_4_2, LANG_UNIVERSAL, PlayerGUID); - pInstance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_BEFORE_START); - } - if (pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) - { - me->Say(SAY_WINDSOR_4_3, LANG_UNIVERSAL, PlayerGUID); - pInstance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); - } - if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_SUPPLY_ROOM) == ENCOUNTER_STATE_ENDED) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_marshal_windsor(Creature* pCreature) -{ - npc_marshal_windsorAI* marshal_windsorAI = new npc_marshal_windsorAI(pCreature); - - marshal_windsorAI->AddWaypoint(0, 316.336,-225.528, -77.7258,7000); - marshal_windsorAI->AddWaypoint(1, 316.336,-225.528, -77.7258,2000); - marshal_windsorAI->AddWaypoint(2, 322.96,-207.13, -77.87,0); - marshal_windsorAI->AddWaypoint(3, 281.05,-172.16, -75.12,0); - marshal_windsorAI->AddWaypoint(4, 272.19,-139.14, -70.61,0); - marshal_windsorAI->AddWaypoint(5, 283.62,-116.09, -70.21,0); - marshal_windsorAI->AddWaypoint(6, 296.18,-94.30, -74.08,0); - marshal_windsorAI->AddWaypoint(7, 294.57,-93.11, -74.08,0); - marshal_windsorAI->AddWaypoint(8, 314.31,-74.31, -76.09,0); - marshal_windsorAI->AddWaypoint(9, 360.22,-62.93, -66.77,0); - marshal_windsorAI->AddWaypoint(10, 383.38,-69.40, -63.25,0); - marshal_windsorAI->AddWaypoint(11, 389.99,-67.86, -62.57,0); - marshal_windsorAI->AddWaypoint(12, 400.98,-72.01, -62.31,0); - marshal_windsorAI->AddWaypoint(13, 404.22,-62.30, -63.50,2300); - marshal_windsorAI->AddWaypoint(14, 404.22,-62.30, -63.50,1500); - marshal_windsorAI->AddWaypoint(15, 407.65,-51.86, -63.96,0); - marshal_windsorAI->AddWaypoint(16, 403.61,-51.71, -63.92,1000); - marshal_windsorAI->AddWaypoint(17, 403.61,-51.71, -63.92,2000); - marshal_windsorAI->AddWaypoint(18, 403.61,-51.71, -63.92,1000); - marshal_windsorAI->AddWaypoint(19, 403.61,-51.71, -63.92,0); - - return marshal_windsorAI; -} - -bool QuestAccept_npc_marshal_windsor(Player* pPlayer, Creature* pCreature, Quest const *quest) -{ - if (quest->GetQuestId() == 4322) - {PlayerStart = player; - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - { - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_IN_PROGRESS); - pCreature->setFaction(11); - } - - } - return false; -} - */ -/*###### -## npc_marshal_reginald_windsor -######*/ - -#define SAY_REGINALD_WINDSOR_0_1 "Can you feel the power, $N??? It's time to ROCK!" -#define SAY_REGINALD_WINDSOR_0_2 "Now we just have to free Tobias and we can get out of here. This way!" -#define SAY_REGINALD_WINDSOR_5_1 "Open it." -#define SAY_REGINALD_WINDSOR_5_2 "I never did like those two. Let's get moving." -#define SAY_REGINALD_WINDSOR_7_1 "Open it and be careful this time!" -#define SAY_REGINALD_WINDSOR_7_2 "That intolerant dirtbag finally got what was coming to him. Good riddance!" -#define SAY_REGINALD_WINDSOR_7_3 "Alright, let's go." -#define SAY_REGINALD_WINDSOR_13_1 "Open it. We need to hurry up. I can smell those Dark Irons coming a mile away and I can tell you one thing, they're COMING!" -#define SAY_REGINALD_WINDSOR_13_2 "Administering fists of fury on Crest Killer!" -#define SAY_REGINALD_WINDSOR_13_3 "He has to be in the last cell. Unless... they killed him." -#define SAY_REGINALD_WINDSOR_14_1 "Get him out of there!" -#define SAY_REGINALD_WINDSOR_14_2 "Excellent work, $N. Let's find the exit. I think I know the way. Follow me!" -#define SAY_REGINALD_WINDSOR_20_1 "We made it!" -#define SAY_REGINALD_WINDSOR_20_2 "Meet me at Maxwell's encampment. We'll go over the next stages of the plan there and figure out a way to decode my tablets without the decryption ring." -#define MOB_ENTRY_SHILL_DINGER 9678 -#define MOB_ENTRY_CREST_KILLER 9680 - -int wp = 0; -/* -struct npc_marshal_reginald_windsorAI : public npc_escortAI -{ - npc_marshal_reginald_windsorAI(Creature *c) : npc_escortAI(c) - { - } - - void WaypointReached(uint32 i) - { - wp=i; - switch(i) - { - case 0: - me->setFaction(11); - me->Say(SAY_REGINALD_WINDSOR_0_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - me->Say(SAY_REGINALD_WINDSOR_0_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 7: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_5_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 8: - me->Say(SAY_REGINALD_WINDSOR_5_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 11: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_7_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 12: - me->Say(SAY_REGINALD_WINDSOR_7_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 13: - me->Say(SAY_REGINALD_WINDSOR_7_3, LANG_UNIVERSAL, PlayerGUID); - break; - case 20: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_13_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 21: - me->Say(SAY_REGINALD_WINDSOR_13_3, LANG_UNIVERSAL, PlayerGUID); - break; - case 23: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_14_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 24: - me->Say(SAY_REGINALD_WINDSOR_14_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 31: - me->Say(SAY_REGINALD_WINDSOR_20_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 32: - me->Say(SAY_REGINALD_WINDSOR_20_2, LANG_UNIVERSAL, PlayerGUID); - PlayerStart->GroupEventHappens(QUEST_JAIL_BREAK, me); - pInstance->SetData(DATA_SHILL, ENCOUNTER_STATE_ENDED); - break; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - if (who->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(who)->GetQuestStatus(4322) == QUEST_STATUS_INCOMPLETE) - { - float Radius = 10.0; - if (me->IsWithinDistInMap(who, Radius)) - { - SetEscortPaused(false); - Start(true, false, who->GetGUID()); - } - } - } - } - - void EnterCombat(Unit* who) - { - switch (urand(0,2)) - { - case 0: me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); break; - case 1: me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); break; - case 2: me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); break; - } - } - void Reset() {} - - void JustDied(Unit *slayer) - { - pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_FAILED); - } - - void UpdateAI(const uint32 diff) - { - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if (wp == 7) - { - if (!pInstance->GetData(DATA_GATE_J) && pInstance->GetData(DATA_JAZ) == ENCOUNTER_STATE_NOT_STARTED) - { - pInstance->SetData(DATA_CREATURE_JAZ,1); - pInstance->SetData(DATA_JAZ,ENCOUNTER_STATE_IN_PROGRESS); - } - if (pInstance->GetData(DATA_CREATURE_JAZ) && pInstance->GetData(DATA_CREATURE_OGRABISI) && pInstance->GetData(DATA_JAZ) == ENCOUNTER_STATE_IN_PROGRESS) - { - SetEscortPaused(false); - pInstance->SetData(DATA_JAZ,ENCOUNTER_STATE_ENDED); - } - } - else if (wp == 11) - { - if (!pInstance->GetData(DATA_GATE_S) && pInstance->GetData(DATA_SHILL) == ENCOUNTER_STATE_NOT_STARTED) - { - pInstance->SetData(DATA_CREATURE_SHILL,1); - pInstance->SetData(DATA_SHILL,ENCOUNTER_STATE_IN_PROGRESS); - } - if (pInstance->GetData(DATA_CREATURE_SHILL) && pInstance->GetData(DATA_SHILL) == ENCOUNTER_STATE_IN_PROGRESS) - { - pInstance->SetData(DATA_SHILL,ENCOUNTER_STATE_ENDED); - SetEscortPaused(false); - } - } - else if (wp == 20) - { - if (!pInstance->GetData(DATA_GATE_C) && pInstance->GetData(DATA_CREST) == ENCOUNTER_STATE_NOT_STARTED) - { - pInstance->SetData(DATA_CREATURE_CREST,1); - me->Say(SAY_REGINALD_WINDSOR_13_2, LANG_UNIVERSAL, PlayerGUID); - pInstance->SetData(DATA_CREST,ENCOUNTER_STATE_IN_PROGRESS); - } - if (pInstance->GetData(DATA_CREATURE_CREST) && pInstance->GetData(DATA_CREST) == ENCOUNTER_STATE_IN_PROGRESS) - { - SetEscortPaused(false); - pInstance->SetData(DATA_CREST,ENCOUNTER_STATE_ENDED); - } - } - if (pInstance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) SetEscortPaused(false); - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_marshal_reginald_windsor(Creature* pCreature) -{ - npc_marshal_reginald_windsorAI* marshal_reginald_windsorAI = new npc_marshal_reginald_windsorAI(pCreature); - - marshal_reginald_windsorAI->AddWaypoint(0, 403.61,-52.71, -63.92,4000); - marshal_reginald_windsorAI->AddWaypoint(1, 403.61,-52.71, -63.92,4000); - marshal_reginald_windsorAI->AddWaypoint(2, 406.33,-54.87, -63.95,0); - marshal_reginald_windsorAI->AddWaypoint(3, 407.99,-73.91, -62.26,0); - marshal_reginald_windsorAI->AddWaypoint(4, 557.03,-119.71, -61.83,0); - marshal_reginald_windsorAI->AddWaypoint(5, 573.40,-124.39, -65.07,0); - marshal_reginald_windsorAI->AddWaypoint(6, 593.91,-130.29, -69.25,0); - marshal_reginald_windsorAI->AddWaypoint(7, 593.21,-132.16, -69.25,0); - marshal_reginald_windsorAI->AddWaypoint(8, 593.21,-132.16, -69.25,3000); - marshal_reginald_windsorAI->AddWaypoint(9, 622.81,-135.55, -71.92,0); - marshal_reginald_windsorAI->AddWaypoint(10, 634.68,-151.29, -70.32,0); - marshal_reginald_windsorAI->AddWaypoint(11, 635.06,-153.25, -70.32,0); - marshal_reginald_windsorAI->AddWaypoint(12, 635.06,-153.25, -70.32,3000); - marshal_reginald_windsorAI->AddWaypoint(13, 635.06,-153.25, -70.32,1500); - marshal_reginald_windsorAI->AddWaypoint(14, 655.25,-172.39, -73.72,0); - marshal_reginald_windsorAI->AddWaypoint(15, 654.79,-226.30, -83.06,0); - marshal_reginald_windsorAI->AddWaypoint(16, 622.85,-268.85, -83.96,0); - marshal_reginald_windsorAI->AddWaypoint(17, 579.45,-275.56, -80.44,0); - marshal_reginald_windsorAI->AddWaypoint(18, 561.19,-266.85, -75.59,0); - marshal_reginald_windsorAI->AddWaypoint(19, 547.91,-253.92, -70.34,0); - marshal_reginald_windsorAI->AddWaypoint(20, 549.20,-252.40, -70.34,0); - marshal_reginald_windsorAI->AddWaypoint(21, 549.20,-252.40, -70.34,4000); - marshal_reginald_windsorAI->AddWaypoint(22, 555.33,-269.16, -74.40,0); - marshal_reginald_windsorAI->AddWaypoint(23, 554.31,-270.88, -74.40,0); - marshal_reginald_windsorAI->AddWaypoint(24, 554.31,-270.88, -74.40,4000); - marshal_reginald_windsorAI->AddWaypoint(25, 536.10,-249.60, -67.47,0); - marshal_reginald_windsorAI->AddWaypoint(26, 520.94,-216.65, -59.28,0); - marshal_reginald_windsorAI->AddWaypoint(27, 505.99,-148.74, -62.17,0); - marshal_reginald_windsorAI->AddWaypoint(28, 484.21,-56.24, -62.43,0); - marshal_reginald_windsorAI->AddWaypoint(29, 470.39,-6.01, -70.10,0); - marshal_reginald_windsorAI->AddWaypoint(30, 451.27,30.85, -70.07,0); - marshal_reginald_windsorAI->AddWaypoint(31, 452.45,29.85, -70.37,1500); - marshal_reginald_windsorAI->AddWaypoint(32, 452.45,29.85, -70.37,7000); - marshal_reginald_windsorAI->AddWaypoint(33, 452.45,29.85, -70.37,10000); - marshal_reginald_windsorAI->AddWaypoint(34, 451.27,31.85, -70.07,0); - - return marshal_reginald_windsorAI; -} -*/ -/*###### -## npc_tobias_seecher -######*/ - -#define SAY_TOBIAS_FREE "Thank you! I will run for safety immediately!" -/* -struct npc_tobias_seecherAI : public npc_escortAI -{ - npc_tobias_seecherAI(Creature *c) :npc_escortAI(c) {} - - void EnterCombat(Unit* who) {} - void Reset() {} - - void JustDied(Unit* killer) - { - if (IsBeingEscorted && killer == me) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_ENDED); - } - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 0:me->Say(SAY_TOBIAS_FREE, LANG_UNIVERSAL, PlayerGUID); break; - case 2: - pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_OBJECTIVE_COMPLETED);break; - case 4: - me->SetVisibility(VISIBILITY_OFF); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_ENDED); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_ENDED) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_tobias_seecher(Creature* pCreature) -{ - npc_tobias_seecherAI* tobias_seecherAI = new npc_tobias_seecherAI(pCreature); - - tobias_seecherAI->AddWaypoint(0, 549.21, -281.07, -75.27); - tobias_seecherAI->AddWaypoint(1, 554.39, -267.39, -73.68); - tobias_seecherAI->AddWaypoint(2, 533.59, -249.38, -67.04); - tobias_seecherAI->AddWaypoint(3, 519.44, -217.02, -59.34); - tobias_seecherAI->AddWaypoint(4, 506.55, -153.49, -62.34); - - return tobias_seecherAI; -} - -bool GossipHello_npc_tobias_seecher(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Get out of here, Tobias, you're free!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2847, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_tobias_seecher(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, true, pPlayer->GetGUID()); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_IN_PROGRESS); - } - return true; -} -*/ - -/*###### -## npc_rocknot -######*/ - -enum RocknotSays -{ - SAY_GOT_BEER = -1230000 -}; - -enum RocknotSpells -{ - SPELL_DRUNKEN_RAGE = 14872 -}; - -enum RocknotQuests -{ - QUEST_ALE = 4295 -}; - -struct npc_rocknotAI : public npc_escortAI -{ - npc_rocknotAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 BreakKeg_Timer; - uint32 BreakDoor_Timer; - - void Reset() - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - BreakKeg_Timer = 0; - BreakDoor_Timer = 0; - } - - void DoGo(uint32 id, uint32 state) - { - if (GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(id))) - pGo->SetGoState((GOState)state); - } - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch(i) - { - case 1: - me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - break; - case 2: - me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); - break; - case 3: - me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); - break; - case 4: - me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - break; - case 5: - me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - BreakKeg_Timer = 2000; - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (BreakKeg_Timer) - { - if (BreakKeg_Timer <= diff) - { - DoGo(DATA_GO_BAR_KEG,0); - BreakKeg_Timer = 0; - BreakDoor_Timer = 1000; - } else BreakKeg_Timer -= diff; - } - - if (BreakDoor_Timer) - { - if (BreakDoor_Timer <= diff) - { - DoGo(DATA_GO_BAR_DOOR,2); - DoGo(DATA_GO_BAR_KEG_TRAP,0); //doesn't work very well, leaving code here for future - //spell by trap has effect61, this indicate the bar go hostile - - if (Unit *tmp = Unit::GetUnit(*me,pInstance->GetData64(DATA_PHALANX))) - tmp->setFaction(14); - - //for later, this event(s) has alot more to it. - //optionally, DONE can trigger bar to go hostile. - pInstance->SetData(TYPE_BAR,DONE); - - BreakDoor_Timer = 0; - } else BreakDoor_Timer -= diff; - } - - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_rocknot(Creature* pCreature) -{ - return new npc_rocknotAI(pCreature); -} - -bool ChooseReward_npc_rocknot(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest, uint32 /*item*/) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (!pInstance) - return true; - - if (pInstance->GetData(TYPE_BAR) == DONE || pInstance->GetData(TYPE_BAR) == SPECIAL) - return true; - - if (_Quest->GetQuestId() == QUEST_ALE) - { - if (pInstance->GetData(TYPE_BAR) != IN_PROGRESS) - pInstance->SetData(TYPE_BAR,IN_PROGRESS); - - pInstance->SetData(TYPE_BAR,SPECIAL); - - //keep track of amount in instance script, returns SPECIAL if amount ok and event in progress - if (pInstance->GetData(TYPE_BAR) == SPECIAL) - { - DoScriptText(SAY_GOT_BEER, pCreature); - pCreature->CastSpell(pCreature,SPELL_DRUNKEN_RAGE,false); - if (npc_escortAI* pEscortAI = CAST_AI(npc_rocknotAI, pCreature->AI())) - pEscortAI->Start(false, false); - } - } - - return true; -} - -/*###### -## -######*/ - -void AddSC_blackrock_depths() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_shadowforge_brazier"; - newscript->pGOHello = &GOHello_go_shadowforge_brazier; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_ring_of_law"; - newscript->pAreaTrigger = &AreaTrigger_at_ring_of_law; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_grimstone"; - newscript->GetAI = &GetAI_npc_grimstone; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phalanx"; - newscript->GetAI = &GetAI_mob_phalanx; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_kharan_mighthammer"; - newscript->pGossipHello = &GossipHello_npc_kharan_mighthammer; - newscript->pGossipSelect = &GossipSelect_npc_kharan_mighthammer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lokhtos_darkbargainer"; - newscript->pGossipHello = &GossipHello_npc_lokhtos_darkbargainer; - newscript->pGossipSelect = &GossipSelect_npc_lokhtos_darkbargainer; - newscript->RegisterSelf(); -/* - newscript = new Script; - newscript->Name = "npc_dughal_stormwing"; - newscript->pGossipHello = &GossipHello_npc_dughal_stormwing; - newscript->pGossipSelect = &GossipSelect_npc_dughal_stormwing; - newscript->GetAI = &GetAI_npc_dughal_stormwing; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tobias_seecher"; - newscript->pGossipHello = &GossipHello_npc_tobias_seecher; - newscript->pGossipSelect = &GossipSelect_npc_tobias_seecher; - newscript->GetAI = &GetAI_npc_tobias_seecher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_marshal_windsor"; - newscript->pQuestAccept = &QuestAccept_npc_marshal_windsor; - newscript->GetAI = &GetAI_npc_marshal_windsor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_marshal_reginald_windsor"; - newscript->GetAI = &GetAI_npc_marshal_reginald_windsor; - newscript->RegisterSelf(); -*/ - newscript = new Script; - newscript->Name = "npc_rocknot"; - newscript->GetAI = &GetAI_npc_rocknot; - newscript->pChooseReward = &ChooseReward_npc_rocknot; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h b/src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h deleted file mode 100644 index edb340252b2..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BRD_H -#define DEF_BRD_H - -#define FACTION_NEUTRAL 734 -#define FACTION_HOSTILE 754 -#define FACTION_FRIEND 35 - -enum eTypes -{ - TYPE_RING_OF_LAW = 1, - TYPE_VAULT = 2, - TYPE_BAR = 3, - TYPE_TOMB_OF_SEVEN = 4, - TYPE_LYCEUM = 5, - TYPE_IRON_HALL = 6, - - DATA_EMPEROR = 10, - DATA_PHALANX = 11, - - DATA_ARENA1 = 12, - DATA_ARENA2 = 13, - DATA_ARENA3 = 14, - DATA_ARENA4 = 15, - - DATA_GO_BAR_KEG = 16, - DATA_GO_BAR_KEG_TRAP = 17, - DATA_GO_BAR_DOOR = 18, - DATA_GO_CHALICE = 19, - - DATA_GHOSTKILL = 20, - DATA_EVENSTARTER = 21, - - DATA_GOLEM_DOOR_N = 22, - DATA_GOLEM_DOOR_S = 23, - - DATA_THRONE_DOOR = 24, - - DATA_SF_BRAZIER_N = 25, - DATA_SF_BRAZIER_S = 26 -}; -#endif diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp deleted file mode 100644 index a387e816951..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ambassador_Flamelash -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_FIREBLAST = 15573 -}; - -struct boss_ambassador_flamelashAI : public ScriptedAI -{ - boss_ambassador_flamelashAI(Creature *c) : ScriptedAI(c) {} - - uint32 FireBlast_Timer; - uint32 Spirit_Timer; - - void Reset() - { - FireBlast_Timer = 2000; - Spirit_Timer = 24000; - } - - void EnterCombat(Unit * /*who*/) {} - - void SummonSpirits(Unit* victim) - { - if (Creature *Spirit = DoSpawnCreature(9178, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) - Spirit->AI()->AttackStart(victim); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FireBlast_Timer - if (FireBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBLAST); - FireBlast_Timer = 7000; - } else FireBlast_Timer -= diff; - - //Spirit_Timer - if (Spirit_Timer <= diff) - { - SummonSpirits(me->getVictim()); - SummonSpirits(me->getVictim()); - SummonSpirits(me->getVictim()); - SummonSpirits(me->getVictim()); - - Spirit_Timer = 30000; - } else Spirit_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ambassador_flamelash(Creature* pCreature) -{ - return new boss_ambassador_flamelashAI (pCreature); -} - -void AddSC_boss_ambassador_flamelash() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ambassador_flamelash"; - newscript->GetAI = &GetAI_boss_ambassador_flamelash; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp deleted file mode 100644 index 60e1dec236c..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Anubshiah -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_SHADOWBOLT = 17228, - SPELL_CURSEOFTONGUES = 15470, - SPELL_CURSEOFWEAKNESS = 17227, - SPELL_DEMONARMOR = 11735, - SPELL_ENVELOPINGWEB = 15471 -}; - -struct boss_anubshiahAI : public ScriptedAI -{ - boss_anubshiahAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowBolt_Timer; - uint32 CurseOfTongues_Timer; - uint32 CurseOfWeakness_Timer; - uint32 DemonArmor_Timer; - uint32 EnvelopingWeb_Timer; - - void Reset() - { - ShadowBolt_Timer = 7000; - CurseOfTongues_Timer = 24000; - CurseOfWeakness_Timer = 12000; - DemonArmor_Timer = 3000; - EnvelopingWeb_Timer = 16000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLT); - ShadowBolt_Timer = 7000; - } else ShadowBolt_Timer -= diff; - - //CurseOfTongues_Timer - if (CurseOfTongues_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CURSEOFTONGUES); - CurseOfTongues_Timer = 18000; - } else CurseOfTongues_Timer -= diff; - - //CurseOfWeakness_Timer - if (CurseOfWeakness_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); - CurseOfWeakness_Timer = 45000; - } else CurseOfWeakness_Timer -= diff; - - //DemonArmor_Timer - if (DemonArmor_Timer <= diff) - { - DoCast(me, SPELL_DEMONARMOR); - DemonArmor_Timer = 300000; - } else DemonArmor_Timer -= diff; - - //EnvelopingWeb_Timer - if (EnvelopingWeb_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ENVELOPINGWEB); - EnvelopingWeb_Timer = 12000; - } else EnvelopingWeb_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_anubshiah(Creature* pCreature) -{ - return new boss_anubshiahAI (pCreature); -} - -void AddSC_boss_anubshiah() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_anubshiah"; - newscript->GetAI = &GetAI_boss_anubshiah; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp deleted file mode 100644 index 29fe219d6ec..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Emperor_Dagran_Thaurissan -SD%Complete: 99 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Yells -{ - SAY_AGGRO = -1230001, - SAY_SLAY = -1230002 -}; - -enum Spells -{ - SPELL_HANDOFTHAURISSAN = 17492, - SPELL_AVATAROFFLAME = 15636 -}; - -struct boss_draganthaurissanAI : public ScriptedAI -{ - boss_draganthaurissanAI(Creature *c) : ScriptedAI(c) {} - - uint32 HandOfThaurissan_Timer; - uint32 AvatarOfFlame_Timer; - //uint32 Counter; - - void Reset() - { - HandOfThaurissan_Timer = 4000; - AvatarOfFlame_Timer = 25000; - //Counter= 0; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - me->CallForHelp(VISIBLE_RANGE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (HandOfThaurissan_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_HANDOFTHAURISSAN); - - //3 Hands of Thaurissan will be casted - //if (Counter < 3) - //{ - // HandOfThaurissan_Timer = 1000; - // ++Counter; - //} - //else - //{ - HandOfThaurissan_Timer = 5000; - //Counter = 0; - //} - } else HandOfThaurissan_Timer -= diff; - - //AvatarOfFlame_Timer - if (AvatarOfFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_AVATAROFFLAME); - AvatarOfFlame_Timer = 18000; - } else AvatarOfFlame_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_draganthaurissan(Creature* pCreature) -{ - return new boss_draganthaurissanAI (pCreature); -} - -void AddSC_boss_draganthaurissan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_emperor_dagran_thaurissan"; - newscript->GetAI = &GetAI_boss_draganthaurissan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp deleted file mode 100644 index 77d69263133..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_General_Angerforge -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_MIGHTYBLOW = 14099, - SPELL_HAMSTRING = 9080, - SPELL_CLEAVE = 20691 -}; - -struct boss_general_angerforgeAI : public ScriptedAI -{ - boss_general_angerforgeAI(Creature *c) : ScriptedAI(c) {} - - uint32 MightyBlow_Timer; - uint32 HamString_Timer; - uint32 Cleave_Timer; - uint32 Adds_Timer; - bool Medics; - - void Reset() - { - MightyBlow_Timer = 8000; - HamString_Timer = 12000; - Cleave_Timer = 16000; - Adds_Timer = 0; - Medics = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonAdds(Unit* victim) - { - if (Creature *SummonedAdd = DoSpawnCreature(8901, irand(-14,14), irand(-14,14), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedAdd->AI()->AttackStart(victim); - } - - void SummonMedics(Unit* victim) - { - if (Creature *SummonedMedic = DoSpawnCreature(8894, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedMedic->AI()->AttackStart(victim); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTYBLOW); - MightyBlow_Timer = 18000; - } else MightyBlow_Timer -= diff; - - //HamString_Timer - if (HamString_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - HamString_Timer = 15000; - } else HamString_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 9000; - } else Cleave_Timer -= diff; - - //Adds_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 21) - { - if (Adds_Timer <= diff) - { - // summon 3 Adds every 25s - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - - Adds_Timer = 25000; - } else Adds_Timer -= diff; - } - - //Summon Medics - if (!Medics && me->GetHealth()*100 / me->GetMaxHealth() < 21) - { - SummonMedics(me->getVictim()); - SummonMedics(me->getVictim()); - Medics = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_general_angerforge(Creature* pCreature) -{ - return new boss_general_angerforgeAI (pCreature); -} - -void AddSC_boss_general_angerforge() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_general_angerforge"; - newscript->GetAI = &GetAI_boss_general_angerforge; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp deleted file mode 100644 index 886bc3fc909..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gorosh_the_Dervish -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_WHIRLWIND = 15589, - SPELL_MORTALSTRIKE = 24573 -}; - -struct boss_gorosh_the_dervishAI : public ScriptedAI -{ - boss_gorosh_the_dervishAI(Creature *c) : ScriptedAI(c) {} - - uint32 WhirlWind_Timer; - uint32 MortalStrike_Timer; - - void Reset() - { - WhirlWind_Timer = 12000; - MortalStrike_Timer = 22000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //WhirlWind_Timer - if (WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - WhirlWind_Timer = 15000; - } else WhirlWind_Timer -= diff; - - //MortalStrike_Timer - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = 15000; - } else MortalStrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gorosh_the_dervish(Creature* pCreature) -{ - return new boss_gorosh_the_dervishAI (pCreature); -} - -void AddSC_boss_gorosh_the_dervish() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gorosh_the_dervish"; - newscript->GetAI = &GetAI_boss_gorosh_the_dervish; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp deleted file mode 100644 index d3551d38790..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grizzle -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Yells -{ - EMOTE_GENERIC_FRENZY_KILL = -1000001 -}; - -enum Spells -{ - SPELL_GROUNDTREMOR = 6524, - SPELL_FRENZY = 28371 -}; - -struct boss_grizzleAI : public ScriptedAI -{ - boss_grizzleAI(Creature *c) : ScriptedAI(c) {} - - uint32 GroundTremor_Timer; - uint32 Frenzy_Timer; - - void Reset() - { - GroundTremor_Timer = 12000; - Frenzy_Timer =0; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //GroundTremor_Timer - if (GroundTremor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GROUNDTREMOR); - GroundTremor_Timer = 8000; - } else GroundTremor_Timer -= diff; - - //Frenzy_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - if (Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); - - Frenzy_Timer = 15000; - } else Frenzy_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_grizzle(Creature* pCreature) -{ - return new boss_grizzleAI (pCreature); -} - -void AddSC_boss_grizzle() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grizzle"; - newscript->GetAI = &GetAI_boss_grizzle; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp deleted file mode 100644 index 2af203826a1..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_High_Interrogator_Gerstahn -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_SHADOWWORDPAIN = 10894, - SPELL_MANABURN = 10876, - SPELL_PSYCHICSCREAM = 8122, - SPELL_SHADOWSHIELD = 22417 -}; - -struct boss_high_interrogator_gerstahnAI : public ScriptedAI -{ - boss_high_interrogator_gerstahnAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowWordPain_Timer; - uint32 ManaBurn_Timer; - uint32 PsychicScream_Timer; - uint32 ShadowShield_Timer; - - void Reset() - { - ShadowWordPain_Timer = 4000; - ManaBurn_Timer = 14000; - PsychicScream_Timer = 32000; - ShadowShield_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SHADOWWORDPAIN); - ShadowWordPain_Timer = 7000; - } else ShadowWordPain_Timer -= diff; - - //ManaBurn_Timer - if (ManaBurn_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_MANABURN); - ManaBurn_Timer = 10000; - } else ManaBurn_Timer -= diff; - - //PsychicScream_Timer - if (PsychicScream_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PSYCHICSCREAM); - PsychicScream_Timer = 30000; - } else PsychicScream_Timer -= diff; - - //ShadowShield_Timer - if (ShadowShield_Timer <= diff) - { - DoCast(me, SPELL_SHADOWSHIELD); - ShadowShield_Timer = 25000; - } else ShadowShield_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_high_interrogator_gerstahn(Creature* pCreature) -{ - return new boss_high_interrogator_gerstahnAI (pCreature); -} - -void AddSC_boss_high_interrogator_gerstahn() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_high_interrogator_gerstahn"; - newscript->GetAI = &GetAI_boss_high_interrogator_gerstahn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp deleted file mode 100644 index 2a0cf9be133..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Magmus -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_FIERYBURST = 13900, - SPELL_WARSTOMP = 24375 -}; - -enum eEnums -{ - DATA_THRONE_DOOR = 24 // not id or guid of doors but number of enum in blackrock_depths.h -}; - -struct boss_magmusAI : public ScriptedAI -{ - boss_magmusAI(Creature *c) : ScriptedAI(c) {} - - uint32 FieryBurst_Timer; - uint32 WarStomp_Timer; - - void Reset() - { - FieryBurst_Timer = 5000; - WarStomp_Timer =0; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FieryBurst_Timer - if (FieryBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIERYBURST); - FieryBurst_Timer = 6000; - } else FieryBurst_Timer -= diff; - - //WarStomp_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - if (WarStomp_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WARSTOMP); - WarStomp_Timer = 8000; - } else WarStomp_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - // When he die open door to last chamber - void JustDied(Unit *who) - { - if (ScriptedInstance* pInstance = who->GetInstanceData()) - pInstance->HandleGameObject(pInstance->GetData64(DATA_THRONE_DOOR), true); - } -}; -CreatureAI* GetAI_boss_magmus(Creature* pCreature) -{ - return new boss_magmusAI (pCreature); -} - -void AddSC_boss_magmus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magmus"; - newscript->GetAI = &GetAI_boss_magmus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_moira_bronzebeard.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_moira_bronzebeard.cpp deleted file mode 100644 index 1c0ed389287..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_moira_bronzebeard.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Moira_Bronzbeard -SD%Complete: 90 -SDComment: Healing of Emperor NYI -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_HEAL = 10917, - SPELL_RENEW = 10929, - SPELL_SHIELD = 10901, - SPELL_MINDBLAST = 10947, - SPELL_SHADOWWORDPAIN = 10894, - SPELL_SMITE = 10934 -}; - -struct boss_moira_bronzebeardAI : public ScriptedAI -{ - boss_moira_bronzebeardAI(Creature *c) : ScriptedAI(c) {} - - uint32 Heal_Timer; - uint32 MindBlast_Timer; - uint32 ShadowWordPain_Timer; - uint32 Smite_Timer; - - void Reset() - { - Heal_Timer = 12000; //These times are probably wrong - MindBlast_Timer = 16000; - ShadowWordPain_Timer = 2000; - Smite_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //MindBlast_Timer - if (MindBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MINDBLAST); - MindBlast_Timer = 14000; - } else MindBlast_Timer -= diff; - - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); - ShadowWordPain_Timer = 18000; - } else ShadowWordPain_Timer -= diff; - - //Smite_Timer - if (Smite_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SMITE); - Smite_Timer = 10000; - } else Smite_Timer -= diff; - - } -}; -CreatureAI* GetAI_boss_moira_bronzebeard(Creature* pCreature) -{ - return new boss_moira_bronzebeardAI (pCreature); -} - -void AddSC_boss_moira_bronzebeard() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_moira_bronzebeard"; - newscript->GetAI = &GetAI_boss_moira_bronzebeard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp deleted file mode 100644 index 94a37e8da7e..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Tomb_Of_Seven -SD%Complete: 90 -SDComment: Learning Smelt Dark Iron if tribute quest rewarded. Missing event. -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" -#include "blackrock_depths.h" - -enum Spells -{ - SPELL_SMELT_DARK_IRON = 14891, - SPELL_LEARN_SMELT = 14894, -}; - -enum Quests -{ - QUEST_SPECTRAL_CHALICE = 4083 -}; - -enum Misc -{ - DATA_SKILLPOINT_MIN = 230 -}; - -#define GOSSIP_ITEM_TEACH_1 "Teach me the art of smelting dark iron" -#define GOSSIP_ITEM_TEACH_2 "Continue..." -#define GOSSIP_ITEM_TEACH_3 "[PH] Continue..." -#define GOSSIP_ITEM_TRIBUTE "I want to pay tribute" - -bool GossipHello_boss_gloomrel(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 1 && pPlayer->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN && !pPlayer->HasSpell(SPELL_SMELT_DARK_IRON)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 0 && pPlayer->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TRIBUTE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_boss_gloomrel(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - pPlayer->SEND_GOSSIP_MENU(2606, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, SPELL_LEARN_SMELT, false); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); - pPlayer->SEND_GOSSIP_MENU(2604, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+22: - pPlayer->CLOSE_GOSSIP_MENU(); - if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) - { - //are 5 minutes expected? go template may have data to despawn when used at quest - pInstance->DoRespawnGameObject(pInstance->GetData64(DATA_GO_CHALICE),MINUTE*5); - } - break; - } - return true; -} - -enum DoomrelSpells -{ - SPELL_SHADOWBOLTVOLLEY = 15245, - SPELL_IMMOLATE = 12742, - SPELL_CURSEOFWEAKNESS = 12493, - SPELL_DEMONARMOR = 13787, - SPELL_SUMMON_VOIDWALKERS = 15092 -}; - -struct boss_doomrelAI : public ScriptedAI -{ - boss_doomrelAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 ShadowVolley_Timer; - uint32 Immolate_Timer; - uint32 CurseOfWeakness_Timer; - uint32 DemonArmor_Timer; - bool Voidwalkers; - - void Reset() - { - ShadowVolley_Timer = 10000; - Immolate_Timer = 18000; - CurseOfWeakness_Timer = 5000; - DemonArmor_Timer = 16000; - Voidwalkers = false; - - me->setFaction(FACTION_FRIEND); - - // was set before event start, so set again - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - - if (pInstance) - if (pInstance->GetData(DATA_GHOSTKILL) >= 7) - me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); - else - me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void EnterEvadeMode() - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->LoadCreaturesAddon(); - if (me->isAlive()) - me->GetMotionMaster()->MoveTargetedHome(); - me->SetLootRecipient(NULL); - if (pInstance) - pInstance->SetData64(DATA_EVENSTARTER, 0); - } - - void JustDied(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_GHOSTKILL, 1); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowVolley_Timer - if (ShadowVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLTVOLLEY); - ShadowVolley_Timer = 12000; - } else ShadowVolley_Timer -= diff; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_IMMOLATE); - - Immolate_Timer = 25000; - } else Immolate_Timer -= diff; - - //CurseOfWeakness_Timer - if (CurseOfWeakness_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); - CurseOfWeakness_Timer = 45000; - } else CurseOfWeakness_Timer -= diff; - - //DemonArmor_Timer - if (DemonArmor_Timer <= diff) - { - DoCast(me, SPELL_DEMONARMOR); - DemonArmor_Timer = 300000; - } else DemonArmor_Timer -= diff; - - //Summon Voidwalkers - if (!Voidwalkers && me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - DoCast(me->getVictim(), SPELL_SUMMON_VOIDWALKERS, true); - Voidwalkers = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_doomrel(Creature* pCreature) -{ - return new boss_doomrelAI (pCreature); -} - -#define GOSSIP_ITEM_CHALLENGE "Your bondage is at an end, Doom'rel. I challenge you!" -#define GOSSIP_SELECT_DOOMREL "[PH] Continue..." - -bool GossipHello_boss_doomrel(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2601, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_boss_doomrel(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_DOOMREL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(2605, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - //start event here - pCreature->setFaction(FACTION_HOSTILE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - pCreature->AI()->AttackStart(pPlayer); - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance) - pInstance->SetData64(DATA_EVENSTARTER,pPlayer->GetGUID()); - break; - } - return true; -} - -void AddSC_boss_tomb_of_seven() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_gloomrel"; - newscript->pGossipHello = &GossipHello_boss_gloomrel; - newscript->pGossipSelect = &GossipSelect_boss_gloomrel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_doomrel"; - newscript->GetAI = &GetAI_boss_doomrel; - newscript->pGossipHello = &GossipHello_boss_doomrel; - newscript->pGossipSelect = &GossipSelect_boss_doomrel; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp b/src/server/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp deleted file mode 100644 index 7684aa6c6ac..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Blackrock_Depths -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -/* -update `creature_template` set `npcflag`='1',`ScriptName`='npc_dughal_stormwing' where `entry`='9022'; -update `creature_template` set `ScriptName`='npc_marshal_windsor' where `entry`='9023'; -update `creature_template` set `ScriptName`='npc_marshal_reginald_windsor' where `entry`='9682'; -update `creature_template` set `npcflag`='1',`ScriptName`='npc_tobias_seecher' where `entry`='9679'; -update `instance_template` set `script`='instance_blackrock_depths' where `map`='230'; -*/ - -#include "ScriptedPch.h" -#include "blackrock_depths.h" - -#define TIMER_TOMBOFTHESEVEN 15000 - -enum eEnums -{ - MAX_ENCOUNTER = 6, - - NPC_EMPEROR = 9019, - NPC_PHALANX = 9502, - NPC_ANGERREL = 9035, - NPC_DOPEREL = 9040, - NPC_HATEREL = 9034, - NPC_VILEREL = 9036, - NPC_SEETHREL = 9038, - NPC_GLOOMREL = 9037, - NPC_DOOMREL = 9039, - NPC_MAGMUS = 9938, - - GO_ARENA1 = 161525, - GO_ARENA2 = 161522, - GO_ARENA3 = 161524, - GO_ARENA4 = 161523, - GO_SHADOW_LOCK = 161460, - GO_SHADOW_MECHANISM = 161461, - GO_SHADOW_GIANT_DOOR = 157923, - GO_SHADOW_DUMMY = 161516, - GO_BAR_KEG_SHOT = 170607, - GO_BAR_KEG_TRAP = 171941, - GO_BAR_DOOR = 170571, - GO_TOMB_ENTER = 170576, - GO_TOMB_EXIT = 170577, - GO_LYCEUM = 170558, - GO_SF_N = 174745, // Shadowforge Brazier North - GO_SF_S = 174744, // Shadowforge Brazier South - GO_GOLEM_ROOM_N = 170573, // Magmus door North - GO_GOLEM_ROOM_S = 170574, // Magmus door Soutsh - GO_THRONE_ROOM = 170575, // Throne door - - GO_SPECTRAL_CHALICE = 164869, - GO_CHEST_SEVEN = 169243 -}; - -struct instance_blackrock_depths : public ScriptedInstance -{ - instance_blackrock_depths(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 EmperorGUID; - uint64 PhalanxGUID; - uint64 MagmusGUID; - - uint64 GoArena1GUID; - uint64 GoArena2GUID; - uint64 GoArena3GUID; - uint64 GoArena4GUID; - uint64 GoShadowLockGUID; - uint64 GoShadowMechGUID; - uint64 GoShadowGiantGUID; - uint64 GoShadowDummyGUID; - uint64 GoBarKegGUID; - uint64 GoBarKegTrapGUID; - uint64 GoBarDoorGUID; - uint64 GoTombEnterGUID; - uint64 GoTombExitGUID; - uint64 GoLyceumGUID; - uint64 GoSFSGUID; - uint64 GoSFNGUID; - uint64 GoGolemNGUID; - uint64 GoGolemSGUID; - uint64 GoThroneGUID; - uint64 GoChestGUID; - - uint32 BarAleCount; - uint32 GhostKillCount; - uint64 TombBossGUIDs[7]; - uint64 TombEventStarterGUID; - uint32 TombTimer; - uint32 TombEventCounter; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - EmperorGUID = 0; - PhalanxGUID = 0; - MagmusGUID = 0; - - GoArena1GUID = 0; - GoArena2GUID = 0; - GoArena3GUID = 0; - GoArena4GUID = 0; - GoShadowLockGUID = 0; - GoShadowMechGUID = 0; - GoShadowGiantGUID = 0; - GoShadowDummyGUID = 0; - GoBarKegGUID = 0; - GoBarKegTrapGUID = 0; - GoBarDoorGUID = 0; - GoTombEnterGUID = 0; - GoTombExitGUID = 0; - GoLyceumGUID = 0; - GoSFSGUID = 0; - GoSFNGUID = 0; - GoGolemNGUID = 0; - GoGolemSGUID = 0; - GoThroneGUID = 0; - GoChestGUID = 0; - - BarAleCount = 0; - GhostKillCount = 0; - TombEventStarterGUID = 0; - TombTimer = TIMER_TOMBOFTHESEVEN; - TombEventCounter = 0; - - for (uint8 i = 0; i < 7; ++i) - TombBossGUIDs[i] = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_EMPEROR: EmperorGUID = pCreature->GetGUID(); break; - case NPC_PHALANX: PhalanxGUID = pCreature->GetGUID(); break; - case NPC_DOOMREL: TombBossGUIDs[0] = pCreature->GetGUID(); break; - case NPC_DOPEREL: TombBossGUIDs[1] = pCreature->GetGUID(); break; - case NPC_HATEREL: TombBossGUIDs[2] = pCreature->GetGUID(); break; - case NPC_VILEREL: TombBossGUIDs[3] = pCreature->GetGUID(); break; - case NPC_SEETHREL: TombBossGUIDs[4] = pCreature->GetGUID(); break; - case NPC_GLOOMREL: TombBossGUIDs[5] = pCreature->GetGUID(); break; - case NPC_ANGERREL: TombBossGUIDs[6] = pCreature->GetGUID(); break; - case NPC_MAGMUS: - MagmusGUID = pCreature->GetGUID(); - if (!pCreature->isAlive()) - HandleGameObject(GetData64(DATA_THRONE_DOOR), true); // if Magmus is dead open door to last boss - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_ARENA1: GoArena1GUID = pGo->GetGUID(); break; - case GO_ARENA2: GoArena2GUID = pGo->GetGUID(); break; - case GO_ARENA3: GoArena3GUID = pGo->GetGUID(); break; - case GO_ARENA4: GoArena4GUID = pGo->GetGUID(); break; - case GO_SHADOW_LOCK: GoShadowLockGUID = pGo->GetGUID(); break; - case GO_SHADOW_MECHANISM: GoShadowMechGUID = pGo->GetGUID(); break; - case GO_SHADOW_GIANT_DOOR: GoShadowGiantGUID = pGo->GetGUID(); break; - case GO_SHADOW_DUMMY: GoShadowDummyGUID = pGo->GetGUID(); break; - case GO_BAR_KEG_SHOT: GoBarKegGUID = pGo->GetGUID(); break; - case GO_BAR_KEG_TRAP: GoBarKegTrapGUID = pGo->GetGUID(); break; - case GO_BAR_DOOR: GoBarDoorGUID = pGo->GetGUID(); break; - case GO_TOMB_ENTER: GoTombEnterGUID = pGo->GetGUID(); break; - case GO_TOMB_EXIT: - GoTombExitGUID = pGo->GetGUID(); - if (GhostKillCount >= 7) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - case GO_LYCEUM: GoLyceumGUID = pGo->GetGUID(); break; - case GO_SF_S: GoSFSGUID = pGo->GetGUID(); break; - case GO_SF_N: GoSFNGUID = pGo->GetGUID(); break; - case GO_GOLEM_ROOM_N: GoGolemNGUID = pGo->GetGUID(); break; - case GO_GOLEM_ROOM_S: GoGolemSGUID = pGo->GetGUID(); break; - case GO_THRONE_ROOM: GoThroneGUID = pGo->GetGUID(); break; - case GO_CHEST_SEVEN: GoChestGUID = pGo->GetGUID(); break; - } - } - - void SetData64(uint32 type, uint64 data) - { - debug_log("TSCR: Instance Blackrock Depths: SetData64 update (Type: %u Data %u)", type, data); - - switch(type) - { - case DATA_EVENSTARTER: - TombEventStarterGUID = data; - if (!TombEventStarterGUID) - TombOfSevenReset();//reset - else - TombOfSevenStart();//start - break; - } - } - - void SetData(uint32 type, uint32 data) - { - debug_log("TSCR: Instance Blackrock Depths: SetData update (Type: %u Data %u)", type, data); - - switch(type) - { - case TYPE_RING_OF_LAW: - m_auiEncounter[0] = data; - break; - case TYPE_VAULT: - m_auiEncounter[1] = data; - break; - case TYPE_BAR: - if (data == SPECIAL) - ++BarAleCount; - else - m_auiEncounter[2] = data; - break; - case TYPE_TOMB_OF_SEVEN: - m_auiEncounter[3] = data; - break; - case TYPE_LYCEUM: - m_auiEncounter[4] = data; - break; - case TYPE_IRON_HALL: - m_auiEncounter[5] = data; - break; - case DATA_GHOSTKILL: - GhostKillCount += data; - break; - } - - if (data == DONE || GhostKillCount >= 7) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << GhostKillCount; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_RING_OF_LAW: - return m_auiEncounter[0]; - case TYPE_VAULT: - return m_auiEncounter[1]; - case TYPE_BAR: - if (m_auiEncounter[2] == IN_PROGRESS && BarAleCount == 3) - return SPECIAL; - else - return m_auiEncounter[2]; - case TYPE_TOMB_OF_SEVEN: - return m_auiEncounter[3]; - case TYPE_LYCEUM: - return m_auiEncounter[4]; - case TYPE_IRON_HALL: - return m_auiEncounter[5]; - case DATA_GHOSTKILL: - return GhostKillCount; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_EMPEROR: - return EmperorGUID; - case DATA_PHALANX: - return PhalanxGUID; - case DATA_ARENA1: - return GoArena1GUID; - case DATA_ARENA2: - return GoArena2GUID; - case DATA_ARENA3: - return GoArena3GUID; - case DATA_ARENA4: - return GoArena4GUID; - case DATA_GO_BAR_KEG: - return GoBarKegGUID; - case DATA_GO_BAR_KEG_TRAP: - return GoBarKegTrapGUID; - case DATA_GO_BAR_DOOR: - return GoBarDoorGUID; - case DATA_EVENSTARTER: - return TombEventStarterGUID; - case DATA_SF_BRAZIER_N: - return GoSFNGUID; - case DATA_SF_BRAZIER_S: - return GoSFSGUID; - case DATA_THRONE_DOOR: - return GoThroneGUID; - case DATA_GOLEM_DOOR_N: - return GoGolemNGUID; - case DATA_GOLEM_DOOR_S: - return GoGolemSGUID; - } - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> GhostKillCount; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - if (GhostKillCount > 0 && GhostKillCount < 7) - GhostKillCount = 0;//reset tomb of seven event - if (GhostKillCount >= 7) - GhostKillCount = 7; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void TombOfSevenEvent() - { - if (GhostKillCount < 7 && TombBossGUIDs[TombEventCounter]) - { - if (Creature* boss = instance->GetCreature(TombBossGUIDs[TombEventCounter])) - { - boss->setFaction(FACTION_HOSTILE); - boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - if (Unit *pTarget = boss->SelectNearestTarget(500)) - boss->AI()->AttackStart(pTarget); - } - } - } - - void TombOfSevenReset() - { - HandleGameObject(GoTombExitGUID,false);//event reseted, close exit door - HandleGameObject(GoTombEnterGUID,true);//event reseted, open entrance door - for (uint8 i = 0; i < 7; ++i) - { - if (Creature* boss = instance->GetCreature(TombBossGUIDs[i])) - { - if (!boss->isAlive()) - {//do not call EnterEvadeMode(), it will create infinit loops - boss->Respawn(); - boss->RemoveAllAuras(); - boss->DeleteThreatList(); - boss->CombatStop(true); - boss->LoadCreaturesAddon(); - boss->GetMotionMaster()->MoveTargetedHome(); - boss->SetLootRecipient(NULL); - } - boss->setFaction(FACTION_FRIEND); - } - } - GhostKillCount = 0; - TombEventStarterGUID = 0; - TombEventCounter = 0; - TombTimer = TIMER_TOMBOFTHESEVEN; - SetData(TYPE_TOMB_OF_SEVEN, NOT_STARTED); - } - - void TombOfSevenStart() - { - HandleGameObject(GoTombExitGUID,false);//event started, close exit door - HandleGameObject(GoTombEnterGUID,false);//event started, close entrance door - SetData(TYPE_TOMB_OF_SEVEN, IN_PROGRESS); - } - - void TombOfSevenEnd() - { - DoRespawnGameObject(GoChestGUID,DAY); - HandleGameObject(GoTombExitGUID,true);//event done, open exit door - HandleGameObject(GoTombEnterGUID,true);//event done, open entrance door - TombEventStarterGUID = 0; - SetData(TYPE_TOMB_OF_SEVEN, DONE); - } - void Update(uint32 diff) - { - if (TombEventStarterGUID && GhostKillCount < 7) - { - if (TombTimer <= diff) - { - TombTimer = TIMER_TOMBOFTHESEVEN; - ++TombEventCounter; - TombOfSevenEvent(); - // Check Killed bosses - for (uint8 i = 0; i < 7; ++i) - { - if (Creature* boss = instance->GetCreature(TombBossGUIDs[i])) - { - if (!boss->isAlive()) - { - GhostKillCount = i+1; - } - } - } - } else TombTimer -= diff; - } - if (GhostKillCount >= 7 && TombEventStarterGUID) - TombOfSevenEnd(); - } -}; - -InstanceData* GetInstanceData_instance_blackrock_depths(Map* pMap) -{ - return new instance_blackrock_depths(pMap); -} - - void AddSC_instance_blackrock_depths() - { - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blackrock_depths"; - newscript->GetInstanceData = &GetInstanceData_instance_blackrock_depths; - newscript->RegisterSelf(); - } diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.cpp deleted file mode 100644 index 2ea115e6e0b..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "blackrock_spire.h" - -enum Creatures -{ - NPC_ROOKERY_WHELP = 10161 -}; - -struct npc_rookey_whelpAI : public ScriptedAI -{ - npc_rookey_whelpAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void JustDied(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(WHELP_DEATH_COUNT, pInstance->GetData(WHELP_DEATH_COUNT)+1); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_rookey_whelp(Creature* pCreature) -{ - return new npc_rookey_whelpAI(pCreature); -} - -bool GOHello_rookey_egg(Player *pPlayer, GameObject * /*pGO*/) -{ - Position pos; - pPlayer->GetPosition(&pos); - pPlayer->SummonCreature(NPC_ROOKERY_WHELP, pos, TEMPSUMMON_TIMED_DESPAWN, 15*IN_MILISECONDS); - //destroy gobject need to be implemented - - return true; -}; - -void AddSC_blackrock_spire() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_rookey_whelp"; - newscript->GetAI = &GetAI_rookey_whelp; - newscript->RegisterSelf(); - newscript = new Script; - - newscript->Name = "go_rookey_egg"; - newscript->pGOHello = &GOHello_rookey_egg; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h b/src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h deleted file mode 100644 index 56b6e0cbe23..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_BRS_H -#define DEF_BRS_H - -enum Data -{ - EVENT_LEEEROY, - WHELP_DEATH_COUNT -}; - -#endif diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp deleted file mode 100644 index b53ddaf23ef..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Drakkisath -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FIRENOVA 23462 -#define SPELL_CLEAVE 20691 -#define SPELL_CONFLIGURATION 16805 -#define SPELL_THUNDERCLAP 15548 //Not sure if right ID. 23931 would be a harder possibility. - -struct boss_drakkisathAI : public ScriptedAI -{ - boss_drakkisathAI(Creature *c) : ScriptedAI(c) {} - - uint32 FireNova_Timer; - uint32 Cleave_Timer; - uint32 Confliguration_Timer; - uint32 Thunderclap_Timer; - - void Reset() - { - FireNova_Timer = 6000; - Cleave_Timer = 8000; - Confliguration_Timer = 15000; - Thunderclap_Timer = 17000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRENOVA); - FireNova_Timer = 10000; - } else FireNova_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 8000; - } else Cleave_Timer -= diff; - - //Confliguration_Timer - if (Confliguration_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CONFLIGURATION); - Confliguration_Timer = 18000; - } else Confliguration_Timer -= diff; - - //Thunderclap_Timer - if (Thunderclap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - Thunderclap_Timer = 20000; - } else Thunderclap_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_drakkisath(Creature* pCreature) -{ - return new boss_drakkisathAI (pCreature); -} - -void AddSC_boss_drakkisath() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_drakkisath"; - newscript->GetAI = &GetAI_boss_drakkisath; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp deleted file mode 100644 index fcd2ea1a6d0..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gyth -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CORROSIVEACID 20667 -#define SPELL_FREEZE 18763 -#define SPELL_FLAMEBREATH 20712 - -struct boss_gythAI : public ScriptedAI -{ - boss_gythAI(Creature *c) : ScriptedAI(c) {} - - uint32 Aggro_Timer; - uint32 Dragons_Timer; - uint32 Orc_Timer; - uint32 CorrosiveAcid_Timer; - uint32 Freeze_Timer; - uint32 Flamebreath_Timer; - uint32 Line1Count; - uint32 Line2Count; - - bool Event; - bool SummonedDragons; - bool SummonedOrcs; - bool SummonedRend; - bool bAggro; - bool RootSelf; - - void Reset() - { - Dragons_Timer = 3000; - Orc_Timer = 60000; - Aggro_Timer = 60000; - CorrosiveAcid_Timer = 8000; - Freeze_Timer = 11000; - Flamebreath_Timer = 4000; - Event = false; - SummonedDragons = false; - SummonedOrcs= false; - SummonedRend = false; - bAggro = false; - RootSelf = false; - - // how many times should the two lines of summoned creatures be spawned - // min 2 x 2, max 7 lines of attack in total - Line1Count = rand() % 4 + 2; - if (Line1Count < 5) - Line2Count = rand() % (5 - Line1Count) + 2; - else - Line2Count = 2; - - //Invisible for event start - me->SetDisplayId(11686); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonCreatureWithRandomTarget(uint32 creatureId) - { - Unit* Summoned = me->SummonCreature(creatureId, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240000); - if (Summoned) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Summoned->AddThreat(pTarget, 1.0f); - } - } - - void UpdateAI(const uint32 diff) - { - //char buf[200]; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!RootSelf) - { - //me->m_canMove = true; - DoCast(me, 33356); - RootSelf = true; - } - - if (!bAggro && Line1Count == 0 && Line2Count == 0) - { - if (Aggro_Timer <= diff) - { - bAggro = true; - // Visible now! - me->SetDisplayId(9723); - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } else Aggro_Timer -= diff; - } - - // Summon Dragon pack. 2 Dragons and 3 Whelps - if (!bAggro && !SummonedRend && Line1Count > 0) - { - if (Dragons_Timer <= diff) - { - SummonCreatureWithRandomTarget(10372); - SummonCreatureWithRandomTarget(10372); - SummonCreatureWithRandomTarget(10442); - SummonCreatureWithRandomTarget(10442); - SummonCreatureWithRandomTarget(10442); - Line1Count = Line1Count - 1; - Dragons_Timer = 60000; - } else Dragons_Timer -= diff; - } - - //Summon Orc pack. 1 Orc Handler 1 Elite Dragonkin and 3 Whelps - if (!bAggro && !SummonedRend && Line1Count == 0 && Line2Count > 0) - { - if (Orc_Timer <= diff) - { - SummonCreatureWithRandomTarget(10447); - SummonCreatureWithRandomTarget(10317); - SummonCreatureWithRandomTarget(10442); - SummonCreatureWithRandomTarget(10442); - SummonCreatureWithRandomTarget(10442); - Line2Count = Line2Count - 1; - Orc_Timer = 60000; - } else Orc_Timer -= diff; - } - - // we take part in the fight - if (bAggro) - { - // CorrosiveAcid_Timer - if (CorrosiveAcid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVEACID); - CorrosiveAcid_Timer = 7000; - } else CorrosiveAcid_Timer -= diff; - - // Freeze_Timer - if (Freeze_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FREEZE); - Freeze_Timer = 16000; - } else Freeze_Timer -= diff; - - // Flamebreath_Timer - if (Flamebreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBREATH); - Flamebreath_Timer = 10500; - } else Flamebreath_Timer -= diff; - - //Summon Rend - if (!SummonedRend && me->GetHealth()*100 / me->GetMaxHealth() < 11 - && me->GetHealth() > 0) - { - //summon Rend and Change model to normal Gyth - //Inturrupt any spell casting - me->InterruptNonMeleeSpells(false); - //Gyth model - me->SetDisplayId(9806); - me->SummonCreature(10429, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000); - SummonedRend = true; - } - - DoMeleeAttackIfReady(); - } // end if Aggro - } -}; - -CreatureAI* GetAI_boss_gyth(Creature* pCreature) -{ - return new boss_gythAI (pCreature); -} - -void AddSC_boss_gyth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gyth"; - newscript->GetAI = &GetAI_boss_gyth; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp deleted file mode 100644 index 9e78667717a..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Halycon -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CROWDPUMMEL 10887 -#define SPELL_MIGHTYBLOW 14099 - -#define ADD_1X -169.839203 -#define ADD_1Y -324.961395 -#define ADD_1Z 64.401443 -#define ADD_1O 3.124724 - -struct boss_halyconAI : public ScriptedAI -{ - boss_halyconAI(Creature *c) : ScriptedAI(c) {} - - uint32 CrowdPummel_Timer; - uint32 MightyBlow_Timer; - bool Summoned; - - void Reset() - { - CrowdPummel_Timer = 8000; - MightyBlow_Timer = 14000; - Summoned = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //CrowdPummel_Timer - if (CrowdPummel_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CROWDPUMMEL); - CrowdPummel_Timer = 14000; - } else CrowdPummel_Timer -= diff; - - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTYBLOW); - MightyBlow_Timer = 10000; - } else MightyBlow_Timer -= diff; - - //Summon Gizrul - if (!Summoned && me->GetHealth()*100 / me->GetMaxHealth() < 25) - { - me->SummonCreature(10268,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000); - Summoned = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_halycon(Creature* pCreature) -{ - return new boss_halyconAI (pCreature); -} - -void AddSC_boss_halycon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_halycon"; - newscript->GetAI = &GetAI_boss_halycon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp deleted file mode 100644 index 65f1e8081a0..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Highlord_Omokk -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_WARSTOMP 24375 -#define SPELL_CLEAVE 15579 -#define SPELL_STRIKE 18368 -#define SPELL_REND 18106 -#define SPELL_SUNDERARMOR 24317 -#define SPELL_KNOCKAWAY 20686 -#define SPELL_SLOW 22356 - -struct boss_highlordomokkAI : public ScriptedAI -{ - boss_highlordomokkAI(Creature *c) : ScriptedAI(c) {} - - uint32 WarStomp_Timer; - uint32 Cleave_Timer; - uint32 Strike_Timer; - uint32 Rend_Timer; - uint32 SunderArmor_Timer; - uint32 KnockAway_Timer; - uint32 Slow_Timer; - - void Reset() - { - WarStomp_Timer = 15000; - Cleave_Timer = 6000; - Strike_Timer = 10000; - Rend_Timer = 14000; - SunderArmor_Timer = 2000; - KnockAway_Timer = 18000; - Slow_Timer = 24000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //WarStomp_Timer - if (WarStomp_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WARSTOMP); - WarStomp_Timer = 14000; - } else WarStomp_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 8000; - } else Cleave_Timer -= diff; - - //Strike_Timer - if (Strike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STRIKE); - Strike_Timer = 10000; - } else Strike_Timer -= diff; - - //Rend_Timer - if (Rend_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REND); - Rend_Timer = 18000; - } else Rend_Timer -= diff; - - //SunderArmor_Timer - if (SunderArmor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDERARMOR); - SunderArmor_Timer = 25000; - } else SunderArmor_Timer -= diff; - - //KnockAway_Timer - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - KnockAway_Timer = 12000; - } else KnockAway_Timer -= diff; - - //Slow_Timer - if (Slow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLOW); - Slow_Timer = 18000; - } else Slow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_highlordomokk(Creature* pCreature) -{ - return new boss_highlordomokkAI (pCreature); -} - -void AddSC_boss_highlordomokk() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_highlord_omokk"; - newscript->GetAI = &GetAI_boss_highlordomokk; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp deleted file mode 100644 index 60dda5a5fab..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mother_Smolderweb -SD%Complete: 100 -SDComment: Uncertain how often mother's milk is casted -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CRYSTALIZE 16104 -#define SPELL_MOTHERSMILK 16468 -#define SPELL_SUMMON_SPIRE_SPIDERLING 16103 - -struct boss_mothersmolderwebAI : public ScriptedAI -{ - boss_mothersmolderwebAI(Creature *c) : ScriptedAI(c) {} - - uint32 Crystalize_Timer; - uint32 MothersMilk_Timer; - - void Reset() - { - Crystalize_Timer = 20000; - MothersMilk_Timer = 10000; - } - - void EnterCombat(Unit * /*who*/) {} - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (me->GetHealth() <= damage) - DoCast(me, SPELL_SUMMON_SPIRE_SPIDERLING, true); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Crystalize_Timer - if (Crystalize_Timer <= diff) - { - DoCast(me, SPELL_CRYSTALIZE); - Crystalize_Timer = 15000; - } else Crystalize_Timer -= diff; - - //MothersMilk_Timer - if (MothersMilk_Timer <= diff) - { - DoCast(me, SPELL_MOTHERSMILK); - MothersMilk_Timer = urand(5000,12500); - } else MothersMilk_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_mothersmolderweb(Creature* pCreature) -{ - return new boss_mothersmolderwebAI (pCreature); -} - -void AddSC_boss_mothersmolderweb() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_mother_smolderweb"; - newscript->GetAI = &GetAI_boss_mothersmolderweb; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp deleted file mode 100644 index 8846442705b..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Overlord_Wyrmthalak -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_BLASTWAVE 11130 -#define SPELL_SHOUT 23511 -#define SPELL_CLEAVE 20691 -#define SPELL_KNOCKAWAY 20686 - -#define ADD_1X -39.355381 -#define ADD_1Y -513.456482 -#define ADD_1Z 88.472046 -#define ADD_1O 4.679872 - -#define ADD_2X -49.875881 -#define ADD_2Y -511.896942 -#define ADD_2Z 88.195160 -#define ADD_2O 4.613114 - -struct boss_overlordwyrmthalakAI : public ScriptedAI -{ - boss_overlordwyrmthalakAI(Creature *c) : ScriptedAI(c) {} - - uint32 BlastWave_Timer; - uint32 Shout_Timer; - uint32 Cleave_Timer; - uint32 Knockaway_Timer; - bool Summoned; - - void Reset() - { - BlastWave_Timer = 20000; - Shout_Timer = 2000; - Cleave_Timer = 6000; - Knockaway_Timer = 12000; - Summoned = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //BlastWave_Timer - if (BlastWave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLASTWAVE); - BlastWave_Timer = 20000; - } else BlastWave_Timer -= diff; - - //Shout_Timer - if (Shout_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHOUT); - Shout_Timer = 10000; - } else Shout_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //Knockaway_Timer - if (Knockaway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - Knockaway_Timer = 14000; - } else Knockaway_Timer -= diff; - - //Summon two Beserks - if (!Summoned && me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0, 100, true); - - if (Creature *SummonedCreature = me->SummonCreature(9216,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000)) - SummonedCreature->AI()->AttackStart(pTarget); - if (Creature *SummonedCreature = me->SummonCreature(9268,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,300000)) - SummonedCreature->AI()->AttackStart(pTarget); - Summoned = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_overlordwyrmthalak(Creature* pCreature) -{ - return new boss_overlordwyrmthalakAI (pCreature); -} - -void AddSC_boss_overlordwyrmthalak() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_overlord_wyrmthalak"; - newscript->GetAI = &GetAI_boss_overlordwyrmthalak; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp deleted file mode 100644 index 6cbd6955665..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Pyroguard_Emberseer -SD%Complete: 100 -SDComment: Event to activate Emberseer NYI -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FIRENOVA 23462 -#define SPELL_FLAMEBUFFET 23341 -#define SPELL_PYROBLAST 17274 - -struct boss_pyroguard_emberseerAI : public ScriptedAI -{ - boss_pyroguard_emberseerAI(Creature *c) : ScriptedAI(c) {} - - uint32 FireNova_Timer; - uint32 FlameBuffet_Timer; - uint32 PyroBlast_Timer; - - void Reset() - { - FireNova_Timer = 6000; - FlameBuffet_Timer = 3000; - PyroBlast_Timer = 14000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRENOVA); - FireNova_Timer = 6000; - } else FireNova_Timer -= diff; - - //FlameBuffet_Timer - if (FlameBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBUFFET); - FlameBuffet_Timer = 14000; - } else FlameBuffet_Timer -= diff; - - //PyroBlast_Timer - if (PyroBlast_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_PYROBLAST); - PyroBlast_Timer = 15000; - } else PyroBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_pyroguard_emberseer(Creature* pCreature) -{ - return new boss_pyroguard_emberseerAI (pCreature); -} - -void AddSC_boss_pyroguard_emberseer() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_pyroguard_emberseer"; - newscript->GetAI = &GetAI_boss_pyroguard_emberseer; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp deleted file mode 100644 index 9058b35cd5c..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Quartmaster_Zigris -SD%Complete: 100 -SDComment: Needs revision -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHOOT 16496 -#define SPELL_STUNBOMB 16497 -#define SPELL_HEALING_POTION 15504 -#define SPELL_HOOKEDNET 15609 - -struct boss_quatermasterzigrisAI : public ScriptedAI -{ - boss_quatermasterzigrisAI(Creature *c) : ScriptedAI(c) {} - - uint32 Shoot_Timer; - uint32 StunBomb_Timer; - //uint32 HelingPotion_Timer; - - void Reset() - { - Shoot_Timer = 1000; - StunBomb_Timer = 16000; - //HelingPotion_Timer = 25000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Shoot_Timer - if (Shoot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHOOT); - Shoot_Timer = 500; - } else Shoot_Timer -= diff; - - //StunBomb_Timer - if (StunBomb_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STUNBOMB); - StunBomb_Timer = 14000; - } else StunBomb_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_quatermasterzigris(Creature* pCreature) -{ - return new boss_quatermasterzigrisAI (pCreature); -} - -void AddSC_boss_quatermasterzigris() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "quartermaster_zigris"; - newscript->GetAI = &GetAI_boss_quatermasterzigris; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp deleted file mode 100644 index 56de5dbb385..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Rend_Blackhand -SD%Complete: 100 -SDComment: Intro event NYI -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_WHIRLWIND 26038 -#define SPELL_CLEAVE 20691 -#define SPELL_THUNDERCLAP 23931 //Not sure if he cast this spell - -struct boss_rend_blackhandAI : public ScriptedAI -{ - boss_rend_blackhandAI(Creature *c) : ScriptedAI(c) {} - - uint32 WhirlWind_Timer; - uint32 Cleave_Timer; - uint32 Thunderclap_Timer; - - void Reset() - { - WhirlWind_Timer = 20000; - Cleave_Timer = 5000; - Thunderclap_Timer = 9000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //WhirlWind_Timer - if (WhirlWind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - WhirlWind_Timer = 18000; - } else WhirlWind_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 10000; - } else Cleave_Timer -= diff; - - //Thunderclap_Timer - if (Thunderclap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - Thunderclap_Timer = 16000; - } else Thunderclap_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_rend_blackhand(Creature* pCreature) -{ - return new boss_rend_blackhandAI (pCreature); -} - -void AddSC_boss_rend_blackhand() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_rend_blackhand"; - newscript->GetAI = &GetAI_boss_rend_blackhand; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp deleted file mode 100644 index 73afc3b5afe..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Shadow_Hunter_Voshgajin -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CURSEOFBLOOD 24673 -#define SPELL_HEX 16708 -#define SPELL_CLEAVE 20691 - -struct boss_shadowvoshAI : public ScriptedAI -{ - boss_shadowvoshAI(Creature *c) : ScriptedAI(c) {} - - uint32 CurseOfBlood_Timer; - uint32 Hex_Timer; - uint32 Cleave_Timer; - - void Reset() - { - CurseOfBlood_Timer = 2000; - Hex_Timer = 8000; - Cleave_Timer = 14000; - - //DoCast(me, SPELL_ICEARMOR, true); - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //CurseOfBlood_Timer - if (CurseOfBlood_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); - CurseOfBlood_Timer = 45000; - } else CurseOfBlood_Timer -= diff; - - //Hex_Timer - if (Hex_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_HEX); - Hex_Timer = 15000; - } else Hex_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_shadowvosh(Creature* pCreature) -{ - return new boss_shadowvoshAI (pCreature); -} - -void AddSC_boss_shadowvosh() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shadow_hunter_voshgajin"; - newscript->GetAI = &GetAI_boss_shadowvosh; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp deleted file mode 100644 index 499f9cf4ce5..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_The_Best -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FLAMEBREAK 16785 -#define SPELL_IMMOLATE 20294 -#define SPELL_TERRIFYINGROAR 14100 - -struct boss_thebeastAI : public ScriptedAI -{ - boss_thebeastAI(Creature *c) : ScriptedAI(c) {} - - uint32 Flamebreak_Timer; - uint32 Immolate_Timer; - uint32 TerrifyingRoar_Timer; - - void Reset() - { - Flamebreak_Timer = 12000; - Immolate_Timer = 3000; - TerrifyingRoar_Timer = 23000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Flamebreak_Timer - if (Flamebreak_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBREAK); - Flamebreak_Timer = 10000; - } else Flamebreak_Timer -= diff; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_IMMOLATE); - Immolate_Timer = 8000; - } else Immolate_Timer -= diff; - - //TerrifyingRoar_Timer - if (TerrifyingRoar_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TERRIFYINGROAR); - TerrifyingRoar_Timer = 20000; - } else TerrifyingRoar_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_thebeast(Creature* pCreature) -{ - return new boss_thebeastAI (pCreature); -} - -void AddSC_boss_thebeast() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_beast"; - newscript->GetAI = &GetAI_boss_thebeast; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp deleted file mode 100644 index 50b47c94fc5..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warmaster_Voone -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SNAPKICK 15618 -#define SPELL_CLEAVE 15579 -#define SPELL_UPPERCUT 10966 -#define SPELL_MORTALSTRIKE 16856 -#define SPELL_PUMMEL 15615 -#define SPELL_THROWAXE 16075 - -struct boss_warmastervooneAI : public ScriptedAI -{ - boss_warmastervooneAI(Creature *c) : ScriptedAI(c) {} - - uint32 Snapkick_Timer; - uint32 Cleave_Timer; - uint32 Uppercut_Timer; - uint32 MortalStrike_Timer; - uint32 Pummel_Timer; - uint32 ThrowAxe_Timer; - - void Reset() - { - Snapkick_Timer = 8000; - Cleave_Timer = 14000; - Uppercut_Timer = 20000; - MortalStrike_Timer = 12000; - Pummel_Timer = 32000; - ThrowAxe_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Snapkick_Timer - if (Snapkick_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SNAPKICK); - Snapkick_Timer = 6000; - } else Snapkick_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 12000; - } else Cleave_Timer -= diff; - - //Uppercut_Timer - if (Uppercut_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_UPPERCUT); - Uppercut_Timer = 14000; - } else Uppercut_Timer -= diff; - - //MortalStrike_Timer - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = 10000; - } else MortalStrike_Timer -= diff; - - //Pummel_Timer - if (Pummel_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PUMMEL); - Pummel_Timer = 16000; - } else Pummel_Timer -= diff; - - //ThrowAxe_Timer - if (ThrowAxe_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THROWAXE); - ThrowAxe_Timer = 8000; - } else ThrowAxe_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_warmastervoone(Creature* pCreature) -{ - return new boss_warmastervooneAI (pCreature); -} - -void AddSC_boss_warmastervoone() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_warmaster_voone"; - newscript->GetAI = &GetAI_boss_warmastervoone; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp b/src/server/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp deleted file mode 100644 index f2e2b39fe87..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "blackrock_spire.h" - -enum Achievements -{ - ACHIEV_LEROY_JENKINS = 2188 -}; - -struct instance_blackrock_spire : public ScriptedInstance -{ - instance_blackrock_spire(Map* pMap) : ScriptedInstance(pMap) {} - - uint32 uiLeeroyTimer; - uint32 uiWhelpCount; - uint32 uiLeroyData; - - bool bLeeeeeeeeroy; - - void Initialize() - { - uiLeeroyTimer = 15*IN_MILISECONDS; - uiWhelpCount = 0; - bLeeeeeeeeroy = true; - uiLeroyData = 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case EVENT_LEEEROY: - if (data == DONE) - DoCompleteAchievement(ACHIEV_LEROY_JENKINS); - uiLeroyData = data; - break; - case WHELP_DEATH_COUNT: - if (data == 1) - { - SetData(EVENT_LEEEROY, IN_PROGRESS); - //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Started"); - } - uiWhelpCount = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case EVENT_LEEEROY: return uiLeroyData; - case WHELP_DEATH_COUNT: return uiWhelpCount; - } - return 0; - } - - void Update(uint32 diff) - { - if (GetData(EVENT_LEEEROY) != FAIL && GetData(EVENT_LEEEROY) == IN_PROGRESS) - { - if (uiLeeroyTimer <= diff) - { - SetData(EVENT_LEEEROY, FAIL); - bLeeeeeeeeroy = false; - //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Failed"); - } else uiLeeroyTimer -= diff; - if (uiWhelpCount >= 50 && bLeeeeeeeeroy) - { - SetData(EVENT_LEEEROY, DONE); - //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Success"); - } - } - } -}; - -InstanceData* GetInstanceData_instance_blackrock_spire(Map* pMap) -{ - return new instance_blackrock_spire(pMap); -} - -void AddSC_instance_blackrock_spire() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blackrock_spire"; - newscript->GetInstanceData = &GetInstanceData_instance_blackrock_spire; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp deleted file mode 100644 index 856e1236176..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Broodlord_Lashlayer -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1469000 -#define SAY_LEASH -1469001 - -#define SPELL_CLEAVE 26350 -#define SPELL_BLASTWAVE 23331 -#define SPELL_MORTALSTRIKE 24573 -#define SPELL_KNOCKBACK 25778 - -struct boss_broodlordAI : public ScriptedAI -{ - boss_broodlordAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cleave_Timer; - uint32 BlastWave_Timer; - uint32 MortalStrike_Timer; - uint32 KnockBack_Timer; - - void Reset() - { - Cleave_Timer = 8000; //These times are probably wrong - BlastWave_Timer = 12000; - MortalStrike_Timer = 20000; - KnockBack_Timer = 30000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - // BlastWave - if (BlastWave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLASTWAVE); - BlastWave_Timer = urand(8000,16000); - } else BlastWave_Timer -= diff; - - //MortalStrike_Timer - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = urand(25000,35000); - } else MortalStrike_Timer -= diff; - - if (KnockBack_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKBACK); - //Drop 50% aggro - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-50); - - KnockBack_Timer = urand(15000,30000); - } else KnockBack_Timer -= diff; - - if (EnterEvadeIfOutOfCombatArea(diff)) - DoScriptText(SAY_LEASH, me); - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_broodlord(Creature* pCreature) -{ - return new boss_broodlordAI (pCreature); -} - -void AddSC_boss_broodlord() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_broodlord"; - newscript->GetAI = &GetAI_boss_broodlord; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp deleted file mode 100644 index 08bebe95384..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Chromaggus -SD%Complete: 95 -SDComment: Chromatic Mutation disabled due to lack of core support -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -enum Emotes -{ - EMOTE_FRENZY = -1469002, - EMOTE_SHIMMER = -1469003 -}; - -enum Spells -{ - //These spells are actually called elemental shield - //What they do is decrease all damage by 75% then they increase - //One school of damage by 1100% - SPELL_FIRE_VULNERABILITY = 22277, - SPELL_FROST_VULNERABILITY = 22278, - SPELL_SHADOW_VULNERABILITY = 22279, - SPELL_NATURE_VULNERABILITY = 22280, - SPELL_ARCANE_VULNERABILITY = 22281, - //Other spells - SPELL_INCINERATE = 23308, //Incinerate 23308,23309 - SPELL_TIMELAPSE = 23310, //Time lapse 23310, 23311(old threat mod that was removed in 2.01) - SPELL_CORROSIVEACID = 23313, //Corrosive Acid 23313, 23314 - SPELL_IGNITEFLESH = 23315, //Ignite Flesh 23315,23316 - SPELL_FROSTBURN = 23187, //Frost burn 23187, 23189 - //Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them - //Since Scripted spells arn't coded I'll just write a function that does the same thing - SPELL_BROODAF_BLUE = 23153, //Blue affliction 23153 - SPELL_BROODAF_BLACK = 23154, //Black affliction 23154 - SPELL_BROODAF_RED = 23155, //Red affliction 23155 (23168 on death) - SPELL_BROODAF_BRONZE = 23170, //Bronze Affliction 23170 - SPELL_BROODAF_GREEN = 23169, //Brood Affliction Green 23169 - SPELL_CHROMATIC_MUT_1 = 23174, //Spell cast on player if they get all 5 debuffs - SPELL_FRENZY = 28371, //The frenzy spell may be wrong - SPELL_ENRAGE = 28747 -}; - -struct boss_chromaggusAI : public ScriptedAI -{ - boss_chromaggusAI(Creature *c) : ScriptedAI(c) - { - //Select the 2 breaths that we are going to use until despawned - //5 possiblities for the first breath, 4 for the second, 20 total possiblites - //This way we don't end up casting 2 of the same breath - //TL TL would be stupid - switch (urand(0,19)) - { - //B1 - Incin - case 0: - Breath1_Spell = SPELL_INCINERATE; - Breath2_Spell = SPELL_TIMELAPSE; - break; - case 1: - Breath1_Spell = SPELL_INCINERATE; - Breath2_Spell = SPELL_CORROSIVEACID; - break; - case 2: - Breath1_Spell = SPELL_INCINERATE; - Breath2_Spell = SPELL_IGNITEFLESH; - break; - case 3: - Breath1_Spell = SPELL_INCINERATE; - Breath2_Spell = SPELL_FROSTBURN; - break; - - //B1 - TL - case 4: - Breath1_Spell = SPELL_TIMELAPSE; - Breath2_Spell = SPELL_INCINERATE; - break; - case 5: - Breath1_Spell = SPELL_TIMELAPSE; - Breath2_Spell = SPELL_CORROSIVEACID; - break; - case 6: - Breath1_Spell = SPELL_TIMELAPSE; - Breath2_Spell = SPELL_IGNITEFLESH; - break; - case 7: - Breath1_Spell = SPELL_TIMELAPSE; - Breath2_Spell = SPELL_FROSTBURN; - break; - - //B1 - Acid - case 8: - Breath1_Spell = SPELL_CORROSIVEACID; - Breath2_Spell = SPELL_INCINERATE; - break; - case 9: - Breath1_Spell = SPELL_CORROSIVEACID; - Breath2_Spell = SPELL_TIMELAPSE; - break; - case 10: - Breath1_Spell = SPELL_CORROSIVEACID; - Breath2_Spell = SPELL_IGNITEFLESH; - break; - case 11: - Breath1_Spell = SPELL_CORROSIVEACID; - Breath2_Spell = SPELL_FROSTBURN; - break; - - //B1 - Ignite - case 12: - Breath1_Spell = SPELL_IGNITEFLESH; - Breath2_Spell = SPELL_INCINERATE; - break; - case 13: - Breath1_Spell = SPELL_IGNITEFLESH; - Breath2_Spell = SPELL_CORROSIVEACID; - break; - case 14: - Breath1_Spell = SPELL_IGNITEFLESH; - Breath2_Spell = SPELL_TIMELAPSE; - break; - case 15: - Breath1_Spell = SPELL_IGNITEFLESH; - Breath2_Spell = SPELL_FROSTBURN; - break; - - //B1 - Frost - case 16: - Breath1_Spell = SPELL_FROSTBURN; - Breath2_Spell = SPELL_INCINERATE; - break; - case 17: - Breath1_Spell = SPELL_FROSTBURN; - Breath2_Spell = SPELL_TIMELAPSE; - break; - case 18: - Breath1_Spell = SPELL_FROSTBURN; - Breath2_Spell = SPELL_CORROSIVEACID; - break; - case 19: - Breath1_Spell = SPELL_FROSTBURN; - Breath2_Spell = SPELL_IGNITEFLESH; - break; - }; - - EnterEvadeMode(); - } - - uint32 Breath1_Spell; - uint32 Breath2_Spell; - uint32 CurrentVurln_Spell; - - uint32 Shimmer_Timer; - uint32 Breath1_Timer; - uint32 Breath2_Timer; - uint32 Affliction_Timer; - uint32 Frenzy_Timer; - bool Enraged; - - void Reset() - { - CurrentVurln_Spell = 0; //We use this to store our last vulnerabilty spell so we can remove it later - - Shimmer_Timer = 0; //Time till we change vurlnerabilites - Breath1_Timer = 30000; //First breath is 30 seconds - Breath2_Timer = 60000; //Second is 1 minute so that we can alternate - Affliction_Timer = 10000; //This is special - 5 seconds means that we cast this on 1 player every 5 sconds - Frenzy_Timer = 15000; - - Enraged = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Shimmer_Timer Timer - if (Shimmer_Timer <= diff) - { - //Remove old vulnerabilty spell - if (CurrentVurln_Spell) - me->RemoveAurasDueToSpell(CurrentVurln_Spell); - - //Cast new random vulnerabilty on self - uint32 spell = RAND(SPELL_FIRE_VULNERABILITY, SPELL_FROST_VULNERABILITY, - SPELL_SHADOW_VULNERABILITY, SPELL_NATURE_VULNERABILITY, SPELL_ARCANE_VULNERABILITY); - - DoCast(me, spell); - CurrentVurln_Spell = spell; - - DoScriptText(EMOTE_SHIMMER, me); - Shimmer_Timer = 45000; - } else Shimmer_Timer -= diff; - - //Breath1_Timer - if (Breath1_Timer <= diff) - { - DoCast(me->getVictim(), Breath1_Spell); - Breath1_Timer = 60000; - } else Breath1_Timer -= diff; - - //Breath2_Timer - if (Breath2_Timer <= diff) - { - DoCast(me->getVictim(), Breath2_Spell); - Breath2_Timer = 60000; - } else Breath2_Timer -= diff; - - //Affliction_Timer - if (Affliction_Timer <= diff) - { - std::list threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) - { - Unit* pUnit; - if ((*i) && (*i)->getSource()) - { - pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit) - { - //Cast affliction - DoCast(pUnit, RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, - SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN), true); - - //Chromatic mutation if target is effected by all afflictions - if (pUnit->HasAura(SPELL_BROODAF_BLUE) - && pUnit->HasAura(SPELL_BROODAF_BLACK) - && pUnit->HasAura(SPELL_BROODAF_RED) - && pUnit->HasAura(SPELL_BROODAF_BRONZE) - && pUnit->HasAura(SPELL_BROODAF_GREEN)) - { - //pTarget->RemoveAllAuras(); - //DoCast(pTarget, SPELL_CHROMATIC_MUT_1); - - //Chromatic mutation is causing issues - //Assuming it is caused by a lack of core support for Charm - //So instead we instant kill our target - - //WORKAROUND - if (pUnit->GetTypeId() == TYPEID_PLAYER) - pUnit->CastSpell(pUnit, 5, false); - } - } - } - } - - Affliction_Timer = 10000; - } else Affliction_Timer -= diff; - - //Frenzy_Timer - if (Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_FRENZY, me); - Frenzy_Timer = urand(10000,15000); - } else Frenzy_Timer -= diff; - - //Enrage if not already enraged and below 20% - if (!Enraged && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_chromaggus(Creature* pCreature) -{ - return new boss_chromaggusAI (pCreature); -} - -void AddSC_boss_chromaggus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_chromaggus"; - newscript->GetAI = &GetAI_boss_chromaggus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp deleted file mode 100644 index 49a999fc458..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ebonroc -SD%Complete: 50 -SDComment: Shadow of Ebonroc needs core support -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWFLAME 22539 -#define SPELL_WINGBUFFET 18500 -#define SPELL_SHADOWOFEBONROC 23340 -#define SPELL_HEAL 41386 //Thea Heal spell of his Shadow - -struct boss_ebonrocAI : public ScriptedAI -{ - boss_ebonrocAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 ShadowOfEbonroc_Timer; - uint32 Heal_Timer; - - void Reset() - { - ShadowFlame_Timer = 15000; //These times are probably wrong - WingBuffet_Timer = 30000; - ShadowOfEbonroc_Timer = 45000; - Heal_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Shadowflame Timer - if (ShadowFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWFLAME); - ShadowFlame_Timer = urand(12000,15000); - } else ShadowFlame_Timer -= diff; - - //Wing Buffet Timer - if (WingBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WINGBUFFET); - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; - - //Shadow of Ebonroc Timer - if (ShadowOfEbonroc_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWOFEBONROC); - ShadowOfEbonroc_Timer = urand(25000,350000); - } else ShadowOfEbonroc_Timer -= diff; - - if (me->getVictim()->HasAura(SPELL_SHADOWOFEBONROC)) - { - if (Heal_Timer <= diff) - { - DoCast(me, SPELL_HEAL); - Heal_Timer = urand(1000,3000); - } else Heal_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ebonroc(Creature* pCreature) -{ - return new boss_ebonrocAI (pCreature); -} - -void AddSC_boss_ebonroc() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ebonroc"; - newscript->GetAI = &GetAI_boss_ebonroc; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp deleted file mode 100644 index af62b1103bc..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Firemaw -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWFLAME 22539 -#define SPELL_WINGBUFFET 23339 -#define SPELL_FLAMEBUFFET 23341 - -struct boss_firemawAI : public ScriptedAI -{ - boss_firemawAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 FlameBuffet_Timer; - - void Reset() - { - ShadowFlame_Timer = 30000; //These times are probably wrong - WingBuffet_Timer = 24000; - FlameBuffet_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWFLAME); - ShadowFlame_Timer = urand(15000,18000); - } else ShadowFlame_Timer -= diff; - - //WingBuffet_Timer - if (WingBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WINGBUFFET); - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-75); - - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; - - //FlameBuffet_Timer - if (FlameBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBUFFET); - FlameBuffet_Timer = 5000; - } else FlameBuffet_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_firemaw(Creature* pCreature) -{ - return new boss_firemawAI (pCreature); -} - -void AddSC_boss_firemaw() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_firemaw"; - newscript->GetAI = &GetAI_boss_firemaw; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp deleted file mode 100644 index b29fe41f2b1..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Flamegor -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_FRENZY -1469031 - -#define SPELL_SHADOWFLAME 22539 -#define SPELL_WINGBUFFET 23339 -#define SPELL_FRENZY 23342 //This spell periodically triggers fire nova - -struct boss_flamegorAI : public ScriptedAI -{ - boss_flamegorAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 Frenzy_Timer; - - void Reset() - { - ShadowFlame_Timer = 21000; //These times are probably wrong - WingBuffet_Timer = 35000; - Frenzy_Timer = 10000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWFLAME); - ShadowFlame_Timer = 15000 + rand()%7000; - } else ShadowFlame_Timer -= diff; - - //WingBuffet_Timer - if (WingBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WINGBUFFET); - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-75); - - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; - - //Frenzy_Timer - if (Frenzy_Timer <= diff) - { - DoScriptText(EMOTE_FRENZY, me); - DoCast(me, SPELL_FRENZY); - Frenzy_Timer = urand(8000, 10000); - } else Frenzy_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_flamegor(Creature* pCreature) -{ - return new boss_flamegorAI (pCreature); -} - -void AddSC_boss_flamegor() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_flamegor"; - newscript->GetAI = &GetAI_boss_flamegor; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp deleted file mode 100644 index 5ef05be519c..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Nefarian -SD%Complete: 80 -SDComment: Some issues with class calls effecting more than one class -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1469007 -#define SAY_XHEALTH -1469008 -#define SAY_SHADOWFLAME -1469009 -#define SAY_RAISE_SKELETONS -1469010 -#define SAY_SLAY -1469011 -#define SAY_DEATH -1469012 - -#define SAY_MAGE -1469013 -#define SAY_WARRIOR -1469014 -#define SAY_DRUID -1469015 -#define SAY_PRIEST -1469016 -#define SAY_PALADIN -1469017 -#define SAY_SHAMAN -1469018 -#define SAY_WARLOCK -1469019 -#define SAY_HUNTER -1469020 -#define SAY_ROGUE -1469021 - -#define SPELL_SHADOWFLAME_INITIAL 22972 -#define SPELL_SHADOWFLAME 22539 -#define SPELL_BELLOWINGROAR 22686 -#define SPELL_VEILOFSHADOW 7068 -#define SPELL_CLEAVE 20691 -#define SPELL_TAILLASH 23364 -#define SPELL_BONECONTRUST 23363 //23362, 23361 - -#define SPELL_MAGE 23410 //wild magic -#define SPELL_WARRIOR 23397 //beserk -#define SPELL_DRUID 23398 // cat form -#define SPELL_PRIEST 23401 // corrupted healing -#define SPELL_PALADIN 23418 //syphon blessing -#define SPELL_SHAMAN 23425 //totems -#define SPELL_WARLOCK 23427 //infernals -#define SPELL_HUNTER 23436 //bow broke -#define SPELL_ROGUE 23414 //Paralise - -struct boss_nefarianAI : public ScriptedAI -{ - boss_nefarianAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowFlame_Timer; - uint32 BellowingRoar_Timer; - uint32 VeilOfShadow_Timer; - uint32 Cleave_Timer; - uint32 TailLash_Timer; - uint32 ClassCall_Timer; - bool Phase3; - - uint32 DespawnTimer; - - void Reset() - { - ShadowFlame_Timer = 12000; //These times are probably wrong - BellowingRoar_Timer = 30000; - VeilOfShadow_Timer = 15000; - Cleave_Timer = 7000; - TailLash_Timer = 10000; - ClassCall_Timer = 35000; //35-40 seconds - Phase3 = false; - - DespawnTimer = 5000; - } - - void KilledUnit(Unit* Victim) - { - if (rand()%5) - return; - - DoScriptText(SAY_SLAY, me, Victim); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * who) - { - DoScriptText(RAND(SAY_XHEALTH,SAY_AGGRO,SAY_SHADOWFLAME), me); - - DoCast(who, SPELL_SHADOWFLAME_INITIAL); - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (DespawnTimer <= diff) - { - if (!UpdateVictim()) - me->ForcedDespawn(); - DespawnTimer = 5000; - } else DespawnTimer -= diff; - - if (!UpdateVictim()) - return; - - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWFLAME); - ShadowFlame_Timer = 12000; - } else ShadowFlame_Timer -= diff; - - //BellowingRoar_Timer - if (BellowingRoar_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BELLOWINGROAR); - BellowingRoar_Timer = 30000; - } else BellowingRoar_Timer -= diff; - - //VeilOfShadow_Timer - if (VeilOfShadow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VEILOFSHADOW); - VeilOfShadow_Timer = 15000; - } else VeilOfShadow_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //TailLash_Timer - if (TailLash_Timer <= diff) - { - //Cast NYI since we need a better check for behind target - //DoCast(me->getVictim(), SPELL_TAILLASH); - - TailLash_Timer = 10000; - } else TailLash_Timer -= diff; - - //ClassCall_Timer - if (ClassCall_Timer <= diff) - { - //Cast a random class call - //On official it is based on what classes are currently on the hostil list - //but we can't do that yet so just randomly call one - - switch (urand(0,8)) - { - case 0: - DoScriptText(SAY_MAGE, me); - DoCast(me, SPELL_MAGE); - break; - case 1: - DoScriptText(SAY_WARRIOR, me); - DoCast(me, SPELL_WARRIOR); - break; - case 2: - DoScriptText(SAY_DRUID, me); - DoCast(me, SPELL_DRUID); - break; - case 3: - DoScriptText(SAY_PRIEST, me); - DoCast(me, SPELL_PRIEST); - break; - case 4: - DoScriptText(SAY_PALADIN, me); - DoCast(me, SPELL_PALADIN); - break; - case 5: - DoScriptText(SAY_SHAMAN, me); - DoCast(me, SPELL_SHAMAN); - break; - case 6: - DoScriptText(SAY_WARLOCK, me); - DoCast(me, SPELL_WARLOCK); - break; - case 7: - DoScriptText(SAY_HUNTER, me); - DoCast(me, SPELL_HUNTER); - break; - case 8: - DoScriptText(SAY_ROGUE, me); - DoCast(me, SPELL_ROGUE); - break; - } - - ClassCall_Timer = 35000 + (rand() % 5000); - } else ClassCall_Timer -= diff; - - //Phase3 begins when we are below X health - if (!Phase3 && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) - { - Phase3 = true; - DoScriptText(SAY_RAISE_SKELETONS, me); - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_nefarian(Creature* pCreature) -{ - return new boss_nefarianAI (pCreature); -} - -void AddSC_boss_nefarian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nefarian"; - newscript->GetAI = &GetAI_boss_nefarian; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp deleted file mode 100644 index a095756b18b..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Razorgore -SD%Complete: 50 -SDComment: Needs additional review. Phase 1 NYI (Grethok the Controller) -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -//Razorgore Phase 2 Script - -#define SAY_EGGS_BROKEN1 -1469022 -#define SAY_EGGS_BROKEN2 -1469023 -#define SAY_EGGS_BROKEN3 -1469024 -#define SAY_DEATH -1469025 - -#define SPELL_CLEAVE 22540 -#define SPELL_WARSTOMP 24375 -#define SPELL_FIREBALLVOLLEY 22425 -#define SPELL_CONFLAGRATION 23023 - -struct boss_razorgoreAI : public ScriptedAI -{ - boss_razorgoreAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cleave_Timer; - uint32 WarStomp_Timer; - uint32 FireballVolley_Timer; - uint32 Conflagration_Timer; - - void Reset() - { - Cleave_Timer = 15000; //These times are probably wrong - WarStomp_Timer = 35000; - FireballVolley_Timer = 7000; - Conflagration_Timer = 12000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = urand(7000,10000); - } else Cleave_Timer -= diff; - - //WarStomp_Timer - if (WarStomp_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WARSTOMP); - WarStomp_Timer = urand(15000,25000); - } else WarStomp_Timer -= diff; - - //FireballVolley_Timer - if (FireballVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALLVOLLEY); - FireballVolley_Timer = urand(12000,15000); - } else FireballVolley_Timer -= diff; - - //Conflagration_Timer - if (Conflagration_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CONFLAGRATION); - //We will remove this threat reduction and add an aura check. - - //if (DoGetThreat(me->getVictim())) - //DoModifyThreatPercent(me->getVictim(),-50); - - Conflagration_Timer = 12000; - } else Conflagration_Timer -= diff; - - // Aura Check. If the gamer is affected by confliguration we attack a random gamer. - if (me->getVictim() && me->getVictim()->HasAura(SPELL_CONFLAGRATION)) - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - me->TauntApply(pTarget); - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_razorgore(Creature* pCreature) -{ - return new boss_razorgoreAI (pCreature); -} - -void AddSC_boss_razorgore() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_razorgore"; - newscript->GetAI = &GetAI_boss_razorgore; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp deleted file mode 100644 index f6e94307f2f..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Vaelastrasz -SD%Complete: 75 -SDComment: Burning Adrenaline not correctly implemented in core -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_LINE1 -1469026 -#define SAY_LINE2 -1469027 -#define SAY_LINE3 -1469028 -#define SAY_HALFLIFE -1469029 -#define SAY_KILLTARGET -1469030 - -#define GOSSIP_ITEM "Start Event " - -#define SPELL_ESSENCEOFTHERED 23513 -#define SPELL_FLAMEBREATH 23461 -#define SPELL_FIRENOVA 23462 -#define SPELL_TAILSWIPE 15847 -#define SPELL_BURNINGADRENALINE 23620 -#define SPELL_CLEAVE 20684 //Chain cleave is most likely named something different and contains a dummy effect - -struct boss_vaelAI : public ScriptedAI -{ - boss_vaelAI(Creature *c) : ScriptedAI(c) - { - c->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - c->setFaction(35); - c->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - uint64 PlayerGUID; - uint32 SpeechTimer; - uint32 SpeechNum; - uint32 Cleave_Timer; - uint32 FlameBreath_Timer; - uint32 FireNova_Timer; - uint32 BurningAdrenalineCaster_Timer; - uint32 BurningAdrenalineTank_Timer; - uint32 TailSwipe_Timer; - bool HasYelled; - bool DoingSpeech; - - void Reset() - { - PlayerGUID = 0; - SpeechTimer = 0; - SpeechNum = 0; - Cleave_Timer = 8000; //These times are probably wrong - FlameBreath_Timer = 11000; - BurningAdrenalineCaster_Timer = 15000; - BurningAdrenalineTank_Timer = 45000; - FireNova_Timer = 5000; - TailSwipe_Timer = 20000; - HasYelled = false; - DoingSpeech = false; - } - - void BeginSpeech(Unit *pTarget) - { - //Stand up and begin speach - PlayerGUID = pTarget->GetGUID(); - - //10 seconds - DoScriptText(SAY_LINE1, me); - - SpeechTimer = 10000; - SpeechNum = 0; - DoingSpeech = true; - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - void KilledUnit(Unit * victim) - { - if (rand()%5) - return; - - DoScriptText(SAY_KILLTARGET, me, victim); - } - - void EnterCombat(Unit * /*who*/) - { - DoCast(me, SPELL_ESSENCEOFTHERED); - DoZoneInCombat(); - me->SetHealth(int(me->GetMaxHealth()*.3)); - } - - void UpdateAI(const uint32 diff) - { - //Speech - if (DoingSpeech) - { - if (SpeechTimer <= diff) - { - switch (SpeechNum) - { - case 0: - //16 seconds till next line - DoScriptText(SAY_LINE2, me); - SpeechTimer = 16000; - ++SpeechNum; - break; - case 1: - //This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!" - DoScriptText(SAY_LINE3, me); - SpeechTimer = 10000; - ++SpeechNum; - break; - case 2: - me->setFaction(103); - if (PlayerGUID && Unit::GetUnit((*me),PlayerGUID)) - { - AttackStart(Unit::GetUnit((*me),PlayerGUID)); - DoCast(me, SPELL_ESSENCEOFTHERED); - } - SpeechTimer = 0; - DoingSpeech = false; - break; - } - } else SpeechTimer -= diff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - // Yell if hp lower than 15% - if (me->GetHealth()*100 / me->GetMaxHealth() < 15 && !HasYelled) - { - DoScriptText(SAY_HALFLIFE, me); - HasYelled = true; - } - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 15000; - } else Cleave_Timer -= diff; - - //FlameBreath_Timer - if (FlameBreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBREATH); - FlameBreath_Timer = urand(4000,8000); - } else FlameBreath_Timer -= diff; - - //BurningAdrenalineCaster_Timer - if (BurningAdrenalineCaster_Timer <= diff) - { - Unit *pTarget = NULL; - - uint8 i = 0; - while (i < 3) // max 3 tries to get a random target with power_mana - { - ++i; - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); //not aggro leader - if (pTarget && pTarget->getPowerType() == POWER_MANA) - i = 3; - } - if (pTarget) // cast on self (see below) - pTarget->CastSpell(pTarget,SPELL_BURNINGADRENALINE,1); - - BurningAdrenalineCaster_Timer = 15000; - } else BurningAdrenalineCaster_Timer -= diff; - - //BurningAdrenalineTank_Timer - if (BurningAdrenalineTank_Timer <= diff) - { - // have the victim cast the spell on himself otherwise the third effect aura will be applied - // to Vael instead of the player - me->getVictim()->CastSpell(me->getVictim(),SPELL_BURNINGADRENALINE,1); - - BurningAdrenalineTank_Timer = 45000; - } else BurningAdrenalineTank_Timer -= diff; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRENOVA); - FireNova_Timer = 5000; - } else FireNova_Timer -= diff; - - //TailSwipe_Timer - if (TailSwipe_Timer <= diff) - { - //Only cast if we are behind - /*if (!me->HasInArc(M_PI, me->getVictim())) - { - DoCast(me->getVictim(), SPELL_TAILSWIPE); - }*/ - - TailSwipe_Timer = 20000; - } else TailSwipe_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -void SendDefaultMenu_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(boss_vaelAI, pCreature->AI())->BeginSpeech(pPlayer); - } -} - -bool GossipSelect_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiSender == GOSSIP_SENDER_MAIN) - SendDefaultMenu_boss_vael(pPlayer, pCreature, uiAction); - - return true; -} - -bool GossipHello_boss_vael(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - - return true; -} - -CreatureAI* GetAI_boss_vael(Creature* pCreature) -{ - return new boss_vaelAI (pCreature); -} - -void AddSC_boss_vael() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vaelastrasz"; - newscript->GetAI = &GetAI_boss_vael; - newscript->pGossipHello = &GossipHello_boss_vael; - newscript->pGossipSelect = &GossipSelect_boss_vael; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp deleted file mode 100644 index dfeb2519bae..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Victor_Nefarius -SD%Complete: 75 -SDComment: Missing some text, Vael beginning event, and spawns Nef in wrong place -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_GAMESBEGIN_1 -1469004 -#define SAY_GAMESBEGIN_2 -1469005 -#define SAY_VAEL_INTRO -1469006 //when he corrupts Vaelastrasz - -#define GOSSIP_ITEM_1 "I've made no mistakes." -#define GOSSIP_ITEM_2 "You have lost your mind, Nefarius. You speak in riddles." -#define GOSSIP_ITEM_3 "Please do." - -#define CREATURE_BRONZE_DRAKANOID 14263 -#define CREATURE_BLUE_DRAKANOID 14261 -#define CREATURE_RED_DRAKANOID 14264 -#define CREATURE_GREEN_DRAKANOID 14262 -#define CREATURE_BLACK_DRAKANOID 14265 - -#define CREATURE_CHROMATIC_DRAKANOID 14302 -#define CREATURE_NEFARIAN 11583 - -#define ADD_X1 -7591.151855 -#define ADD_X2 -7514.598633 -#define ADD_Y1 -1204.051880 -#define ADD_Y2 -1150.448853 -#define ADD_Z1 476.800476 -#define ADD_Z2 476.796570 - -#define NEF_X -7445 -#define NEF_Y -1332 -#define NEF_Z 536 - -#define HIDE_X -7592 -#define HIDE_Y -1264 -#define HIDE_Z 481 - -#define SPELL_SHADOWBOLT 21077 -#define SPELL_FEAR 26070 - -//This script is complicated -//Instead of morphing Victor Nefarius we will have him control phase 1 -//And then have him spawn "Nefarian" for phase 2 -//When phase 2 starts Victor Nefarius will go into hiding and stop attacking -//If Nefarian despawns because he killed the players then this guy will EnterEvadeMode -//and allow players to start the event over -//If nefarian dies then he will kill himself then he will kill himself in his hiding place -//To prevent players from doing the event twice - -struct boss_victor_nefariusAI : public ScriptedAI -{ - boss_victor_nefariusAI(Creature *c) : ScriptedAI(c) - { - NefarianGUID = 0; - switch (urand(0,19)) - { - case 0: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 1: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 2: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 3: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 4: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 5: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 6: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 7: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 8: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 9: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 10: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 11: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 12: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 13: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 14: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 15: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 16: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 17: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 18: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 19: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - } - } - - uint32 SpawnedAdds; - uint32 AddSpawnTimer; - uint32 ShadowBoltTimer; - uint32 FearTimer; - uint32 MindControlTimer; - uint32 ResetTimer; - uint32 DrakType1; - uint32 DrakType2; - uint64 NefarianGUID; - uint32 NefCheckTime; - - void Reset() - { - SpawnedAdds = 0; - AddSpawnTimer = 10000; - ShadowBoltTimer = 5000; - FearTimer = 8000; - ResetTimer = 900000; //On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier - NefarianGUID = 0; - NefCheckTime = 2000; - - me->SetUInt32Value(UNIT_NPC_FLAGS,1); - me->setFaction(35); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void BeginEvent(Player *pTarget) - { - DoScriptText(SAY_GAMESBEGIN_2, me); - - //Trinity::Singleton::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); - /* - list ::const_iterator i = MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); - - for (i = MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); i != MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().end(); ++i) - { - AttackStart((*i)); - } - */ - me->SetUInt32Value(UNIT_NPC_FLAGS,0); - me->setFaction(103); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - AttackStart(pTarget); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void MoveInLineOfSight(Unit *who) - { - //We simply use this function to find players until we can use pMap->GetPlayers() - - if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsHostileTo(who)) - { - //Add them to our threat list - me->AddThreat(who, 0.0f); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Only do this if we haven't spawned nef yet - if (SpawnedAdds < 42) - { - //ShadowBoltTimer - if (ShadowBoltTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SHADOWBOLT); - - ShadowBoltTimer = urand(3000,10000); - } else ShadowBoltTimer -= diff; - - //FearTimer - if (FearTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_FEAR); - - FearTimer = 10000 + (rand()%10000); - } else FearTimer -= diff; - - //Add spawning mechanism - if (AddSpawnTimer <= diff) - { - //Spawn 2 random types of creatures at the 2 locations - uint32 CreatureID; - Creature* Spawned = NULL; - Unit *pTarget = NULL; - - //1 in 3 chance it will be a chromatic - if (urand(0,2) == 0) - CreatureID = CREATURE_CHROMATIC_DRAKANOID; - else - CreatureID = DrakType1; - - ++SpawnedAdds; - - //Spawn Creature and force it to start attacking a random target - Spawned = me->SummonCreature(CreatureID,ADD_X1,ADD_Y1,ADD_Z1,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget && Spawned) - { - Spawned->AI()->AttackStart(pTarget); - Spawned->setFaction(103); - } - - //1 in 3 chance it will be a chromatic - if (urand(0,2) == 0) - CreatureID = CREATURE_CHROMATIC_DRAKANOID; - else - CreatureID = DrakType2; - - ++SpawnedAdds; - - Spawned = me->SummonCreature(CreatureID,ADD_X2,ADD_Y2,ADD_Z2,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget && Spawned) - { - Spawned->AI()->AttackStart(pTarget); - Spawned->setFaction(103); - } - - //Begin phase 2 by spawning Nefarian and what not - if (SpawnedAdds >= 42) - { - //Teleport Victor Nefarius way out of the map - //MapManager::Instance().GetMap(me->GetMapId(), me)->CreatureRelocation(me,0,0,-5000,0); - - //Inturrupt any spell casting - me->InterruptNonMeleeSpells(false); - - //Root self - DoCast(me, 33356); - - //Make super invis - DoCast(me, 8149); - - //Teleport self to a hiding spot (this causes errors in the Trinity log but no real issues) - DoTeleportTo(HIDE_X,HIDE_Y,HIDE_Z); - me->addUnitState(UNIT_STAT_FLEEING); - - //Spawn nef and have him attack a random target - Creature* Nefarian = me->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget && Nefarian) - { - Nefarian->AI()->AttackStart(pTarget); - Nefarian->setFaction(103); - NefarianGUID = Nefarian->GetGUID(); - } - else error_log("TSCR: Blackwing Lair: Unable to spawn nefarian properly."); - } - - AddSpawnTimer = 4000; - } else AddSpawnTimer -= diff; - } - else if (NefarianGUID) - { - if (NefCheckTime <= diff) - { - Unit* Nefarian = Unit::GetCreature((*me),NefarianGUID); - - //If nef is dead then we die to so the players get out of combat - //and cannot repeat the event - if (!Nefarian || !Nefarian->isAlive()) - { - NefarianGUID = 0; - me->ForcedDespawn(); - } - - NefCheckTime = 2000; - } else NefCheckTime -= diff; - } - } -}; - -CreatureAI* GetAI_boss_victor_nefarius(Creature* pCreature) -{ - return new boss_victor_nefariusAI (pCreature); -} - -bool GossipHello_boss_victor_nefarius(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1 , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(7134, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_boss_victor_nefarius(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(7198, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(7199, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - DoScriptText(SAY_GAMESBEGIN_1, pCreature); - CAST_AI(boss_victor_nefariusAI, pCreature->AI())->BeginEvent(pPlayer); - break; - } - return true; -} - -void AddSC_boss_victor_nefarius() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_victor_nefarius"; - newscript->GetAI = &GetAI_boss_victor_nefarius; - newscript->pGossipHello = &GossipHello_boss_victor_nefarius; - newscript->pGossipSelect = &GossipSelect_boss_victor_nefarius; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp b/src/server/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp deleted file mode 100644 index d6403fa1206..00000000000 --- a/src/server/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Blackwing_Lair -SD%Complete: 0 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - diff --git a/src/server/scripts/eastern_kingdoms/blasted_lands.cpp b/src/server/scripts/eastern_kingdoms/blasted_lands.cpp deleted file mode 100644 index 768242fcd22..00000000000 --- a/src/server/scripts/eastern_kingdoms/blasted_lands.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Blasted_Lands -SD%Complete: 90 -SDComment: Quest support: 2784, 2801, 3628. Missing some texts for Fallen Hero. Teleporter to Rise of the Defiler missing group support. -SDCategory: Blasted Lands -EndScriptData */ - -/* ContentData -npc_deathly_usher -npc_fallen_hero_of_horde -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_deathly_usher -######*/ - -#define GOSSIP_ITEM_USHER "I wish to to visit the Rise of the Defiler." - -#define SPELL_TELEPORT_SINGLE 12885 -#define SPELL_TELEPORT_SINGLE_IN_GROUP 13142 -#define SPELL_TELEPORT_GROUP 27686 - -bool GossipHello_npc_deathly_usher(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(3628) == QUEST_STATUS_INCOMPLETE && pPlayer->HasItemCount(10757, 1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_USHER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_deathly_usher(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, SPELL_TELEPORT_SINGLE, true); - } - - return true; -} - -/*###### -## npc_fallen_hero_of_horde -######*/ -#define GOSSIP_H_F1 "Why are you here?" -#define GOSSIP_H_F2 "Continue story..." - -#define GOSSIP_ITEM_FALLEN "Continue..." - -#define GOSSIP_ITEM_FALLEN1 "What could be worse than death?" -#define GOSSIP_ITEM_FALLEN2 "Subordinates?" -#define GOSSIP_ITEM_FALLEN3 "What are the stones of binding?" -#define GOSSIP_ITEM_FALLEN4 "You can count on me, Hero" -#define GOSSIP_ITEM_FALLEN5 "I shall" - -bool GossipHello_npc_fallen_hero_of_horde(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(2784) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_H_F1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - if (pPlayer->GetQuestStatus(2801) == QUEST_STATUS_INCOMPLETE && pPlayer->GetTeam() == HORDE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_H_F2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - if (pPlayer->GetQuestStatus(2801) == QUEST_STATUS_INCOMPLETE && pPlayer->GetTeam() == ALLIANCE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_H_F1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_fallen_hero_of_horde(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - pPlayer->SEND_GOSSIP_MENU(1392, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - pPlayer->SEND_GOSSIP_MENU(1411, pCreature->GetGUID()); - if (pPlayer->GetQuestStatus(2784) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(2784); - if (pPlayer->GetTeam() == ALLIANCE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(1411, pCreature->GetGUID()); - } - break; - - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); - pPlayer->SEND_GOSSIP_MENU(1451, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+21: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); - pPlayer->SEND_GOSSIP_MENU(1452, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+22: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23); - pPlayer->SEND_GOSSIP_MENU(1453, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+23: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24); - pPlayer->SEND_GOSSIP_MENU(1454, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+24: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25); - pPlayer->SEND_GOSSIP_MENU(1455, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+25: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26); - pPlayer->SEND_GOSSIP_MENU(1456, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+26: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(2801); - break; - } - return true; -} - -void AddSC_blasted_lands() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_deathly_usher"; - newscript->pGossipHello = &GossipHello_npc_deathly_usher; - newscript->pGossipSelect = &GossipSelect_npc_deathly_usher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_fallen_hero_of_horde"; - newscript->pGossipHello = &GossipHello_npc_fallen_hero_of_horde; - newscript->pGossipSelect = &GossipSelect_npc_fallen_hero_of_horde; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/boss_kruul.cpp b/src/server/scripts/eastern_kingdoms/boss_kruul.cpp deleted file mode 100644 index 44a6431f9ea..00000000000 --- a/src/server/scripts/eastern_kingdoms/boss_kruul.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kruul -SD%Complete: 100 -SDComment: Highlord Kruul are presumably no longer in-game on regular bases, however future events could bring him back. -SDCategory: Bosses -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWVOLLEY 21341 -#define SPELL_CLEAVE 20677 -#define SPELL_THUNDERCLAP 23931 -#define SPELL_TWISTEDREFLECTION 21063 -#define SPELL_VOIDBOLT 21066 -#define SPELL_RAGE 21340 -#define SPELL_CAPTURESOUL 21054 - -struct boss_kruulAI : public ScriptedAI -{ - boss_kruulAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowVolley_Timer; - uint32 Cleave_Timer; - uint32 ThunderClap_Timer; - uint32 TwistedReflection_Timer; - uint32 VoidBolt_Timer; - uint32 Rage_Timer; - uint32 Hound_Timer; - - void Reset() - { - ShadowVolley_Timer = 10000; - Cleave_Timer = 14000; - ThunderClap_Timer = 20000; - TwistedReflection_Timer = 25000; - VoidBolt_Timer = 30000; - Rage_Timer = 60000; //Cast rage after 1 minute - Hound_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit() - { - // When a player, pet or totem gets killed, Lord Kazzak casts this spell to instantly regenerate 70,000 health. - DoCast(me, SPELL_CAPTURESOUL); - } - - void SummonHounds(Unit* pVictim) - { - if (Creature *Hound = DoSpawnCreature(19207, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) - Hound->AI()->AttackStart(pVictim); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ShadowVolley_Timer - if (ShadowVolley_Timer <= diff) - { - if (urand(0,99) < 45) - DoCast(me->getVictim(), SPELL_SHADOWVOLLEY); - - ShadowVolley_Timer = 5000; - } else ShadowVolley_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - if (urand(0,1)) - DoCast(me->getVictim(), SPELL_CLEAVE); - - Cleave_Timer = 10000; - } else Cleave_Timer -= diff; - - //ThunderClap_Timer - if (ThunderClap_Timer <= diff) - { - if (urand(0,9) < 2) - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - - ThunderClap_Timer = 12000; - } else ThunderClap_Timer -= diff; - - //TwistedReflection_Timer - if (TwistedReflection_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TWISTEDREFLECTION); - TwistedReflection_Timer = 30000; - } else TwistedReflection_Timer -= diff; - - //VoidBolt_Timer - if (VoidBolt_Timer <= diff) - { - if (urand(0,9) < 4) - DoCast(me->getVictim(), SPELL_VOIDBOLT); - - VoidBolt_Timer = 18000; - } else VoidBolt_Timer -= diff; - - //Rage_Timer - if (Rage_Timer <= diff) - { - DoCast(me, SPELL_RAGE); - Rage_Timer = 70000; - } else Rage_Timer -= diff; - - //Hound_Timer - if (Hound_Timer <= diff) - { - SummonHounds(me->getVictim()); - SummonHounds(me->getVictim()); - SummonHounds(me->getVictim()); - - Hound_Timer = 45000; - } else Hound_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_kruul(Creature* pCreature) -{ - return new boss_kruulAI (pCreature); -} - -void AddSC_boss_kruul() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kruul"; - newscript->GetAI = &GetAI_boss_kruul; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/burning_steppes.cpp b/src/server/scripts/eastern_kingdoms/burning_steppes.cpp deleted file mode 100644 index 5a1e338b70f..00000000000 --- a/src/server/scripts/eastern_kingdoms/burning_steppes.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Burning_Steppes -SD%Complete: 100 -SDComment: Quest support: 4224, 4866 -SDCategory: Burning Steppes -EndScriptData */ - -/* ContentData -npc_ragged_john -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_ragged_john -######*/ - -#define GOSSIP_HELLO "Official buisness, John. I need some information about Marsha Windsor. Tell me about the last time you saw him." -#define GOSSIP_SELECT1 "So what did you do?" -#define GOSSIP_SELECT2 "Start making sense, dwarf. I don't want to have anything to do with your cracker, your pappy, or any sort of 'discreditin'." -#define GOSSIP_SELECT3 "Ironfoe?" -#define GOSSIP_SELECT4 "Interesting... continue John." -#define GOSSIP_SELECT5 "So that's how Windsor died..." -#define GOSSIP_SELECT6 "So how did he die?" -#define GOSSIP_SELECT7 "Ok so where the hell is he? Wait a minute! Are you drunk?" -#define GOSSIP_SELECT8 "WHY is he in Blackrock Depths?" -#define GOSSIP_SELECT9 "300? So the Dark Irons killed him and dragged him into the Depths?" -#define GOSSIP_SELECT10 "Ahh... Ironfoe" -#define GOSSIP_SELECT11 "Thanks, Ragged John. Your story was very uplifting and informative" - -struct npc_ragged_johnAI : public ScriptedAI -{ - npc_ragged_johnAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - - void MoveInLineOfSight(Unit *who) - { - if (who->HasAura(16468)) - { - if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 15) && who->isInAccessiblePlaceFor(me)) - { - DoCast(who, 16472); - CAST_PLR(who)->AreaExploredOrEventHappens(4866); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) {} -}; - -CreatureAI* GetAI_npc_ragged_john(Creature* pCreature) -{ - return new npc_ragged_johnAI (pCreature); -} - -bool GossipHello_npc_ragged_john(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(4224) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(2713, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_ragged_john(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2714, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(2715, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(2716, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(2717, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - pPlayer->SEND_GOSSIP_MENU(2718, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - pPlayer->SEND_GOSSIP_MENU(2719, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - pPlayer->SEND_GOSSIP_MENU(2720, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); - pPlayer->SEND_GOSSIP_MENU(2721, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+8: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); - pPlayer->SEND_GOSSIP_MENU(2722, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+9: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); - pPlayer->SEND_GOSSIP_MENU(2723, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+10: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - pPlayer->SEND_GOSSIP_MENU(2725, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(4224); - break; - } - return true; -} - -void AddSC_burning_steppes() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_ragged_john"; - newscript->GetAI = &GetAI_npc_ragged_john; - newscript->pGossipHello = &GossipHello_npc_ragged_john; - newscript->pGossipSelect = &GossipSelect_npc_ragged_john; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/deadmines/boss_mr_smite.cpp b/src/server/scripts/eastern_kingdoms/deadmines/boss_mr_smite.cpp deleted file mode 100644 index 5c6bab46e5a..00000000000 --- a/src/server/scripts/eastern_kingdoms/deadmines/boss_mr_smite.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss Mr.Smite -SD%Complete: -SDComment: Timers and say taken from acid script -EndScriptData */ - -#include "ScriptedPch.h" -#include "deadmines.h" - -enum eSpels -{ - SPELL_TRASH = 3391, - SPELL_SMITE_STOMP = 6432, - SPELL_SMITE_SLAM = 6435, - SPELL_NIMBLE_REFLEXES = 6264, - - EQUIP_SWORD = 5191, - EQUIP_MACE = 7230, - - SAY_AGGRO = -1036001 -}; - -struct boss_mr_smiteAI : public ScriptedAI -{ - boss_mr_smiteAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiTrashTimer; - uint32 uiSlamTimer; - uint32 uiNimbleReflexesTimer; - - uint8 uiHealth; - - uint32 uiPhase; - uint32 uiTimer; - - void Reset() - { - uiTrashTimer = urand(5000,9000); - uiSlamTimer = 9000; - uiNimbleReflexesTimer = urand(15500,31600); - - uiHealth = 0; - - uiPhase = 0; - uiTimer = 0; - - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - bool bCheckChances() - { - uint32 uiChances = urand(0,99); - if (uiChances <= 15) - return false; - else - return true; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - /*START ACID-AI*/ - if (uiTrashTimer <= uiDiff) - { - if (bCheckChances()) - DoCast(me, SPELL_TRASH); - uiTrashTimer = urand(6000,15500); - } else uiTrashTimer -= uiDiff; - - if (uiSlamTimer <= uiDiff) - { - if (bCheckChances()) - DoCast(me->getVictim(), SPELL_SMITE_SLAM); - uiSlamTimer = 11000; - } else uiSlamTimer -= uiDiff; - - if (uiNimbleReflexesTimer <= uiDiff) - { - if (bCheckChances()) - DoCast(me, SPELL_NIMBLE_REFLEXES); - uiNimbleReflexesTimer = urand(27300,60100); - } else uiNimbleReflexesTimer -= uiDiff; - /*END ACID-AI*/ - - if (uiHealth == 0 && me->GetHealth()*100 / me->GetMaxHealth() <= 66 || uiHealth == 1 && me->GetHealth()*100 / me->GetMaxHealth() <= 33) - { - ++uiHealth; - DoCastAOE(SPELL_SMITE_STOMP,false); - SetCombatMovement(false); - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_SMITE_CHEST))) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(1,-3.00+pGo->GetPositionX(),pGo->GetPositionY(),pGo->GetPositionZ()); - } - } - - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - me->HandleEmoteCommand(EMOTE_STATE_KNEEL); //dosen't work? - uiTimer = 1000; - uiPhase = 2; - break; - case 2: - if (uiHealth == 1) - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); - else - SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - uiTimer = 500; - uiPhase = 3; - break; - case 3: - SetCombatMovement(true); - me->GetMotionMaster()->MoveChase(me->getVictim(), me->m_CombatDistance); - uiPhase = 0; - break; - - } - } else uiTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - uiTimer = 1500; - uiPhase = 1; - } - -}; -CreatureAI* GetAI_boss_mr_smite(Creature* pCreature) -{ - return new boss_mr_smiteAI (pCreature); -} - -void AddSC_boss_mr_smite() -{ - Script* newscript; - newscript = new Script; - newscript->Name = "boss_mr_smite"; - newscript->GetAI = &GetAI_boss_mr_smite; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/deadmines/deadmines.cpp b/src/server/scripts/eastern_kingdoms/deadmines/deadmines.cpp deleted file mode 100644 index 5bc1121bead..00000000000 --- a/src/server/scripts/eastern_kingdoms/deadmines/deadmines.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Deadmines -SD%Complete: 0 -SDComment: Placeholder -SDCategory: Deadmines -EndScriptData */ - -#include "ScriptedPch.h" -#include "deadmines.h" -#include "Spell.h" - -/*##### -# item_Defias_Gunpowder -#####*/ - -bool ItemUse_item_defias_gunpowder(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) -{ - ScriptedInstance *pInstance = pPlayer->GetInstanceData(); - - if (!pInstance) - { - pPlayer->GetSession()->SendNotification("Instance script not initialized"); - return true; - } - if (pInstance->GetData(EVENT_STATE)!= CANNON_NOT_USED) - return false; - if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT && - targets.getGOTarget()->GetEntry() == GO_DEFIAS_CANNON) - { - pInstance->SetData(EVENT_STATE, CANNON_GUNPOWDER_USED); - } - - pPlayer->DestroyItemCount(pItem->GetEntry(), 1, true); - return true; -} - -void AddSC_deadmines() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "item_defias_gunpowder"; - newscript->pItemUse = &ItemUse_item_defias_gunpowder; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/deadmines/deadmines.h b/src/server/scripts/eastern_kingdoms/deadmines/deadmines.h deleted file mode 100644 index 203494ad5b7..00000000000 --- a/src/server/scripts/eastern_kingdoms/deadmines/deadmines.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef DEF_DEADMINES_H -#define DEF_DEADMINES_H - -#include "ScriptedPch.h" - -enum CannonState -{ - CANNON_NOT_USED, - CANNON_GUNPOWDER_USED, - CANNON_BLAST_INITIATED, - PIRATES_ATTACK, - EVENT_DONE -}; - -enum Data -{ - EVENT_STATE, - EVENT_RHAHKZOR -}; - -enum Data64 -{ - DATA_SMITE_CHEST -}; - -enum GameObjects -{ - GO_FACTORY_DOOR = 13965, - GO_IRONCLAD_DOOR = 16397, - GO_DEFIAS_CANNON = 16398, - GO_DOOR_LEVER = 101833, - GO_MR_SMITE_CHEST = 144111 -}; -#endif - diff --git a/src/server/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp b/src/server/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp deleted file mode 100644 index f1aa0c62b8a..00000000000 --- a/src/server/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Deadmines -SD%Complete: 100 -SDComment: -SDCategory: Deadmines -EndScriptData */ - -#include "ScriptedPch.h" -#include "deadmines.h" - -enum Sounds -{ - SOUND_CANNONFIRE = 1400, - SOUND_DESTROYDOOR = 3079, - SOUND_MR_SMITE_ALARM1 = 5775, - SOUND_MR_SMITE_ALARM2 = 5777 -}; - -#define SAY_MR_SMITE_ALARM1 "You there, check out that noise!" -#define SAY_MR_SMITE_ALARM2 "We're under attack! A vast, ye swabs! Repel the invaders!" - -enum Misc -{ - DATA_CANNON_BLAST_TIMER = 3000, - DATA_PIRATES_DELAY_TIMER = 1000 -}; - -struct instance_deadmines : public ScriptedInstance -{ - instance_deadmines(Map* pMap) : ScriptedInstance(pMap) { Initialize(); }; - - uint64 FactoryDoorGUID; - uint64 IronCladDoorGUID; - uint64 DefiasCannonGUID; - uint64 DoorLeverGUID; - uint64 DefiasPirate1GUID; - uint64 DefiasPirate2GUID; - uint64 DefiasCompanionGUID; - - uint32 State; - uint32 CannonBlast_Timer; - uint32 PiratesDelay_Timer; - uint64 uiSmiteChestGUID; - - void Initialize() - { - FactoryDoorGUID = 0; - IronCladDoorGUID = 0; - DefiasCannonGUID = 0; - DoorLeverGUID = 0; - DefiasPirate1GUID = 0; - DefiasPirate2GUID = 0; - DefiasCompanionGUID = 0; - - State = CANNON_NOT_USED; - uiSmiteChestGUID = 0; - } - - virtual void Update(uint32 diff) - { - if (!IronCladDoorGUID || !DefiasCannonGUID || !DoorLeverGUID) - return; - - GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID); - if (!pIronCladDoor) - return; - - switch (State) - { - case CANNON_GUNPOWDER_USED: - CannonBlast_Timer = DATA_CANNON_BLAST_TIMER; - // it's a hack - Mr. Smite should do that but his too far away - pIronCladDoor->SetName("Mr. Smite"); - pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM1, LANG_UNIVERSAL, 0); - DoPlaySound(pIronCladDoor, SOUND_MR_SMITE_ALARM1); - State = CANNON_BLAST_INITIATED; - break; - case CANNON_BLAST_INITIATED: - PiratesDelay_Timer = DATA_PIRATES_DELAY_TIMER; - if (CannonBlast_Timer <= diff) - { - SummonCreatures(); - ShootCannon(); - BlastOutDoor(); - LeverStucked(); - pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM2, LANG_UNIVERSAL, 0); - DoPlaySound(pIronCladDoor, SOUND_MR_SMITE_ALARM2); - State = PIRATES_ATTACK; - } else CannonBlast_Timer -= diff; - break; - case PIRATES_ATTACK: - if (PiratesDelay_Timer <= diff) - { - MoveCreaturesInside(); - State = EVENT_DONE; - } else PiratesDelay_Timer -= diff; - break; - } - } - - void SummonCreatures() - { - if (GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID)) - { - Creature *DefiasPirate1 = pIronCladDoor->SummonCreature(657,pIronCladDoor->GetPositionX() - 2,pIronCladDoor->GetPositionY()-7,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - Creature *DefiasPirate2 = pIronCladDoor->SummonCreature(657,pIronCladDoor->GetPositionX() + 3,pIronCladDoor->GetPositionY()-6,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - Creature *DefiasCompanion = pIronCladDoor->SummonCreature(3450,pIronCladDoor->GetPositionX() + 2,pIronCladDoor->GetPositionY()-6,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - - DefiasPirate1GUID = DefiasPirate1->GetGUID(); - DefiasPirate2GUID = DefiasPirate2->GetGUID(); - DefiasCompanionGUID = DefiasCompanion->GetGUID(); - } - } - - void MoveCreaturesInside() - { - if (!DefiasPirate1GUID || !DefiasPirate2GUID || !DefiasCompanionGUID) - return; - - Creature *pDefiasPirate1 = instance->GetCreature(DefiasPirate1GUID); - Creature *pDefiasPirate2 = instance->GetCreature(DefiasPirate2GUID); - Creature *pDefiasCompanion = instance->GetCreature(DefiasCompanionGUID); - if (!pDefiasPirate1 || !pDefiasPirate2 || !pDefiasCompanion) - return; - - MoveCreatureInside(pDefiasPirate1); - MoveCreatureInside(pDefiasPirate2); - MoveCreatureInside(pDefiasCompanion); - } - - void MoveCreatureInside(Creature* pCreature) - { - pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pCreature->GetMotionMaster()->MovePoint(0, -102.7,-655.9, pCreature->GetPositionZ()); - } - - void ShootCannon() - { - if (GameObject *pDefiasCannon = instance->GetGameObject(DefiasCannonGUID)) - { - pDefiasCannon->SetGoState(GO_STATE_ACTIVE); - DoPlaySound(pDefiasCannon, SOUND_CANNONFIRE); - } - } - - void BlastOutDoor() - { - if (GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID)) - { - pIronCladDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - DoPlaySound(pIronCladDoor, SOUND_DESTROYDOOR); - } - } - - void LeverStucked() - { - if (GameObject *pDoorLever = instance->GetGameObject(DoorLeverGUID)) - pDoorLever->SetUInt32Value(GAMEOBJECT_FLAGS, 4); - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_FACTORY_DOOR: FactoryDoorGUID = pGo->GetGUID(); break; - case GO_IRONCLAD_DOOR: IronCladDoorGUID = pGo->GetGUID(); break; - case GO_DEFIAS_CANNON: DefiasCannonGUID = pGo->GetGUID(); break; - case GO_DOOR_LEVER: DoorLeverGUID = pGo->GetGUID(); break; - case GO_MR_SMITE_CHEST: uiSmiteChestGUID = pGo->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch (type) - { - case EVENT_STATE: - if (DefiasCannonGUID && IronCladDoorGUID) - State=data; - break; - case EVENT_RHAHKZOR: - if (data == DONE) - if (GameObject* pGo = instance->GetGameObject(FactoryDoorGUID)) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - } - } - - uint32 GetData(uint32 type) - { - switch (type) - { - case EVENT_STATE: - return State; - } - - return 0; - } - - uint64 GetData64(uint32 data) - { - switch (data) - { - case DATA_SMITE_CHEST: - return uiSmiteChestGUID; - } - - return 0; - } - - void DoPlaySound(GameObject* unit, uint32 sound) - { - WorldPacket data(4); - data.SetOpcode(SMSG_PLAY_SOUND); - data << uint32(sound); - unit->SendMessageToSet(&data,false); - } - - void DoPlaySoundCreature(Unit* unit, uint32 sound) - { - WorldPacket data(4); - data.SetOpcode(SMSG_PLAY_SOUND); - data << uint32(sound); - unit->SendMessageToSet(&data,false); - } -}; - -InstanceData* GetInstanceData_instance_deadmines(Map* pMap) -{ - return new instance_deadmines(pMap); -} - -void AddSC_instance_deadmines() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_deadmines"; - newscript->GetInstanceData = &GetInstanceData_instance_deadmines; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/dun_morogh.cpp b/src/server/scripts/eastern_kingdoms/dun_morogh.cpp deleted file mode 100644 index 4c47cc8bbb8..00000000000 --- a/src/server/scripts/eastern_kingdoms/dun_morogh.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Dun_Morogh -SD%Complete: 50 -SDComment: Quest support: 1783 -SDCategory: Dun Morogh -EndScriptData */ - -/* ContentData -npc_narm_faulk -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_narm_faulk -######*/ - -// signed for 6172 -#define SAY_HEAL -1100280 - -struct npc_narm_faulkAI : public ScriptedAI -{ - uint32 lifeTimer; - bool spellHit; - - npc_narm_faulkAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - lifeTimer = 120000; - me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - me->SetStandState(UNIT_STAND_STATE_DEAD); - spellHit = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void MoveInLineOfSight(Unit * /*who*/) - { - return; - } - - void UpdateAI(const uint32 diff) - { - if (me->IsStandState()) - { - if (lifeTimer <= diff) - { - EnterEvadeMode(); - return; - } - else - lifeTimer -= diff; - } - } - - void SpellHit(Unit * /*Hitter*/, const SpellEntry *Spellkind) - { - if (Spellkind->Id == 8593 && !spellHit) - { - DoCast(me, 32343); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); - //me->RemoveAllAuras(); - DoScriptText(SAY_HEAL, me); - spellHit = true; - } - } - -}; -CreatureAI* GetAI_npc_narm_faulk(Creature* pCreature) -{ - return new npc_narm_faulkAI (pCreature); -} - -void AddSC_dun_morogh() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_narm_faulk"; - newscript->GetAI = &GetAI_npc_narm_faulk; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/duskwood.cpp b/src/server/scripts/eastern_kingdoms/duskwood.cpp deleted file mode 100644 index 89c0ebe4213..00000000000 --- a/src/server/scripts/eastern_kingdoms/duskwood.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2006 - 2009 kb_z - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Duskwood -SD%Complete: 100 -SDComment: Quest Support:8735 -SDCategory: Duskwood -EndScriptData */ - -#include "ScriptedPch.h" - -/*###### -# at_twilight_grove -######*/ - -bool AreaTrigger_at_twilight_grove(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - if (pPlayer->HasQuestForItem(21149)) - { - if (Unit* TCorrupter = pPlayer->SummonCreature(15625,-10328.16,-489.57,49.95,0,TEMPSUMMON_MANUAL_DESPAWN,60000)) - { - TCorrupter->setFaction(14); - TCorrupter->SetMaxHealth(832750); - } - if (Unit* CorrupterSpeaker = pPlayer->SummonCreature(1,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ()-1,0,TEMPSUMMON_TIMED_DESPAWN,15000)) - { - CorrupterSpeaker->SetName("Twilight Corrupter"); - CorrupterSpeaker->SetVisibility(VISIBILITY_ON); - CorrupterSpeaker->MonsterYell("Come, $N. See what the Nightmare brings...",0,pPlayer->GetGUID()); - } - } - return false; -}; - -/*###### -# boss_twilight_corrupter -######*/ - -#define SPELL_SOUL_CORRUPTION 25805 -#define SPELL_CREATURE_OF_NIGHTMARE 25806 -#define SPELL_LEVEL_UP 24312 - -struct boss_twilight_corrupterAI : public ScriptedAI -{ - boss_twilight_corrupterAI(Creature *c) : ScriptedAI(c) {} - - uint32 SoulCorruption_Timer; - uint32 CreatureOfNightmare_Timer; - uint8 KillCount; - - void Reset() - { - SoulCorruption_Timer = 15000; - CreatureOfNightmare_Timer = 30000; - KillCount = 0; - } - void EnterCombat(Unit* /*who*/) - { - me->MonsterYell("The Nightmare cannot be stopped!",0,me->GetGUID()); - } - - void KilledUnit(Unit* victim) - { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - ++KillCount; - me->MonsterTextEmote("Twilight Corrupter squeezes the last bit of life out of $N and swallows their soul.", victim->GetGUID(),true); - - if (KillCount == 3) - { - DoCast(me, SPELL_LEVEL_UP, true); - KillCount = 0; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - if (SoulCorruption_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOUL_CORRUPTION); - SoulCorruption_Timer = rand()%4000+15000; //gotta confirm Timers - } else SoulCorruption_Timer-=diff; - if (CreatureOfNightmare_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CREATURE_OF_NIGHTMARE); - CreatureOfNightmare_Timer = 45000; //gotta confirm Timers - } else CreatureOfNightmare_Timer-=diff; - DoMeleeAttackIfReady(); - }; -}; -CreatureAI* GetAI_boss_twilight_corrupter(Creature* pCreature) -{ - return new boss_twilight_corrupterAI (pCreature); -} - -void AddSC_duskwood() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_twilight_corrupter"; - newscript->GetAI = &GetAI_boss_twilight_corrupter; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_twilight_grove"; - newscript->pAreaTrigger = &AreaTrigger_at_twilight_grove; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/eastern_plaguelands.cpp b/src/server/scripts/eastern_kingdoms/eastern_plaguelands.cpp deleted file mode 100644 index 0c1d3e9072c..00000000000 --- a/src/server/scripts/eastern_kingdoms/eastern_plaguelands.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Eastern_Plaguelands -SD%Complete: 100 -SDComment: Quest support: 5211, 5742. Special vendor Augustus the Touched -SDCategory: Eastern Plaguelands -EndScriptData */ - -/* ContentData -mobs_ghoul_flayer -npc_augustus_the_touched -npc_darrowshire_spirit -npc_tirion_fordring -EndContentData */ - -#include "ScriptedPch.h" - -//id8530 - cannibal ghoul -//id8531 - gibbering ghoul -//id8532 - diseased flayer - -struct mobs_ghoul_flayerAI : public ScriptedAI -{ - mobs_ghoul_flayerAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - - void EnterCombat(Unit* /*who*/) {} - - void JustDied(Unit* Killer) - { - if (Killer->GetTypeId() == TYPEID_PLAYER) - me->SummonCreature(11064, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000); - } -}; - -CreatureAI* GetAI_mobs_ghoul_flayer(Creature* pCreature) -{ - return new mobs_ghoul_flayerAI (pCreature); -} - -/*###### -## npc_augustus_the_touched -######*/ - -bool GossipHello_npc_augustus_the_touched(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(6164)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_augustus_the_touched(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - return true; -} - -/*###### -## npc_darrowshire_spirit -######*/ - -#define SPELL_SPIRIT_SPAWNIN 17321 - -struct npc_darrowshire_spiritAI : public ScriptedAI -{ - npc_darrowshire_spiritAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - DoCast(me, SPELL_SPIRIT_SPAWNIN); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) {} - -}; -CreatureAI* GetAI_npc_darrowshire_spirit(Creature* pCreature) -{ - return new npc_darrowshire_spiritAI (pCreature); -} - -bool GossipHello_npc_darrowshire_spirit(Player* pPlayer, Creature* pCreature) -{ - pPlayer->SEND_GOSSIP_MENU(3873, pCreature->GetGUID()); - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - return true; -} - -/*###### -## npc_tirion_fordring -######*/ - -#define GOSSIP_HELLO "I am ready to hear your tale, Tirion." -#define GOSSIP_SELECT1 "Thank you, Tirion. What of your identity?" -#define GOSSIP_SELECT2 "That is terrible." -#define GOSSIP_SELECT3 "I will, Tirion." - -bool GossipHello_npc_tirion_fordring(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(5742) == QUEST_STATUS_INCOMPLETE && pPlayer->getStandState() == UNIT_STAND_STATE_SIT) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_tirion_fordring(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(4493, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(4494, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(4495, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(5742); - break; - } - return true; -} - -void AddSC_eastern_plaguelands() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mobs_ghoul_flayer"; - newscript->GetAI = &GetAI_mobs_ghoul_flayer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_augustus_the_touched"; - newscript->pGossipHello = &GossipHello_npc_augustus_the_touched; - newscript->pGossipSelect = &GossipSelect_npc_augustus_the_touched; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_darrowshire_spirit"; - newscript->GetAI = &GetAI_npc_darrowshire_spirit; - newscript->pGossipHello = &GossipHello_npc_darrowshire_spirit; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tirion_fordring"; - newscript->pGossipHello = &GossipHello_npc_tirion_fordring; - newscript->pGossipSelect = &GossipSelect_npc_tirion_fordring; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/elwynn_forest.cpp b/src/server/scripts/eastern_kingdoms/elwynn_forest.cpp deleted file mode 100644 index b978507c557..00000000000 --- a/src/server/scripts/eastern_kingdoms/elwynn_forest.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Elwynn_Forest -SD%Complete: 50 -SDComment: Quest support: 1786 -SDCategory: Elwynn Forest -EndScriptData */ - -/* ContentData -npc_henze_faulk -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_henze_faulk -######*/ - -#define SAY_HEAL -1100280 - -struct npc_henze_faulkAI : public ScriptedAI -{ - uint32 lifeTimer; - bool spellHit; - - npc_henze_faulkAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - lifeTimer = 120000; - me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - me->SetStandState(UNIT_STAND_STATE_DEAD); // lay down - spellHit = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void MoveInLineOfSight(Unit * /*who*/) - { - return; - } - - void UpdateAI(const uint32 diff) - { - if (me->IsStandState()) - { - if (lifeTimer <= diff) - { - EnterEvadeMode(); - return; - } - else - lifeTimer -= diff; - } - } - - void SpellHit(Unit * /*Hitter*/, const SpellEntry *Spellkind) - { - if (Spellkind->Id == 8593 && !spellHit) - { - DoCast(me, 32343); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); - //me->RemoveAllAuras(); - DoScriptText(SAY_HEAL, me); - spellHit = true; - } - } - -}; -CreatureAI* GetAI_npc_henze_faulk(Creature* pCreature) -{ - return new npc_henze_faulkAI (pCreature); -} - -void AddSC_elwynn_forest() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_henze_faulk"; - newscript->GetAI = &GetAI_npc_henze_faulk; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/eversong_woods.cpp b/src/server/scripts/eastern_kingdoms/eversong_woods.cpp deleted file mode 100644 index d1c7b9a6bfe..00000000000 --- a/src/server/scripts/eastern_kingdoms/eversong_woods.cpp +++ /dev/null @@ -1,711 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Eversong_Woods -SD%Complete: 100 -SDComment: Quest support: 8483, 8488, 8490, 9686 -SDCategory: Eversong Woods -EndScriptData */ - -/* ContentData -npc_prospector_anvilward -npc_apprentice_mirveda -npc_infused_crystal -npc_kelerun_bloodmourn -go_harbinger_second_trial -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_prospector_anvilward -######*/ - -#define GOSSIP_HELLO "I need a moment of your time, sir." -#define GOSSIP_SELECT "Why... yes, of course. I've something to show you right inside this building, Mr. Anvilward." - -enum eProspectorAnvilward -{ - SAY_ANVIL1 = -1000209, - SAY_ANVIL2 = -1000210, - QUEST_THE_DWARVEN_SPY = 8483, -}; - -struct npc_prospector_anvilwardAI : public npc_escortAI -{ - // CreatureAI functions - npc_prospector_anvilwardAI(Creature *c) : npc_escortAI(c) {} - - // Pure Virtual Functions - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch (i) - { - case 0: DoScriptText(SAY_ANVIL1, me, pPlayer); break; - case 5: DoScriptText(SAY_ANVIL2, me, pPlayer); break; - case 6: me->setFaction(24); break; - } - } - - void Reset() - { - me->RestoreFaction(); - } - - void JustDied(Unit* /*killer*/) - { - me->RestoreFaction(); - } -}; - -CreatureAI* GetAI_npc_prospector_anvilward(Creature* pCreature) -{ - return new npc_prospector_anvilwardAI(pCreature); -} - -bool GossipHello_npc_prospector_anvilward(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_THE_DWARVEN_SPY) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(8239, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_prospector_anvilward(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(8240, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - if (npc_escortAI* pEscortAI = CAST_AI(npc_prospector_anvilwardAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - break; - } - return true; -} - -/*###### -## Quest 9686 Second Trial -######*/ - -#define QUEST_SECOND_TRIAL 9686 - -#define MASTER_KELERUN_BLOODMOURN 17807 - -#define CHAMPION_BLOODWRATH 17809 -#define CHAMPION_LIGHTREND 17810 -#define CHAMPION_SWIFTBLADE 17811 -#define CHAMPION_SUNSTRIKER 17812 - -#define HARBINGER_OF_THE_SECOND_TRIAL 182052 - -#define SPELL_FLASH_OF_LIGHT 19939 -#define TIMER_FLASH_OF_LIGHT 3225 - -#define SPELL_SEAL_OF_JUSTICE 20164 -#define TIMER_SEAL_OF_JUSTICE 10000 - -#define SPELL_JUDGEMENT_OF_LIGHT 20271 -#define TIMER_JUDGEMENT_OF_LIGHT 10000 - -#define SPELL_SEAL_OF_COMMAND 20375 -#define TIMER_SEAL_OF_COMMAND 20000 - -#define OFFSET_NEXT_ATTACK 750 - -#define FACTION_HOSTILE 45 -#define FACTION_FRIENDLY 7 - -// missing from db -#define TEXT_SECOND_TRIAL_1 -1645006 -#define TEXT_SECOND_TRIAL_2 -1645007 -#define TEXT_SECOND_TRIAL_3 -1645008 -#define TEXT_SECOND_TRIAL_4 -1645009 - -struct Locations -{ - float x, y, z, o; -}; - -static Locations SpawnPosition[]= -{ - {5.3, -11.8, 0.361, 4.2}, - {11.2, -29.17, 0.361, 2.7}, - {-5.7, -34.85, 0.361, 1.09}, - {-11.9, -18, 0.361, 5.87} -}; - -static uint32 PaladinEntry[] = {CHAMPION_BLOODWRATH, CHAMPION_LIGHTREND, CHAMPION_SWIFTBLADE, CHAMPION_SUNSTRIKER}; - -/*###### -## npc_second_trial_paladin -######*/ - -struct npc_secondTrialAI : public ScriptedAI -{ - npc_secondTrialAI(Creature *c) : ScriptedAI(c) {} - - uint32 timer; - uint8 questPhase; - uint64 summonerGuid; - - bool spellFlashLight; - bool spellJustice; - bool spellJudLight; - bool spellCommand; - - uint32 timerFlashLight; - uint32 timerJustice; - uint32 timerJudLight; - uint32 timerCommand; - - void Reset() - { - - timer = 2000; - questPhase = 0; - summonerGuid = 0; - - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_KNEEL); - me->setFaction(FACTION_FRIENDLY); - - spellFlashLight = false; - spellJustice = false; - spellJudLight = false; - spellCommand = false; - - switch(me->GetEntry()) - { - case CHAMPION_BLOODWRATH: - spellFlashLight = true; - timerFlashLight = TIMER_FLASH_OF_LIGHT; - break; - case CHAMPION_LIGHTREND: - spellJustice = true; - timerJustice = 500; - break; - case CHAMPION_SWIFTBLADE: - spellJudLight = false; // Misses Script Effect // http://www.wowhead.com/?spell=20271 - timerJudLight = 500; - break; - case CHAMPION_SUNSTRIKER: - spellFlashLight = true; - spellJudLight = false; // Misses Script Effect // http://www.wowhead.com/?spell=20271 - spellCommand = false; // Misses Dummy // http://www.wowhead.com/?spell=20375 - timerFlashLight = TIMER_FLASH_OF_LIGHT; - timerJudLight = 500; - timerCommand = 1500; - break; - } - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (questPhase == 1) - if (timer <= diff) - { - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); - me->setFaction(FACTION_HOSTILE); - questPhase = 0; - - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - me->AddThreat(pTarget, 5000000.0f); - AttackStart(pTarget); - } - } - else - timer -= diff; - - if (!UpdateVictim()) - return; - - // healer - if (spellFlashLight) - if (me->GetHealth()*100 / me->GetMaxHealth() < 70) - if (timerFlashLight <= diff) - { - DoCast(me, SPELL_FLASH_OF_LIGHT); - timerFlashLight = TIMER_FLASH_OF_LIGHT + rand()%TIMER_FLASH_OF_LIGHT; - } - else - timerFlashLight -= diff; - - if (spellJustice) - if (timerJustice <= diff) - { - DoCast(me, SPELL_SEAL_OF_JUSTICE); - timerJustice = TIMER_SEAL_OF_JUSTICE + rand()%TIMER_SEAL_OF_JUSTICE; - } - else - timerJustice -= diff; - - if (spellJudLight) - if (timerJudLight <= diff) - { - DoCast(me, SPELL_JUDGEMENT_OF_LIGHT); - timerJudLight = TIMER_JUDGEMENT_OF_LIGHT + rand()%TIMER_JUDGEMENT_OF_LIGHT; - } - else - timerJudLight -= diff; - - if (spellCommand) - if (timerCommand <= diff) - { - DoCast(me, TIMER_SEAL_OF_COMMAND); - timerCommand = TIMER_SEAL_OF_COMMAND + rand()%TIMER_SEAL_OF_COMMAND; - } - else - timerCommand -= diff; - - DoMeleeAttackIfReady(); - } - - void Activate(uint64 summonerguid); - void KilledUnit(Unit* Killed); - void JustDied(Unit* Killer); - -}; - -/*###### -## npc_second_trial_controller -######*/ - -struct master_kelerun_bloodmournAI : public ScriptedAI -{ - master_kelerun_bloodmournAI(Creature *c) : ScriptedAI(c) {} - - uint8 questPhase; - uint8 paladinPhase; - uint32 timer; - - uint64 paladinGuid[4]; - - void Reset() - { - questPhase = 0; - timer = 60000; - paladinPhase = 0; - for (uint8 i = 0; i < 4; ++i) - paladinGuid[i] = 0; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - // Quest accepted but object not activated, object despawned (if in sync 1 minute!) - if (questPhase == 1) - { - if (timer <= diff) - Reset(); - else - timer -= diff; - } - // fight the 4 paladin mobs phase - else if (questPhase == 2) - { - if (timer <= diff) - { - if (Creature* paladinSpawn = Unit::GetCreature((*me), paladinGuid[paladinPhase])) - { - CAST_AI(npc_secondTrialAI, paladinSpawn->AI())->Activate(me->GetGUID()); - - switch(paladinPhase) - { - case 0: - DoScriptText(TEXT_SECOND_TRIAL_1,me); - break; - case 1: - DoScriptText(TEXT_SECOND_TRIAL_2,me); - break; - case 2: - DoScriptText(TEXT_SECOND_TRIAL_3,me); - break; - case 3: - DoScriptText(TEXT_SECOND_TRIAL_4,me); - break; - } - } - else - Reset(); - - questPhase = 4; - timer = OFFSET_NEXT_ATTACK; - } - else - timer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void StartEvent() - { - - if (questPhase == 1) - { // no player check, quest can be finished as group, so no complex PlayerGUID/group search code - - for (uint8 i = 0; i < 4; ++i) - if (Creature *pSummoned = DoSpawnCreature(PaladinEntry[i], SpawnPosition[i].x, SpawnPosition[i].y, SpawnPosition[i].z, SpawnPosition[i].o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 180000)) - paladinGuid[i] = pSummoned->GetGUID(); - - timer = OFFSET_NEXT_ATTACK; - questPhase = 2; - } - } - - void SecondTrialKill(); - void SummonedCreatureDespawn(Creature* /*c*/) {} -}; - -bool GossipHello_master_kelerun_bloodmourn(Player* pPlayer, Creature* pCreature) -{ - // quest only available if not already started - // Quest_template flag is set to : QUEST_FLAGS_EVENT - // Escort quests or any other event-driven quests. If player in party, all players that can accept this quest will receive confirmation box to accept quest. - // !not sure if this really works! - - if (CAST_AI(master_kelerun_bloodmournAI, pCreature->AI())->questPhase == 0) - { - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - pPlayer->SendPreparedQuest(pCreature->GetGUID()); - } - - pPlayer->SEND_GOSSIP_MENU(pCreature->GetEntry(), pCreature->GetGUID()); - return true; -} - -bool QuestAccept_master_kelerun_bloodmourn(Player* /*pPlayer*/, Creature* pCreature, Quest const *quest) -{ - // One Player exclusive quest, wait for user go activation - if (quest->GetQuestId() == QUEST_SECOND_TRIAL) - CAST_AI(master_kelerun_bloodmournAI, pCreature->AI())->questPhase = 1; - - return true; -} - -void master_kelerun_bloodmournAI::SecondTrialKill() -{ - if (questPhase > 0) - { - ++paladinPhase; - - if (paladinPhase < 4) - questPhase = 2; - else - Reset(); // Quest Complete, QuestComplete handler is in npc_secondTrialAI::JustDied - } -} - -void npc_secondTrialAI::JustDied(Unit* Killer) -{ - if (Killer->GetTypeId() == TYPEID_PLAYER) - { - if (Creature *pSummoner = Unit::GetCreature((*me), summonerGuid)) - CAST_AI(master_kelerun_bloodmournAI, pSummoner->AI())->SecondTrialKill(); - - // last kill quest complete for group - if (me->GetEntry() == CHAMPION_SUNSTRIKER) - { - if (Group *pGroup = CAST_PLR(Killer)->GetGroup()) - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player *pGroupGuy = itr->getSource(); - - // for any leave or dead (with not released body) group member at appropriate distance - if (pGroupGuy && pGroupGuy->IsAtGroupRewardDistance(me) && !pGroupGuy->GetCorpse() && pGroupGuy->GetQuestStatus(QUEST_SECOND_TRIAL) == QUEST_STATUS_INCOMPLETE) - pGroupGuy->CompleteQuest(QUEST_SECOND_TRIAL); - } - } - else if (CAST_PLR(Killer)->GetQuestStatus(QUEST_SECOND_TRIAL) == QUEST_STATUS_INCOMPLETE) - CAST_PLR(Killer)->CompleteQuest(QUEST_SECOND_TRIAL); - } - } -} - -void npc_secondTrialAI::KilledUnit(Unit* Killed) -{ - if (Killed->GetTypeId() == TYPEID_PLAYER) - if (CAST_PLR(Killed)->GetQuestStatus(QUEST_SECOND_TRIAL) == QUEST_STATUS_INCOMPLETE) - CAST_PLR(Killed)->FailQuest(QUEST_SECOND_TRIAL); -} - -void npc_secondTrialAI::Activate(uint64 summonerguid) -{ - questPhase = 1; - summonerGuid = summonerguid; -} - -CreatureAI* GetAI_master_kelerun_bloodmourn(Creature* pCreature) -{ - return new master_kelerun_bloodmournAI (pCreature); -} - -CreatureAI* GetAI_npc_secondTrial(Creature* pCreature) -{ - return new npc_secondTrialAI (pCreature); -} - -/*###### -## go_second_trial -######*/ - -bool GOHello_go_second_trial(Player* /*pPlayer*/, GameObject* pGO) -{ - // find spawn :: master_kelerun_bloodmourn - if (Creature *pCreature = pGO->FindNearestCreature(MASTER_KELERUN_BLOODMOURN, 30.0f)) - CAST_AI(master_kelerun_bloodmournAI, pCreature->AI())->StartEvent(); - - return true; -} - -/*###### -## npc_apprentice_mirveda -######*/ - -#define QUEST_UNEXPECTED_RESULT 8488 -#define MOB_GHARZUL 15958 -#define MOB_ANGERSHADE 15656 - -struct npc_apprentice_mirvedaAI : public ScriptedAI -{ - npc_apprentice_mirvedaAI(Creature* c) : ScriptedAI(c), Summons(me) {} - - uint32 KillCount; - uint64 PlayerGUID; - bool Summon; - SummonList Summons; - - void Reset() - { - KillCount = 0; - PlayerGUID = 0; - Summons.DespawnAll(); - Summon = false; - } - - void EnterCombat(Unit* /*who*/){} - - void JustSummoned(Creature *summoned) - { - summoned->AI()->AttackStart(me); - Summons.Summon(summoned); - } - - void SummonedCreatureDespawn(Creature* summoned) - { - Summons.Despawn(summoned); - ++KillCount; - } - - void JustDied(Unit* /*killer*/) - { - if (PlayerGUID) - if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) - CAST_PLR(pPlayer)->FailQuest(QUEST_UNEXPECTED_RESULT); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (KillCount >= 3 && PlayerGUID) - if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) - CAST_PLR(pPlayer)->CompleteQuest(QUEST_UNEXPECTED_RESULT); - - if (Summon) - { - me->SummonCreature(MOB_GHARZUL, 8745, -7134.32, 35.22, 0, TEMPSUMMON_CORPSE_DESPAWN, 4000); - me->SummonCreature(MOB_ANGERSHADE, 8745, -7134.32, 35.22, 0, TEMPSUMMON_CORPSE_DESPAWN, 4000); - me->SummonCreature(MOB_ANGERSHADE, 8745, -7134.32, 35.22, 0, TEMPSUMMON_CORPSE_DESPAWN, 4000); - Summon = false; - } - } -}; - -bool QuestAccept_npc_apprentice_mirveda(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_UNEXPECTED_RESULT) - { - CAST_AI(npc_apprentice_mirvedaAI, pCreature->AI())->Summon = true; - CAST_AI(npc_apprentice_mirvedaAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); - } - return true; -} - -CreatureAI* GetAI_npc_apprentice_mirvedaAI(Creature* pCreature) -{ - return new npc_apprentice_mirvedaAI (pCreature); -} - -/*###### -## npc_infused_crystal -######*/ - -#define MOB_ENRAGED_WRAITH 17086 -#define EMOTE -1000283 -#define QUEST_POWERING_OUR_DEFENSES 8490 - -struct Location -{ - float x, y, z; -}; - -static Location SpawnLocations[] = -{ - {8270.68, -7188.53, 139.619}, - {8284.27, -7187.78, 139.603}, - {8297.43, -7193.53, 139.603}, - {8303.5, -7201.96, 139.577}, - {8273.22, -7241.82, 139.382}, - {8254.89, -7222.12, 139.603}, - {8278.51, -7242.13, 139.162}, - {8267.97, -7239.17, 139.517} -}; - -struct npc_infused_crystalAI : public Scripted_NoMovementAI -{ - npc_infused_crystalAI(Creature* c) : Scripted_NoMovementAI(c) {} - - uint32 EndTimer; - uint32 WaveTimer; - bool Completed; - bool Progress; - uint64 PlayerGUID; - - void Reset() - { - EndTimer = 0; - Completed = false; - Progress = false; - PlayerGUID = 0; - WaveTimer = 0; - } - - void MoveInLineOfSight(Unit* who) - { - if (!Progress && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 10.0f)) - { - if (CAST_PLR(who)->GetQuestStatus(QUEST_POWERING_OUR_DEFENSES) == QUEST_STATUS_INCOMPLETE) - { - PlayerGUID = who->GetGUID(); - WaveTimer = 1000; - EndTimer = 60000; - Progress = true; - } - } - } - - void JustSummoned(Creature *summoned) - { - summoned->AI()->AttackStart(me); - } - - void JustDied(Unit* /*killer*/) - { - if (PlayerGUID && !Completed) - if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) - CAST_PLR(pPlayer)->FailQuest(QUEST_POWERING_OUR_DEFENSES); - } - - void UpdateAI(const uint32 diff) - { - if (EndTimer < diff && Progress) - { - DoScriptText(EMOTE, me); - Completed = true; - if (PlayerGUID) - if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) - CAST_PLR(pPlayer)->CompleteQuest(QUEST_POWERING_OUR_DEFENSES); - - me->DealDamage(me,me->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - } else EndTimer -= diff; - - if (WaveTimer < diff && !Completed && Progress) - { - uint32 ran1 = rand()%8; - uint32 ran2 = rand()%8; - uint32 ran3 = rand()%8; - me->SummonCreature(MOB_ENRAGED_WRAITH, SpawnLocations[ran1].x, SpawnLocations[ran1].y, SpawnLocations[ran1].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); - me->SummonCreature(MOB_ENRAGED_WRAITH, SpawnLocations[ran2].x, SpawnLocations[ran2].y, SpawnLocations[ran2].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); - me->SummonCreature(MOB_ENRAGED_WRAITH, SpawnLocations[ran3].x, SpawnLocations[ran3].y, SpawnLocations[ran3].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); - WaveTimer = 30000; - } else WaveTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_infused_crystalAI(Creature* pCreature) -{ - return new npc_infused_crystalAI (pCreature); -} - -void AddSC_eversong_woods() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_prospector_anvilward"; - newscript->GetAI = &GetAI_npc_prospector_anvilward; - newscript->pGossipHello = &GossipHello_npc_prospector_anvilward; - newscript->pGossipSelect = &GossipSelect_npc_prospector_anvilward; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_second_trial_controller"; - newscript->GetAI = &GetAI_master_kelerun_bloodmourn; - newscript->pGossipHello = &GossipHello_master_kelerun_bloodmourn; - newscript->pQuestAccept = &QuestAccept_master_kelerun_bloodmourn; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_second_trial_paladin"; - newscript->GetAI = &GetAI_npc_secondTrial; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_second_trial"; - newscript->pGOHello = &GOHello_go_second_trial; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_apprentice_mirveda"; - newscript->GetAI = &GetAI_npc_apprentice_mirvedaAI; - newscript->pQuestAccept = &QuestAccept_npc_apprentice_mirveda; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_infused_crystal"; - newscript->GetAI = &GetAI_npc_infused_crystalAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/ghostlands.cpp b/src/server/scripts/eastern_kingdoms/ghostlands.cpp deleted file mode 100644 index 67e4e764959..00000000000 --- a/src/server/scripts/eastern_kingdoms/ghostlands.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Ghostlands -SD%Complete: 100 -SDComment: Quest support: 9692, 9212. Obtain Budd's Guise of Zul'aman. Vendor Rathis Tomber -SDCategory: Ghostlands -EndScriptData */ - -/* ContentData -npc_blood_knight_dawnstar -npc_budd_nedreck -npc_rathis_tomber -npc_ranger_lilatha -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_blood_knight_dawnstar -######*/ - -#define GOSSIP_H_BKD "Take Blood Knight Insignia" - -bool GossipHello_npc_blood_knight_dawnstar(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(9692) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(24226,1,true)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_H_BKD, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_blood_knight_dawnstar(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 24226, 1, false); - if (msg == EQUIP_ERR_OK) - { - pPlayer->StoreNewItem(dest, 24226, 1, true); - pPlayer->PlayerTalkClass->ClearMenus(); - } - } - return true; -} - -/*###### -## npc_budd_nedreck -######*/ - -#define GOSSIP_HBN "You gave the crew disguises?" - -bool GossipHello_npc_budd_nedreck(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(11166) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_budd_nedreck(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, 42540, false); - } - return true; -} - -/*###### -## npc_rathis_tomber -######*/ - -bool GossipHello_npc_rathis_tomber(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(9152)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - pPlayer->SEND_GOSSIP_MENU(8432, pCreature->GetGUID()); - }else - pPlayer->SEND_GOSSIP_MENU(8431, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_rathis_tomber(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - return true; -} - -/*###### -## npc_ranger_lilatha -######*/ - -enum eEnums -{ - SAY_START = -1000140, - SAY_PROGRESS1 = -1000141, - SAY_PROGRESS2 = -1000142, - SAY_PROGRESS3 = -1000143, - SAY_END1 = -1000144, - SAY_END2 = -1000145, - SAY_CAPTAIN_ANSWER = -1000146, - - QUEST_ESCAPE_FROM_THE_CATACOMBS = 9212, - GO_CAGE = 181152, - NPC_CAPTAIN_HELIOS = 16220, - FACTION_SMOON_E = 1603, -}; - -struct npc_ranger_lilathaAI : public npc_escortAI -{ - npc_ranger_lilathaAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 0: - { - me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - if (GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 20)) - Cage->SetGoState(GO_STATE_ACTIVE); - DoScriptText(SAY_START, me, pPlayer); - break; - } - case 5: - DoScriptText(SAY_PROGRESS1, me, pPlayer); - case 11: - DoScriptText(SAY_PROGRESS2, me, pPlayer); - me->SetOrientation(4.762841); - break; - case 18: - { - DoScriptText(SAY_PROGRESS3, me, pPlayer); - Creature* Summ1 = me->SummonCreature(16342, 7627.083984, -7532.538086, 152.128616, 1.082733, TEMPSUMMON_DEAD_DESPAWN, 0); - Creature* Summ2 = me->SummonCreature(16343, 7620.432129, -7532.550293, 152.454865, 0.827478, TEMPSUMMON_DEAD_DESPAWN, 0); - if (Summ1 && Summ2) - { - Summ1->Attack(me, true); - Summ2->Attack(pPlayer, true); - } - me->AI()->AttackStart(Summ1); - break; - } - case 19: me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); break; - case 25: me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); break; - case 30: - if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(pPlayer)->GroupEventHappens(QUEST_ESCAPE_FROM_THE_CATACOMBS,me); - break; - case 32: - me->SetOrientation(2.978281); - DoScriptText(SAY_END1, me, pPlayer); - break; - case 33: - me->SetOrientation(5.858011); - DoScriptText(SAY_END2, me, pPlayer); - Unit* CaptainHelios = me->FindNearestCreature(NPC_CAPTAIN_HELIOS, 50); - if (CaptainHelios) - DoScriptText(SAY_CAPTAIN_ANSWER, CaptainHelios, pPlayer); - break; - } - } - - void Reset() - { - if (GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 20)) - Cage->SetGoState(GO_STATE_READY); - } -}; - -bool QuestAccept_npc_ranger_lilatha(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_ESCAPE_FROM_THE_CATACOMBS) - { - pCreature->setFaction(113); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_ranger_lilathaAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - } - return true; -} - -CreatureAI* GetAI_npc_ranger_lilathaAI(Creature* pCreature) -{ - return new npc_ranger_lilathaAI(pCreature); -} - -void AddSC_ghostlands() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_blood_knight_dawnstar"; - newscript->pGossipHello = &GossipHello_npc_blood_knight_dawnstar; - newscript->pGossipSelect = &GossipSelect_npc_blood_knight_dawnstar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_budd_nedreck"; - newscript->pGossipHello = &GossipHello_npc_budd_nedreck; - newscript->pGossipSelect = &GossipSelect_npc_budd_nedreck; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_rathis_tomber"; - newscript->pGossipHello = &GossipHello_npc_rathis_tomber; - newscript->pGossipSelect = &GossipSelect_npc_rathis_tomber; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ranger_lilatha"; - newscript->GetAI = &GetAI_npc_ranger_lilathaAI; - newscript->pQuestAccept = &QuestAccept_npc_ranger_lilatha; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp b/src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp deleted file mode 100644 index c39bfb69910..00000000000 --- a/src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Gnomeregan -SDAuthor: Manuel -SD%Complete: 90% -SDComment: Some visual effects are not implemented. -Script Data End */ - -#include "ScriptedPch.h" -#include "gnomeregan.h" -#include "ScriptedEscortAI.h" - -#define GOSSIP_START_EVENT "I am ready to being" - -enum eBlastmasterEmiShortfuse -{ - GOSSIP_TEXT_EMI = 1693, - - SAY_BLASTMASTER_0 = -1090000, - SAY_BLASTMASTER_1 = -1090001, - SAY_BLASTMASTER_2 = -1090002, - SAY_BLASTMASTER_3 = -1090003, - SAY_BLASTMASTER_4 = -1090004, - SAY_BLASTMASTER_5 = -1090005, - SAY_BLASTMASTER_6 = -1090006, - SAY_BLASTMASTER_7 = -1090007, - SAY_BLASTMASTER_8 = -1090008, - SAY_BLASTMASTER_9 = -1090009, - SAY_BLASTMASTER_10 = -1090010, - SAY_BLASTMASTER_11 = -1090011, - SAY_BLASTMASTER_12 = -1090012, - SAY_BLASTMASTER_13 = -1090013, - SAY_BLASTMASTER_14 = -1090014, - SAY_BLASTMASTER_15 = -1090015, - SAY_BLASTMASTER_16 = -1090016, - SAY_BLASTMASTER_17 = -1090017, - SAY_BLASTMASTER_18 = -1090018, - SAY_BLASTMASTER_19 = -1090019, - SAY_BLASTMASTER_20 = -1090020, - SAY_BLASTMASTER_21 = -1090021, - SAY_BLASTMASTER_22 = -1090022, - SAY_BLASTMASTER_23 = -1090023, - SAY_BLASTMASTER_24 = -1090024, - SAY_BLASTMASTER_25 = -1090025, - SAY_BLASTMASTER_26 = -1090026, - SAY_BLASTMASTER_27 = -1090027, - - SAY_GRUBBIS = -1090028 -}; - -const Position SpawnPosition[] = -{ - {-557.630,-114.514,-152.209,0.641}, - {-555.263,-113.802,-152.737,0.311}, - {-552.154,-112.476,-153.349,0.621}, - {-548.692,-111.089,-154.090,0.621}, - {-546.905,-108.340,-154.877,0.729}, - {-547.736,-105.154,-155.176,0.372}, - {-547.274,-114.109,-153.952,0.735}, - {-552.534,-110.012,-153.577,0.747}, - {-550.708,-116.436,-153.103,0.679}, - {-554.030,-115.983,-152.635,0.695}, - {-494.595,-87.516,149.116,3.344}, - {-493.349,-90.845,-148.882,3.717}, - {-491.995,-87.619,-148.197,3.230}, - {-490.732,-90.739,-148.091,3.230}, - {-490.554,-89.114,-148.055,3.230}, - {-495.240,-90.808,-149.493,3.238}, - {-494.195,-89.553,-149.131,3.254} -}; - -struct npc_blastmaster_emi_shortfuseAI : public npc_escortAI -{ - npc_blastmaster_emi_shortfuseAI(Creature* pCreature) : npc_escortAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - pCreature->RestoreFaction(); - Reset(); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiTimer; - - std::list SummonList; - std::list GoSummonList; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - uiTimer = 0; - uiPhase = 0; - - RestoreAll(); - - SummonList.clear(); - GoSummonList.clear(); - } - } - - void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) - { - uiTimer = uiTimerStep; - if (bNextStep) - ++uiPhase; - else - uiPhase = uiPhaseStep; - } - - void CaveDestruction(bool bBool) - { - if (GoSummonList.empty()) - return; - - for (std::list::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) - { - if (GameObject* pGo = GameObject::GetGameObject(*me, *itr)) - { - if (pGo) - { - if (Creature *trigger = pGo->SummonTrigger(pGo->GetPositionX(), pGo->GetPositionY(),pGo->GetPositionZ(), 0, 1)) - { - //visual effects are not working! ¬¬ - trigger->CastSpell(trigger,11542,true); - trigger->CastSpell(trigger,35470,true); - } - pGo->RemoveFromWorld(); - //pGo->CastSpell(me,12158); makes all die?! - } - } - } - - if (bBool) - { - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - pInstance->HandleGameObject(NULL,false,pGo); - }else - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) - pInstance->HandleGameObject(NULL,false,pGo); - } - - void SetInFace(bool bBool) - { - if (!pInstance) - return; - - if (bBool) - { - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - me->SetFacingToObject(pGo); - }else - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) - me->SetFacingToObject(pGo); - } - - void RestoreAll() - { - if (!pInstance) - return; - - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - pInstance->HandleGameObject(NULL,false,pGo); - - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) - pInstance->HandleGameObject(NULL,false,pGo); - - if (!GoSummonList.empty()) - for (std::list::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) - { - if (GameObject* pGo = GameObject::GetGameObject(*me, *itr)) - pGo->RemoveFromWorld(); - } - - if (!SummonList.empty()) - for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) - { - if (Creature* pSummon = Unit::GetCreature(*me, *itr)) - { - if (pSummon->isAlive()) - pSummon->DisappearAndDie(); - else - pSummon->RemoveCorpse(); - } - } - } - - void AggroAllPlayers(Creature* pTemp) - { - Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - pTemp->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(pTemp); - pTemp->AddThreat(pPlayer, 0.0f); - } - } - } - } - - void WaypointReached(uint32 uiPoint) - { - //just in case - if (GetPlayerForEscort()) - if (me->getFaction() != GetPlayerForEscort()->getFaction()) - me->setFaction(GetPlayerForEscort()->getFaction()); - - switch(uiPoint) - { - case 3: - SetEscortPaused(true); - NextStep(2000,false,3); - break; - case 7: - SetEscortPaused(true); - NextStep(2000,false,4); - break; - case 9: - NextStep(1000,false,8); - break; - case 10: - NextStep(25000,false,10); - break; - case 11: - SetEscortPaused(true); - SetInFace(true); - NextStep(1000,false,11); - break; - case 12: - NextStep(25000,false,18); - break; - case 13: - Summon(7); - NextStep(25000,false,19); - break; - case 14: - SetInFace(false); - DoScriptText(SAY_BLASTMASTER_26,me); - SetEscortPaused(true); - NextStep(5000,false,20); - break; - } - } - - void SetData(uint32 uiI,uint32 uiValue) - { - switch(uiI) - { - case 1: - SetEscortPaused(true); - DoScriptText(SAY_BLASTMASTER_0,me); - NextStep(1500,true); - break; - case 2: - if (!pInstance) - return; - - switch(uiValue) - { - case 1: - pInstance->SetData(TYPE_EVENT, IN_PROGRESS); - break; - case 2: - pInstance->SetData(TYPE_EVENT, DONE); - NextStep(5000,false,22); - break; - } - break; - } - } - - void Summon(uint8 uiCase) - { - switch(uiCase) - { - case 1: - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[5], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[6], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[7], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[8], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[9], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - break; - case 2: - if (GameObject* pGo = me->SummonGameObject(183410, -533.140,-105.322,-156.016, 0, 0, 0, 0, 0, 1000)) - { - GoSummonList.push_back(pGo->GetGUID()); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! - } - Summon(3); - break; - case 3: - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - DoScriptText(SAY_BLASTMASTER_19,me); - break; - case 4: - if (GameObject* pGo = me->SummonGameObject(183410, -542.199,-96.854,-155.790, 0, 0, 0, 0, 0, 1000)) - { - GoSummonList.push_back(pGo->GetGUID()); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - } - break; - case 5: - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - DoScriptText(SAY_BLASTMASTER_15,me); - break; - case 6: - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[10], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[11], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[12], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[13], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[14], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - break; - case 7: - if (GameObject* pGo = me->SummonGameObject(183410, -507.820,-103.333,-151.353, 0, 0, 0, 0, 0, 1000)) - { - GoSummonList.push_back(pGo->GetGUID()); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! - Summon(6); - } - break; - case 8: - if (GameObject* pGo = me->SummonGameObject(183410, -511.829,-86.249,-151.431, 0, 0, 0, 0, 0, 1000)) - { - GoSummonList.push_back(pGo->GetGUID()); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! - } - break; - case 9: - if (Creature* pGrubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000)) - DoScriptText(SAY_GRUBBIS,pGrubbis); - me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - break; - } - } - - void UpdateEscortAI(const uint32 uiDiff) - { - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - DoScriptText(SAY_BLASTMASTER_1,me); - NextStep(1500,true); - break; - case 2: - SetEscortPaused(false); - NextStep(0,false,0); - break; - case 3: - DoScriptText(SAY_BLASTMASTER_2,me); - SetEscortPaused(false); - NextStep(0,false,0); - break; - case 4: - DoScriptText(SAY_BLASTMASTER_3,me); - NextStep(3000,true); - break; - case 5: - DoScriptText(SAY_BLASTMASTER_4,me); - NextStep(3000,true); - break; - case 6: - SetInFace(true); - DoScriptText(SAY_BLASTMASTER_5,me); - Summon(1); - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - pInstance->HandleGameObject(NULL,true,pGo); - NextStep(3000,true); - break; - case 7: - DoScriptText(SAY_BLASTMASTER_6,me); - SetEscortPaused(false); - NextStep(0,false,0); - break; - case 8: - me->HandleEmoteCommand(EMOTE_STATE_WORK); - NextStep(25000,true); - break; - case 9: - Summon(2); - NextStep(0,false); - break; - case 10: - Summon(4); - NextStep(0,false); - break; - case 11: - DoScriptText(SAY_BLASTMASTER_17,me); - NextStep(5000,true); - break; - case 12: - DoScriptText(SAY_BLASTMASTER_18,me); - NextStep(5000,true); - break; - case 13: - DoScriptText(SAY_BLASTMASTER_20,me); - CaveDestruction(true); - NextStep(8000,true); - break; - case 14: - DoScriptText(SAY_BLASTMASTER_21,me); - NextStep(8500,true); - break; - case 15: - DoScriptText(SAY_BLASTMASTER_22,me); - NextStep(2000,true); - break; - case 16: - DoScriptText(SAY_BLASTMASTER_23,me); - SetInFace(false); - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) - pInstance->HandleGameObject(NULL,true,pGo); - NextStep(2000,true); - break; - case 17: - SetEscortPaused(false); - DoScriptText(SAY_BLASTMASTER_24,me); - Summon(6); - NextStep(0,false); - break; - case 18: - Summon(7); - NextStep(0,false); - break; - case 19: - SetInFace(false); - Summon(8); - DoScriptText(SAY_BLASTMASTER_25,me); - NextStep(0,false); - break; - case 20: - DoScriptText(SAY_BLASTMASTER_27,me); - NextStep(2000,true); - break; - case 21: - Summon(9); - NextStep(0,false); - break; - case 22: - CaveDestruction(false); - DoScriptText(SAY_BLASTMASTER_20,me); - NextStep(0,false); - break; - } - } else uiTimer -= uiDiff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* pSummon) - { - SummonList.push_back(pSummon->GetGUID()); - AggroAllPlayers(pSummon); - } -}; - -CreatureAI* GetAI_npc_blastmaster_emi_shortfuse(Creature* pCreature) -{ - return new npc_blastmaster_emi_shortfuseAI(pCreature); -} - -bool GossipHello_npc_blastmaster_emi_shortfuse(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && pInstance->GetData(TYPE_EVENT) == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_EMI, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_blastmaster_emi_shortfuse(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - if (npc_escortAI* pEscortAI = CAST_AI(npc_blastmaster_emi_shortfuseAI, pCreature->AI())) - pEscortAI->Start(true, false,pPlayer->GetGUID()); - - pCreature->setFaction(pPlayer->getFaction()); - pCreature->AI()->SetData(1,0); - - pPlayer->CLOSE_GOSSIP_MENU(); - } - return true; -} - -struct boss_grubbisAI : public ScriptedAI -{ - boss_grubbisAI(Creature* pCreature) : ScriptedAI(pCreature) - { - SetDataSummoner(); - } - - void SetDataSummoner() - { - if (!me->isSummon()) - return; - - if (Unit* pSummon = CAST_SUM(me)->GetSummoner()) - CAST_CRE(pSummon)->AI()->SetData(2,1); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (!me->isSummon()) - return; - - if (Unit* pSummon = CAST_SUM(me)->GetSummoner()) - CAST_CRE(pSummon)->AI()->SetData(2,2); - } -}; - -CreatureAI* GetAI_boss_grubbis(Creature* pCreature) -{ - return new boss_grubbisAI(pCreature); -} - -void AddSC_gnomeregan() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_blastmaster_emi_shortfuse"; - newscript->pGossipHello = &GossipHello_npc_blastmaster_emi_shortfuse; - newscript->pGossipSelect = &GossipSelect_npc_blastmaster_emi_shortfuse; - newscript->GetAI = &GetAI_npc_blastmaster_emi_shortfuse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_grubbis"; - newscript->GetAI = &GetAI_boss_grubbis; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h b/src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h deleted file mode 100644 index e46c811e9b1..00000000000 --- a/src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_GNOMEREGAN_H -#define DEF_GNOMEREGAN_H - -enum eGameObjects -{ - GO_CAVE_IN_LEFT = 146085, - GO_CAVE_IN_RIGHT = 146086 -}; - -enum eCreatures -{ - NPC_BLASTMASTER_EMI_SHORTFUSE = 7998, - NPC_CAVERNDEEP_AMBUSHER = 6207, - NPC_GRUBBIS = 7361, - NPC_CHOMPER = 6215 -}; - -enum eData -{ - TYPE_EVENT = 1 -}; - -enum eData64 -{ - DATA_GO_CAVE_IN_LEFT, - DATA_GO_CAVE_IN_RIGHT, - DATA_NPC_BASTMASTER_EMI_SHORTFUSE -}; - -#endif diff --git a/src/server/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp b/src/server/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp deleted file mode 100644 index 980a6d3552b..00000000000 --- a/src/server/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "gnomeregan.h" - -#define MAX_ENCOUNTER 1 - -struct instance_gnomeregan : public ScriptedInstance -{ - instance_gnomeregan(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - }; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 uiCaveInLeftGUID; - uint64 uiCaveInRightGUID; - - uint64 uiBastmasterEmiShortfuseGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - uiCaveInLeftGUID = 0; - uiCaveInRightGUID = 0; - - uiBastmasterEmiShortfuseGUID = 0; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) - { - switch(pCreature->GetEntry()) - { - case NPC_BLASTMASTER_EMI_SHORTFUSE: uiBastmasterEmiShortfuseGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*bAdd*/) - { - switch(pGo->GetEntry()) - { - case GO_CAVE_IN_LEFT: - uiCaveInLeftGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE || m_auiEncounter[0] == NOT_STARTED) - HandleGameObject(NULL,false,pGo); - break; - case GO_CAVE_IN_RIGHT: - uiCaveInRightGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE || m_auiEncounter[0] == NOT_STARTED) - HandleGameObject(NULL,false,pGo); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_EVENT: - m_auiEncounter[0] = uiData; - if (uiData == DONE) - SaveToDB(); - break; - } - } - - uint32 GetData(uint32 uiType, uint32 /*uiData*/) - { - switch(uiType) - { - case TYPE_EVENT: return m_auiEncounter[0]; - } - } - - uint64 GetData64(uint32 uiType) - { - switch(uiType) - { - case DATA_GO_CAVE_IN_LEFT: return uiCaveInLeftGUID; - case DATA_GO_CAVE_IN_RIGHT: return uiCaveInRightGUID; - case DATA_NPC_BASTMASTER_EMI_SHORTFUSE: return uiBastmasterEmiShortfuseGUID; - } - - return 0; - } -}; - -InstanceData* GetInstanceData_instance_gnomeregan(Map* pMap) -{ - return new instance_gnomeregan(pMap); -} - -void AddSC_instance_gnomeregan() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "instance_gnomeregan"; - newscript->GetInstanceData = &GetInstanceData_instance_gnomeregan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/hinterlands.cpp b/src/server/scripts/eastern_kingdoms/hinterlands.cpp deleted file mode 100644 index 59002936e14..00000000000 --- a/src/server/scripts/eastern_kingdoms/hinterlands.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Hinterlands -SD%Complete: 100 -SDComment: Quest support: 863, 2742 -SDCategory: The Hinterlands -EndScriptData */ - -/* ContentData -npc_00x09hl -npc_rinji -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_00x09hl -######*/ - -enum eOOX -{ - SAY_OOX_START = -1000287, - SAY_OOX_AGGRO1 = -1000288, - SAY_OOX_AGGRO2 = -1000289, - SAY_OOX_AMBUSH = -1000290, - SAY_OOX_END = -1000292, - - QUEST_RESQUE_OOX_09 = 836, - - NPC_MARAUDING_OWL = 7808, - NPC_VILE_AMBUSHER = 7809, - - FACTION_ESCORTEE_A = 774, - FACTION_ESCORTEE_H = 775 -}; - -struct npc_00x09hlAI : public npc_escortAI -{ - npc_00x09hlAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void Reset() { } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 26: - DoScriptText(SAY_OOX_AMBUSH, me); - break; - case 43: - DoScriptText(SAY_OOX_AMBUSH, me); - break; - case 64: - DoScriptText(SAY_OOX_END, me); - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->GroupEventHappens(QUEST_RESQUE_OOX_09, me); - break; - } - } - - void WaypointStart(uint32 uiPointId) - { - switch(uiPointId) - { - case 27: - for (uint8 i = 0; i < 3; ++i) - { - const Position src = {147.927444f, -3851.513428f, 130.893f, 0}; - Position dst; - me->GetRandomPoint(src, 7.0f, dst); - DoSummon(NPC_MARAUDING_OWL, dst, 25000, TEMPSUMMON_CORPSE_TIMED_DESPAWN); - } - break; - case 44: - for (uint8 i = 0; i < 3; ++i) - { - const Position src = {-141.151581f, -4291.213867f, 120.130f, 0}; - Position dst; - me->GetRandomPoint(src, 7.0f, dst); - me->SummonCreature(NPC_VILE_AMBUSHER, dst, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 25000); - } - break; - } - } - - void Aggro(Unit* pWho) - { - if (pWho->GetEntry() == NPC_MARAUDING_OWL || pWho->GetEntry() == NPC_VILE_AMBUSHER) - return; - - if (rand()%1) - DoScriptText(SAY_OOX_AGGRO1, me); - else - DoScriptText(SAY_OOX_AGGRO2, me); - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); - } -}; - -bool QuestAccept_npc_00x09hl(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_RESQUE_OOX_09) - { - pCreature->SetStandState(UNIT_STAND_STATE_STAND); - - if (pPlayer->GetTeam() == ALLIANCE) - pCreature->setFaction(FACTION_ESCORTEE_A); - else if (pPlayer->GetTeam() == HORDE) - pCreature->setFaction(FACTION_ESCORTEE_H); - - DoScriptText(SAY_OOX_START, pCreature, pPlayer); - - if (npc_00x09hlAI* pEscortAI = CAST_AI(npc_00x09hlAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); - } - return true; -} - -CreatureAI* GetAI_npc_00x09hl(Creature* pCreature) -{ - return new npc_00x09hlAI(pCreature); -} - -/*###### -## npc_rinji -######*/ - -enum eRinji -{ - SAY_RIN_FREE = -1000403, //from here - SAY_RIN_BY_OUTRUNNER = -1000404, - SAY_RIN_HELP_1 = -1000405, - SAY_RIN_HELP_2 = -1000406, //to here, are used also by 6182 but this is wrong... - SAY_RIN_COMPLETE = -1000407, - SAY_RIN_PROGRESS_1 = -1000408, - SAY_RIN_PROGRESS_2 = -1000409, - - QUEST_RINJI_TRAPPED = 2742, - NPC_RANGER = 2694, - NPC_OUTRUNNER = 2691, - GO_RINJI_CAGE = 142036 -}; - -struct Location -{ - float m_fX, m_fY, m_fZ; -}; - -Location m_afAmbushSpawn[] = -{ - {191.296204, -2839.329346, 107.388}, - {70.972466, -2848.674805, 109.459} -}; - -Location m_afAmbushMoveTo[] = -{ - {166.630386, -2824.780273, 108.153}, - {70.886589, -2874.335449, 116.675} -}; - -struct npc_rinjiAI : public npc_escortAI -{ - npc_rinjiAI(Creature* pCreature) : npc_escortAI(pCreature) - { - m_bIsByOutrunner = false; - m_iSpawnId = 0; - } - - bool m_bIsByOutrunner; - uint32 m_uiPostEventCount; - uint32 m_uiPostEventTimer; - int m_iSpawnId; - - void Reset() - { - m_uiPostEventCount = 0; - m_uiPostEventTimer = 3000; - } - - void JustRespawned() - { - m_bIsByOutrunner = false; - m_iSpawnId = 0; - - npc_escortAI::JustRespawned(); - } - - void EnterCombat(Unit* pWho) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (pWho->GetEntry() == NPC_OUTRUNNER && !m_bIsByOutrunner) - { - DoScriptText(SAY_RIN_BY_OUTRUNNER, pWho); - m_bIsByOutrunner = true; - } - - if (rand()%4) - return; - - //only if attacked and escorter is not in combat? - DoScriptText(RAND(SAY_RIN_HELP_1,SAY_RIN_HELP_2), me); - } - } - - void DoSpawnAmbush(bool bFirst) - { - if (!bFirst) - m_iSpawnId = 1; - - me->SummonCreature(NPC_RANGER, - m_afAmbushSpawn[m_iSpawnId].m_fX, m_afAmbushSpawn[m_iSpawnId].m_fY, m_afAmbushSpawn[m_iSpawnId].m_fZ, 0.0f, - TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - - for (int i = 0; i < 2; ++i) - { - me->SummonCreature(NPC_OUTRUNNER, - m_afAmbushSpawn[m_iSpawnId].m_fX, m_afAmbushSpawn[m_iSpawnId].m_fY, m_afAmbushSpawn[m_iSpawnId].m_fZ, 0.0f, - TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - } - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pSummoned->GetMotionMaster()->MovePoint(0, m_afAmbushMoveTo[m_iSpawnId].m_fX, m_afAmbushMoveTo[m_iSpawnId].m_fY, m_afAmbushMoveTo[m_iSpawnId].m_fZ); - } - - void WaypointReached(uint32 uiPointId) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(uiPointId) - { - case 1: - DoScriptText(SAY_RIN_FREE, me, pPlayer); - break; - case 7: - DoSpawnAmbush(true); - break; - case 13: - DoSpawnAmbush(false); - break; - case 17: - DoScriptText(SAY_RIN_COMPLETE, me, pPlayer); - pPlayer->GroupEventHappens(QUEST_RINJI_TRAPPED, me); - SetRun(); - m_uiPostEventCount = 1; - break; - } - } - - void UpdateEscortAI(const uint32 uiDiff) - { - //Check if we have a current target - if (!UpdateVictim()) - { - if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPostEventCount) - { - if (m_uiPostEventTimer <= uiDiff) - { - m_uiPostEventTimer = 3000; - - if (Unit* pPlayer = GetPlayerForEscort()) - { - switch(m_uiPostEventCount) - { - case 1: - DoScriptText(SAY_RIN_PROGRESS_1, me, pPlayer); - ++m_uiPostEventCount; - break; - case 2: - DoScriptText(SAY_RIN_PROGRESS_2, me, pPlayer); - m_uiPostEventCount = 0; - break; - } - } - else - { - me->ForcedDespawn(); - return; - } - } - else - m_uiPostEventTimer -= uiDiff; - } - - return; - } - - DoMeleeAttackIfReady(); - } -}; - -bool QuestAccept_npc_rinji(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_RINJI_TRAPPED) - { - if (GameObject* pGo = pCreature->FindNearestGameObject(GO_RINJI_CAGE, INTERACTION_DISTANCE)) - pGo->UseDoorOrButton(); - - if (npc_rinjiAI* pEscortAI = CAST_AI(npc_rinjiAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); - } - return true; -} - -CreatureAI* GetAI_npc_rinji(Creature* pCreature) -{ - return new npc_rinjiAI(pCreature); -} - -void AddSC_hinterlands() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_00x09hl"; - newscript->GetAI = &GetAI_npc_00x09hl; - newscript->pQuestAccept = &QuestAccept_npc_00x09hl; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_rinji"; - newscript->GetAI = &GetAI_npc_rinji; - newscript->pQuestAccept = &QuestAccept_npc_rinji; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/ironforge.cpp b/src/server/scripts/eastern_kingdoms/ironforge.cpp deleted file mode 100644 index 5be56cc6c9c..00000000000 --- a/src/server/scripts/eastern_kingdoms/ironforge.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Ironforge -SD%Complete: 100 -SDComment: Quest support: 3702 -SDCategory: Ironforge -EndScriptData */ - -/* ContentData -npc_royal_historian_archesonus -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_royal_historian_archesonus -######*/ - -#define GOSSIP_ITEM_ROYAL "I am ready to listen" -#define GOSSIP_ITEM_ROYAL_1 "That is tragic. How did this happen?" -#define GOSSIP_ITEM_ROYAL_2 "Interesting, continue please." -#define GOSSIP_ITEM_ROYAL_3 "Unbelievable! How dare they??" -#define GOSSIP_ITEM_ROYAL_4 "Of course I will help!" - -bool GossipHello_npc_royal_historian_archesonus(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(3702) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(2235, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_royal_historian_archesonus(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2236, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(2237, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(2238, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(2239, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(3702); - break; - } - return true; -} - -void AddSC_ironforge() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_royal_historian_archesonus"; - newscript->pGossipHello = &GossipHello_npc_royal_historian_archesonus; - newscript->pGossipSelect = &GossipSelect_npc_royal_historian_archesonus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/isle_of_queldanas.cpp b/src/server/scripts/eastern_kingdoms/isle_of_queldanas.cpp deleted file mode 100644 index e5a70fcb1af..00000000000 --- a/src/server/scripts/eastern_kingdoms/isle_of_queldanas.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Isle_of_Queldanas -SD%Complete: 100 -SDComment: Quest support: 11524, 11525, 11532, 11533, 11542, 11543, 11541 -SDCategory: Isle Of Quel'Danas -EndScriptData */ - -/* ContentData -npc_converted_sentry -npc_greengill_slave -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_converted_sentry -######*/ - -#define SAY_CONVERTED_1 -1000188 -#define SAY_CONVERTED_2 -1000189 - -#define SPELL_CONVERT_CREDIT 45009 - -struct npc_converted_sentryAI : public ScriptedAI -{ - npc_converted_sentryAI(Creature *c) : ScriptedAI(c) {} - - bool Credit; - uint32 Timer; - - void Reset() - { - Credit = false; - Timer = 2500; - } - - void MoveInLineOfSight(Unit * /*who*/) {} - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!Credit) - { - if (Timer <= diff) - { - uint32 i = urand(1,2); - if (i == 1) - DoScriptText(SAY_CONVERTED_1, me); - else - DoScriptText(SAY_CONVERTED_2, me); - - DoCast(me, SPELL_CONVERT_CREDIT); - if (me->isPet()) - CAST_PET(me)->SetDuration(7500); - Credit = true; - } else Timer -= diff; - } - } -}; -CreatureAI* GetAI_npc_converted_sentry(Creature* pCreature) -{ - return new npc_converted_sentryAI (pCreature); -} - -/*###### -## npc_greengill_slave -######*/ - -#define ENRAGE 45111 -#define ORB 45109 -#define QUESTG 11541 -#define DM 25060 - -struct npc_greengill_slaveAI : public ScriptedAI -{ - npc_greengill_slaveAI(Creature* c) : ScriptedAI(c) {} - - uint64 PlayerGUID; - - void EnterCombat(Unit* /*who*/){} - - void Reset() - { - PlayerGUID = 0; - } - - void SpellHit(Unit* caster, const SpellEntry* spell) - { - if (!caster) - return; - - if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == ORB && !me->HasAura(ENRAGE)) - { - PlayerGUID = caster->GetGUID(); - if (PlayerGUID) - { - Unit* plr = Unit::GetUnit((*me), PlayerGUID); - if (plr && CAST_PLR(plr)->GetQuestStatus(QUESTG) == QUEST_STATUS_INCOMPLETE) - DoCast(plr, 45110, true); - } - DoCast(me, ENRAGE); - Unit* Myrmidon = me->FindNearestCreature(DM, 70); - if (Myrmidon) - { - me->AddThreat(Myrmidon, 100000.0f); - AttackStart(Myrmidon); - } - } - } - - void UpdateAI(const uint32 /*diff*/) - { - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_greengill_slaveAI(Creature* pCreature) -{ - return new npc_greengill_slaveAI(pCreature); -} - -void AddSC_isle_of_queldanas() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_converted_sentry"; - newscript->GetAI = &GetAI_npc_converted_sentry; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_greengill_slave"; - newscript->GetAI = &GetAI_npc_greengill_slaveAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_curator.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_curator.cpp deleted file mode 100644 index 7105d27ca6a..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_curator.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Curator -SD%Complete: 100 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1532057 -#define SAY_SUMMON1 -1532058 -#define SAY_SUMMON2 -1532059 -#define SAY_EVOCATE -1532060 -#define SAY_ENRAGE -1532061 -#define SAY_KILL1 -1532062 -#define SAY_KILL2 -1532063 -#define SAY_DEATH -1532064 - -//Flare spell info -#define SPELL_ASTRAL_FLARE_PASSIVE 30234 //Visual effect + Flare damage - -//Curator spell info -#define SPELL_HATEFUL_BOLT 30383 -#define SPELL_EVOCATION 30254 -#define SPELL_ENRAGE 30403 //Arcane Infusion: Transforms Curator and adds damage. -#define SPELL_BERSERK 26662 - -struct boss_curatorAI : public ScriptedAI -{ - boss_curatorAI(Creature *c) : ScriptedAI(c) {} - - uint32 AddTimer; - uint32 HatefulBoltTimer; - uint32 BerserkTimer; - - bool Enraged; - bool Evocating; - - void Reset() - { - AddTimer = 10000; - HatefulBoltTimer = 15000; //This time may be wrong - BerserkTimer = 720000; //12 minutes - Enraged = false; - Evocating = false; - - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //always decrease BerserkTimer - if (BerserkTimer <= diff) - { - //if evocate, then break evocate - if (Evocating) - { - if (me->HasAura(SPELL_EVOCATION)) - me->RemoveAurasDueToSpell(SPELL_EVOCATION); - - Evocating = false; - } - - //may not be correct SAY (generic hard enrage) - DoScriptText(SAY_ENRAGE, me); - - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_BERSERK); - - //don't know if he's supposed to do summon/evocate after hard enrage (probably not) - Enraged = true; - } else BerserkTimer -= diff; - - if (Evocating) - { - //not supposed to do anything while evocate - if (me->HasAura(SPELL_EVOCATION)) - return; - else - Evocating = false; - } - - if (!Enraged) - { - if (AddTimer <= diff) - { - //Summon Astral Flare - Creature* AstralFlare = DoSpawnCreature(17096, rand()%37, rand()%37, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (AstralFlare && pTarget) - { - AstralFlare->CastSpell(AstralFlare, SPELL_ASTRAL_FLARE_PASSIVE, false); - AstralFlare->AI()->AttackStart(pTarget); - } - - //Reduce Mana by 10% of max health - if (int32 mana = me->GetMaxPower(POWER_MANA)) - { - mana /= 10; - me->ModifyPower(POWER_MANA, -mana); - - //if this get's us below 10%, then we evocate (the 10th should be summoned now) - if (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA) < 10) - { - DoScriptText(SAY_EVOCATE, me); - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_EVOCATION); - Evocating = true; - //no AddTimer cooldown, this will make first flare appear instantly after evocate end, like expected - return; - } - else - { - if (urand(0,1) == 0) - { - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - } - } - } - - AddTimer = 10000; - } else AddTimer -= diff; - - if (me->GetHealth()*100 / me->GetMaxHealth() <= 15) - { - Enraged = true; - DoCast(me, SPELL_ENRAGE); - DoScriptText(SAY_ENRAGE, me); - } - } - - if (HatefulBoltTimer <= diff) - { - if (Enraged) - HatefulBoltTimer = 7000; - else - HatefulBoltTimer = 15000; - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1)) - DoCast(pTarget, SPELL_HATEFUL_BOLT); - - } else HatefulBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_curator(Creature* pCreature) -{ - return new boss_curatorAI (pCreature); -} - -void AddSC_boss_curator() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_curator"; - newscript->GetAI = &GetAI_boss_curator; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp deleted file mode 100644 index 21db1be1be3..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Maiden_of_Virtue -SD%Complete: 100 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1532018 -#define SAY_SLAY1 -1532019 -#define SAY_SLAY2 -1532020 -#define SAY_SLAY3 -1532021 -#define SAY_REPENTANCE1 -1532022 -#define SAY_REPENTANCE2 -1532023 -#define SAY_DEATH -1532024 - -#define SPELL_REPENTANCE 29511 -#define SPELL_HOLYFIRE 29522 -#define SPELL_HOLYWRATH 32445 -#define SPELL_HOLYGROUND 29512 -#define SPELL_BERSERK 26662 - -struct boss_maiden_of_virtueAI : public ScriptedAI -{ - boss_maiden_of_virtueAI(Creature *c) : ScriptedAI(c) {} - - uint32 Repentance_Timer; - uint32 Holyfire_Timer; - uint32 Holywrath_Timer; - uint32 Holyground_Timer; - uint32 Enrage_Timer; - - bool Enraged; - - void Reset() - { - Repentance_Timer = 25000+(rand()%15000); - Holyfire_Timer = 8000+(rand()%17000); - Holywrath_Timer = 15000+(rand()%10000); - Holyground_Timer = 3000; - Enrage_Timer = 600000; - - Enraged = false; - } - - void KilledUnit(Unit* /*Victim*/) - { - if (urand(0,1) == 0) - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Enrage_Timer < diff && !Enraged) - { - DoCast(me, SPELL_BERSERK, true); - Enraged = true; - } else Enrage_Timer -= diff; - - if (Holyground_Timer <= diff) - { - DoCast(me, SPELL_HOLYGROUND, true); //Triggered so it doesn't interrupt her at all - Holyground_Timer = 3000; - } else Holyground_Timer -= diff; - - if (Repentance_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REPENTANCE); - DoScriptText(RAND(SAY_REPENTANCE1,SAY_REPENTANCE2), me); - - Repentance_Timer = urand(25000,35000); //A little randomness on that spell - } else Repentance_Timer -= diff; - - if (Holyfire_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_HOLYFIRE); - - Holyfire_Timer = urand(8000,23000); //Anywhere from 8 to 23 seconds, good luck having several of those in a row! - } else Holyfire_Timer -= diff; - - if (Holywrath_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_HOLYWRATH); - - Holywrath_Timer = urand(20000,25000); //20-30 secs sounds nice - } else Holywrath_Timer -= diff; - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_boss_maiden_of_virtue(Creature* pCreature) -{ - return new boss_maiden_of_virtueAI (pCreature); -} - -void AddSC_boss_maiden_of_virtue() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_maiden_of_virtue"; - newscript->GetAI = &GetAI_boss_maiden_of_virtue; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp deleted file mode 100644 index a2f2a8b605e..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Midnight -SD%Complete: 100 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_MIDNIGHT_KILL -1532000 -#define SAY_APPEAR1 -1532001 -#define SAY_APPEAR2 -1532002 -#define SAY_APPEAR3 -1532003 -#define SAY_MOUNT -1532004 -#define SAY_KILL1 -1532005 -#define SAY_KILL2 -1532006 -#define SAY_DISARMED -1532007 -#define SAY_DEATH -1532008 -#define SAY_RANDOM1 -1532009 -#define SAY_RANDOM2 -1532010 - -#define SPELL_SHADOWCLEAVE 29832 -#define SPELL_INTANGIBLE_PRESENCE 29833 -#define SPELL_BERSERKER_CHARGE 26561 //Only when mounted - -#define MOUNTED_DISPLAYID 16040 - -//Attumen (TODO: Use the summoning spell instead of Creature id. It works , but is not convenient for us) -#define SUMMON_ATTUMEN 15550 - -struct boss_midnightAI : public ScriptedAI -{ - boss_midnightAI(Creature *c) : ScriptedAI(c) {} - - uint64 Attumen; - uint8 Phase; - uint32 Mount_Timer; - - void Reset() - { - Phase = 1; - Attumen = 0; - Mount_Timer = 0; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_ON); - } - - void EnterCombat(Unit* /*who*/) {} - - void KilledUnit(Unit * /*victim*/) - { - if (Phase == 2) - { - if (Unit *pUnit = Unit::GetUnit(*me, Attumen)) - DoScriptText(SAY_MIDNIGHT_KILL, pUnit); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Phase == 1 && (me->GetHealth()*100)/me->GetMaxHealth() < 95) - { - Phase = 2; - if (Creature* pAttumen = me->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000)) - { - Attumen = pAttumen->GetGUID(); - pAttumen->AI()->AttackStart(me->getVictim()); - SetMidnight(pAttumen, me->GetGUID()); - DoScriptText(RAND(SAY_APPEAR1,SAY_APPEAR2,SAY_APPEAR3), pAttumen); - } - } - else if (Phase == 2 && (me->GetHealth()*100)/me->GetMaxHealth() < 25) - { - if (Unit *pAttumen = Unit::GetUnit(*me, Attumen)) - Mount(pAttumen); - } - else if (Phase == 3) - { - if (Mount_Timer) - { - if (Mount_Timer <= diff) - { - Mount_Timer = 0; - me->SetVisibility(VISIBILITY_OFF); - me->GetMotionMaster()->MoveIdle(); - if (Unit *pAttumen = Unit::GetUnit(*me, Attumen)) - { - pAttumen->SetDisplayId(MOUNTED_DISPLAYID); - pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pAttumen->getVictim()) - { - pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim()); - pAttumen->SetUInt64Value(UNIT_FIELD_TARGET, pAttumen->getVictim()->GetGUID()); - } - pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X,1); - } - } else Mount_Timer -= diff; - } - } - - if (Phase != 3) - DoMeleeAttackIfReady(); - } - - void Mount(Unit *pAttumen) - { - DoScriptText(SAY_MOUNT, pAttumen); - Phase = 3; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - float angle = me->GetAngle(pAttumen); - float distance = me->GetDistance2d(pAttumen); - float newX = me->GetPositionX() + cos(angle)*(distance/2) ; - float newY = me->GetPositionY() + sin(angle)*(distance/2) ; - float newZ = 50; - //me->Relocate(newX,newY,newZ,angle); - //me->SendMonsterMove(newX, newY, newZ, 0, true, 1000); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, newX, newY, newZ); - distance += 10; - newX = me->GetPositionX() + cos(angle)*(distance/2) ; - newY = me->GetPositionY() + sin(angle)*(distance/2) ; - pAttumen->GetMotionMaster()->Clear(); - pAttumen->GetMotionMaster()->MovePoint(0, newX, newY, newZ); - //pAttumen->Relocate(newX,newY,newZ,-angle); - //pAttumen->SendMonsterMove(newX, newY, newZ, 0, true, 1000); - Mount_Timer = 1000; - } - - void SetMidnight(Creature *, uint64); //Below .. -}; - -CreatureAI* GetAI_boss_midnight(Creature* pCreature) -{ - return new boss_midnightAI(pCreature); -} - -struct boss_attumenAI : public ScriptedAI -{ - boss_attumenAI(Creature *c) : ScriptedAI(c) - { - Phase = 1; - - CleaveTimer = urand(10000,15000); - CurseTimer = 30000; - RandomYellTimer = urand(30000,60000); //Occasionally yell - ChargeTimer = 20000; - ResetTimer = 0; - } - - uint64 Midnight; - uint8 Phase; - uint32 CleaveTimer; - uint32 CurseTimer; - uint32 RandomYellTimer; - uint32 ChargeTimer; //only when mounted - uint32 ResetTimer; - - void Reset() - { - ResetTimer = 2000; - } - - void EnterCombat(Unit* /*who*/) {} - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - if (Unit *pMidnight = Unit::GetUnit(*me, Midnight)) - pMidnight->Kill(pMidnight); - } - - void UpdateAI(const uint32 diff) - { - if (ResetTimer) - { - if (ResetTimer <= diff) - { - ResetTimer = 0; - Unit *pMidnight = Unit::GetUnit(*me, Midnight); - if (pMidnight) - { - pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pMidnight->SetVisibility(VISIBILITY_ON); - } - Midnight = 0; - me->SetVisibility(VISIBILITY_OFF); - me->Kill(me); - } - } else ResetTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) - return; - - if (CleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWCLEAVE); - CleaveTimer = urand(10000,15000); - } else CleaveTimer -= diff; - - if (CurseTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); - CurseTimer = 30000; - } else CurseTimer -= diff; - - if (RandomYellTimer <= diff) - { - DoScriptText(RAND(SAY_RANDOM1,SAY_RANDOM2), me); - RandomYellTimer = urand(30000,60000); - } else RandomYellTimer -= diff; - - if (me->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID) - { - if (ChargeTimer <= diff) - { - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && !pTarget->IsWithinDist(me, ATTACK_DISTANCE, false)) - target_list.push_back(pTarget); - pTarget = NULL; - } - if (target_list.size()) - pTarget = *(target_list.begin()+rand()%target_list.size()); - - DoCast(pTarget, SPELL_BERSERKER_CHARGE); - ChargeTimer = 20000; - } else ChargeTimer -= diff; - } - else - { - if ((me->GetHealth()*100)/me->GetMaxHealth() < 25) - { - Creature *pMidnight = Unit::GetCreature(*me, Midnight); - if (pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT) - { - CAST_AI(boss_midnightAI, (pMidnight->AI()))->Mount(me); - me->SetHealth(pMidnight->GetHealth()); - DoResetThreat(); - } - } - } - - DoMeleeAttackIfReady(); - } - - void SpellHit(Unit * /*source*/, const SpellEntry *spell) - { - if (spell->Mechanic == MECHANIC_DISARM) - DoScriptText(SAY_DISARMED, me); - } -}; - -void boss_midnightAI::SetMidnight(Creature *pAttumen, uint64 value) -{ - CAST_AI(boss_attumenAI, pAttumen->AI())->Midnight = value; -} - -CreatureAI* GetAI_boss_attumen(Creature* pCreature) -{ - return new boss_attumenAI (pCreature); -} - -void AddSC_boss_attumen() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_attumen"; - newscript->GetAI = &GetAI_boss_attumen; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_midnight"; - newscript->GetAI = &GetAI_boss_midnight; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp deleted file mode 100644 index 6c8fabcca35..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Moroes -SD%Complete: 95 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define SAY_AGGRO -1532011 -#define SAY_SPECIAL_1 -1532012 -#define SAY_SPECIAL_2 -1532013 -#define SAY_KILL_1 -1532014 -#define SAY_KILL_2 -1532015 -#define SAY_KILL_3 -1532016 -#define SAY_DEATH -1532017 - -#define SPELL_VANISH 29448 -#define SPELL_GARROTE 37066 -#define SPELL_BLIND 34694 -#define SPELL_GOUGE 29425 -#define SPELL_FRENZY 37023 - -#define POS_Z 81.73 - -float Locations[4][3]= -{ - {-10991.0, -1884.33, 0.614315}, - {-10989.4, -1885.88, 0.904913}, - {-10978.1, -1887.07, 2.035550}, - {-10975.9, -1885.81, 2.253890}, -}; - -const uint32 Adds[6]= -{ - 17007, - 19872, - 19873, - 19874, - 19875, - 19876, -}; - -struct boss_moroesAI : public ScriptedAI -{ - boss_moroesAI(Creature *c) : ScriptedAI(c) - { - for (uint8 i = 0; i < 4; ++i) - { - AddId[i] = 0; - } - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint64 AddGUID[4]; - - uint32 Vanish_Timer; - uint32 Blind_Timer; - uint32 Gouge_Timer; - uint32 Wait_Timer; - uint32 CheckAdds_Timer; - uint32 AddId[4]; - - bool InVanish; - bool Enrage; - - void Reset() - { - Vanish_Timer = 30000; - Blind_Timer = 35000; - Gouge_Timer = 23000; - Wait_Timer = 0; - CheckAdds_Timer = 5000; - - Enrage = false; - InVanish = false; - if (me->GetHealth() > 0) - { - SpawnAdds(); - } - - if (pInstance) - pInstance->SetData(TYPE_MOROES, NOT_STARTED); - } - - void StartEvent() - { - if (pInstance) - pInstance->SetData(TYPE_MOROES, IN_PROGRESS); - - DoZoneInCombat(); - } - - void EnterCombat(Unit* /*who*/) - { - StartEvent(); - - DoScriptText(SAY_AGGRO, me); - AddsAttack(); - DoZoneInCombat(); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); - } - - void JustDied(Unit* /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_MOROES, DONE); - - DeSpawnAdds(); - - //remove aura from spell Garrote when Moroes dies - if (pInstance) - pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GARROTE); - } - - void SpawnAdds() - { - DeSpawnAdds(); - if (isAddlistEmpty()) - { - Creature *pCreature = NULL; - std::vector AddList; - - for (uint8 i = 0; i < 6; ++i) - AddList.push_back(Adds[i]); - - while (AddList.size() > 4) - AddList.erase((AddList.begin())+(rand()%AddList.size())); - - uint8 i = 0; - for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr) - { - uint32 entry = *itr; - - pCreature = me->SummonCreature(entry, Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - if (pCreature) - { - AddGUID[i] = pCreature->GetGUID(); - AddId[i] = entry; - } - ++i; - } - }else - { - for (uint8 i = 0; i < 4; ++i) - { - Creature *pCreature = me->SummonCreature(AddId[i], Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - if (pCreature) - { - AddGUID[i] = pCreature->GetGUID(); - } - } - } - } - - bool isAddlistEmpty() - { - for (uint8 i = 0; i < 4; ++i) - { - if (AddId[i] == 0) - return true; - } - return false; - } - - void DeSpawnAdds() - { - for (uint8 i = 0; i < 4 ; ++i) - { - Creature* Temp = NULL; - if (AddGUID[i]) - { - Temp = Creature::GetCreature((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - Temp->DisappearAndDie(); - } - } - } - - void AddsAttack() - { - for (uint8 i = 0; i < 4; ++i) - { - Creature* Temp = NULL; - if (AddGUID[i]) - { - Temp = Creature::GetCreature((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - { - Temp->AI()->AttackStart(me->getVictim()); - DoZoneInCombat(Temp); - } else - EnterEvadeMode(); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (pInstance && !pInstance->GetData(TYPE_MOROES)) - { - EnterEvadeMode(); - return; - } - - if (!Enrage && me->GetHealth()*100 / me->GetMaxHealth() < 30) - { - DoCast(me, SPELL_FRENZY); - Enrage = true; - } - - if (CheckAdds_Timer <= diff) - { - for (uint8 i = 0; i < 4; ++i) - { - Creature* Temp = NULL; - if (AddGUID[i]) - { - Temp = Unit::GetCreature((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - if (!Temp->getVictim()) - Temp->AI()->AttackStart(me->getVictim()); - } - } - CheckAdds_Timer = 5000; - } else CheckAdds_Timer -= diff; - - if (!Enrage) - { - //Cast Vanish, then Garrote random victim - if (Vanish_Timer <= diff) - { - DoCast(me, SPELL_VANISH); - InVanish = true; - Vanish_Timer = 30000; - Wait_Timer = 5000; - } else Vanish_Timer -= diff; - - if (Gouge_Timer <= diff) - { - DoCastVictim(SPELL_GOUGE); - Gouge_Timer = 40000; - } else Gouge_Timer -= diff; - - if (Blind_Timer <= diff) - { - std::list pTargets; - SelectTargetList(pTargets, 5, SELECT_TARGET_RANDOM, me->GetMeleeReach()*5, true); - for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) - if (!me->IsWithinMeleeRange(*i)) - { - DoCast(*i, SPELL_BLIND); - break; - } - Blind_Timer = 40000; - } else Blind_Timer -= diff; - } - - if (InVanish) - { - if (Wait_Timer <= diff) - { - DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2), me); - - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - pTarget->CastSpell(pTarget, SPELL_GARROTE,true); - - InVanish = false; - } else Wait_Timer -= diff; - } - - if (!InVanish) - DoMeleeAttackIfReady(); - } -}; - -struct boss_moroes_guestAI : public ScriptedAI -{ - ScriptedInstance* pInstance; - - uint64 GuestGUID[4]; - - boss_moroes_guestAI(Creature* c) : ScriptedAI(c) - { - for (uint8 i = 0; i < 4; ++i) - GuestGUID[i] = 0; - - pInstance = c->GetInstanceData(); - } - - void Reset() - { - if (pInstance) - pInstance->SetData(TYPE_MOROES, NOT_STARTED); - } - - void AcquireGUID() - { - if (!pInstance) - return; - - uint64 MoroesGUID = pInstance->GetData64(DATA_MOROES); - Creature* Moroes = (Unit::GetCreature((*me), MoroesGUID)); - if (Moroes) - { - for (uint8 i = 0; i < 4; ++i) - { - uint64 GUID = CAST_AI(boss_moroesAI, Moroes->AI())->AddGUID[i]; - if (GUID) - GuestGUID[i] = GUID; - } - } - } - - Unit* SelectGuestTarget() - { - uint64 TempGUID = GuestGUID[rand()%4]; - if (TempGUID) - { - Unit* pUnit = Unit::GetUnit((*me), TempGUID); - if (pUnit && pUnit->isAlive()) - return pUnit; - } - - return me; - } - - void UpdateAI(const uint32 /*diff*/) - { - if (pInstance && !pInstance->GetData(TYPE_MOROES)) - EnterEvadeMode(); - - DoMeleeAttackIfReady(); - } -}; - -#define SPELL_MANABURN 29405 -#define SPELL_MINDFLY 29570 -#define SPELL_SWPAIN 34441 -#define SPELL_SHADOWFORM 29406 - -struct boss_baroness_dorothea_millstipeAI : public boss_moroes_guestAI -{ - //Shadow Priest - boss_baroness_dorothea_millstipeAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 ManaBurn_Timer; - uint32 MindFlay_Timer; - uint32 ShadowWordPain_Timer; - - void Reset() - { - ManaBurn_Timer = 7000; - MindFlay_Timer = 1000; - ShadowWordPain_Timer = 6000; - - DoCast(me, SPELL_SHADOWFORM, true); - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (MindFlay_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MINDFLY); - MindFlay_Timer = 12000; // 3 sec channeled - } else MindFlay_Timer -= diff; - - if (ManaBurn_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (pTarget->getPowerType() == POWER_MANA) - DoCast(pTarget, SPELL_MANABURN); - ManaBurn_Timer = 5000; // 3 sec cast - } else ManaBurn_Timer -= diff; - - if (ShadowWordPain_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, SPELL_SWPAIN); - ShadowWordPain_Timer = 7000; - } - } else ShadowWordPain_Timer -= diff; - } -}; - -#define SPELL_HAMMEROFJUSTICE 13005 -#define SPELL_JUDGEMENTOFCOMMAND 29386 -#define SPELL_SEALOFCOMMAND 29385 - -struct boss_baron_rafe_dreugerAI : public boss_moroes_guestAI -{ - //Retr Pally - boss_baron_rafe_dreugerAI(Creature *c) : boss_moroes_guestAI(c){} - - uint32 HammerOfJustice_Timer; - uint32 SealOfCommand_Timer; - uint32 JudgementOfCommand_Timer; - - void Reset() - { - HammerOfJustice_Timer = 1000; - SealOfCommand_Timer = 7000; - JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (SealOfCommand_Timer <= diff) - { - DoCast(me, SPELL_SEALOFCOMMAND); - SealOfCommand_Timer = 32000; - JudgementOfCommand_Timer = 29000; - } else SealOfCommand_Timer -= diff; - - if (JudgementOfCommand_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_JUDGEMENTOFCOMMAND); - JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; - } else JudgementOfCommand_Timer -= diff; - - if (HammerOfJustice_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMMEROFJUSTICE); - HammerOfJustice_Timer = 12000; - } else HammerOfJustice_Timer -= diff; - } -}; - -#define SPELL_DISPELMAGIC 15090 //Self or other guest+Moroes -#define SPELL_GREATERHEAL 29564 //Self or other guest+Moroes -#define SPELL_HOLYFIRE 29563 -#define SPELL_PWSHIELD 29408 - -struct boss_lady_catriona_von_indiAI : public boss_moroes_guestAI -{ - //Holy Priest - boss_lady_catriona_von_indiAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 DispelMagic_Timer; - uint32 GreaterHeal_Timer; - uint32 HolyFire_Timer; - uint32 PowerWordShield_Timer; - - void Reset() - { - DispelMagic_Timer = 11000; - GreaterHeal_Timer = 1500; - HolyFire_Timer = 5000; - PowerWordShield_Timer = 1000; - - AcquireGUID(); - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (PowerWordShield_Timer <= diff) - { - DoCast(me, SPELL_PWSHIELD); - PowerWordShield_Timer = 15000; - } else PowerWordShield_Timer -= diff; - - if (GreaterHeal_Timer <= diff) - { - Unit *pTarget = SelectGuestTarget(); - - DoCast(pTarget, SPELL_GREATERHEAL); - GreaterHeal_Timer = 17000; - } else GreaterHeal_Timer -= diff; - - if (HolyFire_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HOLYFIRE); - HolyFire_Timer = 22000; - } else HolyFire_Timer -= diff; - - if (DispelMagic_Timer <= diff) - { - if (Unit *pTarget = RAND(SelectGuestTarget(), SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))) - DoCast(pTarget, SPELL_DISPELMAGIC); - - DispelMagic_Timer = 25000; - } else DispelMagic_Timer -= diff; - } -}; - -#define SPELL_CLEANSE 29380 //Self or other guest+Moroes -#define SPELL_GREATERBLESSOFMIGHT 29381 //Self or other guest+Moroes -#define SPELL_HOLYLIGHT 29562 //Self or other guest+Moroes -#define SPELL_DIVINESHIELD 41367 - -struct boss_lady_keira_berrybuckAI : public boss_moroes_guestAI -{ - //Holy Pally - boss_lady_keira_berrybuckAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 Cleanse_Timer; - uint32 GreaterBless_Timer; - uint32 HolyLight_Timer; - uint32 DivineShield_Timer; - - void Reset() - { - Cleanse_Timer = 13000; - GreaterBless_Timer = 1000; - HolyLight_Timer = 7000; - DivineShield_Timer = 31000; - - AcquireGUID(); - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (DivineShield_Timer <= diff) - { - DoCast(me, SPELL_DIVINESHIELD); - DivineShield_Timer = 31000; - } else DivineShield_Timer -= diff; - - if (HolyLight_Timer <= diff) - { - Unit *pTarget = SelectGuestTarget(); - - DoCast(pTarget, SPELL_HOLYLIGHT); - HolyLight_Timer = 10000; - } else HolyLight_Timer -= diff; - - if (GreaterBless_Timer <= diff) - { - Unit *pTarget = SelectGuestTarget(); - - DoCast(pTarget, SPELL_GREATERBLESSOFMIGHT); - - GreaterBless_Timer = 50000; - } else GreaterBless_Timer -= diff; - - if (Cleanse_Timer <= diff) - { - Unit *pTarget = SelectGuestTarget(); - - DoCast(pTarget, SPELL_CLEANSE); - - Cleanse_Timer = 10000; - } else Cleanse_Timer -= diff; - } -}; - -#define SPELL_HAMSTRING 9080 -#define SPELL_MORTALSTRIKE 29572 -#define SPELL_WHIRLWIND 29573 - -struct boss_lord_robin_darisAI : public boss_moroes_guestAI -{ - //Arms Warr - boss_lord_robin_darisAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 Hamstring_Timer; - uint32 MortalStrike_Timer; - uint32 WhirlWind_Timer; - - void Reset() - { - Hamstring_Timer = 7000; - MortalStrike_Timer = 10000; - WhirlWind_Timer = 21000; - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (Hamstring_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - Hamstring_Timer = 12000; - } else Hamstring_Timer -= diff; - - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = 18000; - } else MortalStrike_Timer -= diff; - - if (WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - WhirlWind_Timer = 21000; - } else WhirlWind_Timer -= diff; - } -}; - -#define SPELL_DISARM 8379 -#define SPELL_HEROICSTRIKE 29567 -#define SPELL_SHIELDBASH 11972 -#define SPELL_SHIELDWALL 29390 - -struct boss_lord_crispin_ferenceAI : public boss_moroes_guestAI -{ - //Arms Warr - boss_lord_crispin_ferenceAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 Disarm_Timer; - uint32 HeroicStrike_Timer; - uint32 ShieldBash_Timer; - uint32 ShieldWall_Timer; - - void Reset() - { - Disarm_Timer = 6000; - HeroicStrike_Timer = 10000; - ShieldBash_Timer = 8000; - ShieldWall_Timer = 4000; - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (Disarm_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DISARM); - Disarm_Timer = 12000; - } else Disarm_Timer -= diff; - - if (HeroicStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HEROICSTRIKE); - HeroicStrike_Timer = 10000; - } else HeroicStrike_Timer -= diff; - - if (ShieldBash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHIELDBASH); - ShieldBash_Timer = 13000; - } else ShieldBash_Timer -= diff; - - if (ShieldWall_Timer <= diff) - { - DoCast(me, SPELL_SHIELDWALL); - ShieldWall_Timer = 21000; - } else ShieldWall_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_moroes(Creature* pCreature) -{ - return new boss_moroesAI (pCreature); -} - -CreatureAI* GetAI_baroness_dorothea_millstipe(Creature* pCreature) -{ - return new boss_baroness_dorothea_millstipeAI (pCreature); -} - -CreatureAI* GetAI_baron_rafe_dreuger(Creature* pCreature) -{ - return new boss_baron_rafe_dreugerAI (pCreature); -} - -CreatureAI* GetAI_lady_catriona_von_indi(Creature* pCreature) -{ - return new boss_lady_catriona_von_indiAI (pCreature); -} - -CreatureAI* GetAI_lady_keira_berrybuck(Creature* pCreature) -{ - return new boss_lady_keira_berrybuckAI (pCreature); -} - -CreatureAI* GetAI_lord_robin_daris(Creature* pCreature) -{ - return new boss_lord_robin_darisAI (pCreature); -} - -CreatureAI* GetAI_lord_crispin_ference(Creature* pCreature) -{ - return new boss_lord_crispin_ferenceAI (pCreature); -} - -void AddSC_boss_moroes() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_moroes"; - newscript->GetAI = &GetAI_boss_moroes; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_baroness_dorothea_millstipe"; - newscript->GetAI = &GetAI_baroness_dorothea_millstipe; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_baron_rafe_dreuger"; - newscript->GetAI = &GetAI_baron_rafe_dreuger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lady_catriona_von_indi"; - newscript->GetAI = &GetAI_lady_catriona_von_indi; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lady_keira_berrybuck"; - newscript->GetAI = &GetAI_lady_keira_berrybuck; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_robin_daris"; - newscript->GetAI = &GetAI_lord_robin_daris; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_crispin_ference"; - newscript->GetAI = &GetAI_lord_crispin_ference; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp deleted file mode 100644 index 004f1902bfc..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Netherspite -SD%Complete: 90 -SDComment: Not sure about timing and portals placing -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define EMOTE_PHASE_PORTAL -1532089 -#define EMOTE_PHASE_BANISH -1532090 - -#define SPELL_NETHERBURN_AURA 30522 -#define SPELL_VOIDZONE 37063 -#define SPELL_NETHER_INFUSION 38688 -#define SPELL_NETHERBREATH 38523 -#define SPELL_BANISH_VISUAL 39833 -#define SPELL_BANISH_ROOT 42716 -#define SPELL_EMPOWERMENT 38549 -#define SPELL_NETHERSPITE_ROAR 38684 - -const float PortalCoord[3][3] = -{ - {-11195.353516, -1613.237183, 278.237258}, // Left side - {-11137.846680, -1685.607422, 278.239258}, // Right side - {-11094.493164, -1591.969238, 279.949188} // Back side -}; - -enum Netherspite_Portal{ - RED_PORTAL = 0, // Perseverence - GREEN_PORTAL = 1, // Serenity - BLUE_PORTAL = 2 // Dominance -}; - -const uint32 PortalID[3] = {17369, 17367, 17368}; -const uint32 PortalVisual[3] = {30487,30490,30491}; -const uint32 PortalBeam[3] = {30465,30464,30463}; -const uint32 PlayerBuff[3] = {30421,30422,30423}; -const uint32 NetherBuff[3] = {30466,30467,30468}; -const uint32 PlayerDebuff[3] = {38637,38638,38639}; - -struct boss_netherspiteAI : public ScriptedAI -{ - boss_netherspiteAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - - for (int i=0; i<3; ++i) - { - PortalGUID[i] = 0; - BeamTarget[i] = 0; - BeamerGUID[i] = 0; - } - // need core fix - for (int i=0; i<3; ++i) - { - if (SpellEntry *spell = (SpellEntry*)GetSpellStore()->LookupEntry(PlayerBuff[i])) - spell->AttributesEx |= SPELL_ATTR_EX_NEGATIVE; - } - } - - ScriptedInstance* pInstance; - - bool PortalPhase; - bool Berserk; - uint32 PhaseTimer; // timer for phase switching - uint32 VoidZoneTimer; - uint32 NetherInfusionTimer; // berserking timer - uint32 NetherbreathTimer; - uint32 EmpowermentTimer; - uint32 PortalTimer; // timer for beam checking - uint64 PortalGUID[3]; // guid's of portals - uint64 BeamerGUID[3]; // guid's of auxiliary beaming portals - uint64 BeamTarget[3]; // guid's of portals' current targets - - bool IsBetween(WorldObject* u1, WorldObject *pTarget, WorldObject* u2) // the in-line checker - { - if (!u1 || !u2 || !pTarget) - return false; - - float xn, yn, xp, yp, xh, yh; - xn = u1->GetPositionX(); - yn = u1->GetPositionY(); - xp = u2->GetPositionX(); - yp = u2->GetPositionY(); - xh = pTarget->GetPositionX(); - yh = pTarget->GetPositionY(); - - // check if target is between (not checking distance from the beam yet) - if (dist(xn,yn,xh,yh) >= dist(xn,yn,xp,yp) || dist(xp,yp,xh,yh) >= dist(xn,yn,xp,yp)) - return false; - // check distance from the beam - return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn,yn,xp,yp) < 1.5f); - } - - float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance - { - return sqrt((xa-xb)*(xa-xb) + (ya-yb)*(ya-yb)); - } - - void Reset() - { - Berserk = false; - NetherInfusionTimer = 540000; - VoidZoneTimer = 15000; - NetherbreathTimer = 3000; - - HandleDoors(true); - DestroyPortals(); - } - - void SummonPortals() - { - uint8 r = rand()%4; - uint8 pos[3]; - pos[RED_PORTAL] = (r%2 ? (r>1 ? 2: 1): 0); - pos[GREEN_PORTAL] = (r%2 ? 0: (r>1 ? 2: 1)); - pos[BLUE_PORTAL] = (r>1 ? 1: 2); // Blue Portal not on the left side (0) - - for (int i=0; i<3; ++i) - if (Creature *portal = me->SummonCreature(PortalID[i],PortalCoord[pos[i]][0],PortalCoord[pos[i]][1],PortalCoord[pos[i]][2],0,TEMPSUMMON_TIMED_DESPAWN,60000)) - { - PortalGUID[i] = portal->GetGUID(); - portal->AddAura(PortalVisual[i], portal); - } - } - - void DestroyPortals() - { - for (int i=0; i<3; ++i) - { - if (Creature *portal = Unit::GetCreature(*me, PortalGUID[i])) - portal->DisappearAndDie(); - if (Creature *portal = Unit::GetCreature(*me, BeamerGUID[i])) - portal->DisappearAndDie(); - PortalGUID[i] = 0; - BeamTarget[i] = 0; - } - } - - void UpdatePortals() // Here we handle the beams' behavior - { - for (int j=0; j<3; ++j) // j = color - if (Creature *portal = Unit::GetCreature(*me, PortalGUID[j])) - { - // the one who's been casted upon before - Unit *current = Unit::GetUnit(*portal, BeamTarget[j]); - // temporary store for the best suitable beam reciever - Unit *pTarget = me; - - if (Map* map = me->GetMap()) - { - Map::PlayerList const& players = map->GetPlayers(); - - // get the best suitable target - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player* p = i->getSource(); - if (p && p->isAlive() // alive - && (!pTarget || pTarget->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best - && !p->HasAura(PlayerDebuff[j],0) // not exhausted - && !p->HasAura(PlayerBuff[(j+1)%3],0) // not on another beam - && !p->HasAura(PlayerBuff[(j+2)%3],0) - && IsBetween(me, p, portal)) // on the beam - pTarget = p; - } - } - // buff the target - if (pTarget->GetTypeId() == TYPEID_PLAYER) - pTarget->AddAura(PlayerBuff[j], pTarget); - else - pTarget->AddAura(NetherBuff[j], pTarget); - // cast visual beam on the chosen target if switched - // simple target switching isn't working -> using BeamerGUID to cast (workaround) - if (!current || pTarget != current) - { - BeamTarget[j] = pTarget->GetGUID(); - // remove currently beaming portal - if (Creature *beamer = Unit::GetCreature(*portal, BeamerGUID[j])) - { - beamer->CastSpell(pTarget, PortalBeam[j], false); - beamer->DisappearAndDie(); - BeamerGUID[j] = 0; - } - // create new one and start beaming on the target - if (Creature *beamer = portal->SummonCreature(PortalID[j],portal->GetPositionX(),portal->GetPositionY(),portal->GetPositionZ(),portal->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,60000)) - { - beamer->CastSpell(pTarget, PortalBeam[j], false); - BeamerGUID[j] = beamer->GetGUID(); - } - } - // aggro target if Red Beam - if (j == RED_PORTAL && me->getVictim() != pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - me->getThreatManager().addThreat(pTarget, 100000.0f+DoGetThreat(me->getVictim())); - } - } - - void SwitchToPortalPhase() - { - me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT); - me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL); - SummonPortals(); - PhaseTimer = 60000; - PortalPhase = true; - PortalTimer = 10000; - EmpowermentTimer = 10000; - DoScriptText(EMOTE_PHASE_PORTAL,me); - } - - void SwitchToBanishPhase() - { - me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT); - me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA); - DoCast(me, SPELL_BANISH_VISUAL, true); - DoCast(me, SPELL_BANISH_ROOT, true); - DestroyPortals(); - PhaseTimer = 30000; - PortalPhase = false; - DoScriptText(EMOTE_PHASE_BANISH,me); - - for (int i=0; i<3; ++i) - me->RemoveAurasDueToSpell(NetherBuff[i]); - } - - void HandleDoors(bool open) // Massive Door switcher - { - if (GameObject *Door = GameObject::GetGameObject(*me, pInstance ? pInstance->GetData64(DATA_GO_MASSIVE_DOOR) : 0)) - Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY); - } - - void Aggro(Unit * /*who*/) - { - HandleDoors(false); - SwitchToPortalPhase(); - } - - void JustDied(Unit* /*killer*/) - { - HandleDoors(true); - DestroyPortals(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Void Zone - if (VoidZoneTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,45,true),SPELL_VOIDZONE,true); - VoidZoneTimer = 15000; - } else VoidZoneTimer -= diff; - - // NetherInfusion Berserk - if (!Berserk && NetherInfusionTimer <= diff) - { - me->AddAura(SPELL_NETHER_INFUSION, me); - DoCast(me, SPELL_NETHERSPITE_ROAR); - Berserk = true; - } else NetherInfusionTimer -= diff; - - if (PortalPhase) // PORTAL PHASE - { - // Distribute beams and buffs - if (PortalTimer <= diff) - { - UpdatePortals(); - PortalTimer = 1000; - } else PortalTimer -= diff; - - // Empowerment & Nether Burn - if (EmpowermentTimer <= diff) - { - DoCast(me, SPELL_EMPOWERMENT); - me->AddAura(SPELL_NETHERBURN_AURA, me); - EmpowermentTimer = 90000; - } else EmpowermentTimer -= diff; - - if (PhaseTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - SwitchToBanishPhase(); - return; - } - } else PhaseTimer -= diff; - } - else // BANISH PHASE - { - // Netherbreath - if (NetherbreathTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,40,true)) - DoCast(pTarget, SPELL_NETHERBREATH); - NetherbreathTimer = urand(5000,7000); - } else NetherbreathTimer -= diff; - - if (PhaseTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - SwitchToPortalPhase(); - return; - } - } else PhaseTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_netherspite(Creature *pCreature) -{ - return new boss_netherspiteAI(pCreature); -} - -void AddSC_boss_netherspite() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_netherspite"; - newscript->GetAI = GetAI_boss_netherspite; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp deleted file mode 100644 index 2e8b6f51317..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Nightbane -SD%Complete: 80 -SDComment: SDComment: Timers may incorrect -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -//phase 1 -#define SPELL_BELLOWING_ROAR 39427 -#define SPELL_CHARRED_EARTH 30129 -#define SPELL_DISTRACTING_ASH 30130 -#define SPELL_SMOLDERING_BREATH 30210 -#define SPELL_TAIL_SWEEP 25653 -//phase 2 -#define SPELL_RAIN_OF_BONES 37098 -#define SPELL_SMOKING_BLAST 37057 -#define SPELL_FIREBALL_BARRAGE 30282 -#define SPELL_SEARING_CINDERS 30127 -#define SPELL_SUMMON_SKELETON 30170 - -#define EMOTE_SUMMON "An ancient being awakens in the distance..." -#define YELL_AGGRO "What fools! I shall bring a quick end to your suffering!" -#define YELL_FLY_PHASE "Miserable vermin. I shall exterminate you from the air!" -#define YELL_LAND_PHASE_1 "Enough! I shall land and crush you myself!" -#define YELL_LAND_PHASE_2 "Insects! Let me show you my strength up close!" -#define EMOTE_BREATH "takes a deep breath." - -float IntroWay[8][3] = -{ - {-11053.37,-1794.48,149}, - {-11141.07,-1841.40,125}, - {-11187.28,-1890.23,125}, - {-11189.20,-1931.25,125}, - {-11153.76,-1948.93,125}, - {-11128.73,-1929.75,125}, - {-11140 , -1915 ,122}, - {-11163 , -1903 ,91.473} -}; - -struct boss_nightbaneAI : public ScriptedAI -{ - boss_nightbaneAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = true; - } - - ScriptedInstance* pInstance; - - uint32 Phase; - - bool RainBones; - bool Skeletons; - - uint32 BellowingRoarTimer; - uint32 CharredEarthTimer; - uint32 DistractingAshTimer; - uint32 SmolderingBreathTimer; - uint32 TailSweepTimer; - uint32 RainofBonesTimer; - uint32 SmokingBlastTimer; - uint32 FireballBarrageTimer; - uint32 SearingCindersTimer; - - uint32 FlyCount; - uint32 FlyTimer; - - bool Intro; - bool Flying; - bool Movement; - - uint32 WaitTimer; - uint32 MovePhase; - - void Reset() - { - BellowingRoarTimer = 30000; - CharredEarthTimer = 15000; - DistractingAshTimer = 20000; - SmolderingBreathTimer = 10000; - TailSweepTimer = 12000; - RainofBonesTimer = 10000; - SmokingBlastTimer = 20000; - FireballBarrageTimer = 13000; - SearingCindersTimer = 14000; - WaitTimer = 1000; - - Phase =1; - FlyCount = 0; - MovePhase = 0; - - me->SetSpeed(MOVE_RUN, 2.0f); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->setActive(true); - - if (pInstance) - { - if (pInstance->GetData(TYPE_NIGHTBANE) == DONE || pInstance->GetData(TYPE_NIGHTBANE) == IN_PROGRESS) - me->DisappearAndDie(); - else - pInstance->SetData(TYPE_NIGHTBANE, NOT_STARTED); - } - - HandleTerraceDoors(true); - - Flying = false; - Movement = false; - - if (!Intro) - { - me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0); - me->GetMotionMaster()->MoveTargetedHome(); - } - } - - void HandleTerraceDoors(bool open) - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_1), open); - pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_2), open); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(TYPE_NIGHTBANE, IN_PROGRESS); - - HandleTerraceDoors(false); - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - } - - void AttackStart(Unit* who) - { - if (!Intro && !Flying) - ScriptedAI::AttackStart(who); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_NIGHTBANE, DONE); - - HandleTerraceDoors(true); - } - - void MoveInLineOfSight(Unit *who) - { - if (!Intro && !Flying) - ScriptedAI::MoveInLineOfSight(who); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (Intro) - { - if (id >= 8) - { - Intro = false; - me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0); - return; - } - - WaitTimer = 1; - } - - if (Flying) - { - if (id == 0) - { - me->MonsterTextEmote(EMOTE_BREATH, 0, true); - Flying = false; - Phase = 2; - return; - } - - if (id == 3) - { - MovePhase = 4; - WaitTimer = 1; - return; - } - - if (id == 8) - { - Flying = false; - Phase = 1; - Movement = true; - return; - } - - WaitTimer = 1; - } - } - - void JustSummoned(Creature *summoned) - { - summoned->AI()->AttackStart(me->getVictim()); - } - - void TakeOff() - { - me->MonsterYell(YELL_FLY_PHASE, LANG_UNIVERSAL, NULL); - - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - (*me).GetMotionMaster()->Clear(false); - (*me).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]); - - Flying = true; - - FlyTimer = urand(45000,60000); //timer wrong between 45 and 60 seconds - ++FlyCount; - - RainofBonesTimer = 5000; //timer wrong (maybe) - RainBones = false; - Skeletons = false; - } - - void UpdateAI(const uint32 diff) - { - /* The timer for this was never setup apparently, not sure if the code works properly: - if (WaitTimer <= diff) - { - if (Intro) - { - if (MovePhase >= 7) - { - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); - } - else - { - me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]); - ++MovePhase; - } - } - if (Flying) - { - if (MovePhase >= 7) - { - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); - } - else - { - me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]); - ++MovePhase; - } - } - - WaitTimer = 0; - } else WaitTimer -= diff; - */ - - if (!UpdateVictim()) - return; - - if (Flying) - return; - - // Phase 1 "GROUND FIGHT" - if (Phase == 1) - { - if (Movement) - { - DoStartMovement(me->getVictim()); - Movement = false; - } - - if (BellowingRoarTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); - BellowingRoarTimer = urand(30000,40000); - } else BellowingRoarTimer -= diff; - - if (SmolderingBreathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SMOLDERING_BREATH); - SmolderingBreathTimer = 20000; - } else SmolderingBreathTimer -= diff; - - if (CharredEarthTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CHARRED_EARTH); - CharredEarthTimer = 20000; - } else CharredEarthTimer -= diff; - - if (TailSweepTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (!me->HasInArc(M_PI, pTarget)) - DoCast(pTarget, SPELL_TAIL_SWEEP); - TailSweepTimer = 15000; - } else TailSweepTimer -= diff; - - if (SearingCindersTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SEARING_CINDERS); - SearingCindersTimer = 10000; - } else SearingCindersTimer -= diff; - - uint32 Prozent; - Prozent = (me->GetHealth()*100) / me->GetMaxHealth(); - - if (Prozent < 75 && FlyCount == 0) // first take off 75% - TakeOff(); - - if (Prozent < 50 && FlyCount == 1) // secound take off 50% - TakeOff(); - - if (Prozent < 25 && FlyCount == 2) // third take off 25% - TakeOff(); - - DoMeleeAttackIfReady(); - } - - //Phase 2 "FLYING FIGHT" - if (Phase == 2) - { - if (!RainBones) - { - if (!Skeletons) - { - for (uint8 i = 0; i <= 3; ++i) - { - DoCast(me->getVictim(), SPELL_SUMMON_SKELETON); - Skeletons = true; - } - } - - if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2 - { - DoCast(me->getVictim(), SPELL_RAIN_OF_BONES); - RainBones = true; - SmokingBlastTimer = 20000; - } else RainofBonesTimer -= diff; - - if (DistractingAshTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_DISTRACTING_ASH); - DistractingAshTimer = 2000; //timer wrong - } else DistractingAshTimer -= diff; - } - - if (RainBones) - { - if (SmokingBlastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SMOKING_BLAST); - SmokingBlastTimer = 1500; //timer wrong - } else SmokingBlastTimer -= diff; - } - - if (FireballBarrageTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_FARTHEST, 0)) - DoCast(pTarget, SPELL_FIREBALL_BARRAGE); - FireballBarrageTimer = 20000; - } else FireballBarrageTimer -= diff; - - if (FlyTimer <= diff) //landing - { - me->MonsterYell(RAND(*YELL_LAND_PHASE_1,*YELL_LAND_PHASE_2), LANG_UNIVERSAL, NULL); - - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(3,IntroWay[3][0],IntroWay[3][1],IntroWay[3][2]); - - Flying = true; - } else FlyTimer -= diff; - } - } -}; - -CreatureAI* GetAI_boss_nightbane(Creature* pCreature) -{ - return new boss_nightbaneAI (pCreature); -} - -void AddSC_boss_nightbane() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nightbane"; - newscript->GetAI = &GetAI_boss_nightbane; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp deleted file mode 100644 index 1071eae78a0..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Prince_Malchezzar -SD%Complete: 100 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define SAY_AGGRO -1532091 -#define SAY_AXE_TOSS1 -1532092 -#define SAY_AXE_TOSS2 -1532093 -#define SAY_SPECIAL1 -1532094 -#define SAY_SPECIAL2 -1532095 -#define SAY_SPECIAL3 -1532096 -#define SAY_SLAY1 -1532097 -#define SAY_SLAY2 -1532098 -#define SAY_SLAY3 -1532099 -#define SAY_SUMMON1 -1532100 -#define SAY_SUMMON2 -1532101 -#define SAY_DEATH -1532102 - -// 18 Coordinates for Infernal spawns -struct InfernalPoint -{ - float x,y; -}; - -#define INFERNAL_Z 275.5 - -static InfernalPoint InfernalPoints[] = -{ - {-10922.8, -1985.2}, - {-10916.2, -1996.2}, - {-10932.2, -2008.1}, - {-10948.8, -2022.1}, - {-10958.7, -1997.7}, - {-10971.5, -1997.5}, - {-10990.8, -1995.1}, - {-10989.8, -1976.5}, - {-10971.6, -1973.0}, - {-10955.5, -1974.0}, - {-10939.6, -1969.8}, - {-10958.0, -1952.2}, - {-10941.7, -1954.8}, - {-10943.1, -1988.5}, - {-10948.8, -2005.1}, - {-10984.0, -2019.3}, - {-10932.8, -1979.6}, - {-10935.7, -1996.0} -}; - -#define TOTAL_INFERNAL_POINTS 18 - -//Enfeeble is supposed to reduce hp to 1 and then heal player back to full when it ends -//Along with reducing healing and regen while enfeebled to 0% -//This spell effect will only reduce healing - -#define SPELL_ENFEEBLE 30843 //Enfeeble during phase 1 and 2 -#define SPELL_ENFEEBLE_EFFECT 41624 - -#define SPELL_SHADOWNOVA 30852 //Shadownova used during all phases -#define SPELL_SW_PAIN 30854 //Shadow word pain during phase 1 and 3 (different targeting rules though) -#define SPELL_THRASH_PASSIVE 12787 //Extra attack chance during phase 2 -#define SPELL_SUNDER_ARMOR 30901 //Sunder armor during phase 2 -#define SPELL_THRASH_AURA 12787 //Passive proc chance for thrash -#define SPELL_EQUIP_AXES 30857 //Visual for axe equiping -#define SPELL_AMPLIFY_DAMAGE 39095 //Amplifiy during phase 3 -#define SPELL_CLEAVE 30131 //Same as Nightbane. -#define SPELL_HELLFIRE 30859 //Infenals' hellfire aura -#define NETHERSPITE_INFERNAL 17646 //The netherspite infernal creature -#define MALCHEZARS_AXE 17650 //Malchezar's axes (creatures), summoned during phase 3 - -#define INFERNAL_MODEL_INVISIBLE 11686 //Infernal Effects -#define SPELL_INFERNAL_RELAY 30834 - -#define EQUIP_ID_AXE 33542 //Axes info - -//---------Infernal code first -struct netherspite_infernalAI : public ScriptedAI -{ - netherspite_infernalAI(Creature *c) : ScriptedAI(c) , - malchezaar(0), HellfireTimer(0), CleanupTimer(0), point(NULL) {} - - uint32 HellfireTimer; - uint32 CleanupTimer; - uint32 malchezaar; - InfernalPoint *point; - - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (HellfireTimer) - if (HellfireTimer <= diff) - { - DoCast(me, SPELL_HELLFIRE); - HellfireTimer = 0; - } - else HellfireTimer -= diff; - - if (CleanupTimer) - if (CleanupTimer <= diff) - { - Cleanup(); - CleanupTimer = 0; - } else CleanupTimer -= diff; - } - - void KilledUnit(Unit *who) - { - Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar); - if (pMalchezaar) - CAST_CRE(pMalchezaar)->AI()->KilledUnit(who); - } - - void SpellHit(Unit * /*who*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_INFERNAL_RELAY) - { - me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - HellfireTimer = 4000; - CleanupTimer = 170000; - } - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != malchezaar) - damage = 0; - } - - void Cleanup(); //below ... -}; - -struct boss_malchezaarAI : public ScriptedAI -{ - boss_malchezaarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 EnfeebleTimer; - uint32 EnfeebleResetTimer; - uint32 ShadowNovaTimer; - uint32 SWPainTimer; - uint32 SunderArmorTimer; - uint32 AmplifyDamageTimer; - uint32 Cleave_Timer; - uint32 InfernalTimer; - uint32 AxesTargetSwitchTimer; - uint32 InfernalCleanupTimer; - - std::vector infernals; - std::vector positions; - - uint64 axes[2]; - uint64 enfeeble_targets[5]; - uint64 enfeeble_health[5]; - - uint32 phase; - - void Reset() - { - AxesCleanup(); - ClearWeapons(); - InfernalCleanup(); - positions.clear(); - - for (uint8 i = 0; i < 5; ++i) - enfeeble_targets[i] = 0; - - for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i) - positions.push_back(&InfernalPoints[i]); - - EnfeebleTimer = 30000; - EnfeebleResetTimer = 38000; - ShadowNovaTimer = 35500; - SWPainTimer = 20000; - AmplifyDamageTimer = 5000; - Cleave_Timer = 8000; - InfernalTimer = 45000; - InfernalCleanupTimer = 47000; - AxesTargetSwitchTimer = urand(7500,20000); - SunderArmorTimer = urand(5000,10000); - phase = 1; - - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - AxesCleanup(); - ClearWeapons(); - InfernalCleanup(); - positions.clear(); - - for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i) - positions.push_back(&InfernalPoints[i]); - - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), false); // Open the door leading further in - } - - void InfernalCleanup() - { - //Infernal Cleanup - for (std::vector::const_iterator itr = infernals.begin(); itr != infernals.end(); ++itr) - if (Unit *pInfernal = Unit::GetUnit(*me, *itr)) - if (pInfernal->isAlive()) - { - pInfernal->SetVisibility(VISIBILITY_OFF); - pInfernal->setDeathState(JUST_DIED); - } - - infernals.clear(); - } - - void AxesCleanup() - { - for (uint8 i = 0; i < 2; ++i) - { - Unit *axe = Unit::GetUnit(*me, axes[i]); - if (axe && axe->isAlive()) - axe->Kill(axe); - axes[i] = 0; - } - } - - void ClearWeapons() - { - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - - //damage - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg); - me->UpdateDamagePhysical(BASE_ATTACK); - } - - void EnfeebleHealthEffect() - { - const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT); - if (!info) - return; - - std::list t_list = me->getThreatManager().getThreatList(); - std::vector targets; - - if (!t_list.size()) - return; - - //begin + 1, so we don't target the one with the highest threat - std::list::const_iterator itr = t_list.begin(); - std::advance(itr, 1); - for (; itr != t_list.end(); ++itr) //store the threat list in a different container - if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - if (pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - targets.push_back(pTarget); - - //cut down to size if we have more than 5 targets - while (targets.size() > 5) - targets.erase(targets.begin()+rand()%targets.size()); - - uint32 i = 0; - for (std::vector::const_iterator iter = targets.begin(); iter != targets.end(); ++iter, ++i) - if (Unit *pTarget = *iter) - { - enfeeble_targets[i] = pTarget->GetGUID(); - enfeeble_health[i] = pTarget->GetHealth(); - - pTarget->CastSpell(pTarget, SPELL_ENFEEBLE, true, 0, 0, me->GetGUID()); - pTarget->SetHealth(1); - } - } - - void EnfeebleResetHealth() - { - for (uint8 i = 0; i < 5; ++i) - { - Unit *pTarget = Unit::GetUnit(*me, enfeeble_targets[i]); - if (pTarget && pTarget->isAlive()) - pTarget->SetHealth(enfeeble_health[i]); - enfeeble_targets[i] = 0; - enfeeble_health[i] = 0; - } - } - - void SummonInfernal(const uint32 /*diff*/) - { - InfernalPoint *point = NULL; - Position pos; - if ((me->GetMapId() != 532) || positions.empty()) - me->GetRandomNearPosition(pos, 60); - else - { - std::vector::iterator itr = positions.begin()+rand()%positions.size(); - point = *itr; - positions.erase(itr); - pos.Relocate(point->x, point->y, INFERNAL_Z); - } - - Creature *Infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000); - - if (Infernal) - { - Infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE); - Infernal->setFaction(me->getFaction()); - if (point) - CAST_AI(netherspite_infernalAI, Infernal->AI())->point=point; - CAST_AI(netherspite_infernalAI, Infernal->AI())->malchezaar=me->GetGUID(); - - infernals.push_back(Infernal->GetGUID()); - DoCast(Infernal, SPELL_INFERNAL_RELAY); - } - - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (EnfeebleResetTimer && EnfeebleResetTimer <= diff) // Let's not forget to reset that - { - EnfeebleResetHealth(); - EnfeebleResetTimer = 0; - } else EnfeebleResetTimer -= diff; - - if (me->hasUnitState(UNIT_STAT_STUNNED)) // While shifting to phase 2 malchezaar stuns himself - return; - - if (me->GetUInt64Value(UNIT_FIELD_TARGET) != me->getVictim()->GetGUID()) - me->SetUInt64Value(UNIT_FIELD_TARGET, me->getVictim()->GetGUID()); - - if (phase == 1) - { - if ((me->GetHealth()*100) / me->GetMaxHealth() < 60) - { - me->InterruptNonMeleeSpells(false); - - phase = 2; - - //animation - DoCast(me, SPELL_EQUIP_AXES); - - //text - DoScriptText(SAY_AXE_TOSS1, me); - - //passive thrash aura - DoCast(me, SPELL_THRASH_AURA, true); - - //models - SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE); - - //damage - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg); - me->UpdateDamagePhysical(BASE_ATTACK); - - me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg); - me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg); - //Sigh, updating only works on main attack, do it manually .... - me->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg); - me->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg); - - me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100); - } - } - else if (phase == 2) - { - if ((me->GetHealth()*100) / me->GetMaxHealth() < 30) - { - InfernalTimer = 15000; - - phase = 3; - - ClearWeapons(); - - //remove thrash - me->RemoveAurasDueToSpell(SPELL_THRASH_AURA); - - DoScriptText(SAY_AXE_TOSS2, me); - - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - for (uint8 i = 0; i < 2; ++i) - { - Creature *axe = me->SummonCreature(MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); - if (axe) - { - axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - axe->setFaction(me->getFaction()); - axes[i] = axe->GetGUID(); - if (pTarget) - { - axe->AI()->AttackStart(pTarget); - //axe->getThreatManager().tauntApply(pTarget); //Taunt Apply and fade out does not work properly - // So we'll use a hack to add a lot of threat to our target - axe->AddThreat(pTarget, 10000000.0f); - } - } - } - - if (ShadowNovaTimer > 35000) - ShadowNovaTimer = EnfeebleTimer + 5000; - - return; - } - - if (SunderArmorTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDER_ARMOR); - SunderArmorTimer = urand(10000,18000); - - } else SunderArmorTimer -= diff; - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = urand(6000,12000); - - } else Cleave_Timer -= diff; - } - else - { - if (AxesTargetSwitchTimer <= diff) - { - AxesTargetSwitchTimer = urand(7500,20000); - - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Unit *axe = Unit::GetUnit(*me, axes[i])) - { - if (axe->getVictim()) - DoModifyThreatPercent(axe->getVictim(), -100); - if (pTarget) - axe->AddThreat(pTarget, 1000000.0f); - //axe->getThreatManager().tauntFadeOut(axe->getVictim()); - //axe->getThreatManager().tauntApply(pTarget); - } - } - } - } else AxesTargetSwitchTimer -= diff; - - if (AmplifyDamageTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_AMPLIFY_DAMAGE); - AmplifyDamageTimer = urand(20000,30000); - } else AmplifyDamageTimer -= diff; - } - - //Time for global and double timers - if (InfernalTimer <= diff) - { - SummonInfernal(diff); - InfernalTimer = phase == 3 ? 14500 : 44500; // 15 secs in phase 3, 45 otherwise - } else InfernalTimer -= diff; - - if (ShadowNovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWNOVA); - ShadowNovaTimer = phase == 3 ? 31000 : uint32(-1); - } else ShadowNovaTimer -= diff; - - if (phase != 2) - { - if (SWPainTimer <= diff) - { - Unit *pTarget = NULL; - if (phase == 1) - pTarget = me->getVictim(); // the tank - else // anyone but the tank - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - - if (pTarget) - DoCast(pTarget, SPELL_SW_PAIN); - - SWPainTimer = 20000; - } else SWPainTimer -= diff; - } - - if (phase != 3) - { - if (EnfeebleTimer <= diff) - { - EnfeebleHealthEffect(); - EnfeebleTimer = 30000; - ShadowNovaTimer = 5000; - EnfeebleResetTimer = 9000; - } else EnfeebleTimer -= diff; - } - - if (phase == 2) - DoMeleeAttacksIfReady(); - else - DoMeleeAttackIfReady(); - } - - void DoMeleeAttacksIfReady() - { - if (me->IsWithinMeleeRange(me->getVictim()) && !me->IsNonMeleeSpellCasted(false)) - { - //Check for base attack - if (me->isAttackReady() && me->getVictim()) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - //Check for offhand attack - if (me->isAttackReady(OFF_ATTACK) && me->getVictim()) - { - me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK); - me->resetAttackTimer(OFF_ATTACK); - } - } - } - - void Cleanup(Creature *infernal, InfernalPoint *point) - { - for (std::vector::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr) - if (*itr == infernal->GetGUID()) - { - infernals.erase(itr); - break; - } - - positions.push_back(point); - } -}; - -void netherspite_infernalAI::Cleanup() -{ - Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar); - - if (pMalchezaar && pMalchezaar->isAlive()) - CAST_AI(boss_malchezaarAI, CAST_CRE(pMalchezaar)->AI())->Cleanup(me, point); -} - -CreatureAI* GetAI_netherspite_infernal(Creature* pCreature) -{ - return new netherspite_infernalAI (pCreature); -} - -CreatureAI* GetAI_boss_malchezaar(Creature* pCreature) -{ - return new boss_malchezaarAI (pCreature); -} - -void AddSC_boss_malchezaar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_malchezaar"; - newscript->GetAI = &GetAI_boss_malchezaar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "netherspite_infernal"; - newscript->GetAI = &GetAI_netherspite_infernal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp deleted file mode 100644 index 394cff3ccc5..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Shade_of_Aran -SD%Complete: 95 -SDComment: Flame wreath missing cast animation, mods won't triggere. -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedSimpleAI.h" -#include "karazhan.h" -#include "GameObject.h" - -#define SAY_AGGRO1 -1532073 -#define SAY_AGGRO2 -1532074 -#define SAY_AGGRO3 -1532075 -#define SAY_FLAMEWREATH1 -1532076 -#define SAY_FLAMEWREATH2 -1532077 -#define SAY_BLIZZARD1 -1532078 -#define SAY_BLIZZARD2 -1532079 -#define SAY_EXPLOSION1 -1532080 -#define SAY_EXPLOSION2 -1532081 -#define SAY_DRINK -1532082 //Low Mana / AoE Pyroblast -#define SAY_ELEMENTALS -1532083 -#define SAY_KILL1 -1532084 -#define SAY_KILL2 -1532085 -#define SAY_TIMEOVER -1532086 -#define SAY_DEATH -1532087 -#define SAY_ATIESH -1532088 //Atiesh is equipped by a raid member - -//Spells -#define SPELL_FROSTBOLT 29954 -#define SPELL_FIREBALL 29953 -#define SPELL_ARCMISSLE 29955 -#define SPELL_CHAINSOFICE 29991 -#define SPELL_DRAGONSBREATH 29964 -#define SPELL_MASSSLOW 30035 -#define SPELL_FLAME_WREATH 29946 -#define SPELL_AOE_CS 29961 -#define SPELL_PLAYERPULL 32265 -#define SPELL_AEXPLOSION 29973 -#define SPELL_MASS_POLY 29963 -#define SPELL_BLINK_CENTER 29967 -#define SPELL_ELEMENTALS 29962 -#define SPELL_CONJURE 29975 -#define SPELL_DRINK 30024 -#define SPELL_POTION 32453 -#define SPELL_AOE_PYROBLAST 29978 - -//Creature Spells -#define SPELL_CIRCULAR_BLIZZARD 29951 //29952 is the REAL circular blizzard that leaves persistant blizzards that last for 10 seconds -#define SPELL_WATERBOLT 31012 -#define SPELL_SHADOW_PYRO 29978 - -//Creatures -#define CREATURE_WATER_ELEMENTAL 17167 -#define CREATURE_SHADOW_OF_ARAN 18254 -#define CREATURE_ARAN_BLIZZARD 17161 - -enum SuperSpell -{ - SUPER_FLAME = 0, - SUPER_BLIZZARD, - SUPER_AE, -}; - -struct boss_aranAI : public ScriptedAI -{ - boss_aranAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 SecondarySpellTimer; - uint32 NormalCastTimer; - uint32 SuperCastTimer; - uint32 BerserkTimer; - uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering. - - uint8 LastSuperSpell; - - uint32 FlameWreathTimer; - uint32 FlameWreathCheckTime; - uint64 FlameWreathTarget[3]; - float FWTargPosX[3]; - float FWTargPosY[3]; - - uint32 CurrentNormalSpell; - uint32 ArcaneCooldown; - uint32 FireCooldown; - uint32 FrostCooldown; - - uint32 DrinkInturruptTimer; - - bool ElementalsSpawned; - bool Drinking; - bool DrinkInturrupted; - - void Reset() - { - SecondarySpellTimer = 5000; - NormalCastTimer = 0; - SuperCastTimer = 35000; - BerserkTimer = 720000; - CloseDoorTimer = 15000; - - LastSuperSpell = rand()%3; - - FlameWreathTimer = 0; - FlameWreathCheckTime = 0; - - CurrentNormalSpell = 0; - ArcaneCooldown = 0; - FireCooldown = 0; - FrostCooldown = 0; - - DrinkInturruptTimer = 10000; - - ElementalsSpawned = false; - Drinking = false; - DrinkInturrupted = false; - - if (pInstance) - { - // Not in progress - pInstance->SetData(TYPE_ARAN, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true); - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_ARAN, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - - if (pInstance) - { - pInstance->SetData(TYPE_ARAN, IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false); - } - } - - void FlameWreathEffect() - { - std::vector targets; - std::list t_list = me->getThreatManager().getThreatList(); - - if (!t_list.size()) - return; - - //store the threat list in a different container - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //only on alive players - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - targets.push_back(pTarget); - } - - //cut down to size if we have more than 3 targets - while (targets.size() > 3) - targets.erase(targets.begin()+rand()%targets.size()); - - uint32 i = 0; - for (std::vector::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr) - { - if (*itr) - { - FlameWreathTarget[i] = (*itr)->GetGUID(); - FWTargPosX[i] = (*itr)->GetPositionX(); - FWTargPosY[i] = (*itr)->GetPositionY(); - DoCast((*itr), SPELL_FLAME_WREATH, true); - ++i; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (CloseDoorTimer) - { - if (CloseDoorTimer <= diff) - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false); - CloseDoorTimer = 0; - } - } else CloseDoorTimer -= diff; - } - - //Cooldowns for casts - if (ArcaneCooldown) - { - if (ArcaneCooldown >= diff) - ArcaneCooldown -= diff; - else ArcaneCooldown = 0; - } - - if (FireCooldown) - { - if (FireCooldown >= diff) - FireCooldown -= diff; - else FireCooldown = 0; - } - - if (FrostCooldown) - { - if (FrostCooldown >= diff) - FrostCooldown -= diff; - else FrostCooldown = 0; - } - - if (!Drinking && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA)) < 20) - { - Drinking = true; - me->InterruptNonMeleeSpells(false); - - DoScriptText(SAY_DRINK, me); - - if (!DrinkInturrupted) - { - DoCast(me, SPELL_MASS_POLY, true); - DoCast(me, SPELL_CONJURE, false); - DoCast(me, SPELL_DRINK, false); - me->SetStandState(UNIT_STAND_STATE_SIT); - DrinkInturruptTimer = 10000; - } - } - - //Drink Inturrupt - if (Drinking && DrinkInturrupted) - { - Drinking = false; - me->RemoveAurasDueToSpell(SPELL_DRINK); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)-32000); - DoCast(me, SPELL_POTION, false); - } - - //Drink Inturrupt Timer - if (Drinking && !DrinkInturrupted) - if (DrinkInturruptTimer >= diff) - DrinkInturruptTimer -= diff; - else - { - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_POTION, true); - DoCast(me, SPELL_AOE_PYROBLAST, false); - DrinkInturrupted = true; - Drinking = false; - } - - //Don't execute any more code if we are drinking - if (Drinking) - return; - - //Normal casts - if (NormalCastTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!pTarget) - return; - - uint32 Spells[3]; - uint8 AvailableSpells = 0; - - //Check for what spells are not on cooldown - if (!ArcaneCooldown) - { - Spells[AvailableSpells] = SPELL_ARCMISSLE; - ++AvailableSpells; - } - if (!FireCooldown) - { - Spells[AvailableSpells] = SPELL_FIREBALL; - ++AvailableSpells; - } - if (!FrostCooldown) - { - Spells[AvailableSpells] = SPELL_FROSTBOLT; - ++AvailableSpells; - } - - //If no available spells wait 1 second and try again - if (AvailableSpells) - { - CurrentNormalSpell = Spells[rand() % AvailableSpells]; - DoCast(pTarget, CurrentNormalSpell); - } - } - NormalCastTimer = 1000; - } else NormalCastTimer -= diff; - - if (SecondarySpellTimer <= diff) - { - switch (urand(0,1)) - { - case 0: - DoCast(me, SPELL_AOE_CS); - break; - case 1: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CHAINSOFICE); - break; - } - SecondarySpellTimer = urand(5000,20000); - } else SecondarySpellTimer -= diff; - - if (SuperCastTimer <= diff) - { - uint8 Available[2]; - - switch (LastSuperSpell) - { - case SUPER_AE: - Available[0] = SUPER_FLAME; - Available[1] = SUPER_BLIZZARD; - break; - case SUPER_FLAME: - Available[0] = SUPER_AE; - Available[1] = SUPER_BLIZZARD; - break; - case SUPER_BLIZZARD: - Available[0] = SUPER_FLAME; - Available[1] = SUPER_AE; - break; - } - - LastSuperSpell = Available[urand(0,1)]; - - switch (LastSuperSpell) - { - case SUPER_AE: - DoScriptText(RAND(SAY_EXPLOSION1,SAY_EXPLOSION2), me); - - DoCast(me, SPELL_BLINK_CENTER, true); - DoCast(me, SPELL_PLAYERPULL, true); - DoCast(me, SPELL_MASSSLOW, true); - DoCast(me, SPELL_AEXPLOSION, false); - break; - - case SUPER_FLAME: - DoScriptText(RAND(SAY_FLAMEWREATH1,SAY_FLAMEWREATH2), me); - - FlameWreathTimer = 20000; - FlameWreathCheckTime = 500; - - FlameWreathTarget[0] = 0; - FlameWreathTarget[1] = 0; - FlameWreathTarget[2] = 0; - - FlameWreathEffect(); - break; - - case SUPER_BLIZZARD: - DoScriptText(RAND(SAY_BLIZZARD1,SAY_BLIZZARD2), me); - - if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000)) - { - pSpawn->setFaction(me->getFaction()); - pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false); - } - break; - } - - SuperCastTimer = urand(35000,40000); - } else SuperCastTimer -= diff; - - if (!ElementalsSpawned && me->GetHealth()*100 / me->GetMaxHealth() < 40) - { - ElementalsSpawned = true; - - for (uint32 i = 0; i < 4; ++i) - { - if (Creature* pUnit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90000)) - { - pUnit->Attack(me->getVictim(), true); - pUnit->setFaction(me->getFaction()); - } - } - - DoScriptText(SAY_ELEMENTALS, me); - } - - if (BerserkTimer <= diff) - { - for (uint32 i = 0; i < 5; ++i) - { - if (Creature* pUnit = me->SummonCreature(CREATURE_SHADOW_OF_ARAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) - { - pUnit->Attack(me->getVictim(), true); - pUnit->setFaction(me->getFaction()); - } - } - - DoScriptText(SAY_TIMEOVER, me); - - BerserkTimer = 60000; - } else BerserkTimer -= diff; - - //Flame Wreath check - if (FlameWreathTimer) - { - if (FlameWreathTimer >= diff) - FlameWreathTimer -= diff; - else FlameWreathTimer = 0; - - if (FlameWreathCheckTime <= diff) - { - for (uint8 i = 0; i < 3; ++i) - { - if (!FlameWreathTarget[i]) - continue; - - Unit* pUnit = Unit::GetUnit(*me, FlameWreathTarget[i]); - if (pUnit && !pUnit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3)) - { - pUnit->CastSpell(pUnit, 20476, true, 0, 0, me->GetGUID()); - pUnit->CastSpell(pUnit, 11027, true); - FlameWreathTarget[i] = 0; - } - } - FlameWreathCheckTime = 500; - } else FlameWreathCheckTime -= diff; - } - - if (ArcaneCooldown && FireCooldown && FrostCooldown) - DoMeleeAttackIfReady(); - } - - void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) - { - if (!DrinkInturrupted && Drinking && damage) - DrinkInturrupted = true; - } - - void SpellHit(Unit* /*pAttacker*/, const SpellEntry* Spell) - { - //We only care about inturrupt effects and only if they are durring a spell currently being casted - if ((Spell->Effect[0] != SPELL_EFFECT_INTERRUPT_CAST && - Spell->Effect[1] != SPELL_EFFECT_INTERRUPT_CAST && - Spell->Effect[2] != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCasted(false)) - return; - - //Inturrupt effect - me->InterruptNonMeleeSpells(false); - - //Normally we would set the cooldown equal to the spell duration - //but we do not have access to the DurationStore - - switch (CurrentNormalSpell) - { - case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break; - case SPELL_FIREBALL: FireCooldown = 5000; break; - case SPELL_FROSTBOLT: FrostCooldown = 5000; break; - } - } -}; - -struct water_elementalAI : public ScriptedAI -{ - water_elementalAI(Creature *c) : ScriptedAI(c) {} - - uint32 CastTimer; - - void Reset() - { - CastTimer = 2000 + (rand()%3000); - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (CastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WATERBOLT); - CastTimer = urand(2000,5000); - } else CastTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_aran(Creature* pCreature) -{ - return new boss_aranAI (pCreature); -} - -CreatureAI* GetAI_water_elemental(Creature* pCreature) -{ - return new water_elementalAI (pCreature); -} - -// CONVERT TO ACID -CreatureAI* GetAI_shadow_of_aran(Creature* pCreature) -{ - outstring_log("TSCR: Convert simpleAI script for Creature Entry %u to ACID", pCreature->GetEntry()); - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = SPELL_SHADOW_PYRO; - ai->Spell[0].Cooldown = 5000; - ai->Spell[0].First_Cast = 1000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->EnterEvadeMode(); - - return ai; -} - -void AddSC_boss_shade_of_aran() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shade_of_aran"; - newscript->GetAI = &GetAI_boss_aran; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadow_of_aran"; - newscript->GetAI = &GetAI_shadow_of_aran; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_aran_elemental"; - newscript->GetAI = &GetAI_water_elemental; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp b/src/server/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp deleted file mode 100644 index 5305cc8d354..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Terestian_Illhoof -SD%Complete: 95 -SDComment: Complete! Needs adjustments to use spell though. -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define SAY_SLAY1 -1532065 -#define SAY_SLAY2 -1532066 -#define SAY_DEATH -1532067 -#define SAY_AGGRO -1532068 -#define SAY_SACRIFICE1 -1532069 -#define SAY_SACRIFICE2 -1532070 -#define SAY_SUMMON1 -1532071 -#define SAY_SUMMON2 -1532072 - -#define SPELL_SUMMON_DEMONCHAINS 30120 // Summons demonic chains that maintain the ritual of sacrifice. -#define SPELL_DEMON_CHAINS 30206 // Instant - Visual Effect -#define SPELL_ENRAGE 23537 // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min. -#define SPELL_SHADOW_BOLT 30055 // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage. -#define SPELL_SACRIFICE 30115 // Teleports and adds the debuff -#define SPELL_BERSERK 32965 // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley. -#define SPELL_SUMMON_FIENDISIMP 30184 // Summons a Fiendish Imp. -#define SPELL_SUMMON_IMP 30066 // Summons Kil'rek - -#define SPELL_FIENDISH_PORTAL 30171 // Opens portal and summons Fiendish Portal, 2 sec cast -#define SPELL_FIENDISH_PORTAL_1 30179 // Opens portal and summons Fiendish Portal, instant cast - -#define SPELL_FIREBOLT 30050 // Blasts a target for 150 Fire damage. -#define SPELL_BROKEN_PACT 30065 // All damage taken increased by 25%. -#define SPELL_AMPLIFY_FLAMES 30053 // Increases the Fire damage taken by an enemy by 500 for 25 sec. - -#define CREATURE_DEMONCHAINS 17248 -#define CREATURE_FIENDISHIMP 17267 -#define CREATURE_PORTAL 17265 -#define CREATURE_KILREK 17229 - -struct mob_kilrekAI : public ScriptedAI -{ - mob_kilrekAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 TerestianGUID; - - uint32 AmplifyTimer; - - void Reset() - { - TerestianGUID = 0; - AmplifyTimer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - if (!pInstance) - { - ERROR_INST_DATA(me); - return; - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - uint64 TerestianGUID = pInstance->GetData64(DATA_TERESTIAN); - if (TerestianGUID) - { - Unit* Terestian = Unit::GetUnit((*me), TerestianGUID); - if (Terestian && Terestian->isAlive()) - DoCast(Terestian, SPELL_BROKEN_PACT, true); - } - } else ERROR_INST_DATA(me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (AmplifyTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES); - - AmplifyTimer = urand(10000,20000); - } else AmplifyTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_demon_chainAI : public ScriptedAI -{ - mob_demon_chainAI(Creature *c) : ScriptedAI(c) {} - - uint64 SacrificeGUID; - - void Reset() - { - SacrificeGUID = 0; - } - - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void JustDied(Unit * /*killer*/) - { - if (SacrificeGUID) - { - Unit* Sacrifice = Unit::GetUnit((*me),SacrificeGUID); - if (Sacrifice) - Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE); - } - } -}; - -struct mob_fiendish_portalAI : public PassiveAI -{ - mob_fiendish_portalAI(Creature *c) : PassiveAI(c),summons(me){} - - SummonList summons; - - void Reset() - { - summons.DespawnAll(); - } - - void JustSummoned(Creature* summon) - { - summons.Summon(summon); - DoZoneInCombat(summon); - } - - void DespawnAllImp() - { - summons.DespawnAll(); - } -}; - -struct boss_terestianAI : public ScriptedAI -{ - boss_terestianAI(Creature *c) : ScriptedAI(c) - { - for (uint8 i = 0; i < 2; ++i) - PortalGUID[i] = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint64 PortalGUID[2]; - uint8 PortalsCount; - - uint32 SacrificeTimer; - uint32 ShadowboltTimer; - uint32 SummonTimer; - uint32 BerserkTimer; - - bool SummonedPortals; - bool Berserk; - - void Reset() - { - for (uint8 i = 0; i < 2; ++i) - { - if (PortalGUID[i]) - { - if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[i])) - { - CAST_AI(mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp(); - pPortal->ForcedDespawn(); - } - - PortalGUID[i] = 0; - } - } - - PortalsCount = 0; - SacrificeTimer = 30000; - ShadowboltTimer = 5000; - SummonTimer = 10000; - BerserkTimer = 600000; - - SummonedPortals = false; - Berserk = false; - - if (pInstance) - pInstance->SetData(TYPE_TERESTIAN, NOT_STARTED); - - me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT); - - if (Minion* Kilrek = me->GetFirstMinion()) - { - if (!Kilrek->isAlive()) - { - Kilrek->UnSummon(); - DoCast(me, SPELL_SUMMON_IMP, true); - } - } - else DoCast(me, SPELL_SUMMON_IMP, true); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == CREATURE_PORTAL) - { - PortalGUID[PortalsCount] = pSummoned->GetGUID(); - ++PortalsCount; - - if (pSummoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1) - { - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - SummonedPortals = true; - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*killer*/) - { - for (uint8 i = 0; i < 2; ++i) - { - if (PortalGUID[i]) - { - if (Creature* pPortal = Unit::GetCreature((*me), PortalGUID[i])) - pPortal->ForcedDespawn(); - - PortalGUID[i] = 0; - } - } - - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_TERESTIAN, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (SacrificeTimer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - if (pTarget && pTarget->isAlive()) - { - DoCast(pTarget, SPELL_SACRIFICE, true); - DoCast(pTarget, SPELL_SUMMON_DEMONCHAINS, true); - - if (Creature* Chains = me->FindNearestCreature(CREATURE_DEMONCHAINS, 5000)) - { - CAST_AI(mob_demon_chainAI, Chains->AI())->SacrificeGUID = pTarget->GetGUID(); - Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true); - DoScriptText(RAND(SAY_SACRIFICE1,SAY_SACRIFICE2), me); - SacrificeTimer = 30000; - } - } - } else SacrificeTimer -= diff; - - if (ShadowboltTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT); - ShadowboltTimer = 10000; - } else ShadowboltTimer -= diff; - - if (SummonTimer <= diff) - { - if (!PortalGUID[0]) - DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL, false); - - if (!PortalGUID[1]) - DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL_1, false); - - if (PortalGUID[0] && PortalGUID[1]) - { - if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0,1)])) - pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false); - SummonTimer = 5000; - } - } else SummonTimer -= diff; - - if (!Berserk) - { - if (BerserkTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - Berserk = true; - } else BerserkTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -#define SPELL_FIREBOLT 30050 // Blasts a target for 181-209 Fire damage. - -struct mob_fiendish_impAI : public ScriptedAI -{ - mob_fiendish_impAI(Creature *c) : ScriptedAI(c) {} - - uint32 FireboltTimer; - - void Reset() - { - FireboltTimer = 2000; - - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (FireboltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBOLT); - FireboltTimer = 2200; - } else FireboltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_kilrek(Creature* pCreature) -{ - return new mob_kilrekAI (pCreature); -} - -CreatureAI* GetAI_mob_fiendish_imp(Creature* pCreature) -{ - return new mob_fiendish_impAI (pCreature); -} - -CreatureAI* GetAI_mob_fiendish_portal(Creature* pCreature) -{ - return new mob_fiendish_portalAI (pCreature); -} - -CreatureAI* GetAI_boss_terestian_illhoof(Creature* pCreature) -{ - return new boss_terestianAI (pCreature); -} - -CreatureAI* GetAI_mob_demon_chain(Creature* pCreature) -{ - return new mob_demon_chainAI(pCreature); -} - -void AddSC_boss_terestian_illhoof() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_terestian_illhoof"; - newscript->GetAI = &GetAI_boss_terestian_illhoof; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fiendish_imp"; - newscript->GetAI = &GetAI_mob_fiendish_imp; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name= "mob_fiendish_portal"; - newscript->GetAI = &GetAI_mob_fiendish_portal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_kilrek"; - newscript->GetAI = &GetAI_mob_kilrek; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_demon_chain"; - newscript->GetAI = &GetAI_mob_demon_chain; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp b/src/server/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp deleted file mode 100644 index ae6de9c1add..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp +++ /dev/null @@ -1,1494 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Bosses_Opera -SD%Complete: 90 -SDComment: Oz, Hood, and RAJ event implemented. RAJ event requires more testing. -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -/***********************************/ -/*** OPERA WIZARD OF OZ EVENT *****/ -/*********************************/ - -#define SAY_DOROTHEE_DEATH -1532025 -#define SAY_DOROTHEE_SUMMON -1532026 -#define SAY_DOROTHEE_TITO_DEATH -1532027 -#define SAY_DOROTHEE_AGGRO -1532028 - -#define SAY_ROAR_AGGRO -1532029 -#define SAY_ROAR_DEATH -1532030 -#define SAY_ROAR_SLAY -1532031 - -#define SAY_STRAWMAN_AGGRO -1532032 -#define SAY_STRAWMAN_DEATH -1532033 -#define SAY_STRAWMAN_SLAY -1532034 - -#define SAY_TINHEAD_AGGRO -1532035 -#define SAY_TINHEAD_DEATH -1532036 -#define SAY_TINHEAD_SLAY -1532037 -#define EMOTE_RUST -1532038 - -#define SAY_CRONE_AGGRO -1532039 -#define SAY_CRONE_AGGRO2 -1532040 -#define SAY_CRONE_DEATH -1532041 -#define SAY_CRONE_SLAY -1532042 - -/**** Spells ****/ -// Dorothee -#define SPELL_WATERBOLT 31012 -#define SPELL_SCREAM 31013 -#define SPELL_SUMMONTITO 31014 - -// Tito -#define SPELL_YIPPING 31015 - -// Strawman -#define SPELL_BRAIN_BASH 31046 -#define SPELL_BRAIN_WIPE 31069 -#define SPELL_BURNING_STRAW 31075 - -// Tinhead -#define SPELL_CLEAVE 31043 -#define SPELL_RUST 31086 - -// Roar -#define SPELL_MANGLE 31041 -#define SPELL_SHRED 31042 -#define SPELL_FRIGHTENED_SCREAM 31013 - -// Crone -#define SPELL_CHAIN_LIGHTNING 32337 - -// Cyclone -#define SPELL_KNOCKBACK 32334 -#define SPELL_CYCLONE_VISUAL 32332 - -/** Creature Entries **/ -#define CREATURE_TITO 17548 -#define CREATURE_CYCLONE 18412 -#define CREATURE_CRONE 18168 - -void SummonCroneIfReady(ScriptedInstance* pInstance, Creature* pCreature) -{ - pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, SPECIAL); // Increment DeathCount - - if (pInstance->GetData(DATA_OPERA_OZ_DEATHCOUNT) == 4) - { - if (Creature* pCrone = pCreature->SummonCreature(CREATURE_CRONE, -10891.96, -1755.95, pCreature->GetPositionZ(), 4.64, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) - { - if (pCreature->getVictim()) - pCrone->AI()->AttackStart(pCreature->getVictim()); - } - } -}; - -struct boss_dorotheeAI : public ScriptedAI -{ - boss_dorotheeAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AggroTimer; - - uint32 WaterBoltTimer; - uint32 FearTimer; - uint32 SummonTitoTimer; - - bool SummonedTito; - bool TitoDied; - - void Reset() - { - AggroTimer = 500; - - WaterBoltTimer = 5000; - FearTimer = 15000; - SummonTitoTimer = 47500; - - SummonedTito = false; - TitoDied = false; - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_DOROTHEE_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void SummonTito(); // See below - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DOROTHEE_DEATH, me); - - if (pInstance) - SummonCroneIfReady(pInstance, me); - } - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - if (AggroTimer) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer = 0; - } else AggroTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (WaterBoltTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_WATERBOLT); - WaterBoltTimer = TitoDied ? 1500 : 5000; - } else WaterBoltTimer -= diff; - - if (FearTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SCREAM); - FearTimer = 30000; - } else FearTimer -= diff; - - if (!SummonedTito) - { - if (SummonTitoTimer <= diff) - SummonTito(); - else SummonTitoTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_titoAI : public ScriptedAI -{ - mob_titoAI(Creature* c) : ScriptedAI(c) {} - - uint64 DorotheeGUID; - uint32 YipTimer; - - void Reset() - { - DorotheeGUID = 0; - YipTimer = 10000; - } - - void EnterCombat(Unit* /*who*/) {} - - void JustDied(Unit* /*killer*/) - { - if (DorotheeGUID) - { - Creature* Dorothee = (Unit::GetCreature((*me), DorotheeGUID)); - if (Dorothee && Dorothee->isAlive()) - { - CAST_AI(boss_dorotheeAI, Dorothee->AI())->TitoDied = true; - DoScriptText(SAY_DOROTHEE_TITO_DEATH, Dorothee); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (YipTimer <= diff) - { - DoCast(me->getVictim(), SPELL_YIPPING); - YipTimer = 10000; - } else YipTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -void boss_dorotheeAI::SummonTito() -{ - if (Creature* pTito = me->SummonCreature(CREATURE_TITO, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - DoScriptText(SAY_DOROTHEE_SUMMON, me); - CAST_AI(mob_titoAI, pTito->AI())->DorotheeGUID = me->GetGUID(); - pTito->AI()->AttackStart(me->getVictim()); - SummonedTito = true; - TitoDied = false; - } -} - -struct boss_strawmanAI : public ScriptedAI -{ - boss_strawmanAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AggroTimer; - uint32 BrainBashTimer; - uint32 BrainWipeTimer; - - void Reset() - { - AggroTimer = 13000; - BrainBashTimer = 5000; - BrainWipeTimer = 7000; - } - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_STRAWMAN_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry *Spell) - { - if ((Spell->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && (!(rand()%10))) - { - /* - if (not direct damage(aoe,dot)) - return; - */ - - DoCast(me, SPELL_BURNING_STRAW, true); - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_STRAWMAN_DEATH, me); - - if (pInstance) - SummonCroneIfReady(pInstance, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_STRAWMAN_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - if (AggroTimer) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer = 0; - } else AggroTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (BrainBashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BRAIN_BASH); - BrainBashTimer = 15000; - } else BrainBashTimer -= diff; - - if (BrainWipeTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BRAIN_WIPE); - BrainWipeTimer = 20000; - } else BrainWipeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_tinheadAI : public ScriptedAI -{ - boss_tinheadAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AggroTimer; - uint32 CleaveTimer; - uint32 RustTimer; - - uint8 RustCount; - - void Reset() - { - AggroTimer = 15000; - CleaveTimer = 5000; - RustTimer = 30000; - - RustCount = 0; - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_TINHEAD_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_TINHEAD_DEATH, me); - - if (pInstance) - SummonCroneIfReady(pInstance, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_TINHEAD_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - if (AggroTimer) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer = 0; - } else AggroTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (CleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - CleaveTimer = 5000; - } else CleaveTimer -= diff; - - if (RustCount < 8) - { - if (RustTimer <= diff) - { - ++RustCount; - DoScriptText(EMOTE_RUST, me); - DoCast(me, SPELL_RUST); - RustTimer = 6000; - } else RustTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_roarAI : public ScriptedAI -{ - boss_roarAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AggroTimer; - uint32 MangleTimer; - uint32 ShredTimer; - uint32 ScreamTimer; - - void Reset() - { - AggroTimer = 20000; - MangleTimer = 5000; - ShredTimer = 10000; - ScreamTimer = 15000; - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_ROAR_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_ROAR_DEATH, me); - - if (pInstance) - SummonCroneIfReady(pInstance, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_ROAR_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - if (AggroTimer) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer = 0; - } else AggroTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (MangleTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MANGLE); - MangleTimer = urand(5000,8000); - } else MangleTimer -= diff; - - if (ShredTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHRED); - ShredTimer = urand(10000,15000); - } else ShredTimer -= diff; - - if (ScreamTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FRIGHTENED_SCREAM); - ScreamTimer = urand(20000,30000); - } else ScreamTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_croneAI : public ScriptedAI -{ - boss_croneAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 CycloneTimer; - uint32 ChainLightningTimer; - - void Reset() - { - CycloneTimer = 30000; - ChainLightningTimer = 10000; - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(RAND(SAY_CRONE_AGGRO,SAY_CRONE_AGGRO2), me); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_CRONE_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_OPERA, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (CycloneTimer <= diff) - { - if (Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, urand(0,9), urand(0,9), 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000)) - Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_VISUAL, true); - CycloneTimer = 30000; - } else CycloneTimer -= diff; - - if (ChainLightningTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); - ChainLightningTimer = 15000; - } else ChainLightningTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_cycloneAI : public ScriptedAI -{ - mob_cycloneAI(Creature* c) : ScriptedAI(c) {} - - uint32 MoveTimer; - - void Reset() - { - MoveTimer = 1000; - } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit* /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!me->HasAura(SPELL_KNOCKBACK)) - DoCast(me, SPELL_KNOCKBACK, true); - - if (MoveTimer <= diff) - { - Position pos; - me->GetRandomNearPosition(pos, 10); - me->GetMotionMaster()->MovePoint(0, pos); - MoveTimer = urand(5000,8000); - } else MoveTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_dorothee(Creature* pCreature) -{ - return new boss_dorotheeAI(pCreature); -} - -CreatureAI* GetAI_boss_strawman(Creature* pCreature) -{ - return new boss_strawmanAI(pCreature); -} - -CreatureAI* GetAI_boss_tinhead(Creature* pCreature) -{ - return new boss_tinheadAI(pCreature); -} - -CreatureAI* GetAI_boss_roar(Creature* pCreature) -{ - return new boss_roarAI(pCreature); -} - -CreatureAI* GetAI_boss_crone(Creature* pCreature) -{ - return new boss_croneAI(pCreature); -} - -CreatureAI* GetAI_mob_tito(Creature* pCreature) -{ - return new mob_titoAI(pCreature); -} - -CreatureAI* GetAI_mob_cyclone(Creature* pCreature) -{ - return new mob_cycloneAI(pCreature); -} - -/**************************************/ -/**** Opera Red Riding Hood Event ****/ -/************************************/ - -/**** Yells for the Wolf ****/ -#define SAY_WOLF_AGGRO -1532043 -#define SAY_WOLF_SLAY -1532044 -#define SAY_WOLF_HOOD -1532045 -#define SOUND_WOLF_DEATH 9275 //Only sound on death, no text. - -/**** Spells For The Wolf ****/ -#define SPELL_LITTLE_RED_RIDING_HOOD 30768 -#define SPELL_TERRIFYING_HOWL 30752 -#define SPELL_WIDE_SWIPE 30761 - -#define GOSSIP_GRANDMA "What phat lewtz you have grandmother?" - -/**** The Wolf's Entry ****/ -#define CREATURE_BIG_BAD_WOLF 17521 - -bool GossipHello_npc_grandmother(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GRANDMA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(8990, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_grandmother(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - if (Creature* pBigBadWolf = pCreature->SummonCreature(CREATURE_BIG_BAD_WOLF, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) - pBigBadWolf->AI()->AttackStart(pPlayer); - - pCreature->ForcedDespawn(); - } - - return true; -} - -struct boss_bigbadwolfAI : public ScriptedAI -{ - boss_bigbadwolfAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ChaseTimer; - uint32 FearTimer; - uint32 SwipeTimer; - - uint64 HoodGUID; - float TempThreat; - - bool IsChasing; - - void Reset() - { - ChaseTimer = 30000; - FearTimer = 25000 + rand()%10000; - SwipeTimer = 5000; - - HoodGUID = 0; - TempThreat = 0; - - IsChasing = false; - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_WOLF_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void JustDied(Unit* /*killer*/) - { - DoPlaySoundToSet(me, SOUND_WOLF_DEATH); - - if (pInstance) - { - pInstance->SetData(TYPE_OPERA, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - - if (ChaseTimer <= diff) - { - if (!IsChasing) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(SAY_WOLF_HOOD, me); - DoCast(pTarget, SPELL_LITTLE_RED_RIDING_HOOD, true); - TempThreat = DoGetThreat(pTarget); - if (TempThreat) - DoModifyThreatPercent(pTarget, -100); - HoodGUID = pTarget->GetGUID(); - me->AddThreat(pTarget, 1000000.0f); - ChaseTimer = 20000; - IsChasing = true; - } - } - else - { - IsChasing = false; - - if (Unit *pTarget = Unit::GetUnit((*me), HoodGUID)) - { - HoodGUID = 0; - if (DoGetThreat(pTarget)) - DoModifyThreatPercent(pTarget, -100); - me->AddThreat(pTarget, TempThreat); - TempThreat = 0; - } - - ChaseTimer = 40000; - } - } else ChaseTimer -= diff; - - if (IsChasing) - return; - - if (FearTimer <= diff) - { - DoCast(me->getVictim(), SPELL_TERRIFYING_HOWL); - FearTimer = urand(25000,35000); - } else FearTimer -= diff; - - if (SwipeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WIDE_SWIPE); - SwipeTimer = urand(25000,30000); - } else SwipeTimer -= diff; - - } -}; - -CreatureAI* GetAI_boss_bigbadwolf(Creature* pCreature) -{ - return new boss_bigbadwolfAI(pCreature); -} - -/**********************************************/ -/******** Opera Romeo and Juliet Event *******/ -/********************************************/ - -/**** Speech *****/ -#define SAY_JULIANNE_AGGRO -1532046 -#define SAY_JULIANNE_ENTER -1532047 -#define SAY_JULIANNE_DEATH01 -1532048 -#define SAY_JULIANNE_DEATH02 -1532049 -#define SAY_JULIANNE_RESURRECT -1532050 -#define SAY_JULIANNE_SLAY -1532051 - -#define SAY_ROMULO_AGGRO -1532052 -#define SAY_ROMULO_DEATH -1532053 -#define SAY_ROMULO_ENTER -1532054 -#define SAY_ROMULO_RESURRECT -1532055 -#define SAY_ROMULO_SLAY -1532056 - -/***** Spells For Julianne *****/ -#define SPELL_BLINDING_PASSION 30890 -#define SPELL_DEVOTION 30887 -#define SPELL_ETERNAL_AFFECTION 30878 -#define SPELL_POWERFUL_ATTRACTION 30889 -#define SPELL_DRINK_POISON 30907 - -/***** Spells For Romulo ****/ -#define SPELL_BACKWARD_LUNGE 30815 -#define SPELL_DARING 30841 -#define SPELL_DEADLY_SWATHE 30817 -#define SPELL_POISON_THRUST 30822 - -/**** Other Misc. Spells ****/ -#define SPELL_UNDYING_LOVE 30951 -#define SPELL_RES_VISUAL 24171 - -/*** Misc. Information ****/ -#define CREATURE_ROMULO 17533 -#define ROMULO_X -10900 -#define ROMULO_Y -1758 - -enum RAJPhase -{ - PHASE_JULIANNE = 0, - PHASE_ROMULO = 1, - PHASE_BOTH = 2, -}; - -void PretendToDie(Creature* pCreature) -{ - pCreature->InterruptNonMeleeSpells(true); - pCreature->RemoveAllAuras(); - pCreature->SetHealth(0); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->GetMotionMaster()->MovementExpired(false); - pCreature->GetMotionMaster()->MoveIdle(); - pCreature->SetStandState(UNIT_STAND_STATE_DEAD); -}; - -void Resurrect(Creature *pTarget) -{ - pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTarget->SetHealth(pTarget->GetMaxHealth()); - pTarget->SetStandState(UNIT_STAND_STATE_STAND); - pTarget->CastSpell(pTarget, SPELL_RES_VISUAL, true); - if (pTarget->getVictim()) - { - pTarget->GetMotionMaster()->MoveChase(pTarget->getVictim()); - pTarget->AI()->AttackStart(pTarget->getVictim()); - } - else - pTarget->GetMotionMaster()->Initialize(); -}; - -struct boss_julianneAI : public ScriptedAI -{ - boss_julianneAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EntryYellTimer = 1000; - AggroYellTimer = 10000; - IsFakingDeath = false; - } - - ScriptedInstance* pInstance; - - uint32 EntryYellTimer; - uint32 AggroYellTimer; - - uint64 RomuloGUID; - - uint32 Phase; - - uint32 BlindingPassionTimer; - uint32 DevotionTimer; - uint32 EternalAffectionTimer; - uint32 PowerfulAttractionTimer; - uint32 SummonRomuloTimer; - uint32 ResurrectTimer; - uint32 DrinkPoisonTimer; - uint32 ResurrectSelfTimer; - - bool IsFakingDeath; - bool SummonedRomulo; - bool RomuloDead; - - void Reset() - { - RomuloGUID = 0; - Phase = PHASE_JULIANNE; - - BlindingPassionTimer = 30000; - DevotionTimer = 15000; - EternalAffectionTimer = 25000; - PowerfulAttractionTimer = 5000; - SummonRomuloTimer = 10000; - DrinkPoisonTimer = 0; - ResurrectSelfTimer = 0; - - if (IsFakingDeath) - { - Resurrect(me); - IsFakingDeath = false; - } - - SummonedRomulo = false; - RomuloDead = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry *Spell) - { - if (Spell->Id == SPELL_DRINK_POISON) - { - DoScriptText(SAY_JULIANNE_DEATH01, me); - DrinkPoisonTimer = 2500; - } - } - - void DamageTaken(Unit* done_by, uint32 &damage); - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_JULIANNE_DEATH02, me); - - if (pInstance) - { - pInstance->SetData(TYPE_OPERA, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); - if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_JULIANNE_SLAY, me); - } - - void UpdateAI(const uint32 diff); -}; - -struct boss_romuloAI : public ScriptedAI -{ - boss_romuloAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EntryYellTimer = 8000; - AggroYellTimer = 15000; - } - - ScriptedInstance* pInstance; - - uint64 JulianneGUID; - uint32 Phase; - - uint32 EntryYellTimer; - uint32 AggroYellTimer; - uint32 BackwardLungeTimer; - uint32 DaringTimer; - uint32 DeadlySwatheTimer; - uint32 PoisonThrustTimer; - uint32 ResurrectTimer; - - bool IsFakingDeath; - bool JulianneDead; - - void Reset() - { - JulianneGUID = 0; - Phase = PHASE_ROMULO; - - BackwardLungeTimer = 15000; - DaringTimer = 20000; - DeadlySwatheTimer = 25000; - PoisonThrustTimer = 10000; - ResurrectTimer = 10000; - - IsFakingDeath = false; - JulianneDead = false; - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void DamageTaken(Unit* done_by, uint32 &damage); - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_ROMULO_AGGRO, me); - if (JulianneGUID) - { - Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); - if (Julianne && Julianne->getVictim()) - { - me->AddThreat(Julianne->getVictim(), 1.0f); - AttackStart(Julianne->getVictim()); - } - } - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_ROMULO_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_OPERA, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_ROMULO_SLAY, me); - } - - void UpdateAI(const uint32 diff); -}; - -void boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32 &damage) -{ - if (damage < me->GetHealth()) - return; - - //anything below only used if incoming damage will kill - - if (Phase == PHASE_JULIANNE) - { - damage = 0; - - //this means already drinking, so return - if (IsFakingDeath) - return; - - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_DRINK_POISON); - - IsFakingDeath = true; - //IS THIS USEFULL? Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); - return; - } - - if (Phase == PHASE_ROMULO) - { - error_log("TSCR: boss_julianneAI: cannot take damage in PHASE_ROMULO, why was i here?"); - damage = 0; - return; - } - - if (Phase == PHASE_BOTH) - { - //if this is true then we have to kill romulo too - if (RomuloDead) - { - if (Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID))) - { - Romulo->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Romulo->GetMotionMaster()->Clear(); - Romulo->setDeathState(JUST_DIED); - Romulo->CombatStop(true); - Romulo->DeleteThreatList(); - Romulo->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - - return; - } - - //if not already returned, then romulo is alive and we can pretend die - if (Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID))) - { - PretendToDie(me); - IsFakingDeath = true; - CAST_AI(boss_romuloAI, Romulo->AI())->ResurrectTimer = 10000; - CAST_AI(boss_romuloAI, Romulo->AI())->JulianneDead = true; - damage = 0; - return; - } - } - error_log("TSCR: boss_julianneAI: DamageTaken reach end of code, that should not happen."); -} - -void boss_romuloAI::DamageTaken(Unit* /*done_by*/, uint32 &damage) -{ - if (damage < me->GetHealth()) - return; - - //anything below only used if incoming damage will kill - - if (Phase == PHASE_ROMULO) - { - DoScriptText(SAY_ROMULO_DEATH, me); - PretendToDie(me); - IsFakingDeath = true; - Phase = PHASE_BOTH; - - if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) - { - CAST_AI(boss_julianneAI, Julianne->AI())->RomuloDead = true; - CAST_AI(boss_julianneAI, Julianne->AI())->ResurrectSelfTimer = 10000; - } - - damage = 0; - return; - } - - if (Phase == PHASE_BOTH) - { - if (JulianneDead) - { - if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) - { - Julianne->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Julianne->GetMotionMaster()->Clear(); - Julianne->setDeathState(JUST_DIED); - Julianne->CombatStop(true); - Julianne->DeleteThreatList(); - Julianne->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - return; - } - - if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) - { - PretendToDie(me); - IsFakingDeath = true; - CAST_AI(boss_julianneAI, Julianne->AI())->ResurrectTimer = 10000; - CAST_AI(boss_julianneAI, Julianne->AI())->RomuloDead = true; - damage = 0; - return; - } - } - - error_log("TSCR: boss_romuloAI: DamageTaken reach end of code, that should not happen."); -} - -void boss_julianneAI::UpdateAI(const uint32 diff) -{ - if (EntryYellTimer) - { - if (EntryYellTimer <= diff) - { - DoScriptText(SAY_JULIANNE_ENTER, me); - EntryYellTimer = 0; - } else EntryYellTimer -= diff; - } - - if (AggroYellTimer) - { - if (AggroYellTimer <= diff) - { - DoScriptText(SAY_JULIANNE_AGGRO, me); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->setFaction(16); - AggroYellTimer = 0; - } else AggroYellTimer -= diff; - } - - if (DrinkPoisonTimer) - { - //will do this 2secs after spell hit. this is time to display visual as expected - if (DrinkPoisonTimer <= diff) - { - PretendToDie(me); - Phase = PHASE_ROMULO; - SummonRomuloTimer = 10000; - DrinkPoisonTimer = 0; - } else DrinkPoisonTimer -= diff; - } - - if (Phase == PHASE_ROMULO && !SummonedRomulo) - { - if (SummonRomuloTimer <= diff) - { - if (Creature* pRomulo = me->SummonCreature(CREATURE_ROMULO, ROMULO_X, ROMULO_Y, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) - { - RomuloGUID = pRomulo->GetGUID(); - CAST_AI(boss_romuloAI, pRomulo->AI())->JulianneGUID = me->GetGUID(); - CAST_AI(boss_romuloAI, pRomulo->AI())->Phase = PHASE_ROMULO; - DoZoneInCombat(pRomulo); - - pRomulo->setFaction(16); - } - SummonedRomulo = true; - } else SummonRomuloTimer -= diff; - } - - if (ResurrectSelfTimer) - { - if (ResurrectSelfTimer <= diff) - { - Resurrect(me); - Phase = PHASE_BOTH; - IsFakingDeath = false; - - if (me->getVictim()) - AttackStart(me->getVictim()); - - ResurrectSelfTimer = 0; - ResurrectTimer = 1000; - } else ResurrectSelfTimer -= diff; - } - - if (!UpdateVictim() || IsFakingDeath) - return; - - if (RomuloDead) - { - if (ResurrectTimer <= diff) - { - Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID)); - if (Romulo && CAST_AI(boss_romuloAI, Romulo->AI())->IsFakingDeath) - { - DoScriptText(SAY_JULIANNE_RESURRECT, me); - Resurrect(Romulo); - CAST_AI(boss_romuloAI, Romulo->AI())->IsFakingDeath = false; - RomuloDead = false; - ResurrectTimer = 10000; - } - } else ResurrectTimer -= diff; - } - - if (BlindingPassionTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BLINDING_PASSION); - BlindingPassionTimer = urand(30000,45000); - } else BlindingPassionTimer -= diff; - - if (DevotionTimer <= diff) - { - DoCast(me, SPELL_DEVOTION); - DevotionTimer = urand(15000,45000); - } else DevotionTimer -= diff; - - if (PowerfulAttractionTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_POWERFUL_ATTRACTION); - PowerfulAttractionTimer = urand(5000,30000); - } else PowerfulAttractionTimer -= diff; - - if (EternalAffectionTimer <= diff) - { - if (urand(0,1) && SummonedRomulo) - { - Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID)); - if (Romulo && Romulo->isAlive() && !RomuloDead) - DoCast(Romulo, SPELL_ETERNAL_AFFECTION); - } else DoCast(me, SPELL_ETERNAL_AFFECTION); - - EternalAffectionTimer = urand(45000,60000); - } else EternalAffectionTimer -= diff; - - DoMeleeAttackIfReady(); -} - -void boss_romuloAI::UpdateAI(const uint32 diff) -{ - if (!UpdateVictim() || IsFakingDeath) - return; - - if (JulianneDead) - { - if (ResurrectTimer <= diff) - { - Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); - if (Julianne && CAST_AI(boss_julianneAI, Julianne->AI())->IsFakingDeath) - { - DoScriptText(SAY_ROMULO_RESURRECT, me); - Resurrect(Julianne); - CAST_AI(boss_julianneAI, Julianne->AI())->IsFakingDeath = false; - JulianneDead = false; - ResurrectTimer = 10000; - } - } else ResurrectTimer -= diff; - } - - if (BackwardLungeTimer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - if (pTarget && !me->HasInArc(M_PI, pTarget)) - { - DoCast(pTarget, SPELL_BACKWARD_LUNGE); - BackwardLungeTimer = urand(15000,30000); - } - } else BackwardLungeTimer -= diff; - - if (DaringTimer <= diff) - { - DoCast(me, SPELL_DARING); - DaringTimer = urand(20000,40000); - } else DaringTimer -= diff; - - if (DeadlySwatheTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_DEADLY_SWATHE); - DeadlySwatheTimer = urand(15000,25000); - } else DeadlySwatheTimer -= diff; - - if (PoisonThrustTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_THRUST); - PoisonThrustTimer = urand(10000,20000); - } else PoisonThrustTimer -= diff; - - DoMeleeAttackIfReady(); -} - -CreatureAI* GetAI_boss_julianne(Creature* pCreature) -{ - return new boss_julianneAI(pCreature); -} - -CreatureAI* GetAI_boss_romulo(Creature* pCreature) -{ - return new boss_romuloAI(pCreature); -} - -void AddSC_bosses_opera() -{ - Script* newscript; - - // Oz - newscript = new Script; - newscript->GetAI = &GetAI_boss_dorothee; - newscript->Name = "boss_dorothee"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_strawman; - newscript->Name = "boss_strawman"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_tinhead; - newscript->Name = "boss_tinhead"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_roar; - newscript->Name = "boss_roar"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_crone; - newscript->Name = "boss_crone"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_tito; - newscript->Name = "mob_tito"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_cyclone; - newscript->Name = "mob_cyclone"; - newscript->RegisterSelf(); - - // Hood - newscript = new Script; - newscript->pGossipHello = &GossipHello_npc_grandmother; - newscript->pGossipSelect = &GossipSelect_npc_grandmother; - newscript->Name = "npc_grandmother"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_bigbadwolf; - newscript->Name = "boss_bigbadwolf"; - newscript->RegisterSelf(); - - // Romeo And Juliet - newscript = new Script; - newscript->GetAI = &GetAI_boss_julianne; - newscript->Name = "boss_julianne"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_romulo; - newscript->Name = "boss_romulo"; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp b/src/server/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp deleted file mode 100644 index 59c1236bcdc..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Karazhan -SD%Complete: 70 -SDComment: Instance Script for Karazhan to help in various encounters. TODO: GameObject visibility for Opera event. -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define MAX_ENCOUNTER 12 - -/* -0 - Attumen + Midnight (optional) -1 - Moroes -2 - Maiden of Virtue (optional) -3 - Hyakiss the Lurker / Rokad the Ravager / Shadikith the Glider -4 - Opera Event -5 - Curator -6 - Shade of Aran (optional) -7 - Terestian Illhoof (optional) -8 - Netherspite (optional) -9 - Chess Event -10 - Prince Malchezzar -11 - Nightbane -*/ - -struct instance_karazhan : public ScriptedInstance -{ - instance_karazhan(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string strSaveData; - - uint32 m_uiOperaEvent; - uint32 m_uiOzDeathCount; - - uint64 m_uiCurtainGUID; - uint64 m_uiStageDoorLeftGUID; - uint64 m_uiStageDoorRightGUID; - uint64 m_uiKilrekGUID; - uint64 m_uiTerestianGUID; - uint64 m_uiMoroesGUID; - uint64 m_uiLibraryDoor; // Door at Shade of Aran - uint64 m_uiMassiveDoor; // Door at Netherspite - uint64 m_uiSideEntranceDoor; // Side Entrance - uint64 m_uiGamesmansDoor; // Door before Chess - uint64 m_uiGamesmansExitDoor; // Door after Chess - uint64 m_uiNetherspaceDoor; // Door at Malchezaar - uint64 MastersTerraceDoor[2]; - uint64 ImageGUID; - uint64 DustCoveredChest; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - // 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered. - m_uiOperaEvent = urand(1,3); - m_uiOzDeathCount = 0; - - m_uiCurtainGUID = 0; - m_uiStageDoorLeftGUID = 0; - m_uiStageDoorRightGUID = 0; - - m_uiKilrekGUID = 0; - m_uiTerestianGUID = 0; - m_uiMoroesGUID = 0; - - m_uiLibraryDoor = 0; - m_uiMassiveDoor = 0; - m_uiSideEntranceDoor = 0; - m_uiGamesmansDoor = 0; - m_uiGamesmansExitDoor = 0; - m_uiNetherspaceDoor = 0; - MastersTerraceDoor[0]= 0; - MastersTerraceDoor[1]= 0; - ImageGUID = 0; - DustCoveredChest = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case 17229: m_uiKilrekGUID = pCreature->GetGUID(); break; - case 15688: m_uiTerestianGUID = pCreature->GetGUID(); break; - case 15687: m_uiMoroesGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 uiData) - { - switch (type) - { - case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break; - case TYPE_MOROES: - if (m_auiEncounter[1] == DONE) - break; - m_auiEncounter[1] = uiData; - break; - case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break; - case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break; - case TYPE_OPERA: m_auiEncounter[4] = uiData; break; - case TYPE_CURATOR: m_auiEncounter[5] = uiData; break; - case TYPE_ARAN: m_auiEncounter[6] = uiData; break; - case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break; - case TYPE_NETHERSPITE: m_auiEncounter[8] = uiData; break; - case TYPE_CHESS: - if (uiData == DONE) - DoRespawnGameObject(DustCoveredChest,DAY); - m_auiEncounter[9] = uiData; - break; - case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break; - case TYPE_NIGHTBANE: - if (m_auiEncounter[11] != DONE) - m_auiEncounter[11] = uiData; - break; - case DATA_OPERA_OZ_DEATHCOUNT: - if (uiData == SPECIAL) - ++m_uiOzDeathCount; - else if (uiData == IN_PROGRESS) - m_uiOzDeathCount = 0; - break; - } - - if (uiData == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " - << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11]; - - strSaveData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - void SetData64(uint32 identifier, uint64 data) - { - switch(identifier) - { - case DATA_IMAGE_OF_MEDIVH: ImageGUID = data; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 183932: m_uiCurtainGUID = pGo->GetGUID(); break; - case 184278: - m_uiStageDoorLeftGUID = pGo->GetGUID(); - if (m_auiEncounter[4] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case 184279: - m_uiStageDoorRightGUID = pGo->GetGUID(); - if (m_auiEncounter[4] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case 184517: m_uiLibraryDoor = pGo->GetGUID(); break; - case 185521: m_uiMassiveDoor = pGo->GetGUID(); break; - case 184276: m_uiGamesmansDoor = pGo->GetGUID(); break; - case 184277: m_uiGamesmansExitDoor = pGo->GetGUID(); break; - case 185134: m_uiNetherspaceDoor = pGo->GetGUID(); break; - case 184274: MastersTerraceDoor[0] = pGo->GetGUID(); break; - case 184280: MastersTerraceDoor[1] = pGo->GetGUID(); break; - case 184275: - m_uiSideEntranceDoor = pGo->GetGUID(); - if (m_auiEncounter[4] == DONE) - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - else - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - break; - case 185119: DustCoveredChest = pGo->GetGUID(); break; - } - - switch(m_uiOperaEvent) - { - //TODO: Set Object visibilities for Opera based on performance - case EVENT_OZ: - break; - - case EVENT_HOOD: - break; - - case EVENT_RAJ: - break; - } - } - - std::string GetSaveData() - { - return strSaveData; - } - - uint32 GetData(uint32 uiData) - { - switch (uiData) - { - case TYPE_ATTUMEN: return m_auiEncounter[0]; - case TYPE_MOROES: return m_auiEncounter[1]; - case TYPE_MAIDEN: return m_auiEncounter[2]; - case TYPE_OPTIONAL_BOSS: return m_auiEncounter[3]; - case TYPE_OPERA: return m_auiEncounter[4]; - case TYPE_CURATOR: return m_auiEncounter[5]; - case TYPE_ARAN: return m_auiEncounter[6]; - case TYPE_TERESTIAN: return m_auiEncounter[7]; - case TYPE_NETHERSPITE: return m_auiEncounter[8]; - case TYPE_CHESS: return m_auiEncounter[9]; - case TYPE_MALCHEZZAR: return m_auiEncounter[10]; - case TYPE_NIGHTBANE: return m_auiEncounter[11]; - case DATA_OPERA_PERFORMANCE: return m_uiOperaEvent; - case DATA_OPERA_OZ_DEATHCOUNT: return m_uiOzDeathCount; - case DATA_IMAGE_OF_MEDIVH: return ImageGUID; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch (uiData) - { - case DATA_KILREK: return m_uiKilrekGUID; - case DATA_TERESTIAN: return m_uiTerestianGUID; - case DATA_MOROES: return m_uiMoroesGUID; - case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID; - case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID; - case DATA_GO_CURTAINS: return m_uiCurtainGUID; - case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor; - case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor; - case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor; - case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor; - case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor; - case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor; - case DATA_MASTERS_TERRACE_DOOR_1: return MastersTerraceDoor[0]; - case DATA_MASTERS_TERRACE_DOOR_2: return MastersTerraceDoor[1]; - } - - return 0; - } - - void Load(const char* chrIn) - { - if (!chrIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(chrIn); - std::istringstream loadStream(chrIn); - - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] - >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_karazhan(Map* pMap) -{ - return new instance_karazhan(pMap); -} - -void AddSC_instance_karazhan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_karazhan"; - newscript->GetInstanceData = &GetInstanceData_instance_karazhan; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/karazhan.cpp b/src/server/scripts/eastern_kingdoms/karazhan/karazhan.cpp deleted file mode 100644 index 5186a794b0d..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/karazhan.cpp +++ /dev/null @@ -1,646 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Karazhan -SD%Complete: 100 -SDComment: Support for Barnes (Opera controller) and Berthold (Doorman), Support for Quest 9645. -SDCategory: Karazhan -EndScriptData */ - -/* ContentData -npc_barnes -npc_berthold -npc_image_of_medivh -EndContentData */ - -#include "ScriptedPch.h" -#include "karazhan.h" -#include "ScriptedEscortAI.h" - -/*###### -# npc_barnesAI -######*/ - -#define GOSSIP_READY "I'm not an actor." - -#define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!" -#define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?" -#define OZ_GOSSIP1 "I'm not an actor." -#define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!" -#define OZ_GOSSIP2 "Ok, I'll give it a try, then." - -#define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?" -#define RAJ_GOSSIP1 "I've never been more ready." - -#define OZ_GM_GOSSIP1 "[GM] Change event to EVENT_OZ" -#define OZ_GM_GOSSIP2 "[GM] Change event to EVENT_HOOD" -#define OZ_GM_GOSSIP3 "[GM] Change event to EVENT_RAJ" - -struct Dialogue -{ - int32 textid; - uint32 timer; -}; - -static Dialogue OzDialogue[]= -{ - {-1532103, 6000}, - {-1532104, 18000}, - {-1532105, 9000}, - {-1532106, 15000} -}; - -static Dialogue HoodDialogue[]= -{ - {-1532107, 6000}, - {-1532108, 10000}, - {-1532109, 14000}, - {-1532110, 15000} -}; - -static Dialogue RAJDialogue[]= -{ - {-1532111, 5000}, - {-1532112, 7000}, - {-1532113, 14000}, - {-1532114, 14000} -}; - -// Entries and spawn locations for creatures in Oz event -float Spawns[6][2]= -{ - {17535, -10896}, // Dorothee - {17546, -10891}, // Roar - {17547, -10884}, // Tinhead - {17543, -10902}, // Strawman - {17603, -10892}, // Grandmother - {17534, -10900}, // Julianne -}; - -#define CREATURE_SPOTLIGHT 19525 - -#define SPELL_SPOTLIGHT 25824 -#define SPELL_TUXEDO 32616 - -#define SPAWN_Z 90.5 -#define SPAWN_Y -1758 -#define SPAWN_O 4.738 - -struct npc_barnesAI : public npc_escortAI -{ - npc_barnesAI(Creature* c) : npc_escortAI(c) - { - RaidWiped = false; - m_uiEventId = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 m_uiSpotlightGUID; - - uint32 TalkCount; - uint32 TalkTimer; - uint32 WipeTimer; - uint32 m_uiEventId; - - bool PerformanceReady; - bool RaidWiped; - - void Reset() - { - m_uiSpotlightGUID = 0; - - TalkCount = 0; - TalkTimer = 2000; - WipeTimer = 5000; - - PerformanceReady = false; - - if (pInstance) - m_uiEventId = pInstance->GetData(DATA_OPERA_PERFORMANCE); - } - - void StartEvent() - { - if (!pInstance) - return; - - pInstance->SetData(TYPE_OPERA, IN_PROGRESS); - - //resets count for this event, in case earlier failed - if (m_uiEventId == EVENT_OZ) - pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS); - - Start(false, false); - } - - void EnterCombat(Unit* /*who*/) {} - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch(i) - { - case 0: - DoCast(me, SPELL_TUXEDO, false); - pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT)); - break; - case 4: - TalkCount = 0; - SetEscortPaused(true); - - if (Creature* pSpotlight = me->SummonCreature(CREATURE_SPOTLIGHT, - me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f, - TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000)) - { - pSpotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pSpotlight->CastSpell(pSpotlight, SPELL_SPOTLIGHT, false); - m_uiSpotlightGUID = pSpotlight->GetGUID(); - } - break; - case 8: - pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT)); - PerformanceReady = true; - break; - case 9: - PrepareEncounter(); - pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_CURTAINS)); - break; - } - } - - void Talk(uint32 count) - { - int32 text = 0; - - switch(m_uiEventId) - { - case EVENT_OZ: - if (OzDialogue[count].textid) - text = OzDialogue[count].textid; - if (OzDialogue[count].timer) - TalkTimer = OzDialogue[count].timer; - break; - - case EVENT_HOOD: - if (HoodDialogue[count].textid) - text = HoodDialogue[count].textid; - if (HoodDialogue[count].timer) - TalkTimer = HoodDialogue[count].timer; - break; - - case EVENT_RAJ: - if (RAJDialogue[count].textid) - text = RAJDialogue[count].textid; - if (RAJDialogue[count].timer) - TalkTimer = RAJDialogue[count].timer; - break; - } - - if (text) - DoScriptText(text, me); - } - - void PrepareEncounter() - { - debug_log("TSCR: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId); - uint8 index = 0; - uint8 count = 0; - - switch(m_uiEventId) - { - case EVENT_OZ: - index = 0; - count = 4; - break; - case EVENT_HOOD: - index = 4; - count = index+1; - break; - case EVENT_RAJ: - index = 5; - count = index+1; - break; - } - - for (; index < count; ++index) - { - uint32 entry = ((uint32)Spawns[index][0]); - float PosX = Spawns[index][1]; - - if (Creature* pCreature = me->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) - { - // In case database has bad flags - pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - - RaidWiped = false; - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (HasEscortState(STATE_ESCORT_PAUSED)) - { - if (TalkTimer <= diff) - { - if (TalkCount > 3) - { - if (Creature* pSpotlight = Unit::GetCreature(*me, m_uiSpotlightGUID)) - pSpotlight->ForcedDespawn(); - - SetEscortPaused(false); - return; - } - - Talk(TalkCount); - ++TalkCount; - } else TalkTimer -= diff; - } - - if (PerformanceReady) - { - if (!RaidWiped) - { - if (WipeTimer <= diff) - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) - return; - - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (PlayerList.isEmpty()) - return; - - RaidWiped = true; - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive() && !i->getSource()->isGameMaster()) - { - RaidWiped = false; - break; - } - } - - if (RaidWiped) - { - RaidWiped = true; - EnterEvadeMode(); - return; - } - - WipeTimer = 15000; - } else WipeTimer -= diff; - } - - } - } -}; - -CreatureAI* GetAI_npc_barnesAI(Creature* pCreature) -{ - return new npc_barnesAI(pCreature); -} - -bool GossipHello_npc_barnes(Player* pPlayer, Creature* pCreature) -{ - if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) - { - // Check for death of Moroes and if opera event is not done already - if (pInstance->GetData(TYPE_MOROES) == DONE && pInstance->GetData(TYPE_OPERA) != DONE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (pPlayer->isGameMaster()) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - } - - if (npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI,pCreature->AI())) - { - if (!pBarnesAI->RaidWiped) - pPlayer->SEND_GOSSIP_MENU(8970, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(8975, pCreature->GetGUID()); - - return true; - } - } - } - - pPlayer->SEND_GOSSIP_MENU(8978, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_barnes(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI, pCreature->AI()); - - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(8971, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - pBarnesAI->StartEvent(); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - pBarnesAI->m_uiEventId = EVENT_OZ; - outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_OZ",pPlayer->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pBarnesAI->m_uiEventId = EVENT_HOOD; - outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_HOOD",pPlayer->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->CLOSE_GOSSIP_MENU(); - pBarnesAI->m_uiEventId = EVENT_RAJ; - outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_RAJ",pPlayer->GetGUID()); - break; - } - - return true; -} - -/*### -# npc_berthold -####*/ - -enum eBerthold -{ - SPELL_TELEPORT = 39567 -}; - -#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library" - -bool GossipHello_npc_berthold(Player* pPlayer, Creature* pCreature) -{ - if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) - { - // Check if Shade of Aran event is done - if (pInstance->GetData(TYPE_ARAN) == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_berthold(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, true); - - pPlayer->CLOSE_GOSSIP_MENU(); - return true; -} - -/*### -# npc_image_of_medivh -####*/ - -#define SAY_DIALOG_MEDIVH_1 "You've got my attention, dragon. You'll find I'm not as easily scared as the villagers below." -#define SAY_DIALOG_ARCANAGOS_2 "Your dabbling in the arcane has gone too far, Medivh. You've attracted the attention of powers beyond your understanding. You must leave Karazhan at once!" -#define SAY_DIALOG_MEDIVH_3 "You dare challenge me at my own dwelling? Your arrogance is astounding, even for a dragon!" -#define SAY_DIALOG_ARCANAGOS_4 "A dark power seeks to use you, Medivh! If you stay, dire days will follow. You must hurry, we don't have much time!" -#define SAY_DIALOG_MEDIVH_5 "I do not know what you speak of, dragon... but I will not be bullied by this display of insolence. I'll leave Karazhan when it suits me!" -#define SAY_DIALOG_ARCANAGOS_6 "You leave me no alternative. I will stop you by force if you won't listen to reason!" -#define EMOTE_DIALOG_MEDIVH_7 "begins to cast a spell of great power, weaving his own essence into the magic." -#define SAY_DIALOG_ARCANAGOS_8 "What have you done, wizard? This cannot be! I'm burning from... within!" -#define SAY_DIALOG_MEDIVH_9 "He should not have angered me. I must go... recover my strength now..." - -#define MOB_ARCANAGOS 17652 -#define SPELL_FIRE_BALL 30967 -#define SPELL_UBER_FIREBALL 30971 -#define SPELL_CONFLAGRATION_BLAST 30977 -#define SPELL_MANA_SHIELD 31635 - -static float MedivPos[4] = {-11161.49,-1902.24,91.48,1.94}; -static float ArcanagosPos[4] = {-11169.75,-1881.48,95.39,4.83}; - -struct npc_image_of_medivhAI : public ScriptedAI -{ - npc_image_of_medivhAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint64 ArcanagosGUID; - - uint32 YellTimer; - uint32 Step; - uint32 FireMedivhTimer; - uint32 FireArcanagosTimer; - - bool EventStarted; - - void Reset() - { - ArcanagosGUID = 0; - - if (pInstance && pInstance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0) - { - pInstance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID()); - (*me).GetMotionMaster()->MovePoint(1,MedivPos[0],MedivPos[1],MedivPos[2]); - Step = 0; - }else - { - me->DealDamage(me,me->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - } - } - void EnterCombat(Unit* /*who*/) {} - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - if (id == 1) - { - StartEvent(); - me->SetOrientation(MedivPos[3]); - me->SetOrientation(MedivPos[3]); - } - } - - void StartEvent() - { - Step = 1; - EventStarted = true; - Creature* Arcanagos = me->SummonCreature(MOB_ARCANAGOS,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - if (!Arcanagos) - return; - ArcanagosGUID = Arcanagos->GetGUID(); - Arcanagos->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - (*Arcanagos).GetMotionMaster()->MovePoint(0,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2]); - Arcanagos->SetOrientation(ArcanagosPos[3]); - me->SetOrientation(MedivPos[3]); - YellTimer = 10000; - } - - uint32 NextStep(uint32 Step) - { - Unit* arca = Unit::GetUnit((*me),ArcanagosGUID); - Map* pMap = me->GetMap(); - switch(Step) - { - case 0: return 9999999; - case 1: - me->MonsterYell(SAY_DIALOG_MEDIVH_1,LANG_UNIVERSAL,NULL); - return 10000; - case 2: - if (arca) - CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_2,LANG_UNIVERSAL,NULL); - return 20000; - case 3: - me->MonsterYell(SAY_DIALOG_MEDIVH_3,LANG_UNIVERSAL,NULL); - return 10000; - case 4: - if (arca) - CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, NULL); - return 20000; - case 5: - me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, NULL); - return 20000; - case 6: - if (arca) - CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, NULL); - return 10000; - case 7: - FireArcanagosTimer = 500; - return 5000; - case 8: - FireMedivhTimer = 500; - DoCast(me, SPELL_MANA_SHIELD); - return 10000; - case 9: - me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false); - return 10000; - case 10: - if (arca) - DoCast(arca, SPELL_CONFLAGRATION_BLAST, false); - return 1000; - case 11: - if (arca) - CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL); - return 5000; - case 12: - arca->GetMotionMaster()->MovePoint(0, -11010.82,-1761.18, 156.47); - arca->setActive(true); - arca->InterruptNonMeleeSpells(true); - arca->SetSpeed(MOVE_FLIGHT, 2.0f); - return 10000; - case 13: - me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL); - return 10000; - case 14: - me->SetVisibility(VISIBILITY_OFF); - me->ClearInCombat(); - - if (pMap->IsDungeon()) - { - InstanceMap::PlayerList const &PlayerList = pMap->GetPlayers(); - for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive()) - { - if (i->getSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE) - i->getSource()->CompleteQuest(9645); - } - } - } - return 50000; - case 15: - arca->DealDamage(arca,arca->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return 5000; - default : return 9999999; - } - - } - - void UpdateAI(const uint32 diff) - { - - if (YellTimer <= diff) - { - if (EventStarted) - YellTimer = NextStep(Step++); - } else YellTimer -= diff; - - if (Step >= 7 && Step <= 12) - { - Unit* arca = Unit::GetUnit((*me),ArcanagosGUID); - - if (FireArcanagosTimer <= diff) - { - if (arca) - arca->CastSpell(me, SPELL_FIRE_BALL, false); - FireArcanagosTimer = 6000; - } else FireArcanagosTimer -= diff; - - if (FireMedivhTimer <= diff) - { - if (arca) - DoCast(arca, SPELL_FIRE_BALL); - FireMedivhTimer = 5000; - } else FireMedivhTimer -= diff; - } - } -}; - -CreatureAI* GetAI_npc_image_of_medivh(Creature* pCreature) -{ - return new npc_image_of_medivhAI(pCreature); -} - -void AddSC_karazhan() -{ - Script* newscript; - - newscript = new Script; - newscript->GetAI = &GetAI_npc_barnesAI; - newscript->Name = "npc_barnes"; - newscript->pGossipHello = &GossipHello_npc_barnes; - newscript->pGossipSelect = &GossipSelect_npc_barnes; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_berthold"; - newscript->pGossipHello = &GossipHello_npc_berthold; - newscript->pGossipSelect = &GossipSelect_npc_berthold; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_image_of_medivh"; - newscript->GetAI = &GetAI_npc_image_of_medivh; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/karazhan/karazhan.h b/src/server/scripts/eastern_kingdoms/karazhan/karazhan.h deleted file mode 100644 index 56a6b106332..00000000000 --- a/src/server/scripts/eastern_kingdoms/karazhan/karazhan.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_KARAZHAN_H -#define DEF_KARAZHAN_H - -enum eEnums -{ - TYPE_ATTUMEN = 1, - TYPE_MOROES = 2, - TYPE_MAIDEN = 3, - TYPE_OPTIONAL_BOSS = 4, - TYPE_OPERA = 5, - TYPE_CURATOR = 6, - TYPE_ARAN = 7, - TYPE_TERESTIAN = 8, - TYPE_NETHERSPITE = 9, - TYPE_CHESS = 10, - TYPE_MALCHEZZAR = 11, - TYPE_NIGHTBANE = 12, - - DATA_OPERA_PERFORMANCE = 13, - DATA_OPERA_OZ_DEATHCOUNT = 14, - - DATA_KILREK = 15, - DATA_TERESTIAN = 16, - DATA_MOROES = 17, - DATA_GO_CURTAINS = 18, - DATA_GO_STAGEDOORLEFT = 19, - DATA_GO_STAGEDOORRIGHT = 20, - DATA_GO_LIBRARY_DOOR = 21, - DATA_GO_MASSIVE_DOOR = 22, - DATA_GO_NETHER_DOOR = 23, - DATA_GO_GAME_DOOR = 24, - DATA_GO_GAME_EXIT_DOOR = 25, - - DATA_IMAGE_OF_MEDIVH = 26, - DATA_MASTERS_TERRACE_DOOR_1 = 27, - DATA_MASTERS_TERRACE_DOOR_2 = 28, - DATA_GO_SIDE_ENTRANCE_DOOR = 29 -}; - -enum OperaEvents -{ - EVENT_OZ = 1, - EVENT_HOOD = 2, - EVENT_RAJ = 3 -}; - -#define ERROR_INST_DATA(a) error_log("TSCR: Instance Data for Karazhan not set properly. Encounter for Creature Entry %u may not work properly.", a->GetEntry()); -#endif - diff --git a/src/server/scripts/eastern_kingdoms/loch_modan.cpp b/src/server/scripts/eastern_kingdoms/loch_modan.cpp deleted file mode 100644 index e99a13fb675..00000000000 --- a/src/server/scripts/eastern_kingdoms/loch_modan.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Loch_Modan -SD%Complete: 100 -SDComment: Quest support: 3181 -SDCategory: Loch Modan -EndScriptData */ - -/* ContentData -npc_mountaineer_pebblebitty -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_mountaineer_pebblebitty -######*/ - -#define GOSSIP_MP "Open the gate please, i need to get to Searing Gorge" - -#define GOSSIP_MP1 "But i need to get there, now open the gate!" -#define GOSSIP_MP2 "Ok, so what is this other way?" -#define GOSSIP_MP3 "Doesn't matter, i'm invulnerable." -#define GOSSIP_MP4 "Yes..." -#define GOSSIP_MP5 "Ok, i'll try to remember that." -#define GOSSIP_MP6 "A key? Ok!" - -bool GossipHello_npc_mountaineer_pebblebitty(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (!pPlayer->GetQuestRewardStatus(3181) == 1) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_mountaineer_pebblebitty(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(1833, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(1834, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(1835, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - pPlayer->SEND_GOSSIP_MENU(1836, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - pPlayer->SEND_GOSSIP_MENU(1837, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - pPlayer->SEND_GOSSIP_MENU(1838, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - return true; -} - -void AddSC_loch_modan() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_mountaineer_pebblebitty"; - newscript->pGossipHello = &GossipHello_npc_mountaineer_pebblebitty; - newscript->pGossipSelect = &GossipSelect_npc_mountaineer_pebblebitty; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp b/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp deleted file mode 100644 index b5835dfe0a1..00000000000 --- a/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Felblood_Kaelthas -SD%Complete: 80 -SDComment: Normal and Heroic Support. Issues: Arcane Spheres do not initially follow targets. -SDCategory: Magisters' Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" -#include "WorldPacket.h" - -#define SAY_AGGRO -1585023 //This yell should be done when the room is cleared. For now, set it as a movelineofsight yell. -#define SAY_PHOENIX -1585024 -#define SAY_FLAMESTRIKE -1585025 -#define SAY_GRAVITY_LAPSE -1585026 -#define SAY_TIRED -1585027 -#define SAY_RECAST_GRAVITY -1585028 -#define SAY_DEATH -1585029 - -/*** Spells ***/ - -// Phase 1 spells -#define SPELL_FIREBALL_NORMAL 44189 // Deals 2700-3300 damage at current target -#define SPELL_FIREBALL_HEROIC 46164 // 4950-6050 - -#define SPELL_PHOENIX 44194 // Summons a phoenix (Doesn't work?) -#define SPELL_PHOENIX_BURN 44197 // A spell Phoenix uses to damage everything around -#define SPELL_REBIRTH_DMG 44196 // DMG if a Phoenix rebirth happen - -#define SPELL_FLAMESTRIKE1_NORMAL 44190 // Damage part -#define SPELL_FLAMESTRIKE1_HEROIC 46163 // Heroic damage part -#define SPELL_FLAMESTRIKE2 44191 // Flamestrike indicator before the damage -#define SPELL_FLAMESTRIKE3 44192 // Summons the trigger + animation (projectile) - -#define SPELL_SHOCK_BARRIER 46165 // Heroic only; 10k damage shield, followed by Pyroblast -#define SPELL_PYROBLAST 36819 // Heroic only; 45-55k fire damage - -// Phase 2 spells -#define SPELL_GRAVITY_LAPSE_INITIAL 44224 // Cast at the beginning of every Gravity Lapse -#define SPELL_GRAVITY_LAPSE_CHANNEL 44251 // Channeled; blue beam animation to every enemy in range -#define SPELL_TELEPORT_CENTER 44218 // Should teleport people to the center. Requires DB entry in spell_target_position. -#define SPELL_GRAVITY_LAPSE_FLY 44227 // Hastens flyspeed and allows flying for 1 minute. For some reason removes 44226. -#define SPELL_GRAVITY_LAPSE_DOT 44226 // Knocks up in the air and applies a 300 DPS DoT. -#define SPELL_ARCANE_SPHERE_PASSIVE 44263 // Passive auras on Arcane Spheres -#define SPELL_POWER_FEEDBACK 44233 // Stuns him, making him take 50% more damage for 10 seconds. Cast after Gravity Lapse - -/*** Creatures ***/ -#define CREATURE_PHOENIX 24674 -#define CREATURE_PHOENIX_EGG 24675 -#define CREATURE_ARCANE_SPHERE 24708 - -/** Locations **/ -float KaelLocations[3][2]= -{ - {148.744659, 181.377426}, - {140.823883, 195.403046}, - {156.574188, 195.650482}, -}; - -#define LOCATION_Z -16.727455 - -struct boss_felblood_kaelthasAI : public ScriptedAI -{ - boss_felblood_kaelthasAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 FireballTimer; - uint32 PhoenixTimer; - uint32 FlameStrikeTimer; - uint32 CombatPulseTimer; - - //Heroic only - uint32 PyroblastTimer; - - uint32 GravityLapseTimer; - uint32 GravityLapsePhase; - // 0 = No Gravity Lapse - // 1 = Casting Gravity Lapse visual - // 2 = Teleported people to self - // 3 = Knocked people up in the air - // 4 = Applied an aura that allows them to fly, channeling visual, relased Arcane Orbs. - - bool FirstGravityLapse; - bool HasTaunted; - - uint8 Phase; - // 0 = Not started - // 1 = Fireball; Summon Phoenix; Flamestrike - // 2 = Gravity Lapses - - void Reset() - { - // TODO: Timers - FireballTimer = 0; - PhoenixTimer = 10000; - FlameStrikeTimer = 25000; - CombatPulseTimer = 0; - - PyroblastTimer = 60000; - - GravityLapseTimer = 0; - GravityLapsePhase = 0; - - FirstGravityLapse = true; - HasTaunted = false; - - Phase = 0; - - if (pInstance) - { - pInstance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), true); - // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here) - // Small door opened after event are expected to be closed by default - } - } - - void JustDied(Unit * /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), true); - // Open the encounter door - } - - void DamageTaken(Unit* /*done_by*/, uint32 &damage) - { - if (damage > me->GetHealth()) - RemoveGravityLapse(); // Remove Gravity Lapse so that players fall to ground if they kill him when in air. - } - - void EnterCombat(Unit * /*who*/) - { - if (!pInstance) - return; - - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), false); - //Close the encounter door, open it in JustDied/Reset - } - - void MoveInLineOfSight(Unit *who) - { - if (!HasTaunted && me->IsWithinDistInMap(who, 40.0)) - { - DoScriptText(SAY_AGGRO, me); - HasTaunted = true; - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void SetThreatList(Creature* SummonedUnit) - { - if (!SummonedUnit) - return; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - std::list::const_iterator i = m_threatlist.begin(); - for (i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - { - float threat = me->getThreatManager().getThreat(pUnit); - SummonedUnit->AddThreat(pUnit, threat); - } - } - } - - void TeleportPlayersToSelf() - { - float x = KaelLocations[0][0]; - float y = KaelLocations[0][1]; - me->GetMap()->CreatureRelocation(me, x, y, LOCATION_Z, 0.0f); - //me->SendMonsterMove(x, y, LOCATION_Z, 0, 0, 0); // causes some issues... - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - pUnit->CastSpell(pUnit, SPELL_TELEPORT_CENTER, true); - } - DoCast(me, SPELL_TELEPORT_CENTER, true); - } - - void CastGravityLapseKnockUp() - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - // Knockback into the air - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, me->GetGUID()); - } - } - - void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - // Also needs an exception in spell system. - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, me->GetGUID()); - // Use packet hack - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - } - - void RemoveGravityLapse() - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); - pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); - - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - switch(Phase) - { - case 0: - { - // *Heroic mode only: - if (IsHeroic()) - { - if (PyroblastTimer <= diff) - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - DoCast(me, SPELL_SHOCK_BARRIER, true); - DoCast(me->getVictim(), SPELL_PYROBLAST); - PyroblastTimer = 60000; - } else PyroblastTimer -= diff; - } - - if (FireballTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL_NORMAL); - FireballTimer = urand(2000,6000); - } else FireballTimer -= diff; - - if (PhoenixTimer <= diff) - { - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - - uint8 random = urand(1,2); - float x = KaelLocations[random][0]; - float y = KaelLocations[random][1]; - - Creature* Phoenix = me->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - if (Phoenix) - { - Phoenix->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - SetThreatList(Phoenix); - Phoenix->AI()->AttackStart(pTarget); - } - - DoScriptText(SAY_PHOENIX, me); - - PhoenixTimer = 60000; - } else PhoenixTimer -= diff; - - if (FlameStrikeTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - DoCast(pTarget, SPELL_FLAMESTRIKE3, true); - DoScriptText(SAY_FLAMESTRIKE, me); - } - FlameStrikeTimer = urand(15000,25000); - } else FlameStrikeTimer -= diff; - - // Below 50% - if (me->GetMaxHealth() * 0.5 > me->GetHealth()) - { - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - GravityLapseTimer = 0; - GravityLapsePhase = 0; - Phase = 1; - } - - DoMeleeAttackIfReady(); - } - break; - - case 1: - { - if (GravityLapseTimer <= diff) - { - switch(GravityLapsePhase) - { - case 0: - if (FirstGravityLapse) // Different yells at 50%, and at every following Gravity Lapse - { - DoScriptText(SAY_GRAVITY_LAPSE, me); - FirstGravityLapse = false; - - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_STATUE_LEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_STATUE_RIGHT), true); - } - }else - { - DoScriptText(SAY_RECAST_GRAVITY, me); - } - - DoCast(me, SPELL_GRAVITY_LAPSE_INITIAL); - GravityLapseTimer = 2000 + diff;// Don't interrupt the visual spell - GravityLapsePhase = 1; - break; - - case 1: - TeleportPlayersToSelf(); - GravityLapseTimer = 1000; - GravityLapsePhase = 2; - break; - - case 2: - CastGravityLapseKnockUp(); - GravityLapseTimer = 1000; - GravityLapsePhase = 3; - break; - - case 3: - CastGravityLapseFly(); - GravityLapseTimer = 30000; - GravityLapsePhase = 4; - - for (uint8 i = 0; i < 3; ++i) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); - if (Orb && pTarget) - { - Orb->SetSpeed(MOVE_RUN, 0.5f); - Orb->AddThreat(pTarget, 1000000.0f); - Orb->AI()->AttackStart(pTarget); - } - - } - - DoCast(me, SPELL_GRAVITY_LAPSE_CHANNEL); - break; - - case 4: - me->InterruptNonMeleeSpells(false); - DoScriptText(SAY_TIRED, me); - DoCast(me, SPELL_POWER_FEEDBACK); - RemoveGravityLapse(); - GravityLapseTimer = 10000; - GravityLapsePhase = 0; - break; - } - } else GravityLapseTimer -= diff; - } - break; - } - } -}; - -struct mob_felkael_flamestrikeAI : public ScriptedAI -{ - mob_felkael_flamestrikeAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 FlameStrikeTimer; - - void Reset() - { - FlameStrikeTimer = 5000; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - - DoCast(me, SPELL_FLAMESTRIKE2, true); - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (FlameStrikeTimer <= diff) - { - DoCast(me, SPELL_FLAMESTRIKE1_NORMAL, true); - me->Kill(me); - } else FlameStrikeTimer -= diff; - } -}; - -struct mob_felkael_phoenixAI : public ScriptedAI -{ - mob_felkael_phoenixAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 BurnTimer; - uint32 Death_Timer; - bool Rebirth; - bool FakeDeath; - - void Reset() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - DoCast(me, SPELL_PHOENIX_BURN, true); - BurnTimer = 2000; - Death_Timer = 3000; - Rebirth = false; - FakeDeath = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage < me->GetHealth()) - return; - - //Prevent glitch if in fake death - if (FakeDeath) - { - damage = 0; - return; - - } - //Don't really die in all phases of Kael'Thas - if (pInstance && pInstance->GetData(DATA_KAELTHAS_EVENT) == 0) - { - //prevent death - damage = 0; - FakeDeath = true; - - me->InterruptNonMeleeSpells(false); - me->SetHealth(0); - me->StopMoving(); - me->ClearComboPointHolders(); - me->RemoveAllAurasOnDeath(); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->ClearAllReactives(); - me->SetUInt64Value(UNIT_FIELD_TARGET,0); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - - } - - } - - void JustDied(Unit* /*slayer*/) - { - me->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); - } - - void UpdateAI(const uint32 diff) - { - - //If we are fake death, we cast revbirth and after that we kill the phoenix to spawn the egg. - if (FakeDeath) - { - if (!Rebirth) - { - DoCast(me, SPELL_REBIRTH_DMG); - Rebirth = true; - } - - if (Rebirth) - { - - if (Death_Timer <= diff) - { - me->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); - me->DisappearAndDie(); - Rebirth = false; - } else Death_Timer -= diff; - } - - } - - if (!UpdateVictim()) - return; - - if (BurnTimer <= diff) - { - //spell Burn should possible do this, but it doesn't, so do this for now. - uint16 dmg = urand(1650,2050); - me->DealDamage(me, dmg, 0, DOT, SPELL_SCHOOL_MASK_FIRE, NULL, false); - BurnTimer += 2000; - } BurnTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_felkael_phoenix_eggAI : public ScriptedAI -{ - mob_felkael_phoenix_eggAI(Creature *c) : ScriptedAI(c) {} - - uint32 HatchTimer; - - void Reset() - { - HatchTimer = 10000; - } - - void EnterCombat(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (HatchTimer <= diff) - { - me->SummonCreature(CREATURE_PHOENIX, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - me->Kill(me); - } else HatchTimer -= diff; - - } -}; - -struct mob_arcane_sphereAI : public ScriptedAI -{ - mob_arcane_sphereAI(Creature *c) : ScriptedAI(c) { Reset(); } - - uint32 DespawnTimer; - uint32 ChangeTargetTimer; - - void Reset() - { - DespawnTimer = 30000; - ChangeTargetTimer = urand(6000,12000); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->setFaction(14); - DoCast(me, SPELL_ARCANE_SPHERE_PASSIVE, true); - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (DespawnTimer <= diff) - me->Kill(me); - else - DespawnTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (ChangeTargetTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - } - - ChangeTargetTimer = urand(5000,15000); - } else ChangeTargetTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_felblood_kaelthas(Creature* c) -{ - return new boss_felblood_kaelthasAI(c); -} - -CreatureAI* GetAI_mob_arcane_sphere(Creature* c) -{ - return new mob_arcane_sphereAI(c); -} - -CreatureAI* GetAI_mob_felkael_phoenix(Creature* c) -{ - return new mob_felkael_phoenixAI(c); -} - -CreatureAI* GetAI_mob_felkael_phoenix_egg(Creature* c) -{ - return new mob_felkael_phoenix_eggAI(c); -} - -CreatureAI* GetAI_mob_felkael_flamestrike(Creature* c) -{ - return new mob_felkael_flamestrikeAI(c); -} - -void AddSC_boss_felblood_kaelthas() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_felblood_kaelthas"; - newscript->GetAI = &GetAI_boss_felblood_kaelthas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_arcane_sphere"; - newscript->GetAI = &GetAI_mob_arcane_sphere; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felkael_phoenix"; - newscript->GetAI = &GetAI_mob_felkael_phoenix; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felkael_phoenix_egg"; - newscript->GetAI = &GetAI_mob_felkael_phoenix_egg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felkael_flamestrike"; - newscript->GetAI = &GetAI_mob_felkael_flamestrike; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp b/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp deleted file mode 100644 index 2112eaabc87..00000000000 --- a/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp +++ /dev/null @@ -1,1321 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Priestess_Delrissa -SD%Complete: 65 -SDComment: No Heroic support yet. Needs further testing. Several scripts for pets disabled, not seem to require any special script. -SDCategory: Magister's Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" - -struct Speech -{ - int32 id; -}; - -static Speech LackeyDeath[]= -{ - {-1585013}, - {-1585014}, - {-1585015}, - {-1585016}, -}; - -static Speech PlayerDeath[]= -{ - {-1585017}, - {-1585018}, - {-1585019}, - {-1585020}, - {-1585021}, -}; - -enum eEnums -{ - SAY_AGGRO = -1585012, - SAY_DEATH = -1585022, - - SPELL_DISPEL_MAGIC = 27609, - SPELL_FLASH_HEAL = 17843, - SPELL_SW_PAIN_NORMAL = 14032, - SPELL_SW_PAIN_HEROIC = 15654, - SPELL_SHIELD = 44291, - SPELL_RENEW_NORMAL = 44174, - SPELL_RENEW_HEROIC = 46192, - - MAX_ACTIVE_LACKEY = 4 -}; - -const float fOrientation = 4.98; -const float fZLocation = -19.921; - -float LackeyLocations[4][2]= -{ - {123.77, 17.6007}, - {131.731, 15.0827}, - {121.563, 15.6213}, - {129.988, 17.2355}, -}; - -const uint32 m_auiAddEntries[] = -{ - 24557, //Kagani Nightstrike - 24558, //Elris Duskhallow - 24554, //Eramas Brightblaze - 24561, //Yazzaj - 24559, //Warlord Salaris - 24555, //Garaxxas - 24553, //Apoko - 24556, //Zelfan -}; - -struct boss_priestess_delrissaAI : public ScriptedAI -{ - boss_priestess_delrissaAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - memset(&m_auiLackeyGUID, 0, sizeof(m_auiLackeyGUID)); - LackeyEntryList.clear(); - } - - ScriptedInstance* pInstance; - - std::vector LackeyEntryList; - uint64 m_auiLackeyGUID[MAX_ACTIVE_LACKEY]; - - uint8 PlayersKilled; - - uint32 HealTimer; - uint32 RenewTimer; - uint32 ShieldTimer; - uint32 SWPainTimer; - uint32 DispelTimer; - uint32 ResetTimer; - - void Reset() - { - PlayersKilled = 0; - - HealTimer = 15000; - RenewTimer = 10000; - ShieldTimer = 2000; - SWPainTimer = 5000; - DispelTimer = 7500; - ResetTimer = 5000; - - InitializeLackeys(); - } - - //this mean she at some point evaded - void JustReachedHome() - { - if (pInstance) - pInstance->SetData(DATA_DELRISSA_EVENT, FAIL); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me); - - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[i])) - { - if (!pAdd->getVictim()) - { - who->SetInCombatWith(pAdd); - pAdd->AddThreat(who, 0.0f); - } - } - } - - if (pInstance) - pInstance->SetData(DATA_DELRISSA_EVENT, IN_PROGRESS); - } - - void InitializeLackeys() - { - //can be called if Creature are dead, so avoid - if (!me->isAlive()) - return; - - uint8 j = 0; - - //it's empty, so first time - if (LackeyEntryList.empty()) - { - //pre-allocate size for speed - LackeyEntryList.resize((sizeof(m_auiAddEntries) / sizeof(uint32))); - - //fill vector array with entries from Creature array - for (uint8 i = 0; i < LackeyEntryList.size(); ++i) - LackeyEntryList[i] = m_auiAddEntries[i]; - - //remove random entries - while (LackeyEntryList.size() > MAX_ACTIVE_LACKEY) - LackeyEntryList.erase(LackeyEntryList.begin() + rand()%LackeyEntryList.size()); - - //summon all the remaining in vector - for (std::vector::const_iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr) - { - if (Creature* pAdd = me->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0)) - m_auiLackeyGUID[j] = pAdd->GetGUID(); - - ++j; - } - } - else - { - for (std::vector::const_iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr) - { - Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[j]); - - //object already removed, not exist - if (!pAdd) - { - if (Creature* pAdd = me->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0)) - m_auiLackeyGUID[j] = pAdd->GetGUID(); - } - ++j; - } - } - } - - void KilledUnit(Unit* victim) - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(PlayerDeath[PlayersKilled].id, me); - - if (PlayersKilled < 4) - ++PlayersKilled; - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - if (pInstance->GetData(DATA_DELRISSA_DEATH_COUNT) == MAX_ACTIVE_LACKEY) - pInstance->SetData(DATA_DELRISSA_EVENT, DONE); - else - { - if (me->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ResetTimer <= diff) - { - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - if (me->GetPositionZ() >= z+10) - { - EnterEvadeMode(); - return; - } - ResetTimer = 5000; - } else ResetTimer -= diff; - - if (HealTimer <= diff) - { - uint32 health = me->GetHealth(); - Unit *pTarget = me; - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[i])) - { - if (pAdd->isAlive() && pAdd->GetHealth() < health) - pTarget = pAdd; - } - } - - DoCast(pTarget, SPELL_FLASH_HEAL); - HealTimer = 15000; - } else HealTimer -= diff; - - if (RenewTimer <= diff) - { - Unit *pTarget = me; - - if (urand(0,1)) - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) - if (pAdd->isAlive()) - pTarget = pAdd; - - DoCast(pTarget, SPELL_RENEW_NORMAL); - RenewTimer = 5000; - } else RenewTimer -= diff; - - if (ShieldTimer <= diff) - { - Unit *pTarget = me; - - if (urand(0,1)) - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) - if (pAdd->isAlive() && !pAdd->HasAura(SPELL_SHIELD)) - pTarget = pAdd; - - DoCast(pTarget, SPELL_SHIELD); - ShieldTimer = 7500; - } else ShieldTimer -= diff; - - if (DispelTimer <= diff) - { - Unit *pTarget = NULL; - bool friendly = false; - - if (urand(0,1)) - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - else - { - friendly = true; - - if (urand(0,1)) - pTarget = me; - else - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) - if (pAdd->isAlive()) - pTarget = pAdd; - } - - if (pTarget) - DoCast(pTarget, SPELL_DISPEL_MAGIC); - - DispelTimer = 12000; - } else DispelTimer -= diff; - - if (SWPainTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SW_PAIN_NORMAL); - - SWPainTimer = 10000; - } else SWPainTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_priestess_delrissa(Creature* pCreature) -{ - return new boss_priestess_delrissaAI(pCreature); -} - -enum eHealingPotion -{ - SPELL_HEALING_POTION = 15503 -}; - -//all 8 possible lackey use this common -struct boss_priestess_lackey_commonAI : public ScriptedAI -{ - boss_priestess_lackey_commonAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - memset(&m_auiLackeyGUIDs, 0, sizeof(m_auiLackeyGUIDs)); - AcquireGUIDs(); - } - - ScriptedInstance* pInstance; - - uint64 m_auiLackeyGUIDs[MAX_ACTIVE_LACKEY]; - uint32 ResetThreatTimer; - - bool UsedPotion; - - void Reset() - { - UsedPotion = false; - - // These guys does not follow normal threat system rules - // For later development, some alternative threat system should be made - // We do not know what this system is based upon, but one theory is class (healers=high threat, dps=medium, etc) - // We reset their threat frequently as an alternative until such a system exist - ResetThreatTimer = urand(5000,20000); - - // in case she is not alive and Reset was for some reason called, respawn her (most likely party wipe after killing her) - if (Creature* pDelrissa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DELRISSA) : 0)) - { - if (!pDelrissa->isAlive()) - pDelrissa->Respawn(); - } - } - - void EnterCombat(Unit* pWho) - { - if (!pWho) - return; - - if (pInstance) - { - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUIDs[i])) - { - if (!pAdd->getVictim() && pAdd != me) - { - pWho->SetInCombatWith(pAdd); - pAdd->AddThreat(pWho, 0.0f); - } - } - } - - if (Creature* pDelrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA))) - { - if (pDelrissa->isAlive() && !pDelrissa->getVictim()) - { - pWho->SetInCombatWith(pDelrissa); - pDelrissa->AddThreat(pWho, 0.0f); - } - } - } - } - - void JustDied(Unit* /*killer*/) - { - if (!pInstance) - return; - - Creature* pDelrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA)); - uint32 uiLackeyDeathCount = pInstance->GetData(DATA_DELRISSA_DEATH_COUNT); - - if (!pDelrissa) - return; - - //should delrissa really yell if dead? - DoScriptText(LackeyDeath[uiLackeyDeathCount].id, pDelrissa); - - pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, SPECIAL); - - //increase local var, since we now may have four dead - ++uiLackeyDeathCount; - - if (uiLackeyDeathCount == MAX_ACTIVE_LACKEY) - { - //time to make her lootable and complete event if she died before lackeys - if (!pDelrissa->isAlive()) - { - if (!pDelrissa->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) - pDelrissa->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - - pInstance->SetData(DATA_DELRISSA_EVENT, DONE); - } - } - } - - void KilledUnit(Unit* victim) - { - if (!pInstance) - return; - - if (Creature* Delrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA))) - Delrissa->AI()->KilledUnit(victim); - } - - void AcquireGUIDs() - { - if (!pInstance) - return; - - if (Creature* Delrissa = (Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA)))) - { - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - m_auiLackeyGUIDs[i] = CAST_AI(boss_priestess_delrissaAI, Delrissa->AI())->m_auiLackeyGUID[i]; - } - } - - void UpdateAI(const uint32 diff) - { - if (!UsedPotion && (me->GetHealth()*100 / me->GetMaxHealth()) < 25) - { - DoCast(me, SPELL_HEALING_POTION); - UsedPotion = true; - } - - if (ResetThreatTimer <= diff) - { - DoResetThreat(); - ResetThreatTimer = 5000 + rand()%15000; - } else ResetThreatTimer -= diff; - } -}; - -enum eRogueSpells -{ - SPELL_KIDNEY_SHOT = 27615, - SPELL_GOUGE = 12540, - SPELL_KICK = 27613, - SPELL_VANISH = 44290, - SPELL_BACKSTAB = 15657, - SPELL_EVISCERATE = 27611 -}; - -struct boss_kagani_nightstrikeAI : public boss_priestess_lackey_commonAI -{ - //Rogue - boss_kagani_nightstrikeAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Gouge_Timer; - uint32 Kick_Timer; - uint32 Vanish_Timer; - uint32 Eviscerate_Timer; - uint32 Wait_Timer; - bool InVanish; - - void Reset() - { - Gouge_Timer = 5500; - Kick_Timer = 7000; - Vanish_Timer = 2000; - Eviscerate_Timer = 6000; - Wait_Timer = 5000; - InVanish = false; - me->SetVisibility(VISIBILITY_ON); - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Vanish_Timer <= diff) - { - DoCast(me, SPELL_VANISH); - - Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0); - - DoResetThreat(); - - if (pUnit) - me->AddThreat(pUnit, 1000.0f); - - InVanish = true; - Vanish_Timer = 30000; - Wait_Timer = 10000; - } else Vanish_Timer -= diff; - - if (InVanish) - { - if (Wait_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BACKSTAB, true); - DoCast(me->getVictim(), SPELL_KIDNEY_SHOT, true); - me->SetVisibility(VISIBILITY_ON); // ...? Hacklike - InVanish = false; - } else Wait_Timer -= diff; - } - - if (Gouge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GOUGE); - Gouge_Timer = 5500; - } else Gouge_Timer -= diff; - - if (Kick_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KICK); - Kick_Timer = 7000; - } else Kick_Timer -= diff; - - if (Eviscerate_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_EVISCERATE); - Eviscerate_Timer = 4000; - } else Eviscerate_Timer -= diff; - - if (!InVanish) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kagani_nightstrike(Creature* pCreature) -{ - return new boss_kagani_nightstrikeAI(pCreature); -} - -enum eWarlockSpells -{ - SPELL_IMMOLATE = 44267, - SPELL_SHADOW_BOLT = 12471, - SPELL_SEED_OF_CORRUPTION = 44141, - SPELL_CURSE_OF_AGONY = 14875, - SPELL_FEAR = 38595, - SPELL_IMP_FIREBALL = 44164, - SPELL_SUMMON_IMP = 44163 -}; - -struct boss_ellris_duskhallowAI : public boss_priestess_lackey_commonAI -{ - //Warlock - boss_ellris_duskhallowAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Immolate_Timer; - uint32 Shadow_Bolt_Timer; - uint32 Seed_of_Corruption_Timer; - uint32 Curse_of_Agony_Timer; - uint32 Fear_Timer; - - void Reset() - { - Immolate_Timer = 6000; - Shadow_Bolt_Timer = 3000; - Seed_of_Corruption_Timer = 2000; - Curse_of_Agony_Timer = 1000; - Fear_Timer = 10000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void Aggro(Unit* /*pWho*/) - { - DoCast(me, SPELL_SUMMON_IMP); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Immolate_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_IMMOLATE); - Immolate_Timer = 6000; - } else Immolate_Timer -= diff; - - if (Shadow_Bolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - Shadow_Bolt_Timer = 5000; - } else Shadow_Bolt_Timer -= diff; - - if (Seed_of_Corruption_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_SEED_OF_CORRUPTION); - - Seed_of_Corruption_Timer = 10000; - } else Seed_of_Corruption_Timer -= diff; - - if (Curse_of_Agony_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_CURSE_OF_AGONY); - - Curse_of_Agony_Timer = 13000; - } else Curse_of_Agony_Timer -= diff; - - if (Fear_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_FEAR); - - Fear_Timer = 10000; - } else Fear_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_ellris_duskhallow(Creature* pCreature) -{ - return new boss_ellris_duskhallowAI(pCreature); -} - -enum eKickDown -{ - SPELL_KNOCKDOWN = 11428, - SPELL_SNAP_KICK = 46182 -}; - -struct boss_eramas_brightblazeAI : public boss_priestess_lackey_commonAI -{ - //Monk - boss_eramas_brightblazeAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Knockdown_Timer; - uint32 Snap_Kick_Timer; - - void Reset() - { - Knockdown_Timer = 6000; - Snap_Kick_Timer = 4500; - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Knockdown_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - Knockdown_Timer = 6000; - } else Knockdown_Timer -= diff; - - if (Snap_Kick_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SNAP_KICK); - Snap_Kick_Timer = 4500; - } else Snap_Kick_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_eramas_brightblaze(Creature* pCreature) -{ - return new boss_eramas_brightblazeAI(pCreature); -} - -enum eMageSpells -{ - SPELL_POLYMORPH = 13323, - SPELL_ICE_BLOCK = 27619, - SPELL_BLIZZARD = 44178, - SPELL_ICE_LANCE = 46194, - SPELL_CONE_OF_COLD = 38384, - SPELL_FROSTBOLT = 15043, - SPELL_BLINK = 14514 -}; - -struct boss_yazzaiAI : public boss_priestess_lackey_commonAI -{ - //Mage - boss_yazzaiAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - bool HasIceBlocked; - - uint32 Polymorph_Timer; - uint32 Ice_Block_Timer; - uint32 Wait_Timer; - uint32 Blizzard_Timer; - uint32 Ice_Lance_Timer; - uint32 Cone_of_Cold_Timer; - uint32 Frostbolt_Timer; - uint32 Blink_Timer; - - void Reset() - { - HasIceBlocked = false; - - Polymorph_Timer = 1000; - Ice_Block_Timer = 20000; - Wait_Timer = 10000; - Blizzard_Timer = 8000; - Ice_Lance_Timer = 12000; - Cone_of_Cold_Timer = 10000; - Frostbolt_Timer = 3000; - Blink_Timer = 8000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Polymorph_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_POLYMORPH); - Polymorph_Timer = 20000; - } - } else Polymorph_Timer -= diff; - - if (((me->GetHealth()*100 / me->GetMaxHealth()) < 35) && !HasIceBlocked) - { - DoCast(me, SPELL_ICE_BLOCK); - HasIceBlocked = true; - } - - if (Blizzard_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_BLIZZARD); - - Blizzard_Timer = 8000; - } else Blizzard_Timer -= diff; - - if (Ice_Lance_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ICE_LANCE); - Ice_Lance_Timer = 12000; - } else Ice_Lance_Timer -= diff; - - if (Cone_of_Cold_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CONE_OF_COLD); - Cone_of_Cold_Timer = 10000; - } else Cone_of_Cold_Timer -= diff; - - if (Frostbolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - Frostbolt_Timer = 8000; - } else Frostbolt_Timer -= diff; - - if (Blink_Timer <= diff) - { - bool InMeleeRange = false; - std::list& t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - //if in melee range - if (pTarget->IsWithinDistInMap(me, 5)) - { - InMeleeRange = true; - break; - } - } - } - - //if anybody is in melee range than escape by blink - if (InMeleeRange) - DoCast(me, SPELL_BLINK); - - Blink_Timer = 8000; - } else Blink_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_yazzai(Creature* pCreature) -{ - return new boss_yazzaiAI(pCreature); -} - -enum eWarriorSpells -{ - SPELL_INTERCEPT_STUN = 27577, - SPELL_DISARM = 27581, - SPELL_PIERCING_HOWL = 23600, - SPELL_FRIGHTENING_SHOUT = 19134, - SPELL_HAMSTRING = 27584, - SPELL_BATTLE_SHOUT = 27578, - SPELL_MORTAL_STRIKE = 44268 -}; - -struct boss_warlord_salarisAI : public boss_priestess_lackey_commonAI -{ - //Warrior - boss_warlord_salarisAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Intercept_Stun_Timer; - uint32 Disarm_Timer; - uint32 Piercing_Howl_Timer; - uint32 Frightening_Shout_Timer; - uint32 Hamstring_Timer; - uint32 Mortal_Strike_Timer; - - void Reset() - { - Intercept_Stun_Timer = 500; - Disarm_Timer = 6000; - Piercing_Howl_Timer = 10000; - Frightening_Shout_Timer = 18000; - Hamstring_Timer = 4500; - Mortal_Strike_Timer = 8000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_BATTLE_SHOUT); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Intercept_Stun_Timer <= diff) - { - bool InMeleeRange = false; - std::list& t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - //if in melee range - if (pTarget->IsWithinDistInMap(me, ATTACK_DISTANCE)) - { - InMeleeRange = true; - break; - } - } - } - - //if nobody is in melee range than try to use Intercept - if (!InMeleeRange) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_INTERCEPT_STUN); - } - - Intercept_Stun_Timer = 10000; - } else Intercept_Stun_Timer -= diff; - - if (Disarm_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DISARM); - Disarm_Timer = 6000; - } else Disarm_Timer -= diff; - - if (Hamstring_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - Hamstring_Timer = 4500; - } else Hamstring_Timer -= diff; - - if (Mortal_Strike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - Mortal_Strike_Timer = 4500; - } else Mortal_Strike_Timer -= diff; - - if (Piercing_Howl_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PIERCING_HOWL); - Piercing_Howl_Timer = 10000; - } else Piercing_Howl_Timer -= diff; - - if (Frightening_Shout_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); - Frightening_Shout_Timer = 18000; - } else Frightening_Shout_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_warlord_salaris(Creature* pCreature) -{ - return new boss_warlord_salarisAI(pCreature); -} - -enum eHunterSpells -{ - SPELL_AIMED_SHOT = 44271, - SPELL_SHOOT = 15620, - SPELL_CONCUSSIVE_SHOT = 27634, - SPELL_MULTI_SHOT = 31942, - SPELL_WING_CLIP = 44286, - SPELL_FREEZING_TRAP = 44136, - - NPC_SLIVER = 24552 -}; - -struct boss_garaxxasAI : public boss_priestess_lackey_commonAI -{ - //Hunter - boss_garaxxasAI(Creature *c) : boss_priestess_lackey_commonAI(c) { m_uiPetGUID = 0; } - - uint64 m_uiPetGUID; - - uint32 Aimed_Shot_Timer; - uint32 Shoot_Timer; - uint32 Concussive_Shot_Timer; - uint32 Multi_Shot_Timer; - uint32 Wing_Clip_Timer; - uint32 Freezing_Trap_Timer; - - void Reset() - { - Aimed_Shot_Timer = 6000; - Shoot_Timer = 2500; - Concussive_Shot_Timer = 8000; - Multi_Shot_Timer = 10000; - Wing_Clip_Timer = 4000; - Freezing_Trap_Timer = 15000; - - Unit* pPet = Unit::GetUnit(*me,m_uiPetGUID); - if (!pPet) - me->SummonCreature(NPC_SLIVER, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - - boss_priestess_lackey_commonAI::Reset(); - } - - void JustSummoned(Creature* pSummoned) - { - m_uiPetGUID = pSummoned->GetGUID(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (me->IsWithinDistInMap(me->getVictim(), ATTACK_DISTANCE)) - { - if (Wing_Clip_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WING_CLIP); - Wing_Clip_Timer = 4000; - } else Wing_Clip_Timer -= diff; - - if (Freezing_Trap_Timer <= diff) - { - //attempt find go summoned from spell (casted by me) - GameObject* pGo = me->GetGameObject(SPELL_FREEZING_TRAP); - - //if we have a pGo, we need to wait (only one trap at a time) - if (pGo) - Freezing_Trap_Timer = 2500; - else - { - //if pGo does not exist, then we can cast - DoCast(me->getVictim(), SPELL_FREEZING_TRAP); - Freezing_Trap_Timer = 15000; - } - } else Freezing_Trap_Timer -= diff; - - DoMeleeAttackIfReady(); - } - else - { - if (Concussive_Shot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CONCUSSIVE_SHOT); - Concussive_Shot_Timer = 8000; - } else Concussive_Shot_Timer -= diff; - - if (Multi_Shot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MULTI_SHOT); - Multi_Shot_Timer = 10000; - } else Multi_Shot_Timer -= diff; - - if (Aimed_Shot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_AIMED_SHOT); - Aimed_Shot_Timer = 6000; - } else Aimed_Shot_Timer -= diff; - - if (Shoot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHOOT); - Shoot_Timer = 2500; - } else Shoot_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_garaxxas(Creature* pCreature) -{ - return new boss_garaxxasAI(pCreature); -} - -enum Spells -{ - SPELL_WINDFURY_TOTEM = 27621, - SPELL_WAR_STOMP = 46026, - SPELL_PURGE = 27626, - SPELL_LESSER_HEALING_WAVE = 44256, - SPELL_FROST_SHOCK = 21401, - SPELL_FIRE_NOVA_TOTEM = 44257, - SPELL_EARTHBIND_TOTEM = 15786 -}; - -struct boss_apokoAI : public boss_priestess_lackey_commonAI -{ - //Shaman - boss_apokoAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Totem_Timer; - uint8 Totem_Amount; - uint32 War_Stomp_Timer; - uint32 Purge_Timer; - uint32 Healing_Wave_Timer; - uint32 Frost_Shock_Timer; - - void Reset() - { - Totem_Timer = 2000; - Totem_Amount = 1; - War_Stomp_Timer = 10000; - Purge_Timer = 8000; - Healing_Wave_Timer = 5000; - Frost_Shock_Timer = 7000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Totem_Timer <= diff) - { - DoCast(me, RAND(SPELL_WINDFURY_TOTEM,SPELL_FIRE_NOVA_TOTEM,SPELL_EARTHBIND_TOTEM)); - ++Totem_Amount; - Totem_Timer = Totem_Amount*2000; - } else Totem_Timer -= diff; - - if (War_Stomp_Timer <= diff) - { - DoCast(me, SPELL_WAR_STOMP); - War_Stomp_Timer = 10000; - } else War_Stomp_Timer -= diff; - - if (Purge_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_PURGE); - - Purge_Timer = 15000; - } else Purge_Timer -= diff; - - if (Frost_Shock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_SHOCK); - Frost_Shock_Timer = 7000; - } else Frost_Shock_Timer -= diff; - - if (Healing_Wave_Timer <= diff) - { - // std::vector::const_iterator itr = Group.begin() + rand()%Group.size(); - // uint64 guid = (*itr)->guid; - // if (guid) - // { - // Unit* pAdd = Unit::GetUnit(*me, (*itr)->guid); - // if (pAdd && pAdd->isAlive()) - // { - DoCast(me, SPELL_LESSER_HEALING_WAVE); - Healing_Wave_Timer = 5000; - // } - // } - } else Healing_Wave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_apoko(Creature* pCreature) -{ - return new boss_apokoAI(pCreature); -} - -enum eEngineerSpells -{ - SPELL_GOBLIN_DRAGON_GUN = 44272, - SPELL_ROCKET_LAUNCH = 44137, - SPELL_RECOMBOBULATE = 44274, - SPELL_HIGH_EXPLOSIVE_SHEEP = 44276, - SPELL_FEL_IRON_BOMB = 46024, - SPELL_SHEEP_EXPLOSION = 44279 -}; - -struct boss_zelfanAI : public boss_priestess_lackey_commonAI -{ - //Engineer - boss_zelfanAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Goblin_Dragon_Gun_Timer; - uint32 Rocket_Launch_Timer; - uint32 Recombobulate_Timer; - uint32 High_Explosive_Sheep_Timer; - uint32 Fel_Iron_Bomb_Timer; - - void Reset() - { - Goblin_Dragon_Gun_Timer = 20000; - Rocket_Launch_Timer = 7000; - Recombobulate_Timer = 4000; - High_Explosive_Sheep_Timer = 10000; - Fel_Iron_Bomb_Timer = 15000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Goblin_Dragon_Gun_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GOBLIN_DRAGON_GUN); - Goblin_Dragon_Gun_Timer = 10000; - } else Goblin_Dragon_Gun_Timer -= diff; - - if (Rocket_Launch_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ROCKET_LAUNCH); - Rocket_Launch_Timer = 9000; - } else Rocket_Launch_Timer -= diff; - - if (Fel_Iron_Bomb_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FEL_IRON_BOMB); - Fel_Iron_Bomb_Timer = 15000; - } else Fel_Iron_Bomb_Timer -= diff; - - if (Recombobulate_Timer <= diff) - { - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUIDs[i])) - { - if (pAdd->IsPolymorphed()) - { - DoCast(pAdd, SPELL_RECOMBOBULATE); - break; - } - } - } - Recombobulate_Timer = 2000; - } else Recombobulate_Timer -= diff; - - if (High_Explosive_Sheep_Timer <= diff) - { - DoCast(me, SPELL_HIGH_EXPLOSIVE_SHEEP); - High_Explosive_Sheep_Timer = 65000; - } else High_Explosive_Sheep_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_zelfan(Creature* pCreature) -{ - return new boss_zelfanAI(pCreature); -} - -//struct mob_high_explosive_sheepAI : public ScriptedAI -//{ -// mob_high_explosive_sheepAI(Creature *c) : ScriptedAI(c) {} -// -// uint32 Explosion_Timer; -// -// void Reset() -// { -// Explosion_Timer = 60000; -// } -// -// void JustDied(Unit *Killer){} -// -// void EnterCombat(Unit * /*who*/){} -// -// void UpdateAI(const uint32 diff) -// { -// if (Explosion_Timer <= diff) -// { -// DoCast(me->getVictim(), SPELL_SHEEP_EXPLOSION); -// }else -// Explosion_Timer -= diff; -// } -//}; - -//CreatureAI* GetAI_mob_high_explosive_sheep(Creature* pCreature) -//{ -// return new mob_high_explosive_sheepAI (pCreature); -//}; - -void AddSC_boss_priestess_delrissa() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_priestess_delrissa"; - newscript->GetAI = &GetAI_boss_priestess_delrissa; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_kagani_nightstrike"; - newscript->GetAI = &GetAI_boss_kagani_nightstrike; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_ellris_duskhallow"; - newscript->GetAI = &GetAI_ellris_duskhallow; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_eramas_brightblaze"; - newscript->GetAI = &GetAI_eramas_brightblaze; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_yazzai"; - newscript->GetAI = &GetAI_yazzai; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_warlord_salaris"; - newscript->GetAI = &GetAI_warlord_salaris; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_garaxxas"; - newscript->GetAI = &GetAI_garaxxas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_apoko"; - newscript->GetAI = &GetAI_apoko; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_zelfan"; - newscript->GetAI = &GetAI_zelfan; - newscript->RegisterSelf(); - - /*newscript = new Script; - newscript->Name = "mob_high_explosive_sheep"; - newscript->GetAI = &GetAI_mob_high_explosive_sheep; - newscript->RegisterSelf();*/ -} - diff --git a/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp b/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp deleted file mode 100644 index adb0700eabf..00000000000 --- a/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Selin_Fireheart -SD%Complete: 90 -SDComment: Heroic and Normal Support. Needs further testing. -SDCategory: Magister's Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" - -#define SAY_AGGRO -1585000 -#define SAY_ENERGY -1585001 -#define SAY_EMPOWERED -1585002 -#define SAY_KILL_1 -1585003 -#define SAY_KILL_2 -1585004 -#define SAY_DEATH -1585005 -#define EMOTE_CRYSTAL -1585006 - -//Crystal effect spells -#define SPELL_FEL_CRYSTAL_COSMETIC 44374 -#define SPELL_FEL_CRYSTAL_DUMMY 44329 -#define SPELL_FEL_CRYSTAL_VISUAL 44355 -#define SPELL_MANA_RAGE 44320 // This spell triggers 44321, which changes scale and regens mana Requires an entry in spell_script_target - -//Selin's spells -#define SPELL_DRAIN_LIFE 44294 -#define SPELL_FEL_EXPLOSION 44314 - -#define SPELL_DRAIN_MANA 46153 // Heroic only - -#define CRYSTALS_NUMBER 5 -#define DATA_CRYSTALS 6 - -#define CREATURE_FEL_CRYSTAL 24722 - -struct boss_selin_fireheartAI : public ScriptedAI -{ - boss_selin_fireheartAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - - Crystals.clear(); - //GUIDs per instance is static, so we only need to load them once. - if (pInstance) - { - uint32 size = pInstance->GetData(DATA_FEL_CRYSTAL_SIZE); - for (uint8 i = 0; i < size; ++i) - { - uint64 guid = pInstance->GetData64(DATA_FEL_CRYSTAL); - debug_log("TSCR: Selin: Adding Fel Crystal %u to list", guid); - Crystals.push_back(guid); - } - } - } - - ScriptedInstance* pInstance; - - std::list Crystals; - - uint32 DrainLifeTimer; - uint32 DrainManaTimer; - uint32 FelExplosionTimer; - uint32 DrainCrystalTimer; - uint32 EmpowerTimer; - - bool IsDraining; - bool DrainingCrystal; - - uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course). - - void Reset() - { - if (pInstance) - { - //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) - for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) - { - //Unit* pUnit = Unit::GetUnit(*me, FelCrystals[i]); - Unit* pUnit = Unit::GetUnit(*me, *itr); - if (pUnit) - { - if (!pUnit->isAlive()) - CAST_CRE(pUnit)->Respawn(); // Let the core handle setting death state, etc. - - // Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here. - pUnit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - } - - pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); - // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here) - // Small door opened after event are expected to be closed by default - // Set Inst data for encounter - pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED); - } else error_log(ERROR_INST_DATA); - - DrainLifeTimer = 3000 + rand()%4000; - DrainManaTimer = DrainLifeTimer + 5000; - FelExplosionTimer = 2100; - DrainCrystalTimer = 10000 + rand()%5000; - DrainCrystalTimer = 20000 + rand()%5000; - EmpowerTimer = 10000; - - IsDraining = false; - DrainingCrystal = false; - CrystalGUID = 0; - } - - void SelectNearestCrystal() - { - if (Crystals.empty()) - return; - - //float ShortestDistance = 0; - CrystalGUID = 0; - Unit* pCrystal = NULL; - Unit* CrystalChosen = NULL; - //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) - for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) - { - pCrystal = NULL; - //pCrystal = Unit::GetUnit(*me, FelCrystals[i]); - pCrystal = Unit::GetUnit(*me, *itr); - if (pCrystal && pCrystal->isAlive()) - { - // select nearest - if (!CrystalChosen || me->GetDistanceOrder(pCrystal, CrystalChosen, false)) - { - CrystalGUID = pCrystal->GetGUID(); - CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell. - } - } - } - if (CrystalChosen) - { - DoScriptText(SAY_ENERGY, me); - DoScriptText(EMOTE_CRYSTAL, me); - - CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true); - - float x, y, z; // coords that we move to, close to the crystal. - CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE); - - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->MovePoint(1, x, y, z); - DrainingCrystal = true; - } - } - - void ShatterRemainingCrystals() - { - if (Crystals.empty()) - return; - - //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) - for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) - { - //Creature* pCrystal = (Unit::GetCreature(*me, FelCrystals[i])); - Creature* pCrystal = Unit::GetCreature(*me, *itr); - if (pCrystal && pCrystal->isAlive()) - pCrystal->Kill(pCrystal); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), false); - //Close the encounter door, open it in JustDied/Reset - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type == POINT_MOTION_TYPE && id == 1) - { - Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID); - if (CrystalChosen && CrystalChosen->isAlive()) - { - // Make the crystal attackable - // We also remove NON_ATTACKABLE in case the database has it set. - CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - CrystalChosen->CastSpell(me, SPELL_MANA_RAGE, true); - IsDraining = true; - } - else - { - // Make an error message in case something weird happened here - error_log("TSCR: Selin Fireheart unable to drain crystal as the crystal is either dead or despawned"); - DrainingCrystal = false; - } - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - pInstance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete! - pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); // Open the encounter door - pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_DOOR), true); // Open the door leading further in - ShatterRemainingCrystals(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!DrainingCrystal) - { - uint32 maxPowerMana = me->GetMaxPower(POWER_MANA); - if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10)) - { - if (DrainLifeTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE); - DrainLifeTimer = 10000; - } else DrainLifeTimer -= diff; - - // Heroic only - if (IsHeroic()) - { - if (DrainManaTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_DRAIN_MANA); - DrainManaTimer = 10000; - } else DrainManaTimer -= diff; - } - } - - if (FelExplosionTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_FEL_EXPLOSION); - FelExplosionTimer = 2000; - } - } else FelExplosionTimer -= diff; - - // If below 10% mana, start recharging - maxPowerMana = me->GetMaxPower(POWER_MANA); - if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10)) - { - if (DrainCrystalTimer <= diff) - { - SelectNearestCrystal(); - if (IsHeroic()) - DrainCrystalTimer = 10000 + rand()%5000; - else - DrainCrystalTimer = 20000 + rand()%5000; - } else DrainCrystalTimer -= diff; - } - - }else - { - if (IsDraining) - { - if (EmpowerTimer <= diff) - { - IsDraining = false; - DrainingCrystal = false; - - DoScriptText(SAY_EMPOWERED, me); - - Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID); - if (CrystalChosen && CrystalChosen->isAlive()) - // Use Deal Damage to kill it, not setDeathState. - CrystalChosen->Kill(CrystalChosen); - - CrystalGUID = 0; - - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } else EmpowerTimer -= diff; - } - } - - DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun. - } -}; - -CreatureAI* GetAI_boss_selin_fireheart(Creature* pCreature) -{ - return new boss_selin_fireheartAI (pCreature); -}; - -struct mob_fel_crystalAI : public ScriptedAI -{ - mob_fel_crystalAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} - - void JustDied(Unit* /*killer*/) - { - if (ScriptedInstance* pInstance = me->GetInstanceData()) - { - Creature* Selin = (Unit::GetCreature(*me, pInstance->GetData64(DATA_SELIN))); - if (Selin && Selin->isAlive()) - { - if (CAST_AI(boss_selin_fireheartAI, Selin->AI())->CrystalGUID == me->GetGUID()) - { - // Set this to false if we are the Creature that Selin is draining so his AI flows properly - CAST_AI(boss_selin_fireheartAI, Selin->AI())->DrainingCrystal = false; - CAST_AI(boss_selin_fireheartAI, Selin->AI())->IsDraining = false; - CAST_AI(boss_selin_fireheartAI, Selin->AI())->EmpowerTimer = 10000; - if (Selin->getVictim()) - { - Selin->AI()->AttackStart(Selin->getVictim()); - Selin->GetMotionMaster()->MoveChase(Selin->getVictim()); - } - } - } - } else error_log(ERROR_INST_DATA); - } -}; - -CreatureAI* GetAI_mob_fel_crystal(Creature* pCreature) -{ - return new mob_fel_crystalAI (pCreature); -}; - -void AddSC_boss_selin_fireheart() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_selin_fireheart"; - newscript->GetAI = &GetAI_boss_selin_fireheart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fel_crystal"; - newscript->GetAI = &GetAI_mob_fel_crystal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp b/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp deleted file mode 100644 index bc8bd5cec30..00000000000 --- a/src/server/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Vexallus -SD%Complete: 90 -SDComment: Heroic and Normal support. Needs further testing. -SDCategory: Magister's Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" - -enum eEnums -{ - SAY_AGGRO = -1585007, - SAY_ENERGY = -1585008, - SAY_OVERLOAD = -1585009, - SAY_KILL = -1585010, - EMOTE_DISCHARGE_ENERGY = -1585011, - - //is this text for real? - //#define SAY_DEATH "What...happen...ed." - - //Pure energy spell info - SPELL_ENERGY_BOLT = 46156, - SPELL_ENERGY_FEEDBACK = 44335, - - //Vexallus spell info - SPELL_CHAIN_LIGHTNING = 44318, - SPELL_H_CHAIN_LIGHTNING = 46380, //heroic spell - SPELL_OVERLOAD = 44353, - SPELL_ARCANE_SHOCK = 44319, - SPELL_H_ARCANE_SHOCK = 46381, //heroic spell - - SPELL_SUMMON_PURE_ENERGY = 44322, //mod scale -10 - H_SPELL_SUMMON_PURE_ENERGY1 = 46154, //mod scale -5 - H_SPELL_SUMMON_PURE_ENERGY2 = 46159, //mod scale -5 - - //Creatures - NPC_PURE_ENERGY = 24745, - - INTERVAL_MODIFIER = 15, - INTERVAL_SWITCH = 6 -}; - -struct boss_vexallusAI : public ScriptedAI -{ - boss_vexallusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ChainLightningTimer; - uint32 ArcaneShockTimer; - uint32 OverloadTimer; - uint32 IntervalHealthAmount; - bool Enraged; - - void Reset() - { - ChainLightningTimer = 8000; - ArcaneShockTimer = 5000; - OverloadTimer = 1200; - IntervalHealthAmount = 1; - Enraged = false; - - if (pInstance) - pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_VEXALLUS_EVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature *summoned) - { - if (Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 0)) - summoned->GetMotionMaster()->MoveFollow(temp,0,0); - - //spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok - summoned->CastSpell(summoned,SPELL_ENERGY_BOLT,false,0,0,me->GetGUID()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!Enraged) - { - //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25% - if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(INTERVAL_MODIFIER*IntervalHealthAmount))) - { - //increase amount, unless we're at 10%, then we switch and return - if (IntervalHealthAmount == INTERVAL_SWITCH) - { - Enraged = true; - return; - } - else - ++IntervalHealthAmount; - - DoScriptText(SAY_ENERGY, me); - DoScriptText(EMOTE_DISCHARGE_ENERGY, me); - - if (IsHeroic()) - { - DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false); - DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false); - } - else - DoCast(me, SPELL_SUMMON_PURE_ENERGY, false); - - //below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core - me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (IsHeroic()) - me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - } - - if (ChainLightningTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - - ChainLightningTimer = 8000; - } else ChainLightningTimer -= diff; - - if (ArcaneShockTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - if (pTarget) - DoCast(pTarget, SPELL_ARCANE_SHOCK); - - ArcaneShockTimer = 8000; - } else ArcaneShockTimer -= diff; - } - else - { - if (OverloadTimer <= diff) - { - DoCast(me->getVictim(), SPELL_OVERLOAD); - - OverloadTimer = 2000; - } else OverloadTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vexallus(Creature* pCreature) -{ - return new boss_vexallusAI (pCreature); -}; - -struct mob_pure_energyAI : public ScriptedAI -{ - mob_pure_energyAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - - void JustDied(Unit* slayer) - { - if (Unit *temp = me->GetOwner()) - { - if (temp && temp->isAlive()) - slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID()); - } - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - void AttackStart(Unit * /*who*/) {} -}; - -CreatureAI* GetAI_mob_pure_energy(Creature* pCreature) -{ - return new mob_pure_energyAI (pCreature); -}; - -void AddSC_boss_vexallus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_vexallus"; - newscript->GetAI = &GetAI_boss_vexallus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_pure_energy"; - newscript->GetAI = &GetAI_mob_pure_energy; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp b/src/server/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp deleted file mode 100644 index 455c03739bc..00000000000 --- a/src/server/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Magisters_Terrace -SD%Complete: 60 -SDComment: Designed only for Selin Fireheart -SDCategory: Magister's Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" - -#define MAX_ENCOUNTER 4 - -/* -0 - Selin Fireheart -1 - Vexallus -2 - Priestess Delrissa -3 - Kael'thas Sunstrider -*/ - -struct instance_magisters_terrace : public ScriptedInstance -{ - instance_magisters_terrace(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 DelrissaDeathCount; - - std::list FelCrystals; - std::list::const_iterator CrystalItr; - - uint64 SelinGUID; - uint64 DelrissaGUID; - uint64 VexallusDoorGUID; - uint64 SelinDoorGUID; - uint64 SelinEncounterDoorGUID; - uint64 DelrissaDoorGUID; - uint64 KaelDoorGUID; - uint64 KaelStatue[2]; - - bool InitializedItr; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - FelCrystals.clear(); - - DelrissaDeathCount = 0; - - SelinGUID = 0; - DelrissaGUID = 0; - VexallusDoorGUID = 0; - SelinDoorGUID = 0; - SelinEncounterDoorGUID = 0; - DelrissaDoorGUID = 0; - KaelDoorGUID = 0; - KaelStatue[0] = 0; - KaelStatue[1] = 0; - - InitializedItr = false; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - return false; - } - - uint32 GetData(uint32 identifier) - { - switch(identifier) - { - case DATA_SELIN_EVENT: return m_auiEncounter[0]; - case DATA_VEXALLUS_EVENT: return m_auiEncounter[1]; - case DATA_DELRISSA_EVENT: return m_auiEncounter[2]; - case DATA_KAELTHAS_EVENT: return m_auiEncounter[3]; - case DATA_DELRISSA_DEATH_COUNT: return DelrissaDeathCount; - case DATA_FEL_CRYSTAL_SIZE: return FelCrystals.size(); - } - return 0; - } - - void SetData(uint32 identifier, uint32 data) - { - switch(identifier) - { - case DATA_SELIN_EVENT: m_auiEncounter[0] = data; break; - case DATA_VEXALLUS_EVENT: - if (data == DONE) - DoUseDoorOrButton(VexallusDoorGUID); - m_auiEncounter[1] = data; - break; - case DATA_DELRISSA_EVENT: - if (data == DONE) - DoUseDoorOrButton(DelrissaDoorGUID); - if (data == IN_PROGRESS) - DelrissaDeathCount = 0; - m_auiEncounter[2] = data; - break; - case DATA_KAELTHAS_EVENT: m_auiEncounter[3] = data; break; - - case DATA_DELRISSA_DEATH_COUNT: - if (data == SPECIAL) - ++DelrissaDeathCount; - else - DelrissaDeathCount = 0; - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 24723: SelinGUID = pCreature->GetGUID(); break; - case 24560: DelrissaGUID = pCreature->GetGUID(); break; - case 24722: FelCrystals.push_back(pCreature->GetGUID()); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 187896: VexallusDoorGUID = pGo->GetGUID(); break; - //SunwellRaid Gate 02 - case 187979: SelinDoorGUID = pGo->GetGUID(); break; - //Assembly Chamber Door - case 188065: SelinEncounterDoorGUID = pGo->GetGUID(); break; - case 187770: DelrissaDoorGUID = pGo->GetGUID(); break; - case 188064: KaelDoorGUID = pGo->GetGUID(); break; - case 188165: KaelStatue[0] = pGo->GetGUID(); break; - case 188166: KaelStatue[1] = pGo->GetGUID(); break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_SELIN: return SelinGUID; - case DATA_DELRISSA: return DelrissaGUID; - case DATA_VEXALLUS_DOOR: return VexallusDoorGUID; - case DATA_SELIN_DOOR: return SelinDoorGUID; - case DATA_SELIN_ENCOUNTER_DOOR: return SelinEncounterDoorGUID; - case DATA_DELRISSA_DOOR: return DelrissaDoorGUID; - case DATA_KAEL_DOOR: return KaelDoorGUID; - case DATA_KAEL_STATUE_LEFT: return KaelStatue[0]; - case DATA_KAEL_STATUE_RIGHT: return KaelStatue[1]; - - case DATA_FEL_CRYSTAL: - { - if (FelCrystals.empty()) - { - error_log("TSCR: Magisters Terrace: No Fel Crystals loaded in Inst Data"); - return 0; - } - - if (!InitializedItr) - { - CrystalItr = FelCrystals.begin(); - InitializedItr = true; - } - - uint64 guid = *CrystalItr; - ++CrystalItr; - return guid; - } - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_magisters_terrace(Map* pMap) -{ - return new instance_magisters_terrace(pMap); -} - -void AddSC_instance_magisters_terrace() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_magisters_terrace"; - newscript->GetInstanceData = &GetInstanceData_instance_magisters_terrace; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp b/src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp deleted file mode 100644 index e46da9cb1bf..00000000000 --- a/src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Magisters_Terrace -SD%Complete: 100 -SDComment: Quest support: 11490(post-event) -SDCategory: Magisters Terrace -EndScriptData */ - -/* ContentData -npc_kalecgos -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_kalecgos -######*/ - -enum eEnums -{ - SPELL_TRANSFORM_TO_KAEL = 44670, - SPELL_ORB_KILL_CREDIT = 46307, - NPC_KAEL = 24848, //human form entry - POINT_ID_LAND = 1 -}; - -const float afKaelLandPoint[] = {225.045, -276.236, -5.434}; - -#define GOSSIP_ITEM_KAEL_1 "Who are you?" -#define GOSSIP_ITEM_KAEL_2 "What can we do to assist you?" -#define GOSSIP_ITEM_KAEL_3 "What brings you to the Sunwell?" -#define GOSSIP_ITEM_KAEL_4 "You're not alone here?" -#define GOSSIP_ITEM_KAEL_5 "What would Kil'jaeden want with a mortal woman?" - -// This is friendly keal that appear after used Orb. -// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is -struct npc_kalecgosAI : public ScriptedAI -{ - npc_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 m_uiTransformTimer; - - void Reset() - { - m_uiTransformTimer = 0; - - // we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here - if (me->GetEntry() != NPC_KAEL) - me->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]); - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (uiPointId == POINT_ID_LAND) - m_uiTransformTimer = MINUTE*IN_MILISECONDS; - } - - // some targeting issues with the spell, so use this workaround as temporary solution - void DoWorkaroundForQuestCredit() - { - Map* pMap = me->GetMap(); - - if (!pMap || pMap->IsHeroic()) - return; - - Map::PlayerList const &lList = pMap->GetPlayers(); - - if (lList.isEmpty()) - return; - - SpellEntry const* pSpell = GetSpellStore()->LookupEntry(SPELL_ORB_KILL_CREDIT); - - for (Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pSpell && pSpell->EffectMiscValue[0]) - pPlayer->KilledMonsterCredit(pSpell->EffectMiscValue[0], 0); - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_uiTransformTimer) - { - if (m_uiTransformTimer <= uiDiff) - { - DoCast(me, SPELL_ORB_KILL_CREDIT, false); - DoWorkaroundForQuestCredit(); - - // Transform and update entry, now ready for quest/read gossip - DoCast(me, SPELL_TRANSFORM_TO_KAEL, false); - me->UpdateEntry(NPC_KAEL); - - m_uiTransformTimer = 0; - } else m_uiTransformTimer -= uiDiff; - } - } -}; - -CreatureAI* GetAI_npc_kalecgos(Creature* pCreature) -{ - return new npc_kalecgosAI(pCreature); -} - -bool GossipHello_npc_kalecgos(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(12498, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_kalecgos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(12500, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(12502, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(12606, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(12607, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->SEND_GOSSIP_MENU(12608, pCreature->GetGUID()); - break; - } - - return true; -} - -void AddSC_magisters_terrace() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_kalecgos"; - newscript->GetAI = &GetAI_npc_kalecgos; - newscript->pGossipHello = &GossipHello_npc_kalecgos; - newscript->pGossipSelect = &GossipSelect_npc_kalecgos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h b/src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h deleted file mode 100644 index d6419ea409c..00000000000 --- a/src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_MAGISTERS_TERRACE_H -#define DEF_MAGISTERS_TERRACE_H - -#define DATA_SELIN_EVENT 1 -#define DATA_VEXALLUS_EVENT 2 -#define DATA_DELRISSA_EVENT 3 -#define DATA_KAELTHAS_EVENT 4 - -#define DATA_SELIN 5 -#define DATA_FEL_CRYSTAL 6 -#define DATA_FEL_CRYSTAL_SIZE 7 - -#define DATA_VEXALLUS_DOOR 8 -#define DATA_SELIN_DOOR 9 -#define DATA_DELRISSA 10 -#define DATA_DELRISSA_DOOR 11 -#define DATA_SELIN_ENCOUNTER_DOOR 12 - -#define DATA_KAEL_DOOR 13 -#define DATA_KAEL_STATUE_LEFT 14 -#define DATA_KAEL_STATUE_RIGHT 15 - -#define DATA_DELRISSA_DEATH_COUNT 16 - -#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy." -#endif - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp deleted file mode 100644 index 77c6fafa10a..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Baron_Geddon -SD%Complete: 100 -SDComment: -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_SERVICE -1409000 - -#define SPELL_INFERNO 19695 -#define SPELL_IGNITEMANA 19659 -#define SPELL_LIVINGBOMB 20475 -#define SPELL_ARMAGEDDOM 20479 - -struct boss_baron_geddonAI : public ScriptedAI -{ - boss_baron_geddonAI(Creature *c) : ScriptedAI(c) {} - - uint32 Inferno_Timer; - uint32 IgniteMana_Timer; - uint32 LivingBomb_Timer; - - void Reset() - { - Inferno_Timer = 45000; //These times are probably wrong - IgniteMana_Timer = 30000; - LivingBomb_Timer = 35000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <2% hp cast Armageddom - if (me->GetHealth()*100 / me->GetMaxHealth() <= 2) - { - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_ARMAGEDDOM); - DoScriptText(EMOTE_SERVICE, me); - return; - } - - //Inferno_Timer - if (Inferno_Timer <= diff) - { - DoCast(me, SPELL_INFERNO); - Inferno_Timer = 45000; - } else Inferno_Timer -= diff; - - //IgniteMana_Timer - if (IgniteMana_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_IGNITEMANA); - - IgniteMana_Timer = 30000; - } else IgniteMana_Timer -= diff; - - //LivingBomb_Timer - if (LivingBomb_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LIVINGBOMB); - - LivingBomb_Timer = 35000; - } else LivingBomb_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_baron_geddon(Creature* pCreature) -{ - return new boss_baron_geddonAI (pCreature); -} - -void AddSC_boss_baron_geddon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_baron_geddon"; - newscript->GetAI = &GetAI_boss_baron_geddon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_garr.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_garr.cpp deleted file mode 100644 index 75891cf8c43..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_garr.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Garr -SD%Complete: 50 -SDComment: Adds NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -// Garr spells -#define SPELL_ANTIMAGICPULSE 19492 -#define SPELL_MAGMASHACKLES 19496 -#define SPELL_ENRAGE 19516 //Stacking enrage (stacks to 10 times) - -//Add spells -#define SPELL_ERUPTION 19497 -#define SPELL_IMMOLATE 20294 - -struct boss_garrAI : public ScriptedAI -{ - boss_garrAI(Creature *c) : ScriptedAI(c) {} - - uint32 AntiMagicPulse_Timer; - uint32 MagmaShackles_Timer; - uint32 CheckAdds_Timer; - uint64 Add[8]; - bool Enraged[8]; - - void Reset() - { - AntiMagicPulse_Timer = 25000; //These times are probably wrong - MagmaShackles_Timer = 15000; - CheckAdds_Timer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //AntiMagicPulse_Timer - if (AntiMagicPulse_Timer <= diff) - { - DoCast(me, SPELL_ANTIMAGICPULSE); - AntiMagicPulse_Timer = 10000 + rand()%5000; - } else AntiMagicPulse_Timer -= diff; - - //MagmaShackles_Timer - if (MagmaShackles_Timer <= diff) - { - DoCast(me, SPELL_MAGMASHACKLES); - MagmaShackles_Timer = 8000 + rand()%4000; - } else MagmaShackles_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_fireswornAI : public ScriptedAI -{ - mob_fireswornAI(Creature *c) : ScriptedAI(c) {} - - uint32 Immolate_Timer; - - void Reset() - { - Immolate_Timer = 4000; //These times are probably wrong - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_IMMOLATE); - - Immolate_Timer = urand(5000,10000); - } else Immolate_Timer -= diff; - - //Cast Erruption and let them die - if (me->GetHealth() <= me->GetMaxHealth() * 0.10) - { - DoCast(me->getVictim(), SPELL_ERUPTION); - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_garr(Creature* pCreature) -{ - return new boss_garrAI (pCreature); -} - -CreatureAI* GetAI_mob_firesworn(Creature* pCreature) -{ - return new mob_fireswornAI (pCreature); -} - -void AddSC_boss_garr() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_garr"; - newscript->GetAI = &GetAI_boss_garr; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_firesworn"; - newscript->GetAI = &GetAI_mob_firesworn; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp deleted file mode 100644 index 9ebe69c0c4e..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gehennas -SD%Complete: 90 -SDComment: Adds MC NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWBOLT 19728 -#define SPELL_RAINOFFIRE 19717 -#define SPELL_GEHENNASCURSE 19716 - -struct boss_gehennasAI : public ScriptedAI -{ - boss_gehennasAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowBolt_Timer; - uint32 RainOfFire_Timer; - uint32 GehennasCurse_Timer; - - void Reset() - { - ShadowBolt_Timer = 6000; - RainOfFire_Timer = 10000; - GehennasCurse_Timer = 12000; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - DoCast(pTarget, SPELL_SHADOWBOLT); - - ShadowBolt_Timer = 7000; - } else ShadowBolt_Timer -= diff; - - //RainOfFire_Timer - if (RainOfFire_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_RAINOFFIRE); - - RainOfFire_Timer = urand(4000,12000); - } else RainOfFire_Timer -= diff; - - //GehennasCurse_Timer - if (GehennasCurse_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GEHENNASCURSE); - GehennasCurse_Timer = urand(22000,30000); - } else GehennasCurse_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gehennas(Creature* pCreature) -{ - return new boss_gehennasAI (pCreature); -} - -void AddSC_boss_gehennas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gehennas"; - newscript->GetAI = &GetAI_boss_gehennas; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp deleted file mode 100644 index 2aba378d399..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Golemagg -SD%Complete: 90 -SDComment: Timers need to be confirmed, Golemagg's Trust need to be checked -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" -#include "molten_core.h" - -enum eEnums -{ - SPELL_MAGMASPLASH = 13879, - SPELL_PYROBLAST = 20228, - SPELL_EARTHQUAKE = 19798, - SPELL_ENRAGE = 19953, - SPELL_GOLEMAGG_TRUST = 20553, - - // Core Rager - EMOTE_LOWHP = -1409002, - SPELL_MANGLE = 19820 -}; - -struct boss_golemaggAI : public ScriptedAI -{ - boss_golemaggAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiPyroblastTimer; - uint32 m_uiEarthquakeTimer; - uint32 m_uiBuffTimer; - bool m_bEnraged; - - void Reset() - { - m_uiPyroblastTimer = 7*IN_MILISECONDS; // These timers are probably wrong - m_uiEarthquakeTimer = 3*IN_MILISECONDS; - m_uiBuffTimer = 2.5*IN_MILISECONDS; - m_bEnraged = false; - - DoCast(me, SPELL_MAGMASPLASH, true); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance) - m_pInstance->SetData(DATA_GOLEMAGG_DEATH, 0); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //Pyroblast - if (m_uiPyroblastTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_PYROBLAST); - - m_uiPyroblastTimer = 7*IN_MILISECONDS; - } - else - m_uiPyroblastTimer -= uiDiff; - - // Enrage - if (!m_bEnraged && me->GetHealth()*100 < me->GetMaxHealth()*10) - { - DoCast(me, SPELL_ENRAGE); - m_bEnraged = true; - } - - // Earthquake - if (m_bEnraged) - { - if (m_uiEarthquakeTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_EARTHQUAKE); - m_uiEarthquakeTimer = 3*IN_MILISECONDS; - } - else - m_uiEarthquakeTimer -= uiDiff; - } - - /* - // Golemagg's Trust - if (m_uiBuffTimer <= uidiff) - { - DoCast(me, SPELL_GOLEMAGG_TRUST); - m_uiBuffTimer = 2.5*IN_MILISECONDS; - } - else - m_uiBuffTimer -= uiDiff; - */ - - DoMeleeAttackIfReady(); - } -}; - -struct mob_core_ragerAI : public ScriptedAI -{ - mob_core_ragerAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiMangleTimer; - - void Reset() - { - m_uiMangleTimer = 7*IN_MILISECONDS; // These times are probably wrong - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) - { - if (me->GetHealth()*100 < me->GetMaxHealth()*50) - { - if (m_pInstance) - { - if (Creature* pGolemagg = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_GOLEMAGG))) - { - if (pGolemagg->isAlive()) - { - DoScriptText(EMOTE_LOWHP, me); - me->SetHealth(me->GetMaxHealth()); - } - else - uiDamage = me->GetHealth(); - } - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - // Mangle - if (m_uiMangleTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MANGLE); - m_uiMangleTimer = 10*IN_MILISECONDS; - } - else - m_uiMangleTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_golemagg(Creature* pCreature) -{ - return new boss_golemaggAI (pCreature); -} - -CreatureAI* GetAI_mob_core_rager(Creature* pCreature) -{ - return new mob_core_ragerAI (pCreature); -} - -void AddSC_boss_golemagg() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_golemagg"; - newscript->GetAI = &GetAI_boss_golemagg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_core_rager"; - newscript->GetAI = &GetAI_mob_core_rager; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp deleted file mode 100644 index 50601f04147..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Lucifron -SD%Complete: 100 -SDComment: -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_IMPENDINGDOOM 19702 -#define SPELL_LUCIFRONCURSE 19703 -#define SPELL_SHADOWSHOCK 20603 - -struct boss_lucifronAI : public ScriptedAI -{ - boss_lucifronAI(Creature *c) : ScriptedAI(c) {} - - uint32 ImpendingDoom_Timer; - uint32 LucifronCurse_Timer; - uint32 ShadowShock_Timer; - - void Reset() - { - ImpendingDoom_Timer = 10000; //Initial cast after 10 seconds so the debuffs alternate - LucifronCurse_Timer = 20000; //Initial cast after 20 seconds - ShadowShock_Timer = 6000; //6 seconds - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Impending doom timer - if (ImpendingDoom_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_IMPENDINGDOOM); - ImpendingDoom_Timer = 20000; - } else ImpendingDoom_Timer -= diff; - - //Lucifron's curse timer - if (LucifronCurse_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LUCIFRONCURSE); - LucifronCurse_Timer = 15000; - } else LucifronCurse_Timer -= diff; - - //Shadowshock - if (ShadowShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWSHOCK); - ShadowShock_Timer = 6000; - } else ShadowShock_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_lucifron(Creature* pCreature) -{ - return new boss_lucifronAI (pCreature); -} - -void AddSC_boss_lucifron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lucifron"; - newscript->GetAI = &GetAI_boss_lucifron; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp deleted file mode 100644 index f612003b076..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Magmadar -SD%Complete: 75 -SDComment: Conflag on ground nyi, fear causes issues without VMAPs -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_FRENZY -1409001 - -#define SPELL_FRENZY 19451 -#define SPELL_MAGMASPIT 19449 //This is actually a buff he gives himself -#define SPELL_PANIC 19408 -#define SPELL_LAVABOMB 19411 //This calls a dummy server side effect that isn't implemented yet -#define SPELL_LAVABOMB_ALT 19428 //This is the spell that the lava bomb casts - -struct boss_magmadarAI : public ScriptedAI -{ - boss_magmadarAI(Creature *c) : ScriptedAI(c) {} - - uint32 Frenzy_Timer; - uint32 Panic_Timer; - uint32 Lavabomb_Timer; - - void Reset() - { - Frenzy_Timer = 30000; - Panic_Timer = 20000; - Lavabomb_Timer = 12000; - - DoCast(me, SPELL_MAGMASPIT, true); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Frenzy_Timer - if (Frenzy_Timer <= diff) - { - DoScriptText(EMOTE_FRENZY, me); - DoCast(me, SPELL_FRENZY); - Frenzy_Timer = 15000; - } else Frenzy_Timer -= diff; - - //Panic_Timer - if (Panic_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PANIC); - Panic_Timer = 35000; - } else Panic_Timer -= diff; - - //Lavabomb_Timer - if (Lavabomb_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LAVABOMB_ALT); - - Lavabomb_Timer = 12000; - } else Lavabomb_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_magmadar(Creature* pCreature) -{ - return new boss_magmadarAI (pCreature); -} - -void AddSC_boss_magmadar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magmadar"; - newscript->GetAI = &GetAI_boss_magmadar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp deleted file mode 100644 index 11ae70befcf..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Majordomo_Executus -SD%Complete: 30 -SDComment: Correct spawning and Event NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1409003 -#define SAY_SPAWN -1409004 -#define SAY_SLAY -1409005 -#define SAY_SPECIAL -1409006 -#define SAY_DEFEAT -1409007 - -#define SAY_SUMMON_MAJ -1409008 -#define SAY_ARRIVAL1_RAG -1409009 -#define SAY_ARRIVAL2_MAJ -1409010 -#define SAY_ARRIVAL3_RAG -1409011 -#define SAY_ARRIVAL5_RAG -1409012 - -#define SPAWN_RAG_X 838.51 -#define SPAWN_RAG_Y -829.84 -#define SPAWN_RAG_Z -232.00 -#define SPAWN_RAG_O 1.70 - -#define SPELL_MAGIC_REFLECTION 20619 -#define SPELL_DAMAGE_REFLECTION 21075 - -#define SPELL_BLASTWAVE 20229 -#define SPELL_AEGIS 20620 //This is self casted whenever we are below 50% -#define SPELL_TELEPORT 20618 -#define SPELL_SUMMON_RAGNAROS 19774 - -#define ENTRY_FLAMEWALKER_HEALER 11663 -#define ENTRY_FLAMEWALKER_ELITE 11664 - -struct boss_majordomoAI : public ScriptedAI -{ - boss_majordomoAI(Creature *c) : ScriptedAI(c) {} - - uint32 MagicReflection_Timer; - uint32 DamageReflection_Timer; - uint32 Blastwave_Timer; - - void Reset() - { - MagicReflection_Timer = 30000; //Damage reflection first so we alternate - DamageReflection_Timer = 15000; - Blastwave_Timer = 10000; - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%5) - return; - - DoScriptText(SAY_SLAY, me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Cast Ageis if less than 50% hp - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - DoCast(me, SPELL_AEGIS); - } - - //MagicReflection_Timer - // if (MagicReflection_Timer <= diff) - // { - // DoCast(me, SPELL_MAGICREFLECTION); - - //60 seconds until we should cast this agian - // MagicReflection_Timer = 30000; - // } else MagicReflection_Timer -= diff; - - //DamageReflection_Timer - // if (DamageReflection_Timer <= diff) - // { - // DoCast(me, SPELL_DAMAGEREFLECTION); - - //60 seconds until we should cast this agian - // DamageReflection_Timer = 30000; - // } else DamageReflection_Timer -= diff; - - //Blastwave_Timer - if (Blastwave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLASTWAVE); - Blastwave_Timer = 10000; - } else Blastwave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_majordomo(Creature* pCreature) -{ - return new boss_majordomoAI (pCreature); -} - -void AddSC_boss_majordomo() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_majordomo"; - newscript->GetAI = &GetAI_boss_majordomo; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp deleted file mode 100644 index 71c0b40de3f..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ragnaros -SD%Complete: 75 -SDComment: Intro Dialog and event NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_REINFORCEMENTS1 -1409013 -#define SAY_REINFORCEMENTS2 -1409014 -#define SAY_HAND -1409015 -#define SAY_WRATH -1409016 -#define SAY_KILL -1409017 -#define SAY_MAGMABURST -1409018 - -#define SPELL_HANDOFRAGNAROS 19780 -#define SPELL_WRATHOFRAGNAROS 20566 -#define SPELL_LAVABURST 21158 - -#define SPELL_MAGMABURST 20565 //Ranged attack - -#define SPELL_SONSOFFLAME_DUMMY 21108 //Server side effect -#define SPELL_RAGSUBMERGE 21107 //Stealth aura -#define SPELL_RAGEMERGE 20568 -#define SPELL_MELTWEAPON 21388 -#define SPELL_ELEMENTALFIRE 20564 -#define SPELL_ERRUPTION 17731 - -#define ADD_1X 848.740356 -#define ADD_1Y -816.103455 -#define ADD_1Z -229.74327 -#define ADD_1O 2.615287 - -#define ADD_2X 852.560791 -#define ADD_2Y -849.861511 -#define ADD_2Z -228.560974 -#define ADD_2O 2.836073 - -#define ADD_3X 808.710632 -#define ADD_3Y -852.845764 -#define ADD_3Z -227.914963 -#define ADD_3O 0.964207 - -#define ADD_4X 786.597107 -#define ADD_4Y -821.132874 -#define ADD_4Z -226.350128 -#define ADD_4O 0.949377 - -#define ADD_5X 796.219116 -#define ADD_5Y -800.948059 -#define ADD_5Z -226.010361 -#define ADD_5O 0.560603 - -#define ADD_6X 821.602539 -#define ADD_6Y -782.744109 -#define ADD_6Z -226.023575 -#define ADD_6O 6.157440 - -#define ADD_7X 844.924744 -#define ADD_7Y -769.453735 -#define ADD_7Z -225.521698 -#define ADD_7O 4.4539958 - -#define ADD_8X 839.823364 -#define ADD_8Y -810.869385 -#define ADD_8Z -229.683182 -#define ADD_8O 4.693108 - -struct boss_ragnarosAI : public ScriptedAI -{ - boss_ragnarosAI(Creature *c) : ScriptedAI(c) - { - SetCombatMovement(false); - } - - uint32 WrathOfRagnaros_Timer; - uint32 HandOfRagnaros_Timer; - uint32 LavaBurst_Timer; - uint32 MagmaBurst_Timer; - uint32 ElementalFire_Timer; - uint32 Erruption_Timer; - uint32 Submerge_Timer; - uint32 Attack_Timer; - - bool HasYelledMagmaBurst; - bool HasSubmergedOnce; - bool WasBanished; - bool HasAura; - - void Reset() - { - WrathOfRagnaros_Timer = 30000; - HandOfRagnaros_Timer = 25000; - LavaBurst_Timer = 10000; - MagmaBurst_Timer = 2000; - Erruption_Timer = 15000; - ElementalFire_Timer = 3000; - Submerge_Timer = 180000; - Attack_Timer = 90000; - HasYelledMagmaBurst = false; - HasSubmergedOnce = false; - WasBanished = false; - - DoCast(me, SPELL_MELTWEAPON, true); - HasAura = true; - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%5) - return; - - DoScriptText(SAY_KILL, me); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (WasBanished && Attack_Timer <= diff) - { - //Become unbanished again - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_RAGEMERGE); - WasBanished = false; - } else if (WasBanished) - { - Attack_Timer -= diff; - //Do nothing while banished - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //WrathOfRagnaros_Timer - if (WrathOfRagnaros_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WRATHOFRAGNAROS); - - if (urand(0,1)) - DoScriptText(SAY_WRATH, me); - - WrathOfRagnaros_Timer = 30000; - } else WrathOfRagnaros_Timer -= diff; - - //HandOfRagnaros_Timer - if (HandOfRagnaros_Timer <= diff) - { - DoCast(me, SPELL_HANDOFRAGNAROS); - - if (urand(0,1)) - DoScriptText(SAY_HAND, me); - - HandOfRagnaros_Timer = 25000; - } else HandOfRagnaros_Timer -= diff; - - //LavaBurst_Timer - if (LavaBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LAVABURST); - LavaBurst_Timer = 10000; - } else LavaBurst_Timer -= diff; - - //Erruption_Timer - if (LavaBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ERRUPTION); - Erruption_Timer = urand(20000,45000); - } else Erruption_Timer -= diff; - - //ElementalFire_Timer - if (ElementalFire_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ELEMENTALFIRE); - ElementalFire_Timer = urand(10000,14000); - } else ElementalFire_Timer -= diff; - - //Submerge_Timer - if (!WasBanished && Submerge_Timer <= diff) - { - //Creature spawning and ragnaros becomming unattackable - //is not very well supported in the core - //so added normaly spawning and banish workaround and attack again after 90 secs. - - me->InterruptNonMeleeSpells(false); - //Root self - DoCast(me, 23973); - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); - - if (!HasSubmergedOnce) - { - DoScriptText(SAY_REINFORCEMENTS1, me); - - // summon 10 elementals - for (uint8 i = 0; i < 9; ++i) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (Creature* pSummoned = me->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000)) - pSummoned->AI()->AttackStart(pTarget); - } - } - - HasSubmergedOnce = true; - WasBanished = true; - DoCast(me, SPELL_RAGSUBMERGE); - Attack_Timer = 90000; - - } - else - { - DoScriptText(SAY_REINFORCEMENTS2, me); - - for (uint8 i = 0; i < 9; ++i) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (Creature* pSummoned = me->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000)) - pSummoned->AI()->AttackStart(pTarget); - } - } - - WasBanished = true; - DoCast(me, SPELL_RAGSUBMERGE); - Attack_Timer = 90000; - } - - Submerge_Timer = 180000; - } else Submerge_Timer -= diff; - - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - //Make sure our attack is ready and we arn't currently casting - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - else - { - //MagmaBurst_Timer - if (MagmaBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MAGMABURST); - - if (!HasYelledMagmaBurst) - { - //Say our dialog - DoScriptText(SAY_MAGMABURST, me); - HasYelledMagmaBurst = true; - } - - MagmaBurst_Timer = 2500; - } else MagmaBurst_Timer -= diff; - } - } -}; -CreatureAI* GetAI_boss_ragnaros(Creature* pCreature) -{ - return new boss_ragnarosAI (pCreature); -} - -void AddSC_boss_ragnaros() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ragnaros"; - newscript->GetAI = &GetAI_boss_ragnaros; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp deleted file mode 100644 index 4b0774cdc54..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Shazzrah -SD%Complete: 75 -SDComment: Teleport NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_ARCANEEXPLOSION 19712 -#define SPELL_SHAZZRAHCURSE 19713 -#define SPELL_DEADENMAGIC 19714 -#define SPELL_COUNTERSPELL 19715 - -struct boss_shazzrahAI : public ScriptedAI -{ - boss_shazzrahAI(Creature *c) : ScriptedAI(c) {} - - uint32 ArcaneExplosion_Timer; - uint32 ShazzrahCurse_Timer; - uint32 DeadenMagic_Timer; - uint32 Countspell_Timer; - uint32 Blink_Timer; - - void Reset() - { - ArcaneExplosion_Timer = 6000; //These times are probably wrong - ShazzrahCurse_Timer = 10000; - DeadenMagic_Timer = 24000; - Countspell_Timer = 15000; - Blink_Timer = 30000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANEEXPLOSION); - ArcaneExplosion_Timer = 5000 + rand()%4000; - } else ArcaneExplosion_Timer -= diff; - - //ShazzrahCurse_Timer - if (ShazzrahCurse_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_SHAZZRAHCURSE); - - ShazzrahCurse_Timer = 25000 + rand()%5000; - } else ShazzrahCurse_Timer -= diff; - - //DeadenMagic_Timer - if (DeadenMagic_Timer <= diff) - { - DoCast(me, SPELL_DEADENMAGIC); - DeadenMagic_Timer = 35000; - } else DeadenMagic_Timer -= diff; - - //Countspell_Timer - if (Countspell_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_COUNTERSPELL); - Countspell_Timer = 16000 + rand()%4000; - } else Countspell_Timer -= diff; - - //Blink_Timer - if (Blink_Timer <= diff) - { - // Teleporting him to a random gamer and casting Arcane Explosion after that. - // Blink is not working cause of LoS System we need to do this hardcoded. - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0, 100, true)) - { - DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); - DoCast(pTarget, SPELL_ARCANEEXPLOSION); - DoResetThreat(); - } - - Blink_Timer = 45000; - } else Blink_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_shazzrah(Creature* pCreature) -{ - return new boss_shazzrahAI (pCreature); -} - -void AddSC_boss_shazzrah() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shazzrah"; - newscript->GetAI = &GetAI_boss_shazzrah; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp b/src/server/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp deleted file mode 100644 index 83288fe003b..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Sulfuron_Harbringer -SD%Complete: 80 -SDComment: Adds NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" -#include "molten_core.h" - -#define SPELL_DARKSTRIKE 19777 -#define SPELL_DEMORALIZINGSHOUT 19778 -#define SPELL_INSPIRE 19779 -#define SPELL_KNOCKDOWN 19780 -#define SPELL_FLAMESPEAR 19781 - -//Adds Spells -#define SPELL_HEAL 19775 -#define SPELL_SHADOWWORDPAIN 19776 -#define SPELL_IMMOLATE 20294 - -struct boss_sulfuronAI : public ScriptedAI -{ - boss_sulfuronAI(Creature *c) : ScriptedAI(c) {} - - uint32 Darkstrike_Timer; - uint32 DemoralizingShout_Timer; - uint32 Inspire_Timer; - uint32 Knockdown_Timer; - uint32 Flamespear_Timer; - - void Reset() - { - Darkstrike_Timer=10000; //These times are probably wrong - DemoralizingShout_Timer = 15000; - Inspire_Timer = 13000; - Knockdown_Timer = 6000; - Flamespear_Timer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //DemoralizingShout_Timer - if (DemoralizingShout_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DEMORALIZINGSHOUT); - DemoralizingShout_Timer = 15000 + rand()%5000; - } else DemoralizingShout_Timer -= diff; - - //Inspire_Timer - if (Inspire_Timer <= diff) - { - Creature *pTarget = NULL; - std::list pList = DoFindFriendlyMissingBuff(45.0f,SPELL_INSPIRE); - if (!pList.empty()) - { - std::list::const_iterator i = pList.begin(); - advance(i, (rand()%pList.size())); - pTarget = (*i); - } - - if (pTarget) - DoCast(pTarget, SPELL_INSPIRE); - - DoCast(me, SPELL_INSPIRE); - - Inspire_Timer = 20000 + rand()%6000; - } else Inspire_Timer -= diff; - - //Knockdown_Timer - if (Knockdown_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - Knockdown_Timer = 12000 + rand()%3000; - } else Knockdown_Timer -= diff; - - //Flamespear_Timer - if (Flamespear_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_FLAMESPEAR); - - Flamespear_Timer = 12000 + rand()%4000; - } else Flamespear_Timer -= diff; - - //DarkStrike_Timer - if (Darkstrike_Timer <= diff) - { - DoCast(me, SPELL_DARKSTRIKE); - Darkstrike_Timer = 15000 + rand()%3000; - } else Darkstrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_flamewaker_priestAI : public ScriptedAI -{ - mob_flamewaker_priestAI(Creature *c) : ScriptedAI(c) {} - - uint32 Heal_Timer; - uint32 ShadowWordPain_Timer; - uint32 Immolate_Timer; - - void Reset() - { - Heal_Timer = 15000+rand()%15000; - ShadowWordPain_Timer = 2000; - Immolate_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Casting Heal to Sulfuron or other Guards. - if (Heal_Timer <= diff) - { - Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1); - if (!pUnit) - return; - - DoCast(pUnit, SPELL_HEAL); - - Heal_Timer = 15000+rand()%5000; - } else Heal_Timer -= diff; - - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_SHADOWWORDPAIN); - - ShadowWordPain_Timer = 18000+rand()%8000; - } else ShadowWordPain_Timer -= diff; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); - - Immolate_Timer = 15000+rand()%10000; - } else Immolate_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_sulfuron(Creature* pCreature) -{ - return new boss_sulfuronAI (pCreature); -} - -CreatureAI* GetAI_mob_flamewaker_priest(Creature* pCreature) -{ - return new mob_flamewaker_priestAI (pCreature); -} - -void AddSC_boss_sulfuron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sulfuron"; - newscript->GetAI = &GetAI_boss_sulfuron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flamewaker_priest"; - newscript->GetAI = &GetAI_mob_flamewaker_priest; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp b/src/server/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp deleted file mode 100644 index eb79c234134..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Molten_Core -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" -#include "molten_core.h" - -#define MAX_ENCOUNTER 9 - -#define ID_LUCIFRON 12118 -#define ID_MAGMADAR 11982 -#define ID_GEHENNAS 12259 -#define ID_GARR 12057 -#define ID_GEDDON 12056 -#define ID_SHAZZRAH 12264 -#define ID_GOLEMAGG 11988 -#define ID_SULFURON 12098 -#define ID_DOMO 12018 -#define ID_RAGNAROS 11502 -#define ID_FLAMEWAKERPRIEST 11662 - -struct instance_molten_core : public ScriptedInstance -{ - instance_molten_core(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 Lucifron, Magmadar, Gehennas, Garr, Geddon, Shazzrah, Sulfuron, Golemagg, Domo, Ragnaros, FlamewakerPriest; - uint64 RuneKoro, RuneZeth, RuneMazj, RuneTheri, RuneBlaz, RuneKress, RuneMohn, m_uiFirelordCacheGUID; - - //If all Bosses are dead. - bool IsBossDied[9]; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Lucifron = 0; - Magmadar = 0; - Gehennas = 0; - Garr = 0; - Geddon = 0; - Shazzrah = 0; - Sulfuron = 0; - Golemagg = 0; - Domo = 0; - Ragnaros = 0; - FlamewakerPriest = 0; - - RuneKoro = 0; - RuneZeth = 0; - RuneMazj = 0; - RuneTheri = 0; - RuneBlaz = 0; - RuneKress = 0; - RuneMohn = 0; - - m_uiFirelordCacheGUID = 0; - - IsBossDied[0] = false; - IsBossDied[1] = false; - IsBossDied[2] = false; - IsBossDied[3] = false; - IsBossDied[4] = false; - IsBossDied[5] = false; - IsBossDied[6] = false; - - IsBossDied[7] = false; - IsBossDied[8] = false; - } - - bool IsEncounterInProgress() const - { - return false; - }; - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 176951: //Sulfuron - RuneKoro = pGo->GetGUID(); - break; - case 176952: //Geddon - RuneZeth = pGo->GetGUID(); - break; - case 176953: //Shazzrah - RuneMazj = pGo->GetGUID(); - break; - case 176954: //Golemagg - RuneTheri = pGo->GetGUID(); - break; - case 176955: //Garr - RuneBlaz = pGo->GetGUID(); - break; - case 176956: //Magmadar - RuneKress = pGo->GetGUID(); - break; - case 176957: //Gehennas - RuneMohn = pGo->GetGUID(); - break; - case 179703: - m_uiFirelordCacheGUID = pGo->GetGUID(); //when majordomo event == DONE DoRespawnGameObject(m_uiFirelordCacheGUID,); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case ID_LUCIFRON: - Lucifron = pCreature->GetGUID(); - break; - - case ID_MAGMADAR: - Magmadar = pCreature->GetGUID(); - break; - - case ID_GEHENNAS: - Gehennas = pCreature->GetGUID(); - break; - - case ID_GARR: - Garr = pCreature->GetGUID(); - break; - - case ID_GEDDON: - Geddon = pCreature->GetGUID(); - break; - - case ID_SHAZZRAH: - Shazzrah = pCreature->GetGUID(); - break; - - case ID_SULFURON: - Sulfuron = pCreature->GetGUID(); - break; - - case ID_GOLEMAGG: - Golemagg = pCreature->GetGUID(); - break; - - case ID_DOMO: - Domo = pCreature->GetGUID(); - break; - - case ID_RAGNAROS: - Ragnaros = pCreature->GetGUID(); - break; - - case ID_FLAMEWAKERPRIEST: - FlamewakerPriest = pCreature->GetGUID(); - break; - } - } - - uint64 GetData64 (uint32 identifier) - { - switch(identifier) - { - case DATA_SULFURON: - return Sulfuron; - case DATA_GOLEMAGG: - return Golemagg; - - case DATA_FLAMEWAKERPRIEST: - return FlamewakerPriest; - } - - return 0; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_LUCIFRONISDEAD: - if (IsBossDied[0]) - return 1; - break; - - case DATA_MAGMADARISDEAD: - if (IsBossDied[1]) - return 1; - break; - - case DATA_GEHENNASISDEAD: - if (IsBossDied[2]) - return 1; - break; - - case DATA_GARRISDEAD: - if (IsBossDied[3]) - return 1; - break; - - case DATA_GEDDONISDEAD: - if (IsBossDied[4]) - return 1; - break; - - case DATA_SHAZZRAHISDEAD: - if (IsBossDied[5]) - return 1; - break; - - case DATA_SULFURONISDEAD: - if (IsBossDied[6]) - return 1; - break; - - case DATA_GOLEMAGGISDEAD: - if (IsBossDied[7]) - return 1; - break; - - case DATA_MAJORDOMOISDEAD: - if (IsBossDied[8]) - return 1; - break; - } - - return 0; - } - - void SetData(uint32 type, uint32 /*data*/) - { - if (type == DATA_GOLEMAGG_DEATH) - IsBossDied[7] = true; - } -}; - -InstanceData* GetInstance_instance_molten_core(Map* pMap) -{ - return new instance_molten_core (pMap); -} - -void AddSC_instance_molten_core() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_molten_core"; - newscript->GetInstanceData = &GetInstance_instance_molten_core; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/molten_core.cpp b/src/server/scripts/eastern_kingdoms/molten_core/molten_core.cpp deleted file mode 100644 index f8fe5bf1477..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/molten_core.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Molten_Core -SD%Complete: 100 -SDComment: -SDCategory: Molten Core -EndScriptData */ - -/* ContentData -mob_ancient_core_hound -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedSimpleAI.h" - -#define SPELL_CONE_OF_FIRE 19630 -#define SPELL_BITE 19771 - -//Random Debuff (each hound has only one of these) -#define SPELL_GROUND_STOMP 19364 -#define SPELL_ANCIENT_DREAD 19365 -#define SPELL_CAUTERIZING_FLAMES 19366 -#define SPELL_WITHERING_HEAT 19367 -#define SPELL_ANCIENT_DESPAIR 19369 -#define SPELL_ANCIENT_HYSTERIA 19372 - -CreatureAI* GetAI_mob_ancient_core_hound(Creature* pCreature) -{ - SimpleAI *ai = new SimpleAI(pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = SPELL_CONE_OF_FIRE; - ai->Spell[0].Cooldown = 7000; - ai->Spell[0].First_Cast = 10000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - uint32 RandDebuff = RAND(SPELL_GROUND_STOMP,SPELL_ANCIENT_DREAD,SPELL_CAUTERIZING_FLAMES, - SPELL_WITHERING_HEAT,SPELL_ANCIENT_DESPAIR,SPELL_ANCIENT_HYSTERIA); - - ai->Spell[1].Enabled = true; - ai->Spell[1].Spell_Id = RandDebuff; - ai->Spell[1].Cooldown = 24000; - ai->Spell[1].First_Cast = 15000; - ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->Spell[2].Enabled = true; - ai->Spell[2].Spell_Id = SPELL_BITE; - ai->Spell[2].Cooldown = 6000; - ai->Spell[2].First_Cast = 4000; - ai->Spell[2].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->EnterEvadeMode(); - - return ai; -} - -void AddSC_molten_core() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_ancient_core_hound"; - newscript->GetAI = &GetAI_mob_ancient_core_hound; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/molten_core/molten_core.h b/src/server/scripts/eastern_kingdoms/molten_core/molten_core.h deleted file mode 100644 index 5874d8b9408..00000000000 --- a/src/server/scripts/eastern_kingdoms/molten_core/molten_core.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_MOLTEN_CORE_H -#define DEF_MOLTEN_CORE_H - -#define DATA_FLAMEWAKERPRIEST 1 -#define DATA_GARRISDEAD 2 -#define DATA_GEDDONISDEAD 3 -#define DATA_GEHENNASISDEAD 4 -#define DATA_GOLEMAGGISDEAD 5 -#define DATA_GOLEMAGG_DEATH 6 -#define DATA_LUCIFRONISDEAD 7 -#define DATA_MAGMADARISDEAD 8 -#define DATA_MAJORDOMOISDEAD 9 -#define DATA_SHAZZRAHISDEAD 10 -#define DATA_SULFURON 11 -#define DATA_SULFURONISDEAD 12 -#define DATA_GOLEMAGG 13 -#endif - diff --git a/src/server/scripts/eastern_kingdoms/redridge_mountains.cpp b/src/server/scripts/eastern_kingdoms/redridge_mountains.cpp deleted file mode 100644 index 2f0b5821e86..00000000000 --- a/src/server/scripts/eastern_kingdoms/redridge_mountains.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Redridge Mountains -SD%Complete: 100% -SDComment: Support for quest 219. -Script Data End */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -enum eCorporalKeeshan -{ - QUEST_MISSING_IN_ACTION = 219, - - SAY_CORPORAL_1 = -1000464, - SAY_CORPORAL_2 = -1000465, - SAY_CORPORAL_3 = -1000466, - SAY_CORPORAL_4 = -1000467, - SAY_CORPORAL_5 = -1000468, - - SPELL_MOCKING_BLOW = 21008, - SPELL_SHIELD_BASH = 11972, -}; - -struct npc_corporal_keeshanAI : public npc_escortAI -{ - npc_corporal_keeshanAI(Creature* pCreature) : npc_escortAI(pCreature) {} - - uint32 uiPhase; - uint32 uiTimer; - uint32 uiMockingBlowTimer; - uint32 uiShieldBashTimer; - - void Reset() - { - uiTimer = 0; - uiPhase = 0; - uiMockingBlowTimer = 5000; - uiShieldBashTimer = 8000; - } - - void WaypointReached(uint32 uiI) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - if (uiI >= 65 && me->GetUnitMovementFlags() == MOVEMENTFLAG_WALK_MODE) - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - switch(uiI) - { - case 39: - SetEscortPaused(true); - uiTimer = 2000; - uiPhase = 1; - break; - case 65: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - break; - case 115: - pPlayer->AreaExploredOrEventHappens(QUEST_MISSING_IN_ACTION); - uiTimer = 2000; - uiPhase = 4; - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (HasEscortState(STATE_ESCORT_NONE)) - return; - - npc_escortAI::UpdateAI(uiDiff); - - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - me->SetStandState(UNIT_STAND_STATE_SIT); - uiTimer = 1000; - uiPhase = 2; - break; - case 2: - DoScriptText(SAY_CORPORAL_2,me); - uiTimer = 15000; - uiPhase = 3; - break; - case 3: - DoScriptText(SAY_CORPORAL_3,me); - me->SetStandState(UNIT_STAND_STATE_STAND); - SetEscortPaused(false); - uiTimer = 0; - uiPhase = 0; - break; - case 4: - DoScriptText(SAY_CORPORAL_4, me); - uiTimer = 2500; - uiPhase = 5; - case 5: - DoScriptText(SAY_CORPORAL_5, me); - uiTimer = 0; - uiPhase = 0; - } - } else uiTimer -= uiDiff; - } - - if (!UpdateVictim()) - return; - - if (uiMockingBlowTimer <= uiDiff) - { - DoCast(me->getVictim(),SPELL_MOCKING_BLOW); - uiMockingBlowTimer = 5000; - } else uiMockingBlowTimer -= uiDiff; - - if (uiShieldBashTimer <= uiDiff) - { - DoCast(me->getVictim(),SPELL_MOCKING_BLOW); - uiShieldBashTimer = 8000; - } else uiShieldBashTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -bool QuestAccept_npc_corporal_keeshan(Player* pPlayer, Creature* pCreature, Quest const *pQuest) -{ - if (pQuest->GetQuestId() == QUEST_MISSING_IN_ACTION) - { - CAST_AI(npc_corporal_keeshanAI,pCreature->AI())->Start(true, false, pPlayer->GetGUID(),pQuest); - DoScriptText(SAY_CORPORAL_1, pCreature); - } - - return false; -} - -CreatureAI* GetAI_npc_corporal_keeshan(Creature* pCreature) -{ - return new npc_corporal_keeshanAI(pCreature); -} - -void AddSC_redridge_mountains() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_corporal_keeshan"; - newscript->GetAI = &GetAI_npc_corporal_keeshan; - newscript->pQuestAccept = &QuestAccept_npc_corporal_keeshan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter1.cpp b/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter1.cpp deleted file mode 100644 index bdbf6b7c081..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter1.cpp +++ /dev/null @@ -1,1079 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "Vehicle.h" -#include "ObjectMgr.h" -#include "ScriptedEscortAI.h" - -/*###### -##Quest 12848 -######*/ - -#define GCD_CAST 1 - -enum eDeathKnightSpells -{ - SPELL_SOUL_PRISON_CHAIN_SELF = 54612, - SPELL_SOUL_PRISON_CHAIN = 54613, - SPELL_DK_INITIATE_VISUAL = 51519, - - SPELL_ICY_TOUCH = 52372, - SPELL_PLAGUE_STRIKE = 52373, - SPELL_BLOOD_STRIKE = 52374, - SPELL_DEATH_COIL = 52375 -}; - -#define EVENT_ICY_TOUCH 1 -#define EVENT_PLAGUE_STRIKE 2 -#define EVENT_BLOOD_STRIKE 3 -#define EVENT_DEATH_COIL 4 - -//used by 29519,29520,29565,29566,29567 but signed for 29519 -int32 say_event_start[8] = -{ - -1609000,-1609001,-1609002,-1609003, - -1609004,-1609005,-1609006,-1609007 -}; - -int32 say_event_attack[9] = -{ - -1609008,-1609009,-1609010,-1609011,-1609012, - -1609013,-1609014,-1609015,-1609016 -}; - -uint32 acherus_soul_prison[12] = -{ - 191577, - 191580, - 191581, - 191582, - 191583, - 191584, - 191585, - 191586, - 191587, - 191588, - 191589, - 191590 -}; - -uint32 acherus_unworthy_initiate[5] = -{ - 29519, - 29520, - 29565, - 29566, - 29567 -}; - -enum UnworthyInitiatePhase -{ - PHASE_CHAINED, - PHASE_TO_EQUIP, - PHASE_EQUIPING, - PHASE_TO_ATTACK, - PHASE_ATTACKING, -}; - -struct npc_unworthy_initiateAI : public ScriptedAI -{ - npc_unworthy_initiateAI(Creature *c) : ScriptedAI(c) - { - me->SetReactState(REACT_PASSIVE); - if (!me->GetEquipmentId()) - if (const CreatureInfo *info = GetCreatureInfo(28406)) - if (info->equipmentId) - const_cast(me->GetCreatureInfo())->equipmentId = info->equipmentId; - } - - uint64 playerGUID; - UnworthyInitiatePhase phase; - uint32 wait_timer; - float anchorX, anchorY; - uint64 anchorGUID; - - EventMap events; - - void Reset() - { - anchorGUID = 0; - phase = PHASE_CHAINED; - events.Reset(); - me->setFaction(7); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); - me->LoadEquipment(0, true); - } - - void EnterCombat(Unit * /*who*/) - { - events.ScheduleEvent(EVENT_ICY_TOUCH, 1000, GCD_CAST); - events.ScheduleEvent(EVENT_PLAGUE_STRIKE, 3000, GCD_CAST); - events.ScheduleEvent(EVENT_BLOOD_STRIKE, 2000, GCD_CAST); - events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - { - wait_timer = 5000; - me->CastSpell(me, SPELL_DK_INITIATE_VISUAL, true); - - if (Player* starter = Unit::GetPlayer(playerGUID)) - DoScriptText(say_event_attack[rand()%9], me, starter); - - phase = PHASE_TO_ATTACK; - } - } - - void EventStart(Creature* anchor, Player *pTarget) - { - wait_timer = 5000; - phase = PHASE_TO_EQUIP; - - me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN_SELF); - me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN); - - float z; - anchor->GetContactPoint(me, anchorX, anchorY, z, 1.0f); - - playerGUID = pTarget->GetGUID(); - DoScriptText(say_event_start[rand()%8], me, pTarget); - } - - void UpdateAI(const uint32 diff); -}; - -CreatureAI* GetAI_npc_unworthy_initiate(Creature* pCreature) -{ - return new npc_unworthy_initiateAI(pCreature); -} - -struct npc_unworthy_initiate_anchorAI : public PassiveAI -{ - npc_unworthy_initiate_anchorAI(Creature *c) : PassiveAI(c), prisonerGUID(0) {} - - uint64 prisonerGUID; - - void SetGUID(const uint64 &guid, int32 /*id*/) - { - if (!prisonerGUID) - prisonerGUID = guid; - } - - uint64 GetGUID(int32 /*id*/) { return prisonerGUID; } -}; - -void npc_unworthy_initiateAI::UpdateAI(const uint32 diff) -{ - switch(phase) - { - case PHASE_CHAINED: - if (!anchorGUID) - { - if (Creature *anchor = me->FindNearestCreature(29521, 30)) - { - anchor->AI()->SetGUID(me->GetGUID()); - anchor->CastSpell(me, SPELL_SOUL_PRISON_CHAIN, true); - anchorGUID = anchor->GetGUID(); - } - else - error_log("npc_unworthy_initiateAI: unable to find anchor!"); - - float dist = 99.0f; - GameObject *prison = NULL; - - for (uint8 i = 0; i < 12; ++i) - { - if (GameObject* temp_prison = me->FindNearestGameObject(acherus_soul_prison[i],30)) - { - if (me->IsWithinDist(temp_prison, dist, false)) - { - dist = me->GetDistance2d(temp_prison); - prison = temp_prison; - } - } - } - - if (prison) - prison->ResetDoorOrButton(); - else - error_log("npc_unworthy_initiateAI: unable to find prison!"); - } - return; - case PHASE_TO_EQUIP: - if (wait_timer) - { - if (wait_timer > diff) - wait_timer -= diff; - else - { - me->GetMotionMaster()->MovePoint(1, anchorX, anchorY, me->GetPositionZ()); - //debug_log("npc_unworthy_initiateAI: move to %f %f %f", anchorX, anchorY, me->GetPositionZ()); - phase = PHASE_EQUIPING; - wait_timer = 0; - } - } - return; - case PHASE_TO_ATTACK: - if (wait_timer) - { - if (wait_timer > diff) - wait_timer -= diff; - else - { - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - phase = PHASE_ATTACKING; - - if (Player *pTarget = Unit::GetPlayer(playerGUID)) - me->AI()->AttackStart(pTarget); - wait_timer = 0; - } - } - return; - case PHASE_ATTACKING: - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ICY_TOUCH: - DoCast(me->getVictim(), SPELL_ICY_TOUCH); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(EVENT_ICY_TOUCH, 5000, GCD_CAST); - break; - case EVENT_PLAGUE_STRIKE: - DoCast(me->getVictim(), SPELL_PLAGUE_STRIKE); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(SPELL_PLAGUE_STRIKE, 5000, GCD_CAST); - break; - case EVENT_BLOOD_STRIKE: - DoCast(me->getVictim(), SPELL_BLOOD_STRIKE); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(EVENT_BLOOD_STRIKE, 5000, GCD_CAST); - break; - case EVENT_DEATH_COIL: - DoCast(me->getVictim(), SPELL_DEATH_COIL); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); - break; - } - } - - DoMeleeAttackIfReady(); - } -} - -CreatureAI* GetAI_npc_unworthy_initiate_anchor(Creature* pCreature) -{ - return new npc_unworthy_initiate_anchorAI(pCreature); -} - -bool GOHello_go_acherus_soul_prison(Player* pPlayer, GameObject* pGo) -{ - if (Creature *anchor = pGo->FindNearestCreature(29521, 15)) - if (uint64 prisonerGUID = anchor->AI()->GetGUID()) - if (Creature* prisoner = Creature::GetCreature(*pPlayer, prisonerGUID)) - CAST_AI(npc_unworthy_initiateAI, prisoner->AI())->EventStart(anchor, pPlayer); - - return false; -} - -/*###### -## npc_death_knight_initiate -######*/ - -#define GOSSIP_ACCEPT_DUEL "I challenge you, death knight!" - -enum eDuelEnums -{ - SAY_DUEL_A = -1609080, - SAY_DUEL_B = -1609081, - SAY_DUEL_C = -1609082, - SAY_DUEL_D = -1609083, - SAY_DUEL_E = -1609084, - SAY_DUEL_F = -1609085, - SAY_DUEL_G = -1609086, - SAY_DUEL_H = -1609087, - SAY_DUEL_I = -1609088, - - SPELL_DUEL = 52996, - //SPELL_DUEL_TRIGGERED = 52990, - SPELL_DUEL_VICTORY = 52994, - SPELL_DUEL_FLAG = 52991, - - QUEST_DEATH_CHALLENGE = 12733, - FACTION_HOSTILE = 2068 -}; - -int32 m_auiRandomSay[] = -{ - SAY_DUEL_A, SAY_DUEL_B, SAY_DUEL_C, SAY_DUEL_D, SAY_DUEL_E, SAY_DUEL_F, SAY_DUEL_G, SAY_DUEL_H, SAY_DUEL_I -}; - -struct npc_death_knight_initiateAI : public CombatAI -{ - npc_death_knight_initiateAI(Creature* pCreature) : CombatAI(pCreature) - { - m_bIsDuelInProgress = false; - } - - bool lose; - uint64 m_uiDuelerGUID; - uint32 m_uiDuelTimer; - bool m_bIsDuelInProgress; - - void Reset() - { - lose = false; - me->RestoreFaction(); - CombatAI::Reset(); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); - - m_uiDuelerGUID = 0; - m_uiDuelTimer = 5000; - m_bIsDuelInProgress = false; - } - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - if (!m_bIsDuelInProgress && pSpell->Id == SPELL_DUEL) - { - m_uiDuelerGUID = pCaster->GetGUID(); - m_bIsDuelInProgress = true; - } - } - - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) - { - if (m_bIsDuelInProgress && pDoneBy->IsControlledByPlayer()) - { - if (pDoneBy->GetGUID() != m_uiDuelerGUID && pDoneBy->GetOwnerGUID() != m_uiDuelerGUID) // other players cannot help - uiDamage = 0; - else if (uiDamage >= me->GetHealth()) - { - uiDamage = 0; - - if (!lose) - { - pDoneBy->RemoveGameObject(SPELL_DUEL_FLAG, true); - pDoneBy->AttackStop(); - me->CastSpell(pDoneBy, SPELL_DUEL_VICTORY, true); - lose = true; - me->CastSpell(me, 7267, true); - me->RestoreFaction(); - } - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - { - if (m_bIsDuelInProgress) - { - if (m_uiDuelTimer <= uiDiff) - { - me->setFaction(FACTION_HOSTILE); - - if (Unit* pUnit = Unit::GetUnit(*me, m_uiDuelerGUID)) - AttackStart(pUnit); - } - else - m_uiDuelTimer -= uiDiff; - } - return; - } - - if (m_bIsDuelInProgress) - { - if (lose) - { - if (!me->HasAura(7267)) - EnterEvadeMode(); - return; - } - else if (me->getVictim()->GetTypeId() == TYPEID_PLAYER - && me->getVictim()->GetHealth() * 10 < me->getVictim()->GetMaxHealth()) - { - me->getVictim()->CastSpell(me->getVictim(), 7267, true); // beg - me->getVictim()->RemoveGameObject(SPELL_DUEL_FLAG, true); - EnterEvadeMode(); - return; - } - } - - // TODO: spells - - CombatAI::UpdateAI(uiDiff); - } -}; - -CreatureAI* GetAI_npc_death_knight_initiate(Creature* pCreature) -{ - return new npc_death_knight_initiateAI(pCreature); -} - -bool GossipHello_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_DEATH_CHALLENGE) == QUEST_STATUS_INCOMPLETE && pCreature->GetHealth() == pCreature->GetMaxHealth()) - { - if (pPlayer->GetHealth() * 10 < pPlayer->GetMaxHealth()) - return true; - - if (pPlayer->isInCombat() || pCreature->isInCombat()) - return true; - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ACCEPT_DUEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature),pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pPlayer->isInCombat() || pCreature->isInCombat()) - return true; - - if (npc_death_knight_initiateAI* pInitiateAI = CAST_AI(npc_death_knight_initiateAI, pCreature->AI())) - { - if (pInitiateAI->m_bIsDuelInProgress) - return true; - } - - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); - - int32 uiSayId = rand()% (sizeof(m_auiRandomSay)/sizeof(int32)); - DoScriptText(m_auiRandomSay[uiSayId], pCreature, pPlayer); - - pPlayer->CastSpell(pCreature, SPELL_DUEL, false); - pPlayer->CastSpell(pPlayer, SPELL_DUEL_FLAG, true); - } - return true; -} - -/*###### -## npc_dark_rider_of_acherus -######*/ - -#define DESPAWN_HORSE 52267 -#define SAY_DARK_RIDER "The realm of shadows awaits..." - -struct npc_dark_rider_of_acherusAI : public ScriptedAI -{ - npc_dark_rider_of_acherusAI(Creature *c) : ScriptedAI(c) {} - - uint32 PhaseTimer; - uint32 Phase; - bool Intro; - uint64 TargetGUID; - - void Reset() - { - PhaseTimer = 4000; - Phase = 0; - Intro = false; - TargetGUID = 0; - } - - void UpdateAI(const uint32 diff) - { - if (!Intro || !TargetGUID) - return; - - if (PhaseTimer <= diff) - { - switch(Phase) - { - case 0: - me->MonsterSay(SAY_DARK_RIDER, LANG_UNIVERSAL, 0); - PhaseTimer = 5000; - Phase = 1; - break; - case 1: - if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID)) - DoCast(pTarget, DESPAWN_HORSE, true); - PhaseTimer = 3000; - Phase = 2; - break; - case 2: - me->SetVisibility(VISIBILITY_OFF); - PhaseTimer = 2000; - Phase = 3; - break; - case 3: - me->ForcedDespawn(); - break; - default: - break; - } - } else PhaseTimer -= diff; - - } - - void InitDespawnHorse(Unit *who) - { - if (!who) - return; - - TargetGUID = who->GetGUID(); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->SetSpeed(MOVE_RUN, 0.4f); - me->GetMotionMaster()->MoveChase(who); - me->SetUInt64Value(UNIT_FIELD_TARGET, TargetGUID); - Intro = true; - } - -}; - -CreatureAI* GetAI_npc_dark_rider_of_acherus(Creature* pCreature) -{ - return new npc_dark_rider_of_acherusAI(pCreature); -} - -/*###### -## npc_salanar_the_horseman -######*/ - -enum eSalanar -{ - REALM_OF_SHADOWS = 52693, - EFFECT_STOLEN_HORSE = 52263, - DELIVER_STOLEN_HORSE = 52264, - CALL_DARK_RIDER = 52266, - SPELL_EFFECT_OVERTAKE = 52349 -}; - -struct npc_salanar_the_horsemanAI : public ScriptedAI -{ - npc_salanar_the_horsemanAI(Creature *c) : ScriptedAI(c) {} - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == DELIVER_STOLEN_HORSE) - { - if (caster->GetTypeId() == TYPEID_UNIT && caster->IsVehicle()) - { - if (Unit *charmer = caster->GetCharmer()) - { - charmer->RemoveAurasDueToSpell(EFFECT_STOLEN_HORSE); - caster->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - caster->setFaction(35); - DoCast(caster, CALL_DARK_RIDER, true); - if (Creature* Dark_Rider = me->FindNearestCreature(28654, 15)) - CAST_AI(npc_dark_rider_of_acherusAI, Dark_Rider->AI())->InitDespawnHorse(caster); - } - } - } - } - - void MoveInLineOfSight(Unit *who) - { - ScriptedAI::MoveInLineOfSight(who); - - if (who->GetTypeId() == TYPEID_UNIT && who->IsVehicle() && me->IsWithinDistInMap(who, 5.0f)) - { - if (Unit *charmer = who->GetCharmer()) - { - if (charmer->GetTypeId() == TYPEID_PLAYER) - { - // for quest Into the Realm of Shadows(12687) - if (me->GetEntry() == 28788 && CAST_PLR(charmer)->GetQuestStatus(12687) == QUEST_STATUS_INCOMPLETE) - { - CAST_PLR(charmer)->GroupEventHappens(12687, me); - charmer->RemoveAurasDueToSpell(SPELL_EFFECT_OVERTAKE); - CAST_CRE(who)->ForcedDespawn(); - //CAST_CRE(who)->Respawn(true); - } - - if (CAST_PLR(charmer)->HasAura(REALM_OF_SHADOWS)) - charmer->RemoveAurasDueToSpell(REALM_OF_SHADOWS); - } - } - } - } -}; - -CreatureAI* GetAI_npc_salanar_the_horseman(Creature* pCreature) -{ - return new npc_salanar_the_horsemanAI(pCreature); -} - -/*###### -## npc_ros_dark_rider -######*/ - -struct npc_ros_dark_riderAI : public ScriptedAI -{ - npc_ros_dark_riderAI(Creature *c) : ScriptedAI(c) {} - - void EnterCombat(Unit * /*who*/) - { - me->ExitVehicle(); - } - - void Reset() - { - Creature* deathcharger = me->FindNearestCreature(28782, 30); - if (!deathcharger) return; - deathcharger->RestoreFaction(); - deathcharger->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - deathcharger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (!me->GetVehicle() && deathcharger->IsVehicle() && deathcharger->GetVehicleKit()->HasEmptySeat(0)) - me->EnterVehicle(deathcharger); - } - - void JustDied(Unit *killer) - { - Creature* deathcharger = me->FindNearestCreature(28782, 30); - if (!deathcharger) return; - if (killer->GetTypeId() == TYPEID_PLAYER && deathcharger->GetTypeId() == TYPEID_UNIT && deathcharger->IsVehicle()) - { - deathcharger->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - deathcharger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - deathcharger->setFaction(2096); - } - } -}; - -CreatureAI* GetAI_npc_ros_dark_rider(Creature* pCreature) -{ - return new npc_ros_dark_riderAI(pCreature); -} - -// correct way: 52312 52314 52555 ... -enum SG -{ - GHOULS = 28845, - GHOSTS = 28846, -}; -struct npc_dkc1_gothikAI : public ScriptedAI -{ - npc_dkc1_gothikAI(Creature *c) : ScriptedAI(c) {} - - void MoveInLineOfSight(Unit *who) - { - ScriptedAI::MoveInLineOfSight(who); - - if (who->GetEntry() == GHOULS && me->IsWithinDistInMap(who, 10.0f)) - { - if (Unit *owner = who->GetOwner()) - { - if (owner->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(owner)->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE) - { - //CAST_CRE(who)->CastSpell(owner, 52517, true); - CAST_PLR(owner)->KilledMonsterCredit(GHOULS, me->GetGUID()); - } - //Todo: Creatures must not be removed, but, must instead - // stand next to Gothik and be commanded into the pit - // and dig into the ground. - CAST_CRE(who)->ForcedDespawn(); - - if (CAST_PLR(owner)->GetQuestStatus(12698) == QUEST_STATUS_COMPLETE) - owner->RemoveAllMinionsByEntry(GHOULS); - } - } - } - } -}; - -CreatureAI* GetAI_npc_dkc1_gothik(Creature* pCreature) -{ - return new npc_dkc1_gothikAI(pCreature); -} - -struct npc_scarlet_ghoulAI : public ScriptedAI -{ - npc_scarlet_ghoulAI(Creature *c) : ScriptedAI(c) - { - // Ghouls should display their Birth Animation - // Crawling out of the ground - //DoCast(me, 35177, true); - //me->MonsterSay("Mommy?",LANG_UNIVERSAL,0); - me->SetReactState(REACT_DEFENSIVE); - } - - void FindMinions(Unit *owner) - { - std::list MinionList; - owner->GetAllMinionsByEntry(MinionList,GHOULS); - - if (!MinionList.empty()) - { - for (std::list::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr) - { - if (CAST_CRE(*itr)->GetOwner()->GetGUID() == me->GetOwner()->GetGUID()) - { - if (CAST_CRE(*itr)->isInCombat() && CAST_CRE(*itr)->getAttackerForHelper()) - { - AttackStart(CAST_CRE(*itr)->getAttackerForHelper()); - } - } - } - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!me->isInCombat()) - { - if (Unit *owner = me->GetOwner()) - { - if (owner->GetTypeId() == TYPEID_PLAYER && CAST_PLR(owner)->isInCombat()) - { - if (CAST_PLR(owner)->getAttackerForHelper() && CAST_PLR(owner)->getAttackerForHelper()->GetEntry() == GHOSTS) - { - AttackStart(CAST_PLR(owner)->getAttackerForHelper()); - } - else - { - FindMinions(owner); - } - } - } - } - - if (!UpdateVictim()) - return; - - //ScriptedAI::UpdateAI(diff); - //Check if we have a current target - if (me->getVictim()->GetEntry() == GHOSTS) - { - if (me->isAttackReady()) - { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - } - } -}; - -CreatureAI* GetAI_npc_scarlet_ghoul(Creature* pCreature) -{ - return new npc_scarlet_ghoulAI(pCreature); -} - -/*#### -## npc_scarlet_miner_cart -####*/ - -#define SPELL_CART_CHECK 54173 -#define SPELL_CART_DRAG 52465 - -struct npc_scarlet_miner_cartAI : public PassiveAI -{ - npc_scarlet_miner_cartAI(Creature *c) : PassiveAI(c), minerGUID(0) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetDisplayId(me->GetCreatureInfo()->Modelid1); // H0 is horse - } - - uint64 minerGUID; - - void SetGUID(const uint64 &guid, int32 /*id*/) - { - minerGUID = guid; - } - - void DoAction(const int32 /*param*/) - { - if (Creature *miner = Unit::GetCreature(*me, minerGUID)) - { - // very bad visual effect - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - //me->SetSpeed(MOVE_WALK, miner->GetSpeed(MOVE_WALK)); - me->SetSpeed(MOVE_RUN, miner->GetSpeed(MOVE_RUN)); - me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); - } - } - - void PassengerBoarded(Unit * /*who*/, int8 /*seatId*/, bool apply) - { - if (!apply) - if (Creature *miner = Unit::GetCreature(*me, minerGUID)) - miner->DisappearAndDie(); - } -}; - -CreatureAI* GetAI_npc_scarlet_miner_cart(Creature *_Creature) -{ - return new npc_scarlet_miner_cartAI(_Creature); -} - -/*#### -## npc_scarlet_miner -####*/ - -#define SAY_SCARLET_MINER1 "Where'd this come from? I better get this down to the ships before the foreman sees it!" -#define SAY_SCARLET_MINER2 "Now I can have a rest!" - -struct npc_scarlet_minerAI : public npc_escortAI -{ - npc_scarlet_minerAI(Creature *c) : npc_escortAI(c) - { - me->SetReactState(REACT_PASSIVE); - } - - uint32 IntroTimer; - uint32 IntroPhase; - uint64 carGUID; - - void Reset() - { - carGUID = 0; - IntroTimer = 0; - IntroPhase = 0; - } - - void InitWaypoint() - { - AddWaypoint(1, 2389.03, -5902.74, 109.014, 5000); - AddWaypoint(2, 2341.812012, -5900.484863, 102.619743); - AddWaypoint(3, 2306.561279, -5901.738281, 91.792419); - AddWaypoint(4, 2300.098389, -5912.618652, 86.014885); - AddWaypoint(5, 2294.142090, -5927.274414, 75.316849); - AddWaypoint(6, 2286.984375, -5944.955566, 63.714966); - AddWaypoint(7, 2280.001709, -5961.186035, 54.228283); - AddWaypoint(8, 2259.389648, -5974.197754, 42.359348); - AddWaypoint(9, 2242.882812, -5984.642578, 32.827850); - AddWaypoint(10, 2217.265625, -6028.959473, 7.675705); - AddWaypoint(11, 2202.595947, -6061.325684, 5.882018); - AddWaypoint(12, 2188.974609, -6080.866699, 3.370027); - - if (urand(0,1)) - { - AddWaypoint(13, 2176.483887, -6110.407227, 1.855181); - AddWaypoint(14, 2172.516602, -6146.752441, 1.074235); - AddWaypoint(15, 2138.918457, -6158.920898, 1.342926); - AddWaypoint(16, 2129.866699, -6174.107910, 4.380779); - AddWaypoint(17, 2117.709473, -6193.830078, 13.3542, 10000); - } - else - { - AddWaypoint(13, 2184.190186, -6166.447266, 0.968877); - AddWaypoint(14, 2234.265625, -6163.741211, 0.916021); - AddWaypoint(15, 2268.071777, -6158.750977, 1.822252); - AddWaypoint(16, 2270.028320, -6176.505859, 6.340538); - AddWaypoint(17, 2271.739014, -6195.401855, 13.3542, 10000); - } - } - - void InitCartQuest(Player *who) - { - carGUID = who->GetVehicleBase()->GetGUID(); - InitWaypoint(); - Start(false, false, who->GetGUID()); - SetDespawnAtFar(false); - } - - void WaypointReached(uint32 i) - { - switch (i) - { - case 1: - if (Unit *car = Unit::GetCreature(*me, carGUID)) - { - me->SetInFront(car); - me->SendMovementFlagUpdate(); - } - me->MonsterSay(SAY_SCARLET_MINER1,LANG_UNIVERSAL,NULL); - SetRun(true); - IntroTimer = 4000; - IntroPhase = 1; - break; - case 17: - if (Unit *car = Unit::GetCreature(*me, carGUID)) - { - me->SetInFront(car); - me->SendMovementFlagUpdate(); - car->Relocate(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ()); - car->SendMonsterStop(); - //this make player fall under ground, dunno why - //car->GetMotionMaster()->MovePoint(0, car->GetPositionX(), car->GetPositionY(), me->GetPositionZ()); - car->RemoveAura(SPELL_CART_DRAG); - } - me->MonsterSay(SAY_SCARLET_MINER2,LANG_UNIVERSAL,NULL); - break; - default: - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (IntroPhase) - { - if (IntroTimer <= diff) - { - if (IntroPhase == 1) - { - if (Creature *car = Unit::GetCreature(*me, carGUID)) - DoCast(car, SPELL_CART_DRAG); - IntroTimer = 800; - IntroPhase = 2; - } - else - { - if (Creature *car = Unit::GetCreature(*me, carGUID)) - car->AI()->DoAction(); - IntroPhase = 0; - } - } else IntroTimer-=diff; - } - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_scarlet_miner(Creature *_Creature) -{ - return new npc_scarlet_minerAI(_Creature); -} - -/*###### -## go_inconspicuous_mine_car -######*/ - -#define SPELL_CART_SUMM 52463 - -bool GOHello_go_inconspicuous_mine_car(Player* pPlayer, GameObject* /*pGO*/) -{ - if (pPlayer->GetQuestStatus(12701) == QUEST_STATUS_INCOMPLETE) - { - // Hack Why Trinity Dont Support Custom Summon Location - if (Creature *miner = pPlayer->SummonCreature(28841, 2383.869629, -5900.312500, 107.996086, pPlayer->GetOrientation(),TEMPSUMMON_DEAD_DESPAWN, 1)) - { - pPlayer->CastSpell(pPlayer, SPELL_CART_SUMM, true); - if (Creature *car = pPlayer->GetVehicleCreatureBase()) - { - if (car->GetEntry() == 28817) - { - car->AI()->SetGUID(miner->GetGUID()); - CAST_AI(npc_scarlet_minerAI, miner->AI())->InitCartQuest(pPlayer); - } else error_log("TSCR: GOHello_go_inconspicuous_mine_car vehicle entry is not correct."); - } else error_log("TSCR: GOHello_go_inconspicuous_mine_car player is not on the vehicle."); - } else error_log("TSCR: GOHello_go_inconspicuous_mine_car Scarlet Miner cant be found by script."); - } - return true; -} - -// npc 28912 quest 17217 boss 29001 mob 29007 go 191092 - -void AddSC_the_scarlet_enclave_c1() -{ - Script *newscript; - - // 12848 The Endless Hunger - newscript = new Script; - newscript->Name = "npc_unworthy_initiate"; - newscript->GetAI = &GetAI_npc_unworthy_initiate; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_unworthy_initiate_anchor"; - newscript->GetAI = &GetAI_npc_unworthy_initiate_anchor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_acherus_soul_prison"; - newscript->pGOHello = &GOHello_go_acherus_soul_prison; - newscript->RegisterSelf(); - - // Death's Challenge - newscript = new Script; - newscript->Name = "npc_death_knight_initiate"; - newscript->GetAI = &GetAI_npc_death_knight_initiate; - newscript->pGossipHello = &GossipHello_npc_death_knight_initiate; - newscript->pGossipSelect = &GossipSelect_npc_death_knight_initiate; - newscript->RegisterSelf(); - - // 12680 Grand Theft Palomino - newscript = new Script; - newscript->Name = "npc_salanar_the_horseman"; - newscript->GetAI = &GetAI_npc_salanar_the_horseman; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dark_rider_of_acherus"; - newscript->GetAI = &GetAI_npc_dark_rider_of_acherus; - newscript->RegisterSelf(); - - // 12687 Into the Realm of Shadows - newscript = new Script; - newscript->Name = "npc_ros_dark_rider"; - newscript->GetAI = &GetAI_npc_ros_dark_rider; - newscript->RegisterSelf(); - - // 12698 The Gift That Keeps On Giving - newscript = new Script; - newscript->Name = "npc_dkc1_gothik"; - newscript->GetAI = &GetAI_npc_dkc1_gothik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_scarlet_ghoul"; - newscript->GetAI = &GetAI_npc_scarlet_ghoul; - newscript->RegisterSelf(); - - // Massacre At Light's Point - newscript = new Script; - newscript->Name = "npc_scarlet_miner"; - newscript->GetAI = &GetAI_npc_scarlet_miner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_scarlet_miner_cart"; - newscript->GetAI = &GetAI_npc_scarlet_miner_cart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_inconspicuous_mine_car"; - newscript->pGOHello = &GOHello_go_inconspicuous_mine_car; - newscript->RegisterSelf(); -} - -/* -DELETE FROM `script_texts` WHERE `entry` IN(-1609301, -1609302); -INSERT INTO `script_texts` (`entry`,`content_default`,`type`,`language`,`emote`,`comment`) VALUES -(-1609301, 'Come, weakling! Strike me down!', 0, 0, 0, 'SAY_DEATH_RIDER_FINAL'), -(-1609302, '%s rears up, beckoning you to ride it.', 2, 0, 0, 'SAY_DEATH_CHARGER'); -*/ diff --git a/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter2.cpp b/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter2.cpp deleted file mode 100644 index 91f7e0e6cbe..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter2.cpp +++ /dev/null @@ -1,995 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -//How to win friends and influence enemies -// texts signed for creature 28939 but used for 28939,28940,28610 -enum win_friends -{ - SAY_PERSUADE1 = -1609501, - SAY_PERSUADE2 = -1609502, - SAY_PERSUADE3 = -1609503, - SAY_PERSUADE4 = -1609504, - SAY_PERSUADE5 = -1609505, - SAY_PERSUADE6 = -1609506, - SAY_PERSUADE7 = -1609507, - SAY_CRUSADER1 = -1609508, - SAY_CRUSADER2 = -1609509, - SAY_CRUSADER3 = -1609510, - SAY_CRUSADER4 = -1609511, - SAY_CRUSADER5 = -1609512, - SAY_CRUSADER6 = -1609513, - SAY_PERSUADED1 = -1609514, - SAY_PERSUADED2 = -1609515, - SAY_PERSUADED3 = -1609516, - SAY_PERSUADED4 = -1609517, - SAY_PERSUADED5 = -1609518, - SAY_PERSUADED6 = -1609519, - SPELL_PERSUASIVE_STRIKE = 52781 -}; - -struct npc_crusade_persuadedAI : public ScriptedAI -{ - npc_crusade_persuadedAI(Creature *pCreature) : ScriptedAI(pCreature) {} - - uint32 uiSpeech_timer; - uint32 uiSpeech_counter; - uint64 uiPlayerGUID; - - void Reset() - { - uiSpeech_timer = 0; - uiSpeech_counter = 0; - uiPlayerGUID = 0; - me->SetReactState(REACT_AGGRESSIVE); - me->RestoreFaction(); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_PERSUASIVE_STRIKE && caster->GetTypeId() == TYPEID_PLAYER && me->isAlive() && !uiSpeech_counter) - { - if (CAST_PLR(caster)->GetQuestStatus(12720) == QUEST_STATUS_INCOMPLETE) - { - uiPlayerGUID = caster->GetGUID(); - uiSpeech_timer = 1000; - uiSpeech_counter = 1; - me->setFaction(caster->getFaction()); - me->CombatStop(true); - me->GetMotionMaster()->MoveIdle(); - me->SetReactState(REACT_PASSIVE); - DoCastAOE(58111, true); - - DoScriptText(RAND(SAY_PERSUADE1,SAY_PERSUADE2,SAY_PERSUADE3, - SAY_PERSUADE4,SAY_PERSUADE5,SAY_PERSUADE6, - SAY_PERSUADE7), caster); - - DoScriptText(RAND(SAY_CRUSADER1,SAY_CRUSADER2,SAY_CRUSADER3, - SAY_CRUSADER4,SAY_CRUSADER5,SAY_CRUSADER6), me); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (uiSpeech_counter) - { - if (uiSpeech_timer <= diff) - { - Player* pPlayer = Unit::GetPlayer(uiPlayerGUID); - if (!pPlayer) - { - EnterEvadeMode(); - return; - } - - switch(uiSpeech_counter) - { - case 1: DoScriptText(SAY_PERSUADED1, me); uiSpeech_timer = 8000; break; - case 2: DoScriptText(SAY_PERSUADED2, me); uiSpeech_timer = 8000; break; - case 3: DoScriptText(SAY_PERSUADED3, me); uiSpeech_timer = 8000; break; - case 4: DoScriptText(SAY_PERSUADED4, me); uiSpeech_timer = 8000; break; - case 5: DoScriptText(SAY_PERSUADED5, pPlayer); uiSpeech_timer = 8000; break; - case 6: DoScriptText(SAY_PERSUADED6, me); - pPlayer->Kill(me); - //me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - uiSpeech_counter = 0; - pPlayer->GroupEventHappens(12720, me); - return; - } - - ++uiSpeech_counter; - DoCastAOE(58111, true); - } else uiSpeech_timer -= diff; - - return; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_crusade_persuaded(Creature* pCreature) -{ - return new npc_crusade_persuadedAI (pCreature); -} - -/*###### -## npc_koltira_deathweaver -######*/ - -enum eKoltira -{ - SAY_BREAKOUT1 = -1609561, - SAY_BREAKOUT2 = -1609562, - SAY_BREAKOUT3 = -1609563, - SAY_BREAKOUT4 = -1609564, - SAY_BREAKOUT5 = -1609565, - SAY_BREAKOUT6 = -1609566, - SAY_BREAKOUT7 = -1609567, - SAY_BREAKOUT8 = -1609568, - SAY_BREAKOUT9 = -1609569, - SAY_BREAKOUT10 = -1609570, - - SPELL_KOLTIRA_TRANSFORM = 52899, - SPELL_ANTI_MAGIC_ZONE = 52894, - - QUEST_BREAKOUT = 12727, - - NPC_CRIMSON_ACOLYTE = 29007, - NPC_HIGH_INQUISITOR_VALROTH = 29001, - NPC_KOLTIRA_ALT = 28447, - - //not sure about this id - //NPC_DEATH_KNIGHT_MOUNT = 29201, - MODEL_DEATH_KNIGHT_MOUNT = 25278 -}; - -struct npc_koltira_deathweaverAI : public npc_escortAI -{ - npc_koltira_deathweaverAI(Creature *pCreature) : npc_escortAI(pCreature) - { - me->SetReactState(REACT_DEFENSIVE); - } - - uint32 m_uiWave; - uint32 m_uiWave_Timer; - uint64 m_uiValrothGUID; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - m_uiWave = 0; - m_uiWave_Timer = 3000; - m_uiValrothGUID = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->LoadEquipment(0, true); - me->RemoveAura(SPELL_ANTI_MAGIC_ZONE); - } - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 0: - DoScriptText(SAY_BREAKOUT1, me); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - break; - case 1: - me->SetStandState(UNIT_STAND_STATE_KNEEL); - break; - case 2: - me->SetStandState(UNIT_STAND_STATE_STAND); - //me->UpdateEntry(NPC_KOLTIRA_ALT); //unclear if we must update or not - DoCast(me, SPELL_KOLTIRA_TRANSFORM); - me->LoadEquipment(me->GetEquipmentId()); - break; - case 3: - SetEscortPaused(true); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - DoScriptText(SAY_BREAKOUT2, me); - DoCast(me, SPELL_ANTI_MAGIC_ZONE); // cast again that makes bubble up - break; - case 4: - SetRun(true); - break; - case 9: - me->Mount(MODEL_DEATH_KNIGHT_MOUNT); - break; - case 10: - me->Unmount(); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - if (Player* pPlayer = GetPlayerForEscort()) - { - pSummoned->AI()->AttackStart(pPlayer); - } - - if (pSummoned->GetEntry() == NPC_HIGH_INQUISITOR_VALROTH) - m_uiValrothGUID = pSummoned->GetGUID(); - - pSummoned->AddThreat(me, 0.0f); - pSummoned->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - void SummonAcolyte(uint32 uiAmount) - { - for (uint32 i = 0; i < uiAmount; ++i) - me->SummonCreature(NPC_CRIMSON_ACOLYTE, 1642.329, -6045.818, 127.583, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (HasEscortState(STATE_ESCORT_PAUSED)) - { - if (m_uiWave_Timer <= uiDiff) - { - switch(m_uiWave) - { - case 0: - DoScriptText(SAY_BREAKOUT3, me); - SummonAcolyte(3); - m_uiWave_Timer = 20000; - break; - case 1: - DoScriptText(SAY_BREAKOUT4, me); - SummonAcolyte(3); - m_uiWave_Timer = 20000; - break; - case 2: - DoScriptText(SAY_BREAKOUT5, me); - SummonAcolyte(4); - m_uiWave_Timer = 20000; - break; - case 3: - DoScriptText(SAY_BREAKOUT6, me); - me->SummonCreature(NPC_HIGH_INQUISITOR_VALROTH, 1642.329, -6045.818, 127.583, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); - m_uiWave_Timer = 1000; - break; - case 4: - { - Creature* pTemp = Unit::GetCreature(*me, m_uiValrothGUID); - - if (!pTemp || !pTemp->isAlive()) - { - DoScriptText(SAY_BREAKOUT8, me); - m_uiWave_Timer = 5000; - } - else - { - m_uiWave_Timer = 2500; - return; //return, we don't want m_uiWave to increment now - } - break; - } - case 5: - DoScriptText(SAY_BREAKOUT9, me); - me->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); - // i do not know why the armor will also be removed - m_uiWave_Timer = 2500; - break; - case 6: - DoScriptText(SAY_BREAKOUT10, me); - SetEscortPaused(false); - break; - } - - ++m_uiWave; - } - else - m_uiWave_Timer -= uiDiff; - } - } -}; - -CreatureAI* GetAI_npc_koltira_deathweaver(Creature* pCreature) -{ - return new npc_koltira_deathweaverAI(pCreature); -} - -bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_BREAKOUT) - { - pCreature->SetStandState(UNIT_STAND_STATE_STAND); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_koltira_deathweaverAI,pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID()); - } - return true; -} - -//Scarlet courier -enum ScarletCourierEnum -{ - SAY_TREE1 = -1609531, - SAY_TREE2 = -1609532, - SPELL_SHOOT = 52818, - GO_INCONSPICUOUS_TREE = 191144, - NPC_SCARLET_COURIER = 29076 -}; - -struct mob_scarlet_courierAI : public ScriptedAI -{ - mob_scarlet_courierAI(Creature *pCreature) : ScriptedAI(pCreature) {} - - uint32 uiStage; - uint32 uiStage_timer; - - void Reset() - { - me->Mount(14338); // not sure about this id - uiStage = 1; - uiStage_timer = 3000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_TREE2, me); - me->Unmount(); - uiStage = 0; - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - uiStage = 2; - } - - void UpdateAI(const uint32 diff) - { - if (uiStage && !me->isInCombat()) - { - if (uiStage_timer <= diff) - { - switch(uiStage) - { - case 1: - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - if (GameObject* tree = me->FindNearestGameObject(GO_INCONSPICUOUS_TREE, 40.0f)) - { - DoScriptText(SAY_TREE1, me); - float x, y, z; - tree->GetContactPoint(me, x, y, z); - me->GetMotionMaster()->MovePoint(1, x, y, z); - } - break; - case 2: - if (GameObject* tree = me->FindNearestGameObject(GO_INCONSPICUOUS_TREE, 40.0f)) - if (Unit *unit = tree->GetOwner()) - AttackStart(unit); - break; - } - uiStage_timer = 3000; - uiStage = 0; - } else uiStage_timer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_scarlet_courier(Creature* pCreature) -{ - return new mob_scarlet_courierAI (pCreature); -} - -//Koltira & Valroth- Breakout - -enum valroth -{ - SAY_VALROTH1 = -1609581, - SAY_VALROTH2 = -1609582, - SAY_VALROTH3 = -1609583, - SAY_VALROTH4 = -1609584, - SAY_VALROTH5 = -1609585, - SAY_VALROTH6 = -1609586, - SPELL_RENEW = 38210, - SPELL_INQUISITOR_PENANCE = 52922, - SPELL_VALROTH_SMITE = 52926, - SPELL_SUMMON_VALROTH_REMAINS = 52929 -}; - -struct mob_high_inquisitor_valrothAI : public ScriptedAI -{ - mob_high_inquisitor_valrothAI(Creature *pCreature) : ScriptedAI(pCreature) {} - - uint32 uiRenew_timer; - uint32 uiInquisitor_Penance_timer; - uint32 uiValroth_Smite_timer; - - void Reset() - { - uiRenew_timer = 1000; - uiInquisitor_Penance_timer = 2000; - uiValroth_Smite_timer = 1000; - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_VALROTH2, me); - DoCast(who, SPELL_VALROTH_SMITE); - } - - void UpdateAI(const uint32 diff) - { - if (uiRenew_timer <= diff) - { - Shout(); - DoCast(me, SPELL_RENEW); - uiRenew_timer = 1000 + rand()%5000; - } else uiRenew_timer -= diff; - - if (uiInquisitor_Penance_timer <= diff) - { - Shout(); - DoCast(me->getVictim(), SPELL_INQUISITOR_PENANCE); - uiInquisitor_Penance_timer = 2000 + rand()%5000; - } else uiInquisitor_Penance_timer -= diff; - - if (uiValroth_Smite_timer <= diff) - { - Shout(); - DoCast(me->getVictim(), SPELL_VALROTH_SMITE); - uiValroth_Smite_timer = 1000 + rand()%5000; - } else uiValroth_Smite_timer -= diff; - - DoMeleeAttackIfReady(); - } - - void Shout() - { - if (rand()%100 < 15) - DoScriptText(RAND(SAY_VALROTH3,SAY_VALROTH4,SAY_VALROTH5), me); - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_VALROTH6, me); - killer->CastSpell(me, SPELL_SUMMON_VALROTH_REMAINS, true); - } -}; - -CreatureAI* GetAI_mob_high_inquisitor_valroth(Creature* pCreature) -{ - return new mob_high_inquisitor_valrothAI (pCreature); -} - -/*###### -## npc_a_special_surprise -######*/ -//used by 29032,29061,29065,29067,29068,29070,29074,29072,29073,29071 but signed for 29032 -enum SpecialSurprise -{ - SAY_EXEC_START_1 = -1609025, // speech for all - SAY_EXEC_START_2 = -1609026, - SAY_EXEC_START_3 = -1609027, - SAY_EXEC_PROG_1 = -1609028, - SAY_EXEC_PROG_2 = -1609029, - SAY_EXEC_PROG_3 = -1609030, - SAY_EXEC_PROG_4 = -1609031, - SAY_EXEC_PROG_5 = -1609032, - SAY_EXEC_PROG_6 = -1609033, - SAY_EXEC_PROG_7 = -1609034, - SAY_EXEC_NAME_1 = -1609035, - SAY_EXEC_NAME_2 = -1609036, - SAY_EXEC_RECOG_1 = -1609037, - SAY_EXEC_RECOG_2 = -1609038, - SAY_EXEC_RECOG_3 = -1609039, - SAY_EXEC_RECOG_4 = -1609040, - SAY_EXEC_RECOG_5 = -1609041, - SAY_EXEC_RECOG_6 = -1609042, - SAY_EXEC_NOREM_1 = -1609043, - SAY_EXEC_NOREM_2 = -1609044, - SAY_EXEC_NOREM_3 = -1609045, - SAY_EXEC_NOREM_4 = -1609046, - SAY_EXEC_NOREM_5 = -1609047, - SAY_EXEC_NOREM_6 = -1609048, - SAY_EXEC_NOREM_7 = -1609049, - SAY_EXEC_NOREM_8 = -1609050, - SAY_EXEC_NOREM_9 = -1609051, - SAY_EXEC_THINK_1 = -1609052, - SAY_EXEC_THINK_2 = -1609053, - SAY_EXEC_THINK_3 = -1609054, - SAY_EXEC_THINK_4 = -1609055, - SAY_EXEC_THINK_5 = -1609056, - SAY_EXEC_THINK_6 = -1609057, - SAY_EXEC_THINK_7 = -1609058, - SAY_EXEC_THINK_8 = -1609059, - SAY_EXEC_THINK_9 = -1609060, - SAY_EXEC_THINK_10 = -1609061, - SAY_EXEC_LISTEN_1 = -1609062, - SAY_EXEC_LISTEN_2 = -1609063, - SAY_EXEC_LISTEN_3 = -1609064, - SAY_EXEC_LISTEN_4 = -1609065, - SAY_PLAGUEFIST = -1609066, - SAY_EXEC_TIME_1 = -1609067, - SAY_EXEC_TIME_2 = -1609068, - SAY_EXEC_TIME_3 = -1609069, - SAY_EXEC_TIME_4 = -1609070, - SAY_EXEC_TIME_5 = -1609071, - SAY_EXEC_TIME_6 = -1609072, - SAY_EXEC_TIME_7 = -1609073, - SAY_EXEC_TIME_8 = -1609074, - SAY_EXEC_TIME_9 = -1609075, - SAY_EXEC_TIME_10 = -1609076, - SAY_EXEC_WAITING = -1609077, - EMOTE_DIES = -1609078, - - NPC_PLAGUEFIST = 29053 -}; - -struct npc_a_special_surpriseAI : public ScriptedAI -{ - npc_a_special_surpriseAI(Creature *pCreature) : ScriptedAI(pCreature) {} - - uint32 ExecuteSpeech_Timer; - uint32 ExecuteSpeech_Counter; - uint64 PlayerGUID; - - void Reset() - { - ExecuteSpeech_Timer = 0; - ExecuteSpeech_Counter = 0; - PlayerGUID = 0; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - bool MeetQuestCondition(Unit* pPlayer) - { - switch(me->GetEntry()) - { - case 29061: // Ellen Stanbridge - if (CAST_PLR(pPlayer)->GetQuestStatus(12742) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29072: // Kug Ironjaw - if (CAST_PLR(pPlayer)->GetQuestStatus(12748) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29067: // Donovan Pulfrost - if (CAST_PLR(pPlayer)->GetQuestStatus(12744) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29065: // Yazmina Oakenthorn - if (CAST_PLR(pPlayer)->GetQuestStatus(12743) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29071: // Antoine Brack - if (CAST_PLR(pPlayer)->GetQuestStatus(12750) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29032: // Malar Bravehorn - if (CAST_PLR(pPlayer)->GetQuestStatus(12739) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29068: // Goby Blastenheimer - if (CAST_PLR(pPlayer)->GetQuestStatus(12745) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29073: // Iggy Darktusk - if (CAST_PLR(pPlayer)->GetQuestStatus(12749) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29074: // Lady Eonys - if (CAST_PLR(pPlayer)->GetQuestStatus(12747) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29070: // Valok the Righteous - if (CAST_PLR(pPlayer)->GetQuestStatus(12746) == QUEST_STATUS_INCOMPLETE) - return true; - break; - } - - return false; - } - - void MoveInLineOfSight(Unit* pWho) - { - if (PlayerGUID || pWho->GetTypeId() != TYPEID_PLAYER || !pWho->IsWithinDist(me, INTERACTION_DISTANCE)) - return; - - if (MeetQuestCondition(pWho)) - PlayerGUID = pWho->GetGUID(); - } - - void UpdateAI(const uint32 diff) - { - if (PlayerGUID && !me->getVictim() && me->isAlive()) - { - if (ExecuteSpeech_Timer <= diff) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - - if (!pPlayer) - { - Reset(); - return; - } - - //TODO: simplify text's selection - - switch(pPlayer->getRace()) - { - case RACE_HUMAN: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_5, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_5, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_7, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_6, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_ORC: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_6, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_7, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_8, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_8, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_DWARF: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_2, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_2, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_3, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_2, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_5, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_2, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_3, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_NIGHTELF: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_5, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_6, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_2, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_7, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_UNDEAD_PLAYER: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_3, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_4, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_3, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_1, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_3, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_4, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_TAUREN: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_5, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_8, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_9, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_9, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_GNOME: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_4, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_4, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_6, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_5, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_TROLL: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_3, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_7, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_2, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_6, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_9, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_10, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_4, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_10, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_BLOODELF: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - //case 5: //unknown - case 6: DoScriptText(SAY_EXEC_THINK_3, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_1, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_DRAENEI: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_2, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_1, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_4, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_2, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - } - - if (ExecuteSpeech_Counter >= 9) - ExecuteSpeech_Timer = 15000; - else - ExecuteSpeech_Timer = 7000; - - ++ExecuteSpeech_Counter; - } - else - ExecuteSpeech_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_npc_a_special_surprise(Creature* pCreature) -{ - return new npc_a_special_surpriseAI(pCreature); -} - -void AddSC_the_scarlet_enclave_c2() -{ - Script *newscript; - - // How to win friends and influence enemies - newscript = new Script; - newscript->Name = "npc_crusade_persuaded"; - newscript->GetAI = &GetAI_npc_crusade_persuaded; - newscript->RegisterSelf(); - - // Ambush At The Overlook - newscript = new Script; - newscript->Name = "mob_scarlet_courier"; - newscript->GetAI = &GetAI_mob_scarlet_courier; - newscript->RegisterSelf(); - - // 12727 Bloody Breakout - newscript = new Script; - newscript->Name = "npc_koltira_deathweaver"; - newscript->GetAI = &GetAI_npc_koltira_deathweaver; - newscript->pQuestAccept = &QuestAccept_npc_koltira_deathweaver; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_high_inquisitor_valroth"; - newscript->GetAI = &GetAI_mob_high_inquisitor_valroth; - newscript->RegisterSelf(); - - // A Special Suprise - newscript = new Script; - newscript->Name = "npc_a_special_surprise"; - newscript->GetAI = &GetAI_npc_a_special_surprise; - newscript->RegisterSelf(); -} - -/* --- Bloody Breakout -UPDATE `creature_template` SET `ScriptName`='npc_koltira_deathweaver' WHERE `entry`='28912'; -UPDATE `creature_template` SET `ScriptName`='mob_high_inquisitor_valroth',minmana=6489,maxmana=6489,unit_flags=32768 WHERE `entry`='29001'; -UPDATE `creature_template` SET `ScriptName`='mob_eventai', `AIName`='EventAI',minmana=1020,maxmana=1058,unit_flags=32768 WHERE (`entry`='29007'); -DELETE FROM creature_ai_scripts WHERE id BETWEEN 90030 AND 90033; -INSERT INTO `creature_ai_scripts` VALUES ('90030', '29007', '0', '0', '100', '1', '1000', '4000', '1000', '4000', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Smite'); -INSERT INTO `creature_ai_scripts` VALUES ('90031', '29007', '0', '0', '100', '1', '1000', '10000', '20000', '21000', '11', '34809', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Fury'); -INSERT INTO `creature_ai_scripts` VALUES ('90032', '29007', '0', '0', '100', '1', '1000', '5000', '1000', '5000', '11', '19725', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Turn Undead'); -INSERT INTO `creature_ai_scripts` VALUES ('90033', '29007', '4', '0', '100', '0', '0', '0', '0', '0', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte aggro'); -*/ diff --git a/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter5.cpp b/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter5.cpp deleted file mode 100644 index 3b0ce186592..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter5.cpp +++ /dev/null @@ -1,1684 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -#define LESS_MOB // if you do not have a good server and do not want it to be laggy as hell -//Light of Dawn -enum mograine -{ -#ifdef LESS_MOB - ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - - ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data - ENCOUNTER_DEFENDER_NUMBER = 10, // how many of defender - ENCOUNTER_EARTHSHATTER_NUMBER = 1, // how many of earthshatter - ENCOUNTER_ABOMINATION_NUMBER = 2, // how many of abomination - ENCOUNTER_BEHEMOTH_NUMBER = 1, // how many of behemoth - ENCOUNTER_GHOUL_NUMBER = 5, // how many of ghoul - ENCOUNTER_WARRIOR_NUMBER = 1, // how many of warrior -#else - ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - - ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data - ENCOUNTER_DEFENDER_NUMBER = 20, // how many of defender - ENCOUNTER_EARTHSHATTER_NUMBER = 20, // how many of earthshatter - ENCOUNTER_ABOMINATION_NUMBER = 3, // how many of abomination - ENCOUNTER_BEHEMOTH_NUMBER = 2, // how many of behemoth - ENCOUNTER_GHOUL_NUMBER = 10, // how many of ghoul - ENCOUNTER_WARRIOR_NUMBER = 2, // how many of warrior -#endif - ENCOUNTER_TOTAL_DAWN = 300, // Total number - ENCOUNTER_TOTAL_SCOURGE = 10000, - - WORLD_STATE_REMAINS = 3592, - WORLD_STATE_COUNTDOWN = 3603, - WORLD_STATE_EVENT_BEGIN = 3605, - - SAY_LIGHT_OF_DAWN01 = -1609201, // pre text - SAY_LIGHT_OF_DAWN02 = -1609202, - SAY_LIGHT_OF_DAWN03 = -1609203, - SAY_LIGHT_OF_DAWN04 = -1609204, // intro - SAY_LIGHT_OF_DAWN05 = -1609205, - SAY_LIGHT_OF_DAWN06 = -1609206, - SAY_LIGHT_OF_DAWN07 = -1609207, // During the fight - Korfax, Champion of the Light - SAY_LIGHT_OF_DAWN08 = -1609208, // Lord Maxwell Tyrosus - SAY_LIGHT_OF_DAWN09 = -1609209, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN10 = -1609210, - SAY_LIGHT_OF_DAWN11 = -1609211, - SAY_LIGHT_OF_DAWN12 = -1609212, - SAY_LIGHT_OF_DAWN13 = -1609213, - SAY_LIGHT_OF_DAWN14 = -1609214, - SAY_LIGHT_OF_DAWN15 = -1609215, - SAY_LIGHT_OF_DAWN16 = -1609216, - SAY_LIGHT_OF_DAWN17 = -1609217, - SAY_LIGHT_OF_DAWN18 = -1609218, - SAY_LIGHT_OF_DAWN19 = -1609219, - SAY_LIGHT_OF_DAWN20 = -1609220, - SAY_LIGHT_OF_DAWN21 = -1609221, - SAY_LIGHT_OF_DAWN22 = -1609222, - SAY_LIGHT_OF_DAWN23 = -1609223, - SAY_LIGHT_OF_DAWN24 = -1609224, - SAY_LIGHT_OF_DAWN25 = -1609225, // After the fight - SAY_LIGHT_OF_DAWN26 = -1609226, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN27 = -1609227, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN28 = -1609228, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN29 = -1609229, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN30 = -1609230, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN31 = -1609231, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN32 = -1609232, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN33 = -1609233, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN34 = -1609234, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN35 = -1609235, // Darion Mograine - SAY_LIGHT_OF_DAWN36 = -1609236, // Darion Mograine - SAY_LIGHT_OF_DAWN37 = -1609237, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN38 = -1609238, // Darion Mograine - SAY_LIGHT_OF_DAWN39 = -1609239, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN40 = -1609240, // Darion Mograine - SAY_LIGHT_OF_DAWN41 = -1609241, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN42 = -1609242, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN43 = -1609243, // The Lich King - SAY_LIGHT_OF_DAWN44 = -1609244, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN45 = -1609245, // The Lich King - SAY_LIGHT_OF_DAWN46 = -1609246, // The Lich King - SAY_LIGHT_OF_DAWN47 = -1609247, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN48 = -1609248, // The Lich King - SAY_LIGHT_OF_DAWN49 = -1609249, // The Lich King - SAY_LIGHT_OF_DAWN50 = -1609250, // Lord Maxwell Tyrosus - SAY_LIGHT_OF_DAWN51 = -1609251, // The Lich King - SAY_LIGHT_OF_DAWN52 = -1609252, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN53 = -1609253, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN54 = -1609254, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN55 = -1609255, // The Lich King - SAY_LIGHT_OF_DAWN56 = -1609256, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN57 = -1609257, // The Lich King - SAY_LIGHT_OF_DAWN58 = -1609258, // The Lich King - SAY_LIGHT_OF_DAWN59 = -1609259, // The Lich King - SAY_LIGHT_OF_DAWN60 = -1609260, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN61 = -1609261, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN62 = -1609262, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN63 = -1609263, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN64 = -1609264, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN65 = -1609265, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN66 = -1609266, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN67 = -1609267, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN68 = -1609268, // Highlord Darion Mograine - - EMOTE_LIGHT_OF_DAWN01 = -1609269, // Emotes - EMOTE_LIGHT_OF_DAWN02 = -1609270, - EMOTE_LIGHT_OF_DAWN03 = -1609271, - EMOTE_LIGHT_OF_DAWN04 = -1609272, - EMOTE_LIGHT_OF_DAWN05 = -1609273, - EMOTE_LIGHT_OF_DAWN06 = -1609274, - EMOTE_LIGHT_OF_DAWN07 = -1609275, - EMOTE_LIGHT_OF_DAWN08 = -1609276, - EMOTE_LIGHT_OF_DAWN09 = -1609277, - EMOTE_LIGHT_OF_DAWN10 = -1609278, - EMOTE_LIGHT_OF_DAWN11 = -1609279, - EMOTE_LIGHT_OF_DAWN12 = -1609280, - EMOTE_LIGHT_OF_DAWN13 = -1609281, - EMOTE_LIGHT_OF_DAWN14 = -1609282, - EMOTE_LIGHT_OF_DAWN15 = -1609283, - EMOTE_LIGHT_OF_DAWN16 = -1609284, - EMOTE_LIGHT_OF_DAWN17 = -1609285, - EMOTE_LIGHT_OF_DAWN18 = -1609286, - - GO_LIGHT_OF_DAWN = 191330, - SPELL_THE_LIGHT_OF_DAWN_Q = 53606, // quest credit - - // ---- Dark Knight npc -------------------- - // Highlord Darion Mograine - NPC_HIGHLORD_DARION_MOGRAINE = 29173, - SPELL_ANTI_MAGIC_ZONE1 = 52893, - SPELL_DEATH_STRIKE = 53639, - SPELL_DEATH_EMBRACE = 53635, - SPELL_ICY_TOUCH1 = 49723, - SPELL_THE_LIGHT_OF_DAWN = 53658, - SPELL_THE_MIGHT_OF_MOGRAINE = 53642, // on players when begins - SPELL_UNHOLY_BLIGHT = 53640, - SPELL_ALEXANDROS_MOGRAINE_SPAWN = 53667, - SPELL_MOGRAINE_CHARGE = 53679, - SPELL_ASHBRINGER = 53701, - - // Koltira Deathweaver & Orbaz Bloodbane are using the same abilities - NPC_KOLTIRA_DEATHWEAVER = 29199, - NPC_ORBAZ_BLOODBANE = 29204, // this guy fleed - NPC_THASSARIAN = 29200, // he also does SPELL_THE_LIGHT_OF_DAWN 53658 - SPELL_BLOOD_STRIKE1 = 52374, - SPELL_DEATH_GRIP = 49576, - SPELL_ICY_TOUCH2 = 52372, - SPELL_PLAGUE_STRIKE1 = 50668, - // all do SPELL_HERO_AGGRO_AURA 53627 - - // Lich King - NPC_THE_LICH_KING = 29183, // show up at end - SPELL_APOCALYPSE = 53210, - SPELL_TELEPORT_VISUAL = 52233, - SPELL_SOUL_FEAST_ALEX = 53677, // on Alexandros - SPELL_SOUL_FEAST_TIRION = 53685, // on Tirion - SPELL_ICEBOUND_VISAGE = 53274, // not sure what is it for - SPELL_REBUKE = 53680, - - // others - NPC_RAMPAGING_ABOMINATION = 29186, - SPELL_CLEAVE1 = 53633, - SPELL_SCOURGE_HOOK = 50335, - SPELL_SCOURGE_AGGRO_AURA = 53624, - - NPC_FLESH_BEHEMOTH = 29190, // giant guy - SPELL_STOMP = 53634, - SPELL_THUNDERCLAP = 36706, - SPELL_HERO_AGGRO_AURA = 53627, - - NPC_ACHERUS_GHOUL = 29219, // just ghoul.... - SPELL_GHOULPLOSION = 53632, - - NPC_WARRIOR_OF_THE_FROZEN_WASTES = 29206, // use SPELL_CLEAVE 53631 - - NPC_HIGHLORD_ALEXANDROS_MOGRAINE = 29227, // ghost - NPC_DARION_MOGRAINE = 29228, // ghost - - // ---- Dawn npc -------------------- - // Highlord Tirion Fordring - NPC_HIGHLORD_TIRION_FORDRING = 29175, - EQUIP_HIGHLORD_TIRION_FORDRING = 13262, - SPELL_LAY_ON_HANDS = 53778, - SPELL_REBIRTH_OF_THE_ASHBRINGER = 53702, - SPELL_TIRION_CHARGE = 53705, - SPELL_TIRION_CHARGE_VISUAL = 53706, - - // others - NPC_KORFAX_CHAMPION_OF_THE_LIGHT = 29176, - SPELL_CLEAVE = 53631, - SPELL_HEROIC_LEAP = 53625, - - NPC_LORD_MAXWELL_TYROSUS = 29178, - NPC_LEONID_BARTHALOMEW_THE_REVERED = 29179, - NPC_DUKE_NICHOLAS_ZVERENHOFF = 29180, - - NPC_COMMANDER_ELIGOR_DAWNBRINGER = 29177, - SPELL_HOLY_LIGHT2 = 37979, - - NPC_RAYNE = 29181, - SPELL_REJUVENATION = 20664, - SPELL_STARFALL = 20678, - SPELL_TRANQUILITY = 25817, - SPELL_WRATH = 21807, - - NPC_DEFENDER_OF_THE_LIGHT = 29174, // also does SPELL_HEROIC_LEAP 53625 - SPELL_HOLY_LIGHT1 = 29427, - SPELL_HOLY_STRIKE = 53643, - SPELL_HOLY_WRATH = 53638, - SPELL_UPPERCUT = 53629, - - NPC_RIMBLAT_EARTHSHATTER = 29182, - SPELL_CHAIN_HEAL = 33642, - SPELL_THUNDER = 53630 -}; - -struct Locations -{ - float x, y, z, o; - uint32 id; -}; - -void UpdateWorldState(Map *map, uint32 id, uint32 state) -{ - Map::PlayerList const& players = map->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->SendUpdateWorldState(id,state); - } - } -} - -static Locations LightofDawnLoc[]= -{ - {2281.335, -5300.409, 85.170, 0}, // 0 Tirion Fordring loc - {2283.896, -5287.914, 83.066, 1.55}, // 1 Tirion Fordring loc2 - {2281.461, -5263.014, 81.164, 0}, // 2 Tirion charges - {2262.277, -5293.477, 82.167, 0}, // 3 Tirion run - {2270.286, -5287.73, 82.262, 0}, // 4 Tirion relocate - {2269.511, -5288.289, 82.225, 0}, // 5 Tirion forward - {2262.277, -5293.477, 82.167, 0}, // 6 Tirion runs to Darion - {2270.286, -5287.73, 82.262, 0}, - {2269.511, -5288.289, 82.225, 0}, - {2273.205, -5288.848, 82.617, 0}, // 9 Korfax loc1 - {2274.739, -5287.926, 82.684, 0}, // 10 Korfax loc2 - {2253.673, -5318.004, 81.724, 0}, // 11 Korfax kicked - {2287.028, -5309.644, 87.253, 0}, // 12 Maxwell loc1 - {2286.978, -5308.025, 86.83, 0}, // 13 Maxwell loc2 - {2248.877, -5307.586, 82.166, 0}, // 14 maxwell kicked - {2278.58, -5316.933, 88.319, 0}, // 15 Eligor loc1 - {2278.535, -5315.479, 88.08, 0}, // 16 Eligor loc2 - {2259.416, -5304.505, 82.149, 0}, // 17 eligor kicked - {2289.259, -5280.355, 82.112, 0}, // 18 Koltira loc1 - {2289.02, -5281.985, 82.207, 0}, // 19 Koltira loc2 - {2273.289, -5273.675, 81.701, 0}, // 20 Thassarian loc1 - {2273.332, -5275.544, 81.849, 0}, // 21 Thassarian loc2 - {2281.198, -5257.397, 80.224, 4.66}, // 22 Alexandros loc1 - {2281.156, -5259.934, 80.647, 0}, // 23 Alexandros loc2 - {2281.294, -5281.895, 82.445, 1.35}, // 24 Darion loc1 - {2281.093, -5263.013, 81.125, 0}, // 25 Darion loc1 - {2281.313, -5250.282, 79.322, 4.69}, // 26 Lich King spawns - {2281.523, -5261.058, 80.877, 0}, // 27 Lich king move forwards - {2272.709, -5255.552, 78.226, 0}, // 28 Lich king kicked - {2273.972, -5257.676, 78.862, 0} // 29 Lich king moves forward -}; - -struct npc_highlord_darion_mograineAI : public npc_escortAI -{ - npc_highlord_darion_mograineAI(Creature *pCreature) : npc_escortAI(pCreature) - { - Reset(); - } - - bool bIsBattle; - uint32 uiStep; - uint32 uiPhase_timer; - uint32 uiFight_duration; - uint32 uiTotal_dawn; - uint32 uiTotal_scourge; - uint32 uiSummon_counter; - - // Darion Mograine - uint32 uiAnti_magic_zone; - uint32 uiDeath_strike; - uint32 uiDeath_embrace; - uint32 uiIcy_touch; - uint32 uiUnholy_blight; - uint32 uiFight_speech; - uint32 uiSpawncheck; - uint32 uiTargetcheck; - - // Dawn - uint64 uiTirionGUID; - uint64 uiAlexandrosGUID; - uint64 uiDarionGUID; - uint64 uiKorfaxGUID; - uint64 uiMaxwellGUID; - uint64 uiEligorGUID; - uint64 uiRayneGUID; - uint64 uiDefenderGUID[ENCOUNTER_DEFENDER_NUMBER]; - uint64 uiEarthshatterGUID[ENCOUNTER_EARTHSHATTER_NUMBER]; - - // Death - uint64 uiKoltiraGUID; - uint64 uiOrbazGUID; - uint64 uiThassarianGUID; - uint64 uiLichKingGUID; - uint64 uiAbominationGUID[ENCOUNTER_ABOMINATION_NUMBER]; - uint64 uiBehemothGUID[ENCOUNTER_BEHEMOTH_NUMBER]; - uint64 uiGhoulGUID[ENCOUNTER_GHOUL_NUMBER]; - uint64 uiWarriorGUID[ENCOUNTER_WARRIOR_NUMBER]; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - bIsBattle = false; - uiStep = 0; - uiPhase_timer = 3000; - uiFight_duration = 300000; // 5 minutes - uiTotal_dawn = ENCOUNTER_TOTAL_DAWN; - uiTotal_scourge = ENCOUNTER_TOTAL_SCOURGE; - uiSummon_counter = 0; - - uiAnti_magic_zone = urand(1000,6000); - uiDeath_strike = urand(5000,10000); - uiDeath_embrace = urand(5000,10000); - uiIcy_touch = urand(5000,10000); - uiUnholy_blight = urand(5000,10000); - - uiFight_speech = 15000; - uiSpawncheck = 1000; - uiTargetcheck = 10000; - - me->SetStandState(UNIT_STAND_STATE_STAND); - me->Mount(25279); - me->SetVisibility(VISIBILITY_ON); - - UpdateWorldState(me->GetMap(), WORLD_STATE_REMAINS, 0); - //UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 0); - UpdateWorldState(me->GetMap(), WORLD_STATE_EVENT_BEGIN, 0); - - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiRayneGUID)) - pTemp->setDeathState(JUST_DIED); - - uiTirionGUID = NULL; - uiKorfaxGUID = NULL; - uiMaxwellGUID = NULL; - uiEligorGUID = NULL; - uiRayneGUID = NULL; - - for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiDefenderGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiDefenderGUID[i] = 0; - } - for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiEarthshatterGUID[i] = 0; - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->setDeathState(JUST_DIED); - - uiKoltiraGUID = NULL; - uiOrbazGUID = NULL; - uiThassarianGUID = NULL; - uiLichKingGUID = NULL; - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiAbominationGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiAbominationGUID[i] = 0; - } - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiBehemothGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiBehemothGUID[i] = 0; - } - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiGhoulGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiGhoulGUID[i] = 0; - } - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiWarriorGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiWarriorGUID[i] = 0; - } - } - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who == me) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void MoveInLineOfSight(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack() && me->IsHostileTo(who)) - if (me->IsWithinDistInMap(who, 20) && me->IsWithinLOSInMap(who)) - AttackStart(who); - } - - void SetHoldState(bool bOnHold) - { - SetEscortPaused(bOnHold); - } - - void WaypointReached(uint32 i) - { - switch (i) - { - case 0: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - SetHoldState(true); - break; - case 1: - SetHoldState(true); - - SpawnNPC(); - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN07, pTemp); - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN08, pTemp); - - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - NPCChangeTarget(uiGhoulGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - NPCChangeTarget(uiWarriorGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - NPCChangeTarget(uiAbominationGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - NPCChangeTarget(uiBehemothGUID[i]); - NPCChangeTarget(uiKoltiraGUID); - NPCChangeTarget(uiOrbazGUID); - NPCChangeTarget(uiThassarianGUID); - - me->Unmount(); - me->CastSpell(me, SPELL_THE_MIGHT_OF_MOGRAINE, true); // need to fix, on player only - - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - pTemp->Unmount(); - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - pTemp->Unmount(); - - bIsBattle = true; - break; - case 2: - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - DoCast(me, SPELL_THE_LIGHT_OF_DAWN); - break; - case 3: - { - //Unit* pTirion = Unit::GetCreature(*me, uiTirionGUID); - - DoScriptText(EMOTE_LIGHT_OF_DAWN05, me); - if (me->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) - me->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - { - if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) - pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[19].x, LightofDawnLoc[19].y, LightofDawnLoc[19].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - { - if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) - pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[21].x, LightofDawnLoc[21].y, LightofDawnLoc[21].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - { - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[10].x, LightofDawnLoc[10].y, LightofDawnLoc[10].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - { - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[13].x, LightofDawnLoc[13].y, LightofDawnLoc[13].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - { - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[16].x, LightofDawnLoc[16].y, LightofDawnLoc[16].z); - } - JumpToNextStep(10000); - } break; - case 4: - DoScriptText(SAY_LIGHT_OF_DAWN27, me); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); - SetHoldState(true); - break; - case 5: - DoScriptText(SAY_LIGHT_OF_DAWN33, me); - SetHoldState(true); - break; - case 6: - SetHoldState(true); - me->HandleEmoteCommand(EMOTE_ONESHOT_SPECIALATTACK1H); - JumpToNextStep(1000); - break; - case 7: - SetHoldState(true); - JumpToNextStep(2000); - break; - case 8: - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - me->CastSpell(pTemp, SPELL_ASHBRINGER, true); - DoScriptText(EMOTE_LIGHT_OF_DAWN14, me); - SetHoldState(true); - break; - } - } - - void EnterEvadeMode() - { - if (!bIsBattle)//do not reset self if we are in battle - npc_escortAI::EnterEvadeMode(); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (!bIsBattle) - { - if (uiPhase_timer <= diff) - { - // ******* Before battle ***************************************************************** - switch (uiStep) - { - case 0: // countdown - //UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 1); - break; - - case 1: // just delay - //UpdateWorldState(me->GetMap(), WORLD_STATE_REMAINS, 1); - UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 0); - UpdateWorldState(me->GetMap(), WORLD_STATE_EVENT_BEGIN, 1); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - JumpToNextStep(3000); - break; - - case 2: - DoScriptText(SAY_LIGHT_OF_DAWN04, me); - if (Creature* pKoltira = GetClosestCreatureWithEntry(me, NPC_KOLTIRA_DEATHWEAVER, 50.0f)) - uiKoltiraGUID = pKoltira->GetGUID(); - if (Creature* pOrbaz = GetClosestCreatureWithEntry(me, NPC_ORBAZ_BLOODBANE, 50.0f)) - uiOrbazGUID = pOrbaz->GetGUID(); - if (Creature* pThassarian = GetClosestCreatureWithEntry(me, NPC_THASSARIAN, 50.0f)) - uiThassarianGUID = pThassarian->GetGUID(); - JumpToNextStep(10000); - break; - - case 3: // rise - DoScriptText(SAY_LIGHT_OF_DAWN05, me); - JumpToNextStep(3000); - break; - - case 4: // summon ghoul - // Dunno whats the summon spell, so workaround - DoCast(me, 33271); // shack effect - uiPhase_timer = 500; - if (uiSummon_counter < ENCOUNTER_GHOUL_NUMBER) - { - Unit* pTemp = me->SummonCreature(NPC_ACHERUS_GHOUL, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->setFaction(2084); - uiGhoulGUID[uiSummon_counter] = pTemp->GetGUID(); - ++uiSummon_counter; - } - else - { - uiSummon_counter = 0; - ++uiStep; - } - break; - - case 5: // summon abomination - DoCast(me, 33271); // shack effect - uiPhase_timer = 500; - if (uiSummon_counter < ENCOUNTER_ABOMINATION_NUMBER) - { - Unit* pTemp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->setFaction(2084); - uiAbominationGUID[uiSummon_counter] = pTemp->GetGUID(); - ++uiSummon_counter; - } - else - { - uiSummon_counter = 0; - ++uiStep; - } - break; - - case 6: // summon warrior - DoCast(me, 33271); // shack effect - uiPhase_timer = 500; - if (uiSummon_counter < ENCOUNTER_WARRIOR_NUMBER) - { - Unit* pTemp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->setFaction(2084); - uiWarriorGUID[uiSummon_counter] = pTemp->GetGUID(); - ++uiSummon_counter; - } - else - { - uiSummon_counter = 0; - ++uiStep; - } - break; - - case 7: // summon warrior - DoCast(me, 33271); // shack effect - uiPhase_timer = 500; - if (uiSummon_counter < ENCOUNTER_BEHEMOTH_NUMBER) - { - Unit* pTemp = me->SummonCreature(NPC_FLESH_BEHEMOTH, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->setFaction(2084); - uiBehemothGUID[uiSummon_counter] = pTemp->GetGUID(); - ++uiSummon_counter; - } - else - { - uiSummon_counter = 0; - ++uiStep; - } - break; - - case 8: // summon announce - DoScriptText(SAY_LIGHT_OF_DAWN06, me); - JumpToNextStep(5000); - break; - - case 9: // charge begins - SetHoldState(false); - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - { - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) - { - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - { - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - } - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiAbominationGUID[i])) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiBehemothGUID[i])) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiGhoulGUID[i])) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiWarriorGUID[i])) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - JumpToNextStep(5000); - break; - - // ******* After battle ***************************************************************** - case 11: // Tirion starts to speak - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN28, pTemp); - JumpToNextStep(21000); - break; - - case 12: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN29, pTemp); - JumpToNextStep(13000); - break; - - case 13: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN30, pTemp); - JumpToNextStep(13000); - break; - - case 14: - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_LIGHT_OF_DAWN31, me); - JumpToNextStep(7000); - break; - - case 15: // summon gate - if (Unit* pTemp = me->SummonCreature(NPC_HIGHLORD_ALEXANDROS_MOGRAINE, LightofDawnLoc[22].x, LightofDawnLoc[22].y, LightofDawnLoc[22].z, LightofDawnLoc[22].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) - { - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->CastSpell(pTemp, SPELL_ALEXANDROS_MOGRAINE_SPAWN, true); - DoScriptText(EMOTE_LIGHT_OF_DAWN06, pTemp); - uiAlexandrosGUID = pTemp->GetGUID(); - } - JumpToNextStep(4000); - break; - - case 16: // Alexandros out - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - { - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[23].x, LightofDawnLoc[23].y, LightofDawnLoc[23].z); - DoScriptText(SAY_LIGHT_OF_DAWN32, pTemp); - } - SetHoldState(false); // makes darion turns back - JumpToNextStep(5000); - break; - - case 17: - me->SetStandState(UNIT_STAND_STATE_KNEEL); - DoScriptText(SAY_LIGHT_OF_DAWN34, me); - JumpToNextStep(5000); - break; - - case 18: // Darion's spirit out - if (Unit* pTemp = me->SummonCreature(NPC_DARION_MOGRAINE, LightofDawnLoc[24].x, LightofDawnLoc[24].y, LightofDawnLoc[24].z, LightofDawnLoc[24].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) - { - DoScriptText(SAY_LIGHT_OF_DAWN35, pTemp); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - uiDarionGUID = pTemp->GetGUID(); - } - JumpToNextStep(4000); - break; - - case 19: // runs to father - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - { - DoScriptText(EMOTE_LIGHT_OF_DAWN07, pTemp); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[25].x, LightofDawnLoc[25].y, LightofDawnLoc[25].z); - } - JumpToNextStep(4000); - break; - - case 20: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN36, pTemp); - JumpToNextStep(4000); - break; - - case 21: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - DoScriptText(EMOTE_LIGHT_OF_DAWN08, pTemp); - JumpToNextStep(4000); - break; - - case 22: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN37, pTemp); - JumpToNextStep(8000); - break; - - case 23: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN38, pTemp); - JumpToNextStep(8000); - break; - - case 24: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN39, pTemp); - - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) // Tirion moves forward here - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[1].x, LightofDawnLoc[1].y, LightofDawnLoc[1].z); - - JumpToNextStep(15000); - break; - - case 25: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN40, pTemp); - JumpToNextStep(11000); - break; - - case 26: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN41, pTemp); - JumpToNextStep(5000); - break; - - case 27: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - pTemp->setDeathState(JUST_DIED); - JumpToNextStep(24000); - break; - - case 28: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN42, pTemp); - JumpToNextStep(6000); - break; - - case 29: // lich king spawns - if (Unit* pTemp = me->SummonCreature(NPC_THE_LICH_KING, LightofDawnLoc[26].x, LightofDawnLoc[26].y, LightofDawnLoc[26].z, LightofDawnLoc[26].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) - { - DoScriptText(SAY_LIGHT_OF_DAWN43, pTemp); - uiLichKingGUID = pTemp->GetGUID(); - if (Unit* pAlex = Unit::GetCreature(*me, uiAlexandrosGUID)) - pTemp->CastSpell(pAlex, SPELL_SOUL_FEAST_ALEX, false); - } - JumpToNextStep(2000); - break; - - case 30: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) // just hide him - { - DoScriptText(EMOTE_LIGHT_OF_DAWN09, pTemp); - pTemp->SetVisibility(VISIBILITY_OFF); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - pTemp->InterruptNonMeleeSpells(false); - DoScriptText(SAY_LIGHT_OF_DAWN45, pTemp); - } - JumpToNextStep(3000); - break; - - case 31: - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(EMOTE_LIGHT_OF_DAWN10, me); - DoScriptText(SAY_LIGHT_OF_DAWN44, me); - JumpToNextStep(3000); - break; - - case 32: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[27].x, LightofDawnLoc[27].y, LightofDawnLoc[27].z); - JumpToNextStep(6000); - break; - - case 33: // Darion supports to jump to lich king here - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoCast(me, SPELL_MOGRAINE_CHARGE); // jumping charge -// doesn't make it looks well, so workarounds, Darion charges, looks better - me->SetSpeed(MOVE_RUN, 3.0f); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - SetHoldState(false); - JumpToNextStep(0); - break; - - case 35: // Lich king counterattacks - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - pTemp->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - DoScriptText(SAY_LIGHT_OF_DAWN46, pTemp); - } - me->SetSpeed(MOVE_RUN, 6.0f); - me->SetStandState(UNIT_STAND_STATE_DEAD); - SetHoldState(false); // Darion got kicked by lich king - JumpToNextStep(0); - break; - - case 37: // Lich king counterattacks - me->SetStandState(UNIT_STAND_STATE_KNEEL); - JumpToNextStep(3000); - break; - - case 38: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN47, pTemp); - JumpToNextStep(8000); - break; - - case 39: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN48, pTemp); - JumpToNextStep(15000); - break; - - case 40: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN49, pTemp); - JumpToNextStep(17000); - break; - - case 41: // Lich king - Apocalypse - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - DoScriptText(EMOTE_LIGHT_OF_DAWN11, pTemp); - DoScriptText(SAY_LIGHT_OF_DAWN51, pTemp); - if (Unit* pTirion = Unit::GetCreature(*me, uiTirionGUID)) - { - pTirion->SetStandState(UNIT_STAND_STATE_KNEEL); - //pTemp->CastSpell(pTirion, SPELL_APOCALYPSE, false); // not working - pTemp->CastSpell(pTirion, SPELL_SOUL_FEAST_TIRION, false); - DoScriptText(EMOTE_LIGHT_OF_DAWN12, pTirion); - } - } - JumpToNextStep(2000); - break; - - case 42: // Maxwell yells for attack - { - float fLichPositionX = 0, - fLichPositionY = 0, - fLichPositionZ = 0; - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - fLichPositionX = pTemp->GetPositionX(); - fLichPositionY = pTemp->GetPositionY(); - fLichPositionZ = pTemp->GetPositionZ(); - } - - if (fLichPositionX && fLichPositionY) - { - Unit* pTemp; - pTemp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->setFaction(me->getFaction()); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - uiDefenderGUID[0] = pTemp->GetGUID(); - - pTemp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->setFaction(me->getFaction()); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - uiEarthshatterGUID[0] = pTemp->GetGUID(); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - DoScriptText(SAY_LIGHT_OF_DAWN50, pTemp); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->HandleEmoteCommand(EMOTE_STATE_ATTACK_UNARMED); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - } - } - JumpToNextStep(4500); - break; - - case 43: // They all got kicked - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(EMOTE_LIGHT_OF_DAWN13, pTemp); - - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[14].x, LightofDawnLoc[14].y, LightofDawnLoc[14].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[11].x, LightofDawnLoc[11].y, LightofDawnLoc[11].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[17].x, LightofDawnLoc[17].y, LightofDawnLoc[17].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiDefenderGUID[0])) - { - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[0])) - { - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z); - } - JumpToNextStep(3000); - break; - - case 44: // make them stand up - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - JumpToNextStep(1000); - break; - - case 45: - DoScriptText(SAY_LIGHT_OF_DAWN52, me); - JumpToNextStep(5000); - break; - - case 46: // Darion stand up, "not today" - me->SetSpeed(MOVE_RUN, 1.0f); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_LIGHT_OF_DAWN53, me); - SetHoldState(false); // Darion throws sword - JumpToNextStep(7000); - break; - - case 47: // Ashbringer rebirth - me->SetStandState(UNIT_STAND_STATE_KNEEL); - DoScriptText(EMOTE_LIGHT_OF_DAWN15, me); - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_HIGHLORD_TIRION_FORDRING)); - pTemp->CastSpell(pTemp, SPELL_REBIRTH_OF_THE_ASHBRINGER, false); - } - JumpToNextStep(1000); - break; - - case 48: // Show the cleansing effect (dawn of light) - //if (GameObject* pGo = me->GetMap()->GetGameObject(uiDawnofLightGUID)) - // pGo->SetPhaseMask(128, true); - me->SummonGameObject(GO_LIGHT_OF_DAWN, 2283.896, -5287.914, 83.066, 0, 0, 0, 0, 0, 30000); - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - if (pTemp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER, 0)) - pTemp->RemoveAurasDueToSpell(SPELL_REBIRTH_OF_THE_ASHBRINGER); - pTemp->CastSpell(pTemp, 41542, false); // workarounds, light expoded, makes it cool - pTemp->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->InterruptNonMeleeSpells(false); - JumpToNextStep(2500); - break; - - case 49: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN54, pTemp); - JumpToNextStep(4000); - break; - - case 50: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN55, pTemp); - JumpToNextStep(5000); - break; - - case 51: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN56, pTemp); - JumpToNextStep(1000); - break; - - case 52: // Tiron charges - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - DoScriptText(EMOTE_LIGHT_OF_DAWN16, pTemp); - pTemp->CastSpell(pTemp, SPELL_TIRION_CHARGE, false); // jumping charge - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - pTemp->SetSpeed(MOVE_RUN, 3.0f); // workarounds, make Tirion still running - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2].x, LightofDawnLoc[2].y, LightofDawnLoc[2].z); - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->Relocate(LightofDawnLoc[28].x, LightofDawnLoc[28].y, LightofDawnLoc[28].z); // workarounds, he should kick back by Tirion, but here we relocate him - } - JumpToNextStep(1500); - break; - - case 53: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN57, pTemp); - JumpToNextStep(1000); - break; - - case 54: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - pTemp->SetSpeed(MOVE_RUN, 1.0f); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29].x, LightofDawnLoc[29].y, LightofDawnLoc[29].z); // 26 - } - JumpToNextStep(4000); - break; - - case 55: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); - JumpToNextStep(2000); - break; - - case 56: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - JumpToNextStep(1500); - break; - - case 57: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN58, pTemp); - JumpToNextStep(10000); - break; - - case 58: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN59, pTemp); - JumpToNextStep(10000); - break; - - case 59: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->CastSpell(pTemp, SPELL_TELEPORT_VISUAL, false); - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) // Tirion runs to Darion - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - pTemp->SetSpeed(MOVE_RUN, 1.0f); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[6].x, LightofDawnLoc[6].y, LightofDawnLoc[6].z); - } - JumpToNextStep(2500); - break; - - case 60: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) // Lich king disappears here - { - DoScriptText(EMOTE_LIGHT_OF_DAWN17, pTemp); - pTemp->Kill(pTemp); - } - JumpToNextStep(10000); - break; - - case 61: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN60, pTemp); - JumpToNextStep(3000); - break; - - case 62: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[7].x, LightofDawnLoc[7].y, LightofDawnLoc[7].z); - } - JumpToNextStep(5500); - break; - - case 63: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[8].x, LightofDawnLoc[8].y, LightofDawnLoc[8].z); - DoScriptText(SAY_LIGHT_OF_DAWN61, pTemp); - } - JumpToNextStep(15000); - break; - - case 64: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN62, pTemp); - JumpToNextStep(7000); - break; - - case 65: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN63, pTemp); - JumpToNextStep(10000); - break; - - case 66: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN64, pTemp); - JumpToNextStep(11000); - break; - - case 67: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN65, pTemp); - JumpToNextStep(10000); - break; - - case 68: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN66, pTemp); - JumpToNextStep(8000); - break; - - case 69: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN67, pTemp); - JumpToNextStep(10000); - break; - - case 70: - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_LIGHT_OF_DAWN68, me); - JumpToNextStep(10000); - break; - - case 71: - //if (GameObject* pGo = me->GetMap()->GetGameObject(uiDawnofLightGUID)) // Turn off dawn of light - // pGo->SetPhaseMask(0, true); - - { - Map *map = me->GetMap(); // search players with in 50 yards for quest credit - Map::PlayerList const &PlayerList = map->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource()->isAlive() && me->IsWithinDistInMap(i->getSource(), 50)) - i->getSource()->CastSpell(i->getSource(), SPELL_THE_LIGHT_OF_DAWN_Q, false); - } - } - me->SetVisibility(VISIBILITY_OFF); // respawns another Darion for quest turn in - me->SummonCreature(NPC_HIGHLORD_DARION_MOGRAINE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); - JumpToNextStep(1000); - break; - - case 72: - SetHoldState(false); // Escort ends - JumpToNextStep(25000); - break; - - case 73: - me->ForcedDespawn(); - break; - } - - } else uiPhase_timer -= diff; - } - - // ******* During battle ***************************************************************** - else - { - if (uiAnti_magic_zone <= diff) - { - DoCast(me, SPELL_ANTI_MAGIC_ZONE1); - uiAnti_magic_zone = 25000 + rand()%5000; - } else uiAnti_magic_zone -= diff; - - if (uiDeath_strike <= diff) - { - DoCast(me->getVictim(), SPELL_DEATH_STRIKE); - uiDeath_strike = 5000 + rand()%5000; - } else uiDeath_strike -= diff; - - if (uiDeath_embrace <= diff) - { - DoCast(me->getVictim(), SPELL_DEATH_EMBRACE); - uiDeath_embrace = 5000 + rand()%5000; - } else uiDeath_embrace -= diff; - - if (uiIcy_touch <= diff) - { - DoCast(me->getVictim(), SPELL_ICY_TOUCH1); - uiIcy_touch = 5000 + rand()%5000; - } else uiIcy_touch -= diff; - - if (uiUnholy_blight <= diff) - { - DoCast(me->getVictim(), SPELL_UNHOLY_BLIGHT); - uiUnholy_blight = 5000 + rand()%5000; - } else uiUnholy_blight -= diff; - - if (uiFight_speech <= diff) - { - DoScriptText(RAND(SAY_LIGHT_OF_DAWN09,SAY_LIGHT_OF_DAWN10,SAY_LIGHT_OF_DAWN11, - SAY_LIGHT_OF_DAWN12,SAY_LIGHT_OF_DAWN13,SAY_LIGHT_OF_DAWN14, - SAY_LIGHT_OF_DAWN15,SAY_LIGHT_OF_DAWN16,SAY_LIGHT_OF_DAWN17, - SAY_LIGHT_OF_DAWN18,SAY_LIGHT_OF_DAWN19,SAY_LIGHT_OF_DAWN20, - SAY_LIGHT_OF_DAWN21,SAY_LIGHT_OF_DAWN22,SAY_LIGHT_OF_DAWN23, - SAY_LIGHT_OF_DAWN24), me); - uiFight_speech = 15000 + rand()%5000; - } else uiFight_speech -= diff; - - // Check spawns - if (uiSpawncheck <= diff) - { - SpawnNPC(); - uiSpawncheck = 1000; - } else uiSpawncheck -= diff; - - // Check targets - if (uiTargetcheck <= diff) - { - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - NPCChangeTarget(uiGhoulGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - NPCChangeTarget(uiWarriorGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - NPCChangeTarget(uiAbominationGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - NPCChangeTarget(uiBehemothGUID[i]); - NPCChangeTarget(uiKoltiraGUID); - NPCChangeTarget(uiOrbazGUID); - NPCChangeTarget(uiThassarianGUID); - - uiTargetcheck = 10000; - } else uiTargetcheck -= diff; - - // Battle end - if (uiFight_duration <= diff + 5000) - { - if (!uiTirionGUID) - if (Unit* pTemp = me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING, LightofDawnLoc[0].x, LightofDawnLoc[0].y, LightofDawnLoc[0].z, 1.528, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000)) - { - pTemp->setFaction(me->getFaction()); - pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); - DoScriptText(SAY_LIGHT_OF_DAWN25, pTemp); - uiTirionGUID = pTemp->GetGUID(); - } - } - if (uiFight_duration <= diff) - { - bIsBattle = false; - uiFight_duration = 300000; - - if (me->HasAura(SPELL_THE_MIGHT_OF_MOGRAINE, 0)) - me->RemoveAurasDueToSpell(SPELL_THE_MIGHT_OF_MOGRAINE); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->InterruptNonMeleeSpells(false); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) - DespawnNPC(uiDefenderGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) - DespawnNPC(uiEarthshatterGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - DespawnNPC(uiAbominationGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - DespawnNPC(uiBehemothGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - DespawnNPC(uiGhoulGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - DespawnNPC(uiWarriorGUID[i]); - - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[9].x, LightofDawnLoc[9].y, LightofDawnLoc[9].z); - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[12].x, LightofDawnLoc[12].y, LightofDawnLoc[12].z); - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[15].x, LightofDawnLoc[15].y, LightofDawnLoc[15].z); - } - DespawnNPC(uiRayneGUID); - - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[18].x, LightofDawnLoc[18].y, LightofDawnLoc[18].z); - pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false); - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) - DoScriptText(EMOTE_LIGHT_OF_DAWN04, pTemp); - - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[20].x, LightofDawnLoc[20].y, LightofDawnLoc[20].z); - pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false); - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN26, pTemp); - - SetHoldState(false); - - } else uiFight_duration -= diff; - - DoMeleeAttackIfReady(); - } - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhase_timer = uiTimer; - ++uiStep; - } - - void NPCChangeTarget(uint64 ui_GUID) - { - if (Creature* pTemp = Unit::GetCreature(*me, ui_GUID)) - if (pTemp->isAlive()) - if (Unit* pTarger = SelectUnit(SELECT_TARGET_RANDOM,0)) - if (pTarger->isAlive()) - { - // pTemp->DeleteThreatList(); - pTemp->AddThreat(pTarger, 0.0f); - pTemp->AI()->AttackStart(pTarger); - pTemp->SetInCombatWith(pTarger); - pTarger->SetInCombatWith(pTemp); - // pTemp->GetMotionMaster()->MoveChase(pTarger, 20.0f); - } - } - - void SpawnNPC() - { - Unit* pTemp = NULL; - - // Death - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiGhoulGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_ACHERUS_GHOUL, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2084); - uiGhoulGUID[i] = pTemp->GetGUID(); - } - } - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiAbominationGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2084); - uiAbominationGUID[i] = pTemp->GetGUID(); - } - } - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiWarriorGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2084); - uiWarriorGUID[i] = pTemp->GetGUID(); - } - } - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiBehemothGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_FLESH_BEHEMOTH, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2084); - uiBehemothGUID[i] = pTemp->GetGUID(); - } - } - - // Dawn - for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiDefenderGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiDefenderGUID[i] = pTemp->GetGUID(); - } - } - for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiEarthshatterGUID[i] = pTemp->GetGUID(); - } - } - pTemp = Unit::GetCreature(*me, uiKorfaxGUID); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_KORFAX_CHAMPION_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiKorfaxGUID = pTemp->GetGUID(); - } - pTemp = Unit::GetCreature(*me, uiMaxwellGUID); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_LORD_MAXWELL_TYROSUS, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiMaxwellGUID = pTemp->GetGUID(); - } - pTemp = Unit::GetCreature(*me, uiEligorGUID); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_COMMANDER_ELIGOR_DAWNBRINGER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiEligorGUID = pTemp->GetGUID(); - } - pTemp = Unit::GetCreature(*me, uiRayneGUID); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_RAYNE, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiRayneGUID = pTemp->GetGUID(); - } - } - - void DespawnNPC(uint64 pGUID) - { - if (Creature* pTemp = Unit::GetCreature(*me, pGUID)) - if (pTemp->isAlive()) - { - pTemp->SetVisibility(VISIBILITY_OFF); - pTemp->Kill(pTemp); - } - } -}; - -bool GossipHello_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(12801) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(0, "I am ready.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_highlord_darion_mograineAI, pCreature->AI())->uiStep = 1; - CAST_AI(npc_highlord_darion_mograineAI, pCreature->AI())->Start(true, false, pPlayer->GetGUID()); - break; - } - return true; -} - -/*###### -## npc the lich king in dawn of light -######*/ -struct npc_the_lich_king_tirion_dawnAI : public ScriptedAI -{ - npc_the_lich_king_tirion_dawnAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } - void Reset() {} - void AttackStart(Unit * /*who*/) {} // very sample, just don't make them aggreesive - void UpdateAI(const uint32 /*diff*/) {} - void JustDied(Unit* /*killer*/) {} -}; - -CreatureAI* GetAI_npc_highlord_darion_mograine(Creature* pCreature) -{ - return new npc_highlord_darion_mograineAI(pCreature); -} - -CreatureAI* GetAI_npc_the_lich_king_tirion_dawn(Creature* pCreature) -{ - return new npc_the_lich_king_tirion_dawnAI (pCreature); -} - -void AddSC_the_scarlet_enclave_c5() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_highlord_darion_mograine"; - newscript->GetAI = &GetAI_npc_highlord_darion_mograine; - newscript->pGossipHello = &GossipHello_npc_highlord_darion_mograine; - newscript->pGossipSelect = &GossipSelect_npc_highlord_darion_mograine; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_the_lich_king_tirion_dawn"; - newscript->GetAI = &GetAI_npc_the_lich_king_tirion_dawn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/scarlet_enclave/the_scarlet_enclave.cpp b/src/server/scripts/eastern_kingdoms/scarlet_enclave/the_scarlet_enclave.cpp deleted file mode 100644 index cdfd69234fb..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_enclave/the_scarlet_enclave.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" - -/*#### -## npc_valkyr_battle_maiden -####*/ -#define SPELL_REVIVE 51918 -#define VALK_WHISPER "It is not yet your time, champion. Rise! Rise and fight once more!" - -struct npc_valkyr_battle_maidenAI : public PassiveAI -{ - npc_valkyr_battle_maidenAI(Creature *c) : PassiveAI(c) {} - - uint32 FlyBackTimer; - float x, y, z; - uint32 phase; - - void Reset() - { - me->setActive(true); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlying(true); - FlyBackTimer = 500; - phase = 0; - - me->GetPosition(x, y, z); - z += 4; x -= 3.5; y -= 5; - me->GetMotionMaster()->Clear(false); - me->GetMap()->CreatureRelocation(me, x, y, z, 0.0f); - } - - void UpdateAI(const uint32 diff) - { - if (FlyBackTimer <= diff) - { - Player *plr = NULL; - if (me->isSummon()) - if (Unit *summoner = CAST_SUM(me)->GetSummoner()) - if (summoner->GetTypeId() == TYPEID_PLAYER) - plr = CAST_PLR(summoner); - - if (!plr) - phase = 3; - - switch(phase) - { - case 0: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->HandleEmoteCommand(EMOTE_STATE_FLYGRABCLOSED); - FlyBackTimer = 500; - break; - case 1: - plr->GetClosePoint(x,y,z, me->GetObjectSize()); - z += 2.5; x -= 2; y -= 1.5; - me->GetMotionMaster()->MovePoint(0, x, y, z); - me->SetUInt64Value(UNIT_FIELD_TARGET, plr->GetGUID()); - me->SetVisibility(VISIBILITY_ON); - FlyBackTimer = 4500; - break; - case 2: - if (!plr->isRessurectRequested()) - { - me->HandleEmoteCommand(EMOTE_ONESHOT_CUSTOMSPELL01); - DoCast(plr, SPELL_REVIVE, true); - me->MonsterWhisper(VALK_WHISPER, plr->GetGUID()); - } - FlyBackTimer = 5000; - break; - case 3: - me->SetVisibility(VISIBILITY_OFF); - FlyBackTimer = 3000; - break; - case 4: - me->DisappearAndDie(); - break; - default: - //Nothing To DO - break; - } - ++phase; - } else FlyBackTimer-=diff; - } -}; - -CreatureAI* GetAI_npc_valkyr_battle_maiden(Creature* pCreature) -{ - return new npc_valkyr_battle_maidenAI (pCreature); -} - -void AddSC_the_scarlet_enclave() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_valkyr_battle_maiden"; - newscript->GetAI = &GetAI_npc_valkyr_battle_maiden; - newscript->RegisterSelf(); - - // Chapter 3: Scarlet Armies Approach... - An End To All Things... - // Chapter 4: An End To All Things... - An End To All Things... -} diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp deleted file mode 100644 index cb6ed1daf22..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Arcanist_Doan -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1189019, - SAY_SPECIALAE = -1189020, - - SPELL_POLYMORPH = 13323, - SPELL_AOESILENCE = 8988, - SPELL_ARCANEEXPLOSION = 9433, - SPELL_FIREAOE = 9435, - SPELL_ARCANEBUBBLE = 9438, -}; - -struct boss_arcanist_doanAI : public ScriptedAI -{ - boss_arcanist_doanAI(Creature *c) : ScriptedAI(c) {} - - uint32 Polymorph_Timer; - uint32 AoESilence_Timer; - uint32 ArcaneExplosion_Timer; - bool bCanDetonate; - bool bShielded; - - void Reset() - { - Polymorph_Timer = 20000; - AoESilence_Timer = 15000; - ArcaneExplosion_Timer = 3000; - bCanDetonate = false; - bShielded = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (bShielded && bCanDetonate) - { - DoCast(me, SPELL_FIREAOE); - bCanDetonate = false; - } - - if (me->HasAura(SPELL_ARCANEBUBBLE)) - return; - - //If we are <50% hp cast Arcane Bubble - if (!bShielded && me->GetHealth()*100 / me->GetMaxHealth() <= 50) - { - //wait if we already casting - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoScriptText(SAY_SPECIALAE, me); - DoCast(me, SPELL_ARCANEBUBBLE); - - bCanDetonate = true; - bShielded = true; - } - - if (Polymorph_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_POLYMORPH); - - Polymorph_Timer = 20000; - } else Polymorph_Timer -= diff; - - //AoESilence_Timer - if (AoESilence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_AOESILENCE); - AoESilence_Timer = 15000 + rand()%5000; - } else AoESilence_Timer -= diff; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANEEXPLOSION); - ArcaneExplosion_Timer = 8000; - } else ArcaneExplosion_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_arcanist_doan(Creature* pCreature) -{ - return new boss_arcanist_doanAI (pCreature); -} - -void AddSC_boss_arcanist_doan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_arcanist_doan"; - newscript->GetAI = &GetAI_boss_arcanist_doan; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp deleted file mode 100644 index 6b6efa0f934..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Azshir_the_Sleepless -SD%Complete: 80 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CALLOFTHEGRAVE 17831 -#define SPELL_TERRIFY 7399 -#define SPELL_SOULSIPHON 7290 - -struct boss_azshir_the_sleeplessAI : public ScriptedAI -{ - boss_azshir_the_sleeplessAI(Creature *c) : ScriptedAI(c) {} - - uint32 SoulSiphon_Timer; - uint32 CallOftheGrave_Timer; - uint32 Terrify_Timer; - - void Reset() - { - SoulSiphon_Timer = 1; - CallOftheGrave_Timer = 30000; - Terrify_Timer = 20000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <50% hp cast Soul Siphon rank 1 - if (me->GetHealth()*100 / me->GetMaxHealth() <= 50 && !me->IsNonMeleeSpellCasted(false)) - { - //SoulSiphon_Timer - if (SoulSiphon_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOULSIPHON); - return; - - //SoulSiphon_Timer = 20000; - } else SoulSiphon_Timer -= diff; - } - - //CallOfTheGrave_Timer - if (CallOftheGrave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CALLOFTHEGRAVE); - CallOftheGrave_Timer = 30000; - } else CallOftheGrave_Timer -= diff; - - //Terrify_Timer - if (Terrify_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TERRIFY); - Terrify_Timer = 20000; - } else Terrify_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_azshir_the_sleepless(Creature* pCreature) -{ - return new boss_azshir_the_sleeplessAI (pCreature); -} - -void AddSC_boss_azshir_the_sleepless() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_azshir_the_sleepless"; - newscript->GetAI = &GetAI_boss_azshir_the_sleepless; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp deleted file mode 100644 index f7b6b7cce4b..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Bloodmage_Thalnos -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1189016, - SAY_HEALTH = -1189017, - SAY_KILL = -1189018, - - SPELL_FLAMESHOCK = 8053, - SPELL_SHADOWBOLT = 1106, - SPELL_FLAMESPIKE = 8814, - SPELL_FIRENOVA = 16079, -}; - -struct boss_bloodmage_thalnosAI : public ScriptedAI -{ - boss_bloodmage_thalnosAI(Creature *c) : ScriptedAI(c) {} - - bool HpYell; - uint32 FlameShock_Timer; - uint32 ShadowBolt_Timer; - uint32 FlameSpike_Timer; - uint32 FireNova_Timer; - - void Reset() - { - HpYell = false; - FlameShock_Timer = 10000; - ShadowBolt_Timer = 2000; - FlameSpike_Timer = 8000; - FireNova_Timer = 40000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*Victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <35% hp - if (!HpYell && ((me->GetHealth()*100) / me->GetMaxHealth() <= 35)) - { - DoScriptText(SAY_HEALTH, me); - HpYell = true; - } - - //FlameShock_Timer - if (FlameShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMESHOCK); - FlameShock_Timer = 10000 + rand()%5000; - } else FlameShock_Timer -= diff; - - //FlameSpike_Timer - if (FlameSpike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMESPIKE); - FlameSpike_Timer = 30000; - } else FlameSpike_Timer -= diff; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRENOVA); - FireNova_Timer = 40000; - } else FireNova_Timer -= diff; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLT); - ShadowBolt_Timer = 2000; - } else ShadowBolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_bloodmage_thalnos(Creature* pCreature) -{ - return new boss_bloodmage_thalnosAI (pCreature); -} - -void AddSC_boss_bloodmage_thalnos() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_bloodmage_thalnos"; - newscript->GetAI = &GetAI_boss_bloodmage_thalnos; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp deleted file mode 100644 index 17bbf0c23c6..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp +++ /dev/null @@ -1,892 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Headless_Horseman -SD%Complete: -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "SpellMgr.h" -#include "scarlet_monastery.h" - -//this texts are already used by 3975 and 3976 -#define SAY_ENTRANCE -1189001 -#define SAY_REJOINED -1189002 -#define SAY_LOST_HEAD -1189003 -#define SAY_CONFLAGRATION -1189004 -#define SAY_SPROUTING_PUMPKINS -1189005 -#define SAY_PLAYER_DEATH -1189006 -#define SAY_DEATH -1189007 - -uint32 RandomLaugh[] = {11965, 11975, 11976}; - - // Entryes -#define HH_MOUNTED 23682 -#define HH_UNHORSED 23800 -#define HEAD 23775 -#define PULSING_PUMPKIN 23694 -#define PUMPKIN_FIEND 23545 -#define HELPER 23686 -#define WISP_INVIS 24034 - - //Spells -#define SPELL_CLEAVE 42587 -#define SPELL_CONFLAGRATION 42380 //Phase 2, can't find real spell(Dim Fire?) -//#define SPELL_CONFL_SPEED 22587 //8% increase speed, value 22587 from SPELL_CONFLAGRATION mains that spell? -#define SPELL_SUMMON_PUMPKIN 42394 - -#define SPELL_WHIRLWIND 43116 -#define SPELL_IMMUNE 42556 -#define SPELL_BODY_REGEN 42403 -#define SPELL_CONFUSE 43105 - -#define SPELL_FLYING_HEAD 42399 //visual flying head -#define SPELL_HEAD 42413 //visual buff, "head" -#define SPELL_HEAD_IS_DEAD 42428 //at killing head, Phase 3 - -#define SPELL_PUMPKIN_AURA 42280 -#define SPELL_PUMPKIN_AURA_GREEN 42294 -#define SPELL_SQUASH_SOUL 42514 -#define SPELL_SPROUTING 42281 -#define SPELL_SPROUT_BODY 42285 - - //Effects -#define SPELL_RHYME_BIG 42909 -//#define SPELL_RHYME_SMALL 42910 -#define SPELL_HEAD_SPEAKS 43129 -#define SPELL_HEAD_LANDS 42400 -#define SPELL_BODY_FLAME 42074 -#define SPELL_HEAD_FLAME 42971 -//#define SPELL_ENRAGE_VISUAL 42438 // he uses this spell? -#define SPELL_WISP_BLUE 42821 -#define SPELL_WISP_FLIGHT_PORT 42818 -//#define SPELL_WISP_INVIS 42823 -#define SPELL_SMOKE 42355 -#define SPELL_DEATH 42566 //not correct spell - -struct Locations -{ - float x, y, z; -}; - -static Locations FlightPoint[]= -{ - {1754.00,1346.00,17.50}, - {1765.00,1347.00,19.00}, - {1784.00,1346.80,25.40}, - {1803.30,1347.60,33.00}, - {1824.00,1350.00,42.60}, - {1838.80,1353.20,49.80}, - {1852.00,1357.60,55.70}, - {1861.30,1364.00,59.40}, - {1866.30,1374.80,61.70}, - {1864.00,1387.30,63.20}, - {1854.80,1399.40,64.10}, - {1844.00,1406.90,64.10}, - {1824.30,1411.40,63.30}, - {1801.00,1412.30,60.40}, - {1782.00,1410.10,55.50}, - {1770.50,1405.20,50.30}, - {1765.20,1400.70,46.60}, - {1761.40,1393.40,41.70}, - {1759.10,1386.70,36.60}, - {1757.80,1378.20,29.00}, - {1758.00,1367.00,19.51} -}; - -static Locations Spawn[]= -{ - {1776.27,1348.74,19.20}, //spawn point for pumpkin shrine mob - {1765.28,1347.46,17.55} //spawn point for smoke -}; - -static const char* Text[]= -{ - "Horseman rise...", - "Your time is nigh...", - "You felt death once...", - "Now, know demise!" -}; - -#define EMOTE_LAUGHS "Headless Horseman laughs" - -struct mob_wisp_invisAI : public ScriptedAI -{ - mob_wisp_invisAI(Creature *c) : ScriptedAI(c) - { - Creaturetype = delay = spell = spell2 = 0; - //that's hack but there are no info about range of this spells in dbc - SpellEntry *wisp = GET_SPELL(SPELL_WISP_BLUE); - if (wisp) - wisp->rangeIndex = 6; //100 yards - SpellEntry *port = GET_SPELL(SPELL_WISP_FLIGHT_PORT); - if (port) - port->rangeIndex = 6; - } - - uint32 Creaturetype; - uint32 delay; - uint32 spell; - uint32 spell2; - void Reset(){} - void EnterCombat(Unit * /*who*/){} - void SetType(uint32 _type) - { - switch(Creaturetype = _type) - { - case 1: - spell = SPELL_PUMPKIN_AURA_GREEN; - break; - case 2: - delay = 15000; - spell = SPELL_BODY_FLAME; - spell2 = SPELL_DEATH; - break; - case 3: - delay = 15000; - spell = SPELL_SMOKE; - break; - case 4: - delay = 7000; - spell2 = SPELL_WISP_BLUE; - break; - } - if (spell) - DoCast(me, spell); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_WISP_FLIGHT_PORT && Creaturetype == 4) - me->SetDisplayId(2027); - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || Creaturetype != 1 || !who->isTargetableForAttack()) - return; - - if (me->IsWithinDist(who, 0.1, false) && !who->HasAura(SPELL_SQUASH_SOUL)) - DoCast(who, SPELL_SQUASH_SOUL); - } - - void UpdateAI(const uint32 diff) - { - if (delay) - { - if (delay <= diff) - { - me->RemoveAurasDueToSpell(SPELL_SMOKE); - if (spell2) - DoCast(me, spell2); - delay = 0; - } else delay -= diff; - } - } -}; - -struct mob_headAI : public ScriptedAI -{ - mob_headAI(Creature *c) : ScriptedAI(c) {} - - uint64 bodyGUID; - - uint32 Phase; - uint32 laugh; - uint32 wait; - - bool withbody; - bool die; - - void Reset() - { - Phase = 0; - bodyGUID = 0; - die = false; - withbody = true; - wait = 1000; - laugh = urand(15000,30000); - } - - void EnterCombat(Unit * /*who*/) {} - void SaySound(int32 textEntry, Unit *pTarget = 0) - { - DoScriptText(textEntry, me, pTarget); - //DoCast(me, SPELL_HEAD_SPEAKS, true); - Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000); - if (speaker) - speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); - laugh += 3000; - } - - void DamageTaken(Unit* /*done_by*/,uint32 &damage) - { - if (withbody) - return; - - switch(Phase) - { - case 1: - if (((me->GetHealth() - damage)*100)/me->GetMaxHealth() < 67) - Disappear(); - break; - case 2: - if (((me->GetHealth() - damage)*100)/me->GetMaxHealth() < 34) - Disappear(); - break; - case 3: - if (damage >= me->GetHealth()) - { - die = true; - withbody = true; - wait = 300; - damage = me->GetHealth() - me->GetMaxHealth()/100; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->StopMoving(); - //me->GetMotionMaster()->MoveIdle(); - DoCast(me, SPELL_HEAD_IS_DEAD); - } - break; - } - } - - void SpellHit(Unit *caster, const SpellEntry* spell) - { - if (!withbody) - return; - - if (spell->Id == SPELL_FLYING_HEAD) - { - if (Phase < 3) ++Phase; - else Phase = 3; - withbody = false; - if (!bodyGUID) - bodyGUID = caster->GetGUID(); - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_HEAD_LANDS, true); - DoCast(me, SPELL_HEAD, false); - SaySound(SAY_LOST_HEAD); - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFleeing(caster->getVictim()); - } - } - void Disappear();//we must set returned=true(this will prevent from "body calls head" while head flying to body), see function below - void UpdateAI(const uint32 diff) - { - if (!withbody) - { - if (wait <= diff) - { - wait = 1000; - if (!me->getVictim()) return; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFleeing(me->getVictim()); - } else wait -= diff; - - if (laugh <= diff) - { - laugh = urand(15000,30000); - DoPlaySoundToSet(me, RandomLaugh[urand(0,2)]); - //DoCast(me, SPELL_HEAD_SPEAKS, true); //this spell remove buff "head" - Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000); - if (speaker) - speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); - me->MonsterTextEmote(EMOTE_LAUGHS,NULL); - } else laugh -= diff; - } - else - { - if (die) - { - if (wait <= diff) - { - die = false; - if (Unit *body = Unit::GetUnit((*me), bodyGUID)) - body->Kill(body); - me->Kill(me); - } else wait -= diff; - } - } - } -}; - -struct boss_headless_horsemanAI : public ScriptedAI -{ - boss_headless_horsemanAI(Creature *c) : ScriptedAI(c) - { - SpellEntry *confl = GET_SPELL(SPELL_CONFLAGRATION); - if (confl) - { - confl->EffectApplyAuraName[0] = SPELL_AURA_PERIODIC_DAMAGE_PERCENT; - confl->EffectBasePoints[0] = 10; - //confl->EffectBaseDice[0] = 10; - confl->DmgMultiplier[0] = 1; - } -/* - if (SpellEntry *confl = GET_SPELL(SPELL_CONFLAGRATION)) - confl->EffectTriggerSpell[1] = 22587; - - if (SpellEntry *speed = GET_SPELL(22587)) - { - speed->Effect[1] = SPELL_EFFECT_APPLY_AURA; - speed->EffectApplyAuraName[1] = SPELL_AURA_MOD_CONFUSE; - } -*/ - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint64 headGUID; - uint64 PlayerGUID; - - uint32 Phase; - uint32 id; - uint32 count; - uint32 say_timer; - - uint32 conflagrate; - uint32 summonadds; - uint32 cleave; - uint32 regen; - uint32 whirlwind; - uint32 laugh; - uint32 burn; - - bool withhead; - bool returned; - bool IsFlying; - bool wp_reached; - bool burned; - - void Reset() - { - Phase = 1; - conflagrate = 15000; - summonadds = 15000; - laugh = urand(16000,20000); - cleave = 2000; - regen = 1000; - burn = 6000; - count = 0; - say_timer = 3000; - - withhead = true; - returned = true; - burned = false; - IsFlying = false; - DoCast(me, SPELL_HEAD); - if (headGUID) - { - if (Creature* Head = Unit::GetCreature((*me), headGUID)) - Head->DisappearAndDie(); - - headGUID = 0; - } - - //if (pInstance) - // pInstance->SetData(DATA_HORSEMAN_EVENT, NOT_STARTED); - } - - void FlyMode() - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); - me->SetSpeed(MOVE_WALK,5.0f,true); - wp_reached = false; - count = 0; - say_timer = 3000; - id = 0; - Phase = 0; - } - - void MovementInform(uint32 type, uint32 i) - { - if (type != POINT_MOTION_TYPE || !IsFlying || i != id) - return; - - wp_reached = true; - - switch (id) - { - case 0: - me->SetVisibility(VISIBILITY_ON); - break; - case 1: - { - if (Creature *smoke = me->SummonCreature(HELPER,Spawn[1].x,Spawn[1].y,Spawn[1].z,0,TEMPSUMMON_TIMED_DESPAWN,20000)) - CAST_AI(mob_wisp_invisAI, smoke->AI())->SetType(3); - DoCast(me, SPELL_RHYME_BIG); - break; - } - case 6: - if (pInstance) - pInstance->SetData(GAMEOBJECT_PUMPKIN_SHRINE, 0); //hide gameobject - break; - case 19: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); - break; - case 20: - { - Phase = 1; - IsFlying = false; - wp_reached = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - SaySound(SAY_ENTRANCE); - if (Unit *plr = Unit::GetUnit((*me),PlayerGUID)) - DoStartMovement(plr); - break; - } - } - ++id; - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); - DoZoneInCombat(); - } - void AttackStart(Unit* who) {ScriptedAI::AttackStart(who);} - void MoveInLineOfSight(Unit *who) - { - if (withhead && Phase != 0) - ScriptedAI::MoveInLineOfSight(who); - } - void KilledUnit(Unit *plr) - { - if (plr->GetTypeId() == TYPEID_PLAYER) - { - if (withhead) - SaySound(SAY_PLAYER_DEATH); - //maybe possible when player dies from conflagration - else if (Creature *Head = Unit::GetCreature((*me), headGUID)) - CAST_AI(mob_headAI, Head->AI())->SaySound(SAY_PLAYER_DEATH); - } - } - - void SaySound(int32 textEntry, Unit *pTarget = 0) - { - DoScriptText(textEntry, me, pTarget); - laugh += 4000; - } - - Player* SelectRandomPlayer(float range = 0.0f, bool checkLoS = true) - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) return NULL; - - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - Map::PlayerList::const_iterator i; - if (PlayerList.isEmpty()) return NULL; - - std::list temp; - std::list::const_iterator j; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if ((me->IsWithinLOSInMap(i->getSource()) || !checkLoS) && me->getVictim() != i->getSource() && - me->IsWithinDistInMap(i->getSource(), range) && i->getSource()->isAlive()) - temp.push_back(i->getSource()); - - if (temp.size()) - { - j = temp.begin(); - advance(j, rand()%temp.size()); - return (*j); - } - return NULL; - } - - void SpellHitTarget(Unit* unit, const SpellEntry* spell) - { - if (spell->Id == SPELL_CONFLAGRATION && unit->HasAura(SPELL_CONFLAGRATION)) - SaySound(SAY_CONFLAGRATION,unit); - } - - void JustDied(Unit* /*killer*/) - { - me->StopMoving(); - //me->GetMotionMaster()->MoveIdle(); - SaySound(SAY_DEATH); - if (Creature *flame = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000)) - flame->CastSpell(flame,SPELL_BODY_FLAME,false); - if (Creature *wisp = DoSpawnCreature(WISP_INVIS,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000)) - CAST_AI(mob_wisp_invisAI, wisp->AI())->SetType(4); - if (pInstance) - pInstance->SetData(DATA_HORSEMAN_EVENT, DONE); - } - - void SpellHit(Unit *caster, const SpellEntry* spell) - { - if (withhead) - return; - - if (spell->Id == SPELL_FLYING_HEAD) - { - if (Phase < 3) - ++Phase; - else - Phase = 3; - withhead = true; - me->RemoveAllAuras(); - me->SetName("Headless Horseman"); - me->SetHealth(me->GetMaxHealth()); - SaySound(SAY_REJOINED); - DoCast(me, SPELL_HEAD); - caster->GetMotionMaster()->Clear(false); - caster->GetMotionMaster()->MoveFollow(me,6,urand(0,5)); - //DoResetThreat();//not sure if need - std::list::const_iterator itr; - for (itr = caster->getThreatManager().getThreatList().begin(); itr != caster->getThreatManager().getThreatList().end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive() && pUnit != caster) - me->AddThreat(pUnit,caster->getThreatManager().getThreat(pUnit)); - } - } - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && withhead) - { - withhead = false; - returned = false; - damage = me->GetHealth() - me->GetMaxHealth()/100; - me->RemoveAllAuras(); - me->SetName("Headless Horseman, Unhorsed"); - - if (!headGUID) - headGUID = DoSpawnCreature(HEAD,rand()%6,rand()%6,0,0,TEMPSUMMON_DEAD_DESPAWN,0)->GetGUID(); - Unit* Head = Unit::GetUnit((*me), headGUID); - if (Head && Head->isAlive()) - { - Head->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //Head->CastSpell(Head,SPELL_HEAD_INVIS,false); - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_IMMUNE, true); - DoCast(me, SPELL_BODY_REGEN, true); - DoCast(Head, SPELL_FLYING_HEAD, true); - DoCast(me, SPELL_CONFUSE, false); //test - done_by->ProcDamageAndSpell(me,PROC_FLAG_KILL,PROC_FLAG_KILLED,PROC_EX_NONE,0); - whirlwind = urand(4000,8000); - regen = 0; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (withhead) - { - switch(Phase) - { - case 0: - { - if (!IsFlying) - { - if (say_timer <= diff) - { - say_timer = 3000; - Player *plr = SelectRandomPlayer(100.0f,false); - if (count < 3) - { - if (plr) - plr->Say(Text[count],0); - } - else - { - DoCast(me, SPELL_RHYME_BIG); - if (plr) - { - plr->Say(Text[count],0); - plr->HandleEmoteCommand(ANIM_EMOTE_SHOUT); - } - wp_reached = true; - IsFlying = true; - count = 0; - break; - } - ++count; - } else say_timer -= diff; - } - else - { - if (wp_reached) - { - wp_reached = false; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(id,FlightPoint[id].x,FlightPoint[id].y,FlightPoint[id].z); - } - } - } - break; - case 1: - if (burned) - break; - if (burn <= diff) - { - if (Creature *flame = me->SummonCreature(HELPER,Spawn[0].x,Spawn[0].y,Spawn[0].z,0,TEMPSUMMON_TIMED_DESPAWN,17000)) - CAST_AI(mob_wisp_invisAI, flame->AI())->SetType(2); - burned = true; - } else burn -= diff; - break; - case 2: - if (conflagrate <= diff) - { - if (Unit *plr = SelectRandomPlayer(30.0f)) - DoCast(plr, SPELL_CONFLAGRATION, false); - conflagrate = urand(10000,16000); - } else conflagrate -= diff; - break; - case 3: - if (summonadds <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SUMMON_PUMPKIN); - SaySound(SAY_SPROUTING_PUMPKINS); - summonadds = urand(25000,35000); - } else summonadds -= diff; - break; - } - - if (laugh <= diff) - { - laugh = urand(11000,22000); - me->MonsterTextEmote(EMOTE_LAUGHS,NULL); - DoPlaySoundToSet(me, RandomLaugh[rand()%3]); - } else laugh -= diff; - - if (UpdateVictim()) - { - DoMeleeAttackIfReady(); - if (cleave <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - cleave = urand(2000,6000); //1 cleave per 2.0-6.0sec - } else cleave -= diff; - } - } - else - { - if (regen <= diff) - { - regen = 1000; //"body calls head" - if (me->GetHealth()/me->GetMaxHealth() == 1 && !returned) - { - if (Phase > 1) - --Phase; - else - Phase = 1; - Creature* Head = Unit::GetCreature((*me), headGUID); - if (Head && Head->isAlive()) - { - CAST_AI(mob_headAI, Head->AI())->Phase = Phase; - CAST_AI(mob_headAI, Head->AI())->Disappear(); - } - return; - } - } - else regen -= diff; - - if (whirlwind <= diff) - { - whirlwind = urand(4000,8000); - if (urand(0,1)) - { - me->RemoveAurasDueToSpell(SPELL_CONFUSE); - DoCast(me, SPELL_WHIRLWIND, true); - DoCast(me, SPELL_CONFUSE); - } else - me->RemoveAurasDueToSpell(SPELL_WHIRLWIND); - } else whirlwind -= diff; - } - } -}; - -void mob_headAI::Disappear() -{ - if (withbody) - return; - if (bodyGUID) - { - Creature *body = Unit::GetCreature((*me), bodyGUID); - if (body && body->isAlive()) - { - withbody = true; - me->RemoveAllAuras(); - body->RemoveAurasDueToSpell(SPELL_IMMUNE);//hack, SpellHit doesn't calls if body has immune aura - DoCast(body, SPELL_FLYING_HEAD); - me->SetHealth(me->GetMaxHealth()); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->GetMotionMaster()->MoveIdle(); - CAST_AI(boss_headless_horsemanAI, body->AI())->returned = true; - } - } -} - -struct mob_pulsing_pumpkinAI : public ScriptedAI -{ - mob_pulsing_pumpkinAI(Creature *c) : ScriptedAI(c) {} - - bool sprouted; - uint64 debuffGUID; - - void Reset() - { - float x, y, z; - me->GetPosition(x, y, z); //this visual aura some under ground - me->GetMap()->CreatureRelocation(me, x,y,z + 0.35f, 0.0f); - Despawn(); - Creature *debuff = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,14500); - if (debuff) - { - debuff->SetDisplayId(me->GetDisplayId()); - debuff->CastSpell(debuff,SPELL_PUMPKIN_AURA_GREEN,false); - CAST_AI(mob_wisp_invisAI, debuff->AI())->SetType(1); - debuffGUID = debuff->GetGUID(); - } - sprouted = false; - DoCast(me, SPELL_PUMPKIN_AURA, true); - DoCast(me, SPELL_SPROUTING); - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); - } - - void EnterCombat(Unit * /*who*/){} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SPROUTING) - { - sprouted = true; - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); - DoCast(me, SPELL_SPROUT_BODY, true); - me->UpdateEntry(PUMPKIN_FIEND); - DoStartMovement(me->getVictim()); - } - } - - void Despawn() - { - if (!debuffGUID) return; - Unit *debuff = Unit::GetUnit((*me),debuffGUID); - if (debuff) - debuff->SetVisibility(VISIBILITY_OFF); - debuffGUID = 0; - } - - void JustDied(Unit * /*killer*/) { if (!sprouted) Despawn(); } - - void MoveInLineOfSight(Unit *who) - { - if (!who || !who->isTargetableForAttack() || !me->IsHostileTo(who) || me->getVictim()) - return; - - me->AddThreat(who,0.0f); - if (sprouted) - DoStartMovement(who); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (sprouted && UpdateVictim()) - DoMeleeAttackIfReady(); - } -}; - -bool GOHello_go_loosely_turned_soil(Player* pPlayer, GameObject* soil) -{ - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (pInstance) - { - if (pInstance->GetData(DATA_HORSEMAN_EVENT) != NOT_STARTED) - return true; - pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); - } -/* if (soil->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER && plr->getLevel() > 64) - { - plr->PrepareQuestMenu(soil->GetGUID()); - plr->SendPreparedQuest(soil->GetGUID()); - } - if (plr->GetQuestStatus(11405) == QUEST_STATUS_INCOMPLETE && plr->getLevel() > 64) - { */ - pPlayer->AreaExploredOrEventHappens(11405); - if (Creature *horseman = soil->SummonCreature(HH_MOUNTED,FlightPoint[20].x,FlightPoint[20].y,FlightPoint[20].z,0,TEMPSUMMON_MANUAL_DESPAWN,0)) - { - CAST_AI(boss_headless_horsemanAI, horseman->AI())->PlayerGUID = pPlayer->GetGUID(); - CAST_AI(boss_headless_horsemanAI, horseman->AI())->FlyMode(); - } - //} - return true; -} - -CreatureAI* GetAI_mob_head(Creature* pCreature) -{ - return new mob_headAI (pCreature); -} - -CreatureAI* GetAI_boss_headless_horseman(Creature* pCreature) -{ - return new boss_headless_horsemanAI (pCreature); -} - -CreatureAI* GetAI_mob_pulsing_pumpkin(Creature* pCreature) -{ - return new mob_pulsing_pumpkinAI (pCreature); -} - -CreatureAI* GetAI_mob_wisp_invis(Creature* pCreature) -{ - return new mob_wisp_invisAI (pCreature); -} - -void AddSC_boss_headless_horseman() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_headless_horseman"; - newscript->GetAI = &GetAI_boss_headless_horseman; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_head"; - newscript->GetAI = &GetAI_mob_head; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_pulsing_pumpkin"; - newscript->GetAI = &GetAI_mob_pulsing_pumpkin; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_wisp_invis"; - newscript->GetAI = &GetAI_mob_wisp_invis; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_loosely_turned_soil"; - newscript->pGOHello = &GOHello_go_loosely_turned_soil; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp deleted file mode 100644 index e0db29aa240..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Herod -SD%Complete: 95 -SDComment: Should in addition spawn Myrmidons in the hallway outside -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -#define SAY_AGGRO -1189000 -#define SAY_WHIRLWIND -1189001 -#define SAY_ENRAGE -1189002 -#define SAY_KILL -1189003 -#define EMOTE_ENRAGE -1189004 - -#define SPELL_RUSHINGCHARGE 8260 -#define SPELL_CLEAVE 15496 -#define SPELL_WHIRLWIND 8989 -#define SPELL_FRENZY 8269 - -#define ENTRY_SCARLET_TRAINEE 6575 -#define ENTRY_SCARLET_MYRMIDON 4295 - -struct boss_herodAI : public ScriptedAI -{ - boss_herodAI(Creature *c) : ScriptedAI(c) {} - - bool Enrage; - - uint32 Cleave_Timer; - uint32 Whirlwind_Timer; - - void Reset() - { - Enrage = false; - Cleave_Timer = 12000; - Whirlwind_Timer = 60000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_RUSHINGCHARGE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*killer*/) - { - for (uint8 i = 0; i < 20; ++i) - me->SummonCreature(ENTRY_SCARLET_TRAINEE, 1939.18, -431.58, 17.09, 6.22, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <30% hp goes Enraged - if (!Enrage && me->GetHealth()*100 / me->GetMaxHealth() <= 30 && !me->IsNonMeleeSpellCasted(false)) - { - DoScriptText(EMOTE_ENRAGE, me); - DoScriptText(SAY_ENRAGE, me); - DoCast(me, SPELL_FRENZY); - Enrage = true; - } - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 12000; - } else Cleave_Timer -= diff; - - // Whirlwind_Timer - if (Whirlwind_Timer <= diff) - { - DoScriptText(SAY_WHIRLWIND, me); - DoCast(me->getVictim(), SPELL_WHIRLWIND); - Whirlwind_Timer = 30000; - } else Whirlwind_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_herod(Creature* pCreature) -{ - return new boss_herodAI(pCreature); -} - -struct mob_scarlet_traineeAI : public npc_escortAI -{ - mob_scarlet_traineeAI(Creature *c) : npc_escortAI(c) - { - Start_Timer = urand(1000,6000); - } - - uint32 Start_Timer; - - void Reset() {} - void WaypointReached(uint32 /*uiPoint*/) {} - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (Start_Timer) - { - if (Start_Timer <= diff) - { - Start(true,true); - Start_Timer = 0; - } else Start_Timer -= diff; - } - - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_mob_scarlet_trainee(Creature* pCreature) -{ - return new mob_scarlet_traineeAI(pCreature); -} - -void AddSC_boss_herod() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_herod"; - newscript->GetAI = &GetAI_boss_herod; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_scarlet_trainee"; - newscript->GetAI = &GetAI_mob_scarlet_trainee; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp deleted file mode 100644 index b9b15f34508..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_High_Inquisitor_Fairbanks -SD%Complete: 100 -SDComment: TODO: if this guy not involved in some special event, remove (and let ACID script) -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -enum eSpells -{ - SPELL_CURSEOFBLOOD = 8282, - SPELL_DISPELMAGIC = 15090, - SPELL_FEAR = 12096, - SPELL_HEAL = 12039, - SPELL_POWERWORDSHIELD = 11647, - SPELL_SLEEP = 8399 -}; - -struct boss_high_inquisitor_fairbanksAI : public ScriptedAI -{ - boss_high_inquisitor_fairbanksAI(Creature *c) : ScriptedAI(c) {} - - uint32 CurseOfBlood_Timer; - uint32 DispelMagic_Timer; - uint32 Fear_Timer; - uint32 Heal_Timer; - uint32 Sleep_Timer; - uint32 Dispel_Timer; - bool PowerWordShield; - - void Reset() - { - CurseOfBlood_Timer = 10000; - DispelMagic_Timer = 30000; - Fear_Timer = 40000; - Heal_Timer = 30000; - Sleep_Timer = 30000; - Dispel_Timer = 20000; - PowerWordShield = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <25% hp cast Heal - if (me->GetHealth()*100 / me->GetMaxHealth() <= 25 && !me->IsNonMeleeSpellCasted(false) && Heal_Timer <= diff) - { - DoCast(me, SPELL_HEAL); - Heal_Timer = 30000; - } else Heal_Timer -= diff; - - //Fear_Timer - if (Fear_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_FEAR); - - Fear_Timer = 40000; - } else Fear_Timer -= diff; - - //Sleep_Timer - if (Sleep_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,0)) - DoCast(pTarget, SPELL_SLEEP); - - Sleep_Timer = 30000; - } else Sleep_Timer -= diff; - - //PowerWordShield_Timer - if (!PowerWordShield && me->GetHealth()*100 / me->GetMaxHealth() <= 25) - { - DoCast(me, SPELL_POWERWORDSHIELD); - PowerWordShield = true; - } - - //Dispel_Timer - if (Dispel_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_DISPELMAGIC); - - DispelMagic_Timer = 30000; - } else DispelMagic_Timer -= diff; - - //CurseOfBlood_Timer - if (CurseOfBlood_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); - CurseOfBlood_Timer = 25000; - } else CurseOfBlood_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_high_inquisitor_fairbanks(Creature* pCreature) -{ - return new boss_high_inquisitor_fairbanksAI (pCreature); -} - -void AddSC_boss_high_inquisitor_fairbanks() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_high_inquisitor_fairbanks"; - newscript->GetAI = &GetAI_boss_high_inquisitor_fairbanks; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp deleted file mode 100644 index 300e69611cd..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Houndmaster_Loksey -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1189021, - SPELL_SUMMONSCARLETHOUND = 17164, - SPELL_BLOODLUST = 6742 -}; - -struct boss_houndmaster_lokseyAI : public ScriptedAI -{ - boss_houndmaster_lokseyAI(Creature *c) : ScriptedAI(c) {} - - uint32 BloodLust_Timer; - - void Reset() - { - BloodLust_Timer = 20000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BloodLust_Timer <= diff) - { - DoCast(me, SPELL_BLOODLUST); - BloodLust_Timer = 20000; - } else BloodLust_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_houndmaster_loksey(Creature* pCreature) -{ - return new boss_houndmaster_lokseyAI (pCreature); -} - -void AddSC_boss_houndmaster_loksey() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_houndmaster_loksey"; - newscript->GetAI = &GetAI_boss_houndmaster_loksey; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp deleted file mode 100644 index b4b84fc8059..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Interrogator_Vishas -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "scarlet_monastery.h" - -enum eEnums -{ - SAY_AGGRO = -1189011, - SAY_HEALTH1 = -1189012, - SAY_HEALTH2 = -1189013, - SAY_KILL = -1189014, - SAY_TRIGGER_VORREL = -1189015, - - SPELL_SHADOWWORDPAIN = 2767, -}; - -struct boss_interrogator_vishasAI : public ScriptedAI -{ - boss_interrogator_vishasAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool Yell30; - bool Yell60; - uint32 ShadowWordPain_Timer; - - void Reset() - { - ShadowWordPain_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*Victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*Killer*/) - { - if (!pInstance) - return; - - //Any other actions to do with vorrel? setStandState? - if (Unit *vorrel = Unit::GetUnit(*me,pInstance->GetData64(DATA_VORREL))) - DoScriptText(SAY_TRIGGER_VORREL, vorrel); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are low on hp Do sayings - if (!Yell60 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 60)) - { - DoScriptText(SAY_HEALTH1, me); - Yell60 = true; - } - - if (!Yell30 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 30)) - { - DoScriptText(SAY_HEALTH2, me); - Yell30 = true; - } - - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); - ShadowWordPain_Timer = 5000 + rand()%10000; - } else ShadowWordPain_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_interrogator_vishas(Creature* pCreature) -{ - return new boss_interrogator_vishasAI (pCreature); -} - -void AddSC_boss_interrogator_vishas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_interrogator_vishas"; - newscript->GetAI = &GetAI_boss_interrogator_vishas; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp deleted file mode 100644 index 32b85e214a0..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mograine_And_Whitemane -SD%Complete: 90 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "scarlet_monastery.h" - -enum eEnums -{ - //Mograine says - SAY_MO_AGGRO = -1189005, - SAY_MO_KILL = -1189006, - SAY_MO_RESSURECTED = -1189007, - - //Whitemane says - SAY_WH_INTRO = -1189008, - SAY_WH_KILL = -1189009, - SAY_WH_RESSURECT = -1189010, - - //Mograine Spells - SPELL_CRUSADERSTRIKE = 14518, - SPELL_HAMMEROFJUSTICE = 5589, - SPELL_LAYONHANDS = 9257, - SPELL_RETRIBUTIONAURA = 8990, - - //Whitemanes Spells - SPELL_DEEPSLEEP = 9256, - SPELL_SCARLETRESURRECTION = 9232, - SPELL_DOMINATEMIND = 14515, - SPELL_HOLYSMITE = 9481, - SPELL_HEAL = 12039, - SPELL_POWERWORDSHIELD = 22187 -}; - -struct boss_scarlet_commander_mograineAI : public ScriptedAI -{ - boss_scarlet_commander_mograineAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiCrusaderStrike_Timer; - uint32 m_uiHammerOfJustice_Timer; - - bool m_bHasDied; - bool m_bHeal; - bool m_bFakeDeath; - - void Reset() - { - m_uiCrusaderStrike_Timer = 10000; - m_uiHammerOfJustice_Timer = 10000; - - //Incase wipe during phase that mograine fake death - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - - if (m_pInstance) - if (me->isAlive()) - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT,NOT_STARTED); - - m_bHasDied = false; - m_bHeal = false; - m_bFakeDeath = false; - } - - void JustReachedHome() - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT != NOT_STARTED)) - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, FAIL); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_MO_AGGRO, me); - DoCast(me, SPELL_RETRIBUTIONAURA); - - me->CallForHelp(VISIBLE_RANGE); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(SAY_MO_KILL, me); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) - { - if (uiDamage < me->GetHealth() || m_bHasDied || m_bFakeDeath) - return; - - if (!m_pInstance) - return; - - //On first death, fake death and open door, as well as initiate whitemane if exist - if (Unit* Whitemane = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_WHITEMANE))) - { - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS); - - Whitemane->GetMotionMaster()->MovePoint(1,1163.113370,1398.856812,32.527786); - - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MoveIdle(); - - me->SetHealth(0); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - me->ClearComboPointHolders(); - me->RemoveAllAuras(); - me->ClearAllReactives(); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_DEAD); - - m_bHasDied = true; - m_bFakeDeath = true; - - uiDamage = 0; - } - } - - void SpellHit(Unit* /*pWho*/, const SpellEntry* pSpell) - { - //When hit with ressurection say text - if (pSpell->Id == SPELL_SCARLETRESURRECTION) - { - DoScriptText(SAY_MO_RESSURECTED, me); - m_bFakeDeath = false; - - if (m_pInstance) - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, SPECIAL); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (m_bHasDied && !m_bHeal && m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL) - { - //On ressurection, stop fake death and heal whitemane and resume fight - if (Unit* Whitemane = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_WHITEMANE))) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(Whitemane, SPELL_LAYONHANDS); - - m_uiCrusaderStrike_Timer = 10000; - m_uiHammerOfJustice_Timer = 10000; - - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - - m_bHeal = true; - } - } - - //This if-check to make sure mograine does not attack while fake death - if (m_bFakeDeath) - return; - - //m_uiCrusaderStrike_Timer - if (m_uiCrusaderStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CRUSADERSTRIKE); - m_uiCrusaderStrike_Timer = 10000; - } else m_uiCrusaderStrike_Timer -= uiDiff; - - //m_uiHammerOfJustice_Timer - if (m_uiHammerOfJustice_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_HAMMEROFJUSTICE); - m_uiHammerOfJustice_Timer = 60000; - } else m_uiHammerOfJustice_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_high_inquisitor_whitemaneAI : public ScriptedAI -{ - boss_high_inquisitor_whitemaneAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiHeal_Timer; - uint32 m_uiPowerWordShield_Timer; - uint32 m_uiHolySmite_Timer; - uint32 m_uiWait_Timer; - - bool m_bCanResurrectCheck; - bool m_bCanResurrect; - - void Reset() - { - m_uiWait_Timer = 7000; - m_uiHeal_Timer = 10000; - m_uiPowerWordShield_Timer = 15000; - m_uiHolySmite_Timer = 6000; - - m_bCanResurrectCheck = false; - m_bCanResurrect = false; - - if (m_pInstance) - if (me->isAlive()) - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, NOT_STARTED); - } - - void AttackStart(Unit* pWho) - { - if (m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED) - return; - - ScriptedAI::AttackStart(pWho); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_WH_INTRO, me); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(SAY_WH_KILL, me); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (m_bCanResurrect) - { - //When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out - if (m_pInstance && m_uiWait_Timer <= uiDiff) - { - if (Unit* Mograine = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_MOGRAINE))) - { - DoCast(Mograine, SPELL_SCARLETRESURRECTION); - DoScriptText(SAY_WH_RESSURECT, me); - m_bCanResurrect = false; - } - } - else m_uiWait_Timer -= uiDiff; - } - - //Cast Deep sleep when health is less than 50% - if (!m_bCanResurrectCheck && me->GetHealth()*100 / me->GetMaxHealth() <= 50) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me->getVictim(), SPELL_DEEPSLEEP); - m_bCanResurrectCheck = true; - m_bCanResurrect = true; - return; - } - - //while in "resurrect-mode", don't do anything - if (m_bCanResurrect) - return; - - //If we are <75% hp cast healing spells at self or Mograine - if (m_uiHeal_Timer <= uiDiff) - { - Creature* pTarget = NULL; - - if (me->GetHealth() <= me->GetMaxHealth()*0.75f) - pTarget = me; - - if (m_pInstance) - { - if (Creature* pMograine = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_MOGRAINE))) - { - // checking m_bCanResurrectCheck prevents her healing Mograine while he is "faking death" - if (m_bCanResurrectCheck && pMograine->isAlive() && pMograine->GetHealth() <= pMograine->GetMaxHealth()*0.75f) - pTarget = pMograine; - } - } - - if (pTarget) - DoCast(pTarget, SPELL_HEAL); - - m_uiHeal_Timer = 13000; - } else m_uiHeal_Timer -= uiDiff; - - //m_uiPowerWordShield_Timer - if (m_uiPowerWordShield_Timer <= uiDiff) - { - DoCast(me, SPELL_POWERWORDSHIELD); - m_uiPowerWordShield_Timer = 15000; - } else m_uiPowerWordShield_Timer -= uiDiff; - - //m_uiHolySmite_Timer - if (m_uiHolySmite_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_HOLYSMITE); - m_uiHolySmite_Timer = 6000; - } else m_uiHolySmite_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_scarlet_commander_mograine(Creature* pCreature) -{ - return new boss_scarlet_commander_mograineAI (pCreature); -} - -CreatureAI* GetAI_boss_high_inquisitor_whitemane(Creature* pCreature) -{ - return new boss_high_inquisitor_whitemaneAI (pCreature); -} - -void AddSC_boss_mograine_and_whitemane() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_scarlet_commander_mograine"; - newscript->GetAI = &GetAI_boss_scarlet_commander_mograine; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_high_inquisitor_whitemane"; - newscript->GetAI = &GetAI_boss_high_inquisitor_whitemane; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp deleted file mode 100644 index 5d0a3b3792f..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Scorn -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_LICHSLAP 28873 -#define SPELL_FROSTBOLTVOLLEY 8398 -#define SPELL_MINDFLAY 17313 -#define SPELL_FROSTNOVA 15531 - -struct boss_scornAI : public ScriptedAI -{ - boss_scornAI(Creature *c) : ScriptedAI(c) {} - - uint32 LichSlap_Timer; - uint32 FrostboltVolley_Timer; - uint32 MindFlay_Timer; - uint32 FrostNova_Timer; - - void Reset() - { - LichSlap_Timer = 45000; - FrostboltVolley_Timer = 30000; - MindFlay_Timer = 30000; - FrostNova_Timer = 30000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //LichSlap_Timer - if (LichSlap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LICHSLAP); - LichSlap_Timer = 45000; - } else LichSlap_Timer -= diff; - - //FrostboltVolley_Timer - if (FrostboltVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLTVOLLEY); - FrostboltVolley_Timer = 20000; - } else FrostboltVolley_Timer -= diff; - - //MindFlay_Timer - if (MindFlay_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MINDFLAY); - MindFlay_Timer = 20000; - } else MindFlay_Timer -= diff; - - //FrostNova_Timer - if (FrostNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTNOVA); - FrostNova_Timer = 15000; - } else FrostNova_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_scorn(Creature* pCreature) -{ - return new boss_scornAI (pCreature); -} - -void AddSC_boss_scorn() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_scorn"; - newscript->GetAI = &GetAI_boss_scorn; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp b/src/server/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp deleted file mode 100644 index 33642d4511c..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Scarlet_Monastery -SD%Complete: 50 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "scarlet_monastery.h" - -#define ENTRY_PUMPKIN_SHRINE 186267 -#define ENTRY_HORSEMAN 23682 -#define ENTRY_HEAD 23775 -#define ENTRY_PUMPKIN 23694 - -#define MAX_ENCOUNTER 2 - -struct instance_scarlet_monastery : public ScriptedInstance -{ - instance_scarlet_monastery(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 PumpkinShrineGUID; - uint64 HorsemanGUID; - uint64 HeadGUID; - std::set HorsemanAdds; - - uint64 MograineGUID; - uint64 WhitemaneGUID; - uint64 VorrelGUID; - uint64 DoorHighInquisitorGUID; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - PumpkinShrineGUID = 0; - HorsemanGUID = 0; - HeadGUID = 0; - HorsemanAdds.clear(); - - MograineGUID = 0; - WhitemaneGUID = 0; - VorrelGUID = 0; - DoorHighInquisitorGUID = 0; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case ENTRY_PUMPKIN_SHRINE: PumpkinShrineGUID = pGo->GetGUID();break; - case 104600: DoorHighInquisitorGUID = pGo->GetGUID(); break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case ENTRY_HORSEMAN: HorsemanGUID = pCreature->GetGUID(); break; - case ENTRY_HEAD: HeadGUID = pCreature->GetGUID(); break; - case ENTRY_PUMPKIN: HorsemanAdds.insert(pCreature->GetGUID());break; - case 3976: MograineGUID = pCreature->GetGUID(); break; - case 3977: WhitemaneGUID = pCreature->GetGUID(); break; - case 3981: VorrelGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_MOGRAINE_AND_WHITE_EVENT: - if (data == IN_PROGRESS) - DoUseDoorOrButton(DoorHighInquisitorGUID); - if (data == FAIL) - DoUseDoorOrButton(DoorHighInquisitorGUID); - - m_auiEncounter[0] = data; - break; - case GAMEOBJECT_PUMPKIN_SHRINE: - HandleGameObject(PumpkinShrineGUID, false); - break; - case DATA_HORSEMAN_EVENT: - m_auiEncounter[1] = data; - if (data == DONE) - { - for (std::set::const_iterator itr = HorsemanAdds.begin(); itr != HorsemanAdds.end(); ++itr) - { - Creature* add = instance->GetCreature(*itr); - if (add && add->isAlive()) - add->Kill(add); - } - HorsemanAdds.clear(); - HandleGameObject(PumpkinShrineGUID, false); - } - break; - } - } - - uint64 GetData64(uint32 type) - { - switch(type) - { - //case GAMEOBJECT_PUMPKIN_SHRINE: return PumpkinShrineGUID; - //case DATA_HORSEMAN: return HorsemanGUID; - //case DATA_HEAD: return HeadGUID; - case DATA_MOGRAINE: return MograineGUID; - case DATA_WHITEMANE: return WhitemaneGUID; - case DATA_VORREL: return VorrelGUID; - case DATA_DOOR_WHITEMANE: return DoorHighInquisitorGUID; - } - return 0; - } - - uint32 GetData(uint32 type) - { - if (type == TYPE_MOGRAINE_AND_WHITE_EVENT) - return m_auiEncounter[0]; - if (type == DATA_HORSEMAN_EVENT) - return m_auiEncounter[1]; - return 0; - } -}; - -InstanceData* GetInstanceData_instance_scarlet_monastery(Map* pMap) -{ - return new instance_scarlet_monastery(pMap); -} - -void AddSC_instance_scarlet_monastery() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_scarlet_monastery"; - newscript->GetInstanceData = &GetInstanceData_instance_scarlet_monastery; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h b/src/server/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h deleted file mode 100644 index 2b6399ae3e4..00000000000 --- a/src/server/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SCARLET_M -#define DEF_SCARLET_M - -#define TYPE_MOGRAINE_AND_WHITE_EVENT 1 -#define DATA_MOGRAINE 2 -#define DATA_WHITEMANE 3 -#define DATA_DOOR_WHITEMANE 4 - -#define DATA_HORSEMAN_EVENT 5 -#define GAMEOBJECT_PUMPKIN_SHRINE 6 - -#define DATA_VORREL 7 -#endif - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp deleted file mode 100644 index 50a9e204566..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Darkmaster_Gandling -SD%Complete: 75 -SDComment: Doors missing in instance script. -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_ARCANEMISSILES 22272 -#define SPELL_SHADOWSHIELD 22417 //Not right ID. But 12040 is wrong either. -#define SPELL_CURSE 18702 - -#define ADD_1X 170.205 -#define ADD_1Y 99.413 -#define ADD_1Z 104.733 -#define ADD_1O 3.16 - -#define ADD_2X 170.813 -#define ADD_2Y 97.857 -#define ADD_2Z 104.713 -#define ADD_2O 3.16 - -#define ADD_3X 170.720 -#define ADD_3Y 100.900 -#define ADD_3Z 104.739 -#define ADD_3O 3.16 - -#define ADD_4X 171.866 -#define ADD_4Y 99.373 -#define ADD_4Z 104.732 -#define ADD_4O 3.16 - -struct boss_darkmaster_gandlingAI : public ScriptedAI -{ - boss_darkmaster_gandlingAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ArcaneMissiles_Timer; - uint32 ShadowShield_Timer; - uint32 Curse_Timer; - uint32 Teleport_Timer; - - void Reset() - { - ArcaneMissiles_Timer = 4500; - ShadowShield_Timer = 12000; - Curse_Timer = 2000; - Teleport_Timer = 16000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_GANDLING, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ArcaneMissiles_Timer - if (ArcaneMissiles_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANEMISSILES); - ArcaneMissiles_Timer = 8000; - } else ArcaneMissiles_Timer -= diff; - - //ShadowShield_Timer - if (ShadowShield_Timer <= diff) - { - DoCast(me, SPELL_SHADOWSHIELD); - ShadowShield_Timer = 14000 + rand()%14000; - } else ShadowShield_Timer -= diff; - - //Curse_Timer - if (Curse_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSE); - Curse_Timer = 15000 + rand()%12000; - } else Curse_Timer -= diff; - - //Teleporting Random Target to one of the six pre boss rooms and spawn 3-4 skeletons near the gamer. - //We will only telport if gandling has more than 3% of hp so teleported gamers can always loot. - if (me->GetHealth()*100 / me->GetMaxHealth() > 3) - { - if (Teleport_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - if (DoGetThreat(pTarget)) - DoModifyThreatPercent(pTarget, -100); - - Creature *Summoned = NULL; - switch(rand()%6) - { - case 0: - DoTeleportPlayer(pTarget, 250.0696,0.3921,84.8408,3.149); - Summoned = me->SummonCreature(16119,254.2325,0.3417,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,257.7133,4.0226,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,258.6702,-2.60656,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 1: - DoTeleportPlayer(pTarget, 181.4220,-91.9481,84.8410,1.608); - Summoned = me->SummonCreature(16119,184.0519,-73.5649,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,179.5951,-73.7045,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,180.6452,-78.2143,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,283.2274,-78.1518,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 2: - DoTeleportPlayer(pTarget, 95.1547,-1.8173,85.2289,0.043); - Summoned = me->SummonCreature(16119,100.9404,-1.8016,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,101.3729,0.4882,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,101.4596,-4.4740,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 3: - DoTeleportPlayer(pTarget, 250.0696,0.3921,72.6722,3.149); - Summoned = me->SummonCreature(16119,240.34481,0.7368,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,240.3633,-2.9520,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,240.6702,3.34949,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 4: - DoTeleportPlayer(pTarget, 181.4220,-91.9481,70.7734,1.608); - Summoned = me->SummonCreature(16119,184.0519,-73.5649,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,179.5951,-73.7045,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,180.6452,-78.2143,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,283.2274,-78.1518,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 5: - DoTeleportPlayer(pTarget, 106.1541,-1.8994,75.3663,0.043); - Summoned = me->SummonCreature(16119,115.3945,-1.5555,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,257.7133,1.8066,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,258.6702,-5.1001,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - } - } - Teleport_Timer = 20000 + rand()%15000; - } else Teleport_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_darkmaster_gandling(Creature* pCreature) -{ - return new boss_darkmaster_gandlingAI (pCreature); -} - -void AddSC_boss_darkmaster_gandling() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_darkmaster_gandling"; - newscript->GetAI = &GetAI_boss_darkmaster_gandling; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp deleted file mode 100644 index 8bb9ec68aca..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Death_knight_darkreaver -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -struct boss_death_knight_darkreaverAI : public ScriptedAI -{ - boss_death_knight_darkreaverAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (me->GetHealth() <= damage) - DoCast(me, 23261, true); //Summon Darkreaver's Fallen Charger - } - - void EnterCombat(Unit * /*who*/) - { - } -}; -CreatureAI* GetAI_boss_death_knight_darkreaver(Creature* pCreature) -{ - return new boss_death_knight_darkreaverAI (pCreature); -} - -void AddSC_boss_death_knight_darkreaver() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_death_knight_darkreaver"; - newscript->GetAI = &GetAI_boss_death_knight_darkreaver; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp deleted file mode 100644 index 5ff01d48623..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Doctor_Theolen_Krastinov -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -enum eEnums -{ - EMOTE_GENERIC_FRENZY_KILL = -1000001, - - SPELL_REND = 16509, - SPELL_BACKHAND = 18103, - SPELL_FRENZY = 8269 -}; - -struct boss_theolenkrastinovAI : public ScriptedAI -{ - boss_theolenkrastinovAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiRend_Timer; - uint32 m_uiBackhand_Timer; - uint32 m_uiFrenzy_Timer; - - void Reset() - { - m_uiRend_Timer = 8000; - m_uiBackhand_Timer = 9000; - m_uiFrenzy_Timer = 1000; - } - - void JustDied(Unit* /*pKiller*/) - { - ScriptedInstance* pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_DOCTORTHEOLENKRASTINOV_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //Rend_Timer - if (m_uiRend_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_REND); - m_uiRend_Timer = 10000; - } - else - m_uiRend_Timer -= uiDiff; - - //Backhand_Timer - if (m_uiBackhand_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BACKHAND); - m_uiBackhand_Timer = 10000; - } - else - m_uiBackhand_Timer -= uiDiff; - - //Frenzy_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 26) - { - if (m_uiFrenzy_Timer <= uiDiff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); - - m_uiFrenzy_Timer = 120000; - } - else - m_uiFrenzy_Timer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_theolenkrastinov(Creature* pCreature) -{ - return new boss_theolenkrastinovAI (pCreature); -} - -void AddSC_boss_theolenkrastinov() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_doctor_theolen_krastinov"; - newscript->GetAI = &GetAI_boss_theolenkrastinov; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp deleted file mode 100644 index a038fc7a0b8..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Illucia_Barov -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_CURSEOFAGONY 18671 -#define SPELL_SHADOWSHOCK 20603 -#define SPELL_SILENCE 15487 -#define SPELL_FEAR 6215 - -struct boss_illuciabarovAI : public ScriptedAI -{ - boss_illuciabarovAI(Creature *c) : ScriptedAI(c) {} - - uint32 CurseOfAgony_Timer; - uint32 ShadowShock_Timer; - uint32 Silence_Timer; - uint32 Fear_Timer; - - void Reset() - { - CurseOfAgony_Timer = 18000; - ShadowShock_Timer = 9000; - Silence_Timer = 5000; - Fear_Timer = 30000; - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_LADYILLUCIABAROV_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //CurseOfAgony_Timer - if (CurseOfAgony_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFAGONY); - CurseOfAgony_Timer = 30000; - } else CurseOfAgony_Timer -= diff; - - //ShadowShock_Timer - if (ShadowShock_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_SHADOWSHOCK); - - ShadowShock_Timer = 12000; - } else ShadowShock_Timer -= diff; - - //Silence_Timer - if (Silence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - Silence_Timer = 14000; - } else Silence_Timer -= diff; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - Fear_Timer = 30000; - } else Fear_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_illuciabarov(Creature* pCreature) -{ - return new boss_illuciabarovAI (pCreature); -} - -void AddSC_boss_illuciabarov() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_illucia_barov"; - newscript->GetAI = &GetAI_boss_illuciabarov; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp deleted file mode 100644 index c4c0f95d8d1..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_instructormalicia -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_CALLOFGRAVES 17831 -#define SPELL_CORRUPTION 11672 -#define SPELL_FLASHHEAL 10917 -#define SPELL_RENEW 10929 -#define SPELL_HEALINGTOUCH 9889 - -struct boss_instructormaliciaAI : public ScriptedAI -{ - boss_instructormaliciaAI(Creature *c) : ScriptedAI(c) {} - - uint32 CallOfGraves_Timer; - uint32 Corruption_Timer; - uint32 FlashHeal_Timer; - uint32 Renew_Timer; - uint32 HealingTouch_Timer; - uint32 FlashCounter; - uint32 TouchCounter; - - void Reset() - { - CallOfGraves_Timer = 4000; - Corruption_Timer = 8000; - FlashHeal_Timer = 38000; - Renew_Timer = 32000; - HealingTouch_Timer = 45000; - FlashCounter = 0; - TouchCounter = 0; - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_INSTRUCTORMALICIA_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //CallOfGraves_Timer - if (CallOfGraves_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CALLOFGRAVES); - CallOfGraves_Timer = 65000; - } else CallOfGraves_Timer -= diff; - - //Corruption_Timer - if (Corruption_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_CORRUPTION); - - Corruption_Timer = 24000; - } else Corruption_Timer -= diff; - - //Renew_Timer - if (Renew_Timer <= diff) - { - DoCast(me, SPELL_RENEW); - Renew_Timer = 10000; - } else Renew_Timer -= diff; - - //FlashHeal_Timer - if (FlashHeal_Timer <= diff) - { - DoCast(me, SPELL_FLASHHEAL); - - //5 Flashheals will be casted - if (FlashCounter < 2) - { - FlashHeal_Timer = 5000; - ++FlashCounter; - } - else - { - FlashCounter=0; - FlashHeal_Timer = 30000; - } - } else FlashHeal_Timer -= diff; - - //HealingTouch_Timer - if (HealingTouch_Timer <= diff) - { - DoCast(me, SPELL_HEALINGTOUCH); - - //3 Healingtouchs will be casted - if (HealingTouch_Timer < 2) - { - HealingTouch_Timer = 5500; - ++TouchCounter; - } - else - { - TouchCounter=0; - HealingTouch_Timer = 30000; - } - } else HealingTouch_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_instructormalicia(Creature* pCreature) -{ - return new boss_instructormaliciaAI (pCreature); -} - -void AddSC_boss_instructormalicia() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_instructor_malicia"; - newscript->GetAI = &GetAI_boss_instructormalicia; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp deleted file mode 100644 index f8d8520e394..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_jandicebarov -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CURSEOFBLOOD 24673 -//#define SPELL_ILLUSION 17773 - -//Spells of Illusion of Jandice Barov -#define SPELL_CLEAVE 15584 - -struct boss_jandicebarovAI : public ScriptedAI -{ - boss_jandicebarovAI(Creature *c) : ScriptedAI(c) {} - - uint32 CurseOfBlood_Timer; - uint32 Illusion_Timer; - //uint32 Illusioncounter; - uint32 Invisible_Timer; - bool Invisible; - - void Reset() - { - CurseOfBlood_Timer = 15000; - Illusion_Timer = 30000; - Invisible_Timer = 3000; //Too much too low? - Invisible = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonIllusions(Unit* victim) - { - if (Creature *Illusion = DoSpawnCreature(11439, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) - Illusion->AI()->AttackStart(victim); - } - - void UpdateAI(const uint32 diff) - { - if (Invisible && Invisible_Timer <= diff) - { - //Become visible again - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(11073); //Jandice Model - Invisible = false; - } else if (Invisible) - { - Invisible_Timer -= diff; - //Do nothing while invisible - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //CurseOfBlood_Timer - if (CurseOfBlood_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); - - //45 seconds - CurseOfBlood_Timer = 30000; - } else CurseOfBlood_Timer -= diff; - - //Illusion_Timer - if (!Invisible && Illusion_Timer <= diff) - { - - //Inturrupt any spell casting - me->InterruptNonMeleeSpells(false); - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(11686); // Invisible Model - DoModifyThreatPercent(me->getVictim(),-99); - - //Summon 10 Illusions attacking random gamers - Unit *pTarget = NULL; - for (uint8 i = 0; i < 10; ++i) - { - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - SummonIllusions(pTarget); - } - Invisible = true; - Invisible_Timer = 3000; - - //25 seconds until we should cast this agian - Illusion_Timer = 25000; - } else Illusion_Timer -= diff; - - // //Illusion_Timer - // if (Illusion_Timer <= diff) - // { - // //Cast - // DoCast(me->getVictim(), SPELL_ILLUSION); - // - // //3 Illusion will be summoned - // if (Illusioncounter < 3) - // { - // Illusion_Timer = 500; - // ++Illusioncounter; - // } - // else { - // //15 seconds until we should cast this again - // Illusion_Timer = 15000; - // Illusioncounter = 0; - // } - // - // } else Illusion_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -// Illusion of Jandice Barov Script - -struct mob_illusionofjandicebarovAI : public ScriptedAI -{ - mob_illusionofjandicebarovAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cleave_Timer; - - void Reset() - { - Cleave_Timer = 2000 + rand()%6000; - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_CLEAVE); - - //5-8 seconds - Cleave_Timer = 5000 + rand()%3000; - } else Cleave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_jandicebarov(Creature* pCreature) -{ - return new boss_jandicebarovAI (pCreature); -} - -CreatureAI* GetAI_mob_illusionofjandicebarov(Creature* pCreature) -{ - return new mob_illusionofjandicebarovAI (pCreature); -} - -void AddSC_boss_jandicebarov() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_jandice_barov"; - newscript->GetAI = &GetAI_boss_jandicebarov; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_illusionofjandicebarov"; - newscript->GetAI = &GetAI_mob_illusionofjandicebarov; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp deleted file mode 100644 index c4ae5cc490e..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kormok -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWBOLTVOLLEY 20741 -#define SPELL_BONESHIELD 27688 - -struct boss_kormokAI : public ScriptedAI -{ - boss_kormokAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowVolley_Timer; - uint32 BoneShield_Timer; - uint32 Minion_Timer; - uint32 Mage_Timer; - bool Mages; - - void Reset() - { - ShadowVolley_Timer = 10000; - BoneShield_Timer = 2000; - Minion_Timer = 15000; - Mage_Timer = 0; - Mages = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonMinions(Unit* victim) - { - if (Creature *SummonedMinion = DoSpawnCreature(16119, irand(-7,7), irand(-7,7), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedMinion->AI()->AttackStart(victim); - } - - void SummonMages(Unit* victim) - { - if (Creature *SummonedMage = DoSpawnCreature(16120, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedMage->AI()->AttackStart(victim); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowVolley_Timer - if (ShadowVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLTVOLLEY); - ShadowVolley_Timer = 15000; - } else ShadowVolley_Timer -= diff; - - //BoneShield_Timer - if (BoneShield_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BONESHIELD); - BoneShield_Timer = 45000; - } else BoneShield_Timer -= diff; - - //Minion_Timer - if (Minion_Timer <= diff) - { - //Cast - SummonMinions(me->getVictim()); - SummonMinions(me->getVictim()); - SummonMinions(me->getVictim()); - SummonMinions(me->getVictim()); - - Minion_Timer = 12000; - } else Minion_Timer -= diff; - - //Summon 2 Bone Mages - if (!Mages && me->GetHealth()*100 / me->GetMaxHealth() < 26) - { - //Cast - SummonMages(me->getVictim()); - SummonMages(me->getVictim()); - Mages = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_kormok(Creature* pCreature) -{ - return new boss_kormokAI (pCreature); -} - -void AddSC_boss_kormok() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kormok"; - newscript->GetAI = &GetAI_boss_kormok; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp deleted file mode 100644 index 0956a04d824..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Lord_Alexei_Barov -SD%Complete: 100 -SDComment: aura applied/defined in database -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_IMMOLATE 20294 // Old ID was 15570 -#define SPELL_VEILOFSHADOW 17820 - -struct boss_lordalexeibarovAI : public ScriptedAI -{ - boss_lordalexeibarovAI(Creature *c) : ScriptedAI(c) {} - - uint32 Immolate_Timer; - uint32 VeilofShadow_Timer; - - void Reset() - { - Immolate_Timer = 7000; - VeilofShadow_Timer = 15000; - - me->LoadCreaturesAddon(); - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_LORDALEXEIBAROV_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); - - Immolate_Timer = 12000; - } else Immolate_Timer -= diff; - - //VeilofShadow_Timer - if (VeilofShadow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VEILOFSHADOW); - VeilofShadow_Timer = 20000; - } else VeilofShadow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_lordalexeibarov(Creature* pCreature) -{ - return new boss_lordalexeibarovAI (pCreature); -} - -void AddSC_boss_lordalexeibarov() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lord_alexei_barov"; - newscript->GetAI = &GetAI_boss_lordalexeibarov; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp deleted file mode 100644 index d3b75900202..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Lorekeeper_Polkelt -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_VOLATILEINFECTION 24928 -#define SPELL_DARKPLAGUE 18270 -#define SPELL_CORROSIVEACID 23313 -#define SPELL_NOXIOUSCATALYST 18151 - -struct boss_lorekeeperpolkeltAI : public ScriptedAI -{ - boss_lorekeeperpolkeltAI(Creature *c) : ScriptedAI(c) {} - - uint32 VolatileInfection_Timer; - uint32 Darkplague_Timer; - uint32 CorrosiveAcid_Timer; - uint32 NoxiousCatalyst_Timer; - - void Reset() - { - VolatileInfection_Timer = 38000; - Darkplague_Timer = 8000; - CorrosiveAcid_Timer = 45000; - NoxiousCatalyst_Timer = 35000; - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_LOREKEEPERPOLKELT_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //VolatileInfection_Timer - if (VolatileInfection_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VOLATILEINFECTION); - VolatileInfection_Timer = 32000; - } else VolatileInfection_Timer -= diff; - - //Darkplague_Timer - if (Darkplague_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DARKPLAGUE); - Darkplague_Timer = 8000; - } else Darkplague_Timer -= diff; - - //CorrosiveAcid_Timer - if (CorrosiveAcid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVEACID); - CorrosiveAcid_Timer = 25000; - } else CorrosiveAcid_Timer -= diff; - - //NoxiousCatalyst_Timer - if (NoxiousCatalyst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSCATALYST); - NoxiousCatalyst_Timer = 38000; - } else NoxiousCatalyst_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_lorekeeperpolkelt(Creature* pCreature) -{ - return new boss_lorekeeperpolkeltAI (pCreature); -} - -void AddSC_boss_lorekeeperpolkelt() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lorekeeper_polkelt"; - newscript->GetAI = &GetAI_boss_lorekeeperpolkelt; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp deleted file mode 100644 index 63837e04ad5..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ras_Frostwhisper -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FROSTBOLT 21369 -#define SPELL_ICEARMOR 18100 //This is actually a buff he gives himself -#define SPELL_FREEZE 18763 -#define SPELL_FEAR 26070 -#define SPELL_CHILLNOVA 18099 -#define SPELL_FROSTVOLLEY 8398 - -struct boss_rasfrostAI : public ScriptedAI -{ - boss_rasfrostAI(Creature *c) : ScriptedAI(c) {} - - uint32 IceArmor_Timer; - uint32 Frostbolt_Timer; - uint32 Freeze_Timer; - uint32 Fear_Timer; - uint32 ChillNova_Timer; - uint32 FrostVolley_Timer; - - void Reset() - { - IceArmor_Timer = 2000; - Frostbolt_Timer = 8000; - ChillNova_Timer = 12000; - Freeze_Timer = 18000; - FrostVolley_Timer = 24000; - Fear_Timer = 45000; - - DoCast(me, SPELL_ICEARMOR, true); - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //IceArmor_Timer - if (IceArmor_Timer <= diff) - { - DoCast(me, SPELL_ICEARMOR); - IceArmor_Timer = 180000; - } else IceArmor_Timer -= diff; - - //Frostbolt_Timer - if (Frostbolt_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_FROSTBOLT); - - Frostbolt_Timer = 8000; - } else Frostbolt_Timer -= diff; - - //Freeze_Timer - if (Freeze_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FREEZE); - Freeze_Timer = 24000; - } else Freeze_Timer -= diff; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - Fear_Timer = 30000; - } else Fear_Timer -= diff; - - //ChillNova_Timer - if (ChillNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CHILLNOVA); - ChillNova_Timer = 14000; - } else ChillNova_Timer -= diff; - - //FrostVolley_Timer - if (FrostVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTVOLLEY); - FrostVolley_Timer = 15000; - } else FrostVolley_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_rasfrost(Creature* pCreature) -{ - return new boss_rasfrostAI (pCreature); -} - -void AddSC_boss_rasfrost() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_boss_ras_frostwhisper"; - newscript->GetAI = &GetAI_boss_rasfrost; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp deleted file mode 100644 index 6340f2b0e2d..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_the_ravenian -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_TRAMPLE 15550 -#define SPELL_CLEAVE 20691 -#define SPELL_SUNDERINCLEAVE 25174 -#define SPELL_KNOCKAWAY 10101 - -struct boss_theravenianAI : public ScriptedAI -{ - boss_theravenianAI(Creature *c) : ScriptedAI(c) {} - - uint32 Trample_Timer; - uint32 Cleave_Timer; - uint32 SunderingCleave_Timer; - uint32 KnockAway_Timer; - bool HasYelled; - - void Reset() - { - Trample_Timer = 24000; - Cleave_Timer = 15000; - SunderingCleave_Timer = 40000; - KnockAway_Timer = 32000; - HasYelled = false; - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_THERAVENIAN_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Trample_Timer - if (Trample_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TRAMPLE); - Trample_Timer = 10000; - } else Trample_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //SunderingCleave_Timer - if (SunderingCleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDERINCLEAVE); - SunderingCleave_Timer = 20000; - } else SunderingCleave_Timer -= diff; - - //KnockAway_Timer - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - KnockAway_Timer = 12000; - } else KnockAway_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_theravenian(Creature* pCreature) -{ - return new boss_theravenianAI (pCreature); -} - -void AddSC_boss_theravenian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_ravenian"; - newscript->GetAI = &GetAI_boss_theravenian; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp b/src/server/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp deleted file mode 100644 index a38369faab0..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Vectus -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - EMOTE_GENERIC_FRENZY_KILL = -1000001, - - SPELL_FLAMESTRIKE = 18399, - SPELL_BLAST_WAVE = 16046, - SPELL_FIRESHIELD = 19626, - SPELL_FRENZY = 8269 //28371, -}; - -struct boss_vectusAI : public ScriptedAI -{ - boss_vectusAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiFireShield_Timer; - uint32 m_uiBlastWave_Timer; - uint32 m_uiFrenzy_Timer; - - void Reset() - { - m_uiFireShield_Timer = 2000; - m_uiBlastWave_Timer = 14000; - m_uiFrenzy_Timer = 0; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //FireShield_Timer - if (m_uiFireShield_Timer <= uiDiff) - { - DoCast(me, SPELL_FIRESHIELD); - m_uiFireShield_Timer = 90000; - } - else - m_uiFireShield_Timer -= uiDiff; - - //BlastWave_Timer - if (m_uiBlastWave_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BLAST_WAVE); - m_uiBlastWave_Timer = 12000; - } - else - m_uiBlastWave_Timer -= uiDiff; - - //Frenzy_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 25) - { - if (m_uiFrenzy_Timer <= uiDiff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); - - m_uiFrenzy_Timer = 24000; - } - else - m_uiFrenzy_Timer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vectus(Creature* pCreature) -{ - return new boss_vectusAI (pCreature); -} - -void AddSC_boss_vectus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vectus"; - newscript->GetAI = &GetAI_boss_vectus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp b/src/server/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp deleted file mode 100644 index 992849cff1b..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Scholomance -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define GO_GATE_KIRTONOS 175570 -#define GO_GATE_GANDLING 177374 -#define GO_GATE_MALICIA 177375 -#define GO_GATE_THEOLEN 177377 -#define GO_GATE_POLKELT 177376 -#define GO_GATE_RAVENIAN 177372 -#define GO_GATE_BAROV 177373 -#define GO_GATE_ILLUCIA 177371 - -#define MAX_ENCOUNTER 2 - -struct instance_scholomance : public ScriptedInstance -{ - instance_scholomance(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - //Lord Alexei Barov, Doctor Theolen Krastinov, The Ravenian, Lorekeeper Polkelt, Instructor Malicia and the Lady Illucia Barov. - bool IsBossDied[6]; - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 GateKirtonosGUID; - uint64 GateGandlingGUID; - uint64 GateMiliciaGUID; - uint64 GateTheolenGUID; - uint64 GatePolkeltGUID; - uint64 GateRavenianGUID; - uint64 GateBarovGUID; - uint64 GateIlluciaGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - GateKirtonosGUID = 0; - GateGandlingGUID = 0; - GateMiliciaGUID = 0; - GateTheolenGUID = 0; - GatePolkeltGUID = 0; - GateRavenianGUID = 0; - GateBarovGUID = 0; - GateIlluciaGUID = 0; - - for (uint8 i = 0; i < 6; ++i) - IsBossDied[i] = false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_GATE_KIRTONOS: GateKirtonosGUID = pGo->GetGUID(); break; - case GO_GATE_GANDLING: GateGandlingGUID = pGo->GetGUID(); break; - case GO_GATE_MALICIA: GateMiliciaGUID = pGo->GetGUID(); break; - case GO_GATE_THEOLEN: GateTheolenGUID = pGo->GetGUID(); break; - case GO_GATE_POLKELT: GatePolkeltGUID = pGo->GetGUID(); break; - case GO_GATE_RAVENIAN: GateRavenianGUID = pGo->GetGUID(); break; - case GO_GATE_BAROV: GateBarovGUID = pGo->GetGUID(); break; - case GO_GATE_ILLUCIA: GateIlluciaGUID = pGo->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_LORDALEXEIBAROV_DEATH: - IsBossDied[0] = true; - break; - case DATA_DOCTORTHEOLENKRASTINOV_DEATH: - IsBossDied[1] = true; - break; - case DATA_THERAVENIAN_DEATH: - IsBossDied[2] = true; - break; - case DATA_LOREKEEPERPOLKELT_DEATH: - IsBossDied[3] = true; - break; - case DATA_INSTRUCTORMALICIA_DEATH: - IsBossDied[4] = true; - break; - case DATA_LADYILLUCIABAROV_DEATH: - IsBossDied[5] = true; - break; - case TYPE_GANDLING: - m_auiEncounter[0] = data; - break; - case TYPE_KIRTONOS: - m_auiEncounter[1] = data; - break; - } - } - - uint32 GetData(uint32 type) - { - if (type == TYPE_GANDLING) - { - if (IsBossDied[0] && IsBossDied[1] && IsBossDied[2] && IsBossDied[3] && IsBossDied[4] && IsBossDied[5]) - { - m_auiEncounter[0] = IN_PROGRESS; - return IN_PROGRESS; - } - } - - return 0; - } -}; - -InstanceData* GetInstanceData_instance_scholomance(Map* pMap) -{ - return new instance_scholomance(pMap); -} - -void AddSC_instance_scholomance() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_scholomance"; - newscript->GetInstanceData = &GetInstanceData_instance_scholomance; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/scholomance/scholomance.h b/src/server/scripts/eastern_kingdoms/scholomance/scholomance.h deleted file mode 100644 index 83ce26c9687..00000000000 --- a/src/server/scripts/eastern_kingdoms/scholomance/scholomance.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SCHOLOMANCE_H -#define DEF_SCHOLOMANCE_H - -#define TYPE_GANDLING 1 -#define DATA_DOCTORTHEOLENKRASTINOV_DEATH 2 -#define DATA_INSTRUCTORMALICIA_DEATH 3 -#define DATA_LADYILLUCIABAROV_DEATH 4 -#define DATA_LORDALEXEIBAROV_DEATH 5 -#define DATA_LOREKEEPERPOLKELT_DEATH 6 -#define DATA_THERAVENIAN_DEATH 7 -#define TYPE_KIRTONOS 8 -#endif - diff --git a/src/server/scripts/eastern_kingdoms/searing_gorge.cpp b/src/server/scripts/eastern_kingdoms/searing_gorge.cpp deleted file mode 100644 index 3ad51d033da..00000000000 --- a/src/server/scripts/eastern_kingdoms/searing_gorge.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Searing_Gorge -SD%Complete: 80 -SDComment: Quest support: 3377, 3441 (More accurate info on Kalaran needed). Lothos Riftwaker teleport to Molten Core. -SDCategory: Searing Gorge -EndScriptData */ - -/* ContentData -npc_kalaran_windblade -npc_lothos_riftwaker -npc_zamael_lunthistle -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_kalaran_windblade -######*/ - -#define GOSSIP_HELLO_KW "Tell me what drives this vengance?" -#define GOSSIP_SELECT_KW1 "Continue please" -#define GOSSIP_SELECT_KW2 "Let me confer with my colleagues" - -bool GossipHello_npc_kalaran_windblade(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(3441) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_kalaran_windblade(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(1954, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(1955, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(3441); - break; - } - return true; -} - -/*###### -## npc_lothos_riftwaker -######*/ - -#define GOSSIP_HELLO_LR "Teleport me to the Molten Core" - -bool GossipHello_npc_lothos_riftwaker(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestRewardStatus(7487) || pPlayer->GetQuestRewardStatus(7848)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_LR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lothos_riftwaker(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->TeleportTo(409, 1096, -467, -104.6, 3.64); - } - - return true; -} - -/*###### -## npc_zamael_lunthistle -######*/ - -#define GOSSIP_HELLO_ZL "Tell me your story" -#define GOSSIP_SELECT_ZL1 "Please continue..." -#define GOSSIP_SELECT_ZL2 "Goodbye" - -bool GossipHello_npc_zamael_lunthistle(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(3377) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_ZL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(1920, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_zamael_lunthistle(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_ZL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(1921, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_ZL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(1922, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(3377); - break; - } - return true; -} - -/*###### -## -######*/ - -void AddSC_searing_gorge() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_kalaran_windblade"; - newscript->pGossipHello = &GossipHello_npc_kalaran_windblade; - newscript->pGossipSelect = &GossipSelect_npc_kalaran_windblade; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lothos_riftwaker"; - newscript->pGossipHello = &GossipHello_npc_lothos_riftwaker; - newscript->pGossipSelect = &GossipSelect_npc_lothos_riftwaker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_zamael_lunthistle"; - newscript->pGossipHello = &GossipHello_npc_zamael_lunthistle; - newscript->pGossipSelect = &GossipSelect_npc_zamael_lunthistle; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp b/src/server/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp deleted file mode 100644 index 20959641889..00000000000 --- a/src/server/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Shadowfang_Keep -SD%Complete: 90 -SDComment: -SDCategory: Shadowfang Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadowfang_keep.h" - -#define MAX_ENCOUNTER 4 - -enum eEnums -{ - SAY_BOSS_DIE_AD = -1033007, - SAY_BOSS_DIE_AS = -1033008, - SAY_ARCHMAGE = -1033009, - - NPC_ASH = 3850, - NPC_ADA = 3849, - NPC_ARCHMAGE_ARUGAL = 4275, - NPC_ARUGAL_VOIDWALKER = 4627, - - GO_COURTYARD_DOOR = 18895, //door to open when talking to NPC's - GO_SORCERER_DOOR = 18972, //door to open when Fenrus the Devourer - GO_ARUGAL_DOOR = 18971, //door to open when Wolf Master Nandos - - SPELL_ASHCROMBE_TELEPORT = 15742 -}; - -const Position SpawnLocation[] = -{ - {-148.199,2165.647,128.448,1.026}, - {-153.110,2168.620,128.448,1.026}, - {-145.905,2180.520,128.448,4.183}, - {-140.794,2178.037,128.448,4.090}, - {-138.640,2170.159,136.577,2.737} -}; -struct instance_shadowfang_keep : public ScriptedInstance -{ - instance_shadowfang_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 uiAshGUID; - uint64 uiAdaGUID; - uint64 uiArchmageArugalGUID; - - uint64 DoorCourtyardGUID; - uint64 DoorSorcererGUID; - uint64 DoorArugalGUID; - - uint8 uiPhase; - uint16 uiTimer; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - uiAshGUID = 0; - uiAdaGUID = 0; - uiArchmageArugalGUID = 0; - - DoorCourtyardGUID = 0; - DoorSorcererGUID = 0; - DoorArugalGUID = 0; - - uiPhase = 0; - uiTimer = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_ASH: uiAshGUID = pCreature->GetGUID(); break; - case NPC_ADA: uiAdaGUID = pCreature->GetGUID(); break; - case NPC_ARCHMAGE_ARUGAL: uiArchmageArugalGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_COURTYARD_DOOR: - DoorCourtyardGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - HandleGameObject(NULL, true, pGo); - break; - case GO_SORCERER_DOOR: - DoorSorcererGUID = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - HandleGameObject(NULL, true, pGo); - break; - case GO_ARUGAL_DOOR: - DoorArugalGUID = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(NULL, true, pGo); - break; - } - } - - void DoSpeech() - { - Creature* pAda = instance->GetCreature(uiAdaGUID); - Creature* pAsh = instance->GetCreature(uiAshGUID); - - if (pAda && pAda->isAlive() && pAsh && pAsh->isAlive()) - { - DoScriptText(SAY_BOSS_DIE_AD,pAda); - DoScriptText(SAY_BOSS_DIE_AS,pAsh); - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_FREE_NPC: - if (data == DONE) - DoUseDoorOrButton(DoorCourtyardGUID); - m_auiEncounter[0] = data; - break; - case TYPE_RETHILGORE: - if (data == DONE) - DoSpeech(); - m_auiEncounter[1] = data; - break; - case TYPE_FENRUS: - switch(data) - { - case DONE: - uiTimer = 1000; - uiPhase = 1; - break; - case 7: - DoUseDoorOrButton(DoorSorcererGUID); - break; - } - m_auiEncounter[2] = data; - break; - case TYPE_NANDOS: - if (data == DONE) - DoUseDoorOrButton(DoorArugalGUID); - m_auiEncounter[3] = data; - break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_FREE_NPC: - return m_auiEncounter[0]; - case TYPE_RETHILGORE: - return m_auiEncounter[1]; - case TYPE_FENRUS: - return m_auiEncounter[2]; - case TYPE_NANDOS: - return m_auiEncounter[3]; - } - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void Update(uint32 uiDiff) - { - if (GetData(TYPE_FENRUS) != DONE) - return; - - Creature* pArchmage = instance->GetCreature(uiArchmageArugalGUID); - Creature* pSummon = NULL; - - if (!pArchmage || !pArchmage->isAlive()) - return; - - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - pSummon = pArchmage->SummonCreature(pArchmage->GetEntry(),SpawnLocation[4],TEMPSUMMON_TIMED_DESPAWN,10000); - pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - pSummon->SetReactState(REACT_DEFENSIVE); - pSummon->CastSpell(pSummon,SPELL_ASHCROMBE_TELEPORT,true); - DoScriptText(SAY_ARCHMAGE,pSummon); - uiTimer = 2000; - uiPhase = 2; - break; - case 2: - pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[0],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[1],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[2],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - uiPhase = 0; - break; - - } - } else uiTimer -= uiDiff; - } - } -}; - -InstanceData* GetInstanceData_instance_shadowfang_keep(Map* pMap) -{ - return new instance_shadowfang_keep(pMap); -} - -void AddSC_instance_shadowfang_keep() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_shadowfang_keep"; - newscript->GetInstanceData = &GetInstanceData_instance_shadowfang_keep; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp b/src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp deleted file mode 100644 index 23b8ad89160..00000000000 --- a/src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp +++ /dev/null @@ -1,198 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Shadowfang_Keep -SD%Complete: 75 -SDComment: npc_shadowfang_prisoner using escortAI for movement to door. Might need additional code in case being attacked. Add proper texts/say(). -SDCategory: Shadowfang Keep -EndScriptData */ - -/* ContentData -npc_shadowfang_prisoner -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "shadowfang_keep.h" - -/*###### -## npc_shadowfang_prisoner -######*/ - -enum eEnums -{ - SAY_FREE_AS = -1033000, - SAY_OPEN_DOOR_AS = -1033001, - SAY_POST_DOOR_AS = -1033002, - SAY_FREE_AD = -1033003, - SAY_OPEN_DOOR_AD = -1033004, - SAY_POST1_DOOR_AD = -1033005, - SAY_POST2_DOOR_AD = -1033006, - - SPELL_UNLOCK = 6421, - NPC_ASH = 3850, - - SPELL_DARK_OFFERING = 7154 -}; - -#define GOSSIP_ITEM_DOOR "Thanks, I'll follow you to the door." - -struct npc_shadowfang_prisonerAI : public npc_escortAI -{ - npc_shadowfang_prisonerAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - uiNpcEntry = c->GetEntry(); - } - - ScriptedInstance *pInstance; - uint32 uiNpcEntry; - - void WaypointReached(uint32 uiPoint) - { - switch(uiPoint) - { - case 0: - if (uiNpcEntry == NPC_ASH) - DoScriptText(SAY_FREE_AS, me); - else - DoScriptText(SAY_FREE_AD, me); - break; - case 10: - if (uiNpcEntry == NPC_ASH) - DoScriptText(SAY_OPEN_DOOR_AS, me); - else - DoScriptText(SAY_OPEN_DOOR_AD, me); - break; - case 11: - if (uiNpcEntry == NPC_ASH) - DoCast(me, SPELL_UNLOCK); - break; - case 12: - if (uiNpcEntry == NPC_ASH) - DoScriptText(SAY_POST_DOOR_AS, me); - else - DoScriptText(SAY_POST1_DOOR_AD, me); - - if (pInstance) - pInstance->SetData(TYPE_FREE_NPC, DONE); - break; - case 13: - if (uiNpcEntry != NPC_ASH) - DoScriptText(SAY_POST2_DOOR_AD, me); - break; - } - } - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} -}; - -CreatureAI* GetAI_npc_shadowfang_prisoner(Creature* pCreature) -{ - return new npc_shadowfang_prisonerAI(pCreature); -} - -bool GossipHello_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && pInstance->GetData(TYPE_FREE_NPC) != DONE && pInstance->GetData(TYPE_RETHILGORE) == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DOOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_shadowfang_prisonerAI, pCreature->AI())) - pEscortAI->Start(false, false); - } - return true; -} - -struct npc_arugal_voidwalkerAI : public ScriptedAI -{ - npc_arugal_voidwalkerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiDarkOffering; - - void Reset() - { - uiDarkOffering = urand(290,10); - } - - void UpdateAI(uint32 const uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiDarkOffering <= uiDiff) - { - if (Creature* pFriend = me->FindNearestCreature(me->GetEntry(),25.0f,true)) - { - if (pFriend) - DoCast(pFriend,SPELL_DARK_OFFERING); - } - else - DoCast(me,SPELL_DARK_OFFERING); - uiDarkOffering = urand(4400,12500); - } else uiDarkOffering -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(TYPE_FENRUS, pInstance->GetData(TYPE_FENRUS) + 1); - } -}; - -CreatureAI* GetAI_npc_arugal_voidwalker(Creature* pCreature) -{ - return new npc_arugal_voidwalkerAI(pCreature); -} - -void AddSC_shadowfang_keep() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_shadowfang_prisoner"; - newscript->pGossipHello = &GossipHello_npc_shadowfang_prisoner; - newscript->pGossipSelect = &GossipSelect_npc_shadowfang_prisoner; - newscript->GetAI = &GetAI_npc_shadowfang_prisoner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_arugal_voidwalker"; - newscript->GetAI = &GetAI_npc_arugal_voidwalker; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h b/src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h deleted file mode 100644 index a1a59789632..00000000000 --- a/src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SHADOWFANG_H -#define DEF_SHADOWFANG_H - -enum eData -{ - TYPE_FREE_NPC = 1, - TYPE_RETHILGORE = 2, - TYPE_FENRUS = 3, - TYPE_NANDOS = 4 -}; - -#endif - diff --git a/src/server/scripts/eastern_kingdoms/silvermoon_city.cpp b/src/server/scripts/eastern_kingdoms/silvermoon_city.cpp deleted file mode 100644 index 390f083be48..00000000000 --- a/src/server/scripts/eastern_kingdoms/silvermoon_city.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Silvermoon_City -SD%Complete: 100 -SDComment: Quest support: 9685 -SDCategory: Silvermoon City -EndScriptData */ - -/* ContentData -npc_blood_knight_stillblade -EndContentData */ - -#include "ScriptedPch.h" - -/*####### -# npc_blood_knight_stillblade -#######*/ - -#define SAY_HEAL -1000334 - -#define QUEST_REDEEMING_THE_DEAD 9685 -#define SPELL_SHIMMERING_VESSEL 31225 -#define SPELL_REVIVE_SELF 32343 - -struct npc_blood_knight_stillbladeAI : public ScriptedAI -{ - npc_blood_knight_stillbladeAI(Creature *c) : ScriptedAI(c) {} - - uint32 lifeTimer; - bool spellHit; - - void Reset() - { - lifeTimer = 120000; - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetUInt32Value(UNIT_FIELD_BYTES_1,7); // lay down - spellHit = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void MoveInLineOfSight(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (me->IsStandState()) - { - if (lifeTimer <= diff) - me->AI()->EnterEvadeMode(); - else - lifeTimer -= diff; - } - } - - void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) - { - if ((Spellkind->Id == SPELL_SHIMMERING_VESSEL) && !spellHit && - (Hitter->GetTypeId() == TYPEID_PLAYER) && (CAST_PLR(Hitter)->IsActiveQuest(QUEST_REDEEMING_THE_DEAD))) - { - CAST_PLR(Hitter)->AreaExploredOrEventHappens(QUEST_REDEEMING_THE_DEAD); - DoCast(me, SPELL_REVIVE_SELF); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); - //me->RemoveAllAuras(); - DoScriptText(SAY_HEAL, me); - spellHit = true; - } - } -}; - -CreatureAI* GetAI_npc_blood_knight_stillblade(Creature* pCreature) -{ - return new npc_blood_knight_stillbladeAI (pCreature); -} - -void AddSC_silvermoon_city() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "npc_blood_knight_stillblade"; - newscript->GetAI = &GetAI_npc_blood_knight_stillblade; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/silverpine_forest.cpp b/src/server/scripts/eastern_kingdoms/silverpine_forest.cpp deleted file mode 100644 index dd67f048f32..00000000000 --- a/src/server/scripts/eastern_kingdoms/silverpine_forest.cpp +++ /dev/null @@ -1,385 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Silverpine_Forest -SD%Complete: 100 -SDComment: Quest support: 1886, 435, 452 -SDCategory: Silverpine Forest -EndScriptData */ - -/* ContentData -npc_astor_hadren -npc_deathstalker_erland -pyrewood_ambush -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_astor_hadren -######*/ - -#define GOSSIP_HAH "You're Astor Hadren, right?" -#define GOSSIP_SAH "You've got something I need, Astor. And I'll be taking it now." - -struct npc_astor_hadrenAI : public ScriptedAI -{ - npc_astor_hadrenAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - me->setFaction(68); - } - - void EnterCombat(Unit* /*who*/) - { - } - - void JustDied(Unit * /*who*/) - { - me->setFaction(68); - } -}; - -CreatureAI* GetAI_npc_astor_hadren(Creature* pCreature) -{ - return new npc_astor_hadrenAI(pCreature); -} - -bool GossipHello_npc_astor_hadren(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(1886) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HAH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(623, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_astor_hadren(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SAH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(624, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(21); - if (pPlayer) - CAST_AI(npc_astor_hadrenAI, pCreature->AI())->AttackStart(pPlayer); - break; - } - return true; -} - -/*###### -## npc_deathstalker_erland -######*/ - -enum eErland -{ - SAY_QUESTACCEPT = -1000306, - SAY_START = -1000307, - SAY_AGGRO_1 = -1000308, - SAY_AGGRO_2 = -1000309, - SAY_LAST = -1000310, - - SAY_THANKS = -1000311, - SAY_RANE = -1000312, - SAY_ANSWER = -1000313, - SAY_MOVE_QUINN = -1000314, - - SAY_GREETINGS = -1000315, - SAY_QUINN = -1000316, - SAY_ON_BYE = -1000317, - - QUEST_ESCORTING = 435, - NPC_RANE = 1950, - NPC_QUINN = 1951 -}; - -struct npc_deathstalker_erlandAI : public npc_escortAI -{ - npc_deathstalker_erlandAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 1: DoScriptText(SAY_START, me, pPlayer);break; - case 13: - DoScriptText(SAY_LAST, me, pPlayer); - pPlayer->GroupEventHappens(QUEST_ESCORTING, me); break; - case 14: DoScriptText(SAY_THANKS, me, pPlayer); break; - case 15: { - Unit* Rane = me->FindNearestCreature(NPC_RANE, 20); - if (Rane) - DoScriptText(SAY_RANE, Rane); - break;} - case 16: DoScriptText(SAY_ANSWER, me); break; - case 17: DoScriptText(SAY_MOVE_QUINN, me); break; - case 24: DoScriptText(SAY_GREETINGS, me); break; - case 25: { - Unit* Quinn = me->FindNearestCreature(NPC_QUINN, 20); - if (Quinn) - DoScriptText(SAY_QUINN, Quinn); - break;} - case 26: DoScriptText(SAY_ON_BYE, me, NULL); break; - - } - } - - void Reset() {} - - void EnterCombat(Unit* who) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me, who); - } -}; - -bool QuestAccept_npc_deathstalker_erland(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_ESCORTING) - { - DoScriptText(SAY_QUESTACCEPT, pCreature, pPlayer); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_deathstalker_erlandAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - } - - return true; -} - -CreatureAI* GetAI_npc_deathstalker_erlandAI(Creature* pCreature) -{ - return new npc_deathstalker_erlandAI(pCreature); -} - -/*###### -## pyrewood_ambush -#######*/ - -#define QUEST_PYREWOOD_AMBUSH 452 - -#define NPCSAY_INIT "Get ready, they'll be arriving any minute..." //not blizzlike -#define NPCSAY_END "Thanks for your help!" //not blizzlike - -static float PyrewoodSpawnPoints[3][4] = -{ - //pos_x pos_y pos_z orien - //outside - /* - {-400.85, 1513.64, 18.67, 0}, - {-397.32, 1514.12, 18.67, 0}, - {-397.44, 1511.09, 18.67, 0}, - */ - //door - {-396.17, 1505.86, 19.77, 0}, - {-396.91, 1505.77, 19.77, 0}, - {-397.94, 1504.74, 19.77, 0}, -}; - -#define WAIT_SECS 6000 - -struct pyrewood_ambushAI : public ScriptedAI -{ - pyrewood_ambushAI(Creature *c) : ScriptedAI(c), Summons(me) - { - QuestInProgress = false; - } - - uint32 Phase; - int8 KillCount; - uint32 WaitTimer; - uint64 PlayerGUID; - SummonList Summons; - - bool QuestInProgress; - - void Reset() - { - WaitTimer = WAIT_SECS; - - if (!QuestInProgress) //fix reset values (see UpdateVictim) - { - Phase = 0; - KillCount = 0; - PlayerGUID = 0; - Summons.DespawnAll(); - } - } - - void Aggro(Unit * /*who*/){} - - void JustSummoned(Creature *pSummoned) - { - Summons.Summon(pSummoned); - ++KillCount; - } - - void SummonedCreatureDespawn(Creature *pSummoned) - { - Summons.Despawn(pSummoned); - --KillCount; - } - - void SummonCreatureWithRandomTarget(uint32 creatureId, int position) - { - if (Creature *pSummoned = me->SummonCreature(creatureId, PyrewoodSpawnPoints[position][0], PyrewoodSpawnPoints[position][1], PyrewoodSpawnPoints[position][2], PyrewoodSpawnPoints[position][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000)) - { - Player *pPlayer = NULL; - Unit *pTarget = NULL; - if (PlayerGUID) - { - pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer) - pTarget = RAND((Unit*)me, (Unit*)pPlayer); - } else - pTarget = me; - - if (pTarget) - { - pSummoned->setFaction(168); - pSummoned->AddThreat(pTarget, 32.0f); - pSummoned->AI()->AttackStart(pTarget); - } - } - } - - void JustDied(Unit * /*pKiller*/) - { - if (PlayerGUID) - if (Player *pPlayer = Unit::GetPlayer(PlayerGUID)) - if (pPlayer->GetQuestStatus(QUEST_PYREWOOD_AMBUSH) == QUEST_STATUS_INCOMPLETE) - pPlayer->FailQuest(QUEST_PYREWOOD_AMBUSH); - } - - void UpdateAI(const uint32 diff) - { - //sLog.outString("DEBUG: p(%i) k(%i) d(%u) W(%i)", Phase, KillCount, diff, WaitTimer); - - if (!QuestInProgress) - return; - - if (KillCount && Phase < 6) - { - if (!UpdateVictim()) //reset() on target Despawn... - return; - - DoMeleeAttackIfReady(); - return; - } - - switch (Phase) - { - case 0: - if (WaitTimer == WAIT_SECS) - me->MonsterSay(NPCSAY_INIT, LANG_UNIVERSAL, 0); //no blizzlike - - if (WaitTimer <= diff) - { - WaitTimer -= diff; - return; - } - break; - case 1: - SummonCreatureWithRandomTarget(2060, 1); - break; - case 2: - SummonCreatureWithRandomTarget(2061, 2); - SummonCreatureWithRandomTarget(2062, 0); - break; - case 3: - SummonCreatureWithRandomTarget(2063, 1); - SummonCreatureWithRandomTarget(2064, 2); - SummonCreatureWithRandomTarget(2065, 0); - break; - case 4: - SummonCreatureWithRandomTarget(2066, 1); - SummonCreatureWithRandomTarget(2067, 0); - SummonCreatureWithRandomTarget(2068, 2); - break; - case 5: //end - if (PlayerGUID) - { - if (Player *pPlayer = Unit::GetPlayer(PlayerGUID)) - { - me->MonsterSay(NPCSAY_END, LANG_UNIVERSAL, 0); //not blizzlike - pPlayer->GroupEventHappens(QUEST_PYREWOOD_AMBUSH, me); - } - } - QuestInProgress = false; - Reset(); - break; - } - ++Phase; //prepare next phase - } -}; - -CreatureAI* GetAI_pyrewood_ambush(Creature *pCreature) -{ - return new pyrewood_ambushAI (pCreature); -} - -bool QuestAccept_pyrewood_ambush(Player *pPlayer, Creature *pCreature, const Quest *pQuest) -{ - if (pQuest->GetQuestId() == QUEST_PYREWOOD_AMBUSH && !CAST_AI(pyrewood_ambushAI, pCreature->AI())->QuestInProgress) - { - CAST_AI(pyrewood_ambushAI, pCreature->AI())->QuestInProgress = true; - CAST_AI(pyrewood_ambushAI, pCreature->AI())->Phase = 0; - CAST_AI(pyrewood_ambushAI, pCreature->AI())->KillCount = 0; - CAST_AI(pyrewood_ambushAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); - } - - return true; -} - -/*###### -## AddSC -######*/ - -void AddSC_silverpine_forest() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_astor_hadren"; - newscript->pGossipHello = &GossipHello_npc_astor_hadren; - newscript->pGossipSelect = &GossipSelect_npc_astor_hadren; - newscript->GetAI = &GetAI_npc_astor_hadren; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_deathstalker_erland"; - newscript->GetAI = &GetAI_npc_deathstalker_erlandAI; - newscript->pQuestAccept = &QuestAccept_npc_deathstalker_erland; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "pyrewood_ambush"; - newscript->GetAI = &GetAI_pyrewood_ambush; - newscript->pQuestAccept = &QuestAccept_pyrewood_ambush; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/stormwind_city.cpp b/src/server/scripts/eastern_kingdoms/stormwind_city.cpp deleted file mode 100644 index 36a7d116c3b..00000000000 --- a/src/server/scripts/eastern_kingdoms/stormwind_city.cpp +++ /dev/null @@ -1,696 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Stormwind_City -SD%Complete: 100 -SDComment: Quest support: 1640, 1447, 4185, 11223, 434. -SDCategory: Stormwind City -EndScriptData */ - -/* ContentData -npc_archmage_malin -npc_bartleby -npc_dashel_stonefist -npc_lady_katrana_prestor -npc_tyrion -npc_tyrion_spybot -npc_marzon_silent_blade -npc_lord_gregor_lescovar -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_archmage_malin -######*/ - -#define GOSSIP_ITEM_MALIN "Can you send me to Theramore? I have an urgent message for Lady Jaina from Highlord Bolvar." - -bool GossipHello_npc_archmage_malin(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(11223) == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(11223)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MALIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_archmage_malin(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, 42711, true); - } - - return true; -} - -/*###### -## npc_bartleby -######*/ - -enum eBartleby -{ - FACTION_ENEMY = 168, - QUEST_BEAT = 1640 -}; - -struct npc_bartlebyAI : public ScriptedAI -{ - npc_bartlebyAI(Creature *c) : ScriptedAI(c) - { - m_uiNormalFaction = c->getFaction(); - } - - uint32 m_uiNormalFaction; - - void Reset() - { - if (me->getFaction() != m_uiNormalFaction) - me->setFaction(m_uiNormalFaction); - } - - void AttackedBy(Unit* pAttacker) - { - if (me->getVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) - { - if (uiDamage > me->GetHealth() || ((me->GetHealth() - uiDamage)*100 / me->GetMaxHealth() < 15)) - { - //Take 0 damage - uiDamage = 0; - - if (pDoneBy->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(pDoneBy)->AreaExploredOrEventHappens(QUEST_BEAT); - EnterEvadeMode(); - } - } -}; - -bool QuestAccept_npc_bartleby(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_BEAT) - { - pCreature->setFaction(FACTION_ENEMY); - pCreature->AI()->AttackStart(pPlayer); - } - return true; -} - -CreatureAI* GetAI_npc_bartleby(Creature* pCreature) -{ - return new npc_bartlebyAI(pCreature); -} - -/*###### -## npc_dashel_stonefist -######*/ - -enum eDashel -{ - QUEST_MISSING_DIPLO_PT8 = 1447, - FACTION_HOSTILE = 168 -}; - -struct npc_dashel_stonefistAI : public ScriptedAI -{ - npc_dashel_stonefistAI(Creature *c) : ScriptedAI(c) - { - m_uiNormalFaction = c->getFaction(); - } - - uint32 m_uiNormalFaction; - - void Reset() - { - if (me->getFaction() != m_uiNormalFaction) - me->setFaction(m_uiNormalFaction); - } - - void AttackedBy(Unit* pAttacker) - { - if (me->getVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) - { - if (uiDamage > me->GetHealth() || ((me->GetHealth() - uiDamage)*100 / me->GetMaxHealth() < 15)) - { - uiDamage = 0; - - if (pDoneBy->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(pDoneBy)->AreaExploredOrEventHappens(QUEST_MISSING_DIPLO_PT8); - - EnterEvadeMode(); - } - } -}; - -bool QuestAccept_npc_dashel_stonefist(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT8) - { - pCreature->setFaction(FACTION_HOSTILE); - CAST_AI(npc_dashel_stonefistAI, pCreature->AI())->AttackStart(pPlayer); - } - return true; -} - -CreatureAI* GetAI_npc_dashel_stonefist(Creature* pCreature) -{ - return new npc_dashel_stonefistAI(pCreature); -} - -/*###### -## npc_lady_katrana_prestor -######*/ - -#define GOSSIP_ITEM_KAT_1 "Pardon the intrusion, Lady Prestor, but Highlord Bolvar suggested that I seek your advice." -#define GOSSIP_ITEM_KAT_2 "My apologies, Lady Prestor." -#define GOSSIP_ITEM_KAT_3 "Begging your pardon, Lady Prestor. That was not my intent." -#define GOSSIP_ITEM_KAT_4 "Thank you for your time, Lady Prestor." - -bool GossipHello_npc_lady_katrana_prestor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(4185) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(2693, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lady_katrana_prestor(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2694, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(2695, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(2696, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(4185); - break; - } - return true; -} - -/*###### -## npc_lord_gregor_lescovar -######*/ - -enum eLordGregorLescovar -{ - SAY_LESCOVAR_2 = -1000457, - SAY_GUARD_2 = -1000458, - SAY_LESCOVAR_3 = -1000459, - SAY_MARZON_1 = -1000460, - SAY_LESCOVAR_4 = -1000461, - SAY_TYRION_2 = -1000462, - SAY_MARZON_2 = -1000463, - - NPC_STORMWIND_ROYAL = 1756, - NPC_MARZON_BLADE = 1755, - NPC_TYRION = 7766, - - QUEST_THE_ATTACK = 434 -}; - -struct npc_lord_gregor_lescovarAI : public npc_escortAI -{ - npc_lord_gregor_lescovarAI(Creature* pCreature) : npc_escortAI(pCreature) - { - pCreature->RestoreFaction(); - } - - uint32 uiTimer; - uint32 uiPhase; - - uint64 MarzonGUID; - - void Reset() - { - uiTimer = 0; - uiPhase = 0; - - MarzonGUID = 0; - } - - void EnterEvadeMode() - { - me->DisappearAndDie(); - - if (Creature *pMarzon = Unit::GetCreature(*me, MarzonGUID)) - { - if (pMarzon->isAlive()) - pMarzon->DisappearAndDie(); - } - } - - void EnterCombat(Unit* pWho) - { - if (Creature *pMarzon = Unit::GetCreature(*me, MarzonGUID)) - { - if (pMarzon->isAlive() && !pMarzon->isInCombat()) - pMarzon->AI()->AttackStart(pWho); - } - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 14: - SetEscortPaused(true); - DoScriptText(SAY_LESCOVAR_2, me); - uiTimer = 3000; - uiPhase = 1; - break; - case 16: - SetEscortPaused(true); - if (Creature *pMarzon = me->SummonCreature(NPC_MARZON_BLADE,-8411.360352, 480.069733, 123.760895, 4.941504, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000)) - { - pMarzon->GetMotionMaster()->MovePoint(0,-8408.000977, 468.611450, 123.759903); - MarzonGUID = pMarzon->GetGUID(); - } - uiTimer = 2000; - uiPhase = 4; - break; - } - } - //TO-DO: We don't have movemaps, also we can't make 2 npcs walks to one point propperly (and we can not use escort ai, because they are 2 different spawns and with same entry), because of it we make them, disappear. - void DoGuardsDisappearAndDie() - { - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList,NPC_STORMWIND_ROYAL,8.0f); - if (!GuardList.empty()) - { - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - pGuard->DisappearAndDie(); - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - if (Creature* pGuard = me->FindNearestCreature(NPC_STORMWIND_ROYAL, 8.0f, true)) - DoScriptText(SAY_GUARD_2, pGuard); - uiTimer = 3000; - uiPhase = 2; - break; - case 2: - DoGuardsDisappearAndDie(); - uiTimer = 2000; - uiPhase = 3; - break; - case 3: - SetEscortPaused(false); - uiTimer = 0; - uiPhase = 0; - break; - case 4: - DoScriptText(SAY_LESCOVAR_3, me); - uiTimer = 0; - uiPhase = 0; - break; - case 5: - if (Creature *pMarzon = Unit::GetCreature(*me, MarzonGUID)) - DoScriptText(SAY_MARZON_1, pMarzon); - uiTimer = 3000; - uiPhase = 6; - break; - case 6: - DoScriptText(SAY_LESCOVAR_4, me); - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->AreaExploredOrEventHappens(QUEST_THE_ATTACK); - uiTimer = 2000; - uiPhase = 7; - break; - case 7: - if (Creature* pTyrion = me->FindNearestCreature(NPC_TYRION, 20.0f, true)) - DoScriptText(SAY_TYRION_2, pTyrion); - if (Creature *pMarzon = Unit::GetCreature(*me, MarzonGUID)) - pMarzon->setFaction(14); - me->setFaction(14); - uiTimer = 0; - uiPhase = 0; - break; - } - } else uiTimer -= uiDiff; - } - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_lord_gregor_lescovar(Creature* pCreature) -{ - return new npc_lord_gregor_lescovarAI(pCreature); -} - -/*###### -## npc_marzon_silent_blade -######*/ - -struct npc_marzon_silent_bladeAI : public ScriptedAI -{ - npc_marzon_silent_bladeAI(Creature* pCreature) : ScriptedAI(pCreature) - { - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - } - - void Reset() - { - me->RestoreFaction(); - } - - void EnterCombat(Unit* pWho) - { - DoScriptText(SAY_MARZON_2, me); - - if (me->isSummon()) - { - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - { - if (pSummoner && pSummoner->isAlive() && !pSummoner->isInCombat()) - CAST_CRE(pSummoner)->AI()->AttackStart(pWho); - } - } - } - - void EnterEvadeMode() - { - me->DisappearAndDie(); - - if (me->isSummon()) - { - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - { - if (pSummoner && pSummoner->isAlive()) - CAST_CRE(pSummoner)->DisappearAndDie(); - } - } - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (me->isSummon()) - { - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - { - CAST_AI(npc_lord_gregor_lescovarAI, CAST_CRE(pSummoner)->AI())->uiTimer = 2000; - CAST_AI(npc_lord_gregor_lescovarAI, CAST_CRE(pSummoner)->AI())->uiPhase = 5; - //me->ChangeOrient(0.0f, pSummoner); - } - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_marzon_silent_blade(Creature* pCreature) -{ - return new npc_marzon_silent_bladeAI(pCreature); -} - -/*###### -## npc_tyrion_spybot -######*/ - -enum eTyrionSpybot -{ - SAY_QUEST_ACCEPT_ATTACK = -1000499, - SAY_TYRION_1 = -1000450, - SAY_SPYBOT_1 = -1000451, - SAY_GUARD_1 = -1000452, - SAY_SPYBOT_2 = -1000453, - SAY_SPYBOT_3 = -1000454, - SAY_LESCOVAR_1 = -1000455, - SAY_SPYBOT_4 = -1000456, - - NPC_PRIESTESS_TYRIONA = 7779, - NPC_LORD_GREGOR_LESCOVAR = 1754, -}; - -struct npc_tyrion_spybotAI : public npc_escortAI -{ - npc_tyrion_spybotAI(Creature* pCreature) : npc_escortAI(pCreature) {} - - uint32 uiTimer; - uint32 uiPhase; - - void Reset() - { - uiTimer = 0; - uiPhase = 0; - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 1: - SetEscortPaused(true); - uiTimer = 2000; - uiPhase = 1; - break; - case 5: - SetEscortPaused(true); - DoScriptText(SAY_SPYBOT_1, me); - uiTimer = 2000; - uiPhase = 5; - break; - case 17: - SetEscortPaused(true); - DoScriptText(SAY_SPYBOT_3, me); - uiTimer = 3000; - uiPhase = 8; - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - DoScriptText(SAY_QUEST_ACCEPT_ATTACK, me); - uiTimer = 3000; - uiPhase = 2; - break; - case 2: - if (Creature* pTyrion = me->FindNearestCreature(NPC_TYRION,10.0f)) - DoScriptText(SAY_TYRION_1, pTyrion); - uiTimer = 3000; - uiPhase = 3; - break; - case 3: - me->UpdateEntry(NPC_PRIESTESS_TYRIONA, ALLIANCE); - uiTimer = 2000; - uiPhase = 4; - break; - case 4: - SetEscortPaused(false); - uiPhase = 0; - uiTimer = 0; - break; - case 5: - if (Creature* pGuard = me->FindNearestCreature(NPC_STORMWIND_ROYAL, 10.0f, true)) - DoScriptText(SAY_GUARD_1, pGuard); - uiTimer = 3000; - uiPhase = 6; - break; - case 6: - DoScriptText(SAY_SPYBOT_2, me); - uiTimer = 3000; - uiPhase = 7; - break; - case 7: - SetEscortPaused(false); - uiTimer = 0; - uiPhase = 0; - break; - case 8: - if (Creature* pLescovar = me->FindNearestCreature(NPC_LORD_GREGOR_LESCOVAR,10.0f)) - DoScriptText(SAY_LESCOVAR_1, pLescovar); - uiTimer = 3000; - uiPhase = 9; - break; - case 9: - DoScriptText(SAY_SPYBOT_4, me); - uiTimer = 3000; - uiPhase = 10; - break; - case 10: - if (Creature* pLescovar = me->FindNearestCreature(NPC_LORD_GREGOR_LESCOVAR,10.0f)) - { - if (Player* pPlayer = GetPlayerForEscort()) - { - CAST_AI(npc_lord_gregor_lescovarAI,pLescovar->AI())->Start(false, false, pPlayer->GetGUID()); - CAST_AI(npc_lord_gregor_lescovarAI, pLescovar->AI())->SetMaxPlayerDistance(200.0f); - } - } - me->DisappearAndDie(); - uiTimer = 0; - uiPhase = 0; - break; - } - } else uiTimer -= uiDiff; - } - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_tyrion_spybot(Creature* pCreature) -{ - return new npc_tyrion_spybotAI(pCreature); -} - -/*###### -## npc_tyrion -######*/ - -enum eTyrion -{ - NPC_TYRION_SPYBOT = 8856 -}; - -bool QuestAccept_npc_tyrion(Player* pPlayer, Creature* pCreature, Quest const *pQuest) -{ - if (pQuest->GetQuestId() == QUEST_THE_ATTACK) - { - if (Creature* pSpybot = pCreature->FindNearestCreature(NPC_TYRION_SPYBOT, 5.0f, true)) - { - CAST_AI(npc_tyrion_spybotAI,pSpybot->AI())->Start(false, false, pPlayer->GetGUID()); - CAST_AI(npc_tyrion_spybotAI,pSpybot->AI())->SetMaxPlayerDistance(200.0f); - } - return true; - } - return false; -} - -void AddSC_stormwind_city() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_archmage_malin"; - newscript->pGossipHello = &GossipHello_npc_archmage_malin; - newscript->pGossipSelect = &GossipSelect_npc_archmage_malin; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_bartleby"; - newscript->GetAI = &GetAI_npc_bartleby; - newscript->pQuestAccept = &QuestAccept_npc_bartleby; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dashel_stonefist"; - newscript->GetAI = &GetAI_npc_dashel_stonefist; - newscript->pQuestAccept = &QuestAccept_npc_dashel_stonefist; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lady_katrana_prestor"; - newscript->pGossipHello = &GossipHello_npc_lady_katrana_prestor; - newscript->pGossipSelect = &GossipSelect_npc_lady_katrana_prestor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tyrion"; - newscript->pQuestAccept = &QuestAccept_npc_tyrion; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tyrion_spybot"; - newscript->GetAI = &GetAI_npc_tyrion_spybot; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lord_gregor_lescovar"; - newscript->GetAI = &GetAI_npc_lord_gregor_lescovar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_marzon_silent_blade"; - newscript->GetAI = &GetAI_npc_marzon_silent_blade; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/stranglethorn_vale.cpp b/src/server/scripts/eastern_kingdoms/stranglethorn_vale.cpp deleted file mode 100644 index 08d364d1808..00000000000 --- a/src/server/scripts/eastern_kingdoms/stranglethorn_vale.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Stranglethorn_Vale -SD%Complete: 100 -SDComment: Quest support: 592 -SDCategory: Stranglethorn Vale -EndScriptData */ - -/* ContentData -mob_yenniku -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## mob_yenniku -######*/ - -struct mob_yennikuAI : public ScriptedAI -{ - mob_yennikuAI(Creature *c) : ScriptedAI(c) - { - bReset = false; - } - - uint32 Reset_Timer; - bool bReset; - - void Reset() - { - Reset_Timer = 0; - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - //Yenniku's Release - if (!bReset && CAST_PLR(caster)->GetQuestStatus(592) == QUEST_STATUS_INCOMPLETE && spell->Id == 3607) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); - me->CombatStop(); //stop combat - me->DeleteThreatList(); //unsure of this - me->setFaction(83); //horde generic - - bReset = true; - Reset_Timer = 60000; - } - } - return; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (bReset) - { - if (Reset_Timer <= diff) - { - EnterEvadeMode(); - bReset = false; - me->setFaction(28); //troll, bloodscalp - return; - } - else Reset_Timer -= diff; - - if (me->isInCombat() && me->getVictim()) - { - if (me->getVictim()->GetTypeId() == TYPEID_PLAYER) - { - Unit *victim = me->getVictim(); - if (CAST_PLR(victim)->GetTeam() == HORDE) - { - me->CombatStop(); - me->DeleteThreatList(); - } - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_mob_yenniku(Creature* pCreature) -{ - return new mob_yennikuAI (pCreature); -} - -/*###### -## -######*/ - -void AddSC_stranglethorn_vale() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_yenniku"; - newscript->GetAI = &GetAI_mob_yenniku; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp deleted file mode 100644 index de17717e289..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Baron_Rivendare -SD%Complete: 70 -SDComment: aura applied/defined in database -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SAY_0 "Intruders! More pawns of the Argent Dawn, no doubt. I already count one of their number among my prisoners. Withdraw from my domain before she is executed!" -#define SAY_1 "You're still here? Your foolishness is amusing! The Argent Dawn wench needn't suffer in vain. Leave at once and she shall be spared!" -#define SAY_2 "I shall take great pleasure in taking this poor wretch's life! It's not too late, she needn't suffer in vain. Turn back and her death shall be merciful!" -#define SAY_3 "May this prisoner's death serve as a warning. None shall defy the Scourge and live!" -#define SAY_4 "So you see fit to toy with the Lich King's creations? Ramstein, be sure to give the intruders a proper greeting." -#define SAY_5 "Time to take matters into my own hands. Come. Enter my domain and challenge the might of the Scourge!" - -#define ADD_1X 4017.403809 -#define ADD_1Y -3339.703369 -#define ADD_1Z 115.057655 -#define ADD_1O 5.487860 - -#define ADD_2X 4013.189209 -#define ADD_2Y -3351.808350 -#define ADD_2Z 115.052254 -#define ADD_2O 0.134280 - -#define ADD_3X 4017.738037 -#define ADD_3Y -3363.478016 -#define ADD_3Z 115.057274 -#define ADD_3O 0.723313 - -#define ADD_4X 4048.877197 -#define ADD_4Y -3363.223633 -#define ADD_4Z 115.054253 -#define ADD_4O 3.627735 - -#define ADD_5X 4051.777588 -#define ADD_5Y -3350.893311 -#define ADD_5Z 115.055351 -#define ADD_5O 3.066176 - -#define ADD_6X 4048.375977 -#define ADD_6Y -3339.966309 -#define ADD_6Z 115.055222 -#define ADD_6O 2.457497 - -#define SPELL_SHADOWBOLT 17393 -#define SPELL_CLEAVE 15284 -#define SPELL_MORTALSTRIKE 15708 - -#define SPELL_UNHOLY_AURA 17467 -#define SPELL_RAISEDEAD 17473 //triggers death pact (17471) - -#define SPELL_RAISE_DEAD1 17475 -#define SPELL_RAISE_DEAD2 17476 -#define SPELL_RAISE_DEAD3 17477 -#define SPELL_RAISE_DEAD4 17478 -#define SPELL_RAISE_DEAD5 17479 -#define SPELL_RAISE_DEAD6 17480 - -struct boss_baron_rivendareAI : public ScriptedAI -{ - boss_baron_rivendareAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ShadowBolt_Timer; - uint32 Cleave_Timer; - uint32 MortalStrike_Timer; - // uint32 RaiseDead_Timer; - uint32 SummonSkeletons_Timer; - - void Reset() - { - ShadowBolt_Timer = 5000; - Cleave_Timer = 8000; - MortalStrike_Timer = 12000; - // RaiseDead_Timer = 30000; - SummonSkeletons_Timer = 34000; - if (pInstance && pInstance->GetData(TYPE_RAMSTEIN) == DONE) - pInstance->SetData(TYPE_BARON,NOT_STARTED); - } - - void AttackStart(Unit* who) - { - if (pInstance)//can't use entercombat(), boss' dmg aura sets near players in combat, before entering the room's door - pInstance->SetData(TYPE_BARON,IN_PROGRESS); - ScriptedAI::AttackStart(who); - } - - void JustSummoned(Creature* summoned) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(pTarget); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_BARON,DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowBolt - if (ShadowBolt_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(me->getVictim(), SPELL_SHADOWBOLT); - - ShadowBolt_Timer = 10000; - } else ShadowBolt_Timer -= diff; - - //Cleave - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - //13 seconds until we should cast this again - Cleave_Timer = 7000 + (rand()%10000); - } else Cleave_Timer -= diff; - - //MortalStrike - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = 10000 + (rand()%15000); - } else MortalStrike_Timer -= diff; - - //RaiseDead - // if (RaiseDead_Timer <= diff) - // { - // DoCast(me, SPELL_RAISEDEAD); - // RaiseDead_Timer = 45000; - // } else RaiseDead_Timer -= diff; - - //SummonSkeletons - if (SummonSkeletons_Timer <= diff) - { - me->SummonCreature(11197,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,29000); - - //34 seconds until we should cast this again - SummonSkeletons_Timer = 40000; - } else SummonSkeletons_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_baron_rivendare(Creature* pCreature) -{ - return new boss_baron_rivendareAI (pCreature); -} - -void AddSC_boss_baron_rivendare() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_baron_rivendare"; - newscript->GetAI = &GetAI_boss_baron_rivendare; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp deleted file mode 100644 index cff4fe3fbae..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Baroness_Anastari -SD%Complete: 90 -SDComment: MC disabled -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_BANSHEEWAIL 16565 -#define SPELL_BANSHEECURSE 16867 -#define SPELL_SILENCE 18327 -//#define SPELL_POSSESS 17244 - -struct boss_baroness_anastariAI : public ScriptedAI -{ - boss_baroness_anastariAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 BansheeWail_Timer; - uint32 BansheeCurse_Timer; - uint32 Silence_Timer; - //uint32 Possess_Timer; - - void Reset() - { - BansheeWail_Timer = 1000; - BansheeCurse_Timer = 11000; - Silence_Timer = 13000; - //Possess_Timer = 35000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_BARONESS,IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //BansheeWail - if (BansheeWail_Timer <= diff) - { - if (rand()%100 < 95) - DoCast(me->getVictim(), SPELL_BANSHEEWAIL); - //4 seconds until we should cast this again - BansheeWail_Timer = 4000; - } else BansheeWail_Timer -= diff; - - //BansheeCurse - if (BansheeCurse_Timer <= diff) - { - if (rand()%100 < 75) - DoCast(me->getVictim(), SPELL_BANSHEECURSE); - //18 seconds until we should cast this again - BansheeCurse_Timer = 18000; - } else BansheeCurse_Timer -= diff; - - //Silence - if (Silence_Timer <= diff) - { - if (rand()%100 < 80) - DoCast(me->getVictim(), SPELL_SILENCE); - //13 seconds until we should cast this again - Silence_Timer = 13000; - } else Silence_Timer -= diff; - - //Possess - /* if (Possess_Timer <= diff) - { - //Cast - if (rand()%100 < 65) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget)DoCast(pTarget, SPELL_POSSESS); - } - //50 seconds until we should cast this again - Possess_Timer = 50000; - } else Possess_Timer -= diff; - */ - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_baroness_anastari(Creature* pCreature) -{ - return new boss_baroness_anastariAI (pCreature); -} - -void AddSC_boss_baroness_anastari() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_baroness_anastari"; - newscript->GetAI = &GetAI_boss_baroness_anastari; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp deleted file mode 100644 index c12f7b9ad04..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_cannon_master_willey -SD%Complete: 100 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" - -//front, left -#define ADD_1X 3553.851807 -#define ADD_1Y -2945.885986 -#define ADD_1Z 125.001015 -#define ADD_1O 0.592007 -//front, right -#define ADD_2X 3559.206299 -#define ADD_2Y -2952.929932 -#define ADD_2Z 125.001015 -#define ADD_2O 0.592007 -//mid, left -#define ADD_3X 3552.417480 -#define ADD_3Y -2948.667236 -#define ADD_3Z 125.001015 -#define ADD_3O 0.592007 -//mid, right -#define ADD_4X 3555.651855 -#define ADD_4Y -2953.519043 -#define ADD_4Z 125.001015 -#define ADD_4O 0.592007 -//back, left -#define ADD_5X 3547.927246 -#define ADD_5Y -2950.977295 -#define ADD_5Z 125.001015 -#define ADD_5O 0.592007 -//back, mid -#define ADD_6X 3553.094697 -#define ADD_6Y -2952.123291 -#define ADD_6Z 125.001015 -#define ADD_6O 0.592007 -//back, right -#define ADD_7X 3552.727539 -#define ADD_7Y -2957.776123 -#define ADD_7Z 125.001015 -#define ADD_7O 0.592007 -//behind, left -#define ADD_8X 3547.156250 -#define ADD_8Y -2953.162354 -#define ADD_8Z 125.001015 -#define ADD_8O 0.592007 -//behind, right -#define ADD_9X 3550.202148 -#define ADD_9Y -2957.437744 -#define ADD_9Z 125.001015 -#define ADD_9O 0.592007 - -#define SPELL_KNOCKAWAY 10101 -#define SPELL_PUMMEL 15615 -#define SPELL_SHOOT 16496 -//#define SPELL_SUMMONCRIMSONRIFLEMAN 17279 - -struct boss_cannon_master_willeyAI : public ScriptedAI -{ - boss_cannon_master_willeyAI(Creature *c) : ScriptedAI(c) {} - - uint32 KnockAway_Timer; - uint32 Pummel_Timer; - uint32 Shoot_Timer; - uint32 SummonRifleman_Timer; - - void Reset() - { - Shoot_Timer = 1000; - Pummel_Timer = 7000; - KnockAway_Timer = 11000; - SummonRifleman_Timer = 15000; - } - - void JustDied(Unit* /*Victim*/) - { - me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Pummel - if (Pummel_Timer <= diff) - { - //Cast - if (rand()%100 < 90) //90% chance to cast - { - DoCast(me->getVictim(), SPELL_PUMMEL); - } - //12 seconds until we should cast this again - Pummel_Timer = 12000; - } else Pummel_Timer -= diff; - - //KnockAway - if (KnockAway_Timer <= diff) - { - //Cast - if (rand()%100 < 80) //80% chance to cast - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - } - //14 seconds until we should cast this again - KnockAway_Timer = 14000; - } else KnockAway_Timer -= diff; - - //Shoot - if (Shoot_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_SHOOT); - //1 seconds until we should cast this again - Shoot_Timer = 1000; - } else Shoot_Timer -= diff; - - //SummonRifleman - if (SummonRifleman_Timer <= diff) - { - //Cast - switch (rand()%9) - { - case 0: - me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 1: - me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 2: - me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 3: - me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 4: - me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 5: - me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 6: - me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 7: - me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 8: - me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - } - //30 seconds until we should cast this again - SummonRifleman_Timer = 30000; - } else SummonRifleman_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_cannon_master_willey(Creature* pCreature) -{ - return new boss_cannon_master_willeyAI (pCreature); -} - -void AddSC_boss_cannon_master_willey() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_cannon_master_willey"; - newscript->GetAI = &GetAI_boss_cannon_master_willey; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp deleted file mode 100644 index a8489a7f549..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Dathrohan_Balnazzar -SD%Complete: 95 -SDComment: Possibly need to fix/improve summons after death -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - //Dathrohan spells - SPELL_CRUSADERSHAMMER = 17286, //AOE stun - SPELL_CRUSADERSTRIKE = 17281, - SPELL_HOLYSTRIKE = 17284, //weapon dmg +3 - - //Transform - SPELL_BALNAZZARTRANSFORM = 17288, //restore full HP/mana, trigger spell Balnazzar Transform Stun - - //Balnazzar spells - SPELL_SHADOWSHOCK = 17399, - SPELL_MINDBLAST = 17287, - SPELL_PSYCHICSCREAM = 13704, - SPELL_SLEEP = 12098, - SPELL_MINDCONTROL = 15690, - - NPC_DATHROHAN = 10812, - NPC_BALNAZZAR = 10813, - NPC_ZOMBIE = 10698 //probably incorrect -}; - -struct SummonDef -{ - float m_fX, m_fY, m_fZ, m_fOrient; -}; - -SummonDef m_aSummonPoint[]= -{ - {3444.156, -3090.626, 135.002, 2.240}, //G1 front, left - {3449.123, -3087.009, 135.002, 2.240}, //G1 front, right - {3446.246, -3093.466, 135.002, 2.240}, //G1 back left - {3451.160, -3089.904, 135.002, 2.240}, //G1 back, right - - {3457.995, -3080.916, 135.002, 3.784}, //G2 front, left - {3454.302, -3076.330, 135.002, 3.784}, //G2 front, right - {3460.975, -3078.901, 135.002, 3.784}, //G2 back left - {3457.338, -3073.979, 135.002, 3.784} //G2 back, right -}; - -struct boss_dathrohan_balnazzarAI : public ScriptedAI -{ - boss_dathrohan_balnazzarAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiCrusadersHammer_Timer; - uint32 m_uiCrusaderStrike_Timer; - uint32 m_uiMindBlast_Timer; - uint32 m_uiHolyStrike_Timer; - uint32 m_uiShadowShock_Timer; - uint32 m_uiPsychicScream_Timer; - uint32 m_uiDeepSleep_Timer; - uint32 m_uiMindControl_Timer; - bool m_bTransformed; - - void Reset() - { - m_uiCrusadersHammer_Timer = 8000; - m_uiCrusaderStrike_Timer = 12000; - m_uiMindBlast_Timer = 6000; - m_uiHolyStrike_Timer = 18000; - m_uiShadowShock_Timer = 4000; - m_uiPsychicScream_Timer = 16000; - m_uiDeepSleep_Timer = 20000; - m_uiMindControl_Timer = 10000; - m_bTransformed = false; - - if (me->GetEntry() == NPC_BALNAZZAR) - me->UpdateEntry(NPC_DATHROHAN); - } - - void JustDied(Unit* /*Victim*/) - { - static uint32 uiCount = sizeof(m_aSummonPoint)/sizeof(SummonDef); - - for (uint8 i=0; iSummonCreature(NPC_ZOMBIE, - m_aSummonPoint[i].m_fX, m_aSummonPoint[i].m_fY, m_aSummonPoint[i].m_fZ, m_aSummonPoint[i].m_fOrient, - TEMPSUMMON_TIMED_DESPAWN, HOUR*IN_MILISECONDS); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //START NOT TRANSFORMED - if (!m_bTransformed) - { - //MindBlast - if (m_uiMindBlast_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MINDBLAST); - m_uiMindBlast_Timer = 15000 + rand()%5000; - } else m_uiMindBlast_Timer -= uiDiff; - - //CrusadersHammer - if (m_uiCrusadersHammer_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CRUSADERSHAMMER); - m_uiCrusadersHammer_Timer = 12000; - } else m_uiCrusadersHammer_Timer -= uiDiff; - - //CrusaderStrike - if (m_uiCrusaderStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CRUSADERSTRIKE); - m_uiCrusaderStrike_Timer = 15000; - } else m_uiCrusaderStrike_Timer -= uiDiff; - - //HolyStrike - if (m_uiHolyStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_HOLYSTRIKE); - m_uiHolyStrike_Timer = 15000; - } else m_uiHolyStrike_Timer -= uiDiff; - - //BalnazzarTransform - if (me->GetHealth()*100 / me->GetMaxHealth() < 40) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - //restore hp, mana and stun - DoCast(me, SPELL_BALNAZZARTRANSFORM); - me->UpdateEntry(NPC_BALNAZZAR); - m_bTransformed = true; - } - } - else - { - //MindBlast - if (m_uiMindBlast_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MINDBLAST); - m_uiMindBlast_Timer = 15000 + rand()%5000; - } else m_uiMindBlast_Timer -= uiDiff; - - //ShadowShock - if (m_uiShadowShock_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SHADOWSHOCK); - m_uiShadowShock_Timer = 11000; - } else m_uiShadowShock_Timer -= uiDiff; - - //PsychicScream - if (m_uiPsychicScream_Timer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_PSYCHICSCREAM); - - m_uiPsychicScream_Timer = 20000; - } else m_uiPsychicScream_Timer -= uiDiff; - - //DeepSleep - if (m_uiDeepSleep_Timer <= uiDiff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SLEEP); - - m_uiDeepSleep_Timer = 15000; - } else m_uiDeepSleep_Timer -= uiDiff; - - //MindControl - if (m_uiMindControl_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MINDCONTROL); - m_uiMindControl_Timer = 15000; - } else m_uiMindControl_Timer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_dathrohan_balnazzar(Creature* pCreature) -{ - return new boss_dathrohan_balnazzarAI (pCreature); -} - -void AddSC_boss_dathrohan_balnazzar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_dathrohan_balnazzar"; - newscript->GetAI = &GetAI_boss_dathrohan_balnazzar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp deleted file mode 100644 index 89de7dbc207..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Magistrate_Barthilas -SD%Complete: 70 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_DRAININGBLOW 16793 -#define SPELL_CROWDPUMMEL 10887 -#define SPELL_MIGHTYBLOW 14099 -#define SPELL_FURIOUS_ANGER 16791 - -#define MODEL_NORMAL 10433 -#define MODEL_HUMAN 3637 - -struct boss_magistrate_barthilasAI : public ScriptedAI -{ - boss_magistrate_barthilasAI(Creature *c) : ScriptedAI(c) {} - - uint32 DrainingBlow_Timer; - uint32 CrowdPummel_Timer; - uint32 MightyBlow_Timer; - uint32 FuriousAnger_Timer; - uint32 AngerCount; - - void Reset() - { - DrainingBlow_Timer = 20000; - CrowdPummel_Timer = 15000; - MightyBlow_Timer = 10000; - FuriousAnger_Timer = 5000; - AngerCount = 0; - - if (me->isAlive()) - me->SetDisplayId(MODEL_NORMAL); - else - me->SetDisplayId(MODEL_HUMAN); - } - - void MoveInLineOfSight(Unit *who) - { - //nothing to see here yet - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit* /*Killer*/) - { - me->SetDisplayId(MODEL_HUMAN); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (FuriousAnger_Timer <= diff) - { - FuriousAnger_Timer = 4000; - if (AngerCount > 25) - return; - - ++AngerCount; - DoCast(me, SPELL_FURIOUS_ANGER, false); - } else FuriousAnger_Timer -= diff; - - //DrainingBlow - if (DrainingBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DRAININGBLOW); - DrainingBlow_Timer = 15000; - } else DrainingBlow_Timer -= diff; - - //CrowdPummel - if (CrowdPummel_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CROWDPUMMEL); - CrowdPummel_Timer = 15000; - } else CrowdPummel_Timer -= diff; - - //MightyBlow - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTYBLOW); - MightyBlow_Timer = 20000; - } else MightyBlow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_magistrate_barthilas(Creature* pCreature) -{ - return new boss_magistrate_barthilasAI (pCreature); -} - -void AddSC_boss_magistrate_barthilas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magistrate_barthilas"; - newscript->GetAI = &GetAI_boss_magistrate_barthilas; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp deleted file mode 100644 index 0c1cf011d5e..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_maleki_the_pallid -SD%Complete: 100 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_FROSTBOLT 17503 -#define SPELL_DRAINLIFE 20743 -#define SPELL_DRAIN_MANA 17243 -#define SPELL_ICETOMB 16869 - -struct boss_maleki_the_pallidAI : public ScriptedAI -{ - boss_maleki_the_pallidAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Frostbolt_Timer; - uint32 IceTomb_Timer; - uint32 DrainLife_Timer; - - void Reset() - { - Frostbolt_Timer = 1000; - IceTomb_Timer = 16000; - DrainLife_Timer = 31000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_PALLID,IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frostbolt - if (Frostbolt_Timer <= diff) - { - if (rand()%100 < 90) - DoCast(me->getVictim(), SPELL_FROSTBOLT); - Frostbolt_Timer = 3500; - } else Frostbolt_Timer -= diff; - - //IceTomb - if (IceTomb_Timer <= diff) - { - if (rand()%100 < 65) - DoCast(me->getVictim(), SPELL_ICETOMB); - IceTomb_Timer = 28000; - } else IceTomb_Timer -= diff; - - //DrainLife - if (DrainLife_Timer <= diff) - { - if (rand()%100 < 55) - DoCast(me->getVictim(), SPELL_DRAINLIFE); - DrainLife_Timer = 31000; - } else DrainLife_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_maleki_the_pallid(Creature* pCreature) -{ - return new boss_maleki_the_pallidAI (pCreature); -} - -void AddSC_boss_maleki_the_pallid() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_maleki_the_pallid"; - newscript->GetAI = &GetAI_boss_maleki_the_pallid; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp deleted file mode 100644 index ae7299071f4..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Nerubenkan -SD%Complete: 70 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_ENCASINGWEBS 4962 -#define SPELL_PIERCEARMOR 6016 -#define SPELL_CRYPT_SCARABS 31602 -#define SPELL_RAISEUNDEADSCARAB 17235 - -struct boss_nerubenkanAI : public ScriptedAI -{ - boss_nerubenkanAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 EncasingWebs_Timer; - uint32 PierceArmor_Timer; - uint32 CryptScarabs_Timer; - uint32 RaiseUndeadScarab_Timer; - - void Reset() - { - CryptScarabs_Timer = 3000; - EncasingWebs_Timer = 7000; - PierceArmor_Timer = 19000; - RaiseUndeadScarab_Timer = 3000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_NERUB,IN_PROGRESS); - } - - void RaiseUndeadScarab(Unit* pVictim) - { - if (Creature* pUndeadScarab = DoSpawnCreature(10876, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000)) - if (pUndeadScarab->AI()) - pUndeadScarab->AI()->AttackStart(pVictim); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //EncasingWebs - if (EncasingWebs_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ENCASINGWEBS); - EncasingWebs_Timer = 30000; - } else EncasingWebs_Timer -= diff; - - //PierceArmor - if (PierceArmor_Timer <= diff) - { - if (urand(0,3) < 2) - DoCast(me->getVictim(), SPELL_PIERCEARMOR); - PierceArmor_Timer = 35000; - } else PierceArmor_Timer -= diff; - - //CryptScarabs_Timer - if (CryptScarabs_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CRYPT_SCARABS); - CryptScarabs_Timer = 20000; - } else CryptScarabs_Timer -= diff; - - //RaiseUndeadScarab - if (RaiseUndeadScarab_Timer <= diff) - { - RaiseUndeadScarab(me->getVictim()); - RaiseUndeadScarab_Timer = 16000; - } else RaiseUndeadScarab_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_nerubenkan(Creature* pCreature) -{ - return new boss_nerubenkanAI (pCreature); -} - -void AddSC_boss_nerubenkan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nerubenkan"; - newscript->GetAI = &GetAI_boss_nerubenkan; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp deleted file mode 100644 index 905feb9fffc..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Silver_Hand_Bosses -SD%Complete: 40 -SDComment: Basic script to have support for Horde paladin epic mount (quest 9737). All 5 members of Order of the Silver Hand running this script (least for now) -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -/*##### -# Additional: -# Although this is a working solution, the correct would be in addition to check if Aurius is dead. -# Once player extinguish the eternal flame (cast spell 31497->start event 11206) Aurius should become hostile. -# Once Aurius is defeated, he should be the one summoning the ghosts. -#####*/ - -#define SH_GREGOR 17910 -#define SH_CATHELA 17911 -#define SH_NEMAS 17912 -#define SH_AELMAR 17913 -#define SH_VICAR 17914 -#define SH_QUEST_CREDIT 17915 - -#define SPELL_HOLY_LIGHT 25263 -#define SPELL_DIVINE_SHIELD 13874 - -struct boss_silver_hand_bossesAI : public ScriptedAI -{ - boss_silver_hand_bossesAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 HolyLight_Timer; - uint32 DivineShield_Timer; - - void Reset() - { - HolyLight_Timer = 20000; - DivineShield_Timer = 20000; - - if (pInstance) - { - switch(me->GetEntry()) - { - case SH_AELMAR: - pInstance->SetData(TYPE_SH_AELMAR, 0); - break; - case SH_CATHELA: - pInstance->SetData(TYPE_SH_CATHELA, 0); - break; - case SH_GREGOR: - pInstance->SetData(TYPE_SH_GREGOR, 0); - break; - case SH_NEMAS: - pInstance->SetData(TYPE_SH_NEMAS, 0); - break; - case SH_VICAR: - pInstance->SetData(TYPE_SH_VICAR, 0); - break; - } - } - } - - void EnterCombat(Unit* /*who*/) - { - } - - void JustDied(Unit* Killer) - { - if (pInstance) - { - switch(me->GetEntry()) - { - case SH_AELMAR: - pInstance->SetData(TYPE_SH_AELMAR, 2); - break; - case SH_CATHELA: - pInstance->SetData(TYPE_SH_CATHELA, 2); - break; - case SH_GREGOR: - pInstance->SetData(TYPE_SH_GREGOR, 2); - break; - case SH_NEMAS: - pInstance->SetData(TYPE_SH_NEMAS, 2); - break; - case SH_VICAR: - pInstance->SetData(TYPE_SH_VICAR, 2); - break; - } - if (pInstance->GetData(TYPE_SH_QUEST) && Killer->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(Killer)->KilledMonsterCredit(SH_QUEST_CREDIT,me->GetGUID()); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (HolyLight_Timer <= diff) - { - if (me->GetHealth()*5 < me->GetMaxHealth()) - { - DoCast(me, SPELL_HOLY_LIGHT); - HolyLight_Timer = 20000; - } - } else HolyLight_Timer -= diff; - - if (DivineShield_Timer <= diff) - { - if (me->GetHealth()*20 < me->GetMaxHealth()) - { - DoCast(me, SPELL_DIVINE_SHIELD); - DivineShield_Timer = 40000; - } - } else DivineShield_Timer -= diff; - - DoMeleeAttackIfReady(); - } - -}; -CreatureAI* GetAI_boss_silver_hand_bossesAI(Creature* pCreature) -{ - return new boss_silver_hand_bossesAI (pCreature); -} - -void AddSC_boss_order_of_silver_hand() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_silver_hand_bosses"; - newscript->GetAI = &GetAI_boss_silver_hand_bossesAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp deleted file mode 100644 index c04bae15468..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_postmaster_malown -SD%Complete: 50 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" - -//Spell ID to summon this guy is 24627 "Summon Postmaster Malown" -//He should be spawned along with three other elites once the third postbox has been opened - -#define SAY_MALOWNED "You just got MALOWNED!" - -#define SPELL_WAILINGDEAD 7713 -#define SPELL_BACKHAND 6253 -#define SPELL_CURSEOFWEAKNESS 8552 -#define SPELL_CURSEOFTONGUES 12889 -#define SPELL_CALLOFTHEGRAVE 17831 - -struct boss_postmaster_malownAI : public ScriptedAI -{ - boss_postmaster_malownAI(Creature *c) : ScriptedAI(c) {} - - uint32 WailingDead_Timer; - uint32 Backhand_Timer; - uint32 CurseOfWeakness_Timer; - uint32 CurseOfTongues_Timer; - uint32 CallOfTheGrave_Timer; - bool HasYelled; - - void Reset() - { - WailingDead_Timer = 19000; //lasts 6 sec - Backhand_Timer = 8000; //2 sec stun - CurseOfWeakness_Timer = 20000; //lasts 2 mins - CurseOfTongues_Timer = 22000; - CallOfTheGrave_Timer = 25000; - HasYelled = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //WailingDead - if (WailingDead_Timer <= diff) - { - //Cast - if (rand()%100 < 65) //65% chance to cast - { - DoCast(me->getVictim(), SPELL_WAILINGDEAD); - } - //19 seconds until we should cast this again - WailingDead_Timer = 19000; - } else WailingDead_Timer -= diff; - - //Backhand - if (Backhand_Timer <= diff) - { - //Cast - if (rand()%100 < 45) //45% chance to cast - { - DoCast(me->getVictim(), SPELL_BACKHAND); - } - //8 seconds until we should cast this again - Backhand_Timer = 8000; - } else Backhand_Timer -= diff; - - //CurseOfWeakness - if (CurseOfWeakness_Timer <= diff) - { - //Cast - if (rand()%100 < 3) //3% chance to cast - { - DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); - } - //20 seconds until we should cast this again - CurseOfWeakness_Timer = 20000; - } else CurseOfWeakness_Timer -= diff; - - //CurseOfTongues - if (CurseOfTongues_Timer <= diff) - { - //Cast - if (rand()%100 < 3) //3% chance to cast - { - DoCast(me->getVictim(), SPELL_CURSEOFTONGUES); - } - //22 seconds until we should cast this again - CurseOfTongues_Timer = 22000; - } else CurseOfTongues_Timer -= diff; - - //CallOfTheGrave - if (CallOfTheGrave_Timer <= diff) - { - //Cast - if (rand()%100 < 5) //5% chance to cast - { - DoCast(me->getVictim(), SPELL_CALLOFTHEGRAVE); - } - //25 seconds until we should cast this again - CallOfTheGrave_Timer = 25000; - } else CallOfTheGrave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_postmaster_malown(Creature* pCreature) -{ - return new boss_postmaster_malownAI (pCreature); -} - -void AddSC_boss_postmaster_malown() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_postmaster_malown"; - newscript->GetAI = &GetAI_boss_postmaster_malown; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp deleted file mode 100644 index 3a3ae60c9c9..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Ramstein_The_Gorger -SD%Complete: 70 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_TRAMPLE 5568 -#define SPELL_KNOCKOUT 17307 - - #define C_MINDLESS_UNDEAD 11030 - -struct boss_ramstein_the_gorgerAI : public ScriptedAI -{ - boss_ramstein_the_gorgerAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Trample_Timer; - uint32 Knockout_Timer; - - void Reset() - { - Trample_Timer = 3000; - Knockout_Timer = 12000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - for (uint8 i = 0; i < 30; ++i) - { - if (Creature* mob = me->SummonCreature(C_MINDLESS_UNDEAD,3969.35+irand(-10,10),-3391.87+irand(-10,10),119.11,5.91,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000)) - mob->AI()->AttackStart(me->SelectNearestTarget(500)); - } - - if (pInstance) - pInstance->SetData(TYPE_RAMSTEIN,DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Trample - if (Trample_Timer <= diff) - { - DoCast(me, SPELL_TRAMPLE); - Trample_Timer = 7000; - } else Trample_Timer -= diff; - - //Knockout - if (Knockout_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKOUT); - Knockout_Timer = 10000; - } else Knockout_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ramstein_the_gorger(Creature* pCreature) -{ - return new boss_ramstein_the_gorgerAI (pCreature); -} - -void AddSC_boss_ramstein_the_gorger() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ramstein_the_gorger"; - newscript->GetAI = &GetAI_boss_ramstein_the_gorger; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp b/src/server/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp deleted file mode 100644 index f15eb59ba47..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_timmy_the_cruel -SD%Complete: 100 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_SPAWN "TIMMY!" - -#define SPELL_RAVENOUSCLAW 17470 - -struct boss_timmy_the_cruelAI : public ScriptedAI -{ - boss_timmy_the_cruelAI(Creature *c) : ScriptedAI(c) {} - - uint32 RavenousClaw_Timer; - bool HasYelled; - - void Reset() - { - RavenousClaw_Timer = 10000; - HasYelled = false; - } - - void EnterCombat(Unit * /*who*/) - { - if (!HasYelled) - { - me->MonsterYell(SAY_SPAWN,LANG_UNIVERSAL,NULL); - HasYelled = true; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //RavenousClaw - if (RavenousClaw_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_RAVENOUSCLAW); - //15 seconds until we should cast this again - RavenousClaw_Timer = 15000; - } else RavenousClaw_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_timmy_the_cruel(Creature* pCreature) -{ - return new boss_timmy_the_cruelAI (pCreature); -} - -void AddSC_boss_timmy_the_cruel() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_timmy_the_cruel"; - newscript->GetAI = &GetAI_boss_timmy_the_cruel; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp b/src/server/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp deleted file mode 100644 index ffeaa070a26..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: instance_stratholme -SD%Complete: 50 -SDComment: In progress. Undead side 75% implemented. Save/load not implemented. -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define GO_SERVICE_ENTRANCE 175368 -#define GO_GAUNTLET_GATE1 175357 -#define GO_ZIGGURAT1 175380 //baroness -#define GO_ZIGGURAT2 175379 //nerub'enkan -#define GO_ZIGGURAT3 175381 //maleki -#define GO_ZIGGURAT4 175405 //rammstein -#define GO_ZIGGURAT5 175796 //baron -#define GO_PORT_GAUNTLET 175374 //port from gauntlet to slaugther -#define GO_PORT_SLAUGTHER 175373 //port at slaugther -#define GO_PORT_ELDERS 175377 //port at elders square - -#define C_CRYSTAL 10415 //three ziggurat crystals -#define C_BARON 10440 -#define C_YSIDA_TRIGGER 16100 - -#define C_RAMSTEIN 10439 -#define C_ABOM_BILE 10416 -#define C_ABOM_VENOM 10417 -#define C_BLACK_GUARD 10394 -#define C_YSIDA 16031 - -#define MAX_ENCOUNTER 6 - -struct instance_stratholme : public ScriptedInstance -{ - instance_stratholme(Map* pMap) : ScriptedInstance(pMap) {} - - uint32 Encounter[MAX_ENCOUNTER]; - - bool IsSilverHandDead[5]; - - uint32 BaronRun_Timer; - uint32 SlaugtherSquare_Timer; - - uint64 serviceEntranceGUID; - uint64 gauntletGate1GUID; - uint64 ziggurat1GUID; - uint64 ziggurat2GUID; - uint64 ziggurat3GUID; - uint64 ziggurat4GUID; - uint64 ziggurat5GUID; - uint64 portGauntletGUID; - uint64 portSlaugtherGUID; - uint64 portElderGUID; - - uint64 baronGUID; - uint64 ysidaTriggerGUID; - std::set crystalsGUID; - std::set abomnationGUID; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - Encounter[i] = NOT_STARTED; - - for (uint8 i = 0; i < 5; ++i) - IsSilverHandDead[i] = false; - - BaronRun_Timer = 0; - SlaugtherSquare_Timer = 0; - - serviceEntranceGUID = 0; - gauntletGate1GUID = 0; - ziggurat1GUID = 0; - ziggurat2GUID = 0; - ziggurat3GUID = 0; - ziggurat4GUID = 0; - ziggurat5GUID = 0; - portGauntletGUID = 0; - portSlaugtherGUID = 0; - portElderGUID = 0; - - baronGUID = 0; - ysidaTriggerGUID = 0; - crystalsGUID.clear(); - abomnationGUID.clear(); - } - - bool StartSlaugtherSquare() - { - //change to DONE when crystals implemented - if (Encounter[1] == IN_PROGRESS && Encounter[2] == IN_PROGRESS && Encounter[3] == IN_PROGRESS) - { - HandleGameObject(portGauntletGUID, true); - HandleGameObject(portSlaugtherGUID, true); - return true; - } - - debug_log("TSCR: Instance Stratholme: Cannot open slaugther square yet."); - return false; - } - - //if withRestoreTime true, then newState will be ignored and GO should be restored to original state after 10 seconds - void UpdateGoState(uint64 goGuid, uint32 newState, bool withRestoreTime) - { - if (!goGuid) - return; - - if (GameObject* pGo = instance->GetGameObject(goGuid)) - { - if (withRestoreTime) - pGo->UseDoorOrButton(10); - else - pGo->SetGoState((GOState)newState); - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case C_BARON: baronGUID = pCreature->GetGUID(); break; - case C_YSIDA_TRIGGER: ysidaTriggerGUID = pCreature->GetGUID(); break; - case C_CRYSTAL: crystalsGUID.insert(pCreature->GetGUID()); break; - case C_ABOM_BILE: - case C_ABOM_VENOM: abomnationGUID.insert(pCreature->GetGUID()); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_SERVICE_ENTRANCE: - serviceEntranceGUID = pGo->GetGUID(); - break; - case GO_GAUNTLET_GATE1: - //weird, but unless flag is set, client will not respond as expected. DB bug? - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_LOCKED); - gauntletGate1GUID = pGo->GetGUID(); - break; - case GO_ZIGGURAT1: - ziggurat1GUID = pGo->GetGUID(); - if (GetData(TYPE_BARONESS) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_ZIGGURAT2: - ziggurat2GUID = pGo->GetGUID(); - if (GetData(TYPE_NERUB) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_ZIGGURAT3: - ziggurat3GUID = pGo->GetGUID(); - if (GetData(TYPE_PALLID) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_ZIGGURAT4: - ziggurat4GUID = pGo->GetGUID(); - if (GetData(TYPE_BARON) == DONE || GetData(TYPE_RAMSTEIN) == DONE) - HandleGameObject(0, true, pGo); - break; - case GO_ZIGGURAT5: - ziggurat5GUID = pGo->GetGUID(); - if (GetData(TYPE_BARON) == DONE || GetData(TYPE_RAMSTEIN) == DONE) - HandleGameObject(0, true, pGo); - break; - case GO_PORT_GAUNTLET: - portGauntletGUID = pGo->GetGUID(); - if (GetData(TYPE_BARONESS) == IN_PROGRESS && GetData(TYPE_NERUB) == IN_PROGRESS && GetData(TYPE_PALLID) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_PORT_SLAUGTHER: - portSlaugtherGUID = pGo->GetGUID(); - if (GetData(TYPE_BARONESS) == IN_PROGRESS && GetData(TYPE_NERUB) == IN_PROGRESS && GetData(TYPE_PALLID) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_PORT_ELDERS: - portElderGUID = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_BARON_RUN: - switch(data) - { - case IN_PROGRESS: - if (Encounter[0] == IN_PROGRESS || Encounter[0] == FAIL) - break; - Encounter[0] = data; - BaronRun_Timer = 2700000; - debug_log("TSCR: Instance Stratholme: Baron run in progress."); - break; - case FAIL: - //may add code to remove aura from players, but in theory the time should be up already and removed. - Encounter[0] = data; - break; - case DONE: - Encounter[0] = data; - if (Creature* pYsidaT = instance->GetCreature(ysidaTriggerGUID)) - pYsidaT->SummonCreature(C_YSIDA, - pYsidaT->GetPositionX(),pYsidaT->GetPositionY(),pYsidaT->GetPositionZ(),pYsidaT->GetOrientation(), - TEMPSUMMON_TIMED_DESPAWN,1800000); - BaronRun_Timer = 0; - break; - } - break; - case TYPE_BARONESS: - Encounter[1] = data; - if (data == IN_PROGRESS) - HandleGameObject(ziggurat1GUID, true); - if (data == IN_PROGRESS) //change to DONE when crystals implemented - StartSlaugtherSquare(); - break; - case TYPE_NERUB: - Encounter[2] = data; - if (data == IN_PROGRESS) - HandleGameObject(ziggurat2GUID, true); - if (data == IN_PROGRESS) //change to DONE when crystals implemented - StartSlaugtherSquare(); - break; - case TYPE_PALLID: - Encounter[3] = data; - if (data == IN_PROGRESS) - HandleGameObject(ziggurat3GUID, true); - if (data == IN_PROGRESS) //change to DONE when crystals implemented - StartSlaugtherSquare(); - break; - case TYPE_RAMSTEIN: - if (data == IN_PROGRESS) - { - HandleGameObject(portGauntletGUID, false); - - uint32 count = abomnationGUID.size(); - for (std::set::const_iterator i = abomnationGUID.begin(); i != abomnationGUID.end(); ++i) - { - if (Creature* pAbom = instance->GetCreature(*i)) - { - if (!pAbom->isAlive()) - --count; - } - } - - if (!count) - { - //a bit itchy, it should close the door after 10 secs, but it doesn't. skipping it for now. - //UpdateGoState(ziggurat4GUID,0,true); - if (Creature* pBaron = instance->GetCreature(baronGUID)) - pBaron->SummonCreature(C_RAMSTEIN,4032.84,-3390.24,119.73,4.71,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000); - debug_log("TSCR: Instance Stratholme: Ramstein spawned."); - } - else - debug_log("TSCR: Instance Stratholme: %u Abomnation left to kill.",count); - } - - if (data == NOT_STARTED) - HandleGameObject(portGauntletGUID, true); - - if (data == DONE) - { - SlaugtherSquare_Timer = 300000; - debug_log("TSCR: Instance Stratholme: Slaugther event will continue in 5 minutes."); - } - Encounter[4] = data; - break; - case TYPE_BARON: - if (data == IN_PROGRESS) - { - HandleGameObject(ziggurat4GUID, false); - HandleGameObject(ziggurat5GUID, false); - if (GetData(TYPE_BARON_RUN) == IN_PROGRESS) - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - { - if (pPlayer->HasAura(SPELL_BARON_ULTIMATUM)) - pPlayer->RemoveAurasDueToSpell(SPELL_BARON_ULTIMATUM); - - if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_DEAD_MAN_PLEA); - } - } - } - - SetData(TYPE_BARON_RUN,DONE); - } - } - if (data == DONE || data == NOT_STARTED) - { - HandleGameObject(ziggurat4GUID, true); - HandleGameObject(ziggurat5GUID, true); - } - if (data == DONE) - HandleGameObject(portGauntletGUID, true); - Encounter[5] = data; - break; - case TYPE_SH_AELMAR: - IsSilverHandDead[0] = (data) ? true : false; - break; - case TYPE_SH_CATHELA: - IsSilverHandDead[1] = (data) ? true : false; - break; - case TYPE_SH_GREGOR: - IsSilverHandDead[2] = (data) ? true : false; - break; - case TYPE_SH_NEMAS: - IsSilverHandDead[3] = (data) ? true : false; - break; - case TYPE_SH_VICAR: - IsSilverHandDead[4] = (data) ? true : false; - break; - } - if (data == DONE)SaveToDB(); - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << Encounter[0] << " " << Encounter[1] << " " << Encounter[2] << " " - << Encounter[3] << " " << Encounter[4] << " " << Encounter[5]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> Encounter[0] >> Encounter[1] >> Encounter[2] >> Encounter[3] - >> Encounter[4] >> Encounter[5]; - - // Do not reset 1, 2 and 3. they are not set to done, yet . - if (Encounter[0] == IN_PROGRESS) - Encounter[0] = NOT_STARTED; - if (Encounter[4] == IN_PROGRESS) - Encounter[4] = NOT_STARTED; - if (Encounter[5] == IN_PROGRESS) - Encounter[5] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_SH_QUEST: - if (IsSilverHandDead[0] && IsSilverHandDead[1] && IsSilverHandDead[2] && IsSilverHandDead[3] && IsSilverHandDead[4]) - return 1; - return 0; - case TYPE_BARON_RUN: - return Encounter[0]; - case TYPE_BARONESS: - return Encounter[1]; - case TYPE_NERUB: - return Encounter[2]; - case TYPE_PALLID: - return Encounter[3]; - case TYPE_RAMSTEIN: - return Encounter[4]; - case TYPE_BARON: - return Encounter[5]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_BARON: - return baronGUID; - case DATA_YSIDA_TRIGGER: - return ysidaTriggerGUID; - } - return 0; - } - - void Update(uint32 diff) - { - if (BaronRun_Timer) - { - if (BaronRun_Timer <= diff) - { - if (GetData(TYPE_BARON_RUN) != DONE) - SetData(TYPE_BARON_RUN, FAIL); - BaronRun_Timer = 0; - debug_log("TSCR: Instance Stratholme: Baron run event reached end. Event has state %u.",GetData(TYPE_BARON_RUN)); - } else BaronRun_Timer -= diff; - } - - if (SlaugtherSquare_Timer) - { - if (SlaugtherSquare_Timer <= diff) - { - if (Creature* pBaron = instance->GetCreature(baronGUID)) - { - for (uint8 i = 0; i < 4; ++i) - pBaron->SummonCreature(C_BLACK_GUARD,4032.84,-3390.24,119.73,4.71,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000); - - HandleGameObject(ziggurat4GUID, true); - HandleGameObject(ziggurat5GUID, true); - debug_log("TSCR: Instance Stratholme: Black guard sentries spawned. Opening gates to baron."); - } - SlaugtherSquare_Timer = 0; - } else SlaugtherSquare_Timer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_stratholme(Map* pMap) -{ - return new instance_stratholme(pMap); -} - -void AddSC_instance_stratholme() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_stratholme"; - newscript->GetInstanceData = &GetInstanceData_instance_stratholme; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/stratholme.cpp b/src/server/scripts/eastern_kingdoms/stratholme/stratholme.cpp deleted file mode 100644 index 035fca68b95..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/stratholme.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Stratholme -SD%Complete: 100 -SDComment: Misc mobs for instance. pGo-script to apply aura and start event for quest 8945 -SDCategory: Stratholme -EndScriptData */ - -/* ContentData -go_gauntlet_gate -mob_freed_soul -mob_restless_soul -mobs_spectral_ghostly_citizen -EndContentData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -/*###### -## go_gauntlet_gate (this is the _first_ of the gauntlet gates, two exist) -######*/ - -bool GOHello_go_gauntlet_gate(Player* pPlayer, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - - if (!pInstance) - return false; - - if (pInstance->GetData(TYPE_BARON_RUN) != NOT_STARTED) - return false; - - if (Group *pGroup = pPlayer->GetGroup()) - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* pGroupie = itr->getSource(); - if (!pGroupie) - continue; - - if (pGroupie->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && - !pGroupie->HasAura(SPELL_BARON_ULTIMATUM) && - pGroupie->GetMap() == pGo->GetMap()) - pGroupie->CastSpell(pGroupie,SPELL_BARON_ULTIMATUM,true); - } - } else if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && - !pPlayer->HasAura(SPELL_BARON_ULTIMATUM) && - pPlayer->GetMap() == pGo->GetMap()) - pPlayer->CastSpell(pPlayer,SPELL_BARON_ULTIMATUM,true); - - pInstance->SetData(TYPE_BARON_RUN,IN_PROGRESS); - return false; -} - -/*###### -## mob_freed_soul -######*/ - -//Possibly more of these quotes around. -#define SAY_ZAPPED0 -1329000 -#define SAY_ZAPPED1 -1329001 -#define SAY_ZAPPED2 -1329002 -#define SAY_ZAPPED3 -1329003 - -struct mob_freed_soulAI : public ScriptedAI -{ - mob_freed_soulAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - DoScriptText(RAND(SAY_ZAPPED0,SAY_ZAPPED1,SAY_ZAPPED2,SAY_ZAPPED3), me); - } - - void EnterCombat(Unit* /*who*/) {} -}; - -CreatureAI* GetAI_mob_freed_soul(Creature* pCreature) -{ - return new mob_freed_soulAI (pCreature); -} - -/*###### -## mob_restless_soul -######*/ - -#define SPELL_EGAN_BLASTER 17368 -#define SPELL_SOUL_FREED 17370 -#define QUEST_RESTLESS_SOUL 5282 -#define ENTRY_RESTLESS 11122 -#define ENTRY_FREED 11136 - -struct mob_restless_soulAI : public ScriptedAI -{ - mob_restless_soulAI(Creature *c) : ScriptedAI(c) {} - - uint64 Tagger; - uint32 Die_Timer; - bool Tagged; - - void Reset() - { - Tagger = 0; - Die_Timer = 5000; - Tagged = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - if (!Tagged && spell->Id == SPELL_EGAN_BLASTER && CAST_PLR(caster)->GetQuestStatus(QUEST_RESTLESS_SOUL) == QUEST_STATUS_INCOMPLETE) - { - Tagged = true; - Tagger = caster->GetGUID(); - } - } - } - - void JustSummoned(Creature *summoned) - { - summoned->CastSpell(summoned,SPELL_SOUL_FREED,false); - } - - void JustDied(Unit* /*Killer*/) - { - if (Tagged) - me->SummonCreature(ENTRY_FREED, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 300000); - } - - void UpdateAI(const uint32 diff) - { - if (Tagged) - { - if (Die_Timer <= diff) - { - if (Unit* pTemp = Unit::GetUnit(*me,Tagger)) - { - CAST_PLR(pTemp)->KilledMonsterCredit(ENTRY_RESTLESS, me->GetGUID()); - me->Kill(me); - } - } else Die_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_mob_restless_soul(Creature* pCreature) -{ - return new mob_restless_soulAI (pCreature); -} - -/*###### -## mobs_spectral_ghostly_citizen -######*/ - -enum eGhostlyCitizenSpells -{ - SPELL_HAUNTING_PHANTOM = 16336, - SPELL_SLAP = 6754 -}; - -struct mobs_spectral_ghostly_citizenAI : public ScriptedAI -{ - mobs_spectral_ghostly_citizenAI(Creature *c) : ScriptedAI(c) {} - - uint32 Die_Timer; - bool Tagged; - - void Reset() - { - Die_Timer = 5000; - Tagged = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (!Tagged && spell->Id == SPELL_EGAN_BLASTER) - Tagged = true; - } - - void JustDied(Unit* /*Killer*/) - { - if (Tagged) - { - for (uint32 i = 1; i <= 4; ++i) - { - //100%, 50%, 33%, 25% chance to spawn - if (urand(1,i) == 1) - DoSummon(ENTRY_RESTLESS, me, 20.0f, 600000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Tagged) - { - if (Die_Timer <= diff) - me->Kill(me); - else Die_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void ReceiveEmote(Player* pPlayer, uint32 emote) - { - switch(emote) - { - case TEXTEMOTE_DANCE: - EnterEvadeMode(); - break; - case TEXTEMOTE_RUDE: - if (me->IsWithinDistInMap(pPlayer, 5)) - DoCast(pPlayer, SPELL_SLAP, false); - else - me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE); - break; - case TEXTEMOTE_WAVE: - me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); - break; - case TEXTEMOTE_BOW: - me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); - break; - case TEXTEMOTE_KISS: - me->HandleEmoteCommand(EMOTE_ONESHOT_FLEX); - break; - } - } -}; - -CreatureAI* GetAI_mobs_spectral_ghostly_citizen(Creature* pCreature) -{ - return new mobs_spectral_ghostly_citizenAI (pCreature); -} - -void AddSC_stratholme() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_gauntlet_gate"; - newscript->pGOHello = &GOHello_go_gauntlet_gate; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_freed_soul"; - newscript->GetAI = &GetAI_mob_freed_soul; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_restless_soul"; - newscript->GetAI = &GetAI_mob_restless_soul; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mobs_spectral_ghostly_citizen"; - newscript->GetAI = &GetAI_mobs_spectral_ghostly_citizen; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/stratholme/stratholme.h b/src/server/scripts/eastern_kingdoms/stratholme/stratholme.h deleted file mode 100644 index b9246091a7c..00000000000 --- a/src/server/scripts/eastern_kingdoms/stratholme/stratholme.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_STRATHOLME_H -#define DEF_STRATHOLME_H - -#define TYPE_BARON_RUN 1 -#define TYPE_BARONESS 2 -#define TYPE_NERUB 3 -#define TYPE_PALLID 4 -#define TYPE_RAMSTEIN 5 -#define TYPE_BARON 6 - -#define DATA_BARON 10 -#define DATA_YSIDA_TRIGGER 11 - -#define TYPE_SH_QUEST 20 -#define TYPE_SH_CATHELA 21 -#define TYPE_SH_GREGOR 22 -#define TYPE_SH_NEMAS 23 -#define TYPE_SH_VICAR 24 -#define TYPE_SH_AELMAR 25 - -#define QUEST_DEAD_MAN_PLEA 8945 -#define SPELL_BARON_ULTIMATUM 27861 -#endif - diff --git a/src/server/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp b/src/server/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp deleted file mode 100644 index 6fe65cf963d..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (C) 2006 - 2009 kb_z - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Sunken_Temple -SD%Complete: 100 -SDComment:Place Holder -SDCategory: Sunken Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunken_temple.h" - -#define GO_ATALAI_STATUE1 148830 -#define GO_ATALAI_STATUE2 148831 -#define GO_ATALAI_STATUE3 148832 -#define GO_ATALAI_STATUE4 148833 -#define GO_ATALAI_STATUE5 148834 -#define GO_ATALAI_STATUE6 148835 -#define GO_ATALAI_IDOL 148836 - -#define GO_ATALAI_LIGHT1 148883 -#define GO_ATALAI_LIGHT2 148937 - -#define NPC_MALFURION_STORMRAGE 15362 - -struct instance_sunken_temple : public ScriptedInstance -{ - instance_sunken_temple(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - }; - - uint64 GOAtalaiStatue1; - uint64 GOAtalaiStatue2; - uint64 GOAtalaiStatue3; - uint64 GOAtalaiStatue4; - uint64 GOAtalaiStatue5; - uint64 GOAtalaiStatue6; - uint64 GOAtalaiIdol; - - uint32 State; - - bool s1; - bool s2; - bool s3; - bool s4; - bool s5; - bool s6; - - void Initialize() - { - GOAtalaiStatue1 = 0; - GOAtalaiStatue2 = 0; - GOAtalaiStatue3 = 0; - GOAtalaiStatue4 = 0; - GOAtalaiStatue5 = 0; - GOAtalaiStatue6 = 0; - GOAtalaiIdol = 0; - - State = 0; - - s1 = false; - s2 = false; - s3 = false; - s4 = false; - s5 = false; - s6 = false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_ATALAI_STATUE1: GOAtalaiStatue1 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE2: GOAtalaiStatue2 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE3: GOAtalaiStatue3 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE4: GOAtalaiStatue4 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE5: GOAtalaiStatue5 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE6: GOAtalaiStatue6 = pGo->GetGUID(); break; - case GO_ATALAI_IDOL: GOAtalaiIdol = pGo->GetGUID(); break; - } - } - - virtual void Update(uint32 /*diff*/) // correct order goes form 1-6 - { - switch(State) - { - case GO_ATALAI_STATUE1: - if (!s1 && !s2 && !s3 && !s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue1 = instance->GetGameObject(GOAtalaiStatue1)) - UseStatue(pAtalaiStatue1); - s1 = true; - State = 0; - }; - break; - case GO_ATALAI_STATUE2: - if (s1 && !s2 && !s3 && !s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue2 = instance->GetGameObject(GOAtalaiStatue2)) - UseStatue(pAtalaiStatue2); - s2 = true; - State = 0; - }; - break; - case GO_ATALAI_STATUE3: - if (s1 && s2 && !s3 && !s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue3 = instance->GetGameObject(GOAtalaiStatue3)) - UseStatue(pAtalaiStatue3); - s3 = true; - State = 0; - }; - break; - case GO_ATALAI_STATUE4: - if (s1 && s2 && s3 && !s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue4 = instance->GetGameObject(GOAtalaiStatue4)) - UseStatue(pAtalaiStatue4); - s4 = true; - State = 0; - } - break; - case GO_ATALAI_STATUE5: - if (s1 && s2 && s3 && s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue5 = instance->GetGameObject(GOAtalaiStatue5)) - UseStatue(pAtalaiStatue5); - s5 = true; - State = 0; - } - break; - case GO_ATALAI_STATUE6: - if (s1 && s2 && s3 && s4 && s5 && !s6) - { - if (GameObject *pAtalaiStatue6 = instance->GetGameObject(GOAtalaiStatue6)) - UseStatue(pAtalaiStatue6); - s6 = true; - State = 0; - } - break; - } - }; - - void UseStatue(GameObject* pGo) - { - pGo->SummonGameObject(GO_ATALAI_LIGHT1,pGo->GetPositionX(),pGo->GetPositionY(),pGo->GetPositionZ(),0,0,0,0,0,0); - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 4); - } - - /* - void UseLastStatue(GameObject* pGo) - { - AtalaiStatue1->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue1->GetPositionX(),AtalaiStatue1->GetPositionY(),AtalaiStatue1->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue2->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue2->GetPositionX(),AtalaiStatue2->GetPositionY(),AtalaiStatue2->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue3->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue3->GetPositionX(),AtalaiStatue3->GetPositionY(),AtalaiStatue3->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue4->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue4->GetPositionX(),AtalaiStatue4->GetPositionY(),AtalaiStatue4->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue5->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue5->GetPositionX(),AtalaiStatue5->GetPositionY(),AtalaiStatue5->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue6->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue6->GetPositionX(),AtalaiStatue6->GetPositionY(),AtalaiStatue6->GetPositionZ(),0,0,0,0,0,100000); - pGo->SummonGameObject(148838,-488.997,96.61,-189.019,-1.52,0,0,0,0,100000); - } - */ - - void SetData(uint32 type, uint32 data) - { - if (type == EVENT_STATE) - State = data; - } - - uint32 GetData(uint32 type) - { - if (type == EVENT_STATE) - return State; - return 0; - } -}; - -InstanceData* GetInstanceData_instance_sunken_temple(Map* pMap) -{ - return new instance_sunken_temple(pMap); -} - -void AddSC_instance_sunken_temple() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_sunken_temple"; - newscript->GetInstanceData = &GetInstanceData_instance_sunken_temple; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp b/src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp deleted file mode 100644 index 7f0ca126d78..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2006 - 2009 kb_z - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Sunken_Temple -SD%Complete: 100 -SDComment: Area Trigger + Puzzle event support -SDCategory: Sunken Temple -EndScriptData */ - -/* ContentData -at_malfurion_Stormrage_trigger -EndContentData */ - -#include "ScriptedPch.h" -#include "sunken_temple.h" - -/*##### -# at_malfurion_Stormrage_trigger -#####*/ - -bool AreaTrigger_at_malfurion_stormrage(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - if (ScriptedInstance* pInstance = pPlayer->GetInstanceData()) - { - if (!pPlayer->FindNearestCreature(15362,15)) - pPlayer->SummonCreature(15362, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), -1.52, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 100000); - return false; - } -return false; -} -/*##### -# go_atalai_statue -#####*/ - -bool GOHello_go_atalai_statue(Player* pPlayer, GameObject* pGo) -{ - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (!pInstance) - return false; - pInstance->SetData(EVENT_STATE,pGo->GetEntry()); - return false; -} - -void AddSC_sunken_temple() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "at_malfurion_stormrage"; - newscript->pAreaTrigger = &AreaTrigger_at_malfurion_stormrage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_atalai_statue"; - newscript->pGOHello = &GOHello_go_atalai_statue; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h b/src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h deleted file mode 100644 index 82245095c31..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2006 - 2009 kb_z - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SUNKEN_TEMPLE_H -#define DEF_SUNKEN_TEMPLE_H - -#define TROLLBOSS1_DEATH 1 -#define TROLLBOSS2_DEATH 2 -#define TROLLBOSS3_DEATH 3 -#define TROLLBOSS4_DEATH 4 -#define TROLLBOSS5_DEATH 5 -#define TROLLBOSS6_DEATH 6 -#define JAMMALAN_DEATH 7 -#define MORPHAZ_DEATH 8 -#define HAZZAS_DEATH 9 -#define ERANIKUS_DEATH 10 -#define ATALALARION_DEATH 11 //optional - -#define EVENT_STATE 1 -#endif - diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp b/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp deleted file mode 100644 index 59e58d6df1a..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Brutallus -SD%Complete: 80 -SDComment: Find a way to start the intro, best code for the intro -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -enum Quotes -{ - YELL_INTRO = -1580017, - YELL_INTRO_BREAK_ICE = -1580018, - YELL_INTRO_CHARGE = -1580019, - YELL_INTRO_KILL_MADRIGOSA = -1580020, - YELL_INTRO_TAUNT = -1580021, - - YELL_MADR_ICE_BARRIER = -1580031, - YELL_MADR_INTRO = -1580032, - YELL_MADR_ICE_BLOCK = -1580033, - YELL_MADR_TRAP = -1580034, - YELL_MADR_DEATH = -1580035, - - YELL_AGGRO = -1580022, - YELL_KILL1 = -1580023, - YELL_KILL2 = -1580024, - YELL_KILL3 = -1580025, - YELL_LOVE1 = -1580026, - YELL_LOVE2 = -1580027, - YELL_LOVE3 = -1580028, - YELL_BERSERK = -1580029, - YELL_DEATH = -1580030 -}; - -enum Spells -{ - SPELL_METEOR_SLASH = 45150, - SPELL_BURN = 46394, - SPELL_STOMP = 45185, - SPELL_BERSERK = 26662, - SPELL_DUAL_WIELD = 42459, - - SPELL_INTRO_FROST_BLAST = 45203, - SPELL_INTRO_FROSTBOLT = 44843, - SPELL_INTRO_ENCAPSULATE = 45665, - SPELL_INTRO_ENCAPSULATE_CHANELLING = 45661 -}; - -#define FELMYST 25038 - -struct boss_brutallusAI : public ScriptedAI -{ - boss_brutallusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = true; - } - - ScriptedInstance* pInstance; - - uint32 SlashTimer; - uint32 BurnTimer; - uint32 StompTimer; - uint32 BerserkTimer; - - uint32 IntroPhase; - uint32 IntroPhaseTimer; - uint32 IntroFrostBoltTimer; - - bool Intro; - bool IsIntro; - bool Enraged; - - void Reset() - { - SlashTimer = 11000; - StompTimer = 30000; - BurnTimer = 60000; - BerserkTimer = 360000; - - IntroPhase = 0; - IntroPhaseTimer = 0; - IntroFrostBoltTimer = 0; - - IsIntro = false; - Enraged = false; - - DoCast(me, SPELL_DUAL_WIELD, true); - - if (pInstance) - pInstance->SetData(DATA_BRUTALLUS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_BRUTALLUS_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(YELL_KILL1,YELL_KILL2,YELL_KILL3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(YELL_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_BRUTALLUS_EVENT, DONE); - float x,y,z; - me->GetPosition(x,y,z); - me->SummonCreature(FELMYST, x,y, z+30, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0); - } - } - - void EnterEvadeMode() - { - if (!Intro) - ScriptedAI::EnterEvadeMode(); - } - - void StartIntro() - { - if (!Intro || IsIntro) - return; - error_log("Start Intro"); - Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0); - if (Madrigosa) - { - Madrigosa->Respawn(); - Madrigosa->setActive(true); - IsIntro = true; - Madrigosa->SetMaxHealth(me->GetMaxHealth()); - Madrigosa->SetHealth(me->GetMaxHealth()); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->Attack(Madrigosa, true); - Madrigosa->Attack(me, true); - }else - { - //Madrigosa not found, end intro - error_log("Madrigosa was not found"); - EndIntro(); - } - } - - void EndIntro() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Intro = false; - IsIntro = false; - error_log("End Intro"); - } - - void AttackStart(Unit* pWho) - { - if (!pWho || Intro || IsIntro) - return; - ScriptedAI::AttackStart(pWho); - } - - void DoIntro() - { - Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0); - if (!Madrigosa) - return; - - switch (IntroPhase) - { - case 0: - DoScriptText(YELL_MADR_ICE_BARRIER, Madrigosa); - IntroPhaseTimer = 7000; - ++IntroPhase; - break; - case 1: - me->SetInFront(Madrigosa); - Madrigosa->SetInFront(me); - DoScriptText(YELL_MADR_INTRO, Madrigosa, me); - IntroPhaseTimer = 9000; - ++IntroPhase; - break; - case 2: - DoScriptText(YELL_INTRO, me, Madrigosa); - IntroPhaseTimer = 13000; - ++IntroPhase; - break; - case 3: - DoCast(me, SPELL_INTRO_FROST_BLAST); - Madrigosa->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->AttackStop(); - Madrigosa->AttackStop(); - IntroFrostBoltTimer = 3000; - IntroPhaseTimer = 28000; - ++IntroPhase; - break; - case 4: - DoScriptText(YELL_INTRO_BREAK_ICE, me); - IntroPhaseTimer = 6000; - ++IntroPhase; - break; - case 5: - Madrigosa->CastSpell(me, SPELL_INTRO_ENCAPSULATE_CHANELLING, false); - DoScriptText(YELL_MADR_TRAP, Madrigosa); - DoCast(me, SPELL_INTRO_ENCAPSULATE); - IntroPhaseTimer = 11000; - ++IntroPhase; - break; - case 6: - DoScriptText(YELL_INTRO_CHARGE, me); - IntroPhaseTimer = 5000; - ++IntroPhase; - break; - case 7: - me->Kill(Madrigosa); - DoScriptText(YELL_MADR_DEATH, Madrigosa); - me->SetHealth(me->GetMaxHealth()); - me->AttackStop(); - IntroPhaseTimer = 4000; - ++IntroPhase; - break; - case 8: - DoScriptText(YELL_INTRO_KILL_MADRIGOSA, me); - me->SetOrientation(0.14f); - me->StopMoving(); - Madrigosa->setDeathState(CORPSE); - IntroPhaseTimer = 8000; - ++IntroPhase; - break; - case 9: - DoScriptText(YELL_INTRO_TAUNT, me); - IntroPhaseTimer = 5000; - ++IntroPhase; - break; - case 10: - EndIntro(); - break; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!who->isTargetableForAttack() || !me->IsHostileTo(who)) - return; - if (pInstance && Intro) - pInstance->SetData(DATA_BRUTALLUS_EVENT, SPECIAL); - - if (Intro && !IsIntro) - StartIntro(); - if (!Intro) - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - if (IsIntro) - { - if (IntroPhaseTimer <= diff) - DoIntro(); - else IntroPhaseTimer -= diff; - - if (IntroPhase == 3 + 1) - { - if (IntroFrostBoltTimer <= diff) - { - if (Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0)) - { - Madrigosa->CastSpell(me, SPELL_INTRO_FROSTBOLT, true); - IntroFrostBoltTimer = 2000; - } - } else IntroFrostBoltTimer -= diff; - } - if (!UpdateVictim()) - return; - DoMeleeAttackIfReady(); - } - - if (!UpdateVictim() || IsIntro) - return; - - if (SlashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_METEOR_SLASH); - SlashTimer = 11000; - } else SlashTimer -= diff; - - if (StompTimer <= diff) - { - DoScriptText(RAND(YELL_LOVE1,YELL_LOVE2,YELL_LOVE3), me); - DoCast(me->getVictim(), SPELL_STOMP); - StompTimer = 30000; - } else StompTimer -= diff; - - if (BurnTimer <= diff) - { - std::list pTargets; - SelectTargetList(pTargets, 10, SELECT_TARGET_RANDOM, 100, true); - for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) - if (!(*i)->HasAura(SPELL_BURN)) - { - (*i)->CastSpell((*i), SPELL_BURN, true); - break; - } - BurnTimer = urand(60000,180000); - } else BurnTimer -= diff; - - if (BerserkTimer < diff && !Enraged) - { - DoScriptText(YELL_BERSERK, me); - DoCast(me, SPELL_BERSERK); - Enraged = true; - } else BerserkTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_brutallus(Creature* pCreature) -{ - return new boss_brutallusAI (pCreature); -} - -void AddSC_boss_brutallus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_brutallus"; - newscript->GetAI = &GetAI_boss_brutallus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_eredar_twins.cpp b/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_eredar_twins.cpp deleted file mode 100644 index 602f12065fa..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_eredar_twins.cpp +++ /dev/null @@ -1,762 +0,0 @@ -/* Copyright (C) 2009 Trinity -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Eredar_Twins -SD%Complete: 100 -SDComment: -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -enum Quotes -{ - //Alytesh - YELL_CANFLAGRATION = -1580044, - YELL_SISTER_SACROLASH_DEAD = -1580045, - YELL_ALY_KILL_1 = -1580046, - YELL_ALY_KILL_2 = -1580047, - YELL_ALY_DEAD = -1580048, - YELL_BERSERK = -1580049, - - //Sacrolash - YELL_SHADOW_NOVA = -1580050, - YELL_SISTER_ALYTHESS_DEAD = -1580051, - YELL_SAC_KILL_1 = -1580052, - YELL_SAC_KILL_2 = -1580053, - SAY_SAC_DEAD = -1580054, - YELL_ENRAGE = -1580055, - - //Intro - YELL_INTRO_SAC_1 = -1580056, - YELL_INTRO_ALY_2 = -1580057, - YELL_INTRO_SAC_3 = -1580058, - YELL_INTRO_ALY_4 = -1580059, - YELL_INTRO_SAC_5 = -1580060, - YELL_INTRO_ALY_6 = -1580061, - YELL_INTRO_SAC_7 = -1580062, - YELL_INTRO_ALY_8 = -1580063, - - //Emote - EMOTE_SHADOW_NOVA = -1580064, - EMOTE_CONFLAGRATION = -1580065 -}; - -enum Spells -{ - //Lady Sacrolash spells - SPELL_DARK_TOUCHED = 45347, - SPELL_SHADOW_BLADES = 45248, //10 secs - SPELL_DARK_STRIKE = 45271, - SPELL_SHADOW_NOVA = 45329, //30-35 secs - SPELL_CONFOUNDING_BLOW = 45256, //25 secs - - //Shadow Image spells - SPELL_SHADOW_FURY = 45270, - SPELL_IMAGE_VISUAL = 45263, - - //Misc spells - SPELL_ENRAGE = 46587, - SPELL_EMPOWER = 45366, - SPELL_DARK_FLAME = 45345, - - //Grand Warlock Alythess spells - SPELL_PYROGENICS = 45230, //15secs - SPELL_FLAME_TOUCHED = 45348, - SPELL_CONFLAGRATION = 45342, //30-35 secs - SPELL_BLAZE = 45235, //on main target every 3 secs - SPELL_FLAME_SEAR = 46771, - SPELL_BLAZE_SUMMON = 45236, //187366 GO - SPELL_BLAZE_BURN = 45246 -}; - -struct boss_sacrolashAI : public ScriptedAI -{ - boss_sacrolashAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - bool SisterDeath; - bool Enraged; - - uint32 ShadowbladesTimer; - uint32 ShadownovaTimer; - uint32 ConfoundingblowTimer; - uint32 ShadowimageTimer; - uint32 ConflagrationTimer; - uint32 EnrageTimer; - - void Reset() - { - Enraged = false; - - if (pInstance) - { - Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); - if (Temp) - if (Temp->isDead()) - { - CAST_CRE(Temp)->Respawn(); - }else - { - if (Temp->getVictim()) - { - me->getThreatManager().addThreat(Temp->getVictim(),0.0f); - } - } - } - - if (!me->isInCombat()) - { - ShadowbladesTimer = 10000; - ShadownovaTimer = 30000; - ConfoundingblowTimer = 25000; - ShadowimageTimer = 20000; - ConflagrationTimer = 30000; - EnrageTimer = 360000; - - SisterDeath = false; - } - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * who) - { - DoZoneInCombat(); - - if (pInstance) - { - Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); - if (Temp && Temp->isAlive() && !(Temp->getVictim())) - CAST_CRE(Temp)->AI()->AttackStart(who); - } - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - if (rand()%4 == 0) - DoScriptText(RAND(YELL_SAC_KILL_1,YELL_SAC_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - // only if ALY death - if (SisterDeath) - { - DoScriptText(SAY_SAC_DEAD, me); - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, DONE); - } - else - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - - void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) - { - switch(spell->Id) - { - case SPELL_SHADOW_BLADES: - case SPELL_SHADOW_NOVA: - case SPELL_CONFOUNDING_BLOW: - case SPELL_SHADOW_FURY: - HandleTouchedSpells(pTarget, SPELL_DARK_TOUCHED); - break; - case SPELL_CONFLAGRATION: - HandleTouchedSpells(pTarget, SPELL_FLAME_TOUCHED); - break; - } - } - - void HandleTouchedSpells(Unit *pTarget, uint32 TouchedType) - { - switch(TouchedType) - { - case SPELL_FLAME_TOUCHED: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_DARK_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_DARK_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - } else pTarget->CastSpell(pTarget, SPELL_FLAME_TOUCHED, true); - } - break; - case SPELL_DARK_TOUCHED: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - } else pTarget->CastSpell(pTarget, SPELL_DARK_TOUCHED, true); - } - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!SisterDeath) - { - if (pInstance) - { - Unit* Temp = NULL; - Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); - if (Temp && Temp->isDead()) - { - DoScriptText(YELL_SISTER_ALYTHESS_DEAD, me); - DoCast(me, SPELL_EMPOWER); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - SisterDeath = true; - } - } - } - - if (!UpdateVictim()) - return; - - if (SisterDeath) - { - if (ConflagrationTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_CONFLAGRATION); - ConflagrationTimer = 30000+(rand()%5000); - } - } else ConflagrationTimer -= diff; - } - else - { - if (ShadownovaTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_SHADOW_NOVA); - - if (!SisterDeath) - { - if (pTarget) - DoScriptText(EMOTE_SHADOW_NOVA, me, pTarget); - DoScriptText(YELL_SHADOW_NOVA, me); - } - ShadownovaTimer = 30000+(rand()%5000); - } - } else ShadownovaTimer -=diff; - } - - if (ConfoundingblowTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_CONFOUNDING_BLOW); - ConfoundingblowTimer = 20000 + (rand()%5000); - } - } else ConfoundingblowTimer -=diff; - - if (ShadowimageTimer <= diff) - { - Unit *pTarget = NULL; - Creature* temp = NULL; - for (uint8 i = 0; i<3; ++i) - { - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - temp = DoSpawnCreature(MOB_SHADOW_IMAGE,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN,10000); - if (temp && pTarget) - { - temp->AddThreat(pTarget,1000000);//don't change target(healers) - temp->AI()->AttackStart(pTarget); - } - } - ShadowimageTimer = 20000; - } else ShadowimageTimer -=diff; - - if (ShadowbladesTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_SHADOW_BLADES); - ShadowbladesTimer = 10000; - } - } else ShadowbladesTimer -=diff; - - if (EnrageTimer < diff && !Enraged) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - DoScriptText(YELL_ENRAGE, me); - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else EnrageTimer -= diff; - - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - HandleTouchedSpells(me->getVictim(), SPELL_DARK_TOUCHED); - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - } -}; - -CreatureAI* GetAI_boss_sacrolash(Creature* pCreature) -{ - return new boss_sacrolashAI (pCreature); -}; - -struct boss_alythessAI : public Scripted_NoMovementAI -{ - boss_alythessAI(Creature *c) : Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); - IntroStepCounter = 10; - } - - ScriptedInstance *pInstance; - - bool SisterDeath; - bool Enraged; - - uint32 IntroStepCounter; - uint32 IntroYellTimer; - - uint32 ConflagrationTimer; - uint32 BlazeTimer; - uint32 PyrogenicsTimer; - uint32 ShadownovaTimer; - uint32 FlamesearTimer; - uint32 EnrageTimer; - - void Reset() - { - Enraged = false; - - if (pInstance) - { - Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); - if (Temp) - if (Temp->isDead()) - { - CAST_CRE(Temp)->Respawn(); - }else - { - if (Temp->getVictim()) - { - me->getThreatManager().addThreat(Temp->getVictim(),0.0f); - } - } - } - - if (!me->isInCombat()) - { - ConflagrationTimer = 45000; - BlazeTimer = 100; - PyrogenicsTimer = 15000; - ShadownovaTimer = 40000; - EnrageTimer = 360000; - FlamesearTimer = 15000; - IntroYellTimer = 10000; - - SisterDeath = false; - } - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * who) - { - DoZoneInCombat(); - - if (pInstance) - { - Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); - if (Temp && Temp->isAlive() && !(Temp->getVictim())) - CAST_CRE(Temp)->AI()->AttackStart(who); - } - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit *who) - { - if (!me->isInCombat()) - { - Scripted_NoMovementAI::AttackStart(who); - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) - { - if (!me->isInCombat()) - { - DoStartNoMovement(who); - } - } - } - else if (IntroStepCounter == 10 && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 30)) - { - IntroStepCounter = 0; - } - } - - void KilledUnit(Unit * /*victim*/) - { - if (rand()%4 == 0) - { - DoScriptText(RAND(YELL_ALY_KILL_1,YELL_ALY_KILL_2), me); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (SisterDeath) - { - DoScriptText(YELL_ALY_DEAD, me); - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, DONE); - } - else - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - - void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) - { - switch(spell->Id) - { - - case SPELL_BLAZE: - pTarget->CastSpell(pTarget, SPELL_BLAZE_SUMMON, true); - case SPELL_CONFLAGRATION: - case SPELL_FLAME_SEAR: - HandleTouchedSpells(pTarget, SPELL_FLAME_TOUCHED); - break; - case SPELL_SHADOW_NOVA: - HandleTouchedSpells(pTarget, SPELL_DARK_TOUCHED); - break; - } - } - - void HandleTouchedSpells(Unit *pTarget, uint32 TouchedType) - { - switch(TouchedType) - { - case SPELL_FLAME_TOUCHED: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_DARK_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_DARK_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - }else - { - pTarget->CastSpell(pTarget, SPELL_FLAME_TOUCHED, true); - } - } - break; - case SPELL_DARK_TOUCHED: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - } else pTarget->CastSpell(pTarget, SPELL_DARK_TOUCHED, true); - } - break; - } - } - - uint32 IntroStep(uint32 step) - { - Creature* Sacrolash = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_SACROLASH) : 0); - switch (step) - { - case 0: return 0; - case 1: - if (Sacrolash) - DoScriptText(YELL_INTRO_SAC_1, Sacrolash); - return 1000; - case 2: DoScriptText(YELL_INTRO_ALY_2, me); return 1000; - case 3: - if (Sacrolash) - DoScriptText(YELL_INTRO_SAC_3, Sacrolash); - return 2000; - case 4: DoScriptText(YELL_INTRO_ALY_4, me); return 1000; - case 5: - if (Sacrolash) - DoScriptText(YELL_INTRO_SAC_5, Sacrolash); - return 2000; - case 6: DoScriptText(YELL_INTRO_ALY_6, me); return 1000; - case 7: - if (Sacrolash) - DoScriptText(YELL_INTRO_SAC_7, Sacrolash); - return 3000; - case 8: DoScriptText(YELL_INTRO_ALY_8, me); return 900000; - } - return 10000; - } - - void UpdateAI(const uint32 diff) - { - if (IntroStepCounter < 9) - { - if (IntroYellTimer <= diff) - { - IntroYellTimer = IntroStep(++IntroStepCounter); - } else IntroYellTimer -= diff; - } - - if (!SisterDeath) - { - if (pInstance) - { - Unit* Temp = NULL; - Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); - if (Temp && Temp->isDead()) - { - DoScriptText(YELL_SISTER_SACROLASH_DEAD, me); - DoCast(me, SPELL_EMPOWER); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - SisterDeath = true; - } - } - } - if (!me->getVictim()) - { - if (pInstance) - { - Creature* sisiter = Unit::GetCreature((*me),pInstance->GetData64(DATA_SACROLASH)); - if (sisiter && !sisiter->isDead() && sisiter->getVictim()) - { - me->AddThreat(sisiter->getVictim(),0.0f); - DoStartNoMovement(sisiter->getVictim()); - me->Attack(sisiter->getVictim(),false); - } - } - } - - if (!UpdateVictim()) - return; - - if (SisterDeath) - { - if (ShadownovaTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_SHADOW_NOVA); - ShadownovaTimer= 30000+(rand()%5000); - } - } else ShadownovaTimer -=diff; - } - else - { - if (ConflagrationTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_CONFLAGRATION); - ConflagrationTimer = 30000+(rand()%5000); - - if (!SisterDeath) - { - if (pTarget) - DoScriptText(EMOTE_CONFLAGRATION, me, pTarget); - DoScriptText(YELL_CANFLAGRATION, me); - } - - BlazeTimer = 4000; - } - } else ConflagrationTimer -= diff; - } - - if (FlamesearTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_FLAME_SEAR); - FlamesearTimer = 15000; - } - } else FlamesearTimer -=diff; - - if (PyrogenicsTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_PYROGENICS, true); - PyrogenicsTimer = 15000; - } - } else PyrogenicsTimer -= diff; - - if (BlazeTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me->getVictim(), SPELL_BLAZE); - BlazeTimer = 3800; - } - } else BlazeTimer -= diff; - - if (EnrageTimer < diff && !Enraged) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - DoScriptText(YELL_BERSERK, me); - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else EnrageTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_alythess(Creature* pCreature) -{ - return new boss_alythessAI (pCreature); -}; - -struct mob_shadow_imageAI : public ScriptedAI -{ - mob_shadow_imageAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowfuryTimer; - uint32 KillTimer; - uint32 DarkstrikeTimer; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - ShadowfuryTimer = 5000 + (rand()%15000); - DarkstrikeTimer = 3000; - KillTimer = 15000; - } - - void EnterCombat(Unit * /*who*/){} - - void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) - { - switch(spell->Id) - { - - case SPELL_SHADOW_FURY: - case SPELL_DARK_STRIKE: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - } else pTarget->CastSpell(pTarget,SPELL_DARK_TOUCHED,true); - } - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->HasAura(SPELL_IMAGE_VISUAL)) - DoCast(me, SPELL_IMAGE_VISUAL); - - if (KillTimer <= diff) - { - me->Kill(me); - KillTimer = 9999999; - } else KillTimer -= diff; - - if (!UpdateVictim()) - return; - - if (ShadowfuryTimer <= diff) - { - DoCast(me, SPELL_SHADOW_FURY); - ShadowfuryTimer = 10000; - } else ShadowfuryTimer -=diff; - - if (DarkstrikeTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - DoCast(me->getVictim(), SPELL_DARK_STRIKE); - } - DarkstrikeTimer = 3000; - } else DarkstrikeTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_shadow_image(Creature* pCreature) -{ - return new mob_shadow_imageAI (pCreature); -}; - -void AddSC_boss_eredar_twins() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sacrolash"; - newscript->GetAI = &GetAI_boss_sacrolash; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_alythess"; - newscript->GetAI = &GetAI_boss_alythess; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadow_image"; - newscript->GetAI = &GetAI_mob_shadow_image; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_felmyst.cpp b/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_felmyst.cpp deleted file mode 100644 index 88ad2dbab11..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_felmyst.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/* Copyright (C) 2009 Trinity -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Felmyst -SD%Complete: 0 -SDComment: -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -enum Yells -{ - YELL_BIRTH = -1580036, - YELL_KILL1 = -1580037, - YELL_KILL2 = -1580038, - YELL_BREATH = -1580039, - YELL_TAKEOFF = -1580040, - YELL_BERSERK = -1580041, - YELL_DEATH = -1580042, - YELL_KALECGOS = -1580043, // after felmyst's death spawned and say this -}; - -enum Spells -{ - //Aura - AURA_SUNWELL_RADIANCE = 45769, - AURA_NOXIOUS_FUMES = 47002, - - //Land phase - SPELL_CLEAVE = 19983, - SPELL_CORROSION = 45866, - SPELL_GAS_NOVA = 45855, - SPELL_ENCAPSULATE_CHANNEL = 45661, - // SPELL_ENCAPSULATE_EFFECT = 45665, - // SPELL_ENCAPSULATE_AOE = 45662, - - //Flight phase - SPELL_VAPOR_SELECT = 45391, // fel to player, force cast 45392, 50000y selete target - SPELL_VAPOR_SUMMON = 45392, // player summon vapor, radius around caster, 5y, - SPELL_VAPOR_FORCE = 45388, // vapor to fel, force cast 45389 - SPELL_VAPOR_CHANNEL = 45389, // fel to vapor, green beam channel - SPELL_VAPOR_TRIGGER = 45411, // linked to 45389, vapor to self, trigger 45410 and 46931 - SPELL_VAPOR_DAMAGE = 46931, // vapor damage, 4000 - SPELL_TRAIL_SUMMON = 45410, // vapor summon trail - SPELL_TRAIL_TRIGGER = 45399, // trail to self, trigger 45402 - SPELL_TRAIL_DAMAGE = 45402, // trail damage, 2000 + 2000 dot - SPELL_DEAD_SUMMON = 45400, // summon blazing dead, 5min - SPELL_DEAD_PASSIVE = 45415, - SPELL_FOG_BREATH = 45495, // fel to self, speed burst - SPELL_FOG_TRIGGER = 45582, // fog to self, trigger 45782 - SPELL_FOG_FORCE = 45782, // fog to player, force cast 45714 - SPELL_FOG_INFORM = 45714, // player let fel cast 45717, script effect - SPELL_FOG_CHARM = 45717, // fel to player - SPELL_FOG_CHARM2 = 45726, // link to 45717 - - SPELL_TRANSFORM_TRIGGER = 44885, // madrigosa to self, trigger 46350 - SPELL_TRANSFORM_VISUAL = 46350, // 46411stun? - SPELL_TRANSFORM_FELMYST = 45068, // become fel - SPELL_FELMYST_SUMMON = 45069, - - //Other - SPELL_BERSERK = 45078, - SPELL_CLOUD_VISUAL = 45212, - SPELL_CLOUD_SUMMON = 45884, -}; - -enum PhaseFelmyst -{ - PHASE_NONE, - PHASE_GROUND, - PHASE_FLIGHT, -}; - -enum EventFelmyst -{ - EVENT_NONE, - EVENT_BERSERK, - - EVENT_CLEAVE, - EVENT_CORROSION, - EVENT_GAS_NOVA, - EVENT_ENCAPSULATE, - EVENT_FLIGHT, - - EVENT_FLIGHT_SEQUENCE, - EVENT_SUMMON_DEAD, - EVENT_SUMMON_FOG, -}; - -struct boss_felmystAI : public ScriptedAI -{ - boss_felmystAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - - // wait for core patch be accepted - /*SpellEntry *TempSpell = GET_SPELL(SPELL_ENCAPSULATE_EFFECT); - if (TempSpell->SpellIconID == 2294) - TempSpell->SpellIconID = 2295; - TempSpell = GET_SPELL(SPELL_VAPOR_TRIGGER); - if ((TempSpell->Attributes & SPELL_ATTR_PASSIVE) == 0) - TempSpell->Attributes |= SPELL_ATTR_PASSIVE; - TempSpell = GET_SPELL(SPELL_FOG_CHARM2); - if ((TempSpell->Attributes & SPELL_ATTR_PASSIVE) == 0) - TempSpell->Attributes |= SPELL_ATTR_PASSIVE;*/ - } - - ScriptedInstance *pInstance; - PhaseFelmyst phase; - EventMap events; - - uint32 uiFlightCount; - uint32 uiBreathCount; - - float breathX, breathY; - - void Reset() - { - phase = PHASE_NONE; - - events.Reset(); - - uiFlightCount = 0; - - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - - DespawnSummons(MOB_VAPOR_TRAIL); - me->setActive(false); - - if (pInstance) - pInstance->SetData(DATA_FELMYST_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - events.ScheduleEvent(EVENT_BERSERK, 600000); - - me->setActive(true); - DoZoneInCombat(); - DoCast(me, AURA_SUNWELL_RADIANCE, true); - DoCast(me, AURA_NOXIOUS_FUMES, true); - EnterPhase(PHASE_GROUND); - - if (pInstance) - pInstance->SetData(DATA_FELMYST_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit *who) - { - if (phase != PHASE_FLIGHT) - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (phase != PHASE_FLIGHT) - ScriptedAI::MoveInLineOfSight(who); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(YELL_KILL1,YELL_KILL2), me); - } - - void JustRespawned() - { - DoScriptText(YELL_BIRTH, me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(YELL_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_FELMYST_EVENT, DONE); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - // workaround for linked aura - /*if (spell->Id == SPELL_VAPOR_FORCE) - { - caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true); - }*/ - // workaround for mind control - if (spell->Id == SPELL_FOG_INFORM) - { - float x, y, z; - caster->GetPosition(x, y, z); - if (Unit* summon = me->SummonCreature(MOB_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) - { - summon->SetMaxHealth(caster->GetMaxHealth()); - summon->SetHealth(caster->GetMaxHealth()); - summon->CastSpell(summon, SPELL_FOG_CHARM, true); - summon->CastSpell(summon, SPELL_FOG_CHARM2, true); - } - me->DealDamage(caster, caster->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == MOB_DEAD) - { - summon->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); - DoZoneInCombat(summon); - summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true); - } - } - - void MovementInform(uint32, uint32) - { - if (phase == PHASE_FLIGHT) - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); - } - - void DamageTaken(Unit*, uint32 &damage) - { - if (phase != PHASE_GROUND && damage >= me->GetHealth()) - damage = 0; - } - - void EnterPhase(PhaseFelmyst NextPhase) - { - switch(NextPhase) - { - case PHASE_GROUND: - me->CastStop(SPELL_FOG_BREATH); - me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); - me->SetUnitMovementFlags(MOVEMENTFLAG_NONE); - me->SetSpeed(MOVE_RUN, 2.0); - - events.ScheduleEvent(EVENT_CLEAVE, urand(5000, 10000)); - events.ScheduleEvent(EVENT_CORROSION, urand(10000, 20000)); - events.ScheduleEvent(EVENT_GAS_NOVA, urand(15000, 20000)); - events.ScheduleEvent(EVENT_ENCAPSULATE, urand(20000, 25000)); - events.ScheduleEvent(EVENT_FLIGHT, 60000); - break; - case PHASE_FLIGHT: - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1000); - uiFlightCount = 0; - uiBreathCount = 0; - break; - } - phase = NextPhase; - } - - void HandleFlightSequence() - { - switch(uiFlightCount) - { - case 0: - //me->AttackStop(); - me->GetMotionMaster()->Clear(false); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->StopMoving(); - DoScriptText(YELL_TAKEOFF, me); - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 2000); - break; - case 1: - me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+1, me->GetPositionY(), me->GetPositionZ()+10); - break; - case 2: - { - Unit *pTarget = pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); - if (!pTarget) - pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); - - if (!pTarget) - { - EnterEvadeMode(); - return; - } - - Creature* Vapor = me->SummonCreature(MOB_VAPOR, pTarget->GetPositionX()-5+rand()%10, pTarget->GetPositionY()-5+rand()%10, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); - if (Vapor) - { - Vapor->AI()->AttackStart(pTarget); - me->InterruptNonMeleeSpells(false); - DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug - Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true); - } - - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); - break; - } - case 3: - { - DespawnSummons(MOB_VAPOR_TRAIL); - //DoCast(me, SPELL_VAPOR_SELECT); need core support - - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); - if (!pTarget) - pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); - - if (!pTarget) - { - EnterEvadeMode(); - return; - } - - //pTarget->CastSpell(pTarget, SPELL_VAPOR_SUMMON, true); need core support - Creature* pVapor = me->SummonCreature(MOB_VAPOR, pTarget->GetPositionX()-5+rand()%10, pTarget->GetPositionY()-5+rand()%10, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); - if (pVapor) - { - if (pVapor->AI()) - pVapor->AI()->AttackStart(pTarget); - me->InterruptNonMeleeSpells(false); - DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug - pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true); - } - - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); - break; - } - case 4: - DespawnSummons(MOB_VAPOR_TRAIL); - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); - break; - case 5: - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); - if (!pTarget) - pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); - - if (!pTarget) - { - EnterEvadeMode(); - return; - } - - breathX = pTarget->GetPositionX(); - breathY = pTarget->GetPositionY(); - float x, y, z; - pTarget->GetContactPoint(me, x, y, z, 70); - me->GetMotionMaster()->MovePoint(0, x, y, z+10); - break; - } - case 6: - me->SetOrientation(me->GetAngle(breathX, breathY)); - me->StopMoving(); - //DoTextEmote("takes a deep breath.", NULL); - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); - break; - case 7: - { - DoCast(me, SPELL_FOG_BREATH, true); - float x, y, z; - me->GetPosition(x, y, z); - x = 2 * breathX - x; - y = 2 * breathY - y; - me->GetMotionMaster()->MovePoint(0, x, y, z); - events.ScheduleEvent(EVENT_SUMMON_FOG, 1); - break; - } - case 8: - me->CastStop(SPELL_FOG_BREATH); - me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); - ++uiBreathCount; - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); - if (uiBreathCount < 3) - uiFlightCount = 4; - break; - case 9: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO)) - DoStartMovement(pTarget); - else - { - EnterEvadeMode(); - return; - } - break; - case 10: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - EnterPhase(PHASE_GROUND); - AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO)); - break; - } - ++uiFlightCount; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (phase == PHASE_FLIGHT && !me->IsInEvadeMode()) - EnterEvadeMode(); - return; - } - - events.Update(diff); - - if (me->IsNonMeleeSpellCasted(false)) - return; - - if (phase == PHASE_GROUND) - { - switch(events.ExecuteEvent()) - { - case EVENT_BERSERK: - DoScriptText(YELL_BERSERK, me); - DoCast(me, SPELL_BERSERK, true); - events.ScheduleEvent(EVENT_BERSERK, 10000); - break; - case EVENT_CLEAVE: - DoCast(me->getVictim(), SPELL_CLEAVE, false); - events.ScheduleEvent(EVENT_CLEAVE, urand(5000,10000)); - break; - case EVENT_CORROSION: - DoCast(me->getVictim(), SPELL_CORROSION, false); - events.ScheduleEvent(EVENT_CORROSION, urand(20000,30000)); - break; - case EVENT_GAS_NOVA: - DoCast(me, SPELL_GAS_NOVA, false); - events.ScheduleEvent(EVENT_GAS_NOVA, urand(20000,25000)); - break; - case EVENT_ENCAPSULATE: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true)) - DoCast(pTarget, SPELL_ENCAPSULATE_CHANNEL, false); - events.ScheduleEvent(EVENT_ENCAPSULATE, urand(25000,30000)); - break; - case EVENT_FLIGHT: - EnterPhase(PHASE_FLIGHT); - break; - default: - DoMeleeAttackIfReady(); - break; - } - } - - if (phase == PHASE_FLIGHT) - { - switch(events.ExecuteEvent()) - { - case EVENT_BERSERK: - DoScriptText(YELL_BERSERK, me); - DoCast(me, SPELL_BERSERK, true); - break; - case EVENT_FLIGHT_SEQUENCE: - HandleFlightSequence(); - break; - case EVENT_SUMMON_FOG: - { - float x, y, z; - me->GetPosition(x, y, z); - me->UpdateGroundPositionZ(x, y, z); - if (Creature *Fog = me->SummonCreature(MOB_VAPOR_TRAIL, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 10000)) - { - Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER); - Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true); - me->CastSpell(Fog, SPELL_FOG_FORCE, true); - } - } - events.ScheduleEvent(EVENT_SUMMON_FOG, 1000); - break; - } - } - } - - void DespawnSummons(uint32 entry) - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllCreaturesOfEntryInRange check(me, entry, 100); - Trinity::CreatureListSearcher searcher(me, templist, check); - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - cell.Visit(pair, cSearcher, *(me->GetMap())); - - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - if (entry == MOB_VAPOR_TRAIL && phase == PHASE_FLIGHT) - { - (*i)->GetPosition(x, y, z); - me->SummonCreature(MOB_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - } - (*i)->SetVisibility(VISIBILITY_OFF); - (*i)->setDeathState(JUST_DIED); - if ((*i)->getDeathState() == CORPSE) - (*i)->RemoveCorpse(); - } - } -}; - -struct mob_felmyst_vaporAI : public ScriptedAI -{ - mob_felmyst_vaporAI(Creature *c) : ScriptedAI(c) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetSpeed(MOVE_RUN, 0.8); - } - void Reset() {} - void EnterCombat(Unit* /*who*/) - { - DoZoneInCombat(); - //DoCast(me, SPELL_VAPOR_FORCE, true); core bug - } - void UpdateAI(const uint32 /*diff*/) - { - if (!me->getVictim()) - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - AttackStart(pTarget); - } -}; - -struct mob_felmyst_trailAI : public ScriptedAI -{ - mob_felmyst_trailAI(Creature *c) : ScriptedAI(c) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_TRAIL_TRIGGER, true); - me->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 0.01); // core bug - } - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_boss_felmyst(Creature* pCreature) -{ - return new boss_felmystAI(pCreature); -} - -CreatureAI* GetAI_mob_felmyst_vapor(Creature* pCreature) -{ - return new mob_felmyst_vaporAI(pCreature); -} - -CreatureAI* GetAI_mob_felmyst_trail(Creature* pCreature) -{ - return new mob_felmyst_trailAI(pCreature); -} - -void AddSC_boss_felmyst() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_felmyst"; - newscript->GetAI = &GetAI_boss_felmyst; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felmyst_vapor"; - newscript->GetAI = &GetAI_mob_felmyst_vapor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felmyst_trail"; - newscript->GetAI = &GetAI_mob_felmyst_trail; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp b/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp deleted file mode 100644 index 146771325eb..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kalecgos -SD%Complete: 95 -SDComment: -SDCategory: Sunwell_Plateau -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -enum Yells -{ - //Kalecgos dragon form - SAY_EVIL_AGGRO = -1580000, - SAY_EVIL_SPELL1 = -1580001, - SAY_EVIL_SPELL2 = -1580002, - SAY_EVIL_SLAY1 = -1580003, - SAY_EVIL_SLAY2 = -1580004, - SAY_EVIL_ENRAGE = -1580005, - - //Kalecgos humanoid form - SAY_GOOD_AGGRO = -1580006, - SAY_GOOD_NEAR_DEATH = -1580007, - SAY_GOOD_NEAR_DEATH2 = -1580008, - SAY_GOOD_PLRWIN = -1580009, - - //Sathrovarr - SAY_SATH_AGGRO = -1580010, - SAY_SATH_DEATH = -1580011, - SAY_SATH_SPELL1 = -1580012, - SAY_SATH_SPELL2 = -1580013, - SAY_SATH_SLAY1 = -1580014, - SAY_SATH_SLAY2 = -1580015, - SAY_SATH_ENRAGE = -1580016, -}; - -enum Spells -{ - AURA_SUNWELL_RADIANCE = 45769, - AURA_SPECTRAL_EXHAUSTION = 44867, - AURA_SPECTRAL_REALM = 46021, - AURA_SPECTRAL_INVISIBILITY = 44801, - AURA_DEMONIC_VISUAL = 44800, - - SPELL_SPECTRAL_BLAST = 44869, - SPELL_TELEPORT_SPECTRAL = 46019, - SPELL_ARCANE_BUFFET = 45018, - SPELL_FROST_BREATH = 44799, - SPELL_TAIL_LASH = 45122, - - SPELL_BANISH = 44836, - SPELL_TRANSFORM_KALEC = 44670, - SPELL_ENRAGE = 44807, - - SPELL_CORRUPTION_STRIKE = 45029, - SPELL_AGONY_CURSE = 45032, - SPELL_SHADOW_BOLT = 45031, - - SPELL_HEROIC_STRIKE = 45026, - SPELL_REVITALIZE = 45027 -}; - -enum SWPActions -{ - DO_ENRAGE = 1, - DO_BANISH = 2, -}; - -#define GO_FAILED "You are unable to use this currently." - -#define EMOTE_UNABLE_TO_FIND "is unable to find Kalecgos" - -#define FLY_X 1679 -#define FLY_Y 900 -#define FLY_Z 82 - -#define CENTER_X 1705 -#define CENTER_Y 930 -#define RADIUS 30 - -#define DRAGON_REALM_Z 53.079 -#define DEMON_REALM_Z -74.558 - -#define MAX_PLAYERS_IN_SPECTRAL_REALM 0 //over this, teleport object won't work, 0 disables check - -uint32 WildMagic[] = { 44978, 45001, 45002, 45004, 45006, 45010 }; - -struct boss_kalecgosAI : public ScriptedAI -{ - boss_kalecgosAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - SathGUID = 0; - DoorGUID = 0; - bJustReset = false; - me->setActive(true); - SpellEntry *TempSpell = GET_SPELL(SPELL_SPECTRAL_BLAST); - if (TempSpell) - TempSpell->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ENEMY; - } - - ScriptedInstance *pInstance; - - uint32 ArcaneBuffetTimer; - uint32 FrostBreathTimer; - uint32 WildMagicTimer; - uint32 SpectralBlastTimer; - uint32 TailLashTimer; - uint32 CheckTimer; - uint32 TalkTimer; - uint32 TalkSequence; - uint32 ResetTimer; - - bool isFriendly; - bool isEnraged; - bool isBanished; - bool bJustReset; - - uint64 SathGUID; - uint64 DoorGUID; - - void Reset() - { - if (pInstance) - { - SathGUID = pInstance->GetData64(DATA_SATHROVARR); - pInstance->SetData(DATA_KALECGOS_EVENT, NOT_STARTED); - } - - if (Creature *Sath = Unit::GetCreature(*me, SathGUID)) - Sath->AI()->EnterEvadeMode(); - - me->setFaction(14); - if (!bJustReset) //first reset at create - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SetVisibility(VISIBILITY_ON); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - } - me->SetHealth(me->GetMaxHealth());//dunno why it does not resets health at evade.. - ArcaneBuffetTimer = 8000; - FrostBreathTimer = 15000; - WildMagicTimer = 10000; - TailLashTimer = 25000; - SpectralBlastTimer = urand(20000,25000); - CheckTimer = 1000; - ResetTimer = 30000; - - TalkTimer = 0; - TalkSequence = 0; - isFriendly = false; - isEnraged = false; - isBanished = false; - } - - void EnterEvadeMode() - { - bJustReset = true; - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - ScriptedAI::EnterEvadeMode(); - } - - void DoAction(const int32 param) - { - switch (param) - { - case DO_ENRAGE: - isEnraged = true; - me->CastSpell(me, SPELL_ENRAGE, true); - break; - case DO_BANISH: - isBanished = true; - me->CastSpell(me, SPELL_BANISH, true); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (TalkTimer) - { - if (!TalkSequence) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(); - ++TalkSequence; - } - if (TalkTimer <= diff) - { - if (isFriendly) - GoodEnding(); - else - BadEnding(); - ++TalkSequence; - } else TalkTimer -= diff; - } - else - { - if (bJustReset) - { - if (ResetTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SetVisibility(VISIBILITY_ON); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - ResetTimer = 10000; - bJustReset = false; - } else ResetTimer -= diff; - return; - } - if (!UpdateVictim()) - return; - - if (CheckTimer <= diff) - { - if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75) - { - me->AI()->EnterEvadeMode(); - return; - } - if (HealthBelowPct(10) && !isEnraged) - { - if (Creature* Sath = Unit::GetCreature(*me, SathGUID)) - Sath->AI()->DoAction(DO_ENRAGE); - DoAction(DO_ENRAGE); - } - if (!isBanished && HealthBelowPct(1)) - { - if (Creature* Sath = Unit::GetCreature(*me, SathGUID)) - { - if (Sath->HasAura(SPELL_BANISH)) - { - Sath->DealDamage(Sath, Sath->GetHealth()); - return; - } - else - DoAction(DO_BANISH); - } - else - { - error_log("TSCR: Didn't find Shathrowar. Kalecgos event reseted."); - EnterEvadeMode(); - return; - } - } - CheckTimer = 1000; - } else CheckTimer -= diff; - - if (ArcaneBuffetTimer <= diff) - { - DoCastAOE(SPELL_ARCANE_BUFFET); - ArcaneBuffetTimer = 8000; - } else ArcaneBuffetTimer -= diff; - - if (FrostBreathTimer <= diff) - { - DoCastAOE(SPELL_FROST_BREATH); - FrostBreathTimer = 15000; - } else FrostBreathTimer -= diff; - - if (TailLashTimer <= diff) - { - DoCastAOE(SPELL_TAIL_LASH); - TailLashTimer = 15000; - } else TailLashTimer -= diff; - - if (WildMagicTimer <= diff) - { - DoCastAOE(WildMagic[rand()%6]); - WildMagicTimer = 20000; - } else WildMagicTimer -= diff; - - if (SpectralBlastTimer <= diff) - { - std::list &m_threatlist = me->getThreatManager().getThreatList(); - std::list targetList; - for (std::list::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) - if ((*itr)->getTarget() && (*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->GetGUID() != me->getVictim()->GetGUID() && !(*itr)->getTarget()->HasAura(AURA_SPECTRAL_EXHAUSTION) && (*itr)->getTarget()->GetPositionZ() > me->GetPositionZ()-5) - targetList.push_back((*itr)->getTarget()); - if (targetList.empty()) - { - SpectralBlastTimer = 1000; - return; - } - std::list::const_iterator i = targetList.begin(); - advance(i, rand()%targetList.size()); - if ((*i)) - { - (*i)->CastSpell((*i), SPELL_SPECTRAL_BLAST,true); - SpectralBlastTimer = 20000+rand()%5000; - } else SpectralBlastTimer = 1000; - } else SpectralBlastTimer -= diff; - - DoMeleeAttackIfReady(); - } - } - - void MoveInLineOfSight(Unit *who) - { - if (bJustReset)//boss is invisible, don't attack - return; - - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius)) - AttackStart(who); - } - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = 0; - } - - void EnterCombat(Unit* /*who*/) - { - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_EVIL_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_KALECGOS_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_EVIL_SLAY1,SAY_EVIL_SLAY2), me); - } - - void MovementInform(uint32 type,uint32 /*id*/) - { - if (type != POINT_MOTION_TYPE) - return; - me->SetVisibility(VISIBILITY_OFF); - if (isFriendly) - { - me->setDeathState(JUST_DIED); - - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer) - ((InstanceMap*)me->GetMap())->PermBindAllPlayers(pPlayer); - } - } - } - else - { - me->GetMotionMaster()->MoveTargetedHome(); - TalkTimer = 1000; - } - } - - void GoodEnding() - { - switch(TalkSequence) - { - case 1: - me->setFaction(35); - TalkTimer = 1000; - break; - case 2: - DoScriptText(SAY_GOOD_PLRWIN, me); - TalkTimer = 10000; - break; - case 3: - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); - TalkTimer = 600000; - break; - default: - break; - } - } - - void BadEnding() - { - switch(TalkSequence) - { - case 1: - DoScriptText(SAY_EVIL_ENRAGE, me); - TalkTimer = 3000; - break; - case 2: - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); - TalkTimer = 15000; - break; - case 3: - EnterEvadeMode(); - break; - default: - break; - } - } -}; - -struct boss_sathrovarrAI : public ScriptedAI -{ - boss_sathrovarrAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - KalecGUID = 0; - KalecgosGUID = 0; - } - - ScriptedInstance *pInstance; - - uint32 CorruptionStrikeTimer; - uint32 AgonyCurseTimer; - uint32 ShadowBoltTimer; - uint32 CheckTimer; - uint32 ResetThreat; - - uint64 KalecGUID; - uint64 KalecgosGUID; - - bool isEnraged; - bool isBanished; - - void Reset() - { - me->SetHealth(me->GetMaxHealth());//dunno why it does not resets health at evade.. - me->setActive(true); - if (pInstance) - { - KalecgosGUID = pInstance->GetData64(DATA_KALECGOS_DRAGON); - pInstance->SetData(DATA_KALECGOS_EVENT, NOT_STARTED); - } - if (KalecGUID) - { - if (Creature* Kalec = Unit::GetCreature(*me, KalecGUID)) - Kalec->setDeathState(JUST_DIED); - KalecGUID = 0; - } - - ShadowBoltTimer = 7000 + rand()%3 * 1000; - AgonyCurseTimer = 20000; - CorruptionStrikeTimer = 13000; - CheckTimer = 1000; - ResetThreat = 1000; - isEnraged = false; - isBanished = false; - - me->CastSpell(me, AURA_DEMONIC_VISUAL, true); - TeleportAllPlayersBack(); - } - - void EnterCombat(Unit* /*who*/) - { - if (Creature *Kalec = me->SummonCreature(MOB_KALEC, me->GetPositionX() + 10, me->GetPositionY() + 5, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) - { - KalecGUID = Kalec->GetGUID(); - me->CombatStart(Kalec); - me->AddThreat(Kalec, 100.0f); - Kalec->setActive(true); - } - DoScriptText(SAY_SATH_AGGRO, me); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = 0; - } - - void KilledUnit(Unit *pTarget) - { - if (pTarget->GetGUID() == KalecGUID) - { - TeleportAllPlayersBack(); - if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) - { - CAST_AI(boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1; - CAST_AI(boss_kalecgosAI, Kalecgos->AI())->isFriendly = false; - } - EnterEvadeMode(); - return; - } - DoScriptText(RAND(SAY_SATH_SLAY1,SAY_SATH_SLAY2), me); - } - - void JustDied(Unit * /*killer*/) - { - DoScriptText(SAY_SATH_DEATH, me); - me->GetMap()->CreatureRelocation(me, me->GetPositionX(), me->GetPositionY(), DRAGON_REALM_Z, me->GetOrientation()); - TeleportAllPlayersBack(); - if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) - { - CAST_AI(boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1; - CAST_AI(boss_kalecgosAI, Kalecgos->AI())->isFriendly = true; - } - - if (pInstance) - pInstance->SetData(DATA_KALECGOS_EVENT, DONE); - } - - void TeleportAllPlayersBack() - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) return; - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->GetPositionZ() <= DRAGON_REALM_Z-5) - { - i->getSource()->RemoveAura(AURA_SPECTRAL_REALM); - i->getSource()->TeleportTo(me->GetMap()->GetId(),i->getSource()->GetPositionX(),i->getSource()->GetPositionY(),DRAGON_REALM_Z+5,i->getSource()->GetOrientation()); - } - } - } - - void DoAction(const int32 param) - { - switch (param) - { - case DO_ENRAGE: - isEnraged = true; - me->CastSpell(me, SPELL_ENRAGE, true); - break; - case DO_BANISH: - isBanished = true; - me->CastSpell(me, SPELL_BANISH, true); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) - me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); - if (!UpdateVictim()) - return; - - if (CheckTimer <= diff) - { - Creature *Kalec = Unit::GetCreature(*me, KalecGUID); - if (!Kalec || (Kalec && !Kalec->isAlive())) - { - if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) - Kalecgos->AI()->EnterEvadeMode(); - return; - } - if (HealthBelowPct(10) && !isEnraged) - { - if (Creature* Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) - Kalecgos->AI()->DoAction(DO_ENRAGE); - DoAction(DO_ENRAGE); - } - Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID); - if (Kalecgos) - { - if (!Kalecgos->isInCombat()) - { - me->AI()->EnterEvadeMode(); - return; - } - } - if (!isBanished && HealthBelowPct(1)) - { - if (Kalecgos) - { - if (Kalecgos->HasAura(SPELL_BANISH)) - { - me->DealDamage(me, me->GetHealth()); - return; - } - else - DoAction(DO_BANISH); - } - else - { - me->MonsterTextEmote(EMOTE_UNABLE_TO_FIND, NULL); - EnterEvadeMode(); - return; - } - } - CheckTimer = 1000; - } else CheckTimer -= diff; - - if (ResetThreat <= diff) - { - for (std::list::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) - { - if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - if (pUnit->GetPositionZ() > me->GetPositionZ()+5) - { - me->getThreatManager().modifyThreatPercent(pUnit,-100); - } - } - } - ResetThreat = 1000; - } else ResetThreat -= diff; - - if (ShadowBoltTimer <= diff) - { - if (!(rand()%5))DoScriptText(SAY_SATH_SPELL1, me); - DoCast(me, SPELL_SHADOW_BOLT); - ShadowBoltTimer = 7000+(rand()%3000); - } else ShadowBoltTimer -= diff; - - if (AgonyCurseTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (!pTarget) pTarget = me->getVictim(); - DoCast(pTarget, SPELL_AGONY_CURSE); - AgonyCurseTimer = 20000; - } else AgonyCurseTimer -= diff; - - if (CorruptionStrikeTimer <= diff) - { - if (!(rand()%5))DoScriptText(SAY_SATH_SPELL2, me); - DoCast(me->getVictim(), SPELL_CORRUPTION_STRIKE); - CorruptionStrikeTimer = 13000; - } else CorruptionStrikeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_kalecAI : public ScriptedAI -{ - ScriptedInstance *pInstance; - - uint32 RevitalizeTimer; - uint32 HeroicStrikeTimer; - uint32 YellTimer; - uint32 YellSequence; - - uint64 SathGUID; - - bool isEnraged; // if demon is enraged - - boss_kalecAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() - { - if (pInstance) - SathGUID = pInstance->GetData64(DATA_SATHROVARR); - - RevitalizeTimer = 5000; - HeroicStrikeTimer = 3000; - YellTimer = 5000; - YellSequence = 0; - - isEnraged = false; - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != SathGUID) - damage = 0; - else if (isEnraged) - damage *= 3; - } - - void UpdateAI(const uint32 diff) - { - if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) - me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); - if (!UpdateVictim()) - return; - - if (YellTimer <= diff) - { - switch(YellSequence) - { - case 0: - DoScriptText(SAY_GOOD_AGGRO, me); - ++YellSequence; - break; - case 1: - if (HealthBelowPct(50)) - { - DoScriptText(SAY_GOOD_NEAR_DEATH, me); - ++YellSequence; - } - break; - case 2: - if (HealthBelowPct(10)) - { - DoScriptText(SAY_GOOD_NEAR_DEATH2, me); - ++YellSequence; - } - break; - default: - break; - } - YellTimer = 5000; - } - - if (RevitalizeTimer <= diff) - { - DoCast(me, SPELL_REVITALIZE); - RevitalizeTimer = 5000; - } else RevitalizeTimer -= diff; - - if (HeroicStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HEROIC_STRIKE); - HeroicStrikeTimer = 2000; - } else HeroicStrikeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -bool GOkalecgos_teleporter(Player* pPlayer, GameObject* pGo) -{ - uint32 SpectralPlayers = 0; - Map* pMap = pGo->GetMap(); - if (!pMap->IsDungeon()) return true; - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->GetPositionZ() < DEMON_REALM_Z + 5) - ++SpectralPlayers; - } - if (pPlayer->HasAura(AURA_SPECTRAL_EXHAUSTION) || (MAX_PLAYERS_IN_SPECTRAL_REALM && SpectralPlayers >= MAX_PLAYERS_IN_SPECTRAL_REALM)) - pPlayer->GetSession()->SendNotification(GO_FAILED); - else - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_SPECTRAL, true); - return true; -} - -CreatureAI* GetAI_boss_kalecgos(Creature* pCreature) -{ - return new boss_kalecgosAI (pCreature); -} - -CreatureAI* GetAI_boss_Sathrovarr(Creature* pCreature) -{ - return new boss_sathrovarrAI (pCreature); -} - -CreatureAI* GetAI_boss_kalec(Creature* pCreature) -{ - return new boss_kalecAI (pCreature); -} - -void AddSC_boss_kalecgos() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kalecgos"; - newscript->GetAI = &GetAI_boss_kalecgos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_sathrovarr"; - newscript->GetAI = &GetAI_boss_Sathrovarr; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_kalec"; - newscript->GetAI = &GetAI_boss_kalec; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "kalecgos_teleporter"; - newscript->pGOHello = &GOkalecgos_teleporter; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp b/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp deleted file mode 100644 index f1c3a769b28..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp +++ /dev/null @@ -1,1408 +0,0 @@ -/* Copyright (C) 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kiljaeden -SD%Complete: 80 -SDComment: Sinister Reflection Model, Armageddon Visual, SAY_KJ_SHADOWSPIKE3, Emote, End Sequence -SDCategory: Sunwell_Plateau -EndScriptData */ - -//TODO rewrite Armageddon - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" -#include - -/*** Speech and sounds***/ -enum Yells -{ - // These are used throughout Sunwell and Magisters(?). Players can hear this while running through the instances. - SAY_KJ_OFFCOMBAT1 = -1580066, - SAY_KJ_OFFCOMBAT2 = -1580067, - SAY_KJ_OFFCOMBAT3 = -1580068, - SAY_KJ_OFFCOMBAT4 = -1580069, - SAY_KJ_OFFCOMBAT5 = -1580070, - - // Encounter speech and sounds - SAY_KJ_EMERGE = -1580071, - SAY_KJ_SLAY1 = -1580072, - SAY_KJ_SLAY2 = -1580073, - SAY_KJ_REFLECTION1 = -1580074, - SAY_KJ_REFLECTION2 = -1580075, - SAY_KJ_DARKNESS1 = -1580076, - SAY_KJ_DARKNESS2 = -1580077, - SAY_KJ_DARKNESS3 = -1580078, - SAY_KJ_PHASE3 = -1580079, - SAY_KJ_PHASE4 = -1580080, - SAY_KJ_PHASE5 = -1580081, - SAY_KJ_DEATH = -1580093, - EMOTE_KJ_DARKNESS = -1580094, - - /*** Kalecgos - Anveena speech at the beginning of Phase 5; Anveena's sacrifice ***/ - SAY_KALECGOS_AWAKEN = -1580082, - SAY_ANVEENA_IMPRISONED = -1580083, - SAY_KALECGOS_LETGO = -1580084, - SAY_ANVEENA_LOST = -1580085, - SAY_KALECGOS_FOCUS = -1580086, - SAY_ANVEENA_KALEC = -1580087, - SAY_KALECGOS_FATE = -1580088, - SAY_ANVEENA_GOODBYE = -1580089, - SAY_KALECGOS_GOODBYE = -1580090, - SAY_KALECGOS_ENCOURAGE = -1580091, - - /*** Kalecgos says throughout the fight ***/ - SAY_KALECGOS_JOIN = -1580092, - SAY_KALEC_ORB_READY1 = -1580095, - SAY_KALEC_ORB_READY2 = -1580096, - SAY_KALEC_ORB_READY3 = -1580097, - SAY_KALEC_ORB_READY4 = -1580098 -}; - -/*** Spells used during the encounter ***/ -enum Spells -{ - /* Hand of the Deceiver's spells and cosmetics */ - SPELL_SHADOW_BOLT_VOLLEY = 45770, // ~30 yard range Shadow Bolt Volley for ~2k(?) damage - SPELL_SHADOW_INFUSION = 45772, // They gain this at 20% - Immunity to Stun/Silence and makes them look angry! - SPELL_FELFIRE_PORTAL = 46875, // Creates a portal that spawns Felfire Fiends (LIVE FOR THE SWARM!1 FOR THE OVERMIND!) - SPELL_SHADOW_CHANNELING = 46757, // Channeling animation out of combat - - /* Volatile Felfire Fiend's spells */ - SPELL_FELFIRE_FISSION = 45779, // Felfire Fiends explode when they die or get close to target. - - /* Kil'Jaeden's spells and cosmetics */ - SPELL_TRANS = 23188, // Surprisingly, this seems to be the right spell.. (Where is it used?) - SPELL_REBIRTH = 44200, // Emerge from the Sunwell - SPELL_SOUL_FLAY = 45442, // 9k Shadow damage over 3 seconds. Spammed throughout all the fight. - SPELL_SOUL_FLAY_SLOW = 47106, - SPELL_LEGION_LIGHTNING = 45664, // Chain Lightning, 4 targets, ~3k Shadow damage, 1.5k mana burn - SPELL_FIRE_BLOOM = 45641, // Places a debuff on 5 raid members, which causes them to deal 2k Fire damage to nearby allies and selves. MIGHT NOT WORK - SPELL_DESTROY_ALL_DRAKES = 46707, // when he use it? - - SPELL_SINISTER_REFLECTION = 45785, // Summon shadow copies of 5 raid members that fight against KJ's enemies//dont work - // 45892 // right one for SPELL_SINISTER_REFLECTION but no EffectScriptEffect - SPELL_COPY_WEAPON = 41055, // } - SPELL_COPY_WEAPON2 = 41054, // } - SPELL_COPY_OFFHAND = 45206, // }- Spells used in Sinister Reflection creation - SPELL_COPY_OFFHAND_WEAPON = 45205, // } - - SPELL_SHADOW_SPIKE = 46680, // Bombard random raid members with Shadow Spikes (Very similar to Void Reaver orbs) - SPELL_FLAME_DART = 45737, // Bombards the raid with flames every 3(?) seconds - SPELL_DARKNESS_OF_A_THOUSAND_SOULS = 46605, // Begins a 8-second channeling, after which he will deal 50'000 damage to the raid - SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE = 45657, - - /* Armageddon spells wrong visual */ - SPELL_ARMAGEDDON_TRIGGER = 45909, // Meteor spell trigger missile should cast Creature on himself - SPELL_ARMAGEDDON_VISUAL = 45911, // Does the hellfire visual to indicate where the meteor missle lands - SPELL_ARMAGEDDON_VISUAL2 = 45914, // Does the light visual to indicate where the meteor missle lands - SPELL_ARMAGEDDON_VISUAL3 = 24207, // This shouldn't correct but same as seen on the movie - SPELL_ARMAGEDDON_SUMMON_TRIGGER = 45921, // Summons the triggers that cast the spells on himself need random target select - SPELL_ARMAGEDDON_DAMAGE = 45915, // This does the area damage - - /* Shield Orb Spells*/ - SPELL_SHADOW_BOLT = 45680, //45679 would be correct but triggers to often //TODO fix console error - - /* Anveena's spells and cosmetics (Or, generally, everything that has "Anveena" in name) */ - SPELL_ANVEENA_PRISON = 46367, // She hovers locked within a bubble - SPELL_ANVEENA_ENERGY_DRAIN = 46410, // Sunwell energy glow animation (Control mob uses this) - SPELL_SACRIFICE_OF_ANVEENA = 46474, // This is cast on Kil'Jaeden when Anveena sacrifices herself into the Sunwell - - /* Sinister Reflection Spells */ - SPELL_SR_CURSE_OF_AGONY = 46190, - SPELL_SR_SHADOW_BOLT = 47076, - - SPELL_SR_EARTH_SHOCK = 47071, - - SPELL_SR_FIREBALL = 47074, - - SPELL_SR_HEMORRHAGE = 45897, - - SPELL_SR_HOLY_SHOCK = 38921, - SPELL_SR_HAMMER_OF_JUSTICE = 37369, - - SPELL_SR_HOLY_SMITE = 47077, - SPELL_SR_RENEW = 47079, - - SPELL_SR_SHOOT = 16496, - SPELL_SR_MULTI_SHOT = 48098, - SPELL_SR_WING_CLIP = 40652, - - SPELL_SR_WHIRLWIND = 17207, - - SPELL_SR_MOONFIRE = 47072, - //SPELL_SR_PLAGU STRIKE = 58843, Dk Spell! - - /*** Other Spells (used by players, etc) ***/ - SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT = 45839, // Possess the blue dragon from the orb to help the raid. - SPELL_ENTROPIUS_BODY = 46819, // Visual for Entropius at the Epilogue - SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated -}; - -/*** Error messages ***/ -#define ERROR_KJ_NOT_SUMMONED "TSCR ERROR: Unable to summon Kil'Jaeden for some reason" - -/*** Others ***/ -#define FLOOR_Z 28.050388 -#define SHIELD_ORB_Z 45.000 - -enum Phase -{ - PHASE_DECEIVERS = 1, // Fight 3 adds - PHASE_NORMAL = 2, // Kil'Jaeden emerges from the sunwell - PHASE_DARKNESS = 3, // At 85%, he gains few abilities; Kalecgos joins the fight - PHASE_ARMAGEDDON = 4, // At 55%, he gains even more abilities - PHASE_SACRIFICE = 5, // At 25%, Anveena sacrifices herself into the Sunwell; at this point he becomes enraged and has *significally* shorter cooldowns. -}; - -//Timers -enum KilJaedenTimers -{ - TIMER_SPEECH = 0, - - //Phase 2 Timer - TIMER_SOUL_FLAY = 1, - TIMER_LEGION_LIGHTNING = 2, - TIMER_FIRE_BLOOM = 3, - TIMER_SUMMON_SHILEDORB = 4, - - //Phase 3 Timer - TIMER_SHADOW_SPIKE = 5, - TIMER_FLAME_DART = 6, - TIMER_DARKNESS = 7, - TIMER_ORBS_EMPOWER = 8, - - //Phase 4 Timer - TIMER_ARMAGEDDON = 9 -}; - -// Locations of the Hand of Deceiver adds -Position DeceiverLocations[3]= -{ - {1682.045, 631.299, 5.936}, - {1684.099, 618.848, 0.589}, - {1694.170, 612.272, 1.416}, -}; - -// Locations, where Shield Orbs will spawn -float ShieldOrbLocations[4][2]= -{ - {1698.900, 627.870}, // middle pont of Sunwell - {12, 3.14}, // First one spawns northeast of KJ - {12, 3.14/0.7}, // Second one spawns southeast - {12, 3.14*3.8} // Third one spawns (?) -}; - -struct Speech -{ - int32 textid; - uint32 pCreature, timer; -}; - -// Timers -static Speech Speeches[]= -{ - //Kil Phase 1 -> Phase 2 - {SAY_KJ_EMERGE, DATA_KILJAEDEN, 0}, - {SAY_KALECGOS_JOIN, DATA_KALECGOS_KJ, 26000}, - //Kil Phase 2 -> Phase 3 - {SAY_KALECGOS_AWAKEN, DATA_KALECGOS_KJ, 10000}, - {SAY_ANVEENA_IMPRISONED, DATA_ANVEENA, 5000}, - {SAY_KJ_PHASE3, DATA_KILJAEDEN, 5000}, - //Kil Phase 3 -> Phase 4 - {SAY_KALECGOS_LETGO, DATA_KALECGOS_KJ, 10000}, - {SAY_ANVEENA_LOST, DATA_ANVEENA, 8000}, - {SAY_KJ_PHASE4, DATA_KILJAEDEN, 7000}, - //Kil Phase 4 -> Phase 5 - {SAY_KALECGOS_FOCUS, DATA_KALECGOS_KJ, 4000}, - {SAY_ANVEENA_KALEC, DATA_ANVEENA, 11000}, - {SAY_KALECGOS_FATE, DATA_KALECGOS_KJ, 2000}, - {SAY_ANVEENA_GOODBYE, DATA_ANVEENA, 6000}, - {SAY_KJ_PHASE5, DATA_KILJAEDEN, 5500}, - - // use in End sequence? - {SAY_KALECGOS_GOODBYE, DATA_KALECGOS_KJ, 12000}, -}; - -//AI for Kalecgos -struct boss_kalecgos_kjAI : public ScriptedAI -{ - boss_kalecgos_kjAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint8 OrbsEmpowered; - uint8 EmpowerCount; - - void Reset() - { - OrbsEmpowered = 0; - EmpowerCount = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setActive(true); - - for (uint8 i = 0; i < 4; ++i) - if (GameObject* pOrb = GetOrb(i)) - pOrb->SetGoType(GAMEOBJECT_TYPE_BUTTON); - } - - GameObject* GetOrb(int32 index) - { - if (!pInstance) - return NULL; - - switch(index) - { - case 0: - return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1)); - case 1: - return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2)); - case 2: - return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3)); - case 3: - return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4)); - } - - return NULL; - } - - void ResetOrbs() - { - me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); - for (uint8 i = 0; i < 4; ++i) - if (GameObject* pOrb = GetOrb(i)) - pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 0); - } - - void EmpowerOrb(bool all) - { - GameObject* pOrbEmpowered = GetOrb(OrbsEmpowered); - if (!pOrbEmpowered) - return; - - if (all) - { - me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); - for (uint8 i = 0; i < 4; ++i) - { - if (GameObject* pOrb = GetOrb(i)) - { - pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); - pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 35); - pOrb->setActive(true); - pOrb->Refresh(); - } - } - DoScriptText(SAY_KALECGOS_ENCOURAGE, me); - } - else - { - if (GameObject* pOrb = GetOrb(urand(0,3))) - { - pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); - pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 35); - pOrb->setActive(true); - pOrb->Refresh(); - - OrbsEmpowered = (OrbsEmpowered+1)%4; - - ++EmpowerCount; - switch(EmpowerCount) - { - case 1: DoScriptText(SAY_KALEC_ORB_READY1, me); break; - case 2: DoScriptText(SAY_KALEC_ORB_READY2, me); break; - case 3: DoScriptText(SAY_KALEC_ORB_READY3, me); break; - case 4: DoScriptText(SAY_KALEC_ORB_READY4, me); break; - } - } - } - } - - void UpdateAI(const uint32 diff) - { - } - - void SetRingOfBlueFlames() - { - me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); - for (uint8 i = 0; i < 4; ++i) - { - if (GameObject* pOrb = GetOrb(i)) - { - if (pOrb->GetUInt32Value(GAMEOBJECT_FACTION) == 35) - { - pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); - pOrb->setActive(true); - pOrb->Refresh(); - } - } - } - } -}; - -CreatureAI* GetAI_boss_kalecgos_kj(Creature* pCreature) -{ - return new boss_kalecgos_kjAI (pCreature); -} - -bool GOHello_go_orb_of_the_blue_flight(Player* pPlayer, GameObject* pGo) -{ - if (pGo->GetUInt32Value(GAMEOBJECT_FACTION) == 35) - { - ScriptedInstance* pInstance = pGo->GetInstanceData(); - pPlayer->SummonCreature(CREATURE_POWER_OF_THE_BLUE_DRAGONFLIGHT, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 121000); - pPlayer->CastSpell(pPlayer, SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT, false); - pGo->SetUInt32Value(GAMEOBJECT_FACTION, 0); - - if (Creature* pKalec = Unit::GetCreature(*pPlayer, pInstance->GetData64(DATA_KALECGOS_KJ))) - CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->SetRingOfBlueFlames(); - - pGo->Refresh(); - } - return true; -} - -//AI for Kil'jaeden Event Controller -struct mob_kiljaeden_controllerAI : public Scripted_NoMovementAI -{ - mob_kiljaeden_controllerAI(Creature* c) : Scripted_NoMovementAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - SummonList summons; - - bool bSummonedDeceivers; - bool bKiljaedenDeath; - - uint32 uiRandomSayTimer; - uint32 phase; - uint8 deceiverDeathCount; - - void InitializeAI() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->addUnitState(UNIT_STAT_STUNNED); - - ScriptedAI::InitializeAI(); - } - - void Reset() - { - phase = PHASE_DECEIVERS; - - if (Creature* pKalecKJ = Unit::GetCreature((*me), pInstance->GetData64(DATA_KALECGOS_KJ))) - CAST_AI(boss_kalecgos_kjAI, pKalecKJ->AI())->ResetOrbs(); - deceiverDeathCount = 0; - bSummonedDeceivers = false; - bKiljaedenDeath = false; - uiRandomSayTimer = 30000; - summons.DespawnAll(); - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - case CREATURE_HAND_OF_THE_DECEIVER: - summoned->CastSpell(summoned, SPELL_SHADOW_CHANNELING, false); - break; - case CREATURE_ANVEENA: - summoned->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); - summoned->CastSpell(summoned, SPELL_ANVEENA_PRISON, true); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - break; - case CREATURE_KILJAEDEN: - summoned->CastSpell(summoned, SPELL_REBIRTH, false); - summoned->AddThreat(me->getVictim(), 1.0f); - break; - } - summons.Summon(summoned); - } - - void UpdateAI(const uint32 diff) - { - if (uiRandomSayTimer < diff) - { - if (pInstance && pInstance->GetData(DATA_MURU_EVENT) != DONE && pInstance->GetData(DATA_KILJAEDEN_EVENT) == NOT_STARTED) - DoScriptText(RAND(SAY_KJ_OFFCOMBAT1,SAY_KJ_OFFCOMBAT2,SAY_KJ_OFFCOMBAT3,SAY_KJ_OFFCOMBAT4,SAY_KJ_OFFCOMBAT5), me); - uiRandomSayTimer = 30000; - } else uiRandomSayTimer -= diff; - - if (!bSummonedDeceivers) - { - for (uint8 i = 0; i < 3; ++i) - me->SummonCreature(CREATURE_HAND_OF_THE_DECEIVER, DeceiverLocations[i], TEMPSUMMON_DEAD_DESPAWN, 0); - - DoSpawnCreature(CREATURE_ANVEENA, 0, 0, 40, 0, TEMPSUMMON_DEAD_DESPAWN, 0); - DoCast(me, SPELL_ANVEENA_ENERGY_DRAIN); - bSummonedDeceivers = true; - } - - if (deceiverDeathCount > 2 && phase == PHASE_DECEIVERS) - { - me->RemoveAurasDueToSpell(SPELL_ANVEENA_ENERGY_DRAIN); - phase = PHASE_NORMAL; - DoSpawnCreature(CREATURE_KILJAEDEN, 0, 0,0, 0, TEMPSUMMON_MANUAL_DESPAWN, 0); - } - } -}; - -CreatureAI* GetAI_mob_kiljaeden_controller(Creature* pCreature) -{ - return new mob_kiljaeden_controllerAI (pCreature); -} - -//AI for Kil'jaeden -struct boss_kiljaedenAI : public Scripted_NoMovementAI -{ - boss_kiljaedenAI(Creature* c) : Scripted_NoMovementAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - SummonList summons; - - uint8 Phase; - uint8 ActiveTimers; - uint32 SpeechTimer; - - uint32 Timer[10]; - uint32 WaitTimer; - uint8 speechCount; - uint8 speechPhaseEnd; - - /* Boolean */ - bool IsInDarkness; - bool TimerIsDeactivated[10]; - bool IsWaiting; - bool OrbActivated; - bool SpeechBegins; - - void InitializeAI() - { - Scripted_NoMovementAI::InitializeAI(); - } - - void Reset() - { - TimerIsDeactivated[TIMER_SPEECH] = false; - Timer[TIMER_SPEECH] = 0; - - //Phase 2 Timer - Timer[TIMER_SOUL_FLAY] = 11000; - Timer[TIMER_LEGION_LIGHTNING] = 30000; - Timer[TIMER_FIRE_BLOOM] = 20000; - Timer[TIMER_SUMMON_SHILEDORB] = 35000; - - //Phase 3 Timer - Timer[TIMER_SHADOW_SPIKE] = 4000; - Timer[TIMER_FLAME_DART] = 3000; - Timer[TIMER_DARKNESS] = 45000; - Timer[TIMER_ORBS_EMPOWER] = 35000; - - //Phase 4 Timer - Timer[TIMER_ARMAGEDDON] = 2000; - - ActiveTimers = 5; - WaitTimer = 0; - speechCount = 0; - SpeechTimer = 0; - - Phase = PHASE_NORMAL; - - IsInDarkness = false; - IsWaiting = false; - OrbActivated = false; - SpeechBegins = true; - - if (pInstance) - { - if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ))) - pKalec->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); - } - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 12); - ChangeTimers(false, 0); - summons.DespawnAll(); - } - - void ChangeTimers(bool status, uint32 WTimer) - { - for (uint8 i = 1; i < ActiveTimers; ++i) - TimerIsDeactivated[i] = status; - - if (WTimer > 0) - { - IsWaiting = true; - WaitTimer = WTimer; - } - - if (OrbActivated) - TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true; - if (Timer[TIMER_SHADOW_SPIKE] == 0) - TimerIsDeactivated[TIMER_SHADOW_SPIKE] = true; - if (Phase == PHASE_SACRIFICE) - TimerIsDeactivated[TIMER_SUMMON_SHILEDORB] = true; - } - - void JustSummoned(Creature* summoned) - { - if (summoned->GetEntry() == CREATURE_ARMAGEDDON_TARGET) - { - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - // summoned->SetVisibility(VISIBILITY_OFF); //with this we cant see the armageddon visuals - } - else - summoned->SetLevel(me->getLevel()); - - summoned->setFaction(me->getFaction()); - summons.Summon(summoned); - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_KJ_DEATH, me); - summons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_KILJAEDEN_EVENT, DONE); - } - - void KilledUnit(Unit* victim) - { - DoScriptText(RAND(SAY_KJ_SLAY1,SAY_KJ_SLAY2), me); - } - - void EnterEvadeMode() - { - Scripted_NoMovementAI::EnterEvadeMode(); - summons.DespawnAll(); - - // Reset the controller - if (pInstance) - { - if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) - CAST_AI(mob_kiljaeden_controllerAI, pControl->AI())->Reset(); - } - } - - void EnterCombat(Unit* who) - { - DoZoneInCombat(); - } - - void EnterNextPhase() - { - SpeechBegins = true; - OrbActivated = false; - ChangeTimers(true, 0);//stop every cast Shadow spike will reactivate em all - TimerIsDeactivated[TIMER_SHADOW_SPIKE] = false; - Timer[TIMER_SHADOW_SPIKE] = 100; - // empowered orbs before darkness - Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(10000,40000); - Timer[TIMER_ORBS_EMPOWER] = (Phase == PHASE_SACRIFICE) ? 10000 : 5000; - } - - void CastSinisterReflection() - { - DoScriptText(RAND(SAY_KJ_REFLECTION1,SAY_KJ_REFLECTION2), me); - for (uint8 i = 0; i < 4; ++i) - { - float x,y,z; - Unit *pTarget; - for (uint8 z = 0; z < 6; ++z) - { - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0))break; - } - if (pTarget) - { - pTarget->GetPosition(x,y,z); - if (Creature* pSinisterReflection = me->SummonCreature(CREATURE_SINISTER_REFLECTION, x,y,z,0, TEMPSUMMON_CORPSE_DESPAWN, 0)) - { - pSinisterReflection->SetDisplayId(pTarget->GetDisplayId()); - pSinisterReflection->AI()->AttackStart(pTarget); - } - } - } - } - - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim() || Phase < PHASE_NORMAL) - return; - - if (IsWaiting) - { - if (WaitTimer <= diff) - { - IsWaiting = false; - ChangeTimers(false, 0); - } else WaitTimer -= diff; - } - - for (uint8 t = 0; t < ActiveTimers; ++t) - { - if (Timer[t] < diff && !TimerIsDeactivated[t]) - { - switch(t) - { - case TIMER_SPEECH: - if (SpeechBegins) - { - SpeechBegins=false; - switch(Phase) - { - case PHASE_NORMAL: - speechPhaseEnd=1; - break; - case PHASE_DARKNESS: - speechPhaseEnd=4; - break; - case PHASE_ARMAGEDDON: - speechPhaseEnd=7; - break; - case PHASE_SACRIFICE: - speechPhaseEnd=12; - break; - } - } - if (Speeches[speechCount].timer < SpeechTimer) - { - SpeechTimer = 0; - if (Creature* pSpeechCreature = Unit::GetCreature(*me, pInstance->GetData64(Speeches[speechCount].pCreature))) - DoScriptText(Speeches[speechCount].textid, pSpeechCreature); - if (speechCount == 12) - if (Creature* pAnveena = Unit::GetCreature(*me, pInstance->GetData64(DATA_ANVEENA))) - pAnveena->CastSpell(me, SPELL_SACRIFICE_OF_ANVEENA, false); - // ChangeTimers(true, 10000); // Kil should do an emote while screaming without attacking for 10 seconds - if (speechCount == speechPhaseEnd) - TimerIsDeactivated[TIMER_SPEECH]=true; - speechCount++; - } - SpeechTimer += diff; - break; - case TIMER_SOUL_FLAY: - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me->getVictim(), SPELL_SOUL_FLAY_SLOW, false); - DoCast(me->getVictim(), SPELL_SOUL_FLAY, false); - Timer[TIMER_SOUL_FLAY] = 3500; - } - break; - case TIMER_LEGION_LIGHTNING: - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit* pRandomPlayer; - - me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY); - for (uint8 z = 0; z < 6; ++z) - { - pRandomPlayer = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!pRandomPlayer->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) - break; - } - - if (pRandomPlayer) - DoCast(pRandomPlayer, SPELL_LEGION_LIGHTNING, false); - else - error_log("try to cast SPELL_LEGION_LIGHTNING on invalid target"); - - Timer[TIMER_LEGION_LIGHTNING] = (Phase == PHASE_SACRIFICE) ? 18000 : 30000; // 18 seconds in PHASE_SACRIFICE - Timer[TIMER_SOUL_FLAY] = 2500; - } - break; - case TIMER_FIRE_BLOOM: - if (!me->IsNonMeleeSpellCasted(false)) - { - me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY); - DoCastAOE(SPELL_FIRE_BLOOM, false); - Timer[TIMER_FIRE_BLOOM] = (Phase == PHASE_SACRIFICE) ? 25000 : 40000; // 25 seconds in PHASE_SACRIFICE - Timer[TIMER_SOUL_FLAY] = 1000; - } - break; - case TIMER_SUMMON_SHILEDORB: - for (uint8 i = 1; i < Phase; ++i) - { - float sx, sy; - sx = ShieldOrbLocations[0][0] + sin(ShieldOrbLocations[i][0]); - sy = ShieldOrbLocations[0][1] + sin(ShieldOrbLocations[i][1]); - me->SummonCreature(CREATURE_SHIELD_ORB, sx, sy, SHIELD_ORB_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); - } - Timer[TIMER_SUMMON_SHILEDORB] = urand(30000,60000); // 30-60seconds cooldown - Timer[TIMER_SOUL_FLAY] = 2000; - break; - case TIMER_SHADOW_SPIKE: //Phase 3 - if (!me->IsNonMeleeSpellCasted(false)) - { - CastSinisterReflection(); - DoCastAOE(SPELL_SHADOW_SPIKE, false); - ChangeTimers(true, 30000); - Timer[TIMER_SHADOW_SPIKE] = 0; - TimerIsDeactivated[TIMER_SPEECH] = false; - } - break; - case TIMER_FLAME_DART: //Phase 3 - DoCastAOE(SPELL_FLAME_DART, false); - Timer[TIMER_FLAME_DART] = 3000; //TODO Timer - break; - case TIMER_DARKNESS: //Phase 3 - if (!me->IsNonMeleeSpellCasted(false)) - { - // Begins to channel for 8 seconds, then deals 50'000 damage to all raid members. - if (!IsInDarkness) - { - DoScriptText(EMOTE_KJ_DARKNESS, me); - DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS, false); - ChangeTimers(true, 9000); - Timer[TIMER_DARKNESS] = 8750; - TimerIsDeactivated[TIMER_DARKNESS] = false; - if (Phase == PHASE_SACRIFICE) - TimerIsDeactivated[TIMER_ARMAGEDDON] = false; - IsInDarkness = true; - } - else - { - Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(40000,70000); - IsInDarkness = false; - DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE); - DoScriptText(RAND(SAY_KJ_DARKNESS1,SAY_KJ_DARKNESS2,SAY_KJ_DARKNESS3), me); - } - Timer[TIMER_SOUL_FLAY] = 9000; - } - break; - case TIMER_ORBS_EMPOWER: //Phase 3 - if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ))) - { - switch (Phase) - { - case PHASE_SACRIFICE: - CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(true); - break; - default: - CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(false); - break; - } - } - OrbActivated = true; - TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true; - break; - case TIMER_ARMAGEDDON: //Phase 4 - Unit *pTarget; - for (uint8 z = 0; z < 6; ++z) - { - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break; - } - if (pTarget) - { - float x, y, z; - pTarget->GetPosition(x, y, z); - me->SummonCreature(CREATURE_ARMAGEDDON_TARGET, x,y,z,0, TEMPSUMMON_TIMED_DESPAWN,15000); - } - Timer[TIMER_ARMAGEDDON] = 2000; // No, I'm not kidding - break; - } - } - } - DoMeleeAttackIfReady(); - //Time runs over! - for (uint8 i = 0; i < ActiveTimers; ++i) - if (!TimerIsDeactivated[i]) - { - Timer[i] -= diff; - if (((int32)Timer[i]) < 0) Timer[i] = 0; - } - - //Phase 3 - if (Phase <= PHASE_NORMAL && !IsInDarkness) - { - if (Phase == PHASE_NORMAL && HealthBelowPct(85)) - { - Phase = PHASE_DARKNESS; - ActiveTimers = 9; - EnterNextPhase(); - } - else return; - } - - //Phase 4 - if (Phase <= PHASE_DARKNESS && !IsInDarkness) - { - if (Phase == PHASE_DARKNESS && HealthBelowPct(55)) - { - Phase = PHASE_ARMAGEDDON; - ActiveTimers = 10; - EnterNextPhase(); - } - else return; - } - - //Phase 5 specific spells all we can - if (Phase <= PHASE_ARMAGEDDON && !IsInDarkness) - { - if (Phase == PHASE_ARMAGEDDON && HealthBelowPct(25)) - { - Phase = PHASE_SACRIFICE; - EnterNextPhase(); - } - else return; - } - } -}; - -CreatureAI* GetAI_boss_kiljaeden(Creature* pCreature) -{ - return new boss_kiljaedenAI (pCreature); -} - -//AI for Hand of the Deceiver -struct mob_hand_of_the_deceiverAI : public ScriptedAI -{ - mob_hand_of_the_deceiverAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ShadowBoltVolleyTimer; - uint32 FelfirePortalTimer; - - void Reset() - { - // TODO: Timers! - ShadowBoltVolleyTimer = urand(8000,14000); // So they don't all cast it in the same moment. - FelfirePortalTimer = 20000; - if (pInstance) - pInstance->SetData(DATA_KILJAEDEN_EVENT, NOT_STARTED); - } - - void JustSummoned(Creature* summoned) - { - summoned->setFaction(me->getFaction()); - summoned->SetLevel(me->getLevel()); - } - - void EnterCombat(Unit* who) - { - if (pInstance) - { - pInstance->SetData(DATA_KILJAEDEN_EVENT, IN_PROGRESS); - if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) - pControl->AddThreat(who, 1.0f); - } - me->InterruptNonMeleeSpells(true); - } - - void JustDied(Unit* killer) - { - if (!pInstance) - return; - - if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) - ++(CAST_AI(mob_kiljaeden_controllerAI, pControl->AI())->deceiverDeathCount); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - DoCast(me, SPELL_SHADOW_CHANNELING); - - if (!UpdateVictim()) - return; - - // Gain Shadow Infusion at 20% health - if (HealthBelowPct(20) && !me->HasAura(SPELL_SHADOW_INFUSION, 0)) - DoCast(me, SPELL_SHADOW_INFUSION, true); - - // Shadow Bolt Volley - Shoots Shadow Bolts at all enemies within 30 yards, for ~2k Shadow damage. - if (ShadowBoltVolleyTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); - ShadowBoltVolleyTimer = 12000; - } - else - ShadowBoltVolleyTimer -= diff; - - // Felfire Portal - Creatres a portal, that spawns Volatile Felfire Fiends, which do suicide bombing. - if (FelfirePortalTimer <= diff) - { - if (Creature* pPortal = DoSpawnCreature(CREATURE_FELFIRE_PORTAL, 0, 0,0, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) - { - std::list::iterator itr; - for (itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) - { - Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pUnit) - pPortal->AddThreat(pUnit, 1.0f); - } - } - FelfirePortalTimer = 20000; - } else FelfirePortalTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_hand_of_the_deceiver(Creature* pCreature) -{ - return new mob_hand_of_the_deceiverAI (pCreature); -} - -//AI for Felfire Portal -struct mob_felfire_portalAI : public Scripted_NoMovementAI -{ - mob_felfire_portalAI(Creature* c) : Scripted_NoMovementAI(c) {} - - uint32 uiSpawnFiendTimer; - - void Reset() - { - uiSpawnFiendTimer = 5000; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); - } - - void JustSummoned(Creature* summoned) - { - summoned->setFaction(me->getFaction()); - summoned->SetLevel(me->getLevel()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiSpawnFiendTimer <= diff) - { - if (Creature* pFiend = DoSpawnCreature(CREATURE_VOLATILE_FELFIRE_FIEND, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) - pFiend->AddThreat(SelectUnit(SELECT_TARGET_RANDOM,0), 100000.0f); - uiSpawnFiendTimer = urand(4000,8000); - } else uiSpawnFiendTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_felfire_portal(Creature* pCreature) -{ - return new mob_felfire_portalAI (pCreature); -} - -//AI for Felfire Fiend -struct mob_volatile_felfire_fiendAI : public ScriptedAI -{ - mob_volatile_felfire_fiendAI(Creature* c) : ScriptedAI(c) {} - - uint32 uiExplodeTimer; - - bool bLockedTarget; - - void Reset() - { - uiExplodeTimer = 2000; - bLockedTarget = false; - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage > me->GetHealth()) - DoCast(me, SPELL_FELFIRE_FISSION, true); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!bLockedTarget) - { - me->AddThreat(me->getVictim(), 10000000.0f); - bLockedTarget = true; - } - - if (uiExplodeTimer) - { - if (uiExplodeTimer <= diff) - uiExplodeTimer = 0; - else uiExplodeTimer -= diff; - } - else if (me->IsWithinDistInMap(me->getVictim(), 3)) // Explode if it's close enough to it's target - { - DoCast(me->getVictim(), SPELL_FELFIRE_FISSION); - me->Kill(me); - } - } -}; - -CreatureAI* GetAI_mob_volatile_felfire_fiend(Creature* pCreature) -{ - return new mob_volatile_felfire_fiendAI (pCreature); -} - -//AI for Armageddon target -struct mob_armageddonAI : public Scripted_NoMovementAI -{ - mob_armageddonAI(Creature* c) : Scripted_NoMovementAI(c) {} - - uint8 spell; - uint32 uiTimer; - - void Reset() - { - spell = 0; - uiTimer = 0; - } - - void UpdateAI(const uint32 diff) - { - if (uiTimer <= diff) - { - switch(spell) - { - case 0: - DoCast(me, SPELL_ARMAGEDDON_VISUAL, true); - ++spell; - break; - case 1: - DoCast(me, SPELL_ARMAGEDDON_VISUAL2, true); - uiTimer = 9000; - ++spell; - break; - case 2: - DoCast(me, SPELL_ARMAGEDDON_TRIGGER, true); - ++spell; - uiTimer = 5000; - break; - case 3: - me->Kill(me); - me->RemoveCorpse(); - break; - } - } else uiTimer -=diff; - } -}; - -CreatureAI* GetAI_mob_armageddon(Creature* pCreature) -{ - return new mob_armageddonAI (pCreature); -} - -//AI for Shield Orbs -struct mob_shield_orbAI : public ScriptedAI -{ - mob_shield_orbAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bPointReached; - bool bClockwise; - uint32 uiTimer; - uint32 uiCheckTimer; - float x, y, r, c, mx, my; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - bPointReached = true; - uiTimer = urand(500,1000); - uiCheckTimer = 1000; - r = 17; - c = 0; - mx = ShieldOrbLocations[0][0]; - my = ShieldOrbLocations[0][1]; - bClockwise = urand(0,1); - } - - void UpdateAI(const uint32 diff) - { - if (bPointReached) - { - if (bClockwise) - { - y = my - r * sin(c); - x = mx - r * cos(c); - } - else - { - y = my + r * sin(c); - x = mx + r * cos(c); - } - bPointReached = false; - uiCheckTimer = 1000; - me->GetMotionMaster()->MovePoint(1,x, y, SHIELD_ORB_Z); - c += M_PI/32; - if (c >= 2*M_PI) c = 0; - } - else - { - if (uiCheckTimer <= diff) - { - DoTeleportTo(x,y,SHIELD_ORB_Z); - bPointReached = true; - } - else uiCheckTimer -= diff; - } - - if (uiTimer <= diff) - { - if (Unit* random = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0)) - DoCast(random, SPELL_SHADOW_BOLT, false); - uiTimer = urand(500,1000); - } else uiTimer -= diff; - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - bPointReached = true; - } -}; - -CreatureAI* GetAI_mob_shield_orb(Creature* pCreature) -{ - return new mob_shield_orbAI (pCreature); -} - -//AI for Sinister Reflection -struct mob_sinster_reflectionAI : public ScriptedAI -{ - mob_sinster_reflectionAI(Creature* c) : ScriptedAI(c) {} - - uint8 victimClass; - uint32 uiTimer[3]; - - void Reset() - { - uiTimer[0] = 0; - uiTimer[1] = 0; - uiTimer[2] = 0; - victimClass = 0; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if ((victimClass == 0) && me->getVictim()) - { - victimClass = me->getVictim()->getClass(); - switch (victimClass) - { - case CLASS_DRUID: - break; - case CLASS_HUNTER: - break; - case CLASS_MAGE: - break; - case CLASS_WARLOCK: - break; - case CLASS_WARRIOR: - me->SetCanDualWield(true); - break; - case CLASS_PALADIN: - break; - case CLASS_PRIEST: - break; - case CLASS_SHAMAN: - me->SetCanDualWield(true); - break; - case CLASS_ROGUE: - me->SetCanDualWield(true); - break; - } - } - - switch(victimClass) { - case CLASS_DRUID: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_MOONFIRE, false); - uiTimer[1] = urand(2000,4000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_HUNTER: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_MULTI_SHOT, false); - uiTimer[1] = urand(8000,10000); - } - if (uiTimer[2] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_SHOOT, false); - uiTimer[2] = urand(4000,6000); - } - if (me->IsWithinMeleeRange(me->getVictim(), 6)) - { - if (uiTimer[0] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_MULTI_SHOT, false); - uiTimer[0] = urand(6000,8000); - } - DoMeleeAttackIfReady(); - } - break; - case CLASS_MAGE: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_FIREBALL, false); - uiTimer[1] = urand(2000,4000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_WARLOCK: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_SHADOW_BOLT, false); - uiTimer[1] = urand(3000,5000); - } - if (uiTimer[2] <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_SR_CURSE_OF_AGONY, true); - uiTimer[2] = urand(2000,4000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_WARRIOR: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_WHIRLWIND, false); - uiTimer[1] = urand(9000,11000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_PALADIN: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_HAMMER_OF_JUSTICE, false); - uiTimer[1] = urand(6000,8000); - } - if (uiTimer[2] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_HOLY_SHOCK, false); - uiTimer[2] = urand(2000,4000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_PRIEST: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_HOLY_SMITE, false); - uiTimer[1] = urand(4000,6000); - } - if (uiTimer[2] <= diff) - { - DoCast(me, SPELL_SR_RENEW, false); - uiTimer[2] = urand(6000,8000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_SHAMAN: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_EARTH_SHOCK, false); - uiTimer[1] = urand(4000,6000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_ROGUE: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_HEMORRHAGE, true); - uiTimer[1] = urand(4000,6000); - } - DoMeleeAttackIfReady(); - break; - } - debug_log("Sinister-Timer"); - for (uint8 i = 0; i < 3; ++i) - uiTimer[i] -= diff; - } -}; - -CreatureAI* GetAI_mob_sinster_reflection(Creature* pCreature) -{ - return new mob_sinster_reflectionAI (pCreature); -} - -void AddSC_boss_kiljaeden() -{ - Script* newscript; - - newscript = new Script; - newscript->pGOHello = &GOHello_go_orb_of_the_blue_flight; - newscript->Name = "go_orb_of_the_blue_flight"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_kalecgos_kj; - newscript->Name = "boss_kalecgos_kj"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_kiljaeden; - newscript->Name = "boss_kiljaeden"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_kiljaeden_controller; - newscript->Name = "mob_kiljaeden_controller"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_hand_of_the_deceiver; - newscript->Name = "mob_hand_of_the_deceiver"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_felfire_portal; - newscript->Name = "mob_felfire_portal"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_volatile_felfire_fiend; - newscript->Name = "mob_volatile_felfire_fiend"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_armageddon; - newscript->Name = "mob_armageddon"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_shield_orb; - newscript->Name = "mob_shield_orb"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_sinster_reflection; - newscript->Name = "mob_sinster_reflection"; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp b/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp deleted file mode 100644 index 9dca453ade6..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp +++ /dev/null @@ -1,640 +0,0 @@ -/* Copyright (C) 2009 Trinity -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Muru -SD%Complete: 80 -SDComment: all sounds, black hole effect triggers to often (46228) -*/ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -// Muru & Entropius's spells -enum Spells -{ - SPELL_ENRAGE = 26662, - - // Muru's spells - SPELL_NEGATIVE_ENERGY = 46009, //(this trigger 46008) - SPELL_DARKNESS = 45999, - SPELL_OPEN_ALL_PORTALS = 46177, - SPELL_OPEN_PORTAL = 45977, - SPELL_OPEN_PORTAL_2 = 45976, - SPELL_SUMMON_BERSERKER = 46037, - SPELL_SUMNON_FURY_MAGE = 46038, - SPELL_SUMMON_VOID_SENTINEL = 45988, - SPELL_SUMMON_ENTROPIUS = 46217, - - // Entropius's spells - SPELL_DARKNESS_E = 46269, - SPELL_BLACKHOLE = 46282, - SPELL_NEGATIVE_ENERGY_E = 46284, - SPELL_ENTROPIUS_SPAWN = 46223, - - // Shadowsword Berserker's spells - SPELL_FLURRY = 46160, - SPELL_DUAL_WIELD = 29651, - - // Shadowsword Fury Mage's spells - SPELL_FEL_FIREBALL = 46101, - SPELL_SPELL_FURY = 46102, - - // Void Sentinel's spells - SPELL_SHADOW_PULSE = 46087, - SPELL_VOID_BLAST = 46161, - - // Void Spawn's spells - SPELL_SHADOW_BOLT_VOLLEY = 46082, - - //Dark Fiend Spells - SPELL_DARKFIEND_AOE = 45944, - SPELL_DARKFIEND_VISUAL = 45936, - SPELL_DARKFIEND_SKIN = 45934, - - //Black Hole Spells - SPELL_BLACKHOLE_SPAWN = 46242, - SPELL_BLACKHOLE_GROW = 46228 -}; - -enum BossTimers{ - TIMER_DARKNESS = 0, - TIMER_HUMANOIDES = 1, - TIMER_PHASE = 2, - TIMER_SENTINEL = 3 -}; - -float DarkFiends[8][4] = -{ - {1819.9, 609.80, 69.74, 1.94}, - {1829.39, 617.89, 69.73, 2.61}, - {1801.98, 633.62, 69.74, 5.71}, - {1830.88, 629.99, 69.73, 3.52}, - {1800.38, 621.41, 69.74, 0.22}, - {1808.3 , 612.45, 69.73, 1.02}, - {1823.9 , 639.69, 69.74, 4.12}, - {1811.85, 640.46, 69.73, 4.97} -}; - -float Humanoides[6][5] = -{ - {CREATURE_FURY_MAGE, 1780.16, 666.83, 71.19, 5.21}, - {CREATURE_FURY_MAGE, 1847.93, 600.30, 71.30, 2.57}, - {CREATURE_BERSERKER, 1779.97, 660.64, 71.19, 5.28}, - {CREATURE_BERSERKER, 1786.2 , 661.01, 71.19, 4.51}, - {CREATURE_BERSERKER, 1845.17, 602.63, 71.28, 2.43}, - {CREATURE_BERSERKER, 1842.91, 599.93, 71.23, 2.44} -}; - -uint32 EnrageTimer = 600000; -struct boss_entropiusAI : public ScriptedAI -{ - boss_entropiusAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - SummonList Summons; - - uint32 BlackHoleSummonTimer; - - void Reset() - { - BlackHoleSummonTimer = 15000; - DoCastAOE(SPELL_NEGATIVE_ENERGY_E, false); - - Summons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoCastAOE(SPELL_NEGATIVE_ENERGY_E, true); - DoCast(me, SPELL_ENTROPIUS_SPAWN, false); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - case CREATURE_DARK_FIENDS: - summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false); - break; - case CREATURE_DARKNESS: - summoned->addUnitState(UNIT_STAT_STUNNED); - float x,y,z,o; - summoned->GetHomePosition(x,y,z,o); - me->SummonCreature(CREATURE_DARK_FIENDS, x,y,z,o, TEMPSUMMON_CORPSE_DESPAWN, 0); - break; - } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); - Summons.Summon(summoned); - } - - void JustDied(Unit* /*killer*/) - { - Summons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (EnrageTimer < diff && !me->HasAura(SPELL_ENRAGE, 0)) - { - DoCast(me, SPELL_ENRAGE, false); - } else EnrageTimer -= diff; - - if (BlackHoleSummonTimer <= diff) - { - Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!random) - return; - - DoCast(random, SPELL_DARKNESS_E, false); - - random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!random) - return; - - random->CastSpell(random, SPELL_BLACKHOLE, false); - BlackHoleSummonTimer = 15000; - } else BlackHoleSummonTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_entropius(Creature* pCreature) -{ - return new boss_entropiusAI (pCreature); -} - -struct boss_muruAI : public Scripted_NoMovementAI -{ - boss_muruAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - SummonList Summons; - - uint8 Phase; - uint32 Timer[4]; - - bool DarkFiend; - - void Reset() - { - DarkFiend = false; - Phase = 1; - - EnrageTimer = 600000; - Timer[TIMER_DARKNESS] = 45000; - Timer[TIMER_HUMANOIDES] = 10000; - Timer[TIMER_PHASE] = 2000; - Timer[TIMER_SENTINEL] = 31500; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - Summons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoCastAOE(SPELL_NEGATIVE_ENERGY,false); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, IN_PROGRESS); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage > me->GetHealth() && Phase == 1) - { - damage = 0; - Phase = 2; - me->RemoveAllAuras(); - DoCast(me, SPELL_OPEN_ALL_PORTALS, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - if (Phase > 1 && Phase < 4) - damage = 0; - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - case BOSS_ENTROPIUS: - me->SetVisibility(VISIBILITY_OFF); - break; - case CREATURE_DARK_FIENDS: - summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false); - break; - } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); - Summons.Summon(summoned); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Phase == 3) - { - if (Timer[TIMER_PHASE] <= diff) - { - if (!pInstance) - return; - switch(pInstance->GetData(DATA_MURU_EVENT)) - { - case NOT_STARTED: - Reset(); - break; - case DONE: - Phase = 4; - me->DisappearAndDie(); - break; - } - Timer[TIMER_PHASE] = 3000; - } else Timer[TIMER_PHASE] -= diff; - return; - } - - if (EnrageTimer < diff && !me->HasAura(SPELL_ENRAGE, 0)) - { - DoCast(me, SPELL_ENRAGE, false); - } else EnrageTimer -= diff; - - for (uint8 i = 0; i < 4; ++i) - { - if (Timer[i] <= diff) - { - switch(i) - { - case TIMER_DARKNESS: - if (!DarkFiend) - { - DoCastAOE(SPELL_DARKNESS, false); - Timer[TIMER_DARKNESS] = 3000; - DarkFiend = true; - } - else - { - DarkFiend = false; - for (uint8 i = 0; i < 8; ++i) - me->SummonCreature(CREATURE_DARK_FIENDS,DarkFiends[i][0],DarkFiends[i][1],DarkFiends[i][2], DarkFiends[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); - Timer[TIMER_DARKNESS] = 42000; - } - break; - case TIMER_HUMANOIDES: - for (uint8 i = 0; i < 6; ++i) - me->SummonCreature(Humanoides[i][0],Humanoides[i][1],Humanoides[i][2],Humanoides[i][3], Humanoides[i][4], TEMPSUMMON_CORPSE_DESPAWN, 0); - Timer[TIMER_HUMANOIDES] = 60000; - break; - case TIMER_PHASE: - me->RemoveAllAuras(); - DoCast(me, SPELL_SUMMON_ENTROPIUS, false); - Timer[TIMER_PHASE] = 3000; - Phase = 3; - return; - case TIMER_SENTINEL: - DoCastAOE(SPELL_OPEN_PORTAL_2, false); - Timer[TIMER_SENTINEL] = 30000; - break; - } - break; - } - } - - //Timer - for (uint8 i = 0; i < 4; ++i) - { - if (i != TIMER_PHASE)Timer[i] -= diff; - else if (Phase == 2) Timer[i] -= diff; - } - } -}; - -CreatureAI* GetAI_boss_muru(Creature* pCreature) -{ - return new boss_muruAI (pCreature); -} - -struct npc_muru_portalAI : public Scripted_NoMovementAI -{ - npc_muru_portalAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - SummonList Summons; - - bool SummonSentinel; - bool InAction; - - uint32 SummonTimer; - - void Reset() - { - SummonTimer = 5000; - - InAction = false; - SummonSentinel = false; - - me->addUnitState(UNIT_STAT_STUNNED); - - Summons.DespawnAll(); - } - - void JustSummoned(Creature* summoned) - { - if (pInstance) - if (Player* Target = Unit::GetPlayer(pInstance->GetData64(DATA_PLAYER_GUID))) - summoned->AI()->AttackStart(Target); - - Summons.Summon(summoned); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry* Spell) - { - float x,y,z,o; - me->GetHomePosition(x,y,z,o); - DoTeleportTo(x,y,z); - InAction = true; - switch(Spell->Id) - { - case SPELL_OPEN_ALL_PORTALS: - DoCastAOE(SPELL_OPEN_PORTAL, false); - break; - case SPELL_OPEN_PORTAL_2: - DoCastAOE(SPELL_OPEN_PORTAL, false); - SummonSentinel = true; - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!SummonSentinel) - { - if (InAction && pInstance && pInstance->GetData(DATA_MURU_EVENT) == NOT_STARTED) - Reset(); - return; - } - if (SummonTimer <= diff) - { - DoCastAOE(SPELL_SUMMON_VOID_SENTINEL, false); - SummonTimer = 5000; - SummonSentinel = false; - } else SummonTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_muru_portal(Creature* pCreature) -{ - return new npc_muru_portalAI (pCreature); -} - -struct npc_dark_fiendAI : public ScriptedAI -{ - npc_dark_fiendAI(Creature *c) : ScriptedAI(c) {} - - uint32 WaitTimer; - bool InAction; - - void Reset() - { - WaitTimer = 2000; - InAction = false; - - me->addUnitState(UNIT_STAT_STUNNED); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry* Spell) - { - for (uint8 i = 0; i < 3; ++i) - if (Spell->Effect[i] == 38) - me->DisappearAndDie(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (WaitTimer <= diff) - { - if (!InAction) - { - me->clearUnitState(UNIT_STAT_STUNNED); - DoCastAOE(SPELL_DARKFIEND_SKIN, false); - AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)); - InAction = true; - WaitTimer = 500; - } - else - { - - if (me->IsWithinDist(me->getVictim(), 5)) - { - DoCastAOE(SPELL_DARKFIEND_AOE, false); - me->DisappearAndDie(); - } - WaitTimer = 500; - } - } else WaitTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_dark_fiend(Creature* pCreature) -{ - return new npc_dark_fiendAI (pCreature); -} - -struct npc_void_sentinelAI : public ScriptedAI -{ - npc_void_sentinelAI(Creature *c) : ScriptedAI(c){} - - uint32 PulseTimer; - uint32 VoidBlastTimer; - - void Reset() - { - PulseTimer = 3000; - VoidBlastTimer = 45000; //is this a correct timer? - - float x,y,z,o; - me->GetHomePosition(x,y,z,o); - DoTeleportTo(x,y,71); - } - - void JustDied(Unit* /*killer*/) - { - for (uint8 i = 0; i < 8; ++i) - me->SummonCreature(CREATURE_VOID_SPAWN, me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(), rand()%6, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (PulseTimer <= diff) - { - DoCastAOE(SPELL_SHADOW_PULSE, true); - PulseTimer = 3000; - } else PulseTimer -= diff; - - if (VoidBlastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_VOID_BLAST, false); - VoidBlastTimer = 45000; - } else VoidBlastTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_void_sentinel(Creature* pCreature) -{ - return new npc_void_sentinelAI (pCreature); -} - -struct npc_blackholeAI : public ScriptedAI -{ - npc_blackholeAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 DespawnTimer; - uint32 SpellTimer; - uint8 Phase; - uint8 NeedForAHack; - - void Reset() - { - DespawnTimer = 15000; - SpellTimer = 5000; - Phase = 0; - - me->addUnitState(UNIT_STAT_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_SPAWN, true); - } - - void UpdateAI(const uint32 diff) - { - if (SpellTimer <= diff) - { - Unit* Victim = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); - switch (NeedForAHack) - { - case 0: - me->clearUnitState(UNIT_STAT_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_GROW, false); - if (Victim) - AttackStart(Victim); - SpellTimer = 700; - NeedForAHack = 2; - break; - case 1: - me->AddAura(SPELL_BLACKHOLE_GROW, me); - NeedForAHack = 2; - SpellTimer = 600; - break; - case 2: - SpellTimer = 400; - NeedForAHack = 3; - me->RemoveAura(SPELL_BLACKHOLE_GROW, 1); - break; - case 3: - SpellTimer = urand(400,900); - NeedForAHack = 1; - if (Unit* Temp = me->getVictim()) - { - if (Temp->GetPositionZ() > 73 && Victim) - AttackStart(Victim); - } else - return; - } - } else SpellTimer -= diff; - - if (DespawnTimer <= diff) - me->DisappearAndDie(); - else DespawnTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_blackhole(Creature* pCreature) -{ - return new npc_blackholeAI (pCreature); -} - -void AddSC_boss_muru() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_muru"; - newscript->GetAI = &GetAI_boss_muru; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_entropius"; - newscript->GetAI = &GetAI_boss_entropius; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_muru_portal"; - newscript->GetAI = &GetAI_npc_muru_portal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dark_fiend"; - newscript->GetAI = &GetAI_npc_dark_fiend; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_void_sentinel"; - newscript->GetAI = &GetAI_npc_void_sentinel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_blackhole"; - newscript->GetAI = &GetAI_npc_blackhole; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp b/src/server/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp deleted file mode 100644 index 94b7bf4b735..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -/* ScriptData -SDName: Instance_Sunwell_Plateau -SD%Complete: 25 -SDComment: VERIFY SCRIPT -SDCategory: Sunwell_Plateau -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -#define MAX_ENCOUNTER 6 - -/* Sunwell Plateau: -0 - Kalecgos and Sathrovarr -1 - Brutallus -2 - Felmyst -3 - Eredar Twins (Alythess and Sacrolash) -4 - M'uru -5 - Kil'Jaeden -*/ - -struct instance_sunwell_plateau : public ScriptedInstance -{ - instance_sunwell_plateau(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - /** Creatures **/ - uint64 Kalecgos_Dragon; - uint64 Kalecgos_Human; - uint64 Sathrovarr; - uint64 Brutallus; - uint64 Madrigosa; - uint64 Felmyst; - uint64 Alythess; - uint64 Sacrolash; - uint64 Muru; - uint64 KilJaeden; - uint64 KilJaedenController; - uint64 Anveena; - uint64 KalecgosKJ; - uint32 SpectralPlayers; - - /** GameObjects **/ - uint64 ForceField; // Kalecgos Encounter - uint64 KalecgosWall[2]; - uint64 FireBarrier; // Felmysts Encounter - uint64 MurusGate[2]; // Murus Encounter - - /*** Misc ***/ - uint32 SpectralRealmTimer; - std::vector SpectralRealmList; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - /*** Creatures ***/ - Kalecgos_Dragon = 0; - Kalecgos_Human = 0; - Sathrovarr = 0; - Brutallus = 0; - Madrigosa = 0; - Felmyst = 0; - Alythess = 0; - Sacrolash = 0; - Muru = 0; - KilJaeden = 0; - KilJaedenController = 0; - Anveena = 0; - KalecgosKJ = 0; - SpectralPlayers = 0; - - /*** GameObjects ***/ - ForceField = 0; - FireBarrier = 0; - MurusGate[0] = 0; - MurusGate[1] = 0; - KalecgosWall[0] = 0; - KalecgosWall[1] = 0; - - /*** Misc ***/ - SpectralRealmTimer = 5000; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* plr = itr->getSource(); - if (plr && !plr->HasAura(45839,0)) - return plr; - } - } - - debug_log("TSCR: Instance Sunwell Plateau: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 24850: Kalecgos_Dragon = pCreature->GetGUID(); break; - case 24891: Kalecgos_Human = pCreature->GetGUID(); break; - case 24892: Sathrovarr = pCreature->GetGUID(); break; - case 24882: Brutallus = pCreature->GetGUID(); break; - case 24895: Madrigosa = pCreature->GetGUID(); break; - case 25038: Felmyst = pCreature->GetGUID(); break; - case 25166: Alythess = pCreature->GetGUID(); break; - case 25165: Sacrolash = pCreature->GetGUID(); break; - case 25741: Muru = pCreature->GetGUID(); break; - case 25315: KilJaeden = pCreature->GetGUID(); break; - case 25608: KilJaedenController = pCreature->GetGUID(); break; - case 26046: Anveena = pCreature->GetGUID(); break; - case 25319: KalecgosKJ = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 188421: ForceField = pGo->GetGUID(); break; - case 188523: KalecgosWall[0] = pGo->GetGUID(); break; - case 188524: KalecgosWall[0] = pGo->GetGUID(); break; - case 188075: - if (m_auiEncounter[2] == DONE) - HandleGameObject(NULL, true, pGo); - FireBarrier = pGo->GetGUID(); - break; - case 187990: MurusGate[0] = pGo->GetGUID(); break; - case 188118: - if (m_auiEncounter[4] == DONE) - HandleGameObject(NULL, true, pGo); - MurusGate[1]= pGo->GetGUID(); - break; - } - } - - uint32 GetData(uint32 id) - { - switch(id) - { - case DATA_KALECGOS_EVENT: return m_auiEncounter[0]; - case DATA_BRUTALLUS_EVENT: return m_auiEncounter[1]; - case DATA_FELMYST_EVENT: return m_auiEncounter[2]; - case DATA_EREDAR_TWINS_EVENT: return m_auiEncounter[3]; - case DATA_MURU_EVENT: return m_auiEncounter[4]; - case DATA_KILJAEDEN_EVENT: return m_auiEncounter[5]; - } - return 0; - } - - uint64 GetData64(uint32 id) - { - switch(id) - { - case DATA_KALECGOS_DRAGON: return Kalecgos_Dragon; - case DATA_KALECGOS_HUMAN: return Kalecgos_Human; - case DATA_SATHROVARR: return Sathrovarr; - case DATA_GO_FORCEFIELD: return ForceField; - case DATA_BRUTALLUS: return Brutallus; - case DATA_MADRIGOSA: return Madrigosa; - case DATA_FELMYST: return Felmyst; - case DATA_ALYTHESS: return Alythess; - case DATA_SACROLASH: return Sacrolash; - case DATA_MURU: return Muru; - case DATA_KILJAEDEN: return KilJaeden; - case DATA_KILJAEDEN_CONTROLLER: return KilJaedenController; - case DATA_ANVEENA: return Anveena; - case DATA_KALECGOS_KJ: return KalecgosKJ; - case DATA_PLAYER_GUID: - Player* Target = GetPlayerInMap(); - return Target->GetGUID(); - } - return 0; - } - - void SetData(uint32 id, uint32 data) - { - switch(id) - { - case DATA_KALECGOS_EVENT: - { - if (data == NOT_STARTED || data == DONE) - { - HandleGameObject(ForceField,true); - HandleGameObject(KalecgosWall[0],true); - HandleGameObject(KalecgosWall[1],true); - } - else if (data == IN_PROGRESS) - { - HandleGameObject(ForceField,false); - HandleGameObject(KalecgosWall[0],false); - HandleGameObject(KalecgosWall[1],false); - } - m_auiEncounter[0] = data; - } - break; - case DATA_BRUTALLUS_EVENT: m_auiEncounter[1] = data; break; - case DATA_FELMYST_EVENT: - if (data == DONE) - HandleGameObject(FireBarrier, true); - m_auiEncounter[2] = data; break; - case DATA_EREDAR_TWINS_EVENT: m_auiEncounter[3] = data; break; - case DATA_MURU_EVENT: - switch(data) - { - case DONE: - HandleGameObject(MurusGate[0], true); - HandleGameObject(MurusGate[1], true); - break; - case IN_PROGRESS: - HandleGameObject(MurusGate[0], false); - HandleGameObject(MurusGate[1], false); - break; - case NOT_STARTED: - HandleGameObject(MurusGate[0], true); - HandleGameObject(MurusGate[1], false); - break; - } - m_auiEncounter[4] = data; break; - case DATA_KILJAEDEN_EVENT: m_auiEncounter[5] = data; break; - } - - if (data == DONE) - SaveToDB(); - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " - << m_auiEncounter[4] << " " << m_auiEncounter[5]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_sunwell_plateau(Map* pMap) -{ - return new instance_sunwell_plateau(pMap); -} - -void AddSC_instance_sunwell_plateau() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_sunwell_plateau"; - newscript->GetInstanceData = &GetInstanceData_instance_sunwell_plateau; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.cpp b/src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.cpp deleted file mode 100644 index dbf67d5f26e..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Sunwell_Plateau -SD%Complete: 0 -SDComment: Placeholder, Epilogue after Kil'jaeden, Captain Selana Gossips -EndScriptData */ - -/* ContentData -npc_prophet_velen -npc_captain_selana -EndContentData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -/*###### -## npc_prophet_velen -######*/ - -enum ProphetSpeeches -{ - PROPHET_SAY1 = -1580099, - PROPHET_SAY2 = -1580100, - PROPHET_SAY3 = -1580101, - PROPHET_SAY4 = -1580102, - PROPHET_SAY5 = -1580103, - PROPHET_SAY6 = -1580104, - PROPHET_SAY7 = -1580105, - PROPHET_SAY8 = -1580106 -}; - -enum LiadrinnSpeeches -{ - LIADRIN_SAY1 = -1580107, - LIADRIN_SAY2 = -1580108, - LIADRIN_SAY3 = -1580109 -}; - -/*###### -## npc_captain_selana -######*/ - -#define CS_GOSSIP1 "Give me a situation report, Captain." -#define CS_GOSSIP2 "What went wrong?" -#define CS_GOSSIP3 "Why did they stop?" -#define CS_GOSSIP4 "Your insight is appreciated." - -void AddSC_sunwell_plateau() -{ -} diff --git a/src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h b/src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h deleted file mode 100644 index 9f1a2480c96..00000000000 --- a/src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SUNWELLPLATEAU_H -#define DEF_SUNWELLPLATEAU_H - -/*** Encounters ***/ -enum Data -{ - DATA_KALECGOS_EVENT, - DATA_BRUTALLUS_EVENT, - DATA_FELMYST_EVENT, - DATA_EREDAR_TWINS_EVENT, - DATA_MURU_EVENT, - DATA_KILJAEDEN_EVENT, -}; - -enum Data64 -{ - /*** Creatures ***/ - DATA_KALECGOS_DRAGON, - DATA_KALECGOS_HUMAN, - DATA_SATHROVARR, - DATA_BRUTALLUS, - DATA_MADRIGOSA, - DATA_FELMYST, - DATA_ALYTHESS, - DATA_SACROLASH, - DATA_MURU, - DATA_KILJAEDEN, - DATA_KILJAEDEN_CONTROLLER, - DATA_ANVEENA, - DATA_KALECGOS_KJ, - - /*** GameObjects ***/ - DATA_GO_FORCEFIELD, - DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1, - DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2, - DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3, - DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4, - - /*** Misc ***/ - DATA_PLAYER_GUID, -}; - -enum Creatures -{ - BOSS_MURU = 25741, - BOSS_ENTROPIUS = 25840, - MOB_KALECGOS = 24850, - MOB_KALEC = 24891, - MOB_SATHROVARR = 24892, - - MOB_DEAD = 25268, - MOB_FLIGHT_LEFT = 25357, - MOB_FLIGHT_RIGHT = 25358, - MOB_DEATH_CLOUD = 25703, - MOB_VAPOR = 25265, - MOB_VAPOR_TRAIL = 25267, - - MOB_GRAND_WARLOCK_ALYTHESS = 25166, - MOB_SHADOW_IMAGE = 25214, - MOB_LADY_SACROLASH = 25165, - - CREATURE_ANVEENA = 26046, // Embodiment of the Sunwell - CREATURE_KALECGOS = 25319, // Helps the raid throughout the fight - CREATURE_PROPHET = 26246, // Outro - CREATURE_KILJAEDEN = 25315, // Give it to 'em KJ! - CREATURE_HAND_OF_THE_DECEIVER = 25588, // Adds found before KJ emerges - CREATURE_FELFIRE_PORTAL = 25603, // Portal spawned be Hand of the Deceivers - CREATURE_VOLATILE_FELFIRE_FIEND = 25598, // Fiends spawned by the above portal - CREATURE_ARMAGEDDON_TARGET = 25735, // This mob casts meteor on itself.. I think - CREATURE_SHIELD_ORB = 25502, // Shield orbs circle the room raining shadow bolts on raid - CREATURE_THE_CORE_OF_ENTROPIUS = 26262, // Used in the ending cinematic? - CREATURE_POWER_OF_THE_BLUE_DRAGONFLIGHT = 25653, // NPC that players possess when using the Orb of the Blue Dragonflight - CREATURE_SPIKE_TARGET1 = 30598, // Should summon these under Shadow Spike Channel on targets place - CREATURE_SPIKE_TARGET2 = 30614, - CREATURE_SINISTER_REFLECTION = 25708, // Sinister Relection spawnd on Phase swichtes - - CREATURE_DARKNESS = 25879, - CREATURE_DARK_FIENDS = 25744, - CREATURE_BERSERKER = 25798, - CREATURE_FURY_MAGE = 25799, - CREATURE_VOID_SENTINEL = 25772, - CREATURE_VOID_SPAWN = 25824, - CREATURE_BLACK_HOLE = 25855, -}; - -enum GameObjects -{ - GAMEOBJECT_ORB_OF_THE_BLUE_DRAGONFLIGHT = 188415, -}; - -#endif diff --git a/src/server/scripts/eastern_kingdoms/tirisfal_glades.cpp b/src/server/scripts/eastern_kingdoms/tirisfal_glades.cpp deleted file mode 100644 index 8b6d73df704..00000000000 --- a/src/server/scripts/eastern_kingdoms/tirisfal_glades.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Tirisfal_Glades -SD%Complete: 100 -SDComment: Quest support: 590, 1819 -SDCategory: Tirisfal Glades -EndScriptData */ - -/* ContentData -npc_calvin_montague -go_mausoleum_door -go_mausoleum_trigger -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_calvin_montague -######*/ - -enum eCalvin -{ - SAY_COMPLETE = -1000431, - SPELL_DRINK = 2639, // possibly not correct spell (but iconId is correct) - QUEST_590 = 590, - FACTION_HOSTILE = 168 -}; - -struct npc_calvin_montagueAI : public ScriptedAI -{ - npc_calvin_montagueAI(Creature* pCreature) : ScriptedAI(pCreature) { } - - uint32 m_uiPhase; - uint32 m_uiPhaseTimer; - uint64 m_uiPlayerGUID; - - void Reset() - { - m_uiPhase = 0; - m_uiPhaseTimer = 5000; - m_uiPlayerGUID = 0; - - me->RestoreFaction(); - - if (!me->HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE)) - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - void EnterCombat(Unit* /*who*/) {} - - void AttackedBy(Unit* pAttacker) - { - if (me->getVictim() || me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) - { - if (uiDamage > me->GetHealth() || ((me->GetHealth() - uiDamage)*100 / me->GetMaxHealth() < 15)) - { - uiDamage = 0; - - me->RestoreFaction(); - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->CombatStop(true); - - m_uiPhase = 1; - - if (pDoneBy->GetTypeId() == TYPEID_PLAYER) - m_uiPlayerGUID = pDoneBy->GetGUID(); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_uiPhase) - { - if (m_uiPhaseTimer <= uiDiff) - m_uiPhaseTimer = 7500; - else - { - m_uiPhaseTimer -= uiDiff; - return; - } - - switch(m_uiPhase) - { - case 1: - DoScriptText(SAY_COMPLETE, me); - ++m_uiPhase; - break; - case 2: - if (Player *pPlayer = Unit::GetPlayer(m_uiPlayerGUID)) - pPlayer->AreaExploredOrEventHappens(QUEST_590); - - DoCast(me, SPELL_DRINK, true); - ++m_uiPhase; - break; - case 3: - EnterEvadeMode(); - break; - } - - return; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_calvin_montague(Creature* pCreature) -{ - return new npc_calvin_montagueAI (pCreature); -} - -bool QuestAccept_npc_calvin_montague(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_590) - { - pCreature->setFaction(FACTION_HOSTILE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - CAST_AI(npc_calvin_montagueAI, pCreature->AI())->AttackStart(pPlayer); - } - return true; -} - -/*###### -## go_mausoleum_door -## go_mausoleum_trigger -######*/ - -enum eMausoleum -{ - QUEST_ULAG = 1819, - NPC_ULAG = 6390, - GO_TRIGGER = 104593, - GO_DOOR = 176594 -}; - -bool GOHello_go_mausoleum_door(Player* pPlayer, GameObject* /*pGo*/) -{ - if (pPlayer->GetQuestStatus(QUEST_ULAG) != QUEST_STATUS_INCOMPLETE) - return false; - - if (GameObject* pTrigger = pPlayer->FindNearestGameObject(GO_TRIGGER, 30.0f)) - { - pTrigger->SetGoState(GO_STATE_READY); - pPlayer->SummonCreature(NPC_ULAG, 2390.26, 336.47, 40.01, 2.26, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000); - return false; - } - - return false; -} - -bool GOHello_go_mausoleum_trigger(Player* pPlayer, GameObject* pGo) -{ - if (pPlayer->GetQuestStatus(QUEST_ULAG) != QUEST_STATUS_INCOMPLETE) - return false; - - if (GameObject* pDoor = pPlayer->FindNearestGameObject(GO_DOOR, 30.0f)) - { - pGo->SetGoState(GO_STATE_ACTIVE); - pDoor->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - return true; - } - - return false; -} - -void AddSC_tirisfal_glades() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_calvin_montague"; - newscript->GetAI = &GetAI_npc_calvin_montague; - newscript->pQuestAccept = &QuestAccept_npc_calvin_montague; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_mausoleum_door"; - newscript->pGOHello = &GOHello_go_mausoleum_door; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_mausoleum_trigger"; - newscript->pGOHello = &GOHello_go_mausoleum_trigger; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp b/src/server/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp deleted file mode 100644 index cd3bc5fc219..00000000000 --- a/src/server/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp +++ /dev/null @@ -1,497 +0,0 @@ -/* Copyright (C) 2006,2007 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_archaedas -SD%Complete: 100 -SDComment: Archaedas is activated when 1 person (was 3, changed in 3.0.8) clicks on his altar. -Every 10 seconds he will awaken one of his minions along the wall. -At 66%, he will awaken the 6 Guardians. -At 33%, he will awaken the Vault Walkers -On his death the vault door opens. -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO "Who dares awaken Archaedas? Who dares the wrath of the makers!" -#define SOUND_AGGRO 5855 - -#define SAY_SUMMON "Awake ye servants, defend the discs!" -#define SOUND_SUMMON 5856 - -#define SAY_SUMMON2 "To my side, brothers. For the makers!" -#define SOUND_SUMMON2 5857 - -#define SAY_KILL "Reckless mortal." -#define SOUND_KILL 5858 - -#define SPELL_GROUND_TREMOR 6524 -#define SPELL_ARCHAEDAS_AWAKEN 10347 -#define SPELL_BOSS_OBJECT_VISUAL 11206 -#define SPELL_BOSS_AGGRO 10340 -#define SPELL_SUB_BOSS_AGGRO 11568 -#define SPELL_AWAKEN_VAULT_WALKER 10258 -#define SPELL_AWAKEN_EARTHEN_GUARDIAN 10252 - -struct boss_archaedasAI : public ScriptedAI -{ - boss_archaedasAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - uint32 Tremor_Timer; - int32 Awaken_Timer; - uint32 WallMinionTimer; - bool wakingUp; - - bool guardiansAwake; - bool vaultWalkersAwake; - ScriptedInstance* pInstance; - - void Reset() - { - Tremor_Timer = 60000; - Awaken_Timer = 0; - WallMinionTimer = 10000; - - wakingUp = false; - guardiansAwake = false; - vaultWalkersAwake = false; - - if (pInstance) - pInstance->SetData (NULL, 5); // respawn any dead minions - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - - } - - void ActivateMinion (uint64 guid, bool flag) - { - Unit *minion = Unit::GetUnit(*me, guid); - - if (minion && minion->isAlive()) - { - DoCast (minion, SPELL_AWAKEN_VAULT_WALKER, flag); - minion->CastSpell(minion, SPELL_ARCHAEDAS_AWAKEN,true); - } - } - - void EnterCombat(Unit * /*who*/) - { - me->setFaction (14); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); - } - - void SpellHit (Unit* /*caster*/, const SpellEntry *spell) - { - // Being woken up from the altar, start the awaken sequence - if (spell == GetSpellStore()->LookupEntry(SPELL_ARCHAEDAS_AWAKEN)) { - me->MonsterYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_AGGRO); - Awaken_Timer = 4000; - wakingUp = true; - } - } - - void KilledUnit(Unit * /*victim*/) - { - me->MonsterYell(SAY_KILL,LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - // we're still doing awaken animation - if (wakingUp && Awaken_Timer >= 0) { - Awaken_Timer -= diff; - return; // dont do anything until we are done - } else if (wakingUp && Awaken_Timer <= 0) { - wakingUp = false; - AttackStart(Unit::GetUnit(*me, pInstance->GetData64(0))); - return; // dont want to continue until we finish the AttackStart method - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - // wake a wall minion - if (WallMinionTimer <= diff) { - pInstance->SetData (NULL, 2); - - WallMinionTimer = 10000; - } else WallMinionTimer -= diff; - - //If we are <66 summon the guardians - if (!guardiansAwake && me->GetHealth()*100 / me->GetMaxHealth() <= 66) { - ActivateMinion(pInstance->GetData64(5),true); // EarthenGuardian1 - ActivateMinion(pInstance->GetData64(6),true); // EarthenGuardian2 - ActivateMinion(pInstance->GetData64(7),true); // EarthenGuardian3 - ActivateMinion(pInstance->GetData64(8),true); // EarthenGuardian4 - ActivateMinion(pInstance->GetData64(9),true); // EarthenGuardian5 - ActivateMinion(pInstance->GetData64(10),false); // EarthenGuardian6 - me->MonsterYell(SAY_SUMMON,LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_SUMMON); - guardiansAwake = true; - } - - //If we are <33 summon the vault walkers - if (!vaultWalkersAwake && me->GetHealth()*100 / me->GetMaxHealth() <= 33) { - ActivateMinion(pInstance->GetData64(1),true); // VaultWalker1 - ActivateMinion(pInstance->GetData64(2),true); // VaultWalker2 - ActivateMinion(pInstance->GetData64(3),true); // VaultWalker3 - ActivateMinion(pInstance->GetData64(4),false); // VaultWalker4 - me->MonsterYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_SUMMON2); - vaultWalkersAwake = true; - } - - if (Tremor_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_GROUND_TREMOR); - - //45 seconds until we should cast this agian - Tremor_Timer = 45000; - } else Tremor_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied (Unit * /*killer*/) { - if (pInstance) - { - pInstance->SetData(NULL,3); // open the vault door - pInstance->SetData(NULL,4); // deactivate his minions - } - } - -}; - -CreatureAI* GetAI_boss_archaedas(Creature* pCreature) -{ - return new boss_archaedasAI (pCreature); -} - -/* ScriptData -SDName: mob_archaedas_minions -SD%Complete: 100 -SDComment: These mobs are initially frozen until Archaedas awakens them -one at a time. -EndScriptData */ - -#define SPELL_ARCHAEDAS_AWAKEN 10347 - -struct mob_archaedas_minionsAI : public ScriptedAI -{ - mob_archaedas_minionsAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - uint32 Arcing_Timer; - int32 Awaken_Timer; - bool wakingUp; - - bool amIAwake; - ScriptedInstance* pInstance; - - void Reset() - { - Arcing_Timer = 3000; - Awaken_Timer = 0; - - wakingUp = false; - amIAwake = false; - - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->RemoveAllAuras(); - } - - void EnterCombat(Unit * /*who*/) - { - me->setFaction (14); - me->RemoveAllAuras(); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - amIAwake = true; - } - - void SpellHit (Unit* /*caster*/, const SpellEntry *spell) { - // time to wake up, start animation - if (spell == GetSpellStore()->LookupEntry(SPELL_ARCHAEDAS_AWAKEN)){ - Awaken_Timer = 5000; - wakingUp = true; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (amIAwake) - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - // we're still in the awaken animation - if (wakingUp && Awaken_Timer >= 0) { - Awaken_Timer -= diff; - return; // dont do anything until we are done - } else if (wakingUp && Awaken_Timer <= 0) { - wakingUp = false; - amIAwake = true; - // AttackStart(Unit::GetUnit(*me, pInstance->GetData64(0))); // whoWokeArchaedasGUID - return; // dont want to continue until we finish the AttackStart method - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_archaedas_minions(Creature* pCreature) -{ - return new mob_archaedas_minionsAI (pCreature); -} - -/* ScriptData -SDName: go_altar_archaedas -SD%Complete: 100 -SDComment: Needs 1 person to activate the Archaedas script -SDCategory: Uldaman -EndScriptData */ - -#define OBJECT_ALTAR_OF_ARCHAEDAS 133234 - -#define NUMBER_NEEDED_TO_ACTIVATE 1 // as of patch 3.0.8 the altars can be opened by a single player (previously 3) - -#define SPELL_BOSS_OBJECT_VISUAL 11206 - -//uint64 altarOfArchaedasCount[5]; -//int32 altarOfArchaedasCounter=0; - -bool GOHello_go_altar_of_archaedas(Player* pPlayer, GameObject* /*pGo*/) -{ - //bool alreadyUsed; - //pGo->AddUse (); - - /* - alreadyUsed = false; - for (uint32 loop=0; loop<5; loop++) { - if (altarOfArchaedasCount[loop] == pPlayer->GetGUID()) alreadyUsed = true; - } - if (!alreadyUsed) - altarOfArchaedasCount[altarOfArchaedasCounter++] = pPlayer->GetGUID(); - */ - - pPlayer->CastSpell (pPlayer, SPELL_BOSS_OBJECT_VISUAL, false); - - /* - if (altarOfArchaedasCounter < NUMBER_NEEDED_TO_ACTIVATE) - return false; // not enough people yet - - // Check to make sure at least three people are still casting - uint8 count = 0; - Unit *pTarget; - for (uint8 x = 0; x <= 5; ++x) - { - pTarget = Unit::GetUnit(*pPlayer, altarOfArchaedasCount[x]); - if (!pTarget) - continue; - if (pTarget->IsNonMeleeSpellCasted(true)) - ++count; - if (count >= NUMBER_NEEDED_TO_ACTIVATE) - break; - } - - if (count < NUMBER_NEEDED_TO_ACTIVATE) - return false; // not enough people - */ - - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (!pInstance) - return false; - - pInstance->SetData(NULL,0); - pInstance->SetData64(0,pPlayer->GetGUID()); // activate archaedas - - return false; -} - -/* ScriptData -SDName: mob_stonekeepers -SD%Complete: 100 -SDComment: After activating the altar of the keepers, the stone keepers will -wake up one by one. -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SELF_DESTRUCT 9874 - -struct mob_stonekeepersAI : public ScriptedAI -{ - mob_stonekeepersAI(Creature *c) : ScriptedAI(c) - { - pInstance = (me->GetInstanceData()); - } - - ScriptedInstance* pInstance; - - void Reset() - { - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->RemoveAllAuras(); - } - - void EnterCombat(Unit * /*who*/) - { - me->setFaction (14); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - } - - void UpdateAI(const uint32 /*diff*/) - { - - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit * /*attacker*/) - { - DoCast (me, SPELL_SELF_DESTRUCT,true); - if (pInstance) - pInstance->SetData(NULL, 1); // activate next stonekeeper - } - -}; - -CreatureAI* GetAI_mob_stonekeepers(Creature* pCreature) -{ - return new mob_stonekeepersAI (pCreature); -} - -/* ScriptData -SDName: go_altar_of_the_keepers -SD%Complete: 100 -SDComment: Need 1 person to activate to open the altar. One by one the StoneKeepers will activate. After all four are dead than the door will open. -SDCategory: Uldaman -EndScriptData */ - -#define SPELL_BOSS_OBJECT_VISUAL 11206 - -#define NUMBER_NEEDED_TO_ACTIVATE 1 // as of patch 3.0.8 the altars can be opened by a single player (previously 3) - -//static uint64 altarOfTheKeeperCount[5]; -//static uint32 altarOfTheKeeperCounter=0; - -bool GOHello_go_altar_of_the_keepers(Player* pPlayer, GameObject* /*pGo*/) -{ - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (!pInstance) - return true; - - //bool alreadyUsed; - - //pGo->AddUse(); - - //alreadyUsed = false; - //for (uint32 loop=0; loop<5; ++loop) - //{ - // if (altarOfTheKeeperCount[loop] == pPlayer->GetGUID()) - //alreadyUsed = true; - //} - //if (!alreadyUsed && altarOfTheKeeperCounter < 5) - // altarOfTheKeeperCount[altarOfTheKeeperCounter++] = pPlayer->GetGUID(); - pPlayer->CastSpell (pPlayer, SPELL_BOSS_OBJECT_VISUAL, false); - - //if (altarOfTheKeeperCounter < NUMBER_NEEDED_TO_ACTIVATE) - //{ - //error_log("not enough people yet, altarOfTheKeeperCounter = %d", altarOfTheKeeperCounter); - // return false; // not enough people yet - //} -/* - // Check to make sure at least three people are still casting - uint8 count = 0; - Unit *pTarget; - for (uint8 x = 0; x < 5; ++x) - { - pTarget = Unit::GetUnit(*pPlayer, altarOfTheKeeperCount[x]); - //error_log("number of people currently activating it: %d", x+1); - if (!pTarget) - continue; - if (pTarget->IsNonMeleeSpellCasted(true)) - ++count; - if (count >= NUMBER_NEEDED_TO_ACTIVATE) - break; - } - - if (count < NUMBER_NEEDED_TO_ACTIVATE) - { - //error_log("still not enough people"); - return true; // not enough people - } -*/ - //error_log ("activating stone keepers"); - pInstance->SetData(NULL,1); // activate the Stone Keepers - return true; -} - -void AddSC_boss_archaedas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_archaedas"; - newscript->GetAI = &GetAI_boss_archaedas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_altar_of_archaedas"; - newscript->pGOHello = &GOHello_go_altar_of_archaedas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_archaedas_minions"; - newscript->GetAI = &GetAI_mob_archaedas_minions; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_altar_of_the_keepers"; - newscript->pGOHello = &GOHello_go_altar_of_the_keepers; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stonekeepers"; - newscript->GetAI = &GetAI_mob_stonekeepers; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp b/src/server/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp deleted file mode 100644 index 9b6d5dba642..00000000000 --- a/src/server/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ironaya -SD%Complete: 100 -SDComment: -SDCategory: Uldaman -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1070000 - -#define SPELL_ARCINGSMASH 8374 -#define SPELL_KNOCKAWAY 10101 -#define SPELL_WSTOMP 11876 - -struct boss_ironayaAI : public ScriptedAI -{ - boss_ironayaAI(Creature *c) : ScriptedAI(c) {} - - uint32 Arcing_Timer; - bool hasCastedWstomp; - bool hasCastedKnockaway; - - void Reset() - { - Arcing_Timer = 3000; - hasCastedKnockaway = false; - hasCastedWstomp = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //If we are <50% hp do knockaway ONCE - if (!hasCastedKnockaway && me->GetHealth()*2 < me->GetMaxHealth()) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); - - // current aggro target is knocked away pick new target - Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - - if (!Target || Target == me->getVictim()) - Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); - - if (Target) - me->TauntApply(Target); - - //Shouldn't cast this agian - hasCastedKnockaway = true; - } - - //Arcing_Timer - if (Arcing_Timer <= diff) - { - DoCast(me, SPELL_ARCINGSMASH); - Arcing_Timer = 13000; - } else Arcing_Timer -= diff; - - if (!hasCastedWstomp && me->GetHealth()*4 < me->GetMaxHealth()) - { - DoCast(me, SPELL_WSTOMP); - hasCastedWstomp = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ironaya(Creature* pCreature) -{ - return new boss_ironayaAI (pCreature); -} - -void AddSC_boss_ironaya() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ironaya"; - newscript->GetAI = &GetAI_boss_ironaya; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp b/src/server/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp deleted file mode 100644 index a519ad678b7..00000000000 --- a/src/server/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright (C) 2006,2007 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -#define SPELL_ARCHAEDAS_AWAKEN 10347 -#define SPELL_AWAKEN_VAULT_WALKER 10258 - -#define ARCHAEDAS_TEMPLE_DOOR 141869 -#define ALTAR_OF_ARCHAEDAS 133234 - -#define ALTAR_OF_THE_KEEPER_TEMPLE_DOOR 124367 -#define ALTAR_OF_THE_KEEPER_TEMPLE 130511 - -#define ANCIENT_VAULT_DOOR 124369 - -struct instance_uldaman : public ScriptedInstance -{ - instance_uldaman(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - }; - - void Initialize() - { - archaedasGUID = 0; - altarOfTheKeeperTempleDoor = 0; - archaedasTempleDoor = 0; - ancientVaultDoor = 0; - whoWokeArchaedasGUID = 0; - } - - uint64 archaedasGUID; - uint64 altarOfTheKeeperTempleDoor; - uint64 archaedasTempleDoor; - uint64 ancientVaultDoor; - uint64 whoWokeArchaedasGUID; - - std::vector stoneKeeper; - std::vector altarOfTheKeeperCount; - std::vector vaultWalker; - std::vector earthenGuardian; - std::vector archaedasWallMinions; // minions lined up around the wall - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch (pGo->GetEntry()) - { - case ALTAR_OF_THE_KEEPER_TEMPLE_DOOR: // lock the door - altarOfTheKeeperTempleDoor = pGo->GetGUID(); - break; - - case ARCHAEDAS_TEMPLE_DOOR: - archaedasTempleDoor = pGo->GetGUID(); - break; - - case ANCIENT_VAULT_DOOR: - pGo->SetGoState(GO_STATE_READY); - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33); - ancientVaultDoor = pGo->GetGUID(); - break; - } - } - - void SetFrozenState(Creature* pCreature) - { - pCreature->setFaction(35); - pCreature->RemoveAllAuras(); - //creature->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_ANIMATION_FROZEN); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - } - - void OpenDoor(uint64 guid) - { - GameObject* pGo = instance->GetGameObject(guid); - if (!pGo) - return; - - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33); - pGo->SetGoState(GO_STATE_ACTIVE); - } - - void ActivateStoneKeepers() - { - for (std::vector::const_iterator i = stoneKeeper.begin(); i != stoneKeeper.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || !pTarget->isAlive() || pTarget->getFaction() == 14) - continue; - pTarget->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); - pTarget->setFaction(14); - pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - return; // only want the first one we find - } - // if we get this far than all four are dead so open the door - SetData (NULL, 0); - } - - void ActivateWallMinions() - { - Creature *archaedas = instance->GetCreature(archaedasGUID); - if (!archaedas) - return; - - for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || !pTarget->isAlive() || pTarget->getFaction() == 14) - continue; - archaedas->CastSpell(pTarget, SPELL_AWAKEN_VAULT_WALKER, true); - pTarget->CastSpell(pTarget, SPELL_ARCHAEDAS_AWAKEN,true); - return; // only want the first one we find - } - } - - // used when Archaedas dies. All active minions must be despawned. - void DeActivateMinions() - { - // first despawn any aggroed wall minions - for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) - continue; - pTarget->setDeathState(JUST_DIED); - pTarget->RemoveCorpse(); - } - - // Vault Walkers - for (std::vector::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) - continue; - pTarget->setDeathState(JUST_DIED); - pTarget->RemoveCorpse(); - } - - // Earthen Guardians - for (std::vector::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) - continue; - pTarget->setDeathState(JUST_DIED); - pTarget->RemoveCorpse(); - } - } - - void ActivateArchaedas(uint64 target) - { - Creature *archaedas = instance->GetCreature(archaedasGUID); - if (!archaedas) - return; - - if (Unit *victim = Unit::GetUnit(*archaedas, target)) - { - archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN,false); - whoWokeArchaedasGUID = target; - } - } - - void RespawnMinions() - { - // first respawn any aggroed wall minions - for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (pTarget && pTarget->isDead()) - { - pTarget->Respawn(); - pTarget->GetMotionMaster()->MoveTargetedHome(); - SetFrozenState(pTarget); - } - } - - // Vault Walkers - for (std::vector::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (pTarget && pTarget->isDead()) - { - pTarget->Respawn(); - pTarget->GetMotionMaster()->MoveTargetedHome(); - SetFrozenState(pTarget); - } - } - - // Earthen Guardians - for (std::vector::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (pTarget && pTarget->isDead()) - { - pTarget->Respawn(); - pTarget->GetMotionMaster()->MoveTargetedHome(); - SetFrozenState(pTarget); - } - } - } - - void SetData (uint32 /*type*/, uint32 data) - { - //error_log ("SetData: data = %d", data); - if (data == 0) OpenDoor (altarOfTheKeeperTempleDoor); - if (data == 0) OpenDoor (archaedasTempleDoor); - if (data == 3) OpenDoor (ancientVaultDoor); - if (data == 1) ActivateStoneKeepers(); - if (data == 2) ActivateWallMinions(); - if (data == 4) DeActivateMinions(); - if (data == 5) RespawnMinions(); - } - - void SetData64 (uint32 type, uint64 data) - { - // Archaedas - if (type == 0) - { - ActivateArchaedas (data); - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) { - case 4857: // Stone Keeper - SetFrozenState (pCreature); - stoneKeeper.push_back(pCreature->GetGUID()); - break; - - case 7309: // Earthen Custodian - archaedasWallMinions.push_back(pCreature->GetGUID()); - break; - - case 7077: // Earthen Hallshaper - archaedasWallMinions.push_back(pCreature->GetGUID()); - break; - - case 7076: // Earthen Guardian - earthenGuardian.push_back(pCreature->GetGUID()); - break; - - case 10120: // Vault Walker - vaultWalker.push_back(pCreature->GetGUID()); - break; - - case 2748: // Archaedas - archaedasGUID = pCreature->GetGUID(); - break; - - } // end switch - } // end OnCreatureCreate - - uint64 GetData64 (uint32 identifier) - { - if (identifier == 0) return whoWokeArchaedasGUID; - if (identifier == 1) return vaultWalker[0]; // VaultWalker1 - if (identifier == 2) return vaultWalker[1]; // VaultWalker2 - if (identifier == 3) return vaultWalker[2]; // VaultWalker3 - if (identifier == 4) return vaultWalker[3]; // VaultWalker4 - - if (identifier == 5) return earthenGuardian[0]; - if (identifier == 6) return earthenGuardian[1]; - if (identifier == 7) return earthenGuardian[2]; - if (identifier == 8) return earthenGuardian[3]; - if (identifier == 9) return earthenGuardian[4]; - if (identifier == 10) return earthenGuardian[5]; - - return 0; - } // end GetData64 -}; - -InstanceData* GetInstanceData_instance_uldaman(Map* pMap) -{ - return new instance_uldaman(pMap); -} - -void AddSC_instance_uldaman() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_uldaman"; - newscript->GetInstanceData = &GetInstanceData_instance_uldaman; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/uldaman/uldaman.cpp b/src/server/scripts/eastern_kingdoms/uldaman/uldaman.cpp deleted file mode 100644 index 2bd8387efa5..00000000000 --- a/src/server/scripts/eastern_kingdoms/uldaman/uldaman.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Uldaman -SD%Complete: 100 -SDComment: Quest support: 2278 + 1 trash mob. -SDCategory: Uldaman -EndScriptData */ - -/* ContentData -mob_jadespine_basilisk -npc_lore_keeper_of_norgannon -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## mob_jadespine_basilisk -######*/ - -#define SPELL_CSLUMBER 3636 - -struct mob_jadespine_basiliskAI : public ScriptedAI -{ - mob_jadespine_basiliskAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cslumber_Timer; - - void Reset() - { - Cslumber_Timer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Cslumber_Timer - if (Cslumber_Timer <= diff) - { - //Cast - // DoCast(me->getVictim(), SPELL_CSLUMBER); - DoCast(me->getVictim(), SPELL_CSLUMBER, true); - - //Stop attacking target thast asleep and pick new target - Cslumber_Timer = 28000; - - Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - - if (!Target || Target == me->getVictim()) - Target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - - if (Target) - me->TauntApply(Target); - - } else Cslumber_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_jadespine_basilisk(Creature* pCreature) -{ - return new mob_jadespine_basiliskAI (pCreature); -} - -/*###### -## npc_lore_keeper_of_norgannon -######*/ - -#define GOSSIP_HELLO_KEEPER "Who are the Earthen?" -#define GOSSIP_SELECT_KEEPER1 "What is a \"subterranean being matrix\"?" -#define GOSSIP_SELECT_KEEPER2 "What are the anomalies you speak of?" -#define GOSSIP_SELECT_KEEPER3 "What is a resilient foundation of construction?" -#define GOSSIP_SELECT_KEEPER4 "So... the Earthen were made out of stone?" -#define GOSSIP_SELECT_KEEPER5 "Anything else I should know about the Earthen?" -#define GOSSIP_SELECT_KEEPER6 "I think I understand the Creators' design intent for the Earthen now. What are the Earthen's anomalies that you spoke of earlier?" -#define GOSSIP_SELECT_KEEPER7 "What high-stress environments would cause the Earthen to destabilize?" -#define GOSSIP_SELECT_KEEPER8 "What happens when the Earthen destabilize?" -#define GOSSIP_SELECT_KEEPER9 "Troggs?! Are the troggs you mention the same as the ones in the world today?" -#define GOSSIP_SELECT_KEEPER10 "You mentioned two results when the Earthen destabilize. What is the second?" -#define GOSSIP_SELECT_KEEPER11 "Dwarves!!! Now you're telling me that dwarves originally came from the Earthen?!" -#define GOSSIP_SELECT_KEEPER12 "These dwarves are the same ones today, yes? Do the dwarves maintain any other links to the Earthen?" -#define GOSSIP_SELECT_KEEPER13 "Who are the Creators?" -#define GOSSIP_SELECT_KEEPER14 "This is a lot to think about." -#define GOSSIP_SELECT_KEEPER15 "I will access the discs now." - -bool GossipHello_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(2278) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KEEPER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(1079, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(1080, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(1081, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(1082, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(1083, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(1084, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - pPlayer->SEND_GOSSIP_MENU(1085, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); - pPlayer->SEND_GOSSIP_MENU(1086, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+8: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); - pPlayer->SEND_GOSSIP_MENU(1087, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+9: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); - pPlayer->SEND_GOSSIP_MENU(1088, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+10: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+11); - pPlayer->SEND_GOSSIP_MENU(1089, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+12); - pPlayer->SEND_GOSSIP_MENU(1090, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+12: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+13); - pPlayer->SEND_GOSSIP_MENU(1091, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+13: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+14); - pPlayer->SEND_GOSSIP_MENU(1092, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+14: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+15); - pPlayer->SEND_GOSSIP_MENU(1093, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+15: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+16); - pPlayer->SEND_GOSSIP_MENU(1094, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+16: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(2278); - break; - } - return true; -} - -void AddSC_uldaman() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_jadespine_basilisk"; - newscript->GetAI = &GetAI_mob_jadespine_basilisk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lore_keeper_of_norgannon"; - newscript->pGossipHello = &GossipHello_npc_lore_keeper_of_norgannon; - newscript->pGossipSelect = &GossipSelect_npc_lore_keeper_of_norgannon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/undercity.cpp b/src/server/scripts/eastern_kingdoms/undercity.cpp deleted file mode 100644 index 22eb3241874..00000000000 --- a/src/server/scripts/eastern_kingdoms/undercity.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Undercity -SD%Complete: 95 -SDComment: Quest support: 6628, 9180(post-event). -SDCategory: Undercity -EndScriptData */ - -/* ContentData -npc_lady_sylvanas_windrunner -npc_highborne_lamenter -npc_parqual_fintallas -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_lady_sylvanas_windrunner -######*/ - -#define SAY_LAMENT_END -1000196 -#define EMOTE_LAMENT_END -1000197 - -#define SOUND_CREDIT 10896 -#define ENTRY_HIGHBORNE_LAMENTER 21628 -#define ENTRY_HIGHBORNE_BUNNY 21641 - -#define SPELL_HIGHBORNE_AURA 37090 -#define SPELL_SYLVANAS_CAST 36568 -#define SPELL_RIBBON_OF_SOULS 34432 //the real one to use might be 37099 - -float HighborneLoc[4][3]= -{ - {1285.41, 312.47, 0.51}, - {1286.96, 310.40, 1.00}, - {1289.66, 309.66, 1.52}, - {1292.51, 310.50, 1.99}, -}; - -#define HIGHBORNE_LOC_Y -61.00 -#define HIGHBORNE_LOC_Y_NEW -55.50 - -struct npc_lady_sylvanas_windrunnerAI : public ScriptedAI -{ - npc_lady_sylvanas_windrunnerAI(Creature *c) : ScriptedAI(c) {} - - uint32 LamentEvent_Timer; - bool LamentEvent; - uint64 targetGUID; - - void Reset() - { - LamentEvent_Timer = 5000; - LamentEvent = false; - targetGUID = 0; - } - - void EnterCombat(Unit * /*who*/) {} - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == ENTRY_HIGHBORNE_BUNNY) - { - if (Unit *pTarget = Unit::GetUnit(*summoned,targetGUID)) - { - pTarget->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), me->GetPositionZ()+15.0,0); - pTarget->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), me->GetPositionZ()+15.0, 0.0f); - summoned->CastSpell(pTarget, SPELL_RIBBON_OF_SOULS, false); - } - - summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - targetGUID = summoned->GetGUID(); - } - } - - void UpdateAI(const uint32 diff) - { - if (LamentEvent) - { - if (LamentEvent_Timer <= diff) - { - DoSummon(ENTRY_HIGHBORNE_BUNNY, me, 10.0f, 3000, TEMPSUMMON_TIMED_DESPAWN); - - LamentEvent_Timer = 2000; - if (!me->HasAura(SPELL_SYLVANAS_CAST)) - { - DoScriptText(SAY_LAMENT_END, me); - DoScriptText(EMOTE_LAMENT_END, me); - LamentEvent = false; - } - } else LamentEvent_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_lady_sylvanas_windrunner(Creature* pCreature) -{ - return new npc_lady_sylvanas_windrunnerAI (pCreature); -} - -bool ChooseReward_npc_lady_sylvanas_windrunner(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest, uint32 /*slot*/) -{ - if (_Quest->GetQuestId() == 9180) - { - CAST_AI(npc_lady_sylvanas_windrunnerAI, pCreature->AI())->LamentEvent = true; - CAST_AI(npc_lady_sylvanas_windrunnerAI, pCreature->AI())->DoPlaySoundToSet(pCreature,SOUND_CREDIT); - pCreature->CastSpell(pCreature,SPELL_SYLVANAS_CAST,false); - - for (uint8 i = 0; i < 4; ++i) - pCreature->SummonCreature(ENTRY_HIGHBORNE_LAMENTER, HighborneLoc[i][0], HighborneLoc[i][1], HIGHBORNE_LOC_Y, HighborneLoc[i][2], TEMPSUMMON_TIMED_DESPAWN, 160000); - } - - return true; -} - -/*###### -## npc_highborne_lamenter -######*/ - -struct npc_highborne_lamenterAI : public ScriptedAI -{ - npc_highborne_lamenterAI(Creature *c) : ScriptedAI(c) {} - - uint32 EventMove_Timer; - uint32 EventCast_Timer; - bool EventMove; - bool EventCast; - - void Reset() - { - EventMove_Timer = 10000; - EventCast_Timer = 17500; - EventMove = true; - EventCast = true; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (EventMove) - { - if (EventMove_Timer <= diff) - { - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SendMonsterMoveWithSpeed(me->GetPositionX(),me->GetPositionY(),HIGHBORNE_LOC_Y_NEW,5000); - me->GetMap()->CreatureRelocation(me,me->GetPositionX(),me->GetPositionY(),HIGHBORNE_LOC_Y_NEW,me->GetOrientation()); - EventMove = false; - } else EventMove_Timer -= diff; - } - if (EventCast) - { - if (EventCast_Timer <= diff) - { - DoCast(me, SPELL_HIGHBORNE_AURA); - EventCast = false; - } else EventCast_Timer -= diff; - } - } -}; -CreatureAI* GetAI_npc_highborne_lamenter(Creature* pCreature) -{ - return new npc_highborne_lamenterAI (pCreature); -} - -/*###### -## npc_parqual_fintallas -######*/ - -#define SPELL_MARK_OF_SHAME 6767 - -#define GOSSIP_HPF1 "Gul'dan" -#define GOSSIP_HPF2 "Kel'Thuzad" -#define GOSSIP_HPF3 "Ner'zhul" - -bool GossipHello_npc_parqual_fintallas(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(6628) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasAura(SPELL_MARK_OF_SHAME)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HPF1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HPF2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HPF3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(5822, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(5821, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_parqual_fintallas(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer,SPELL_MARK_OF_SHAME,false); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(6628); - } - return true; -} - -/*###### -## AddSC -######*/ - -void AddSC_undercity() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_lady_sylvanas_windrunner"; - newscript->GetAI = &GetAI_npc_lady_sylvanas_windrunner; - newscript->pChooseReward = &ChooseReward_npc_lady_sylvanas_windrunner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_highborne_lamenter"; - newscript->GetAI = &GetAI_npc_highborne_lamenter; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_parqual_fintallas"; - newscript->pGossipHello = &GossipHello_npc_parqual_fintallas; - newscript->pGossipSelect = &GossipSelect_npc_parqual_fintallas; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/western_plaguelands.cpp b/src/server/scripts/eastern_kingdoms/western_plaguelands.cpp deleted file mode 100644 index 778bcea0b1e..00000000000 --- a/src/server/scripts/eastern_kingdoms/western_plaguelands.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Western_Plaguelands -SD%Complete: 90 -SDComment: Quest support: 5097, 5098, 5216, 5219, 5222, 5225, 5229, 5231, 5233, 5235. To obtain Vitreous Focuser (could use more spesifics about gossip items) -SDCategory: Western Plaguelands -EndScriptData */ - -/* ContentData -npcs_dithers_and_arbington -npc_myranda_the_hag -npc_the_scourge_cauldron -npc_andorhal_tower -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npcs_dithers_and_arbington -######*/ - -#define GOSSIP_HDA1 "What does the Felstone Field Cauldron need?" -#define GOSSIP_HDA2 "What does the Dalson's Tears Cauldron need?" -#define GOSSIP_HDA3 "What does the Writhing Haunt Cauldron need?" -#define GOSSIP_HDA4 "What does the Gahrron's Withering Cauldron need?" - -#define GOSSIP_SDA1 "Thanks, i need a Vitreous Focuser" - -bool GossipHello_npcs_dithers_and_arbington(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - if (pPlayer->GetQuestRewardStatus(5237) || pPlayer->GetQuestRewardStatus(5238)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HDA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HDA3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HDA4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(3985, pCreature->GetGUID()); - }else - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npcs_dithers_and_arbington(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(3980, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(3981, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(3982, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SDA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(3983, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, 17529, false); - break; - } - return true; -} - -/*###### -## npc_myranda_the_hag -######*/ - -enum eMyranda -{ - QUEST_SUBTERFUGE = 5862, - QUEST_IN_DREAMS = 5944, - SPELL_SCARLET_ILLUSION = 17961 -}; - -#define GOSSIP_ITEM_ILLUSION "I am ready for the illusion, Myranda." - -bool GossipHello_npc_myranda_the_hag(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_SUBTERFUGE) == QUEST_STATUS_COMPLETE && - !pPlayer->GetQuestRewardStatus(QUEST_IN_DREAMS) && !pPlayer->HasAura(SPELL_SCARLET_ILLUSION)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ILLUSION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(4773, pCreature->GetGUID()); - return true; - } - else - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_myranda_the_hag(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_SCARLET_ILLUSION, false); - } - return true; -} - -/*###### -## npc_the_scourge_cauldron -######*/ - -struct npc_the_scourge_cauldronAI : public ScriptedAI -{ - npc_the_scourge_cauldronAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - - void EnterCombat(Unit* /*who*/) {} - - void DoDie() - { - //summoner dies here - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - //override any database `spawntimesecs` to prevent duplicated summons - uint32 rTime = me->GetRespawnDelay(); - if (rTime<600) - me->SetRespawnDelay(600); - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || who->GetTypeId() != TYPEID_PLAYER) - return; - - if (who->GetTypeId() == TYPEID_PLAYER) - { - switch(me->GetAreaId()) - { - case 199: //felstone - if (CAST_PLR(who)->GetQuestStatus(5216) == QUEST_STATUS_INCOMPLETE || - CAST_PLR(who)->GetQuestStatus(5229) == QUEST_STATUS_INCOMPLETE) - { - me->SummonCreature(11075, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); - DoDie(); - } - break; - case 200: //dalson - if (CAST_PLR(who)->GetQuestStatus(5219) == QUEST_STATUS_INCOMPLETE || - CAST_PLR(who)->GetQuestStatus(5231) == QUEST_STATUS_INCOMPLETE) - { - me->SummonCreature(11077, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); - DoDie(); - } - break; - case 201: //gahrron - if (CAST_PLR(who)->GetQuestStatus(5225) == QUEST_STATUS_INCOMPLETE || - CAST_PLR(who)->GetQuestStatus(5235) == QUEST_STATUS_INCOMPLETE) - { - me->SummonCreature(11078, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); - DoDie(); - } - break; - case 202: //writhing - if (CAST_PLR(who)->GetQuestStatus(5222) == QUEST_STATUS_INCOMPLETE || - CAST_PLR(who)->GetQuestStatus(5233) == QUEST_STATUS_INCOMPLETE) - { - me->SummonCreature(11076, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); - DoDie(); - } - break; - } - } - } -}; -CreatureAI* GetAI_npc_the_scourge_cauldron(Creature* pCreature) -{ - return new npc_the_scourge_cauldronAI (pCreature); -} - -/*###### -## npcs_andorhal_tower -######*/ - -enum eAndorhalTower -{ - GO_BEACON_TORCH = 176093 -}; - -struct npc_andorhal_towerAI : public Scripted_NoMovementAI -{ - npc_andorhal_towerAI(Creature *c) : Scripted_NoMovementAI(c) {} - - void MoveInLineOfSight(Unit* pWho) - { - if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER) - return; - - if (me->FindNearestGameObject(GO_BEACON_TORCH, 10.0f)) - CAST_PLR(pWho)->KilledMonsterCredit(me->GetEntry(), me->GetGUID()); - } -}; - -CreatureAI* GetAI_npc_andorhal_tower(Creature* pCreature) -{ - return new npc_andorhal_towerAI (pCreature); -} - -/*###### -## npc_anchorite_truuen -######*/ - -enum eTruuen -{ - NPC_GHOST_UTHER = 17233, - NPC_THEL_DANIS = 1854, - NPC_GHOUL = 1791, //ambush - - QUEST_TOMB_LIGHTBRINGER = 9446, - - SAY_WP_0 = -1999981, //Beware! We are attacked! - SAY_WP_1 = -1999982, //It must be the purity of the Mark of the Lightbringer that is drawing forth the Scourge to attack us. We must proceed with caution lest we be overwhelmed! - SAY_WP_2 = -1999983, //This land truly needs to be cleansed by the Light! Let us continue on to the tomb. It isn't far now... - SAY_WP_3 = -1999984, //Be welcome, friends! - SAY_WP_4 = -1999985, //Thank you for coming here in remembrance of me. Your efforts in recovering that symbol, while unnecessary, are certainly touching to an old man's heart. - SAY_WP_5 = -1999986, //Please, rise my friend. Keep the Blessing as a symbol of the strength of the Light and how heroes long gone might once again rise in each of us to inspire. - SAY_WP_6 = -1999987 //Thank you my friend for making this possible. This is a day that I shall never forget! I think I will stay a while. Please return to High Priestess MacDonnell at the camp. I know that she'll be keenly interested to know of what has transpired here. -}; - -struct npc_anchorite_truuenAI : public npc_escortAI -{ - npc_anchorite_truuenAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - uint32 m_uiChatTimer; - - uint64 UghostGUID; - uint64 TheldanisGUID; - - Creature* Ughost; - Creature* Theldanis; - - void Reset() - { - m_uiChatTimer = 7000; - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_GHOUL) - pSummoned->AI()->AttackStart(me); - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - switch (i) - { - case 8: - DoScriptText(SAY_WP_0, me); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+7.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+5.0f, me->GetPositionY()+5.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - break; - case 9: - DoScriptText(SAY_WP_1, me); - break; - case 14: - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+7.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+5.0f, me->GetPositionY()+5.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+10.0f, me->GetPositionY()+10.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+8.0f, me->GetPositionY()+8.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - break; - case 15: - DoScriptText(SAY_WP_2, me); - case 21: - Theldanis = GetClosestCreatureWithEntry(me, NPC_THEL_DANIS, 150); - DoScriptText(SAY_WP_3, Theldanis); - break; - case 22: - break; - case 23: - Ughost = me->SummonCreature(NPC_GHOST_UTHER, 971.86,-1825.42 ,81.99 , 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - Ughost->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - DoScriptText(SAY_WP_4, Ughost, me); - m_uiChatTimer = 4000; - break; - case 24: - DoScriptText(SAY_WP_5, Ughost, me); - m_uiChatTimer = 4000; - break; - case 25: - DoScriptText(SAY_WP_6, Ughost, me); - m_uiChatTimer = 4000; - break; - case 26: - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_TOMB_LIGHTBRINGER, me); - break; - } - } - - void EnterCombat(Unit* /*pWho*/){} - - void JustDied(Unit* /*pKiller*/) - { - Player* pPlayer = GetPlayerForEscort(); - if (pPlayer) - pPlayer->FailQuest(QUEST_TOMB_LIGHTBRINGER); - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - DoMeleeAttackIfReady(); - if (HasEscortState(STATE_ESCORT_ESCORTING)) - m_uiChatTimer = 6000; - } -}; - -CreatureAI* GetAI_npc_anchorite_truuen(Creature* pCreature) -{ - return new npc_anchorite_truuenAI(pCreature); -} - -bool QuestAccept_npc_anchorite_truuen(Player* pPlayer, Creature* pCreature, Quest const *quest) -{ - npc_escortAI* pEscortAI = CAST_AI(npc_anchorite_truuenAI, pCreature->AI()); - - if (quest->GetQuestId() == QUEST_TOMB_LIGHTBRINGER) - pEscortAI->Start(true, true, pPlayer->GetGUID()); - return false; -} - -/*###### -## -######*/ - -void AddSC_western_plaguelands() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npcs_dithers_and_arbington"; - newscript->pGossipHello = &GossipHello_npcs_dithers_and_arbington; - newscript->pGossipSelect = &GossipSelect_npcs_dithers_and_arbington; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_myranda_the_hag"; - newscript->pGossipHello = &GossipHello_npc_myranda_the_hag; - newscript->pGossipSelect = &GossipSelect_npc_myranda_the_hag; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_the_scourge_cauldron"; - newscript->GetAI = &GetAI_npc_the_scourge_cauldron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_andorhal_tower"; - newscript->GetAI = &GetAI_npc_andorhal_tower; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anchorite_truuen"; - newscript->GetAI = &GetAI_npc_anchorite_truuen; - newscript->pQuestAccept = &QuestAccept_npc_anchorite_truuen; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/westfall.cpp b/src/server/scripts/eastern_kingdoms/westfall.cpp deleted file mode 100644 index 6f2f439f7fb..00000000000 --- a/src/server/scripts/eastern_kingdoms/westfall.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Westfall -SD%Complete: 90 -SDComment: Quest support: 155, 1651 -SDCategory: Westfall -EndScriptData */ - -/* ContentData -npc_daphne_stilwell -npc_defias_traitor -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_daphne_stilwell -######*/ - -enum eEnums -{ - SAY_DS_START = -1000293, - SAY_DS_DOWN_1 = -1000294, - SAY_DS_DOWN_2 = -1000295, - SAY_DS_DOWN_3 = -1000296, - SAY_DS_PROLOGUE = -1000297, - - SPELL_SHOOT = 6660, - QUEST_TOME_VALOR = 1651, - NPC_DEFIAS_RAIDER = 6180, - EQUIP_ID_RIFLE = 2511 -}; - -struct npc_daphne_stilwellAI : public npc_escortAI -{ - npc_daphne_stilwellAI(Creature* pCreature) : npc_escortAI(pCreature) {} - - uint32 uiWPHolder; - uint32 uiShootTimer; - - void Reset() - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - switch(uiWPHolder) - { - case 7: DoScriptText(SAY_DS_DOWN_1, me); break; - case 8: DoScriptText(SAY_DS_DOWN_2, me); break; - case 9: DoScriptText(SAY_DS_DOWN_3, me); break; - } - } - else - uiWPHolder = 0; - - uiShootTimer = 0; - } - - void WaypointReached(uint32 uiPoint) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - uiWPHolder = uiPoint; - - switch(uiPoint) - { - case 4: - SetEquipmentSlots(false, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE, EQUIP_ID_RIFLE); - me->SetSheath(SHEATH_STATE_RANGED); - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING_NOSHEATHE); - break; - case 7: - me->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836, 1569.755, 54.267, 4.230, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697, 1569.124, 54.421, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237, 1568.307, 54.620, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 8: - me->SetSheath(SHEATH_STATE_RANGED); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836, 1569.755, 54.267, 4.230, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697, 1569.124, 54.421, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237, 1568.307, 54.620, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.037, 1570.213, 54.961, 4.283, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 9: - me->SetSheath(SHEATH_STATE_RANGED); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836, 1569.755, 54.267, 4.230, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697, 1569.124, 54.421, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237, 1568.307, 54.620, 4.206, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11448.037, 1570.213, 54.961, 4.283, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_DEFIAS_RAIDER, -11449.018, 1570.738, 54.828, 4.220, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 10: - SetRun(false); - break; - case 11: - DoScriptText(SAY_DS_PROLOGUE, me); - break; - case 13: - SetEquipmentSlots(true); - me->SetSheath(SHEATH_STATE_UNARMED); - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING_NOSHEATHE); - break; - case 17: - pPlayer->GroupEventHappens(QUEST_TOME_VALOR, me); - break; - } - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - if (me->Attack(pWho, false)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(pWho, 30.0f); - } - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->AI()->AttackStart(me); - } - - void Update(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (uiShootTimer <= diff) - { - uiShootTimer = 1500; - - if (!me->IsWithinDist(me->getVictim(), ATTACK_DISTANCE)) - DoCast(me->getVictim(), SPELL_SHOOT); - } else uiShootTimer -= diff; - } -}; - -bool QuestAccept_npc_daphne_stilwell(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_TOME_VALOR) - { - DoScriptText(SAY_DS_START, pCreature); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_daphne_stilwellAI, pCreature->AI())) - pEscortAI->Start(true, true, pPlayer->GetGUID()); - } - - return true; -} - -CreatureAI* GetAI_npc_daphne_stilwell(Creature* pCreature) -{ - return new npc_daphne_stilwellAI(pCreature); -} - -/*###### -## npc_defias_traitor -######*/ - -#define SAY_START -1000101 -#define SAY_PROGRESS -1000102 -#define SAY_END -1000103 -#define SAY_AGGRO_1 -1000104 -#define SAY_AGGRO_2 -1000105 - -#define QUEST_DEFIAS_BROTHERHOOD 155 - -struct npc_defias_traitorAI : public npc_escortAI -{ - npc_defias_traitorAI(Creature *c) : npc_escortAI(c) { Reset(); } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch (i) - { - case 35: - SetRun(false); - break; - case 36: - DoScriptText(SAY_PROGRESS, me, pPlayer); - break; - case 44: - DoScriptText(SAY_END, me, pPlayer); - { - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_DEFIAS_BROTHERHOOD,me); - } - break; - } - } - void EnterCombat(Unit* who) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me, who); - } - - void Reset() {} -}; - -bool QuestAccept_npc_defias_traitor(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_DEFIAS_BROTHERHOOD) - { - if (npc_escortAI* pEscortAI = CAST_AI(npc_defias_traitorAI, pCreature->AI())) - pEscortAI->Start(true, true, pPlayer->GetGUID()); - - DoScriptText(SAY_START, pCreature, pPlayer); - } - - return true; -} - -CreatureAI* GetAI_npc_defias_traitor(Creature* pCreature) -{ - return new npc_defias_traitorAI(pCreature); -} - -void AddSC_westfall() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_daphne_stilwell"; - newscript->GetAI = &GetAI_npc_daphne_stilwell; - newscript->pQuestAccept = &QuestAccept_npc_daphne_stilwell; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_defias_traitor"; - newscript->GetAI = &GetAI_npc_defias_traitor; - newscript->pQuestAccept = &QuestAccept_npc_defias_traitor; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/wetlands.cpp b/src/server/scripts/eastern_kingdoms/wetlands.cpp deleted file mode 100644 index 02f7abdf4c2..00000000000 --- a/src/server/scripts/eastern_kingdoms/wetlands.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Wetlands -SD%Complete: 80 -SDComment: Quest support: 1249 -SDCategory: Wetlands -EndScriptData */ - -/* ContentData -npc_mikhail -npc_tapoke_slim_jahn -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_tapoke_slim_jahn -######*/ - -enum eTapokeSlim -{ - QUEST_MISSING_DIPLO_PT11 = 1249, - FACTION_ENEMY = 168, - SPELL_STEALTH = 1785, - SPELL_CALL_FRIENDS = 16457, //summons 1x friend - NPC_SLIMS_FRIEND = 4971, - NPC_TAPOKE_SLIM_JAHN = 4962 -}; - -struct npc_tapoke_slim_jahnAI : public npc_escortAI -{ - npc_tapoke_slim_jahnAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - bool m_bFriendSummoned; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - m_bFriendSummoned = false; - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 2: - if (me->HasStealthAura()) - me->RemoveAurasDueToSpell(SPELL_AURA_MOD_STEALTH); - - SetRun(); - me->setFaction(FACTION_ENEMY); - break; - } - } - - void Aggro(Unit* /*pWho*/) - { - Player* pPlayer = GetPlayerForEscort(); - - if (HasEscortState(STATE_ESCORT_ESCORTING) && !m_bFriendSummoned && pPlayer) - { - for (uint8 i = 0; i < 3; ++i) - DoCast(me, SPELL_CALL_FRIENDS, true); - - m_bFriendSummoned = true; - } - } - - void JustSummoned(Creature* pSummoned) - { - if (Player* pPlayer = GetPlayerForEscort()) - pSummoned->AI()->AttackStart(pPlayer); - } - - void AttackedBy(Unit* pAttacker) - { - if (me->getVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) - { - if (me->GetHealth()*100 < me->GetMaxHealth()*20) - { - if (Player* pPlayer = GetPlayerForEscort()) - { - if (pPlayer->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(pPlayer)->GroupEventHappens(QUEST_MISSING_DIPLO_PT11, me); - - uiDamage = 0; - - me->RestoreFaction(); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - - SetRun(false); - } - } - } -}; - -CreatureAI* GetAI_npc_tapoke_slim_jahn(Creature* pCreature) -{ - return new npc_tapoke_slim_jahnAI(pCreature); -} - -/*###### -## npc_mikhail -######*/ - -bool QuestAccept_npc_mikhail(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT11) - { - Creature* pSlim = pCreature->FindNearestCreature(NPC_TAPOKE_SLIM_JAHN, 25.0f); - - if (!pSlim) - return false; - - if (!pSlim->HasStealthAura()) - pSlim->CastSpell(pSlim, SPELL_STEALTH, true); - - if (npc_tapoke_slim_jahnAI* pEscortAI = CAST_AI(npc_tapoke_slim_jahnAI, pSlim->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); - } - return false; -} - -/*###### -## AddSC -######*/ - -void AddSC_wetlands() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_tapoke_slim_jahn"; - newscript->GetAI = &GetAI_npc_tapoke_slim_jahn; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_mikhail"; - newscript->pQuestAccept = &QuestAccept_npc_mikhail; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp b/src/server/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp deleted file mode 100644 index f516065cc03..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* Copyright ?2006 - 2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_Akilzon -SD%Complete: 75% -SDComment: Missing timer for Call Lightning and Sound ID's -SQLUpdate: -#Temporary fix for Soaring Eagles - -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" -#include "Weather.h" - -#define SPELL_STATIC_DISRUPTION 43622 -#define SPELL_STATIC_VISUAL 45265 -#define SPELL_CALL_LIGHTNING 43661 //Missing timer -#define SPELL_GUST_OF_WIND 43621 -#define SPELL_ELECTRICAL_STORM 43648 -#define SPELL_BERSERK 45078 -#define SPELL_ELECTRICAL_DAMAGE 43657 -#define SPELL_ELECTRICAL_OVERLOAD 43658 -#define SPELL_EAGLE_SWOOP 44732 - -//"Your death gonna be quick, strangers. You shoulda never have come to this place..." -#define SAY_ONAGGRO "I be da predator! You da prey..." -#define SAY_ONDEATH "You can't... kill... me spirit!" -#define SAY_ONSLAY1 "Ya got nothin'!" -#define SAY_ONSLAY2 "Stop your cryin'!" -#define SAY_ONSUMMON "Feed, me bruddahs!" -#define SAY_ONENRAGE "All you be doing is wasting my time!" -#define SOUND_ONAGGRO 12013 -#define SOUND_ONDEATH 12019 -#define SOUND_ONSLAY1 12017 -#define SOUND_ONSLAY2 12018 -#define SOUND_ONSUMMON 12014 -#define SOUND_ONENRAGE 12016 - -#define MOB_SOARING_EAGLE 24858 -#define SE_LOC_X_MAX 400 -#define SE_LOC_X_MIN 335 -#define SE_LOC_Y_MAX 1435 -#define SE_LOC_Y_MIN 1370 - -struct boss_akilzonAI : public ScriptedAI -{ - boss_akilzonAI(Creature *c) : ScriptedAI(c) - { - SpellEntry *TempSpell = GET_SPELL(SPELL_ELECTRICAL_DAMAGE); - if (TempSpell) - TempSpell->EffectBasePoints[1] = 49;//disable bugged lightning until fixed in core - pInstance = c->GetInstanceData(); - } - ScriptedInstance *pInstance; - - uint64 BirdGUIDs[8]; - uint64 TargetGUID; - uint64 CycloneGUID; - uint64 CloudGUID; - - uint32 StaticDisruption_Timer; - uint32 GustOfWind_Timer; - uint32 CallLighting_Timer; - uint32 ElectricalStorm_Timer; - uint32 SummonEagles_Timer; - uint32 Enrage_Timer; - - uint32 StormCount; - uint32 StormSequenceTimer; - - bool isRaining; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_AKILZONEVENT, NOT_STARTED); - - StaticDisruption_Timer = urand(10000,20000); //10 to 20 seconds (bosskillers) - GustOfWind_Timer = urand(20000,30000); //20 to 30 seconds(bosskillers) - CallLighting_Timer = urand(10000,20000); //totaly random timer. can't find any info on this - ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) - Enrage_Timer = 10*MINUTE*IN_MILISECONDS; //10 minutes till enrage(bosskillers) - SummonEagles_Timer = 99999; - - TargetGUID = 0; - CloudGUID = 0; - CycloneGUID = 0; - DespawnSummons(); - for (uint8 i = 0; i < 8; ++i) - BirdGUIDs[i] = 0; - - StormCount = 0; - StormSequenceTimer = 0; - - isRaining = false; - - SetWeather(WEATHER_STATE_FINE, 0.0f); - } - - void EnterCombat(Unit * /*who*/) - { - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - //DoZoneInCombat(); - if (pInstance) - pInstance->SetData(DATA_AKILZONEVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*Killer*/) - { - me->MonsterYell(SAY_ONDEATH,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me, SOUND_ONDEATH); - if (pInstance) - pInstance->SetData(DATA_AKILZONEVENT, DONE); - DespawnSummons(); - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,1)) - { - case 0: - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONSLAY1); - break; - case 1: - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONSLAY2); - break; - } - } - - void DespawnSummons() - { - for (uint8 i = 0; i < 8; ++i) - { - Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]); - if (bird && bird->isAlive()) - { - bird->SetVisibility(VISIBILITY_OFF); - bird->setDeathState(JUST_DIED); - } - } - } - - void SetWeather(uint32 weather, float grade) - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) - return; - - WorldPacket data(SMSG_WEATHER, (4+4+4)); - data << uint32(weather) << float(grade) << uint8(0); - - pMap->SendToPlayers(&data); - } - - void HandleStormSequence(Unit *Cloud) // 1: begin, 2-9: tick, 10: end - { - if (StormCount < 10 && StormCount > 1) - { - // deal damage - int32 bp0 = 800; - for (uint8 i = 2; i < StormCount; ++i) - bp0 *= 2; - - CellPair p(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - std::list tempUnitMap; - - { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, 999); - Trinity::UnitListSearcher searcher(me, tempUnitMap, u_check); - - TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); - TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); - - cell.Visit(p, world_unit_searcher, *(me->GetMap())); - cell.Visit(p, grid_unit_searcher, *(me->GetMap())); - } - //dealdamege - for (std::list::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i) - { - if (!Cloud->IsWithinDist(*i, 6, false)) - { - Cloud->CastCustomSpell(*i, 43137, &bp0, NULL, NULL, true, 0, 0, me->GetGUID()); - } - } - // visual - float x,y,z; - z = me->GetPositionZ(); - for (uint8 i = 0; i < 5+rand()%5; ++i) - { - x = 343+rand()%60; - y = 1380+rand()%60; - if (Unit *trigger = me->SummonTrigger(x, y, z, 0, 2000)) - { - trigger->setFaction(35); - trigger->SetMaxHealth(100000); - trigger->SetHealth(100000); - trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (Cloud) - Cloud->CastCustomSpell(trigger, /*43661*/43137, &bp0, NULL, NULL,true, 0, 0, Cloud->GetGUID()); - } - } - } - ++StormCount; - if (StormCount > 10) - { - StormCount = 0; // finish - SummonEagles_Timer = 5000; - me->InterruptNonMeleeSpells(false); - CloudGUID = 0; - if (Cloud) - Cloud->DealDamage(Cloud, Cloud->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - SetWeather(WEATHER_STATE_FINE, 0.0f); - isRaining = false; - } - StormSequenceTimer = 1000; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (StormCount) - { - Unit *pTarget = Unit::GetUnit(*me, CloudGUID); - if (!pTarget || !pTarget->isAlive()) - { - EnterEvadeMode(); - return; - } - else if (Unit* Cyclone = Unit::GetUnit(*me, CycloneGUID)) - Cyclone->CastSpell(pTarget, 25160, true); // keep casting or... - - if (StormSequenceTimer <= diff) - HandleStormSequence(pTarget); - else - StormSequenceTimer -= diff; - - return; - } - - if (Enrage_Timer <= diff) - { - me->MonsterYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONENRAGE); - DoCast(me, SPELL_BERSERK, true); - Enrage_Timer = 600000; - } else Enrage_Timer -= diff; - - if (StaticDisruption_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) pTarget = me->getVictim(); - TargetGUID = pTarget->GetGUID(); - DoCast(pTarget, SPELL_STATIC_DISRUPTION, false); - me->SetInFront(me->getVictim()); - StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s - - /*if (float dist = me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f) dist = 5.0f; - SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/ - } else StaticDisruption_Timer -= diff; - - if (GustOfWind_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) pTarget = me->getVictim(); - DoCast(pTarget, SPELL_GUST_OF_WIND); - GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers) - } else GustOfWind_Timer -= diff; - - if (CallLighting_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CALL_LIGHTNING); - CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this - } else CallLighting_Timer -= diff; - - if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000) - { - SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f); - isRaining = true; - } - - if (ElectricalStorm_Timer <= diff) { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); - if (!pTarget) - { - EnterEvadeMode(); - return; - } - pTarget->CastSpell(pTarget, 44007, true);//cloud visual - DoCast(pTarget, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual - float x,y,z; - pTarget->GetPosition(x,y,z); - if (pTarget) - { - pTarget->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - pTarget->SendMonsterMove(x,y,me->GetPositionZ()+15,0); - } - Unit *Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000); - if (Cloud) - { - CloudGUID = Cloud->GetGUID(); - Cloud->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - Cloud->StopMoving(); - Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); - Cloud->setFaction(35); - Cloud->SetMaxHealth(9999999); - Cloud->SetHealth(9999999); - Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) - StormCount = 1; - StormSequenceTimer = 0; - } else ElectricalStorm_Timer -= diff; - - if (SummonEagles_Timer <= diff) - { - me->MonsterYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONSUMMON); - - float x, y, z; - me->GetPosition(x, y, z); - - for (uint8 i = 0; i < 8; ++i) - { - Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]); - if (!bird) //they despawned on die - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - x = pTarget->GetPositionX() + irand(-10,10); - y = pTarget->GetPositionY() + irand(-10,10); - z = pTarget->GetPositionZ() + urand(16,20); - if (z > 95) - z = 95 - urand(0,5); - } - Creature *pCreature = me->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (pCreature) - { - pCreature->AddThreat(me->getVictim(), 1.0f); - pCreature->AI()->AttackStart(me->getVictim()); - BirdGUIDs[i] = pCreature->GetGUID(); - } - } - } - SummonEagles_Timer = 999999; - } else SummonEagles_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soaring_eagleAI : public ScriptedAI -{ - mob_soaring_eagleAI(Creature *c) : ScriptedAI(c) {} - - uint32 EagleSwoop_Timer; - bool arrived; - uint32 TargetGUID; - - void Reset() - { - EagleSwoop_Timer = 5000 + rand()%5000; - arrived = true; - TargetGUID = 0; - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - } - - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - - void MoveInLineOfSight(Unit* /*who*/) {} - - void MovementInform(uint32, uint32) - { - arrived = true; - if (TargetGUID) - { - if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID)) - DoCast(pTarget, SPELL_EAGLE_SWOOP, true); - TargetGUID = 0; - me->SetSpeed(MOVE_RUN, 1.2f); - EagleSwoop_Timer = 5000 + rand()%5000; - } - } - - void UpdateAI(const uint32 diff) - { - if (EagleSwoop_Timer <= diff) - EagleSwoop_Timer = 0; - else - EagleSwoop_Timer -= diff; - - if (arrived) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - if (EagleSwoop_Timer) - { - x = pTarget->GetPositionX() + irand(-10,10); - y = pTarget->GetPositionY() + irand(-10,10); - z = pTarget->GetPositionZ() + urand(10,15); - if (z > 95) - z = 95 - urand(0,5); - } - else - { - pTarget->GetContactPoint(me, x, y, z); - z += 2; - me->SetSpeed(MOVE_RUN, 5.0f); - TargetGUID = pTarget->GetGUID(); - } - me->GetMotionMaster()->MovePoint(0, x, y, z); - arrived = false; - } - } - } -}; - -//Soaring Eagle -CreatureAI* GetAI_mob_soaring_eagle(Creature* pCreature) -{ - return new mob_soaring_eagleAI(pCreature); -} - -CreatureAI* GetAI_boss_akilzon(Creature* pCreature) -{ - return new boss_akilzonAI(pCreature); -} - -void AddSC_boss_akilzon() -{ - Script *newscript = NULL; - - newscript = new Script; - newscript->Name = "boss_akilzon"; - newscript->GetAI = &GetAI_boss_akilzon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_akilzon_eagle"; - newscript->GetAI = &GetAI_mob_soaring_eagle; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp b/src/server/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp deleted file mode 100644 index aee0a8a59ea..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_Halazzi -SD%Complete: 80 -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" -//#include "spell.h" - -#define YELL_AGGRO "Get on your knees and bow to da fang and claw!" -#define SOUND_AGGRO 12020 -#define YELL_SABER_ONE "You gonna leave in pieces!" -#define YELL_SABER_TWO "Me gonna carve ya now!" -#define YELL_SPLIT "Me gonna carve ya now!" -#define SOUND_SPLIT 12021 -#define YELL_MERGE "Spirit, come back to me!" -#define SOUND_MERGE 12022 -#define YELL_KILL_ONE "You cant fight the power!" -#define SOUND_KILL_ONE 12026 -#define YELL_KILL_TWO "You gonna fail!" -#define SOUND_KILL_TWO 12027 -#define YELL_DEATH "Chaga... choka'jinn." -#define SOUND_DEATH 12028 -#define YELL_BERSERK "Whatch you be doing? Pissin' yourselves..." -#define SOUND_BERSERK 12025 - -#define SPELL_DUAL_WIELD 29651 -#define SPELL_SABER_LASH 43267 -#define SPELL_FRENZY 43139 -#define SPELL_FLAMESHOCK 43303 -#define SPELL_EARTHSHOCK 43305 -#define SPELL_TRANSFORM_SPLIT 43142 -#define SPELL_TRANSFORM_SPLIT2 43573 -#define SPELL_TRANSFORM_MERGE 43271 -#define SPELL_SUMMON_LYNX 43143 -#define SPELL_SUMMON_TOTEM 43302 -#define SPELL_BERSERK 45078 - -#define MOB_SPIRIT_LYNX 24143 -#define SPELL_LYNX_FRENZY 43290 -#define SPELL_SHRED_ARMOR 43243 - -#define MOB_TOTEM 24224 -#define SPELL_LIGHTNING 43301 - -enum PhaseHalazzi -{ - PHASE_NONE = 0, - PHASE_LYNX = 1, - PHASE_SPLIT = 2, - PHASE_HUMAN = 3, - PHASE_MERGE = 4, - PHASE_ENRAGE = 5 -}; - -struct boss_halazziAI : public ScriptedAI -{ - boss_halazziAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - // need to find out what controls totem's spell cooldown - SpellEntry *TempSpell = GET_SPELL(SPELL_LIGHTNING); - if (TempSpell && TempSpell->CastingTimeIndex != 5) - TempSpell->CastingTimeIndex = 5; // 2000 ms casting time - } - - ScriptedInstance *pInstance; - - uint32 FrenzyTimer; - uint32 SaberlashTimer; - uint32 ShockTimer; - uint32 TotemTimer; - uint32 CheckTimer; - uint32 BerserkTimer; - - uint32 TransformCount; - - PhaseHalazzi Phase; - - uint64 LynxGUID; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_HALAZZIEVENT, NOT_STARTED); - - TransformCount = 0; - BerserkTimer = 600000; - CheckTimer = 1000; - - DoCast(me, SPELL_DUAL_WIELD, true); - - Phase = PHASE_NONE; - EnterPhase(PHASE_LYNX); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS); - - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_AGGRO); - - EnterPhase(PHASE_LYNX); - } - - void JustSummoned(Creature* summon) - { - summon->AI()->AttackStart(me->getVictim()); - if (summon->GetEntry() == MOB_SPIRIT_LYNX) - LynxGUID = summon->GetGUID(); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE) - damage = 0; - } - - void SpellHit(Unit*, const SpellEntry *spell) - { - if (spell->Id == SPELL_TRANSFORM_SPLIT2) - EnterPhase(PHASE_HUMAN); - } - - void AttackStart(Unit *who) - { - if (Phase != PHASE_MERGE) ScriptedAI::AttackStart(who); - } - - void EnterPhase(PhaseHalazzi NextPhase) - { - switch(NextPhase) - { - case PHASE_LYNX: - case PHASE_ENRAGE: - if (Phase == PHASE_MERGE) - { - DoCast(me, SPELL_TRANSFORM_MERGE, true); - me->Attack(me->getVictim(), true); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - if (Creature *Lynx = Unit::GetCreature(*me, LynxGUID)) - Lynx->DisappearAndDie(); - me->SetMaxHealth(600000); - me->SetHealth(600000 - 150000 * TransformCount); - FrenzyTimer = 16000; - SaberlashTimer = 20000; - ShockTimer = 10000; - TotemTimer = 12000; - break; - case PHASE_SPLIT: - me->MonsterYell(YELL_SPLIT, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_SPLIT); - DoCast(me, SPELL_TRANSFORM_SPLIT, true); - break; - case PHASE_HUMAN: - //DoCast(me, SPELL_SUMMON_LYNX, true); - DoSpawnCreature(MOB_SPIRIT_LYNX, 5,5,0,0, TEMPSUMMON_CORPSE_DESPAWN, 0); - me->SetMaxHealth(400000); - me->SetHealth(400000); - ShockTimer = 10000; - TotemTimer = 12000; - break; - case PHASE_MERGE: - if (Unit *pLynx = Unit::GetUnit(*me, LynxGUID)) - { - me->MonsterYell(YELL_MERGE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_MERGE); - pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pLynx->GetMotionMaster()->Clear(); - pLynx->GetMotionMaster()->MoveFollow(me, 0, 0); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveFollow(pLynx, 0, 0); - ++TransformCount; - } - break; - default: - break; - } - Phase = NextPhase; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BerserkTimer <= diff) - { - me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_BERSERK); - DoCast(me, SPELL_BERSERK, true); - BerserkTimer = 60000; - } else BerserkTimer -= diff; - - if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE) - { - if (SaberlashTimer <= diff) - { - // A tank with more than 490 defense skills should receive no critical hit - //DoCast(me, 41296, true); - DoCast(me->getVictim(), SPELL_SABER_LASH, true); - //me->RemoveAurasDueToSpell(41296); - SaberlashTimer = 30000; - } else SaberlashTimer -= diff; - - if (FrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - FrenzyTimer = urand(10000,15000); - } else FrenzyTimer -= diff; - - if (Phase == PHASE_LYNX) - if (CheckTimer <= diff) - { - if (me->GetHealth() * 4 < me->GetMaxHealth() * (3 - TransformCount)) - EnterPhase(PHASE_SPLIT); - CheckTimer = 1000; - } else CheckTimer -= diff; - } - - if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE) - { - if (TotemTimer <= diff) - { - DoCast(me, SPELL_SUMMON_TOTEM); - TotemTimer = 20000; - } else TotemTimer -= diff; - - if (ShockTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget->IsNonMeleeSpellCasted(false)) - DoCast(pTarget, SPELL_EARTHSHOCK); - else - DoCast(pTarget, SPELL_FLAMESHOCK); - ShockTimer = 10000 + rand()%5000; - } - } else ShockTimer -= diff; - - if (Phase == PHASE_HUMAN) - if (CheckTimer <= diff) - { - if (((me->GetHealth()*100) / me->GetMaxHealth() <= 20)/*me->GetHealth() * 10 < me->GetMaxHealth()*/) - EnterPhase(PHASE_MERGE); - else - { - Unit *Lynx = Unit::GetUnit(*me, LynxGUID); - if (Lynx && ((Lynx->GetHealth()*100) / Lynx->GetMaxHealth() <= 20)/*Lynx->GetHealth() * 10 < Lynx->GetMaxHealth()*/) - EnterPhase(PHASE_MERGE); - } - CheckTimer = 1000; - } else CheckTimer -= diff; - } - - if (Phase == PHASE_MERGE) - { - if (CheckTimer <= diff) - { - Unit *Lynx = Unit::GetUnit(*me, LynxGUID); - if (Lynx) - { - Lynx->GetMotionMaster()->MoveFollow(me, 0, 0); - me->GetMotionMaster()->MoveFollow(Lynx, 0, 0); - if (me->IsWithinDistInMap(Lynx, 6.0f)) - { - if (TransformCount < 3) - EnterPhase(PHASE_LYNX); - else - EnterPhase(PHASE_ENRAGE); - } - } - CheckTimer = 1000; - } else CheckTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,1)) - { - case 0: - me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL_ONE); - break; - - case 1: - me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL_TWO); - break; - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_HALAZZIEVENT, DONE); - - me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_DEATH); - } -}; - -// Spirits Lynx AI - -struct boss_spiritlynxAI : public ScriptedAI -{ - boss_spiritlynxAI(Creature *c) : ScriptedAI(c) {} - - uint32 FrenzyTimer; - uint32 shredder_timer; - - void Reset() - { - FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds - shredder_timer = 4000; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - damage = 0; - } - - void AttackStart(Unit *who) - { - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (FrenzyTimer <= diff) - { - DoCast(me, SPELL_LYNX_FRENZY); - FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds - } else FrenzyTimer -= diff; - - if (shredder_timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHRED_ARMOR); - shredder_timer = 4000; - } else shredder_timer -= diff; - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_boss_halazziAI(Creature* pCreature) -{ - return new boss_halazziAI (pCreature); -} - -CreatureAI* GetAI_boss_spiritlynxAI(Creature* pCreature) -{ - return new boss_spiritlynxAI (pCreature); -} - -void AddSC_boss_halazzi() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_halazzi"; - newscript->GetAI = &GetAI_boss_halazziAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_halazzi_lynx"; - newscript->GetAI = &GetAI_boss_spiritlynxAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulaman/boss_hexlord.cpp b/src/server/scripts/eastern_kingdoms/zulaman/boss_hexlord.cpp deleted file mode 100644 index 7baa9292142..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/boss_hexlord.cpp +++ /dev/null @@ -1,907 +0,0 @@ -/* Copyright ?2006,2007 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Hex_Lord_Malacrass -SD%Complete: -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" - -#define YELL_AGGRO "Da shadow gonna fall on you... " -#define SOUND_YELL_AGGRO 12041 -#define YELL_SPIRIT_BOLTS "Your soul gonna bleed!" -#define SOUND_YELL_SPIRIT_BOLTS 12047 -#define YELL_DRAIN_POWER "Darkness comin\' for you" -#define SOUND_YELL_DRAIN_POWER 12046 -#define YELL_KILL_ONE "Dis a nightmare ya don\' wake up from!" -#define SOUND_YELL_KILL_ONE 12043 -#define YELL_KILL_TWO "Azzaga choogo zinn!" -#define SOUND_YELL_KILL_TWO 12044 -#define YELL_DEATH "Dis not... da end of me..." -#define SOUND_YELL_DEATH 12051 - -#define SPELL_SPIRIT_BOLTS 43383 -#define SPELL_DRAIN_POWER 44131 -#define SPELL_SIPHON_SOUL 43501 - -#define MOB_TEMP_TRIGGER 23920 - -//Defines for various powers he uses after using soul drain - -//Druid -#define SPELL_DR_LIFEBLOOM 43421 -#define SPELL_DR_THORNS 43420 -#define SPELL_DR_MOONFIRE 43545 - -//Hunter -#define SPELL_HU_EXPLOSIVE_TRAP 43444 -#define SPELL_HU_FREEZING_TRAP 43447 -#define SPELL_HU_SNAKE_TRAP 43449 - -//Mage -#define SPELL_MG_FIREBALL 41383 -#define SPELL_MG_FROSTBOLT 43428 -#define SPELL_MG_FROST_NOVA 43426 -#define SPELL_MG_ICE_LANCE 43427 - -//Paladin -#define SPELL_PA_CONSECRATION 43429 -#define SPELL_PA_HOLY_LIGHT 43451 -#define SPELL_PA_AVENGING_WRATH 43430 - -//Priest -#define SPELL_PR_HEAL 41372 -#define SPELL_PR_MIND_CONTROL 43550 -#define SPELL_PR_MIND_BLAST 41374 -#define SPELL_PR_SW_DEATH 41375 -#define SPELL_PR_PSYCHIC_SCREAM 43432 -#define SPELL_PR_PAIN_SUPP 44416 - -//Rogue -#define SPELL_RO_BLIND 43433 -#define SPELL_RO_SLICE_DICE 43457 -#define SPELL_RO_WOUND_POISON 39665 - -//Shaman -#define SPELL_SH_FIRE_NOVA 43436 -#define SPELL_SH_HEALING_WAVE 43548 -#define SPELL_SH_CHAIN_LIGHT 43435 - -//Warlock -#define SPELL_WL_CURSE_OF_DOOM 43439 -#define SPELL_WL_RAIN_OF_FIRE 43440 -#define SPELL_WL_UNSTABLE_AFFL 35183 - -//Warrior -#define SPELL_WR_SPELL_REFLECT 43443 -#define SPELL_WR_WHIRLWIND 43442 -#define SPELL_WR_MORTAL_STRIKE 43441 - -#define ORIENT 1.5696 -#define POS_Y 921.2795 -#define POS_Z 33.8883 - -static float Pos_X[4] = {112.8827, 107.8827, 122.8827, 127.8827}; - -static uint32 AddEntryList[8]= -{ - 24240, //Alyson Antille - 24241, //Thurg - 24242, //Slither - 24243, //Lord Raadan - 24244, //Gazakroth - 24245, //Fenstalker - 24246, //Darkheart - 24247 //Koragg -}; - -enum AbilityTarget -{ - ABILITY_TARGET_SELF = 0, - ABILITY_TARGET_VICTIM = 1, - ABILITY_TARGET_ENEMY = 2, - ABILITY_TARGET_HEAL = 3, - ABILITY_TARGET_BUFF = 4, - ABILITY_TARGET_SPECIAL = 5 -}; - -struct PlayerAbilityStruct -{ - uint32 spell; - AbilityTarget target; - uint32 cooldown; -}; - -static PlayerAbilityStruct PlayerAbility[][3] = -{ - // 1 warrior - {{SPELL_WR_SPELL_REFLECT, ABILITY_TARGET_SELF, 10000}, - {SPELL_WR_WHIRLWIND, ABILITY_TARGET_SELF, 10000}, - {SPELL_WR_MORTAL_STRIKE, ABILITY_TARGET_VICTIM, 6000}}, - // 2 paladin - {{SPELL_PA_CONSECRATION, ABILITY_TARGET_SELF, 10000}, - {SPELL_PA_HOLY_LIGHT, ABILITY_TARGET_HEAL, 10000}, - {SPELL_PA_AVENGING_WRATH, ABILITY_TARGET_SELF, 10000}}, - // 3 hunter - {{SPELL_HU_EXPLOSIVE_TRAP, ABILITY_TARGET_SELF, 10000}, - {SPELL_HU_FREEZING_TRAP, ABILITY_TARGET_SELF, 10000}, - {SPELL_HU_SNAKE_TRAP, ABILITY_TARGET_SELF, 10000}}, - // 4 rogue - {{SPELL_RO_WOUND_POISON, ABILITY_TARGET_VICTIM, 3000}, - {SPELL_RO_SLICE_DICE, ABILITY_TARGET_SELF, 10000}, - {SPELL_RO_BLIND, ABILITY_TARGET_ENEMY, 10000}}, - // 5 priest - {{SPELL_PR_PAIN_SUPP, ABILITY_TARGET_HEAL, 10000}, - {SPELL_PR_HEAL, ABILITY_TARGET_HEAL, 10000}, - {SPELL_PR_PSYCHIC_SCREAM, ABILITY_TARGET_SELF, 10000}}, - // 5* shadow priest - {{SPELL_PR_MIND_CONTROL, ABILITY_TARGET_ENEMY, 15000}, - {SPELL_PR_MIND_BLAST, ABILITY_TARGET_ENEMY, 5000}, - {SPELL_PR_SW_DEATH, ABILITY_TARGET_ENEMY, 10000}}, - // 7 shaman - {{SPELL_SH_FIRE_NOVA, ABILITY_TARGET_SELF, 10000}, - {SPELL_SH_HEALING_WAVE, ABILITY_TARGET_HEAL, 10000}, - {SPELL_SH_CHAIN_LIGHT, ABILITY_TARGET_ENEMY, 8000}}, - // 8 mage - {{SPELL_MG_FIREBALL, ABILITY_TARGET_ENEMY, 5000}, - {SPELL_MG_FROSTBOLT, ABILITY_TARGET_ENEMY, 5000}, - {SPELL_MG_ICE_LANCE, ABILITY_TARGET_SPECIAL, 2000}}, - // 9 warlock - {{SPELL_WL_CURSE_OF_DOOM, ABILITY_TARGET_ENEMY, 10000}, - {SPELL_WL_RAIN_OF_FIRE, ABILITY_TARGET_ENEMY, 10000}, - {SPELL_WL_UNSTABLE_AFFL, ABILITY_TARGET_ENEMY, 10000}}, - // 11 druid - {{SPELL_DR_LIFEBLOOM, ABILITY_TARGET_HEAL, 10000}, - {SPELL_DR_THORNS, ABILITY_TARGET_SELF, 10000}, - {SPELL_DR_MOONFIRE, ABILITY_TARGET_ENEMY, 8000}} -}; - -struct boss_hexlord_addAI : public ScriptedAI -{ - ScriptedInstance* pInstance; - - boss_hexlord_addAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() {} - - void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} - - void UpdateAI(const uint32 /*diff*/) - { - if (pInstance && pInstance->GetData(DATA_HEXLORDEVENT) != IN_PROGRESS) - { - EnterEvadeMode(); - return; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_hex_lord_malacrassAI : public ScriptedAI -{ - boss_hex_lord_malacrassAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - SelectAddEntry(); - for (uint8 i = 0; i < 4; ++i) - AddGUID[i] = 0; - } - - ScriptedInstance *pInstance; - - uint64 AddGUID[4]; - uint32 AddEntry[4]; - - uint64 PlayerGUID; - - uint32 SpiritBolts_Timer; - uint32 DrainPower_Timer; - uint32 SiphonSoul_Timer; - uint32 PlayerAbility_Timer; - uint32 CheckAddState_Timer; - uint32 ResetTimer; - - uint32 PlayerClass; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_HEXLORDEVENT, NOT_STARTED); - - SpiritBolts_Timer = 20000; - DrainPower_Timer = 60000; - SiphonSoul_Timer = 100000; - PlayerAbility_Timer = 99999; - CheckAddState_Timer = 5000; - ResetTimer = 5000; - - SpawnAdds(); - - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 46916); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HEXLORDEVENT, IN_PROGRESS); - - DoZoneInCombat(); - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_AGGRO); - - for (uint8 i = 0; i < 4; ++i) - { - Unit* Temp = Unit::GetUnit((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - CAST_CRE(Temp)->AI()->AttackStart(me->getVictim()); - else - { - EnterEvadeMode(); - break; - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,1)) - { - case 0: - me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); - break; - case 1: - me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); - break; - } - } - - void JustDied(Unit* /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_HEXLORDEVENT, DONE); - - me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_DEATH); - - for (uint8 i = 0; i < 4 ; ++i) - { - Unit* Temp = Unit::GetUnit((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - Temp->DealDamage(Temp, Temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - void SelectAddEntry() - { - std::vector AddList; - - for (uint8 i = 0; i < 8; ++i) - AddList.push_back(AddEntryList[i]); - - while (AddList.size() > 4) - AddList.erase(AddList.begin()+rand()%AddList.size()); - - uint8 i = 0; - for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr, ++i) - AddEntry[i] = *itr; - } - - void SpawnAdds() - { - for (uint8 i = 0; i < 4; ++i) - { - Creature *pCreature = (Unit::GetCreature((*me), AddGUID[i])); - if (!pCreature || !pCreature->isAlive()) - { - if (pCreature) pCreature->setDeathState(DEAD); - pCreature = me->SummonCreature(AddEntry[i], Pos_X[i], POS_Y, POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0); - if (pCreature) AddGUID[i] = pCreature->GetGUID(); - } - else - { - pCreature->AI()->EnterEvadeMode(); - pCreature->GetMap()->CreatureRelocation(me, Pos_X[i], POS_Y, POS_Z, ORIENT); - pCreature->StopMoving(); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ResetTimer <= diff) - { - if (me->IsWithinDist3d(119.223, 1035.45, 29.4481, 10)) - { - EnterEvadeMode(); - return; - } - ResetTimer = 5000; - } else ResetTimer -= diff; - - if (CheckAddState_Timer <= diff) - { - for (uint8 i = 0; i < 4; ++i) - if (Creature *pTemp = Unit::GetCreature(*me, AddGUID[i])) - if (pTemp->isAlive() && !pTemp->getVictim()) - pTemp->AI()->AttackStart(me->getVictim()); - - CheckAddState_Timer = 5000; - } else CheckAddState_Timer -= diff; - - if (DrainPower_Timer <= diff) - { - DoCast(me, SPELL_DRAIN_POWER, true); - me->MonsterYell(YELL_DRAIN_POWER, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_DRAIN_POWER); - DrainPower_Timer = urand(40000,55000); // must cast in 60 sec, or buff/debuff will disappear - } else DrainPower_Timer -= diff; - - if (SpiritBolts_Timer <= diff) - { - if (DrainPower_Timer < 12000) // channel 10 sec - SpiritBolts_Timer = 13000; // cast drain power first - else - { - DoCast(me, SPELL_SPIRIT_BOLTS, false); - me->MonsterYell(YELL_SPIRIT_BOLTS, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_SPIRIT_BOLTS); - SpiritBolts_Timer = 40000; - SiphonSoul_Timer = 10000; // ready to drain - PlayerAbility_Timer = 99999; - } - } else SpiritBolts_Timer -= diff; - - if (SiphonSoul_Timer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 70, true); - Unit *trigger = DoSpawnCreature(MOB_TEMP_TRIGGER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); - if (!pTarget || !trigger) - { - EnterEvadeMode(); - return; - } - else - { - trigger->SetDisplayId(11686); - trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - trigger->CastSpell(pTarget, SPELL_SIPHON_SOUL, true); - trigger->GetMotionMaster()->MoveChase(me); - - //DoCast(pTarget, SPELL_SIPHON_SOUL, true); - //me->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pTarget->GetGUID()); - //me->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SIPHON_SOUL); - - PlayerGUID = pTarget->GetGUID(); - PlayerAbility_Timer = urand(8000,10000); - PlayerClass = pTarget->getClass() - 1; - - if (PlayerClass == CLASS_DRUID-1) - PlayerClass = CLASS_DRUID; - else if (PlayerClass == CLASS_PRIEST-1 && pTarget->HasSpell(15473)) - PlayerClass = CLASS_PRIEST; // shadow priest - - SiphonSoul_Timer = 99999; // buff lasts 30 sec - } - } else SiphonSoul_Timer -= diff; - - if (PlayerAbility_Timer <= diff) - { - //Unit *pTarget = Unit::GetUnit(*me, PlayerGUID); - //if (pTarget && pTarget->isAlive()) - //{ - UseAbility(); - PlayerAbility_Timer = urand(8000,10000); - //} - } else PlayerAbility_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - void UseAbility() - { - uint8 random = urand(0,2); - Unit *pTarget = NULL; - switch(PlayerAbility[PlayerClass][random].target) - { - case ABILITY_TARGET_SELF: - pTarget = me; - break; - case ABILITY_TARGET_VICTIM: - pTarget = me->getVictim(); - break; - case ABILITY_TARGET_ENEMY: - default: - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - break; - case ABILITY_TARGET_HEAL: - pTarget = DoSelectLowestHpFriendly(50, 0); - break; - case ABILITY_TARGET_BUFF: - { - std::list templist = DoFindFriendlyMissingBuff(50, PlayerAbility[PlayerClass][random].spell); - if (!templist.empty()) - pTarget = *(templist.begin()); - } - break; - } - if (pTarget) - DoCast(pTarget, PlayerAbility[PlayerClass][random].spell, false); - } -}; - -#define SPELL_BLOODLUST 43578 -#define SPELL_CLEAVE 15496 - -struct boss_thurgAI : public boss_hexlord_addAI -{ - - boss_thurgAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 bloodlust_timer; - uint32 cleave_timer; - - void Reset() - { - bloodlust_timer = 15000; - cleave_timer = 10000; - - boss_hexlord_addAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (bloodlust_timer <= diff) - { - std::list templist = DoFindFriendlyMissingBuff(50, SPELL_BLOODLUST); - if (!templist.empty()) - { - if (Unit *pTarget = *(templist.begin())) - DoCast(pTarget, SPELL_BLOODLUST, false); - } - bloodlust_timer = 12000; - } else bloodlust_timer -= diff; - - if (cleave_timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE, false); - cleave_timer = 12000; //3 sec cast - } else cleave_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_FLASH_HEAL 43575 -#define SPELL_DISPEL_MAGIC 43577 - -struct boss_alyson_antilleAI : public boss_hexlord_addAI -{ - //Holy Priest - boss_alyson_antilleAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 flashheal_timer; - uint32 dispelmagic_timer; - - void Reset() - { - flashheal_timer = 2500; - dispelmagic_timer = 10000; - - //AcquireGUID(); - - boss_hexlord_addAI::Reset(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack()) - { - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, 20); - me->AddThreat(who, 0.0f); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (flashheal_timer <= diff) - { - Unit *pTarget = DoSelectLowestHpFriendly(99, 30000); - if (pTarget) - { - if (pTarget->IsWithinDistInMap(me, 50)) - DoCast(pTarget, SPELL_FLASH_HEAL, false); - else - { - // bugged - //me->GetMotionMaster()->Clear(); - //me->GetMotionMaster()->MoveChase(pTarget, 20); - } - } - else - { - if (urand(0,1)) - pTarget = DoSelectLowestHpFriendly(50, 0); - else - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_DISPEL_MAGIC, false); - } - flashheal_timer = 2500; - } else flashheal_timer -= diff; - - /*if (dispelmagic_timer <= diff) - { - if (urand(0,1)) - { - Unit *pTarget = SelectTarget(); - - DoCast(pTarget, SPELL_DISPEL_MAGIC, false); - } - else - me->CastSpell(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DISPEL_MAGIC, false); - - dispelmagic_timer = 12000; - } else dispelmagic_timer -= diff;*/ - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_FIREBOLT 43584 - -struct boss_gazakrothAI : public boss_hexlord_addAI -{ - boss_gazakrothAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 firebolt_timer; - - void Reset() - { - firebolt_timer = 2000; - boss_hexlord_addAI::Reset(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack()) - { - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, 20); - me->AddThreat(who, 0.0f); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (firebolt_timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBOLT, false); - firebolt_timer = 700; - } else firebolt_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_FLAME_BREATH 43582 -#define SPELL_THUNDERCLAP 43583 - -struct boss_lord_raadanAI : public boss_hexlord_addAI -{ - boss_lord_raadanAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 flamebreath_timer; - uint32 thunderclap_timer; - - void Reset() - { - flamebreath_timer = 8000; - thunderclap_timer = 13000; - - boss_hexlord_addAI::Reset(); - - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (thunderclap_timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP, false); - thunderclap_timer = 12000; - } else thunderclap_timer -= diff; - - if (flamebreath_timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAME_BREATH, false); - flamebreath_timer = 12000; - } else flamebreath_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_PSYCHIC_WAIL 43590 - -struct boss_darkheartAI : public boss_hexlord_addAI -{ - boss_darkheartAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 psychicwail_timer; - - void Reset() - { - psychicwail_timer = 8000; - boss_hexlord_addAI::Reset(); - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (psychicwail_timer <= diff) - { - DoCast(me->getVictim(), SPELL_PSYCHIC_WAIL, false); - psychicwail_timer = 12000; - } else psychicwail_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_VENOM_SPIT 43579 - -struct boss_slitherAI : public boss_hexlord_addAI -{ - boss_slitherAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 venomspit_timer; - - void Reset() - { - venomspit_timer = 5000; - boss_hexlord_addAI::Reset(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack()) - { - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, 20); - me->AddThreat(who, 0.0f); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (venomspit_timer <= diff) - { - if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(victim, SPELL_VENOM_SPIT, false); - venomspit_timer = 2500; - } else venomspit_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -//Fenstalker -#define SPELL_VOLATILE_INFECTION 43586 - -struct boss_fenstalkerAI : public boss_hexlord_addAI -{ - boss_fenstalkerAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 volatileinf_timer; - - void Reset() - { - volatileinf_timer = 15000; - boss_hexlord_addAI::Reset(); - - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (volatileinf_timer <= diff) - { - // core bug - me->getVictim()->CastSpell(me->getVictim(),SPELL_VOLATILE_INFECTION, false); - volatileinf_timer = 12000; - } else volatileinf_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -//Koragg -#define SPELL_COLD_STARE 43593 -#define SPELL_MIGHTY_BLOW 43592 - -struct boss_koraggAI : public boss_hexlord_addAI -{ - boss_koraggAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 coldstare_timer; - uint32 mightyblow_timer; - - void Reset() - { - coldstare_timer = 15000; - mightyblow_timer = 10000; - boss_hexlord_addAI::Reset(); - - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (mightyblow_timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, false); - mightyblow_timer = 12000; - } - if (coldstare_timer <= diff) - { - if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(victim, SPELL_COLD_STARE, false); - coldstare_timer = 12000; - } - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_boss_hex_lord_malacrass(Creature* pCreature) -{ - return new boss_hex_lord_malacrassAI (pCreature); -} - -CreatureAI* GetAI_boss_thurg(Creature* pCreature) -{ - return new boss_thurgAI (pCreature); -} - -CreatureAI* GetAI_boss_alyson_antille(Creature* pCreature) -{ - return new boss_alyson_antilleAI (pCreature); -} - -CreatureAI* GetAI_boss_gazakroth(Creature* pCreature) -{ - return new boss_gazakrothAI (pCreature); -} - -CreatureAI* GetAI_boss_lord_raadan(Creature* pCreature) -{ - return new boss_lord_raadanAI (pCreature); -} - -CreatureAI* GetAI_boss_darkheart(Creature* pCreature) -{ - return new boss_darkheartAI (pCreature); -} - -CreatureAI* GetAI_boss_slither(Creature* pCreature) -{ - return new boss_slitherAI (pCreature); -} - -CreatureAI* GetAI_boss_fenstalker(Creature* pCreature) -{ - return new boss_fenstalkerAI (pCreature); -} - -CreatureAI* GetAI_boss_koragg(Creature* pCreature) -{ - return new boss_koraggAI (pCreature); -} -void AddSC_boss_hex_lord_malacrass() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hexlord_malacrass"; - newscript->GetAI = &GetAI_boss_hex_lord_malacrass; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_thurg"; - newscript->GetAI = &GetAI_boss_thurg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_gazakroth"; - newscript->GetAI = &GetAI_boss_gazakroth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_raadan"; - newscript->GetAI = &GetAI_boss_lord_raadan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_darkheart"; - newscript->GetAI = &GetAI_boss_darkheart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_slither"; - newscript->GetAI = &GetAI_boss_slither; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fenstalker"; - newscript->GetAI = &GetAI_boss_fenstalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_koragg"; - newscript->GetAI = &GetAI_boss_koragg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_alyson_antille"; - newscript->GetAI = &GetAI_boss_alyson_antille; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp b/src/server/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp deleted file mode 100644 index 9ac54976241..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp +++ /dev/null @@ -1,687 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -*(at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Janalai -SD%Complete: 100 -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" -#include "GridNotifiers.h" - -enum eEnums -{ - SAY_AGGRO = -1568000, - SAY_FIRE_BOMBS = -1568001, - SAY_SUMMON_HATCHER = -1568002, - SAY_ALL_EGGS = -1568003, - SAY_BERSERK = -1568004, - SAY_SLAY_1 = -1568005, - SAY_SLAY_2 = -1568006, - SAY_DEATH = -1568007, - SAY_EVENT_STRANGERS = -1568008, - SAY_EVENT_FRIENDS = -1568009, - -// Jan'alai - SPELL_FLAME_BREATH = 43140, - SPELL_FIRE_WALL = 43113, - SPELL_ENRAGE = 44779, - SPELL_SUMMON_PLAYERS = 43097, - SPELL_TELE_TO_CENTER = 43098, // coord - SPELL_HATCH_ALL = 43144, - SPELL_BERSERK = 45078, - -// -- Fire Bob Spells - SPELL_FIRE_BOMB_CHANNEL = 42621, // last forever - SPELL_FIRE_BOMB_THROW = 42628, // throw visual - SPELL_FIRE_BOMB_DUMMY = 42629, // bomb visual - SPELL_FIRE_BOMB_DAMAGE = 42630, - -// --Summons - MOB_AMANI_HATCHER = 23818, - MOB_HATCHLING = 23598, // 42493 - MOB_EGG = 23817, - MOB_FIRE_BOMB = 23920, - -// -- Hatcher Spells - SPELL_HATCH_EGG = 43734, // 42471 - -// -- Hatchling Spells - SPELL_FLAMEBUFFET = 43299 -}; - -const int area_dx = 44; -const int area_dy = 51; - -float JanalainPos[1][3] = -{ - {-33.93, 1149.27, 19} -}; - -float FireWallCoords[4][4] = -{ - {-10.13, 1149.27, 19, 3.1415}, - {-33.93, 1123.90, 19, 0.5*3.1415}, - {-54.80, 1150.08, 19, 0}, - {-33.93, 1175.68, 19, 1.5*3.1415} -}; - -float hatcherway[2][5][3] = -{ - { - {-87.46,1170.09,6}, - {-74.41,1154.75,6}, - {-52.74,1153.32,19}, - {-33.37,1172.46,19}, - {-33.09,1203.87,19} - }, - { - {-86.57,1132.85,6}, - {-73.94,1146.00,6}, - {-52.29,1146.51,19}, - {-33.57,1125.72,19}, - {-34.29,1095.22,19} - } -}; - -struct boss_janalaiAI : public ScriptedAI -{ - boss_janalaiAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - - SpellEntry *TempSpell = GET_SPELL(SPELL_HATCH_EGG); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) - { - TempSpell->EffectImplicitTargetA[0] = 1; - TempSpell->EffectImplicitTargetB[0] = 0; - } - } - - ScriptedInstance *pInstance; - - uint32 FireBreathTimer; - uint32 BombTimer; - uint32 BombSequenceTimer; - uint32 BombCount; - uint32 HatcherTimer; - uint32 EnrageTimer; - - bool noeggs; - bool enraged; - bool isBombing; - - bool isFlameBreathing; - - uint64 FireBombGUIDs[40]; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_JANALAIEVENT, NOT_STARTED); - - FireBreathTimer = 8000; - BombTimer = 30000; - BombSequenceTimer = 1000; - BombCount = 0; - HatcherTimer = 10000; - EnrageTimer = MINUTE*5*IN_MILISECONDS; - - noeggs = false; - isBombing =false; - enraged = false; - - isFlameBreathing = false; - - for (uint8 i = 0; i < 40; ++i) - FireBombGUIDs[i] = 0; - - HatchAllEggs(1); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_JANALAIEVENT, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_JANALAIEVENT, IN_PROGRESS); - - DoScriptText(SAY_AGGRO, me); -// DoZoneInCombat(); - } - - void DamageDeal(Unit *pTarget, uint32 &damage) - { - if (isFlameBreathing) - { - if (!me->HasInArc(M_PI/6, pTarget)) - damage = 0; - } - } - - void FireWall() - { - uint8 WallNum; - Creature* wall = NULL; - for (uint8 i = 0; i < 4; ++i) - { - if (i == 0 || i == 2) - WallNum = 3; - else - WallNum = 2; - - for (uint8 j = 0; j < WallNum; j++) - { - if (WallNum == 3) - wall = me->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0],FireWallCoords[i][1]+5*(j-1),FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000); - else - wall = me->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0]-2+4*j,FireWallCoords[i][1],FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000); - if (wall) wall->CastSpell(wall, SPELL_FIRE_WALL, true); - } - } - } - - void SpawnBombs() - { - float dx, dy; - for (int i(0); i < 40; ++i) - { - dx = irand(-area_dx/2, area_dx/2); - dy = irand(-area_dy/2, area_dy/2); - - Creature* bomb = DoSpawnCreature(MOB_FIRE_BOMB, dx, dy, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); - if (bomb) FireBombGUIDs[i] = bomb->GetGUID(); - } - BombCount = 0; - } - - bool HatchAllEggs(uint32 uiAction) //1: reset, 2: isHatching all - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllCreaturesOfEntryInRange check(me, MOB_EGG, 100); - Trinity::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap())); - } - - //error_log("Eggs %d at middle", templist.size()); - if (!templist.size()) - return false; - - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - if (uiAction == 1) - (*i)->SetDisplayId(10056); - else if (uiAction == 2 &&(*i)->GetDisplayId() != 11686) - (*i)->CastSpell(*i, SPELL_HATCH_EGG, false); - } - return true; - } - - void Boom() - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllCreaturesOfEntryInRange check(me, MOB_FIRE_BOMB, 100); - Trinity::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap())); - } - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - (*i)->CastSpell(*i, SPELL_FIRE_BOMB_DAMAGE, true); - (*i)->RemoveAllAuras(); - } - } - - void HandleBombSequence() - { - if (BombCount < 40) - { - if (Unit *FireBomb = Unit::GetUnit((*me), FireBombGUIDs[BombCount])) - { - FireBomb->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(FireBomb, SPELL_FIRE_BOMB_THROW, true); - FireBomb->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - ++BombCount; - if (BombCount == 40) - { - BombSequenceTimer = 5000; - } else BombSequenceTimer = 100; - } - else - { - Boom(); - isBombing = false; - BombTimer = urand(20000,40000); - me->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_CHANNEL); - if (EnrageTimer <= 10000) - EnrageTimer = 0; - else - EnrageTimer -= 10000; - } - } - - void UpdateAI(const uint32 diff) - { - if (isFlameBreathing) - { - if (!me->IsNonMeleeSpellCasted(false)) - isFlameBreathing = false; - else - return; - } - - if (isBombing) - { - if (BombSequenceTimer <= diff) - HandleBombSequence(); - else - BombSequenceTimer -= diff; - return; - } - - if (!UpdateVictim()) - return; - - //enrage if under 25% hp before 5 min. - if (!enraged && me->GetHealth() * 4 < me->GetMaxHealth()) - EnrageTimer = 0; - - if (EnrageTimer <= diff) - { - if (!enraged) - { - DoCast(me, SPELL_ENRAGE, true); - enraged = true; - EnrageTimer = 300000; - } - else - { - DoScriptText(SAY_BERSERK, me); - DoCast(me, SPELL_BERSERK, true); - EnrageTimer = 300000; - } - } else EnrageTimer -= diff; - - if (BombTimer <= diff) - { - DoScriptText(SAY_FIRE_BOMBS, me); - - me->AttackStop(); - me->GetMotionMaster()->Clear(); - DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); - me->StopMoving(); - DoCast(me, SPELL_FIRE_BOMB_CHANNEL, false); - //DoTeleportPlayer(me, JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2], 0); - //DoCast(me, SPELL_TELE_TO_CENTER, true); - - FireWall(); - SpawnBombs(); - isBombing = true; - BombSequenceTimer = 100; - - //Teleport every Player into the middle - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) return; - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* i_pl = i->getSource()) - if (i_pl->isAlive()) - DoTeleportPlayer(i_pl, JanalainPos[0][0]-5+rand()%10, JanalainPos[0][1]-5+rand()%10, JanalainPos[0][2], 0); - //DoCast(Temp, SPELL_SUMMON_PLAYERS, true) // core bug, spell does not work if too far - return; - } else BombTimer -= diff; - - if (!noeggs) - { - if (100 * me->GetHealth() < 35 * me->GetMaxHealth()) - { - DoScriptText(SAY_ALL_EGGS, me); - - me->AttackStop(); - me->GetMotionMaster()->Clear(); - DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); - me->StopMoving(); - DoCast(me, SPELL_HATCH_ALL, false); - HatchAllEggs(2); - noeggs = true; - } - else if (HatcherTimer <= diff) - { - if (HatchAllEggs(0)) - { - DoScriptText(SAY_SUMMON_HATCHER, me); - me->SummonCreature(MOB_AMANI_HATCHER,hatcherway[0][0][0],hatcherway[0][0][1],hatcherway[0][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); - me->SummonCreature(MOB_AMANI_HATCHER,hatcherway[1][0][0],hatcherway[1][0][1],hatcherway[1][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); - HatcherTimer = 90000; - } - else - noeggs = true; - } else HatcherTimer -= diff; - } - - EnterEvadeIfOutOfCombatArea(diff); - - DoMeleeAttackIfReady(); - - if (FireBreathTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - me->AttackStop(); - me->GetMotionMaster()->Clear(); - DoCast(pTarget, SPELL_FLAME_BREATH, false); - me->StopMoving(); - isFlameBreathing = true; - } - FireBreathTimer = 8000; - } else FireBreathTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_janalaiAI(Creature* pCreature) -{ - return new boss_janalaiAI(pCreature); -} - -struct mob_janalai_firebombAI : public ScriptedAI -{ - mob_janalai_firebombAI(Creature *c) : ScriptedAI(c){} - - void Reset() {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_FIRE_BOMB_THROW) - DoCast(me, SPELL_FIRE_BOMB_DUMMY, true); - } - - void EnterCombat(Unit* /*who*/) {} - - void AttackStart(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_mob_janalai_firebombAI(Creature* pCreature) -{ - return new mob_janalai_firebombAI(pCreature); -} - -struct mob_amanishi_hatcherAI : public ScriptedAI -{ - mob_amanishi_hatcherAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 waypoint; - uint32 HatchNum; - uint32 WaitTimer; - - bool side; - bool hasChangedSide; - bool isHatching; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - side =(me->GetPositionY() < 1150); - waypoint = 0; - isHatching = false; - hasChangedSide = false; - WaitTimer = 1; - HatchNum = 0; - } - - bool HatchEggs(uint32 num) - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllCreaturesOfEntryInRange check(me, 23817, 50); - Trinity::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap())); - } - - //error_log("Eggs %d at %d", templist.size(), side); - - for (std::list::const_iterator i = templist.begin(); i != templist.end() && num > 0; ++i) - if ((*i)->GetDisplayId() != 11686) - { - (*i)->CastSpell(*i, SPELL_HATCH_EGG, false); - num--; - } - - return num == 0; // if num == 0, no more templist - } - - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void MovementInform(uint32, uint32) - { - if (waypoint == 5) - { - isHatching = true; - HatchNum = 1; - WaitTimer = 5000; - } - else - WaitTimer = 1; - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance || !(pInstance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS)) - { - me->DisappearAndDie(); - return; - } - - if (!isHatching) - { - if (WaitTimer) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0,hatcherway[side][waypoint][0],hatcherway[side][waypoint][1],hatcherway[side][waypoint][2]); - ++waypoint; - WaitTimer = 0; - } - } - else - { - if (WaitTimer <= diff) - { - if (HatchEggs(HatchNum)) - { - ++HatchNum; - WaitTimer = 10000; - } - else if (!hasChangedSide) - { - side = side ? 0 : 1; - isHatching = false; - waypoint = 3; - WaitTimer = 1; - hasChangedSide = true; - } - else - me->DisappearAndDie(); - - } else WaitTimer -= diff; - } - } -}; - -CreatureAI* GetAI_mob_amanishi_hatcherAI(Creature* pCreature) -{ - return new mob_amanishi_hatcherAI(pCreature); -} - -struct mob_hatchlingAI : public ScriptedAI -{ - mob_hatchlingAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 BuffetTimer; - - void Reset() - { - BuffetTimer = 7000; - if (me->GetPositionY() > 1150) - me->GetMotionMaster()->MovePoint(0, hatcherway[0][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[0][3][2]); - else - me->GetMotionMaster()->MovePoint(0,hatcherway[1][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[1][3][2]); - - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - } - - void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/} - - void UpdateAI(const uint32 diff) - { - if (!pInstance || !(pInstance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS)) - { - me->DisappearAndDie(); - return; - } - - if (!UpdateVictim()) - return; - - if (BuffetTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBUFFET, false); - BuffetTimer = 10000; - } else BuffetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_hatchlingAI(Creature* pCreature) -{ - return new mob_hatchlingAI(pCreature); -} - -struct mob_eggAI : public ScriptedAI -{ - mob_eggAI(Creature *c) : ScriptedAI(c){} - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_HATCH_EGG) - { - DoSpawnCreature(MOB_HATCHLING, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - me->SetDisplayId(11686); - } - } -}; - -CreatureAI* GetAI_mob_eggAI(Creature* pCreature) -{ - return new mob_eggAI(pCreature); -} - -void AddSC_boss_janalai() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_janalai"; - newscript->GetAI = &GetAI_boss_janalaiAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_janalai_firebomb"; - newscript->GetAI = &GetAI_mob_janalai_firebombAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_janalai_hatcher"; - newscript->GetAI = &GetAI_mob_amanishi_hatcherAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_janalai_hatchling"; - newscript->GetAI = &GetAI_mob_hatchlingAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_janalai_egg"; - newscript->GetAI = &GetAI_mob_eggAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp b/src/server/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp deleted file mode 100644 index ae5c6596d2d..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp +++ /dev/null @@ -1,451 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Nalorakk -SD%Complete: 100 -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" -#include "GridNotifiers.h" - -//Trash Waves -float NalorakkWay[8][3] = -{ - { 18.569, 1414.512, 11.42},// waypoint 1 - {-17.264, 1419.551, 12.62}, - {-52.642, 1419.357, 27.31},// waypoint 2 - {-69.908, 1419.721, 27.31}, - {-79.929, 1395.958, 27.31}, - {-80.072, 1374.555, 40.87},// waypoint 3 - {-80.072, 1314.398, 40.87}, - {-80.072, 1295.775, 48.60} // waypoint 4 -}; - -#define YELL_NALORAKK_WAVE1 "Get da move on, guards! It be killin' time!" -#define SOUND_NALORAKK_WAVE1 12066 -#define YELL_NALORAKK_WAVE2 "Guards, go already! Who you more afraid of, dem... or me?" -#define SOUND_NALORAKK_WAVE2 12067 -#define YELL_NALORAKK_WAVE3 "Ride now! Ride out dere and bring me back some heads!" -#define SOUND_NALORAKK_WAVE3 12068 -#define YELL_NALORAKK_WAVE4 "I be losin' me patience! Go on: make dem wish dey was never born!" -#define SOUND_NALORAKK_WAVE4 12069 - -//Unimplemented SoundIDs -/* -#define SOUND_NALORAKK_EVENT1 12078 -#define SOUND_NALORAKK_EVENT2 12079 -*/ - -//General defines -#define YELL_AGGRO "You be dead soon enough!" -#define SOUND_YELL_AGGRO 12070 -#define YELL_KILL_ONE "Mua-ha-ha! Now whatchoo got to say?" -#define SOUND_YELL_KILL_ONE 12075 -#define YELL_KILL_TWO "Da Amani gonna rule again!" -#define SOUND_YELL_KILL_TWO 12076 -#define YELL_DEATH "I... be waitin' on da udda side...." -#define SOUND_YELL_DEATH 12077 -#define YELL_BERSERK "You had your chance, now it be too late!" //Never seen this being used, so just guessing from what I hear. -#define SOUND_YELL_BERSERK 12074 - -#define SPELL_BERSERK 45078 - -//Defines for Troll form -#define SPELL_BRUTALSWIPE 42384 -#define SPELL_MANGLE 42389 -#define SPELL_MANGLEEFFECT 44955 -#define SPELL_SURGE 42402 -#define SPELL_BEARFORM 42377 - -#define YELL_SURGE "I bring da pain!" -#define SOUND_YELL_SURGE 12071 - -#define YELL_SHIFTEDTOTROLL "Make way for Nalorakk!" -#define SOUND_YELL_TOTROLL 12073 - -//Defines for Bear form -#define SPELL_LACERATINGSLASH 42395 -#define SPELL_RENDFLESH 42397 -#define SPELL_DEAFENINGROAR 42398 - -#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!" -#define SOUND_YELL_TOBEAR 12072 - -struct boss_nalorakkAI : public ScriptedAI -{ - boss_nalorakkAI(Creature *c) : ScriptedAI(c) - { - MoveEvent = true; - MovePhase = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 BrutalSwipe_Timer; - uint32 Mangle_Timer; - uint32 Surge_Timer; - - uint32 LaceratingSlash_Timer; - uint32 RendFlesh_Timer; - uint32 DeafeningRoar_Timer; - - uint32 ShapeShift_Timer; - uint32 Berserk_Timer; - - bool inBearForm; - bool MoveEvent; - bool inMove; - uint32 MovePhase; - uint32 waitTimer; - - void Reset() - { - if (MoveEvent) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - inMove = false; - waitTimer = 0; - me->SetSpeed(MOVE_RUN,2); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - }else - { - (*me).GetMotionMaster()->MovePoint(0,NalorakkWay[7][0],NalorakkWay[7][1],NalorakkWay[7][2]); - } - - if (pInstance) - pInstance->SetData(DATA_NALORAKKEVENT, NOT_STARTED); - - Surge_Timer = 15000 + rand()%5000; - BrutalSwipe_Timer = 7000 + rand()%5000; - Mangle_Timer = 10000 + rand()%5000; - ShapeShift_Timer = 45000 + rand()%5000; - Berserk_Timer = 600000; - - inBearForm = false; - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); // TODO: find the correct equipment id - } - - void SendAttacker(Unit *pTarget) - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllFriendlyCreaturesInGrid check(me); - Trinity::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap())); - } - - if (!templist.size()) - return; - - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - if ((*i) && me->IsWithinDistInMap((*i),25)) - { - (*i)->SetNoCallAssistance(true); - (*i)->AI()->AttackStart(pTarget); - } - } - } - - void AttackStart(Unit* who) - { - if (!MoveEvent) - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (!MoveEvent) - { - ScriptedAI::MoveInLineOfSight(who); - } - else - { - if (me->IsHostileTo(who)) - { - if (!inMove) - { - switch(MovePhase) - { - case 0: - if (me->IsWithinDistInMap(who, 50)) - { - me->MonsterYell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1); - - (*me).GetMotionMaster()->MovePoint(1,NalorakkWay[1][0],NalorakkWay[1][1],NalorakkWay[1][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 2: - if (me->IsWithinDistInMap(who, 40)) - { - me->MonsterYell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2); - - (*me).GetMotionMaster()->MovePoint(3,NalorakkWay[3][0],NalorakkWay[3][1],NalorakkWay[3][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 5: - if (me->IsWithinDistInMap(who, 40)) - { - me->MonsterYell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3); - - (*me).GetMotionMaster()->MovePoint(6,NalorakkWay[6][0],NalorakkWay[6][1],NalorakkWay[6][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 7: - if (me->IsWithinDistInMap(who, 50)) - { - SendAttacker(who); - - me->MonsterYell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - MoveEvent = false; - } - break; - } - } - } - } - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS); - - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_AGGRO); - DoZoneInCombat(); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_NALORAKKEVENT, DONE); - - me->MonsterYell(YELL_DEATH,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me, SOUND_YELL_DEATH); - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,1)) - { - case 0: - me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); - break; - case 1: - me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); - break; - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (MoveEvent) - { - if (type != POINT_MOTION_TYPE) - return; - - if (!inMove) - return; - - if (MovePhase != id) - return; - - switch(MovePhase) - { - case 2: - me->SetOrientation(3.1415*2); - inMove = false; - return; - case 1: - case 3: - case 4: - case 6: - MovePhase ++; - waitTimer = 1; - inMove = true; - return; - case 5: - me->SetOrientation(3.1415*0.5); - inMove = false; - return; - case 7: - me->SetOrientation(3.1415*0.5); - inMove = false; - return; - } - - } - } - - void UpdateAI(const uint32 diff) - { - if (waitTimer) - { - if (inMove) - if (waitTimer <= diff) - { - (*me).GetMotionMaster()->MovementExpired(); - (*me).GetMotionMaster()->MovePoint(MovePhase,NalorakkWay[MovePhase][0],NalorakkWay[MovePhase][1],NalorakkWay[MovePhase][2]); - waitTimer = 0; - } else waitTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_BERSERK); - Berserk_Timer = 600000; - } else Berserk_Timer -= diff; - - if (ShapeShift_Timer <= diff) - { - if (inBearForm) - { - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); - me->MonsterYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_TOTROLL); - me->RemoveAurasDueToSpell(SPELL_BEARFORM); - Surge_Timer = 15000 + rand()%5000; - BrutalSwipe_Timer = 7000 + rand()%5000; - Mangle_Timer = 10000 + rand()%5000; - ShapeShift_Timer = 45000 + rand()%5000; - inBearForm = false; - } - else - { - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0); - me->MonsterYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_TOBEAR); - DoCast(me, SPELL_BEARFORM, true); - LaceratingSlash_Timer = 2000; // dur 18s - RendFlesh_Timer = 3000; // dur 5s - DeafeningRoar_Timer = 5000 + rand()%5000; // dur 2s - ShapeShift_Timer = 20000 + rand()%5000; // dur 30s - inBearForm = true; - } - } else ShapeShift_Timer -= diff; - - if (!inBearForm) - { - if (BrutalSwipe_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BRUTALSWIPE); - BrutalSwipe_Timer = 7000 + rand()%5000; - } else BrutalSwipe_Timer -= diff; - - if (Mangle_Timer <= diff) - { - if (me->getVictim() && !me->getVictim()->HasAura(SPELL_MANGLEEFFECT)) - { - DoCast(me->getVictim(), SPELL_MANGLE); - Mangle_Timer = 1000; - } - else Mangle_Timer = 10000 + rand()%5000; - } else Mangle_Timer -= diff; - - if (Surge_Timer <= diff) - { - me->MonsterYell(YELL_SURGE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_SURGE); - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true); - if (pTarget) - DoCast(pTarget, SPELL_SURGE); - Surge_Timer = 15000 + rand()%5000; - } else Surge_Timer -= diff; - } - else - { - if (LaceratingSlash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LACERATINGSLASH); - LaceratingSlash_Timer = 18000 + rand()%5000; - } else LaceratingSlash_Timer -= diff; - - if (RendFlesh_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_RENDFLESH); - RendFlesh_Timer = 5000 + rand()%5000; - } else RendFlesh_Timer -= diff; - - if (DeafeningRoar_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DEAFENINGROAR); - DeafeningRoar_Timer = 15000 + rand()%5000; - } else DeafeningRoar_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_nalorakk(Creature* pCreature) -{ - return new boss_nalorakkAI (pCreature); -} - -void AddSC_boss_nalorakk() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nalorakk"; - newscript->GetAI = &GetAI_boss_nalorakk; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp b/src/server/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp deleted file mode 100644 index 91cfa728f89..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp +++ /dev/null @@ -1,623 +0,0 @@ -/* Copyright (C) 2006,2007,2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_ZulJin -SD%Complete: 85% -SDComment: -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" - -//Speech -#define YELL_TRANSFORM_TO_LYNX "Let me introduce to you my new bruddahs: fang and claw!" -#define SOUND_TRANSFORM_TO_LYNX 12094 - -#define YELL_TRANSFORM_TO_BEAR "Got me some new tricks...like me bruddah bear!" -#define SOUND_TRANSFORM_TO_BEAR 12092 - -#define YELL_TRANSFORM_TO_DRAGONHAWK "Ya don' have to look to da sky to see da dragonhawk!" -#define SOUND_TRANSFORM_TO_DRAGONHAWK 12095 - -#define YELL_TRANSFORM_TO_EAGLE "Dere be no hidin' from da eagle!" -#define SOUND_TRANSFORM_TO_EAGLE 12093 - -#define YELL_KILL_ONE "Da Amani de chuka!" -#define SOUND_KILL_ONE 12098 - -#define YELL_KILL_TWO "Lot more gonna fall like you!" -#define SOUND_KILL_TWO 12099 - -#define YELL_FIRE_BREATH "Fire kill you just as quick!" -#define SOUND_FIRE_BRETH 12096 - -#define YELL_AGGRO "Nobody badduh dan me!" -#define SOUND_AGGRO 12091 - -#define YELL_BERSERK "You too slow! Me too strong!" -#define SOUND_BERSERK 12097 - -#define YELL_DEATH "Mebbe me fall...but da Amani empire...never gonna die..." -#define SOUND_DEATH 12100 - -//Still not used, need more info -#define YELL_INTRO "Everybody always wanna take from us. Now we gonna start takin' back. Anybody who get in our way...gonna drown in their own blood! De Amani empire be back now...seekin' vengeance. And we gonna start...with you!" -#define SOUND_INTRO 12090 - -//Spells: -//====== Troll Form -#define SPELL_WHIRLWIND 17207 -#define SPELL_GRIEVOUS_THROW 43093 // remove debuff after full healed -//====== Bear Form -#define SPELL_CREEPING_PARALYSIS 43095 // should cast on the whole raid -#define SPELL_OVERPOWER 43456 // use after melee attack dodged -//====== Eagle Form -#define SPELL_ENERGY_STORM 43983 // enemy area aura, trigger 42577 -#define SPELL_ZAP_INFORM 42577 -#define SPELL_ZAP_DAMAGE 43137 // 1250 damage -#define SPELL_SUMMON_CYCLONE 43112 // summon four feather vortex -#define CREATURE_FEATHER_VORTEX 24136 -#define SPELL_CYCLONE_VISUAL 43119 // trigger 43147 visual -#define SPELL_CYCLONE_PASSIVE 43120 // trigger 43121 (4y aoe) every second -//Lynx Form -#define SPELL_CLAW_RAGE_HASTE 42583 -#define SPELL_CLAW_RAGE_TRIGGER 43149 -#define SPELL_CLAW_RAGE_DAMAGE 43150 -#define SPELL_LYNX_RUSH_HASTE 43152 -#define SPELL_LYNX_RUSH_DAMAGE 43153 -//Dragonhawk Form -#define SPELL_FLAME_WHIRL 43213 // trigger two spells -#define SPELL_FLAME_BREATH 43215 -#define SPELL_SUMMON_PILLAR 43216 // summon 24187 -#define CREATURE_COLUMN_OF_FIRE 24187 -#define SPELL_PILLAR_TRIGGER 43218 // trigger 43217 - -//cosmetic -#define SPELL_SPIRIT_AURA 42466 -#define SPELL_SIPHON_SOUL 43501 - -//Transforms: -#define SPELL_SHAPE_OF_THE_BEAR 42594 // 15% dmg -#define SPELL_SHAPE_OF_THE_EAGLE 42606 -#define SPELL_SHAPE_OF_THE_LYNX 42607 // haste melee 30% -#define SPELL_SHAPE_OF_THE_DRAGONHAWK 42608 - -#define SPELL_BERSERK 45078 - -#define PHASE_BEAR 0 -#define PHASE_EAGLE 1 -#define PHASE_LYNX 2 -#define PHASE_DRAGONHAWK 3 -#define PHASE_TROLL 4 - -//coords for going for changing form -#define CENTER_X 120.148811 -#define CENTER_Y 703.713684 -#define CENTER_Z 45.111477 - -struct SpiritInfoStruct -{ - uint32 entry; - float x, y, z, orient; -}; - -static SpiritInfoStruct SpiritInfo[] = -{ - {23878, 147.87, 706.51, 45.11, 3.04}, - {23880, 88.95, 705.49, 45.11, 6.11}, - {23877, 137.23, 725.98, 45.11, 3.71}, - {23879, 104.29, 726.43, 45.11, 5.43} -}; - -struct TransformStruct -{ - uint32 sound; - char* text; - uint32 spell, unaura; -}; - -static TransformStruct Transform[] = -{ - {SOUND_TRANSFORM_TO_BEAR, YELL_TRANSFORM_TO_BEAR, SPELL_SHAPE_OF_THE_BEAR, SPELL_WHIRLWIND}, - {SOUND_TRANSFORM_TO_EAGLE, YELL_TRANSFORM_TO_EAGLE, SPELL_SHAPE_OF_THE_EAGLE, SPELL_SHAPE_OF_THE_BEAR}, - {SOUND_TRANSFORM_TO_LYNX, YELL_TRANSFORM_TO_LYNX, SPELL_SHAPE_OF_THE_LYNX, SPELL_SHAPE_OF_THE_EAGLE}, - {SOUND_TRANSFORM_TO_DRAGONHAWK, YELL_TRANSFORM_TO_DRAGONHAWK, SPELL_SHAPE_OF_THE_DRAGONHAWK, SPELL_SHAPE_OF_THE_LYNX} -}; - -struct boss_zuljinAI : public ScriptedAI -{ - boss_zuljinAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - ScriptedInstance *pInstance; - - uint64 SpiritGUID[4]; - uint64 ClawTargetGUID; - uint64 TankGUID; - - uint32 Phase; - uint32 health_20; - - uint32 Intro_Timer; - uint32 Berserk_Timer; - - uint32 Whirlwind_Timer; - uint32 Grievous_Throw_Timer; - - uint32 Creeping_Paralysis_Timer; - uint32 Overpower_Timer; - - uint32 Claw_Rage_Timer; - uint32 Lynx_Rush_Timer; - uint32 Claw_Counter; - uint32 Claw_Loop_Timer; - - uint32 Flame_Whirl_Timer; - uint32 Flame_Breath_Timer; - uint32 Pillar_Of_Fire_Timer; - - SummonList Summons; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_ZULJINEVENT, NOT_STARTED); - - Phase = 0; - - health_20 = me->GetMaxHealth()*0.2; - - Intro_Timer = 37000; - Berserk_Timer = 600000; - - Whirlwind_Timer = 7000; - Grievous_Throw_Timer = 8000; - - Creeping_Paralysis_Timer = 7000; - Overpower_Timer = 0; - - Claw_Rage_Timer = 5000; - Lynx_Rush_Timer = 14000; - Claw_Loop_Timer = 0; - Claw_Counter = 0; - - Flame_Whirl_Timer = 5000; - Flame_Breath_Timer = 6000; - Pillar_Of_Fire_Timer = 7000; - - ClawTargetGUID = 0; - TankGUID = 0; - - Summons.DespawnAll(); - - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 47174); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674); - //me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_ZULJINEVENT, IN_PROGRESS); - - DoZoneInCombat(); - - me->MonsterYell(YELL_INTRO,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me, SOUND_INTRO); - SpawnAdds(); - EnterPhase(0); - } - - void KilledUnit(Unit* /*victim*/) - { - if (Intro_Timer) - return; - - switch (urand(0,1)) - { - case 0: - me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL_ONE); - break; - case 1: - me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL_TWO); - break; - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ZULJINEVENT, DONE); - - me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_DEATH); - Summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE); - - if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[3])) - Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); - } - - void AttackStart(Unit *who) - { - if (Phase == 2) - AttackStartNoMove(who); - else - ScriptedAI::AttackStart(who); - } - - void DoMeleeAttackIfReady() - { - if (!me->IsNonMeleeSpellCasted(false)) - { - if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim())) - { - if (Phase == 1 && !Overpower_Timer) - { - uint32 health = me->getVictim()->GetHealth(); - me->AttackerStateUpdate(me->getVictim()); - if (me->getVictim() && health == me->getVictim()->GetHealth()) - { - DoCast(me->getVictim(), SPELL_OVERPOWER, false); - Overpower_Timer = 5000; - } - } else me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - } - - void SpawnAdds() - { - Creature *pCreature = NULL; - for (uint8 i = 0; i < 4; ++i) - { - pCreature = me->SummonCreature(SpiritInfo[i].entry, SpiritInfo[i].x, SpiritInfo[i].y, SpiritInfo[i].z, SpiritInfo[i].orient, TEMPSUMMON_DEAD_DESPAWN, 0); - if (pCreature) - { - pCreature->CastSpell(pCreature, SPELL_SPIRIT_AURA, true); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - SpiritGUID[i] = pCreature->GetGUID(); - } - } - } - - void DespawnAdds() - { - for (uint8 i = 0; i < 4; ++i) - { - Unit* Temp = NULL; - if (SpiritGUID[i]) - { - if (Temp = Unit::GetUnit(*me, SpiritGUID[i])) - { - Temp->SetVisibility(VISIBILITY_OFF); - Temp->setDeathState(DEAD); - } - } - SpiritGUID[i] = 0; - } - } - - void JustSummoned(Creature *summon) - { - Summons.Summon(summon); - } - - void SummonedCreatureDespawn(Creature *summon) - { - Summons.Despawn(summon); - } - - void EnterPhase(uint32 NextPhase) - { - switch(NextPhase) - { - case 0: - break; - case 1: - case 2: - case 3: - case 4: - DoTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, 100); - DoResetThreat(); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); - me->RemoveAurasDueToSpell(Transform[Phase].unaura); - DoCast(me, Transform[Phase].spell); - me->MonsterYell(Transform[Phase].text, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, Transform[Phase].sound); - if (Phase > 0) - { - if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[Phase - 1])) - Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); - } - if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[NextPhase - 1])) - Temp->CastSpell(me, SPELL_SIPHON_SOUL, false); // should m cast on temp - if (NextPhase == 2) - { - me->GetMotionMaster()->Clear(); - DoCast(me, SPELL_ENERGY_STORM, true); // enemy aura - for (uint8 i = 0; i < 4; ++i) - { - Creature* Vortex = DoSpawnCreature(CREATURE_FEATHER_VORTEX, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Vortex) - { - Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true); - Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true); - Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Vortex->SetSpeed(MOVE_RUN, 1.0f); - Vortex->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); - DoZoneInCombat(Vortex); - } - } - } - else - me->AI()->AttackStart(me->getVictim()); - if (NextPhase == 3) - { - me->RemoveAurasDueToSpell(SPELL_ENERGY_STORM); - Summons.DespawnEntry(CREATURE_FEATHER_VORTEX); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - break; - default: - break; - } - Phase = NextPhase; - } - - void UpdateAI(const uint32 diff) - { - if (!TankGUID) - { - if (!UpdateVictim()) - return; - - if (me->GetHealth() < health_20 * (4 - Phase)) - EnterPhase(Phase + 1); - } - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_BERSERK); - Berserk_Timer = 60000; - } else Berserk_Timer -= diff; - - switch (Phase) - { - case 0: - if (Intro_Timer) - { - if (Intro_Timer <= diff) - { - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_AGGRO); - Intro_Timer = 0; - } else Intro_Timer -= diff; - } - - if (Whirlwind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - Whirlwind_Timer = 15000 + rand()%5000; - } else Whirlwind_Timer -= diff; - - if (Grievous_Throw_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_GRIEVOUS_THROW, false); - Grievous_Throw_Timer = 10000; - } else Grievous_Throw_Timer -= diff; - break; - - case 1: - if (Creeping_Paralysis_Timer <= diff) - { - DoCast(me, SPELL_CREEPING_PARALYSIS); - Creeping_Paralysis_Timer = 20000; - } else Creeping_Paralysis_Timer -= diff; - - if (Overpower_Timer <= diff) - { - // implemented in DoMeleeAttackIfReady() - Overpower_Timer = 0; - } else Overpower_Timer -= diff; - break; - - case 2: - return; - - case 3: - if (Claw_Rage_Timer <= diff) - { - if (!TankGUID) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - TankGUID = me->getVictim()->GetGUID(); - me->SetSpeed(MOVE_RUN, 5.0f); - AttackStart(pTarget); // change victim - Claw_Rage_Timer = 0; - Claw_Loop_Timer = 500; - Claw_Counter = 0; - } - } - else if (!Claw_Rage_Timer) // do not do this when Lynx_Rush - { - if (Claw_Loop_Timer <= diff) - { - Unit *pTarget = me->getVictim(); - if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = Unit::GetUnit(*me, TankGUID); - if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - AttackStart(pTarget); - if (me->IsWithinMeleeRange(pTarget)) - { - DoCast(pTarget, SPELL_CLAW_RAGE_DAMAGE, true); - ++Claw_Counter; - if (Claw_Counter == 12) - { - Claw_Rage_Timer = 15000 + rand()%5000; - me->SetSpeed(MOVE_RUN, 1.2f); - AttackStart(Unit::GetUnit(*me, TankGUID)); - TankGUID = 0; - return; - } - else - Claw_Loop_Timer = 500; - } - } - else - { - EnterEvadeMode(); // if (pTarget) - return; - } - } else Claw_Loop_Timer -= diff; - } //if (TankGUID) - } else Claw_Rage_Timer -= diff; - - if (Lynx_Rush_Timer <= diff) - { - if (!TankGUID) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - TankGUID = me->getVictim()->GetGUID(); - me->SetSpeed(MOVE_RUN, 5.0f); - AttackStart(pTarget); // change victim - Lynx_Rush_Timer = 0; - Claw_Counter = 0; - } - } - else if (!Lynx_Rush_Timer) - { - Unit *pTarget = me->getVictim(); - if (!pTarget || !pTarget->isTargetableForAttack()) - { - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - AttackStart(pTarget); - } - if (pTarget) - { - if (me->IsWithinMeleeRange(pTarget)) - { - DoCast(pTarget, SPELL_LYNX_RUSH_DAMAGE, true); - ++Claw_Counter; - if (Claw_Counter == 9) - { - Lynx_Rush_Timer = 15000 + rand()%5000; - me->SetSpeed(MOVE_RUN, 1.2f); - AttackStart(Unit::GetUnit(*me, TankGUID)); - TankGUID = 0; - } - else - AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); - } - } - else - { - EnterEvadeMode(); // if (pTarget) - return; - } - } //if (TankGUID) - } else Lynx_Rush_Timer -= diff; - - break; - case 4: - if (Flame_Whirl_Timer <= diff) - { - DoCast(me, SPELL_FLAME_WHIRL); - Flame_Whirl_Timer = 12000; - }Flame_Whirl_Timer -= diff; - - if (Pillar_Of_Fire_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SUMMON_PILLAR); - Pillar_Of_Fire_Timer = 10000; - } else Pillar_Of_Fire_Timer -= diff; - - if (Flame_Breath_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - me->SetInFront(pTarget); - DoCast(me, SPELL_FLAME_BREATH); - Flame_Breath_Timer = 10000; - } else Flame_Breath_Timer -= diff; - break; - - default: - break; - } - - if (!TankGUID) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_zuljin(Creature* pCreature) -{ - return new boss_zuljinAI (pCreature); -} - -struct feather_vortexAI : public ScriptedAI -{ - feather_vortexAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - - void EnterCombat(Unit * /*pTarget*/) {} - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_ZAP_INFORM) - DoCast(caster, SPELL_ZAP_DAMAGE, true); - } - - void UpdateAI(const uint32 /*diff*/) - { - //if the vortex reach the target, it change his target to another player - if (me->IsWithinMeleeRange(me->getVictim())) - AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); - } -}; - -CreatureAI* GetAI_feather_vortexAI(Creature* pCreature) -{ - return new feather_vortexAI (pCreature); -} - -void AddSC_boss_zuljin() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_zuljin"; - newscript->GetAI = &GetAI_boss_zuljin; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_zuljin_vortex"; - newscript->GetAI = &GetAI_feather_vortexAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp b/src/server/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp deleted file mode 100644 index 897330691a6..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp +++ /dev/null @@ -1,320 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: instance_zulaman -SD%Complete: 80 -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" - -#define MAX_ENCOUNTER 6 -#define RAND_VENDOR 2 - -//187021 //Harkor's Satchel -//186648 //Tanzar's Trunk -//186672 //Ashli's Bag -//186667 //Kraz's Package -// Chests spawn at bear/eagle/dragonhawk/lynx bosses -// The loots depend on how many bosses have been killed, but not the entries of the chests -// But we cannot add loots to gameobject, so we have to use the fixed loot_template -struct SHostageInfo -{ - uint32 npc, pGo; - float x, y, z, o; -}; - -static SHostageInfo HostageInfo[] = -{ - {23790, 186648, -57, 1343, 40.77, 3.2}, // bear - {23999, 187021, 400, 1414, 74.36, 3.3}, // eagle - {24001, 186672, -35, 1134, 18.71, 1.9}, // dragonhawk - {24024, 186667, 413, 1117, 6.32, 3.1} // lynx - -}; - -struct instance_zulaman : public ScriptedInstance -{ - instance_zulaman(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 HarkorsSatchelGUID; - uint64 TanzarsTrunkGUID; - uint64 AshlisBagGUID; - uint64 KrazsPackageGUID; - - uint64 HexLordGateGUID; - uint64 ZulJinGateGUID; - uint64 AkilzonDoorGUID; - uint64 ZulJinDoorGUID; - uint64 HalazziDoorGUID; - - uint32 QuestTimer; - uint16 BossKilled; - uint16 QuestMinute; - uint16 ChestLooted; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 RandVendor[RAND_VENDOR]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - HarkorsSatchelGUID = 0; - TanzarsTrunkGUID = 0; - AshlisBagGUID = 0; - KrazsPackageGUID = 0; - - HexLordGateGUID = 0; - ZulJinGateGUID = 0; - AkilzonDoorGUID = 0; - HalazziDoorGUID = 0; - ZulJinDoorGUID = 0; - - QuestTimer = 0; - QuestMinute = 21; - BossKilled = 0; - ChestLooted = 0; - - for (uint8 i = 0; i < RAND_VENDOR; ++i) - RandVendor[i] = NOT_STARTED; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 23578://janalai - case 23863://zuljin - case 24239://hexlord - case 23577://halazzi - case 23576://nalorakk - default: break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 186303: HalazziDoorGUID = pGo->GetGUID(); break; - case 186304: ZulJinGateGUID = pGo->GetGUID(); break; - case 186305: HexLordGateGUID = pGo->GetGUID(); break; - case 186858: AkilzonDoorGUID = pGo->GetGUID(); break; - case 186859: ZulJinDoorGUID = pGo->GetGUID(); break; - - case 187021: HarkorsSatchelGUID = pGo->GetGUID(); break; - case 186648: TanzarsTrunkGUID = pGo->GetGUID(); break; - case 186672: AshlisBagGUID = pGo->GetGUID(); break; - case 186667: KrazsPackageGUID = pGo->GetGUID(); break; - default: break; - - } - CheckInstanceStatus(); - } - - void SummonHostage(uint8 num) - { - if (!QuestMinute) - return; - - Map::PlayerList const &PlayerList = instance->GetPlayers(); - if (PlayerList.isEmpty()) - return; - - Map::PlayerList::const_iterator i = PlayerList.begin(); - if (Player* i_pl = i->getSource()) - { - if (Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0)) - { - Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - } - } - - void CheckInstanceStatus() - { - if (BossKilled >= 4) - HandleGameObject(HexLordGateGUID, true); - - if (BossKilled >= 5) - HandleGameObject(ZulJinGateGUID, true); - } - - std::string GetSaveData() - { - std::ostringstream ss; - ss << "S " << BossKilled << " " << ChestLooted << " " << QuestMinute; - char* data = new char[ss.str().length()+1]; - strcpy(data, ss.str().c_str()); - //error_log("TSCR: Zul'aman saved, %s.", data); - return data; - } - - void Load(const char* load) - { - if (!load) return; - std::istringstream ss(load); - //error_log("TSCR: Zul'aman loaded, %s.", ss.str().c_str()); - char dataHead; // S - uint16 data1, data2, data3; - ss >> dataHead >> data1 >> data2 >> data3; - //error_log("TSCR: Zul'aman loaded, %d %d %d.", data1, data2, data3); - if (dataHead == 'S') - { - BossKilled = data1; - ChestLooted = data2; - QuestMinute = data3; - } else error_log("TSCR: Zul'aman: corrupted save data."); - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_NALORAKKEVENT: - m_auiEncounter[0] = data; - if (data == DONE) - { - if (QuestMinute) - { - QuestMinute += 15; - DoUpdateWorldState(3106, QuestMinute); - } - SummonHostage(0); - } - break; - case DATA_AKILZONEVENT: - m_auiEncounter[1] = data; - HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS); - if (data == DONE) - { - if (QuestMinute) - { - QuestMinute += 10; - DoUpdateWorldState(3106, QuestMinute); - } - SummonHostage(1); - } - break; - case DATA_JANALAIEVENT: - m_auiEncounter[2] = data; - if (data == DONE) SummonHostage(2); - break; - case DATA_HALAZZIEVENT: - m_auiEncounter[3] = data; - HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS); - if (data == DONE) SummonHostage(3); - break; - case DATA_HEXLORDEVENT: - m_auiEncounter[4] = data; - if (data == IN_PROGRESS) - HandleGameObject(HexLordGateGUID, false); - else if (data == NOT_STARTED) - CheckInstanceStatus(); - break; - case DATA_ZULJINEVENT: - m_auiEncounter[5] = data; - HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS); - break; - case DATA_CHESTLOOTED: - ++ChestLooted; - SaveToDB(); - break; - case TYPE_RAND_VENDOR_1: - RandVendor[0] = data; - break; - case TYPE_RAND_VENDOR_2: - RandVendor[1] = data; - break; - } - - if (data == DONE) - { - ++BossKilled; - if (QuestMinute && BossKilled >= 4) - { - QuestMinute = 0; - DoUpdateWorldState(3104, 0); - } - CheckInstanceStatus(); - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_NALORAKKEVENT: return m_auiEncounter[0]; - case DATA_AKILZONEVENT: return m_auiEncounter[1]; - case DATA_JANALAIEVENT: return m_auiEncounter[2]; - case DATA_HALAZZIEVENT: return m_auiEncounter[3]; - case DATA_HEXLORDEVENT: return m_auiEncounter[4]; - case DATA_ZULJINEVENT: return m_auiEncounter[5]; - case DATA_CHESTLOOTED: return ChestLooted; - case TYPE_RAND_VENDOR_1: return RandVendor[0]; - case TYPE_RAND_VENDOR_2: return RandVendor[1]; - default: return 0; - } - } - - void Update(uint32 diff) - { - if (QuestMinute) - { - if (QuestTimer <= diff) - { - QuestMinute--; - SaveToDB(); - QuestTimer += 60000; - if (QuestMinute) - { - DoUpdateWorldState(3104, 1); - DoUpdateWorldState(3106, QuestMinute); - } else DoUpdateWorldState(3104, 0); - } - QuestTimer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_zulaman(Map* pMap) -{ - return new instance_zulaman(pMap); -} - -void AddSC_instance_zulaman() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_zulaman"; - newscript->GetInstanceData = &GetInstanceData_instance_zulaman; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulaman/zulaman.cpp b/src/server/scripts/eastern_kingdoms/zulaman/zulaman.cpp deleted file mode 100644 index 067ae687644..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/zulaman.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Zulaman -SD%Complete: 90 -SDComment: Forest Frog will turn into different NPC's. Workaround to prevent new entry from running this script -SDCategory: Zul'Aman -EndScriptData */ - -/* ContentData -npc_forest_frog -EndContentData */ - -#include "ScriptedPch.h" -#include "zulaman.h" - -/*###### -## npc_forest_frog -######*/ - -#define SPELL_REMOVE_AMANI_CURSE 43732 -#define SPELL_PUSH_MOJO 43923 -#define ENTRY_FOREST_FROG 24396 - -struct npc_forest_frogAI : public ScriptedAI -{ - npc_forest_frogAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() {} - - void EnterCombat(Unit * /*who*/) {} - - void DoSpawnRandom() - { - if (pInstance) - { - uint32 cEntry = 0; - switch(rand()%10) - { - case 0: cEntry = 24397; break; //Mannuth - case 1: cEntry = 24403; break; //Deez - case 2: cEntry = 24404; break; //Galathryn - case 3: cEntry = 24405; break; //Adarrah - case 4: cEntry = 24406; break; //Fudgerick - case 5: cEntry = 24407; break; //Darwen - case 6: cEntry = 24445; break; //Mitzi - case 7: cEntry = 24448; break; //Christian - case 8: cEntry = 24453; break; //Brennan - case 9: cEntry = 24455; break; //Hollee - } - - if (!pInstance->GetData(TYPE_RAND_VENDOR_1)) - if (rand()%10 == 1) cEntry = 24408; //Gunter - if (!pInstance->GetData(TYPE_RAND_VENDOR_2)) - if (rand()%10 == 1) cEntry = 24409; //Kyren - - if (cEntry) me->UpdateEntry(cEntry); - - if (cEntry == 24408) pInstance->SetData(TYPE_RAND_VENDOR_1,DONE); - if (cEntry == 24409) pInstance->SetData(TYPE_RAND_VENDOR_2,DONE); - } - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && me->GetEntry() == ENTRY_FOREST_FROG) - { - //increase or decrease chance of mojo? - if (rand()%99 == 50) DoCast(caster, SPELL_PUSH_MOJO, true); - else DoSpawnRandom(); - } - } -}; -CreatureAI* GetAI_npc_forest_frog(Creature* pCreature) -{ - return new npc_forest_frogAI (pCreature); -} - -/*###### -## npc_zulaman_hostage -######*/ - -#define GOSSIP_HOSTAGE1 "I am glad to help you." - -static uint32 HostageEntry[] = {23790, 23999, 24024, 24001}; -static uint32 ChestEntry[] = {186648, 187021, 186672, 186667}; - -struct npc_zulaman_hostageAI : public ScriptedAI -{ - npc_zulaman_hostageAI(Creature *c) : ScriptedAI(c) {IsLoot = false;} - bool IsLoot; - uint64 PlayerGUID; - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - void JustDied(Unit* /*who*/) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer) pPlayer->SendLoot(me->GetGUID(), LOOT_CORPSE); - } - void UpdateAI(const uint32 /*diff*/) - { - if (IsLoot) - DoCast(me, 7, false); - } -}; - -bool GossipHello_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HOSTAGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - pPlayer->CLOSE_GOSSIP_MENU(); - - if (!pCreature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - return true; - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance) - { - //uint8 progress = pInstance->GetData(DATA_CHESTLOOTED); - pInstance->SetData(DATA_CHESTLOOTED, 0); - float x, y, z; - pCreature->GetPosition(x, y, z); - uint32 entry = pCreature->GetEntry(); - for (uint8 i = 0; i < 4; ++i) - { - if (HostageEntry[i] == entry) - { - pCreature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0); - break; - } - } - /*Creature* summon = pCreature->SummonCreature(HostageInfo[progress], x-2, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 0); - if (summon) - { - CAST_AI(npc_zulaman_hostageAI, summon->AI())->PlayerGUID = pPlayer->GetGUID(); - CAST_AI(npc_zulaman_hostageAI, summon->AI())->IsLoot = true; - summon->SetDisplayId(10056); - summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - }*/ - } - return true; -} - -CreatureAI* GetAI_npc_zulaman_hostage(Creature* pCreature) -{ - return new npc_zulaman_hostageAI(pCreature); -} - -void AddSC_zulaman() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_forest_frog"; - newscript->GetAI = &GetAI_npc_forest_frog; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_zulaman_hostage"; - newscript->GetAI = &GetAI_npc_zulaman_hostage; - newscript->pGossipHello = &GossipHello_npc_zulaman_hostage; - newscript->pGossipSelect = &GossipSelect_npc_zulaman_hostage; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulaman/zulaman.h b/src/server/scripts/eastern_kingdoms/zulaman/zulaman.h deleted file mode 100644 index 6fb0ef173bd..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulaman/zulaman.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_ZULAMAN_H -#define DEF_ZULAMAN_H - -#define DATA_NALORAKKEVENT 1 -#define DATA_AKILZONEVENT 2 -#define DATA_JANALAIEVENT 3 -#define DATA_HALAZZIEVENT 4 -#define DATA_HEXLORDEVENT 5 -#define DATA_ZULJINEVENT 6 -#define DATA_CHESTLOOTED 7 -#define TYPE_RAND_VENDOR_1 8 -#define TYPE_RAND_VENDOR_2 9 - -#endif - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp deleted file mode 100644 index cbbe6c4dc4c..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Arlokk -SD%Complete: 95 -SDComment: Wrong cleave and red aura is missing. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -bool GOHello_go_gong_of_bethekk(Player* /*pPlayer*/, GameObject* pGo) -{ - if (ScriptedInstance* m_pInstance = pGo->GetInstanceData()) - { - if (m_pInstance->GetData(TYPE_ARLOKK) == DONE || m_pInstance->GetData(TYPE_ARLOKK) == IN_PROGRESS) - return true; - - m_pInstance->SetData(TYPE_ARLOKK, IN_PROGRESS); - return true; - } - - return true; -} - -enum eEnums -{ - SAY_AGGRO = -1309011, - SAY_FEAST_PANTHER = -1309012, - SAY_DEATH = -1309013, - - SPELL_SHADOWWORDPAIN = 23952, - SPELL_GOUGE = 24698, - SPELL_MARK = 24210, - SPELL_CLEAVE = 26350, //Perhaps not right. Not a red aura... - SPELL_PANTHER_TRANSFORM = 24190, - - MODEL_ID_NORMAL = 15218, - MODEL_ID_PANTHER = 15215, - MODEL_ID_BLANK = 11686, - - NPC_ZULIAN_PROWLER = 15101 -}; - -struct boss_arlokkAI : public ScriptedAI -{ - boss_arlokkAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiShadowWordPain_Timer; - uint32 m_uiGouge_Timer; - uint32 m_uiMark_Timer; - uint32 m_uiCleave_Timer; - uint32 m_uiVanish_Timer; - uint32 m_uiVisible_Timer; - - uint32 m_uiSummon_Timer; - uint32 m_uiSummonCount; - - Unit* m_pMarkedTarget; - uint64 MarkedTargetGUID; - - bool m_bIsPhaseTwo; - bool m_bIsVanished; - - void Reset() - { - m_uiShadowWordPain_Timer = 8000; - m_uiGouge_Timer = 14000; - m_uiMark_Timer = 35000; - m_uiCleave_Timer = 4000; - m_uiVanish_Timer = 60000; - m_uiVisible_Timer = 6000; - - m_uiSummon_Timer = 5000; - m_uiSummonCount = 0; - - m_bIsPhaseTwo = false; - m_bIsVanished = false; - - MarkedTargetGUID = 0; - - me->SetDisplayId(MODEL_ID_NORMAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustReachedHome() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_ARLOKK, NOT_STARTED); - - //we should be summoned, so despawn - me->ForcedDespawn(); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - me->SetDisplayId(MODEL_ID_NORMAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (m_pInstance) - m_pInstance->SetData(TYPE_ARLOKK, DONE); - } - - void DoSummonPhanters() - { - if (Unit *pMarkedTarget = Unit::GetUnit(*me, MarkedTargetGUID)) - DoScriptText(SAY_FEAST_PANTHER, me, pMarkedTarget); - - me->SummonCreature(NPC_ZULIAN_PROWLER, -11532.7998, -1649.6734, 41.4800, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(NPC_ZULIAN_PROWLER, -11532.9970, -1606.4840, 41.2979, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - } - - void JustSummoned(Creature* pSummoned) - { - if (Unit *pMarkedTarget = Unit::GetUnit(*me, MarkedTargetGUID)) - pSummoned->AI()->AttackStart(pMarkedTarget); - - ++m_uiSummonCount; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (!m_bIsPhaseTwo) - { - if (m_uiShadowWordPain_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); - m_uiShadowWordPain_Timer = 15000; - } - else - m_uiShadowWordPain_Timer -= uiDiff; - - if (m_uiMark_Timer <= uiDiff) - { - Unit *pMarkedTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (pMarkedTarget) - { - DoCast(pMarkedTarget, SPELL_MARK); - MarkedTargetGUID = pMarkedTarget->GetGUID(); - } - else - error_log("TSCR: boss_arlokk could not accuire pMarkedTarget."); - - m_uiMark_Timer = 15000; - } - else - m_uiMark_Timer -= uiDiff; - } - else - { - //Cleave_Timer - if (m_uiCleave_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - m_uiCleave_Timer = 16000; - } - else - m_uiCleave_Timer -= uiDiff; - - //Gouge_Timer - if (m_uiGouge_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_GOUGE); - - DoModifyThreatPercent(me->getVictim(),-80); - - m_uiGouge_Timer = 17000+rand()%10000; - } - else - m_uiGouge_Timer -= uiDiff; - } - - if (m_uiSummonCount <= 30) - { - if (m_uiSummon_Timer <= uiDiff) - { - DoSummonPhanters(); - m_uiSummon_Timer = 5000; - } - else - m_uiSummon_Timer -= uiDiff; - } - - if (m_uiVanish_Timer <= uiDiff) - { - //Invisble Model - me->SetDisplayId(MODEL_ID_BLANK); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - me->AttackStop(); - DoResetThreat(); - - m_bIsVanished = true; - - m_uiVanish_Timer = 45000; - m_uiVisible_Timer = 6000; - } - else - m_uiVanish_Timer -= uiDiff; - - if (m_bIsVanished) - { - if (m_uiVisible_Timer <= uiDiff) - { - //The Panther Model - me->SetDisplayId(MODEL_ID_PANTHER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); - me->UpdateDamagePhysical(BASE_ATTACK); - - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - AttackStart(pTarget); - - m_bIsPhaseTwo = true; - m_bIsVanished = false; - } - else - m_uiVisible_Timer -= uiDiff; - } - else - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_arlokk(Creature* pCreature) -{ - return new boss_arlokkAI (pCreature); -} - -void AddSC_boss_arlokk() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_gong_of_bethekk"; - newscript->pGOHello = &GOHello_go_gong_of_bethekk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_arlokk"; - newscript->GetAI = &GetAI_boss_arlokk; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp deleted file mode 100644 index 0201235be70..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gahz'ranka -SD%Complete: 85 -SDComment: Massive Geyser with knockback not working. Spell buggy. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FROSTBREATH 16099 -#define SPELL_MASSIVEGEYSER 22421 //Not working. Cause its a summon... -#define SPELL_SLAM 24326 - -struct boss_gahzrankaAI : public ScriptedAI -{ - boss_gahzrankaAI(Creature *c) : ScriptedAI(c) {} - uint32 Frostbreath_Timer; - uint32 MassiveGeyser_Timer; - uint32 Slam_Timer; - - void Reset() - { - Frostbreath_Timer = 8000; - MassiveGeyser_Timer = 25000; - Slam_Timer = 17000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frostbreath_Timer - if (Frostbreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBREATH); - Frostbreath_Timer = 7000 + rand()%4000; - } else Frostbreath_Timer -= diff; - - //MassiveGeyser_Timer - if (MassiveGeyser_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MASSIVEGEYSER); - DoResetThreat(); - - MassiveGeyser_Timer = 22000 + rand()%10000; - } else MassiveGeyser_Timer -= diff; - - //Slam_Timer - if (Slam_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLAM); - Slam_Timer = 12000 + rand()%8000; - } else Slam_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gahzranka(Creature* pCreature) -{ - return new boss_gahzrankaAI (pCreature); -} - -void AddSC_boss_gahzranka() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gahzranka"; - newscript->GetAI = &GetAI_boss_gahzranka; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp deleted file mode 100644 index 67de135674a..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grilek -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SPELL_AVARTAR 24646 //The Enrage Spell -#define SPELL_GROUNDTREMOR 6524 - -struct boss_grilekAI : public ScriptedAI -{ - boss_grilekAI(Creature *c) : ScriptedAI(c) {} - - uint32 Avartar_Timer; - uint32 GroundTremor_Timer; - - void Reset() - { - Avartar_Timer = 15000 + rand()%10000; - GroundTremor_Timer = 8000 + rand()%8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Avartar_Timer - if (Avartar_Timer <= diff) - { - - DoCast(me, SPELL_AVARTAR); - Unit *pTarget = NULL; - - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-50); - if (pTarget) - AttackStart(pTarget); - - Avartar_Timer = 25000 + rand()%10000; - } else Avartar_Timer -= diff; - - //GroundTremor_Timer - if (GroundTremor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GROUNDTREMOR); - GroundTremor_Timer = 12000 + rand()%4000; - } else GroundTremor_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_grilek(Creature* pCreature) -{ - return new boss_grilekAI (pCreature); -} - -void AddSC_boss_grilek() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grilek"; - newscript->GetAI = &GetAI_boss_grilek; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp deleted file mode 100644 index d7dd5020b74..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hakkar -SD%Complete: 95 -SDComment: Blood siphon spell buggy cause of Core Issue. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309020 -#define SAY_FLEEING -1309021 -#define SAY_MINION_DESTROY -1309022 //where does it belong? -#define SAY_PROTECT_ALTAR -1309023 //where does it belong? - -#define SPELL_BLOODSIPHON 24322 -#define SPELL_CORRUPTEDBLOOD 24328 -#define SPELL_CAUSEINSANITY 24327 //Not working disabled. -#define SPELL_WILLOFHAKKAR 24178 -#define SPELL_ENRAGE 24318 - -// The Aspects of all High Priests -#define SPELL_ASPECT_OF_JEKLIK 24687 -#define SPELL_ASPECT_OF_VENOXIS 24688 -#define SPELL_ASPECT_OF_MARLI 24686 -#define SPELL_ASPECT_OF_THEKAL 24689 -#define SPELL_ASPECT_OF_ARLOKK 24690 - -struct boss_hakkarAI : public ScriptedAI -{ - boss_hakkarAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 BloodSiphon_Timer; - uint32 CorruptedBlood_Timer; - uint32 CauseInsanity_Timer; - uint32 WillOfHakkar_Timer; - uint32 Enrage_Timer; - - uint32 CheckJeklik_Timer; - uint32 CheckVenoxis_Timer; - uint32 CheckMarli_Timer; - uint32 CheckThekal_Timer; - uint32 CheckArlokk_Timer; - - uint32 AspectOfJeklik_Timer; - uint32 AspectOfVenoxis_Timer; - uint32 AspectOfMarli_Timer; - uint32 AspectOfThekal_Timer; - uint32 AspectOfArlokk_Timer; - - bool Enraged; - - void Reset() - { - BloodSiphon_Timer = 90000; - CorruptedBlood_Timer = 25000; - CauseInsanity_Timer = 17000; - WillOfHakkar_Timer = 17000; - Enrage_Timer = 600000; - - CheckJeklik_Timer = 1000; - CheckVenoxis_Timer = 2000; - CheckMarli_Timer = 3000; - CheckThekal_Timer = 4000; - CheckArlokk_Timer = 5000; - - AspectOfJeklik_Timer = 4000; - AspectOfVenoxis_Timer = 7000; - AspectOfMarli_Timer = 12000; - AspectOfThekal_Timer = 8000; - AspectOfArlokk_Timer = 18000; - - Enraged = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //BloodSiphon_Timer - if (BloodSiphon_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLOODSIPHON); - BloodSiphon_Timer = 90000; - } else BloodSiphon_Timer -= diff; - - //CorruptedBlood_Timer - if (CorruptedBlood_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORRUPTEDBLOOD); - CorruptedBlood_Timer = 30000 + rand()%15000; - } else CorruptedBlood_Timer -= diff; - - //CauseInsanity_Timer - /*if (CauseInsanity_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CAUSEINSANITY); - - CauseInsanity_Timer = 35000 + rand()%8000; - } else CauseInsanity_Timer -= diff;*/ - - //WillOfHakkar_Timer - if (WillOfHakkar_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_WILLOFHAKKAR); - - WillOfHakkar_Timer = 25000 + rand()%10000; - } else WillOfHakkar_Timer -= diff; - - if (!Enraged && Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else Enrage_Timer -= diff; - - //Checking if Jeklik is dead. If not we cast her Aspect - if (CheckJeklik_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_JEKLIK) != DONE) - { - if (AspectOfJeklik_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASPECT_OF_JEKLIK); - AspectOfJeklik_Timer = 10000 + rand()%4000; - } else AspectOfJeklik_Timer -= diff; - } - } - CheckJeklik_Timer = 1000; - } else CheckJeklik_Timer -= diff; - - //Checking if Venoxis is dead. If not we cast his Aspect - if (CheckVenoxis_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_VENOXIS) != DONE) - { - if (AspectOfVenoxis_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASPECT_OF_VENOXIS); - AspectOfVenoxis_Timer = 8000; - } else AspectOfVenoxis_Timer -= diff; - } - } - CheckVenoxis_Timer = 1000; - } else CheckVenoxis_Timer -= diff; - - //Checking if Marli is dead. If not we cast her Aspect - if (CheckMarli_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_MARLI) != DONE) - { - if (AspectOfMarli_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); - AspectOfMarli_Timer = 10000; - } else AspectOfMarli_Timer -= diff; - - } - } - CheckMarli_Timer = 1000; - } else CheckMarli_Timer -= diff; - - //Checking if Thekal is dead. If not we cast his Aspect - if (CheckThekal_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_THEKAL) != DONE) - { - if (AspectOfThekal_Timer <= diff) - { - DoCast(me, SPELL_ASPECT_OF_THEKAL); - AspectOfThekal_Timer = 15000; - } else AspectOfThekal_Timer -= diff; - } - } - CheckThekal_Timer = 1000; - } else CheckThekal_Timer -= diff; - - //Checking if Arlokk is dead. If yes we cast her Aspect - if (CheckArlokk_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_ARLOKK) != DONE) - { - if (AspectOfArlokk_Timer <= diff) - { - DoCast(me, SPELL_ASPECT_OF_ARLOKK); - DoResetThreat(); - - AspectOfArlokk_Timer = 10000 + rand()%5000; - } else AspectOfArlokk_Timer -= diff; - } - } - CheckArlokk_Timer = 1000; - } else CheckArlokk_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_hakkar(Creature* pCreature) -{ - return new boss_hakkarAI (pCreature); -} - -void AddSC_boss_hakkar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hakkar"; - newscript->GetAI = &GetAI_boss_hakkar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp deleted file mode 100644 index ca67d0842c3..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hazzarah -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SPELL_MANABURN 26046 -#define SPELL_SLEEP 24664 - -struct boss_hazzarahAI : public ScriptedAI -{ - boss_hazzarahAI(Creature *c) : ScriptedAI(c) {} - - uint32 ManaBurn_Timer; - uint32 Sleep_Timer; - uint32 Illusions_Timer; - - void Reset() - { - ManaBurn_Timer = 4000 + rand()%6000; - Sleep_Timer = 10000 + rand()%8000; - Illusions_Timer = 10000 + rand()%8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ManaBurn_Timer - if (ManaBurn_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MANABURN); - ManaBurn_Timer = 8000 + rand()%8000; - } else ManaBurn_Timer -= diff; - - //Sleep_Timer - if (Sleep_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLEEP); - Sleep_Timer = 12000 + rand()%8000; - } else Sleep_Timer -= diff; - - //Illusions_Timer - if (Illusions_Timer <= diff) - { - //We will summon 3 illusions that will spawn on a random gamer and attack this gamer - //We will just use one model for the beginning - Unit *pTarget = NULL; - for (uint8 i = 0; i < 3; ++i) - { - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget) - return; - - Creature *Illusion = me->SummonCreature(15163,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,30000); - if (Illusion) - Illusion->AI()->AttackStart(pTarget); - } - - Illusions_Timer = 15000 + rand()%10000; - } else Illusions_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_hazzarah(Creature* pCreature) -{ - return new boss_hazzarahAI (pCreature); -} - -void AddSC_boss_hazzarah() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hazzarah"; - newscript->GetAI = &GetAI_boss_hazzarah; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp deleted file mode 100644 index fae05fcf384..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Jeklik -SD%Complete: 85 -SDComment: Problem in finding the right flying batriders for spawning and making them fly. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309002 -#define SAY_RAIN_FIRE -1309003 -#define SAY_DEATH -1309004 - -#define SPELL_CHARGE 22911 -#define SPELL_SONICBURST 23918 -#define SPELL_SCREECH 6605 -#define SPELL_SHADOW_WORD_PAIN 23952 -#define SPELL_MIND_FLAY 23953 -#define SPELL_CHAIN_MIND_FLAY 26044 //Right ID unknown. So disabled -#define SPELL_GREATERHEAL 23954 -#define SPELL_BAT_FORM 23966 - -// Batriders Spell - -#define SPELL_BOMB 40332 //Wrong ID but Magmadars bomb is not working... - -struct boss_jeklikAI : public ScriptedAI -{ - boss_jeklikAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 Charge_Timer; - uint32 SonicBurst_Timer; - uint32 Screech_Timer; - uint32 SpawnBats_Timer; - uint32 ShadowWordPain_Timer; - uint32 MindFlay_Timer; - uint32 ChainMindFlay_Timer; - uint32 GreaterHeal_Timer; - uint32 SpawnFlyingBats_Timer; - - bool PhaseTwo; - - void Reset() - { - Charge_Timer = 20000; - SonicBurst_Timer = 8000; - Screech_Timer = 13000; - SpawnBats_Timer = 60000; - ShadowWordPain_Timer = 6000; - MindFlay_Timer = 11000; - ChainMindFlay_Timer = 26000; - GreaterHeal_Timer = 50000; - SpawnFlyingBats_Timer = 10000; - - PhaseTwo = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_BAT_FORM); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_JEKLIK, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->getVictim() && me->isAlive()) - { - if ((me->GetHealth()*100 / me->GetMaxHealth() > 50)) - { - if (Charge_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_CHARGE); - AttackStart(pTarget); - } - - Charge_Timer = 15000 + rand()%15000; - } else Charge_Timer -= diff; - - if (SonicBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SONICBURST); - SonicBurst_Timer = 8000 + rand()%5000; - } else SonicBurst_Timer -= diff; - - if (Screech_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SCREECH); - Screech_Timer = 18000 + rand()%8000; - } else Screech_Timer -= diff; - - if (SpawnBats_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - Creature* Bat = NULL; - Bat = me->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - Bat = me->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - Bat = me->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - Bat = me->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - Bat = me->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - Bat = me->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - SpawnBats_Timer = 60000; - } else SpawnBats_Timer -= diff; - } - else - { - if (PhaseTwo) - { - if (PhaseTwo && ShadowWordPain_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); - ShadowWordPain_Timer = 12000 + rand()%6000; - } - }ShadowWordPain_Timer -=diff; - - if (MindFlay_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIND_FLAY); - MindFlay_Timer = 16000; - }MindFlay_Timer -=diff; - - if (ChainMindFlay_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me->getVictim(), SPELL_CHAIN_MIND_FLAY); - ChainMindFlay_Timer = 15000 + rand()%15000; - }ChainMindFlay_Timer -=diff; - - if (GreaterHeal_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_GREATERHEAL); - GreaterHeal_Timer = 25000 + rand()%10000; - }GreaterHeal_Timer -=diff; - - if (SpawnFlyingBats_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (!pTarget) - return; - - Creature* FlyingBat = me->SummonCreature(14965, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (FlyingBat) - FlyingBat->AI()->AttackStart(pTarget); - - SpawnFlyingBats_Timer = 10000 + rand()%5000; - } else SpawnFlyingBats_Timer -=diff; - } - else - { - me->SetDisplayId(15219); - DoResetThreat(); - PhaseTwo = true; - } - } - - DoMeleeAttackIfReady(); - } - } -}; - -//Flying Bat -struct mob_batriderAI : public ScriptedAI -{ - mob_batriderAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 Bomb_Timer; - uint32 Check_Timer; - - void Reset() - { - Bomb_Timer = 2000; - Check_Timer = 1000; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI (const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Bomb_Timer - if (Bomb_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_BOMB); - Bomb_Timer = 5000; - } - } else Bomb_Timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_JEKLIK) == DONE) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_jeklik(Creature* pCreature) -{ - return new boss_jeklikAI (pCreature); -} - -CreatureAI* GetAI_mob_batrider(Creature* pCreature) -{ - return new mob_batriderAI (pCreature); -} - -void AddSC_boss_jeklik() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_jeklik"; - newscript->GetAI = &GetAI_boss_jeklik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_batrider"; - newscript->GetAI = &GetAI_mob_batrider; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp deleted file mode 100644 index 58f91f85a95..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Jin'do the Hexxer -SD%Complete: 85 -SDComment: Mind Control not working because of core bug. Shades visible for all. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309014 - -#define SPELL_BRAINWASHTOTEM 24262 -#define SPELL_POWERFULLHEALINGWARD 24309 //We will not use this spell. We will summon a totem by script cause the spell totems will not cast. -#define SPELL_HEX 24053 -#define SPELL_DELUSIONSOFJINDO 24306 -#define SPELL_SHADEOFJINDO 24308 //We will not use this spell. We will summon a shade by script. - -//Healing Ward Spell -#define SPELL_HEAL 38588 //Totems are not working right. Right heal spell ID is 24311 but this spell is not casting... - -//Shade of Jindo Spell -#define SPELL_SHADOWSHOCK 19460 -#define SPELL_INVISIBLE 24699 - -struct boss_jindoAI : public ScriptedAI -{ - boss_jindoAI(Creature *c) : ScriptedAI(c) {} - - uint32 BrainWashTotem_Timer; - uint32 HealingWard_Timer; - uint32 Hex_Timer; - uint32 Delusions_Timer; - uint32 Teleport_Timer; - - void Reset() - { - BrainWashTotem_Timer = 20000; - HealingWard_Timer = 16000; - Hex_Timer = 8000; - Delusions_Timer = 10000; - Teleport_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //BrainWashTotem_Timer - if (BrainWashTotem_Timer <= diff) - { - DoCast(me, SPELL_BRAINWASHTOTEM); - BrainWashTotem_Timer = 18000 + rand()%8000; - } else BrainWashTotem_Timer -= diff; - - //HealingWard_Timer - if (HealingWard_Timer <= diff) - { - //DoCast(me, SPELL_POWERFULLHEALINGWARD); - me->SummonCreature(14987, me->GetPositionX()+3, me->GetPositionY()-2, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,30000); - HealingWard_Timer = 14000 + rand()%6000; - } else HealingWard_Timer -= diff; - - //Hex_Timer - if (Hex_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HEX); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-80); - - Hex_Timer = 12000 + rand()%8000; - } else Hex_Timer -= diff; - - //Casting the delusion curse with a shade. So shade will attack the same target with the curse. - if (Delusions_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_DELUSIONSOFJINDO); - - Creature *Shade = me->SummonCreature(14986, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Shade) - Shade->AI()->AttackStart(pTarget); - } - - Delusions_Timer = 4000 + rand()%8000; - } else Delusions_Timer -= diff; - - //Teleporting a random gamer and spawning 9 skeletons that will attack this gamer - if (Teleport_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoTeleportPlayer(pTarget, -11583.7783,-1249.4278,77.5471,4.745); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(pTarget,-100); - - Creature *Skeletons; - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+2, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()-2, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+4, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()-4, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()+2, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()-2, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()+4, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()-4, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+3, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - } - - Teleport_Timer = 15000 + rand()%8000; - } else Teleport_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Healing Ward -struct mob_healing_wardAI : public ScriptedAI -{ - mob_healing_wardAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 Heal_Timer; - - ScriptedInstance *pInstance; - - void Reset() - { - Heal_Timer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI (const uint32 diff) - { - //Heal_Timer - if (Heal_Timer <= diff) - { - if (pInstance) - { - Unit *pJindo = Unit::GetUnit((*me), pInstance->GetData64(DATA_JINDO)); - if (pJindo) - DoCast(pJindo, SPELL_HEAL); - } - Heal_Timer = 3000; - } else Heal_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Shade of Jindo -struct mob_shade_of_jindoAI : public ScriptedAI -{ - mob_shade_of_jindoAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowShock_Timer; - - void Reset() - { - ShadowShock_Timer = 1000; - DoCast(me, SPELL_INVISIBLE, true); - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI (const uint32 diff) - { - - //ShadowShock_Timer - if (ShadowShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWSHOCK); - ShadowShock_Timer = 2000; - } else ShadowShock_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_jindo(Creature* pCreature) -{ - return new boss_jindoAI (pCreature); -} - -CreatureAI* GetAI_mob_healing_ward(Creature* pCreature) -{ - return new mob_healing_wardAI (pCreature); -} - -CreatureAI* GetAI_mob_shade_of_jindo(Creature* pCreature) -{ - return new mob_shade_of_jindoAI (pCreature); -} - -void AddSC_boss_jindo() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_jindo"; - newscript->GetAI = &GetAI_boss_jindo; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_healing_ward"; - newscript->GetAI = &GetAI_mob_healing_ward; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shade_of_jindo"; - newscript->GetAI = &GetAI_mob_shade_of_jindo; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp deleted file mode 100644 index 4609605f3c1..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mandokir -SD%Complete: 90 -SDComment: Ohgan function needs improvements. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309015 -#define SAY_DING_KILL -1309016 -#define SAY_GRATS_JINDO -1309017 -#define SAY_WATCH -1309018 -#define SAY_WATCH_WHISPER -1309019 //is this text for real? easter egg? - -#define SPELL_CHARGE 24315 -#define SPELL_CLEAVE 20691 -#define SPELL_FEAR 29321 -#define SPELL_WHIRLWIND 24236 -#define SPELL_MORTAL_STRIKE 24573 -#define SPELL_ENRAGE 23537 -#define SPELL_WATCH 24314 -#define SPELL_LEVEL_UP 24312 - -//Ohgans Spells -#define SPELL_SUNDERARMOR 24317 - -struct boss_mandokirAI : public ScriptedAI -{ - boss_mandokirAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 KillCount; - uint32 Watch_Timer; - uint32 TargetInRange; - uint32 Cleave_Timer; - uint32 Whirlwind_Timer; - uint32 Fear_Timer; - uint32 MortalStrike_Timer; - uint32 Check_Timer; - float targetX; - float targetY; - float targetZ; - - ScriptedInstance *m_pInstance; - - bool endWatch; - bool someWatched; - bool RaptorDead; - bool CombatStart; - - uint64 WatchTarget; - - void Reset() - { - KillCount = 0; - Watch_Timer = 33000; - Cleave_Timer = 7000; - Whirlwind_Timer = 20000; - Fear_Timer = 1000; - MortalStrike_Timer = 1000; - Check_Timer = 1000; - - targetX = 0.0; - targetY = 0.0; - targetZ = 0.0; - TargetInRange = 0; - - WatchTarget = 0; - - someWatched = false; - endWatch = false; - RaptorDead = false; - CombatStart = false; - - DoCast(me, 23243); - } - - void KilledUnit(Unit* victim) - { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - ++KillCount; - - if (KillCount == 3) - { - DoScriptText(SAY_DING_KILL, me); - - if (m_pInstance) - { - uint64 JindoGUID = m_pInstance->GetData64(DATA_JINDO); - if (JindoGUID) - { - if (Unit* jTemp = Unit::GetUnit(*me,JindoGUID)) - { - if (jTemp->isAlive()) - DoScriptText(SAY_GRATS_JINDO, jTemp); - } - } - } - DoCast(me, SPELL_LEVEL_UP, true); - KillCount = 0; - } - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->getVictim() && me->isAlive()) - { - if (!CombatStart) - { - //At combat Start Mandokir is mounted so we must unmount it first - me->Unmount(); - - //And summon his raptor - me->SummonCreature(14988, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000); - CombatStart = true; - } - - if (Watch_Timer <= diff) //Every 20 Sec Mandokir will check this - { - if (WatchTarget) //If someone is watched and If the Position of the watched target is different from the one stored, or are attacking, mandokir will charge him - { - Unit* pUnit = Unit::GetUnit(*me, WatchTarget); - - if (pUnit && ( - targetX != pUnit->GetPositionX() || - targetY != pUnit->GetPositionY() || - targetZ != pUnit->GetPositionZ() || - pUnit->isInCombat())) - { - if (me->IsWithinMeleeRange(pUnit)) - { - DoCast(pUnit, 24316); - } - else - { - DoCast(pUnit, SPELL_CHARGE); - //me->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true,1); - AttackStart(pUnit); - } - } - } - someWatched = false; - Watch_Timer = 20000; - } else Watch_Timer -= diff; - - if ((Watch_Timer < 8000) && !someWatched) //8 sec(cast time + expire time) before the check for the watch effect mandokir will cast watch debuff on a random target - { - if (Unit* p = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoScriptText(SAY_WATCH, me, p); - DoCast(p, SPELL_WATCH); - WatchTarget = p->GetGUID(); - someWatched = true; - endWatch = true; - } - } - - if ((Watch_Timer < 1000) && endWatch) //1 sec before the debuf expire, store the target position - { - Unit* pUnit = Unit::GetUnit(*me, WatchTarget); - if (pUnit) - { - targetX = pUnit->GetPositionX(); - targetY = pUnit->GetPositionY(); - targetZ = pUnit->GetPositionZ(); - } - endWatch = false; - } - - if (!someWatched) - { - //Cleave - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //Whirlwind - if (Whirlwind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - Whirlwind_Timer = 18000; - } else Whirlwind_Timer -= diff; - - //If more then 3 targets in melee range mandokir will cast fear - if (Fear_Timer <= diff) - { - TargetInRange = 0; - - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit(*me, (*i)->getUnitGuid()); - if (pUnit && me->IsWithinMeleeRange(pUnit)) - ++TargetInRange; - } - - if (TargetInRange > 3) - DoCast(me->getVictim(), SPELL_FEAR); - - Fear_Timer = 4000; - } else Fear_Timer -=diff; - - //Mortal Strike if target below 50% hp - if (me->getVictim() && me->getVictim()->GetHealth() < me->getVictim()->GetMaxHealth()*0.5) - { - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - MortalStrike_Timer = 15000; - } else MortalStrike_Timer -= diff; - } - } - //Checking if Ohgan is dead. If yes Mandokir will enrage. - if (Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_OHGAN) == DONE) - { - if (!RaptorDead) - { - DoCast(me, SPELL_ENRAGE); - RaptorDead = true; - } - } - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - - DoMeleeAttackIfReady(); - } - } -}; - -//Ohgan -struct mob_ohganAI : public ScriptedAI -{ - mob_ohganAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 SunderArmor_Timer; - ScriptedInstance *m_pInstance; - - void Reset() - { - SunderArmor_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) {} - - void JustDied(Unit* /*Killer*/) - { - if (m_pInstance) - m_pInstance->SetData(TYPE_OHGAN, DONE); - } - - void UpdateAI (const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //SunderArmor_Timer - if (SunderArmor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDERARMOR); - SunderArmor_Timer = 10000 + rand()%5000; - } else SunderArmor_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_mandokir(Creature* pCreature) -{ - return new boss_mandokirAI (pCreature); -} - -CreatureAI* GetAI_mob_ohgan(Creature* pCreature) -{ - return new mob_ohganAI (pCreature); -} - -void AddSC_boss_mandokir() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_mandokir"; - newscript->GetAI = &GetAI_boss_mandokir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ohgan"; - newscript->GetAI = &GetAI_mob_ohgan; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp deleted file mode 100644 index 77e9f9b929f..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Marli -SD%Complete: 80 -SDComment: Charging healers and casters not working. Perhaps wrong Spell Timers. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309005 -#define SAY_TRANSFORM -1309006 -#define SAY_SPIDER_SPAWN -1309007 -#define SAY_DEATH -1309008 - -#define SPELL_CHARGE 22911 -#define SPELL_ASPECT_OF_MARLI 24686 // A stun spell -#define SPELL_ENVOLWINGWEB 24110 -#define SPELL_POISONVOLLEY 24099 -#define SPELL_SPIDER_FORM 24084 - -//The Spider Spells -#define SPELL_LEVELUP 24312 //Not right Spell. - -struct boss_marliAI : public ScriptedAI -{ - boss_marliAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 SpawnStartSpiders_Timer; - uint32 PoisonVolley_Timer; - uint32 SpawnSpider_Timer; - uint32 Charge_Timer; - uint32 Aspect_Timer; - uint32 Transform_Timer; - uint32 TransformBack_Timer; - - bool Spawned; - bool PhaseTwo; - - void Reset() - { - SpawnStartSpiders_Timer = 1000; - PoisonVolley_Timer = 15000; - SpawnSpider_Timer = 30000; - Charge_Timer = 1500; - Aspect_Timer = 12000; - Transform_Timer = 45000; - TransformBack_Timer = 25000; - - Spawned = false; - PhaseTwo = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - if (m_pInstance) - m_pInstance->SetData(TYPE_MARLI, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->getVictim() && me->isAlive()) - { - if (PoisonVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISONVOLLEY); - PoisonVolley_Timer = 10000 + rand()%10000; - } else PoisonVolley_Timer -= diff; - - if (!PhaseTwo && Aspect_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); - Aspect_Timer = 13000 + rand()%5000; - } else Aspect_Timer -= diff; - - if (!Spawned && SpawnStartSpiders_Timer <= diff) - { - DoScriptText(SAY_SPIDER_SPAWN, me); - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget) - return; - - Creature *Spider = NULL; - - Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - - Spawned = true; - } else SpawnStartSpiders_Timer -= diff; - - if (SpawnSpider_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget) - return; - - Creature *Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - SpawnSpider_Timer = 12000 + rand()%5000; - } else SpawnSpider_Timer -= diff; - - if (!PhaseTwo && Transform_Timer <= diff) - { - DoScriptText(SAY_TRANSFORM, me); - DoCast(me, SPELL_SPIDER_FORM); - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); - me->UpdateDamagePhysical(BASE_ATTACK); - DoCast(me->getVictim(), SPELL_ENVOLWINGWEB); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-100); - - PhaseTwo = true; - Transform_Timer = urand(35000,60000); - } else Transform_Timer -= diff; - - if (PhaseTwo) - { - if (Charge_Timer <= diff) - { - Unit *pTarget = NULL; - int i = 0; - while (i < 3) // max 3 tries to get a random target with power_mana - { - ++i; - pTarget = SelectTarget(SELECT_TARGET_RANDOM,1, 100, true); // not aggro leader - if (pTarget && pTarget->getPowerType() == POWER_MANA) - i = 3; - } - if (pTarget) - { - DoCast(pTarget, SPELL_CHARGE); - //me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); - //me->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, true,1); - AttackStart(pTarget); - } - - Charge_Timer = 8000; - } else Charge_Timer -= diff; - - if (TransformBack_Timer <= diff) - { - me->SetDisplayId(15220); - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1))); - me->UpdateDamagePhysical(BASE_ATTACK); - - PhaseTwo = false; - TransformBack_Timer = urand(25000,40000); - } else TransformBack_Timer -= diff; - - } - - DoMeleeAttackIfReady(); - } - } -}; - -//Spawn of Marli -struct mob_spawn_of_marliAI : public ScriptedAI -{ - mob_spawn_of_marliAI(Creature *c) : ScriptedAI(c) {} - - uint32 LevelUp_Timer; - - void Reset() - { - LevelUp_Timer = 3000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI (const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //LevelUp_Timer - if (LevelUp_Timer <= diff) - { - DoCast(me, SPELL_LEVELUP); - LevelUp_Timer = 3000; - } else LevelUp_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_marli(Creature* pCreature) -{ - return new boss_marliAI (pCreature); -} - -CreatureAI* GetAI_mob_spawn_of_marli(Creature* pCreature) -{ - return new mob_spawn_of_marliAI (pCreature); -} - -void AddSC_boss_marli() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_marli"; - newscript->GetAI = &GetAI_boss_marli; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_spawn_of_marli"; - newscript->GetAI = &GetAI_mob_spawn_of_marli; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp deleted file mode 100644 index f7b01b26e19..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Renataki -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SPELL_AMBUSH 24337 -#define SPELL_THOUSANDBLADES 24649 - -#define EQUIP_ID_MAIN_HAND 0 //was item display id 31818, but this id does not exist - -struct boss_renatakiAI : public ScriptedAI -{ - boss_renatakiAI(Creature *c) : ScriptedAI(c) {} - - uint32 Invisible_Timer; - uint32 Ambush_Timer; - uint32 Visible_Timer; - uint32 Aggro_Timer; - uint32 ThousandBlades_Timer; - - bool Invisible; - bool Ambushed; - - void Reset() - { - Invisible_Timer = 8000 + rand()%10000; - Ambush_Timer = 3000; - Visible_Timer = 4000; - Aggro_Timer = 15000 + rand()%10000; - ThousandBlades_Timer = 4000 + rand()%4000; - - Invisible = false; - Ambushed = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Invisible_Timer - if (Invisible_Timer <= diff) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - me->SetDisplayId(11686); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Invisible = true; - - Invisible_Timer = 15000 + rand()%15000; - } else Invisible_Timer -= diff; - - if (Invisible) - { - if (Ambush_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - { - DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); - DoCast(pTarget, SPELL_AMBUSH); - } - - Ambushed = true; - Ambush_Timer = 3000; - } else Ambush_Timer -= diff; - } - - if (Ambushed) - { - if (Visible_Timer <= diff) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - - me->SetDisplayId(15268); - SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Invisible = false; - - Visible_Timer = 4000; - } else Visible_Timer -= diff; - } - - //Resetting some aggro so he attacks other gamers - if (!Invisible) - if (Aggro_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-50); - - if (pTarget) - AttackStart(pTarget); - - Aggro_Timer = 7000 + rand()%13000; - } else Aggro_Timer -= diff; - - if (!Invisible) - if (ThousandBlades_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THOUSANDBLADES); - ThousandBlades_Timer = 7000 + rand()%5000; - } else ThousandBlades_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_renataki(Creature* pCreature) -{ - return new boss_renatakiAI (pCreature); -} - -void AddSC_boss_renataki() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_renataki"; - newscript->GetAI = &GetAI_boss_renataki; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp deleted file mode 100644 index 179700d36e7..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp +++ /dev/null @@ -1,556 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Thekal -SD%Complete: 95 -SDComment: Almost finished. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309009 -#define SAY_DEATH -1309010 - -#define SPELL_MORTALCLEAVE 22859 -#define SPELL_SILENCE 23207 -#define SPELL_FRENZY 23342 -#define SPELL_FORCEPUNCH 24189 -#define SPELL_CHARGE 24408 -#define SPELL_ENRAGE 23537 -#define SPELL_SUMMONTIGERS 24183 -#define SPELL_TIGER_FORM 24169 -#define SPELL_RESURRECT 24173 //We will not use this spell. - -//Zealot Lor'Khan Spells -#define SPELL_SHIELD 25020 -#define SPELL_BLOODLUST 24185 -#define SPELL_GREATERHEAL 24208 -#define SPELL_DISARM 22691 - -//Zealot Lor'Khan Spells -#define SPELL_SWEEPINGSTRIKES 18765 -#define SPELL_SINISTERSTRIKE 15667 -#define SPELL_GOUGE 24698 -#define SPELL_KICK 15614 -#define SPELL_BLIND 21060 - -struct boss_thekalAI : public ScriptedAI -{ - boss_thekalAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 MortalCleave_Timer; - uint32 Silence_Timer; - uint32 Frenzy_Timer; - uint32 ForcePunch_Timer; - uint32 Charge_Timer; - uint32 Enrage_Timer; - uint32 SummonTigers_Timer; - uint32 Check_Timer; - uint32 Resurrect_Timer; - - ScriptedInstance *m_pInstance; - bool Enraged; - bool PhaseTwo; - bool WasDead; - - void Reset() - { - MortalCleave_Timer = 4000; - Silence_Timer = 9000; - Frenzy_Timer = 30000; - ForcePunch_Timer = 4000; - Charge_Timer = 12000; - Enrage_Timer = 32000; - SummonTigers_Timer = 25000; - Check_Timer = 10000; - Resurrect_Timer = 10000; - - Enraged = false; - PhaseTwo = false; - WasDead = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - if (m_pInstance) - m_pInstance->SetData(TYPE_THEKAL, DONE); - } - - void JustReachedHome() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_THEKAL, NOT_STARTED); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Check_Timer for the death of LorKhan and Zath. - if (!WasDead && Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL) - { - //Resurrect LorKhan - if (Unit *pLorKhan = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_LORKHAN))) - { - pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pLorKhan->setFaction(14); - pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); - - m_pInstance->SetData(TYPE_LORKHAN, DONE); - } - } - - if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL) - { - //Resurrect Zath - Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH)); - if (pZath) - { - pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pZath->setFaction(14); - pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); - - m_pInstance->SetData(TYPE_ZATH, DONE); - } - } - } - - Check_Timer = 5000; - } else Check_Timer -= diff; - - if (!PhaseTwo && MortalCleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALCLEAVE); - MortalCleave_Timer = 15000 + rand()%5000; - } else MortalCleave_Timer -= diff; - - if (!PhaseTwo && Silence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - Silence_Timer = 20000 + rand()%5000; - } else Silence_Timer -= diff; - - if (!PhaseTwo && !WasDead && me->GetHealth() <= me->GetMaxHealth() * 0.05) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - me->AttackStop(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_THEKAL, SPECIAL); - - WasDead=true; - } - - //Thekal will transform to Tiger if he died and was not resurrected after 10 seconds. - if (!PhaseTwo && WasDead) - { - if (Resurrect_Timer <= diff) - { - DoCast(me, SPELL_TIGER_FORM); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetHealth(int(me->GetMaxHealth()*1.0)); - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40))); - me->UpdateDamagePhysical(BASE_ATTACK); - DoResetThreat(); - PhaseTwo = true; - } else Resurrect_Timer -= diff; - } - - if ((me->GetHealth()*100 / me->GetMaxHealth() == 100) && WasDead) - { - WasDead = false; - } - - if (PhaseTwo) - { - if (Charge_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_CHARGE); - DoResetThreat(); - AttackStart(pTarget); - } - - Charge_Timer = 15000 + rand()%7000; - } else Charge_Timer -= diff; - - if (Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - Frenzy_Timer = 30000; - } else Frenzy_Timer -= diff; - - if (ForcePunch_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - ForcePunch_Timer = 16000 + rand()%5000; - } else ForcePunch_Timer -= diff; - - if (SummonTigers_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUMMONTIGERS); - SummonTigers_Timer = 10000 + rand()%4000; - } else SummonTigers_Timer -= diff; - - if ((me->GetHealth()*100 / me->GetMaxHealth() < 11) && !Enraged) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } - } - - DoMeleeAttackIfReady(); - - } -}; - -//Zealot Lor'Khan -struct mob_zealot_lorkhanAI : public ScriptedAI -{ - mob_zealot_lorkhanAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 Shield_Timer; - uint32 BloodLust_Timer; - uint32 GreaterHeal_Timer; - uint32 Disarm_Timer; - uint32 Check_Timer; - - bool FakeDeath; - - ScriptedInstance *m_pInstance; - - void Reset() - { - Shield_Timer = 1000; - BloodLust_Timer = 16000; - GreaterHeal_Timer = 32000; - Disarm_Timer = 6000; - Check_Timer = 10000; - - FakeDeath = false; - - if (m_pInstance) - m_pInstance->SetData(TYPE_LORKHAN, NOT_STARTED); - - me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI (const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Shield_Timer - if (Shield_Timer <= diff) - { - DoCast(me, SPELL_SHIELD); - Shield_Timer = 61000; - } else Shield_Timer -= diff; - - //BloodLust_Timer - if (BloodLust_Timer <= diff) - { - DoCast(me, SPELL_BLOODLUST); - BloodLust_Timer = 20000+rand()%8000; - } else BloodLust_Timer -= diff; - - //Casting Greaterheal to Thekal or Zath if they are in meele range. - if (GreaterHeal_Timer <= diff) - { - if (m_pInstance) - { - Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL)); - Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH)); - - if (!pThekal || !pZath) - return; - - switch (urand(0,1)) - { - case 0: - if (me->IsWithinMeleeRange(pThekal)) - DoCast(pThekal, SPELL_GREATERHEAL); - break; - case 1: - if (me->IsWithinMeleeRange(pZath)) - DoCast(pZath, SPELL_GREATERHEAL); - break; - } - } - - GreaterHeal_Timer = 15000+rand()%5000; - } else GreaterHeal_Timer -= diff; - - //Disarm_Timer - if (Disarm_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DISARM); - Disarm_Timer = 15000+rand()%10000; - } else Disarm_Timer -= diff; - - //Check_Timer for the death of LorKhan and Zath. - if (!FakeDeath && Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL) - { - //Resurrect Thekal - if (Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL))) - { - pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pThekal->setFaction(14); - pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); - } - } - - if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL) - { - //Resurrect Zath - if (Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH))) - { - pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pZath->setFaction(14); - pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); - } - } - } - - Check_Timer = 5000; - } else Check_Timer -= diff; - - if (me->GetHealth() <= me->GetMaxHealth() * 0.05) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - me->setFaction(35); - me->AttackStop(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_LORKHAN, SPECIAL); - - FakeDeath = true; - } - - DoMeleeAttackIfReady(); - } -}; - -//Zealot Zath -struct mob_zealot_zathAI : public ScriptedAI -{ - mob_zealot_zathAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 SweepingStrikes_Timer; - uint32 SinisterStrike_Timer; - uint32 Gouge_Timer; - uint32 Kick_Timer; - uint32 Blind_Timer; - uint32 Check_Timer; - - bool FakeDeath; - - ScriptedInstance *m_pInstance; - - void Reset() - { - SweepingStrikes_Timer = 13000; - SinisterStrike_Timer = 8000; - Gouge_Timer = 25000; - Kick_Timer = 18000; - Blind_Timer = 5000; - Check_Timer = 10000; - - FakeDeath = false; - - if (m_pInstance) - m_pInstance->SetData(TYPE_ZATH, NOT_STARTED); - - me->SetStandState(UNIT_STAND_STATE_STAND); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI (const uint32 diff) - { - if (!UpdateVictim()) - return; - - //SweepingStrikes_Timer - if (SweepingStrikes_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SWEEPINGSTRIKES); - SweepingStrikes_Timer = 22000+rand()%4000; - } else SweepingStrikes_Timer -= diff; - - //SinisterStrike_Timer - if (SinisterStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SINISTERSTRIKE); - SinisterStrike_Timer = 8000+rand()%8000; - } else SinisterStrike_Timer -= diff; - - //Gouge_Timer - if (Gouge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GOUGE); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-100); - - Gouge_Timer = 17000+rand()%10000; - } else Gouge_Timer -= diff; - - //Kick_Timer - if (Kick_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KICK); - Kick_Timer = 15000+rand()%10000; - } else Kick_Timer -= diff; - - //Blind_Timer - if (Blind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLIND); - Blind_Timer = 10000+rand()%10000; - } else Blind_Timer -= diff; - - //Check_Timer for the death of LorKhan and Zath. - if (!FakeDeath && Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL) - { - //Resurrect LorKhan - if (Unit *pLorKhan = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_LORKHAN))) - { - pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pLorKhan->setFaction(14); - pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); - } - } - - if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL) - { - //Resurrect Thekal - if (Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL))) - { - pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pThekal->setFaction(14); - pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); - } - } - } - - Check_Timer = 5000; - } else Check_Timer -= diff; - - if (me->GetHealth() <= me->GetMaxHealth() * 0.05) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - me->setFaction(35); - me->AttackStop(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_ZATH, SPECIAL); - - FakeDeath = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_thekal(Creature* pCreature) -{ - return new boss_thekalAI (pCreature); -} - -CreatureAI* GetAI_mob_zealot_lorkhan(Creature* pCreature) -{ - return new mob_zealot_lorkhanAI (pCreature); -} - -CreatureAI* GetAI_mob_zealot_zath(Creature* pCreature) -{ - return new mob_zealot_zathAI (pCreature); -} - -void AddSC_boss_thekal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_thekal"; - newscript->GetAI = &GetAI_boss_thekal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_zealot_lorkhan"; - newscript->GetAI = &GetAI_mob_zealot_lorkhan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_zealot_zath"; - newscript->GetAI = &GetAI_mob_zealot_zath; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp deleted file mode 100644 index ec1a7a142b5..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Venoxis -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_TRANSFORM -1309000 -#define SAY_DEATH -1309001 - -#define SPELL_HOLY_FIRE 23860 -#define SPELL_HOLY_WRATH 28883 //Not sure if this or 23979 -#define SPELL_VENOMSPIT 23862 -#define SPELL_HOLY_NOVA 23858 -#define SPELL_POISON_CLOUD 23861 -#define SPELL_SNAKE_FORM 23849 -#define SPELL_RENEW 23895 -#define SPELL_BERSERK 23537 -#define SPELL_DISPELL 23859 - -struct boss_venoxisAI : public ScriptedAI -{ - boss_venoxisAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 HolyFire_Timer; - uint32 HolyWrath_Timer; - uint32 VenomSpit_Timer; - uint32 Renew_Timer; - uint32 PoisonCloud_Timer; - uint32 HolyNova_Timer; - uint32 Dispell_Timer; - uint32 TargetInRange; - - bool PhaseTwo; - bool InBerserk; - - void Reset() - { - HolyFire_Timer = 10000; - HolyWrath_Timer = 60500; - VenomSpit_Timer = 5500; - Renew_Timer = 30500; - PoisonCloud_Timer = 2000; - HolyNova_Timer = 5000; - Dispell_Timer = 35000; - TargetInRange = 0; - - PhaseTwo = false; - InBerserk= false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - if (m_pInstance) - m_pInstance->SetData(TYPE_VENOXIS, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if ((me->GetHealth()*100 / me->GetMaxHealth() > 50)) - { - if (Dispell_Timer <= diff) - { - DoCast(me, SPELL_DISPELL); - Dispell_Timer = 15000 + rand()%15000; - } else Dispell_Timer -= diff; - - if (Renew_Timer <= diff) - { - DoCast(me, SPELL_RENEW); - Renew_Timer = 20000 + rand()%10000; - } else Renew_Timer -= diff; - - if (HolyWrath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HOLY_WRATH); - HolyWrath_Timer = 15000 + rand()%10000; - } else HolyWrath_Timer -= diff; - - if (HolyNova_Timer <= diff) - { - TargetInRange = 0; - for (uint8 i = 0; i < 10; ++i) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,i)) - if (me->IsWithinMeleeRange(pTarget)) - ++TargetInRange; - } - - if (TargetInRange > 1) - { - DoCast(me->getVictim(), SPELL_HOLY_NOVA); - HolyNova_Timer = 1000; - } - else - { - HolyNova_Timer = 2000; - } - - } else HolyNova_Timer -= diff; - - if (HolyFire_Timer < diff && TargetInRange < 3) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_HOLY_FIRE); - - HolyFire_Timer = 8000; - } else HolyFire_Timer -= diff; - } - else - { - if (!PhaseTwo) - { - DoScriptText(SAY_TRANSFORM, me); - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SNAKE_FORM); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 25))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 25))); - me->UpdateDamagePhysical(BASE_ATTACK); - DoResetThreat(); - PhaseTwo = true; - } - - if (PhaseTwo && PoisonCloud_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_CLOUD); - PoisonCloud_Timer = 15000; - }PoisonCloud_Timer -=diff; - - if (PhaseTwo && VenomSpit_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_VENOMSPIT); - - VenomSpit_Timer = 15000 + rand()%5000; - } else VenomSpit_Timer -= diff; - - if (PhaseTwo && (me->GetHealth()*100 / me->GetMaxHealth() < 11)) - { - if (!InBerserk) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_BERSERK); - InBerserk = true; - } - } - } - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_venoxis(Creature* pCreature) -{ - return new boss_venoxisAI (pCreature); -} - -void AddSC_boss_venoxis() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_venoxis"; - newscript->GetAI = &GetAI_boss_venoxis; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp deleted file mode 100644 index a71d7e0504a..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Wushoolay -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SPELL_LIGHTNINGCLOUD 25033 -#define SPELL_LIGHTNINGWAVE 24819 - -struct boss_wushoolayAI : public ScriptedAI -{ - boss_wushoolayAI(Creature *c) : ScriptedAI(c) {} - - uint32 LightningCloud_Timer; - uint32 LightningWave_Timer; - - void Reset() - { - LightningCloud_Timer = 5000 + rand()%5000; - LightningWave_Timer = 8000 + rand()%8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //LightningCloud_Timer - if (LightningCloud_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LIGHTNINGCLOUD); - LightningCloud_Timer = 15000 + rand()%5000; - } else LightningCloud_Timer -= diff; - - //LightningWave_Timer - if (LightningWave_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_LIGHTNINGWAVE); - - LightningWave_Timer = 12000 + rand()%4000; - } else LightningWave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_wushoolay(Creature* pCreature) -{ - return new boss_wushoolayAI (pCreature); -} - -void AddSC_boss_wushoolay() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_wushoolay"; - newscript->GetAI = &GetAI_boss_wushoolay; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp b/src/server/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp deleted file mode 100644 index aaed1c6df3a..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_ZulGurub -SD%Complete: 80 -SDComment: Missing reset function after killing a boss for Ohgan, Thekal. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -struct instance_zulgurub : public ScriptedInstance -{ - instance_zulgurub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. - uint32 m_auiEncounter[MAX_ENCOUNTERS]; - - //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. - uint64 m_uiLorKhanGUID; - uint64 m_uiZathGUID; - uint64 m_uiThekalGUID; - uint64 m_uiJindoGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiLorKhanGUID = 0; - m_uiZathGUID = 0; - m_uiThekalGUID = 0; - m_uiJindoGUID = 0; - } - - bool IsEncounterInProgress() const - { - //not active in Zul'Gurub - return false; - } - - void OnCreatureCreate(Creature* pCreature) - { - switch(pCreature->GetEntry()) - { - case 11347: m_uiLorKhanGUID = pCreature->GetGUID(); break; - case 11348: m_uiZathGUID = pCreature->GetGUID(); break; - case 14509: m_uiThekalGUID = pCreature->GetGUID(); break; - case 11380: m_uiJindoGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_ARLOKK: - m_auiEncounter[0] = uiData; - break; - - case TYPE_JEKLIK: - m_auiEncounter[1] = uiData; - break; - - case TYPE_VENOXIS: - m_auiEncounter[2] = uiData; - break; - - case TYPE_MARLI: - m_auiEncounter[3] = uiData; - break; - - case TYPE_THEKAL: - m_auiEncounter[4] = uiData; - break; - - case TYPE_LORKHAN: - m_auiEncounter[5] = uiData; - break; - - case TYPE_ZATH: - m_auiEncounter[6] = uiData; - break; - - case TYPE_OHGAN: - m_auiEncounter[7] = uiData; - break; - } - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case TYPE_ARLOKK: - return m_auiEncounter[0]; - case TYPE_JEKLIK: - return m_auiEncounter[1]; - case TYPE_VENOXIS: - return m_auiEncounter[2]; - case TYPE_MARLI: - return m_auiEncounter[3]; - case TYPE_THEKAL: - return m_auiEncounter[4]; - case TYPE_LORKHAN: - return m_auiEncounter[5]; - case TYPE_ZATH: - return m_auiEncounter[6]; - case TYPE_OHGAN: - return m_auiEncounter[7]; - } - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_LORKHAN: - return m_uiLorKhanGUID; - case DATA_ZATH: - return m_uiZathGUID; - case DATA_THEKAL: - return m_uiThekalGUID; - case DATA_JINDO: - return m_uiJindoGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_zulgurub(Map* pMap) -{ - return new instance_zulgurub(pMap); -} - -void AddSC_instance_zulgurub() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_zulgurub"; - newscript->GetInstanceData = &GetInstanceData_instance_zulgurub; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/eastern_kingdoms/zulgurub/zulgurub.h b/src/server/scripts/eastern_kingdoms/zulgurub/zulgurub.h deleted file mode 100644 index bf55a54c1d5..00000000000 --- a/src/server/scripts/eastern_kingdoms/zulgurub/zulgurub.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_ZULGURUB_H -#define DEF_ZULGURUB_H - -enum eTypes -{ - MAX_ENCOUNTERS = 8, - - TYPE_ARLOKK = 1, - TYPE_JEKLIK = 2, - TYPE_VENOXIS = 3, - TYPE_MARLI = 4, - TYPE_OHGAN = 5, - TYPE_THEKAL = 6, - TYPE_ZATH = 7, - TYPE_LORKHAN = 8, - - DATA_JINDO = 10, - DATA_LORKHAN = 11, - DATA_THEKAL = 12, - DATA_ZATH = 13 -}; - -#endif - diff --git a/src/server/scripts/examples/example_creature.cpp b/src/server/scripts/examples/example_creature.cpp deleted file mode 100644 index 856b680e2e6..00000000000 --- a/src/server/scripts/examples/example_creature.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Example_Creature -SD%Complete: 100 -SDComment: Short custom scripting example -SDCategory: Script Examples -EndScriptData */ - -#include "ScriptedPch.h" - -// **** This script is designed as an example for others to build on **** -// **** Please modify whatever you'd like to as this script is only for developement **** - -// **** Script Info **** -// This script is written in a way that it can be used for both friendly and hostile monsters -// Its primary purpose is to show just how much you can really do with scripts -// I recommend trying it out on both an agressive NPC and on friendly npc - -// **** Quick Info **** -// Functions with Handled Function marked above them are functions that are called automatically by the core -// Functions that are marked Custom Function are functions I've created to simplify code - -enum Yells -{ - //List of text id's. The text is stored in database, also in a localized version - //(if translation not exist for the textId, default english text will be used) - //Not required to define in this way, but simplify if changes are needed. - SAY_AGGRO = -1999900, - SAY_RANDOM_0 = -1999901, - SAY_RANDOM_1 = -1999902, - SAY_RANDOM_2 = -1999903, - SAY_RANDOM_3 = -1999904, - SAY_RANDOM_4 = -1999905, - SAY_BERSERK = -1999906, - SAY_PHASE = -1999907, - SAY_DANCE = -1999908, - SAY_SALUTE = -1999909, - SAY_EVADE = -1999910, -}; - -enum Spells -{ - // List of spells. - // Not required to define them in this way, but will make it easier to maintain in case spellId change - SPELL_BUFF = 25661, - SPELL_ONE = 12555, - SPELL_ONE_ALT = 24099, - SPELL_TWO = 10017, - SPELL_THREE = 26027, - SPELL_FRENZY = 23537, - SPELL_BERSERK = 32965, -}; - -enum eEnums -{ - // any other constants - FACTION_WORGEN = 24 -}; - -//List of gossip item texts. Items will appear in the gossip window. -#define GOSSIP_ITEM "I'm looking for a fight" - -struct example_creatureAI : public ScriptedAI -{ - //*** HANDLED FUNCTION *** - //This is the constructor, called only once when the Creature is first created - example_creatureAI(Creature *c) : ScriptedAI(c) {} - - //*** CUSTOM VARIABLES **** - //These variables are for use only by this individual script. - //Nothing else will ever call them but us. - - uint32 m_uiSayTimer; // Timer for random chat - uint32 m_uiRebuffTimer; // Timer for rebuffing - uint32 m_uiSpell1Timer; // Timer for spell 1 when in combat - uint32 m_uiSpell2Timer; // Timer for spell 1 when in combat - uint32 m_uiSpell3Timer; // Timer for spell 1 when in combat - uint32 m_uiBeserkTimer; // Timer until we go into Beserk (enraged) mode - uint32 m_uiPhase; // The current battle phase we are in - uint32 m_uiPhaseTimer; // Timer until phase transition - - //*** HANDLED FUNCTION *** - //This is called after spawn and whenever the core decides we need to evade - void Reset() - { - m_uiPhase = 1; // Start in phase 1 - m_uiPhaseTimer = 60000; // 60 seconds - m_uiSpell1Timer = 5000; // 5 seconds - m_uiSpell2Timer = urand(10000,20000); // between 10 and 20 seconds - m_uiSpell3Timer = 19000; // 19 seconds - m_uiBeserkTimer = 120000; // 2 minutes - - me->RestoreFaction(); - } - - //*** HANDLED FUNCTION *** - // Enter Combat called once per combat - void EnterCombat(Unit* pWho) - { - //Say some stuff - DoScriptText(SAY_AGGRO, me, pWho); - } - - //*** HANDLED FUNCTION *** - // Attack Start is called when victim change (including at start of combat) - // By default, attack pWho and start movement toward the victim. - //void AttackStart(Unit* pWho) - //{ - // ScriptedAI::AttackStart(pWho); - //} - - //*** HANDLED FUNCTION *** - // Called when going out of combat. Reset is called just after. - void EnterEvadeMode() - { - DoScriptText(SAY_EVADE, me); - } - - //*** HANDLED FUNCTION *** - //Our Receive emote function - void ReceiveEmote(Player* /*pPlayer*/, uint32 uiTextEmote) - { - me->HandleEmoteCommand(uiTextEmote); - - switch(uiTextEmote) - { - case TEXTEMOTE_DANCE: - DoScriptText(SAY_DANCE, me); - break; - case TEXTEMOTE_SALUTE: - DoScriptText(SAY_SALUTE, me); - break; - } - } - - //*** HANDLED FUNCTION *** - //Update AI is called Every single map update (roughly once every 50ms if a player is within the grid) - void UpdateAI(const uint32 uiDiff) - { - //Out of combat timers - if (!me->getVictim()) - { - //Random Say timer - if (m_uiSayTimer <= uiDiff) - { - //Random switch between 5 outcomes - DoScriptText(RAND(SAY_RANDOM_0,SAY_RANDOM_1,SAY_RANDOM_2,SAY_RANDOM_3,SAY_RANDOM_4), me); - - m_uiSayTimer = 45000; //Say something agian in 45 seconds - } - else - m_uiSayTimer -= uiDiff; - - //Rebuff timer - if (m_uiRebuffTimer <= uiDiff) - { - DoCast(me, SPELL_BUFF); - m_uiRebuffTimer = 900000; //Rebuff agian in 15 minutes - } - else - m_uiRebuffTimer -= uiDiff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Spell 1 timer - if (m_uiSpell1Timer <= uiDiff) - { - //Cast spell one on our current target. - if (rand()%50 > 10) - DoCast(me->getVictim(), SPELL_ONE_ALT); - else if (me->IsWithinDist(me->getVictim(), 25.0f)) - DoCast(me->getVictim(), SPELL_ONE); - - m_uiSpell1Timer = 5000; - } - else - m_uiSpell1Timer -= uiDiff; - - //Spell 2 timer - if (m_uiSpell2Timer <= uiDiff) - { - //Cast spell two on our current target. - DoCast(me->getVictim(), SPELL_TWO); - m_uiSpell2Timer = 37000; - } - else - m_uiSpell2Timer -= uiDiff; - - //Beserk timer - if (m_uiPhase > 1) - { - //Spell 3 timer - if (m_uiSpell3Timer <= uiDiff) - { - //Cast spell one on our current target. - DoCast(me->getVictim(), SPELL_THREE); - - m_uiSpell3Timer = 19000; - } - else - m_uiSpell3Timer -= uiDiff; - - if (m_uiBeserkTimer <= uiDiff) - { - //Say our line then cast uber death spell - DoScriptText(SAY_BERSERK, me, me->getVictim()); - DoCast(me->getVictim(), SPELL_BERSERK); - - //Cast our beserk spell agian in 12 seconds if we didn't kill everyone - m_uiBeserkTimer = 12000; - } - else - m_uiBeserkTimer -= uiDiff; - } - else if (m_uiPhase == 1) //Phase timer - { - if (m_uiPhaseTimer <= uiDiff) - { - //Go to next phase - ++m_uiPhase; - DoScriptText(SAY_PHASE, me); - DoCast(me, SPELL_FRENZY); - } - else - m_uiPhaseTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } -}; - -//This is the GetAI method used by all scripts that involve AI -//It is called every time a new Creature using this script is created -CreatureAI* GetAI_example_creature(Creature* pCreature) -{ - return new example_creatureAI (pCreature); -} - -//This function is called when the player clicks an option on the gossip menu -bool GossipSelect_example_creature(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - //Set our faction to hostile towards all - pCreature->setFaction(FACTION_WORGEN); - pCreature->AI()->AttackStart(pPlayer); - } - - return true; -} - -//This function is called when the player opens the gossip menu -bool GossipHello_example_creature(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - - return true; -} - -//This is the actual function called only once durring InitScripts() -//It must define all handled functions that are to be run in this script -void AddSC_example_creature() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "example_creature"; - newscript->GetAI = &GetAI_example_creature; - newscript->pGossipHello = &GossipHello_example_creature; - newscript->pGossipSelect = &GossipSelect_example_creature; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/examples/example_escort.cpp b/src/server/scripts/examples/example_escort.cpp deleted file mode 100644 index bf2b454bf8e..00000000000 --- a/src/server/scripts/examples/example_escort.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Example_Escort -SD%Complete: 100 -SDComment: Script used for testing escortAI -SDCategory: Script Examples -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -enum eEnums -{ - NPC_FELBOAR = 21878, - - SPELL_DEATH_COIL = 33130, - SPELL_ELIXIR_OF_FORTITUDE = 3593, - SPELL_BLUE_FIREWORK = 11540, - - SAY_AGGRO1 = -1999910, - SAY_AGGRO2 = -1999911, - SAY_WP_1 = -1999912, - SAY_WP_2 = -1999913, - SAY_WP_3 = -1999914, - SAY_WP_4 = -1999915, - SAY_DEATH_1 = -1999916, - SAY_DEATH_2 = -1999917, - SAY_DEATH_3 = -1999918, - SAY_SPELL = -1999919, - SAY_RAND_1 = -1999920, - SAY_RAND_2 = -1999921 -}; - -#define GOSSIP_ITEM_1 "Click to Test Escort(Attack, Run)" -#define GOSSIP_ITEM_2 "Click to Test Escort(NoAttack, Walk)" -#define GOSSIP_ITEM_3 "Click to Test Escort(NoAttack, Run)" - -struct example_escortAI : public npc_escortAI -{ - // CreatureAI functions - example_escortAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - uint32 m_uiDeathCoilTimer; - uint32 m_uiChatTimer; - - void JustSummoned(Creature* pSummoned) - { - pSummoned->AI()->AttackStart(me); - } - - // Pure Virtual Functions (Have to be implemented) - void WaypointReached(uint32 uiWP) - { - switch (uiWP) - { - case 1: - DoScriptText(SAY_WP_1, me); - break; - case 3: - DoScriptText(SAY_WP_2, me); - me->SummonCreature(NPC_FELBOAR, me->GetPositionX()+5.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); - break; - case 4: - if (Player* pPlayer = GetPlayerForEscort()) - { - //pTmpPlayer is the target of the text - DoScriptText(SAY_WP_3, me, pPlayer); - //pTmpPlayer is the source of the text - DoScriptText(SAY_WP_4, pPlayer); - } - break; - } - } - - void EnterCombat(Unit* /*pWho*/) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (Player* pPlayer = GetPlayerForEscort()) - DoScriptText(SAY_AGGRO1, me, pPlayer); - } - else - DoScriptText(SAY_AGGRO2, me); - } - - void Reset() - { - m_uiDeathCoilTimer = 4000; - m_uiChatTimer = 4000; - } - - void JustDied(Unit* pKiller) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (Player* pPlayer = GetPlayerForEscort()) - { - // not a likely case, code here for the sake of example - if (pKiller == me) - { - DoScriptText(SAY_DEATH_1, me, pPlayer); - } - else - DoScriptText(SAY_DEATH_2, me, pPlayer); - } - } - else - DoScriptText(SAY_DEATH_3, me); - } - - void UpdateAI(const uint32 uiDiff) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(uiDiff); - - //Combat check - if (me->getVictim()) - { - if (m_uiDeathCoilTimer <= uiDiff) - { - DoScriptText(SAY_SPELL, me); - DoCast(me->getVictim(), SPELL_DEATH_COIL, false); - m_uiDeathCoilTimer = 4000; - } - else - m_uiDeathCoilTimer -= uiDiff; - } - else - { - //Out of combat but being escorted - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (m_uiChatTimer <= uiDiff) - { - if (me->HasAura(SPELL_ELIXIR_OF_FORTITUDE, 0)) - { - DoScriptText(SAY_RAND_1, me); - DoCast(me, SPELL_BLUE_FIREWORK, false); - } - else - { - DoScriptText(SAY_RAND_2, me); - DoCast(me, SPELL_ELIXIR_OF_FORTITUDE, false); - } - - m_uiChatTimer = 12000; - } - else - m_uiChatTimer -= uiDiff; - } - } - } -}; - -CreatureAI* GetAI_example_escort(Creature* pCreature) -{ - return new example_escortAI(pCreature); -} - -bool GossipHello_example_escort(Player* pPlayer, Creature* pCreature) -{ - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - pPlayer->PrepareGossipMenu(pCreature, 0); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - - pPlayer->SendPreparedGossip(pCreature); - - return true; -} - -bool GossipSelect_example_escort(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - npc_escortAI* pEscortAI = CAST_AI(example_escortAI, pCreature->AI()); - - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pEscortAI) - pEscortAI->Start(true, true, pPlayer->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pEscortAI) - pEscortAI->Start(false, false, pPlayer->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pEscortAI) - pEscortAI->Start(false, true, pPlayer->GetGUID()); - break; - default: - return false; // nothing defined -> trinity core handling - } - - return true; // no default handling -> prevent trinity core handling -} - -void AddSC_example_escort() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "example_escort"; - newscript->GetAI = &GetAI_example_escort; - newscript->pGossipHello = &GossipHello_example_escort; - newscript->pGossipSelect = &GossipSelect_example_escort; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/examples/example_gossip_codebox.cpp b/src/server/scripts/examples/example_gossip_codebox.cpp deleted file mode 100644 index e208722784a..00000000000 --- a/src/server/scripts/examples/example_gossip_codebox.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Example_Gossip_Codebox -SD%Complete: 100 -SDComment: Show a codebox in gossip option -SDCategory: Script Examples -EndScriptData */ - -#include "ScriptedPch.h" -#include - -enum eEnums -{ - SPELL_POLYMORPH = 12826, - SPELL_MARK_OF_THE_WILD = 26990, - - SAY_NOT_INTERESTED = -1999922, - SAY_WRONG = -1999923, - SAY_CORRECT = -1999924 -}; - -#define GOSSIP_ITEM_1 "A quiz: what's your name?" -#define GOSSIP_ITEM_2 "I'm not interested" - -//This function is called when the player opens the gossip menubool -bool GossipHello_example_gossip_codebox(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1, "", 0, true); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetGUID()); - - return true; -} - -//This function is called when the player clicks an option on the gossip menubool -bool GossipSelect_example_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - DoScriptText(SAY_NOT_INTERESTED, pCreature); - pPlayer->CLOSE_GOSSIP_MENU(); - } - - return true; -} - -bool GossipSelectWithCode_example_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode) -{ - if (uiSender == GOSSIP_SENDER_MAIN) - { - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - if (std::strcmp(sCode, pPlayer->GetName()) != 0) - { - DoScriptText(SAY_WRONG, pCreature); - pCreature->CastSpell(pPlayer, SPELL_POLYMORPH, true); - } - else - { - DoScriptText(SAY_CORRECT, pCreature); - pCreature->CastSpell(pPlayer, SPELL_MARK_OF_THE_WILD, true); - } - pPlayer->CLOSE_GOSSIP_MENU(); - - return true; - } - } - - return false; -} - -void AddSC_example_gossip_codebox() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "example_gossip_codebox"; - newscript->pGossipHello = &GossipHello_example_gossip_codebox; - newscript->pGossipSelect = &GossipSelect_example_gossip_codebox; - newscript->pGossipSelectWithCode = &GossipSelectWithCode_example_gossip_codebox; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/examples/example_misc.cpp b/src/server/scripts/examples/example_misc.cpp deleted file mode 100644 index 3c96cc0bae7..00000000000 --- a/src/server/scripts/examples/example_misc.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Example_Misc -SD%Complete: 100 -SDComment: Item, Areatrigger and other small code examples -SDCategory: Script Examples -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptMgr.h" - -enum eSay -{ - SAY_HI = -1999925 -}; - -bool AT_example_areatrigger(Player* pPlayer, const AreaTriggerEntry * /*pAt*/) -{ - DoScriptText(SAY_HI, pPlayer); - return true; -} - -extern void LoadDatabase(); -bool ItemUse_example_item(Player* /*pPlayer*/, Item* /*pItem*/, SpellCastTargets const& /*scTargets*/) -{ - sScriptMgr.LoadDatabase(); - return true; -} - -bool GOHello_example_go_teleporter(Player* pPlayer, GameObject* /*pGo*/) -{ - pPlayer->TeleportTo(0, 1807.07f, 336.105f, 70.3975f, 0.0f); - return false; -} - -void AddSC_example_misc() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "example_areatrigger"; - newscript->pAreaTrigger = &AT_example_areatrigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "example_item"; - newscript->pItemUse = &ItemUse_example_item; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "example_go_teleporter"; - newscript->pGOHello = &GOHello_example_go_teleporter; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/ashenvale.cpp b/src/server/scripts/kalimdor/ashenvale.cpp deleted file mode 100644 index 13e8f442048..00000000000 --- a/src/server/scripts/kalimdor/ashenvale.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Ashenvale -SD%Complete: 70 -SDComment: Quest support: 6544, 6482 -SDCategory: Ashenvale Forest -EndScriptData */ - -/* ContentData -npc_torek -npc_ruul_snowhoof -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*#### -# npc_torek -####*/ - -#define SAY_READY -1000106 -#define SAY_MOVE -1000107 -#define SAY_PREPARE -1000108 -#define SAY_WIN -1000109 -#define SAY_END -1000110 - -#define SPELL_REND 11977 -#define SPELL_THUNDERCLAP 8078 - -#define QUEST_TOREK_ASSULT 6544 - -#define ENTRY_SPLINTERTREE_RAIDER 12859 -#define ENTRY_DURIEL 12860 -#define ENTRY_SILVERWING_SENTINEL 12896 -#define ENTRY_SILVERWING_WARRIOR 12897 - -struct npc_torekAI : public npc_escortAI -{ - npc_torekAI(Creature *c) : npc_escortAI(c) {} - - uint32 Rend_Timer; - uint32 Thunderclap_Timer; - bool Completed; - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch (i) - { - case 1: - DoScriptText(SAY_MOVE, me, pPlayer); - break; - case 8: - DoScriptText(SAY_PREPARE, me, pPlayer); - break; - case 19: - //TODO: verify location and creatures amount. - me->SummonCreature(ENTRY_DURIEL,1776.73,-2049.06,109.83,1.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000); - me->SummonCreature(ENTRY_SILVERWING_SENTINEL,1774.64,-2049.41,109.83,1.40,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000); - me->SummonCreature(ENTRY_SILVERWING_WARRIOR,1778.73,-2049.50,109.83,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000); - break; - case 20: - DoScriptText(SAY_WIN, me, pPlayer); - Completed = true; - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_TOREK_ASSULT, me); - break; - case 21: - DoScriptText(SAY_END, me, pPlayer); - break; - } - } - - void Reset() - { - Rend_Timer = 5000; - Thunderclap_Timer = 8000; - Completed = false; - } - - void EnterCombat(Unit* /*who*/) - { - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (Rend_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REND); - Rend_Timer = 20000; - } else Rend_Timer -= diff; - - if (Thunderclap_Timer <= diff) - { - DoCast(me, SPELL_THUNDERCLAP); - Thunderclap_Timer = 30000; - } else Thunderclap_Timer -= diff; - } -}; - -bool QuestAccept_npc_torek(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_TOREK_ASSULT) - { - //TODO: find companions, make them follow Torek, at any time (possibly done by core/database in future?) - DoScriptText(SAY_READY, pCreature, pPlayer); - pCreature->setFaction(113); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_torekAI, pCreature->AI())) - pEscortAI->Start(true, true, pPlayer->GetGUID()); - } - - return true; -} - -CreatureAI* GetAI_npc_torek(Creature* pCreature) -{ - return new npc_torekAI(pCreature); -} - -/*#### -# npc_ruul_snowhoof -####*/ - -#define QUEST_FREEDOM_TO_RUUL 6482 -#define GO_CAGE 178147 - -struct npc_ruul_snowhoofAI : public npc_escortAI -{ - npc_ruul_snowhoofAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 0: { - me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 20); - if (Cage) - Cage->SetGoState(GO_STATE_ACTIVE); - break;} - case 13: - me->SummonCreature(3922, 3449.218018, -587.825073, 174.978867, 4.714445, TEMPSUMMON_DEAD_DESPAWN, 60000); - me->SummonCreature(3921, 3446.384521, -587.830872, 175.186279, 4.714445, TEMPSUMMON_DEAD_DESPAWN, 60000); - me->SummonCreature(3926, 3444.218994, -587.835327, 175.380600, 4.714445, TEMPSUMMON_DEAD_DESPAWN, 60000); - break; - case 19: - me->SummonCreature(3922, 3508.344482, -492.024261, 186.929031, 4.145029, TEMPSUMMON_DEAD_DESPAWN, 60000); - me->SummonCreature(3921, 3506.265625, -490.531006, 186.740128, 4.239277, TEMPSUMMON_DEAD_DESPAWN, 60000); - me->SummonCreature(3926, 3503.682373, -489.393799, 186.629684, 4.349232, TEMPSUMMON_DEAD_DESPAWN, 60000); - break; - - case 21:{ - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_FREEDOM_TO_RUUL, me); - - break; } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void Reset() - { - GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 20); - if (Cage) - Cage->SetGoState(GO_STATE_READY); - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - } -}; - -bool QuestAccept_npc_ruul_snowhoof(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_FREEDOM_TO_RUUL) - { - pCreature->setFaction(113); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_ruul_snowhoofAI, (pCreature->AI()))) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - } - return true; -} - -CreatureAI* GetAI_npc_ruul_snowhoofAI(Creature* pCreature) -{ - return new npc_ruul_snowhoofAI(pCreature); -} - -enum eEnums -{ - SAY_MUG_START1 = -1800054, - SAY_MUG_START2 = -1800055, - SAY_MUG_BRAZIER = -1800056, - SAY_MUG_BRAZIER_WAIT = -1800057, - SAY_MUG_ON_GUARD = -1800058, - SAY_MUG_REST = -1800059, - SAY_MUG_DONE = -1800060, - SAY_MUG_GRATITUDE = -1800061, - SAY_MUG_PATROL = -1800062, - SAY_MUG_RETURN = -1800063, - - QUEST_VORSHA = 6641, - - GO_NAGA_BRAZIER = 178247, - - NPC_WRATH_RIDER = 3713, - NPC_WRATH_SORCERESS = 3717, - NPC_WRATH_RAZORTAIL = 3712, - - NPC_WRATH_PRIESTESS = 3944, - NPC_WRATH_MYRMIDON = 3711, - NPC_WRATH_SEAWITCH = 3715, - - NPC_VORSHA = 12940, - NPC_MUGLASH = 12717 -}; - -static float m_afFirstNagaCoord[3][3]= -{ - {3603.504150, 1122.631104, 1.635}, // rider - {3589.293945, 1148.664063, 5.565}, // sorceress - {3609.925537, 1168.759521, -1.168} // razortail -}; - -static float m_afSecondNagaCoord[3][3]= -{ - {3609.925537, 1168.759521, -1.168}, // witch - {3645.652100, 1139.425415, 1.322}, // priest - {3583.602051, 1128.405762, 2.347} // myrmidon -}; - -static float m_fVorshaCoord[]={3633.056885, 1172.924072, -5.388}; - - -struct npc_muglashAI : public npc_escortAI -{ - npc_muglashAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - uint32 m_uiWaveId; - uint32 m_uiEventTimer; - bool m_bIsBrazierExtinguished; - - void JustSummoned(Creature* pSummoned) - { - pSummoned->AI()->AttackStart(me); - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - switch(i) - { - case 0: - if (pPlayer) - DoScriptText(SAY_MUG_START2, me, pPlayer); - break; - case 24: - if (pPlayer) - DoScriptText(SAY_MUG_BRAZIER, me, pPlayer); - - if (GameObject* pGo = GetClosestGameObjectWithEntry(me, GO_NAGA_BRAZIER, INTERACTION_DISTANCE*2)) - { - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - SetEscortPaused(true); - } - break; - case 25: - DoScriptText(SAY_MUG_GRATITUDE, me); - - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_VORSHA, me); - break; - case 26: - DoScriptText(SAY_MUG_PATROL, me); - break; - case 27: - DoScriptText(SAY_MUG_RETURN, me); - break; - } - } - - void Aggro(Unit* /*pWho*/) - { - if (HasEscortState(STATE_ESCORT_PAUSED)) - { - if (urand(0, 1)) - DoScriptText(SAY_MUG_ON_GUARD, me); - return; - } - } - - void Reset() - { - m_uiEventTimer = 10000; - m_uiWaveId = 0; - m_bIsBrazierExtinguished = false; - } - - void JustDied(Unit* /*pKiller*/) - { - Player* pPlayer = GetPlayerForEscort(); - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (pPlayer) - { - pPlayer->FailQuest(QUEST_VORSHA); - } - } - } - - void DoWaveSummon() - { - switch(m_uiWaveId) - { - case 1: - me->SummonCreature(NPC_WRATH_RIDER, m_afFirstNagaCoord[0][0], m_afFirstNagaCoord[0][1], m_afFirstNagaCoord[0][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - me->SummonCreature(NPC_WRATH_SORCERESS, m_afFirstNagaCoord[1][0], m_afFirstNagaCoord[1][1], m_afFirstNagaCoord[1][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - me->SummonCreature(NPC_WRATH_RAZORTAIL, m_afFirstNagaCoord[2][0], m_afFirstNagaCoord[2][1], m_afFirstNagaCoord[2][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - break; - case 2: - me->SummonCreature(NPC_WRATH_PRIESTESS, m_afSecondNagaCoord[0][0], m_afSecondNagaCoord[0][1], m_afSecondNagaCoord[0][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - me->SummonCreature(NPC_WRATH_MYRMIDON, m_afSecondNagaCoord[1][0], m_afSecondNagaCoord[1][1], m_afSecondNagaCoord[1][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - me->SummonCreature(NPC_WRATH_SEAWITCH, m_afSecondNagaCoord[2][0], m_afSecondNagaCoord[2][1], m_afSecondNagaCoord[2][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - break; - case 3: - me->SummonCreature(NPC_VORSHA, m_fVorshaCoord[0], m_fVorshaCoord[1], m_fVorshaCoord[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - break; - case 4: - SetEscortPaused(false); - DoScriptText(SAY_MUG_DONE, me); - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!me->getVictim()) - { - if (HasEscortState(STATE_ESCORT_PAUSED) && m_bIsBrazierExtinguished) - { - if (m_uiEventTimer < uiDiff) - { - ++m_uiWaveId; - DoWaveSummon(); - m_uiEventTimer = 10000; - } - else - m_uiEventTimer -= uiDiff; - } - return; - } - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_muglash(Creature* pCreature) -{ - return new npc_muglashAI(pCreature); -} - -bool QuestAccept_npc_muglash(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_VORSHA) - { - if (npc_muglashAI* pEscortAI = CAST_AI(npc_muglashAI, pCreature->AI())) - { - DoScriptText(SAY_MUG_START1, pCreature); - pCreature->setFaction(113); - - pEscortAI->Start(true, true, pPlayer->GetGUID()); - } - } - return true; -} - - -bool GOHello_go_naga_brazier(Player* /*pPlayer*/, GameObject* pGo) -{ - if (Creature* pCreature = GetClosestCreatureWithEntry(pGo, NPC_MUGLASH, INTERACTION_DISTANCE*2)) - { - if (npc_muglashAI* pEscortAI = CAST_AI(npc_muglashAI, pCreature->AI())) - { - DoScriptText(SAY_MUG_BRAZIER_WAIT, pCreature); - - pEscortAI->m_bIsBrazierExtinguished = true; - return false; - } - } - return true; -} - -void AddSC_ashenvale() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_torek"; - newscript->GetAI = &GetAI_npc_torek; - newscript->pQuestAccept = &QuestAccept_npc_torek; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ruul_snowhoof"; - newscript->GetAI = &GetAI_npc_ruul_snowhoofAI; - newscript->pQuestAccept = &QuestAccept_npc_ruul_snowhoof; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_muglash"; - newscript->GetAI = &GetAI_npc_muglash; - newscript->pQuestAccept = &QuestAccept_npc_muglash; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_naga_brazier"; - newscript->pGOHello = &GOHello_go_naga_brazier; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/azshara.cpp b/src/server/scripts/kalimdor/azshara.cpp deleted file mode 100644 index 937afe0ae5d..00000000000 --- a/src/server/scripts/kalimdor/azshara.cpp +++ /dev/null @@ -1,514 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Azshara -SD%Complete: 90 -SDComment: Quest support: 2744, 3141, 9364, 10994 -SDCategory: Azshara -EndScriptData */ - -/* ContentData -mobs_spitelashes -npc_loramus_thalipedes -mob_rizzle_sprysprocket -mob_depth_charge -EndContentData */ - -#include "ScriptedPch.h" -#include "World.h" -#include "WorldPacket.h" - -/*###### -## mobs_spitelashes -######*/ - -struct mobs_spitelashesAI : public ScriptedAI -{ - mobs_spitelashesAI(Creature *c) : ScriptedAI(c) {} - - uint32 morphtimer; - bool spellhit; - - void Reset() - { - morphtimer = 0; - spellhit = false; - } - - void EnterCombat(Unit * /*who*/) { } - - void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) - { - if (!spellhit && - Hitter->GetTypeId() == TYPEID_PLAYER && - CAST_PLR(Hitter)->GetQuestStatus(9364) == QUEST_STATUS_INCOMPLETE && - (Spellkind->Id == 118 || Spellkind->Id == 12824 || Spellkind->Id == 12825 || Spellkind->Id == 12826)) - { - spellhit=true; - DoCast(me, 29124); //become a sheep - } - } - - void UpdateAI(const uint32 diff) - { - // we mustn't remove the Creature in the same round in which we cast the summon spell, otherwise there will be no summons - if (spellhit && morphtimer >= 5000) - { - me->ForcedDespawn(); - return; - } - // walk 5 seconds before summoning - if (spellhit && morphtimer<5000) - { - morphtimer+=diff; - if (morphtimer >= 5000) - { - DoCast(me, 28406); //summon copies - DoCast(me, 6924); //visual explosion - } - } - if (!UpdateVictim()) - return; - - //TODO: add abilities for the different creatures - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_mobs_spitelashes(Creature* pCreature) -{ - return new mobs_spitelashesAI (pCreature); -} - -/*###### -## npc_loramus_thalipedes -######*/ - -#define GOSSIP_HELLO_LT1 "Can you help me?" -#define GOSSIP_HELLO_LT2 "Tell me your story" -#define GOSSIP_SELECT_LT1 "Please continue" -#define GOSSIP_SELECT_LT2 "I do not understand" -#define GOSSIP_SELECT_LT3 "Indeed" -#define GOSSIP_SELECT_LT4 "I will do this with or your help, Loramus" -#define GOSSIP_SELECT_LT5 "Yes" - -bool GossipHello_npc_loramus_thalipedes(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(2744) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_LT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - if (pPlayer->GetQuestStatus(3141) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_LT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_loramus_thalipedes(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(2744); - break; - - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); - pPlayer->SEND_GOSSIP_MENU(1813, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+21: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); - pPlayer->SEND_GOSSIP_MENU(1814, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+22: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23); - pPlayer->SEND_GOSSIP_MENU(1815, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+23: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24); - pPlayer->SEND_GOSSIP_MENU(1816, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+24: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_LT5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25); - pPlayer->SEND_GOSSIP_MENU(1817, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+25: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(3141); - break; - } - return true; -} - -/*#### -# mob_rizzle_sprysprocket -####*/ - -#define MOB_DEPTH_CHARGE 23025 -#define SPELL_RIZZLE_BLACKJACK 39865 -#define SPELL_RIZZLE_ESCAPE 39871 -#define SPELL_RIZZLE_FROST_GRENADE 40525 -#define SPELL_DEPTH_CHARGE_TRAP 38576 -#define SPELL_PERIODIC_DEPTH_CHARGE 39912 -#define SPELL_GIVE_SOUTHFURY_MOONSTONE 39886 - -#define SAY_RIZZLE_START -1000245 -#define SAY_RIZZLE_GRENADE -1000246 -#define SAY_RIZZLE_FINAL -1000247 - -#define GOSSIP_GET_MOONSTONE "Hand over the Southfury moonstone and I'll let you go." - -//next message must be send to player when Rizzle jump into river, not implemented -#define MSG_ESCAPE_NOTICE "Rizzle Sprysprocket takes the Southfury moonstone and escapes into the river. Follow her!" - -float WPs[58][4] = -{ -//pos_x pos_y pos_z orien -{3691.97, -3962.41, 35.9118, 3.67}, -{3675.02, -3960.49, 35.9118, 3.67}, -{3653.19, -3958.33, 33.9118, 3.59}, -{3621.12, -3958.51, 29.9118, 3.48}, -{3604.86, -3963, 29.9118, 3.48}, -{3569.94, -3970.25, 29.9118, 3.44}, -{3541.03, -3975.64, 29.9118, 3.41}, -{3510.84, -3978.71, 29.9118, 3.41}, -{3472.7, -3997.07, 29.9118, 3.35}, -{3439.15, -4014.55, 29.9118, 3.29}, -{3412.8, -4025.87, 29.9118, 3.25}, -{3384.95, -4038.04, 29.9118, 3.24}, -{3346.77, -4052.93, 29.9118, 3.22}, -{3299.56, -4071.59, 29.9118, 3.20}, -{3261.22, -4080.38, 30.9118, 3.19}, -{3220.68, -4083.09, 31.9118, 3.18}, -{3187.11, -4070.45, 33.9118, 3.16}, -{3162.78, -4062.75, 33.9118, 3.15}, -{3136.09, -4050.32, 33.9118, 3.07}, -{3119.47, -4044.51, 36.0363, 3.07}, -{3098.95, -4019.8, 33.9118, 3.07}, -{3073.07, -4011.42, 33.9118, 3.07}, -{3051.71, -3993.37, 33.9118, 3.02}, -{3027.52, -3978.6, 33.9118, 3.00}, -{3003.78, -3960.14, 33.9118, 2.98}, -{2977.99, -3941.98, 31.9118, 2.96}, -{2964.57, -3932.07, 30.9118, 2.96}, -{2947.9, -3921.31, 29.9118, 2.96}, -{2924.91, -3910.8, 29.9118, 2.94}, -{2903.04, -3896.42, 29.9118, 2.93}, -{2884.75, -3874.03, 29.9118, 2.90}, -{2868.19, -3851.48, 29.9118, 2.82}, -{2854.62, -3819.72, 29.9118, 2.80}, -{2825.53, -3790.4, 29.9118, 2.744}, -{2804.31, -3773.05, 29.9118, 2.71}, -{2769.78, -3763.57, 29.9118, 2.70}, -{2727.23, -3745.92, 30.9118, 2.69}, -{2680.12, -3737.49, 30.9118, 2.67}, -{2647.62, -3739.94, 30.9118, 2.66}, -{2616.6, -3745.75, 30.9118, 2.64}, -{2589.38, -3731.97, 30.9118, 2.61}, -{2562.94, -3722.35, 31.9118, 2.56}, -{2521.05, -3716.6, 31.9118, 2.55}, -{2485.26, -3706.67, 31.9118, 2.51}, -{2458.93, -3696.67, 31.9118, 2.51}, -{2432, -3692.03, 31.9118, 2.46}, -{2399.59, -3681.97, 31.9118, 2.45}, -{2357.75, -3666.6, 31.9118, 2.44}, -{2311.99, -3656.88, 31.9118, 2.94}, -{2263.41, -3649.55, 31.9118, 3.02}, -{2209.05, -3641.76, 31.9118, 2.99}, -{2164.83, -3637.64, 31.9118, 3.15}, -{2122.42, -3639, 31.9118, 3.21}, -{2075.73, -3643.59, 31.9118, 3.22}, -{2033.59, -3649.52, 31.9118, 3.42}, -{1985.22, -3662.99, 31.9118, 3.42}, -{1927.09, -3679.56, 33.9118, 3.42}, -{1873.57, -3695.32, 33.9118, 3.44} -}; - -struct mob_rizzle_sprysprocketAI : public ScriptedAI -{ - mob_rizzle_sprysprocketAI(Creature *c) : ScriptedAI(c) {} - - uint32 spellEscape_Timer; - uint32 Teleport_Timer; - uint32 Check_Timer; - uint32 Grenade_Timer; - uint32 Must_Die_Timer; - uint32 CurrWP; - - uint64 PlayerGUID; - - bool Must_Die; - bool Escape; - bool ContinueWP; - bool Reached; - - void Reset() - { - spellEscape_Timer = 1300; - Teleport_Timer = 3500; - Check_Timer = 10000; - Grenade_Timer = 30000; - Must_Die_Timer = 3000; - CurrWP = 0; - - PlayerGUID = 0; - - Must_Die = false; - Escape = false; - ContinueWP = false; - Reached = false; - } - - void UpdateAI(const uint32 diff) - { - if (Must_Die) - if (Must_Die_Timer <= diff) - { - me->ForcedDespawn(); - return; - } else Must_Die_Timer -= diff; - - if (!Escape) - { - if (!PlayerGUID) - return; - - if (spellEscape_Timer <= diff) - { - DoCast(me, SPELL_RIZZLE_ESCAPE, false); - spellEscape_Timer = 10000; - } else spellEscape_Timer -= diff; - - if (Teleport_Timer <= diff) - { - //temp solution - unit can't be teleported by core using spelleffect 5, only players - Map* pMap = me->GetMap(); - if (pMap) - { - pMap->CreatureRelocation(me, 3706.39, -3969.15, 35.9118, 0); - me->AI_SendMoveToPacket(3706.39, -3969.15, 35.9118, 0, 0, 0); - } - //begin swimming and summon depth charges - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - SendText(MSG_ESCAPE_NOTICE, pPlayer); - DoCast(me, SPELL_PERIODIC_DEPTH_CHARGE); - me->SetUnitMovementFlags(MOVEMENTFLAG_HOVER | MOVEMENTFLAG_SWIMMING); - me->SetSpeed(MOVE_RUN, 0.85f, true); - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP][0], WPs[CurrWP][1], WPs[CurrWP][2]); - Escape = true; - } else Teleport_Timer -= diff; - - return; - } - - if (ContinueWP) - { - me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP][0], WPs[CurrWP][1], WPs[CurrWP][2]); - ContinueWP = false; - } - - if (Grenade_Timer <= diff) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer) - { - DoScriptText(SAY_RIZZLE_GRENADE, me, pPlayer); - DoCast(pPlayer, SPELL_RIZZLE_FROST_GRENADE, true); - } - Grenade_Timer = 30000; - } else Grenade_Timer -= diff; - - if (Check_Timer <= diff) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (!pPlayer) - { - me->ForcedDespawn(); - return; - } - - if (me->IsWithinDist(pPlayer, 10) && me->GetPositionX() > pPlayer->GetPositionX() && !Reached) - { - DoScriptText(SAY_RIZZLE_FINAL, me); - me->SetUInt32Value(UNIT_NPC_FLAGS, 1); - me->setFaction(35); - me->GetMotionMaster()->MoveIdle(); - me->RemoveAurasDueToSpell(SPELL_PERIODIC_DEPTH_CHARGE); - Reached = true; - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - - } - - void SendText(const char *text, Player* pPlayer) - { - WorldPacket data(SMSG_SERVER_MESSAGE, 0); // guess size - data << text; - if (pPlayer) - pPlayer->GetSession()->SendPacket(&data); - } - - void AttackStart(Unit *who) - { - if (!who || PlayerGUID) - return; - - if (who->GetTypeId() == TYPEID_PLAYER && CAST_PLR(who)->GetQuestStatus(10994) == QUEST_STATUS_INCOMPLETE) - { - PlayerGUID = who->GetGUID(); - DoScriptText(SAY_RIZZLE_START, me); - DoCast(who, SPELL_RIZZLE_BLACKJACK, false); - return; - } - } - - void EnterCombat(Unit* /*who*/) {} - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 57) - { - me->ForcedDespawn(); - return; - } - - ++CurrWP; - ContinueWP = true; - } - -}; - -bool GossipHello_mob_rizzle_sprysprocket(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(10994) != QUEST_STATUS_INCOMPLETE) - return true; - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GET_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(10811, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_mob_rizzle_sprysprocket(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1 && pPlayer->GetQuestStatus(10994) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, SPELL_GIVE_SOUTHFURY_MOONSTONE, true); - CAST_AI(mob_rizzle_sprysprocketAI, pCreature->AI())->Must_Die_Timer = 3000; - CAST_AI(mob_rizzle_sprysprocketAI, pCreature->AI())->Must_Die = true; - } - return true; -} - -CreatureAI* GetAI_mob_rizzle_sprysprocket(Creature* pCreature) -{ - return new mob_rizzle_sprysprocketAI (pCreature); -} - -/*#### -# mob_depth_charge -####*/ - -struct mob_depth_chargeAI : public ScriptedAI -{ - mob_depth_chargeAI(Creature *c) : ScriptedAI(c) {} - - bool we_must_die; - uint32 must_die_timer; - - void Reset() - { - me->SetUnitMovementFlags(MOVEMENTFLAG_HOVER | MOVEMENTFLAG_SWIMMING); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - we_must_die = false; - must_die_timer = 1000; - } - - void UpdateAI(const uint32 diff) - { - if (we_must_die) - if (must_die_timer <= diff) - { - me->ForcedDespawn(); - } else must_die_timer -= diff; - return; - } - - void MoveInLineOfSight(Unit *who) - { - if (!who) - return; - - if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 5)) - { - DoCast(who, SPELL_DEPTH_CHARGE_TRAP); - we_must_die = true; - return; - } - } - - void AttackStart(Unit * /*who*/) - { - } - - void EnterCombat(Unit* /*who*/) - { - } -}; - -CreatureAI* GetAI_mob_depth_charge(Creature* pCreature) -{ - return new mob_depth_chargeAI (pCreature); -} - -void AddSC_azshara() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mobs_spitelashes"; - newscript->GetAI = &GetAI_mobs_spitelashes; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_loramus_thalipedes"; - newscript->pGossipHello = &GossipHello_npc_loramus_thalipedes; - newscript->pGossipSelect = &GossipSelect_npc_loramus_thalipedes; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_rizzle_sprysprocket"; - newscript->GetAI = &GetAI_mob_rizzle_sprysprocket; - newscript->pGossipHello = &GossipHello_mob_rizzle_sprysprocket; - newscript->pGossipSelect = &GossipSelect_mob_rizzle_sprysprocket; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_depth_charge"; - newscript->GetAI = &GetAI_mob_depth_charge; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/azuremyst_isle.cpp b/src/server/scripts/kalimdor/azuremyst_isle.cpp deleted file mode 100644 index d31eaa9e84b..00000000000 --- a/src/server/scripts/kalimdor/azuremyst_isle.cpp +++ /dev/null @@ -1,718 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Azuremyst_Isle -SD%Complete: 75 -SDComment: Quest support: 9283, 9537, 9582, 9554, 9531, 9303(special flight path, proper model for mount missing). Injured Draenei cosmetic only, 9582. -SDCategory: Azuremyst Isle -EndScriptData */ - -/* ContentData -npc_draenei_survivor -npc_engineer_spark_overgrind -npc_injured_draenei -npc_magwin -npc_geezle -mob_nestlewood_owlkin -go_ravager_cage -npc_death_ravager -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include - -/*###### -## npc_draenei_survivor -######*/ - -enum eEnums -{ - SAY_HEAL1 = -1000176, - SAY_HEAL2 = -1000177, - SAY_HEAL3 = -1000178, - SAY_HEAL4 = -1000179, - - SAY_HELP1 = -1000180, - SAY_HELP2 = -1000181, - SAY_HELP3 = -1000182, - SAY_HELP4 = -1000183, - - SPELL_IRRIDATION = 35046, - SPELL_STUNNED = 28630 -}; - -struct npc_draenei_survivorAI : public ScriptedAI -{ - npc_draenei_survivorAI(Creature *c) : ScriptedAI(c) {} - - uint64 pCaster; - - uint32 SayThanksTimer; - uint32 RunAwayTimer; - uint32 SayHelpTimer; - - bool CanSayHelp; - - void Reset() - { - pCaster = 0; - - SayThanksTimer = 0; - RunAwayTimer = 0; - SayHelpTimer = 10000; - - CanSayHelp = true; - - DoCast(me, SPELL_IRRIDATION, true); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - me->SetHealth(int(me->GetMaxHealth()*.1)); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (CanSayHelp && who->GetTypeId() == TYPEID_PLAYER && me->IsFriendlyTo(who) && me->IsWithinDistInMap(who, 25.0f)) - { - //Random switch between 4 texts - DoScriptText(RAND(SAY_HELP1, SAY_HELP2, SAY_HELP3, SAY_HELP4), me, who); - - SayHelpTimer = 20000; - CanSayHelp = false; - } - } - - void SpellHit(Unit *Caster, const SpellEntry *Spell) - { - if (Spell->SpellFamilyFlags[2] & 0x080000000) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoCast(me, SPELL_STUNNED, true); - - pCaster = Caster->GetGUID(); - - SayThanksTimer = 5000; - } - } - - void UpdateAI(const uint32 diff) - { - if (SayThanksTimer) - { - if (SayThanksTimer <= diff) - { - me->RemoveAurasDueToSpell(SPELL_IRRIDATION); - - if (Player* pPlayer = Unit::GetPlayer(pCaster)) - { - DoScriptText(RAND(SAY_HEAL1, SAY_HEAL2, SAY_HEAL3, SAY_HEAL4), me, pPlayer); - - pPlayer->TalkedToCreature(me->GetEntry(),me->GetGUID()); - } - - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, -4115.053711f, -13754.831055f, 73.508949f); - - RunAwayTimer = 10000; - SayThanksTimer = 0; - } else SayThanksTimer -= diff; - - return; - } - - if (RunAwayTimer) - { - if (RunAwayTimer <= diff) - me->ForcedDespawn(); - else - RunAwayTimer -= diff; - - return; - } - - if (SayHelpTimer <= diff) - { - CanSayHelp = true; - SayHelpTimer = 20000; - } else SayHelpTimer -= diff; - } -}; -CreatureAI* GetAI_npc_draenei_survivor(Creature* pCreature) -{ - return new npc_draenei_survivorAI (pCreature); -} - -/*###### -## npc_engineer_spark_overgrind -######*/ - -enum eOvergrind -{ - SAY_TEXT = -1000184, - SAY_EMOTE = -1000185, - ATTACK_YELL = -1000186, - - AREA_COVE = 3579, - AREA_ISLE = 3639, - QUEST_GNOMERCY = 9537, - FACTION_HOSTILE = 14, - SPELL_DYNAMITE = 7978 -}; - -#define GOSSIP_FIGHT "Traitor! You will be brought to justice!" - -struct npc_engineer_spark_overgrindAI : public ScriptedAI -{ - npc_engineer_spark_overgrindAI(Creature *c) : ScriptedAI(c) - { - NormFaction = c->getFaction(); - NpcFlags = c->GetUInt32Value(UNIT_NPC_FLAGS); - - if (c->GetAreaId() == AREA_COVE || c->GetAreaId() == AREA_ISLE) - IsTreeEvent = true; - } - - uint32 NormFaction; - uint32 NpcFlags; - - uint32 Dynamite_Timer; - uint32 Emote_Timer; - - bool IsTreeEvent; - - void Reset() - { - Dynamite_Timer = 8000; - Emote_Timer = 120000 + rand()%30000; - - me->setFaction(NormFaction); - me->SetUInt32Value(UNIT_NPC_FLAGS, NpcFlags); - - IsTreeEvent = false; - } - - void EnterCombat(Unit* who) - { - DoScriptText(ATTACK_YELL, me, who); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat() && !IsTreeEvent) - { - if (Emote_Timer <= diff) - { - DoScriptText(SAY_TEXT, me); - DoScriptText(SAY_EMOTE, me); - Emote_Timer = 120000 + rand()%30000; - } else Emote_Timer -= diff; - } - else if (IsTreeEvent) - return; - - if (!UpdateVictim()) - return; - - if (Dynamite_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DYNAMITE); - Dynamite_Timer = 8000; - } else Dynamite_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_engineer_spark_overgrind(Creature* pCreature) -{ - return new npc_engineer_spark_overgrindAI (pCreature); -} - -bool GossipHello_npc_engineer_spark_overgrind(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_GNOMERCY) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_engineer_spark_overgrind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(FACTION_HOSTILE); - CAST_AI(npc_engineer_spark_overgrindAI, pCreature->AI())->AttackStart(pPlayer); - } - return true; -} - -/*###### -## npc_injured_draenei -######*/ - -struct npc_injured_draeneiAI : public ScriptedAI -{ - npc_injured_draeneiAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - me->SetHealth(int(me->GetMaxHealth()*.15)); - switch (rand()%2) - { - case 0: me->SetStandState(UNIT_STAND_STATE_SIT); break; - case 1: me->SetStandState(UNIT_STAND_STATE_SLEEP); break; - } - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 /*diff*/) - { - } - -}; -CreatureAI* GetAI_npc_injured_draenei(Creature* pCreature) -{ - return new npc_injured_draeneiAI (pCreature); -} - -/*###### -## npc_magwin -######*/ - -enum eMagwin -{ - SAY_START = -1000111, - SAY_AGGRO = -1000112, - SAY_PROGRESS = -1000113, - SAY_END1 = -1000114, - SAY_END2 = -1000115, - EMOTE_HUG = -1000116, - - QUEST_A_CRY_FOR_SAY_HELP = 9528 -}; - -struct npc_magwinAI : public npc_escortAI -{ - npc_magwinAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 0: - DoScriptText(SAY_START, me, pPlayer); - break; - case 17: - DoScriptText(SAY_PROGRESS, me, pPlayer); - break; - case 28: - DoScriptText(SAY_END1, me, pPlayer); - break; - case 29: - DoScriptText(EMOTE_HUG, me, pPlayer); - DoScriptText(SAY_END2, me, pPlayer); - pPlayer->GroupEventHappens(QUEST_A_CRY_FOR_SAY_HELP,me); - break; - } - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me, who); - } - - void Reset() { } -}; - -bool QuestAccept_npc_magwin(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_A_CRY_FOR_SAY_HELP) - { - pCreature->setFaction(113); - if (npc_escortAI* pEscortAI = CAST_AI(npc_escortAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - } - return true; -} - -CreatureAI* GetAI_npc_magwinAI(Creature* pCreature) -{ - return new npc_magwinAI(pCreature); -} - -/*###### -## npc_geezle -######*/ - -enum eGeezle -{ - QUEST_TREES_COMPANY = 9531, - - SPELL_TREE_DISGUISE = 30298, - - GEEZLE_SAY_1 = -1100259, - SPARK_SAY_2 = -1100260, - SPARK_SAY_3 = -1100261, - GEEZLE_SAY_4 = -1100262, - SPARK_SAY_5 = -1100263, - SPARK_SAY_6 = -1100264, - GEEZLE_SAY_7 = -1100265, - - EMOTE_SPARK = -1100266, - - MOB_SPARK = 17243, - GO_NAGA_FLAG = 181694 -}; - -static float SparkPos[3] = {-5029.91, -11291.79, 8.096}; - -struct npc_geezleAI : public ScriptedAI -{ - npc_geezleAI(Creature *c) : ScriptedAI(c) {} - - uint64 SparkGUID; - - uint32 Step; - uint32 SayTimer; - - bool EventStarted; - - void Reset() - { - SparkGUID = 0; - Step = 0; - StartEvent(); - } - - void EnterCombat(Unit* /*who*/){} - - void StartEvent() - { - Step = 0; - EventStarted = true; - Creature* Spark = me->SummonCreature(MOB_SPARK, SparkPos[0], SparkPos[1], SparkPos[2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000); - if (Spark) - { - SparkGUID = Spark->GetGUID(); - Spark->setActive(true); - Spark->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - SayTimer = 8000; - } - - uint32 NextStep(uint32 Step) - { - Creature* Spark = Unit::GetCreature(*me, SparkGUID); - - switch(Step) - { - case 0: - if (Spark) - Spark->GetMotionMaster()->MovePoint(0, -5080.70, -11253.61, 0.56); - me->GetMotionMaster()->MovePoint(0, -5092.26, -11252, 0.71); - return 9000; // NPCs are walking up to fire - case 1: - DespawnNagaFlag(true); - DoScriptText(EMOTE_SPARK, Spark); - return 1000; - case 2: - DoScriptText(GEEZLE_SAY_1, me, Spark); - if (Spark) - { - Spark->SetInFront(me); - me->SetInFront(Spark); - } - return 5000; - case 3: DoScriptText(SPARK_SAY_2, Spark); return 7000; - case 4: DoScriptText(SPARK_SAY_3, Spark); return 8000; - case 5: DoScriptText(GEEZLE_SAY_4, me, Spark); return 8000; - case 6: DoScriptText(SPARK_SAY_5, Spark); return 9000; - case 7: DoScriptText(SPARK_SAY_6, Spark); return 8000; - case 8: DoScriptText(GEEZLE_SAY_7, me, Spark); return 2000; - case 9: - me->GetMotionMaster()->MoveTargetedHome(); - if (Spark) - Spark->GetMotionMaster()->MovePoint(0, SparkPos[0], SparkPos[1], SparkPos[2]); - CompleteQuest(); - return 9000; - case 10: - if (Spark) - Spark->DisappearAndDie(); - DespawnNagaFlag(false); - me->DisappearAndDie(); - default: return 99999999; - } - } - - // will complete Tree's company quest for all nearby players that are disguised as trees - void CompleteQuest() - { - float radius = 50.0f; - std::list players; - Trinity::AnyPlayerInObjectRangeCheck checker(me, radius); - Trinity::PlayerListSearcher searcher(me, players, checker); - me->VisitNearbyWorldObject(radius, searcher); - - for (std::list::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if ((*itr)->GetQuestStatus(QUEST_TREES_COMPANY) == QUEST_STATUS_INCOMPLETE - &&(*itr)->HasAura(SPELL_TREE_DISGUISE)) - { - (*itr)->KilledMonsterCredit(MOB_SPARK,0); - } - } - } - - void DespawnNagaFlag(bool despawn) - { - std::list FlagList; - me->GetGameObjectListWithEntryInGrid(FlagList,GO_NAGA_FLAG, 100.0f); - - if (!FlagList.empty()) - { - for (std::list::const_iterator itr = FlagList.begin(); itr != FlagList.end(); ++itr) - { - if (despawn) - { - (*itr)->SetLootState(GO_JUST_DEACTIVATED); - } - else - (*itr)->Respawn(); - } - } else error_log("SD2 ERROR: FlagList is empty!"); - } - - void UpdateAI(const uint32 diff) - { - if (SayTimer <= diff) - { - if (EventStarted) - { - SayTimer = NextStep(Step++); - } - } else SayTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_geezleAI(Creature* pCreature) -{ - return new npc_geezleAI(pCreature); -} - -/*###### -## mob_nestlewood_owlkin -######*/ - -enum eOwlkin -{ - SPELL_INOCULATE_OWLKIN = 29528, - ENTRY_OWLKIN = 16518, - ENTRY_OWLKIN_INOC = 16534 -}; - -struct npc_nestlewood_owlkinAI : public ScriptedAI -{ - npc_nestlewood_owlkinAI(Creature *c) : ScriptedAI(c) {} - - uint32 DespawnTimer; - - void Reset() - { - DespawnTimer = 0; - } - - void UpdateAI(const uint32 diff) - { - //timer gets adjusted by the triggered aura effect - if (DespawnTimer) - { - if (DespawnTimer <= diff) - { - //once we are able to, despawn us - me->ForcedDespawn(); - return; - } else DespawnTimer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_nestlewood_owlkinAI(Creature* pCreature) -{ - return new npc_nestlewood_owlkinAI (pCreature); -} - -bool EffectDummyCreature_npc_nestlewood_owlkin(Unit * /*pCaster*/, uint32 spellId, uint32 effIndex, Creature *pCreatureTarget) -{ - //always check spellid and effectindex - if (spellId == SPELL_INOCULATE_OWLKIN && effIndex == 0) - { - if (pCreatureTarget->GetEntry() != ENTRY_OWLKIN) - return true; - - pCreatureTarget->UpdateEntry(ENTRY_OWLKIN_INOC); - - //set despawn timer, since we want to remove Creature after a short time - CAST_AI(npc_nestlewood_owlkinAI, pCreatureTarget->AI())->DespawnTimer = 15000; - - //always return true when we are handling this spell and effect - return true; - } - return false; -} - -enum eRavegerCage -{ - NPC_DEATH_RAVAGER = 17556, - - SPELL_REND = 13443, - SPELL_ENRAGING_BITE = 30736, - - QUEST_STRENGTH_ONE = 9582 -}; - -bool go_ravager_cage(Player* pPlayer, GameObject* pGo) -{ - - if (pPlayer->GetQuestStatus(QUEST_STRENGTH_ONE) == QUEST_STATUS_INCOMPLETE) - { - if (Creature* ravager = pGo->FindNearestCreature(NPC_DEATH_RAVAGER, 5.0f, true)) - { - ravager->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - ravager->SetReactState(REACT_AGGRESSIVE); - ravager->AI()->AttackStart(pPlayer); - } - } - return true ; -} - -struct npc_death_ravagerAI : public ScriptedAI -{ - npc_death_ravagerAI(Creature *c) : ScriptedAI(c){} - - uint32 RendTimer; - uint32 EnragingBiteTimer; - - void Reset() - { - RendTimer = 30000; - EnragingBiteTimer = 20000; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (RendTimer <= diff) - { - DoCast(me->getVictim(), SPELL_REND); - RendTimer = 30000; - } - else RendTimer -= diff; - - if (EnragingBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ENRAGING_BITE); - EnragingBiteTimer = 15000; - } - else EnragingBiteTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_death_ravagerAI(Creature* pCreature) -{ - return new npc_death_ravagerAI(pCreature); -} - -void AddSC_azuremyst_isle() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_draenei_survivor"; - newscript->GetAI = &GetAI_npc_draenei_survivor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_engineer_spark_overgrind"; - newscript->GetAI = &GetAI_npc_engineer_spark_overgrind; - newscript->pGossipHello = &GossipHello_npc_engineer_spark_overgrind; - newscript->pGossipSelect = &GossipSelect_npc_engineer_spark_overgrind; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_injured_draenei"; - newscript->GetAI = &GetAI_npc_injured_draenei; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_magwin"; - newscript->GetAI = &GetAI_npc_magwinAI; - newscript->pQuestAccept = &QuestAccept_npc_magwin; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_geezle"; - newscript->GetAI = &GetAI_npc_geezleAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_nestlewood_owlkin"; - newscript->GetAI = &GetAI_npc_nestlewood_owlkinAI; - newscript->pEffectDummyCreature = &EffectDummyCreature_npc_nestlewood_owlkin; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="npc_death_ravager"; - newscript->GetAI = &GetAI_npc_death_ravagerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="go_ravager_cage"; - newscript->pGOHello = &go_ravager_cage; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.cpp b/src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.cpp deleted file mode 100644 index a3fd42a0fe7..00000000000 --- a/src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" -#include "ScriptedEscortAI.h" - -enum eSpells -{ - SPELL_BLESSING_OF_BLACKFATHOM = 8733, - SPELL_RAVAGE = 8391, - SPELL_FROST_NOVA = 865, - SPELL_FROST_BOLT_VOLLEY = 8398, - SPELL_TELEPORT_DARNASSUS = 9268 -}; - -#define GOSSIP_ITEM_MORRIDUNE "Please port me to Darnassus" - -const Position HomePosition = {-815.817,-145.299,-25.870, 0}; - -bool GoHello_blackfathom_altar(Player *pPlayer, GameObject* /*pGo*/) -{ - if (!pPlayer->HasAura(SPELL_BLESSING_OF_BLACKFATHOM)) - pPlayer->AddAura(SPELL_BLESSING_OF_BLACKFATHOM,pPlayer); - return true; -} - -bool GoHello_blackfathom_fire(Player * /*pPlayer*/, GameObject* pGo) -{ - ScriptedInstance *pInstance = pGo->GetInstanceData(); - - if (pInstance) - { - pGo->SetGoState(GO_STATE_ACTIVE); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pInstance->SetData(DATA_FIRE, pInstance->GetData(DATA_FIRE) + 1); - return true; - } - return false; -} - -struct npc_blackfathom_deeps_eventAI : public ScriptedAI -{ - npc_blackfathom_deeps_eventAI(Creature* pCreature) : ScriptedAI(pCreature) - { - if (pCreature->isSummon()) - { - pCreature->SetHomePosition(HomePosition); - AttackPlayer(); - } - - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiRavageTimer; - uint32 uiFrostNovaTimer; - uint32 uiFrostBoltVolleyTimer; - - bool bFlee; - - void Reset() - { - bFlee = false; - - uiRavageTimer = urand(5000,8000); - uiFrostNovaTimer = urand(9000,12000); - uiFrostBoltVolleyTimer = urand(2000,4000); - } - - void AttackPlayer() - { - Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - me->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(me); - me->AddThreat(pPlayer, 0.0f); - } - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - switch (me->GetEntry()) - { - case NPC_AKU_MAI_SNAPJAW: - { - if (uiRavageTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_RAVAGE); - uiRavageTimer = urand(9000,14000); - } else uiRavageTimer -= uiDiff; - break; - } - case NPC_MURKSHALLOW_SOFTSHELL: - case NPC_BARBED_CRUSTACEAN: - { - if (!bFlee && HealthBelowPct(15)) - { - bFlee = true; - me->DoFleeToGetAssistance(); - } - break; - } - case NPC_AKU_MAI_SERVANT: - { - if (uiFrostBoltVolleyTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget) - DoCast(pTarget, SPELL_FROST_BOLT_VOLLEY); - } - uiFrostBoltVolleyTimer = urand(5000,8000); - } else uiFrostBoltVolleyTimer -= uiDiff; - if (uiFrostNovaTimer <= uiDiff) - { - DoCastAOE(SPELL_FROST_NOVA,false); - uiFrostNovaTimer = urand(25000,30000); - } else uiFrostNovaTimer -= uiDiff; - break; - } - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (me->isSummon()) //we are not a normal spawn. - if (pInstance) - pInstance->SetData(DATA_EVENT, pInstance->GetData(DATA_EVENT) + 1); - } -}; - -CreatureAI* GetAI_npc_blackfathom_deeps_event(Creature* pCreature) -{ - return new npc_blackfathom_deeps_eventAI (pCreature); -} - -enum eMorridune -{ - SAY_MORRIDUNE_1 = -1048003, - SAY_MORRIDUNE_2 = -1048004 -}; - -struct npc_morriduneAI : public npc_escortAI -{ - npc_morriduneAI(Creature* pCreature) : npc_escortAI(pCreature) - { - DoScriptText(SAY_MORRIDUNE_1,pCreature); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - Start(false,false,NULL); - } - - void WaypointReached(uint32 uiPoint) - { - switch(uiPoint) - { - case 4: - SetEscortPaused(true); - me->SetOrientation(1.775791); - me->SendMovementFlagUpdate(); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - DoScriptText(SAY_MORRIDUNE_2,me); - break; - } - } -}; - -CreatureAI* GetAI_npc_morridune(Creature* pCreature) -{ - return new npc_morriduneAI (pCreature); -} - -bool GossipHello_npc_morridune(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MORRIDUNE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_morridune(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->TeleportTo(1,9952.239,2284.277,1341.394,1.595); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - return true; -} - -void AddSC_blackfathom_deeps() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "go_blackfathom_altar"; - newscript->pGOHello = &GoHello_blackfathom_altar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_blackfathom_fire"; - newscript->pGOHello = &GoHello_blackfathom_fire; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_blackfathom_deeps_event"; - newscript->GetAI = &GetAI_npc_blackfathom_deeps_event; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_morridune"; - newscript->GetAI = &GetAI_npc_morridune; - newscript->pGossipHello = &GossipHello_npc_morridune; - newscript->pGossipSelect = &GossipSelect_npc_morridune; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.h b/src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.h deleted file mode 100644 index e8bbab9f105..00000000000 --- a/src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BFD_H -#define DEF_BFD_H - -enum Data64 -{ - DATA_SHRINE1, - DATA_SHRINE2, - DATA_SHRINE3, - DATA_SHRINE4, - DATA_TWILIGHT_LORD_KELRIS, - DATA_SHRINE_OF_GELIHAST, - DATA_ALTAR_OF_THE_DEEPS, - DATA_MAINDOOR, -}; - -enum Data -{ - TYPE_GELIHAST, - TYPE_KELRIS, - TYPE_SHRINE, - TYPE_AKU_MAI, - DATA_FIRE, - DATA_EVENT -}; - -enum Creatures -{ - NPC_TWILIGHT_LORD_KELRIS = 4832, - NPC_LORGUS_JETT = 12902, - - NPC_AKU_MAI_SNAPJAW = 4825, - NPC_MURKSHALLOW_SOFTSHELL = 4977, - NPC_AKU_MAI_SERVANT = 4978, - NPC_BARBED_CRUSTACEAN = 4823, - - NPC_MORRIDUNE = 6729 -}; - -enum GameObjects -{ - GO_SHRINE_OF_GELIHAST = 103015, - GO_FIRE_OF_AKU_MAI_1 = 21118, - GO_FIRE_OF_AKU_MAI_2 = 21119, - GO_FIRE_OF_AKU_MAI_3 = 21120, - GO_FIRE_OF_AKU_MAI_4 = 21121, - GO_AKU_MAI_DOOR = 21117, - GO_ALTAR_OF_THE_DEEPS = 103016 -}; -#endif diff --git a/src/server/scripts/kalimdor/blackfathom_depths/boss_aku_mai.cpp b/src/server/scripts/kalimdor/blackfathom_depths/boss_aku_mai.cpp deleted file mode 100644 index a4b7a160be8..00000000000 --- a/src/server/scripts/kalimdor/blackfathom_depths/boss_aku_mai.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" - -enum Spells -{ - SPELL_POISON_CLOUD = 3815, - SPELL_FRENZIED_RAGE = 3490 -}; - -struct boss_aku_maiAI : public ScriptedAI -{ - boss_aku_maiAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiPoisonCloudTimer; - bool bIsEnraged; - - ScriptedInstance *pInstance; - - void Reset() - { - uiPoisonCloudTimer = urand(5000,9000); - bIsEnraged = false; - if (pInstance) - pInstance->SetData(TYPE_AKU_MAI, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(TYPE_AKU_MAI, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_AKU_MAI, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiPoisonCloudTimer < diff) - { - DoCastVictim(SPELL_POISON_CLOUD); - uiPoisonCloudTimer = urand(25000,50000); - } else uiPoisonCloudTimer -= diff; - - if (!bIsEnraged && HealthBelowPct(30)) - { - DoCast(me,SPELL_FRENZIED_RAGE); - bIsEnraged = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_aku_mai(Creature* pCreature) -{ - return new boss_aku_maiAI (pCreature); -} - -void AddSC_boss_aku_mai() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_aku_mai"; - newscript->GetAI = &GetAI_boss_aku_mai; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/blackfathom_depths/boss_gelihast.cpp b/src/server/scripts/kalimdor/blackfathom_depths/boss_gelihast.cpp deleted file mode 100644 index 374a526f098..00000000000 --- a/src/server/scripts/kalimdor/blackfathom_depths/boss_gelihast.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" - -enum Spells -{ - SPELL_NET = 6533 -}; - -struct boss_gelihastAI : public ScriptedAI -{ - boss_gelihastAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiNetTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiNetTimer = urand(2000,4000); - if (pInstance) - pInstance->SetData(TYPE_GELIHAST, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(TYPE_GELIHAST, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_GELIHAST, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiNetTimer < diff) - { - DoCastVictim(SPELL_NET); - uiNetTimer = urand(4000,7000); - } else uiNetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_gelihast(Creature* pCreature) -{ - return new boss_gelihastAI (pCreature); -} - -void AddSC_boss_gelihast() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_gelihast"; - newscript->GetAI = &GetAI_boss_gelihast; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/blackfathom_depths/boss_kelris.cpp b/src/server/scripts/kalimdor/blackfathom_depths/boss_kelris.cpp deleted file mode 100644 index bd7e1014d1a..00000000000 --- a/src/server/scripts/kalimdor/blackfathom_depths/boss_kelris.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" - -enum Spells -{ - SPELL_MIND_BLAST = 15587, - SPELL_SLEEP = 8399, -}; - -//Id's from ACID -enum Yells -{ - SAY_AGGRO = -1048002, - SAY_SLEEP = -1048001, - SAY_DEATH = -1048000 -}; - -struct boss_kelrisAI : public ScriptedAI -{ - boss_kelrisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiMindBlastTimer; - uint32 uiSleepTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiMindBlastTimer = urand(2000,5000); - uiSleepTimer = urand(9000,12000); - if (pInstance) - pInstance->SetData(TYPE_KELRIS, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(TYPE_KELRIS, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - pInstance->SetData(TYPE_KELRIS, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiMindBlastTimer < diff) - { - DoCastVictim(SPELL_MIND_BLAST); - uiMindBlastTimer = urand(7000,9000); - } else uiMindBlastTimer -= diff; - - if (uiSleepTimer < diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(SAY_SLEEP, me); - DoCast(pTarget, SPELL_SLEEP); - } - uiSleepTimer = urand(15000,20000); - } else uiSleepTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kelris(Creature* pCreature) -{ - return new boss_kelrisAI (pCreature); -} - -void AddSC_boss_kelris() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_kelris"; - newscript->GetAI = &GetAI_boss_kelris; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp b/src/server/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp deleted file mode 100644 index a485684e699..00000000000 --- a/src/server/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Blackfathom_Deeps -SD%Complete: 50 -SDComment: -SDCategory: Blackfathom Deeps -EndScriptData */ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" - -#define MAX_ENCOUNTER 4 - -/* Encounter 0 = Gelihast - Encounter 1 = Twilight Lord Kelris - Encounter 2 = Shrine event - Encounter 3 = Aku'Mai - */ - -const Position LorgusPosition[4] = -{ - { -458.500610, -38.343079, -33.474445 }, - { -469.423615, -88.400513, -39.265102 }, - { -622.354980, -10.350100, -22.777000 }, - { -759.640564, 16.658913, -29.159529 } -}; - -const Position SpawnsLocation[] = -{ - {-775.431, -153.853, -25.871, 3.207}, - {-775.404, -174.132, -25.871, 3.185}, - {-862.430, -154.937, -25.871, 0.060}, - {-862.193, -174.251, -25.871, 6.182}, - {-863.895, -458.899, -33.891, 5.637} -}; - -struct instance_blackfathom_deeps : public ScriptedInstance -{ - instance_blackfathom_deeps(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 m_uiTwilightLordKelrisGUID; - uint64 m_uiShrine1GUID; - uint64 m_uiShrine2GUID; - uint64 m_uiShrine3GUID; - uint64 m_uiShrine4GUID; - uint64 m_uiShrineOfGelihastGUID; - uint64 m_uiAltarOfTheDeepsGUID; - uint64 m_uiMainDoorGUID; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - uint8 m_uiCountFires; - uint8 uiDeathTimes; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiTwilightLordKelrisGUID = 0; - m_uiShrine1GUID = 0; - m_uiShrine2GUID = 0; - m_uiShrine3GUID = 0; - m_uiShrine4GUID = 0; - m_uiShrineOfGelihastGUID = 0; - m_uiAltarOfTheDeepsGUID = 0; - m_uiMainDoorGUID = 0; - m_uiCountFires = 0; - uiDeathTimes = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case NPC_TWILIGHT_LORD_KELRIS: - m_uiTwilightLordKelrisGUID = pCreature->GetGUID(); - break; - case NPC_LORGUS_JETT: - pCreature->SetHomePosition(LorgusPosition[urand(0,3)]); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_FIRE_OF_AKU_MAI_1: - m_uiShrine1GUID = pGo->GetGUID(); - break; - case GO_FIRE_OF_AKU_MAI_2: - m_uiShrine2GUID = pGo->GetGUID(); - break; - case GO_FIRE_OF_AKU_MAI_3: - m_uiShrine3GUID = pGo->GetGUID(); - break; - case GO_FIRE_OF_AKU_MAI_4: - m_uiShrine4GUID = pGo->GetGUID(); - break; - case GO_SHRINE_OF_GELIHAST: - m_uiShrineOfGelihastGUID = pGo->GetGUID(); - if (m_auiEncounter[0] != DONE) - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case GO_ALTAR_OF_THE_DEEPS: - m_uiAltarOfTheDeepsGUID = pGo->GetGUID(); - if (m_auiEncounter[3] != DONE) - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case GO_AKU_MAI_DOOR: - if (m_auiEncounter[2] == DONE) - HandleGameObject(NULL,true,pGo); - m_uiMainDoorGUID = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_GELIHAST: - m_auiEncounter[0] = uiData; - if (uiData == DONE) - if (GameObject *pGo = instance->GetGameObject(m_uiShrineOfGelihastGUID)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case TYPE_AKU_MAI: - m_auiEncounter[3] = uiData; - if (uiData == DONE) - if (GameObject *pGo = instance->GetGameObject(m_uiAltarOfTheDeepsGUID)) - { - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGo->SummonCreature(NPC_MORRIDUNE,SpawnsLocation[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - break; - case DATA_FIRE: - m_uiCountFires = uiData; - switch (m_uiCountFires) - { - case 1: - if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) - { - pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - break; - case 2: - if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) - { - for (uint8 i = 0; i < 2; ++i) - { - pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - } - break; - case 3: - if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) - { - pGO->SummonCreature(NPC_AKU_MAI_SERVANT, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_AKU_MAI_SERVANT, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - break; - case 4: - if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) - { - pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - break; - } - break; - case DATA_EVENT: - uiDeathTimes = uiData; - if (uiDeathTimes == 18) - HandleGameObject(m_uiMainDoorGUID,true); - break; - } - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case TYPE_GELIHAST: - return m_auiEncounter[0]; - case TYPE_KELRIS: - return m_auiEncounter[1]; - case TYPE_SHRINE: - return m_auiEncounter[2]; - case TYPE_AKU_MAI: - return m_auiEncounter[3]; - case DATA_FIRE: - return m_uiCountFires; - case DATA_EVENT: - return uiDeathTimes; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_TWILIGHT_LORD_KELRIS: - return m_uiTwilightLordKelrisGUID; - case DATA_SHRINE1: - return m_uiShrine1GUID; - case DATA_SHRINE2: - return m_uiShrine2GUID; - case DATA_SHRINE3: - return m_uiShrine3GUID; - case DATA_SHRINE4: - return m_uiShrine4GUID; - case DATA_SHRINE_OF_GELIHAST: - return m_uiShrineOfGelihastGUID; - case DATA_MAINDOOR: - return m_uiMainDoorGUID; - } - - return 0; - } -}; - -InstanceData* GetInstanceData_instance_blackfathom_deeps(Map* pMap) -{ - return new instance_blackfathom_deeps(pMap); -} - -void AddSC_instance_blackfathom_deeps() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blackfathom_deeps"; - newscript->GetInstanceData = &GetInstanceData_instance_blackfathom_deeps; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/bloodmyst_isle.cpp b/src/server/scripts/kalimdor/bloodmyst_isle.cpp deleted file mode 100644 index 108d03b8976..00000000000 --- a/src/server/scripts/kalimdor/bloodmyst_isle.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Bloodmyst_Isle -SD%Complete: 80 -SDComment: Quest support: 9670, 9756(gossip items text needed). -SDCategory: Bloodmyst Isle -EndScriptData */ - -/* ContentData -mob_webbed_creature -npc_captured_sunhawk_agent -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## mob_webbed_creature -######*/ - -//possible creatures to be spawned -const uint32 possibleSpawns[32] = {17322, 17661, 17496, 17522, 17340, 17352, 17333, 17524, 17654, 17348, 17339, 17345, 17359, 17353, 17336, 17550, 17330, 17701, 17321, 17680, 17325, 17320, 17683, 17342, 17715, 17334, 17341, 17338, 17337, 17346, 17344, 17327}; - -struct mob_webbed_creatureAI : public ScriptedAI -{ - mob_webbed_creatureAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - } - - void EnterCombat(Unit* /*who*/) - { - } - - void JustDied(Unit* Killer) - { - uint32 spawnCreatureID = 0; - - switch (urand(0,2)) - { - case 0: - spawnCreatureID = 17681; - if (Killer->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(Killer)->KilledMonsterCredit(spawnCreatureID, me->GetGUID()); - break; - case 1: - case 2: - spawnCreatureID = possibleSpawns[urand(0,30)]; - break; - } - - if (spawnCreatureID) - me->SummonCreature(spawnCreatureID, 0.0f, 0.0f, 0.0f, me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - } -}; -CreatureAI* GetAI_mob_webbed_creature(Creature* pCreature) -{ - return new mob_webbed_creatureAI (pCreature); -} - -/*###### -## npc_captured_sunhawk_agent -######*/ - -#define C_SUNHAWK_TRIGGER 17974 - -#define GOSSIP_HELLO_CSA "[PH] " -#define GOSSIP_SELECT_CSA1 "[PH] " -#define GOSSIP_SELECT_CSA2 "[PH] " -#define GOSSIP_SELECT_CSA3 "[PH] " -#define GOSSIP_SELECT_CSA4 "[PH] " -#define GOSSIP_SELECT_CSA5 "[PH] " - -bool GossipHello_npc_captured_sunhawk_agent(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->HasAura(31609) && pPlayer->GetQuestStatus(9756) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_CSA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(9136, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(9134, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_captured_sunhawk_agent(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(9137, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(9138, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(9139, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(9140, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_CSA5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(9141, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->TalkedToCreature(C_SUNHAWK_TRIGGER, pCreature->GetGUID()); - break; - } - return true; -} - -void AddSC_bloodmyst_isle() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_webbed_creature"; - newscript->GetAI = &GetAI_mob_webbed_creature; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_captured_sunhawk_agent"; - newscript->pGossipHello = &GossipHello_npc_captured_sunhawk_agent; - newscript->pGossipSelect = &GossipSelect_npc_captured_sunhawk_agent; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/boss_azuregos.cpp b/src/server/scripts/kalimdor/boss_azuregos.cpp deleted file mode 100644 index 8aeedfa199e..00000000000 --- a/src/server/scripts/kalimdor/boss_azuregos.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Azuregos -SD%Complete: 90 -SDComment: Teleport not included, spell reflect not effecting dots (Core problem) -SDCategory: Azshara -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_TELEPORT -1000100 - -#define SPELL_MARKOFFROST 23182 -#define SPELL_MANASTORM 21097 -#define SPELL_CHILL 21098 -#define SPELL_FROSTBREATH 21099 -#define SPELL_REFLECT 22067 -#define SPELL_CLEAVE 8255 //Perhaps not right ID -#define SPELL_ENRAGE 23537 - -struct boss_azuregosAI : public ScriptedAI -{ - boss_azuregosAI(Creature *c) : ScriptedAI(c) {} - - uint32 MarkOfFrost_Timer; - uint32 ManaStorm_Timer; - uint32 Chill_Timer; - uint32 Breath_Timer; - uint32 Teleport_Timer; - uint32 Reflect_Timer; - uint32 Cleave_Timer; - uint32 Enrage_Timer; - bool Enraged; - - void Reset() - { - MarkOfFrost_Timer = 35000; - ManaStorm_Timer = 5000 + rand()%12000; - Chill_Timer = 10000 + rand()%20000; - Breath_Timer = 2000 + rand()%6000; - Teleport_Timer = 30000; - Reflect_Timer = 15000 + rand()%15000; - Cleave_Timer = 7000; - Enrage_Timer = 0; - Enraged = false; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Teleport_Timer <= diff) - { - DoScriptText(SAY_TELEPORT, me); - std::list& m_threatlist = me->getThreatManager().getThreatList(); - std::list::const_iterator i = m_threatlist.begin(); - for (i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+3, pUnit->GetOrientation()); - } - } - - DoResetThreat(); - Teleport_Timer = 30000; - } else Teleport_Timer -= diff; - - // //MarkOfFrost_Timer - // if (MarkOfFrost_Timer <= diff) - // { - // DoCast(me->getVictim(), SPELL_MARKOFFROST); - // MarkOfFrost_Timer = 25000; - // } else MarkOfFrost_Timer -= diff; - - //Chill_Timer - if (Chill_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CHILL); - Chill_Timer = 13000 + rand()%12000; - } else Chill_Timer -= diff; - - //Breath_Timer - if (Breath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBREATH); - Breath_Timer = 10000 + rand()%5000; - } else Breath_Timer -= diff; - - //ManaStorm_Timer - if (ManaStorm_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_MANASTORM); - ManaStorm_Timer = 7500 + rand()%5000; - } else ManaStorm_Timer -= diff; - - //Reflect_Timer - if (Reflect_Timer <= diff) - { - DoCast(me, SPELL_REFLECT); - Reflect_Timer = 20000 + rand()%15000; - } else Reflect_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //Enrage_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 26 && !Enraged) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_azuregos(Creature* pCreature) -{ - return new boss_azuregosAI (pCreature); -} - -void AddSC_boss_azuregos() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_azuregos"; - newscript->GetAI = &GetAI_boss_azuregos; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp b/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp deleted file mode 100644 index 287d3cf8e9b..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -/* Script Data Start -SDName: Boss epoch -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro, consecutive attacks to a random target durin time wrap, adjust timers -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CURSE_OF_EXERTION = 52772, - SPELL_TIME_WARP = 52766, //Time slows down, reducing attack, casting and movement speed by 70% for 6 sec. - SPELL_TIME_STOP = 58848, //Stops time in a 50 yard sphere for 2 sec. - SPELL_WOUNDING_STRIKE = 52771, //Used only on the tank - H_SPELL_WOUNDING_STRIKE = 58830 -}; - -enum Yells -{ - SAY_INTRO = -1595000, //"Prince Arthas Menethil, on this day, a powerful darkness has taken hold of your soul. The death you are destined to visit upon others will this day be your own." - SAY_AGGRO = -1595001, //"We'll see about that, young prince." - SAY_TIME_WARP_1 = -1595002, //"Tick tock, tick tock..." - SAY_TIME_WARP_2 = -1595003, //"Not quick enough!" - SAY_TIME_WARP_3 = -1595004, //"Let's get this over with. " - SAY_SLAY_1 = -1595005, //"There is no future for you." - SAY_SLAY_2 = -1595006, //"This is the hour of our greatest triumph!" - SAY_SLAY_3 = -1595007, //"You were destined to fail. " - SAY_DEATH = -1595008 //"*gurgles*" -}; - -struct boss_epochAI : public ScriptedAI -{ - boss_epochAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint8 uiStep; - - uint32 uiStepTimer; - uint32 uiWoundingStrikeTimer; - uint32 uiTimeWarpTimer; - uint32 uiTimeStopTimer; - uint32 uiCurseOfExertionTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiStep = 1; - uiStepTimer = 26000; - uiCurseOfExertionTimer = 9300; - uiTimeWarpTimer = 25300; - uiTimeStopTimer = 21300; - uiWoundingStrikeTimer = 5300; - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiCurseOfExertionTimer < diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CURSE_OF_EXERTION); - uiCurseOfExertionTimer = 9300; - } else uiCurseOfExertionTimer -= diff; - - if (uiWoundingStrikeTimer < diff) - { - DoCastVictim(SPELL_WOUNDING_STRIKE); - uiWoundingStrikeTimer = 5300; - } else uiWoundingStrikeTimer -= diff; - - if (uiTimeStopTimer < diff) - { - DoCastAOE(SPELL_TIME_STOP); - uiTimeStopTimer = 21300; - } else uiTimeStopTimer -= diff; - - if (uiTimeWarpTimer < diff) - { - DoScriptText(RAND(SAY_TIME_WARP_1,SAY_TIME_WARP_2,SAY_TIME_WARP_3), me); - DoCastAOE(SPELL_TIME_WARP); - uiTimeWarpTimer = 25300; - } else uiTimeWarpTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_epoch(Creature* pCreature) -{ - return new boss_epochAI (pCreature); -} - -void AddSC_boss_epoch() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_epoch"; - newscript->GetAI = &GetAI_boss_epoch; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp b/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp deleted file mode 100644 index 12cdf00f2a5..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CORRUPTING_BLIGHT = 60588, - SPELL_VOID_STRIKE = 60590 -}; - -enum Yells -{ - SAY_AGGRO = -1595045, - SAY_FAIL = -1595046, - SAY_DEATH = -1595047 -}; - - -struct boss_infinite_corruptorAI : public ScriptedAI -{ - boss_infinite_corruptorAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, DONE); - } -}; - -CreatureAI* GetAI_boss_infinite_corruptor(Creature* pCreature) -{ - return new boss_infinite_corruptorAI(pCreature); -} - -void AddSC_boss_infinite_corruptor() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_infinite_corruptor"; - newscript->GetAI = &GetAI_boss_infinite_corruptor; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp b/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp deleted file mode 100644 index a39f3289a5a..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss mal_ganis -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro & outro -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_mal_ganis' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CARRION_SWARM = 52720, //A cresting wave of chaotic magic splashes over enemies in front of the caster, dealing 3230 to 3570 Shadow damage and 380 to 420 Shadow damage every 3 sec. for 15 sec. - H_SPELL_CARRION_SWARM = 58852, - SPELL_MIND_BLAST = 52722, //Inflicts 4163 to 4837 Shadow damage to an enemy. - H_SPELL_MIND_BLAST = 58850, - SPELL_SLEEP = 52721, //Puts an enemy to sleep for up to 10 sec. Any damage caused will awaken the target. - H_SPELL_SLEEP = 58849, - SPELL_VAMPIRIC_TOUCH = 52723 //Heals the caster for half the damage dealt by a melee attack. -}; - -enum Yells -{ - SAY_INTRO_1 = -1595009, - SAY_INTRO_2 = -1595010, - SAY_AGGRO = -1595011, - SAY_KILL_1 = -1595012, - SAY_KILL_2 = -1595013, - SAY_KILL_3 = -1595014, - SAY_SLAY_1 = -1595015, - SAY_SLAY_2 = -1595016, - SAY_SLAY_3 = -1595017, - SAY_SLAY_4 = -1595018, - SAY_SLEEP_1 = -1595019, - SAY_SLEEP_2 = -1595020, - SAY_30HEALTH = -1595021, - SAY_15HEALTH = -1595022, - SAY_ESCAPE_SPEECH_1 = -1595023, - SAY_ESCAPE_SPEECH_2 = -1595024, - SAY_OUTRO = -1595025, -}; - -enum CombatPhases -{ - COMBAT, - OUTRO -}; - -struct boss_mal_ganisAI : public ScriptedAI -{ - boss_mal_ganisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiCarrionSwarmTimer; - uint32 uiMindBlastTimer; - uint32 uiVampiricTouchTimer; - uint32 uiSleepTimer; - - uint8 uiOutroStep; - uint32 uiOutroTimer; - - bool bYelled; - bool bYelled2; - - CombatPhases Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - bYelled = false; - bYelled2 = false; - Phase = COMBAT; - uiCarrionSwarmTimer = 6000; - uiMindBlastTimer = 11000; - uiVampiricTouchTimer = urand(10000,15000); - uiSleepTimer = urand(15000,20000); - uiOutroTimer = 1000; - - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, IN_PROGRESS); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = me->GetHealth()-1; - } - - void UpdateAI(const uint32 diff) - { - switch(Phase) - { - case COMBAT: - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bYelled && HealthBelowPct(30)) - { - DoScriptText(SAY_30HEALTH, me); - bYelled = true; - } - - if (!bYelled2 && HealthBelowPct(15)) - { - DoScriptText(SAY_15HEALTH, me); - bYelled2 = true; - } - - if (HealthBelowPct(1)) - { - //Handle Escape Event: Don't forget to add Player::RewardPlayerAndGroupAtEvent - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - uiOutroStep = 1; - Phase = OUTRO; - return; - } - - if (Creature* pArthas = me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0)) - if (pArthas->isDead()) - { - EnterEvadeMode(); - me->DisappearAndDie(); - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, FAIL); - } - - if (uiCarrionSwarmTimer < diff) - { - DoCastVictim(SPELL_CARRION_SWARM); - uiCarrionSwarmTimer = 7000; - } else uiCarrionSwarmTimer -= diff; - - if (uiMindBlastTimer < diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_MIND_BLAST); - uiMindBlastTimer = 6000; - } else uiMindBlastTimer -= diff; - - if (uiVampiricTouchTimer < diff) - { - DoCast(me, SPELL_VAMPIRIC_TOUCH); - uiVampiricTouchTimer = 32000; - } else uiVampiricTouchTimer -= diff; - - if (uiSleepTimer < diff) - { - DoScriptText(RAND(SAY_SLEEP_1,SAY_SLEEP_2), me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SLEEP); - uiSleepTimer = urand(15000,20000); - } else uiSleepTimer -= diff; - - DoMeleeAttackIfReady(); - break; - case OUTRO: - if (uiOutroTimer < diff) - { - switch(uiOutroStep) - { - case 1: - DoScriptText(SAY_ESCAPE_SPEECH_1, me); - me->GetMotionMaster()->MoveTargetedHome(); - ++uiOutroStep; - uiOutroTimer = 8000; - break; - case 2: - me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0); - me->HandleEmoteCommand(29); - DoScriptText(SAY_ESCAPE_SPEECH_2, me); - ++uiOutroStep; - uiOutroTimer = 9000; - break; - case 3: - DoScriptText(SAY_OUTRO, me); - ++uiOutroStep; - uiOutroTimer = 16000; - break; - case 4: - me->HandleEmoteCommand(33); - ++uiOutroStep; - uiOutroTimer = 500; - break; - case 5: - me->SetVisibility(VISIBILITY_OFF); - me->Kill(me); - break; - - } - } else uiOutroTimer -= diff; - break; - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_MAL_GANIS_EVENT, DONE); - - // give achievement credit to players. criteria use spell 58630 which doesn't exist. - if (pInstance) - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 58630); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } -}; - -CreatureAI* GetAI_boss_mal_ganis(Creature* pCreature) -{ - return new boss_mal_ganisAI (pCreature); -} - -void AddSC_boss_mal_ganis() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_mal_ganis"; - newscript->GetAI = &GetAI_boss_mal_ganis; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp b/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp deleted file mode 100644 index eba9733c745..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss meathook -SDAuthor: Tartalo -SD%Complete: 100 -SDComment: It may need timer adjustment -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CONSTRICTING_CHAINS = 52696, //Encases the targets in chains, dealing 1800 Physical damage every 1 sec. and stunning the target for 5 sec. - H_SPELL_CONSTRICTING_CHAINS = 58823, - SPELL_DISEASE_EXPULSION = 52666, //Meathook belches out a cloud of disease, dealing 1710 to 1890 Nature damage and interrupting the spell casting of nearby enemy targets for 4 sec. - H_SPELL_DISEASE_EXPULSION = 58824, - SPELL_FRENZY = 58841 //Increases the caster's Physical damage by 10% for 30 sec. -}; - -enum Yells -{ - SAY_AGGRO = -1595026, - SAY_SLAY_1 = -1595027, - SAY_SLAY_2 = -1595028, - SAY_SLAY_3 = -1595029, - SAY_SPAWN = -1595030, - SAY_DEATH = -1595031 -}; - -struct boss_meathookAI : public ScriptedAI -{ - boss_meathookAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - DoScriptText(SAY_SPAWN,me); - } - - uint32 uiChainTimer; - uint32 uiDiseaseTimer; - uint32 uiFrenzyTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiChainTimer = urand(12000,17000); //seen on video 13, 17, 15, 12, 16 - uiDiseaseTimer = urand(2000,4000); //approx 3s - uiFrenzyTimer = urand(21000,26000); //made it up - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiDiseaseTimer <= diff) - { - DoCastAOE(SPELL_DISEASE_EXPULSION); - uiDiseaseTimer = urand(1500,4000); - } else uiDiseaseTimer -= diff; - - if (uiFrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - uiFrenzyTimer = urand(21000,26000); - } else uiFrenzyTimer -= diff; - - if (uiChainTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CONSTRICTING_CHAINS); //anyone but the tank - uiChainTimer = urand(2000,4000); - } else uiChainTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_meathook(Creature* pCreature) -{ - return new boss_meathookAI (pCreature); -} - -void AddSC_boss_meathook() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_meathook"; - newscript->GetAI = &GetAI_boss_meathook; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp b/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp deleted file mode 100644 index da1c8098517..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss salramm -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_salramm' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CURSE_OF_TWISTED_FLESH = 58845, - SPELL_EXPLODE_GHOUL = 52480, - H_SPELL_EXPLODE_GHOUL = 58825, - SPELL_SHADOW_BOLT = 57725, - H_SPELL_SHADOW_BOLT = 58828, - SPELL_STEAL_FLESH = 52708, - SPELL_SUMMON_GHOULS = 52451 -}; - -enum Yells -{ - SAY_AGGRO = -1595032, - SAY_SPAWN = -1595033, - SAY_SLAY_1 = -1595034, - SAY_SLAY_2 = -1595035, - SAY_SLAY_3 = -1595036, - SAY_DEATH = -1595037, - SAY_EXPLODE_GHOUL_1 = -1595038, - SAY_EXPLODE_GHOUL_2 = -1595039, - SAY_STEAL_FLESH_1 = -1595040, - SAY_STEAL_FLESH_2 = -1595041, - SAY_STEAL_FLESH_3 = -1595042, - SAY_SUMMON_GHOULS_1 = -1595043, - SAY_SUMMON_GHOULS_2 = -1595044 -}; - -struct boss_salrammAI : public ScriptedAI -{ - boss_salrammAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - DoScriptText(SAY_SPAWN,me); - } - - uint32 uiCurseFleshTimer; - uint32 uiExplodeGhoulTimer; - uint32 uiShadowBoltTimer; - uint32 uiStealFleshTimer; - uint32 uiSummonGhoulsTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiCurseFleshTimer = 30000; //30s DBM - uiExplodeGhoulTimer = urand(25000,28000); //approx 6 sec after summon ghouls - uiShadowBoltTimer = urand(8000,12000); // approx 10s - uiStealFleshTimer = 12345; - uiSummonGhoulsTimer = urand(19000,24000); //on a video approx 24s after aggro - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Curse of twisted flesh timer - if (uiCurseFleshTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSE_OF_TWISTED_FLESH); - uiCurseFleshTimer = 37000; - } else uiCurseFleshTimer -= diff; - - //Shadow bolt timer - if (uiShadowBoltTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - uiShadowBoltTimer = urand(8000,12000); - } else uiShadowBoltTimer -= diff; - - //Steal Flesh timer - if (uiStealFleshTimer <= diff) - { - DoScriptText(RAND(SAY_STEAL_FLESH_1,SAY_STEAL_FLESH_2,SAY_STEAL_FLESH_3), me); - if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(random_pTarget, SPELL_STEAL_FLESH); - uiStealFleshTimer = 10000; - } else uiStealFleshTimer -= diff; - - //Summon ghouls timer - if (uiSummonGhoulsTimer <= diff) - { - DoScriptText(RAND(SAY_SUMMON_GHOULS_1,SAY_SUMMON_GHOULS_2), me); - if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(random_pTarget, SPELL_SUMMON_GHOULS); - uiSummonGhoulsTimer = 10000; - } else uiSummonGhoulsTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_salramm(Creature* pCreature) -{ - return new boss_salrammAI (pCreature); -} - -void AddSC_boss_salramm() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_salramm"; - newscript->GetAI = &GetAI_boss_salramm; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp b/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp deleted file mode 100644 index faaed2eb6db..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp +++ /dev/null @@ -1,1210 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" -#include "ScriptedEscortAI.h" - -enum Says -{ - //First Act - Uther and Jaina Dialog - SAY_PHASE101 = -1595070, //Arthas - SAY_PHASE102 = -1595071, //Uther - SAY_PHASE103 = -1595072, //Arthas - SAY_PHASE104 = -1595073, //Arthas - SAY_PHASE105 = -1595074, //Uther - SAY_PHASE106 = -1595075, //Arthas - SAY_PHASE107 = -1595076, //Uther - SAY_PHASE108 = -1595077, //Arthas - SAY_PHASE109 = -1595078, //Arthas - SAY_PHASE110 = -1595079, //Uther - SAY_PHASE111 = -1595080, //Arthas - SAY_PHASE112 = -1595081, //Uther - SAY_PHASE113 = -1595082, //Jaina - SAY_PHASE114 = -1595083, //Arthas - SAY_PHASE115 = -1595084, //Uther - SAY_PHASE116 = -1595085, //Arthas - SAY_PHASE117 = -1595086, //Jaina - SAY_PHASE118 = -1595087, //Arthas - //Second Act - City Streets - SAY_PHASE201 = -1595088, //Arthas - SAY_PHASE202 = -1595089, //Cityman - SAY_PHASE203 = -1595090, //Arthas - SAY_PHASE204 = -1595091, //Crazyman - SAY_PHASE205 = -1595092, //Arthas - SAY_PHASE206 = -1595009, //Malganis - SAY_PHASE207 = -1595010, //Malganis - SAY_PHASE208 = -1595093, //Arthas - SAY_PHASE209 = -1595094, //Arthas - SAY_PHASE210 = -1595095, //Arthas - //Third Act - Town Hall - SAY_PHASE301 = -1595096, //Arthas - SAY_PHASE302 = -1595097, //Drakonian - SAY_PHASE303 = -1595098, //Arthas - SAY_PHASE304 = -1595099, //Arthas - SAY_PHASE305 = -1595100, //Drakonian - SAY_PHASE306 = -1595101, //Arthas - SAY_PHASE307 = -1595102, //Arthas - SAY_PHASE308 = -1595103, //Arthas - SAY_PHASE309 = -1595104, //Arthas - SAY_PHASE310 = -1595105, //Arthas - SAY_PHASE311 = -1595106, //Arthas - SAY_PHASE312 = -1595107, //Arthas - SAY_PHASE313 = -1595108, //Arthas - SAY_PHASE314 = -1595000, //Epoch - SAY_PHASE315 = -1595109, //Arthas - //Fourth Act - Fire Corridor - SAY_PHASE401 = -1595110, //Arthas - SAY_PHASE402 = -1595111, //Arthas - SAY_PHASE403 = -1595112, //Arthas - SAY_PHASE404 = -1595113, //Arthas - SAY_PHASE405 = -1595114, //Arthas - SAY_PHASE406 = -1595115, //Arthas - SAY_PHASE407 = -1595116, //Arthas - //Fifth Act - Mal'Ganis Fight - SAY_PHASE501 = -1595117, //Arthas - SAY_PHASE502 = -1595118, //Arthas - SAY_PHASE503 = -1595119, //Arthas - SAY_PHASE504 = -1595120, //Arthas -}; - -enum NPCs -{ - NPC_INFINITE_ADVERSARY = 27742, - NPC_INFINITE_HUNTER = 27743, - NPC_INFINITE_AGENT = 27744, - NPC_TIME_RIFT = 28409, - NPC_ZOMBIE = 27737, - NPC_GHOUL = 28249, - NPC_NECROMANCER = 28200, - NPC_STALKER = 28199, - NPC_FIEND = 27734, - NPC_GOLEM = 28201, - NPC_EGHOUL = 27729, - NPC_CONSTRUCT = 27736, - - NPC_INVIS_TARGET = 20562, - - NPC_KNIGHT_ESCORT = 27745, - NPC_PRIEST_ESCORT = 27747, - NPC_CITY_MAN = 28167, - NPC_CITY_MAN2 = 28169, - NPC_CITY_MAN3 = 31126, - NPC_CITY_MAN4 = 31127, -}; - -enum Spells -{ - SPELL_FEAR = 39176, - SPELL_ARTHAS_AURA = 52442, - SPELL_EXORCISM_N = 52445, - SPELL_EXORCISM_H = 58822, - SPELL_HOLY_LIGHT = 52444, -}; - -enum GossipMenuArthas -{ - GOSSIP_MENU_ARTHAS_1 = 100001, - GOSSIP_MENU_ARTHAS_2 = 100002, - GOSSIP_MENU_ARTHAS_3 = 100003, - GOSSIP_MENU_ARTHAS_4 = 100004, - GOSSIP_MENU_ARTHAS_5 = 100005 -}; - -enum -{ - ENCOUNTER_WAVES_NUMBER = 8, - ENCOUNTER_WAVES_MAX_SPAWNS = 5, - ENCOUNTER_DRACONIAN_NUMBER = 4, - ENCOUNTER_CHRONO_SPAWNS = 19 -}; - -// Locations for necromancers and add to spawn -float WavesLocations[ENCOUNTER_WAVES_NUMBER][ENCOUNTER_WAVES_MAX_SPAWNS][5]= -{ - { - {NPC_ZOMBIE, 2164.698975, 1255.392944, 135.040878, 0.490202}, - {NPC_ZOMBIE, 2183.501465, 1263.079102, 134.859055, 3.169981}, - {NPC_GHOUL, 2177.512939, 1247.313843, 135.846695, 1.696574}, - {NPC_GHOUL, 2171.991943, 1246.615845, 135.745026, 1.696574}, - {0, 0, 0, 0, 0} - }, - { - {NPC_GHOUL, 2254.434326, 1163.427612, 138.055038, 2.077358}, - {NPC_GHOUL, 2254.703613, 1158.867798, 138.212234, 2.345532}, - {NPC_GHOUL, 2257.615723, 1162.310913, 138.091202, 2.077358}, - {NPC_NECROMANCER, 2258.258057, 1157.250732, 138.272873, 2.387766}, - {0, 0, 0, 0, 0} - }, - { - {NPC_STALKER, 2348.120117, 1202.302490, 130.491104, 4.698538}, - {NPC_GHOUL, 2352.863525, 1207.819092, 130.424271, 4.949865}, - {NPC_GHOUL, 2343.593750, 1207.915039, 130.781311, 4.321547}, - {NPC_NECROMANCER, 2348.257324, 1212.202515, 130.670135, 4.450352}, - {0, 0, 0, 0, 0} - }, - { - {NPC_STALKER, 2139.825195, 1356.277100, 132.199615, 5.820131}, - {NPC_GHOUL, 2137.073486, 1362.464844, 132.271637, 5.820131}, - {NPC_GHOUL, 2134.075684, 1354.148071, 131.885864, 5.820131}, - {NPC_NECROMANCER, 2133.302246, 1358.907837, 132.037689, 5.820131}, - {0, 0, 0, 0, 0} - }, - { - {NPC_NECROMANCER, 2264.013428, 1174.055908, 138.093094, 2.860481}, - {NPC_GHOUL, 2264.207764, 1170.892700, 138.034973, 2.860481}, - {NPC_GHOUL, 2266.948975, 1176.898926, 137.976929, 2.860481}, - {NPC_STALKER, 2269.215576, 1170.109253, 137.742691, 2.860481}, - {NPC_FIEND, 2273.106689, 1176.101074, 137.880508, 2.860481} - }, - { - {NPC_GOLEM, 2349.701660, 1188.436646, 130.428864, 3.908642}, - {NPC_GHOUL, 2349.909180, 1194.582642, 130.417816, 3.577001}, - {NPC_EGHOUL, 2354.662598, 1185.692017, 130.552032, 3.577001}, - {NPC_EGHOUL, 2354.716797, 1191.614380, 130.539810, 3.577001}, - {0, 0, 0, 0, 0} - }, - { - {NPC_CONSTRUCT, 2145.212891, 1355.288086, 132.288773, 6.004838}, - {NPC_NECROMANCER, 2137.078613, 1357.612671, 132.173340, 6.004838}, - {NPC_EGHOUL, 2139.402100, 1352.541626, 132.127518, 5.812850}, - {NPC_EGHOUL, 2142.408447, 1360.760620, 132.321564, 5.812850}, - {0, 0, 0, 0, 0} - }, - { - {NPC_GHOUL, 2172.686279, 1259.618164, 134.391754, 1.865499}, - {NPC_FIEND, 2177.649170, 1256.061157, 135.096512, 1.849572}, - {NPC_CONSTRUCT, 2170.782959, 1253.594849, 134.973022, 1.849572}, - {NPC_NECROMANCER, 2175.595703, 1249.041992, 135.603531, 1.849572}, - {0, 0, 0, 0, 0} - } -}; - -// Locations for rifts to spawn and draconians to go -float RiftAndSpawnsLocations[ENCOUNTER_CHRONO_SPAWNS][5]= -{ - {NPC_TIME_RIFT, 2431.790039, 1190.670044, 148.076004, 0.187923}, - {NPC_INFINITE_ADVERSARY, 2433.857910, 1185.612061, 148.075974, 4.566168}, - {NPC_INFINITE_ADVERSARY, 2437.577881, 1188.241089, 148.075974, 0.196999}, - {NPC_INFINITE_AGENT, 2437.165527, 1192.294922, 148.075974, 0.169247}, - {NPC_INFINITE_HUNTER, 2434.989990, 1197.679565, 148.075974, 0.715971}, - {NPC_TIME_RIFT, 2403.954834, 1178.815430, 148.075943, 4.966126}, - {NPC_INFINITE_AGENT, 2403.676758, 1171.495850, 148.075607, 4.902797}, - {NPC_INFINITE_HUNTER, 2407.691162, 1172.162720, 148.075607, 4.963010}, - {NPC_TIME_RIFT, 2414.217041, 1133.446167, 148.076050, 1.706972}, - {NPC_INFINITE_ADVERSARY, 2416.024658, 1139.456177, 148.076431, 1.752129}, - {NPC_INFINITE_HUNTER, 2410.866699, 1139.680542, 148.076431, 1.752129}, - {NPC_TIME_RIFT, 2433.081543, 1099.869751, 148.076157, 1.809509}, - {NPC_INFINITE_ADVERSARY, 2426.947998, 1107.471680, 148.076019, 1.877580}, - {NPC_INFINITE_HUNTER, 2432.944580, 1108.896362, 148.208160, 2.199241}, - {NPC_TIME_RIFT, 2444.077637, 1114.366089, 148.076157, 3.049565}, - {NPC_INFINITE_ADVERSARY, 2438.190674, 1118.368164, 148.076172, 3.139232}, - {NPC_INFINITE_AGENT, 2435.861328, 1113.402954, 148.169327, 2.390271}, - {NPC_TIME_RIFT, 2463.131592, 1115.391724, 152.473129, 3.409651}, - {NPC_EPOCH, 2451.809326, 1112.901245, 149.220459, 3.363617} -}; - -struct npc_arthasAI : public npc_escortAI -{ - npc_arthasAI(Creature *pCreature) : npc_escortAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* pInstance; - - bool bStepping; - uint32 uiStep; - uint32 uiPhaseTimer; - uint32 uiGossipStep; - uint32 uiPlayerFaction; - uint32 uiBossEvent; - uint32 uiWave; - - uint64 uiUtherGUID; - uint64 uiJainaGUID; - uint64 uiCitymenGUID[2]; - uint64 uiWaveGUID[ENCOUNTER_WAVES_MAX_SPAWNS]; - uint64 uiInfiniteDraconianGUID[ENCOUNTER_DRACONIAN_NUMBER]; - uint64 uiStalkerGUID; - - uint64 uiBossGUID; //uiMeathookGUID || uiSalrammGUID - uint64 uiEpochGUID; - uint64 uiMalganisGUID; - uint64 uiInfiniteGUID; - - uint32 uiExorcismTimer; - - void Reset() - { - uiUtherGUID = 0; - uiJainaGUID = 0; - - for (uint8 i = 0; i < 2; ++i) - uiCitymenGUID[i] = 0; - - for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - uiWaveGUID[i] = 0; - - for (uint8 i = 0; i < ENCOUNTER_DRACONIAN_NUMBER; ++i) - uiInfiniteDraconianGUID[i] = 0; - - uiStalkerGUID = 0; - uiBossGUID = 0; - uiEpochGUID = 0; - uiMalganisGUID = 0; - uiInfiniteGUID = 0; - - if (pInstance) { - pInstance->SetData(DATA_ARTHAS_EVENT, NOT_STARTED); - switch(pInstance->GetData(DATA_ARTHAS_EVENT)) - { - case NOT_STARTED: - bStepping = true; - uiStep = 0; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - uiBossEvent = DATA_MEATHOOK_EVENT; - uiGossipStep = 0; - break; - } - uiPhaseTimer = 1000; - uiExorcismTimer = 7300; - uiWave = 0; - } - } - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_ARTHAS_AURA); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ARTHAS_EVENT, FAIL); - } - - void SpawnTimeRift(uint32 timeRiftID, uint64* guidVector) - { - me->SummonCreature((uint32)RiftAndSpawnsLocations[timeRiftID][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_DESPAWN,11000); - - for (uint32 i = timeRiftID+1; i < ENCOUNTER_CHRONO_SPAWNS; ++i) - { - if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_TIME_RIFT) break; - if (Creature* pTemp = me->SummonCreature((uint32)RiftAndSpawnsLocations[i][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - guidVector[i-timeRiftID-1] = pTemp->GetGUID(); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pTemp->SetReactState(REACT_PASSIVE); - pTemp->GetMotionMaster()->MovePoint(0, RiftAndSpawnsLocations[i][1],RiftAndSpawnsLocations[i][2],RiftAndSpawnsLocations[i][3]); - if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_EPOCH) - uiEpochGUID = pTemp->GetGUID(); - } - } - } - - void SpawnWaveGroup(uint32 waveID, uint64* guidVector) - { - for (uint32 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - { - if ((uint32)WavesLocations[waveID][i][0] == 0) break; - if (Creature* pTemp = me->SummonCreature((uint32)WavesLocations[waveID][i][0],WavesLocations[waveID][i][1],WavesLocations[waveID][i][2],WavesLocations[waveID][i][3],WavesLocations[waveID][i][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - guidVector[i] = pTemp->GetGUID(); - } - } - } - - void SetHoldState(bool bOnHold) - { - SetEscortPaused(bOnHold); - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhaseTimer = uiTimer; - ++uiStep; - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 0: - case 1: - case 3: - case 9: - case 10: - case 11: - case 22: - case 23: - case 26: - case 55: - case 56: - SetHoldState(true); - bStepping = true; - break; - case 7: - if (Unit* pCityman0 = me->SummonCreature(NPC_CITY_MAN,2091.977f,1275.021f,140.757f,0.558f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) - uiCitymenGUID[0] = pCityman0->GetGUID(); - if (Unit* pCityman1 = me->SummonCreature(NPC_CITY_MAN2,2093.514f,1275.842f,140.408f,3.801f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) - uiCitymenGUID[1] = pCityman1->GetGUID(); - break; - case 8: - uiGossipStep = 1; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - case 12: - SetRun(true); - DoScriptText(SAY_PHASE210, me); - if (Unit* pDisguised0 = me->SummonCreature(NPC_CITY_MAN3,2398.14f,1207.81f,134.04f,5.155249f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[0] = pDisguised0->GetGUID(); - if (Unit* pDisguised1 = me->SummonCreature(NPC_CITY_MAN4,2403.22f,1205.54f,134.04f,3.311264f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[1] = pDisguised1->GetGUID(); - - if (Unit* pDisguised2 = me->SummonCreature(NPC_CITY_MAN,2400.82f,1201.69f,134.01f,1.534082f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[2] = pDisguised2->GetGUID(); - pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); - pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[0]); - pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); - } - } - } - break; - case 20: - uiGossipStep = 2; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetRun(false); - SetHoldState(true); - break; - case 21: - DoScriptText(SAY_PHASE301, me); - break; - case 25: - SetRun(false); - SpawnTimeRift(0,&uiInfiniteDraconianGUID[0]); - DoScriptText(SAY_PHASE307,me); - break; - case 29: - SetRun(false); - SpawnTimeRift(5,&uiInfiniteDraconianGUID[0]); - SpawnTimeRift(8,&uiInfiniteDraconianGUID[2]); - DoScriptText(SAY_PHASE309,me); - SetHoldState(true); - bStepping = true; - break; - case 31: - SetRun(false); - SpawnTimeRift(11,&uiInfiniteDraconianGUID[0]); - SpawnTimeRift(14,&uiInfiniteDraconianGUID[2]); - DoScriptText(SAY_PHASE311,me); - SetHoldState(true); - bStepping = true; - break; - case 32: - DoScriptText(SAY_PHASE401,me); - break; - case 34: - DoScriptText(SAY_PHASE402,me); - break; - case 35: - DoScriptText(SAY_PHASE403,me); - break; - case 36: - if (pInstance) - { - GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SHKAF_GATE)); - pGate->SetGoState(GO_STATE_ACTIVE); - } - break; - case 45: - SetRun(true); - SetDespawnAtFar(false); - uiGossipStep = 4; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - case 47: - SetRun(false); - DoScriptText(SAY_PHASE405,me); - break; - case 48: - SetRun(true); - DoScriptText(SAY_PHASE406,me); - break; - case 53: - DoScriptText(SAY_PHASE407,me); - break; - case 54: - uiGossipStep = 5; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - } - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - DoMeleeAttackIfReady(); - - if (bStepping) - { - if (uiPhaseTimer <= diff) - { - switch(uiStep) - { - //After reset - case 0: - if (Unit* pJaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f)) - uiJainaGUID = pJaina->GetGUID(); - else if (Unit* pJaina = me->SummonCreature(NPC_JAINA,1895.48f,1292.66f,143.706f,0.023475f,TEMPSUMMON_DEAD_DESPAWN,180000)) - uiJainaGUID = pJaina->GetGUID(); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 0 - case 1: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - if (Unit* pUther = me->SummonCreature(NPC_UTHER,1794.357f,1272.183f,140.558f,1.37f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiUtherGUID = pUther->GetGUID(); - pUther->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pUther->GetMotionMaster()->MovePoint(0, 1897.018f, 1287.487f, 143.481f); - pUther->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiUtherGUID); - } - JumpToNextStep(17000); - break; - case 2: - DoScriptText(SAY_PHASE101, me); - JumpToNextStep(2000); - break; - case 3: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - { - DoScriptText(SAY_PHASE102, pUther); - } - JumpToNextStep(8000); - break; - case 4: - SetEscortPaused(false); - bStepping = false; - SetRun(false); - DoScriptText(SAY_PHASE103, me); - JumpToNextStep(0); - break; - //After waypoint 1 - case 5: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - pJaina->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - DoScriptText(SAY_PHASE104, me); - JumpToNextStep(10000); - break; - case 6: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE105, pUther); - JumpToNextStep(1000); - break; - case 7: - DoScriptText(SAY_PHASE106, me); - JumpToNextStep(4000); - break; - case 8: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE107, pUther); - JumpToNextStep(6000); - break; - case 9: - DoScriptText(SAY_PHASE108, me); - JumpToNextStep(4000); - break; - case 10: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE109, pUther); - JumpToNextStep(8000); - break; - case 11: - DoScriptText(SAY_PHASE110, me); - JumpToNextStep(4000); - break; - case 12: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE111, pUther); - JumpToNextStep(4000); - break; - case 13: - DoScriptText(SAY_PHASE112, me); - JumpToNextStep(11000); - break; - case 14: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - DoScriptText(SAY_PHASE113, pJaina); - JumpToNextStep(3000); - break; - case 15: - DoScriptText(SAY_PHASE114, me); - JumpToNextStep(9000); - break; - case 16: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE115, pUther); - JumpToNextStep(4000); - break; - case 17: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - { - pUther->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pUther->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); - } - JumpToNextStep(1000); - break; - case 18: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - { - me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); - pJaina->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pJaina->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); - } - JumpToNextStep(1000); - break; - case 19: - DoScriptText(SAY_PHASE116, me); - JumpToNextStep(1000); - break; - case 20: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - DoScriptText(SAY_PHASE117, pJaina); - JumpToNextStep(3000); - break; - case 21: - SetEscortPaused(false); - bStepping = false; - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After waypoint 3 - case 22: - DoScriptText(SAY_PHASE118, me); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); - JumpToNextStep(10000); - break; - case 23: - SetEscortPaused(false); - bStepping = false; - SetRun(true); - - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - pJaina->DisappearAndDie(); - - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - pUther->DisappearAndDie(); - - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After Gossip 1 (waypoint 8) - case 24: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2026.469f,1287.088f,143.596f,1.37f,TEMPSUMMON_TIMED_DESPAWN,14000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - JumpToNextStep(1000); - break; - case 25: - DoScriptText(SAY_PHASE201, me); - JumpToNextStep(12000); - break; - case 26: - SetEscortPaused(false); - bStepping = false; - SetRun(false); - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After waypoint 9 - case 27: - me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[0]); - if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) - { - pCityman->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - pCityman->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pCityman->GetMotionMaster()->MovePoint(0, 2088.625f,1279.191f,140.743f); - } - JumpToNextStep(2000); - break; - case 28: - if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) - DoScriptText(SAY_PHASE202, pCityman); - JumpToNextStep(4000); - break; - case 29: - SetEscortPaused(false); - bStepping = false; - DoScriptText(SAY_PHASE203, me); - JumpToNextStep(0); - break; - //After waypoint 10 - case 30: - me->HandleEmoteCommand(37); - JumpToNextStep(1000); - break; - case 31: - SetEscortPaused(false); - bStepping = false; - if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) - { - DoScriptText(SAY_PHASE204, pCityman1); - pCityman1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pCityman0 = Unit::GetCreature(*me, uiCitymenGUID[0])) - pCityman0->Kill(pCityman0); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[1]); - } - JumpToNextStep(0); - break; - //After waypoint 11 - case 32: - me->HandleEmoteCommand(37); - JumpToNextStep(1000); - break; - case 33: - if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) - pCityman1->Kill(pCityman1); - JumpToNextStep(1000); - break; - case 34: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - DoScriptText(SAY_PHASE205, me); - JumpToNextStep(3000); - break; - case 35: - if (Unit* pStalkerM = me->SummonCreature(NPC_INVIS_TARGET,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) - { - uiStalkerGUID = pStalkerM->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - JumpToNextStep(1000); - break; - case 36: - if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) - { - if (Creature* pStalkerM = Unit::GetCreature(*me, uiStalkerGUID)) - pMalganis->CastSpell(pStalkerM,63793,false); - - uiMalganisGUID = pMalganis->GetGUID(); - DoScriptText(SAY_PHASE206, pMalganis); - pMalganis->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - pMalganis->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(11000); - break; - case 37: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - { - if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN, 100.0f)) - pZombie->UpdateEntry(NPC_ZOMBIE, 0); - else if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN2, 100.0f)) - pZombie->UpdateEntry(NPC_ZOMBIE, 0); - else //There's no one else to transform - uiStep++; - } - else - uiStep++; - uiPhaseTimer = 500; - break; - case 38: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - DoScriptText(SAY_PHASE207, pMalganis); - JumpToNextStep(17000); - break; - case 39: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - pMalganis->SetVisibility(VISIBILITY_OFF); - DoScriptText(SAY_PHASE208, me); - JumpToNextStep(7000); - break; - case 40: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - DoScriptText(SAY_PHASE209, me); - - uiBossEvent = DATA_MEATHOOK_EVENT; - if (pInstance) - pInstance->SetData(DATA_ARTHAS_EVENT, IN_PROGRESS); - - me->SetReactState(REACT_DEFENSIVE); - SetDespawnAtFar(false); - JumpToNextStep(5000); - break; - case 41: //Summon wave group - case 43: - case 45: - case 47: - case 51: - case 53: - case 55: - case 57: - if (pInstance->GetData(uiBossEvent) != DONE) - { - SpawnWaveGroup(uiWave, uiWaveGUID); - uiWave++; - } - JumpToNextStep(500); - break; - case 42: //Wait group to die - case 44: - case 46: - case 48: - case 52: - case 54: - case 56: - case 58: - if (pInstance->GetData(uiBossEvent) != DONE) - { - uint32 mobCounter = 0; - uint32 deadCounter = 0; - for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - { - if (uiWaveGUID[i] == 0) - break; - ++mobCounter; - Unit* pTemp = Unit::GetCreature(*me, uiWaveGUID[i]); - if (!pTemp || pTemp->isDead()) - ++deadCounter; - } - - if (mobCounter <= deadCounter) //If group is dead - JumpToNextStep(1000); - else - uiPhaseTimer = 1000; - } - else - JumpToNextStep(500); - break; - case 49: //Summon Boss - case 59: - if (pInstance->GetData(uiBossEvent) != DONE) - { - uint32 uiBossID = 0; - if (uiBossEvent == DATA_MEATHOOK_EVENT) - uiBossID = NPC_MEATHOOK; - else if (uiBossEvent == DATA_SALRAMM_EVENT) - uiBossID = NPC_SALRAMM; - - if (Unit* pBoss = me->SummonCreature(uiBossID,2232.19f,1331.933f,126.662f,3.15f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - uiBossGUID = pBoss->GetGUID(); - pBoss->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pBoss->GetMotionMaster()->MovePoint(0, 2194.110f,1332.00f,130.00f); - } - } - JumpToNextStep(30000); - break; - case 50: //Wait Boss death - case 60: - if (pInstance) - { - if (pInstance->GetData(uiBossEvent) == DONE) - { - JumpToNextStep(1000); - if (uiBossEvent == DATA_MEATHOOK_EVENT) - uiBossEvent = DATA_SALRAMM_EVENT; - else if (uiBossEvent == DATA_SALRAMM_EVENT) - { - SetHoldState(false); - bStepping = false; - uiBossEvent = DATA_EPOCH_EVENT; - } - } - else if (pInstance->GetData(uiBossEvent) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After Gossip 2 (waypoint 22) - case 61: - me->SetReactState(REACT_AGGRESSIVE); - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) - pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) - pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - JumpToNextStep(1000); - break; - case 62: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - DoScriptText(SAY_PHASE302, pDisguised0); - JumpToNextStep(7000); - break; - case 63: - DoScriptText(SAY_PHASE303, me); - SetHoldState(false); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 23 - case 64: - me->HandleEmoteCommand(54); - JumpToNextStep(1000); - break; - case 65: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - pDisguised0->HandleEmoteCommand(11); - JumpToNextStep(1000); - break; - case 66: - DoScriptText(SAY_PHASE304,me); - JumpToNextStep(2000); - break; - case 67: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - DoScriptText(SAY_PHASE305,pDisguised0); - JumpToNextStep(1000); - break; - case 68: - if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) - { - pDisguised2->UpdateEntry(NPC_INFINITE_HUNTER, 0); - //Make them unattackable - pDisguised2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised2->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 69: - if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) - { - pDisguised1->UpdateEntry(NPC_INFINITE_AGENT, 0); - //Make them unattackable - pDisguised1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised1->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 70: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - { - pDisguised0->UpdateEntry(NPC_INFINITE_ADVERSARY, 0); - //Make them unattackable - pDisguised0->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised0->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 71: - //After waypoint 26,29,31 - case 73: - case 75: - case 77: - //Make cratures attackable - for (uint32 i = 0; i< ENCOUNTER_DRACONIAN_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiInfiniteDraconianGUID[i])) - { - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pTemp->SetReactState(REACT_AGGRESSIVE); - } - JumpToNextStep(5000); - break; - case 72: - case 74: - case 76: - if (me->isInCombat()) - uiPhaseTimer = 1000; - else - { - if (uiStep == 72) DoScriptText(SAY_PHASE308,me); - if (uiStep == 74) DoScriptText(SAY_PHASE308,me); - if (uiStep == 76) DoScriptText(SAY_PHASE310,me); - SetHoldState(false); - bStepping = false; - SetRun(true); - JumpToNextStep(2000); - } - break; - case 78: - if (me->isInCombat()) - uiPhaseTimer = 1000; - else - { - DoScriptText(SAY_PHASE312,me); - JumpToNextStep(5000); - } - break; - case 79: - DoScriptText(SAY_PHASE313,me); - JumpToNextStep(1000); - break; - case 80: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - { - SpawnTimeRift(17,&uiEpochGUID); - if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) - DoScriptText(SAY_PHASE314,pEpoch); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiEpochGUID); - } - JumpToNextStep(18000); - break; - case 81: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - DoScriptText(SAY_PHASE315, me); - JumpToNextStep(6000); - break; - case 82: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - { - if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) - { - //Make Epoch attackable - pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pEpoch->SetReactState(REACT_AGGRESSIVE); - } - - } - JumpToNextStep(1000); - break; - case 83: - if (pInstance) - { - if (pInstance->GetData(DATA_EPOCH_EVENT) == DONE) - { - uiGossipStep = 3; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - bStepping = false; - uiBossEvent = DATA_MAL_GANIS_EVENT; - JumpToNextStep(15000); - } - else if (pInstance->GetData(DATA_EPOCH_EVENT) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After Gossip 4 - case 84: - DoScriptText(SAY_PHASE404,me); - SetHoldState(false); - bStepping = false; - break; - //After Gossip 5 - case 85: - DoScriptText(SAY_PHASE501, me); - if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2296.665f,1502.362f,128.362f,4.961f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - uiMalganisGUID = pMalganis->GetGUID(); - pMalganis->SetReactState(REACT_PASSIVE); - } - if (pInstance) - { - GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAL_GANIS_GATE_1)); - pGate->SetGoState(GO_STATE_ACTIVE); - } - SetHoldState(false); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 55 - case 86: - DoScriptText(SAY_PHASE502, me); - JumpToNextStep(6000); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); - break; - case 87: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - { - pMalganis->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_6 | UNIT_FLAG_UNK_9 | UNIT_FLAG_UNK_15); - pMalganis->SetReactState(REACT_AGGRESSIVE); - } - JumpToNextStep(1000); - break; - case 88: - if (pInstance) - { - if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == DONE) - { - SetHoldState(false); - JumpToNextStep(1000); - } - else if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After waypoint 56 - case 89: - SetRun(true); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); - DoScriptText(SAY_PHASE503, me); - JumpToNextStep(7000); - break; - case 90: - if (pInstance) - { - pInstance->SetData(DATA_ARTHAS_EVENT, DONE); //Rewards: Achiev & Chest ;D - me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance->GetData64(DATA_MAL_GANIS_GATE_2)); //Look behind - } - DoScriptText(SAY_PHASE504, me); - bStepping = false; - break; - } - } else uiPhaseTimer -= diff; - } - - //Battling skills - if (!me->getVictim()) - return; - - if (uiExorcismTimer < diff) - { - if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(target, SPELL_EXORCISM_N); - uiExorcismTimer = 7300; - } else uiExorcismTimer -= diff; - - if (HealthBelowPct(40)) - DoCast(me, SPELL_HOLY_LIGHT); - } -}; - -CreatureAI* GetAI_npc_arthas(Creature* pCreature) -{ - return new npc_arthasAI(pCreature); -} - -#define GOSSIP_ITEM_ARTHAS_0 "I'm ready to start Culling of Stratholme." -#define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready." -#define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness." -#define GOSSIP_ITEM_ARTHAS_3 "I'm ready." -#define GOSSIP_ITEM_ARTHAS_4 "For Lordaeron!" -#define GOSSIP_ITEM_ARTHAS_5 "I'm ready to battle the dreadlord, sire." - -bool GossipHello_npc_arthas(Player* pPlayer, Creature* pCreature) -{ - npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); - - if (pAI && pAI->bStepping == false) - { - switch (pAI->uiGossipStep) - { - case 0: //This one is a workaround since the very beggining of the script is wrong. - if (pPlayer->GetQuestStatus(13149) != QUEST_STATUS_COMPLETE) - return false; - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - break; - case 1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_1, pCreature->GetGUID()); - break; - case 2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_2, pCreature->GetGUID()); - break; - case 3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_3, pCreature->GetGUID()); - break; - case 4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_4, pCreature->GetGUID()); - break; - case 5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_5, pCreature->GetGUID()); - break; - default: - return false; - } - } - return true; -} - - -bool GossipSelect_npc_arthas(Player *pPlayer, Creature *pCreature, uint32 /*sender*/, uint32 action) -{ - npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); - - if (!pAI) - return false; - - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - pAI->Start(true,true,pPlayer->GetGUID(),0,false,false); - pAI->SetDespawnAtEnd(false); - pAI->bStepping = false; - pAI->uiStep = 1; - break; - case GOSSIP_ACTION_INFO_DEF+1: - pAI->bStepping = true; - pAI->uiStep = 24; - break; - case GOSSIP_ACTION_INFO_DEF+2: - pAI->SetHoldState(false); - pAI->bStepping = false; - pAI->uiStep = 61; - break; - case GOSSIP_ACTION_INFO_DEF+3: - pAI->SetHoldState(false); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pAI->bStepping = true; - pAI->uiStep = 84; - break; - case GOSSIP_ACTION_INFO_DEF+5: - pAI->bStepping = true; - pAI->uiStep = 85; - break; - } - pPlayer->CLOSE_GOSSIP_MENU(); - pAI->SetDespawnAtFar(true); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - return true; -} - -void AddSC_culling_of_stratholme() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_arthas"; - newscript->GetAI = &GetAI_npc_arthas; - newscript->pGossipHello = &GossipHello_npc_arthas; - newscript->pGossipSelect = &GossipSelect_npc_arthas; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h b/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h deleted file mode 100644 index 4278ad46500..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef DEF_CULLING_OF_STRATHOLME_H -#define DEF_CULLING_OF_STRATHOLME_H - -enum Data -{ - DATA_MEATHOOK_EVENT, - DATA_SALRAMM_EVENT, - DATA_EPOCH_EVENT, - DATA_MAL_GANIS_EVENT, - DATA_INFINITE_EVENT, - DATA_ARTHAS_EVENT -}; - -enum Data64 -{ - DATA_ARTHAS, - DATA_MEATHOOK, - DATA_SALRAMM, - DATA_EPOCH, - DATA_MAL_GANIS, - DATA_INFINITE, - DATA_SHKAF_GATE, - DATA_MAL_GANIS_GATE_1, - DATA_MAL_GANIS_GATE_2, - DATA_EXIT_GATE, - DATA_MAL_GANIS_CHEST -}; - -enum Creatures -{ - NPC_MEATHOOK = 26529, - NPC_SALRAMM = 26530, - NPC_EPOCH = 26532, - NPC_MAL_GANIS = 26533, - NPC_INFINITE = 32273, - NPC_ARTHAS = 26499, - NPC_JAINA = 26497, - NPC_UTHER = 26528 -}; - -enum GameObjects -{ - GO_SHKAF_GATE = 188686, - GO_MALGANIS_GATE_1 = 187711, - GO_MALGANIS_GATE_2 = 187723, - GO_EXIT_GATE = 191788, - GO_MALGANIS_CHEST_N = 190663, - GO_MALGANIS_CHEST_H = 193597 -}; -#endif diff --git a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp deleted file mode 100644 index 73742a1e748..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -#define MAX_ENCOUNTER 5 - -/* Culling of Stratholme encounters: -0 - Meathook -1 - Salramm the Fleshcrafter -2 - Chrono-Lord Epoch -3 - Mal'Ganis -4 - Infinite Corruptor (Heroic only) -*/ - -struct instance_culling_of_stratholme : public ScriptedInstance -{ - instance_culling_of_stratholme(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiArthas; - uint64 uiMeathook; - uint64 uiSalramm; - uint64 uiEpoch; - uint64 uiMalGanis; - uint64 uiInfinite; - - uint64 uiShkafGate; - uint64 uiMalGanisGate1; - uint64 uiMalGanisGate2; - uint64 uiExitGate; - uint64 uiMalGanisChest; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_ARTHAS: - uiArthas = pCreature->GetGUID(); - break; - case NPC_MEATHOOK: - uiMeathook = pCreature->GetGUID(); - break; - case NPC_SALRAMM: - uiSalramm = pCreature->GetGUID(); - break; - case NPC_EPOCH: - uiEpoch = pCreature->GetGUID(); - break; - case NPC_MAL_GANIS: - uiMalGanis = pCreature->GetGUID(); - break; - case NPC_INFINITE: - uiInfinite = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_SHKAF_GATE: - uiShkafGate = pGo->GetGUID(); - break; - case GO_MALGANIS_GATE_1: - uiMalGanisGate1 = pGo->GetGUID(); - break; - case GO_MALGANIS_GATE_2: - uiMalGanisGate2 = pGo->GetGUID(); - break; - case GO_EXIT_GATE: - uiExitGate = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(uiExitGate,true); - break; - case GO_MALGANIS_CHEST_N: - case GO_MALGANIS_CHEST_H: - uiMalGanisChest = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MEATHOOK_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_SALRAMM_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_EPOCH_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_MAL_GANIS_EVENT: - m_auiEncounter[3] = data; - - switch(m_auiEncounter[3]) - { - case NOT_STARTED: - HandleGameObject(uiMalGanisGate2,true); - break; - case IN_PROGRESS: - HandleGameObject(uiMalGanisGate2,false); - break; - case DONE: - HandleGameObject(uiExitGate, true); - if (GameObject *pGo = instance->GetGameObject(uiMalGanisChest)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - } - break; - case DATA_INFINITE_EVENT: - m_auiEncounter[4] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_MEATHOOK_EVENT: return m_auiEncounter[0]; - case DATA_SALRAMM_EVENT: return m_auiEncounter[1]; - case DATA_EPOCH_EVENT: return m_auiEncounter[2]; - case DATA_MAL_GANIS_EVENT: return m_auiEncounter[3]; - case DATA_INFINITE_EVENT: return m_auiEncounter[4]; - } - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_ARTHAS: return uiArthas; - case DATA_MEATHOOK: return uiMeathook; - case DATA_SALRAMM: return uiSalramm; - case DATA_EPOCH: return uiEpoch; - case DATA_MAL_GANIS: return uiMalGanis; - case DATA_INFINITE: return uiInfinite; - case DATA_SHKAF_GATE: return uiShkafGate; - case DATA_MAL_GANIS_GATE_1: return uiMalGanisGate1; - case DATA_MAL_GANIS_GATE_2: return uiMalGanisGate2; - case DATA_EXIT_GATE: return uiExitGate; - case DATA_MAL_GANIS_CHEST: return uiMalGanisChest; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "C S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; - - if (dataHead1 == 'C' && dataHead2 == 'S') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap) -{ - return new instance_culling_of_stratholme(pMap); -} - -void AddSC_instance_culling_of_stratholme() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_culling_of_stratholme"; - newscript->GetInstanceData = &GetInstanceData_instance_culling_of_stratholme; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp b/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp deleted file mode 100644 index 49cf7cd4433..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Aeonus -SD%Complete: 80 -SDComment: Some spells not implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269012, - SAY_AGGRO = -1269013, - SAY_BANISH = -1269014, - SAY_SLAY1 = -1269015, - SAY_SLAY2 = -1269016, - SAY_DEATH = -1269017, - EMOTE_FRENZY = -1269018, - - SPELL_CLEAVE = 40504, - SPELL_TIME_STOP = 31422, - SPELL_ENRAGE = 37605, - SPELL_SAND_BREATH = 31473, - H_SPELL_SAND_BREATH = 39049 -}; - -struct boss_aeonusAI : public ScriptedAI -{ - boss_aeonusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SandBreath_Timer; - uint32 TimeStop_Timer; - uint32 Frenzy_Timer; - - void Reset() - { - SandBreath_Timer = 15000+rand()%15000; - TimeStop_Timer = 10000+rand()%5000; - Frenzy_Timer = 30000+rand()%15000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_RIFT,DONE); - pInstance->SetData(TYPE_MEDIVH,DONE);//FIXME: later should be removed - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sand Breath - if (SandBreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SAND_BREATH); - SandBreath_Timer = 15000+rand()%10000; - } else SandBreath_Timer -= diff; - - //Time Stop - if (TimeStop_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIME_STOP); - TimeStop_Timer = 20000+rand()%15000; - } else TimeStop_Timer -= diff; - - //Frenzy - if (Frenzy_Timer <= diff) - { - DoScriptText(EMOTE_FRENZY, me); - DoCast(me, SPELL_ENRAGE); - Frenzy_Timer = 20000+rand()%15000; - } else Frenzy_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_aeonus(Creature* pCreature) -{ - return new boss_aeonusAI (pCreature); -} - -void AddSC_boss_aeonus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_aeonus"; - newscript->GetAI = &GetAI_boss_aeonus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp b/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp deleted file mode 100644 index 1f2b4a80612..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Chrono_Lord_Deja -SD%Complete: 65 -SDComment: All abilities not implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269006, - SAY_AGGRO = -1269007, - SAY_BANISH = -1269008, - SAY_SLAY1 = -1269009, - SAY_SLAY2 = -1269010, - SAY_DEATH = -1269011, - - SPELL_ARCANE_BLAST = 31457, - H_SPELL_ARCANE_BLAST = 38538, - SPELL_ARCANE_DISCHARGE = 31472, - H_SPELL_ARCANE_DISCHARGE = 38539, - SPELL_TIME_LAPSE = 31467, - SPELL_ATTRACTION = 38540 //Not Implemented (Heroic mode) -}; - -struct boss_chrono_lord_dejaAI : public ScriptedAI -{ - boss_chrono_lord_dejaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 ArcaneBlast_Timer; - uint32 TimeLapse_Timer; - uint32 Attraction_Timer; - uint32 ArcaneDischarge_Timer; - - void Reset() - { - ArcaneBlast_Timer = 18000+rand()%5000; - TimeLapse_Timer = 10000+rand()%5000; - ArcaneDischarge_Timer = 20000+rand()%10000; - Attraction_Timer = 25000+rand()%10000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Arcane Blast - if (ArcaneBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BLAST); - ArcaneBlast_Timer = 15000+rand()%10000; - } else ArcaneBlast_Timer -= diff; - - //Arcane Discharge - if (ArcaneDischarge_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - DoCast(pTarget, SPELL_ARCANE_DISCHARGE); - ArcaneDischarge_Timer = 20000+rand()%10000; - } else ArcaneDischarge_Timer -= diff; - - //Time Lapse - if (TimeLapse_Timer <= diff) - { - DoScriptText(SAY_BANISH, me); - DoCast(me, SPELL_TIME_LAPSE); - TimeLapse_Timer = 15000+rand()%10000; - } else TimeLapse_Timer -= diff; - - if (IsHeroic()) - { - if (Attraction_Timer <= diff) - { - DoCast(me, SPELL_ATTRACTION); - Attraction_Timer = 25000+rand()%10000; - } else Attraction_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_chrono_lord_deja(Creature* pCreature) -{ - return new boss_chrono_lord_dejaAI (pCreature); -} - -void AddSC_boss_chrono_lord_deja() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_chrono_lord_deja"; - newscript->GetAI = &GetAI_boss_chrono_lord_deja; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp b/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp deleted file mode 100644 index 04b4b020ead..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Temporus -SD%Complete: 75 -SDComment: More abilities need to be implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269000, - SAY_AGGRO = -1269001, - SAY_BANISH = -1269002, - SAY_SLAY1 = -1269003, - SAY_SLAY2 = -1269004, - SAY_DEATH = -1269005, - - SPELL_HASTE = 31458, - SPELL_MORTAL_WOUND = 31464, - SPELL_WING_BUFFET = 31475, - H_SPELL_WING_BUFFET = 38593, - SPELL_REFLECT = 38592 //Not Implemented (Heroic mod) -}; - -struct boss_temporusAI : public ScriptedAI -{ - boss_temporusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Haste_Timer; - uint32 SpellReflection_Timer; - uint32 MortalWound_Timer; - uint32 WingBuffet_Timer; - - void Reset() - { - Haste_Timer = 15000+rand()%8000; - SpellReflection_Timer = 30000; - MortalWound_Timer = 8000; - WingBuffet_Timer = 25000+rand()%10000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Attack Haste - if (Haste_Timer <= diff) - { - DoCast(me, SPELL_HASTE); - Haste_Timer = 20000+rand()%5000; - } else Haste_Timer -= diff; - - //MortalWound_Timer - if (MortalWound_Timer <= diff) - { - DoCast(me, SPELL_MORTAL_WOUND); - MortalWound_Timer = 10000+rand()%10000; - } else MortalWound_Timer -= diff; - - //Wing ruffet - if (WingBuffet_Timer <= diff) - { - DoCast(me, SPELL_WING_BUFFET); - WingBuffet_Timer = 20000+rand()%10000; - } else WingBuffet_Timer -= diff; - - if (IsHeroic()) - { - if (SpellReflection_Timer <= diff) - { - DoCast(me, SPELL_REFLECT); - SpellReflection_Timer = 25000+rand()%10000; - } else SpellReflection_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_temporus(Creature* pCreature) -{ - return new boss_temporusAI (pCreature); -} - -void AddSC_boss_temporus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_temporus"; - newscript->GetAI = &GetAI_boss_temporus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp b/src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp deleted file mode 100644 index b0432a9b57c..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Dark_Portal -SD%Complete: 30 -SDComment: Misc NPC's and mobs for instance. Most here far from complete. -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -/* ContentData -npc_medivh_bm -npc_time_rift -npc_saat -EndContentData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -#define SAY_ENTER -1269020 //where does this belong? -#define SAY_INTRO -1269021 -#define SAY_WEAK75 -1269022 -#define SAY_WEAK50 -1269023 -#define SAY_WEAK25 -1269024 -#define SAY_DEATH -1269025 -#define SAY_WIN -1269026 -#define SAY_ORCS_ENTER -1269027 -#define SAY_ORCS_ANSWER -1269028 - -#define SPELL_CHANNEL 31556 -#define SPELL_PORTAL_RUNE 32570 //aura(portal on ground effect) - -#define SPELL_BLACK_CRYSTAL 32563 //aura -#define SPELL_PORTAL_CRYSTAL 32564 //summon - -#define SPELL_BANISH_PURPLE 32566 //aura -#define SPELL_BANISH_GREEN 32567 //aura - -#define SPELL_CORRUPT 31326 -#define SPELL_CORRUPT_AEONUS 37853 - -#define C_COUNCIL_ENFORCER 17023 - -struct npc_medivh_bmAI : public ScriptedAI -{ - npc_medivh_bmAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SpellCorrupt_Timer; - uint32 Check_Timer; - - bool Life75; - bool Life50; - bool Life25; - - void Reset() - { - SpellCorrupt_Timer = 0; - - if (!pInstance) - return; - - if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) - DoCast(me, SPELL_CHANNEL, true); - else if (me->HasAura(SPELL_CHANNEL)) - me->RemoveAura(SPELL_CHANNEL); - - DoCast(me, SPELL_PORTAL_RUNE, true); - } - - void MoveInLineOfSight(Unit *who) - { - if (!pInstance) - return; - - if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 10.0f)) - { - if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS || pInstance->GetData(TYPE_MEDIVH) == DONE) - return; - - DoScriptText(SAY_INTRO, me); - pInstance->SetData(TYPE_MEDIVH,IN_PROGRESS); - DoCast(me, SPELL_CHANNEL, false); - Check_Timer = 5000; - } - else if (who->GetTypeId() == TYPEID_UNIT && me->IsWithinDistInMap(who, 15.0f)) - { - if (pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) - return; - - uint32 entry = who->GetEntry(); - if (entry == C_ASSAS || entry == C_WHELP || entry == C_CHRON || entry == C_EXECU || entry == C_VANQU) - { - who->StopMoving(); - who->CastSpell(me,SPELL_CORRUPT,false); - } - else if (entry == C_AEONUS) - { - who->StopMoving(); - who->CastSpell(me,SPELL_CORRUPT_AEONUS,false); - } - } - } - - void AttackStart(Unit * /*who*/) - { - //if (pInstance && pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) - //return; - - //ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit * /*who*/) {} - - void SpellHit(Unit* /*caster*/, const SpellEntry* spell) - { - if (SpellCorrupt_Timer) - return; - - if (spell->Id == SPELL_CORRUPT_AEONUS) - SpellCorrupt_Timer = 1000; - - if (spell->Id == SPELL_CORRUPT) - SpellCorrupt_Timer = 3000; - } - - void JustDied(Unit* Killer) - { - if (Killer->GetEntry() == me->GetEntry()) - return; - - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (SpellCorrupt_Timer) - { - if (SpellCorrupt_Timer <= diff) - { - pInstance->SetData(TYPE_MEDIVH,SPECIAL); - - if (me->HasAura(SPELL_CORRUPT_AEONUS)) - SpellCorrupt_Timer = 1000; - else if (me->HasAura(SPELL_CORRUPT)) - SpellCorrupt_Timer = 3000; - else - SpellCorrupt_Timer = 0; - } else SpellCorrupt_Timer -= diff; - } - - if (Check_Timer) - { - if (Check_Timer <= diff) - { - uint32 pct = pInstance->GetData(DATA_SHIELD); - - Check_Timer = 5000; - - if (Life25 && pct <= 25) - { - DoScriptText(SAY_WEAK25, me); - Life25 = false; - } - else if (Life50 && pct <= 50) - { - DoScriptText(SAY_WEAK50, me); - Life50 = false; - } - else if (Life75 && pct <= 75) - { - DoScriptText(SAY_WEAK75, me); - Life75 = false; - } - - //if we reach this it means event was running but at some point reset. - if (pInstance->GetData(TYPE_MEDIVH) == NOT_STARTED) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - me->Respawn(); - return; - } - - if (pInstance->GetData(TYPE_RIFT) == DONE) - { - DoScriptText(SAY_WIN, me); - Check_Timer = 0; - - if (me->HasAura(SPELL_CHANNEL)) - me->RemoveAura(SPELL_CHANNEL); - - //TODO: start the post-event here - pInstance->SetData(TYPE_MEDIVH,DONE); - } - } else Check_Timer -= diff; - } - - //if (!UpdateVictim()) - //return; - - //DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_medivh_bm(Creature* pCreature) -{ - return new npc_medivh_bmAI (pCreature); -} - -struct Wave -{ - uint32 PortalMob[4]; //spawns for portal waves (in order) -}; - -static Wave PortalWaves[]= -{ - {C_ASSAS, C_WHELP, C_CHRON, 0}, - {C_EXECU, C_CHRON, C_WHELP, C_ASSAS}, - {C_EXECU, C_VANQU, C_CHRON, C_ASSAS} -}; - -struct npc_time_riftAI : public ScriptedAI -{ - npc_time_riftAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 TimeRiftWave_Timer; - uint8 mRiftWaveCount; - uint8 mPortalCount; - uint8 mWaveId; - - void Reset() - { - - TimeRiftWave_Timer = 15000; - mRiftWaveCount = 0; - - if (!pInstance) - return; - - mPortalCount = pInstance->GetData(DATA_PORTAL_COUNT); - - if (mPortalCount < 6) - mWaveId = 0; - else if (mPortalCount > 12) - mWaveId = 2; - else mWaveId = 1; - - } - void EnterCombat(Unit * /*who*/) {} - - void DoSummonAtRift(uint32 creature_entry) - { - if (!creature_entry) - return; - - if (pInstance && pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) - { - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - return; - } - - Position pos; - me->GetRandomNearPosition(pos, 10.0f); - - //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); - - if (Unit *Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) - if (Unit *temp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_MEDIVH) : 0)) - Summon->AddThreat(temp,0.0f); - } - - void DoSelectSummon() - { - uint32 entry = 0; - - if ((mRiftWaveCount > 2 && mWaveId < 1) || mRiftWaveCount > 3) - mRiftWaveCount = 0; - - entry = PortalWaves[mWaveId].PortalMob[mRiftWaveCount]; - debug_log("TSCR: npc_time_rift: summoning wave Creature (Wave %u, Entry %u).",mRiftWaveCount,entry); - - ++mRiftWaveCount; - - if (entry == C_WHELP) - { - for (uint8 i = 0; i < 3; ++i) - DoSummonAtRift(entry); - } else DoSummonAtRift(entry); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (TimeRiftWave_Timer <= diff) - { - DoSelectSummon(); - TimeRiftWave_Timer = 15000; - } else TimeRiftWave_Timer -= diff; - - if (me->IsNonMeleeSpellCasted(false)) - return; - - debug_log("TSCR: npc_time_rift: not casting anylonger, i need to die."); - me->setDeathState(JUST_DIED); - - if (pInstance->GetData(TYPE_RIFT) == IN_PROGRESS) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } -}; - -CreatureAI* GetAI_npc_time_rift(Creature* pCreature) -{ - return new npc_time_riftAI (pCreature); -} - -#define SAY_SAAT_WELCOME -1269019 - -#define GOSSIP_ITEM_OBTAIN "[PH] Obtain Chrono-Beacon" -#define SPELL_CHRONO_BEACON 34975 -#define ITEM_CHRONO_BEACON 24289 - -bool GossipHello_npc_saat(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(10000, pCreature->GetGUID()); - return true; - } - else if (pPlayer->GetQuestRewardStatus(QUEST_OPENING_PORTAL) && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(10001, pCreature->GetGUID()); - return true; - } - - pPlayer->SEND_GOSSIP_MENU(10002, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_saat(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer,SPELL_CHRONO_BEACON,false); - } - return true; -} - -void AddSC_dark_portal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_medivh_bm"; - newscript->GetAI = &GetAI_npc_medivh_bm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_time_rift"; - newscript->GetAI = &GetAI_npc_time_rift; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_saat"; - newscript->pGossipHello = &GossipHello_npc_saat; - newscript->pGossipSelect = &GossipSelect_npc_saat; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h b/src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h deleted file mode 100644 index 7bfd8c917d7..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_DARKPORTAL_H -#define DEF_DARKPORTAL_H - -#define TYPE_MEDIVH 1 -#define TYPE_RIFT 2 - -#define DATA_MEDIVH 10 -#define DATA_PORTAL_COUNT 11 -#define DATA_SHIELD 12 - -#define WORLD_STATE_BM 2541 -#define WORLD_STATE_BM_SHIELD 2540 -#define WORLD_STATE_BM_RIFT 2784 - -#define QUEST_OPENING_PORTAL 10297 -#define QUEST_MASTER_TOUCH 9836 - -#define C_TIME_KEEPER 17918 -#define C_RKEEP 21104 -#define C_RLORD 17839 -#define C_DEJA 17879 -#define C_TEMPO 17880 -#define C_AEONUS 17881 -#define C_ASSAS 17835 -#define C_WHELP 21818 -#define C_CHRON 17892 -#define C_EXECU 18994 -#define C_VANQU 18995 - -#endif - diff --git a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp b/src/server/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp deleted file mode 100644 index d1280230808..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Dark_Portal -SD%Complete: 50 -SDComment: Quest support: 9836, 10297. Currently in progress. -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -#define MAX_ENCOUNTER 2 - -#define C_MEDIVH 15608 -#define C_TIME_RIFT 17838 - -#define SPELL_RIFT_CHANNEL 31387 - -#define RIFT_BOSS 1 - -inline uint32 RandRiftBoss() { return ((rand()%2) ? C_RKEEP : C_RLORD); } - -float PortalLocation[4][4]= -{ - {-2041.06, 7042.08, 29.99, 1.30}, - {-1968.18, 7042.11, 21.93, 2.12}, - {-1885.82, 7107.36, 22.32, 3.07}, - {-1928.11, 7175.95, 22.11, 3.44} -}; - -struct Wave -{ - uint32 PortalBoss; //protector of current portal - uint32 NextPortalTime; //time to next portal, or 0 if portal boss need to be killed -}; - -static Wave RiftWaves[]= -{ - {RIFT_BOSS, 0}, - {C_DEJA, 0}, - {RIFT_BOSS, 120000}, - {C_TEMPO, 140000}, - {RIFT_BOSS, 120000}, - {C_AEONUS, 0} -}; - -struct instance_dark_portal : public ScriptedInstance -{ - instance_dark_portal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint32 mRiftPortalCount; - uint32 mShieldPercent; - uint8 mRiftWaveCount; - uint8 mRiftWaveId; - - uint32 NextPortal_Timer; - - uint64 MedivhGUID; - uint8 CurrentRiftId; - - void Initialize() - { - MedivhGUID = 0; - Clear(); - } - - void Clear() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - mRiftPortalCount = 0; - mShieldPercent = 100; - mRiftWaveCount = 0; - mRiftWaveId = 0; - - CurrentRiftId = 0; - - NextPortal_Timer = 0; - } - - void InitWorldState(bool Enable = true) - { - DoUpdateWorldState(WORLD_STATE_BM,Enable ? 1 : 0); - DoUpdateWorldState(WORLD_STATE_BM_SHIELD, 100); - DoUpdateWorldState(WORLD_STATE_BM_RIFT, 0); - } - - bool IsEncounterInProgress() - { - if (GetData(TYPE_MEDIVH) == IN_PROGRESS) - return true; - - return false; - } - - void OnPlayerEnter(Player* pPlayer) - { - if (GetData(TYPE_MEDIVH) == IN_PROGRESS) - return; - - pPlayer->SendUpdateWorldState(WORLD_STATE_BM,0); - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == C_MEDIVH) - MedivhGUID = pCreature->GetGUID(); - } - - //what other conditions to check? - bool CanProgressEvent() - { - if (instance->GetPlayers().isEmpty()) - return false; - - return true; - } - - uint8 GetRiftWaveId() - { - switch(mRiftPortalCount) - { - case 6: - mRiftWaveId = 2; - return 1; - case 12: - mRiftWaveId = 4; - return 3; - case 18: - return 5; - default: - return mRiftWaveId; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_MEDIVH: - if (data == SPECIAL && m_auiEncounter[0] == IN_PROGRESS) - { - --mShieldPercent; - - DoUpdateWorldState(WORLD_STATE_BM_SHIELD, mShieldPercent); - - if (!mShieldPercent) - { - if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) - { - if (pMedivh->isAlive()) - { - pMedivh->DealDamage(pMedivh, pMedivh->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - m_auiEncounter[0] = FAIL; - m_auiEncounter[1] = NOT_STARTED; - } - } - } - } - else - { - if (data == IN_PROGRESS) - { - debug_log("TSCR: Instance Dark Portal: Starting event."); - InitWorldState(); - m_auiEncounter[1] = IN_PROGRESS; - NextPortal_Timer = 15000; - } - - if (data == DONE) - { - //this may be completed further out in the post-event - debug_log("TSCR: Instance Dark Portal: Event completed."); - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - { - if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL); - - if (pPlayer->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH); - } - } - } - } - - m_auiEncounter[0] = data; - } - break; - case TYPE_RIFT: - if (data == SPECIAL) - { - if (mRiftPortalCount < 7) - NextPortal_Timer = 5000; - } - else - m_auiEncounter[1] = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_MEDIVH: - return m_auiEncounter[0]; - case TYPE_RIFT: - return m_auiEncounter[1]; - case DATA_PORTAL_COUNT: - return mRiftPortalCount; - case DATA_SHIELD: - return mShieldPercent; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - if (data == DATA_MEDIVH) - return MedivhGUID; - - return 0; - } - - Creature* SummonedPortalBoss(Creature* me) - { - uint32 entry = RiftWaves[GetRiftWaveId()].PortalBoss; - - if (entry == RIFT_BOSS) - entry = RandRiftBoss(); - - debug_log("TSCR: Instance Dark Portal: Summoning rift boss entry %u.",entry); - - Position pos; - me->GetRandomNearPosition(pos, 10.0f); - - //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); - - if (Creature *summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) - return summon; - - debug_log("TSCR: Instance Dark Portal: What just happened there? No boss, no loot, no fun..."); - return NULL; - } - - void DoSpawnPortal() - { - if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) - { - uint8 tmp = urand(0,2); - - if (tmp >= CurrentRiftId) - ++tmp; - - debug_log("TSCR: Instance Dark Portal: Creating Time Rift at locationId %i (old locationId was %u).",tmp,CurrentRiftId); - - CurrentRiftId = tmp; - - Creature *pTemp = pMedivh->SummonCreature(C_TIME_RIFT, - PortalLocation[tmp][0],PortalLocation[tmp][1],PortalLocation[tmp][2],PortalLocation[tmp][3], - TEMPSUMMON_CORPSE_DESPAWN,0); - if (pTemp) - { - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (Creature *pBoss = SummonedPortalBoss(pTemp)) - { - if (pBoss->GetEntry() == C_AEONUS) - pBoss->AddThreat(pMedivh,0.0f); - else - { - pBoss->AddThreat(pTemp,0.0f); - pTemp->CastSpell(pBoss,SPELL_RIFT_CHANNEL,false); - } - } - } - } - } - - void Update(uint32 diff) - { - if (m_auiEncounter[1] != IN_PROGRESS) - return; - - //add delay timer? - if (!CanProgressEvent()) - { - Clear(); - return; - } - - if (NextPortal_Timer) - { - if (NextPortal_Timer <= diff) - { - ++mRiftPortalCount; - - DoUpdateWorldState(WORLD_STATE_BM_RIFT, mRiftPortalCount); - - DoSpawnPortal(); - NextPortal_Timer = RiftWaves[GetRiftWaveId()].NextPortalTime; - } else NextPortal_Timer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_dark_portal(Map* pMap) -{ - return new instance_dark_portal(pMap); -} - -void AddSC_instance_dark_portal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_dark_portal"; - newscript->GetInstanceData = &GetInstanceData_instance_dark_portal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp deleted file mode 100644 index 14ce4a59b37..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp +++ /dev/null @@ -1,309 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_CARRION_SWARM 31306 -#define SPELL_SLEEP 31298 -#define SPELL_VAMPIRIC_AURA 38196 -#define SPELL_INFERNO 31299 - -#define SAY_ONDEATH "The clock... is still... ticking." -#define SOUND_ONDEATH 10982 - -#define SAY_ONSLAY1 "Your hopes are lost!" -#define SAY_ONSLAY2 "Scream for me!" -#define SAY_ONSLAY3 "Pity, no time for a slow death!" -#define SOUND_ONSLAY1 10981 -#define SOUND_ONSLAY2 11038 -#define SOUND_ONSLAY3 11039 - -#define SAY_SWARM1 "The swarm is eager to feed!" -#define SAY_SWARM2 "Pestilence upon you!" -#define SOUND_SWARM1 10979 -#define SOUND_SWARM2 11037 - -#define SAY_SLEEP1 "You look tired..." -#define SAY_SLEEP2 "Sweet dreams..." -#define SOUND_SLEEP1 10978 -#define SOUND_SLEEP2 11545 - -#define SAY_INFERNO1 "Let fire rain from above!" -#define SAY_INFERNO2 "Earth and sky shall burn!" -#define SOUND_INFERNO1 10980 -#define SOUND_INFERNO2 11036 - -#define SAY_ONAGGRO "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!" -#define SOUND_ONAGGRO 10977 - -struct boss_anetheronAI : public hyjal_trashAI -{ - boss_anetheronAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_SLEEP); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) - { - TempSpell->EffectImplicitTargetA[0] = 1; - TempSpell->EffectImplicitTargetB[0] = 0; - } - } - - uint32 SwarmTimer; - uint32 SleepTimer; - uint32 AuraTimer; - uint32 InfernoTimer; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - SwarmTimer = 45000; - SleepTimer = 60000; - AuraTimer = 5000; - InfernoTimer = 45000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, 0); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 4896.08, -1576.35, 1333.65); - AddWaypoint(1, 4898.68, -1615.02, 1329.48); - AddWaypoint(2, 4907.12, -1667.08, 1321.00); - AddWaypoint(3, 4963.18, -1699.35, 1340.51); - AddWaypoint(4, 4989.16, -1716.67, 1335.74); - AddWaypoint(5, 5026.27, -1736.89, 1323.02); - AddWaypoint(6, 5037.77, -1770.56, 1324.36); - AddWaypoint(7, 5067.23, -1789.95, 1321.17); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (SwarmTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CARRION_SWARM); - - SwarmTimer = urand(45000,60000); - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_SWARM1); - me->MonsterYell(SAY_SWARM1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_SWARM2); - me->MonsterYell(SAY_SWARM2, LANG_UNIVERSAL, 0); - break; - } - } else SwarmTimer -= diff; - - if (SleepTimer <= diff) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - pTarget->CastSpell(pTarget,SPELL_SLEEP,true); - } - SleepTimer = 60000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_SLEEP1); - me->MonsterYell(SAY_SLEEP1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_SLEEP2); - me->MonsterYell(SAY_SLEEP2, LANG_UNIVERSAL, 0); - break; - } - } else SleepTimer -= diff; - if (AuraTimer <= diff) - { - DoCast(me, SPELL_VAMPIRIC_AURA, true); - AuraTimer = urand(10000,20000); - } else AuraTimer -= diff; - if (InfernoTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_INFERNO); - InfernoTimer = 45000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_INFERNO1); - me->MonsterYell(SAY_INFERNO1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_INFERNO2); - me->MonsterYell(SAY_INFERNO2, LANG_UNIVERSAL, 0); - break; - } - } else InfernoTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_anetheron(Creature* pCreature) -{ - return new boss_anetheronAI (pCreature); -} - -#define SPELL_IMMOLATION 31303 -#define SPELL_INFERNO_EFFECT 31302 - -struct mob_towering_infernalAI : public ScriptedAI -{ - mob_towering_infernalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - AnetheronGUID = pInstance->GetData64(DATA_ANETHERON); - } - - uint32 ImmolationTimer; - uint32 CheckTimer; - uint64 AnetheronGUID; - ScriptedInstance* pInstance; - - void Reset() - { - DoCast(me, SPELL_INFERNO_EFFECT); - ImmolationTimer = 5000; - CheckTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - } - - void JustDied(Unit * /*victim*/) - { - } - - void MoveInLineOfSight(Unit *who) - { - if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) - AttackStart(who); - } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (AnetheronGUID) - { - Creature* boss = Unit::GetCreature((*me),AnetheronGUID); - if (!boss || (boss && boss->isDead())) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (ImmolationTimer <= diff) - { - DoCast(me, SPELL_IMMOLATION); - ImmolationTimer = 5000; - } else ImmolationTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_towering_infernal(Creature* pCreature) -{ - return new mob_towering_infernalAI (pCreature); -} - -void AddSC_boss_anetheron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_anetheron"; - newscript->GetAI = &GetAI_boss_anetheron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_towering_infernal"; - newscript->GetAI = &GetAI_mob_towering_infernal; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp deleted file mode 100644 index 8e1fa378e07..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Archimonde -SD%Complete: 85 -SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented. -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "SpellAuras.h" -#include "hyjal_trash.h" - -//text id -1534018 are the text used when previous events complete. Not part of this script. -#define SAY_AGGRO -1534019 -#define SAY_DOOMFIRE1 -1534020 -#define SAY_DOOMFIRE2 -1534021 -#define SAY_AIR_BURST1 -1534022 -#define SAY_AIR_BURST2 -1534023 -#define SAY_SLAY1 -1534024 -#define SAY_SLAY2 -1534025 -#define SAY_SLAY3 -1534026 -#define SAY_ENRAGE -1534027 -#define SAY_DEATH -1534028 -#define SAY_SOUL_CHARGE1 -1534029 -#define SAY_SOUL_CHARGE2 -1534030 - -#define SPELL_DENOUEMENT_WISP 32124 -#define SPELL_ANCIENT_SPARK 39349 -#define SPELL_PROTECTION_OF_ELUNE 38528 - -#define SPELL_DRAIN_WORLD_TREE 39140 -#define SPELL_DRAIN_WORLD_TREE_2 39141 - -#define SPELL_FINGER_OF_DEATH 31984 -#define SPELL_HAND_OF_DEATH 35354 -#define SPELL_AIR_BURST 32014 -#define SPELL_GRIP_OF_THE_LEGION 31972 -#define SPELL_DOOMFIRE_STRIKE 31903 //summons two creatures -#define SPELL_DOOMFIRE_SPAWN 32074 -#define SPELL_DOOMFIRE 31945 -#define SPELL_SOUL_CHARGE_YELLOW 32045 -#define SPELL_SOUL_CHARGE_GREEN 32051 -#define SPELL_SOUL_CHARGE_RED 32052 -#define SPELL_UNLEASH_SOUL_YELLOW 32054 -#define SPELL_UNLEASH_SOUL_GREEN 32057 -#define SPELL_UNLEASH_SOUL_RED 32053 -#define SPELL_FEAR 31970 - -#define CREATURE_ARCHIMONDE 17968 -#define CREATURE_DOOMFIRE 18095 -#define CREATURE_DOOMFIRE_SPIRIT 18104 -#define CREATURE_ANCIENT_WISP 17946 -#define CREATURE_CHANNEL_TARGET 22418 - -#define NORDRASSIL_X 5503.713 -#define NORDRASSIL_Y -3523.436 -#define NORDRASSIL_Z 1608.781 - -struct mob_ancient_wispAI : public ScriptedAI -{ - mob_ancient_wispAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - ArchimondeGUID = 0; - } - - ScriptedInstance* pInstance; - uint64 ArchimondeGUID; - uint32 CheckTimer; - - void Reset() - { - CheckTimer = 1000; - - if (pInstance) - ArchimondeGUID = pInstance->GetData64(DATA_ARCHIMONDE); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void EnterCombat(Unit* /*who*/) {} - - void DamageTaken(Unit* /*done_by*/, uint32 &damage) { damage = 0; } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (Unit* Archimonde = Unit::GetUnit((*me), ArchimondeGUID)) - { - if ((((Archimonde->GetHealth()*100) / Archimonde->GetMaxHealth()) < 2) || !Archimonde->isAlive()) - DoCast(me, SPELL_DENOUEMENT_WISP); - else - DoCast(Archimonde, SPELL_ANCIENT_SPARK); - } - CheckTimer = 1000; - } else CheckTimer -= diff; - } -}; - -/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will - MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */ -struct mob_doomfireAI : public ScriptedAI -{ - mob_doomfireAI(Creature* c) : ScriptedAI(c) {} - - void Reset() { } - - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit* /*who*/) {} - void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } -}; - -/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or - travels in random directions if pTarget cannot be found. */ -struct mob_doomfire_targettingAI : public ScriptedAI -{ - mob_doomfire_targettingAI(Creature* c) : ScriptedAI(c) {} - - uint64 TargetGUID; - uint32 ChangeTargetTimer; - - void Reset() - { - TargetGUID = 0; - ChangeTargetTimer = 5000; - } - - void MoveInLineOfSight(Unit* who) - { - //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0 - //when UpdateAI needs it, it will be forced to select randomPoint - if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER) - TargetGUID = who->GetGUID(); - } - - void EnterCombat(Unit* /*who*/) {} - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } - - void UpdateAI(const uint32 diff) - { - if (ChangeTargetTimer <= diff) - { - if (Unit *temp = Unit::GetUnit(*me,TargetGUID)) - { - me->GetMotionMaster()->MoveFollow(temp,0.0f,0.0f); - TargetGUID = 0; - } - else - { - Position pos; - me->GetRandomNearPosition(pos, 40); - me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - } - - ChangeTargetTimer = 5000; - } else ChangeTargetTimer -= diff; - } -}; - -/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers. - The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the - hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then - select a random pTarget and cast the spell on them. However, if someone IS in melee range, and this - is NOT the main tank (creature's victim), then we aggro that player and they become the new victim. - For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will - randomly select it's pTarget to follow and then we create the random movement making it unpredictable. */ - -struct boss_archimondeAI : public hyjal_trashAI -{ - boss_archimondeAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 DoomfireSpiritGUID; - uint64 WorldTreeGUID; - - uint32 DrainNordrassilTimer; - uint32 FearTimer; - uint32 AirBurstTimer; - uint32 GripOfTheLegionTimer; - uint32 DoomfireTimer; - uint32 SoulChargeTimer; - uint32 SoulChargeCount; - uint32 MeleeRangeCheckTimer; - uint32 HandOfDeathTimer; - uint32 SummonWispTimer; - uint32 WispCount; - uint32 EnrageTimer; - uint32 CheckDistanceTimer; - - bool Enraged; - bool BelowTenPercent; - bool HasProtected; - bool IsChanneling; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); - - DoomfireSpiritGUID = 0; - damageTaken = 0; - WorldTreeGUID = 0; - - DrainNordrassilTimer = 0; - FearTimer = 42000; - AirBurstTimer = 30000; - GripOfTheLegionTimer = urand(5000,25000); - DoomfireTimer = 20000; - SoulChargeTimer = urand(2000,30000); - SoulChargeCount = 0; - MeleeRangeCheckTimer = 15000; - HandOfDeathTimer = 2000; - WispCount = 0; // When ~30 wisps are summoned, Archimonde dies - EnrageTimer = 600000; // 10 minutes - CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage - SummonWispTimer = 0; - - Enraged = false; - BelowTenPercent = false; - HasProtected = false; - IsChanneling = false; - } - - void EnterCombat(Unit * /*who*/) - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * victim) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - - if (victim && (victim->GetTypeId() == TYPEID_PLAYER)) - GainSoulCharge(CAST_PLR(victim)); - } - - void GainSoulCharge(Player* victim) - { - switch(victim->getClass()) - { - case CLASS_PRIEST: - case CLASS_PALADIN: - case CLASS_WARLOCK: - victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); - break; - case CLASS_MAGE: - case CLASS_ROGUE: - case CLASS_WARRIOR: - victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); - break; - case CLASS_DRUID: - case CLASS_SHAMAN: - case CLASS_HUNTER: - victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); - break; - } - - SoulChargeTimer = urand(2000,30000); - ++SoulChargeCount; - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, DONE); - } - - bool CanUseFingerOfDeath() - { - // First we check if our current victim is in melee range or not. - Unit* victim = me->getVictim(); - if (victim && me->IsWithinDistInMap(victim, me->GetAttackDistance(victim))) - return false; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - if (m_threatlist.empty()) - return false; - - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - targets.push_back(pUnit); - } - - if (targets.empty()) - return false; - - targets.sort(Trinity::ObjectDistanceOrderPred(me)); - Unit *pTarget = targets.front(); - if (pTarget) - { - if (!me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) - return true; // Cast Finger of Death - else // This target is closest, he is our new tank - me->AddThreat(pTarget, me->getThreatManager().getThreat(me->getVictim())); - } - - return false; - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == CREATURE_ANCIENT_WISP) - summoned->AI()->AttackStart(me); - else - { - summoned->setFaction(me->getFaction()); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) - { - DoomfireSpiritGUID = summoned->GetGUID(); - } - - if (summoned->GetEntry() == CREATURE_DOOMFIRE) - { - summoned->CastSpell(summoned,SPELL_DOOMFIRE_SPAWN,false); - summoned->CastSpell(summoned,SPELL_DOOMFIRE,true,0,0,me->GetGUID()); - - if (Unit *DoomfireSpirit = Unit::GetUnit(*me, DoomfireSpiritGUID)) - { - summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit,0.0f,0.0f); - DoomfireSpiritGUID = 0; - } - } - } - - //this is code doing close to what the summoning spell would do (spell 31903) - void SummonDoomfire(Unit *pTarget) - { - me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, - pTarget->GetPositionX()+15.0,pTarget->GetPositionY()+15.0,pTarget->GetPositionZ(),0, - TEMPSUMMON_TIMED_DESPAWN, 27000); - - me->SummonCreature(CREATURE_DOOMFIRE, - pTarget->GetPositionX()-15.0,pTarget->GetPositionY()-15.0,pTarget->GetPositionZ(),0, - TEMPSUMMON_TIMED_DESPAWN, 27000); - } - - void UnleashSoulCharge() - { - me->InterruptNonMeleeSpells(false); - - bool HasCast = false; - uint32 chargeSpell = 0; - uint32 unleashSpell = 0; - - switch (urand(0,2)) - { - case 0: - chargeSpell = SPELL_SOUL_CHARGE_RED; - unleashSpell = SPELL_UNLEASH_SOUL_RED; - break; - case 1: - chargeSpell = SPELL_SOUL_CHARGE_YELLOW; - unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; - break; - case 2: - chargeSpell = SPELL_SOUL_CHARGE_GREEN; - unleashSpell = SPELL_UNLEASH_SOUL_GREEN; - break; - } - - if (me->HasAura(chargeSpell)) - { - me->RemoveAuraFromStack(chargeSpell); - DoCast(me->getVictim(), unleashSpell); - HasCast = true; - SoulChargeCount--; - } - - if (HasCast) - SoulChargeTimer = urand(2000,30000); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - { - if (pInstance) - { - // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. - if ((pInstance->GetData(DATA_AZGALOREVENT) < DONE) && ((me->GetVisibility() != VISIBILITY_OFF) || (me->getFaction() != 35))) - { - me->SetVisibility(VISIBILITY_OFF); - me->setFaction(35); - } - else if ((pInstance->GetData(DATA_AZGALOREVENT) >= DONE) && ((me->GetVisibility() != VISIBILITY_ON) || (me->getFaction() == 35))) - { - me->setFaction(1720); - me->SetVisibility(VISIBILITY_ON); - } - } - - if (DrainNordrassilTimer <= diff) - { - if (!IsChanneling) - { - Creature *temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 1200000); - - if (temp) - WorldTreeGUID = temp->GetGUID(); - - if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Nordrassil->SetDisplayId(11686); - DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); - IsChanneling = true; - } - } - - if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); - DrainNordrassilTimer = 1000; - } - } else DrainNordrassilTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !BelowTenPercent && !Enraged) - BelowTenPercent = true; - - if (!Enraged) - { - if (EnrageTimer <= diff) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) > 10) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - DoScriptText(SAY_ENRAGE, me); - } - } else EnrageTimer -= diff; - - if (CheckDistanceTimer <= diff) - { - // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature - Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000); - if (Check) - { - Check->SetVisibility(VISIBILITY_OFF); - - if (me->IsWithinDistInMap(Check, 75)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - DoScriptText(SAY_ENRAGE, me); - } - } - CheckDistanceTimer = 5000; - } else CheckDistanceTimer -= diff; - } - - if (BelowTenPercent) - { - if (!HasProtected) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - - //all members of raid must get this buff - DoCast(me->getVictim(), SPELL_PROTECTION_OF_ELUNE); - HasProtected = true; - Enraged = true; - } - - if (SummonWispTimer <= diff) - { - DoSpawnCreature(CREATURE_ANCIENT_WISP, rand()%40, rand()%40, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - SummonWispTimer = 1500; - ++WispCount; - } else SummonWispTimer -= diff; - - if (WispCount >= 30) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (Enraged) - { - if (HandOfDeathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HAND_OF_DEATH); - HandOfDeathTimer = 2000; - } else HandOfDeathTimer -= diff; - return; // Don't do anything after this point. - } - - if (SoulChargeCount) - { - if (SoulChargeTimer <= diff) - UnleashSoulCharge(); - else SoulChargeTimer -= diff; - } - - if (GripOfTheLegionTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); - GripOfTheLegionTimer = urand(5000,25000); - } else GripOfTheLegionTimer -= diff; - - if (AirBurstTimer <= diff) - { - if (urand(0,1)) - DoScriptText(SAY_AIR_BURST1, me); - else - DoScriptText(SAY_AIR_BURST2, me); - - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank - AirBurstTimer = urand(25000,40000); - } else AirBurstTimer -= diff; - - if (FearTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - FearTimer = 42000; - } else FearTimer -= diff; - - if (DoomfireTimer <= diff) - { - if (urand(0,1)) - DoScriptText(SAY_DOOMFIRE1, me); - else - DoScriptText(SAY_DOOMFIRE2, me); - - Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!temp) - temp = me->getVictim(); - - //replace with spell cast 31903 once implicitTarget 73 implemented - SummonDoomfire(temp); - - //supposedly three doomfire can be up at the same time - DoomfireTimer = 20000; - } else DoomfireTimer -= diff; - - if (MeleeRangeCheckTimer <= diff) - { - if (CanUseFingerOfDeath()) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); - MeleeRangeCheckTimer = 1000; - } - - MeleeRangeCheckTimer = 5000; - } else MeleeRangeCheckTimer -= diff; - - DoMeleeAttackIfReady(); - } - void WaypointReached(uint32 /*i*/){} -}; - -CreatureAI* GetAI_boss_archimonde(Creature* pCreature) -{ - return new boss_archimondeAI (pCreature); -} - -CreatureAI* GetAI_mob_doomfire(Creature* pCreature) -{ - return new mob_doomfireAI(pCreature); -} - -CreatureAI* GetAI_mob_doomfire_targetting(Creature* pCreature) -{ - return new mob_doomfire_targettingAI(pCreature); -} - -CreatureAI* GetAI_mob_ancient_wisp(Creature* pCreature) -{ - return new mob_ancient_wispAI(pCreature); -} - -void AddSC_boss_archimonde() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_archimonde"; - newscript->GetAI = &GetAI_boss_archimonde; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_doomfire"; - newscript->GetAI = &GetAI_mob_doomfire; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_doomfire_targetting"; - newscript->GetAI = &GetAI_mob_doomfire_targetting; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ancient_wisp"; - newscript->GetAI = &GetAI_mob_ancient_wisp; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp deleted file mode 100644 index 69e37f7f740..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp +++ /dev/null @@ -1,285 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_RAIN_OF_FIRE 31340 -#define SPELL_DOOM 31347 -#define SPELL_HOWL_OF_AZGALOR 31344 -#define SPELL_CLEAVE 31345 -#define SPELL_BERSERK 26662 - -#define SAY_ONDEATH "Your time is almost... up" -#define SOUND_ONDEATH 11002 - -#define SAY_ONSLAY1 "Reesh, hokta!" -#define SAY_ONSLAY2 "Don't fight it" -#define SAY_ONSLAY3 "No one is going to save you" -#define SOUND_ONSLAY1 11001 -#define SOUND_ONSLAY2 11048 -#define SOUND_ONSLAY3 11047 - -#define SAY_DOOM1 "Just a taste... of what awaits you" -#define SAY_DOOM2 "Suffer you despicable insect!" -#define SOUND_DOOM1 11046 -#define SOUND_DOOM2 11000 - -#define SAY_ONAGGRO "Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!" -#define SOUND_ONAGGRO 10999 - -struct boss_azgalorAI : public hyjal_trashAI -{ - boss_azgalorAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_HOWL_OF_AZGALOR); - if (TempSpell) - TempSpell->EffectRadiusIndex[0] = 12;//100yards instead of 50000?! - } - - uint32 RainTimer; - uint32 DoomTimer; - uint32 HowlTimer; - uint32 CleaveTimer; - uint32 EnrageTimer; - bool enraged; - - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - RainTimer = 20000; - DoomTimer = 50000; - HowlTimer = 30000; - CleaveTimer = 10000; - EnrageTimer = 600000; - enraged = false; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 5492.91, -2404.61, 1462.63); - AddWaypoint(1, 5531.76, -2460.87, 1469.55); - AddWaypoint(2, 5554.58, -2514.66, 1476.12); - AddWaypoint(3, 5554.16, -2567.23, 1479.90); - AddWaypoint(4, 5540.67, -2625.99, 1480.89); - AddWaypoint(5, 5508.16, -2659.2, 1480.15); - AddWaypoint(6, 5489.62, -2704.05, 1482.18); - AddWaypoint(7, 5457.04, -2726.26, 1485.10); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (RainTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,30,true), SPELL_RAIN_OF_FIRE); - RainTimer = 20000+rand()%15000; - } else RainTimer -= diff; - - if (DoomTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,100,true), SPELL_DOOM);//never on tank - DoomTimer = 45000+rand()%5000; - } else DoomTimer -= diff; - - if (HowlTimer <= diff) - { - DoCast(me, SPELL_HOWL_OF_AZGALOR); - HowlTimer = 30000; - } else HowlTimer -= diff; - - if (CleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - CleaveTimer = 10000+rand()%5000; - } else CleaveTimer -= diff; - - if (EnrageTimer < diff && !enraged) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_BERSERK, true); - enraged = true; - EnrageTimer = 600000; - } else EnrageTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_azgalor(Creature* pCreature) -{ - return new boss_azgalorAI (pCreature); -} - -#define SPELL_THRASH 12787 -#define SPELL_CRIPPLE 31406 -#define SPELL_WARSTOMP 31408 - -struct mob_lesser_doomguardAI : public hyjal_trashAI -{ - mob_lesser_doomguardAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - AzgalorGUID = pInstance->GetData64(DATA_AZGALOR); - } - - uint32 CrippleTimer; - uint32 WarstompTimer; - uint32 CheckTimer; - uint64 AzgalorGUID; - ScriptedInstance* pInstance; - - void Reset() - { - CrippleTimer = 50000; - WarstompTimer = 10000; - DoCast(me, SPELL_THRASH); - CheckTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - } - - void WaypointReached(uint32 /*i*/) - { - } - - void MoveInLineOfSight(Unit *who) - { - if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) - AttackStart(who); - } - - void JustDied(Unit * /*victim*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (AzgalorGUID) - { - Creature* boss = Unit::GetCreature((*me),AzgalorGUID); - if (!boss || (boss && boss->isDead())) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (WarstompTimer <= diff) - { - DoCast(me, SPELL_WARSTOMP); - WarstompTimer = 10000+rand()%5000; - } else WarstompTimer -= diff; - - if (CrippleTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_CRIPPLE); - CrippleTimer = 25000+rand()%5000; - } else CrippleTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_lesser_doomguard(Creature* pCreature) -{ - return new mob_lesser_doomguardAI (pCreature); -} - -void AddSC_boss_azgalor() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_azgalor"; - newscript->GetAI = &GetAI_boss_azgalor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lesser_doomguard"; - newscript->GetAI = &GetAI_mob_lesser_doomguard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp deleted file mode 100644 index b52d22842e3..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp +++ /dev/null @@ -1,197 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_CLEAVE 31436 -#define SPELL_WARSTOMP 31480 -#define SPELL_MARK 31447 - -#define SOUND_ONDEATH 11018 - -#define SAY_ONSLAY1 "Shaza-Kiel!" -#define SAY_ONSLAY2 "You... are nothing!" -#define SAY_ONSLAY3 "Miserable nuisance!" -#define SOUND_ONSLAY1 11017 -#define SOUND_ONSLAY2 11053 -#define SOUND_ONSLAY3 11054 - -#define SAY_MARK1 "Your death will be a painful one." -#define SAY_MARK2 "You... are marked." -#define SOUND_MARK1 11016 -#define SOUND_MARK2 11052 - -#define SAY_ONAGGRO "Cry for mercy! Your meaningless lives will soon be forfeit." -#define SOUND_ONAGGRO 11015 - -struct boss_kazrogalAI : public hyjal_trashAI -{ - boss_kazrogalAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_MARK); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) - { - TempSpell->EffectImplicitTargetA[0] = 1; - TempSpell->EffectImplicitTargetB[0] = 0; - } - } - - uint32 CleaveTimer; - uint32 WarStompTimer; - uint32 MarkTimer; - uint32 MarkTimerBase; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - CleaveTimer = 5000; - WarStompTimer = 15000; - MarkTimer = 45000; - MarkTimerBase = 45000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 5492.91, -2404.61, 1462.63); - AddWaypoint(1, 5531.76, -2460.87, 1469.55); - AddWaypoint(2, 5554.58, -2514.66, 1476.12); - AddWaypoint(3, 5554.16, -2567.23, 1479.90); - AddWaypoint(4, 5540.67, -2625.99, 1480.89); - AddWaypoint(5, 5508.16, -2659.2, 1480.15); - AddWaypoint(6, 5489.62, -2704.05, 1482.18); - AddWaypoint(7, 5457.04, -2726.26, 1485.10); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (CleaveTimer <= diff) - { - DoCast(me, SPELL_CLEAVE); - CleaveTimer = 6000+rand()%15000; - } else CleaveTimer -= diff; - - if (WarStompTimer <= diff) - { - DoCast(me, SPELL_WARSTOMP); - WarStompTimer = 60000; - } else WarStompTimer -= diff; - - if (me->HasAura(SPELL_MARK)) - me->RemoveAurasDueToSpell(SPELL_MARK); - if (MarkTimer <= diff) - { - //cast dummy, useful for bos addons - me->CastCustomSpell(me, SPELL_MARK, NULL, NULL, NULL, false, NULL, NULL, me->GetGUID()); - - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->getPowerType() == POWER_MANA) - { - pTarget->CastSpell(pTarget, SPELL_MARK,true);//only cast on mana users - } - } - MarkTimerBase -= 5000; - if (MarkTimerBase < 5500) - MarkTimerBase = 5500; - MarkTimer = MarkTimerBase; - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_MARK1); - me->MonsterYell(SAY_MARK1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_MARK2); - me->MonsterYell(SAY_MARK2, LANG_UNIVERSAL, NULL); - break; - } - } else MarkTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kazrogal(Creature* pCreature) -{ - return new boss_kazrogalAI (pCreature); -} - -void AddSC_boss_kazrogal() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kazrogal"; - newscript->GetAI = &GetAI_boss_kazrogal; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp deleted file mode 100644 index 7465b997117..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp +++ /dev/null @@ -1,192 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_FROST_ARMOR 31256 -#define SPELL_DEATH_AND_DECAY 31258 - -#define SPELL_FROST_NOVA 31250 -#define SPELL_ICEBOLT 31249 - -#define SAY_ONDEATH "You have won this battle, but not... the... war" -#define SOUND_ONDEATH 11026 - -#define SAY_ONSLAY1 "All life must perish!" -#define SAY_ONSLAY2 "Victory to the Legion!" -#define SOUND_ONSLAY1 11025 -#define SOUND_ONSLAY2 11057 - -#define SAY_DECAY1 "Crumble and rot!" -#define SAY_DECAY2 "Ashes to ashes, dust to dust" -#define SOUND_DECAY1 11023 -#define SOUND_DECAY2 11055 - -#define SAY_NOVA1 "Succumb to the icy chill... of death!" -#define SAY_NOVA2 "It will be much colder in your grave" -#define SOUND_NOVA1 11024 -#define SOUND_NOVA2 11058 - -#define SAY_ONAGGRO "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!" -#define SOUND_ONAGGRO 11022 - -struct boss_rage_winterchillAI : public hyjal_trashAI -{ - boss_rage_winterchillAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - } - - uint32 FrostArmorTimer; - uint32 DecayTimer; - uint32 NovaTimer; - uint32 IceboltTimer; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - FrostArmorTimer = 37000; - DecayTimer = 45000; - NovaTimer = 15000; - IceboltTimer = 10000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0f); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, NULL); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 4896.08, -1576.35, 1333.65); - AddWaypoint(1, 4898.68, -1615.02, 1329.48); - AddWaypoint(2, 4907.12, -1667.08, 1321.00); - AddWaypoint(3, 4963.18, -1699.35, 1340.51); - AddWaypoint(4, 4989.16, -1716.67, 1335.74); - AddWaypoint(5, 5026.27, -1736.89, 1323.02); - AddWaypoint(6, 5037.77, -1770.56, 1324.36); - AddWaypoint(7, 5067.23, -1789.95, 1321.17); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (FrostArmorTimer <= diff) - { - DoCast(me, SPELL_FROST_ARMOR); - FrostArmorTimer = 40000+rand()%20000; - } else FrostArmorTimer -= diff; - if (DecayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_DEATH_AND_DECAY); - DecayTimer = 60000+rand()%20000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_DECAY1); - me->MonsterYell(SAY_DECAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_DECAY2); - me->MonsterYell(SAY_DECAY2, LANG_UNIVERSAL, NULL); - break; - } - } else DecayTimer -= diff; - if (NovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_NOVA); - NovaTimer = 30000+rand()%15000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_NOVA1); - me->MonsterYell(SAY_NOVA1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_NOVA2); - me->MonsterYell(SAY_NOVA2, LANG_UNIVERSAL, NULL); - break; - } - } else NovaTimer -= diff; - if (IceboltTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,40,true), SPELL_ICEBOLT); - IceboltTimer = 11000+rand()%20000; - } else IceboltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_rage_winterchill(Creature* pCreature) -{ - return new boss_rage_winterchillAI (pCreature); -} - -void AddSC_boss_rage_winterchill() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_rage_winterchill"; - newscript->GetAI = &GetAI_boss_rage_winterchill; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp deleted file mode 100644 index 16a050939cc..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp +++ /dev/null @@ -1,247 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Hyjal -SD%Complete: 80 -SDComment: gossip text id's unknown -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -/* ContentData -npc_jaina_proudmoore -npc_thrall -npc_tyrande_whisperwind -EndContentData */ - -#include "ScriptedPch.h" -#include "hyjalAI.h" - -#define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore." -#define GOSSIP_ITEM_ANETHERON "We are ready for whatever Archimonde might send our way, Lady Proudmoore." - -#define GOSSIP_ITEM_BEGIN_HORDE "I am with you, Thrall." -#define GOSSIP_ITEM_AZGALOR "We have nothing to fear." - -#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!" - -#define GOSSIP_ITEM_TYRANDE "Aid us in defending Nordrassil" -#define ITEM_TEAR_OF_GODDESS 24494 - -#define GOSSIP_ITEM_GM1 "[GM] Toggle Debug Timers" - -CreatureAI* GetAI_npc_jaina_proudmoore(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - - ai->Reset(); - ai->EnterEvadeMode(); - - ai->Spell[0].SpellId = SPELL_BLIZZARD; - ai->Spell[0].Cooldown = 15000 + rand()%20000; - ai->Spell[0].TargetType = TARGETTYPE_RANDOM; - - ai->Spell[1].SpellId = SPELL_PYROBLAST; - ai->Spell[1].Cooldown = 5500 + rand()%4000; - ai->Spell[1].TargetType = TARGETTYPE_RANDOM; - - ai->Spell[2].SpellId = SPELL_SUMMON_ELEMENTALS; - ai->Spell[2].Cooldown = 15000 + rand()%30000; - ai->Spell[2].TargetType = TARGETTYPE_SELF; - - return ai; -} - -bool GossipHello_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - if (ai->EventBegun) - return false; - - uint32 RageEncounter = ai->GetInstanceData(DATA_RAGEWINTERCHILLEVENT); - uint32 AnetheronEncounter = ai->GetInstanceData(DATA_ANETHERONEVENT); - if (RageEncounter == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - else if (RageEncounter == DONE && AnetheronEncounter == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - else if (RageEncounter == DONE && AnetheronEncounter == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - - if (pPlayer->isGameMaster()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - ai->FirstBossDead = true; - ai->WaveCount = 9; - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - ai->Retreat(); - break; - case GOSSIP_ACTION_INFO_DEF: - ai->Debug = !ai->Debug; - debug_log("TSCR: HyjalAI - Debug mode has been toggled"); - break; - } - return true; -} - -CreatureAI* GetAI_npc_thrall(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - - ai->Reset(); - ai->EnterEvadeMode(); - - ai->Spell[0].SpellId = SPELL_CHAIN_LIGHTNING; - ai->Spell[0].Cooldown = 3000 + rand()%5000; - ai->Spell[0].TargetType = TARGETTYPE_VICTIM; - - ai->Spell[1].SpellId = SPELL_SUMMON_DIRE_WOLF; - ai->Spell[1].Cooldown = 6000 + rand()%35000; - ai->Spell[1].TargetType = TARGETTYPE_RANDOM; - - return ai; -} - -bool GossipHello_npc_thrall(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - if (ai->EventBegun) - return false; - - uint32 AnetheronEvent = ai->GetInstanceData(DATA_ANETHERONEVENT); - // Only let them start the Horde phases if Anetheron is dead. - if (AnetheronEvent == DONE && ai->GetInstanceData(DATA_ALLIANCE_RETREAT)) - { - uint32 KazrogalEvent = ai->GetInstanceData(DATA_KAZROGALEVENT); - uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); - if (KazrogalEvent == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - else if (KazrogalEvent == DONE && AzgalorEvent == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - else if (AzgalorEvent == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - } - - if (pPlayer->isGameMaster()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_thrall(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - ai->DeSpawnVeins();//despawn the alliance veins - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - ai->FirstBossDead = true; - ai->WaveCount = 9; - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - ai->Retreat(); - break; - case GOSSIP_ACTION_INFO_DEF: - ai->Debug = !ai->Debug; - debug_log("TSCR: HyjalAI - Debug mode has been toggled"); - break; - } - return true; -} - -CreatureAI* GetAI_npc_tyrande_whisperwind(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - ai->Reset(); - ai->EnterEvadeMode(); - return ai; -} - -bool GossipHello_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); - - // Only let them get item if Azgalor is dead. - if (AzgalorEvent == DONE && !pPlayer->HasItemCount(ITEM_TEAR_OF_GODDESS,1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TYRANDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_TEAR_OF_GODDESS, 1); - if (msg == EQUIP_ERR_OK) - { - Item* item = pPlayer->StoreNewItem(dest, ITEM_TEAR_OF_GODDESS, true); - if (item && pPlayer) - pPlayer->SendNewItem(item,1,true,false,true); - } - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - CAST_AI(hyjalAI, pCreature->AI()); - } - return true; -} - -void AddSC_hyjal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_jaina_proudmoore"; - newscript->GetAI = &GetAI_npc_jaina_proudmoore; - newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore; - newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thrall"; - newscript->GetAI = &GetAI_npc_thrall; - newscript->pGossipHello = &GossipHello_npc_thrall; - newscript->pGossipSelect = &GossipSelect_npc_thrall; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tyrande_whisperwind"; - newscript->pGossipHello = &GossipHello_npc_tyrande_whisperwind; - newscript->pGossipSelect = &GossipSelect_npc_tyrande_whisperwind; - newscript->GetAI = &GetAI_npc_tyrande_whisperwind; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h b/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h deleted file mode 100644 index bfc9a54dfd9..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_HYJAL_H -#define DEF_HYJAL_H - -#define ERROR_INST_DATA "TSCR: Instance data not set properly for Mount Hyjal. Encounters will be buggy." - -enum eTypes -{ - WORLD_STATE_WAVES = 2842, - WORLD_STATE_ENEMY = 2453, - WORLD_STATE_ENEMYCOUNT = 2454, - - DATA_ANETHERON = 1, - DATA_ANETHERONEVENT = 2, - DATA_ARCHIMONDE = 3, - DATA_ARCHIMONDEEVENT = 4, - DATA_AZGALOR = 5, - DATA_AZGALOREVENT = 6, - DATA_JAINAPROUDMOORE = 7, - DATA_KAZROGAL = 8, - DATA_KAZROGALEVENT = 9, - DATA_RAGEWINTERCHILL = 10, - DATA_RAGEWINTERCHILLEVENT = 11, - DATA_THRALL = 12, - DATA_TYRANDEWHISPERWIND = 13, - DATA_TRASH = 14, - DATA_RESET_TRASH_COUNT = 15, - DATA_ALLIANCE_RETREAT = 16, - DATA_HORDE_RETREAT = 17, - DATA_RAIDDAMAGE = 18, - DATA_RESET_RAIDDAMAGE = 19, - TYPE_RETREAT = 20 -}; -#endif - diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp deleted file mode 100644 index 3c12b54f3f4..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp +++ /dev/null @@ -1,1157 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: HyjalAI -SD%Complete: 90 -SDComment: -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjalAI.h" -#include "hyjal_trash.h" -#include "MapManager.h" -#include "Language.h" -#include "Chat.h" -#include "Object.h" - -#define SPAWN_GARG_GATE 0 -#define SPAWN_WYRM_GATE 1 -#define SPAWN_NEAR_TOWER 2 - -#define YELL_HURRY "Hurry, we don't have much time" - -// Locations for summoning gargoyls and frost wyrms in special cases -float SpawnPointSpecial[3][3]= -{ - {5497.08, -2493.23, 1535.72}, //spawn point for the gargoyles near the horde gate - {5624.53, -2548.12, 1551.54}, //spawn point for the frost wyrm near the horde gate - {5604.41, -2811.98, 1547.77} //spawn point for the gargoyles and wyrms near the horde tower -}; - -// Locations for summoning waves in Alliance base -float AllianceBase[4][3]= -{ - {4928.48, -1526.38, 1326.83}, - {4923.54, -1514.29, 1327.98}, - {4928.41, -1510.35, 1327.99}, - {4938.35, -1521.00, 1326.69} -}; - -float JainaDummySpawn[2][4]= -{ - {5497.01, -2719.03, 1483.08, 2.90426}, - {5484.98, -2721.69, 1483.39, 6.00656} -}; - -// Locations for summoning waves in Horde base -float HordeBase[4][3]= -{ - {5458.01, -2340.27, 1459.60}, - {5466.01, -2334.69, 1460.06}, - {5468.45, -2355.13, 1459.99}, - {5479.06, -2344.16, 1461.74} -}; - -// Lady Jaina's waypoints when retreathing -float JainaWPs[2][3]= -{ - {5078.56, -1789.79, 1320.73},//next to the small stairs - {5037.38, -1778.39, 1322.61},//center of alliance base -}; - -float InfernalPos[8][3]=//spawn points for the infernals in the horde base -{ - {5453.59, -2764.52, 1493.50}, - {5478.4, -2781.77, 1497.52}, - {5506.09, -2780.53, 1496.32}, - {5532.1, -2763.42, 1492.37}, - {5544.16, -2733.99, 1487.14}, - {5536.19, -2708.18, 1480.01}, - {5510.16, -2691.75, 1479.66}, - {5482.39, -2689.19, 1481.09} -}; - -float InfernalSPWP[26][4]=//spawn points for the infernals in the horde base used in the cleaning wave -{ - {5490.96, -2718.72, 1482.96, 0.49773}, - {5449.51, -2723.32, 1485.69, 2.69685}, - {5520.83, -2624.68, 1483.82, 1.20459}, - {5558.28, -2629.26, 1485.76, 0.37992}, - {5567.97, -2758.69, 1494.10, 5.04125}, - {5384.90, -2793.47, 1503.90, 5.55412}, - {5495.33, -2814.06, 1501.56, 1.12055}, - {5472.63, -2929.39, 1538.31, 1.95777}, - {5334.72, -2952.29, 1534.34, 0.50869}, - {5398.36, -2872.46, 1512.38, 0.76787}, - {5514.39, -2768.63, 1492.30, 1.55721}, - {5598.91, -2703.75, 1495.64, 2.56644}, - {5467.80, -2655.93, 1482.27, 0.85819}, - {5399.83, -2985.24, 1545.04, 5.92559}, - {5232.13, -2967.05, 1553.09, 5.41351}, - {5272.02, -3082.52, 1567.09, 3.40681}, - {5343.26, -3120.71, 1582.92, 3.16727}, - {5371.26, -3175.24, 1587.41, 6.10466}, - {5434.67, -3177.91, 1579.25, 2.77850}, - {5237.39, -3149.25, 1593.59, 0.83855}, - {5202.15, -3016.64, 1566.28, 3.31256}, - {5302.54, -2914.37, 1528.53, 3.37146}, - {5439.04, -2834.81, 1508.80, 2.14231}, - {5421.33, -2771.04, 1494.28, 6.06223}, - {5549.76, -2692.93, 1482.68, 2.19414}, - {5459.78, -2755.71, 1490.68, 1.05139} -}; - -float VeinPos[14][8]=//spawn points of the ancient gem veins -{ - {5184.84, -1982.59, 1382.66, 2.58079, 0, 0, 0.960944, 0.276742}, //alliance - {5107.66, -2071.16, 1368.37, 2.65148, 0, 0, 0.970124, 0.242611}, //alliance - {5040.53, -2227.65, 1403.17, 3.35049, 0, 0, 0.99455, -0.104257}, //alliance - {5187.59, -2453.12, 1455.51, 5.87943, 0, 0, 0.20051, -0.979692}, //alliance - {5429.43, -2340.65, 1465.38, 4.7681, 0, 0, 0.687138, -0.726527}, //alliance - {5463.99, -2315.95, 1470.29, 1.52045, 0, 0, 0.689084, 0.724682}, //alliance - {5624.65, -2495.09, 1510.11, 0.0124869, 0, 0, 0.00624342, 0.999981}, //alliance - {5285.41, -3348.32, 1663.01, 1.57152, 0, 0, 0.707362, 0.706852}, //horde - {5417.69, -3372.52, 1656.31, 0.361993, 0, 0, 0.18001, 0.983665}, //horde - {5315.34, -3238.32, 1622.88, 3.03627, 0, 0, 0.998614, 0.0526347}, //horde - {5303.4, -3096.44, 1596.41, 1.72073, 0, 0, 0.758081, 0.65216}, //horde - {5265.13, -3177.27, 1616.22, 0.813604, 0, 0, 0.395674, 0.918391}, //horde - {5374.3, -3420.59, 1653.43, 1.45762, 0, 0, 0.665981, 0.745969}, //horde - {5441.54, -3321.59, 1651.55, 0.258306, 0, 0, 0.128794, 0.991671} //horde -}; - -float AllianceOverrunGargPos[5][4]=//gargoyle spawn points in the alliance overrun -{ - {5279.94, -2049.68, 1311.38, 0},//garg1 - {5289.15, -2219.06, 1291.12, 0},//garg2 - {5202.07, -2136.10, 1305.07, 2.8},//garg3 - {5071.52, -2425.63, 1454.48, 5.54},//garg4 - {5120.65, -2467.92, 1463.93, 2.54}//garg5 -}; - -float AllianceFirePos[92][8]=//spawn points for the fire visuals (GO) in the alliance base -{ - {5039.9, -1796.84, 1323.88, 2.59222, 0, 0, 0.962511, 0.271243}, - {5087.2, -1795.2, 1320.68, 1.03946, 0, 0, 0.496644, 0.867954}, - {5112.68, -1806.66, 1359.93, 1.37799, 0, 0, 0.63576, 0.771887}, - {5095.61, -1793.27, 1359.78, 0.580806, 0, 0, 0.286338, 0.958129}, - {5090.43, -1784.45, 1360.44, 0.796784, 0, 0, 0.387937, 0.921686}, - {5139.25, -1783.11, 1359.39, 3.30849, 0, 0, 0.99652, -0.0833509}, - {5112.16, -1763.72, 1361.35, 5.10312, 0, 0, 0.556388, -0.830922}, - {4981.18, -1793.98, 1335.7, 3.23072, 0, 0, 0.999007, -0.0445498}, - {4996.57, -1766.75, 1341.62, 3.5331, 0, 0, 0.980902, -0.194505}, - {4983.74, -1769.25, 1345.75, 3.79228, 0, 0, 0.947541, -0.319635}, - {4996.01, -1774.43, 1330.71, 3.07364, 0, 0, 0.999423, 0.0339693}, - {5094.2, -1726.13, 1330.55, 1.56175, 0, 0, 0.703901, 0.710298}, - {5079.82, -1721.24, 1336.26, 1.18868, 0, 0, 0.559964, 0.828517}, - {5077.68, -1717.15, 1327.78, 0.0145145, 0, 0, 0.00725717, 0.999974}, - {5122.27, -1738.22, 1341.67, 0.835256, 0, 0, 0.405593, 0.914054}, - {5131.88, -1741.15, 1335.25, 2.15472, 0, 0, 0.880712, 0.473653}, - {5196.93, -1772.99, 1345.2, 0.128397, 0, 0, 0.0641544, 0.99794}, - {5225.33, -1756.06, 1344.17, 3.04223, 0, 0, 0.998766, 0.0496599}, - {5224.84, -1767.05, 1360.06, 3.19538, 0, 0, 0.999638, -0.0268922}, - {5202.05, -1763.47, 1361.68, 2.59455, 0, 0, 0.962826, 0.270122}, - {5194.74, -1766.66, 1356.94, 0.0734191, 0, 0, 0.0367013, 0.999326}, - {5159.67, -1832.97, 1344.5, 5.17457, 0, 0, 0.526356, -0.850264}, - {5096.17, -1858.73, 1332.46, 5.30021, 0, 0, 0.471939, -0.881631}, - {5110.7, -1856.59, 1342.84, 5.97564, 0, 0, 0.153167, -0.9882}, - {5109.76, -1855.3, 1332.38, 4.89572, 0, 0, 0.639411, -0.768865}, - {5068.95, -1837.37, 1328.81, 2.61569, 0, 0, 0.965628, 0.25993}, - {5064.4, -1824.77, 1329.02, 2.16409, 0, 0, 0.88292, 0.469524}, - {5059.89, -1848.79, 1329.59, 0.0709955, 0, 0, 0.0354903, 0.99937}, - {5014.37, -1851.39, 1322.56, 4.66949, 0, 0, 0.722111, -0.691777}, - {5025.1, -1848.27, 1323.39, 4.44565, 0, 0, 0.794854, -0.606801}, - {4942.63, -1890.13, 1326.59, 3.28719, 0, 0, 0.997351, -0.0727343}, - {4937.95, -1888.71, 1352.41, 3.41678, 0, 0, 0.990549, -0.13716}, - {4922.48, -1881.92, 1352.41, 5.03077, 0, 0, 0.586075, -0.810257}, - {4915.35, -1894.32, 1351.24, 6.22457, 0, 0, 0.0293048, -0.999571}, - {4922.71, -1904.84, 1352.56, 1.37866, 0, 0, 0.63602, 0.771672}, - {4932.89, -1905.49, 1352.56, 1.89702, 0, 0, 0.812549, 0.582893}, - {5011.83, -1861.05, 1345.86, 4.43777, 0, 0, 0.797239, -0.603664}, - {5011.83, -1861.05, 1363.26, 4.748, 0, 0, 0.694406, -0.719583}, - {5021.46, -1858.35, 1342.17, 4.86188, 0, 0, 0.652329, -0.757936}, - {4995.02, -1698.3, 1370.38, 6.15779, 0, 0, 0.0626579, -0.998035}, - {5119.85, -1728.9, 1336.04, 5.87112, 0, 0, 0.204579, -0.97885}, - {5214.75, -1751.02, 1342.5, 5.08965, 0, 0, 0.561972, -0.827156}, - {5075.04, -1822.43, 1328.87, 3.99951, 0, 0, 0.9094, -0.415924}, - {5057.09, -1823.32, 1350.35, 3.88169, 0, 0, 0.93231, -0.361659}, - {4984.6, -1816.99, 1329.21, 3.05308, 0, 0, 0.999021, 0.0442417}, - {4983.35, -1811.55, 1356.82, 3.33975, 0, 0, 0.995096, -0.098917}, - {4984.11, -1825.73, 1350.76, 2.26375, 0, 0, 0.905211, 0.424962}, - {4968.47, -1786.46, 1354.09, 3.07663, 0, 0, 0.999473, 0.0324733}, - {5061.82, -1751.16, 1339.07, 5.94727, 0, 0, 0.167171, -0.985928}, - {5063.75, -1763, 1351.91, 0.759707, 0, 0, 0.370784, 0.928719}, - {5078.65, -1708.26, 1353.9, 1.27022, 0, 0, 0.593264, 0.805008}, - {4983.19, -1755.96, 1331.13, 4.28221, 0, 0, 0.841733, -0.539894}, - {4972.76, -1755.3, 1332.5, 4.21938, 0, 0, 0.858276, -0.513188}, - {4961.65, -1760.82, 1351.69, 3.56515, 0, 0, 0.977659, -0.210198}, - {5086.45, -1779.83, 1321.62, 6.23157, 0, 0, 0.0258051, -0.999667}, - {5063.15, -1756.74, 1328.56, 0.886926, 0, 0, 0.42907, 0.903271}, - {5042.45, -1800.61, 1323.88, 2.50093, 0, 0, 0.949131, 0.31488}, - {5084.74, -1725.35, 1327.89, 1.65034, 0, 0, 0.734663, 0.678432}, - {4993.25, -1758.1, 1331.07, 3.49995, 0, 0, 0.98399, -0.178223}, - {5078.53, -1867.85, 1348.91, 5.85612, 0, 0, 0.211913, -0.977288}, - {5080.74, -1869.73, 1333.18, 6.18206, 0, 0, 0.0505424, -0.998722}, - {5089.55, -1894.13, 1356.08, 1.52072, 0, 0, 0.689181, 0.724589}, - {5113.24, -1899.49, 1363.77, 1.50108, 0, 0, 0.682034, 0.731321}, - {4984.18, -1907.69, 1325.62, 3.82193, 0, 0, 0.942698, -0.333646}, - {5094.14, -2432.08, 1429.38, 4.70083, 0, 0, 0.711182, -0.703007}, - {5329.89, -2113.30, 1281.06, 5.60560, 0, 0, 0.332347, -0.943157}, - {5170.87, -2148.13, 1278.32, 1.63540, 0, 0, 0.729573, 0.683903 }, - {5132.94, -1960.25, 1367.8, 3.69787, 0, 0, 0.961568, -0.274566}, - {5280.82, -2351.55, 1431.57, 4.46913, 0, 0, 0.787677, -0.616088}, - {5176.78, -2121.43, 1295.27, 3.24153, 0, 0, 0.998752, -0.04995}, - {5332.75, -2101.41, 1296.37, 5.50350, 0, 0, 0.380043, -0.924969}, - {5265.70, -2050.27, 1287.57, 0.50051, 0, 0, 0.247655, 0.968848 }, - {5194.21, -2129.89, 1274.04, 3.08053, 0, 0, 0.999534, 0.0305272}, - {5225.81, -1985.50, 1364.15, 0.37247, 0, 0, 0.185163, 0.982708 }, - {5339.46, -2204.47, 1280.45, 0.99921, 0, 0, 0.479081, 0.877771 }, - {5269.63, -2020.57, 1299.62, 3.00201, 0, 0, 0.997566, 0.0697332}, - {5111.54, -2445.70, 1435.31, 2.70983, 0, 0, 0.976788, 0.214207 }, - {5111.24, -1901.14, 1355.33, 1.61028, 0, 0, 0.720929, 0.693009 }, - {5310.42, -2207.82, 1277.46, 0.50441, 0, 0, 0.249544, 0.968363 }, - {5150.81, -2042.13, 1394.3, 2.21031, 0, 0, 0.893534, 0.448995 }, - {5224.84, -2376.61, 1366.33, 5.0621, 0, 0, 0.573311, -0.819338}, - {5105.41, -2454.86, 1446.16, 4.64584, 0, 0, 0.730239, -0.683191}, - {5309.65, -2188.28, 1266.84, 5.56631, 0, 0, 0.350811, -0.936446}, - {5281.46, -2047.82, 1287.67, 2.44909, 0, 0, 0.940652, 0.339373 }, - {5325.45, -2189.41, 1309.6, 6.23783, 0, 0, 0.0226771, -0.999743}, - {5190.96, -2142.54, 1293.03, 6.25668, 0, 0, 0.0132544, -0.999912}, - {5089.99, -2467.49, 1441.8, 0.77381, 0, 0, 0.377326, 0.92608 }, - {5195.08, -2129.01, 1285.36, 3.55727, 0, 0, 0.978480, -0.206344}, - {5353.76, -2116.28, 1299.27, 6.17894, 0, 0, 0.0521006, -0.998642}, - {5271.14, -2037.38, 1299.24, 4.07879, 0, 0, 0.892201, -0.451638}, - {5332.5 , -2181.28, 1279.95, 4.6906, 0, 0, 0.714768, -0.699362}, - {5108.2 , -2429.84, 1427.73, 4.5194, 0, 0, 0.771943, -0.635691} -}; - -float HordeFirePos[65][8]=//spawn points for the fire visuals (GO) in the horde base -{ - {5524.11, -2612.73, 1483.38, 1.96198, 0, 0, 0.831047, 0.556202}, - {5514.42, -2617.19, 1505.77, 1.82453, 0, 0, 0.790892, 0.611956}, - {5510.21, -2624.77, 1485.34, 1.71065, 0, 0, 0.754783, 0.655974}, - {5570.72, -2619.04, 1487.62, 0.728898, 0, 0, 0.356435, 0.93432}, - {5570.29, -2639.37, 1487.31, 1.49308, 0, 0, 0.679104, 0.734042}, - {5583.56, -2637.2, 1503.78, 1.46559, 0, 0, 0.668951, 0.743307}, - {5571.53, -2626.81, 1510.99, 0.362107, 0, 0, 0.180066, 0.983654}, - {5545.97, -2659.62, 1489.64, 5.07055, 0, 0, 0.569845, -0.821752}, - {5557.44, -2675.91, 1482.58, 1.70118, 0, 0, 0.751671, 0.659539}, - {5594.98, -2742.31, 1495.51, 4.5993, 0, 0, 0.74594, -0.666013}, - {5599.65, -2755.6, 1505.05, 1.66896, 0, 0, 0.740947, 0.671564}, - {5565.95, -2774.75, 1499.48, 6.22425, 0, 0, 0.0294611, -0.999566}, - {5567.1, -2769.7, 1511.17, 5.99257, 0, 0, 0.144799, -0.989461}, - {5572.84, -2774.16, 1527.06, 0.836428, 0, 0, 0.406129, 0.913816}, - {5538.32, -2805.94, 1498.87, 4.30082, 0, 0, 0.836674, -0.547701}, - {5515.66, -2801.74, 1503.53, 5.57316, 0, 0, 0.347602, -0.937642}, - {5516.76, -2827.14, 1501.15, 0.35026, 0, 0, 0.174236, 0.984704}, - {5536.13, -2813.51, 1537.21, 4.51681, 0, 0, 0.772765, -0.634692}, - {5525.05, -2825.16, 1538.53, 0.489275, 0, 0, 0.242205, 0.970225}, - {5534.42, -2815.45, 1562.84, 4.62834, 0, 0, 0.736191, -0.676774}, - {5519.64, -2831.12, 1526.46, 0.611008, 0, 0, 0.300774, 0.953696}, - {5551.04, -2827.55, 1523.5, 3.35206, 0, 0, 0.994468, -0.10504}, - {5469.22, -2802.87, 1503.5, 4.99509, 0, 0, 0.600436, -0.799673}, - {5427.8, -2737.26, 1487.12, 1.78673, 0, 0, 0.779186, 0.626793}, - {5454.1, -2709.1, 1485.92, 3.03552, 0, 0, 0.998594, 0.0530137}, - {5436.3, -2718.2, 1506.02, 2.7567, 0, 0, 0.981539, 0.191261}, - {5412.6, -2740.55, 1510.79, 2.98446, 0, 0, 0.996915, 0.0784832}, - {5406.12, -2752.48, 1521.01, 2.05769, 0, 0, 0.856705, 0.515807}, - {5445.24, -2676.35, 1521.89, 2.91378, 0, 0, 0.99352, 0.113661}, - {5481.4, -2665.08, 1482.23, 4.30001, 0, 0, 0.836895, -0.547363}, - {5443.51, -2675.44, 1487.12, 2.90986, 0, 0, 0.993295, 0.115606}, - {5391.72, -2647.3, 1528.9, 3.76987, 0, 0, 0.951063, -0.308997}, - {5421.09, -2734.12, 1521.01, 2.70567, 0, 0, 0.97634, 0.216242}, - {5405.39, -2710.33, 1533.77, 2.51324, 0, 0, 0.951052, 0.309032}, - {5423.96, -2703.76, 1516.34, 2.79206, 0, 0, 0.984767, 0.173879}, - {5444.75, -2735.23, 1486.37, 2.22657, 0, 0, 0.897155, 0.441715}, - {5570.98, -2747.91, 1495.7, 5.14433, 0, 0, 0.53915, -0.84221}, - {5567.79, -2673.9, 1484.66, 2.72529, 0, 0, 0.978415, 0.20665}, - {5600.71, -2696.8, 1500.42, 0.443704, 0, 0, 0.220036, 0.975492}, - {5600.7, -2693.04, 1515.2, 5.16003, 0, 0, 0.532522, -0.846416}, - {5627.56, -2839.66, 1510.53, 5.41527, 0, 0, 0.420463, -0.907309}, - {5622.02, -2868.71, 1516.22, 2.25482, 0, 0, 0.903303, 0.429002}, - {5586.61, -2878.97, 1510.34, 4.55604, 0, 0, 0.76017, -0.649724}, - {5583.78, -2843.71, 1509.54, 5.35715, 0, 0, 0.44665, -0.894709}, - {5580.95, -2811.3, 1513.3, 3.57587, 0, 0, 0.976518, -0.215434}, - {5542.52, -2869.31, 1523.13, 5.23304, 0, 0, 0.501275, -0.865288}, - {5557.35, -2866.36, 1518.76, 4.48299, 0, 0, 0.783388, -0.621533}, - {5380.91, -2849.36, 1512.81, 3.90962, 0, 0, 0.927168, -0.374646}, - {5395.76, -2881.41, 1521.11, 4.28426, 0, 0, 0.84118, -0.540755}, - {5374.87, -2859.63, 1528.98, 3.30252, 0, 0, 0.996765, -0.0803745}, - {5356.07, -2854.66, 1520.34, 5.83933, 0, 0, 0.220108, -0.975475}, - {5363.01, -2975.72, 1539.02, 4.13738, 0, 0, 0.87859, -0.477576}, - {5336.85, -2980.74, 1561.24, 5.11126, 0, 0, 0.553001, -0.83318}, - {5335.23, -2974.62, 1540.05, 5.04451, 0, 0, 0.580496, -0.814263}, - {5422.37, -2998.87, 1549.98, 4.51831, 0, 0, 0.772288, -0.635272}, - {5405.54, -3014.6, 1562.16, 5.86761, 0, 0, 0.206298, -0.978489}, - {5427.96, -3019.4, 1561.58, 3.53498, 0, 0, 0.980718, -0.19543}, - {5348.12, -2977.84, 1582.47, 3.94025, 0, 0, 0.921323, -0.388799}, - {5331.12, -2993.71, 1576.14, 0.0642734, 0, 0, 0.0321311, 0.999484}, - {5321.63, -2986.55, 1552.2, 5.29503, 0, 0, 0.474219, -0.880407}, - {5292.1, -2914.36, 1529.52, 2.9742, 0, 0, 0.996499, 0.083601}, - {5281.77, -2926.5, 1530.62, 1.67829, 0, 0, 0.744071, 0.6681}, - {5287.19, -2909.94, 1543.49, 3.31192, 0, 0, 0.996376, -0.0850591}, - {5534.15, -2679.35, 1483.61, 0.428685, 0, 0, 0.212705, 0.977116}, - {5545.43, -2647.82, 1483.05, 5.38848, 0, 0, 0.432578, -0.901596} -}; - -hyjalAI::hyjalAI(Creature *c) : npc_escortAI(c), Summons(me) -{ - pInstance = c->GetInstanceData(); - VeinsSpawned[0] = false; - VeinsSpawned[1] = false; - for (uint8 i=0; i<14; ++i) - VeinGUID[i] = 0; - InfernalCount = 0; - TeleportTimer = 1000; - Overrun = false; - Teleported = false; - WaitForTeleport = false; - OverrunCounter = 0; - OverrunCounter2 = 0; - InfernalPoint = 0; - RespawnTimer = 10000; - DoRespawn = false; - DoHide = false; - MassTeleportTimer = 0; - DoMassTeleport = false; -} - -void hyjalAI::JustSummoned(Creature *summoned) -{ - Summons.Summon(summoned); -} - -void hyjalAI::SummonedCreatureDespawn(Creature* summoned) -{ - Summons.Despawn(summoned); -} - -void hyjalAI::Reset() -{ - IsDummy = false; - me->setActive(true); - // GUIDs - PlayerGUID = 0; - BossGUID[0] = 0; - BossGUID[1] = 0; - - // Timers - NextWaveTimer = 10000; - CheckTimer = 0; - RetreatTimer = 1000; - - // Misc - WaveCount = 0; - EnemyCount = 0; - - // Set faction properly based on Creature entry - switch(me->GetEntry()) - { - case JAINA: - Faction = 0; - DoCast(me, SPELL_BRILLIANCE_AURA, true); - break; - - case THRALL: - Faction = 1; - break; - - case TYRANDE: - Faction = 2; - break; - } - - //Bools - EventBegun = false; - FirstBossDead = false; - SecondBossDead = false; - Summon = false; - bRetreat = false; - Debug = false; - - //Flags - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - //Initialize spells - memset(Spell, 0, sizeof(Spell)); - - //Reset Instance Data for trash count - if (pInstance) - { - if ((!pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == JAINA) || (pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == THRALL)) - { - //Reset World States - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); - pInstance->SetData(DATA_RESET_TRASH_COUNT, 0); - } - } else error_log(ERROR_INST_DATA); - - //Visibility - DoHide = true; -} - -void hyjalAI::EnterEvadeMode() -{ - if (me->GetEntry() != JAINA) - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->LoadCreaturesAddon(); - - if (me->isAlive()) - me->GetMotionMaster()->MoveTargetedHome(); - - me->SetLootRecipient(NULL); -} - -void hyjalAI::EnterCombat(Unit * /*who*/) -{ - if (IsDummy)return; - for (uint8 i = 0; i < 3; ++i) - if (Spell[i].Cooldown) - SpellTimer[i] = Spell[i].Cooldown; - - Talk(ATTACKED); -} - -void hyjalAI::MoveInLineOfSight(Unit *who) -{ - if (IsDummy) - return; - - npc_escortAI::MoveInLineOfSight(who); -} - -void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) -{ - uint32 random = rand()%4; - float SpawnLoc[3]; - - for (uint8 i = 0; i < 3; ++i) - { - SpawnLoc[i] = Base[random][i]; - } - Creature* pCreature = NULL; - switch(entry) - { - case 17906: //GARGOYLE - - if (!FirstBossDead && (WaveCount == 1 || WaveCount == 3)) - {//summon at tower - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][1]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - if (pCreature) - CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; - }else{//summon at gate - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_GARG_GATE][0]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][1]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - } - break; - case 17907: //FROST_WYRM , - if (FirstBossDead && WaveCount == 1) //summon at gate - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_WYRM_GATE][0],SpawnPointSpecial[SPAWN_WYRM_GATE][1],SpawnPointSpecial[SPAWN_WYRM_GATE][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - else - { - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0], SpawnPointSpecial[SPAWN_NEAR_TOWER][1],SpawnPointSpecial[SPAWN_NEAR_TOWER][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - if (pCreature) - CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; - } - break; - case 17908: //GIANT_INFERNAL - ++InfernalCount; - if (InfernalCount > 7) - InfernalCount = 0; - pCreature = me->SummonCreature(entry, InfernalPos[InfernalCount][0], InfernalPos[InfernalCount][1], InfernalPos[InfernalCount][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - break; - default: - pCreature = me->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - break; - - } - - if (pCreature) - { - // Increment Enemy Count to be used in World States and instance script - ++EnemyCount; - - pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pCreature->setActive(true); - switch(entry) - { - case NECROMANCER: - case ABOMINATION: - case GHOUL: - case BANSHEE: - case CRYPT_FIEND: - case GARGOYLE: - case FROST_WYRM: - case GIANT_INFERNAL: - case FEL_STALKER: - case RAGE_WINTERCHILL: - case ANETHERON: - case KAZROGAL: - case AZGALOR: - CAST_AI(hyjal_trashAI, pCreature->AI())->IsEvent = true; - break; - } - if (pInstance) - { - if (pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE) - pCreature->SetDisableReputationGain(true);//no repu for solo farming - } - // Check if Creature is a boss. - if (pCreature->isWorldBoss()) - { - if (!FirstBossDead) BossGUID[0] = pCreature->GetGUID(); - else BossGUID[1] = pCreature->GetGUID(); - CheckTimer = 5000; - } - } -} - -void hyjalAI::SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]) -{ - // 1 in 4 chance we give a rally yell. Not sure if the chance is offilike. - if (rand()%4 == 0) - Talk(RALLY); - - if (!pInstance) - { - error_log(ERROR_INST_DATA); - return; - } - InfernalCount = 0;//reset infernal count every new wave - - EnemyCount = pInstance->GetData(DATA_TRASH); - for (uint8 i = 0; i < 18; ++i) - { - if (wave[Count].Mob[i]) - SummonCreature(wave[Count].Mob[i], Base); - } - - if (!wave[Count].IsBoss) - { - uint32 stateValue = Count+1; - if (FirstBossDead) - stateValue -= 9; // Subtract 9 from it to give the proper wave number if we are greater than 8 - - // Set world state to our current wave number - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, stateValue); // Set world state to our current wave number - // Enable world state - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); // Enable world state - - pInstance->SetData(DATA_TRASH, EnemyCount); // Send data for instance script to update count - - if (!Debug) - NextWaveTimer = wave[Count].WaveTimer; - else - { - NextWaveTimer = 15000; - debug_log("TSCR: HyjalAI: debug mode is enabled. Next Wave in 15 seconds"); - } - } - else - { - // Set world state for waves to 0 to disable it. - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); - - // Set World State for enemies invading to 1. - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 1); - - Summon = false; - } - CheckTimer = 5000; -} - -void hyjalAI::StartEvent(Player* pPlayer) -{ - if (!pPlayer || IsDummy || !pInstance) - return; - - Talk(BEGIN); - - EventBegun = true; - Summon = true; - - NextWaveTimer = 15000; - CheckTimer = 5000; - PlayerGUID = pPlayer->GetGUID(); - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); - - DeSpawnVeins(); -} - -uint32 hyjalAI::GetInstanceData(uint32 Event) -{ - if (pInstance) - return pInstance->GetData(Event); - else error_log(ERROR_INST_DATA); - - return 0; -} - -void hyjalAI::Talk(uint32 id) -{ - std::list index; - for (uint8 i = 0; i < 9; ++i) - { - if (Faction == 0) // Alliance - { - if (JainaQuotes[i].id == id) - index.push_back(i); - } - else if (Faction == 1) // Horde - { - if (ThrallQuotes[i].id == id) - index.push_back(i); - } - } - - if (index.empty()) - return; // No quotes found, no use to continue - - uint8 ind = *(index.begin()) + rand()%index.size(); - - int32 YellId = 0; - if (Faction == 0) // Alliance - { - YellId = JainaQuotes[ind].textid; - } - else if (Faction == 1) // Horde - { - YellId = ThrallQuotes[ind].textid; - } - - if (YellId) - DoScriptText(YellId, me); -} - -void hyjalAI::Retreat() -{ - if (pInstance) - { - pInstance->SetData(TYPE_RETREAT,SPECIAL); - - if (Faction == 0) - { - pInstance->SetData(DATA_ALLIANCE_RETREAT, 1); - AddWaypoint(0,JainaWPs[0][0],JainaWPs[0][1],JainaWPs[0][2]); - AddWaypoint(1,JainaWPs[1][0],JainaWPs[1][1],JainaWPs[1][2]); - Start(false, false); - SetDespawnAtEnd(false);//move to center of alliance base - } - if (Faction == 1) - { - pInstance->SetData(DATA_HORDE_RETREAT, 1); - Creature* JainaDummy = me->SummonCreature(JAINA,JainaDummySpawn[0][0],JainaDummySpawn[0][1],JainaDummySpawn[0][2],JainaDummySpawn[0][3],TEMPSUMMON_TIMED_DESPAWN,60000); - if (JainaDummy) - { - JainaDummy->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - CAST_AI(hyjalAI, JainaDummy->AI())->IsDummy = true; - DummyGuid = JainaDummy->GetGUID(); - } - AddWaypoint(0,JainaDummySpawn[1][0],JainaDummySpawn[1][1],JainaDummySpawn[1][2]); - Start(false, false); - SetDespawnAtEnd(false);//move to center of alliance base - } - } - SpawnVeins(); - Overrun = true; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//cant talk after overrun event started -} - -void hyjalAI::SpawnVeins() -{ - if (Faction == 0) - { - if (VeinsSpawned[0])//prevent any buggers - return; - for (uint8 i = 0; i<7; ++i) - { - GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); - if (gem) - VeinGUID[i]=gem->GetGUID(); - } - VeinsSpawned[0] = true; - }else{ - if (VeinsSpawned[1]) - return; - for (uint8 i = 7; i<14; ++i) - { - GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); - if (gem) - VeinGUID[i]=gem->GetGUID(); - } - VeinsSpawned[1] = true; - } -} - -void hyjalAI::DeSpawnVeins() -{ - if (!pInstance) - return; - if (Faction == 1) - { - Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (!pUnit)return; - hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); - if (!ai)return; - for (uint8 i = 0; i<7; ++i) - { - if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) - gem->Delete(); - } - } else if (Faction) - { - Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_THRALL)); - if (!pUnit)return; - hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); - if (!ai)return; - for (uint8 i = 7; i<14; ++i) - { - if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) - gem->Delete(); - } - } -} - -void hyjalAI::UpdateAI(const uint32 diff) -{ - if (IsDummy) - { - if (MassTeleportTimer < diff && DoMassTeleport) - { - DoCast(me, SPELL_MASS_TELEPORT, false); - DoMassTeleport = false; - } else MassTeleportTimer -= diff; - return; - } - if (DoHide) - { - DoHide = false; - switch(me->GetEntry()) - { - case JAINA: - if (pInstance && pInstance->GetData(DATA_ALLIANCE_RETREAT)) - { - me->SetVisibility(VISIBILITY_OFF); - HideNearPos(me->GetPositionX(), me->GetPositionY()); - HideNearPos(5037.76, -1889.71); - for (uint8 i = 0; i < 92; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); - - } - else me->SetVisibility(VISIBILITY_ON); - break; - case THRALL: //thrall - if (pInstance && pInstance->GetData(DATA_HORDE_RETREAT)) - { - me->SetVisibility(VISIBILITY_OFF); - HideNearPos(me->GetPositionX(), me->GetPositionY()); - HideNearPos(5563, -2763.19); - HideNearPos(5542.2, -2629.36); - for (uint8 i = 0; i < 65; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); - - } - else me->SetVisibility(VISIBILITY_ON); - break; - } - } - if (DoRespawn) - { - if (RespawnTimer <= diff) - { - DoRespawn = false; - RespawnNearPos(me->GetPositionX(), me->GetPositionY()); - if (Faction == 0) - { - RespawnNearPos(5037.76, -1889.71); - } else if (Faction == 1) - { - RespawnNearPos(5563, -2763.19); - RespawnNearPos(5542.2, -2629.36); - } - me->SetVisibility(VISIBILITY_ON); - }else{ - RespawnTimer -= diff; - me->SetVisibility(VISIBILITY_OFF); - } - return; - } - if (Overrun) - DoOverrun(Faction, diff); - if (bRetreat) - { - if (RetreatTimer <= diff) - { - IsDummy = true; - bRetreat = false; - HideNearPos(me->GetPositionX(), me->GetPositionY()); - switch(me->GetEntry()) - { - case JAINA://jaina - HideNearPos(5037.76, -1889.71); - break; - case THRALL://thrall - HideNearPos(5563, -2763.19); - HideNearPos(5542.2, -2629.36); - HideNearPos(5603.75, -2853.12); - break; - } - me->SetVisibility(VISIBILITY_OFF); - } else RetreatTimer -= diff; - } - - if (!EventBegun) - return; - - if (Summon) - { - if (pInstance && EnemyCount) - { - EnemyCount = pInstance->GetData(DATA_TRASH); - if (!EnemyCount) - NextWaveTimer = 5000; - } - - if (NextWaveTimer <= diff) - { - if (Faction == 0) - SummonNextWave(AllianceWaves, WaveCount, AllianceBase); - else if (Faction == 1) - SummonNextWave(HordeWaves, WaveCount, HordeBase); - ++WaveCount; - } else NextWaveTimer -= diff; - } - - if (CheckTimer <= diff) - { - for (uint8 i = 0; i < 2; ++i) - { - if (BossGUID[i]) - { - Unit* pUnit = Unit::GetUnit((*me), BossGUID[i]); - if (pUnit && (!pUnit->isAlive())) - { - if (BossGUID[i] == BossGUID[0]) - { - Talk(INCOMING); - FirstBossDead = true; - } - else if (BossGUID[i] == BossGUID[1]) - { - Talk(SUCCESS); - SecondBossDead = true; - } - EventBegun = false; - CheckTimer = 0; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - BossGUID[i] = 0; - if (pInstance) - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); // Reset world state for enemies to disable it - } - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - if (!UpdateVictim()) - return; - - for (uint8 i = 0; i < 3; ++i) - { - if (Spell[i].SpellId) - { - if (SpellTimer[i] <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - Unit *pTarget = NULL; - - switch(Spell[i].TargetType) - { - case TARGETTYPE_SELF: pTarget = me; break; - case TARGETTYPE_RANDOM: pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); break; - case TARGETTYPE_VICTIM: pTarget = me->getVictim(); break; - } - - if (pTarget && pTarget->isAlive()) - { - DoCast(pTarget, Spell[i].SpellId); - SpellTimer[i] = Spell[i].Cooldown; - } - } else SpellTimer[i] -= diff; - } - } - - DoMeleeAttackIfReady(); -} -void hyjalAI::JustDied(Unit* /*killer*/) -{ - if (IsDummy)return; - me->Respawn(); - me->SetVisibility(VISIBILITY_OFF); - DoRespawn = true; - RespawnTimer = 120000; - Talk(DEATH); - Summons.DespawnAll();//despawn all wave's summons - if (pInstance) - {//reset encounter if boss is despawned (ex: thrall is killed, boss despawns, event stucks at inprogress) - if (pInstance->GetData(DATA_RAGEWINTERCHILLEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_ANETHERONEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_KAZROGALEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_AZGALOREVENT) == IN_PROGRESS) - pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); - pInstance->SetData(DATA_RESET_RAIDDAMAGE, NULL);//reset damage on die - } -} -void hyjalAI::HideNearPos(float x, float y) -{ - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - // First get all creatures. - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - // Get Creatures - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - (*itr)->SetVisibility(VISIBILITY_OFF); - (*itr)->setFaction(35);//make them friendly so mobs won't attack them - } - } -} -void hyjalAI::RespawnNearPos(float x, float y) -{ - CellPair p(Trinity::ComputeCellPair(x, y)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::RespawnDo u_do; - Trinity::WorldObjectWorker worker(me, u_do); - TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); - cell.Visit(p, obj_worker, *me->GetMap()); -} -void hyjalAI::WaypointReached(uint32 i) -{ - if (i == 1 || (i == 0 && me->GetEntry() == THRALL)) - { - me->MonsterYell(YELL_HURRY,0,0); - WaitForTeleport = true; - TeleportTimer = 20000; - if (me->GetEntry() == JAINA) - DoCast(me, SPELL_MASS_TELEPORT, false); - if (me->GetEntry() == THRALL && DummyGuid) - { - Unit* Dummy = Unit::GetUnit((*me),DummyGuid); - if (Dummy) - { - CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->DoMassTeleport = true; - CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->MassTeleportTimer = 20000; - Dummy->CastSpell(me, SPELL_MASS_TELEPORT, false); - } - } - //do some talking - //all alive guards walk near here - CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - // First get all creatures. - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive() && (*itr) != me && (*itr)->GetEntry() != JAINA) - { - if (!(*itr)->IsWithinDist(me, 60)) - (*itr)->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - float x, y, z; - (*itr)->SetDefaultMovementType(IDLE_MOTION_TYPE); - (*itr)->GetMotionMaster()->Initialize(); - float range = 10; - if (me->GetEntry() == THRALL)range = 20; - me->GetNearPoint(me, x, y, z, range, 0, me->GetAngle((*itr))); - (*itr)->GetMotionMaster()->MovePoint(0, x+irand(-5,5), y+irand(-5,5), me->GetPositionZ()); - } - } - } - } -} -void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) -{ - npc_escortAI::UpdateAI(diff); - if (WaitForTeleport) - { - if (TeleportTimer <= diff) - { - CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive()) - { - (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); - (*itr)->setFaction(35);//make them friendly so mobs won't attack them - (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - DoCast(me, SPELL_TELEPORT_VISUAL); - bRetreat = true; - RetreatTimer = 1000; - } - - WaitForTeleport = false; - Teleported = true; - }TeleportTimer -= diff; - } - if (!Teleported) - return; - Overrun = false;//execute once - switch(faction) - { - case 0://alliance - for (uint8 i = 0; i < 92; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); - - for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(GHOUL, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 3; ++i)//summon 3 abominations - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(ABOMINATION, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles - { - Creature* pUnit = me->SummonCreature(GARGOYLE, AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - pUnit->SetHomePosition(AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3]); - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - break; - case 1://horde - for (uint8 i = 0; i < 65; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); - - for (uint8 i = 0; i < 26; ++i)//summon infernals - { - Creature* pUnit = me->SummonCreature(GIANT_INFERNAL, InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - pUnit->SetHomePosition(InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3]); - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(GHOUL, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 5; ++i)//summon 5 abominations - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(ABOMINATION, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - break; - } -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h b/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h deleted file mode 100644 index 5c75465b7b4..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef SC_HYJALAI_H -#define SC_HYJALAI_H - -#include "hyjal.h" -#include "ScriptedEscortAI.h" - -// Trash Mobs summoned in waves -#define NECROMANCER 17899//done -#define ABOMINATION 17898//done -#define GHOUL 17895//done -#define BANSHEE 17905//done -#define CRYPT_FIEND 17897//done -#define GARGOYLE 17906//done -#define FROST_WYRM 17907//done -#define GIANT_INFERNAL 17908//done -#define FEL_STALKER 17916//done - -#define JAINA 17772 -#define THRALL 17852 -#define TYRANDE 17948 - -#define ANCIENT_VEIN 185557 -#define FLAMEOBJECT 182592 - -// Bosses summoned after every 8 waves -#define RAGE_WINTERCHILL 17767 -#define ANETHERON 17808 -#define KAZROGAL 17888 -#define AZGALOR 17842 -#define ARCHIMONDE 17968 - -#define SPELL_TELEPORT_VISUAL 41232 -#define SPELL_MASS_TELEPORT 16807 - -//Spells for Jaina -#define SPELL_BRILLIANCE_AURA 31260 // The database must handle this spell via creature_addon(it should, but is removed in evade..) -#define SPELL_BLIZZARD 31266 -#define SPELL_PYROBLAST 31263 -#define SPELL_SUMMON_ELEMENTALS 31264 - -//Thrall spells -#define SPELL_CHAIN_LIGHTNING 31330 -#define SPELL_SUMMON_DIRE_WOLF 31331 - -struct Wave -{ - uint32 Mob[18]; // Stores Creature Entries to be summoned in Waves - uint32 WaveTimer; // The timer before the next wave is summoned - bool IsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that -}; - -static Wave AllianceWaves[]= // Waves that will be summoned in the Alliance Base -{ // Rage Winterchill Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron - {RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, - // Anetheron Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, GHOUL, GHOUL, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - // All 8 Waves are summoned, summon Anatheron - {ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} -}; - -static Wave HordeWaves[]= // Waves that are summoned in the Horde base -{ // Kaz'Rogal Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, - // All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor - {KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, - // Azgalor Wave 1-8 - {ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, FROST_WYRM, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, - {GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, 0, 0, 0, 0, 180000, false}, - {FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, - // All 8 Waves are summoned, summon Azgalor - {AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} -}; - -enum TargetType // Used in the spell cast system for the AI -{ - TARGETTYPE_SELF = 0, - TARGETTYPE_RANDOM = 1, - TARGETTYPE_VICTIM = 2, -}; - -struct Yells -{ - uint32 id; // Used to determine the type of yell (attack, rally, etc) - int32 textid; // The text id to be yelled -}; - -enum YellId -{ - ATTACKED = 0, // Used when attacked and set in combat - BEGIN = 1, // Used when the event is begun - INCOMING = 2, // Used to warn the raid that another wave phase is coming - RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned - FAILURE = 4, // Used when raid has failed (unsure where to place) - SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase - DEATH = 6, // Used on death -}; - -static Yells JainaQuotes[]= -{ - {ATTACKED, -1534000}, - {ATTACKED, -1534001}, - {INCOMING, -1534002}, - {BEGIN, -1534003}, - {RALLY, -1534004}, - {RALLY, -1534005}, - {FAILURE, -1534006}, - {SUCCESS, -1534007}, - {DEATH, -1534008}, -}; - -static Yells ThrallQuotes[]= -{ - {ATTACKED, -1534009}, - {ATTACKED, -1534010}, - {INCOMING, -1534011}, - {BEGIN, -1534012}, - {RALLY, -1534013}, - {RALLY, -1534014}, - {FAILURE, -1534015}, - {SUCCESS, -1534016}, - {DEATH, -1534017}, -}; - -struct hyjalAI : public npc_escortAI -{ - hyjalAI(Creature *c); - - void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat - - void EnterEvadeMode(); // Send creature back to spawn location and evade. - - void EnterCombat(Unit * /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack - - void UpdateAI(const uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells. - - void JustDied(Unit* /*killer*/); // Called on death, informs the raid that they have failed. - - void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal - { - Faction = _faction; - } - - void Retreat(); // "Teleport" (teleport visual + set invisible) all friendly creatures away from the base. - - void SpawnVeins(); - void DeSpawnVeins(); - void JustSummoned(Creature *summoned); - void SummonedCreatureDespawn(Creature* summoned); - void HideNearPos(float x, float y); - void RespawnNearPos(float x, float y); - void WaypointReached(uint32 i); - void DoOverrun(uint32 faction, const uint32 diff); - void MoveInLineOfSight(Unit *who); - - void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base - - // Summons the next wave, calls SummonCreature - void SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]); - - void StartEvent(Player* player); // Begins the event by gossip click - - uint32 GetInstanceData(uint32 Event); // Gets instance data for this instance, used to check if raid has gotten past a certain point and can access the next phase - - void Talk(uint32 id); // Searches for the appropriate yell and sound and uses it to inform the raid of various things - - public: - ScriptedInstance* pInstance; - - uint64 PlayerGUID; - uint64 BossGUID[2]; - uint64 VeinGUID[14]; - - uint32 NextWaveTimer; - uint32 WaveCount; - uint32 CheckTimer; - uint32 Faction; - uint32 EnemyCount; - uint32 RetreatTimer; - - bool EventBegun; - bool FirstBossDead; - bool SecondBossDead; - bool Summon; - bool bRetreat; - bool Debug; - bool VeinsSpawned[2]; - uint8 InfernalCount; - SummonList Summons; - bool Overrun; - bool Teleported; - bool WaitForTeleport; - uint32 TeleportTimer; - uint32 OverrunCounter; - uint32 OverrunCounter2; - uint32 InfernalPoint; - uint32 RespawnTimer; - bool DoRespawn; - bool DoHide; - bool IsDummy; - uint32 MassTeleportTimer; - bool DoMassTeleport; - uint64 DummyGuid; - - struct Spell - { - uint32 SpellId; - uint32 Cooldown; - uint32 TargetType; - }Spell[3]; - - private: - uint32 SpellTimer[3]; - //std::list CreatureList; -}; -#endif - diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp deleted file mode 100644 index c4cf9ede397..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp +++ /dev/null @@ -1,1440 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" -#include "hyjalAI.h" - -#define SPELL_METEOR 33814 //infernal visual -#define SPELL_IMMOLATION 37059 -#define SPELL_FLAME_BUFFET 31724 -#define NPC_TRIGGER 21987 //World Trigger (Tiny) -#define MODEL_INVIS 11686 //invisible model - -float HordeWPs[8][3]=//basic waypoints from spawn to leader -{ - {5492.91, -2404.61, 1462.63}, - {5531.76, -2460.87, 1469.55}, - {5554.58, -2514.66, 1476.12}, - {5554.16, -2567.23, 1479.90}, - {5540.67, -2625.99, 1480.89}, - {5508.16, -2659.20, 1480.15},//random rush starts from here - {5489.62, -2704.05, 1482.18}, - {5457.04, -2726.26, 1485.10} -}; -float AllianceWPs[8][3]=//basic waypoints from spawn to leader -{ - {4896.08, -1576.35, 1333.65}, - {4898.68, -1615.02, 1329.48}, - {4907.12, -1667.08, 1321.00}, - {4963.18, -1699.35, 1340.51}, - {4989.16, -1716.67, 1335.74},//first WP in the base, after the gate - {5026.27, -1736.89, 1323.02}, - {5037.77, -1770.56, 1324.36}, - {5067.23, -1789.95, 1321.17} -}; - -float FrostWyrmWPs[3][3]=//waypoints for the frost wyrms in horde base -{ - {5580.82, -2628.83, 1528.28}, - {5550.90, -2667.16, 1505.45}, - {5459.64, -2725.91, 1484.83} -}; - -float GargoyleWPs[3][3]=//waypoints for the gargoyles in horde base -{ - {5533.66, -2634.32, 1495.33}, - {5517.88, -2712.05, 1490.54}, - {5459.64, -2725.91, 1484.83} -}; - -float FlyPathWPs[3][3]=//waypoints for the gargoyls and frost wyrms in horde base in wave 1/3 -{ - {5531.96, -2772.83, 1516.68}, - {5498.32, -2734.84, 1497.01}, - {5456.67, -2725.48, 1493.08} -}; - -float AllianceOverrunWP[55][3]=//waypoints in the alliance base used in the end in the cleaning wave -{ - {4976.37,-1708.02,1339.43},//0spawn - {4994.83,-1725.52,1333.25},//1 start - {4982.92,-1753.7,1330.69},//2 end - {4996.75,-1721.47,1332.95},//3 start - {5015.74,-1755.05,1322.49},//4 - {4998.68,-1773.44,1329.59},//5 - {4994.83,-1725.52,1333.25},//6 start - {5022.8,-1735.46,1323.53},//7 - {5052.15,-1729.02,1320.88},//8 - {5082.43,-1726.29,1327.87},//9 - {4994.83,-1725.52,1333.25},//10 start - {5018.92,-1751.14,1322.19},//11 - {5040.09,-1792.09,1322.1},//12 - {4994.83,-1725.52,1333.25},//13 start - {5023.47,-1748.1,1322.51},//14 - {5013.43,-1842.39,1322.07},//15 - {4994.83,-1725.52,1333.25},//16 start - {5020.8,-1756.86,1322.2},//17 - {5019.53,-1824.6,1321.96},//18 - {5043.42,-1853.75,1324.52},//19 - {5053.02,-1864.13,1330.36},//20 - {5062.49,-1852.47,1330.49},//21 - {5015.27, -1738.77, 1324.83},//35//start 22 - {5027.97, -1775.25, 1321.87},//34 23 - {5015.94, -1821.24, 1321.86},//33 24 - {4983.25, -1857.4, 1320.48},//32 25 - {4981.51, -1883.7, 1322.34},//31 26 - {5002.33, -1893.98, 1325.88},//30 27 - {5049.32, -1886.54, 1331.69},//29 28 - {5089.68, -1846.88, 1328.99},//28 29 - {5127.90, -1825.14, 1335.58},//27 30 - {5163.27, -1789.08, 1337.04},//26 31 - {5138.97, -1755.88, 1334.57},//25 32 - {5096.63, -1742.22, 1329.61},//24 33 - {5065.81, -1729.43, 1325.66},//23 34 - {5049.32, -1726.31, 1320.64},//22 start - {5081.07, -1902.10, 1346.36},//36 abo start - {5107.65, -1912.03, 1356.49},//37 - {5132.83, -1927.07, 1362.42},//38 - {5147.78, -1954.41, 1365.98},//39 - {5164.96, -1966.48, 1367.04},//40 - {5189.04, -1961.06, 1367.90},//41 - {5212.27, -1975.30, 1365.58},//42 - {5221.82, -1994.18, 1364.97},//43 end1 - {5202.23, -1994.94, 1367.59},//44 end2 - {5279.94, -2049.68, 1311.38},//45 garg1 - {5289.15, -2219.06, 1291.12},//46 garg2 - {5202.07, -2136.10, 1305.07},//47 garg3 - {5071.52, -2425.63, 1454.48},//48 garg4 - {5120.65, -2467.92, 1463.93},//49 garg5 - {5283.04, -2043.26, 1300.11},//50 garg target1 - {5313.22, -2207.60, 1290.06},//51 garg target2 - {5180.41, -2121.87, 1292.62},//52 garg target3 - {5088.68, -2432.04, 1441.73},//53 garg target4 - {5111.26, -2454.73, 1449.63}//54 garg target5 - -}; - -float HordeOverrunWP[21][3]=//waypoints in the horde base used in the end in the cleaning wave -{ - {5490.72,-2702.94,1482.14},//0 start - {5469.77,-2741.34,1486.95}, - {5439.47,-2771.02,1494.59}, - {5408.85,-2811.92,1505.68}, - {5423.87,-2857.80,1515.55}, - {5428.19,-2898.15,1524.61}, - {5394.59,-2930.05,1528.23}, - {5351.11,-2935.80,1532.24}, - {5312.37,-2959.06,1536.21}, - {5264.93,-2989.80,1545.70}, - {5256.63,-3056.16,1559.24}, - {5267.32,-3119.55,1575.36}, - {5305.61,-3139.88,1586.38}, - {5330.56,-3135.37,1588.58}, - {5365.87,-3139.78,1583.96}, - {5389.39,-3163.57,1582.57},//15 end - {5500.86,-2669.89,1481.04},//16 start - {5472.08,-2715.14,1483.55}, - {5450.11,-2721.47,1485.61}, - {5433.25,-2712.93,1493.02},//19 end 1 - {5429.91,-2718.44,1493.42}//20 end 2 -}; - -hyjal_trashAI::hyjal_trashAI(Creature *c) : npc_escortAI(c) -{ - pInstance = c->GetInstanceData(); - IsEvent = false; - Delay = 0; - LastOverronPos = 0; - IsOverrun = false; - OverrunType = 0; - SetupOverrun = false; - faction = 0; - useFlyPath = false; - damageTaken = 0; - Reset(); -} - -void hyjal_trashAI::DamageTaken(Unit *done_by, uint32 &damage) -{ - if (done_by->GetTypeId() == TYPEID_PLAYER || (done_by->GetTypeId() == TYPEID_UNIT && CAST_CRE(done_by)->isPet())) - { - damageTaken += damage; - if (pInstance) - pInstance->SetData(DATA_RAIDDAMAGE,damage);//store raid's damage - } -} - -void hyjal_trashAI::UpdateAI(const uint32 /*diff*/) -{ - if (IsOverrun && !SetupOverrun) - { - SetupOverrun = true; - if (faction == 0) - { - if (me->GetEntry() == GARGOYLE) - { - DummyTarget[0] = AllianceOverrunWP[50+OverrunType][0]; //+OverrunType 0 - 4 - DummyTarget[1] = AllianceOverrunWP[50+OverrunType][1]; - DummyTarget[2] = AllianceOverrunWP[50+OverrunType][2]; - } - if (me->GetEntry() == ABOMINATION) - { - for (uint8 i = 0; i < 4; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); - AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); - AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); - AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); - AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); - AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); - AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); - - AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); - AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); - AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); - AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); - AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); - AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); - AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); - AddWaypoint(18, AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2]); - me->SetHomePosition(AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 18; - Start(true, true); - break; - case 1: - AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); - AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); - AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); - AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); - AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); - AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); - AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); - - AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); - AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); - AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); - AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); - AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); - AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); - AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); - AddWaypoint(18, AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2]); - me->SetHomePosition(AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 18; - Start(true, true); - break; - default: - for (uint8 i = 22; i < 36; ++i) - AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); - - SetDespawnAtEnd(true); - LastOverronPos = 17; - Start(true, true); - break; - } - } - if (me->GetEntry() == GHOUL) - { - for (uint8 i = 0; i < 4; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(4, AllianceOverrunWP[1][0]+irand(-3,3), AllianceOverrunWP[1][1]+irand(-3,3), AllianceOverrunWP[1][2]); - AddWaypoint(5, AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2]); - me->SetHomePosition(AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 5; - Start(true, true); - break; - case 1: - AddWaypoint(4, AllianceOverrunWP[3][0]+irand(-3,3), AllianceOverrunWP[3][1]+irand(-3,3), AllianceOverrunWP[3][2]); - AddWaypoint(5, AllianceOverrunWP[4][0]+irand(-3,3), AllianceOverrunWP[4][1]+irand(-3,3), AllianceOverrunWP[4][2]); - AddWaypoint(6, AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2]); - me->SetHomePosition(AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 2: - AddWaypoint(4, AllianceOverrunWP[6][0]+irand(-3,3), AllianceOverrunWP[6][1]+irand(-3,3), AllianceOverrunWP[6][2]); - AddWaypoint(5, AllianceOverrunWP[7][0]+irand(-3,3), AllianceOverrunWP[7][1]+irand(-3,3), AllianceOverrunWP[7][2]); - AddWaypoint(6, AllianceOverrunWP[8][0]+irand(-3,3), AllianceOverrunWP[8][1]+irand(-3,3), AllianceOverrunWP[8][2]); - AddWaypoint(7, AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2]); - me->SetHomePosition(AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 7; - Start(true, true); - break; - case 3: - AddWaypoint(4, AllianceOverrunWP[10][0]+irand(-3,3), AllianceOverrunWP[10][1]+irand(-3,3), AllianceOverrunWP[10][2]); - AddWaypoint(5, AllianceOverrunWP[11][0]+irand(-3,3), AllianceOverrunWP[11][1]+irand(-3,3), AllianceOverrunWP[11][2]); - AddWaypoint(6, AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2]); - me->SetHomePosition(AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 4: - AddWaypoint(4, AllianceOverrunWP[13][0]+irand(-3,3), AllianceOverrunWP[13][1]+irand(-3,3), AllianceOverrunWP[13][2]); - AddWaypoint(5, AllianceOverrunWP[14][0]+irand(-3,3), AllianceOverrunWP[14][1]+irand(-3,3), AllianceOverrunWP[14][2]); - AddWaypoint(6, AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2]); - me->SetHomePosition(AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 5: - AddWaypoint(4, AllianceOverrunWP[16][0]+irand(-3,3), AllianceOverrunWP[16][1]+irand(-3,3), AllianceOverrunWP[16][2]); - AddWaypoint(5, AllianceOverrunWP[17][0]+irand(-3,3), AllianceOverrunWP[17][1]+irand(-3,3), AllianceOverrunWP[17][2]); - AddWaypoint(6, AllianceOverrunWP[18][0]+irand(-3,3), AllianceOverrunWP[18][1]+irand(-3,3), AllianceOverrunWP[18][2]); - AddWaypoint(7, AllianceOverrunWP[19][0]+irand(-3,3), AllianceOverrunWP[19][1]+irand(-3,3), AllianceOverrunWP[19][2]); - AddWaypoint(8, AllianceOverrunWP[20][0]+irand(-3,3), AllianceOverrunWP[20][1]+irand(-3,3), AllianceOverrunWP[20][2]); - AddWaypoint(9, AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2]); - me->SetHomePosition(AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 9; - Start(true, true); - break; - default: - for (uint8 i = 22; i < 36; ++i) - AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 17; - Start(true, true); - break; - } - } - } - if (faction == 1) - { - if (me->GetEntry() == GHOUL) - { - for (uint8 i = 0; i < 6; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); - AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); - AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); - AddWaypoint(8, HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2]); - me->SetHomePosition(HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 8; - Start(true, true); - break; - case 1: - AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); - AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); - AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); - AddWaypoint(8, HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2]); - me->SetHomePosition(HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 8; - Start(true, true); - break; - default: - for (uint8 i = 0; i < 16; ++i) - AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 21; - Start(true, true); - break; - } - } - if (me->GetEntry() == ABOMINATION) - { - for (uint8 i = 0; i < 6; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-10,10), HordeWPs[i][1]+irand(-10,10), HordeWPs[i][2]); - for (uint8 i = 0; i < 16; ++i) - AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 21; - Start(true, true); - } - } - } -} - -void hyjal_trashAI::JustDied(Unit * /*victim*/) -{ - if (!pInstance) - return; - if (IsEvent && !me->isWorldBoss()) - pInstance->SetData(DATA_TRASH, 0);//signal trash is dead - - if ((pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE && !me->isWorldBoss()) || (damageTaken < me->GetMaxHealth()/4 && me->isWorldBoss())) - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);//no loot -} - -struct mob_giant_infernalAI : public hyjal_trashAI -{ - mob_giant_infernalAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - meteor = false;//call once! - CanMove = false; - Delay = rand()%30000; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(MODEL_INVIS); - pGo = false; - pos = 0; - Reset(); - } - - bool meteor; - bool CanMove; - bool WpEnabled; - bool pGo; - uint32 pos; - uint32 spawnTimer; - uint32 FlameBuffetTimer; - bool imol; - - void Reset() - { - spawnTimer = 2000; - FlameBuffetTimer= 2000; - imol = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 0 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Delay <= diff) - { - Delay=0; - }else{ - Delay-=diff; - return; - } - if (!meteor) - { - float x,y,z; - me->GetPosition(x,y,z); - Creature* trigger = me->SummonCreature(NPC_TRIGGER,x+8,y+8,z+25+rand()%10,me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,1000); - if (trigger) - { - trigger->SetVisibility(VISIBILITY_OFF); - trigger->setFaction(me->getFaction()); - trigger->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - trigger->CastSpell(me,SPELL_METEOR,true); - } - me->GetMotionMaster()->Clear(); - meteor = true; - } else if (!CanMove){ - if (spawnTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); - CanMove = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && !pInstance->GetData(DATA_HORDE_RETREAT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } else if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && pInstance->GetData(DATA_HORDE_RETREAT)){ - //do overrun - } - } - } else spawnTimer -= diff; - } - if (!CanMove)return; - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, HordeWPs[7][0]+irand(-3,3), HordeWPs[7][1]+irand(-3,3), HordeWPs[7][2]);//HordeWPs[7] infront of thrall - Start(true, true); - SetDespawnAtEnd(false); - } - } - } - - if (!UpdateVictim()) - return; - if (!imol) - { - DoCast(me, SPELL_IMMOLATION); - imol=true; - } - if (FlameBuffetTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAME_BUFFET, true); - FlameBuffetTimer = 7000; - } else FlameBuffetTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_giant_infernal(Creature* pCreature) -{ - return new mob_giant_infernalAI(pCreature); -} - -#define SPELL_DISEASE_CLOUD 31607 -#define SPELL_KNOCKDOWN 31610 - -struct mob_abominationAI : public hyjal_trashAI -{ - mob_abominationAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 KnockDownTimer; - uint32 pos; - void Reset() - { - KnockDownTimer = 10000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - if (i == LastOverronPos && IsOverrun) - { - if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) - { - me->setDeathState(DEAD); - me->RemoveCorpse(); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!me->HasAura(SPELL_DISEASE_CLOUD)) - DoCast(me, SPELL_DISEASE_CLOUD); - if (!UpdateVictim()) - return; - if (KnockDownTimer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - KnockDownTimer = 15000+rand()%10000; - } else KnockDownTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_abomination(Creature* pCreature) -{ - return new mob_abominationAI(pCreature); -} - -#define SPELL_FRENZY 31540 - -struct mob_ghoulAI : public hyjal_trashAI -{ - mob_ghoulAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 FrenzyTimer; - uint32 pos; - uint32 MoveTimer; - bool RandomMove; - void Reset() - { - FrenzyTimer = 5000+rand()%5000; - MoveTimer = 2000; - RandomMove = false; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - if (i == LastOverronPos && IsOverrun) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); - if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) - { - me->setDeathState(DEAD); - me->RemoveCorpse(); - } - - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (FrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - FrenzyTimer = 15000+rand()%15000; - } else FrenzyTimer -= diff; - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_ghoul(Creature* pCreature) -{ - return new mob_ghoulAI(pCreature); -} - -#define SPELL_RAISE_DEAD_1 31617 -#define SPELL_RAISE_DEAD_2 31624 -#define SPELL_RAISE_DEAD_3 31625 -#define SPELL_SHADOW_BOLT 31627 - -struct mob_necromancerAI : public hyjal_trashAI -{ - mob_necromancerAI(Creature* c) : hyjal_trashAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - SummonList summons; - bool pGo; - uint32 ShadowBoltTimer; - uint32 pos; - void Reset() - { - ShadowBoltTimer = 1000+rand()%5000; - summons.DespawnAll(); - } - - void JustSummoned(Creature* summon) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true); - if (pTarget && summon) - summon->Attack(pTarget,false); - summons.Summon(summon); - } - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoSpawnCreature(17902,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - DoSpawnCreature(17902,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - case 1: - DoSpawnCreature(17903,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - DoSpawnCreature(17903,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - case 2: - DoSpawnCreature(RAND(17902,17903),3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(true, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(true, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (ShadowBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - ShadowBoltTimer = 20000+rand()%10000; - } else ShadowBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_necromancer(Creature* pCreature) -{ - return new mob_necromancerAI(pCreature); -} - -#define SPELL_BANSHEE_CURSE 31651 -#define SPELL_BANSHEE_WAIL 38183 -#define SPELL_ANTI_MAGIC_SHELL 31662 - -struct mob_bansheeAI : public hyjal_trashAI -{ - mob_bansheeAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 CourseTimer; - uint32 WailTimer; - uint32 ShellTimer; - uint32 pos; - void Reset() - { - CourseTimer = 20000+rand()%5000; - WailTimer = 15000+rand()%5000; - ShellTimer = 50000+rand()%10000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (CourseTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BANSHEE_CURSE); - CourseTimer = 20000+rand()%5000; - } else CourseTimer -= diff; - if (WailTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BANSHEE_WAIL); - WailTimer = 15000+rand()%5000; - } else WailTimer -= diff; - if (ShellTimer <= diff) - { - DoCast(me, SPELL_ANTI_MAGIC_SHELL); - ShellTimer = 50000+rand()%10000; - } else ShellTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_banshee(Creature* pCreature) -{ - return new mob_bansheeAI(pCreature); -} - -#define SPELL_WEB 28991 - -struct mob_crypt_fiendAI : public hyjal_trashAI -{ - mob_crypt_fiendAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 WebTimer; - uint32 pos; - void Reset() - { - WebTimer = 20000+rand()%5000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - - } - } - } - if (!UpdateVictim()) - return; - if (WebTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WEB); - WebTimer = 20000+rand()%5000; - } else WebTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_crypt_fiend(Creature* pCreature) -{ - return new mob_crypt_fiendAI(pCreature); -} - -#define SPELL_MANA_BURN 31729 - -struct mob_fel_stalkerAI : public hyjal_trashAI -{ - mob_fel_stalkerAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 ManaBurnTimer; - uint32 pos; - void Reset() - { - ManaBurnTimer = 9000+rand()%5000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - - } - } - } - if (!UpdateVictim()) - return; - if (ManaBurnTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MANA_BURN); - ManaBurnTimer = 9000+rand()%5000; - } else ManaBurnTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_fel_stalker(Creature* pCreature) -{ - return new mob_fel_stalkerAI(pCreature); -} - -#define SPELL_FROST_BREATH 31688 - -struct mob_frost_wyrmAI : public hyjal_trashAI -{ - mob_frost_wyrmAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 FrostBreathTimer; - uint32 pos; - uint32 MoveTimer; - - void Reset() - { - FrostBreathTimer = 5000; - MoveTimer = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 2 && pInstance && !IsOverrun) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - { - me->AddThreat(pTarget,0.0); - DoCast(pTarget, SPELL_FROST_BREATH, true); - } - } - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_TRASH, 0);//signal trash is dead - - float x,y,z; - me->GetPosition(x,y,z); - z = me->GetMap()->GetHeight(x, y, z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - me->GetMap()->CreatureRelocation(me, x,y,z,0); - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - { - CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); - npc_escortAI::UpdateAI(diff); - } - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (!useFlyPath) - { - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FrostWyrmWPs[i][0], FrostWyrmWPs[i][1], FrostWyrmWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else{//fly path FlyPathWPs - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (!me->IsWithinDist(me->getVictim(), 25)){ - if (MoveTimer <= diff) - { - me->GetMotionMaster()->MoveChase(me->getVictim()); - MoveTimer = 2000; - } else MoveTimer-=diff; - } - - if (FrostBreathTimer <= diff) - { - if (!me->IsWithinDist(me->getVictim(), 25)) - { - DoCast(me->getVictim(), SPELL_FROST_BREATH); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - FrostBreathTimer = 4000; - } - } else FrostBreathTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_frost_wyrm(Creature* pCreature) -{ - return new mob_frost_wyrmAI(pCreature); -} - -#define SPELL_GARGOYLE_STRIKE 31664 - -struct mob_gargoyleAI : public hyjal_trashAI -{ - mob_gargoyleAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - DummyTarget[0] = 0;DummyTarget[1] = 0;DummyTarget[2] = 0; - Reset(); - } - - bool pGo; - uint32 StrikeTimer; - uint32 pos; - uint32 MoveTimer; - float Zpos; - bool forcemove; - - void Reset() - { - forcemove = true; - Zpos = 10.0; - StrikeTimer = 2000+rand()%5000; - MoveTimer = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 2 && pInstance && !IsOverrun) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - { - me->AddThreat(pTarget,0.0); - DoCast(pTarget, SPELL_GARGOYLE_STRIKE, true); - } - } - } - - void JustDied(Unit *victim) - { - float x,y,z; - me->GetPosition(x,y,z); - z = me->GetMap()->GetHeight(x, y, z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - me->GetMap()->CreatureRelocation(me, x,y,z,0); - hyjal_trashAI::JustDied(victim); - } - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - { - CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); - npc_escortAI::UpdateAI(diff); - } - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (!useFlyPath) - { - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, GargoyleWPs[i][0]+irand(-10,10), GargoyleWPs[i][1]+irand(-10,10), GargoyleWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else{//fly path FlyPathWPs - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (IsOverrun && !UpdateVictim()) - { - if (faction == 0)//alliance - { - if (StrikeTimer <= diff) - { - me->CastSpell(DummyTarget[0],DummyTarget[1],DummyTarget[2],SPELL_GARGOYLE_STRIKE,false); - StrikeTimer = 2000+rand()%1000; - } else StrikeTimer -= diff; - } - } - if (!UpdateVictim()) - return; - if (!me->IsWithinDist(me->getVictim(), 20) || forcemove) - { - forcemove = false; - if (forcemove) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - me->Attack(pTarget,false); - } - if (MoveTimer <= diff) - { - float x,y,z; - me->getVictim()->GetPosition(x,y,z); - me->GetMotionMaster()->MovePoint(0,x,y,z+Zpos); - Zpos-=1.0; - if (Zpos <= 0)Zpos=0; - MoveTimer = 2000; - } else MoveTimer-=diff; - } - if (StrikeTimer <= diff) - { - if (me->IsWithinDist(me->getVictim(), 20)) - { - DoCast(me->getVictim(), SPELL_GARGOYLE_STRIKE); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - StrikeTimer = 2000+rand()%1000; - } else StrikeTimer=0; - } else StrikeTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_gargoyle(Creature* pCreature) -{ - return new mob_gargoyleAI(pCreature); -} - -#define SPELL_EXPLODING_SHOT 7896 - -struct alliance_riflemanAI : public Scripted_NoMovementAI -{ - alliance_riflemanAI(Creature *c) : Scripted_NoMovementAI(c) - { - Reset(); - } - - uint32 ExplodeTimer; - - void JustDied(Unit* /*who*/) - { - } - - void Reset() - { - ExplodeTimer = 5000+rand()%5000; - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && me->IsHostileTo(who)) - { - //float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, 30)) - AttackStart(who); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - if (ExplodeTimer <= diff) - { - if (!me->IsWithinDistInMap(me->getVictim(), 30)) - { - EnterEvadeMode(); - return; - } - int dmg = 500+rand()%700; - me->CastCustomSpell(me->getVictim(), SPELL_EXPLODING_SHOT, &dmg, 0, 0, false); - ExplodeTimer = 5000+rand()%5000; - } else ExplodeTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_alliance_rifleman(Creature* pCreature) -{ - return new alliance_riflemanAI(pCreature); -} - -void AddSC_hyjal_trash() -{ - Script *newscript = new Script; - newscript->Name = "mob_giant_infernal"; - newscript->GetAI = &GetAI_mob_giant_infernal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_abomination"; - newscript->GetAI = &GetAI_mob_abomination; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ghoul"; - newscript->GetAI = &GetAI_mob_ghoul; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_necromancer"; - newscript->GetAI = &GetAI_mob_necromancer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_banshee"; - newscript->GetAI = &GetAI_mob_banshee; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crypt_fiend"; - newscript->GetAI = &GetAI_mob_crypt_fiend; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fel_stalker"; - newscript->GetAI = &GetAI_mob_fel_stalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frost_wyrm"; - newscript->GetAI = &GetAI_mob_frost_wyrm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_gargoyle"; - newscript->GetAI = &GetAI_mob_gargoyle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "alliance_rifleman"; - newscript->GetAI = &GetAI_alliance_rifleman; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.h b/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.h deleted file mode 100644 index 21ee4bc06cc..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.h +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef SC_HYJAL_TRASH_AI_H -#define SC_HYJAL_TRASH_AI_H - -#include "hyjal.h" -#include "ScriptedEscortAI.h" - -#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies - -struct hyjal_trashAI : public npc_escortAI -{ - hyjal_trashAI(Creature *c); - - void UpdateAI(const uint32 diff); - - void JustDied(Unit* /*killer*/); - - void DamageTaken(Unit *done_by, uint32 &damage); - - public: - ScriptedInstance* pInstance; - bool IsEvent; - uint32 Delay; - uint32 LastOverronPos; - bool IsOverrun; - bool SetupOverrun; - uint32 OverrunType; - uint8 faction; - bool useFlyPath; - uint32 damageTaken; - float DummyTarget[3]; - - //private: -}; -#endif diff --git a/src/server/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp b/src/server/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp deleted file mode 100644 index e89d518c5bc..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp +++ /dev/null @@ -1,324 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Mount_Hyjal -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -enum eEnums -{ - MAX_ENCOUNTER = 5, - - GO_ANCIENT_GEM = 185557 -}; -/* Battle of Mount Hyjal encounters: -0 - Rage Winterchill event -1 - Anetheron event -2 - Kaz'rogal event -3 - Azgalor event -4 - Archimonde event -*/ - -struct instance_mount_hyjal : public ScriptedInstance -{ - instance_mount_hyjal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - std::list m_uiAncientGemGUID; - - uint64 RageWinterchill; - uint64 Anetheron; - uint64 Kazrogal; - uint64 Azgalor; - uint64 Archimonde; - uint64 JainaProudmoore; - uint64 Thrall; - uint64 TyrandeWhisperwind; - uint64 HordeGate; - uint64 ElfGate; - - uint32 Trash; - - uint32 hordeRetreat; - uint32 allianceRetreat; - bool ArchiYell; - - uint32 RaidDamage; - - #define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more." - #define YELL_EFFORTS_NAME "Archimonde" - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiAncientGemGUID.clear(); - - RageWinterchill = 0; - Anetheron = 0; - Kazrogal = 0; - Azgalor = 0; - Archimonde = 0; - JainaProudmoore = 0; - Thrall = 0; - TyrandeWhisperwind = 0; - HordeGate = 0; - ElfGate = 0; - ArchiYell = false; - RaidDamage = 0; - - Trash = 0; - - hordeRetreat = 0; - allianceRetreat = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 182060: - HordeGate = pGo->GetGUID(); - if (allianceRetreat) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - case 182061: - ElfGate = pGo->GetGUID(); - if (hordeRetreat) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - case GO_ANCIENT_GEM: - m_uiAncientGemGUID.push_back(pGo->GetGUID()); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17767: RageWinterchill = pCreature->GetGUID(); break; - case 17808: Anetheron = pCreature->GetGUID(); break; - case 17888: Kazrogal = pCreature->GetGUID(); break; - case 17842: Azgalor = pCreature->GetGUID(); break; - case 17968: Archimonde = pCreature->GetGUID(); break; - case 17772: JainaProudmoore = pCreature->GetGUID(); break; - case 17852: Thrall = pCreature->GetGUID(); break; - case 17948: TyrandeWhisperwind = pCreature->GetGUID(); break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_RAGEWINTERCHILL: return RageWinterchill; - case DATA_ANETHERON: return Anetheron; - case DATA_KAZROGAL: return Kazrogal; - case DATA_AZGALOR: return Azgalor; - case DATA_ARCHIMONDE: return Archimonde; - case DATA_JAINAPROUDMOORE: return JainaProudmoore; - case DATA_THRALL: return Thrall; - case DATA_TYRANDEWHISPERWIND: return TyrandeWhisperwind; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_RAGEWINTERCHILLEVENT: m_auiEncounter[0] = data; break; - case DATA_ANETHERONEVENT: - m_auiEncounter[1] = data; - break; - case DATA_KAZROGALEVENT: m_auiEncounter[2] = data; break; - case DATA_AZGALOREVENT: - { - m_auiEncounter[3] = data; - if (data == DONE) - { - if (ArchiYell)break; - ArchiYell = true; - - Creature* pCreature = instance->GetCreature(Azgalor); - if (pCreature) - { - Creature* pUnit = pCreature->SummonCreature(21987,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,10000); - - Map* pMap = pCreature->GetMap(); - if (pMap->IsDungeon() && pUnit) - { - pUnit->SetVisibility(VISIBILITY_OFF); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()) - { - WorldPacket data(SMSG_MESSAGECHAT, 200); - pUnit->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,YELL_EFFORTS,0,YELL_EFFORTS_NAME,i->getSource()->GetGUID()); - i->getSource()->GetSession()->SendPacket(&data); - - WorldPacket data2(SMSG_PLAY_SOUND, 4); - data2 << 10986; - i->getSource()->GetSession()->SendPacket(&data2); - } - } - } - } - } - } - break; - case DATA_ARCHIMONDEEVENT: m_auiEncounter[4] = data; break; - case DATA_RESET_TRASH_COUNT: Trash = 0; break; - - case DATA_TRASH: - if (data) Trash = data; - else Trash--; - DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash); - break; - case TYPE_RETREAT: - if (data == SPECIAL) - { - if (!m_uiAncientGemGUID.empty()) - { - for (std::list::const_iterator itr = m_uiAncientGemGUID.begin(); itr != m_uiAncientGemGUID.end(); ++itr) - { - //don't know how long it expected - DoRespawnGameObject(*itr,DAY); - } - } - } - break; - case DATA_ALLIANCE_RETREAT: - allianceRetreat = data; - HandleGameObject(HordeGate, true); - SaveToDB(); - break; - case DATA_HORDE_RETREAT: - hordeRetreat = data; - HandleGameObject(ElfGate, true); - SaveToDB(); - break; - case DATA_RAIDDAMAGE: - RaidDamage += data; - if (RaidDamage >= MINRAIDDAMAGE) - RaidDamage = MINRAIDDAMAGE; - break; - case DATA_RESET_RAIDDAMAGE: - RaidDamage = 0; - break; - } - - debug_log("TSCR: Instance Hyjal: Instance data updated for event %u (Data=%u)",type,data); - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] - << " " << allianceRetreat << " " << hordeRetreat - << " " << RaidDamage; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_RAGEWINTERCHILLEVENT: return m_auiEncounter[0]; - case DATA_ANETHERONEVENT: return m_auiEncounter[1]; - case DATA_KAZROGALEVENT: return m_auiEncounter[2]; - case DATA_AZGALOREVENT: return m_auiEncounter[3]; - case DATA_ARCHIMONDEEVENT: return m_auiEncounter[4]; - case DATA_TRASH: return Trash; - case DATA_ALLIANCE_RETREAT: return allianceRetreat; - case DATA_HORDE_RETREAT: return hordeRetreat; - case DATA_RAIDDAMAGE: return RaidDamage; - } - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4] >> allianceRetreat >> hordeRetreat >> RaidDamage; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_mount_hyjal(Map* pMap) -{ - return new instance_mount_hyjal(pMap); -} - -void AddSC_instance_mount_hyjal() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_hyjal"; - newscript->GetInstanceData = &GetInstanceData_instance_mount_hyjal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp b/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp deleted file mode 100644 index 91c9e274b83..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Captain_Skarloc -SD%Complete: 75 -SDComment: Missing adds, missing waypoints to move up to Thrall once spawned + speech before enter combat. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define SAY_ENTER -1560000 -#define SAY_TAUNT1 -1560001 -#define SAY_TAUNT2 -1560002 -#define SAY_SLAY1 -1560003 -#define SAY_SLAY2 -1560004 -#define SAY_DEATH -1560005 - -#define SPELL_HOLY_LIGHT 29427 -#define SPELL_CLEANSE 29380 -#define SPELL_HAMMER_OF_JUSTICE 13005 -#define SPELL_HOLY_SHIELD 31904 -#define SPELL_DEVOTION_AURA 8258 -#define SPELL_CONSECRATION 38385 - -struct boss_captain_skarlocAI : public ScriptedAI -{ - boss_captain_skarlocAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Holy_Light_Timer; - uint32 Cleanse_Timer; - uint32 HammerOfJustice_Timer; - uint32 HolyShield_Timer; - uint32 DevotionAura_Timer; - uint32 Consecration_Timer; - - void Reset() - { - Holy_Light_Timer = 20000 + rand()%10000; - Cleanse_Timer = 10000; - HammerOfJustice_Timer = 20000 + rand()%15000; - HolyShield_Timer = 240000; - DevotionAura_Timer = 3000; - Consecration_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - //This is not correct. Should taunt Thrall before engage in combat - DoScriptText(SAY_TAUNT1, me); - DoScriptText(SAY_TAUNT2, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - pInstance->SetData(TYPE_THRALL_PART1, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Holy_Light - if (Holy_Light_Timer <= diff) - { - DoCast(me, SPELL_HOLY_LIGHT); - Holy_Light_Timer = 30000; - } else Holy_Light_Timer -= diff; - - //Cleanse - if (Cleanse_Timer <= diff) - { - DoCast(me, SPELL_CLEANSE); - Cleanse_Timer = 10000; - } else Cleanse_Timer -= diff; - - //Hammer of Justice - if (HammerOfJustice_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); - HammerOfJustice_Timer = 60000; - } else HammerOfJustice_Timer -= diff; - - //Holy Shield - if (HolyShield_Timer <= diff) - { - DoCast(me, SPELL_HOLY_SHIELD); - HolyShield_Timer = 240000; - } else HolyShield_Timer -= diff; - - //Devotion_Aura - if (DevotionAura_Timer <= diff) - { - DoCast(me, SPELL_DEVOTION_AURA); - DevotionAura_Timer = 45000 + rand()%10000; - } else DevotionAura_Timer -= diff; - - //Consecration - if (Consecration_Timer <= diff) - { - //DoCast(me->getVictim(), SPELL_CONSECRATION); - Consecration_Timer = 5000 + rand()%5000; - } else Consecration_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_captain_skarloc(Creature* pCreature) -{ - return new boss_captain_skarlocAI (pCreature); -} - -void AddSC_boss_captain_skarloc() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_captain_skarloc"; - newscript->GetAI = &GetAI_boss_captain_skarloc; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp b/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp deleted file mode 100644 index 2c2ad96ddb7..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Epoch_Hunter -SD%Complete: 60 -SDComment: Missing spawns pre-event, missing speech to be coordinated with rest of escort event. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define SAY_ENTER1 -1560013 -#define SAY_ENTER2 -1560014 -#define SAY_ENTER3 -1560015 -#define SAY_AGGRO1 -1560016 -#define SAY_AGGRO2 -1560017 -#define SAY_SLAY1 -1560018 -#define SAY_SLAY2 -1560019 -#define SAY_BREATH1 -1560020 -#define SAY_BREATH2 -1560021 -#define SAY_DEATH -1560022 - -#define SPELL_SAND_BREATH 31914 -#define SPELL_IMPENDING_DEATH 31916 -#define SPELL_MAGIC_DISRUPTION_AURA 33834 -#define SPELL_WING_BUFFET 31475 - -struct boss_epoch_hunterAI : public ScriptedAI -{ - boss_epoch_hunterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SandBreath_Timer; - uint32 ImpendingDeath_Timer; - uint32 WingBuffet_Timer; - uint32 Mda_Timer; - - void Reset() - { - SandBreath_Timer = 8000 + rand()%8000; - ImpendingDeath_Timer = 25000 + rand()%5000; - WingBuffet_Timer = 35000; - Mda_Timer = 40000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2), me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - pInstance->SetData(TYPE_THRALL_PART4, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sand Breath - if (SandBreath_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me->getVictim(), SPELL_SAND_BREATH); - - DoScriptText(RAND(SAY_BREATH1,SAY_BREATH2), me); - - SandBreath_Timer = 10000 + rand()%10000; - } else SandBreath_Timer -= diff; - - if (ImpendingDeath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_IMPENDING_DEATH); - ImpendingDeath_Timer = 25000+rand()%5000; - } else ImpendingDeath_Timer -= diff; - - if (WingBuffet_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_WING_BUFFET); - WingBuffet_Timer = 25000+rand()%10000; - } else WingBuffet_Timer -= diff; - - if (Mda_Timer <= diff) - { - DoCast(me, SPELL_MAGIC_DISRUPTION_AURA); - Mda_Timer = 15000; - } else Mda_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_epoch_hunter(Creature* pCreature) -{ - return new boss_epoch_hunterAI (pCreature); -} - -void AddSC_boss_epoch_hunter() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_epoch_hunter"; - newscript->GetAI = &GetAI_boss_epoch_hunter; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp b/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp deleted file mode 100644 index dae0f5390b1..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Luetenant_Drake -SD%Complete: 70 -SDComment: Missing proper code for patrolling area after being spawned. Script for GO (barrels) quest 10283 -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" -#include "ScriptedEscortAI.h" - -/*###### -## go_barrel_old_hillsbrad -######*/ - -bool GOHello_go_barrel_old_hillsbrad(Player* /*pPlayer*/, GameObject* pGO) -{ - if (ScriptedInstance* pInstance = pGO->GetInstanceData()) - { - if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE) - return false; - - pInstance->SetData(TYPE_BARREL_DIVERSION, IN_PROGRESS); - } - - return false; -} - -/*###### -## boss_lieutenant_drake -######*/ - -#define SAY_ENTER -1560006 -#define SAY_AGGRO -1560007 -#define SAY_SLAY1 -1560008 -#define SAY_SLAY2 -1560009 -#define SAY_MORTAL -1560010 -#define SAY_SHOUT -1560011 -#define SAY_DEATH -1560012 - -#define SPELL_WHIRLWIND 31909 -#define SPELL_HAMSTRING 9080 -#define SPELL_MORTAL_STRIKE 31911 -#define SPELL_FRIGHTENING_SHOUT 33789 - -struct Location -{ - uint32 wpId; - float x; - float y; - float z; -}; - -static Location DrakeWP[]= -{ - {0, 2125.84, 88.2535, 54.8830}, - {1, 2111.01, 93.8022, 52.6356}, - {2, 2106.70, 114.753, 53.1965}, - {3, 2107.76, 138.746, 52.5109}, - {4, 2114.83, 160.142, 52.4738}, - {5, 2125.24, 178.909, 52.7283}, - {6, 2151.02, 208.901, 53.1551}, - {7, 2177.00, 233.069, 52.4409}, - {8, 2190.71, 227.831, 53.2742}, - {9, 2178.14, 214.219, 53.0779}, - {10, 2154.99, 202.795, 52.6446}, - {11, 2132.00, 191.834, 52.5709}, - {12, 2117.59, 166.708, 52.7686}, - {13, 2093.61, 139.441, 52.7616}, - {14, 2086.29, 104.950, 52.9246}, - {15, 2094.23, 81.2788, 52.6946}, - {16, 2108.70, 85.3075, 53.3294}, - {17, 2125.50, 88.9481, 54.7953}, - {18, 2128.20, 70.9763, 64.4221} -}; - -struct boss_lieutenant_drakeAI : public ScriptedAI -{ - boss_lieutenant_drakeAI(Creature *c) : ScriptedAI(c) {} - - bool CanPatrol; - uint32 wpId; - - uint32 Whirlwind_Timer; - uint32 Fear_Timer; - uint32 MortalStrike_Timer; - uint32 ExplodingShout_Timer; - - void Reset() - { - CanPatrol = true; - wpId = 0; - - Whirlwind_Timer = 20000; - Fear_Timer = 30000; - MortalStrike_Timer = 45000; - ExplodingShout_Timer = 25000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - //TODO: make this work - if (CanPatrol && wpId == 0) - { - me->GetMotionMaster()->MovePoint(DrakeWP[0].wpId, DrakeWP[0].x, DrakeWP[0].y, DrakeWP[0].z); - ++wpId; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Whirlwind - if (Whirlwind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - Whirlwind_Timer = 20000+rand()%5000; - } else Whirlwind_Timer -= diff; - - //Fear - if (Fear_Timer <= diff) - { - DoScriptText(SAY_SHOUT, me); - DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); - Fear_Timer = 25000+rand()%10000; - } else Fear_Timer -= diff; - - //Mortal Strike - if (MortalStrike_Timer <= diff) - { - DoScriptText(SAY_MORTAL, me); - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - MortalStrike_Timer = 20000+rand()%10000; - } else MortalStrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_lieutenant_drake(Creature* pCreature) -{ - return new boss_lieutenant_drakeAI (pCreature); -} - -void AddSC_boss_lieutenant_drake() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_barrel_old_hillsbrad"; - newscript->pGOHello = &GOHello_go_barrel_old_hillsbrad; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lieutenant_drake"; - newscript->GetAI = &GetAI_boss_lieutenant_drake; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp b/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp deleted file mode 100644 index fa0b7c14595..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Old_Hillsbrad -SD%Complete: 75 -SDComment: If thrall escort fail, all parts will reset. In future, save sub-parts and continue from last known. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define MAX_ENCOUNTER 6 - -#define THRALL_ENTRY 17876 -#define TARETHA_ENTRY 18887 -#define EPOCH_ENTRY 18096 - -#define DRAKE_ENTRY 17848 - -#define QUEST_ENTRY_DIVERSION 10283 -#define LODGE_QUEST_TRIGGER 20155 - -struct instance_old_hillsbrad : public ScriptedInstance -{ - instance_old_hillsbrad(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 mBarrelCount; - uint32 mThrallEventCount; - - uint64 ThrallGUID; - uint64 TarethaGUID; - uint64 EpochGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - mBarrelCount = 0; - mThrallEventCount = 0; - ThrallGUID = 0; - TarethaGUID = 0; - EpochGUID = 0; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - - debug_log("TSCR: Instance Old Hillsbrad: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void UpdateQuestCredit() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->KilledMonsterCredit(LODGE_QUEST_TRIGGER,0); - } - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case THRALL_ENTRY: - ThrallGUID = pCreature->GetGUID(); - break; - case TARETHA_ENTRY: - TarethaGUID = pCreature->GetGUID(); - break; - case EPOCH_ENTRY: - EpochGUID = pCreature->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - Player* pPlayer = GetPlayerInMap(); - - if (!pPlayer) - { - debug_log("TSCR: Instance Old Hillsbrad: SetData (Type: %u Data %u) cannot find any player.", type, data); - return; - } - - switch(type) - { - case TYPE_BARREL_DIVERSION: - { - if (data == IN_PROGRESS) - { - if (mBarrelCount >= 5) - return; - - ++mBarrelCount; - DoUpdateWorldState(WORLD_STATE_OH, mBarrelCount); - - debug_log("TSCR: Instance Old Hillsbrad: go_barrel_old_hillsbrad count %u",mBarrelCount); - - m_auiEncounter[0] = IN_PROGRESS; - - if (mBarrelCount == 5) - { - UpdateQuestCredit(); - pPlayer->SummonCreature(DRAKE_ENTRY, 2128.43, 71.01, 64.42, 1.74, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000); - m_auiEncounter[0] = DONE; - } - } - break; - } - case TYPE_THRALL_EVENT: - { - if (data == FAIL) - { - if (mThrallEventCount <= 20) - { - ++mThrallEventCount; - m_auiEncounter[1] = NOT_STARTED; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); - m_auiEncounter[2] = NOT_STARTED; - m_auiEncounter[3] = NOT_STARTED; - m_auiEncounter[4] = NOT_STARTED; - m_auiEncounter[5] = NOT_STARTED; - } - else if (mThrallEventCount > 20) - { - m_auiEncounter[1] = data; - m_auiEncounter[2] = data; - m_auiEncounter[3] = data; - m_auiEncounter[4] = data; - m_auiEncounter[5] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); - } - } - else - m_auiEncounter[1] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall escort event adjusted to data %u.",data); - break; - } - case TYPE_THRALL_PART1: - m_auiEncounter[2] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part I adjusted to data %u.",data); - break; - case TYPE_THRALL_PART2: - m_auiEncounter[3] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part II adjusted to data %u.",data); - break; - case TYPE_THRALL_PART3: - m_auiEncounter[4] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part III adjusted to data %u.",data); - break; - case TYPE_THRALL_PART4: - m_auiEncounter[5] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part IV adjusted to data %u.",data); - break; - } - } - - uint32 GetData(uint32 data) - { - switch(data) - { - case TYPE_BARREL_DIVERSION: - return m_auiEncounter[0]; - case TYPE_THRALL_EVENT: - return m_auiEncounter[1]; - case TYPE_THRALL_PART1: - return m_auiEncounter[2]; - case TYPE_THRALL_PART2: - return m_auiEncounter[3]; - case TYPE_THRALL_PART3: - return m_auiEncounter[4]; - case TYPE_THRALL_PART4: - return m_auiEncounter[5]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THRALL: - return ThrallGUID; - case DATA_TARETHA: - return TarethaGUID; - case DATA_EPOCH: - return EpochGUID; - } - return 0; - } -}; -InstanceData* GetInstanceData_instance_old_hillsbrad(Map* pMap) -{ - return new instance_old_hillsbrad(pMap); -} - -void AddSC_instance_old_hillsbrad() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_old_hillsbrad"; - newscript->GetInstanceData = &GetInstanceData_instance_old_hillsbrad; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp b/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp deleted file mode 100644 index 08c63954db5..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp +++ /dev/null @@ -1,658 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Old_Hillsbrad -SD%Complete: 40 -SDComment: Quest support: 10283, 10284. All friendly NPC's. Thrall waypoints fairly complete, missing many details, but possible to complete escort. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -/* ContentData -npc_erozion -npc_thrall_old_hillsbrad -npc_taretha -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "old_hillsbrad.h" - -#define QUEST_ENTRY_HILLSBRAD 10282 -#define QUEST_ENTRY_DIVERSION 10283 -#define QUEST_ENTRY_ESCAPE 10284 -#define QUEST_ENTRY_RETURN 10285 -#define ITEM_ENTRY_BOMBS 25853 - -#define GOSSIP_HELLO_EROZION1 "I need a pack of Incendiary Bombs." -#define GOSSIP_HELLO_EROZION2 "[PH] Teleport please, i'm tired." - -/*###### -## npc_erozion -######*/ - -bool GossipHello_npc_erozion(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance && pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE && !pPlayer->HasItemCount(ITEM_ENTRY_BOMBS,1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - if (!pPlayer->GetQuestRewardStatus(QUEST_ENTRY_RETURN) && pPlayer->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(9778, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_erozion(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_ENTRY_BOMBS, 1); - if (msg == EQUIP_ERR_OK) - { - pPlayer->StoreNewItem(dest, ITEM_ENTRY_BOMBS, true); - } - pPlayer->SEND_GOSSIP_MENU(9515, pCreature->GetGUID()); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - } - return true; -} - -/*###### -## npc_thrall_old_hillsbrad -######*/ - -//Thrall texts -#define SAY_TH_START_EVENT_PART1 -1560023 -#define SAY_TH_ARMORY -1560024 -#define SAY_TH_SKARLOC_MEET -1560025 -#define SAY_TH_SKARLOC_TAUNT -1560026 -#define SAY_TH_START_EVENT_PART2 -1560027 -#define SAY_TH_MOUNTS_UP -1560028 -#define SAY_TH_CHURCH_END -1560029 -#define SAY_TH_MEET_TARETHA -1560030 -#define SAY_TH_EPOCH_WONDER -1560031 -#define SAY_TH_EPOCH_KILL_TARETHA -1560032 -#define SAY_TH_EVENT_COMPLETE -1560033 - -#define SAY_TH_RANDOM_LOW_HP1 -1560034 -#define SAY_TH_RANDOM_LOW_HP2 -1560035 - -#define SAY_TH_RANDOM_DIE1 -1560036 -#define SAY_TH_RANDOM_DIE2 -1560037 - -#define SAY_TH_RANDOM_AGGRO1 -1560038 -#define SAY_TH_RANDOM_AGGRO2 -1560039 -#define SAY_TH_RANDOM_AGGRO3 -1560040 -#define SAY_TH_RANDOM_AGGRO4 -1560041 - -#define SAY_TH_RANDOM_KILL1 -1560042 -#define SAY_TH_RANDOM_KILL2 -1560043 -#define SAY_TH_RANDOM_KILL3 -1560044 - -#define SAY_TH_LEAVE_COMBAT1 -1560045 -#define SAY_TH_LEAVE_COMBAT2 -1560046 -#define SAY_TH_LEAVE_COMBAT3 -1560047 - -//Taretha texts -#define SAY_TA_FREE -1560048 -#define SAY_TA_ESCAPED -1560049 - -//Misc for Thrall -#define SPELL_STRIKE 14516 -#define SPELL_SHIELD_BLOCK 12169 -#define SPELL_SUMMON_EROZION_IMAGE 33954 //if thrall dies during escort? - -#define SPEED_WALK (0.5f) -#define SPEED_RUN (1.0f) -#define SPEED_MOUNT (1.6f) - -#define THRALL_WEAPON_MODEL 22106 -#define THRALL_WEAPON_INFO 218169346 -#define THRALL_SHIELD_MODEL 18662 -#define THRALL_SHIELD_INFO 234948100 -#define THRALL_MODEL_UNEQUIPPED 17292 -#define THRALL_MODEL_EQUIPPED 18165 - -//Misc Creature entries -#define ENTRY_ARMORER 18764 -#define ENTRY_SCARLOC 17862 - -#define MOB_ENTRY_RIFLE 17820 -#define MOB_ENTRY_WARDEN 17833 -#define MOB_ENTRY_VETERAN 17860 -#define MOB_ENTRY_WATCHMAN 17814 -#define MOB_ENTRY_SENTRY 17815 - -#define MOB_ENTRY_BARN_GUARDSMAN 18092 -#define MOB_ENTRY_BARN_PROTECTOR 18093 -#define MOB_ENTRY_BARN_LOOKOUT 18094 - -#define MOB_ENTRY_CHURCH_GUARDSMAN 23175 -#define MOB_ENTRY_CHURCH_PROTECTOR 23179 -#define MOB_ENTRY_CHURCH_LOOKOUT 23177 - -#define MOB_ENTRY_INN_GUARDSMAN 23176 -#define MOB_ENTRY_INN_PROTECTOR 23180 -#define MOB_ENTRY_INN_LOOKOUT 23178 - -#define SKARLOC_MOUNT 18798 -#define SKARLOC_MOUNT_MODEL 18223 -#define EROZION_ENTRY 18723 -#define ENTRY_EPOCH 18096 - -//gossip items -#define GOSSIP_ID_START 9568 -#define GOSSIP_ID_SKARLOC1 9614 //I'm glad Taretha is alive. We now must find a way to free her... -#define GOSSIP_ITEM_SKARLOC1 "Taretha cannot see you, Thrall." -#define GOSSIP_ID_SKARLOC2 9579 //What do you mean by this? Is Taretha in danger? -#define GOSSIP_ITEM_SKARLOC2 "The situation is rather complicated, Thrall. It would be best for you to head into the mountains now, before more of Blackmoore's men show up. We'll make sure Taretha is safe." -#define GOSSIP_ID_SKARLOC3 9580 - -#define GOSSIP_ID_TARREN 9597 //tarren mill is beyond these trees -#define GOSSIP_ITEM_TARREN "We're ready, Thrall." - -#define GOSSIP_ID_COMPLETE 9578 //Thank you friends, I owe my freedom to you. Where is Taretha? I hoped to see her - -#define GOSSIP_ITEM_WALKING "[PH] Start walking." - -struct npc_thrall_old_hillsbradAI : public npc_escortAI -{ - npc_thrall_old_hillsbradAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - HadMount = false; - me->setActive(true); - } - - ScriptedInstance *pInstance; - - uint64 TarethaGUID; - - bool LowHp; - bool HadMount; - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch(i) - { - case 8: - SetRun(false); - me->SummonCreature(18764,2181.87,112.46,89.45,0.26,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 9: - DoScriptText(SAY_TH_ARMORY, me); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_MODEL); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_MODEL); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); - break; - case 10: - me->SetDisplayId(THRALL_MODEL_EQUIPPED); - break; - case 11: - SetRun(); - break; - case 15: - me->SummonCreature(MOB_ENTRY_RIFLE,2200.28,137.37,87.93,5.07,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2197.44,131.83,87.93,0.78,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2203.62,135.40,87.93,3.70,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2200.75,130.13,87.93,1.48,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 21: - me->SummonCreature(MOB_ENTRY_RIFLE,2135.80,154.01,67.45,4.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2144.36,151.87,67.74,4.46,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2142.12,154.41,67.12,4.56,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2138.08,155.38,67.24,4.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 25: - me->SummonCreature(MOB_ENTRY_RIFLE,2102.98,192.17,65.24,6.02,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2108.48,198.75,65.18,5.15,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2106.11,197.29,65.18,5.63,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2104.18,194.82,65.18,5.75,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 29: - DoScriptText(SAY_TH_SKARLOC_MEET, me); - me->SummonCreature(ENTRY_SCARLOC,2036.48,271.22,63.43,5.27,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - //temporary,skarloc should rather be triggered to walk up to thrall - break; - case 30: - SetEscortPaused(true); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetRun(false); - break; - case 31: - DoScriptText(SAY_TH_MOUNTS_UP, me); - DoMount(); - SetRun(); - break; - case 37: - //possibly regular patrollers? If so, remove this and let database handle them - me->SummonCreature(MOB_ENTRY_WATCHMAN,2124.26,522.16,56.87,3.99,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WATCHMAN,2121.69,525.37,57.11,4.01,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_SENTRY,2124.65,524.55,56.63,3.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 59: - me->SummonCreature(SKARLOC_MOUNT,2488.64,625.77,58.26,4.71,TEMPSUMMON_TIMED_DESPAWN,10000); - DoUnmount(); - HadMount = false; - SetRun(false); - break; - case 60: - me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); - //make horsie run off - SetEscortPaused(true); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pInstance->SetData(TYPE_THRALL_PART2, DONE); - SetRun(); - break; - case 64: - SetRun(false); - break; - case 68: - me->SummonCreature(MOB_ENTRY_BARN_PROTECTOR,2500.22,692.60,55.50,2.84,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_LOOKOUT,2500.13,696.55,55.51,3.38,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.55,693.64,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.94,695.81,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 71: - SetRun(); - break; - case 81: - SetRun(false); - break; - case 83: - me->SummonCreature(MOB_ENTRY_CHURCH_PROTECTOR,2627.33,646.82,56.03,4.28,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_LOOKOUT,2624.14,648.03,56.03,4.50,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2625.32,649.60,56.03,4.38,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2627.22,649.00,56.03,4.34,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - break; - case 84: - DoScriptText(SAY_TH_CHURCH_END, me); - SetRun(); - break; - case 91: - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - SetRun(false); - break; - case 93: - me->SummonCreature(MOB_ENTRY_INN_PROTECTOR,2652.71,660.31,61.93,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_LOOKOUT,2648.96,662.59,61.93,0.79,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2657.36,662.34,61.93,2.68,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2656.39,659.77,61.93,2.61,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 94: - if (uint64 TarethaGUID = pInstance->GetData64(DATA_TARETHA)) - { - if (Unit* Taretha = Unit::GetUnit((*me), TarethaGUID)) - DoScriptText(SAY_TA_ESCAPED, Taretha, me); - } - break; - case 95: - DoScriptText(SAY_TH_MEET_TARETHA, me); - pInstance->SetData(TYPE_THRALL_PART3,DONE); - SetEscortPaused(true); - break; - case 96: - DoScriptText(SAY_TH_EPOCH_WONDER, me); - break; - case 97: - DoScriptText(SAY_TH_EPOCH_KILL_TARETHA, me); - SetRun(); - break; - case 98: - //trigger epoch Yell("Thrall! Come outside and face your fate! ....") - //from here, thrall should not never be allowed to move to point 106 which he currently does. - break; - - case 106: - { - //trigger taretha to run down outside - if (Creature* Taretha = pInstance->instance->GetCreature(pInstance->GetData64(DATA_TARETHA))) - { - if (Player* pPlayer = GetPlayerForEscort()) - CAST_AI(npc_escortAI, (Taretha->AI()))->Start(false, true, pPlayer->GetGUID()); - } - - //kill credit Creature for quest - Map* pMap = me->GetMap(); - Map::PlayerList const& players = pMap->GetPlayers(); - if (!players.isEmpty() && pMap->IsDungeon()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->KilledMonsterCredit(20156,me->GetGUID()); - } - } - - //alot will happen here, thrall and taretha talk, erozion appear at spot to explain - me->SummonCreature(EROZION_ENTRY,2646.47,680.416,55.38,4.16,TEMPSUMMON_TIMED_DESPAWN,120000); - } - break; - case 108: - //last waypoint, just set Thrall invisible, respawn is turned off - me->SetVisibility(VISIBILITY_OFF); - break; - } - } - - void Reset() - { - LowHp = false; - - if (HadMount) - DoMount(); - - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - DoUnmount(); - HadMount = false; - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - me->SetDisplayId(THRALL_MODEL_UNEQUIPPED); - } - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - DoScriptText(RAND(SAY_TH_LEAVE_COMBAT1,SAY_TH_LEAVE_COMBAT2,SAY_TH_LEAVE_COMBAT3), me); - } - } - void StartWP() - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetEscortPaused(false); - } - void DoMount() - { - me->Mount(SKARLOC_MOUNT_MODEL); - me->SetSpeed(MOVE_RUN,SPEED_MOUNT); - } - void DoUnmount() - { - me->Unmount(); - me->SetSpeed(MOVE_RUN,SPEED_RUN); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(RAND(SAY_TH_RANDOM_AGGRO1,SAY_TH_RANDOM_AGGRO2,SAY_TH_RANDOM_AGGRO3,SAY_TH_RANDOM_AGGRO4), me); - if (me->IsMounted()) - { - DoUnmount(); - HadMount = true; - } - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - //TODO: make Scarloc start into event instead, and not start attack directly - case MOB_ENTRY_BARN_GUARDSMAN: - case MOB_ENTRY_BARN_PROTECTOR: - case MOB_ENTRY_BARN_LOOKOUT: - case SKARLOC_MOUNT: - case EROZION_ENTRY: - break; - default: - summoned->AI()->AttackStart(me); - break; - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_TH_RANDOM_KILL1,SAY_TH_RANDOM_KILL2,SAY_TH_RANDOM_KILL3), me); - } - void JustDied(Unit *slayer) - { - if (pInstance) - pInstance->SetData(TYPE_THRALL_EVENT,FAIL); - - // Don't do a yell if he kills self (if player goes too far or at the end). - if (slayer == me) - return; - - DoScriptText(RAND(SAY_TH_RANDOM_DIE1,SAY_TH_RANDOM_DIE2), me); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - //TODO: add his abilities'n-crap here - if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) - { - DoScriptText(RAND(SAY_TH_RANDOM_LOW_HP1,SAY_TH_RANDOM_LOW_HP2), me); - LowHp = true; - } - } -}; - -CreatureAI* GetAI_npc_thrall_old_hillsbrad(Creature* pCreature) -{ - return new npc_thrall_old_hillsbradAI(pCreature); -} - -bool GossipHello_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - { - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - pPlayer->SendPreparedQuest(pCreature->GetGUID()); - } - - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance) - { - if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE && !pInstance->GetData(TYPE_THRALL_EVENT)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WALKING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START, pCreature->GetGUID()); - } - - if (pInstance->GetData(TYPE_THRALL_PART1) == DONE && !pInstance->GetData(TYPE_THRALL_PART2)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC1, pCreature->GetGUID()); - } - - if (pInstance->GetData(TYPE_THRALL_PART2) == DONE && !pInstance->GetData(TYPE_THRALL_PART3)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TARREN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_TARREN, pCreature->GetGUID()); - } - } - return true; -} - -bool GossipSelect_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pInstance) - { - pInstance->SetData(TYPE_THRALL_EVENT,IN_PROGRESS); - pInstance->SetData(TYPE_THRALL_PART1,IN_PROGRESS); - } - - DoScriptText(SAY_TH_START_EVENT_PART1, pCreature); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())) - pEscortAI->Start(true, true, pPlayer->GetGUID()); - - CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(100.0f);//not really needed, because it will not despawn if player is too far - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); - break; - - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC2, pCreature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+20: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC3, pCreature->GetGUID()); - pCreature->SummonCreature(SKARLOC_MOUNT,2038.81,270.26,63.20,5.41,TEMPSUMMON_TIMED_DESPAWN,12000); - if (pInstance) - pInstance->SetData(TYPE_THRALL_PART2,IN_PROGRESS); - - DoScriptText(SAY_TH_START_EVENT_PART2, pCreature); - - CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); - break; - - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pInstance) - pInstance->SetData(TYPE_THRALL_PART3,IN_PROGRESS); - CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); - break; - } - return true; -} - -/*###### -## npc_taretha -######*/ - -#define GOSSIP_ID_EPOCH1 9610 //Thank you for helping Thrall escape, friends. Now I only hope -#define GOSSIP_ITEM_EPOCH1 "Strange wizard?" -#define GOSSIP_ID_EPOCH2 9613 //Yes, friends. This man was no wizard of -#define GOSSIP_ITEM_EPOCH2 "We'll get you out. Taretha. Don't worry. I doubt the wizard would wander too far away." - -struct npc_tarethaAI : public npc_escortAI -{ - npc_tarethaAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void WaypointReached(uint32 i) - { - switch(i) - { - case 6: - DoScriptText(SAY_TA_FREE, me); - break; - case 7: - me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); - break; - } - } - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_taretha(Creature* pCreature) -{ - return new npc_tarethaAI(pCreature); -} - -bool GossipHello_npc_taretha(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance && pInstance->GetData(TYPE_THRALL_PART3) == DONE && pInstance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH1, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_taretha(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH2, pCreature->GetGUID()); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - { - pInstance->SetData(TYPE_THRALL_PART4,IN_PROGRESS); - if (pInstance->GetData64(DATA_EPOCH) == 0) - pCreature->SummonCreature(ENTRY_EPOCH,2639.13,698.55,65.43,4.59,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); - - if (uint64 ThrallGUID = pInstance->GetData64(DATA_THRALL)) - { - Creature* Thrall = (Unit::GetCreature((*pCreature), ThrallGUID)); - if (Thrall) - CAST_AI(npc_thrall_old_hillsbradAI, Thrall->AI())->StartWP(); - } - } - } - return true; -} - -/*###### -## AddSC -######*/ - -void AddSC_old_hillsbrad() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_erozion"; - newscript->pGossipHello = &GossipHello_npc_erozion; - newscript->pGossipSelect = &GossipSelect_npc_erozion; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thrall_old_hillsbrad"; - newscript->pGossipHello = &GossipHello_npc_thrall_old_hillsbrad; - newscript->pGossipSelect = &GossipSelect_npc_thrall_old_hillsbrad; - newscript->GetAI = &GetAI_npc_thrall_old_hillsbrad; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_taretha"; - newscript->pGossipHello = &GossipHello_npc_taretha; - newscript->pGossipSelect = &GossipSelect_npc_taretha; - newscript->GetAI = &GetAI_npc_taretha; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h b/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h deleted file mode 100644 index 5c398cc2647..00000000000 --- a/src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_OLD_HILLSBRAD_H -#define DEF_OLD_HILLSBRAD_H - -#define TYPE_BARREL_DIVERSION 1 -#define TYPE_THRALL_EVENT 2 -#define TYPE_THRALL_PART1 3 -#define TYPE_THRALL_PART2 4 -#define TYPE_THRALL_PART3 5 -#define TYPE_THRALL_PART4 6 -#define DATA_THRALL 7 -#define DATA_TARETHA 8 -#define DATA_EPOCH 9 -#define WORLD_STATE_OH 2436 -#endif - diff --git a/src/server/scripts/kalimdor/darkshore.cpp b/src/server/scripts/kalimdor/darkshore.cpp deleted file mode 100644 index 26b42a86422..00000000000 --- a/src/server/scripts/kalimdor/darkshore.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Darkshore -SD%Complete: 100 -SDComment: Quest support: 731, 2078, 5321 -SDCategory: Darkshore -EndScriptData */ - -/* ContentData -npc_kerlonian -npc_prospector_remtravel -npc_threshwackonator -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "ScriptedFollowerAI.h" - -/*#### -# npc_kerlonian -####*/ - -enum eKerlonian -{ - SAY_KER_START = -1000434, - - EMOTE_KER_SLEEP_1 = -1000435, - EMOTE_KER_SLEEP_2 = -1000436, - EMOTE_KER_SLEEP_3 = -1000437, - - SAY_KER_SLEEP_1 = -1000438, - SAY_KER_SLEEP_2 = -1000439, - SAY_KER_SLEEP_3 = -1000440, - SAY_KER_SLEEP_4 = -1000441, - - EMOTE_KER_AWAKEN = -1000445, - - SAY_KER_ALERT_1 = -1000442, - SAY_KER_ALERT_2 = -1000443, - - SAY_KER_END = -1000444, - - SPELL_SLEEP_VISUAL = 25148, - SPELL_AWAKEN = 17536, - QUEST_SLEEPER_AWAKENED = 5321, - NPC_LILADRIS = 11219, //attackers entries unknown - FACTION_KER_ESCORTEE = 113 -}; - -//TODO: make concept similar as "ringo" -escort. Find a way to run the scripted attacks, _if_ player are choosing road. -struct npc_kerlonianAI : public FollowerAI -{ - npc_kerlonianAI(Creature* pCreature) : FollowerAI(pCreature) { } - - uint32 m_uiFallAsleepTimer; - - void Reset() - { - m_uiFallAsleepTimer = urand(10000, 45000); - } - - void MoveInLineOfSight(Unit *pWho) - { - FollowerAI::MoveInLineOfSight(pWho); - - if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_LILADRIS) - { - if (me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE*5)) - { - if (Player* pPlayer = GetLeaderForFollower()) - { - if (pPlayer->GetQuestStatus(QUEST_SLEEPER_AWAKENED) == QUEST_STATUS_INCOMPLETE) - pPlayer->GroupEventHappens(QUEST_SLEEPER_AWAKENED, me); - - DoScriptText(SAY_KER_END, me); - } - - SetFollowComplete(); - } - } - } - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - if (HasFollowState(STATE_FOLLOW_INPROGRESS | STATE_FOLLOW_PAUSED) && pSpell->Id == SPELL_AWAKEN) - ClearSleeping(); - } - - void SetSleeping() - { - SetFollowPaused(true); - - DoScriptText(RAND(EMOTE_KER_SLEEP_1,EMOTE_KER_SLEEP_2,EMOTE_KER_SLEEP_3), me); - - DoScriptText(RAND(SAY_KER_SLEEP_1,SAY_KER_SLEEP_2,SAY_KER_SLEEP_3,SAY_KER_SLEEP_4), me); - - me->SetStandState(UNIT_STAND_STATE_SLEEP); - DoCast(me, SPELL_SLEEP_VISUAL, false); - } - - void ClearSleeping() - { - me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL); - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoScriptText(EMOTE_KER_AWAKEN, me); - - SetFollowPaused(false); - } - - void UpdateFollowerAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - { - if (!HasFollowState(STATE_FOLLOW_INPROGRESS)) - return; - - if (!HasFollowState(STATE_FOLLOW_PAUSED)) - { - if (m_uiFallAsleepTimer <= uiDiff) - { - SetSleeping(); - m_uiFallAsleepTimer = urand(25000, 90000); - } - else - m_uiFallAsleepTimer -= uiDiff; - } - - return; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_kerlonian(Creature* pCreature) -{ - return new npc_kerlonianAI(pCreature); -} - -bool QuestAccept_npc_kerlonian(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_SLEEPER_AWAKENED) - { - if (npc_kerlonianAI* pKerlonianAI = CAST_AI(npc_kerlonianAI, pCreature->AI())) - { - pCreature->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_KER_START, pCreature, pPlayer); - pKerlonianAI->StartFollow(pPlayer, FACTION_KER_ESCORTEE, pQuest); - } - } - - return true; -} - -/*#### -# npc_prospector_remtravel -####*/ - -enum eRemtravel -{ - SAY_REM_START = -1000327, - SAY_REM_AGGRO = -1000328, - SAY_REM_RAMP1_1 = -1000329, - SAY_REM_RAMP1_2 = -1000330, - SAY_REM_BOOK = -1000331, - SAY_REM_TENT1_1 = -1000332, - SAY_REM_TENT1_2 = -1000333, - SAY_REM_MOSS = -1000334, - EMOTE_REM_MOSS = -1000335, - SAY_REM_MOSS_PROGRESS = -1000336, - SAY_REM_PROGRESS = -1000337, - SAY_REM_REMEMBER = -1000338, - EMOTE_REM_END = -1000339, - - FACTION_ESCORTEE = 10, - QUEST_ABSENT_MINDED_PT2 = 731, - NPC_GRAVEL_SCOUT = 2158, - NPC_GRAVEL_BONE = 2159, - NPC_GRAVEL_GEO = 2160 -}; - -struct npc_prospector_remtravelAI : public npc_escortAI -{ - npc_prospector_remtravelAI(Creature* pCreature) : npc_escortAI(pCreature) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 0: - DoScriptText(SAY_REM_START, me, pPlayer); - break; - case 5: - DoScriptText(SAY_REM_RAMP1_1, me, pPlayer); - break; - case 6: - DoSpawnCreature(NPC_GRAVEL_SCOUT, -10.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - DoSpawnCreature(NPC_GRAVEL_BONE, -10.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 9: - DoScriptText(SAY_REM_RAMP1_2, me, pPlayer); - break; - case 14: - //depend quest rewarded? - DoScriptText(SAY_REM_BOOK, me, pPlayer); - break; - case 15: - DoScriptText(SAY_REM_TENT1_1, me, pPlayer); - break; - case 16: - DoSpawnCreature(NPC_GRAVEL_SCOUT, -10.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - DoSpawnCreature(NPC_GRAVEL_BONE, -10.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 17: - DoScriptText(SAY_REM_TENT1_2, me, pPlayer); - break; - case 26: - DoScriptText(SAY_REM_MOSS, me, pPlayer); - break; - case 27: - DoScriptText(EMOTE_REM_MOSS, me, pPlayer); - break; - case 28: - DoScriptText(SAY_REM_MOSS_PROGRESS, me, pPlayer); - break; - case 29: - DoSpawnCreature(NPC_GRAVEL_SCOUT, -15.0f, 3.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - DoSpawnCreature(NPC_GRAVEL_BONE, -15.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - DoSpawnCreature(NPC_GRAVEL_GEO, -15.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 31: - DoScriptText(SAY_REM_PROGRESS, me, pPlayer); - break; - case 41: - DoScriptText(SAY_REM_REMEMBER, me, pPlayer); - break; - case 42: - DoScriptText(EMOTE_REM_END, me, pPlayer); - pPlayer->GroupEventHappens(QUEST_ABSENT_MINDED_PT2, me); - break; - } - } - - void Reset() {} - - void EnterCombat(Unit* who) - { - if (rand()%2) - DoScriptText(SAY_REM_AGGRO, me, who); - } - - void JustSummoned(Creature* /*pSummoned*/) - { - //unsure if it should be any - //pSummoned->AI()->AttackStart(me); - } -}; - -CreatureAI* GetAI_npc_prospector_remtravel(Creature* pCreature) -{ - return new npc_prospector_remtravelAI(pCreature); -} - -bool QuestAccept_npc_prospector_remtravel(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_ABSENT_MINDED_PT2) - { - if (npc_escortAI* pEscortAI = CAST_AI(npc_prospector_remtravelAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID()); - - pCreature->setFaction(FACTION_ESCORTEE); - } - - return true; -} - -/*#### -# npc_threshwackonator -####*/ - -enum eThreshwackonator -{ - EMOTE_START = -1000413, //signed for 4966 - SAY_AT_CLOSE = -1000414, //signed for 4966 - QUEST_GYROMAST_REV = 2078, - NPC_GELKAK = 6667, - FACTION_HOSTILE = 14 -}; - -#define GOSSIP_ITEM_INSERT_KEY "[PH] Insert key" - -struct npc_threshwackonatorAI : public FollowerAI -{ - npc_threshwackonatorAI(Creature* pCreature) : FollowerAI(pCreature) { } - - void Reset() { } - - void MoveInLineOfSight(Unit* pWho) - { - FollowerAI::MoveInLineOfSight(pWho); - - if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_GELKAK) - { - if (me->IsWithinDistInMap(pWho, 10.0f)) - { - DoScriptText(SAY_AT_CLOSE, pWho); - DoAtEnd(); - } - } - } - - void DoAtEnd() - { - me->setFaction(FACTION_HOSTILE); - - if (Player* pHolder = GetLeaderForFollower()) - me->AI()->AttackStart(pHolder); - - SetFollowComplete(); - } -}; - -CreatureAI* GetAI_npc_threshwackonator(Creature* pCreature) -{ - return new npc_threshwackonatorAI(pCreature); -} - -bool GossipHello_npc_threshwackonator(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_GYROMAST_REV) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_INSERT_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_threshwackonator(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - if (npc_threshwackonatorAI* pThreshAI = CAST_AI(npc_threshwackonatorAI, pCreature->AI())) - { - DoScriptText(EMOTE_START, pCreature); - pThreshAI->StartFollow(pPlayer); - } - } - - return true; -} - -void AddSC_darkshore() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_kerlonian"; - newscript->GetAI = &GetAI_npc_kerlonian; - newscript->pQuestAccept = &QuestAccept_npc_kerlonian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_prospector_remtravel"; - newscript->GetAI = &GetAI_npc_prospector_remtravel; - newscript->pQuestAccept = &QuestAccept_npc_prospector_remtravel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_threshwackonator"; - newscript->GetAI = &GetAI_npc_threshwackonator; - newscript->pGossipHello = &GossipHello_npc_threshwackonator; - newscript->pGossipSelect = &GossipSelect_npc_threshwackonator; - newscript->pGossipSelect = &GossipSelect_npc_threshwackonator; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/desolace.cpp b/src/server/scripts/kalimdor/desolace.cpp deleted file mode 100644 index 6b3ec8071dd..00000000000 --- a/src/server/scripts/kalimdor/desolace.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Desolace -SD%Complete: 100 -SDComment: Quest support: 5561 -SDCategory: Desolace -EndScriptData */ - -/* ContentData -npc_aged_dying_ancient_kodo -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -enum eDyingKodo -{ - // signed for 9999 - SAY_SMEED_HOME_1 = -1000348, - SAY_SMEED_HOME_2 = -1000349, - SAY_SMEED_HOME_3 = -1000350, - - QUEST_KODO = 5561, - - NPC_SMEED = 11596, - NPC_AGED_KODO = 4700, - NPC_DYING_KODO = 4701, - NPC_ANCIENT_KODO = 4702, - NPC_TAMED_KODO = 11627, - - SPELL_KODO_KOMBO_ITEM = 18153, - SPELL_KODO_KOMBO_PLAYER_BUFF = 18172, //spells here have unclear function, but using them at least for visual parts and checks - SPELL_KODO_KOMBO_DESPAWN_BUFF = 18377, - SPELL_KODO_KOMBO_GOSSIP = 18362 - -}; - -struct npc_aged_dying_ancient_kodoAI : public ScriptedAI -{ - npc_aged_dying_ancient_kodoAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } - - uint32 m_uiDespawnTimer; - - void Reset() - { - m_uiDespawnTimer = 0; - } - - void MoveInLineOfSight(Unit* pWho) - { - if (pWho->GetEntry() == NPC_SMEED) - { - if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - return; - - if (me->IsWithinDistInMap(pWho, 10.0f)) - { - DoScriptText(RAND(SAY_SMEED_HOME_1,SAY_SMEED_HOME_2,SAY_SMEED_HOME_3), pWho); - - //spell have no implemented effect (dummy), so useful to notify spellHit - DoCast(me, SPELL_KODO_KOMBO_GOSSIP, true); - } - } - } - - void SpellHit(Unit* /*pCaster*/, SpellEntry const* pSpell) - { - if (pSpell->Id == SPELL_KODO_KOMBO_GOSSIP) - { - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - m_uiDespawnTimer = 60000; - } - } - - void UpdateAI(const uint32 diff) - { - //timer should always be == 0 unless we already updated entry of creature. Then not expect this updated to ever be in combat. - if (m_uiDespawnTimer && m_uiDespawnTimer <= diff) - { - if (!me->getVictim() && me->isAlive()) - { - Reset(); - me->setDeathState(JUST_DIED); - me->Respawn(); - return; - } - } else m_uiDespawnTimer -= diff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_aged_dying_ancient_kodo(Creature* pCreature) -{ - return new npc_aged_dying_ancient_kodoAI(pCreature); -} - -bool EffectDummyCreature_npc_aged_dying_ancient_kodo(Unit *pCaster, uint32 spellId, uint32 effIndex, Creature *pCreatureTarget) -{ - //always check spellid and effectindex - if (spellId == SPELL_KODO_KOMBO_ITEM && effIndex == 0) - { - //no effect if player/creature already have aura from spells - if (pCaster->HasAura(SPELL_KODO_KOMBO_PLAYER_BUFF) || pCreatureTarget->HasAura(SPELL_KODO_KOMBO_DESPAWN_BUFF)) - return true; - - if (pCreatureTarget->GetEntry() == NPC_AGED_KODO || - pCreatureTarget->GetEntry() == NPC_DYING_KODO || - pCreatureTarget->GetEntry() == NPC_ANCIENT_KODO) - { - pCaster->CastSpell(pCaster,SPELL_KODO_KOMBO_PLAYER_BUFF,true); - - pCreatureTarget->UpdateEntry(NPC_TAMED_KODO); - pCreatureTarget->CastSpell(pCreatureTarget,SPELL_KODO_KOMBO_DESPAWN_BUFF,false); - - if (pCreatureTarget->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) - pCreatureTarget->GetMotionMaster()->MoveIdle(); - - pCreatureTarget->GetMotionMaster()->MoveFollow(pCaster, PET_FOLLOW_DIST, pCreatureTarget->GetFollowAngle()); - } - - //always return true when we are handling this spell and effect - return true; - } - return false; -} - -bool GossipHello_npc_aged_dying_ancient_kodo(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->HasAura(SPELL_KODO_KOMBO_PLAYER_BUFF) && pCreature->HasAura(SPELL_KODO_KOMBO_DESPAWN_BUFF)) - { - //the expected quest objective - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - - pPlayer->RemoveAurasDueToSpell(SPELL_KODO_KOMBO_PLAYER_BUFF); - pCreature->GetMotionMaster()->MoveIdle(); - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -/*###### -## go_iruxos. Quest 5381 -######*/ - -bool GOHello_go_iruxos(Player *pPlayer, GameObject* /*pGO*/) -{ - if (pPlayer->GetQuestStatus(5381) == QUEST_STATUS_INCOMPLETE) - pPlayer->SummonCreature(11876, pPlayer->GetInnPosX(),pPlayer->GetInnPosY(),pPlayer->GetInnPosZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - - return true; -} - -/*###### -## npc_dalinda_malem. Quest 1440 -######*/ - -#define QUEST_RETURN_TO_VAHLARRIEL 1440 - -struct npc_dalindaAI : public npc_escortAI -{ - npc_dalindaAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - switch (i) - { - case 1: - me->IsStandState(); - break; - case 15: - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_RETURN_TO_VAHLARRIEL, me); - break; - } - } - - void EnterCombat(Unit* /*pWho*/) { } - - void Reset() {} - - void JustDied(Unit* /*pKiller*/) - { - Player* pPlayer = GetPlayerForEscort(); - if (pPlayer) - pPlayer->FailQuest(QUEST_RETURN_TO_VAHLARRIEL); - return; - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - if (!UpdateVictim()) - return; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_dalinda(Creature* pCreature) -{ - return new npc_dalindaAI(pCreature); -} - -bool QuestAccept_npc_dalinda(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_RETURN_TO_VAHLARRIEL) - { - if (npc_escortAI* pEscortAI = CAST_AI(npc_dalindaAI, pCreature->AI())) - { - pEscortAI->Start(true, false, pPlayer->GetGUID()); - pCreature->setFaction(113); - } - } - return true; -} - -void AddSC_desolace() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_aged_dying_ancient_kodo"; - newscript->GetAI = &GetAI_npc_aged_dying_ancient_kodo; - newscript->pEffectDummyCreature = &EffectDummyCreature_npc_aged_dying_ancient_kodo; - newscript->pGossipHello = &GossipHello_npc_aged_dying_ancient_kodo; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_iruxos"; - newscript->pGOHello = &GOHello_go_iruxos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dalinda"; - newscript->GetAI = &GetAI_npc_dalinda; - newscript->pQuestAccept = &QuestAccept_npc_dalinda; - newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/kalimdor/durotar.cpp b/src/server/scripts/kalimdor/durotar.cpp deleted file mode 100644 index 9ca6074cad3..00000000000 --- a/src/server/scripts/kalimdor/durotar.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (C) 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -#include "ScriptedPch.h" - -/*###### -##Quest 5441: Lazy Peons -##npc_lazy_peon -######*/ - -enum LazyPeonYells -{ - SAY_SPELL_HIT = -1999900 //Ow! OK, I''ll get back to work, $N!' -}; - -enum LazyPeon -{ - QUEST_LAZY_PEONS = 5441, - GO_LUMBERPILE = 175784, - SPELL_BUFF_SLEEP = 17743, - SPELL_AWAKEN_PEON = 19938 -}; - -struct npc_lazy_peonAI : public ScriptedAI -{ - npc_lazy_peonAI(Creature *c) : ScriptedAI(c) {} - - uint64 uiPlayerGUID; - - uint32 m_uiRebuffTimer; - bool work; - - void Reset () - { - uiPlayerGUID = 0; - work = false; - } - - void MovementInform(uint32 /*type*/, uint32 id) - { - if (id == 1) - work = true; - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_AWAKEN_PEON && caster->GetTypeId() == TYPEID_PLAYER - && CAST_PLR(caster)->GetQuestStatus(QUEST_LAZY_PEONS) == QUEST_STATUS_INCOMPLETE) - { - caster->ToPlayer()->KilledMonsterCredit(me->GetEntry(),me->GetGUID()); - DoScriptText(SAY_SPELL_HIT, me, caster); - me->RemoveAllAuras(); - if (GameObject* Lumberpile = me->FindNearestGameObject(GO_LUMBERPILE, 20)) - me->GetMotionMaster()->MovePoint(1,Lumberpile->GetPositionX()-1,Lumberpile->GetPositionY(),Lumberpile->GetPositionZ()); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (work == true) - me->HandleEmoteCommand(466); - if (m_uiRebuffTimer <= uiDiff) - { - DoCast(me, SPELL_BUFF_SLEEP); - m_uiRebuffTimer = 300000; //Rebuff agian in 5 minutes - } - else - m_uiRebuffTimer -= uiDiff; - if (!UpdateVictim()) - return; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_lazy_peon(Creature* pCreature) -{ - return new npc_lazy_peonAI(pCreature); -} - -void AddSC_durotar() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_lazy_peon"; - newscript->GetAI = &GetAI_npc_lazy_peon; - newscript->RegisterSelf(); -} \ No newline at end of file diff --git a/src/server/scripts/kalimdor/dustwallow_marsh.cpp b/src/server/scripts/kalimdor/dustwallow_marsh.cpp deleted file mode 100644 index a80c514eed7..00000000000 --- a/src/server/scripts/kalimdor/dustwallow_marsh.cpp +++ /dev/null @@ -1,425 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Dustwallow_Marsh -SD%Complete: 95 -SDComment: Quest support: 11180, 558, 11126, 11142, 11180. Vendor Nat Pagle -SDCategory: Dustwallow Marsh -EndScriptData */ - -/* ContentData -mobs_risen_husk_spirit -npc_restless_apparition -npc_deserter_agitator -npc_lady_jaina_proudmoore -npc_nat_pagle -npc_private_hendel -npc_cassa_crimsonwing - handled by npc_taxi -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## mobs_risen_husk_spirit -######*/ - -enum eHuskSpirit -{ - QUEST_WHATS_HAUNTING_WITCH_HILL = 11180, - - SPELL_SUMMON_RESTLESS_APPARITION = 42511, - SPELL_CONSUME_FLESH = 37933, //Risen Husk - SPELL_INTANGIBLE_PRESENCE = 43127, //Risen Spirit - - NPC_RISEN_HUSK = 23555, - NPC_RISEN_SPIRIT = 23554, - NPC_RESTLESS_APPARITION = 23861 -}; - -struct mobs_risen_husk_spiritAI : public ScriptedAI -{ - mobs_risen_husk_spiritAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiConsumeFlesh_Timer; - uint32 m_uiIntangiblePresence_Timer; - - void Reset() - { - m_uiConsumeFlesh_Timer = 10000; - m_uiIntangiblePresence_Timer = 5000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (m_uiConsumeFlesh_Timer <= uiDiff) - { - if (me->GetEntry() == NPC_RISEN_HUSK) - DoCast(me->getVictim(), SPELL_CONSUME_FLESH); - - m_uiConsumeFlesh_Timer = 15000; - } - else - m_uiConsumeFlesh_Timer -= uiDiff; - - if (m_uiIntangiblePresence_Timer <= uiDiff) - { - if (me->GetEntry() == NPC_RISEN_SPIRIT) - DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); - - m_uiIntangiblePresence_Timer = 20000; - } - else - m_uiIntangiblePresence_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* pKiller) - { - if (pKiller->GetTypeId() == TYPEID_PLAYER) - if (CAST_PLR(pKiller)->GetQuestStatus(QUEST_WHATS_HAUNTING_WITCH_HILL) == QUEST_STATUS_INCOMPLETE) - { - DoCast(pKiller, SPELL_SUMMON_RESTLESS_APPARITION, true); - CAST_PLR(pKiller)->KilledMonsterCredit(NPC_RESTLESS_APPARITION,0); - } - } -}; - -CreatureAI* GetAI_mobs_risen_husk_spirit(Creature* pCreature) -{ - return new mobs_risen_husk_spiritAI (pCreature); -} - -/*###### -## npc_restless_apparition -######*/ - -enum eRestlessApparition -{ - SAY_RESTLESS_1 = -1000469, - SAY_RESTLESS_2 = -1000470, - SAY_RESTLESS_3 = -1000471 -}; - -struct npc_restless_apparitionAI : public ScriptedAI -{ - npc_restless_apparitionAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - void Reset() - { - DoScriptText(RAND(SAY_RESTLESS_1,SAY_RESTLESS_2,SAY_RESTLESS_3), me); - } -}; - -CreatureAI* GetAI_npc_restless_apparition(Creature* pCreature) -{ - return new npc_restless_apparitionAI (pCreature); -} - -/*###### -## npc_deserter_agitator -######*/ - -enum eAgitator -{ - QUEST_TRAITORS_AMONG_US = 11126, - FACTION_THER_DESERTER = 1883 -}; - -struct npc_deserter_agitatorAI : public ScriptedAI -{ - npc_deserter_agitatorAI(Creature* pCreature) : ScriptedAI(pCreature) { } - - void Reset() - { - me->RestoreFaction(); - } -}; - -CreatureAI* GetAI_npc_deserter_agitator(Creature* pCreature) -{ - return new npc_deserter_agitatorAI (pCreature); -} - -bool GossipHello_npc_deserter_agitator(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_TRAITORS_AMONG_US) == QUEST_STATUS_INCOMPLETE) - { - pCreature->setFaction(FACTION_THER_DESERTER); - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_lady_jaina_proudmoore -######*/ - -enum eLadyJaina -{ - QUEST_JAINAS_AUTOGRAPH = 558, - SPELL_JAINAS_AUTOGRAPH = 23122 -}; - -#define GOSSIP_ITEM_JAINA "I know this is rather silly but i have a young ward who is a bit shy and would like your autograph." - -bool GossipHello_npc_lady_jaina_proudmoore(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_JAINAS_AUTOGRAPH) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_JAINA, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lady_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_SENDER_INFO) - { - pPlayer->SEND_GOSSIP_MENU(7012, pCreature->GetGUID()); - pPlayer->CastSpell(pPlayer, SPELL_JAINAS_AUTOGRAPH, false); - } - return true; -} - -/*###### -## npc_nat_pagle -######*/ - -enum eNatPagle -{ - QUEST_NATS_MEASURING_TAPE = 8227 -}; - -bool GossipHello_npc_nat_pagle(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(QUEST_NATS_MEASURING_TAPE)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - pPlayer->SEND_GOSSIP_MENU(7640, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(7638, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_nat_pagle(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_private_hendel -######*/ - -enum eHendel -{ - // looks like all this text ids are wrong. - SAY_PROGRESS_1_TER = -1000411, // signed for 3568 - SAY_PROGRESS_2_HEN = -1000412, // signed for 3568 - SAY_PROGRESS_3_TER = -1000413, - SAY_PROGRESS_4_TER = -1000414, - EMOTE_SURRENDER = -1000415, - - QUEST_MISSING_DIPLO_PT16 = 1324, - FACTION_HOSTILE = 168, //guessed, may be different - - NPC_SENTRY = 5184, //helps hendel - NPC_JAINA = 4968, //appears once hendel gives up - NPC_TERVOSH = 4967 -}; - -//TODO: develop this further, end event not created -struct npc_private_hendelAI : public ScriptedAI -{ - npc_private_hendelAI(Creature* pCreature) : ScriptedAI(pCreature) { } - - void Reset() - { - me->RestoreFaction(); - } - - void AttackedBy(Unit* pAttacker) - { - if (me->getVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) - { - if (uiDamage > me->GetHealth() || ((me->GetHealth() - uiDamage)*100 / me->GetMaxHealth() < 20)) - { - uiDamage = 0; - - if (Player* pPlayer = pDoneBy->GetCharmerOrOwnerPlayerOrPlayerItself()) - pPlayer->GroupEventHappens(QUEST_MISSING_DIPLO_PT16, me); - - DoScriptText(EMOTE_SURRENDER, me); - EnterEvadeMode(); - } - } -}; - -bool QuestAccept_npc_private_hendel(Player* /*pPlayer*/, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT16) - pCreature->setFaction(FACTION_HOSTILE); - - return true; -} - -CreatureAI* GetAI_npc_private_hendel(Creature* pCreature) -{ - return new npc_private_hendelAI(pCreature); -} - -/*###### -## npc_zelfrax -######*/ - -const Position MovePosition = {-2967.030,-3872.1799,35.620}; - -enum eZelfrax -{ - SAY_ZELFRAX = -1000472, - SAY_ZELFRAX_2 = -1000473 -}; - -struct npc_zelfraxAI : public ScriptedAI -{ - npc_zelfraxAI(Creature* pCreature) : ScriptedAI(pCreature) - { - MoveToDock(); - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - if (me->Attack(pWho, true)) - { - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - if (IsCombatMovement()) - me->GetMotionMaster()->MoveChase(pWho); - } - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - me->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); - SetCombatMovement(true); - - if (me->isInCombat()) - if (Unit* pUnit = me->getVictim()) - me->GetMotionMaster()->MoveChase(pUnit); - } - - void MoveToDock() - { - SetCombatMovement(false); - me->GetMotionMaster()->MovePoint(0,MovePosition); - DoScriptText(SAY_ZELFRAX,me); - DoScriptText(SAY_ZELFRAX_2,me); - } - - void UpdateAI(uint32 const /*uiDiff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_zelfrax(Creature* pCreature) -{ - return new npc_zelfraxAI(pCreature); -} - -void AddSC_dustwallow_marsh() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mobs_risen_husk_spirit"; - newscript->GetAI = &GetAI_mobs_risen_husk_spirit; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_restless_apparition"; - newscript->GetAI = &GetAI_npc_restless_apparition; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_deserter_agitator"; - newscript->GetAI = &GetAI_npc_deserter_agitator; - newscript->pGossipHello = &GossipHello_npc_deserter_agitator; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lady_jaina_proudmoore"; - newscript->pGossipHello = &GossipHello_npc_lady_jaina_proudmoore; - newscript->pGossipSelect = &GossipSelect_npc_lady_jaina_proudmoore; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_nat_pagle"; - newscript->pGossipHello = &GossipHello_npc_nat_pagle; - newscript->pGossipSelect = &GossipSelect_npc_nat_pagle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_private_hendel"; - newscript->GetAI = &GetAI_npc_private_hendel; - newscript->pQuestAccept = &QuestAccept_npc_private_hendel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_zelfrax"; - newscript->GetAI = &GetAI_npc_zelfrax; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/felwood.cpp b/src/server/scripts/kalimdor/felwood.cpp deleted file mode 100644 index 01da356a63e..00000000000 --- a/src/server/scripts/kalimdor/felwood.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Felwood -SD%Complete: 95 -SDComment: Quest support: 4101, 4102 -SDCategory: Felwood -EndScriptData */ - -/* ContentData -npcs_riverbreeze_and_silversky -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npcs_riverbreeze_and_silversky -######*/ - -#define GOSSIP_ITEM_BEACON "Please make me a Cenarion Beacon" - -bool GossipHello_npcs_riverbreeze_and_silversky(Player* pPlayer, Creature* pCreature) -{ - uint32 eCreature = pCreature->GetEntry(); - - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (eCreature == 9528) - { - if (pPlayer->GetQuestRewardStatus(4101)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(2848, pCreature->GetGUID()); - } else if (pPlayer->GetTeam() == HORDE) - pPlayer->SEND_GOSSIP_MENU(2845, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(2844, pCreature->GetGUID()); - } - - if (eCreature == 9529) - { - if (pPlayer->GetQuestRewardStatus(4102)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(2849, pCreature->GetGUID()); - } else if (pPlayer->GetTeam() == ALLIANCE) - pPlayer->SEND_GOSSIP_MENU(2843, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(2842, pCreature->GetGUID()); - } - - return true; -} - -bool GossipSelect_npcs_riverbreeze_and_silversky(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, 15120, false); - } - return true; -} - -void AddSC_felwood() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npcs_riverbreeze_and_silversky"; - newscript->pGossipHello = &GossipHello_npcs_riverbreeze_and_silversky; - newscript->pGossipSelect = &GossipSelect_npcs_riverbreeze_and_silversky; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/feralas.cpp b/src/server/scripts/kalimdor/feralas.cpp deleted file mode 100644 index 2a87de1a67c..00000000000 --- a/src/server/scripts/kalimdor/feralas.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Feralas -SD%Complete: 100 -SDComment: Quest support: 3520, 2767, Special vendor Gregan Brewspewer -SDCategory: Feralas -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_gregan_brewspewer -######*/ - -#define GOSSIP_HELLO "Buy somethin', will ya?" - -bool GossipHello_npc_gregan_brewspewer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor() && pPlayer->GetQuestStatus(3909) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(2433, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_gregan_brewspewer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - pPlayer->SEND_GOSSIP_MENU(2434, pCreature->GetGUID()); - } - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - return true; -} - -/*###### -## npc_oox22fe -######*/ - -enum eOOX -{ - //signed for 7806 - SAY_OOX_START = -1000287, - SAY_OOX_AGGRO1 = -1000288, - SAY_OOX_AGGRO2 = -1000289, - SAY_OOX_AMBUSH = -1000290, - SAY_OOX_END = -1000292, - - NPC_YETI = 7848, - NPC_GORILLA = 5260, - NPC_WOODPAW_REAVER = 5255, - NPC_WOODPAW_BRUTE = 5253, - NPC_WOODPAW_ALPHA = 5258, - NPC_WOODPAW_MYSTIC = 5254, - - QUEST_RESCUE_OOX22FE = 2767, - FACTION_ESCORTEE_A = 774, - FACTION_ESCORTEE_H = 775 -}; - -struct npc_oox22feAI : public npc_escortAI -{ - npc_oox22feAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void WaypointReached(uint32 i) - { - switch (i) - { - // First Ambush(3 Yetis) - case 11: - DoScriptText(SAY_OOX_AMBUSH, me); - me->SummonCreature(NPC_YETI, -4841.01, 1593.91, 73.42, 3.98, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - me->SummonCreature(NPC_YETI, -4837.61, 1568.58, 78.21, 3.13, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - me->SummonCreature(NPC_YETI, -4841.89, 1569.95, 76.53, 0.68, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - break; - //Second Ambush(3 Gorillas) - case 21: - DoScriptText(SAY_OOX_AMBUSH, me); - me->SummonCreature(NPC_GORILLA, -4595.81, 2005.99, 53.08, 3.74, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - me->SummonCreature(NPC_GORILLA, -4597.53, 2008.31, 52.70, 3.78, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - me->SummonCreature(NPC_GORILLA, -4599.37, 2010.59, 52.77, 3.84, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - break; - //Third Ambush(4 Gnolls) - case 30: - DoScriptText(SAY_OOX_AMBUSH, me); - me->SummonCreature(NPC_WOODPAW_REAVER, -4425.14, 2075.87, 47.77, 3.77, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - me->SummonCreature(NPC_WOODPAW_BRUTE , -4426.68, 2077.98, 47.57, 3.77, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - me->SummonCreature(NPC_WOODPAW_MYSTIC, -4428.33, 2080.24, 47.43, 3.87, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - me->SummonCreature(NPC_WOODPAW_ALPHA , -4430.04, 2075.54, 46.83, 3.81, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - break; - case 37: - DoScriptText(SAY_OOX_END, me); - // Award quest credit - if (Player* pPlayer = GetPlayerForEscort()) - { - pPlayer->GroupEventHappens(QUEST_RESCUE_OOX22FE, me); - } - break; - } - } - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - me->SetStandState(UNIT_STAND_STATE_DEAD); - } - - void EnterCombat(Unit* /*who*/) - { - //For an small probability the npc says something when he get aggro - if (urand(0,9) > 7) - DoScriptText(RAND(SAY_OOX_AGGRO1,SAY_OOX_AGGRO2), me); - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } -}; - -CreatureAI* GetAI_npc_oox22fe(Creature* pCreature) -{ - return new npc_oox22feAI(pCreature); -} - -bool QuestAccept_npc_oox22fe(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_RESCUE_OOX22FE) - { - DoScriptText(SAY_OOX_START, pCreature); - //change that the npc is not lying dead on the ground - pCreature->SetStandState(UNIT_STAND_STATE_STAND); - - if (pPlayer->GetTeam() == ALLIANCE) - pCreature->setFaction(FACTION_ESCORTEE_A); - - if (pPlayer->GetTeam() == HORDE) - pCreature->setFaction(FACTION_ESCORTEE_H); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_oox22feAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - - } - return true; -} - -/*###### -## npc_screecher_spirit -######*/ - -bool GossipHello_npc_screecher_spirit(Player* pPlayer, Creature* pCreature) -{ - pPlayer->SEND_GOSSIP_MENU(2039, pCreature->GetGUID()); - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - return true; -} - -/*###### -## AddSC -######*/ - -void AddSC_feralas() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_gregan_brewspewer"; - newscript->pGossipHello = &GossipHello_npc_gregan_brewspewer; - newscript->pGossipSelect = &GossipSelect_npc_gregan_brewspewer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_oox22fe"; - newscript->GetAI = &GetAI_npc_oox22fe; - newscript->pQuestAccept = &QuestAccept_npc_oox22fe; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_screecher_spirit"; - newscript->pGossipHello = &GossipHello_npc_screecher_spirit; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp b/src/server/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp deleted file mode 100644 index 6f6b9d1baa9..00000000000 --- a/src/server/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Celebras_the_Cursed -SD%Complete: 100 -SDComment: -SDCategory: Maraudon -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_WRATH 21807 -#define SPELL_ENTANGLINGROOTS 12747 -#define SPELL_CORRUPT_FORCES 21968 - -struct celebras_the_cursedAI : public ScriptedAI -{ - celebras_the_cursedAI(Creature *c) : ScriptedAI(c) {} - - uint32 Wrath_Timer; - uint32 EntanglingRoots_Timer; - uint32 CorruptForces_Timer; - - void Reset() - { - Wrath_Timer = 8000; - EntanglingRoots_Timer = 2000; - CorruptForces_Timer = 30000; - } - - void EnterCombat(Unit * /*who*/) { } - - void JustDied(Unit* /*Killer*/) - { - me->SummonCreature(13716, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Wrath - if (Wrath_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - DoCast(pTarget, SPELL_WRATH); - Wrath_Timer = 8000; - } else Wrath_Timer -= diff; - - //EntanglingRoots - if (EntanglingRoots_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ENTANGLINGROOTS); - EntanglingRoots_Timer = 20000; - } else EntanglingRoots_Timer -= diff; - - //CorruptForces - if (CorruptForces_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_CORRUPT_FORCES); - CorruptForces_Timer = 20000; - } else CorruptForces_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_celebras_the_cursed(Creature* pCreature) -{ - return new celebras_the_cursedAI (pCreature); -} - -void AddSC_boss_celebras_the_cursed() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "celebras_the_cursed"; - newscript->GetAI = &GetAI_celebras_the_cursed; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/maraudon/boss_landslide.cpp b/src/server/scripts/kalimdor/maraudon/boss_landslide.cpp deleted file mode 100644 index d5b03ff218f..00000000000 --- a/src/server/scripts/kalimdor/maraudon/boss_landslide.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Landslide -SD%Complete: 100 -SDComment: -SDCategory: Maraudon -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_KNOCKAWAY 18670 -#define SPELL_TRAMPLE 5568 -#define SPELL_LANDSLIDE 21808 - -struct boss_landslideAI : public ScriptedAI -{ - boss_landslideAI(Creature *c) : ScriptedAI(c) {} - - uint32 KnockAway_Timer; - uint32 Trample_Timer; - uint32 Landslide_Timer; - - void Reset() - { - KnockAway_Timer = 8000; - Trample_Timer = 2000; - Landslide_Timer = 0; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //KnockAway_Timer - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - KnockAway_Timer = 15000; - } else KnockAway_Timer -= diff; - - //Trample_Timer - if (Trample_Timer <= diff) - { - DoCast(me, SPELL_TRAMPLE); - Trample_Timer = 8000; - } else Trample_Timer -= diff; - - //Landslide - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - if (Landslide_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_LANDSLIDE); - Landslide_Timer = 60000; - } else Landslide_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_landslide(Creature* pCreature) -{ - return new boss_landslideAI (pCreature); -} - -void AddSC_boss_landslide() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_landslide"; - newscript->GetAI = &GetAI_boss_landslide; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/maraudon/boss_noxxion.cpp b/src/server/scripts/kalimdor/maraudon/boss_noxxion.cpp deleted file mode 100644 index b49b1a5d71f..00000000000 --- a/src/server/scripts/kalimdor/maraudon/boss_noxxion.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Noxxion -SD%Complete: 100 -SDComment: -SDCategory: Maraudon -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_TOXICVOLLEY 21687 -#define SPELL_UPPERCUT 22916 - -struct boss_noxxionAI : public ScriptedAI -{ - boss_noxxionAI(Creature *c) : ScriptedAI(c) {} - - uint32 ToxicVolley_Timer; - uint32 Uppercut_Timer; - uint32 Adds_Timer; - uint32 Invisible_Timer; - bool Invisible; - - void Reset() - { - ToxicVolley_Timer = 7000; - Uppercut_Timer = 16000; - Adds_Timer = 19000; - Invisible_Timer = 15000; //Too much too low? - Invisible = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonAdds(Unit* pVictim) - { - if (Creature *Add = DoSpawnCreature(13456, irand(-7,7), irand(-7,7), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 90000)) - Add->AI()->AttackStart(pVictim); - } - - void UpdateAI(const uint32 diff) - { - if (Invisible && Invisible_Timer <= diff) - { - //Become visible again - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //Noxxion model - me->SetDisplayId(11172); - Invisible = false; - //me->m_canMove = true; - } else if (Invisible) - { - Invisible_Timer -= diff; - //Do nothing while invisible - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //ToxicVolley_Timer - if (ToxicVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TOXICVOLLEY); - ToxicVolley_Timer = 9000; - } else ToxicVolley_Timer -= diff; - - //Uppercut_Timer - if (Uppercut_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_UPPERCUT); - Uppercut_Timer = 12000; - } else Uppercut_Timer -= diff; - - //Adds_Timer - if (!Invisible && Adds_Timer <= diff) - { - //Inturrupt any spell casting - //me->m_canMove = true; - me->InterruptNonMeleeSpells(false); - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // Invisible Model - me->SetDisplayId(11686); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - Invisible = true; - Invisible_Timer = 15000; - - Adds_Timer = 40000; - } else Adds_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_noxxion(Creature* pCreature) -{ - return new boss_noxxionAI (pCreature); -} - -void AddSC_boss_noxxion() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_noxxion"; - newscript->GetAI = &GetAI_boss_noxxion; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/maraudon/boss_princess_theradras.cpp b/src/server/scripts/kalimdor/maraudon/boss_princess_theradras.cpp deleted file mode 100644 index 963863e89c8..00000000000 --- a/src/server/scripts/kalimdor/maraudon/boss_princess_theradras.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Princess_Theradras -SD%Complete: 100 -SDComment: -SDCategory: Maraudon -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_DUSTFIELD 21909 -#define SPELL_BOULDER 21832 -#define SPELL_THRASH 3391 -#define SPELL_REPULSIVEGAZE 21869 - -struct boss_ptheradrasAI : public ScriptedAI -{ - boss_ptheradrasAI(Creature *c) : ScriptedAI(c) {} - - uint32 Dustfield_Timer; - uint32 Boulder_Timer; - uint32 Thrash_Timer; - uint32 RepulsiveGaze_Timer; - - void Reset() - { - Dustfield_Timer = 8000; - Boulder_Timer = 2000; - Thrash_Timer = 5000; - RepulsiveGaze_Timer = 23000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*killer*/) - { - me->SummonCreature(12238,28.067,61.875,-123.405,4.67,TEMPSUMMON_TIMED_DESPAWN,600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Dustfield_Timer - if (Dustfield_Timer <= diff) - { - DoCast(me, SPELL_DUSTFIELD); - Dustfield_Timer = 14000; - } else Dustfield_Timer -= diff; - - //Boulder_Timer - if (Boulder_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - DoCast(pTarget, SPELL_BOULDER); - Boulder_Timer = 10000; - } else Boulder_Timer -= diff; - - //RepulsiveGaze_Timer - if (RepulsiveGaze_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REPULSIVEGAZE); - RepulsiveGaze_Timer = 20000; - } else RepulsiveGaze_Timer -= diff; - - //Thrash_Timer - if (Thrash_Timer <= diff) - { - DoCast(me, SPELL_THRASH); - Thrash_Timer = 18000; - } else Thrash_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ptheradras(Creature* pCreature) -{ - return new boss_ptheradrasAI (pCreature); -} - -void AddSC_boss_ptheradras() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_princess_theradras"; - newscript->GetAI = &GetAI_boss_ptheradras; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/moonglade.cpp b/src/server/scripts/kalimdor/moonglade.cpp deleted file mode 100644 index 16c78f20812..00000000000 --- a/src/server/scripts/kalimdor/moonglade.cpp +++ /dev/null @@ -1,571 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Moonglade -SD%Complete: 100 -SDComment: Quest support: 30, 272, 5929, 5930, 10965. Special Flight Paths for Druid class. -SDCategory: Moonglade -EndScriptData */ - -/* ContentData -npc_bunthen_plainswind -npc_great_bear_spirit -npc_silva_filnaveth -npc_clintar_spirit -npc_clintar_dreamwalker -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_bunthen_plainswind -######*/ - -enum eBunthen -{ - QUEST_SEA_LION_HORDE = 30, - QUEST_SEA_LION_ALLY = 272, - TAXI_PATH_ID_ALLY = 315, - TAXI_PATH_ID_HORDE = 316 -}; - -#define GOSSIP_ITEM_THUNDER "I'd like to fly to Thunder Bluff." -#define GOSSIP_ITEM_AQ_END "Do you know where I can find Half Pendant of Aquatic Endurance?" - -bool GossipHello_npc_bunthen_plainswind(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->getClass() != CLASS_DRUID) - pPlayer->SEND_GOSSIP_MENU(4916, pCreature->GetGUID()); - else if (pPlayer->GetTeam() != HORDE) - { - if (pPlayer->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - pPlayer->SEND_GOSSIP_MENU(4917, pCreature->GetGUID()); - } - else if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == HORDE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THUNDER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (pPlayer->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - - pPlayer->SEND_GOSSIP_MENU(4918, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_bunthen_plainswind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == HORDE) - pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID_HORDE); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->SEND_GOSSIP_MENU(5373, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(5376, pCreature->GetGUID()); - break; - } - return true; -} - -/*###### -## npc_great_bear_spirit -######*/ - -#define GOSSIP_BEAR1 "What do you represent, spirit?" -#define GOSSIP_BEAR2 "I seek to understand the importance of strength of the body." -#define GOSSIP_BEAR3 "I seek to understand the importance of strength of the heart." -#define GOSSIP_BEAR4 "I have heard your words, Great Bear Spirit, and I understand. I now seek your blessings to fully learn the way of the Claw." - -bool GossipHello_npc_great_bear_spirit(Player* pPlayer, Creature* pCreature) -{ - //ally or horde quest - if (pPlayer->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(4719, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(4718, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_great_bear_spirit(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(4721, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(4733, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(4734, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(4735, pCreature->GetGUID()); - if (pPlayer->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(5929); - if (pPlayer->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(5930); - break; - } - return true; -} - -/*###### -## npc_silva_filnaveth -######*/ - -#define GOSSIP_ITEM_RUTHERAN "I'd like to fly to Rut'theran Village." -#define GOSSIP_ITEM_AQ_AGI "Do you know where I can find Half Pendant of Aquatic Agility?" - -bool GossipHello_npc_silva_filnaveth(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->getClass() != CLASS_DRUID) - pPlayer->SEND_GOSSIP_MENU(4913, pCreature->GetGUID()); - else if (pPlayer->GetTeam() != ALLIANCE) - { - if (pPlayer->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - pPlayer->SEND_GOSSIP_MENU(4915, pCreature->GetGUID()); - } - else if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == ALLIANCE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTHERAN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (pPlayer->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - - pPlayer->SEND_GOSSIP_MENU(4914, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_silva_filnaveth(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == ALLIANCE) - pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID_ALLY); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->SEND_GOSSIP_MENU(5374, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(5375, pCreature->GetGUID()); - break; - } - return true; -} - -/*###### -## npc_clintar_spirit -######*/ - -float Clintar_spirit_WP[41][5] = -{ - //pos_x pos_y pos_z orien waitTime -{7465.28, -3115.46, 439.327, 0.83, 4000}, -{7476.49, -3101, 443.457, 0.89, 0}, -{7486.57, -3085.59, 439.478, 1.07, 0}, -{7472.19, -3085.06, 443.142, 3.07, 0}, -{7456.92, -3085.91, 438.862, 3.24, 0}, -{7446.68, -3083.43, 438.245, 2.40, 0}, -{7446.17, -3080.21, 439.826, 1.10, 6000}, -{7452.41, -3085.8, 438.984, 5.78, 0}, -{7469.11, -3084.94, 443.048, 6.25, 0}, -{7483.79, -3085.44, 439.607, 6.25, 0}, -{7491.14, -3090.96, 439.983, 5.44, 0}, -{7497.62, -3098.22, 436.854, 5.44, 0}, -{7498.72, -3113.41, 434.596, 4.84, 0}, -{7500.06, -3122.51, 434.749, 5.17, 0}, -{7504.96, -3131.53, 434.475, 4.74, 0}, -{7504.31, -3133.53, 435.693, 3.84, 6000}, -{7504.55, -3133.27, 435.476, 0.68, 15000}, -{7501.99, -3126.01, 434.93, 1.83, 0}, -{7490.76, -3114.97, 434.431, 2.51, 0}, -{7479.64, -3105.51, 431.123, 1.83, 0}, -{7474.63, -3086.59, 428.994, 1.83, 2000}, -{7472.96, -3074.18, 427.566, 1.57, 0}, -{7472.25, -3063, 428.268, 1.55, 0}, -{7473.46, -3054.22, 427.588, 0.36, 0}, -{7475.08, -3053.6, 428.653, 0.36, 6000}, -{7474.66, -3053.56, 428.433, 3.19, 4000}, -{7471.81, -3058.84, 427.073, 4.29, 0}, -{7472.16, -3064.91, 427.772, 4.95, 0}, -{7471.56, -3085.36, 428.924, 4.72, 0}, -{7473.56, -3093.48, 429.294, 5.04, 0}, -{7478.94, -3104.29, 430.638, 5.23, 0}, -{7484.46, -3109.61, 432.769, 5.79, 0}, -{7490.23, -3111.08, 434.431, 0.02, 0}, -{7496.29, -3108, 434.783, 1.15, 0}, -{7497.46, -3100.66, 436.191, 1.50, 0}, -{7495.64, -3093.39, 438.349, 2.10, 0}, -{7492.44, -3086.01, 440.267, 1.38, 0}, -{7498.26, -3076.44, 440.808, 0.71, 0}, -{7506.4, -3067.35, 443.64, 0.77, 0}, -{7518.37, -3057.42, 445.584, 0.74, 0}, -{7517.51, -3056.3, 444.568, 2.49, 4500} -}; - -#define ASPECT_RAVEN 22915 - -#define ASPECT_RAVEN_SUMMON_X 7472.96 -#define ASPECT_RAVEN_SUMMON_Y -3074.18 -#define ASPECT_RAVEN_SUMMON_Z 427.566 -#define CLINTAR_SPIRIT_SUMMON_X 7459.2275 -#define CLINTAR_SPIRIT_SUMMON_Y -3122.5632 -#define CLINTAR_SPIRIT_SUMMON_Z 438.9842 -#define CLINTAR_SPIRIT_SUMMON_O 0.8594 - -//from -1000292 to -1000287 are signed for 7806. but all this texts ids wrong. -#define CLINTAR_SPIRIT_SAY_START -1000286 -#define CLINTAR_SPIRIT_SAY_UNDER_ATTACK_1 -1000287 -#define CLINTAR_SPIRIT_SAY_UNDER_ATTACK_2 -1000288 -#define CLINTAR_SPIRIT_SAY_GET_ONE -1000289 -#define CLINTAR_SPIRIT_SAY_GET_TWO -1000290 -#define CLINTAR_SPIRIT_SAY_GET_THREE -1000291 -#define CLINTAR_SPIRIT_SAY_GET_FINAL -1000292 - -struct npc_clintar_spiritAI : public npc_escortAI -{ -public: - npc_clintar_spiritAI(Creature *c) : npc_escortAI(c) {} - - uint32 Step; - uint32 CurrWP; - uint32 Event_Timer; - uint32 checkPlayer_Timer; - - uint64 PlayerGUID; - - bool Event_onWait; - - void Reset() - { - if (!PlayerGUID) - { - Step = 0; - CurrWP = 0; - Event_Timer = 0; - PlayerGUID = 0; - checkPlayer_Timer = 1000; - Event_onWait = false; - } - } - - void JustDied(Unit * /*killer*/) - { - if (!PlayerGUID) - return; - - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer && pPlayer->GetQuestStatus(10965) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->FailQuest(10965); - PlayerGUID = 0; - Reset(); - } - } - - void EnterEvadeMode() - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer && pPlayer->isInCombat() && pPlayer->getAttackerForHelper()) - { - AttackStart(pPlayer->getAttackerForHelper()); - return; - } - npc_escortAI::EnterEvadeMode(); - } - - void EnterCombat(Unit* who) - { - uint32 rnd = rand()%2; - switch(rnd) - { - case 0: DoScriptText(CLINTAR_SPIRIT_SAY_UNDER_ATTACK_1, me, who); break; - case 1: DoScriptText(CLINTAR_SPIRIT_SAY_UNDER_ATTACK_2, me, who); break; - } - } - - void StartEvent(Player* pPlayer) - { - if (!pPlayer) - return; - if (pPlayer->GetQuestStatus(10965) == QUEST_STATUS_INCOMPLETE) - { - for (uint8 i = 0; i < 41; ++i) - { - AddWaypoint(i, Clintar_spirit_WP[i][0], Clintar_spirit_WP[i][1], Clintar_spirit_WP[i][2], (uint32)Clintar_spirit_WP[i][4]); - } - PlayerGUID = pPlayer->GetGUID(); - Start(true,false,PlayerGUID); - } - return; - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (!PlayerGUID) - { - me->setDeathState(JUST_DIED); - return; - } - - if (!me->isInCombat() && !Event_onWait) - { - if (checkPlayer_Timer <= diff) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer && pPlayer->isInCombat() && pPlayer->getAttackerForHelper()) - AttackStart(pPlayer->getAttackerForHelper()); - checkPlayer_Timer = 1000; - } else checkPlayer_Timer -= diff; - } - - if (Event_onWait && Event_Timer <= diff) - { - - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (!pPlayer || (pPlayer && pPlayer->GetQuestStatus(10965) == QUEST_STATUS_NONE)) - { - me->setDeathState(JUST_DIED); - return; - } - - switch(CurrWP) - { - case 0: - switch(Step) - { - case 0: - me->Say(CLINTAR_SPIRIT_SAY_START,0,PlayerGUID); - Event_Timer = 8000; - Step = 1; - break; - case 1: - Event_onWait = false; - break; - } - break; - case 6: - switch(Step) - { - case 0: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); - Event_Timer = 5000; - Step = 1; - break; - case 1: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); - DoScriptText(CLINTAR_SPIRIT_SAY_GET_ONE, me, pPlayer); - Event_onWait = false; - break; - } - break; - case 15: - switch(Step) - { - case 0: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); - Event_Timer = 5000; - Step = 1; - break; - case 1: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); - Event_onWait = false; - break; - } - break; - case 16: - switch(Step) - { - case 0: - DoScriptText(CLINTAR_SPIRIT_SAY_GET_TWO, me, pPlayer); - Event_Timer = 15000; - Step = 1; - break; - case 1: - Event_onWait = false; - break; - } - break; - case 20: - switch(Step) - { - case 0: - { - Creature *mob = me->SummonCreature(ASPECT_RAVEN, ASPECT_RAVEN_SUMMON_X, ASPECT_RAVEN_SUMMON_Y, ASPECT_RAVEN_SUMMON_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000); - if (mob) - { - mob->AddThreat(me,10000.0f); - mob->AI()->AttackStart(me); - } - Event_Timer = 2000; - Step = 1; - break; - } - case 1: - Event_onWait = false; - break; - } - break; - case 24: - switch(Step) - { - case 0: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 133); - Event_Timer = 5000; - Step = 1; - break; - case 1: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); - Event_onWait = false; - break; - } - break; - case 25: - switch(Step) - { - case 0: - DoScriptText(CLINTAR_SPIRIT_SAY_GET_THREE, me, pPlayer); - Event_Timer = 4000; - Step = 1; - break; - case 1: - Event_onWait = false; - break; - } - break; - case 40: - switch(Step) - { - case 0: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 2); - DoScriptText(CLINTAR_SPIRIT_SAY_GET_FINAL, me, pPlayer); - pPlayer->CompleteQuest(10965); - Event_Timer = 1500; - Step = 1; - break; - case 1: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); - Event_Timer = 3000; - Step = 2; - break; - case 2: - pPlayer->TalkedToCreature(me->GetEntry(), me->GetGUID()); - PlayerGUID = 0; - Reset(); - me->setDeathState(JUST_DIED); - break; - } - break; - default: - Event_onWait = false; - break; - } - - } else if (Event_onWait) Event_Timer -= diff; - } - - void WaypointReached(uint32 id) - { - CurrWP = id; - Event_Timer = 0; - Step = 0; - Event_onWait = true; - } -}; - -CreatureAI* GetAI_npc_clintar_spirit(Creature* pCreature) -{ - return new npc_clintar_spiritAI (pCreature); -} - -/*#### -# npc_clintar_dreamwalker -####*/ - -#define CLINTAR_SPIRIT 22916 - -bool QuestAccept_npc_clintar_dreamwalker(Player* pPlayer, Creature* pCreature, Quest const *quest) -{ - if (quest->GetQuestId() == 10965) - { - Creature *clintar_spirit = pCreature->SummonCreature(CLINTAR_SPIRIT, CLINTAR_SPIRIT_SUMMON_X, CLINTAR_SPIRIT_SUMMON_Y, CLINTAR_SPIRIT_SUMMON_Z, CLINTAR_SPIRIT_SUMMON_O, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 100000); - if (clintar_spirit) - CAST_AI(npc_clintar_spiritAI, clintar_spirit->AI())->StartEvent(pPlayer); - } - return true; -} - -/*#### -# -####*/ - -void AddSC_moonglade() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_bunthen_plainswind"; - newscript->pGossipHello = &GossipHello_npc_bunthen_plainswind; - newscript->pGossipSelect = &GossipSelect_npc_bunthen_plainswind; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_great_bear_spirit"; - newscript->pGossipHello = &GossipHello_npc_great_bear_spirit; - newscript->pGossipSelect = &GossipSelect_npc_great_bear_spirit; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_silva_filnaveth"; - newscript->pGossipHello = &GossipHello_npc_silva_filnaveth; - newscript->pGossipSelect = &GossipSelect_npc_silva_filnaveth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_clintar_dreamwalker"; - newscript->pQuestAccept = &QuestAccept_npc_clintar_dreamwalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_clintar_spirit"; - newscript->GetAI = &GetAI_npc_clintar_spirit; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/mulgore.cpp b/src/server/scripts/kalimdor/mulgore.cpp deleted file mode 100644 index c87e5e36dad..00000000000 --- a/src/server/scripts/kalimdor/mulgore.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Mulgore -SD%Complete: 100 -SDComment: Support for quest: 11129, 772 -SDCategory: Mulgore -EndScriptData */ - -/* ContentData -npc_skorn_whitecloud -npc_kyle_frenzied -npc_plains_vision -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -# npc_skorn_whitecloud -######*/ - -#define GOSSIP_SW "Tell me a story, Skorn." - -bool GossipHello_npc_skorn_whitecloud(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (!pPlayer->GetQuestRewardStatus(770)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(522, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_skorn_whitecloud(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - pPlayer->SEND_GOSSIP_MENU(523, pCreature->GetGUID()); - - return true; -} - -/*##### -# npc_kyle_frenzied -######*/ - -enum eKyleFrenzied -{ - //emote signed for 7780 but propably thats wrong id. - EMOTE_SEE_LUNCH = -1000340, - EMOTE_EAT_LUNCH = -1000341, - EMOTE_DANCE = -1000342, - - SPELL_LUNCH = 42222, - NPC_KYLE_FRENZIED = 23616, - NPC_KYLE_FRIENDLY = 23622, - POINT_ID = 1 -}; - -struct npc_kyle_frenziedAI : public ScriptedAI -{ - npc_kyle_frenziedAI(Creature *c) : ScriptedAI(c) {} - - bool bEvent; - bool m_bIsMovingToLunch; - uint64 uiPlayerGUID; - uint32 uiEventTimer; - uint8 uiEventPhase; - - void Reset() - { - bEvent = false; - m_bIsMovingToLunch = false; - uiPlayerGUID = 0; - uiEventTimer = 5000; - uiEventPhase = 0; - - if (me->GetEntry() == NPC_KYLE_FRIENDLY) - me->UpdateEntry(NPC_KYLE_FRENZIED); - } - - void SpellHit(Unit* pCaster, SpellEntry const* pSpell) - { - if (!me->getVictim() && !bEvent && pSpell->Id == SPELL_LUNCH) - { - if (pCaster->GetTypeId() == TYPEID_PLAYER) - uiPlayerGUID = pCaster->GetGUID(); - - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) - { - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); - } - - bEvent = true; - DoScriptText(EMOTE_SEE_LUNCH, me); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_CREATURE_SPECIAL); - } - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE || !bEvent) - return; - - if (uiPointId == POINT_ID) - m_bIsMovingToLunch = false; - } - - void UpdateAI(const uint32 diff) - { - if (bEvent) - { - if (m_bIsMovingToLunch) - return; - - if (uiEventTimer <= diff) - { - uiEventTimer = 5000; - ++uiEventPhase; - - switch(uiEventPhase) - { - case 1: - if (Unit* pUnit = Unit::GetUnit(*me,uiPlayerGUID)) - { - if (GameObject* pGo = pUnit->GetGameObject(SPELL_LUNCH)) - { - m_bIsMovingToLunch = true; - me->GetMotionMaster()->MovePoint(POINT_ID, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ()); - } - } - break; - case 2: - DoScriptText(EMOTE_EAT_LUNCH, me); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USESTANDING); - break; - case 3: - if (Player* pUnit = Unit::GetPlayer(uiPlayerGUID)) - pUnit->TalkedToCreature(me->GetEntry(), me->GetGUID()); - - me->UpdateEntry(NPC_KYLE_FRIENDLY); - break; - case 4: - uiEventTimer = 30000; - DoScriptText(EMOTE_DANCE, me); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCESPECIAL); - break; - case 5: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - Reset(); - me->GetMotionMaster()->Clear(); - break; - } - } - else - uiEventTimer -= diff; - } - } -}; - -CreatureAI* GetAI_npc_kyle_frenzied(Creature* pCreature) -{ - return new npc_kyle_frenziedAI (pCreature); -} - -/*##### -# npc_plains_vision -######*/ - -float wp_plain_vision[50][3] = -{ - {-2226.32, -408.095, -9.36235}, - {-2203.04, -437.212, -5.72498}, - {-2163.91, -457.851, -7.09049}, - {-2123.87, -448.137, -9.29591}, - {-2104.66, -427.166, -6.49513}, - {-2101.48, -422.826, -5.3567}, - {-2097.56, -417.083, -7.16716}, - {-2084.87, -398.626, -9.88973}, - {-2072.71, -382.324, -10.2488}, - {-2054.05, -356.728, -6.22468}, - {-2051.8, -353.645, -5.35791}, - {-2049.08, -349.912, -6.15723}, - {-2030.6, -310.724, -9.59302}, - {-2002.15, -249.308, -10.8124}, - {-1972.85, -195.811, -10.6316}, - {-1940.93, -147.652, -11.7055}, - {-1888.06, -81.943, -11.4404}, - {-1837.05, -34.0109, -12.258}, - {-1796.12, -14.6462, -10.3581}, - {-1732.61, -4.27746, -10.0213}, - {-1688.94, -0.829945, -11.7103}, - {-1681.32, 13.0313, -9.48056}, - {-1677.04, 36.8349, -7.10318}, - {-1675.2, 68.559, -8.95384}, - {-1676.57, 89.023, -9.65104}, - {-1678.16, 110.939, -10.1782}, - {-1677.86, 128.681, -5.73869}, - {-1675.27, 144.324, -3.47916}, - {-1671.7, 163.169, -1.23098}, - {-1666.61, 181.584, 5.26145}, - {-1661.51, 196.154, 8.95252}, - {-1655.47, 210.811, 8.38727}, - {-1647.07, 226.947, 5.27755}, - {-1621.65, 232.91, 2.69579}, - {-1600.23, 237.641, 2.98539}, - {-1576.07, 242.546, 4.66541}, - {-1554.57, 248.494, 6.60377}, - {-1547.53, 259.302, 10.6741}, - {-1541.7, 269.847, 16.4418}, - {-1539.83, 278.989, 21.0597}, - {-1540.16, 290.219, 27.8247}, - {-1538.99, 298.983, 34.0032}, - {-1540.38, 307.337, 41.3557}, - {-1536.61, 314.884, 48.0179}, - {-1532.42, 323.277, 55.6667}, - {-1528.77, 329.774, 61.1525}, - {-1525.65, 333.18, 63.2161}, - {-1517.01, 350.713, 62.4286}, - {-1511.39, 362.537, 62.4539}, - {-1508.68, 366.822, 62.733} -}; - -struct npc_plains_visionAI : public ScriptedAI -{ - npc_plains_visionAI(Creature *c) : ScriptedAI(c) {} - - bool newWaypoint; - uint8 WayPointId; - uint8 amountWP; - - void Reset() - { - WayPointId = 0; - newWaypoint = true; - amountWP = 49; - } - - void EnterCombat(Unit* /*who*/){} - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id < amountWP) - { - ++WayPointId; - newWaypoint = true; - } - else - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (newWaypoint) - { - me->GetMotionMaster()->MovePoint(WayPointId, wp_plain_vision[WayPointId][0], wp_plain_vision[WayPointId][1], wp_plain_vision[WayPointId][2]); - newWaypoint = false; - } - } -}; - -CreatureAI* GetAI_npc_plains_vision(Creature* pCreature) -{ - return new npc_plains_visionAI (pCreature); -} - -/*##### -# -######*/ - -void AddSC_mulgore() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_skorn_whitecloud"; - newscript->pGossipHello = &GossipHello_npc_skorn_whitecloud; - newscript->pGossipSelect = &GossipSelect_npc_skorn_whitecloud; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_kyle_frenzied"; - newscript->GetAI = &GetAI_npc_kyle_frenzied; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_plains_vision"; - newscript->GetAI = &GetAI_npc_plains_vision; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp b/src/server/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp deleted file mode 100644 index 2d351d6c6a2..00000000000 --- a/src/server/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp +++ /dev/null @@ -1,500 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Onyxia -SD%Complete: 95 -SDComment: - Ground visual for Deep Breath effect; - Wing Buffet not ignoring armor; - Not summoning whelps on phase 3 (lacks info) - -SDCategory: Onyxia's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "onyxias_lair.h" - -enum eYells -{ - SAY_AGGRO = -1249000, - SAY_KILL = -1249001, - SAY_PHASE_2_TRANS = -1249002, - SAY_PHASE_3_TRANS = -1249003, - EMOTE_BREATH = -1249004, -}; - -enum eSpells -{ - // Phase 1 spells - SPELL_WING_BUFFET = 18500, - SPELL_FLAME_BREATH = 18435, - SPELL_CLEAVE = 68868, - SPELL_TAIL_SWEEP = 68867, - - // Phase 2 spells - SPELL_DEEP_BREATH = 23461, - SPELL_FIREBALL = 18392, - - //Not much choise about these. We have to make own defintion on the direction/start-end point - SPELL_BREATH_NORTH_TO_SOUTH = 17086, // 20x in "array" - SPELL_BREATH_SOUTH_TO_NORTH = 18351, // 11x in "array" - - SPELL_BREATH_EAST_TO_WEST = 18576, // 7x in "array" - SPELL_BREATH_WEST_TO_EAST = 18609, // 7x in "array" - - SPELL_BREATH_SE_TO_NW = 18564, // 12x in "array" - SPELL_BREATH_NW_TO_SE = 18584, // 12x in "array" - SPELL_BREATH_SW_TO_NE = 18596, // 12x in "array" - SPELL_BREATH_NE_TO_SW = 18617, // 12x in "array" - - //SPELL_BREATH = 21131, // 8x in "array", different initial cast than the other arrays - - // Phase 3 spells - SPELL_BELLOWING_ROAR = 18431, -}; - -struct sOnyxMove -{ - uint32 uiLocId; - uint32 uiLocIdEnd; - uint32 uiSpellId; - float fX, fY, fZ; -}; - -static sOnyxMove aMoveData[]= -{ - {0, 1, SPELL_BREATH_WEST_TO_EAST, -33.5561f, -182.682f, -56.9457f},//west - {1, 0, SPELL_BREATH_EAST_TO_WEST, -31.4963f, -250.123f, -55.1278f},//east - {2, 4, SPELL_BREATH_NW_TO_SE, 6.8951f, -180.246f, -55.896f},//north-west - {3, 5, SPELL_BREATH_NE_TO_SW, 10.2191f, -247.912f, -55.896f},//north-east - {4, 2, SPELL_BREATH_SE_TO_NW, -63.5156f, -240.096f, -55.477f},//south-east - {5, 3, SPELL_BREATH_SW_TO_NE, -58.2509f, -189.020f, -55.790f},//south-west - {6, 7, SPELL_BREATH_SOUTH_TO_NORTH, -65.8444f, -213.809f, -55.2985f},//south - {7, 6, SPELL_BREATH_NORTH_TO_SOUTH, 22.8763f, -217.152f, -55.0548f},//north -}; - -const Position MiddleRoomLocation = {-23.6155, -215.357, -55.7344}; - -static Position aSpawnLocations[3]= -{ - //Whelps - {-30.127, -254.463, -89.440}, - {-30.817, -177.106, -89.258}, - //Lair Guard - {-145.950, -212.831, -68.659} -}; - -struct boss_onyxiaAI : public ScriptedAI -{ - boss_onyxiaAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) - { - m_pInstance = pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* m_pInstance; - SummonList Summons; - - uint32 m_uiPhase; - - uint32 m_uiFlameBreathTimer; - uint32 m_uiCleaveTimer; - uint32 m_uiTailSweepTimer; - uint32 m_uiWingBuffetTimer; - - uint32 m_uiMovePoint; - uint32 m_uiMovementTimer; - sOnyxMove* m_pPointData; - - uint32 m_uiFireballTimer; - uint32 m_uiWhelpTimer; - uint32 m_uiLairGuardTimer; - uint32 m_uiDeepBreathTimer; - - uint32 m_uiBellowingRoarTimer; - - uint8 m_uiSummonWhelpCount; - uint8 m_uiSummonLairGuardCount; - bool m_bIsMoving; - - void Reset() - { - if (!IsCombatMovement()) - SetCombatMovement(true); - - m_uiPhase = PHASE_START; - - m_uiFlameBreathTimer = urand(10000, 20000); - m_uiTailSweepTimer = urand(15000, 20000); - m_uiCleaveTimer = urand(2000, 5000); - m_uiWingBuffetTimer = urand(10000, 20000); - - m_uiMovePoint = urand(0, 5); - m_uiMovementTimer = 20000; - m_pPointData = GetMoveData(); - - m_uiFireballTimer = 15000; - m_uiWhelpTimer = 1000; - m_uiLairGuardTimer = 15000; - m_uiDeepBreathTimer = 85000; - - m_uiBellowingRoarTimer = 30000; - - Summons.DespawnAll(); - m_uiSummonWhelpCount = 0; - m_uiSummonLairGuardCount = 0; - m_bIsMoving = false; - - if (m_pInstance) - { - m_pInstance->SetData(DATA_ONYXIA, NOT_STARTED); - m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void EnterCombat(Unit* pWho) - { - DoScriptText(SAY_AGGRO, me); - me->SetInCombatWithZone(); - - if (m_pInstance) - { - m_pInstance->SetData(DATA_ONYXIA, IN_PROGRESS); - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - sLog.outBasic("[Onyxia] DoStartTimedAchievement(%u,%u)",ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void JustDied(Unit* killer) - { - if (m_pInstance) - m_pInstance->SetData(DATA_ONYXIA, DONE); - - Summons.DespawnAll(); - } - - void JustSummoned(Creature *pSummoned) - { - pSummoned->SetInCombatWithZone(); - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - pSummoned->AI()->AttackStart(pTarget); - - switch (pSummoned->GetEntry()) - { - case NPC_WHELP: - ++m_uiSummonWhelpCount; - break; - case NPC_LAIRGUARD: - pSummoned->setActive(true); - ++m_uiSummonLairGuardCount; - break; - } - Summons.Summon(pSummoned); - } - - void SummonedCreatureDespawn(Creature *summon) - { - Summons.Despawn(summon); - } - - void KilledUnit(Unit* pVictim) - { - DoScriptText(SAY_KILL, me); - } - - void SpellHit(Unit *pCaster, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_BREATH_EAST_TO_WEST || - pSpell->Id == SPELL_BREATH_WEST_TO_EAST || - pSpell->Id == SPELL_BREATH_SE_TO_NW || - pSpell->Id == SPELL_BREATH_NW_TO_SE || - pSpell->Id == SPELL_BREATH_SW_TO_NE || - pSpell->Id == SPELL_BREATH_NE_TO_SW) - { - m_pPointData = GetMoveData(); - m_uiMovePoint = m_pPointData->uiLocIdEnd; - - me->SetSpeed(MOVE_FLIGHT, 1.5f); - me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation); - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type == POINT_MOTION_TYPE) - { - switch (id) - { - case 8: - m_pPointData = GetMoveData(); - if (m_pPointData) - { - me->SetSpeed(MOVE_FLIGHT, 1.0f); - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); - } - break; - case 9: - me->GetMotionMaster()->MoveChase(me->getVictim()); - m_uiBellowingRoarTimer = 1000; - break; - default: - m_bIsMoving = false; - break; - } - } - } - - void SpellHitTarget(Unit* target, const SpellEntry* pSpell) - { - //Workaround - Couldn't find a way to group this spells (All Eruption) - if (((pSpell->Id >= 17086 && pSpell->Id <= 17095) || - (pSpell->Id == 17097) || - (pSpell->Id >= 18351 && pSpell->Id <= 18361) || - (pSpell->Id >= 18564 && pSpell->Id <= 18576) || - (pSpell->Id >= 18578 && pSpell->Id <= 18607) || - (pSpell->Id == 18609) || - (pSpell->Id >= 18611 && pSpell->Id <= 18628) || - (pSpell->Id >= 21132 && pSpell->Id <= 21133) || - (pSpell->Id >= 21135 && pSpell->Id <= 21139) || - (pSpell->Id >= 22191 && pSpell->Id <= 22202) || - (pSpell->Id >= 22267 && pSpell->Id <= 22268)) && - (target->GetTypeId() == TYPEID_PLAYER)) - { - if (m_pInstance) - { - m_pInstance->SetData(DATA_SHE_DEEP_BREATH_MORE, FAIL); - } - } - } - - sOnyxMove* GetMoveData() - { - uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); - - for (uint32 i = 0; i < uiMaxCount; ++i) - { - if (aMoveData[i].uiLocId == m_uiMovePoint) - return &aMoveData[i]; - } - - return NULL; - } - - void SetNextRandomPoint() - { - uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); - - int iTemp = rand()%(uiMaxCount-1); - - if (iTemp >= m_uiMovePoint) - ++iTemp; - - m_uiMovePoint = iTemp; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //Common to PHASE_START && PHASE_END - if (m_uiPhase == PHASE_START || m_uiPhase == PHASE_END) - { - //Specific to PHASE_START || PHASE_END - if (m_uiPhase == PHASE_START) - { - if (me->GetHealth()*100 / me->GetMaxHealth() < 60) - { - m_uiPhase = PHASE_BREATH; - - if (m_pInstance) - m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); - - SetCombatMovement(false); - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - me->SetFlying(true); - - DoScriptText(SAY_PHASE_2_TRANS, me); - - if (m_pPointData) - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); - - m_uiWhelpTimer = 1000; - return; - } - } - else - { - if (m_uiBellowingRoarTimer <= uiDiff) - { - DoCastVictim(SPELL_BELLOWING_ROAR); - // Eruption - GameObject* pFloor = NULL; - Trinity::GameObjectInRangeCheck check(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 15); - Trinity::GameObjectLastSearcher searcher(me, pFloor, check); - me->VisitNearbyGridObject(30, searcher); - if (m_pInstance && pFloor) - m_pInstance->SetData64(DATA_FLOOR_ERUPTION_GUID, pFloor->GetGUID()); - m_uiBellowingRoarTimer = 30000; - } - else - m_uiBellowingRoarTimer -= uiDiff; - } - - if (m_uiFlameBreathTimer <= uiDiff) - { - DoCastVictim(SPELL_FLAME_BREATH); - m_uiFlameBreathTimer = urand(10000, 20000); - } - else - m_uiFlameBreathTimer -= uiDiff; - - if (m_uiTailSweepTimer <= uiDiff) - { - DoCastAOE(SPELL_TAIL_SWEEP); - m_uiTailSweepTimer = urand(15000, 20000); - } - else - m_uiTailSweepTimer -= uiDiff; - - if (m_uiCleaveTimer <= uiDiff) - { - DoCastVictim(SPELL_CLEAVE); - m_uiCleaveTimer = urand(2000, 5000); - } - else - m_uiCleaveTimer -= uiDiff; - - if (m_uiWingBuffetTimer <= uiDiff) - { - DoCastVictim(SPELL_WING_BUFFET); - m_uiWingBuffetTimer = urand(15000, 30000); - } - else - m_uiWingBuffetTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - else - { - if (me->GetHealth()*100 / me->GetMaxHealth() < 40) - { - m_uiPhase = PHASE_END; - if (m_pInstance) - m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); - DoScriptText(SAY_PHASE_3_TRANS, me); - - SetCombatMovement(true); - me->SetFlying(false); - m_bIsMoving = false; - me->GetMotionMaster()->MovePoint(9,me->GetHomePosition()); - return; - } - - if (m_uiDeepBreathTimer <= uiDiff) - { - if (!m_bIsMoving) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoScriptText(EMOTE_BREATH, me); - DoCast(me, m_pPointData->uiSpellId); - m_uiDeepBreathTimer = 70000; - } - } - else - m_uiDeepBreathTimer -= uiDiff; - - if (m_uiMovementTimer <= uiDiff) - { - if (!m_bIsMoving) - { - SetNextRandomPoint(); - m_pPointData = GetMoveData(); - - if (!m_pPointData) - return; - - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); - m_bIsMoving = true; - m_uiMovementTimer = 25000; - } - } - else - m_uiMovementTimer -= uiDiff; - - if (m_uiFireballTimer <= uiDiff) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FIREBALL); - - m_uiFireballTimer = 8000; - } - } - else - m_uiFireballTimer -= uiDiff; - - if (m_uiLairGuardTimer <= uiDiff) - { - me->SummonCreature(NPC_LAIRGUARD, aSpawnLocations[2].GetPositionX(), aSpawnLocations[2].GetPositionY(), aSpawnLocations[2].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - if (m_uiSummonLairGuardCount >= RAID_MODE(1,2)) - { - m_uiSummonLairGuardCount = 0; - m_uiLairGuardTimer = 30000; - } - else - m_uiLairGuardTimer = 2000; - } - else - m_uiLairGuardTimer -= uiDiff; - - if (m_uiWhelpTimer <= uiDiff) - { - me->SummonCreature(NPC_WHELP, aSpawnLocations[0].GetPositionX(), aSpawnLocations[0].GetPositionY(), aSpawnLocations[0].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - me->SummonCreature(NPC_WHELP, aSpawnLocations[1].GetPositionX(), aSpawnLocations[1].GetPositionY(), aSpawnLocations[1].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - if (m_uiSummonWhelpCount >= RAID_MODE(20,40)) - { - m_uiSummonWhelpCount = 0; - m_uiWhelpTimer = 90000; - } - else - m_uiWhelpTimer = 500; - } - else - m_uiWhelpTimer -= uiDiff; - } - } -}; - -CreatureAI* GetAI_boss_onyxiaAI(Creature* pCreature) -{ - return new boss_onyxiaAI (pCreature); -} - -void AddSC_boss_onyxia() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_onyxia"; - newscript->GetAI = &GetAI_boss_onyxiaAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp b/src/server/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp deleted file mode 100644 index cfd66bf80f4..00000000000 --- a/src/server/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Onyxias_Lair -SD%Complete: 100 -SDComment: -SDCategory: Onyxia's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "onyxias_lair.h" - -struct instance_onyxias_lair : public ScriptedInstance -{ - instance_onyxias_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - //Eruption is a BFS graph problem - //One map to remember all floor, one map to keep floor that still need to erupt and one queue to know what needs to be removed - std::map FloorEruptionGUID[2]; - std::queue FloorEruptionGUIDQueue; - - uint64 m_uiOnyxiasGUID; - uint32 m_uiOnyxiaLiftoffTimer; - uint32 m_uiManyWhelpsCounter; - uint32 m_uiEruptTimer; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - - bool m_bAchievManyWhelpsHandleIt; - bool m_bAchievSheDeepBreathMore; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiOnyxiasGUID = 0; - m_uiOnyxiaLiftoffTimer = 0; - m_uiManyWhelpsCounter = 0; - m_bAchievManyWhelpsHandleIt = false; - m_bAchievSheDeepBreathMore = true; - - m_uiEruptTimer = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - switch (pCreature->GetEntry()) - { - case NPC_ONYXIA: - m_uiOnyxiasGUID = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if ((pGo->GetGOInfo()->displayId == 4392 || pGo->GetGOInfo()->displayId == 4472) && pGo->GetGOInfo()->trap.spellId == 17731) - { - if (add) - FloorEruptionGUID[0].insert(std::make_pair(pGo->GetGUID(),0)); - else - FloorEruptionGUID[0].erase(pGo->GetGUID()); - return; - } - - switch(pGo->GetEntry()) - { - case GO_WHELP_SPAWNER: - Position pGoPos; - pGo->GetPosition(&pGoPos); - if (Creature* pTemp = pGo->SummonCreature(NPC_WHELP,pGoPos,TEMPSUMMON_CORPSE_DESPAWN)) - { - pTemp->SetInCombatWithZone(); - ++m_uiManyWhelpsCounter; - } - break; - } - } - - void FloorEruption(uint64 floorEruptedGUID) - { - if (GameObject *pFloorEruption = instance->GetGameObject(floorEruptedGUID)) - { - //THIS GOB IS A TRAP - What shall i do? =( - //Cast it spell? Copyed Heigan method - pFloorEruption->SendCustomAnim(); - pFloorEruption->CastSpell(NULL, Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL ? 17731 : 69294); //pFloorEruption->GetGOInfo()->trap.spellId - - //Get all immediatly nearby floors - std::list nearFloorList; - Trinity::GameObjectInRangeCheck check(pFloorEruption->GetPositionX(), pFloorEruption->GetPositionY(), pFloorEruption->GetPositionZ(), 15); - Trinity::GameObjectListSearcher searcher(pFloorEruption, nearFloorList, check); - pFloorEruption->VisitNearbyGridObject(999, searcher); - //remove all that are not present on FloorEruptionGUID[1] and update treeLen on each GUID - for (std::list::const_iterator itr = nearFloorList.begin(); itr != nearFloorList.end(); ++itr) - { - if (((*itr)->GetGOInfo()->displayId == 4392 || (*itr)->GetGOInfo()->displayId == 4472) && (*itr)->GetGOInfo()->trap.spellId == 17731) - { - uint64 nearFloorGUID = (*itr)->GetGUID(); - if (FloorEruptionGUID[1].find(nearFloorGUID) != FloorEruptionGUID[1].end() && (*FloorEruptionGUID[1].find(nearFloorGUID)).second == 0) - { - (*FloorEruptionGUID[1].find(nearFloorGUID)).second = (*FloorEruptionGUID[1].find(floorEruptedGUID)).second+1; - FloorEruptionGUIDQueue.push(nearFloorGUID); - } - } - } - } - FloorEruptionGUID[1].erase(floorEruptedGUID); - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case DATA_ONYXIA: - m_auiEncounter[0] = uiData; - if (uiData == IN_PROGRESS) - SetData(DATA_SHE_DEEP_BREATH_MORE, IN_PROGRESS); - break; - case DATA_ONYXIA_PHASE: - if (uiData == PHASE_BREATH) //Used to mark the liftoff phase - { - m_bAchievManyWhelpsHandleIt = false; - m_uiManyWhelpsCounter = 0; - m_uiOnyxiaLiftoffTimer = 10*IN_MILISECONDS; - } - break; - case DATA_SHE_DEEP_BREATH_MORE: - if (uiData == IN_PROGRESS) - { - m_bAchievSheDeepBreathMore = true; - } - else if (uiData == FAIL) - { - m_bAchievSheDeepBreathMore = false; - } - break; - } - - if (uiType < MAX_ENCOUNTER && uiData == DONE) - SaveToDB(); - } - - void SetData64(uint32 uiType, uint64 uiData) - { - switch(uiType) - { - case DATA_FLOOR_ERUPTION_GUID: - FloorEruptionGUID[1] = FloorEruptionGUID[0]; - FloorEruptionGUIDQueue.push(uiData); - m_uiEruptTimer = 2500; - break; - } - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case DATA_ONYXIA: - return m_auiEncounter[0]; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_ONYXIA_GUID: - return m_uiOnyxiasGUID; - } - - return 0; - } - - void Update(uint32 uiDiff) - { - if (GetData(DATA_ONYXIA) == IN_PROGRESS) - { - if (m_uiOnyxiaLiftoffTimer && m_uiOnyxiaLiftoffTimer <= uiDiff) - { - m_uiOnyxiaLiftoffTimer = 0; - if (m_uiManyWhelpsCounter >= 50) - m_bAchievManyWhelpsHandleIt = true; - } else m_uiOnyxiaLiftoffTimer -= uiDiff; - } - - if (!FloorEruptionGUIDQueue.empty()) - { - if (m_uiEruptTimer <= uiDiff) - { - uint32 treeHeight = 0; - do - { - treeHeight = (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second; - FloorEruption(FloorEruptionGUIDQueue.front()); - FloorEruptionGUIDQueue.pop(); - } while (!FloorEruptionGUIDQueue.empty() && (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second == treeHeight); - m_uiEruptTimer = 1000; - } - else - m_uiEruptTimer -= uiDiff; - } - } - - bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* target = NULL, uint32 miscvalue1 = 0) - { - switch(criteria_id) - { - case ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER: // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s - case ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER: // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s - return m_bAchievManyWhelpsHandleIt; - case ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER: // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath - case ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER: // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath - return m_bAchievSheDeepBreathMore; - } - return false; - } -}; - -InstanceData* GetInstanceData_instance_onyxias_lair(Map* pMap) -{ - return new instance_onyxias_lair(pMap); -} - -void AddSC_instance_onyxias_lair() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_onyxias_lair"; - newscript->GetInstanceData = &GetInstanceData_instance_onyxias_lair; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/onyxias_lair/onyxias_lair.h b/src/server/scripts/kalimdor/onyxias_lair/onyxias_lair.h deleted file mode 100644 index cadd5b5a2d5..00000000000 --- a/src/server/scripts/kalimdor/onyxias_lair/onyxias_lair.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_ONYXIAS_LAIR_H -#define DEF_ONYXIAS_LAIR_H - -enum eData64 -{ - DATA_ONYXIA_GUID, - DATA_FLOOR_ERUPTION_GUID -}; - -enum eInstanceData -{ - DATA_ONYXIA, - MAX_ENCOUNTER, - - DATA_ONYXIA_PHASE, - DATA_SHE_DEEP_BREATH_MORE, - DATA_MANY_WHELPS_COUNT -}; - -enum eCreatures -{ - NPC_WHELP = 11262, - NPC_LAIRGUARD = 36561, - - NPC_ONYXIA = 10184 -}; - -enum eOnyxiaPhases -{ - PHASE_START = 1, - PHASE_BREATH = 2, - PHASE_END = 3 -}; - -enum eGameObjects -{ - GO_WHELP_SPAWNER = 176510, - GO_WHELP_EGG = 176511 -}; - -enum eAchievementData -{ - ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER = 12565, // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s - ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER = 12568, // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s - ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER = 12566, // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath - ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER = 12569, // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath - ACHIEV_TIMED_START_EVENT = 6601, // Timed event for achievement 4402, 4005: More Dots! (10,25 player) 5 min kill -}; -#endif diff --git a/src/server/scripts/kalimdor/orgrimmar.cpp b/src/server/scripts/kalimdor/orgrimmar.cpp deleted file mode 100644 index 71fa4381e9d..00000000000 --- a/src/server/scripts/kalimdor/orgrimmar.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Orgrimmar -SD%Complete: 100 -SDComment: Quest support: 2460, 5727, 6566 -SDCategory: Orgrimmar -EndScriptData */ - -/* ContentData -npc_neeru_fireblade npc_text + gossip options text missing -npc_shenthul -npc_thrall_warchief -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_neeru_fireblade -######*/ - -#define QUEST_5727 5727 - -#define GOSSIP_HNF "You may speak frankly, Neeru..." -#define GOSSIP_SNF "[PH] ..." -bool GossipHello_npc_neeru_fireblade(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_5727) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HNF, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(4513, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_neeru_fireblade(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SNF, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(4513, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(QUEST_5727); - break; - } - return true; -} - -/*###### -## npc_shenthul -######*/ - -enum eShenthul -{ - QUEST_SHATTERED_SALUTE = 2460 -}; - -struct npc_shenthulAI : public ScriptedAI -{ - npc_shenthulAI(Creature* c) : ScriptedAI(c) {} - - bool CanTalk; - bool CanEmote; - uint32 Salute_Timer; - uint32 Reset_Timer; - uint64 PlayerGUID; - - void Reset() - { - CanTalk = false; - CanEmote = false; - Salute_Timer = 6000; - Reset_Timer = 0; - PlayerGUID = 0; - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (CanEmote) - { - if (Reset_Timer <= diff) - { - if (Player* pPlayer = Unit::GetPlayer(PlayerGUID)) - { - if (pPlayer->GetTypeId() == TYPEID_PLAYER && pPlayer->GetQuestStatus(QUEST_SHATTERED_SALUTE) == QUEST_STATUS_INCOMPLETE) - pPlayer->FailQuest(QUEST_SHATTERED_SALUTE); - } - Reset(); - } else Reset_Timer -= diff; - } - - if (CanTalk && !CanEmote) - { - if (Salute_Timer <= diff) - { - me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); - CanEmote = true; - Reset_Timer = 60000; - } else Salute_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void ReceiveEmote(Player* pPlayer, uint32 emote) - { - if (emote == TEXTEMOTE_SALUTE && pPlayer->GetQuestStatus(QUEST_SHATTERED_SALUTE) == QUEST_STATUS_INCOMPLETE) - { - if (CanEmote) - { - pPlayer->AreaExploredOrEventHappens(QUEST_SHATTERED_SALUTE); - Reset(); - } - } - } -}; - -CreatureAI* GetAI_npc_shenthul(Creature* pCreature) -{ - return new npc_shenthulAI (pCreature); -} - -bool QuestAccept_npc_shenthul(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_SHATTERED_SALUTE) - { - CAST_AI(npc_shenthulAI, pCreature->AI())->CanTalk = true; - CAST_AI(npc_shenthulAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); - } - return true; -} - -/*###### -## npc_thrall_warchief -######*/ - -#define QUEST_6566 6566 - -#define SPELL_CHAIN_LIGHTNING 16033 -#define SPELL_SHOCK 16034 - -#define GOSSIP_HTW "Please share your wisdom with me, Warchief." -#define GOSSIP_STW1 "What discoveries?" -#define GOSSIP_STW2 "Usurper?" -#define GOSSIP_STW3 "With all due respect, Warchief - why not allow them to be destroyed? Does this not strengthen our position?" -#define GOSSIP_STW4 "I... I did not think of it that way, Warchief." -#define GOSSIP_STW5 "I live only to serve, Warchief! My life is empty and meaningless without your guidance." -#define GOSSIP_STW6 "Of course, Warchief!" - -//TODO: verify abilities/timers -struct npc_thrall_warchiefAI : public ScriptedAI -{ - npc_thrall_warchiefAI(Creature* c) : ScriptedAI(c) {} - - uint32 ChainLightning_Timer; - uint32 Shock_Timer; - - void Reset() - { - ChainLightning_Timer = 2000; - Shock_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ChainLightning_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); - ChainLightning_Timer = 9000; - } else ChainLightning_Timer -= diff; - - if (Shock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHOCK); - Shock_Timer = 15000; - } else Shock_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_thrall_warchief(Creature* pCreature) -{ - return new npc_thrall_warchiefAI (pCreature); -} - -bool GossipHello_npc_thrall_warchief(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_6566) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HTW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_thrall_warchief(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(5733, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(5734, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(5735, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(5736, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(5737, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - pPlayer->SEND_GOSSIP_MENU(5738, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(QUEST_6566); - break; - } - return true; -} - -void AddSC_orgrimmar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_neeru_fireblade"; - newscript->pGossipHello = &GossipHello_npc_neeru_fireblade; - newscript->pGossipSelect = &GossipSelect_npc_neeru_fireblade; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_shenthul"; - newscript->GetAI = &GetAI_npc_shenthul; - newscript->pQuestAccept = &QuestAccept_npc_shenthul; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thrall_warchief"; - newscript->GetAI = &GetAI_npc_thrall_warchief; - newscript->pGossipHello = &GossipHello_npc_thrall_warchief; - newscript->pGossipSelect = &GossipSelect_npc_thrall_warchief; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp b/src/server/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp deleted file mode 100644 index 711c4f0b2c1..00000000000 --- a/src/server/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Amnennar_the_coldbringer -SD%Complete: 100 -SDComment: -SDCategory: Razorfen Downs -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1129000 -#define SAY_SUMMON60 -1129001 -#define SAY_SUMMON30 -1129002 -#define SAY_HP -1129003 -#define SAY_KILL -1129004 - -#define SPELL_AMNENNARSWRATH 13009 -#define SPELL_FROSTBOLT 15530 -#define SPELL_FROST_NOVA 15531 -#define SPELL_FROST_SPECTRES 12642 - -struct boss_amnennar_the_coldbringerAI : public ScriptedAI -{ - boss_amnennar_the_coldbringerAI(Creature *c) : ScriptedAI(c) {} - - uint32 AmnenarsWrath_Timer; - uint32 FrostBolt_Timer; - uint32 FrostNova_Timer; - bool Spectrals60; - bool Spectrals30; - bool Hp; - - void Reset() - { - AmnenarsWrath_Timer = 8000; - FrostBolt_Timer = 1000; - FrostNova_Timer = 10000 + rand()%5000; - Spectrals30 = false; - Spectrals60 = false; - Hp = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit() - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //AmnenarsWrath_Timer - if (AmnenarsWrath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_AMNENNARSWRATH); - AmnenarsWrath_Timer = 12000; - } else AmnenarsWrath_Timer -= diff; - - //FrostBolt_Timer - if (FrostBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - FrostBolt_Timer = 8000; - } else FrostBolt_Timer -= diff; - - if (FrostNova_Timer <= diff) - { - DoCast(me, SPELL_FROST_NOVA); - FrostNova_Timer = 15000; - } else FrostNova_Timer -= diff; - - if (!Spectrals60 && me->GetHealth()*100 / me->GetMaxHealth() < 60) - { - DoScriptText(SAY_SUMMON60, me); - DoCast(me->getVictim(), SPELL_FROST_SPECTRES); - Spectrals60 = true; - } - - if (!Hp && me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - DoScriptText(SAY_HP, me); - Hp = true; - } - - if (!Spectrals30 && me->GetHealth()*100 / me->GetMaxHealth() < 30) - { - DoScriptText(SAY_SUMMON30, me); - DoCast(me->getVictim(), SPELL_FROST_SPECTRES); - Spectrals30 = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_amnennar_the_coldbringer(Creature* pCreature) -{ - return new boss_amnennar_the_coldbringerAI (pCreature); -} - -void AddSC_boss_amnennar_the_coldbringer() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_amnennar_the_coldbringer"; - newscript->GetAI = &GetAI_boss_amnennar_the_coldbringer; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/razorfen_downs/instance_razorfen_downs.cpp b/src/server/scripts/kalimdor/razorfen_downs/instance_razorfen_downs.cpp deleted file mode 100644 index 04904f08a57..00000000000 --- a/src/server/scripts/kalimdor/razorfen_downs/instance_razorfen_downs.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "razorfen_downs.h" - -#define MAX_ENCOUNTER 1 - -struct instance_razorfen_downs : public ScriptedInstance -{ - instance_razorfen_downs(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - }; - - uint64 uiGongGUID; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint8 uiGongWaves; - - std::string str_data; - - void Initialize() - { - uiGongGUID = 0; - - uiGongWaves = 0; - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - saveStream << "T C " << m_auiEncounter[0] - << " " << uiGongWaves; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; - - if (dataHead1 == 'T' && dataHead2 == 'C') - { - m_auiEncounter[0] = data0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiGongWaves = data1; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*bAdd*/) - { - switch(pGo->GetEntry()) - { - case GO_GONG: - uiGongGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - break; - default: - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - if (uiType == DATA_GONG_WAVES) - { - uiGongWaves = uiData; - - switch(uiGongWaves) - { - case 9: - case 14: - if (GameObject* pGo = instance->GetGameObject(uiGongGUID)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - break; - case 1: - case 10: - case 16: - { - GameObject* pGo = instance->GetGameObject(uiGongGUID); - - if (!pGo) - return; - - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - - uint32 uiCreature = 0; - uint8 uiSummonTimes = 0; - - switch(uiGongWaves) - { - case 1: - uiCreature = CREATURE_TOMB_FIEND; - uiSummonTimes = 7; - break; - case 10: - uiCreature = CREATURE_TOMB_REAVER; - uiSummonTimes = 3; - break; - case 16: - uiCreature = CREATURE_TUTEN_KASH; - break; - default: - break; - } - - - if (Creature* pCreature = pGo->SummonCreature(uiCreature,2502.635,844.140,46.896,0.633)) - { - if (uiGongWaves == 10 || uiGongWaves == 1) - { - for (uint8 i = 0; i < uiSummonTimes; ++i) - { - if (Creature* pSummon = pGo->SummonCreature(uiCreature,2502.635 + float(irand(-5,5)),844.140 + float(irand(-5,5)),46.896,0.633)) - pSummon->GetMotionMaster()->MovePoint(0,2533.479 + float(irand(-5,5)),870.020 + float(irand(-5,5)),47.678); - } - } - pCreature->GetMotionMaster()->MovePoint(0,2533.479 + float(irand(-5,5)),870.020 + float(irand(-5,5)),47.678); - } - break; - } - default: - break; - } - } - - if (uiType == BOSS_TUTEN_KASH) - { - m_auiEncounter[0] = uiData; - - if (uiData == DONE) - SaveToDB(); - } - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case DATA_GONG_WAVES: - return uiGongWaves; - } - - return 0; - } - - uint64 GetData64(uint32 uiType) - { - switch(uiType) - { - case DATA_GONG: return uiGongGUID; - } - - return 0; - } -}; - -InstanceData* GetInstanceData_instance_razorfen_downs(Map* pMap) -{ - return new instance_razorfen_downs(pMap); -} - -void AddSC_instance_razorfen_downs() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "instance_razorfen_downs"; - newscript->GetInstanceData = &GetInstanceData_instance_razorfen_downs; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp b/src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp deleted file mode 100644 index 3e8f4049a37..00000000000 --- a/src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Razorfen_Downs -SD%Complete: 100 -SDComment: Support for Henry Stern(2 recipes) -SDCategory: Razorfen Downs -EndScriptData */ - -/* ContentData -npc_henry_stern -EndContentData */ - -#include "ScriptedPch.h" -#include "razorfen_downs.h" - -/*### -# npc_henry_stern -####*/ - -enum eEnums -{ - SPELL_GOLDTHORN_TEA = 13028, - SPELL_TEACHING_GOLDTHORN_TEA = 13029, - SPELL_MIGHT_TROLLS_BLOOD_POTION = 3451, - SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION = 13030, - GOSSIP_TEXT_TEA_ANSWER = 2114, - GOSSIP_TEXT_POTION_ANSWER = 2115, -}; - -#define GOSSIP_ITEM_TEA "Teach me the cooking recipe" -#define GOSSIP_ITEM_POTION "Teach me the alchemy recipe" - -bool GossipHello_npc_henry_stern (Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetBaseSkillValue(SKILL_COOKING) >= 175 && !pPlayer->HasSpell(SPELL_GOLDTHORN_TEA)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (pPlayer->GetBaseSkillValue(SKILL_ALCHEMY) >= 180 && !pPlayer->HasSpell(SPELL_MIGHT_TROLLS_BLOOD_POTION)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_POTION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_henry_stern (Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CastSpell(pPlayer, SPELL_TEACHING_GOLDTHORN_TEA, true); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_TEA_ANSWER, pCreature->GetGUID()); - } - - if (uiAction == GOSSIP_ACTION_INFO_DEF + 2) - { - pPlayer->CastSpell(pPlayer, SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION, true); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_POTION_ANSWER, pCreature->GetGUID()); - } - - return true; -} - -/*###### -## go_gong -######*/ - -bool GOHello_go_gong(Player* /*pPlayer*/, GameObject* pGO) -{ - //basic support, not blizzlike data is missing... - ScriptedInstance* pInstance = pGO->GetInstanceData(); - - if (pInstance) - { - pInstance->SetData(DATA_GONG_WAVES,pInstance->GetData(DATA_GONG_WAVES)+1); - return true; - } - - return false; -} - -enum eTombCreature -{ - SPELL_WEB = 745 -}; - -struct npc_tomb_creatureAI : public ScriptedAI -{ - npc_tomb_creatureAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiWebTimer; - - void Reset() - { - uiWebTimer = urand(5000,8000); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //from acid - if (me->GetEntry() == CREATURE_TOMB_REAVER) - { - if (uiWebTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_WEB); - uiWebTimer = urand(7000,16000); - } else uiWebTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(DATA_GONG_WAVES,pInstance->GetData(DATA_GONG_WAVES)+1); - } -}; - -CreatureAI* GetAI_npc_tomb_creature(Creature* pCreature) -{ - return new npc_tomb_creatureAI (pCreature); -} - -void AddSC_razorfen_downs() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_henry_stern"; - newscript->pGossipHello = &GossipHello_npc_henry_stern; - newscript->pGossipSelect = &GossipSelect_npc_henry_stern; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_gong"; - newscript->pGOHello = &GOHello_go_gong; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tomb_creature"; - newscript->GetAI = &GetAI_npc_tomb_creature; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.h b/src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.h deleted file mode 100644 index a67b4223c4a..00000000000 --- a/src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_RAZORFEN_DOWNS_H -#define DEF_RAZORFEN_DOWNS_H - -enum eData -{ - BOSS_TUTEN_KASH, - DATA_GONG_WAVES -}; - -enum eData64 -{ - DATA_GONG -}; - -enum eGameObject -{ - GO_GONG = 148917 -}; - -enum eCreature -{ - CREATURE_TOMB_FIEND = 7349, - CREATURE_TOMB_REAVER = 7351, - CREATURE_TUTEN_KASH = 7355 -}; - -#endif diff --git a/src/server/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp b/src/server/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp deleted file mode 100644 index 8a92d3d4d89..00000000000 --- a/src/server/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Razorfen_Kraul -SD%Complete: -SDComment: -SDCategory: Razorfen Kraul -EndScriptData */ - -#include "ScriptedPch.h" -#include "razorfen_kraul.h" - -#define WARD_KEEPERS_NR 2 - -struct instance_razorfen_kraul : public ScriptedInstance -{ - instance_razorfen_kraul(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 DoorWardGUID; - uint32 WardCheck_Timer; - int WardKeeperAlive; - - void Initialize() - { - WardKeeperAlive = 1; - WardCheck_Timer = 4000; - DoorWardGUID = 0; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - debug_log("TSCR: Instance Razorfen Kraul: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*apply*/) - { - switch(pGo->GetEntry()) - { - case 21099: DoorWardGUID = pGo->GetGUID(); break; - } - } - - void Update(uint32 diff) - { - if (WardCheck_Timer <= diff) - { - HandleGameObject(DoorWardGUID, WardKeeperAlive); - WardKeeperAlive = 0; - WardCheck_Timer = 4000; - }else - WardCheck_Timer -= diff; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_WARD_KEEPERS: - if (data == NOT_STARTED) - WardKeeperAlive = 1; - break; - } - } - -}; - -InstanceData* GetInstanceData_instance_razorfen_kraul(Map* pMap) -{ - return new instance_razorfen_kraul(pMap); -} - -void AddSC_instance_razorfen_kraul() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_razorfen_kraul"; - newscript->GetInstanceData = &GetInstanceData_instance_razorfen_kraul; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.cpp b/src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.cpp deleted file mode 100644 index 8470fa6c7ac..00000000000 --- a/src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Razorfen Kraul -SD%Complete: 100 -SDComment: Quest support: 1144 -SDCategory: Razorfen Kraul -EndScriptData */ - -/* ContentData -npc_willix -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "razorfen_kraul.h" - -#define SAY_READY -1047000 -#define SAY_POINT -1047001 -#define SAY_AGGRO1 -1047002 -#define SAY_BLUELEAF -1047003 -#define SAY_DANGER -1047004 -#define SAY_BAD -1047005 -#define SAY_THINK -1047006 -#define SAY_SOON -1047007 -#define SAY_FINALY -1047008 -#define SAY_WIN -1047009 -#define SAY_END -1047010 - -#define QUEST_WILLIX_THE_IMPORTER 1144 -#define ENTRY_BOAR 4514 -#define SPELL_QUILLBOAR_CHANNELING 7083 - -struct npc_willixAI : public npc_escortAI -{ - npc_willixAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch (i) - { - case 3: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - DoScriptText(SAY_POINT, me, pPlayer); - break; - case 4: - me->SummonCreature(ENTRY_BOAR, 2137.66, 1843.98, 48.08, 1.54, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 8: - DoScriptText(SAY_BLUELEAF, me, pPlayer); - break; - case 9: - DoScriptText(SAY_DANGER, me, pPlayer); - break; - case 13: - DoScriptText(SAY_BAD, me, pPlayer); - break; - case 14: - me->SummonCreature(ENTRY_BOAR, 2078.91, 1704.54, 56.77, 1.54, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 25: - DoScriptText(SAY_THINK, me, pPlayer); - break; - case 31: - DoScriptText(SAY_SOON, me, pPlayer); - break; - case 42: - DoScriptText(SAY_FINALY, me, pPlayer); - break; - case 43: - me->SummonCreature(ENTRY_BOAR, 1956.43, 1596.97, 81.75, 1.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 45: - DoScriptText(SAY_WIN, me, pPlayer); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(pPlayer)->GroupEventHappens(QUEST_WILLIX_THE_IMPORTER,me); - break; - case 46: - DoScriptText(SAY_END, me, pPlayer); - break; - } - } - - void Reset() {} - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO1, me, NULL); - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void JustDied(Unit* /*killer*/) - { - if (Player* pPlayer = GetPlayerForEscort()) - CAST_PLR(pPlayer)->FailQuest(QUEST_WILLIX_THE_IMPORTER); - } -}; - -bool QuestAccept_npc_willix(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_WILLIX_THE_IMPORTER) - { - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - DoScriptText(SAY_READY, pCreature, pPlayer); - pCreature->setFaction(113); - } - - return true; -} - -struct npc_deaths_head_ward_keeperAI : public ScriptedAI -{ - npc_deaths_head_ward_keeperAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 QuillboarChanneling_Timer; - - void Reset() - { - QuillboarChanneling_Timer = 1500; - } - - void UpdateAI(const uint32 diff) - { - if (!me->isAlive()) - return; - - if (pInstance) - pInstance->SetData(TYPE_WARD_KEEPERS, NOT_STARTED); - - if (QuillboarChanneling_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_QUILLBOAR_CHANNELING); - QuillboarChanneling_Timer = 1100; - } else QuillboarChanneling_Timer -= diff; - - } -}; - -CreatureAI* GetAI_npc_deaths_head_ward_keeper(Creature* pCreature) -{ - return new npc_deaths_head_ward_keeperAI(pCreature); -} - -CreatureAI* GetAI_npc_willix(Creature* pCreature) -{ - return new npc_willixAI(pCreature); -} - -void AddSC_razorfen_kraul() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_willix"; - newscript->GetAI = &GetAI_npc_willix; - newscript->pQuestAccept = &QuestAccept_npc_willix; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_deaths_head_ward_keeper"; - newscript->GetAI = &GetAI_npc_deaths_head_ward_keeper; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h b/src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h deleted file mode 100644 index e2219986f63..00000000000 --- a/src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_RAZORFEN_KRAUL_H -#define DEF_RAZORFEN_KRAUL_H - -#define TYPE_WARD_KEEPERS 1 -#endif diff --git a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp b/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp deleted file mode 100644 index f6dc75558c8..00000000000 --- a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ayamiss -SD%Complete: 50 -SDComment: VERIFY SCRIPT -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -/* -To do: -make him fly from 70-100% -*/ - -enum Spells -{ - SPELL_STINGERSPRAY = 25749, - SPELL_POISONSTINGER = 25748, //only used in phase1 - SPELL_SUMMONSWARMER = 25844, //might be 25708 - SPELL_PARALYZE = 23414 //doesnt work correct (core) -}; - -struct boss_ayamissAI : public ScriptedAI -{ - boss_ayamissAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 STINGERSPRAY_Timer; - uint32 POISONSTINGER_Timer; - uint32 SUMMONSWARMER_Timer; - uint32 phase; - - ScriptedInstance *pInstance; - - void Reset() - { - STINGERSPRAY_Timer = 30000; - POISONSTINGER_Timer = 30000; - SUMMONSWARMER_Timer = 60000; - phase=1; - - if (pInstance) - pInstance->SetData(DATA_AYAMISS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_AYAMISS_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_AYAMISS_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If he is 70% start phase 2 - if (phase == 1 && me->GetHealth()*100 / me->GetMaxHealth() <= 70 && !me->IsNonMeleeSpellCasted(false)) - { - phase=2; - } - - //STINGERSPRAY_Timer (only in phase2) - if (phase == 2 && STINGERSPRAY_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STINGERSPRAY); - STINGERSPRAY_Timer = 30000; - } else STINGERSPRAY_Timer -= diff; - - //POISONSTINGER_Timer (only in phase1) - if (phase == 1 && POISONSTINGER_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISONSTINGER); - POISONSTINGER_Timer = 30000; - } else POISONSTINGER_Timer -= diff; - - //SUMMONSWARMER_Timer (only in phase1) - if (SUMMONSWARMER_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUMMONSWARMER); - SUMMONSWARMER_Timer = 60000; - } else SUMMONSWARMER_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ayamiss(Creature* pCreature) -{ - return new boss_ayamissAI (pCreature); -} - -void AddSC_boss_ayamiss() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ayamiss"; - newscript->GetAI = &GetAI_boss_ayamiss; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp b/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp deleted file mode 100644 index 86a2c559543..00000000000 --- a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Buru -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Yells -{ - EMOTE_TARGET = -1509002 -}; - -struct boss_buruAI : public ScriptedAI -{ - boss_buruAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_BURU_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_BURU_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_BURU_EVENT, DONE); - } -}; -CreatureAI* GetAI_boss_buru(Creature* pCreature) -{ - return new boss_buruAI (pCreature); -} - -void AddSC_boss_buru() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_buru"; - newscript->GetAI = &GetAI_boss_buru; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp b/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp deleted file mode 100644 index 44f11bf4b60..00000000000 --- a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kurinnaxx -SD%Complete: 100 -SDComment: VERIFY SCRIPT AND SQL -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Spells -{ - SPELL_MORTALWOUND = 25646, - SPELL_SANDTRAP = 25656, - SPELL_ENRAGE = 28798, - SPELL_SUMMON_PLAYER = 26446, - SPELL_TRASH = 3391, - SPELL_WIDE_SLASH = 25814 -}; - -struct boss_kurinnaxxAI : public ScriptedAI -{ - boss_kurinnaxxAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiMortalWoundTimer; - uint32 uiSandtrapTimer; - uint32 uiWideSlashTimer; - uint32 uiSummonPlayerTimer; - uint32 uiTrashTimer; - bool bIsEnraged; - - ScriptedInstance* pInstance; - - void Reset() - { - bIsEnraged = false; - uiMortalWoundTimer = urand(2000,7000); - uiSandtrapTimer = urand(20000,30000); - uiWideSlashTimer = urand(10000,15000); - uiTrashTimer = urand(20000,25000); - uiSummonPlayerTimer = urand(30000,40000); - - if (pInstance) - pInstance->SetData(DATA_KURINNAXX_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_KURINNAXX_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_KURINNAXX_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <30% cast enrage - if (!bIsEnraged && me->GetHealth()*100 / me->GetMaxHealth() <= 30 && !me->IsNonMeleeSpellCasted(false)) - { - bIsEnraged = true; - DoCast(me, SPELL_ENRAGE); - } - - //Mortal Wound spell - if (uiMortalWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALWOUND); - uiMortalWoundTimer = urand(2000,7000); - } else uiMortalWoundTimer -= diff; - - //Santrap spell - if (uiSandtrapTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SANDTRAP); - uiSandtrapTimer = 30000; - } else uiSandtrapTimer -= diff; - - //Wide Slash spell - if (uiWideSlashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WIDE_SLASH); - uiWideSlashTimer = urand(10000,15000); - } else uiWideSlashTimer -= diff; - - //Trash spell - if (uiTrashTimer <= diff) - { - DoCast(me, SPELL_TRASH); - uiTrashTimer = urand(20000,25000); - } else uiTrashTimer -= diff; - - //Summon Player spell - if (uiSummonPlayerTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SUMMON_PLAYER); - uiSummonPlayerTimer = urand(30000,40000); - } else uiSummonPlayerTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_kurinnaxx(Creature* pCreature) -{ - return new boss_kurinnaxxAI (pCreature); -} - -void AddSC_boss_kurinnaxx() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kurinnaxx"; - newscript->GetAI = &GetAI_boss_kurinnaxx; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp b/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp deleted file mode 100644 index 1882adc8fbb..00000000000 --- a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Moam -SD%Complete: 90 -SDComment: TODO: Adjust timer, correct Stone phase buff -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Emotes -{ - EMOTE_AGGRO = -1509000, - EMOTE_MANA_FULL = -1509001 -}; - -enum Spells -{ - SPELL_TRAMPLE = 15550, - SPELL_DRAINMANA = 27256, //Doesn't exist ? - SPELL_ARCANEERUPTION = 25672, - SPELL_SUMMONMANA = 25681, //Summon Mana fiend. It only summons one so exec it three times - SPELL_GRDRSLEEP = 24360 //Greater Dreamless Sleep -}; - -enum Creatures -{ - CREATURE_MANA_FIEND = 15527 -}; - -enum CombatPhase -{ - NORMAL, - STONE -}; - -struct boss_moamAI : public ScriptedAI -{ - boss_moamAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiTrampleTimer; - uint32 uiDrainManaTimer; - uint32 uiPhaseTimer; - CombatPhase Phase; - - ScriptedInstance *pInstance; - - void Reset() - { - uiTrampleTimer = urand(3000,7000); - uiDrainManaTimer = urand(3000,7000); - uiPhaseTimer = 90000; - Phase = NORMAL; - me->SetPower(POWER_MANA,0); - - if (pInstance) - pInstance->SetData(DATA_MOAM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(EMOTE_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MOAM_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_MOAM_EVENT, DONE); - } - - void DrainMana() - { - for (uint8 i=0;i<6;++i) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - pTarget->ModifyPower(POWER_MANA, -500); - me->ModifyPower(POWER_MANA, 1000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Phase == NORMAL) - { - if (!UpdateVictim()) - return; - - //If we are 100%MANA cast Arcane Erruption - if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA)) - { - DoCast(me->getVictim(), SPELL_ARCANEERUPTION); - DoScriptText(EMOTE_MANA_FULL, me); - me->SetPower(POWER_MANA,0); - } - - //Trample Spell - if (uiTrampleTimer <= diff) - { - DoCast(me->getVictim(), SPELL_TRAMPLE); - uiTrampleTimer = urand(3000,7000); - } else uiTrampleTimer -= diff; - - //Drain Mana - if (uiDrainManaTimer <= diff) - { - DrainMana(); - uiDrainManaTimer = urand(3000,7000); - } else uiDrainManaTimer -= diff; - - DoMeleeAttackIfReady(); - - //After 90secs change phase - if (uiPhaseTimer <= diff) - { - Phase = STONE; - DoCast(me, SPELL_SUMMONMANA); - DoCast(me, SPELL_SUMMONMANA); - DoCast(me, SPELL_SUMMONMANA); - DoCast(me, SPELL_GRDRSLEEP); - } else uiPhaseTimer -= diff; - } - } -}; - -CreatureAI* GetAI_boss_moam(Creature* pCreature) -{ - return new boss_moamAI (pCreature); -} - -void AddSC_boss_moam() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_moam"; - newscript->GetAI = &GetAI_boss_moam; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp b/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp deleted file mode 100644 index 57ba8d9da7f..00000000000 --- a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ossirian -SD%Complete: 0 -SDComment: Place holder -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Yells -{ - SAY_SURPREME2 = -1509019, - SAY_SURPREME3 = -1509020, - SAY_RAND_INTRO1 = -1509021, - SAY_RAND_INTRO2 = -1509022, - SAY_RAND_INTRO3 = -1509023, - SAY_RAND_INTRO4 = -1509024, //possibly old? - SAY_AGGRO = -1509025, - SAY_SLAY = -1509026, - SAY_DEATH = -1509027 -}; - -struct boss_ossirianAI : public ScriptedAI -{ - boss_ossirianAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_OSSIRIAN_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_OSSIRIAN_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_OSSIRIAN_EVENT, DONE); - } -}; -CreatureAI* GetAI_boss_ossirian(Creature* pCreature) -{ - return new boss_ossirianAI (pCreature); -} - -void AddSC_boss_ossirian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ossirian"; - newscript->GetAI = &GetAI_boss_ossirian; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp b/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp deleted file mode 100644 index 5be60dc0ca0..00000000000 --- a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Rajaxx -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Yells -{ - SAY_ANDOROV_INTRO = -1509003, - SAY_ANDOROV_ATTACK = -1509004, - SAY_WAVE3 = -1509005, - SAY_WAVE4 = -1509006, - SAY_WAVE5 = -1509007, - SAY_WAVE6 = -1509008, - SAY_WAVE7 = -1509009, - SAY_INTRO = -1509010, - SAY_UNK1 = -1509011, - SAY_UNK2 = -1509012, - SAY_UNK3 = -1509013, - SAY_UNK4 = -1509014, - SAY_DEAGGRO = -1509015, - SAY_KILLS_ANDOROV = -1509016, - SAY_COMPLETE_QUEST = -1509017 //Yell when realm complete quest 8743 for world event -}; - -struct boss_rajaxxAI : public ScriptedAI -{ - boss_rajaxxAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_RAJAXX_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_RAJAXX_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_RAJAXX_EVENT, DONE); - } -}; -CreatureAI* GetAI_boss_rajaxx(Creature* pCreature) -{ - return new boss_rajaxxAI (pCreature); -} - -void AddSC_boss_rajaxx() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_rajaxx"; - newscript->GetAI = &GetAI_boss_rajaxx; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp b/src/server/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp deleted file mode 100644 index ba7471bdbd2..00000000000 --- a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Ruins_of_Ahnqiraj -SD%Complete: 0 -SDComment: Place holder -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -#define MAX_ENCOUNTER 6 - -/* Ruins of Ahn'Qiraj encounters: -0 - Kurinnaxx -1 - General Rajaxx -2 - Moam -3 - Buru the Gorger -4 - Ayamiss the Hunter -5 - Ossirian the Unscarred */ - -struct instance_ruins_of_ahn_qiraj : public ScriptedInstance -{ - instance_ruins_of_ahn_qiraj(Map* pMap) : ScriptedInstance(pMap) { Initialize(); } - - uint64 uiKurinaxx; - uint64 uiRajaxx; - uint64 uiMoam; - uint64 uiBuru; - uint64 uiAyamiss; - uint64 uiOssirian; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - uiKurinaxx = 0; - uiRajaxx = 0; - uiMoam = 0; - uiBuru = 0; - uiAyamiss = 0; - uiOssirian = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case CREATURE_KURINAXX: - uiKurinaxx = pCreature->GetGUID(); - break; - case CREATURE_RAJAXX: - uiRajaxx = pCreature->GetGUID(); - break; - case CREATURE_MOAM: - uiMoam = pCreature->GetGUID(); - break; - case CREATURE_BURU: - uiBuru = pCreature->GetGUID(); - break; - case CREATURE_AYAMISS: - uiAyamiss = pCreature->GetGUID(); - break; - case CREATURE_OSSIRIAN: - uiOssirian = pCreature->GetGUID(); - break; - } - } - - uint32 GetData(uint32 identifier) - { - switch(identifier) - { - case DATA_KURINNAXX_EVENT: return m_auiEncounter[0]; - case DATA_RAJAXX_EVENT: return m_auiEncounter[1]; - case DATA_MOAM_EVENT: return m_auiEncounter[2]; - case DATA_BURU_EVENT: return m_auiEncounter[3]; - case DATA_AYAMISS_EVENT: return m_auiEncounter[4]; - case DATA_OSSIRIAN_EVENT: return m_auiEncounter[5]; - } - - return 0; - } - - void SetData(uint32 identifier, uint32 data) - { - switch(identifier) - { - case DATA_KURINNAXX_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_RAJAXX_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_MOAM_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_BURU_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_AYAMISS_EVENT: - m_auiEncounter[4] = data; - break; - case DATA_OSSIRIAN_EVENT: - m_auiEncounter[5] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint64 GetData64(uint32 uiIdentifier) - { - switch(uiIdentifier) - { - case DATA_KURINNAXX: return uiKurinaxx; - case DATA_RAJAXX: return uiRajaxx; - case DATA_MOAM: return uiMoam; - case DATA_BURU: return uiBuru; - case DATA_AYAMISS: return uiAyamiss; - case DATA_OSSIRIAN: return uiOssirian; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "R A " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; - - if (dataHead1 == 'R' && dataHead2 == 'A') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - m_auiEncounter[5] = data5; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - } -}; - -InstanceData* GetInstanceData_instance_ruins_of_ahn_qiraj(Map* pMap) -{ - return new instance_ruins_of_ahn_qiraj(pMap); -} - -void AddSC_instance_ruins_of_ahnqiraj() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_ruins_of_ahnqiraj"; - newscript->GetInstanceData = &GetInstanceData_instance_ruins_of_ahn_qiraj; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h b/src/server/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h deleted file mode 100644 index 33fd75d557a..00000000000 --- a/src/server/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DEF_RUINS_OF_AHNQIRAJ_H -#define DEF_RUINS_OF_AHNQIRAJ_H - -enum Data -{ - DATA_KURINNAXX_EVENT, - DATA_RAJAXX_EVENT, - DATA_MOAM_EVENT, - DATA_BURU_EVENT, - DATA_AYAMISS_EVENT, - DATA_OSSIRIAN_EVENT -}; - -enum Data64 -{ - DATA_KURINNAXX, - DATA_RAJAXX, - DATA_MOAM, - DATA_BURU, - DATA_AYAMISS, - DATA_OSSIRIAN -}; - -enum Bosses -{ - CREATURE_KURINAXX = 15348, - CREATURE_RAJAXX = 15341, - CREATURE_MOAM = 15340, - CREATURE_BURU = 15370, - CREATURE_AYAMISS = 15369, - CREATURE_OSSIRIAN = 15339 -}; - -#endif diff --git a/src/server/scripts/kalimdor/silithus.cpp b/src/server/scripts/kalimdor/silithus.cpp deleted file mode 100644 index 6383284011f..00000000000 --- a/src/server/scripts/kalimdor/silithus.cpp +++ /dev/null @@ -1,1140 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Silithus -SD%Complete: 100 -SDComment: Quest support: 7785, 8304, 8507. -SDCategory: Silithus -EndScriptData */ - -/* ContentData -npc_highlord_demitrian -npcs_rutgar_and_frankal -quest_a_pawn_on_the_eternal_pawn -EndContentData */ - -#include "ScriptedPch.h" - -/*### -## npc_highlord_demitrian -###*/ - -#define GOSSIP_DEMITRIAN1 "What do you know of it?" -#define GOSSIP_DEMITRIAN2 "I am listening , Demitrian." -#define GOSSIP_DEMITRIAN3 "Continue, please." -#define GOSSIP_DEMITRIAN4 "A battle?" -#define GOSSIP_DEMITRIAN5 "" -#define GOSSIP_DEMITRIAN6 "Caught unaware? How?" -#define GOSSIP_DEMITRIAN7 "So what did Ragnaros do next?" - -bool GossipHello_npc_highlord_demitrian(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(7785) == QUEST_STATUS_NONE && - (pPlayer->HasItemCount(18563,1,false) || pPlayer->HasItemCount(18564,1,false))) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(6812, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_highlord_demitrian(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(6842, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(6843, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(6844, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(6867, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(6868, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEMITRIAN7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(6869, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->SEND_GOSSIP_MENU(6870, pCreature->GetGUID()); - - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 19016, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, 19016, true); - break; - } - return true; -} - -/*### -## npcs_rutgar_and_frankal -###*/ - -//gossip item text best guess -#define GOSSIP_ITEM1 "I seek information about Natalia" - -#define GOSSIP_ITEM2 "That sounds dangerous!" -#define GOSSIP_ITEM3 "What did you do?" -#define GOSSIP_ITEM4 "Who?" -#define GOSSIP_ITEM5 "Women do that. What did she demand?" -#define GOSSIP_ITEM6 "What do you mean?" -#define GOSSIP_ITEM7 "What happened next?" - -#define GOSSIP_ITEM11 "Yes, please continue" -#define GOSSIP_ITEM12 "What language?" -#define GOSSIP_ITEM13 "The Priestess attacked you?!" -#define GOSSIP_ITEM14 "I should ask the monkey about this" -#define GOSSIP_ITEM15 "Then what..." - -//trigger creatures to kill -#define TRIGGER_RUTGAR 15222 -#define TRIGGER_FRANKAL 15221 - -bool GossipHello_npcs_rutgar_and_frankal(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(8304) == QUEST_STATUS_INCOMPLETE && - pCreature->GetEntry() == 15170 && - !pPlayer->GetReqKillOrCastCurrentCount(8304, TRIGGER_RUTGAR)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - if (pPlayer->GetQuestStatus(8304) == QUEST_STATUS_INCOMPLETE && - pCreature->GetEntry() == 15171 && - pPlayer->GetReqKillOrCastCurrentCount(8304, TRIGGER_RUTGAR)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); - - pPlayer->SEND_GOSSIP_MENU(7754, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npcs_rutgar_and_frankal(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(7755, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(7756, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(7757, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(7758, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - pPlayer->SEND_GOSSIP_MENU(7759, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - pPlayer->SEND_GOSSIP_MENU(7760, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 6: - pPlayer->SEND_GOSSIP_MENU(7761, pCreature->GetGUID()); - //'kill' our trigger to update quest status - pPlayer->KilledMonsterCredit(TRIGGER_RUTGAR, pCreature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF + 9: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - pPlayer->SEND_GOSSIP_MENU(7762, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 10: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - pPlayer->SEND_GOSSIP_MENU(7763, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 11: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); - pPlayer->SEND_GOSSIP_MENU(7764, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 12: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); - pPlayer->SEND_GOSSIP_MENU(7765, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 13: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); - pPlayer->SEND_GOSSIP_MENU(7766, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 14: - pPlayer->SEND_GOSSIP_MENU(7767, pCreature->GetGUID()); - //'kill' our trigger to update quest status - pPlayer->KilledMonsterCredit(TRIGGER_FRANKAL, pCreature->GetGUID()); - break; - } - return true; -} - -/*#### -# quest_a_pawn_on_the_eternal_board (Defines) -####*/ -enum eEternalBoard -{ - QUEST_A_PAWN_ON_THE_ETERNAL_BOARD = 8519, - - FACTION_HOSTILE = 14, - FACTION_FRIENDLY = 35, - - C_ANACHRONOS = 15381, - C_FANDRAL_STAGHELM = 15382, - C_ARYGOS = 15380, - C_MERITHRA = 15378, - C_CAELESTRASZ = 15379, - - ANACHRONOS_SAY_1 = -1350000, - ANACHRONOS_SAY_2 = -1350001, - ANACHRONOS_SAY_3 = -1350002, - ANACHRONOS_SAY_4 = -1350003, - ANACHRONOS_SAY_5 = -1350004, - ANACHRONOS_SAY_6 = -1350005, - ANACHRONOS_SAY_7 = -1350006, - ANACHRONOS_SAY_8 = -1350007, - ANACHRONOS_SAY_9 = -1350008, - ANACHRONOS_SAY_10 = -1350009, - ANACHRONOS_EMOTE_1 = -1350010, - ANACHRONOS_EMOTE_2 = -1350011, - ANACHRONOS_EMOTE_3 = -1350012, - - FANDRAL_SAY_1 = -1350013, - FANDRAL_SAY_2 = -1350014, - FANDRAL_SAY_3 = -1350015, - FANDRAL_SAY_4 = -1350016, - FANDRAL_SAY_5 = -1350017, - FANDRAL_SAY_6 = -1350018, - FANDRAL_EMOTE_1 = -1350019, - FANDRAL_EMOTE_2 = -1350020, - - CAELESTRASZ_SAY_1 = -1350021, - CAELESTRASZ_SAY_2 = -1350022, - CAELESTRASZ_YELL_1 = -1350023, - - ARYGOS_SAY_1 = -1350024, - ARYGOS_YELL_1 = -1350025, - ARYGOS_EMOTE_1 = -1350026, - - MERITHRA_SAY_1 = -1350027, - MERITHRA_SAY_2 = -1350028, - MERITHRA_YELL_1 = -1350029, - MERITHRA_EMOTE_1 = -1350030, - - GO_GATE_OF_AHN_QIRAJ = 176146, - GO_GLYPH_OF_AHN_QIRAJ = 176148, - GO_ROOTS_OF_AHN_QIRAJ = 176147 -}; -/*##### -# Quest: A Pawn on the Eternal Board -#####*/ - -/* ContentData -A Pawn on the Eternal Board - creatures, gameobjects and defines -mob_qiraj_war_spawn : Adds that are summoned in the Qiraj gates battle. -npc_anachronos_the_ancient : Creature that controls the event. -npc_anachronos_quest_trigger: controls the spawning of the BG War mobs. -go_crystalline_tear : GameObject that begins the event and hands out quest -TO DO: get correct spell IDs and timings for spells cast upon dragon transformations -TO DO: Dragons should use the HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF) after transformation,but for some unknown reason it doesnt work. -EndContentData */ - -#define QUEST_A_PAWN_ON_THE_ETERNAL_BOARD 8519 -#define EVENT_AREA_RADIUS 65 //65yds -#define EVENT_COOLDOWN 500000 //in ms. appear after event completed or failed (should be = Adds despawn time) - -struct QuestCinematic -{ - int32 TextId; - uint32 Creature, Timer; -}; - -// Creature 0 - Anachronos, 1 - Fandral, 2 - Arygos, 3 - Merithra, 4 - Caelestrasz -static QuestCinematic EventAnim[]= -{ - {ANACHRONOS_SAY_1, 0, 2000}, - {FANDRAL_SAY_1, 1, 4000}, - {MERITHRA_EMOTE_1, 3, 500}, - {MERITHRA_SAY_1, 3, 500}, - {ARYGOS_EMOTE_1, 2, 2000}, - {CAELESTRASZ_SAY_1, 4, 8000}, - {MERITHRA_SAY_2, 3, 6000}, - {NULL,3,2000}, - {MERITHRA_YELL_1, 3, 2500}, - {NULL, 3, 3000},//Morph - {NULL,3,4000},//EmoteLiftoff - {NULL, 3, 4000},// spell - {NULL, 3, 1250},//fly - {NULL, 3, 250},//remove flags - {ARYGOS_SAY_1, 2, 3000}, - {NULL,3,2000}, - {ARYGOS_YELL_1, 2, 3000}, - {NULL, 3, 3000},//Morph - {NULL,3,4000},//EmoteLiftoff - {NULL, 3, 4000},// spell - {NULL, 3, 1000},//fly - {NULL, 3, 1000},//remove flags - {CAELESTRASZ_SAY_2, 4, 5000}, - {NULL,3,3000}, - {CAELESTRASZ_YELL_1, 4, 3000}, - {NULL, 3, 3000},//Morph - {NULL,3,4000},//EmoteLiftoff - {NULL, 3, 2500},// spell - {ANACHRONOS_SAY_2, 0, 2000}, - {NULL, 3, 250},//fly - {NULL, 3, 25},//remove flags - {FANDRAL_SAY_2, 1, 3000}, - {ANACHRONOS_SAY_3, 0, 10000},//Both run through the armies - {NULL,3,2000},// Sands will stop - {NULL,3,8000},// Summon Gate - {ANACHRONOS_SAY_4, 0, 4000}, - {NULL, 0, 2000},//spell 1-> Arcane cosmetic (Mobs freeze) - {NULL, 0, 5000}, //Spell 2-> Arcane long cosmetic (barrier appears) (Barrier -> Glyphs) - {NULL, 0, 7000},//BarrieR - {NULL, 0, 4000},//Glyphs - {ANACHRONOS_SAY_5, 0, 2000}, - {NULL, 0, 4000},// Roots - {FANDRAL_SAY_3, 1, 3000},//Root Text - {FANDRAL_EMOTE_1, 1, 3000},//falls knee - {ANACHRONOS_SAY_6, 0, 3000}, - {ANACHRONOS_SAY_7, 0, 3000}, - {ANACHRONOS_SAY_8, 0, 8000}, - {ANACHRONOS_EMOTE_1, 0, 1000},//Give Scepter - {FANDRAL_SAY_4, 1, 3000}, - {FANDRAL_SAY_5, 1, 3000},//->Equip hammer~Scepter, throw it at door - {FANDRAL_EMOTE_2, 1, 3000},//Throw hammer at door. - {ANACHRONOS_SAY_9, 0, 3000}, - {FANDRAL_SAY_6, 1, 3000}, //fandral goes away - {ANACHRONOS_EMOTE_2, 0, 3000}, - {ANACHRONOS_EMOTE_3, 0, 3000}, - {NULL, 0, 2000}, - {NULL, 0, 2000}, - {NULL, 0, 4000}, - {ANACHRONOS_SAY_10, 0, 3000}, - {NULL, 0, 2000}, - {NULL, 0, 3000}, - {NULL, 0, 15000}, - {NULL, 0, 5000}, - {NULL, 0, 3500}, - {NULL, 0, 5000}, - {NULL, 0, 3500}, - {NULL, 0, 5000}, - {NULL, 0, NULL} -}; - -struct Location -{ - float x, y, z, o; -}; - -//Cordinates for Spawns -static Location SpawnLocation[]= -{ - {-8085, 1528, 2.61, 3.141592},//Kaldorei Infantry - {-8080, 1526, 2.61, 3.141592},//Kaldorei Infantry - {-8085, 1524, 2.61, 3.141592},//Kaldorei Infantry - {-8080, 1522, 2.61, 3.141592},//Kaldorei Infantry - {-8085, 1520, 2.61, 3.141592},//Kaldorei Infantry - - {-8085, 1524, 2.61, 3.141592},//Kaldorei Infantry - {-8080, 1522, 2.61, 3.141592},//Kaldorei Infantry - {-8085, 1520, 2.61, 3.141592},//Kaldorei Infantry - {-8080, 1518, 2.61, 3.141592},//Kaldorei Infantry - {-8085, 1516, 2.61, 3.141592},//Kaldorei Infantry - - {-8085, 1518, 2.61, 3.141592},//Kaldorei Infantry - {-8080, 1516, 2.61, 3.141592},//Kaldorei Infantry - {-8080, 1520, 2.61, 3.141592},//Kaldorei Infantry - {-8080, 1424, 2.61, 3.141592},//Kaldorei Infantry - {-8085, 1422, 2.61, 3.141592},//Kaldorei Infantry - // 2 waves of warriors - {-8082, 1528, 2.61, 3.141592},//Kaldorei Infantry - {-8078, 1525, 2.61, 3.141592},//Kaldorei Infantry - {-8082, 1524, 2.61, 3.141592},//Kaldorei Infantry - {-8078, 1526, 2.61, 3.141592},//Kaldorei Infantry - {-8082, 1527, 2.61, 3.141592},//Kaldorei Infantry - - {-8082, 1524, 2.61, 3.141592},//Kaldorei Infantry - {-8078, 1522, 2.61, 3.141592},//Kaldorei Infantry - {-8082, 1520, 2.61, 3.141592},//Kaldorei Infantry - {-8078, 1518, 2.61, 3.141592},//Kaldorei Infantry - {-8082, 1516, 2.61, 3.141592},//Kaldorei Infantry - - {-8082, 1523, 2.61, 3.141592},//Kaldorei Infantry - {-8078, 1521, 2.61, 3.141592},//Kaldorei Infantry - {-8082, 1528, 2.61, 3.141592},//Kaldorei Infantry - {-8078, 1519, 2.61, 3.141592},//Kaldorei Infantry - {-8082, 1526, 2.61, 3.141592},//Kaldorei Infantry - - {-8082, 1524, 2.61, 3.141592},//Kaldorei Infantry - {-8078, 1522, 2.61, 3.141592},//Kaldorei Infantry - {-8082, 1520, 2.61, 3.141592},//Kaldorei Infantry - {-8078, 1518, 2.61, 3.141592},//Kaldorei Infantry - {-8082, 1516, 2.61, 3.141592},//Kaldorei Infantry - - {-8088, 1510, 2.61, 0},//Anubisath Conqueror - {-8084, 1520, 2.61, 0},//Anubisath Conqueror - {-8088, 1530, 2.61, 0},//Anubisath Conqueror - - {-8080, 1513, 2.61, 0},//Qiraj Wasp - {-8082, 1523, 2.61, 0},//Qiraj Wasp - {-8085, 1518, 2.61, 0},//Qiraj Wasp - {-8082, 1516, 2.61, 0},//Qiraj Wasp - {-8085, 1520, 2.61, 0},//Qiraj Wasp - {-8080, 1528, 2.61, 0},//Qiraj Wasp - - {-8082, 1513, 2.61, 0},//Qiraj Wasp - {-8079, 1523, 2.61, 0},//Qiraj Wasp - {-8080, 1531, 2.61, 0},//Qiraj Wasp - {-8079, 1516, 2.61, 0},//Qiraj Wasp - {-8082, 1520, 2.61, 0},//Qiraj Wasp - {-8080, 1518, 2.61, 0},//Qiraj Wasp - - {-8081, 1514, 2.61, 0},//Qiraj Tank - {-8081, 1520, 2.61, 0},//Qiraj Tank - {-8081, 1526, 2.61, 0},//Qiraj Tank - {-8081, 1512, 2.61, 0},//Qiraj Tank - {-8082, 1520, 2.61, 0},//Qiraj Tank - {-8081, 1528, 2.61, 0},//Qiraj Tank - - {-8082, 1513, 2.61, 3.141592},//Anubisath Conqueror - {-8082, 1520, 2.61, 3.141592},//Anubisath Conqueror - {-8082, 1527, 2.61, 3.141592},//Anubisath Conqueror -}; - -struct WaveData -{ - uint8 SpawnCount, UsedSpawnPoint; - uint32 CreatureId, SpawnTimer, YellTimer, DespTimer; - int32 WaveTextId; -}; - -static WaveData WavesInfo[] = -{ - {30, 0, 15423, 0, 0,24000, NULL}, //Kaldorei Soldier - {3, 35, 15424, 0, 0,24000, NULL}, //Anubisath Conqueror - {12, 38, 15414, 0, 0,24000, NULL}, //Qiraji Wasps - {6, 50, 15422, 0, 0,24000, NULL}, //Qiraji Tanks - {15, 15, 15423, 0, 0,24000, NULL} //Kaldorei Soldier - -}; - -struct SpawnSpells -{ - uint32 Timer1, Timer2, SpellId; -}; - -static SpawnSpells SpawnCast[]=// -{ - {100000, 2000, 33652}, // Stop Time - {38500, 300000, 28528}, // Poison Cloud - {58000, 300000, 35871}, // Frost Debuff (need correct spell) - {80950, 300000, 42075}, // Fire Explosion (need correct spell however this one looks cool) -}; -/*##### -# npc_anachronos_the_ancient -######*/ -struct npc_anachronos_the_ancientAI : public ScriptedAI -{ - npc_anachronos_the_ancientAI(Creature* c) : ScriptedAI(c) {} - - uint32 AnimationTimer; - uint8 AnimationCount; - - uint64 AnachronosQuestTriggerGUID; - uint64 MerithraGUID; - uint64 ArygosGUID; - uint64 CaelestraszGUID; - uint64 FandralGUID; - uint64 PlayerGUID; - bool eventEnd; - - void Reset() - { - AnimationTimer = 1500; - AnimationCount = 0; - AnachronosQuestTriggerGUID = 0; - MerithraGUID = 0; - ArygosGUID = 0; - CaelestraszGUID = 0; - FandralGUID = 0; - PlayerGUID = 0; - eventEnd = false; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void HandleAnimation() - { - Player* plr = Unit::GetPlayer(PlayerGUID); - if (!plr) - return; - - Unit* Fandral = plr->FindNearestCreature(C_FANDRAL_STAGHELM, 100, me); - Unit* Arygos = plr->FindNearestCreature(C_ARYGOS, 100,me); - Unit* Caelestrasz = plr->FindNearestCreature(C_CAELESTRASZ, 100, me); - Unit* Merithra = plr->FindNearestCreature(C_MERITHRA, 100,me); - - if (!Fandral || !Arygos || !Caelestrasz || !Merithra) - return; - - Unit* mob; - AnimationTimer = EventAnim[AnimationCount].Timer; - if (eventEnd == false) - { - switch(AnimationCount) - { - case 0: - DoScriptText(ANACHRONOS_SAY_1, me , Fandral); - break; - case 1: - Fandral->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - DoScriptText(FANDRAL_SAY_1, Fandral,me); - break; - case 2: - Fandral->SetUInt64Value(UNIT_FIELD_TARGET,NULL); - DoScriptText(MERITHRA_EMOTE_1,Merithra); - break; - case 3: - DoScriptText(MERITHRA_SAY_1,Merithra); - break; - case 4: - DoScriptText(ARYGOS_EMOTE_1,Arygos); - break; - case 5: - Caelestrasz->SetUInt64Value(UNIT_FIELD_TARGET, Fandral->GetGUID()); - DoScriptText(CAELESTRASZ_SAY_1, Caelestrasz); - break; - case 6: - DoScriptText(MERITHRA_SAY_2, Merithra); - break; - case 7: - Caelestrasz->SetUInt64Value(UNIT_FIELD_TARGET, NULL); - Merithra->GetMotionMaster()->MoveCharge(-8065,1530,2.61,10); - break; - case 8: - DoScriptText(MERITHRA_YELL_1,Merithra); - break; - case 9: - Merithra->CastSpell(Merithra,25105,true); - break; - case 10: - Merithra->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - Merithra->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - Merithra->GetMotionMaster()->MoveCharge(-8065,1530,6.61,3); - break; - case 11: - Merithra->CastSpell(Merithra,24818,false); - break; - case 12: - Merithra->GetMotionMaster()->MoveCharge(-8100,1530,50,42); - break; - case 13: - break; - case 14: - DoScriptText(ARYGOS_SAY_1,Arygos); - Merithra->SetVisibility(VISIBILITY_OFF); - break; - case 15: - Arygos->GetMotionMaster()->MoveCharge(-8065,1530,2.61,10); - Merithra->GetMotionMaster()->MoveCharge(-8034.535,1535.14,2.61,42); - break; - case 16: - DoScriptText(ARYGOS_YELL_1, Arygos); - break; - case 17: - Arygos->CastSpell(Arygos,25107,true); - break; - case 18: - Arygos->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - Arygos->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - Arygos->GetMotionMaster()->MoveCharge(-8065,1530,6.61,42); - break; - case 19: - Arygos->CastSpell(Arygos,50505,false); - break; - case 20: - Arygos->GetMotionMaster()->MoveCharge(-8095,1530,50,42); - break; - case 21: - break; - case 22: - DoScriptText(CAELESTRASZ_SAY_2,Caelestrasz, Fandral); - break; - case 23: - Caelestrasz->GetMotionMaster()->MoveCharge(-8065,1530,2.61,10); - Arygos->SetVisibility(VISIBILITY_OFF); - Arygos->GetMotionMaster()->MoveCharge(-8034.535,1535.14,2.61,10); - break; - case 24: - DoScriptText(CAELESTRASZ_YELL_1, Caelestrasz); - break; - case 25: - Caelestrasz->CastSpell(Caelestrasz,25106,true); - break; - case 26: - Caelestrasz->HandleEmoteCommand(254); - Caelestrasz->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - Caelestrasz->GetMotionMaster()->MoveCharge(-8065,1530,7.61,4); - break; - case 27: - Caelestrasz->CastSpell(Caelestrasz,54293,false); - break; - case 28: - DoScriptText(ANACHRONOS_SAY_2,me, Fandral); - break; - case 29: - Caelestrasz->GetMotionMaster()->MoveCharge(-8095,1530,50,42); - DoScriptText(FANDRAL_SAY_2, Fandral, me); - break; - case 30: - break; - case 31: - DoScriptText(ANACHRONOS_SAY_3, me, Fandral); - break; - case 32: - Caelestrasz->SetVisibility(VISIBILITY_OFF); - Caelestrasz->GetMotionMaster()->MoveCharge(-8034.535,1535.14,2.61,42); - Fandral->GetMotionMaster()->MoveCharge(-8108,1529,2.77,8); - me->GetMotionMaster()->MoveCharge(-8113,1525,2.77,8); - break;//both run to the gate - case 33: - DoScriptText(ANACHRONOS_SAY_4, me); - Caelestrasz->GetMotionMaster()->MoveCharge(-8050,1473,65,15); - break; //Text: sands will stop - case 34: - DoCast(plr, 23017, true);//Arcane Channeling - break; - case 35: - me->CastSpell(-8088,1520.43,2.67,25158,true); - break; - case 36: - DoCast(plr, 25159, true); - break; - case 37: - me->SummonGameObject(GO_GATE_OF_AHN_QIRAJ,-8130,1525,17.5,0,0,0,0,0,0); - break; - case 38: - DoCast(plr, 25166, true); - me->SummonGameObject(GO_GLYPH_OF_AHN_QIRAJ,-8130,1525,17.5,0,0,0,0,0,0); - break; - case 39: - DoScriptText(ANACHRONOS_SAY_5, me, Fandral); - break; - case 40: - Fandral->CastSpell(me, 25167, true); - break; - case 41: - Fandral->SummonGameObject(GO_ROOTS_OF_AHN_QIRAJ,-8130,1525,17.5,0,0,0,0,0,0); - DoScriptText(FANDRAL_SAY_3, Fandral); - break; - case 42: - me->CastStop(); - DoScriptText(FANDRAL_EMOTE_1, Fandral); - break; - case 43: - Fandral->CastStop(); - break; - case 44: - DoScriptText(ANACHRONOS_SAY_6, me); - break; - case 45: - DoScriptText(ANACHRONOS_SAY_7, me); - break; - case 46: - DoScriptText(ANACHRONOS_SAY_8, me); - me->GetMotionMaster()->MoveCharge(-8110,1527,2.77,4); - break; - case 47: - DoScriptText(ANACHRONOS_EMOTE_1, me); - break; - case 48: - DoScriptText(FANDRAL_SAY_4,Fandral,me); - break; - case 49: - DoScriptText(FANDRAL_SAY_5,Fandral,me); - break; - case 50: - DoScriptText(FANDRAL_EMOTE_2,Fandral); - Fandral->CastSpell(-8127,1525,17.5,33806,true); - break; - case 51: - { - uint32 entries[4] = { 15423, 15424, 15414, 15422 }; - for (uint8 i = 0; i < 4; ++i) - { - mob = plr->FindNearestCreature(entries[i],50,me); - while (mob) - { - mob->RemoveFromWorld(); - mob = plr->FindNearestCreature(15423,50,me); - } - } - break; - } - case 52: - Fandral->GetMotionMaster()->MoveCharge(-8028.75, 1538.795, 2.61,4); - DoScriptText(ANACHRONOS_SAY_9, me,Fandral); - break; - case 53: - DoScriptText(FANDRAL_SAY_6,Fandral); - break; - case 54: - DoScriptText(ANACHRONOS_EMOTE_2,me); - break; - case 55: - Fandral->SetVisibility(VISIBILITY_OFF); - break; - case 56: - DoScriptText(ANACHRONOS_EMOTE_3, me); - me->GetMotionMaster()->MoveCharge(-8116,1522,3.65,4); - break; - case 57: - me->GetMotionMaster()->MoveCharge(-8116.7,1527,3.7,4); - break; - case 58: - me->GetMotionMaster()->MoveCharge(-8112.67,1529.9,2.86,4); - break; - case 59: - me->GetMotionMaster()->MoveCharge(-8117.99,1532.24,3.94,4); - break; - case 60: - if (plr) - DoScriptText(ANACHRONOS_SAY_10, me,plr); - me->GetMotionMaster()->MoveCharge(-8113.46,1524.16,2.89,4); - break; - case 61: - me->GetMotionMaster()->MoveCharge(-8057.1,1470.32,2.61,6); - if (plr->IsInRange(me,0,15)) - plr->GroupEventHappens(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD ,me); - break; - case 62: - me->SetDisplayId(15500); - break; - case 63: - me->HandleEmoteCommand(254); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - break; - case 64: - me->GetMotionMaster()->MoveCharge(-8000,1400,150,9); - break; - case 65: - me->SetVisibility(VISIBILITY_OFF); - if (Creature* AnachronosQuestTrigger = (Unit::GetCreature(*me, AnachronosQuestTriggerGUID))) - { - DoScriptText(ARYGOS_YELL_1,me); - AnachronosQuestTrigger->AI()->EnterEvadeMode(); - eventEnd=true; - } - break; - } - } - ++AnimationCount; - } - void UpdateAI(const uint32 diff) - { - if (AnimationTimer) - { - if (AnimationTimer <= diff) - HandleAnimation(); - else AnimationTimer -= diff; - } - if (AnimationCount < 65) - me->CombatStop(); - if (AnimationCount == 65 || eventEnd) - me->AI()->EnterEvadeMode(); - } -}; - -/*###### -# mob_qiraj_war_spawn -######*/ - -struct mob_qiraj_war_spawnAI : public ScriptedAI -{ - mob_qiraj_war_spawnAI(Creature* c) : ScriptedAI(c) {} - - uint64 MobGUID; - uint64 PlayerGUID; - uint32 SpellTimer1, SpellTimer2, SpellTimer3,SpellTimer4; - bool Timers; - bool hasTarget; - - void Reset() - { - MobGUID = 0; - PlayerGUID = 0; - Timers = false; - hasTarget = false; - } - - void EnterCombat(Unit* /*who*/) {} - void JustDied(Unit* slayer); - - void UpdateAI(const uint32 diff) - { - Unit *pTarget = NULL; - //Player* plr = me->GetPlayer(PlayerGUID); - - if (!Timers) - { - if (me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) //all but Kaldorei Soldiers - { - SpellTimer1 = SpawnCast[1].Timer1; - SpellTimer2 = SpawnCast[2].Timer1; - SpellTimer3 = SpawnCast[3].Timer1; - } - if (me->GetEntry() == 15423 || me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) - SpellTimer4 = SpawnCast[0].Timer1; - Timers = true; - } - if (me->GetEntry() == 15424 || me->GetEntry() == 15422|| me->GetEntry() == 15414) - { - if (SpellTimer1 <= diff) - { - DoCast(me, SpawnCast[1].SpellId); - DoCast(me, 24319); - SpellTimer1 = SpawnCast[1].Timer2; - } else SpellTimer1 -= diff; - if (SpellTimer2 <= diff) - { - DoCast(me, SpawnCast[2].SpellId); - SpellTimer2 = SpawnCast[2].Timer2; - } else SpellTimer2 -= diff; - if (SpellTimer3 <= diff) - { - DoCast(me, SpawnCast[3].SpellId); - SpellTimer3 = SpawnCast[3].Timer2; - } else SpellTimer3 -= diff; - } - if (me->GetEntry() == 15423 || me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) - { - if (SpellTimer4 <= diff) - { - me->RemoveAllAttackers(); - me->AttackStop(); - DoCast(me, 15533); - SpellTimer4 = SpawnCast[0].Timer2; - } else SpellTimer4 -= diff; - } - if (!hasTarget) - { - if (me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) - pTarget = me->FindNearestCreature(15423,20,true); - if (me->GetEntry() == 15423) - { - uint8 tar = urand(0,2); - - if (tar == 0) - pTarget = me->FindNearestCreature(15422,20,true); - else if (tar == 1) - pTarget = me->FindNearestCreature(15424,20,true); - else if (tar == 2) - pTarget = me->FindNearestCreature(15414,20,true); - } - hasTarget = true; - if (pTarget) - me->AI()->AttackStart(pTarget); - } - if (!(me->FindNearestCreature(15379,60))) - DoCast(me, 33652); - - if (!UpdateVictim()) - { - hasTarget = false; - return; - } - - DoMeleeAttackIfReady(); - } -}; - -/*##### -# npc_anachronos_quest_trigger -#####*/ - -struct npc_anachronos_quest_triggerAI : public ScriptedAI -{ - npc_anachronos_quest_triggerAI(Creature* c) : ScriptedAI(c) {} - - uint64 PlayerGUID; - - uint32 WaveTimer; - uint32 AnnounceTimer; - - int8 LiveCount; - uint8 WaveCount; - - bool EventStarted; - bool Announced; - bool Failed; - - void Reset() - { - PlayerGUID = 0; - - WaveTimer = 2000; - AnnounceTimer = 1000; - LiveCount = 0; - WaveCount = 0; - - EventStarted = false; - Announced = false; - Failed = false; - - me->SetVisibility(VISIBILITY_OFF); - } - - void SummonNextWave() - { - //uint8 count = WavesInfo[WaveCount].SpawnCount; - uint8 locIndex = WavesInfo[WaveCount].UsedSpawnPoint; - srand(time(NULL));//initializing random seed - //uint8 KaldoreiSoldierCount = 0; - //uint8 AnubisathConquerorCount = 0; - //uint8 QirajiWaspCount = 0; - for (uint8 i = 0; i < 67; ++i) - { - Creature* Spawn = NULL; - float X = SpawnLocation[locIndex + i].x; - float Y = SpawnLocation[locIndex + i].y; - float Z = SpawnLocation[locIndex + i].z; - float O = SpawnLocation[locIndex + i].o; - uint32 desptimer = WavesInfo[WaveCount].DespTimer; - Spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, X, Y, Z, O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, desptimer); - - if (Spawn) - { - Spawn->LoadCreaturesAddon(); - if (Spawn->GetGUID() == 15423) - Spawn->SetUInt32Value(UNIT_FIELD_DISPLAYID,15427+rand()%4); - if (i >= 30) WaveCount = 1; - if (i >= 33) WaveCount = 2; - if (i >= 45) WaveCount = 3; - if (i >= 51) WaveCount = 4; - - if (WaveCount < 5) //1-4 Wave - { - CAST_AI(mob_qiraj_war_spawnAI, Spawn->AI())->MobGUID = me->GetGUID(); - CAST_AI(mob_qiraj_war_spawnAI, Spawn->AI())->PlayerGUID = PlayerGUID; - } - } - } - WaveTimer = WavesInfo[WaveCount].SpawnTimer; - AnnounceTimer = WavesInfo[WaveCount].YellTimer; - } - - void CheckEventFail() - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - - if (!pPlayer) - return; - - if (Group *EventGroup = pPlayer->GetGroup()) - { - Player* GroupMember; - - uint8 GroupMemberCount = 0; - uint8 DeadMemberCount = 0; - uint8 FailedMemberCount = 0; - - const Group::MemberSlotList members = EventGroup->GetMemberSlots(); - - for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) - { - GroupMember = (Unit::GetPlayer(itr->guid)); - if (!GroupMember) - continue; - if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) == QUEST_STATUS_INCOMPLETE) - { - GroupMember->FailQuest(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD); - GroupMember->SetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD, QUEST_STATUS_NONE); - ++FailedMemberCount; - } - ++GroupMemberCount; - - if (GroupMember->isDead()) - ++DeadMemberCount; - } - - if (GroupMemberCount == FailedMemberCount || !pPlayer->IsWithinDistInMap(me, EVENT_AREA_RADIUS)) - Failed = true; //only so event can restart - } - } - - void LiveCounter() - { - --LiveCount; - if (!LiveCount) - Announced = false; - } - - void UpdateAI(const uint32 diff) - { - if (!PlayerGUID || !EventStarted) - return; - - if (WaveCount < 4) - { - if (!Announced && AnnounceTimer <= diff) - { - DoScriptText(WavesInfo[WaveCount].WaveTextId, me); - Announced = true; - } else AnnounceTimer -= diff; - - if (WaveTimer <= diff) - SummonNextWave(); - else WaveTimer -= diff; - } - CheckEventFail(); - if (WaveCount == 4 || Failed) - EnterEvadeMode(); - }; -}; -void mob_qiraj_war_spawnAI::JustDied(Unit* /*slayer*/) -{ - me->RemoveCorpse(); - if (Creature* Mob = (Unit::GetCreature(*me, MobGUID))) - CAST_AI(npc_anachronos_quest_triggerAI, Mob->AI())->LiveCounter(); - -}; -/*##### -# go_crystalline_tear -######*/ - -bool GOQuestAccept_GO_crystalline_tear(Player* plr, GameObject* go, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) - { - - if (Unit* Anachronos_Quest_Trigger = go->FindNearestCreature(15454, 100, plr)) - { - - Unit *Merithra = Anachronos_Quest_Trigger->SummonCreature(15378,-8034.535,1535.14,2.61,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); - Unit *Caelestrasz = Anachronos_Quest_Trigger->SummonCreature(15379,-8032.767, 1533.148,2.61, 1.5,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); - Unit *Arygos = Anachronos_Quest_Trigger->SummonCreature(15380,-8034.52, 1537.843, 2.61, 5.7,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); - /* Unit *Fandral = */ Anachronos_Quest_Trigger->SummonCreature(15382,-8028.462, 1535.843, 2.61, 3.141592,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); - Creature *Anachronos = Anachronos_Quest_Trigger->SummonCreature(15381,-8028.75, 1538.795, 2.61, 4,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,220000); - - if (Merithra) - { - Merithra->SetUInt32Value(UNIT_NPC_FLAGS, 0); - Merithra->SetUInt32Value(UNIT_FIELD_BYTES_1,0); - Merithra->SetUInt32Value(UNIT_FIELD_DISPLAYID,15420); - Merithra->setFaction(35); - } - - if (Caelestrasz) - { - Caelestrasz->SetUInt32Value(UNIT_NPC_FLAGS, 0); - Caelestrasz->SetUInt32Value(UNIT_FIELD_BYTES_1,0); - Caelestrasz->SetUInt32Value(UNIT_FIELD_DISPLAYID,15419); - Caelestrasz->setFaction(35); - } - - if (Arygos) - { - Arygos->SetUInt32Value(UNIT_NPC_FLAGS, 0); - Arygos->SetUInt32Value(UNIT_FIELD_BYTES_1,0); - Arygos->SetUInt32Value(UNIT_FIELD_DISPLAYID,15418); - Arygos->setFaction(35); - } - - if (Anachronos) - { - CAST_AI(npc_anachronos_the_ancientAI, Anachronos->AI())->PlayerGUID = plr->GetGUID(); - CAST_AI(npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->Failed=false; - CAST_AI(npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->PlayerGUID = plr->GetGUID(); - CAST_AI(npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->EventStarted=true; - CAST_AI(npc_anachronos_quest_triggerAI, CAST_CRE(Anachronos_Quest_Trigger)->AI())->Announced=true; - } - } - } - return true; -} - -CreatureAI* GetAI_npc_anachronos_quest_trigger(Creature* c) -{ - return new npc_anachronos_quest_triggerAI(c); -} - -CreatureAI* GetAI_mob_qiraj_war_spawn(Creature* c) -{ - return new mob_qiraj_war_spawnAI(c); -} - -CreatureAI* GetAI_npc_anachronos_the_ancient(Creature* c) -{ - return new npc_anachronos_the_ancientAI(c); -} - -void AddSC_silithus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_crystalline_tear"; - newscript->pGOQuestAccept = &GOQuestAccept_GO_crystalline_tear; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anachronos_quest_trigger"; - newscript->GetAI = &GetAI_npc_anachronos_quest_trigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anachronos_the_ancient"; - newscript->GetAI = &GetAI_npc_anachronos_the_ancient; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_qiraj_war_spawn"; - newscript->GetAI = &GetAI_mob_qiraj_war_spawn; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_highlord_demitrian"; - newscript->pGossipHello = &GossipHello_npc_highlord_demitrian; - newscript->pGossipSelect = &GossipSelect_npc_highlord_demitrian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npcs_rutgar_and_frankal"; - newscript->pGossipHello = &GossipHello_npcs_rutgar_and_frankal; - newscript->pGossipSelect = &GossipSelect_npcs_rutgar_and_frankal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/stonetalon_mountains.cpp b/src/server/scripts/kalimdor/stonetalon_mountains.cpp deleted file mode 100644 index 6e627948788..00000000000 --- a/src/server/scripts/kalimdor/stonetalon_mountains.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Stonetalon_Mountains -SD%Complete: 95 -SDComment: Quest support: 6627, 6523 -SDCategory: Stonetalon Mountains -EndScriptData */ - -/* ContentData -npc_braug_dimspirit -npc_kaya_flathoof -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_braug_dimspirit -######*/ - -#define GOSSIP_HBD1 "Ysera" -#define GOSSIP_HBD2 "Neltharion" -#define GOSSIP_HBD3 "Nozdormu" -#define GOSSIP_HBD4 "Alexstrasza" -#define GOSSIP_HBD5 "Malygos" - -bool GossipHello_npc_braug_dimspirit(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(6627) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HBD5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(5820, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(5819, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_braug_dimspirit(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer,6766,false); - - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(6627); - } - return true; -} - -/*###### -## npc_kaya_flathoof -######*/ - -enum eKaya -{ - FACTION_ESCORTEE_H = 775, - - NPC_GRIMTOTEM_RUFFIAN = 11910, - NPC_GRIMTOTEM_BRUTE = 11912, - NPC_GRIMTOTEM_SORCERER = 11913, - - SAY_START = -1000357, - SAY_AMBUSH = -1000358, - SAY_END = -1000359, - - QUEST_PROTECT_KAYA = 6523 -}; - -struct npc_kaya_flathoofAI : public npc_escortAI -{ - npc_kaya_flathoofAI(Creature* c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 16: - DoScriptText(SAY_AMBUSH, me); - me->SummonCreature(NPC_GRIMTOTEM_BRUTE, -48.53, -503.34, -46.31, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_GRIMTOTEM_RUFFIAN, -38.85, -503.77, -45.90, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - me->SummonCreature(NPC_GRIMTOTEM_SORCERER, -36.37, -496.23, -45.71, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 18: me->SetInFront(pPlayer); - DoScriptText(SAY_END, me, pPlayer); - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_PROTECT_KAYA, me); - break; - } - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void Reset(){} -}; - -bool QuestAccept_npc_kaya_flathoof(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_PROTECT_KAYA) - { - if (npc_escortAI* pEscortAI = CAST_AI(npc_kaya_flathoofAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - - DoScriptText(SAY_START, pCreature); - pCreature->setFaction(113); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - return true; -} - -CreatureAI* GetAI_npc_kaya_flathoofAI(Creature* pCreature) -{ - return new npc_kaya_flathoofAI(pCreature); -} - -/*###### -## AddSC -######*/ - -void AddSC_stonetalon_mountains() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_braug_dimspirit"; - newscript->pGossipHello = &GossipHello_npc_braug_dimspirit; - newscript->pGossipSelect = &GossipSelect_npc_braug_dimspirit; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_kaya_flathoof"; - newscript->GetAI = &GetAI_npc_kaya_flathoofAI; - newscript->pQuestAccept = &QuestAccept_npc_kaya_flathoof; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/tanaris.cpp b/src/server/scripts/kalimdor/tanaris.cpp deleted file mode 100644 index bb82dea64cf..00000000000 --- a/src/server/scripts/kalimdor/tanaris.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Tanaris -SD%Complete: 80 -SDComment: Quest support: 648, 1560, 2954, 4005, 10277, 10279(Special flight path). Noggenfogger vendor -SDCategory: Tanaris -EndScriptData */ - -/* ContentData -mob_aquementas -npc_custodian_of_time -npc_marin_noggenfogger -npc_steward_of_time -npc_stone_watcher_of_norgannon -npc_OOX17 -npc_tooga -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "ScriptedFollowerAI.h" - -/*###### -## mob_aquementas -######*/ - -#define AGGRO_YELL_AQUE -1000350 - -#define SPELL_AQUA_JET 13586 -#define SPELL_FROST_SHOCK 15089 - -struct mob_aquementasAI : public ScriptedAI -{ - mob_aquementasAI(Creature *c) : ScriptedAI(c) {} - - uint32 SendItem_Timer; - uint32 SwitchFaction_Timer; - bool isFriendly; - - uint32 FrostShock_Timer; - uint32 AquaJet_Timer; - - void Reset() - { - SendItem_Timer = 0; - SwitchFaction_Timer = 10000; - me->setFaction(35); - isFriendly = true; - - AquaJet_Timer = 5000; - FrostShock_Timer = 1000; - } - - void SendItem(Unit* receiver) - { - if (CAST_PLR(receiver)->HasItemCount(11169,1,false) && - CAST_PLR(receiver)->HasItemCount(11172,11,false) && - CAST_PLR(receiver)->HasItemCount(11173,1,false) && - !CAST_PLR(receiver)->HasItemCount(11522,1,true)) - { - ItemPosCountVec dest; - uint8 msg = CAST_PLR(receiver)->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 11522, 1, false); - if (msg == EQUIP_ERR_OK) - CAST_PLR(receiver)->StoreNewItem(dest, 11522, 1, true); - } - } - - void EnterCombat(Unit* who) - { - DoScriptText(AGGRO_YELL_AQUE, me, who); - } - - void UpdateAI(const uint32 diff) - { - if (isFriendly) - { - if (SwitchFaction_Timer <= diff) - { - me->setFaction(91); - isFriendly = false; - } else SwitchFaction_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - if (!isFriendly) - { - if (SendItem_Timer <= diff) - { - if (me->getVictim()->GetTypeId() == TYPEID_PLAYER) - SendItem(me->getVictim()); - SendItem_Timer = 5000; - } else SendItem_Timer -= diff; - } - - if (FrostShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_SHOCK); - FrostShock_Timer = 15000; - } else FrostShock_Timer -= diff; - - if (AquaJet_Timer <= diff) - { - DoCast(me, SPELL_AQUA_JET); - AquaJet_Timer = 15000; - } else AquaJet_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_mob_aquementas(Creature* pCreature) -{ - return new mob_aquementasAI (pCreature); -} - -/*###### -## npc_custodian_of_time -######*/ - -#define WHISPER_CUSTODIAN_1 -1000217 -#define WHISPER_CUSTODIAN_2 -1000218 -#define WHISPER_CUSTODIAN_3 -1000219 -#define WHISPER_CUSTODIAN_4 -1000220 -#define WHISPER_CUSTODIAN_5 -1000221 -#define WHISPER_CUSTODIAN_6 -1000222 -#define WHISPER_CUSTODIAN_7 -1000223 -#define WHISPER_CUSTODIAN_8 -1000224 -#define WHISPER_CUSTODIAN_9 -1000225 -#define WHISPER_CUSTODIAN_10 -1000226 -#define WHISPER_CUSTODIAN_11 -1000227 -#define WHISPER_CUSTODIAN_12 -1000228 -#define WHISPER_CUSTODIAN_13 -1000229 -#define WHISPER_CUSTODIAN_14 -1000230 - -struct npc_custodian_of_timeAI : public npc_escortAI -{ - npc_custodian_of_timeAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player *pPlayer = GetPlayerForEscort(); - if (!pPlayer) - return; - - switch(i) - { - case 0: DoScriptText(WHISPER_CUSTODIAN_1, me, pPlayer); break; - case 1: DoScriptText(WHISPER_CUSTODIAN_2, me, pPlayer); break; - case 2: DoScriptText(WHISPER_CUSTODIAN_3, me, pPlayer); break; - case 3: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; - case 5: DoScriptText(WHISPER_CUSTODIAN_5, me, pPlayer); break; - case 6: DoScriptText(WHISPER_CUSTODIAN_6, me, pPlayer); break; - case 7: DoScriptText(WHISPER_CUSTODIAN_7, me, pPlayer); break; - case 8: DoScriptText(WHISPER_CUSTODIAN_8, me, pPlayer); break; - case 9: DoScriptText(WHISPER_CUSTODIAN_9, me, pPlayer); break; - case 10: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; - case 13: DoScriptText(WHISPER_CUSTODIAN_10, me, pPlayer); break; - case 14: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; - case 16: DoScriptText(WHISPER_CUSTODIAN_11, me, pPlayer); break; - case 17: DoScriptText(WHISPER_CUSTODIAN_12, me, pPlayer); break; - case 18: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; - case 22: DoScriptText(WHISPER_CUSTODIAN_13, me, pPlayer); break; - case 23: DoScriptText(WHISPER_CUSTODIAN_4, me, pPlayer); break; - case 24: - DoScriptText(WHISPER_CUSTODIAN_14, me, pPlayer); - DoCast(pPlayer, 34883); - // below here is temporary workaround, to be removed when spell works properly - pPlayer->AreaExploredOrEventHappens(10277); - break; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - if (who->GetTypeId() == TYPEID_PLAYER) - { - if (who->HasAura(34877) && CAST_PLR(who)->GetQuestStatus(10277) == QUEST_STATUS_INCOMPLETE) - { - float Radius = 10.0; - if (me->IsWithinDistInMap(who, Radius)) - { - Start(false, false, who->GetGUID()); - } - } - } - } - - void EnterCombat(Unit* /*who*/) {} - void Reset() { } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_custodian_of_time(Creature* pCreature) -{ - return new npc_custodian_of_timeAI(pCreature); -} - -/*###### -## npc_marin_noggenfogger -######*/ - -bool GossipHello_npc_marin_noggenfogger(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(2662)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_marin_noggenfogger(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_steward_of_time -######*/ - -#define GOSSIP_ITEM_FLIGHT "Please take me to the master's lair." - -bool GossipHello_npc_steward_of_time(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(10279) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestRewardStatus(10279)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(9978, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(9977, pCreature->GetGUID()); - - return true; -} - -bool QuestAccept_npc_steward_of_time(Player* pPlayer, Creature* /*pCreature*/, Quest const *quest) -{ - if (quest->GetQuestId() == 10279) //Quest: To The Master's Lair - pPlayer->CastSpell(pPlayer,34891,true); //(Flight through Caverns) - - return false; -} - -bool GossipSelect_npc_steward_of_time(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - pPlayer->CastSpell(pPlayer,34891,true); //(Flight through Caverns) - - return true; -} - -/*###### -## npc_stone_watcher_of_norgannon -######*/ - -#define GOSSIP_ITEM_NORGANNON_1 "What function do you serve?" -#define GOSSIP_ITEM_NORGANNON_2 "What are the Plates of Uldum?" -#define GOSSIP_ITEM_NORGANNON_3 "Where are the Plates of Uldum?" -#define GOSSIP_ITEM_NORGANNON_4 "Excuse me? We've been \"reschedueled for visitations\"? What does that mean?!" -#define GOSSIP_ITEM_NORGANNON_5 "So, what's inside Uldum?" -#define GOSSIP_ITEM_NORGANNON_6 "I will return when i have the Plates of Uldum." - -bool GossipHello_npc_stone_watcher_of_norgannon(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(2954) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(1674, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_stone_watcher_of_norgannon(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(1675, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(1676, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(1677, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(1678, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(1679, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(2954); - break; - } - return true; -} - -/*###### -## npc_OOX17 -######*/ - -enum e00X17 -{ - //texts are signed for 7806 - SAY_OOX_START = -1000287, - SAY_OOX_AGGRO1 = -1000288, - SAY_OOX_AGGRO2 = -1000289, - SAY_OOX_AMBUSH = -1000290, - SAY_OOX17_AMBUSH_REPLY = -1000291, - SAY_OOX_END = -1000292, - - Q_OOX17 = 648, - SPAWN_FIRST = 7803, - SPAWN_SECOND_1 = 5617, - SPAWN_SECOND_2 = 7805 -}; - -struct npc_OOX17AI : public npc_escortAI -{ - npc_OOX17AI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) { - case 23: - me->SummonCreature(SPAWN_FIRST, -8350.96, -4445.79, 10.10, 6.20, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(SPAWN_FIRST, -8355.96, -4447.79, 10.10, 6.27, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(SPAWN_FIRST, -8353.96, -4442.79, 10.10, 6.08, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - DoScriptText(SAY_OOX_AMBUSH, me); - break; - - case 56: - me->SummonCreature(SPAWN_SECOND_1, -7510.07, -4795.50, 9.35, 6.06, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(SPAWN_SECOND_2, -7515.07, -4797.50, 9.35, 6.22, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(SPAWN_SECOND_2, -7518.07, -4792.50, 9.35, 6.22, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - DoScriptText(SAY_OOX_AMBUSH, me); - if (Unit* scoff = me->FindNearestCreature(SPAWN_SECOND_2, 30)) - DoScriptText(SAY_OOX17_AMBUSH_REPLY, scoff); - break; - - case 86: - if (pPlayer) - { - DoScriptText(SAY_OOX_END, me); - pPlayer->GroupEventHappens(Q_OOX17, me); - } - break; - } - } - - void Reset(){} - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(RAND(SAY_OOX_AGGRO1,SAY_OOX_AGGRO2), me); - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } -}; - -bool QuestAccept_npc_OOX17(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == Q_OOX17) - { - pCreature->setFaction(113); - pCreature->SetHealth(pCreature->GetMaxHealth()); - pCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - DoScriptText(SAY_OOX_START, pCreature); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_OOX17AI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - } - return true; -} - -CreatureAI* GetAI_npc_OOX17(Creature* pCreature) -{ - return new npc_OOX17AI(pCreature); -} - -/*#### -# npc_tooga -####*/ - -enum eTooga -{ - SAY_TOOG_THIRST = -1000391, - SAY_TOOG_WORRIED = -1000392, - SAY_TOOG_POST_1 = -1000393, - SAY_TORT_POST_2 = -1000394, - SAY_TOOG_POST_3 = -1000395, - SAY_TORT_POST_4 = -1000396, - SAY_TOOG_POST_5 = -1000397, - SAY_TORT_POST_6 = -1000398, - - QUEST_TOOGA = 1560, - NPC_TORTA = 6015, - - POINT_ID_TO_WATER = 1, - FACTION_TOOG_ESCORTEE = 113 -}; - -const float m_afToWaterLoc[] = {-7032.664551, -4906.199219, -1.606446}; - -struct npc_toogaAI : public FollowerAI -{ - npc_toogaAI(Creature* pCreature) : FollowerAI(pCreature) { } - - uint32 m_uiCheckSpeechTimer; - uint32 m_uiPostEventTimer; - uint32 m_uiPhasePostEvent; - - uint64 TortaGUID; - - void Reset() - { - m_uiCheckSpeechTimer = 2500; - m_uiPostEventTimer = 1000; - m_uiPhasePostEvent = 0; - - TortaGUID = 0; - } - - void MoveInLineOfSight(Unit *pWho) - { - FollowerAI::MoveInLineOfSight(pWho); - - if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE | STATE_FOLLOW_POSTEVENT) && pWho->GetEntry() == NPC_TORTA) - { - if (me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) - { - if (Player* pPlayer = GetLeaderForFollower()) - { - if (pPlayer->GetQuestStatus(QUEST_TOOGA) == QUEST_STATUS_INCOMPLETE) - pPlayer->GroupEventHappens(QUEST_TOOGA, me); - } - - TortaGUID = pWho->GetGUID(); - SetFollowComplete(true); - } - } - } - - void MovementInform(uint32 uiMotionType, uint32 uiPointId) - { - FollowerAI::MovementInform(uiMotionType, uiPointId); - - if (uiMotionType != POINT_MOTION_TYPE) - return; - - if (uiPointId == POINT_ID_TO_WATER) - SetFollowComplete(); - } - - void UpdateFollowerAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - { - //we are doing the post-event, or... - if (HasFollowState(STATE_FOLLOW_POSTEVENT)) - { - if (m_uiPostEventTimer <= uiDiff) - { - m_uiPostEventTimer = 5000; - - Unit *pTorta = Unit::GetUnit(*me, TortaGUID); - if (!pTorta || !pTorta->isAlive()) - { - //something happened, so just complete - SetFollowComplete(); - return; - } - - switch(m_uiPhasePostEvent) - { - case 1: - DoScriptText(SAY_TOOG_POST_1, me); - break; - case 2: - DoScriptText(SAY_TORT_POST_2, pTorta); - break; - case 3: - DoScriptText(SAY_TOOG_POST_3, me); - break; - case 4: - DoScriptText(SAY_TORT_POST_4, pTorta); - break; - case 5: - DoScriptText(SAY_TOOG_POST_5, me); - break; - case 6: - DoScriptText(SAY_TORT_POST_6, pTorta); - me->GetMotionMaster()->MovePoint(POINT_ID_TO_WATER, m_afToWaterLoc[0], m_afToWaterLoc[1], m_afToWaterLoc[2]); - break; - } - - ++m_uiPhasePostEvent; - } - else - m_uiPostEventTimer -= uiDiff; - } - //...we are doing regular speech check - else if (HasFollowState(STATE_FOLLOW_INPROGRESS)) - { - if (m_uiCheckSpeechTimer <= uiDiff) - { - m_uiCheckSpeechTimer = 5000; - - if (urand(0,9) > 8) - DoScriptText(RAND(SAY_TOOG_THIRST,SAY_TOOG_WORRIED), me); - } - else - m_uiCheckSpeechTimer -= uiDiff; - } - - return; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_tooga(Creature* pCreature) -{ - return new npc_toogaAI(pCreature); -} - -bool QuestAccept_npc_tooga(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_TOOGA) - { - if (npc_toogaAI* pToogaAI = CAST_AI(npc_toogaAI, pCreature->AI())) - pToogaAI->StartFollow(pPlayer, FACTION_TOOG_ESCORTEE, pQuest); - } - - return true; -} - -void AddSC_tanaris() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_aquementas"; - newscript->GetAI = &GetAI_mob_aquementas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_custodian_of_time"; - newscript->GetAI = &GetAI_npc_custodian_of_time; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_marin_noggenfogger"; - newscript->pGossipHello = &GossipHello_npc_marin_noggenfogger; - newscript->pGossipSelect = &GossipSelect_npc_marin_noggenfogger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_steward_of_time"; - newscript->pGossipHello = &GossipHello_npc_steward_of_time; - newscript->pGossipSelect = &GossipSelect_npc_steward_of_time; - newscript->pQuestAccept = &QuestAccept_npc_steward_of_time; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_stone_watcher_of_norgannon"; - newscript->pGossipHello = &GossipHello_npc_stone_watcher_of_norgannon; - newscript->pGossipSelect = &GossipSelect_npc_stone_watcher_of_norgannon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_OOX17"; - newscript->GetAI = &GetAI_npc_OOX17; - newscript->pQuestAccept = &QuestAccept_npc_OOX17; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tooga"; - newscript->GetAI = &GetAI_npc_tooga; - newscript->pQuestAccept = &QuestAccept_npc_tooga; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/teldrassil.cpp b/src/server/scripts/kalimdor/teldrassil.cpp deleted file mode 100644 index 1607ab904a8..00000000000 --- a/src/server/scripts/kalimdor/teldrassil.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Teldrassil -SD%Complete: 100 -SDComment: Quest support: 938 -SDCategory: Teldrassil -EndScriptData */ - -/* ContentData -npc_mist -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedFollowerAI.h" - -/*#### -# npc_mist -####*/ - -enum eMist -{ - SAY_AT_HOME = -1000323, - EMOTE_AT_HOME = -1000324, - QUEST_MIST = 938, - NPC_ARYNIA = 3519, - FACTION_DARNASSUS = 79 -}; - -struct npc_mistAI : public FollowerAI -{ - npc_mistAI(Creature* pCreature) : FollowerAI(pCreature) { } - - void Reset() { } - - void MoveInLineOfSight(Unit *pWho) - { - FollowerAI::MoveInLineOfSight(pWho); - - if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_ARYNIA) - { - if (me->IsWithinDistInMap(pWho, 10.0f)) - { - DoScriptText(SAY_AT_HOME, pWho); - DoComplete(); - } - } - } - - void DoComplete() - { - DoScriptText(EMOTE_AT_HOME, me); - - if (Player* pPlayer = GetLeaderForFollower()) - { - if (pPlayer->GetQuestStatus(QUEST_MIST) == QUEST_STATUS_INCOMPLETE) - pPlayer->GroupEventHappens(QUEST_MIST, me); - } - - //The follow is over (and for later development, run off to the woods before really end) - SetFollowComplete(); - } - - //call not needed here, no known abilities - /*void UpdateFollowerAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - }*/ -}; - -CreatureAI* GetAI_npc_mist(Creature* pCreature) -{ - return new npc_mistAI(pCreature); -} - -bool QuestAccept_npc_mist(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_MIST) - { - if (npc_mistAI* pMistAI = CAST_AI(npc_mistAI, pCreature->AI())) - pMistAI->StartFollow(pPlayer, FACTION_DARNASSUS, pQuest); - } - - return true; -} - -void AddSC_teldrassil() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_mist"; - newscript->GetAI = &GetAI_npc_mist; - newscript->pQuestAccept = &QuestAccept_npc_mist; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp deleted file mode 100644 index f6e3b0c741b..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: boss_kri, boss_yauj, boss_vem : The Bug Trio -SD%Complete: 100 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" - -#define SPELL_CLEAVE 26350 -#define SPELL_TOXIC_VOLLEY 25812 -#define SPELL_POISON_CLOUD 38718 //Only Spell with right dmg. -#define SPELL_ENRAGE 34624 //Changed cause 25790 is casted on gamers too. Same prob with old explosion of twin emperors. - -#define SPELL_CHARGE 26561 -#define SPELL_KNOCKBACK 26027 - -#define SPELL_HEAL 25807 -#define SPELL_FEAR 19408 - -struct boss_kriAI : public ScriptedAI -{ - boss_kriAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Cleave_Timer; - uint32 ToxicVolley_Timer; - uint32 Check_Timer; - - bool VemDead; - bool Death; - - void Reset() - { - Cleave_Timer = 4000 + rand()%4000; - ToxicVolley_Timer = 6000 + rand()%6000; - Check_Timer = 2000; - - VemDead = false; - Death = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) - // Unlootable if death - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - - pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); - } - } - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 5000 + rand()%7000; - } else Cleave_Timer -= diff; - - //ToxicVolley_Timer - if (ToxicVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TOXIC_VOLLEY); - ToxicVolley_Timer = 10000 + rand()%5000; - } else ToxicVolley_Timer -= diff; - - if (me->GetHealth() <= me->GetMaxHealth() * 0.05 && !Death) - { - DoCast(me->getVictim(), SPELL_POISON_CLOUD); - Death = true; - } - - if (!VemDead) - { - //Checking if Vem is dead. If yes we will enrage. - if (Check_Timer <= diff) - { - if (pInstance && pInstance->GetData(DATA_VEMISDEAD)) - { - DoCast(me, SPELL_ENRAGE); - VemDead = true; - } - Check_Timer = 2000; - } else Check_Timer -=diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_vemAI : public ScriptedAI -{ - boss_vemAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Charge_Timer; - uint32 KnockBack_Timer; - uint32 Enrage_Timer; - - bool Enraged; - - void Reset() - { - Charge_Timer = 15000 + rand()%12000; - KnockBack_Timer = 8000 + rand()%12000; - Enrage_Timer = 120000; - - Enraged = false; - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_VEM_DEATH, 0); - if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) - // Unlootable if death - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Charge_Timer - if (Charge_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - { - DoCast(pTarget, SPELL_CHARGE); - //me->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, true,1); - AttackStart(pTarget); - } - - Charge_Timer = 8000 + rand()%8000; - } else Charge_Timer -= diff; - - //KnockBack_Timer - if (KnockBack_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKBACK); - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-80); - KnockBack_Timer = 15000 + rand()%10000; - } else KnockBack_Timer -= diff; - - //Enrage_Timer - if (!Enraged && Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else Charge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_yaujAI : public ScriptedAI -{ - boss_yaujAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Heal_Timer; - uint32 Fear_Timer; - uint32 Check_Timer; - - bool VemDead; - - void Reset() - { - Heal_Timer = 25000 + rand()%15000; - Fear_Timer = 12000 + rand()%12000; - Check_Timer = 2000; - - VemDead = false; - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) - // Unlootable if death - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); - } - - for (uint8 i = 0; i < 10; ++i) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - Creature* Summoned = me->SummonCreature(15621,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,90000); - if (Summoned && pTarget) - Summoned->AI()->AttackStart(pTarget); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - DoResetThreat(); - Fear_Timer = 20000; - } else Fear_Timer -= diff; - - //Casting Heal to other twins or herself. - if (Heal_Timer <= diff) - { - if (pInstance) - { - Unit *pKri = Unit::GetUnit((*me), pInstance->GetData64(DATA_KRI)); - Unit *pVem = Unit::GetUnit((*me), pInstance->GetData64(DATA_VEM)); - - switch (urand(0,2)) - { - case 0: - if (pKri) - DoCast(pKri, SPELL_HEAL); - break; - case 1: - if (pVem) - DoCast(pVem, SPELL_HEAL); - break; - case 2: - DoCast(me, SPELL_HEAL); - break; - } - } - - Heal_Timer = 15000+rand()%15000; - } else Heal_Timer -= diff; - - //Checking if Vem is dead. If yes we will enrage. - if (Check_Timer <= diff) - { - if (!VemDead) - { - if (pInstance) - { - if (pInstance->GetData(DATA_VEMISDEAD)) - { - DoCast(me, SPELL_ENRAGE); - VemDead = true; - } - } - } - Check_Timer = 2000; - } else Check_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_yauj(Creature* pCreature) -{ - return new boss_yaujAI (pCreature); -} - -CreatureAI* GetAI_boss_vem(Creature* pCreature) -{ - return new boss_vemAI (pCreature); -} - -CreatureAI* GetAI_boss_kri(Creature* pCreature) -{ - return new boss_kriAI (pCreature); -} - -void AddSC_bug_trio() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kri"; - newscript->GetAI = &GetAI_boss_kri; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_vem"; - newscript->GetAI = &GetAI_boss_vem; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_yauj"; - newscript->GetAI = &GetAI_boss_yauj; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp deleted file mode 100644 index 3e42d16be3a..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp +++ /dev/null @@ -1,1307 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Cthun -SD%Complete: 95 -SDComment: Darkglare tracking issue -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" - -/* - * This is a 2 phases events. Here follows an explanation of the main events and transition between phases and sub-phases. - * - * The first phase is the EYE phase: the Eye of C'Thun is active and C'thun is not active. - * During this phase, the "Eye of C'Thun" alternates between 2 sub-phases: - * - PHASE_EYE_GREEN_BEAM: - * 50 sec phase during which the Eye mainly casts its Green Beam every 3 sec. - * - PHASE_EYE_RED_BEAM: - * 35 sec phase during which the Eye casts its red beam every sec. - * This EYE phase ends when the "Eye of C'Thun" is killed. Then starts the CTHUN phase. - * - * The second phase is the CTHUN phase. The Eye of C'Thun is not active and C'Thun is active. - * This phase starts with the transformation of the Eye into C'Thun (PHASE_CTHUN_TRANSITION). - * After the transformation, C'Thun alternates between 2 sub-phases: - * - PHASE_CTHUN_STOMACH: - * - C'Thun is almost insensible to all damage (99% damage reduction). - * - It spawns 2 tentacles in its stomach. - * - C'Thun swallows players. - * - This sub-phase ends when the 2 tentacles are killed. Swallowed players are regurgitate. - * - * - PHASE_CTHUN_WEAK: - * - weakened C'Thun takes normal damage. - * - This sub-phase ends after 45 secs. - * - * This CTHUN phase ends when C'Thun is killed - * - * Note: - * - the current phase is stored in the instance data to be easily shared between the eye and cthun. - */ - -#define PI 3.14 - -enum Phases -{ - PHASE_NOT_STARTED = 0, - - // Main Phase 1 - EYE - PHASE_EYE_GREEN_BEAM = 1, - PHASE_EYE_RED_BEAM = 2, - - // Main Phase 2 - CTHUN - PHASE_CTHUN_TRANSITION = 3, - PHASE_CTHUN_STOMACH = 4, - PHASE_CTHUN_WEAK = 5, - - PHASE_CTHUN_DONE = 6, -}; - -enum Creatures -{ - MOB_CTHUN_PORTAL = 15896, - - //***** Main Phase 1 ******** - BOSS_EYE_OF_CTHUN = 15589, - MOB_CLAW_TENTACLE = 15725, - MOB_EYE_TENTACLE = 15726, - MOB_SMALL_PORTAL = 15904, - - //***** Main Phase 2 ******** - MOB_BODY_OF_CTHUN = 15809, - MOB_GIANT_CLAW_TENTACLE = 15728, - MOB_GIANT_EYE_TENTACLE = 15334, - MOB_FLESH_TENTACLE = 15802, - MOB_GIANT_PORTAL = 15910, -}; - -enum Spells -{ - //***** Main Phase 1 ******** - //Eye Spells - SPELL_FREEZE_ANIM = 16245, - SPELL_GREEN_BEAM = 26134, - SPELL_DARK_GLARE = 26029, - SPELL_RED_COLORATION = 22518, //Probably not the right spell but looks similar - - //Eye Tentacles Spells - SPELL_MIND_FLAY = 26143, - - //Claw Tentacles Spells - SPELL_GROUND_RUPTURE = 26139, - SPELL_HAMSTRING = 26141, - - //***** Main Phase 2 ****** - //Body spells - //#define SPELL_CARAPACE_CTHUN 26156 //Was removed from client dbcs - SPELL_TRANSFORM = 26232, - SPELL_PURPLE_COLORATION = 22581, //Probably not the right spell but looks similar - - //Eye Tentacles Spells - //SAME AS PHASE1 - - //Giant Claw Tentacles - SPELL_MASSIVE_GROUND_RUPTURE = 26100, - - //Also casts Hamstring - SPELL_THRASH = 3391, - - //Giant Eye Tentacles - //CHAIN CASTS "SPELL_GREEN_BEAM" - - //Stomach Spells - SPELL_MOUTH_TENTACLE = 26332, - SPELL_EXIT_STOMACH_KNOCKBACK = 25383, - SPELL_DIGESTIVE_ACID = 26476, -}; - -enum Actions -{ - ACTION_FLESH_TENTACLE_KILLED = 1, -}; - -enum Yells -{ - //Text emote - EMOTE_WEAKENED = -1531011, - - //****** Out of Combat ****** - // Random Wispers - No txt only sound - // The random sound is chosen by the client. - RANDOM_SOUND_WHISPER = 8663, -}; - -//Stomach Teleport positions -#define STOMACH_X -8562.0f -#define STOMACH_Y 2037.0f -#define STOMACH_Z -70.0f -#define STOMACH_O 5.05f - -//Flesh tentacle positions -const Position FleshTentaclePos[2] = -{ - { -8571.0f, 1990.0f, -98.0f, 1.22f}, - { -8525.0f, 1994.0f, -98.0f, 2.12f}, -}; - -//Kick out position -const Position KickPos = { -8545.0f, 1984.0f, -96.0f}; - -struct eye_of_cthunAI : public Scripted_NoMovementAI -{ - eye_of_cthunAI(Creature *c) : Scripted_NoMovementAI(c) - { - pInst = c->GetInstanceData(); - if (!pInst) - error_log("TSCR: No Instance eye_of_cthunAI"); - } - - ScriptedInstance* pInst; - - //Global variables - uint32 PhaseTimer; - - //Eye beam phase - uint32 BeamTimer; - uint32 EyeTentacleTimer; - uint32 ClawTentacleTimer; - - //Dark Glare phase - uint32 DarkGlareTick; - uint32 DarkGlareTickTimer; - float DarkGlareAngle; - bool ClockWise; - - void Reset() - { - //Phase information - PhaseTimer = 50000; //First dark glare in 50 seconds - - //Eye beam phase 50 seconds - BeamTimer = 3000; - EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam - ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam) - - //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks) - DarkGlareTick = 0; - DarkGlareTickTimer = 1000; - DarkGlareAngle = 0; - ClockWise = false; - - //Reset flags - me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_ON); - - //Reset Phase - if (pInst) - pInst->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); - - //to avoid having a following void zone - Creature* pPortal= me->FindNearestCreature(MOB_CTHUN_PORTAL, 10); - if (pPortal) - pPortal->SetReactState(REACT_PASSIVE); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - if (pInst) - pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); - } - - void SpawnEyeTentacle(float x, float y) - { - if (Creature* Spawned = DoSpawnCreature(MOB_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500)) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - if (Spawned->AI()) - Spawned->AI()->AttackStart(pTarget); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //No instance - if (!pInst) - return; - - uint32 currentPhase = pInst->GetData(DATA_CTHUN_PHASE); - if (currentPhase == PHASE_EYE_GREEN_BEAM || currentPhase == PHASE_EYE_RED_BEAM) - { - // EyeTentacleTimer - if (EyeTentacleTimer <= diff) - { - //Spawn the 8 Eye Tentacles in the corret spots - SpawnEyeTentacle(0, 20); //south - SpawnEyeTentacle(10, 10); //south west - SpawnEyeTentacle(20, 0); //west - SpawnEyeTentacle(10, -10); //north west - - SpawnEyeTentacle(0, -20); //north - SpawnEyeTentacle(-10, -10); //north east - SpawnEyeTentacle(-20, 0); // east - SpawnEyeTentacle(-10, 10); // south east - - EyeTentacleTimer = 45000; - } else EyeTentacleTimer -= diff; - } - - switch (currentPhase) - { - case PHASE_EYE_GREEN_BEAM: - //BeamTimer - if (BeamTimer <= diff) - { - //SPELL_GREEN_BEAM - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - me->InterruptNonMeleeSpells(false); - DoCast(pTarget, SPELL_GREEN_BEAM); - - //Correctly update our target - me->SetUInt64Value(UNIT_FIELD_TARGET, pTarget->GetGUID()); - } - - //Beam every 3 seconds - BeamTimer = 3000; - } else BeamTimer -= diff; - - //ClawTentacleTimer - if (ClawTentacleTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - Creature* Spawned = NULL; - - //Spawn claw tentacle on the random target - Spawned = me->SummonCreature(MOB_CLAW_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500); - - if (Spawned && Spawned->AI()) - Spawned->AI()->AttackStart(pTarget); - } - - //One claw tentacle every 12.5 seconds - ClawTentacleTimer = 12500; - } else ClawTentacleTimer -= diff; - - //PhaseTimer - if (PhaseTimer <= diff) - { - //Switch to Dark Beam - pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_RED_BEAM); - - me->InterruptNonMeleeSpells(false); - me->SetReactState(REACT_PASSIVE); - - //Remove any target - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - //Select random target for dark beam to start on - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - //Face our target - DarkGlareAngle = me->GetAngle(pTarget); - DarkGlareTickTimer = 1000; - DarkGlareTick = 0; - ClockWise = RAND(true, false); - } - - //Add red coloration to C'thun - DoCast(me, SPELL_RED_COLORATION, true); - - //Freeze animation - DoCast(me, SPELL_FREEZE_ANIM); - me->SetOrientation(DarkGlareAngle); - me->StopMoving(); - - //Darkbeam for 35 seconds - PhaseTimer = 35000; - } else PhaseTimer -= diff; - - break; - - case PHASE_EYE_RED_BEAM: - if (DarkGlareTick < 35) - if (DarkGlareTickTimer <= diff) - { - //Set angle and cast - if (ClockWise) - me->SetOrientation(DarkGlareAngle + ((float)DarkGlareTick*PI/35)); - else - me->SetOrientation(DarkGlareAngle - ((float)DarkGlareTick*PI/35)); - - me->StopMoving(); - - //Actual dark glare cast, maybe something missing here? - DoCast(me, SPELL_DARK_GLARE, false); - - //Increase tick - ++DarkGlareTick; - - //1 second per tick - DarkGlareTickTimer = 1000; - } else DarkGlareTickTimer -= diff; - - //PhaseTimer - if (PhaseTimer <= diff) - { - //Switch to Eye Beam - pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); - - BeamTimer = 3000; - ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam) - - me->InterruptNonMeleeSpells(false); - - //Remove Red coloration from c'thun - me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); - - //set it back to aggressive - me->SetReactState(REACT_AGGRESSIVE); - - //Eye Beam for 50 seconds - PhaseTimer = 50000; - } else PhaseTimer -= diff; - - break; - - //Transition phase - case PHASE_CTHUN_TRANSITION: - //Remove any target - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - me->SetHealth(0); - me->SetVisibility(VISIBILITY_OFF); - break; - - //Dead phase - case PHASE_CTHUN_DONE: - Creature* pPortal= me->FindNearestCreature(MOB_CTHUN_PORTAL, 10); - if (pPortal) - pPortal->ForcedDespawn(); - - me->ForcedDespawn(); - break; - } - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - //No instance - if (!pInst) - return; - - switch (pInst->GetData(DATA_CTHUN_PHASE)) - { - case PHASE_EYE_GREEN_BEAM: - case PHASE_EYE_RED_BEAM: - //Only if it will kill - if (damage < me->GetHealth()) - return; - - //Fake death in phase 0 or 1 (green beam or dark glare phase) - me->InterruptNonMeleeSpells(false); - - //Remove Red coloration from c'thun - me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - - //Reset to normal emote state and prevent select and attack - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - //Remove Target field - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - //Death animation/respawning; - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_TRANSITION); - - me->SetHealth(0); - damage = 0; - - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - break; - - case PHASE_CTHUN_DONE: - //Allow death here - return; - - default: - //Prevent death in these phases - damage = 0; - return; - } - } -}; - -struct cthunAI : public Scripted_NoMovementAI -{ - cthunAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - - pInst = c->GetInstanceData(); - if (!pInst) - error_log("TSCR: No Instance eye_of_cthunAI"); - } - - ScriptedInstance* pInst; - - //Out of combat whisper timer - uint32 WisperTimer; - - //Global variables - uint32 PhaseTimer; - - //------------------- - - //Phase transition - uint64 HoldPlayer; - - //Body Phase - uint32 EyeTentacleTimer; - uint8 FleshTentaclesKilled; - uint32 GiantClawTentacleTimer; - uint32 GiantEyeTentacleTimer; - uint32 StomachAcidTimer; - uint32 StomachEnterTimer; - uint32 StomachEnterVisTimer; - uint64 StomachEnterTarget; - - //Stomach map, bool = true then in stomach - UNORDERED_MAP Stomach_Map; - - void Reset() - { - //One random wisper every 90 - 300 seconds - WisperTimer = 90000; - - //Phase information - PhaseTimer = 10000; //Emerge in 10 seconds - - //No hold player for transition - HoldPlayer = 0; - - //Body Phase - EyeTentacleTimer = 30000; - FleshTentaclesKilled = 0; - GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat) - GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat) - StomachAcidTimer = 4000; //Every 4 seconds - StomachEnterTimer = 10000; //Every 10 seconds - StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer - StomachEnterTarget = 0; //Target to be teleported to stomach - - //Clear players in stomach and outside - Stomach_Map.clear(); - - //Reset flags - me->RemoveAurasDueToSpell(SPELL_TRANSFORM); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_OFF); - - if (pInst) - pInst->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void SpawnEyeTentacle(float x, float y) - { - Creature* Spawned; - Spawned = DoSpawnCreature(MOB_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500); - if (Spawned && Spawned->AI()) - if (Unit *pTarget = SelectRandomNotStomach()) - Spawned->AI()->AttackStart(pTarget); - } - - Unit* SelectRandomNotStomach() - { - if (Stomach_Map.empty()) - return NULL; - - UNORDERED_MAP::const_iterator i = Stomach_Map.begin(); - - std::list temp; - std::list::const_iterator j; - - //Get all players in map - while (i != Stomach_Map.end()) - { - //Check for valid player - Unit* pUnit = Unit::GetUnit(*me, i->first); - - //Only units out of stomach - if (pUnit && i->second == false) - temp.push_back(pUnit); - - ++i; - } - - if (temp.empty()) - return NULL; - - j = temp.begin(); - - //Get random but only if we have more than one unit on threat list - if (temp.size() > 1) - advance (j , rand() % (temp.size() - 1)); - - return (*j); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - { - //No target so we'll use this section to do our random wispers instance wide - //WisperTimer - if (WisperTimer <= diff) - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) return; - - //Play random sound to the zone - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) - { - if (Player* pPlr = itr->getSource()) - pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER,pPlr); - } - } - - //One random wisper every 90 - 300 seconds - WisperTimer = urand(90000,300000); - } else WisperTimer -= diff; - - return; - } - - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - //No instance - if (!pInst) - return; - - uint32 currentPhase = pInst->GetData(DATA_CTHUN_PHASE); - if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK) - { - // EyeTentacleTimer - if (EyeTentacleTimer <= diff) - { - //Spawn the 8 Eye Tentacles in the corret spots - SpawnEyeTentacle(0, 20); //south - SpawnEyeTentacle(10, 10); //south west - SpawnEyeTentacle(20, 0); //west - SpawnEyeTentacle(10, -10); //north west - - SpawnEyeTentacle(0, -20); //north - SpawnEyeTentacle(-10, -10); //north east - SpawnEyeTentacle(-20, 0); // east - SpawnEyeTentacle(-10, 10); // south east - - EyeTentacleTimer = 30000; // every 30sec in phase 2 - } else EyeTentacleTimer -= diff; - } - - switch (currentPhase) - { - //Transition phase - case PHASE_CTHUN_TRANSITION: - //PhaseTimer - if (PhaseTimer <= diff) - { - //Switch - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); - - //Switch to c'thun model - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_TRANSFORM, false); - me->SetHealth(me->GetMaxHealth()); - - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - //Emerging phase - //AttackStart(Unit::GetUnit(*me, HoldpPlayer)); - DoZoneInCombat(); - - //Place all units in threat list on outside of stomach - Stomach_Map.clear(); - - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - //Outside stomach - Stomach_Map[(*i)->getUnitGuid()] = false; - } - - //Spawn 2 flesh tentacles - FleshTentaclesKilled = 0; - - //Spawn flesh tentacle - for (uint8 i = 0; i < 2; i++) - { - Creature* spawned = me->SummonCreature(MOB_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); - if (!spawned) - ++FleshTentaclesKilled; - } - - PhaseTimer = 0; - } else PhaseTimer -= diff; - - break; - - //Body Phase - case PHASE_CTHUN_STOMACH: - //Remove Target field - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - //Weaken - if (FleshTentaclesKilled > 1) - { - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_WEAK); - - DoScriptText(EMOTE_WEAKENED, me); - PhaseTimer = 45000; - - DoCast(me, SPELL_PURPLE_COLORATION, true); - - UNORDERED_MAP::iterator i = Stomach_Map.begin(); - - //Kick all players out of stomach - while (i != Stomach_Map.end()) - { - //Check for valid player - Unit* pUnit = Unit::GetUnit(*me, i->first); - - //Only move units in stomach - if (pUnit && i->second == true) - { - //Teleport each player out - DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+10, rand()%6); - - //Cast knockback on them - DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); - - //Remove the acid debuff - pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); - - i->second = false; - } - ++i; - } - - return; - } - - //Stomach acid - if (StomachAcidTimer <= diff) - { - //Apply aura to all players in stomach - UNORDERED_MAP::iterator i = Stomach_Map.begin(); - - while (i != Stomach_Map.end()) - { - //Check for valid player - Unit* pUnit = Unit::GetUnit(*me, i->first); - - //Only apply to units in stomach - if (pUnit && i->second == true) - { - //Cast digestive acid on them - DoCast(pUnit, SPELL_DIGESTIVE_ACID, true); - - //Check if player should be kicked from stomach - if (pUnit->IsWithinDist3d(&KickPos, 15.0f)) - { - //Teleport each player out - DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+10, rand()%6); - - //Cast knockback on them - DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); - - //Remove the acid debuff - pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); - - i->second = false; - } - } - ++i; - } - - StomachAcidTimer = 4000; - } else StomachAcidTimer -= diff; - - //Stomach Enter Timer - if (StomachEnterTimer <= diff) - { - if (Unit *pTarget = SelectRandomNotStomach()) - { - //Set target in stomach - Stomach_Map[pTarget->GetGUID()] = true; - pTarget->InterruptNonMeleeSpells(false); - pTarget->CastSpell(pTarget, SPELL_MOUTH_TENTACLE, true, NULL, NULL, me->GetGUID()); - StomachEnterTarget = pTarget->GetGUID(); - StomachEnterVisTimer = 3800; - } - - StomachEnterTimer = 13800; - } else StomachEnterTimer -= diff; - - if (StomachEnterVisTimer && StomachEnterTarget) - if (StomachEnterVisTimer <= diff) - { - //Check for valid player - Unit* pUnit = Unit::GetUnit(*me, StomachEnterTarget); - - if (pUnit) - { - DoTeleportPlayer(pUnit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O); - } - - StomachEnterTarget = 0; - StomachEnterVisTimer = 0; - } else StomachEnterVisTimer -= diff; - - //GientClawTentacleTimer - if (GiantClawTentacleTimer <= diff) - { - if (Unit *pTarget = SelectRandomNotStomach()) - { - //Spawn claw tentacle on the random target - if (Creature* spawned = me->SummonCreature(MOB_GIANT_CLAW_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500)) - if (spawned->AI()) - spawned->AI()->AttackStart(pTarget); - } - - //One giant claw tentacle every minute - GiantClawTentacleTimer = 60000; - } else GiantClawTentacleTimer -= diff; - - //GiantEyeTentacleTimer - if (GiantEyeTentacleTimer <= diff) - { - if (Unit *pTarget = SelectRandomNotStomach()) - { - //Spawn claw tentacle on the random target - if (Creature* spawned = me->SummonCreature(MOB_GIANT_EYE_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500)) - if (spawned->AI()) - spawned->AI()->AttackStart(pTarget); - } - - //One giant eye tentacle every minute - GiantEyeTentacleTimer = 60000; - } else GiantEyeTentacleTimer -= diff; - - break; - - //Weakened state - case PHASE_CTHUN_WEAK: - //PhaseTimer - if (PhaseTimer <= diff) - { - //Switch - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); - - //Remove purple coloration - me->RemoveAurasDueToSpell(SPELL_PURPLE_COLORATION); - - //Spawn 2 flesh tentacles - FleshTentaclesKilled = 0; - - //Spawn flesh tentacle - for (uint8 i = 0; i < 2; i++) - { - Creature* spawned = me->SummonCreature(MOB_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); - if (!spawned) - ++FleshTentaclesKilled; - } - - PhaseTimer = 0; - } else PhaseTimer -= diff; - - break; - } - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInst) - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - //No instance - if (!pInst) - return; - - switch (pInst->GetData(DATA_CTHUN_PHASE)) - { - case PHASE_CTHUN_STOMACH: - //Not weakened so reduce damage by 99% - damage /= 100; - if (damage == 0) - damage = 1; - - //Prevent death in non-weakened state - if (damage >= me->GetHealth()) - damage = 0; - - return; - - case PHASE_CTHUN_WEAK: - //Weakened - takes normal damage - return; - - default: - damage = 0; - break; - } - } - - void DoAction(const int32 param) - { - switch(param) - { - case ACTION_FLESH_TENTACLE_KILLED: - ++FleshTentaclesKilled; - break; - } - } -}; - -struct eye_tentacleAI : public Scripted_NoMovementAI -{ - eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - } - - uint32 MindflayTimer; - uint32 KillSelfTimer; - uint64 Portal; - - void JustDied(Unit* /*who*/) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - } - - void Reset() - { - //Mind flay half a second after we spawn - MindflayTimer = 500; - - //This prevents eyes from overlapping - KillSelfTimer = 35000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //KillSelfTimer - if (KillSelfTimer <= diff) - { - me->Kill(me); - return; - } else KillSelfTimer -= diff; - - //MindflayTimer - if (MindflayTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && !pTarget->HasAura(SPELL_DIGESTIVE_ACID)) - DoCast(pTarget, SPELL_MIND_FLAY); - - //Mindflay every 10 seconds - MindflayTimer = 10000; - } else MindflayTimer -= diff; - } -}; - -struct claw_tentacleAI : public Scripted_NoMovementAI -{ - claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - - if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - } - - uint32 GroundRuptureTimer; - uint32 HamstringTimer; - uint32 EvadeTimer; - uint64 Portal; - - void JustDied(Unit* /*who*/) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - } - - void Reset() - { - //First rupture should happen half a second after we spawn - GroundRuptureTimer = 500; - HamstringTimer = 2000; - EvadeTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //EvadeTimer - if (!me->IsWithinMeleeRange(me->getVictim())) - if (EvadeTimer <= diff) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - - //Dissapear and reappear at new position - me->SetVisibility(VISIBILITY_OFF); - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget) - { - me->Kill(me); - return; - } - - if (!pTarget->HasAura(SPELL_DIGESTIVE_ACID)) - { - me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); - if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - - GroundRuptureTimer = 500; - HamstringTimer = 2000; - EvadeTimer = 5000; - AttackStart(pTarget); - } - - me->SetVisibility(VISIBILITY_ON); - } else EvadeTimer -= diff; - - //GroundRuptureTimer - if (GroundRuptureTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); - GroundRuptureTimer = 30000; - } else GroundRuptureTimer -= diff; - - //HamstringTimer - if (HamstringTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - HamstringTimer = 5000; - } else HamstringTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct giant_claw_tentacleAI : public Scripted_NoMovementAI -{ - giant_claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - - if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - } - - uint32 GroundRuptureTimer; - uint32 ThrashTimer; - uint32 HamstringTimer; - uint32 EvadeTimer; - uint64 Portal; - - void JustDied(Unit* /*who*/) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - } - - void Reset() - { - //First rupture should happen half a second after we spawn - GroundRuptureTimer = 500; - HamstringTimer = 2000; - ThrashTimer = 5000; - EvadeTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //EvadeTimer - if (!me->IsWithinMeleeRange(me->getVictim())) - if (EvadeTimer <= diff) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - - //Dissapear and reappear at new position - me->SetVisibility(VISIBILITY_OFF); - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (!pTarget) - { - me->Kill(me); - return; - } - - if (!pTarget->HasAura(SPELL_DIGESTIVE_ACID)) - { - me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); - if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - - GroundRuptureTimer = 500; - HamstringTimer = 2000; - ThrashTimer = 5000; - EvadeTimer = 5000; - AttackStart(pTarget); - } - - me->SetVisibility(VISIBILITY_ON); - - } else EvadeTimer -= diff; - - //GroundRuptureTimer - if (GroundRuptureTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); - GroundRuptureTimer = 30000; - } else GroundRuptureTimer -= diff; - - //ThrashTimer - if (ThrashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_THRASH); - ThrashTimer = 10000; - } else ThrashTimer -= diff; - - //HamstringTimer - if (HamstringTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - HamstringTimer = 10000; - } else HamstringTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct giant_eye_tentacleAI : public Scripted_NoMovementAI -{ - giant_eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - - if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - } - - uint32 BeamTimer; - uint64 Portal; - - void JustDied(Unit* /*who*/) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - } - - void Reset() - { - //Green Beam half a second after we spawn - BeamTimer = 500; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //BeamTimer - if (BeamTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && !pTarget->HasAura(SPELL_DIGESTIVE_ACID)) - DoCast(pTarget, SPELL_GREEN_BEAM); - - //Beam every 2 seconds - BeamTimer = 2100; - } else BeamTimer -= diff; - } -}; - -struct flesh_tentacleAI : public Scripted_NoMovementAI -{ - flesh_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - } - - void JustDied(Unit* /*killer*/) - { - if (CAST_SUM(me)) - if (Creature* pSummoner = CAST_CRE(CAST_SUM(me)->GetSummoner())) - if (pSummoner->AI()) - pSummoner->AI()->DoAction(ACTION_FLESH_TENTACLE_KILLED); - } -}; - -//GetAIs -CreatureAI* GetAI_eye_of_cthun(Creature* pCreature) -{ - return new eye_of_cthunAI (pCreature); -} - -CreatureAI* GetAI_cthun(Creature* pCreature) -{ - return new cthunAI (pCreature); -} - -CreatureAI* GetAI_eye_tentacle(Creature* pCreature) -{ - return new eye_tentacleAI (pCreature); -} - -CreatureAI* GetAI_claw_tentacle(Creature* pCreature) -{ - return new claw_tentacleAI (pCreature); -} - -CreatureAI* GetAI_giant_claw_tentacle(Creature* pCreature) -{ - return new giant_claw_tentacleAI (pCreature); -} - -CreatureAI* GetAI_giant_eye_tentacle(Creature* pCreature) -{ - return new giant_eye_tentacleAI (pCreature); -} - -CreatureAI* GetAI_flesh_tentacle(Creature* pCreature) -{ - return new flesh_tentacleAI (pCreature); -} - -void AddSC_boss_cthun() -{ - Script *newscript; - - //Eye - newscript = new Script; - newscript->Name = "boss_eye_of_cthun"; - newscript->GetAI = &GetAI_eye_of_cthun; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_cthun"; - newscript->GetAI = &GetAI_cthun; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_eye_tentacle"; - newscript->GetAI = &GetAI_eye_tentacle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_claw_tentacle"; - newscript->GetAI = &GetAI_claw_tentacle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_giant_claw_tentacle"; - newscript->GetAI = &GetAI_giant_claw_tentacle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_giant_eye_tentacle"; - newscript->GetAI = &GetAI_giant_eye_tentacle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_giant_flesh_tentacle"; - newscript->GetAI = &GetAI_flesh_tentacle; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp deleted file mode 100644 index 32d5ec1c3df..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Fankriss -SD%Complete: 100 -SDComment: sound not implemented -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" - -#define SOUND_SENTENCE_YOU 8588 -#define SOUND_SERVE_TO 8589 -#define SOUND_LAWS 8590 -#define SOUND_TRESPASS 8591 -#define SOUND_WILL_BE 8592 - -#define SPELL_MORTAL_WOUND 28467 -#define SPELL_ROOT 28858 - -// Enrage for his spawns -#define SPELL_ENRAGE 28798 - -struct boss_fankrissAI : public ScriptedAI -{ - boss_fankrissAI(Creature *c) : ScriptedAI(c) {} - - uint32 MortalWound_Timer; - uint32 SpawnHatchlings_Timer; - uint32 SpawnSpawns_Timer; - int Rand; - int RandX; - int RandY; - - Creature* Hatchling; - Creature* Spawn; - - void Reset() - { - MortalWound_Timer = 10000 + rand()%5000; - SpawnHatchlings_Timer = 6000 + rand()%6000; - SpawnSpawns_Timer = 15000 + rand()%30000; - } - - void SummonSpawn(Unit* victim) - { - if (!victim) - return; - - Rand = 10 + (rand()%10); - switch (rand()%2) - { - case 0: RandX = 0 - Rand; break; - case 1: RandX = 0 + Rand; break; - } - Rand = 0; - Rand = 10 + (rand()%10); - switch (rand()%2) - { - case 0: RandY = 0 - Rand; break; - case 1: RandY = 0 + Rand; break; - } - Rand = 0; - Spawn = DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - if (Spawn) - Spawn->AI()->AttackStart(victim); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //MortalWound_Timer - if (MortalWound_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - MortalWound_Timer = 10000 + rand()%10000; - } else MortalWound_Timer -= diff; - - //Summon 1-3 Spawns of Fankriss at random time. - if (SpawnSpawns_Timer <= diff) - { - switch (urand(0,2)) - { - case 0: - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - break; - case 1: - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - break; - case 2: - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - break; - } - SpawnSpawns_Timer = 30000 + rand()%30000; - } else SpawnSpawns_Timer -= diff; - - // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer. - //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot. - if (me->GetHealth()*100 / me->GetMaxHealth() > 3) - { - if (SpawnHatchlings_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, SPELL_ROOT); - - if (DoGetThreat(pTarget)) - DoModifyThreatPercent(pTarget, -100); - - switch(urand(0,2)) - { - case 0: - DoTeleportPlayer(pTarget, -8106.0142,1289.2900,-74.419533,5.112); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - break; - case 1: - DoTeleportPlayer(pTarget, -7990.135354,1155.1907,-78.849319,2.608); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - break; - case 2: - DoTeleportPlayer(pTarget,-8159.7753,1127.9064,-76.868660,0.675); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - break; - } - } - SpawnHatchlings_Timer = 45000 + rand()%15000; - } else SpawnHatchlings_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_fankriss(Creature* pCreature) -{ - return new boss_fankrissAI (pCreature); -} - -void AddSC_boss_fankriss() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_fankriss"; - newscript->GetAI = &GetAI_boss_fankriss; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp deleted file mode 100644 index f0e3a425edd..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Huhuran -SD%Complete: 100 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_GENERIC_FRENZY_KILL -1000001 -#define EMOTE_GENERIC_BERSERK -1000004 - -#define SPELL_FRENZY 26051 -#define SPELL_BERSERK 26068 -#define SPELL_POISONBOLT 26052 -#define SPELL_NOXIOUSPOISON 26053 -#define SPELL_WYVERNSTING 26180 -#define SPELL_ACIDSPIT 26050 - -struct boss_huhuranAI : public ScriptedAI -{ - boss_huhuranAI(Creature *c) : ScriptedAI(c) {} - - uint32 Frenzy_Timer; - uint32 Wyvern_Timer; - uint32 Spit_Timer; - uint32 PoisonBolt_Timer; - uint32 NoxiousPoison_Timer; - uint32 FrenzyBack_Timer; - - bool Frenzy; - bool Berserk; - - void Reset() - { - Frenzy_Timer = 25000 + rand()%10000; - Wyvern_Timer = 18000 + rand()%10000; - Spit_Timer = 8000; - PoisonBolt_Timer = 4000; - NoxiousPoison_Timer = 10000 + rand()%10000; - FrenzyBack_Timer = 15000; - - Frenzy = false; - Berserk = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frenzy_Timer - if (!Frenzy && Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); - Frenzy = true; - PoisonBolt_Timer = 3000; - Frenzy_Timer = 25000 + rand()%10000; - } else Frenzy_Timer -= diff; - - // Wyvern Timer - if (Wyvern_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_WYVERNSTING); - Wyvern_Timer = 15000 + rand()%17000; - } else Wyvern_Timer -= diff; - - //Spit Timer - if (Spit_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ACIDSPIT); - Spit_Timer = 5000 + rand()%5000; - } else Spit_Timer -= diff; - - //NoxiousPoison_Timer - if (NoxiousPoison_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSPOISON); - NoxiousPoison_Timer = 12000 + rand()%12000; - } else NoxiousPoison_Timer -= diff; - - //PoisonBolt only if frenzy or berserk - if (Frenzy || Berserk) - { - if (PoisonBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISONBOLT); - PoisonBolt_Timer = 3000; - } else PoisonBolt_Timer -= diff; - } - - //FrenzyBack_Timer - if (Frenzy && FrenzyBack_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - Frenzy = false; - FrenzyBack_Timer = 15000; - } else FrenzyBack_Timer -= diff; - - if (!Berserk && me->GetHealth()*100 / me->GetMaxHealth() < 31) - { - me->InterruptNonMeleeSpells(false); - DoScriptText(EMOTE_GENERIC_BERSERK, me); - DoCast(me, SPELL_BERSERK); - Berserk = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_huhuran(Creature* pCreature) -{ - return new boss_huhuranAI (pCreature); -} - -void AddSC_boss_huhuran() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_huhuran"; - newscript->GetAI = &GetAI_boss_huhuran; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp deleted file mode 100644 index 1dd642c38f4..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ouro -SD%Complete: 85 -SDComment: No model for submerging. Currently just invisible. -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" - -#define SPELL_SWEEP 26103 -#define SPELL_SANDBLAST 26102 -#define SPELL_GROUND_RUPTURE 26100 -#define SPELL_BIRTH 26262 //The Birth Animation - -#define SPELL_DIRTMOUND_PASSIVE 26092 - -struct boss_ouroAI : public ScriptedAI -{ - boss_ouroAI(Creature *c) : ScriptedAI(c) {} - - uint32 Sweep_Timer; - uint32 SandBlast_Timer; - uint32 Submerge_Timer; - uint32 Back_Timer; - uint32 ChangeTarget_Timer; - uint32 Spawn_Timer; - - bool Enrage; - bool Submerged; - - void Reset() - { - Sweep_Timer = 5000 + rand()%5000; - SandBlast_Timer = 20000 + rand()%15000; - Submerge_Timer = 90000 + rand()%60000; - Back_Timer = 30000 + rand()%15000; - ChangeTarget_Timer = 5000 + rand()%3000; - Spawn_Timer = 10000 + rand()%10000; - - Enrage = false; - Submerged = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoCast(me->getVictim(), SPELL_BIRTH); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sweep_Timer - if (!Submerged && Sweep_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SWEEP); - Sweep_Timer = 15000 + rand()%15000; - } else Sweep_Timer -= diff; - - //SandBlast_Timer - if (!Submerged && SandBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SANDBLAST); - SandBlast_Timer = 20000 + rand()%15000; - } else SandBlast_Timer -= diff; - - //Submerge_Timer - if (!Submerged && Submerge_Timer <= diff) - { - //Cast - me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(35); - DoCast(me, SPELL_DIRTMOUND_PASSIVE); - - Submerged = true; - Back_Timer = 30000 + rand()%15000; - } else Submerge_Timer -= diff; - - //ChangeTarget_Timer - if (Submerged && ChangeTarget_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (pTarget) - DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); - - ChangeTarget_Timer = 10000 + rand()%10000; - } else ChangeTarget_Timer -= diff; - - //Back_Timer - if (Submerged && Back_Timer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - - DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); - - Submerged = false; - Submerge_Timer = 60000 + rand()%60000; - } else Back_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ouro(Creature* pCreature) -{ - return new boss_ouroAI (pCreature); -} - -void AddSC_boss_ouro() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ouro"; - newscript->GetAI = &GetAI_boss_ouro; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp deleted file mode 100644 index 282a25b7215..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Sartura -SD%Complete: 95 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1531008 -#define SAY_SLAY -1531009 -#define SAY_DEATH -1531010 - -#define SPELL_WHIRLWIND 26083 -#define SPELL_ENRAGE 28747 //Not sure if right ID. -#define SPELL_ENRAGEHARD 28798 - -//Guard Spell -#define SPELL_WHIRLWINDADD 26038 -#define SPELL_KNOCKBACK 26027 - -struct boss_sarturaAI : public ScriptedAI -{ - boss_sarturaAI(Creature *c) : ScriptedAI(c) {} - - uint32 WhirlWind_Timer; - uint32 WhirlWindRandom_Timer; - uint32 WhirlWindEnd_Timer; - uint32 AggroReset_Timer; - uint32 AggroResetEnd_Timer; - uint32 EnrageHard_Timer; - - bool Enraged; - bool EnragedHard; - bool WhirlWind; - bool AggroReset; - - void Reset() - { - WhirlWind_Timer = 30000; - WhirlWindRandom_Timer = 3000 + rand()%4000; - WhirlWindEnd_Timer = 15000; - AggroReset_Timer = 45000 + rand()%10000; - AggroResetEnd_Timer = 5000; - EnrageHard_Timer = 10*60000; - - WhirlWind = false; - AggroReset = false; - Enraged = false; - EnragedHard = false; - - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (WhirlWind) - { - if (WhirlWindRandom_Timer <= diff) - { - //Attack random Gamers - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget) - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - - WhirlWindRandom_Timer = 3000 + rand()%4000; - } else WhirlWindRandom_Timer -= diff; - - if (WhirlWindEnd_Timer <= diff) - { - WhirlWind = false; - WhirlWind_Timer = 25000 + rand()%15000; - } else WhirlWindEnd_Timer -= diff; - } - - if (!WhirlWind) - { - if (WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - WhirlWind = true; - WhirlWindEnd_Timer = 15000; - } else WhirlWind_Timer -= diff; - - if (AggroReset_Timer <= diff) - { - //Attack random Gamers - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget) - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - - AggroReset = true; - AggroReset_Timer = 2000 + rand()%3000; - } else AggroReset_Timer -= diff; - - if (AggroReset) - { - if (AggroResetEnd_Timer <= diff) - { - AggroReset = false; - AggroResetEnd_Timer = 5000; - AggroReset_Timer = 35000 + rand()%10000; - } else AggroResetEnd_Timer -= diff; - } - - //If she is 20% enrage - if (!Enraged) - { - if (me->GetHealth()*100 / me->GetMaxHealth() <= 20 && !me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } - } - - //After 10 minutes hard enrage - if (!EnragedHard) - { - if (EnrageHard_Timer <= diff) - { - DoCast(me, SPELL_ENRAGEHARD); - EnragedHard = true; - } else EnrageHard_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - } -}; - -struct mob_sartura_royal_guardAI : public ScriptedAI -{ - mob_sartura_royal_guardAI(Creature *c) : ScriptedAI(c) {} - - uint32 WhirlWind_Timer; - uint32 WhirlWindRandom_Timer; - uint32 WhirlWindEnd_Timer; - uint32 AggroReset_Timer; - uint32 AggroResetEnd_Timer; - uint32 KnockBack_Timer; - - bool WhirlWind; - bool AggroReset; - - void Reset() - { - WhirlWind_Timer = 30000; - WhirlWindRandom_Timer = 3000 + rand()%4000; - WhirlWindEnd_Timer = 15000; - AggroReset_Timer = 45000 + rand()%10000; - AggroResetEnd_Timer = 5000; - KnockBack_Timer = 10000; - - WhirlWind = false; - AggroReset = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!WhirlWind && WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWINDADD); - WhirlWind = true; - WhirlWind_Timer = 25000 + rand()%15000; - WhirlWindEnd_Timer = 15000; - } else WhirlWind_Timer -= diff; - - if (WhirlWind) - { - if (WhirlWindRandom_Timer <= diff) - { - //Attack random Gamers - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget) - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - - WhirlWindRandom_Timer = 3000 + rand()%4000; - } else WhirlWindRandom_Timer -= diff; - - if (WhirlWindEnd_Timer <= diff) - { - WhirlWind = false; - } else WhirlWindEnd_Timer -= diff; - } - - if (!WhirlWind) - { - if (AggroReset_Timer <= diff) - { - //Attack random Gamers - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget) - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - - AggroReset = true; - AggroReset_Timer = 2000 + rand()%3000; - } else AggroReset_Timer -= diff; - - if (KnockBack_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWINDADD); - KnockBack_Timer = 10000 + rand()%10000; - } else KnockBack_Timer -= diff; - } - - if (AggroReset) - { - if (AggroResetEnd_Timer <= diff) - { - AggroReset = false; - AggroResetEnd_Timer = 5000; - AggroReset_Timer = 30000 + rand()%10000; - } else AggroResetEnd_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_sartura(Creature* pCreature) -{ - return new boss_sarturaAI (pCreature); -} - -CreatureAI* GetAI_mob_sartura_royal_guard(Creature* pCreature) -{ - return new mob_sartura_royal_guardAI (pCreature); -} - -void AddSC_boss_sartura() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_sartura"; - newscript->GetAI = &GetAI_boss_sartura; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_sartura_royal_guard"; - newscript->GetAI = &GetAI_mob_sartura_royal_guard; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp deleted file mode 100644 index 7e52bed750c..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Skeram -SD%Complete: 75 -SDComment: Mind Control buggy. -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" -#include "Group.h" - -#define SAY_AGGRO1 -1531000 -#define SAY_AGGRO2 -1531001 -#define SAY_AGGRO3 -1531002 -#define SAY_SLAY1 -1531003 -#define SAY_SLAY2 -1531004 -#define SAY_SLAY3 -1531005 -#define SAY_SPLIT -1531006 -#define SAY_DEATH -1531007 - -#define SPELL_ARCANE_EXPLOSION 25679 -#define SPELL_EARTH_SHOCK 26194 -#define SPELL_TRUE_FULFILLMENT4 26526 -#define SPELL_BLINK 28391 - -class ov_mycoordinates -{ - public: - float x,y,z,r; - ov_mycoordinates(float cx, float cy, float cz, float cr) - { - x = cx; y = cy; z = cz; r = cr; - } -}; - -struct boss_skeramAI : public ScriptedAI -{ - boss_skeramAI(Creature *c) : ScriptedAI(c) - { - IsImage = false; - } - - uint32 ArcaneExplosion_Timer; - uint32 EarthShock_Timer; - uint32 FullFillment_Timer; - uint32 Blink_Timer; - uint32 Invisible_Timer; - - bool Images75; - bool Images50; - bool Images25; - bool IsImage; - bool Invisible; - - void Reset() - { - ArcaneExplosion_Timer = 6000 + rand()%6000; - EarthShock_Timer = 2000; - FullFillment_Timer = 15000; - Blink_Timer = 8000 + rand()%12000; - Invisible_Timer = 500; - - Images75 = false; - Images50 = false; - Images25 = false; - Invisible = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - if (IsImage) - me->setDeathState(JUST_DIED); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit* /*Killer*/) - { - if (!IsImage) - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - if (IsImage || Images75) - return; - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); - ArcaneExplosion_Timer = 8000 + rand()%10000; - } else ArcaneExplosion_Timer -= diff; - - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - //Make sure our attack is ready and we arn't currently casting - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - }else - { - //EarthShock_Timer - if (EarthShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_EARTH_SHOCK); - EarthShock_Timer = 1000; - } else EarthShock_Timer -= diff; - } - - //Blink_Timer - if (Blink_Timer <= diff) - { - //DoCast(me, SPELL_BLINK); - switch (urand(0,2)) - { - case 0: - me->GetMap()->CreatureRelocation(me, -8340.782227,2083.814453,125.648788,0.0f); - DoResetThreat(); - break; - case 1: - me->GetMap()->CreatureRelocation(me, -8341.546875,2118.504639,133.058151,0.0f); - DoResetThreat(); - break; - case 2: - me->GetMap()->CreatureRelocation(me, -8318.822266,2058.231201,133.058151,0.0f); - DoResetThreat(); - break; - } - DoStopAttack(); - - Blink_Timer= 20000 + rand()%20000; - } else Blink_Timer -= diff; - - int procent = (int) (me->GetHealth()*100 / me->GetMaxHealth() +0.5); - - //Summoning 2 Images and teleporting to a random position on 75% health - if ((!Images75 && !IsImage) && (procent <= 75 && procent > 70)) - DoSplit(75); - - //Summoning 2 Images and teleporting to a random position on 50% health - if ((!Images50 && !IsImage) && - (procent <= 50 && procent > 45)) - DoSplit(50); - - //Summoning 2 Images and teleporting to a random position on 25% health - if ((!Images25 && !IsImage) && (procent <= 25 && procent > 20)) - DoSplit(25); - - //Invisible_Timer - if (Invisible) - { - if (Invisible_Timer <= diff) - { - //Making Skeram visible after telporting - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - Invisible_Timer = 2500; - Invisible = false; - } else Invisible_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void DoSplit(int atPercent /* 75 50 25 */) - { - DoScriptText(SAY_SPLIT, me); - - ov_mycoordinates *place1 = new ov_mycoordinates(-8340.782227,2083.814453,125.648788,0); - ov_mycoordinates *place2 = new ov_mycoordinates(-8341.546875,2118.504639,133.058151,0); - ov_mycoordinates *place3 = new ov_mycoordinates(-8318.822266,2058.231201,133.058151,0); - - ov_mycoordinates *bossc=place1, *i1=place2, *i2=place3; - - switch (urand(0,2)) - { - case 0: - bossc=place1; - i1=place2; - i2=place3; - break; - case 1: - bossc=place2; - i1=place1; - i2=place3; - break; - case 2: - bossc=place3; - i1=place1; - i2=place2; - break; - } - - for (uint16 i = 0; i < 41; ++i) - { - if (Player *pTarget = CAST_PLR(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))) - { - if (Group *pGrp = pTarget->GetGroup()) - for (uint8 ico = 0; ico < TARGETICONCOUNT; ++ico) - { - //if (grp->m_targetIcons[ico] == me->GetGUID()) -- private member :( - pGrp->SetTargetIcon(ico, 0, 0); - } - - break; - } - } - - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_OFF); - me->GetMap()->CreatureRelocation(me, bossc->x, bossc->y, bossc->z, bossc->r); - Invisible = true; - delete place1; - delete place2; - delete place3; - DoResetThreat(); - DoStopAttack(); - - switch (atPercent) - { - case 75: Images75 = true; break; - case 50: Images50 = true; break; - case 25: Images25 = true; break; - } - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - Creature *Image1 = me->SummonCreature(15263, i1->x, i1->y, i1->z, i1->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); - if (Image1) - { - Image1->SetMaxHealth(me->GetMaxHealth() / 5); - Image1->SetHealth(me->GetHealth() / 5); - if (pTarget) - Image1->AI()->AttackStart(pTarget); - CAST_AI(boss_skeramAI, Image1->AI())->IsImage = true; - } - - Creature *Image2 = me->SummonCreature(15263,i2->x, i2->y, i2->z, i2->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); - if (Image2) - { - Image2->SetMaxHealth(me->GetMaxHealth() / 5); - Image2->SetHealth(me->GetHealth() / 5); - if (pTarget) - Image2->AI()->AttackStart(pTarget); - CAST_AI(boss_skeramAI, Image2->AI())->IsImage = true; - } - Invisible = true; - } - -}; - -CreatureAI* GetAI_boss_skeram(Creature* pCreature) -{ - return new boss_skeramAI (pCreature); -} - -void AddSC_boss_skeram() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_skeram"; - newscript->GetAI = &GetAI_boss_skeram; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp deleted file mode 100644 index 73f17485f7f..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp +++ /dev/null @@ -1,596 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Twinemperors -SD%Complete: 95 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" -#include "WorldPacket.h" - -#include "Item.h" -#include "Spell.h" - -#define SPELL_HEAL_BROTHER 7393 -#define SPELL_TWIN_TELEPORT 800 // CTRA watches for this spell to start its teleport timer -#define SPELL_TWIN_TELEPORT_VISUAL 26638 // visual - -#define SPELL_EXPLODEBUG 804 -#define SPELL_MUTATE_BUG 802 - -#define SOUND_VN_DEATH 8660 //8660 - Death - Feel -#define SOUND_VN_AGGRO 8661 //8661 - Aggro - Let none -#define SOUND_VN_KILL 8662 //8661 - Kill - your fate - -#define SOUND_VL_AGGRO 8657 //8657 - Aggro - To Late -#define SOUND_VL_KILL 8658 //8658 - Kill - You will not -#define SOUND_VL_DEATH 8659 //8659 - Death - -#define PULL_RANGE 50 -#define ABUSE_BUG_RANGE 20 -#define SPELL_BERSERK 26662 -#define TELEPORTTIME 30000 - -#define SPELL_UPPERCUT 26007 -#define SPELL_UNBALANCING_STRIKE 26613 - -#define VEKLOR_DIST 20 // VL will not come to melee when attacking - -#define SPELL_SHADOWBOLT 26006 -#define SPELL_BLIZZARD 26607 -#define SPELL_ARCANEBURST 568 - -struct boss_twinemperorsAI : public ScriptedAI -{ - boss_twinemperorsAI(Creature *c): ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Heal_Timer; - uint32 Teleport_Timer; - bool AfterTeleport; - uint32 AfterTeleportTimer; - bool DontYellWhenDead; - uint32 Abuse_Bug_Timer, BugsTimer; - bool tspellcasted; - uint32 EnrageTimer; - - virtual bool IAmVeklor() = 0; - virtual void Reset() = 0; - virtual void CastSpellOnBug(Creature *pTarget) = 0; - - void TwinReset() - { - Heal_Timer = 0; // first heal immediately when they get close together - Teleport_Timer = TELEPORTTIME; - AfterTeleport = false; - tspellcasted = false; - AfterTeleportTimer = 0; - Abuse_Bug_Timer = 10000 + rand()%7000; - BugsTimer = 2000; - me->clearUnitState(UNIT_STAT_STUNNED); - DontYellWhenDead = false; - EnrageTimer = 15*60000; - } - - Creature *GetOtherBoss() - { - if (pInstance) - return Unit::GetCreature(*me, pInstance->GetData64(IAmVeklor() ? DATA_VEKNILASH : DATA_VEKLOR)); - else - return NULL; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - Unit *pOtherBoss = GetOtherBoss(); - if (pOtherBoss) - { - float dPercent = ((float)damage) / ((float)me->GetMaxHealth()); - int odmg = (int)(dPercent * ((float)pOtherBoss->GetMaxHealth())); - int ohealth = pOtherBoss->GetHealth()-odmg; - pOtherBoss->SetHealth(ohealth > 0 ? ohealth : 0); - if (ohealth <= 0) - { - pOtherBoss->setDeathState(JUST_DIED); - pOtherBoss->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - } - } - - void JustDied(Unit* /*Killer*/) - { - Creature *pOtherBoss = GetOtherBoss(); - if (pOtherBoss) - { - pOtherBoss->SetHealth(0); - pOtherBoss->setDeathState(JUST_DIED); - pOtherBoss->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - CAST_AI(boss_twinemperorsAI, pOtherBoss->AI())->DontYellWhenDead = true; - } - if (!DontYellWhenDead) // I hope AI is not threaded - DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_DEATH : SOUND_VN_DEATH); - } - - void KilledUnit(Unit* /*victim*/) - { - DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_KILL : SOUND_VN_KILL); - } - - void EnterCombat(Unit * who) - { - DoZoneInCombat(); - Creature *pOtherBoss = GetOtherBoss(); - if (pOtherBoss) - { - // TODO: we should activate the other boss location so he can start attackning even if nobody - // is near I dont know how to do that - ScriptedAI *otherAI = CAST_AI(ScriptedAI, pOtherBoss->AI()); - if (!pOtherBoss->isInCombat()) - { - DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_AGGRO : SOUND_VN_AGGRO); - otherAI->AttackStart(who); - otherAI->DoZoneInCombat(); - } - } - } - - void SpellHit(Unit *caster, const SpellEntry *entry) - { - if (caster == me) - return; - - Creature *pOtherBoss = GetOtherBoss(); - if (entry->Id != SPELL_HEAL_BROTHER || !pOtherBoss) - return; - - // add health so we keep same percentage for both brothers - uint32 mytotal = me->GetMaxHealth(), histotal = pOtherBoss->GetMaxHealth(); - float mult = ((float)mytotal) / ((float)histotal); - if (mult < 1) - mult = 1.0f/mult; - #define HEAL_BROTHER_AMOUNT 30000.0f - uint32 largerAmount = (uint32)((HEAL_BROTHER_AMOUNT * mult) - HEAL_BROTHER_AMOUNT); - - if (mytotal > histotal) - { - uint32 h = me->GetHealth()+largerAmount; - me->SetHealth(std::min(mytotal, h)); - } - else - { - uint32 h = pOtherBoss->GetHealth()+largerAmount; - pOtherBoss->SetHealth(std::min(histotal, h)); - } - } - - void TryHealBrother(uint32 diff) - { - if (IAmVeklor()) // this spell heals caster and the other brother so let VN cast it - return; - - if (Heal_Timer <= diff) - { - Unit *pOtherBoss = GetOtherBoss(); - if (pOtherBoss && pOtherBoss->IsWithinDist(me,60)) - { - DoCast(pOtherBoss, SPELL_HEAL_BROTHER); - Heal_Timer = 1000; - } - } else Heal_Timer -= diff; - } - - void TeleportToMyBrother() - { - if (!pInstance) - return; - - Teleport_Timer = TELEPORTTIME; - - if (IAmVeklor()) - return; // mechanics handled by veknilash so they teleport exactly at the same time and to correct coordinates - - Creature *pOtherBoss = GetOtherBoss(); - if (pOtherBoss) - { - //me->MonsterYell("Teleporting ...", LANG_UNIVERSAL, 0); - float other_x = pOtherBoss->GetPositionX(); - float other_y = pOtherBoss->GetPositionY(); - float other_z = pOtherBoss->GetPositionZ(); - float other_o = pOtherBoss->GetOrientation(); - - Map *thismap = me->GetMap(); - thismap->CreatureRelocation(pOtherBoss, me->GetPositionX(), - me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); - thismap->CreatureRelocation(me, other_x, other_y, other_z, other_o); - - SetAfterTeleport(); - CAST_AI(boss_twinemperorsAI, pOtherBoss->AI())->SetAfterTeleport(); - } - } - - void SetAfterTeleport() - { - me->InterruptNonMeleeSpells(false); - DoStopAttack(); - DoResetThreat(); - DoCast(me, SPELL_TWIN_TELEPORT_VISUAL); - me->addUnitState(UNIT_STAT_STUNNED); - AfterTeleport = true; - AfterTeleportTimer = 2000; - tspellcasted = false; - } - - bool TryActivateAfterTTelep(uint32 diff) - { - if (AfterTeleport) - { - if (!tspellcasted) - { - me->clearUnitState(UNIT_STAT_STUNNED); - DoCast(me, SPELL_TWIN_TELEPORT); - me->addUnitState(UNIT_STAT_STUNNED); - } - - tspellcasted = true; - - if (AfterTeleportTimer <= diff) - { - AfterTeleport = false; - me->clearUnitState(UNIT_STAT_STUNNED); - if (Unit *nearu = me->SelectNearestTarget(100)) - { - //DoYell(nearu->GetName(), LANG_UNIVERSAL, 0); - AttackStart(nearu); - me->AddThreat(nearu, 10000); - } - return true; - } - else - { - AfterTeleportTimer -= diff; - // update important timers which would otherwise get skipped - if (EnrageTimer > diff) - EnrageTimer -= diff; - else - EnrageTimer = 0; - if (Teleport_Timer > diff) - Teleport_Timer -= diff; - else - Teleport_Timer = 0; - return false; - } - } - else - { - return true; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - float attackRadius = me->GetAttackDistance(who); - if (attackRadius < PULL_RANGE) - attackRadius = PULL_RANGE; - if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= /*CREATURE_Z_ATTACK_RANGE*/7 /*there are stairs*/) - { - //if (who->HasStealthAura()) - // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - } - } - - Creature *RespawnNearbyBugsAndGetOne() - { - std::list lUnitList; - me->GetCreatureListWithEntryInGrid(lUnitList,15316,150.0f); - me->GetCreatureListWithEntryInGrid(lUnitList,15317,150.0f); - - if (lUnitList.empty()) - return NULL; - - Creature *nearb = NULL; - - for (std::list::const_iterator iter = lUnitList.begin(); iter != lUnitList.end(); ++iter) - { - Creature *c = *iter; - if (c) - { - if (c->isDead()) - { - c->Respawn(); - c->setFaction(7); - c->RemoveAllAuras(); - } - if (c->IsWithinDistInMap(me, ABUSE_BUG_RANGE)) - { - if (!nearb || (rand()%4) == 0) - nearb = c; - } - } - } - return nearb; - } - - void HandleBugs(uint32 diff) - { - if (BugsTimer < diff || Abuse_Bug_Timer <= diff) - { - Creature *c = RespawnNearbyBugsAndGetOne(); - if (Abuse_Bug_Timer <= diff) - { - if (c) - { - CastSpellOnBug(c); - Abuse_Bug_Timer = 10000 + rand()%7000; - } - else - { - Abuse_Bug_Timer = 1000; - } - } - else - { - Abuse_Bug_Timer -= diff; - } - BugsTimer = 2000; - } - else - { - BugsTimer -= diff; - Abuse_Bug_Timer -= diff; - } - } - - void CheckEnrage(uint32 diff) - { - if (EnrageTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(true)) - { - DoCast(me, SPELL_BERSERK); - EnrageTimer = 60*60000; - } else EnrageTimer = 0; - } else EnrageTimer-=diff; - } -}; - -struct boss_veknilashAI : public boss_twinemperorsAI -{ - bool IAmVeklor() {return false;} - boss_veknilashAI(Creature *c) : boss_twinemperorsAI(c) {} - - uint32 UpperCut_Timer; - uint32 UnbalancingStrike_Timer; - uint32 Scarabs_Timer; - int Rand; - int RandX; - int RandY; - - Creature* Summoned; - - void Reset() - { - TwinReset(); - UpperCut_Timer = 14000 + rand()%15000; - UnbalancingStrike_Timer = 8000 + rand()%10000; - Scarabs_Timer = 7000 + rand()%7000; - - //Added. Can be removed if its included in DB. - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - } - - void CastSpellOnBug(Creature *pTarget) - { - pTarget->setFaction(14); - pTarget->AI()->AttackStart(me->getThreatManager().getHostilTarget()); - pTarget->AddAura(SPELL_MUTATE_BUG, pTarget); - pTarget->SetHealth(pTarget->GetMaxHealth()); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!TryActivateAfterTTelep(diff)) - return; - - //UnbalancingStrike_Timer - if (UnbalancingStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE); - UnbalancingStrike_Timer = 8000+rand()%12000; - } else UnbalancingStrike_Timer -= diff; - - if (UpperCut_Timer <= diff) - { - Unit* randomMelee = SelectTarget(SELECT_TARGET_RANDOM, 0, NOMINAL_MELEE_RANGE, true); - if (randomMelee) - DoCast(randomMelee, SPELL_UPPERCUT); - UpperCut_Timer = 15000+rand()%15000; - } else UpperCut_Timer -= diff; - - HandleBugs(diff); - - //Heal brother when 60yrds close - TryHealBrother(diff); - - //Teleporting to brother - if (Teleport_Timer <= diff) - { - TeleportToMyBrother(); - } else Teleport_Timer -= diff; - - CheckEnrage(diff); - - DoMeleeAttackIfReady(); - } -}; - -struct boss_veklorAI : public boss_twinemperorsAI -{ - bool IAmVeklor() {return true;} - boss_veklorAI(Creature *c) : boss_twinemperorsAI(c) {} - - uint32 ShadowBolt_Timer; - uint32 Blizzard_Timer; - uint32 ArcaneBurst_Timer; - uint32 Scorpions_Timer; - int Rand; - int RandX; - int RandY; - - Creature* Summoned; - - void Reset() - { - TwinReset(); - ShadowBolt_Timer = 0; - Blizzard_Timer = 15000 + rand()%5000; - ArcaneBurst_Timer = 1000; - Scorpions_Timer = 7000 + rand()%7000; - - //Added. Can be removed if its included in DB. - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0); - } - - void CastSpellOnBug(Creature *pTarget) - { - pTarget->setFaction(14); - pTarget->AddAura(SPELL_EXPLODEBUG, pTarget); - pTarget->SetHealth(pTarget->GetMaxHealth()); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // reset arcane burst after teleport - we need to do this because - // when VL jumps to VN's location there will be a warrior who will get only 2s to run away - // which is almost impossible - if (AfterTeleport) - ArcaneBurst_Timer = 5000; - if (!TryActivateAfterTTelep(diff)) - return; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - if (!me->IsWithinDist(me->getVictim(), 45.0f)) - me->GetMotionMaster()->MoveChase(me->getVictim(), VEKLOR_DIST, 0); - else - DoCast(me->getVictim(), SPELL_SHADOWBOLT); - ShadowBolt_Timer = 2000; - } else ShadowBolt_Timer -= diff; - - //Blizzard_Timer - if (Blizzard_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45, true); - if (pTarget) - DoCast(pTarget, SPELL_BLIZZARD); - Blizzard_Timer = 15000+rand()%15000; - } else Blizzard_Timer -= diff; - - if (ArcaneBurst_Timer <= diff) - { - Unit *mvic; - if ((mvic=SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) != NULL) - { - DoCast(mvic, SPELL_ARCANEBURST); - ArcaneBurst_Timer = 5000; - } - } else ArcaneBurst_Timer -= diff; - - HandleBugs(diff); - - //Heal brother when 60yrds close - TryHealBrother(diff); - - //Teleporting to brother - if (Teleport_Timer <= diff) - { - TeleportToMyBrother(); - } else Teleport_Timer -= diff; - - CheckEnrage(diff); - - //VL doesn't melee - //DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack()) - { - // VL doesn't melee - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); - me->AddThreat(who, 0.0f); - } - } - } -}; - -CreatureAI* GetAI_boss_veknilash(Creature* pCreature) -{ - return new boss_veknilashAI (pCreature); -} - -CreatureAI* GetAI_boss_veklor(Creature* pCreature) -{ - return new boss_veklorAI (pCreature); -} - -void AddSC_boss_twinemperors() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_veknilash"; - newscript->GetAI = &GetAI_boss_veknilash; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_veklor"; - newscript->GetAI = &GetAI_boss_veklor; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp deleted file mode 100644 index f5e71a35bae..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Viscidus -SD%Complete: 0 -SDComment: place holder -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_POISON_SHOCK 25993 -#define SPELL_POISONBOLT_VOLLEY 25991 - -#define SPELL_TOXIN_CLOUD 25989 - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp deleted file mode 100644 index 1125a0c8623..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Temple_of_Ahnqiraj -SD%Complete: 80 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" - -struct instance_temple_of_ahnqiraj : public ScriptedInstance -{ - instance_temple_of_ahnqiraj(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - //If Vem is dead... - bool IsBossDied[3]; - - //Storing Skeram, Vem and Kri. - uint64 SkeramGUID; - uint64 VemGUID; - uint64 KriGUID; - uint64 VeklorGUID; - uint64 VeknilashGUID; - - uint32 BugTrioDeathCount; - - uint32 CthunPhase; - - void Initialize() - { - IsBossDied[0] = false; - IsBossDied[1] = false; - IsBossDied[2] = false; - - SkeramGUID = 0; - VemGUID = 0; - KriGUID = 0; - VeklorGUID = 0; - VeknilashGUID = 0; - - BugTrioDeathCount = 0; - - CthunPhase = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case 15263: SkeramGUID = pCreature->GetGUID(); break; - case 15544: VemGUID = pCreature->GetGUID(); break; - case 15511: KriGUID = pCreature->GetGUID(); break; - case 15276: VeklorGUID = pCreature->GetGUID(); break; - case 15275: VeknilashGUID = pCreature->GetGUID(); break; - } - } - - bool IsEncounterInProgress() const - { - //not active in AQ40 - return false; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_VEMISDEAD: - if (IsBossDied[0]) - return 1; - break; - - case DATA_VEKLORISDEAD: - if (IsBossDied[1]) - return 1; - break; - - case DATA_VEKNILASHISDEAD: - if (IsBossDied[2]) - return 1; - break; - - case DATA_BUG_TRIO_DEATH: - return BugTrioDeathCount; - - case DATA_CTHUN_PHASE: - return CthunPhase; - } - return 0; - } - - uint64 GetData64 (uint32 identifier) - { - switch(identifier) - { - case DATA_SKERAM: - return SkeramGUID; - case DATA_VEM: - return VemGUID; - case DATA_KRI: - return KriGUID; - case DATA_VEKLOR: - return VeklorGUID; - case DATA_VEKNILASH: - return VeknilashGUID; - } - return 0; - } // end GetData64 - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_VEM_DEATH: - IsBossDied[0] = true; - break; - - case DATA_BUG_TRIO_DEATH: - ++BugTrioDeathCount; - break; - - case DATA_VEKLOR_DEATH: - IsBossDied[1] = true; - break; - - case DATA_VEKNILASH_DEATH: - IsBossDied[2] = true; - break; - - case DATA_CTHUN_PHASE: - CthunPhase = data; - break; - } - } -}; - -InstanceData* GetInstanceData_instance_temple_of_ahnqiraj(Map* pMap) -{ - return new instance_temple_of_ahnqiraj(pMap); -} - -void AddSC_instance_temple_of_ahnqiraj() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_temple_of_ahnqiraj"; - newscript->GetInstanceData = &GetInstanceData_instance_temple_of_ahnqiraj; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp b/src/server/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp deleted file mode 100644 index 074f9ed68ae..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: mob_anubisath_sentinel -SD%Complete: 95 -SDComment: Shadow storm is not properly implemented in core it should only pTarget ppl outside of melee range. -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "WorldPacket.h" - -#include "Item.h" -#include "Player.h" -#include "Spell.h" - -#include "Cell.h" -#include "CellImpl.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" - -#define SPELL_MENDING_BUFF 2147 - -#define SPELL_KNOCK_BUFF 21737 -#define SPELL_KNOCK 25778 -#define SPELL_MANAB_BUFF 812 -#define SPELL_MANAB 25779 - -#define SPELL_REFLECTAF_BUFF 13022 -#define SPELL_REFLECTSFr_BUFF 19595 -#define SPELL_THORNS_BUFF 25777 - -#define SPELL_THUNDER_BUFF 2834 -#define SPELL_THUNDER 8732 - -#define SPELL_MSTRIKE_BUFF 9347 -#define SPELL_MSTRIKE 24573 - -#define SPELL_STORM_BUFF 2148 -#define SPELL_STORM 26546 - -struct aqsentinelAI : public ScriptedAI -{ - uint32 ability; - int abselected; - - void selectAbility(int asel) - { - switch (asel) - { - case 0: ability = SPELL_MENDING_BUFF;break; - case 1: ability = SPELL_KNOCK_BUFF;break; - case 2: ability = SPELL_MANAB_BUFF;break; - case 3: ability = SPELL_REFLECTAF_BUFF;break; - case 4: ability = SPELL_REFLECTSFr_BUFF;break; - case 5: ability = SPELL_THORNS_BUFF;break; - case 6: ability = SPELL_THUNDER_BUFF;break; - case 7: ability = SPELL_MSTRIKE_BUFF;break; - case 8: ability = SPELL_STORM_BUFF;break; - } - } - - aqsentinelAI(Creature *c) : ScriptedAI(c) - { - ClearBuddyList(); - abselected = 0; // just initialization of variable - } - - uint64 NearbyGUID[3]; - - void ClearBuddyList() - { - NearbyGUID[0] = NearbyGUID[1] = NearbyGUID[2] = 0; - } - - void AddBuddyToList(uint64 CreatureGUID) - { - if (CreatureGUID == me->GetGUID()) - return; - - for (int i=0; i<3; ++i) - { - if (NearbyGUID[i] == CreatureGUID) - return; - if (!NearbyGUID[i]) - { - NearbyGUID[i] = CreatureGUID; - return; - } - } - } - - void GiveBuddyMyList(Creature *c) - { - aqsentinelAI *cai = CAST_AI(aqsentinelAI, (c)->AI()); - for (int i=0; i<3; ++i) - if (NearbyGUID[i] && NearbyGUID[i] != c->GetGUID()) - cai->AddBuddyToList(NearbyGUID[i]); - cai->AddBuddyToList(me->GetGUID()); - } - - void SendMyListToBuddies() - { - for (int i=0; i<3; ++i) - if (Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[i])) - GiveBuddyMyList(pNearby); - } - - void CallBuddiesToAttack(Unit *who) - { - for (int i=0; i<3; ++i) - { - Creature *c = Unit::GetCreature(*me, NearbyGUID[i]); - if (c) - { - if (!c->isInCombat()) - { - c->SetNoCallAssistance(true); - if (c->AI()) - c->AI()->AttackStart(who); - } - } - } - } - - void AddSentinelsNear(Unit * /*nears*/) - { - std::list assistList; - me->GetCreatureListWithEntryInGrid(assistList,15264,70.0f); - - if (assistList.empty()) - return; - - for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) - AddBuddyToList((*iter)->GetGUID()); - } - - int pickAbilityRandom(bool *chosenAbilities) - { - for (int t = 0; t < 2; ++t) - { - for (int i = !t ? (rand()%9) : 0; i < 9; ++i) - { - if (!chosenAbilities[i]) - { - chosenAbilities[i] = true; - return i; - } - } - } - return 0; // should never happen - } - - void GetOtherSentinels(Unit *who) - { - bool *chosenAbilities = new bool[9]; - memset(chosenAbilities, 0, 9*sizeof(bool)); - selectAbility(pickAbilityRandom(chosenAbilities)); - - ClearBuddyList(); - AddSentinelsNear(me); - int bli; - for (bli = 0; bli < 3; ++bli) - { - if (!NearbyGUID[bli]) - break; - - Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[bli]); - if (!pNearby) - break; - - AddSentinelsNear(pNearby); - CAST_AI(aqsentinelAI, pNearby->AI())->gatherOthersWhenAggro = false; - CAST_AI(aqsentinelAI, pNearby->AI())->selectAbility(pickAbilityRandom(chosenAbilities)); - } - /*if (bli < 3) - DoYell("I dont have enough buddies.", LANG_NEUTRAL, 0);*/ - SendMyListToBuddies(); - CallBuddiesToAttack(who); - - delete[] chosenAbilities; - } - - bool gatherOthersWhenAggro; - - void Reset() - { - if (!me->isDead()) - { - for (int i=0; i<3; ++i) - { - if (!NearbyGUID[i]) - continue; - if (Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[i])) - { - if (pNearby->isDead()) - pNearby->Respawn(); - } - } - } - ClearBuddyList(); - gatherOthersWhenAggro = true; - } - - void GainSentinelAbility(uint32 id) - { - me->AddAura(id, me); - } - - void EnterCombat(Unit * who) - { - if (gatherOthersWhenAggro) - GetOtherSentinels(who); - - GainSentinelAbility(ability); - DoZoneInCombat(); - } - - void JustDied(Unit* /*who*/) - { - for (int ni=0; ni<3; ++ni) - { - Creature *sent = Unit::GetCreature(*me, NearbyGUID[ni]); - if (!sent) - continue; - if (sent->isDead()) - continue; - int h = sent->GetHealth() + (sent->GetMaxHealth() / 2); - if (h > sent->GetMaxHealth()) - h = sent->GetMaxHealth(); - sent->SetHealth(h); - CAST_AI(aqsentinelAI, sent->AI())->GainSentinelAbility(ability); - } - } - - Unit *GetHatedManaUser() const - { - std::list::const_iterator i; - for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit->getPowerType() == POWER_MANA) - return pUnit; - } - return NULL; - } - - Unit* GetAuraEffectTriggerTarget(uint32 spellId, uint8 /*effIndex*/) const - { - switch (spellId) - { - case SPELL_KNOCK_BUFF: - case SPELL_THUNDER_BUFF: - case SPELL_MSTRIKE_BUFF: - case SPELL_STORM_BUFF: - return me->getVictim(); - - case SPELL_MANAB_BUFF: - return GetHatedManaUser(); - - case SPELL_MENDING_BUFF: - case SPELL_REFLECTAF_BUFF: - case SPELL_REFLECTSFr_BUFF: - case SPELL_THORNS_BUFF: - default: - return me; - } - } -}; -CreatureAI* GetAI_mob_anubisath_sentinelAI(Creature* pCreature) -{ - return new aqsentinelAI (pCreature); -} - -void AddSC_mob_anubisath_sentinel() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_anubisath_sentinel"; - newscript->GetAI = &GetAI_mob_anubisath_sentinelAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h b/src/server/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h deleted file mode 100644 index 5d545ed7c74..00000000000 --- a/src/server/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_TEMPLE_OF_AHNQIRAJ_H -#define DEF_TEMPLE_OF_AHNQIRAJ_H - -#define DATA_SKERAM 1 -#define DATA_KRI 2 -#define DATA_VEM 3 -#define DATA_VEMISDEAD 4 -#define DATA_VEM_DEATH 5 -#define DATA_VEKLOR 6 -#define DATA_VEKLORISDEAD 7 -#define DATA_VEKLOR_DEATH 8 -#define DATA_VEKNILASH 9 -#define DATA_VEKNILASHISDEAD 10 -#define DATA_VEKNILASH_DEATH 11 -#define DATA_BUG_TRIO_DEATH 14 - -#define DATA_CTHUN_PHASE 20 -#endif - diff --git a/src/server/scripts/kalimdor/the_barrens.cpp b/src/server/scripts/kalimdor/the_barrens.cpp deleted file mode 100644 index 04daac96877..00000000000 --- a/src/server/scripts/kalimdor/the_barrens.cpp +++ /dev/null @@ -1,701 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: The_Barrens -SD%Complete: 90 -SDComment: Quest support: 863, 898, 1719, 2458, 4921, 6981, -SDCategory: Barrens -EndScriptData */ - -/* ContentData -npc_beaten_corpse -npc_gilthares -npc_sputtervalve -npc_taskmaster_fizzule -npc_twiggy_flathead -npc_wizzlecrank_shredder -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_beaten_corpse -######*/ - -#define GOSSIP_CORPSE "Examine corpse in detail..." - -enum eQuests -{ - QUEST_LOST_IN_BATTLE = 4921 -}; - -bool GossipHello_npc_beaten_corpse(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CORPSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(3557, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_beaten_corpse(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF +1) - { - pPlayer->SEND_GOSSIP_MENU(3558, pCreature->GetGUID()); - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - } - return true; -} - -/*###### -# npc_gilthares -######*/ - -enum eGilthares -{ - SAY_GIL_START = -1000370, - SAY_GIL_AT_LAST = -1000371, - SAY_GIL_PROCEED = -1000372, - SAY_GIL_FREEBOOTERS = -1000373, - SAY_GIL_AGGRO_1 = -1000374, - SAY_GIL_AGGRO_2 = -1000375, - SAY_GIL_AGGRO_3 = -1000376, - SAY_GIL_AGGRO_4 = -1000377, - SAY_GIL_ALMOST = -1000378, - SAY_GIL_SWEET = -1000379, - SAY_GIL_FREED = -1000380, - - QUEST_FREE_FROM_HOLD = 898, - AREA_MERCHANT_COAST = 391, - FACTION_ESCORTEE = 232 //guessed, possible not needed for this quest -}; - -struct npc_giltharesAI : public npc_escortAI -{ - npc_giltharesAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void Reset() { } - - void WaypointReached(uint32 uiPointId) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(uiPointId) - { - case 16: - DoScriptText(SAY_GIL_AT_LAST, me, pPlayer); - break; - case 17: - DoScriptText(SAY_GIL_PROCEED, me, pPlayer); - break; - case 18: - DoScriptText(SAY_GIL_FREEBOOTERS, me, pPlayer); - break; - case 37: - DoScriptText(SAY_GIL_ALMOST, me, pPlayer); - break; - case 47: - DoScriptText(SAY_GIL_SWEET, me, pPlayer); - break; - case 53: - DoScriptText(SAY_GIL_FREED, me, pPlayer); - pPlayer->GroupEventHappens(QUEST_FREE_FROM_HOLD, me); - break; - } - } - - void Aggro(Unit* pWho) - { - //not always use - if (rand()%4) - return; - - //only aggro text if not player and only in this area - if (pWho->GetTypeId() != TYPEID_PLAYER && me->GetAreaId() == AREA_MERCHANT_COAST) - { - //appears to be pretty much random (possible only if escorter not in combat with pWho yet?) - DoScriptText(RAND(SAY_GIL_AGGRO_1, SAY_GIL_AGGRO_2, SAY_GIL_AGGRO_3, SAY_GIL_AGGRO_4), me, pWho); - } - } -}; - -CreatureAI* GetAI_npc_gilthares(Creature* pCreature) -{ - return new npc_giltharesAI(pCreature); -} - -bool QuestAccept_npc_gilthares(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_FREE_FROM_HOLD) - { - pCreature->setFaction(FACTION_ESCORTEE); - pCreature->SetStandState(UNIT_STAND_STATE_STAND); - - DoScriptText(SAY_GIL_START, pCreature, pPlayer); - - if (npc_giltharesAI* pEscortAI = CAST_AI(npc_giltharesAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); - } - return true; -} - -/*###### -## npc_sputtervalve -######*/ - -#define GOSSIP_SPUTTERVALVE "Can you tell me about this shard?" - -bool GossipHello_npc_sputtervalve(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(6981) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SPUTTERVALVE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_sputtervalve(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->SEND_GOSSIP_MENU(2013, pCreature->GetGUID()); - pPlayer->AreaExploredOrEventHappens(6981); - } - return true; -} - -/*###### -## npc_taskmaster_fizzule -######*/ - -enum eEnums -{ - FACTION_FRIENDLY_F = 35, - SPELL_FLARE = 10113, - SPELL_FOLLY = 10137, -}; - -struct npc_taskmaster_fizzuleAI : public ScriptedAI -{ - npc_taskmaster_fizzuleAI(Creature* c) : ScriptedAI(c) - { - factionNorm = c->getFaction(); - } - - uint32 factionNorm; - bool IsFriend; - uint32 Reset_Timer; - uint8 FlareCount; - - void Reset() - { - IsFriend = false; - Reset_Timer = 120000; - FlareCount = 0; - me->setFaction(factionNorm); - } - - void DoFriend() - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - - me->StopMoving(); - me->GetMotionMaster()->MoveIdle(); - - me->setFaction(FACTION_FRIENDLY_F); - me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_FLARE || spell->Id == SPELL_FOLLY) - { - ++FlareCount; - - if (FlareCount >= 2) - IsFriend = true; - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (IsFriend) - { - if (Reset_Timer <= diff) - { - EnterEvadeMode(); - return; - } else Reset_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void ReceiveEmote(Player* /*pPlayer*/, uint32 emote) - { - if (emote == TEXTEMOTE_SALUTE) - { - if (FlareCount >= 2) - { - if (me->getFaction() == FACTION_FRIENDLY_F) - return; - - DoFriend(); - } - } - } -}; - -CreatureAI* GetAI_npc_taskmaster_fizzule(Creature* pCreature) -{ - return new npc_taskmaster_fizzuleAI(pCreature); -} - -/*##### -## npc_twiggy_flathead -#####*/ - -enum eTwiggyFlathead -{ - NPC_BIG_WILL = 6238, - NPC_AFFRAY_CHALLENGER = 6240, - - SAY_BIG_WILL_READY = -1000123, - SAY_TWIGGY_FLATHEAD_BEGIN = -1000124, - SAY_TWIGGY_FLATHEAD_FRAY = -1000125, - SAY_TWIGGY_FLATHEAD_DOWN = -1000126, - SAY_TWIGGY_FLATHEAD_OVER = -1000127, -}; - -float AffrayChallengerLoc[6][4]= -{ - {-1683, -4326, 2.79, 0}, - {-1682, -4329, 2.79, 0}, - {-1683, -4330, 2.79, 0}, - {-1680, -4334, 2.79, 1.49}, - {-1674, -4326, 2.79, 3.49}, - {-1677, -4334, 2.79, 1.66} -}; - -struct npc_twiggy_flatheadAI : public ScriptedAI -{ - npc_twiggy_flatheadAI(Creature *c) : ScriptedAI(c) {} - - bool EventInProgress; - bool EventGrate; - bool EventBigWill; - bool Challenger_down[6]; - uint32 Wave; - uint32 Wave_Timer; - uint32 Challenger_checker; - uint64 PlayerGUID; - uint64 AffrayChallenger[6]; - uint64 BigWill; - - void Reset() - { - EventInProgress = false; - EventGrate = false; - EventBigWill = false; - Wave_Timer = 600000; - Challenger_checker = 0; - Wave = 0; - PlayerGUID = 0; - - for (uint8 i = 0; i < 6; ++i) - { - AffrayChallenger[i] = 0; - Challenger_down[i] = false; - } - BigWill = 0; - } - - void EnterCombat(Unit * /*who*/) { } - - void MoveInLineOfSight(Unit *who) - { - if (!who || (!who->isAlive())) return; - - if (me->IsWithinDistInMap(who, 10.0f) && (who->GetTypeId() == TYPEID_PLAYER) && CAST_PLR(who)->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE && !EventInProgress) - { - PlayerGUID = who->GetGUID(); - EventInProgress = true; - } - } - - void KilledUnit(Unit * /*victim*/) { } - - void UpdateAI(const uint32 diff) - { - if (EventInProgress) { - Player* pWarrior = NULL; - - if (PlayerGUID) - pWarrior = Unit::GetPlayer(PlayerGUID); - - if (!pWarrior) - return; - - if (!pWarrior->isAlive() && pWarrior->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE) { - EventInProgress = false; - DoScriptText(SAY_TWIGGY_FLATHEAD_DOWN, me); - pWarrior->FailQuest(1719); - - for (uint8 i = 0; i < 6; ++i) - { - if (AffrayChallenger[i]) - { - Creature* pCreature = Unit::GetCreature((*me), AffrayChallenger[i]); - if (pCreature) { - if (pCreature->isAlive()) - { - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->setDeathState(JUST_DIED); - } - } - } - AffrayChallenger[i] = 0; - Challenger_down[i] = false; - } - - if (BigWill) - { - Creature* pCreature = Unit::GetCreature((*me), BigWill); - if (pCreature) { - if (pCreature->isAlive()) { - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->setDeathState(JUST_DIED); - } - } - } - BigWill = 0; - } - - if (!EventGrate && EventInProgress) - { - float x,y,z; - pWarrior->GetPosition(x, y, z); - - if (x >= -1684 && x <= -1674 && y >= -4334 && y <= -4324) { - pWarrior->AreaExploredOrEventHappens(1719); - DoScriptText(SAY_TWIGGY_FLATHEAD_BEGIN, me); - - for (uint8 i = 0; i < 6; ++i) - { - Creature* pCreature = me->SummonCreature(NPC_AFFRAY_CHALLENGER, AffrayChallengerLoc[i][0], AffrayChallengerLoc[i][1], AffrayChallengerLoc[i][2], AffrayChallengerLoc[i][3], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); - if (!pCreature) - continue; - pCreature->setFaction(35); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); - AffrayChallenger[i] = pCreature->GetGUID(); - } - Wave_Timer = 5000; - Challenger_checker = 1000; - EventGrate = true; - } - } - else if (EventInProgress) - { - if (Challenger_checker <= diff) - { - for (uint8 i = 0; i < 6; ++i) - { - if (AffrayChallenger[i]) - { - Creature* pCreature = Unit::GetCreature((*me), AffrayChallenger[i]); - if ((!pCreature || (!pCreature->isAlive())) && !Challenger_down[i]) - { - DoScriptText(SAY_TWIGGY_FLATHEAD_DOWN, me); - Challenger_down[i] = true; - } - } - } - Challenger_checker = 1000; - } else Challenger_checker -= diff; - - if (Wave_Timer <= diff) - { - if (AffrayChallenger[Wave] && Wave < 6 && !EventBigWill) - { - DoScriptText(SAY_TWIGGY_FLATHEAD_FRAY, me); - Creature* pCreature = Unit::GetCreature((*me), AffrayChallenger[Wave]); - if (pCreature && (pCreature->isAlive())) - { - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); - pCreature->setFaction(14); - pCreature->AI()->AttackStart(pWarrior); - ++Wave; - Wave_Timer = 20000; - } - } - else if (Wave >= 6 && !EventBigWill) { - if (Creature* pCreature = me->SummonCreature(NPC_BIG_WILL, -1722, -4341, 6.12, 6.26, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 480000)) - { - BigWill = pCreature->GetGUID(); - //pCreature->GetMotionMaster()->MovePoint(0, -1693, -4343, 4.32); - //pCreature->GetMotionMaster()->MovePoint(1, -1684, -4333, 2.78); - pCreature->GetMotionMaster()->MovePoint(2, -1682, -4329, 2.79); - pCreature->HandleEmoteCommand(EMOTE_STATE_READYUNARMED); - EventBigWill = true; - Wave_Timer = 1000; - } - } - else if (Wave >= 6 && EventBigWill && BigWill) - { - Creature* pCreature = Unit::GetCreature((*me), BigWill); - if (!pCreature || !pCreature->isAlive()) - { - DoScriptText(SAY_TWIGGY_FLATHEAD_OVER, me); - EventInProgress = false; - EventBigWill = false; - EventGrate = false; - PlayerGUID = 0; - Wave = 0; - } - } - } else Wave_Timer -= diff; - } - } - } -}; - -CreatureAI* GetAI_npc_twiggy_flathead(Creature* pCreature) -{ - return new npc_twiggy_flatheadAI (pCreature); -} - -/*##### -## npc_wizzlecrank_shredder -#####*/ - -enum eEnums_Wizzlecrank -{ - SAY_START = -1000298, - SAY_STARTUP1 = -1000299, - SAY_STARTUP2 = -1000300, - SAY_MERCENARY = -1000301, - SAY_PROGRESS_1 = -1000302, - SAY_PROGRESS_2 = -1000303, - SAY_PROGRESS_3 = -1000304, - SAY_END = -1000305, - - QUEST_ESCAPE = 863, - FACTION_RATCHET = 637, - NPC_PILOT_WIZZ = 3451, - NPC_MERCENARY = 3282, -}; - -struct npc_wizzlecrank_shredderAI : public npc_escortAI -{ - npc_wizzlecrank_shredderAI(Creature* pCreature) : npc_escortAI(pCreature) - { - m_bIsPostEvent = false; - m_uiPostEventTimer = 1000; - m_uiPostEventCount = 0; - } - - bool m_bIsPostEvent; - uint32 m_uiPostEventTimer; - uint32 m_uiPostEventCount; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (me->getStandState() == UNIT_STAND_STATE_DEAD) - me->SetStandState(UNIT_STAND_STATE_STAND); - - m_bIsPostEvent = false; - m_uiPostEventTimer = 1000; - m_uiPostEventCount = 0; - } - } - - void WaypointReached(uint32 uiPointId) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(uiPointId) - { - case 0: - DoScriptText(SAY_STARTUP1, me); - break; - case 9: - SetRun(false); - break; - case 17: - if (Creature* pTemp = me->SummonCreature(NPC_MERCENARY, 1128.489f, -3037.611f, 92.701f, 1.472f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000)) - { - DoScriptText(SAY_MERCENARY, pTemp); - me->SummonCreature(NPC_MERCENARY, 1160.172f, -2980.168f, 97.313f, 3.690f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - } - break; - case 24: - m_bIsPostEvent = true; - break; - } - } - - void WaypointStart(uint32 uiPointId) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(uiPointId) - { - case 9: - DoScriptText(SAY_STARTUP2, me, pPlayer); - break; - case 18: - DoScriptText(SAY_PROGRESS_1, me, pPlayer); - SetRun(); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_PILOT_WIZZ) - me->SetStandState(UNIT_STAND_STATE_DEAD); - - if (pSummoned->GetEntry() == NPC_MERCENARY) - pSummoned->AI()->AttackStart(me); - } - - void UpdateEscortAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - { - if (m_bIsPostEvent) - { - if (m_uiPostEventTimer <= uiDiff) - { - switch(m_uiPostEventCount) - { - case 0: - DoScriptText(SAY_PROGRESS_2, me); - break; - case 1: - DoScriptText(SAY_PROGRESS_3, me); - break; - case 2: - DoScriptText(SAY_END, me); - break; - case 3: - if (Player* pPlayer = GetPlayerForEscort()) - { - pPlayer->GroupEventHappens(QUEST_ESCAPE, me); - me->SummonCreature(NPC_PILOT_WIZZ, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 180000); - } - break; - } - - ++m_uiPostEventCount; - m_uiPostEventTimer = 5000; - } - else - m_uiPostEventTimer -= uiDiff; - } - - return; - } - - DoMeleeAttackIfReady(); - } -}; - -bool QuestAccept_npc_wizzlecrank_shredder(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_ESCAPE) - { - pCreature->setFaction(FACTION_RATCHET); - if (npc_escortAI* pEscortAI = CAST_AI(npc_wizzlecrank_shredderAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - } - return true; -} - -CreatureAI* GetAI_npc_wizzlecrank_shredderAI(Creature* pCreature) -{ - return new npc_wizzlecrank_shredderAI(pCreature); -} - -void AddSC_the_barrens() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_beaten_corpse"; - newscript->pGossipHello = &GossipHello_npc_beaten_corpse; - newscript->pGossipSelect = &GossipSelect_npc_beaten_corpse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_gilthares"; - newscript->GetAI = &GetAI_npc_gilthares; - newscript->pQuestAccept = &QuestAccept_npc_gilthares; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_sputtervalve"; - newscript->pGossipHello = &GossipHello_npc_sputtervalve; - newscript->pGossipSelect = &GossipSelect_npc_sputtervalve; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_taskmaster_fizzule"; - newscript->GetAI = &GetAI_npc_taskmaster_fizzule; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_twiggy_flathead"; - newscript->GetAI = &GetAI_npc_twiggy_flathead; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_wizzlecrank_shredder"; - newscript->GetAI = &GetAI_npc_wizzlecrank_shredderAI; - newscript->pQuestAccept = &QuestAccept_npc_wizzlecrank_shredder; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/thousand_needles.cpp b/src/server/scripts/kalimdor/thousand_needles.cpp deleted file mode 100644 index 3f54a62dd0b..00000000000 --- a/src/server/scripts/kalimdor/thousand_needles.cpp +++ /dev/null @@ -1,454 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Thousand Needles -SD%Complete: 100 -SDComment: Support for Quest: 1950, 4770, 4904, 4966, 5151. -SDCategory: Thousand Needles -EndScriptData */ - -/* ContentData -npc_kanati -npc_lakota_windsong -npc_swiftmountain -npc_plucky -go_panther_cage -npc_enraged_panther -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*##### -# npc_kanati -######*/ - -enum eKanati -{ - SAY_KAN_START = -1000410, - - QUEST_PROTECT_KANATI = 4966, - NPC_GALAK_ASS = 10720 -}; - -const float m_afGalakLoc[]= {-4867.387695, -1357.353760, -48.226 }; - -struct npc_kanatiAI : public npc_escortAI -{ - npc_kanatiAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void Reset() { } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 0: - DoScriptText(SAY_KAN_START, me); - DoSpawnGalak(); - break; - case 1: - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->GroupEventHappens(QUEST_PROTECT_KANATI, me); - break; - } - } - - void DoSpawnGalak() - { - for (int i = 0; i < 3; ++i) - me->SummonCreature(NPC_GALAK_ASS, - m_afGalakLoc[0], m_afGalakLoc[1], m_afGalakLoc[2], 0.0f, - TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->AI()->AttackStart(me); - } -}; - -CreatureAI* GetAI_npc_kanati(Creature* pCreature) -{ - return new npc_kanatiAI(pCreature); -} - -bool QuestAccept_npc_kanati(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_PROTECT_KANATI) - { - if (npc_kanatiAI* pEscortAI = CAST_AI(npc_kanatiAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest, true); - } - return true; -} - -/*###### -# npc_lakota_windsong -######*/ - -enum eLakota -{ - SAY_LAKO_START = -1000365, - SAY_LAKO_LOOK_OUT = -1000366, - SAY_LAKO_HERE_COME = -1000367, - SAY_LAKO_MORE = -1000368, - SAY_LAKO_END = -1000369, - - QUEST_FREE_AT_LAST = 4904, - NPC_GRIM_BANDIT = 10758, - FACTION_ESCORTEE_LAKO = 232, //guessed - - ID_AMBUSH_1 = 0, - ID_AMBUSH_2 = 2, - ID_AMBUSH_3 = 4 -}; - -float m_afBanditLoc[6][6]= -{ - {-4905.479492, -2062.732666, 84.352}, - {-4915.201172, -2073.528320, 84.733}, - {-4878.883301, -1986.947876, 91.966}, - {-4877.503906, -1966.113403, 91.859}, - {-4767.985352, -1873.169189, 90.192}, - {-4788.861328, -1888.007813, 89.888} -}; - -struct npc_lakota_windsongAI : public npc_escortAI -{ - npc_lakota_windsongAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void Reset() { } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 8: - DoScriptText(SAY_LAKO_LOOK_OUT, me); - DoSpawnBandits(ID_AMBUSH_1); - break; - case 14: - DoScriptText(SAY_LAKO_HERE_COME, me); - DoSpawnBandits(ID_AMBUSH_2); - break; - case 21: - DoScriptText(SAY_LAKO_MORE, me); - DoSpawnBandits(ID_AMBUSH_3); - break; - case 45: - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->GroupEventHappens(QUEST_FREE_AT_LAST, me); - break; - } - } - - void DoSpawnBandits(int uiAmbushId) - { - for (int i = 0; i < 2; ++i) - me->SummonCreature(NPC_GRIM_BANDIT, - m_afBanditLoc[i+uiAmbushId][0], m_afBanditLoc[i+uiAmbushId][1], m_afBanditLoc[i+uiAmbushId][2], 0.0f, - TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); - } -}; - -CreatureAI* GetAI_npc_lakota_windsong(Creature* pCreature) -{ - return new npc_lakota_windsongAI(pCreature); -} - -bool QuestAccept_npc_lakota_windsong(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_FREE_AT_LAST) - { - DoScriptText(SAY_LAKO_START, pCreature, pPlayer); - pCreature->setFaction(FACTION_ESCORTEE_LAKO); - - if (npc_lakota_windsongAI* pEscortAI = CAST_AI(npc_lakota_windsongAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); - } - return true; -} - -/*###### -# npc_paoka_swiftmountain -######*/ - -enum ePacka -{ - SAY_START = -1000362, - SAY_WYVERN = -1000363, - SAY_COMPLETE = -1000364, - - QUEST_HOMEWARD = 4770, - NPC_WYVERN = 4107, - FACTION_ESCORTEE = 232 //guessed -}; - -float m_afWyvernLoc[3][3]= -{ - {-4990.606, -906.057, -5.343}, - {-4970.241, -927.378, -4.951}, - {-4985.364, -952.528, -5.199} -}; - -struct npc_paoka_swiftmountainAI : public npc_escortAI -{ - npc_paoka_swiftmountainAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void Reset() { } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 15: - DoScriptText(SAY_WYVERN, me); - DoSpawnWyvern(); - break; - case 26: - DoScriptText(SAY_COMPLETE, me); - break; - case 27: - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->GroupEventHappens(QUEST_HOMEWARD, me); - break; - } - } - - void DoSpawnWyvern() - { - for (int i = 0; i < 3; ++i) - me->SummonCreature(NPC_WYVERN, - m_afWyvernLoc[i][0], m_afWyvernLoc[i][1], m_afWyvernLoc[i][2], 0.0f, - TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); - } -}; - -CreatureAI* GetAI_npc_paoka_swiftmountain(Creature* pCreature) -{ - return new npc_paoka_swiftmountainAI(pCreature); -} - -bool QuestAccept_npc_paoka_swiftmountain(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_HOMEWARD) - { - DoScriptText(SAY_START, pCreature, pPlayer); - pCreature->setFaction(FACTION_ESCORTEE); - - if (npc_paoka_swiftmountainAI* pEscortAI = CAST_AI(npc_paoka_swiftmountainAI,pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); - } - return true; -} - -/*##### -# npc_plucky -######*/ - -#define GOSSIP_P "Please tell me the Phrase.." - -enum ePlucky -{ - FACTION_FRIENDLY = 35, - QUEST_SCOOP = 1950, - SPELL_PLUCKY_HUMAN = 9192, - SPELL_PLUCKY_CHICKEN = 9220 -}; - -struct npc_pluckyAI : public ScriptedAI -{ - npc_pluckyAI(Creature *c) : ScriptedAI(c) { m_uiNormFaction = c->getFaction(); } - - uint32 m_uiNormFaction; - uint32 m_uiResetTimer; - - void Reset() - { - m_uiResetTimer = 120000; - - if (me->getFaction() != m_uiNormFaction) - me->setFaction(m_uiNormFaction); - - if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - DoCast(me, SPELL_PLUCKY_CHICKEN, false); - } - - void ReceiveEmote(Player* pPlayer, uint32 uiTextEmote) - { - if (pPlayer->GetQuestStatus(QUEST_SCOOP) == QUEST_STATUS_INCOMPLETE) - { - if (uiTextEmote == TEXTEMOTE_BECKON) - { - me->setFaction(FACTION_FRIENDLY); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - DoCast(me, SPELL_PLUCKY_HUMAN, false); - } - } - - if (uiTextEmote == TEXTEMOTE_CHICKEN) - { - if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - return; - else - { - me->setFaction(FACTION_FRIENDLY); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - DoCast(me, SPELL_PLUCKY_HUMAN, false); - me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - { - if (m_uiResetTimer <= uiDiff) - { - if (!me->getVictim()) - EnterEvadeMode(); - else - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - return; - } - else - m_uiResetTimer -= uiDiff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -bool GossipHello_npc_plucky(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_SCOOP) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_P, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(738, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_plucky(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CompleteQuest(QUEST_SCOOP); - break; - } - return true; -} - -CreatureAI* GetAI_npc_plucky(Creature* pCreature) -{ - return new npc_pluckyAI(pCreature); -} - -enum ePantherCage -{ - ENRAGED_PANTHER = 10992 -}; - -bool go_panther_cage(Player* pPlayer, GameObject* pGo) -{ - - if (pPlayer->GetQuestStatus(5151) == QUEST_STATUS_INCOMPLETE) - { - if (Creature* panther = pGo->FindNearestCreature(ENRAGED_PANTHER, 5, true)) - { - panther->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - panther->SetReactState(REACT_AGGRESSIVE); - panther->AI()->AttackStart(pPlayer); - } - } - - return true ; -} - -struct npc_enraged_pantherAI : public ScriptedAI -{ - npc_enraged_pantherAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_enraged_panther(Creature* pCreature) -{ - return new npc_enraged_pantherAI(pCreature); -} - -void AddSC_thousand_needles() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_kanati"; - newscript->GetAI = &GetAI_npc_kanati; - newscript->pQuestAccept = &QuestAccept_npc_kanati; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lakota_windsong"; - newscript->GetAI = &GetAI_npc_lakota_windsong; - newscript->pQuestAccept = &QuestAccept_npc_lakota_windsong; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_paoka_swiftmountain"; - newscript->GetAI = &GetAI_npc_paoka_swiftmountain; - newscript->pQuestAccept = &QuestAccept_npc_paoka_swiftmountain; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_plucky"; - newscript->GetAI = &GetAI_npc_plucky; - newscript->pGossipHello = &GossipHello_npc_plucky; - newscript->pGossipSelect = &GossipSelect_npc_plucky; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="npc_enraged_panther"; - newscript->GetAI = &GetAI_npc_enraged_panther; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="go_panther_cage"; - newscript->pGOHello = &go_panther_cage; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/thunder_bluff.cpp b/src/server/scripts/kalimdor/thunder_bluff.cpp deleted file mode 100644 index 288f00946f0..00000000000 --- a/src/server/scripts/kalimdor/thunder_bluff.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Thunder_Bluff -SD%Complete: 100 -SDComment: Quest support: 925 -SDCategory: Thunder Bluff -EndScriptData */ - -#include "ScriptedPch.h" - -/*##### -# npc_cairne_bloodhoof -######*/ - -#define SPELL_BERSERKER_CHARGE 16636 -#define SPELL_CLEAVE 16044 -#define SPELL_MORTAL_STRIKE 16856 -#define SPELL_THUNDERCLAP 23931 -#define SPELL_UPPERCUT 22916 - -#define GOSSIP_HCB "I know this is rather silly but a young ward who is a bit shy would like your hoofprint." -//TODO: verify abilities/timers -struct npc_cairne_bloodhoofAI : public ScriptedAI -{ - npc_cairne_bloodhoofAI(Creature* c) : ScriptedAI(c) {} - - uint32 BerserkerCharge_Timer; - uint32 Cleave_Timer; - uint32 MortalStrike_Timer; - uint32 Thunderclap_Timer; - uint32 Uppercut_Timer; - - void Reset() - { - BerserkerCharge_Timer = 30000; - Cleave_Timer = 5000; - MortalStrike_Timer = 10000; - Thunderclap_Timer = 15000; - Uppercut_Timer = 10000; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BerserkerCharge_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - DoCast(pTarget, SPELL_BERSERKER_CHARGE); - BerserkerCharge_Timer = 25000; - } else BerserkerCharge_Timer -= diff; - - if (Uppercut_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_UPPERCUT); - Uppercut_Timer = 20000; - } else Uppercut_Timer -= diff; - - if (Thunderclap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - Thunderclap_Timer = 15000; - } else Thunderclap_Timer -= diff; - - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - MortalStrike_Timer = 15000; - } else MortalStrike_Timer -= diff; - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_cairne_bloodhoof(Creature* pCreature) -{ - return new npc_cairne_bloodhoofAI (pCreature); -} - -bool GossipHello_npc_cairne_bloodhoof(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(925) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HCB, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO); - - pPlayer->SEND_GOSSIP_MENU(7013, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_cairne_bloodhoof(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_SENDER_INFO) - { - pPlayer->CastSpell(pPlayer, 23123, false); - pPlayer->SEND_GOSSIP_MENU(7014, pCreature->GetGUID()); - } - return true; -} - -void AddSC_thunder_bluff() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_cairne_bloodhoof"; - newscript->GetAI = &GetAI_npc_cairne_bloodhoof; - newscript->pGossipHello = &GossipHello_npc_cairne_bloodhoof; - newscript->pGossipSelect = &GossipSelect_npc_cairne_bloodhoof; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/ungoro_crater.cpp b/src/server/scripts/kalimdor/ungoro_crater.cpp deleted file mode 100644 index 2be4a95eb4b..00000000000 --- a/src/server/scripts/kalimdor/ungoro_crater.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Ungoro Crater -SD%Complete: 100 -SDComment: Support for Quest: 4245, 4491 -SDCategory: Ungoro Crater -EndScriptData */ - -/* ContentData -npc_a-me -npc_ringo -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "ScriptedFollowerAI.h" - -#define SAY_READY -1100200 -#define SAY_AGGRO1 -1100201 -#define SAY_SEARCH -1100202 -#define SAY_AGGRO2 -1100203 -#define SAY_AGGRO3 -1100204 -#define SAY_FINISH -1100205 - -#define SPELL_DEMORALIZINGSHOUT 13730 - -#define QUEST_CHASING_AME 4245 -#define ENTRY_TARLORD 6519 -#define ENTRY_TARLORD1 6519 -#define ENTRY_STOMPER 6513 - -struct npc_ameAI : public npc_escortAI -{ - npc_ameAI(Creature *c) : npc_escortAI(c) {} - - uint32 DEMORALIZINGSHOUT_Timer; - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch (i) - { - - case 19: - me->SummonCreature(ENTRY_STOMPER, -6391.69, -1730.49, -272.83, 4.96, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - DoScriptText(SAY_AGGRO1, me, pPlayer); - break; - case 28: - DoScriptText(SAY_SEARCH, me, pPlayer); - break; - case 38: - me->SummonCreature(ENTRY_TARLORD, -6370.75, -1382.84, -270.51, 6.06, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - DoScriptText(SAY_AGGRO2, me, pPlayer); - break; - case 49: - me->SummonCreature(ENTRY_TARLORD1, -6324.44, -1181.05, -270.17, 4.34, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - DoScriptText(SAY_AGGRO3, me, pPlayer); - break; - case 55: - DoScriptText(SAY_FINISH, me, pPlayer); - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_CHASING_AME,me); - break; - - } - } - - void Reset() - { - DEMORALIZINGSHOUT_Timer = 5000; - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void JustDied(Unit* /*killer*/) - { - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->FailQuest(QUEST_CHASING_AME); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - if (!UpdateVictim()) - return; - - if (DEMORALIZINGSHOUT_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DEMORALIZINGSHOUT); - DEMORALIZINGSHOUT_Timer = 70000; - } else DEMORALIZINGSHOUT_Timer -= diff; - - } -}; - -bool QuestAccept_npc_ame(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_CHASING_AME) - { - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); - DoScriptText(SAY_READY, pCreature, pPlayer); - pCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); - // Change faction so mobs attack - pCreature->setFaction(113); - } - return true; -} - -CreatureAI* GetAI_npc_ame(Creature* pCreature) -{ - return new npc_ameAI(pCreature); -} - -/*#### -# npc_ringo -####*/ - -enum eRingo -{ - SAY_RIN_START_1 = -1000416, - SAY_RIN_START_2 = -1000417, - - SAY_FAINT_1 = -1000418, - SAY_FAINT_2 = -1000419, - SAY_FAINT_3 = -1000420, - SAY_FAINT_4 = -1000421, - - SAY_WAKE_1 = -1000422, - SAY_WAKE_2 = -1000423, - SAY_WAKE_3 = -1000424, - SAY_WAKE_4 = -1000425, - - SAY_RIN_END_1 = -1000426, - SAY_SPR_END_2 = -1000427, - SAY_RIN_END_3 = -1000428, - EMOTE_RIN_END_4 = -1000429, - EMOTE_RIN_END_5 = -1000430, - SAY_RIN_END_6 = -1000431, // signed for 6784 - SAY_SPR_END_7 = -1000432, - EMOTE_RIN_END_8 = -1000433, - - SPELL_REVIVE_RINGO = 15591, - QUEST_A_LITTLE_HELP = 4491, - NPC_SPRAGGLE = 9997, - FACTION_ESCORTEE = 113 -}; - -struct npc_ringoAI : public FollowerAI -{ - npc_ringoAI(Creature* pCreature) : FollowerAI(pCreature) { } - - uint32 m_uiFaintTimer; - uint32 m_uiEndEventProgress; - uint32 m_uiEndEventTimer; - - uint64 SpraggleGUID; - - void Reset() - { - m_uiFaintTimer = urand(30000, 60000); - m_uiEndEventProgress = 0; - m_uiEndEventTimer = 1000; - SpraggleGUID = 0; - } - - void MoveInLineOfSight(Unit *pWho) - { - FollowerAI::MoveInLineOfSight(pWho); - - if (!me->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_SPRAGGLE) - { - if (me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) - { - if (Player* pPlayer = GetLeaderForFollower()) - { - if (pPlayer->GetQuestStatus(QUEST_A_LITTLE_HELP) == QUEST_STATUS_INCOMPLETE) - pPlayer->GroupEventHappens(QUEST_A_LITTLE_HELP, me); - } - - SpraggleGUID = pWho->GetGUID(); - SetFollowComplete(true); - } - } - } - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - if (HasFollowState(STATE_FOLLOW_INPROGRESS | STATE_FOLLOW_PAUSED) && pSpell->Id == SPELL_REVIVE_RINGO) - ClearFaint(); - } - - void SetFaint() - { - if (!HasFollowState(STATE_FOLLOW_POSTEVENT)) - { - SetFollowPaused(true); - - DoScriptText(RAND(SAY_FAINT_1,SAY_FAINT_2,SAY_FAINT_3,SAY_FAINT_4), me); - } - - //what does actually happen here? Emote? Aura? - me->SetStandState(UNIT_STAND_STATE_SLEEP); - } - - void ClearFaint() - { - me->SetStandState(UNIT_STAND_STATE_STAND); - - if (HasFollowState(STATE_FOLLOW_POSTEVENT)) - return; - - DoScriptText(RAND(SAY_WAKE_1,SAY_WAKE_2,SAY_WAKE_3,SAY_WAKE_4), me); - - SetFollowPaused(false); - } - - void UpdateFollowerAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - { - if (HasFollowState(STATE_FOLLOW_POSTEVENT)) - { - if (m_uiEndEventTimer <= uiDiff) - { - Unit *pSpraggle = Unit::GetUnit(*me, SpraggleGUID); - if (!pSpraggle || !pSpraggle->isAlive()) - { - SetFollowComplete(); - return; - } - - switch(m_uiEndEventProgress) - { - case 1: - DoScriptText(SAY_RIN_END_1, me); - m_uiEndEventTimer = 3000; - break; - case 2: - DoScriptText(SAY_SPR_END_2, pSpraggle); - m_uiEndEventTimer = 5000; - break; - case 3: - DoScriptText(SAY_RIN_END_3, me); - m_uiEndEventTimer = 1000; - break; - case 4: - DoScriptText(EMOTE_RIN_END_4, me); - SetFaint(); - m_uiEndEventTimer = 9000; - break; - case 5: - DoScriptText(EMOTE_RIN_END_5, me); - ClearFaint(); - m_uiEndEventTimer = 1000; - break; - case 6: - DoScriptText(SAY_RIN_END_6, me); - m_uiEndEventTimer = 3000; - break; - case 7: - DoScriptText(SAY_SPR_END_7, pSpraggle); - m_uiEndEventTimer = 10000; - break; - case 8: - DoScriptText(EMOTE_RIN_END_8, me); - m_uiEndEventTimer = 5000; - break; - case 9: - SetFollowComplete(); - break; - } - - ++m_uiEndEventProgress; - } - else - m_uiEndEventTimer -= uiDiff; - } - else if (HasFollowState(STATE_FOLLOW_INPROGRESS)) - { - if (!HasFollowState(STATE_FOLLOW_PAUSED)) - { - if (m_uiFaintTimer <= uiDiff) - { - SetFaint(); - m_uiFaintTimer = urand(60000, 120000); - } - else - m_uiFaintTimer -= uiDiff; - } - } - - return; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_ringo(Creature* pCreature) -{ - return new npc_ringoAI(pCreature); -} - -bool QuestAccept_npc_ringo(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_A_LITTLE_HELP) - { - if (npc_ringoAI* pRingoAI = CAST_AI(npc_ringoAI, pCreature->AI())) - { - pCreature->SetStandState(UNIT_STAND_STATE_STAND); - pRingoAI->StartFollow(pPlayer, FACTION_ESCORTEE, pQuest); - } - } - - return true; -} - -void AddSC_ungoro_crater() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_ame"; - newscript->GetAI = &GetAI_npc_ame; - newscript->pQuestAccept = &QuestAccept_npc_ame; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ringo"; - newscript->GetAI = &GetAI_npc_ringo; - newscript->pQuestAccept = &QuestAccept_npc_ringo; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/wailing_caverns/instance_wailing_caverns.cpp b/src/server/scripts/kalimdor/wailing_caverns/instance_wailing_caverns.cpp deleted file mode 100644 index 287b5db6d57..00000000000 --- a/src/server/scripts/kalimdor/wailing_caverns/instance_wailing_caverns.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Wailing_Caverns -SD%Complete: 99 -SDComment: Everything seems to work, still need some checking -SDCategory: Wailing Caverns -EndScriptData */ - -#include "ScriptedPch.h" -#include "wailing_caverns.h" - -#define MAX_ENCOUNTER 9 - -struct instance_wailing_caverns : public ScriptedInstance -{ - instance_wailing_caverns(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - bool yelled; - uint64 NaralexGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - yelled = false; - NaralexGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == DATA_NARALEX) - NaralexGUID = pCreature->GetGUID(); - } - - void SetData(uint32 type, uint32 data) - { - switch (type) - { - case TYPE_LORD_COBRAHN: m_auiEncounter[0] = data;break; - case TYPE_LORD_PYTHAS: m_auiEncounter[1] = data;break; - case TYPE_LADY_ANACONDRA: m_auiEncounter[2] = data;break; - case TYPE_LORD_SERPENTIS: m_auiEncounter[3] = data;break; - case TYPE_NARALEX_EVENT: m_auiEncounter[4] = data;break; - case TYPE_NARALEX_PART1: m_auiEncounter[5] = data;break; - case TYPE_NARALEX_PART2: m_auiEncounter[6] = data;break; - case TYPE_NARALEX_PART3: m_auiEncounter[7] = data;break; - case TYPE_MUTANUS_THE_DEVOURER: m_auiEncounter[8] = data;break; - case TYPE_NARALEX_YELLED: yelled = true; break; - } - if (data == DONE)SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch (type) - { - case TYPE_LORD_COBRAHN: return m_auiEncounter[0]; - case TYPE_LORD_PYTHAS: return m_auiEncounter[1]; - case TYPE_LADY_ANACONDRA: return m_auiEncounter[2]; - case TYPE_LORD_SERPENTIS: return m_auiEncounter[3]; - case TYPE_NARALEX_EVENT: return m_auiEncounter[4]; - case TYPE_NARALEX_PART1: return m_auiEncounter[5]; - case TYPE_NARALEX_PART2: return m_auiEncounter[6]; - case TYPE_NARALEX_PART3: return m_auiEncounter[7]; - case TYPE_MUTANUS_THE_DEVOURER: return m_auiEncounter[8]; - case TYPE_NARALEX_YELLED: return yelled; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - if (data == DATA_NARALEX)return NaralexGUID; - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " - << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] >> m_auiEncounter[8]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] != DONE) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } - -}; - -InstanceData* GetInstanceData_instance_wailing_caverns(Map* pMap) -{ - return new instance_wailing_caverns(pMap); -} - -void AddSC_instance_wailing_caverns() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_wailing_caverns"; - newscript->GetInstanceData = &GetInstanceData_instance_wailing_caverns; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.cpp b/src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.cpp deleted file mode 100644 index 544c119fc93..00000000000 --- a/src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Wailing Caverns -SD%Complete: 95 -SDComment: Need to add skill usage for Disciple of Naralex -SDCategory: Wailing Caverns -EndScriptData */ - -/* ContentData -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "wailing_caverns.h" - -/*###### -## npc_disciple_of_naralex -######*/ - -enum eEnums -{ - //say - SAY_MAKE_PREPARATIONS = -1043001, - SAY_TEMPLE_OF_PROMISE = -1043002, - SAY_MUST_CONTINUE = -1043003, - SAY_BANISH_THE_SPIRITS = -1043004, - SAY_CAVERNS_PURIFIED = -1043005, - SAY_BEYOND_THIS_CORRIDOR = -1043006, - SAY_EMERALD_DREAM = -1043007, - SAY_MUTANUS_THE_DEVOURER = -1043012, - SAY_NARALEX_AWAKES = -1043014, - SAY_THANK_YOU = -1043015, - SAY_FAREWELL = -1043016, - SAY_ATTACKED = -1043017, - //yell - SAY_AT_LAST = -1043000, - SAY_I_AM_AWAKE = -1043013, - //emote - EMOTE_AWAKENING_RITUAL = -1043008, - EMOTE_TROUBLED_SLEEP = -1043009, - EMOTE_WRITHE_IN_AGONY = -1043010, - EMOTE_HORRENDOUS_VISION = -1043011, - //spell - SPELL_MARK_OF_THE_WILD_RANK_2 = 5232, - SPELL_SERPENTINE_CLEANSING = 6270, - SPELL_NARALEXS_AWAKENING = 6271, - SPELL_FLIGHT_FORM = 33943, - //npc entry - NPC_DEVIATE_RAVAGER = 3636, - NPC_DEVIATE_VIPER = 5755, - NPC_DEVIATE_MOCCASIN = 5762, - NPC_NIGHTMARE_ECTOPLASM = 5763, - NPC_MUTANUS_THE_DEVOURER = 3654, -}; - -#define GOSSIP_ID_START_1 698 //Naralex sleeps again! -#define GOSSIP_ID_START_2 699 //The fanglords are dead! -#define GOSSIP_ITEM_NARALEX "Let the event begin!" -#define ACHIEVEMENT_WAILING_CAVERNS 630 - -struct npc_disciple_of_naralexAI : public npc_escortAI -{ - npc_disciple_of_naralexAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - eventTimer = 0; - currentEvent = 0; - eventProgress = 0; - me->setActive(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - uint32 eventTimer; - uint32 currentEvent; - uint32 eventProgress; - ScriptedInstance *pInstance; - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch (i) - { - case 4: - eventProgress = 1; - currentEvent = TYPE_NARALEX_PART1; - pInstance->SetData(TYPE_NARALEX_PART1, IN_PROGRESS); - break; - case 5: - DoScriptText(SAY_MUST_CONTINUE, me); - pInstance->SetData(TYPE_NARALEX_PART1, DONE); - break; - case 11: - eventProgress = 1; - currentEvent = TYPE_NARALEX_PART2; - pInstance->SetData(TYPE_NARALEX_PART2, IN_PROGRESS); - break; - case 19: - DoScriptText(SAY_BEYOND_THIS_CORRIDOR, me); - break; - case 24: - eventProgress = 1; - currentEvent = TYPE_NARALEX_PART3; - pInstance->SetData(TYPE_NARALEX_PART3, IN_PROGRESS); - break; - } - } - - void Reset() - { - - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_ATTACKED, me, who); - } - - void JustDied(Unit * /*slayer*/) - { - if (pInstance) - { - pInstance->SetData(TYPE_NARALEX_EVENT, FAIL); - pInstance->SetData(TYPE_NARALEX_PART1, FAIL); - pInstance->SetData(TYPE_NARALEX_PART2, FAIL); - pInstance->SetData(TYPE_NARALEX_PART3, FAIL); - } - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void UpdateAI(const uint32 diff) - { - if (currentEvent != TYPE_NARALEX_PART3) - npc_escortAI::UpdateAI(diff); - - if (!pInstance) - return; - if (eventTimer <= diff) - { - eventTimer = 0; - if (pInstance->GetData(currentEvent) == IN_PROGRESS) - { - switch (currentEvent) - { - case TYPE_NARALEX_PART1: - if (eventProgress == 1) - { - ++eventProgress; - DoScriptText(SAY_TEMPLE_OF_PROMISE, me); - me->SummonCreature(NPC_DEVIATE_RAVAGER, -82.1763, 227.874, -93.3233, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - me->SummonCreature(NPC_DEVIATE_RAVAGER, -72.9506, 216.645, -93.6756, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - } - break; - case TYPE_NARALEX_PART2: - if (eventProgress == 1) - { - ++eventProgress; - DoScriptText(SAY_BANISH_THE_SPIRITS, me); - DoCast(me, SPELL_SERPENTINE_CLEANSING); - //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(false); - eventTimer = 30000; - me->SummonCreature(NPC_DEVIATE_VIPER, -61.5261, 273.676, -92.8442, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - me->SummonCreature(NPC_DEVIATE_VIPER, -58.4658, 280.799, -92.8393, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - me->SummonCreature(NPC_DEVIATE_VIPER, -50.002, 278.578, -92.8442, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - } - else - if (eventProgress == 2) - { - //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(true); - DoScriptText(SAY_CAVERNS_PURIFIED, me); - pInstance->SetData(TYPE_NARALEX_PART2, DONE); - if (me->HasAura(SPELL_SERPENTINE_CLEANSING)) - me->RemoveAura(SPELL_SERPENTINE_CLEANSING); - } - break; - case TYPE_NARALEX_PART3: - if (eventProgress == 1) - { - ++eventProgress; - eventTimer = 4000; - me->SetStandState(UNIT_STAND_STATE_KNEEL); - DoScriptText(SAY_EMERALD_DREAM, me); - } - else - if (eventProgress == 2) - { - ++eventProgress; - eventTimer = 15000; - //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(false); - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoCast(naralex, SPELL_NARALEXS_AWAKENING, true); - DoScriptText(EMOTE_AWAKENING_RITUAL, me); - } - else - if (eventProgress == 3) - { - ++eventProgress; - eventTimer = 15000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoScriptText(EMOTE_TROUBLED_SLEEP, naralex); - me->SummonCreature(NPC_DEVIATE_MOCCASIN, 135.943, 199.701, -103.529, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_DEVIATE_MOCCASIN, 151.08, 221.13, -103.609, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_DEVIATE_MOCCASIN, 128.007, 227.428, -97.421, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - } - else - if (eventProgress == 4) - { - ++eventProgress; - eventTimer = 30000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoScriptText(EMOTE_WRITHE_IN_AGONY, naralex); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 133.413, 207.188, -102.469, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 142.857, 218.645, -102.905, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 105.102, 227.211, -102.752, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 153.372, 235.149, -102.826, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 149.524, 251.113, -102.558, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 136.208, 266.466, -102.977, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 126.167, 274.759, -102.962, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - } - else - if (eventProgress == 5) - { - ++eventProgress; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoScriptText(EMOTE_HORRENDOUS_VISION, naralex); - me->SummonCreature(NPC_MUTANUS_THE_DEVOURER, 150.872, 262.905, -103.503, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - DoScriptText(SAY_MUTANUS_THE_DEVOURER, me); - pInstance->SetData(TYPE_MUTANUS_THE_DEVOURER, IN_PROGRESS); - } - else - if (eventProgress == 6 && pInstance->GetData(TYPE_MUTANUS_THE_DEVOURER) == DONE) - { - ++eventProgress; - eventTimer = 3000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - { - AchievementEntry const *AchievWC = GetAchievementStore()->LookupEntry(ACHIEVEMENT_WAILING_CAVERNS); - if (AchievWC) - { - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievWC); - } - } - if (me->HasAura(SPELL_NARALEXS_AWAKENING)) - me->RemoveAura(SPELL_NARALEXS_AWAKENING); - naralex->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_I_AM_AWAKE, naralex); - } - DoScriptText(SAY_NARALEX_AWAKES, me); - } - else - if (eventProgress == 7) - { - ++eventProgress; - eventTimer = 6000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoScriptText(SAY_THANK_YOU, naralex); - } - else - if (eventProgress == 8) - { - ++eventProgress; - eventTimer = 8000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - { - DoScriptText(SAY_FAREWELL, naralex); - naralex->AddAura(SPELL_FLIGHT_FORM, naralex); - } - SetRun(); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->AddAura(SPELL_FLIGHT_FORM, me); - } - else - if (eventProgress == 9) - { - ++eventProgress; - eventTimer = 1500; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - naralex->GetMotionMaster()->MovePoint(25, naralex->GetPositionX(), naralex->GetPositionY(), naralex->GetPositionZ()); - } - else - if (eventProgress == 10) - { - ++eventProgress; - eventTimer = 2500; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - { - naralex->GetMotionMaster()->MovePoint(0, 117.095512, 247.107971, -96.167870); - naralex->GetMotionMaster()->MovePoint(1, 90.388809, 276.135406, -83.389801); - } - me->GetMotionMaster()->MovePoint(26, 117.095512, 247.107971, -96.167870); - me->GetMotionMaster()->MovePoint(27, 144.375443, 281.045837, -82.477135); - } - else - if (eventProgress == 11) - { - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - naralex->SetVisibility(VISIBILITY_OFF); - me->SetVisibility(VISIBILITY_OFF); - pInstance->SetData(TYPE_NARALEX_PART3, DONE); - } - break; - } - } - } else eventTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_disciple_of_naralex(Creature* pCreature) -{ - return new npc_disciple_of_naralexAI(pCreature); -} - -bool GossipHello_npc_disciple_of_naralex(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance *pInstance = pCreature->GetInstanceData(); - - if (pInstance) - { - pCreature->CastSpell(pPlayer, SPELL_MARK_OF_THE_WILD_RANK_2, true); - if ((pInstance->GetData(TYPE_LORD_COBRAHN) == DONE) && (pInstance->GetData(TYPE_LORD_PYTHAS) == DONE) && - (pInstance->GetData(TYPE_LADY_ANACONDRA) == DONE) && (pInstance->GetData(TYPE_LORD_SERPENTIS) == DONE)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NARALEX, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START_2, pCreature->GetGUID()); - - if (!pInstance->GetData(TYPE_NARALEX_YELLED)) - { - DoScriptText(SAY_AT_LAST, pCreature); - pInstance->SetData(TYPE_NARALEX_YELLED, 1); - } - } - else - { - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START_1, pCreature->GetGUID()); - } - } - return true; -} - -bool GossipSelect_npc_disciple_of_naralex(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - ScriptedInstance *pInstance = pCreature->GetInstanceData(); - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - if (pInstance) - pInstance->SetData(TYPE_NARALEX_EVENT, IN_PROGRESS); - - DoScriptText(SAY_MAKE_PREPARATIONS, pCreature); - - pCreature->setFaction(250); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); - } - return true; -} - -void AddSC_wailing_caverns() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_disciple_of_naralex"; - newscript->pGossipHello = &GossipHello_npc_disciple_of_naralex; - newscript->pGossipSelect = &GossipSelect_npc_disciple_of_naralex; - newscript->GetAI = &GetAI_npc_disciple_of_naralex; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.h b/src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.h deleted file mode 100644 index 6ef1a673c59..00000000000 --- a/src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_WAILING_CAVERNS_H -#define DEF_WAILING_CAVERNS_H - -enum eTypes -{ - TYPE_LORD_COBRAHN = 1, - TYPE_LORD_PYTHAS = 2, - TYPE_LADY_ANACONDRA = 3, - TYPE_LORD_SERPENTIS = 4, - TYPE_NARALEX_EVENT = 5, - TYPE_NARALEX_PART1 = 6, - TYPE_NARALEX_PART2 = 7, - TYPE_NARALEX_PART3 = 8, - TYPE_MUTANUS_THE_DEVOURER = 9, - TYPE_NARALEX_YELLED = 10, - - DATA_NARALEX = 3679, -}; - -#endif diff --git a/src/server/scripts/kalimdor/winterspring.cpp b/src/server/scripts/kalimdor/winterspring.cpp deleted file mode 100644 index a284f32aeaa..00000000000 --- a/src/server/scripts/kalimdor/winterspring.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Winterspring -SD%Complete: 90 -SDComment: Quest support: 5126 (Loraxs' tale missing proper gossip items text). Vendor Rivern Frostwind. Obtain Cache of Mau'ari -SDCategory: Winterspring -EndScriptData */ - -/* ContentData -npc_lorax -npc_rivern_frostwind -npc_witch_doctor_mauari -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_lorax -######*/ - -#define GOSSIP_HL "Talk to me" - -#define GOSSIP_SL1 "What do you do here?" -#define GOSSIP_SL2 "I can help you" -#define GOSSIP_SL3 "What deal?" -#define GOSSIP_SL4 "Then what happened?" -#define GOSSIP_SL5 "He is not safe, i'll make sure of that." - -bool GossipHello_npc_lorax(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(5126) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lorax(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(3759, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(3760, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(3761, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(3762, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - pPlayer->SEND_GOSSIP_MENU(3763, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(5126); - break; - } - return true; -} - -/*###### -## npc_rivern_frostwind -######*/ - -bool GossipHello_npc_rivern_frostwind(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor() && pPlayer->GetReputationRank(589) == REP_EXALTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_rivern_frostwind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_witch_doctor_mauari -######*/ - -#define GOSSIP_HWDM "I'd like you to make me a new Cache of Mau'ari please." - -bool GossipHello_npc_witch_doctor_mauari(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestRewardStatus(975)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HWDM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(3377, pCreature->GetGUID()); - }else - pPlayer->SEND_GOSSIP_MENU(3375, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_witch_doctor_mauari(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, 16351, false); - } - - return true; -} - -void AddSC_winterspring() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_lorax"; - newscript->pGossipHello = &GossipHello_npc_lorax; - newscript->pGossipSelect = &GossipSelect_npc_lorax; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_rivern_frostwind"; - newscript->pGossipHello = &GossipHello_npc_rivern_frostwind; - newscript->pGossipSelect = &GossipSelect_npc_rivern_frostwind; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_witch_doctor_mauari"; - newscript->pGossipHello = &GossipHello_npc_witch_doctor_mauari; - newscript->pGossipSelect = &GossipSelect_npc_witch_doctor_mauari; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/kalimdor/zulfarrak/instance_zulfarrak.cpp b/src/server/scripts/kalimdor/zulfarrak/instance_zulfarrak.cpp deleted file mode 100644 index 530ef30f44c..00000000000 --- a/src/server/scripts/kalimdor/zulfarrak/instance_zulfarrak.cpp +++ /dev/null @@ -1,58 +0,0 @@ - /* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" - -#define NPC_GAHZRILLA 7273 - -struct instance_zulfarrak : public ScriptedInstance -{ - instance_zulfarrak(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 GahzRillaEncounter; - - void Initialize() - { - GahzRillaEncounter = NOT_STARTED; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == NPC_GAHZRILLA) - { - if (GahzRillaEncounter >= IN_PROGRESS) - pCreature->DisappearAndDie(); - else - GahzRillaEncounter = IN_PROGRESS; - } - } -}; - -InstanceData* GetInstanceData_instance_zulfarrak(Map* pMap) -{ - return new instance_zulfarrak(pMap); -} - -void AddSC_instance_zulfarrak() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_zulfarrak"; - newscript->GetInstanceData = &GetInstanceData_instance_zulfarrak; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/kalimdor/zulfarrak/zulfarrak.cpp b/src/server/scripts/kalimdor/zulfarrak/zulfarrak.cpp deleted file mode 100644 index 2ca053c23b6..00000000000 --- a/src/server/scripts/kalimdor/zulfarrak/zulfarrak.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Zulfarrak -SD%Complete: 50 -SDComment: Consider it temporary, no instance script made for this instance yet. -SDCategory: Zul'Farrak -EndScriptData */ - -/* ContentData -npc_sergeant_bly -npc_weegli_blastfuse -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_sergeant_bly -######*/ - -#define FACTION_HOSTILE 14 -#define FACTION_FRIENDLY 35 - -#define SPELL_SHIELD_BASH 11972 -#define SPELL_REVENGE 12170 - -#define GOSSIP_BLY "[PH] In that case, I will take my reward!" - -struct npc_sergeant_blyAI : public ScriptedAI -{ - npc_sergeant_blyAI(Creature *c) : ScriptedAI(c) - { - //pInstance = c->GetInstanceData(); - } - - //ScriptedInstance* pInstance; - - uint32 ShieldBash_Timer; - uint32 Revenge_Timer; //this is wrong, spell should never be used unless me->getVictim() dodge, parry or block attack. Trinity support required. - - void Reset() - { - ShieldBash_Timer = 5000; - Revenge_Timer = 8000; - - me->setFaction(FACTION_FRIENDLY); - - /*if (pInstance) - pInstance->SetData(0, NOT_STARTED);*/ - } - - void EnterCombat(Unit * /*who*/) - { - /*if (pInstance) - pInstance->SetData(0, IN_PROGRESS);*/ - } - - void JustDied(Unit * /*victim*/) - { - /*if (pInstance) - pInstance->SetData(0, DONE);*/ - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShieldBash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHIELD_BASH); - ShieldBash_Timer = 15000; - } else ShieldBash_Timer -= diff; - - if (Revenge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REVENGE); - Revenge_Timer = 10000; - } else Revenge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_sergeant_bly(Creature* pCreature) -{ - return new npc_sergeant_blyAI (pCreature); -} - -bool GossipHello_npc_sergeant_bly(Player* pPlayer, Creature* pCreature) -{ - /*if (pInstance->GetData(0) == DONE) - {*/ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(1517, pCreature->GetGUID()); - /*} - else if (pInstance->GetData(0) == IN_PROGRESS) - pPlayer->SEND_GOSSIP_MENU(1516, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(1515, pCreature->GetGUID());*/ - - return true; -} - -bool GossipSelect_npc_sergeant_bly(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(FACTION_HOSTILE); - CAST_AI(npc_sergeant_blyAI, pCreature->AI())->AttackStart(pPlayer); - } - return true; -} - -/*###### -## npc_weegli_blastfuse -######*/ - -#define SPELL_BOMB 8858 -#define SPELL_GOBLIN_LAND_MINE 21688 -#define SPELL_SHOOT 6660 -#define SPELL_WEEGLIS_BARREL 10772 - -#define GOSSIP_WEEGLI "[PH] Please blow up the door." - -struct npc_weegli_blastfuseAI : public ScriptedAI -{ - npc_weegli_blastfuseAI(Creature *c) : ScriptedAI(c) - { - //pInstance = c->GetInstanceData(); - } - - //ScriptedInstance* pInstance; - - void Reset() - { - /*if (pInstance) - pInstance->SetData(0, NOT_STARTED);*/ - } - - void EnterCombat(Unit * /*who*/) - { - /*if (pInstance) - pInstance->SetData(0, IN_PROGRESS);*/ - } - - void JustDied(Unit * /*victim*/) - { - /*if (pInstance) - pInstance->SetData(0, DONE);*/ - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_weegli_blastfuse(Creature* pCreature) -{ - return new npc_weegli_blastfuseAI (pCreature); -} - -bool GossipHello_npc_weegli_blastfuse(Player* pPlayer, Creature* pCreature) -{ - //event not implemented yet, this is only placeholder for future developement - /*if (pInstance->GetData(0) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEEGLI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(1514, pCreature->GetGUID());//if event can proceed to end - } - else if (pInstance->GetData(0) == IN_PROGRESS) - pPlayer->SEND_GOSSIP_MENU(1513, pCreature->GetGUID());//if event are in progress - else*/ - pPlayer->SEND_GOSSIP_MENU(1511, pCreature->GetGUID()); //if event not started - return true; -} - -bool GossipSelect_npc_weegli_blastfuse(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - //here we make him run to door, set the charge and run away off to nowhere - } - return true; -} - -/*###### -## go_shallow_grave -######*/ - -enum { - ZOMBIE = 7286, - DEAD_HERO = 7276, - ZOMBIE_CHANCE = 65, - DEAD_HERO_CHANCE = 10 -}; - -bool GOHello_go_shallow_grave(Player* /*pPlayer*/, GameObject* pGo) -{ - // randomly summon a zombie or dead hero the first time a grave is used - if (pGo->GetUseCount() == 0) - { - uint32 randomchance = urand(0,100); - if (randomchance < ZOMBIE_CHANCE) - pGo->SummonCreature(ZOMBIE, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - else if ((randomchance-ZOMBIE_CHANCE) < DEAD_HERO_CHANCE) - pGo->SummonCreature(DEAD_HERO, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - } - pGo->AddUse(); - return false; -} - -/*###### -## at_zumrah -######*/ - -enum { - ZUMRAH_ID = 7271, - ZUMRAH_HOSTILE_FACTION = 37 -}; - -bool AreaTrigger_at_zumrah(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - Creature* Zumrah = pPlayer->FindNearestCreature(ZUMRAH_ID, 30.0f); - - if (!Zumrah) - return false; - - Zumrah->setFaction(ZUMRAH_HOSTILE_FACTION); - Zumrah->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - return true; -} - -void AddSC_zulfarrak() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sergeant_bly"; - newscript->GetAI = &GetAI_npc_sergeant_bly; - newscript->pGossipHello = &GossipHello_npc_sergeant_bly; - newscript->pGossipSelect = &GossipSelect_npc_sergeant_bly; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_weegli_blastfuse"; - newscript->GetAI = &GetAI_npc_weegli_blastfuse; - newscript->pGossipHello = &GossipHello_npc_weegli_blastfuse; - newscript->pGossipSelect = &GossipSelect_npc_weegli_blastfuse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_shallow_grave"; - newscript->pGOHello = &GOHello_go_shallow_grave; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_zumrah"; - newscript->pAreaTrigger = &AreaTrigger_at_zumrah; - newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/northrend/azjol_nerub/ahnkahet/ahnkahet.h b/src/server/scripts/northrend/azjol_nerub/ahnkahet/ahnkahet.h deleted file mode 100644 index 240ad77c74d..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/ahnkahet/ahnkahet.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_AHNKAHET_H -#define DEF_AHNKAHET_H - -enum Data64 -{ - DATA_ELDER_NADOX, - DATA_PRINCE_TALDARAM, - DATA_JEDOGA_SHADOWSEEKER, - DATA_HERALD_VOLAZJ, - DATA_AMANITAR, - DATA_SPHERE1, - DATA_SPHERE2, - DATA_PRINCE_TALDARAM_PLATFORM, - DATA_PL_JEDOGA_TARGET, - DATA_ADD_JEDOGA_OPFER, - DATA_ADD_JEDOGA_INITIAND -}; - -enum Data -{ - DATA_ELDER_NADOX_EVENT, - DATA_PRINCE_TALDARAM_EVENT, - DATA_JEDOGA_SHADOWSEEKER_EVENT, - DATA_HERALD_VOLAZJ_EVENT, - DATA_AMANITAR_EVENT, - DATA_SPHERE1_EVENT, - DATA_SPHERE2_EVENT, - DATA_JEDOGA_TRIGGER_SWITCH, - DATA_JEDOGA_RESET_INITIANDS, - DATA_INITIAND_KILLED, - DATA_ALL_INITIAND_DEAD -}; - -#endif diff --git a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp b/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp deleted file mode 100644 index 51c4bce0c2d..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Comment: Find correct mushrooms spell to make them visible - buffs of the mushrooms not ever applied to the users... - */ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -enum Spells -{ - SPELL_BASH = 57094, // Victim - SPELL_ENTANGLING_ROOTS = 57095, // Random Victim 100Y - SPELL_MINI = 57055, // Self - SPELL_VENOM_BOLT_VOLLEY = 57088, // Random Victim 100Y - SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS = 56648, // Killer 3Y - SPELL_POISONOUS_MUSHROOM_POISON_CLOUD = 57061, // Self - Duration 8 Sec - SPELL_POISONOUS_MUSHROOM_VISUAL_AREA = 61566, // Self - SPELL_POISONOUS_MUSHROOM_VISUAL_AURA = 56741, // Self - SPELL_PUTRID_MUSHROOM = 31690, // To make the mushrooms visible -}; - -enum Creatures -{ - NPC_HEALTHY_MUSHROOM = 30391, - NPC_POISONOUS_MUSHROOM = 30435 -}; - -struct boss_amanitarAI : public ScriptedAI -{ - boss_amanitarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - bFirstTime = true; - } - - ScriptedInstance* pInstance; - - uint32 uiRootTimer; - uint32 uiBashTimer; - uint32 uiBoltTimer; - uint32 uiSpawnTimer; - - bool bFirstTime; - - void Reset() - { - uiRootTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); - uiBashTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); - uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - uiSpawnTimer = 0; - - me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - - if (pInstance) - { - pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); - if (!bFirstTime) - pInstance->SetData(DATA_AMANITAR_EVENT, FAIL); - else - bFirstTime = false; - } - } - - void JustDied(Unit * /*Killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_AMANITAR_EVENT, DONE); - pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_AMANITAR_EVENT, IN_PROGRESS); - - DoCast(me, SPELL_MINI, false); - } - - void SpawnAdds() - { - for (uint8 i = 0; i < 30; ++i) - { - Unit* victim = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (victim) - { - Position pos; - victim->GetPosition(&pos); - me->GetRandomNearPosition(pos, float(urand(5,80))); - me->SummonCreature(NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILISECONDS); - me->GetRandomNearPosition(pos, float(urand(5,80))); - me->SummonCreature(NPC_HEALTHY_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILISECONDS); - } - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiSpawnTimer <= diff) - { - SpawnAdds(); - uiSpawnTimer = urand(35*IN_MILISECONDS,40*IN_MILISECONDS); - } else uiSpawnTimer -= diff; - - if (uiRootTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ENTANGLING_ROOTS); - uiRootTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiRootTimer -= diff; - - if (uiBashTimer <= diff) - { - DoCastVictim(SPELL_BASH); - uiBashTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiBashTimer -= diff; - - if (uiBoltTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_VENOM_BOLT_VOLLEY); - uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_amanitar_mushroomsAI : public Scripted_NoMovementAI -{ - mob_amanitar_mushroomsAI(Creature* c) : Scripted_NoMovementAI(c) {} - - uint32 uiAuraTimer; - uint32 uiDeathTimer; - - void Reset() - { - DoCast(me, SPELL_PUTRID_MUSHROOM, true); // Hack, to make the mushrooms visible, can't find orig. spell... - - if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) - DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true); - - uiAuraTimer = 0; - uiDeathTimer = 30*IN_MILISECONDS; - } - - void JustDied(Unit *killer) - { - if (!killer) - return; - - if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && killer->GetTypeId() == TYPEID_PLAYER) - { - me->InterruptNonMeleeSpells(false); - DoCast(killer, SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, false); - } - } - - void EnterCombat(Unit * /*who*/) {} - void AttackStart(Unit * /*victim*/) {} - - void UpdateAI(const uint32 diff) - { - if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) - { - if (uiAuraTimer <= diff) - { - DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AREA, true); - DoCast(me, SPELL_POISONOUS_MUSHROOM_POISON_CLOUD, false); - uiAuraTimer = 7*IN_MILISECONDS; - } else uiAuraTimer -= diff; - } - if (uiDeathTimer <= diff) - me->DisappearAndDie(); - else uiDeathTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_amanitar(Creature* pCreature) -{ - return new boss_amanitarAI (pCreature); -} - -CreatureAI* GetAI_mob_amanitar_mushrooms(Creature *pCreature) -{ - return new mob_amanitar_mushroomsAI (pCreature); -} - -void AddSC_boss_amanitar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_amanitar"; - newscript->GetAI = &GetAI_boss_amanitar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_amanitar_mushrooms"; - newscript->GetAI = &GetAI_mob_amanitar_mushrooms; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp deleted file mode 100644 index 2215d91c749..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -bool DeadAhnkaharGuardian; // needed for achievement: Respect Your Elders(2038) - -enum Achievements -{ - ACHIEV_RESPECT_YOUR_ELDERS = 2038 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1619014, - SAY_SLAY_1 = -1619015, - SAY_SLAY_2 = -1619016, - SAY_SLAY_3 = -1619017, - SAY_DEATH = -1619018, - SAY_EGG_SAC_1 = -1619019, - SAY_EGG_SAC_2 = -1619020 -}; - -enum Spells -{ - SPELL_BROOD_PLAGUE = 56130, - H_SPELL_BROOD_PLAGUE = 59467, - H_SPELL_BROOD_RAGE = 59465, - SPELL_ENRAGE = 26662, // Enraged if too far away from home - SPELL_SUMMON_SWARMERS = 56119, //2x 30178 -- 2x every 10secs - SPELL_SUMMON_SWARM_GUARD = 56120, //1x 30176 -- every 25secs -}; - -enum Creatures -{ - MOB_AHNKAHAR_SWARMER = 30178, - MOB_AHNKAHAR_GUARDIAN_ENTRY = 30176 -}; - -#define EMOTE_HATCHES "An Ahn'kahar Guardian hatches!" - -struct boss_elder_nadoxAI : public ScriptedAI -{ - boss_elder_nadoxAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiPlagueTimer; - uint32 uiRagueTimer; - - uint32 uiSwarmerSpawnTimer; - uint32 uiGuardSpawnTimer; - uint32 uiEnragueTimer; - - bool bGuardSpawned; - - ScriptedInstance *pInstance; - - void Reset() - { - uiPlagueTimer = 13*IN_MILISECONDS; - uiRagueTimer = 20*IN_MILISECONDS; - - uiSwarmerSpawnTimer = 10*IN_MILISECONDS; - uiGuardSpawnTimer = 25*IN_MILISECONDS; - - uiEnragueTimer = 5*IN_MILISECONDS; - - DeadAhnkaharGuardian = false; - bGuardSpawned = false; - - if (pInstance) - pInstance->SetData(DATA_ELDER_NADOX_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_DEATH,me); - - if (pInstance) - pInstance->SetData(DATA_ELDER_NADOX_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_SLAY_3,me); //SAY_SLAY_3 on death? - - if (pInstance) - { - pInstance->SetData(DATA_ELDER_NADOX_EVENT, DONE); - if (IsHeroic() && !DeadAhnkaharGuardian) - pInstance->DoCompleteAchievement(ACHIEV_RESPECT_YOUR_ELDERS); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiPlagueTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BROOD_PLAGUE); - uiPlagueTimer = 15*IN_MILISECONDS; - } else uiPlagueTimer -= diff; - - if (IsHeroic()) - if (uiRagueTimer <= diff) - { - if (Creature *pSwarmer = me->FindNearestCreature(MOB_AHNKAHAR_SWARMER, 35)) - { - DoCast(pSwarmer, H_SPELL_BROOD_RAGE, true); - uiRagueTimer = 15*IN_MILISECONDS; - } - } else uiRagueTimer -= diff; - - if (uiSwarmerSpawnTimer <= diff) - { - DoCast(me, SPELL_SUMMON_SWARMERS, true); - DoCast(me, SPELL_SUMMON_SWARMERS); - if (urand(1,3) == 3) // 33% chance of dialog - DoScriptText(RAND(SAY_EGG_SAC_1,SAY_EGG_SAC_2), me); - - uiSwarmerSpawnTimer = 10*IN_MILISECONDS; - } else uiSwarmerSpawnTimer -= diff; - - if (!bGuardSpawned && uiGuardSpawnTimer <= diff) - { - me->MonsterTextEmote(EMOTE_HATCHES,me->GetGUID(),true); - DoCast(me, SPELL_SUMMON_SWARM_GUARD); - bGuardSpawned = true; - } else uiGuardSpawnTimer -= diff; - - if (uiEnragueTimer <= diff) - { - if (me->HasAura(SPELL_ENRAGE,0)) - return; - - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - if (z < 24) - if (!me->IsNonMeleeSpellCasted(false)) - DoCast(me, SPELL_ENRAGE, true); - - uiEnragueTimer = 5*IN_MILISECONDS; - } else uiEnragueTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_elder_nadox(Creature* pCreature) -{ - return new boss_elder_nadoxAI(pCreature); -} - -enum AddSpells -{ - SPELL_SPRINT = 56354, - SPELL_GUARDIAN_AURA = 56151 -}; - -struct mob_ahnkahar_nerubianAI : public ScriptedAI -{ - mob_ahnkahar_nerubianAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 uiSprintTimer; - - void Reset() - { - if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) //magic numbers are bad! - DoCast(me, SPELL_GUARDIAN_AURA, true); - uiSprintTimer = 10*IN_MILISECONDS; - } - - void JustDied(Unit * /*killer*/) - { - if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) - DeadAhnkaharGuardian = true; - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) - me->RemoveAurasDueToSpell(SPELL_GUARDIAN_AURA); - - if (pInstance) - { - if (pInstance->GetData(DATA_ELDER_NADOX_EVENT) != IN_PROGRESS) - { - me->DisappearAndDie(); - } - } - - if (!UpdateVictim()) - return; - - if (uiSprintTimer <= diff) - { - DoCast(me, SPELL_SPRINT); - uiSprintTimer = 25*IN_MILISECONDS; - } else uiSprintTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//HACK: No, AI. Replace with proper db content? -struct mob_nadox_eggsAI : public Scripted_NoMovementAI -{ - mob_nadox_eggsAI(Creature* c) : Scripted_NoMovementAI(c) - { - c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - c->UpdateAllStats(); - } - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*victim*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_mob_ahnkahar_nerubian(Creature* pCreature) -{ - return new mob_ahnkahar_nerubianAI(pCreature); -} - -CreatureAI* GetAI_mob_nadox_eggs(Creature* _Creature) -{ - return new mob_nadox_eggsAI(_Creature); -} - -void AddSC_boss_elder_nadox() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_elder_nadox"; - newscript->GetAI = &GetAI_boss_elder_nadox; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ahnkahar_nerubian"; - newscript->GetAI = &GetAI_mob_ahnkahar_nerubian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_nadox_eggs"; - newscript->GetAI = &GetAI_mob_nadox_eggs; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp deleted file mode 100644 index 16c291d6484..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Comment: Missing AI for Twisted Visages - */ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -enum Spells -{ - SPELL_INSANITY = 57496, //Dummy - INSANITY_VISUAL = 57561, - SPELL_INSANITY_TARGET = 57508, - SPELL_MIND_FLAY = 57941, - SPELL_SHADOW_BOLT_VOLLEY = 57942, - SPELL_SHIVER = 57949, - SPELL_CLONE_PLAYER = 57507, //casted on player during insanity - SPELL_INSANITY_PHASING_1 = 57508, - SPELL_INSANITY_PHASING_2 = 57509, - SPELL_INSANITY_PHASING_3 = 57510, - SPELL_INSANITY_PHASING_4 = 57511, - SPELL_INSANITY_PHASING_5 = 57512 -}; - -enum Creatures -{ - MOB_TWISTED_VISAGE = 30625 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1619030, - SAY_SLAY_1 = -1619031, - SAY_SLAY_2 = -1619032, - SAY_SLAY_3 = -1619033, - SAY_DEATH_1 = -1619034, - SAY_DEATH_2 = -1619035, - SAY_PHASE = -1619036 -}; - -enum Achievements -{ - ACHIEV_QUICK_DEMISE_START_EVENT = 20382, -}; - -struct boss_volazjAI : public ScriptedAI -{ - boss_volazjAI(Creature* pCreature) : ScriptedAI(pCreature),Summons(me) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 uiMindFlayTimer; - uint32 uiShadowBoltVolleyTimer; - uint32 uiShiverTimer; - uint32 insanityHandled; - SummonList Summons; - - // returns the percentage of health after taking the given damage. - uint32 GetHealthPct(uint32 damage) - { - if (damage > me->GetHealth()) - return 0; - return 100*(me->GetHealth()-damage)/me->GetMaxHealth(); - } - - void DamageTaken(Unit * /*pAttacker*/, uint32 &damage) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - damage = 0; - - if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)|| - (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33)) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_INSANITY, false); - } - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (spell->Id == SPELL_INSANITY) - { - // Not good target or too many players - if (pTarget->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4) - return; - // First target - start channel visual and set self as unnattackable - if (!insanityHandled) - { - // Channel visual - DoCast(me, INSANITY_VISUAL, true); - // Unattackable - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(true, UNIT_STAT_STUNNED); - } - // phase mask - pTarget->CastSpell(pTarget, SPELL_INSANITY_TARGET+insanityHandled, true); - // summon twisted party members for this target - Map::PlayerList const &players = me->GetMap()->GetPlayers(); - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player *plr = i->getSource(); - if (!plr || !plr->isAlive()) - continue; - // Summon clone - if (Unit *summon = me->SummonCreature(MOB_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,0)) - { - // required for correct visual - // Fixme: allow mirror image query to send other guid to get rid of minion status - summon->SetUInt64Value(UNIT_FIELD_CREATEDBY, plr->GetGUID()); - // clone - plr->CastSpell(summon, SPELL_CLONE_PLAYER, true); - // set phase - summon->SetPhaseMask((1<<(4+insanityHandled)),true); - } - } - ++insanityHandled; - } - } - - void ResetPlayersPhaseMask() - { - Map::PlayerList const &players = me->GetMap()->GetPlayers(); - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player* pPlayer = i->getSource(); - pPlayer->RemoveAurasDueToSpell(GetSpellForPhaseMask(pPlayer->GetPhaseMask())); - } - } - - void Reset() - { - uiMindFlayTimer = 8*IN_MILISECONDS; - uiShadowBoltVolleyTimer = 5*IN_MILISECONDS; - uiShiverTimer = 15*IN_MILISECONDS; - - if (pInstance) - { - pInstance->SetData(DATA_HERALD_VOLAZJ, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - } - - // Visible for all players in insanity - me->SetPhaseMask((1|16|32|64|128|256),true); - // Used for Insanity handling - insanityHandled = 0; - - ResetPlayersPhaseMask(); - - // Cleanup - Summons.DespawnAll(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - { - pInstance->SetData(DATA_HERALD_VOLAZJ, IN_PROGRESS); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - } - } - - void JustSummoned(Creature *summon) - { - Summons.Summon(summon); - } - - uint32 GetSpellForPhaseMask(uint32 phase) - { - uint32 spell = 0; - switch (phase) - { - case 16: - spell = SPELL_INSANITY_PHASING_1; - break; - case 32: - spell = SPELL_INSANITY_PHASING_2; - break; - case 64: - spell = SPELL_INSANITY_PHASING_3; - break; - case 128: - spell = SPELL_INSANITY_PHASING_4; - break; - case 256: - spell = SPELL_INSANITY_PHASING_5; - break; - } - return spell; - } - - void SummonedCreatureDespawn(Creature *summon) - { - uint32 phase= summon->GetPhaseMask(); - uint32 nextPhase = 0; - Summons.Despawn(summon); - - // Check if all summons in this phase killed - for (SummonList::const_iterator iter = Summons.begin(); iter != Summons.end(); ++iter) - { - if (Creature *visage = Unit::GetCreature(*me, *iter)) - { - // Not all are dead - if (phase == visage->GetPhaseMask()) - return; - else - nextPhase = visage->GetPhaseMask(); - } - } - - // Roll Insanity - uint32 spell = GetSpellForPhaseMask(phase); - uint32 spell2 = GetSpellForPhaseMask(nextPhase); - Map* pMap = me->GetMap(); - if (!pMap) - return; - - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->HasAura(spell)) - { - pPlayer->RemoveAurasDueToSpell(spell); - if (spell2) // if there is still some different mask cast spell for it - pPlayer->CastSpell(pPlayer, spell2, true); - } - } - } - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (insanityHandled) - { - if (!Summons.empty()) - return; - - insanityHandled = 0; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(false, UNIT_STAT_STUNNED); - me->RemoveAurasDueToSpell(INSANITY_VISUAL); - } - - if (uiMindFlayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MIND_FLAY); - uiMindFlayTimer = 20*IN_MILISECONDS; - } else uiMindFlayTimer -= diff; - - if (uiShadowBoltVolleyTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); - uiShadowBoltVolleyTimer = 5*IN_MILISECONDS; - } else uiShadowBoltVolleyTimer -= diff; - - if (uiShiverTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHIVER); - uiShiverTimer = 15*IN_MILISECONDS; - } else uiShiverTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH_1, me); - - if (pInstance) - pInstance->SetData(DATA_HERALD_VOLAZJ, DONE); - - Summons.DespawnAll(); - ResetPlayersPhaseMask(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_volazj(Creature* pCreature) -{ - return new boss_volazjAI (pCreature); -} - -void AddSC_boss_volazj() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_volazj"; - newscript->GetAI = &GetAI_boss_volazj; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp deleted file mode 100644 index eb8046f63cd..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Comment: Complete - BUT THE TRIGGER NEEDS DATA WHETHER THE PRISON OF TALDARAM IS OFFLINE ! - */ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -enum Yells -{ - TEXT_AGGRO = -1619000, - TEXT_SACRIFICE_1_1 = -1619001, - TEXT_SACRIFICE_1_2 = -1619002, - TEXT_SACRIFICE_2_1 = -1619003, - TEXT_SACRIFICE_2_2 = -1619004, - TEXT_SLAY_1 = -1619005, - TEXT_SLAY_2 = -1619006, - TEXT_SLAY_3 = -1619007, - TEXT_DEATH = -1619008, - TEXT_PREACHING_1 = -1619009, - TEXT_PREACHING_2 = -1619010, - TEXT_PREACHING_3 = -1619011, - TEXT_PREACHING_4 = -1619012, - TEXT_PREACHING_5 = -1619013 -}; - -enum Spells -{ - SPELL_SPHERE_VISUAL = 56075, - SPELL_GIFT_OF_THE_HERALD = 56219, - SPELL_CYCLONE_STRIKE = 56855, // Self - SPELL_CYCLONE_STRIKE_H = 60030, - SPELL_LIGHTNING_BOLT = 56891, // 40Y - SPELL_LIGHTNING_BOLT_H = 60032, // 40Y - SPELL_THUNDERSHOCK = 56926, // 30Y - SPELL_THUNDERSHOCK_H = 60029 // 30Y -}; - -enum Creatures -{ - NPC_JEDOGA_CONTROLLER = 30181 -}; - -const Position JedogaPosition[2] = -{ - {372.330994f, -705.278015f, -0.624178f, 5.427970f}, - {372.330994f, -705.278015f, -16.179716f, 5.427970f} -}; - -struct boss_jedoga_shadowseekerAI : public ScriptedAI -{ - boss_jedoga_shadowseekerAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - bFirstTime = true; - bPreDone = false; - } - - ScriptedInstance* pInstance; - - uint32 uiOpFerTimer; - uint32 uiCycloneTimer; - uint32 uiBoltTimer; - uint32 uiThunderTimer; - - bool bPreDone; - bool bOpFerok; - bool bOnGround; - bool bOpFerokFail; - bool bCanDown; - - bool bFirstTime; - - void Reset() - { - uiOpFerTimer = urand(15*IN_MILISECONDS,20*IN_MILISECONDS); - - uiCycloneTimer = 3*IN_MILISECONDS; - uiBoltTimer = 7*IN_MILISECONDS; - uiThunderTimer = 12*IN_MILISECONDS; - - bOpFerok = false; - bOpFerokFail = false; - bOnGround = false; - bCanDown = false; - - if (pInstance) - { - if (!bFirstTime) - pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, FAIL); - - pInstance->SetData64(DATA_PL_JEDOGA_TARGET, 0); - pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); - pInstance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); - } - MoveUp(); - - bFirstTime = false; - } - - void EnterCombat(Unit* who) - { - if (!pInstance || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) - return; - - DoScriptText(TEXT_AGGRO, me); - me->SetInCombatWithZone(); - pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* who) - { - if (!who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) - return; - - ScriptedAI::AttackStart(who); - } - - void KilledUnit(Unit* Victim) - { - if (!Victim || Victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(RAND(TEXT_SLAY_1, TEXT_SLAY_2, TEXT_SLAY_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(TEXT_DEATH, me); - if (pInstance) - pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, DONE); - } - - void MoveInLineOfSight(Unit* who) - { - if (!pInstance || !who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) - return; - - if (!bPreDone && who->GetTypeId() == TYPEID_PLAYER && me->GetDistance(who) < 100.0f) - { - DoScriptText(RAND(TEXT_PREACHING_1, TEXT_PREACHING_2, TEXT_PREACHING_3, TEXT_PREACHING_4, TEXT_PREACHING_5), me); - bPreDone = true; - } - - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS || !bOnGround) - return; - - if (!me->getVictim() && who->isTargetableForAttack() && me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - if (!me->getVictim()) - { - who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (me->GetMap()->IsDungeon()) - { - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } - } - } - } - - void MoveDown() - { - if (!pInstance) - return; - - bOpFerokFail = false; - - pInstance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 0); - me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); -/* me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); - me->SendMonsterMove(JedogaPosition[1], MOVEFLAG_JUMP, 0); - me->Relocate(JedogaPosition[1][0], JedogaPosition[1][1], JedogaPosition[1][2], JedogaPosition[1][3]); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); -*/ - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - - bOnGround = true; - - if (UpdateVictim()) - { - AttackStart(me->getVictim()); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - else - { - if (Unit* pTarget = Unit::GetUnit(*me, pInstance->GetData64(DATA_PL_JEDOGA_TARGET))) - { - AttackStart(pTarget); - pInstance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) - EnterCombat(pTarget); - } - else if (!me->isInCombat()) - EnterEvadeMode(); - } - } - - void MoveUp() - { - if (!pInstance) - return; - - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - - me->AttackStop(); - me->RemoveAllAuras(); - me->LoadCreaturesAddon(); - me->GetMotionMaster()->MovePoint(0, JedogaPosition[0]); -/* me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); - me->SendMonsterMove(JedogaPosition[0][0], JedogaPosition[0][1], JedogaPosition[0][2], 0, MOVEFLAG_JUMP, 0); - me->Relocate(JedogaPosition[0][0], JedogaPosition[0][1], JedogaPosition[0][2], JedogaPosition[0][3]); - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); -*/ - - pInstance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 1); - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) OpferRufen(); - - bOnGround = false; - uiOpFerTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } - - void OpferRufen() - { - if (!pInstance) - return; - - uint64 opfer = pInstance->GetData64(DATA_ADD_JEDOGA_INITIAND); - - if (opfer) - { - DoScriptText(RAND(TEXT_SACRIFICE_1_1, TEXT_SACRIFICE_1_2), me); - pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, opfer); - } else - bCanDown = true; - } - - void Opfern() - { - DoScriptText(RAND(TEXT_SACRIFICE_2_1, TEXT_SACRIFICE_2_2), me); - - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_GIFT_OF_THE_HERALD, false); - - bOpFerok = false; - bCanDown = true; - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && pInstance->GetData(DATA_ALL_INITIAND_DEAD)) - MoveDown(); - - if (bOpFerok && !bOnGround && !bCanDown) Opfern(); - - if (bOpFerokFail && !bOnGround && !bCanDown) - bCanDown = true; - - if (bCanDown) - { - MoveDown(); - bCanDown = false; - } - - if (bOnGround) - { - if (!UpdateVictim()) - return; - - if (uiCycloneTimer <= diff) - { - DoCast(me, SPELL_CYCLONE_STRIKE, false); - uiCycloneTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiCycloneTimer -= diff; - - if (uiBoltTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->CastSpell(pTarget, DUNGEON_MODE(SPELL_LIGHTNING_BOLT, SPELL_LIGHTNING_BOLT_H), false); - - uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiBoltTimer -= diff; - - if (uiThunderTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->CastSpell(pTarget, DUNGEON_MODE(SPELL_THUNDERSHOCK, SPELL_THUNDERSHOCK_H), false); - - uiThunderTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiThunderTimer -= diff; - - if (uiOpFerTimer <= diff) - MoveUp(); - else - uiOpFerTimer -= diff; - - DoMeleeAttackIfReady(); - } - } -}; - -struct mob_jedoga_initiandAI : public ScriptedAI -{ - mob_jedoga_initiandAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 bCheckTimer; - - bool bWalking; - - void Reset() - { - if (!pInstance) - return; - - bWalking = false; - bCheckTimer = 2*IN_MILISECONDS; - - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) - { - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - } - else - { - DoCast(me, SPELL_SPHERE_VISUAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - } - } - - void JustDied(Unit* Killer) - { - if (!Killer || !pInstance) return; - - if (bWalking) - { - Creature* boss = me->GetMap()->GetCreature(pInstance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); - if (boss && !CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok) CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = true; - - if (Killer->GetTypeId() == TYPEID_PLAYER) pInstance->SetData(DATA_INITIAND_KILLED, 1); - pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); - - bWalking = false; - } - if (Killer->GetTypeId() == TYPEID_PLAYER) pInstance->SetData64(DATA_PL_JEDOGA_TARGET, Killer->GetGUID()); - } - - void EnterCombat(Unit* who) - { - if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) return; - } - - void AttackStart(Unit* victim) - { - if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !victim) return; - - ScriptedAI::AttackStart(victim); - } - - void MoveInLineOfSight(Unit* who) - { - if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE || !pInstance) return; - - switch(uiPointId) - { - case 1: - { - Creature* boss = me->GetMap()->GetCreature(pInstance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); - if (boss) - { - CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok = true; - CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = false; - me->Kill(me); - } - } - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance && bCheckTimer <= diff) - { - if (me->GetGUID() == pInstance->GetData64(DATA_ADD_JEDOGA_OPFER) && !bWalking) - { - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - - float distance = me->GetDistance(JedogaPosition[1]); - - if (distance < 9.0f) - me->SetSpeed(MOVE_WALK, 0.5f, true); - else if (distance < 15.0f) - me->SetSpeed(MOVE_WALK, 0.75f, true); - else if (distance < 20.0f) - me->SetSpeed(MOVE_WALK, 1.0f, true); - - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); - bWalking = true; - } - if (!bWalking) - { - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && me->HasAura(SPELL_SPHERE_VISUAL)) - { - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - } - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS && !me->HasAura(SPELL_SPHERE_VISUAL)) - { - DoCast(me, SPELL_SPHERE_VISUAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - } - } - bCheckTimer = 2*IN_MILISECONDS; - } else bCheckTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -// ------------------------------------------------------------------------------------------------------------ -// Jedogas Aufseher - Entry: 30181 -// ------------------------------------------------------------------------------------------------------------ -enum AufseherSpell -{ - SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1 = 60342, - SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2 = 56312 -}; - -struct npc_jedogas_aufseher_triggerAI : public Scripted_NoMovementAI -{ - npc_jedogas_aufseher_triggerAI(Creature* c) : Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); -// c->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); -// c->setFaction(35); - bRemoved = false; - bRemoved2 = false; - bCasted = false; - bCasted2 = false; - } - - ScriptedInstance* pInstance; - - bool bRemoved; - bool bRemoved2; - bool bCasted; - bool bCasted2; - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*victim*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 /*diff*/) - { - if (!pInstance) - return; - - if (!bRemoved && me->GetPositionX() > 440.0f) - { - if (pInstance->GetData(DATA_PRINCE_TALDARAM_EVENT) == DONE) - { - me->InterruptNonMeleeSpells(true); - bRemoved = true; - return; - } - if (!bCasted) - { - DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1, false); - bCasted = true; - } - } - if (!bRemoved2 && me->GetPositionX() < 440.0f) - { - if (!bCasted2 && pInstance->GetData(DATA_JEDOGA_TRIGGER_SWITCH)) - { - DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2, false); - bCasted2 = true; - } - if (bCasted2 && !pInstance->GetData(DATA_JEDOGA_TRIGGER_SWITCH)) - { - me->InterruptNonMeleeSpells(true); - bCasted2 = false; - } - if (!bRemoved2 && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == DONE) - { - me->InterruptNonMeleeSpells(true); - bRemoved2 = true; - } - } - } -}; - -CreatureAI* GetAI_boss_jedoga_shadowseeker(Creature* pCreature) -{ - return new boss_jedoga_shadowseekerAI (pCreature); -} - -CreatureAI* GetAI_mob_jedoga_initiand(Creature* pCreature) -{ - return new mob_jedoga_initiandAI (pCreature); -} - -CreatureAI* GetAI_npc_jedogas_aufseher_trigger(Creature* pCreature) -{ - return new npc_jedogas_aufseher_triggerAI (pCreature); -} - -void AddSC_boss_jedoga_shadowseeker() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_jedoga_shadowseeker"; - newscript->GetAI = &GetAI_boss_jedoga_shadowseeker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_jedoga_initiand"; - newscript->GetAI = &GetAI_mob_jedoga_initiand; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jedogas_aufseher_trigger"; - newscript->GetAI = &GetAI_npc_jedogas_aufseher_trigger; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp deleted file mode 100644 index 93a66ccfbca..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -enum Spells -{ - SPELL_BLOODTHIRST = 55968, //Trigger Spell + add aura - SPELL_CONJURE_FLAME_SPHERE = 55931, - SPELL_FLAME_SPHERE_SUMMON_1 = 55895,// 1x 30106 - H_SPELL_FLAME_SPHERE_SUMMON_1 = 59511,// 1x 31686 - H_SPELL_FLAME_SPHERE_SUMMON_2 = 59512,// 1x 31687 - SPELL_FLAME_SPHERE_SPAWN_EFFECT = 55891, - SPELL_FLAME_SPHERE_VISUAL = 55928, - SPELL_FLAME_SPHERE_PERIODIC = 55926, - H_SPELL_FLAME_SPHERE_PERIODIC = 59508, - SPELL_FLAME_SPHERE_DEATH_EFFECT = 55947, - SPELL_BEAM_VISUAL = 60342, - SPELL_EMBRACE_OF_THE_VAMPYR = 55959, - H_SPELL_EMBRACE_OF_THE_VAMPYR = 59513, - SPELL_VANISH = 55964, - CREATURE_FLAME_SPHERE = 30106, - H_CREATURE_FLAME_SPHERE_1 = 31686, - H_CREATURE_FLAME_SPHERE_2 = 31687 -}; -enum Misc -{ - DATA_EMBRACE_DMG = 20000, - H_DATA_EMBRACE_DMG = 40000, - DATA_SPHERE_DISTANCE = 15 -}; -#define DATA_SPHERE_ANGLE_OFFSET 0.7 -#define DATA_GROUND_POSITION_Z 11.4 - -enum Yells -{ - SAY_AGGRO = -1619021, - SAY_SLAY_1 = -1619022, - SAY_SLAY_2 = -1619023, - SAY_DEATH = -1619024, - SAY_FEED_1 = -1619025, - SAY_FEED_2 = -1619026, - SAY_VANISH_1 = -1619027, - SAY_VANISH_2 = -1619028 -}; -enum CombatPhase -{ - NORMAL, - CASTING_FLAME_SPHERES, - JUST_VANISHED, - VANISHED, - FEEDING -}; -enum GameObjects -{ - GO_SPHERE1 = 193093, - GO_SPHERE2 = 193094 -}; - -struct boss_taldaramAI : public ScriptedAI -{ - boss_taldaramAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - uint32 uiBloodthirstTimer; - uint32 uiVanishTimer; - uint32 uiWaitTimer; - uint32 uiEmbraceTimer; - uint32 uiEmbraceTakenDamage; - uint32 uiFlamesphereTimer; - uint32 uiPhaseTimer; - - uint64 uiEmbraceTarget; - - CombatPhase Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - uiBloodthirstTimer = 10*IN_MILISECONDS; - uiVanishTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); - uiEmbraceTimer = 20*IN_MILISECONDS; - uiFlamesphereTimer = 5*IN_MILISECONDS; - uiEmbraceTakenDamage = 0; - Phase = NORMAL; - uiPhaseTimer = 0; - uiEmbraceTarget = 0; - if (pInstance) - pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, IN_PROGRESS); - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - if (uiPhaseTimer <= diff) - { - switch (Phase) - { - case CASTING_FLAME_SPHERES: - { - Creature* pSpheres[3]; - - //DoCast(me, SPELL_FLAME_SPHERE_SUMMON_1); - pSpheres[0] = DoSpawnCreature(CREATURE_FLAME_SPHERE, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); - Unit *pSphereTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pSphereTarget && pSpheres[0]) - { - float angle,x,y; - angle = pSpheres[0]->GetAngle(pSphereTarget); - x = pSpheres[0]->GetPositionX() + DATA_SPHERE_DISTANCE * cos(angle); - y = pSpheres[0]->GetPositionY() + DATA_SPHERE_DISTANCE * sin(angle); - pSpheres[0]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[0]->GetPositionZ()); - } - if (IsHeroic()) - { - //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_1); - pSpheres[1] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_1, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); - //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_2); - pSpheres[2] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_2, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); - if (pSphereTarget && pSpheres[1] && pSpheres[2]) - { - float angle,x,y; - angle = pSpheres[1]->GetAngle(pSphereTarget) + DATA_SPHERE_ANGLE_OFFSET; - x = pSpheres[1]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * cos(angle); - y = pSpheres[1]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * sin(angle); - pSpheres[1]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[1]->GetPositionZ()); - angle = pSpheres[2]->GetAngle(pSphereTarget) - DATA_SPHERE_ANGLE_OFFSET; - x = pSpheres[2]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * cos(angle); - y = pSpheres[2]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * sin(angle); - pSpheres[2]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[2]->GetPositionZ()); - } - } - - Phase = NORMAL; - uiPhaseTimer = 0; - break; - } - case JUST_VANISHED: - if (Unit *pEmbraceTarget = GetEmbraceTarget()) - { - me->GetMotionMaster()->Clear(); - me->SetSpeed(MOVE_WALK, 2.0f, true); - me->GetMotionMaster()->MoveChase(pEmbraceTarget); - } - Phase = VANISHED; - uiPhaseTimer = 1300; - break; - case VANISHED: - if (Unit *pEmbraceTarget = GetEmbraceTarget()) - DoCast(pEmbraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR); - me->GetMotionMaster()->Clear(); - me->SetSpeed(MOVE_WALK, 1.0f, true); - me->GetMotionMaster()->MoveChase(me->getVictim()); - Phase = FEEDING; - uiPhaseTimer = 20*IN_MILISECONDS; - break; - case FEEDING: - Phase = NORMAL; - uiPhaseTimer = 0; - uiEmbraceTarget = 0; - break; - case NORMAL: - if (uiBloodthirstTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BLOODTHIRST); - uiBloodthirstTimer = 10*IN_MILISECONDS; - } else uiBloodthirstTimer -= diff; - - if (uiFlamesphereTimer <= diff) - { - DoCast(me, SPELL_CONJURE_FLAME_SPHERE); - Phase = CASTING_FLAME_SPHERES; - uiPhaseTimer = 3*IN_MILISECONDS + diff; - uiFlamesphereTimer = 15*IN_MILISECONDS; - } else uiFlamesphereTimer -= diff; - - if (uiVanishTimer <= diff) - { - //Count alive players - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - // exclude pets & totems - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) - target_list.push_back(pTarget); - pTarget = NULL; - } - //He only vanishes if there are 3 or more alive players - if (target_list.size() > 2) - { - DoScriptText(RAND(SAY_VANISH_1,SAY_VANISH_2), me); - DoCast(me, SPELL_VANISH); - Phase = JUST_VANISHED; - uiPhaseTimer = 500; - if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - uiEmbraceTarget = pEmbraceTarget->GetGUID(); - - } - uiVanishTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); - } else uiVanishTimer -= diff; - - DoMeleeAttackIfReady(); - break; - } - } else uiPhaseTimer -= diff; - } - - void DamageTaken(Unit* /*done_by*/, uint32 &damage) - { - Unit* pEmbraceTarget = GetEmbraceTarget(); - - if (Phase == FEEDING && pEmbraceTarget && pEmbraceTarget->isAlive()) - { - uiEmbraceTakenDamage += damage; - if (uiEmbraceTakenDamage > DUNGEON_MODE(DATA_EMBRACE_DMG, H_DATA_EMBRACE_DMG)) - { - Phase = NORMAL; - uiPhaseTimer = 0; - uiEmbraceTarget = 0; - me->CastStop(); - } - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - Unit* pEmbraceTarget = GetEmbraceTarget(); - if (Phase == FEEDING && pEmbraceTarget && victim == pEmbraceTarget) - { - Phase = NORMAL; - uiPhaseTimer = 0; - uiEmbraceTarget = 0; - } - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - bool CheckSpheres() - { - if (!pInstance) - return false; - - uint64 uiSphereGuids[2]; - uiSphereGuids[0] = pInstance->GetData64(DATA_SPHERE1); - uiSphereGuids[1] = pInstance->GetData64(DATA_SPHERE2); - - for (uint8 i=0; i < 2; ++i) - { - GameObject *pSpheres = pInstance->instance->GetGameObject(uiSphereGuids[i]); - if (!pSpheres) - return false; - if (pSpheres->GetGoState() != GO_STATE_ACTIVE) - return false; - } - RemovePrison(); - return true; - } - - Unit* GetEmbraceTarget() - { - if (!uiEmbraceTarget) - return NULL; - - return Unit::GetUnit(*me, uiEmbraceTarget); - } - - void RemovePrison() - { - if (!pInstance) - return; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAurasDueToSpell(SPELL_BEAM_VISUAL); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation()); - uint64 prison_GUID = pInstance->GetData64(DATA_PRINCE_TALDARAM_PLATFORM); - pInstance->HandleGameObject(prison_GUID,true); - } -}; - -struct mob_taldaram_flamesphereAI : public ScriptedAI -{ - mob_taldaram_flamesphereAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiDespawnTimer; - ScriptedInstance* pInstance; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); - me->setFaction(16); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); - DoCast(me, SPELL_FLAME_SPHERE_VISUAL); - DoCast(me, SPELL_FLAME_SPHERE_SPAWN_EFFECT); - DoCast(me, SPELL_FLAME_SPHERE_PERIODIC); - uiDespawnTimer = 10*IN_MILISECONDS; - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void JustDied(Unit* /*who*/) - { - DoCast(me, SPELL_FLAME_SPHERE_DEATH_EFFECT); - } - - void UpdateAI(const uint32 diff) - { - if (uiDespawnTimer <= diff) - me->DisappearAndDie(); - else - uiDespawnTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_taldaram(Creature* pCreature) -{ - return new boss_taldaramAI (pCreature); -} - -CreatureAI* GetAI_mob_taldaram_flamesphere(Creature* pCreature) -{ - return new mob_taldaram_flamesphereAI (pCreature); -} - -bool GOHello_prince_taldaram_sphere(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - - Creature *pPrinceTaldaram = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_PRINCE_TALDARAM) : 0); - if (pPrinceTaldaram && pPrinceTaldaram->isAlive()) - { - // maybe these are hacks :( - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - switch(pGO->GetEntry()) - { - case GO_SPHERE1: pInstance->SetData(DATA_SPHERE1_EVENT,IN_PROGRESS); break; - case GO_SPHERE2: pInstance->SetData(DATA_SPHERE2_EVENT,IN_PROGRESS); break; - } - - CAST_AI(boss_taldaramAI, pPrinceTaldaram->AI())->CheckSpheres(); - } - return true; -} - -void AddSC_boss_taldaram() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_taldaram"; - newscript->GetAI = &GetAI_boss_taldaram; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_taldaram_flamesphere"; - newscript->GetAI = &GetAI_mob_taldaram_flamesphere; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "prince_taldaram_sphere"; - newscript->pGOHello = &GOHello_prince_taldaram_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp deleted file mode 100644 index 4e6e3ec8c9f..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -/* Ahn'kahet encounters: -0 - Elder Nadox -1 - Prince Taldaram -2 - Jedoga Shadowseeker -3 - Herald Volazj -4 - Amanitar (Heroic only) -*/ - -#define MAX_ENCOUNTER 5 - -enum Achievements -{ - ACHIEV_VOLUNTEER_WORK = 2056 -}; - -struct instance_ahnkahet : public ScriptedInstance -{ - instance_ahnkahet(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 Elder_Nadox; - uint64 Prince_Taldaram; - uint64 Jedoga_Shadowseeker; - uint64 Herald_Volazj; - uint64 Amanitar; - - uint64 Prince_TaldaramSpheres[2]; - uint64 Prince_TaldaramPlatform; - uint64 Prince_TaldaramGate; - - std::set InitiandGUIDs; - uint64 JedogaSacrifices; - uint64 JedogaTarget; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 spheres[2]; - - uint8 InitiandCnt, - switchtrigger, - initiandkilled; - - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - InitiandGUIDs.clear(); - - Elder_Nadox =0; - Prince_Taldaram =0; - Jedoga_Shadowseeker =0; - Herald_Volazj =0; - Amanitar =0; - - spheres[0] = NOT_STARTED; - spheres[1] = NOT_STARTED; - - InitiandCnt = 0; - switchtrigger = 0; - initiandkilled = 0; - JedogaSacrifices = 0; - JedogaTarget = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 29309: Elder_Nadox = pCreature->GetGUID(); break; - case 29308: Prince_Taldaram = pCreature->GetGUID(); break; - case 29310: Jedoga_Shadowseeker = pCreature->GetGUID(); break; - case 29311: Herald_Volazj = pCreature->GetGUID(); break; - case 30258: Amanitar = pCreature->GetGUID(); break; - case 30114: InitiandGUIDs.insert(pCreature->GetGUID()); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 193564: Prince_TaldaramPlatform = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) HandleGameObject(NULL,true,pGo); break; - case 193093: Prince_TaldaramSpheres[0] = pGo->GetGUID(); - if (spheres[0] == IN_PROGRESS) - { - pGo->SetGoState(GO_STATE_ACTIVE); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - else pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case 193094: Prince_TaldaramSpheres[1] = pGo->GetGUID(); - if (spheres[1] == IN_PROGRESS) - { - pGo->SetGoState(GO_STATE_ACTIVE); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - else pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case 192236: Prince_TaldaramGate = pGo->GetGUID(); // Web gate past Prince Taldaram - if (m_auiEncounter[1] == DONE)HandleGameObject(NULL,true,pGo);break; - } - } - - void SetData64(uint32 idx, uint64 guid) - { - switch(idx) - { - case DATA_ADD_JEDOGA_OPFER: JedogaSacrifices = guid; break; - case DATA_PL_JEDOGA_TARGET: JedogaTarget = guid; break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_ELDER_NADOX: return Elder_Nadox; - case DATA_PRINCE_TALDARAM: return Prince_Taldaram; - case DATA_JEDOGA_SHADOWSEEKER: return Jedoga_Shadowseeker; - case DATA_HERALD_VOLAZJ: return Herald_Volazj; - case DATA_AMANITAR: return Amanitar; - case DATA_SPHERE1: return Prince_TaldaramSpheres[0]; - case DATA_SPHERE2: return Prince_TaldaramSpheres[1]; - case DATA_PRINCE_TALDARAM_PLATFORM: return Prince_TaldaramPlatform; - case DATA_ADD_JEDOGA_INITIAND: - { - std::vector vInitiands; - vInitiands.clear(); - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (cr && cr->isAlive()) - vInitiands.push_back(*itr); - } - if (vInitiands.empty()) - return 0; - uint8 j = urand(0,vInitiands.size() -1); - return vInitiands[j]; - } - case DATA_ADD_JEDOGA_OPFER: return JedogaSacrifices; - case DATA_PL_JEDOGA_TARGET: return JedogaTarget; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_ELDER_NADOX_EVENT: m_auiEncounter[0] = data; break; - case DATA_PRINCE_TALDARAM_EVENT: - if (data == DONE) - HandleGameObject(Prince_TaldaramGate,true); - m_auiEncounter[1] = data; - break; - case DATA_JEDOGA_SHADOWSEEKER_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) - { - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (cr && cr->isAlive()) - { - cr->SetVisibility(VISIBILITY_OFF); - cr->setDeathState(JUST_DIED); - cr->RemoveCorpse(); - } - } - if (!initiandkilled && instance->IsHeroic()) - DoCompleteAchievement(ACHIEV_VOLUNTEER_WORK); - } - break; - case DATA_HERALD_VOLAZJ_EVENT: m_auiEncounter[3] = data; break; - case DATA_AMANITAR_EVENT: m_auiEncounter[4] = data; break; - case DATA_SPHERE1_EVENT: spheres[0] = data; break; - case DATA_SPHERE2_EVENT: spheres[1] = data; break; - case DATA_JEDOGA_TRIGGER_SWITCH: switchtrigger = data; break; - case DATA_INITIAND_KILLED: initiandkilled = data; break; - case DATA_JEDOGA_RESET_INITIANDS: - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (cr) - { - cr->Respawn(); - if (!cr->IsInEvadeMode()) cr->AI()->EnterEvadeMode(); - } - } - break; - } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_ELDER_NADOX_EVENT: return m_auiEncounter[0]; - case DATA_PRINCE_TALDARAM_EVENT: return m_auiEncounter[1]; - case DATA_JEDOGA_SHADOWSEEKER_EVENT: return m_auiEncounter[2]; - case DATA_HERALD_VOLAZJ: return m_auiEncounter[3]; - case DATA_AMANITAR_EVENT: return m_auiEncounter[4]; - case DATA_SPHERE1_EVENT: return spheres[0]; - case DATA_SPHERE2_EVENT: return spheres[1]; - case DATA_ALL_INITIAND_DEAD: - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (!cr || (cr && cr->isAlive())) return 0; - } - return 1; - case DATA_JEDOGA_TRIGGER_SWITCH: return switchtrigger; - case DATA_INITIAND_KILLED: return initiandkilled; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "A K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " - << spheres[0] << " " << spheres[1]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5, data6; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6; - - if (dataHead1 == 'A' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - spheres[0] = data5; - spheres[1] = data6; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_ahnkahet(Map* pMap) -{ - return new instance_ahnkahet(pMap); -} - -void AddSC_instance_ahnkahet() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_ahnkahet"; - newscript->GetInstanceData = &GetInstanceData_instance_ahnkahet; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/azjol_nerub.h b/src/server/scripts/northrend/azjol_nerub/azjol_nerub/azjol_nerub.h deleted file mode 100644 index 4113885b6f4..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/azjol_nerub.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_AZJOL_NERUB_H -#define DEF_AZJOL_NERUB_H - -enum Data64 -{ - DATA_KRIKTHIR_THE_GATEWATCHER, - DATA_HADRONOX, - DATA_ANUBARAK, - DATA_WATCHER_GASHRA, - DATA_WATCHER_SILTHIK, - DATA_WATCHER_NARJIL -}; -enum Data -{ - DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, - DATA_HADRONOX_EVENT, - DATA_ANUBARAK_EVENT -}; - -#endif diff --git a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp b/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp deleted file mode 100644 index 6de6578f7bb..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -//SQL: UPDATE creature_template SET mechanic_immune_mask = 1073741823 WHERE name like "anub'arak%"; - -enum Spells -{ - SPELL_CARRION_BEETLES = 53520, - SPELL_SUMMON_CARRION_BEETLES = 53521, - SPELL_LEECHING_SWARM = 53467, - SPELL_POUND = 53472, - SPELL_POUND_H = 59433, - SPELL_SUBMERGE = 53421, - SPELL_IMPALE_DMG = 53454, - SPELL_IMPALE_DMG_H = 59446, - SPELL_IMPALE_SHAKEGROUND = 53455, - SPELL_IMPALE_SPIKE = 53539, //this is not the correct visual effect - //SPELL_IMPALE_TARGET = 53458, -}; - -enum Creatures -{ - CREATURE_GUARDIAN = 29216, - CREATURE_VENOMANCER = 29217, - CREATURE_DATTER = 29213, - CREATURE_IMPALE_TARGET = 89, - DISPLAY_INVISIBLE = 11686 -}; - -// not in db -enum Yells -{ - SAY_INTRO = -1601010, - SAY_AGGRO = -1601000, - SAY_SLAY_1 = -1601001, - SAY_SLAY_2 = -1601002, - SAY_SLAY_3 = -1601003, - SAY_LOCUST_1 = -1601005, - SAY_LOCUST_2 = -1601006, - SAY_LOCUST_3 = -1601007, - SAY_SUBMERGE_1 = -1601008, - SAY_SUBMERGE_2 = -1601009, - SAY_DEATH = -1601004 -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 20381, -}; - -enum Phases -{ - PHASE_MELEE = 0, - PHASE_UNDERGROUND = 1, - IMPALE_PHASE_TARGET = 0, - IMPALE_PHASE_ATTACK = 1, - IMPALE_PHASE_DMG = 2 -}; - -const Position SpawnPoint[2] = -{ - { 550.7, 282.8, 224.3 }, - { 551.1, 229.4, 224.3 }, -}; - -const Position SpawnPointGuardian[2] = -{ - { 550.348633, 316.006805, 234.2947 }, - { 550.188660, 324.264557, 237.7412 }, -}; - -struct boss_anub_arakAI : public ScriptedAI -{ - boss_anub_arakAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - bool bChanneling; - bool bGuardianSummoned; - bool bVenomancerSummoned; - bool bDatterSummoned; - uint8 uiPhase; - uint32 uiUndergroundPhase; - uint32 uiCarrionBeetlesTimer; - uint32 uiLeechingSwarmTimer; - uint32 uiPoundTimer; - uint32 uiSubmergeTimer; - uint32 uiUndergroundTimer; - uint32 uiVenomancerTimer; - uint32 uiDatterTimer; - - uint32 uiImpaleTimer; - uint32 uiImpalePhase; - uint64 uiImpaleTarget; - - SummonList lSummons; - - void Reset() - { - uiCarrionBeetlesTimer = 8*IN_MILISECONDS; - uiLeechingSwarmTimer = 20*IN_MILISECONDS; - uiImpaleTimer = 9*IN_MILISECONDS; - uiPoundTimer = 15*IN_MILISECONDS; - - uiPhase = PHASE_MELEE; - uiUndergroundPhase = 0; - bChanneling = false; - uiImpalePhase = IMPALE_PHASE_TARGET; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->RemoveAura(SPELL_SUBMERGE); - - lSummons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_ANUBARAK_EVENT, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - Creature* DoSummonImpaleTarget(Unit *pTarget) - { - Position targetPos; - pTarget->GetPosition(&targetPos); - - if (TempSummon* pImpaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILISECONDS)) - { - uiImpaleTarget = pImpaleTarget->GetGUID(); - pImpaleTarget->SetReactState(REACT_PASSIVE); - pImpaleTarget->SetDisplayId(DISPLAY_INVISIBLE); - pImpaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - return pImpaleTarget; - } - - return NULL; - } - - void EnterCombat(Unit * /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - pInstance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - switch (uiPhase) - { - case PHASE_UNDERGROUND: - if (uiImpaleTimer <= diff) - { - switch(uiImpalePhase) - { - case IMPALE_PHASE_TARGET: - if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) - pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SHAKEGROUND, true); - uiImpaleTimer = 3*IN_MILISECONDS; - uiImpalePhase = IMPALE_PHASE_ATTACK; - } - break; - case IMPALE_PHASE_ATTACK: - if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) - { - pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SPIKE, false); - pImpaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND); - } - uiImpalePhase = IMPALE_PHASE_DMG; - uiImpaleTimer = 1*IN_MILISECONDS; - break; - case IMPALE_PHASE_DMG: - if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) - me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_IMPALE_DMG, SPELL_IMPALE_DMG_H), true); - uiImpalePhase = IMPALE_PHASE_TARGET; - uiImpaleTimer = 9*IN_MILISECONDS; - break; - } - } else uiImpaleTimer -= diff; - - if (!bGuardianSummoned) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Guardian = me->SummonCreature(CREATURE_GUARDIAN,SpawnPointGuardian[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Guardian->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Guardian); - } - } - bGuardianSummoned = true; - } - - if (!bVenomancerSummoned) - { - if (uiVenomancerTimer <= diff) - { - if (uiUndergroundPhase > 1) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Venomancer = me->SummonCreature(CREATURE_VENOMANCER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Venomancer->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Venomancer); - } - } - bVenomancerSummoned = true; - } - } else uiVenomancerTimer -= diff; - } - - if (!bDatterSummoned) - { - if (uiDatterTimer <= diff) - { - if (uiUndergroundPhase > 2) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Datter = me->SummonCreature(CREATURE_DATTER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Datter->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Datter); - } - } - bDatterSummoned = true; - } - } else uiDatterTimer -= diff; - } - - if (uiUndergroundTimer <= diff) - { - me->RemoveAura(SPELL_SUBMERGE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - uiPhase = PHASE_MELEE; - } else uiUndergroundTimer -= diff; - break; - - case PHASE_MELEE: - if (((uiUndergroundPhase == 0 && HealthBelowPct(75)) - || (uiUndergroundPhase == 1 && HealthBelowPct(50)) - || (uiUndergroundPhase == 2 && HealthBelowPct(25))) - && !me->hasUnitState(UNIT_STAT_CASTING)) - { - bGuardianSummoned = false; - bVenomancerSummoned = false; - bDatterSummoned = false; - - uiUndergroundTimer = 40*IN_MILISECONDS; - uiVenomancerTimer = 25*IN_MILISECONDS; - uiDatterTimer = 32*IN_MILISECONDS; - - uiImpalePhase = 0; - uiImpaleTimer = 9*IN_MILISECONDS; - - DoCast(me, SPELL_SUBMERGE, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - - uiPhase = PHASE_UNDERGROUND; - ++uiUndergroundPhase; - } - - if (bChanneling == true) - { - for (uint8 i = 0; i < 8; ++i) - DoCast(me->getVictim(), SPELL_SUMMON_CARRION_BEETLES, true); - bChanneling = false; - } - else if (uiCarrionBeetlesTimer <= diff) - { - bChanneling = true; - DoCastVictim(SPELL_CARRION_BEETLES); - uiCarrionBeetlesTimer = 25*IN_MILISECONDS; - } else uiCarrionBeetlesTimer -= diff; - - if (uiLeechingSwarmTimer <= diff) - { - DoCast(me, SPELL_LEECHING_SWARM, true); - uiLeechingSwarmTimer = 19*IN_MILISECONDS; - } else uiLeechingSwarmTimer -= diff; - - if (uiPoundTimer <= diff) - { - if (Unit *target = me->getVictim()) - { - if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) - me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_POUND, SPELL_POUND_H), false); - } - uiPoundTimer = 16.5*IN_MILISECONDS; - } else uiPoundTimer -= diff; - - DoMeleeAttackIfReady(); - break; - } - } - - void JustDied(Unit * /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - lSummons.DespawnAll(); - if (pInstance) - pInstance->SetData(DATA_ANUBARAK_EVENT, DONE); - } - - void KilledUnit(Unit *pVictim) - { - if (pVictim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustSummoned(Creature* summon) - { - lSummons.Summon(summon); - } -}; - -CreatureAI* GetAI_boss_anub_arak(Creature *pCreature) -{ - return new boss_anub_arakAI (pCreature); -} - -void AddSC_boss_anub_arak() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_anub_arak"; - newscript->GetAI = &GetAI_boss_anub_arak; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp b/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp deleted file mode 100644 index 0fc4e87d7c5..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* -* Comment: No Waves atm and the doors spells are crazy... -* -* When your group enters the main room (the one after the bridge), you will notice a group of 3 Nerubians. -* When you engage them, 2 more groups like this one spawn behind the first one - it is important to pull the first group back, -* so you don't aggro all 3. Hadronox will be under you, fighting Nerubians. -* -* This is the timed gauntlet - waves of non-elite spiders -* will spawn from the 3 doors located a little above the main room, and will then head down to fight Hadronox. After clearing the -* main room, it is recommended to just stay in it, kill the occasional non-elites that will attack you instead of the boss, and wait for -* Hadronox to make his way to you. When Hadronox enters the main room, she will web the doors, and no more non-elites will spawn. -*/ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -enum Spells -{ - SPELL_ACID_CLOUD = 53400, // Victim - SPELL_LEECH_POISON = 53030, // Victim - SPELL_PIERCE_ARMOR = 53418, // Victim - SPELL_WEB_GRAB = 57731, // Victim - SPELL_WEB_FRONT_DOORS = 53177, // Self - SPELL_WEB_SIDE_DOORS = 53185, // Self - H_SPELL_ACID_CLOUD = 59419, - H_SPELL_LEECH_POISON = 59417, - H_SPELL_WEB_GRAB = 59421 -}; - -struct boss_hadronoxAI : public ScriptedAI -{ - boss_hadronoxAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - fMaxDistance = 50.0f; - bFirstTime = true; - } - - ScriptedInstance* pInstance; - - uint32 uiAcidTimer; - uint32 uiLeechTimer; - uint32 uiPierceTimer; - uint32 uiGrabTimer; - uint32 uiDoorsTimer; - uint32 uiCheckDistanceTimer; - - bool bFirstTime; - - float fMaxDistance; - - void Reset() - { - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 9.0f); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 9.0f); - - uiAcidTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); - uiLeechTimer = urand(3*IN_MILISECONDS,9*IN_MILISECONDS); - uiPierceTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); - uiGrabTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); - uiDoorsTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - uiCheckDistanceTimer = 2*IN_MILISECONDS; - - if (pInstance && (pInstance->GetData(DATA_HADRONOX_EVENT) != DONE && !bFirstTime)) - pInstance->SetData(DATA_HADRONOX_EVENT, FAIL); - - bFirstTime = false; - } - - //when Hadronox kills any enemy (that includes a party member) she will regain 10% of her HP if the target had Leech Poison on - void KilledUnit(Unit* Victim) - { - // not sure if this aura check is correct, I think it is though - if (!Victim || !Victim->HasAura(DUNGEON_MODE(SPELL_LEECH_POISON, H_SPELL_LEECH_POISON)) || !me->isAlive()) - return; - - uint32 health = me->GetMaxHealth()/10; - - if ((me->GetHealth()+health) >= me->GetMaxHealth()) - me->SetHealth(me->GetMaxHealth()); - else - me->SetHealth(me->GetHealth()+health); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_HADRONOX_EVENT, DONE); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HADRONOX_EVENT, IN_PROGRESS); - me->SetInCombatWithZone(); - } - - void CheckDistance(float dist, const uint32 uiDiff) - { - if (!me->isInCombat()) - return; - - float x=0.0f, y=0.0f, z=0.0f; - me->GetRespawnCoord(x,y,z); - - if (uiCheckDistanceTimer <= uiDiff) - uiCheckDistanceTimer = 5*IN_MILISECONDS; - else - { - uiCheckDistanceTimer -= uiDiff; - return; - } - if (me->IsInEvadeMode() || !me->getVictim()) - return; - if (me->GetDistance(x,y,z) > dist) - EnterEvadeMode(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) return; - - // Without he comes up through the air to players on the bridge after krikthir if players crossing this bridge! - CheckDistance(fMaxDistance, diff); - - if (me->HasAura(SPELL_WEB_FRONT_DOORS) || me->HasAura(SPELL_WEB_SIDE_DOORS)) - { - if (IsCombatMovement()) - SetCombatMovement(false); - } - else if (!IsCombatMovement()) - SetCombatMovement(true); - - if (uiPierceTimer <= diff) - { - DoCast(me->getVictim(), SPELL_PIERCE_ARMOR); - uiPierceTimer = 8*IN_MILISECONDS; - } else uiPierceTimer -= diff; - - if (uiAcidTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ACID_CLOUD); - - uiAcidTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiAcidTimer -= diff; - - if (uiLeechTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_LEECH_POISON); - - uiLeechTimer = urand(11*IN_MILISECONDS,14*IN_MILISECONDS); - } else uiLeechTimer -= diff; - - if (uiGrabTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) // Draws all players (and attacking Mobs) to itself. - DoCast(pTarget, SPELL_WEB_GRAB); - - uiGrabTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiGrabTimer -= diff; - - if (uiDoorsTimer <= diff) - { - //DoCast(me, RAND(SPELL_WEB_FRONT_DOORS, SPELL_WEB_SIDE_DOORS)); - uiDoorsTimer = urand(30*IN_MILISECONDS,60*IN_MILISECONDS); - } else uiDoorsTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_hadronox(Creature* pCreature) -{ - return new boss_hadronoxAI (pCreature); -} - -void AddSC_boss_hadronox() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_hadronox"; - newscript->GetAI = &GetAI_boss_hadronox; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp deleted file mode 100644 index 4863bdcb032..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: Find in the future best timers and the event is not implemented. - */ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -enum Spells -{ - SPELL_MIND_FLAY = 52586, - H_SPELL_MIND_FLAY = 59367, - SPELL_CURSE_OF_FATIGUE = 52592, - H_SPELL_CURSE_OF_FATIGUE = 59368, - SPELL_FRENZY = 28747, //maybe 53361 - SPELL_SUMMON_SKITTERING_SWARMER = 52438, //AOE Effect 140, maybe 52439 - SPELL_SUMMON_SKITTERING_SWARMER_1 = 52439, //Summon 3x 28735 - H_SPELL_ACID_SPLASH = 59363, - SPELL_ACID_SPLASH = 52446, - SPELL_CHARGE = 16979,//maybe is another spell - SPELL_BACKSTAB = 52540, - SPELL_SHADOW_BOLT = 52534, - H_SPELL_SHADOW_BOLT = 59357, - SPELL_SHADOW_NOVA = 52535, - H_SPELL_SHADOW_NOVA = 59358, - SPELL_STRIKE = 52532, - SPELL_CLEAVE = 49806, - SPELL_ENRAGE = 52470, - SPELL_INFECTED_BITE = 52469, - H_SPELL_INFECTED_BITE = 59364, - SPELL_WEB_WRAP = 52086,//the spell is not working properly - SPELL_BLINDING_WEBS = 52524, - H_SPELL_BLINDING_WEBS = 59365, - SPELL_POSION_SPRAY = 52493, - H_SPELL_POSION_SPRAY = 59366 -}; - -enum Mobs -{ - MOB_SKITTERING_SWARMER = 28735, - MOB_SKITTERING_SWARMER_CONTROLLER = 32593, - MOB_SKITTERING_INFECTIOR = 28736 -}; - -enum Yells -{ - SAY_AGGRO = -1601011, - SAY_SLAY_1 = -1601012, - SAY_SLAY_2 = -1601013, - SAY_DEATH = -1601014, - //Not in db - SAY_SEND_GROUP_1 = -1601020, - SAY_SEND_GROUP_2 = -1601021, - SAY_SEND_GROUP_3 = -1601022, - SAY_SWARM_1 = -1601015, - SAY_SWARM_2 = -1601016, - SAY_PREFIGHT_1 = -1601017, - SAY_PREFIGHT_2 = -1601018, - SAY_PREFIGHT_3 = -1601019 -}; - -enum Misc -{ - ACHIEV_WATH_HIM_DIE = 1296 -}; - -const Position SpawnPoint[] = -{ - { 566.164, 682.087, 769.079, 2.21657 }, - { 529.042, 706.941, 777.298, 1.0821 }, - { 489.975, 671.239, 772.131, 0.261799 }, - { 488.556, 692.95, 771.764, 4.88692 }, - { 553.34, 640.387, 777.419, 1.20428 }, - { 517.486, 706.398, 777.335, 5.35816 }, - { 504.01, 637.693, 777.479, 0.506145 }, - { 552.625, 706.408, 777.177, 3.4383 } -}; -struct boss_krik_thirAI : public ScriptedAI -{ - boss_krik_thirAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiMindFlayTimer; - uint32 uiCurseFatigueTimer; - uint32 uiSummonTimer; - - void Reset() - { - uiMindFlayTimer = 15*IN_MILISECONDS; - uiCurseFatigueTimer = 12*IN_MILISECONDS; - - if (pInstance) - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - Summon(); - uiSummonTimer = 15*IN_MILISECONDS; - - if (pInstance) - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, IN_PROGRESS); - } - - void Summon() - { - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiSummonTimer <= diff) - { - Summon(); - uiSummonTimer = 15*IN_MILISECONDS; - } else uiSummonTimer -= diff; - - if (uiMindFlayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MIND_FLAY); - uiMindFlayTimer = 15*IN_MILISECONDS; - } else uiMindFlayTimer -= diff; - - if (uiCurseFatigueTimer <= diff) - { - //WowWiki say "Curse of Fatigue-Kirk'thir will cast Curse of Fatigue on 2-3 targets periodically." - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - Unit *pTarget_1 = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - - DoCast(pTarget, SPELL_CURSE_OF_FATIGUE); - DoCast(pTarget_1, SPELL_CURSE_OF_FATIGUE); - - uiCurseFatigueTimer = 10*IN_MILISECONDS; - } else uiCurseFatigueTimer -= diff; - - if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10)) - DoCast(me, SPELL_FRENZY, true); - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DONE); - //Achievement: Watch him die - Creature *pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_GASHRA)); - if (!pAdd || !pAdd->isAlive()) - return; - - pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_SILTHIK)); - if (!pAdd || !pAdd->isAlive()) - return; - - pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_NARJIL)); - if (!pAdd || !pAdd->isAlive()) - return; - - pInstance->DoCompleteAchievement(ACHIEV_WATH_HIM_DIE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustSummoned(Creature* summoned) - { - summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); - } -}; - -struct npc_skittering_infectorAI : public ScriptedAI -{ - npc_skittering_infectorAI(Creature *c) : ScriptedAI(c) {} - - void JustDied(Unit* /*killer*/) - { - //The spell is not working propperly - DoCast(me->getVictim(),SPELL_ACID_SPLASH, true); - } - -}; - -struct npc_anub_ar_skirmisherAI : public ScriptedAI -{ - npc_anub_ar_skirmisherAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiChargeTimer; - uint32 uiBackstabTimer; - - void Reset() - { - uiChargeTimer = 11*IN_MILISECONDS; - uiBackstabTimer = 7*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiChargeTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoResetThreat(); - me->AddThreat(pTarget,1.0f); - DoCast(pTarget, SPELL_CHARGE, true); - } - uiChargeTimer = 15*IN_MILISECONDS; - } else uiChargeTimer -= diff; - - if (uiBackstabTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BACKSTAB); - uiBackstabTimer = 12*IN_MILISECONDS; - } else uiBackstabTimer -= diff; - - DoMeleeAttackIfReady(); - - } -}; - -struct npc_anub_ar_shadowcasterAI : public ScriptedAI -{ - npc_anub_ar_shadowcasterAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiShadowBoltTimer; - uint32 uiShadowNovaTimer; - - void Reset() - { - uiShadowBoltTimer = 6*IN_MILISECONDS; - uiShadowNovaTimer = 15*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiShadowBoltTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SHADOW_BOLT, true); - uiShadowBoltTimer = 15*IN_MILISECONDS; - } else uiShadowBoltTimer -= diff; - - if (uiShadowNovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_NOVA, true); - uiShadowNovaTimer = 17*IN_MILISECONDS; - } else uiShadowNovaTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_anub_ar_warriorAI : public ScriptedAI -{ - npc_anub_ar_warriorAI(Creature *c) : ScriptedAI(c){} - - uint32 uiCleaveTimer; - uint32 uiStrikeTimer; - - void Reset() - { - uiCleaveTimer = 11*IN_MILISECONDS; - uiStrikeTimer = 6*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STRIKE, true); - uiStrikeTimer = 15*IN_MILISECONDS; - } else uiStrikeTimer -= diff; - - if (uiCleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE, true); - uiCleaveTimer = 17*IN_MILISECONDS; - } else uiCleaveTimer -= diff; - - DoMeleeAttackIfReady(); - - } - -}; - -struct npc_watcher_gashraAI : public ScriptedAI -{ - npc_watcher_gashraAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - } - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_ENRAGE, true); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - uiWebWrapTimer = 17*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 15*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_watcher_narjilAI : public ScriptedAI -{ - npc_watcher_narjilAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - uint32 uiBindingWebsTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - uiBindingWebsTimer = 17*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - uiWebWrapTimer = 15*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 11*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - if (uiBindingWebsTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BLINDING_WEBS, true); - uiBindingWebsTimer = 17*IN_MILISECONDS; - } else uiBindingWebsTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_watcher_silthikAI : public ScriptedAI -{ - npc_watcher_silthikAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - uint32 uiPoisonSprayTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - uiPoisonSprayTimer = 15*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - - uiWebWrapTimer = 15*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 15*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - if (uiPoisonSprayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POSION_SPRAY, true); - uiPoisonSprayTimer = 17*IN_MILISECONDS; - } else uiPoisonSprayTimer -= diff; - - DoMeleeAttackIfReady(); - - } -}; - -CreatureAI* GetAI_boss_krik_thir(Creature* pCreature) -{ - return new boss_krik_thirAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_skirmisher (Creature* pCreature) -{ - return new npc_anub_ar_skirmisherAI (pCreature); -} - -CreatureAI* GetAI_npc_skittering_infector (Creature* pCreature) -{ - return new npc_skittering_infectorAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_shadowcaster (Creature* pCreature) -{ - return new npc_anub_ar_shadowcasterAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_warrior (Creature* pCreature) -{ - return new npc_anub_ar_warriorAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_gashra (Creature* pCreature) -{ - return new npc_watcher_gashraAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_narjil (Creature* pCreature) -{ - return new npc_watcher_narjilAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_silthik (Creature* pCreature) -{ - return new npc_watcher_silthikAI (pCreature); -} - -void AddSC_boss_krik_thir() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_krik_thir"; - newscript->GetAI = &GetAI_boss_krik_thir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_skittering_infector"; - newscript->GetAI = &GetAI_npc_skittering_infector; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_skirmisher"; - newscript->GetAI = &GetAI_npc_anub_ar_skirmisher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_shadowcaster"; - newscript->GetAI = &GetAI_npc_anub_ar_shadowcaster; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_gashra"; - newscript->GetAI = &GetAI_npc_watcher_gashra; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_warrior"; - newscript->GetAI = &GetAI_npc_anub_ar_warrior; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_silthik"; - newscript->GetAI = &GetAI_npc_watcher_silthik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_narjil"; - newscript->GetAI = &GetAI_npc_watcher_narjil; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp b/src/server/scripts/northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp deleted file mode 100644 index d12dbd604ba..00000000000 --- a/src/server/scripts/northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -#define MAX_ENCOUNTER 3 - -/* Azjol Nerub encounters: -0 - Krik'thir the Gatewatcher -1 - Hadronox -2 - Anub'arak -*/ - -struct instance_azjol_nerub : public ScriptedInstance -{ - instance_azjol_nerub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiKrikthir; - uint64 uiHadronox; - uint64 uiAnubarak; - uint64 uiWatcherGashra; - uint64 uiWatcherSilthik; - uint64 uiWatcherNarjil; - uint64 uiAnubarakDoor[3]; - - uint64 uiKrikthirDoor; - - uint32 auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&auiEncounter, 0, sizeof(auiEncounter)); - memset(&uiAnubarakDoor, 0, sizeof(uiAnubarakDoor)); - - uiKrikthir = 0; - uiHadronox = 0; - uiAnubarak = 0; - uiWatcherGashra = 0; - uiWatcherSilthik = 0; - uiWatcherNarjil = 0; - uiKrikthirDoor = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 28684: uiKrikthir = pCreature->GetGUID(); break; - case 28921: uiHadronox = pCreature->GetGUID(); break; - case 29120: uiAnubarak = pCreature->GetGUID(); break; - case 28730: uiWatcherGashra = pCreature->GetGUID(); break; - case 28731: uiWatcherSilthik = pCreature->GetGUID(); break; - case 28729: uiWatcherNarjil = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch (pGo->GetEntry()) - { - case 192395: - uiKrikthirDoor = pGo->GetGUID(); - if (auiEncounter[0] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 192396: - uiAnubarakDoor[0] = pGo->GetGUID(); - break; - case 192397: - uiAnubarakDoor[1] = pGo->GetGUID(); - break; - case 192398: - uiAnubarakDoor[2] = pGo->GetGUID(); - break; - } - } - - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_KRIKTHIR_THE_GATEWATCHER: return uiKrikthir; - case DATA_HADRONOX: return uiHadronox; - case DATA_ANUBARAK: return uiAnubarak; - case DATA_WATCHER_GASHRA: return uiWatcherGashra; - case DATA_WATCHER_SILTHIK: return uiWatcherSilthik; - case DATA_WATCHER_NARJIL: return uiWatcherNarjil; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: - auiEncounter[0] = data; - if (data == DONE) - HandleGameObject(uiKrikthirDoor,true); - break; - case DATA_HADRONOX_EVENT: - auiEncounter[1] = data; - break; - case DATA_ANUBARAK_EVENT: - auiEncounter[2] = data; - if (data == IN_PROGRESS) - for (uint8 i = 0; i < 3; ++i) - HandleGameObject(uiAnubarakDoor[i], false); - else if (data == NOT_STARTED || data == DONE) - for (uint8 i = 0; i < 3; ++i) - HandleGameObject(uiAnubarakDoor[i], true); - break; - } - - if (data == DONE) - { - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: return auiEncounter[0]; - case DATA_HADRONOX_EVENT: return auiEncounter[1]; - case DATA_ANUBARAK_EVENT: return auiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "A N " << auiEncounter[0] << " " << auiEncounter[1] << " " - << auiEncounter[2]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0,data1,data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'A' && dataHead2 == 'N') - { - auiEncounter[0] = data0; - auiEncounter[1] = data1; - auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (auiEncounter[i] == IN_PROGRESS) - auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_azjol_nerub(Map* pMap) -{ - return new instance_azjol_nerub(pMap); -} - -void AddSC_instance_azjol_nerub() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_azjol_nerub"; - newscript->GetInstanceData = &GetInstanceData_instance_azjol_nerub; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/borean_tundra.cpp b/src/server/scripts/northrend/borean_tundra.cpp deleted file mode 100644 index 19d82dc9044..00000000000 --- a/src/server/scripts/northrend/borean_tundra.cpp +++ /dev/null @@ -1,2323 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Borean_Tundra -SD%Complete: 100 -SDComment: Quest support: 11708. Taxi vendors. -SDCategory: Borean Tundra -EndScriptData */ - -/* ContentData -npc_iruk -npc_corastrasza -npc_jenny -npc_sinkhole_kill_credit -npc_khunok_the_behemoth -npc_scourge_prisoner -mob_nerubar_victim -npc_keristrasza -npc_nesingwary_trapper -npc_lurgglbr -npc_nexus_drake_hatchling -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "ScriptedFollowerAI.h" - -/*###### -## npc_sinkhole_kill_credit -######*/ - -enum eSinkhole -{ - SPELL_SET_CART = 46797, - SPELL_EXPLODE_CART = 46799, - SPELL_SUMMON_CART = 46798, - SPELL_SUMMON_WORM = 46800, -}; - -struct npc_sinkhole_kill_creditAI : public ScriptedAI -{ - npc_sinkhole_kill_creditAI(Creature* c) : ScriptedAI(c){} - - uint32 uiPhaseTimer; - uint8 Phase; - uint64 casterGuid; - - void Reset() - { - uiPhaseTimer = 500; - Phase = 0; - casterGuid = 0; - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (Phase) - return; - - if (spell->Id == SPELL_SET_CART && caster->GetTypeId() == TYPEID_PLAYER - && CAST_PLR(caster)->GetQuestStatus(11897) == QUEST_STATUS_INCOMPLETE) - { - Phase = 1; - casterGuid = caster->GetGUID(); - } - } - - void EnterCombat(Unit* /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (!Phase) - return; - - if (uiPhaseTimer <= diff) - { - switch (Phase) - { - case 1: - DoCast(me, SPELL_EXPLODE_CART, true); - DoCast(me, SPELL_SUMMON_CART, true); - if (GameObject* cart = me->FindNearestGameObject(188160,3)) - cart->SetUInt32Value(GAMEOBJECT_FACTION, 14); - uiPhaseTimer = 3000; - Phase = 2; - break; - case 2: - if (GameObject* cart = me->FindNearestGameObject(188160,3)) - cart->UseDoorOrButton(); - DoCast(me, SPELL_EXPLODE_CART, true); - uiPhaseTimer = 3000; - Phase = 3; - break; - case 3: - DoCast(me, SPELL_EXPLODE_CART, true); - uiPhaseTimer = 2000; - Phase = 4; - case 5: - DoCast(me, SPELL_SUMMON_WORM, true); - if (Unit* worm = me->FindNearestCreature(26250, 3)) - { - worm->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - worm->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); - } - uiPhaseTimer = 1000; - Phase = 6; - break; - case 6: - DoCast(me, SPELL_EXPLODE_CART, true); - if (Unit* worm = me->FindNearestCreature(26250, 3)) - { - me->Kill(worm); - worm->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - uiPhaseTimer = 2000; - Phase = 7; - break; - case 7: - DoCast(me, SPELL_EXPLODE_CART, true); - if (Player *caster = Unit::GetPlayer(casterGuid)) - caster->KilledMonster(me->GetCreatureInfo(),me->GetGUID()); - uiPhaseTimer = 5000; - Phase = 8; - break; - case 8: - EnterEvadeMode(); - break; - } - } else uiPhaseTimer -= diff; - - } - -}; - -CreatureAI* GetAI_npc_sinkhole_kill_credit(Creature* pCreature) -{ - return new npc_sinkhole_kill_creditAI(pCreature); -} - -/*###### -## npc_khunok_the_behemoth -######*/ - -struct npc_khunok_the_behemothAI : public ScriptedAI -{ - npc_khunok_the_behemothAI(Creature *c) : ScriptedAI(c) {} - - void MoveInLineOfSight(Unit *who) - { - ScriptedAI::MoveInLineOfSight(who); - - if (who->GetTypeId() != TYPEID_UNIT) - return; - - if (who->GetEntry() == 25861 && me->IsWithinDistInMap(who, 10.0f)) - { - if (Unit *owner = who->GetOwner()) - { - if (owner->GetTypeId() == TYPEID_PLAYER) - { - owner->CastSpell(owner, 46231, true); - CAST_CRE(who)->ForcedDespawn(); - } - } - } - } -}; - -CreatureAI* GetAI_npc_khunok_the_behemoth(Creature* pCreature) -{ - return new npc_khunok_the_behemothAI(pCreature); -} - -/*###### -## npc_keristrasza -######*/ - -enum eKeristrasza -{ - SPELL_TELEPORT_TO_SARAGOSA = 46772 -}; - -#define GOSSIP_HELLO_KERI "I am prepared to face Saragosa!" - -bool GossipHello_npc_keristrasza(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(11957) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KERI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_keristrasza(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_TO_SARAGOSA, true); - } - - return true; -} - -/*###### -## npc_corastrasza -######*/ - -#define GOSSIP_ITEM_C_1 "I... I think so..." - -enum eCorastrasza -{ - SPELL_SUMMON_WYRMREST_SKYTALON = 61240, - SPELL_WYRMREST_SKYTALON_RIDE_PERIODIC = 61244, - - QUEST_ACES_HIGH_DAILY = 13414, - QUEST_ACES_HIGH = 13413 -}; - -bool GossipHello_npc_corastrasza(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_ACES_HIGH) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_ACES_HIGH_DAILY) == QUEST_STATUS_INCOMPLETE) //It's the same dragon for both quests. - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_C_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_corastrasza(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - pPlayer->CastSpell(pPlayer, SPELL_SUMMON_WYRMREST_SKYTALON, true); - pPlayer->CastSpell(pPlayer, SPELL_WYRMREST_SKYTALON_RIDE_PERIODIC, true); - - } - - return true; -} - -/*###### -## npc_iruk -######*/ - -#define GOSSIP_ITEM_I "" - -enum eIruk -{ - QUEST_SPIRITS_WATCH_OVER_US = 11961, - SPELL_CREATURE_TOTEM_OF_ISSLIRUK = 46816, - GOSSIP_TEXT_I = 12585 -}; - -bool GossipHello_npc_iruk(Player* pPlayer, Creature* pCreature) -{ - - if (pPlayer->GetQuestStatus(QUEST_SPIRITS_WATCH_OVER_US) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_I, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_I, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_iruk(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CastSpell(pPlayer, SPELL_CREATURE_TOTEM_OF_ISSLIRUK, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - - } - return true; -} -/*###### -## mob_nerubar_victim -######*/ - -#define WARSONG_PEON 25270 - -const uint32 nerubarVictims[3] = -{ - 45526, 45527, 45514 -}; -struct mob_nerubar_victimAI : public ScriptedAI -{ - mob_nerubar_victimAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void JustDied(Unit* Killer) - { - if (Killer->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(Killer)->GetQuestStatus(11611) == QUEST_STATUS_INCOMPLETE) - { - uint8 uiRand = urand(0,99); - if (uiRand < 25) - { - Killer->CastSpell(me,45532,true); - CAST_PLR(Killer)->KilledMonsterCredit(WARSONG_PEON, 0); - } - else if (uiRand < 75) - Killer->CastSpell(me, nerubarVictims[urand(0,2)], true); - } - } - } -}; -CreatureAI* GetAI_mob_nerubar_victim(Creature *pCreature) -{ - return new mob_nerubar_victimAI (pCreature); -} -/*###### -## npc_scourge_prisoner -######*/ - -enum eScourgePrisoner -{ - GO_SCOURGE_CAGE = 187867 -}; - -struct npc_scourge_prisonerAI : public ScriptedAI -{ - npc_scourge_prisonerAI(Creature* pCreature) : ScriptedAI (pCreature){} - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - - if (GameObject* pGO = me->FindNearestGameObject(GO_SCOURGE_CAGE,5.0f)) - if (pGO->GetGoState() == GO_STATE_ACTIVE) - pGO->SetGoState(GO_STATE_READY); - } - -}; -CreatureAI* GetAI_npc_scourge_prisoner(Creature* pCreature) -{ - return new npc_scourge_prisonerAI(pCreature); -} - -/*###### -## npc_jenny -######*/ -enum eJenny -{ - QUEST_LOADER_UP = 11881, - - NPC_FEZZIX_GEARTWIST = 25849, - NPC_JENNY = 25969, - - SPELL_GIVE_JENNY_CREDIT = 46358, - SPELL_CRATES_CARRIED = 46340, - SPELL_DROP_CRATE = 46342 -}; - -struct npc_jennyAI : public ScriptedAI -{ - npc_jennyAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - bool setCrateNumber; - - void Reset() - { - if (!setCrateNumber) - setCrateNumber = true; - - me->SetReactState(REACT_PASSIVE); - - switch (CAST_PLR(me->GetOwner())->GetTeamId()) - { - case TEAM_ALLIANCE: - me->setFaction(FACTION_ESCORT_A_NEUTRAL_ACTIVE); - break; - default: - case TEAM_HORDE: - me->setFaction(FACTION_ESCORT_H_NEUTRAL_ACTIVE); - break; - } - } - - void DamageTaken(Unit* /*pDone_by*/, uint32& /*uiDamage*/) - { - DoCast(me, SPELL_DROP_CRATE, true); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (setCrateNumber) - { - me->AddAura(SPELL_CRATES_CARRIED,me); - setCrateNumber = false; - } - - if (!setCrateNumber && !me->HasAura(SPELL_CRATES_CARRIED)) - me->DisappearAndDie(); - - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_npc_jenny(Creature *pCreature) -{ - return new npc_jennyAI (pCreature); -} - -/*###### -## npc_fezzix_geartwist -######*/ - -struct npc_fezzix_geartwistAI : public ScriptedAI -{ - npc_fezzix_geartwistAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - void MoveInLineOfSight(Unit* pWho) - { - ScriptedAI::MoveInLineOfSight(pWho); - - if (pWho->GetTypeId() != TYPEID_UNIT) - return; - - if (pWho->GetEntry() == NPC_JENNY && me->IsWithinDistInMap(pWho, 10.0f)) - { - if (Unit* pOwner = pWho->GetOwner()) - { - if (pOwner->GetTypeId() == TYPEID_PLAYER) - { - if (pWho->HasAura(SPELL_CRATES_CARRIED)) - { - pOwner->CastSpell(pOwner, SPELL_GIVE_JENNY_CREDIT, true); // Maybe is not working. - CAST_PLR(pOwner)->CompleteQuest(QUEST_LOADER_UP); - CAST_CRE(pWho)->DisappearAndDie(); - } - } - } - } - } -}; - -CreatureAI* GetAI_npc_fezzix_geartwist(Creature* pCreature) -{ - return new npc_fezzix_geartwistAI(pCreature); -} - -/*###### -## npc_nesingwary_trapper -######*/ - -enum eNesingwaryTrapper -{ - GO_HIGH_QUALITY_FUR = 187983, - - GO_CARIBOU_TRAP_1 = 187982, - GO_CARIBOU_TRAP_2 = 187995, - GO_CARIBOU_TRAP_3 = 187996, - GO_CARIBOU_TRAP_4 = 187997, - GO_CARIBOU_TRAP_5 = 187998, - GO_CARIBOU_TRAP_6 = 187999, - GO_CARIBOU_TRAP_7 = 188000, - GO_CARIBOU_TRAP_8 = 188001, - GO_CARIBOU_TRAP_9 = 188002, - GO_CARIBOU_TRAP_10 = 188003, - GO_CARIBOU_TRAP_11 = 188004, - GO_CARIBOU_TRAP_12 = 188005, - GO_CARIBOU_TRAP_13 = 188006, - GO_CARIBOU_TRAP_14 = 188007, - GO_CARIBOU_TRAP_15 = 188008, - - SPELL_TRAPPED = 46104, -}; - -#define CaribouTrapsNum 15 -const uint32 CaribouTraps[CaribouTrapsNum] = -{ - GO_CARIBOU_TRAP_1, GO_CARIBOU_TRAP_2, GO_CARIBOU_TRAP_3, GO_CARIBOU_TRAP_4, GO_CARIBOU_TRAP_5, - GO_CARIBOU_TRAP_6, GO_CARIBOU_TRAP_7, GO_CARIBOU_TRAP_8, GO_CARIBOU_TRAP_9, GO_CARIBOU_TRAP_10, - GO_CARIBOU_TRAP_11, GO_CARIBOU_TRAP_12, GO_CARIBOU_TRAP_13, GO_CARIBOU_TRAP_14, GO_CARIBOU_TRAP_15, -}; -//#define SAY_NESINGWARY_1 -1571008 - -struct npc_nesingwary_trapperAI : public ScriptedAI -{ - npc_nesingwary_trapperAI(Creature *c) : ScriptedAI(c) { c->SetVisibility(VISIBILITY_OFF); } - - uint64 go_caribouGUID; - uint8 Phase; - uint32 uiPhaseTimer; - - void Reset() - { - me->SetVisibility(VISIBILITY_OFF); - uiPhaseTimer = 2500; - Phase = 1; - go_caribouGUID = 0; - } - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void JustDied(Unit * /*who*/) - { - if (GameObject *go_caribou = me->GetMap()->GetGameObject(go_caribouGUID)) - go_caribou->SetLootState(GO_JUST_DEACTIVATED); - - if (TempSummon *summon = me->ToTempSummon()) - if (summon->isSummon()) - if (Unit *pTemp = summon->GetSummoner()) - if (pTemp->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(pTemp)->KilledMonsterCredit(me->GetEntry(),0); - - if (GameObject *go_caribou = me->GetMap()->GetGameObject(go_caribouGUID)) - go_caribou->SetGoState(GO_STATE_READY); - } - - void UpdateAI(const uint32 diff) - { - if (uiPhaseTimer <= diff) - { - switch (Phase) - { - case 1: - me->SetVisibility(VISIBILITY_ON); - uiPhaseTimer = 2000; - Phase = 2; - break; - - case 2: - if (GameObject *go_fur = me->FindNearestGameObject(GO_HIGH_QUALITY_FUR, 11.0f)) - me->GetMotionMaster()->MovePoint(0, go_fur->GetPositionX(), go_fur->GetPositionY(), go_fur->GetPositionZ()); - uiPhaseTimer = 1500; - Phase = 3; - break; - case 3: - //DoScriptText(SAY_NESINGWARY_1, me); - uiPhaseTimer = 2000; - Phase = 4; - break; - case 4: - me->HandleEmoteCommand(EMOTE_ONESHOT_LOOT); - uiPhaseTimer = 1000; - Phase = 5; - break; - case 5: - me->HandleEmoteCommand(EMOTE_ONESHOT_NONE); - uiPhaseTimer = 500; - Phase = 6; - break; - case 6: - if (GameObject *go_fur = me->FindNearestGameObject(GO_HIGH_QUALITY_FUR, 11.0f)) - go_fur->Delete(); - uiPhaseTimer = 500; - Phase = 7; - break; - - case 7: - { - GameObject *go_caribou = NULL; - for (uint8 i = 0; i < CaribouTrapsNum; ++i) - { - go_caribou = me->FindNearestGameObject(CaribouTraps[i], 5.0f); - if (go_caribou) - { - go_caribou->SetGoState(GO_STATE_ACTIVE); - go_caribouGUID = go_caribou->GetGUID(); - break; - } - } - Phase = 8; - uiPhaseTimer = 1000; - } - break; - case 8: - DoCast(me, SPELL_TRAPPED, true); - Phase = 0; - break; - } - } else uiPhaseTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_nesingwary_trapper(Creature *pCreature) -{ - return new npc_nesingwary_trapperAI (pCreature); -} - -/*###### -## npc_lurgglbr -######*/ - -enum eLurgglbr -{ - QUEST_ESCAPE_WINTERFIN_CAVERNS = 11570, - - GO_CAGE = 187369, - - FACTION_ESCORTEE_A = 774, - FACTION_ESCORTEE_H = 775, -}; - -/*#define SAY_WP_1_LUR_START -1571004 -#define SAY_WP_1_LUR_END -1571005 -#define SAY_WP_41_LUR_START -1571006 -#define SAY_WP_41_LUR_END -1571007*/ - -struct npc_lurgglbrAI : public npc_escortAI -{ - npc_lurgglbrAI(Creature* pCreature) : npc_escortAI(pCreature){} - - uint32 IntroTimer; - uint32 IntroPhase; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - IntroTimer = 0; - IntroPhase = 0; - } - } - - void WaypointReached(uint32 i) - { - switch (i) - { - case 0: - IntroPhase = 1; - IntroTimer = 2000; - break; - case 41: - IntroPhase = 4; - IntroTimer = 2000; - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (IntroPhase) - { - if (IntroTimer <= diff) - { - switch(IntroPhase) - { - case 1: - //DoScriptText(SAY_WP_1_LUR_START,me); - IntroPhase = 2; - IntroTimer = 7500; - break; - case 2: - //DoScriptText(SAY_WP_1_LUR_END,me); - IntroPhase = 3; - IntroTimer = 7500; - break; - case 3: - me->SetReactState(REACT_AGGRESSIVE); - IntroPhase = 0; - IntroTimer = 0; - break; - case 4: - //DoScriptText(SAY_WP_41_LUR_START,me); - IntroPhase = 5; - IntroTimer = 8000; - break; - case 5: - //DoScriptText(SAY_WP_41_LUR_END,me); - IntroPhase = 6; - IntroTimer = 2500; - break; - - case 6: - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->AreaExploredOrEventHappens(QUEST_ESCAPE_WINTERFIN_CAVERNS); - IntroPhase = 7; - IntroTimer = 2500; - break; - - case 7: - me->ForcedDespawn(); - IntroPhase = 0; - IntroTimer = 0; - break; - } - } else IntroTimer -= diff; - } - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_npc_lurgglbr(Creature* pCreature) -{ - return new npc_lurgglbrAI(pCreature); -} - -bool QuestAccept_npc_lurgglbr(Player* pPlayer, Creature* pCreature, Quest const *pQuest) -{ - if (pQuest->GetQuestId() == QUEST_ESCAPE_WINTERFIN_CAVERNS) - { - if (GameObject* pGo = pCreature->FindNearestGameObject(GO_CAGE, 5.0f)) - { - pGo->SetRespawnTime(0); - pGo->SetGoType(GAMEOBJECT_TYPE_BUTTON); - pGo->UseDoorOrButton(20); - } - - if (npc_escortAI* pEscortAI = CAST_AI(npc_lurgglbrAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - - switch (pPlayer->GetTeam()) - { - case ALLIANCE: - pCreature->setFaction(FACTION_ESCORTEE_A); - break; - default: - case HORDE: - pCreature->setFaction(FACTION_ESCORTEE_H); - break; - } - - return true; - } - return false; -} - -/*###### -## npc_nexus_drake_hatchling -######*/ - -enum eNexusDrakeHatchling -{ - SPELL_DRAKE_HARPOON = 46607, - SPELL_RED_DRAGONBLOOD = 46620, - SPELL_DRAKE_HATCHLING_SUBDUED = 46691, - SPELL_SUBDUED = 46675, - - NPC_RAELORASZ = 26117, - - QUEST_DRAKE_HUNT = 11919, - QUEST_DRAKE_HUNT_D = 11940 -}; - -struct npc_nexus_drake_hatchlingAI : public FollowerAI //The spell who makes the npc follow the player is missing, also we can use FollowerAI! -{ - npc_nexus_drake_hatchlingAI(Creature *c) : FollowerAI(c) {} - - uint64 HarpoonerGUID; - bool WithRedDragonBlood; - - void Reset() - { - WithRedDragonBlood = false; - HarpoonerGUID = 0; - } - - void EnterCombat(Unit* pWho) - { - if (me->canAttack(pWho)) - AttackStart(pWho); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_DRAKE_HARPOON && caster->GetTypeId() == TYPEID_PLAYER) - { - HarpoonerGUID = caster->GetGUID(); - DoCast(me, SPELL_RED_DRAGONBLOOD, true); - } - WithRedDragonBlood = true; - } - - void MoveInLineOfSight(Unit *pWho) - { - FollowerAI::MoveInLineOfSight(pWho); - - if (!HarpoonerGUID) - return; - - if (me->HasAura(SPELL_SUBDUED) && pWho->GetEntry() == NPC_RAELORASZ) - { - if (me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) - { - if (Player *pHarpooner = Unit::GetPlayer(HarpoonerGUID)) - { - pHarpooner->KilledMonsterCredit(26175,0); - pHarpooner->RemoveAura(SPELL_DRAKE_HATCHLING_SUBDUED); - SetFollowComplete(); - HarpoonerGUID = 0; - me->DisappearAndDie(); - } - } - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (WithRedDragonBlood && HarpoonerGUID && !me->HasAura(SPELL_RED_DRAGONBLOOD)) - { - if (Player *pHarpooner = Unit::GetPlayer(HarpoonerGUID)) - { - EnterEvadeMode(); - StartFollow(pHarpooner, 35, NULL); - - DoCast(me, SPELL_SUBDUED, true); - pHarpooner->CastSpell(pHarpooner, SPELL_DRAKE_HATCHLING_SUBDUED, true); - - me->AttackStop(); - WithRedDragonBlood = false; - } - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_nexus_drake_hatchling(Creature* pCreature) -{ - return new npc_nexus_drake_hatchlingAI(pCreature); -} - -/*###### -## npc_thassarian -######*/ - -enum eThassarian -{ - QUEST_LAST_RITES = 12019, - - SPELL_TRANSFORM_VALANAR = 46753, - SPELL_STUN = 46957, - SPELL_SHADOW_BOLT = 15537, - - NPC_IMAGE_LICH_KING = 26203, - NPC_COUNSELOR_TALBOT = 25301, - NPC_PRINCE_VALANAR = 28189, - NPC_GENERAL_ARLOS = 25250, - NPC_LERYSSA = 25251, - - SAY_TALBOT_1 = -1571004, - SAY_LICH_1 = -1571005, - SAY_TALBOT_2 = -1571006, - SAY_THASSARIAN_1 = -1571007, - SAY_THASSARIAN_2 = -1571008, - SAY_LICH_2 = -1571009, - SAY_THASSARIAN_3 = -1571010, - SAY_TALBOT_3 = -1571011, - SAY_LICH_3 = -1571012, - SAY_TALBOT_4 = -1571013, - SAY_ARLOS_1 = -1571014, - SAY_ARLOS_2 = -1571015, - SAY_LERYSSA_1 = -1571016, - SAY_THASSARIAN_4 = -1571017, - SAY_LERYSSA_2 = -1571018, - SAY_THASSARIAN_5 = -1571019, - SAY_LERYSSA_3 = -1571020, - SAY_THASSARIAN_6 = -1571021, - SAY_LERYSSA_4 = -1571022, - SAY_THASSARIAN_7 = -1571023, -}; - -#define GOSSIP_ITEM_T "Let's do this, Thassarian. It's now or never." - -struct npc_thassarianAI : public npc_escortAI -{ - npc_thassarianAI(Creature* pCreature) : npc_escortAI(pCreature) - { - } - - uint64 uiArthas; - uint64 uiTalbot; - uint64 uiLeryssa; - uint64 uiArlos; - - bool bArthasInPosition; - bool bArlosInPosition; - bool bLeryssaInPosition; - bool bTalbotInPosition; - - uint32 uiPhase; - uint32 uiPhaseTimer; - - void Reset() - { - me->RestoreFaction(); - me->RemoveStandFlags(UNIT_STAND_STATE_SIT); - - uiArthas = 0; - uiTalbot = 0; - uiLeryssa = 0; - uiArlos = 0; - - bArthasInPosition = false; - bArlosInPosition = false; - bLeryssaInPosition = false; - bTalbotInPosition = false; - - uiPhase = 0; - uiPhaseTimer = 0; - } - - void WaypointReached(uint32 uiPointId) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(uiPointId) - { - case 3: - SetEscortPaused(true); - if (Creature *pArthas = me->SummonCreature(NPC_IMAGE_LICH_KING, 3730.313, 3518.689, 473.324, 1.562, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) - { - uiArthas = pArthas->GetGUID(); - pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pArthas->SetReactState(REACT_PASSIVE); - pArthas->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pArthas->GetMotionMaster()->MovePoint(0, 3737.374756,3564.841309,477.433014); - } - if (Creature *pTalbot = me->SummonCreature(NPC_COUNSELOR_TALBOT, 3747.23, 3614.936, 473.321, 4.462012, TEMPSUMMON_CORPSE_TIMED_DESPAWN,120000)) - { - uiTalbot = pTalbot->GetGUID(); - pTalbot->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTalbot->GetMotionMaster()->MovePoint(0, 3738.000977,3568.882080,477.433014); - } - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - break; - - case 4: - SetEscortPaused(true); - uiPhase = 7; - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (bArthasInPosition && bTalbotInPosition) - { - uiPhase = 1; - bArthasInPosition = false; - bTalbotInPosition = false; - } - - if (bArlosInPosition && bLeryssaInPosition) - { - bArlosInPosition = false; - bLeryssaInPosition = false; - DoScriptText(SAY_THASSARIAN_1, me); - SetEscortPaused(false); - } - - if (uiPhaseTimer <= uiDiff) - { - Creature* pTalbot = me->GetCreature(*me, uiTalbot); - Creature* pArthas = me->GetCreature(*me, uiArthas); - switch (uiPhase) - { - case 1: - if (pTalbot) - pTalbot->SetStandState(UNIT_STAND_STATE_KNEEL); - uiPhaseTimer = 3000; - ++uiPhase; - break; - - case 2: - if (pTalbot) - { - pTalbot->UpdateEntry(NPC_PRINCE_VALANAR,ALLIANCE); - pTalbot->setFaction(14); - pTalbot->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTalbot->SetReactState(REACT_PASSIVE); - } - uiPhaseTimer = 5000; - ++uiPhase; - break; - - case 3: - if (pTalbot) - DoScriptText(SAY_TALBOT_1, pTalbot); - uiPhaseTimer = 5000; - ++uiPhase; - break; - - case 4: - if (pArthas) - DoScriptText(SAY_LICH_1, pArthas); - uiPhaseTimer = 5000; - ++uiPhase; - break; - - case 5: - if (pTalbot) - DoScriptText(SAY_TALBOT_2, pTalbot); - uiPhaseTimer = 5000; - ++uiPhase; - break; - - case 6: - if (Creature* pArlos = me->SummonCreature(NPC_GENERAL_ARLOS, 3745.527100, 3615.655029, 473.321533, 4.447805, TEMPSUMMON_CORPSE_TIMED_DESPAWN,120000)) - { - uiArlos = pArlos->GetGUID(); - pArlos->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pArlos->GetMotionMaster()->MovePoint(0, 3735.570068, 3572.419922, 477.441010); - } - if (Creature *pLeryssa = me->SummonCreature(NPC_LERYSSA, 3749.654541, 3614.959717, 473.323486, 4.524959, TEMPSUMMON_CORPSE_TIMED_DESPAWN,120000)) - { - uiLeryssa = pLeryssa->GetGUID(); - pLeryssa->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pLeryssa->SetReactState(REACT_PASSIVE); - pLeryssa->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pLeryssa->GetMotionMaster()->MovePoint(0, 3741.969971, 3571.439941, 477.441010); - } - uiPhaseTimer = 2000; - uiPhase = 0; - break; - - case 7: - DoScriptText(SAY_THASSARIAN_2, me); - uiPhaseTimer = 5000; - ++uiPhase; - break; - - case 8: - if (pArthas && pTalbot) - { - pArthas->SetInFront(me); //The client doesen't update with the new orientation :l - pTalbot->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_LICH_2, pArthas); - } - uiPhaseTimer = 5000; - uiPhase = 9; - break; - - case 9: - DoScriptText(SAY_THASSARIAN_3, me); - uiPhaseTimer = 5000; - uiPhase = 10; - break; - - case 10: - if (pTalbot) - DoScriptText(SAY_TALBOT_3, pTalbot); - uiPhaseTimer = 5000; - uiPhase = 11; - break; - - case 11: - if (pArthas) - DoScriptText(SAY_LICH_3, pArthas); - uiPhaseTimer = 5000; - uiPhase = 12; - break; - - case 12: - if (pTalbot) - DoScriptText(SAY_TALBOT_4, pTalbot); - uiPhaseTimer = 2000; - uiPhase = 13; - break; - - case 13: - if (pArthas) - pArthas->RemoveFromWorld(); - ++uiPhase; - break; - - case 14: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pTalbot) - { - pTalbot->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTalbot->SetReactState(REACT_AGGRESSIVE); - pTalbot->CastSpell(me, SPELL_SHADOW_BOLT, false); - } - uiPhaseTimer = 1500; - ++uiPhase; - break; - - case 15: - me->SetReactState(REACT_AGGRESSIVE); - AttackStart(pTalbot); - uiPhase = 0; - break; - - case 16: - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - uiPhaseTimer = 20000; - ++uiPhase; - break; - - case 17: - if (Creature* pLeryssa = me->GetCreature(*me, uiLeryssa)) - pLeryssa->RemoveFromWorld(); - if (Creature* pArlos= me->GetCreature(*me, uiArlos)) - pArlos->RemoveFromWorld(); - if (pTalbot) - pTalbot->RemoveFromWorld(); - me->RemoveStandFlags(UNIT_STAND_STATE_SIT); - SetEscortPaused(false); - uiPhaseTimer = 0; - uiPhase = 0; - } - } else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (Creature* pTalbot = me->GetCreature(*me, uiTalbot)) - pTalbot->RemoveFromWorld(); - - if (Creature* pLeryssa = me->GetCreature(*me, uiLeryssa)) - pLeryssa->RemoveFromWorld(); - - if (Creature* pArlos = me->GetCreature(*me, uiArlos)) - pArlos->RemoveFromWorld(); - - if (Creature* pArthas = me->GetCreature(*me, uiArthas)) - pArthas->RemoveFromWorld(); - } -}; - -bool GossipHello_npc_thassarian(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_LAST_RITES) == QUEST_STATUS_INCOMPLETE && pCreature->GetAreaId() == 4125) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_T, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_thassarian(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(200.0f); - break; - } - return true; -} - -CreatureAI* GetAI_npc_thassarian(Creature *pCreature) -{ - return new npc_thassarianAI (pCreature); -} - -/*###### -## npc_image_lich_king -######*/ - -struct npc_image_lich_kingAI : public ScriptedAI -{ - npc_image_lich_kingAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - void Reset() - { - me->RestoreFaction(); - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (me->isSummon()) - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - CAST_AI(npc_thassarianAI,CAST_CRE(pSummoner)->AI())->bArthasInPosition = true; - } -}; - -CreatureAI* GetAI_npc_image_lich_king(Creature* pCreature) -{ - return new npc_image_lich_kingAI (pCreature); -} - -/*###### -## npc_general_arlos -######*/ - -struct npc_general_arlosAI : public ScriptedAI -{ - npc_general_arlosAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - me->addUnitState(UNIT_STAT_STUNNED); - me->CastSpell(me, SPELL_STUN, true); - if (me->isSummon()) - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - CAST_AI(npc_thassarianAI,CAST_CRE(pSummoner)->AI())->bArlosInPosition = true; - } -}; - -CreatureAI* GetAI_npc_general_arlos(Creature *pCreature) -{ - return new npc_general_arlosAI(pCreature); -} - -/*###### -## npc_counselor_talbot -######*/ - -enum eCounselorTalbot -{ - SPELL_DEFLECTION = 51009, - SPELL_SOUL_BLAST = 50992, -}; - -struct npc_counselor_talbotAI : public ScriptedAI -{ - npc_counselor_talbotAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pCreature->RestoreFaction(); - } - - uint64 LeryssaGUID; - uint64 ArlosGUID; - - bool bCheck; - - uint32 uiShadowBoltTimer; - uint32 uiDeflectionTimer; - uint32 uiSoulBlastTimer; - - void Reset() - { - LeryssaGUID = 0; - ArlosGUID = 0; - bCheck = false; - uiShadowBoltTimer = urand(5000,12000); - uiDeflectionTimer = urand(20000,25000); - uiSoulBlastTimer = urand (12000,18000); - } - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (me->isSummon()) - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - CAST_AI(npc_thassarianAI,CAST_CRE(pSummoner)->AI())->bTalbotInPosition = true; - } - - void UpdateAI(const uint32 uiDiff) - { - if (bCheck) - { - if (Creature *pLeryssa = me->FindNearestCreature(NPC_LERYSSA, 50.0f, true)) - LeryssaGUID = pLeryssa->GetGUID(); - if (Creature *pArlos = me->FindNearestCreature(NPC_GENERAL_ARLOS, 50.0f, true)) - ArlosGUID = pArlos->GetGUID(); - bCheck = false; - } - - if (!UpdateVictim()) - return; - - if (me->GetAreaId() == 4125) - { - if (uiShadowBoltTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - uiShadowBoltTimer = urand(5000,12000); - } else uiShadowBoltTimer -= uiDiff; - - if (uiDeflectionTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_DEFLECTION); - uiDeflectionTimer = urand(20000,25000); - } else uiDeflectionTimer -= uiDiff; - - if (uiSoulBlastTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SOUL_BLAST); - uiSoulBlastTimer = urand (12000,18000); - } else uiSoulBlastTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* pKiller) - { - if (!LeryssaGUID || !ArlosGUID) - return; - - Creature *pLeryssa = Unit::GetCreature(*me, LeryssaGUID); - Creature *pArlos = Unit::GetCreature(*me, ArlosGUID); - if (!pLeryssa || !pArlos) - return; - - DoScriptText(SAY_ARLOS_1, pArlos); - DoScriptText(SAY_ARLOS_2, pArlos); - DoScriptText(SAY_LERYSSA_1, pLeryssa); - pArlos->Kill(pArlos, false); - pLeryssa->RemoveAura(SPELL_STUN); - pLeryssa->clearUnitState(UNIT_STAT_STUNNED); - pLeryssa->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pLeryssa->GetMotionMaster()->MovePoint(0,3722.114502, 3564.201660, 477.441437); - - if (pKiller->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(pKiller)->RewardPlayerAndGroupAtEvent(NPC_PRINCE_VALANAR, 0); - } -}; - -CreatureAI* GetAI_npc_counselor_talbot(Creature* pCreature) -{ - return new npc_counselor_talbotAI (pCreature); -} - -/*###### -## npc_leryssa -######*/ - -struct npc_leryssaAI : public ScriptedAI -{ - npc_leryssaAI(Creature* pCreature) : ScriptedAI(pCreature) - { - bDone = false; - Phase = 0; - uiPhaseTimer = 0; - - pCreature->RemoveStandFlags(UNIT_STAND_STATE_SIT); - } - - bool bDone; - - uint32 Phase; - uint32 uiPhaseTimer; - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (!bDone) - { - if (Creature* pTalbot = me->FindNearestCreature(NPC_PRINCE_VALANAR, 50.0f, true)) - CAST_AI(npc_counselor_talbotAI, pTalbot->AI())->bCheck = true; - - me->addUnitState(UNIT_STAT_STUNNED); - me->CastSpell(me, SPELL_STUN, true); - - if (me->isSummon()) - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - CAST_AI(npc_thassarianAI,CAST_CRE(pSummoner)->AI())->bLeryssaInPosition = true; - bDone = true; - } - else - { - me->SetStandState(UNIT_STAND_STATE_SIT); - if (me->isSummon()) - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - pSummoner->SetStandState(UNIT_STAND_STATE_SIT); - uiPhaseTimer = 1500; - Phase = 1; - } - } - - void UpdateAI(const uint32 uiDiff) - { - ScriptedAI::UpdateAI(uiDiff); - - if (uiPhaseTimer <= uiDiff) - { - switch (Phase) - { - case 1: - if (me->isSummon()) - if (Unit* pThassarian = CAST_SUM(me)->GetSummoner()) - DoScriptText(SAY_THASSARIAN_4, pThassarian); - uiPhaseTimer = 5000; - ++Phase; - break; - case 2: - DoScriptText(SAY_LERYSSA_2, me); - uiPhaseTimer = 5000; - ++Phase; - break; - case 3: - if (me->isSummon()) - if (Unit* pThassarian = CAST_SUM(me)->GetSummoner()) - DoScriptText(SAY_THASSARIAN_5, pThassarian); - uiPhaseTimer = 5000; - ++Phase; - break; - case 4: - DoScriptText(SAY_LERYSSA_3, me); - uiPhaseTimer = 5000; - ++Phase; - break; - case 5: - if (me->isSummon()) - if (Unit* pThassarian = CAST_SUM(me)->GetSummoner()) - DoScriptText(SAY_THASSARIAN_6, pThassarian); - uiPhaseTimer = 5000; - ++Phase; - break; - - case 6: - DoScriptText(SAY_LERYSSA_4, me); - uiPhaseTimer = 5000; - ++Phase; - break; - case 7: - if (me->isSummon()) - if (Unit* pThassarian = CAST_SUM(me)->GetSummoner()) - { - DoScriptText(SAY_THASSARIAN_7, pThassarian); - CAST_AI(npc_thassarianAI,CAST_CRE(pThassarian)->AI())->uiPhase = 16; - } - uiPhaseTimer = 5000; - Phase = 0; - break; - } - } else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_leryssa(Creature *pCreature) -{ - return new npc_leryssaAI (pCreature); -} - -/*###### -## npc_beryl_sorcerer -######*/ - -enum eBerylSorcerer -{ - NPC_CAPTURED_BERLY_SORCERER = 25474, - NPC_LIBRARIAN_DONATHAN = 25262, - - SPELL_ARCANE_CHAINS = 45611, - SPELL_COSMETIC_CHAINS = 54324, - SPELL_COSMETIC_ENSLAVE_CHAINS_SELF = 45631 -}; - -struct npc_beryl_sorcererAI : public FollowerAI -{ - npc_beryl_sorcererAI(Creature* pCreature) : FollowerAI(pCreature) {} - - bool bEnslaved; - - void Reset() - { - me->SetReactState(REACT_AGGRESSIVE); - bEnslaved = false; - } - - void EnterCombat(Unit* pWho) - { - if (me->canAttack(pWho)) - AttackStart(pWho); - } - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_ARCANE_CHAINS && pCaster->GetTypeId() == TYPEID_PLAYER && me->GetHealth()*100 / me->GetMaxHealth() <= 50 && !bEnslaved) - { - EnterEvadeMode(); //We make sure that the npc is not attacking the player! - me->SetReactState(REACT_PASSIVE); - StartFollow(CAST_PLR(pCaster), NULL, NULL); - me->UpdateEntry(NPC_CAPTURED_BERLY_SORCERER, TEAM_NEUTRAL); - DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF, true); - CAST_PLR(pCaster)->KilledMonsterCredit(NPC_CAPTURED_BERLY_SORCERER, 0); - bEnslaved = true; - } - } - - void MoveInLineOfSight(Unit* pWho) - { - FollowerAI::MoveInLineOfSight(pWho); - - if (pWho->GetEntry() == NPC_LIBRARIAN_DONATHAN && me->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) - { - SetFollowComplete(); - me->DisappearAndDie(); - } - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_beryl_sorcerer(Creature* pCreature) -{ - return new npc_beryl_sorcererAI(pCreature); -} - -/*###### -## npc_imprisoned_beryl_sorcerer -######*/ - -enum eImprisionedBerylSorcerer -{ - SPELL_NEURAL_NEEDLE = 45634, - - NPC_IMPRISONED_BERYL_SORCERER = 25478, - - SAY_IMPRISIONED_BERYL_1 = -1571024, - SAY_IMPRISIONED_BERYL_2 = -1571025, - SAY_IMPRISIONED_BERYL_3 = -1571026, - SAY_IMPRISIONED_BERYL_4 = -1571027, - SAY_IMPRISIONED_BERYL_5 = -1571028, - SAY_IMPRISIONED_BERYL_6 = -1571029, - SAY_IMPRISIONED_BERYL_7 = -1571030, -}; - -struct npc_imprisoned_beryl_sorcererAI : public ScriptedAI -{ - npc_imprisoned_beryl_sorcererAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint64 CasterGUID; - - uint32 uiStep; - uint32 uiPhase; - - void Reset() - { - uiStep = 1; - uiPhase = 0; - CasterGUID = NULL; - } - - void EnterCombat(Unit* /*pWho*/) - { - } - - void SpellHit(Unit* pUnit, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_NEURAL_NEEDLE && pUnit->GetTypeId() == TYPEID_PLAYER) - { - ++uiPhase; - CasterGUID = pUnit->GetGUID(); - } - } - - void UpdateAI(const uint32 uiDiff) - { - ScriptedAI::UpdateAI(uiDiff); - - if (!me->HasAura(SPELL_COSMETIC_ENSLAVE_CHAINS_SELF)) - DoCast(me, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF); - - if (me->GetReactState() != REACT_PASSIVE) - me->SetReactState(REACT_PASSIVE); - - switch (uiPhase) - { - case 1: - if (uiStep == 1) - { - DoScriptText(SAY_IMPRISIONED_BERYL_1, me); - uiStep = 2; - } - break; - - case 2: - if (uiStep == 2) - { - DoScriptText(SAY_IMPRISIONED_BERYL_2, me); - uiStep = 3; - } - break; - - case 3: - if (uiStep == 3) - { - DoScriptText(SAY_IMPRISIONED_BERYL_3, me); - uiStep = 4; - } - break; - - case 4: - if (uiStep == 4) - { - DoScriptText(SAY_IMPRISIONED_BERYL_4, me); - uiStep = 5; - } - break; - - case 5: - if (uiStep == 5) - { - if (Player *pCaster = Unit::GetPlayer(CasterGUID)) - { - DoScriptText(SAY_IMPRISIONED_BERYL_5, me); - pCaster->KilledMonsterCredit(25478,0); - uiStep = 6; - } - } - break; - - case 6: - if (uiStep == 6) - { - DoScriptText(SAY_IMPRISIONED_BERYL_6, me); - uiStep = 7; - } - break; - - case 7: - if (uiStep == 7) - { - DoScriptText(SAY_IMPRISIONED_BERYL_7, me); - uiStep = 1; - uiPhase = 0; - } - break; - } - } -}; - -CreatureAI* GetAI_npc_imprisoned_beryl_sorcerer(Creature* pCreature) -{ - return new npc_imprisoned_beryl_sorcererAI(pCreature); -} - -/*###### -## npc_mootoo_the_younger -######*/ -enum Script_Texts_Mootoo_the_Younger -{ - SAY_1 =-1750040, - SAY_2 =-1750041, - SAY_3 =-1750042, - SAY_4 =-1750043, - SAY_5 =-1750044 -}; -enum Mootoo_the_Younger_Entries -{ - NPC_MOOTOO_THE_YOUNGER =25504, - QUEST_ESCAPING_THE_MIST =11664 -}; -bool QuestAccept_npc_mootoo_the_younger(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_ESCAPING_THE_MIST) - { - switch (pPlayer->GetTeam()) - { - case ALLIANCE: - pCreature->setFaction(FACTION_ESCORTEE_A); - break; - case HORDE: - pCreature->setFaction(FACTION_ESCORTEE_H); - break; - } - DoScriptText(SAY_1, pCreature); - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - } - return true; -} -struct npc_mootoo_the_youngerAI : public npc_escortAI -{ - npc_mootoo_the_youngerAI(Creature *c) : npc_escortAI(c) {} - - void Reset() - { - SetDespawnAtFar(false); - } - - void JustDied(Unit* /*killer*/) - { - if (Player* pPlayer=GetPlayerForEscort()) - pPlayer->FailQuest(QUEST_ESCAPING_THE_MIST); - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 10: - me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); - DoScriptText(SAY_2, me); - break; - case 12: - DoScriptText(SAY_3, me); - me->HandleEmoteCommand(EMOTE_ONESHOT_LOOT); - break; - case 16: - DoScriptText(SAY_4, me); - me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); - break; - case 20: - me->SetPhaseMask(1,true); - DoScriptText(SAY_5, me); - me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_ESCAPING_THE_MIST, me); - SetRun(true); - break; - } - } -}; -CreatureAI* GetAI_npc_mootoo_the_younger(Creature* pCreature) -{ - return new npc_mootoo_the_youngerAI(pCreature); -} - -/*###### -## npc_bonker_togglevolt -######*/ - -enum Bonker_Togglevolt_Entries -{ - NPC_BONKER_TOGGLEVOLT =25589, - QUEST_GET_ME_OUTA_HERE =11673 -}; -enum Script_Texts_Bonker_Togglevolt -{ - SAY_bonker_1 =-1700002, - SAY_bonker_2 =-1700003 -}; - -bool QuestAccept_npc_bonker_togglevolt(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_GET_ME_OUTA_HERE) - { - switch (pPlayer->GetTeam()) - { - case ALLIANCE: - pCreature->setFaction(FACTION_ESCORTEE_A); - break; - case HORDE: - pCreature->setFaction(FACTION_ESCORTEE_H); - break; - } - DoScriptText(SAY_bonker_2, pCreature, pPlayer); - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, true, pPlayer->GetGUID()); - } - return true; -} -struct npc_bonker_togglevoltAI : public npc_escortAI -{ - npc_bonker_togglevoltAI(Creature *c) : npc_escortAI(c) {} - uint32 Bonker_agro; - - void Reset() - { - Bonker_agro=0; - SetDespawnAtFar(false); - } - - void JustDied(Unit* /*killer*/) - { - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->FailQuest(QUEST_ESCAPING_THE_MIST); - } - - void UpdateEscortAI(const uint32 /*diff*/) - { - if (GetAttack() && UpdateVictim()) - { - if (Bonker_agro == 0) - { - DoScriptText(SAY_bonker_1,me); - Bonker_agro++; - } - DoMeleeAttackIfReady(); - } - else Bonker_agro=0; - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 29: - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_GET_ME_OUTA_HERE, me); - break; - } - } -}; - -CreatureAI* GetAI_npc_bonker_togglevolt(Creature* pCreature) -{ - return new npc_bonker_togglevoltAI(pCreature); -} - -/*###### -## Help Those That Cannot Help Themselves, Quest 11876 -######*/ - -enum eHelpThemselves -{ - QUEST_CANNOT_HELP_THEMSELVES = 11876, - GO_MAMMOTH_TRAP_1 = 188022, - GO_MAMMOTH_TRAP_2 = 188024, - GO_MAMMOTH_TRAP_3 = 188025, - GO_MAMMOTH_TRAP_4 = 188026, - GO_MAMMOTH_TRAP_5 = 188027, - GO_MAMMOTH_TRAP_6 = 188028, - GO_MAMMOTH_TRAP_7 = 188029, - GO_MAMMOTH_TRAP_8 = 188030, - GO_MAMMOTH_TRAP_9 = 188031, - GO_MAMMOTH_TRAP_10 = 188032, - GO_MAMMOTH_TRAP_11 = 188033, - GO_MAMMOTH_TRAP_12 = 188034, - GO_MAMMOTH_TRAP_13 = 188035, - GO_MAMMOTH_TRAP_14 = 188036, - GO_MAMMOTH_TRAP_15 = 188037, - GO_MAMMOTH_TRAP_16 = 188038, - GO_MAMMOTH_TRAP_17 = 188039, - GO_MAMMOTH_TRAP_18 = 188040, - GO_MAMMOTH_TRAP_19 = 188041, - GO_MAMMOTH_TRAP_20 = 188042, - GO_MAMMOTH_TRAP_21 = 188043, - GO_MAMMOTH_TRAP_22 = 188044, -}; - -#define MammothTrapsNum 22 -const uint32 MammothTraps[MammothTrapsNum] = -{ - GO_MAMMOTH_TRAP_1, GO_MAMMOTH_TRAP_2, GO_MAMMOTH_TRAP_3, GO_MAMMOTH_TRAP_4, GO_MAMMOTH_TRAP_5, - GO_MAMMOTH_TRAP_6, GO_MAMMOTH_TRAP_7, GO_MAMMOTH_TRAP_8, GO_MAMMOTH_TRAP_9, GO_MAMMOTH_TRAP_10, - GO_MAMMOTH_TRAP_11, GO_MAMMOTH_TRAP_12, GO_MAMMOTH_TRAP_13, GO_MAMMOTH_TRAP_14, GO_MAMMOTH_TRAP_15, - GO_MAMMOTH_TRAP_16, GO_MAMMOTH_TRAP_17, GO_MAMMOTH_TRAP_18, GO_MAMMOTH_TRAP_19, GO_MAMMOTH_TRAP_20, - GO_MAMMOTH_TRAP_21, GO_MAMMOTH_TRAP_22 -}; - -struct npc_trapped_mammoth_calfAI : public ScriptedAI -{ - npc_trapped_mammoth_calfAI(Creature* c) : ScriptedAI(c) {} - - uint32 uiTimer; - bool bStarted; - - void Reset() - { - uiTimer = 1500; - bStarted = false; - - GameObject* pTrap; - for (uint8 i = 0; i < MammothTrapsNum; ++i) - { - pTrap = me->FindNearestGameObject(MammothTraps[i],11.0f); - if (pTrap) - { - pTrap->SetGoState(GO_STATE_ACTIVE); - return; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (bStarted) - { - if (uiTimer <= diff) - { - Position pos; - me->GetRandomNearPosition(pos, 10.0f); - me->GetMotionMaster()->MovePoint(0,pos); - bStarted = false; - } - else uiTimer -= diff; - } - } - - void DoAction(const int32 param) - { - if (param == 1) - bStarted = true; - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - - if (uiType != POINT_MOTION_TYPE) - return; - me->DisappearAndDie(); - GameObject* pTrap; - for (uint8 i = 0; i < MammothTrapsNum; ++i) - { - pTrap = me->FindNearestGameObject(MammothTraps[i],11.0f); - if (pTrap) - { - pTrap->SetLootState(GO_JUST_DEACTIVATED); - return; - } - } - } -}; - -CreatureAI* GetAI_npc_trapped_mammoth_calf(Creature* pCreature) -{ - return new npc_trapped_mammoth_calfAI(pCreature); -} - -/*###### -## Quest 11653: Hah... You're Not So Big Now! -######*/ - -enum eNotSoBig -{ - QUEST_YOU_RE_NOT_SO_BIG_NOW = 11653, - SPELL_AURA_NOTSOBIG_1 = 45672, - SPELL_AURA_NOTSOBIG_2 = 45673, - SPELL_AURA_NOTSOBIG_3 = 45677, - SPELL_AURA_NOTSOBIG_4 = 45681 -}; - -struct npc_magmoth_crusherAI : public ScriptedAI -{ - npc_magmoth_crusherAI(Creature* c) : ScriptedAI(c) {} - - void JustDied(Unit *pKiller) - { - if (pKiller->GetTypeId() == TYPEID_PLAYER && - CAST_PLR(pKiller)->GetQuestStatus(QUEST_YOU_RE_NOT_SO_BIG_NOW) == QUEST_STATUS_INCOMPLETE && - (me->HasAura(SPELL_AURA_NOTSOBIG_1) || me->HasAura(SPELL_AURA_NOTSOBIG_2) || - me->HasAura(SPELL_AURA_NOTSOBIG_3) || me->HasAura(SPELL_AURA_NOTSOBIG_4))) - { - Quest const* qInfo = objmgr.GetQuestTemplate(QUEST_YOU_RE_NOT_SO_BIG_NOW); - if (qInfo) - CAST_PLR(pKiller)->KilledMonsterCredit(qInfo->ReqCreatureOrGOId[0],0); - } - } -}; - -CreatureAI* GetAI_npc_magmoth_crusher(Creature* pCreature) -{ - return new npc_magmoth_crusherAI(pCreature); -} - -/*###### -## Quest 11608: Bury Those Cockroaches! -######*/ - -#define QUEST_BURY_THOSE_COCKROACHES 11608 -#define SPELL_SEAFORIUM_DEPTH_CHARGE_EXPLOSION 45502 - -struct npc_seaforium_depth_chargeAI : public ScriptedAI -{ - npc_seaforium_depth_chargeAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiExplosionTimer; - void Reset() - { - uiExplosionTimer = urand(5000,10000); - } - void UpdateAI(const uint32 diff) - { - if (uiExplosionTimer < diff) - { - DoCast(SPELL_SEAFORIUM_DEPTH_CHARGE_EXPLOSION); - for (uint8 i = 0; i < 4; ++i) - { - if (Creature* cCredit = me->FindNearestCreature(25402 + i, 10.0f))//25402-25405 credit markers - { - if (Unit* uOwner = me->GetOwner(true)) - { - Player* pOwner = uOwner->ToPlayer(); - if (pOwner && pOwner->GetQuestStatus(QUEST_BURY_THOSE_COCKROACHES) == QUEST_STATUS_INCOMPLETE) - pOwner->KilledMonsterCredit(cCredit->GetEntry(),cCredit->GetGUID()); - } - } - } - me->Kill(me); - return; - } else uiExplosionTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_seaforium_depth_charge(Creature* pCreature) -{ - return new npc_seaforium_depth_chargeAI(pCreature); -} - -/*###### -## Help Those That Cannot Help Themselves, Quest 11876 -######*/ - -enum eValiancekeepcannons -{ - GO_VALIANCE_KEEP_CANNON_1 = 187560, - GO_VALIANCE_KEEP_CANNON_2 = 188692 -}; - -struct npc_valiance_keep_cannoneerAI : public ScriptedAI -{ - npc_valiance_keep_cannoneerAI(Creature* c) : ScriptedAI(c) {} - - uint32 uiTimer; - - void Reset() - { - uiTimer = urand(13000,18000); - } - - void UpdateAI(const uint32 diff) - { - if (uiTimer <= diff) - { - me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); - GameObject* pCannon = me->FindNearestGameObject(GO_VALIANCE_KEEP_CANNON_1,10); - if (!pCannon) - pCannon = me->FindNearestGameObject(GO_VALIANCE_KEEP_CANNON_2,10); - if (pCannon) - pCannon->Use(me); - uiTimer = urand(13000,18000); - } - else uiTimer -= diff; - - if (!UpdateVictim()) - return; - } - -}; - -CreatureAI* GetAI_npc_valiance_keep_cannoneer(Creature* pCreature) -{ - return new npc_valiance_keep_cannoneerAI(pCreature); -} - -/******************************************************* - * npc_warmage_coldarra - *******************************************************/ - -enum Spells -{ - SPELL_TRANSITUS_SHIELD_BEAM = 48310 -}; - -enum NPCs -{ - NPC_TRANSITUS_SHIELD_DUMMY = 27306, - NPC_WARMAGE_HOLLISTER = 27906, - NPC_WARMAGE_CALANDRA = 27173, - NPC_WARMAGE_WATKINS = 27904 -}; - -struct npc_warmage_coldarraAI : public Scripted_NoMovementAI -{ - npc_warmage_coldarraAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature){} - - uint32 m_uiTimer; //Timer until recast - - void Reset() - { - m_uiTimer = 0; - } - - void Aggro(Unit* /*pWho*/) {} - - void AttackStart(Unit* /*pWho*/) {} - - void UpdateAI(const uint32 uiDiff) - { - if (m_uiTimer <= uiDiff) - { - std::list orbList; - GetCreatureListWithEntryInGrid(orbList, me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f); - - switch(me->GetEntry()) - { - case NPC_WARMAGE_HOLLISTER: - { - if (!orbList.empty()) - { - for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) - { - if (Creature* pOrb = *itr) - if (pOrb->GetPositionY() > 6680) - DoCast(pOrb,SPELL_TRANSITUS_SHIELD_BEAM); - } - } - m_uiTimer = urand(90000,120000); - } - break; - case NPC_WARMAGE_CALANDRA: - { - if (!orbList.empty()) - { - for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) - { - if (Creature* pOrb = *itr) - if ((pOrb->GetPositionY() < 6680) && (pOrb->GetPositionY() > 6630)) - DoCast(pOrb,SPELL_TRANSITUS_SHIELD_BEAM); - } - } - m_uiTimer = urand(90000,120000); - } - break; - case NPC_WARMAGE_WATKINS: - { - if (!orbList.empty()) - { - for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) - { - if (Creature* pOrb = *itr) - if (pOrb->GetPositionY() < 6630) - DoCast(pOrb,SPELL_TRANSITUS_SHIELD_BEAM); - } - } - m_uiTimer = urand(90000,120000); - } - break; - } - } - else m_uiTimer -= uiDiff; - - ScriptedAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_npc_warmage_coldarra(Creature* pCreature) -{ - return new npc_warmage_coldarraAI(pCreature); -} - -void AddSC_borean_tundra() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sinkhole_kill_credit"; - newscript->GetAI = &GetAI_npc_sinkhole_kill_credit; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_khunok_the_behemoth"; - newscript->GetAI = &GetAI_npc_khunok_the_behemoth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_keristrasza"; - newscript->pGossipHello = &GossipHello_npc_keristrasza; - newscript->pGossipSelect = &GossipSelect_npc_keristrasza; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_corastrasza"; - newscript->pGossipHello = &GossipHello_npc_corastrasza; - newscript->pGossipSelect = &GossipSelect_npc_corastrasza; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_iruk"; - newscript->pGossipHello = &GossipHello_npc_iruk; - newscript->pGossipSelect = &GossipSelect_npc_iruk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_nerubar_victim"; - newscript->GetAI = &GetAI_mob_nerubar_victim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_scourge_prisoner"; - newscript->GetAI = &GetAI_npc_scourge_prisoner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jenny"; - newscript->GetAI = &GetAI_npc_jenny; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_fezzix_geartwist"; - newscript->GetAI = &GetAI_npc_fezzix_geartwist; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_nesingwary_trapper"; - newscript->GetAI = &GetAI_npc_nesingwary_trapper; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lurgglbr"; - newscript->GetAI = &GetAI_npc_lurgglbr; - newscript->pQuestAccept = &QuestAccept_npc_lurgglbr; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_nexus_drake_hatchling"; - newscript->GetAI = &GetAI_npc_nexus_drake_hatchling; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thassarian"; - newscript->GetAI = &GetAI_npc_thassarian; - newscript->pGossipHello = &GossipHello_npc_thassarian; - newscript->pGossipSelect = &GossipSelect_npc_thassarian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_image_lich_king"; - newscript->GetAI = &GetAI_npc_image_lich_king; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_counselor_talbot"; - newscript->GetAI = &GetAI_npc_counselor_talbot; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_leryssa"; - newscript->GetAI = &GetAI_npc_leryssa; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_general_arlos"; - newscript->GetAI = &GetAI_npc_general_arlos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_beryl_sorcerer"; - newscript->GetAI = &GetAI_npc_beryl_sorcerer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_imprisoned_beryl_sorcerer"; - newscript->GetAI = &GetAI_npc_imprisoned_beryl_sorcerer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_mootoo_the_younger"; - newscript->GetAI = &GetAI_npc_mootoo_the_younger; - newscript->pQuestAccept=&QuestAccept_npc_mootoo_the_younger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_bonker_togglevolt"; - newscript->GetAI = &GetAI_npc_bonker_togglevolt; - newscript->pQuestAccept=&QuestAccept_npc_bonker_togglevolt; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_trapped_mammoth_calf"; - newscript->GetAI = &GetAI_npc_trapped_mammoth_calf; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_magmoth_crusher"; - newscript->GetAI = &GetAI_npc_magmoth_crusher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_seaforium_depth_charge"; - newscript->GetAI = &GetAI_npc_seaforium_depth_charge; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_valiance_keep_cannoneer"; - newscript->GetAI = &GetAI_npc_valiance_keep_cannoneer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_warmage_coldarra"; - newscript->GetAI = &GetAI_npc_warmage_coldarra; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp b/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp deleted file mode 100644 index c33ea69fa2d..00000000000 --- a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Argent Challenge Encounter. -SD%Complete: 50 % -SDComment: AI for Argent Soldiers are not implemented. AI from bosses need more improvements. -SDCategory: Trial of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" -#include "ScriptedEscortAI.h" - -enum eSpells -{ - //Eadric - SPELL_EADRIC_ACHIEVEMENT = 68197, - SPELL_HAMMER_JUSTICE = 66863, - SPELL_HAMMER_RIGHTEOUS = 66867, - SPELL_RADIANCE = 66935, - SPELL_VENGEANCE = 66865, - - //Paletress - SPELL_SMITE = 66536, - SPELL_SMITE_H = 67674, - SPELL_HOLY_FIRE = 66538, - SPELL_HOLY_FIRE_H = 67676, - SPELL_RENEW = 66537, - SPELL_RENEW_H = 67675, - SPELL_HOLY_NOVA = 66546, - SPELL_SHIELD = 66515, - SPELL_CONFESS = 66680, - SPELL_SUMMON_MEMORY = 66545, - - //Memory - SPELL_OLD_WOUNDS = 66620, - SPELL_OLD_WOUNDS_H = 67679, - SPELL_SHADOWS_PAST = 66619, - SPELL_SHADOWS_PAST_H = 67678, - SPELL_WAKING_NIGHTMARE = 66552, - SPELL_WAKING_NIGHTMARE_H = 67677 -}; - -struct boss_eadricAI : public ScriptedAI -{ - boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - pCreature->SetReactState(REACT_PASSIVE); - pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint32 uiVenganceTimer; - uint32 uiRadianceTimer; - uint32 uiHammerJusticeTimer; - uint32 uiResetTimer; - - bool bDone; - - void Reset() - { - uiVenganceTimer = 10000; - uiRadianceTimer = 16000; - uiHammerJusticeTimer = 25000; - uiResetTimer = 5000; - - bDone = false; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - damage = 0; - EnterEvadeMode(); - me->setFaction(35); - bDone = true; - } - } - - void MovementInform(uint32 MovementType, uint32 /*Data*/) - { - if (MovementType != POINT_MOTION_TYPE) - return; - - if (pInstance) - pInstance->SetData(BOSS_ARGENT_CHALLENGE_E, DONE); - - me->DisappearAndDie(); - } - - void UpdateAI(const uint32 uiDiff) - { - if (bDone && uiResetTimer <= uiDiff) - { - me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); - bDone = false; - } else uiResetTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - if (uiHammerJusticeTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - { - DoCast(pTarget, SPELL_HAMMER_JUSTICE); - DoCast(pTarget, SPELL_HAMMER_RIGHTEOUS); - } - } - uiHammerJusticeTimer = 25000; - } else uiHammerJusticeTimer -= uiDiff; - - if (uiVenganceTimer <= uiDiff) - { - DoCast(me,SPELL_VENGEANCE); - - uiVenganceTimer = 10000; - } else uiVenganceTimer -= uiDiff; - - if (uiRadianceTimer <= uiDiff) - { - DoCastAOE(SPELL_RADIANCE); - - uiRadianceTimer = 16000; - } else uiRadianceTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_eadric(Creature* pCreature) -{ - return new boss_eadricAI(pCreature); -} - -struct boss_paletressAI : public ScriptedAI -{ - boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - MemoryGUID = 0; - pCreature->SetReactState(REACT_PASSIVE); - pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pCreature->RestoreFaction(); - } - - ScriptedInstance* pInstance; - - Creature* pMemory; - uint64 MemoryGUID; - - bool bHealth; - bool bDone; - - uint32 uiHolyFireTimer; - uint32 uiHolySmiteTimer; - uint32 uiRenewTimer; - uint32 uiResetTimer; - - void Reset() - { - me->RemoveAllAuras(); - - uiHolyFireTimer = urand(9000,12000); - uiHolySmiteTimer = urand(5000,7000); - uiRenewTimer = urand(2000,5000); - - uiResetTimer = 7000; - - bHealth = false; - bDone = false; - - if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) - if (pMemory->isAlive()) - pMemory->RemoveFromWorld(); - } - - void SetData(uint32 uiId, uint32 /*uiValue*/) - { - if (uiId == 1) - me->RemoveAura(SPELL_SHIELD); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - damage = 0; - EnterEvadeMode(); - me->setFaction(35); - bDone = true; - } - } - - void MovementInform(uint32 MovementType, uint32 Point) - { - if (MovementType != POINT_MOTION_TYPE || Point != 0) - return; - - if (pInstance) - pInstance->SetData(BOSS_ARGENT_CHALLENGE_P, DONE); - - me->DisappearAndDie(); - } - - void UpdateAI(const uint32 uiDiff) - { - if (bDone && uiResetTimer <= uiDiff) - { - me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); - bDone = false; - } else uiResetTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - if (uiHolyFireTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_HOLY_FIRE); - } - if (me->HasAura(SPELL_SHIELD)) - uiHolyFireTimer = 13000; - else - uiHolyFireTimer = urand(9000,12000); - } else uiHolyFireTimer -= uiDiff; - - if (uiHolySmiteTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_SMITE); - } - if (me->HasAura(SPELL_SHIELD)) - uiHolySmiteTimer = 9000; - else - uiHolySmiteTimer = urand(5000,7000); - } else uiHolySmiteTimer -= uiDiff; - - if (me->HasAura(SPELL_SHIELD)) - if (uiRenewTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - uint8 uiTarget = urand(0,1); - switch(uiTarget) - { - case 0: - DoCast(me,SPELL_RENEW); - break; - case 1: - if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) - if (pMemory->isAlive()) - DoCast(pMemory, SPELL_RENEW); - break; - } - uiRenewTimer = urand(15000,17000); - } else uiRenewTimer -= uiDiff; - - - if (!bHealth && me->GetHealth()*100 / me->GetMaxHealth() <= 25) - { - me->InterruptNonMeleeSpells(true); - DoCastAOE(SPELL_HOLY_NOVA,false); - DoCast(me, SPELL_SHIELD); - DoCastAOE(SPELL_SUMMON_MEMORY,false); - DoCastAOE(SPELL_CONFESS,false); - - bHealth = true; - } - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* pSummon) - { - MemoryGUID = pSummon->GetGUID(); - } -}; - -CreatureAI* GetAI_boss_paletress(Creature* pCreature) -{ - return new boss_paletressAI(pCreature); -} - -struct npc_memoryAI : public ScriptedAI -{ - npc_memoryAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiOldWoundsTimer; - uint32 uiShadowPastTimer; - uint32 uiWakingNightmare; - - void Reset() - { - uiOldWoundsTimer = 12000; - uiShadowPastTimer = 5000; - uiWakingNightmare = 7000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiOldWoundsTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, SPELL_OLD_WOUNDS); - } - uiOldWoundsTimer = 12000; - }else uiOldWoundsTimer -= uiDiff; - - if (uiWakingNightmare <= uiDiff) - { - DoCast(me, SPELL_WAKING_NIGHTMARE); - uiWakingNightmare = 7000; - }else uiWakingNightmare -= uiDiff; - - if (uiShadowPastTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_SHADOWS_PAST); - } - uiShadowPastTimer = 5000; - }else uiShadowPastTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (me->isSummon()) - { - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - { - if (pSummoner && pSummoner->isAlive()) - CAST_CRE(pSummoner)->AI()->SetData(1,0); - } - } - } -}; - -CreatureAI* GetAI_npc_memory(Creature* pCreature) -{ - return new npc_memoryAI(pCreature); -} - -// THIS AI NEEDS MORE IMPROVEMENTS -struct npc_argent_soldierAI : public npc_escortAI -{ - npc_argent_soldierAI(Creature* pCreature) : npc_escortAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - me->SetReactState(REACT_DEFENSIVE); - SetDespawnAtEnd(false); - uiWaypoint = 0; - } - - ScriptedInstance* pInstance; - - uint8 uiWaypoint; - - void WaypointReached(uint32 uiPoint) - { - if (uiPoint == 0) - { - switch(uiWaypoint) - { - case 0: - me->SetOrientation(5.81); - break; - case 1: - me->SetOrientation(4.60); - break; - case 2: - me->SetOrientation(2.79); - break; - } - - me->SendMovementFlagUpdate(); - } - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch(me->GetEntry()) - { - case NPC_ARGENT_LIGHWIELDER: - switch(uiType) - { - case 0: - AddWaypoint(0,712.14,628.42,411.88); - break; - case 1: - AddWaypoint(0,742.44,650.29,411.79); - break; - case 2: - AddWaypoint(0,783.33,615.29,411.84); - break; - } - break; - case NPC_ARGENT_MONK: - switch(uiType) - { - case 0: - AddWaypoint(0,713.12,632.97,411.90); - break; - case 1: - AddWaypoint(0,746.73,650.24,411.56); - break; - case 2: - AddWaypoint(0,781.32,610.54,411.82); - break; - } - break; - case NPC_PRIESTESS: - switch(uiType) - { - case 0: - AddWaypoint(0,715.06,637.07,411.91); - break; - case 1: - AddWaypoint(0,750.72,650.20,411.77); - break; - case 2: - AddWaypoint(0,779.77,607.03,411.81); - break; - } - break; - } - - Start(false,true,0); - uiWaypoint = uiType; - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(DATA_ARGENT_SOLDIER_DEFEATED,pInstance->GetData(DATA_ARGENT_SOLDIER_DEFEATED) + 1); - } -}; - -CreatureAI* GetAI_npc_argent_soldier(Creature* pCreature) -{ - return new npc_argent_soldierAI(pCreature); -} - -void AddSC_boss_argent_challenge() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "boss_eadric"; - NewScript->GetAI = &GetAI_boss_eadric; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_paletress"; - NewScript->GetAI = &GetAI_boss_paletress; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_memory"; - NewScript->GetAI = &GetAI_npc_memory; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_argent_soldier"; - NewScript->GetAI = &GetAI_npc_argent_soldier; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp b/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp deleted file mode 100644 index e1f4586ca6c..00000000000 --- a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Black Knight -SD%Complete: 80% -SDComment: missing yells. not sure about timers. -SDCategory: Trial of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "trial_of_the_champion.h" - -enum eSpells -{ - //phase 1 - SPELL_PLAGUE_STRIKE = 67884, - SPELL_PLAGUE_STRIKE_2 = 67724, - SPELL_ICY_TOUCH_H = 67881, - SPELL_ICY_TOUCH = 67718, - SPELL_DEATH_RESPITE = 67745, - SPELL_DEATH_RESPITE_2 = 68306, - SPELL_DEATH_RESPITE_3 = 66798, - SPELL_OBLITERATE_H = 67883, - SPELL_OBLITERATE = 67725, - //in this phase should rise herald (the spell is missing) - - //phase 2 - During this phase, the Black Knight will use the same abilities as in phase 1, except for Death's Respite - SPELL_ARMY_DEAD = 67761, - SPELL_DESECRATION = 67778, - SPELL_DESECRATION_2 = 67778, - SPELL_GHOUL_EXPLODE = 67751, - - //phase 3 - SPELL_DEATH_BITE_H = 67875, - SPELL_DEATH_BITE = 67808, - SPELL_MARKED_DEATH = 67882, - SPELL_MARKED_DEATH_2 = 67823, - - SPELL_BLACK_KNIGHT_RES = 67693, - - SPELL_LEAP = 67749, - SPELL_LEAP_H = 67880 -}; - -enum eModels -{ - MODEL_SKELETON = 29846, - MODEL_GHOST = 21300 -}; - -enum ePhases -{ - PHASE_UNDEAD = 1, - PHASE_SKELETON = 2, - PHASE_GHOST = 3 -}; - -struct boss_black_knightAI : public ScriptedAI -{ - boss_black_knightAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - std::list SummonList; - - bool bEventInProgress; - bool bEvent; - bool bSummonArmy; - bool bDeathArmyDone; - - uint8 uiPhase; - - uint32 uiPlagueStrikeTimer; - uint32 uiIcyTouchTimer; - uint32 uiDeathRespiteTimer; - uint32 uiObliterateTimer; - uint32 uiDesecration; - uint32 uiResurrectTimer; - uint32 uiDeathArmyCheckTimer; - uint32 uiGhoulExplodeTimer; - uint32 uiDeathBiteTimer; - uint32 uiMarkedDeathTimer; - - void Reset() - { - RemoveSummons(); - me->SetDisplayId(me->GetNativeDisplayId()); - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - - bEventInProgress = false; - bEvent = false; - bSummonArmy = false; - bDeathArmyDone = false; - - uiPhase = PHASE_UNDEAD; - - uiIcyTouchTimer = urand(5000,9000); - uiPlagueStrikeTimer = urand(10000,13000); - uiDeathRespiteTimer = urand(15000,16000); - uiObliterateTimer = urand(17000,19000); - uiDesecration = urand(15000,16000); - uiDeathArmyCheckTimer = 7000; - uiResurrectTimer = 4000; - uiGhoulExplodeTimer = 8000; - uiDeathBiteTimer = urand (2000,4000); - uiMarkedDeathTimer = urand (5000,7000); - } - - void RemoveSummons() - { - if (SummonList.empty()) - return; - - for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - if (pTemp) - pTemp->DisappearAndDie(); - } - SummonList.clear(); - } - - void JustSummoned(Creature* pSummon) - { - SummonList.push_back(pSummon->GetGUID()); - pSummon->AI()->AttackStart(me->getVictim()); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (bEventInProgress) - if (uiResurrectTimer <= uiDiff) - { - me->SetHealth(me->GetMaxHealth()); - DoCast(me,SPELL_BLACK_KNIGHT_RES,true); - uiPhase++; - uiResurrectTimer = 4000; - bEventInProgress = false; - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - } else uiResurrectTimer -= uiDiff; - - switch(uiPhase) - { - case PHASE_UNDEAD: - case PHASE_SKELETON: - { - if (uiIcyTouchTimer <= uiDiff) - { - DoCastVictim(SPELL_ICY_TOUCH); - uiIcyTouchTimer = urand(5000,7000); - } else uiIcyTouchTimer -= uiDiff; - if (uiPlagueStrikeTimer <= uiDiff) - { - DoCastVictim(SPELL_ICY_TOUCH); - uiPlagueStrikeTimer = urand(12000,15000); - } else uiPlagueStrikeTimer -= uiDiff; - if (uiObliterateTimer <= uiDiff) - { - DoCastVictim(SPELL_OBLITERATE); - uiObliterateTimer = urand(17000,19000); - } else uiObliterateTimer -= uiDiff; - switch(uiPhase) - { - case PHASE_UNDEAD: - { - if (uiDeathRespiteTimer <= uiDiff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_DEATH_RESPITE); - } - uiDeathRespiteTimer = urand(15000,16000); - } else uiDeathRespiteTimer -= uiDiff; - break; - } - case PHASE_SKELETON: - { - if (!bSummonArmy) - { - bSummonArmy = true; - me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - DoCast(me, SPELL_ARMY_DEAD); - } - if (!bDeathArmyDone) - if (uiDeathArmyCheckTimer <= uiDiff) - { - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - uiDeathArmyCheckTimer = 0; - bDeathArmyDone = true; - } else uiDeathArmyCheckTimer -= uiDiff; - if (uiDesecration <= uiDiff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_DESECRATION); - } - uiDesecration = urand(15000,16000); - } else uiDesecration -= uiDiff; - if (uiGhoulExplodeTimer <= uiDiff) - { - DoCast(me, SPELL_GHOUL_EXPLODE); - uiGhoulExplodeTimer = 8000; - } else uiGhoulExplodeTimer -= uiDiff; - break; - } - break; - } - break; - } - case PHASE_GHOST: - { - if (uiDeathBiteTimer <= uiDiff) - { - DoCastAOE(SPELL_DEATH_BITE); - uiDeathBiteTimer = urand (2000, 4000); - } else uiDeathBiteTimer -= uiDiff; - if (uiMarkedDeathTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_MARKED_DEATH); - } - uiMarkedDeathTimer = urand (5000, 7000); - } else uiMarkedDeathTimer -= uiDiff; - break; - } - } - - if (!me->hasUnitState(UNIT_STAT_ROOT) && !me->GetHealth()*100 / me->GetMaxHealth() <= 0) - DoMeleeAttackIfReady(); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) - { - if (uiDamage > me->GetHealth() && uiPhase <= PHASE_SKELETON) - { - uiDamage = 0; - me->SetHealth(0); - me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - RemoveSummons(); - switch(uiPhase) - { - case PHASE_UNDEAD: - me->SetDisplayId(MODEL_SKELETON); - break; - case PHASE_SKELETON: - me->SetDisplayId(MODEL_GHOST); - break; - } - bEventInProgress = true; - } - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_BLACK_KNIGHT,DONE); - } -}; - -CreatureAI* GetAI_boss_black_knight(Creature *pCreature) -{ - return new boss_black_knightAI (pCreature); -} - -struct npc_risen_ghoulAI : public ScriptedAI -{ - npc_risen_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiAttackTimer; - - void Reset() - { - uiAttackTimer = 3500; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiAttackTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, (SPELL_LEAP)); - } - uiAttackTimer = 3500; - } else uiAttackTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_risen_ghoul(Creature* pCreature) -{ - return new npc_risen_ghoulAI(pCreature); -} - -struct npc_black_knight_skeletal_gryphonAI : public npc_escortAI -{ - npc_black_knight_skeletal_gryphonAI(Creature* pCreature) : npc_escortAI(pCreature) - { - Start(false,true,0,NULL); - } - - void WaypointReached(uint32 /*i*/) - { - - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - } - -}; - -CreatureAI* GetAI_npc_black_knight_skeletal_gryphon(Creature* pCreature) -{ - return new npc_black_knight_skeletal_gryphonAI(pCreature); -} - -void AddSC_boss_black_knight() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "boss_black_knight"; - NewScript->GetAI = &GetAI_boss_black_knight; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_risen_ghoul"; - NewScript->GetAI = &GetAI_npc_risen_ghoul; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_black_knight_skeletal_gryphon"; - NewScript->GetAI = &GetAI_npc_black_knight_skeletal_gryphon; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp b/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp deleted file mode 100644 index 4bf8143a210..00000000000 --- a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp +++ /dev/null @@ -1,993 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: boss_grand_champions -SD%Complete: 50 % -SDComment: Is missing the ai to make the npcs look for a new mount and use it. -SDCategory: Trial Of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "Vehicle.h" -#include "trial_of_the_champion.h" - -enum eSpells -{ - //Vehicle - SPELL_CHARGE = 63010, - SPELL_SHIELD_BREAKER = 68504, - SPELL_SHIELD = 66482, - - // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior - SPELL_MORTAL_STRIKE = 68783, - SPELL_MORTAL_STRIKE_H = 68784, - SPELL_BLADESTORM = 63784, - SPELL_INTERCEPT = 67540, - SPELL_ROLLING_THROW = 47115, //not implemented in the AI yet... - - // Ambrose Boltspark && Eressea Dawnsinger || Mage - SPELL_FIREBALL = 66042, - SPELL_FIREBALL_H = 68310, - SPELL_BLAST_WAVE = 66044, - SPELL_BLAST_WAVE_H = 68312, - SPELL_HASTE = 66045, - SPELL_POLYMORPH = 66043, - SPELL_POLYMORPH_H = 68311, - - // Colosos && Runok Wildmane || Shaman - SPELL_CHAIN_LIGHTNING = 67529, - SPELL_CHAIN_LIGHTNING_H = 68319, - SPELL_EARTH_SHIELD = 67530, - SPELL_HEALING_WAVE = 67528, - SPELL_HEALING_WAVE_H = 68318, - SPELL_HEX_OF_MENDING = 67534, - - // Jaelyne Evensong && Zul'tore || Hunter - SPELL_DISENGAGE = 68340, //not implemented in the AI yet... - SPELL_LIGHTNING_ARROWS = 66083, - SPELL_MULTI_SHOT = 66081, - SPELL_SHOOT = 65868, - SPELL_SHOOT_H = 67988, - - // Lana Stouthammer Evensong && Deathstalker Visceri || Rouge - SPELL_EVISCERATE = 67709, - SPELL_EVISCERATE_H = 68317, - SPELL_FAN_OF_KNIVES = 67706, - SPELL_POISON_BOTTLE = 67701 -}; - -enum eSeat -{ - SEAT_ID_0 = 0 -}; - -struct Point -{ - float x,y,z; -}; - -const Point MovementPoint[] = -{ - {746.84,623.15,411.41}, - {747.96,620.29,411.09}, - {750.23,618.35,411.09} -}; - -void AggroAllPlayers(Creature* pTemp) -{ - Map::PlayerList const &PlList = pTemp->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - pTemp->SetReactState(REACT_AGGRESSIVE); - pTemp->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(pTemp); - pTemp->AddThreat(pPlayer, 0.0f); - } - } - } -} - -bool GrandChampionsOutVehicle(Creature* me) -{ - ScriptedInstance* pInstance = me->GetInstanceData(); - - if (!pInstance) - return false; - - Creature* pGrandChampion1 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_1)); - Creature* pGrandChampion2 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_2)); - Creature* pGrandChampion3 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_3)); - - if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) - { - if (!pGrandChampion1->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && - !pGrandChampion2->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && - !pGrandChampion3->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return true; - } - - return false; -} - -/* -* Generic AI for vehicles used by npcs in ToC, it needs more improvements. * -* Script Complete: 25%. * -*/ - -struct generic_vehicleAI_toc5AI : public npc_escortAI -{ - generic_vehicleAI_toc5AI(Creature* pCreature) : npc_escortAI(pCreature) - { - SetDespawnAtEnd(false); - uiWaypointPath = 0; - - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiChargeTimer; - uint32 uiShieldBreakerTimer; - uint32 uiBuffTimer; - - uint32 uiWaypointPath; - - void Reset() - { - uiChargeTimer = 5000; - uiShieldBreakerTimer = 8000; - uiBuffTimer = urand(30000,60000); - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch(uiType) - { - case 1: - AddWaypoint(0,747.36,634.07,411.572); - AddWaypoint(1,780.43,607.15,411.82); - AddWaypoint(2,785.99,599.41,411.92); - AddWaypoint(3,778.44,601.64,411.79); - uiWaypointPath = 1; - break; - case 2: - AddWaypoint(0,747.35,634.07,411.57); - AddWaypoint(1,768.72,581.01,411.92); - AddWaypoint(2,763.55,590.52,411.71); - uiWaypointPath = 2; - break; - case 3: - AddWaypoint(0,747.35,634.07,411.57); - AddWaypoint(1,784.02,645.33,412.39); - AddWaypoint(2,775.67,641.91,411.91); - uiWaypointPath = 3; - break; - } - - if (uiType <= 3) - Start(false,true,0,NULL); - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 2: - if (pInstance && uiWaypointPath == 3 || uiWaypointPath == 2) - pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); - break; - case 3: - if (pInstance) - pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); - break; - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoCastSpellShield(); - } - - void DoCastSpellShield() - { - for (uint8 i = 0; i < 3; ++i) - DoCast(me,SPELL_SHIELD,true); - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - if (uiBuffTimer <= uiDiff) - { - if (!me->HasAura(SPELL_SHIELD)) - DoCastSpellShield(); - - uiBuffTimer = urand(30000,45000); - }else uiBuffTimer -= uiDiff; - - if (uiChargeTimer <= uiDiff) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) - { - DoResetThreat(); - me->AddThreat(pPlayer,1.0f); - DoCast(pPlayer, SPELL_CHARGE); - break; - } - } - } - uiChargeTimer = 5000; - }else uiChargeTimer -= uiDiff; - - //dosen't work at all - if (uiShieldBreakerTimer <= uiDiff) - { - Vehicle *pVehicle = me->GetVehicleKit(); - if (!pVehicle) - return; - - if (Unit* pPassenger = pVehicle->GetPassenger(SEAT_ID_0)) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,10.0f,30.0f,false)) - { - pPassenger->CastSpell(pPlayer,SPELL_SHIELD_BREAKER,true); - break; - } - } - } - } - uiShieldBreakerTimer = 7000; - }else uiShieldBreakerTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_generic_vehicleAI_toc5(Creature* pCreature) -{ - return new generic_vehicleAI_toc5AI(pCreature); -} - -// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior -struct boss_warrior_toc5AI : public ScriptedAI -{ - boss_warrior_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiBladeStormTimer; - uint32 uiInterceptTimer; - uint32 uiMortalStrikeTimer; - uint32 uiAttackTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiBladeStormTimer = urand(15000,20000); - uiInterceptTimer = 7000; - uiMortalStrikeTimer = urand(8000,12000); - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiInterceptTimer <= uiDiff) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) - { - DoResetThreat(); - me->AddThreat(pPlayer,5.0f); - DoCast(pPlayer,SPELL_INTERCEPT); - break; - } - } - } - uiInterceptTimer = 7000; - } else uiInterceptTimer -= uiDiff; - - if (uiBladeStormTimer <= uiDiff) - { - DoCastVictim(SPELL_BLADESTORM); - uiBladeStormTimer = urand(15000,20000); - } else uiBladeStormTimer -= uiDiff; - - if (uiMortalStrikeTimer <= uiDiff) - { - DoCastVictim(SPELL_MORTAL_STRIKE); - uiMortalStrikeTimer = urand(8000,12000); - } else uiMortalStrikeTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_warrior_toc5(Creature* pCreature) -{ - return new boss_warrior_toc5AI(pCreature); -} - -// Ambrose Boltspark && Eressea Dawnsinger || Mage -struct boss_mage_toc5AI : public ScriptedAI -{ - boss_mage_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiFireBallTimer; - uint32 uiBlastWaveTimer; - uint32 uiHasteTimer; - uint32 uiPolymorphTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiFireBallTimer = 5000; - uiPolymorphTimer = 8000; - uiBlastWaveTimer = 12000; - uiHasteTimer = 22000; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (uiFireBallTimer <= uiDiff) - { - if (me->getVictim()) - DoCastVictim(SPELL_FIREBALL); - uiFireBallTimer = 5000; - } else uiFireBallTimer -= uiDiff; - - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiFireBallTimer <= uiDiff) - { - DoCastVictim(SPELL_FIREBALL); - uiFireBallTimer = 5000; - } else uiFireBallTimer -= uiDiff; - - if (uiPolymorphTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_POLYMORPH); - uiPolymorphTimer = 8000; - } else uiPolymorphTimer -= uiDiff; - - if (uiBlastWaveTimer <= uiDiff) - { - DoCastAOE(SPELL_BLAST_WAVE,false); - uiBlastWaveTimer = 13000; - } else uiBlastWaveTimer -= uiDiff; - - if (uiHasteTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - - DoCast(me,SPELL_HASTE); - uiHasteTimer = 22000; - } else uiHasteTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_mage_toc5(Creature* pCreature) -{ - return new boss_mage_toc5AI(pCreature); -} - -// Colosos && Runok Wildmane || Shaman -struct boss_shaman_toc5AI : public ScriptedAI -{ - boss_shaman_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiChainLightningTimer; - uint32 uiEartShieldTimer; - uint32 uiHealingWaveTimer; - uint32 uiHexMendingTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiChainLightningTimer = 16000; - uiHealingWaveTimer = 12000; - uiEartShieldTimer = urand(30000,35000); - uiHexMendingTimer = urand(20000,25000); - } - - void EnterCombat(Unit* pWho) - { - DoCast(me,SPELL_EARTH_SHIELD); - DoCast(pWho,SPELL_HEX_OF_MENDING); - }; - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiChainLightningTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget,SPELL_CHAIN_LIGHTNING); - - uiChainLightningTimer = 16000; - } else uiChainLightningTimer -= uiDiff; - - if (uiHealingWaveTimer <= uiDiff) - { - bool bChance = urand(0,1); - - if (!bChance) - { - if (Unit* pFriend = DoSelectLowestHpFriendly(40)) - DoCast(pFriend,SPELL_HEALING_WAVE); - } else - DoCast(me,SPELL_HEALING_WAVE); - - uiHealingWaveTimer = 12000; - } else uiHealingWaveTimer -= uiDiff; - - if (uiEartShieldTimer <= uiDiff) - { - DoCast(me,SPELL_EARTH_SHIELD); - - uiEartShieldTimer = urand(30000,35000); - } else uiEartShieldTimer -= uiDiff; - - if (uiHexMendingTimer <= uiDiff) - { - DoCastVictim(SPELL_HEX_OF_MENDING,true); - - uiHexMendingTimer = urand(20000,25000); - } else uiHexMendingTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_shaman_toc5(Creature* pCreature) -{ - return new boss_shaman_toc5AI(pCreature); -} - -// Jaelyne Evensong && Zul'tore || Hunter -struct boss_hunter_toc5AI : public ScriptedAI -{ - boss_hunter_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiShootTimer; - uint32 uiMultiShotTimer; - uint32 uiLightningArrowsTimer; - - uint64 uiTargetGUID; - - bool bShoot; - bool bDone; - bool bHome; - - void Reset() - { - uiShootTimer = 12000; - uiMultiShotTimer = 0; - uiLightningArrowsTimer = 7000; - - uiTargetGUID = 0; - - bShoot = false; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiLightningArrowsTimer <= uiDiff) - { - DoCastAOE(SPELL_LIGHTNING_ARROWS,false); - uiLightningArrowsTimer = 7000; - } else uiLightningArrowsTimer -= uiDiff; - - if (uiShootTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_FARTHEST,0,30.0f)) - { - uiTargetGUID = pTarget->GetGUID(); - DoCast(pTarget, SPELL_SHOOT); - } - uiShootTimer = 12000; - uiMultiShotTimer = 3000; - bShoot = true; - } else uiShootTimer -= uiDiff; - - if (bShoot && uiMultiShotTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - Unit* pTarget = Unit::GetUnit(*me, uiTargetGUID); - - if (pTarget && me->IsInRange(pTarget,5.0f,30.0f,false)) - { - DoCast(pTarget,SPELL_MULTI_SHOT); - } else - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,5.0f,30.0f,false)) - { - DoCast(pTarget,SPELL_MULTI_SHOT); - break; - } - } - } - } - bShoot = false; - } else uiMultiShotTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_hunter_toc5(Creature* pCreature) -{ - return new boss_hunter_toc5AI(pCreature); -} - -// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge -struct boss_rouge_toc5AI : public ScriptedAI -{ - boss_rouge_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - uint32 uiEviscerateTimer; - uint32 uiFanKivesTimer; - uint32 uiPosionBottleTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiEviscerateTimer = 8000; - uiFanKivesTimer = 14000; - uiPosionBottleTimer = 19000; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - } else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiEviscerateTimer <= uiDiff) - { - DoCast(me->getVictim(),SPELL_EVISCERATE); - uiEviscerateTimer = 8000; - } else uiEviscerateTimer -= uiDiff; - - if (uiFanKivesTimer <= uiDiff) - { - DoCastAOE(SPELL_FAN_OF_KNIVES,false); - uiFanKivesTimer = 14000; - } else uiFanKivesTimer -= uiDiff; - - if (uiPosionBottleTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget,SPELL_POISON_BOTTLE); - uiPosionBottleTimer = 19000; - } else uiPosionBottleTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_rouge_toc5(Creature* pCreature) -{ - return new boss_rouge_toc5AI(pCreature); -} - -void AddSC_boss_grand_champions() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "generic_vehicleAI_toc5"; - NewScript->GetAI = &GetAI_generic_vehicleAI_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_warrior_toc5"; - NewScript->GetAI = &GetAI_boss_warrior_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_mage_toc5"; - NewScript->GetAI = &GetAI_boss_mage_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_shaman_toc5"; - NewScript->GetAI = &GetAI_boss_shaman_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_hunter_toc5"; - NewScript->GetAI = &GetAI_boss_hunter_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_rouge_toc5"; - NewScript->GetAI = &GetAI_boss_rouge_toc5; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp b/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp deleted file mode 100644 index 04b671ec11c..00000000000 --- a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* ScriptData -SDName: Instance Trial of the Champion -SDComment: -SDCategory: Trial Of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" - -#define MAX_ENCOUNTER 4 - -struct instance_trial_of_the_champion : public ScriptedInstance -{ - instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint8 uiMovementDone; - uint8 uiGrandChampionsDeaths; - uint8 uiArgentSoldierDeaths; - - uint64 uiAnnouncerGUID; - uint64 uiMainGateGUID; - uint64 uiGrandChampionVehicle1GUID; - uint64 uiGrandChampionVehicle2GUID; - uint64 uiGrandChampionVehicle3GUID; - uint64 uiGrandChampion1GUID; - uint64 uiGrandChampion2GUID; - uint64 uiGrandChampion3GUID; - uint64 uiChampionLootGUID; - uint64 uiArgentChampionGUID; - - std::list VehicleList; - - std::string str_data; - - bool bDone; - - void Initialize() - { - uiMovementDone = 0; - uiGrandChampionsDeaths = 0; - uiArgentSoldierDeaths = 0; - - uiAnnouncerGUID = 0; - uiMainGateGUID = 0; - uiGrandChampionVehicle1GUID = 0; - uiGrandChampionVehicle2GUID = 0; - uiGrandChampionVehicle3GUID = 0; - uiGrandChampion1GUID = 0; - uiGrandChampion2GUID = 0; - uiGrandChampion3GUID = 0; - uiChampionLootGUID = 0; - uiArgentChampionGUID = 0; - - bDone = false; - - VehicleList.clear(); - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - } - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - uint32 TeamInInstance = 0; - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - TeamInInstance = pPlayer->GetTeam(); - } - - switch(pCreature->GetEntry()) - { - // Champions - case VEHICLE_MOKRA_SKILLCRUSHER_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT, ALLIANCE); - break; - case VEHICLE_ERESSEA_DAWNSINGER_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_AMBROSE_BOLTSPARK_MOUNT, ALLIANCE); - break; - case VEHICLE_RUNOK_WILDMANE_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_COLOSOS_MOUNT, ALLIANCE); - break; - case VEHICLE_ZUL_TORE_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_EVENSONG_MOUNT, ALLIANCE); - break; - case VEHICLE_DEATHSTALKER_VESCERI_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_LANA_STOUTHAMMER_MOUNT, ALLIANCE); - break; - // Coliseum Announcer || Just NPC_JAEREN must be spawned. - case NPC_JAEREN: - uiAnnouncerGUID = pCreature->GetGUID(); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_ARELAS,ALLIANCE); - break; - case VEHICLE_ARGENT_WARHORSE: - case VEHICLE_ARGENT_BATTLEWORG: - VehicleList.push_back(pCreature->GetGUID()); - break; - case NPC_EADRIC: - case NPC_PALETRESS: - uiArgentChampionGUID = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGO, bool /*bAdd*/) - { - switch(pGO->GetEntry()) - { - case GO_MAIN_GATE: - uiMainGateGUID = pGO->GetGUID(); - break; - case GO_CHAMPIONS_LOOT: - case GO_CHAMPIONS_LOOT_H: - uiChampionLootGUID = pGO->GetGUID(); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case DATA_MOVEMENT_DONE: - uiMovementDone = uiData; - if (uiMovementDone == 3) - { - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - pAnnouncer->AI()->SetData(DATA_IN_POSITION,0); - } - break; - case BOSS_GRAND_CHAMPIONS: - m_auiEncounter[0] = uiData; - if (uiData == IN_PROGRESS) - { - for (std::list::const_iterator itr = VehicleList.begin(); itr != VehicleList.end(); ++itr) - if (Creature* pSummon = instance->GetCreature(*itr)) - pSummon->RemoveFromWorld(); - }else if (uiData == DONE) - { - ++uiGrandChampionsDeaths; - if (uiGrandChampionsDeaths == 3) - { - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - } - } - break; - case DATA_ARGENT_SOLDIER_DEFEATED: - uiArgentSoldierDeaths = uiData; - if (uiArgentSoldierDeaths == 9) - { - if (Creature* pBoss = instance->GetCreature(uiArgentChampionGUID)) - { - pBoss->GetMotionMaster()->MovePoint(0,746.88,618.74,411.06); - pBoss->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pBoss->SetReactState(REACT_AGGRESSIVE); - } - } - break; - case BOSS_ARGENT_CHALLENGE_E: - m_auiEncounter[1] = uiData; - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - break; - case BOSS_ARGENT_CHALLENGE_P: - m_auiEncounter[2] = uiData; - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - break; - } - - if (uiData == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 uiData) - { - switch(uiData) - { - case BOSS_GRAND_CHAMPIONS: return m_auiEncounter[0]; - case BOSS_ARGENT_CHALLENGE_E: return m_auiEncounter[1]; - case BOSS_ARGENT_CHALLENGE_P: return m_auiEncounter[2]; - case BOSS_BLACK_KNIGHT: return m_auiEncounter[3]; - - case DATA_MOVEMENT_DONE: return uiMovementDone; - case DATA_ARGENT_SOLDIER_DEFEATED: return uiArgentSoldierDeaths; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_ANNOUNCER: return uiAnnouncerGUID; - case DATA_MAIN_GATE: return uiMainGateGUID; - - case DATA_GRAND_CHAMPION_1: return uiGrandChampion1GUID; - case DATA_GRAND_CHAMPION_2: return uiGrandChampion2GUID; - case DATA_GRAND_CHAMPION_3: return uiGrandChampion3GUID; - } - - return 0; - } - - void SetData64(uint32 uiType, uint64 uiData) - { - switch(uiType) - { - case DATA_GRAND_CHAMPION_1: - uiGrandChampion1GUID = uiData; - break; - case DATA_GRAND_CHAMPION_2: - uiGrandChampion2GUID = uiData; - break; - case DATA_GRAND_CHAMPION_3: - uiGrandChampion3GUID = uiData; - break; - } - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - saveStream << "T C " << m_auiEncounter[0] - << " " << m_auiEncounter[1] - << " " << m_auiEncounter[2] - << " " << m_auiEncounter[3] - << " " << uiGrandChampionsDeaths - << " " << uiMovementDone; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; - - if (dataHead1 == 'T' && dataHead2 == 'C') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiGrandChampionsDeaths = data4; - uiMovementDone = data5; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_trial_of_the_champion(Map* pMap) -{ - return new instance_trial_of_the_champion(pMap); -} - -void AddSC_instance_trial_of_the_champion() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_trial_of_the_champion"; - newscript->GetInstanceData = &GetInstanceData_instance_trial_of_the_champion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp b/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp deleted file mode 100644 index 090b64b96cc..00000000000 --- a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Trial Of the Champion -SD%Complete: -SDComment: -SDCategory: trial_of_the_champion -EndScriptData */ - -/* ContentData -npc_announcer_toc5 -EndContentData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" -#include "Vehicle.h" - -#define GOSSIP_START_EVENT1 "I'm ready to start challenge." -#define GOSSIP_START_EVENT2 "I'm ready for the next challenge." - -#define ORIENTATION 4.714 - -/*###### -## npc_announcer_toc5 -######*/ - -const Position SpawnPosition = {746.261,657.401,411.681,4.65}; - -struct npc_announcer_toc5AI : public ScriptedAI -{ - npc_announcer_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - uiSummonTimes = 0; - uiPosition = 0; - uiLesserChampions = 0; - - uiFirstBoss = 0; - uiSecondBoss = 0; - uiThirdBoss = 0; - - uiArgentChampion = 0; - - uiPhase = 0; - uiTimer = 0; - - uiVehicle1GUID = 0; - uiVehicle2GUID = 0; - uiVehicle3GUID = 0; - - Champion1List.clear(); - Champion2List.clear(); - Champion3List.clear(); - - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - SetGrandChampionsForEncounter(); - SetArgentChampion(); - } - - ScriptedInstance* pInstance; - - uint8 uiSummonTimes; - uint8 uiPosition; - uint8 uiLesserChampions; - - uint32 uiArgentChampion; - - uint32 uiFirstBoss; - uint32 uiSecondBoss; - uint32 uiThirdBoss; - - uint32 uiPhase; - uint32 uiTimer; - - uint64 uiVehicle1GUID; - uint64 uiVehicle2GUID; - uint64 uiVehicle3GUID; - - uint64 uiGrandChampionBoss1; - - std::list Champion1List; - std::list Champion2List; - std::list Champion3List; - - void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) - { - uiTimer = uiTimerStep; - if (bNextStep) - ++uiPhase; - else - uiPhase = uiPhaseStep; - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch (uiType) - { - case DATA_START: - DoSummonGrandChampion(uiFirstBoss); - NextStep(10000,false,1); - break; - case DATA_IN_POSITION: //movement done. - me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); - if (GameObject* pGO = GameObject::GetGameObject(*me, pInstance->GetData64(DATA_MAIN_GATE))) - pInstance->HandleGameObject(pGO->GetGUID(),false); - NextStep(10000,false,3); - break; - case DATA_LESSER_CHAMPIONS_DEFEATED: - { - ++uiLesserChampions; - std::list TempList; - if (uiLesserChampions == 3 || uiLesserChampions == 6) - { - switch(uiLesserChampions) - { - case 3: - TempList = Champion2List; - break; - case 6: - TempList = Champion3List; - break; - } - - for (std::list::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr) - if (Creature* pSummon = Unit::GetCreature(*me, *itr)) - AggroAllPlayers(pSummon); - }else if (uiLesserChampions == 9) - StartGrandChampionsAttack(); - - break; - } - } - } - - void StartGrandChampionsAttack() - { - Creature* pGrandChampion1 = Unit::GetCreature(*me, uiVehicle1GUID); - Creature* pGrandChampion2 = Unit::GetCreature(*me, uiVehicle2GUID); - Creature* pGrandChampion3 = Unit::GetCreature(*me, uiVehicle3GUID); - - if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) - { - AggroAllPlayers(pGrandChampion1); - AggroAllPlayers(pGrandChampion2); - AggroAllPlayers(pGrandChampion3); - } - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (uiPointId == 1) - { - me->SetOrientation(ORIENTATION); - me->SendMovementFlagUpdate(); - } - } - - void DoSummonGrandChampion(uint32 uiBoss) - { - ++uiSummonTimes; - uint32 VEHICLE_TO_SUMMON1 = 0; - uint32 VEHICLE_TO_SUMMON2 = 0; - switch(uiBoss) - { - case 0: - VEHICLE_TO_SUMMON1 = VEHICLE_MOKRA_SKILLCRUSHER_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_ORGRIMMAR_WOLF; - break; - case 1: - VEHICLE_TO_SUMMON1 = VEHICLE_ERESSEA_DAWNSINGER_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_SILVERMOON_HAWKSTRIDER; - break; - case 2: - VEHICLE_TO_SUMMON1 = VEHICLE_RUNOK_WILDMANE_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_THUNDER_BLUFF_KODO; - break; - case 3: - VEHICLE_TO_SUMMON1 = VEHICLE_ZUL_TORE_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_DARKSPEAR_RAPTOR; - break; - case 4: - VEHICLE_TO_SUMMON1 = VEHICLE_DEATHSTALKER_VESCERI_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_FORSAKE_WARHORSE; - break; - default: - return; - } - - if (Creature* pBoss = me->SummonCreature(VEHICLE_TO_SUMMON1,SpawnPosition)) - { - switch(uiSummonTimes) - { - case 1: - { - uiVehicle1GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss1 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle1GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss1 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_1,uiVehicle1GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_1,uiGrandChampionBoss1); - } - pBoss->AI()->SetData(1,0); - break; - } - case 2: - { - uiVehicle2GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss2 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle2GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss2 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_2,uiVehicle2GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_2,uiGrandChampionBoss2); - } - pBoss->AI()->SetData(2,0); - break; - } - case 3: - { - uiVehicle3GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss3 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle3GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss3 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_3,uiVehicle3GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_3,uiGrandChampionBoss3); - } - pBoss->AI()->SetData(3,0); - break; - } - default: - return; - } - - for (uint8 i = 0; i < 3; ++i) - { - if (Creature* pAdd = me->SummonCreature(VEHICLE_TO_SUMMON2,SpawnPosition,TEMPSUMMON_CORPSE_DESPAWN)) - { - switch(uiSummonTimes) - { - case 1: - Champion1List.push_back(pAdd->GetGUID()); - break; - case 2: - Champion2List.push_back(pAdd->GetGUID()); - break; - case 3: - Champion3List.push_back(pAdd->GetGUID()); - break; - } - - switch(i) - { - case 0: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI); - break; - case 1: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2); - break; - case 2: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2 + M_PI); - break; - } - } - - } - } - } - - void DoStartArgentChampionEncounter() - { - me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); - - if (Creature* pBoss = me->SummonCreature(uiArgentChampion,SpawnPosition)) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_LIGHWIELDER,SpawnPosition)) - pTrash->AI()->SetData(i,0); - if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_MONK,SpawnPosition)) - pTrash->AI()->SetData(i,0); - if (Creature* pTrash = me->SummonCreature(NPC_PRIESTESS,SpawnPosition)) - pTrash->AI()->SetData(i,0); - } - } - } - - void SetGrandChampionsForEncounter() - { - uiFirstBoss = urand(0,4); - - while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss) - { - uiSecondBoss = urand(0,4); - uiThirdBoss = urand(0,4); - } - } - - void SetArgentChampion() - { - uint8 uiTempBoss = urand(0,1); - - switch(uiTempBoss) - { - case 0: - uiArgentChampion = NPC_EADRIC; - break; - case 1: - uiArgentChampion = NPC_PALETRESS; - break; - } - } - - void StartEncounter() - { - if (!pInstance) - return; - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - if (pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) - { - if (pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED) - { - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) - me->AI()->SetData(DATA_START,0); - - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE) - DoStartArgentChampionEncounter(); - } - - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) - me->SummonCreature(VEHICLE_BLACK_KNIGHT,769.834,651.915,447.035,0); - } - } - - void AggroAllPlayers(Creature* pTemp) - { - Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - pTemp->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetReactState(REACT_AGGRESSIVE); - pTemp->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(pTemp); - pTemp->AddThreat(pPlayer, 0.0f); - } - } - } - } - - - void UpdateAI(const uint32 uiDiff) - { - ScriptedAI::UpdateAI(uiDiff); - - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - DoSummonGrandChampion(uiSecondBoss); - NextStep(10000,true); - break; - case 2: - DoSummonGrandChampion(uiThirdBoss); - NextStep(0,false); - break; - case 3: - if (!Champion1List.empty()) - { - for (std::list::const_iterator itr = Champion1List.begin(); itr != Champion1List.end(); ++itr) - if (Creature* pSummon = Unit::GetCreature(*me, *itr)) - AggroAllPlayers(pSummon); - NextStep(0,false); - } - break; - } - } else uiTimer -= uiDiff; - - if (!UpdateVictim()) - return; - } - - void JustSummoned(Creature* pSummon) - { - if (pInstance && pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) - { - pSummon->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pSummon->SetReactState(REACT_PASSIVE); - } - } - - void SummonedCreatureDespawn(Creature* pSummon) - { - switch(pSummon->GetEntry()) - { - case VEHICLE_DARNASSIA_NIGHTSABER: - case VEHICLE_EXODAR_ELEKK: - case VEHICLE_STORMWIND_STEED: - case VEHICLE_GNOMEREGAN_MECHANOSTRIDER: - case VEHICLE_IRONFORGE_RAM: - case VEHICLE_FORSAKE_WARHORSE: - case VEHICLE_THUNDER_BLUFF_KODO: - case VEHICLE_ORGRIMMAR_WOLF: - case VEHICLE_SILVERMOON_HAWKSTRIDER: - case VEHICLE_DARKSPEAR_RAPTOR: - me->AI()->SetData(DATA_LESSER_CHAMPIONS_DEFEATED,0); - break; - } - } -}; - -CreatureAI* GetAI_npc_announcer_toc5(Creature* pCreature) -{ - return new npc_announcer_toc5AI(pCreature); -} - -bool GossipHello_npc_announcer_toc5(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && - pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && - pInstance->GetData(BOSS_BLACK_KNIGHT) == DONE && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) - return false; - - if (pInstance && - pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED && - pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - else if (pInstance) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_announcer_toc5(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_announcer_toc5AI, pCreature->AI())->StartEncounter(); - } - - return true; -} - -void AddSC_trial_of_the_champion() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "npc_announcer_toc5"; - NewScript->GetAI = &GetAI_npc_announcer_toc5; - NewScript->pGossipHello = &GossipHello_npc_announcer_toc5; - NewScript->pGossipSelect = &GossipSelect_npc_announcer_toc5; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h b/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h deleted file mode 100644 index 221c7c0412f..00000000000 --- a/src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_TOC_H -#define DEF_TOC_H - - -enum eData -{ - BOSS_GRAND_CHAMPIONS, - BOSS_ARGENT_CHALLENGE_E, - BOSS_ARGENT_CHALLENGE_P, - BOSS_BLACK_KNIGHT, - DATA_MOVEMENT_DONE, - DATA_LESSER_CHAMPIONS_DEFEATED, - DATA_START, - DATA_IN_POSITION, - DATA_ARGENT_SOLDIER_DEFEATED -}; - -enum Data64 -{ - DATA_ANNOUNCER, - DATA_MAIN_GATE, - - DATA_GRAND_CHAMPION_VEHICLE_1, - DATA_GRAND_CHAMPION_VEHICLE_2, - DATA_GRAND_CHAMPION_VEHICLE_3, - - DATA_GRAND_CHAMPION_1, - DATA_GRAND_CHAMPION_2, - DATA_GRAND_CHAMPION_3 -}; - -enum eNpcs -{ - // Horde Champions - NPC_MOKRA = 35572, - NPC_ERESSEA = 35569, - NPC_RUNOK = 35571, - NPC_ZULTORE = 35570, - NPC_VISCERI = 35617, - - // Alliance Champions - NPC_JACOB = 34705, - NPC_AMBROSE = 34702, - NPC_COLOSOS = 34701, - NPC_JAELYNE = 34657, - NPC_LANA = 34703, - - NPC_EADRIC = 35119, - NPC_PALETRESS = 34928, - - NPC_ARGENT_LIGHWIELDER = 35309, - NPC_ARGENT_MONK = 35305, - NPC_PRIESTESS = 35307, - - NPC_BLACK_KNIGHT = 35451, - - NPC_RISEN_JAEREN = 35545, - NPC_RISEN_ARELAS = 35564, - - NPC_JAEREN = 35004, - NPC_ARELAS = 35005 -}; - -enum eGameObjects -{ - GO_MAIN_GATE = 195647, - - GO_CHAMPIONS_LOOT = 195709, - GO_CHAMPIONS_LOOT_H = 195710, - - GO_EADRIC_LOOT = 195374, - GO_EADRIC_LOOT_H = 195375, - - GO_PALETRESS_LOOT = 195323, - GO_PALETRESS_LOOT_H = 195324 -}; - -enum eVehicles -{ - //Grand Champions Alliance Vehicles - VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT = 35637, - VEHICLE_AMBROSE_BOLTSPARK_MOUNT = 35633, - VEHICLE_COLOSOS_MOUNT = 35768, - VEHICLE_EVENSONG_MOUNT = 34658, - VEHICLE_LANA_STOUTHAMMER_MOUNT = 35636, - //Faction Champions (ALLIANCE) - VEHICLE_DARNASSIA_NIGHTSABER = 33298, - VEHICLE_EXODAR_ELEKK = 33416, - VEHICLE_STORMWIND_STEED = 33297, - VEHICLE_GNOMEREGAN_MECHANOSTRIDER = 33301, - VEHICLE_IRONFORGE_RAM = 33408, - //Grand Champions Horde Vehicles - VEHICLE_MOKRA_SKILLCRUSHER_MOUNT = 35638, - VEHICLE_ERESSEA_DAWNSINGER_MOUNT = 35635, - VEHICLE_RUNOK_WILDMANE_MOUNT = 35640, - VEHICLE_ZUL_TORE_MOUNT = 35641, - VEHICLE_DEATHSTALKER_VESCERI_MOUNT = 35634, - //Faction Champions (HORDE) - VEHICLE_FORSAKE_WARHORSE = 33414, - VEHICLE_THUNDER_BLUFF_KODO = 33300, - VEHICLE_ORGRIMMAR_WOLF = 33409, - VEHICLE_SILVERMOON_HAWKSTRIDER = 33418, - VEHICLE_DARKSPEAR_RAPTOR = 33299, - - VEHICLE_ARGENT_WARHORSE = 35644, - VEHICLE_ARGENT_BATTLEWORG = 36558, - - VEHICLE_BLACK_KNIGHT = 35491 -}; - -#endif diff --git a/src/server/scripts/northrend/crystalsong_forest.cpp b/src/server/scripts/northrend/crystalsong_forest.cpp deleted file mode 100644 index 208e9dea5b5..00000000000 --- a/src/server/scripts/northrend/crystalsong_forest.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: CrystalSongForest -SDAuthor: Malcrom -SD%Complete: 99% -SDComment: -SDCategory: CrystalsongForest -Script Data End */ - -#include "ScriptedPch.h" - -/******************************************************* - * npc_warmage_violetstand - *******************************************************/ - -enum Spells -{ - SPELL_TRANSITUS_SHIELD_BEAM = 48310 -}; - -enum NPCs -{ - NPC_TRANSITUS_SHIELD_DUMMY = 27306, - NPC_WARMAGE_SARINA = 32369, - NPC_WARMAGE_HALISTER = 32371, - NPC_WARMAGE_ILSUDRIA = 32372 -}; - -struct npc_warmage_violetstandAI : public Scripted_NoMovementAI -{ - npc_warmage_violetstandAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature){} - - uint64 uiTargetGUID; - - void Reset() - { - uiTargetGUID = 0; - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - if (me->GetEntry() == NPC_WARMAGE_SARINA) - { - if (!uiTargetGUID) - { - std::list orbList; - GetCreatureListWithEntryInGrid(orbList, me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f); - if (!orbList.empty()) - { - for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) - { - if (Creature* pOrb = *itr) - { - if (pOrb->GetPositionY() < 1000) - { - uiTargetGUID = pOrb->GetGUID(); - break; - } - } - } - } - } - }else - { - if (!uiTargetGUID) - if (Creature* pOrb = GetClosestCreatureWithEntry(me,NPC_TRANSITUS_SHIELD_DUMMY,32.0f)) - uiTargetGUID = pOrb->GetGUID(); - - } - - if (Creature* pOrb = me->GetCreature(*me,uiTargetGUID)) - DoCast(pOrb,SPELL_TRANSITUS_SHIELD_BEAM); - - } -}; - -CreatureAI* GetAI_npc_warmage_violetstand(Creature* pCreature) -{ - return new npc_warmage_violetstandAI(pCreature); -} - -void AddSC_crystalsong_forest() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_warmage_violetstand"; - newscript->GetAI = &GetAI_npc_warmage_violetstand; - newscript->RegisterSelf(); -} \ No newline at end of file diff --git a/src/server/scripts/northrend/dalaran.cpp b/src/server/scripts/northrend/dalaran.cpp deleted file mode 100644 index 7d5e76ffe35..00000000000 --- a/src/server/scripts/northrend/dalaran.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Dalaran -SDAuthor: WarHead, MaXiMiUS -SD%Complete: 99% -SDComment: For what is 63990+63991? Same function but don't work correct... -SDCategory: Dalaran -Script Data End */ - -#include "ScriptedPch.h" - -/******************************************************* - * npc_mageguard_dalaran - *******************************************************/ - -enum Spells -{ - SPELL_TRESPASSER_A = 54028, - SPELL_TRESPASSER_H = 54029 -}; - -enum NPCs // All outdoor guards are within 35.0f of these NPCs -{ - NPC_APPLEBOUGH_A = 29547, - NPC_SWEETBERRY_H = 29715, -}; - -struct npc_mageguard_dalaranAI : public Scripted_NoMovementAI -{ - npc_mageguard_dalaranAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_NORMAL, true); - pCreature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - } - - void Reset(){} - - void Aggro(Unit* /*pWho*/){} - - void AttackStart(Unit* /*pWho*/){} - - void MoveInLineOfSight(Unit *pWho) - { - if (!pWho || !pWho->IsInWorld() || pWho->GetZoneId() != 4395) - return; - - if (!me->IsWithinDist(pWho, 65.0f, false)) - return; - - Player *pPlayer = pWho->GetCharmerOrOwnerPlayerOrPlayerItself(); - - if (!pPlayer || pPlayer->isGameMaster() || pPlayer->IsBeingTeleported()) - return; - - switch (me->GetEntry()) - { - case 29254: - if (pPlayer->GetTeam() == HORDE) // Horde unit found in Alliance area - if (GetClosestCreatureWithEntry(me, NPC_APPLEBOUGH_A, 32.0f)) - { - if (me->isInBackInMap(pWho, 12.0f)) // In my line of sight, "outdoors", and behind me - DoCast(pWho, SPELL_TRESPASSER_A); // Teleport the Horde unit out - } - else // In my line of sight, and "indoors" - DoCast(pWho, SPELL_TRESPASSER_A); // Teleport the Horde unit out - break; - case 29255: - if (pPlayer->GetTeam() == ALLIANCE) // Alliance unit found in Horde area - if (GetClosestCreatureWithEntry(me, NPC_SWEETBERRY_H, 32.0f)) - { - if (me->isInBackInMap(pWho, 12.0f)) // In my line of sight, "outdoors", and behind me - DoCast(pWho, SPELL_TRESPASSER_H); // Teleport the Alliance unit out - } - else // In my line of sight, and "indoors" - DoCast(pWho, SPELL_TRESPASSER_H); // Teleport the Alliance unit out - break; - } - me->SetOrientation(me->GetHomePosition().GetOrientation()); - return; - } - - void UpdateAI(const uint32 /*diff*/){} -}; - -CreatureAI* GetAI_npc_mageguard_dalaran(Creature* pCreature) -{ - return new npc_mageguard_dalaranAI(pCreature); -} - -/*###### -## npc_hira_snowdawn -######*/ - -enum eHiraSnowdawn -{ - SPELL_COLD_WEATHER_FLYING = 54197 -}; - -#define GOSSIP_TEXT_TRAIN_HIRA "I seek training to ride a steed." - -bool GossipHello_npc_hira_snowdawn(Player* pPlayer, Creature* pCreature) -{ - if (!pCreature->isVendor() || !pCreature->isTrainer()) - return false; - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_TRAIN_HIRA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); - - if (pPlayer->getLevel() >= 80 && pPlayer->HasSpell(SPELL_COLD_WEATHER_FLYING)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_hira_snowdawn(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRAIN) - pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); - - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -void AddSC_dalaran() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_mageguard_dalaran"; - newscript->GetAI = &GetAI_npc_mageguard_dalaran; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_hira_snowdawn"; - newscript->pGossipHello = &GossipHello_npc_hira_snowdawn; - newscript->pGossipSelect = &GossipSelect_npc_hira_snowdawn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/dragonblight.cpp b/src/server/scripts/northrend/dragonblight.cpp deleted file mode 100644 index 4f26ec1de1a..00000000000 --- a/src/server/scripts/northrend/dragonblight.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Dragonblight -SD%Complete: 100 -SDComment: -SDCategory: Dragonblight -EndScriptData */ - -/* ContentData -npc_alexstrasza_wr_gate -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -enum eEnums -{ - QUEST_RETURN_TO_AG_A = 12499, - QUEST_RETURN_TO_AG_H = 12500, - MOVIE_ID_GATES = 14 -}; - -#define GOSSIP_ITEM_WHAT_HAPPENED "Alexstrasza, can you show me what happened here?" - -bool GossipHello_npc_alexstrasza_wr_gate(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestRewardStatus(QUEST_RETURN_TO_AG_A) || pPlayer->GetQuestRewardStatus(QUEST_RETURN_TO_AG_H)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WHAT_HAPPENED, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_alexstrasza_wr_gate(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->SendMovieStart(MOVIE_ID_GATES); - } - - return true; -} - -/*###### -## npc_inquisitor_hallard. Quest 12321 -######*/ - - -enum eInquisitor -{ - NPC_GODFREY = 27577, - SPELL_HOLY_FIRE = 39323, - - SAY_WP_0 = -1800014, - SAY_WP_1 = -1800015, - SAY_WP_2 = -1800016, - SAY_WP_3 = -1800017, - SAY_WP_4 = -1800018, - SAY_WP_5 = -1800019, - SAY_WP_6 = -1800020, - SAY_WP_7 = -1800021, - SAY_WP_8 = -1800022, - SAY_WP_9 = -1800023, - SAY_WP_10 = -1800024, - SAY_WP_11 = -1800025, - SAY_WP_12 = -1800026, - SAY_WP_13 = -1800027, - SAY_WP_14 = -1800028, - SAY_WP_15 = -1800029, - SAY_WP_16 = -1800030, - SAY_WP_17 = -1800031, - SAY_WP_18 = -1800032, - SAY_WP_19 = -1800033, - SAY_WP_20 = -1800034, - SAY_WP_21 = -1800035, - SAY_WP_22 = -1800036, - SAY_WP_23 = -1800037, - SAY_WP_24 = -1800038, - SAY_WP_25 = -1800039, - SAY_WP_26 = -1800040, - SAY_WP_27 = -1800041 -}; - -#define QUEST_A_RIGHTEOUS_SERMON 12321 - -struct npc_inquisitor_hallardAI : public npc_escortAI -{ - npc_inquisitor_hallardAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - bool Completed; - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - if (!pPlayer) - return; - Creature* Godfrey = me->FindNearestCreature(NPC_GODFREY, 50, true); - if (!Godfrey) - return; - switch (i) - { - case 1: - DoScriptText(SAY_WP_1, me, Godfrey); - me->SetUInt64Value(UNIT_FIELD_TARGET, Godfrey->GetGUID()); - me->HandleEmoteCommand(5); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - case 2: - Godfrey->HandleEmoteCommand(434); - DoScriptText(SAY_WP_2, me, Godfrey); - me->HandleEmoteCommand(15); - break; - case 3: - DoScriptText(SAY_WP_3, me, Godfrey); - me->HandleEmoteCommand(1); - break; - case 4: - DoScriptText(SAY_WP_4, Godfrey); - break; - case 5: - DoScriptText(SAY_WP_5, Godfrey); - break; - case 6: - DoScriptText(SAY_WP_6, Godfrey); - break; - case 7: - DoScriptText(SAY_WP_7, me, Godfrey); - me->HandleEmoteCommand(1); - break; - case 8: - DoScriptText(SAY_WP_8, me, Godfrey); - me->HandleEmoteCommand(16); - break; - case 9: - DoScriptText(SAY_WP_9, me, Godfrey); - me->HandleEmoteCommand(5); - break; - case 10: - DoScriptText(SAY_WP_10, me, Godfrey); - DoCast(Godfrey, SPELL_HOLY_FIRE); - break; - case 11: - Godfrey->HandleEmoteCommand(434); - DoScriptText(SAY_WP_11, Godfrey); - break; - case 12: - DoScriptText(SAY_WP_12, me, Godfrey); - DoCast(Godfrey, SPELL_HOLY_FIRE); - break; - case 13: - DoScriptText(SAY_WP_13, me, Godfrey); - DoCast(Godfrey, SPELL_HOLY_FIRE); - break; - case 14: - Godfrey->HandleEmoteCommand(434); - DoScriptText(SAY_WP_14, Godfrey); - break; - case 15: - DoScriptText(SAY_WP_15, me, Godfrey); - DoCast(Godfrey, SPELL_HOLY_FIRE); - break; - case 16: - DoScriptText(SAY_WP_16, me, Godfrey); - break; - case 17: - DoScriptText(SAY_WP_17, me, Godfrey); - break; - case 18: - DoScriptText(SAY_WP_18, Godfrey); - break; - case 19: - DoScriptText(SAY_WP_19, me, Godfrey); - break; - case 20: - DoScriptText(SAY_WP_20, Godfrey); - break; - case 21: - DoScriptText(SAY_WP_21, Godfrey); - break; - case 22: - DoScriptText(SAY_WP_22, me, Godfrey); - break; - case 23: - DoScriptText(SAY_WP_23, Godfrey); - break; - case 24: - DoScriptText(SAY_WP_24, Godfrey); - break; - case 25: - DoScriptText(SAY_WP_25, me, Godfrey); - break; - case 26: - DoScriptText(SAY_WP_26, me); - me->SetUInt64Value(UNIT_FIELD_TARGET, pPlayer->GetGUID()); - break; - case 27: - DoScriptText(SAY_WP_27, me, Godfrey); - me->SetUInt64Value(UNIT_FIELD_TARGET, Godfrey->GetGUID()); - Completed = true; - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_A_RIGHTEOUS_SERMON, me); - break; - } - } - - void Reset() - { - Completed = false; - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - } -}; - -bool QuestAccept_npc_inquisitor_hallard(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_A_RIGHTEOUS_SERMON) - { - DoScriptText(SAY_WP_0, pCreature, pPlayer); - if (npc_escortAI* pEscortAI = CAST_AI(npc_inquisitor_hallardAI, pCreature->AI())) - { - pEscortAI->Start(true, false, pPlayer->GetGUID(), 0, true); - pCreature->GetMotionMaster()->MovePoint(0, 3801.543, -679.350, 213.75); - } - } - return true; -} - -CreatureAI* GetAI_npc_inquisitor_hallard(Creature* pCreature) -{ - return new npc_inquisitor_hallardAI(pCreature); -} - -void AddSC_dragonblight() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_alexstrasza_wr_gate"; - newscript->pGossipHello = &GossipHello_npc_alexstrasza_wr_gate; - newscript->pGossipSelect = &GossipSelect_npc_alexstrasza_wr_gate; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_inquisitor_hallard"; - newscript->GetAI = &GetAI_npc_inquisitor_hallard; - newscript->pQuestAccept = &QuestAccept_npc_inquisitor_hallard; - newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/northrend/draktharon_keep/boss_dred.cpp b/src/server/scripts/northrend/draktharon_keep/boss_dred.cpp deleted file mode 100644 index ba64a4748dd..00000000000 --- a/src/server/scripts/northrend/draktharon_keep/boss_dred.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: MAYBE need more improve the "Raptor Call". - */ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -enum eSpells -{ - SPELL_BELLOWING_ROAR = 22686, // fears the group, can be resisted/dispelled - SPELL_GRIEVOUS_BITE = 48920, - SPELL_MANGLING_SLASH = 48873, //casted on the current tank, adds debuf - SPELL_FEARSOME_ROAR = 48849, - H_SPELL_FEARSOME_ROAR = 59422, //Not stacking, debuff - SPELL_PIERCING_SLASH = 48878, //debuff -->Armor reduced by 75% - SPELL_RAPTOR_CALL = 59416, //dummy - SPELL_GUT_RIP = 49710, - SPELL_REND = 13738 -}; - -enum eArchivements -{ - ACHIEV_BETTER_OFF_DRED = 2039 -}; - -enum Creatures -{ - NPC_RAPTOR_1 = 26641, - NPC_RAPTOR_2 = 26628 -}; - -struct boss_dredAI : public ScriptedAI -{ - boss_dredAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBellowingRoarTimer; - uint32 uiGrievousBiteTimer; - uint32 uiManglingSlashTimer; - uint32 uiFearsomeRoarTimer; - uint32 uiPiercingSlashTimer; - uint32 uiRaptorCallTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - { - pInstance->SetData(DATA_DRED_EVENT,NOT_STARTED); - pInstance->SetData(DATA_KING_DRED_ACHIEV, 0); - } - - uiBellowingRoarTimer = 33*IN_MILISECONDS; - uiGrievousBiteTimer = 20*IN_MILISECONDS; - uiManglingSlashTimer = 18.5*IN_MILISECONDS; - uiFearsomeRoarTimer = urand(10*IN_MILISECONDS,20*IN_MILISECONDS); - uiPiercingSlashTimer = 17*IN_MILISECONDS; - uiRaptorCallTimer = urand(20*IN_MILISECONDS,25*IN_MILISECONDS); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_DRED_EVENT,IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBellowingRoarTimer < diff) - { - DoCastAOE(SPELL_BELLOWING_ROAR, false); - uiBellowingRoarTimer = 40*IN_MILISECONDS; - } else uiBellowingRoarTimer -=diff; - - if (uiGrievousBiteTimer < diff) - { - DoCastVictim(SPELL_GRIEVOUS_BITE ,false); - uiGrievousBiteTimer = 20*IN_MILISECONDS; - } else uiGrievousBiteTimer -=diff; - - if (uiManglingSlashTimer < diff) - { - DoCastVictim(SPELL_MANGLING_SLASH,false); - uiManglingSlashTimer = 20*IN_MILISECONDS; - } else uiManglingSlashTimer -=diff; - - if (uiFearsomeRoarTimer < diff) - { - DoCastAOE(SPELL_FEARSOME_ROAR,false); - uiFearsomeRoarTimer = urand(16*IN_MILISECONDS,18*IN_MILISECONDS); - } else uiFearsomeRoarTimer -=diff; - - if (uiPiercingSlashTimer < diff) - { - DoCastVictim(SPELL_PIERCING_SLASH,false); - uiPiercingSlashTimer = 20*IN_MILISECONDS; - } else uiPiercingSlashTimer -=diff; - - if (uiRaptorCallTimer < diff) - { - DoCastVictim(SPELL_RAPTOR_CALL,false); - - float x,y,z; - - me->GetClosePoint(x,y,z,me->GetObjectSize()/3,10.0f); - me->SummonCreature(RAND(NPC_RAPTOR_1,NPC_RAPTOR_2),x,y,z,0,TEMPSUMMON_DEAD_DESPAWN,1*IN_MILISECONDS); - - uiRaptorCallTimer = urand(20*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiRaptorCallTimer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_DRED_EVENT,DONE); - - if (IsHeroic() && pInstance->GetData(DATA_KING_DRED_ACHIEV) == 6) - pInstance->DoCompleteAchievement(ACHIEV_BETTER_OFF_DRED); - } - } -}; - -CreatureAI* GetAI_boss_dred(Creature* pCreature) -{ - return new boss_dredAI (pCreature); -} - -struct npc_drakkari_gutripperAI : public ScriptedAI -{ - npc_drakkari_gutripperAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 GutRipTimer; - - void Reset() - { - GutRipTimer = urand(10000,15000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (GutRipTimer < diff) - { - DoCastVictim(SPELL_GUT_RIP,false); - GutRipTimer = urand(10000,15000); - }else GutRipTimer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (IsHeroic() && pInstance->GetData(DATA_DRED_EVENT) == IN_PROGRESS && pInstance->GetData(DATA_KING_DRED_ACHIEV) < 6) - { - pInstance->SetData(DATA_KING_DRED_ACHIEV, pInstance->GetData(DATA_KING_DRED_ACHIEV) + 1); - } - } - } -}; - -CreatureAI* GetAI_npc_drakkari_gutripper(Creature* pCreature) -{ - return new npc_drakkari_gutripperAI (pCreature); -} - -struct npc_drakkari_scytheclawAI : public ScriptedAI -{ - npc_drakkari_scytheclawAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiRendTimer; - - void Reset() - { - uiRendTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiRendTimer < diff) - { - DoCastVictim(SPELL_REND,false); - uiRendTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - }else uiRendTimer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (IsHeroic() && pInstance->GetData(DATA_DRED_EVENT) == IN_PROGRESS && pInstance->GetData(DATA_KING_DRED_ACHIEV) < 6) - { - pInstance->SetData(DATA_KING_DRED_ACHIEV, pInstance->GetData(DATA_KING_DRED_ACHIEV) + 1); - } - } - } -}; - -CreatureAI* GetAI_npc_drakkari_scytheclaw(Creature* pCreature) -{ - return new npc_drakkari_scytheclawAI (pCreature); -} - -void AddSC_boss_dred() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_drakkari_gutripper"; - newscript->GetAI = &GetAI_npc_drakkari_gutripper; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_drakkari_scytheclaw"; - newscript->GetAI = &GetAI_npc_drakkari_scytheclaw; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_dred"; - newscript->GetAI = &GetAI_boss_dred; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/draktharon_keep/boss_novos.cpp b/src/server/scripts/northrend/draktharon_keep/boss_novos.cpp deleted file mode 100644 index 5e8792c352d..00000000000 --- a/src/server/scripts/northrend/draktharon_keep/boss_novos.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* -* Copyright (C) 2008 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -enum Spells -{ - SPELL_ARCANE_BLAST = 49198, - H_SPELL_ARCANE_BLAST = 59909, - SPELL_ARCANE_FIELD = 47346, - SPELL_BLIZZARD = 49034, - H_SPELL_BLIZZARD = 59854, - SPELL_FROSTBOLT = 49037, - H_SPELL_FROSTBOLT = 59855, - SPELL_WRATH_OF_MISERY = 50089, - H_SPELL_WRATH_OF_MISERY = 59856, - SPELL_SUMMON_MINIONS = 59910 //Summons an army of Fetid Troll Corpses to assist the caster. -}; -//not in db -enum Yells -{ - SAY_AGGRO = -1600000, - SAY_KILL = -1600001, - SAY_DEATH = -1600002, - SAY_NECRO_ADD = -1600003, - SAY_REUBBLE_1 = -1600004, - SAY_REUBBLE_2 = -1600005 -}; -enum Creatures -{ - CREATURE_RISEN_SHADOWCASTER = 27600, - CREATURE_FETID_TROLL_CORPSE = 27598, - CREATURE_HULKING_CORPSE = 27597, - CREATURE_CRYSTAL_HANDLER = 26627 -}; -enum CombatPhase -{ - IDLE, - PHASE_1, - PHASE_2 -}; -enum Achievements -{ - ACHIEV_OH_NOVOS = 2057 -}; - -static Position AddSpawnPoint = { -379.20, -816.76, 59.70 }; -static Position CrystalHandlerSpawnPoint = { -326.626343, -709.956604, 27.813314 }; -static Position AddDestinyPoint = { -379.314545, -772.577637, 28.58837 }; - -struct boss_novosAI : public Scripted_NoMovementAI -{ - boss_novosAI(Creature *c) : Scripted_NoMovementAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiTimer; - uint32 uiCrystalHandlerTimer; - - bool bAchiev; - - SummonList lSummons; - - std::list luiCrystals; - - CombatPhase Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - Phase = IDLE; - luiCrystals.clear(); - bAchiev = true; - me->CastStop(); - lSummons.DespawnAll(); - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (pInstance) - { - pInstance->SetData(DATA_NOVOS_EVENT, NOT_STARTED); - luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_1)); - luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_2)); - luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_3)); - luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_4)); - for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) - { - if (GameObject* pTemp = pInstance->instance->GetGameObject(*itr)) - pTemp->SetGoState(GO_STATE_READY); - } - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - Phase = PHASE_1; - uiCrystalHandlerTimer = 30*IN_MILISECONDS; - uiTimer = 1*IN_MILISECONDS; - DoCast(SPELL_ARCANE_FIELD); - if (pInstance) - { - for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) - { - if (GameObject *pTemp = pInstance->instance->GetGameObject(*itr)) - pTemp->SetGoState(GO_STATE_ACTIVE); - } - pInstance->SetData(DATA_NOVOS_EVENT, IN_PROGRESS); - } - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void UpdateAI(const uint32 diff) - { - switch (Phase) - { - case PHASE_1: - if (uiTimer <= diff) - { - Creature *pSummon = me->SummonCreature(RAND(CREATURE_FETID_TROLL_CORPSE,CREATURE_HULKING_CORPSE,CREATURE_RISEN_SHADOWCASTER), AddSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); - pSummon->GetMotionMaster()->MovePoint(0, AddDestinyPoint); - //If spell is casted stops casting arcane field so no spell casting - //DoCast(me, SPELL_SUMMON_MINIONS); - uiTimer = 3*IN_MILISECONDS; - } else uiTimer -= diff; - if (uiCrystalHandlerTimer <= diff) - { - DoScriptText(SAY_NECRO_ADD, me); - Creature *pCrystalHandler = me->SummonCreature(CREATURE_CRYSTAL_HANDLER, CrystalHandlerSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); - pCrystalHandler->GetMotionMaster()->MovePoint(0, AddDestinyPoint); - uiCrystalHandlerTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiCrystalHandlerTimer -= diff; - break; - case PHASE_2: - if (uiTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, DUNGEON_MODE(RAND(SPELL_ARCANE_BLAST,SPELL_BLIZZARD,SPELL_FROSTBOLT,SPELL_WRATH_OF_MISERY), - RAND(H_SPELL_ARCANE_BLAST,H_SPELL_BLIZZARD,H_SPELL_FROSTBOLT,H_SPELL_WRATH_OF_MISERY))); - uiTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); - } else uiTimer -= diff; - break; - } - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - { - pInstance->SetData(DATA_NOVOS_EVENT, DONE); - - if (IsHeroic() && bAchiev) - pInstance->DoCompleteAchievement(ACHIEV_OH_NOVOS); - } - lSummons.DespawnAll(); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(SAY_KILL, me); - } - - void JustSummoned(Creature *summon) - { - lSummons.Summon(summon); - } - - void RemoveCrystal() - { - if (!luiCrystals.empty()) - { - if (pInstance) - if (GameObject *pTemp = pInstance->instance->GetGameObject(luiCrystals.back())) - pTemp->SetGoState(GO_STATE_READY); - luiCrystals.pop_back(); - } - if (luiCrystals.empty()) - { - me->CastStop(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Phase = PHASE_2; - uiTimer = 1*IN_MILISECONDS; - } - } - - Unit* GetRandomTarget() - { - return SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - } -}; - -enum CrystalHandlerSpells -{ - SPELL_FLASH_OF_DARKNESS = 49668, - H_SPELL_FLASH_OF_DARKNESS = 59004 -}; - -struct mob_crystal_handlerAI : public ScriptedAI -{ - mob_crystal_handlerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiFlashOfDarknessTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiFlashOfDarknessTimer = 5*IN_MILISECONDS; - } - - void JustDied(Unit* /*killer*/) - { - if (Creature* pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) - CAST_AI(boss_novosAI,pNovos->AI())->RemoveCrystal(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiFlashOfDarknessTimer <= diff) - { - DoCast(me->getVictim(), DUNGEON_MODE(SPELL_FLASH_OF_DARKNESS,H_SPELL_FLASH_OF_DARKNESS)); - uiFlashOfDarknessTimer = 5*IN_MILISECONDS; - } else uiFlashOfDarknessTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE || id != 0) - return; - if (Creature *pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) - if (Unit *pTarget = CAST_AI(boss_novosAI, pNovos->AI())->GetRandomTarget()) - AttackStart(pTarget); - } -}; - -struct mob_novos_minionAI : public ScriptedAI -{ - mob_novos_minionAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE || id !=0) - return; - if (Creature* pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) - { - CAST_AI(boss_novosAI, pNovos->AI())->bAchiev = false; - if (Unit *pTarget = CAST_AI(boss_novosAI, pNovos->AI())->GetRandomTarget()) - AttackStart(pTarget); - } - } -}; - -CreatureAI* GetAI_boss_novos(Creature* pCreature) -{ - return new boss_novosAI (pCreature); -} - -CreatureAI* GetAI_mob_crystal_handler(Creature* pCreature) -{ - return new mob_crystal_handlerAI (pCreature); -} - -CreatureAI* GetAI_mob_novos_minion(Creature* pCreature) -{ - return new mob_novos_minionAI (pCreature); -} - -void AddSC_boss_novos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_novos"; - newscript->GetAI = &GetAI_boss_novos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crystal_handler"; - newscript->GetAI = &GetAI_mob_crystal_handler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_novos_minion"; - newscript->GetAI = &GetAI_mob_novos_minion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/draktharon_keep/boss_tharon_ja.cpp b/src/server/scripts/northrend/draktharon_keep/boss_tharon_ja.cpp deleted file mode 100644 index 1e60dfc6135..00000000000 --- a/src/server/scripts/northrend/draktharon_keep/boss_tharon_ja.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -enum Spells -{ - //skeletal spells (phase 1) - SPELL_CURSE_OF_LIFE = 49527, - H_SPELL_CURSE_OF_LIFE = 59972, - SPELL_RAIN_OF_FIRE = 49518, - H_SPELL_RAIN_OF_FIRE = 59971, - SPELL_SHADOW_VOLLEY = 49528, - H_SPELL_SHADOW_VOLLEY = 59973, - SPELL_DECAY_FLESH = 49356, //casted at end of phase 1, starts phase 2 - //flesh spells (phase 2) - SPELL_GIFT_OF_THARON_JA = 52509, - SPELL_EYE_BEAM = 49544, - H_SPELL_EYE_BEAM = 59965, - SPELL_LIGHTNING_BREATH = 49537, - H_SPELL_LIGHTNING_BREATH = 59963, - SPELL_POISON_CLOUD = 49548, - H_SPELL_POISON_CLOUD = 59969, - SPELL_RETURN_FLESH = 53463, //Channeled spell ending phase two and returning to phase 1. This ability will stun the party for 6 seconds. - SPELL_ACHIEVEMENT_CHECK = 61863, -}; - -enum Yells -{ - SAY_AGGRO = -1600011, - SAY_KILL_1 = -1600012, - SAY_KILL_2 = -1600013, - SAY_FLESH_1 = -1600014, - SAY_FLESH_2 = -1600015, - SAY_SKELETON_1 = -1600016, - SAY_SKELETON_2 = -1600017, - SAY_DEATH = -1600018 -}; -enum Models -{ - MODEL_FLESH = 27073, - MODEL_SKELETON = 27511 -}; -enum CombatPhase -{ - SKELETAL, - GOING_FLESH, - FLESH, - GOING_SKELETAL -}; - -struct boss_tharon_jaAI : public ScriptedAI -{ - boss_tharon_jaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiPhaseTimer; - uint32 uiCurseOfLifeTimer; - uint32 uiRainOfFireTimer; - uint32 uiShadowVolleyTimer; - uint32 uiEyeBeamTimer; - uint32 uiLightningBreathTimer; - uint32 uiPoisonCloudTimer; - - CombatPhase Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - uiPhaseTimer = 20*IN_MILISECONDS; - uiCurseOfLifeTimer = 1*IN_MILISECONDS; - uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); - uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); - Phase = SKELETAL; - me->SetDisplayId(me->GetNativeDisplayId()); - if (pInstance) - pInstance->SetData(DATA_THARON_JA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_THARON_JA_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - switch (Phase) - { - case SKELETAL: - if (uiCurseOfLifeTimer < diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CURSE_OF_LIFE); - uiCurseOfLifeTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiCurseOfLifeTimer -= diff; - - if (uiShadowVolleyTimer < diff) - { - DoCastVictim(SPELL_SHADOW_VOLLEY); - uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); - } else uiShadowVolleyTimer -= diff; - - if (uiRainOfFireTimer < diff) - { - DoCastAOE(SPELL_RAIN_OF_FIRE); - uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); - } else uiRainOfFireTimer -= diff; - - if (uiPhaseTimer < diff) - { - DoCast(SPELL_DECAY_FLESH); - Phase = GOING_FLESH; - uiPhaseTimer = 6*IN_MILISECONDS; - } else uiPhaseTimer -= diff; - - DoMeleeAttackIfReady(); - break; - case GOING_FLESH: - if (uiPhaseTimer < diff) - { - DoScriptText(RAND(SAY_FLESH_1,SAY_FLESH_2),me); - me->SetDisplayId(MODEL_FLESH); - std::list& threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - Unit *pTemp = Unit::GetUnit((*me),(*itr)->getUnitGuid()); - if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) - { - me->AddAura(SPELL_GIFT_OF_THARON_JA,pTemp); - pTemp->SetDisplayId(MODEL_SKELETON); - } - } - uiPhaseTimer = 20*IN_MILISECONDS; - uiLightningBreathTimer = urand(3*IN_MILISECONDS,4*IN_MILISECONDS); - uiEyeBeamTimer = urand(4*IN_MILISECONDS,8*IN_MILISECONDS); - uiPoisonCloudTimer = urand(6*IN_MILISECONDS,7*IN_MILISECONDS); - Phase = FLESH; - } else uiPhaseTimer -= diff; - break; - case FLESH: - if (uiLightningBreathTimer < diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_LIGHTNING_BREATH); - uiLightningBreathTimer = urand(6*IN_MILISECONDS,7*IN_MILISECONDS); - } else uiLightningBreathTimer -= diff; - - if (uiEyeBeamTimer < diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_EYE_BEAM); - uiEyeBeamTimer = urand(4*IN_MILISECONDS,6*IN_MILISECONDS); - } else uiEyeBeamTimer -= diff; - - if (uiPoisonCloudTimer < diff) - { - DoCastAOE(SPELL_POISON_CLOUD); - uiPoisonCloudTimer = urand(10*IN_MILISECONDS,12*IN_MILISECONDS); - } else uiPoisonCloudTimer -= diff; - - if (uiPhaseTimer < diff) - { - DoCast(SPELL_RETURN_FLESH); - Phase = GOING_SKELETAL; - uiPhaseTimer = 6*IN_MILISECONDS; - } else uiPhaseTimer -= diff; - DoMeleeAttackIfReady(); - break; - case GOING_SKELETAL: - if (uiPhaseTimer < diff) - { - DoScriptText(RAND(SAY_SKELETON_1,SAY_SKELETON_2), me); - me->DeMorph(); - Phase = SKELETAL; - uiPhaseTimer = 20*IN_MILISECONDS; - uiCurseOfLifeTimer = 1*IN_MILISECONDS; - uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); - uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); - std::list& threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - Unit *pTemp = Unit::GetUnit((*me),(*itr)->getUnitGuid()); - if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) - { - if (pTemp->HasAura(SPELL_GIFT_OF_THARON_JA)) - pTemp->RemoveAura(SPELL_GIFT_OF_THARON_JA); - pTemp->DeMorph(); - } - } - } else uiPhaseTimer -= diff; - break; - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2),me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH,me); - - if (pInstance) - { - // clean morph on players - Map::PlayerList const &PlayerList = pInstance->instance->GetPlayers(); - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player *pPlayer = i->getSource()) - pPlayer->DeMorph(); - // cast is not rewarding the achievement. - // DoCast(SPELL_ACHIEVEMENT_CHECK); - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, SPELL_ACHIEVEMENT_CHECK); - - pInstance->SetData(DATA_THARON_JA_EVENT, DONE); - } - } -}; - -CreatureAI* GetAI_boss_tharon_ja(Creature* pCreature) -{ - return new boss_tharon_jaAI (pCreature); -} - -void AddSC_boss_tharon_ja() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_tharon_ja"; - newscript->GetAI = &GetAI_boss_tharon_ja; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/draktharon_keep/boss_trollgore.cpp b/src/server/scripts/northrend/draktharon_keep/boss_trollgore.cpp deleted file mode 100644 index 03eac73385d..00000000000 --- a/src/server/scripts/northrend/draktharon_keep/boss_trollgore.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: TODO: spawn troll waves - */ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -enum Spells -{ - SPELL_INFECTED_WOUND = 49637, - SPELL_CRUSH = 49639, - SPELL_CORPSE_EXPLODE = 49555, - SPELL_CONSUME = 49380, - SPELL_CONSUME_AURA = 49381, - //Heroic spells - H_SPELL_CORPSE_EXPLODE = 59807, - H_SPELL_CONSUME = 59803, - H_SPELL_CONSUME_AURA = 59805, -}; -enum Yells -{ - SAY_AGGRO = -1600006, - SAY_KILL = -1600007, - SAY_CONSUME = -1600008, - SAY_EXPLODE = -1600009, - SAY_DEATH = -1600010 -}; -enum Achievements -{ - ACHIEV_CONSUMPTION_JUNCTION = 2151 -}; -enum Creatures -{ - NPC_DRAKKARI_INVADER_1 = 27753, - NPC_DRAKKARI_INVADER_2 = 27709 -}; - -Position AddSpawnPoint = { -260.493011, -622.968018, 26.605301, 3.036870 }; - -struct boss_trollgoreAI : public ScriptedAI -{ - boss_trollgoreAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiConsumeTimer; - uint32 uiAuraCountTimer; - uint32 uiCrushTimer; - uint32 uiInfectedWoundTimer; - uint32 uiExplodeCorpseTimer; - uint32 uiSpawnTimer; - - bool bAchiev; - - SummonList lSummons; - - ScriptedInstance* pInstance; - - void Reset() - { - uiConsumeTimer = 15*IN_MILISECONDS; - uiAuraCountTimer = 15.5*IN_MILISECONDS; - uiCrushTimer = urand(1*IN_MILISECONDS,5*IN_MILISECONDS); - uiInfectedWoundTimer = urand(60*IN_MILISECONDS,10*IN_MILISECONDS); - uiExplodeCorpseTimer = 3*IN_MILISECONDS; - uiSpawnTimer = urand(30*IN_MILISECONDS,40*IN_MILISECONDS); - - bAchiev = IsHeroic(); - - lSummons.DespawnAll(); - - me->RemoveAura(DUNGEON_MODE(SPELL_CONSUME_AURA,H_SPELL_CONSUME_AURA)); - - if (pInstance) - pInstance->SetData(DATA_TROLLGORE_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_TROLLGORE_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiSpawnTimer <= diff) - { - uint32 spawnNumber = urand(2,DUNGEON_MODE(3,5)); - for (uint8 i = 0; i < spawnNumber; ++i) - DoSummon(RAND(NPC_DRAKKARI_INVADER_1,NPC_DRAKKARI_INVADER_2), AddSpawnPoint, 0, TEMPSUMMON_DEAD_DESPAWN); - uiSpawnTimer = urand(30*IN_MILISECONDS,40*IN_MILISECONDS); - } else uiSpawnTimer -= diff; - - if (uiConsumeTimer <= diff) - { - DoScriptText(SAY_CONSUME, me); - DoCast(SPELL_CONSUME); - uiConsumeTimer = 15*IN_MILISECONDS; - } else uiConsumeTimer -= diff; - - if (bAchiev) - { - Aura *pConsumeAura = me->GetAura(DUNGEON_MODE(SPELL_CONSUME_AURA,H_SPELL_CONSUME_AURA)); - if (pConsumeAura && pConsumeAura->GetStackAmount() > 9) - bAchiev = false; - } - - if (uiCrushTimer <= diff) - { - DoCastVictim(SPELL_CRUSH); - uiCrushTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiCrushTimer -= diff; - - if (uiInfectedWoundTimer <= diff) - { - DoCastVictim(SPELL_INFECTED_WOUND); - uiInfectedWoundTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); - } else uiInfectedWoundTimer -= diff; - - if (uiExplodeCorpseTimer <= diff) - { - DoCast(SPELL_CORPSE_EXPLODE); - DoScriptText(SAY_EXPLODE, me); - uiExplodeCorpseTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); - } else uiExplodeCorpseTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - lSummons.DespawnAll(); - - if (pInstance) - { - if (bAchiev) - pInstance->DoCompleteAchievement(ACHIEV_CONSUMPTION_JUNCTION); - pInstance->SetData(DATA_TROLLGORE_EVENT, DONE); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(SAY_KILL, me); - } - - void JustSummoned(Creature* summon) - { - lSummons.push_back(summon->GetGUID()); - if (summon->AI()) - summon->AI()->AttackStart(me); - } -}; - -CreatureAI* GetAI_boss_trollgore(Creature* pCreature) -{ - return new boss_trollgoreAI (pCreature); -} - -void AddSC_boss_trollgore() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_trollgore"; - newscript->GetAI = &GetAI_boss_trollgore; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/draktharon_keep/drak_tharon_keep.h b/src/server/scripts/northrend/draktharon_keep/drak_tharon_keep.h deleted file mode 100644 index 597971d17dd..00000000000 --- a/src/server/scripts/northrend/draktharon_keep/drak_tharon_keep.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright (C) 2008 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef DEF_DRAK_THARON_H -#define DEF_DRAK_THARON_H -enum Data -{ - DATA_TROLLGORE_EVENT, - DATA_NOVOS_EVENT, - DATA_DRED_EVENT, - DATA_THARON_JA_EVENT, - DATA_KING_DRED_ACHIEV -}; -enum Data64 -{ - DATA_TROLLGORE, - DATA_NOVOS, - DATA_DRED, - DATA_THARON_JA, - DATA_NOVOS_CRYSTAL_1, - DATA_NOVOS_CRYSTAL_2, - DATA_NOVOS_CRYSTAL_3, - DATA_NOVOS_CRYSTAL_4 -}; -#endif diff --git a/src/server/scripts/northrend/draktharon_keep/instance_drak_tharon_keep.cpp b/src/server/scripts/northrend/draktharon_keep/instance_drak_tharon_keep.cpp deleted file mode 100644 index 9f4d2ee52a2..00000000000 --- a/src/server/scripts/northrend/draktharon_keep/instance_drak_tharon_keep.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -#define MAX_ENCOUNTER 4 - -/* Drak'Tharon Keep encounters: -0 - Trollgore -1 - Novos -2 - King Dred -3 - Tharon Ja -*/ - -enum Creatures -{ - NPC_TROLLGORE = 26630, - NPC_NOVOS = 26631, - NPC_KING_DRED = 27483, - NPC_THARON_JA = 26632 -}; -enum GameObjects -{ - GO_NOVOS_CRYSTAL_1 = 189299, - GO_NOVOS_CRYSTAL_2 = 189300, - GO_NOVOS_CRYSTAL_3 = 189301, - GO_NOVOS_CRYSTAL_4 = 189302 -}; - -struct instance_drak_tharon : public ScriptedInstance -{ - instance_drak_tharon(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint8 uiDredAchievCounter; - - uint64 uiTrollgore; - uint64 uiNovos; - uint64 uiDred; - uint64 uiTharonJa; - - uint64 uiNovosCrystal1; - uint64 uiNovosCrystal2; - uint64 uiNovosCrystal3; - uint64 uiNovosCrystal4; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() - { - uiTrollgore = 0; - uiNovos = 0; - uiDred = 0; - uiTharonJa = 0; - uiNovosCrystal1 = 0; - uiNovosCrystal2 = 0; - uiNovosCrystal3 = 0; - uiNovosCrystal4 = 0; - uiDredAchievCounter = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_NOVOS_CRYSTAL_1: - uiNovosCrystal1 = pGo->GetGUID(); - break; - case GO_NOVOS_CRYSTAL_2: - uiNovosCrystal2 = pGo->GetGUID(); - break; - case GO_NOVOS_CRYSTAL_3: - uiNovosCrystal3 = pGo->GetGUID(); - break; - case GO_NOVOS_CRYSTAL_4: - uiNovosCrystal4 = pGo->GetGUID(); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_TROLLGORE: - uiTrollgore = pCreature->GetGUID(); - break; - case NPC_NOVOS: - uiNovos = pCreature->GetGUID(); - break; - case NPC_KING_DRED: - uiDred = pCreature->GetGUID(); - break; - case NPC_THARON_JA: - uiTharonJa = pCreature->GetGUID(); - break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_TROLLGORE: return uiTrollgore; - case DATA_NOVOS: return uiNovos; - case DATA_DRED: return uiDred; - case DATA_THARON_JA: return uiTharonJa; - case DATA_NOVOS_CRYSTAL_1: return uiNovosCrystal1; - case DATA_NOVOS_CRYSTAL_2: return uiNovosCrystal2; - case DATA_NOVOS_CRYSTAL_3: return uiNovosCrystal3; - case DATA_NOVOS_CRYSTAL_4: return uiNovosCrystal4; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_TROLLGORE_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_NOVOS_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_DRED_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_THARON_JA_EVENT: - m_auiEncounter[3] = data; - break; - - case DATA_KING_DRED_ACHIEV: - uiDredAchievCounter = data; - break; - } - - if (data == DONE) - { - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch (type) - { - case DATA_TROLLGORE_EVENT: return m_auiEncounter[0]; - case DATA_NOVOS_EVENT: return m_auiEncounter[1]; - case DATA_DRED_EVENT: return m_auiEncounter[2]; - case DATA_THARON_JA_EVENT: return m_auiEncounter[3]; - case DATA_KING_DRED_ACHIEV: return uiDredAchievCounter; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::string str_data; - - std::ostringstream saveStream; - saveStream << "D K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0,data1,data2,data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'D' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_drak_tharon(Map* pMap) -{ - return new instance_drak_tharon(pMap); -} - -void AddSC_instance_drak_tharon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_drak_tharon"; - newscript->GetInstanceData = &GetInstanceData_instance_drak_tharon; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp b/src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp deleted file mode 100644 index 59db2842735..00000000000 --- a/src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -/* - * TODO: - * - Fix Soul Storm spell and remove work around. - */ - -enum Yells -{ - SAY_AGGRO = -1632001, - SAY_SLAY_1 = -1632002, - SAY_SLAY_2 = -1632003, - SAY_DEATH = -1632004, - SAY_SOUL_STORM = -1632005, - SAY_CORRUPT_SOUL = -1632006, -}; - -enum Spells -{ - SPELL_MAGIC_S_BANE = 68793, - SPELL_CORRUPT_SOUL = 68839, - SPELL_CONSUME_SOUL = 68858, - SPELL_TELEPORT = 68988, - SPELL_FEAR = 68950, - SPELL_SOULSTORM = 68872, - SPELL_SOULSTORM_AURA = 68921, - SPELL_SHADOW_BOLT = 70043, -}; - -enum Events -{ - EVENT_NONE, - EVENT_SHADOW_BOLT, - EVENT_MAGIC_BANE, - EVENT_CORRUPT_SOUL, - EVENT_SOUL_STORM, - EVENT_SOUL_STORM_AURA, - EVENT_FEAR, -}; - -enum CombatPhases -{ - PHASE_1, - PHASE_2 -}; - -struct boss_bronjahmAI : public ScriptedAI -{ - boss_bronjahmAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - CombatPhases phase; - - void Reset() - { - phase = PHASE_1; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - - events.Reset(); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); - events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); - events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - // Cast aura spell on all players farther than 10y - void ApplySoulStorm() - { - std::list targetList; - - SelectTargetList(targetList, 100, SELECT_TARGET_TOPAGGRO, -10.0f); - if (targetList.empty()) - return; - - for (std::list::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr) - { - Unit* pUnit = (*itr); - if (pUnit && pUnit->isAlive()) - me->CastSpell(pUnit, SPELL_SOULSTORM_AURA, true); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (phase == PHASE_1 && HealthBelowPct(30)) - { - phase = PHASE_2; - DoCast(me,SPELL_TELEPORT); - me->GetMotionMaster()->Clear(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - events.CancelEvent(EVENT_CORRUPT_SOUL); - events.ScheduleEvent(EVENT_SOUL_STORM, 1000); - events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); - return; - } - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CORRUPT_SOUL: - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - DoScriptText(SAY_CORRUPT_SOUL, me); - DoCast(pTarget,SPELL_CORRUPT_SOUL); - } - events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); - break; - case EVENT_SOUL_STORM: - DoScriptText(SAY_SOUL_STORM, me); - // DoCast(me, SPELL_SOULSTORM); bug: put the aura without the limit of 10 yards. - events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); - break; - case EVENT_SOUL_STORM_AURA: - ApplySoulStorm(); - events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); - break; - case EVENT_FEAR: - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget,SPELL_FEAR); - events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); - break; - case EVENT_SHADOW_BOLT: - DoCastVictim(SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); - break; - case EVENT_MAGIC_BANE: - DoCastVictim(SPELL_MAGIC_S_BANE); - events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_bronjahm(Creature* pCreature) -{ - return new boss_bronjahmAI(pCreature); -} - -struct mob_corrupted_soul_fragmentAI : public ScriptedAI -{ - mob_corrupted_soul_fragmentAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCheckTimer; - - void Reset() - { - uiCheckTimer = 0; // first check is immediate - } - - void UpdateAI(const uint32 diff) - { - if (uiCheckTimer <= diff) - { - if (pInstance) - { - Creature* pBronjham = Unit::GetCreature(*me, pInstance->GetData64(DATA_BRONJAHM)); - if (pBronjham && pBronjham->isAlive()) - { - if (me->IsWithinMeleeRange(pBronjham)) - { - pBronjham->CastSpell(pBronjham, SPELL_CONSUME_SOUL, true); - me->ForcedDespawn(); - } - else - { - Position pos; - pBronjham->GetPosition(&pos); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, pos); - } - } - else - me->ForcedDespawn(); - } - uiCheckTimer = 500; - } - else - uiCheckTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_corrupted_soul_fragment(Creature* pCreature) -{ - return new mob_corrupted_soul_fragmentAI(pCreature); -} - -void AddSC_boss_bronjahm() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_bronjahm"; - newscript->GetAI = &GetAI_boss_bronjahm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_corrupted_soul_fragment"; - newscript->GetAI = &GetAI_mob_corrupted_soul_fragment; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp b/src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp deleted file mode 100644 index 6811ba953e2..00000000000 --- a/src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -/* - * TODO: - * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing). - * - Fix outro npc movement - */ - -#define PI 3.1415f - -enum Yells -{ - SAY_FACE_ANGER_AGGRO = -1632010, - SAY_FACE_DESIRE_AGGRO = -1632011, - SAY_FACE_ANGER_SLAY_1 = -1632012, - SAY_FACE_SORROW_SLAY_1 = -1632013, - SAY_FACE_DESIRE_SLAY_1 = -1632014, - SAY_FACE_ANGER_SLAY_2 = -1632015, - SAY_FACE_SORROW_SLAY_2 = -1632016, - SAY_FACE_DESIRE_SLAY_2 = -1632017, - SAY_FACE_SORROW_DEATH = -1632019, - SAY_FACE_DESIRE_DEATH = -1632020, - EMOTE_MIRRORED_SOUL = -1632021, - EMOTE_UNLEASH_SOUL = -1632022, - SAY_FACE_ANGER_UNLEASH_SOUL = -1632023, - SAY_FACE_SORROW_UNLEASH_SOUL = -1632024, - SAY_FACE_DESIRE_UNLEASH_SOUL = -1632025, - EMOTE_WAILING_SOUL = -1632026, - SAY_FACE_ANGER_WAILING_SOUL = -1632027, - SAY_FACE_DESIRE_WAILING_SOUL = -1632028, - - SAY_JAINA_OUTRO = -1632029, - SAY_SYLVANAS_OUTRO = -1632030, -}; - -enum Spells -{ - SPELL_PHANTOM_BLAST = 68982, - H_SPELL_PHANTOM_BLAST = 70322, - SPELL_MIRRORED_SOUL = 69051, - SPELL_WELL_OF_SOULS = 68820, - SPELL_WELL_OF_SOULS_VIS = 68854, - SPELL_UNLEASHED_SOULS = 68939, - SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase - SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual - SPELL_WAILING_SOULS = 68873, // the actual spell - H_SPELL_WAILING_SOULS = 70324, -// 68871,68873,68875,68876,68899,68912,70324, -// 68899 trigger 68871 -}; - -enum Events -{ - EVENT_NONE, - EVENT_PHANTOM_BLAST, - EVENT_MIRRORED_SOUL, - EVENT_WELL_OF_SOULS, - EVENT_UNLEASHED_SOULS, - EVENT_WAILING_SOULS, - EVENT_WAILING_SOULS_TICK, - EVENT_FACE_ANGER, -}; - -enum eEnum -{ - ACHIEV_THREE_FACED = 4523, - DISPLAY_ANGER = 30148, - DISPLAY_SORROW = 30149, - DISPLAY_DESIRE = 30150, -}; - -struct -{ - uint32 entry[2]; - Position movePosition; -} outroPositions[] = -{ - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5590.47, 2427.79, 705.935, 0.802851 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5593.59, 2428.34, 705.935, 0.977384 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2429.31, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2421.12, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.43, 2426.53, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.55, 2418.36, 705.935, 1.15192 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5598, 2429.14, 705.935, 1.0472 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5594.04, 2424.87, 705.935, 1.15192 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5597.89, 2421.54, 705.935, 0.610865 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5598.57, 2434.62, 705.935, 1.13446 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5585.46, 2417.99, 705.935, 1.06465 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5605.81, 2428.42, 705.935, 0.820305 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5591.61, 2412.66, 705.935, 0.925025 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5593.9, 2410.64, 705.935, 0.872665 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5586.76, 2416.73, 705.935, 0.942478 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5592.23, 2419.14, 705.935, 0.855211 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5594.61, 2416.87, 705.935, 0.907571 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5589.77, 2421.03, 705.935, 0.855211 } }, - - { NPC_KORELN, NPC_LORALEN, { 5602.58, 2435.95, 705.935, 0.959931 } }, - { NPC_ELANDRA, NPC_KALIRA, { 5606.13, 2433.16, 705.935, 0.785398 } }, - { NPC_JAINA_PART2, NPC_SYLVANAS_PART2, { 5606.12, 2436.6, 705.935, 0.890118 } }, - - { 0, 0, { 0, 0, 0, 0 } } -}; - -struct boss_devourer_of_soulsAI : public ScriptedAI -{ - boss_devourer_of_soulsAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - bool bThreeFaceAchievement; - - ScriptedInstance* pInstance; - EventMap events; - - // wailing soul event - float beamAngle; - float beamAngleDiff; - int8 wailingSoulTick; - - uint64 uiMirroredSoulTarget; - - void Reset() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->SetDisplayId(DISPLAY_ANGER); - me->SetReactState(REACT_AGGRESSIVE); - - events.Reset(); - - bThreeFaceAchievement = true; - uiMirroredSoulTarget = 0; - - if (pInstance) - pInstance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS); - - DoScriptText(RAND(SAY_FACE_ANGER_AGGRO,SAY_FACE_DESIRE_AGGRO), me); - - events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); - events.ScheduleEvent(EVENT_MIRRORED_SOUL, 8000); - events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000); - events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000); - events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - if (uiMirroredSoulTarget && me->HasAura(SPELL_MIRRORED_SOUL)) - { - if (Player *pPlayer = Unit::GetPlayer(uiMirroredSoulTarget)) - { - if (Aura *pAura = pPlayer->GetAura(SPELL_MIRRORED_SOUL)) - { - int32 mirrorDamage = (uiDamage * 45)/100; - me->CastCustomSpell(pPlayer, 69034, &mirrorDamage, 0, 0, true); -// me->DealDamage(pPlayer, (uiDamage * 45)/100, 0, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); - } - else - uiMirroredSoulTarget = 0; - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_FACE_ANGER_SLAY_1,SAY_FACE_SORROW_SLAY_1,SAY_FACE_DESIRE_SLAY_1, - SAY_FACE_ANGER_SLAY_2,SAY_FACE_SORROW_SLAY_2,SAY_FACE_DESIRE_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - Position spawnPoint = { 5618.139, 2451.873, 705.854 }; - - DoScriptText(RAND(SAY_FACE_SORROW_DEATH,SAY_FACE_DESIRE_DEATH), me); - - if (pInstance) - { - pInstance->SetData(DATA_DEVOURER_EVENT, DONE); - - if (bThreeFaceAchievement && IsHeroic()) - pInstance->DoCompleteAchievement(ACHIEV_THREE_FACED); - - int32 entryIndex; - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - entryIndex = 0; - else - entryIndex = 1; - - for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i) - { - if (Creature *pSummon = me->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint, TEMPSUMMON_DEAD_DESPAWN)) - { - pSummon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition); - - if (pSummon->GetEntry() == NPC_JAINA_PART2) - DoScriptText(SAY_JAINA_OUTRO, pSummon); - else if (pSummon->GetEntry() == NPC_SYLVANAS_PART2) - DoScriptText(SAY_SYLVANAS_OUTRO, pSummon); - } - } - } - } - - void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry *pSpell) - { - if (pSpell->Id == H_SPELL_PHANTOM_BLAST) - bThreeFaceAchievement = false; - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_PHANTOM_BLAST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0)) - DoCast(pTarget, SPELL_PHANTOM_BLAST); - events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); - break; - case EVENT_MIRRORED_SOUL: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) - { - uiMirroredSoulTarget = pTarget->GetGUID(); - DoCast(pTarget, SPELL_MIRRORED_SOUL); - DoScriptText(EMOTE_MIRRORED_SOUL, me); - } - events.ScheduleEvent(EVENT_MIRRORED_SOUL, urand(15000,30000)); - break; - case EVENT_WELL_OF_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_WELL_OF_SOULS); - events.ScheduleEvent(EVENT_WELL_OF_SOULS, 20000); - break; - case EVENT_UNLEASHED_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_UNLEASHED_SOULS); - me->SetDisplayId(DISPLAY_SORROW); - DoScriptText(RAND(SAY_FACE_ANGER_UNLEASH_SOUL,SAY_FACE_SORROW_UNLEASH_SOUL,SAY_FACE_DESIRE_UNLEASH_SOUL), me); - DoScriptText(EMOTE_UNLEASH_SOUL, me); - events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 30000); - events.ScheduleEvent(EVENT_FACE_ANGER, 5000); - break; - case EVENT_FACE_ANGER: - me->SetDisplayId(DISPLAY_ANGER); - break; - - case EVENT_WAILING_SOULS: - me->SetDisplayId(DISPLAY_DESIRE); - DoScriptText(RAND(SAY_FACE_ANGER_WAILING_SOUL,SAY_FACE_DESIRE_WAILING_SOUL), me); - DoScriptText(EMOTE_WAILING_SOUL, me); - DoCast(me, SPELL_WAILING_SOULS_STARTING); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->SetOrientation(me->GetAngle(pTarget)); - DoCast(me, SPELL_WAILING_SOULS_BEAM); - } - - beamAngle = me->GetOrientation(); - - beamAngleDiff = PI/30.0f; // PI/2 in 15 sec = PI/30 per tick - if (RAND(true,false)) - beamAngleDiff = -beamAngleDiff; - - me->InterruptNonMeleeSpells(false); - me->SetReactState(REACT_PASSIVE); - - //Remove any target - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - me->GetMotionMaster()->Clear(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - - wailingSoulTick = 15; - events.DelayEvents(18000); // no other events during wailing souls - events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3000); // first one after 3 secs. - break; - - case EVENT_WAILING_SOULS_TICK: - beamAngle += beamAngleDiff; - me->SetOrientation(beamAngle); - me->StopMoving(); - - DoCast(me, SPELL_WAILING_SOULS); - - if (--wailingSoulTick) - events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 1000); - else - { - me->SetReactState(REACT_AGGRESSIVE); - me->SetDisplayId(DISPLAY_ANGER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->GetMotionMaster()->MoveChase(me->getVictim()); - events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); - } - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_devourer_of_souls(Creature* pCreature) -{ - return new boss_devourer_of_soulsAI(pCreature); -} - -void AddSC_boss_devourer_of_souls() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_devourer_of_souls"; - newscript->GetAI = &GetAI_boss_devourer_of_souls; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp b/src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp deleted file mode 100644 index 5c85da69898..00000000000 --- a/src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp +++ /dev/null @@ -1,899 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -enum Spells -{ - //Spiteful Apparition - SPELL_SPITE = 68895, - H_SPELL_SPITE = 70212, - - //Spectral Warden - SPELL_VEIL_OF_SHADOWS = 69633, - SPELL_WAIL_OF_SOULS = 69148, - H_SPELL_WAIL_OF_SOULS = 70210, - - //Soulguard Watchman - SPELL_SHROUD_OF_RUNES = 69056, - SPELL_UNHOLY_RAGE = 69053, - - //Soulguard Reaper - SPELL_FROST_NOVA = 69060, - H_SPELL_FROST_NOVA = 70209, - SPELL_SHADOW_LANCE = 69058, - - //Soulguard Bonecaster - SPELL_BONE_VOLLEY = 69080, - H_SPELL_BONE_VOLLEY = 70206, - SPELL_RAISE_DEAD = 69562, - SPELL_SHIELD_OF_BONES = 69069, - H_SPELL_SHIELD_OF_BONES = 70207, - - //Soulguard Animator - // Raise dead 69562 - SPELL_SHADOW_BOLT = 69068, - H_SPELL_SHADOW_BOLT = 70208, - SPELL_SOUL_SICKNESS = 69131, - SPELL_SOUL_SIPHON = 69128, - - //Soulguard Adept - //Raise dead 69562 - //Shadow Bolt 69068/70208 - SPELL_DRAIN_LIFE = 69066, - H_SPELL_DRAIN_LIFE = 70213, - SPELL_SHADOW_MEND = 69564, - H_SPELL_SHADOW_MEND = 70205, - - //Soul Horror - SPELL_SOUL_STRIKE = 69088, - H_SPELL_SOUL_STRIKE = 70211, -}; - -enum Events -{ - EVENT_NONE, - - // Jaina/Sylvanas Intro - EVENT_INTRO_1, - EVENT_INTRO_2, - EVENT_INTRO_3, - EVENT_INTRO_4, - EVENT_INTRO_5, - EVENT_INTRO_6, - EVENT_INTRO_7, - EVENT_INTRO_8, - - //Spiteful Apparition - EVENT_SPITE, - - //Spectral Warden - EVENT_VEIL_OF_SHADOWS, - EVENT_WAIL_OF_SOULS, - - //Soulguard Watchman - EVENT_SHROUD_OF_RUNES, - EVENT_UNHOLY_RAGE, - - //Soulguard Reaper - EVENT_FROST_NOVA, - EVENT_SHADOW_LANCE, - - //Soulguard Bonecaster - EVENT_BONE_VOLLEY, - EVENT_RAISE_DEAD, - EVENT_SHIELD_OF_BONES, - - //Soulguard Animator - EVENT_SHADOW_BOLT, - EVENT_SOUL_SICKNESS, - EVENT_SOUL_SIPHON, - - //Soulguard Adept - EVENT_DRAIN_LIFE, - EVENT_SHADOW_MEND, - - //Soul Horror - EVENT_SOUL_STRIKE, -}; - -/****************************************SYLVANAS************************************/ -#define GOSSIP_SYLVANAS_ITEM "What would you have of me, Banshee Queen?" -#define GOSSIP_JAINA_ITEM "What would you have of me, my lady?" - -enum Yells -{ - SAY_JAINA_INTRO_1 = -1632040, - SAY_JAINA_INTRO_2 = -1632041, - SAY_JAINA_INTRO_3 = -1632042, - SAY_JAINA_INTRO_4 = -1632043, - SAY_JAINA_INTRO_5 = -1632044, - SAY_JAINA_INTRO_6 = -1632045, - SAY_JAINA_INTRO_7 = -1632046, - SAY_JAINA_INTRO_8 = -1632047, - - SAY_SYLVANAS_INTRO_1 = -1632050, - SAY_SYLVANAS_INTRO_2 = -1632051, - SAY_SYLVANAS_INTRO_3 = -1632052, - SAY_SYLVANAS_INTRO_4 = -1632053, - SAY_SYLVANAS_INTRO_5 = -1632054, - SAY_SYLVANAS_INTRO_6 = -1632055, -}; - -enum eSylvanas -{ - GOSSIP_SPEECHINTRO = 13525, - ACTION_INTRO, -}; - -enum Phase -{ - PHASE_NORMAL, - PHASE_INTRO, -}; - -struct npc_sylvanas_fosAI: public ScriptedAI -{ - npc_sylvanas_fosAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - ScriptedInstance* pInstance; - - EventMap events; - Phase phase; - - void Reset() - { - events.Reset(); - phase = PHASE_NORMAL; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_INTRO: - { - phase = PHASE_INTRO; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - events.Reset(); - events.ScheduleEvent(EVENT_INTRO_1, 1000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_INTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_INTRO_1: - DoScriptText(SAY_SYLVANAS_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_2, 11500); - break; - - case EVENT_INTRO_2: - DoScriptText(SAY_SYLVANAS_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_3, 10500); - break; - - case EVENT_INTRO_3: - DoScriptText(SAY_SYLVANAS_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_4, 9500); - break; - - case EVENT_INTRO_4: - DoScriptText(SAY_SYLVANAS_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_5, 10500); - break; - - case EVENT_INTRO_5: - DoScriptText(SAY_SYLVANAS_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_6, 9500); - break; - - case EVENT_INTRO_6: - DoScriptText(SAY_SYLVANAS_INTRO_6, me); - // End of Intro - phase = PHASE_NORMAL; - break; - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - //if (me->hasUnitState(UNIT_STAT_CASTING)) - // return; - - //while (uint32 eventId = events.ExecuteEvent()) - //{ - // switch(eventId) - // { - // } - //} - - DoMeleeAttackIfReady(); - } -}; - -struct npc_jaina_fosAI: public ScriptedAI -{ - npc_jaina_fosAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - ScriptedInstance* pInstance; - - EventMap events; - Phase phase; - - void Reset() - { - events.Reset(); - phase = PHASE_NORMAL; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_INTRO: - { - phase = PHASE_INTRO; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - events.Reset(); - events.ScheduleEvent(EVENT_INTRO_1, 1000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_INTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_INTRO_1: - DoScriptText(SAY_JAINA_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_2, 8000); - break; - - case EVENT_INTRO_2: - DoScriptText(SAY_JAINA_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_3, 8500); - break; - - case EVENT_INTRO_3: - DoScriptText(SAY_JAINA_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_4, 8000); - break; - - case EVENT_INTRO_4: - DoScriptText(SAY_JAINA_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_5, 10000); - break; - - case EVENT_INTRO_5: - DoScriptText(SAY_JAINA_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_6, 8000); - break; - - case EVENT_INTRO_6: - DoScriptText(SAY_JAINA_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_7, 12000); - break; - - case EVENT_INTRO_7: - DoScriptText(SAY_JAINA_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_8, 8000); - break; - - case EVENT_INTRO_8: - DoScriptText(SAY_JAINA_INTRO_8, me); - // End of Intro - phase = PHASE_NORMAL; - break; - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - //if (me->hasUnitState(UNIT_STAT_CASTING)) - // return; - - //while (uint32 eventId = events.ExecuteEvent()) - //{ - // switch(eventId) - // { - // } - //} - - DoMeleeAttackIfReady(); - } -}; - -bool GossipHello_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->GetEntry() == NPC_JAINA_PART1) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_JAINA_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - else - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SYLVANAS_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_INTRO); - break; - } - - return true; -} - -struct mob_spiteful_apparitionAI: public ScriptedAI -{ - mob_spiteful_apparitionAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SPITE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SPITE: - DoCast(me->getVictim(), SPELL_SPITE); - events.RescheduleEvent(EVENT_SPITE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_spectral_wardenAI: public ScriptedAI -{ - mob_spectral_wardenAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_VEIL_OF_SHADOWS, 5000); - events.ScheduleEvent(EVENT_WAIL_OF_SOULS, 10000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_VEIL_OF_SHADOWS: - DoCast(me->getVictim(), SPELL_VEIL_OF_SHADOWS); - events.RescheduleEvent(EVENT_VEIL_OF_SHADOWS, 10000); - return; - case EVENT_WAIL_OF_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_WAIL_OF_SOULS); - events.RescheduleEvent(EVENT_WAIL_OF_SOULS, 5000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_watchmanAI: public ScriptedAI -{ - mob_soulguard_watchmanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHROUD_OF_RUNES, 1000); - events.ScheduleEvent(EVENT_UNHOLY_RAGE, 1000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHROUD_OF_RUNES: - DoCast(me, SPELL_SHROUD_OF_RUNES); - events.RescheduleEvent(EVENT_SHROUD_OF_RUNES, 5000); - return; - case EVENT_UNHOLY_RAGE: - DoCast(me, SPELL_UNHOLY_RAGE); - events.RescheduleEvent(EVENT_UNHOLY_RAGE, 99999); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_reaperAI: public ScriptedAI -{ - mob_soulguard_reaperAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_NOVA, 8000); - events.ScheduleEvent(EVENT_SHADOW_LANCE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROST_NOVA: - DoCast(me, SPELL_FROST_NOVA); - events.RescheduleEvent(EVENT_FROST_NOVA, 9600); - return; - case EVENT_SHADOW_LANCE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_LANCE); - events.RescheduleEvent(EVENT_SHADOW_LANCE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_bonecasterAI: public ScriptedAI -{ - mob_soulguard_bonecasterAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BONE_VOLLEY, 6000); - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHIELD_OF_BONES, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BONE_VOLLEY: - DoCastAOE(SPELL_BONE_VOLLEY); - events.RescheduleEvent(EVENT_BONE_VOLLEY, 7000); - return; - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHIELD_OF_BONES: - DoCast(me, SPELL_SHIELD_OF_BONES); - events.RescheduleEvent(EVENT_SHIELD_OF_BONES, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_animatorAI: public ScriptedAI -{ - mob_soulguard_animatorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 5000); - events.ScheduleEvent(EVENT_SOUL_SICKNESS, 8000); - events.ScheduleEvent(EVENT_SOUL_SIPHON, 10000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; - case EVENT_SOUL_SICKNESS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SOUL_SICKNESS); - events.RescheduleEvent(EVENT_SOUL_SICKNESS, 10000); - return; - case EVENT_SOUL_SIPHON: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SOUL_SIPHON); - events.RescheduleEvent(EVENT_SOUL_SIPHON, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_adeptAI: public ScriptedAI -{ - mob_soulguard_adeptAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 8000); - events.ScheduleEvent(EVENT_DRAIN_LIFE, 7000); - events.ScheduleEvent(EVENT_SHADOW_MEND, 35000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 4000); - return; - case EVENT_DRAIN_LIFE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DRAIN_LIFE); - events.RescheduleEvent(EVENT_DRAIN_LIFE, 9000); - return; - case EVENT_SHADOW_MEND: - DoCast(me, SPELL_SHADOW_MEND); - events.RescheduleEvent(EVENT_SHADOW_MEND, 20000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soul_horrorAI: public ScriptedAI -{ - mob_soul_horrorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SOUL_STRIKE, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SOUL_STRIKE: - DoCast(me->getVictim(), SPELL_SOUL_STRIKE); - events.RescheduleEvent(EVENT_SOUL_STRIKE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_jaina_fosAI(Creature* pCreature) -{ - return new npc_jaina_fosAI(pCreature); -}; - -CreatureAI* GetAI_npc_sylvanas_fosAI(Creature* pCreature) -{ - return new npc_sylvanas_fosAI(pCreature); -}; - -CreatureAI* GetAI_mob_spiteful_apparitionAI(Creature* pCreature) -{ - return new mob_spiteful_apparitionAI(pCreature); -} - -CreatureAI* GetAI_mob_spectral_wardenAI(Creature* pCreature) -{ - return new mob_spectral_wardenAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_watchmanAI(Creature* pCreature) -{ - return new mob_soulguard_watchmanAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_reaperAI(Creature* pCreature) -{ - return new mob_soulguard_reaperAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_bonecasterAI(Creature* pCreature) -{ - return new mob_soulguard_bonecasterAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_animatorAI(Creature* pCreature) -{ - return new mob_soulguard_animatorAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_adeptAI(Creature* pCreature) -{ - return new mob_soulguard_adeptAI(pCreature); -} - -CreatureAI* GetAI_mob_soul_horrorAI(Creature* pCreature) -{ - return new mob_soul_horrorAI(pCreature); -} - -void AddSC_forge_of_souls() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sylvanas_fos"; - newscript->GetAI = &GetAI_npc_sylvanas_fosAI; - newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jaina_fos"; - newscript->GetAI = &GetAI_npc_jaina_fosAI; - newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_spiteful_apparition"; - newscript->GetAI = &GetAI_mob_spiteful_apparitionAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_spectral_warden"; - newscript->GetAI = &GetAI_mob_spectral_wardenAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_watchman"; - newscript->GetAI = &GetAI_mob_soulguard_watchmanAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_reaper"; - newscript->GetAI = &GetAI_mob_soulguard_reaperAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_bonecaster"; - newscript->GetAI = &GetAI_mob_soulguard_bonecasterAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_animator"; - newscript->GetAI = &GetAI_mob_soulguard_animatorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_adept"; - newscript->GetAI = &GetAI_mob_soulguard_adeptAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soul_horror"; - newscript->GetAI = &GetAI_mob_soul_horrorAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h b/src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h deleted file mode 100644 index e0479eb4d2b..00000000000 --- a/src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_FORGE_OF_SOULS_H -#define DEF_FORGE_OF_SOULS_H - -enum Data -{ - DATA_BRONJAHM_EVENT, - DATA_DEVOURER_EVENT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_BRONJAHM, - DATA_DEVOURER, -}; - -enum Creatures -{ - CREATURE_BRONJAHM = 36497, - CREATURE_DEVOURER = 36502, - - NPC_SYLVANAS_PART1 = 37596, - NPC_SYLVANAS_PART2 = 38161, - NPC_JAINA_PART1 = 37597, - NPC_JAINA_PART2 = 38160, - NPC_KALIRA = 37583, - NPC_ELANDRA = 37774, - NPC_LORALEN = 37779, - NPC_KORELN = 37582, - NPC_CHAMPION_1_HORDE = 37584, - NPC_CHAMPION_2_HORDE = 37587, - NPC_CHAMPION_3_HORDE = 37588, - NPC_CHAMPION_1_ALLIANCE = 37496, - NPC_CHAMPION_2_ALLIANCE = 37497, -}; -#endif diff --git a/src/server/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp b/src/server/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp deleted file mode 100644 index 67a6cdb4579..00000000000 --- a/src/server/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -#define MAX_ENCOUNTER 2 - -/* Forge of Souls encounters: -0- Bronjahm, The Godfather of Souls -1- The Devourer of Souls -*/ - -struct instance_forge_of_souls : public ScriptedInstance -{ - instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiBronjahm; - uint64 uiDevourer; - - uint32 uiEncounter[MAX_ENCOUNTER]; - uint32 uiTeamInInstance; - - void Initialize() - { - uiBronjahm = 0; - uiDevourer = 0; - - uiTeamInInstance = 0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - - if (!players.isEmpty()) - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - - switch(pCreature->GetEntry()) - { - case CREATURE_BRONJAHM: - uiBronjahm = pCreature->GetGUID(); - break; - case CREATURE_DEVOURER: - uiDevourer = pCreature->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_BRONJAHM_EVENT: - uiEncounter[0] = data; - break; - case DATA_DEVOURER_EVENT: - uiEncounter[1] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_BRONJAHM_EVENT: return uiEncounter[0]; - case DATA_DEVOURER_EVENT: return uiEncounter[1]; - case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_BRONJAHM: return uiBronjahm; - case DATA_DEVOURER: return uiBronjahm; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "F S " << uiEncounter[0] << " " << uiEncounter[1]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; - - if (dataHead1 == 'F' && dataHead2 == 'S') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap) -{ - return new instance_forge_of_souls(pMap); -} - -void AddSC_instance_forge_of_souls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_forge_of_souls"; - newscript->GetInstanceData = &GetInstanceData_instance_forge_of_souls; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp b/src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp deleted file mode 100644 index c9978faca6e..00000000000 --- a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_AGGRO = -1668050, - SAY_SLAY_1 = -1668051, - SAY_SLAY_2 = -1668052, - SAY_DEATH = -1668053, - SAY_IMPENDING_DESPAIR = -1668054, - SAY_DEFILING_HORROR = -1668055, -}; - -enum Spells -{ - SPELL_QUIVERING_STRIKE = 72422, - SPELL_IMPENDING_DESPAIR = 72426, - SPELL_DEFILING_HORROR = 72435, - SPELL_HOPELESSNESS = 72395, - H_SPELL_HOPELESSNESS = 72390, // TODO: not in dbc. Add in DB. -}; - -enum Events -{ - EVENT_NONE, - EVENT_QUIVERING_STRIKE, - EVENT_IMPENDING_DESPAIR, - EVENT_DEFILING_HORROR, -}; - -struct boss_falricAI : public boss_horAI -{ - boss_falricAI(Creature *pCreature) : boss_horAI(pCreature) {} - - uint8 uiHopelessnessCount; - - void Reset() - { - boss_horAI::Reset(); - - uiHopelessnessCount = 0; - - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000); - events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000); - events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, DONE); - } - - void KilledUnit(Unit *victim) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_QUIVERING_STRIKE: - DoCast(SPELL_QUIVERING_STRIKE); - events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000); - break; - case EVENT_IMPENDING_DESPAIR: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - { - DoScriptText(SAY_IMPENDING_DESPAIR, me); - DoCast(pTarget, SPELL_IMPENDING_DESPAIR); - } - events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000); - break; - case EVENT_DEFILING_HORROR: - DoCast(SPELL_DEFILING_HORROR); - events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. - break; - } - - if ((uiHopelessnessCount < 1 && HealthBelowPct(66)) - || (uiHopelessnessCount < 2 && HealthBelowPct(33)) - || (uiHopelessnessCount < 3 && HealthBelowPct(10))) - { - uiHopelessnessCount++; - DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS,H_SPELL_HOPELESSNESS)); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_falric(Creature* pCreature) -{ - return new boss_falricAI(pCreature); -} - -void AddSC_boss_falric() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_falric"; - newscript->GetAI = &GetAI_boss_falric; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp b/src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp deleted file mode 100644 index 95fb2737ce9..00000000000 --- a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_AGGRO = -1668060, - SAY_SLAY_1 = -1668061, - SAY_SLAY_2 = -1668062, - SAY_DEATH = -1668063, - SAY_CORRUPTED_FLESH_1 = -1668064, - SAY_CORRUPTED_FLESH_2 = -1668065, -}; - -enum Spells -{ - SPELL_OBLITERATE = 72360, - SPELL_WELL_OF_CORRUPTION = 72362, - SPELL_CORRUPTED_FLESH = 72363, - SPELL_SHARED_SUFFERING = 72368, -}; - -enum Events -{ - EVENT_NONE, - EVENT_OBLITERATE, - EVENT_WELL_OF_CORRUPTION, - EVENT_CORRUPTED_FLESH, - EVENT_SHARED_SUFFERING, -}; - -struct boss_marwynAI : public boss_horAI -{ - boss_marwynAI(Creature *pCreature) : boss_horAI(pCreature) {} - - void Reset() - { - boss_horAI::Reset(); - - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_OBLITERATE, 30000); // TODO Check timer - events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); - events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); - events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); // TODO Check timer - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, DONE); - } - - void KilledUnit(Unit *victim) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_OBLITERATE: - DoCast(SPELL_OBLITERATE); - events.ScheduleEvent(EVENT_OBLITERATE, 30000); - break; - case EVENT_WELL_OF_CORRUPTION: - DoCast(SPELL_WELL_OF_CORRUPTION); - events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); - break; - case EVENT_CORRUPTED_FLESH: - DoScriptText(RAND(SAY_CORRUPTED_FLESH_1,SAY_CORRUPTED_FLESH_2), me); - DoCast(SPELL_CORRUPTED_FLESH); - events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); - break; - case EVENT_SHARED_SUFFERING: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHARED_SUFFERING); - events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); - break; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_marwyn(Creature* pCreature) -{ - return new boss_marwynAI(pCreature); -} - -void AddSC_boss_marwyn() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_marwyn"; - newscript->GetAI = &GetAI_boss_marwyn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp b/src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp deleted file mode 100644 index fb3d3d5d752..00000000000 --- a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_JAINA_INTRO_1 = -1668001, - SAY_JAINA_INTRO_2 = -1668002, - SAY_JAINA_INTRO_3 = -1668003, - SAY_JAINA_INTRO_4 = -1668004, - SAY_UTHER_INTRO_A2_1 = -1668005, - SAY_JAINA_INTRO_5 = -1668006, - SAY_UTHER_INTRO_A2_2 = -1668007, - SAY_JAINA_INTRO_6 = -1668008, - SAY_UTHER_INTRO_A2_3 = -1668009, - SAY_JAINA_INTRO_7 = -1668010, - SAY_UTHER_INTRO_A2_4 = -1668011, - SAY_JAINA_INTRO_8 = -1668012, - SAY_UTHER_INTRO_A2_5 = -1668013, - SAY_JAINA_INTRO_9 = -1668014, - SAY_UTHER_INTRO_A2_6 = -1668015, - SAY_UTHER_INTRO_A2_7 = -1668016, - SAY_JAINA_INTRO_10 = -1668017, - SAY_UTHER_INTRO_A2_8 = -1668018, - SAY_JAINA_INTRO_11 = -1668019, - SAY_UTHER_INTRO_A2_9 = -1668020, - - SAY_SYLVANAS_INTRO_1 = -1668021, - SAY_SYLVANAS_INTRO_2 = -1668022, - SAY_SYLVANAS_INTRO_3 = -1668023, - SAY_UTHER_INTRO_H2_1 = -1668024, - SAY_SYLVANAS_INTRO_4 = -1668025, - SAY_UTHER_INTRO_H2_2 = -1668026, - SAY_SYLVANAS_INTRO_5 = -1668027, - SAY_UTHER_INTRO_H2_3 = -1668028, - SAY_SYLVANAS_INTRO_6 = -1668029, - SAY_UTHER_INTRO_H2_4 = -1668030, - SAY_SYLVANAS_INTRO_7 = -1668031, - SAY_UTHER_INTRO_H2_5 = -1668032, - SAY_UTHER_INTRO_H2_6 = -1668033, - SAY_SYLVANAS_INTRO_8 = -1668034, - SAY_UTHER_INTRO_H2_7 = -1668035, - - SAY_LK_INTRO_1 = -1668036, - SAY_LK_INTRO_2 = -1668037, - SAY_LK_INTRO_3 = -1668038, - SAY_FALRIC_INTRO_1 = -1668039, - SAY_MARWYN_INTRO_1 = -1668040, - SAY_FALRIC_INTRO_2 = -1668041, - - SAY_JAINA_INTRO_END = -1668042, - SAY_SYLVANAS_INTRO_END = -1668043, -}; - -enum Events -{ - EVENT_NONE, - - EVENT_START_INTRO, - EVENT_SKIP_INTRO, - - EVENT_INTRO_A2_1, - EVENT_INTRO_A2_2, - EVENT_INTRO_A2_3, - EVENT_INTRO_A2_4, - EVENT_INTRO_A2_5, - EVENT_INTRO_A2_6, - EVENT_INTRO_A2_7, - EVENT_INTRO_A2_8, - EVENT_INTRO_A2_9, - EVENT_INTRO_A2_10, - EVENT_INTRO_A2_11, - EVENT_INTRO_A2_12, - EVENT_INTRO_A2_13, - EVENT_INTRO_A2_14, - EVENT_INTRO_A2_15, - EVENT_INTRO_A2_16, - EVENT_INTRO_A2_17, - EVENT_INTRO_A2_18, - EVENT_INTRO_A2_19, - - EVENT_INTRO_H2_1, - EVENT_INTRO_H2_2, - EVENT_INTRO_H2_3, - EVENT_INTRO_H2_4, - EVENT_INTRO_H2_5, - EVENT_INTRO_H2_6, - EVENT_INTRO_H2_7, - EVENT_INTRO_H2_8, - EVENT_INTRO_H2_9, - EVENT_INTRO_H2_10, - EVENT_INTRO_H2_11, - EVENT_INTRO_H2_12, - EVENT_INTRO_H2_13, - EVENT_INTRO_H2_14, - EVENT_INTRO_H2_15, - - EVENT_INTRO_LK_1, - EVENT_INTRO_LK_2, - EVENT_INTRO_LK_3, - EVENT_INTRO_LK_4, - EVENT_INTRO_LK_5, - EVENT_INTRO_LK_6, - EVENT_INTRO_LK_7, - EVENT_INTRO_LK_8, - EVENT_INTRO_LK_9, - - EVENT_INTRO_END, -}; - -enum eEnum -{ - ACTION_START_INTRO, - ACTION_SKIP_INTRO, - - QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710, - QUEST_DELIVRANCE_FROM_THE_PIT_H2 = 24712, - QUEST_WRATH_OF_THE_LICH_KING_A2 = 24500, - QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802, -}; - -static Position HallsofReflectionLocs[]= -{ - {5283.234863, 1990.946777, 707.695679, 0.929097}, // 2 Loralen Follows - {5408.031250, 2102.918213, 707.695251, 0.792756}, // 9 Sylvanas Follows - {5401.866699, 2110.837402, 707.695251, 0.800610}, // 10 Loralen follows -}; - -static Position SpawnPos = {5262.540527, 1949.693726, 707.695007, 0.808736}; // Jaina/Sylvanas Beginning Position -static Position MoveThronePos = {5306.952148, 1998.499023, 709.341431, 1.277278}; // Jaina/Sylvanas walks to throne -static Position UtherSpawnPos = {5308.310059, 2003.857178, 709.341431, 4.650315}; -static Position LichKingSpawnPos = {5362.917480, 2062.307129, 707.695374, 3.945812}; -static Position LichKingMoveThronePos = {5312.080566, 2009.172119, 709.341431, 3.973301}; // Lich King walks to throne -static Position LichKingMoveAwayPos = {5400.069824, 2102.7131689, 707.69525, 0.843803}; // Lich King walks away - -// AI of Part1: handle the intro till start of gauntlet event. -struct npc_jaina_or_sylvanas_horAI : public ScriptedAI -{ - npc_jaina_or_sylvanas_horAI(Creature *pCreature) : ScriptedAI(pCreature) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint64 uiUther; - uint64 uiLichKing; - - EventMap events; - - void Reset() - { - events.Reset(); - - uiUther = 0; - uiLichKing = 0; - - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetVisibility(VISIBILITY_ON); - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_START_INTRO: - events.ScheduleEvent(EVENT_START_INTRO, 0); - break; - case ACTION_SKIP_INTRO: - events.ScheduleEvent(EVENT_SKIP_INTRO, 0); - break; - } - } - - void UpdateAI(const uint32 diff) - { - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_START_INTRO: - me->GetMotionMaster()->MovePoint(0, MoveThronePos); - // Begining of intro is differents between factions as the speech sequence and timers are differents. - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - events.ScheduleEvent(EVENT_INTRO_A2_1, 0); - else - events.ScheduleEvent(EVENT_INTRO_H2_1, 0); - break; - - // A2 Intro Events - case EVENT_INTRO_A2_1: - DoScriptText(SAY_JAINA_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_A2_2, 5000); - break; - case EVENT_INTRO_A2_2: - DoScriptText(SAY_JAINA_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_A2_3, 10000); - break; - case EVENT_INTRO_A2_3: - // TODO: she's doing some kind of spell casting emote - pInstance->HandleGameObject(pInstance->GetData64(DATA_FROSTMOURNE), true); - events.ScheduleEvent(EVENT_INTRO_A2_4, 10000); - break; - case EVENT_INTRO_A2_4: - // spawn UTHER during speach 2 - if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pUther->GetMotionMaster()->MoveIdle(); - pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas - uiUther = pUther->GetGUID(); - } - events.ScheduleEvent(EVENT_INTRO_A2_5, 2000); - break; - case EVENT_INTRO_A2_5: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_1, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_6, 3000); - break; - case EVENT_INTRO_A2_6: - DoScriptText(SAY_JAINA_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_A2_7, 6000); - break; - case EVENT_INTRO_A2_7: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_2, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_8, 6500); - break; - case EVENT_INTRO_A2_8: - DoScriptText(SAY_JAINA_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_A2_9, 2000); - break; - case EVENT_INTRO_A2_9: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_3, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_10, 9000); - break; - case EVENT_INTRO_A2_10: - DoScriptText(SAY_JAINA_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_A2_11, 5000); - break; - case EVENT_INTRO_A2_11: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_4, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_12, 11000); - break; - case EVENT_INTRO_A2_12: - DoScriptText(SAY_JAINA_INTRO_8, me); - events.ScheduleEvent(EVENT_INTRO_A2_13, 4000); - break; - case EVENT_INTRO_A2_13: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_5, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_14, 12500); - break; - case EVENT_INTRO_A2_14: - DoScriptText(SAY_JAINA_INTRO_9, me); - events.ScheduleEvent(EVENT_INTRO_A2_15, 10000); - break; - case EVENT_INTRO_A2_15: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_6, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_16, 22000); - break; - case EVENT_INTRO_A2_16: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_7, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_17, 4000); - break; - case EVENT_INTRO_A2_17: - DoScriptText(SAY_JAINA_INTRO_10, me); - events.ScheduleEvent(EVENT_INTRO_A2_18, 2000); - break; - case EVENT_INTRO_A2_18: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); - DoScriptText(SAY_UTHER_INTRO_A2_8, pUther); - } - events.ScheduleEvent(EVENT_INTRO_A2_19, 11000); - break; - case EVENT_INTRO_A2_19: - DoScriptText(SAY_JAINA_INTRO_11, me); - events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); - break; - - // H2 Intro Events - case EVENT_INTRO_H2_1: - DoScriptText(SAY_SYLVANAS_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_H2_2, 8000); - break; - case EVENT_INTRO_H2_2: - DoScriptText(SAY_SYLVANAS_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_H2_3, 6000); - break; - case EVENT_INTRO_H2_3: - DoScriptText(SAY_SYLVANAS_INTRO_3, me); - // TODO: she's doing some kind of spell casting emote - events.ScheduleEvent(EVENT_INTRO_H2_4, 6000); - break; - case EVENT_INTRO_H2_4: - // spawn UTHER during speach 2 - if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pUther->GetMotionMaster()->MoveIdle(); - pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas - uiUther = pUther->GetGUID(); - } - events.ScheduleEvent(EVENT_INTRO_H2_5, 2000); - break; - case EVENT_INTRO_H2_5: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_1, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_6, 11000); - break; - case EVENT_INTRO_H2_6: - DoScriptText(SAY_SYLVANAS_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_H2_7, 3000); - break; - case EVENT_INTRO_H2_7: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_2, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_8, 6000); - break; - case EVENT_INTRO_H2_8: - DoScriptText(SAY_SYLVANAS_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_H2_9, 5000); - break; - case EVENT_INTRO_H2_9: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_3, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_10, 19000); - break; - case EVENT_INTRO_H2_10: - DoScriptText(SAY_SYLVANAS_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_H2_11, 1500); - break; - case EVENT_INTRO_H2_11: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_4, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_12, 19500); - break; - case EVENT_INTRO_H2_12: - DoScriptText(SAY_SYLVANAS_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_H2_13, 2000); - break; - case EVENT_INTRO_H2_13: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); - DoScriptText(SAY_UTHER_INTRO_H2_5, pUther); - } - events.ScheduleEvent(EVENT_INTRO_H2_14, 12000); - break; - case EVENT_INTRO_H2_14: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_6, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_15, 8000); - break; - case EVENT_INTRO_H2_15: - DoScriptText(SAY_SYLVANAS_INTRO_8, me); - events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); - break; - - // Remaining Intro Events common for both faction - case EVENT_INTRO_LK_1: - // Spawn LK in front of door, and make him move to the sword. - if (Creature* pLichKing = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pLichKing->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); - pLichKing->SetReactState(REACT_PASSIVE); - uiLichKing = pLichKing->GetGUID(); - } - - if (Creature* pUther = me->GetCreature(*me, uiUther)) - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - DoScriptText(SAY_UTHER_INTRO_A2_9, pUther); - else - DoScriptText(SAY_UTHER_INTRO_H2_7, pUther); - - events.ScheduleEvent(EVENT_INTRO_LK_2, 11000); - break; - - case EVENT_INTRO_LK_2: - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - DoScriptText(SAY_LK_INTRO_1, pLichKing); - events.ScheduleEvent(EVENT_INTRO_LK_3, 2000); - break; - - case EVENT_INTRO_LK_3: - // The Lich King banishes Uther to the abyss. - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->DisappearAndDie(); - uiUther = 0; - } - - // He steps forward and removes the runeblade from the heap of skulls. - - events.ScheduleEvent(EVENT_INTRO_LK_4, 4000); - break; - - case EVENT_INTRO_LK_4: - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - DoScriptText(SAY_LK_INTRO_2, pLichKing); - events.ScheduleEvent(EVENT_INTRO_LK_5, 10000); - break; - - case EVENT_INTRO_LK_5: - // summon Falric and Marwyn. then go back to the door - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - pFalric->SetVisibility(VISIBILITY_ON); - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - pMarwyn->SetVisibility(VISIBILITY_ON); - - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - { - pLichKing->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - DoScriptText(SAY_LK_INTRO_3, pLichKing); - } - - events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); - break; - - case EVENT_INTRO_LK_6: - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - DoScriptText(SAY_FALRIC_INTRO_1, pFalric); - - events.ScheduleEvent(EVENT_INTRO_LK_7, 2000); - break; - - case EVENT_INTRO_LK_7: - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - DoScriptText(SAY_MARWYN_INTRO_1, pMarwyn); - - events.ScheduleEvent(EVENT_INTRO_LK_8, 2000); - break; - - case EVENT_INTRO_LK_8: - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - DoScriptText(SAY_FALRIC_INTRO_2, pFalric); - - events.ScheduleEvent(EVENT_INTRO_LK_9, 5000); - break; - - case EVENT_INTRO_LK_9: - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - DoScriptText(SAY_JAINA_INTRO_END, me); - else - DoScriptText(SAY_SYLVANAS_INTRO_END, me); - - me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - // TODO: Loralen/Koreln shall run also - events.ScheduleEvent(EVENT_INTRO_END, 10000); - break; - - case EVENT_INTRO_END: - if (pInstance) - pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave - - // Loralen or Koreln disappearAndDie() - me->DisappearAndDie(); - break; - - case EVENT_SKIP_INTRO: - // TODO: implement - - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - pFalric->SetVisibility(VISIBILITY_ON); - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - pMarwyn->SetVisibility(VISIBILITY_ON); - - me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - // TODO: Loralen/Koreln shall run also - - events.ScheduleEvent(EVENT_INTRO_END, 15000); - break; - } - } -}; - -bool GossipHello_npc_sylvanas_hor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_H2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - // once last quest is completed, she offers this shortcut of the starting event - if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_H2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Dark Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - - return true; -} - -bool GossipHello_npc_jaina_hor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_A2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - // once last quest of the series is completed, she offers this shortcut of the starting event - if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_A2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "My Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_or_sylvanas_hor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_START_INTRO); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_SKIP_INTRO); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - } - - return true; -} - -enum TrashSpells -{ - // Ghostly Priest - SPELL_SHADOW_WORD_PAIN = 72318, - SPELL_CIRCLE_OF_DESTRUCTION = 72320, - SPELL_COWER_IN_FEAR = 72321, - SPELL_DARK_MENDING = 72322, - - // Phantom Mage - SPELL_FIREBALL = 72163, - SPELL_FLAMESTRIKE = 72169, - SPELL_FROSTBOLT = 72166, - SPELL_CHAINS_OF_ICE = 72121, - SPELL_HALLUCINATION = 72342, - - // Phantom Hallucination (same as phantom mage + HALLUCINATION_2 when dies) - SPELL_HALLUCINATION_2 = 72344, - - // Shadowy Mercenary - SPELL_SHADOW_STEP = 72326, - SPELL_DEADLY_POISON = 72329, - SPELL_ENVENOMED_DAGGER_THROW = 72333, - SPELL_KIDNEY_SHOT = 72335, - - // Spectral Footman - SPELL_SPECTRAL_STRIKE = 72198, - SPELL_SHIELD_BASH = 72194, - SPELL_TORTURED_ENRAGE = 72203, - - // Tortured Rifleman - SPELL_SHOOT = 72208, - SPELL_CURSED_ARROW = 72222, - SPELL_FROST_TRAP = 72215, - SPELL_ICE_SHOT = 72268, -}; - -enum TrashEvents -{ - EVENT_TRASH_NONE, - - // Ghostly Priest - EVENT_SHADOW_WORD_PAIN, - EVENT_CIRCLE_OF_DESTRUCTION, - EVENT_COWER_IN_FEAR, - EVENT_DARK_MENDING, - - // Phantom Mage - EVENT_FIREBALL, - EVENT_FLAMESTRIKE, - EVENT_FROSTBOLT, - EVENT_CHAINS_OF_ICE, - EVENT_HALLUCINATION, - - // Shadowy Mercenary - EVENT_SHADOW_STEP, - EVENT_DEADLY_POISON, - EVENT_ENVENOMED_DAGGER_THROW, - EVENT_KIDNEY_SHOT, - - // Spectral Footman - EVENT_SPECTRAL_STRIKE, - EVENT_SHIELD_BASH, - EVENT_TORTURED_ENRAGE, - - // Tortured Rifleman - EVENT_SHOOT, - EVENT_CURSED_ARROW, - EVENT_FROST_TRAP, - EVENT_ICE_SHOT, -}; - -struct npc_ghostly_priestAI: public ScriptedAI -{ - npc_ghostly_priestAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); // TODO: adjust timers - events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); - events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); - events.ScheduleEvent(EVENT_DARK_MENDING, 20000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_WORD_PAIN: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); - return; - case EVENT_CIRCLE_OF_DESTRUCTION: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CIRCLE_OF_DESTRUCTION); - events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); - return; - case EVENT_COWER_IN_FEAR: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_COWER_IN_FEAR); - events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); - return; - case EVENT_DARK_MENDING: - // find an ally with missing HP - if (Unit *pTarget = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000,50000))) - { - DoCast(pTarget, SPELL_DARK_MENDING); - events.ScheduleEvent(EVENT_DARK_MENDING, 20000); - } - else - { - // no friendly unit with missing hp. re-check in just 5 sec. - events.ScheduleEvent(EVENT_DARK_MENDING, 5000); - } - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_phantom_mageAI: public ScriptedAI -{ - npc_phantom_mageAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FIREBALL, 3000); // TODO: adjust timers - events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000); - events.ScheduleEvent(EVENT_FROSTBOLT, 9000); - events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000); - events.ScheduleEvent(EVENT_HALLUCINATION, 40000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FIREBALL: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_FIREBALL); - events.ScheduleEvent(EVENT_FIREBALL, 15000); - return; - case EVENT_FLAMESTRIKE: - DoCast(SPELL_FLAMESTRIKE); - events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); - return; - case EVENT_FROSTBOLT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_FROSTBOLT); - events.ScheduleEvent(EVENT_FROSTBOLT, 15000); - return; - case EVENT_CHAINS_OF_ICE: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CHAINS_OF_ICE); - events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); - return; - case EVENT_HALLUCINATION: - DoCast(SPELL_HALLUCINATION); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_phantom_hallucinationAI: public npc_phantom_mageAI -{ - npc_phantom_hallucinationAI(Creature *c) : npc_phantom_mageAI(c) - { - } - - void JustDied(Unit * /*pWho*/) - { - DoCast(SPELL_HALLUCINATION_2); - } -}; - -struct npc_shadowy_mercenaryAI: public ScriptedAI -{ - npc_shadowy_mercenaryAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); // TODO: adjust timers - events.ScheduleEvent(EVENT_DEADLY_POISON, 5000); - events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); - events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_STEP: - DoCast(SPELL_SHADOW_STEP); - events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); - return; - case EVENT_DEADLY_POISON: - DoCast(me->getVictim(), SPELL_DEADLY_POISON); - events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); - return; - case EVENT_ENVENOMED_DAGGER_THROW: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_ENVENOMED_DAGGER_THROW); - events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); - return; - case EVENT_KIDNEY_SHOT: - DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); - events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_spectral_footmanAI: public ScriptedAI -{ - npc_spectral_footmanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); // TODO: adjust timers - events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); - events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SPECTRAL_STRIKE: - DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); - events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); - return; - case EVENT_SHIELD_BASH: - DoCast(me->getVictim(), SPELL_SHIELD_BASH); - events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); - return; - case EVENT_TORTURED_ENRAGE: - DoCast(SPELL_TORTURED_ENRAGE); - events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_tortured_riflemanAI : public ScriptedAI -{ - npc_tortured_riflemanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHOOT, 2000); // TODO: adjust timers - events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); - events.ScheduleEvent(EVENT_FROST_TRAP, 1000); - events.ScheduleEvent(EVENT_ICE_SHOT, 15000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHOOT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHOOT); - events.ScheduleEvent(EVENT_SHOOT, 2000); - return; - case EVENT_CURSED_ARROW: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CURSED_ARROW); - events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); - return; - case EVENT_FROST_TRAP: - DoCast(SPELL_FROST_TRAP); - events.ScheduleEvent(EVENT_FROST_TRAP, 30000); - return; - case EVENT_ICE_SHOT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_ICE_SHOT); - events.ScheduleEvent(EVENT_ICE_SHOT, 15000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_jaina_or_sylvanas_horAI(Creature* pCreature) -{ - return new npc_jaina_or_sylvanas_horAI(pCreature); -} - -CreatureAI* GetAI_npc_ghostly_priestAI(Creature* pCreature) -{ - return new npc_ghostly_priestAI(pCreature); -} - -CreatureAI* GetAI_npc_phantom_mageAI(Creature* pCreature) -{ - return new npc_phantom_mageAI(pCreature); -} - -CreatureAI* GetAI_npc_phantom_hallucinationAI(Creature* pCreature) -{ - return new npc_phantom_hallucinationAI(pCreature); -} - -CreatureAI* GetAI_npc_shadowy_mercenaryAI(Creature* pCreature) -{ - return new npc_shadowy_mercenaryAI(pCreature); -} - -CreatureAI* GetAI_npc_spectral_footmanAI(Creature* pCreature) -{ - return new npc_spectral_footmanAI(pCreature); -} - -CreatureAI* GetAI_npc_tortured_riflemanAI(Creature* pCreature) -{ - return new npc_tortured_riflemanAI(pCreature); -} - -void AddSC_halls_of_reflection() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sylvanas_hor_part1"; - newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; - newscript->pGossipHello = &GossipHello_npc_sylvanas_hor; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jaina_hor_part1"; - newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; - newscript->pGossipHello = &GossipHello_npc_jaina_hor; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ghostly_priest"; - newscript->GetAI = &GetAI_npc_ghostly_priestAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_phantom_mage"; - newscript->GetAI = &GetAI_npc_phantom_mageAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_phantom_hallucination"; - newscript->GetAI = &GetAI_npc_phantom_hallucinationAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_shadowy_mercenary"; - newscript->GetAI = &GetAI_npc_shadowy_mercenaryAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_spectral_footman"; - newscript->GetAI = &GetAI_npc_spectral_footmanAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tortured_rifleman"; - newscript->GetAI = &GetAI_npc_tortured_riflemanAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h b/src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h deleted file mode 100644 index 46ae0cb283c..00000000000 --- a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_HALLS_OF_REFLECTION_H -#define DEF_HALLS_OF_REFLECTION_H - -enum Data -{ - DATA_FALRIC_EVENT, - DATA_MARWYN_EVENT, - DATA_LICHKING_EVENT, - DATA_WAVE_COUNT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_FALRIC, - DATA_MARWYN, - DATA_LICHKING, - DATA_FROSTMOURNE, -}; - -enum Creatures -{ - NPC_FALRIC = 38112, - NPC_MARWYN = 38113, - NPC_LICH_KING_EVENT = 37226, - NPC_LICH_KING_BOSS = 36954, - - NPC_UTHER = 37225, - NPC_JAINA_PART1 = 37221, - NPC_JAINA_PART2 = 36955, - NPC_SYLVANAS_PART1 = 37223, - NPC_SYLVANAS_PART2 = 37554, - - NPC_WAVE_MERCENARY = 38177, - NPC_WAVE_FOOTMAN = 38173, - NPC_WAVE_RIFLEMAN = 38176, - NPC_WAVE_PRIEST = 38175, - NPC_WAVE_MAGE = 38172, -}; - -enum GameObjects -{ - GO_FROSTMOURNE = 202302, - GO_FROSTMOURNE_ALTAR = 202236, - GO_FRONT_DOOR = 201976, - GO_ARTHAS_DOOR = 197341, -}; - -enum HorWorldStates -{ - WORLD_STATE_HOR = 4884, - WORLD_STATE_HOR_WAVE_COUNT = 4882, -}; - -// Common actions from Instance Script to Boss Script -enum Actions -{ - ACTION_ENTER_COMBAT, -}; - -// Base class for FALRIC and MARWYN -// handled the summonList and the notification events to/from the InstanceData -struct boss_horAI : ScriptedAI -{ - boss_horAI(Creature *pCreature) : ScriptedAI(pCreature), summons(pCreature) - { - pInstance = me->GetInstanceData(); - } - - InstanceData* pInstance; - EventMap events; - SummonList summons; - - void Reset() - { - events.Reset(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); - } - - void DamageTaken(Unit *pWho, uint32 &uiDamage) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - uiDamage = 0; - } - - void DoAction(const int32 actionID) - { - switch(actionID) - { - case ACTION_ENTER_COMBAT: // called by InstanceData when boss shall enter in combat. - // Just in case. Should have been done by InstanceData - me->SetVisibility(VISIBILITY_ON); - - // Reset flags - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - - if (Unit *pUnit = me->SelectNearestTarget()) - AttackStart(pUnit); - - DoZoneInCombat(); - break; - } - } - - void JustSummoned(Creature *pSummoned) - { - summons.Summon(pSummoned); - - if (Unit *pUnit = pSummoned->SelectNearestTarget()) - { - if (pSummoned->AI()) - pSummoned->AI()->AttackStart(pUnit); - else - { - pSummoned->GetMotionMaster()->MoveChase(pUnit); - pSummoned->Attack(pUnit, true); - } - } - - if (pSummoned->AI()) - pSummoned->AI()->DoZoneInCombat(); - } - - void SummonedCreatureDespawn(Creature *pSummoned) - { - summons.Despawn(pSummoned); - if (summons.empty()) - { - if (pSummoned->isAlive()) - pInstance->SetData(DATA_WAVE_COUNT, NOT_STARTED); - else - pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); - } - } -}; - -#endif diff --git a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp b/src/server/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp deleted file mode 100644 index 7a5d2479b7c..00000000000 --- a/src/server/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -#define MAX_ENCOUNTER 3 - -/* Halls of Reflection encounters: -0- Falric -1- Marwyn -2- The Lich King -*/ - -enum eEnum -{ - ENCOUNTER_WAVE_MERCENARY = 6, - ENCOUNTER_WAVE_FOOTMAN = 10, - ENCOUNTER_WAVE_RIFLEMAN = 6, - ENCOUNTER_WAVE_PRIEST = 6, - ENCOUNTER_WAVE_MAGE = 6, -}; - -enum Events -{ - EVENT_NONE, - EVENT_NEXT_WAVE, - EVENT_START_LICH_KING, -}; - -static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] = -{ - {5277.74,2016.88,707.778,5.96903}, - {5295.88,2040.34,707.778,5.07891}, - {5320.37,1980.13,707.778,2.00713}, - {5280.51,1997.84,707.778,0.296706}, - {5302.45,2042.22,707.778,4.90438}, - {5306.57,1977.47,707.778,1.50098}, -}; - -static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] = -{ - {5312.75,2037.12,707.778,4.59022}, - {5309.58,2042.67,707.778,4.69494}, - {5275.08,2008.72,707.778,6.21337}, - {5279.65,2004.66,707.778,0.069813}, - {5275.48,2001.14,707.778,0.174533}, - {5316.7,2041.55,707.778,4.50295}, -}; - -static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] = -{ - {5302.25,1972.41,707.778,1.37881}, - {5311.03,1972.23,707.778,1.64061}, - {5277.36,1993.23,707.778,0.401426}, - {5318.7,2036.11,707.778,4.2237}, - {5335.72,1996.86,707.778,2.74017}, - {5299.43,1979.01,707.778,1.23918}, -}; - -static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] = -{ - {5306.06,2037,707.778,4.81711}, - {5344.15,2007.17,707.778,3.15905}, - {5337.83,2010.06,707.778,3.22886}, - {5343.29,1999.38,707.778,2.9147}, - {5340.84,1992.46,707.778,2.75762}, - {5325.07,1977.6,707.778,2.07694}, - {5336.6,2017.28,707.778,3.47321}, - {5313.82,1978.15,707.778,1.74533}, - {5280.63,2012.16,707.778,6.05629}, - {5322.96,2040.29,707.778,4.34587}, -}; - -static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] = -{ - {5343.47,2015.95,707.778,3.49066}, - {5337.86,2003.4,707.778,2.98451}, - {5319.16,1974,707.778,1.91986}, - {5299.25,2036,707.778,5.02655}, - {5295.64,1973.76,707.778,1.18682}, - {5282.9,2019.6,707.778,5.88176}, -}; - -struct instance_halls_of_reflection : public ScriptedInstance -{ - instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiFalric; - uint64 uiMarwyn; - uint64 uiLichKingEvent; - uint64 uiJainaPart1; - uint64 uiSylvanasPart1; - - uint64 uiFrostmourne; - uint64 uiFrostmourneAltar; - uint64 uiArthasDoor; - uint64 uiFrontDoor; - - uint32 uiEncounter[MAX_ENCOUNTER]; - uint32 uiTeamInInstance; - uint32 uiWaveCount; - bool bIntroDone; - - EventMap events; - - void Initialize() - { - events.Reset(); - - uiFalric = 0; - uiMarwyn = 0; - uiLichKingEvent = 0; - uiJainaPart1 = 0; - uiSylvanasPart1 = 0; - - uiFrostmourne = 0; - uiFrostmourneAltar = 0; - uiArthasDoor = 0; - uiFrontDoor = 0; - uiTeamInInstance = 0; - uiWaveCount = 0; - bIntroDone = false; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - if (!add) - return; - - Map::PlayerList const &players = instance->GetPlayers(); - if (!players.isEmpty()) - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - - switch(pCreature->GetEntry()) - { - case NPC_FALRIC: - uiFalric = pCreature->GetGUID(); - break; - case NPC_MARWYN: - uiMarwyn = pCreature->GetGUID(); - break; - case NPC_LICH_KING_EVENT: - uiLichKingEvent = pCreature->GetGUID(); - break; - case NPC_JAINA_PART1: - uiJainaPart1 = pCreature->GetGUID(); - break; - case NPC_SYLVANAS_PART1: - uiSylvanasPart1 = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if (!add) - return; - - // TODO: init state depending on encounters - switch(pGo->GetEntry()) - { - case GO_FROSTMOURNE: - uiFrostmourne = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, false, pGo); - break; - case GO_FROSTMOURNE_ALTAR: - uiFrostmourneAltar = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, true, pGo); - break; - case GO_FRONT_DOOR: - uiFrontDoor = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, true, pGo); - break; - case GO_ARTHAS_DOOR: - uiArthasDoor = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - - if (uiEncounter[1] == DONE) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - if (type == DATA_WAVE_COUNT && data == SPECIAL) - { - bIntroDone = true; - events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); - return; - } - - - if (uiWaveCount && data == NOT_STARTED) - DoWipe(); - - switch(type) - { - case DATA_FALRIC_EVENT: - uiEncounter[0] = data; - if (data == DONE) - events.ScheduleEvent(EVENT_NEXT_WAVE, 60000); - break; - case DATA_MARWYN_EVENT: - uiEncounter[1] = data; - if (data == DONE) - HandleGameObject(uiArthasDoor, true); - break; - case DATA_LICHKING_EVENT: - uiEncounter[2] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_FALRIC_EVENT: return uiEncounter[0]; - case DATA_MARWYN_EVENT: return uiEncounter[1]; - case DATA_LICHKING_EVENT: return uiEncounter[2]; - case DATA_WAVE_COUNT: return uiWaveCount; - case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_FALRIC: return uiFalric; - case DATA_MARWYN: return uiMarwyn; - case DATA_LICHKING: return uiLichKingEvent; - case DATA_FROSTMOURNE: return uiFrostmourne; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H R 1 " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 version; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2; - - if (dataHead1 == 'H' && dataHead2 == 'R') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - if (uiEncounter[0] == DONE || uiEncounter[1] == DONE) - bIntroDone = true; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void AddWave() - { - DoUpdateWorldState(WORLD_STATE_HOR, 1); - DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); - - switch(uiWaveCount) - { - case 1: - case 2: - case 3: - case 4: - if (Creature *pFalric = instance->GetCreature(uiFalric)) - SpawnWave(pFalric); - break; - case 5: - if (GetData(DATA_FALRIC_EVENT) == DONE) - events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); - else if (Creature *pFalric = instance->GetCreature(uiFalric)) - if (pFalric->AI()) - pFalric->AI()->DoAction(ACTION_ENTER_COMBAT); - break; - case 6: - case 7: - case 8: - case 9: - if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) - SpawnWave(pMarwyn); - break; - case 10: - if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit! - if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) - if (pMarwyn->AI()) - pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT); - break; - } - } - - // Wipe has been detected. Perform cleanup and reset. - void DoWipe() - { - uiWaveCount = 0; - events.Reset(); - DoUpdateWorldState(WORLD_STATE_HOR, 1); - DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); - HandleGameObject(uiFrontDoor, true); - - // TODO - // in case of wipe, the event is normally restarted by jumping into the center of the room. - // As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted. - if (Creature* pJaina = instance->GetCreature(uiJainaPart1)) - pJaina->Respawn(); - if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1)) - pSylvanas->Respawn(); - - if (Creature* pFalric = instance->GetCreature(uiFalric)) - pFalric->SetVisibility(VISIBILITY_OFF); - if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) - pMarwyn->SetVisibility(VISIBILITY_OFF); - } - - // spawn a wave on behalf of the summoner. - void SpawnWave(Creature *pSummoner) - { - uint32 index; - - pSummoner->SetVisibility(VISIBILITY_ON); - - // TODO: do composition at random. # of spawn also depends on uiWaveCount - // As of now, it is just one of each. - index = urand(0,ENCOUNTER_WAVE_MERCENARY-1); - pSummoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_FOOTMAN-1); - pSummoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_RIFLEMAN-1); - pSummoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_PRIEST-1); - pSummoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_MAGE-1); - pSummoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - } - - void Update(uint32 diff) - { - if (!instance->HavePlayers()) - return; - - events.Update(diff); - - switch(uint32 eventId = events.ExecuteEvent()) - { - case EVENT_NEXT_WAVE: - uiWaveCount++; - AddWave(); - break; - case EVENT_START_LICH_KING: - // TODO - break; - } - } -}; - -InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap) -{ - return new instance_halls_of_reflection(pMap); -} - -void AddSC_instance_halls_of_reflection() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_reflection"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_reflection; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp b/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp deleted file mode 100644 index 25c78c4a0d3..00000000000 --- a/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -enum Yells -{ - SAY_AGGRO = -1658001, - SAY_SLAY_1 = -1658002, - SAY_SLAY_2 = -1658003, - SAY_DEATH = -1658004, - SAY_PHASE2 = -1658005, - SAY_PHASE3 = -1658006, - - SAY_TYRANNUS_DEATH = -1659007, -}; - -enum eEvents -{ - EVENT_NONE, - EVENT_PERMAFROST, - EVENT_THROW_SARONITE, - EVENT_CHILLINGWAVE, - EVENT_DEEPFREEZE, -}; - -enum Spells -{ - SPELL_PERMAFROST = 70326, - SPELL_PERMAFROST_TRIGGER = 68786, // triggered by PERMAFROST. Used to check aura - SPELL_THROW_SARONITE = 68788, - SPELL_THUNDERING_STOMP = 68771, - SPELL_CHILLING_WAVE = 68778, - H_SPELL_CHILLING_WAVE = 70333, - SPELL_DEEP_FREEZE = 70381, - H_SPELL_DEEP_FREEZE = 72930, - SPELL_FORGE_MACE = 68785, - H_SPELL_FORGE_MACE = 70335, - SPELL_FORGE_BLADE = 68774, - H_SPELL_FORGE_BLADE = 70334, -}; - -enum eEnums -{ - EQUIP_ID_SWORD = 49345, - EQUIP_ID_MACE = 49344, - ACHIEV_DOESNT_GO_TO_ELEVEN = 4524, -}; - -struct boss_garfrostAI : public ScriptedAI -{ - boss_garfrostAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - bool phase2; - bool phase3; - bool bAchievement; - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - phase2 = false; - phase3 = false; - bAchievement = true; - - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_PERMAFROST); - - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_THROW_SARONITE, 45000); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& /*uiDamage*/) - { - if (HealthBelowPct(66) && !phase2) - { - phase2 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_BLADE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.ScheduleEvent(EVENT_CHILLINGWAVE, 10000); - } - - if (HealthBelowPct(33) && !phase3) - { - phase3 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_MACE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.CancelEvent(EVENT_CHILLINGWAVE); // cast only in phase 2. - events.ScheduleEvent(EVENT_DEEPFREEZE, 10000); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - { - if (Creature *pTyrannus = me->GetCreature(*me, pInstance->GetData64(DATA_TYRANNUS))) - DoScriptText(SAY_TYRANNUS_DEATH, pTyrannus); - - pInstance->SetData(DATA_GARFROST_EVENT, DONE); - if (IsHeroic() && bAchievement) - pInstance->DoCompleteAchievement(ACHIEV_DOESNT_GO_TO_ELEVEN); - } - } - - void SpellHitTarget(Unit* pTarget, const SpellEntry *spell) - { - if (spell->Id == SPELL_PERMAFROST_TRIGGER && bAchievement) - { - if (Aura *pAura = pTarget->GetAura(SPELL_PERMAFROST_TRIGGER)) - if (pAura->GetStackAmount() > 10) - bAchievement = false; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_THROW_SARONITE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_THROW_SARONITE); - events.RescheduleEvent(EVENT_THROW_SARONITE, 35000); - return; - case EVENT_DEEPFREEZE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DEEP_FREEZE); - events.RescheduleEvent(EVENT_DEEPFREEZE, 35000); - return; - case EVENT_CHILLINGWAVE: - DoCastAOE(SPELL_CHILLING_WAVE); - events.RescheduleEvent(EVENT_CHILLINGWAVE, 40000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_garfrost(Creature* pCreature) -{ - return new boss_garfrostAI (pCreature); -} - -void AddSC_boss_garfrost() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_garfrost"; - newscript->GetAI = &GetAI_boss_garfrost; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp b/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp deleted file mode 100644 index 8b8b03a3d4e..00000000000 --- a/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/* - * SDComment: Spell Explosive barrage is not working. - */ - -enum Spells -{ - SPELL_PURSUED = 68987, - SPELL_CONFUSION = 69029, - SPELL_EXPLOSIVE_BARRAGE = 69263, - SPELL_MIGHTY_KICK = 69021, - SPELL_POISON_NOVA = 68989, - H_SPELL_POISON_NOVA = 70434, - SPELL_SHADOW_BOLT = 69028, - SPELL_TOXIC_WASTE = 69024, - H_SPELL_TOXIC_WASTE = 70436, -}; - -enum Yells -{ - // Krick - SAY_KRICK_AGGRO = -1658010, - SAY_KRICK_SLAY_1 = -1658011, - SAY_KRICK_SLAY_2 = -1658012, - SAY_KRICK_BARRAGE_1 = -1658013, - SAY_KRICK_BARRAGE_2 = -1658014, - SAY_KRICK_POISON_NOVA = -1658015, - SAY_KRICK_CHASE_1 = -1658016, - SAY_KRICK_CHASE_2 = -1658017, - SAY_KRICK_CHASE_3 = -1658018, - - // Ick - SAY_ICK_POISON_NOVA = -1658020, - SAY_ICK_CHASE_1 = -1658021, - - // OUTRO - SAY_KRICK_OUTRO_1 = -1658030, - SAY_JAYNA_OUTRO_2 = -1658031, - SAY_SYLVANAS_OUTRO_2 = -1658032, - SAY_KRICK_OUTRO_3 = -1658033, - SAY_JAYNA_OUTRO_4 = -1658034, - SAY_SYLVANAS_OUTRO_4 = -1658035, - SAY_KRICK_OUTRO_5 = -1658036, - SAY_TYRANNUS_OUTRO_7 = -1658037, - SAY_KRICK_OUTRO_8 = -1658038, - SAY_TYRANNUS_OUTRO_9 = -1658039, - SAY_JAYNA_OUTRO_10 = -1658040, - SAY_SYLVANAS_OUTRO_10 = -1658041, -}; - -enum Events -{ - EVENT_NONE, - EVENT_PURSUE, - EVENT_MIGHTY_KICK, - EVENT_POISON_NOVA, - EVENT_EXPLOSIVE_BARRAGE, - EVENT_END_EXPLOSIVE_BARRAGE, - - // Krick - EVENT_SHADOW_BOLT, - EVENT_TOXIC_WASTE, - - // Krick OUTRO - EVENT_OUTRO_1, - EVENT_OUTRO_2, - EVENT_OUTRO_3, - EVENT_OUTRO_4, - EVENT_OUTRO_5, - EVENT_OUTRO_6, - EVENT_OUTRO_7, - EVENT_OUTRO_8, - EVENT_OUTRO_9, - EVENT_OUTRO_10, - EVENT_OUTRO_11, - EVENT_OUTRO_12, - EVENT_OUTRO_END, -}; - -enum KrickPhase -{ - PHASE_COMBAT, - PHASE_OUTRO, -}; - -enum Actions -{ - ACTION_OUTRO, -}; - -enum Misc -{ - SEAT_KRICK = 0, - - // events GCD. Shall not be 0. - GCD_1 = 1, -}; - -// Krick is the Gnome. -// Ick is the Mount -// Common Events are handled/triggered by Ick that "drive" Krick through DoAction. - -struct boss_ickAI : public ScriptedAI -{ - boss_ickAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, NOT_STARTED); - } - - Creature* GetKrick() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_KRICK) : 0); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, IN_PROGRESS); - - Creature* pKrick = GetKrick(); - if (!pKrick) - pKrick = me->SummonCreature(CREATURE_KRICK, *me, TEMPSUMMON_MANUAL_DESPAWN); - - if (pKrick) - DoScriptText(SAY_KRICK_AGGRO, pKrick); - - events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000, GCD_1); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 35000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - } - - void EnterEvadeMode() - { - me->GetMotionMaster()->Clear(); - ScriptedAI::EnterEvadeMode(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (Creature* pKrick = GetKrick()) - { - if (pKrick->AI()) - pKrick->AI()->DoAction(ACTION_OUTRO); - } - - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; - - if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) - { - EnterEvadeMode(); - return; - } - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch(events.ExecuteEvent()) - { - case EVENT_PURSUE: - if (Creature* pKrick = GetKrick()) - DoScriptText(RAND(SAY_KRICK_CHASE_1,SAY_KRICK_CHASE_2,SAY_KRICK_CHASE_3), pKrick); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->Attack(pTarget,false); - DoScriptText(SAY_ICK_CHASE_1, me, pTarget); - DoCast(pTarget, SPELL_PURSUED); - } - - DoCast(SPELL_CONFUSION); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - return; - - case EVENT_MIGHTY_KICK: - DoCast(me->getVictim(), SPELL_MIGHTY_KICK); - events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000, GCD_1); - return; - - case EVENT_POISON_NOVA: - if (Creature* pKrick = GetKrick()) - DoScriptText(SAY_KRICK_POISON_NOVA, pKrick); - - DoScriptText(SAY_ICK_POISON_NOVA, me); - DoCastAOE(SPELL_POISON_NOVA); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - return; - - case EVENT_TOXIC_WASTE: - DoCast(me->getVictim(), SPELL_TOXIC_WASTE); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - return; - - case EVENT_SHADOW_BOLT: - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - return; - - case EVENT_EXPLOSIVE_BARRAGE: - if (Creature *pKrick = GetKrick()) - { - DoScriptText(SAY_KRICK_BARRAGE_1, pKrick); - DoScriptText(SAY_KRICK_BARRAGE_2, pKrick); - } - - DoCastAOE(SPELL_EXPLOSIVE_BARRAGE); - me->GetMotionMaster()->MoveIdle(); - events.DelayEvents(20000, GCD_1); // 2 sec cast + 18 sec - events.ScheduleEvent(EVENT_END_EXPLOSIVE_BARRAGE, 20000); - return; - - case EVENT_END_EXPLOSIVE_BARRAGE: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 25000); - break; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_krickAI : public ScriptedAI -{ - boss_krickAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - KrickPhase phase; - uint64 uiNpcOutroDialog; - uint64 uiTyrannus; - - void Reset() - { - uiNpcOutroDialog = 0; - uiTyrannus = 0; - phase = PHASE_COMBAT; - - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_OFF); - } - - Creature* GetIck() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ICK) : 0); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_KRICK_SLAY_1,SAY_KRICK_SLAY_2), me); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - // if killed whatever the reason, it breaks the outro - uiDamage = 0; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_OUTRO: - { - Position pos; - if (Creature* pIck = GetIck()) - { - // TODO: tele on Ick then run some distance. - pIck->GetNearPosition(pos, 5.0f, 3.14); - me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0.0f); - } - me->SetVisibility(VISIBILITY_ON); - - Creature* pJainaOrSylvanas = me->GetCreature(*me, pInstance->GetData64(DATA_JAINA_SYLVANAS_1)); - if (pJainaOrSylvanas) { - Position pos; - me->GetNearPosition(pos, 5.0f, 0); - pJainaOrSylvanas->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), - pos.GetAngle(me->GetPositionX(), me->GetPositionY())); - } - else { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - pJainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - else - pJainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - } - - if (pJainaOrSylvanas) - { - pJainaOrSylvanas->SetOrientation(pJainaOrSylvanas->GetAngle(me->GetPositionX(), me->GetPositionY())); - me->SetOrientation(me->GetAngle(pJainaOrSylvanas->GetPositionX(), pJainaOrSylvanas->GetPositionY())); - uiNpcOutroDialog = pJainaOrSylvanas->GetGUID(); - } - - phase = PHASE_OUTRO; - events.Reset(); - events.ScheduleEvent(EVENT_OUTRO_1, 1000); - break; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_OUTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_OUTRO_1: - { - DoScriptText(SAY_KRICK_OUTRO_1, me); - events.ScheduleEvent(EVENT_OUTRO_2, 14000); - break; - } - case EVENT_OUTRO_2: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_2, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_2, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_3, 8500); - break; - } - case EVENT_OUTRO_3: - DoScriptText(SAY_KRICK_OUTRO_3, me); - events.ScheduleEvent(EVENT_OUTRO_4, 12000); - break; - case EVENT_OUTRO_4: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_4, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_4, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_5, 8000); - break; - } - case EVENT_OUTRO_5: - DoScriptText(SAY_KRICK_OUTRO_5, me); - events.ScheduleEvent(EVENT_OUTRO_6, 4000); - break; - case EVENT_OUTRO_6: - // TODO spawn Tyrannus at some distance and MovePoint near-by (flying on rimefang) - // store uiTyrannus - // Adjust timer so tyrannus has time to come - uiTyrannus = (pInstance ? pInstance->GetData64(DATA_TYRANNUS) : 0); - events.ScheduleEvent(EVENT_OUTRO_7, 1); - break; - case EVENT_OUTRO_7: - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_7, pTyrannus); - events.ScheduleEvent(EVENT_OUTRO_8, 7000); - break; - case EVENT_OUTRO_8: - DoScriptText(SAY_KRICK_OUTRO_8, me); - // TODO: Tyrannus starts killing Krick. - // there shall be some visual spell effect - events.ScheduleEvent(EVENT_OUTRO_9, 6000); - break; - case EVENT_OUTRO_9: - // tyrannus kills krick - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetHealth(0); - - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_9, pTyrannus); - - events.ScheduleEvent(EVENT_OUTRO_10, 12000); - break; - case EVENT_OUTRO_10: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_10, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_10, pNpcDialog); - } - - // End of OUTRO. for now... - events.ScheduleEvent(EVENT_OUTRO_END, 8000); - break; - } - case EVENT_OUTRO_END: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - pNpcDialog->DisappearAndDie(); - - me->DisappearAndDie(); - break; - } - } - return; - } - } -}; - -CreatureAI* GetAI_boss_ick(Creature* pCreature) -{ - return new boss_ickAI(pCreature); -} - -CreatureAI* GetAI_boss_krick(Creature* pCreature) -{ - return new boss_krickAI(pCreature); -} - -void AddSC_boss_ick() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ick"; - newscript->GetAI = &GetAI_boss_ick; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_krick"; - newscript->GetAI = &GetAI_boss_krick; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp deleted file mode 100644 index 55ffa0b4e4b..00000000000 --- a/src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/* - * SDComment: TODO: - * - implement aura for spell Overlord Brand. - * - Intro/Outro - * - improve script of Rimefang - */ - -enum Yells -{ - SAY_AMBUSH_1 = -1658050, - SAY_AMBUSH_2 = -1658051, - SAY_GAUNTLET_START = -1658052, - SAY_INTRO_1 = -1658053, - SAY_INTRO_2 = -1658054, - - SAY_AGGRO = -1658055, - SAY_SLAY_1 = -1658056, - SAY_SLAY_2 = -1658057, - SAY_DEATH = -1658058, - SAY_MARK_RIMEFANG_1 = -1658059, - SAY_MARK_RIMEFANG_2 = -1658060, - SAY_DARK_MIGHT_1 = -1658061, - SAY_DARK_MIGHT_2 = -1658062, - - SAY_GORKUN_OUTRO_1 = -1658063, - SAY_GORKUN_OUTRO_2 = -1658064, - SAY_JAYNA_OUTRO_3 = -1658065, - SAY_SYLVANAS_OUTRO_3 = -1658066, - SAY_JAYNA_OUTRO_4 = -1658067, - SAY_SYLVANAS_OUTRO_4 = -1658068, - SAY_JAYNA_OUTRO_5 = -1658069, -}; - -enum Spells -{ - SPELL_FORCEFUL_SMASH = 69155, - H_SPELL_FORCEFUL_SMASH = 69627, - SPELL_OVERLORDS_BRAND = 69172, - SPELL_DARK_MIGHT = 69167, - H_SPELL_DARK_MIGHT = 69629, - SPELL_HOARFROST = 69246, - SPELL_MARK_OF_RIMEFANG = 69275, - SPELL_ICY_BLAST = 69233, - H_SPELL_ICY_BLAST = 69646, - SPELL_ICY_BLAST_2 = 69238, - H_SPELL_ICY_BLAST_2 = 69628, -}; - -enum Events -{ - EVENT_NONE, - EVENT_FORCEFUL_SMASH, - EVENT_OVERLORDS_BRAND, - EVENT_DARK_MIGHT, - - // Rimefang - EVENT_MARK_OF_RIMEFANG, - EVENT_HOARFROST, - EVENT_ICY_BLAST, - EVENT_ICY_BLAST_2, -}; - -enum Misc -{ - SEAT_TYRANNUS = 0 -}; - -struct boss_tyrannusAI : public ScriptedAI -{ - boss_tyrannusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, NOT_STARTED); - } - - Creature* GetRimefang() - { - return me->GetCreature(*me, pInstance->GetData64(DATA_RIMEFANG)); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - me->ExitVehicle(); - - // restore health if any damage done during intro - me->SetHealth(me->GetMaxHealth()); - - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 35000); - events.ScheduleEvent(EVENT_DARK_MIGHT, 40000); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_TYRANNUS_EVENT, DONE); - if (Creature* pRimefang = GetRimefang()) - pRimefang->ForcedDespawn(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FORCEFUL_SMASH: - DoCast(me->getVictim(), SPELL_FORCEFUL_SMASH); - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - return; - case EVENT_OVERLORDS_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_OVERLORDS_BRAND); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 45000); - return; - case EVENT_DARK_MIGHT: - DoScriptText(SAY_DARK_MIGHT_1, me); - DoScriptText(SAY_DARK_MIGHT_2, me); - DoCast(me, SPELL_DARK_MIGHT); - events.ScheduleEvent(EVENT_DARK_MIGHT, 60000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_rimefangAI : public ScriptedAI -{ - boss_rimefangAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 25000); - events.ScheduleEvent(EVENT_ICY_BLAST, 35000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_MARK_OF_RIMEFANG: - DoScriptText(SAY_MARK_RIMEFANG_1, me); - DoScriptText(SAY_MARK_RIMEFANG_2, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_MARK_OF_RIMEFANG); - events.ScheduleEvent(EVENT_HOARFROST, 5000); - return; - case EVENT_HOARFROST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HOARFROST); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 20000); - return; - case EVENT_ICY_BLAST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ICY_BLAST); - events.ScheduleEvent(EVENT_ICY_BLAST_2, 5000); - return; - case EVENT_ICY_BLAST_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget->getVictim(), SPELL_ICY_BLAST_2); - events.ScheduleEvent(EVENT_ICY_BLAST, 30000); - return; - } - } - } -}; - -CreatureAI* GetAI_boss_tyrannus(Creature* pCreature) -{ - return new boss_tyrannusAI(pCreature); -} - -CreatureAI* GetAI_boss_rimefang(Creature* pCreature) -{ - return new boss_rimefangAI(pCreature); -} - -void AddSC_boss_tyrannus() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_tyrannus"; - newscript->GetAI = &GetAI_boss_tyrannus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="boss_rimefang"; - newscript->GetAI = &GetAI_boss_rimefang; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp b/src/server/scripts/northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp deleted file mode 100644 index 8512eca24c1..00000000000 --- a/src/server/scripts/northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -#define MAX_ENCOUNTER 3 - -/* Pit of Saron encounters: -0- Forgemaster Garfrost -1- Krick and Ick -2- Scourgelord Tyrannus -*/ - -struct instance_pit_of_saron : public ScriptedInstance -{ - instance_pit_of_saron(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiKrick; - uint64 uiIck; - uint64 uiGarfrost; - uint64 uiTyrannus; - uint64 uiRimefang; - - uint64 uiJainaOrSylvanas1; - uint64 uiJainaOrSylvanas2; - - uint32 uiTeamInInstance; - uint32 uiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - - uiGarfrost = 0; - uiKrick = 0; - uiIck = 0; - uiTyrannus = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - } - - switch(pCreature->GetEntry()) - { - case CREATURE_KRICK: - uiKrick = pCreature->GetGUID(); - break; - - case CREATURE_ICK: - uiIck = pCreature->GetGUID(); - break; - - case CREATURE_GARFROST: - uiGarfrost = pCreature->GetGUID(); - break; - - case CREATURE_TYRANNUS: - uiTyrannus = pCreature->GetGUID(); - break; - - case CREATURE_RIMEFANG: - uiRimefang = pCreature->GetGUID(); - break; - - case NPC_SYLVANAS_PART1: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); - uiJainaOrSylvanas1 = pCreature->GetGUID(); - break; - case NPC_SYLVANAS_PART2: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); - uiJainaOrSylvanas2 = pCreature->GetGUID(); - break; - case NPC_KILARA: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_ELANDRA, ALLIANCE); - break; - case NPC_KORALEN: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_KORLAEN, ALLIANCE); - break; - case NPC_CHAMPION_1_HORDE: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_2_HORDE: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_GARFROST: return uiGarfrost; - case DATA_KRICK: return uiKrick; - case DATA_ICK: return uiIck; - case DATA_TYRANNUS: return uiTyrannus; - case DATA_RIMEFANG: return uiRimefang; - - case DATA_JAINA_SYLVANAS_1: return uiJainaOrSylvanas1; - case DATA_JAINA_SYLVANAS_2: return uiJainaOrSylvanas2; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_GARFROST_EVENT: - uiEncounter[0] = data; - break; - case DATA_TYRANNUS_EVENT: - uiEncounter[1] = data; - break; - case DATA_KRICKANDICK_EVENT: - uiEncounter[2] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_GARFROST_EVENT: return uiEncounter[0]; - case DATA_TYRANNUS_EVENT: return uiEncounter[1]; - case DATA_KRICKANDICK_EVENT: return uiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::string str_data; - - std::ostringstream saveStream; - saveStream << "P S " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'P' && dataHead2 == 'S') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_pit_of_saron(Map* pMap) -{ - return new instance_pit_of_saron(pMap); -} - -void AddSC_instance_pit_of_saron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_pit_of_saron"; - newscript->GetInstanceData = &GetInstanceData_instance_pit_of_saron; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp b/src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp deleted file mode 100644 index bc53efc7033..00000000000 --- a/src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp +++ /dev/null @@ -1,1101 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/***************************************SPELLS*************************************/ -// Ymirjar Wrathbringer -#define SPELL_BLIGHT DUNGEON_MODE(69603,70285) - -//Ymirjar Skycaller -#define SPELL_FROSTBLADE 70291 -#define SPELL_GLACIAL_STRIKE 70292 - -//Ymirjar Flamebearer -#define SPELL_FIREBALL DUNGEON_MODE(69583,70282) -#define SPELL_HELLFIRE DUNGEON_MODE(69586,70283) -#define SPELL_TACTICAL_BLINK 69584 - -//Ymirjar Deathbringer -#define SPELL_EMPOWERED_SHADOW_BOLT DUNGEON_MODE(69528,70281) -#define SPELL_SUMMON_UNDEAD 69516 - -//Wrathbone Laborer -#define SPELL_BLINDING_DIRT 70302 -#define SPELL_PUNCTURE_WOUND DUNGEON_MODE(70278,70279) -#define SPELL_SHOVELLED DUNGEON_MODE(69572,70280) - -//Wrathbone Coldwraith -#define SPELL_FREEZING_CIRCLE DUNGEON_MODE(69574,70276) -#define SPELL_FROSTBOLT DUNGEON_MODE(69573,70277) - -//Stonespine Gargoyle -#define SPELL_GARGOYLE_STRIKE DUNGEON_MODE(69520,70275) -#define SPELL_STONEFORM 69575 - -// Plagueborn Horror -#define SPELL_BLIGHT_BOMB 69582 -#define SPELL_PUSTULANT_FLESH DUNGEON_MODE(69581,70273) -#define SPELL_TOXIC_WASTE 70274 - -//Iceborn Proto-Drake -#define SPELL_FROST_BREATH DUNGEON_MODE(69527,70272) - -//Hungering Ghoul -#define SPELL_DEVOUR_FLESH 70393 - -//Fallen Warrior -#define SPELL_ARCING_SLICE 69579 -#define SPELL_DEMORALIZING_SHOUT 61044 -#define SPELL_SHIELD_BLOCK 69580 - -//Deathwhisper Torturer -#define SPELL_BLACK_BRAND 70392 -#define SPELL_CURSE_OF_AGONY 70391 - -//Deathwhisper Shadowcaster -#define SPELL_SHADOW_BOLT DUNGEON_MODE(70386,70387) - -//Deathwhisper Necrolyte -#define SPELL_CONVERSION_BEAM DUNGEON_MODE(69578,70269) -#define SPELL_SHADOW_BOLT_2 DUNGEON_MODE(69577,70270) - -//Wrathbone Sorcerer -#define SPELL_SHADOW_BOLT_3 DUNGEON_MODE(70386,70387) - -//Geist Ambusher -#define SPELL_LEAPING_FACE_MAUL DUNGEON_MODE(69504,70271) - -/****************************************EVENTS************************************/ -enum eEvents -{ - EVENT_NONE, - - // Ymirjar Wrathbringer - EVENT_BLIGHT, - - // Ymirjar Skycaller - EVENT_FROSTBLADE, - EVENT_GLACIAL_STRIKE, - - // Ymirjar Flamebearer - EVENT_FIREBALL, - EVENT_HELLFIRE, - EVENT_TACTICAL_BLINK, - - //Ymirjar Deathbringer - EVENT_EMPOWERED_SHADOW_BOLT, - EVENT_SUMMON_UNDEAD, - - //Wrathbone Laborer - EVENT_BLINDING_DIRT, - EVENT_PUNCTURE_WOUND, - EVENT_SHOVELLED, - - //Wrathbone Coldwraith - EVENT_FREEZING_CIRCLE, - EVENT_FROSTBOLT, - - //Stonespine Gargoyle - EVENT_GARGOYLE_STRIKE, - EVENT_STONEFORM, - - //Plagueborn Horror - EVENT_BLIGHT_BOMB, - EVENT_PUSTULANT_FLESH, - EVENT_TOXIC_WASTE, - - //Iceborn Proto-Drake - EVENT_FROST_BREATH, - - //Hungering Ghoul - EVENT_DEVOUR_FLESH, - - //Fallen Warrior - EVENT_ARCING_SLICE, - EVENT_DEMORALIZING_SHOUT, - EVENT_SHIELD_BLOCK, - - //Deathwhisper Torturer - EVENT_BLACK_BRAND, - EVENT_CURSE_OF_AGONY, - - //Deathwhisper Shadowcaster - EVENT_SHADOW_BOLT, - - //Deathwhisper Necrolyte - EVENT_CONVERSION_BEAM, - EVENT_SHADOW_BOLT_2, - - EVENT_SHADOW_BOLT_3, - - //Geist Ambusher - EVENT_LEAPING_FACE_MAUL, -}; - -/****************************************AI****************************************/ -struct mob_ymirjar_wrathbringerAI : public ScriptedAI -{ - mob_ymirjar_wrathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT, 7000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLIGHT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLIGHT); - events.RescheduleEvent(EVENT_BLIGHT, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_skyCallerAI: public ScriptedAI -{ - mob_ymirjar_skyCallerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROSTBLADE, 1); - events.ScheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_GLACIAL_STRIKE: - DoCast(me->getVictim(), SPELL_GLACIAL_STRIKE); - events.RescheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - return; - case EVENT_FROSTBLADE: - DoCast(me, SPELL_FROSTBLADE); - events.CancelEvent(EVENT_FROSTBLADE); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_flamebearerAI: public ScriptedAI -{ - mob_ymirjar_flamebearerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FIREBALL, 4000); - events.ScheduleEvent(EVENT_HELLFIRE, 8000); - events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FIREBALL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FIREBALL); - events.RescheduleEvent(EVENT_FIREBALL, 5000); - return; - case EVENT_HELLFIRE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HELLFIRE); - events.RescheduleEvent(EVENT_HELLFIRE, 10000); - return; - case EVENT_TACTICAL_BLINK: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_TACTICAL_BLINK); - events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_deathbringerAI: public ScriptedAI -{ - mob_ymirjar_deathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_EMPOWERED_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_EMPOWERED_SHADOW_BOLT); - events.RescheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_laborerAI: public ScriptedAI -{ - mob_wrathbone_laborerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); - events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - events.ScheduleEvent(EVENT_SHOVELLED, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLINDING_DIRT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLINDING_DIRT); - events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); - return; - case EVENT_PUNCTURE_WOUND: - DoCast(me->getVictim(), SPELL_PUNCTURE_WOUND); - events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - return; - case EVENT_SHOVELLED: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHOVELLED); - events.RescheduleEvent(EVENT_SHOVELLED, 7000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_coldwraithAI: public ScriptedAI -{ - mob_wrathbone_coldwraithAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - events.ScheduleEvent(EVENT_FROSTBOLT, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FREEZING_CIRCLE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FREEZING_CIRCLE); - events.RescheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - return; - case EVENT_FROSTBOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FROSTBOLT); - events.RescheduleEvent(EVENT_FROSTBOLT, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_stonespine_gargoyleAI: public ScriptedAI -{ - mob_stonespine_gargoyleAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_GARGOYLE_STRIKE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_GARGOYLE_STRIKE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_GARGOYLE_STRIKE); - events.RescheduleEvent(EVENT_GARGOYLE_STRIKE, 6000); - return; - case EVENT_STONEFORM: - if (HealthBelowPct(10)) - DoCast(me, SPELL_STONEFORM); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_plagueborn_horrorAI: public ScriptedAI -{ - mob_plagueborn_horrorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT_BOMB, 999999); - events.ScheduleEvent(EVENT_PUSTULANT_FLESH, 5000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLIGHT_BOMB: - if (HealthBelowPct(15)) - DoCast(me, SPELL_BLIGHT_BOMB); - return; - case EVENT_PUSTULANT_FLESH: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_PUSTULANT_FLESH); - events.RescheduleEvent(EVENT_PUSTULANT_FLESH, 10000); - return; - case EVENT_TOXIC_WASTE: - DoCast(me, SPELL_TOXIC_WASTE); - events.RescheduleEvent(EVENT_TOXIC_WASTE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_iceborn_protodrakeAI: public ScriptedAI -{ - mob_iceborn_protodrakeAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_BREATH, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROST_BREATH: - DoCast(me->getVictim(), SPELL_FROST_BREATH); - events.RescheduleEvent(EVENT_FROST_BREATH, 10000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_hungering_ghoulAI: public ScriptedAI -{ - mob_hungering_ghoulAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_DEVOUR_FLESH, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_DEVOUR_FLESH: - DoCast(me->getVictim(), SPELL_DEVOUR_FLESH); - events.RescheduleEvent(EVENT_DEVOUR_FLESH, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_fallen_warriorAI: public ScriptedAI -{ - mob_fallen_warriorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_ARCING_SLICE, 8000); - events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - events.ScheduleEvent(EVENT_SHIELD_BLOCK, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ARCING_SLICE: - DoCast(me->getVictim(), SPELL_ARCING_SLICE); - events.RescheduleEvent(EVENT_ARCING_SLICE, 10000); - return; - case EVENT_DEMORALIZING_SHOUT: - DoCast(me, SPELL_DEMORALIZING_SHOUT); - events.RescheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - return; - case EVENT_SHIELD_BLOCK: - DoCast(me->getVictim(), SPELL_SHIELD_BLOCK); - events.RescheduleEvent(EVENT_SHIELD_BLOCK, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_torturerAI: public ScriptedAI -{ - mob_deathwhisper_torturerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLACK_BRAND, 10000); - events.ScheduleEvent(EVENT_CURSE_OF_AGONY, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLACK_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLACK_BRAND); - events.RescheduleEvent(EVENT_BLACK_BRAND, 10000); - return; - case EVENT_CURSE_OF_AGONY: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CURSE_OF_AGONY); - events.RescheduleEvent(EVENT_CURSE_OF_AGONY, 13000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_shadowcasterAI: public ScriptedAI -{ - mob_deathwhisper_shadowcasterAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_necrolyteAI: public ScriptedAI -{ - mob_deathwhisper_necrolyteAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_CONVERSION_BEAM, 12000); - events.ScheduleEvent(EVENT_SHADOW_BOLT_2, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CONVERSION_BEAM: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CONVERSION_BEAM); - events.RescheduleEvent(EVENT_CONVERSION_BEAM, 12000); - return; - case EVENT_SHADOW_BOLT_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_2); - events.RescheduleEvent(EVENT_SHADOW_BOLT_2, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_sorcererAI: public ScriptedAI -{ - mob_wrathbone_sorcererAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT_3, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_BOLT_3: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_3); - events.RescheduleEvent(EVENT_SHADOW_BOLT_3, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_geist_ambusherAI: public ScriptedAI -{ - mob_geist_ambusherAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - //Only here so when I figure out how to make it cast on an NPC i can do that. - events.ScheduleEvent(EVENT_LEAPING_FACE_MAUL, 99999); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - //Should only be used on NPCs - case EVENT_LEAPING_FACE_MAUL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_LEAPING_FACE_MAUL); - events.CancelEvent(EVENT_LEAPING_FACE_MAUL); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_ymirjar_wrathbringerAI(Creature* pCreature) -{ - return new mob_ymirjar_wrathbringerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_skyCallerAI(Creature* pCreature) -{ - return new mob_ymirjar_skyCallerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_flamebearerAI(Creature* pCreature) -{ - return new mob_ymirjar_flamebearerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_deathbringerAI(Creature* pCreature) -{ - return new mob_ymirjar_deathbringerAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_laborerAI(Creature* pCreature) -{ - return new mob_wrathbone_laborerAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_coldwraithAI(Creature* pCreature) -{ - return new mob_wrathbone_coldwraithAI(pCreature); -} - -CreatureAI* GetAI_mob_stonespine_gargoyleAI(Creature* pCreature) -{ - return new mob_stonespine_gargoyleAI(pCreature); -} - -CreatureAI* GetAI_mob_plagueborn_horrorAI(Creature* pCreature) -{ - return new mob_plagueborn_horrorAI(pCreature); -} - -CreatureAI* GetAI_mob_iceborn_protodrakeAI(Creature* pCreature) -{ - return new mob_iceborn_protodrakeAI(pCreature); -} - -CreatureAI* GetAI_mob_hungering_ghoulAI(Creature* pCreature) -{ - return new mob_hungering_ghoulAI(pCreature); -} - -CreatureAI* GetAI_mob_fallen_warriorAI(Creature* pCreature) -{ - return new mob_fallen_warriorAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_torturerAI(Creature* pCreature) -{ - return new mob_deathwhisper_torturerAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_shadowcasterAI(Creature* pCreature) -{ - return new mob_deathwhisper_shadowcasterAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_necrolyteAI(Creature* pCreature) -{ - return new mob_deathwhisper_necrolyteAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_sorcererAI(Creature* pCreature) -{ - return new mob_wrathbone_sorcererAI(pCreature); -} - -CreatureAI* GetAI_mob_geist_ambusherAI(Creature* pCreature) -{ - return new mob_geist_ambusherAI(pCreature); -} - -void AddSC_pit_of_saron() -{ - Script *newscript; - newscript = new Script; - newscript->Name="mob_ymirjar_wrathbringer"; - newscript->GetAI = &GetAI_mob_ymirjar_wrathbringerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_skycaller"; - newscript->GetAI = &GetAI_mob_ymirjar_skyCallerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_flamebearer"; - newscript->GetAI = &GetAI_mob_ymirjar_flamebearerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_deathbringer"; - newscript->GetAI = &GetAI_mob_ymirjar_deathbringerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_laborer"; - newscript->GetAI = &GetAI_mob_wrathbone_laborerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_coldwraith"; - newscript->GetAI = &GetAI_mob_wrathbone_coldwraithAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_stonespine_gargoyle"; - newscript->GetAI = &GetAI_mob_stonespine_gargoyleAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_plagueborn_horror"; - newscript->GetAI = &GetAI_mob_plagueborn_horrorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_iceborn_protodrake"; - newscript->GetAI = &GetAI_mob_iceborn_protodrakeAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_hungering_ghoul"; - newscript->GetAI = &GetAI_mob_hungering_ghoulAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_fallen_warrior"; - newscript->GetAI = &GetAI_mob_fallen_warriorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_torturer"; - newscript->GetAI = &GetAI_mob_deathwhisper_torturerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_shadowcaster"; - newscript->GetAI = &GetAI_mob_deathwhisper_shadowcasterAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_necrolyte"; - newscript->GetAI = &GetAI_mob_deathwhisper_necrolyteAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_sorcerer"; - newscript->GetAI = &GetAI_mob_wrathbone_sorcererAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_geist_ambusher"; - newscript->GetAI = &GetAI_mob_geist_ambusherAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.h b/src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.h deleted file mode 100644 index 4a221d17518..00000000000 --- a/src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_PIT_OF_SARON_H -#define DEF_PIT_OF_SARON_H - -enum Data -{ - DATA_GARFROST_EVENT, - DATA_KRICKANDICK_EVENT, - DATA_TYRANNUS_EVENT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_GARFROST, - DATA_KRICK, - DATA_ICK, - DATA_TYRANNUS, - DATA_RIMEFANG, - - DATA_JAINA_SYLVANAS_1, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. - DATA_JAINA_SYLVANAS_2, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. -}; - -enum Creatures -{ - CREATURE_GARFROST = 36494, - CREATURE_KRICK = 36477, - CREATURE_ICK = 36476, - CREATURE_TYRANNUS = 36658, - CREATURE_RIMEFANG = 36661, - - NPC_SYLVANAS_PART1 = 36990, - NPC_SYLVANAS_PART2 = 38189, - NPC_JAINA_PART1 = 36993, - NPC_JAINA_PART2 = 38188, - NPC_KILARA = 37583, - NPC_ELANDRA = 37774, - NPC_KORALEN = 37779, - NPC_KORLAEN = 37582, - NPC_CHAMPION_1_HORDE = 37584, - NPC_CHAMPION_2_HORDE = 37587, - NPC_CHAMPION_3_HORDE = 37588, - NPC_CHAMPION_1_ALLIANCE = 37496, - NPC_CHAMPION_2_ALLIANCE = 37497, -}; - -#endif diff --git a/src/server/scripts/northrend/grizzly_hills.cpp b/src/server/scripts/northrend/grizzly_hills.cpp deleted file mode 100644 index 4b6d65a9764..00000000000 --- a/src/server/scripts/northrend/grizzly_hills.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Grizzly_Hills -SD%Complete: 80 -SDComment: Quest support: 12231, 12247 -SDCategory: Grizzly Hills -EndScriptData */ - -/* ContentData -npc_orsonn_and_kodian -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -#define GOSSIP_ITEM1 "You're free to go Orsonn, but first tell me what's wrong with the furbolg." -#define GOSSIP_ITEM2 "What happened then?" -#define GOSSIP_ITEM3 "Thank you, Son of Ursoc. I'll see what can be done." -#define GOSSIP_ITEM4 "Who was this stranger?" -#define GOSSIP_ITEM5 "Thank you, Kodian. I'll do what I can." - -enum eEnums -{ - GOSSIP_TEXTID_ORSONN1 = 12793, - GOSSIP_TEXTID_ORSONN2 = 12794, - GOSSIP_TEXTID_ORSONN3 = 12796, - - GOSSIP_TEXTID_KODIAN1 = 12797, - GOSSIP_TEXTID_KODIAN2 = 12798, - - NPC_ORSONN = 27274, - NPC_KODIAN = 27275, - - //trigger creatures - NPC_ORSONN_CREDIT = 27322, - NPC_KODIAN_CREDIT = 27321, - - QUEST_CHILDREN_OF_URSOC = 12247, - QUEST_THE_BEAR_GODS_OFFSPRING = 12231 -}; - -bool GossipHello_npc_orsonn_and_kodian(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_CHILDREN_OF_URSOC) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_THE_BEAR_GODS_OFFSPRING) == QUEST_STATUS_INCOMPLETE) - { - switch(pCreature->GetEntry()) - { - case NPC_ORSONN: - if (!pPlayer->GetReqKillOrCastCurrentCount(QUEST_CHILDREN_OF_URSOC, NPC_ORSONN_CREDIT) || !pPlayer->GetReqKillOrCastCurrentCount(QUEST_THE_BEAR_GODS_OFFSPRING, NPC_ORSONN_CREDIT)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN1, pCreature->GetGUID()); - return true; - } - break; - case NPC_KODIAN: - if (!pPlayer->GetReqKillOrCastCurrentCount(QUEST_CHILDREN_OF_URSOC, NPC_KODIAN_CREDIT) || !pPlayer->GetReqKillOrCastCurrentCount(QUEST_THE_BEAR_GODS_OFFSPRING, NPC_KODIAN_CREDIT)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_KODIAN1, pCreature->GetGUID()); - return true; - } - break; - } - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_orsonn_and_kodian(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ORSONN3, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->TalkedToCreature(NPC_ORSONN_CREDIT, pCreature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_KODIAN2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->TalkedToCreature(NPC_KODIAN_CREDIT, pCreature->GetGUID()); - break; - } - - return true; -} - -/*###### -## Quest 12027: Mr. Floppy's Perilous Adventure -######*/ - -enum eFloppy -{ - NPC_MRFLOPPY = 26589, - NPC_HUNGRY_WORG = 26586, - NPC_RAVENOUS_WORG = 26590, //RWORG - NPC_EMILY = 26588, - - QUEST_PERILOUS_ADVENTURE = 12027, - - SPELL_MRFLOPPY = 47184, //vehicle aura - - SAY_WORGHAGGRO1 = -1800001, //Um... I think one of those wolves is back... - SAY_WORGHAGGRO2 = -1800002, //He's going for Mr. Floppy! - SAY_WORGRAGGRO3 = -1800003, //Oh, no! Look, it's another wolf, and it's a biiiiiig one! - SAY_WORGRAGGRO4 = -1800004, //He's gonna eat Mr. Floppy! You gotta help Mr. Floppy! You just gotta! - SAY_RANDOMAGGRO = -1800005, //There's a big meanie attacking Mr. Floppy! Help! - SAY_VICTORY1 = -1800006, //Let's get out of here before more wolves find us! - SAY_VICTORY2 = -1800007, //Don't go toward the light, Mr. Floppy! - SAY_VICTORY3 = -1800008, //Mr. Floppy, you're ok! Thank you so much for saving Mr. Floppy! - SAY_VICTORY4 = -1800009, //I think I see the camp! We're almost home, Mr. Floppy! Let's go! - TEXT_EMOTE_WP1 = -1800010, //Mr. Floppy revives - TEXT_EMOTE_AGGRO = -1800011, //The Ravenous Worg chomps down on Mr. Floppy - SAY_QUEST_ACCEPT = -1800012, //Are you ready, Mr. Floppy? Stay close to me and watch out for those wolves! - SAY_QUEST_COMPLETE = -1800013 //Thank you for helping me get back to the camp. Go tell Walter that I'm safe now! -}; - -//emily -struct npc_emilyAI : public npc_escortAI -{ - npc_emilyAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - uint32 m_uiChatTimer; - - uint64 RWORGGUID; - uint64 MrfloppyGUID; - - bool Completed; - - void JustSummoned(Creature* pSummoned) - { - if (Creature* Mrfloppy = GetClosestCreatureWithEntry(me, NPC_MRFLOPPY, 50.0f)) - pSummoned->AI()->AttackStart(Mrfloppy); - else - pSummoned->AI()->AttackStart(me->getVictim()); - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - if (!pPlayer) - return; - switch (i) - { - case 9: - if (Creature *Mrfloppy = GetClosestCreatureWithEntry(me, NPC_MRFLOPPY, 100.0f)) - MrfloppyGUID = Mrfloppy->GetGUID(); - break; - case 10: - if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) - { - DoScriptText(SAY_WORGHAGGRO1, me); - me->SummonCreature(NPC_HUNGRY_WORG,me->GetPositionX()+5,me->GetPositionY()+2,me->GetPositionZ()+1,3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); - } - break; - case 11: - if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) - Mrfloppy->GetMotionMaster()->MoveFollow(me, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - break; - case 17: - if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) - Mrfloppy->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); - DoScriptText(SAY_WORGRAGGRO3, me); - if (Creature *RWORG = me->SummonCreature(NPC_RAVENOUS_WORG,me->GetPositionX()+10,me->GetPositionY()+8,me->GetPositionZ()+2,3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000)) - { - RWORG->setFaction(35); - RWORGGUID = RWORG->GetGUID(); - } - break; - case 18: - if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) - { - if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) - RWORG->GetMotionMaster()->MovePoint(0, Mrfloppy->GetPositionX(), Mrfloppy->GetPositionY(), Mrfloppy->GetPositionZ()); - DoCast(Mrfloppy,SPELL_MRFLOPPY); - } - break; - case 19: - if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) - { - if (Mrfloppy->HasAura(SPELL_MRFLOPPY, 0)) - { - if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) - Mrfloppy->EnterVehicle(RWORG); - } - } - break; - case 20: - if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) - RWORG->HandleEmoteCommand(34); - break; - case 21: - if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) - { - if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) - { - RWORG->Kill(Mrfloppy); - Mrfloppy->ExitVehicle(); - RWORG->setFaction(14); - RWORG->GetMotionMaster()->MovePoint(0, RWORG->GetPositionX()+10,RWORG->GetPositionY()+80,RWORG->GetPositionZ()); - DoScriptText(SAY_VICTORY2, me); - } - } - break; - case 22: - if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) - { - if (Mrfloppy->isDead()) - { - if (Creature *RWORG = Unit::GetCreature(*me, RWORGGUID)) - RWORG->DisappearAndDie(); - me->GetMotionMaster()->MovePoint(0, Mrfloppy->GetPositionX(), Mrfloppy->GetPositionY(), Mrfloppy->GetPositionZ()); - Mrfloppy->setDeathState(ALIVE); - Mrfloppy->GetMotionMaster()->MoveFollow(me, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - DoScriptText(SAY_VICTORY3, me); - } - } - break; - case 24: - if (pPlayer) - { - Completed = true; - pPlayer->GroupEventHappens(QUEST_PERILOUS_ADVENTURE, me); - DoScriptText(SAY_QUEST_COMPLETE, me, pPlayer); - } - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - break; - case 25: - DoScriptText(SAY_VICTORY4, me); - break; - case 27: - me->DisappearAndDie(); - if (Creature *Mrfloppy = Unit::GetCreature(*me, MrfloppyGUID)) - Mrfloppy->DisappearAndDie(); - break; - } - } - - void EnterCombat(Unit* /*Who*/) - { - DoScriptText(SAY_RANDOMAGGRO, me); - } - - void Reset() - { - m_uiChatTimer = 4000; - MrfloppyGUID = 0; - RWORGGUID = 0; - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (m_uiChatTimer <= uiDiff) - { - m_uiChatTimer = 12000; - } - else - m_uiChatTimer -= uiDiff; - } - } -}; - -bool QuestAccept_npc_emily(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_PERILOUS_ADVENTURE) - { - DoScriptText(SAY_QUEST_ACCEPT, pCreature); - if (Creature* Mrfloppy = GetClosestCreatureWithEntry(pCreature, NPC_MRFLOPPY, 180.0f)) - { - Mrfloppy->GetMotionMaster()->MoveFollow(pCreature, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - } - - if (npc_escortAI* pEscortAI = CAST_AI(npc_emilyAI, (pCreature->AI()))) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - } - return true; -} - -CreatureAI* GetAI_npc_emily(Creature* pCreature) -{ - return new npc_emilyAI(pCreature); -} - -//mrfloppy - -struct npc_mrfloppyAI : public ScriptedAI -{ - npc_mrfloppyAI(Creature *c) : ScriptedAI(c) {} - - uint64 EmilyGUID; - uint64 RWORGGUID; - uint64 HWORGGUID; - - void Reset() {} - - void EnterCombat(Unit* Who) - { - if (Creature* Emily = GetClosestCreatureWithEntry(me, NPC_EMILY, 50.0f)) - { - switch(Who->GetEntry()) - { - case NPC_HUNGRY_WORG: - DoScriptText(SAY_WORGHAGGRO2, Emily); - break; - case NPC_RAVENOUS_WORG: - DoScriptText(SAY_WORGRAGGRO4, Emily); - break; - default: - DoScriptText(SAY_RANDOMAGGRO, Emily); - } - } - } - - void EnterEvadeMode() {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_npc_mrfloppy(Creature* pCreature) -{ - return new npc_mrfloppyAI(pCreature); -} - -// Outhouse Bunny - -enum eOuthouseBunny -{ - SPELL_OUTHOUSE_GROANS = 48382, - SPELL_CAMERA_SHAKE = 47533, - SPELL_DUST_FIELD = 48329 -}; - -enum eSounds -{ - SOUND_FEMALE = 12671, - SOUND_MALE = 12670 -}; -struct npc_outhouse_bunnyAI : public ScriptedAI -{ - npc_outhouse_bunnyAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint8 m_counter; - uint8 m_gender; - - void Reset() - { - m_counter = 0; - m_gender = 0; - } - - void SetData(uint32 uiType, uint32 uiData) - { - if (uiType == 1) - m_gender = uiData; - } - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_OUTHOUSE_GROANS) - { - ++m_counter; - if (m_counter < 5) - DoCast(pCaster, SPELL_CAMERA_SHAKE, true); - else - m_counter = 0; - DoCast(me, SPELL_DUST_FIELD, true); - switch (m_gender) - { - case GENDER_FEMALE: DoPlaySoundToSet(me, SOUND_FEMALE); break; - case GENDER_MALE: DoPlaySoundToSet(me, SOUND_MALE); break; - } - } - } -}; - -CreatureAI* GetAI_npc_outhouse_bunny(Creature* pCreature) -{ - return new npc_outhouse_bunnyAI (pCreature); -} - -// Tallhorn Stage - -enum etallhornstage -{ - OBJECT_HAUNCH = 188665 -}; - -struct npc_tallhorn_stagAI : public ScriptedAI -{ - npc_tallhorn_stagAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint8 m_uiPhase; - - void Reset() - { - m_uiPhase = 1; - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (m_uiPhase == 1) - { - if (GameObject* haunch = me->FindNearestGameObject(OBJECT_HAUNCH, 2.0f)) - { - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - } - m_uiPhase = 0; - } - } -}; - -CreatureAI* GetAI_npc_tallhorn_stag(Creature* pCreature) -{ - return new npc_tallhorn_stagAI (pCreature); -} - -// Amberpine Woodsman - -enum eamberpinewoodsman -{ - TALLHORN_STAG = 26363 -}; - -struct npc_amberpine_woodsmanAI : public ScriptedAI -{ - npc_amberpine_woodsmanAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint8 m_uiPhase; - uint32 m_uiTimer; - - void Reset() - { - m_uiTimer = 0; - m_uiPhase = 1; - } - - void UpdateAI(const uint32 uiDiff) - { - // call this each update tick? - if (Creature* stag = me->FindNearestCreature(TALLHORN_STAG, 0.2f)) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USESTANDING); - } - else - if (m_uiPhase) - { - if (m_uiTimer <= uiDiff) - { - switch(m_uiPhase) - { - case 1: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_LOOT); - m_uiTimer = 3000; - m_uiPhase = 2; - break; - case 2: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACK1H); - m_uiTimer = 4000; - m_uiPhase = 1; - break; - } - } - else - m_uiTimer -= uiDiff; - } - ScriptedAI::UpdateAI(uiDiff); - - UpdateVictim(); - } -}; - -/*###### -## Quest 12288: Overwhelmed! -######*/ - -enum eSkirmisher -{ - SPELL_RENEW_SKIRMISHER = 48812, - CREDIT_NPC = 27466, - - RANDOM_SAY_1 = -1800044, //Ahh..better.. - RANDOM_SAY_2 = -1800045, //Whoa.. i nearly died there. Thank you, $Race! - RANDOM_SAY_3 = -1800046 //Thank you. $Class! -}; - -struct npc_wounded_skirmisherAI : public ScriptedAI -{ - npc_wounded_skirmisherAI(Creature *c) : ScriptedAI(c) {} - - uint64 uiPlayerGUID; - - uint32 DespawnTimer; - - void Reset () - { - DespawnTimer = 5000; - uiPlayerGUID = 0; - } - - void MovementInform(uint32, uint32 id) - { - if (id == 1) - me->ForcedDespawn(DespawnTimer); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_RENEW_SKIRMISHER && caster->GetTypeId() == TYPEID_PLAYER - && caster->ToPlayer()->GetQuestStatus(12288) == QUEST_STATUS_INCOMPLETE) - { - caster->ToPlayer()->KilledMonsterCredit(CREDIT_NPC, 0); - DoScriptText(RAND(RANDOM_SAY_1,RANDOM_SAY_2,RANDOM_SAY_3),caster); - if(me->IsStandState()) - me->GetMotionMaster()->MovePoint(1, me->GetPositionX()+7, me->GetPositionY()+7, me->GetPositionZ()); - else - { - me->SetStandState(UNIT_STAND_STATE_STAND); - me->ForcedDespawn(DespawnTimer); - } - - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_wounded_skirmisher(Creature* pCreature) -{ - return new npc_wounded_skirmisherAI(pCreature); -} - -CreatureAI* GetAI_npc_amberpine_woodsman(Creature* pCreature) -{ - return new npc_amberpine_woodsmanAI (pCreature); -} - -void AddSC_grizzly_hills() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_orsonn_and_kodian"; - newscript->pGossipHello = &GossipHello_npc_orsonn_and_kodian; - newscript->pGossipSelect = &GossipSelect_npc_orsonn_and_kodian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_emily"; - newscript->GetAI = &GetAI_npc_emily; - newscript->pQuestAccept = &QuestAccept_npc_emily; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_mrfloppy"; - newscript->GetAI = &GetAI_npc_mrfloppy; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_outhouse_bunny"; - newscript->GetAI = &GetAI_npc_outhouse_bunny; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tallhorn_stag"; - newscript->GetAI = &GetAI_npc_tallhorn_stag; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_amberpine_woodsman"; - newscript->GetAI = &GetAI_npc_amberpine_woodsman; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_wounded_skirmisher"; - newscript->GetAI = &GetAI_npc_wounded_skirmisher; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/northrend/gundrak/boss_drakkari_colossus.cpp deleted file mode 100644 index 04603c68813..00000000000 --- a/src/server/scripts/northrend/gundrak/boss_drakkari_colossus.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: The event with the Living Mojos is not implemented, just is done that when one of the mojos around the boss take damage will make the boss enter in combat! - */ - -#include "ScriptedPch.h" -#include "gundrak.h" - -enum Spells -{ - SPELL_EMERGE = 54850, - SPELL_MIGHTY_BLOW = 54719, - SPELL_MERGE = 54878, - SPELL_SURGE = 54801, - SPELL_FREEZE_ANIM = 16245, - SPELL_MOJO_PUDDLE = 55627, - H_SPELL_MOJO_PUDDLE = 58994, - SPELL_MOJO_WAVE = 55626, - H_SPELL_MOJO_WAVE = 58993 -}; - -struct boss_drakkari_colossusAI : public ScriptedAI -{ - boss_drakkari_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bHealth; - bool bHealth1; - - uint32 MightyBlowTimer; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, NOT_STARTED); - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->clearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); - me->SetReactState(REACT_PASSIVE); - MightyBlowTimer = 10*IN_MILISECONDS; - bHealth = false; - bHealth1 = false; - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, IN_PROGRESS); - } - - void CreatureState(Creature* pWho, bool bRestore = false) - { - if (!pWho) - return; - - if (bRestore) - { - pWho->clearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); - pWho->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pWho == me) - me->RemoveAura(SPELL_FREEZE_ANIM); - }else - { - pWho->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pWho->addUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); - if (pWho == me) - DoCast(me,SPELL_FREEZE_ANIM); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bHealth && HealthBelowPct(50) && !HealthBelowPct(5)) - { - CreatureState(me, false); - DoCast(me,SPELL_FREEZE_ANIM); - DoCast(me,SPELL_EMERGE); - bHealth = true; - } - - if (!bHealth1 && HealthBelowPct(5)) - { - DoCast(me,SPELL_EMERGE); - CreatureState(me, false); - bHealth1 = true; - me->RemoveAllAuras(); - } - - if (MightyBlowTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, true); - MightyBlowTimer = 10*IN_MILISECONDS; - } else MightyBlowTimer -= diff; - - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, DONE); - } - - void JustSummoned(Creature* pSummon) - { - if (HealthBelowPct(5)) - pSummon->DealDamage(pSummon, pSummon->GetHealth() * 0.5 , NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - pSummon->AI()->AttackStart(me->getVictim()); - } -}; - -struct boss_drakkari_elementalAI : public ScriptedAI -{ - boss_drakkari_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiSurgeTimer; - - bool bGoToColossus; - - void Reset() - { - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->CreatureState(me, true); - uiSurgeTimer = 7*IN_MILISECONDS; - bGoToColossus = false; - } - - void EnterEvadeMode() - { - me->RemoveFromWorld(); - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - { - CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->CreatureState(pColossus, true); - CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->bHealth1 = false; - } - me->RemoveFromWorld(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bGoToColossus && HealthBelowPct(50)) - { - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - { - if (!CAST_AI(boss_drakkari_colossusAI,pColossus->AI())->HealthBelowPct(6)) - { - me->InterruptNonMeleeSpells(true); - DoCast(pColossus, SPELL_MERGE); - bGoToColossus = true; - } - } - } - - if (uiSurgeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SURGE); - uiSurgeTimer = 7*IN_MILISECONDS; - } else uiSurgeTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - pColossus->Kill(pColossus); - } -}; - -struct npc_living_mojoAI : public ScriptedAI -{ - npc_living_mojoAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiMojoWaveTimer; - uint32 uiMojoPuddleTimer; - - void Reset() - { - uiMojoWaveTimer = 2*IN_MILISECONDS; - uiMojoPuddleTimer = 7*IN_MILISECONDS; - } - - void EnterCombat(Unit* /*who*/) - { - - //Check if the npc is near of Drakkari Colossus. - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - { - if (pColossus->isAlive() && me->IsInRange3d(pColossus->GetHomePosition().GetPositionX(),pColossus->GetHomePosition().GetPositionY(),pColossus->GetHomePosition().GetPositionZ(),0.0f,17.0f)) - me->SetReactState(REACT_PASSIVE); - else - me->SetReactState(REACT_AGGRESSIVE); - } - } - - void DamageTaken(Unit* pDone_by, uint32& /*uiDamage*/) - { - if (me->HasReactState(REACT_PASSIVE)) - { - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - { - if (pColossus->isAlive() && !pColossus->isInCombat()) - { - pColossus->RemoveAura(SPELL_FREEZE_ANIM); - pColossus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - pColossus->SetReactState(REACT_AGGRESSIVE); - if (pDone_by && pDone_by->isAlive()) - pColossus->AI()->AttackStart(pDone_by); - EnterEvadeMode(); - } - } - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiMojoWaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MOJO_WAVE); - uiMojoWaveTimer = 15*IN_MILISECONDS; - } else uiMojoWaveTimer -= diff; - - if (uiMojoPuddleTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MOJO_PUDDLE); - uiMojoPuddleTimer = 18*IN_MILISECONDS; - } else uiMojoPuddleTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_drakkari_colossus(Creature* pCreature) -{ - return new boss_drakkari_colossusAI (pCreature); -} - -CreatureAI* GetAI_boss_drakkari_elemental(Creature* pCreature) -{ - return new boss_drakkari_elementalAI (pCreature); -} - -CreatureAI* GetAI_npc_living_mojo(Creature* pCreature) -{ - return new npc_living_mojoAI (pCreature); -} - -void AddSC_boss_drakkari_colossus() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_drakkari_colossus"; - newscript->GetAI = &GetAI_boss_drakkari_colossus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_drakkari_elemental"; - newscript->GetAI = &GetAI_boss_drakkari_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_living_mojo"; - newscript->GetAI = &GetAI_npc_living_mojo; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/gundrak/boss_eck.cpp b/src/server/scripts/northrend/gundrak/boss_eck.cpp deleted file mode 100644 index 3bf1a33da5a..00000000000 --- a/src/server/scripts/northrend/gundrak/boss_eck.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -enum Spells -{ - SPELL_ECK_BERSERK = 55816, //Eck goes berserk, increasing his attack speed by 150% and all damage he deals by 500%. - SPELL_ECK_BITE = 55813, //Eck bites down hard, inflicting 150% of his normal damage to an enemy. - SPELL_ECK_SPIT = 55814, //Eck spits toxic bile at enemies in a cone in front of him, inflicting 2970 Nature damage and draining 220 mana every 1 sec for 3 sec. - SPELL_ECK_SPRING_1 = 55815, //Eck leaps at a distant target. --> Drops aggro and charges a random player. Tank can simply taunt him back. - SPELL_ECK_SPRING_2 = 55837 //Eck leaps at a distant target. -}; - -static Position EckSpawnPoint = { 1643.877930, 936.278015, 107.204948, 0.668432 }; - -struct boss_eckAI : public ScriptedAI -{ - boss_eckAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBerserkTimer; - uint32 uiBiteTimer; - uint32 uiSpitTimer; - uint32 uiSpringTimer; - - bool bBerserk; - - ScriptedInstance* pInstance; - - void Reset() - { - uiBerserkTimer = urand(60*IN_MILISECONDS,90*IN_MILISECONDS); //60-90 secs according to wowwiki - uiBiteTimer = 5*IN_MILISECONDS; - uiSpitTimer = 10*IN_MILISECONDS; - uiSpringTimer = 8*IN_MILISECONDS; - - bBerserk = false; - - if (pInstance) - pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ECK_BITE); - uiBiteTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); - } else uiBiteTimer -= diff; - - if (uiSpitTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ECK_SPIT); - uiSpitTimer = urand(6*IN_MILISECONDS,14*IN_MILISECONDS); - } else uiSpitTimer -= diff; - - if (uiSpringTimer <= diff) - { - Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, RAND(SPELL_ECK_SPRING_1, SPELL_ECK_SPRING_2)); - uiSpringTimer = urand(5*IN_MILISECONDS,10*IN_MILISECONDS); - } - } else uiSpringTimer -= diff; - - //Berserk on timer or 20% of health - if (!bBerserk) - { - if (uiBerserkTimer <= diff) - { - DoCast(me, SPELL_ECK_BERSERK); - bBerserk = true; - } - else - { - uiBerserkTimer -= diff; - if (HealthBelowPct(20)) - { - DoCast(me, SPELL_ECK_BERSERK); - bBerserk = true; - } - } - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, DONE); - } -}; - -CreatureAI* GetAI_boss_eck(Creature* pCreature) -{ - return new boss_eckAI (pCreature); -} - -struct npc_ruins_dwellerAI : public ScriptedAI -{ - npc_ruins_dwellerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void JustDied(Unit * /*who*/) - { - if (pInstance) - { - pInstance->SetData64(DATA_RUIN_DWELLER_DIED,me->GetGUID()); - if (pInstance->GetData(DATA_ALIVE_RUIN_DWELLERS) == 0) - me->SummonCreature(CREATURE_ECK, EckSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300*IN_MILISECONDS); - } - } -}; - -CreatureAI* GetAI_npc_ruins_dweller(Creature* pCreature) -{ - return new npc_ruins_dwellerAI (pCreature); -} - -void AddSC_boss_eck() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_eck"; - newscript->GetAI = &GetAI_boss_eck; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ruins_dweller"; - newscript->GetAI = &GetAI_npc_ruins_dweller; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/gundrak/boss_gal_darah.cpp b/src/server/scripts/northrend/gundrak/boss_gal_darah.cpp deleted file mode 100644 index c87a6600783..00000000000 --- a/src/server/scripts/northrend/gundrak/boss_gal_darah.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -//Spells -enum Spells -{ - SPELL_ENRAGE = 55285, - H_SPELL_ENRAGE = 59828, - SPELL_IMPALING_CHARGE = 54956, - H_SPELL_IMPALING_CHARGE = 59827, - SPELL_STOMP = 55292, - H_SPELL_STOMP = 59829, - SPELL_PUNCTURE = 55276, - H_SPELL_PUNCTURE = 59826, - SPELL_STAMPEDE = 55218, - SPELL_WHIRLING_SLASH = 55250, - H_SPELL_WHIRLING_SLASH = 59824, - SPELL_ECK_RESIDUE = 55817 -}; - -//Yells -enum Yells -{ - SAY_AGGRO = -1604000, - SAY_SLAY_1 = -1604001, - SAY_SLAY_2 = -1604002, - SAY_SLAY_3 = -1604003, - SAY_DEATH = -1604004, - SAY_SUMMON_RHINO_1 = -1604005, - SAY_SUMMON_RHINO_2 = -1604006, - SAY_SUMMON_RHINO_3 = -1604007, - SAY_TRANSFORM_1 = -1604008, //Phase change - SAY_TRANSFORM_2 = -1604009 -}; - -enum Achievements -{ - ACHIEV_WHAT_THE_ECK = 1864, - ACHIEV_SHARE_THE_LOVE = 2152 -}; - -enum Displays -{ - DISPLAY_RHINO = 26265, - DISPLAY_TROLL = 27061 -}; - -enum CombatPhase -{ - TROLL, - RHINO -}; - -struct boss_gal_darahAI : public ScriptedAI -{ - boss_gal_darahAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiStampedeTimer; - uint32 uiWhirlingSlashTimer; - uint32 uiPunctureTimer; - uint32 uiEnrageTimer; - uint32 uiImpalingChargeTimer; - uint32 uiStompTimer; - uint32 uiTransformationTimer; - std::set lImpaledPlayers; - - CombatPhase Phase; - - uint8 uiPhaseCounter; - - bool bStartOfTransformation; - - ScriptedInstance* pInstance; - - void Reset() - { - uiStampedeTimer = 10*IN_MILISECONDS; - uiWhirlingSlashTimer = 21*IN_MILISECONDS; - uiPunctureTimer = 10*IN_MILISECONDS; - uiEnrageTimer = 15*IN_MILISECONDS; - uiImpalingChargeTimer = 21*IN_MILISECONDS; - uiStompTimer = 25*IN_MILISECONDS; - uiTransformationTimer = 9*IN_MILISECONDS; - uiPhaseCounter = 0; - - lImpaledPlayers.clear(); - - bStartOfTransformation = true; - - Phase = TROLL; - - me->SetDisplayId(DISPLAY_TROLL); - - if (pInstance) - pInstance->SetData(DATA_GAL_DARAH_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_GAL_DARAH_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - switch (Phase) - { - case TROLL: - if (uiPhaseCounter == 2) - { - if (uiTransformationTimer <= diff) - { - me->SetDisplayId(DISPLAY_RHINO); - Phase = RHINO; - uiPhaseCounter = 0; - DoScriptText(SAY_TRANSFORM_1, me); - uiTransformationTimer = 5*IN_MILISECONDS; - bStartOfTransformation = true; - me->clearUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); - me->SetReactState(REACT_AGGRESSIVE); - } - else - { - uiTransformationTimer -= diff; - - if (bStartOfTransformation) - { - bStartOfTransformation = false; - me->addUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); - me->SetReactState(REACT_PASSIVE); - } - } - } - else - { - if (uiStampedeTimer <= diff) - { - DoCast(me, SPELL_STAMPEDE); - DoScriptText(RAND(SAY_SUMMON_RHINO_1,SAY_SUMMON_RHINO_2,SAY_SUMMON_RHINO_3),me); - uiStampedeTimer = 15*IN_MILISECONDS; - } else uiStampedeTimer -= diff; - - if (uiWhirlingSlashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLING_SLASH); - uiWhirlingSlashTimer = 21*IN_MILISECONDS; - ++uiPhaseCounter; - } else uiWhirlingSlashTimer -= diff; - } - break; - case RHINO: - if (uiPhaseCounter == 2) - { - if (uiTransformationTimer <= diff) - { - me->SetDisplayId(DISPLAY_TROLL); - Phase = TROLL; - uiPhaseCounter = 0; - DoScriptText(SAY_TRANSFORM_2, me); - uiTransformationTimer = 9*IN_MILISECONDS; - bStartOfTransformation = true; - me->clearUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); - me->SetReactState(REACT_AGGRESSIVE); - } - else - { - uiTransformationTimer -= diff; - - if (bStartOfTransformation) - { - bStartOfTransformation = false; - me->addUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); - me->SetReactState(REACT_PASSIVE); - } - } - } - else - { - if (uiPunctureTimer <= diff) - { - DoCast(me->getVictim(), SPELL_PUNCTURE); - uiPunctureTimer = 8*IN_MILISECONDS; - } else uiPunctureTimer -= diff; - - if (uiEnrageTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ENRAGE); - uiEnrageTimer = 20*IN_MILISECONDS; - } else uiEnrageTimer -= diff; - - if (uiStompTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STOMP); - uiStompTimer = 20*IN_MILISECONDS; - } else uiStompTimer -= diff; - - if (uiImpalingChargeTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, SPELL_IMPALING_CHARGE); - lImpaledPlayers.insert(pTarget->GetGUID()); - } - uiImpalingChargeTimer = 31*IN_MILISECONDS; - ++uiPhaseCounter; - } else uiImpalingChargeTimer -= diff; - } - break; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic()) - { - if (lImpaledPlayers.size() == 5) - pInstance->DoCompleteAchievement(ACHIEV_SHARE_THE_LOVE); - - AchievementEntry const *achievWhatTheEck = GetAchievementStore()->LookupEntry(ACHIEV_WHAT_THE_ECK); - if (achievWhatTheEck) - { - Map::PlayerList const &players = pInstance->instance->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - if (itr->getSource()->HasAura(SPELL_ECK_RESIDUE)) - itr->getSource()->CompletedAchievement(achievWhatTheEck); - } - } - - pInstance->SetData(DATA_GAL_DARAH_EVENT, DONE); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_gal_darah(Creature* pCreature) -{ - return new boss_gal_darahAI (pCreature); -} - -void AddSC_boss_gal_darah() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_gal_darah"; - newscript->GetAI = &GetAI_boss_gal_darah; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/gundrak/boss_moorabi.cpp b/src/server/scripts/northrend/gundrak/boss_moorabi.cpp deleted file mode 100644 index 84a7d8bc654..00000000000 --- a/src/server/scripts/northrend/gundrak/boss_moorabi.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -enum eSpells -{ - SPELL_DETERMINED_STAB = 55104, - SPELL_GROUND_TREMOR = 55142, - SPELL_NUMBING_SHOUT = 55106, - SPELL_DETERMINED_GORE = 55102, - H_SPELL_DETERMINED_GORE = 59444, - SPELL_QUAKE = 55101, - SPELL_NUMBING_ROAR = 55100, - SPELL_MOJO_FRENZY = 55163, - SPELL_TRANSFORMATION = 55098, //Periodic, The caster transforms into a powerful mammoth, increasing Physical damage done by 25% and granting immunity to Stun effects. -}; - -enum eArchivements -{ - ACHIEV_LESS_RABI = 2040 -}; - -enum eSays -{ - SAY_AGGRO = -1604010, - //SAY_SLAY_1 = -1604011, // not in db - SAY_SLAY_2 = -1604012, - SAY_SLAY_3 = -1604013, - SAY_DEATH = -1604014, - SAY_TRANSFORM = -1604015, - SAY_QUAKE = -1604016, - EMOTE_TRANSFORM = -1604017 -}; - -struct boss_moorabiAI : public ScriptedAI -{ - boss_moorabiAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bPhase; - - uint32 uiNumblingShoutTimer; - uint32 uiGroundTremorTimer; - uint32 uiDeterminedStabTimer; - uint32 uiTransformationTImer; - - void Reset() - { - uiGroundTremorTimer = 18*IN_MILISECONDS; - uiNumblingShoutTimer = 10*IN_MILISECONDS; - uiDeterminedStabTimer = 20*IN_MILISECONDS; - uiTransformationTImer = 12*IN_MILISECONDS; - bPhase = false; - - if (pInstance) - pInstance->SetData(DATA_MOORABI_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_MOJO_FRENZY, true); - - if (pInstance) - pInstance->SetData(DATA_MOORABI_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bPhase && me->HasAura(SPELL_TRANSFORMATION)) - { - bPhase = true; - me->RemoveAura(SPELL_MOJO_FRENZY); - } - - if (uiGroundTremorTimer <= uiDiff) - { - DoScriptText(SAY_QUAKE, me); - if (bPhase) - DoCast(me->getVictim(), SPELL_QUAKE, true); - else - DoCast(me->getVictim(), SPELL_GROUND_TREMOR, true); - uiGroundTremorTimer = 10*IN_MILISECONDS; - } else uiGroundTremorTimer -= uiDiff; - - if (uiNumblingShoutTimer <= uiDiff) - { - if (bPhase) - DoCast(me->getVictim(), SPELL_NUMBING_ROAR, true); - else - DoCast(me->getVictim(), SPELL_NUMBING_SHOUT, true); - uiNumblingShoutTimer = 10*IN_MILISECONDS; - } else uiNumblingShoutTimer -=uiDiff; - - if (uiDeterminedStabTimer <= uiDiff) - { - if (bPhase) - DoCast(me->getVictim(), SPELL_DETERMINED_GORE); - else - DoCast(me->getVictim(), SPELL_DETERMINED_STAB, true); - uiDeterminedStabTimer = 8*IN_MILISECONDS; - } else uiDeterminedStabTimer -=uiDiff; - - if (!bPhase && uiTransformationTImer <= uiDiff) - { - DoScriptText(EMOTE_TRANSFORM, me); - DoScriptText(SAY_TRANSFORM, me); - DoCast(me, SPELL_TRANSFORMATION, false); - uiTransformationTImer = 10*IN_MILISECONDS; - } else uiTransformationTImer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_MOORABI_EVENT, DONE); - - if (IsHeroic() && !bPhase) - pInstance->DoCompleteAchievement(ACHIEV_LESS_RABI); - } - } - - void KilledUnit(Unit* pVictim) - { - if (pVictim == me) - return; - - DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_moorabi(Creature *pCreature) -{ - return new boss_moorabiAI(pCreature); -} - -void AddSC_boss_moorabi() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_moorabi"; - newscript->GetAI = &GetAI_boss_moorabi; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/gundrak/boss_slad_ran.cpp b/src/server/scripts/northrend/gundrak/boss_slad_ran.cpp deleted file mode 100644 index 1014beaeddd..00000000000 --- a/src/server/scripts/northrend/gundrak/boss_slad_ran.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -//Spells -enum Spells -{ - SPELL_POISON_NOVA = 55081, - H_SPELL_POISON_NOVA = 59842, - SPELL_POWERFULL_BITE = 48287, - H_SPELL_POWERFULL_BITE = 59840, - SPELL_VENOM_BOLT = 54970, - H_SPELL_VENOM_BOLT = 59839 -}; - -//Yell -enum Yells -{ - SAY_AGGRO = -1604017, - SAY_SLAY_1 = -1604018, - SAY_SLAY_2 = -1604019, - SAY_SLAY_3 = -1604020, - SAY_DEATH = -1604021, - SAY_SUMMON_SNAKES = -1604022, - SAY_SUMMON_CONSTRICTORS = -1604023 -}; - -//Creatures -enum Creatures -{ - CREATURE_SNAKE = 29680, - CREATURE_CONSTRICTORS = 29713 -}; - -//Creatures' spells -enum ConstrictorSpells -{ - SPELL_GRIP_OF_SLAD_RAN = 55093, - SPELL_VENOMOUS_BITE = 54987, - H_SPELL_VENOMOUS_BITE = 58996 -}; - -static Position SpawnLoc[]= -{ - {1783.81, 646.637, 133.948, 3.71755}, - {1775.03, 606.586, 134.165, 1.43117}, - {1717.39, 630.041, 129.282, 5.96903}, - {1765.66, 646.542, 134.02, 5.11381}, - {1716.76, 635.159, 129.282, 0.191986} -}; - -struct boss_slad_ranAI : public ScriptedAI -{ - boss_slad_ranAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiPoisonNovaTimer; - uint32 uiPowerfullBiteTimer; - uint32 uiVenomBoltTimer; - uint32 uiSpawnTimer; - - uint8 uiPhase; - - SummonList lSummons; - - ScriptedInstance* pInstance; - - void Reset() - { - uiPoisonNovaTimer = 10*IN_MILISECONDS; - uiPowerfullBiteTimer = 3*IN_MILISECONDS; - uiVenomBoltTimer = 15*IN_MILISECONDS; - uiSpawnTimer = 5*IN_MILISECONDS; - uiPhase = 0; - - lSummons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_SLAD_RAN_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_SLAD_RAN_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiPoisonNovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_NOVA); - uiPoisonNovaTimer = 15*IN_MILISECONDS; - } else uiPoisonNovaTimer -= diff; - - if (uiPowerfullBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POWERFULL_BITE); - uiPowerfullBiteTimer = 10*IN_MILISECONDS; - } else uiPowerfullBiteTimer -= diff; - - if (uiVenomBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_VENOM_BOLT); - uiVenomBoltTimer = 10*IN_MILISECONDS; - } else uiVenomBoltTimer -= diff; - - if (uiPhase) - { - if (uiSpawnTimer <= diff) - { - if (uiPhase == 1) - for (uint8 i = 0; i < DUNGEON_MODE(3, 5); ++i) - me->SummonCreature(CREATURE_SNAKE, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); - if (uiPhase == 2) - for (uint8 i = 0; i < DUNGEON_MODE(3, 5); ++i) - me->SummonCreature(CREATURE_CONSTRICTORS, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); - uiSpawnTimer = 5*IN_MILISECONDS; - } else uiSpawnTimer -= diff; - } - - if (uiPhase == 0 && HealthBelowPct(30)) - { - DoScriptText(SAY_SUMMON_SNAKES,me); - uiPhase = 1; - } - - if (uiPhase == 1 && HealthBelowPct(25)) - { - DoScriptText(SAY_SUMMON_CONSTRICTORS,me); - uiPhase = 2; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_SLAD_RAN_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustSummoned(Creature* summoned) - { - summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); - lSummons.Summon(summoned); - } -}; - -struct mob_slad_ran_constrictorAI : public ScriptedAI -{ - mob_slad_ran_constrictorAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiGripOfSladRanTimer; - - void Reset() - { - uiGripOfSladRanTimer = 1*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - if (uiGripOfSladRanTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GRIP_OF_SLAD_RAN); - uiGripOfSladRanTimer = 5*IN_MILISECONDS; - } else uiGripOfSladRanTimer -= diff; - } - - ScriptedInstance* pInstance; -}; - -struct mob_slad_ran_viperAI : public ScriptedAI -{ - mob_slad_ran_viperAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiVenomousBiteTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiVenomousBiteTimer = 2*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiVenomousBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_VENOMOUS_BITE); - uiVenomousBiteTimer = 10*IN_MILISECONDS; - } else uiVenomousBiteTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_slad_ran(Creature* pCreature) -{ - return new boss_slad_ranAI (pCreature); -} - -CreatureAI* GetAI_mob_slad_ran_constrictor(Creature* pCreature) -{ - return new mob_slad_ran_constrictorAI (pCreature); -} - -CreatureAI* GetAI_mob_slad_ran_viper(Creature* pCreature) -{ - return new mob_slad_ran_viperAI (pCreature); -} - -void AddSC_boss_slad_ran() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_slad_ran"; - newscript->GetAI = &GetAI_boss_slad_ran; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_slad_ran_constrictor"; - newscript->GetAI = &GetAI_mob_slad_ran_constrictor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_slad_ran_viper"; - newscript->GetAI = &GetAI_mob_slad_ran_viper; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/gundrak/gundrak.h b/src/server/scripts/northrend/gundrak/gundrak.h deleted file mode 100644 index a443aa4e698..00000000000 --- a/src/server/scripts/northrend/gundrak/gundrak.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef DEF_GUNDRAK_H -#define DEF_GUNDRAK_H - -enum Data -{ - DATA_SLAD_RAN_EVENT, - DATA_MOORABI_EVENT, - DATA_DRAKKARI_COLOSSUS_EVENT, - DATA_GAL_DARAH_EVENT, - DATA_ECK_THE_FEROCIOUS_EVENT, - DATA_ALIVE_RUIN_DWELLERS -}; - -enum Data64 -{ - DATA_SLAD_RAN_ALTAR, - DATA_MOORABI_ALTAR, - DATA_DRAKKARI_COLOSSUS_ALTAR, - DATA_SLAD_RAN_STATUE, - DATA_MOORABI_STATUE, - DATA_DRAKKARI_COLOSSUS_STATUE, - DATA_DRAKKARI_COLOSSUS, - DATA_RUIN_DWELLER_DIED -}; - -enum mainCreatures -{ - CREATURE_RUIN_DWELLER = 29920, - CREATURE_SLAD_RAN = 29304, - CREATURE_MOORABI = 29305, - CREATURE_GALDARAH = 29306, - CREATURE_DRAKKARICOLOSSUS = 29307, - CREATURE_ECK = 29932 -}; - -#endif diff --git a/src/server/scripts/northrend/gundrak/instance_gundrak.cpp b/src/server/scripts/northrend/gundrak/instance_gundrak.cpp deleted file mode 100644 index 4dd896f74f2..00000000000 --- a/src/server/scripts/northrend/gundrak/instance_gundrak.cpp +++ /dev/null @@ -1,536 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -#define MAX_ENCOUNTER 5 - -/* GunDrak encounters: -0 - Slad'Ran -1 - Moorabi -2 - Drakkari Colossus -3 - Gal'Darah -4 - Eck the Ferocious -*/ - -struct instance_gundrak : public ScriptedInstance -{ - instance_gundrak(Map* pMap) : ScriptedInstance(pMap) - { - bHeroicMode = pMap->IsHeroic(); - Initialize(); - }; - - bool bHeroicMode; - bool spawnSupport; - - uint32 timer; - uint32 phase; - uint64 toActivate; - - uint64 uiSladRan; - uint64 uiMoorabi; - uint64 uiDrakkariColossus; - uint64 uiGalDarah; - uint64 uiEckTheFerocious; - - uint64 uiSladRanAltar; - uint64 uiMoorabiAltar; - uint64 uiDrakkariColossusAltar; - uint64 uiSladRanStatue; - uint64 uiMoorabiStatue; - uint64 uiDrakkariColossusStatue; - uint64 uiGalDarahStatue; - uint64 uiEckTheFerociousDoor; - uint64 uiEckTheFerociousDoorBehind; - uint64 uiGalDarahDoor1; - uint64 uiGalDarahDoor2; - uint64 uiBridge; - uint64 uiCollision; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - GOState uiSladRanStatueState; - GOState uiMoorabiStatueState; - GOState uiDrakkariColossusStatueState; - GOState uiGalDarahStatueState; - GOState uiBridgeState; - GOState uiCollisionState; - - std::set DwellerGUIDs; - - std::string str_data; - - void Initialize() - { - spawnSupport = false; - - timer = 0; - phase = 0; - toActivate = 0; - - uiSladRan = 0; - uiMoorabi = 0; - uiDrakkariColossus = 0; - uiGalDarah = 0; - uiEckTheFerocious = 0; - - uiSladRanAltar = 0; - uiMoorabiAltar = 0; - uiDrakkariColossusAltar = 0; - - uiSladRanStatue = 0; - uiMoorabiStatue = 0; - uiDrakkariColossusStatue = 0; - uiGalDarahStatue = 0; - - uiEckTheFerociousDoor = 0; - uiEckTheFerociousDoorBehind = 0; - uiGalDarahDoor1 = 0; - uiGalDarahDoor2 = 0; - - uiBridge = 0; - uiCollision = 0; - - uiSladRanStatueState = GO_STATE_ACTIVE; - uiMoorabiStatueState = GO_STATE_ACTIVE; - uiDrakkariColossusStatueState = GO_STATE_ACTIVE; - uiGalDarahStatueState = GO_STATE_READY; - uiBridgeState = GO_STATE_ACTIVE; - uiCollisionState = GO_STATE_READY; - - DwellerGUIDs.clear(); - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case CREATURE_SLAD_RAN: uiSladRan = pCreature->GetGUID(); break; - case CREATURE_MOORABI: uiMoorabi = pCreature->GetGUID(); break; - case CREATURE_GALDARAH: uiGalDarah = pCreature->GetGUID(); break; - case CREATURE_DRAKKARICOLOSSUS: uiDrakkariColossus = pCreature->GetGUID(); break; - case CREATURE_ECK: uiEckTheFerocious = pCreature->GetGUID(); break; - case CREATURE_RUIN_DWELLER: - if (pCreature->isAlive()) - DwellerGUIDs.insert(pCreature->GetGUID()); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 192518: - uiSladRanAltar = pGo->GetGUID(); - // Make sure that they start out as unusuable - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - if (m_auiEncounter[0] == DONE) - { - if (uiSladRanStatueState == GO_STATE_ACTIVE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - else - { - ++phase; - pGo->SetGoState(GO_STATE_ACTIVE); - } - } - break; - case 192519: - uiMoorabiAltar = pGo->GetGUID(); - // Make sure that they start out as unusuable - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - if (m_auiEncounter[0] == DONE) - { - if (uiMoorabiStatueState == GO_STATE_ACTIVE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - else - { - ++phase; - pGo->SetGoState(GO_STATE_ACTIVE); - } - } - break; - case 192520: - uiDrakkariColossusAltar = pGo->GetGUID(); - // Make sure that they start out as unusuable - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - if (m_auiEncounter[0] == DONE) - { - if (uiDrakkariColossusStatueState == GO_STATE_ACTIVE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - else - { - ++phase; - pGo->SetGoState(GO_STATE_ACTIVE); - } - } - break; - case 192564: - uiSladRanStatue = pGo->GetGUID(); - pGo->SetGoState(uiSladRanStatueState); - break; - case 192565: - uiMoorabiStatue = pGo->GetGUID(); - pGo->SetGoState(uiMoorabiStatueState); - break; - case 192566: - uiGalDarahStatue = pGo->GetGUID(); - pGo->SetGoState(uiGalDarahStatueState); - break; - case 192567: - uiDrakkariColossusStatue = pGo->GetGUID(); - pGo->SetGoState(uiDrakkariColossusStatueState); - break; - case 192632: - uiEckTheFerociousDoor = pGo->GetGUID(); - if (bHeroicMode && m_auiEncounter[1] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 192569: - uiEckTheFerociousDoorBehind = pGo->GetGUID(); - if (bHeroicMode && m_auiEncounter[4] == DONE) - HandleGameObject(NULL,true,pGo); - case 193208: - uiGalDarahDoor1 = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 193209: - uiGalDarahDoor2 = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 193188: - uiBridge = pGo->GetGUID(); - pGo->SetGoState(uiBridgeState); - break; - case 192633: - uiCollision = pGo->GetGUID(); - pGo->SetGoState(uiCollisionState); - - // Can't spawn here with SpawnGameObject because pGo isn't added to world yet... - if (uiCollisionState == GO_STATE_ACTIVE_ALTERNATIVE) - spawnSupport = true; - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_SLAD_RAN_EVENT: - m_auiEncounter[0] = data; - if (data == DONE) - { - GameObject* pGo = instance->GetGameObject(uiSladRanAltar); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - } - break; - case DATA_MOORABI_EVENT: - m_auiEncounter[1] = data; - if (data == DONE) - { - GameObject* pGo = instance->GetGameObject(uiMoorabiAltar); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - if (bHeroicMode) - HandleGameObject(uiEckTheFerociousDoor,true); - } - break; - case DATA_DRAKKARI_COLOSSUS_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) - { - GameObject* pGo = instance->GetGameObject(uiDrakkariColossusAltar); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - } - break; - case DATA_GAL_DARAH_EVENT: - m_auiEncounter[3] = data; - if (data == DONE) - { - HandleGameObject(uiGalDarahDoor1,true); - HandleGameObject(uiGalDarahDoor2,true); - } - break; - case DATA_ECK_THE_FEROCIOUS_EVENT: - m_auiEncounter[4] = data; - if (bHeroicMode && data == DONE) - HandleGameObject(uiEckTheFerociousDoorBehind,true); - break; - } - - if (data == DONE) - SaveToDB(); - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_RUIN_DWELLER_DIED) - DwellerGUIDs.erase(data); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_SLAD_RAN_EVENT: return m_auiEncounter[0]; - case DATA_MOORABI_EVENT: return m_auiEncounter[1]; - case DATA_GAL_DARAH_EVENT: return m_auiEncounter[2]; - case DATA_DRAKKARI_COLOSSUS_EVENT: return m_auiEncounter[3]; - case DATA_ECK_THE_FEROCIOUS_EVENT: return m_auiEncounter[4]; - case DATA_ALIVE_RUIN_DWELLERS: return DwellerGUIDs.size(); - } - - return 0; - } - - uint64 GetData64(uint32 type) - { - switch(type) - { - case DATA_SLAD_RAN_ALTAR: return uiSladRanAltar; - case DATA_MOORABI_ALTAR: return uiMoorabiAltar; - case DATA_DRAKKARI_COLOSSUS_ALTAR: return uiDrakkariColossusAltar; - case DATA_SLAD_RAN_STATUE: return uiSladRanStatue; - case DATA_MOORABI_STATUE: return uiMoorabiStatue; - case DATA_DRAKKARI_COLOSSUS_STATUE: return uiDrakkariColossusStatue; - case DATA_DRAKKARI_COLOSSUS: return uiDrakkariColossus; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "G D " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " - << (uiSladRanStatue ? GetObjState(uiSladRanStatue) : GO_STATE_ACTIVE) << " " << (uiMoorabiStatue ? GetObjState(uiMoorabiStatue) : GO_STATE_ACTIVE) << " " - << (uiDrakkariColossusStatue ? GetObjState(uiDrakkariColossusStatue) : GO_STATE_ACTIVE) << " " << (uiGalDarahStatue ? GetObjState(uiGalDarahStatue) : GO_STATE_READY) << " " - << (uiBridge ? GetObjState(uiBridge) : GO_STATE_ACTIVE) << " " << (uiCollision ? GetObjState(uiCollision) : GO_STATE_READY); - - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 - >> data4 >> data5 >> data6 >> data7 >> data8 >> data9 >> data10; - - if (dataHead1 == 'G' && dataHead2 == 'D') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - uiSladRanStatueState = GOState(data5); - uiMoorabiStatueState = GOState(data6); - uiDrakkariColossusStatueState = GOState(data7); - uiGalDarahStatueState = GOState(data8); - uiBridgeState = GOState(data9); - uiCollisionState = GOState(data10); - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - bool QueueActivation(uint64 guid, uint32 time) - { - if (timer) - return false; - - toActivate = guid; - timer = time; - phase++; - return true; - } - - void Update(uint32 diff) - { - // Spawn the support for the bridge if necessary - if (spawnSupport) - { - if (GameObject* pCollision = instance->GetGameObject(uiCollision)) - pCollision->SummonGameObject(192743, pCollision->GetPositionX(), pCollision->GetPositionY(), pCollision->GetPositionZ(), pCollision->GetOrientation(), 0, 0, 0, 0, 0); - spawnSupport = false; - } - - // If there is nothing to activate, then return - if (!toActivate) - return; - - if (timer < diff) - { - timer = 0; - if (toActivate == uiBridge) - { - toActivate = 0; - GameObject* pBridge = instance->GetGameObject(uiBridge); - GameObject* pCollision = instance->GetGameObject(uiCollision); - GameObject* pSladRanStatue = instance->GetGameObject(uiSladRanStatue); - GameObject* pMoorabiStatue = instance->GetGameObject(uiMoorabiStatue); - GameObject* pDrakkariColossusStatue = instance->GetGameObject(uiDrakkariColossusStatue); - GameObject* pGalDarahStatue = instance->GetGameObject(uiGalDarahStatue); - - if (pBridge && pCollision && pSladRanStatue && pMoorabiStatue && pDrakkariColossusStatue && pGalDarahStatue) - { - pBridge->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pCollision->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pSladRanStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pMoorabiStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pDrakkariColossusStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pGalDarahStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - - // Add the GO that solidifies the bridge so you can walk on it - spawnSupport = true; - SaveToDB(); - } - } - else - { - uint32 spell = 0; - GameObject* pAltar = NULL; - if (toActivate == uiSladRanStatue) - { - spell = 57071; - pAltar = instance->GetGameObject(uiSladRanAltar); - } else if (toActivate == uiMoorabiStatue) - { - spell = 57068; - pAltar = instance->GetGameObject(uiMoorabiAltar); - } else if (toActivate == uiDrakkariColossusStatue) - { - spell = 57072; - pAltar = instance->GetGameObject(uiDrakkariColossusAltar); - } - - // This is a workaround to make the beam cast properly. The caster should be ID 30298 but since the spells - // all are with scripted target for that same ID, it will hit itself. - if (pAltar) - if (Creature* trigger = pAltar->SummonCreature(18721, pAltar->GetPositionX(), pAltar->GetPositionY(), pAltar->GetPositionZ() + 3, pAltar->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 5000)) - { - // Set the trigger model to invisible - trigger->SetDisplayId(11686); - trigger->CastSpell(trigger, spell, false); - } - - if (GameObject* statueGO = instance->GetGameObject(toActivate)) - statueGO->SetGoState(GO_STATE_READY); - - toActivate = 0; - - if (phase == 3) - QueueActivation(uiBridge, 3000); - else - SaveToDB(); // Don't save in between last statue and bridge turning in case of crash leading to stuck instance - } - } else timer -= diff; - } - - GOState GetObjState(uint64 guid) - { - if (GameObject* go = instance->GetGameObject(guid)) - return go->GetGoState(); - return GO_STATE_ACTIVE; - } -}; - -bool GOHello_altar(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - uint64 uiStatue = 0; - - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - if (pInstance) - { - switch(pGO->GetEntry()) - { - case 192518: uiStatue = pInstance->GetData64(DATA_SLAD_RAN_STATUE); break; - case 192519: uiStatue = pInstance->GetData64(DATA_MOORABI_STATUE); break; - case 192520: uiStatue = pInstance->GetData64(DATA_DRAKKARI_COLOSSUS_STATUE); break; - } - if (((instance_gundrak*)pInstance)->QueueActivation(uiStatue, 3500)) - { - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - } - return true; - } - return false; -} - -InstanceData* GetInstanceData_instance_gundrak(Map* pMap) -{ - return new instance_gundrak(pMap); -} - -void AddSC_instance_gundrak() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_gundrak"; - newscript->GetInstanceData = &GetInstanceData_instance_gundrak; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_gundrak_altar"; - newscript->pGOHello = &GOHello_altar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/howling_fjord.cpp b/src/server/scripts/northrend/howling_fjord.cpp deleted file mode 100644 index 172501e2faa..00000000000 --- a/src/server/scripts/northrend/howling_fjord.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Sholazar_Basin -SD%Complete: 100 -SDComment: Quest support: 11253, 11241. -SDCategory: howling_fjord -EndScriptData */ - -/* ContentData -npc_plaguehound_tracker -npc_apothecary_hanes -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_apothecary_hanes -######*/ -enum Entries -{ - NPC_APOTHECARY_HANES = 23784, - FACTION_ESCORTEE_A = 774, - FACTION_ESCORTEE_H = 775, - NPC_HANES_FIRE_TRIGGER = 23968, - QUEST_TRAIL_OF_FIRE = 11241, - SPELL_COSMETIC_LOW_POLY_FIRE = 56274 -}; - -bool QuestAccept_npc_apothecary_hanes(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_TRAIL_OF_FIRE) - { - switch (pPlayer->GetTeam()) - { - case ALLIANCE: - pCreature->setFaction(FACTION_ESCORTEE_A); - break; - case HORDE: - pCreature->setFaction(FACTION_ESCORTEE_H); - break; - } - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - } - return true; -} - -struct npc_Apothecary_HanesAI : public npc_escortAI -{ - npc_Apothecary_HanesAI(Creature* pCreature) : npc_escortAI(pCreature){} - uint32 PotTimer; - - void Reset () - { - SetDespawnAtFar(false); - PotTimer = 10000; //10 sec cooldown on potion - } - - void JustDied(Unit* /*killer*/) - { - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->FailQuest(QUEST_TRAIL_OF_FIRE); - } - - void UpdateEscortAI(const uint32 diff) - { - if (HealthBelowPct(75)) - { - if (PotTimer <= diff) - { - DoCast(me, 17534, true); - PotTimer = 10000; - } else PotTimer -= diff; - } - if (GetAttack() && UpdateVictim()) - DoMeleeAttackIfReady(); - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - if (!pPlayer) - return; - switch(i) - { - case 1: - me->SetReactState(REACT_AGGRESSIVE); - SetRun(true); - break; - case 23: - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_TRAIL_OF_FIRE, me); - me->ForcedDespawn(); - break; - case 5: - if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) - Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); - SetRun(false); - break; - case 6: - if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) - Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); - SetRun(true); - break; - case 8: - if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) - Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); - SetRun(false); - break; - case 9: - if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) - Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); - break; - case 10: - SetRun(true); - break; - case 13: - SetRun(false); - break; - case 14: - if (Unit* Trigger = me->FindNearestCreature(NPC_HANES_FIRE_TRIGGER,10.0f)) - Trigger->CastSpell(Trigger, SPELL_COSMETIC_LOW_POLY_FIRE, false); - SetRun(true); - break; - } - } -}; -CreatureAI* GetAI_npc_apothecary_hanes(Creature* pCreature) -{ - return new npc_Apothecary_HanesAI(pCreature); -} -/*###### -## npc_plaguehound_tracker -######*/ - -enum ePlaguehound -{ - QUEST_SNIFF_OUT_ENEMY = 11253 -}; - -struct npc_plaguehound_trackerAI : public npc_escortAI -{ - npc_plaguehound_trackerAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void Reset() - { - InitScriptData(); - } - - void InitScriptData() - { - Player* pPlayer = NULL; - if (me->isSummon()) - if (Unit* summoner = CAST_SUM(me)->GetSummoner()) - if (summoner->GetTypeId() == TYPEID_PLAYER) - pPlayer = CAST_PLR(summoner); - - if (!pPlayer) - return; - - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - Start(false, false, pPlayer->GetGUID()); - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = NULL; - if (me->isSummon()) - if (Unit* summoner = CAST_SUM(me)->GetSummoner()) - if (summoner->GetTypeId() == TYPEID_PLAYER) - pPlayer = CAST_PLR(summoner); - - if (!pPlayer) - return; - - switch(i) - { - case 26: - me->ForcedDespawn(); - break; - } - } -}; - -CreatureAI* GetAI_npc_plaguehound_tracker(Creature* pCreature) -{ - return new npc_plaguehound_trackerAI(pCreature); -} - -/*###### -## npc_razael_and_lyana -######*/ - -#define GOSSIP_RAZAEL_REPORT "High Executor Anselm wants a report on the situation." -#define GOSSIP_LYANA_REPORT "High Executor Anselm requests your report." - -enum eRazael -{ - QUEST_REPORTS_FROM_THE_FIELD = 11221, - NPC_RAZAEL = 23998, - NPC_LYANA = 23778, - GOSSIP_TEXTID_RAZAEL1 = 11562, - GOSSIP_TEXTID_RAZAEL2 = 11564, - GOSSIP_TEXTID_LYANA1 = 11586, - GOSSIP_TEXTID_LYANA2 = 11588 -}; - -bool GossipHello_npc_razael_and_lyana(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_REPORTS_FROM_THE_FIELD) == QUEST_STATUS_INCOMPLETE) - switch (pCreature->GetEntry()) - { - case NPC_RAZAEL: - if (!pPlayer->GetReqKillOrCastCurrentCount(QUEST_REPORTS_FROM_THE_FIELD, NPC_RAZAEL)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_RAZAEL_REPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RAZAEL1, pCreature->GetGUID()); - return true; - } - break; - case NPC_LYANA: - if (!pPlayer->GetReqKillOrCastCurrentCount(QUEST_REPORTS_FROM_THE_FIELD, NPC_LYANA)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LYANA_REPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LYANA1, pCreature->GetGUID()); - return true; - } - break; - } - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_razael_and_lyana(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RAZAEL2, pCreature->GetGUID()); - pPlayer->TalkedToCreature(NPC_RAZAEL, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LYANA2, pCreature->GetGUID()); - pPlayer->TalkedToCreature(NPC_LYANA, pCreature->GetGUID()); - break; - } - return true; -} - -/*###### -## npc_mcgoyver -######*/ - -#define GOSSIP_ITEM_MG_I "Walt sent me to pick up some dark iron ingots." -#define GOSSIP_ITEM_MG_II "Yarp." - -enum eMcGoyver -{ - QUEST_WE_CAN_REBUILD_IT = 11483, - - SPELL_CREATURE_DARK_IRON_INGOTS = 44512, - SPELL_TAXI_EXPLORERS_LEAGUE = 44280, - - GOSSIP_TEXTID_MCGOYVER = 12193 -}; - -bool GossipHello_npc_mcgoyver(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_WE_CAN_REBUILD_IT) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MG_I, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_mcgoyver(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MG_II, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_MCGOYVER, pCreature->GetGUID()); - pPlayer->CastSpell(pPlayer, SPELL_CREATURE_DARK_IRON_INGOTS, true); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CastSpell(pPlayer, SPELL_TAXI_EXPLORERS_LEAGUE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - return true; -} - -void AddSC_howling_fjord() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_apothecary_hanes"; - newscript->GetAI = &GetAI_npc_apothecary_hanes; - newscript->pQuestAccept = &QuestAccept_npc_apothecary_hanes; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_plaguehound_tracker"; - newscript->GetAI = &GetAI_npc_plaguehound_tracker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_razael_and_lyana"; - newscript->pGossipHello = &GossipHello_npc_razael_and_lyana; - newscript->pGossipSelect = &GossipSelect_npc_razael_and_lyana; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_mcgoyver"; - newscript->pGossipHello = &GossipHello_npc_mcgoyver; - newscript->pGossipSelect = &GossipSelect_npc_mcgoyver; - newscript->RegisterSelf(); - } diff --git a/src/server/scripts/northrend/icecrown.cpp b/src/server/scripts/northrend/icecrown.cpp deleted file mode 100644 index 76608bdb73d..00000000000 --- a/src/server/scripts/northrend/icecrown.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Icecrown -SD%Complete: 100 -SDComment: Quest support: 12807 -SDCategory: Icecrown -EndScriptData */ - -/* ContentData -npc_arete -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_arete -######*/ - -#define GOSSIP_ARETE_ITEM1 "Lord-Commander, I would hear your tale." -#define GOSSIP_ARETE_ITEM2 "" -#define GOSSIP_ARETE_ITEM3 "I thought that they now called themselves the Scarlet Onslaught?" -#define GOSSIP_ARETE_ITEM4 "Where did the grand admiral go?" -#define GOSSIP_ARETE_ITEM5 "That's fine. When do I start?" -#define GOSSIP_ARETE_ITEM6 "Let's finish this!" -#define GOSSIP_ARETE_ITEM7 "That's quite a tale, Lord-Commander." - -enum eArete -{ - GOSSIP_TEXTID_ARETE1 = 13525, - GOSSIP_TEXTID_ARETE2 = 13526, - GOSSIP_TEXTID_ARETE3 = 13527, - GOSSIP_TEXTID_ARETE4 = 13528, - GOSSIP_TEXTID_ARETE5 = 13529, - GOSSIP_TEXTID_ARETE6 = 13530, - GOSSIP_TEXTID_ARETE7 = 13531, - - QUEST_THE_STORY_THUS_FAR = 12807 -}; - -bool GossipHello_npc_arete(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_THE_STORY_THUS_FAR) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE1, pCreature->GetGUID()); - return true; - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_arete(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE3, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE4, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE5, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE6, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE7, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(QUEST_THE_STORY_THUS_FAR); - break; - } - - return true; -} - -/*###### -## npc_dame_evniki_kapsalis -######*/ - -enum eDameEnvikiKapsalis -{ - TITLE_CRUSADER = 123 -}; - -bool GossipHello_npc_dame_evniki_kapsalis(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->HasTitle(TITLE_CRUSADER)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_dame_evniki_kapsalis(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - return true; -} - -/*###### -## npc_squire_david -######*/ - -enum eSquireDavid -{ - QUEST_THE_ASPIRANT_S_CHALLENGE_H = 13680, - QUEST_THE_ASPIRANT_S_CHALLENGE_A = 13679, - - NPC_ARGENT_VALIANT = 33448, - - GOSSIP_TEXTID_SQUIRE = 14407 -}; - -#define GOSSIP_SQUIRE_ITEM_1 "I am ready to fight!" -#define GOSSIP_SQUIRE_ITEM_2 "How do the Argent Crusader raiders fight?" - -bool GossipHello_npc_squire_david(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_H) == QUEST_STATUS_INCOMPLETE || - pPlayer->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_A) == QUEST_STATUS_INCOMPLETE)//We need more info about it. - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - } - - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SQUIRE, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_squire_david(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->SummonCreature(NPC_ARGENT_VALIANT,8575.451,952.472,547.554,0.38); - } - //else - //pPlayer->SEND_GOSSIP_MENU(???, pCreature->GetGUID()); Missing text - return true; -} - -/*###### -## npc_argent_valiant -######*/ - -enum eArgentValiant -{ - SPELL_CHARGE = 63010, - SPELL_SHIELD_BREAKER = 65147, - - NPC_ARGENT_VALIANT_CREDIT = 24108 -}; - -struct npc_argent_valiantAI : public ScriptedAI -{ - npc_argent_valiantAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pCreature->GetMotionMaster()->MovePoint(0,8599.258,963.951,547.553); - pCreature->setFaction(35); //wrong faction in db? - } - - uint32 uiChargeTimer; - uint32 uiShieldBreakerTimer; - - void Reset() - { - uiChargeTimer = 7000; - uiShieldBreakerTimer = 10000; - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - me->setFaction(14); - } - - void DamageTaken(Unit* pDoneBy, uint32& uiDamage) - { - if (uiDamage > me->GetHealth() && pDoneBy->GetTypeId() == TYPEID_PLAYER) - { - uiDamage = 0; - CAST_PLR(pDoneBy)->KilledMonsterCredit(NPC_ARGENT_VALIANT_CREDIT,0); - me->setFaction(35); - me->ForcedDespawn(5000); - me->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - EnterEvadeMode(); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiChargeTimer <= uiDiff) - { - DoCastVictim(SPELL_CHARGE); - uiChargeTimer = 7000; - } else uiChargeTimer -= uiDiff; - - if (uiShieldBreakerTimer <= uiDiff) - { - DoCastVictim(SPELL_SHIELD_BREAKER); - uiShieldBreakerTimer = 10000; - } else uiShieldBreakerTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_argent_valiant(Creature* pCreature) -{ - return new npc_argent_valiantAI (pCreature); -} - -/*###### -## npc_argent_tournament_post -######*/ - -enum eArgentTournamentPost -{ - SPELL_ROPE_BEAM = 63413, - NPC_GORMOK_THE_IMPALER = 35469, - NPC_ICEHOWL = 35470 -}; - -struct npc_argent_tournament_postAI : public ScriptedAI -{ - npc_argent_tournament_postAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - if (Creature* pTarget = me->FindNearestCreature(NPC_GORMOK_THE_IMPALER, 6.0f)) - DoCast(pTarget, SPELL_ROPE_BEAM); - - if (Creature* pTarget2 = me->FindNearestCreature(NPC_ICEHOWL, 6.0f)) - DoCast(pTarget2, SPELL_ROPE_BEAM); - - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_npc_argent_tournament_post(Creature* pCreature) -{ - return new npc_argent_tournament_postAI (pCreature); -} - -/*###### -## npc_alorah_and_grimmin -######*/ - -enum ealorah_and_grimmin -{ - SPELL_CHAIN = 68341, - NPC_FJOLA_LIGHTBANE = 36065, - NPC_EYDIS_DARKBANE = 36066, - NPC_PRIESTESS_ALORAH = 36101, - NPC_PRIEST_GRIMMIN = 36102 -}; - -struct npc_alorah_and_grimminAI : public ScriptedAI -{ - npc_alorah_and_grimminAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - bool uiCast; - - void Reset() - { - uiCast = false; - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (uiCast) - return; - uiCast = true; - Creature* pTarget = NULL; - - switch(me->GetEntry()) - { - case NPC_PRIESTESS_ALORAH: - pTarget = me->FindNearestCreature(NPC_EYDIS_DARKBANE, 10.0f); - break; - case NPC_PRIEST_GRIMMIN: - pTarget = me->FindNearestCreature(NPC_FJOLA_LIGHTBANE, 10.0f); - break; - } - if (pTarget) - DoCast(pTarget, SPELL_CHAIN); - - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_npc_alorah_and_grimmin(Creature* pCreature) -{ - return new npc_alorah_and_grimminAI (pCreature); -} - -/*###### -## npc_guardian_pavilion -######*/ - -enum eGuardianPavilion -{ - SPELL_TRESPASSER_H = 63987, - AREA_SUNREAVER_PAVILION = 4676, - - AREA_SILVER_COVENANT_PAVILION = 4677, - SPELL_TRESPASSER_A = 63986, -}; - -struct npc_guardian_pavilionAI : public Scripted_NoMovementAI -{ - npc_guardian_pavilionAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) {} - - void MoveInLineOfSight(Unit* pWho) - { - if (me->GetAreaId() != AREA_SUNREAVER_PAVILION && me->GetAreaId() != AREA_SILVER_COVENANT_PAVILION) - return; - - if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER || !me->IsHostileTo(pWho) || !me->isInBackInMap(pWho, 5.0f)) - return; - - if (pWho->HasAura(SPELL_TRESPASSER_H) || pWho->HasAura(SPELL_TRESPASSER_A)) - return; - - if (pWho->ToPlayer()->GetTeamId() == TEAM_ALLIANCE) - pWho->CastSpell(pWho, SPELL_TRESPASSER_H, true); - else - pWho->CastSpell(pWho, SPELL_TRESPASSER_A, true); - - } -}; - -CreatureAI* GetAI_npc_guardian_pavilion(Creature* pCreature) -{ - return new npc_guardian_pavilionAI (pCreature); -} - -void AddSC_icecrown() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_arete"; - newscript->pGossipHello = &GossipHello_npc_arete; - newscript->pGossipSelect = &GossipSelect_npc_arete; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dame_evniki_kapsalis"; - newscript->pGossipHello = &GossipHello_npc_dame_evniki_kapsalis; - newscript->pGossipSelect = &GossipSelect_npc_dame_evniki_kapsalis; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_squire_david"; - newscript->pGossipHello = &GossipHello_npc_squire_david; - newscript->pGossipSelect = &GossipSelect_npc_squire_david; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_argent_valiant"; - newscript->GetAI = &GetAI_npc_argent_valiant; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_argent_tournament_post"; - newscript->GetAI = &GetAI_npc_argent_tournament_post; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_alorah_and_grimmin"; - newscript->GetAI = &GetAI_npc_alorah_and_grimmin; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_guardian_pavilion"; - newscript->GetAI = &GetAI_npc_guardian_pavilion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_anubrekhan.cpp b/src/server/scripts/northrend/naxxramas/boss_anubrekhan.cpp deleted file mode 100644 index 896eb068eb6..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_anubrekhan.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SAY_GREET RAND(-1533000,-1533004,-1533005,-1533006,-1533007) -#define SAY_AGGRO RAND(-1533001,-1533002,-1533003) -#define SAY_SLAY -1533008 - -#define MOB_CRYPT_GUARD 16573 - -const Position GuardSummonPos = {3333.72, -3476.30, 287.1, 6.2801}; - -enum Events -{ - EVENT_NONE, - EVENT_IMPALE, - EVENT_LOCUST, - EVENT_SPAWN_GUARDIAN_NORMAL, - EVENT_BERSERK, -}; - -enum Spells -{ - SPELL_IMPALE_10 = 28783, - SPELL_IMPALE_25 = 56090, - SPELL_LOCUST_SWARM_10 = 28785, - SPELL_LOCUST_SWARM_25 = 54021, - SPELL_SUMMON_CORPSE_SCARABS_PLR = 29105, // This spawns 5 corpse scarabs on top of player - SPELL_SUMMON_CORPSE_SCARABS_MOB = 28864, // This spawns 10 corpse scarabs on top of dead guards - SPELL_BERSERK = 27680, -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 9891, -}; - -struct boss_anubrekhanAI : public BossAI -{ - boss_anubrekhanAI(Creature *c) : BossAI(c, BOSS_ANUBREKHAN) {} - - bool hasTaunted; - - void Reset() - { - _Reset(); - - hasTaunted = false; - - if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - { - Position pos; - - // respawn guard using home position, - // otherwise, after a wipe, they respawn where boss was at wipe moment. - pos = me->GetHomePosition(); - pos.m_positionY -= 10.0f; - me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); - - pos = me->GetHomePosition(); - pos.m_positionY += 10.0f; - me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); - } - } - - void KilledUnit(Unit* victim) - { - //Force the player to spawn corpse scarabs via spell, TODO: Check percent chance for scarabs, 20% at the moment - if (!(rand()%5)) - if (victim->GetTypeId() == TYPEID_PLAYER) - victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, NULL, NULL, me->GetGUID()); - - DoScriptText(SAY_SLAY, me); - } - - void JustDied(Unit *) - { - _JustDied(); - - // start achievement timer (kill Maexna within 20 min) - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO, me); - events.ScheduleEvent(EVENT_IMPALE, 10000 + rand()%10000); - events.ScheduleEvent(EVENT_LOCUST, 90000); - events.ScheduleEvent(EVENT_BERSERK, 600000); - - if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000,20000)); - } - - void MoveInLineOfSight(Unit *who) - { - if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER) - { - DoScriptText(SAY_GREET, me); - hasTaunted = true; - } - ScriptedAI::MoveInLineOfSight(who); - } - - void SummonedCreatureDespawn(Creature *summon) - { - BossAI::SummonedCreatureDespawn(summon); - - // check if it is an actual killed guard - if (!me->isAlive() || summon->isAlive() || summon->GetEntry() != MOB_CRYPT_GUARD) - return; - - summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, NULL, NULL, me->GetGUID()); - } - - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim() || !CheckInRoom()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_IMPALE: - //Cast Impale on a random target - //Do NOT cast it when we are afflicted by locust swarm - if (!me->HasAura(RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25))) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_IMPALE_10,SPELL_IMPALE_25)); - events.ScheduleEvent(EVENT_IMPALE, urand(10000,20000)); - break; - case EVENT_LOCUST: - // TODO : Add Text - DoCast(me, RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25)); - DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); - events.ScheduleEvent(EVENT_LOCUST, 90000); - break; - case EVENT_SPAWN_GUARDIAN_NORMAL: - // TODO : Add Text - DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); - break; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK, true); - events.ScheduleEvent(EVENT_BERSERK, 600000); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_anubrekhan(Creature* pCreature) -{ - return new boss_anubrekhanAI (pCreature); -} - -void AddSC_boss_anubrekhan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_anubrekhan"; - newscript->GetAI = &GetAI_boss_anubrekhan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_faerlina.cpp b/src/server/scripts/northrend/naxxramas/boss_faerlina.cpp deleted file mode 100644 index aa5a940eb8f..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_faerlina.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Yells -{ - SAY_GREET = -1533009, - SAY_AGGRO_1 = -1533010, - SAY_AGGRO_2 = -1533011, - SAY_AGGRO_3 = -1533012, - SAY_AGGRO_4 = -1533013, - SAY_SLAY_1 = -1533014, - SAY_SLAY_2 = -1533015, - SAY_DEATH = -1533016 -}; -//#define SOUND_RANDOM_AGGRO 8955 //soundId containing the 4 aggro sounds, we not using this - -enum Spells -{ - SPELL_POISON_BOLT_VOLLEY = 28796, - H_SPELL_POISON_BOLT_VOLLEY = 54098, - SPELL_RAIN_OF_FIRE = 28794, - H_SPELL_RAIN_OF_FIRE = 54099, - SPELL_FRENZY = 28798, - H_SPELL_FRENZY = 54100, - SPELL_WIDOWS_EMBRACE = 28732, - H_SPELL_WIDOWS_EMBRACE = 54097 -}; - -enum Events -{ - EVENT_NONE, - EVENT_POISON, - EVENT_FIRE, - EVENT_FRENZY -}; - -enum Achievements -{ - ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10 = 1997, - ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25 = 2140 -}; - -struct boss_faerlinaAI : public BossAI -{ - boss_faerlinaAI(Creature *c) : BossAI(c, BOSS_FAERLINA), greet(false) {} - - bool greet; - bool doDelayFrenzy; - bool bAchievement; - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4), me); - events.ScheduleEvent(EVENT_POISON, urand(10000,15000)); - events.ScheduleEvent(EVENT_FIRE, urand(6000,18000)); - events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000)); - } - - void Reset() - { - doDelayFrenzy = false; - bAchievement = true; - _Reset(); - } - - void MoveInLineOfSight(Unit *who) - { - if (!greet && who->GetTypeId() == TYPEID_PLAYER) - { - DoScriptText(SAY_GREET, me); - greet = true; - } - BossAI::MoveInLineOfSight(who); - } - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%3)) - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - - if (instance && bAchievement) - instance->DoCompleteAchievement(RAID_MODE(ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10,ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25)); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (doDelayFrenzy && !me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE, H_SPELL_WIDOWS_EMBRACE))) - { - doDelayFrenzy = false; - DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY), true); - } - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_POISON: - if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE))) - DoCastAOE(RAID_MODE(SPELL_POISON_BOLT_VOLLEY,H_SPELL_POISON_BOLT_VOLLEY)); - events.ScheduleEvent(EVENT_POISON, urand(8000,15000)); - break; - case EVENT_FIRE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_RAIN_OF_FIRE, H_SPELL_RAIN_OF_FIRE)); - events.ScheduleEvent(EVENT_FIRE, urand(6000,18000)); - break; - case EVENT_FRENZY: - // TODO : Add Text - if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE))) - DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY)); - else - doDelayFrenzy = true; - - events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000)); - break; - } - } - - DoMeleeAttackIfReady(); - } - - void SpellHit(Unit* caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_WIDOWS_EMBRACE || spell->Id == H_SPELL_WIDOWS_EMBRACE) - { - // TODO : Add Text - bAchievement = false; - doDelayFrenzy = true; - me->Kill(caster); - } - } -}; - -CreatureAI* GetAI_boss_faerlina(Creature* pCreature) -{ - return new boss_faerlinaAI (pCreature); -} - -struct mob_faerlina_addAI : public ScriptedAI -{ - mob_faerlina_addAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) { - me->ApplySpellImmune(0, IMMUNITY_MECHANIC, SPELL_EFFECT_BIND, true); - me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true); - } - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance && getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - { - if (Creature *pFaerlina = pInstance->instance->GetCreature(pInstance->GetData64(DATA_FAERLINA))) - DoCast(pFaerlina, SPELL_WIDOWS_EMBRACE); - } - } -}; - -CreatureAI* GetAI_mob_faerlina_add(Creature* pCreature) -{ - return new mob_faerlina_addAI (pCreature); -} - -void AddSC_boss_faerlina() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_faerlina"; - newscript->GetAI = &GetAI_boss_faerlina; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_faerlina_add"; - newscript->GetAI = &GetAI_mob_faerlina_add; - newscript->RegisterSelf(); -} - - diff --git a/src/server/scripts/northrend/naxxramas/boss_four_horsemen.cpp b/src/server/scripts/northrend/naxxramas/boss_four_horsemen.cpp deleted file mode 100644 index f04b39040db..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_four_horsemen.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Horsemen -{ - HORSEMEN_THANE, - HORSEMEN_LADY, - HORSEMEN_BARON, - HORSEMEN_SIR, -}; - -enum Events -{ - EVENT_NONE, - EVENT_MARK, - EVENT_CAST, - EVENT_BERSERK, -}; - -const Position WaypointPositions[12] = -{ - // Thane waypoints - {2542.3, -2984.1, 241.49, 5.362}, - {2547.6, -2999.4, 241.34, 5.049}, - {2542.9, -3015.0, 241.35, 4.654}, - // Lady waypoints - {2498.3, -2961.8, 241.28, 3.267}, - {2487.7, -2959.2, 241.28, 2.890}, - {2469.4, -2947.6, 241.28, 2.576}, - // Baron waypoints - {2553.8, -2968.4, 241.33, 5.757}, - {2564.3, -2972.5, 241.33, 5.890}, - {2583.9, -2971.67, 241.35, 0.008}, - // Sir waypoints - {2534.5, -2921.7, 241.53, 1.363}, - {2523.5, -2902.8, 241.28, 2.095}, - {2517.8, -2896.6, 241.28, 2.315}, -}; - -const uint32 MOB_HORSEMEN[] = {16064, 16065, 30549, 16063}; -const uint32 SPELL_MARK[] = {28832, 28833, 28834, 28835}; -#define SPELL_PRIMARY(i) RAID_MODE(SPELL_PRIMARY_N[i],SPELL_PRIMARY_H[i]) -const uint32 SPELL_PRIMARY_N[] = {28884, 28863, 28882, 28883}; -const uint32 SPELL_PRIMARY_H[] = {57467, 57463, 57369, 57466}; -#define SPELL_SECONDARY(i) RAID_MODE(SPELL_SECONDARY_N[i],SPELL_SECONDARY_H[i]) -const uint32 SPELL_SECONDARY_N[]= {0, 57374, 0, 57376}; -const uint32 SPELL_SECONDARY_H[]= {0, 57464, 0, 57465}; -const uint32 SPELL_PUNISH[] = {0, 57381, 0, 57377}; -#define SPELL_BERSERK 26662 - -// used by 16063,16064,16065,30549, but signed for 16063 -const int32 SAY_AGGRO[] = {-1533051, -1533044, -1533065, -1533058}; -const int32 SAY_TAUNT[3][4] ={ {-1533052, -1533045, -1533071, -1533059}, - {-1533053, -1533046, -1533072, -1533060}, - {-1533054, -1533047, -1533073, -1533061},}; -const int32 SAY_SPECIAL[] = {-1533055, -1533048, -1533070, -1533062}; -const int32 SAY_SLAY[] = {-1533056, -1533049, -1533068, -1533063}; -const int32 SAY_DEATH[] = {-1533057, -1533050, -1533074, -1533064}; - -#define SAY_BARON_AGGRO RAND(-1533065,-1533066,-1533067) -#define SAY_BARON_SLAY RAND(-1533068,-1533069) - -struct boss_four_horsemenAI : public BossAI -{ - boss_four_horsemenAI(Creature *c) : BossAI(c, BOSS_HORSEMEN) - { - id = Horsemen(0); - for (uint8 i = 0; i < 4; ++i) - if (me->GetEntry() == MOB_HORSEMEN[i]) - id = Horsemen(i); - caster = (id == HORSEMEN_LADY || id == HORSEMEN_SIR); - } - - Horsemen id; - uint64 uiEventStarterGUID; - uint8 nextWP; - uint32 punishTimer; - bool caster; - bool nextMovementStarted; - bool movementCompleted; - bool movementStarted; - bool encounterActionAttack; - bool encounterActionReset; - bool doDelayPunish; - - void Reset() - { - if (!encounterActionReset) - DoEncounterAction(NULL, false, true, false); - - if (instance) - instance->SetData(DATA_HORSEMEN0 + id, NOT_STARTED); - - me->SetReactState(REACT_AGGRESSIVE); - uiEventStarterGUID = 0; - nextWP = 0; - punishTimer = 2000; - nextMovementStarted = false; - movementCompleted = false; - movementStarted = false; - encounterActionAttack = false; - encounterActionReset = false; - doDelayPunish = false; - _Reset(); - } - - bool DoEncounterAction(Unit *who, bool attack, bool reset, bool checkAllDead) - { - if (!instance) - return false; - - Creature *Thane = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_THANE))); - Creature *Lady = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_LADY))); - Creature *Baron = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_BARON))); - Creature *Sir = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_SIR))); - - if (Thane && Lady && Baron && Sir) - { - if (attack && who) - { - CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionAttack = true; - CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionAttack = true; - CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionAttack = true; - CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionAttack = true; - - CAST_AI(boss_four_horsemenAI, Thane->AI())->AttackStart(who); - CAST_AI(boss_four_horsemenAI, Lady->AI())->AttackStart(who); - CAST_AI(boss_four_horsemenAI, Baron->AI())->AttackStart(who); - CAST_AI(boss_four_horsemenAI, Sir->AI())->AttackStart(who); - } - - if (reset) - { - if (instance->GetBossState(BOSS_HORSEMEN) != NOT_STARTED) - { - if (!Thane->isAlive()) - Thane->Respawn(); - - if (!Lady->isAlive()) - Lady->Respawn(); - - if (!Baron->isAlive()) - Baron->Respawn(); - - if (!Sir->isAlive()) - Sir->Respawn(); - - CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionReset = true; - CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionReset = true; - CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionReset = true; - CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionReset = true; - - CAST_AI(boss_four_horsemenAI, Thane->AI())->EnterEvadeMode(); - CAST_AI(boss_four_horsemenAI, Lady->AI())->EnterEvadeMode(); - CAST_AI(boss_four_horsemenAI, Baron->AI())->EnterEvadeMode(); - CAST_AI(boss_four_horsemenAI, Sir->AI())->EnterEvadeMode(); - } - } - - if (checkAllDead) - return !Thane->isAlive() && !Lady->isAlive() && !Baron->isAlive() && !Sir->isAlive(); - } - return false; - } - - void BeginFourHorsemenMovement() - { - movementStarted = true; - me->SetReactState(REACT_PASSIVE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true); - - switch(id) - { - case HORSEMEN_THANE: - me->GetMotionMaster()->MovePoint(0, WaypointPositions[0]); - break; - case HORSEMEN_LADY: - me->GetMotionMaster()->MovePoint(3, WaypointPositions[3]); - break; - case HORSEMEN_BARON: - me->GetMotionMaster()->MovePoint(6, WaypointPositions[6]); - break; - case HORSEMEN_SIR: - me->GetMotionMaster()->MovePoint(9, WaypointPositions[9]); - break; - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 2 || id == 5 || id == 8 || id == 11) - { - movementCompleted = true; - me->SetReactState(REACT_AGGRESSIVE); - - Unit *eventStarter = Unit::GetUnit(*me, uiEventStarterGUID); - - if (eventStarter && me->canAttack(eventStarter)) - AttackStart(eventStarter); - else if (!UpdateVictim()) - { - EnterEvadeMode(); - return; - } - - if (caster) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - } - - return; - } - - nextMovementStarted = false; - nextWP = id + 1; - } - - // switch to "who" if nearer than current target. - void SelectNearestTarget(Unit *who) - { - if (me->getVictim() && me->GetDistanceOrder(who, me->getVictim()) && me->canAttack(who)) - { - me->getThreatManager().modifyThreatPercent(me->getVictim(), -100); - me->AddThreat(who, 1000000.0f); - } - } - - void MoveInLineOfSight(Unit *who) - { - BossAI::MoveInLineOfSight(who); - if (caster) - SelectNearestTarget(who); - } - - void AttackStart(Unit *who) - { - if (!movementCompleted && !movementStarted) - { - uiEventStarterGUID = who->GetGUID(); - BeginFourHorsemenMovement(); - - if (!encounterActionAttack) - DoEncounterAction(who, true, false, false); - } - else if (movementCompleted && movementStarted) - { - if (caster) - me->Attack(who, false); - else - BossAI::AttackStart(who); - } - } - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%5)) - { - if (id == HORSEMEN_BARON) - DoScriptText(SAY_BARON_SLAY, me); - else - DoScriptText(SAY_SLAY[id], me); - } - } - - void JustDied(Unit* /*killer*/) - { - events.Reset(); - summons.DespawnAll(); - - if (instance) - instance->SetData(DATA_HORSEMEN0 + id, DONE); - - if (instance && DoEncounterAction(NULL, false, false, true)) - { - instance->SetBossState(BOSS_HORSEMEN, DONE); - instance->SaveToDB(); - - // Achievements related to the 4-horsemen are given through spell 59450 which does not exist. - // There is thus no way it can be given by casting the spell on the players. - instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59450); - } - - DoScriptText(SAY_DEATH[id], me); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - - if (id == HORSEMEN_BARON) - DoScriptText(SAY_BARON_AGGRO, me); - else - DoScriptText(SAY_AGGRO[id], me); - - events.ScheduleEvent(EVENT_MARK, 15000); - events.ScheduleEvent(EVENT_CAST, 20000+rand()%5000); - events.ScheduleEvent(EVENT_BERSERK, 15*100*1000); - } - - void UpdateAI(const uint32 diff) - { - if (nextWP && movementStarted && !movementCompleted && !nextMovementStarted) - { - nextMovementStarted = true; - me->GetMotionMaster()->MovePoint(nextWP, WaypointPositions[nextWP]); - } - - if (!UpdateVictim() || !CheckInRoom() || !movementCompleted) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_MARK: - if (!(rand()%5)) - DoScriptText(SAY_SPECIAL[id], me); - DoCastAOE(SPELL_MARK[id]); - events.ScheduleEvent(EVENT_MARK, 15000); - break; - case EVENT_CAST: - if (!(rand()%5)) - DoScriptText(SAY_TAUNT[rand()%3][id], me); - - if (caster) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) - DoCast(pTarget, SPELL_PRIMARY(id)); - } - else - DoCast(me->getVictim(), SPELL_PRIMARY(id)); - - events.ScheduleEvent(EVENT_CAST, 15000); - break; - case EVENT_BERSERK: - DoScriptText(SAY_SPECIAL[id], me); - DoCast(me, EVENT_BERSERK); - break; - } - } - - if (punishTimer <= diff) - { - if (doDelayPunish) - { - DoCastAOE(SPELL_PUNISH[id], true); - doDelayPunish = false; - } - punishTimer = 2000; - } else punishTimer -= diff; - - if (!caster) - DoMeleeAttackIfReady(); - else if ((!DoSpellAttackIfReady(SPELL_SECONDARY(id)) || !me->IsWithinLOSInMap(me->getVictim())) && movementCompleted && !doDelayPunish) - doDelayPunish = true; - } -}; - -CreatureAI* GetAI_four_horsemen(Creature* pCreature) -{ - return new boss_four_horsemenAI (pCreature); -} - -void AddSC_boss_four_horsemen() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_four_horsemen"; - newscript->GetAI = &GetAI_four_horsemen; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_gluth.cpp b/src/server/scripts/northrend/naxxramas/boss_gluth.cpp deleted file mode 100644 index ab6fa6c46d3..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_gluth.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SPELL_MORTAL_WOUND 25646 -#define SPELL_ENRAGE RAID_MODE(28371,54427) -#define SPELL_DECIMATE RAID_MODE(28374,54426) -#define SPELL_BERSERK 26662 -#define SPELL_INFECTED_WOUND 29306 - -#define MOB_ZOMBIE 16360 - -const Position PosSummon[3] = -{ - {3267.9, -3172.1, 297.42, 0.94}, - {3253.2, -3132.3, 297.42, 0}, - {3308.3, -3185.8, 297.42, 1.58}, -}; - -enum Events -{ - EVENT_NONE, - EVENT_WOUND, - EVENT_ENRAGE, - EVENT_DECIMATE, - EVENT_BERSERK, - EVENT_SUMMON, -}; - -#define EMOTE_NEARBY " spots a nearby zombie to devour!" - -struct boss_gluthAI : public BossAI -{ - boss_gluthAI(Creature *c) : BossAI(c, BOSS_GLUTH) - { - // Do not let Gluth be affected by zombies' debuff - me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true); - } - - void MoveInLineOfSight(Unit *who) - { - if (who->GetEntry() == MOB_ZOMBIE && me->IsWithinDistInMap(who, 7)) - { - SetGazeOn(who); - // TODO: use a script text - me->MonsterTextEmote(EMOTE_NEARBY, 0, true); - } - else - BossAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - events.ScheduleEvent(EVENT_WOUND, 10000); - events.ScheduleEvent(EVENT_ENRAGE, 15000); - events.ScheduleEvent(EVENT_DECIMATE, 105000); - events.ScheduleEvent(EVENT_BERSERK, 8*60000); - events.ScheduleEvent(EVENT_SUMMON, 15000); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == MOB_ZOMBIE) - summon->AI()->AttackStart(me); - summons.Summon(summon); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictimWithGaze() || !CheckInRoom()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_WOUND: - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - events.ScheduleEvent(EVENT_WOUND, 10000); - break; - case EVENT_ENRAGE: - // TODO : Add missing text - DoCast(me, SPELL_ENRAGE); - events.ScheduleEvent(EVENT_ENRAGE, 15000); - break; - case EVENT_DECIMATE: - // TODO : Add missing text - DoCastAOE(SPELL_DECIMATE); - events.ScheduleEvent(EVENT_DECIMATE, 105000); - break; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - events.ScheduleEvent(EVENT_BERSERK, 5*60000); - break; - case EVENT_SUMMON: - for (uint32 i = 0; i < RAID_MODE(1,2); ++i) - DoSummon(MOB_ZOMBIE, PosSummon[rand()%3]); - events.ScheduleEvent(EVENT_SUMMON, 10000); - break; - } - } - - if (me->getVictim() && me->getVictim()->GetEntry() == MOB_ZOMBIE) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->Kill(me->getVictim()); - me->ModifyHealth(me->GetMaxHealth() * 0.05f); - } - } - else - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_gluth(Creature* pCreature) -{ - return new boss_gluthAI (pCreature); -} - -void AddSC_boss_gluth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gluth"; - newscript->GetAI = &GetAI_boss_gluth; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/northrend/naxxramas/boss_gothik.cpp b/src/server/scripts/northrend/naxxramas/boss_gothik.cpp deleted file mode 100644 index d958ff24951..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_gothik.cpp +++ /dev/null @@ -1,582 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Yells -{ - SAY_SPEECH = -1533040, - SAY_KILL = -1533041, - SAY_DEATH = -1533042, - SAY_TELEPORT = -1533043 -}; -//Gothik -enum Spells -{ - SPELL_HARVEST_SOUL = 28679, - SPELL_SHADOW_BOLT = 29317, - H_SPELL_SHADOW_BOLT = 56405, - SPELL_INFORM_LIVE_TRAINEE = 27892, - SPELL_INFORM_LIVE_KNIGHT = 27928, - SPELL_INFORM_LIVE_RIDER = 27935, - SPELL_INFORM_DEAD_TRAINEE = 27915, - SPELL_INFORM_DEAD_KNIGHT = 27931, - SPELL_INFORM_DEAD_RIDER = 27937 -}; -enum Creatures -{ - MOB_LIVE_TRAINEE = 16124, - MOB_LIVE_KNIGHT = 16125, - MOB_LIVE_RIDER = 16126, - MOB_DEAD_TRAINEE = 16127, - MOB_DEAD_KNIGHT = 16148, - MOB_DEAD_RIDER = 16150, - MOB_DEAD_HORSE = 16149 -}; - -struct Waves { uint32 entry, time, mode; }; -// wave setups are not the same in heroic and normal difficulty, -// mode is 0 only normal, 1 both and 2 only heroic -// but this is handled in DoGothikSummon function -const Waves waves[] = -{ - {MOB_LIVE_TRAINEE, 20000, 1}, - {MOB_LIVE_TRAINEE, 20000, 1}, - {MOB_LIVE_TRAINEE, 10000, 1}, - {MOB_LIVE_KNIGHT, 10000, 1}, - {MOB_LIVE_TRAINEE, 15000, 1}, - {MOB_LIVE_KNIGHT, 5000, 1}, - {MOB_LIVE_TRAINEE, 20000, 1}, - {MOB_LIVE_TRAINEE, 0, 1}, - {MOB_LIVE_KNIGHT, 10000, 1}, - {MOB_LIVE_TRAINEE, 10000, 2}, - {MOB_LIVE_RIDER, 10000, 0}, - {MOB_LIVE_RIDER, 5000, 2}, - {MOB_LIVE_TRAINEE, 5000, 0}, - {MOB_LIVE_TRAINEE, 15000, 2}, - {MOB_LIVE_KNIGHT, 15000, 0}, - {MOB_LIVE_TRAINEE, 0, 0}, - {MOB_LIVE_RIDER, 10000, 1}, - {MOB_LIVE_KNIGHT, 10000, 1}, - {MOB_LIVE_TRAINEE, 10000, 0}, - {MOB_LIVE_RIDER, 10000, 2}, - {MOB_LIVE_TRAINEE, 0, 2}, - {MOB_LIVE_RIDER, 5000, 1}, - {MOB_LIVE_TRAINEE, 0, 2}, - {MOB_LIVE_KNIGHT, 5000, 1}, - {MOB_LIVE_RIDER, 0, 2}, - {MOB_LIVE_TRAINEE, 20000, 1}, - {MOB_LIVE_RIDER, 0, 1}, - {MOB_LIVE_KNIGHT, 0, 1}, - {MOB_LIVE_TRAINEE, 25000, 2}, - {MOB_LIVE_TRAINEE, 15000, 0}, - {MOB_LIVE_TRAINEE, 25000, 0}, - {0, 0, 1}, -}; - -#define POS_Y_GATE -3360.78f -#define POS_Y_WEST -3285.0f -#define POS_Y_EAST -3434.0f -#define POS_X_NORTH 2750.49f -#define POS_X_SOUTH 2633.84f - -#define IN_LIVE_SIDE(who) (who->GetPositionY() < POS_Y_GATE) - -enum Events -{ - EVENT_NONE, - EVENT_SUMMON, - EVENT_HARVEST, - EVENT_BOLT, - EVENT_TELEPORT -}; -enum Pos -{ - POS_LIVE = 6, - POS_DEAD = 5 -}; - -const Position PosSummonLive[POS_LIVE] = -{ - {2669.7, -3428.76, 268.56, 1.6}, - {2692.1, -3428.76, 268.56, 1.6}, - {2714.4, -3428.76, 268.56, 1.6}, - {2669.7, -3431.67, 268.56, 1.6}, - {2692.1, -3431.67, 268.56, 1.6}, - {2714.4, -3431.67, 268.56, 1.6}, -}; - -const Position PosSummonDead[POS_DEAD] = -{ - {2725.1, -3310.0, 268.85, 3.4}, - {2699.3, -3322.8, 268.60, 3.3}, - {2733.1, -3348.5, 268.84, 3.1}, - {2682.8, -3304.2, 268.85, 3.9}, - {2664.8, -3340.7, 268.23, 3.7}, -}; - -const float PosGroundLiveSide[4] = {2691.2, -3387.0, 267.68, 1.52}; -const float PosGroundDeadSide[4] = {2693.5, -3334.6, 267.68, 4.67}; -const float PosPlatform[4] = {2640.5, -3360.6, 285.26, 0}; - -// Predicate function to check that the r efzr unit is NOT on the same side as the source. -struct NotOnSameSide : public std::unary_function { - bool m_inLiveSide; - NotOnSameSide(Unit *pSource) : m_inLiveSide(IN_LIVE_SIDE(pSource)) {} - bool operator() (const Unit *pTarget) { - return (m_inLiveSide != IN_LIVE_SIDE(pTarget)); - } -}; - -struct boss_gothikAI : public BossAI -{ - boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK) {} - - uint32 waveCount; - typedef std::vector TriggerVct; - TriggerVct liveTrigger, deadTrigger; - bool mergedSides; - bool phaseTwo; - bool thirtyPercentReached; - - std::vector LiveTriggerGUID; - std::vector DeadTriggerGUID; - - void Reset() - { - LiveTriggerGUID.clear(); - DeadTriggerGUID.clear(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); - me->SetReactState(REACT_PASSIVE); - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); - _Reset(); - mergedSides = false; - phaseTwo = false; - thirtyPercentReached = false; - } - - void EnterCombat(Unit * /*who*/) - { - for (uint32 i = 0; i < POS_LIVE; ++i) - if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonLive[i])) - LiveTriggerGUID.push_back(trigger->GetGUID()); - for (uint32 i = 0; i < POS_DEAD; ++i) - if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonDead[i])) - DeadTriggerGUID.push_back(trigger->GetGUID()); - - if (LiveTriggerGUID.size() < POS_LIVE || DeadTriggerGUID.size() < POS_DEAD) - { - error_log("Script Gothik: cannot summon triggers!"); - EnterEvadeMode(); - return; - } - - _EnterCombat(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); - waveCount = 0; - events.ScheduleEvent(EVENT_SUMMON, 30000); - DoTeleportTo(PosPlatform); - DoScriptText(SAY_SPEECH, me); - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_READY); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == WORLD_TRIGGER) - summon->setActive(true); - else if (!mergedSides) - { - summon->AI()->DoAction(me->HasReactState(REACT_PASSIVE) ? 1 : 0); - summon->AI()->EnterEvadeMode(); - } - else - { - summon->AI()->DoAction(0); - summon->AI()->DoZoneInCombat(); - } - summons.Summon(summon); - } - - void SummonedCreatureDespawn(Creature *summon) - { - summons.Despawn(summon); - } - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*Killer*/) - { - LiveTriggerGUID.clear(); - DeadTriggerGUID.clear(); - _JustDied(); - DoScriptText(SAY_DEATH, me); - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); - } - - void DoGothikSummon(uint32 entry) - { - if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - { - switch(entry) - { - case MOB_LIVE_TRAINEE: - { - if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[0])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1); - if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[1])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1); - if (Creature *LiveTrigger2 = Unit::GetCreature(*me, LiveTriggerGUID[2])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger2, 1); - break; - } - case MOB_LIVE_KNIGHT: - { - if (Creature *LiveTrigger3 = Unit::GetCreature(*me, LiveTriggerGUID[3])) - DoSummon(MOB_LIVE_KNIGHT, LiveTrigger3, 1); - if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[5])) - DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1); - break; - } - case MOB_LIVE_RIDER: - { - if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1); - break; - } - } - } - else - { - switch(entry) - { - case MOB_LIVE_TRAINEE: - { - if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1); - if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1); - break; - } - case MOB_LIVE_KNIGHT: - { - if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1); - break; - } - case MOB_LIVE_RIDER: - { - if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1); - break; - } - } - } - } - - bool CheckGroupSplitted() - { - bool checklife = false; - bool checkdead = false; - - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->isAlive() && - i->getSource()->GetPositionX() <= POS_X_NORTH && - i->getSource()->GetPositionX() >= POS_X_SOUTH && - i->getSource()->GetPositionY() <= POS_Y_GATE && - i->getSource()->GetPositionY() >= POS_Y_EAST) - { - checklife = true; - } - else if (i->getSource() && i->getSource()->isAlive() && - i->getSource()->GetPositionX() <= POS_X_NORTH && - i->getSource()->GetPositionX() >= POS_X_SOUTH && - i->getSource()->GetPositionY() >= POS_Y_GATE && - i->getSource()->GetPositionY() <= POS_Y_WEST) - { - checkdead = true; - } - - if (checklife && checkdead) - return true; - } - } - } - - return false; - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - uint32 spellId = 0; - switch(spell->Id) - { - case SPELL_INFORM_LIVE_TRAINEE: spellId = SPELL_INFORM_DEAD_TRAINEE; break; - case SPELL_INFORM_LIVE_KNIGHT: spellId = SPELL_INFORM_DEAD_KNIGHT; break; - case SPELL_INFORM_LIVE_RIDER: spellId = SPELL_INFORM_DEAD_RIDER; break; - } - if (spellId && me->isInCombat()) - { - me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST); - if (Creature *pRandomDeadTrigger = Unit::GetCreature(*me, DeadTriggerGUID[rand() % POS_DEAD])) - me->CastSpell(pRandomDeadTrigger, spellId, true); - } - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (!me->isInCombat()) - return; - - switch(spell->Id) - { - case SPELL_INFORM_DEAD_TRAINEE: - DoSummon(MOB_DEAD_TRAINEE, pTarget, 0); - break; - case SPELL_INFORM_DEAD_KNIGHT: - DoSummon(MOB_DEAD_KNIGHT, pTarget, 0); - break; - case SPELL_INFORM_DEAD_RIDER: - DoSummon(MOB_DEAD_RIDER, pTarget, 1.0f); - DoSummon(MOB_DEAD_HORSE, pTarget, 1.0f); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateCombatState() || !CheckInRoom()) - return; - - events.Update(diff); - - if (!thirtyPercentReached && HealthBelowPct(30) && phaseTwo) - { - thirtyPercentReached = true; - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); - } - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SUMMON: - if (waves[waveCount].entry) - { - if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) - DoGothikSummon(waves[waveCount].entry); - else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) - DoGothikSummon(waves[waveCount].entry); - else if (waves[waveCount].mode == 1) - DoGothikSummon(waves[waveCount].entry); - - // if group is not splitted, open gate and merge both sides at ~ 2 minutes (wave 11) - if (waveCount == 11) - { - if (!CheckGroupSplitted()) - { - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); - summons.DoAction(0, 0); - summons.DoZoneInCombat(); - mergedSides = true; - } - } - - if (waves[waveCount].mode == 1) - events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); - else if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) - events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); - else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) - events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); - else - events.ScheduleEvent(EVENT_SUMMON, 0); - - ++waveCount; - } - else - { - phaseTwo = true; - DoScriptText(SAY_TELEPORT, me); - DoTeleportTo(PosGroundLiveSide); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - summons.DoAction(0, 0); - summons.DoZoneInCombat(); - events.ScheduleEvent(EVENT_BOLT, 1000); - events.ScheduleEvent(EVENT_HARVEST, urand(3000,15000)); - events.ScheduleEvent(EVENT_TELEPORT, 20000); - } - break; - case EVENT_BOLT: - DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BOLT, H_SPELL_SHADOW_BOLT)); - events.ScheduleEvent(EVENT_BOLT, 1000); - break; - case EVENT_HARVEST: - DoCast(me->getVictim(), SPELL_HARVEST_SOUL, true); - events.ScheduleEvent(EVENT_HARVEST, urand(20000,25000)); - break; - case EVENT_TELEPORT: - if (!thirtyPercentReached) - { - me->AttackStop(); - if (IN_LIVE_SIDE(me)) - { - DoTeleportTo(PosGroundDeadSide); - } - else - { - DoTeleportTo(PosGroundLiveSide); - } - - me->getThreatManager().resetAggro(NotOnSameSide(me)); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0)) - { - me->getThreatManager().addThreat(pTarget, 100.0f); - AttackStart(pTarget); - } - - events.ScheduleEvent(EVENT_TELEPORT, 20000); - } - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_gothik_minionAI : public CombatAI -{ - mob_gothik_minionAI(Creature *c) : CombatAI(c) - { - liveSide = IN_LIVE_SIDE(me); - } - - bool liveSide; - bool gateClose; - - bool isOnSameSide(const Unit *pWho) - { - return (liveSide == IN_LIVE_SIDE(pWho)); - } - - void DoAction(const int32 param) - { - gateClose = param; - } - - void DamageTaken(Unit *attacker, uint32 &damage) - { - if (gateClose && !isOnSameSide(attacker)) - damage = 0; - } - - void JustDied(Unit * /*killer*/) - { - if (me->isSummon()) - { - if (Unit *owner = CAST_SUM(me)->GetSummoner()) - CombatAI::JustDied(owner); - } - } - - void EnterEvadeMode() - { - if (!gateClose) - { - CombatAI::EnterEvadeMode(); - return; - } - - if (!_EnterEvadeMode()) - return; - - Map* pMap = me->GetMap(); - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->isAlive() && isOnSameSide(i->getSource())) - { - AttackStart(i->getSource()); - return; - } - } - } - } - - me->GetMotionMaster()->MoveIdle(); - Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (gateClose && (!isOnSameSide(me) || me->getVictim() && !isOnSameSide(me->getVictim()))) - { - EnterEvadeMode(); - return; - } - - CombatAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_boss_gothik(Creature* pCreature) -{ - return new boss_gothikAI (pCreature); -} - -CreatureAI* GetAI_mob_gothik_minion(Creature* pCreature) -{ - return new mob_gothik_minionAI (pCreature); -} - -void AddSC_boss_gothik() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gothik"; - newscript->GetAI = &GetAI_boss_gothik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_gothik_minion"; - newscript->GetAI = &GetAI_mob_gothik_minion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_grobbulus.cpp b/src/server/scripts/northrend/naxxramas/boss_grobbulus.cpp deleted file mode 100644 index 7df01e18483..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_grobbulus.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SPELL_BOMBARD_SLIME 28280 - -#define SPELL_POISON_CLOUD 28240 -#define SPELL_MUTATING_INJECTION 28169 -#define SPELL_SLIME_SPRAY RAID_MODE(28157,54364) -#define SPELL_BERSERK 26662 -#define SPELL_POISON_CLOUD_ADD 59116 - -#define EVENT_BERSERK 1 -#define EVENT_CLOUD 2 -#define EVENT_INJECT 3 -#define EVENT_SPRAY 4 - -#define MOB_FALLOUT_SLIME 16290 - -struct boss_grobbulusAI : public BossAI -{ - boss_grobbulusAI(Creature *c) : BossAI(c, BOSS_GROBBULUS) - { - me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_POISON_CLOUD_ADD, true); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - events.ScheduleEvent(EVENT_CLOUD, 15000); - events.ScheduleEvent(EVENT_INJECT, 20000); - events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure - events.ScheduleEvent(EVENT_BERSERK, 12*60000); - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (spell->Id == uint32(SPELL_SLIME_SPRAY)) - { - if (TempSummon *slime = me->SummonCreature(MOB_FALLOUT_SLIME, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) - DoZoneInCombat(slime); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CLOUD: - DoCastAOE(SPELL_POISON_CLOUD); - events.ScheduleEvent(EVENT_CLOUD, 15000); - return; - case EVENT_BERSERK: - DoCastAOE(SPELL_BERSERK); - return; - case EVENT_SPRAY: - DoCastAOE(SPELL_SLIME_SPRAY); - events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); - return; - case EVENT_INJECT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - if (!pTarget->HasAura(SPELL_MUTATING_INJECTION)) - DoCast(pTarget, SPELL_MUTATING_INJECTION); - events.ScheduleEvent(EVENT_INJECT, 8000 + 12000 * ((float)me->GetHealth() / me->GetMaxHealth())); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_grobbulus_poison_cloudAI : public Scripted_NoMovementAI -{ - npc_grobbulus_poison_cloudAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - Reset(); - } - - uint32 Cloud_Timer; - - void Reset() - { - Cloud_Timer = 1000; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void UpdateAI(const uint32 diff) - { - if (Cloud_Timer <= diff) - { - DoCast(me, SPELL_POISON_CLOUD_ADD); - Cloud_Timer = 10000; - } else Cloud_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_grobbulus(Creature* pCreature) -{ - return new boss_grobbulusAI (pCreature); -} - -CreatureAI* GetAI_npc_grobbulus_poison_cloud(Creature* pCreature) -{ - return new npc_grobbulus_poison_cloudAI(pCreature); -} - -void AddSC_boss_grobbulus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grobbulus"; - newscript->GetAI = &GetAI_boss_grobbulus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_grobbulus_poison_cloud"; - newscript->GetAI = &GetAI_npc_grobbulus_poison_cloud; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_heigan.cpp b/src/server/scripts/northrend/naxxramas/boss_heigan.cpp deleted file mode 100644 index 1de9c0e00c8..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_heigan.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SAY_AGGRO RAND(-1533109,-1533110,-1533111) -#define SAY_SLAY -1533112 -#define SAY_TAUNT RAND(-1533113,-1533114,-1533115,-1533116,-1533117) -#define SAY_DEATH -1533118 - -#define SPELL_SPELL_DISRUPTION 29310 -#define SPELL_DECREPIT_FEVER RAID_MODE(29998,55011) -#define SPELL_PLAGUE_CLOUD 29350 - -enum Events -{ - EVENT_NONE, - EVENT_DISRUPT, - EVENT_FEVER, - EVENT_ERUPT, - EVENT_PHASE, -}; - -enum Phases -{ - PHASE_FIGHT = 1, - PHASE_DANCE, -}; - -struct boss_heiganAI : public BossAI -{ - boss_heiganAI(Creature *c) : BossAI(c, BOSS_HEIGAN) {} - - uint32 eruptSection; - bool eruptDirection; - Phases phase; - - void KilledUnit(Unit* /*Victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_SLAY, me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO, me); - EnterPhase(PHASE_FIGHT); - } - - void EnterPhase(Phases newPhase) - { - phase = newPhase; - events.Reset(); - eruptSection = 3; - if (phase == PHASE_FIGHT) - { - events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000)); - events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000)); - events.ScheduleEvent(EVENT_PHASE, 90000); - events.ScheduleEvent(EVENT_ERUPT, 15000); - } - else - { - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o); - DoCastAOE(SPELL_PLAGUE_CLOUD); - events.ScheduleEvent(EVENT_PHASE, 45000); - events.ScheduleEvent(EVENT_ERUPT, 8000); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim() || !CheckInRoom()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_DISRUPT: - DoCastAOE(SPELL_SPELL_DISRUPTION); - events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000)); - break; - case EVENT_FEVER: - DoCastAOE(SPELL_DECREPIT_FEVER); - events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000)); - break; - case EVENT_PHASE: - // TODO : Add missing texts for both phase switches - EnterPhase(phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT); - break; - case EVENT_ERUPT: - instance->SetData(DATA_HEIGAN_ERUPT, eruptSection); - TeleportCheaters(); - - if (eruptSection == 0) - eruptDirection = true; - else if (eruptSection == 3) - eruptDirection = false; - - eruptDirection ? ++eruptSection : --eruptSection; - - events.ScheduleEvent(EVENT_ERUPT, phase == PHASE_FIGHT ? 10000 : 3000); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_heigan(Creature* pCreature) -{ - return new boss_heiganAI (pCreature); -} - -void AddSC_boss_heigan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_heigan"; - newscript->GetAI = &GetAI_boss_heigan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_highlord_mograine.cpp b/src/server/scripts/northrend/naxxramas/boss_highlord_mograine.cpp deleted file mode 100644 index 4eb72a3780e..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_highlord_mograine.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Highlord_Mograine -SD%Complete: 100 -SDComment: SCRIPT OBSOLETE -SDCategory: Naxxramas -EndScriptData */ - -#include "precompiled.h" - -//All horsemen -#define SPELL_SHIELDWALL 29061 -#define SPELL_BESERK 26662 - -// highlord mograine -#define SPELL_MARK_OF_MOGRAINE 28834 -#define SPELL_RIGHTEOUS_FIRE 28882 // Applied as a 25% chance on melee hit to proc. me->GetVictim() - -#define SAY_TAUNT1 "Enough prattling. Let them come! We shall grind their bones to dust." -#define SAY_TAUNT2 "Conserve your anger! Harness your rage! You will all have outlets for your frustration soon enough." -#define SAY_TAUNT3 "Life is meaningless. It is in death that we are truly tested." -#define SAY_AGGRO1 "You seek death?" -#define SAY_AGGRO2 "None shall pass!" -#define SAY_AGGRO3 "Be still!" -#define SAY_SLAY1 "You will find no peace in death." -#define SAY_SLAY2 "The master's will is done." -#define SAY_SPECIAL "Bow to the might of the Highlord!" -#define SAY_DEATH "I... am... released! Perhaps it's not too late to - noo! I need... more time..." - -#define SOUND_TAUNT1 8842 -#define SOUND_TAUNT2 8843 -#define SOUND_TAUNT3 8844 -#define SOUND_AGGRO1 8835 -#define SOUND_AGGRO2 8836 -#define SOUND_AGGRO3 8837 -#define SOUND_SLAY1 8839 -#define SOUND_SLAY2 8840 -#define SOUND_SPECIAL 8841 -#define SOUND_DEATH 8838 - -#define SPIRIT_OF_MOGRAINE 16775 - -struct TRINITY_DLL_DECL boss_highlord_mograineAI : public ScriptedAI -{ - boss_highlord_mograineAI(Creature *c) : ScriptedAI(c) {} - - uint32 Mark_Timer; - uint32 RighteousFire_Timer; - bool ShieldWall1; - bool ShieldWall2; - - void Reset() - { - Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. - RighteousFire_Timer = 2000; // applied approx 1 out of 4 attacks - ShieldWall1 = true; - ShieldWall2 = true; - } - - void InitialYell() - { - if (!me->isInCombat()) - { - switch(rand()%3) - { - case 0: - DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_AGGRO1); - break; - case 1: - DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_AGGRO2); - break; - case 2: - DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_AGGRO3); - break; - } - } - } - - void KilledUnit() - { - switch(rand()%2) - { - case 0: - DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_SLAY1); - break; - case 1: - DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_SLAY2); - break; - } - } - - void JustDied(Unit* Killer) - { - DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me, SOUND_DEATH); - } - - void Aggro(Unit *who) - { - InitialYell(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Mark of Mograine - if (Mark_Timer < diff) - { - DoCast(me->getVictim(),SPELL_MARK_OF_MOGRAINE); - Mark_Timer = 12000; - }else Mark_Timer -= diff; - - // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds - if (ShieldWall1 && (me->GetHealth()*100 / me->GetMaxHealth()) < 50) - { - if (ShieldWall1) - { - DoCast(me,SPELL_SHIELDWALL); - ShieldWall1 = false; - } - } - if (ShieldWall2 && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) - { - if (ShieldWall2) - { - DoCast(me,SPELL_SHIELDWALL); - ShieldWall2 = false; - } - } - - // Righteous Fire - if (RighteousFire_Timer < diff) - { - if (rand()%4 == 1) // 1/4 - { - DoCast(me->getVictim(),SPELL_RIGHTEOUS_FIRE); - } - RighteousFire_Timer = 2000; - }else RighteousFire_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_highlord_mograine(Creature* pCreature) -{ - return new boss_highlord_mograineAI (pCreature); -} - -void AddSC_boss_highlord_mograine() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_highlord_mograine"; - newscript->GetAI = &GetAI_boss_highlord_mograine; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/northrend/naxxramas/boss_kelthuzad.cpp b/src/server/scripts/northrend/naxxramas/boss_kelthuzad.cpp deleted file mode 100644 index bfcd0636298..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_kelthuzad.cpp +++ /dev/null @@ -1,706 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_KelThuzad -SD%Complete: 80% -SDComment: VERIFY SCRIPT -SDCategory: Naxxramas -EndScriptData */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Yells -{ - //when shappiron dies. dialog between kel and lich king (in this order) - SAY_SAPP_DIALOG1 = -1533084, //not used - SAY_SAPP_DIALOG2_LICH = -1533085, //not used - SAY_SAPP_DIALOG3 = -1533086, //not used - SAY_SAPP_DIALOG4_LICH = -1533087, //not used - SAY_SAPP_DIALOG5 = -1533088, //not used - SAY_CAT_DIED = -1533089, //when cat dies, not used - //when each of the 4 wing bosses dies - SAY_TAUNT1 = -1533090, //not used - SAY_TAUNT2 = -1533091, //not used - SAY_TAUNT3 = -1533092, //not used - SAY_TAUNT4 = -1533093, //not used - SAY_SUMMON_MINIONS = -1533105, //start of phase 1 - SAY_AGGRO_1 = -1533094, //start of phase 2 - SAY_AGGRO_2 = -1533095, - SAY_AGGRO_3 = -1533096, - SAY_SLAY_1 = -1533097, - SAY_SLAY_2 = -1533098, - SAY_DEATH = -1533099, - SAY_CHAIN_1 = -1533100, - SAY_CHAIN_2 = -1533101, - SAY_FROST_BLAST = -1533102, - SAY_SPECIAL_1 = -1533106, - SAY_SPECIAL_2 = -1533107, - SAY_SPECIAL_3 = -1533108, - SAY_REQUEST_AID = -1533103, //start of phase 3 - SAY_ANSWER_REQUEST = -1533104 //lich king answer -}; -enum Event -{ - EVENT_NONE, - EVENT_BOLT, - EVENT_NOVA, - EVENT_CHAIN, - EVENT_CHAINED_SPELL, - EVENT_DETONATE, - EVENT_FISSURE, - EVENT_BLAST, - - EVENT_WASTE, - EVENT_ABOMIN, - EVENT_WEAVER, - EVENT_ICECROWN, - EVENT_TRIGGER, - - EVENT_PHASE, -}; - -enum Spells -{ - SPELL_FROST_BOLT = 28478, - H_SPELL_FROST_BOLT = 55802, - SPELL_FROST_BOLT_AOE = 28479, - H_SPELL_FROST_BOLT_AOE = 55807, - SPELL_SHADOW_FISURE = 27810, - SPELL_VOID_BLAST = 27812, - SPELL_MANA_DETONATION = 27819, - SPELL_FROST_BLAST = 27808, - SPELL_CHAINS_OF_KELTHUZAD = 28410, //28408 script effect - SPELL_KELTHUZAD_CHANNEL = 29423, - SPELL_BERSERK = 28498, - - //spells for chained - //warlock - SPELL_CURSE_OF_AGONY = 47864, - SPELL_SHADOW_BOLT = 47809, - //shaman - SPELL_EARTH_SHOCK = 49231, - SPELL_HEALING_WAVE = 49273, - //mage - SPELL_FROST_FIREBOLT = 47610, - SPELL_ARCANE_MISSILES = 42846, - //rogue - SPELL_HEMORRHAGE = 48660, - SPELL_MUTILATE = 48666, - //paladin - SPELL_HOLY_SHOCK = 48825, - SPELL_HAMMER_OF_JUSTICE = 10308, - //priest - SPELL_VAMPIRIC_TOUCH = 48160, - SPELL_RENEW = 48068, - //hunter - SPELL_MULTI_SHOT = 49048, - SPELL_VOLLEY = 58434, - //warrior - SPELL_BLADESTORM = 46924, - SPELL_CLEAVE = 47520, - //druid - SPELL_MOONFIRE = 48463, - SPELL_LIFEBLOOM = 48451, - //death knight - SPELL_PLAGUE_STRIKE = 49921, - SPELL_HOWLING_BLAST = 51411, -}; - -enum Creatures -{ - NPC_WASTE = 16427, // Soldiers of the Frozen Wastes - NPC_ABOMINATION = 16428, // Unstoppable Abominations - NPC_WEAVER = 16429, // Soul Weavers - NPC_ICECROWN = 16441 // Guardians of Icecrown -}; - -const Position Pos[12] = -{ - {3783.272705, -5062.697266, 143.711203, 3.617599}, //LEFT_FAR - {3730.291260, -5027.239258, 143.956909, 4.461900}, //LEFT_MIDDLE - {3757.6, -5172.0, 143.7, 1.97}, //WINDOW_PORTAL05 - {3759.355225, -5174.128418, 143.802383, 2.170104}, //RIGHT_FAR - {3700.724365, -5185.123047, 143.928024, 1.309310}, //RIGHT_MIDDLE - {3700.86, -5181.29, 143.928024, 1.42}, //WINDOW_PORTAL04 - {3754.431396, -5080.727734, 142.036316, 3.736189}, //LEFT_FAR - {3724.396484, -5061.330566, 142.032700, 4.564785}, //LEFT_MIDDLE - {3732.02, -5028.53, 143.92, 4.49}, //WINDOW_PORTAL02 - {3687.571777, -5126.831055, 142.017807, 0.604023}, //RIGHT_FAR - {3707.990733, -5151.450195, 142.032562, 1.376855}, //RIGHT_MIDDLE - {3782.76, -5062.97, 143.79, 3.82}, //WINDOW_PORTAL03 -}; - -//creatures in corners -//Unstoppable Abominations -#define MAX_ABOMINATIONS 21 -const Position PosAbominations[MAX_ABOMINATIONS] = -{ - {3755.52, -5155.22, 143.480, 2.0}, - {3744.35, -5164.03, 143.590, 2.00}, - {3749.28, -5159.04, 143.190, 2.0}, - {3774.47, -5076.28, 143.528, 2.15912}, - {3765.94, -5074.15, 143.186, 3.77233}, - {3763.15, -5063.36, 143.694, 3.77233}, - {3737.81, -5045.69, 143.709, 4.9033}, - {3728.13, -5045.01, 143.355, 1.45069}, - {3721.56, -5048.35, 143.542, 1.45069}, - {3689.55, -5049.66, 143.637, 5.2104}, - {3681.71, -5053.03, 143.242, 2.47957}, - {3677.64, -5061.44, 143.358, 2.47957}, - {3654.2, -5090.87, 143.469, 1.0313}, - {3650.39, -5097.45, 143.496, 2.5047}, - {3658.7, -5103.59, 143.607, 3.3278}, - {3659.02, -5133.97, 143.624, 3.84538}, - {3666.33, -5139.34, 143.183, 3.84538}, - {3669.74, -5149.63, 143.678, 0.528643}, - {3695.53, -5169.53, 143.671, 2.11908}, - {3701.98, -5166.51, 143.395, 1.24257}, - {3709.62, -5169.15, 143.576, 5.97695}, -}; - -//Soldiers of the Frozen Wastes -#define MAX_WASTES 49 -const Position PosWastes[MAX_WASTES] = -{ - {3754.41, -5147.24, 143.204, 2.0}, - {3754.68, -5156.17, 143.418, 2.0}, - {3757.91, -5160.12, 143.503, 2.0}, - {3752.67, -5164.6, 143.395, 2.0}, - {3745.42, -5164.47, 143.565, 2.74587}, - {3741.2, -5155.92, 143.17, 5.29134}, - {3746.57, -5148.82, 143.176, 5.07772}, - {3778.14, -5070.1, 143.568, 3.16208}, - {3775.09, -5078.97, 143.65, 2.81022}, - {3773.54, -5083.47, 143.758, 3.21549}, - {3765, -5078.29, 143.176, 4.36688}, - {3766.94, -5072.63, 143.184, 5.27951}, - {3762.68, -5064.94, 143.635, 3.95297}, - {3769.9, -5059.94, 143.74, 3.36549}, - {3736.33, -5042.18, 143.643, 5.9471}, - {3727.51, -5040.58, 143.502, 0.871859}, - {3719.89, -5049.64, 143.58, 4.75172}, - {3720.69, -5044.43, 143.662, 1.87245}, - {3725.69, -5048.99, 143.363, 2.48271}, - {3732.33, -5054.01, 143.44, 3.59405}, - {3738.09, -5051.06, 143.718, 4.70931}, - {3682.76, -5063.5, 143.175, 0.636238}, - {3686.7, -5060.58, 143.18, 0.636238}, - {3682.45, -5057.21, 143.184, 5.61252}, - {3677.57, -5053.34, 143.369, 1.52531}, - {3677.3, -5062.26, 143.369, 2.73482}, - {3691.21, -5053.02, 143.421, 5.93218}, - {3685.22, -5053.34, 143.314, 4.70303}, - {3652.11, -5088.47, 143.555, 0.793317}, - {3648.23, -5093.21, 143.311, 1.18837}, - {3648.14, -5100.11, 143.632, 2.12221}, - {3653.88, -5099.7, 143.558, 3.04348}, - {3661.23, -5100.33, 143.42, 4.08335}, - {3663.49, -5092.77, 143.346, 4.47134}, - {3661.85, -5087.99, 143.571, 1.0148}, - {3664.56, -5149.01, 143.532, 0.0762528}, - {3665.01, -5142.04, 143.201, 1.72009}, - {3671.15, -5142.92, 143.174, 4.81535}, - {3670.18, -5134.38, 143.177, 5.37534}, - {3664.33, -5131.69, 143.262, 5.39576}, - {3658.21, -5133.63, 143.662, 1.3863}, - {3659.7, -5144.49, 143.363, 2.32328}, - {3705.71, -5179.63, 143.746, 1.06743}, - {3696.77, -5177.45, 143.759, 5.36748}, - {3700.97, -5173.13, 143.52, 3.26575}, - {3708.53, -5172.19, 143.573, 3.26575}, - {3712.49, -5167.62, 143.657, 5.63295}, - {3704.89, -5161.84, 143.239, 5.63295}, - {3695.66, -5164.63, 143.674, 1.54416}, -}; - -//Soul Weavers -#define MAX_WEAVERS 7 -const Position PosWeavers[MAX_WEAVERS] = -{ - {3752.45, -5168.35, 143.562, 1.6094}, - {3772.2, -5070.04, 143.329, 1.93686}, - {3732.28, -5032.88, 143.771, 3.08355}, - {3689.05, -5055.7, 143.172, 6.09554}, - {3649.45, -5093.17, 143.299, 2.51805}, - {3659.7, -5144.49, 143.363, 4.08806}, - {3704.71, -5175.96, 143.597, 3.36549}, -}; - -// predicate function to select not charmed target -struct NotCharmedTargetSelector : public std::unary_function { - NotCharmedTargetSelector() {} - - bool operator() (const Unit *pTarget) { - return (!pTarget->isCharmed()); - } -}; - -struct boss_kelthuzadAI : public BossAI -{ - boss_kelthuzadAI(Creature* c) : BossAI(c, BOSS_KELTHUZAD), spawns(c) - { - uiFaction = me->getFaction(); - } - - uint32 Phase; - uint32 uiGuardiansOfIcecrownTimer; - uint32 uiFaction; - - uint8 nGuardiansOfIcecrownCount; - uint8 nAbomination; - uint8 nWeaver; - - std::map chained; - - uint64 PortalsGUID[4]; - uint64 KTTriggerGUID; - - SummonList spawns; // adds spawn by the trigger. kept in separated list (i.e. not in summons) - - void Reset() - { - _Reset(); - - PortalsGUID[0] = PortalsGUID[1] = PortalsGUID[2] = PortalsGUID[3] = 0; - KTTriggerGUID = 0; - - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - std::map::const_iterator itr; - for (itr = chained.begin(); itr != chained.end(); ++itr) - { - if (Player* charmed = Unit::GetPlayer((*itr).first)) - charmed->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); - } - - chained.clear(); - spawns.DespawnAll(); - - FindGameObjects(); - - if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID)) - { - pKTTrigger->ResetDoorOrButton(); - pKTTrigger->SetPhaseMask(1, true); - } - - for (uint8 i = 0; i <= 3; ++i) - { - if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) - { - if (!((pPortal->getLootState() == GO_READY) || (pPortal->getLootState() == GO_NOT_READY))) - pPortal->ResetDoorOrButton(); - } - } - - nGuardiansOfIcecrownCount = 0; - uiGuardiansOfIcecrownTimer = 5000; //5 seconds for summoning each Guardian of Icecrown in phase 3 - - Phase = 0; - nAbomination = 0; - nWeaver = 0; - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - - std::map::const_iterator itr; - for (itr = chained.begin(); itr != chained.end(); ++itr) - { - if (Player* pPlayer = Unit::GetPlayer((*itr).first)) - pPlayer->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); - } - chained.clear(); - } - - void EnterCombat(Unit* /*who*/) - { - me->setFaction(uiFaction); - - _EnterCombat(); - FindGameObjects(); - for (uint8 i = 0; i <= 3; ++i) - { - if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) - pPortal->ResetDoorOrButton(); - } - DoCast(me, SPELL_KELTHUZAD_CHANNEL, false); - DoScriptText(SAY_SUMMON_MINIONS, me); - Phase = 1; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4); - events.ScheduleEvent(EVENT_TRIGGER, 5000); - events.ScheduleEvent(EVENT_WASTE, 15000); - events.ScheduleEvent(EVENT_ABOMIN, 30000); - events.ScheduleEvent(EVENT_WEAVER, 50000); - events.ScheduleEvent(EVENT_PHASE, 228000); - } - - void FindGameObjects() - { - PortalsGUID[0] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL01) : 0; - PortalsGUID[1] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL02) : 0; - PortalsGUID[2] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL03) : 0; - PortalsGUID[3] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL04) : 0; - KTTriggerGUID = instance ? instance->GetData64(DATA_KELTHUZAD_TRIGGER) : 0; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateCombatState()) - return; - - events.Update(diff); - - if (Phase == 1) - { - while (uint32 eventId = events.GetEvent()) - { - switch(eventId) - { - case EVENT_WASTE: - DoSummon(NPC_WASTE, Pos[RAND(0,3,6,9)]); - events.RepeatEvent(urand(2000,5000)); - break; - case EVENT_ABOMIN: - if (nAbomination < 8) - { - DoSummon(NPC_ABOMINATION, Pos[RAND(1,4,7,10)]); - nAbomination++; - events.RepeatEvent(20000); - } - else - events.PopEvent(); - break; - case EVENT_WEAVER: - if (nWeaver < 8) - { - DoSummon(NPC_WEAVER, Pos[RAND(0,3,6,9)]); - nWeaver++; - events.RepeatEvent(25000); - } - else - events.PopEvent(); - break; - case EVENT_TRIGGER: - if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID)) - pKTTrigger->SetPhaseMask(2, true); - events.PopEvent(); - break; - case EVENT_PHASE: - events.Reset(); - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - spawns.DespawnAll(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - me->CastStop(); - - DoStartMovement(me->getVictim()); - events.ScheduleEvent(EVENT_BOLT, urand(5000,10000)); - events.ScheduleEvent(EVENT_NOVA, 15000); - events.ScheduleEvent(EVENT_DETONATE, urand(30000,40000)); - events.ScheduleEvent(EVENT_FISSURE, urand(10000,30000)); - events.ScheduleEvent(EVENT_BLAST, urand(60000,120000)); - if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - events.ScheduleEvent(EVENT_CHAIN, urand(30000,60000)); - Phase = 2; - break; - default: - events.PopEvent(); - break; - } - } - } - else - { - //start phase 3 when we are 45% health - if (Phase != 3) - { - if (HealthBelowPct(45)) - { - Phase = 3 ; - DoScriptText(SAY_REQUEST_AID, me); - //here Lich King should respond to KelThuzad but I don't know which Creature to make talk - //so for now just make Kelthuzad says it. - DoScriptText(SAY_ANSWER_REQUEST, me); - - for (uint8 i = 0; i <= 3; ++i) - { - if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) - { - if (pPortal->getLootState() == GO_READY) - pPortal->UseDoorOrButton(); - } - } - } - } - else if (nGuardiansOfIcecrownCount < RAID_MODE(2,4)) - { - if (uiGuardiansOfIcecrownTimer <= diff) - { - // TODO : Add missing text - if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2,5,8,11)])) - pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2); - ++nGuardiansOfIcecrownCount; - uiGuardiansOfIcecrownTimer = 5000; - } - else uiGuardiansOfIcecrownTimer -= diff; - } - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (uint32 eventId = events.GetEvent()) - { - switch(eventId) - { - case EVENT_BOLT: - DoCastVictim(RAID_MODE(SPELL_FROST_BOLT,H_SPELL_FROST_BOLT)); - events.RepeatEvent(urand(5000,10000)); - break; - case EVENT_NOVA: - DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE,H_SPELL_FROST_BOLT_AOE)); - events.RepeatEvent(urand(15000,30000)); - break; - case EVENT_CHAIN: - { - uint32 count = urand(1,3); - for (uint8 i = 1; i <= count; i++) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true); - if (pTarget && !pTarget->isCharmed() && (chained.find(pTarget->GetGUID()) == chained.end())) - { - DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD); - float scale = pTarget->GetFloatValue(OBJECT_FIELD_SCALE_X); - chained.insert(std::make_pair(pTarget->GetGUID(), scale)); - pTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2); - events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm - } - } - if (!chained.empty()) - DoScriptText(RAND(SAY_CHAIN_1,SAY_CHAIN_2), me); - events.RepeatEvent(urand(100000,180000)); - break; - } - case EVENT_CHAINED_SPELL: - { - std::map::iterator itr; - for (itr = chained.begin(); itr != chained.end();) - { - if (Unit* player = Unit::GetPlayer((*itr).first)) - { - if (!player->isCharmed()) - { - player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); - std::map::iterator next = itr; - ++next; - chained.erase(itr); - itr = next; - continue; - } - - if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector())) - { - switch(player->getClass()) - { - case CLASS_DRUID: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_MOONFIRE, false); - else - player->CastSpell(me, SPELL_LIFEBLOOM, false); - break; - case CLASS_HUNTER: - player->CastSpell(pTarget, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false); - break; - case CLASS_MAGE: - player->CastSpell(pTarget, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false); - break; - case CLASS_WARLOCK: - player->CastSpell(pTarget, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true); - break; - case CLASS_WARRIOR: - player->CastSpell(pTarget, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false); - break; - case CLASS_PALADIN: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_HAMMER_OF_JUSTICE, false); - else - player->CastSpell(me, SPELL_HOLY_SHOCK, false); - break; - case CLASS_PRIEST: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_VAMPIRIC_TOUCH, false); - else - player->CastSpell(me, SPELL_RENEW, false); - break; - case CLASS_SHAMAN: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_EARTH_SHOCK, false); - else - player->CastSpell(me, SPELL_HEALING_WAVE, false); - break; - case CLASS_ROGUE: - player->CastSpell(pTarget, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false); - break; - case CLASS_DEATH_KNIGHT: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_PLAGUE_STRIKE, true); - else - player->CastSpell(pTarget, SPELL_HOWLING_BLAST, true); - break; - } - } - } - ++itr; - } - - if (chained.empty()) - events.PopEvent(); - else - events.RepeatEvent(5000); - - break; - } - case EVENT_DETONATE: - { - std::vector unitList; - std::list *threatList = &me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr) - { - if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER - && (*itr)->getTarget()->getPowerType() == POWER_MANA - && (*itr)->getTarget()->GetPower(POWER_MANA)) - unitList.push_back((*itr)->getTarget()); - } - - if (!unitList.empty()) - { - std::vector::const_iterator itr = unitList.begin(); - advance(itr, rand()%unitList.size()); - DoCast(*itr, SPELL_MANA_DETONATION); - DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2,SAY_SPECIAL_3), me); - } - - events.RepeatEvent(urand(20000,50000)); - break; - } - case EVENT_FISSURE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_FISURE); - events.RepeatEvent(urand(10000,45000)); - break; - case EVENT_BLAST: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1,0), 0, true)) - DoCast(pTarget, SPELL_FROST_BLAST); - if (rand()%2) - DoScriptText(SAY_FROST_BLAST, me); - events.RepeatEvent(urand(30000,90000)); - break; - default: - events.PopEvent(); - break; - } - } - - DoMeleeAttackIfReady(); - } - } -}; - -CreatureAI* GetAI_boss_kelthuzadAI(Creature* pCreature) -{ - return new boss_kelthuzadAI (pCreature); -} - -bool AreaTrigger_at_kelthuzad_center(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - if (pPlayer->isGameMaster()) - return false; - - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (!pInstance || pInstance->IsEncounterInProgress() || pInstance->GetBossState(BOSS_KELTHUZAD) == DONE) - return false; - - Creature* pKelthuzad = CAST_CRE(Unit::GetUnit(*pPlayer, pInstance->GetData64(DATA_KELTHUZAD))); - if (!pKelthuzad) - return false; - - boss_kelthuzadAI* pKelthuzadAI = CAST_AI(boss_kelthuzadAI, pKelthuzad->AI()); - if (!pKelthuzadAI) - return false; - - pKelthuzadAI->AttackStart(pPlayer); - if (GameObject* trigger = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_TRIGGER))) - { - if (trigger->getLootState() == GO_READY) - trigger->UseDoorOrButton(); - - // Note: summon must be done by trigger and not by KT. - // Otherwise, they attack immediately as KT is in combat. - for (uint8 i = 0; i <= MAX_ABOMINATIONS; ++i) - { - if (Creature* sum = trigger->SummonCreature(NPC_ABOMINATION, PosAbominations[i])) - { - pKelthuzadAI->spawns.Summon(sum); - sum->GetMotionMaster()->MoveRandom(9.0f); - sum->SetReactState(REACT_DEFENSIVE); - } - } - for (uint8 i = 0; i <= MAX_WASTES; ++i) - { - if (Creature* sum = trigger->SummonCreature(NPC_WASTE, PosWastes[i])) - { - pKelthuzadAI->spawns.Summon(sum); - sum->GetMotionMaster()->MoveRandom(5.0f); - sum->SetReactState(REACT_DEFENSIVE); - } - } - for (uint8 i = 0; i <= MAX_WEAVERS; ++i) - { - if (Creature* sum = trigger->SummonCreature(NPC_WEAVER, PosWeavers[i])) - { - pKelthuzadAI->spawns.Summon(sum); - sum->GetMotionMaster()->MoveRandom(9.0f); - sum->SetReactState(REACT_DEFENSIVE); - } - } - } - - return true; -} - -void AddSC_boss_kelthuzad() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kelthuzad"; - newscript->GetAI = &GetAI_boss_kelthuzadAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_kelthuzad_center"; - newscript->pAreaTrigger = &AreaTrigger_at_kelthuzad_center; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_loatheb.cpp b/src/server/scripts/northrend/naxxramas/boss_loatheb.cpp deleted file mode 100644 index 0b0c8f5e4c5..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_loatheb.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Spells -{ - SPELL_NECROTIC_AURA = 55593, - SPELL_SUMMON_SPORE = 29234, - SPELL_DEATHBLOOM = 29865, - H_SPELL_DEATHBLOOM = 55053, - SPELL_INEVITABLE_DOOM = 29204, - H_SPELL_INEVITABLE_DOOM = 55052 -}; - -enum Events -{ - EVENT_NONE, - EVENT_AURA, - EVENT_BLOOM, - EVENT_DOOM, -}; - -struct boss_loathebAI : public BossAI -{ - boss_loathebAI(Creature *c) : BossAI(c, BOSS_LOATHEB) {} - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - events.ScheduleEvent(EVENT_AURA, 10000); - events.ScheduleEvent(EVENT_BLOOM, 5000); - events.ScheduleEvent(EVENT_DOOM, 120000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_AURA: - DoCastAOE(SPELL_NECROTIC_AURA); - events.ScheduleEvent(EVENT_AURA, 20000); - break; - case EVENT_BLOOM: - // TODO : Add missing text - DoCastAOE(SPELL_SUMMON_SPORE, true); - DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM,H_SPELL_DEATHBLOOM)); - events.ScheduleEvent(EVENT_BLOOM, 30000); - break; - case EVENT_DOOM: - DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM,H_SPELL_INEVITABLE_DOOM)); - events.ScheduleEvent(EVENT_DOOM, events.GetTimer() < 5*60000 ? 30000 : 15000); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_loatheb(Creature* pCreature) -{ - return new boss_loathebAI (pCreature); -} - -enum SporeSpells -{ - SPELL_FUNGAL_CREEP = 29232 -}; - -struct mob_loatheb_sporeAI : public ScriptedAI -{ - mob_loatheb_sporeAI(Creature *c) : ScriptedAI(c) {} - - void JustDied(Unit* killer) - { - DoCast(killer, SPELL_FUNGAL_CREEP); - } -}; - -CreatureAI* GetAI_mob_loatheb_spore(Creature* pCreature) -{ - return new mob_loatheb_sporeAI (pCreature); -} - -void AddSC_boss_loatheb() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_loatheb"; - newscript->GetAI = &GetAI_boss_loatheb; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_loatheb_spore"; - newscript->GetAI = &GetAI_mob_loatheb_spore; - newscript->RegisterSelf(); - - // Fungal Creep - //GetAISpellInfo(29232)->condition = AICOND_DIE; -} - diff --git a/src/server/scripts/northrend/naxxramas/boss_maexxna.cpp b/src/server/scripts/northrend/naxxramas/boss_maexxna.cpp deleted file mode 100644 index 71d9cb86102..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_maexxna.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Spells -{ - SPELL_WEB_WRAP = 28622, - SPELL_WEB_SPRAY_10 = 29484, - SPELL_WEB_SPRAY_25 = 54125, - SPELL_POISON_SHOCK_10 = 28741, - SPELL_POISON_SHOCK_25 = 54122, - SPELL_NECROTIC_POISON_10 = 28776, - SPELL_NECROTIC_POISON_25 = 54121, - SPELL_FRENZY_10 = 54123, - SPELL_FRENZY_25 = 54124, -}; - -enum Creatures -{ - MOB_WEB_WRAP = 16486, - MOB_SPIDERLING = 17055, -}; - -#define MAX_POS_WRAP 3 -const Position PosWrap[MAX_POS_WRAP] = -{ - {3546.796, -3869.082, 296.450, 0.0}, - {3531.271, -3847.424, 299.450, 0.0}, - {3497.067, -3843.384, 302.384, 0.0}, -}; - -enum Events -{ - EVENT_NONE, - EVENT_SPRAY, - EVENT_SHOCK, - EVENT_POISON, - EVENT_WRAP, - EVENT_SUMMON, - EVENT_FRENZY, -}; - -struct boss_maexxnaAI : public BossAI -{ - boss_maexxnaAI(Creature *c) : BossAI(c, BOSS_MAEXXNA) {} - - bool enraged; - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - enraged = false; - events.ScheduleEvent(EVENT_WRAP, 20000); - events.ScheduleEvent(EVENT_SPRAY, 40000); - events.ScheduleEvent(EVENT_SHOCK, urand(5000,10000)); - events.ScheduleEvent(EVENT_POISON, urand(10000,15000)); - events.ScheduleEvent(EVENT_SUMMON, 30000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim() || !CheckInRoom()) - return; - - if (!enraged && HealthBelowPct(30)) - { - enraged = true; - events.ScheduleEvent(EVENT_FRENZY, 0); // will be cast immediately - } - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_WRAP: - // TODO : Add missing text - for (uint8 i = 0; i < RAID_MODE(1,2); ++i) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP)) - { - pTarget->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25)); - uint8 pos = rand()%MAX_POS_WRAP; - pTarget->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20); - if (Creature *wrap = DoSummon(MOB_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN)) - wrap->AI()->SetGUID(pTarget->GetGUID()); - } - } - events.ScheduleEvent(EVENT_WRAP, 40000); - break; - case EVENT_SPRAY: - DoCastAOE(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25)); - events.ScheduleEvent(EVENT_SPRAY, 40000); - break; - case EVENT_SHOCK: - DoCastAOE(RAID_MODE(SPELL_POISON_SHOCK_10,SPELL_POISON_SHOCK_25)); - events.ScheduleEvent(EVENT_SHOCK, urand(10000,20000)); - break; - case EVENT_POISON: - DoCast(me->getVictim(), RAID_MODE(SPELL_NECROTIC_POISON_10,SPELL_NECROTIC_POISON_25)); - events.ScheduleEvent(EVENT_POISON, urand(10000, 20000)); - break; - case EVENT_FRENZY: - DoCast(me, RAID_MODE(SPELL_FRENZY_10,SPELL_FRENZY_25), true); - events.ScheduleEvent(EVENT_FRENZY, 600000); - break; - case EVENT_SUMMON: - // TODO : Add missing text - uint8 amount = urand(8,10); - for (uint8 i = 0; i < amount; ++i) - DoSummon(MOB_SPIDERLING, me, 0, TEMPSUMMON_CORPSE_DESPAWN); - events.ScheduleEvent(EVENT_SUMMON, 40000); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_webwrapAI : public NullCreatureAI -{ - mob_webwrapAI(Creature *c) : NullCreatureAI(c), victimGUID(0) {} - - uint64 victimGUID; - - void SetGUID(const uint64 &guid, int32 /*param*/) - { - victimGUID = guid; - if (me->m_spells[0] && victimGUID) - if (Unit *victim = Unit::GetUnit(*me, victimGUID)) - victim->CastSpell(victim, me->m_spells[0], true, NULL, NULL, me->GetGUID()); - } - - void JustDied(Unit * /*killer*/) - { - if (me->m_spells[0] && victimGUID) - if (Unit *victim = Unit::GetUnit(*me, victimGUID)) - victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID()); - } -}; - -CreatureAI* GetAI_boss_maexxna(Creature* pCreature) -{ - return new boss_maexxnaAI (pCreature); -} - -CreatureAI* GetAI_mob_webwrap(Creature* pCreature) -{ - return new mob_webwrapAI (pCreature); -} - -void AddSC_boss_maexxna() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_maexxna"; - newscript->GetAI = &GetAI_boss_maexxna; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_webwrap"; - newscript->GetAI = &GetAI_mob_webwrap; - newscript->RegisterSelf(); - -} - diff --git a/src/server/scripts/northrend/naxxramas/boss_noth.cpp b/src/server/scripts/northrend/naxxramas/boss_noth.cpp deleted file mode 100644 index b0cd4018955..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_noth.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SAY_AGGRO RAND(-1533075,-1533076,-1533077) -#define SAY_SUMMON -1533078 -#define SAY_SLAY RAND(-1533079,-1533080) -#define SAY_DEATH -1533081 - -#define SOUND_DEATH 8848 - -#define SPELL_CURSE_PLAGUEBRINGER RAID_MODE(29213,54835) -#define SPELL_BLINK RAND(29208,29209,29210,29211) -#define SPELL_CRIPPLE RAID_MODE(29212,54814) -#define SPELL_TELEPORT 29216 - -#define MOB_WARRIOR 16984 -#define MOB_CHAMPION 16983 -#define MOB_GUARDIAN 16981 - -// Teleport position of Noth on his balcony -#define TELE_X 2631.370 -#define TELE_Y -3529.680 -#define TELE_Z 274.040 -#define TELE_O 6.277 - -#define MAX_SUMMON_POS 5 - -const float SummonPos[MAX_SUMMON_POS][4] = -{ - {2728.12, -3544.43, 261.91, 6.04}, - {2729.05, -3544.47, 261.91, 5.58}, - {2728.24, -3465.08, 264.20, 3.56}, - {2704.11, -3456.81, 265.53, 4.51}, - {2663.56, -3464.43, 262.66, 5.20}, -}; - -enum Events -{ - EVENT_NONE, - EVENT_BERSERK, - EVENT_CURSE, - EVENT_BLINK, - EVENT_WARRIOR, - EVENT_BALCONY, - EVENT_WAVE, - EVENT_GROUND, -}; - -struct boss_nothAI : public BossAI -{ - boss_nothAI(Creature *c) : BossAI(c, BOSS_NOTH) {} - - uint32 waveCount, balconyCount; - - void Reset() - { - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - _Reset(); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO, me); - balconyCount = 0; - EnterPhaseGround(); - } - - void EnterPhaseGround() - { - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoZoneInCombat(); - if (me->getThreatManager().isThreatListEmpty()) - EnterEvadeMode(); - else - { - events.ScheduleEvent(EVENT_BALCONY, 110000); - events.ScheduleEvent(EVENT_CURSE, 10000+rand()%15000); - events.ScheduleEvent(EVENT_WARRIOR, 30000); - if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - events.ScheduleEvent(EVENT_BLINK, 20000 + rand()%20000); - } - } - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_SLAY, me); - } - - void JustSummoned(Creature *summon) - { - summons.Summon(summon); - summon->setActive(true); - summon->AI()->DoZoneInCombat(); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - } - - void SummonUndead(uint32 entry, uint32 num) - { - for (uint32 i = 0; i < num; ++i) - { - uint32 pos = rand()%MAX_SUMMON_POS; - me->SummonCreature(entry, SummonPos[pos][0], SummonPos[pos][1], SummonPos[pos][2], - SummonPos[pos][3], TEMPSUMMON_CORPSE_DESPAWN, 60000); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateCombatState() || !CheckInRoom()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CURSE: - DoCastAOE(SPELL_CURSE_PLAGUEBRINGER); - events.ScheduleEvent(EVENT_CURSE, 50000 + rand()%10000); - return; - case EVENT_WARRIOR: - DoScriptText(SAY_SUMMON, me); - SummonUndead(MOB_WARRIOR, RAID_MODE(2,3)); - events.ScheduleEvent(EVENT_WARRIOR, 30000); - return; - case EVENT_BLINK: - DoCastAOE(SPELL_CRIPPLE, true); - DoCastAOE(SPELL_BLINK); - DoResetThreat(); - events.ScheduleEvent(EVENT_BLINK, 40000); - return; - case EVENT_BALCONY: - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->AttackStop(); - me->RemoveAllAuras(); - me->NearTeleportTo(TELE_X, TELE_Y, TELE_Z, TELE_O); - events.Reset(); - events.ScheduleEvent(EVENT_WAVE, 2000 + rand()%3000); - waveCount = 0; - return; - case EVENT_WAVE: - DoScriptText(SAY_SUMMON, me); - switch(balconyCount) - { - case 0: SummonUndead(MOB_CHAMPION, RAID_MODE(2,4)); break; - case 1: SummonUndead(MOB_CHAMPION, RAID_MODE(1,2)); - SummonUndead(MOB_GUARDIAN, RAID_MODE(1,2)); break; - case 2: SummonUndead(MOB_GUARDIAN, RAID_MODE(2,4)); break; - default:SummonUndead(MOB_CHAMPION, RAID_MODE(5,10)); - SummonUndead(MOB_GUARDIAN, RAID_MODE(5,10));break; - } - ++waveCount; - events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, 30000 + rand()%15000); - return; - case EVENT_GROUND: - { - ++balconyCount; - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o); - events.ScheduleEvent(EVENT_BALCONY, 110000); - EnterPhaseGround(); - return; - } - } - } - - if (me->HasReactState(REACT_AGGRESSIVE)) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_noth(Creature* pCreature) -{ - return new boss_nothAI (pCreature); -} - -void AddSC_boss_noth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_noth"; - newscript->GetAI = &GetAI_boss_noth; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_patchwerk.cpp b/src/server/scripts/northrend/naxxramas/boss_patchwerk.cpp deleted file mode 100644 index e4472b299ce..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_patchwerk.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Spells -{ - SPELL_HATEFUL_STRIKE = 41926, - H_SPELL_HATEFUL_STRIKE = 59192, - SPELL_FRENZY = 28131, - SPELL_BERSERK = 26662, - SPELL_SLIME_BOLT = 32309, -}; - -enum Yells -{ - SAY_AGGRO_1 = -1533017, - SAY_AGGRO_2 = -1533018, - SAY_SLAY = -1533019, - SAY_DEATH = -1533020, - EMOTE_BERSERK = -1533021, - EMOTE_ENRAGE = -1533022, -}; - -enum Events -{ - EVENT_NONE, - EVENT_BERSERK, - EVENT_HATEFUL, - EVENT_SLIME -}; - -enum -{ - ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT = 10286, -}; - -struct boss_patchwerkAI : public BossAI -{ - boss_patchwerkAI(Creature *c) : BossAI(c, BOSS_PATCHWERK) {} - - bool Enraged; - - void Reset() - { - _Reset(); - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); - } - - void KilledUnit(Unit* /*Victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_SLAY, me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - Enraged = false; - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me); - events.ScheduleEvent(EVENT_HATEFUL, 1200); - events.ScheduleEvent(EVENT_BERSERK, 360000); - - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_HATEFUL: - { - //Cast Hateful strike on the player with the highest - //amount of HP within melee distance - uint32 MostHP = 0; - Unit* pMostHPTarget = NULL; - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit *pTarget = (*i)->getTarget(); - if (pTarget->isAlive() && pTarget->GetHealth() > MostHP && me->IsWithinMeleeRange(pTarget)) - { - MostHP = pTarget->GetHealth(); - pMostHPTarget = pTarget; - } - } - - if (pMostHPTarget) - DoCast(pMostHPTarget, RAID_MODE(SPELL_HATEFUL_STRIKE,H_SPELL_HATEFUL_STRIKE), true); - - events.ScheduleEvent(EVENT_HATEFUL, 1200); - break; - } - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK, true); - DoScriptText(EMOTE_BERSERK, me); - events.ScheduleEvent(EVENT_SLIME, 2000); - break; - case EVENT_SLIME: - DoCast(me->getVictim(), SPELL_SLIME_BOLT); - events.ScheduleEvent(EVENT_SLIME, 2000); - break; - } - } - - if (!Enraged && HealthBelowPct(5)) - { - DoCast(me, SPELL_FRENZY, true); - DoScriptText(EMOTE_ENRAGE, me); - Enraged = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_patchwerk(Creature* pCreature) -{ - return new boss_patchwerkAI (pCreature); -} - -void AddSC_boss_patchwerk() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_patchwerk"; - newscript->GetAI = &GetAI_boss_patchwerk; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_razuvious.cpp b/src/server/scripts/northrend/naxxramas/boss_razuvious.cpp deleted file mode 100644 index d507df86e83..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_razuvious.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -//Razuvious - NO TEXT sound only -//8852 aggro01 - Hah hah, I'm just getting warmed up! -//8853 aggro02 Stand and fight! -//8854 aggro03 Show me what you've got! -//8861 slay1 - You should've stayed home! -//8863 slay2- -//8858 cmmnd3 - You disappoint me, students! -//8855 cmmnd1 - Do as I taught you! -//8856 cmmnd2 - Show them no mercy! -//8859 cmmnd4 - The time for practice is over! Show me what you've learned! -//8861 Sweep the leg! Do you have a problem with that? -//8860 death - An honorable... death... -//8947 - Aggro Mixed? - ? - -#define SOUND_AGGRO RAND(8852,8853,8854) -#define SOUND_SLAY RAND(8861,8863) -#define SOUND_COMMND RAND(8855,8856,8858,8859,8861) -#define SOUND_DEATH 8860 -#define SOUND_AGGROMIX 8847 - -#define SPELL_UNBALANCING_STRIKE 26613 -#define SPELL_DISRUPTING_SHOUT RAID_MODE(29107,55543) -#define SPELL_JAGGED_KNIFE 55550 -#define SPELL_HOPELESS 29125 - -enum Events -{ - EVENT_NONE, - EVENT_STRIKE, - EVENT_SHOUT, - EVENT_KNIFE, - EVENT_COMMAND, -}; - -struct boss_razuviousAI : public BossAI -{ - boss_razuviousAI(Creature *c) : BossAI(c, BOSS_RAZUVIOUS) {} - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%3)) - DoPlaySoundToSet(me, SOUND_SLAY); - } - - void DamageTaken(Unit* pDone_by, uint32& uiDamage) - { - // Damage done by the controlled Death Knight understudies should also count toward damage done by players - if (pDone_by->GetTypeId() == TYPEID_UNIT && (pDone_by->GetEntry() == 16803 || pDone_by->GetEntry() == 29941)) - { - me->LowerPlayerDamageReq(uiDamage); - } - } - - void JustDied(Unit* /*killer*/) - { - _JustDied(); - DoPlaySoundToSet(me, SOUND_DEATH); - me->CastSpell(me, SPELL_HOPELESS, true); // TODO: this may affect other creatures - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoPlaySoundToSet(me, SOUND_AGGRO); - events.ScheduleEvent(EVENT_STRIKE, 30000); - events.ScheduleEvent(EVENT_SHOUT, 25000); - events.ScheduleEvent(EVENT_COMMAND, 40000); - events.ScheduleEvent(EVENT_KNIFE, 10000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_STRIKE: - DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE); - events.ScheduleEvent(EVENT_STRIKE, 30000); - return; - case EVENT_SHOUT: - DoCastAOE(SPELL_DISRUPTING_SHOUT); - events.ScheduleEvent(EVENT_SHOUT, 25000); - return; - case EVENT_KNIFE: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) - DoCast(pTarget, SPELL_JAGGED_KNIFE); - events.ScheduleEvent(EVENT_KNIFE, 10000); - return; - case EVENT_COMMAND: - DoPlaySoundToSet(me, SOUND_COMMND); - events.ScheduleEvent(EVENT_COMMAND, 40000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_razuvious(Creature* pCreature) -{ - return new boss_razuviousAI (pCreature); -} - -void AddSC_boss_razuvious() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_razuvious"; - newscript->GetAI = &GetAI_boss_razuvious; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/boss_sapphiron.cpp b/src/server/scripts/northrend/naxxramas/boss_sapphiron.cpp deleted file mode 100644 index d75b3ab78b0..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_sapphiron.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define EMOTE_BREATH -1533082 -#define EMOTE_ENRAGE -1533083 - -#define SPELL_FROST_AURA RAID_MODE(28531,55799) -#define SPELL_CLEAVE 19983 -#define SPELL_TAIL_SWEEP RAID_MODE(55697,55696) -#define SPELL_SUMMON_BLIZZARD 28560 -#define SPELL_LIFE_DRAIN RAID_MODE(28542,55665) -#define SPELL_ICEBOLT 28522 -#define SPELL_FROST_BREATH 29318 -#define SPELL_FROST_EXPLOSION 28524 -#define SPELL_FROST_MISSILE 30101 -#define SPELL_BERSERK 26662 -#define SPELL_DIES 29357 - -#define SPELL_CHILL RAID_MODE(28547,55699) - -#define MOB_BLIZZARD 16474 -#define GO_ICEBLOCK 181247 - -#define ACHIEVEMENT_THE_HUNDRED_CLUB RAID_MODE(2146, 2147) -#define MAX_FROST_RESISTANCE 100 - -enum Phases -{ - PHASE_NULL = 0, - PHASE_BIRTH, - PHASE_GROUND, - PHASE_FLIGHT, -}; - -enum Events -{ - EVENT_NONE, - EVENT_BERSERK, - EVENT_CLEAVE, - EVENT_TAIL, - EVENT_DRAIN, - EVENT_BLIZZARD, - EVENT_FLIGHT, - EVENT_LIFTOFF, - EVENT_ICEBOLT, - EVENT_BREATH, - EVENT_EXPLOSION, - EVENT_LAND, - EVENT_GROUND, - EVENT_BIRTH, -}; - -typedef std::map IceBlockMap; - -struct boss_sapphironAI : public BossAI -{ - boss_sapphironAI(Creature* c) : BossAI(c, BOSS_SAPPHIRON) - , phase(PHASE_NULL) - { - pMap = me->GetMap(); - } - - Phases phase; - uint32 iceboltCount; - IceBlockMap iceblocks; - - bool CanTheHundredClub; // needed for achievement: The Hundred Club(2146, 2147) - uint32 CheckFrostResistTimer; - Map* pMap; - - void InitializeAI() - { - float x, y, z; - me->GetPosition(x, y, z); - me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - - ScriptedAI::InitializeAI(); - } - - void Reset() - { - _Reset(); - - if (phase == PHASE_FLIGHT) - ClearIceBlock(); - - phase = PHASE_NULL; - - CanTheHundredClub = true; - CheckFrostResistTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - - me->CastSpell(me, SPELL_FROST_AURA, true); - - events.ScheduleEvent(EVENT_BERSERK, 15*60000); - EnterPhaseGround(); - - CheckPlayersFrostResist(); - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (spell->Id == SPELL_ICEBOLT) - { - IceBlockMap::iterator itr = iceblocks.find(pTarget->GetGUID()); - if (itr != iceblocks.end() && !itr->second) - { - if (GameObject *iceblock = me->SummonGameObject(GO_ICEBLOCK, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, 0, 0, 0, 0, 25000)) - itr->second = iceblock->GetGUID(); - } - } - } - - void JustDied(Unit* /*who*/) - { - _JustDied(); - me->CastSpell(me, SPELL_DIES, true); - - CheckPlayersFrostResist(); - if (CanTheHundredClub) - { - AchievementEntry const *AchievTheHundredClub = GetAchievementStore()->LookupEntry(ACHIEVEMENT_THE_HUNDRED_CLUB); - if (AchievTheHundredClub) - { - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievTheHundredClub); - } - } - } - } - - void MovementInform(uint32, uint32 id) - { - if (id == 1) - events.ScheduleEvent(EVENT_LIFTOFF, 0); - } - - void DoAction(const int32 param) - { - if (param == DATA_SAPPHIRON_BIRTH) - { - phase = PHASE_BIRTH; - events.ScheduleEvent(EVENT_BIRTH, 23000); - } - } - - void CheckPlayersFrostResist() - { - if (CanTheHundredClub && pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (itr->getSource()->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE) - { - CanTheHundredClub = false; - break; - } - } - } - } - - void EnterPhaseGround() - { - phase = PHASE_GROUND; - me->SetReactState(REACT_AGGRESSIVE); - events.SetPhase(PHASE_GROUND); - events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_BLIZZARD, 5000+rand()%5000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_FLIGHT, 45000); - } - - void ClearIceBlock() - { - for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr) - { - if (Player* pPlayer = Unit::GetPlayer(itr->first)) - pPlayer->RemoveAura(SPELL_ICEBOLT); - if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second)) - pGo->Delete(); - } - iceblocks.clear(); - } - - void UpdateAI(const uint32 diff) - { - if (!phase) - return; - - events.Update(diff); - - if (phase != PHASE_BIRTH && !UpdateCombatState() || !CheckInRoom()) - return; - - if (CanTheHundredClub) - { - if (CheckFrostResistTimer <= diff) - { - CheckPlayersFrostResist(); - CheckFrostResistTimer = (rand() % 5 + 5) * 1000; - } else CheckFrostResistTimer -= diff; - } - - if (phase == PHASE_GROUND) - { - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BERSERK: - DoScriptText(EMOTE_ENRAGE, me); - DoCast(me, SPELL_BERSERK); - return; - case EVENT_CLEAVE: - DoCast(me->getVictim(), SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); - return; - case EVENT_TAIL: - DoCastAOE(SPELL_TAIL_SWEEP); - events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); - return; - case EVENT_DRAIN: - DoCastAOE(SPELL_LIFE_DRAIN); - events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); - return; - case EVENT_BLIZZARD: - { - //DoCastAOE(SPELL_SUMMON_BLIZZARD); - if (Creature *pSummon = DoSummon(MOB_BLIZZARD, me, 0.0f, urand(25000,30000), TEMPSUMMON_TIMED_DESPAWN)) - pSummon->GetMotionMaster()->MoveRandom(40); - events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20000,7000), 0, PHASE_GROUND); - break; - } - case EVENT_FLIGHT: - phase = PHASE_FLIGHT; - events.SetPhase(PHASE_FLIGHT); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->GetMotionMaster()->MovePoint(1, x, y, z); - return; - } - } - - DoMeleeAttackIfReady(); - } - else - { - if (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_LIFTOFF: - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SendMovementFlagUpdate(); - events.ScheduleEvent(EVENT_ICEBOLT, 1500); - iceboltCount = RAID_MODE(2,3); - return; - case EVENT_ICEBOLT: - { - std::vector targets; - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT)) - targets.push_back((*i)->getTarget()); - - if (targets.empty()) - iceboltCount = 0; - else - { - std::vector::const_iterator itr = targets.begin(); - advance(itr, rand()%targets.size()); - iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0)); - DoCast(*itr, SPELL_ICEBOLT); - --iceboltCount; - } - - if (iceboltCount) - events.ScheduleEvent(EVENT_ICEBOLT, 1000); - else - events.ScheduleEvent(EVENT_BREATH, 1000); - return; - } - case EVENT_BREATH: - { - DoScriptText(EMOTE_BREATH, me); - DoCastAOE(SPELL_FROST_MISSILE); - events.ScheduleEvent(EVENT_EXPLOSION, 8000); - return; - } - case EVENT_EXPLOSION: - CastExplosion(); - ClearIceBlock(); - events.ScheduleEvent(EVENT_LAND, 3000); - return; - case EVENT_LAND: - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SendMovementFlagUpdate(); - events.ScheduleEvent(EVENT_GROUND, 1500); - return; - case EVENT_GROUND: - EnterPhaseGround(); - return; - case EVENT_BIRTH: - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - return; - } - }//if (uint32 eventId = events.ExecuteEvent()) - }//if (phase == PHASE_GROUND) - } - - void CastExplosion() - { - DoZoneInCombat(); // make sure everyone is in threatlist - std::vector targets; - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit *pTarget = (*i)->getTarget(); - if (pTarget->GetTypeId() != TYPEID_PLAYER) - continue; - - if (pTarget->HasAura(SPELL_ICEBOLT)) - { - pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); - targets.push_back(pTarget); - continue; - } - - for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr) - { - if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second)) - { - if (pGo->IsInBetween(me, pTarget, 2.0f) - && me->GetExactDist2d(pTarget->GetPositionX(), pTarget->GetPositionY()) - me->GetExactDist2d(pGo->GetPositionX(), pGo->GetPositionY()) < 5.0f) - { - pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); - targets.push_back(pTarget); - break; - } - } - } - } - - me->CastSpell(me, SPELL_FROST_EXPLOSION, true); - - for (std::vector::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - (*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false); - } -}; - -CreatureAI* GetAI_boss_sapphiron(Creature* pCreature) -{ - return new boss_sapphironAI (pCreature); -} - -void AddSC_boss_sapphiron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_sapphiron"; - newscript->GetAI = &GetAI_boss_sapphiron; - newscript->RegisterSelf(); - - // Chill - GetAISpellInfo(28547)->cooldown = 1000; - GetAISpellInfo(55699)->cooldown = 1000; -} diff --git a/src/server/scripts/northrend/naxxramas/boss_thaddius.cpp b/src/server/scripts/northrend/naxxramas/boss_thaddius.cpp deleted file mode 100644 index 350cd450510..00000000000 --- a/src/server/scripts/northrend/naxxramas/boss_thaddius.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -//Stalagg -enum StalaggYells -{ - SAY_STAL_AGGRO = -1533023, //not used - SAY_STAL_SLAY = -1533024, //not used - SAY_STAL_DEATH = -1533025 //not used -}; - -enum StalagSpells -{ - SPELL_POWERSURGE = 28134, - H_SPELL_POWERSURGE = 54529, - SPELL_MAGNETIC_PULL = 28338, - SPELL_STALAGG_TESLA = 28097 -}; - -//Feugen -enum FeugenYells -{ - SAY_FEUG_AGGRO = -1533026, //not used - SAY_FEUG_SLAY = -1533027, //not used - SAY_FEUG_DEATH = -1533028 //not used -}; - -enum FeugenSpells -{ - SPELL_STATICFIELD = 28135, - H_SPELL_STATICFIELD = 54528, - SPELL_FEUGEN_TESLA = 28109 -}; - -// Thaddius DoAction -enum ThaddiusActions -{ - ACTION_FEUGEN_RESET, - ACTION_FEUGEN_DIED, - ACTION_STALAGG_RESET, - ACTION_STALAGG_DIED -}; - -//generic -#define C_TESLA_COIL 16218 //the coils (emotes "Tesla Coil overloads!") - -//Thaddius -enum ThaddiusYells -{ - SAY_GREET = -1533029, //not used - SAY_AGGRO_1 = -1533030, - SAY_AGGRO_2 = -1533031, - SAY_AGGRO_3 = -1533032, - SAY_SLAY = -1533033, - SAY_ELECT = -1533034, //not used - SAY_DEATH = -1533035, - SAY_SCREAM1 = -1533036, //not used - SAY_SCREAM2 = -1533037, //not used - SAY_SCREAM3 = -1533038, //not used - SAY_SCREAM4 = -1533039 //not used -}; - -enum ThaddiusSpells -{ - SPELL_POLARITY_SHIFT = 28089, - SPELL_BALL_LIGHTNING = 28299, - SPELL_CHAIN_LIGHTNING = 28167, - H_SPELL_CHAIN_LIGHTNING = 54531, - SPELL_BERSERK = 27680 -}; - -enum Events -{ - EVENT_NONE, - EVENT_SHIFT, - EVENT_CHAIN, - EVENT_BERSERK, -}; - -struct boss_thaddiusAI : public BossAI -{ - boss_thaddiusAI(Creature *c) : BossAI(c, BOSS_THADDIUS) - { - // init is a bit tricky because thaddius shall track the life of both adds, but not if there was a wipe - // and, in particular, if there was a crash after both adds were killed (should not respawn) - - // Moreover, the adds may not yet be spawn. So just track down the status if mob is spawn - // and each mob will send its status at reset (meaning that it is alive) - checkFeugenAlive = false; - if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN))) - checkFeugenAlive = pFeugen->isAlive(); - - checkStalaggAlive = false; - if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG))) - checkStalaggAlive = pStalagg->isAlive(); - - if (!checkFeugenAlive && !checkStalaggAlive) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_AGGRESSIVE); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_PASSIVE); - } - } - - bool checkStalaggAlive; - bool checkFeugenAlive; - uint32 uiAddsTimer; - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_SLAY, me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - } - - void DoAction(const int32 action) - { - switch(action) - { - case ACTION_FEUGEN_RESET: - checkFeugenAlive = true; - break; - case ACTION_FEUGEN_DIED: - checkFeugenAlive = false; - break; - case ACTION_STALAGG_RESET: - checkStalaggAlive = true; - break; - case ACTION_STALAGG_DIED: - checkStalaggAlive = false; - break; - } - - if (!checkFeugenAlive && !checkStalaggAlive) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - // REACT_AGGRESSIVE only reset when he takes damage. - DoZoneInCombat(); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_PASSIVE); - } - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - events.ScheduleEvent(EVENT_SHIFT, 30000); - events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000)); - events.ScheduleEvent(EVENT_BERSERK, 360000); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 & /*uiDamage*/) - { - me->SetReactState(REACT_AGGRESSIVE); - } - - void UpdateAI(const uint32 diff) - { - if (checkFeugenAlive && checkStalaggAlive) - uiAddsTimer = 0; - - if (checkStalaggAlive != checkFeugenAlive) - { - uiAddsTimer += diff; - if (uiAddsTimer > 5000) - { - if (!checkStalaggAlive) - { - if (instance) - if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG))) - pStalagg->Respawn(); - } - else - { - if (instance) - if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN))) - pFeugen->Respawn(); - } - } - } - - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHIFT: - DoCastAOE(SPELL_POLARITY_SHIFT); - events.ScheduleEvent(EVENT_SHIFT, 30000); - return; - case EVENT_CHAIN: - DoCast(me->getVictim(), RAID_MODE(SPELL_CHAIN_LIGHTNING, H_SPELL_CHAIN_LIGHTNING)); - events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000)); - return; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - return; - } - } - - if (events.GetTimer() > 15000 && !me->IsWithinMeleeRange(me->getVictim())) - DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); - else - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_thaddius(Creature* pCreature) -{ - return new boss_thaddiusAI (pCreature); -} - -struct mob_stalaggAI : public ScriptedAI -{ - mob_stalaggAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 powerSurgeTimer; - uint32 magneticPullTimer; - - void Reset() - { - if (pInstance) - if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_STALAGG_RESET); - powerSurgeTimer = urand(20000,25000); - magneticPullTimer = 20000; - } - - void EnterCombat(Unit * /*pWho*/) - { - DoCast(SPELL_STALAGG_TESLA); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_STALAGG_DIED); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (magneticPullTimer <= uiDiff) - { - if (Creature *pFeugen = me->GetCreature(*me, pInstance->GetData64(DATA_FEUGEN))) - { - Unit* pStalaggVictim = me->getVictim(); - Unit* pFeugenVictim = pFeugen->getVictim(); - - if (pFeugenVictim && pStalaggVictim) - { - // magnetic pull is not working. So just jump. - - // reset aggro to be sure that feugen will not follow the jump - pFeugen->getThreatManager().modifyThreatPercent(pFeugenVictim, -100); - pFeugenVictim->JumpTo(me, 0.3f); - - me->getThreatManager().modifyThreatPercent(pStalaggVictim, -100); - pStalaggVictim->JumpTo(pFeugen, 0.3f); - } - } - - magneticPullTimer = 20000; - } - else magneticPullTimer -= uiDiff; - - if (powerSurgeTimer <= uiDiff) - { - DoCast(me, RAID_MODE(SPELL_POWERSURGE, H_SPELL_POWERSURGE)); - powerSurgeTimer = urand(15000,20000); - } else powerSurgeTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_stalagg(Creature* pCreature) -{ - return new mob_stalaggAI(pCreature); -} - -struct mob_feugenAI : public ScriptedAI -{ - mob_feugenAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 staticFieldTimer; - - void Reset() - { - if (pInstance) - if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_FEUGEN_RESET); - staticFieldTimer = 5000; - } - - void EnterCombat(Unit * /*pWho*/) - { - DoCast(SPELL_FEUGEN_TESLA); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_FEUGEN_DIED); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (staticFieldTimer <= uiDiff) - { - DoCast(me, RAID_MODE(SPELL_STATICFIELD, H_SPELL_STATICFIELD)); - staticFieldTimer = 5000; - } else staticFieldTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_feugen(Creature* pCreature) -{ - return new mob_feugenAI(pCreature); -} - -void AddSC_boss_thaddius() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_thaddius"; - newscript->GetAI = &GetAI_boss_thaddius; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stalagg"; - newscript->GetAI = &GetAI_mob_stalagg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_feugen"; - newscript->GetAI = &GetAI_mob_feugen; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/instance_naxxramas.cpp b/src/server/scripts/northrend/naxxramas/instance_naxxramas.cpp deleted file mode 100644 index 706789a73f1..00000000000 --- a/src/server/scripts/northrend/naxxramas/instance_naxxramas.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -const DoorData doorData[] = -{ - {181126, BOSS_ANUBREKHAN,DOOR_TYPE_ROOM, BOUNDARY_S}, - {181195, BOSS_ANUBREKHAN,DOOR_TYPE_PASSAGE, 0}, - {194022, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0}, - {181209, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0}, - {181209, BOSS_MAEXXNA, DOOR_TYPE_ROOM, BOUNDARY_SW}, - {181200, BOSS_NOTH, DOOR_TYPE_ROOM, BOUNDARY_N}, - {181201, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_E}, - {181202, BOSS_NOTH, DOOR_TYPE_PASSAGE, 0}, - {181202, BOSS_HEIGAN, DOOR_TYPE_ROOM, BOUNDARY_N}, - {181203, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_E}, - {181241, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, 0}, - {181241, BOSS_LOATHEB, DOOR_TYPE_ROOM, BOUNDARY_W}, - {181123, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE, 0}, - {181123, BOSS_GROBBULUS, DOOR_TYPE_ROOM, 0}, - {181120, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NW}, - {181121, BOSS_GLUTH, DOOR_TYPE_PASSAGE, 0}, - {181121, BOSS_THADDIUS, DOOR_TYPE_ROOM, 0}, - {181124, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE, 0}, - {181124, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_N}, - {181125, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_S}, - {181119, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, 0}, - {181119, BOSS_HORSEMEN, DOOR_TYPE_ROOM, BOUNDARY_NE}, - {181225, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE, BOUNDARY_W}, - {181228, BOSS_KELTHUZAD, DOOR_TYPE_ROOM, BOUNDARY_S}, - {0, 0, DOOR_TYPE_ROOM, 0}, // EOF -}; - -const MinionData minionData[] = -{ - //{16573, BOSS_ANUBREKHAN}, there is no spawn point in db, so we do not add them here - {16506, BOSS_FAERLINA}, - {16803, BOSS_RAZUVIOUS}, - {16063, BOSS_HORSEMEN}, - {16064, BOSS_HORSEMEN}, - {16065, BOSS_HORSEMEN}, - {30549, BOSS_HORSEMEN}, - {0, 0,} -}; - -enum eEnums -{ - GO_HORSEMEN_CHEST_HERO = 193426, - GO_HORSEMEN_CHEST = 181366, //four horsemen event, DoRespawnGameObject() when event == DONE - GO_GOTHIK_GATE = 181170, - GO_KELTHUZAD_PORTAL01 = 181402, - GO_KELTHUZAD_PORTAL02 = 181403, - GO_KELTHUZAD_PORTAL03 = 181404, - GO_KELTHUZAD_PORTAL04 = 181405, - GO_KELTHUZAD_TRIGGER = 181444, - - SPELL_ERUPTION = 29371 -}; - -const float HeiganPos[2] = {2796, -3707}; -const float HeiganEruptionSlope[3] = -{ - (-3685 - HeiganPos[1]) /(2724 - HeiganPos[0]), - (-3647 - HeiganPos[1]) /(2749 - HeiganPos[0]), - (-3637 - HeiganPos[1]) /(2771 - HeiganPos[0]), -}; - -// 0 H x -// 1 ^ -// 2 | -// 3 y<--o -inline uint32 GetEruptionSection(float x, float y) -{ - y -= HeiganPos[1]; - if (y < 1.0f) - return 0; - - x -= HeiganPos[0]; - if (x > -1.0f) - return 3; - - float slope = y/x; - for (uint32 i = 0; i < 3; ++i) - if (slope > HeiganEruptionSlope[i]) - return i; - return 3; -} - -struct instance_naxxramas : public InstanceData -{ - instance_naxxramas(Map* pMap) : InstanceData(pMap) - { - SetBossNumber(MAX_BOSS_NUMBER); - LoadDoorData(doorData); - LoadMinionData(minionData); - } - - std::set HeiganEruptionGUID[4]; - uint64 GothikGateGUID; - uint64 HorsemenChestGUID; - uint64 SapphironGUID; - uint64 uiFaerlina; - uint64 uiThane; - uint64 uiLady; - uint64 uiBaron; - uint64 uiSir; - - uint64 uiThaddius; - uint64 uiFeugen; - uint64 uiStalagg; - - uint64 uiKelthuzad; - uint64 uiKelthuzadTrigger; - uint64 uiPortals[4]; - - time_t minHorsemenDiedTime; - time_t maxHorsemenDiedTime; - - void OnCreatureCreate(Creature* pCreature, bool add) - { - switch(pCreature->GetEntry()) - { - case 15989: SapphironGUID = add ? pCreature->GetGUID() : 0; return; - case 15953: uiFaerlina = pCreature->GetGUID(); return; - case 16064: uiThane = pCreature->GetGUID(); return; - case 16065: uiLady = pCreature->GetGUID(); return; - case 30549: uiBaron = pCreature->GetGUID(); return; - case 16063: uiSir = pCreature->GetGUID(); return; - case 15928: uiThaddius = pCreature->GetGUID(); return; - case 15930: uiFeugen = pCreature->GetGUID(); return; - case 15929: uiStalagg = pCreature->GetGUID(); return; - case 15990: uiKelthuzad = pCreature->GetGUID(); return; - } - - AddMinion(pCreature, add); - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if (pGo->GetGOInfo()->displayId == 6785 || pGo->GetGOInfo()->displayId == 1287) - { - uint32 section = GetEruptionSection(pGo->GetPositionX(), pGo->GetPositionY()); - if (add) - HeiganEruptionGUID[section].insert(pGo->GetGUID()); - else - HeiganEruptionGUID[section].erase(pGo->GetGUID()); - return; - } - - switch(pGo->GetEntry()) - { - case GO_BIRTH: - if (!add && SapphironGUID) - { - if (Creature *pSapphiron = instance->GetCreature(SapphironGUID)) - pSapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH); - return; - } - case GO_GOTHIK_GATE: GothikGateGUID = add ? pGo->GetGUID() : 0; break; - case GO_HORSEMEN_CHEST: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break; - case GO_HORSEMEN_CHEST_HERO: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break; - case GO_KELTHUZAD_PORTAL01: uiPortals[0] = pGo->GetGUID(); break; - case GO_KELTHUZAD_PORTAL02: uiPortals[1] = pGo->GetGUID(); break; - case GO_KELTHUZAD_PORTAL03: uiPortals[2] = pGo->GetGUID(); break; - case GO_KELTHUZAD_PORTAL04: uiPortals[3] = pGo->GetGUID(); break; - case GO_KELTHUZAD_TRIGGER: uiKelthuzadTrigger = pGo->GetGUID(); break; - } - - AddDoor(pGo, add); - } - - void SetData(uint32 id, uint32 value) - { - switch(id) - { - case DATA_HEIGAN_ERUPT: - HeiganErupt(value); - break; - case DATA_GOTHIK_GATE: - if (GameObject *pGothikGate = instance->GetGameObject(GothikGateGUID)) - pGothikGate->SetGoState(GOState(value)); - break; - - case DATA_HORSEMEN0: - case DATA_HORSEMEN1: - case DATA_HORSEMEN2: - case DATA_HORSEMEN3: - if (value == NOT_STARTED) - { - minHorsemenDiedTime = 0; - maxHorsemenDiedTime = 0; - } - else if (value == DONE) - { - time_t now = time(NULL); - - if (minHorsemenDiedTime == 0) - minHorsemenDiedTime = now; - - maxHorsemenDiedTime = now; - } - break; - } - } - - uint64 GetData64(uint32 id) - { - switch(id) - { - case DATA_FAERLINA: - return uiFaerlina; - case DATA_THANE: - return uiThane; - case DATA_LADY: - return uiLady; - case DATA_BARON: - return uiBaron; - case DATA_SIR: - return uiSir; - case DATA_THADDIUS: - return uiThaddius; - case DATA_FEUGEN: - return uiFeugen; - case DATA_STALAGG: - return uiStalagg; - case DATA_KELTHUZAD: - return uiKelthuzad; - case DATA_KELTHUZAD_PORTAL01: - return uiPortals[0]; - case DATA_KELTHUZAD_PORTAL02: - return uiPortals[1]; - case DATA_KELTHUZAD_PORTAL03: - return uiPortals[2]; - case DATA_KELTHUZAD_PORTAL04: - return uiPortals[3]; - case DATA_KELTHUZAD_TRIGGER: - return uiKelthuzadTrigger; - } - return 0; - } - - bool SetBossState(uint32 id, EncounterState state) - { - if (!InstanceData::SetBossState(id, state)) - return false; - - if (id == BOSS_HORSEMEN && state == DONE) - { - if (GameObject *pHorsemenChest = instance->GetGameObject(HorsemenChestGUID)) - pHorsemenChest->SetRespawnTime(pHorsemenChest->GetRespawnDelay()); - } - - return true; - } - - void HeiganErupt(uint32 section) - { - for (uint32 i = 0; i < 4; ++i) - { - if (i == section) - continue; - - for (std::set::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr) - { - if (GameObject *pHeiganEruption = instance->GetGameObject(*itr)) - { - pHeiganEruption->SendCustomAnim(); - pHeiganEruption->CastSpell(NULL, SPELL_ERUPTION); - } - } - } - } - - bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/) - { - switch(criteria_id) - { - case 7600: // Criteria for achievement 2176: And They Would All Go Down Together 15sec of each other 10-man - if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) - return true; - return false; - case 7601: // Criteria for achievement 2177: And They Would All Go Down Together 15sec of each other 25-man - if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) - return true; - return false; - case 13233: // Criteria for achievement 2186: The Immortal (25-man) - // TODO. - break; - case 13237: // Criteria for achievement 2187: The Undying (10-man) - // TODO. - break; - } - return false; - } -}; - -InstanceData* GetInstanceData_instance_naxxramas(Map* pMap) -{ - return new instance_naxxramas(pMap); -} - -void AddSC_instance_naxxramas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_naxxramas"; - newscript->GetInstanceData = &GetInstanceData_instance_naxxramas; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/naxxramas/naxxramas.h b/src/server/scripts/northrend/naxxramas/naxxramas.h deleted file mode 100644 index 9b1fac2ff5b..00000000000 --- a/src/server/scripts/northrend/naxxramas/naxxramas.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_NAXXRAMAS_H -#define DEF_NAXXRAMAS_H - -enum Encounter -{ - BOSS_ANUBREKHAN, - BOSS_FAERLINA, - BOSS_MAEXXNA, - BOSS_NOTH, - BOSS_HEIGAN, - BOSS_LOATHEB, - BOSS_PATCHWERK, - BOSS_GROBBULUS, - BOSS_GLUTH, - BOSS_THADDIUS, - BOSS_RAZUVIOUS, - BOSS_GOTHIK, - BOSS_HORSEMEN, - BOSS_SAPPHIRON, - BOSS_KELTHUZAD, - MAX_BOSS_NUMBER -}; - -enum Data -{ - DATA_HEIGAN_ERUPT, - DATA_GOTHIK_GATE, - DATA_SAPPHIRON_BIRTH, - - DATA_HORSEMEN0, - DATA_HORSEMEN1, - DATA_HORSEMEN2, - DATA_HORSEMEN3, -}; - -enum Data64 -{ - DATA_FAERLINA, - DATA_THANE, - DATA_LADY, - DATA_BARON, - DATA_SIR, - DATA_THADDIUS, - DATA_FEUGEN, - DATA_STALAGG, - DATA_KELTHUZAD, - DATA_KELTHUZAD_PORTAL01, - DATA_KELTHUZAD_PORTAL02, - DATA_KELTHUZAD_PORTAL03, - DATA_KELTHUZAD_PORTAL04, - DATA_KELTHUZAD_TRIGGER, -}; - -#define GO_BIRTH 181356 - -#endif - diff --git a/src/server/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp b/src/server/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp deleted file mode 100644 index bbb1df2731d..00000000000 --- a/src/server/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* Script Data Start -SDName: Boss malygos -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -//Spells -#define SPELL_ARCANE_BREATH_N 56272 -#define SPELL_ARCANE_BREATH_H 60072 -#define SPELL_ARCANE_PULSE 57432 -#define SPELL_ARCANE_STORM_1 57459 -#define SPELL_ARCANE_STORM_2 61693 -#define SPELL_ARCANE_STORM_3 61694 -#define SPELL_STATIC_FIELD 57430 -#define SPELL_SURGE_OF_POWER_1 56505 -#define SPELL_SURGE_OF_POWER_2 57407 -#define SPELL_SURGE_OF_POWER_3 60936 -#define SPELL_VORTEX 56105 - -//Dragon "mounts" spells in Phase3 -//they use Rugelike energy -#define SPELL_DMOUNT_FLAME_SPIKE 56091 //maybe not accurate -#define SPELL_DMOUNT_ENGULF_IN_FLAMES 61621 -#define SPELL_DMOUNT_REVIVIFY 57090 -#define SPELL_DMOUNT_LIFE_BURST 57143 -#define SPELL_DMOUNT_FLAME_SHIELD 57108 -//#define SPELL_DMOUNT_UNKNOWN XYZ //Increases your drake's flight speed by 500%. - -//not in db -//Yell -//-->Other -#define SAY_ANTI_MAGIC_SHELL -1616000 -#define SAY_BREATH_ATTACK -1616001 -#define SAY_HIGH_DAMAGE_MODE -1616002 -#define SAY_MAGIC_BLAST -1616003 -//--> Generic Spells -#define SAY_GENERIC_SPELL_1 -1616004 -#define SAY_GENERIC_SPELL_2 -1616005 -#define SAY_GENERIC_SPELL_3 -1616006 -#define SAY_DEATH -1616007 -//--> Prefight -#define SAY_PREFIGHT_1 -1616008 -#define SAY_PREFIGHT_2 -1616009 -#define SAY_PREFIGHT_3 -1616010 -#define SAY_PREFIGHT_4 -1616011 -#define SAY_PREFIGHT_5 -1616012 -//--> Phase1 -#define SAY_PHASE1_AGGRO -1616013 -#define SAY_PHASE1_END -1616014 -#define SAY_PHASE1_SLAY_1 -1616015 -#define SAY_PHASE1_SLAY_2 -1616016 -#define SAY_PHASE1_SLAY_3 -1616017 - -//--> Phase2 at 50% HP, - -/*Malygos himself is not targetable during this phase, it will end when the adds he spawns are all killed. However, he does continue to play a part in the encounter. -During this phase he drops anti-magic zones onto the ground the raid MUST stand inside of, it reduces magical damage taken by 50%. They shrink over time, so it's important that your raid moves to each new one he drops. -Throughout the phase, he will deep breath doing ~4k damage per second, unless you are standing inside of the anti-magic zone. -The way the fight works during this phase is there are NPCs riding around on disks in the room. There are two types of mobs, Lords and Scions. -The Lords will move down onto the group, and need to be tanked (They will one-shot a non-tank). After they die, they drop a disk that a raid member can mount onto, which allows them to fly, to attack the Scions that do not come down to the ground. -It is recommended to let melee take the first disks, then ranged. As those mobs die, they also drop disks, which allows the rest of your dps to get onto them. -The Scions will continually cast Arcane Blast on random targets on the floor, which is mitigated by the anti-magic zones. While mounted on a disk, you will not take damage. -After all of the NPCs riding on the disks die, the players on the disks need to dismount as Phase 3 is about to begin.*/ - -//not in db -#define SAY_PHASE2_AGGRO -1616018 -#define SAY_PHASE2_END -1616019 -#define SAY_PHASE2_SLAY_1 -1616020 -#define SAY_PHASE2_SLAY_2 -1616021 -#define SAY_PHASE2_SLAY_3 -1616022 -//--> Phase3 Malygos destroys the floor, encounter continues on dragon "mounts" -#define SAY_PHASE3_INTRO -1616023 -#define SAY_PHASE3_AGGRO -1616024 -#define SAY_PHASE3_SLAY_1 -1616025 -#define SAY_PHASE3_SLAY_2 -1616026 -#define SAY_PHASE3_SLAY_3 -1616027 -#define SAY_PHASE3_BIG_ATTACK -1616028 - -enum -{ - ACHIEV_TIMED_START_EVENT = 20387, -}; - -struct boss_malygosAI : public ScriptedAI -{ - boss_malygosAI(Creature *c) : ScriptedAI(c) - { - instance = me->GetInstanceData(); - } - - InstanceData *instance; - - uint32 phase; - uint32 enrage; - - void Reset() - { - phase = 1; - enrage = 615000; //Source Deadly Boss Mod - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) - { - if (phase == 1) - { - DoScriptText(SAY_PHASE1_AGGRO, me); - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - if (phase == 2) - DoScriptText(SAY_PHASE1_AGGRO, me); - if (phase == 3) - DoScriptText(SAY_PHASE1_AGGRO, me); - } - - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (phase == 1 && HealthBelowPct(50)) { - phase = 2; - //spawn adds - //set malygos unatackable untill all adds spawned dead - //start phase3 - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - if (phase == 1) - DoScriptText(RAND(SAY_PHASE1_SLAY_1,SAY_PHASE1_SLAY_2,SAY_PHASE1_SLAY_3), me); - if (phase == 2) - DoScriptText(RAND(SAY_PHASE2_SLAY_1,SAY_PHASE2_SLAY_2,SAY_PHASE2_SLAY_3), me); - if (phase == 3) - DoScriptText(RAND(SAY_PHASE3_SLAY_1,SAY_PHASE3_SLAY_2,SAY_PHASE3_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_malygos(Creature* pCreature) -{ - return new boss_malygosAI (pCreature); -} - -void AddSC_boss_malygos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_malygos"; - newscript->GetAI = &GetAI_boss_malygos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h b/src/server/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h deleted file mode 100644 index caa82a92e95..00000000000 --- a/src/server/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef DEF_EYE_OF_ETERNITY_H -#define DEF_EYE_OF_ETERNITY_H - -#endif diff --git a/src/server/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp b/src/server/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp deleted file mode 100644 index d93ec415b42..00000000000 --- a/src/server/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "ScriptedPch.h" -#include "eye_of_eternity.h" - -struct instance_eye_of_eternity : public ScriptedInstance -{ - instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; -}; - -InstanceData* GetInstanceData_instance_eye_of_eternity(Map* pMap) -{ - return new instance_eye_of_eternity(pMap); -} - -void AddSC_instance_eye_of_eternity() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_eye_of_eternity"; - newscript->GetInstanceData = &GetInstanceData_instance_eye_of_eternity; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/nexus/boss_anomalus.cpp b/src/server/scripts/northrend/nexus/nexus/boss_anomalus.cpp deleted file mode 100644 index 02c39dc1232..00000000000 --- a/src/server/scripts/northrend/nexus/nexus/boss_anomalus.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - //Spells - SPELL_SPARK = 47751, - H_SPELL_SPARK = 57062, - SPELL_RIFT_SHIELD = 47748, - SPELL_CHARGE_RIFT = 47747, //Works wrong (affect players, not rifts) - SPELL_CREATE_RIFT = 47743, //Don't work, using WA - SPELL_ARCANE_ATTRACTION = 57063, //No idea, when it's used -}; - -enum Adds -{ - MOB_CRAZED_MANA_WRAITH = 26746, - MOB_CHAOTIC_RIFT = 26918 -}; -enum Yells -{ - //Yell - SAY_AGGRO = -1576010, - SAY_DEATH = -1576011, - SAY_RIFT = -1576012, - SAY_SHIELD = -1576013 -}; - -enum Achievs -{ - ACHIEV_CHAOS_THEORY = 2037 -}; - -const Position RiftLocation[6] = -{ - {652.64, -273.70, -8.75}, - {634.45, -265.94, -8.44}, - {620.73, -281.17, -9.02}, - {626.10, -304.67, -9.44}, - {639.87, -314.11, -9.49}, - {651.72, -297.44, -9.37} -}; - -struct boss_anomalusAI : public ScriptedAI -{ - boss_anomalusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint8 Phase; - uint32 uiSparkTimer; - uint32 uiCreateRiftTimer; - uint64 uiChaoticRiftGUID; - - bool bDeadChaoticRift; // needed for achievement: Chaos Theory(2037) - - void Reset() - { - Phase = 0; - uiSparkTimer = 5*IN_MILISECONDS; - uiChaoticRiftGUID = 0; - - bDeadChaoticRift = false; - - if (pInstance) - pInstance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && !bDeadChaoticRift) - pInstance->DoCompleteAchievement(ACHIEV_CHAOS_THEORY); - pInstance->SetData(DATA_ANOMALUS_EVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetDistance(me->GetHomePosition()) > 60.0f) - { - //Not blizzlike, hack to avoid an exploit - EnterEvadeMode(); - return; - } - - if (me->HasAura(SPELL_RIFT_SHIELD)) - { - if (uiChaoticRiftGUID) - { - Unit* Rift = Unit::GetUnit((*me), uiChaoticRiftGUID); - if (Rift && Rift->isDead()) - { - me->RemoveAurasDueToSpell(SPELL_RIFT_SHIELD); - uiChaoticRiftGUID = 0; - } - return; - } - } else - uiChaoticRiftGUID = 0; - - if ((Phase == 0) && HealthBelowPct(50)) - { - Phase = 1; - DoScriptText(SAY_SHIELD, me); - DoCast(me, SPELL_RIFT_SHIELD); - Creature* Rift = me->SummonCreature(MOB_CHAOTIC_RIFT, RiftLocation[urand(0,5)], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); - if (Rift) - { - //DoCast(Rift, SPELL_CHARGE_RIFT); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Rift->AI()->AttackStart(pTarget); - uiChaoticRiftGUID = Rift->GetGUID(); - DoScriptText(SAY_RIFT , me); - } - } - - - if (uiSparkTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SPARK); - uiSparkTimer = 5*IN_MILISECONDS; - } else uiSparkTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_anomalus(Creature* pCreature) -{ - return new boss_anomalusAI (pCreature); -} - -enum RiftSpells -{ - SPELL_CHAOTIC_ENERGY_BURST = 47688, - SPELL_CHARGED_CHAOTIC_ENERGY_BURST = 47737, - SPELL_ARCANEFORM = 48019 //Chaotic Rift visual -}; - -struct mob_chaotic_riftAI : public Scripted_NoMovementAI -{ - mob_chaotic_riftAI(Creature *c) : Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiChaoticEnergyBurstTimer; - uint32 uiSummonCrazedManaWraithTimer; - - void Reset() - { - uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; - uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; - //me->SetDisplayId(25206); //For some reason in DB models for ally and horde are different. - //Model for ally (1126) does not show auras. Horde model works perfect. - //Set model to horde number - DoCast(me, SPELL_ARCANEFORM, false); - } - - void JustDied(Unit * /*killer*/) - { - if (Creature* pAnomalus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0)) - CAST_AI(boss_anomalusAI,pAnomalus->AI())->bDeadChaoticRift = true; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiChaoticEnergyBurstTimer <= diff) - { - Unit* pAnomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - if (pAnomalus && pAnomalus->HasAura(SPELL_RIFT_SHIELD)) - DoCast(pTarget, SPELL_CHARGED_CHAOTIC_ENERGY_BURST); - else - DoCast(pTarget, SPELL_CHAOTIC_ENERGY_BURST); - uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; - } else uiChaoticEnergyBurstTimer -= diff; - - if (uiSummonCrazedManaWraithTimer <= diff) - { - Creature* Wraith = me->SummonCreature(MOB_CRAZED_MANA_WRAITH, me->GetPositionX()+1, me->GetPositionY()+1, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); - if (Wraith) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Wraith->AI()->AttackStart(pTarget); - Unit* Anomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); - if (Anomalus && Anomalus->HasAura(SPELL_RIFT_SHIELD)) - uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; - else - uiSummonCrazedManaWraithTimer = 10*IN_MILISECONDS; - } else uiSummonCrazedManaWraithTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_chaotic_rift(Creature* pCreature) -{ - return new mob_chaotic_riftAI (pCreature); -} - -void AddSC_boss_anomalus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_anomalus"; - newscript->GetAI = &GetAI_boss_anomalus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_chaotic_rift"; - newscript->GetAI = &GetAI_mob_chaotic_rift; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/nexus/boss_keristrasza.cpp b/src/server/scripts/northrend/nexus/nexus/boss_keristrasza.cpp deleted file mode 100644 index ff633c55eac..00000000000 --- a/src/server/scripts/northrend/nexus/nexus/boss_keristrasza.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - //Spells - SPELL_FROZEN_PRISON = 47854, - SPELL_TAIL_SWEEP = 50155, - SPELL_CRYSTAL_CHAINS = 50997, - SPELL_ENRAGE = 8599, - SPELL_CRYSTALFIRE_BREATH = 48096, - H_SPELL_CRYSTALFIRE_BREATH = 57091, - SPELL_CRYSTALIZE = 48179, - SPELL_INTENSE_COLD = 48094, - SPELL_INTENSE_COLD_TRIGGERED = 48095 -}; -enum Yells -{ - //Yell - SAY_AGGRO = -1576040, - SAY_SLAY = -1576041, - SAY_ENRAGE = -1576042, - SAY_DEATH = -1576043, - SAY_CRYSTAL_NOVA = -1576044 -}; -enum Achievements -{ - ACHIEV_INTENSE_COLD = 2036 -}; -enum Misc -{ - DATA_CONTAINMENT_SPHERES = 3 -}; - -struct boss_keristraszaAI : public ScriptedAI -{ - boss_keristraszaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCrystalfireBreathTimer; - uint32 uiCrystalChainsCrystalizeTimer; - uint32 uiTailSweepTimer; - bool bEnrage; - - uint64 auiContainmentSphereGUIDs[DATA_CONTAINMENT_SPHERES]; - - uint32 uiCheckIntenseColdTimer; - bool bMoreThanTwoIntenseCold; // needed for achievement: Intense Cold(2036) - - void Reset() - { - uiCrystalfireBreathTimer = 14*IN_MILISECONDS; - uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); - uiTailSweepTimer = 5*IN_MILISECONDS; - bEnrage = false; - - uiCheckIntenseColdTimer = 2*IN_MILISECONDS; - bMoreThanTwoIntenseCold = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - - RemovePrison(CheckContainmentSpheres()); - - if (pInstance) - pInstance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCastAOE(SPELL_INTENSE_COLD); - - if (pInstance) - pInstance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && !bMoreThanTwoIntenseCold) - pInstance->DoCompleteAchievement(ACHIEV_INTENSE_COLD); - pInstance->SetData(DATA_KERISTRASZA_EVENT, DONE); - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_SLAY, me); - } - - bool CheckContainmentSpheres(bool remove_prison = false) - { - if (!pInstance) - return false; - - auiContainmentSphereGUIDs[0] = pInstance->GetData64(ANOMALUS_CONTAINMET_SPHERE); - auiContainmentSphereGUIDs[1] = pInstance->GetData64(ORMOROKS_CONTAINMET_SPHERE); - auiContainmentSphereGUIDs[2] = pInstance->GetData64(TELESTRAS_CONTAINMET_SPHERE); - - GameObject *ContainmentSpheres[DATA_CONTAINMENT_SPHERES]; - - for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i) - { - ContainmentSpheres[i] = pInstance->instance->GetGameObject(auiContainmentSphereGUIDs[i]); - if (!ContainmentSpheres[i]) - return false; - if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE) - return false; - } - if (remove_prison) - RemovePrison(true); - return true; - } - - void RemovePrison(bool remove) - { - if (remove) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (me->HasAura(SPELL_FROZEN_PRISON)) - me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoCast(me, SPELL_FROZEN_PRISON, false); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiCheckIntenseColdTimer < diff && !bMoreThanTwoIntenseCold) - { - std::list ThreatList = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER) - continue; - - Aura *AuraIntenseCold = pTarget->GetAura(SPELL_INTENSE_COLD_TRIGGERED); - if (AuraIntenseCold && AuraIntenseCold->GetStackAmount() > 2) - { - bMoreThanTwoIntenseCold = true; - break; - } - } - uiCheckIntenseColdTimer = 2*IN_MILISECONDS; - } else uiCheckIntenseColdTimer -= diff; - - if (!bEnrage && HealthBelowPct(25)) - { - DoScriptText(SAY_ENRAGE, me); - DoCast(me, SPELL_ENRAGE); - bEnrage = true; - } - - if (uiCrystalfireBreathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CRYSTALFIRE_BREATH); - uiCrystalfireBreathTimer = 14*IN_MILISECONDS; - } else uiCrystalfireBreathTimer -= diff; - - if (uiTailSweepTimer <= diff) - { - DoCast(me, SPELL_TAIL_SWEEP); - uiTailSweepTimer = 5*IN_MILISECONDS; - } else uiTailSweepTimer -= diff; - - if (uiCrystalChainsCrystalizeTimer <= diff) - { - DoScriptText(SAY_CRYSTAL_NOVA, me); - if (IsHeroic()) - DoCast(me, SPELL_CRYSTALIZE); - else if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CRYSTAL_CHAINS); - uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); - } else uiCrystalChainsCrystalizeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_keristrasza(Creature* pCreature) -{ - return new boss_keristraszaAI (pCreature); -} - -bool GOHello_containment_sphere(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - - Creature *pKeristrasza = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_KERISTRASZA) : 0); - if (pKeristrasza && pKeristrasza->isAlive()) - { - // maybe these are hacks :( - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - CAST_AI(boss_keristraszaAI, pKeristrasza->AI())->CheckContainmentSpheres(true); - } - return true; -} - -void AddSC_boss_keristrasza() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_keristrasza"; - newscript->GetAI = &GetAI_boss_keristrasza; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "containment_sphere"; - newscript->pGOHello = &GOHello_containment_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp b/src/server/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp deleted file mode 100644 index 0bf9fb07bb7..00000000000 --- a/src/server/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - SPELL_ICE_NOVA = 47772, - H_SPELL_ICE_NOVA = 56935, - SPELL_FIREBOMB = 47773, - H_SPELL_FIREBOMB = 56934, - SPELL_GRAVITY_WELL = 47756, - SPELL_TELESTRA_BACK = 47714, - - SPELL_FIRE_MAGUS_VISUAL = 47705, - SPELL_FROST_MAGUS_VISUAL = 47706, - SPELL_ARCANE_MAGUS_VISUAL = 47704 -}; -enum Creatures -{ - MOB_FIRE_MAGUS = 26928, - MOB_FROST_MAGUS = 26930, - MOB_ARCANE_MAGUS = 26929 -}; -enum Yells -{ - SAY_AGGRO = -1576000, - SAY_KILL = -1576001, - SAY_DEATH = -1576002, - SAY_MERGE = -1576003, - SAY_SPLIT_1 = -1576004, - SAY_SPLIT_2 = -1576005, -}; -enum Achievements -{ - ACHIEV_SPLIT_PERSONALITY = 2150, - ACHIEV_TIMER = 5*IN_MILISECONDS -}; - -const Position CenterOfRoom = {504.80, 89.07, -16.12, 6.27}; - -struct boss_magus_telestraAI : public ScriptedAI -{ - boss_magus_telestraAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 uiFireMagusGUID; - uint64 uiFrostMagusGUID; - uint64 uiArcaneMagusGUID; - - bool bFireMagusDead; - bool bFrostMagusDead; - bool bArcaneMagusDead; - bool bIsWaitingToAppear; - bool bIsAchievementTimerRunning; - - uint32 uiIsWaitingToAppearTimer; - uint32 uiIceNovaTimer; - uint32 uiFireBombTimer; - uint32 uiGravityWellTimer; - uint32 uiCooldown; - uint32 uiAchievementTimer; - - uint8 Phase; - uint8 uiAchievementProgress; - - void Reset() - { - Phase = 0; - //These times are probably wrong - uiIceNovaTimer = 7*IN_MILISECONDS; - uiFireBombTimer = 0; - uiGravityWellTimer = 15*IN_MILISECONDS; - uiCooldown = 0; - - uiFireMagusGUID = 0; - uiFrostMagusGUID = 0; - uiArcaneMagusGUID = 0; - - uiAchievementProgress = 0; - uiAchievementTimer = 0; - - bIsAchievementTimerRunning = false; - bIsWaitingToAppear = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - if (pInstance) - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && uiAchievementProgress == 2) - pInstance->DoCompleteAchievement(ACHIEV_SPLIT_PERSONALITY); - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE); - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - uint64 SplitPersonality(uint32 entry) - { - if (Creature* Summoned = me->SummonCreature(entry, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS)) - { - switch (entry) - { - case MOB_FIRE_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_FIRE_MAGUS_VISUAL, false); - break; - } - case MOB_FROST_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_FROST_MAGUS_VISUAL, false); - break; - } - case MOB_ARCANE_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_ARCANE_MAGUS_VISUAL, false); - break; - } - } - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Summoned->AI()->AttackStart(pTarget); - return Summoned->GetGUID(); - } - return 0; - } - - void SummonedCreatureDespawn(Creature *summon) - { - if (summon->isAlive()) - return; - - if (summon->GetGUID() == uiFireMagusGUID) - { - bFireMagusDead = true; - bIsAchievementTimerRunning = true; - } - else if (summon->GetGUID() == uiFrostMagusGUID) - { - bFrostMagusDead = true; - bIsAchievementTimerRunning = true; - } - else if (summon->GetGUID() == uiArcaneMagusGUID) - { - bArcaneMagusDead = true; - bIsAchievementTimerRunning = true; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (bIsWaitingToAppear) - { - me->StopMoving(); - me->AttackStop(); - if (uiIsWaitingToAppearTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - bIsWaitingToAppear = false; - } else uiIsWaitingToAppearTimer -= diff; - return; - } - - if ((Phase == 1) ||(Phase == 3)) - { - if (bIsAchievementTimerRunning) - uiAchievementTimer += diff; - if (bFireMagusDead && bFrostMagusDead && bArcaneMagusDead) - { - if (uiAchievementTimer <= ACHIEV_TIMER) - uiAchievementProgress +=1; - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, CenterOfRoom.GetPositionX(), CenterOfRoom.GetPositionY(), CenterOfRoom.GetPositionZ(), CenterOfRoom.GetOrientation()); - DoCast(me, SPELL_TELESTRA_BACK); - me->SetVisibility(VISIBILITY_ON); - if (Phase == 1) - Phase = 2; - if (Phase == 3) - Phase = 4; - uiFireMagusGUID = 0; - uiFrostMagusGUID = 0; - uiArcaneMagusGUID = 0; - bIsWaitingToAppear = true; - uiIsWaitingToAppearTimer = 4*IN_MILISECONDS; - DoScriptText(SAY_MERGE, me); - bIsAchievementTimerRunning = false; - uiAchievementTimer = 0; - } - else - return; - } - - if ((Phase == 0) && HealthBelowPct(50)) - { - Phase = 1; - me->CastStop(); - me->RemoveAllAuras(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); - uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); - uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); - bFireMagusDead = false; - bFrostMagusDead = false; - bArcaneMagusDead = false; - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - return; - } - - if (IsHeroic() && (Phase == 2) && HealthBelowPct(10)) - { - Phase = 3; - me->CastStop(); - me->RemoveAllAuras(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); - uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); - uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); - bFireMagusDead = false; - bFrostMagusDead = false; - bArcaneMagusDead = false; - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - return; - } - - if (uiCooldown) - { - if (uiCooldown <= diff) - uiCooldown = 0; - else - { - uiCooldown -= diff; - return; - } - } - - if (uiIceNovaTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_ICE_NOVA, false); - uiCooldown = 1.5*IN_MILISECONDS; - } - uiIceNovaTimer = 15*IN_MILISECONDS; - } else uiIceNovaTimer -= diff; - - if (uiGravityWellTimer <= diff) - { - if (Unit *pTarget = me->getVictim()) - { - DoCast(pTarget, SPELL_GRAVITY_WELL); - uiCooldown = 6*IN_MILISECONDS; - } - uiGravityWellTimer = 15*IN_MILISECONDS; - } else uiGravityWellTimer -= diff; - - if (uiFireBombTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_FIREBOMB, false); - uiCooldown = 2*IN_MILISECONDS; - } - uiFireBombTimer = 2*IN_MILISECONDS; - } else uiFireBombTimer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_magus_telestra(Creature* pCreature) -{ - return new boss_magus_telestraAI (pCreature); -} - -void AddSC_boss_magus_telestra() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_magus_telestra"; - newscript->GetAI = &GetAI_boss_magus_telestra; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/nexus/boss_ormorok.cpp b/src/server/scripts/northrend/nexus/nexus/boss_ormorok.cpp deleted file mode 100644 index 1304f95c7ac..00000000000 --- a/src/server/scripts/northrend/nexus/nexus/boss_ormorok.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - SPELL_CRYSTAL_SPIKES = 47958, //Don't work, using walkaround - H_SPELL_CRYSTAL_SPIKES = 57082, //Don't work, using walkaround - SPELL_CRYSTALL_SPIKE_DAMAGE = 47944, - H_SPELL_CRYSTALL_SPIKE_DAMAGE = 57067, - SPELL_CRYSTAL_SPIKE_PREVISUAL = 50442, - MOB_CRYSTAL_SPIKE = 27099, - SPELL_SPELL_REFLECTION = 47981, - SPELL_TRAMPLE = 48016, - H_SPELL_TRAMPLE = 57066, - SPELL_FRENZY = 48017, - SPELL_SUMMON_CRYSTALLINE_TANGLER = 61564, //summons npc 32665 - SPELL_ROOTS = 28858 //proper spell id is unknown -}; -enum Yells -{ - SAY_AGGRO = -1576020, - SAY_DEATH = -1576021, - SAY_REFLECT = -1576022, - SAY_CRYSTAL_SPIKES = -1576023, - SAY_KILL = -1576024 -}; -enum Creatures -{ - MOB_CRYSTALLINE_TANGLER = 32665 -}; - -#define SPIKE_DISTANCE 5.0f - -struct boss_ormorokAI : public ScriptedAI -{ - boss_ormorokAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bFrenzy; - bool bCrystalSpikes; - uint8 uiCrystalSpikesCount; - float fBaseX; - float fBaseY; - float fBaseZ; - float fBaseO; - float fSpikeXY[4][2]; - - uint32 uiCrystalSpikesTimer; - uint32 uiCrystalSpikesTimer2; - uint32 uiTrampleTimer; - uint32 uiFrenzyTimer; - uint32 uiSpellReflectionTimer; - uint32 uiSummonCrystallineTanglerTimer; - - void Reset() - { - uiCrystalSpikesTimer = 12*IN_MILISECONDS; - uiTrampleTimer = 10*IN_MILISECONDS; - uiSpellReflectionTimer = 30*IN_MILISECONDS; - uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; - bFrenzy = false; - bCrystalSpikes = false; - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - return; - } - if (bCrystalSpikes) - if (uiCrystalSpikesTimer2 <= diff) - { - fSpikeXY[0][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); - fSpikeXY[0][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); - fSpikeXY[1][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); - fSpikeXY[1][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); - fSpikeXY[2][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); - fSpikeXY[2][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); - fSpikeXY[3][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); - fSpikeXY[3][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); - for (uint8 i = 0; i < 4; ++i) - me->SummonCreature(MOB_CRYSTAL_SPIKE, fSpikeXY[i][0], fSpikeXY[i][1], fBaseZ, 0, TEMPSUMMON_TIMED_DESPAWN, 7*IN_MILISECONDS); - if (++uiCrystalSpikesCount >= 13) - bCrystalSpikes = false; - uiCrystalSpikesTimer2 = 200; - } else uiCrystalSpikesTimer2 -= diff; - - if (!bFrenzy && (me->GetHealth() < me->GetMaxHealth() * 0.25)) - { - DoCast(me, SPELL_FRENZY); - bFrenzy = true; - } - - if (uiTrampleTimer <= diff) - { - DoCast(me, SPELL_TRAMPLE); - uiTrampleTimer = 10*IN_MILISECONDS; - } else uiTrampleTimer -= diff; - - if (uiSpellReflectionTimer <= diff) - { - DoScriptText(SAY_REFLECT, me); - DoCast(me, SPELL_SPELL_REFLECTION); - uiSpellReflectionTimer = 30*IN_MILISECONDS; - } else uiSpellReflectionTimer -= diff; - - if (uiCrystalSpikesTimer <= diff) - { - DoScriptText(SAY_CRYSTAL_SPIKES, me); - bCrystalSpikes = true; - uiCrystalSpikesCount = 1; - uiCrystalSpikesTimer2 = 0; - fBaseX = me->GetPositionX(); - fBaseY = me->GetPositionY(); - fBaseZ = me->GetPositionZ(); - fBaseO = me->GetOrientation(); - uiCrystalSpikesTimer = 20*IN_MILISECONDS; - } else uiCrystalSpikesTimer -= diff; - - if (IsHeroic() && (uiSummonCrystallineTanglerTimer <= diff)) - { - Creature* Crystalline_Tangler = me->SummonCreature(MOB_CRYSTALLINE_TANGLER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); - if (Crystalline_Tangler) - { - Unit *pTarget = NULL; - uint8 Healer = 0; - for (uint8 j = 1; j <= 4; j++) - { - switch (j) - { - case 1: Healer = CLASS_PRIEST; break; - case 2: Healer = CLASS_PALADIN; break; - case 3: Healer = CLASS_DRUID; break; - case 4: Healer = CLASS_SHAMAN; break; - } - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pTemp = Unit::GetUnit((*me),(*i)->getUnitGuid()); - if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && pTemp->getClass() == Healer) - { - pTarget = pTemp; - break; - } - } - if (pTarget) - break; - } - if (!pTarget) - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Crystalline_Tangler->AI()->AttackStart(pTarget); - Crystalline_Tangler->getThreatManager().addThreat(pTarget, 1000000000.0f); - } - } - uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; - } else uiSummonCrystallineTanglerTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_crystal_spikeAI : public Scripted_NoMovementAI -{ - mob_crystal_spikeAI(Creature *c) : Scripted_NoMovementAI(c) - { - } - - uint32 SpellCrystalSpikeDamageTimer; - uint32 SpellCrystalSpikePrevisualTimer; - - void Reset() - { - SpellCrystalSpikeDamageTimer = 3.7*IN_MILISECONDS; - SpellCrystalSpikePrevisualTimer = 1*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (SpellCrystalSpikePrevisualTimer <= diff) - { - DoCast(me, SPELL_CRYSTAL_SPIKE_PREVISUAL); - SpellCrystalSpikePrevisualTimer = 10*IN_MILISECONDS; - } else SpellCrystalSpikePrevisualTimer -= diff; - - if (SpellCrystalSpikeDamageTimer <= diff) - { - DoCast(me, SPELL_CRYSTALL_SPIKE_DAMAGE); - SpellCrystalSpikeDamageTimer = 10*IN_MILISECONDS; - } else SpellCrystalSpikeDamageTimer -= diff; - } -}; - -struct mob_crystalline_tanglerAI : public ScriptedAI -{ - mob_crystalline_tanglerAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiRootsTimer; - - void Reset() - { - uiRootsTimer = 1*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (uiRootsTimer <= diff) - { - if (me->IsWithinDist(me->getVictim(), 5.0f, false)) - { - DoCast(me->getVictim(), SPELL_ROOTS); - uiRootsTimer = 15*IN_MILISECONDS; - } - } else uiRootsTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_crystal_spike(Creature* pCreature) -{ - return new mob_crystal_spikeAI (pCreature); -} - -CreatureAI* GetAI_mob_crystalline_tangler(Creature* pCreature) -{ - return new mob_crystalline_tanglerAI (pCreature); -} - -CreatureAI* GetAI_boss_ormorok(Creature* pCreature) -{ - return new boss_ormorokAI (pCreature); -} - -void AddSC_boss_ormorok() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ormorok"; - newscript->GetAI = &GetAI_boss_ormorok; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crystal_spike"; - newscript->GetAI = &GetAI_mob_crystal_spike; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crystalline_tangler"; - newscript->GetAI = &GetAI_mob_crystalline_tangler; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/nexus/commander_kolurg.cpp b/src/server/scripts/northrend/nexus/nexus/commander_kolurg.cpp deleted file mode 100644 index 4bd9f55a013..00000000000 --- a/src/server/scripts/northrend/nexus/nexus/commander_kolurg.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Script Data Start -SDName: Boss Commander Kolurg -SDAuthor: LordVanMartin -SD%Complete: -SDComment: Only Alliance Heroic -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_commander_kolurg' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -#define SPELL_BATTLE_SHOUT 31403 -#define SPELL_CHARGE 60067 -#define SPELL_FRIGHTENING_SHOUT 19134 -#define SPELL_WHIRLWIND_1 38619 -#define SPELL_WHIRLWIND_2 38618 - -//not used -//Yell -#define SAY_AGGRO -1576024 -#define SAY_KILL -1576025 -#define SAY_DEATH -1576026 - -struct boss_commander_kolurgAI : public ScriptedAI -{ - boss_commander_kolurgAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) {} -}; - -CreatureAI* GetAI_boss_commander_kolurg(Creature* pCreature) -{ - return new boss_commander_kolurgAI (pCreature); -} - -void AddSC_boss_commander_kolurg() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_commander_kolurg"; - newscript->GetAI = &GetAI_boss_commander_kolurg; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/nexus/commander_stoutbeard.cpp b/src/server/scripts/northrend/nexus/nexus/commander_stoutbeard.cpp deleted file mode 100644 index ef02baa38e6..00000000000 --- a/src/server/scripts/northrend/nexus/nexus/commander_stoutbeard.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* Script Data Start -SDName: Boss Commander Stoutbeard -SDAuthor: LordVanMartin -SD%Complete: -SDComment: Only Horde Heroic -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_commander_stoutbeard' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -#define SPELL_BATTLE_SHOUT 31403 -#define SPELL_CHARGE 60067 -#define SPELL_FRIGHTENING_SHOUT 19134 -#define SPELL_WHIRLWIND_1 38619 -#define SPELL_WHIRLWIND_2 38618 - -//not used -//Yell -#define SAY_AGGRO -1576021 -#define SAY_KILL -1576022 -#define SAY_DEATH -1576023 - -struct boss_commander_stoutbeardAI : public ScriptedAI -{ - boss_commander_stoutbeardAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - } -}; - -CreatureAI* GetAI_boss_commander_stoutbeard(Creature* pCreature) -{ - return new boss_commander_stoutbeardAI (pCreature); -} - -void AddSC_boss_commander_stoutbeard() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_commander_stoutbeard"; - newscript->GetAI = &GetAI_boss_commander_stoutbeard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/nexus/instance_nexus.cpp b/src/server/scripts/northrend/nexus/nexus/instance_nexus.cpp deleted file mode 100644 index db70245e3a4..00000000000 --- a/src/server/scripts/northrend/nexus/nexus/instance_nexus.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -#define NUMBER_OF_ENCOUNTERS 4 - -enum Factions -{ - FACTION_HOSTILE_FOR_ALL = 16 -}; - -struct instance_nexus : public ScriptedInstance -{ - instance_nexus(Map *pMap) : ScriptedInstance(pMap) { Initialize(); } - - uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS]; - - uint64 Anomalus; - uint64 Keristrasza; - - uint64 AnomalusContainmentSphere; - uint64 OrmoroksContainmentSphere; - uint64 TelestrasContainmentSphere; - - std::string strInstData; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Anomalus = 0; - Keristrasza = 0; - } - - void OnCreatureCreate(Creature *pCreature, bool /*bAdd*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - uint32 TeamInInstance = 0; - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - TeamInInstance = pPlayer->GetTeam(); - } - switch (pCreature->GetEntry()) - { - case 26763: - Anomalus = pCreature->GetGUID(); - break; - case 26723: - Keristrasza = pCreature->GetGUID(); - break; - // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. - case 26800: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26799, HORDE); - break; - } - case 26802: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26801, HORDE); - break; - } - case 26805: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26803, HORDE); - break; - } - case 27949: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(27947, HORDE); - break; - } - case 26796: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26798, HORDE); - break; - } - } - } - - void OnGameObjectCreate(GameObject *pGo, bool /*bAdd*/) - { - switch (pGo->GetEntry()) - { - case 188527: - { - AnomalusContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - case 188528: - { - OrmoroksContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - case 188526: - { - TelestrasContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - } - } - - uint32 GetData(uint32 identifier) - { - switch(identifier) - { - case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0]; - case DATA_ANOMALUS_EVENT: return m_auiEncounter[1]; - case DATA_ORMOROK_EVENT: return m_auiEncounter[2]; - case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3]; - } - return 0; - } - - void SetData(uint32 identifier, uint32 data) - { - switch (identifier) - { - case DATA_MAGUS_TELESTRA_EVENT: - { - if (data == DONE) - { - GameObject *Sphere = instance->GetGameObject(TelestrasContainmentSphere); - if (Sphere) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[0] = data; - break; - } - case DATA_ANOMALUS_EVENT: - { - if (data == DONE) - { - if (GameObject *Sphere = instance->GetGameObject(AnomalusContainmentSphere)) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[1] = data; - break; - } - case DATA_ORMOROK_EVENT: - { - if (data == DONE) - { - if (GameObject *Sphere = instance->GetGameObject(OrmoroksContainmentSphere)) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[2] = data; - break; - } - case DATA_KERISTRASZA_EVENT: - m_auiEncounter[3] = data; - break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3]; - - strInstData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint64 GetData64(uint32 uiIdentifier) - { - switch(uiIdentifier) - { - case DATA_ANOMALUS: return Anomalus; - case DATA_KERISTRASZA: return Keristrasza; - case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere; - case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere; - case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere; - } - return 0; - } - - std::string GetSaveData() - { - return strInstData; - } - - void Load(const char *chrIn) - { - if (!chrIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(chrIn); - - std::istringstream loadStream(chrIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - - for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData *GetInstanceData_instance_nexus(Map *pMap) -{ - return new instance_nexus(pMap); -} - -void AddSC_instance_nexus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_nexus"; - newscript->GetInstanceData = &GetInstanceData_instance_nexus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/nexus/nexus.h b/src/server/scripts/northrend/nexus/nexus/nexus.h deleted file mode 100644 index 66902bece30..00000000000 --- a/src/server/scripts/northrend/nexus/nexus/nexus.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_NEXUS_H -#define DEF_NEXUS_H - -enum eTypes -{ - DATA_MAGUS_TELESTRA_EVENT, - DATA_ANOMALUS_EVENT, - DATA_ORMOROK_EVENT, - DATA_KERISTRASZA_EVENT, - - DATA_ANOMALUS, - DATA_KERISTRASZA, - - ANOMALUS_CONTAINMET_SPHERE, - ORMOROKS_CONTAINMET_SPHERE, - TELESTRAS_CONTAINMET_SPHERE -}; - -#endif diff --git a/src/server/scripts/northrend/nexus/oculus/boss_drakos.cpp b/src/server/scripts/northrend/nexus/oculus/boss_drakos.cpp deleted file mode 100644 index 7d276206339..00000000000 --- a/src/server/scripts/northrend/nexus/oculus/boss_drakos.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - SPELL_MAGIC_PULL = 51336, - SPELL_MAGIC_PULL_EFFECT = 50770, - SPELL_THUNDERING_STOMP = 50774, - SPELL_THUNDERING_STOMP_H = 59370, - SPELL_UNSTABLE_SPHERE_PASSIVE = 50756, - SPELL_UNSTABLE_SPHERE_PULSE = 50757, - SPELL_UNSTABLE_SPHERE_TIMER = 50758, - NPC_UNSTABLE_SPHERE = 28166, -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1578000, - SAY_KILL_1 = -1578001, - SAY_KILL_2 = -1578002, - SAY_KILL_3 = -1578003, - SAY_DEATH = -1578004, - SAY_PULL_1 = -1578005, - SAY_PULL_2 = -1578006, - SAY_PULL_3 = -1578007, - SAY_PULL_4 = -1578008, - SAY_STOMP_1 = -1578009, - SAY_STOMP_2 = -1578010, - SAY_STOMP_3 = -1578011 -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 18153, -}; - -struct boss_drakosAI : public ScriptedAI -{ - boss_drakosAI(Creature* pCreature) : ScriptedAI(pCreature), lSummons(me) - { - pInstance = pCreature->GetInstanceData(); - } - - uint32 uiMagicPullTimer; - uint32 uiStompTimer; - uint32 uiBombSummonTimer; - - bool bPostPull; - - ScriptedInstance* pInstance; - SummonList lSummons; - - void Reset() - { - lSummons.DespawnAll(); - uiMagicPullTimer = 15000; - uiStompTimer = 17000; - uiBombSummonTimer = 2000; - - bPostPull = false; - - if (pInstance) - pInstance->SetData(DATA_DRAKOS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_DRAKOS_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature* pSummon) - { - lSummons.Summon(pSummon); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBombSummonTimer <= uiDiff) - { - Position pPosition; - me->GetPosition(&pPosition); - - if (bPostPull) - { - for (uint8 uiI = 0; uiI >= 3; uiI++) - { - me->GetRandomNearPosition(pPosition, float(urand(0,10))); - me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); - } - } - else - { - me->GetRandomNearPosition(pPosition, float(urand(0,10))); - me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); - } - - uiBombSummonTimer = 2000; - } else uiBombSummonTimer -= uiDiff; - - if (uiMagicPullTimer <= uiDiff) - { - DoCast(SPELL_MAGIC_PULL); - - bPostPull = true; - - uiMagicPullTimer = 15000; - } else uiMagicPullTimer -= uiDiff; - - if (uiStompTimer <= uiDiff) - { - DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2,SAY_STOMP_3), me); - DoCast(SPELL_THUNDERING_STOMP); - uiStompTimer = 17000; - } else uiStompTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_DRAKOS_EVENT, DONE); - // start achievement timer (kill Eregos within 20 min) - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - lSummons.DespawnAll(); - } - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); - } -}; - -CreatureAI* GetAI_boss_drakos(Creature* pCreature) -{ - return new boss_drakosAI (pCreature); -} - -struct npc_unstable_sphereAI : public ScriptedAI -{ - npc_unstable_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiPulseTimer; - uint32 uiDeathTimer; - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveRandom(40.0f); - - me->AddAura(SPELL_UNSTABLE_SPHERE_PASSIVE, me); - me->AddAura(SPELL_UNSTABLE_SPHERE_TIMER, me); - - uiPulseTimer = 3000; - uiDeathTimer = 19000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (uiPulseTimer <= uiDiff) - { - DoCast(SPELL_UNSTABLE_SPHERE_PULSE); - uiPulseTimer = 3*IN_MILISECONDS; - } else uiPulseTimer -= uiDiff; - - if (uiDeathTimer <= uiDiff) - me->DisappearAndDie(); - else uiDeathTimer -= uiDiff; - } -}; - -CreatureAI* GetAI_npc_unstable_sphere(Creature* pCreature) -{ - return new npc_unstable_sphereAI (pCreature); -} - -void AddSC_boss_drakos() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_drakos"; - newscript->GetAI = &GetAI_boss_drakos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_unstable_sphere"; - newscript->GetAI = &GetAI_npc_unstable_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/oculus/boss_eregos.cpp b/src/server/scripts/northrend/nexus/oculus/boss_eregos.cpp deleted file mode 100644 index 94fb90ab206..00000000000 --- a/src/server/scripts/northrend/nexus/oculus/boss_eregos.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -//Types of drake mounts: Ruby(Tank), Amber(DPS), Emerald(Healer) -//Two Repeating phases - -enum Spells -{ - SPELL_ARCANE_BARRAGE = 50804, - H_SPELL_ARCANE_BARRAGE = 59381, - SPELL_ARCANE_VOLLEY = 51153, - H_SPELL_ARCANE_VOLLEY = 59382, - SPELL_ENRAGED_ASSAULT = 51170, - SPELL_PLANAR_ANOMALIES = 57959, - SPELL_PLANAR_SHIFT = 51162, -}; -/*Ruby Drake , -(npc 27756) (item 37860) -(summoned by spell Ruby Essence = 37860 ---> Call Amber Drake == 49462 ---> Summon 27756) -*/ -enum RubyDrake -{ - NPC_RUBY_DRAKE_VEHICLE = 27756, - SPELL_RIDE_RUBY_DRAKE_QUE = 49463, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49464 - SPELL_RUBY_DRAKE_SADDLE = 49464, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_RUBY_SEARING_WRATH = 50232, //(60 yds) - Instant - Breathes a stream of fire at an enemy dragon, dealing 6800 to 9200 Fire damage and then jumping to additional dragons within 30 yards. Each jump increases the damage by 50%. Affects up to 5 total targets - SPELL_RUBY_EVASIVE_AURA = 50248, //Instant - Allows the Ruby Drake to generate Evasive Charges when hit by hostile attacks and spells. - SPELL_RUBY_EVASIVE_MANEUVERS = 50240, //Instant - 5 sec. cooldown - Allows your drake to dodge all incoming attacks and spells. Requires Evasive Charges to use. Each attack or spell dodged while this ability is active burns one Evasive Charge. Lasts 30 sec. or until all charges are exhausted. - //you do not have acces to until you kill Mage-Lord Urom - SPELL_RUBY_MARTYR = 50253 //Instant - 10 sec. cooldown - Redirect all harmful spells cast at friendly drakes to yourself for 10 sec. -}; -/*Amber Drake, -(npc 27755) (item 37859) -(summoned by spell Amber Essence = 37859 ---> Call Amber Drake == 49461 ---> Summon 27755) -*/ -enum AmberDrake -{ - NPC_AMBER_DRAKE_VEHICLE = 27755, - SPELL_RIDE_AMBER_DRAKE_QUE = 49459, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49460 - SPELL_AMBER_DRAKE_SADDLE = 49460, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_AMBER_SHOCK_LANCE = 49840, //(60 yds) - Instant - Deals 4822 to 5602 Arcane damage and detonates all Shock Charges on an enemy dragon. Damage is increased by 6525 for each detonated. -// SPELL_AMBER_STOP_TIME //Instant - 1 min cooldown - Halts the passage of time, freezing all enemy dragons in place for 10 sec. This attack applies 5 Shock Charges to each affected target. - //you do not have access to until you kill the Mage-Lord Urom. - SPELL_AMBER_TEMPORAL_RIFT = 49592 //(60 yds) - Channeled - Channels a temporal rift on an enemy dragon for 10 sec. While trapped in the rift, all damage done to the target is increased by 100%. In addition, for every 15,000 damage done to a target affected by Temporal Rift, 1 Shock Charge is generated. -}; -/*Emerald Drake, -(npc 27692) (item 37815), - (summoned by spell Emerald Essence = 37815 ---> Call Emerald Drake == 49345 ---> Summon 27692) -*/ -enum EmeraldDrake -{ - NPC_EMERALD_DRAKE_VEHICLE = 27692, - SPELL_RIDE_EMERALD_DRAKE_QUE = 49427, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49346 - SPELL_EMERALD_DRAKE_SADDLE = 49346, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_EMERALD_LEECHING_POISON = 50328, //(60 yds) - Instant - Poisons the enemy dragon, leeching 1300 to the caster every 2 sec. for 12 sec. Stacks up to 3 times. - SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, //(60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25,000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec. - // you do not have access to until you kill the Mage-Lord Urom - SPELL_EMERALD_DREAM_FUNNEL = 50344 //(60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels. -}; - -struct boss_eregosAI : public ScriptedAI -{ - boss_eregosAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, DONE); - } -}; - -CreatureAI* GetAI_boss_eregos(Creature* pCreature) -{ - return new boss_eregosAI (pCreature); -} - -void AddSC_boss_eregos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_eregos"; - newscript->GetAI = &GetAI_boss_eregos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/oculus/boss_urom.cpp b/src/server/scripts/northrend/nexus/oculus/boss_urom.cpp deleted file mode 100644 index 29435441d00..00000000000 --- a/src/server/scripts/northrend/nexus/oculus/boss_urom.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Urom -SD%Complete: 80 -SDComment: Is not working SPELL_ARCANE_SHIELD. SPELL_FROSTBOMB has some issues, the damage aura should not stack. -SDCategory: Instance Script -EndScriptData */ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - - SPELL_ARCANE_SHIELD = 53813, //Dummy --> Channeled, shields the caster from damage. - SPELL_EMPOWERED_ARCANE_EXPLOSION = 51110, - SPELL_EMPOWERED_ARCANE_EXPLOSION_2 = 59377, - SPELL_FROSTBOMB = 51103, //Urom throws a bomb, hitting its target with the highest aggro which inflict directly 650 frost damage and drops a frost zone on the ground. This zone deals 650 frost damage per second and reduce the movement speed by 35%. Lasts 1 minute. - SPELL_SUMMON_MENAGERIE = 50476, //Summons an assortment of creatures and teleports the caster to safety. - SPELL_SUMMON_MENAGERIE_2 = 50495, - SPELL_SUMMON_MENAGERIE_3 = 50496, - SPELL_TELEPORT = 51112, //Teleports to the center of Oculus - SPELL_TIME_BOMB = 51121, //Deals arcane damage to a random player, and after 6 seconds, deals zone damage to nearby equal to the health missing of the target afflicted by the debuff. - SPELL_TIME_BOMB_2 = 59376 -}; - -enum Yells -{ - SAY_AGGRO_1 = -1578000, - SAY_AGGRO_2 = -1578001, - SAY_AGGRO_3 = -1578002, - SAY_AGGRO_4 = -1578003, - SAY_TELEPORT = -1578004, -}; - -enum eCreature -{ - NPC_PHANTASMAL_CLOUDSCRAPER = 27645, - NPC_PHANTASMAL_MAMMOTH = 27642, - NPC_PHANTASMAL_WOLF = 27644, - - NPC_PHANTASMAL_AIR = 27650, - NPC_PHANTASMAL_FIRE = 27651, - NPC_PHANTASMAL_WATER = 27653, - - NPC_PHANTASMAL_MURLOC = 27649, - NPC_PHANTASMAL_NAGAL = 27648, - NPC_PHANTASMAL_OGRE = 27647 -}; - -struct Summons -{ - uint32 uiEntry[4]; -}; - -static Summons Group[]= -{ - {NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_MAMMOTH,NPC_PHANTASMAL_WOLF}, - {NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_WATER,NPC_PHANTASMAL_FIRE}, - {NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_NAGAL,NPC_PHANTASMAL_MURLOC} -}; - -static uint32 TeleportSpells[]= -{ - SPELL_SUMMON_MENAGERIE,SPELL_SUMMON_MENAGERIE_2,SPELL_SUMMON_MENAGERIE_3 -}; - -static int32 SayAggro[]= -{ - SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4 -}; - -struct boss_uromAI : public ScriptedAI -{ - boss_uromAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - float x,y; - - bool bCanCast; - bool bCanGoBack; - - uint8 uiGroup[3]; - - uint32 uiTeleportTimer; - uint32 uiArcaneExplosionTimer; - uint32 uiCastArcaneExplosionTimer; - uint32 uiFrostBombTimer; - uint32 uiTimeBombTimer; - - void Reset() - { - if (pInstance && pInstance->GetData(DATA_VAROS_EVENT) != DONE) - DoCast(SPELL_ARCANE_SHIELD); - - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, NOT_STARTED); - - if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) == 0) - { - uiGroup[0] = 0; - uiGroup[1] = 0; - uiGroup[2] = 0; - } - - x,y = 0.0f; - bCanCast = false; - bCanGoBack = false; - - me->GetMotionMaster()->MoveIdle(); - - uiTeleportTimer = urand(30000,35000); - uiArcaneExplosionTimer = 9000; - uiCastArcaneExplosionTimer = 2000; - uiFrostBombTimer = urand(5000,8000); - uiTimeBombTimer = urand(20000,25000); - } - - void EnterCombat(Unit* pWho) - { - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, IN_PROGRESS); - - SetGroups(); - SummonGroups(); - CastTeleport(); - - if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) != 3) - pInstance->SetData(DATA_UROM_PLATAFORM,pInstance->GetData(DATA_UROM_PLATAFORM)+1); - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - if (me->GetPositionZ() > 518.63) - DoStartNoMovement(pWho); - - if (me->GetPositionZ() < 518.63) - { - if (me->Attack(pWho, true)) - { - DoScriptText(SayAggro[3],me); - - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(pWho, 0,0); - } - } - } - - void SetGroups() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) != 0) - return; - - while (uiGroup[0] == uiGroup[1] || uiGroup[0] == uiGroup[2] || uiGroup[1] == uiGroup[2]) - { - uiGroup[0] = urand(0,2); - uiGroup[1] = urand(0,2); - uiGroup[2] = urand(0,2); - } - } - - void SetPosition(uint8 uiI) - { - switch(uiI) - { - case 0: - x = me->GetPositionX() + 4; - y = me->GetPositionY() - 4; - break; - case 1: - x = me->GetPositionX() + 4; - y = me->GetPositionY() + 4; - break; - case 2: - x = me->GetPositionX() - 4; - y = me->GetPositionY() + 4; - break; - case 3: - x = me->GetPositionX() - 4; - y = me->GetPositionY() - 4; - break; - default: - break; - } - } - - void SummonGroups() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) - return; - - for (uint8 uiI = 0; uiI < 4 ; uiI++) - { - SetPosition(uiI); - me->SummonCreature(Group[uiGroup[pInstance->GetData(DATA_UROM_PLATAFORM)]].uiEntry[uiI],x,y,me->GetPositionZ(),me->GetOrientation()); - } - } - - void CastTeleport() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) - return; - - DoScriptText(SayAggro[pInstance->GetData(DATA_UROM_PLATAFORM)],me); - DoCast(TeleportSpells[pInstance->GetData(DATA_UROM_PLATAFORM)]); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) < 2) - return; - - if (uiTeleportTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(false); - DoScriptText(SAY_TELEPORT,me); - me->GetMotionMaster()->MoveIdle(); - DoCast(SPELL_TELEPORT); - uiTeleportTimer = urand(30000,35000); - - } else uiTeleportTimer -= uiDiff; - - if (bCanCast && !me->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION)) - { - if (uiCastArcaneExplosionTimer <= uiDiff) - { - bCanCast = false; - bCanGoBack = true; - DoCastAOE(SPELL_EMPOWERED_ARCANE_EXPLOSION); - uiCastArcaneExplosionTimer = 2000; - }else uiCastArcaneExplosionTimer -= uiDiff; - } - - if (bCanGoBack) - { - if (uiArcaneExplosionTimer <= uiDiff) - { - Position pPos; - me->getVictim()->GetPosition(&pPos); - - me->NearTeleportTo(pPos.GetPositionX(),pPos.GetPositionY(),pPos.GetPositionZ(),pPos.GetOrientation()); - me->GetMotionMaster()->MoveChase(me->getVictim(),0,0); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - - bCanCast = false; - bCanGoBack = false; - uiArcaneExplosionTimer = 9000; - } else uiArcaneExplosionTimer -= uiDiff; - } - - if (!me->IsNonMeleeSpellCasted(false, true, true)) - { - if (uiFrostBombTimer <= uiDiff) - { - DoCastVictim(SPELL_FROSTBOMB); - uiFrostBombTimer = urand(5000,8000); - } else uiFrostBombTimer -= uiDiff; - - if (uiTimeBombTimer <= uiDiff) - { - if (Unit* pUnit = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pUnit,SPELL_TIME_BOMB); - - uiTimeBombTimer = urand(20000,25000); - } else uiTimeBombTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, DONE); - } - - void JustSummoned(Creature* pSummon) - { - pSummon->SetInCombatWithZone(); - } - - void LeaveCombat() - { - me->RemoveAllAuras(); - me->CombatStop(false); - me->DeleteThreatList(); - } - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - switch(pSpell->Id) - { - case SPELL_SUMMON_MENAGERIE: - me->SetHomePosition(968.66,1042.53,527.32,0.077); - LeaveCombat(); - break; - case SPELL_SUMMON_MENAGERIE_2: - me->SetHomePosition(1164.02,1170.85,527.321,3.66); - LeaveCombat(); - break; - case SPELL_SUMMON_MENAGERIE_3: - me->SetHomePosition(1118.31,1080.377,508.361,4.25); - LeaveCombat(); - break; - case SPELL_TELEPORT: - me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE); // with out it the npc will fall down while is casting - bCanCast = true; - break; - default: - break; - } - } -}; - -CreatureAI* GetAI_boss_urom(Creature* pCreature) -{ - return new boss_uromAI (pCreature); -} - -void AddSC_boss_urom() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_urom"; - newscript->GetAI = &GetAI_boss_urom; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/oculus/boss_varos.cpp b/src/server/scripts/northrend/nexus/oculus/boss_varos.cpp deleted file mode 100644 index 79034250a43..00000000000 --- a/src/server/scripts/northrend/nexus/oculus/boss_varos.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - SPELL_ENERGIZE_CORES = 50785, //Damage 5938 to 6562, effec2 Triggers 54069, effect3 Triggers 56251 - SPELL_ENERGIZE_CORES_TRIGGER_1 = 54069, - SPELL_ENERGIZE_CORES_TRIGGER_2 = 56251, - SPELL_ENERGIZE_CORES_2 = 59372, //Damage 9025 to 9975, effect2 Triggers 54069, effect 56251 - SPELL_CALL_AZURE_RING_CAPTAIN = 51002, //Effect Send Event (12229) - SPELL_CALL_AZURE_RING_CAPTAIN_2 = 51006, //Effect Send Event (10665) - SPELL_CALL_AZURE_RING_CAPTAIN_3 = 51007, //Effect Send Event (18454) - SPELL_CALL_AZURE_RING_CAPTAIN_4 = 51008, //Effect Send Event (18455) - SPELL_CALL_AMPLIFY_MAGIC = 51054, - SPELL_CALL_AMPLIFY_MAGIC_2 = 59371 -}; -//not in db -enum Yells -{ - SAY_AGGRO = -1578022, - SAY_KILL_1 = -1578023, - SAY_KILL_2 = -1578024, - SAY_DEATH = -1578025, - SAY_STRIKE_1 = -1578026, - SAY_STRIKE_2 = -1578027, - SAY_STRIKE_3 = -1578028, - SAY_SPAWN = -1578029 -}; - -struct boss_varosAI : public ScriptedAI -{ - boss_varosAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, NOT_STARTED); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, IN_PROGRESS); - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, DONE); - } - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } -}; - -CreatureAI* GetAI_boss_varos(Creature* pCreature) -{ - return new boss_varosAI (pCreature); -} - -void AddSC_boss_varos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_varos"; - newscript->GetAI = &GetAI_boss_varos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/oculus/instance_oculus.cpp b/src/server/scripts/northrend/nexus/oculus/instance_oculus.cpp deleted file mode 100644 index 49be2385a3c..00000000000 --- a/src/server/scripts/northrend/nexus/oculus/instance_oculus.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -#define MAX_ENCOUNTER 4 - -/* The Occulus encounters: -0 - Drakos the Interrogator -1 - Varos Cloudstrider -2 - Mage-Lord Urom -3 - Ley-Guardian Eregos */ - -struct instance_oculus : public ScriptedInstance -{ - instance_oculus(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiDrakos; - uint64 uiVaros; - uint64 uiUrom; - uint64 uiEregos; - - uint8 uiPlataformUrom; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - std::list GameObjectList; - - void Initialize() - { - uiPlataformUrom = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case CREATURE_DRAKOS: - uiDrakos = pCreature->GetGUID(); - break; - case CREATURE_VAROS: - uiVaros = pCreature->GetGUID(); - break; - case CREATURE_UROM: - uiUrom = pCreature->GetGUID(); - break; - case CREATURE_EREGOS: - uiEregos = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGO, bool bAdd) - { - if (pGO->GetEntry() == GO_DRAGON_CAGE_DOOR) - { - if (DATA_DRAKOS_EVENT == DONE) - pGO->SetGoState(GO_STATE_ACTIVE); - else - pGO->SetGoState(GO_STATE_READY); - - GameObjectList.push_back(pGO->GetGUID()); - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_DRAKOS_EVENT: - m_auiEncounter[0] = data; - if (data == DONE) - OpenCageDoors(); - break; - case DATA_VAROS_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_UROM_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_EREGOS_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_UROM_PLATAFORM: - uiPlataformUrom = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_DRAKOS_EVENT: return m_auiEncounter[0]; - case DATA_VAROS_EVENT: return m_auiEncounter[1]; - case DATA_UROM_EVENT: return m_auiEncounter[2]; - case DATA_EREGOS_EVENT: return m_auiEncounter[3]; - case DATA_UROM_PLATAFORM: return uiPlataformUrom; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_DRAKOS: return uiDrakos; - case DATA_VAROS: return uiVaros; - case DATA_UROM: return uiUrom; - case DATA_EREGOS: return uiEregos; - } - - return 0; - } - - void OpenCageDoors() - { - if (GameObjectList.empty()) - return; - - for (std::list::const_iterator itr = GameObjectList.begin(); itr != GameObjectList.end(); ++itr) - { - if (GameObject* pGO = instance->GetGameObject(*itr)) - pGO->SetGoState(GO_STATE_ACTIVE); - } - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "T O " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'T' && dataHead2 == 'O') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_oculus(Map* pMap) -{ - return new instance_oculus(pMap); -} - -void AddSC_instance_oculus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_oculus"; - newscript->GetInstanceData = &GetInstanceData_instance_oculus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/oculus/oculus.cpp b/src/server/scripts/northrend/nexus/oculus/oculus.cpp deleted file mode 100644 index 685583532d5..00000000000 --- a/src/server/scripts/northrend/nexus/oculus/oculus.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -#define GOSSIP_ITEM_DRAKES "So where do we go from here?" -#define GOSSIP_ITEM_BELGARISTRASZ1 "I want to fly on the wings of the Red Flight" -#define GOSSIP_ITEM_BELGARISTRASZ2 "What abilities do Ruby Drakes have?" -#define GOSSIP_ITEM_VERDISA1 "I want to fly on the wings of the Green Flight" -#define GOSSIP_ITEM_VERDISA2 "What abilities do Emerald Drakes have?" -#define GOSSIP_ITEM_ETERNOS1 "I want to fly on the wings of the Bronze Flight" -#define GOSSIP_ITEM_ETERNOS2 "What abilities do Amber Drakes have?" - -#define HAS_ESSENCE(a) ((a)->HasItemCount(ITEM_EMERALD_ESSENCE,1) || (a)->HasItemCount(ITEM_AMBER_ESSENCE,1) || (a)->HasItemCount(ITEM_RUBY_ESSENCE,1)) - -enum Drakes -{ - GOSSIP_TEXTID_DRAKES = 13267, - GOSSIP_TEXTID_BELGARISTRASZ1 = 12916, - GOSSIP_TEXTID_BELGARISTRASZ2 = 13466, - GOSSIP_TEXTID_BELGARISTRASZ3 = 13254, - GOSSIP_TEXTID_VERDISA1 = 1, - GOSSIP_TEXTID_VERDISA2 = 1, - GOSSIP_TEXTID_VERDISA3 = 1, - GOSSIP_TEXTID_ETERNOS1 = 1, - GOSSIP_TEXTID_ETERNOS2 = 1, - GOSSIP_TEXTID_ETERNOS3 = 13256, - - ITEM_EMERALD_ESSENCE = 37815, - ITEM_AMBER_ESSENCE = 37859, - ITEM_RUBY_ESSENCE = 37860, - - NPC_VERDISA = 27657, - NPC_BELGARISTRASZ = 27658, - NPC_ETERNOS = 27659 -}; - -bool GossipHello_npc_oculus_drake(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->GetInstanceData()->GetData(DATA_DRAKOS_EVENT) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DRAKES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DRAKES, pCreature->GetGUID()); - } - - return true; -} - -bool GossipSelect_npc_oculus_drake(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(pCreature->GetEntry()) - { - case NPC_VERDISA: //Verdisa - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_EMERALD_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_EMERALD_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA3, pCreature->GetGUID()); - break; - } - break; - case NPC_BELGARISTRASZ: //Belgaristrasz - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_RUBY_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_RUBY_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ3, pCreature->GetGUID()); - break; - } - break; - case NPC_ETERNOS: //Eternos - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_AMBER_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_AMBER_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS3, pCreature->GetGUID()); - break; - } - break; - } - - return true; -} - -void AddSC_oculus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_oculus_drake"; - newscript->pGossipHello = &GossipHello_npc_oculus_drake; - newscript->pGossipSelect = &GossipSelect_npc_oculus_drake; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/nexus/oculus/oculus.h b/src/server/scripts/northrend/nexus/oculus/oculus.h deleted file mode 100644 index b212c9b8b6a..00000000000 --- a/src/server/scripts/northrend/nexus/oculus/oculus.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DEF_OCULUS_H -#define DEF_OCULUS_H - -enum Data -{ - DATA_DRAKOS_EVENT, - DATA_VAROS_EVENT, - DATA_UROM_EVENT, - DATA_EREGOS_EVENT, - DATA_UROM_PLATAFORM -}; - -enum Data64 -{ - DATA_DRAKOS, - DATA_VAROS, - DATA_UROM, - DATA_EREGOS -}; - -enum Bosses -{ - CREATURE_DRAKOS = 27654, - CREATURE_VAROS = 27447, - CREATURE_UROM = 27655, - CREATURE_EREGOS = 27656 -}; - -enum GameObjects -{ - GO_DRAGON_CAGE_DOOR = 193995 -}; - -#endif diff --git a/src/server/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp b/src/server/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp deleted file mode 100644 index 3e24aaeb6c0..00000000000 --- a/src/server/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp +++ /dev/null @@ -1,1421 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "obsidian_sanctum.h" - -enum eEnums -{ - //Sartharion Yell - SAY_SARTHARION_AGGRO = -1615018, - SAY_SARTHARION_BERSERK = -1615019, - SAY_SARTHARION_BREATH = -1615020, - SAY_SARTHARION_CALL_SHADRON = -1615021, - SAY_SARTHARION_CALL_TENEBRON = -1615022, - SAY_SARTHARION_CALL_VESPERON = -1615023, - SAY_SARTHARION_DEATH = -1615024, - SAY_SARTHARION_SPECIAL_1 = -1615025, - SAY_SARTHARION_SPECIAL_2 = -1615026, - SAY_SARTHARION_SPECIAL_3 = -1615027, - SAY_SARTHARION_SPECIAL_4 = -1615028, - SAY_SARTHARION_SLAY_1 = -1615029, - SAY_SARTHARION_SLAY_2 = -1615030, - SAY_SARTHARION_SLAY_3 = -1615031, - - WHISPER_LAVA_CHURN = -1615032, - - WHISPER_SHADRON_DICIPLE = -1615008, - WHISPER_VESPERON_DICIPLE = -1615041, - WHISPER_HATCH_EGGS = -1615017, - WHISPER_OPEN_PORTAL = -1615042, // whisper, shared by two dragons - - //Sartharion Spells - SPELL_BERSERK = 61632, // Increases the caster's attack speed by 150% and all damage it deals by 500% for 5 min. - SPELL_CLEAVE = 56909, // Inflicts 35% weapon damage to an enemy and its nearest allies, affecting up to 10 targets. - SPELL_FLAME_BREATH = 56908, // Inflicts 8750 to 11250 Fire damage to enemies in a cone in front of the caster. - SPELL_FLAME_BREATH_H = 58956, // Inflicts 10938 to 14062 Fire damage to enemies in a cone in front of the caster. - SPELL_TAIL_LASH = 56910, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec. - SPELL_TAIL_LASH_H = 58957, // A sweeping tail strike hits all enemies behind the caster, inflicting 4375 to 5625 damage and stunning them for 2 sec. - SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%. - SPELL_LAVA_STRIKE = 57571, // (Real spell casted should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572) - SPELL_TWILIGHT_REVENGE = 60639, - - SPELL_PYROBUFFET = 56916, // currently used for hard enrage after 15 minutes - SPELL_PYROBUFFET_RANGE = 58907, // possibly used when player get too far away from dummy creatures (2x Creature entry 30494) - - SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO - SPELL_TWILIGHT_SHIFT = 57874, // Twilight Shift Aura - SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase - SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave) - - //Mini bosses common spells - SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase - - //Miniboses (Vesperon, Shadron, Tenebron) - SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster. - SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster. - - SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec. - SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec. - - //Vesperon - //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times - NPC_ACOLYTE_OF_VESPERON = 31219, // Acolyte of Vesperon - SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%. - SPELL_TWILIGHT_TORMENT_VESP = 57948, // (Shadow only) trigger 57935 then 57988 - SPELL_TWILIGHT_TORMENT_VESP_ACO = 58853, // (Fire and Shadow) trigger 58835 then 57988 - - //Shadron - //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times - NPC_ACOLYTE_OF_SHADRON = 31218, // Acolyte of Shadron - SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%. - SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron - SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion - SPELL_VOID_BLAST = 57581, // Twilight Fissure - SPELL_VOID_BLAST_H = 59128, - - //Tenebron - //in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708 - SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%. - //Tenebron, dummy spell - SPELL_SUMMON_TWILIGHT_WHELP = 58035, // doesn't work, will spawn NPC_TWILIGHT_WHELP - SPELL_SUMMON_SARTHARION_TWILIGHT_WHELP = 58826, // doesn't work, will spawn NPC_SHARTHARION_TWILIGHT_WHELP - - SPELL_HATCH_EGGS_H = 59189, - SPELL_HATCH_EGGS = 58542, - SPELL_HATCH_EGGS_EFFECT_H = 59190, - SPELL_HATCH_EGGS_EFFECT = 58685, - NPC_TWILIHT_WHELP = 31214, - NPC_TWILIGHT_EGG = 30882, - - //Whelps - NPC_TWILIGHT_WHELP = 30890, - NPC_SHARTHARION_TWILIGHT_WHELP = 31214, - SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s - - //flame tsunami - SPELL_FLAME_TSUNAMI = 57494, // the visual dummy - SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction - SPELL_FLAME_TSUNAMI_DMG_AURA = 57492, // periodic damage, npc has this aura - - NPC_FLAME_TSUNAMI = 30616, // for the flame waves - NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike - - //using these custom points for dragons start and end - POINT_ID_INIT = 100, - POINT_ID_LAND = 200, - - //Achievements - ACHIEV_TWILIGHT_ASSIST = 2049, - H_ACHIEV_TWILIGHT_ASSIST = 2052, - ACHIEV_TWILIGHT_DUO = 2050, - H_ACHIEV_TWILIGHT_DUO = 2053, - ACHIEV_TWILIGHT_ZONE = 2051, - H_ACHIEV_TWILIGHT_ZONE = 2054 -}; - -struct Waypoint -{ - float m_fX, m_fY, m_fZ; -}; -struct Location -{ - float x,y,z; -}; -struct Locations -{ - float x,y,z; -}; - -//each dragons special points. First where fly to before connect to connon, second where land point is. -Waypoint m_aTene[]= -{ - {3212.854, 575.597, 109.856}, //init - {3246.425, 565.367, 61.249} //end -}; - -Waypoint m_aShad[]= -{ - {3293.238, 472.223, 106.968}, - {3271.669, 526.907, 61.931} -}; - -Waypoint m_aVesp[]= -{ - {3193.310, 472.861, 102.697}, - {3227.268, 533.238, 59.995} -}; - -#define MAX_WAYPOINT 6 -//points around raid "isle", counter clockwise. should probably be adjusted to be more alike -Waypoint m_aDragonCommon[MAX_WAYPOINT]= -{ - {3214.012, 468.932, 98.652}, - {3244.950, 468.427, 98.652}, - {3283.520, 496.869, 98.652}, - {3287.316, 555.875, 98.652}, - {3250.479, 585.827, 98.652}, - {3209.969, 566.523, 98.652} -}; -static Location FlameRight1Spawn = { 3197.59, 495.336, 57.8462 }; -static Location FlameRight1Direction = { 3289.28, 521.569, 55.1526 }; -static Location FlameRight2Spawn = { 3201.94, 543.324, 56.7209 }; -static Location FlameRight2Direction = { 3288.98, 549.291, 55.1232 }; -static Location FlameLeft1Spawn = { 3290.24, 521.725, 55.1238 }; -static Location FlameLeft1Direction = { 3199.94, 516.891, 57.5112 }; -static Location FlameLeft2Spawn = { 3290.33, 586.51, 55.063 }; -static Location FlameLeft2Direction = { 3195.03, 479.135, 55.6331 }; - -static Location AcolyteofShadron = { 3363.92, 534.703, 97.2683 }; -static Location AcolyteofShadron2 = { 3246.57, 551.263, 58.6164 }; -static Location AcolyteofVesperon = { 3145.68, 520.71, 89.7 }; -static Location AcolyteofVesperon2 = { 3246.57, 551.263, 58.6164 }; - -Locations TwilightEggs[] = -{ - {3219.28, 669.121 , 88.5549}, - {3221.55, 682.852 , 90.5361}, - {3239.77, 685.94 , 90.3168}, - {3250.33, 669.749 , 88.7637}, - {3246.6, 642.365 , 84.8752}, - {3233.68, 653.117 , 85.7051} -}; -Locations TwilightEggsSarth[] = -{ - {3261.75, 539.14 , 58.6082}, - {3257.41, 512.939 , 58.5432}, - {3231.04, 498.281 , 58.6439} -}; - -/*###### -## Boss Sartharion -######*/ - -struct boss_sartharionAI : public ScriptedAI -{ - boss_sartharionAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool m_bIsBerserk; - bool m_bIsSoftEnraged; - - uint32 m_uiEnrageTimer; - bool m_bIsHardEnraged; - - uint32 m_uiTenebronTimer; - uint32 m_uiShadronTimer; - uint32 m_uiVesperonTimer; - - uint32 m_uiFlameTsunamiTimer; - uint32 m_uiFlameBreathTimer; - uint32 m_uiTailSweepTimer; - uint32 m_uiCleaveTimer; - uint32 m_uiLavaStrikeTimer; - - bool m_bHasCalledTenebron; - bool m_bHasCalledShadron; - bool m_bHasCalledVesperon; - - uint32 achievProgress; - - void Reset() - { - m_bIsBerserk = false; - m_bIsSoftEnraged = false; - - m_uiEnrageTimer = 15*MINUTE*IN_MILISECONDS; - m_bIsHardEnraged = false; - - m_uiTenebronTimer = 30000; - m_uiShadronTimer = 75000; - m_uiVesperonTimer = 120000; - - m_uiFlameTsunamiTimer = 30000; - m_uiFlameBreathTimer = 20000; - m_uiTailSweepTimer = 20000; - m_uiCleaveTimer = 7000; - m_uiLavaStrikeTimer = 5000; - - m_bHasCalledTenebron = false; - m_bHasCalledShadron = false; - m_bHasCalledVesperon = false; - - if (me->HasAura(SPELL_TWILIGHT_REVENGE)) - me->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE); - - me->ResetLootMode(); - - achievProgress = 0; - } - - void JustReachedHome() - { - if (pInstance) - pInstance->SetData(TYPE_SARTHARION_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_SARTHARION_AGGRO,me); - DoZoneInCombat(); - - if (pInstance) - { - pInstance->SetData(TYPE_SARTHARION_EVENT, IN_PROGRESS); - FetchDragons(); - } - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_SARTHARION_DEATH,me); - - if (pInstance) - { - if (achievProgress >= 1) - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_ASSIST,H_ACHIEV_TWILIGHT_ASSIST)); - else if (achievProgress >= 2) - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_DUO,H_ACHIEV_TWILIGHT_DUO)); - else if (achievProgress == 3) - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_ZONE,H_ACHIEV_TWILIGHT_ZONE)); - - pInstance->SetData(TYPE_SARTHARION_EVENT, DONE); - } - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SARTHARION_SLAY_1,SAY_SARTHARION_SLAY_2,SAY_SARTHARION_SLAY_3), me); - } - - // me->ResetLootMode() is called from Reset() - // AddDrakeLootMode() should only ever be called from FetchDragons(), which is called from Aggro() - void AddDrakeLootMode() - { - if (me->HasLootMode(LOOT_MODE_HARD_MODE_2)) // Has two Drake loot modes - me->AddLootMode(LOOT_MODE_HARD_MODE_3); // Add 3rd Drake loot mode - else if (me->HasLootMode(LOOT_MODE_HARD_MODE_1)) // Has one Drake loot mode - me->AddLootMode(LOOT_MODE_HARD_MODE_2); // Add 2nd Drake loot mode - else // Has no Drake loot modes - me->AddLootMode(LOOT_MODE_HARD_MODE_1); // Add 1st Drake loot mode - } - - void FetchDragons() - { - if (!pInstance) - return; - Creature* pFetchTene = Unit::GetCreature(*me, pInstance->GetData64(DATA_TENEBRON)); - Creature* pFetchShad = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON)); - Creature* pFetchVesp = Unit::GetCreature(*me, pInstance->GetData64(DATA_VESPERON)); - - //if at least one of the dragons are alive and are being called - bool bCanUseWill = false; - - if (pFetchTene && pFetchTene->isAlive() && !pFetchTene->getVictim()) - { - bCanUseWill = true; - pFetchTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ); - - if (!pFetchTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pFetchTene->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (pFetchShad && pFetchShad->isAlive() && !pFetchShad->getVictim()) - { - bCanUseWill = true; - pFetchShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ); - - if (!pFetchShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pFetchShad->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (pFetchVesp && pFetchVesp->isAlive() && !pFetchVesp->getVictim()) - { - bCanUseWill = true; - pFetchVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ); - - if (!pFetchVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pFetchVesp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (bCanUseWill) - DoCast(me, SPELL_WILL_OF_SARTHARION); - } - - void CallDragon(uint32 uiDataId) - { - if (pInstance) - { - if (Creature *pTemp = Unit::GetCreature(*me,pInstance->GetData64(uiDataId))) - { - if (pTemp->isAlive() && !pTemp->getVictim()) - { - if (pTemp->HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE)) - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - if (pTemp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - int32 iTextId = 0; - AddDrakeLootMode(); - - achievProgress++; - - switch(pTemp->GetEntry()) - { - case NPC_TENEBRON: - iTextId = SAY_SARTHARION_CALL_TENEBRON; - pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aTene[1].m_fX, m_aTene[1].m_fY, m_aTene[1].m_fZ); - break; - case NPC_SHADRON: - iTextId = SAY_SARTHARION_CALL_SHADRON; - pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aShad[1].m_fX, m_aShad[1].m_fY, m_aShad[1].m_fZ); - break; - case NPC_VESPERON: - iTextId = SAY_SARTHARION_CALL_VESPERON; - pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aVesp[1].m_fX, m_aVesp[1].m_fY, m_aVesp[1].m_fZ); - break; - } - - DoScriptText(iTextId, me); - } - } - } - } - - void SendFlameTsunami() - { - if (Map* pMap = me->GetMap()) - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (!PlayerList.isEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource() && i->getSource()->isAlive()) - DoScriptText(WHISPER_LAVA_CHURN, me, i->getSource()); - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - Unit* pTene = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_TENEBRON) : 0); - Unit* pShad = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SHADRON) : 0); - Unit* pVesp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_VESPERON) : 0); - - //spell will target dragons, if they are still alive at 35% - if (!m_bIsBerserk && (me->GetHealth()*100 / me->GetMaxHealth()) <= 35 - && ((pTene && pTene->isAlive()) || (pShad && pShad->isAlive()) || (pVesp && pVesp->isAlive()))) - { - DoScriptText(SAY_SARTHARION_BERSERK, me); - DoCast(me, SPELL_BERSERK); - m_bIsBerserk = true; - } - - //soft enrage - if (!m_bIsSoftEnraged && (me->GetHealth()*100 / me->GetMaxHealth()) <= 10) - { - // TODO - m_bIsSoftEnraged = true; - } - - // hard enrage - if (!m_bIsHardEnraged) - { - if (m_uiEnrageTimer <= uiDiff) - { - DoCast(me, SPELL_PYROBUFFET, true); - m_bIsHardEnraged = true; - } - else - m_uiEnrageTimer -= uiDiff; - } - - // flame tsunami - if (m_uiFlameTsunamiTimer <= uiDiff) - { - SendFlameTsunami(); - switch(urand(0,1)) - { - case 0: - { - if (Creature *Right1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight1Spawn.x, FlameRight1Spawn.y , FlameRight1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) - Right1->GetMotionMaster()->MovePoint(0, FlameRight1Direction.x, FlameRight1Direction.y, FlameRight1Direction.z); - if (Creature *Right2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight2Spawn.x, FlameRight2Spawn.y , FlameRight2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) - Right2->GetMotionMaster()->MovePoint(0, FlameRight2Direction.x, FlameRight2Direction.y, FlameRight2Direction.z); - break; - } - case 1: - { - if (Creature *Left1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft1Spawn.x, FlameLeft1Spawn.y , FlameLeft1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) - Left1->GetMotionMaster()->MovePoint(0, FlameLeft1Direction.x, FlameLeft1Direction.y, FlameLeft1Direction.z); - if (Creature *Left2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft2Spawn.x, FlameLeft2Spawn.y , FlameLeft2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) - Left2->GetMotionMaster()->MovePoint(0, FlameLeft2Direction.x, FlameLeft2Direction.y, FlameLeft2Direction.z); - break; - } - } - - m_uiFlameTsunamiTimer = 30000; - } - else - m_uiFlameTsunamiTimer -= uiDiff; - - // flame breath - if (m_uiFlameBreathTimer <= uiDiff) - { - DoScriptText(SAY_SARTHARION_BREATH, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_FLAME_BREATH, SPELL_FLAME_BREATH_H)); - m_uiFlameBreathTimer = urand(25000,35000); - } - else - m_uiFlameBreathTimer -= uiDiff; - - // Tail Sweep - if (m_uiTailSweepTimer <= uiDiff) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_TAIL_LASH, SPELL_TAIL_LASH_H)); - m_uiTailSweepTimer = urand(15000,20000); - } - else - m_uiTailSweepTimer -= uiDiff; - - // Cleave - if (m_uiCleaveTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - m_uiCleaveTimer = urand(7000,10000); - } - else - m_uiCleaveTimer -= uiDiff; - - // Lavas Strike - if (m_uiLavaStrikeTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_LAVA_STRIKE); - - if (urand(0,4) == 4) - DoScriptText(RAND(SAY_SARTHARION_SPECIAL_1,SAY_SARTHARION_SPECIAL_2,SAY_SARTHARION_SPECIAL_3), me); - } - m_uiLavaStrikeTimer = urand(5000,20000); - } - else - m_uiLavaStrikeTimer -= uiDiff; - - // call tenebron - if (!m_bHasCalledTenebron && m_uiTenebronTimer <= uiDiff) - { - CallDragon(DATA_TENEBRON); - m_bHasCalledTenebron = true; - } - else - m_uiTenebronTimer -= uiDiff; - - // call shadron - if (!m_bHasCalledShadron && m_uiShadronTimer <= uiDiff) - { - CallDragon(DATA_SHADRON); - m_bHasCalledShadron = true; - } - else - m_uiShadronTimer -= uiDiff; - - // call vesperon - if (!m_bHasCalledVesperon && m_uiVesperonTimer <= uiDiff) - { - CallDragon(DATA_VESPERON); - m_bHasCalledVesperon = true; - } - else - m_uiVesperonTimer -= uiDiff; - - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(uiDiff); - } -}; - -CreatureAI* GetAI_boss_sartharion(Creature* pCreature) -{ - return new boss_sartharionAI(pCreature); -} - -enum TeneText -{ - SAY_TENEBRON_AGGRO = -1615009, - SAY_TENEBRON_SLAY_1 = -1615010, - SAY_TENEBRON_SLAY_2 = -1615011, - SAY_TENEBRON_DEATH = -1615012, - SAY_TENEBRON_BREATH = -1615013, - SAY_TENEBRON_RESPOND = -1615014, - SAY_TENEBRON_SPECIAL_1 = -1615015, - SAY_TENEBRON_SPECIAL_2 = -1615016 -}; - -enum ShadText -{ - SAY_SHADRON_AGGRO = -1615000, - SAY_SHADRON_SLAY_1 = -1615001, - SAY_SHADRON_SLAY_2 = -1615002, - SAY_SHADRON_DEATH = -1615003, - SAY_SHADRON_BREATH = -1615004, - SAY_SHADRON_RESPOND = -1615005, - SAY_SHADRON_SPECIAL_1 = -1615006, - SAY_SHADRON_SPECIAL_2 = -1615007 -}; - -enum VespText -{ - SAY_VESPERON_AGGRO = -1615033, - SAY_VESPERON_SLAY_1 = -1615034, - SAY_VESPERON_SLAY_2 = -1615035, - SAY_VESPERON_DEATH = -1615036, - SAY_VESPERON_BREATH = -1615037, - SAY_VESPERON_RESPOND = -1615038, - SAY_VESPERON_SPECIAL_1 = -1615039, - SAY_VESPERON_SPECIAL_2 = -1615040 -}; - -//to control each dragons common abilities -struct dummy_dragonAI : public ScriptedAI -{ - dummy_dragonAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 m_uiWaypointId; - uint32 m_uiMoveNextTimer; - int32 m_iPortalRespawnTime; - bool m_bCanMoveFree; - - void Reset() - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (GameObject* TwilightPortal = GameObject::GetGameObject((*me), pInstance->GetData64(GO_TWILIGHT_PORTAL))) - TwilightPortal->SetGoState(GO_STATE_READY); - - m_uiWaypointId = 0; - m_uiMoveNextTimer = 500; - m_iPortalRespawnTime = 30000; - m_bCanMoveFree = false; - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (!pInstance || uiType != POINT_MOTION_TYPE) - return; - - debug_log("dummy_dragonAI: %s reached point %u", me->GetName(), uiPointId); - - //if healers messed up the raid and we was already initialized - if (pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) - { - EnterEvadeMode(); - return; - } - - //this is end, if we reach this, don't do much - if (uiPointId == POINT_ID_LAND) - { - me->GetMotionMaster()->Clear(); - m_bCanMoveFree = false; - return; - } - - //get amount of common points - uint32 uiCommonWPCount = sizeof(m_aDragonCommon)/sizeof(Waypoint); - - //increase - m_uiWaypointId = uiPointId+1; - - //if we have reached a point bigger or equal to count, it mean we must reset to point 0 - if (m_uiWaypointId >= uiCommonWPCount) - { - if (!m_bCanMoveFree) - m_bCanMoveFree = true; - - m_uiWaypointId = 0; - } - - m_uiMoveNextTimer = 500; - } - - //used when open portal and spawn mobs in phase - void DoRaidWhisper(int32 iTextId) - { - Map* pMap = me->GetMap(); - - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - DoScriptText(iTextId, me, i->getSource()); - } - } - } - - //"opens" the portal and does the "opening" whisper - void OpenPortal() - { - int32 iTextId = 0; - - //there are 4 portal spawn locations, each are expected to be spawned with negative spawntimesecs in database - - //using a grid search here seem to be more efficient than caching all four guids - //in instance script and calculate range to each. - GameObject* pPortal = me->FindNearestGameObject(GO_TWILIGHT_PORTAL,50.0f); - if (GameObject* TwilightPortal = GameObject::GetGameObject((*me), pInstance->GetData64(GO_TWILIGHT_PORTAL))) - TwilightPortal->SetGoState(GO_STATE_ACTIVE); - - switch(me->GetEntry()) - { - case NPC_TENEBRON: - { - iTextId = WHISPER_HATCH_EGGS; - if (pInstance && pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[0].x, TwilightEggs[0].y, TwilightEggs[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - else - me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggsSarth[0].x, TwilightEggsSarth[0].y, TwilightEggsSarth[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - break; - } - case NPC_SHADRON: - { - iTextId = WHISPER_OPEN_PORTAL; - if (pInstance && !pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron.x, AcolyteofShadron.y , AcolyteofShadron.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - else - me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2.x, AcolyteofShadron2.y , AcolyteofShadron2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - - break; - } - case NPC_VESPERON: - { - if (pInstance && !pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon.x, AcolyteofVesperon.y , AcolyteofVesperon.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - else - me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon2.x, AcolyteofVesperon2.y , AcolyteofVesperon2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - - iTextId = WHISPER_OPEN_PORTAL; - break; - } - } - - DoRaidWhisper(iTextId); - - //By using SetRespawnTime() we will actually "spawn" the object with our defined time. - //Once time is up, portal will disappear again. - if (pPortal && !pPortal->isSpawned()) - pPortal->SetRespawnTime(m_iPortalRespawnTime); - - //Unclear what are expected to happen if one drake has a portal open already - //Refresh respawnTime so time again are set to 30secs? - } - - void JustDied(Unit* /*pKiller*/) - { - int32 iTextId = 0; - uint32 uiSpellId = 0; - - switch(me->GetEntry()) - { - case NPC_TENEBRON: - iTextId = SAY_TENEBRON_DEATH; - uiSpellId = SPELL_POWER_OF_TENEBRON; - break; - case NPC_SHADRON: - iTextId = SAY_SHADRON_DEATH; - uiSpellId = SPELL_POWER_OF_SHADRON; - break; - case NPC_VESPERON: - iTextId = SAY_VESPERON_DEATH; - uiSpellId = SPELL_POWER_OF_VESPERON; - break; - } - - DoScriptText(iTextId, me); - - me->RemoveOwnedAura(uiSpellId); - - if (pInstance) - { - // not if solo mini-boss fight - if (pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) - return; - - // Twilight Revenge to main boss - if (Unit* pSartharion = Unit::GetUnit((*me), pInstance->GetData64(DATA_SARTHARION))) - if (pSartharion->isAlive()) - DoCast(pSartharion, SPELL_TWILIGHT_REVENGE, true); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_bCanMoveFree && m_uiMoveNextTimer) - { - if (m_uiMoveNextTimer <= uiDiff) - { - if (m_uiWaypointId < MAX_WAYPOINT) - me->GetMotionMaster()->MovePoint(m_uiWaypointId, - m_aDragonCommon[m_uiWaypointId].m_fX, m_aDragonCommon[m_uiWaypointId].m_fY, m_aDragonCommon[m_uiWaypointId].m_fZ); - - debug_log("dummy_dragonAI: %s moving to point %u", me->GetName(), m_uiWaypointId); - m_uiMoveNextTimer = 0; - } - else - m_uiMoveNextTimer -= uiDiff; - } - } -}; - -/*###### -## Mob Tenebron -######*/ - -struct mob_tenebronAI : public dummy_dragonAI -{ - mob_tenebronAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} - - uint32 m_uiShadowBreathTimer; - uint32 m_uiShadowFissureTimer; - uint32 m_uiHatchEggTimer; - - void Reset() - { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiHatchEggTimer = 30000; - } - - void Aggro(Unit* /*pWho*/) - { - DoScriptText(SAY_TENEBRON_AGGRO, me); - DoZoneInCombat(); - DoCast(me, SPELL_POWER_OF_TENEBRON); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_TENEBRON_SLAY_1,SAY_TENEBRON_SLAY_2), me); - /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - achievProgress = 1;*/ - } - - void UpdateAI(const uint32 uiDiff) - { - //if no target, update dummy and return - if (!UpdateVictim()) - { - dummy_dragonAI::UpdateAI(uiDiff); - return; - } - - // shadow fissure - if (m_uiShadowFissureTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE)); - - m_uiShadowFissureTimer = urand(15000,20000); - } - else - m_uiShadowFissureTimer -= uiDiff; - - // Hach Egg - if (m_uiHatchEggTimer <= uiDiff) - { - OpenPortal(); - m_uiHatchEggTimer = 30000; - } - else - m_uiHatchEggTimer -= uiDiff; - - // shadow breath - if (m_uiShadowBreathTimer <= uiDiff) - { - DoScriptText(SAY_TENEBRON_BREATH, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); - m_uiShadowBreathTimer = urand(20000,25000); - } - else - m_uiShadowBreathTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_tenebron(Creature* pCreature) -{ - return new mob_tenebronAI(pCreature); -} - -/*###### -## Mob Shadron -######*/ - -struct mob_shadronAI : public dummy_dragonAI -{ - mob_shadronAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} - - uint32 m_uiShadowBreathTimer; - uint32 m_uiShadowFissureTimer; - uint32 m_uiAcolyteShadronTimer; - - void Reset() - { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiAcolyteShadronTimer = 60000; - - if (me->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) - me->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); - - if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) - me->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); - } - - void Aggro(Unit* /*pWho*/) - { - DoScriptText(SAY_SHADRON_AGGRO,me); - DoZoneInCombat(); - DoCast(me, SPELL_POWER_OF_SHADRON); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SHADRON_SLAY_1,SAY_SHADRON_SLAY_2), me); - /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - achievProgress = 2;*/ - } - - void UpdateAI(const uint32 uiDiff) - { - //if no target, update dummy and return - if (!UpdateVictim()) - { - dummy_dragonAI::UpdateAI(uiDiff); - return; - } - - // shadow fissure - if (m_uiShadowFissureTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H)); - - m_uiShadowFissureTimer = urand(15000,20000); - } - else - m_uiShadowFissureTimer -= uiDiff; - - // Portal Event - if (m_uiAcolyteShadronTimer <= uiDiff) - { - if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) - return; - - OpenPortal(); - m_uiAcolyteShadronTimer = urand(60000,65000); - } - else - m_uiAcolyteShadronTimer -= uiDiff; - - // shadow breath - if (m_uiShadowBreathTimer <= uiDiff) - { - DoScriptText(SAY_SHADRON_BREATH, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); - m_uiShadowBreathTimer = urand(20000,25000); - } - else - m_uiShadowBreathTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_shadron(Creature* pCreature) -{ - return new mob_shadronAI(pCreature); -} - -/*###### -## Mob Vesperon -######*/ - -struct mob_vesperonAI : public dummy_dragonAI -{ - mob_vesperonAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} - - uint32 m_uiShadowBreathTimer; - uint32 m_uiShadowFissureTimer; - uint32 m_uiAcolyteVesperonTimer; - - void Reset() - { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiAcolyteVesperonTimer = 60000; - } - - void Aggro(Unit* /*pWho*/) - { - DoScriptText(SAY_VESPERON_AGGRO,me); - DoZoneInCombat(); - DoCast(me, SPELL_POWER_OF_VESPERON); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_VESPERON_SLAY_1,SAY_VESPERON_SLAY_2), me); - /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - achievProgress = 3;*/ - } - - void UpdateAI(const uint32 uiDiff) - { - //if no target, update dummy and return - if (!UpdateVictim()) - { - dummy_dragonAI::UpdateAI(uiDiff); - return; - } - - // shadow fissure - if (m_uiShadowFissureTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H)); - - m_uiShadowFissureTimer = urand(15000,20000); - } - else - m_uiShadowFissureTimer -= uiDiff; - - // Portal Event - if (m_uiAcolyteVesperonTimer <= uiDiff) - { - OpenPortal(); - DoCast(me->getVictim(), SPELL_TWILIGHT_TORMENT_VESP); - m_uiAcolyteVesperonTimer = urand(60000,70000); - } - else - m_uiAcolyteVesperonTimer -= uiDiff; - - // shadow breath - if (m_uiShadowBreathTimer <= uiDiff) - { - DoScriptText(SAY_VESPERON_BREATH, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); - m_uiShadowBreathTimer = urand(20000,25000); - } - else - m_uiShadowBreathTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_vesperon(Creature* pCreature) -{ - return new mob_vesperonAI(pCreature); -} - -/*###### -## Mob Acolyte of Shadron -######*/ - -struct mob_acolyte_of_shadronAI : public ScriptedAI -{ - mob_acolyte_of_shadronAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 uiShiftEffectTimer; - - void Reset() - { - uiShiftEffectTimer = 1000; - if (pInstance) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true); - - Creature* pSartharion = Unit::GetCreature(*me, pInstance->GetData64(DATA_SARTHARION)); - if (Creature* pShadron = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON))) - //if not solo figth, buff main boss, else place debuff on mini-boss. both spells TARGET_SCRIPT - if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - pSartharion->CastSpell(me, SPELL_GIFT_OF_TWILIGTH_SAR, true); - else - { - pShadron->CastSpell(me, SPELL_GIFT_OF_TWILIGTH_SHA,true); - pShadron->AddThreat(pTarget, 100.0f); - AttackStart(pShadron->getVictim()); - } - } - me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER,me); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - //Creature* pDebuffTarget = NULL; - Map *map = me->GetMap(); - if (map->IsDungeon()) - { - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT,0) && !i->getSource()->getVictim()) - { - i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_SHIFT_REMOVAL_ALL,true); - i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_RESIDUE,true); - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); - } - } - } - - if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - { - //not solo fight, so main boss has deduff - Creature* pDebuffTarget = Unit::GetCreature(*me, pInstance->GetData64(DATA_SARTHARION)); - if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SAR)) - pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SAR); - } - else - { - //event not in progress, then solo fight and must remove debuff mini-boss - Creature* pDebuffTarget = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON)); - if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) - pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); - } - } - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_acolyte_of_shadron(Creature* pCreature) -{ - return new mob_acolyte_of_shadronAI(pCreature); -} - -/*###### -## Mob Acolyte of Vesperon -######*/ - -struct mob_acolyte_of_vesperonAI : public ScriptedAI -{ - mob_acolyte_of_vesperonAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - { - me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER,me); - } - DoCast(me, SPELL_TWILIGHT_TORMENT_VESP_ACO); - } - - void JustDied(Unit* /*pKiller*/) - { - // remove twilight torment on Vesperon - if (pInstance) - { - Creature* pVesperon = Unit::GetCreature(*me, pInstance->GetData64(DATA_VESPERON)); - - if (pVesperon && pVesperon->isAlive() && pVesperon->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) - pVesperon->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); - - Map *map = me->GetMap(); - if (map->IsDungeon()) - { - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT,0) && !i->getSource()->getVictim()) - { - i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_SHIFT_REMOVAL_ALL,true); - i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_RESIDUE,true); - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); - } - if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_TORMENT_VESP,0) && !i->getSource()->getVictim()) - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); - } - } - - } - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_acolyte_of_vesperon(Creature* pCreature) -{ - return new mob_acolyte_of_vesperonAI(pCreature); -} - -/*###### -## Mob Twilight Eggs -######*/ - -struct mob_twilight_eggsAI : public Scripted_NoMovementAI -{ - mob_twilight_eggsAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - uint32 m_uiFadeArmorTimer; - uint32 m_uiHatchEggTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - m_uiHatchEggTimer = 20000; - m_uiFadeArmorTimer = 1000; - } - void SpawnWhelps() - { - if (!pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - else - me->SummonCreature(NPC_SHARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - me->DealDamage(me, me->GetHealth()); - } - void UpdateAI(const uint32 uiDiff) - { - if (m_uiHatchEggTimer <= uiDiff) - { - SpawnWhelps(); - } - else - m_uiHatchEggTimer -= uiDiff; - } - void AttackStart(Unit* /*pWho*/) {} - void MoveInLineOfSight(Unit* /*pWho*/) {} -}; - -CreatureAI* GetAI_mob_twilight_eggs(Creature* pCreature) -{ - return new mob_twilight_eggsAI(pCreature); -} - -/*###### -## Flame Tzunami -######*/ -struct npc_flame_tsunamiAI : public ScriptedAI -{ - npc_flame_tsunamiAI(Creature* pCreature) : ScriptedAI(pCreature) - { - me->HasAura(SPELL_FLAME_TSUNAMI_DMG_AURA); - DoCast(me, SPELL_FLAME_TSUNAMI); - } - - uint32 Tsunami_Timer; - - void Reset() - { - Tsunami_Timer = 100; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void UpdateAI(const uint32 diff) - { - if (Tsunami_Timer <= diff) - { - DoCast(me, SPELL_FLAME_TSUNAMI_DMG_AURA); - Tsunami_Timer = 1000; - } else Tsunami_Timer -= diff; - } -}; -// Twilight Fissure -struct npc_twilight_fissureAI : public Scripted_NoMovementAI -{ - npc_twilight_fissureAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - Reset(); - } - - uint32 VoidBlast_Timer; - - void Reset() - { - VoidBlast_Timer = 5000; - } - - void UpdateAI(const uint32 diff) - { - if (VoidBlast_Timer <= diff) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_VOID_BLAST, SPELL_VOID_BLAST_H)); - VoidBlast_Timer = 9000; - me->Kill(me); - } else VoidBlast_Timer -= diff; - } -}; - - -CreatureAI* GetAI_npc_flame_tsunami(Creature* pCreature) -{ - return new npc_flame_tsunamiAI(pCreature); -} - -CreatureAI* GetAI_npc_twilight_fissure(Creature* pCreature) -{ - return new npc_twilight_fissureAI(pCreature); -} - -/*###### -## Mob Twilight Whelps -######*/ - -struct mob_twilight_whelpAI : public ScriptedAI -{ - mob_twilight_whelpAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 m_uiFadeArmorTimer; - - void Reset() - { - m_uiFadeArmorTimer = 1000; - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // twilight torment - if (m_uiFadeArmorTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_FADE_ARMOR); - m_uiFadeArmorTimer = urand(5000,10000); - } - else - m_uiFadeArmorTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_twilight_whelp(Creature* pCreature) -{ - return new mob_twilight_whelpAI(pCreature); -} - -void AddSC_boss_sartharion() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sartharion"; - newscript->GetAI = &GetAI_boss_sartharion; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_vesperon"; - newscript->GetAI = &GetAI_mob_vesperon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadron"; - newscript->GetAI = &GetAI_mob_shadron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tenebron"; - newscript->GetAI = &GetAI_mob_tenebron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_acolyte_of_shadron"; - newscript->GetAI = &GetAI_mob_acolyte_of_shadron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_acolyte_of_vesperon"; - newscript->GetAI = &GetAI_mob_acolyte_of_vesperon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_twilight_eggs"; - newscript->GetAI = &GetAI_mob_twilight_eggs; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_flame_tsunami"; - newscript->GetAI = &GetAI_npc_flame_tsunami; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_twilight_fissure"; - newscript->GetAI = &GetAI_npc_twilight_fissure; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_twilight_whelp"; - newscript->GetAI = &GetAI_mob_twilight_whelp; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp b/src/server/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp deleted file mode 100644 index 7ef8e03c779..00000000000 --- a/src/server/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "ScriptedPch.h" -#include "obsidian_sanctum.h" - -#define MAX_ENCOUNTER 1 - -/* Obsidian Sanctum encounters: -0 - Sartharion -*/ - -struct instance_obsidian_sanctum : public ScriptedInstance -{ - instance_obsidian_sanctum(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint64 m_uiSartharionGUID; - uint64 m_uiTenebronGUID; - uint64 m_uiShadronGUID; - uint64 m_uiVesperonGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiSartharionGUID = 0; - m_uiTenebronGUID = 0; - m_uiShadronGUID = 0; - m_uiVesperonGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_SARTHARION: - m_uiSartharionGUID = pCreature->GetGUID(); - break; - //three dragons below set to active state once created. - //we must expect bigger raid to encounter main boss, and then three dragons must be active due to grid differences - case NPC_TENEBRON: - m_uiTenebronGUID = pCreature->GetGUID(); - pCreature->setActive(true); - break; - case NPC_SHADRON: - m_uiShadronGUID = pCreature->GetGUID(); - pCreature->setActive(true); - break; - case NPC_VESPERON: - m_uiVesperonGUID = pCreature->GetGUID(); - pCreature->setActive(true); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - if (uiType == TYPE_SARTHARION_EVENT) - m_auiEncounter[0] = uiData; - } - - uint32 GetData(uint32 uiType) - { - if (uiType == TYPE_SARTHARION_EVENT) - return m_auiEncounter[0]; - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_SARTHARION: - return m_uiSartharionGUID; - case DATA_TENEBRON: - return m_uiTenebronGUID; - case DATA_SHADRON: - return m_uiShadronGUID; - case DATA_VESPERON: - return m_uiVesperonGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_obsidian_sanctum(Map* pMap) -{ - return new instance_obsidian_sanctum(pMap); -} - -void AddSC_instance_obsidian_sanctum() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_obsidian_sanctum"; - newscript->GetInstanceData = &GetInstanceData_instance_obsidian_sanctum; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h b/src/server/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h deleted file mode 100644 index 59013174795..00000000000 --- a/src/server/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef DEF_OBSIDIAN_SANCTUM_H -#define DEF_OBSIDIAN_SANCTUM_H - -enum eTypes -{ - TYPE_SARTHARION_EVENT = 1, - - DATA_SARTHARION = 10, - DATA_TENEBRON = 11, - DATA_SHADRON = 12, - DATA_VESPERON = 13, - - NPC_SARTHARION = 28860, - NPC_TENEBRON = 30452, - NPC_SHADRON = 30451, - NPC_VESPERON = 30449, - GO_TWILIGHT_PORTAL = 193988 -}; - -#endif diff --git a/src/server/scripts/northrend/sholazar_basin.cpp b/src/server/scripts/northrend/sholazar_basin.cpp deleted file mode 100644 index b5df8998b4a..00000000000 --- a/src/server/scripts/northrend/sholazar_basin.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Sholazar_Basin -SD%Complete: 100 -SDComment: Quest support: 12570, 12573, 12621. -SDCategory: Sholazar_Basin -EndScriptData */ - -/* ContentData -npc_injured_rainspeaker_oracle -npc_vekjik -avatar_of_freya -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_injured_rainspeaker_oracle -######*/ - -#define GOSSIP_ITEM1 "I am ready to travel to your village now." - -enum eRainspeaker -{ - SAY_START_IRO = -1571000, - SAY_QUEST_ACCEPT_IRO = -1571001, - SAY_END_IRO = -1571002, - - QUEST_FORTUNATE_MISUNDERSTANDINGS = 12570, - FACTION_ESCORTEE_A = 774, - FACTION_ESCORTEE_H = 775 -}; - -struct npc_injured_rainspeaker_oracleAI : public npc_escortAI -{ - npc_injured_rainspeaker_oracleAI(Creature* c) : npc_escortAI(c) { c_guid = c->GetGUID(); } - - uint64 c_guid; - - void Reset() - { - me->RestoreFaction(); - // if we will have other way to assign this to only one npc remove this part - if (GUID_LOPART(me->GetGUID()) != 101030) - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 1: SetRun(); break; - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_JUMPING); - me->SetSpeed(MOVE_SWIM, 0.85f, true); - me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); - break; - case 19: - me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); - break; - case 28: - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->GroupEventHappens(QUEST_FORTUNATE_MISUNDERSTANDINGS, me); - // me->RestoreFaction(); - DoScriptText(SAY_END_IRO,me); - SetRun(false); - break; - } - } - - void JustDied(Unit* /*killer*/) - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - if (Player* pPlayer = GetPlayerForEscort()) - { - if (pPlayer->GetQuestStatus(QUEST_FORTUNATE_MISUNDERSTANDINGS) != QUEST_STATUS_COMPLETE) - pPlayer->FailQuest(QUEST_FORTUNATE_MISUNDERSTANDINGS); - } - } -}; - -bool GossipHello_npc_injured_rainspeaker_oracle(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_FORTUNATE_MISUNDERSTANDINGS) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_injured_rainspeaker_oracle(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(35.0f); - pCreature->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); - DoScriptText(SAY_START_IRO, pCreature); - - switch (pPlayer->GetTeam()){ - case ALLIANCE: - pCreature->setFaction(FACTION_ESCORTEE_A); - break; - case HORDE: - pCreature->setFaction(FACTION_ESCORTEE_H); - break; - } - } - return true; -} - -bool QuestAccept_npc_injured_rainspeaker_oracle(Player* /*pPlayer*/, Creature* pCreature, Quest const * /*_Quest*/) -{ - DoScriptText(SAY_QUEST_ACCEPT_IRO, pCreature); - return false; -} - -CreatureAI* GetAI_npc_injured_rainspeaker_oracle(Creature* pCreature) -{ - return new npc_injured_rainspeaker_oracleAI(pCreature); -} - -/*###### -## npc_vekjik -######*/ - -#define GOSSIP_VEKJIK_ITEM1 "Shaman Vekjik, I have spoken with the big-tongues and they desire peace. I have brought this offering on their behalf." -#define GOSSIP_VEKJIK_ITEM2 "No no... I had no intentions of betraying your people. I was only defending myself. it was all a misunderstanding." - -enum eVekjik -{ - GOSSIP_TEXTID_VEKJIK1 = 13137, - GOSSIP_TEXTID_VEKJIK2 = 13138, - - SAY_TEXTID_VEKJIK1 = -1000208, - - SPELL_FREANZYHEARTS_FURY = 51469, - - QUEST_MAKING_PEACE = 12573 -}; - -bool GossipHello_npc_vekjik(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_MAKING_PEACE) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VEKJIK_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VEKJIK1, pCreature->GetGUID()); - return true; - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_vekjik(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VEKJIK_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VEKJIK2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - DoScriptText(SAY_TEXTID_VEKJIK1, pCreature, pPlayer); - pPlayer->AreaExploredOrEventHappens(QUEST_MAKING_PEACE); - pCreature->CastSpell(pPlayer, SPELL_FREANZYHEARTS_FURY, false); - break; - } - - return true; -} - -/*###### -## avatar_of_freya -######*/ - -#define GOSSIP_ITEM_AOF1 "I want to stop the Scourge as much as you do. How can I help?" -#define GOSSIP_ITEM_AOF2 "You can trust me. I am no friend of the Lich King." -#define GOSSIP_ITEM_AOF3 "I will not fail." - -enum eFreya -{ - QUEST_FREYA_PACT = 12621, - - SPELL_FREYA_CONVERSATION = 52045, - - GOSSIP_TEXTID_AVATAR1 = 13303, - GOSSIP_TEXTID_AVATAR2 = 13304, - GOSSIP_TEXTID_AVATAR3 = 13305 -}; - -bool GossipHello_npc_avatar_of_freya(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_FREYA_PACT) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR1, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_avatar_of_freya(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AOF3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXTID_AVATAR3, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CastSpell(pPlayer, SPELL_FREYA_CONVERSATION, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - return true; -} - -/*###### -## npc_geezle -######*/ - -struct npc_bushwhackerAI : public ScriptedAI -{ - npc_bushwhackerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - MoveToSummoner(); - } - - void MoveToSummoner() - { - if (me->isSummon()) - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - if (pSummoner) - me->GetMotionMaster()->MovePoint(0,pSummoner->GetPositionX(),pSummoner->GetPositionY(),pSummoner->GetPositionZ()); - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_bushwhacker(Creature* pCreature) -{ - return new npc_bushwhackerAI(pCreature); -} - -/*###### -## npc_engineer_helice -######*/ - -enum eEnums -{ - SPELL_EXPLODE_CRYSTAL = 62487, - SPELL_FLAMES = 64561, - - SAY_WP_7 = -1800047, - SAY_WP_6 = -1800048, - SAY_WP_5 = -1800049, - SAY_WP_4 = -1800050, - SAY_WP_3 = -1800051, - SAY_WP_2 = -1800052, - SAY_WP_1 = -1800053, - - QUEST_DISASTER = 12688 -}; - -struct npc_engineer_heliceAI : public npc_escortAI -{ - npc_engineer_heliceAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - uint32 m_uiChatTimer; - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - switch (i) - { - case 0: - DoScriptText(SAY_WP_2, me); - break; - case 1: - DoScriptText(SAY_WP_3, me); - me->CastSpell(5918.33, 5372.91, -98.770, SPELL_EXPLODE_CRYSTAL, true); - me->SummonGameObject(184743, 5918.33, 5372.91, -98.770, 0, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN); //approx 3 to 4 seconds - me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); - break; - case 2: - DoScriptText(SAY_WP_4, me); - break; - case 7: - DoScriptText(SAY_WP_5, me); - break; - case 8: - me->CastSpell(5887.37, 5379.39, -91.289, SPELL_EXPLODE_CRYSTAL, true); - me->SummonGameObject(184743, 5887.37, 5379.39, -91.289, 0, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN); //approx 3 to 4 seconds - me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); - break; - case 9: - DoScriptText(SAY_WP_6, me); - break; - case 13: - if (pPlayer) - { - pPlayer->GroupEventHappens(QUEST_DISASTER, me); - DoScriptText(SAY_WP_7, me); - } - break; - } - } - - void Reset() - { - m_uiChatTimer = 4000; - } - void JustDied(Unit* /*pKiller*/) - { - Player* pPlayer = GetPlayerForEscort(); - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (pPlayer) - pPlayer->FailQuest(QUEST_DISASTER); - } - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (m_uiChatTimer <= uiDiff) - { - m_uiChatTimer = 12000; - } - else - m_uiChatTimer -= uiDiff; - } - } -}; - -CreatureAI* GetAI_npc_engineer_helice(Creature* pCreature) -{ - return new npc_engineer_heliceAI(pCreature); -} - -bool QuestAccept_npc_engineer_helice(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_DISASTER) - { - if (npc_engineer_heliceAI* pEscortAI = CAST_AI(npc_engineer_heliceAI, pCreature->AI())) - { - pCreature->GetMotionMaster()->MoveJumpTo(0, 0.4, 0.4); - pCreature->setFaction(113); - - pEscortAI->Start(false, false, pPlayer->GetGUID()); - DoScriptText(SAY_WP_1, pCreature); - } - } - return true; -} - -void AddSC_sholazar_basin() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "npc_injured_rainspeaker_oracle"; - newscript->GetAI = &GetAI_npc_injured_rainspeaker_oracle; - newscript->pGossipHello = &GossipHello_npc_injured_rainspeaker_oracle; - newscript->pGossipSelect = &GossipSelect_npc_injured_rainspeaker_oracle; - newscript->pQuestAccept = &QuestAccept_npc_injured_rainspeaker_oracle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_vekjik"; - newscript->pGossipHello = &GossipHello_npc_vekjik; - newscript->pGossipSelect = &GossipSelect_npc_vekjik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_avatar_of_freya"; - newscript->pGossipHello = &GossipHello_npc_avatar_of_freya; - newscript->pGossipSelect = &GossipSelect_npc_avatar_of_freya; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_bushwhacker"; - newscript->GetAI = &GetAI_npc_bushwhacker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_engineer_helice"; - newscript->GetAI = &GetAI_npc_engineer_helice; - newscript->pQuestAccept = &QuestAccept_npc_engineer_helice; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/storm_peaks.cpp b/src/server/scripts/northrend/storm_peaks.cpp deleted file mode 100644 index 9275e24bd2f..00000000000 --- a/src/server/scripts/northrend/storm_peaks.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/* Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_agnetta_tyrsdottar -######*/ - -#define SAY_AGGRO -1571003 -#define GOSSIP_AGNETTA "Skip the warmup, sister... or are you too scared to face soemeone your own size?" - -enum eAgnetta -{ - QUEST_ITS_THAT_YOUR_GOBLIN = 12969, - FACTION_HOSTILE_AT1 = 45 -}; - -struct npc_agnetta_tyrsdottarAI : public ScriptedAI -{ - npc_agnetta_tyrsdottarAI(Creature* pCreature) : ScriptedAI(pCreature) { } - - void Reset() - { - me->RestoreFaction(); - } -}; - -CreatureAI* GetAI_npc_agnetta_tyrsdottar(Creature* pCreature) -{ - return new npc_agnetta_tyrsdottarAI(pCreature); -} - -bool GossipHello_npc_agnetta_tyrsdottar(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_ITS_THAT_YOUR_GOBLIN) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AGNETTA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(13691, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_agnetta_tyrsdottar(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - DoScriptText(SAY_AGGRO, pCreature); - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(FACTION_HOSTILE_AT1); - pCreature->AI()->AttackStart(pPlayer); - } - - return true; -} - -/*###### -## npc_frostborn_scout -######*/ - -#define GOSSIP_ITEM1 "Are you okay? I've come to take you back to Frosthold if you can stand." -#define GOSSIP_ITEM2 "I'm sorry that I didn't get here sooner. What happened?" -#define GOSSIP_ITEM3 "I'll go get some help. Hang in there." - -enum eFrostbornScout -{ - QUEST_MISSING_SCOUTS = 12864 -}; - -bool GossipHello_npc_frostborn_scout(Player* pPlayer, Creature* pCreature) -{ - - if (pPlayer->GetQuestStatus(QUEST_MISSING_SCOUTS) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->PlayerTalkClass->SendGossipMenu(13611, pCreature->GetGUID()); - } - - return true; -} - -bool GossipSelect_npc_frostborn_scout(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->PlayerTalkClass->SendGossipMenu(13612, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->PlayerTalkClass->SendGossipMenu(13613, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->PlayerTalkClass->SendGossipMenu(13614, pCreature->GetGUID()); - pPlayer->AreaExploredOrEventHappens(QUEST_MISSING_SCOUTS); - break; - } - - return true; -} - -/*###### -## npc_thorim -######*/ - -#define GOSSIP_HN "Thorim?" -#define GOSSIP_SN1 "Can you tell me what became of Sif?" -#define GOSSIP_SN2 "He did more than that, Thorim. He controls Ulduar now." -#define GOSSIP_SN3 "It needn't end this way." - -enum eThorim -{ - QUEST_SIBLING_RIVALRY = 13064, - NPC_THORIM = 29445, - GOSSIP_TEXTID_THORIM1 = 13799, - GOSSIP_TEXTID_THORIM2 = 13801, - GOSSIP_TEXTID_THORIM3 = 13802, - GOSSIP_TEXTID_THORIM4 = 13803 -}; - -bool GossipHello_npc_thorim(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_SIBLING_RIVALRY) == QUEST_STATUS_INCOMPLETE) { - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM1, pCreature->GetGUID()); - return true; - } - return false; -} - -bool GossipSelect_npc_thorim(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM3, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM4, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CompleteQuest(QUEST_SIBLING_RIVALRY); - break; - } - return true; -} - -/*###### -## npc_goblin_prisoner -######*/ - -enum eGoblinPrisoner -{ - GO_RUSTY_CAGE = 191544 -}; - -struct npc_goblin_prisonerAI : public ScriptedAI -{ - npc_goblin_prisonerAI(Creature* pCreature) : ScriptedAI (pCreature){} - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - - if (GameObject* pGO = me->FindNearestGameObject(GO_RUSTY_CAGE,5.0f)) - { - if (pGO->GetGoState() == GO_STATE_ACTIVE) - pGO->SetGoState(GO_STATE_READY); - } - } - -}; - -CreatureAI* GetAI_npc_goblin_prisoner(Creature* pCreature) -{ - return new npc_goblin_prisonerAI(pCreature); -} - -/*###### -## npc_victorious_challenger -######*/ - -#define GOSSIP_CHALLENGER "Let's do this, sister." - -enum eVictoriousChallenger -{ - QUEST_TAKING_ALL_CHALLENGERS = 12971, - QUEST_DEFENDING_YOUR_TITLE = 13423, - - SPELL_SUNDER_ARMOR = 11971, - SPELL_REND_VC = 11977 -}; - -struct npc_victorious_challengerAI : public ScriptedAI -{ - npc_victorious_challengerAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 SunderArmorTimer; - uint32 RendTimer; - - void Reset() - { - me->RestoreFaction(); - - SunderArmorTimer = 10000; - RendTimer = 15000; - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (RendTimer < diff) - { - DoCast(me->getVictim(), SPELL_REND_VC, true); - RendTimer = 15000; - }else RendTimer -= diff; - - if (SunderArmorTimer < diff) - { - DoCast(me->getVictim(), SPELL_SUNDER_ARMOR, true); - SunderArmorTimer = 10000; - }else SunderArmorTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void KilledUnit(Unit* /*victim*/) - { - me->RestoreFaction(); - } - -}; - -bool GossipHello_npc_victorious_challenger(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_TAKING_ALL_CHALLENGERS) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_DEFENDING_YOUR_TITLE) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CHALLENGER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; - } - - return false; -} - -bool GossipSelect_npc_victorious_challenger(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(14); - pCreature->AI()->AttackStart(pPlayer); - } - - return true; -} - -CreatureAI* GetAI_npc_victorious_challenger(Creature* pCreature) -{ - return new npc_victorious_challengerAI(pCreature); -} - -/*###### -## npc_loklira_crone -######*/ - -#define GOSSIP_LOKLIRACRONE "Tell me about this proposal" -#define GOSSIP_LOKLIRACRONE1 "What happened then?" -#define GOSSIP_LOKLIRACRONE2 "You want me to take part in the Hyldsmeet to end the war?" -#define GOSSIP_LOKLIRACRONE3 "Very well. I'll take part in this competition." - -enum eLokliraCrone -{ - QUEST_HYLDSMEET = 12970, - - GOSSIP_TEXTID_LOK1 = 13778, - GOSSIP_TEXTID_LOK2 = 13779, - GOSSIP_TEXTID_LOK3 = 13780 -}; - -bool GossipHello_npc_loklira_crone(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_HYLDSMEET) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; - } - return false; -} - -bool GossipSelect_npc_loklira_crone(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK1, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOKLIRACRONE3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOK3, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CompleteQuest(QUEST_HYLDSMEET); - break; - } - return true; -} - -///////////////////// -///npc_injured_goblin -///////////////////// - -enum eInjuredGoblin -{ - QUEST_BITTER_DEPARTURE = 12832, - SAY_QUEST_ACCEPT = -1800042, - SAY_END_WP_REACHED = -1800043 -}; - -#define GOSSIP_ITEM_1 "I am ready, lets get you out of here" - -struct npc_injured_goblinAI : public npc_escortAI -{ - npc_injured_goblinAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - switch (i) - { - case 26: - DoScriptText(SAY_END_WP_REACHED, me, pPlayer); - break; - case 27: - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_BITTER_DEPARTURE, me); - break; - } - } - - void EnterCombat(Unit* /*pWho*/) {} - - void Reset() {} - - void JustDied(Unit* /*pKiller*/) - { - Player* pPlayer = GetPlayerForEscort(); - if (HasEscortState(STATE_ESCORT_ESCORTING) && pPlayer) - pPlayer->FailQuest(QUEST_BITTER_DEPARTURE); - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - if (!UpdateVictim()) - return; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_injured_goblin(Creature* pCreature) -{ - return new npc_injured_goblinAI(pCreature); -} - -bool GossipHello_npc_injured_goblin(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_BITTER_DEPARTURE) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->PlayerTalkClass->SendGossipMenu(9999999, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(999999, pCreature->GetGUID()); - return true; -} - -bool QuestAccept_npc_injured_goblin(Player* /*pPlayer*/, Creature* pCreature, Quest const *quest) -{ - if (quest->GetQuestId() == QUEST_BITTER_DEPARTURE) - DoScriptText(SAY_QUEST_ACCEPT, pCreature); - - return false; -} - -bool GossipSelect_npc_injured_goblin(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - npc_escortAI* pEscortAI = CAST_AI(npc_injured_goblinAI, pCreature->AI()); - - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pEscortAI->Start(true, true, pPlayer->GetGUID()); - pCreature->setFaction(113); - } - return true; -} - - -void AddSC_storm_peaks() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_agnetta_tyrsdottar"; - newscript->GetAI = &GetAI_npc_agnetta_tyrsdottar; - newscript->pGossipHello = &GossipHello_npc_agnetta_tyrsdottar; - newscript->pGossipSelect = &GossipSelect_npc_agnetta_tyrsdottar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_frostborn_scout"; - newscript->pGossipHello = &GossipHello_npc_frostborn_scout; - newscript->pGossipSelect = &GossipSelect_npc_frostborn_scout; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thorim"; - newscript->pGossipHello = &GossipHello_npc_thorim; - newscript->pGossipSelect = &GossipSelect_npc_thorim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_goblin_prisoner"; - newscript->GetAI = &GetAI_npc_goblin_prisoner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_victorious_challenger"; - newscript->GetAI = &GetAI_npc_victorious_challenger; - newscript->pGossipHello = &GossipHello_npc_victorious_challenger; - newscript->pGossipSelect = &GossipSelect_npc_victorious_challenger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_loklira_crone"; - newscript->pGossipHello = &GossipHello_npc_loklira_crone; - newscript->pGossipSelect = &GossipSelect_npc_loklira_crone; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_injured_goblin"; - newscript->GetAI = &GetAI_npc_injured_goblin; - newscript->pGossipHello = &GossipHello_npc_injured_goblin; - newscript->pGossipSelect = &GossipSelect_npc_injured_goblin; - newscript->pQuestAccept = &QuestAccept_npc_injured_goblin; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp b/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp deleted file mode 100644 index c2da2a24e71..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss General Bjarngrim -SD%Complete: 70% -SDComment: Waypoint needed, we expect boss to always have 2x Stormforged Lieutenant following -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - //Yell - SAY_AGGRO = -1602000, - SAY_SLAY_1 = -1602001, - SAY_SLAY_2 = -1602002, - SAY_SLAY_3 = -1602003, - SAY_DEATH = -1602004, - SAY_BATTLE_STANCE = -1602005, - EMOTE_BATTLE_STANCE = -1602006, - SAY_BERSEKER_STANCE = -1602007, - EMOTE_BERSEKER_STANCE = -1602008, - SAY_DEFENSIVE_STANCE = -1602009, - EMOTE_DEFENSIVE_STANCE = -1602010, - - SPELL_DEFENSIVE_STANCE = 53790, - //SPELL_DEFENSIVE_AURA = 41105, - SPELL_SPELL_REFLECTION = 36096, - SPELL_PUMMEL = 12555, - SPELL_KNOCK_AWAY = 52029, - SPELL_IRONFORM = 52022, - - SPELL_BERSEKER_STANCE = 53791, - //SPELL_BERSEKER_AURA = 41107, - SPELL_INTERCEPT = 58769, - SPELL_WHIRLWIND = 52027, - SPELL_CLEAVE = 15284, - - SPELL_BATTLE_STANCE = 53792, - //SPELL_BATTLE_AURA = 41106, - SPELL_MORTAL_STRIKE = 16856, - SPELL_SLAM = 52026, - - //OTHER SPELLS - //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other - //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above - - NPC_STORMFORGED_LIEUTENANT = 29240, - SPELL_ARC_WELD = 59085, - SPELL_RENEW_STEEL_N = 52774, - SPELL_RENEW_STEEL_H = 59160, - - EQUIP_SWORD = 37871, - EQUIP_SHIELD = 35642, - EQUIP_MACE = 43623, - - STANCE_DEFENSIVE = 0, - STANCE_BERSERKER = 1, - STANCE_BATTLE = 2 -}; - -/*###### -## boss_bjarngrim -######*/ - -struct boss_bjarngrimAI : public ScriptedAI -{ - boss_bjarngrimAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - m_uiStance = STANCE_DEFENSIVE; - memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID)); - } - - ScriptedInstance* m_pInstance; - - bool m_bIsChangingStance; - - uint8 m_uiChargingStatus; - uint8 m_uiStance; - - uint32 m_uiCharge_Timer; - uint32 m_uiChangeStance_Timer; - - uint32 m_uiReflection_Timer; - uint32 m_uiKnockAway_Timer; - uint32 m_uiPummel_Timer; - uint32 m_uiIronform_Timer; - - uint32 m_uiIntercept_Timer; - uint32 m_uiWhirlwind_Timer; - uint32 m_uiCleave_Timer; - - uint32 m_uiMortalStrike_Timer; - uint32 m_uiSlam_Timer; - - uint64 m_auiStormforgedLieutenantGUID[2]; - - void Reset() - { - m_bIsChangingStance = false; - - m_uiChargingStatus = 0; - m_uiCharge_Timer = 1000; - - m_uiChangeStance_Timer = 20000 + rand()%5000; - - m_uiReflection_Timer = 8000; - m_uiKnockAway_Timer = 20000; - m_uiPummel_Timer = 10000; - m_uiIronform_Timer = 25000; - - m_uiIntercept_Timer = 5000; - m_uiWhirlwind_Timer = 10000; - m_uiCleave_Timer = 8000; - - m_uiMortalStrike_Timer = 8000; - m_uiSlam_Timer = 10000; - - for (uint8 i = 0; i < 2; ++i) - { - if (Creature* pStormforgedLieutenant = (Unit::GetCreature((*me), m_auiStormforgedLieutenantGUID[i]))) - { - if (!pStormforgedLieutenant->isAlive()) - pStormforgedLieutenant->Respawn(); - } - } - - if (m_uiStance != STANCE_DEFENSIVE) - { - DoRemoveStanceAura(m_uiStance); - DoCast(me, SPELL_DEFENSIVE_STANCE); - m_uiStance = STANCE_DEFENSIVE; - } - - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - //must get both lieutenants here and make sure they are with him - me->CallForHelp(30.0f); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, DONE); - } - - //TODO: remove when removal is done by the core - void DoRemoveStanceAura(uint8 uiStance) - { - switch(uiStance) - { - case STANCE_DEFENSIVE: - me->RemoveAurasDueToSpell(SPELL_DEFENSIVE_STANCE); - break; - case STANCE_BERSERKER: - me->RemoveAurasDueToSpell(SPELL_BERSEKER_STANCE); - break; - case STANCE_BATTLE: - me->RemoveAurasDueToSpell(SPELL_BATTLE_STANCE); - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // Change stance - if (m_uiChangeStance_Timer <= uiDiff) - { - //wait for current spell to finish before change stance - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoRemoveStanceAura(m_uiStance); - - int uiTempStance = rand()%(3-1); - - if (uiTempStance >= m_uiStance) - ++uiTempStance; - - m_uiStance = uiTempStance; - - switch(m_uiStance) - { - case STANCE_DEFENSIVE: - DoScriptText(SAY_DEFENSIVE_STANCE, me); - DoScriptText(EMOTE_DEFENSIVE_STANCE, me); - DoCast(me, SPELL_DEFENSIVE_STANCE); - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); - break; - case STANCE_BERSERKER: - DoScriptText(SAY_BERSEKER_STANCE, me); - DoScriptText(EMOTE_BERSEKER_STANCE, me); - DoCast(me, SPELL_BERSEKER_STANCE); - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); - break; - case STANCE_BATTLE: - DoScriptText(SAY_BATTLE_STANCE, me); - DoScriptText(EMOTE_BATTLE_STANCE, me); - DoCast(me, SPELL_BATTLE_STANCE); - SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - break; - } - - m_uiChangeStance_Timer = 20000 + rand()%5000; - return; - } - else - m_uiChangeStance_Timer -= uiDiff; - - switch(m_uiStance) - { - case STANCE_DEFENSIVE: - { - if (m_uiReflection_Timer <= uiDiff) - { - DoCast(me, SPELL_SPELL_REFLECTION); - m_uiReflection_Timer = 8000 + rand()%1000; - } - else - m_uiReflection_Timer -= uiDiff; - - if (m_uiKnockAway_Timer <= uiDiff) - { - DoCast(me, SPELL_KNOCK_AWAY); - m_uiKnockAway_Timer = 20000 + rand()%1000; - } - else - m_uiKnockAway_Timer -= uiDiff; - - if (m_uiPummel_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_PUMMEL); - m_uiPummel_Timer = 10000 + rand()%1000; - } - else - m_uiPummel_Timer -= uiDiff; - - if (m_uiIronform_Timer <= uiDiff) - { - DoCast(me, SPELL_IRONFORM); - m_uiIronform_Timer = 25000 + rand()%1000; - } - else - m_uiIronform_Timer -= uiDiff; - - break; - } - case STANCE_BERSERKER: - { - if (m_uiIntercept_Timer <= uiDiff) - { - //not much point is this, better random target and more often? - DoCast(me->getVictim(), SPELL_INTERCEPT); - m_uiIntercept_Timer = 45000 + rand()%1000; - } - else - m_uiIntercept_Timer -= uiDiff; - - if (m_uiWhirlwind_Timer <= uiDiff) - { - DoCast(me, SPELL_WHIRLWIND); - m_uiWhirlwind_Timer = 10000 + rand()%1000; - } - else - m_uiWhirlwind_Timer -= uiDiff; - - if (m_uiCleave_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - m_uiCleave_Timer = 8000 + rand()%1000; - } - else - m_uiCleave_Timer -= uiDiff; - - break; - } - case STANCE_BATTLE: - { - if (m_uiMortalStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - m_uiMortalStrike_Timer = 20000 + rand()%1000; - } - else - m_uiMortalStrike_Timer -= uiDiff; - - if (m_uiSlam_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SLAM); - m_uiSlam_Timer = 15000 + rand()%1000; - } - else - m_uiSlam_Timer -= uiDiff; - - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -/*###### -## mob_stormforged_lieutenant -######*/ - -struct mob_stormforged_lieutenantAI : public ScriptedAI -{ - mob_stormforged_lieutenantAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiArcWeld_Timer; - uint32 m_uiRenewSteel_Timer; - - void Reset() - { - m_uiArcWeld_Timer = 20000 + rand()%1000; - m_uiRenewSteel_Timer = 10000 + rand()%1000; - } - - void EnterCombat(Unit* pWho) - { - if (m_pInstance) - { - if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) - { - if (pBjarngrim->isAlive() && !pBjarngrim->getVictim()) - pBjarngrim->AI()->AttackStart(pWho); - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_uiArcWeld_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_ARC_WELD); - m_uiArcWeld_Timer = 20000 + rand()%1000; - } - else - m_uiArcWeld_Timer -= uiDiff; - - if (m_uiRenewSteel_Timer <= uiDiff) - { - if (m_pInstance) - { - if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) - { - if (pBjarngrim->isAlive()) - DoCast(pBjarngrim, SPELL_RENEW_STEEL_N); - } - } - m_uiRenewSteel_Timer = 10000 + rand()%4000; - } - else - m_uiRenewSteel_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_bjarngrim(Creature* pCreature) -{ - return new boss_bjarngrimAI(pCreature); -} - -CreatureAI* GetAI_mob_stormforged_lieutenant(Creature* pCreature) -{ - return new mob_stormforged_lieutenantAI(pCreature); -} - -void AddSC_boss_bjarngrim() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_bjarngrim"; - newscript->GetAI = &GetAI_boss_bjarngrim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stormforged_lieutenant"; - newscript->GetAI = &GetAI_mob_stormforged_lieutenant; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp b/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp deleted file mode 100644 index ecf61188b3e..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: Timer check pending - */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum Spells -{ - SPELL_BALL_LIGHTNING = 52780, - H_SPELL_BALL_LIGHTNING = 59800, - SPELL_STATIC_OVERLOAD = 52658, - H_SPELL_STATIC_OVERLOAD = 59795, - - SPELL_DISPERSE = 52770, - SPELL_SUMMON_SPARK = 52746, - SPELL_SPARK_DESPAWN = 52776, - - //Spark of Ionar - SPELL_SPARK_VISUAL_TRIGGER = 52667, - H_SPELL_SPARK_VISUAL_TRIGGER = 59833 -}; - -enum Yells -{ - SAY_AGGRO = -1602011, - SAY_SLAY_1 = -1602012, - SAY_SLAY_2 = -1602013, - SAY_SLAY_3 = -1602014, - SAY_DEATH = -1602015, - SAY_SPLIT_1 = -1602016, - SAY_SPLIT_2 = -1602017 -}; - -enum Creatures -{ - NPC_SPARK_OF_IONAR = 28926 -}; - -enum Misc -{ - DATA_MAX_SPARKS = 5, - DATA_MAX_SPARK_DISTANCE = 90, // Distance to boss - prevent runs through the whole instance - DATA_POINT_CALLBACK = 0 -}; - -/*###### -## Boss Ionar -######*/ - -struct boss_ionarAI : public ScriptedAI -{ - boss_ionarAI(Creature *pCreature) : ScriptedAI(pCreature), lSparkList(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - SummonList lSparkList; - - bool bIsSplitPhase; - bool bHasDispersed; - - uint32 uiSplitTimer; - - uint32 uiStaticOverloadTimer; - uint32 uiBallLightningTimer; - - uint32 uiDisperseHealth; - - void Reset() - { - lSparkList.DespawnAll(); - - bIsSplitPhase = true; - bHasDispersed = false; - - uiSplitTimer = 25*IN_MILISECONDS; - - uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); - uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); - - uiDisperseHealth = 45 + urand(0,10); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - if (me->GetVisibility() == VISIBILITY_OFF) - me->SetVisibility(VISIBILITY_ON); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - lSparkList.DespawnAll(); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - //make sparks come back - void CallBackSparks() - { - //should never be empty here, but check - if (lSparkList.empty()) - return; - - Position pos; - me->GetPosition(&pos); - - for (std::list::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) - { - if (Creature* pSpark = Unit::GetCreature(*me, *itr)) - { - if (pSpark->isAlive()) - { - pSpark->SetSpeed(MOVE_RUN, 2.0f); - pSpark->GetMotionMaster()->Clear(); - pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); - } - else - pSpark->ForcedDespawn(); - } - } - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - if (me->GetVisibility() == VISIBILITY_OFF) - uiDamage = 0; - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) - { - lSparkList.Summon(pSummoned); - - pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER,H_SPELL_SPARK_VISUAL_TRIGGER), true); - - Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - pSummoned->SetInCombatWith(pTarget); - pSummoned->GetMotionMaster()->Clear(); - pSummoned->GetMotionMaster()->MoveFollow(pTarget, 0.0f, 0.0f); - } - } - } - - void SummonedCreatureDespawn(Creature *pSummoned) - { - if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) - lSparkList.Despawn(pSummoned); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // Splitted - if (me->GetVisibility() == VISIBILITY_OFF) - { - if (uiSplitTimer <= uiDiff) - { - uiSplitTimer = 2.5*IN_MILISECONDS; - - // Return sparks to where Ionar splitted - if (bIsSplitPhase) - { - CallBackSparks(); - bIsSplitPhase = false; - } - // Lightning effect and restore Ionar - else if (lSparkList.empty()) - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - DoCast(me, SPELL_SPARK_DESPAWN, false); - - uiSplitTimer = 25*IN_MILISECONDS; - bIsSplitPhase = true; - - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - } - else - uiSplitTimer -= uiDiff; - - return; - } - - if (uiStaticOverloadTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_STATIC_OVERLOAD); - - uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); - } - else - uiStaticOverloadTimer -= uiDiff; - - if (uiBallLightningTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); - uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); - } - else - uiBallLightningTimer -= uiDiff; - - // Health check - if (!bHasDispersed && HealthBelowPct(uiDisperseHealth)) - { - bHasDispersed = true; - - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me, SPELL_DISPERSE, true); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ionar(Creature* pCreature) -{ - return new boss_ionarAI(pCreature); -} - -bool EffectDummyCreature_boss_ionar(Unit* /*pCaster*/, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_DISPERSE && uiEffIndex == 0) - { - if (pCreatureTarget->GetEntry() != NPC_IONAR) - return true; - - for (uint8 i = 0; i < DATA_MAX_SPARKS; ++i) - pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true); - - pCreatureTarget->AttackStop(); - pCreatureTarget->SetVisibility(VISIBILITY_OFF); - pCreatureTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - pCreatureTarget->GetMotionMaster()->Clear(); - pCreatureTarget->GetMotionMaster()->MoveIdle(); - - //always return true when we are handling this spell and effect - return true; - } - return false; -} - -/*###### -## mob_spark_of_ionar -######*/ - -struct mob_spark_of_ionarAI : public ScriptedAI -{ - mob_spark_of_ionarAI(Creature *pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCheckTimer; - - void Reset() - { - uiCheckTimer = 2*IN_MILISECONDS; - me->SetReactState(REACT_PASSIVE); - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE || !pInstance) - return; - - if (uiPointId == DATA_POINT_CALLBACK) - me->ForcedDespawn(); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - uiDamage = 0; - } - - void UpdateAI(const uint32 uiDiff) - { - // Despawn if the encounter is not running - if (pInstance && pInstance->GetData(TYPE_IONAR) != IN_PROGRESS) - { - me->ForcedDespawn(); - return; - } - - // Prevent them to follow players through the whole instance - if (uiCheckTimer <= uiDiff) - { - if (pInstance) - { - Creature* pIonar = pInstance->instance->GetCreature(pInstance->GetData64(DATA_IONAR)); - if (pIonar && pIonar->isAlive()) - { - if (me->GetDistance(pIonar) > DATA_MAX_SPARK_DISTANCE) - { - Position pos; - pIonar->GetPosition(&pos); - - me->SetSpeed(MOVE_RUN, 2.0f); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); - } - } - else - me->ForcedDespawn(); - } - uiCheckTimer = 2*IN_MILISECONDS; - } - else - uiCheckTimer -= uiDiff; - - // No melee attack at all! - } -}; - -CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature) -{ - return new mob_spark_of_ionarAI(pCreature); -} - -void AddSC_boss_ionar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ionar"; - newscript->GetAI = &GetAI_boss_ionar; - newscript->pEffectDummyCreature = &EffectDummyCreature_boss_ionar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_spark_of_ionar"; - newscript->GetAI = &GetAI_mob_spark_of_ionar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp b/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp deleted file mode 100644 index f08c19efca2..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Loken -SD%Complete: 60% -SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414) -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - ACHIEV_TIMELY_DEATH_START_EVENT = 20384, - - SAY_AGGRO = -1602018, - SAY_INTRO_1 = -1602019, - SAY_INTRO_2 = -1602020, - SAY_SLAY_1 = -1602021, - SAY_SLAY_2 = -1602022, - SAY_SLAY_3 = -1602023, - SAY_DEATH = -1602024, - SAY_NOVA_1 = -1602025, - SAY_NOVA_2 = -1602026, - SAY_NOVA_3 = -1602027, - SAY_75HEALTH = -1602028, - SAY_50HEALTH = -1602029, - SAY_25HEALTH = -1602030, - EMOTE_NOVA = -1602031, - - SPELL_ARC_LIGHTNING = 52921, - SPELL_LIGHTNING_NOVA_N = 52960, - SPELL_LIGHTNING_NOVA_H = 59835, - - SPELL_PULSING_SHOCKWAVE_N = 52961, - SPELL_PULSING_SHOCKWAVE_H = 59836, - SPELL_PULSING_SHOCKWAVE_AURA = 59414 -}; - -/*###### -## Boss Loken -######*/ - -struct boss_lokenAI : public ScriptedAI -{ - boss_lokenAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - bool m_bIsAura; - - uint32 m_uiArcLightning_Timer; - uint32 m_uiLightningNova_Timer; - uint32 m_uiPulsingShockwave_Timer; - uint32 m_uiResumePulsingShockwave_Timer; - - uint32 m_uiHealthAmountModifier; - - void Reset() - { - m_bIsAura = false; - - m_uiArcLightning_Timer = 15000; - m_uiLightningNova_Timer = 20000; - m_uiPulsingShockwave_Timer = 2000; - m_uiResumePulsingShockwave_Timer = 15000; - - m_uiHealthAmountModifier = 1; - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED); - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS); - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); - } - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_LOKEN, DONE); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_bIsAura) - { - // workaround for PULSING_SHOCKWAVE - if (m_uiPulsingShockwave_Timer <= uiDiff) - { - Map* pMap = me->GetMap(); - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack()) - { - int32 dmg; - float m_fDist = me->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()); - - dmg = DUNGEON_MODE(100, 150); // need to correct damage - if (m_fDist > 1.0f) // Further from 1 yard - dmg *= m_fDist; - - me->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false); - } - } - m_uiPulsingShockwave_Timer = 2000; - } else m_uiPulsingShockwave_Timer -= uiDiff; - } - else - { - if (m_uiResumePulsingShockwave_Timer <= uiDiff) - { - //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement? - DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); - - DoCast(me, SPELL_PULSING_SHOCKWAVE_N); // need core support - m_bIsAura = true; - m_uiResumePulsingShockwave_Timer = 0; - } - else - m_uiResumePulsingShockwave_Timer -= uiDiff; - } - - if (m_uiArcLightning_Timer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ARC_LIGHTNING); - - m_uiArcLightning_Timer = 15000 + rand()%1000; - } - else - m_uiArcLightning_Timer -= uiDiff; - - if (m_uiLightningNova_Timer <= uiDiff) - { - DoScriptText(RAND(SAY_NOVA_1,SAY_NOVA_2,SAY_NOVA_3), me); - DoScriptText(EMOTE_NOVA, me); - DoCast(me, SPELL_LIGHTNING_NOVA_N); - - m_bIsAura = false; - m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura - m_uiLightningNova_Timer = 20000 + rand()%1000; - } - else - m_uiLightningNova_Timer -= uiDiff; - - // Health check - if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(25*m_uiHealthAmountModifier))) - { - switch(m_uiHealthAmountModifier) - { - case 1: DoScriptText(SAY_75HEALTH, me); break; - case 2: DoScriptText(SAY_50HEALTH, me); break; - case 3: DoScriptText(SAY_25HEALTH, me); break; - } - - ++m_uiHealthAmountModifier; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_loken(Creature* pCreature) -{ - return new boss_lokenAI(pCreature); -} - -void AddSC_boss_loken() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_loken"; - newscript->GetAI = &GetAI_boss_loken; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp b/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp deleted file mode 100644 index 184050e3103..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Volkhan -SD%Complete: 60% -SDComment: Not considered complete. Some events may fail and need further development -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - SAY_AGGRO = -1602032, - SAY_SLAY_1 = -1602033, - SAY_SLAY_2 = -1602034, - SAY_SLAY_3 = -1602035, - SAY_DEATH = -1602036, - SAY_STOMP_1 = -1602037, - SAY_STOMP_2 = -1602038, - SAY_FORGE_1 = -1602039, - SAY_FORGE_2 = -1602040, - EMOTE_TO_ANVIL = -1602041, - EMOTE_SHATTER = -1602042, - - SPELL_HEAT_N = 52387, - SPELL_HEAT_H = 59528, - SPELL_SHATTERING_STOMP_N = 52237, - SPELL_SHATTERING_STOMP_H = 59529, - - //unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on: - SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil - SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss - - //SPELL_TEMPER_VISUAL = 52661, //summons GO - - SPELL_SUMMON_MOLTEN_GOLEM = 52405, - - //Molten Golem - SPELL_BLAST_WAVE = 23113, - SPELL_IMMOLATION_STRIKE_N = 52433, - SPELL_IMMOLATION_STRIKE_H = 59530, - SPELL_SHATTER_N = 52429, - SPELL_SHATTER_H = 59527, - - NPC_VOLKHAN_ANVIL = 28823, - NPC_MOLTEN_GOLEM = 28695, - NPC_BRITTLE_GOLEM = 28681, - - POINT_ID_ANVIL = 0, - MAX_GOLEM = 2, - - ACHIEVEMENT_SHATTER_RESISTANT = 2042 -}; - -/*###### -## Boss Volkhan -######*/ - -struct boss_volkhanAI : public ScriptedAI -{ - boss_volkhanAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - std::list m_lGolemGUIDList; - - bool m_bHasTemper; - bool m_bIsStriking; - bool m_bCanShatterGolem; - - uint8 GolemsShattered; - uint32 m_uiPause_Timer; - uint32 m_uiShatteringStomp_Timer; - uint32 m_uiShatter_Timer; - - uint32 m_uiHealthAmountModifier; - - void Reset() - { - m_bIsStriking = false; - m_bHasTemper = false; - m_bCanShatterGolem = false; - - m_uiPause_Timer = 3500; - m_uiShatteringStomp_Timer = 0; - m_uiShatter_Timer = 5000; - GolemsShattered = 0; - - m_uiHealthAmountModifier = 1; - - DespawnGolem(); - m_lGolemGUIDList.clear(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); - } - - void AttackStart(Unit* pWho) - { - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - if (!m_bHasTemper) - me->GetMotionMaster()->MoveChase(pWho); - } - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - DespawnGolem(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, DONE); - - if (IsHeroic() && GolemsShattered < 5) - { - AchievementEntry const *AchievShatterResistant = GetAchievementStore()->LookupEntry(ACHIEVEMENT_SHATTER_RESISTANT); - if (AchievShatterResistant) - { - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievShatterResistant); - } - } - } - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void DespawnGolem() - { - if (m_lGolemGUIDList.empty()) - return; - - for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - if (pTemp->isAlive()) - pTemp->ForcedDespawn(); - } - } - - m_lGolemGUIDList.clear(); - } - - void ShatterGolem() - { - if (m_lGolemGUIDList.empty()) - return; - - for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - // only shatter brittle golems - if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM) - { - pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false); - GolemsShattered += 1; - } - } - } - } - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_TEMPER_DUMMY) - m_bIsStriking = true; - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_MOLTEN_GOLEM) - { - m_lGolemGUIDList.push_back(pSummoned->GetGUID()); - - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - - //why healing when just summoned? - pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, me->GetGUID()); - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_bIsStriking) - { - if (m_uiPause_Timer <= uiDiff) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) - { - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - - m_bHasTemper = false; - m_bIsStriking = false; - m_uiPause_Timer = 3500; - } - else - m_uiPause_Timer -= uiDiff; - - return; - } - - // When to start shatter? After 60, 40 or 20% hp? - if (!m_bHasTemper && m_uiHealthAmountModifier >= 3) - { - if (m_uiShatteringStomp_Timer <= uiDiff) - { - //should he stomp even if he has no brittle golem to shatter? - - DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2), me); - - DoCast(me, SPELL_SHATTERING_STOMP_N); - - DoScriptText(EMOTE_SHATTER, me); - - m_uiShatteringStomp_Timer = 30000; - m_bCanShatterGolem = true; - } - else - m_uiShatteringStomp_Timer -= uiDiff; - } - - // Shatter Golems 3 seconds after Shattering Stomp - if (m_bCanShatterGolem) - { - if (m_uiShatter_Timer <= uiDiff) - { - ShatterGolem(); - m_uiShatter_Timer = 3000; - m_bCanShatterGolem = false; - } - else - m_uiShatter_Timer -= uiDiff; - } - - // Health check - if (!m_bCanShatterGolem && (me->GetHealth()*100 / me->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier))) - { - ++m_uiHealthAmountModifier; - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoScriptText(RAND(SAY_FORGE_1,SAY_FORGE_2), me); - - m_bHasTemper = true; - - DoCast(me, SPELL_TEMPER, false); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_volkhan(Creature* pCreature) -{ - return new boss_volkhanAI(pCreature); -} - -bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_TEMPER_DUMMY && uiEffIndex == 0) - { - if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN) - return true; - - for (uint8 i = 0; i < MAX_GOLEM; ++i) - { - pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true); - } - - //always return true when we are handling this spell and effect - return true; - } - - return false; -} - -/*###### -## npc_volkhan_anvil -######*/ - -bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_TEMPER && uiEffIndex == 0) - { - if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL) - return true; - - Creature *cre = CAST_CRE(pCaster); - - DoScriptText(EMOTE_TO_ANVIL, pCaster); - - float fX, fY, fZ; - pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE); - - pCaster->AttackStop(); - - if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - pCaster->GetMotionMaster()->MovementExpired(); - - cre->GetMap()->CreatureRelocation(cre, fX, fY, fZ, pCreatureTarget->GetOrientation()); - cre->SendMonsterMove(fX, fY, fZ, 0, cre->GetUnitMovementFlags(), 1); - - pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); - - //always return true when we are handling this spell and effect - return true; - } - - return false; -} - -/*###### -## mob_molten_golem -######*/ - -struct mob_molten_golemAI : public ScriptedAI -{ - mob_molten_golemAI(Creature *pCreature) : ScriptedAI(pCreature) - { - } - - bool m_bIsFrozen; - - uint32 m_uiBlast_Timer; - uint32 m_uiDeathDelay_Timer; - uint32 m_uiImmolation_Timer; - - void Reset() - { - m_bIsFrozen = false; - - m_uiBlast_Timer = 20000; - m_uiDeathDelay_Timer = 0; - m_uiImmolation_Timer = 5000; - } - - void AttackStart(Unit* pWho) - { - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - if (!m_bIsFrozen) - me->GetMotionMaster()->MoveChase(pWho); - } - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) - { - if (uiDamage > me->GetHealth()) - { - me->UpdateEntry(NPC_BRITTLE_GOLEM); - me->SetHealth(1); - uiDamage = 0; - me->RemoveAllAuras(); - me->AttackStop(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - m_bIsFrozen = true; - } - } - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - //this is the dummy effect of the spells - if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H) - { - if (me->GetEntry() == NPC_BRITTLE_GOLEM) - me->ForcedDespawn(); - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target or if we are frozen - if (!UpdateVictim() || m_bIsFrozen) - return; - - if (m_uiBlast_Timer <= uiDiff) - { - DoCast(me, SPELL_BLAST_WAVE); - m_uiBlast_Timer = 20000; - } - else - m_uiBlast_Timer -= uiDiff; - - if (m_uiImmolation_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_IMMOLATION_STRIKE_N); - m_uiImmolation_Timer = 5000; - } - else - m_uiImmolation_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_molten_golem(Creature* pCreature) -{ - return new mob_molten_golemAI(pCreature); -} - -void AddSC_boss_volkhan() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_volkhan"; - newscript->GetAI = &GetAI_boss_volkhan; - newscript->pEffectDummyCreature = &EffectDummyCreature_boss_volkhan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_volkhan_anvil"; - newscript->pEffectDummyCreature = &EffectDummyCreature_npc_volkhan_anvil; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_molten_golem"; - newscript->GetAI = &GetAI_mob_molten_golem; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h b/src/server/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h deleted file mode 100644 index d9739fdf888..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_HALLS_OF_LIGHTNING_H -#define DEF_HALLS_OF_LIGHTNING_H - -enum eTypes -{ - MAX_ENCOUNTER = 4, - - DATA_BJARNGRIM = 1, - DATA_IONAR = 2, - DATA_LOKEN = 3, - DATA_VOLKHAN = 4, - - TYPE_BJARNGRIM = 10, - TYPE_IONAR = 11, - TYPE_LOKEN = 12, - TYPE_VOLKHAN = 13, - - NPC_BJARNGRIM = 28586, - NPC_VOLKHAN = 28587, - NPC_IONAR = 28546, - NPC_LOKEN = 28923, - - GO_BJARNGRIM_DOOR = 191416, //_doors10 - GO_VOLKHAN_DOOR = 191325, //_doors07 - GO_IONAR_DOOR = 191326, //_doors05 - GO_LOKEN_DOOR = 191324, //_doors02 - GO_LOKEN_THRONE = 192654 -}; - -#endif diff --git a/src/server/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp b/src/server/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp deleted file mode 100644 index 46cd5c9cccc..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Halls_of_Lightning -SD%Complete: 90% -SDComment: All ready. -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -/* Halls of Lightning encounters: -0 - General Bjarngrim -1 - Volkhan -2 - Ionar -3 - Loken -*/ - -struct instance_halls_of_lightning : public ScriptedInstance -{ - instance_halls_of_lightning(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 m_uiGeneralBjarngrimGUID; - uint64 m_uiIonarGUID; - uint64 m_uiLokenGUID; - uint64 m_uiVolkhanGUID; - - uint64 m_uiBjarngrimDoorGUID; - uint64 m_uiVolkhanDoorGUID; - uint64 m_uiIonarDoorGUID; - uint64 m_uiLokenDoorGUID; - uint64 m_uiLokenGlobeGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiGeneralBjarngrimGUID = 0; - m_uiVolkhanGUID = 0; - m_uiIonarGUID = 0; - m_uiLokenGUID = 0; - - m_uiBjarngrimDoorGUID = 0; - m_uiVolkhanDoorGUID = 0; - m_uiIonarDoorGUID = 0; - m_uiLokenDoorGUID = 0; - m_uiLokenGlobeGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_BJARNGRIM: - m_uiGeneralBjarngrimGUID = pCreature->GetGUID(); - break; - case NPC_VOLKHAN: - m_uiVolkhanGUID = pCreature->GetGUID(); - break; - case NPC_IONAR: - m_uiIonarGUID = pCreature->GetGUID(); - break; - case NPC_LOKEN: - m_uiLokenGUID = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_BJARNGRIM_DOOR: - m_uiBjarngrimDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_VOLKHAN_DOOR: - m_uiVolkhanDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_IONAR_DOOR: - m_uiIonarDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_LOKEN_DOOR: - m_uiLokenDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_LOKEN_THRONE: - m_uiLokenGlobeGUID = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_BJARNGRIM: - if (uiData == DONE) - DoUseDoorOrButton(m_uiBjarngrimDoorGUID); - m_auiEncounter[0] = uiData; - break; - case TYPE_VOLKHAN: - if (uiData == DONE) - DoUseDoorOrButton(m_uiVolkhanDoorGUID); - m_auiEncounter[1] = uiData; - break; - case TYPE_IONAR: - if (uiData == DONE) - DoUseDoorOrButton(m_uiIonarDoorGUID); - m_auiEncounter[2] = uiData; - break; - case TYPE_LOKEN: - if (uiData == DONE) - { - DoUseDoorOrButton(m_uiLokenDoorGUID); - - //Appears to be type 5 GO with animation. Need to figure out how this work, code below only placeholder - if (GameObject* pGlobe = instance->GetGameObject(m_uiLokenGlobeGUID)) - pGlobe->SetGoState(GO_STATE_ACTIVE); - } - m_auiEncounter[3] = uiData; - break; - } - - if (uiData == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case TYPE_BJARNGRIM: - return m_auiEncounter[0]; - case TYPE_VOLKHAN: - return m_auiEncounter[1]; - case TYPE_IONAR: - return m_auiEncounter[2]; - case TYPE_LOKEN: - return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_BJARNGRIM: - return m_uiGeneralBjarngrimGUID; - case DATA_VOLKHAN: - return m_uiVolkhanGUID; - case DATA_IONAR: - return m_uiIonarGUID; - case DATA_LOKEN: - return m_uiLokenGUID; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H L " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'H' && dataHead2 == 'L') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_halls_of_lightning(Map* pMap) -{ - return new instance_halls_of_lightning(pMap); -} - -void AddSC_instance_halls_of_lightning() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_lightning"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_lightning; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp b/src/server/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp deleted file mode 100644 index 0674b7c79eb..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* Script Data Start -SDName: Boss krystallus -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_krystallus' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_BOULDER_TOSS = 50843, - H_SPELL_BOULDER_TOSS = 59742, - SPELL_GROUND_SPIKE = 59750, - SPELL_GROUND_SLAM = 50827, - SPELL_SHATTER = 50810, - H_SPELL_SHATTER = 61546, - SPELL_STOMP = 48131, - H_SPELL_STOMP = 59744 -}; - -enum Yells -{ - SAY_AGGRO = -1599007, - SAY_KILL = -1599008, - SAY_DEATH = -1599009, - SAY_SHATTER = -1599010 -}; - -struct boss_krystallusAI : public ScriptedAI -{ - boss_krystallusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBoulderTossTimer; - uint32 uiGroundSpikeTimer; - uint32 uiGroundSlamTimer; - uint32 uiShatterTimer; - uint32 uiStompTimer; - - bool bIsSlam; - - ScriptedInstance* pInstance; - - void Reset() - { - bIsSlam = false; - - uiBoulderTossTimer = 3000 + rand()%6000; - uiGroundSpikeTimer = 9000 + rand()%5000; - uiGroundSlamTimer = 15000 + rand()%3000; - uiStompTimer = 20000 + rand()%9000; - uiShatterTimer = 0; - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, NOT_STARTED); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBoulderTossTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BOULDER_TOSS); - uiBoulderTossTimer = 9000 + rand()%6000; - } else uiBoulderTossTimer -= diff; - - if (uiGroundSpikeTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_GROUND_SPIKE); - uiGroundSpikeTimer = 12000 + rand()%5000; - } else uiGroundSpikeTimer -= diff; - - if (uiStompTimer <= diff) - { - DoCast(me, SPELL_STOMP); - uiStompTimer = 20000 + rand()%9000; - } else uiStompTimer -= diff; - - if (uiGroundSlamTimer <= diff) - { - DoCast(me, SPELL_GROUND_SLAM); - bIsSlam = true; - uiShatterTimer = 10000; - uiGroundSlamTimer = 15000 + rand()%3000; - } else uiGroundSlamTimer -= diff; - - if (bIsSlam) - { - if (uiShatterTimer <= diff) - { - DoCast(me, SPELL_SHATTER); - bIsSlam = false; - } else uiShatterTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(SAY_KILL, me); - } -}; - -CreatureAI* GetAI_boss_krystallus(Creature* pCreature) -{ - return new boss_krystallusAI (pCreature); -} - -void AddSC_boss_krystallus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_krystallus"; - newscript->GetAI = &GetAI_boss_krystallus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp b/src/server/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp deleted file mode 100644 index b3c3c675347..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* Script Data Start -SDName: Boss maiden_of_grief -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_maiden_of_grief' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_PARTING_SORROW = 59723, - SPELL_STORM_OF_GRIEF_N = 50752, - SPELL_STORM_OF_GRIEF_H = 59772, - SPELL_SHOCK_OF_SORROW_N = 50760, - SPELL_SHOCK_OF_SORROW_H = 59726, - SPELL_PILLAR_OF_WOE_N = 50761, - SPELL_PILLAR_OF_WOE_H = 59727 -}; - -enum Yells -{ - SAY_AGGRO = -1599000, - SAY_SLAY_1 = -1599001, - SAY_SLAY_2 = -1599002, - SAY_SLAY_3 = -1599003, - SAY_SLAY_4 = -1599004, - SAY_DEATH = -1599005, - SAY_STUN = -1599006 -}; - -enum Achievements -{ - ACHIEV_GOOD_GRIEF_START_EVENT = 20383, -}; - -struct boss_maiden_of_griefAI : public ScriptedAI -{ - boss_maiden_of_griefAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 PartingSorrowTimer; - uint32 StormOfGriefTimer; - uint32 ShockOfSorrowTimer; - uint32 PillarOfWoeTimer; - - void Reset() - { - PartingSorrowTimer = 25000 + rand()%5000; - StormOfGriefTimer = 10000; - ShockOfSorrowTimer = 20000+rand()%5000; - PillarOfWoeTimer = 5000 + rand()%10000; - - if (pInstance) - { - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAIDEN_DOOR))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, IN_PROGRESS); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (IsHeroic()) - { - if (PartingSorrowTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget) - DoCast(pTarget, SPELL_PARTING_SORROW); - - PartingSorrowTimer = 30000 + rand()%10000; - } else PartingSorrowTimer -= diff; - } - - if (StormOfGriefTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STORM_OF_GRIEF_N, true); - StormOfGriefTimer = 15000 + rand()%5000; - } else StormOfGriefTimer -= diff; - - if (ShockOfSorrowTimer <= diff) - { - DoResetThreat(); - DoScriptText(SAY_STUN, me); - DoCast(me, SPELL_SHOCK_OF_SORROW_N); - ShockOfSorrowTimer = 20000 + rand()%10000; - } else ShockOfSorrowTimer -= diff; - - if (PillarOfWoeTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - - if (pTarget) - DoCast(pTarget, SPELL_PILLAR_OF_WOE_N); - else - DoCast(me->getVictim(), SPELL_PILLAR_OF_WOE_N); - - PillarOfWoeTimer = 5000 + rand()%20000; - } else PillarOfWoeTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } -}; - -CreatureAI* GetAI_boss_maiden_of_grief(Creature* pCreature) -{ - return new boss_maiden_of_griefAI (pCreature); -} - -void AddSC_boss_maiden_of_grief() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_maiden_of_grief"; - newscript->GetAI = &GetAI_boss_maiden_of_grief; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp b/src/server/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp deleted file mode 100644 index 68c3e34e6bf..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* Script Data Start -SDName: Boss sjonnir -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_sjonnir' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_LIGHTING_RING = 51849, //Periodic Trigger (interval 2s) spell = 50841 - H_SPELL_LIGHTING_RING = 59861, //Periodic Trigger (interval 2s) spell = 59849 - SPELL_LIGHTING_RING_1 = 50840, //Periodic Trigger (interval 2s) spell = 50841 - H_SPELL_LIGHTING_RING_1 = 59848, //Periodic Trigger (interval 2s) spell = 59849 - SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835 - H_SPELL_STATIC_CHARGE = 59846, //Periodic Trigger 2s interval, spell =50847 - SPELL_CHAIN_LIGHTING = 50830, - H_SPELL_CHAIN_LIGHTING = 59844, - SPELL_LIGHTING_SHIELD = 50831, - H_SPELL_LIGHTING_SHIELD = 59845, - SPELL_FRENZY = 28747 -}; - -enum Yells -{ - SAY_AGGRO = -1599011, - SAY_SLAY_1 = -1599012, - SAY_SLAY_2 = -1599013, - SAY_SLAY_3 = -1599014, - SAY_DEATH = -1599015 -}; - -#define EMOTE_GENERIC_FRENZY -1000002 - -enum SjonnirCreatures -{ - CREATURE_FORGED_IRON_TROGG = 27979, - CREATURE_MALFORMED_OOZE = 27981, - CREATURE_FORGED_IRON_DWARF = 27982, - CREATURE_IRON_SLUDGE = 28165 -}; - -enum Misc -{ - DATA_TIME_BEFORE_OOZE = 150000, //2min 30 secs - ACHIEV_ABUSE_THE_OOZE = 2155 -}; - -struct Locations -{ - float x, y, z; -}; - -static Locations PipeLocations[] = -{ - {1295.44, 734.07, 200.3}, //left - {1297.7, 595.6, 199.9} //right -}; - -static Locations CenterPoint = {1295.21, 667.157, 189.691}; - -struct boss_sjonnirAI : public ScriptedAI -{ - boss_sjonnirAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - bool bIsFrenzy; - - uint32 uiChainLightningTimer; - uint32 uiLightningShieldTimer; - uint32 uiStaticChargeTimer; - uint32 uiLightningRingTimer; - uint32 uiSummonTimer; - uint32 uiFrenzyTimer; - uint32 uiEncounterTimer; - uint32 uiKilledIronSludges; - - SummonList lSummons; - - ScriptedInstance* pInstance; - - void Reset() - { - bIsFrenzy = false; - - uiEncounterTimer = 0; - uiChainLightningTimer = 3000 + rand()%5000; - uiLightningShieldTimer = 20000 + rand()%5000; - uiStaticChargeTimer = 20000 + rand()%5000; - uiLightningRingTimer = 30000 + rand()%5000; - uiSummonTimer = 5000; - uiFrenzyTimer = 300000; //5 minutes - uiKilledIronSludges = 0; - - lSummons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_SJONNIR_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - uiEncounterTimer = 0; - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SJONNIR_DOOR))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - pInstance->SetData(DATA_SJONNIR_EVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiChainLightningTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CHAIN_LIGHTING); - uiChainLightningTimer = 10000 + rand()%5000; - } else uiChainLightningTimer -= diff; - - if (uiLightningShieldTimer <= diff) - { - DoCast(me, SPELL_LIGHTING_SHIELD); - uiLightningShieldTimer -= diff; - } - - if (uiStaticChargeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STATIC_CHARGE); - uiStaticChargeTimer = 20000 + rand()%5000; - } uiStaticChargeTimer -= diff; - - if (uiLightningRingTimer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_LIGHTING_RING); - uiLightningRingTimer = 30000 + rand()%5000; - } else uiLightningRingTimer -= diff; - - if (uiSummonTimer <= diff) - { - uint32 uiSummonPipe = rand()%2; - me->SummonCreature(uiEncounterTimer > DATA_TIME_BEFORE_OOZE ? CREATURE_MALFORMED_OOZE : - RAND(CREATURE_FORGED_IRON_DWARF,CREATURE_FORGED_IRON_TROGG), - PipeLocations[uiSummonPipe].x, PipeLocations[uiSummonPipe].y, PipeLocations[uiSummonPipe].z, 0.0f, - TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - uiSummonTimer = 20000; - } else uiSummonTimer -= diff; - - if (!bIsFrenzy) - { - if (uiFrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - bIsFrenzy = true; - } - else uiFrenzyTimer -= diff; - } - - uiEncounterTimer +=diff; - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* summon) - { - summon->GetMotionMaster()->MovePoint(0, CenterPoint.x, CenterPoint.y, CenterPoint.z); - /*if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - summon->AI()->AttackStart(pTarget);*/ - lSummons.Summon(summon); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - lSummons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_SJONNIR_EVENT, DONE); - if (IsHeroic() && uiKilledIronSludges > 4) - pInstance->DoCompleteAchievement(ACHIEV_ABUSE_THE_OOZE); - } - } - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void KilledIronSludge() - { - ++uiKilledIronSludges; - } -}; - -CreatureAI* GetAI_boss_sjonnir(Creature* pCreature) -{ - return new boss_sjonnirAI (pCreature); -} - -struct mob_malformed_oozeAI : public ScriptedAI -{ - mob_malformed_oozeAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiMergeTimer; - - void Reset() - { - uiMergeTimer = 10000; - } - - void UpdateAI(const uint32 diff) - { - if (uiMergeTimer <= diff) - { - if (Creature* pTemp = me->FindNearestCreature(CREATURE_MALFORMED_OOZE, 3.0f, true)) - { - DoSpawnCreature(CREATURE_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); - pTemp->DisappearAndDie(); - me->DisappearAndDie(); - } - uiMergeTimer = 3000; - } else uiMergeTimer -= diff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_malformed_ooze(Creature* pCreature) -{ - return new mob_malformed_oozeAI(pCreature); -} - -struct mob_iron_sludgeAI : public ScriptedAI -{ - mob_iron_sludgeAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - if (Creature* pSjonnir = Unit::GetCreature(*me, pInstance->GetData64(DATA_SJONNIR))) - CAST_AI(boss_sjonnirAI, pSjonnir->AI())->KilledIronSludge(); - } -}; - -CreatureAI* GetAI_mob_iron_sludge(Creature* pCreature) -{ - return new mob_iron_sludgeAI(pCreature); -} - -void AddSC_boss_sjonnir() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sjonnir"; - newscript->GetAI = &GetAI_boss_sjonnir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_malformed_ooze"; - newscript->GetAI = &GetAI_mob_malformed_ooze; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_iron_sludge"; - newscript->GetAI = &GetAI_mob_iron_sludge; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp b/src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp deleted file mode 100644 index 8febdaab879..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp +++ /dev/null @@ -1,724 +0,0 @@ -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "halls_of_stone.h" - -enum Texts -{ - SAY_KILL_1 = -1599016, - SAY_KILL_2 = -1599017, - SAY_KILL_3 = -1599018, - SAY_LOW_HEALTH = -1599019, - SAY_DEATH = -1599020, - SAY_PLAYER_DEATH_1 = -1599021, - SAY_PLAYER_DEATH_2 = -1599022, - SAY_PLAYER_DEATH_3 = -1599023, - SAY_ESCORT_START = -1599024, - - SAY_SPAWN_DWARF = -1599025, - SAY_SPAWN_TROGG = -1599026, - SAY_SPAWN_OOZE = -1599027, - SAY_SPAWN_EARTHEN = -1599028, - - SAY_EVENT_INTRO_1 = -1599029, - SAY_EVENT_INTRO_2 = -1599030, - SAY_EVENT_INTRO_3_ABED = -1599031, - - SAY_EVENT_A_1 = -1599032, - SAY_EVENT_A_2_KADD = -1599033, - SAY_EVENT_A_3 = -1599034, - - SAY_EVENT_B_1 = -1599035, - SAY_EVENT_B_2_MARN = -1599036, - SAY_EVENT_B_3 = -1599037, - - SAY_EVENT_C_1 = -1599038, - SAY_EVENT_C_2_ABED = -1599039, - SAY_EVENT_C_3 = -1599040, - - SAY_EVENT_D_1 = -1599041, - SAY_EVENT_D_2_ABED = -1599042, - SAY_EVENT_D_3 = -1599043, - SAY_EVENT_D_4_ABED = -1599044, - - SAY_EVENT_END_01 = -1599045, - SAY_EVENT_END_02 = -1599046, - SAY_EVENT_END_03_ABED = -1599047, - SAY_EVENT_END_04 = -1599048, - SAY_EVENT_END_05_ABED = -1599049, - SAY_EVENT_END_06 = -1599050, - SAY_EVENT_END_07_ABED = -1599051, - SAY_EVENT_END_08 = -1599052, - SAY_EVENT_END_09_KADD = -1599053, - SAY_EVENT_END_10 = -1599054, - SAY_EVENT_END_11_KADD = -1599055, - SAY_EVENT_END_12 = -1599056, - SAY_EVENT_END_13_KADD = -1599057, - SAY_EVENT_END_14 = -1599058, - SAY_EVENT_END_15_MARN = -1599059, - SAY_EVENT_END_16 = -1599060, - SAY_EVENT_END_17_MARN = -1599061, - SAY_EVENT_END_18 = -1599062, - SAY_EVENT_END_19_MARN = -1599063, - SAY_EVENT_END_20 = -1599064, - SAY_EVENT_END_21_ABED = -1599065, - - SAY_VICTORY_SJONNIR_1 = -1599066, - SAY_VICTORY_SJONNIR_2 = -1599067, - - SAY_ENTRANCE_MEET = -1599068, - - TEXT_ID_START = 13100, - TEXT_ID_PROGRESS = 13101 -}; - -enum BrannCreatures -{ - CREATURE_TRIBUNAL_OF_THE_AGES = 28234, - CREATURE_BRANN_BRONZEBEARD = 28070, - CREATURE_DARK_MATTER_TARGET = 28237, - CREATURE_SEARING_GAZE_TARGET = 28265, - CREATURE_DARK_RUNE_PROTECTOR = 27983, - CREATURE_DARK_RUNE_STORMCALLER = 27984, - CREATURE_IRON_GOLEM_CUSTODIAN = 27985, -}; - -enum Spells -{ - SPELL_STEALTH = 58506, - //Kadrak - SPELL_GLARE_OF_THE_TRIBUNAL = 50988, - H_SPELL_GLARE_OF_THE_TRIBUNAL = 59868, - //Marnak - SPELL_DARK_MATTER = 51012, - H_SPELL_DARK_MATTER = 59868, - //Abedneum - SPELL_SEARING_GAZE = 51136, - H_SPELL_SEARING_GAZE = 59867 -}; - -enum Quests -{ - QUEST_HALLS_OF_STONE = 13207 -}; - -enum Achievements -{ - ACHIEV_BRANN_SPANKIN_NEW = 2154 -}; - -#define GOSSIP_ITEM_START "Brann, it would be our honor!" -#define GOSSIP_ITEM_PROGRESS "Let's move Brann, enough of the history lessons!" - -static Position SpawnLocations[]= -{ - {946.992, 397.016, 208.374}, - {960.748, 382.944, 208.374}, -}; - -struct mob_tribuna_controllerAI : public ScriptedAI -{ - mob_tribuna_controllerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - SetCombatMovement(false); - } - - ScriptedInstance* pInstance; - - uint32 uiKaddrakEncounterTimer; - uint32 uiMarnakEncounterTimer; - uint32 uiAbedneumEncounterTimer; - - bool bKaddrakActivated; - bool bMarnakActivated; - bool bAbedneumActivated; - - std::list KaddrakGUIDList; - - void Reset() - { - uiKaddrakEncounterTimer = 1500; - uiMarnakEncounterTimer = 10000; - uiAbedneumEncounterTimer = 10000; - - bKaddrakActivated = false; - bMarnakActivated = false; - bAbedneumActivated = false; - - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); - } - - KaddrakGUIDList.clear(); - } - - void UpdateFacesList() - { - /*GetCreatureListWithEntryInGrid(lKaddrakGUIDList, me, CREATURE_KADDRAK, 50.0f); - if (!lKaddrakGUIDList.empty()) - { - uint32 uiPositionCounter = 0; - for (std::list::const_iterator itr = lKaddrakGUIDList.begin(); itr != lKaddrakGUIDList.end(); ++itr) - { - if ((*itr)->isAlive()) - { - if (uiPositionCounter == 0) - { - (*itr)->GetMap()->CreatureRelocation((*itr), 927.265, 333.200, 218.780, (*itr)->GetOrientation()); - (*itr)->SendMonsterMove(927.265, 333.200, 218.780, 0, (*itr)->GetMovementFlags(), 1); - } - else - { - (*itr)->GetMap()->CreatureRelocation((*itr), 921.745, 328.076, 218.780, (*itr)->GetOrientation()); - (*itr)->SendMonsterMove(921.745, 328.076, 218.780, 0, (*itr)->GetMovementFlags(), 1); - } - } - ++uiPositionCounter; - } - }*/ - } - - void UpdateAI(const uint32 diff) - { - if (bKaddrakActivated) - { - if (uiKaddrakEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (!KaddrakGUIDList.empty()) - for (std::list::const_iterator itr = KaddrakGUIDList.begin(); itr != KaddrakGUIDList.end(); ++itr) - { - if (Creature *pKaddrak = Unit::GetCreature(*me, *itr)) - { - if (pKaddrak->isAlive()) - pKaddrak->CastSpell(pTarget, DUNGEON_MODE(SPELL_GLARE_OF_THE_TRIBUNAL, H_SPELL_GLARE_OF_THE_TRIBUNAL), true); - } - } - uiKaddrakEncounterTimer = 1500; - } else uiKaddrakEncounterTimer -= diff; - } - if (bMarnakActivated) - { - if (uiMarnakEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature* pSummon = me->SummonCreature(CREATURE_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) - { - pSummon->SetDisplayId(11686); - pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_DARK_MATTER, H_SPELL_DARK_MATTER), true); - } - } - uiMarnakEncounterTimer = 30000 + rand()%1000; - } else uiMarnakEncounterTimer -= diff; - } - if (bAbedneumActivated) - { - if (uiAbedneumEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature* pSummon = me->SummonCreature(CREATURE_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) - { - pSummon->SetDisplayId(11686); - pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_SEARING_GAZE, H_SPELL_SEARING_GAZE), true); - } - } - uiAbedneumEncounterTimer = 30000 + rand()%1000; - } else uiAbedneumEncounterTimer -= diff; - } - } -}; - -struct npc_brann_hosAI : public npc_escortAI -{ - npc_brann_hosAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiStep; - uint32 uiPhaseTimer; - - uint64 uiControllerGUID; - std::list lDwarfGUIDList; - - ScriptedInstance* pInstance; - - bool bIsBattle; - bool bIsLowHP; - bool bHasBeenDamaged; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - bIsLowHP = false; - bIsBattle = false; - bHasBeenDamaged = false; - uiStep = 0; - uiPhaseTimer = 0; - uiControllerGUID = 0; - - DespawnDwarf(); - - if (pInstance) - pInstance->SetData(DATA_BRANN_EVENT, NOT_STARTED); - } - } - - void DespawnDwarf() - { - if (lDwarfGUIDList.empty()) - return; - for (std::list::const_iterator itr = lDwarfGUIDList.begin(); itr != lDwarfGUIDList.end(); ++itr) - { - Creature* pTemp = Unit::GetCreature(*me, pInstance ? (*itr) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->ForcedDespawn(); - } - lDwarfGUIDList.clear(); - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 7: - if (Creature* pCreature = GetClosestCreatureWithEntry(me, CREATURE_TRIBUNAL_OF_THE_AGES, 100.0f)) - { - if (!pCreature->isAlive()) - pCreature->Respawn(); - CAST_AI(mob_tribuna_controllerAI, pCreature->AI())->UpdateFacesList(); - uiControllerGUID = pCreature->GetGUID(); - } - break; - case 13: - DoScriptText(SAY_EVENT_INTRO_1, me); - SetEscortPaused(true); - JumpToNextStep(20000); - break; - case 17: - DoScriptText(SAY_EVENT_INTRO_2, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_TRIBUNAL_CONSOLE),true); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - SetEscortPaused(true); - JumpToNextStep(8500); - break; - case 18: - SetEscortPaused(true); - break; - } - } - - void SpawnDwarf(uint32 uiType) - { - switch(uiType) - { - case 1: - { - uint32 uiSpawnNumber = DUNGEON_MODE(2,3); - for (uint8 i = 0; i < uiSpawnNumber; ++i) - me->SummonCreature(CREATURE_DARK_RUNE_PROTECTOR, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - } - case 2: - for (uint8 i = 0; i < 2; ++i) - me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - case 3: - me->SummonCreature(CREATURE_IRON_GOLEM_CUSTODIAN, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - lDwarfGUIDList.push_back(pSummoned->GetGUID()); - pSummoned->AddThreat(me, 0.0f); - pSummoned->AI()->AttackStart(me); - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhaseTimer = uiTimer; - ++uiStep; - } - - void StartWP() - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetEscortPaused(false); - uiStep = 1; - Start(); - } - - void DamageTaken(Unit* /*done_by*/, uint32 & /*damage*/) - { - if (!bHasBeenDamaged) - bHasBeenDamaged = true; - } - - void UpdateEscortAI(const uint32 uiDiff) - { - if (uiPhaseTimer <= uiDiff) - { - switch(uiStep) - { - case 1: - if (pInstance) - { - if (pInstance->GetData(DATA_BRANN_EVENT) != NOT_STARTED) - return; - pInstance->SetData(DATA_BRANN_EVENT, IN_PROGRESS); - } - bIsBattle = false; - DoScriptText(SAY_ESCORT_START, me); - SetRun(true); - JumpToNextStep(0); - break; - case 3: - SetEscortPaused(false); - JumpToNextStep(0); - break; - case 5: - if (pInstance) - if (Creature* pTemp = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM)))) - DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp); - JumpToNextStep(8500); - break; - case 6: - DoScriptText(SAY_EVENT_A_1, me); - JumpToNextStep(6500); - break; - case 7: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_A_2_KADD, pTemp); - JumpToNextStep(12500); - break; - case 8: - DoScriptText(SAY_EVENT_A_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bKaddrakActivated = true; - JumpToNextStep(5000); - break; - case 9: - me->SetReactState(REACT_PASSIVE); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 10: - DoScriptText(SAY_EVENT_B_1, me); - JumpToNextStep(6000); - break; - case 11: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_B_2_MARN, pTemp); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 12: - DoScriptText(SAY_EVENT_B_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bMarnakActivated = true; - JumpToNextStep(10000); - break; - case 13: - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 14: - SpawnDwarf(2); - JumpToNextStep(20000); - break; - case 15: - DoScriptText(SAY_EVENT_C_1, me); - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 16: - SpawnDwarf(2); - JumpToNextStep(20000); - break; - case 17: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_C_2_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 18: - DoScriptText(SAY_EVENT_C_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bAbedneumActivated = true; - JumpToNextStep(5000); - break; - case 19: - SpawnDwarf(2); - JumpToNextStep(10000); - break; - case 20: - SpawnDwarf(1); - JumpToNextStep(15000); - break; - case 21: - DoScriptText(SAY_EVENT_D_1, me); - SpawnDwarf(3); - JumpToNextStep(20000); - break; - case 22: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_D_2_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(5000); - break; - case 23: - SpawnDwarf(2); - JumpToNextStep(15000); - break; - case 24: - DoScriptText(SAY_EVENT_D_3, me); - SpawnDwarf(3); - JumpToNextStep(5000); - break; - case 25: - SpawnDwarf(1); - JumpToNextStep(5000); - break; - case 26: - SpawnDwarf(2); - JumpToNextStep(10000); - break; - case 27: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_D_4_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 28: - me->SetReactState(REACT_DEFENSIVE); - DoScriptText(SAY_EVENT_END_01, me); - me->SetStandState(UNIT_STAND_STATE_STAND); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - bIsBattle = true; - SetEscortPaused(false); - JumpToNextStep(6500); - break; - case 29: - DoScriptText(SAY_EVENT_END_02, me); - if (pInstance) - { - pInstance->SetData(DATA_BRANN_EVENT, DONE); - - // Achievement criteria is with spell 59046 which does not exist. - // There is thus no way it can be given by casting the spell on the players. - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59046); - - if (!bHasBeenDamaged) - pInstance->DoCompleteAchievement(ACHIEV_BRANN_SPANKIN_NEW); - } - - JumpToNextStep(5500); - break; - case 30: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_03_ABED, pTemp); - JumpToNextStep(8500); - break; - case 31: - DoScriptText(SAY_EVENT_END_04, me); - JumpToNextStep(11500); - break; - case 32: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_05_ABED, pTemp); - JumpToNextStep(11500); - break; - case 33: - DoScriptText(SAY_EVENT_END_06, me); - JumpToNextStep(4500); - break; - case 34: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_07_ABED, pTemp); - JumpToNextStep(22500); - break; - case 35: - DoScriptText(SAY_EVENT_END_08, me); - JumpToNextStep(7500); - break; - case 36: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_09_KADD, pTemp); - JumpToNextStep(18500); - break; - case 37: - DoScriptText(SAY_EVENT_END_10, me); - JumpToNextStep(5500); - break; - case 38: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_11_KADD, pTemp); - JumpToNextStep(20500); - break; - case 39: - DoScriptText(SAY_EVENT_END_12, me); - JumpToNextStep(2500); - break; - case 40: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_13_KADD, pTemp); - JumpToNextStep(19500); - break; - case 41: - DoScriptText(SAY_EVENT_END_14, me); - JumpToNextStep(10500); - break; - case 42: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_15_MARN, pTemp); - JumpToNextStep(6500); - break; - case 43: - DoScriptText(SAY_EVENT_END_16, me); - JumpToNextStep(6500); - break; - case 44: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_17_MARN, pTemp); - JumpToNextStep(25500); - break; - case 45: - DoScriptText(SAY_EVENT_END_18, me); - JumpToNextStep(23500); - break; - case 46: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_19_MARN, pTemp); - JumpToNextStep(3500); - break; - case 47: - DoScriptText(SAY_EVENT_END_20, me); - JumpToNextStep(8500); - break; - case 48: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_21_ABED, pTemp); - JumpToNextStep(5500); - break; - case 49: - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); - } - Player* pPlayer = GetPlayerForEscort(); - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, me); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - JumpToNextStep(180000); - break; - } - case 50: - SetEscortPaused(false); - break; - } - } else uiPhaseTimer -= uiDiff; - - if (!bIsLowHP && HealthBelowPct(30)) - { - DoScriptText(SAY_LOW_HEALTH, me); - bIsLowHP = true; - } - else if (bIsLowHP && !HealthBelowPct(30)) - bIsLowHP = false; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_brann_hos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1 || uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_brann_hosAI, pCreature->AI())->StartWP(); - } - - return true; -} - -CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature) -{ - return new mob_tribuna_controllerAI(pCreature); -} - -CreatureAI* GetAI_npc_brann_hos(Creature* pCreature) -{ - return new npc_brann_hosAI(pCreature); -} - -void AddSC_halls_of_stone() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_brann_hos"; - newscript->GetAI = &GetAI_npc_brann_hos; - newscript->pGossipHello = &GossipHello_npc_brann_hos; - newscript->pGossipSelect = &GossipSelect_npc_brann_hos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tribuna_controller"; - newscript->GetAI = &GetAI_mob_tribuna_controller; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h b/src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h deleted file mode 100644 index b61e7057ddc..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef DEF_HALLS_OF_STONE_H -#define DEF_HALLS_OF_STONE_H -enum Data -{ - DATA_KRYSTALLUS_EVENT, - DATA_MAIDEN_OF_GRIEF_EVENT, - DATA_SJONNIR_EVENT, - DATA_BRANN_EVENT -}; -enum Data64 -{ - DATA_KRYSTALLUS, - DATA_MAIDEN_OF_GRIEF, - DATA_SJONNIR, - DATA_KADDRAK, - DATA_MARNAK, - DATA_ABEDNEUM, - DATA_GO_TRIBUNAL_CONSOLE, - DATA_GO_KADDRAK, - DATA_GO_MARNAK, - DATA_GO_ABEDNEUM, - DATA_GO_SKY_FLOOR, - DATA_SJONNIR_DOOR, - DATA_MAIDEN_DOOR -}; -enum Creatures -{ - CREATURE_MAIDEN = 27975, - CREATURE_KRYSTALLUS = 27977, - CREATURE_SJONNIR = 27978, - CREATURE_MARNAK = 30897, - CREATURE_KADDRAK = 30898, - CREATURE_ABEDNEUM = 30899, - CREATURE_BRANN = 28070 -}; -enum GameObjects -{ - GO_ABEDNEUM = 191669, - GO_MARNAK = 192170, - GO_KADDRAK = 192171, - GO_MAIDEN_DOOR = 191292, - GO_BRANN_DOOR = 191295, - GO_SJONNIR_DOOR = 191296, - GO_TRIBUNAL_CONSOLE = 193907, - GO_TRIBUNAL_CHEST = 190586, - GO_TRIBUNAL_CHEST_HERO = 193996 -}; -#endif diff --git a/src/server/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp b/src/server/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp deleted file mode 100644 index 69bb3779e70..00000000000 --- a/src/server/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -#define MAX_ENCOUNTER 4 - -/* Halls of Stone encounters: -0- Krystallus -1- Maiden of Grief -2- Escort Event -3- Sjonnir The Ironshaper -*/ - -struct instance_halls_of_stone : public ScriptedInstance -{ - instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiMaidenOfGrief; - uint64 uiKrystallus; - uint64 uiSjonnir; - - uint64 uiKaddrak; - uint64 uiAbedneum; - uint64 uiMarnak; - uint64 uiBrann; - - uint64 uiMaidenOfGriefDoor; - uint64 uiSjonnirDoor; - uint64 uiBrannDoor; - uint64 uiTribunalConsole; - uint64 uiTribunalChest; - uint64 uiTribunalSkyFloor; - uint64 uiKaddrakGo; - uint64 uiAbedneumGo; - uint64 uiMarnakGo; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() - { - uiMaidenOfGrief = 0; - uiKrystallus = 0; - uiSjonnir = 0; - - uiKaddrak = 0; - uiMarnak = 0; - uiAbedneum = 0; - uiBrann = 0; - - uiMaidenOfGriefDoor = 0; - uiSjonnirDoor = 0; - uiBrannDoor = 0; - uiKaddrakGo = 0; - uiMarnakGo = 0; - uiAbedneumGo = 0; - uiTribunalConsole = 0; - uiTribunalChest = 0; - uiTribunalSkyFloor = 0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i] = NOT_STARTED; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case CREATURE_MAIDEN: uiMaidenOfGrief = pCreature->GetGUID(); break; - case CREATURE_KRYSTALLUS: uiKrystallus = pCreature->GetGUID(); break; - case CREATURE_SJONNIR: uiSjonnir = pCreature->GetGUID(); break; - case CREATURE_MARNAK: uiMarnak = pCreature->GetGUID(); break; - case CREATURE_KADDRAK: uiKaddrak = pCreature->GetGUID(); break; - case CREATURE_ABEDNEUM: uiAbedneum = pCreature->GetGUID(); break; - case CREATURE_BRANN: uiBrann = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_ABEDNEUM: - uiAbedneumGo = pGo->GetGUID(); - break; - case GO_MARNAK: - uiMarnakGo = pGo->GetGUID(); - break; - case GO_KADDRAK: - uiKaddrakGo = pGo->GetGUID(); - break; - case GO_MAIDEN_DOOR: - uiMaidenOfGriefDoor = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_BRANN_DOOR: - uiBrannDoor = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_SJONNIR_DOOR: - uiSjonnirDoor = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_TRIBUNAL_CONSOLE: - uiTribunalConsole = pGo->GetGUID(); - break; - case GO_TRIBUNAL_CHEST: - case GO_TRIBUNAL_CHEST_HERO: - uiTribunalChest = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - case 191527: - uiTribunalSkyFloor = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MAIDEN_OF_GRIEF_EVENT: - m_auiEncounter[1] = data; - if (m_auiEncounter[1] == DONE) - HandleGameObject(uiBrannDoor,true); - break; - case DATA_KRYSTALLUS_EVENT: - m_auiEncounter[0] = data; - if (m_auiEncounter[0] == DONE) - HandleGameObject(uiMaidenOfGriefDoor,true); - break; - case DATA_SJONNIR_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_BRANN_EVENT: - m_auiEncounter[2] = data; - if (m_auiEncounter[2] == DONE) - { - HandleGameObject(uiSjonnirDoor,true); - GameObject *pGo = instance->GetGameObject(uiTribunalChest); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - } - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_KRYSTALLUS_EVENT: return m_auiEncounter[0]; - case DATA_MAIDEN_OF_GRIEF_EVENT: return m_auiEncounter[1]; - case DATA_SJONNIR_EVENT: return m_auiEncounter[2]; - case DATA_BRANN_EVENT: return m_auiEncounter[3]; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_MAIDEN_OF_GRIEF: return uiMaidenOfGrief; - case DATA_KRYSTALLUS: return uiKrystallus; - case DATA_SJONNIR: return uiSjonnir; - case DATA_KADDRAK: return uiKaddrak; - case DATA_MARNAK: return uiMarnak; - case DATA_ABEDNEUM: return uiAbedneum; - case DATA_GO_TRIBUNAL_CONSOLE: return uiTribunalConsole; - case DATA_GO_KADDRAK: return uiKaddrakGo; - case DATA_GO_ABEDNEUM: return uiAbedneumGo; - case DATA_GO_MARNAK: return uiMarnakGo; - case DATA_GO_SKY_FLOOR: return uiTribunalSkyFloor; - case DATA_SJONNIR_DOOR: return uiSjonnirDoor; - case DATA_MAIDEN_DOOR: return uiMaidenOfGriefDoor; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'H' && dataHead2 == 'S') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_halls_of_stone(Map* pMap) -{ - return new instance_halls_of_stone(pMap); -} - -void AddSC_instance_halls_of_stone() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_stone"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_stone; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_algalon.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_algalon.cpp deleted file mode 100644 index e944543fb9e..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_algalon.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -#define GAMEOBJECT_GIVE_OF_THE_OBSERVER 194821 - -enum Spells -{ - SPELL_ASCEND = 64487, - SPELL_BERSERK = 47008, - SPELL_BIG_BANG = 64443, - H_SPELL_BIG_BANG = 64584, - SPELL_COSMIC_SMASH = 62301, - H_SPELL_COSMIC_SMASH = 64598, - SPELL_PHASE_PUNCH = 64412, - SPELL_QUANTUM_STRIKE = 64395, - H_SPELL_QUANTUM_STRIKE = 64592, - SPELL_BLACK_HOLE_EXPLOSION = 64122, - SPELL_ARCANE_BARAGE = 64599, - H_SPELL_ARCANE_BARAGE = 64607 -}; - -enum Creatures -{ - CREATURE_COLLAPSING_STAR = 32955, - CREATURE_BLACK_HOLE = 32953, - CREATURE_LIVING_CONSTELLATION = 33052, - CREATURE_DARK_MATTER = 33089 -}; - -#define NORDRASSIL_X 1614.288574 -#define NORDRASSIL_Y -320.713287 -#define NORDRASSIL_Z 417.321167 -#define NORDRASSIL_X 1614.276245 -#define NORDRASSIL_Y -287.016632 -#define NORDRASSIL_Z 417.321106 -#define NORDRASSIL_X 1650.428467 -#define NORDRASSIL_Y -292.331390 -#define NORDRASSIL_Z 417.321167 -#define NORDRASSIL_X 1649.501831 -#define NORDRASSIL_Y -324.609222 -#define NORDRASSIL_Z 417.322174 - -enum Yells -{ - SAY_AGGRO = -1603000, - SAY_SLAY_1 = -1603001, - SAY_SLAY_2 = -1603002, - SAY_ENGADED_FOR_FIRTS_TIME = -1603003, - SAY_PHASE_2 = -1603004, - SAY_SUMMON_COLLAPSING_STAR = -1603005, - SAY_DEATH_1 = -1603006, - SAY_DEATH_2 = -1603007, - SAY_DEATH_3 = -1603008, - SAY_DEATH_4 = -1603009, - SAY_DEATH_5 = -1603010, - SAY_BERSERK = -1603011, - SAY_BIG_BANG_1 = -1603012, - SAY_BIG_BANG_2 = -1603013, - SAY_TIMER_1 = -1603014, - SAY_TIMER_2 = -1603015, - SAY_TIMER_3 = -1603016, - SAY_SUMMON_1 = -1603017, - SAY_SUMMON_2 = -1603018, - SAY_SUMMON_3 = -1603019, -}; - -struct boss_algalonAI : public ScriptedAI -{ - boss_algalonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Summon = false; // not in reset. intro speech done only once. - } - - ScriptedInstance* pInstance; - - std::list m_lCollapsingStarGUIDList; - - uint32 Phase; - uint32 Ascend_Timer; - uint32 Berserk_Timer; - uint32 BigBang_Timer; - uint32 CosmicSmash_Timer; - uint32 PhasePunch_Timer; - uint32 QuantumStrike_Timer; - uint32 CollapsingStar_Timer; - uint32 uiPhase_timer; - uint32 uiStep; - - uint64 BlackHoleGUID; - - bool Enrage; - bool Summon; - - void EnterCombat(Unit* who) - { - if (Summon) - { - DoScriptText(SAY_AGGRO, me); - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - DoZoneInCombat(who->ToCreature()); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - uiStep = 1; - } - - if (pInstance) - pInstance->SetData(TYPE_ALGALON, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void Reset() - { - Phase = 1; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pInstance) - pInstance->SetData(TYPE_ALGALON, NOT_STARTED); - - BlackHoleGUID = 0; - - uiPhase_timer = 0; - Ascend_Timer = 480000; //8 minutes - QuantumStrike_Timer = 4000 + rand()%10000; - Berserk_Timer = 360000; //6 minutes - CollapsingStar_Timer = urand(15000, 20000); //Spawns between 15 to 20 seconds - BigBang_Timer = 90000; - PhasePunch_Timer = 8000; - CosmicSmash_Timer = urand(30000, 60000); - Enrage = false; - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhase_timer = uiTimer; - ++uiStep; - } - - void DespawnCollapsingStar() - { - if (m_lCollapsingStarGUIDList.empty()) - return; - - for (std::list::const_iterator itr = m_lCollapsingStarGUIDList.begin(); itr != m_lCollapsingStarGUIDList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - if (pTemp->isAlive()) - pTemp->ForcedDespawn(); - } - } - m_lCollapsingStarGUIDList.clear(); - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == CREATURE_COLLAPSING_STAR) - { - Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (me->getVictim()) - pSummoned->AI()->AttackStart(pTarget ? pTarget : me->getVictim()); - m_lCollapsingStarGUIDList.push_back(pSummoned->GetGUID()); - } - } - - void SummonCollapsingStar(Unit* target) - { - DoScriptText(SAY_SUMMON_COLLAPSING_STAR, me); - me->SummonCreature(CREATURE_COLLAPSING_STAR,target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN, 100000); - me->SummonCreature(CREATURE_BLACK_HOLE,target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN, 27000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Phase == 1 && HealthBelowPct(20)) - { - Phase = 2; - DoScriptText(SAY_PHASE_2, me); - } - - if (HealthBelowPct(2)) - { - me->SummonGameObject(GAMEOBJECT_GIVE_OF_THE_OBSERVER, 1634.258667, -295.101166,417.321381,0,0,0,0,0,0); - - // All of them. or random? - DoScriptText(SAY_DEATH_1, me); - DoScriptText(SAY_DEATH_2, me); - DoScriptText(SAY_DEATH_3, me); - DoScriptText(SAY_DEATH_4, me); - DoScriptText(SAY_DEATH_5, me); - - me->DisappearAndDie(); - - if (pInstance) - pInstance->SetData(TYPE_ALGALON, DONE); - - return; - } - - if (Phase == 1) - { - if (!Summon) - { - if (uiPhase_timer <= diff) - { - switch(uiStep) - { - case 1: - DoScriptText(SAY_SUMMON_1, me); - JumpToNextStep(3000); - break; - case 2: - DoScriptText(SAY_SUMMON_2, me); - JumpToNextStep(3000); - break; - case 3: - DoScriptText(SAY_SUMMON_3, me); - JumpToNextStep(3000); - break; - case 4: - DoScriptText(SAY_ENGADED_FOR_FIRTS_TIME, me); - JumpToNextStep(3000); - break; - case 5: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - Summon = true; - break; - } - } else uiPhase_timer -= diff; - - return; - } - - if (QuantumStrike_Timer <= diff) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_QUANTUM_STRIKE,H_SPELL_QUANTUM_STRIKE), true); - - QuantumStrike_Timer = urand(4000, 14000); - } else QuantumStrike_Timer -= diff; - - if (BigBang_Timer <= diff) - { - DoScriptText(RAND(SAY_BIG_BANG_1,SAY_BIG_BANG_2), me); - DoCast(me->getVictim(), RAID_MODE(SPELL_BIG_BANG,H_SPELL_BIG_BANG), true); - - BigBang_Timer = 90000; - } else BigBang_Timer -= diff; - - if (Ascend_Timer <= diff) - { - DoCast(me->getVictim(),SPELL_ASCEND, true); - - Ascend_Timer = 480000; - } else Ascend_Timer -= diff; - - if (PhasePunch_Timer <= diff) - { - DoCast(me->getVictim(),SPELL_PHASE_PUNCH, true); - - PhasePunch_Timer = 8000; - } else PhasePunch_Timer -= diff; - - if (CosmicSmash_Timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), RAID_MODE(SPELL_COSMIC_SMASH,H_SPELL_COSMIC_SMASH), true); - - CosmicSmash_Timer = urand(30000, 60000); - } else CosmicSmash_Timer -= diff; - - if (Berserk_Timer <= diff) - { - DoScriptText(SAY_BERSERK, me); - DoCast(me->getVictim(),SPELL_BERSERK, true); - - Berserk_Timer = 360000; - } else Berserk_Timer -= diff; - - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } - - if (Phase == 2) - { - if (Enrage) - { - if (Ascend_Timer <= diff) - { - DoCast(me, SPELL_ASCEND); - DoScriptText(SAY_BERSERK, me); - Ascend_Timer = urand(360000,365000); - Enrage = false; - } else Ascend_Timer -= diff; - } - } - - DoMeleeAttackIfReady(); - } -}; - -//Collapsing Star -struct mob_collapsing_starAI : public ScriptedAI -{ - mob_collapsing_starAI(Creature *pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 BlackHoleExplosion_Timer; - - void Reset() - { - BlackHoleExplosion_Timer = 0; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BlackHoleExplosion_Timer <= diff) - { - me->CastSpell(me, SPELL_BLACK_HOLE_EXPLOSION, false); - BlackHoleExplosion_Timer = 0; - } else BlackHoleExplosion_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_algalon(Creature* pCreature) -{ - return new boss_algalonAI(pCreature); -} - -CreatureAI* GetAI_mob_collapsing_star(Creature* pCreature) -{ - return new mob_collapsing_starAI(pCreature); -} - -void AddSC_boss_Algalon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_algalon"; - newscript->GetAI = &GetAI_boss_algalon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_collapsing_star"; - newscript->GetAI = &GetAI_mob_collapsing_star; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp deleted file mode 100644 index 8d3ae4d3431..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Assembly of Iron encounter -SD%Complete: 60% -SDComment: Runes need DB support, chain lightning won't cast, supercharge won't cast (pTarget error?) - it worked before during debugging. -SDCategory: Ulduar - Ulduar -EndScriptData */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -// Any boss -#define SPELL_SUPERCHARGE 61920 -#define SPELL_BERSERK 47008 // Hard enrage, don't know the correct ID. - -// Steelbreaker -#define SPELL_HIGH_VOLTAGE 61890 -#define SPELL_HIGH_VOLTAGE_H 63498 -#define SPELL_FUSION_PUNCH 61903 -#define SPELL_FUSION_PUNCH_H 63493 -#define SPELL_STATIC_DISRUPTION 44008 -#define SPELL_STATIC_DISRUPTION_H 63494 -#define SPELL_OVERWHELMING_POWER_H 61888 -#define SPELL_OVERWHELMING_POWER 64637 -#define SPELL_ELECTRICAL_CHARGE 61902 - -// Runemaster Molgeim -#define SPELL_SHIELD_OF_RUNES 62274 -#define SPELL_SHIELD_OF_RUNES_H 63489 -#define SPELL_RUNE_OF_POWER 64320 -#define SPELL_RUNE_OF_DEATH 62269 -#define SPELL_RUNE_OF_SUMMONING 62273 -#define SPELL_LIGHTNING_BLAST 62054 -#define SPELL_LIGHTNING_BLAST_H 63491 -#define CREATURE_RUNE_OF_SUMMONING 33051 - -// Stormcaller Brundir -#define SPELL_CHAIN_LIGHTNING_N 61879 -#define SPELL_CHAIN_LIGHTNING_H 63479 -#define SPELL_OVERLOAD 61869 -#define SPELL_OVERLOAD_H 63481 -#define SPELL_LIGHTNING_WHIRL 61915 -#define SPELL_LIGHTNING_WHIRL_H 63483 -#define SPELL_LIGHTNING_TENDRILS 61887 -#define SPELL_LIGHTNING_TENDRILS_H 63486 -#define SPELL_STORMSHIELD 64187 - -enum Events -{ - EVENT_NONE, - EVENT_ENRAGE, - // Steelbreaker - EVENT_FUSION_PUNCH, - EVENT_STATIC_DISRUPTION, - EVENT_OVERWHELMING_POWER, - // Molgeim - EVENT_RUNE_OF_POWER, - EVENT_SHIELD_OF_RUNES, - EVENT_RUNE_OF_DEATH, - EVENT_RUNE_OF_SUMMONING, - EVENT_LIGHTNING_BLAST, - // Brundir - EVENT_CHAIN_LIGHTNING, - EVENT_OVERLOAD, - EVENT_LIGHTNING_WHIRL, - EVENT_LIGHTNING_TENDRILS, - EVENT_STORMSHIELD, -}; - -enum Yells -{ - SAY_STEELBREAKER_AGGRO = -1603020, - SAY_STEELBREAKER_SLAY_1 = -1603021, - SAY_STEELBREAKER_SLAY_2 = -1603022, - SAY_STEELBREAKER_POWER = -1603023, - SAY_STEELBREAKER_DEATH_1 = -1603024, - SAY_STEELBREAKER_DEATH_2 = -1603025, - SAY_STEELBREAKER_BERSERK = -1603026, - - SAY_MOLGEIM_AGGRO = -1603030, - SAY_MOLGEIM_SLAY_1 = -1603031, - SAY_MOLGEIM_SLAY_2 = -1603032, - SAY_MOLGEIM_RUNE_DEATH = -1603033, - SAY_MOLGEIM_SUMMON = -1603034, - SAY_MOLGEIM_DEATH_1 = -1603035, - SAY_MOLGEIM_DEATH_2 = -1603036, - SAY_MOLGEIM_BERSERK = -1603037, - - SAY_BRUNDIR_AGGRO = -1603040, - SAY_BRUNDIR_SLAY_1 = -1603041, - SAY_BRUNDIR_SLAY_2 = -1603042, - SAY_BRUNDIR_SPECIAL = -1603043, - SAY_BRUNDIR_FLIGHT = -1603044, - SAY_BRUNDIR_DEATH_1 = -1603045, - SAY_BRUNDIR_DEATH_2 = -1603046, - SAY_BRUNDIR_BERSERK = -1603047, -}; - -bool IsEncounterComplete(ScriptedInstance* pInstance, Creature* me) -{ - if (!pInstance || !me) - return false; - - for (uint8 i = 0; i < 3; ++i) - { - uint64 guid = pInstance->GetData64(DATA_STEELBREAKER+i); - if (!guid) - return false; - - if (Creature *boss = Unit::GetCreature(*me, guid)) - { - if (boss->isAlive()) - return false; - } - else - return false; - } - return true; -} - -struct boss_steelbreakerAI : public ScriptedAI -{ - boss_steelbreakerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() - { - events.Reset(); - phase = 0; - me->RemoveAllAuras(); - if (pInstance) - pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); - } - - EventMap events; - ScriptedInstance* pInstance; - uint32 phase; - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_STEELBREAKER_AGGRO, me); - DoZoneInCombat(); - DoCast(me, RAID_MODE(SPELL_HIGH_VOLTAGE, SPELL_HIGH_VOLTAGE_H)); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - UpdatePhase(); - } - - void UpdatePhase() - { - ++phase; - events.SetPhase(phase); - events.RescheduleEvent(EVENT_FUSION_PUNCH, 15000); - if (phase >= 2) - events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 30000); - if (phase >= 3) - events.RescheduleEvent(EVENT_OVERWHELMING_POWER, rand()%5000); - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - if (Creature* Brundir = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0)) - if (Brundir->isAlive()) - Brundir->SetHealth(Brundir->GetMaxHealth()); - - if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0)) - if (Molgeim->isAlive()) - Molgeim->SetHealth(Molgeim->GetMaxHealth()); - - DoCast(SPELL_SUPERCHARGE); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_STEELBREAKER_DEATH_1,SAY_STEELBREAKER_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(TYPE_ASSEMBLY, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_STEELBREAKER_SLAY_1,SAY_STEELBREAKER_SLAY_2), me); - - if (phase == 3) - DoCast(me, SPELL_ELECTRICAL_CHARGE); - } - - void SpellHit(Unit * /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - UpdatePhase(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ENRAGE: - DoScriptText(SAY_STEELBREAKER_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_FUSION_PUNCH: - DoCast(me->getVictim(), RAID_MODE(SPELL_FUSION_PUNCH, SPELL_FUSION_PUNCH_H)); - events.ScheduleEvent(EVENT_FUSION_PUNCH, urand(13000, 22000)); - break; - case EVENT_STATIC_DISRUPTION: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, RAID_MODE(SPELL_STATIC_DISRUPTION, SPELL_STATIC_DISRUPTION_H)); - events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(20000, 40000)); - break; - case EVENT_OVERWHELMING_POWER: - DoScriptText(SAY_STEELBREAKER_POWER, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_OVERWHELMING_POWER, SPELL_OVERWHELMING_POWER_H)); - events.ScheduleEvent(EVENT_OVERWHELMING_POWER, RAID_MODE(60000, 35000)); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_runemaster_molgeimAI : public ScriptedAI -{ - boss_runemaster_molgeimAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() - { - if (pInstance) - pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); - events.Reset(); - me->RemoveAllAuras(); - phase = 0; - } - - ScriptedInstance* pInstance; - EventMap events; - uint32 phase; - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_MOLGEIM_AGGRO, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - UpdatePhase(); - } - - void UpdatePhase() - { - ++phase; - events.SetPhase(phase); - events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27000); - events.RescheduleEvent(EVENT_RUNE_OF_POWER, 60000); - if (phase >= 2) - events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 30000); - if (phase >= 3) - events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0)) - if (Steelbreaker->isAlive()) - Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth()); - - if (Creature* Brundir = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0)) - if (Brundir->isAlive()) - Brundir->SetHealth(Brundir->GetMaxHealth()); - - DoCast(me, SPELL_SUPERCHARGE); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_MOLGEIM_DEATH_1,SAY_MOLGEIM_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(TYPE_ASSEMBLY, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_MOLGEIM_SLAY_1,SAY_MOLGEIM_SLAY_2), me); - } - - void SpellHit(Unit * /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - UpdatePhase(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ENRAGE: - DoScriptText(SAY_MOLGEIM_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly - { - Unit *pTarget = DoSelectLowestHpFriendly(60); - if (!pTarget || (pTarget && !pTarget->isAlive())) - pTarget = me; - DoCast(pTarget, SPELL_RUNE_OF_POWER); - events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000); - break; - } - case EVENT_SHIELD_OF_RUNES: - DoCast(me, RAID_MODE(SPELL_SHIELD_OF_RUNES, SPELL_SHIELD_OF_RUNES_H)); - events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, urand(27000,34000)); - break; - case EVENT_RUNE_OF_DEATH: - DoScriptText(SAY_MOLGEIM_RUNE_DEATH, me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_RUNE_OF_DEATH); - events.ScheduleEvent(EVENT_RUNE_OF_DEATH, urand(30000,40000)); - break; - case EVENT_RUNE_OF_SUMMONING: - DoScriptText(SAY_MOLGEIM_SUMMON, me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_RUNE_OF_SUMMONING); - events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_lightning_elementalAI : public ScriptedAI -{ - mob_lightning_elementalAI(Creature *c) : ScriptedAI(c) - { - Charge(); - } - - void Charge() - { - Unit* pTarget = me->SelectNearestTarget(); - me->AddThreat(pTarget, 5000000.0f); - AttackStart(pTarget); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!me->isInCombat()) - return; - - if (!UpdateVictim()) - return; - - if (me->IsWithinMeleeRange(me->getVictim())) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_LIGHTNING_BLAST, SPELL_LIGHTNING_BLAST_H)); - me->Kill(me); // hack until spell works - } - - me->GetMotionMaster()->MoveChase(me->getVictim()); // needed at every update? - } -}; - -struct mob_rune_of_summoningAI : public ScriptedAI -{ - mob_rune_of_summoningAI(Creature *c) : ScriptedAI(c) - { - SummonLightningElemental(); - } - - void SummonLightningElemental() - { - me->SummonCreature(CREATURE_RUNE_OF_SUMMONING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN); - me->DealDamage(me, me->GetHealth()); - } -}; - -struct boss_stormcaller_brundirAI : public ScriptedAI -{ - boss_stormcaller_brundirAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() - { - if (pInstance) - pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); - me->RemoveAllAuras(); - events.Reset(); - phase = 0; - } - - EventMap events; - ScriptedInstance* pInstance; - uint32 phase; - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_BRUNDIR_AGGRO, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - UpdatePhase(); - } - - void UpdatePhase() - { - ++phase; - events.SetPhase(phase); - events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000,17000)); - events.RescheduleEvent(EVENT_OVERLOAD, urand(60000,125000)); - if (phase >= 2) - events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000,40000)); - if (phase >= 3) - { - DoCast(me, SPELL_STORMSHIELD); - events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, urand(40000,80000)); - } - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0)) - if (Steelbreaker->isAlive()) - Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth()); - - if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0)) - if (Molgeim->isAlive()) - Molgeim->SetHealth(Molgeim->GetMaxHealth()); - - DoCast(SPELL_SUPERCHARGE); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_BRUNDIR_DEATH_1,SAY_BRUNDIR_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(TYPE_ASSEMBLY, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_BRUNDIR_SLAY_1,SAY_BRUNDIR_SLAY_2), me); - } - - void SpellHit(Unit * /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - UpdatePhase(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ENRAGE: - DoScriptText(SAY_BRUNDIR_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_CHAIN_LIGHTNING: - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, RAID_MODE(SPELL_CHAIN_LIGHTNING_N , SPELL_CHAIN_LIGHTNING_H)); - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000,17000)); - break; - case EVENT_OVERLOAD: - DoCast(RAID_MODE(SPELL_OVERLOAD , SPELL_OVERLOAD_H)); - events.ScheduleEvent(EVENT_OVERLOAD, urand(60000,125000)); - break; - case EVENT_LIGHTNING_WHIRL: - DoCast(RAID_MODE(SPELL_LIGHTNING_WHIRL , SPELL_LIGHTNING_WHIRL_H)); - events.ScheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000,40000)); - break; - case EVENT_LIGHTNING_TENDRILS: - DoCast(RAID_MODE(SPELL_LIGHTNING_TENDRILS, SPELL_LIGHTNING_TENDRILS_H)); - events.DelayEvents(15000, 5000); - DoResetThreat(); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_steelbreaker(Creature* pCreature) -{ - return new boss_steelbreakerAI (pCreature); -} - -CreatureAI* GetAI_boss_runemaster_molgeim(Creature* pCreature) -{ - return new boss_runemaster_molgeimAI (pCreature); -} - -CreatureAI* GetAI_boss_stormcaller_brundir(Creature* pCreature) -{ - return new boss_stormcaller_brundirAI (pCreature); -} - -CreatureAI* GetAI_mob_lightning_elemental(Creature* pCreature) -{ - return new mob_lightning_elementalAI (pCreature); -} - -CreatureAI* GetAI_mob_rune_of_summoning(Creature* pCreature) -{ - return new mob_rune_of_summoningAI (pCreature); -} - -void AddSC_boss_assembly_of_iron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_steelbreaker"; - newscript->GetAI = &GetAI_boss_steelbreaker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_runemaster_molgeim"; - newscript->GetAI = &GetAI_boss_runemaster_molgeim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_stormcaller_brundir"; - newscript->GetAI = &GetAI_boss_stormcaller_brundir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lightning_elemental"; - newscript->GetAI = &GetAI_mob_lightning_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_rune_of_summoning"; - newscript->GetAI = &GetAI_mob_rune_of_summoning; - newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp deleted file mode 100644 index 41c0f317f4e..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -//boss_auriaya -#define SPELL_TERRIFYING_SCREECH 64386 -#define SPELL_SETINEL_BLAST 64679 -#define SPELL_SONIC_SCREECH 64422 -#define SPELL_SUMMON_SWARMING_GUARDIAN 64397 - -enum Yells -{ - SAY_AGGRO = -1603050, - SAY_SLAY_1 = -1603051, - SAY_SLAY_2 = -1603052, - SAY_DEATH = -1603053, - SAY_BERSERK = -1603054, -}; - -struct boss_auriaya_AI : public BossAI -{ - boss_auriaya_AI(Creature *pCreature) : BossAI(pCreature, TYPE_AURIAYA) - { - } - - uint32 TERRIFYING_SCREECH_Timer; - uint32 SONIC_SCREECH_Timer; - - void Reset() - { - _Reset(); - TERRIFYING_SCREECH_Timer = 180000; - SONIC_SCREECH_Timer = 30000; - } - - void EnterCombat(Unit* /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO,me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (TERRIFYING_SCREECH_Timer <= diff) - { - DoCast(SPELL_TERRIFYING_SCREECH); - TERRIFYING_SCREECH_Timer = 180000; - } else TERRIFYING_SCREECH_Timer -= diff; - - if (SONIC_SCREECH_Timer <= diff) - { - DoCastVictim(SPELL_SONIC_SCREECH); - SONIC_SCREECH_Timer = 30000; - } else SONIC_SCREECH_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_auriaya(Creature* pCreature) -{ - return new boss_auriaya_AI (pCreature); -} - -void AddSC_boss_auriaya() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_auriaya"; - newscript->GetAI = &GetAI_boss_auriaya; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp deleted file mode 100644 index b50f12805a4..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: Tower Event support is not finished, there is missing code on triggers and - * Lore Keeper and Brann Bronzebeard are not scripted yet. Lore Keeper's script - * should activate the hard mode so is not possible to play hard-mode yet. Add a call to - * Leviathan's DoAction(0) from Lore Keeper's script to activate hard-mode - */ - -#include "ScriptedPch.h" -#include "ulduar.h" -#include "Vehicle.h" - -enum Spells -{ - SPELL_PURSUED = 62374, - SPELL_GATHERING_SPEED = 62375, - SPELL_BATTERING_RAM = 62376, - SPELL_FLAME_VENTS = 62396, - SPELL_MISSILE_BARRAGE = 62400, - SPELL_SYSTEMS_SHUTDOWN = 62475, - - SPELL_FLAME_CANNON = 62395, -// SPELL_FLAME_CANNON = 64692, trigger the same spell - - SPELL_OVERLOAD_CIRCUIT = 62399, - SPELL_SEARING_FLAME = 62402, - SPELL_BLAZE = 62292, - SPELL_SMOKE_TRAIL = 63575, - SPELL_ELECTROSHOCK = 62522, - //TOWER BUFF SPELLS - SPELL_THORIM_S_HAMMER = 62912, // Tower of Storms - SPELL_MIMIRON_S_INFERNO = 62910, // Tower of Flames - SPELL_HODIR_S_FURY = 62297, // Tower of Frost - SPELL_FREYA_S_WARD = 62906 // Tower of Nature -}; - -enum Creatures -{ - MOB_MECHANOLIFT = 33214, - MOB_LIQUID = 33189, - MOB_CONTAINER = 33218, -}; - -enum Events -{ - EVENT_NONE, - EVENT_PURSUE, - EVENT_MISSILE, - EVENT_VENT, - EVENT_SPEED, - EVENT_SUMMON, - EVENT_THORIM_S_HAMMER, // Tower of Storms - EVENT_MIMIRON_S_INFERNO, // Tower of Flames - EVENT_HODIR_S_FURY, // Tower of Frost - EVENT_FREYA_S_WARD // Tower of Nature -}; - -enum Seats -{ - SEAT_PLAYER = 0, - SEAT_TURRET = 1, - SEAT_DEVICE = 2, -}; - -enum Yells -{ - SAY_AGGRO = -1603060, - SAY_SLAY = -1603061, - SAY_DEATH = -1603062, - SAY_TARGET_1 = -1603063, - SAY_TARGET_2 = -1603064, - SAY_TARGET_3 = -1603065, - SAY_HARDMODE = -1603066, - SAY_TOWER_NONE = -1603067, - SAY_TOWER_FROST = -1603068, - SAY_TOWER_FLAME = -1603069, - SAY_TOWER_NATURE = -1603070, - SAY_TOWER_STORM = -1603071, - SAY_PLAYER_RIDING = -1603072, - SAY_OVERLOAD_1 = -1603073, - SAY_OVERLOAD_2 = -1603074, - SAY_OVERLOAD_3 = -1603075, -}; - -enum eAchievementData -{ - //ACHIEV_CHAMPION_OF_ULDUAR = 10042, - //ACHIEV_CONQUEROR_OF_ULDUAR = 10352, - ACHIEV_10_NUKED_FROM_ORBIT = 10058, - ACHIEV_25_NUKED_FROM_ORBIT = 10060, - ACHIEV_10_ORBITAL_BOMBARDMENT = 10056, - ACHIEV_25_ORBITAL_BOMBARDMENT = 10061, - ACHIEV_10_ORBITAL_DEVASTATION = 10057, - ACHIEV_25_ORBITAL_DEVASTATION = 10059, - ACHIEV_10_ORBIT_UARY = 10218, - ACHIEV_25_ORBIT_UARY = 10219, - ACHIEV_10_SHUTOUT = 10054, - ACHIEV_25_SHUTOUT = 10055, - ACHIEV_10_SIEGE_OF_ULDUAR = 9999, - ACHIEV_25_SIEGE_OF_ULDUAR = 10003, - //ACHIEV_10_THREE_CAR_GARAGE = 10046, 10047, 10048, - //ACHIEV_25_THREE_CAR_GARAGE = 10049, 10050, 10051, - ACHIEV_10_UNBROKEN = 10044, - ACHIEV_25_UNBROKEN = 10045, -}; - -static Position Center[]= -{ - {354.8771, -12.90240, 409.803650}, -}; - -struct boss_flame_leviathanAI : public BossAI -{ - boss_flame_leviathanAI(Creature* pCreature) : BossAI(pCreature, TYPE_LEVIATHAN), vehicle(pCreature->GetVehicleKit()) - { - assert(vehicle); - - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - Vehicle* vehicle; - uint8 uiActiveTowers; - - void Reset() - { - _Reset(); - assert(vehicle); - uiActiveTowers = 0; - me->SetReactState(REACT_AGGRESSIVE); - } - - void EnterCombat(Unit* /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO, me); - me->SetReactState(REACT_DEFENSIVE); - events.ScheduleEvent(EVENT_PURSUE, 0); - events.ScheduleEvent(EVENT_MISSILE, 1500); - events.ScheduleEvent(EVENT_VENT, 20000); - events.ScheduleEvent(EVENT_SPEED, 15000); - events.ScheduleEvent(EVENT_SUMMON, 0); - - if (Creature *turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET))) - turret->AI()->DoZoneInCombat(); - } - - // TODO: effect 0 and effect 1 may be on different target - void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_PURSUED) - AttackStart(pTarget); - } - - void JustDied(Unit* /*victim*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - if (pInstance) - { - if (uiActiveTowers) - { - switch (uiActiveTowers) - { - case 4: - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBIT_UARY, ACHIEV_25_ORBIT_UARY)); - break; - case 3: - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_NUKED_FROM_ORBIT, ACHIEV_25_NUKED_FROM_ORBIT)); - break; - case 2: - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBITAL_DEVASTATION, ACHIEV_25_ORBITAL_DEVASTATION)); - break; - case 1: - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBITAL_BOMBARDMENT, ACHIEV_25_ORBITAL_BOMBARDMENT)); - break; - } - } - } - } - - void SpellHit(Unit* /*caster*/, const SpellEntry* pSpell) - { - if (pSpell->Id == 62472) - vehicle->InstallAllAccessories(); - else if (pSpell->Id == SPELL_ELECTROSHOCK) - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; - - if (me->getThreatManager().isThreatListEmpty()) - { - EnterEvadeMode(); - return; - } - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - uint32 eventId = events.GetEvent(); - if (!me->getVictim()) - eventId = EVENT_PURSUE; - - switch(eventId) - { - case 0: break; // this is a must - case EVENT_PURSUE: - DoCastAOE(SPELL_PURSUED, true); - //events.RepeatEvent(35000); // this should not be used because eventId may be overriden - events.RescheduleEvent(EVENT_PURSUE, 35000); - if (!me->getVictim()) // all siege engines and demolishers are dead - UpdateVictim(); // begin to kill other things - return; - case EVENT_MISSILE: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_MISSILE_BARRAGE); - events.RepeatEvent(1500); - return; - case EVENT_VENT: - DoCastAOE(SPELL_FLAME_VENTS); - events.RepeatEvent(20000); - return; - case EVENT_SPEED: - DoCastAOE(SPELL_GATHERING_SPEED); - events.RepeatEvent(15000); - return; - case EVENT_SUMMON: - if (summons.size() < 15) // 4seat+1turret+10lift - if (Creature* pLift = DoSummonFlyer(MOB_MECHANOLIFT, me, urand(20,40), 50, 0)) - pLift->GetMotionMaster()->MoveRandom(100); - events.RepeatEvent(2000); - return; - case EVENT_THORIM_S_HAMMER: // Tower of Storms - DoCast(me, SPELL_THORIM_S_HAMMER); - events.RepeatEvent(urand(60000, 120000)); - return; - case EVENT_MIMIRON_S_INFERNO: // Tower of Flames - DoCast(me->getVictim(), SPELL_MIMIRON_S_INFERNO); - events.RepeatEvent(urand(60000, 120000)); - return; - case EVENT_HODIR_S_FURY: // Tower of Frost - DoCast(me->getVictim(), SPELL_HODIR_S_FURY); - events.RepeatEvent(urand(60000, 120000)); - return; - case EVENT_FREYA_S_WARD: // Tower of Nature - DoCast(me, SPELL_FREYA_S_WARD); - events.RepeatEvent(urand(60000, 120000)); - return; - default: - events.PopEvent(); - break; - } - DoSpellAttackIfReady(SPELL_BATTERING_RAM); - } - - void DoAction(const int32 uiAction) - { - // Start encounter - if (uiAction == 10) - { - me->GetMotionMaster()->MovePoint(0, Center[0]); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - return; - } - /* - Tower event triggers - General TODO: - Yells - - Actions: - DoAction(0): Activate hard-mode. Buff up leviathan's AP & health, schedule all the tower spells. - Should be triggered on Lore Keeper's script - DoAction(1-4): A tower have been destroyed, debuff leviathan's AP & health - DoAction(1); Tower of Storms has been destroyed, deschedule spell Thorim's Hammer - DoAction(2): Tower of Flames has been destroyed, deschedule spell Mimiron's Inferno - DoAction(3): Tower of Frost has been destroyed, deschedule spell Hodir's Fury - DoAction(4): Tower of Nature has been destroyed, deschedule spell Freya's Ward - */ - - if (uiAction) // Tower destruction, debuff leviathan AP & health - { - --uiActiveTowers; - } - - switch (uiAction) - { - case 0: // Activate hard-mode - events.ScheduleEvent(EVENT_THORIM_S_HAMMER, urand(30000,60000)); - events.ScheduleEvent(EVENT_MIMIRON_S_INFERNO, urand(30000,60000)); - events.ScheduleEvent(EVENT_HODIR_S_FURY, urand(30000,60000)); - events.ScheduleEvent(EVENT_FREYA_S_WARD, urand(30000,60000)); - uiActiveTowers=4; - break; - case 1: // Tower of Storms destroyed - events.CancelEvent(EVENT_THORIM_S_HAMMER); - break; - case 2: // Tower of Flames destroyed - events.CancelEvent(EVENT_MIMIRON_S_INFERNO); - break; - case 3: // Tower of Frost destroyed - events.CancelEvent(EVENT_HODIR_S_FURY); - break; - case 4: // Tower of Nature destroyed - events.CancelEvent(EVENT_FREYA_S_WARD); - break; - } - } -}; - -//#define BOSS_DEBUG - -struct boss_flame_leviathan_seatAI : public PassiveAI -{ - boss_flame_leviathan_seatAI(Creature *c) : PassiveAI(c), vehicle(c->GetVehicleKit()) - { - assert(vehicle); -#ifdef BOSS_DEBUG - me->SetReactState(REACT_AGGRESSIVE); -#endif - } - - Vehicle* vehicle; - -#ifdef BOSS_DEBUG - void MoveInLineOfSight(Unit *who) - { - if (who->GetTypeId() == TYPEID_PLAYER && CAST_PLR(who)->isGameMaster() - && !who->GetVehicle() && vehicle->GetPassenger(SEAT_TURRET)) - who->EnterVehicle(vehicle, SEAT_PLAYER); - } -#endif - - void PassengerBoarded(Unit* who, int8 seatId, bool apply) - { - if (!me->GetVehicle()) - return; - - if (seatId == SEAT_PLAYER) - { - if (!apply) - return; - - if (Creature* turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET))) - { - turret->setFaction(me->GetVehicleBase()->getFaction()); - turret->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable - turret->AI()->AttackStart(who); - } - if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) - { - device->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - device->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - } - else if (seatId == SEAT_TURRET) - { - if (apply) - return; - - if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) - { - device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - device->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable - } - } - } -}; - -struct boss_flame_leviathan_defense_turretAI : public TurretAI -{ - boss_flame_leviathan_defense_turretAI(Creature *c) : TurretAI(c) {} - - void DamageTaken(Unit* who, uint32 &damage) - { - if (!CanAIAttack(who)) - damage = 0; - } - - bool CanAIAttack(const Unit *who) const - { - if (who->GetTypeId() != TYPEID_PLAYER || !who->GetVehicle() || who->GetVehicleBase()->GetEntry() != 33114) - return false; - return true; - } -}; - -struct boss_flame_leviathan_overload_deviceAI : public PassiveAI -{ - boss_flame_leviathan_overload_deviceAI(Creature* pCreature) : PassiveAI(pCreature) {} - - void DoAction(const int32 param) - { - if (param == EVENT_SPELLCLICK) - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (me->GetVehicle()) - { - if (Unit* pPlayer = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) - { - pPlayer->ExitVehicle(); - me->GetVehicleBase()->CastSpell(pPlayer, SPELL_SMOKE_TRAIL, true); - if (Unit* leviathan = me->GetVehicleBase()->GetVehicleBase()) - pPlayer->GetMotionMaster()->MoveKnockbackFrom(leviathan->GetPositionX(), leviathan->GetPositionY(), 30, 30); - } - } - } - } -}; - -struct boss_flame_leviathan_safety_containerAI : public PassiveAI -{ - boss_flame_leviathan_safety_containerAI(Creature *c) : PassiveAI(c) {} - - void MovementInform(uint32 /*type*/, uint32 id) - { - if (id == me->GetEntry()) - { - if (Creature* pLiquid = DoSummon(MOB_LIQUID, me, 0)) - pLiquid->CastSpell(pLiquid, 62494, true); - me->DisappearAndDie(); // this will relocate creature to sky - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!me->GetVehicle() && me->isSummon() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) - me->GetMotionMaster()->MoveFall(409.8f, me->GetEntry()); - } -}; - -struct spell_pool_of_tarAI : public TriggerAI -{ - spell_pool_of_tarAI(Creature *c) : TriggerAI(c) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void DamageTaken(Unit * /*who*/, uint32 &damage) - { - damage = 0; - } - - void SpellHit(Unit* /*caster*/, const SpellEntry *spell) - { - if (spell->SchoolMask & SPELL_SCHOOL_MASK_FIRE && !me->HasAura(SPELL_BLAZE)) - me->CastSpell(me, SPELL_BLAZE, true); - } -}; - -struct npc_colossusAI : public ScriptedAI -{ - npc_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance *pInstance; - Position pPos; - - void JustDied(Unit* /*Who*/) - { - if (me->GetHomePosition().IsInDist(Center,50.f)) - { - if (pInstance) - pInstance->SetData(TYPE_COLOSSUS,pInstance->GetData(TYPE_COLOSSUS)+1); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_boss_flame_leviathan(Creature* pCreature) -{ - return new boss_flame_leviathanAI (pCreature); -} - -CreatureAI* GetAI_boss_flame_leviathan_seat(Creature* pCreature) -{ - return new boss_flame_leviathan_seatAI (pCreature); -} - -CreatureAI* GetAI_boss_flame_leviathan_defense_turret(Creature* pCreature) -{ - return new boss_flame_leviathan_defense_turretAI (pCreature); -} - -CreatureAI* GetAI_boss_flame_leviathan_overload_device(Creature* pCreature) -{ - return new boss_flame_leviathan_overload_deviceAI (pCreature); -} - -CreatureAI* GetAI_boss_flame_leviathan_safety_containerAI(Creature* pCreature) -{ - return new boss_flame_leviathan_safety_containerAI(pCreature); -} - -CreatureAI* GetAI_spell_pool_of_tar(Creature* pCreature) -{ - return new spell_pool_of_tarAI (pCreature); -} - -CreatureAI* GetAI_npc_colossus(Creature* pCreature) -{ - return new npc_colossusAI(pCreature); -} - -void AddSC_boss_flame_leviathan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_flame_leviathan"; - newscript->GetAI = &GetAI_boss_flame_leviathan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_flame_leviathan_seat"; - newscript->GetAI = &GetAI_boss_flame_leviathan_seat; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_flame_leviathan_defense_turret"; - newscript->GetAI = &GetAI_boss_flame_leviathan_defense_turret; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_flame_leviathan_overload_device"; - newscript->GetAI = &GetAI_boss_flame_leviathan_overload_device; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_flame_leviathan_safety_container"; - newscript->GetAI = &GetAI_boss_flame_leviathan_safety_containerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "spell_pool_of_tar"; - newscript->GetAI = &GetAI_spell_pool_of_tar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_colossus"; - newscript->GetAI = &GetAI_npc_colossus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_freya.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_freya.cpp deleted file mode 100644 index ee995878a0e..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_freya.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO = -1603180, - SAY_AGGRO_WITH_ELDER = -1603181, - SAY_SLAY_1 = -1603182, - SAY_SLAY_2 = -1603183, - SAY_DEATH = -1603184, - SAY_BERSERK = -1603185, - SAY_SUMMON_CONSERVATOR = -1603186, - SAY_SUMMON_TRIO = -1603187, - SAY_SUMMON_LASHERS = -1603188, - SAY_YS_HELP = -1603189, - - // Elder Brightleaf - SAY_BRIGHTLEAF_AGGRO = -1603190, - SAY_BRIGHTLEAF_SLAY_1 = -1603191, - SAY_BRIGHTLEAF_SLAY_2 = -1603192, - SAY_BRIGHTLEAF_DEATH = -1603193, - - // Elder Ironbranch - SAY_IRONBRANCH_AGGRO = -1603194, - SAY_IRONBRANCH_SLAY_1 = -1603195, - SAY_IRONBRANCH_SLAY_2 = -1603196, - SAY_IRONBRANCH_DEATH = -1603197, - - // Elder Stonebark - SAY_STONEBARK_AGGRO = -1603198, - SAY_STONEBARK_SLAY_1 = -1603199, - SAY_STONEBARK_SLAY_2 = -1603200, - SAY_STONEBARK_DEATH = -1603201, -}; - -enum -{ - // Con-speed-atory timed achievement. - // TODO Should be started when 1st trash is killed. - ACHIEV_CON_SPEED_ATORY_START_EVENT = 21597, - SPELL_ACHIEVEMENT_CHECK = 65074, - - // Lumberjacked timed achievement. - // TODO should be started when 1st elder is killed. - // Spell should be casted when 3rd elder is killed. - ACHIEV_LUMBERJACKED = 21686, - SPELL_LUMBERJACKED_ACHIEVEMENT_CHECK = 65296, -}; - -struct boss_freyaAI : public BossAI -{ - boss_freyaAI(Creature* pCreature) : BossAI(pCreature, TYPE_FREYA) - { - } - - void Reset() - { - _Reset(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - - // cast is not rewarding the achievement. - // DoCast(SPELL_ACHIEVEMENT_CHECK); - instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_ACHIEVEMENT_CHECK); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - _EnterCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; -//SPELLS TODO: - -// - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_freya(Creature* pCreature) -{ - return new boss_freyaAI(pCreature); -} - -void AddSC_boss_freya() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_freya"; - newscript->GetAI = &GetAI_boss_freya; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp deleted file mode 100644 index f84c638d3e3..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO = -1603290, - SAY_SLAY_1 = -1603291, - SAY_SLAY_2 = -1603292, - SAY_KITE = -1603293, - SAY_DEATH = -1603294, - SAY_BERSERK = -1603295, - SAY_HARDMODE_ON = -1603296, -}; diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_hodir.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_hodir.cpp deleted file mode 100644 index 6facd8ac639..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_hodir.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO = -1603210, - SAY_SLAY_1 = -1603211, - SAY_SLAY_2 = -1603212, - SAY_FLASH_FREEZE = -1603213, - SAY_STALACTITE = -1603214, - SAY_DEATH = -1603215, - SAY_BERSERK = -1603216, - SAY_YS_HELP = -1603217, - SAY_HARD_MODE_MISSED = -1603218, -}; - -struct boss_hodirAI : public BossAI -{ - boss_hodirAI(Creature *pCreature) : BossAI(pCreature, TYPE_HODIR) - { - } - - void Reset() - { - _Reset(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - _EnterCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; -//SPELLS TODO: - -// - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_hodir(Creature* pCreature) -{ - return new boss_hodirAI(pCreature); -} - -void AddSC_boss_hodir() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hodir"; - newscript->GetAI = &GetAI_boss_hodir; - newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_ignis.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_ignis.cpp deleted file mode 100644 index 05f9ecd3c66..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_ignis.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -#define SPELL_FLAME_JETS 62680 -#define SPELL_SCORCH 62546 -#define SPELL_SLAG_POT 62717 - -enum Yells -{ - SAY_AGGRO = -1603220, - SAY_SLAY_1 = -1603221, - SAY_SLAY_2 = -1603222, - SAY_DEATH = -1603223, - SAY_SUMMON = -1603224, - SAY_SLAG_POT = -1603225, - SAY_SCORCH_1 = -1603226, - SAY_SCORCH_2 = -1603227, - SAY_BERSERK = -1603228, -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 20951, -}; - -struct boss_ignis_AI : public BossAI -{ - boss_ignis_AI(Creature *pCreature) : BossAI(pCreature, TYPE_IGNIS) {} - - uint32 uiFlameJetsTimer; - uint32 uiScorchTimer; - uint32 uiSlagPotTimer; - - void Reset() - { - _Reset(); - uiFlameJetsTimer = 32000; - uiScorchTimer = 100; - uiSlagPotTimer = 100; - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO,me); - _EnterCombat(); - - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetPositionY() < 150 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(false); - me->GetMotionMaster()->MoveTargetedHome(); - } - - if (uiFlameJetsTimer <= diff) - { - DoCast(SPELL_FLAME_JETS); - uiFlameJetsTimer = 25000; - } else uiFlameJetsTimer -= diff; - - if (uiScorchTimer <= diff) - { - DoScriptText(RAND(SAY_SCORCH_1,SAY_SCORCH_2), me); - DoCast(SPELL_SCORCH); - uiScorchTimer = 20000; - } else uiScorchTimer -= diff; - - if (uiSlagPotTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(SAY_SLAG_POT, me); - DoCast(pTarget, SPELL_SLAG_POT); - } - uiSlagPotTimer = 30000; - } else uiSlagPotTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ignis(Creature* pCreature) -{ - return new boss_ignis_AI (pCreature); -} -void AddSC_boss_ignis() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ignis"; - newscript->GetAI = &GetAI_boss_ignis; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp deleted file mode 100644 index 2080b458a1b..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" -#include "Vehicle.h" - -#define SPELL_ARM_DEAD_DAMAGE RAID_MODE(63629,63979) -#define SPELL_TWO_ARM_SMASH RAID_MODE(63356,64003) -#define SPELL_ONE_ARM_SMASH RAID_MODE(63573,64006) -#define SPELL_STONE_SHOUT RAID_MODE(63716,64005) -#define SPELL_PETRIFY_BREATH RAID_MODE(62030,63980) - -#define SPELL_STONE_GRIP RAID_MODE(62166,63981) -#define SPELL_ARM_SWEEP RAID_MODE(63766,63983) - -enum Events -{ - EVENT_NONE = 0, - EVENT_SMASH, - EVENT_GRIP, - EVENT_SWEEP, -}; - -enum Yells -{ - SAY_AGGRO = -1603230, - SAY_SLAY_1 = -1603231, - SAY_SLAY_2 = -1603232, - SAY_LEFT_ARM_GONE = -1603233, - SAY_RIGHT_ARM_GONE = -1603234, - SAY_SHOCKWAVE = -1603235, - SAY_GRAB_PLAYER = -1603236, - SAY_DEATH = -1603237, - SAY_BERSERK = -1603238, -}; - -enum -{ - ACHIEV_DISARMED_START_EVENT = 21687, -}; - -struct boss_kologarnAI : public BossAI -{ - boss_kologarnAI(Creature *pCreature) : BossAI(pCreature, TYPE_KOLOGARN), vehicle(pCreature->GetVehicleKit()), - left(false), right(false) - { - assert(vehicle); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); // i think this is a hack, but there is no other way to disable his rotation - } - - Vehicle *vehicle; - bool left, right; - - void AttackStart(Unit *who) - { - me->Attack(who, true); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void KilledUnit(Unit* /*who*/) - { - DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_2), me); - } - - void PassengerBoarded(Unit *who, int8 /*seatId*/, bool apply) - { - if (who->GetTypeId() == TYPEID_UNIT) - { - if (who->GetEntry() == 32933) - left = apply; - else if (who->GetEntry() == 32934) - right = apply; - - if (!apply && instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT); - - who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - CAST_CRE(who)->SetReactState(REACT_PASSIVE); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - _EnterCombat(); - events.ScheduleEvent(EVENT_SMASH, 5000); - events.ScheduleEvent(EVENT_SWEEP, 10000); - events.ScheduleEvent(EVENT_GRIP, 15000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - // TODO: because we are using hack, he is stunned and cannot cast, so we use triggered for every spell - switch(events.GetEvent()) - { - case EVENT_NONE: - break; - case EVENT_SMASH: - if (left && right) - DoCastVictim(SPELL_TWO_ARM_SMASH, true); - else if (left || right) - DoCastVictim(SPELL_ONE_ARM_SMASH, true); - events.RepeatEvent(15000); - break; - case EVENT_SWEEP: - if (left) - DoCastAOE(SPELL_ARM_SWEEP, true); - events.RepeatEvent(15000); - break; - case EVENT_GRIP: - if (right) - DoCastAOE(SPELL_STONE_GRIP, true); - events.RepeatEvent(15000); - break; - default: - events.PopEvent(); - break; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kologarn(Creature* pCreature) -{ - return new boss_kologarnAI (pCreature); -} - -void AddSC_boss_kologarn() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kologarn"; - newscript->GetAI = &GetAI_boss_kologarn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp deleted file mode 100644 index 2b9994d5d9b..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO = -1603240, - SAY_HARDMODE_ON = -1603241, - SAY_MKII_ACTIVATE = -1603242, - SAY_MKII_SLAY_1 = -1603243, - SAY_MKII_SLAY_2 = -1603244, - SAY_MKII_DEATH = -1603245, - SAY_VX001_ACTIVATE = -1603246, - SAY_VX001_SLAY_1 = -1603247, - SAY_VX001_SLAY_2 = -1603248, - SAY_VX001_DEATH = -1603249, - SAY_AERIAL_ACTIVATE = -1603250, - SAY_AERIAL_SLAY_1 = -1603251, - SAY_AERIAL_SLAY_2 = -1603252, - SAY_AERIAL_DEATH = -1603253, - SAY_V07TRON_ACTIVATE = -1603254, - SAY_V07TRON_SLAY_1 = -1603255, - SAY_V07TRON_SLAY_2 = -1603256, - SAY_V07TRON_DEATH = -1603257, - SAY_BERSERK = -1603258, - SAY_YS_HELP = -1603259, -}; diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp deleted file mode 100644 index c61f1046474..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: razorscale -SDAuthor: MaXiMiUS -SD%Complete: 65 -EndScriptData */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -//not in db -#define SAY_AGGRO -2000000 -#define SAY_KILL -2000001 -#define SAY_PHASE_2_TRANS -2000002 -#define SAY_PHASE_3_TRANS -2000003 -#define EMOTE_BREATH -2000004 - -enum Spells -{ - SPELL_FLAMEBUFFET = 64016, - SPELL_FIREBALL = 62796, - - SPELL_WINGBUFFET = 62666, - SPELL_FLAMEBREATH = 63317, - SPELL_FUSEARMOR = 64771, - SPELL_DEVOURINGFLAME = 63014 -}; - -enum Mobs -{ - NPC_DARK_RUNE_SENTINEL = 33846 -}; - -struct boss_razorscaleAI : public BossAI -{ - boss_razorscaleAI(Creature *pCreature) : BossAI(pCreature, TYPE_RAZORSCALE) {} - - uint8 Phase; - - uint32 FlameBreathTimer; - uint32 FuseArmorTimer; - uint32 DevouringFlameTimer; - uint32 FlameBuffetTimer; - uint32 SummonAddsTimer; - uint32 WingBuffetTimer; - uint32 FireballTimer; - //uint32 StunTimer; - //uint32 CastSpellsTimer; - - bool InitialSpawn; - bool IsFlying; - - void Reset() - { - Phase = 1; - - FlyPhase(Phase, 0); - - FlameBreathTimer = 20000; - DevouringFlameTimer = 2000; - FuseArmorTimer = 15000; - FlameBuffetTimer = 3000; - SummonAddsTimer = 45000; - WingBuffetTimer = 17000; - FireballTimer = 18000; - //StunTimer = 30000; - //CastSpellsTimer = 0; - - InitialSpawn = true; - IsFlying = true; - - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - } - - void JustDied(Unit* /*Killer*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetPositionY() > -60 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(false); - me->GetMotionMaster()->MoveTargetedHome(); - } - - // Victim is not controlled by a player (should never happen) - if (me->getVictim() && !me->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) - me->Kill(me->getVictim()); - - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 99 && Phase == 1) // TODO: Only land (exit Phase 1) if brought down with harpoon guns! This is important! - { - Phase = 2; - DoScriptText(SAY_PHASE_2_TRANS, me); // Audio: "Move quickly! She won't remain grounded for long!" - } - - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 33 && Phase == 2) // Health under 33%, Razorscale can't fly anymore. - { - Phase = 3; - DoScriptText(SAY_PHASE_3_TRANS, me); // "Razorscale lands permanently!" - // TODO: Cast Devouring Flame on all harpoon guns simultaneously, briefly after Phase 3 starts (lasts until the harpoon guns are destroyed) - } - - /* - if (Phase == 2 && CastSpellsTimer > 0) // 5 seconds of spell casting, after stun breaks, during Phase 2 - { - if (CastSpellsTimer <= diff) // 5 seconds are up - Phase = 1; // Return to phase 1 - else - CastSpellsTimer -= diff; - }*/ - - FlyPhase(Phase, diff); - - if (Phase >= 2) // Ground Phase (Phase 3 = permanent ground phase) - { - if (FuseArmorTimer <= diff) - { - DoCastVictim(SPELL_FUSEARMOR); - FuseArmorTimer = 10000; - } else FuseArmorTimer -= diff; - - if (WingBuffetTimer <= diff) - { - DoCast(SPELL_WINGBUFFET); - WingBuffetTimer = urand(7000,14000); - } else WingBuffetTimer -= diff; - - if (FireballTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - { - me->SetInFront(pTarget); - DoCast(pTarget, SPELL_FIREBALL); - } - - FireballTimer = 18000; - } else FireballTimer -= diff; - - if (FlameBreathTimer <= diff) - { - DoScriptText(EMOTE_BREATH, me); // TODO: "Razorscale takes a deep breath..." - DoCastVictim(SPELL_FLAMEBREATH); - FlameBreathTimer = 15000; - WingBuffetTimer = 0; - } else FlameBreathTimer -= diff; - - if (Phase == 3) - { - if (FlameBuffetTimer <= diff) - { - DoScriptText(EMOTE_BREATH, me); - std::list pTargets; - SelectTargetList(pTargets, RAID_MODE(3,9), SELECT_TARGET_RANDOM, 100, true); - uint8 i = 0; - for (std::list::const_iterator itr = pTargets.begin(); itr != pTargets.end();) - { - if (me->HasInArc(M_PI, *itr)) - { - DoCast(*itr, SPELL_FLAMEBUFFET, true); - ++i; - } - if (++itr == pTargets.end() || i == RAID_MODE(3,9)) - { - AttackStart(*--itr); // seems to attack targets randomly during perma-ground phase.. - break; - } - } - FlameBuffetTimer = 25000; - } else FlameBuffetTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - else if (Phase == 1) //Flying Phase - { - if (InitialSpawn) - SummonAdds(); - - InitialSpawn = false; - - if (FireballTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - { - me->SetInFront(pTarget); - DoCast(pTarget, SPELL_FIREBALL); - } - - FireballTimer = 18000; - } else FireballTimer -= diff; - - if (DevouringFlameTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - { - me->SetInFront(pTarget); - DoCast(pTarget, SPELL_DEVOURINGFLAME); - } - - DevouringFlameTimer = 10000; - } else DevouringFlameTimer -= diff; - - if (SummonAddsTimer <= diff) - SummonAdds(); - else SummonAddsTimer -= diff; - } - } - - void SummonAdds() - { - // TODO: Adds will come in waves from mole machines. One mole can spawn a Dark Rune Watcher - // with 1-2 Guardians, or a lone Sentinel. Up to 4 mole machines can spawn adds at any given time. - uint8 random = urand(1,4); - for (uint8 i = 0; i < random; ++i) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - { - float x = std::max(500.0f, std::min(650.0f, pTarget->GetPositionX() + irand(-20,20))); // Safe range is between 500 and 650 - float y = std::max(-235.0f, std::min(-145.0f, pTarget->GetPositionY() + irand(-20,20))); // Safe range is between -235 and -145 - float z = me->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); // Ground level - // TODO: Spawn drillers, then spawn adds 5 seconds later - if (Creature *pAdd = me->SummonCreature(NPC_DARK_RUNE_SENTINEL, x, y, z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)) - pAdd->AI()->AttackStart(pTarget); - } - } - SummonAddsTimer = 45000; - } - - void FlyPhase(uint8 Phase, const uint32 /*diff*/) - { - const float x = 587.54; - const float y = -174.92; - const float GroundLevel = me->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); - const float FlightHeight = GroundLevel + 4.0f; // TODO: Fly out of range of attacks (442 is sufficient height for this), minus ~(10*number of harpoon gun chains attached to Razorscale) - - if (Phase == 1) // Always flying during Phase 1 - IsFlying = true; - - me->SetFlying(IsFlying); - me->SendMovementFlagUpdate(); - me->SetSpeed(MOVE_WALK, IsFlying ? 7.0f : 2.5f, IsFlying); - - if (Phase == 1) // Flying Phase - { - if (me->GetPositionZ() > FlightHeight) // Correct height, stop moving - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - else // Incorrect height - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->GetMotionMaster()->MovePoint(0, x, y, FlightHeight + 0.5f); // Fly to slightly above (x, y, FlightHeight) - } - } - else // Ground Phases - { - const float CurrentGroundLevel = me->GetBaseMap()->GetHeight(me->GetPositionX(), me->GetPositionY(), MAX_HEIGHT); - //if (StunTimer == 30000) // Only fly around if not stunned. - //{ - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - if (IsFlying && me->GetPositionZ() > CurrentGroundLevel) // Fly towards the ground - me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), CurrentGroundLevel); - // TODO: Swoop up just before landing - else - IsFlying = false; // Landed, no longer flying - //} - - //if (!IsFlying &&Phase == 2 && CastSpellsTimer == 0 && StunTimer >= diff) // No longer flying, non-permanent ground phase, and not casting spells - //{ - // TODO: Add stun here. 30 second stun after Razorscale is grounded by harpoon guns - //StunTimer -= diff; - //} - //else if (StunTimer != 30000 && (StunTimer < 0 || Phase == 3)) // Stun is active, and needs to end. Note: Stun breaks instantly if Phase 3 starts - //{ - // TODO: Remove stun here. - //DoCast(SPELL_WINGBUFFET); // "Used in the beginning of the phase." - //WingBuffetTimer = urand(7000,14000); - //StunTimer = 30000; // Reinitialize the stun timer - //if (Phase == 2) // Non-permanent ground phase - // CastSpellsTimer = 5000; // Five seconds of casting before returning to Phase 1 - //} - } - } -}; - -CreatureAI* GetAI_boss_razorscale(Creature* pCreature) -{ - return new boss_razorscaleAI (pCreature); -} - -void AddSC_boss_razorscale() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_razorscale"; - newscript->GetAI = &GetAI_boss_razorscale; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_thorim.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_thorim.cpp deleted file mode 100644 index bbab077e10e..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_thorim.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO_1 = -1603270, - SAY_AGGRO_2 = -1603271, - SAY_SPECIAL_1 = -1603272, - SAY_SPECIAL_2 = -1603273, - SAY_SPECIAL_3 = -1603274, - SAY_JUMPDOWN = -1603275, - SAY_SLAY_1 = -1603276, - SAY_SLAY_2 = -1603277, - SAY_BERSERK = -1603278, - SAY_WIPE = -1603279, - SAY_DEATH = -1603280, - SAY_END_NORMAL_1 = -1603281, - SAY_END_NORMAL_2 = -1603282, - SAY_END_NORMAL_3 = -1603283, - SAY_END_HARD_1 = -1603284, - SAY_END_HARD_2 = -1603285, - SAY_END_HARD_3 = -1603286, - SAY_YS_HELP = -1603287, -}; - -struct boss_thorimAI : public BossAI -{ - boss_thorimAI(Creature* pCreature) : BossAI(pCreature, TYPE_THORIM) - { - } - - void Reset() - { - _Reset(); - } - - void EnterEvadeMode() - { - DoScriptText(SAY_WIPE, me); - _EnterEvadeMode(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me); - _EnterCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; -//SPELLS TODO: - -// - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_thorim(Creature* pCreature) -{ - return new boss_thorimAI(pCreature); -} - -void AddSC_boss_thorim() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_thorim"; - newscript->GetAI = &GetAI_boss_thorim; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_xt002.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_xt002.cpp deleted file mode 100644 index 58123951d2f..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_xt002.cpp +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - TODO: - Add achievments - Boombot explosion only hurt allies to the npc at the moment - Boombot explosion visual - Test the enrage timer - Fix gravity bomb - tractor beam. - Fix void zone spell - If the boss is to close to a scrap pile -> no summon - make the life sparks visible... -*/ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Spells -{ - SPELL_TYMPANIC_TANTRUM = 62776, - SPELL_SEARING_LIGHT_10 = 63018, - SPELL_SEARING_LIGHT_25 = 65121, - - SPELL_GRAVITY_BOMB_10 = 63024, - SPELL_GRAVITY_BOMB_25 = 63234, - SPELL_GRAVITY_BOMB_AURA_10 = 63025, - SPELL_GRAVITY_BOMB_AURA_25 = 63233, - - SPELL_HEARTBREAK_10 = 65737, - SPELL_HEARTBREAK_25 = 64193, - - SPELL_ENRAGE = 26662, - - //------------------VOID ZONE-------------------- - SPELL_VOID_ZONE_10 = 64203, - SPELL_VOID_ZONE_25 = 64235, - - // Life Spark - SPELL_STATIC_CHARGED_10 = 64227, - SPELL_STATIC_CHARGED_25 = 64236, - SPELL_SHOCK = 64230, - - //----------------XT-002 HEART------------------- - SPELL_EXPOSED_HEART = 63849, - - //---------------XM-024 PUMMELLER---------------- - SPELL_ARCING_SMASH = 8374, - SPELL_TRAMPLE = 5568, - SPELL_UPPERCUT = 10966, - - //------------------BOOMBOT----------------------- - SPELL_BOOM = 62834, -}; - -enum Timers -{ - TIMER_TYMPANIC_TANTRUM_MIN = 32000, - TIMER_TYMPANIC_TANTRUM_MAX = 36000, - TIMER_SEARING_LIGHT = 20000, - TIMER_SPAWN_LIFE_SPARK = 9000, - TIMER_GRAVITY_BOMB = 20000, - TIMER_HEART_PHASE = 30000, - TIMER_ENRAGE = 600000, - TIMER_GRAVITY_BOMB_AURA = 8900, - - TIMER_VOID_ZONE = 3000, - - // Life Spark - TIMER_SHOCK = 12000, - - // Pummeller - // Timers may be off - TIMER_ARCING_SMASH = 27000, - TIMER_TRAMPLE = 22000, - TIMER_UPPERCUT = 17000, - - TIMER_SPAWN_ADD = 12000, -}; - -enum Creatures -{ - NPC_VOID_ZONE = 34001, - NPC_LIFE_SPARK = 34004, - NPC_XT002_HEART = 33329, - NPC_XS013_SCRAPBOT = 33343, - NPC_XM024_PUMMELLER = 33344, - NPC_XE321_BOOMBOT = 33346, -}; - -enum Actions -{ - ACTION_ENTER_HARD_MODE = 0, -}; - -enum XT002Data -{ - DATA_TRANSFERED_HEALTH = 0, -}; - -enum Yells -{ - SAY_AGGRO = -1603300, - SAY_HEART_OPENED = -1603301, - SAY_HEART_CLOSED = -1603302, - SAY_TYMPANIC_TANTRUM = -1603303, - SAY_SLAY_1 = -1603304, - SAY_SLAY_2 = -1603305, - SAY_BERSERK = -1603306, - SAY_DEATH = -1603307, - SAY_SUMMON = -1603308, -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 21027, -}; - -//#define GRAVITY_BOMB_DMG_MIN_10 11700 -//#define GRAVITY_BOMB_DMG_MAX_10 12300 -//#define GRAVITY_BOMB_DMG_MIN_25 14625 -//#define GRAVITY_BOMB_DMG_MAX_25 15375 -//#define GRAVITY_BOMB_RADIUS 12 - -//#define VOID_ZONE_DMG_10 5000 -//#define VOID_ZONE_DMG_25 7500 -//#define VOID_ZONE_RADIUS - - -/************************************************ ------------------SPAWN LOCATIONS----------------- -************************************************/ -//Shared Z-level -#define SPAWN_Z 412 -//Lower right -#define LR_X 796 -#define LR_Y -94 -//Lower left -#define LL_X 796 -#define LL_Y 57 -//Upper right -#define UR_X 890 -#define UR_Y -82 -//Upper left -#define UL_X 894 -#define UL_Y 62 - -/*------------------------------------------------------- - * - * XT-002 DECONSTRUCTOR - * - *///---------------------------------------------------- -struct boss_xt002_AI : public BossAI -{ - boss_xt002_AI(Creature *pCreature) : BossAI(pCreature, TYPE_XT002) - { - } - - uint32 uiSearingLightTimer; - uint32 uiSpawnLifeSparkTimer; - uint32 uiGravityBombTimer; - uint32 uiGravityBombAuraTimer; - uint32 uiTympanicTantrumTimer; - uint32 uiHeartPhaseTimer; - uint32 uiSpawnAddTimer; - uint32 uiEnrageTimer; - - bool searing_light_active; - uint64 uiSearingLightTarget; - - bool gravity_bomb_active; - uint64 uiGravityBombTarget; - - uint8 phase; - uint8 heart_exposed; - bool enraged; - - uint32 transferHealth; - bool enterHardMode; - bool hardMode; - - void Reset() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - - //Makes XT-002 to cast a light bomb 10 seconds after aggro. - uiSearingLightTimer = TIMER_SEARING_LIGHT/2; - uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; - uiGravityBombTimer = TIMER_GRAVITY_BOMB; - uiGravityBombAuraTimer = TIMER_GRAVITY_BOMB_AURA; - uiHeartPhaseTimer = TIMER_HEART_PHASE; - uiSpawnAddTimer = TIMER_SPAWN_ADD; - uiEnrageTimer = TIMER_ENRAGE; - - //Tantrum is casted a bit slower the first time. - uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX) * 2; - - searing_light_active = false; - gravity_bomb_active = false; - enraged = false; - hardMode = false; - enterHardMode = false; - - phase = 1; - heart_exposed = 0; - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - _EnterCombat(); - - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void DoAction(const int32 action) - { - switch (action) - { - case ACTION_ENTER_HARD_MODE: - if (!hardMode) - { - hardMode = true; - - // Enter hard mode - enterHardMode = true; - - // set max health - me->SetHealth(me->GetMaxHealth()); - - // Get his heartbreak buff - me->CastSpell(me, RAID_MODE(SPELL_HEARTBREAK_10, SPELL_HEARTBREAK_25), true); - } - break; - } - } - - void SetData(uint32 id, uint32 value) - { - switch(id) - { - case DATA_TRANSFERED_HEALTH: - transferHealth = value; - break; - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (enterHardMode) - { - SetPhaseOne(); - enterHardMode = false; - } - - // Handles spell casting. These spells only occur during phase 1 and hard mode - if (phase == 1 || hardMode) - { - if (uiSearingLightTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, RAID_MODE(SPELL_SEARING_LIGHT_10, SPELL_SEARING_LIGHT_25)); - uiSearingLightTarget = pTarget->GetGUID(); - } - uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; - if (hardMode) - searing_light_active = true; - uiSearingLightTimer = TIMER_SEARING_LIGHT; - } else uiSearingLightTimer -= diff; - - if (uiGravityBombTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, RAID_MODE(SPELL_GRAVITY_BOMB_10,SPELL_GRAVITY_BOMB_25)); - uiGravityBombTarget = pTarget->GetGUID(); - } - uiGravityBombTimer = TIMER_GRAVITY_BOMB; - gravity_bomb_active = true; - } else uiGravityBombTimer -= diff; - - if (uiTympanicTantrumTimer <= 0) - { - DoScriptText(SAY_TYMPANIC_TANTRUM, me); - DoCast(SPELL_TYMPANIC_TANTRUM); - uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX); - } else uiTympanicTantrumTimer -= diff; - } - - if (!hardMode) - { - if (phase == 1) - { - if (HealthBelowPct(75) && heart_exposed == 0) - { - exposeHeart(); - } - else if (HealthBelowPct(50) && heart_exposed == 1) - { - exposeHeart(); - } - else if (HealthBelowPct(25) && heart_exposed == 2) - { - exposeHeart(); - } - - DoMeleeAttackIfReady(); - } - else - { - //Stop moving - me->StopMoving(); - - //Start summoning adds - if (uiSpawnAddTimer <= diff) - { - DoScriptText(SAY_SUMMON, me); - - // Spawn Pummeller - switch (rand() % 4) - { - case 0: me->SummonCreature(NPC_XM024_PUMMELLER, LR_X, LR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 1: me->SummonCreature(NPC_XM024_PUMMELLER, LL_X, LL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 2: me->SummonCreature(NPC_XM024_PUMMELLER, UR_X, UR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 3: me->SummonCreature(NPC_XM024_PUMMELLER, UL_X, UL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - } - - // Spawn 5 Bombs - for (int8 n = 0; n < 5; n++) - { - //Some randomes are added so they wont spawn in a pile - switch(rand() % 4) - { - case 0: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(LR_X - 3, LR_X + 3), irand(LR_Y - 3, LR_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 1: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(LL_X - 3, LL_X + 3), irand(LL_Y - 3, LL_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 2: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(UR_X - 3, UR_X + 3), irand(UR_Y - 3, UR_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 3: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(UL_X - 3, UL_X + 3), irand(UL_Y - 3, UL_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - } - } - - //Spawn 5 Scrapbots - switch (rand() % 4) - { - case 0: me->SummonCreature(NPC_XE321_BOOMBOT, LR_X, LR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 1: me->SummonCreature(NPC_XE321_BOOMBOT, LL_X, LL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 2: me->SummonCreature(NPC_XE321_BOOMBOT, UR_X, UR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 3: me->SummonCreature(NPC_XE321_BOOMBOT, UL_X, UL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - } - - uiSpawnAddTimer = TIMER_SPAWN_ADD; - } else uiSpawnAddTimer -= diff; - - // Is the phase over? - if (uiHeartPhaseTimer <= diff) - { - DoScriptText(SAY_HEART_CLOSED, me); - SetPhaseOne(); - } - else - uiHeartPhaseTimer -= diff; - } - } - else - { - // Adding life sparks when searing light debuff runs out if hard mode - if (searing_light_active) - { - if (uiSpawnLifeSparkTimer <= diff) - { - if (Unit *pSearingLightTarget = me->GetUnit(*me, uiSearingLightTarget)) - pSearingLightTarget->SummonCreature(NPC_LIFE_SPARK, pSearingLightTarget->GetPositionX(), pSearingLightTarget->GetPositionY(), pSearingLightTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; - searing_light_active = false; - } else uiSpawnLifeSparkTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - if (gravity_bomb_active) - { - if (uiGravityBombAuraTimer <= diff) - { - if (Unit *pGravityBombTarget = me->GetUnit(*me, uiGravityBombTarget)) - { - pGravityBombTarget->RemoveAurasDueToSpell(RAID_MODE(SPELL_GRAVITY_BOMB_10,SPELL_GRAVITY_BOMB_25)); - if (hardMode) - { - //Remains spawned for 3 minutes - pGravityBombTarget->SummonCreature(NPC_VOID_ZONE, pGravityBombTarget->GetPositionX(), pGravityBombTarget->GetPositionY(), pGravityBombTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); - } - } - - gravity_bomb_active = false; - uiGravityBombAuraTimer = TIMER_GRAVITY_BOMB_AURA; - //gravityBomb(); - } else uiGravityBombAuraTimer -= diff; - } - - //Enrage stuff - if (!enraged) - if (uiEnrageTimer <= diff) - { - DoScriptText(SAY_BERSERK, me); - DoCast(me, SPELL_ENRAGE); - enraged = true; - } else uiEnrageTimer -= diff; - } - - void exposeHeart() - { - //Make untargetable - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - - //Summon the heart npc - me->SummonCreature(NPC_XT002_HEART, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 7, 0, TEMPSUMMON_TIMED_DESPAWN, TIMER_HEART_PHASE); - - // Start "end of phase 2 timer" - uiHeartPhaseTimer = TIMER_HEART_PHASE; - - //Phase 2 has offically started - phase = 2; - heart_exposed++; - - //Reset the add spawning timer - uiSpawnAddTimer = TIMER_SPAWN_ADD; - - DoScriptText(SAY_HEART_OPENED, me); - } - - void SetPhaseOne() - { - uiSearingLightTimer = TIMER_SEARING_LIGHT / 2; - uiGravityBombTimer = TIMER_GRAVITY_BOMB; - uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX); - uiSpawnAddTimer = TIMER_SPAWN_ADD; - - if (!hardMode) - me->ModifyHealth(-((int32)transferHealth)); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - phase = 1; - } - - // TODO: put in comment and kept for reference. The spell should be fixed properly in spell system, if necessary. - ////Have to do this the custom way since the original spell messes up player movement - //void gravityBomb() - //{ - // uint32 maxDamage = RAID_MODE(GRAVITY_BOMB_DMG_MAX_10, GRAVITY_BOMB_DMG_MAX_25); - // uint32 minDamage = RAID_MODE(GRAVITY_BOMB_DMG_MIN_10, GRAVITY_BOMB_DMG_MIN_25); - // uint16 range = GRAVITY_BOMB_RADIUS; - // Map* pMap = me->GetMap(); - // if (pMap && pMap->IsDungeon()) - // { - // Map::PlayerList const &PlayerList = pMap->GetPlayers(); - // for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - // { - // //If a player is within the range of the spell - // if (i->getSource() && i->getSource()->GetDistance2d(pGravityBombTarget) <= range) - // { - // //Deal damage to the victim - // int32 damage = urand(minDamage, maxDamage); - // i->getSource()->ModifyHealth(-damage); - // me->SendSpellNonMeleeDamageLog(i->getSource(), SPELL_GRAVITY_BOMB_AURA_10, damage, SPELL_SCHOOL_MASK_SHADOW, 0, 0, false, 0); - - // //Replacing the tractor beam effect - // i->getSource()->JumpTo(pGravityBombTarget, 5); - // } - // } - // } - //} -}; - -CreatureAI* GetAI_boss_xt002(Creature* pCreature) -{ - return new boss_xt002_AI(pCreature); -} - -/*------------------------------------------------------- - * - * XT-002 HEART - * - *///---------------------------------------------------- -struct mob_xt002_heartAI : public ScriptedAI -{ - mob_xt002_heartAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_EXPOSED_HEART); - } - - ScriptedInstance* m_pInstance; - - void JustDied(Unit * /*victim*/) - { - if (m_pInstance) - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - if (pXT002->AI()) - pXT002->AI()->DoAction(ACTION_ENTER_HARD_MODE); - - //removes the aura - me->RemoveAurasDueToSpell(SPELL_EXPOSED_HEART); - } - - void DamageTaken(Unit * /*pDone*/, uint32 &damage) - { - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - if (pXT002->AI()) - { - uint32 health = me->GetHealth(); - health -= damage; - if (health < 0) - health = 0; - - pXT002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetMaxHealth() - health); - } - } -}; - -CreatureAI* GetAI_mob_xt002_heart(Creature* pCreature) -{ - return new mob_xt002_heartAI(pCreature); -} - -/*------------------------------------------------------- - * - * XS-013 SCRAPBOT - * - *///---------------------------------------------------- -struct mob_scrapbotAI : public ScriptedAI -{ - mob_scrapbotAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = me->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - me->GetMotionMaster()->MoveChase(pXT002); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - { - if (me->GetDistance2d(pXT002) <= 0.5) - { - // TODO Send raid message - - // Increase health with 1 percent - pXT002->ModifyHealth(pXT002->GetMaxHealth() * 0.01); - - // Despawns the scrapbot - me->ForcedDespawn(); - } - } - } -}; - -CreatureAI* GetAI_mob_scrapbot(Creature* pCreature) -{ - return new mob_scrapbotAI(pCreature); -} - -/*------------------------------------------------------- - * - * XM-024 PUMMELLER - * - *///---------------------------------------------------- -struct mob_pummellerAI : public ScriptedAI -{ - mob_pummellerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - int32 uiArcingSmashTimer; - int32 uiTrampleTimer; - int32 uiUppercutTimer; - - void Reset() - { - uiArcingSmashTimer = TIMER_ARCING_SMASH; - uiTrampleTimer = TIMER_TRAMPLE; - uiUppercutTimer = TIMER_UPPERCUT; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->IsWithinMeleeRange(me->getVictim())) - { - if (uiArcingSmashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCING_SMASH); - uiArcingSmashTimer = TIMER_ARCING_SMASH; - } else uiArcingSmashTimer -= diff; - - if (uiTrampleTimer <= diff) - { - DoCast(me->getVictim(), SPELL_TRAMPLE); - uiTrampleTimer = TIMER_TRAMPLE; - } else uiTrampleTimer -= diff; - - if (uiUppercutTimer <= diff) - { - DoCast(me->getVictim(), SPELL_UPPERCUT); - uiUppercutTimer = TIMER_UPPERCUT; - } else uiUppercutTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_pummeller(Creature* pCreature) -{ - return new mob_pummellerAI(pCreature); -} - -/*------------------------------------------------------- - * - * XE-321 BOOMBOT - * - *///---------------------------------------------------- -struct mob_boombotAI : public ScriptedAI -{ - mob_boombotAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - me->GetMotionMaster()->MoveChase(pXT002); - } - - void JustDied(Unit * /*killer*/) - { - DoCast(SPELL_BOOM); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - { - if (me->GetDistance2d(pXT002) <= 0.5) - { - //Explosion - DoCast(me, SPELL_BOOM); - - //Despawns the boombot - me->ForcedDespawn(); - } - } - } -}; - -CreatureAI* GetAI_mob_boombot(Creature* pCreature) -{ - return new mob_boombotAI(pCreature); -} - -/*------------------------------------------------------- - * - * VOID ZONE - * - *///---------------------------------------------------- -struct mob_void_zoneAI : public ScriptedAI -{ - mob_void_zoneAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - } - - ScriptedInstance* m_pInstance; - uint32 uiVoidZoneTimer; - - void Reset() - { - uiVoidZoneTimer = TIMER_VOID_ZONE; - } - - void UpdateAI(const uint32 diff) - { - if (uiVoidZoneTimer <= diff) - { - //voidZone(); - uiVoidZoneTimer = TIMER_VOID_ZONE; - } else uiVoidZoneTimer -= diff; - } - - // TODO: put in comment and kept for reference. The spell should be fixed properly in spell system, if necessary. - //void voidZone() - //{ - // Map* pMap = me->GetMap(); - // if (pMap && pMap->IsDungeon()) - // { - // Map::PlayerList const &PlayerList = pMap->GetPlayers(); - // for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - // { - // // If a player is within the range of the spell - // if (i->getSource() && i->getSource()->GetDistance2d(me) <= 16) - // { - // // Deal damage to the victim - // int32 damage = RAID_MODE(VOID_ZONE_DMG_10, VOID_ZONE_DMG_25); - // me->DealDamage(i->getSource(), damage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); - // } - // } - // } - //} -}; - -CreatureAI* GetAI_mob_void_zone(Creature* pCreature) -{ - return new mob_void_zoneAI(pCreature); -} - -/*------------------------------------------------------- - * - * LIFE SPARK - * - *///---------------------------------------------------- -struct mob_life_sparkAI : public ScriptedAI -{ - mob_life_sparkAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - uint32 uiShockTimer; - - void Reset() - { - DoCast(me, RAID_MODE(SPELL_STATIC_CHARGED_10, SPELL_STATIC_CHARGED_25)); - uiShockTimer = 0; // first one is immediate. - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiShockTimer <= diff) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - DoCast(me->getVictim(), SPELL_SHOCK); - uiShockTimer = TIMER_SHOCK; - } - } - else uiShockTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_life_spark(Creature* pCreature) -{ - return new mob_life_sparkAI(pCreature); -} - -void AddSC_boss_xt002() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_xt002"; - newscript->GetAI = &GetAI_boss_xt002; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_xt002_heart"; - newscript->GetAI = &GetAI_mob_xt002_heart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_scrapbot"; - newscript->GetAI = &GetAI_mob_scrapbot; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_pummeller"; - newscript->GetAI = &GetAI_mob_pummeller; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_boombot"; - newscript->GetAI = &GetAI_mob_boombot; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_void_zone"; - newscript->GetAI = &GetAI_mob_void_zone; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_life_spark"; - newscript->GetAI = &GetAI_mob_life_spark; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp b/src/server/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp deleted file mode 100644 index 8f42f289204..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Sara_Yells -{ - SAY_SARA_PREFIGHT_1 = -1603310, - SAY_SARA_PREFIGHT_2 = -1603311, - SAY_SARA_AGGRO_1 = -1603312, - SAY_SARA_AGGRO_2 = -1603313, - SAY_SARA_AGGRO_3 = -1603314, - SAY_SARA_SLAY_1 = -1603315, - SAY_SARA_SLAY_2 = -1603316, - WHISP_SARA_INSANITY = -1603317, - SAY_SARA_PHASE2_1 = -1603318, - SAY_SARA_PHASE2_2 = -1603319, -}; - -enum YoggSaron_Yells -{ - SAY_PHASE2_1 = -1603330, - SAY_PHASE2_2 = -1603331, - SAY_PHASE2_3 = -1603332, - SAY_PHASE2_4 = -1603333, - SAY_PHASE2_5 = -1603334, - SAY_PHASE3 = -1603335, - SAY_VISION = -1603336, - SAY_SLAY_1 = -1603337, - SAY_SLAY_2 = -1603338, - WHISP_INSANITY_1 = -1603339, - WHISP_INSANITY_2 = -1603340, - SAY_DEATH = -1603341, -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 21001, -}; diff --git a/src/server/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp b/src/server/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp deleted file mode 100644 index 692dbf72473..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum eGameObjects -{ - GO_KOLOGARN_CHEST_HERO = 195047, - GO_KOLOGARN_CHEST = 195046, - GO_THORIM_CHEST_HERO = 194315, - GO_THORIM_CHEST = 194314, - GO_HODIR_CHEST_HERO = 194308, - GO_HODIR_CHEST = 194307, - GO_FREYA_CHEST_HERO = 194325, - GO_FREYA_CHEST = 194324, - GO_LEVIATHAN_DOOR = 194905, - GO_LEVIATHAN_GATE = 194630 -}; - -struct instance_ulduar : public ScriptedInstance -{ - instance_ulduar(Map* pMap) : ScriptedInstance(pMap) { Initialize(); }; - - uint32 uiEncounter[MAX_ENCOUNTER]; - std::string m_strInstData; - uint8 flag; - - uint64 uiLeviathanGUID; - uint64 uiIgnisGUID; - uint64 uiRazorscaleGUID; - uint64 uiXT002GUID; - uint64 uiAssemblyGUIDs[3]; - uint64 uiKologarnGUID; - uint64 uiAuriayaGUID; - uint64 uiMimironGUID; - uint64 uiHodirGUID; - uint64 uiThorimGUID; - uint64 uiFreyaGUID; - uint64 uiVezaxGUID; - uint64 uiYoggSaronGUID; - uint64 uiAlgalonGUID; - uint64 uiLeviathanDoor[7]; - uint64 uiLeviathanGateGUID; - - uint64 uiKologarnChestGUID; - uint64 uiThorimChestGUID; - uint64 uiHodirChestGUID; - uint64 uiFreyaChestGUID; - - void Initialize() - { - uiLeviathanGUID = 0; - uiIgnisGUID = 0; - uiRazorscaleGUID = 0; - uiXT002GUID = 0; - uiKologarnGUID = 0; - uiAuriayaGUID = 0; - uiMimironGUID = 0; - uiHodirGUID = 0; - uiThorimGUID = 0; - uiFreyaGUID = 0; - uiVezaxGUID = 0; - uiYoggSaronGUID = 0; - uiAlgalonGUID = 0; - uiKologarnChestGUID = 0; - uiKologarnChestGUID = 0; - uiHodirChestGUID = 0; - uiFreyaChestGUID = 0; - uiLeviathanGateGUID = 0; - flag = 0; - - memset(&uiEncounter, 0, sizeof(uiEncounter)); - memset(&uiAssemblyGUIDs, 0, sizeof(uiAssemblyGUIDs)); - memset(&uiLeviathanDoor, 0, sizeof(uiLeviathanDoor)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (uiEncounter[i] == IN_PROGRESS) - return true; - } - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_LEVIATHAN: - uiLeviathanGUID = pCreature->GetGUID(); - break; - case NPC_IGNIS: - uiIgnisGUID = pCreature->GetGUID(); - break; - case NPC_RAZORSCALE: - uiRazorscaleGUID = pCreature->GetGUID(); - break; - case NPC_XT002: - uiXT002GUID = pCreature->GetGUID(); - break; - - // Assembly of Iron - case NPC_STEELBREAKER: - uiAssemblyGUIDs[0] = pCreature->GetGUID(); - break; - case NPC_MOLGEIM: - uiAssemblyGUIDs[1] = pCreature->GetGUID(); - break; - case NPC_BRUNDIR: - uiAssemblyGUIDs[2] = pCreature->GetGUID(); - break; - - case NPC_KOLOGARN: - uiKologarnGUID = pCreature->GetGUID(); - break; - case NPC_AURIAYA: - uiAuriayaGUID = pCreature->GetGUID(); - break; - case NPC_MIMIRON: - uiMimironGUID = pCreature->GetGUID(); - break; - case NPC_HODIR: - uiHodirGUID = pCreature->GetGUID(); - break; - case NPC_THORIM: - uiThorimGUID = pCreature->GetGUID(); - break; - case NPC_FREYA: - uiFreyaGUID = pCreature->GetGUID(); - break; - case NPC_VEZAX: - uiVezaxGUID = pCreature->GetGUID(); - break; - case NPC_YOGGSARON: - uiYoggSaronGUID = pCreature->GetGUID(); - break; - case NPC_ALGALON: - uiAlgalonGUID = pCreature->GetGUID(); - break; - } - - } - - void OnGameObjectCreate(GameObject* pGO, bool add) - { - switch(pGO->GetEntry()) - { - case GO_KOLOGARN_CHEST_HERO: - case GO_KOLOGARN_CHEST: - uiKologarnChestGUID = add ? pGO->GetGUID() : NULL; - break; - case GO_THORIM_CHEST_HERO: - case GO_THORIM_CHEST: - uiThorimChestGUID = add ? pGO->GetGUID() : NULL; - break; - case GO_HODIR_CHEST_HERO: - case GO_HODIR_CHEST: - uiHodirChestGUID = add ? pGO->GetGUID() : NULL; - break; - case GO_FREYA_CHEST_HERO: - case GO_FREYA_CHEST: - uiFreyaChestGUID = add ? pGO->GetGUID() : NULL; - break; - case GO_LEVIATHAN_DOOR: - uiLeviathanDoor[flag] = pGO->GetGUID(); - HandleGameObject(NULL, true, pGO); - flag++; - if (flag == 7) - flag =0; - break; - case GO_LEVIATHAN_GATE: - uiLeviathanGateGUID = pGO->GetGUID(); - HandleGameObject(NULL, false, pGO); - break; - } - } - - void ProcessEvent(GameObject* pGO, uint32 uiEventId) - { - // Flame Leviathan's Tower Event triggers - Creature* pFlameLeviathan = instance->GetCreature(NPC_LEVIATHAN); - if (pFlameLeviathan && pFlameLeviathan->isAlive()) //No leviathan, no event triggering ;) - switch(uiEventId) - { - case EVENT_TOWER_OF_STORM_DESTROYED: - pFlameLeviathan->AI()->DoAction(1); - break; - case EVENT_TOWER_OF_FROST_DESTROYED: - pFlameLeviathan->AI()->DoAction(2); - break; - case EVENT_TOWER_OF_FLAMES_DESTROYED: - pFlameLeviathan->AI()->DoAction(3); - break; - case EVENT_TOWER_OF_NATURE_DESTROYED: - pFlameLeviathan->AI()->DoAction(4); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - if (type != TYPE_COLOSSUS) - uiEncounter[type] = data; - - switch(type) - { - /*case TYPE_IGNIS: - case TYPE_RAZORSCALE: - case TYPE_XT002: - case TYPE_ASSEMBLY: - case TYPE_AURIAYA: - case TYPE_MIMIRON: - case TYPE_VEZAX: - case TYPE_YOGGSARON: - break;*/ - case TYPE_LEVIATHAN: - if (data == IN_PROGRESS) - { - for (uint8 uiI = 0; uiI < 7; uiI++) - HandleGameObject(uiLeviathanDoor[uiI],false); - } - else - { - for (uint8 uiI = 0; uiI < 7; uiI++) - HandleGameObject(uiLeviathanDoor[uiI],true); - } - break; - case TYPE_KOLOGARN: - if (data == DONE) - if (GameObject* pGO = instance->GetGameObject(uiKologarnChestGUID)) - pGO->SetRespawnTime(pGO->GetRespawnDelay()); - break; - case TYPE_HODIR: - if (data == DONE) - if (GameObject* pGO = instance->GetGameObject(uiHodirChestGUID)) - pGO->SetRespawnTime(pGO->GetRespawnDelay()); - break; - case TYPE_THORIM: - if (data == DONE) - if (GameObject* pGO = instance->GetGameObject(uiThorimChestGUID)) - pGO->SetRespawnTime(pGO->GetRespawnDelay()); - break; - case TYPE_FREYA: - if (data == DONE) - if (GameObject* pGO = instance->GetGameObject(uiFreyaChestGUID)) - pGO->SetRespawnTime(pGO->GetRespawnDelay()); - break; - case TYPE_COLOSSUS: - if (data == 2) - { - if (Creature* pBoss = instance->GetCreature(uiLeviathanGUID)) - pBoss->AI()->DoAction(10); - if (GameObject* pGate = instance->GetGameObject(uiLeviathanGateGUID)) - pGate->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - } - break; - default: - break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - saveStream << uiEncounter[i] << " "; - - m_strInstData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case TYPE_LEVIATHAN: return uiLeviathanGUID; - case TYPE_IGNIS: return uiIgnisGUID; - case TYPE_RAZORSCALE: return uiRazorscaleGUID; - case TYPE_XT002: return uiXT002GUID; - case TYPE_KOLOGARN: return uiKologarnGUID; - case TYPE_AURIAYA: return uiAuriayaGUID; - case TYPE_MIMIRON: return uiMimironGUID; - case TYPE_HODIR: return uiMimironGUID; - case TYPE_THORIM: return uiThorimGUID; - case TYPE_FREYA: return uiFreyaGUID; - case TYPE_VEZAX: return uiVezaxGUID; - case TYPE_YOGGSARON: return uiYoggSaronGUID; - case TYPE_ALGALON: return uiAlgalonGUID; - - // Assembly of Iron - case DATA_STEELBREAKER: return uiAssemblyGUIDs[0]; - case DATA_MOLGEIM: return uiAssemblyGUIDs[1]; - case DATA_BRUNDIR: return uiAssemblyGUIDs[2]; - } - - return 0; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_LEVIATHAN: - case TYPE_IGNIS: - case TYPE_RAZORSCALE: - case TYPE_XT002: - case TYPE_ASSEMBLY: - case TYPE_KOLOGARN: - case TYPE_AURIAYA: - case TYPE_MIMIRON: - case TYPE_HODIR: - case TYPE_THORIM: - case TYPE_FREYA: - case TYPE_VEZAX: - case TYPE_YOGGSARON: - case TYPE_ALGALON: - case TYPE_COLOSSUS: - return uiEncounter[type]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "U U " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2] << " " << uiEncounter[3] - << uiEncounter[4] << " " << uiEncounter[5] << " " << uiEncounter[6] << " " << uiEncounter[7] - << uiEncounter[8] << " " << uiEncounter[9] << " " << uiEncounter[10] << " " << uiEncounter[11] - << uiEncounter[12] << " " << uiEncounter[13] << " " << uiEncounter[14]; - - m_strInstData = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return m_strInstData; - } - - void Load(const char* strIn) - { - if (!strIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(strIn); - - char dataHead1, dataHead2; - uint32 data0, data1, data2, data3, data4, data5, data6, - data7, data8, data9, data10, data11, data12, data13, data14; - - std::istringstream loadStream(strIn); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6 - >> data7 >> data8 >> data9 >> data10 >> data11 >> data12 >> data13 >> data14; - - if (dataHead1 == 'U' && dataHead2 == 'U') - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - loadStream >> uiEncounter[i]; - - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - } - } - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_ulduar(Map* pMap) -{ - return new instance_ulduar(pMap); -} - -void AddSC_instance_ulduar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_ulduar"; - newscript->GetInstanceData = &GetInstanceData_instance_ulduar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/ulduar/ulduar/ulduar.h b/src/server/scripts/northrend/ulduar/ulduar/ulduar.h deleted file mode 100644 index cb11bcb579c..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/ulduar.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_ULDUAR_H -#define DEF_ULDUAR_H - -enum eTypes -{ - MAX_ENCOUNTER = 15, - - TYPE_LEVIATHAN = 0, - TYPE_IGNIS = 1, - TYPE_RAZORSCALE = 2, - TYPE_XT002 = 3, - TYPE_ASSEMBLY = 4, - TYPE_KOLOGARN = 5, - TYPE_AURIAYA = 6, - TYPE_MIMIRON = 7, - TYPE_HODIR = 8, - TYPE_THORIM = 9, - TYPE_FREYA = 10, - TYPE_VEZAX = 11, - TYPE_YOGGSARON = 12, - TYPE_ALGALON = 13, - TYPE_COLOSSUS = 14, - - DATA_STEELBREAKER = 20, - DATA_MOLGEIM = 21, - DATA_BRUNDIR = 22, - DATA_RUNEMASTER_MOLGEIM = 23, - DATA_STORMCALLER_BRUNDIR = 24, - - NPC_LEVIATHAN = 33113, - NPC_IGNIS = 33118, - NPC_RAZORSCALE = 33186, - NPC_XT002 = 33293, - NPC_STEELBREAKER = 32867, - NPC_MOLGEIM = 32927, - NPC_BRUNDIR = 32857, - NPC_KOLOGARN = 32930, - NPC_AURIAYA = 33515, - NPC_MIMIRON = 33350, - NPC_HODIR = 32845, - NPC_THORIM = 32865, - NPC_FREYA = 32906, - NPC_VEZAX = 33271, - NPC_YOGGSARON = 33288, - NPC_ALGALON = 32871, - - EVENT_TOWER_OF_STORM_DESTROYED = 21031, - EVENT_TOWER_OF_FROST_DESTROYED = 21032, - EVENT_TOWER_OF_FLAMES_DESTROYED = 21033, - EVENT_TOWER_OF_NATURE_DESTROYED = 21030 -}; - -#endif diff --git a/src/server/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp b/src/server/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp deleted file mode 100644 index 44f9e86b69c..00000000000 --- a/src/server/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "ScriptedPch.h" -#include "ulduar.h" - -/* -The teleporter appears to be active and stable. - -- Expedition Base Camp -- Formation Grounds -- Colossal Forge -- Scrapyard -- Antechamber of Ulduar -- Shattered Walkway -- Conservatory of Life -*/ - -#define BASE_CAMP 200 -#define GROUNDS 201 -#define FORGE 202 -#define SCRAPYARD 203 -#define ANTECHAMBER 204 -#define WALKWAY 205 -#define CONSERVATORY 206 - -bool GoHello_ulduar_teleporter(Player *pPlayer, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - if (!pInstance) return true; - - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Expedition Base Camp", GOSSIP_SENDER_MAIN, BASE_CAMP); - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Formation Grounds", GOSSIP_SENDER_MAIN, GROUNDS); - if (pInstance->GetData(TYPE_LEVIATHAN) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Colossal Forge", GOSSIP_SENDER_MAIN, FORGE); - if (pInstance->GetData(TYPE_XT002) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Scrapyard", GOSSIP_SENDER_MAIN, SCRAPYARD); - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Antechamber of Ulduar", GOSSIP_SENDER_MAIN, ANTECHAMBER); - if (pInstance->GetData(TYPE_KOLOGARN) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Shattered Walkway", GOSSIP_SENDER_MAIN, WALKWAY); - if (pInstance->GetData(TYPE_AURIAYA) == DONE) - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Conservatory of Life", GOSSIP_SENDER_MAIN, CONSERVATORY); - } - } - } - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pGO->GetGUID()); - - return true; -} - -bool GOSelect_ulduar_teleporter(Player *pPlayer, GameObject * /*pGO*/, uint32 sender, uint32 action) -{ - if (sender != GOSSIP_SENDER_MAIN) return true; - if (!pPlayer->getAttackers().empty()) return true; - - switch(action) - { - case BASE_CAMP: - pPlayer->TeleportTo(603, -706.122, -92.6024, 429.876, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case GROUNDS: - pPlayer->TeleportTo(603, 131.248, -35.3802, 409.804, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case FORGE: - pPlayer->TeleportTo(603, 553.233, -12.3247, 409.679, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case SCRAPYARD: - pPlayer->TeleportTo(603, 926.292, -11.4635, 418.595, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case ANTECHAMBER: - pPlayer->TeleportTo(603, 1498.09, -24.246, 420.967, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case WALKWAY: - pPlayer->TeleportTo(603, 1859.45, -24.1, 448.9, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case CONSERVATORY: - pPlayer->TeleportTo(603, 2086.27, -24.3134, 421.239, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - } - - return true; -} - -void AddSC_ulduar_teleporter() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "ulduar_teleporter"; - newscript->pGOHello = &GoHello_ulduar_teleporter; - newscript->pGOSelect = &GOSelect_ulduar_teleporter; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp deleted file mode 100644 index 77f824c48d5..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ingvar_The_Plunderer -SD%Complete: 95 -SDComment: Some Problems with Annhylde Movement, Blizzlike Timers -SDCategory: Udgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum Yells -{ - //Yells Ingvar - YELL_AGGRO_1 = -1574005, - YELL_AGGRO_2 = -1574006, - - YELL_DEAD_1 = -1574007, - YELL_DEAD_2 = -1574008, - - YELL_KILL_1 = -1574009, - YELL_KILL_2 = -1574010, -}; - -enum Creatures -{ - MOB_INGVAR_HUMAN = 23954, - MOB_ANNHYLDE_THE_CALLER = 24068, - MOB_INGVAR_UNDEAD = 23980, -}; - -enum Spells -{ - //Ingvar Spells human form - SPELL_CLEAVE = 42724, - SPELL_SMASH = 42669, - H_SPELL_SMASH = 59706, - SPELL_STAGGERING_ROAR = 42708, - H_SPELL_STAGGERING_ROAR = 59708, - SPELL_ENRAGE = 42705, - H_SPELL_ENRAGE = 59707, - - SPELL_INGVAR_FEIGN_DEATH = 42795, - SPELL_SUMMON_BANSHEE = 42912, - SPELL_SCOURG_RESURRECTION = 42863, // Spawn resurrect effect around Ingvar - - //Ingvar Spells undead form - SPELL_DARK_SMASH = 42723, - SPELL_DREADFUL_ROAR = 42729, - H_SPELL_DREADFUL_ROAR = 59734, - SPELL_WOE_STRIKE = 42730, - H_SPELL_WOE_STRIKE = 59735, - - ENTRY_THROW_TARGET = 23996, - SPELL_SHADOW_AXE_SUMMON = 42749 -}; - -struct boss_ingvar_the_plundererAI : public ScriptedAI -{ - boss_ingvar_the_plundererAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bIsUndead; - bool bEventInProgress; - - uint32 uiCleaveTimer; - uint32 uiSmashTimer; - uint32 uiEnrageTimer; - uint32 uiRoarTimer; - uint32 uiSpawnResTimer; - - void Reset() - { - if (bIsUndead) - me->UpdateEntry(MOB_INGVAR_HUMAN); - - bIsUndead = false; - bEventInProgress = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - - uiCleaveTimer = 2000; - uiSmashTimer = 5000; - uiEnrageTimer = 10000; - uiRoarTimer = 15000; - - uiSpawnResTimer = 3000; - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, NOT_STARTED); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth() && !bIsUndead) - { - //DoCast(me, SPELL_INGVAR_FEIGN_DEATH, true); // Dont work ??? - // visuel hack - me->SetHealth(0); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - // visuel hack end - - bEventInProgress = true; - bIsUndead = true; - - DoScriptText(YELL_DEAD_1,me); - } - - if (bEventInProgress) - { - damage = 0; - } - } - - void StartZombiePhase() - { - bIsUndead = true; - bEventInProgress = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->UpdateEntry(MOB_INGVAR_UNDEAD); - me->SetInCombatWith(me->getVictim()); - me->GetMotionMaster()->MoveChase(me->getVictim()); - - DoScriptText(YELL_AGGRO_2,me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO_1,me); - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(YELL_DEAD_2,me); - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - if (bIsUndead) - DoScriptText(YELL_KILL_1,me); - else - DoScriptText(YELL_KILL_2,me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (bEventInProgress) - { - if (uiSpawnResTimer) - if (uiSpawnResTimer <= diff) - { - DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position - // DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ? - uiSpawnResTimer = 0; - } else uiSpawnResTimer -= diff; - - return; - } - - if (uiCleaveTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me->getVictim(), SPELL_WOE_STRIKE); - else - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = rand()%5000 + 2000; - } - } else uiCleaveTimer -= diff; - - if (uiSmashTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me->getVictim(), SPELL_DARK_SMASH); - else - DoCast(me->getVictim(), SPELL_SMASH); - uiSmashTimer = 10000; - } - } else uiSmashTimer -= diff; - - if (!bIsUndead) - { - if (uiEnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - uiEnrageTimer = 10000; - } else uiEnrageTimer -= diff; - } else // In Undead form used to summon weapon - { - if (uiEnrageTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - // Spawn target for Axe - Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); - if (pTarget) - { - me->SummonCreature(ENTRY_THROW_TARGET,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,2000); - - DoCast(me, SPELL_SHADOW_AXE_SUMMON); - } - uiEnrageTimer = 30000; - } - } else uiEnrageTimer -= diff; - } - - if (uiRoarTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me, SPELL_DREADFUL_ROAR); - else - DoCast(me, SPELL_STAGGERING_ROAR); - uiRoarTimer = 10000; - } - } else uiRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ingvar_the_plunderer(Creature* pCreature) -{ - return new boss_ingvar_the_plundererAI(pCreature); -} - -enum eSpells -{ -//we don't have that text in db so comment it until we get this text -// YELL_RESSURECT = -1574025, - -//Spells for Annhylde - SPELL_SCOURG_RESURRECTION_HEAL = 42704, //Heal Max + DummyAura - SPELL_SCOURG_RESURRECTION_BEAM = 42857, //Channeling Beam of Annhylde - SPELL_SCOURG_RESURRECTION_DUMMY = 42862, //Some Emote Dummy? - SPELL_INGVAR_TRANSFORM = 42796 -}; - -struct mob_annhylde_the_callerAI : public ScriptedAI -{ - mob_annhylde_the_callerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - float x,y,z; - ScriptedInstance* pInstance; - uint32 uiResurectTimer; - uint32 uiResurectPhase; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_HOVER); - me->SetSpeed(MOVE_SWIM , 1.0f); - me->SetSpeed(MOVE_RUN , 1.0f); - me->SetSpeed(MOVE_WALK , 1.0f); - //me->SetSpeed(MOVE_FLIGHT , 1.0f); - - me->GetPosition(x,y,z); - DoTeleportTo(x+1,y,z+30); - - Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - me->GetMotionMaster()->MovePoint(1,x,y,z+15); - -// DoScriptText(YELL_RESSURECT,me); - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - Unit* ingvar = Unit::GetUnit((*me), pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - switch (id) - { - case 1: - ingvar->RemoveAura(SPELL_SUMMON_BANSHEE); - ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_DUMMY,true); - DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); - uiResurectTimer = 8000; - uiResurectPhase = 1; - break; - case 2: - me->SetVisibility(VISIBILITY_OFF); - me->DealDamage(me,me->GetHealth()); - me->RemoveCorpse(); - break; - } - } - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit * /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (uiResurectTimer) - if (uiResurectTimer <= diff) - { - if (uiResurectPhase == 1) - { - Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - ingvar->SetStandState(UNIT_STAND_STATE_STAND); - ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_HEAL,false); - } - uiResurectTimer = 3000; - uiResurectPhase = 2; - } - else if (uiResurectPhase == 2) - { - if (Creature* ingvar = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0)) - { - ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); - - if (boss_ingvar_the_plundererAI* pAI = CAST_AI(boss_ingvar_the_plundererAI, ingvar->AI())) - pAI->StartZombiePhase(); - - me->GetMotionMaster()->MovePoint(2,x+1,y,z+30); - ++uiResurectPhase; - uiResurectTimer = 0; - } - } - - } else uiResurectTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_annhylde_the_caller(Creature* pCreature) -{ - return new mob_annhylde_the_callerAI (pCreature); -} - -enum eShadowAxe -{ - SPELL_SHADOW_AXE_DAMAGE = 42750, - H_SPELL_SHADOW_AXE_DAMAGE = 59719 -}; - -struct mob_ingvar_throw_dummyAI : public ScriptedAI -{ - mob_ingvar_throw_dummyAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 uiDespawnTimer; - - void Reset() - { - Unit *pTarget = me->FindNearestCreature(ENTRY_THROW_TARGET,50); - if (pTarget) - { - DoCast(me, SPELL_SHADOW_AXE_DAMAGE); - float x,y,z; - pTarget->GetPosition(x,y,z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - } - uiDespawnTimer = 7000; - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit * /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (uiDespawnTimer <= diff) - { - me->DealDamage(me,me->GetHealth()); - me->RemoveCorpse(); - uiDespawnTimer = 0; - } else uiDespawnTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_ingvar_throw_dummy(Creature* pCreature) -{ - return new mob_ingvar_throw_dummyAI (pCreature); -} - -void AddSC_boss_ingvar_the_plunderer() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ingvar_the_plunderer"; - newscript->GetAI = &GetAI_boss_ingvar_the_plunderer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_annhylde_the_caller"; - newscript->GetAI = &GetAI_mob_annhylde_the_caller; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ingvar_throw_dummy"; - newscript->GetAI = &GetAI_mob_ingvar_throw_dummy; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp deleted file mode 100644 index d69f0eee846..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Prince_Keleseth -SD%Complete: 90 -SDComment: Needs Prince Movements, Needs adjustments to blizzlike timers, Needs Shadowbolt castbar, Needs right Ressurect Visual, Needs Some Heroic Spells -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum eEnums -{ - ACHIEVEMENT_ON_THE_ROCKS = 1919, - - SPELL_SHADOWBOLT = 43667, - SPELL_SHADOWBOLT_HEROIC = 59389, - SPELL_FROST_TOMB = 48400, - SPELL_FROST_TOMB_SUMMON = 42714, - SPELL_DECREPIFY = 42702, - SPELL_SCOURGE_RESSURRECTION = 42704, - CREATURE_FROSTTOMB = 23965, - CREATURE_SKELETON = 23970, - - SAY_AGGRO = -1574000, - SAY_FROST_TOMB = -1574001, - SAY_SKELETONS = -1574002, - SAY_KILL = -1574003, - SAY_DEATH = -1574004 -}; - -#define SKELETONSPAWN_Z 42.8668 - -float SkeletonSpawnPoint[5][5]= -{ - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, -}; - -float AttackLoc[3]={197.636, 194.046, 40.8164}; - -bool ShatterFrostTomb; // needed for achievement: On The Rocks(1919) - -struct mob_frost_tombAI : public ScriptedAI -{ - mob_frost_tombAI(Creature *c) : ScriptedAI(c) - { - FrostTombGUID = 0; - } - - uint64 FrostTombGUID; - - void SetPrisoner(Unit* uPrisoner) - { - FrostTombGUID = uPrisoner->GetGUID(); - } - - void Reset(){ FrostTombGUID = 0; } - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void JustDied(Unit *killer) - { - if (killer->GetGUID() != me->GetGUID()) - ShatterFrostTomb = true; - - if (FrostTombGUID) - { - Unit* FrostTomb = Unit::GetUnit((*me),FrostTombGUID); - if (FrostTomb) - FrostTomb->RemoveAurasDueToSpell(SPELL_FROST_TOMB); - } - } - - void UpdateAI(const uint32 /*diff*/) - { - Unit* temp = Unit::GetUnit((*me),FrostTombGUID); - if ((temp && temp->isAlive() && !temp->HasAura(SPELL_FROST_TOMB)) || !temp) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } -}; - -struct boss_kelesethAI : public ScriptedAI -{ - boss_kelesethAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 FrostTombTimer; - uint32 SummonSkeletonsTimer; - uint32 RespawnSkeletonsTimer; - uint32 ShadowboltTimer; - uint64 SkeletonGUID[5]; - bool Skeletons; - bool RespawnSkeletons; - - void Reset() - { - ShadowboltTimer = 0; - Skeletons = false; - - ShatterFrostTomb = false; - - ResetTimer(); - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (IsHeroic() && !ShatterFrostTomb) - { - AchievementEntry const *AchievOnTheRocks = GetAchievementStore()->LookupEntry(ACHIEVEMENT_ON_THE_ROCKS); - if (AchievOnTheRocks) - { - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievOnTheRocks); - } - } - } - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); - } - - void ResetTimer(uint32 inc = 0) - { - SummonSkeletonsTimer = 5000 + inc; - FrostTombTimer = 28000 + inc; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowboltTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - me->CastSpell(pTarget, DUNGEON_MODE(SPELL_SHADOWBOLT, SPELL_SHADOWBOLT_HEROIC), true); - ShadowboltTimer = 10000; - } else ShadowboltTimer -= diff; - - if (!Skeletons) - if ((SummonSkeletonsTimer <= diff)) - { - Creature* Skeleton; - DoScriptText(SAY_SKELETONS, me); - for (uint8 i = 0; i < 5; ++i) - { - Skeleton = me->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1] , SKELETONSPAWN_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); - if (Skeleton) - { - Skeleton->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Skeleton->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY() , me->GetPositionZ()); - Skeleton->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Skeleton); - } - } - Skeletons = true; - } else SummonSkeletonsTimer -= diff; - - if (FrostTombTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (pTarget->isAlive()) - { - //DoCast(pTarget, SPELL_FROST_TOMB_SUMMON, true); - if (Creature *pChains = me->SummonCreature(CREATURE_FROSTTOMB, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) - { - CAST_AI(mob_frost_tombAI, pChains->AI())->SetPrisoner(pTarget); - pChains->CastSpell(pTarget, SPELL_FROST_TOMB, true); - - DoScriptText(SAY_FROST_TOMB, me); - } - } - FrostTombTimer = 15000; - } else FrostTombTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_vrykul_skeletonAI : public ScriptedAI -{ - mob_vrykul_skeletonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 Respawn_Time; - uint64 Target_Guid; - uint32 Decrepify_Timer; - - bool isDead; - - void Reset() - { - Respawn_Time = 12000; - Decrepify_Timer = urand(10000,20000); - isDead = false; - } - - void EnterCombat(Unit * /*who*/){} - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() == me->GetGUID()) - return; - - if (damage >= me->GetHealth()) - { - PretendToDie(); - damage = 0; - } - } - - void PretendToDie() - { - isDead = true; - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - }; - - void Resurrect() - { - isDead = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_SCOURGE_RESSURRECTION, true); - - if (me->getVictim()) - { - me->GetMotionMaster()->MoveChase(me->getVictim()); - me->AI()->AttackStart(me->getVictim()); - } - else - me->GetMotionMaster()->Initialize(); - }; - - void UpdateAI(const uint32 diff) - { - if (pInstance && pInstance->GetData(DATA_PRINCEKELESETH_EVENT) == IN_PROGRESS) - { - if (isDead) - { - if (Respawn_Time <= diff) - { - Resurrect(); - Respawn_Time = 12000; - } else Respawn_Time -= diff; - } - else - { - if (!UpdateVictim()) - return; - - if (Decrepify_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DECREPIFY); - Decrepify_Timer = 30000; - } else Decrepify_Timer -= diff; - - DoMeleeAttackIfReady(); - } - }else - { - if (me->isAlive()) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - } -}; - -CreatureAI* GetAI_mob_frost_tomb(Creature* pCreature) -{ - return new mob_frost_tombAI(pCreature); -} - -CreatureAI* GetAI_boss_keleseth(Creature* pCreature) -{ - return new boss_kelesethAI (pCreature); -} - -CreatureAI* GetAI_mob_vrykul_skeleton(Creature* pCreature) -{ - return new mob_vrykul_skeletonAI (pCreature); -} - -void AddSC_boss_keleseth() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_keleseth"; - newscript->GetAI = &GetAI_boss_keleseth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frost_tomb"; - newscript->GetAI = &GetAI_mob_frost_tomb; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_vrykul_skeleton"; - newscript->GetAI = &GetAI_mob_vrykul_skeleton; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp deleted file mode 100644 index 2146d37635b..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Skarvald_Dalronn -SD%Complete: 95 -SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum eEnums -{ - //signed for 24200, but used by 24200,27390 - YELL_SKARVALD_AGGRO = -1574011, - YELL_SKARVALD_DAL_DIED = -1574012, - YELL_SKARVALD_SKA_DIEDFIRST = -1574013, - YELL_SKARVALD_KILL = -1574014, - YELL_SKARVALD_DAL_DIEDFIRST = -1574015, - - //signed for 24201, but used by 24201,27389 - YELL_DALRONN_AGGRO = -1574016, - YELL_DALRONN_SKA_DIED = -1574017, - YELL_DALRONN_DAL_DIEDFIRST = -1574018, - YELL_DALRONN_KILL = -1574019, - YELL_DALRONN_SKA_DIEDFIRST = -1574020, - -//Spells of Skarvald and his Ghost - MOB_SKARVALD_THE_CONSTRUCTOR = 24200, - SPELL_CHARGE = 43651, - SPELL_STONE_STRIKE = 48583, - SPELL_SUMMON_SKARVALD_GHOST = 48613, - MOB_SKARVALD_GHOST = 27390, -//Spells of Dalronn and his Ghost - MOB_DALRONN_THE_CONTROLLER = 24201, - SPELL_SHADOW_BOLT = 43649, - H_SPELL_SHADOW_BOLT = 59575, - H_SPELL_SUMMON_SKELETONS = 52611, - SPELL_DEBILITATE = 43650, - SPELL_SUMMON_DALRONN_GHOST = 48612, - MOB_DALRONN_GHOST = 27389 -}; - -struct boss_skarvald_the_constructorAI : public ScriptedAI -{ - boss_skarvald_the_constructorAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool ghost; - uint32 Charge_Timer; - uint32 StoneStrike_Timer; - uint32 Response_Timer; - uint32 Check_Timer; - bool Dalronn_isDead; - - void Reset() - { - Charge_Timer = 5000; - StoneStrike_Timer = 10000; - Dalronn_isDead = false; - Check_Timer = 5000; - - ghost = (me->GetEntry() == MOB_SKARVALD_GHOST); - if (!ghost && pInstance) - { - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn && dalronn->isDead()) - CAST_CRE(dalronn)->Respawn(); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit * who) - { - if (!ghost && pInstance) - { - DoScriptText(YELL_SKARVALD_AGGRO,me); - - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn && dalronn->isAlive() && !dalronn->getVictim()) - dalronn->getThreatManager().addThreat(who,0.0f); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* Killer) - { - if (!ghost && pInstance) - { - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn) - { - if (dalronn->isDead()) - { - DoScriptText(YELL_SKARVALD_DAL_DIED,me); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); - } - else - { - DoScriptText(YELL_SKARVALD_SKA_DIEDFIRST,me); - - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true); - Creature* temp = me->SummonCreature(MOB_SKARVALD_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); - if (temp) - { - temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - temp->AI()->AttackStart(Killer); - } - } - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - if (!ghost) - { - DoScriptText(YELL_SKARVALD_KILL,me); - } - } - - void UpdateAI(const uint32 diff) - { - if (ghost) - { - if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (!UpdateVictim()) - return; - - if (!ghost) - { - if (Check_Timer) - if (Check_Timer <= diff) - { - Check_Timer = 5000; - Unit* dalronn = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_DALRONN) : 0); - if (dalronn && dalronn->isDead()) - { - Dalronn_isDead = true; - Response_Timer = 2000; - Check_Timer = 0; - } - } else Check_Timer -= diff; - - if (Response_Timer) - if (Dalronn_isDead) - if (Response_Timer <= diff) - { - DoScriptText(YELL_SKARVALD_DAL_DIEDFIRST,me); - - Response_Timer = 0; - } else Response_Timer -= diff; - } - - if (Charge_Timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE); - Charge_Timer = 5000+rand()%5000; - } else Charge_Timer -= diff; - - if (StoneStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STONE_STRIKE); - StoneStrike_Timer = 5000+rand()%5000; - } else StoneStrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_skarvald_the_constructor(Creature* pCreature) -{ - return new boss_skarvald_the_constructorAI (pCreature); -} - -struct boss_dalronn_the_controllerAI : public ScriptedAI -{ - boss_dalronn_the_controllerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool ghost; - uint32 ShadowBolt_Timer; - uint32 Debilitate_Timer; - uint32 Summon_Timer; - - uint32 Response_Timer; - uint32 Check_Timer; - uint32 AggroYell_Timer; - bool Skarvald_isDead; - - void Reset() - { - ShadowBolt_Timer = 1000; - Debilitate_Timer = 5000; - Summon_Timer = 10000; - Check_Timer = 5000; - Skarvald_isDead = false; - AggroYell_Timer = 0; - - ghost = me->GetEntry() == MOB_DALRONN_GHOST; - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald && skarvald->isDead()) - CAST_CRE(skarvald)->Respawn(); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit * who) - { - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald && skarvald->isAlive() && !skarvald->getVictim()) - skarvald->getThreatManager().addThreat(who,0.0f); - - AggroYell_Timer = 5000; - - if (pInstance) - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* Killer) - { - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald) - if (skarvald->isDead()) - { - DoScriptText(YELL_DALRONN_SKA_DIED,me); - - if (pInstance) - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); - } - else - { - DoScriptText(YELL_DALRONN_DAL_DIEDFIRST,me); - - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true); - Creature* temp = me->SummonCreature(MOB_DALRONN_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); - if (temp) - { - temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - temp->AI()->AttackStart(Killer); - } - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - if (!ghost) - { - DoScriptText(YELL_DALRONN_KILL,me); - } - } - - void UpdateAI(const uint32 diff) - { - if (ghost) - { - if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (!UpdateVictim()) - return; - - if (AggroYell_Timer) - if (AggroYell_Timer <= diff) - { - DoScriptText(YELL_DALRONN_AGGRO,me); - - AggroYell_Timer = 0; - } else AggroYell_Timer -= diff; - - if (!ghost) - { - if (Check_Timer) - if (Check_Timer <= diff) - { - Check_Timer = 5000; - Unit* skarvald = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SKARVALD) : 0); - if (skarvald && skarvald->isDead()) - { - Skarvald_isDead = true; - Response_Timer = 2000; - Check_Timer = 0; - } - } else Check_Timer -= diff; - - if (Response_Timer) - if (Skarvald_isDead) - if (Response_Timer <= diff) - { - DoScriptText(YELL_DALRONN_SKA_DIEDFIRST,me); - - Response_Timer = 0; - } else Response_Timer -= diff; - } - - if (ShadowBolt_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOW_BOLT); - ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells - } - } else ShadowBolt_Timer -= diff; - - if (Debilitate_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DEBILITATE); - Debilitate_Timer = 5000+rand()%5000; - } - } else Debilitate_Timer -= diff; - - if (IsHeroic()) - if (Summon_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, H_SPELL_SUMMON_SKELETONS); - Summon_Timer = (rand()%10000) + 20000; - } - } else Summon_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_dalronn_the_controller(Creature* pCreature) -{ - return new boss_dalronn_the_controllerAI (pCreature); -} - -void AddSC_boss_skarvald_dalronn() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_skarvald_the_constructor"; - newscript->GetAI = &GetAI_boss_skarvald_the_constructor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_dalronn_the_controller"; - newscript->GetAI = &GetAI_boss_dalronn_the_controller; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp deleted file mode 100644 index 03f97b1d27e..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Utgarde_Keep -SD%Complete: 90 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Utgarde Keep Scripts -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -#define MAX_ENCOUNTER 3 - -#define ENTRY_BELLOW_1 186688 -#define ENTRY_BELLOW_2 186689 -#define ENTRY_BELLOW_3 186690 - -#define ENTRY_FORGEFIRE_1 186692 -#define ENTRY_FORGEFIRE_2 186693 -#define ENTRY_FORGEFIRE_3 186691 - -#define ENTRY_GLOWING_ANVIL_1 186609 -#define ENTRY_GLOWING_ANVIL_2 186610 -#define ENTRY_GLOWING_ANVIL_3 186611 - -#define ENTRY_GIANT_PORTCULLIS_1 186756 -#define ENTRY_GIANT_PORTCULLIS_2 186694 - -/* Utgarde Keep encounters: -0 - Prince Keleseth -1 - Skarvald Dalronn -2 - Ingvar the Plunderer -*/ - -struct instance_utgarde_keep : public ScriptedInstance -{ - instance_utgarde_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 Keleseth; - uint64 Skarvald; - uint64 Dalronn; - uint64 Ingvar; - - uint64 forge_bellow[3]; - uint64 forge_fire[3]; - uint64 forge_anvil[3]; - uint64 portcullis[2]; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 forge_event[3]; - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Keleseth = 0; - Skarvald = 0; - Dalronn = 0; - Ingvar = 0; - - for (uint8 i = 0; i < 3; ++i) - { - forge_bellow[i] = 0; - forge_fire[i] = 0; - forge_anvil[i] = 0; - forge_event[i] = NOT_STARTED; - } - - portcullis[0] = 0; - portcullis[1] = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - - debug_log("TSCR: Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 23953: Keleseth = pCreature->GetGUID(); break; - case 24201: Dalronn = pCreature->GetGUID(); break; - case 24200: Skarvald = pCreature->GetGUID(); break; - case 23954: Ingvar = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - //door and object id - case ENTRY_BELLOW_1: forge_bellow[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_BELLOW_2: forge_bellow[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_BELLOW_3: forge_bellow[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_1: forge_fire[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_2: forge_fire[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_3: forge_fire[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_1: forge_anvil[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_2: forge_anvil[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_3: forge_anvil[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GIANT_PORTCULLIS_1: portcullis[0] = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GIANT_PORTCULLIS_2: portcullis[1] = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_PRINCEKELESETH: return Keleseth; - case DATA_DALRONN: return Dalronn; - case DATA_SKARVALD: return Skarvald; - case DATA_INGVAR: return Ingvar; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_PRINCEKELESETH_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_SKARVALD_DALRONN_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_INGVAR_EVENT: - if (data == DONE) - { - HandleGameObject(portcullis[0], true); - HandleGameObject(portcullis[1], true); - } - m_auiEncounter[2] = data; - break; - case EVENT_FORGE_1: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[0],false); - HandleGameObject(forge_fire[0],false); - HandleGameObject(forge_anvil[0],false); - }else - { - HandleGameObject(forge_bellow[0],true); - HandleGameObject(forge_fire[0],true); - HandleGameObject(forge_anvil[0],true); - } - forge_event[0] = data; - break; - case EVENT_FORGE_2: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[1],false); - HandleGameObject(forge_fire[1],false); - HandleGameObject(forge_anvil[1],false); - }else - { - HandleGameObject(forge_bellow[1],true); - HandleGameObject(forge_fire[1],true); - HandleGameObject(forge_anvil[1],true); - } - forge_event[1] = data; - break; - case EVENT_FORGE_3: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[2],false); - HandleGameObject(forge_fire[2],false); - HandleGameObject(forge_anvil[2],false); - }else - { - HandleGameObject(forge_bellow[2],true); - HandleGameObject(forge_fire[2],true); - HandleGameObject(forge_anvil[2],true); - } - forge_event[2] = data; - break; - } - - if (data == DONE) - { - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_PRINCEKELESETH_EVENT: return m_auiEncounter[0]; - case DATA_SKARVALD_DALRONN_EVENT: return m_auiEncounter[1]; - case DATA_INGVAR_EVENT: return m_auiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "U K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << forge_event[0] << " " << forge_event[1] << " " << forge_event[2]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; - - if (dataHead1 == 'U' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - forge_event[0] = data3; - forge_event[1] = data4; - forge_event[2] = data5; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_utgarde_keep(Map* pMap) -{ - return new instance_utgarde_keep(pMap); -} - -void AddSC_instance_utgarde_keep() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_utgarde_keep"; - newscript->GetInstanceData = &GetInstanceData_instance_utgarde_keep; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp deleted file mode 100644 index 95825aa49b6..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -uint32 entry_search[3] = -{ - 186609, - 186610, - 186611 -}; - -struct npc_dragonflayer_forge_masterAI : public ScriptedAI -{ - npc_dragonflayer_forge_masterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - fm_Type = 0; - } - - ScriptedInstance* pInstance; - uint8 fm_Type; - - void Reset() - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - CheckForge(); - } - - void CheckForge() - { - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,me->isAlive() ? NOT_STARTED : DONE); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,me->isAlive() ? NOT_STARTED : DONE); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,me->isAlive() ? NOT_STARTED : DONE); - break; - } - } - } - - void JustDied(Unit * /*killer*/) - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,DONE); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,DONE); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,DONE); - break; - } - } - } - - void EnterCombat(Unit * /*who*/) - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,IN_PROGRESS); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,IN_PROGRESS); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,IN_PROGRESS); - break; - } - } - me->SetUInt32Value(UNIT_NPC_EMOTESTATE ,EMOTE_ONESHOT_NONE); - } - - uint8 GetForgeMasterType() - { - float diff = 30.0f; - int near_f = 0; - - for (uint8 i = 0; i < 3 ; ++i) - { - GameObject* temp; - temp = me->FindNearestGameObject(entry_search[i],30); - if (temp) - { - if (me->IsWithinDist(temp,diff,false)) - { - near_f = i + 1; - diff = me->GetDistance2d(temp); - - } - } - } - - switch (near_f) - { - case 1: return 1; - case 2: return 2; - case 3: return 3; - default: return 0; - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (fm_Type == 0) - fm_Type = GetForgeMasterType(); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_dragonflayer_forge_master(Creature* pCreature) -{ - return new npc_dragonflayer_forge_masterAI(pCreature); -} - -void AddSC_utgarde_keep() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_dragonflayer_forge_master"; - newscript->GetAI = &GetAI_npc_dragonflayer_forge_master; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.h b/src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.h deleted file mode 100644 index b630e156564..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_UTGARDE_KEEP_H -#define DEF_UTGARDE_KEEP_H - -#define DATA_PRINCEKELESETH 1 -#define DATA_SKARVALD 3 -#define DATA_DALRONN 4 -#define DATA_INGVAR 6 - -#define DATA_PRINCEKELESETH_EVENT 2 -#define DATA_SKARVALD_DALRONN_EVENT 5 -#define DATA_INGVAR_EVENT 7 - -#define EVENT_FORGE_1 8 -#define EVENT_FORGE_2 9 -#define EVENT_FORGE_3 10 - -#endif diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp deleted file mode 100644 index 297fe37b7d8..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp +++ /dev/null @@ -1,830 +0,0 @@ -/* Script Data Start -SDName: Boss palehoof -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_palehoof' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_ARCING_SMASH = 48260, - SPELL_IMPALE = 48261, - H_SPELL_IMPALE = 59268, - SPELL_WITHERING_ROAR = 48256, - H_SPELL_WITHERING_ROAR = 59267, - SPELL_FREEZE = 16245 -}; - -//Orb spells -enum OrbSpells -{ - SPELL_ORB_VISUAL = 48044, - SPELL_ORB_CHANNEL = 48048 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1575000, - SAY_SLAY_1 = -1575001, - SAY_SLAY_2 = -1575002, - SAY_DEATH = -1575003 -}; - -enum Creatures -{ - MOB_STASIS_CONTROLLER = 26688 -}; - -struct Locations -{ - float x, y, z; -}; - -struct Locations moveLocs[]= -{ - {261.6,-449.3,109.5}, - {263.3,-454.0,109.5}, - {291.5,-450.4,109.5}, - {291.5,-454.0,109.5}, - {310.0,-453.4,109.5}, - {238.6,-460.7,109.5} -}; - -enum Phase -{ - PHASE_FRENZIED_WORGEN, - PHASE_RAVENOUS_FURLBORG, - PHASE_MASSIVE_JORMUNGAR, - PHASE_FEROCIOUS_RHINO, - PHASE_GORTOK_PALEHOOF, - PHASE_NONE -}; - -struct boss_palehoofAI : public ScriptedAI -{ - boss_palehoofAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiArcingSmashTimer; - uint32 uiImpaleTimer; - uint32 uiWhiteringRoarTimer; - uint32 uiWaitingTimer; - Phase currentPhase; - uint8 AddCount; - bool DoneAdds[4]; - - ScriptedInstance *pInstance; - - void Reset() - { - uiArcingSmashTimer = 15000; - uiImpaleTimer = 12000; - uiWhiteringRoarTimer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - for (uint32 i=0;i<4;i++) - DoneAdds[i]=false; - AddCount=0; - - currentPhase=PHASE_NONE; - - if (pInstance) - { - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, NOT_STARTED); - - Creature* pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GORTOK_PALEHOOF_SPHERE)); - if (pGo) - { - pGo->SetGoState(GO_STATE_READY); - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void UpdateAI(const uint32 diff) - { - if (currentPhase != PHASE_GORTOK_PALEHOOF) - return; - //Return since we have no target - if (!UpdateVictim()) - return; - - Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->DisappearAndDie(); - - if (uiArcingSmashTimer <= diff) - { - DoCast(me, SPELL_ARCING_SMASH); - uiArcingSmashTimer = urand(13000,17000); - } else uiArcingSmashTimer -= diff; - - if (uiImpaleTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_IMPALE); - uiImpaleTimer = urand(8000,12000); - } else uiImpaleTimer -= diff; - - if (uiWhiteringRoarTimer <= diff) - { - DoCast(me, SPELL_WITHERING_ROAR); - uiWhiteringRoarTimer = urand(8000,12000); - } else uiWhiteringRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, DONE); - Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->DisappearAndDie(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void NextPhase() - { - if (currentPhase == PHASE_NONE) - { - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); - me->SummonCreature(MOB_STASIS_CONTROLLER,moveLocs[5].x,moveLocs[5].y,moveLocs[5].z,0,TEMPSUMMON_CORPSE_DESPAWN); - } - Phase move = PHASE_NONE; - if (AddCount >= DUNGEON_MODE(2,4)) - move = PHASE_GORTOK_PALEHOOF; - else - { - //select random not yet defeated add - uint8 next = urand(0,3); - for (uint8 i=0; i < 16; i++) - { - if (!DoneAdds[i%4] && next == 0) - { - move = (Phase)(i%4); - break; - } else if (!DoneAdds[i%4] && next > 0) - --next; - } - ++AddCount; - DoneAdds[move] = true; - move = (Phase)(move%4); - } - //send orb to summon spot - Creature *pOrb = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pOrb && pOrb->isAlive()) - { - if (currentPhase == PHASE_NONE) - pOrb->CastSpell(me,SPELL_ORB_VISUAL,true); - pOrb->GetMotionMaster()->MovePoint(move,moveLocs[move].x,moveLocs[move].y,moveLocs[move].z); - } - currentPhase = move; - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_boss_palehoof(Creature* pCreature) -{ - return new boss_palehoofAI (pCreature); -} - -//ravenous furbolg's spells -enum RavenousSpells -{ - SPELL_CHAIN_LIGHTING = 48140, - H_SPELL_CHAIN_LIGHTING = 59273, - SPELL_CRAZED = 48139, - SPELL_TERRIFYING_ROAR = 48144 -}; - -struct mob_ravenous_furbolgAI : public ScriptedAI -{ - mob_ravenous_furbolgAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiChainLightingTimer; - uint32 uiCrazedTimer; - uint32 uiTerrifyingRoarTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiChainLightingTimer = 5000; - uiCrazedTimer = 10000; - uiTerrifyingRoarTimer = 15000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiChainLightingTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTING); - uiChainLightingTimer = 5000 + rand()%5000; - } else uiChainLightingTimer -= diff; - - if (uiCrazedTimer <= diff) - { - DoCast(me, SPELL_CRAZED); - uiCrazedTimer = 8000 + rand()%4000; - } else uiCrazedTimer -= diff; - - if (uiTerrifyingRoarTimer <= diff) - { - DoCast(me, SPELL_TERRIFYING_ROAR); - uiTerrifyingRoarTimer = 10000 + rand()%10000; - } else uiTerrifyingRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_ravenous_furbolg(Creature* pCreature) -{ - return new mob_ravenous_furbolgAI (pCreature); -} - -//frenzied worgen's spells -enum FrenziedSpells -{ - SPELL_MORTAL_WOUND = 48137, - H_SPELL_MORTAL_WOUND = 59265, - SPELL_ENRAGE_1 = 48138, - SPELL_ENRAGE_2 = 48142 -}; - -struct mob_frenzied_worgenAI : public ScriptedAI -{ - mob_frenzied_worgenAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiMortalWoundTimer; - uint32 uiEnrage1Timer; - uint32 uiEnrage2Timer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiMortalWoundTimer = 5000; - uiEnrage1Timer = 15000; - uiEnrage2Timer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiMortalWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - uiMortalWoundTimer = 3000 + rand()%4000; - } else uiMortalWoundTimer -= diff; - - if (uiEnrage1Timer <= diff) - { - DoCast(me, SPELL_ENRAGE_1); - uiEnrage1Timer = 15000; - } else uiEnrage1Timer -= diff; - - if (uiEnrage2Timer <= diff) - { - DoCast(me, SPELL_ENRAGE_2); - uiEnrage2Timer = 10000; - } else uiEnrage2Timer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - if (pInstance) - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance->GetData64(DATA_GORTOK_PALEHOOF)); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_frenzied_worgen(Creature* pCreature) -{ - return new mob_frenzied_worgenAI (pCreature); -} - -//ferocious rhino's spells -enum FerociousSpells -{ - SPELL_GORE = 48130, - H_SPELL_GORE = 59264, - SPELL_GRIEVOUS_WOUND = 48105, - H_SPELL_GRIEVOUS_WOUND = 59263, - SPELL_STOMP = 48131 -}; - -struct mob_ferocious_rhinoAI : public ScriptedAI -{ - mob_ferocious_rhinoAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiStompTimer; - uint32 uiGoreTimer; - uint32 uiGrievousWoundTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiStompTimer = 10000; - uiGoreTimer = 15000; - uiGrievousWoundTimer = 20000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiStompTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STOMP); - uiStompTimer = 8000 + rand()%4000; - } else uiStompTimer -= diff; - - if (uiGoreTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GORE); - uiGoreTimer = 13000 + rand()%4000; - } else uiGoreTimer -= diff; - - if (uiGrievousWoundTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_GRIEVOUS_WOUND); - uiGrievousWoundTimer = 18000 + rand()%4000; - } else uiGrievousWoundTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_ferocious_rhino(Creature* pCreature) -{ - return new mob_ferocious_rhinoAI (pCreature); -} - -//massive jormungar's spells -enum MassiveSpells -{ - SPELL_ACID_SPIT = 48132, - SPELL_ACID_SPLATTER = 48136, - H_SPELL_ACID_SPLATTER = 59272, - SPELL_POISON_BREATH = 48133, - H_SPELL_POISON_BREATH = 59271 -}; - -enum MassiveAdds -{ - CREATURE_JORMUNGAR_WORM = 27228 -}; - -struct mob_massive_jormungarAI : public ScriptedAI -{ - mob_massive_jormungarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiAcidSpitTimer; - uint32 uiAcidSplatterTimer; - uint32 uiPoisonBreathTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiAcidSpitTimer = 3000; - uiAcidSplatterTimer = 12000; - uiPoisonBreathTimer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiAcidSpitTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ACID_SPIT); - uiAcidSpitTimer = 2000 + rand()%2000; - } else uiAcidSpitTimer -= diff; - - if (uiAcidSplatterTimer <= diff) - { - DoCast(me, SPELL_POISON_BREATH); - uiAcidSplatterTimer = 10000 + rand()%4000; - } else uiAcidSplatterTimer -= diff; - - if (uiPoisonBreathTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_POISON_BREATH); - uiPoisonBreathTimer = 8000 + rand()%4000; - } else uiPoisonBreathTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI,pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_massive_jormungar(Creature* pCreature) -{ - return new mob_massive_jormungarAI (pCreature); -} - - -struct mob_palehoof_orbAI : public ScriptedAI -{ - mob_palehoof_orbAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 SummonTimer; - Phase currentPhase; - - void Reset() - { - currentPhase=PHASE_NONE; - SummonTimer=5000; - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); - me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL); - me->SetSpeed(MOVE_FLIGHT , 0.5f); - } - - void UpdateAI(const uint32 diff) - { - if (currentPhase == PHASE_NONE) - return; - - if (SummonTimer <= diff) - { - if (currentPhase<5&¤tPhase >= 0) - { - Creature *pNext = NULL; - switch(currentPhase) - { - case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; - case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; - case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; - case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; - case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; - } - - if (pNext) - { - pNext->RemoveAurasDueToSpell(SPELL_FREEZE); - pNext->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - pNext->SetStandState(UNIT_STAND_STATE_STAND); - pNext->SetInCombatWithZone(); - pNext->Attack(pNext->SelectNearestTarget(100),true); - - } - currentPhase=PHASE_NONE; - } - } else SummonTimer-=diff; - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - if (id<0 || id>4) - return; - Creature *pNext = NULL; - switch(id) - { - case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; - case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; - case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; - case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; - case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; - } - if (pNext) - DoCast(pNext, SPELL_ORB_CHANNEL, false); - currentPhase=(Phase)id; - SummonTimer=5000; - } -}; - -CreatureAI* GetAI_mob_palehoof_orb(Creature* pCreature) -{ - return new mob_palehoof_orbAI (pCreature); -} - - - -bool GOHello_palehoof_sphere(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - - Creature *pPalehoof = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - { - // maybe these are hacks :( - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - return true; -} - - - -void AddSC_boss_palehoof() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_palehoof"; - newscript->GetAI = &GetAI_boss_palehoof; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ravenous_furbolg"; - newscript->GetAI = &GetAI_mob_ravenous_furbolg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frenzied_worgen"; - newscript->GetAI = &GetAI_mob_frenzied_worgen; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ferocious_rhino"; - newscript->GetAI = &GetAI_mob_ferocious_rhino; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_massive_jormungar"; - newscript->GetAI = &GetAI_mob_massive_jormungar; - newscript->RegisterSelf(); - - - newscript = new Script; - newscript->Name = "mob_palehoof_orb"; - newscript->GetAI = &GetAI_mob_palehoof_orb; - newscript->RegisterSelf(); - - - newscript = new Script; - newscript->Name = "go_palehoof_sphere"; - newscript->pGOHello=&GOHello_palehoof_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp deleted file mode 100644 index a75eb3465be..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Boss_Skadi -SDAuthor: LordVanMartin, JohnHoliver -SD%Complete: 90% -SDComment: - After Unmount() he appears to still be flying even with SetFlying(false) - -SDCategory: Utgarde Pinnacle -Script Data End */ - -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -//Yell -enum eYells -{ - SAY_AGGRO = -1575004, - SAY_KILL_1 = -1575005, - SAY_KILL_2 = -1575006, - EMOTE_RANGE = -1575007, //Skadi - SAY_DEATH = -1575008, - SAY_DRAKE_DEATH = -1575009, - EMOTE_BREATH = -1575010, //Grauf - SAY_DRAKE_BREATH_1 = -1575011, - SAY_DRAKE_BREATH_2 = -1575012, - SAY_DRAKE_BREATH_3 = -1575013, -}; - -static Position SpawnLoc = {468.931, -513.555, 104.723}; -static Position Location[]= -{ - // Boss - {341.740997, -516.955017, 104.66900}, // 0 - {293.299, -505.95, 142.03}, // 1 - {301.664, -535.164, 146.097}, // 2 - {521.031006, -544.667847, 128.80064}, // 3 - {477.311981, -509.296814, 104.72308}, // 4 - {341.740997, -516.955017, 104.66900}, // 5 - {341.740997, -516.955017, 104.66900}, // 6 - {341.740997, -516.955017, 104.66900}, // 7 - // Triggers Left - {469.661, -484.546, 104.712}, // 8 - {483.315, -485.028, 104.718}, // 9 - {476.87, -487.994, 104.735}, //10 - {477.512, -497.772, 104.728}, //11 - {486.287, -500.759, 104.722}, //12 - {480.1, -503.895, 104.722}, //13 - {472.391, -505.103, 104.723}, //14 - {478.885, -510.803, 104.723}, //15 - {489.529, -508.615, 104.723}, //16 - {484.272, -508.589, 104.723}, //17 - {465.328, -506.495, 104.427}, //18 - {456.885, -508.104, 104.447}, //19 - {450.177, -507.989, 105.247}, //20 - {442.273, -508.029, 104.813}, //21 - {434.225, -508.19, 104.787}, //22 - {423.902, -508.525, 104.274}, //23 - {414.551, -508.645, 105.136}, //24 - {405.787, -508.755, 104.988}, //25 - {398.812, -507.224, 104.82}, //26 - {389.702, -506.846, 104.729}, //27 - {381.856, -506.76, 104.756}, //28 - {372.881, -507.254, 104.779}, //29 - {364.978, -508.182, 104.673}, //30 - {357.633, -508.075, 104.647}, //31 - {350.008, -506.826, 104.588}, //32 - {341.69, -506.77, 104.499}, //33 - {335.31, -505.745, 105.18}, //34 - {471.178, -510.74, 104.723}, //35 - {461.759, -510.365, 104.199}, //36 - {424.07287, -510.082916, 104.711082}, //37 - // Triggers Right - {489.46, -513.297, 105.413}, //38 - {485.706, -517.175, 104.724}, //39 - {480.98, -519.313, 104.724}, //40 - {475.05, -520.52, 104.724}, //41 - {482.97, -512.099, 104.724}, //42 - {477.082, -514.172, 104.724}, //43 - {468.991, -516.691, 104.724}, //44 - {461.722, -517.063, 104.627}, //45 - {455.88, -517.681, 104.707}, //46 - {450.499, -519.099, 104.701}, //47 - {444.889, -518.963, 104.82}, //48 - {440.181, -518.893, 104.861}, //49 - {434.393, -518.758, 104.891}, //50 - {429.328, -518.583, 104.904}, //51 - {423.844, -518.394, 105.004}, //52 - {418.707, -518.266, 105.135}, //53 - {413.377, -518.085, 105.153}, //54 - {407.277, -517.844, 104.893}, //55 - {401.082, -517.443, 104.723}, //56 - {394.933, -514.64, 104.724}, //57 - {388.917, -514.688, 104.734}, //58 - {383.814, -515.834, 104.73}, //59 - {377.887, -518.653, 104.777}, //60 - {371.376, -518.289, 104.781}, //61 - {365.669, -517.822, 104.758}, //62 - {359.572, -517.314, 104.706}, //63 - {353.632, -517.146, 104.647}, //64 - {347.998, -517.038, 104.538}, //65 - {341.803, -516.98, 104.584}, //66 - {335.879, -516.674, 104.628}, //67 - {329.871, -515.92, 104.711}, //68 - // Breach Zone - {485.4577, -511.2515, 115.3011}, //69 - {435.1892, -514.5232, 118.6719}, //70 - {413.9327, -540.9407, 138.2614}, //71 -}; - -enum eCombatPhase -{ - FLYING, - SKADI -}; - -enum eSpells -{ - //Skadi Spells - SPELL_CRUSH = 50234, - SPELL_POISONED_SPEAR = 50225, //isn't being casted =/ - SPELL_WHIRLWIND = 50228, //random target, but not the tank approx. every 20s - SPELL_RAPID_FIRE = 56570, - SPELL_HARPOON_DAMAGE = 56578, - SPELL_FREEZING_CLOUD = 47579, -}; - -enum eCreature -{ - CREATURE_YMIRJAR_WARRIOR = 26690, - CREATURE_YMIRJAR_WITCH_DOCTOR = 26691, - CREATURE_YMIRJAR_HARPOONER = 26692, - CREATURE_GRAUF = 26893, - CREATURE_TRIGGER = 28351, - DATA_MOUNT = 27043, -}; - -enum eAchievments -{ - ACHIEV_TIMED_START_EVENT = 17726, -}; - -struct boss_skadiAI : public ScriptedAI -{ - boss_skadiAI(Creature *c) : ScriptedAI(c), Summons(me) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - SummonList Summons; - uint64 m_uiGraufGUID; - std::vector triggersGUID; - - uint32 m_uiCrushTimer; - uint32 m_uiPoisonedSpearTimer; - uint32 m_uiWhirlwindTimer; - uint32 m_uiWaypointId; - uint32 m_uiMovementTimer; - uint32 m_uiMountTimer; - uint32 m_uiSummonTimer; - uint8 m_uiSpellHitCount; - bool m_bSaidEmote; - - eCombatPhase Phase; - - void Reset() - { - triggersGUID.clear(); - - m_uiCrushTimer = 8000; - m_uiPoisonedSpearTimer = 10000; - m_uiWhirlwindTimer = 20000; - m_uiMountTimer = 3000; - m_uiWaypointId = 0; - m_bSaidEmote = false; - m_uiSpellHitCount = 0; - - Phase = SKADI; - - Summons.DespawnAll(); - me->SetSpeed(MOVE_FLIGHT, 3.0f); - if ((Unit::GetCreature((*me), m_uiGraufGUID) == NULL) && !me->IsMounted()) - me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); - if (m_pInstance) - { - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, NOT_STARTED); - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void JustReachedHome() - { - me->SetFlying(false); - me->Unmount(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - if (Unit::GetCreature((*me), m_uiGraufGUID) == NULL) - me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - Phase = FLYING; - - m_uiMovementTimer = 1000; - m_uiSummonTimer = 10000; - me->SetInCombatWithZone(); - if (m_pInstance) - { - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, IN_PROGRESS); - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - me->GetMotionMaster()->MoveJump(Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 5.0f, 10.0f); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - m_uiMountTimer = 1000; - Summons.DespawnEntry(CREATURE_GRAUF); - } - } - - void JustSummoned(Creature* pSummoned) - { - switch (pSummoned->GetEntry()) - { - case CREATURE_GRAUF: - m_uiGraufGUID = pSummoned->GetGUID(); - break; - case CREATURE_YMIRJAR_WARRIOR: - case CREATURE_YMIRJAR_WITCH_DOCTOR: - case CREATURE_YMIRJAR_HARPOONER: - pSummoned->setActive(true); - pSummoned->SetInCombatWithZone(); - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - break; - case CREATURE_TRIGGER: - pSummoned->CastSpell((Unit*)NULL, SPELL_FREEZING_CLOUD, true); - pSummoned->ForcedDespawn(10*IN_MILISECONDS); - break; - } - Summons.Summon(pSummoned); - } - - void SummonedCreatureDespawn(Creature* pSummoned) - { - if (pSummoned->GetEntry() == CREATURE_GRAUF) - m_uiGraufGUID = 0; - Summons.Despawn(pSummoned); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_HARPOON_DAMAGE) - { - m_uiSpellHitCount++; - if (m_uiSpellHitCount >= 5) - { - Phase = SKADI; - me->SetFlying(false); - me->Unmount(); - if(Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILISECONDS)) - { - pGrauf->GetMotionMaster()->MoveFall(0); - pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); - } - sLog.outBasic("[Skadi] Fly off"); - me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - DoScriptText(SAY_DRAKE_DEATH, me); - m_uiCrushTimer = 8000; - m_uiPoisonedSpearTimer = 10000; - m_uiWhirlwindTimer = 20000; - me->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); - } - } - } - - - void UpdateAI(const uint32 diff) - { - switch(Phase) - { - case FLYING: - if (!UpdateVictim()) - return; - - if (me->GetPositionX() >= 519) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - if (!m_bSaidEmote) - { - DoScriptText(EMOTE_RANGE, me); - m_bSaidEmote = true; - } - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - m_bSaidEmote = false; - } - - if (m_uiMountTimer && m_uiMountTimer <= diff) - { - me->Mount(DATA_MOUNT); - me->SetFlying(true); - m_uiMountTimer = 0; - } else m_uiMountTimer -= diff; - - if (m_uiSummonTimer <= diff) - { - SpawnMobs(); - m_uiSummonTimer = 25000; - } else m_uiSummonTimer -= diff; - - if (m_uiMovementTimer <= diff) - { - switch(m_uiWaypointId) - { - case 0: - me->GetMotionMaster()->MovePoint(0, Location[1].GetPositionX(), Location[1].GetPositionY(), Location[1].GetPositionZ()); - m_uiMovementTimer = 5000; - break; - case 1: - me->GetMotionMaster()->MovePoint(0, Location[2].GetPositionX(), Location[2].GetPositionY(), Location[2].GetPositionZ()); - m_uiMovementTimer = 2000; - break; - case 2: - me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); - m_uiMovementTimer = 15000; - break; - case 3: - me->GetMotionMaster()->MovePoint(0, Location[69].GetPositionX(), Location[69].GetPositionY(), Location[69].GetPositionZ()); - DoScriptText(RAND(SAY_DRAKE_BREATH_1,SAY_DRAKE_BREATH_2), me); - DoScriptText(EMOTE_BREATH, me); - m_uiMovementTimer = 2500; - break; - case 4: - me->GetMotionMaster()->MovePoint(0, Location[70].GetPositionX(), Location[70].GetPositionY(), Location[70].GetPositionZ()); - m_uiMovementTimer = 2000; - SpawnTrigger(); - break; - case 5: - me->GetMotionMaster()->MovePoint(0, Location[71].GetPositionX(), Location[71].GetPositionY(), Location[71].GetPositionZ()); - m_uiMovementTimer = 3000; - break; - case 6: - me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); - m_uiWaypointId = 2; - m_uiMovementTimer = 15000; - break; - } - m_uiWaypointId++; - } else m_uiMovementTimer -= diff; - break; - case SKADI: - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_uiCrushTimer <= diff) - { - DoCastVictim(SPELL_CRUSH); - m_uiCrushTimer = 8000; - } else m_uiCrushTimer -= diff; - - if (m_uiPoisonedSpearTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_POISONED_SPEAR); - m_uiPoisonedSpearTimer = 10000; - } else m_uiPoisonedSpearTimer -= diff; - - if (m_uiWhirlwindTimer <= diff) - { - DoCastAOE(SPELL_WHIRLWIND); - m_uiWhirlwindTimer = 20000; - } else m_uiWhirlwindTimer -= diff; - - DoMeleeAttackIfReady(); - break; - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - Summons.DespawnAll(); - if (m_pInstance) - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void SpawnMobs() - { - for (uint8 i = 0; i < DUNGEON_MODE(5,6); ++i) - { - switch (urand(0,2)) - { - case 0: me->SummonCreature(CREATURE_YMIRJAR_WARRIOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - case 1: me->SummonCreature(CREATURE_YMIRJAR_WITCH_DOCTOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - case 2: me->SummonCreature(CREATURE_YMIRJAR_HARPOONER, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - } - } - } - - void SpawnTrigger() - { - uint8 iStart,iEnd; - switch (urand(0,1)) - { - case 0: - iStart = 8; - iEnd = 37; - break; - case 1: - iStart = 38; - iEnd = 68; - break; - } - for(uint32 i = iStart; i < iEnd; ++i) - me->SummonCreature(CREATURE_TRIGGER,Location[i]); - } -}; - -bool GOHello_go_harpoon_launcher(Player *pPlayer, GameObject *pGO) -{ - ScriptedInstance* m_pInstance; - m_pInstance = (ScriptedInstance*)pGO->GetInstanceData(); - if (!m_pInstance) return false; - - if (Creature* pSkadi = Unit::GetCreature((*pGO),m_pInstance->GetData64(DATA_SKADI_THE_RUTHLESS))) - { - pPlayer->CastSpell(pSkadi,SPELL_RAPID_FIRE, true); - } - return false; -} - -CreatureAI* GetAI_boss_skadi(Creature* pCreature) -{ - return new boss_skadiAI (pCreature); -} - -void AddSC_boss_skadi() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_skadi"; - newscript->GetAI = &GetAI_boss_skadi; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_harpoon_launcher"; - newscript->pGOHello = &GOHello_go_harpoon_launcher; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp deleted file mode 100644 index aae1015ddab..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_CALL_FLAMES = 48258, - SPELL_RITUAL_OF_THE_SWORD = 48276, //Effect #1 Teleport, Effect #2 Dummy - SPELL_SINSTER_STRIKE = 15667, - H_SPELL_SINSTER_STRIKE = 59409, - SPELL_SVALA_TRANSFORMING1 = 54140, - SPELL_SVALA_TRANSFORMING2 = 54205 -}; -//not in db -enum Yells -{ - SAY_DIALOG_WITH_ARTHAS_1 = -1575015, - SAY_DIALOG_WITH_ARTHAS_2 = -1575016, - SAY_DIALOG_WITH_ARTHAS_3 = -1575017, - SAY_AGGRO = -1575018, - SAY_SLAY_1 = -1575019, - SAY_SLAY_2 = -1575020, - SAY_SLAY_3 = -1575021, - SAY_DEATH = -1575022, - SAY_SACRIFICE_PLAYER_1 = -1575023, - SAY_SACRIFICE_PLAYER_2 = -1575024, - SAY_SACRIFICE_PLAYER_3 = -1575025, - SAY_SACRIFICE_PLAYER_4 = -1575026, - SAY_SACRIFICE_PLAYER_5 = -1575027, - SAY_DIALOG_OF_ARTHAS_1 = -1575028, - SAY_DIALOG_OF_ARTHAS_2 = -1575029 -}; -enum Creatures -{ - CREATURE_ARTHAS = 24266, // Image of Arthas - CREATURE_SVALA_SORROWGRAVE = 26668, // Svala after transformation - CREATURE_SVALA = 29281, // Svala before transformation - CREATURE_RITUAL_CHANNELER = 27281 -}; -enum ChannelerSpells -{ - //ritual channeler's spells - SPELL_PARALYZE = 48278, - SPELL_SHADOWS_IN_THE_DARK = 59407 -}; -enum Misc -{ - DATA_SVALA_DISPLAY_ID = 25944 -}; -enum IntroPhase -{ - IDLE, - INTRO, - FINISHED -}; -enum CombatPhase -{ - NORMAL, - SACRIFICING -}; - -static Position RitualChannelerPos[]= -{ - {296.42, -355.01, 90.94}, - {302.36, -352.01, 90.54}, - {291.39, -350.89, 90.54} -}; -static Position ArthasPos = { 295.81, -366.16, 92.57, 1.58 }; -static Position SvalaPos = { 296.632, -346.075, 90.6307, 1.58 }; - -struct boss_svalaAI : public ScriptedAI -{ - boss_svalaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiIntroTimer; - - uint8 uiIntroPhase; - - IntroPhase Phase; - - TempSummon* pArthas; - uint64 uiArthasGUID; - - ScriptedInstance* pInstance; - - void Reset() - { - Phase = IDLE; - uiIntroTimer = 1*IN_MILISECONDS; - uiIntroPhase = 0; - uiArthasGUID = 0; - - if (pInstance) - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); - } - - void MoveInLineOfSight(Unit* pWho) - { - if (!pWho) - return; - - if (Phase == IDLE && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && me->IsWithinDistInMap(pWho, 40)) - { - Phase = INTRO; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Creature *pArthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - pArthas->SetFloatValue(OBJECT_FIELD_SCALE_X, 5); - uiArthasGUID = pArthas->GetGUID(); - } - } - } - - void AttackStart(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (Phase != INTRO) - return; - - if (uiIntroTimer <= diff) - { - Creature *pArthas = Unit::GetCreature(*me, uiArthasGUID); - if (!pArthas) - return; - - switch (uiIntroPhase) - { - case 0: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_1, me); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 1: - DoScriptText(SAY_DIALOG_OF_ARTHAS_1, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 2: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_2, me); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 3: - DoScriptText(SAY_DIALOG_OF_ARTHAS_2, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 4: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_3, me); - DoCast(me, SPELL_SVALA_TRANSFORMING1); - ++uiIntroPhase; - uiIntroTimer = 2.8*IN_MILISECONDS; - break; - case 5: - DoCast(me, SPELL_SVALA_TRANSFORMING2); - ++uiIntroPhase; - uiIntroTimer = 200; - break; - case 6: - if (Creature* pSvalaSorrowgrave = me->SummonCreature(CREATURE_SVALA_SORROWGRAVE, SvalaPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60*IN_MILISECONDS)) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(DATA_SVALA_DISPLAY_ID); - pArthas->ToTempSummon()->UnSummon(); - uiArthasGUID = 0; - Phase = FINISHED; - } - else - Reset(); - break; - } - } else uiIntroTimer -= diff; - } -}; - -struct mob_ritual_channelerAI : public Scripted_NoMovementAI -{ - mob_ritual_channelerAI(Creature *c) :Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - DoCast(me, SPELL_SHADOWS_IN_THE_DARK); - } - - // called by svala sorrowgrave to set guid of victim - void DoAction(uint32 /*action*/) - { - if (pInstance) - if (Unit *pVictim = me->GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER))) - DoCast(pVictim, SPELL_PARALYZE); - } - - void EnterCombat(Unit* /*who*/) - { - } -}; - -struct boss_svala_sorrowgraveAI : public ScriptedAI -{ - boss_svala_sorrowgraveAI(Creature *c) : ScriptedAI(c), summons(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiSinsterStrikeTimer; - uint32 uiCallFlamesTimer; - uint32 uiRitualOfSwordTimer; - uint32 uiSacrificeTimer; - - CombatPhase Phase; - - SummonList summons; - - bool bSacrificed; - - ScriptedInstance* pInstance; - - void Reset() - { - uiSinsterStrikeTimer = 7*IN_MILISECONDS; - uiCallFlamesTimer = 10*IN_MILISECONDS; - uiRitualOfSwordTimer = 20*IN_MILISECONDS; - uiSacrificeTimer = 8*IN_MILISECONDS; - - bSacrificed = false; - - Phase = NORMAL; - - DoTeleportTo(296.632, -346.075, 90.6307); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - - summons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); - pInstance->SetData64(DATA_SACRIFICED_PLAYER,0); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature *summon) - { - summons.Summon(summon); - } - - void SummonedCreatureDespawn(Creature *summon) - { - summons.Despawn(summon); - } - - void UpdateAI(const uint32 diff) - { - if (Phase == NORMAL) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiSinsterStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); - uiSinsterStrikeTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); - } else uiSinsterStrikeTimer -= diff; - - if (uiCallFlamesTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, SPELL_CALL_FLAMES); - uiCallFlamesTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); - } - } else uiCallFlamesTimer -= diff; - - if (!bSacrificed) - if (uiRitualOfSwordTimer <= diff) - { - if (Unit* pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(RAND(SAY_SACRIFICE_PLAYER_1,SAY_SACRIFICE_PLAYER_2,SAY_SACRIFICE_PLAYER_3,SAY_SACRIFICE_PLAYER_4,SAY_SACRIFICE_PLAYER_5),me); - DoCast(pSacrificeTarget, SPELL_RITUAL_OF_THE_SWORD); - //Spell doesn't teleport - DoTeleportPlayer(pSacrificeTarget, 296.632, -346.075, 90.63, 4.6); - me->SetUnitMovementFlags(MOVEMENTFLAG_FLY_MODE); - DoTeleportTo(296.632, -346.075, 120.85); - Phase = SACRIFICING; - if (pInstance) - { - pInstance->SetData64(DATA_SACRIFICED_PLAYER,pSacrificeTarget->GetGUID()); - - for (uint8 i = 0; i < 3; ++i) - if (Creature* pSummon = me->SummonCreature(CREATURE_RITUAL_CHANNELER, RitualChannelerPos[i], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) - pSummon->AI()->DoAction(0); - } - - bSacrificed = true; - } - } else uiRitualOfSwordTimer -= diff; - - DoMeleeAttackIfReady(); - } - else //SACRIFICING - { - if (uiSacrificeTimer <= diff) - { - Unit* pSacrificeTarget = pInstance ? Unit::GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER)) : NULL; - if (pInstance && !summons.empty() && pSacrificeTarget && pSacrificeTarget->isAlive()) - me->Kill(pSacrificeTarget, false); // durability damage? - - //go down - Phase = NORMAL; - pSacrificeTarget = NULL; - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->GetMotionMaster()->MoveChase(pTarget); - - uiSacrificeTimer = 8*IN_MILISECONDS; - } - else uiSacrificeTimer -= diff; - } - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* pKiller) - { - if (pInstance) - { - Creature* pSvala = Unit::GetCreature((*me), pInstance->GetData64(DATA_SVALA)); - if (pSvala && pSvala->isAlive()) - pKiller->Kill(pSvala); - - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); - } - DoScriptText(SAY_DEATH, me); - } -}; - -CreatureAI* GetAI_boss_svala(Creature* pCreature) -{ - return new boss_svalaAI (pCreature); -} - -CreatureAI* GetAI_mob_ritual_channeler(Creature* pCreature) -{ - return new mob_ritual_channelerAI(pCreature); -} - -CreatureAI* GetAI_boss_svala_sorrowgrave(Creature* pCreature) -{ - return new boss_svala_sorrowgraveAI(pCreature); -} - -void AddSC_boss_svala() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_svala"; - newscript->GetAI = &GetAI_boss_svala; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ritual_channeler"; - newscript->GetAI = &GetAI_mob_ritual_channeler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_svala_sorrowgrave"; - newscript->GetAI = &GetAI_boss_svala_sorrowgrave; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp deleted file mode 100644 index 1a650f94101..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* Script Data Start -SDName: Boss ymiron -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_ymiron' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_BANE = 48294, - H_SPELL_BANE = 59301, - SPELL_DARK_SLASH = 48292, - SPELL_FETID_ROT = 48291, - H_SPELL_FETID_ROT = 59300, - SPELL_SCREAMS_OF_THE_DEAD = 51750, - SPELL_SPIRIT_BURST = 48529, - H_SPELL_SPIRIT_BURST = 59305, - SPELL_SPIRIT_STRIKE = 48423, - H_SPELL_SPIRIT_STRIKE = 59304, - SPELL_ANCESTORS_VENGEANCE = 16939, - - SPELL_SUMMON_AVENGING_SPIRIT = 48592, - SPELL_SUMMON_SPIRIT_FOUNT = 48386, - - SPELL_CHANNEL_SPIRIT_TO_YMIRON = 48316, - SPELL_CHANNEL_YMIRON_TO_SPIRIT = 48307, - - SPELL_SPIRIT_FOUNT = 48380, - H_SPELL_SPIRIT_FOUNT = 59320 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1575028, - SAY_SLAY_1 = -1575029, - SAY_SLAY_2 = -1575030, - SAY_SLAY_3 = -1575031, - SAY_SLAY_4 = -1575032, - SAY_DEATH = -1575033, - SAY_SUMMON_BJORN = -1575034, - SAY_SUMMON_HALDOR = -1575035, - SAY_SUMMON_RANULF = -1575036, - SAY_SUMMON_TORGYN = -1575037 -}; - -enum Creatures -{ - CREATURE_BJORN = 27303, - CREATURE_BJORN_VISUAL = 27304, - CREATURE_HALDOR = 27307, - CREATURE_HALDOR_VISUAL = 27310, - CREATURE_RANULF = 27308, - CREATURE_RANULF_VISUAL = 27311, - CREATURE_TORGYN = 27309, - CREATURE_TORGYN_VISUAL = 27312, - CREATURE_SPIRIT_FOUNT = 27339, - CREATURE_AVENGING_SPIRIT = 27386 -}; - -struct ActiveBoatStruct -{ - uint32 npc; - int32 say; - float MoveX,MoveY,MoveZ,SpawnX,SpawnY,SpawnZ,SpawnO; -}; - -static ActiveBoatStruct ActiveBot[4] = -{ - {CREATURE_BJORN_VISUAL, SAY_SUMMON_BJORN, 404.379, -335.335, 104.756, 413.594, -335.408, 107.995, 3.157}, - {CREATURE_HALDOR_VISUAL, SAY_SUMMON_HALDOR, 380.813, -335.069, 104.756, 369.994, -334.771, 107.995, 6.232}, - {CREATURE_RANULF_VISUAL, SAY_SUMMON_RANULF, 381.546, -314.362, 104.756, 370.841, -314.426, 107.995, 6.232}, - {CREATURE_TORGYN_VISUAL, SAY_SUMMON_TORGYN, 404.310, -314.761, 104.756, 413.992, -314.703, 107.995, 3.157} -}; - -struct boss_ymironAI : public ScriptedAI -{ - boss_ymironAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - srand(time(NULL)); - for (int i = 0; i < 4; ++i) - m_uiActiveOrder[i] = i; - for (int i = 0; i < 3; ++i) - { - int r = i + (rand()%(4-i)); - int temp = m_uiActiveOrder[i]; - m_uiActiveOrder[i] = m_uiActiveOrder[r]; - m_uiActiveOrder[r] = temp; - } - } - - bool m_bIsWalking; - bool m_bIsPause; - bool m_bIsActiveWithBJORN; - bool m_bIsActiveWithHALDOR; - bool m_bIsActiveWithRANULF; - bool m_bIsActiveWithTORGYN; - - uint8 m_uiActiveOrder[4]; - uint8 m_uiActivedNumber; - - uint32 m_uiFetidRot_Timer; - uint32 m_uiBane_Timer; - uint32 m_uiDarkSlash_Timer; - uint32 m_uiAncestors_Vengeance_Timer; - - uint32 m_uiAbility_BJORN_Timer; - uint32 m_uiAbility_HALDOR_Timer; - uint32 m_uiAbility_RANULF_Timer; - uint32 m_uiAbility_TORGYN_Timer; - - uint32 m_uiPause_Timer; - uint32 m_uiHealthAmountModifier; - uint32 m_uiHealthAmountMultipler; - - uint64 m_uiActivedCreatureGUID; - uint64 m_uiOrbGUID; - - ScriptedInstance *pInstance; - - void Reset() - { - m_bIsPause = false; - m_bIsActiveWithBJORN = false; - m_bIsActiveWithHALDOR = false; - m_bIsActiveWithRANULF = false; - m_bIsActiveWithTORGYN = false; - - m_uiFetidRot_Timer = urand(8000,13000); - m_uiBane_Timer = urand(18000,23000); - m_uiDarkSlash_Timer = urand(28000,33000); - m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(60000,45000); - m_uiPause_Timer = 0; - - m_uiAbility_BJORN_Timer = 0; - m_uiAbility_HALDOR_Timer = 0; - m_uiAbility_RANULF_Timer = 0; - m_uiAbility_TORGYN_Timer = 0; - - m_uiActivedNumber = 0; - m_uiHealthAmountModifier = 1; - m_uiHealthAmountMultipler = DUNGEON_MODE(20,25); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (m_bIsWalking) - { - if (m_uiPause_Timer <= diff) - { - DoScriptText(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].say, me); - DoCast(me, SPELL_CHANNEL_YMIRON_TO_SPIRIT); // should be on spirit - if (Creature* pTemp = me->SummonCreature(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].npc, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnX, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnY, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnZ, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnO, TEMPSUMMON_CORPSE_DESPAWN, 0)) - { - m_uiActivedCreatureGUID = pTemp->GetGUID(); - pTemp->CastSpell(me, SPELL_CHANNEL_SPIRIT_TO_YMIRON, true); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - switch(m_uiActiveOrder[m_uiActivedNumber]) - { - case 0: m_bIsActiveWithBJORN = true; break; - case 1: m_bIsActiveWithHALDOR = true; break; - case 2: m_bIsActiveWithRANULF = true; break; - case 3: m_bIsActiveWithTORGYN = true; break; - } - } - - m_bIsPause = true; - m_bIsWalking = false; - m_uiPause_Timer = 3000; - } else m_uiPause_Timer -= diff; - return; - } - else if (m_bIsPause) - { - if (m_uiPause_Timer <= diff) - { - m_uiAbility_BJORN_Timer = 5000; - m_uiAbility_HALDOR_Timer = 5000; - m_uiAbility_RANULF_Timer = 5000; - m_uiAbility_TORGYN_Timer = 5000; - - m_bIsPause = false; - m_uiPause_Timer = 0; - } else m_uiPause_Timer -= diff; - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!m_bIsPause) - { - // Normal spells ------------------------------------------------------------------------ - if (m_uiBane_Timer <= diff) - { - DoCast(me, SPELL_BANE); - m_uiBane_Timer = urand(20000,25000); - } else m_uiBane_Timer -= diff; - - if (m_uiFetidRot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FETID_ROT); - m_uiFetidRot_Timer = urand(10000,15000); - } else m_uiFetidRot_Timer -= diff; - - if (m_uiDarkSlash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DARK_SLASH); - m_uiDarkSlash_Timer = urand(30000,35000); - } else m_uiDarkSlash_Timer -= diff; - - if (m_uiAncestors_Vengeance_Timer <= diff) - { - DoCast(me, SPELL_ANCESTORS_VENGEANCE); - m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(urand(60000,65000),urand(45000,50000)); - } else m_uiAncestors_Vengeance_Timer -= diff; - - // Abilities ------------------------------------------------------------------------------ - if (m_bIsActiveWithBJORN && m_uiAbility_BJORN_Timer <= diff) - { - //DoCast(me, SPELL_SUMMON_SPIRIT_FOUNT); // works fine, but using summon has better control - if (Creature* pTemp = me->SummonCreature(CREATURE_SPIRIT_FOUNT, 385+rand()%10, -330+rand()%10, 104.756, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) - { - pTemp->SetSpeed(MOVE_RUN, 0.4f); - pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SPIRIT_FOUNT, H_SPELL_SPIRIT_FOUNT), true); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->SetDisplayId(11686); - //pTemp->GetMotionMaster()->MoveChase(me->getVictim()); - m_uiOrbGUID = pTemp->GetGUID(); - } - m_bIsActiveWithBJORN = false; // only one orb - } else m_uiAbility_BJORN_Timer -= diff; - - if (m_bIsActiveWithHALDOR && m_uiAbility_HALDOR_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SPIRIT_STRIKE); - m_uiAbility_HALDOR_Timer = 5000; // overtime - } else m_uiAbility_HALDOR_Timer -= diff; - - if (m_bIsActiveWithRANULF && m_uiAbility_RANULF_Timer <= diff) - { - DoCast(me, SPELL_SPIRIT_BURST); - m_uiAbility_RANULF_Timer = 10000; // overtime - } else m_uiAbility_RANULF_Timer -= diff; - - if (m_bIsActiveWithTORGYN && m_uiAbility_TORGYN_Timer <= diff) - { - float x,y,z; - x = me->GetPositionX()-5; - y = me->GetPositionY()-5; - z = me->GetPositionZ(); - for (uint8 i = 0; i < 4; ++i) - { - //DoCast(me, SPELL_SUMMON_AVENGING_SPIRIT); // works fine, but using summon has better control - if (Creature* pTemp = me->SummonCreature(CREATURE_AVENGING_SPIRIT, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - pTemp->AddThreat(pTarget, 0.0f); - pTemp->AI()->AttackStart(pTarget); - } - } - } - m_uiAbility_TORGYN_Timer = 15000; // overtime - } else m_uiAbility_TORGYN_Timer -= diff; - - // Health check ----------------------------------------------------------------------------- - if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(m_uiHealthAmountMultipler * m_uiHealthAmountModifier))) - { - uint8 m_uiOrder = m_uiHealthAmountModifier - 1; - ++m_uiHealthAmountModifier; - - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_SCREAMS_OF_THE_DEAD); - me->GetMotionMaster()->Clear(); - me->StopMoving(); - me->AttackStop(); - me->GetMotionMaster()->MovePoint(0, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveX, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveY, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveZ); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - m_bIsActiveWithBJORN = false; - m_bIsActiveWithHALDOR = false; - m_bIsActiveWithRANULF = false; - m_bIsActiveWithTORGYN = false; - - m_uiBane_Timer += 8000; - m_uiFetidRot_Timer += 8000; - m_uiDarkSlash_Timer += 8000; - m_uiAncestors_Vengeance_Timer += 8000; - - m_uiActivedNumber = m_uiOrder; - m_bIsWalking = true; - m_uiPause_Timer = 2000; - return; - } - DoMeleeAttackIfReady(); - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } - - void DespawnBoatGhosts(uint64& m_uiCreatureGUID) - { - if (m_uiCreatureGUID) - if (Creature* pTemp = Unit::GetCreature(*me, m_uiCreatureGUID)) - pTemp->DisappearAndDie(); - - m_uiCreatureGUID = 0; - } -}; - -CreatureAI* GetAI_boss_ymiron(Creature* pCreature) -{ - return new boss_ymironAI(pCreature); -} - -void AddSC_boss_ymiron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ymiron"; - newscript->GetAI = &GetAI_boss_ymiron; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp b/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp deleted file mode 100644 index cf042867707..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -#define MAX_ENCOUNTER 4 - -/* Utgarde Pinnacle encounters: -0 - Svala Sorrowgrave -1 - Gortok Palehoof -2 - Skadi the Ruthless -3 - King Ymiron -*/ - -enum GameObjects -{ - ENTRY_SKADI_THE_RUTHLESS_DOOR = 192173, - ENTRY_KING_YMIRON_DOOR = 192174, - ENTRY_GORK_PALEHOOF_SPHERE = 188593 -}; - -struct instance_pinnacle : public ScriptedInstance -{ - instance_pinnacle(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiSvalaSorrowgrave; - uint64 uiGortokPalehoof; - uint64 uiSkadiTheRuthless; - uint64 uiKingYmiron; - - uint64 uiSkadiTheRuthlessDoor; - uint64 uiKingYmironDoor; - uint64 uiGortokPalehoofSphere; - - uint64 uiFrenziedWorgen; - uint64 uiRavenousFurbolg; - uint64 uiFerociousRhino; - uint64 uiMassiveJormungar; - uint64 uiPalehoofOrb; - - uint64 uiSvala; - uint64 uiSacrificedPlayer; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i] = NOT_STARTED; - - uiSvalaSorrowgrave = 0; - uiGortokPalehoof = 0; - uiSkadiTheRuthless = 0; - uiKingYmiron = 0; - - uiSkadiTheRuthlessDoor = 0; - uiKingYmironDoor = 0; - uiGortokPalehoofSphere = 0; - - uiFrenziedWorgen = 0; - uiRavenousFurbolg = 0; - uiFerociousRhino = 0; - uiMassiveJormungar = 0; - uiPalehoofOrb = 0; - - uiSvala = 0; - uiSacrificedPlayer = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case BOSS_SVALA_SORROWGRAVE: uiSvalaSorrowgrave = pCreature->GetGUID(); break; - case BOSS_GORTOK_PALEHOOF: uiGortokPalehoof = pCreature->GetGUID(); break; - case BOSS_SKADI_RUTHLESS: uiSkadiTheRuthless = pCreature->GetGUID(); break; - case BOSS_KING_YMIRON: uiKingYmiron = pCreature->GetGUID(); break; - case MOB_FRENZIED_WORGEN: uiFrenziedWorgen = pCreature->GetGUID(); break; - case MOB_RAVENOUS_FURBOLG: uiRavenousFurbolg = pCreature->GetGUID(); break; - case MOB_MASSIVE_JORMUNGAR: uiMassiveJormungar = pCreature->GetGUID(); break; - case MOB_FEROCIOUS_RHINO: uiFerociousRhino = pCreature->GetGUID(); break; - case MOB_SVALA: uiSvala = pCreature->GetGUID(); break; - case MOB_PALEHOOF_ORB: uiPalehoofOrb = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case ENTRY_SKADI_THE_RUTHLESS_DOOR: - uiSkadiTheRuthlessDoor = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) HandleGameObject(NULL,true,pGo); - break; - case ENTRY_KING_YMIRON_DOOR: - uiKingYmironDoor = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) HandleGameObject(NULL,true,pGo); - break; - case ENTRY_GORK_PALEHOOF_SPHERE: - uiGortokPalehoofSphere = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - { - HandleGameObject(NULL,true,pGo); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_SVALA_SORROWGRAVE_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_GORTOK_PALEHOOF_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_SKADI_THE_RUTHLESS_EVENT: - if (data == DONE) - HandleGameObject(uiSkadiTheRuthlessDoor,true); - m_auiEncounter[2] = data; - break; - case DATA_KING_YMIRON_EVENT: - if (data == DONE) - HandleGameObject(uiKingYmironDoor,true); - m_auiEncounter[3] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_SACRIFICED_PLAYER) - uiSacrificedPlayer = data; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_SVALA_SORROWGRAVE_EVENT: return m_auiEncounter[0]; - case DATA_GORTOK_PALEHOOF_EVENT: return m_auiEncounter[1]; - case DATA_SKADI_THE_RUTHLESS_EVENT: return m_auiEncounter[2]; - case DATA_KING_YMIRON_EVENT: return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_SVALA_SORROWGRAVE: return uiSvalaSorrowgrave; - case DATA_GORTOK_PALEHOOF: return uiGortokPalehoof; - case DATA_SKADI_THE_RUTHLESS: return uiSkadiTheRuthless; - case DATA_KING_YMIRON: return uiKingYmiron; - case DATA_MOB_FRENZIED_WORGEN: return uiFrenziedWorgen; - case DATA_MOB_RAVENOUS_FURBOLG: return uiRavenousFurbolg; - case DATA_MOB_MASSIVE_JORMUNGAR: return uiMassiveJormungar; - case DATA_MOB_FEROCIOUS_RHINO: return uiFerociousRhino; - case DATA_MOB_ORB: return uiPalehoofOrb; - case DATA_SVALA: return uiSvala; - case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "U P " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'U' && dataHead2 == 'P') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_utgarde_pinnacle(Map* pMap) -{ - return new instance_pinnacle(pMap); -} - -void AddSC_instance_utgarde_pinnacle() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_utgarde_pinnacle"; - newscript->GetInstanceData = &GetInstanceData_instance_utgarde_pinnacle; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h b/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h deleted file mode 100644 index a51d7aceda0..00000000000 --- a/src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef DEF_PINNACLE_H -#define DEF_PINNACLE_H - -enum Data -{ - DATA_SVALA_SORROWGRAVE_EVENT, - DATA_GORTOK_PALEHOOF_EVENT, - DATA_SKADI_THE_RUTHLESS_EVENT, - DATA_KING_YMIRON_EVENT -}; -enum Data64 -{ - DATA_SVALA, - DATA_SVALA_SORROWGRAVE, - DATA_GORTOK_PALEHOOF, - DATA_SKADI_THE_RUTHLESS, - DATA_MOB_GRAUF, - DATA_KING_YMIRON, - DATA_MOB_FRENZIED_WORGEN, - DATA_MOB_RAVENOUS_FURBOLG, - DATA_MOB_MASSIVE_JORMUNGAR, - DATA_MOB_FEROCIOUS_RHINO, - DATA_MOB_ORB, - DATA_GORTOK_PALEHOOF_SPHERE, - DATA_SACRIFICED_PLAYER -}; - -enum eCreatures -{ - BOSS_SVALA_SORROWGRAVE = 26668, - BOSS_GORTOK_PALEHOOF = 26687, - BOSS_SKADI_RUTHLESS = 26693, - BOSS_KING_YMIRON = 26861, - MOB_FRENZIED_WORGEN = 26683, - MOB_RAVENOUS_FURBOLG = 26684, - MOB_MASSIVE_JORMUNGAR = 26685, - MOB_FEROCIOUS_RHINO = 26686, - MOB_SVALA = 29281, - MOB_PALEHOOF_ORB = 26688, -}; - -#endif diff --git a/src/server/scripts/northrend/vault_of_archavon/boss_archavon.cpp b/src/server/scripts/northrend/vault_of_archavon/boss_archavon.cpp deleted file mode 100644 index 11d432e94c6..00000000000 --- a/src/server/scripts/northrend/vault_of_archavon/boss_archavon.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2009-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*** SQL START *** -UPDATE `creature_template` SET `ScriptName`='boss_archavon' WHERE `entry`='31125'; -UPDATE `creature_template` SET `ScriptName`='mob_archavon_warder' WHERE `entry`='32353'; -*** SQL END ***/ - -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -#define EMOTE_BERSERK -1590002 - -//Spells Archavon -#define SPELL_ROCK_SHARDS 58678 -#define SPELL_CRUSHING_LEAP RAID_MODE(58960,60894)//Instant (10-80yr range) -- Leaps at an enemy, inflicting 8000 Physical damage, knocking all nearby enemies away, and creating a cloud of choking debris. -#define SPELL_STOMP RAID_MODE(58663,60880) -#define SPELL_IMPALE RAID_MODE(58666,60882) //Lifts an enemy off the ground with a spiked fist, inflicting 47125 to 52875 Physical damage and 9425 to 10575 additional damage each second for 8 sec. -#define SPELL_BERSERK 47008 -//Spells Archavon Warders -#define SPELL_ROCK_SHOWER RAID_MODE(60919,60923) -#define SPELL_SHIELD_CRUSH RAID_MODE(60897,60899) -#define SPELL_WHIRL RAID_MODE(60902,60916) - -//4 Warders spawned -#define ARCHAVON_WARDER 32353 //npc 32353 - -//Yell -#define SAY_LEAP "Archavon the Stone Watcher lunges for $N!" //$N should be the target - -#define EVENT_ROCK_SHARDS 1 //15s cd -#define EVENT_CHOKING_CLOUD 2 //30s cd -#define EVENT_STOMP 3 //45s cd -#define EVENT_IMPALE 4 -#define EVENT_BERSERK 5 //300s cd - -//mob -#define EVENT_ROCK_SHOWER 5 //set = 20s cd,unkown cd -#define EVENT_SHIELD_CRUSH 6 //set = 30s cd -#define EVENT_WHIRL 8 //set= 10s cd - -struct boss_archavonAI : public ScriptedAI -{ - boss_archavonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_ARCHAVON_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit* /*Victim*/) {} - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ARCHAVON_EVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); - events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); - events.ScheduleEvent(EVENT_STOMP, 45000); - events.ScheduleEvent(EVENT_BERSERK, 300000); - - if (pInstance) - pInstance->SetData(DATA_ARCHAVON_EVENT, IN_PROGRESS); - } - - // Below UpdateAI may need review/debug. - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ROCK_SHARDS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ROCK_SHARDS); - events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); - return; - case EVENT_CHOKING_CLOUD: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CRUSHING_LEAP, true); //10y~80y, ignore range - events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); - return; - case EVENT_STOMP: - DoCast(me->getVictim(), SPELL_STOMP); - events.ScheduleEvent(EVENT_IMPALE, 3000); - events.ScheduleEvent(EVENT_STOMP, 45000); - return; - case EVENT_IMPALE: - DoCast(me->getVictim(), SPELL_IMPALE); - return; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - DoScriptText(EMOTE_BERSERK, me); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -/*###### -## Mob Archavon Warder -######*/ -struct mob_archavon_warderAI : public ScriptedAI //npc 32353 -{ - mob_archavon_warderAI(Creature *c) : ScriptedAI(c) {} - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ROCK_SHOWER, 2000); - events.ScheduleEvent(EVENT_SHIELD_CRUSH, 20000); - events.ScheduleEvent(EVENT_WHIRL, 7500); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ROCK_SHOWER: - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ROCK_SHOWER); - events.ScheduleEvent(EVENT_ROCK_SHARDS, 6000); - return; - } - case EVENT_SHIELD_CRUSH: - DoCast(me->getVictim(), SPELL_SHIELD_CRUSH); - events.ScheduleEvent(EVENT_SHIELD_CRUSH, 20000); - return; - case EVENT_WHIRL: - DoCast(me->getVictim(), SPELL_WHIRL); - events.ScheduleEvent(EVENT_WHIRL, 8000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_archavon_warder(Creature* pCreature) -{ - return new mob_archavon_warderAI(pCreature); -} - -CreatureAI* GetAI_boss_archavon(Creature* pCreature) -{ - return new boss_archavonAI (pCreature); -} - -void AddSC_boss_archavon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_archavon"; - newscript->GetAI = &GetAI_boss_archavon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_archavon_warder"; - newscript->GetAI = &GetAI_mob_archavon_warder; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/vault_of_archavon/boss_emalon.cpp b/src/server/scripts/northrend/vault_of_archavon/boss_emalon.cpp deleted file mode 100644 index 92a0331708e..00000000000 --- a/src/server/scripts/northrend/vault_of_archavon/boss_emalon.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2009-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -//Emalon spells -#define SPELL_CHAIN_LIGHTNING RAID_MODE(64213, 64215) -#define SPELL_LIGHTNING_NOVA RAID_MODE(64216, 65279) -#define SPELL_OVERCHARGE 64218 //Casted every 45 sec on a random Tempest Minion -#define SPELL_BERSERK 26662 - -//Tempest Minion spells -#define SPELL_SHOCK 64363 -#define SPELL_OVERCHARGED 64217 -#define SPELL_OVERCHARGED_BLAST 64219 //Casted when Overcharged reaches 10 stacks. Mob dies after that - -//Emotes -#define EMOTE_OVERCHARGE -1590000 -#define EMOTE_MINION_RESPAWN -1590001 -#define EMOTE_BERSERK -1590002 - -//Events -#define EVENT_CHAIN_LIGHTNING 1 -#define EVENT_LIGHTNING_NOVA 2 -#define EVENT_OVERCHARGE 3 -#define EVENT_BERSERK 4 -#define EVENT_SHOCK 5 - -//Creatures -#define MOB_TEMPEST_MINION 33998 - -#define MAX_TEMPEST_MINIONS 4 - -struct Position TempestMinions[MAX_TEMPEST_MINIONS] = -{ - {-203.980103, -281.287720, 91.650223, 1.598807}, - {-233.489410, -281.139282, 91.652412, 1.598807}, - {-233.267578, -297.104645, 91.681915, 1.598807}, - {-203.842529, -297.097015, 91.745163, 1.598807} -}; - -/*###### -## Emalon the Storm Watcher -######*/ -struct boss_emalonAI : public BossAI -{ - boss_emalonAI(Creature *c) : BossAI(c, DATA_EMALON_EVENT) - { - } - - void Reset() - { - _Reset(); - - for (uint8 i = 0; i < MAX_TEMPEST_MINIONS; ++i) - me->SummonCreature(MOB_TEMPEST_MINION, TempestMinions[i], TEMPSUMMON_CORPSE_DESPAWN, 0); - } - - void JustSummoned(Creature *summoned) - { - BossAI::JustSummoned(summoned); - - if (me->getVictim() && summoned->AI()) - summoned->AI()->AttackStart(me->getVictim()); - } - - void EnterCombat(Unit * who) - { - if (!summons.empty()) - { - for (std::list::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) - { - Creature *minion = Unit::GetCreature(*me, *itr); - if (minion && minion->isAlive() && !minion->getVictim() && minion->AI()) - minion->AI()->AttackStart(who); - } - } - - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 5000); - events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 40000); - events.ScheduleEvent(EVENT_BERSERK, 360000); - events.ScheduleEvent(EVENT_OVERCHARGE, 45000); - - _EnterCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CHAIN_LIGHTNING: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 25000); - break; - case EVENT_LIGHTNING_NOVA: - DoCastAOE(SPELL_LIGHTNING_NOVA, false); - events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 40000); - break; - case EVENT_OVERCHARGE: - if (!summons.empty()) - { - std::list::const_iterator itr = summons.begin(); - std::advance(itr, urand(0, summons.size()-1)); - Creature *minion = Unit::GetCreature(*me, *itr); - if (minion && minion->isAlive()) - { - minion->CastSpell(me, SPELL_OVERCHARGED, true); - minion->SetHealth(minion->GetMaxHealth()); - DoScriptText(EMOTE_OVERCHARGE, me); - events.ScheduleEvent(EVENT_OVERCHARGE, 45000); - } - } - break; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - DoScriptText(EMOTE_BERSERK, me); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -/*###### -## Tempest Minion -######*/ -struct mob_tempest_minionAI : public ScriptedAI -{ - mob_tempest_minionAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - EventMap events; - - uint32 uiOverchargedTimer; - - void Reset() - { - events.Reset(); - - uiOverchargedTimer = 0; - } - - void JustDied(Unit* /*Killer*/) - { - if (Creature *pEmalon = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EMALON) : 0)) - { - if (pEmalon->isAlive()) - { - pEmalon->SummonCreature(MOB_TEMPEST_MINION, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoScriptText(EMOTE_MINION_RESPAWN, me); - } - } - } - - void EnterCombat(Unit * who) - { - DoZoneInCombat(); - events.ScheduleEvent(EVENT_SHOCK, 20000); - - if (Creature *pEmalon = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EMALON) : 0)) - { - if (!pEmalon->getVictim() && pEmalon->AI()) - pEmalon->AI()->AttackStart(who); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (Aura *overchargedAura = me->GetAura(SPELL_OVERCHARGED)) - { - if (overchargedAura->GetStackAmount() < 10) - { - if (uiOverchargedTimer <= diff) - { - DoCast(me, SPELL_OVERCHARGED); - uiOverchargedTimer = 2000; - } else uiOverchargedTimer -=diff; - } - else - { - if (overchargedAura->GetStackAmount() == 10) - { - DoCast(me, SPELL_OVERCHARGED_BLAST); - me->ForcedDespawn(); - DoScriptText(EMOTE_MINION_RESPAWN, me); - } - } - } - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHOCK: - DoCast(me->getVictim(), SPELL_SHOCK); - events.ScheduleEvent(EVENT_SHOCK, 20000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_tempest_minion(Creature *_Creature) -{ - return new mob_tempest_minionAI (_Creature); -} - -CreatureAI* GetAI_boss_emalon(Creature *_Creature) -{ - return new boss_emalonAI (_Creature); -} - -void AddSC_boss_emalon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_emalon"; - newscript->GetAI = &GetAI_boss_emalon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tempest_minion"; - newscript->GetAI = &GetAI_mob_tempest_minion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/vault_of_archavon/boss_koralon.cpp b/src/server/scripts/northrend/vault_of_archavon/boss_koralon.cpp deleted file mode 100644 index 61843647136..00000000000 --- a/src/server/scripts/northrend/vault_of_archavon/boss_koralon.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2009-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*** SQL START *** -UPDATE `creature_template` SET `ScriptName`='boss_koralon' WHERE `entry`='35013'; -UPDATE `creature_template` SET `ScriptName`='mob_flame_warder' WHERE `entry`='35143'; -*** SQL END ***/ - -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -enum Events -{ - EVENT_NONE, - - // Koralon - EVENT_BURNING_BREATH, - EVENT_BURNING_FURY, - EVENT_FLAME_CINDER_A, - EVENT_METEOR_FISTS_A, - EVENT_METEOR_FISTS_B, - - // Flame Warder - EVENT_FW_LAVA_BIRST, - EVENT_FW_METEOR_FISTS_A, - EVENT_FW_METEOR_FISTS_B, -}; - -enum Spells -{ - // Spells Koralon - SPELL_BURNING_BREATH = 66665, - SPELL_BURNING_BREATH_H = 67328, - SPELL_BURNING_FURY = 66721, - SPELL_FLAME_CINDER_A = 66684, - SPELL_FLAME_CINDER_A_H = 67332, - SPELL_FLAME_CINDER_B = 66681, // don't know the real relation to SPELL_FLAME_CINDER_A atm. - SPELL_METEOR_FISTS_A = 66725, - SPELL_METEOR_FISTS_A_H = 66765, - SPELL_METEOR_FISTS_B = 67333, - SPELL_METEOR_FISTS_B_H = 68161, - - // Spells Flame Warder - SPELL_FW_LAVA_BIRST = 66813, - SPELL_FW_LAVA_BIRST_H = 67330, - SPELL_FW_METEOR_FISTS_A = 66808, - SPELL_FW_METEOR_FISTS_A_H = 66809, - SPELL_FW_METEOR_FISTS_B = 67331, - SPELL_FW_METEOR_FISTS_B_H = 68160, -}; - -struct boss_koralonAI : public ScriptedAI -{ - boss_koralonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_KORALON_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit* /*Victim*/) {} - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_KORALON_EVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - - DoCast(me, SPELL_BURNING_FURY); - - events.ScheduleEvent(EVENT_BURNING_FURY, 20000); // TODO check timer - events.ScheduleEvent(EVENT_BURNING_BREATH, 15000); // 1st after 15sec, then every 45sec - events.ScheduleEvent(EVENT_METEOR_FISTS_A, 75000); // 1st after 75sec, then every 45sec - events.ScheduleEvent(EVENT_FLAME_CINDER_A, 30000); // TODO check timer - - if (pInstance) - pInstance->SetData(DATA_KORALON_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BURNING_FURY: - DoCast(me, SPELL_BURNING_FURY); - events.ScheduleEvent(EVENT_BURNING_FURY, 20000); - return; - case EVENT_BURNING_BREATH: - DoCast(me, RAID_MODE(SPELL_BURNING_BREATH,SPELL_BURNING_BREATH_H)); - events.ScheduleEvent(EVENT_BURNING_BREATH, 45000); - return; - case EVENT_METEOR_FISTS_A: - DoCast(me, RAID_MODE(SPELL_METEOR_FISTS_A,SPELL_METEOR_FISTS_A_H)); - events.ScheduleEvent(EVENT_METEOR_FISTS_B, 1500); - return; - case EVENT_METEOR_FISTS_B: - DoCast(me, RAID_MODE(SPELL_METEOR_FISTS_B,SPELL_METEOR_FISTS_B_H)); - events.ScheduleEvent(EVENT_METEOR_FISTS_A, 45000); - return; - case EVENT_FLAME_CINDER_A: - DoCast(me, RAID_MODE(SPELL_FLAME_CINDER_A,SPELL_FLAME_CINDER_A_H)); - events.ScheduleEvent(EVENT_FLAME_CINDER_A, 30000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -/*###### -## Mob Flame Warder -######*/ -struct mob_flame_warderAI : public ScriptedAI -{ - mob_flame_warderAI(Creature *c) : ScriptedAI(c) {} - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - - events.ScheduleEvent(EVENT_FW_LAVA_BIRST, 5000); - events.ScheduleEvent(EVENT_FW_METEOR_FISTS_A, 10000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FW_LAVA_BIRST: - DoCast(me->getVictim(), RAID_MODE(SPELL_FW_LAVA_BIRST,SPELL_FW_LAVA_BIRST_H)); - events.ScheduleEvent(EVENT_FW_LAVA_BIRST, 15000); - return; - case EVENT_FW_METEOR_FISTS_A: - DoCast(me, RAID_MODE(SPELL_FW_METEOR_FISTS_A,SPELL_FW_METEOR_FISTS_A_H)); - events.ScheduleEvent(EVENT_FW_METEOR_FISTS_B, 1500); - return; - case EVENT_FW_METEOR_FISTS_B: - DoCast(me, RAID_MODE(SPELL_FW_METEOR_FISTS_B,SPELL_FW_METEOR_FISTS_B_H)); - events.ScheduleEvent(EVENT_FW_METEOR_FISTS_A, 20000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_koralon(Creature* pCreature) -{ - return new boss_koralonAI (pCreature); -} - -CreatureAI* GetAI_mob_flame_warder(Creature* pCreature) -{ - return new mob_flame_warderAI (pCreature); -} - -void AddSC_boss_koralon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_koralon"; - newscript->GetAI = &GetAI_boss_koralon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flame_warder"; - newscript->GetAI = &GetAI_mob_flame_warder; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/vault_of_archavon/boss_toravon.cpp b/src/server/scripts/northrend/vault_of_archavon/boss_toravon.cpp deleted file mode 100644 index 2e16f9211d2..00000000000 --- a/src/server/scripts/northrend/vault_of_archavon/boss_toravon.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (C) 2009-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*** SQL START *** -UPDATE `creature_template` SET `ScriptName`='boss_toravon' WHERE `entry`='38433'; -UPDATE `creature_template` SET `ScriptName`='mob_frost_warder' WHERE `entry`='38482'; -UPDATE `creature_template` SET `ScriptName`='mob_frozen_orb_stalker' WHERE `entry`='38461'; -UPDATE `creature_template` SET `ScriptName`='mob_frozen_orb' WHERE `entry`='38456'; -*** SQL END ***/ - -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -// Spells Toravon -#define SPELL_FREEZING_GROUND RAID_MODE(72090,72104) // don't know cd... using 20 secs. -#define SPELL_FROZEN_ORB RAID_MODE(72091,72095) -#define SPELL_WHITEOUT RAID_MODE(72034,72096) // Every 38 sec. cast. (after SPELL_FROZEN_ORB) -#define SPELL_FROZEN_MALLET 71993 - -// Spells Frost Warder -#define SPELL_FROST_BLAST RAID_MODE(72123,72124) // don't know cd... using 20 secs. -#define SPELL_FROZEN_MALLET 72122 - -// Spell Frozen Orb -#define SPELL_FROZEN_ORB_DMG 72081 // priodic dmg aura -#define SPELL_FROZEN_ORB_AURA 72067 // make visible - -// Spell Frozen Orb Stalker -#define SPELL_FROZEN_ORB_SUMMON 72093 // summon orb - -// Events boss -#define EVENT_FREEZING_GROUND 1 -#define EVENT_FROZEN_ORB 2 -#define EVENT_WHITEOUT 3 - -// Events mob -#define EVENT_FROST_BLAST 4 - -// Mob Frozen Orb -#define MOB_FROZEN_ORB 38456 // 1 in 10 mode and 3 in 25 mode - -struct boss_toravonAI : public ScriptedAI -{ - boss_toravonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_TORAVON_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit* /*Victim*/) {} - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_TORAVON_EVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - - DoCast(me, SPELL_FROZEN_MALLET); - - events.ScheduleEvent(EVENT_FROZEN_ORB, 11000); - events.ScheduleEvent(EVENT_WHITEOUT, 13000); - events.ScheduleEvent(EVENT_FREEZING_GROUND, 15000); - - if (pInstance) - pInstance->SetData(DATA_TORAVON_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROZEN_ORB: - DoCast(me, SPELL_FROZEN_ORB); - events.ScheduleEvent(EVENT_FROZEN_ORB, 38000); - return; - case EVENT_WHITEOUT: - DoCast(me, SPELL_WHITEOUT); - events.ScheduleEvent(EVENT_WHITEOUT, 38000); - return; - case EVENT_FREEZING_GROUND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FREEZING_GROUND); - events.ScheduleEvent(EVENT_FREEZING_GROUND, 20000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -/*###### -## Mob Frost Warder -######*/ -struct mob_frost_warderAI : public ScriptedAI -{ - mob_frost_warderAI(Creature *c) : ScriptedAI(c) {} - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - - DoCast(me, SPELL_FROZEN_MALLET); - - events.ScheduleEvent(EVENT_FROST_BLAST, 5000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROST_BLAST: - DoCast(me->getVictim(), SPELL_FROST_BLAST); - events.ScheduleEvent(EVENT_FROST_BLAST, 20000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - - -/*###### -## Mob Frozen Orb -######*/ -struct mob_frozen_orbAI : public ScriptedAI -{ - mob_frozen_orbAI(Creature *c) : ScriptedAI(c) {} - - bool done; - uint32 killtimer; - - void Reset() - { - done = false; - killtimer = 60000; // if after this time there is no victim -> destroy! - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!done) - { - DoCast(me, SPELL_FROZEN_ORB_AURA, true); - DoCast(me, SPELL_FROZEN_ORB_DMG, true); - done = true; - } - - if (killtimer <= diff) - { - if (!UpdateVictim()) - me->ForcedDespawn(); - killtimer = 10000; - } - else - killtimer -= diff; - } -}; - -/*###### -## Mob Frozen Orb Stalker -######*/ -struct mob_frozen_orb_stalkerAI : public Scripted_NoMovementAI -{ - mob_frozen_orb_stalkerAI(Creature* c) : Scripted_NoMovementAI(c) - { - c->SetVisibility(VISIBILITY_OFF); - c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); - c->SetReactState(REACT_PASSIVE); - - pInstance = c->GetInstanceData(); - spawned = false; - } - - ScriptedInstance *pInstance; - bool spawned; - - void UpdateAI(const uint32 /*diff*/) - { - if (spawned) - return; - - spawned = true; - if (!pInstance) - return; - - Unit* pToravon = me->GetCreature(*me, pInstance->GetData64(DATA_TORAVON)); - if (!pToravon) - return; - - uint8 num_orbs = RAID_MODE(1, 3); - for (uint8 i=0; iGetNearPoint(pToravon, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 10.0f, 0.0f); - me->SetPosition(pos, true); - DoCast(me, SPELL_FROZEN_ORB_SUMMON); - } - } -}; - -CreatureAI* GetAI_boss_toravon(Creature* pCreature) -{ - return new boss_toravonAI (pCreature); -} - -CreatureAI* GetAI_mob_frost_warder(Creature* pCreature) -{ - return new mob_frost_warderAI (pCreature); -} - -CreatureAI* GetAI_mob_frozen_orb(Creature* pCreature) -{ - return new mob_frozen_orbAI (pCreature); -} - -CreatureAI* GetAI_mob_frozen_orb_stalker(Creature* pCreature) -{ - return new mob_frozen_orb_stalkerAI (pCreature); -} - -void AddSC_boss_toravon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_toravon"; - newscript->GetAI = &GetAI_boss_toravon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frost_warder"; - newscript->GetAI = &GetAI_mob_frost_warder; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frozen_orb"; - newscript->GetAI = &GetAI_mob_frozen_orb; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frozen_orb_stalker"; - newscript->GetAI = &GetAI_mob_frozen_orb_stalker; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp b/src/server/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp deleted file mode 100644 index a7183921cce..00000000000 --- a/src/server/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -#define ENCOUNTERS 4 - -/* Vault of Archavon encounters: -1 - Archavon the Stone Watcher event -2 - Emalon the Storm Watcher event -3 - Koralon the Flame Watcher event -4 - Toravon the Ice Watcher event -*/ - -struct instance_archavon : public ScriptedInstance -{ - instance_archavon(Map *Map) : ScriptedInstance(Map) {}; - - uint32 uiEncounters[ENCOUNTERS]; - - uint64 uiArchavon; - uint64 uiEmalon; - uint64 uiKoralon; - uint64 uiToravon; - - void Initialize() - { - uiArchavon = 0; - uiEmalon = 0; - uiKoralon = 0; - uiToravon = 0; - - for (uint8 i = 0; i < ENCOUNTERS; i++) - uiEncounters[i] = NOT_STARTED; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < ENCOUNTERS; i++) - if (uiEncounters[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature *creature, bool /*add*/) - { - switch(creature->GetEntry()) - { - case CREATURE_ARCHAVON: uiArchavon = creature->GetGUID(); break; - case CREATURE_EMALON: uiEmalon = creature->GetGUID(); break; - case CREATURE_KORALON: uiKoralon = creature->GetGUID(); break; - case CREATURE_TORAVON: uiToravon = creature->GetGUID(); break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_ARCHAVON_EVENT: return uiEncounters[0]; - case DATA_EMALON_EVENT: return uiEncounters[1]; - case DATA_KORALON_EVENT: return uiEncounters[2]; - case DATA_TORAVON_EVENT: return uiEncounters[3]; - } - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_ARCHAVON: return uiArchavon; - case DATA_EMALON: return uiEmalon; - case DATA_KORALON: return uiKoralon; - case DATA_TORAVON: return uiToravon; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_ARCHAVON_EVENT: uiEncounters[0] = data; break; - case DATA_EMALON_EVENT: uiEncounters[1] = data; break; - case DATA_KORALON_EVENT: uiEncounters[2] = data; break; - case DATA_TORAVON_EVENT: uiEncounters[3] = data; break; - } - - if (data == DONE) - SaveToDB(); - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << uiEncounters[0] << " " << uiEncounters[1] << " " << uiEncounters[2] << " " << uiEncounters[3]; - - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream stream(in); - stream >> uiEncounters[0] >> uiEncounters[1] >> uiEncounters[2] >> uiEncounters[3]; - - for (uint8 i = 0; i < ENCOUNTERS; ++i) - if (uiEncounters[i] == IN_PROGRESS) - uiEncounters[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_archavon(Map* map) -{ - return new instance_archavon(map); -} - -void AddSC_instance_archavon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_archavon"; - newscript->GetInstanceData = &GetInstanceData_instance_archavon; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/vault_of_archavon/vault_of_archavon.h b/src/server/scripts/northrend/vault_of_archavon/vault_of_archavon.h deleted file mode 100644 index 6aa642ff701..00000000000 --- a/src/server/scripts/northrend/vault_of_archavon/vault_of_archavon.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef DEF_ARCHAVON_H -#define DEF_ARCHAVON_H - -enum Creatures -{ - CREATURE_ARCHAVON = 31125, - CREATURE_EMALON = 33993, - CREATURE_KORALON = 35013, - CREATURE_TORAVON = 38433, -}; - -enum Data -{ - DATA_ARCHAVON_EVENT, - DATA_EMALON_EVENT, - DATA_KORALON_EVENT, - DATA_TORAVON_EVENT, -}; - -enum Data64 -{ - DATA_ARCHAVON, - DATA_EMALON, - DATA_KORALON, - DATA_TORAVON, -}; - -#endif diff --git a/src/server/scripts/northrend/violet_hold/boss_cyanigosa.cpp b/src/server/scripts/northrend/violet_hold/boss_cyanigosa.cpp deleted file mode 100644 index 589e69a6f18..00000000000 --- a/src/server/scripts/northrend/violet_hold/boss_cyanigosa.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* Script Data Start -SDName: Boss cyanigosa -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_ARCANE_VACUUM = 58694, - SPELL_BLIZZARD = 58693, - H_SPELL_BLIZZARD = 59369, - SPELL_MANA_DESTRUCTION = 59374, - SPELL_TAIL_SWEEP = 58690, - H_SPELL_TAIL_SWEEP = 59283, - SPELL_UNCONTROLLABLE_ENERGY = 58688, - H_SPELL_UNCONTROLLABLE_ENERGY = 59281, - SPELL_TRANSFORM = 58668 -}; - -enum Yells -{ - SAY_AGGRO = -1608000, - SAY_SLAY_1 = -1608001, - SAY_SLAY_2 = -1608002, - SAY_SLAY_3 = -1608003, - SAY_DEATH = -1608004, - SAY_SPAWN = -1608005, - SAY_DISRUPTION = -1608006, - SAY_BREATH_ATTACK = -1608007, - SAY_SPECIAL_ATTACK_1 = -1608008, - SAY_SPECIAL_ATTACK_2 = -1608009 -}; - -struct boss_cyanigosaAI : public ScriptedAI -{ - boss_cyanigosaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiArcaneVacuumTimer; - uint32 uiBlizzardTimer; - uint32 uiManaDestructionTimer; - uint32 uiTailSweepTimer; - uint32 uiUncontrollableEnergyTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiArcaneVacuumTimer = 10000; - uiBlizzardTimer = 15000; - uiManaDestructionTimer = 30000; - uiTailSweepTimer = 20000; - uiUncontrollableEnergyTimer = 25000; - if (pInstance) - pInstance->SetData(DATA_CYANIGOSA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_TRANSFORM); - - if (pInstance) - pInstance->SetData(DATA_CYANIGOSA_EVENT, IN_PROGRESS); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (pInstance && pInstance->GetData(DATA_REMOVE_NPC) == 1) - { - me->ForcedDespawn(); - pInstance->SetData(DATA_REMOVE_NPC, 0); - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiArcaneVacuumTimer <= diff) - { - DoCast(SPELL_ARCANE_VACUUM); - uiArcaneVacuumTimer = 10000; - } else uiArcaneVacuumTimer -= diff; - - if (uiBlizzardTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BLIZZARD); - uiBlizzardTimer = 15000; - } else uiBlizzardTimer -= diff; - - if (uiTailSweepTimer <= diff) - { - DoCast(SPELL_TAIL_SWEEP); - uiTailSweepTimer = 20000; - } else uiTailSweepTimer -= diff; - - if (uiUncontrollableEnergyTimer <= diff) - { - DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY); - uiUncontrollableEnergyTimer = 25000; - } else uiUncontrollableEnergyTimer -= diff; - - if (IsHeroic()) - if (uiManaDestructionTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_MANA_DESTRUCTION); - uiManaDestructionTimer = 30000; - } else uiManaDestructionTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_CYANIGOSA_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_cyanigosa(Creature* pCreature) -{ - return new boss_cyanigosaAI (pCreature); -} - -void AddSC_boss_cyanigosa() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_cyanigosa"; - newscript->GetAI = &GetAI_boss_cyanigosa; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/boss_erekem.cpp b/src/server/scripts/northrend/violet_hold/boss_erekem.cpp deleted file mode 100644 index a9cc7393af4..00000000000 --- a/src/server/scripts/northrend/violet_hold/boss_erekem.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* Script Data Start -SDName: Boss erekem -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_BLOODLUST = 54516, - SPELL_BREAK_BONDS = 59463, - SPELL_CHAIN_HEAL = 54481, - H_SPELL_CHAIN_HEAL = 59473, - SPELL_EARTH_SHIELD = 54479, - H_SPELL_EARTH_SHIELD = 59471, - SPELL_EARTH_SHOCK = 54511, - SPELL_LIGHTNING_BOLT = 53044, - SPELL_STORMSTRIKE = 51876 -}; - -enum Yells -{ - SAY_AGGRO = -1608010, - SAY_SLAY_1 = -1608011, - SAY_SLAY_2 = -1608012, - SAY_SLAY_3 = -1608013, - SAY_DEATH = -1608014, - SAY_SPAWN = -1608015, - SAY_ADD_KILLED = -1608016, - SAY_BOTH_ADDS_KILLED = -1608017 -}; - -struct boss_erekemAI : public ScriptedAI -{ - boss_erekemAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBloodlustTimer; - uint32 uiChainHealTimer; - uint32 uiEarthShockTimer; - uint32 uiLightningBoltTimer; - uint32 uiEarthShieldTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiBloodlustTimer = 15000; - uiChainHealTimer = 0; - uiEarthShockTimer = urand(2000,8000); - uiLightningBoltTimer = urand(5000,10000); - uiEarthShieldTimer = 20000; - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - - if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) - { - if (!pGuard1->isAlive()) - pGuard1->Respawn(); - } - if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) - { - if (!pGuard2->isAlive()) - pGuard2->Respawn(); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - - if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) - { - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - if (!pGuard1->getVictim() && pGuard1->AI()) - pGuard1->AI()->AttackStart(pWho); - } - if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) - { - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - if (!pGuard2->getVictim() && pGuard2->AI()) - pGuard2->AI()->AttackStart(pWho); - } - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_EARTH_SHIELD); - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_EREKEM_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //spam stormstrike in hc mode if spawns are dead - if (IsHeroic()) - { - if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) - { - if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) - { - if (!pGuard1->isAlive() && !pGuard2->isAlive()) - DoCast(me->getVictim(), SPELL_STORMSTRIKE); - } - } - } - - if (uiEarthShieldTimer <= diff) - { - DoCast(me, SPELL_EARTH_SHIELD); - uiEarthShieldTimer = 20000; - } else uiEarthShieldTimer -= diff; - - if (uiChainHealTimer <= diff) - { - if (uint64 TargetGUID = GetChainHealTargetGUID()) - { - if (Creature *pTarget = Unit::GetCreature(*me, TargetGUID)) - DoCast(pTarget, SPELL_CHAIN_HEAL); - - //If one of the adds is dead spawn heals faster - Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0); - Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0); - uiChainHealTimer = ((pGuard1 && !pGuard1->isAlive()) || (pGuard2 && !pGuard2->isAlive()) ? 3000 : 8000) + rand()%3000; - } - } else uiChainHealTimer -= diff; - - if (uiBloodlustTimer <= diff) - { - DoCast(me, SPELL_BLOODLUST); - uiBloodlustTimer = urand(35000,45000); - } else uiBloodlustTimer -= diff; - - if (uiEarthShockTimer <= diff) - { - DoCast(me->getVictim(), SPELL_EARTH_SHOCK); - uiEarthShockTimer = urand(8000,13000); - } else uiEarthShockTimer -= diff; - - if (uiLightningBoltTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_LIGHTNING_BOLT); - uiLightningBoltTimer = urand(18000,24000); - } else uiLightningBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - uint64 GetChainHealTargetGUID() - { - if (HealthBelowPct(85)) - return me->GetGUID(); - - Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0); - if (pGuard1 && pGuard1->isAlive() && (pGuard1->GetHealth()*100 <= pGuard1->GetMaxHealth() * 75)) - return pGuard1->GetGUID(); - - Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0); - if (pGuard2 && pGuard2->isAlive() && (pGuard2->GetHealth()*100 <= pGuard2->GetMaxHealth() * 75)) - return pGuard2->GetGUID(); - - return 0; - } -}; - -CreatureAI* GetAI_boss_erekem(Creature* pCreature) -{ - return new boss_erekemAI (pCreature); -} - -enum GuardSpells -{ - SPELL_GUSHING_WOUND = 39215, - SPELL_HOWLING_SCREECH = 54462, - SPELL_STRIKE = 14516 -}; - -struct mob_erekem_guardAI : public ScriptedAI -{ - mob_erekem_guardAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiGushingWoundTimer; - uint32 uiHowlingScreechTimer; - uint32 uiStrikeTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiStrikeTimer = urand(4000,8000); - uiHowlingScreechTimer = urand(8000,13000); - uiGushingWoundTimer = urand(1000,3000); - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - - if (uiStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STRIKE); - uiStrikeTimer = urand(4000,8000); - } else uiStrikeTimer -= diff; - - if (uiHowlingScreechTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HOWLING_SCREECH); - uiHowlingScreechTimer = urand(8000,13000); - } else uiHowlingScreechTimer -= diff; - - if (uiGushingWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GUSHING_WOUND); - uiGushingWoundTimer = urand(7000,12000); - } else uiGushingWoundTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_erekem_guard(Creature* pCreature) -{ - return new mob_erekem_guardAI (pCreature); -} - -void AddSC_boss_erekem() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_erekem"; - newscript->GetAI = &GetAI_boss_erekem; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_erekem_guard"; - newscript->GetAI = &GetAI_mob_erekem_guard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/boss_ichoron.cpp b/src/server/scripts/northrend/violet_hold/boss_ichoron.cpp deleted file mode 100644 index a28bfdffb7c..00000000000 --- a/src/server/scripts/northrend/violet_hold/boss_ichoron.cpp +++ /dev/null @@ -1,394 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Boss ichoron -SDAuthor: ckegg -SD%Complete: 80% -SDComment: TODO: better spawn location for adds -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_DRAINED = 59820, - SPELL_FRENZY = 54312, - SPELL_FRENZY_H = 59522, - SPELL_PROTECTIVE_BUBBLE = 54306, - SPELL_WATER_BLAST = 54237, - SPELL_WATER_BLAST_H = 59520, - SPELL_WATER_BOLT_VOLLEY = 54241, - SPELL_WATER_BOLT_VOLLEY_H = 59521, - SPELL_SPLASH = 59516, -}; - -enum IchoronCreatures -{ - NPC_ICHOR_GLOBULE = 29321, -}; - -enum Yells -{ - SAY_AGGRO = -1608018, - SAY_SLAY_1 = -1608019, - SAY_SLAY_2 = -1608020, - SAY_SLAY_3 = -1608021, - SAY_DEATH = -1608022, - SAY_SPAWN = -1608023, - SAY_ENRAGE = -1608024, - SAY_SHATTER = -1608025, - SAY_BUBBLE = -1608026 -}; - -enum Achievements -{ - ACHIEVEMENT_DEHYDRATION = 2041, -}; - -enum Actions -{ - ACTION_WATER_ELEMENT_HIT = 1, - ACTION_WATER_ELEMENT_KILLED = 2, -}; - -// TODO get those positions from spawn of creature 29326 -#define MAX_SPAWN_LOC 5 -static Position SpawnLoc[MAX_SPAWN_LOC]= -{ - {1840.64, 795.407, 44.079, 1.676}, - {1886.24, 757.733, 47.750, 5.201}, - {1877.91, 845.915, 43.417, 3.560}, - {1918.97, 850.645, 47.225, 4.136}, - {1935.50, 796.224, 52.492, 4.224}, -}; - -struct boss_ichoronAI : public ScriptedAI -{ - boss_ichoronAI(Creature* pCreature) : ScriptedAI(pCreature), m_waterElements(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - bool bIsExploded; - bool bIsFrenzy; - bool bAchievement; - - uint32 uiBubbleCheckerTimer; - uint32 uiWaterBoltVolleyTimer; - - ScriptedInstance* pInstance; - - SummonList m_waterElements; - - void Reset() - { - bIsExploded = false; - bIsFrenzy = false; - bAchievement = true; - uiBubbleCheckerTimer = 1000; - uiWaterBoltVolleyTimer = urand(10000, 15000); - - me->SetVisibility(VISIBILITY_ON); - DespawnWaterElements(); - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - DoCast(me, SPELL_PROTECTIVE_BUBBLE); - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ICHORON_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void DoAction(const int32 param) - { - if (!me->isAlive()) - return; - - switch(param) - { - case ACTION_WATER_ELEMENT_HIT: - me->SetHealth(me->GetHealth() + me->GetMaxHealth() * 0.01); - - if (bIsExploded) - DoExplodeCompleted(); - - bAchievement = false; - break; - case ACTION_WATER_ELEMENT_KILLED: - uint32 damage = (me->GetMaxHealth()*3)/100; - me->SetHealth(me->GetHealth() - damage); - me->LowerPlayerDamageReq(damage); - break; - } - } - - void DespawnWaterElements() - { - m_waterElements.DespawnAll(); - } - - // call when explode shall stop. - // either when "hit" by a bubble, or when there is no bubble left. - void DoExplodeCompleted() - { - bIsExploded = false; - - if (!HealthBelowPct(25)) - { - DoScriptText(SAY_BUBBLE, me); - DoCast(me, SPELL_PROTECTIVE_BUBBLE, true); - } - - me->SetVisibility(VISIBILITY_ON); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - - void MoveInLineOfSight(Unit* /*pWho*/) {} - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded) - { - DoScriptText(SAY_ENRAGE, me); - DoCast(me, SPELL_FRENZY, true); - bIsFrenzy = true; - } - - if (!bIsFrenzy) - { - if (uiBubbleCheckerTimer <= uiDiff) - { - if (!bIsExploded) - { - if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE, 0)) - { - DoScriptText(SAY_SHATTER, me); - DoCast(me, SPELL_WATER_BLAST); - DoCast(me, SPELL_DRAINED); - bIsExploded = true; - me->AttackStop(); - me->SetVisibility(VISIBILITY_OFF); - for (uint8 i = 0; i < 10; i++) - { - int tmp = urand(0, MAX_SPAWN_LOC-1); - me->SummonCreature(NPC_ICHOR_GLOBULE, SpawnLoc[tmp], TEMPSUMMON_CORPSE_DESPAWN); - } - } - } - else - { - bool bIsWaterElementsAlive = false; - if (!m_waterElements.empty()) - { - for (std::list::const_iterator itr = m_waterElements.begin(); itr != m_waterElements.end(); ++itr) - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - if (pTemp->isAlive()) - { - bIsWaterElementsAlive = true; - break; - } - } - - if (!bIsWaterElementsAlive) - DoExplodeCompleted(); - } - uiBubbleCheckerTimer = 1000; - } - else uiBubbleCheckerTimer -= uiDiff; - } - - if (!bIsExploded) - { - if (uiWaterBoltVolleyTimer <= uiDiff) - { - DoCast(me, SPELL_WATER_BOLT_VOLLEY); - uiWaterBoltVolleyTimer = urand(10000, 15000); - } - else uiWaterBoltVolleyTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (bIsExploded) - { - bIsExploded = false; - me->SetVisibility(VISIBILITY_ON); - } - - DespawnWaterElements(); - - if (pInstance) - { - if (IsHeroic() && bAchievement) - pInstance->DoCompleteAchievement(ACHIEVEMENT_DEHYDRATION); - - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->SetSpeed(MOVE_RUN, 0.3f); - pSummoned->GetMotionMaster()->MoveFollow(me, 0, 0); - m_waterElements.push_back(pSummoned->GetGUID()); - } - - - void SummonedCreatureDespawn(Creature *pSummoned) - { - m_waterElements.remove(pSummoned->GetGUID()); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_ichoron(Creature* pCreature) -{ - return new boss_ichoronAI (pCreature); -} - -struct mob_ichor_globuleAI : public ScriptedAI -{ - mob_ichor_globuleAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiRangeCheck_Timer; - - void Reset() - { - uiRangeCheck_Timer = 1000; - } - - void AttackStart(Unit* /*pWho*/) - { - return; - } - - void UpdateAI(const uint32 uiDiff) - { - if (uiRangeCheck_Timer < uiDiff) - { - if (pInstance) - { - if (Creature* pIchoron = Unit::GetCreature(*me, pInstance->GetData64(DATA_ICHORON))) - { - if (me->IsWithinDist(pIchoron, 2.0f , false)) - { - if (pIchoron->AI()) - pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT); - me->ForcedDespawn(); - } - } - } - uiRangeCheck_Timer = 1000; - } - else uiRangeCheck_Timer -= uiDiff; - } - - void JustDied(Unit* /*pKiller*/) - { - DoCast(me, SPELL_SPLASH); - if (Creature* pIchoron = Unit::GetCreature(*me, pInstance->GetData64(DATA_ICHORON))) - if (pIchoron->AI()) - pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED); - } -}; - -CreatureAI* GetAI_mob_ichor_globule(Creature* pCreature) -{ - return new mob_ichor_globuleAI (pCreature); -} - -void AddSC_boss_ichoron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ichoron"; - newscript->GetAI = &GetAI_boss_ichoron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ichor_globule"; - newscript->GetAI = &GetAI_mob_ichor_globule; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/boss_lavanthor.cpp b/src/server/scripts/northrend/violet_hold/boss_lavanthor.cpp deleted file mode 100644 index d8cd3a4962f..00000000000 --- a/src/server/scripts/northrend/violet_hold/boss_lavanthor.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* Script Data Start -SDName: Boss lavanthor -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_CAUTERIZING_FLAMES = 59466, //Only in heroic - SPELL_FIREBOLT = 54235, - H_SPELL_FIREBOLT = 59468, - SPELL_FLAME_BREATH = 54282, - H_SPELL_FLAME_BREATH = 59469, - SPELL_LAVA_BURN = 54249, - H_SPELL_LAVA_BURN = 59594 -}; - -struct boss_lavanthorAI : public ScriptedAI -{ - boss_lavanthorAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiFireboltTimer; - uint32 uiFlameBreathTimer; - uint32 uiLavaBurnTimer; - uint32 uiCauterizingFlamesTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiFireboltTimer = 1000; - uiFlameBreathTimer = 5000; - uiLavaBurnTimer = 10000; - uiCauterizingFlamesTimer = 3000; - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_LAVANTHOR_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiFireboltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBOLT); - uiFireboltTimer = urand(5000,13000); - } else uiFireboltTimer -= diff; - - if (uiFlameBreathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAME_BREATH); - uiFlameBreathTimer = urand(10000,15000); - } else uiFlameBreathTimer -= diff; - - if (uiLavaBurnTimer <= diff) - { - DoCast(me->getVictim(), SPELL_LAVA_BURN); - uiLavaBurnTimer = urand(15000,23000); - } - - if (IsHeroic()) - { - if (uiCauterizingFlamesTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CAUTERIZING_FLAMES); - uiCauterizingFlamesTimer = urand(10000,16000); - } else uiCauterizingFlamesTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } -}; - -CreatureAI* GetAI_boss_lavanthor(Creature* pCreature) -{ - return new boss_lavanthorAI (pCreature); -} - -void AddSC_boss_lavanthor() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_lavanthor"; - newscript->GetAI = &GetAI_boss_lavanthor; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/boss_moragg.cpp b/src/server/scripts/northrend/violet_hold/boss_moragg.cpp deleted file mode 100644 index 6d283c7bfb4..00000000000 --- a/src/server/scripts/northrend/violet_hold/boss_moragg.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Script Data Start -SDName: Boss moragg -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "violet_hold.h" - -//Spells -enum Spells -{ - SPELL_CORROSIVE_SALIVA = 54527, - SPELL_OPTIC_LINK = 54396 -}; - -struct boss_moraggAI : public ScriptedAI -{ - boss_moraggAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiOpticLinkTimer; - uint32 uiCorrosiveSalivaTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiOpticLinkTimer = 10000; - uiCorrosiveSalivaTimer = 5000; - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MORAGG_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiOpticLinkTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_OPTIC_LINK); - uiOpticLinkTimer = 15000; - } else uiOpticLinkTimer -= diff; - - if (uiCorrosiveSalivaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVE_SALIVA); - uiCorrosiveSalivaTimer = 10000; - } else uiCorrosiveSalivaTimer -= diff; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT,13); - } - } - } -}; - -CreatureAI* GetAI_boss_moragg(Creature* pCreature) -{ - return new boss_moraggAI (pCreature); -} - -void AddSC_boss_moragg() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_moragg"; - newscript->GetAI = &GetAI_boss_moragg; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/boss_xevozz.cpp b/src/server/scripts/northrend/violet_hold/boss_xevozz.cpp deleted file mode 100644 index 2633705c1b7..00000000000 --- a/src/server/scripts/northrend/violet_hold/boss_xevozz.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Boss xevozz -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_ARCANE_BARRAGE_VOLLEY = 54202, - SPELL_ARCANE_BARRAGE_VOLLEY_H = 59483, - SPELL_ARCANE_BUFFET = 54226, - SPELL_ARCANE_BUFFET_H = 59485, - SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102, - SPELL_SUMMON_ETHEREAL_SPHERE_2 = 54137, - SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138, -}; - -enum NPCs -{ - NPC_ETHEREAL_SPHERE = 29271, - //NPC_ETHEREAL_SPHERE2 = 32582, // heroic only? -}; - -enum CreatureSpells -{ - SPELL_ARCANE_POWER = 54160, - H_SPELL_ARCANE_POWER = 59474, - SPELL_SUMMON_PLAYERS = 54164, - SPELL_POWER_BALL_VISUAL = 54141, -}; - -enum Yells -{ - SAY_AGGRO = -1608027, - SAY_SLAY_1 = -1608028, - SAY_SLAY_2 = -1608029, - SAY_SLAY_3 = -1608030, - SAY_DEATH = -1608031, - SAY_SPAWN = -1608032, - SAY_CHARGED = -1608033, - SAY_REPEAT_SUMMON_1 = -1608034, - SAY_REPEAT_SUMMON_2 = -1608035, - SAY_SUMMON_ENERGY = -1608036 -}; - -struct boss_xevozzAI : public ScriptedAI -{ - boss_xevozzAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiSummonEtherealSphere_Timer; - uint32 uiArcaneBarrageVolley_Timer; - uint32 uiArcaneBuffet_Timer; - - void Reset() - { - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - - uiSummonEtherealSphere_Timer = urand(10000, 12000); - uiArcaneBarrageVolley_Timer = urand(20000, 22000); - uiArcaneBuffet_Timer = uiSummonEtherealSphere_Timer + urand(5000, 6000); - DespawnSphere(); - } - - void DespawnSphere() - { - std::list assistList; - GetCreatureListWithEntryInGrid(assistList,me, NPC_ETHEREAL_SPHERE ,150.0f); - - if (assistList.empty()) - return; - - for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) - { - if (Creature* pSphere = *iter) - pSphere->Kill(pSphere, false); - } - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->SetSpeed(MOVE_RUN, 0.5f); - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - pSummoned->AddThreat(pTarget, 0.00f); - pSummoned->AI()->AttackStart(pTarget); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_XEVOZZ_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void MoveInLineOfSight(Unit* /*pWho*/) {} - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiArcaneBarrageVolley_Timer < uiDiff) - { - DoCast(me, SPELL_ARCANE_BARRAGE_VOLLEY); - uiArcaneBarrageVolley_Timer = urand(20000, 22000); - } - else uiArcaneBarrageVolley_Timer -= uiDiff; - - if (uiArcaneBuffet_Timer) - if (uiArcaneBuffet_Timer < uiDiff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BUFFET); - uiArcaneBuffet_Timer = 0; - } - else uiArcaneBuffet_Timer -= uiDiff; - - if (uiSummonEtherealSphere_Timer < uiDiff) - { - DoScriptText(SAY_SPAWN, me); - DoCast(me, SPELL_SUMMON_ETHEREAL_SPHERE_1); - if (IsHeroic()) // extra one for heroic - me->SummonCreature(NPC_ETHEREAL_SPHERE, me->GetPositionX()-5+rand()%10, me->GetPositionY()-5+rand()%10, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 40000); - - uiSummonEtherealSphere_Timer = urand(45000, 47000); - uiArcaneBuffet_Timer = urand(5000, 6000); - } - else uiSummonEtherealSphere_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - DespawnSphere(); - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } - void KilledUnit(Unit* pVictim) - { - if (pVictim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_xevozz(Creature* pCreature) -{ - return new boss_xevozzAI (pCreature); -} - -struct mob_ethereal_sphereAI : public ScriptedAI -{ - mob_ethereal_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiSummonPlayers_Timer; - uint32 uiRangeCheck_Timer; - - void Reset() - { - uiSummonPlayers_Timer = urand(33000, 35000); - uiRangeCheck_Timer = 1000; - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!me->HasAura(SPELL_POWER_BALL_VISUAL)) - DoCast(me, SPELL_POWER_BALL_VISUAL); - - if (uiRangeCheck_Timer < uiDiff) - { - if (pInstance) - { - if (Creature* pXevozz = Unit::GetCreature(*me, pInstance->GetData64(DATA_XEVOZZ))) - { - float fDistance = me->GetDistance2d(pXevozz); - if (fDistance <= 3) - DoCast(pXevozz, SPELL_ARCANE_POWER); - else - DoCast(me, 35845); //Is it blizzlike? - } - } - uiRangeCheck_Timer = 1000; - } - else uiRangeCheck_Timer -= uiDiff; - - if (uiSummonPlayers_Timer < uiDiff) - { - DoCast(me, SPELL_SUMMON_PLAYERS); // not working right - - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (!PlayerList.isEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource()->isAlive()) - DoTeleportPlayer(i->getSource(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), i->getSource()->GetOrientation()); - } - - uiSummonPlayers_Timer = urand(33000, 35000); - } - else uiSummonPlayers_Timer -= uiDiff; - } -}; - -CreatureAI* GetAI_mob_ethereal_sphere(Creature* pCreature) -{ - return new mob_ethereal_sphereAI (pCreature); -} - -void AddSC_boss_xevozz() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_xevozz"; - newscript->GetAI = &GetAI_boss_xevozz; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ethereal_sphere"; - newscript->GetAI = &GetAI_mob_ethereal_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/boss_zuramat.cpp b/src/server/scripts/northrend/violet_hold/boss_zuramat.cpp deleted file mode 100644 index da75ed94fc2..00000000000 --- a/src/server/scripts/northrend/violet_hold/boss_zuramat.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* Script Data Start -SDName: Boss zuramat -SD%Complete: -SDComment: The phasemask for the voids dosen't work. -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_SHROUD_OF_DARKNESS = 54524, - H_SPELL_SHROUD_OF_DARKNESS = 59745, - SPELL_SUMMON_VOID_SENTRY = 54369, - SPELL_VOID_SHIFT = 54361, - H_SPELL_VOID_SHIFT = 59743, - - SPELL_ZURAMAT_ADD_2 = 54342, - H_SPELL_ZURAMAT_ADD_2 = 59747 -}; - -enum ZuramatCreatures -{ - CREATURE_VOID_SENTRY = 29364 -}; - -enum Yells -{ - SAY_AGGRO = -1608037, - SAY_SLAY_1 = -1608038, - SAY_SLAY_2 = -1608039, - SAY_SLAY_3 = -1608040, - SAY_DEATH = -1608041, - SAY_SPAWN = -1608042, - SAY_SHIELD = -1608043, - SAY_WHISPER = -1608044 -}; - -struct boss_zuramatAI : public ScriptedAI -{ - boss_zuramatAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 SpellVoidShiftTimer; - uint32 SpellSummonVoidTimer; - uint32 SpellShroudOfDarknessTimer; - - void Reset() - { - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - - SpellShroudOfDarknessTimer = 22000; - SpellVoidShiftTimer = 15000; - SpellSummonVoidTimer = 12000; - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ZURAMAT_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (SpellSummonVoidTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SUMMON_VOID_SENTRY, false); - SpellSummonVoidTimer = 20000; - } else SpellSummonVoidTimer -=diff; - - if (SpellVoidShiftTimer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_VOID_SHIFT); - SpellVoidShiftTimer = 20000; - } else SpellVoidShiftTimer -=diff; - - if (SpellShroudOfDarknessTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHROUD_OF_DARKNESS); - SpellShroudOfDarknessTimer = 20000; - } else SpellShroudOfDarknessTimer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustSummoned(Creature* summon) - { - summon->AI()->AttackStart(me->getVictim()); - summon->AI()->DoCastAOE(SPELL_ZURAMAT_ADD_2); - summon->SetPhaseMask(17,true); - } -}; - -CreatureAI* GetAI_boss_zuramat(Creature* pCreature) -{ - return new boss_zuramatAI (pCreature); -} - -void AddSC_boss_zuramat() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_zuramat"; - newscript->GetAI = &GetAI_boss_zuramat; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/instance_violet_hold.cpp b/src/server/scripts/northrend/violet_hold/instance_violet_hold.cpp deleted file mode 100644 index 781511f940b..00000000000 --- a/src/server/scripts/northrend/violet_hold/instance_violet_hold.cpp +++ /dev/null @@ -1,528 +0,0 @@ -#include "ScriptedPch.h" -#include "violet_hold.h" - -#define MAX_ENCOUNTER 3 - -/* Violet Hold encounters: -0 - First boss -1 - Second boss -2 - Cyanigosa*/ - -/* Violet hold bosses: -1 - Moragg -2 - Erekem -3 - Ichoron -4 - Lavanthor -5 - Xevozz -6 - Zuramat -7 - Cyanigosa */ - -enum GameObjects -{ - GO_MAIN_DOOR = 191723, - GO_XEVOZZ_DOOR = 191556, - GO_LAVANTHOR_DOOR = 191566, - GO_ICHORON_DOOR = 191722, - GO_ZURAMAT_DOOR = 191565, - GO_EREKEM_DOOR = 191564, - GO_EREKEM_GUARD_1_DOOR = 191563, - GO_EREKEM_GUARD_2_DOOR = 191562, - GO_MORAGG_DOOR = 191606, - GO_INTRO_ACTIVATION_CRYSTAL = 193615, - GO_ACTIVATION_CRYSTAL = 193611 -}; - -const Position PortalLocation[] = -{ - {1936.07, 803.198, 53.3749, 3.12414}, - {1877.51, 850.104, 44.6599, 4.7822 }, - {1890.64, 753.471, 48.7224, 1.71042}, - {1908.31, 809.657, 38.7037, 3.08701}, - {1918.37, 853.437, 47.1624, 4.12294}, - {1927.61, 758.436, 51.4533, 2.20891} -}; - -struct instance_violet_hold : public ScriptedInstance -{ - instance_violet_hold(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiMoragg; - uint64 uiErekem; - uint64 uiErekemGuard[2]; - uint64 uiIchoron; - uint64 uiLavanthor; - uint64 uiXevozz; - uint64 uiZuramat; - uint64 uiCyanigosa; - uint64 uiSinclari; - - uint64 uiMoraggCell; - uint64 uiErekemCell; - uint64 uiErekemLeftGuardCell; - uint64 uiErekemRightGuardCell; - uint64 uiIchoronCell; - uint64 uiLavanthorCell; - uint64 uiXevozzCell; - uint64 uiZuramatCell; - uint64 uiMainDoor; - - uint64 uiActivationCrystal[3]; - - uint32 uiActivationTimer; - - uint8 uiWaveCount; - uint8 uiLocation; - uint8 uiFirstBoss; - uint8 uiSecondBoss; - uint8 uiRemoveNpc; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - uint8 uiCountErekemGuards; - uint8 uiCountActivationCrystals; - - bool bActive; - bool bWiped; - - std::string str_data; - - void Initialize() - { - uiMoragg = 0; - uiErekem = 0; - uiIchoron = 0; - uiLavanthor = 0; - uiXevozz = 0; - uiZuramat = 0; - uiCyanigosa = 0; - uiSinclari = 0; - - uiMoraggCell = 0; - uiErekemCell = 0; - uiErekemGuard[0] = 0; - uiErekemGuard[1] = 0; - uiIchoronCell = 0; - uiLavanthorCell = 0; - uiXevozzCell = 0; - uiZuramatCell = 0; - uiMainDoor = 0; - uiRemoveNpc = 0; - - uiWaveCount = 0; - uiLocation = urand(0,5); - uiFirstBoss = 0; - uiSecondBoss = 0; - uiCountErekemGuards = 0; - uiCountActivationCrystals = 0; - - uiActivationTimer = 5000; - - bActive = false; - bWiped = false; - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - switch(pCreature->GetEntry()) - { - case CREATURE_XEVOZZ: - uiXevozz = pCreature->GetGUID(); - break; - case CREATURE_LAVANTHOR: - uiLavanthor = pCreature->GetGUID(); - break; - case CREATURE_ICHORON: - uiIchoron = pCreature->GetGUID(); - break; - case CREATURE_ZURAMAT: - uiZuramat = pCreature->GetGUID(); - break; - case CREATURE_EREKEM: - uiErekem = pCreature->GetGUID(); - break; - case CREATURE_EREKEM_GUARD: - if (uiCountErekemGuards < 2) - { - uiErekemGuard[uiCountErekemGuards++] = pCreature->GetGUID(); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - } - break; - case CREATURE_MORAGG: - uiMoragg = pCreature->GetGUID(); - break; - case CREATURE_CYANIGOSA: - uiCyanigosa = pCreature->GetGUID(); - break; - case CREATURE_SINCLARI: - uiSinclari = pCreature->GetGUID(); - break; - } - - if (add && (pCreature->GetGUID() == uiFirstBoss || pCreature->GetGUID() == uiSecondBoss)) - { - pCreature->AllLootRemovedFromCorpse(); - pCreature->RemoveLootMode(1); - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_EREKEM_GUARD_1_DOOR: - uiErekemLeftGuardCell = pGo->GetGUID(); - break; - case GO_EREKEM_GUARD_2_DOOR: - uiErekemRightGuardCell = pGo->GetGUID(); - break; - case GO_EREKEM_DOOR: - uiErekemCell = pGo->GetGUID(); - break; - case GO_ZURAMAT_DOOR: - uiZuramatCell = pGo->GetGUID(); - break; - case GO_LAVANTHOR_DOOR: - uiLavanthorCell = pGo->GetGUID(); - break; - case GO_MORAGG_DOOR: - uiMoraggCell = pGo->GetGUID(); - break; - case GO_ICHORON_DOOR: - uiIchoronCell = pGo->GetGUID(); - break; - case GO_XEVOZZ_DOOR: - uiXevozzCell = pGo->GetGUID(); - break; - case GO_MAIN_DOOR: - uiMainDoor = pGo->GetGUID(); - break; - case GO_ACTIVATION_CRYSTAL: - if (uiCountActivationCrystals < 3) - uiActivationCrystal[uiCountActivationCrystals++] = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_1ST_BOSS_EVENT: - m_auiEncounter[0] = data; - if (data == DONE) - SaveToDB(); - break; - case DATA_2ND_BOSS_EVENT: - m_auiEncounter[1] = data; - if (data == DONE) - SaveToDB(); - break; - case DATA_CYANIGOSA_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) - { - SaveToDB(); - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_ACTIVE); - } - break; - case DATA_WAVE_COUNT: - uiWaveCount = data; - bActive = true; - break; - case DATA_REMOVE_NPC: - uiRemoveNpc = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_1ST_BOSS_EVENT: return m_auiEncounter[0]; - case DATA_2ND_BOSS_EVENT: return m_auiEncounter[1]; - case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2]; - case DATA_WAVE_COUNT: return uiWaveCount; - case DATA_REMOVE_NPC: return uiRemoveNpc; - } - - return 0; - } - - void SpawnPortal() - { - if (Creature *pSinclari = instance->GetCreature(uiSinclari)) - if (Creature *pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL,PortalLocation[uiLocation],TEMPSUMMON_CORPSE_DESPAWN)) - uiLocation = (uiLocation+urand(1,5))%6; - } - - void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true) - { - Creature* pBoss = NULL; - - switch(uiBoss) - { - case BOSS_MORAGG: - HandleGameObject(uiMoraggCell,bForceRespawn); - pBoss = instance->GetCreature(uiMoragg); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - case BOSS_EREKEM: - HandleGameObject(uiErekemCell, bForceRespawn); - HandleGameObject(uiErekemRightGuardCell, bForceRespawn); - HandleGameObject(uiErekemLeftGuardCell, bForceRespawn); - - pBoss = instance->GetCreature(uiErekem); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - - if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0])) - { - if (bForceRespawn) - pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - else - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - } - - if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1])) - { - if (bForceRespawn) - pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - else - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - } - break; - case BOSS_ICHORON: - HandleGameObject(uiIchoronCell,bForceRespawn); - pBoss = instance->GetCreature(uiIchoron); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - case BOSS_LAVANTHOR: - HandleGameObject(uiLavanthorCell,bForceRespawn); - pBoss = instance->GetCreature(uiLavanthor); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - case BOSS_XEVOZZ: - HandleGameObject(uiXevozzCell,bForceRespawn); - pBoss = instance->GetCreature(uiXevozz); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - case BOSS_ZURAMAT: - HandleGameObject(uiZuramatCell,bForceRespawn); - pBoss = instance->GetCreature(uiZuramat); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - } - - if (!bForceRespawn && pBoss) - { - if (pBoss->isDead()) - { - // respawn but avoid to be looted again - pBoss->Respawn(); - pBoss->RemoveLootMode(1); - } - pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - SetData(DATA_WAVE_COUNT,0); - uiWaveCount = 0; - } - } - - void AddWave() - { - DoUpdateWorldState(WORLD_STATE_VH, 1); - DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, uiWaveCount); - DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); // TODO - - switch(uiWaveCount) - { - case 6: - if (uiFirstBoss == 0) - uiFirstBoss = urand(1,6); - StartBossEncounter(uiFirstBoss); - break; - case 12: - if (uiSecondBoss == 0) - do - { - uiSecondBoss = urand(1,6); - } while (uiSecondBoss == uiFirstBoss); - StartBossEncounter(uiSecondBoss); - break; - case 18: - { - Creature *pSinclari = instance->GetCreature(uiSinclari); - if (pSinclari) - pSinclari->SummonCreature(CREATURE_CYANIGOSA,PortalLocation[0],TEMPSUMMON_DEAD_DESPAWN); - break; - } - case 1: - { - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_READY); - } - default: - if (!bWiped) - SpawnPortal(); - bWiped = false; - break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_MORAGG: return uiMoragg; - case DATA_EREKEM: return uiErekem; - case DATA_EREKEM_GUARD_1: return uiErekemGuard[0]; - case DATA_EREKEM_GUARD_2: return uiErekemGuard[1]; - case DATA_ICHORON: return uiIchoron; - case DATA_LAVANTHOR: return uiLavanthor; - case DATA_XEVOZZ: return uiXevozz; - case DATA_ZURAMAT: return uiZuramat; - case DATA_CYANIGOSA: return uiCyanigosa; - case DATA_MORAGG_CELL: return uiMoraggCell; - case DATA_EREKEM_CELL: return uiErekemCell; - case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell; - case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell; - case DATA_ICHORON_CELL: return uiIchoronCell; - case DATA_LAVANTHOR_CELL: return uiLavanthorCell; - case DATA_XEVOZZ_CELL: return uiXevozzCell; - case DATA_ZURAMAT_CELL: return uiZuramatCell; - case DATA_MAIN_DOOR: return uiMainDoor; - case DATA_SINCLARI: return uiSinclari; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "V H " << (uint16)m_auiEncounter[0] - << " " << (uint16)m_auiEncounter[1] - << " " << (uint16)m_auiEncounter[2] - << " " << (uint16)uiFirstBoss - << " " << (uint16)uiSecondBoss; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; - - if (dataHead1 == 'V' && dataHead2 == 'H') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiFirstBoss = data3; - uiSecondBoss = data4; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - bool CheckWipe() - { - Map::PlayerList const &players = instance->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - return false; - } - - return true; - } - - void Update(uint32 diff) - { - if (!instance->HavePlayers()) - return; - - if (bActive) - { - if (uiActivationTimer < diff) - { - AddWave(); - bActive = false; - uiActivationTimer = 5000; - } else uiActivationTimer -= diff; - } - - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - if (pMainDoor->GetGoState() != GO_STATE_ACTIVE && CheckWipe()) - { - SetData(DATA_REMOVE_NPC, 1); - StartBossEncounter(uiFirstBoss, false); - StartBossEncounter(uiSecondBoss, false); - bWiped = true; - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) - { - pSinclari->DisappearAndDie(); - pSinclari->Respawn(true); - } - - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_ACTIVE); - SetData(DATA_WAVE_COUNT, 0); - } - } -}; - -InstanceData* GetInstanceData_instance_violet_hold(Map* pMap) -{ - return new instance_violet_hold(pMap); -} - -void AddSC_instance_violet_hold() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_violet_hold"; - newscript->GetInstanceData = &GetInstanceData_instance_violet_hold; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/violet_hold.cpp b/src/server/scripts/northrend/violet_hold/violet_hold.cpp deleted file mode 100644 index 49883b5dbf3..00000000000 --- a/src/server/scripts/northrend/violet_hold/violet_hold.cpp +++ /dev/null @@ -1,274 +0,0 @@ -#include "ScriptedPch.h" -#include "violet_hold.h" - -#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay." -#define GOSSIP_ITEM_1 "Activate the crystals when we get in trouble, right" -#define SPAWN_TIME 20000 - -enum PortalCreatures -{ - CREATURE_AZURE_INVADER = 30661, - CREATURE_AZURE_SPELLBREAKER = 30662, - CREATURE_AZURE_BINDER = 30663, - CREATURE_AZURE_MAGE_SLAYER = 30664, - CREATURE_AZURE_CAPTAIN = 30666, - CREATURE_AZURE_SORCEROR = 30667, - CREATURE_AZURE_RAIDER = 30668, - CREATURE_AZURE_STALKER = 32191 -}; - -enum Spells -{ - SPELL_PORTAL_CHANNEL = 58012 -}; - -enum eSinclari -{ - NPC_VIOLET_HOLD_GUARD = 30659, - - SAY_SINCLARI_1 = -1608045, -}; - -const Position DoorPosition = { 1828.300049, 797.309021, 46.135502, 1.48353}; -const Position MovePosition = { 1806.955566, 803.851807, 44.363323}; - -struct npc_sinclariAI : public ScriptedAI -{ - npc_sinclariAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiTimer; - - void Reset() - { - uiPhase = 0; - uiTimer = 0; - - me->SetVisibility(VISIBILITY_ON); - me->SetReactState(REACT_AGGRESSIVE); - - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - { - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - { - pGuard->DisappearAndDie(); - pGuard->Respawn(); - pGuard->SetVisibility(VISIBILITY_ON); - pGuard->SetReactState(REACT_AGGRESSIVE); - } - } - } - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (pInstance) - { - pInstance->SetData(DATA_WAVE_COUNT,1); - pInstance->SetData(DATA_REMOVE_NPC,0); // might not have been reset after a wipe on a boss. - } - - //She should not be despawned, she will be used by the instance to summon some npcs - me->SetVisibility(VISIBILITY_OFF); - me->SetReactState(REACT_PASSIVE); - } - - void UpdateAI(const uint32 uiDiff) - { - ScriptedAI::UpdateAI(uiDiff); - - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - DoScriptText(SAY_SINCLARI_1, me); - uiTimer = 4000; - uiPhase = 2; - break; - case 2: - { - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - { - pGuard->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pGuard->GetMotionMaster()->MovePoint(0, MovePosition); - } - } - uiTimer = 6000; - uiPhase = 3; - break; - } - case 3: - { - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - { - pGuard->SetVisibility(VISIBILITY_OFF); - pGuard->SetReactState(REACT_PASSIVE); - } - } - uiTimer = 2000; - uiPhase = 4; - break; - } - case 4: - me->GetMotionMaster()->MovePoint(0, MovePosition); - uiTimer = 0; - uiPhase = 0; - break; - } - } - else uiTimer -= uiDiff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_sinclari(Creature* pCreature) -{ - return new npc_sinclariAI(pCreature); -} - -bool GossipHello_npc_sinclari(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance && pInstance->GetData(DATA_CYANIGOSA_EVENT) != DONE && pInstance->GetData(DATA_WAVE_COUNT) == 0 && pPlayer) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_1,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_START_EVENT,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(13853, pCreature->GetGUID()); - }else - pPlayer->SEND_GOSSIP_MENU(13910, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_sinclari(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - if (pPlayer) - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_sinclariAI, (pCreature->AI()))->uiPhase = 1; - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->SEND_GOSSIP_MENU(13854, pCreature->GetGUID()); - break; - } - return true; -} - -struct npc_teleportation_portalAI : public ScriptedAI -{ - npc_teleportation_portalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiSpawnTimer; - bool bPortalGuardianOrKeeperSpawn; - - ScriptedInstance *pInstance; - - void Reset() - { - uiSpawnTimer = 10000; - bPortalGuardianOrKeeperSpawn = false; - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (pInstance && pInstance->GetData(DATA_REMOVE_NPC) == 1) - { - me->ForcedDespawn(); - pInstance->SetData(DATA_REMOVE_NPC, 0); - } - - if (uiSpawnTimer <= diff) - { - if (bPortalGuardianOrKeeperSpawn) - { - uint8 k = pInstance->GetData(DATA_WAVE_COUNT) < 12 ? 2 : 3; - for (uint8 i = 0; i < k; ++i) - { - uint32 entry = RAND(CREATURE_AZURE_CAPTAIN,CREATURE_AZURE_RAIDER,CREATURE_AZURE_STALKER,CREATURE_AZURE_SORCEROR); - if (Creature* pSummon = DoSummon(entry, me, 2.0f, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) - pSummon->GetMotionMaster()->MovePoint(0, DoorPosition); - } - } - else - { - bPortalGuardianOrKeeperSpawn = true; - uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER); - if (Creature *pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) - me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false); - } - uiSpawnTimer = SPAWN_TIME; - } else uiSpawnTimer -= diff; - - if (bPortalGuardianOrKeeperSpawn && !me->IsNonMeleeSpellCasted(false)) - { - me->Kill(me, false); - me->RemoveCorpse(); - return; - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_WAVE_COUNT,pInstance->GetData(DATA_WAVE_COUNT)+1); - } -}; - -CreatureAI* GetAI_npc_teleportation_portal(Creature *pCreature) -{ - return new npc_teleportation_portalAI(pCreature); -} - -void AddSC_violet_hold() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sinclari_vh"; - newscript->GetAI = &GetAI_npc_sinclari; - newscript->pGossipHello = &GossipHello_npc_sinclari; - newscript->pGossipSelect = &GossipSelect_npc_sinclari; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_teleportation_portal_vh"; - newscript->GetAI = &GetAI_npc_teleportation_portal; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/northrend/violet_hold/violet_hold.h b/src/server/scripts/northrend/violet_hold/violet_hold.h deleted file mode 100644 index 4476d5e823a..00000000000 --- a/src/server/scripts/northrend/violet_hold/violet_hold.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef DEF_VIOLET_HOLD_H -#define DEF_VIOLET_HOLD_H - -enum Creatures -{ - CREATURE_TELEPORTATION_PORTAL = 31011, - CREATURE_PORTAL_GUARDIAN = 30660, - CREATURE_PORTAL_KEEPER = 30695, - CREATURE_XEVOZZ = 29266, - CREATURE_LAVANTHOR = 29312, - CREATURE_ICHORON = 29313, - CREATURE_ZURAMAT = 29314, - CREATURE_EREKEM = 29315, - CREATURE_EREKEM_GUARD = 29395, - CREATURE_MORAGG = 29316, - CREATURE_CYANIGOSA = 31134, - CREATURE_SINCLARI = 30658 -}; - -enum Data -{ - DATA_1ST_BOSS_EVENT, - DATA_2ND_BOSS_EVENT, - DATA_CYANIGOSA_EVENT, - DATA_WAVE_COUNT, - DATA_REMOVE_NPC -}; - -enum Data64 -{ - DATA_MORAGG, - DATA_EREKEM, - DATA_EREKEM_GUARD_1, - DATA_EREKEM_GUARD_2, - DATA_ICHORON, - DATA_LAVANTHOR, - DATA_XEVOZZ, - DATA_ZURAMAT, - DATA_CYANIGOSA, - DATA_MORAGG_CELL, - DATA_EREKEM_CELL, - DATA_EREKEM_LEFT_GUARD_CELL, - DATA_EREKEM_RIGHT_GUARD_CELL, - DATA_ICHORON_CELL, - DATA_LAVANTHOR_CELL, - DATA_XEVOZZ_CELL, - DATA_ZURAMAT_CELL, - DATA_MAIN_DOOR, - DATA_SINCLARI -}; - -enum Bosses -{ - BOSS_NONE, // 0 used as marker for not yet randomized - BOSS_MORAGG, - BOSS_EREKEM, - BOSS_ICHORON, - BOSS_LAVANTHOR, - BOSS_XEVOZZ, - BOSS_ZURAMAT, - BOSS_CYANIGOSA -}; - -enum VHWorldStates -{ - WORLD_STATE_VH = 3816, - WORLD_STATE_VH_PRISON_STATE = 3815, - WORLD_STATE_VH_WAVE_COUNT = 3810, -}; - -#endif diff --git a/src/server/scripts/northrend/zuldrak.cpp b/src/server/scripts/northrend/zuldrak.cpp deleted file mode 100644 index a821ea4ffae..00000000000 --- a/src/server/scripts/northrend/zuldrak.cpp +++ /dev/null @@ -1,1403 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*#### -## npc_drakuru_shackles -####*/ - -enum eDrakuruShackles -{ - SPELL_LEFT_CHAIN = 59951, - SPELL_RIGHT_CHAIN = 59952, - SPELL_UNLOCK_SHACKLE = 55083, - SPELL_FREE_RAGECLAW = 55223, - - NPC_RAGECLAW = 29686 -}; - -struct npc_drakuru_shacklesAI : public ScriptedAI -{ - npc_drakuru_shacklesAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint64 RageclawGUID; - - void Reset() - { - RageclawGUID = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 0.1f); - - if (Unit* summon = me->SummonCreature(NPC_RAGECLAW, x, y, z, - 0, TEMPSUMMON_DEAD_DESPAWN, 1000)) - { - RageclawGUID = summon->GetGUID(); - LockRageclaw(); - } - } - - void LockRageclaw() - { - Unit *Rageclaw = Unit::GetCreature(*me, RageclawGUID); - // pointer check not needed - me->SetInFront(Rageclaw); - Rageclaw->SetInFront(me); - - DoCast(Rageclaw, SPELL_LEFT_CHAIN, true); - DoCast(Rageclaw, SPELL_RIGHT_CHAIN, true); - } - - void UnlockRageclaw(Unit* pWho) - { - if (!pWho) - return; - - Creature *Rageclaw = Unit::GetCreature(*me, RageclawGUID); - // pointer check not needed - DoCast(Rageclaw, SPELL_FREE_RAGECLAW, true); - - me->setDeathState(DEAD); - } - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_UNLOCK_SHACKLE) - { - if (Creature *Rageclaw = Unit::GetCreature(*me, RageclawGUID)) - UnlockRageclaw(pCaster); - else - me->setDeathState(JUST_DIED); - } - } -}; - - -CreatureAI* GetAI_npc_drakuru_shackles(Creature* pCreature) -{ - return new npc_drakuru_shacklesAI (pCreature); -} - -/*#### -## npc_captured_rageclaw -####*/ - -enum eRageclaw -{ - SPELL_UNSHACKLED = 55085, - SPELL_KNEEL = 39656 -}; - -const char * SAY_RAGECLAW_1 = "I poop on you, trollses!"; -const char * SAY_RAGECLAW_2 = "ARRRROOOOGGGGAAAA!"; -const char * SAY_RAGECLAW_3 = "No more mister nice wolvar!"; - -#define SAY_RAGECLAW RAND(SAY_RAGECLAW_1,SAY_RAGECLAW_2,SAY_RAGECLAW_3) - -struct npc_captured_rageclawAI : public ScriptedAI -{ - npc_captured_rageclawAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 DespawnTimer; - bool Despawn; - - void Reset() - { - Despawn = false; - DespawnTimer = 0; - me->setFaction(35); - DoCast(me, SPELL_KNEEL, true); // Little Hack for kneel - Thanks Illy :P - } - - void MoveInLineOfSight(Unit * /*who*/){} - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_FREE_RAGECLAW) - { - me->RemoveAurasDueToSpell(SPELL_LEFT_CHAIN); - - me->RemoveAurasDueToSpell(SPELL_RIGHT_CHAIN); - - me->RemoveAurasDueToSpell(SPELL_KNEEL); - - me->setFaction(me->GetCreatureInfo()->faction_H); - - DoCast(me, SPELL_UNSHACKLED, true); - me->MonsterSay(SAY_RAGECLAW, LANG_UNIVERSAL, NULL); - me->GetMotionMaster()->MoveRandom(10); - - DespawnTimer = 10000; - Despawn = true; - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (UpdateVictim()) - { - DoMeleeAttackIfReady(); - return; - } - - if (!Despawn) - return; - - if (DespawnTimer <= uiDiff) - me->DisappearAndDie(); - else DespawnTimer -= uiDiff; - } -}; - -CreatureAI* GetAI_npc_captured_rageclaw(Creature* pCreature) -{ - return new npc_captured_rageclawAI (pCreature); -} - -/*#### -## npc_gymer -####*/ - -#define GOSSIP_ITEM_G "I'm ready, Gymer. Let's go!" - -enum eGymer -{ - QUEST_STORM_KING_VENGEANCE = 12919, - SPELL_GYMER = 55568 -}; - -bool GossipHello_npc_gymer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_STORM_KING_VENGEANCE) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_G, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(13640, pCreature->GetGUID()); - } - - return true; -} - -bool GossipSelect_npc_gymer(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_GYMER, true); - } - - return true; -} - -/*#### -## npc_gurgthock -####*/ - -enum eGurgthock -{ - QUEST_AMPHITHEATER_ANGUISH_TUSKARRMAGEDDON = 12935, - QUEST_AMPHITHEATER_ANGUISH_KORRAK_BLOODRAGER = 12936, - QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_2 = 12954, - QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_1 = 12932, - QUEST_AMPHITHEATER_ANGUISH_MAGNATAUR = 12933, - QUEST_AMPHITHEATER_ANGUISH_FROM_BEYOND = 12934, - - NPC_ORINOKO_TUSKBREAKER = 30020, - NPC_KORRAK_BLOODRAGER = 30023, - NPC_YGGDRAS = 30014, - NPC_STINKBEARD = 30017, - NPC_AZ_BARIN = 30026, // air - NPC_DUKE_SINGEN = 30019, // fire - NPC_ERATHIUS = 30025, // earth - NPC_GARGORAL = 30024, // water - NPC_FIEND_WATER = 30044, - NPC_FIEND_AIR = 30045, - NPC_FIEND_FIRE = 30042, - NPC_FIEND_EARTH = 30043, - - SAY_QUEST_ACCEPT_TUSKARRMAGEDON = -1571031, - SAY_QUEST_ACCEPT_KORRAK_1 = -1571033, - SAY_QUEST_ACCEPT_KORRAK_2 = -1571034, - SAY_QUEST_ACCEPT_MAGNATAUR = -1571035, - - EMOTE_YGGDRAS_SPAWN = -1571039, - SAY_STINKBEARD_SPAWN = -1571040, - SAY_GURGTHOCK_ELEMENTAL_SPAWN = -1571041, - - SPELL_CRASHING_WAVE = 55909, // water - SPELL_SHOCKWAVE = 55918, // earth - SPELL_BLAST_OF_AIR = 55912, // air - SPELL_MAGMA_WAVE = 55916, // fire - - SPELL_ORB_OF_WATER = 55888, // fiend of water spell - SPELL_ORB_OF_STORMS = 55882, // fiend of air spell - SPELL_BOULDER = 55886, // fiend of earth spell - SPELL_ORB_OF_FLAME = 55872, // fiend of fire spell -}; - -struct BossAndAdd -{ - uint32 uiBoss; - uint32 uiAdd; - uint32 uiSpell; - uint32 uiAddSpell; -}; - -static BossAndAdd Boss[]= -{ - {NPC_GARGORAL,NPC_FIEND_WATER,SPELL_CRASHING_WAVE,SPELL_ORB_OF_WATER}, - {NPC_AZ_BARIN,NPC_FIEND_AIR,SPELL_BLAST_OF_AIR,SPELL_ORB_OF_STORMS}, - {NPC_DUKE_SINGEN,NPC_FIEND_FIRE,SPELL_MAGMA_WAVE,SPELL_ORB_OF_FLAME}, - {NPC_ERATHIUS,NPC_FIEND_EARTH,SPELL_SHOCKWAVE,SPELL_BOULDER}, -}; - -const Position SpawnPosition[] = -{ - {5754.692, -2939.46, 286.276123, 5.156380}, // stinkbeard || orinoko || korrak - {5762.054199, -2954.385010, 273.826955, 5.108289}, //yggdras - {5776.855, -2989.77979, 272.96814, 5.194} // elementals -}; - -const Position AddSpawnPosition[] = -{ - {5722.487, -3010.75, 312.751648, 0.478}, // caster location - {5724.983, -2969.89551, 286.359619, 0.478}, - {5733.76025, -3000.34644, 286.359619, 0.478}, - {5739.8125, -2981.524, 290.7671, 0.478}, // caster location - {5742.101, -2950.75586, 286.2643, 5.21}, - {5743.305, -3011.29736, 290.7671, 0.478}, // caster location - {5744.417, -3025.528, 286.35965, 0.478}, - {5763.189, -3029.67529, 290.7671, 0.478}, - {5769.401, -2935.121, 286.335754, 5.21}, - {5793.061, -2934.593, 286.359619, 3.53}, - {5797.32129, -2955.26855, 290.7671, 3.53}, // caster location - {5813.94531, -2956.74683, 286.359619, 3.53}, - {5816.85547, -2974.476, 290.7671, 3.53}, // caster location - {5820.30859, -3002.83716, 290.7671, 3.53}, // caster location - {5828.50244, -2981.737, 286.359619, 3.53}, - {5828.899, -2960.15479, 312.751648, 3.53}, // caster location -}; - - -struct npc_gurgthockAI : public ScriptedAI -{ - npc_gurgthockAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint64 SummonGUID; - uint64 uiPlayerGUID; - - uint32 uiTimer; - uint32 uiPhase; - uint32 uiRemoveFlagTimer; - uint32 uiQuest; - uint8 uiBossRandom; - - bool bRemoveFlag; - - void Reset() - { - SummonGUID = 0; - uiPlayerGUID = 0; - - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - uiTimer = 0; - uiPhase = 0; - uiQuest = 0; - uiRemoveFlagTimer = 5000; - - uiBossRandom = 0; - - bRemoveFlag = false; - } - - void SetGUID(const uint64 &guid, int32 id) - { - uiPlayerGUID = guid; - } - - void SetData(uint32 uiId, uint32 uiValue) - { - bRemoveFlag = true; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - - switch(uiId) - { - case 1: - switch(uiValue) - { - case QUEST_AMPHITHEATER_ANGUISH_TUSKARRMAGEDDON: - DoScriptText(SAY_QUEST_ACCEPT_TUSKARRMAGEDON, me); - uiPhase = 1; - uiTimer = 4000; - break; - case QUEST_AMPHITHEATER_ANGUISH_KORRAK_BLOODRAGER: - DoScriptText(SAY_QUEST_ACCEPT_KORRAK_1, me); - uiPhase = 3; - uiTimer = 3000; - break; - case QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_2: - case QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_1: - uiPhase = 6; - uiTimer = 3000; - break; - case QUEST_AMPHITHEATER_ANGUISH_MAGNATAUR: - uiTimer = 5000; - uiPhase = 7; - break; - case QUEST_AMPHITHEATER_ANGUISH_FROM_BEYOND: - uiTimer = 2000; - uiPhase = 12; - break; - } - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - ScriptedAI::UpdateAI(uiDiff); - - if (bRemoveFlag) - if (uiRemoveFlagTimer <= uiDiff) - { - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - bRemoveFlag = false; - - uiRemoveFlagTimer = 10000; - } else uiRemoveFlagTimer -= uiDiff; - - if (uiPhase) - { - Player* pPlayer = me->GetPlayer(uiPlayerGUID); - - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - if (Creature* pSummon = me->SummonCreature(NPC_ORINOKO_TUSKBREAKER, SpawnPosition[0], TEMPSUMMON_CORPSE_DESPAWN, 1000)) - SummonGUID = pSummon->GetGUID(); - uiPhase = 2; - uiTimer = 4000; - break; - case 2: - if (Creature* pSummon = Unit::GetCreature(*me, SummonGUID)) - pSummon->GetMotionMaster()->MoveJump(5776.319824, -2981.005371, 273.100037, 10.0f, 20.0f); - uiPhase = 0; - SummonGUID = 0; - break; - case 3: - DoScriptText(SAY_QUEST_ACCEPT_KORRAK_2, me); - uiTimer = 3000; - uiPhase = 4; - break; - case 4: - if (Creature* pSummon = me->SummonCreature(NPC_KORRAK_BLOODRAGER, SpawnPosition[0], TEMPSUMMON_CORPSE_DESPAWN, 1000)) - SummonGUID = pSummon->GetGUID(); - uiTimer = 3000; - uiPhase = 0; - break; - case 6: - { - if (!pPlayer) - return; - - std::string sText = ("The grand Amphitheater of Anguish awaits, " + std::string(pPlayer->GetName()) + ". Remember, once a battle starts you have to stay in the area. WIN OR DIE!"); - - me->MonsterSay(sText.c_str(),LANG_UNIVERSAL,0); - uiTimer = 5000; - uiPhase = 9; - } - break; - case 7: - { - if (!pPlayer) - return; - - std::string sText = ("Prepare to make you stand, " + std::string(pPlayer->GetName()) + "! Get in the Amphitheater and stand ready! Remember, you and your opponent must stay in the arena at all times or you will be disqualified!"); - me->MonsterSay(sText.c_str(),LANG_UNIVERSAL,0); - uiTimer = 3000; - uiPhase = 8; - } - break; - case 8: - DoScriptText(SAY_QUEST_ACCEPT_MAGNATAUR, me); - uiTimer = 5000; - uiPhase = 11; - break; - case 9: - { - if (!pPlayer) - return; - - std::string sText = ("Here we are once again, ladies and gentlemen. The epic struggle between life and death in the Amphitheater of Anguish! For this round we have " + std::string(pPlayer->GetName()) + " versus the hulking jormungar, Yg... Yggd? Yggdoze? Who comes up with these names?! " + std::string(pPlayer->GetName()) + " versus big worm!"); - me->MonsterYell(sText.c_str(),LANG_UNIVERSAL,0); - uiTimer = 10000; - uiPhase = 10; - } - break; - case 10: - me->SummonCreature(NPC_YGGDRAS, SpawnPosition[1], TEMPSUMMON_CORPSE_DESPAWN, 1000); - DoScriptText(EMOTE_YGGDRAS_SPAWN,me); - uiPhase = 0; - break; - case 11: - if (Creature* pCreature = me->SummonCreature(NPC_STINKBEARD, SpawnPosition[0], TEMPSUMMON_CORPSE_DESPAWN, 1000)) - DoScriptText(SAY_STINKBEARD_SPAWN,pCreature); - uiPhase = 0; - break; - case 12: - { - if (!pPlayer) - return; - - std::string sText = ("Prepare to make you stand, " + std::string(pPlayer->GetName()) + "! Get in the Amphitheater and stand ready! Remember, you and your opponent must stay in the arena at all times or you will be disqualified!"); - me->MonsterSay(sText.c_str(),LANG_UNIVERSAL,0); - uiTimer = 5000; - uiPhase = 13; - } - break; - case 13: - DoScriptText(SAY_GURGTHOCK_ELEMENTAL_SPAWN,me); - uiTimer = 3000; - uiPhase = 14; - break; - case 14: - uiBossRandom = urand(0,3); - if (Creature* pCreature = me->SummonCreature(Boss[uiBossRandom].uiBoss,SpawnPosition[2],TEMPSUMMON_CORPSE_DESPAWN, 1000)) - pCreature->AI()->SetData(1,uiBossRandom); - uiPhase = 0; - break; - } - }else uiTimer -= uiDiff; - } - } -}; - -bool QuestAccept_npc_gurgthock(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - switch (pQuest->GetQuestId()) - { - case QUEST_AMPHITHEATER_ANGUISH_TUSKARRMAGEDDON: - pCreature->AI()->SetData(1, pQuest->GetQuestId()); - break; - case QUEST_AMPHITHEATER_ANGUISH_KORRAK_BLOODRAGER: - pCreature->AI()->SetData(1, pQuest->GetQuestId()); - break; - case QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_2: - case QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_1: - pCreature->AI()->SetData(1, pQuest->GetQuestId()); - break; - case QUEST_AMPHITHEATER_ANGUISH_MAGNATAUR: - pCreature->AI()->SetData(1, pQuest->GetQuestId()); - break; - case QUEST_AMPHITHEATER_ANGUISH_FROM_BEYOND: - pCreature->AI()->SetData(1, pQuest->GetQuestId()); - break; - } - - pCreature->AI()->SetGUID(pPlayer->GetGUID()); - - return false; -} - -CreatureAI* GetAI_npc_gurgthock(Creature* pCreature) -{ - return new npc_gurgthockAI(pCreature); -} - -/*#### -## npc_orinoko_tuskbreaker -####*/ - -enum eOrinokoTuskbreaker -{ - SPELL_BATTLE_SHOUT = 32064, - SPELL_FISHY_SCENT = 55937, - SPELL_IMPALE = 55929, - SPELL_SUMMON_WHISKER = 55946, - - NPC_WHISKER = 30113, - NPC_HUNGRY_PENGUIN = 30110, - - SAY_CALL_FOR_HELP = -1571032 -}; - -struct npc_orinoko_tuskbreakerAI : public ScriptedAI -{ - npc_orinoko_tuskbreakerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - } - - bool bSummoned; - bool bBattleShout; - bool bFishyScent; - - uint32 uiBattleShoutTimer; - uint32 uiFishyScentTimer; - - uint64 AffectedGUID; - uint64 uiWhisker; - - void Reset() - { - bSummoned = false; - bBattleShout = false; - bFishyScent = false; - uiBattleShoutTimer = 0; - uiFishyScentTimer = 20000; - uiWhisker = 0; - AffectedGUID = 0; - } - - void EnterEvadeMode() - { - if (Creature *pWhisker = me->GetCreature(*me, uiWhisker)) - pWhisker->RemoveFromWorld(); - } - - void MovementInform(uint32 uiType, uint32 uiId) - { - if (uiType != POINT_MOTION_TYPE) - return; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - me->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - uiBattleShoutTimer = 7000; - } - - void EnterCombat(Unit* pWho) - { - DoCast(pWho, SPELL_IMPALE); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (!bBattleShout && uiBattleShoutTimer <= uiDiff) - { - DoCast(me, SPELL_BATTLE_SHOUT); - bBattleShout = true; - } else uiBattleShoutTimer -= uiDiff; - - if (uiFishyScentTimer <= uiDiff) - { - if (Unit *pAffected = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pAffected, SPELL_FISHY_SCENT); - AffectedGUID = pAffected->GetGUID(); - } - uiFishyScentTimer = 20000; - } else uiFishyScentTimer -= uiDiff; - - if (!bSummoned && me->GetHealth()*100 / me->GetMaxHealth() <= 50) - { - DoScriptText(SAY_CALL_FOR_HELP ,me); - //DoCast(me->getVictim(), SPELL_SUMMON_WHISKER); petai is not working correctly??? - - if (Creature *pWhisker = me->SummonCreature(NPC_WHISKER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) - uiWhisker = pWhisker->GetGUID(); - bSummoned = true; - } - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* pSummon) - { - switch(pSummon->GetEntry()) - { - case NPC_WHISKER: - pSummon->AI()->AttackStart(me->getVictim()); - break; - case NPC_HUNGRY_PENGUIN: - if (Unit *pAffected = Unit::GetUnit(*me, AffectedGUID)) - { - if (pAffected->isAlive()) - pSummon->AI()->AttackStart(pAffected); - } - break; - } - } - - void JustDied(Unit* pKiller) - { - if (uiWhisker) - if (Creature *pWhisker = me->GetCreature(*me, uiWhisker)) - pWhisker->RemoveFromWorld(); - - if (pKiller->GetTypeId() == TYPEID_PLAYER) - pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_TUSKARRMAGEDDON, pKiller); - - } -}; - -CreatureAI* GetAI_npc_orinoko_tuskbreaker(Creature* pCreature) -{ - return new npc_orinoko_tuskbreakerAI(pCreature); -} - -/*#### -## npc_korrak_bloodrager -####*/ - -enum eKorrakBloodrager -{ - SPELL_GROW = 55948, - SPELL_CHARGE = 24193, - SPELL_UPPERCUT = 30471, - SPELL_ENRAGE = 42745 -}; - -struct npc_korrak_bloodragerAI : public npc_escortAI -{ - npc_korrak_bloodragerAI(Creature* pCreature) : npc_escortAI(pCreature) - { - Start(true,true, 0, NULL); - SetDespawnAtEnd(false); - } - - uint32 uiChargeTimer; - uint32 uiUppercutTimer; - - bool bEnrage; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - uiChargeTimer = 15000; - uiUppercutTimer = 12000; - bEnrage = false; - } - - void WaypointReached(uint32 uiI) - { - switch(uiI) - { - case 6: - me->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(), 0); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - break; - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoCast(me, SPELL_GROW); - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - if (uiUppercutTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_NEAREST, 0)) - DoCast(pTarget, SPELL_UPPERCUT); - uiUppercutTimer = 12000; - } else uiUppercutTimer -= uiDiff; - - if (uiChargeTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_FARTHEST, 0)) - DoCast(pTarget, SPELL_CHARGE); - uiChargeTimer = 15000; - } else uiChargeTimer -= uiDiff; - - if (!bEnrage && me->GetHealth()*100 / me->GetMaxHealth() <= 20) - { - DoCast(me, SPELL_ENRAGE); - bEnrage = true; - } - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* pKiller) - { - if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()) - pPlayer->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_KORRAK_BLOODRAGER, pKiller); - } -}; - -CreatureAI* GetAI_npc_korrak_bloodrager(Creature* pCreature) -{ - return new npc_korrak_bloodragerAI(pCreature); -} - -/*#### -## npc_yggdras -####*/ - -enum eYggdras -{ - SPELL_CLEAVE = 40504, - SPELL_CORRODE_FLESH = 57076, - SPELL_JORMUNGAR_SPAWN = 55859 -}; - -struct npc_yggdrasAI : public ScriptedAI -{ - npc_yggdrasAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiCleaveTimer; - uint32 uiCorrodeFleshTimer; - - void Reset() - { - uiCleaveTimer = 9000; - uiCorrodeFleshTimer = 6000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (me->getVictim()->GetPositionZ() >= 286.276) - { - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - if (pUnit->GetPositionZ() <= 286.276) - { - me->getThreatManager().resetAllAggro(); - me->AddThreat(pUnit,5.0f); - break; - } - EnterEvadeMode(); - } - } - } - - if (uiCleaveTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = 9000; - } else uiCleaveTimer -= uiDiff; - - if (uiCorrodeFleshTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CORRODE_FLESH); - uiCorrodeFleshTimer = 6000; - } else uiCorrodeFleshTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* pKiller) - { - if (Unit* pSummoner = me->ToTempSummon()->GetSummoner()) - { - std::string sText = (std::string(pKiller->GetName()) + " has defeated Yg.. Yggg-really big worm!"); - pSummoner->MonsterYell(sText.c_str(),LANG_UNIVERSAL,0); - } - - - if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - pPlayer->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_1, pKiller); - pPlayer->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_YGGDRAS_2, pKiller); - } - - for (uint8 i = 0; i < 3; ++i) - DoCast(pKiller, SPELL_JORMUNGAR_SPAWN, true); - } -}; - -CreatureAI* GetAI_npc_yggdras(Creature* pCreature) -{ - return new npc_yggdrasAI(pCreature); -} - -enum eStinkbeard -{ - SPELL_ENRAGE_STINKBEARD = 50420, - SPELL_KNOCK_AWAY = 31389, - SPELL_STINKY_BEARD = 55867, - SPELL_THUNDERBLADE = 55866, - SPELL_THUNDERCLAP = 15588 -}; - -/*#### -## npc_stinkbeard -####*/ - -struct npc_stinkbeardAI : public npc_escortAI -{ - npc_stinkbeardAI(Creature* pCreature) : npc_escortAI(pCreature) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - Start(true,true, 0, NULL); - SetDespawnAtEnd(false); - } - - uint32 uiKnockAwayTimer; - uint32 uiStinkyBeardTimer; - - bool bEnrage; - bool bThunderClap; - - void Reset() - { - me->AddAura(SPELL_THUNDERBLADE,me); - uiKnockAwayTimer = 10000; - uiStinkyBeardTimer = 15000; - bEnrage = false; - bThunderClap = false; - } - - void WaypointReached(uint32 uiI) - { - switch(uiI) - { - case 7: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - if (Unit* victim = me->getVictim()) - { - if (victim->GetPositionZ() >= 286.276) - { - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - if (pUnit->GetPositionZ() <= 286.276) - { - me->getThreatManager().resetAllAggro(); - me->AddThreat(pUnit,5.0f); - break; - } - EnterEvadeMode(); - } - } - } - } - - if (bThunderClap && me->GetHealth()*100 / me->GetMaxHealth() <= 10) - { - DoCastAOE(SPELL_THUNDERCLAP); - bThunderClap = true; - } - - if (uiKnockAwayTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, SPELL_KNOCK_AWAY); - } - uiKnockAwayTimer = 10000; - } else uiKnockAwayTimer -= uiDiff; - - if (uiStinkyBeardTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, SPELL_STINKY_BEARD); - } - uiStinkyBeardTimer = 15000; - } else uiStinkyBeardTimer -= uiDiff; - - if (!bEnrage && me->GetHealth()*100 / me->GetMaxHealth() <= 20) - { - DoCast(me, SPELL_ENRAGE_STINKBEARD); - bEnrage = true; - } - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* pKiller) - { - if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()) - pPlayer->GetCharmerOrOwnerPlayerOrPlayerItself()->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_MAGNATAUR, pKiller); - - std::string sText = ("And with AUTHORITY, " + std::string(pKiller->GetName()) + " dominates the magnataur lord! Stinkbeard's clan is gonna miss him back home in the Dragonblight!"); - me->MonsterYell(sText.c_str(),LANG_UNIVERSAL,0); - } -}; - -CreatureAI* GetAI_npc_stinkbeard(Creature* pCreature) -{ - return new npc_stinkbeardAI(pCreature); -} - -/*#### -## npc_elemental_lord -####*/ - -struct npc_elemental_lordAI : public ScriptedAI -{ - npc_elemental_lordAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - std::list SummonList; - - uint32 uiElementalSpellTimer; - - uint8 uiBossRandom; - uint32 uiSpellEntry; - - bool bAddAttack; - - void Reset() - { - uiBossRandom = 0; - uiSpellEntry = 0; - uiElementalSpellTimer = urand(5000,8000); - - bAddAttack = false; - } - - void SetData(uint32 uiData, uint32 uiValue) - { - if (uiData == 1) - { - uiBossRandom = uiValue; - SummonAdds(); - } - } - - void SummonAdds() - { - if (!Boss[uiBossRandom].uiAdd) - return; - - SummonList.clear(); - - for (uint8 uiI = 0; uiI < 16 ; uiI++) - { - if (Creature* pSummon = me->SummonCreature(Boss[uiBossRandom].uiAdd,AddSpawnPosition[uiI])) - { - pSummon->AI()->SetData(1,uiBossRandom); - SummonList.push_back(pSummon->GetGUID()); - } - } - - } - - void EnterCombat(Unit* pUnit) - { - if (!SummonList.empty()) - for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - pTemp->m_CombatDistance = 100.0f; // ugly hack? we are not in a instance sorry. :( - pTemp->AI()->AttackStart(pUnit); - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (me->getVictim()->GetPositionZ() >= 286.276) - { - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - if (pUnit->GetPositionZ() <= 286.276) - { - me->getThreatManager().resetAllAggro(); - me->AddThreat(pUnit,5.0f); - break; - } - EnterEvadeMode(); - } - } - } - - if (uiElementalSpellTimer <= uiDiff) - { - DoCastVictim(Boss[uiBossRandom].uiSpell); - - uiElementalSpellTimer = urand(5000,8000); - } else uiElementalSpellTimer -= uiDiff; - - if (!bAddAttack && me->GetHealth()*100 / me->GetMaxHealth() <= 20) - { - if (!SummonList.empty()) - for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - if (pTemp->GetPositionZ() >= 287.00f) - continue; - - if (pTemp->getVictim()) - pTemp->GetMotionMaster()->MoveChase(pTemp->getVictim()); - } - } - - bAddAttack = true; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* pKiller) - { - if (!SummonList.empty()) - for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - pTemp->ForcedDespawn(); - } - - if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself()) - pPlayer->GetCharmerOrOwnerPlayerOrPlayerItself()->GroupEventHappens(QUEST_AMPHITHEATER_ANGUISH_FROM_BEYOND, pKiller); - - std::string sText = (std::string(pKiller->GetName()) + " is victorious once more!"); - - if (Unit* pSummoner = me->ToTempSummon()->GetSummoner()) - pSummoner->MonsterYell(sText.c_str(),LANG_UNIVERSAL,0); - } -}; - -CreatureAI* GetAI_npc_elemental_lord(Creature* pCreature) -{ - return new npc_elemental_lordAI(pCreature); -} - -/*#### -## npc_fiend_elemental -####*/ - -struct npc_fiend_elementalAI : public ScriptedAI -{ - npc_fiend_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiMissleTimer; - uint32 uiSpell; - - void Reset() - { - if (me->GetPositionZ() >= 287.0f) - me->GetMotionMaster()->MoveIdle(); - - uiSpell = 0; - uiMissleTimer = urand(2000,7000); - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - AttackStartNoMove(pWho); - } - - void SetData(uint32 uiData, uint32 uiValue) - { - if (uiData == 1) - uiSpell = Boss[uiValue].uiAddSpell; - - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (me->GetPositionZ() >= 287.0f) - if (uiMissleTimer <= uiDiff) - { - DoCast(me,uiSpell); // this spell is not supported ... YET! - uiMissleTimer = urand(2000,7000); - - } else uiMissleTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_fiend_elemental(Creature* pCreature) -{ - return new npc_fiend_elementalAI(pCreature); -} - -/*#### -## npc_released_offspring_harkoa -####*/ - -struct npc_released_offspring_harkoaAI : public ScriptedAI -{ - npc_released_offspring_harkoaAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - void Reset() - { - float x, y, z; - me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 25.0f); - me->GetMotionMaster()->MovePoint(0, x, y, z); - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - me->DisappearAndDie(); - } -}; - -CreatureAI* GetAI_npc_released_offspring_harkoa(Creature* pCreature) -{ - return new npc_released_offspring_harkoaAI(pCreature); -} - -/*###### -## npc_crusade_recruit -######*/ - -enum eCrusade_recruit -{ - SPELL_QUEST_CREDIT = 50633, - - QUEST_TROLL_PATROL_INTESTINAL_FORTITUDE = 12509, - - GOSSIP_CRUSADE_TEXT = 13069, - - SAY_RECRUIT_1 = -1571036, - SAY_RECRUIT_2 = -1571037, - SAY_RECRUIT_3 = -1571038 -}; - -#define GOSSIP_ITEM_1 "Get out there and make those Scourge wish they were never reborn!" - -struct npc_crusade_recruitAI : public ScriptedAI -{ - npc_crusade_recruitAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint8 m_uiPhase; //The current phase we are in - uint32 m_uiTimer; //Timer until phase transition - float m_heading; //Store creature heading - - void Reset() - { - m_uiTimer = 0; - m_uiPhase = 0; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_COWER); - m_heading = me->GetOrientation(); - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_uiPhase) - { - if (m_uiTimer <= uiDiff) - { - switch(m_uiPhase) - { - case 1: - // say random text - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - DoScriptText(RAND(SAY_RECRUIT_1,SAY_RECRUIT_2,SAY_RECRUIT_3), me); - m_uiTimer = 3000; - m_uiPhase = 2; - break; - case 2: - // walk forward - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->MovePoint(0,me->GetPositionX() + (cos(m_heading) * 10), me->GetPositionY() + (sin(m_heading) * 10), me->GetPositionZ()); - m_uiTimer = 5000; - m_uiPhase = 3; - break; - case 3: - // despawn - me->DisappearAndDie(); - m_uiTimer = 0; - m_uiPhase = 0; - break; - } - } - else - m_uiTimer -= uiDiff; - } - ScriptedAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_npc_crusade_recruit(Creature* pCreature) -{ - return new npc_crusade_recruitAI (pCreature); -} - -bool GossipHello_npc_crusade_recruit(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_TROLL_PATROL_INTESTINAL_FORTITUDE) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(GOSSIP_CRUSADE_TEXT, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_crusade_recruit(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF +1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, SPELL_QUEST_CREDIT, true); - CAST_AI(npc_crusade_recruitAI, (pCreature->AI()))->m_uiPhase = 1; - pCreature->SetInFront(pPlayer); - pCreature->SendMovementFlagUpdate(); - } - - return true; -} - -/*###### -## Quest 12916: Our Only Hope! -## go_scourge_enclosure -######*/ - -enum eScourgeEnclosure -{ - QUEST_OUR_ONLY_HOPE = 12916, - NPC_GYMER_DUMMY = 29928 //from quest template -}; - -bool GOHello_go_scourge_enclosure(Player* pPlayer, GameObject* pGO) -{ - if (pPlayer->GetQuestStatus(QUEST_OUR_ONLY_HOPE) == QUEST_STATUS_INCOMPLETE) - { - Creature* pGymerDummy = pGO->FindNearestCreature(NPC_GYMER_DUMMY,20.0f); - if (pGymerDummy) - { - pGO->UseDoorOrButton(); - pPlayer->KilledMonsterCredit(pGymerDummy->GetEntry(),pGymerDummy->GetGUID()); - pGymerDummy->CastSpell(pGymerDummy, 55529, true); - pGymerDummy->DisappearAndDie(); - } - } - return true; -} - -void AddSC_zuldrak() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_drakuru_shackles"; - newscript->GetAI = &GetAI_npc_drakuru_shackles; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_captured_rageclaw"; - newscript->GetAI = &GetAI_npc_captured_rageclaw; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_gymer"; - newscript->pGossipHello = &GossipHello_npc_gymer; - newscript->pGossipSelect = &GossipSelect_npc_gymer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_gurgthock"; - newscript->GetAI = &GetAI_npc_gurgthock; - newscript->pQuestAccept = &QuestAccept_npc_gurgthock; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_orinoko_tuskbreaker"; - newscript->GetAI = &GetAI_npc_orinoko_tuskbreaker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_korrak_bloodrager"; - newscript->GetAI = &GetAI_npc_korrak_bloodrager; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_yggdras"; - newscript->GetAI = &GetAI_npc_yggdras; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_stinkbeard"; - newscript->GetAI = &GetAI_npc_stinkbeard; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_released_offspring_harkoa"; - newscript->GetAI = &GetAI_npc_released_offspring_harkoa; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_crusade_recruit"; - newscript->GetAI = &GetAI_npc_crusade_recruit; - newscript->pGossipHello = &GossipHello_npc_crusade_recruit; - newscript->pGossipSelect = &GossipSelect_npc_crusade_recruit; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_elemental_lord"; - newscript->GetAI = &GetAI_npc_elemental_lord; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_fiend_elemental"; - newscript->GetAI = &GetAI_npc_fiend_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_scourge_enclosure"; - newscript->pGOHello = &GOHello_go_scourge_enclosure; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp b/src/server/scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp deleted file mode 100644 index bfde95ffcb0..00000000000 --- a/src/server/scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Exarch_Maladaar -SD%Complete: 95 -SDComment: Most of event implemented, some adjustments to timers remain and possibly make some better code for switching his dark side in to better "images" of player. -SDCategory: Auchindoun, Auchenai Crypts -EndScriptData */ - -/* ContentData -mob_stolen_soul -boss_exarch_maladaar -mob_avatar_of_martyred -EndContentData */ - -#include "ScriptedPch.h" - -#define SPELL_MOONFIRE 37328 -#define SPELL_FIREBALL 37329 -#define SPELL_MIND_FLAY 37330 -#define SPELL_HEMORRHAGE 37331 -#define SPELL_FROSTSHOCK 37332 -#define SPELL_CURSE_OF_AGONY 37334 -#define SPELL_MORTAL_STRIKE 37335 -#define SPELL_FREEZING_TRAP 37368 -#define SPELL_HAMMER_OF_JUSTICE 37369 - -struct mob_stolen_soulAI : public ScriptedAI -{ - mob_stolen_soulAI(Creature *c) : ScriptedAI(c) {} - - uint8 myClass; - uint32 Class_Timer; - - void Reset() - { - Class_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { } - - void SetMyClass(uint8 myclass) - { - myClass = myclass; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Class_Timer <= diff) - { - switch (myClass) - { - case CLASS_WARRIOR: - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - Class_Timer = 6000; - break; - case CLASS_PALADIN: - DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); - Class_Timer = 6000; - break; - case CLASS_HUNTER: - DoCast(me->getVictim(), SPELL_FREEZING_TRAP); - Class_Timer = 20000; - break; - case CLASS_ROGUE: - DoCast(me->getVictim(), SPELL_HEMORRHAGE); - Class_Timer = 10000; - break; - case CLASS_PRIEST: - DoCast(me->getVictim(), SPELL_MIND_FLAY); - Class_Timer = 5000; - break; - case CLASS_SHAMAN: - DoCast(me->getVictim(), SPELL_FROSTSHOCK); - Class_Timer = 8000; - break; - case CLASS_MAGE: - DoCast(me->getVictim(), SPELL_FIREBALL); - Class_Timer = 5000; - break; - case CLASS_WARLOCK: - DoCast(me->getVictim(), SPELL_CURSE_OF_AGONY); - Class_Timer = 20000; - break; - case CLASS_DRUID: - DoCast(me->getVictim(), SPELL_MOONFIRE); - Class_Timer = 10000; - break; - } - } else Class_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_stolen_soul(Creature* pCreature) -{ - return new mob_stolen_soulAI (pCreature); -} - -#define SAY_INTRO -1558000 -#define SAY_SUMMON -1558001 - -#define SAY_AGGRO_1 -1558002 -#define SAY_AGGRO_2 -1558003 -#define SAY_AGGRO_3 -1558004 - -#define SAY_ROAR -1558005 -#define SAY_SOUL_CLEAVE -1558006 - -#define SAY_SLAY_1 -1558007 -#define SAY_SLAY_2 -1558008 - -#define SAY_DEATH -1558009 - -#define SPELL_RIBBON_OF_SOULS 32422 -#define SPELL_SOUL_SCREAM 32421 - -#define SPELL_STOLEN_SOUL 32346 -#define SPELL_STOLEN_SOUL_VISUAL 32395 - -#define SPELL_SUMMON_AVATAR 32424 - -#define ENTRY_STOLEN_SOUL 18441 - -struct boss_exarch_maladaarAI : public ScriptedAI -{ - boss_exarch_maladaarAI(Creature *c) : ScriptedAI(c) - { - HasTaunted = false; - } - - uint32 soulmodel; - uint64 soulholder; - uint8 soulclass; - - uint32 Fear_timer; - uint32 Ribbon_of_Souls_timer; - uint32 StolenSoul_Timer; - - bool HasTaunted; - bool Avatar_summoned; - - void Reset() - { - soulmodel = 0; - soulholder = 0; - soulclass = 0; - - Fear_timer = 15000 + rand()% 5000; - Ribbon_of_Souls_timer = 5000; - StolenSoul_Timer = 25000 + rand()% 10000; - - Avatar_summoned = false; - } - - void MoveInLineOfSight(Unit *who) - { - if (!HasTaunted && me->IsWithinDistInMap(who, 150.0)) - { - DoScriptText(SAY_INTRO, me); - HasTaunted = true; - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == ENTRY_STOLEN_SOUL) - { - //SPELL_STOLEN_SOUL_VISUAL has shapeshift effect, but not implemented feature in Trinity for this spell. - summoned->CastSpell(summoned,SPELL_STOLEN_SOUL_VISUAL,false); - summoned->SetDisplayId(soulmodel); - summoned->setFaction(me->getFaction()); - - if (Unit *pTarget = Unit::GetUnit(*me,soulholder)) - { - - CAST_AI(mob_stolen_soulAI, summoned->AI())->SetMyClass(soulclass); - summoned->AI()->AttackStart(pTarget); - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - //When Exarch Maladar is defeated D'ore appear. - me->SummonCreature(19412, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!Avatar_summoned && ((me->GetHealth()*100) / me->GetMaxHealth() < 25)) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(SAY_SUMMON, me); - - DoCast(me, SPELL_SUMMON_AVATAR); - Avatar_summoned = true; - StolenSoul_Timer = 15000 + rand()% 15000; - } - - if (StolenSoul_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - uint32 i = urand(1,2); - if (i == 1) - DoScriptText(SAY_ROAR, me); - else - DoScriptText(SAY_SOUL_CLEAVE, me); - - soulmodel = pTarget->GetDisplayId(); - soulholder = pTarget->GetGUID(); - soulclass = pTarget->getClass(); - - DoCast(pTarget, SPELL_STOLEN_SOUL); - me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); - - StolenSoul_Timer = 20000 + rand()% 10000; - } else StolenSoul_Timer = 1000; - } - } else StolenSoul_Timer -= diff; - - if (Ribbon_of_Souls_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_RIBBON_OF_SOULS); - - Ribbon_of_Souls_timer = 5000 + (rand()%20 * 1000); - } else Ribbon_of_Souls_timer -= diff; - - if (Fear_timer <= diff) - { - DoCast(me, SPELL_SOUL_SCREAM); - Fear_timer = 15000 + rand()% 15000; - } else Fear_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_exarch_maladaar(Creature* pCreature) -{ - return new boss_exarch_maladaarAI (pCreature); -} - -#define SPELL_AV_MORTAL_STRIKE 16856 -#define SPELL_AV_SUNDER_ARMOR 16145 - -struct mob_avatar_of_martyredAI : public ScriptedAI -{ - mob_avatar_of_martyredAI(Creature *c) : ScriptedAI(c) {} - - uint32 Mortal_Strike_timer; - - void Reset() - { - Mortal_Strike_timer = 10000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Mortal_Strike_timer <= diff) - { - DoCast(me->getVictim(), SPELL_AV_MORTAL_STRIKE); - Mortal_Strike_timer = 10000 + rand()%20 * 1000; - } else Mortal_Strike_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_avatar_of_martyred(Creature* pCreature) -{ - return new mob_avatar_of_martyredAI (pCreature); -} - -void AddSC_boss_exarch_maladaar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_exarch_maladaar"; - newscript->GetAI = &GetAI_boss_exarch_maladaar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_avatar_of_martyred"; - newscript->GetAI = &GetAI_mob_avatar_of_martyred; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stolen_soul"; - newscript->GetAI = &GetAI_mob_stolen_soul; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp deleted file mode 100644 index c13e2905171..00000000000 --- a/src/server/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -Name: Boss_Shirrak_the_dead_watcher -%Complete: 80 -Comment: InhibitMagic should stack slower far from the boss, proper Visual for Focus Fire, heroic implemented -Category: Auchindoun, Auchenai Crypts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_INHIBITMAGIC 32264 -#define SPELL_ATTRACTMAGIC 32265 -#define N_SPELL_CARNIVOROUSBITE 36383 -#define H_SPELL_CARNIVOROUSBITE 39382 -#define SPELL_CARNIVOROUSBITE DUNGEON_MODE(N_SPELL_CARNIVOROUSBITE, H_SPELL_CARNIVOROUSBITE) - -#define ENTRY_FOCUS_FIRE 18374 - -#define N_SPELL_FIERY_BLAST 32302 -#define H_SPELL_FIERY_BLAST 38382 -#define SPELL_FIERY_BLAST DUNGEON_MODE(N_SPELL_FIERY_BLAST, H_SPELL_FIERY_BLAST) -#define SPELL_FOCUS_FIRE_VISUAL 42075 //need to find better visual - -#define EMOTE_FOCUSES_ON "focuses on " - -struct boss_shirrak_the_dead_watcherAI : public ScriptedAI -{ - boss_shirrak_the_dead_watcherAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Inhibitmagic_Timer; - uint32 Attractmagic_Timer; - uint32 Carnivorousbite_Timer; - uint32 FocusFire_Timer; - - uint64 FocusedTargetGUID; - - void Reset() - { - Inhibitmagic_Timer = 0; - Attractmagic_Timer = 28000; - Carnivorousbite_Timer = 10000; - FocusFire_Timer = 17000; - FocusedTargetGUID = 0; - } - - void EnterCombat(Unit * /*who*/) - { } - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == ENTRY_FOCUS_FIRE) - { - summoned->CastSpell(summoned,SPELL_FOCUS_FIRE_VISUAL,false); - summoned->setFaction(me->getFaction()); - summoned->SetLevel(me->getLevel()); - summoned->addUnitState(UNIT_STAT_ROOT); - - if (Unit *pFocusedTarget = Unit::GetUnit(*me, FocusedTargetGUID)) - summoned->AI()->AttackStart(pFocusedTarget); - } - } - - void UpdateAI(const uint32 diff) - { - //Inhibitmagic_Timer - if (Inhibitmagic_Timer <= diff) - { - float dist; - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* i_pl = i->getSource()) - if (i_pl->isAlive() && (dist = i_pl->IsWithinDist(me, 45))) - { - i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC); - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 35) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 25) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 15) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - } - Inhibitmagic_Timer = 3000+(rand()%1000); - } else Inhibitmagic_Timer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Attractmagic_Timer - if (Attractmagic_Timer <= diff) - { - DoCast(me, SPELL_ATTRACTMAGIC); - Attractmagic_Timer = 30000; - Carnivorousbite_Timer = 1500; - } else Attractmagic_Timer -= diff; - - //Carnivorousbite_Timer - if (Carnivorousbite_Timer <= diff) - { - DoCast(me, SPELL_CARNIVOROUSBITE); - Carnivorousbite_Timer = 10000; - } else Carnivorousbite_Timer -= diff; - - //FocusFire_Timer - if (FocusFire_Timer <= diff) - { - // Summon Focus Fire & Emote - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) - { - FocusedTargetGUID = pTarget->GetGUID(); - me->SummonCreature(ENTRY_FOCUS_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,5500); - - // TODO: Find better way to handle emote - // Emote - std::string *emote = new std::string(EMOTE_FOCUSES_ON); - emote->append(pTarget->GetName()); - emote->append("!"); - const char* text = emote->c_str(); - me->MonsterTextEmote(text, 0, true); - delete emote; - } - FocusFire_Timer = 15000+(rand()%5000); - } else FocusFire_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_shirrak_the_dead_watcher(Creature* pCreature) -{ - return new boss_shirrak_the_dead_watcherAI (pCreature); -} - -struct mob_focus_fireAI : public ScriptedAI -{ - mob_focus_fireAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 FieryBlast_Timer; - bool fiery1, fiery2; - - void Reset() - { - FieryBlast_Timer = 3000+(rand()%1000); - fiery1 = fiery2 = true; - } - - void EnterCombat(Unit * /*who*/) - { } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FieryBlast_Timer - if (fiery2 && FieryBlast_Timer <= diff) - { - DoCast(me, SPELL_FIERY_BLAST); - - if (fiery1) fiery1 = false; - else if (fiery2) fiery2 = false; - - FieryBlast_Timer = 1000; - } else FieryBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_focus_fire(Creature* pCreature) -{ - return new mob_focus_fireAI (pCreature); -} - -void AddSC_boss_shirrak_the_dead_watcher() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shirrak_the_dead_watcher"; - newscript->GetAI = &GetAI_boss_shirrak_the_dead_watcher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_focus_fire"; - newscript->GetAI = &GetAI_mob_focus_fire; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp b/src/server/scripts/outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp deleted file mode 100644 index 5b15178c33e..00000000000 --- a/src/server/scripts/outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_NexusPrince_Shaffar -SD%Complete: 80 -SDComment: Need more tuning of spell timers, it should not be as linear fight as current. Also should possibly find a better way to deal with his three initial beacons to make sure all aggro. -SDCategory: Auchindoun, Mana Tombs -EndScriptData */ - -/* ContentData -boss_nexusprince_shaffar -mob_ethereal_beacon -EndContentData */ - -#include "ScriptedPch.h" - -enum ePrince -{ - SAY_INTRO = -1557000, - SAY_AGGRO_1 = -1557001, - SAY_AGGRO_2 = -1557002, - SAY_AGGRO_3 = -1557003, - SAY_SLAY_1 = -1557004, - SAY_SLAY_2 = -1557005, - SAY_SUMMON = -1557006, - SAY_DEAD = -1557007, - - SPELL_BLINK = 34605, - SPELL_FROSTBOLT = 32364, - SPELL_FIREBALL = 32363, - SPELL_FROSTNOVA = 32365, - - SPELL_ETHEREAL_BEACON = 32371, // Summons NPC_BEACON - SPELL_ETHEREAL_BEACON_VISUAL = 32368, - - NPC_BEACON = 18431, - NPC_SHAFFAR = 18344, - - NR_INITIAL_BEACONS = 3 -}; - -struct boss_nexusprince_shaffarAI : public ScriptedAI -{ - boss_nexusprince_shaffarAI(Creature *c) : ScriptedAI(c), summons(me) { HasTaunted = false; } - - uint32 Blink_Timer; - uint32 Beacon_Timer; - uint32 FireBall_Timer; - uint32 Frostbolt_Timer; - uint32 FrostNova_Timer; - - SummonList summons; - - bool HasTaunted; - bool CanBlink; - - void Reset() - { - Blink_Timer = 1500; - Beacon_Timer = 10000; - FireBall_Timer = 8000; - Frostbolt_Timer = 4000; - FrostNova_Timer = 15000; - - CanBlink = false; - - float dist = 8.0f; - float posX, posY, posZ, angle; - me->GetHomePosition(posX, posY, posZ, angle); - - me->SummonCreature(NPC_BEACON, posX - dist, posY - dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - me->SummonCreature(NPC_BEACON, posX - dist, posY + dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - me->SummonCreature(NPC_BEACON, posX + dist, posY, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - } - - void EnterEvadeMode() - { - summons.DespawnAll(); - ScriptedAI::EnterEvadeMode(); - } - - void MoveInLineOfSight(Unit *who) - { - if (!HasTaunted && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 100.0f)) - { - DoScriptText(SAY_INTRO, me); - HasTaunted = true; - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - DoZoneInCombat(); - summons.DoZoneInCombat(); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == NPC_BEACON) - { - summoned->CastSpell(summoned,SPELL_ETHEREAL_BEACON_VISUAL,false); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(pTarget); - } - - summons.Summon(summoned); - } - - void SummonedCreatureDespawn(Creature *summon) - { - summons.Despawn(summon); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEAD, me); - summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (FrostNova_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoCast(me, SPELL_FROSTNOVA); - FrostNova_Timer = 17500 + rand()%7500; - CanBlink = true; - } else FrostNova_Timer -= diff; - - if (Frostbolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - Frostbolt_Timer = 4500 + rand()%1500; - } else Frostbolt_Timer -= diff; - - if (FireBall_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL); - FireBall_Timer = 4500 + rand()%1500; - } else FireBall_Timer -= diff; - - if (CanBlink) - { - if (Blink_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - //expire movement, will prevent from running right back to victim after cast - //(but should MoveChase be used again at a certain time or should he not move?) - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - - DoCast(me, SPELL_BLINK); - Blink_Timer = 1000 + rand()%1500; - CanBlink = false; - } else Blink_Timer -= diff; - } - - if (Beacon_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - if (!urand(0,3)) - DoScriptText(SAY_SUMMON, me); - - DoCast(me, SPELL_ETHEREAL_BEACON, true); - - Beacon_Timer = 10000; - } else Beacon_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_nexusprince_shaffar(Creature* pCreature) -{ - return new boss_nexusprince_shaffarAI (pCreature); -} - -enum eEnums -{ - SPELL_ARCANE_BOLT = 15254, - SPELL_ETHEREAL_APPRENTICE = 32372 // Summon 18430 -}; - -struct mob_ethereal_beaconAI : public ScriptedAI -{ - mob_ethereal_beaconAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Apprentice_Timer; - uint32 ArcaneBolt_Timer; - uint32 Check_Timer; - - void KillSelf() - { - me->Kill(me); - } - - void Reset() - { - Apprentice_Timer = DUNGEON_MODE(20000, 10000); - ArcaneBolt_Timer = 1000; - Check_Timer = 1000; - } - - void EnterCombat(Unit * who) - { - // Send Shaffar to fight - Creature* Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); - if (!Shaffar || Shaffar->isDead()) - { - KillSelf(); - return; - } - if (!Shaffar->isInCombat()) - Shaffar->AI()->AttackStart(who); - } - - void JustSummoned(Creature *summoned) - { - summoned->AI()->AttackStart(me->getVictim()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Check_Timer <= diff) - { - Creature *Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); - if (!Shaffar || Shaffar->isDead() || !Shaffar->isInCombat()) - { - KillSelf(); - return; - } - Check_Timer = 1000; - } else Check_Timer -= diff; - - if (ArcaneBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BOLT); - ArcaneBolt_Timer = 2000 + rand()%2500; - } else ArcaneBolt_Timer -= diff; - - if (Apprentice_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoCast(me, SPELL_ETHEREAL_APPRENTICE, true); - me->ForcedDespawn(); - return; - } else Apprentice_Timer -= diff; - } -}; - -CreatureAI* GetAI_mob_ethereal_beacon(Creature* pCreature) -{ - return new mob_ethereal_beaconAI (pCreature); -} - -enum eEthereal -{ - SPELL_ETHEREAL_APPRENTICE_FIREBOLT = 32369, - SPELL_ETHEREAL_APPRENTICE_FROSTBOLT = 32370 -}; - -struct mob_ethereal_apprenticeAI : public ScriptedAI -{ - mob_ethereal_apprenticeAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cast_Timer; - - bool isFireboltTurn; - - void Reset() - { - Cast_Timer = 3000; - isFireboltTurn = true; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Cast_Timer <= diff) - { - if (isFireboltTurn) - { - DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FIREBOLT, true); - isFireboltTurn = false; - }else{ - DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FROSTBOLT, true); - isFireboltTurn = true; - } - Cast_Timer = 3000; - } else Cast_Timer -= diff; - } -}; - -CreatureAI* GetAI_mob_ethereal_apprentice(Creature* pCreature) -{ - return new mob_ethereal_apprenticeAI (pCreature); -} - -void AddSC_boss_nexusprince_shaffar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_nexusprince_shaffar"; - newscript->GetAI = &GetAI_boss_nexusprince_shaffar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ethereal_beacon"; - newscript->GetAI = &GetAI_mob_ethereal_beacon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ethereal_apprentice"; - newscript->GetAI = &GetAI_mob_ethereal_apprentice; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/mana_tombs/boss_pandemonius.cpp b/src/server/scripts/outland/auchindoun/mana_tombs/boss_pandemonius.cpp deleted file mode 100644 index 51ec2e83b46..00000000000 --- a/src/server/scripts/outland/auchindoun/mana_tombs/boss_pandemonius.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Pandemonius -SD%Complete: 75 -SDComment: Not known how void blast is done (amount of rapid cast seems to be related to players in party). All mobs remaining in surrounding area should aggro when engaged. -SDCategory: Auchindoun, Mana Tombs -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1557008 -#define SAY_AGGRO_2 -1557009 -#define SAY_AGGRO_3 -1557010 - -#define SAY_KILL_1 -1557011 -#define SAY_KILL_2 -1557012 - -#define SAY_DEATH -1557013 - -#define EMOTE_DARK_SHELL -1557014 - -#define SPELL_VOID_BLAST 32325 -#define H_SPELL_VOID_BLAST 38760 -#define SPELL_DARK_SHELL 32358 -#define H_SPELL_DARK_SHELL 38759 - -struct boss_pandemoniusAI : public ScriptedAI -{ - boss_pandemoniusAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 VoidBlast_Timer; - uint32 DarkShell_Timer; - uint32 VoidBlast_Counter; - - void Reset() - { - VoidBlast_Timer = 8000+rand()%15000; - DarkShell_Timer = 20000; - VoidBlast_Counter = 0; - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (VoidBlast_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_VOID_BLAST); - VoidBlast_Timer = 500; - ++VoidBlast_Counter; - } - - if (VoidBlast_Counter == 5) - { - VoidBlast_Timer = 15000+rand()%10000; - VoidBlast_Counter = 0; - } - } else VoidBlast_Timer -= diff; - - if (!VoidBlast_Counter) - { - if (DarkShell_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(EMOTE_DARK_SHELL, me); - - DoCast(me, SPELL_DARK_SHELL); - DarkShell_Timer = 20000; - } else DarkShell_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_pandemonius(Creature* pCreature) -{ - return new boss_pandemoniusAI (pCreature); -} - -void AddSC_boss_pandemonius() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_pandemonius"; - newscript->GetAI = &GetAI_boss_pandemonius; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp b/src/server/scripts/outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp deleted file mode 100644 index 9628fa1a98f..00000000000 --- a/src/server/scripts/outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Darkweaver_Syth -SD%Complete: 85 -SDComment: Shock spells/times need more work. Heroic partly implemented. -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_SUMMON -1556000 - -#define SAY_AGGRO_1 -1556001 -#define SAY_AGGRO_2 -1556002 -#define SAY_AGGRO_3 -1556003 - -#define SAY_SLAY_1 -1556004 -#define SAY_SLAY_2 -1556005 - -#define SAY_DEATH -1556006 - -#define SPELL_FROST_SHOCK 21401 //37865 -#define SPELL_FLAME_SHOCK 34354 -#define SPELL_SHADOW_SHOCK 30138 -#define SPELL_ARCANE_SHOCK 37132 - -#define SPELL_CHAIN_LIGHTNING 15659 //15305 - -#define SPELL_SUMMON_SYTH_FIRE 33537 // Spawns 19203 -#define SPELL_SUMMON_SYTH_ARCANE 33538 // Spawns 19205 -#define SPELL_SUMMON_SYTH_FROST 33539 // Spawns 19204 -#define SPELL_SUMMON_SYTH_SHADOW 33540 // Spawns 19206 - -#define SPELL_FLAME_BUFFET DUNGEON_MODE(33526, 38141) -#define SPELL_ARCANE_BUFFET DUNGEON_MODE(33527, 38138) -#define SPELL_FROST_BUFFET DUNGEON_MODE(33528, 38142) -#define SPELL_SHADOW_BUFFET DUNGEON_MODE(33529, 38143) - -struct boss_darkweaver_sythAI : public ScriptedAI -{ - boss_darkweaver_sythAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 flameshock_timer; - uint32 arcaneshock_timer; - uint32 frostshock_timer; - uint32 shadowshock_timer; - uint32 chainlightning_timer; - - bool summon90; - bool summon50; - bool summon10; - - void Reset() - { - flameshock_timer = 2000; - arcaneshock_timer = 4000; - frostshock_timer = 6000; - shadowshock_timer = 8000; - chainlightning_timer = 15000; - - summon90 = false; - summon50 = false; - summon10 = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustSummoned(Creature *summoned) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(pTarget); - } - - void SythSummoning() - { - DoScriptText(SAY_SUMMON, me); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me, SPELL_SUMMON_SYTH_ARCANE, true); //front - DoCast(me, SPELL_SUMMON_SYTH_FIRE, true); //back - DoCast(me, SPELL_SUMMON_SYTH_FROST, true); //left - DoCast(me, SPELL_SUMMON_SYTH_SHADOW, true); //right - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 90) && !summon90) - { - SythSummoning(); - summon90 = true; - } - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 50) && !summon50) - { - SythSummoning(); - summon50 = true; - } - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 10) && !summon10) - { - SythSummoning(); - summon10 = true; - } - - if (flameshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_SHOCK); - - flameshock_timer = 10000 + rand()%5000; - } else flameshock_timer -= diff; - - if (arcaneshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_SHOCK); - - arcaneshock_timer = 10000 + rand()%5000; - } else arcaneshock_timer -= diff; - - if (frostshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_SHOCK); - - frostshock_timer = 10000 + rand()%5000; - } else frostshock_timer -= diff; - - if (shadowshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_SHOCK); - - shadowshock_timer = 10000 + rand()%5000; - } else shadowshock_timer -= diff; - - if (chainlightning_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - - chainlightning_timer = 25000; - } else chainlightning_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_darkweaver_syth(Creature* pCreature) -{ - return new boss_darkweaver_sythAI (pCreature); -} - -/* ELEMENTALS */ - -struct mob_syth_fireAI : public ScriptedAI -{ - mob_syth_fireAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 flameshock_timer; - uint32 flamebuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - flameshock_timer = 2500; - flamebuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (flameshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_SHOCK); - - flameshock_timer = 5000; - } else flameshock_timer -= diff; - - if (flamebuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_BUFFET); - - flamebuffet_timer = 5000; - } else flamebuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_fire(Creature* pCreature) -{ - return new mob_syth_fireAI (pCreature); -} - -struct mob_syth_arcaneAI : public ScriptedAI -{ - mob_syth_arcaneAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 arcaneshock_timer; - uint32 arcanebuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); - arcaneshock_timer = 2500; - arcanebuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (arcaneshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_SHOCK); - - arcaneshock_timer = 5000; - } else arcaneshock_timer -= diff; - - if (arcanebuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_BUFFET); - - arcanebuffet_timer = 5000; - } else arcanebuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_arcane(Creature* pCreature) -{ - return new mob_syth_arcaneAI (pCreature); -} - -struct mob_syth_frostAI : public ScriptedAI -{ - mob_syth_frostAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 frostshock_timer; - uint32 frostbuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - frostshock_timer = 2500; - frostbuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (frostshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_SHOCK); - - frostshock_timer = 5000; - } else frostshock_timer -= diff; - - if (frostbuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_BUFFET); - - frostbuffet_timer = 5000; - } else frostbuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_frost(Creature* pCreature) -{ - return new mob_syth_frostAI (pCreature); -} - -struct mob_syth_shadowAI : public ScriptedAI -{ - mob_syth_shadowAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 shadowshock_timer; - uint32 shadowbuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); - shadowshock_timer = 2500; - shadowbuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (shadowshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_SHOCK); - - shadowshock_timer = 5000; - } else shadowshock_timer -= diff; - - if (shadowbuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_BUFFET); - - shadowbuffet_timer = 5000; - } else shadowbuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_shadow(Creature* pCreature) -{ - return new mob_syth_shadowAI (pCreature); -} - -void AddSC_boss_darkweaver_syth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_darkweaver_syth"; - newscript->GetAI = &GetAI_boss_darkweaver_syth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_fire"; - newscript->GetAI = &GetAI_mob_syth_arcane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_arcane"; - newscript->GetAI = &GetAI_mob_syth_arcane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_frost"; - newscript->GetAI = &GetAI_mob_syth_frost; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_shadow"; - newscript->GetAI = &GetAI_mob_syth_shadow; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/src/server/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp deleted file mode 100644 index 32b97293ca3..00000000000 --- a/src/server/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Talon_King_Ikiss -SD%Complete: 80 -SDComment: Heroic supported. Some details missing, but most are spell related. -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "sethekk_halls.h" - -#define SAY_INTRO -1556007 - -#define SAY_AGGRO_1 -1556008 -#define SAY_AGGRO_2 -1556009 -#define SAY_AGGRO_3 -1556010 - -#define SAY_SLAY_1 -1556011 -#define SAY_SLAY_2 -1556012 -#define SAY_DEATH -1556013 -#define EMOTE_ARCANE_EXP -1556015 - -#define SPELL_BLINK 38194 -#define SPELL_BLINK_TELEPORT 38203 -#define SPELL_MANA_SHIELD 38151 -#define SPELL_ARCANE_BUBBLE 9438 -#define H_SPELL_SLOW 35032 - -#define SPELL_POLYMORPH 38245 -#define H_SPELL_POLYMORPH 43309 - -#define SPELL_ARCANE_VOLLEY 35059 -#define H_SPELL_ARCANE_VOLLEY 40424 - -#define SPELL_ARCANE_EXPLOSION 38197 -#define H_SPELL_ARCANE_EXPLOSION 40425 - -struct boss_talon_king_ikissAI : public ScriptedAI -{ - boss_talon_king_ikissAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ArcaneVolley_Timer; - uint32 Sheep_Timer; - uint32 Blink_Timer; - uint32 Slow_Timer; - - bool ManaShield; - bool Blink; - bool Intro; - - void Reset() - { - ArcaneVolley_Timer = 5000; - Sheep_Timer = 8000; - Blink_Timer = 35000; - Slow_Timer = 15000+rand()%15000; - Blink = false; - Intro = false; - ManaShield = false; - } - - void MoveInLineOfSight(Unit *who) - { - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (!Intro && me->IsWithinDistInMap(who, 100)) - { - Intro = true; - DoScriptText(SAY_INTRO, me); - } - - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_IKISSDOOREVENT, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Blink) - { - DoCast(me, SPELL_ARCANE_EXPLOSION); - DoCast(me, SPELL_ARCANE_BUBBLE, true); - Blink = false; - } - - if (ArcaneVolley_Timer <= diff) - { - DoCast(me, SPELL_ARCANE_VOLLEY); - ArcaneVolley_Timer = 7000+rand()%5000; - } else ArcaneVolley_Timer -= diff; - - if (Sheep_Timer <= diff) - { - Unit *pTarget; - - //second top aggro target in normal, random target in heroic correct? - if (IsHeroic()) - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - else - pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); - - if (pTarget) - DoCast(pTarget, SPELL_POLYMORPH); - Sheep_Timer = 15000+rand()%2500; - } else Sheep_Timer -= diff; - - //may not be correct time to cast - if (!ManaShield && ((me->GetHealth()*100) / me->GetMaxHealth() < 20)) - { - DoCast(me, SPELL_MANA_SHIELD); - ManaShield = true; - } - - if (IsHeroic()) - { - if (Slow_Timer <= diff) - { - DoCast(me, H_SPELL_SLOW); - Slow_Timer = 15000+rand()%25000; - } else Slow_Timer -= diff; - } - - if (Blink_Timer <= diff) - { - DoScriptText(EMOTE_ARCANE_EXP, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - //Spell doesn't work, but we use for visual effect at least - DoCast(pTarget, SPELL_BLINK); - - float X = pTarget->GetPositionX(); - float Y = pTarget->GetPositionY(); - float Z = pTarget->GetPositionZ(); - - DoTeleportTo(X,Y,Z); - - DoCast(pTarget, SPELL_BLINK_TELEPORT); - Blink = true; - } - Blink_Timer = 35000+rand()%5000; - } else Blink_Timer -= diff; - - if (!Blink) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_talon_king_ikiss(Creature* pCreature) -{ - return new boss_talon_king_ikissAI (pCreature); -} - -void AddSC_boss_talon_king_ikiss() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_talon_king_ikiss"; - newscript->GetAI = &GetAI_boss_talon_king_ikiss; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp b/src/server/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp deleted file mode 100644 index ee27da3cff5..00000000000 --- a/src/server/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance - Sethekk Halls -SD%Complete: 50 -SDComment: Instance Data for Sethekk Halls instance -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "sethekk_halls.h" - -enum eEnums -{ - NPC_ANZU = 23035, - IKISS_DOOR = 177203, -}; - -struct instance_sethekk_halls : public ScriptedInstance -{ - instance_sethekk_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 AnzuEncounter; - uint64 m_uiIkissDoorGUID; - - void Initialize() - { - AnzuEncounter = NOT_STARTED; - m_uiIkissDoorGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == NPC_ANZU) - { - if (AnzuEncounter >= IN_PROGRESS) - pCreature->DisappearAndDie(); - else - AnzuEncounter = IN_PROGRESS; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - if (pGo->GetEntry() == IKISS_DOOR) - m_uiIkissDoorGUID = pGo->GetGUID(); - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_IKISSDOOREVENT: - if (data == DONE) - DoUseDoorOrButton(m_uiIkissDoorGUID,DAY*IN_MILISECONDS); - break; - case TYPE_ANZU_ENCOUNTER: - AnzuEncounter = data; - break; - } - } -}; - -InstanceData* GetInstanceData_instance_sethekk_halls(Map* pMap) -{ - return new instance_sethekk_halls(pMap); -} - -void AddSC_instance_sethekk_halls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_sethekk_halls"; - newscript->GetInstanceData = &GetInstanceData_instance_sethekk_halls; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h b/src/server/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h deleted file mode 100644 index 79a6cd4952d..00000000000 --- a/src/server/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SETHEKK_HALLS_H -#define DEF_SETHEKK_HALLS_H - -enum eTypes -{ - DATA_IKISSDOOREVENT = 1, - TYPE_ANZU_ENCOUNTER = 2, -}; -#endif - diff --git a/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp deleted file mode 100644 index 2bb6a717a5a..00000000000 --- a/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ambassador_Hellmaw -SD%Complete: 80 -SDComment: Enrage spell missing/not known -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "shadow_labyrinth.h" - -enum eEnums -{ - SAY_INTRO = -1555000, - SAY_AGGRO1 = -1555001, - SAY_AGGRO2 = -1555002, - SAY_AGGRO3 = -1555003, - SAY_HELP = -1555004, - SAY_SLAY1 = -1555005, - SAY_SLAY2 = -1555006, - SAY_DEATH = -1555007, - - SPELL_BANISH = 30231, - SPELL_CORROSIVE_ACID = 33551, - SPELL_FEAR = 33547, - SPELL_ENRAGE = 34970 -}; - -struct boss_ambassador_hellmawAI : public npc_escortAI -{ - boss_ambassador_hellmawAI(Creature* pCreature) : npc_escortAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 EventCheck_Timer; - uint32 CorrosiveAcid_Timer; - uint32 Fear_Timer; - uint32 Enrage_Timer; - bool Intro; - bool IsBanished; - bool Enraged; - - void Reset() - { - EventCheck_Timer = 5000; - CorrosiveAcid_Timer = 5000 + rand()%5000; - Fear_Timer = 25000 + rand()%5000; - Enrage_Timer = 180000; - Intro = false; - IsBanished = true; - Enraged = false; - - if (m_pInstance && me->isAlive()) - { - if (m_pInstance->GetData(TYPE_OVERSEER) != DONE) - DoCast(me, SPELL_BANISH, true); - } - } - - void JustReachedHome() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_HELLMAW, FAIL); - } - - void MoveInLineOfSight(Unit* pWho) - { - if (me->HasAura(SPELL_BANISH)) - return; - - npc_escortAI::MoveInLineOfSight(pWho); - } - - void WaypointReached(uint32 /*i*/) - { - } - - void DoIntro() - { - if (me->HasAura(SPELL_BANISH)) - me->RemoveAurasDueToSpell(SPELL_BANISH); - - IsBanished = false; - Intro = true; - - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_HELLMAW) != FAIL) - { - DoScriptText(SAY_INTRO, me); - Start(true, false, 0, NULL, false, true); - } - - m_pInstance->SetData(TYPE_HELLMAW, IN_PROGRESS); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_HELLMAW, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!Intro && !HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (EventCheck_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_OVERSEER) == DONE) - { - DoIntro(); - return; - } - } - EventCheck_Timer = 5000; - return; - } - else - { - EventCheck_Timer -= diff; - return; - } - } - - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->HasAura(SPELL_BANISH, 0)) - { - EnterEvadeMode(); - return; - } - - if (CorrosiveAcid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVE_ACID); - CorrosiveAcid_Timer = 15000 + rand()%10000; - } else CorrosiveAcid_Timer -= diff; - - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 20000 + rand()%15000; - } else Fear_Timer -= diff; - - if (IsHeroic()) - { - if (!Enraged && Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else Enrage_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_boss_ambassador_hellmaw(Creature* pCreature) -{ - return new boss_ambassador_hellmawAI(pCreature); -} - -void AddSC_boss_ambassador_hellmaw() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ambassador_hellmaw"; - newscript->GetAI = &GetAI_boss_ambassador_hellmaw; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp deleted file mode 100644 index 52c60ae0d0e..00000000000 --- a/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Blackheart_the_Inciter -SD%Complete: 75 -SDComment: Incite Chaos not functional since core lacks Mind Control support -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define SPELL_INCITE_CHAOS 33676 -#define SPELL_INCITE_CHAOS_B 33684 //debuff applied to each member of party -#define SPELL_CHARGE 33709 -#define SPELL_WAR_STOMP 33707 - -#define SAY_INTRO1 -1555008 //not used -#define SAY_INTRO2 -1555009 //not used -#define SAY_INTRO3 -1555010 //not used -#define SAY_AGGRO1 -1555011 -#define SAY_AGGRO2 -1555012 -#define SAY_AGGRO3 -1555013 -#define SAY_SLAY1 -1555014 -#define SAY_SLAY2 -1555015 -#define SAY_HELP -1555016 //not used -#define SAY_DEATH -1555017 - -//below, not used -#define SAY2_INTRO1 -1555018 -#define SAY2_INTRO2 -1555019 -#define SAY2_INTRO3 -1555020 -#define SAY2_AGGRO1 -1555021 -#define SAY2_AGGRO2 -1555022 -#define SAY2_AGGRO3 -1555023 -#define SAY2_SLAY1 -1555024 -#define SAY2_SLAY2 -1555025 -#define SAY2_HELP -1555026 -#define SAY2_DEATH -1555027 - -struct boss_blackheart_the_inciterAI : public ScriptedAI -{ - boss_blackheart_the_inciterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - bool InciteChaos; - uint32 InciteChaos_Timer; - uint32 InciteChaosWait_Timer; - uint32 Charge_Timer; - uint32 Knockback_Timer; - - void Reset() - { - InciteChaos = false; - InciteChaos_Timer = 20000; - InciteChaosWait_Timer = 15000; - Charge_Timer = 5000; - Knockback_Timer = 15000; - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (InciteChaos) - { - if (InciteChaosWait_Timer <= diff) - { - InciteChaos = false; - InciteChaosWait_Timer = 15000; - } else InciteChaosWait_Timer -= diff; - - return; - } - - if (InciteChaos_Timer <= diff) - { - DoCast(me, SPELL_INCITE_CHAOS); - - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - pTarget->CastSpell(pTarget,SPELL_INCITE_CHAOS_B,true); - } - - DoResetThreat(); - InciteChaos = true; - InciteChaos_Timer = 40000; - return; - } else InciteChaos_Timer -= diff; - - //Charge_Timer - if (Charge_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CHARGE); - Charge_Timer = 15000 + rand()%10000; - } else Charge_Timer -= diff; - - //Knockback_Timer - if (Knockback_Timer <= diff) - { - DoCast(me, SPELL_WAR_STOMP); - Knockback_Timer = 18000 + rand()%6000; - } else Knockback_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_blackheart_the_inciter(Creature* pCreature) -{ - return new boss_blackheart_the_inciterAI (pCreature); -} - -void AddSC_boss_blackheart_the_inciter() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_blackheart_the_inciter"; - newscript->GetAI = &GetAI_boss_blackheart_the_inciter; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp deleted file mode 100644 index 8b63b765b47..00000000000 --- a/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grandmaster_Vorpil -SD%Complete: 100 -SDComment: -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define SAY_INTRO -1555028 -#define SAY_AGGRO1 -1555029 -#define SAY_AGGRO2 -1555030 -#define SAY_AGGRO3 -1555031 -#define SAY_HELP -1555032 -#define SAY_SLAY1 -1555033 -#define SAY_SLAY2 -1555034 -#define SAY_DEATH -1555035 - -#define SPELL_RAIN_OF_FIRE 33617 -#define H_SPELL_RAIN_OF_FIRE 39363 - -#define SPELL_DRAW_SHADOWS 33563 -#define SPELL_SHADOWBOLT_VOLLEY 33841 -#define SPELL_BANISH 38791 - -#define MOB_VOID_TRAVELER 19226 -#define SPELL_SACRIFICE 33587 -#define SPELL_SHADOW_NOVA 33846 -#define SPELL_EMPOWERING_SHADOWS 33783 -#define H_SPELL_EMPOWERING_SHADOWS 39364 - -#define MOB_VOID_PORTAL 19224 -#define SPELL_VOID_PORTAL_VISUAL 33569 - -float VorpilPosition[3] = {-252.8820,-264.3030,17.1}; - -float VoidPortalCoords[5][3] = -{ - {-283.5894, -239.5718, 12.7}, - {-306.5853, -258.4539, 12.7}, - {-295.8789, -269.0899, 12.7}, - {-209.3401, -262.7564, 17.1}, - {-261.4533, -297.3298, 17.1} -}; - -struct mob_voidtravelerAI : public ScriptedAI -{ - mob_voidtravelerAI(Creature *c) : ScriptedAI(c) - { - } - - uint64 VorpilGUID; - uint32 move; - bool sacrificed; - - void Reset() - { - VorpilGUID = 0; - move = 0; - sacrificed = false; - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (!VorpilGUID) - { - me->Kill(me); - return; - } - if (move <= diff) - { - Creature *Vorpil = Unit::GetCreature(*me, VorpilGUID); - if (!Vorpil) - { - VorpilGUID = 0; - return; - } - - if (sacrificed) - { - me->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), Vorpil); - Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth()/25); - DoCast(me, SPELL_SHADOW_NOVA, true); - me->Kill(me); - return; - } - me->GetMotionMaster()->MoveFollow(Vorpil,0,0); - if (me->IsWithinDist(Vorpil, 3)) - { - DoCast(me, SPELL_SACRIFICE, false); - sacrificed = true; - move = 500; - return; - } - if (!Vorpil->isInCombat() || Vorpil->isDead()) - { - me->Kill(me); - return; - } - move = 1000; - } else move -= diff; - } -}; -CreatureAI* GetAI_mob_voidtraveler(Creature* pCreature) -{ - return new mob_voidtravelerAI (pCreature); -} - -struct boss_grandmaster_vorpilAI : public ScriptedAI -{ - boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = false; - } - - ScriptedInstance *pInstance; - bool Intro, HelpYell; - bool sumportals; - - uint32 ShadowBoltVolley_Timer; - uint32 DrawShadows_Timer; - uint32 summonTraveler_Timer; - uint32 banish_Timer; - uint64 PortalsGuid[5]; - - void Reset() - { - ShadowBoltVolley_Timer = 7000 + rand()%7000; - DrawShadows_Timer = 45000; - summonTraveler_Timer = 90000; - banish_Timer = 17000; - HelpYell = false; - destroyPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED); - } - - void summonPortals() - { - if (!sumportals) - { - for (uint8 i = 0; i < 5; ++i) - { - Creature *Portal = NULL; - Portal = me->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000); - if (Portal) - { - PortalsGuid[i] = Portal->GetGUID(); - Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false); - } - } - sumportals = true; - summonTraveler_Timer = 5000; - } - } - - void destroyPortals() - { - if (sumportals) - { - for (uint8 i = 0; i < 5; ++i) - { - Unit *Portal = Unit::GetUnit((*me), PortalsGuid[i]); - if (Portal && Portal->isAlive()) - Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - PortalsGuid[i] = 0; - } - sumportals = false; - } - } - - void spawnVoidTraveler() - { - int pos = urand(0,4); - me->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,5000); - if (!HelpYell) - { - DoScriptText(SAY_HELP, me); - HelpYell = true; - } - } - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == MOB_VOID_TRAVELER) - CAST_AI(mob_voidtravelerAI, summoned->AI())->VorpilGUID = me->GetGUID(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - destroyPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - summonPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS); - } - - void MoveInLineOfSight(Unit *who) - { - ScriptedAI::MoveInLineOfSight(who); - - if (!Intro && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 100) && me->IsHostileTo(who)) - { - DoScriptText(SAY_INTRO, me); - Intro = true; - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOWBOLT_VOLLEY); - ShadowBoltVolley_Timer = 15000 + rand()%15000; - } else ShadowBoltVolley_Timer -= diff; - - if (IsHeroic() && banish_Timer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,false); - if (pTarget) - { - DoCast(pTarget, SPELL_BANISH); - banish_Timer = 16000; - } - } else banish_Timer -= diff; - - if (DrawShadows_Timer <= diff) - { - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* i_pl = i->getSource()) - if (i_pl->isAlive() && !i_pl->HasAura(SPELL_BANISH)) - i_pl->TeleportTo(me->GetMapId(), VorpilPosition[0],VorpilPosition[1],VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT); - - me->GetMap()->CreatureRelocation(me, VorpilPosition[0],VorpilPosition[1],VorpilPosition[2],0.0f); - DoCast(me, SPELL_DRAW_SHADOWS, true); - - DoCast(me, SPELL_RAIN_OF_FIRE); - - ShadowBoltVolley_Timer = 6000; - DrawShadows_Timer = 30000; - } else DrawShadows_Timer -= diff; - - if (summonTraveler_Timer <= diff) - { - spawnVoidTraveler(); - summonTraveler_Timer = 10000; - //enrage at 20% - if ((me->GetHealth()*5) < me->GetMaxHealth()) - summonTraveler_Timer = 5000; - } else summonTraveler_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_grandmaster_vorpil(Creature* pCreature) -{ - return new boss_grandmaster_vorpilAI (pCreature); -} - -void AddSC_boss_grandmaster_vorpil() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grandmaster_vorpil"; - newscript->GetAI = &GetAI_boss_grandmaster_vorpil; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_voidtraveler"; - newscript->GetAI = &GetAI_mob_voidtraveler; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_murmur.cpp b/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_murmur.cpp deleted file mode 100644 index 14bf249c3b5..00000000000 --- a/src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_murmur.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Murmur -SD%Complete: 90 -SDComment: Timers may be incorrect -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define EMOTE_SONIC_BOOM -1555036 - -#define SPELL_SONIC_BOOM_CAST DUNGEON_MODE(33923, 38796) -#define SPELL_SONIC_BOOM_EFFECT DUNGEON_MODE(33666, 38795) -#define SPELL_RESONANCE 33657 -#define SPELL_MURMURS_TOUCH DUNGEON_MODE(33711, 38794) -#define SPELL_MAGNETIC_PULL 33689 -#define SPELL_SONIC_SHOCK 38797 -#define SPELL_THUNDERING_STORM 39365 - -struct boss_murmurAI : public ScriptedAI -{ - boss_murmurAI(Creature *c) : ScriptedAI(c) - { - SetCombatMovement(false); - } - - uint32 SonicBoom_Timer; - uint32 MurmursTouch_Timer; - uint32 Resonance_Timer; - uint32 MagneticPull_Timer; - uint32 SonicShock_Timer; - uint32 ThunderingStorm_Timer; - bool SonicBoom; - - void Reset() - { - SonicBoom_Timer = 30000; - MurmursTouch_Timer = 8000 + rand()%12000; - Resonance_Timer = 5000; - MagneticPull_Timer = 15000 + rand()%15000; - ThunderingStorm_Timer = 15000; - SonicShock_Timer = 10000; - SonicBoom = false; - - //database should have `RegenHealth`=0 to prevent regen - uint32 hp = (me->GetMaxHealth()*40)/100; - if (hp) me->SetHealth(hp); - me->ResetPlayerDamageReq(); - } - - void SonicBoomEffect() - { - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - //Not do anything without aura, spell can be resisted! - if (pTarget->HasAura(SPELL_SONIC_BOOM_CAST) && me->IsWithinDistInMap(pTarget, 34.0f)) - { - //This will be wrong calculation. Also, comments suggest it must deal damage - pTarget->SetHealth(uint32(pTarget->GetMaxHealth() - pTarget->GetMaxHealth() * 0.8)); - } - } - } - } - - void EnterCombat(Unit * /*who*/) { } - - // Sonic Boom instant damage (needs core fix instead of this) - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (pTarget && pTarget->isAlive() && spell && spell->Id == uint32(SPELL_SONIC_BOOM_EFFECT)) - me->DealDamage(pTarget,(pTarget->GetHealth()*90)/100,NULL,SPELL_DIRECT_DAMAGE,SPELL_SCHOOL_MASK_NATURE,spell); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target or casting - if (!UpdateVictim() || me->IsNonMeleeSpellCasted(false)) - return; - - // Sonic Boom - if (SonicBoom) - { - DoCast(me, SPELL_SONIC_BOOM_EFFECT, true); - SonicBoomEffect(); - - SonicBoom = false; - Resonance_Timer = 1500; - } - if (SonicBoom_Timer <= diff) - { - DoScriptText(EMOTE_SONIC_BOOM, me); - DoCast(me, SPELL_SONIC_BOOM_CAST); - SonicBoom_Timer = 30000; - SonicBoom = true; - return; - } else SonicBoom_Timer -= diff; - - // Murmur's Touch - if (MurmursTouch_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,80,true)) - DoCast(pTarget, SPELL_MURMURS_TOUCH); - MurmursTouch_Timer = 25000 + rand()%10000; - } else MurmursTouch_Timer -= diff; - - // Resonance - if (!SonicBoom && !(me->IsWithinMeleeRange(me->getVictim()))) - { - if (Resonance_Timer <= diff) - { - DoCast(me, SPELL_RESONANCE); - Resonance_Timer = 5000; - } else Resonance_Timer -= diff; - } - - // Magnetic Pull - if (MagneticPull_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - if (pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) - { - DoCast(pTarget, SPELL_MAGNETIC_PULL); - MagneticPull_Timer = 15000+rand()%15000; - return; - } - MagneticPull_Timer = 500; - } else MagneticPull_Timer -= diff; - - if (IsHeroic()) - { - // Thundering Storm - if (ThunderingStorm_Timer <= diff) - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) - if (pTarget->isAlive() && !me->IsWithinDist(pTarget, 35, false)) - DoCast(pTarget, SPELL_THUNDERING_STORM, true); - ThunderingStorm_Timer = 15000; - } else ThunderingStorm_Timer -= diff; - - // Sonic Shock - if (SonicShock_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,20,false)) - if (pTarget->isAlive()) - DoCast(pTarget, SPELL_SONIC_SHOCK); - SonicShock_Timer = 10000+rand()%10000; - } else SonicShock_Timer -= diff; - } - - // Select nearest most aggro target if top aggro too far - if (!me->isAttackReady()) - return; - if (!me->IsWithinMeleeRange(me->getVictim())) - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) - if (pTarget->isAlive() && me->IsWithinMeleeRange(pTarget)) - { - me->TauntApply(pTarget); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_murmur(Creature* pCreature) -{ - return new boss_murmurAI (pCreature); -} - -void AddSC_boss_murmur() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_murmur"; - newscript->GetAI = &GetAI_boss_murmur; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp deleted file mode 100644 index 78340e5e132..00000000000 --- a/src/server/scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Shadow_Labyrinth -SD%Complete: 85 -SDComment: Some cleanup left along with save -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define MAX_ENCOUNTER 5 - -#define REFECTORY_DOOR 183296 //door opened when blackheart the inciter dies -#define SCREAMING_HALL_DOOR 183295 //door opened when grandmaster vorpil dies - -/* Shadow Labyrinth encounters: -1 - Ambassador Hellmaw event -2 - Blackheart the Inciter event -3 - Grandmaster Vorpil event -4 - Murmur event -*/ - -struct instance_shadow_labyrinth : public ScriptedInstance -{ - instance_shadow_labyrinth(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 m_uiRefectoryDoorGUID; - uint64 m_uiScreamingHallDoorGUID; - - uint64 m_uiGrandmasterVorpil; - uint32 m_uiFelOverseerCount; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiRefectoryDoorGUID = 0; - m_uiScreamingHallDoorGUID = 0; - - m_uiGrandmasterVorpil = 0; - m_uiFelOverseerCount = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case REFECTORY_DOOR: - m_uiRefectoryDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case SCREAMING_HALL_DOOR: - m_uiScreamingHallDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 18732: - m_uiGrandmasterVorpil = pCreature->GetGUID(); - break; - case 18796: - if (pCreature->isAlive()) - { - ++m_uiFelOverseerCount; - debug_log("TSCR: Shadow Labyrinth: counting %u Fel Overseers.",m_uiFelOverseerCount); - } - break; - } - } - - void SetData(uint32 type, uint32 uiData) - { - switch(type) - { - case TYPE_HELLMAW: - m_auiEncounter[0] = uiData; - break; - - case TYPE_OVERSEER: - if (uiData != DONE) - { - error_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER did not expect other data than DONE"); - return; - } - if (m_uiFelOverseerCount) - { - --m_uiFelOverseerCount; - - if (m_uiFelOverseerCount) - debug_log("TSCR: Shadow Labyrinth: %u Fel Overseers left to kill.",m_uiFelOverseerCount); - else - { - m_auiEncounter[1] = DONE; - debug_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER == DONE"); - } - } - break; - - case DATA_BLACKHEARTTHEINCITEREVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiRefectoryDoorGUID); - m_auiEncounter[2] = uiData; - break; - - case DATA_GRANDMASTERVORPILEVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiScreamingHallDoorGUID); - m_auiEncounter[3] = uiData; - break; - - case DATA_MURMUREVENT: - m_auiEncounter[4] = uiData; - break; - } - - if (uiData == DONE) - { - if (type == TYPE_OVERSEER && m_uiFelOverseerCount != 0) - return; - - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_HELLMAW: return m_auiEncounter[0]; - case TYPE_OVERSEER: return m_auiEncounter[1]; - case DATA_GRANDMASTERVORPILEVENT: return m_auiEncounter[3]; - case DATA_MURMUREVENT: return m_auiEncounter[4]; - } - return false; - } - - uint64 GetData64(uint32 identifier) - { - if (identifier == DATA_GRANDMASTERVORPIL) - return m_uiGrandmasterVorpil; - - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_shadow_labyrinth(Map* pMap) -{ - return new instance_shadow_labyrinth(pMap); -} - -void AddSC_instance_shadow_labyrinth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_shadow_labyrinth"; - newscript->GetInstanceData = &GetInstanceData_instance_shadow_labyrinth; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h b/src/server/scripts/outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h deleted file mode 100644 index a78955368bf..00000000000 --- a/src/server/scripts/outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SHADOW_LABYRINTH_H -#define DEF_SHADOW_LABYRINTH_H - -#define TYPE_HELLMAW 1 -#define TYPE_OVERSEER 2 -#define DATA_BLACKHEARTTHEINCITEREVENT 3 -#define DATA_GRANDMASTERVORPILEVENT 4 -#define DATA_MURMUREVENT 5 -#define DATA_GRANDMASTERVORPIL 6 -#endif - diff --git a/src/server/scripts/outland/black_temple/black_temple.cpp b/src/server/scripts/outland/black_temple/black_temple.cpp deleted file mode 100644 index c1e7f19fbb1..00000000000 --- a/src/server/scripts/outland/black_temple/black_temple.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Black_Temple -SD%Complete: 95 -SDComment: Spirit of Olum: Player Teleporter to Seer Kanai Teleport after defeating Naj'entus and Supremus. TODO: Find proper gossip. -SDCategory: Black Temple -EndScriptData */ - -/* ContentData -npc_spirit_of_olum -EndContentData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -/*### -# npc_spirit_of_olum -####*/ - -#define SPELL_TELEPORT 41566 // s41566 - Teleport to Ashtongue NPC's -#define GOSSIP_OLUM1 "Teleport me to the other Ashtongue Deathsworn" - -bool GossipHello_npc_spirit_of_olum(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && (pInstance->GetData(DATA_SUPREMUSEVENT) >= DONE) && (pInstance->GetData(DATA_HIGHWARLORDNAJENTUSEVENT) >= DONE)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_OLUM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_spirit_of_olum(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - pPlayer->CLOSE_GOSSIP_MENU(); - - pPlayer->InterruptNonMeleeSpells(false); - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, false); - return true; -} - -void AddSC_black_temple() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_spirit_of_olum"; - newscript->pGossipHello = &GossipHello_npc_spirit_of_olum; - newscript->pGossipSelect = &GossipSelect_npc_spirit_of_olum; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/black_temple.h b/src/server/scripts/outland/black_temple/black_temple.h deleted file mode 100644 index b7432cd5b20..00000000000 --- a/src/server/scripts/outland/black_temple/black_temple.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BLACK_TEMPLE_H -#define DEF_BLACK_TEMPLE_H - -enum eTypes -{ - DATA_AKAMA = 1, - DATA_AKAMA_SHADE = 2, - DATA_GURTOGGBLOODBOILEVENT = 3, - DATA_HIGHWARLORDNAJENTUS = 4, - DATA_HIGHWARLORDNAJENTUSEVENT = 5, - DATA_ILLIDANSTORMRAGE = 6, - DATA_ILLIDANSTORMRAGEEVENT = 7, - DATA_ILLIDARICOUNCILEVENT = 8, - DATA_ILLIDARICOUNCIL = 9, - DATA_LADYMALANDE = 10, - DATA_HIGHNETHERMANCERZEREVOR = 11, - DATA_GATHIOSTHESHATTERER = 12, - DATA_VERASDARKSHADOW = 13, - DATA_MOTHERSHAHRAZEVENT = 14, - DATA_RELIQUARYOFSOULSEVENT = 15, - DATA_SHADEOFAKAMA = 16, - DATA_SHADEOFAKAMAEVENT = 17, - DATA_SUPREMUS = 18, - DATA_SUPREMUSEVENT = 19, - DATA_TERONGOREFIENDEVENT = 20, - DATA_GAMEOBJECT_NAJENTUS_GATE = 21, - DATA_GAMEOBJECT_ILLIDAN_GATE = 22, - DATA_GAMEOBJECT_ILLIDAN_DOOR_R = 23, - DATA_GAMEOBJECT_ILLIDAN_DOOR_L = 24, - DATA_GAMEOBJECT_SUPREMUS_DOORS = 25, - DATA_BLOOD_ELF_COUNCIL_VOICE = 26 -}; - -#endif - diff --git a/src/server/scripts/outland/black_temple/boss_bloodboil.cpp b/src/server/scripts/outland/black_temple/boss_bloodboil.cpp deleted file mode 100644 index 1093ce06cb8..00000000000 --- a/src/server/scripts/outland/black_temple/boss_bloodboil.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Bloodboil -SD%Complete: 80 -SDComment: Bloodboil not working correctly, missing enrage -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -//Speech'n'Sound -#define SAY_AGGRO -1564029 -#define SAY_SLAY1 -1564030 -#define SAY_SLAY2 -1564031 -#define SAY_SPECIAL1 -1564032 -#define SAY_SPECIAL2 -1564033 -#define SAY_ENRAGE1 -1564034 -#define SAY_ENRAGE2 -1564035 -#define SAY_DEATH -1564036 - -//Spells -#define SPELL_ACID_GEYSER 40630 -#define SPELL_ACIDIC_WOUND 40481 -#define SPELL_ARCING_SMASH 40599 -#define SPELL_BLOODBOIL 42005 // This spell is AoE whereas it shouldn't be -#define SPELL_FEL_ACID 40508 -#define SPELL_FEL_RAGE_SELF 40594 -#define SPELL_FEL_RAGE_TARGET 40604 -#define SPELL_FEL_RAGE_2 40616 -#define SPELL_FEL_RAGE_3 41625 -#define SPELL_BEWILDERING_STRIKE 40491 -#define SPELL_EJECT1 40486 // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) -#define SPELL_EJECT2 40597 // 1000 Physical damage + Stun (used in phase 2?) -#define SPELL_TAUNT_GURTOGG 40603 -#define SPELL_INSIGNIFIGANCE 40618 -#define SPELL_BERSERK 45078 - -//This is used to sort the players by distance in preparation for the Bloodboil cast. - -struct boss_gurtogg_bloodboilAI : public ScriptedAI -{ - boss_gurtogg_bloodboilAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 TargetGUID; - - float TargetThreat; - - uint32 BloodboilTimer; - uint32 BloodboilCount; - uint32 AcidGeyserTimer; - uint32 AcidicWoundTimer; - uint32 ArcingSmashTimer; - uint32 EnrageTimer; - uint32 FelAcidTimer; - uint32 EjectTimer; - uint32 BewilderingStrikeTimer; - uint32 PhaseChangeTimer; - - bool Phase1; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, NOT_STARTED); - - TargetGUID = 0; - - TargetThreat = 0; - - BloodboilTimer = 10000; - BloodboilCount = 0; - AcidGeyserTimer = 1000; - AcidicWoundTimer = 6000; - ArcingSmashTimer = 19000; - EnrageTimer = 600000; - FelAcidTimer = 25000; - EjectTimer = 10000; - BewilderingStrikeTimer = 15000; - PhaseChangeTimer = 60000; - - Phase1 = true; - - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited. - void CastBloodboil() - { - // Get the Threat List - std::list m_threatlist = me->getThreatManager().getThreatList(); - - if (!m_threatlist.size()) // He doesn't have anyone in his threatlist, useless to continue - return; - - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //only on alive players - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - targets.push_back(pTarget); - } - - //Sort the list of players - targets.sort(Trinity::ObjectDistanceOrderPred(me, false)); - //Resize so we only get top 5 - targets.resize(5); - - //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp - /*SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(SPELL_BLOODBOIL); - if (spellInfo) - { - for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - { - Unit *pTarget = *itr; - if (!pTarget) return; - for (uint32 i = 0; i<3; ++i) - { - uint8 eff = spellInfo->Effect[i]; - if (eff >= TOTAL_SPELL_EFFECTS) - continue; - - Aura *Aur = new Aura(spellInfo, i, pTarget, pTarget, pTarget); - pTarget->AddAura(Aur); - } - } - }*/ - } - - void RevertThreatOnTarget(uint64 guid) - { - Unit* pUnit = NULL; - pUnit = Unit::GetUnit((*me), guid); - if (pUnit) - { - if (DoGetThreat(pUnit)) - DoModifyThreatPercent(pUnit, -100); - if (TargetThreat) - me->AddThreat(pUnit, TargetThreat); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ArcingSmashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCING_SMASH); - ArcingSmashTimer = 10000; - } else ArcingSmashTimer -= diff; - - if (FelAcidTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FEL_ACID); - FelAcidTimer = 25000; - } else FelAcidTimer -= diff; - - if (!me->HasAura(SPELL_BERSERK)) - { - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - DoScriptText(RAND(SAY_ENRAGE1,SAY_ENRAGE2), me); - } else EnrageTimer -= diff; - } - - if (Phase1) - { - if (BewilderingStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BEWILDERING_STRIKE); - float mt_threat = DoGetThreat(me->getVictim()); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1)) - me->AddThreat(pTarget, mt_threat); - BewilderingStrikeTimer = 20000; - } else BewilderingStrikeTimer -= diff; - - if (EjectTimer <= diff) - { - DoCast(me->getVictim(), SPELL_EJECT1); - DoModifyThreatPercent(me->getVictim(), -40); - EjectTimer = 15000; - } else EjectTimer -= diff; - - if (AcidicWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ACIDIC_WOUND); - AcidicWoundTimer = 10000; - } else AcidicWoundTimer -= diff; - - if (BloodboilTimer <= diff) - { - if (BloodboilCount < 5) // Only cast it five times. - { - //CastBloodboil(); // Causes issues on windows, so is commented out. - DoCast(me->getVictim(), SPELL_BLOODBOIL); - ++BloodboilCount; - BloodboilTimer = 10000*BloodboilCount; - } - } else BloodboilTimer -= diff; - } - - if (!Phase1) - { - if (AcidGeyserTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ACID_GEYSER); - AcidGeyserTimer = 30000; - } else AcidGeyserTimer -= diff; - - if (EjectTimer <= diff) - { - DoCast(me->getVictim(), SPELL_EJECT2); - EjectTimer = 15000; - } else EjectTimer -= diff; - } - - if (PhaseChangeTimer <= diff) - { - if (Phase1) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget && pTarget->isAlive()) - { - Phase1 = false; - - TargetThreat = DoGetThreat(pTarget); - TargetGUID = pTarget->GetGUID(); - pTarget->CastSpell(me, SPELL_TAUNT_GURTOGG, true); - if (DoGetThreat(pTarget)) - DoModifyThreatPercent(pTarget, -100); - me->AddThreat(pTarget, 50000000.0f); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); - // If VMaps are disabled, this spell can call the whole instance - DoCast(me, SPELL_INSIGNIFIGANCE, true); - DoCast(pTarget, SPELL_FEL_RAGE_TARGET, true); - DoCast(pTarget, SPELL_FEL_RAGE_2, true); - /* These spells do not work, comment them out for now. - DoCast(pTarget, SPELL_FEL_RAGE_2, true); - DoCast(pTarget, SPELL_FEL_RAGE_3, true);*/ - - //Cast this without triggered so that it appears in combat logs and shows visual. - DoCast(me, SPELL_FEL_RAGE_SELF); - - DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); - - AcidGeyserTimer = 1000; - PhaseChangeTimer = 30000; - } - } else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage - { - if (TargetGUID) - RevertThreatOnTarget(TargetGUID); - TargetGUID = 0; - Phase1 = true; - BloodboilTimer = 10000; - BloodboilCount = 0; - AcidicWoundTimer += 2000; - ArcingSmashTimer += 2000; - FelAcidTimer += 2000; - EjectTimer += 2000; - PhaseChangeTimer = 60000; - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); - } - } else PhaseChangeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_gurtogg_bloodboil(Creature* pCreature) -{ - return new boss_gurtogg_bloodboilAI (pCreature); -} - -void AddSC_boss_gurtogg_bloodboil() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gurtogg_bloodboil"; - newscript->GetAI = &GetAI_boss_gurtogg_bloodboil; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/boss_illidan.cpp b/src/server/scripts/outland/black_temple/boss_illidan.cpp deleted file mode 100644 index b8e09c0e08e..00000000000 --- a/src/server/scripts/outland/black_temple/boss_illidan.cpp +++ /dev/null @@ -1,2248 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_illidan_stormrage -SD%Complete: 90 -SDComment: Somewhat of a workaround for Parasitic Shadowfiend, unable to summon GOs for Cage Trap. -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -#define GETGO(obj, guid) GameObject* obj = pInstance->instance->GetGameObject(guid) -#define GETUNIT(unit, guid) Unit* unit = Unit::GetUnit(*me, guid) -#define GETCRE(cre, guid) Creature* cre = Unit::GetCreature(*me, guid) -#define HPPCT(unit) unit->GetHealth()*100 / unit->GetMaxHealth() - -/************* Quotes and Sounds ***********************/ -// Gossip for when a player clicks Akama -#define GOSSIP_ITEM "We are ready to face Illidan" - -// Yells for/by Akama -#define SAY_AKAMA_BEWARE "Be wary friends, The Betrayer meditates in the court just beyond." -#define SOUND_AKAMA_BEWARE 11388 -#define SAY_AKAMA_MINION "Come, my minions. Deal with this traitor as he deserves!" -#define SOUND_AKAMA_MINION 11465 -#define SAY_AKAMA_LEAVE "I'll deal with these mongrels. Strike now, friends! Strike at the betrayer!" -#define SOUND_AKAMA_LEAVE 11390 - -// Self explanatory -const char* SAY_KILL1 = "Who shall be next to taste my blades?!"; -#define SOUND_KILL1 11473 -const char* SAY_KILL2 = "This is too easy!"; -#define SOUND_KILL2 11472 - -// I think I'll fly now and let my subordinates take you on -#define SAY_TAKEOFF "I will not be touched by rabble such as you!" -#define SOUND_TAKEOFF 11479 -#define SAY_SUMMONFLAMES "Behold the flames of Azzinoth!" -#define SOUND_SUMMONFLAMES 11480 - -// When casting Eye Blast. Demon Fire will be appear on places that he casts this -#define SAY_EYE_BLAST "Stare into the eyes of the Betrayer!" -#define SOUND_EYE_BLAST 11481 - -// kk, I go big, dark and demon on you. -#define SAY_MORPH "Behold the power... of the demon within!" -#define SOUND_MORPH 11475 - -// I KILL! -#define SAY_ENRAGE "You've wasted too much time mortals, now you shall fall!" -#define SOUND_ENRAGE 11474 - -/************** Spells *************/ -// Normal Form -#define SPELL_SHEAR 37335 // 41032 is bugged, cannot be block/dodge/parry// Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5 second cast -#define SPELL_FLAME_CRASH 40832 // Summons an invis/unselect passive mob that has an aura of flame in a circle around him. -#define SPELL_DRAW_SOUL 40904 // 5k Shadow Damage in front of him. Heals Illidan for 100k health (script effect) -#define SPELL_PARASITIC_SHADOWFIEND 41917 // DoT of 3k Shadow every 2 seconds. Lasts 10 seconds. (Script effect: Summon 2 parasites once the debuff has ticked off) -#define SPELL_PARASITIC_SHADOWFIEND2 41914 // Used by Parasitic -#define SPELL_SUMMON_PARASITICS 41915 // Summons 2 Parasitic Shadowfiends on the target. It's supposed to be cast as soon as the Parasitic Shadowfiend debuff is gone, but the spells aren't linked :( -#define SPELL_AGONIZING_FLAMES 40932 // 4k fire damage initial to target and anyone w/i 5 yards. PHASE 3 ONLY -#define SPELL_ENRAGE 40683 // Increases damage by 50% and attack speed by 30%. 20 seconds, PHASE 5 ONLY -// Flying (Phase 2) -#define SPELL_THROW_GLAIVE 39635 // Throws a glaive on the ground -#define SPELL_THROW_GLAIVE2 39849 // Animation for the above spell -#define SPELL_GLAIVE_RETURNS 39873 // Glaive flies back to Illidan -#define SPELL_FIREBALL 40598 // 2.5k-3.5k damage in 10 yard radius. 2 second cast time. -#define SPELL_DARK_BARRAGE 40585 // 10 second channeled spell, 3k shadow damage per second. -// Demon Form -#define SPELL_DEMON_TRANSFORM_1 40511 // First phase of animations for transforming into Dark Illidan (fall to ground) -#define SPELL_DEMON_TRANSFORM_2 40398 // Second phase of animations (kneel) -#define SPELL_DEMON_TRANSFORM_3 40510 // Final phase of animations (stand up and roar) -#define SPELL_DEMON_FORM 40506 // Transforms into Demon Illidan. Has an Aura of Dread on him. -#define SPELL_SHADOW_BLAST 41078 // 8k - 11k Shadow Damage. Targets highest threat. Has a splash effect, damaging anyone in 20 yards of the target. -#define SPELL_FLAME_BURST 41126 // Hurls fire at entire raid for ~3.5k damage every 10 seconds. Resistable. (Does not work: Script effect) -#define SPELL_FLAME_BURST_EFFECT 41131 // The actual damage. Have each player cast it on itself (workaround) -// Other Illidan spells -#define SPELL_KNEEL 39656 // Before beginning encounter, this is how he appears (talking to skully). -#define SPELL_SHADOW_PRISON 40647 // Illidan casts this spell to immobilize entire raid when he summons Maiev. -#define SPELL_DEATH 41220 // This spell doesn't do anything except stun Illidan and set him on his knees. -#define SPELL_BERSERK 45078 // Damage increased by 500%, attack speed by 150% -#define SPELL_DUAL_WIELD 42459 -//Phase Normal spells -#define SPELL_FLAME_CRASH_EFFECT 40836 // Firey blue ring of circle that the other flame crash summons -#define SPELL_SUMMON_SHADOWDEMON 41117 // Summon four shadowfiends -#define SPELL_SHADOWFIEND_PASSIVE 41913 // Passive aura for shadowfiends -#define SPELL_SHADOW_DEMON_PASSIVE 41079 // Adds the "shadowform" aura to Shadow Demons. -#define SPELL_CONSUME_SOUL 41080 // Once the Shadow Demons reach their target, they use this to kill them -#define SPELL_PARALYZE 41083 // Shadow Demons cast this on their target -#define SPELL_PURPLE_BEAM 39123 // Purple Beam connecting Shadow Demon to their target -//Phase Flight spells -#define SPELL_AZZINOTH_CHANNEL 39857 // Glaives cast it on Flames. Not sure if this is the right spell. -#define SPELL_EYE_BLAST_TRIGGER 40017 // This summons Demon Form every few seconds and deals ~20k damage in its radius -#define SPELL_EYE_BLAST 39908 // This does the blue flamey animation. -#define SPELL_BLAZE_EFFECT 40610 // Green flame on the ground, triggers damage (5k) every few seconds -#define SPELL_BLAZE_SUMMON 40637 // Summons the Blaze creature -#define SPELL_DEMON_FIRE 40029 // Blue fire trail left by Eye Blast. Deals 2k per second if players stand on it. -#define SPELL_FLAME_BLAST 40631 // Flames of Azzinoth use this. Frontal cone AoE 7k-9k damage. -#define SPELL_CHARGE 41581 //40602 // Flames of Azzinoth charges whoever is too far from them. They enrage after this. For simplicity, we'll use the same enrage as Illidan. -#define SPELL_FLAME_ENRAGE 45078 -//Akama spells -#define SPELL_AKAMA_DOOR_CHANNEL 41268 // Akama's channel spell on the door before the Temple Summit -#define SPELL_DEATHSWORN_DOOR_CHANNEL 41269 // Olum and Udalo's channel spell on the door before the Temple Summit -#define SPELL_AKAMA_DOOR_FAIL 41271 // Not sure where this is really used... -#define SPELL_HEALING_POTION 40535 // Akama uses this to heal himself to full. -#define SPELL_CHAIN_LIGHTNING 40536 // 6938 to 8062 for 5 targets -//Maiev spells -#define SPELL_CAGE_TRAP_DUMMY 40761 // Put this in DB for cage trap GO. -#define SPELL_CAGED 40695 // Caged Trap triggers will cast this on Illidan if he is within 3 yards -#define SPELL_CAGE_TRAP_SUMMON 40694 // Summons a Cage Trap GO (bugged) on the ground along with a Cage Trap Disturb Trigger mob (working) -#define SPELL_CAGE_TRAP_BEAM 40713 // 8 Triggers on the ground in an octagon cast spells like this on Illidan 'caging him' -#define SPELL_TELEPORT_VISUAL 41232 // Teleport visual for Maiev -#define SPELL_SHADOW_STRIKE 40685 // 4375 to 5625 every 3 seconds for 12 seconds -#define SPELL_THROW_DAGGER 41152 // 5400 to 6600 damage, need dagger -#define SPELL_FAN_BLADES 39954 // bugged visual - -// Other defines -#define CENTER_X 676.740 -#define CENTER_Y 305.297 -#define CENTER_Z 353.192 - -#define FLAME_ENRAGE_DISTANCE 30 -#define FLAME_CHARGE_DISTANCE 50 - -#define EQUIP_ID_MAIN_HAND 32837 -#define EQUIP_ID_OFF_HAND 32838 - -/**** Creature Summon and Recognition IDs ****/ -enum CreatureEntry -{ - EMPTY = 0, - AKAMA = 22990, - ILLIDAN_STORMRAGE = 22917, - BLADE_OF_AZZINOTH = 22996, - FLAME_OF_AZZINOTH = 22997, - MAIEV_SHADOWSONG = 23197, - SHADOW_DEMON = 23375, - DEMON_FIRE = 23069, - FLAME_CRASH = 23336, - ILLIDAN_DOOR_TRIGGER = 23412, - SPIRIT_OF_OLUM = 23411, - SPIRIT_OF_UDALO = 23410, - ILLIDARI_ELITE = 23226, - PARASITIC_SHADOWFIEND = 23498, - CAGE_TRAP_TRIGGER = 23292, -}; - -/*** Phase Names ***/ -enum PhaseIllidan -{ - PHASE_ILLIDAN_NULL = 0, - PHASE_NORMAL = 1, - PHASE_FLIGHT = 2, - PHASE_NORMAL_2 = 3, - PHASE_DEMON = 4, - PHASE_NORMAL_MAIEV = 5, - PHASE_TALK_SEQUENCE = 6, - PHASE_FLIGHT_SEQUENCE = 7, - PHASE_TRANSFORM_SEQUENCE = 8, - PHASE_ILLIDAN_MAX = 9, -};//Maiev uses the same phase - -enum PhaseAkama -{ - PHASE_AKAMA_NULL = 0, - PHASE_CHANNEL = 1, - PHASE_WALK = 2, - PHASE_TALK = 3, - PHASE_FIGHT_ILLIDAN = 4, - PHASE_FIGHT_MINIONS = 5, - PHASE_RETURN = 6, -}; - -enum EventIllidan -{ - EVENT_NULL = 0, - EVENT_BERSERK = 1, - //normal phase - EVENT_TAUNT = 2, - EVENT_SHEAR = 3, - EVENT_FLAME_CRASH = 4, - EVENT_PARASITIC_SHADOWFIEND = 5, - EVENT_PARASITE_CHECK = 6, - EVENT_DRAW_SOUL = 7, - EVENT_AGONIZING_FLAMES = 8, - EVENT_TRANSFORM_NORMAL = 9, - EVENT_ENRAGE = 10, - //flight phase - EVENT_FIREBALL = 2, - EVENT_DARK_BARRAGE = 3, - EVENT_EYE_BLAST = 4, - EVENT_MOVE_POINT = 5, - //demon phase - EVENT_SHADOW_BLAST = 2, - EVENT_FLAME_BURST = 3, - EVENT_SHADOWDEMON = 4, - EVENT_TRANSFORM_DEMON = 5, - //sequence phase - EVENT_TALK_SEQUENCE = 2, - EVENT_FLIGHT_SEQUENCE = 2, - EVENT_TRANSFORM_SEQUENCE = 2, -}; - -enum EventMaiev -{ - EVENT_MAIEV_NULL = 0, - EVENT_MAIEV_STEALTH = 1, - EVENT_MAIEV_TAUNT = 2, - EVENT_MAIEV_SHADOW_STRIKE = 3, - EVENT_MAIEV_THROW_DAGGER = 4, - EVENT_MAIEV_TRAP = 4, -}; - -static EventIllidan MaxTimer[]= -{ - EVENT_NULL, - EVENT_DRAW_SOUL, - EVENT_MOVE_POINT, - EVENT_TRANSFORM_NORMAL, - EVENT_TRANSFORM_DEMON, - EVENT_ENRAGE, - EVENT_TALK_SEQUENCE, - EVENT_FLIGHT_SEQUENCE, - EVENT_TRANSFORM_SEQUENCE -}; - -struct Yells -{ - uint32 sound; - char* text; - uint32 pCreature, timer, emote; - bool Talk; -}; - -static Yells Conversation[]= -{ - {11463, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.", ILLIDAN_STORMRAGE, 8000, 0, true}, - {0, NULL, ILLIDAN_STORMRAGE, 5000, 396, true}, - {11389, "We've come to end your reign, Illidan. My people and all of Outland shall be free!", AKAMA, 7000, 25, true}, - {0, NULL, AKAMA, 5000, 66, true}, - {11464, "Boldly said. But I remain unconvinced.", ILLIDAN_STORMRAGE, 8000, 396, true}, - {11380, "The time has come! The moment is at hand!", AKAMA, 3000, 22, true}, - {0, NULL, AKAMA, 2000, 15, true}, - {11466, "You are not prepared!", ILLIDAN_STORMRAGE, 3000, 406, true}, - {0, NULL, EMPTY, 1000, 0, true}, - {0, NULL, EMPTY, 0, 0, false},//9 - {11476, "Is this it, mortals? Is this all the fury you can muster?", ILLIDAN_STORMRAGE, 8000, 0, true}, - {11491, "Their fury pales before mine, Illidan. We have some unsettled business between us.", MAIEV_SHADOWSONG, 8000, 5, true}, - {11477, "Maiev... How is this even possible?", ILLIDAN_STORMRAGE, 5000, 1, true}, - {11492, "Ah... my long hunt is finally over. Today, Justice will be done!", MAIEV_SHADOWSONG, 8000, 15, true}, - {11470, "Feel the hatred of ten thousand years!", ILLIDAN_STORMRAGE, 1000, 0, false},//14 - {11496, "Ahh... It is finished. You are beaten.", MAIEV_SHADOWSONG, 6000, 0, true},//15 - {11478, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..", ILLIDAN_STORMRAGE, 30000, 65, true}, // Emote dead for now. Kill him later - {11497, "He is right. I feel nothing... I am nothing... Farewell, champions.", MAIEV_SHADOWSONG, 9000, 0, true}, - {11498, NULL, MAIEV_SHADOWSONG, 5000, 0, true}, - {11498, NULL, EMPTY, 1000, 0, true},//19 Maiev disappear - {11387, "The Light will fill these dismal halls once again. I swear it.", AKAMA, 8000, 0, true}, - {0, NULL, EMPTY, 1000, 0, false}//21 -}; - -static Yells RandomTaunts[]= -{ - {11467, "I can feel your hatred.", ILLIDAN_STORMRAGE, 0, 0, false}, - {11468, "Give in to your fear!", ILLIDAN_STORMRAGE, 0, 0, false}, - {11469, "You know nothing of power!", ILLIDAN_STORMRAGE, 0, 0, false}, - {11471, "Such... arrogance!", ILLIDAN_STORMRAGE, 0, 0, false} -}; - -static Yells MaievTaunts[]= -{ - {11493, "That is for Naisha!", MAIEV_SHADOWSONG, 0, false}, - {11494, "Bleed as I have bled!", MAIEV_SHADOWSONG, 0, 0, false}, - {11495, "There shall be no prison for you this time!", MAIEV_SHADOWSONG, 0, 0, false}, - {11500, "Meet your end, demon!", MAIEV_SHADOWSONG, 0, 0, false} -}; - -struct Locations -{ - float x, y, z; -}; - -static Locations HoverPosition[]= -{ - {657, 340, 355}, - {657, 275, 355}, - {705, 275, 355}, - {705, 340, 355} -}; - -static Locations GlaivePosition[]= -{ - {695.105, 305.303, 354.256}, - {659.338, 305.303, 354.256},//the distance between two glaives is 36 - {700.105, 305.303, 354.256}, - {664.338, 305.303, 354.256} -}; - -static Locations EyeBlast[]= -{ - {677, 350, 354},//start point, pass through glaive point - {677, 260, 354} -}; - -static Locations AkamaWP[]= -{ - {770.01, 304.50, 312.29}, // Bottom of the first stairs, at the doors - {780.66, 304.50, 319.74}, // Top of the first stairs - {790.13, 319.68, 319.76}, // Bottom of the second stairs (left from the entrance) - {787.17, 347.38, 341.42}, // Top of the second stairs - {781.34, 350.31, 341.44}, // Bottom of the third stairs - {762.60, 361.06, 353.60}, // Top of the third stairs - {756.35, 360.52, 353.27}, // Before the door-thingy - {743.82, 342.21, 353.00}, // Somewhere further - {732.69, 305.13, 353.00}, // In front of Illidan - (8) - {738.11, 365.44, 353.00}, // in front of the door-thingy (the other one!) - {792.18, 366.62, 341.42}, // Down the first flight of stairs - {796.84, 304.89, 319.76}, // Down the second flight of stairs - {782.01, 304.55, 319.76} // Final location - back at the initial gates. This is where he will fight the minions! (12) -}; -// 755.762, 304.0747, 312.1769 -- This is where Akama should be spawned -static Locations SpiritSpawns[]= -{ - {755.5426, 309.9156, 312.2129}, - {755.5426, 298.7923, 312.0834} -}; - -struct Animation // For the demon transformation -{ - uint32 aura, unaura, timer, size, displayid, phase; - bool equip; -}; - -static Animation DemonTransformation[]= -{ - {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, true}, - {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, true}, - {0, 0, 3000, 1073741824, 21322, 6, false},//stunned, cannot cast demon form - {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, false}, - {SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 4, false}, - {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, false}, - {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, false}, - {0, SPELL_DEMON_FORM, 3000, 1069547520, 21135, 6, false}, - {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, true}, - {0, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 8, true} -}; - -#define EMOTE_SETS_GAZE_ON "sets its gaze on $N!" -#define EMOTE_UNABLE_TO_SUMMON "is unable to summon Maiev Shadowsong and enter Phase 4. Resetting Encounter." - -/************************************** Illidan's AI ***************************************/ -struct boss_illidan_stormrageAI : public ScriptedAI -{ - boss_illidan_stormrageAI(Creature* c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - DoCast(me, SPELL_DUAL_WIELD, true); - - SpellEntry *TempSpell = GET_SPELL(SPELL_SHADOWFIEND_PASSIVE); - if (TempSpell) - TempSpell->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends - } - - ScriptedInstance* pInstance; - - PhaseIllidan Phase; - EventIllidan Event; - uint32 Timer[EVENT_ENRAGE + 1]; - - uint32 TalkCount; - uint32 TransformCount; - uint32 FlightCount; - - uint32 HoverPoint; - - uint64 AkamaGUID; - uint64 MaievGUID; - uint64 FlameGUID[2]; - uint64 GlaiveGUID[2]; - - SummonList Summons; - - void Reset(); - - void JustSummoned(Creature* summon); - - void SummonedCreatureDespawn(Creature* summon) - { - if (summon->GetCreatureInfo()->Entry == FLAME_OF_AZZINOTH) - { - for (uint8 i = 0; i < 2; ++i) - if (summon->GetGUID() == FlameGUID[i]) - FlameGUID[i] = 0; - - if (!FlameGUID[0] && !FlameGUID[1] && Phase != PHASE_ILLIDAN_NULL) - { - me->InterruptNonMeleeSpells(true); - EnterPhase(PHASE_FLIGHT_SEQUENCE); - } - } - Summons.Despawn(summon); - } - - void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) - { - if (FlightCount == 7) //change hover point - { - if (me->getVictim()) - { - me->SetInFront(me->getVictim()); - me->StopMoving(); - } - EnterPhase(PHASE_FLIGHT); - } - else // handle flight sequence - Timer[EVENT_FLIGHT_SEQUENCE] = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - me->setActive(true); - DoZoneInCombat(); - } - - void AttackStart(Unit *who) - { - if (!who || Phase >= PHASE_TALK_SEQUENCE) - return; - - if (Phase == PHASE_FLIGHT || Phase == PHASE_DEMON) - AttackStartNoMove(who); - else - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit *) {} - - void JustDied(Unit * /*killer*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (!pInstance) - return; - - pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, DONE); // Completed - - for (uint8 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L + 1; ++i) - pInstance->HandleGameObject(pInstance->GetData64(i), true); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) return; - // TODO: Find better way to handle emote - switch (urand(0,1)) - { - case 0: - me->MonsterYell(SAY_KILL1, LANG_UNIVERSAL, victim->GetGUID()); - DoPlaySoundToSet(me, SOUND_KILL1); - break; - case 1: - me->MonsterYell(SAY_KILL2, LANG_UNIVERSAL, victim->GetGUID()); - DoPlaySoundToSet(me, SOUND_KILL2); - break; - } - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = 0; - if (done_by->GetGUID() == MaievGUID) - done_by->AddThreat(me, -(3*(float)damage)/4); // do not let maiev tank him - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades! - { - if (!me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) - SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - else - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - } - } - - void DeleteFromThreatList(uint64 TargetGUID) - { - for (std::list::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) - { - if ((*itr)->getUnitGuid() == TargetGUID) - { - (*itr)->removeReference(); - break; - } - } - } - - void Talk(uint32 count) - { - Timer[EVENT_TALK_SEQUENCE] = Conversation[count].timer; - - Creature* pCreature = NULL; - if (Conversation[count].pCreature == ILLIDAN_STORMRAGE) - pCreature = me; - else if (Conversation[count].pCreature == AKAMA) - pCreature = (Unit::GetCreature((*me), AkamaGUID)); - else if (Conversation[count].pCreature == MAIEV_SHADOWSONG) - pCreature = (Unit::GetCreature((*me), MaievGUID)); - - if (pCreature) - { - if (Conversation[count].emote) - pCreature->HandleEmoteCommand(Conversation[count].emote); // Make the Creature do some animation! - if (Conversation[count].text) - pCreature->MonsterYell(Conversation[count].text, LANG_UNIVERSAL, 0); // Have the Creature yell out some text - if (Conversation[count].sound) - DoPlaySoundToSet(pCreature, Conversation[count].sound); // Play some sound on the creature - } - } - - void EnterPhase(PhaseIllidan NextPhase); - void CastEyeBlast(); - void SummonFlamesOfAzzinoth(); - void SummonMaiev(); - void HandleTalkSequence(); - void HandleFlightSequence() - { - switch(FlightCount) - { - case 1://lift off - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - me->StopMoving(); - me->MonsterYell(SAY_TAKEOFF, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_TAKEOFF); - Timer[EVENT_FLIGHT_SEQUENCE] = 3000; - break; - case 2://move to center - me->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); //+5, for SPELL_THROW_GLAIVE bug - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 3://throw one glaive - { - uint8 i=1; - Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Glaive) - { - GlaiveGUID[i] = Glaive->GetGUID(); - Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Glaive->SetDisplayId(11686); - Glaive->setFaction(me->getFaction()); - DoCast(Glaive, SPELL_THROW_GLAIVE2); - } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 700; - break; - case 4://throw another - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - { - uint8 i=0; - Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Glaive) - { - GlaiveGUID[i] = Glaive->GetGUID(); - Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Glaive->SetDisplayId(11686); - Glaive->setFaction(me->getFaction()); - DoCast(Glaive, SPELL_THROW_GLAIVE, true); - } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 5000; - break; - case 5://summon flames - SummonFlamesOfAzzinoth(); - Timer[EVENT_FLIGHT_SEQUENCE] = 3000; - break; - case 6://fly to hover point - me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 7://return to center - me->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 8://glaive return - for (uint8 i = 0; i < 2; ++i) - { - if (GlaiveGUID[i]) - { - Unit* Glaive = Unit::GetUnit((*me), GlaiveGUID[i]); - if (Glaive) - { - Glaive->CastSpell(me, SPELL_GLAIVE_RETURNS, false); // Make it look like the Glaive flies back up to us - Glaive->SetDisplayId(11686); // disappear but not die for now - } - } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 2000; - break; - case 9://land - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->StopMoving(); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - for (uint8 i = 0; i < 2; ++i) - { - if (GlaiveGUID[i]) - { - if (GETUNIT(Glaive, GlaiveGUID[i])) - { - Glaive->SetVisibility(VISIBILITY_OFF); - Glaive->setDeathState(JUST_DIED); // Despawn the Glaive - } - GlaiveGUID[i] = 0; - } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 2000; - break; - case 10://attack - DoResetThreat(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - EnterPhase(PHASE_NORMAL_2); - break; - default: - break; - } - ++FlightCount; - } - - void HandleTransformSequence() - { - if (DemonTransformation[TransformCount].unaura) - me->RemoveAurasDueToSpell(DemonTransformation[TransformCount].unaura); - - if (DemonTransformation[TransformCount].aura) - DoCast(me, DemonTransformation[TransformCount].aura, true); - - if (DemonTransformation[TransformCount].displayid) - me->SetDisplayId(DemonTransformation[TransformCount].displayid); // It's morphin time! - - if (DemonTransformation[TransformCount].equip) - { - // Requip warglaives if needed - SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - } - else - { - // Unequip warglaives if needed - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - } - - switch(TransformCount) - { - case 2: - DoResetThreat(); - break; - case 4: - EnterPhase(PHASE_DEMON); - break; - case 7: - DoResetThreat(); - break; - case 9: - if (MaievGUID) - EnterPhase(PHASE_NORMAL_MAIEV); // Depending on whether we summoned Maiev, we switch to either phase 5 or 3 - else - EnterPhase(PHASE_NORMAL_2); - break; - default: - break; - } - if (Phase == PHASE_TRANSFORM_SEQUENCE) - Timer[EVENT_TRANSFORM_SEQUENCE] = DemonTransformation[TransformCount].timer; - ++TransformCount; - } - - void UpdateAI(const uint32 diff) - { - if ((!UpdateVictim()) && Phase < PHASE_TALK_SEQUENCE) - return; - - Event = EVENT_NULL; - for (uint32 i = 1; i <= MaxTimer[Phase]; ++i) - { - if (Timer[i]) // Event is enabled - if (Timer[i] <= diff) - { - if (!Event) // No event with higher priority - Event = (EventIllidan)i; - } - else Timer[i] -= diff; - } - - switch(Phase) - { - case PHASE_NORMAL: - if (HPPCT(me) < 65) - EnterPhase(PHASE_FLIGHT_SEQUENCE); - break; - - case PHASE_NORMAL_2: - if (HPPCT(me) < 30) - EnterPhase(PHASE_TALK_SEQUENCE); - break; - - case PHASE_NORMAL_MAIEV: - if (HPPCT(me) < 1) - EnterPhase(PHASE_TALK_SEQUENCE); - break; - - case PHASE_TALK_SEQUENCE: - if (Event == EVENT_TALK_SEQUENCE) - HandleTalkSequence(); - break; - - case PHASE_FLIGHT_SEQUENCE: - if (Event == EVENT_FLIGHT_SEQUENCE) - HandleFlightSequence(); - break; - - case PHASE_TRANSFORM_SEQUENCE: - if (Event == EVENT_TRANSFORM_SEQUENCE) - HandleTransformSequence(); - break; - } - - if (me->IsNonMeleeSpellCasted(false)) - return; - - if (Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV && !me->HasAura(SPELL_CAGED)) - { - switch(Event) - { - //PHASE_NORMAL - case EVENT_BERSERK: - me->MonsterYell(SAY_ENRAGE, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_ENRAGE); - DoCast(me, SPELL_BERSERK, true); - Timer[EVENT_BERSERK] = 5000;//The buff actually lasts forever. - break; - - case EVENT_TAUNT: - { - uint32 random = rand()%4; - char* yell = RandomTaunts[random].text; - uint32 soundid = RandomTaunts[random].sound; - if (yell) - me->MonsterYell(yell, LANG_UNIVERSAL, 0); - if (soundid) - DoPlaySoundToSet(me, soundid); - } - Timer[EVENT_TAUNT] = 25000 + rand()%10000; - break; - - case EVENT_SHEAR: - // no longer exists in 3.0.2 - //DoCast(me->getVictim(), SPELL_SHEAR); - Timer[EVENT_SHEAR] = 25000 + (rand()%16 * 1000); - break; - - case EVENT_FLAME_CRASH: - DoCast(me->getVictim(), SPELL_FLAME_CRASH); - Timer[EVENT_FLAME_CRASH] = 30000 + rand()%10000; - break; - - case EVENT_PARASITIC_SHADOWFIEND: - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true)) - DoCast(pTarget, SPELL_PARASITIC_SHADOWFIEND, true); - Timer[EVENT_PARASITIC_SHADOWFIEND] = 35000 + rand()%10000; - } - break; - - case EVENT_PARASITE_CHECK: - Timer[EVENT_PARASITE_CHECK] = 0; - break; - - case EVENT_DRAW_SOUL: - DoCast(me->getVictim(), SPELL_DRAW_SOUL); - Timer[EVENT_DRAW_SOUL] = 50000 + rand()%10000; - break; - - //PHASE_NORMAL_2 - case EVENT_AGONIZING_FLAMES: - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES); - Timer[EVENT_AGONIZING_FLAMES] = 0; - break; - - case EVENT_TRANSFORM_NORMAL: - EnterPhase(PHASE_TRANSFORM_SEQUENCE); - break; - - //PHASE_NORMAL_MAIEV - case EVENT_ENRAGE: - DoCast(me, SPELL_ENRAGE); - Timer[EVENT_ENRAGE] = 0; - break; - - default: - break; - } - DoMeleeAttackIfReady(); - } - - if (Phase == PHASE_FLIGHT) - { - switch(Event) - { - case EVENT_FIREBALL: - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL); - Timer[EVENT_FIREBALL] = 3000; - break; - - case EVENT_DARK_BARRAGE: - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE); - Timer[EVENT_DARK_BARRAGE] = 0; - break; - - case EVENT_EYE_BLAST: - CastEyeBlast(); - Timer[EVENT_EYE_BLAST] = 0; - break; - - case EVENT_MOVE_POINT: - Phase = PHASE_FLIGHT_SEQUENCE; - Timer[EVENT_FLIGHT_SEQUENCE] = 0;//do not start Event when changing hover point - HoverPoint += (rand()%3 + 1); - if (HoverPoint > 3) - HoverPoint -= 4; - me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); - break; - - default: - break; - } - } - - if (Phase == PHASE_DEMON) - { - switch(Event) - { - case EVENT_SHADOW_BLAST: - me->GetMotionMaster()->Clear(false); - if (!me->IsWithinDistInMap(me->getVictim(), 50)||!me->IsWithinLOSInMap(me->getVictim())) - me->GetMotionMaster()->MoveChase(me->getVictim(), 30); - else - me->GetMotionMaster()->MoveIdle(); - DoCast(me->getVictim(), SPELL_SHADOW_BLAST); - Timer[EVENT_SHADOW_BLAST] = 4000; - break; - case EVENT_SHADOWDEMON: - DoCast(me, SPELL_SUMMON_SHADOWDEMON); - Timer[EVENT_SHADOWDEMON] = 0; - Timer[EVENT_FLAME_BURST] += 10000; - break; - case EVENT_FLAME_BURST: - DoCast(me, SPELL_FLAME_BURST); - Timer[EVENT_FLAME_BURST] = 15000; - break; - case EVENT_TRANSFORM_DEMON: - EnterPhase(PHASE_TRANSFORM_SEQUENCE); - break; - default: - break; - } - } - } -}; - -/********************************** End of Illidan AI ******************************************/ - -struct flame_of_azzinothAI : public ScriptedAI -{ - flame_of_azzinothAI(Creature *c) : ScriptedAI(c) {} - - uint32 FlameBlastTimer; - uint32 CheckTimer; - uint64 GlaiveGUID; - - void Reset() - { - FlameBlastTimer = 15000; - CheckTimer = 5000; - GlaiveGUID = 0; - } - - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - - void ChargeCheck() - { - Unit *pTarget = SelectTarget(SELECT_TARGET_FARTHEST, 0, 200, false); - if (pTarget && (!me->IsWithinCombatRange(pTarget, FLAME_CHARGE_DISTANCE))) - { - me->AddThreat(pTarget, 5000000.0f); - AttackStart(pTarget); - DoCast(pTarget, SPELL_CHARGE); - me->MonsterTextEmote(EMOTE_SETS_GAZE_ON, pTarget->GetGUID()); - } - } - - void EnrageCheck() - { - if (GETUNIT(Glaive, GlaiveGUID)) - { - if (!me->IsWithinDistInMap(Glaive, FLAME_ENRAGE_DISTANCE)) - { - Glaive->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_FLAME_ENRAGE, true); - DoResetThreat(); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget && pTarget->isAlive()) - { - me->AddThreat(me->getVictim(), 5000000.0f); - AttackStart(me->getVictim()); - } - } - else if (!me->HasAura(SPELL_AZZINOTH_CHANNEL)) - { - Glaive->CastSpell(me, SPELL_AZZINOTH_CHANNEL, false); - me->RemoveAurasDueToSpell(SPELL_FLAME_ENRAGE); - } - } - } - - void SetGlaiveGUID(uint64 guid){ GlaiveGUID = guid; } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (FlameBlastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BLAZE_SUMMON, true); //appear at victim - DoCast(me->getVictim(), SPELL_FLAME_BLAST); - FlameBlastTimer = 15000; //10000 is official-like? - DoZoneInCombat(); //in case someone is revived - } else FlameBlastTimer -= diff; - - if (CheckTimer <= diff) - { - ChargeCheck(); - EnrageCheck(); - CheckTimer = 1000; - } else CheckTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -/******* Functions and vars for Akama's AI ******/ -struct npc_akama_illidanAI : public ScriptedAI -{ - npc_akama_illidanAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - JustCreated = true; - } - bool JustCreated; - ScriptedInstance* pInstance; - - PhaseAkama Phase; - bool Event; - uint32 Timer; - - uint64 IllidanGUID; - uint64 ChannelGUID; - uint64 SpiritGUID[2]; - uint64 GateGUID; - uint64 DoorGUID[2]; - - uint32 ChannelCount; - uint32 WalkCount; - uint32 TalkCount; - uint32 Check_Timer; - - void Reset() - { - WalkCount = 0; - if (pInstance) - { - pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); - - IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); - GateGUID = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_GATE); - DoorGUID[0] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_R); - DoorGUID[1] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_L); - - if (JustCreated)//close all doors at create - { - pInstance->HandleGameObject(GateGUID, false); - - for (uint8 i = 0; i < 2; ++i) - pInstance->HandleGameObject(DoorGUID[i], false); - //JustCreated = false; - }else - {//open all doors, raid wiped - pInstance->HandleGameObject(GateGUID, true); - WalkCount = 1;//skip first wp - for (uint8 i = 0; i < 2; ++i) - pInstance->HandleGameObject(DoorGUID[i], true); - } - } - else - { - IllidanGUID = 0; - GateGUID = 0; - DoorGUID[0] = 0; - DoorGUID[1] = 0; - } - - ChannelGUID = 0; - SpiritGUID[0] = 0; - SpiritGUID[1] = 0; - - Phase = PHASE_AKAMA_NULL; - Timer = 0; - - ChannelCount = 0; - TalkCount = 0; - Check_Timer = 5000; - - KillAllElites(); - - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values.. - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->setActive(false); - me->SetVisibility(VISIBILITY_OFF); - } - - // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit - void EnterEvadeMode() - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void MovementInform(uint32 MovementType, uint32 /*Data*/) - { - if (MovementType == POINT_MOTION_TYPE) - Timer = 1; - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage > me->GetHealth() || done_by->GetGUID() != IllidanGUID) - damage = 0; - } - - void KillAllElites() - { - std::list& threatList = me->getThreatManager().getThreatList(); - std::vector eliteList; - for (std::list::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->GetEntry() == ILLIDARI_ELITE) - eliteList.push_back(pUnit); - } - for (std::vector::const_iterator itr = eliteList.begin(); itr != eliteList.end(); ++itr) - (*itr)->setDeathState(JUST_DIED); - EnterEvadeMode(); - } - - void BeginTalk() - { - if (!pInstance) - return; - - pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, IN_PROGRESS); - for (uint8 i = 0; i < 2; ++i) - pInstance->HandleGameObject(DoorGUID[i], false); - if (GETCRE(Illidan, IllidanGUID)) - { - Illidan->RemoveAurasDueToSpell(SPELL_KNEEL); - me->SetInFront(Illidan); - Illidan->SetInFront(me); - me->GetMotionMaster()->MoveIdle(); - Illidan->GetMotionMaster()->MoveIdle(); - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->AkamaGUID = me->GetGUID(); - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->EnterPhase(PHASE_TALK_SEQUENCE); - } - } - - void BeginChannel() - { - me->setActive(true); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - if (!JustCreated) - return; - float x, y, z; - if (GETGO(Gate, GateGUID)) - Gate->GetPosition(x, y, z); - else - return;//if door not spawned, don't crash server - - if (Creature* Channel = me->SummonCreature(ILLIDAN_DOOR_TRIGGER, x, y, z+5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) - { - ChannelGUID = Channel->GetGUID(); - Channel->SetDisplayId(11686); // Invisible but spell visuals can still be seen. - DoCast(Channel, SPELL_AKAMA_DOOR_FAIL); - } - - for (uint8 i = 0; i < 2; ++i) - if (Creature* Spirit = me->SummonCreature(i ? SPIRIT_OF_OLUM : SPIRIT_OF_UDALO, SpiritSpawns[i].x, SpiritSpawns[i].y, SpiritSpawns[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) - { - Spirit->SetVisibility(VISIBILITY_OFF); - SpiritGUID[i] = Spirit->GetGUID(); - } - } - - void BeginWalk() - { - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->SetSpeed(MOVE_RUN, 1.0f); - me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); - } - - void EnterPhase(PhaseAkama NextPhase) - { - if (!pInstance) - return; - switch(NextPhase) - { - case PHASE_CHANNEL: - BeginChannel(); - Timer = 5000; - ChannelCount = 0; - break; - case PHASE_WALK: - if (Phase == PHASE_CHANNEL) - WalkCount = 0; - else if (Phase == PHASE_TALK) - { - if (GETCRE(Illidan, IllidanGUID)) - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); - EnterEvadeMode(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - ++WalkCount; - } - JustCreated = false; - BeginWalk(); - Timer = 0; - break; - case PHASE_TALK: - if (Phase == PHASE_WALK) - { - BeginTalk(); - Timer = 0; - } - else if (Phase == PHASE_FIGHT_ILLIDAN) - { - Timer = 1; - TalkCount = 0; - } - break; - case PHASE_FIGHT_ILLIDAN: - if (GETUNIT(Illidan, IllidanGUID)) - { - me->AddThreat(Illidan, 10000000.0f); - me->GetMotionMaster()->MoveChase(Illidan); - } - Timer = 30000; //chain lightning - break; - case PHASE_FIGHT_MINIONS: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Timer = 10000 + rand()%6000;//summon minion - break; - case PHASE_RETURN: - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - KillAllElites(); - WalkCount = 0; - BeginWalk(); - Timer = 1; - break; - default: - break; - } - Phase = NextPhase; - Event = false; - } - - void HandleTalkSequence() - { - switch(TalkCount) - { - case 0: - if (GETCRE(Illidan, IllidanGUID)) - { - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->Timer[EVENT_TAUNT] += 30000; - Illidan->MonsterYell(SAY_AKAMA_MINION, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(Illidan, SOUND_AKAMA_MINION); - } - Timer = 8000; - break; - case 1: - me->MonsterYell(SAY_AKAMA_LEAVE, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_AKAMA_LEAVE); - Timer = 3000; - break; - case 2: - EnterPhase(PHASE_WALK); - break; - } - ++TalkCount; - } - - void HandleChannelSequence() - { - Unit* Channel = NULL, *Spirit[2]; - if (ChannelCount <= 5) - { - Channel = Unit::GetUnit((*me), ChannelGUID); - Spirit[0] = Unit::GetUnit((*me), SpiritGUID[0]); - Spirit[1] = Unit::GetUnit((*me), SpiritGUID[1]); - if (!Channel || !Spirit[0] || !Spirit[1]) - return; - } - - switch(ChannelCount) - { - case 0: // channel failed - me->InterruptNonMeleeSpells(true); - Timer = 2000; - break; - case 1: // spirit appear - Spirit[0]->SetVisibility(VISIBILITY_ON); - Spirit[1]->SetVisibility(VISIBILITY_ON); - Timer = 2000; - break; - case 2: // spirit help - DoCast(Channel, SPELL_AKAMA_DOOR_CHANNEL); - Spirit[0]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); - Spirit[1]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); - Timer = 5000; - break; - case 3: //open the gate - me->InterruptNonMeleeSpells(true); - Spirit[0]->InterruptNonMeleeSpells(true); - Spirit[1]->InterruptNonMeleeSpells(true); - if (pInstance) - pInstance->HandleGameObject(GateGUID, true); - Timer = 2000; - break; - case 4: - me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); - Timer = 2000; - break; - case 5: - me->MonsterYell(SAY_AKAMA_BEWARE, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_AKAMA_BEWARE); - Channel->setDeathState(JUST_DIED); - Spirit[0]->SetVisibility(VISIBILITY_OFF); - Spirit[1]->SetVisibility(VISIBILITY_OFF); - Timer = 3000; - break; - case 6: - EnterPhase(PHASE_WALK); - break; - default: - break; - } - ++ChannelCount; - } - - void HandleWalkSequence() - { - switch(WalkCount) - { - case 6: - for (uint8 i = 0; i < 2; ++i) - if (pInstance) - pInstance->HandleGameObject(DoorGUID[i], true); - break; - case 8: - if (Phase == PHASE_WALK) - EnterPhase(PHASE_TALK); - else - EnterPhase(PHASE_FIGHT_ILLIDAN); - break; - case 12: - EnterPhase(PHASE_FIGHT_MINIONS); - break; - } - - if (Phase == PHASE_WALK) - { - Timer = 0; - ++WalkCount; - me->GetMotionMaster()->MovePoint(WalkCount, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); - } - } - - void UpdateAI(const uint32 diff) - { - if (me->GetVisibility() == VISIBILITY_OFF) - { - if (Check_Timer <= diff) - { - if (pInstance && pInstance->GetData(DATA_ILLIDARICOUNCILEVENT) == DONE) - me->SetVisibility(VISIBILITY_ON); - - Check_Timer = 5000; - } else Check_Timer -= diff; - } - Event = false; - if (Timer) - { - if (Timer <= diff) - Event = true; - else Timer -= diff; - } - - if (Event) - { - switch(Phase) - { - case PHASE_CHANNEL: - if (JustCreated) - HandleChannelSequence(); - else{ - EnterPhase(PHASE_WALK); - } - break; - case PHASE_TALK: - HandleTalkSequence(); - break; - case PHASE_WALK: - case PHASE_RETURN: - HandleWalkSequence(); - break; - case PHASE_FIGHT_ILLIDAN: - { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && HPPCT(Illidan) < 90) - EnterPhase(PHASE_TALK); - else - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); - Timer = 30000; - } - } - break; - case PHASE_FIGHT_MINIONS: - { - float x, y, z; - me->GetPosition(x, y, z); - Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); - //Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); - if (Elite) - { - Elite->AI()->AttackStart(me); - Elite->AddThreat(me, 1000000.0f); - AttackStart(Elite); - me->AddThreat(Elite, 1000000.0f); - } - Timer = 10000 + rand()%6000; - GETUNIT(Illidan, IllidanGUID); - if (Illidan && HPPCT(Illidan) < 10) - EnterPhase(PHASE_RETURN); - } - break; - default: - break; - } - } - - if (!UpdateVictim()) - return; - - if (me->GetHealth()*100 / me->GetMaxHealth() < 20) - DoCast(me, SPELL_HEALING_POTION); - - DoMeleeAttackIfReady(); - } -}; - -struct boss_maievAI : public ScriptedAI -{ - boss_maievAI(Creature *c) : ScriptedAI(c) {}; - - uint64 IllidanGUID; - - PhaseIllidan Phase; - EventMaiev Event; - uint32 Timer[5]; - uint32 MaxTimer; - - void Reset() - { - MaxTimer = 0; - Phase = PHASE_NORMAL_MAIEV; - IllidanGUID = 0; - Timer[EVENT_MAIEV_STEALTH] = 0; - Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; - Timer[EVENT_MAIEV_SHADOW_STRIKE] = 30000; - SetEquipmentSlots(false, 44850, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, 45738); - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - void EnterEvadeMode() {} - void GetIllidanGUID(uint64 guid) { IllidanGUID = guid; } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != IllidanGUID) - damage = 0; - else - { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && Illidan->getVictim() == me) - damage = me->GetMaxHealth()/10; - if (damage >= me->GetHealth()) - damage = 0; - } - } - - void AttackStart(Unit *who) - { - if (!who || Timer[EVENT_MAIEV_STEALTH]) - return; - - if (Phase == PHASE_TALK_SEQUENCE) - AttackStartNoMove(who); - else if (Phase == PHASE_DEMON || Phase == PHASE_TRANSFORM_SEQUENCE) - { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && me->IsWithinDistInMap(Illidan, 25)) - BlinkToPlayer();//Do not let dread aura hurt her. - AttackStartNoMove(who); - } - else - ScriptedAI::AttackStart(who); - } - - void DoAction(const int32 param) - { - if (param > PHASE_ILLIDAN_NULL && param < PHASE_ILLIDAN_MAX) - EnterPhase(PhaseIllidan(param)); - } - - void EnterPhase(PhaseIllidan NextPhase)//This is in fact Illidan's phase. - { - switch(NextPhase) - { - case PHASE_TALK_SEQUENCE: - if (Timer[EVENT_MAIEV_STEALTH]) - { - me->SetHealth(me->GetMaxHealth()); - me->SetVisibility(VISIBILITY_ON); - Timer[EVENT_MAIEV_STEALTH] = 0; - } - me->InterruptNonMeleeSpells(false); - me->GetMotionMaster()->Clear(false); - me->AttackStop(); - me->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); - MaxTimer = 0; - break; - case PHASE_TRANSFORM_SEQUENCE: - MaxTimer = 4; - Timer[EVENT_MAIEV_TAUNT] += 10000; - Timer[EVENT_MAIEV_THROW_DAGGER] = 2000; - break; - case PHASE_DEMON: - break; - case PHASE_NORMAL_MAIEV: - MaxTimer = 4; - Timer[EVENT_MAIEV_TAUNT] += 10000; - Timer[EVENT_MAIEV_TRAP] = 22000; - break; - default: - break; - } - if (Timer[EVENT_MAIEV_STEALTH]) - MaxTimer = 1; - Phase = NextPhase; - } - - void BlinkTo(float x, float y, float z) - { - me->AttackStop(); - me->InterruptNonMeleeSpells(false); - me->GetMotionMaster()->Clear(false); - DoTeleportTo(x, y, z); - DoCast(me, SPELL_TELEPORT_VISUAL, true); - } - - void BlinkToPlayer() - { - if (GETCRE(Illidan, IllidanGUID)) - { - Unit *pTarget = CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (!pTarget || !me->IsWithinDistInMap(pTarget, 80) || Illidan->IsWithinDistInMap(pTarget, 20)) - { - uint8 pos = rand()%4; - BlinkTo(HoverPosition[pos].x, HoverPosition[pos].y, HoverPosition[pos].z); - } - else - { - float x, y, z; - pTarget->GetPosition(x, y, z); - BlinkTo(x, y, z); - } - } - } - - void UpdateAI(const uint32 diff) - { - if ((!UpdateVictim()) - && !Timer[EVENT_MAIEV_STEALTH]) - return; - - Event = EVENT_MAIEV_NULL; - for (uint8 i = 1; i <= MaxTimer; ++i) - if (Timer[i]) - { - if (Timer[i] <= diff) - Event = (EventMaiev)i; - else Timer[i] -= diff; - } - - switch(Event) - { - case EVENT_MAIEV_STEALTH: - { - me->SetHealth(me->GetMaxHealth()); - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Timer[EVENT_MAIEV_STEALTH] = 0; - BlinkToPlayer(); - EnterPhase(Phase); - } - break; - case EVENT_MAIEV_TAUNT: - { - uint32 random = rand()%4; - char* text = MaievTaunts[random].text; - uint32 sound = MaievTaunts[random].sound; - me->MonsterYell(text, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, sound); - Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; - } - break; - case EVENT_MAIEV_SHADOW_STRIKE: - DoCast(me->getVictim(), SPELL_SHADOW_STRIKE); - Timer[EVENT_MAIEV_SHADOW_STRIKE] = 60000; - break; - case EVENT_MAIEV_TRAP: - if (Phase == PHASE_NORMAL_MAIEV) - { - BlinkToPlayer(); - DoCast(me, SPELL_CAGE_TRAP_SUMMON); - Timer[EVENT_MAIEV_TRAP] = 22000; - } - else - { - if (!me->IsWithinDistInMap(me->getVictim(), 40)) - me->GetMotionMaster()->MoveChase(me->getVictim(), 30); - DoCast(me->getVictim(), SPELL_THROW_DAGGER); - Timer[EVENT_MAIEV_THROW_DAGGER] = 2000; - } - break; - default: - break; - } - - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (GETCRE(Illidan, IllidanGUID)) - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); - me->AttackStop(); - Timer[EVENT_MAIEV_STEALTH] = 60000; //reappear after 1 minute - MaxTimer = 1; - } - - if (Phase == PHASE_NORMAL_MAIEV) - DoMeleeAttackIfReady(); - } -}; - -bool GossipSelect_npc_akama_at_illidan(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) // Time to begin the Event - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_akama_illidanAI, pCreature->AI())->EnterPhase(PHASE_CHANNEL); - } - return true; -} - -bool GossipHello_npc_akama_at_illidan(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(10465, pCreature->GetGUID()); - - return true; -} - -struct cage_trap_triggerAI : public ScriptedAI -{ - cage_trap_triggerAI(Creature *c) : ScriptedAI(c) {} - - uint64 IllidanGUID; - uint32 DespawnTimer; - - bool Active; - bool SummonedBeams; - - void Reset() - { - IllidanGUID = 0; - - Active = false; - SummonedBeams = false; - - DespawnTimer = 0; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/){} - - void MoveInLineOfSight(Unit *who) - { - if (!Active) - return; - - if (who && (who->GetTypeId() != TYPEID_PLAYER)) - { - if (who->GetEntry() == ILLIDAN_STORMRAGE) // Check if who is Illidan - { - if (!IllidanGUID && me->IsWithinDistInMap(who, 3) && (!who->HasAura(SPELL_CAGED))) - { - IllidanGUID = who->GetGUID(); - who->CastSpell(who, SPELL_CAGED, true); - DespawnTimer = 5000; - if (who->HasAura(SPELL_ENRAGE)) - who->RemoveAurasDueToSpell(SPELL_ENRAGE); // Dispel his enrage - //if (GameObject* CageTrap = pInstance->instance->GetGameObject(pInstance->GetData64(CageTrapGUID))) - // CageTrap->SetLootState(GO_JUST_DEACTIVATED); - } - } - } - } - - void UpdateAI(const uint32 diff) - { - if (DespawnTimer) - if (DespawnTimer <= diff) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - else DespawnTimer -= diff; - - //if (IllidanGUID && !SummonedBeams) - //{ - // if (Unit* Illidan = Unit::GetUnit(*me, IllidanGUID) - // { - // //TODO: Find proper spells and properly apply 'caged' Illidan effect - // } - //} - } -}; - -bool GOHello_cage_trap(Player* pPlayer, GameObject* pGo) -{ - float x, y, z; - pPlayer->GetPosition(x, y, z); - - // Grid search for nearest live Creature of entry 23304 within 10 yards - if (Creature* pTrigger = pGo->FindNearestCreature(23304, 10.0f)) - CAST_AI(cage_trap_triggerAI, pTrigger->AI())->Active = true; - pGo->SetGoState(GO_STATE_ACTIVE); - return true; -} - -struct shadow_demonAI : public ScriptedAI -{ - shadow_demonAI(Creature *c) : ScriptedAI(c) {} - - uint64 TargetGUID; - - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - - void Reset() - { - TargetGUID = 0; - DoCast(me, SPELL_SHADOW_DEMON_PASSIVE, true); - } - - void JustDied(Unit * /*killer*/) - { - if (Unit *pTarget = Unit::GetUnit((*me), TargetGUID)) - pTarget->RemoveAurasDueToSpell(SPELL_PARALYZE); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) return; - - if (me->getVictim()->GetTypeId() != TYPEID_PLAYER) return; // Only cast the below on players. - - if (!me->getVictim()->HasAura(SPELL_PARALYZE)) - { - TargetGUID = me->getVictim()->GetGUID(); - me->AddThreat(me->getVictim(), 10000000.0f); - DoCast(me->getVictim(), SPELL_PURPLE_BEAM, true); - DoCast(me->getVictim(), SPELL_PARALYZE, true); - } - // Kill our target if we're very close. - if (me->IsWithinDistInMap(me->getVictim(), 3)) - DoCast(me->getVictim(), SPELL_CONSUME_SOUL); - } -}; - -// Shadowfiends interact with Illidan, setting more targets in Illidan's hashmap -struct mob_parasitic_shadowfiendAI : public ScriptedAI -{ - mob_parasitic_shadowfiendAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint64 IllidanGUID; - uint32 CheckTimer; - - void Reset() - { - if (pInstance) - IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); - else - IllidanGUID = 0; - - CheckTimer = 5000; - DoCast(me, SPELL_SHADOWFIEND_PASSIVE, true); - } - - void EnterCombat(Unit* /*who*/) { DoZoneInCombat(); } - - void DoMeleeAttackIfReady() - { - if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim())) - { - if (!me->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND) - && !me->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) - { - if (Creature* illidan = Unit::GetCreature((*me),IllidanGUID))//summon only in 1. phase - if (CAST_AI(boss_illidan_stormrageAI, illidan->AI())->Phase == PHASE_NORMAL) - me->CastSpell(me->getVictim(), SPELL_PARASITIC_SHADOWFIEND2, true, 0, 0, IllidanGUID); //do not stack - } - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->getVictim()) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) - AttackStart(pTarget); - else - { - me->SetVisibility(VISIBILITY_OFF); - me->setDeathState(JUST_DIED); - return; - } - } - - if (CheckTimer <= diff) - { - GETUNIT(Illidan, IllidanGUID); - if (!Illidan || CAST_CRE(Illidan)->IsInEvadeMode()) - { - me->SetVisibility(VISIBILITY_OFF); - me->setDeathState(JUST_DIED); - return; - } else CheckTimer = 5000; - } else CheckTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct blade_of_azzinothAI : public NullCreatureAI -{ - blade_of_azzinothAI(Creature* c) : NullCreatureAI(c) {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_THROW_GLAIVE2 || spell->Id == SPELL_THROW_GLAIVE) - me->SetDisplayId(21431);//appear when hit by Illidan's glaive - } -}; - -void boss_illidan_stormrageAI::Reset() -{ - if (pInstance) - pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); - - if (AkamaGUID) - { - if (GETCRE(Akama, AkamaGUID)) - { - if (!Akama->isAlive()) - Akama->Respawn(); - else - { - CAST_AI(npc_akama_illidanAI, Akama->AI())->EnterEvadeMode(); - Akama->GetMotionMaster()->MoveTargetedHome(); - CAST_AI(npc_akama_illidanAI, Akama->AI())->Reset(); - } - } - AkamaGUID = 0; - } - - MaievGUID = 0; - for (uint8 i = 0; i < 2; ++i) - { - FlameGUID[i] = 0; - GlaiveGUID[i] = 0; - } - - Phase = PHASE_ILLIDAN_NULL; - Event = EVENT_NULL; - Timer[EVENT_BERSERK] = 1500000; - - HoverPoint = 0; - TalkCount = 0; - FlightCount = 0; - TransformCount = 0; - - me->SetDisplayId(21135); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->setActive(false); - Summons.DespawnAll(); -} - -void boss_illidan_stormrageAI::JustSummoned(Creature* summon) -{ - Summons.Summon(summon); - switch(summon->GetEntry()) - { - case PARASITIC_SHADOWFIEND: - { - if (Phase == PHASE_TALK_SEQUENCE) - { - summon->SetVisibility(VISIBILITY_OFF); - summon->setDeathState(JUST_DIED); - return; - } - Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true); - if (!pTarget || pTarget->HasAura(SPELL_PARASITIC_SHADOWFIEND) - || pTarget->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true); - if (pTarget) - summon->AI()->AttackStart(pTarget); - } - break; - case SHADOW_DEMON: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) // only on players. - { - summon->AddThreat(pTarget, 5000000.0f); - summon->AI()->AttackStart(pTarget); - } - break; - case MAIEV_SHADOWSONG: - { - summon->SetVisibility(VISIBILITY_OFF); // Leave her invisible until she has to talk - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - MaievGUID = summon->GetGUID(); - CAST_AI(boss_maievAI, summon->AI())->GetIllidanGUID(me->GetGUID()); - summon->AI()->DoAction(PHASE_TALK_SEQUENCE); - } - break; - case FLAME_OF_AZZINOTH: - { - summon->AI()->AttackStart(summon->SelectNearestTarget(999)); - } - break; - default: - break; - } -} - -void boss_illidan_stormrageAI::HandleTalkSequence() -{ - switch(TalkCount) - { - case 0: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - break; - case 8: - // Equip our warglaives! - SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - break; - case 9: - if (GETCRE(Akama, AkamaGUID)) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->AddThreat(Akama, 100.0f); - CAST_AI(npc_akama_illidanAI, Akama->AI())->EnterPhase(PHASE_FIGHT_ILLIDAN); - EnterPhase(PHASE_NORMAL); - } - break; - case 10: - SummonMaiev(); - break; - case 11: - if (GETUNIT(Maiev, MaievGUID)) - { - Maiev->SetVisibility(VISIBILITY_ON); // Maiev is now visible - Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); // onoz she looks like she teleported! - Maiev->SetInFront(me); // Have her face us - me->SetInFront(Maiev); // Face her, so it's not rude =P - Maiev->GetMotionMaster()->MoveIdle(); - me->GetMotionMaster()->MoveIdle(); - } - break; - case 14: - if (GETCRE(Maiev, MaievGUID)) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - Maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - Maiev->AddThreat(me, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE - Maiev->AI()->AttackStart(me); // Force Maiev to attack us. - EnterPhase(PHASE_NORMAL_MAIEV); - } - break; - case 15: - DoCast(me, SPELL_DEATH); // Animate his kneeling + stun him - Summons.DespawnAll(); - break; - case 17: - if (GETUNIT(Akama, AkamaGUID)) - { - if (!me->IsWithinDistInMap(Akama, 15)) - { - float x, y, z; - me->GetPosition(x, y, z); - x += 10; y += 10; - Akama->GetMotionMaster()->Clear(false); - //Akama->GetMotionMaster()->MoveIdle(); - Akama->GetMap()->CreatureRelocation(me, x, y, z, 0.0f); - Akama->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_NONE, 0);//Illidan must not die until Akama arrives. - Akama->GetMotionMaster()->MoveChase(me); - } - } - break; - case 19: // Make Maiev leave - if (GETUNIT(Maiev, MaievGUID)) - { - Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); - Maiev->setDeathState(JUST_DIED); - me->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); - } - break; - case 21: // Kill ourself. - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - break; - default: - break; - } - if (Phase == PHASE_TALK_SEQUENCE) - Talk(TalkCount); // This function does most of the talking - ++TalkCount; -} - -void boss_illidan_stormrageAI::CastEyeBlast() -{ - me->InterruptNonMeleeSpells(false); - - me->MonsterYell(SAY_EYE_BLAST, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_EYE_BLAST); - - float distx, disty, dist[2]; - for (uint8 i = 0; i < 2; ++i) - { - distx = EyeBlast[i].x - HoverPosition[HoverPoint].x; - disty = EyeBlast[i].y - HoverPosition[HoverPoint].y; - dist[i] = distx * distx + disty * disty; - } - Locations initial = EyeBlast[dist[0] < dist[1] ? 0 : 1]; - for (uint8 i = 0; i < 2; ++i) - { - distx = GlaivePosition[i].x - HoverPosition[HoverPoint].x; - disty = GlaivePosition[i].y - HoverPosition[HoverPoint].y; - dist[i] = distx * distx + disty * disty; - } - Locations final = GlaivePosition[dist[0] < dist[1] ? 0 : 1]; - - final.x = 2 * final.x - initial.x; - final.y = 2 * final.y - initial.y; - - Creature* Trigger = me->SummonCreature(23069, initial.x, initial.y, initial.z, 0, TEMPSUMMON_TIMED_DESPAWN, 13000); - if (!Trigger) return; - - Trigger->SetSpeed(MOVE_WALK, 3); - Trigger->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z); - - //Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetUInt64Value(UNIT_FIELD_TARGET, Trigger->GetGUID()); - DoCast(Trigger, SPELL_EYE_BLAST); -} - -void boss_illidan_stormrageAI::SummonFlamesOfAzzinoth() -{ - me->MonsterYell(SAY_SUMMONFLAMES, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_SUMMONFLAMES); - - for (uint8 i = 0; i < 2; ++i) - { - if (GETUNIT(Glaive, GlaiveGUID[i])) - { - Creature* Flame = me->SummonCreature(FLAME_OF_AZZINOTH, GlaivePosition[i+2].x, GlaivePosition[i+2].y, GlaivePosition[i+2].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - if (Flame) - { - Flame->setFaction(me->getFaction()); // Just in case the database has it as a different faction - Flame->SetMeleeDamageSchool(SPELL_SCHOOL_FIRE); - FlameGUID[i] = Flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase - CAST_AI(flame_of_azzinothAI, Flame->AI())->SetGlaiveGUID(GlaiveGUID[i]); - Glaive->CastSpell(Flame, SPELL_AZZINOTH_CHANNEL, false); // Glaives do some random Beam type channel on it. - } - } - } -} - -void boss_illidan_stormrageAI::SummonMaiev() -{ - DoCast(me, SPELL_SHADOW_PRISON, true); - DoCast(me, 40403, true); - if (!MaievGUID) // If Maiev cannot be summoned, reset the encounter and post some errors to the console. - { - EnterEvadeMode(); - me->MonsterTextEmote(EMOTE_UNABLE_TO_SUMMON, 0); - error_log("SD2 ERROR: Unable to summon Maiev Shadowsong (entry: 23197). Check your database to see if you have the proper SQL for Maiev Shadowsong (entry: 23197)"); - } -} - -void boss_illidan_stormrageAI::EnterPhase(PhaseIllidan NextPhase) -{ - DoZoneInCombat(); - switch(NextPhase) - { - case PHASE_NORMAL: - case PHASE_NORMAL_2: - case PHASE_NORMAL_MAIEV: - AttackStart(me->getVictim()); - Timer[EVENT_TAUNT] = 32000; - Timer[EVENT_SHEAR] = 10000 + rand()%15 * 1000; - Timer[EVENT_FLAME_CRASH] = 20000; - Timer[EVENT_PARASITIC_SHADOWFIEND] = 25000; - Timer[EVENT_PARASITE_CHECK] = 0; - Timer[EVENT_DRAW_SOUL] = 30000; - if (NextPhase == PHASE_NORMAL) - break; - Timer[EVENT_AGONIZING_FLAMES] = 35000; - Timer[EVENT_TRANSFORM_NORMAL] = 60000; - if (NextPhase == PHASE_NORMAL_2) - break; - Timer[EVENT_ENRAGE] = 30000 + rand()%10 * 1000; - break; - case PHASE_FLIGHT: - Timer[EVENT_FIREBALL] = 1000; - if (!(rand()%4)) - Timer[EVENT_DARK_BARRAGE] = 10000; - Timer[EVENT_EYE_BLAST] = 10000 + rand()%15 * 1000; - Timer[EVENT_MOVE_POINT] = 20000 + rand()%20 * 1000; - break; - case PHASE_DEMON: - Timer[EVENT_SHADOW_BLAST] = 1000; - Timer[EVENT_FLAME_BURST] = 10000; - Timer[EVENT_SHADOWDEMON] = 30000; - Timer[EVENT_TRANSFORM_DEMON] = 60000; - AttackStart(me->getVictim()); - break; - case PHASE_TALK_SEQUENCE: - Timer[EVENT_TALK_SEQUENCE] = 100; - me->RemoveAllAuras(); - me->InterruptNonMeleeSpells(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->GetMotionMaster()->Clear(false); - me->AttackStop(); - break; - case PHASE_FLIGHT_SEQUENCE: - if (Phase == PHASE_NORMAL) //lift off - { - FlightCount = 1; - Timer[EVENT_FLIGHT_SEQUENCE] = 1; - me->RemoveAllAuras(); - me->InterruptNonMeleeSpells(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->GetMotionMaster()->Clear(false); - me->AttackStop(); - } - else //land - Timer[EVENT_FLIGHT_SEQUENCE] = 2000; - break; - case PHASE_TRANSFORM_SEQUENCE: - if (Phase == PHASE_DEMON) - Timer[EVENT_TRANSFORM_SEQUENCE] = 500; - else - { - TransformCount = 0; - Timer[EVENT_TRANSFORM_SEQUENCE] = 500; - me->MonsterYell(SAY_MORPH, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_MORPH); - } - me->GetMotionMaster()->Clear(); - me->AttackStop(); - break; - default: - break; - } - if (MaievGUID) - { - GETCRE(Maiev, MaievGUID); - if (Maiev && Maiev->isAlive()) - Maiev->AI()->DoAction(NextPhase); - } - Phase = NextPhase; - Event = EVENT_NULL; -} - -CreatureAI* GetAI_boss_illidan_stormrage(Creature* pCreature) -{ - return new boss_illidan_stormrageAI (pCreature); -} - -CreatureAI* GetAI_npc_akama_at_illidan(Creature* pCreature) -{ - return new npc_akama_illidanAI(pCreature); -} - -CreatureAI* GetAI_boss_maiev(Creature* pCreature) -{ - return new boss_maievAI (pCreature); -} - -CreatureAI* GetAI_mob_flame_of_azzinoth(Creature* pCreature) -{ - return new flame_of_azzinothAI (pCreature); -} - -CreatureAI* GetAI_cage_trap_trigger(Creature* pCreature) -{ - return new cage_trap_triggerAI (pCreature); -} - -CreatureAI* GetAI_shadow_demon(Creature* pCreature) -{ - return new shadow_demonAI (pCreature); -} - -CreatureAI* GetAI_blade_of_azzinoth(Creature* pCreature) -{ - return new blade_of_azzinothAI (pCreature); -} - -CreatureAI* GetAI_parasitic_shadowfiend(Creature* pCreature) -{ - return new mob_parasitic_shadowfiendAI (pCreature); -} - -void AddSC_boss_illidan() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_illidan_stormrage"; - newscript->GetAI = &GetAI_boss_illidan_stormrage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_akama_illidan"; - newscript->GetAI = &GetAI_npc_akama_at_illidan; - newscript->pGossipHello = &GossipHello_npc_akama_at_illidan; - newscript->pGossipSelect = &GossipSelect_npc_akama_at_illidan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_maiev_shadowsong"; - newscript->GetAI = &GetAI_boss_maiev; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flame_of_azzinoth"; - newscript->GetAI = &GetAI_mob_flame_of_azzinoth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_blade_of_azzinoth"; - newscript->GetAI = &GetAI_blade_of_azzinoth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "gameobject_cage_trap"; - newscript->pGOHello = &GOHello_cage_trap; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_cage_trap_trigger"; - newscript->GetAI = &GetAI_cage_trap_trigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadow_demon"; - newscript->GetAI = &GetAI_shadow_demon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_parasitic_shadowfiend"; - newscript->GetAI = &GetAI_parasitic_shadowfiend; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/boss_mother_shahraz.cpp b/src/server/scripts/outland/black_temple/boss_mother_shahraz.cpp deleted file mode 100644 index 5949fc46511..00000000000 --- a/src/server/scripts/outland/black_temple/boss_mother_shahraz.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mother_Shahraz -SD%Complete: 80 -SDComment: Saber Lash missing, Fatal Attraction slightly incorrect; need to damage only if affected players are within range of each other -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -//Speech'n'Sounds -#define SAY_TAUNT1 -1564018 -#define SAY_TAUNT2 -1564019 -#define SAY_TAUNT3 -1564020 -#define SAY_AGGRO -1564021 -#define SAY_SPELL1 -1564022 -#define SAY_SPELL2 -1564023 -#define SAY_SPELL3 -1564024 -#define SAY_SLAY1 -1564025 -#define SAY_SLAY2 -1564026 -#define SAY_ENRAGE -1564027 -#define SAY_DEATH -1564028 - -//Spells -#define SPELL_BEAM_SINISTER 40859 -#define SPELL_BEAM_VILE 40860 -#define SPELL_BEAM_WICKED 40861 -#define SPELL_BEAM_SINFUL 40827 -#define SPELL_ATTRACTION 40871 -#define SPELL_SILENCING_SHRIEK 40823 -#define SPELL_ENRAGE 23537 -#define SPELL_SABER_LASH 40810//43267 -#define SPELL_SABER_LASH_IMM 43690 -#define SPELL_TELEPORT_VISUAL 40869 -#define SPELL_BERSERK 45078 - -uint32 PrismaticAuras[]= -{ - 40880, // Shadow - 40882, // Fire - 40883, // Nature - 40891, // Arcane - 40896, // Frost - 40897, // Holy -}; - -struct Locations -{ - float x,y,z; -}; - -static Locations TeleportPoint[]= -{ - {959.996, 212.576, 193.843}, - {932.537, 231.813, 193.838}, - {958.675, 254.767, 193.822}, - {946.955, 201.316, 192.535}, - {944.294, 149.676, 197.551}, - {930.548, 284.888, 193.367}, - {965.997, 278.398, 195.777} -}; - -struct boss_shahrazAI : public ScriptedAI -{ - boss_shahrazAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 TargetGUID[3]; - uint32 BeamTimer; - uint32 BeamCount; - uint32 CurrentBeam; - uint32 PrismaticShieldTimer; - uint32 FatalAttractionTimer; - uint32 FatalAttractionExplodeTimer; - uint32 ShriekTimer; - uint32 SaberTimer; - uint32 RandomYellTimer; - uint32 EnrageTimer; - uint32 ExplosionCount; - - bool Enraged; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, NOT_STARTED); - - for (uint8 i = 0; i<3; ++i) - TargetGUID[i] = 0; - - BeamTimer = 20000; // Timers may be incorrect - BeamCount = 0; - CurrentBeam = 0; // 0 - Sinister, 1 - Vile, 2 - Wicked, 3 - Sinful - PrismaticShieldTimer = 0; - FatalAttractionTimer = 60000; - FatalAttractionExplodeTimer = 70000; - ShriekTimer = 30000; - SaberTimer = 35000; - RandomYellTimer = 70000 + rand()%41 * 1000; - EnrageTimer = 600000; - ExplosionCount = 0; - - Enraged = false; - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, IN_PROGRESS); - - DoZoneInCombat(); - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - void TeleportPlayers() - { - uint32 random = rand()%7; - float X = TeleportPoint[random].x; - float Y = TeleportPoint[random].y; - float Z = TeleportPoint[random].z; - for (uint8 i = 0; i < 3; ++i) - { - Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - TargetGUID[i] = pUnit->GetGUID(); - pUnit->CastSpell(pUnit, SPELL_TELEPORT_VISUAL, true); - DoTeleportPlayer(pUnit, X, Y, Z, pUnit->GetOrientation()); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !Enraged) - { - Enraged = true; - DoCast(me, SPELL_ENRAGE, true); - DoScriptText(SAY_ENRAGE, me); - } - - //Randomly cast one beam. - if (BeamTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (!pTarget || !pTarget->isAlive()) - return; - - BeamTimer = 9000; - - switch(CurrentBeam) - { - case 0: - DoCast(pTarget, SPELL_BEAM_SINISTER); - break; - case 1: - DoCast(pTarget, SPELL_BEAM_VILE); - break; - case 2: - DoCast(pTarget, SPELL_BEAM_WICKED); - break; - case 3: - DoCast(pTarget, SPELL_BEAM_SINFUL); - break; - } - ++BeamCount; - uint32 Beam = CurrentBeam; - if (BeamCount > 3) - while (CurrentBeam == Beam) - CurrentBeam = rand()%3; - - } else BeamTimer -= diff; - - // Random Prismatic Shield every 15 seconds. - if (PrismaticShieldTimer <= diff) - { - uint32 random = rand()%6; - if (PrismaticAuras[random]) - DoCast(me, PrismaticAuras[random]); - PrismaticShieldTimer = 15000; - } else PrismaticShieldTimer -= diff; - - // Select 3 random targets (can select same target more than once), teleport to a random location then make them cast explosions until they get away from each other. - if (FatalAttractionTimer <= diff) - { - ExplosionCount = 0; - - TeleportPlayers(); - - DoScriptText(RAND(SAY_SPELL2,SAY_SPELL3), me); - FatalAttractionExplodeTimer = 2000; - FatalAttractionTimer = 40000 + rand()%31 * 1000; - } else FatalAttractionTimer -= diff; - - if (FatalAttractionExplodeTimer <= diff) - { - // Just make them explode three times... they're supposed to keep exploding while they are in range, but it'll take too much code. I'll try to think of an efficient way for it later. - if (ExplosionCount < 3) - { - for (uint8 i = 0; i < 3; ++i) - { - Unit* pUnit = NULL; - if (TargetGUID[i]) - { - pUnit = Unit::GetUnit((*me), TargetGUID[i]); - if (pUnit) - pUnit->CastSpell(pUnit, SPELL_ATTRACTION, true); - TargetGUID[i] = 0; - } - } - - ++ExplosionCount; - FatalAttractionExplodeTimer = 1000; - } - else - { - FatalAttractionExplodeTimer = FatalAttractionTimer + 2000; - ExplosionCount = 0; - } - } else FatalAttractionExplodeTimer -= diff; - - if (ShriekTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCING_SHRIEK); - ShriekTimer = 25000+rand()%10 * 1000; - } else ShriekTimer -= diff; - - if (SaberTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SABER_LASH); - SaberTimer = 25000+rand()%10 * 1000; - } else SaberTimer -= diff; - - //Enrage - if (!me->HasAura(SPELL_BERSERK)) - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - DoScriptText(SAY_ENRAGE, me); - } else EnrageTimer -= diff; - - //Random taunts - if (RandomYellTimer <= diff) - { - DoScriptText(RAND(SAY_TAUNT1,SAY_TAUNT2,SAY_TAUNT3), me); - RandomYellTimer = 60000 + rand()%91 * 1000; - } else RandomYellTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_shahraz(Creature* pCreature) -{ - return new boss_shahrazAI (pCreature); -} - -void AddSC_boss_mother_shahraz() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_mother_shahraz"; - newscript->GetAI = &GetAI_boss_shahraz; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/boss_reliquary_of_souls.cpp b/src/server/scripts/outland/black_temple/boss_reliquary_of_souls.cpp deleted file mode 100644 index 3e019a8dc35..00000000000 --- a/src/server/scripts/outland/black_temple/boss_reliquary_of_souls.cpp +++ /dev/null @@ -1,690 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Reliquary_of_Souls -SD%Complete: 90 -SDComment: -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" -#include "Spell.h" - -//Sound'n'speech -//Suffering -#define SUFF_SAY_FREED -1564047 -#define SUFF_SAY_AGGRO -1564048 -#define SUFF_SAY_SLAY1 -1564049 -#define SUFF_SAY_SLAY2 -1564050 -#define SUFF_SAY_SLAY3 -1564051 -#define SUFF_SAY_RECAP -1564052 -#define SUFF_SAY_AFTER -1564053 -#define SUFF_EMOTE_ENRAGE -1564054 - -//Desire -#define DESI_SAY_FREED -1564055 -#define DESI_SAY_SLAY1 -1564056 -#define DESI_SAY_SLAY2 -1564057 -#define DESI_SAY_SLAY3 -1564058 -#define DESI_SAY_SPEC -1564059 -#define DESI_SAY_RECAP -1564060 -#define DESI_SAY_AFTER -1564061 - -//Anger -#define ANGER_SAY_FREED -1564062 -#define ANGER_SAY_FREED2 -1564063 -#define ANGER_SAY_SLAY1 -1564064 -#define ANGER_SAY_SLAY2 -1564065 -#define ANGER_SAY_SPEC -1564066 -#define ANGER_SAY_BEFORE -1564067 -#define ANGER_SAY_DEATH -1564068 - -//Spells -#define AURA_OF_SUFFERING 41292 -#define AURA_OF_SUFFERING_ARMOR 42017 // linked aura, need core support -#define ESSENCE_OF_SUFFERING_PASSIVE 41296 // periodic trigger 41294 -#define ESSENCE_OF_SUFFERING_PASSIVE2 41623 -#define SPELL_FIXATE_TARGET 41294 // dummy, select target -#define SPELL_FIXATE_TAUNT 41295 // force taunt -#define SPELL_ENRAGE 41305 -#define SPELL_SOUL_DRAIN 41303 - -#define AURA_OF_DESIRE 41350 -#define AURA_OF_DESIRE_DAMAGE 41352 -#define SPELL_RUNE_SHIELD 41431 -#define SPELL_DEADEN 41410 -#define SPELL_SOUL_SHOCK 41426 - -#define AURA_OF_ANGER 41337 -#define SPELL_SELF_SEETHE 41364 // force cast 41520 -#define SPELL_ENEMY_SEETHE 41520 -#define SPELL_SOUL_SCREAM 41545 -#define SPELL_SPITE_TARGET 41376 // cast 41377 after 6 sec -#define SPELL_SPITE_DAMAGE 41377 - -#define ENSLAVED_SOUL_PASSIVE 41535 -#define SPELL_SOUL_RELEASE 41542 -#define SPELL_SUBMERGE 37550 //dropout 'head' - -#define CREATURE_ENSLAVED_SOUL 23469 -#define NUMBER_ENSLAVED_SOUL 8 - -struct Position2d -{ - float x,y; -}; - -static Position2d Coords[]= -{ - {450.4, 212.3}, - {542.1, 212.3}, - {542.1, 168.3}, - {542.1, 137.4}, - {450.4, 137.4}, - {450.4, 168.3} -}; - -struct npc_enslaved_soulAI : public ScriptedAI -{ - npc_enslaved_soulAI(Creature *c) : ScriptedAI(c) {} - - uint64 ReliquaryGUID; - - void Reset() {ReliquaryGUID = 0;} - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, ENSLAVED_SOUL_PASSIVE, true); - DoZoneInCombat(); - } - - void JustDied(Unit *killer); -}; - -struct boss_reliquary_of_soulsAI : public ScriptedAI -{ - boss_reliquary_of_soulsAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EssenceGUID = 0; - } - - ScriptedInstance* pInstance; - - uint64 EssenceGUID; - - uint32 Phase; - uint32 Counter; - uint32 Timer; - - uint32 SoulCount; - uint32 SoulDeathCount; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, NOT_STARTED); - - if (EssenceGUID) - { - if (Creature* Essence = Unit::GetCreature(*me, EssenceGUID)) - { - Essence->ForcedDespawn(); - } - EssenceGUID = 0; - } - - Phase = 0; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - me->RemoveAurasDueToSpell(SPELL_SUBMERGE); - } - - void EnterCombat(Unit* who) - { - me->AddThreat(who, 10000.0f); - DoZoneInCombat(); - if (pInstance) - pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, IN_PROGRESS); - - Phase = 1; - Counter = 0; - Timer = 0; - } - - bool SummonSoul() - { - uint32 random = rand()%6; - float x = Coords[random].x; - float y = Coords[random].y; - Creature* Soul = me->SummonCreature(CREATURE_ENSLAVED_SOUL, x, y, me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0); - if (!Soul) return false; - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - CAST_AI(npc_enslaved_soulAI, Soul->AI())->ReliquaryGUID = me->GetGUID(); - Soul->AI()->AttackStart(pTarget); - } else EnterEvadeMode(); - return true; - } - - void MergeThreatList(Creature *pTarget) - { - if (!pTarget) - return; - - std::list& m_threatlist = pTarget->getThreatManager().getThreatList(); - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit) - { - DoModifyThreatPercent(pUnit, -100); - float threat = pTarget->getThreatManager().getThreat(pUnit); - me->AddThreat(pUnit, threat); // This makes it so that the unit has the same amount of threat in Reliquary's threatlist as in the target creature's (One of the Essences). - } - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!Phase) - return; - - if (me->getThreatManager().getThreatList().empty()) // Reset if event is begun and we don't have a threatlist - { - EnterEvadeMode(); - return; - } - - Creature* Essence = NULL; - if (EssenceGUID) - { - Essence = Unit::GetCreature(*me, EssenceGUID); - if (!Essence) - { - EnterEvadeMode(); - return; - } - } - - if (Timer <= diff) - { - switch(Counter) - { - case 0: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); // I R ANNNGRRRY! - DoStartNoMovement(me); - Timer = 3000; - break; - case 1: - Timer = 2800; - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_SUBMERGE); // Release the cube - DoCast(me, SPELL_SUBMERGE); - DoStartNoMovement(me); - break; - case 2: - Timer = 5000; - if (Creature* Summon = DoSpawnCreature(23417+Phase, 0, 0, 0, 0, TEMPSUMMON_DEAD_DESPAWN, 0)) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED); // Ribs: open - Summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_TOPAGGRO, 0)); - EssenceGUID = Summon->GetGUID(); - DoStartNoMovement(me); - } else EnterEvadeMode(); - break; - case 3: - Timer = 1000; - if (Phase == 3) - { - if (!Essence->isAlive()) - DoCast(me, 7, true); - else return; - } - else - { - if (Essence->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - { - MergeThreatList(Essence); - Essence->RemoveAllAuras(); - Essence->DeleteThreatList(); - Essence->GetMotionMaster()->MoveFollow(me,0.0f,0.0f); - } else return; - } - break; - case 4: - Timer = 1500; - if (Essence->IsWithinDistInMap(me, 10)) - { - Essence->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); //rotate and disappear - Timer = 2000; - me->RemoveAurasDueToSpell(SPELL_SUBMERGE); - } - else - { - MergeThreatList(Essence); - Essence->RemoveAllAuras(); - Essence->DeleteThreatList(); - Essence->GetMotionMaster()->MoveFollow(me, 0, 0); - return; - } - break; - case 5: - if (Phase == 1) - { - DoScriptText(SUFF_SAY_AFTER, Essence); - } - else - { - DoScriptText(DESI_SAY_AFTER, Essence); - } - Essence->ForcedDespawn(); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE,0); - EssenceGUID = 0; - SoulCount = 0; - SoulDeathCount = 0; - Timer = 3000; - break; - case 6: - if (SoulCount < NUMBER_ENSLAVED_SOUL) - { - if (SummonSoul()) - ++SoulCount; - Timer = 500; - return; - } - break; - case 7: - if (SoulDeathCount >= SoulCount) - { - Counter = 1; - ++Phase; - Timer = 5000; - } - return; - default: - break; - } - ++Counter; - } else Timer -= diff; - } -}; - -struct boss_essence_of_sufferingAI : public ScriptedAI -{ - boss_essence_of_sufferingAI(Creature *c) : ScriptedAI(c) {} - - uint64 StatAuraGUID; - - uint32 AggroYellTimer; - uint32 FixateTimer; - uint32 EnrageTimer; - uint32 SoulDrainTimer; - uint32 AuraTimer; - - void Reset() - { - StatAuraGUID = 0; - - AggroYellTimer = 5000; - FixateTimer = 8000; - EnrageTimer = 30000; - SoulDrainTimer = 45000; - AuraTimer = 5000; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - damage = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->Yell(SUFF_SAY_RECAP,LANG_UNIVERSAL,0); - DoScriptText(SUFF_SAY_RECAP, me); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - { - DoScriptText(SUFF_SAY_FREED, me); - DoZoneInCombat(); - DoCast(me, AURA_OF_SUFFERING, true); // linked aura need core support - DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE, true); - DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE2, true); - } - else return; - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SUFF_SAY_SLAY1,SUFF_SAY_SLAY2,SUFF_SAY_SLAY3), me); - } - - void CastFixate() - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - if (m_threatlist.empty()) - return; // No point continuing if empty threatlist. - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) // Only alive players - targets.push_back(pUnit); - } - if (targets.empty()) - return; // No targets added for some reason. No point continuing. - targets.sort(Trinity::ObjectDistanceOrderPred(me)); // Sort players by distance. - targets.resize(1); // Only need closest target. - Unit *pTarget = targets.front(); // Get the first target. - if (pTarget) - pTarget->CastSpell(me, SPELL_FIXATE_TAUNT, true); - DoResetThreat(); - me->AddThreat(pTarget,1000000); - } - - void UpdateAI(const uint32 diff) - { - if (me->isInCombat()) - { - //Supposed to be cast on nearest target - if (FixateTimer <= diff) - { - CastFixate(); - FixateTimer = 5000; - if (!(rand()%16)) - { - DoScriptText(SUFF_SAY_AGGRO, me); - } - } else FixateTimer -= diff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - EnrageTimer = 60000; - DoScriptText(SUFF_EMOTE_ENRAGE, me); - } else EnrageTimer -= diff; - - if (SoulDrainTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SOUL_DRAIN); - SoulDrainTimer = 60000; - } else SoulDrainTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_essence_of_desireAI : public ScriptedAI -{ - boss_essence_of_desireAI(Creature *c) : ScriptedAI(c) {} - - uint32 RuneShieldTimer; - uint32 DeadenTimer; - uint32 SoulShockTimer; - - void Reset() - { - RuneShieldTimer = 60000; - DeadenTimer = 30000; - SoulShockTimer = 5000; - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_CONFUSE, true); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by == me) - return; - - if (damage >= me->GetHealth()) - { - damage = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoScriptText(SUFF_SAY_RECAP, me); - } - else - { - int32 bp0 = damage / 2; - me->CastCustomSpell(done_by, AURA_OF_DESIRE_DAMAGE, &bp0, NULL, NULL, true); - } - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)) - for (uint8 i = 0; i < 3; ++i) - if (spell->Effect[i] == SPELL_EFFECT_INTERRUPT_CAST) - if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_SOUL_SHOCK - || me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_DEADEN) - me->InterruptSpell(CURRENT_GENERIC_SPELL, false); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(DESI_SAY_FREED, me); - DoZoneInCombat(); - DoCast(me, AURA_OF_DESIRE, true); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(DESI_SAY_SLAY1,DESI_SAY_SLAY2,DESI_SAY_SLAY3), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (RuneShieldTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_RUNE_SHIELD, true); - SoulShockTimer += 2000; - DeadenTimer += 2000; - RuneShieldTimer = 60000; - } else RuneShieldTimer -= diff; - - if (SoulShockTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOUL_SHOCK); - SoulShockTimer = 5000; - } else SoulShockTimer -= diff; - - if (DeadenTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me->getVictim(), SPELL_DEADEN); - DeadenTimer = 25000 + rand()%10000; - if (!(rand()%2)) - { - DoScriptText(DESI_SAY_SPEC, me); - } - } else DeadenTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_essence_of_angerAI : public ScriptedAI -{ - boss_essence_of_angerAI(Creature *c) : ScriptedAI(c) {} - - uint64 AggroTargetGUID; - - uint32 CheckTankTimer; - uint32 SoulScreamTimer; - uint32 SpiteTimer; - - std::list SpiteTargetGUID; - - bool CheckedAggro; - - void Reset() - { - AggroTargetGUID = 0; - - CheckTankTimer = 5000; - SoulScreamTimer = 10000; - SpiteTimer = 30000; - - SpiteTargetGUID.clear(); - - CheckedAggro = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(ANGER_SAY_FREED,ANGER_SAY_FREED2), me); - - DoZoneInCombat(); - DoCast(me, AURA_OF_ANGER, true); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(ANGER_SAY_DEATH, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(ANGER_SAY_SLAY1,ANGER_SAY_SLAY2), me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!CheckedAggro) - { - AggroTargetGUID = me->getVictim()->GetGUID(); - CheckedAggro = true; - } - - if (CheckTankTimer <= diff) - { - if (me->getVictim()->GetGUID() != AggroTargetGUID) - { - DoScriptText(ANGER_SAY_BEFORE, me); - DoCast(me, SPELL_SELF_SEETHE, true); - AggroTargetGUID = me->getVictim()->GetGUID(); - } - CheckTankTimer = 2000; - } else CheckTankTimer -= diff; - - if (SoulScreamTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOUL_SCREAM); - SoulScreamTimer = 9000 + rand()%2000; - if (!(rand()%3)) - { - DoScriptText(ANGER_SAY_SPEC, me); - } - } else SoulScreamTimer -= diff; - - if (SpiteTimer <= diff) - { - DoCast(me, SPELL_SPITE_TARGET); - SpiteTimer = 30000; - DoScriptText(ANGER_SAY_SPEC, me); - } else SpiteTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -void npc_enslaved_soulAI::JustDied(Unit * /*killer*/) -{ - if (ReliquaryGUID) - if (Creature *Reliquary = (Unit::GetCreature((*me), ReliquaryGUID))) - ++(CAST_AI(boss_reliquary_of_soulsAI, Reliquary->AI())->SoulDeathCount); - - DoCast(me, SPELL_SOUL_RELEASE, true); -} - -CreatureAI* GetAI_boss_reliquary_of_souls(Creature* pCreature) -{ - return new boss_reliquary_of_soulsAI (pCreature); -} - -CreatureAI* GetAI_boss_essence_of_suffering(Creature* pCreature) -{ - return new boss_essence_of_sufferingAI (pCreature); -} - -CreatureAI* GetAI_boss_essence_of_desire(Creature* pCreature) -{ - return new boss_essence_of_desireAI (pCreature); -} - -CreatureAI* GetAI_boss_essence_of_anger(Creature* pCreature) -{ - return new boss_essence_of_angerAI (pCreature); -} - -CreatureAI* GetAI_npc_enslaved_soul(Creature* pCreature) -{ - return new npc_enslaved_soulAI (pCreature); -} - -void AddSC_boss_reliquary_of_souls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_reliquary_of_souls"; - newscript->GetAI = &GetAI_boss_reliquary_of_souls; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_essence_of_suffering"; - newscript->GetAI = &GetAI_boss_essence_of_suffering; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_essence_of_desire"; - newscript->GetAI = &GetAI_boss_essence_of_desire; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_essence_of_anger"; - newscript->GetAI = &GetAI_boss_essence_of_anger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_enslaved_soul"; - newscript->GetAI = &GetAI_npc_enslaved_soul; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/boss_shade_of_akama.cpp b/src/server/scripts/outland/black_temple/boss_shade_of_akama.cpp deleted file mode 100644 index 94f88d5715c..00000000000 --- a/src/server/scripts/outland/black_temple/boss_shade_of_akama.cpp +++ /dev/null @@ -1,871 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Shade_of_Akama -SD%Complete: 90 -SDComment: Seems to be complete. -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -#define SAY_DEATH -1564013 -#define SAY_LOW_HEALTH -1564014 -// Ending cinematic text -#define SAY_FREE -1564015 -#define SAY_BROKEN_FREE_01 -1564016 -#define SAY_BROKEN_FREE_02 -1564017 - -#define GOSSIP_ITEM "We are ready to fight alongside you, Akama" - -struct Location -{ - float x, y, o, z; -}; - -static Location ChannelerLocations[]= -{ - {463.161285, 401.219757, 3.141592}, - {457.377625, 391.227661, 2.106461}, - {446.012421, 391.227661, 1.071904}, - {439.533783, 401.219757, 0.000000}, - {446.012421, 411.211853, 5.210546}, - {457.377625, 411.211853, 4.177494} -}; - -static Location SpawnLocations[]= -{ - {498.652740, 461.728119, 0}, - {498.505003, 339.619324, 0} -}; - -static Location AkamaWP[]= -{ - {482.352448, 401.162720, 0, 112.783928}, - {469.597443, 402.264404, 0, 118.537910} -}; - -static Location BrokenCoords[]= -{ - {541.375916, 401.439575, M_PI, 112.783997}, // The place where Akama channels - {534.130005, 352.394531, 2.164150, 112.783737}, // Behind a 'pillar' which is behind the east alcove - {499.621185, 341.534729, 1.652856, 112.783730}, // East Alcove - {499.151093, 461.036438, 4.770888, 112.78370}, // West Alcove -}; - -static Location BrokenWP[]= -{ - {492.491638, 400.744690, 3.122336, 112.783737}, - {494.335724, 382.221771, 2.676230, 112.783737}, - {489.555939, 373.507202, 2.416263, 112.783737}, - {491.136353, 427.868774, 3.519748, 112.783737}, -}; - -// Locations -#define Z1 118.543144 -#define Z2 120.783768 -#define Z_SPAWN 113.537949 -#define AGGRO_X 482.793182 -#define AGGRO_Y 401.270172 -#define AGGRO_Z 112.783928 -#define AKAMA_X 514.583984 -#define AKAMA_Y 400.601013 -#define AKAMA_Z 112.783997 - -// Spells -#define SPELL_VERTEX_SHADE_BLACK 39833 -#define SPELL_SHADE_SOUL_CHANNEL 40401 -#define SPELL_DESTRUCTIVE_POISON 40874 -#define SPELL_LIGHTNING_BOLT 42024 -#define SPELL_AKAMA_SOUL_CHANNEL 40447 -#define SPELL_AKAMA_SOUL_RETRIEVE 40902 -#define AKAMA_SOUL_EXPEL 40855 -#define SPELL_SHADE_SOUL_CHANNEL_2 40520 - -// Channeler entry -#define CREATURE_CHANNELER 23421 -#define CREATURE_SORCERER 23215 -#define CREATURE_DEFENDER 23216 -#define CREATURE_BROKEN 23319 - -const uint32 spawnEntries[4]= { 23523, 23318, 23524 }; - -struct mob_ashtongue_channelerAI : public ScriptedAI -{ - mob_ashtongue_channelerAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;} - - uint64 ShadeGUID; - - void Reset() {} - void JustDied(Unit* /*killer*/); - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -struct mob_ashtongue_sorcererAI : public ScriptedAI -{ - mob_ashtongue_sorcererAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;} - - uint64 ShadeGUID; - uint32 CheckTimer; - bool StartBanishing; - - void Reset() - { - StartBanishing = false; - CheckTimer = 5000; - } - - void JustDied(Unit* /*killer*/); - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (StartBanishing) - return; - - if (CheckTimer <= diff) - { - Creature* Shade = Unit::GetCreature((*me), ShadeGUID); - if (Shade && Shade->isAlive() && me->isAlive()) - { - if (me->IsWithinDist(Shade, 20,false)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL, true); - DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL_2, true); - - StartBanishing = true; - } - } - CheckTimer = 2000; - } else CheckTimer -= diff; - } -}; - -struct boss_shade_of_akamaAI : public ScriptedAI -{ - boss_shade_of_akamaAI(Creature* c) : ScriptedAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - AkamaGUID = pInstance ? pInstance->GetData64(DATA_AKAMA_SHADE) : 0; - me->setActive(true);//if view distance is too low - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); - } - - ScriptedInstance* pInstance; - - std::list Channelers; - std::list Sorcerers; - uint64 AkamaGUID; - - uint32 SorcererCount; - uint32 DeathCount; - - uint32 ReduceHealthTimer; - uint32 SummonTimer; - uint32 ResetTimer; - uint32 DefenderTimer; // They are on a flat 15 second timer, independant of the other summon Creature timer. - - bool IsBanished; - bool HasKilledAkama; - bool reseting; - bool GridSearcherSucceeded; - bool HasKilledAkamaAndReseting; - SummonList summons; - - void Reset() - { - reseting = true; - HasKilledAkamaAndReseting = false; - - GridSearcherSucceeded = false; - - Sorcerers.clear(); - summons.DespawnAll();//despawn all adds - - if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) - { - Akama->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//turn gossip on so players can restart the event - if (Akama->isDead()) - { - Akama->Respawn();//respawn akama if dead - Akama->AI()->EnterEvadeMode(); - } - } - SorcererCount = 0; - DeathCount = 0; - - SummonTimer = 10000; - ReduceHealthTimer = 0; - ResetTimer = 60000; - DefenderTimer = 15000; - - IsBanished = true; - HasKilledAkama = false; - - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //me->GetMotionMaster()->Clear(); - //me->GetMotionMaster()->MoveIdle(); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); - - if (pInstance) - pInstance->SetData(DATA_SHADEOFAKAMAEVENT, NOT_STARTED); - - reseting = false; - } - void JustDied(Unit* /*killer*/) - { - summons.DespawnAll(); - } - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524) - summons.Summon(summon); - } - void SummonedCreatureDespawn(Creature *summon) - { - if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524) - summons.Despawn(summon); - } - - void MoveInLineOfSight(Unit * /*who*/) - { - if (!GridSearcherSucceeded) - { - FindChannelers(); - - if (!Channelers.empty()) - { - for (std::list::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - { - Creature* Channeler = (Unit::GetCreature(*me, *itr)); - if (Channeler) - { - if (Channeler->isDead()) - { - Channeler->RemoveCorpse(); - Channeler->Respawn(); - } - - Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true); - Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL_2, true); - Channeler->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - GridSearcherSucceeded = true; - } - } - } else error_log("SD2 ERROR: No Channelers are stored in the list. This encounter will not work properly"); - } - } - - void AttackStart(Unit* who) - { - if (!who || IsBanished) return; - - if (who->isTargetableForAttack() && who != me) - DoStartMovement(who); - } - - void IncrementDeathCount(uint64 guid = 0) // If guid is set, will remove it from list of sorcerer - { - if (reseting) - return; - - debug_log("TSCR: Increasing Death Count for Shade of Akama encounter"); - ++DeathCount; - me->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2); - if (guid) - { - if (Sorcerers.empty()) - error_log("SD2 ERROR: Shade of Akama - attempt to remove guid %u from Sorcerers list but list is already empty", guid); - else Sorcerers.remove(guid); - } - } - - void SummonCreature() - { - uint32 random = rand()%2; - float X = SpawnLocations[random].x; - float Y = SpawnLocations[random].y; - // max of 6 sorcerers can be summoned - if ((rand()%3 == 0) && (DeathCount > 0) && (SorcererCount < 7)) - { - Creature* Sorcerer = me->SummonCreature(CREATURE_SORCERER, X, Y, Z_SPAWN, 0, TEMPSUMMON_DEAD_DESPAWN, 0); - if (Sorcerer) - { - CAST_AI(mob_ashtongue_sorcererAI, Sorcerer->AI())->ShadeGUID = me->GetGUID(); - Sorcerer->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Sorcerer->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); - Sorcerer->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - Sorcerers.push_back(Sorcerer->GetGUID()); - --DeathCount; - ++SorcererCount; - } - } - else - { - for (uint8 i = 0; i < 3; ++i) - { - Creature* Spawn = me->SummonCreature(spawnEntries[i], X, Y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); - if (Spawn) - { - Spawn->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Spawn->GetMotionMaster()->MovePoint(0, AGGRO_X, AGGRO_Y, AGGRO_Z); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - Spawn->AI()->AttackStart(pTarget); - } - } - } - } - - void FindChannelers() - { - std::list ChannelerList; - me->GetCreatureListWithEntryInGrid(ChannelerList,CREATURE_CHANNELER,50.0f); - - if (!ChannelerList.empty()) - { - for (std::list::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr) - { - CAST_AI(mob_ashtongue_channelerAI, (*itr)->AI())->ShadeGUID = me->GetGUID(); - Channelers.push_back((*itr)->GetGUID()); - debug_log("TSCR: Shade of Akama Grid Search found channeler %u. Adding to list", (*itr)->GetGUID()); - } - } - else error_log("SD2 ERROR: Grid Search was unable to find any channelers. Shade of Akama encounter will be buggy"); - } - - void SetSelectableChannelers() - { - if (Channelers.empty()) - { - error_log("SD2 ERROR: Channeler List is empty, Shade of Akama encounter will be buggy"); - return; - } - - for (std::list::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - if (Creature* Channeler = (Unit::GetCreature(*me, *itr))) - Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void SetAkamaGUID(uint64 guid) { AkamaGUID = guid; } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; - - if (IsBanished) - { - // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check - if (me->getThreatManager().getThreatList().size() < 2) - { - EnterEvadeMode(); - return; - } - - if (DefenderTimer <= diff) - { - uint32 ran = rand()%2; - Creature* Defender = me->SummonCreature(CREATURE_DEFENDER, SpawnLocations[ran].x, SpawnLocations[ran].y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); - if (Defender) - { - Defender->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - bool move = true; - if (AkamaGUID) - { - if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) - { - float x, y, z; - Akama->GetPosition(x,y,z); - // They move towards AKama - Defender->GetMotionMaster()->MovePoint(0, x, y, z); - Defender->AI()->AttackStart(Akama); - } else move = false; - } else move = false; - if (!move) - Defender->GetMotionMaster()->MovePoint(0, AKAMA_X, AKAMA_Y, AKAMA_Z); - } - DefenderTimer = 15000; - } else DefenderTimer -= diff; - - if (SummonTimer <= diff) - { - SummonCreature(); - SummonTimer = 35000; - } else SummonTimer -= diff; - - if (DeathCount >= 6) - { - if (AkamaGUID) - { - Creature* Akama = Unit::GetCreature((*me), AkamaGUID); - if (Akama && Akama->isAlive()) - { - IsBanished = false; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveChase(Akama); - Akama->GetMotionMaster()->Clear(); - // Shade should move to Akama, not the other way around - Akama->GetMotionMaster()->MoveIdle(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // Crazy amount of threat - me->AddThreat(Akama, 10000000.0f); - Akama->AddThreat(me, 10000000.0f); - me->Attack(Akama, true); - Akama->Attack(me, true); - } - } - } - } - else // No longer banished, let's fight Akama now - { - if (ReduceHealthTimer <= diff) - { - if (AkamaGUID) - { - Creature* Akama = Unit::GetCreature((*me), AkamaGUID); - if (Akama && Akama->isAlive()) - { - //10 % less health every few seconds. - me->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - ReduceHealthTimer = 12000; - } - } - } else ReduceHealthTimer -= diff; - - if (HasKilledAkama) - { - if (!HasKilledAkamaAndReseting)//do not let players kill Shade if Akama is dead and Shade is waiting for ResetTimer!! event would bug - { - HasKilledAkamaAndReseting = true; - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(); - //me->SetHealth(me->GetMaxHealth()); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->GetMotionMaster()->MoveTargetedHome(); - } - if (ResetTimer <= diff) - { - EnterEvadeMode();// Reset a little while after killing Akama, evade and respawn Akama - return; - } else ResetTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - } -}; - -void mob_ashtongue_channelerAI::JustDied(Unit* /*killer*/) -{ - Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); - if (Shade && Shade->isAlive()) - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(); - else error_log("SD2 ERROR: Channeler dead but unable to increment DeathCount for Shade of Akama."); -} - -void mob_ashtongue_sorcererAI::JustDied(Unit* /*killer*/) -{ - Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); - if (Shade && Shade->isAlive()) - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(me->GetGUID()); - else error_log("SD2 ERROR: Sorcerer dead but unable to increment DeathCount for Shade of Akama."); -} - -struct npc_akamaAI : public ScriptedAI -{ - npc_akamaAI(Creature* c) : ScriptedAI(c), summons(me) - { - ShadeHasDied = false; - StartCombat = false; - pInstance = c->GetInstanceData(); - ShadeGUID = pInstance ? pInstance->GetData64(DATA_SHADEOFAKAMA) : NOT_STARTED; - me->setActive(true); - EventBegun = false; - CastSoulRetrieveTimer = 0; - SoulRetrieveTimer = 0; - SummonBrokenTimer = 0; - EndingTalkCount = 0; - WayPointId = 0; - BrokenSummonIndex = 0; - BrokenList.clear(); - HasYelledOnce = false; - } - - ScriptedInstance* pInstance; - - uint64 ShadeGUID; - - uint32 DestructivePoisonTimer; - uint32 LightningBoltTimer; - uint32 CheckTimer; - uint32 CastSoulRetrieveTimer; - uint32 SoulRetrieveTimer; - uint32 SummonBrokenTimer; - uint32 EndingTalkCount; - uint32 WayPointId; - uint32 BrokenSummonIndex; - - std::list BrokenList; - - bool EventBegun; - bool ShadeHasDied; - bool StartCombat; - bool HasYelledOnce; - SummonList summons; - - void Reset() - { - DestructivePoisonTimer = 15000; - LightningBoltTimer = 10000; - CheckTimer = 2000; - - if (!EventBegun) - { - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has very very strange values - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - summons.DespawnAll(); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == CREATURE_BROKEN) - summons.Summon(summon); - } - void SummonedCreatureDespawn(Creature *summon) - { - if (summon->GetEntry() == CREATURE_BROKEN) - summons.Despawn(summon); - } - - void EnterCombat(Unit* /*who*/) {} - - void BeginEvent(Player* pl) - { - if (!pInstance) - return; - - ShadeGUID = pInstance->GetData64(DATA_SHADEOFAKAMA); - if (!ShadeGUID) - return; - - Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); - if (Shade) - { - pInstance->SetData(DATA_SHADEOFAKAMAEVENT, IN_PROGRESS); - // Prevent players from trying to restart event - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->SetAkamaGUID(me->GetGUID()); - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->SetSelectableChannelers(); - Shade->AddThreat(me, 1000000.0f); - me->CombatStart(Shade); - Shade->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - Shade->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (pl) Shade->AddThreat(pl, 1.0f); - DoZoneInCombat(Shade); - EventBegun = true; - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - switch(id) - { - case 0: ++WayPointId; break; - - case 1: - if (Creature* Shade = Unit::GetCreature(*me, ShadeGUID)) - { - me->SetUInt64Value(UNIT_FIELD_TARGET, ShadeGUID); - DoCast(Shade, SPELL_AKAMA_SOUL_RETRIEVE); - EndingTalkCount = 0; - SoulRetrieveTimer = 16000; - } - break; - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - EventBegun = false; - ShadeHasDied = false; - StartCombat = false; - CastSoulRetrieveTimer = 0; - SoulRetrieveTimer = 0; - SummonBrokenTimer = 0; - EndingTalkCount = 0; - WayPointId = 0; - BrokenSummonIndex = 0; - BrokenList.clear(); - HasYelledOnce = false; - Creature* Shade = Unit::GetCreature((*me), ShadeGUID); - if (Shade && Shade->isAlive()) - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->HasKilledAkama = true; - summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!EventBegun) - return; - - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 15 && !HasYelledOnce) - { - DoScriptText(SAY_LOW_HEALTH, me); - HasYelledOnce = true; - } - - if (ShadeGUID && !StartCombat) - { - Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); - if (Shade && Shade->isAlive()) - { - if (CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IsBanished) - { - if (CastSoulRetrieveTimer <= diff) - { - DoCast(Shade, SPELL_AKAMA_SOUL_CHANNEL); - CastSoulRetrieveTimer = 500; - } else CastSoulRetrieveTimer -= diff; - } - else - { - me->InterruptNonMeleeSpells(false); - StartCombat = true; - } - } - } - - if (ShadeHasDied && (WayPointId == 1)) - { - if (pInstance) - pInstance->SetData(DATA_SHADEOFAKAMAEVENT, DONE); - me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[1].x, AkamaWP[1].y, AkamaWP[1].z); - ++WayPointId; - } - - if (!ShadeHasDied && StartCombat) - { - if (CheckTimer <= diff) - { - if (ShadeGUID) - { - Creature* Shade = Unit::GetCreature((*me), ShadeGUID); - if (Shade && !Shade->isAlive()) - { - ShadeHasDied = true; - WayPointId = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z); - } - if (Shade && Shade->isAlive()) - { - if (Shade->getThreatManager().getThreatList().size() < 2) - Shade->AI()->EnterEvadeMode(); - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - } - - if (SummonBrokenTimer && BrokenSummonIndex < 4) - { - if (SummonBrokenTimer <= diff) - { - for (uint8 i = 0; i < 4; ++i) - { - float x = BrokenCoords[BrokenSummonIndex].x + (i*5); - float y = BrokenCoords[BrokenSummonIndex].y + (1*5); - float z = BrokenCoords[BrokenSummonIndex].z; - float o = BrokenCoords[BrokenSummonIndex].o; - Creature* Broken = me->SummonCreature(CREATURE_BROKEN, x, y, z, o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000); - if (Broken) - { - float wx = BrokenWP[BrokenSummonIndex].x + (i*5); - float wy = BrokenWP[BrokenSummonIndex].y + (i*5); - float wz = BrokenWP[BrokenSummonIndex].z; - Broken->GetMotionMaster()->MovePoint(0, wx, wy, wz); - Broken->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - BrokenList.push_back(Broken->GetGUID()); - } - } - ++BrokenSummonIndex; - SummonBrokenTimer = 1000; - } else SummonBrokenTimer -= diff; - } - - if (SoulRetrieveTimer) - if (SoulRetrieveTimer <= diff) - { - switch(EndingTalkCount) - { - case 0: - me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); - ++EndingTalkCount; - SoulRetrieveTimer = 2000; - SummonBrokenTimer = 1; - break; - case 1: - DoScriptText(SAY_FREE, me); - ++EndingTalkCount; - SoulRetrieveTimer = 25000; - break; - case 2: - if (!BrokenList.empty()) - { - bool Yelled = false; - for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if (Creature* pUnit = Unit::GetCreature(*me, *itr)) - { - if (!Yelled) - { - DoScriptText(SAY_BROKEN_FREE_01, pUnit); - Yelled = true; - } - pUnit->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); - } - } - ++EndingTalkCount; - SoulRetrieveTimer = 1500; - break; - case 3: - if (!BrokenList.empty()) - { - for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if (Creature* pUnit = Unit::GetCreature(*me, *itr)) - // This is the incorrect spell, but can't seem to find the right one. - pUnit->CastSpell(pUnit, 39656, true); - } - ++EndingTalkCount; - SoulRetrieveTimer = 5000; - break; - case 4: - if (!BrokenList.empty()) - { - for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if (Creature* pUnit = Unit::GetCreature((*me), *itr)) - pUnit->MonsterYell(SAY_BROKEN_FREE_02, LANG_UNIVERSAL, 0); - } - SoulRetrieveTimer = 0; - break; - } - } else SoulRetrieveTimer -= diff; - - if (!UpdateVictim()) - return; - - if (DestructivePoisonTimer <= diff) - { - Creature* Shade = Unit::GetCreature((*me), ShadeGUID); - if (Shade && Shade->isAlive()) - DoCast(Shade, SPELL_DESTRUCTIVE_POISON); - DestructivePoisonTimer = 15000; - } else DestructivePoisonTimer -= diff; - - if (LightningBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); - LightningBoltTimer = 10000; - } else LightningBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_shade_of_akama(Creature* pCreature) -{ - return new boss_shade_of_akamaAI (pCreature); -} - -CreatureAI* GetAI_mob_ashtongue_channeler(Creature* pCreature) -{ - return new mob_ashtongue_channelerAI (pCreature); -} - -CreatureAI* GetAI_mob_ashtongue_sorcerer(Creature* pCreature) -{ - return new mob_ashtongue_sorcererAI (pCreature); -} - -CreatureAI* GetAI_npc_akama_shade(Creature* pCreature) -{ - return new npc_akamaAI (pCreature); -} - -bool GossipSelect_npc_akama(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_akamaAI, pCreature->AI())->BeginEvent(pPlayer); - } - - return true; -} - -bool GossipHello_npc_akama(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->isAlive()) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - } - - return true; -} - -void AddSC_boss_shade_of_akama() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shade_of_akama"; - newscript->GetAI = &GetAI_boss_shade_of_akama; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ashtongue_channeler"; - newscript->GetAI = &GetAI_mob_ashtongue_channeler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ashtongue_sorcerer"; - newscript->GetAI = &GetAI_mob_ashtongue_sorcerer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_akama_shade"; - newscript->GetAI = &GetAI_npc_akama_shade; - newscript->pGossipHello = &GossipHello_npc_akama; - newscript->pGossipSelect = &GossipSelect_npc_akama; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/boss_supremus.cpp b/src/server/scripts/outland/black_temple/boss_supremus.cpp deleted file mode 100644 index bc1ea3ec673..00000000000 --- a/src/server/scripts/outland/black_temple/boss_supremus.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Supremus -SD%Complete: 95 -SDComment: Need to implement molten punch -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -#define EMOTE_NEW_TARGET -1564010 -#define EMOTE_PUNCH_GROUND -1564011 //DoScriptText(EMOTE_PUNCH_GROUND, me); -#define EMOTE_GROUND_CRACK -1564012 - -//Spells -#define SPELL_MOLTEN_PUNCH 40126 -#define SPELL_HATEFUL_STRIKE 41926 -#define SPELL_MOLTEN_FLAME 40980 -#define SPELL_VOLCANIC_ERUPTION 40117 -#define SPELL_VOLCANIC_SUMMON 40276 -#define SPELL_BERSERK 45078 - -#define CREATURE_VOLCANO 23085 -#define CREATURE_STALKER 23095 - -#define PHASE_STRIKE 1 -#define PHASE_CHASE 2 - -#define EVENT_BERSERK 1 -#define EVENT_SWITCH_PHASE 2 -#define EVENT_FLAME 3 -#define EVENT_VOLCANO 4 -#define EVENT_SWITCH_TARGET 5 -#define EVENT_HATEFUL_STRIKE 6 - -#define GCD_CAST 1 - -struct molten_flameAI : public NullCreatureAI -{ - molten_flameAI(Creature *c) : NullCreatureAI(c) {} - - void InitializeAI() - { - float x, y, z; - me->GetNearPoint(me, x, y, z, 1, 100, M_PI*2*rand_norm()); - me->GetMotionMaster()->MovePoint(0, x, y, z); - me->SetVisibility(VISIBILITY_OFF); - me->CastSpell(me,SPELL_MOLTEN_FLAME,true); - } -}; - -struct boss_supremusAI : public ScriptedAI -{ - boss_supremusAI(Creature *c) : ScriptedAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - SummonList summons; - uint32 phase; - - void Reset() - { - if (pInstance) - { - if (me->isAlive()) - { - pInstance->SetData(DATA_SUPREMUSEVENT, NOT_STARTED); - //ToggleDoors(true); - } - //else ToggleDoors(false); - } - - phase = 0; - - events.Reset(); - summons.DespawnAll(); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_SUPREMUSEVENT, IN_PROGRESS); - - ChangePhase(); - events.ScheduleEvent(EVENT_BERSERK, 900000, GCD_CAST); - events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST); - } - - void ChangePhase() - { - if (!phase || phase == PHASE_CHASE) - { - phase = PHASE_STRIKE; - summons.DoAction(EVENT_VOLCANO, 0); - events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); - me->SetSpeed(MOVE_RUN, 1.2f); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); - } - else - { - phase = PHASE_CHASE; - events.ScheduleEvent(EVENT_VOLCANO, 5000, GCD_CAST, PHASE_CHASE); - events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); - me->SetSpeed(MOVE_RUN, 0.9f); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); - } - DoResetThreat(); - DoZoneInCombat(); - events.SetPhase(phase); - events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000, GCD_CAST); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_SUPREMUSEVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GAMEOBJECT_SUPREMUS_DOORS), true); - } - summons.DespawnAll(); - } - - void JustSummoned(Creature *summon) {summons.Summon(summon);} - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - - Unit* CalculateHatefulStrikeTarget() - { - uint32 health = 0; - Unit *pTarget = NULL; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - std::list::const_iterator i = m_threatlist.begin(); - for (i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && me->IsWithinMeleeRange(pUnit)) - { - if (pUnit->GetHealth() > health) - { - health = pUnit->GetHealth(); - pTarget = pUnit; - } - } - } - - return pTarget; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK, true); - break; - case EVENT_FLAME: - DoCast(me, SPELL_MOLTEN_PUNCH); - events.DelayEvents(1500, GCD_CAST); - events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST); - break; - case EVENT_HATEFUL_STRIKE: - if (Unit *pTarget = CalculateHatefulStrikeTarget()) - DoCast(pTarget, SPELL_HATEFUL_STRIKE); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); - break; - case EVENT_SWITCH_TARGET: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - { - DoResetThreat(); - me->AddThreat(pTarget, 5000000.0f); - DoScriptText(EMOTE_NEW_TARGET, me); - } - events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); - break; - case EVENT_VOLCANO: - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true); - if (!pTarget) pTarget = me->getVictim(); - if (pTarget) - { - //DoCast(pTarget, SPELL_VOLCANIC_SUMMON);//movement bugged - me->SummonCreature(CREATURE_VOLCANO,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); - DoScriptText(EMOTE_GROUND_CRACK, me); - events.DelayEvents(1500, GCD_CAST); - } - events.ScheduleEvent(EVENT_VOLCANO, 10000, GCD_CAST, PHASE_CHASE); - return; - } - case EVENT_SWITCH_PHASE: - ChangePhase(); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_volcanoAI : public Scripted_NoMovementAI -{ - npc_volcanoAI(Creature *c) : Scripted_NoMovementAI(c) {} - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //DoCast(me, SPELL_VOLCANIC_ERUPTION); - me->SetReactState(REACT_PASSIVE); - wait = 3000; - } - uint32 wait; - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void DoAction(const uint32 /*info*/) - { - me->RemoveAura(SPELL_VOLCANIC_ERUPTION); - } - - void UpdateAI(const uint32 diff) - { - if (wait <= diff)//wait 3secs before casting - { - DoCast(me, SPELL_VOLCANIC_ERUPTION); - wait = 60000; - } - else wait -= diff; - } - -}; - -CreatureAI* GetAI_boss_supremus(Creature* pCreature) -{ - return new boss_supremusAI (pCreature); -} - -CreatureAI* GetAI_molten_flame(Creature* pCreature) -{ - return new molten_flameAI (pCreature); -} - -CreatureAI* GetAI_npc_volcano(Creature* pCreature) -{ - return new npc_volcanoAI (pCreature); -} - -void AddSC_boss_supremus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_supremus"; - newscript->GetAI = &GetAI_boss_supremus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "molten_flame"; - newscript->GetAI = &GetAI_molten_flame; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_volcano"; - newscript->GetAI = &GetAI_npc_volcano; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/boss_teron_gorefiend.cpp b/src/server/scripts/outland/black_temple/boss_teron_gorefiend.cpp deleted file mode 100644 index 670edc4d869..00000000000 --- a/src/server/scripts/outland/black_temple/boss_teron_gorefiend.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Teron_Gorefiend -SD%Complete: 60 -SDComment: Requires Mind Control support for Ghosts. -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - - //Speech'n'sound -#define SAY_INTRO -1564037 -#define SAY_AGGRO -1564038 -#define SAY_SLAY1 -1564039 -#define SAY_SLAY2 -1564040 -#define SAY_SPELL1 -1564041 -#define SAY_SPELL2 -1564042 -#define SAY_SPECIAL1 -1564043 -#define SAY_SPECIAL2 -1564044 -#define SAY_ENRAGE -1564045 -#define SAY_DEATH -1564046 - -//Spells -#define SPELL_INCINERATE 40239 -#define SPELL_CRUSHING_SHADOWS 40243 -#define SPELL_SHADOWBOLT 40185 -#define SPELL_PASSIVE_SHADOWFORM 40326 -#define SPELL_SHADOW_OF_DEATH 40251 -#define SPELL_BERSERK 45078 - -#define SPELL_ATROPHY 40327 // Shadowy Constructs use this when they get within melee range of a player - -#define CREATURE_DOOM_BLOSSOM 23123 -#define CREATURE_SHADOWY_CONSTRUCT 23111 - -struct mob_doom_blossomAI : public ScriptedAI -{ - mob_doom_blossomAI(Creature *c) : ScriptedAI(c) {} - - uint32 CheckTeronTimer; - uint32 ShadowBoltTimer; - uint64 TeronGUID; - - void Reset() - { - CheckTeronTimer = 5000; - ShadowBoltTimer = 12000; - TeronGUID = 0; - } - - void EnterCombat(Unit * /*who*/) { } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void Despawn() - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - } - - void UpdateAI(const uint32 diff) - { - if (CheckTeronTimer <= diff) - { - if (TeronGUID) - { - DoZoneInCombat(); - - Creature* Teron = (Unit::GetCreature((*me), TeronGUID)); - if ((Teron) && (!Teron->isAlive() || Teron->IsInEvadeMode())) - Despawn(); - } - else - Despawn(); - - CheckTeronTimer = 5000; - } else CheckTeronTimer -= diff; - - if (ShadowBoltTimer < diff && me->isInCombat()) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOWBOLT); - ShadowBoltTimer = 10000; - } else ShadowBoltTimer -= diff; - return; - } - - void SetTeronGUID(uint64 guid){ TeronGUID = guid; } -}; - -struct mob_shadowy_constructAI : public ScriptedAI -{ - mob_shadowy_constructAI(Creature* c) : ScriptedAI(c) {} - - uint64 GhostGUID; - uint64 TeronGUID; - - uint32 CheckPlayerTimer; - uint32 CheckTeronTimer; - - void Reset() - { - GhostGUID = 0; - TeronGUID = 0; - - CheckPlayerTimer = 2000; - CheckTeronTimer = 5000; - } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (!who || (!who->isAlive()) || (who->GetGUID() == GhostGUID)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - -/* Comment it out for now. NOTE TO FUTURE DEV: UNCOMMENT THIS OUT ONLY AFTER MIND CONTROL IS IMPLEMENTED - void DamageTaken(Unit* done_by, uint32 &damage) - { - if (done_by->GetGUID() != GhostGUID) - damage = 0; // Only the ghost can deal damage. - } - */ - - void CheckPlayers() - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - if (m_threatlist.empty()) - return; // No threat list. Don't continue. - std::list::const_iterator itr = m_threatlist.begin(); - std::list targets; - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - targets.push_back(pUnit); - } - targets.sort(Trinity::ObjectDistanceOrderPred(me)); - Unit *pTarget = targets.front(); - if (pTarget && me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) - { - DoCast(pTarget, SPELL_ATROPHY); - me->AI()->AttackStart(pTarget); - } - } - - void UpdateAI(const uint32 diff) - { - if (CheckPlayerTimer <= diff) - { - CheckPlayers(); - CheckPlayerTimer = 3000; - } else CheckPlayerTimer -= diff; - - if (CheckTeronTimer <= diff) - { - Creature* Teron = (Unit::GetCreature((*me), TeronGUID)); - if (!Teron || !Teron->isAlive() || Teron->IsInEvadeMode()) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - - CheckTeronTimer = 5000; - } else CheckTeronTimer -= diff; - } -}; - -struct boss_teron_gorefiendAI : public ScriptedAI -{ - boss_teron_gorefiendAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 IncinerateTimer; - uint32 SummonDoomBlossomTimer; - uint32 EnrageTimer; - uint32 CrushingShadowsTimer; - uint32 ShadowOfDeathTimer; - uint32 SummonShadowsTimer; - uint32 RandomYellTimer; - uint32 AggroTimer; - - uint64 AggroTargetGUID; - uint64 GhostGUID; // Player that gets killed by Shadow of Death and gets turned into a ghost - - bool Intro; - bool Done; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_TERONGOREFIENDEVENT, NOT_STARTED); - - IncinerateTimer = 20000 + rand()%11000; - SummonDoomBlossomTimer = 12000; - EnrageTimer = 600000; - CrushingShadowsTimer = 22000; - SummonShadowsTimer = 60000; - RandomYellTimer = 50000; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // Start off unattackable so that the intro is done properly - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - AggroTimer = 20000; - AggroTargetGUID = 0; - Intro = false; - Done = false; - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit* pWho) - { - if (!Intro && pWho->GetTypeId() == TYPEID_PLAYER && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && pWho->isInAccessiblePlaceFor(me)) - { - if (me->IsWithinDistInMap(pWho, VISIBLE_RANGE) && me->IsWithinLOSInMap(pWho)) - { - if (pInstance) - pInstance->SetData(DATA_TERONGOREFIENDEVENT, IN_PROGRESS); - - me->GetMotionMaster()->Clear(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoScriptText(SAY_INTRO, me); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); - AggroTargetGUID = pWho->GetGUID(); - Intro = true; - } - } - if (Done) - ScriptedAI::MoveInLineOfSight(pWho); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_TERONGOREFIENDEVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - float CalculateRandomLocation(float Loc, uint32 radius) - { - float coord = Loc; - switch (urand(0,1)) - { - case 0: - coord += rand()%radius; - break; - case 1: - coord -= rand()%radius; - break; - } - return coord; - } - - void SetThreatList(Creature* Blossom) - { - if (!Blossom) return; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - std::list::const_iterator i = m_threatlist.begin(); - for (i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - { - float threat = DoGetThreat(pUnit); - Blossom->AddThreat(pUnit, threat); - } - } - } - - void MindControlGhost() - { - /************************************************************************/ - /** NOTE FOR FUTURE DEVELOPER: PROPERLY IMPLEMENT THE GHOST PORTION *****/ - /** ONLY AFTER TrinIty FULLY IMPLEMENTS MIND CONTROL ABILITIES *****/ - /** THE CURRENT CODE IN THIS FUNCTION IS ONLY THE BEGINNING OF *****/ - /** WHAT IS FULLY NECESSARY FOR GOREFIEND TO BE 100% COMPLETE *****/ - /************************************************************************/ - - Unit* Ghost = NULL; - if (GhostGUID) - Ghost = Unit::GetUnit((*me), GhostGUID); - if (Ghost && Ghost->isAlive() && Ghost->HasAura(SPELL_SHADOW_OF_DEATH)) - { - /*float x,y,z; - Ghost->GetPosition(x,y,z); - Creature* control = me->SummonCreature(CREATURE_GHOST, x, y, z, 0, TEMPSUMMON_TIMED_DESAWN, 30000); - if (control) - { - CAST_PLR(Ghost)->Possess(control); - Ghost->DealDamage(Ghost, Ghost->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, - false); - }*/ - for (uint8 i = 0; i < 4; ++i) - { - Creature* Construct = NULL; - float X = CalculateRandomLocation(Ghost->GetPositionX(), 10); - float Y = CalculateRandomLocation(Ghost->GetPositionY(), 10); - Construct = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, Y, Ghost->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); - if (Construct) - { - Construct->CastSpell(Construct, SPELL_PASSIVE_SHADOWFORM, true); - SetThreatList(Construct); // Use same function as Doom Blossom to set Threat List. - CAST_AI(mob_shadowy_constructAI, Construct->AI())->GhostGUID = GhostGUID; - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) // someone's trying to solo. - pTarget = me->getVictim(); - - if (pTarget) - Construct->GetMotionMaster()->MoveChase(pTarget); - } - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Intro && !Done) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoScriptText(SAY_AGGRO, me); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - Done = true; - if (AggroTargetGUID) - { - Unit* pUnit = Unit::GetUnit((*me), AggroTargetGUID); - if (pUnit) - AttackStart(pUnit); - - DoZoneInCombat(); - } - else - { - EnterEvadeMode(); - return; - } - } else AggroTimer -= diff; - } - - if (!UpdateVictim() || !Done) - return; - - if (SummonShadowsTimer <= diff) - { - //MindControlGhost(); - - for (uint8 i = 0; i < 2; ++i) - { - Creature* Shadow = NULL; - float X = CalculateRandomLocation(me->GetPositionX(), 10); - Shadow = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 0); - if (Shadow) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget) - Shadow->AI()->AttackStart(pTarget); - } - } - SummonShadowsTimer = 60000; - } else SummonShadowsTimer -= diff; - - if (SummonDoomBlossomTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float X = CalculateRandomLocation(pTarget->GetPositionX(), 20); - float Y = CalculateRandomLocation(pTarget->GetPositionY(), 20); - float Z = pTarget->GetPositionZ(); - Z = me->GetMap()->GetHeight(X, Y, Z); - Creature* DoomBlossom = me->SummonCreature(CREATURE_DOOM_BLOSSOM, X, Y, Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); - if (DoomBlossom) - { - DoomBlossom->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoomBlossom->setFaction(me->getFaction()); - DoomBlossom->AddThreat(pTarget, 1.0f); - CAST_AI(mob_doom_blossomAI, DoomBlossom->AI())->SetTeronGUID(me->GetGUID()); - pTarget->CombatStart(DoomBlossom); - SetThreatList(DoomBlossom); - SummonDoomBlossomTimer = 35000; - } - } - } else SummonDoomBlossomTimer -= diff; - - if (IncinerateTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget) - { - DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); - DoCast(pTarget, SPELL_INCINERATE); - IncinerateTimer = 20000 + rand()%31 * 1000; - } - } else IncinerateTimer -= diff; - - if (CrushingShadowsTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, SPELL_CRUSHING_SHADOWS); - CrushingShadowsTimer = 10000 + rand()%16 * 1000; - } else CrushingShadowsTimer -= diff; - - /*** NOTE FOR FUTURE DEV: UNCOMMENT BELOW ONLY IF MIND CONTROL IS FULLY IMPLEMENTED **/ - /*if (ShadowOfDeathTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, SPELL_SHADOW_OF_DEATH); - GhostGUID = pTarget->GetGUID(); - ShadowOfDeathTimer = 30000; - SummonShadowsTimer = 53000; // Make it VERY close but slightly less so that we can check if the aura is still on the player - } - } else ShadowOfDeathTimer -= diff;*/ - - if (RandomYellTimer <= diff) - { - DoScriptText(RAND(SAY_SPELL1,SAY_SPELL2), me); - RandomYellTimer = 50000 + rand()%51 * 1000; - } else RandomYellTimer -= diff; - - if (!me->HasAura(SPELL_BERSERK)) - { - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - DoScriptText(SAY_ENRAGE, me); - } else EnrageTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_doom_blossom(Creature* pCreature) -{ - return new mob_doom_blossomAI(pCreature); -} - -CreatureAI* GetAI_mob_shadowy_construct(Creature* pCreature) -{ - return new mob_shadowy_constructAI(pCreature); -} - -CreatureAI* GetAI_boss_teron_gorefiend(Creature* pCreature) -{ - return new boss_teron_gorefiendAI (pCreature); -} - -void AddSC_boss_teron_gorefiend() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_doom_blossom"; - newscript->GetAI = &GetAI_mob_doom_blossom; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadowy_construct"; - newscript->GetAI = &GetAI_mob_shadowy_construct; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_teron_gorefiend"; - newscript->GetAI = &GetAI_boss_teron_gorefiend; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/boss_warlord_najentus.cpp b/src/server/scripts/outland/black_temple/boss_warlord_najentus.cpp deleted file mode 100644 index 7d94b4b36a0..00000000000 --- a/src/server/scripts/outland/black_temple/boss_warlord_najentus.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warlord_Najentus -SD%Complete: 95 -SDComment: -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -enum eEnums -{ - SAY_AGGRO = -1564000, - SAY_NEEDLE1 = -1564001, - SAY_NEEDLE2 = -1564002, - SAY_SLAY1 = -1564003, - SAY_SLAY2 = -1564004, - SAY_SPECIAL1 = -1564005, - SAY_SPECIAL2 = -1564006, - SAY_ENRAGE1 = -1564007, //is this text actually in use? - SAY_ENRAGE2 = -1564008, - SAY_DEATH = -1564009, - - //Spells - SPELL_NEEDLE_SPINE = 39992, - SPELL_TIDAL_BURST = 39878, - SPELL_TIDAL_SHIELD = 39872, - SPELL_IMPALING_SPINE = 39837, - SPELL_CREATE_NAJENTUS_SPINE = 39956, - SPELL_HURL_SPINE = 39948, - SPELL_BERSERK = 26662, - - GOBJECT_SPINE = 185584, - - EVENT_BERSERK = 1, - EVENT_YELL = 2, - EVENT_NEEDLE = 3, - EVENT_SPINE = 4, - EVENT_SHIELD = 5, - - GCD_CAST = 1, - GCD_YELL = 2 -}; - -struct boss_najentusAI : public ScriptedAI -{ - boss_najentusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - uint64 SpineTargetGUID; - - void Reset() - { - events.Reset(); - - SpineTargetGUID = 0; - - if (pInstance) - pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(rand()%2 ? SAY_SLAY1 : SAY_SLAY2, me); - events.DelayEvents(5000, GCD_YELL); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_HURL_SPINE && me->HasAura(SPELL_TIDAL_SHIELD)) - { - me->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD); - DoCast(me, SPELL_TIDAL_BURST, true); - ResetTimer(); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, IN_PROGRESS); - - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_BERSERK, 480000, GCD_CAST); - events.ScheduleEvent(EVENT_YELL, 45000 + (rand()%76)*1000, GCD_YELL); - ResetTimer(); - } - - bool RemoveImpalingSpine() - { - if (!SpineTargetGUID) return false; - Unit *pTarget = Unit::GetUnit(*me, SpineTargetGUID); - if (pTarget && pTarget->HasAura(SPELL_IMPALING_SPINE)) - pTarget->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE); - SpineTargetGUID=0; - return true; - } - - void ResetTimer(uint32 inc = 0) - { - events.RescheduleEvent(EVENT_NEEDLE, 10000 + inc, GCD_CAST); - events.RescheduleEvent(EVENT_SPINE, 20000 + inc, GCD_CAST); - events.RescheduleEvent(EVENT_SHIELD, 60000 + inc); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHIELD: - DoCast(me, SPELL_TIDAL_SHIELD, true); - ResetTimer(45000); - break; - case EVENT_BERSERK: - DoScriptText(SAY_ENRAGE2, me); - DoCast(me, SPELL_BERSERK, true); - events.DelayEvents(15000, GCD_YELL); - break; - case EVENT_SPINE: - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) pTarget = me->getVictim(); - if (pTarget) - { - DoCast(pTarget, SPELL_IMPALING_SPINE, true); - SpineTargetGUID = pTarget->GetGUID(); - //must let target summon, otherwise you cannot click the spine - pTarget->SummonGameObject(GOBJECT_SPINE, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 30); - DoScriptText(rand()%2 ? SAY_NEEDLE1 : SAY_NEEDLE2, me); - events.DelayEvents(1500, GCD_CAST); - events.DelayEvents(15000, GCD_YELL); - } - events.ScheduleEvent(EVENT_SPINE, 21000, GCD_CAST); - return; - } - case EVENT_NEEDLE: - { - //DoCast(me, SPELL_NEEDLE_SPINE, true); - std::list pTargets; - SelectTargetList(pTargets, 3, SELECT_TARGET_RANDOM, 80, true); - for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) - DoCast(*i, 39835, true); - events.ScheduleEvent(EVENT_NEEDLE, urand(15000,25000), GCD_CAST); - events.DelayEvents(1500, GCD_CAST); - return; - } - case EVENT_YELL: - DoScriptText(RAND(SAY_SPECIAL1, SAY_SPECIAL2), me); - events.ScheduleEvent(EVENT_YELL, urand(25000,100000), GCD_YELL); - events.DelayEvents(15000, GCD_YELL); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -bool GOHello_go_najentus_spine(Player* pPlayer, GameObject* pGo) -{ - if (ScriptedInstance* pInstance = pGo->GetInstanceData()) - if (Creature* Najentus = Unit::GetCreature(*pGo, pInstance->GetData64(DATA_HIGHWARLORDNAJENTUS))) - if (CAST_AI(boss_najentusAI, Najentus->AI())->RemoveImpalingSpine()) - { - pPlayer->CastSpell(pPlayer, SPELL_CREATE_NAJENTUS_SPINE, true); - pGo->Delete(); - } - return true; -} - -CreatureAI* GetAI_boss_najentus(Creature* pCreature) -{ - return new boss_najentusAI (pCreature); -} - -void AddSC_boss_najentus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_najentus"; - newscript->GetAI = &GetAI_boss_najentus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_najentus_spine"; - newscript->pGOHello = &GOHello_go_najentus_spine; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/illidari_council.cpp b/src/server/scripts/outland/black_temple/illidari_council.cpp deleted file mode 100644 index 82cc2876b5a..00000000000 --- a/src/server/scripts/outland/black_temple/illidari_council.cpp +++ /dev/null @@ -1,874 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Illidari_Council -SD%Complete: 95 -SDComment: Circle of Healing not working properly. -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -//Speech'n'Sounds -#define SAY_GATH_SLAY -1564085 -#define SAY_GATH_SLAY_COMNT -1564089 -#define SAY_GATH_DEATH -1564093 -#define SAY_GATH_SPECIAL1 -1564077 -#define SAY_GATH_SPECIAL2 -1564081 - -#define SAY_VERA_SLAY -1564086 -#define SAY_VERA_COMNT -1564089 //signed for 22949 -#define SAY_VERA_DEATH -1564094 -#define SAY_VERA_SPECIAL1 -1564078 -#define SAY_VERA_SPECIAL2 -1564082 - -#define SAY_MALA_SLAY -1564087 -#define SAY_MALA_COMNT -1564090 -#define SAY_MALA_DEATH -1564095 -#define SAY_MALA_SPECIAL1 -1564079 -#define SAY_MALA_SPECIAL2 -1564083 - -#define SAY_ZERE_SLAY -1564088 -#define SAY_ZERE_COMNT -1564091 -#define SAY_ZERE_DEATH -1564096 -#define SAY_ZERE_SPECIAL1 -1564080 -#define SAY_ZERE_SPECIAL2 -1564084 - -#define ERROR_INST_DATA "SD2 ERROR: Instance Data for Black Temple not set properly; Illidari Council event will not function properly." - -#define AKAMAID 23089 - -struct CouncilYells -{ - int32 entry; - uint32 timer; -}; - -static CouncilYells CouncilAggro[]= -{ - {-1564069, 5000}, // Gathios - {-1564070, 5500}, // Veras - {-1564071, 5000}, // Malande - {-1564072, 0}, // Zerevor -}; - -// Need to get proper timers for this later -static CouncilYells CouncilEnrage[]= -{ - {-1564073, 2000}, // Gathios - {-1564074, 6000}, // Veras - {-1564075, 5000}, // Malande - {-1564076, 0}, // Zerevor -}; - -// High Nethermancer Zerevor's spells -#define SPELL_FLAMESTRIKE 41481 -#define SPELL_BLIZZARD 41482 -#define SPELL_ARCANE_BOLT 41483 -#define SPELL_ARCANE_EXPLOSION 41524 -#define SPELL_DAMPEN_MAGIC 41478 - -// Lady Malande's spells -#define SPELL_EMPOWERED_SMITE 41471 -#define SPELL_CIRCLE_OF_HEALING 41455 -#define SPELL_REFLECTIVE_SHIELD 41475 -#define SPELL_DIVINE_WRATH 41472 -#define SPELL_HEAL_VISUAL 24171 - -// Gathios the Shatterer's spells -#define SPELL_BLESS_PROTECTION 41450 -#define SPELL_BLESS_SPELLWARD 41451 -#define SPELL_CONSECRATION 41541 -#define SPELL_HAMMER_OF_JUSTICE 41468 -#define SPELL_SEAL_OF_COMMAND 41469 -#define SPELL_SEAL_OF_BLOOD 41459 -#define SPELL_CHROMATIC_AURA 41453 -#define SPELL_DEVOTION_AURA 41452 - -// Veras Darkshadow's spells -#define SPELL_DEADLY_POISON 41485 -#define SPELL_ENVENOM 41487 -#define SPELL_VANISH 41479 - -#define SPELL_BERSERK 45078 - -struct mob_blood_elf_council_voice_triggerAI : public ScriptedAI -{ - mob_blood_elf_council_voice_triggerAI(Creature* c) : ScriptedAI(c) - { - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; - } - - uint64 Council[4]; - - uint32 EnrageTimer; - uint32 AggroYellTimer; - - uint8 YellCounter; // Serves as the counter for both the aggro and enrage yells - - bool EventStarted; - - void Reset() - { - EnrageTimer = 900000; // 15 minutes - AggroYellTimer = 500; - - YellCounter = 0; - - EventStarted = false; - } - - // finds and stores the GUIDs for each Council member using instance data system. - void LoadCouncilGUIDs() - { - if (ScriptedInstance* pInstance = me->GetInstanceData()) - { - Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[1] = pInstance->GetData64(DATA_VERASDARKSHADOW); - Council[2] = pInstance->GetData64(DATA_LADYMALANDE); - Council[3] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); - } else error_log(ERROR_INST_DATA); - } - - void EnterCombat(Unit* /*who*/) {} - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!EventStarted) - return; - - if (YellCounter > 3) - return; - - if (AggroYellTimer) - { - if (AggroYellTimer <= diff) - { - if (Unit* pMember = Unit::GetUnit(*me, Council[YellCounter])) - { - DoScriptText(CouncilAggro[YellCounter].entry, pMember); - AggroYellTimer = CouncilAggro[YellCounter].timer; - } - ++YellCounter; - if (YellCounter > 3) - YellCounter = 0; // Reuse for Enrage Yells - } else AggroYellTimer -= diff; - } - - if (EnrageTimer) - { - if (EnrageTimer <= diff) - { - if (Unit* pMember = Unit::GetUnit(*me, Council[YellCounter])) - { - pMember->CastSpell(pMember, SPELL_BERSERK, true); - DoScriptText(CouncilEnrage[YellCounter].entry, pMember); - EnrageTimer = CouncilEnrage[YellCounter].timer; - } - ++YellCounter; - } else EnrageTimer -= diff; - } - } -}; - -struct mob_illidari_councilAI : public ScriptedAI -{ - mob_illidari_councilAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; - } - - ScriptedInstance* pInstance; - - uint64 Council[4]; - - uint32 CheckTimer; - uint32 EndEventTimer; - - uint8 DeathCount; - - bool EventBegun; - - void Reset() - { - CheckTimer = 2000; - EndEventTimer = 0; - - DeathCount = 0; - - Creature* pMember = NULL; - for (uint8 i = 0; i < 4; ++i) - { - pMember = Unit::GetCreature((*me), Council[i]); - if (!pMember) - continue; - - if (!pMember->isAlive()) - { - pMember->RemoveCorpse(); - pMember->Respawn(); - } - pMember->AI()->EnterEvadeMode(); - } - - if (pInstance) - { - pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, NOT_STARTED); - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) - VoiceTrigger->AI()->EnterEvadeMode(); - } - - EventBegun = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(11686); - } - - void EnterCombat(Unit * /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void StartEvent(Unit *pTarget) - { - if (!pInstance) - return; - - if (pTarget && pTarget->isAlive()) - { - Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); - Council[2] = pInstance->GetData64(DATA_LADYMALANDE); - Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); - - // Start the event for the Voice Trigger - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) - { - CAST_AI(mob_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->LoadCouncilGUIDs(); - CAST_AI(mob_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->EventStarted = true; - } - - for (uint8 i = 0; i < 4; ++i) - { - Unit* Member = NULL; - if (Council[i]) - { - Member = Unit::GetUnit((*me), Council[i]); - if (Member && Member->isAlive()) - CAST_CRE(Member)->AI()->AttackStart(pTarget); - } - } - - pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, IN_PROGRESS); - - EventBegun = true; - } - } - - void UpdateAI(const uint32 diff) - { - if (!EventBegun) return; - - if (EndEventTimer) - { - if (EndEventTimer <= diff) - { - if (DeathCount > 3) - { - if (pInstance) - { - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) - VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, DONE); - //me->SummonCreature(AKAMAID,746.466980f,304.394989f,311.90208f,6.272870f,TEMPSUMMON_DEAD_DESPAWN,0); - } - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - - Creature* pMember = (Unit::GetCreature(*me, Council[DeathCount])); - if (pMember && pMember->isAlive()) - pMember->DealDamage(pMember, pMember->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - ++DeathCount; - EndEventTimer = 1500; - } else EndEventTimer -= diff; - } - - if (CheckTimer) - { - if (CheckTimer <= diff) - { - uint8 EvadeCheck = 0; - for (uint8 i = 0; i < 4; ++i) - { - if (Council[i]) - { - if (Creature* Member = (Unit::GetCreature((*me), Council[i]))) - { - // This is the evade/death check. - if (Member->isAlive() && !Member->getVictim()) - ++EvadeCheck; //If all members evade, we reset so that players can properly reset the event - else if (!Member->isAlive()) // If even one member dies, kill the rest, set instance data, and kill self. - { - EndEventTimer = 1000; - CheckTimer = 0; - return; - } - } - } - } - - if (EvadeCheck > 3) - Reset(); - - CheckTimer = 2000; - } else CheckTimer -= diff; - } - - } -}; - -struct boss_illidari_councilAI : public ScriptedAI -{ - boss_illidari_councilAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; - LoadedGUIDs = false; - } - - uint64 Council[4]; - - ScriptedInstance* pInstance; - - bool LoadedGUIDs; - - void EnterCombat(Unit* who) - { - if (pInstance) - { - Creature* Controller = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ILLIDARICOUNCIL))); - if (Controller) - CAST_AI(mob_illidari_councilAI, Controller->AI())->StartEvent(who); - } - else - { - error_log(ERROR_INST_DATA); - EnterEvadeMode(); - return; - } - DoZoneInCombat(); - // Load GUIDs on first aggro because the Creature guids are only set as the creatures are created in world- - // this means that for each pCreature, it will attempt to LoadGUIDs even though some of the other creatures are - // not in world, and thus have no GUID set in the instance data system. Putting it in aggro ensures that all the creatures - // have been loaded and have their GUIDs set in the instance data system. - if (!LoadedGUIDs) - LoadGUIDs(); - } - - void EnterEvadeMode() - { - for (uint8 i = 0; i < 4; ++i) - { - if (Unit* pUnit = Unit::GetUnit(*me, Council[i])) - if (pUnit != me && pUnit->getVictim()) - { - AttackStart(pUnit->getVictim()); - return; - } - } - ScriptedAI::EnterEvadeMode(); - } - - void DamageTaken(Unit* done_by, uint32 &damage) - { - if (done_by == me) - return; - - damage /= 4; - for (uint8 i = 0; i < 4; ++i) - { - if (Creature* pUnit = Unit::GetCreature(*me, Council[i])) - if (pUnit != me && damage < pUnit->GetHealth()) - { - pUnit->SetHealth(pUnit->GetHealth() - damage); - pUnit->LowerPlayerDamageReq(damage); - } - } - } - - void LoadGUIDs() - { - if (!pInstance) - { - error_log(ERROR_INST_DATA); - return; - } - - Council[0] = pInstance->GetData64(DATA_LADYMALANDE); - Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); - Council[2] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); - - LoadedGUIDs = true; - } -}; - -struct boss_gathios_the_shattererAI : public boss_illidari_councilAI -{ - boss_gathios_the_shattererAI(Creature *c) : boss_illidari_councilAI(c) {} - - uint32 ConsecrationTimer; - uint32 HammerOfJusticeTimer; - uint32 SealTimer; - uint32 AuraTimer; - uint32 BlessingTimer; - - void Reset() - { - ConsecrationTimer = 40000; - HammerOfJusticeTimer = 10000; - SealTimer = 40000; - AuraTimer = 90000; - BlessingTimer = 60000; - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_GATH_SLAY, me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_GATH_DEATH, me); - } - - Unit* SelectCouncilMember() - { - Unit* pUnit = me; - uint32 member = 0; // He chooses Lady Malande most often - - if (rand()%10 == 0) // But there is a chance he picks someone else. - member = urand(1, 3); - - if (member != 2) // No need to create another pointer to us using Unit::GetUnit - pUnit = Unit::GetUnit((*me), Council[member]); - return pUnit; - } - - void CastAuraOnCouncil() - { - uint32 spellid = 0; - switch (urand(0,1)) - { - case 0: spellid = SPELL_DEVOTION_AURA; break; - case 1: spellid = SPELL_CHROMATIC_AURA; break; - } - for (uint8 i = 0; i < 4; ++i) - { - Unit* pUnit = Unit::GetUnit((*me), Council[i]); - if (pUnit) - pUnit->CastSpell(pUnit, spellid, true, 0, 0, me->GetGUID()); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BlessingTimer <= diff) - { - if (Unit* pUnit = SelectCouncilMember()) - { - switch (urand(0,1)) - { - case 0: DoCast(pUnit, SPELL_BLESS_SPELLWARD); break; - case 1: DoCast(pUnit, SPELL_BLESS_PROTECTION); break; - } - } - BlessingTimer = 60000; - } else BlessingTimer -= diff; - - if (ConsecrationTimer <= diff) - { - DoCast(me, SPELL_CONSECRATION); - ConsecrationTimer = 40000; - } else ConsecrationTimer -= diff; - - if (HammerOfJusticeTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - // is in ~10-40 yd range - if (me->IsInRange(pTarget, 10.0f, 40.0f, false)) - { - DoCast(pTarget, SPELL_HAMMER_OF_JUSTICE); - HammerOfJusticeTimer = 20000; - } - } - } else HammerOfJusticeTimer -= diff; - - if (SealTimer <= diff) - { - switch (urand(0,1)) - { - case 0: DoCast(me, SPELL_SEAL_OF_COMMAND); break; - case 1: DoCast(me, SPELL_SEAL_OF_BLOOD); break; - } - SealTimer = 40000; - } else SealTimer -= diff; - - if (AuraTimer <= diff) - { - CastAuraOnCouncil(); - AuraTimer = 90000; - } else AuraTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_high_nethermancer_zerevorAI : public boss_illidari_councilAI -{ - boss_high_nethermancer_zerevorAI(Creature *c) : boss_illidari_councilAI(c) {} - - uint32 BlizzardTimer; - uint32 FlamestrikeTimer; - uint32 ArcaneBoltTimer; - uint32 DampenMagicTimer; - uint32 Cooldown; - uint32 ArcaneExplosionTimer; - - void Reset() - { - BlizzardTimer = 30000 + rand()%61 * 1000; - FlamestrikeTimer = 30000 + rand()%61 * 1000; - ArcaneBoltTimer = 10000; - DampenMagicTimer = 2000; - ArcaneExplosionTimer = 14000; - Cooldown = 0; - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_ZERE_SLAY, me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_ZERE_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Cooldown) - { - if (Cooldown <= diff) Cooldown = 0; - else - { - Cooldown -= diff; - return; // Don't cast any other spells if global cooldown is still ticking - } - } - - if (DampenMagicTimer <= diff) - { - DoCast(me, SPELL_DAMPEN_MAGIC); - Cooldown = 1000; - DampenMagicTimer = 67200; // almost 1,12 minutes - ArcaneBoltTimer += 1000; // Give the Mage some time to spellsteal Dampen. - } else DampenMagicTimer -= diff; - - if (ArcaneExplosionTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); - Cooldown = 1000; - ArcaneExplosionTimer = 14000; - } else ArcaneExplosionTimer -= diff; - - if (ArcaneBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BOLT); - ArcaneBoltTimer = 3000; - Cooldown = 2000; - } else ArcaneBoltTimer -= diff; - - if (BlizzardTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_BLIZZARD); - BlizzardTimer = 45000 + rand()%46 * 1000; - FlamestrikeTimer += 10000; - Cooldown = 1000; - } - } else BlizzardTimer -= diff; - - if (FlamestrikeTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_FLAMESTRIKE); - FlamestrikeTimer = 55000 + rand()%46 * 1000; - BlizzardTimer += 10000; - Cooldown = 2000; - } - } else FlamestrikeTimer -= diff; - } -}; - -struct boss_lady_malandeAI : public boss_illidari_councilAI -{ - boss_lady_malandeAI(Creature *c) : boss_illidari_councilAI(c) {} - - uint32 EmpoweredSmiteTimer; - uint32 CircleOfHealingTimer; - uint32 DivineWrathTimer; - uint32 ReflectiveShieldTimer; - - void Reset() - { - EmpoweredSmiteTimer = 38000; - CircleOfHealingTimer = 20000; - DivineWrathTimer = 40000; - ReflectiveShieldTimer = 0; - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_MALA_SLAY, me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_MALA_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (EmpoweredSmiteTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_EMPOWERED_SMITE); - EmpoweredSmiteTimer = 38000; - } - } else EmpoweredSmiteTimer -= diff; - - if (CircleOfHealingTimer <= diff) - { - DoCast(me, SPELL_CIRCLE_OF_HEALING); - CircleOfHealingTimer = 60000; - } else CircleOfHealingTimer -= diff; - - if (DivineWrathTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_DIVINE_WRATH); - DivineWrathTimer = 40000 + rand()%41 * 1000; - } - } else DivineWrathTimer -= diff; - - if (ReflectiveShieldTimer <= diff) - { - DoCast(me, SPELL_REFLECTIVE_SHIELD); - ReflectiveShieldTimer = 65000; - } else ReflectiveShieldTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_veras_darkshadowAI : public boss_illidari_councilAI -{ - boss_veras_darkshadowAI(Creature *c) : boss_illidari_councilAI(c) {} - - uint64 EnvenomTargetGUID; - - uint32 DeadlyPoisonTimer; - uint32 VanishTimer; - uint32 AppearEnvenomTimer; - - bool HasVanished; - - void Reset() - { - EnvenomTargetGUID = 0; - - DeadlyPoisonTimer = 20000; - VanishTimer = 60000 + rand()%61 * 1000; - AppearEnvenomTimer = 150000; - - HasVanished = false; - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_VERA_SLAY, me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_VERA_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!HasVanished) - { - if (DeadlyPoisonTimer <= diff) - { - DoCast(me->getVictim(), SPELL_DEADLY_POISON); - DeadlyPoisonTimer = 15000 + rand()%31 * 1000; - } else DeadlyPoisonTimer -= diff; - - if (AppearEnvenomTimer <= diff) // Cast Envenom. This is cast 4 seconds after Vanish is over - { - DoCast(me->getVictim(), SPELL_ENVENOM); - AppearEnvenomTimer = 90000; - } else AppearEnvenomTimer -= diff; - - if (VanishTimer <= diff) // Disappear and stop attacking, but follow a random unit - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - VanishTimer = 30000; - AppearEnvenomTimer= 28000; - HasVanished = true; - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoResetThreat(); - // Chase a unit. Check before DoMeleeAttackIfReady prevents from attacking - me->AddThreat(pTarget, 500000.0f); - me->GetMotionMaster()->MoveChase(pTarget); - } - } else VanishTimer -= diff; - - DoMeleeAttackIfReady(); - } - else - { - if (VanishTimer <= diff) // Become attackable and poison current target - { - Unit *pTarget = me->getVictim(); - DoCast(pTarget, SPELL_DEADLY_POISON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoResetThreat(); - me->AddThreat(pTarget, 3000.0f); // Make Veras attack his target for a while, he will cast Envenom 4 seconds after. - DeadlyPoisonTimer += 6000; - VanishTimer = 90000; - AppearEnvenomTimer = 4000; - HasVanished = false; - } else VanishTimer -= diff; - - if (AppearEnvenomTimer <= diff) // Appear 2 seconds before becoming attackable (Shifting out of vanish) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - me->SetVisibility(VISIBILITY_ON); - AppearEnvenomTimer = 6000; - } else AppearEnvenomTimer -= diff; - } - } -}; - -CreatureAI* GetAI_mob_blood_elf_council_voice_trigger(Creature* c) -{ - return new mob_blood_elf_council_voice_triggerAI(c); -} - -CreatureAI* GetAI_mob_illidari_council(Creature* pCreature) -{ - return new mob_illidari_councilAI (pCreature); -} - -CreatureAI* GetAI_boss_gathios_the_shatterer(Creature* pCreature) -{ - return new boss_gathios_the_shattererAI (pCreature); -} - -CreatureAI* GetAI_boss_lady_malande(Creature* pCreature) -{ - return new boss_lady_malandeAI (pCreature); -} - -CreatureAI* GetAI_boss_veras_darkshadow(Creature* pCreature) -{ - return new boss_veras_darkshadowAI (pCreature); -} - -CreatureAI* GetAI_boss_high_nethermancer_zerevor(Creature* pCreature) -{ - return new boss_high_nethermancer_zerevorAI (pCreature); -} - -void AddSC_boss_illidari_council() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_illidari_council"; - newscript->GetAI = &GetAI_mob_illidari_council; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_blood_elf_council_voice_trigger"; - newscript->GetAI = &GetAI_mob_blood_elf_council_voice_trigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_gathios_the_shatterer"; - newscript->GetAI = &GetAI_boss_gathios_the_shatterer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lady_malande"; - newscript->GetAI = &GetAI_boss_lady_malande; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_veras_darkshadow"; - newscript->GetAI = &GetAI_boss_veras_darkshadow; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_high_nethermancer_zerevor"; - newscript->GetAI = &GetAI_boss_high_nethermancer_zerevor; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/black_temple/instance_black_temple.cpp b/src/server/scripts/outland/black_temple/instance_black_temple.cpp deleted file mode 100644 index 88e25026a13..00000000000 --- a/src/server/scripts/outland/black_temple/instance_black_temple.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Black_Temple -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Black Temple Scripts -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -#define MAX_ENCOUNTER 9 - -/* Black Temple encounters: -0 - High Warlord Naj'entus event -1 - Supremus Event -2 - Shade of Akama Event -3 - Teron Gorefiend Event -4 - Gurtogg Bloodboil Event -5 - Reliquary Of Souls Event -6 - Mother Shahraz Event -7 - Illidari Council Event -8 - Illidan Stormrage Event -*/ - -struct instance_black_temple : public ScriptedInstance -{ - instance_black_temple(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 Najentus; - uint64 Akama; // This is the Akama that starts the Illidan encounter. - uint64 Akama_Shade; // This is the Akama that starts the Shade of Akama encounter. - uint64 ShadeOfAkama; - uint64 Supremus; - uint64 LadyMalande; - uint64 GathiosTheShatterer; - uint64 HighNethermancerZerevor; - uint64 VerasDarkshadow; - uint64 IllidariCouncil; - uint64 BloodElfCouncilVoice; - uint64 IllidanStormrage; - - uint64 NajentusGate; - uint64 MainTempleDoors; - uint64 ShadeOfAkamaDoor; - uint64 CommonDoor;//Teron - uint64 TeronDoor; - uint64 GuurtogDoor; - uint64 MotherDoor; - uint64 TempleDoor;//Befor mother - uint64 CouncilDoor; - uint64 SimpleDoor;//council - uint64 IllidanGate; - uint64 IllidanDoor[2]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Najentus = 0; - Akama = 0; - Akama_Shade = 0; - ShadeOfAkama = 0; - Supremus = 0; - LadyMalande = 0; - GathiosTheShatterer = 0; - HighNethermancerZerevor = 0; - VerasDarkshadow = 0; - IllidariCouncil = 0; - BloodElfCouncilVoice = 0; - IllidanStormrage = 0; - - NajentusGate = 0; - MainTempleDoors = 0; - ShadeOfAkamaDoor= 0; - CommonDoor = 0;//teron - TeronDoor = 0; - GuurtogDoor = 0; - MotherDoor = 0; - TempleDoor = 0; - SimpleDoor = 0;//Bycouncil - CouncilDoor = 0; - IllidanGate = 0; - IllidanDoor[0] = 0; - IllidanDoor[1] = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - - debug_log("TSCR: Instance Black Temple: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 22887: Najentus = pCreature->GetGUID(); break; - case 23089: Akama = pCreature->GetGUID(); break; - case 22990: Akama_Shade = pCreature->GetGUID(); break; - case 22841: ShadeOfAkama = pCreature->GetGUID(); break; - case 22898: Supremus = pCreature->GetGUID(); break; - case 22917: IllidanStormrage = pCreature->GetGUID(); break; - case 22949: GathiosTheShatterer = pCreature->GetGUID(); break; - case 22950: HighNethermancerZerevor = pCreature->GetGUID(); break; - case 22951: LadyMalande = pCreature->GetGUID(); break; - case 22952: VerasDarkshadow = pCreature->GetGUID(); break; - case 23426: IllidariCouncil = pCreature->GetGUID(); break; - case 23499: BloodElfCouncilVoice = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 185483: NajentusGate = pGo->GetGUID();// Gate past Naj'entus (at the entrance to Supermoose's courtyards) - if (m_auiEncounter[0] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185882: MainTempleDoors = pGo->GetGUID();// Main Temple Doors - right past Supermoose (Supremus) - if (m_auiEncounter[1] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185478: ShadeOfAkamaDoor = pGo->GetGUID();break; - case 185480: CommonDoor = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE)HandleGameObject(NULL,true,pGo);break; - case 186153: TeronDoor = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185892: GuurtogDoor = pGo->GetGUID(); - if (m_auiEncounter[4] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185479: TempleDoor = pGo->GetGUID(); - if (m_auiEncounter[5] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185482: MotherDoor = pGo->GetGUID(); - if (m_auiEncounter[6] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185481: CouncilDoor = pGo->GetGUID(); - if (m_auiEncounter[7] == DONE)HandleGameObject(NULL,true,pGo);break; - case 186152: SimpleDoor = pGo->GetGUID(); - if (m_auiEncounter[7] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185905: IllidanGate = pGo->GetGUID(); break; // Gate leading to Temple Summit - case 186261: IllidanDoor[0] = pGo->GetGUID(); break; // Right door at Temple Summit - case 186262: IllidanDoor[1] = pGo->GetGUID(); break; // Left door at Temple Summit - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_HIGHWARLORDNAJENTUS: return Najentus; - case DATA_AKAMA: return Akama; - case DATA_AKAMA_SHADE: return Akama_Shade; - case DATA_SHADEOFAKAMA: return ShadeOfAkama; - case DATA_SUPREMUS: return Supremus; - case DATA_ILLIDANSTORMRAGE: return IllidanStormrage; - case DATA_GATHIOSTHESHATTERER: return GathiosTheShatterer; - case DATA_HIGHNETHERMANCERZEREVOR: return HighNethermancerZerevor; - case DATA_LADYMALANDE: return LadyMalande; - case DATA_VERASDARKSHADOW: return VerasDarkshadow; - case DATA_ILLIDARICOUNCIL: return IllidariCouncil; - case DATA_GAMEOBJECT_NAJENTUS_GATE: return NajentusGate; - case DATA_GAMEOBJECT_ILLIDAN_GATE: return IllidanGate; - case DATA_GAMEOBJECT_ILLIDAN_DOOR_R: return IllidanDoor[0]; - case DATA_GAMEOBJECT_ILLIDAN_DOOR_L: return IllidanDoor[1]; - case DATA_GAMEOBJECT_SUPREMUS_DOORS: return MainTempleDoors; - case DATA_BLOOD_ELF_COUNCIL_VOICE: return BloodElfCouncilVoice; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_HIGHWARLORDNAJENTUSEVENT: - if (data == DONE) - { - HandleGameObject(NajentusGate, true); - } - m_auiEncounter[0] = data;break; - case DATA_SUPREMUSEVENT: - if (data == DONE) - { - HandleGameObject(NajentusGate, true); - } - m_auiEncounter[1] = data; break; - case DATA_SHADEOFAKAMAEVENT: - if (data == IN_PROGRESS) - { - HandleGameObject(ShadeOfAkamaDoor, false); - } else HandleGameObject(ShadeOfAkamaDoor, true); - m_auiEncounter[2] = data; break; - case DATA_TERONGOREFIENDEVENT: - if (data == IN_PROGRESS) - { - HandleGameObject(TeronDoor, false); - HandleGameObject(CommonDoor, false); - }else - { - HandleGameObject(TeronDoor, true); - HandleGameObject(CommonDoor, true); - } - m_auiEncounter[3] = data; break; - case DATA_GURTOGGBLOODBOILEVENT: - if (data == DONE) - { - HandleGameObject(GuurtogDoor, true); - } - m_auiEncounter[4] = data; break; - case DATA_RELIQUARYOFSOULSEVENT: - if (data == DONE) - { - HandleGameObject(TempleDoor, true); - } - m_auiEncounter[5] = data; break; - case DATA_MOTHERSHAHRAZEVENT: - if (data == DONE) - { - HandleGameObject(MotherDoor, true); - } - m_auiEncounter[6] = data; break; - case DATA_ILLIDARICOUNCILEVENT: - if (data == IN_PROGRESS) - { - HandleGameObject(CouncilDoor, false); - HandleGameObject(SimpleDoor, false); - }else - { - HandleGameObject(CouncilDoor, true); - HandleGameObject(SimpleDoor, true); - } - m_auiEncounter[7] = data; break; - case DATA_ILLIDANSTORMRAGEEVENT: m_auiEncounter[8] = data; break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] - << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " << m_auiEncounter[7] - << " " << m_auiEncounter[8]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_HIGHWARLORDNAJENTUSEVENT: return m_auiEncounter[0]; - case DATA_SUPREMUSEVENT: return m_auiEncounter[1]; - case DATA_SHADEOFAKAMAEVENT: return m_auiEncounter[2]; - case DATA_TERONGOREFIENDEVENT: return m_auiEncounter[3]; - case DATA_GURTOGGBLOODBOILEVENT: return m_auiEncounter[4]; - case DATA_RELIQUARYOFSOULSEVENT: return m_auiEncounter[5]; - case DATA_MOTHERSHAHRAZEVENT: return m_auiEncounter[6]; - case DATA_ILLIDARICOUNCILEVENT: return m_auiEncounter[7]; - case DATA_ILLIDANSTORMRAGEEVENT: return m_auiEncounter[8]; - } - - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] - >> m_auiEncounter[3] >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] - >> m_auiEncounter[7] >> m_auiEncounter[8]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_black_temple(Map* pMap) -{ - return new instance_black_temple(pMap); -} - -void AddSC_instance_black_temple() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_black_temple"; - newscript->GetInstanceData = &GetInstanceData_instance_black_temple; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/blades_edge_mountains.cpp b/src/server/scripts/outland/blades_edge_mountains.cpp deleted file mode 100644 index f5b4539edaf..00000000000 --- a/src/server/scripts/outland/blades_edge_mountains.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Blades_Edge_Mountains -SD%Complete: 90 -SDComment: Quest support: 10503, 10504, 10556, 10609, 10682, 10821, 10980. Ogri'la->Skettis Flight. (npc_daranelle needs bit more work before consider complete) -SDCategory: Blade's Edge Mountains -EndScriptData */ - -/* ContentData -mobs_bladespire_ogre -mobs_nether_drake -npc_daranelle -npc_overseer_nuaar -npc_saikkal_the_elder -go_legion_obelisk -EndContentData */ - -#include "ScriptedPch.h" - -//Support for quest: You're Fired! (10821) -bool obelisk_one, obelisk_two, obelisk_three, obelisk_four, obelisk_five; - -#define LEGION_OBELISK_ONE 185193 -#define LEGION_OBELISK_TWO 185195 -#define LEGION_OBELISK_THREE 185196 -#define LEGION_OBELISK_FOUR 185197 -#define LEGION_OBELISK_FIVE 185198 - -/*###### -## mobs_bladespire_ogre -######*/ - -//TODO: add support for quest 10512 + Creature abilities -struct mobs_bladespire_ogreAI : public ScriptedAI -{ - mobs_bladespire_ogreAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_mobs_bladespire_ogre(Creature* pCreature) -{ - return new mobs_bladespire_ogreAI (pCreature); -} - -/*###### -## mobs_nether_drake -######*/ - -enum eNetherdrake -{ - SAY_NIHIL_1 = -1000169, //signed for 5955 - SAY_NIHIL_2 = -1000170, //signed for 5955 - SAY_NIHIL_3 = -1000171, //signed for 5955 - SAY_NIHIL_4 = -1000172, //signed for 20021, used by 20021,21817,21820,21821,21823 - SAY_NIHIL_INTERRUPT = -1000173, //signed for 20021, used by 20021,21817,21820,21821,21823 - - ENTRY_WHELP = 20021, - ENTRY_PROTO = 21821, - ENTRY_ADOLE = 21817, - ENTRY_MATUR = 21820, - ENTRY_NIHIL = 21823, - - SPELL_T_PHASE_MODULATOR = 37573, - - SPELL_ARCANE_BLAST = 38881, - SPELL_MANA_BURN = 38884, - SPELL_INTANGIBLE_PRESENCE = 36513 -}; - -struct mobs_nether_drakeAI : public ScriptedAI -{ - mobs_nether_drakeAI(Creature *c) : ScriptedAI(c) {} - - bool IsNihil; - uint32 NihilSpeech_Timer; - uint32 NihilSpeech_Phase; - - uint32 ArcaneBlast_Timer; - uint32 ManaBurn_Timer; - uint32 IntangiblePresence_Timer; - - void Reset() - { - IsNihil = false; - NihilSpeech_Timer = 3000; - NihilSpeech_Phase = 0; - - ArcaneBlast_Timer = 7500; - ManaBurn_Timer = 10000; - IntangiblePresence_Timer = 15000; - } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - //in case Creature was not summoned (not expected) - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 0) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - me->SetHealth(0); - } - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_T_PHASE_MODULATOR && caster->GetTypeId() == TYPEID_PLAYER) - { - const uint32 entry_list[4] = {ENTRY_PROTO, ENTRY_ADOLE, ENTRY_MATUR, ENTRY_NIHIL}; - int cid = rand()%(4-1); - - if (entry_list[cid] == me->GetEntry()) - ++cid; - - //we are nihil, so say before transform - if (me->GetEntry() == ENTRY_NIHIL) - { - DoScriptText(SAY_NIHIL_INTERRUPT, me); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - IsNihil = false; - } - - if (me->UpdateEntry(entry_list[cid])) - { - if (entry_list[cid] == ENTRY_NIHIL) - { - EnterEvadeMode(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - IsNihil = true; - }else - AttackStart(caster); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (IsNihil) - { - if (NihilSpeech_Timer <= diff) - { - switch(NihilSpeech_Phase) - { - case 0: - DoScriptText(SAY_NIHIL_1, me); - ++NihilSpeech_Phase; - break; - case 1: - DoScriptText(SAY_NIHIL_2, me); - ++NihilSpeech_Phase; - break; - case 2: - DoScriptText(SAY_NIHIL_3, me); - ++NihilSpeech_Phase; - break; - case 3: - DoScriptText(SAY_NIHIL_4, me); - ++NihilSpeech_Phase; - break; - case 4: - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //take off to location above - me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+50.0f, me->GetPositionY(), me->GetPositionZ()+50.0f); - ++NihilSpeech_Phase; - break; - } - NihilSpeech_Timer = 5000; - } else NihilSpeech_Timer -=diff; - - //anything below here is not interesting for Nihil, so skip it - return; - } - - if (!UpdateVictim()) - return; - - if (IntangiblePresence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); - IntangiblePresence_Timer = 15000+rand()%15000; - } else IntangiblePresence_Timer -= diff; - - if (ManaBurn_Timer <= diff) - { - Unit *pTarget = me->getVictim(); - if (pTarget && pTarget->getPowerType() == POWER_MANA) - DoCast(pTarget, SPELL_MANA_BURN); - ManaBurn_Timer = 8000+rand()%8000; - } else ManaBurn_Timer -= diff; - - if (ArcaneBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BLAST); - ArcaneBlast_Timer = 2500+rand()%5000; - } else ArcaneBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mobs_nether_drake(Creature* pCreature) -{ - return new mobs_nether_drakeAI (pCreature); -} - -/*###### -## npc_daranelle -######*/ - -enum eDaranelle -{ - SAY_SPELL_INFLUENCE = -1000174, - SPELL_LASHHAN_CHANNEL = 36904 -}; - -struct npc_daranelleAI : public ScriptedAI -{ - npc_daranelleAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (who->GetTypeId() == TYPEID_PLAYER) - { - if (who->HasAura(SPELL_LASHHAN_CHANNEL) && me->IsWithinDistInMap(who, 10.0f)) - { - DoScriptText(SAY_SPELL_INFLUENCE, me, who); - //TODO: Move the below to updateAI and run if this statement == true - DoCast(who, 37028, true); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } -}; - -CreatureAI* GetAI_npc_daranelle(Creature* pCreature) -{ - return new npc_daranelleAI (pCreature); -} - -/*###### -## npc_overseer_nuaar -######*/ - -#define GOSSIP_HELLO_ON "Overseer, I am here to negotiate on behalf of the Cenarion Expedition." - -bool GossipHello_npc_overseer_nuaar(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(10682) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_ON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(10532, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_overseer_nuaar(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->SEND_GOSSIP_MENU(10533, pCreature->GetGUID()); - pPlayer->AreaExploredOrEventHappens(10682); - } - return true; -} - -/*###### -## npc_saikkal_the_elder -######*/ - -#define GOSSIP_HELLO_STE "Yes... yes, it's me." -#define GOSSIP_SELECT_STE "Yes elder. Tell me more of the book." - -bool GossipHello_npc_saikkal_the_elder(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(10980) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_STE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(10794, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_saikkal_the_elder(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_STE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(10795, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - pPlayer->SEND_GOSSIP_MENU(10796, pCreature->GetGUID()); - break; - } - return true; -} - -/*###### -## go_legion_obelisk -######*/ - -bool GOHello_go_legion_obelisk(Player* pPlayer, GameObject* pGo) -{ - if (pPlayer->GetQuestStatus(10821) == QUEST_STATUS_INCOMPLETE) - { - switch(pGo->GetEntry()) - { - case LEGION_OBELISK_ONE: - obelisk_one = true; - break; - case LEGION_OBELISK_TWO: - obelisk_two = true; - break; - case LEGION_OBELISK_THREE: - obelisk_three = true; - break; - case LEGION_OBELISK_FOUR: - obelisk_four = true; - break; - case LEGION_OBELISK_FIVE: - obelisk_five = true; - break; - } - - if (obelisk_one == true && obelisk_two == true && obelisk_three == true && obelisk_four == true && obelisk_five == true) - { - pGo->SummonCreature(19963,2943.40f,4778.20f,284.49f,0.94f,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); - //reset global var - obelisk_one = false; - obelisk_two = false; - obelisk_three = false; - obelisk_four = false; - obelisk_five = false; - } - } - - return true; -} - - -/*###### -## npc_bloodmaul_brutebane -######*/ - - -enum eBloodmaul -{ - NPC_OGRE_BRUTE = 19995, - NPC_QUEST_CREDIT = 21241, - GO_KEG = 184315 -}; - -struct npc_bloodmaul_brutebaneAI : public ScriptedAI -{ - npc_bloodmaul_brutebaneAI(Creature *c) : ScriptedAI(c) - { - if(Creature* Ogre = me->FindNearestCreature(NPC_OGRE_BRUTE, 50, true)) - { - Ogre->SetReactState(REACT_DEFENSIVE); - Ogre->GetMotionMaster()->MovePoint(1, me->GetPositionX()-1, me->GetPositionY()+1, me->GetPositionZ()); - } - } - - uint64 OgreGUID; - - void Reset() - { - OgreGUID = 0; - } - - void UpdateAI(const uint32 /*uiDiff*/) {} -}; - -CreatureAI* GetAI_npc_bloodmaul_brutebane(Creature* pCreature) -{ - return new npc_bloodmaul_brutebaneAI (pCreature); -} - -/*###### -## npc_ogre_brute -######*/ - -struct npc_ogre_bruteAI : public ScriptedAI -{ - npc_ogre_bruteAI(Creature *c) : ScriptedAI(c) {} - - uint64 PlayerGUID; - - void Reset() - { - PlayerGUID = 0; - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || (!who->isAlive())) return; - - if (me->IsWithinDistInMap(who, 50.0f) && (who->GetTypeId() == TYPEID_PLAYER) && who->ToPlayer()->GetQuestStatus(10512) == QUEST_STATUS_INCOMPLETE) - { - PlayerGUID = who->GetGUID(); - } - } - - void MovementInform(uint32 /*type*/, uint32 id) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (id == 1) - { - GameObject* Keg = me->FindNearestGameObject(GO_KEG, 20); - if (Keg) - Keg->Delete(); - me->HandleEmoteCommand(7); - me->SetReactState(REACT_AGGRESSIVE); - me->GetMotionMaster()->MoveTargetedHome(); - Creature* Credit = me->FindNearestCreature(NPC_QUEST_CREDIT, 50, true); - if (pPlayer && Credit) - pPlayer->KilledMonster(Credit->GetCreatureInfo(), Credit->GetGUID()); - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_ogre_brute(Creature* pCreature) -{ - return new npc_ogre_bruteAI(pCreature); -} - -/*###### -## AddSC -######*/ - -void AddSC_blades_edge_mountains() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mobs_bladespire_ogre"; - newscript->GetAI = &GetAI_mobs_bladespire_ogre; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mobs_nether_drake"; - newscript->GetAI = &GetAI_mobs_nether_drake; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_daranelle"; - newscript->GetAI = &GetAI_npc_daranelle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_overseer_nuaar"; - newscript->pGossipHello = &GossipHello_npc_overseer_nuaar; - newscript->pGossipSelect = &GossipSelect_npc_overseer_nuaar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_saikkal_the_elder"; - newscript->pGossipHello = &GossipHello_npc_saikkal_the_elder; - newscript->pGossipSelect = &GossipSelect_npc_saikkal_the_elder; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_legion_obelisk"; - newscript->pGOHello = &GOHello_go_legion_obelisk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_bloodmaul_brutebane"; - newscript->GetAI = &GetAI_npc_bloodmaul_brutebane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ogre_brute"; - newscript->GetAI = &GetAI_npc_ogre_brute; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/boss_doomlord_kazzak.cpp b/src/server/scripts/outland/boss_doomlord_kazzak.cpp deleted file mode 100644 index 9e9538f2d23..00000000000 --- a/src/server/scripts/outland/boss_doomlord_kazzak.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Doomlord_Kazzak -SD%Complete: 70 -SDComment: Using incorrect spell for Mark of Kazzak -SDCategory: Hellfire Peninsula -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_INTRO -1000147 -#define SAY_AGGRO1 -1000148 -#define SAY_AGGRO2 -1000149 -#define SAY_SURPREME1 -1000154 -#define SAY_SURPREME2 -1000149 -#define SAY_KILL1 -1000150 -#define SAY_KILL2 -1000151 -#define SAY_KILL3 -1000152 -#define SAY_DEATH -1000155 -#define EMOTE_FRENZY -1000151 -#define SAY_RAND1 -1000158 -#define SAY_RAND2 -1000157 - -#define SPELL_SHADOWVOLLEY 32963 -#define SPELL_CLEAVE 31779 -#define SPELL_THUNDERCLAP 36706 -#define SPELL_VOIDBOLT 39329 -#define SPELL_MARKOFKAZZAK 32960 -#define SPELL_ENRAGE 32964 -#define SPELL_CAPTURESOUL 32966 -#define SPELL_TWISTEDREFLECTION 21063 - -struct boss_doomlordkazzakAI : public ScriptedAI -{ - boss_doomlordkazzakAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowVolley_Timer; - uint32 Cleave_Timer; - uint32 ThunderClap_Timer; - uint32 VoidBolt_Timer; - uint32 MarkOfKazzak_Timer; - uint32 Enrage_Timer; - uint32 Twisted_Reflection_Timer; - - void Reset() - { - ShadowVolley_Timer = 6000 + rand()%4000; - Cleave_Timer = 7000; - ThunderClap_Timer = 14000 + rand()%4000; - VoidBolt_Timer = 30000; - MarkOfKazzak_Timer = 25000; - Enrage_Timer = 60000; - Twisted_Reflection_Timer = 33000; // Timer may be incorrect - } - - void JustRespawned() - { - DoScriptText(SAY_INTRO, me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2), me); - } - - void KilledUnit(Unit* victim) - { - // When Kazzak kills a player (not pets/totems), he regens some health - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoCast(me, SPELL_CAPTURESOUL); - - DoScriptText(RAND(SAY_KILL1,SAY_KILL2,SAY_KILL3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ShadowVolley_Timer - if (ShadowVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWVOLLEY); - ShadowVolley_Timer = 4000 + rand()%2000; - } else ShadowVolley_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 8000 + rand()%4000; - } else Cleave_Timer -= diff; - - //ThunderClap_Timer - if (ThunderClap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - ThunderClap_Timer = 10000 + rand()%4000; - } else ThunderClap_Timer -= diff; - - //VoidBolt_Timer - if (VoidBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VOIDBOLT); - VoidBolt_Timer = 15000 + rand()%3000; - } else VoidBolt_Timer -= diff; - - //MarkOfKazzak_Timer - if (MarkOfKazzak_Timer <= diff) - { - Unit* victim = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (victim->GetPower(POWER_MANA)) - { - DoCast(victim, SPELL_MARKOFKAZZAK); - MarkOfKazzak_Timer = 20000; - } - } else MarkOfKazzak_Timer -= diff; - - //Enrage_Timer - if (Enrage_Timer <= diff) - { - DoScriptText(EMOTE_FRENZY, me); - DoCast(me, SPELL_ENRAGE); - Enrage_Timer = 30000; - } else Enrage_Timer -= diff; - - if (Twisted_Reflection_Timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_TWISTEDREFLECTION); - Twisted_Reflection_Timer = 15000; - } else Twisted_Reflection_Timer -= diff; - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_boss_doomlordkazzak(Creature* pCreature) -{ - return new boss_doomlordkazzakAI (pCreature); -} - -void AddSC_boss_doomlordkazzak() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_doomlord_kazzak"; - newscript->GetAI = &GetAI_boss_doomlordkazzak; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/boss_doomwalker.cpp b/src/server/scripts/outland/boss_doomwalker.cpp deleted file mode 100644 index 60bcd7ee373..00000000000 --- a/src/server/scripts/outland/boss_doomwalker.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Doomwalker -SD%Complete: 100 -SDComment: -SDCategory: Shadowmoon Valley -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1000159 -#define SAY_EARTHQUAKE_1 -1000160 -#define SAY_EARTHQUAKE_2 -1000161 -#define SAY_OVERRUN_1 -1000162 -#define SAY_OVERRUN_2 -1000163 -#define SAY_SLAY_1 -1000164 -#define SAY_SLAY_2 -1000165 -#define SAY_SLAY_3 -1000166 -#define SAY_DEATH -1000167 - -#define SPELL_EARTHQUAKE 32686 -#define SPELL_SUNDER_ARMOR 33661 -#define SPELL_CHAIN_LIGHTNING 33665 -#define SPELL_OVERRUN 32636 -#define SPELL_ENRAGE 33653 -#define SPELL_MARK_DEATH 37128 -#define SPELL_AURA_DEATH 37131 - -struct boss_doomwalkerAI : public ScriptedAI -{ - boss_doomwalkerAI(Creature *c) : ScriptedAI(c) {} - - uint32 Chain_Timer; - uint32 Enrage_Timer; - uint32 Overrun_Timer; - uint32 Quake_Timer; - uint32 Armor_Timer; - - bool InEnrage; - - void Reset() - { - Enrage_Timer = 0; - Armor_Timer = 5000 + rand()%8000; - Chain_Timer = 10000 + rand()%20000; - Quake_Timer = 25000 + rand()%10000; - Overrun_Timer = 30000 + rand()%15000; - - InEnrage = false; - } - - void KilledUnit(Unit* Victim) - { - Victim->CastSpell(Victim,SPELL_MARK_DEATH,0); - - if (rand()%5) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void MoveInLineOfSight(Unit *who) - { - if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsHostileTo(who)) - { - if (who->HasAura(SPELL_MARK_DEATH,0)) - { - who->CastSpell(who,SPELL_AURA_DEATH,1); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Spell Enrage, when hp <= 20% gain enrage - if (((me->GetHealth()*100)/ me->GetMaxHealth()) <= 20) - { - if (Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enrage_Timer = 6000; - InEnrage = true; - } else Enrage_Timer -= diff; - } - - //Spell Overrun - if (Overrun_Timer <= diff) - { - DoScriptText(RAND(SAY_OVERRUN_1,SAY_OVERRUN_2), me); - - DoCast(me->getVictim(), SPELL_OVERRUN); - Overrun_Timer = 25000 + rand()%15000; - } else Overrun_Timer -= diff; - - //Spell Earthquake - if (Quake_Timer <= diff) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_EARTHQUAKE_1,SAY_EARTHQUAKE_2), me); - - //remove enrage before casting earthquake because enrage + earthquake = 16000dmg over 8sec and all dead - if (InEnrage) - me->RemoveAura(SPELL_ENRAGE); - - DoCast(me, SPELL_EARTHQUAKE); - Quake_Timer = 30000 + rand()%25000; - } else Quake_Timer -= diff; - - //Spell Chain Lightning - if (Chain_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - - Chain_Timer = 7000 + rand()%20000; - } else Chain_Timer -= diff; - - //Spell Sunder Armor - if (Armor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDER_ARMOR); - Armor_Timer = 10000 + rand()%15000; - } else Armor_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_doomwalker(Creature* pCreature) -{ - return new boss_doomwalkerAI (pCreature); -} - -void AddSC_boss_doomwalker() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_doomwalker"; - newscript->GetAI = &GetAI_boss_doomwalker; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp b/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp deleted file mode 100644 index 69a969adda0..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp +++ /dev/null @@ -1,746 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Fathomlord_Karathress -SD%Complete: 70 -SDComment: Cyclone workaround -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedEscortAI.h" - -#define SAY_AGGRO -1548021 -#define SAY_GAIN_BLESSING -1548022 -#define SAY_GAIN_ABILITY1 -1548023 -#define SAY_GAIN_ABILITY2 -1548024 -#define SAY_GAIN_ABILITY3 -1548025 -#define SAY_SLAY1 -1548026 -#define SAY_SLAY2 -1548027 -#define SAY_SLAY3 -1548028 -#define SAY_DEATH -1548029 - -//Karathress spells -#define SPELL_CATACLYSMIC_BOLT 38441 -#define SPELL_POWER_OF_SHARKKIS 38455 -#define SPELL_POWER_OF_TIDALVESS 38452 -#define SPELL_POWER_OF_CARIBDIS 38451 -#define SPELL_ENRAGE 24318 -#define SPELL_SEAR_NOVA 38445 -#define SPELL_BLESSING_OF_THE_TIDES 38449 - -//Sharkkis spells -#define SPELL_LEECHING_THROW 29436 -#define SPELL_THE_BEAST_WITHIN 38373 -#define SPELL_MULTISHOT 38366 -#define SPELL_SUMMON_FATHOM_LURKER 38433 -#define SPELL_SUMMON_FATHOM_SPOREBAT 38431 -#define SPELL_PET_ENRAGE 19574 - -//Tidalvess spells -#define SPELL_FROST_SHOCK 38234 -#define SPELL_SPITFIRE_TOTEM 38236 -#define SPELL_POISON_CLEANSING_TOTEM 38306 -// Spell obsolete -// #define SPELL_POISON_CLEANSING_EFFECT 8167 -#define SPELL_EARTHBIND_TOTEM 38304 -#define SPELL_EARTHBIND_TOTEM_EFFECT 6474 -#define SPELL_WINDFURY_WEAPON 38184 - -//Caribdis Spells -#define SPELL_WATER_BOLT_VOLLEY 38335 -#define SPELL_TIDAL_SURGE 38358 -#define SPELL_TIDAL_SURGE_FREEZE 38357 -#define SPELL_HEAL 38330 -#define SPELL_SUMMON_CYCLONE 38337 -#define SPELL_CYCLONE_CYCLONE 29538 - -//Yells and Quotes -#define SAY_GAIN_BLESSING_OF_TIDES "Your overconfidence will be your undoing! Guards, lend me your strength!" -#define SOUND_GAIN_BLESSING_OF_TIDES 11278 -#define SAY_MISC "Alana be'lendor!" //don't know what use this -#define SOUND_MISC 11283 - -//Summoned Unit GUIDs -#define CREATURE_CYCLONE 22104 -#define CREATURE_FATHOM_SPOREBAT 22120 -#define CREATURE_FATHOM_LURKER 22119 -#define CREATURE_SPITFIRE_TOTEM 22091 -#define CREATURE_EARTHBIND_TOTEM 22486 -#define CREATURE_POISON_CLEANSING_TOTEM 22487 - -//entry and position for Seer Olum -#define SEER_OLUM 22820 -#define OLUM_X 446.78f -#define OLUM_Y -542.76f -#define OLUM_Z -7.54773f -#define OLUM_O 0.401581f - -//Fathom-Lord Karathress AI -struct boss_fathomlord_karathressAI : public ScriptedAI -{ - boss_fathomlord_karathressAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Advisors[0] = 0; - Advisors[1] = 0; - Advisors[2] = 0; - } - - ScriptedInstance* pInstance; - - uint32 CataclysmicBolt_Timer; - uint32 Enrage_Timer; - uint32 SearNova_Timer; - - bool BlessingOfTides; - - uint64 Advisors[3]; - - void Reset() - { - CataclysmicBolt_Timer = 10000; - Enrage_Timer = 600000; //10 minutes - SearNova_Timer = 20000+rand()%40000; // 20 - 60 seconds - - BlessingOfTides = false; - - if (pInstance) - { - uint64 RAdvisors[3]; - RAdvisors[0] = pInstance->GetData64(DATA_SHARKKIS); - RAdvisors[1] = pInstance->GetData64(DATA_TIDALVESS); - RAdvisors[2] = pInstance->GetData64(DATA_CARIBDIS); - //Respawn of the 3 Advisors - Creature* pAdvisor = NULL; - for (int i=0; i<3; ++i) - - if (RAdvisors[i]) - { - pAdvisor = (Unit::GetCreature((*me), RAdvisors[i])); - if (pAdvisor && !pAdvisor->isAlive()) - { - pAdvisor->Respawn(); - pAdvisor->AI()->EnterEvadeMode(); - pAdvisor->GetMotionMaster()->MoveTargetedHome(); - } - } - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - } - - void EventSharkkisDeath() - { - DoScriptText(SAY_GAIN_ABILITY1, me); - DoCast(me, SPELL_POWER_OF_SHARKKIS); - } - - void EventTidalvessDeath() - { - DoScriptText(SAY_GAIN_ABILITY2, me); - DoCast(me, SPELL_POWER_OF_TIDALVESS); - } - - void EventCaribdisDeath() - { - DoScriptText(SAY_GAIN_ABILITY3, me); - DoCast(me, SPELL_POWER_OF_CARIBDIS); - } - - void GetAdvisors() - { - if (!pInstance) - return; - - Advisors[0] = pInstance->GetData64(DATA_SHARKKIS); - Advisors[1] = pInstance->GetData64(DATA_TIDALVESS); - Advisors[2] = pInstance->GetData64(DATA_CARIBDIS); - } - - void StartEvent(Unit *who) - { - if (!pInstance) - return; - - GetAdvisors(); - - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); - - //support for quest 10944 - me->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 3600000); - } - - void EnterCombat(Unit * who) - { - StartEvent(who); - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - GetAdvisors(); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //CataclysmicBolt_Timer - if (CataclysmicBolt_Timer <= diff) - { - //select a random unit other than the main tank - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - - //if there aren't other units, cast on the tank - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget) - DoCast(pTarget, SPELL_CATACLYSMIC_BOLT); - CataclysmicBolt_Timer = 10000; - } else CataclysmicBolt_Timer -= diff; - - //SearNova_Timer - if (SearNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SEAR_NOVA); - SearNova_Timer = 20000+rand()%40000; - } else SearNova_Timer -= diff; - - //Enrage_Timer - if (Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enrage_Timer = 90000; - } else Enrage_Timer -= diff; - - //Blessing of Tides Trigger - if ((me->GetHealth()*100 / me->GetMaxHealth()) <= 75 && !BlessingOfTides) - { - BlessingOfTides = true; - bool continueTriggering = false; - Creature* Advisor; - for (uint8 i = 0; i < 4; ++i) - if (Advisors[i]) - { - Advisor = (Unit::GetCreature(*me, Advisors[i])); - if (Advisor && Advisor->isAlive()) - { - continueTriggering = true; - break; - } - } - if (continueTriggering) - { - DoCast(me, SPELL_BLESSING_OF_THE_TIDES); - me->MonsterYell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_GAIN_BLESSING_OF_TIDES); - } - } - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Sharkkis AI -struct boss_fathomguard_sharkkisAI : public ScriptedAI -{ - boss_fathomguard_sharkkisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 LeechingThrow_Timer; - uint32 TheBeastWithin_Timer; - uint32 Multishot_Timer; - uint32 Pet_Timer; - - bool pet; - - uint64 SummonedPet; - - void Reset() - { - LeechingThrow_Timer = 20000; - TheBeastWithin_Timer = 30000; - Multishot_Timer = 15000; - Pet_Timer = 10000; - - pet = false; - - Creature *Pet = Unit::GetCreature(*me, SummonedPet); - if (Pet && Pet->isAlive()) - { - Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - SummonedPet = 0; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //LeechingThrow_Timer - if (LeechingThrow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LEECHING_THROW); - LeechingThrow_Timer = 20000; - } else LeechingThrow_Timer -= diff; - - //Multishot_Timer - if (Multishot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MULTISHOT); - Multishot_Timer = 20000; - } else Multishot_Timer -= diff; - - //TheBeastWithin_Timer - if (TheBeastWithin_Timer <= diff) - { - DoCast(me, SPELL_THE_BEAST_WITHIN); - Creature *Pet = Unit::GetCreature(*me, SummonedPet); - if (Pet && Pet->isAlive()) - { - Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); - } - TheBeastWithin_Timer = 30000; - } else TheBeastWithin_Timer -= diff; - - //Pet_Timer - if (Pet_Timer < diff && pet == false) - { - pet = true; - //uint32 spell_id; - uint32 pet_id; - if (!urand(0,1)) - { - //spell_id = SPELL_SUMMON_FATHOM_LURKER; - pet_id = CREATURE_FATHOM_LURKER; - } - else - { - //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; - pet_id = CREATURE_FATHOM_SPOREBAT; - } - //DoCast(me, spell_id, true); - Creature *Pet = DoSpawnCreature(pet_id,0,0,0,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (Pet && pTarget) - { - Pet->AI()->AttackStart(pTarget); - SummonedPet = Pet->GetGUID(); - } - } else Pet_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Tidalvess AI -struct boss_fathomguard_tidalvessAI : public ScriptedAI -{ - boss_fathomguard_tidalvessAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 FrostShock_Timer; - uint32 Spitfire_Timer; - uint32 PoisonCleansing_Timer; - uint32 Earthbind_Timer; - - void Reset() - { - FrostShock_Timer = 25000; - Spitfire_Timer = 60000; - PoisonCleansing_Timer = 30000; - Earthbind_Timer = 45000; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - if (!me->isAlive() && Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventTidalvessDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - DoCast(me, SPELL_WINDFURY_WEAPON); - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - if (!me->HasAura(SPELL_WINDFURY_WEAPON)) - { - DoCast(me, SPELL_WINDFURY_WEAPON); - } - - //FrostShock_Timer - if (FrostShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_SHOCK); - FrostShock_Timer = 25000+rand()%5000; - } else FrostShock_Timer -= diff; - - //Spitfire_Timer - if (Spitfire_Timer <= diff) - { - DoCast(me, SPELL_SPITFIRE_TOTEM); - Unit *SpitfireTotem = Unit::GetUnit(*me, CREATURE_SPITFIRE_TOTEM); - if (SpitfireTotem) - { - CAST_CRE(SpitfireTotem)->AI()->AttackStart(me->getVictim()); - } - Spitfire_Timer = 60000; - } else Spitfire_Timer -= diff; - - //PoisonCleansing_Timer - if (PoisonCleansing_Timer <= diff) - { - DoCast(me, SPELL_POISON_CLEANSING_TOTEM); - PoisonCleansing_Timer = 30000; - } else PoisonCleansing_Timer -= diff; - - //Earthbind_Timer - if (Earthbind_Timer <= diff) - { - DoCast(me, SPELL_EARTHBIND_TOTEM); - Earthbind_Timer = 45000; - } else Earthbind_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Caribdis AI -struct boss_fathomguard_caribdisAI : public ScriptedAI -{ - boss_fathomguard_caribdisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 WaterBoltVolley_Timer; - uint32 TidalSurge_Timer; - uint32 Heal_Timer; - uint32 Cyclone_Timer; - - void Reset() - { - WaterBoltVolley_Timer = 35000; - TidalSurge_Timer = 15000+rand()%5000; - Heal_Timer = 55000; - Cyclone_Timer = 30000+rand()%10000; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - if (!me->isAlive() && Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventCaribdisDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //WaterBoltVolley_Timer - if (WaterBoltVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WATER_BOLT_VOLLEY); - WaterBoltVolley_Timer = 30000; - } else WaterBoltVolley_Timer -= diff; - - //TidalSurge_Timer - if (TidalSurge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIDAL_SURGE); - // Hacky way to do it - won't trigger elseways - me->getVictim()->CastSpell(me->getVictim(), SPELL_TIDAL_SURGE_FREEZE, true); - TidalSurge_Timer = 15000+rand()%5000; - } else TidalSurge_Timer -= diff; - - //Cyclone_Timer - if (Cyclone_Timer <= diff) - { - //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work - Cyclone_Timer = 30000+rand()%10000; - Creature *Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000); - if (Cyclone) - { - CAST_CRE(Cyclone)->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); - Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Cyclone->setFaction(me->getFaction()); - Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Cyclone->AI()->AttackStart(pTarget); - } - } - } else Cyclone_Timer -= diff; - - //Heal_Timer - if (Heal_Timer <= diff) - { - // It can be cast on any of the mobs - Unit *pUnit = NULL; - - while (pUnit == NULL || !pUnit->isAlive()) - { - pUnit = selectAdvisorUnit(); - } - - if (pUnit && pUnit->isAlive()) - DoCast(pUnit, SPELL_HEAL); - Heal_Timer = 60000; - } else Heal_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - Unit* selectAdvisorUnit() - { - Unit* pUnit = NULL; - if (pInstance) - { - switch(rand()%4) - { - case 0: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESS)); - break; - case 1: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_SHARKKIS)); - break; - case 2: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_TIDALVESS)); - break; - case 3: - pUnit = me; - break; - } - } else pUnit = me; - - return pUnit; - } -}; - -CreatureAI* GetAI_boss_fathomlord_karathress(Creature* pCreature) -{ - return new boss_fathomlord_karathressAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_sharkkis(Creature* pCreature) -{ - return new boss_fathomguard_sharkkisAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_tidalvess(Creature* pCreature) -{ - return new boss_fathomguard_tidalvessAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_caribdis(Creature* pCreature) -{ - return new boss_fathomguard_caribdisAI (pCreature); -} - -void AddSC_boss_fathomlord_karathress() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_fathomlord_karathress"; - newscript->GetAI = &GetAI_boss_fathomlord_karathress; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_sharkkis"; - newscript->GetAI = &GetAI_boss_fathomguard_sharkkis; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_tidalvess"; - newscript->GetAI = &GetAI_boss_fathomguard_tidalvess; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_caribdis"; - newscript->GetAI = &GetAI_boss_fathomguard_caribdis; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp b/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp deleted file mode 100644 index 923fdf55f80..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hydross_The_Unstable -SD%Complete: 90 -SDComment: Some details and adjustments left to do, probably nothing major. Spawns may be spawned in different way/location. -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define SAY_AGGRO -1548000 -#define SAY_SWITCH_TO_CLEAN -1548001 -#define SAY_CLEAN_SLAY1 -1548002 -#define SAY_CLEAN_SLAY2 -1548003 -#define SAY_CLEAN_DEATH -1548004 -#define SAY_SWITCH_TO_CORRUPT -1548005 -#define SAY_CORRUPT_SLAY1 -1548006 -#define SAY_CORRUPT_SLAY2 -1548007 -#define SAY_CORRUPT_DEATH -1548008 - -#define SWITCH_RADIUS 18 - -#define MODEL_CORRUPT 20609 -#define MODEL_CLEAN 20162 - -#define SPELL_WATER_TOMB 38235 -#define SPELL_MARK_OF_HYDROSS1 38215 -#define SPELL_MARK_OF_HYDROSS2 38216 -#define SPELL_MARK_OF_HYDROSS3 38217 -#define SPELL_MARK_OF_HYDROSS4 38218 -#define SPELL_MARK_OF_HYDROSS5 38231 -#define SPELL_MARK_OF_HYDROSS6 40584 -#define SPELL_MARK_OF_CORRUPTION1 38219 -#define SPELL_MARK_OF_CORRUPTION2 38220 -#define SPELL_MARK_OF_CORRUPTION3 38221 -#define SPELL_MARK_OF_CORRUPTION4 38222 -#define SPELL_MARK_OF_CORRUPTION5 38230 -#define SPELL_MARK_OF_CORRUPTION6 40583 -#define SPELL_VILE_SLUDGE 38246 -#define SPELL_ENRAGE 27680 //this spell need verification -#define SPELL_SUMMON_WATER_ELEMENT 36459 //not in use yet(in use ever?) -#define SPELL_ELEMENTAL_SPAWNIN 25035 -#define SPELL_BLUE_BEAM 40227 //channeled Hydross Beam Helper (not in use yet) - -#define ENTRY_PURE_SPAWN 22035 -#define ENTRY_TAINTED_SPAWN 22036 -#define ENTRY_BEAM_DUMMY 21934 - -#define HYDROSS_X -239.439 -#define HYDROSS_Y -363.481 - -#define SPAWN_X_DIFF1 6.934003 -#define SPAWN_Y_DIFF1 -11.255012 -#define SPAWN_X_DIFF2 -6.934003 -#define SPAWN_Y_DIFF2 11.255012 -#define SPAWN_X_DIFF3 -12.577011 -#define SPAWN_Y_DIFF3 -4.72702 -#define SPAWN_X_DIFF4 12.577011 -#define SPAWN_Y_DIFF4 4.72702 - -struct boss_hydross_the_unstableAI : public ScriptedAI -{ - boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 beams[2]; - uint32 PosCheck_Timer; - uint32 MarkOfHydross_Timer; - uint32 MarkOfCorruption_Timer; - uint32 WaterTomb_Timer; - uint32 VileSludge_Timer; - uint32 MarkOfHydross_Count; - uint32 MarkOfCorruption_Count; - uint32 EnrageTimer; - bool CorruptedForm; - bool beam; - SummonList Summons; - - void Reset() - { - DeSummonBeams(); - beams[0] = 0; - beams[1] = 0; - PosCheck_Timer = 2500; - MarkOfHydross_Timer = 15000; - MarkOfCorruption_Timer = 15000; - WaterTomb_Timer = 7000; - VileSludge_Timer = 7000; - MarkOfHydross_Count = 0; - MarkOfCorruption_Count = 0; - EnrageTimer = 600000; - - CorruptedForm = false; - me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - - me->SetDisplayId(MODEL_CLEAN); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); - beam = false; - Summons.DespawnAll(); - } - - void SummonBeams() - { - Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-258.333,-356.34,22.0499,5.90835,TEMPSUMMON_CORPSE_DESPAWN,0); - if (beamer) - { - beamer->CastSpell(me,SPELL_BLUE_BEAM,true); - beamer->SetDisplayId(11686); //invisible - beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - beams[0]=beamer->GetGUID(); - } - beamer = beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-219.918,-371.308,22.0042,2.73072,TEMPSUMMON_CORPSE_DESPAWN,0); - if (beamer) - { - beamer->CastSpell(me,SPELL_BLUE_BEAM,true); - beamer->SetDisplayId(11686); //invisible - beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - beams[1]=beamer->GetGUID(); - } - } - void DeSummonBeams() - { - for (uint8 i=0; i<2; ++i) - { - Creature* mob = Unit::GetCreature(*me,beams[i]); - if (mob) - { - mob->setDeathState(DEAD); - mob->RemoveCorpse(); - } - } - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - if (CorruptedForm) - { - DoScriptText(RAND(SAY_CORRUPT_SLAY1,SAY_CORRUPT_SLAY2), me); - } - else - { - DoScriptText(RAND(SAY_CLEAN_SLAY1,SAY_CLEAN_SLAY2), me); - } - } - - void JustSummoned(Creature* summoned) - { - if (summoned->GetEntry() == ENTRY_PURE_SPAWN) - { - summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); - Summons.Summon(summoned); - } - if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN) - { - summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); - Summons.Summon(summoned); - } - } - - void SummonedCreatureDespawn(Creature *summon) - { - Summons.Despawn(summon); - } - - void JustDied(Unit * /*victim*/) - { - if (CorruptedForm) - DoScriptText(SAY_CORRUPT_DEATH, me); - else - DoScriptText(SAY_CLEAN_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, DONE); - Summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!beam) - { - SummonBeams(); - beam=true; - } - //Return since we have no target - if (!UpdateVictim()) - return; - - // corrupted form - if (CorruptedForm) - { - //MarkOfCorruption_Timer - if (MarkOfCorruption_Timer <= diff) - { - if (MarkOfCorruption_Count <= 5) - { - uint32 mark_spell = 0; - - switch (MarkOfCorruption_Count) - { - case 0: mark_spell = SPELL_MARK_OF_CORRUPTION1; break; - case 1: mark_spell = SPELL_MARK_OF_CORRUPTION2; break; - case 2: mark_spell = SPELL_MARK_OF_CORRUPTION3; break; - case 3: mark_spell = SPELL_MARK_OF_CORRUPTION4; break; - case 4: mark_spell = SPELL_MARK_OF_CORRUPTION5; break; - case 5: mark_spell = SPELL_MARK_OF_CORRUPTION6; break; - } - - DoCast(me->getVictim(), mark_spell); - - if (MarkOfCorruption_Count < 5) - ++MarkOfCorruption_Count; - } - - MarkOfCorruption_Timer = 15000; - } else MarkOfCorruption_Timer -= diff; - - //VileSludge_Timer - if (VileSludge_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_VILE_SLUDGE); - - VileSludge_Timer = 15000; - } else VileSludge_Timer -= diff; - - //PosCheck_Timer - if (PosCheck_Timer <= diff) - { - if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) - { - // switch to clean form - me->SetDisplayId(MODEL_CLEAN); - CorruptedForm = false; - MarkOfHydross_Count = 0; - - DoScriptText(SAY_SWITCH_TO_CLEAN, me); - DoResetThreat(); - SummonBeams(); - - // spawn 4 adds - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - } - - PosCheck_Timer = 2500; - } else PosCheck_Timer -=diff; - } - // clean form - else - { - //MarkOfHydross_Timer - if (MarkOfHydross_Timer <= diff) - { - if (MarkOfHydross_Count <= 5) - { - uint32 mark_spell = NULL; - - switch(MarkOfHydross_Count) - { - case 0: mark_spell = SPELL_MARK_OF_HYDROSS1; break; - case 1: mark_spell = SPELL_MARK_OF_HYDROSS2; break; - case 2: mark_spell = SPELL_MARK_OF_HYDROSS3; break; - case 3: mark_spell = SPELL_MARK_OF_HYDROSS4; break; - case 4: mark_spell = SPELL_MARK_OF_HYDROSS5; break; - case 5: mark_spell = SPELL_MARK_OF_HYDROSS6; break; - } - - DoCast(me->getVictim(), mark_spell); - - if (MarkOfHydross_Count < 5) - ++MarkOfHydross_Count; - } - - MarkOfHydross_Timer = 15000; - } else MarkOfHydross_Timer -= diff; - - //WaterTomb_Timer - if (WaterTomb_Timer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget) - DoCast(pTarget, SPELL_WATER_TOMB); - - WaterTomb_Timer = 7000; - } else WaterTomb_Timer -= diff; - - //PosCheck_Timer - if (PosCheck_Timer <= diff) - { - if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) - { - // switch to corrupted form - me->SetDisplayId(MODEL_CORRUPT); - MarkOfCorruption_Count = 0; - CorruptedForm = true; - - DoScriptText(SAY_SWITCH_TO_CORRUPT, me); - DoResetThreat(); - DeSummonBeams(); - - // spawn 4 adds - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - } - - PosCheck_Timer = 2500; - } else PosCheck_Timer -=diff; - } - - //EnrageTimer - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - EnrageTimer = 60000; - } else EnrageTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_hydross_the_unstable(Creature* pCreature) -{ - return new boss_hydross_the_unstableAI (pCreature); -} - -void AddSC_boss_hydross_the_unstable() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hydross_the_unstable"; - newscript->GetAI = &GetAI_boss_hydross_the_unstable; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp deleted file mode 100644 index 2f0485d0e6c..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp +++ /dev/null @@ -1,1039 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA - */ - -/* ScriptData -SDName: Boss_Lady_Vashj -SD%Complete: 99 -SDComment: Missing blizzlike Shield Generators coords -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedSimpleAI.h" -#include "Spell.h" - -#define SAY_INTRO -1548042 -#define SAY_AGGRO1 -1548043 -#define SAY_AGGRO2 -1548044 -#define SAY_AGGRO3 -1548045 -#define SAY_AGGRO4 -1548046 -#define SAY_PHASE1 -1548047 -#define SAY_PHASE2 -1548048 -#define SAY_PHASE3 -1548049 -#define SAY_BOWSHOT1 -1548050 -#define SAY_BOWSHOT2 -1548051 -#define SAY_SLAY1 -1548052 -#define SAY_SLAY2 -1548053 -#define SAY_SLAY3 -1548054 -#define SAY_DEATH -1548055 - -#define SPELL_SURGE 38044 -#define SPELL_MULTI_SHOT 38310 -#define SPELL_SHOCK_BLAST 38509 -#define SPELL_ENTANGLE 38316 -#define SPELL_STATIC_CHARGE_TRIGGER 38280 -#define SPELL_FORKED_LIGHTNING 40088 -#define SPELL_SHOOT 40873 -#define SPELL_POISON_BOLT 40095 -#define SPELL_TOXIC_SPORES 38575 -#define SPELL_MAGIC_BARRIER 38112 - -#define MIDDLE_X 30.134 -#define MIDDLE_Y -923.65 -#define MIDDLE_Z 42.9 - -#define SPOREBAT_X 30.977156 -#define SPOREBAT_Y -925.297761 -#define SPOREBAT_Z 77.176567 -#define SPOREBAT_O 5.223932 - -#define SHIED_GENERATOR_CHANNEL 19870 -#define ENCHANTED_ELEMENTAL 21958 -#define TAINTED_ELEMENTAL 22009 -#define COILFANG_STRIDER 22056 -#define COILFANG_ELITE 22055 -#define TOXIC_SPOREBAT 22140 -#define TOXIC_SPORES_TRIGGER 22207 - -#define TEXT_NOT_INITIALIZED "Instance script not initialized" -#define TEXT_ALREADY_DEACTIVATED "Already deactivated" - -float ElementPos[8][4] = -{ - {8.3, -835.3, 21.9, 5}, - {53.4, -835.3, 21.9, 4.5}, - {96, -861.9, 21.8, 4}, - {96, -986.4, 21.4, 2.5}, - {54.4, -1010.6, 22, 1.8}, - {9.8, -1012, 21.7, 1.4}, - {-35, -987.6, 21.5, 0.8}, - {-58.9, -901.6, 21.5, 6} -}; - -float ElementWPPos[8][3] = -{ - {71.700752, -883.905884, 41.097168}, - {45.039848, -868.022827, 41.097015}, - {14.585141, -867.894470, 41.097061}, - {-25.415508, -906.737732, 41.097061}, - {-11.801594, -963.405884, 41.097067}, - {14.556657, -979.051514, 41.097137}, - {43.466549, -979.406677, 41.097027}, - {69.945908, -964.663940, 41.097054} -}; - -float SporebatWPPos[8][3] = -{ - {31.6,-896.3,59.1}, - {9.1, -913.9, 56}, - {5.2, -934.4, 52.4}, - {20.7, -946.9, 49.7}, - {41, -941.9, 51}, - {47.7, -927.3, 55}, - {42.2, -912.4, 51.7}, - {27, -905.9, 50} -}; - -float CoilfangElitePos[3][4] = -{ - {28.84, -923.28, 42.9, 6}, - {31.183281, -953.502625, 41.523602, 1.640957}, - {58.895180, -923.124268, 41.545307, 3.152848} -}; - -float CoilfangStriderPos[3][4] = -{ - {66.427010, -948.778503, 41.262245, 2.584220}, - {7.513962, -959.538208, 41.300422, 1.034629}, - {-12.843201, -907.798401, 41.239620, 6.087094} -}; - -float ShieldGeneratorChannelPos[4][4] = -{ - {49.6262, -902.181, 43.0975, 3.95683}, - {10.988, -901.616, 42.5371, 5.4373}, - {10.3859, -944.036, 42.5446, 0.779888}, - {49.3126, -943.398, 42.5501, 2.40174} -}; - -//Lady Vashj AI -struct boss_lady_vashjAI : public ScriptedAI -{ - boss_lady_vashjAI (Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = false; - JustCreated = true; - c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //set it only once on Creature create (no need do intro if wiped) - } - - ScriptedInstance *pInstance; - - uint64 ShieldGeneratorChannel[4]; - - uint32 AggroTimer; - uint32 ShockBlast_Timer; - uint32 Entangle_Timer; - uint32 StaticCharge_Timer; - uint32 ForkedLightning_Timer; - uint32 Check_Timer; - uint32 EnchantedElemental_Timer; - uint32 TaintedElemental_Timer; - uint32 CoilfangElite_Timer; - uint32 CoilfangStrider_Timer; - uint32 SummonSporebat_Timer; - uint32 SummonSporebat_StaticTimer; - uint8 EnchantedElemental_Pos; - uint8 Phase; - - bool Entangle; - bool Intro; - bool CanAttack; - bool JustCreated; - - void Reset() - { - AggroTimer = 19000; - ShockBlast_Timer = 1+rand()%60000; - Entangle_Timer = 30000; - StaticCharge_Timer = 10000+rand()%15000; - ForkedLightning_Timer = 2000; - Check_Timer = 15000; - EnchantedElemental_Timer = 5000; - TaintedElemental_Timer = 50000; - CoilfangElite_Timer = 45000+rand()%5000; - CoilfangStrider_Timer = 60000+rand()%10000; - SummonSporebat_Timer = 10000; - SummonSporebat_StaticTimer = 30000; - EnchantedElemental_Pos = 0; - Phase = 0; - - Entangle = false; - if (JustCreated) - { - CanAttack = false; - JustCreated = false; - } else CanAttack = true; - - Unit *remo; - for (uint8 i = 0; i < 4; ++i) - { - remo = Unit::GetUnit(*me, ShieldGeneratorChannel[i]); - if (remo) - remo->setDeathState(JUST_DIED); - } - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED); - ShieldGeneratorChannel[0] = 0; - ShieldGeneratorChannel[1] = 0; - ShieldGeneratorChannel[2] = 0; - ShieldGeneratorChannel[3] = 0; - - me->SetCorpseDelay(1000*60*60); - } - - //Called when a tainted elemental dies - void EventTaintedElementalDeath() - { - //the next will spawn 50 seconds after the previous one's death - if (TaintedElemental_Timer > 50000) - TaintedElemental_Timer = 50000; - } - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, DONE); - } - - void StartEvent() - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3,SAY_AGGRO4), me); - - Phase = 1; - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - //remove old tainted cores to prevent cheating in phase 2 - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* i_pl = i->getSource()) - { - i_pl->DestroyItemCount(31088, 1, true); - } - } - } - StartEvent();//this is EnterCombat(), so were are 100% in combat, start the event - - if (Phase != 2) - AttackStart(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (!Intro) - { - Intro = true; - DoScriptText(SAY_INTRO, me); - } - if (!CanAttack) - return; - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) - { - //if (who->HasStealthAura()) - // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - - if (!me->isInCombat())//AttackStart() sets UNIT_FLAG_IN_COMBAT, so this msut be before attacking - StartEvent(); - - if (Phase != 2) - AttackStart(who); - } - } - } - - void CastShootOrMultishot() - { - switch (urand(0,1)) - { - case 0: - //Shoot - //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. - DoCast(me->getVictim(), SPELL_SHOOT); - break; - case 1: - //Multishot - //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. - DoCast(me->getVictim(), SPELL_MULTI_SHOT); - break; - } - if (rand()%3) - { - DoScriptText(RAND(SAY_BOWSHOT1,SAY_BOWSHOT2), me); - } - } - - void UpdateAI(const uint32 diff) - { - if (!CanAttack && Intro) - { - if (AggroTimer <= diff) - { - CanAttack = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer=19000; - }else - { - AggroTimer-=diff; - return; - } - } - //to prevent abuses during phase 2 - if (Phase == 2 && !me->getVictim() && me->isInCombat()) - { - EnterEvadeMode(); - return; - } - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Phase == 1 || Phase == 3) - { - //ShockBlast_Timer - if (ShockBlast_Timer <= diff) - { - //Shock Burst - //Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. - DoCast(me->getVictim(), SPELL_SHOCK_BLAST); - me->TauntApply(me->getVictim()); - - ShockBlast_Timer = 1000+rand()%14000; //random cooldown - } else ShockBlast_Timer -= diff; - - //StaticCharge_Timer - if (StaticCharge_Timer <= diff) - { - //Static Charge - //Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. - Unit *pTarget = NULL; - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true); - - if (pTarget && !pTarget->HasAura(SPELL_STATIC_CHARGE_TRIGGER)) - //cast Static Charge every 2 seconds for 20 seconds - DoCast(pTarget, SPELL_STATIC_CHARGE_TRIGGER); - - StaticCharge_Timer = 10000+rand()%20000; //blizzlike - } else StaticCharge_Timer -= diff; - - //Entangle_Timer - if (Entangle_Timer <= diff) - { - if (!Entangle) - { - //Entangle - //Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. - DoCast(me->getVictim(), SPELL_ENTANGLE); - Entangle = true; - Entangle_Timer = 10000; - } - else - { - CastShootOrMultishot(); - Entangle = false; - Entangle_Timer = 20000+rand()%5000; - } - } else Entangle_Timer -= diff; - - //Phase 1 - if (Phase == 1) - { - //Start phase 2 - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 70) - { - //Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. - Phase = 2; - - me->GetMotionMaster()->Clear(); - DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - - Creature *pCreature; - for (uint8 i = 0; i < 4; ++i) - { - pCreature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0], ShieldGeneratorChannelPos[i][1], ShieldGeneratorChannelPos[i][2], ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); - if (pCreature) - ShieldGeneratorChannel[i] = pCreature->GetGUID(); - } - DoScriptText(SAY_PHASE2, me); - } - } - //Phase 3 - else - { - //SummonSporebat_Timer - if (SummonSporebat_Timer <= diff) - { - Creature *Sporebat = NULL; - Sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (Sporebat) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Sporebat->AI()->AttackStart(pTarget); - } - - //summon sporebats faster and faster - if (SummonSporebat_StaticTimer > 1000) - SummonSporebat_StaticTimer -= 1000; - - SummonSporebat_Timer = SummonSporebat_StaticTimer; - - if (SummonSporebat_Timer < 5000) - SummonSporebat_Timer = 5000; - - } else SummonSporebat_Timer -= diff; - } - - //Melee attack - DoMeleeAttackIfReady(); - - //Check_Timer - used to check if somebody is in melee range - if (Check_Timer <= diff) - { - bool InMeleeRange = false; - Unit *pTarget; - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //if in melee range - if (pTarget && pTarget->IsWithinDistInMap(me, 5)) - { - InMeleeRange = true; - break; - } - } - - //if nobody is in melee range - if (!InMeleeRange) - CastShootOrMultishot(); - - Check_Timer = 5000; - } else Check_Timer -= diff; - } - //Phase 2 - else - { - //ForkedLightning_Timer - if (ForkedLightning_Timer <= diff) - { - //Forked Lightning - //Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (!pTarget) - pTarget = me->getVictim(); - - DoCast(pTarget, SPELL_FORKED_LIGHTNING); - - ForkedLightning_Timer = 2000+rand()%6000; //blizzlike - } else ForkedLightning_Timer -= diff; - - //EnchantedElemental_Timer - if (EnchantedElemental_Timer <= diff) - { - Creature *Elemental; - Elemental = me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (EnchantedElemental_Pos == 7) - EnchantedElemental_Pos = 0; - else - ++EnchantedElemental_Pos; - - EnchantedElemental_Timer = 10000+rand()%5000; - } else EnchantedElemental_Timer -= diff; - - //TaintedElemental_Timer - if (TaintedElemental_Timer <= diff) - { - Creature *Tain_Elemental; - uint32 pos = rand()%8; - Tain_Elemental = me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN, 0); - - TaintedElemental_Timer = 120000; - } else TaintedElemental_Timer -= diff; - - //CoilfangElite_Timer - if (CoilfangElite_Timer <= diff) - { - uint32 pos = rand()%3; - Creature* CoilfangElite = NULL; - CoilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (CoilfangElite) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - CoilfangElite->AI()->AttackStart(pTarget); - else if (me->getVictim()) - CoilfangElite->AI()->AttackStart(me->getVictim()); - } - CoilfangElite_Timer = 45000+rand()%5000; - } else CoilfangElite_Timer -= diff; - - //CoilfangStrider_Timer - if (CoilfangStrider_Timer <= diff) - { - uint32 pos = rand()%3; - Creature* CoilfangStrider = NULL; - CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (CoilfangStrider) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - CoilfangStrider->AI()->AttackStart(pTarget); - else if (me->getVictim()) - CoilfangStrider->AI()->AttackStart(me->getVictim()); - } - CoilfangStrider_Timer = 60000+rand()%10000; - } else CoilfangStrider_Timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - //Start Phase 3 - if (pInstance && pInstance->GetData(DATA_CANSTARTPHASE3)) - { - //set life 50% - me->SetHealth(me->GetMaxHealth()/2); - - me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); - - DoScriptText(SAY_PHASE3, me); - - Phase = 3; - - //return to the tank - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - Check_Timer = 1000; - } else Check_Timer -= diff; - } - } -}; - -//Enchanted Elemental -//If one of them reaches Vashj he will increase her damage done by 5%. -struct mob_enchanted_elementalAI : public ScriptedAI -{ - mob_enchanted_elementalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 move; - uint32 phase; - float x, y, z; - - uint64 VashjGUID; - - void Reset() - { - me->SetSpeed(MOVE_WALK,0.6);//walk - me->SetSpeed(MOVE_RUN,0.6);//run - move = 0; - phase = 1; - - VashjGUID = 0; - - for (int i = 0; i<8; ++i)//search for nearest waypoint (up on stairs) - { - if (!x || !y || !z) - { - x = ElementWPPos[i][0]; - y = ElementWPPos[i][1]; - z = ElementWPPos[i][2]; - } - else - { - if (me->GetDistance(ElementWPPos[i][0],ElementWPPos[i][1],ElementWPPos[i][2]) < me->GetDistance(x,y,z)) - { - x = ElementWPPos[i][0]; - y = ElementWPPos[i][1]; - z = ElementWPPos[i][2]; - } - } - } - if (pInstance) - VashjGUID = pInstance->GetData64(DATA_LADYVASHJ); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (!VashjGUID) - return; - - if (move <= diff) - { - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - if (phase == 1) - me->GetMotionMaster()->MovePoint(0, x, y, z); - if (phase == 1 && me->IsWithinDist3d(x,y,z, 0.1)) - phase = 2; - if (phase == 2) - { - me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - phase = 3; - } - if (phase == 3) - { - me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - if (me->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) - DoCast(me, SPELL_SURGE); - } - if (Creature *Vashj = Unit::GetCreature(*me, VashjGUID)) - { - if (!Vashj->isInCombat() || CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase != 2 || Vashj->isDead()) - { - //call Unsummon() - me->Kill(me); - } - } - move = 1000; - } else move -= diff; - } -}; - -//Tainted Elemental -//This mob has 7,900 life, doesn't move, and shoots Poison Bolts at one person anywhere in the area, doing 3,000 nature damage and placing a posion doing 2,000 damage every 2 seconds. He will switch targets often, or sometimes just hang on a single player, but there is nothing you can do about it except heal the damage and kill the Tainted Elemental -struct mob_tainted_elementalAI : public ScriptedAI -{ - mob_tainted_elementalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 PoisonBolt_Timer; - uint32 Despawn_Timer; - - void Reset() - { - PoisonBolt_Timer = 5000+rand()%5000; - Despawn_Timer = 30000; - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - { - Creature *Vashj = NULL; - Vashj = (Unit::GetCreature((*me), pInstance->GetData64(DATA_LADYVASHJ))); - - if (Vashj) - CAST_AI(boss_lady_vashjAI, Vashj->AI())->EventTaintedElementalDeath(); - } - } - - void EnterCombat(Unit * who) - { - me->AddThreat(who, 0.1f); - } - - void UpdateAI(const uint32 diff) - { - //PoisonBolt_Timer - if (PoisonBolt_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget && pTarget->IsWithinDistInMap(me, 30)) - DoCast(pTarget, SPELL_POISON_BOLT); - - PoisonBolt_Timer = 5000+rand()%5000; - } else PoisonBolt_Timer -= diff; - - //Despawn_Timer - if (Despawn_Timer <= diff) - { - //call Unsummon() - me->setDeathState(DEAD); - - //to prevent crashes - Despawn_Timer = 1000; - } else Despawn_Timer -= diff; - } -}; - -//Toxic Sporebat -//Toxic Spores: Used in Phase 3 by the Spore Bats, it creates a contaminated green patch of ground, dealing about 2775-3225 nature damage every second to anyone who stands in it. -struct mob_toxic_sporebatAI : public ScriptedAI -{ - mob_toxic_sporebatAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EnterEvadeMode(); - } - - ScriptedInstance *pInstance; - - uint32 movement_timer; - uint32 ToxicSpore_Timer; - uint32 bolt_timer; - uint32 Check_Timer; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->setFaction(14); - movement_timer = 0; - ToxicSpore_Timer = 5000; - bolt_timer = 5500; - Check_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - - } - - void MoveInLineOfSight(Unit * /*who*/) - { - - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - movement_timer = 0; - } - - void UpdateAI (const uint32 diff) - { - //Random movement - if (movement_timer <= diff) - { - uint32 rndpos = rand()%8; - me->GetMotionMaster()->MovePoint(1,SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]); - movement_timer = 6000; - } else movement_timer -= diff; - - //toxic spores - if (bolt_timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); - if (trig) - { - trig->setFaction(14); - trig->CastSpell(trig, SPELL_TOXIC_SPORES,true); - } - } - bolt_timer = 10000+rand()%5000; - } - else bolt_timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - if (pInstance) - { - //check if vashj is death - Unit *Vashj = NULL; - Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); - if (!Vashj || (Vashj && !Vashj->isAlive()) || (Vashj && CAST_AI(boss_lady_vashjAI, CAST_CRE(Vashj)->AI())->Phase != 3)) - { - //remove - me->setDeathState(DEAD); - me->RemoveCorpse(); - me->setFaction(35); - } - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - } -}; - -//Coilfang Elite -//It's an elite Naga mob with 170,000 HP. It does about 5000 damage on plate, and has a nasty cleave hitting for about 7500 damage -CreatureAI* GetAI_mob_coilfang_elite(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = 31345; //Cleave - ai->Spell[0].Cooldown = 15000; - ai->Spell[0].CooldownRandomAddition = 5000; - ai->Spell[0].First_Cast = 5000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_RANDOM; - - ai->EnterEvadeMode(); - - return ai; -} - -//Coilfang Strider -//It hits plate for about 8000 damage, has a Mind Blast spell doing about 3000 shadow damage, and a Psychic Scream Aura, which fears everybody in a 8 yard range of it every 2-3 seconds , for 5 seconds and increasing their movement speed by 150% during the fear. -CreatureAI* GetAI_mob_coilfang_strider(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = 41374; //Mind Blast - ai->Spell[0].Cooldown = 30000; - ai->Spell[0].CooldownRandomAddition = 10000; - ai->Spell[0].First_Cast = 8000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - //Scream aura not implemented - - ai->EnterEvadeMode(); - - return ai; -} - -struct mob_shield_generator_channelAI : public ScriptedAI -{ - mob_shield_generator_channelAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 Check_Timer; - bool Casted; - void Reset() - { - Check_Timer = 0; - Casted = false; - me->SetDisplayId(11686); //invisible - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI (const uint32 diff) - { - if (!pInstance) - return; - - if (Check_Timer <= diff) - { - Unit *Vashj = NULL; - Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); - - if (Vashj && Vashj->isAlive()) - { - //start visual channel - if (!Casted || !Vashj->HasAura(SPELL_MAGIC_BARRIER)) - { - DoCast(Vashj, SPELL_MAGIC_BARRIER, true); - Casted = true; - } - } - Check_Timer = 1000; - } else Check_Timer -= diff; - } -}; - -bool ItemUse_item_tainted_core(Player* pPlayer, Item* /*_Item*/, SpellCastTargets const& targets) -{ - ScriptedInstance *pInstance = pPlayer->GetInstanceData(); - - if (!pInstance) - { - pPlayer->GetSession()->SendNotification(TEXT_NOT_INITIALIZED); - return true; - } - - Creature *Vashj = NULL; - Vashj = (Unit::GetCreature((*pPlayer), pInstance->GetData64(DATA_LADYVASHJ))); - if (Vashj && CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase == 2) - { - if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT) - { - uint32 identifier; - uint8 channel_identifier; - switch(targets.getGOTarget()->GetEntry()) - { - case 185052: - identifier = DATA_SHIELDGENERATOR1; - channel_identifier = 0; - break; - case 185053: - identifier = DATA_SHIELDGENERATOR2; - channel_identifier = 1; - break; - case 185051: - identifier = DATA_SHIELDGENERATOR3; - channel_identifier = 2; - break; - case 185054: - identifier = DATA_SHIELDGENERATOR4; - channel_identifier = 3; - break; - default: - return true; - } - - if (pInstance->GetData(identifier)) - { - pPlayer->GetSession()->SendNotification(TEXT_ALREADY_DEACTIVATED); - return true; - } - - //get and remove channel - Unit *Channel = NULL; - Channel = Unit::GetCreature(*Vashj, CAST_AI(boss_lady_vashjAI, Vashj->AI())->ShieldGeneratorChannel[channel_identifier]); - if (Channel) - { - //call Unsummon() - Channel->setDeathState(JUST_DIED); - } - - pInstance->SetData(identifier, 1); - - //remove this item - pPlayer->DestroyItemCount(31088, 1, true); - return true; - } - else if (targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT) - return false; - else if (targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) - { - pPlayer->DestroyItemCount(31088, 1, true); - pPlayer->CastSpell(targets.getUnitTarget(), 38134, true); - return true; - } - } - return true; -} - -CreatureAI* GetAI_boss_lady_vashj(Creature* pCreature) -{ - return new boss_lady_vashjAI (pCreature); -} - -CreatureAI* GetAI_mob_enchanted_elemental(Creature* pCreature) -{ - return new mob_enchanted_elementalAI (pCreature); -} - -CreatureAI* GetAI_mob_tainted_elemental(Creature* pCreature) -{ - return new mob_tainted_elementalAI (pCreature); -} - -CreatureAI* GetAI_mob_toxic_sporebat(Creature* pCreature) -{ - return new mob_toxic_sporebatAI (pCreature); -} - -CreatureAI* GetAI_mob_shield_generator_channel(Creature* pCreature) -{ - return new mob_shield_generator_channelAI (pCreature); -} - -void AddSC_boss_lady_vashj() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lady_vashj"; - newscript->GetAI = &GetAI_boss_lady_vashj; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_enchanted_elemental"; - newscript->GetAI = &GetAI_mob_enchanted_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tainted_elemental"; - newscript->GetAI = &GetAI_mob_tainted_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_toxic_sporebat"; - newscript->GetAI = &GetAI_mob_toxic_sporebat; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_elite"; - newscript->GetAI = &GetAI_mob_coilfang_elite; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_strider"; - newscript->GetAI = &GetAI_mob_coilfang_strider; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shield_generator_channel"; - newscript->GetAI = &GetAI_mob_shield_generator_channel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_tainted_core"; - newscript->pItemUse = &ItemUse_item_tainted_core; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp deleted file mode 100644 index 61c9ed9d527..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Leotheras_The_Blind -SD%Complete: 80 -SDComment: Possesion Support -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -// --- Spells used by Leotheras The Blind -#define SPELL_WHIRLWIND 37640 -#define SPELL_CHAOS_BLAST 37674 -#define SPELL_BERSERK 26662 -#define SPELL_INSIDIOUS_WHISPER 37676 -#define SPELL_DUAL_WIELD 42459 - -// --- Spells used in banish phase --- -#define BANISH_BEAM 38909 -#define AURA_BANISH 37833 - -// --- Spells used by Greyheart Spellbinders -#define SPELL_EARTHSHOCK 39076 -#define SPELL_MINDBLAST 37531 - -// --- Spells used by Inner Demons and Creature ID -#define INNER_DEMON_ID 21857 -#define AURA_DEMONIC_ALIGNMENT 37713 -#define SPELL_SHADOWBOLT 39309 -#define SPELL_SOUL_LINK 38007 -#define SPELL_CONSUMING_MADNESS 37749 //not supported by core yet - -//Misc. -#define MODEL_DEMON 20125 -#define MODEL_NIGHTELF 20514 -#define DEMON_FORM 21875 -#define MOB_SPELLBINDER 21806 - -#define SAY_AGGRO -1548009 -#define SAY_SWITCH_TO_DEMON -1548010 -#define SAY_INNER_DEMONS -1548011 -#define SAY_DEMON_SLAY1 -1548012 -#define SAY_DEMON_SLAY2 -1548013 -#define SAY_DEMON_SLAY3 -1548014 -#define SAY_NIGHTELF_SLAY1 -1548015 -#define SAY_NIGHTELF_SLAY2 -1548016 -#define SAY_NIGHTELF_SLAY3 -1548017 -#define SAY_FINAL_FORM -1548018 -#define SAY_FREE -1548019 -#define SAY_DEATH -1548020 - -struct mob_inner_demonAI : public ScriptedAI -{ - mob_inner_demonAI(Creature *c) : ScriptedAI(c) - { - victimGUID = 0; - } - - uint32 ShadowBolt_Timer; - - uint32 Link_Timer; - uint64 victimGUID; - - void Reset() - { - ShadowBolt_Timer = 10000; - Link_Timer = 1000; - } - void JustDied(Unit * /*victim*/) - { - Unit* pUnit = Unit::GetUnit((*me),victimGUID); - if (pUnit && pUnit->HasAura(SPELL_INSIDIOUS_WHISPER)) - pUnit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID()) - { - damage = 0; - DoModifyThreatPercent(done_by, -100); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (!victimGUID) return; - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (me->getVictim()->GetGUID() != victimGUID) - { - DoModifyThreatPercent(me->getVictim(), -100); - Unit* owner = Unit::GetUnit((*me),victimGUID); - if (owner && owner->isAlive()) - { - me->AddThreat(owner,999999); - AttackStart(owner); - } else if (owner && owner->isDead()) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - } - - if (Link_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOUL_LINK, true); - Link_Timer = 1000; - } else Link_Timer -= diff; - - if (!me->HasAura(AURA_DEMONIC_ALIGNMENT)) - DoCast(me, AURA_DEMONIC_ALIGNMENT, true); - - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLT, false); - ShadowBolt_Timer = 10000; - } else ShadowBolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -//Original Leotheras the Blind AI -struct boss_leotheras_the_blindAI : public ScriptedAI -{ - boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c) - { - c->GetPosition(x,y,z); - pInstance = c->GetInstanceData(); - Demon = 0; - - for (uint8 i = 0; i < 3; ++i)//clear guids - SpellBinderGUID[i] = 0; - } - - ScriptedInstance *pInstance; - - uint32 Whirlwind_Timer; - uint32 ChaosBlast_Timer; - uint32 SwitchToDemon_Timer; - uint32 SwitchToHuman_Timer; - uint32 Berserk_Timer; - uint32 InnerDemons_Timer; - uint32 BanishTimer; - - bool DealDamage; - bool NeedThreatReset; - bool DemonForm; - bool IsFinalForm; - bool EnrageUsed; - float x,y,z; - - uint64 InnderDemon[5]; - uint32 InnerDemon_Count; - uint64 Demon; - uint64 SpellBinderGUID[3]; - - void Reset() - { - CheckChannelers(); - BanishTimer = 1000; - Whirlwind_Timer = 15000; - ChaosBlast_Timer = 1000; - SwitchToDemon_Timer = 45000; - SwitchToHuman_Timer = 60000; - Berserk_Timer = 600000; - InnerDemons_Timer = 30000; - me->SetCanDualWield(true); - DealDamage = true; - DemonForm = false; - IsFinalForm = false; - NeedThreatReset = false; - EnrageUsed = false; - InnerDemon_Count = 0; - me->SetSpeed(MOVE_RUN, 2.0f, true); - me->SetDisplayId(MODEL_NIGHTELF); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - DoCast(me, SPELL_DUAL_WIELD, true); - me->SetCorpseDelay(1000*60*60); - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED); - } - - void CheckChannelers(/*bool DoEvade = true*/) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Creature *add = Unit::GetCreature(*me,SpellBinderGUID[i])) - add->DisappearAndDie(); - - float nx = x; - float ny = y; - float o = 2.4f; - if (i == 0) {nx += 10; ny -= 5; o=2.5f;} - if (i == 1) {nx -= 8; ny -= 7; o=0.9f;} - if (i == 2) {nx -= 3; ny += 9; o=5.0f;} - Creature* binder = me->SummonCreature(MOB_SPELLBINDER,nx,ny,z,o,TEMPSUMMON_DEAD_DESPAWN,0); - if (binder) - SpellBinderGUID[i] = binder->GetGUID(); - - } - } - void MoveInLineOfSight(Unit *who) - { - if (me->HasAura(AURA_BANISH)) - return; - - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius)) - { - // Check first that object is in an angle in front of this one before LoS check - if (me->HasInArc(M_PI/2.0f, who) && me->IsWithinLOSInMap(who)) - { - AttackStart(who); - } - } - } - } - - void StartEvent() - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, IN_PROGRESS); - } - - void CheckBanish() - { - uint8 AliveChannelers = 0; - for (uint8 i = 0; i < 3; ++i) - { - Unit *add = Unit::GetUnit(*me,SpellBinderGUID[i]); - if (add && add->isAlive()) - ++AliveChannelers; - } - - // channelers == 0 remove banish aura - if (AliveChannelers == 0 && me->HasAura(AURA_BANISH)) - { - // removing banish aura - me->RemoveAurasDueToSpell(AURA_BANISH); - - // Leotheras is getting immune again - me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); - - // changing model to bloodelf - me->SetDisplayId(MODEL_NIGHTELF); - - // and reseting equipment - me->LoadEquipment(me->GetEquipmentId()); - - if (pInstance && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - Unit *victim = NULL; - victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); - if (victim) - me->getThreatManager().addThreat(victim, 1); - StartEvent(); - } - } - else if (AliveChannelers != 0 && !me->HasAura(AURA_BANISH)) - { - // channelers != 0 apply banish aura - // removing Leotheras banish immune to apply AURA_BANISH - me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); - DoCast(me, AURA_BANISH); - - // changing model - me->SetDisplayId(MODEL_DEMON); - - // and removing weapons - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - } - } - - //Despawn all Inner Demon summoned - void DespawnDemon() - { - for (uint8 i=0; i<5; ++i) - { - if (InnderDemon[i]) - { - //delete creature - Creature* pCreature = Unit::GetCreature((*me), InnderDemon[i]); - if (pCreature && pCreature->isAlive()) - { - pCreature->ForcedDespawn(); - } - InnderDemon[i] = 0; - } - } - - InnerDemon_Count = 0; - } - - void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core - { - for (uint8 i=0; i<5; ++i) - { - if (InnderDemon[i] > 0) - { - Creature* pUnit = Unit::GetCreature((*me), InnderDemon[i]); - if (pUnit && pUnit->isAlive()) - { - Unit* pUnit_pTarget = Unit::GetUnit(*pUnit, CAST_AI(mob_inner_demonAI, pUnit->AI())->victimGUID); - if (pUnit_pTarget && pUnit_pTarget->isAlive()) - { - pUnit->CastSpell(pUnit_pTarget, SPELL_CONSUMING_MADNESS, true); - DoModifyThreatPercent(pUnit_pTarget, -100); - } - } - } - } - } - - void KilledUnit(Unit * victim) - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - if (DemonForm) - { - DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); - } - else - { - DoScriptText(RAND(SAY_NIGHTELF_SLAY1,SAY_NIGHTELF_SLAY2,SAY_NIGHTELF_SLAY3), me); - } - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - //despawn copy - if (Demon) - { - if (Creature* pDemon = Unit::GetCreature(*me, Demon)) - pDemon->ForcedDespawn(); - } - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - if (me->HasAura(AURA_BANISH)) - return; - - me->LoadEquipment(me->GetEquipmentId()); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (me->HasAura(AURA_BANISH) || !UpdateVictim()) - { - if (BanishTimer <= diff) - { - CheckBanish();//no need to check every update tick - BanishTimer = 1000; - } else BanishTimer -= diff; - return; - } - if (me->HasAura(SPELL_WHIRLWIND)) - if (Whirlwind_Timer <= diff) - { - Unit *newTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (newTarget) - { - DoResetThreat(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0,newTarget->GetPositionX(),newTarget->GetPositionY(),newTarget->GetPositionZ()); - } - Whirlwind_Timer = 2000; - } else Whirlwind_Timer -= diff; - - // reseting after changing forms and after ending whirlwind - if (NeedThreatReset && !me->HasAura(SPELL_WHIRLWIND)) - { - // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding) - if (DemonForm) - InnerDemons_Timer = 30000; - else - Whirlwind_Timer = 15000; - - NeedThreatReset = false; - DoResetThreat(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - - //Enrage_Timer (10 min) - if (Berserk_Timer < diff && !EnrageUsed) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_BERSERK); - EnrageUsed = true; - } else Berserk_Timer -= diff; - - if (!DemonForm) - { - //Whirldind Timer - if (!me->HasAura(SPELL_WHIRLWIND)) - { - if (Whirlwind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - // while whirlwinding this variable is used to countdown target's change - Whirlwind_Timer = 2000; - NeedThreatReset = true; - } else Whirlwind_Timer -= diff; - } - //Switch_Timer - - if (!IsFinalForm) - if (SwitchToDemon_Timer <= diff) - { - //switch to demon form - me->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0); - me->SetDisplayId(MODEL_DEMON); - DoScriptText(SAY_SWITCH_TO_DEMON, me); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - DemonForm = true; - NeedThreatReset = true; - SwitchToDemon_Timer = 45000; - } else SwitchToDemon_Timer -= diff; - DoMeleeAttackIfReady(); - } - else - { - //ChaosBlast_Timer - if (!me->getVictim()) - return; - if (me->IsWithinDist(me->getVictim(), 30)) - me->StopMoving(); - if (ChaosBlast_Timer <= diff) - { - // will cast only when in range of spell - if (me->IsWithinDist(me->getVictim(), 30)) - { - //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); - int damage = 100; - me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); - } - ChaosBlast_Timer = 3000; - } else ChaosBlast_Timer -= diff; - //Summon Inner Demon - if (InnerDemons_Timer <= diff) - { - std::list& ThreatList = me->getThreatManager().getThreatList(); - std::vector TargetList; - for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) - { - Unit *tempTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->getVictim()->GetGUID() && TargetList.size()<5) - TargetList.push_back(tempTarget); - } - //SpellEntry *spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); - for (std::vector::const_iterator itr = TargetList.begin(); itr != TargetList.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive()) - { - Creature * demon = me->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (demon) - { - demon->AI()->AttackStart((*itr)); - CAST_AI(mob_inner_demonAI, demon->AI())->victimGUID = (*itr)->GetGUID(); - - (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); - - if (InnerDemon_Count > 4) - InnerDemon_Count = 0; - - //Safe storing of creatures - InnderDemon[InnerDemon_Count] = demon->GetGUID(); - - //Update demon count - ++InnerDemon_Count; - } - } - } - DoScriptText(SAY_INNER_DEMONS, me); - - InnerDemons_Timer = 999999; - } else InnerDemons_Timer -= diff; - - //Switch_Timer - if (SwitchToHuman_Timer <= diff) - { - //switch to nightelf form - me->SetDisplayId(MODEL_NIGHTELF); - me->LoadEquipment(me->GetEquipmentId()); - - CastConsumingMadness(); - DespawnDemon(); - - DemonForm = false; - NeedThreatReset = true; - - SwitchToHuman_Timer = 60000; - } else SwitchToHuman_Timer -= diff; - } - - if (!IsFinalForm && (me->GetHealth()*100 / me->GetMaxHealth()) < 15) - { - //at this point he divides himself in two parts - CastConsumingMadness(); - DespawnDemon(); - Creature *Copy = NULL; - Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000); - if (Copy) - { - Demon = Copy->GetGUID(); - if (me->getVictim()) - Copy->AI()->AttackStart(me->getVictim()); - } - //set nightelf final form - IsFinalForm = true; - DemonForm = false; - - DoScriptText(SAY_FINAL_FORM, me); - me->SetDisplayId(MODEL_NIGHTELF); - me->LoadEquipment(me->GetEquipmentId()); - } - } -}; - -//Leotheras the Blind Demon Form AI -struct boss_leotheras_the_blind_demonformAI : public ScriptedAI -{ - boss_leotheras_the_blind_demonformAI(Creature *c) : ScriptedAI(c) {} - - uint32 ChaosBlast_Timer; - bool DealDamage; - - void Reset() - { - ChaosBlast_Timer = 1000; - DealDamage = true; - } - - void StartEvent() - { - DoScriptText(SAY_FREE, me); - } - - void KilledUnit(Unit * victim) - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) - DoCast(me, 8149, true); - } - - void EnterCombat(Unit * /*who*/) - { - StartEvent(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - //ChaosBlast_Timer - if (me->IsWithinDist(me->getVictim(), 30)) - me->StopMoving(); - - if (ChaosBlast_Timer <= diff) - { - // will cast only when in range od spell - if (me->IsWithinDist(me->getVictim(), 30)) - { - //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); - int damage = 100; - me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); - ChaosBlast_Timer = 3000; - } - } else ChaosBlast_Timer -= diff; - - //Do NOT deal any melee damage to the target. - } -}; -struct mob_greyheart_spellbinderAI : public ScriptedAI -{ - mob_greyheart_spellbinderAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - leotherasGUID = 0; - AddedBanish = false; - } - - ScriptedInstance *pInstance; - - uint64 leotherasGUID; - - uint32 Mindblast_Timer; - uint32 Earthshock_Timer; - - bool AddedBanish; - - void Reset() - { - Mindblast_Timer = 3000 + rand()%5000; - Earthshock_Timer = 5000 + rand()%5000; - - if (pInstance) - { - pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, 0); - Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); - if (leotheras && leotheras->isAlive()) - CAST_AI(boss_leotheras_the_blindAI, leotheras->AI())->CheckChannelers(/*false*/); - } - } - - void EnterCombat(Unit * who) - { - me->InterruptNonMeleeSpells(false); - if (pInstance) - pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID()); - } - - void JustRespawned() - { - AddedBanish = false; - Reset(); - } - - void CastChanneling() - { - if (!me->isInCombat() && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - { - if (leotherasGUID) - { - Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); - if (leotheras && leotheras->isAlive()) - DoCast(leotheras, BANISH_BEAM); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance) - { - if (!leotherasGUID) - leotherasGUID = pInstance->GetData64(DATA_LEOTHERAS); - - if (!me->isInCombat() && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - Unit *victim = NULL; - victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); - if (victim) - AttackStart(victim); - } - } - - if (!UpdateVictim()) - { - CastChanneling(); - return; - } - - if (pInstance && !pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - EnterEvadeMode(); - return; - } - - if (Mindblast_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (pTarget)DoCast(pTarget, SPELL_MINDBLAST); - - Mindblast_Timer = 10000 + rand()%5000; - } else Mindblast_Timer -= diff; - - if (Earthshock_Timer <= diff) - { - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) - { - if (Player* i_pl = itr->getSource()) - { - bool isCasting = false; - for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) - if (i_pl->GetCurrentSpell(i)) - isCasting = true; - - if (isCasting) - { - DoCast(i_pl, SPELL_EARTHSHOCK); - break; - } - } - } - Earthshock_Timer = 8000 + rand()%7000; - } else Earthshock_Timer -= diff; - DoMeleeAttackIfReady(); - } - - void JustDied(Unit * /*killer*/) {} -}; -CreatureAI* GetAI_boss_leotheras_the_blind(Creature* pCreature) -{ - return new boss_leotheras_the_blindAI (pCreature); -} - -CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature* pCreature) -{ - return new boss_leotheras_the_blind_demonformAI (pCreature); -} - -CreatureAI* GetAI_mob_greyheart_spellbinder(Creature* pCreature) -{ - return new mob_greyheart_spellbinderAI (pCreature); -} - -CreatureAI* GetAI_mob_inner_demon(Creature* pCreature) -{ - return new mob_inner_demonAI (pCreature); -} -void AddSC_boss_leotheras_the_blind() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_leotheras_the_blind"; - newscript->GetAI = &GetAI_boss_leotheras_the_blind; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_leotheras_the_blind_demonform"; - newscript->GetAI = &GetAI_boss_leotheras_the_blind_demonform; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_greyheart_spellbinder"; - newscript->GetAI = &GetAI_mob_greyheart_spellbinder; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_inner_demon"; - newscript->GetAI = &GetAI_mob_inner_demon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp b/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp deleted file mode 100644 index b1c0c10bcce..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: boss_the_lurker_below -SD%Complete: 80 -SDComment: Coilfang Frenzy, find out how could we fishing in the strangepool -SDCategory: The Lurker Below -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedSimpleAI.h" -#include "Spell.h" - -#define SPELL_SPOUT 37433 -#define SPELL_SPOUT_ANIM 42835 -#define SPELL_SPOUT_BREATH 37431 -#define SPELL_KNOCKBACK 19813 -#define SPELL_GEYSER 37478 -#define SPELL_WHIRL 37660 -#define SPELL_WATERBOLT 37138 -#define SPELL_SUBMERGE 37550 -#define SPELL_EMERGE 20568 - -#define EMOTE_SPOUT "The Lurker Below takes a deep breath." - -#define SPOUT_DIST 100 - -#define MOB_COILFANG_GUARDIAN 21873 -#define MOB_COILFANG_AMBUSHER 21865 - -//Ambusher spells -#define SPELL_SPREAD_SHOT 37790 -#define SPELL_SHOOT 37770 - -//Guardian spells -#define SPELL_ARCINGSMASH 38761 // Wrong SpellId. Can't find the right one. -#define SPELL_HAMSTRING 26211 - -float AddPos[9][3] = -{ - {2.8553810, -459.823914, -19.182686}, //MOVE_AMBUSHER_1 X, Y, Z - {12.400000, -466.042267, -19.182686}, //MOVE_AMBUSHER_2 X, Y, Z - {51.366653, -460.836060, -19.182686}, //MOVE_AMBUSHER_3 X, Y, Z - {62.597980, -457.433044, -19.182686}, //MOVE_AMBUSHER_4 X, Y, Z - {77.607452, -384.302765, -19.182686}, //MOVE_AMBUSHER_5 X, Y, Z - {63.897900, -378.984924, -19.182686}, //MOVE_AMBUSHER_6 X, Y, Z - {34.447250, -387.333618, -19.182686}, //MOVE_GUARDIAN_1 X, Y, Z - {14.388216, -423.468018, -19.625271}, //MOVE_GUARDIAN_2 X, Y, Z - {42.471519, -445.115295, -19.769423} //MOVE_GUARDIAN_3 X, Y, Z -}; - -struct boss_the_lurker_belowAI : public Scripted_NoMovementAI -{ - boss_the_lurker_belowAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - SpellEntry *TempSpell = GET_SPELL(SPELL_SPOUT_ANIM); - if (TempSpell) - { - TempSpell->Effect[0] = 0;//remove all spell effect, only anim is needed - TempSpell->Effect[1] = 0; - TempSpell->Effect[2] = 0; - } - } - - ScriptedInstance* pInstance; - SummonList Summons; - - bool Spawned; - bool Submerged; - bool InRange; - bool CanStartEvent; - uint32 RotTimer; - uint32 SpoutAnimTimer; - uint32 WaterboltTimer; - uint32 SpoutTimer; - uint32 WhirlTimer; - uint32 PhaseTimer; - uint32 GeyserTimer; - uint32 CheckTimer; - uint32 WaitTimer; - uint32 WaitTimer2; - - bool CheckCanStart()//check if players fished - { - if (pInstance && pInstance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) - return false; - return true; - } - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); - SpoutAnimTimer = 1000; - RotTimer = 0; - WaterboltTimer = 15000;//give time to get in range when fight starts - SpoutTimer = 45000; - WhirlTimer = 18000;//after avery spout - PhaseTimer = 120000; - GeyserTimer = rand()%5000 + 15000; - CheckTimer = 15000;//give time to get in range when fight starts - WaitTimer = 60000;//never reached - WaitTimer2 = 60000;//never reached - - Submerged = true;//will be false at combat start - Spawned = false; - InRange = false; - CanStartEvent = false; - - Summons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_THELURKERBELOWEVENT, NOT_STARTED); - pInstance->SetData(DATA_STRANGE_POOL, NOT_STARTED); - } - DoCast(me, SPELL_SUBMERGE);//submerge anim - me->SetVisibility(VISIBILITY_OFF);//we start invis under water, submerged - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_THELURKERBELOWEVENT, DONE); - - Summons.DespawnAll(); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - pInstance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS); - Scripted_NoMovementAI::EnterCombat(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (!CanStartEvent)//boss is invisible, don't attack - return; - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius)) - { - AttackStart(who); - } - } - } - - void MovementInform(uint32 type, uint32 /*id*/) - { - if (type == ROTATE_MOTION_TYPE) - me->SetReactState(REACT_AGGRESSIVE); - } - - void UpdateAI(const uint32 diff) - { - if (!CanStartEvent)//boss is invisible, don't attack - { - if (CheckCanStart()) - { - if (Submerged) - { - me->SetVisibility(VISIBILITY_ON); - Submerged = false; - WaitTimer2 = 500; - } - if (!Submerged && WaitTimer2 <= diff)//wait 500ms before emerge anim - { - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); - DoCast(me, SPELL_EMERGE, false); - WaitTimer2 = 60000;//never reached - WaitTimer = 3000; - } else WaitTimer2 -= diff; - - if (WaitTimer <= diff)//wait 3secs for emerge anim, then attack - { - WaitTimer = 3000; - CanStartEvent=true;//fresh fished from pool - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } else WaitTimer -= diff; - } - return; - } - - if (me->getThreatManager().getThreatList().empty())//check if should evade - { - if (me->isInCombat()) - EnterEvadeMode(); - return; - } - if (!Submerged) - { - if (PhaseTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SUBMERGE); - PhaseTimer = 60000;//60secs submerged - Submerged = true; - } else PhaseTimer-=diff; - - if (SpoutTimer <= diff) - { - me->MonsterTextEmote(EMOTE_SPOUT,0,true); - me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveRotate(20000, rand()%2 ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); - SpoutTimer = 45000; - WhirlTimer = 20000;//whirl directly after spout - RotTimer = 20000; - return; - } else SpoutTimer -= diff; - - //Whirl directly after a Spout and at random times - if (WhirlTimer <= diff) - { - WhirlTimer = 18000; - DoCast(me, SPELL_WHIRL); - } else WhirlTimer -= diff; - - if (CheckTimer <= diff)//check if there are players in melee range - { - InRange = false; - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (me->IsWithinMeleeRange(i->getSource())) - InRange = true; - } - } - CheckTimer = 2000; - } else CheckTimer -= diff; - - if (RotTimer) - { - Map* pMap = me->GetMap(); - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->isAlive() && me->HasInArc((double)diff/20000*(double)M_PI*2,i->getSource()) && me->IsWithinDist(i->getSource(), SPOUT_DIST) && !i->getSource()->IsInWater()) - DoCast(i->getSource(), SPELL_SPOUT, true);//only knock back palyers in arc, in 100yards, not in water - } - } - - if (SpoutAnimTimer <= diff) - { - DoCast(me, SPELL_SPOUT_ANIM, true); - SpoutAnimTimer = 1000; - } else SpoutAnimTimer -= diff; - - if (RotTimer <= diff) - { - RotTimer = 0; - } else RotTimer -= diff; - return; - } - - if (GeyserTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (!pTarget && me->getVictim()) - pTarget = me->getVictim(); - if (pTarget) - DoCast(pTarget, SPELL_GEYSER, true); - GeyserTimer = rand()%5000 + 15000; - } else GeyserTimer -= diff; - - if (!InRange)//if on players in melee range cast Waterbolt - { - if (WaterboltTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget && me->getVictim()) - pTarget = me->getVictim(); - if (pTarget) - DoCast(pTarget, SPELL_WATERBOLT, true); - WaterboltTimer = 3000; - } else WaterboltTimer -= diff; - } - - if (!UpdateCombatState()) - return; - - DoMeleeAttackIfReady(); - - }else//submerged - { - if (PhaseTimer <= diff) - { - Submerged = false; - me->InterruptNonMeleeSpells(false);//shouldn't be any - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); - DoCast(me, SPELL_EMERGE, true); - Spawned = false; - SpoutTimer = 3000; // directly cast Spout after emerging! - PhaseTimer = 120000; - return; - } else PhaseTimer-=diff; - - if (me->getThreatManager().getThreatList().empty())//check if should evade - { - EnterEvadeMode(); - return; - } - if (!me->isInCombat()) - DoZoneInCombat(); - - if (!Spawned) - { - me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - //spawn adds - for (uint8 i = 0; i < 9; ++i) - { - Creature* Summoned; - if (i < 6) - Summoned = me->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - else Summoned = me->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (Summoned) - Summons.Summon(Summoned); - } - Spawned = true; - } - } - } - }; - -CreatureAI* GetAI_mob_coilfang_guardian(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = SPELL_ARCINGSMASH; - ai->Spell[0].Cooldown = 15000; - ai->Spell[0].First_Cast = 5000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->Spell[1].Enabled = true; - ai->Spell[1].Spell_Id = SPELL_HAMSTRING; - ai->Spell[1].Cooldown = 10000; - ai->Spell[1].First_Cast = 2000; - ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; - - return ai; -} - -struct mob_coilfang_ambusherAI : public Scripted_NoMovementAI -{ - mob_coilfang_ambusherAI(Creature *c) : Scripted_NoMovementAI(c) - { - SpellEntry *TempSpell = GET_SPELL(SPELL_SHOOT); - if (TempSpell) - TempSpell->Effect[0] = 2;//change spell effect from weapon % dmg to simple phisical dmg - } - - uint32 MultiShotTimer; - uint32 ShootBowTimer; - - void Reset() - { - MultiShotTimer = 10000; - ShootBowTimer = 4000; - - } - - void EnterCombat(Unit * /*who*/) - { - - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who) && me->IsWithinDistInMap(who, 45)) - { - AttackStart(who); - } - } - - void UpdateAI(const uint32 diff) - { - if (MultiShotTimer <= diff) - { - if (me->getVictim()) - DoCast(me->getVictim(), SPELL_SPREAD_SHOT, true); - - MultiShotTimer = 10000+rand()%10000; - ShootBowTimer += 1500;//add global cooldown - } else MultiShotTimer -= diff; - - if (ShootBowTimer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - int bp0 = 1100; - if (pTarget) - me->CastCustomSpell(pTarget,SPELL_SHOOT,&bp0,NULL,NULL,true); - ShootBowTimer = 4000+rand()%5000; - MultiShotTimer += 1500;//add global cooldown - } else ShootBowTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_coilfang_ambusher(Creature* pCreature) -{ - return new mob_coilfang_ambusherAI (pCreature); -} - -CreatureAI* GetAI_boss_the_lurker_below(Creature* pCreature) -{ - return new boss_the_lurker_belowAI (pCreature); -} - -void AddSC_boss_the_lurker_below() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_lurker_below"; - newscript->GetAI = &GetAI_boss_the_lurker_below; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_guardian"; - newscript->GetAI = &GetAI_mob_coilfang_guardian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_ambusher"; - newscript->GetAI = &GetAI_mob_coilfang_ambusher; - newscript->RegisterSelf(); -} - - diff --git a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp deleted file mode 100644 index 14c87aee141..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Morogrim_Tidewalker -SD%Complete: 90 -SDComment: Water globules don't explode properly, remove hacks -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define SAY_AGGRO -1548030 -#define SAY_SUMMON1 -1548031 -#define SAY_SUMMON2 -1548032 -#define SAY_SUMMON_BUBL1 -1548033 -#define SAY_SUMMON_BUBL2 -1548034 -#define SAY_SLAY1 -1548035 -#define SAY_SLAY2 -1548036 -#define SAY_SLAY3 -1548037 -#define SAY_DEATH -1548038 -#define EMOTE_WATERY_GRAVE -1548039 -#define EMOTE_EARTHQUAKE -1548040 -#define EMOTE_WATERY_GLOBULES -1548041 - -#define SPELL_TIDAL_WAVE 37730 -#define SPELL_WATERY_GRAVE 38049 -#define SPELL_EARTHQUAKE 37764 -#define SPELL_WATERY_GRAVE_EXPLOSION 37852 - -#define WATERY_GRAVE_X1 334.64 -#define WATERY_GRAVE_Y1 -728.89 -#define WATERY_GRAVE_Z1 -14.42 -#define WATERY_GRAVE_X2 365.51 -#define WATERY_GRAVE_Y2 -737.14 -#define WATERY_GRAVE_Z2 -14.44 -#define WATERY_GRAVE_X3 366.19 -#define WATERY_GRAVE_Y3 -709.59 -#define WATERY_GRAVE_Z3 -14.36 -#define WATERY_GRAVE_X4 372.93 -#define WATERY_GRAVE_Y4 -690.96 -#define WATERY_GRAVE_Z4 -14.44 - -#define SPELL_WATERY_GRAVE_1 38023 -#define SPELL_WATERY_GRAVE_2 38024 -#define SPELL_WATERY_GRAVE_3 38025 -#define SPELL_WATERY_GRAVE_4 37850 - -#define SPELL_SUMMON_WATER_GLOBULE_1 37854 -#define SPELL_SUMMON_WATER_GLOBULE_2 37858 -#define SPELL_SUMMON_WATER_GLOBULE_3 37860 -#define SPELL_SUMMON_WATER_GLOBULE_4 37861 - -/*#define SPELL_SUMMON_MURLOC_A6 39813 -#define SPELL_SUMMON_MURLOC_A7 39814 -#define SPELL_SUMMON_MURLOC_A8 39815 -#define SPELL_SUMMON_MURLOC_A9 39816 -#define SPELL_SUMMON_MURLOC_A10 39817 - -#define SPELL_SUMMON_MURLOC_B6 39818 -#define SPELL_SUMMON_MURLOC_B7 39819 -#define SPELL_SUMMON_MURLOC_B8 39820 -#define SPELL_SUMMON_MURLOC_B9 39821 -#define SPELL_SUMMON_MURLOC_B10 39822*/ - -float MurlocCords[10][5] = -{ - {21920, 424.36, -715.4, -7.14, 0.124}, - {21920, 425.13, -719.3, -7.14, 0.124}, - {21920, 425.05, -724.23, -7.14, 0.124}, - {21920, 424.91, -728.68, -7.14, 0.124}, - {21920, 424.84, -732.18, -7.14, 0.124}, - {21920, 321.05, -734.2, -13.15, 0.124}, - {21920, 321.05, -729.4, -13.15, 0.124}, - {21920, 321.05, -724.03, -13.15, 0.124}, - {21920, 321.05, -718.73, -13.15, 0.124}, - {21920, 321.05, -714.24, -13.15, 0.124} -}; - -//Creatures -#define WATER_GLOBULE 21913 -#define TIDEWALKER_LURKER 21920 - -//Morogrim Tidewalker AI -struct boss_morogrim_tidewalkerAI : public ScriptedAI -{ - boss_morogrim_tidewalkerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - Map::PlayerList const *PlayerList; - - uint32 TidalWave_Timer; - uint32 WateryGrave_Timer; - uint32 Earthquake_Timer; - uint32 WateryGlobules_Timer; - uint32 globulespell[4]; - int8 Playercount; - int8 counter; - - bool Earthquake; - bool Phase2; - - void Reset() - { - TidalWave_Timer = 10000; - WateryGrave_Timer = 30000; - Earthquake_Timer = 40000; - WateryGlobules_Timer = 0; - globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1; - globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2; - globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3; - globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4; - - Earthquake = false; - Phase2 = false; - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); - } - - void StartEvent() - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - PlayerList = &me->GetMap()->GetPlayers(); - Playercount = PlayerList->getSize(); - StartEvent(); - } - - void ApplyWateryGrave(Unit* pPlayer, uint8 i) - { - switch(i) - { - case 0: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_1, true); break; - case 1: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_2, true); break; - case 2: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_3, true); break; - case 3: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_4, true); break; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Earthquake_Timer - if (Earthquake_Timer <= diff) - { - if (!Earthquake) - { - DoCast(me->getVictim(), SPELL_EARTHQUAKE); - Earthquake = true; - Earthquake_Timer = 10000; - } - else - { - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - - for (uint8 i = 0; i < 10; ++i) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - Creature* Murloc = me->SummonCreature(MurlocCords[i][0],MurlocCords[i][1],MurlocCords[i][2],MurlocCords[i][3],MurlocCords[i][4], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); - if (pTarget && Murloc) - Murloc->AI()->AttackStart(pTarget); - } - DoScriptText(EMOTE_EARTHQUAKE, me); - Earthquake = false; - Earthquake_Timer = 40000+rand()%5000; - } - } else Earthquake_Timer -= diff; - - //TidalWave_Timer - if (TidalWave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIDAL_WAVE); - TidalWave_Timer = 20000; - } else TidalWave_Timer -= diff; - - if (!Phase2) - { - //WateryGrave_Timer - if (WateryGrave_Timer <= diff) - { - //Teleport 4 players under the waterfalls - Unit *pTarget; - using std::set; - setlist; - set::const_iterator itr; - for (uint8 i = 0; i < 4; ++i) - { - counter = 0; - do - { - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only - if (counter < Playercount) - break; - if (pTarget) - itr = list.find(pTarget->GetGUID()); - ++counter; - } while (itr != list.end()); - - if (pTarget) - { - list.insert(pTarget->GetGUID()); - ApplyWateryGrave(pTarget, i); - } - } - - DoScriptText(RAND(SAY_SUMMON_BUBL1,SAY_SUMMON_BUBL2), me); - - DoScriptText(EMOTE_WATERY_GRAVE, me); - WateryGrave_Timer = 30000; - } else WateryGrave_Timer -= diff; - - //Start Phase2 - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) - Phase2 = true; - } - else - { - //WateryGlobules_Timer - if (WateryGlobules_Timer <= diff) - { - Unit* pGlobuleTarget; - using std::set; - setglobulelist; - set::const_iterator itr; - for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD - { - counter = 0; - do { - pGlobuleTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); - if (pGlobuleTarget) - itr = globulelist.find(pGlobuleTarget->GetGUID()); - if (counter > Playercount) - break; - ++counter; - } while (itr != globulelist.end()); - if (pGlobuleTarget) - globulelist.insert(pGlobuleTarget->GetGUID()); - pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true); - } - DoScriptText(EMOTE_WATERY_GLOBULES, me); - WateryGlobules_Timer = 25000; - } else WateryGlobules_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -//Water Globule AI -#define SPELL_GLOBULE_EXPLOSION 37871 - -struct mob_water_globuleAI : public ScriptedAI -{ - mob_water_globuleAI(Creature *c) : ScriptedAI(c) {} - - uint32 Check_Timer; - - void Reset() - { - Check_Timer = 1000; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - //no attack radius check - it attacks the first target that moves in his los - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Check_Timer <= diff) - { - if (me->IsWithinDistInMap(me->getVictim(), 5)) - { - DoCast(me->getVictim(), SPELL_GLOBULE_EXPLOSION); - - //despawn - me->ForcedDespawn(); - return; - } - Check_Timer = 500; - } else Check_Timer -= diff; - - //do NOT deal any melee damage to the target. - } -}; - -CreatureAI* GetAI_boss_morogrim_tidewalker(Creature* pCreature) -{ - return new boss_morogrim_tidewalkerAI (pCreature); -} -CreatureAI* GetAI_mob_water_globule(Creature* pCreature) -{ - return new mob_water_globuleAI (pCreature); -} - -void AddSC_boss_morogrim_tidewalker() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_morogrim_tidewalker"; - newscript->GetAI = &GetAI_boss_morogrim_tidewalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_water_globule"; - newscript->GetAI = &GetAI_mob_water_globule; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp deleted file mode 100644 index c80afae15c7..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Serpent_Shrine -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Serpent Shrine Scripts -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define MAX_ENCOUNTER 6 -#define SPELL_SCALDINGWATER 37284 -#define MOB_COILFANG_FRENZY 21508 -#define TRASHMOB_COILFANG_PRIESTESS 21220 //6*2 -#define TRASHMOB_COILFANG_SHATTERER 21301 //6*3 - -#define MIN_KILLS 30 - -//NOTE: there are 6 platforms -//there should be 3 shatterers and 2 priestess on all platforms, total of 30 elites, else it won't work! -//delete all other elites not on platforms! these mobs should only be on those platforms nowhere else. - -/* Serpentshrine cavern encounters: -0 - Hydross The Unstable event -1 - Leotheras The Blind Event -2 - The Lurker Below Event -3 - Fathom-Lord Karathress Event -4 - Morogrim Tidewalker Event -5 - Lady Vashj Event -*/ - -bool GOHello_go_bridge_console(Player* /*pPlayer*/, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - - if (!pInstance) - return false; - - if (pInstance) - pInstance->SetData(DATA_CONTROL_CONSOLE, DONE); - - return true; -} - -struct instance_serpentshrine_cavern : public ScriptedInstance -{ - instance_serpentshrine_cavern(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 LurkerBelow; - uint64 Sharkkis; - uint64 Tidalvess; - uint64 Caribdis; - uint64 LadyVashj; - uint64 Karathress; - uint64 KarathressEvent_Starter; - uint64 LeotherasTheBlind; - uint64 LeotherasEventStarter; - - uint64 ControlConsole; - uint64 BridgePart[3]; - uint32 StrangePool; - uint32 FishingTimer; - uint32 LurkerSubEvent; - uint32 WaterCheckTimer; - uint32 FrenzySpawnTimer; - uint32 Water; - uint32 TrashCount; - - bool ShieldGeneratorDeactivated[4]; - uint32 m_auiEncounter[MAX_ENCOUNTER]; - bool DoSpawnFrenzy; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - LurkerBelow = 0; - Sharkkis = 0; - Tidalvess = 0; - Caribdis = 0; - LadyVashj = 0; - Karathress = 0; - KarathressEvent_Starter = 0; - LeotherasTheBlind = 0; - LeotherasEventStarter = 0; - - ControlConsole = 0; - BridgePart[0] = 0; - BridgePart[1] = 0; - BridgePart[2] = 0; - StrangePool = 0; - Water = WATERSTATE_FRENZY; - - ShieldGeneratorDeactivated[0] = false; - ShieldGeneratorDeactivated[1] = false; - ShieldGeneratorDeactivated[2] = false; - ShieldGeneratorDeactivated[3] = false; - FishingTimer = 1000; - LurkerSubEvent = 0; - WaterCheckTimer = 500; - FrenzySpawnTimer = 2000; - DoSpawnFrenzy = false; - TrashCount = 0; - - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void Update (uint32 diff) - { - //Lurker Fishing event - if (LurkerSubEvent == LURKER_FISHING) - { - if (FishingTimer <= diff) - { - LurkerSubEvent = LURKER_HOOKED; - SetData(DATA_STRANGE_POOL, IN_PROGRESS);//just fished, signal Lurker script to emerge and start fight, we use IN_PROGRESS so it won't get saved and lurker will be alway invis at start if server restarted - } else FishingTimer -= diff; - } - //Water checks - if (WaterCheckTimer <= diff) - { - if (TrashCount >= MIN_KILLS) - Water = WATERSTATE_SCALDING; - else - Water = WATERSTATE_FRENZY; - - Map::PlayerList const &PlayerList = instance->GetPlayers(); - if (PlayerList.isEmpty()) - return; - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isAlive() && /*i->getSource()->GetPositionZ() <= -21.434931f*/pPlayer->IsInWater()) - { - if (Water == WATERSTATE_SCALDING) - { - - if (!pPlayer->HasAura(SPELL_SCALDINGWATER)) - { - pPlayer->CastSpell(pPlayer, SPELL_SCALDINGWATER,true); - } - } else if (Water == WATERSTATE_FRENZY) - { - //spawn frenzy - if (DoSpawnFrenzy) - { - if (Creature* frenzy = pPlayer->SummonCreature(MOB_COILFANG_FRENZY,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ(),pPlayer->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,2000)) - { - frenzy->Attack(pPlayer,false); - frenzy->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); - } - DoSpawnFrenzy = false; - } - } - } - if (!pPlayer->IsInWater()) - pPlayer->RemoveAurasDueToSpell(SPELL_SCALDINGWATER); - } - - } - WaterCheckTimer = 500;//remove stress from core - } else WaterCheckTimer -= diff; - if (FrenzySpawnTimer <= diff) - { - DoSpawnFrenzy = true; - FrenzySpawnTimer = 2000; - } else FrenzySpawnTimer -= diff; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 184568: - ControlConsole = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184203: - BridgePart[0] = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184204: - BridgePart[1] = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184205: - BridgePart[2] = pGo->GetGUID(); - pGo->setActive(true); - break; - case GAMEOBJECT_FISHINGNODE_ENTRY://no way checking if fish is hooked, so we create a timed event - if (LurkerSubEvent == LURKER_NOT_STARTED) - { - FishingTimer = 10000+rand()%30000;//random time before lurker emerges - LurkerSubEvent = LURKER_FISHING; - } - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 21212: LadyVashj = pCreature->GetGUID(); break; - case 21214: Karathress = pCreature->GetGUID(); break; - case 21966: Sharkkis = pCreature->GetGUID(); break; - case 21217: LurkerBelow = pCreature->GetGUID(); break; - case 21965: Tidalvess = pCreature->GetGUID(); break; - case 21964: Caribdis = pCreature->GetGUID(); break; - case 21215: LeotherasTheBlind = pCreature->GetGUID(); break; - /*case TRASHMOB_COILFANG_PRIESTESS: - case TRASHMOB_COILFANG_SHATTERER: - if (pCreature->isAlive()) - ++TrashCount; - break;*/ - } - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_KARATHRESSEVENT_STARTER) - KarathressEvent_Starter = data; - if (type == DATA_LEOTHERAS_EVENT_STARTER) - LeotherasEventStarter = data; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_THELURKERBELOW: return LurkerBelow; - case DATA_SHARKKIS: return Sharkkis; - case DATA_TIDALVESS: return Tidalvess; - case DATA_CARIBDIS: return Caribdis; - case DATA_LADYVASHJ: return LadyVashj; - case DATA_KARATHRESS: return Karathress; - case DATA_KARATHRESSEVENT_STARTER: return KarathressEvent_Starter; - case DATA_LEOTHERAS: return LeotherasTheBlind; - case DATA_LEOTHERAS_EVENT_STARTER: return LeotherasEventStarter; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_STRANGE_POOL: - { - StrangePool = data; - if (data == NOT_STARTED) - LurkerSubEvent = LURKER_NOT_STARTED; - } - break; - case DATA_CONTROL_CONSOLE: - if (data == DONE) - { - HandleGameObject(BridgePart[0], true); - HandleGameObject(BridgePart[0], true); - HandleGameObject(BridgePart[0], true); - } - ControlConsole = data;break; - case DATA_TRASH : - { - if (data == 1 && TrashCount < MIN_KILLS) - ++TrashCount;//+1 died - SaveToDB(); - break; - } - case DATA_WATER : Water = data;break; - case DATA_HYDROSSTHEUNSTABLEEVENT: m_auiEncounter[0] = data; break; - case DATA_LEOTHERASTHEBLINDEVENT: m_auiEncounter[1] = data; break; - case DATA_THELURKERBELOWEVENT: m_auiEncounter[2] = data; break; - case DATA_KARATHRESSEVENT: m_auiEncounter[3] = data; break; - case DATA_MOROGRIMTIDEWALKEREVENT: m_auiEncounter[4] = data; break; - //Lady Vashj - case DATA_LADYVASHJEVENT: - if (data == NOT_STARTED) - { - ShieldGeneratorDeactivated[0] = false; - ShieldGeneratorDeactivated[1] = false; - ShieldGeneratorDeactivated[2] = false; - ShieldGeneratorDeactivated[3] = false; - } - m_auiEncounter[5] = data; break; - case DATA_SHIELDGENERATOR1:ShieldGeneratorDeactivated[0] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR2:ShieldGeneratorDeactivated[1] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR3:ShieldGeneratorDeactivated[2] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR4:ShieldGeneratorDeactivated[3] = (data) ? true : false; break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_HYDROSSTHEUNSTABLEEVENT: return m_auiEncounter[0]; - case DATA_LEOTHERASTHEBLINDEVENT: return m_auiEncounter[1]; - case DATA_THELURKERBELOWEVENT: return m_auiEncounter[2]; - case DATA_KARATHRESSEVENT: return m_auiEncounter[3]; - case DATA_MOROGRIMTIDEWALKEREVENT: return m_auiEncounter[4]; - //Lady Vashj - case DATA_LADYVASHJEVENT: return m_auiEncounter[5]; - case DATA_SHIELDGENERATOR1: return ShieldGeneratorDeactivated[0]; - case DATA_SHIELDGENERATOR2: return ShieldGeneratorDeactivated[1]; - case DATA_SHIELDGENERATOR3: return ShieldGeneratorDeactivated[2]; - case DATA_SHIELDGENERATOR4: return ShieldGeneratorDeactivated[3]; - case DATA_CANSTARTPHASE3: - if (ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3])return 1;break; - case DATA_STRANGE_POOL: return StrangePool; - case DATA_WATER: return Water; - } - return 0; - } - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << TrashCount; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> TrashCount; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_serpentshrine_cavern(Map* pMap) -{ - return new instance_serpentshrine_cavern(pMap); -} - -void AddSC_instance_serpentshrine_cavern() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_serpent_shrine"; - newscript->GetInstanceData = &GetInstanceData_instance_serpentshrine_cavern; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_bridge_console"; - newscript->pGOHello = &GOHello_go_bridge_console; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h b/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h deleted file mode 100644 index adfa39dc7e0..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SERPENT_SHRINE_H -#define DEF_SERPENT_SHRINE_H -enum LurkerEventState -{ - LURKER_NOT_STARTED = 0, - LURKER_FISHING = 1, - LURKER_HOOKED = 2 -}; -enum WaterEventState -{ - WATERSTATE_NONE = 0, - WATERSTATE_FRENZY = 1, - WATERSTATE_SCALDING = 2 -}; -#define DATA_CANSTARTPHASE3 1 -#define DATA_CARIBDIS 2 -#define DATA_HYDROSSTHEUNSTABLEEVENT 3 -#define DATA_KARATHRESS 4 -#define DATA_KARATHRESSEVENT 5 -#define DATA_KARATHRESSEVENT_STARTER 6 -#define DATA_LADYVASHJ 7 -#define DATA_LADYVASHJEVENT 8 -#define DATA_LEOTHERASTHEBLINDEVENT 9 -#define DATA_MOROGRIMTIDEWALKEREVENT 10 -#define DATA_SHARKKIS 11 -#define DATA_SHIELDGENERATOR1 12 -#define DATA_SHIELDGENERATOR2 13 -#define DATA_SHIELDGENERATOR3 14 -#define DATA_SHIELDGENERATOR4 15 -#define DATA_THELURKERBELOW 16 -#define DATA_THELURKERBELOWEVENT 17 -#define DATA_TIDALVESS 18 -#define DATA_FATHOMLORDKARATHRESSEVENT 19 -#define DATA_LEOTHERAS 20 -#define DATA_LEOTHERAS_EVENT_STARTER 21 -#define DATA_CONTROL_CONSOLE 22 -#define DATA_STRANGE_POOL 23 -#define DATA_WATER 24 -#define DATA_TRASH 25 -#endif - diff --git a/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp b/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp deleted file mode 100644 index 8e1b438bdc5..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hydromancer_Thespia -SD%Complete: 80 -SDComment: Needs additional adjustments (when instance script is adjusted) -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -/* ContentData -boss_hydromancer_thespia -mob_coilfang_waterelemental -EndContentData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_SUMMON -1545000 -#define SAY_AGGRO_1 -1545001 -#define SAY_AGGRO_2 -1545002 -#define SAY_AGGRO_3 -1545003 -#define SAY_SLAY_1 -1545004 -#define SAY_SLAY_2 -1545005 -#define SAY_DEAD -1545006 - -#define SPELL_LIGHTNING_CLOUD 25033 -#define SPELL_LUNG_BURST 31481 -#define SPELL_ENVELOPING_WINDS 31718 - -struct boss_thespiaAI : public ScriptedAI -{ - boss_thespiaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 LightningCloud_Timer; - uint32 LungBurst_Timer; - uint32 EnvelopingWinds_Timer; - - void Reset() - { - LightningCloud_Timer = 15000; - LungBurst_Timer = 7000; - EnvelopingWinds_Timer = 9000; - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, NOT_STARTED); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEAD, me); - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //LightningCloud_Timer - if (LightningCloud_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LIGHTNING_CLOUD); - - //cast twice in Heroic mode - if (IsHeroic()) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LIGHTNING_CLOUD); - - LightningCloud_Timer = 15000+rand()%10000; - } else LightningCloud_Timer -=diff; - - //LungBurst_Timer - if (LungBurst_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LUNG_BURST); - LungBurst_Timer = 7000+rand()%5000; - } else LungBurst_Timer -=diff; - - //EnvelopingWinds_Timer - if (EnvelopingWinds_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ENVELOPING_WINDS); - - //cast twice in Heroic mode - if (IsHeroic()) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ENVELOPING_WINDS); - EnvelopingWinds_Timer = 10000+rand()%5000; - } else EnvelopingWinds_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -#define SPELL_WATER_BOLT_VOLLEY 34449 -#define H_SPELL_WATER_BOLT_VOLLEY 37924 - -struct mob_coilfang_waterelementalAI : public ScriptedAI -{ - mob_coilfang_waterelementalAI(Creature *c) : ScriptedAI(c) {} - - uint32 WaterBoltVolley_Timer; - - void Reset() - { - WaterBoltVolley_Timer = 3000+rand()%3000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (WaterBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_WATER_BOLT_VOLLEY); - WaterBoltVolley_Timer = 7000+rand()%5000; - } else WaterBoltVolley_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_thespiaAI(Creature* pCreature) -{ - return new boss_thespiaAI (pCreature); -} - -CreatureAI* GetAI_mob_coilfang_waterelementalAI(Creature* pCreature) -{ - return new mob_coilfang_waterelementalAI (pCreature); -} - -void AddSC_boss_hydromancer_thespia() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_hydromancer_thespia"; - newscript->GetAI = &GetAI_boss_thespiaAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_waterelemental"; - newscript->GetAI = &GetAI_mob_coilfang_waterelementalAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp b/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp deleted file mode 100644 index f2da4058e44..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mekgineer_Steamrigger -SD%Complete: 60 -SDComment: Mechanics' interrrupt heal doesn't work very well, also a proper movement needs to be implemented -> summon further away and move towards pTarget to repair. -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -/* ContentData -boss_mekgineer_steamrigger -mob_steamrigger_mechanic -EndContentData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_MECHANICS -1545007 -#define SAY_AGGRO_1 -1545008 -#define SAY_AGGRO_2 -1545009 -#define SAY_AGGRO_3 -1545010 -#define SAY_AGGRO_4 -1545011 -#define SAY_SLAY_1 -1545012 -#define SAY_SLAY_2 -1545013 -#define SAY_SLAY_3 -1545014 -#define SAY_DEATH -1545015 - -#define SPELL_SUPER_SHRINK_RAY 31485 -#define SPELL_SAW_BLADE 31486 -#define SPELL_ELECTRIFIED_NET 35107 -#define H_SPELL_ENRAGE 1 //corrent enrage spell not known - -#define ENTRY_STREAMRIGGER_MECHANIC 17951 - -struct boss_mekgineer_steamriggerAI : public ScriptedAI -{ - boss_mekgineer_steamriggerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Shrink_Timer; - uint32 Saw_Blade_Timer; - uint32 Electrified_Net_Timer; - bool Summon75; - bool Summon50; - bool Summon25; - - void Reset() - { - Shrink_Timer = 20000; - Saw_Blade_Timer = 15000; - Electrified_Net_Timer = 10000; - - Summon75 = false; - Summon50 = false; - Summon25 = false; - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, NOT_STARTED); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, IN_PROGRESS); - } - - //no known summon spells exist - void SummonMechanichs() - { - DoScriptText(SAY_MECHANICS, me); - - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - - if (rand()%2) - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,-7,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - if (rand()%2) - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,7,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Shrink_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUPER_SHRINK_RAY); - Shrink_Timer = 20000; - } else Shrink_Timer -= diff; - - if (Saw_Blade_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_SAW_BLADE); - else - DoCast(me->getVictim(), SPELL_SAW_BLADE); - - Saw_Blade_Timer = 15000; - } else Saw_Blade_Timer -= diff; - - if (Electrified_Net_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ELECTRIFIED_NET); - Electrified_Net_Timer = 10000; - } - else Electrified_Net_Timer -= diff; - - if (!Summon75) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 75) - { - SummonMechanichs(); - Summon75 = true; - } - } - - if (!Summon50) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) - { - SummonMechanichs(); - Summon50 = true; - } - } - - if (!Summon25) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) - { - SummonMechanichs(); - Summon25 = true; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_mekgineer_steamrigger(Creature* pCreature) -{ - return new boss_mekgineer_steamriggerAI (pCreature); -} - -#define SPELL_DISPEL_MAGIC 17201 -#define SPELL_REPAIR 31532 -#define H_SPELL_REPAIR 37936 - -#define MAX_REPAIR_RANGE (13.0f) //we should be at least at this range for repair -#define MIN_REPAIR_RANGE (7.0f) //we can stop movement at this range to repair but not required - -struct mob_steamrigger_mechanicAI : public ScriptedAI -{ - mob_steamrigger_mechanicAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Repair_Timer; - - void Reset() - { - Repair_Timer = 2000; - } - - void MoveInLineOfSight(Unit* /*who*/) - { - //react only if attacked - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (Repair_Timer <= diff) - { - if (pInstance && pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER) && pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) - { - if (Unit* pMekgineer = Unit::GetUnit((*me), pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER))) - { - if (me->IsWithinDistInMap(pMekgineer, MAX_REPAIR_RANGE)) - { - //are we already channeling? Doesn't work very well, find better check? - if (!me->GetUInt32Value(UNIT_CHANNEL_SPELL)) - { - //me->GetMotionMaster()->MovementExpired(); - //me->GetMotionMaster()->MoveIdle(); - - DoCast(me, SPELL_REPAIR, true); - } - Repair_Timer = 5000; - } - else - { - //me->GetMotionMaster()->MovementExpired(); - //me->GetMotionMaster()->MoveFollow(pMekgineer,0,0); - } - } - } else Repair_Timer = 5000; - } else Repair_Timer -= diff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_steamrigger_mechanic(Creature* pCreature) -{ - return new mob_steamrigger_mechanicAI (pCreature); -} - -void AddSC_boss_mekgineer_steamrigger() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_mekgineer_steamrigger"; - newscript->GetAI = &GetAI_boss_mekgineer_steamrigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_steamrigger_mechanic"; - newscript->GetAI = &GetAI_mob_steamrigger_mechanic; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp b/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp deleted file mode 100644 index f46956dda81..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warlord_Kalithres -SD%Complete: 65 -SDComment: Contains workarounds regarding warlord's rage spells not acting as expected. Both scripts here require review and fine tuning. -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_INTRO -1545016 -#define SAY_REGEN -1545017 -#define SAY_AGGRO1 -1545018 -#define SAY_AGGRO2 -1545019 -#define SAY_AGGRO3 -1545020 -#define SAY_SLAY1 -1545021 -#define SAY_SLAY2 -1545022 -#define SAY_DEATH -1545023 - -#define SPELL_SPELL_REFLECTION 31534 -#define SPELL_IMPALE 39061 -#define SPELL_WARLORDS_RAGE 37081 -#define SPELL_WARLORDS_RAGE_NAGA 31543 - -#define SPELL_WARLORDS_RAGE_PROC 36453 - -struct mob_naga_distillerAI : public ScriptedAI -{ - mob_naga_distillerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - //hack, due to really weird spell behaviour :( - if (pInstance) - { - if (pInstance->GetData(TYPE_DISTILLER) == IN_PROGRESS) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - } - - void EnterCombat(Unit * /*who*/) { } - - void StartRageGen(Unit * /*caster*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - DoCast(me, SPELL_WARLORDS_RAGE_NAGA, true); - - if (pInstance) - pInstance->SetData(TYPE_DISTILLER,IN_PROGRESS); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (me->GetHealth() <= damage) - if (pInstance) - pInstance->SetData(TYPE_DISTILLER,DONE); - } -}; - -struct boss_warlord_kalithreshAI : public ScriptedAI -{ - boss_warlord_kalithreshAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Reflection_Timer; - uint32 Impale_Timer; - uint32 Rage_Timer; - bool CanRage; - - void Reset() - { - Reflection_Timer = 10000; - Impale_Timer = 7000+rand()%7000; - Rage_Timer = 45000; - CanRage = false; - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - //hack :( - if (spell->Id == SPELL_WARLORDS_RAGE_PROC) - if (pInstance) - if (pInstance->GetData(TYPE_DISTILLER) == DONE) - me->RemoveAurasDueToSpell(SPELL_WARLORDS_RAGE_PROC); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Rage_Timer <= diff) - { - if (Creature* distiller = me->FindNearestCreature(17954, 100.0f)) - { - DoScriptText(SAY_REGEN, me); - DoCast(me, SPELL_WARLORDS_RAGE); - CAST_AI(mob_naga_distillerAI, distiller->AI())->StartRageGen(me); - } - Rage_Timer = 3000+rand()%15000; - } else Rage_Timer -= diff; - - //Reflection_Timer - if (Reflection_Timer <= diff) - { - DoCast(me, SPELL_SPELL_REFLECTION); - Reflection_Timer = 15000+rand()%10000; - } else Reflection_Timer -= diff; - - //Impale_Timer - if (Impale_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_IMPALE); - - Impale_Timer = 7500+rand()%5000; - } else Impale_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_naga_distiller(Creature* pCreature) -{ - return new mob_naga_distillerAI (pCreature); -} - -CreatureAI* GetAI_boss_warlord_kalithresh(Creature* pCreature) -{ - return new boss_warlord_kalithreshAI (pCreature); -} - -void AddSC_boss_warlord_kalithresh() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_naga_distiller"; - newscript->GetAI = &GetAI_mob_naga_distiller; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_warlord_kalithresh"; - newscript->GetAI = &GetAI_boss_warlord_kalithresh; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp b/src/server/scripts/outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp deleted file mode 100644 index 188a23738f5..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Steam_Vault -SD%Complete: 80 -SDComment: Instance script and access panel GO -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define MAX_ENCOUNTER 4 - -#define MAIN_CHAMBERS_DOOR 183049 -#define ACCESS_PANEL_HYDRO 184125 -#define ACCESS_PANEL_MEK 184126 - -/* Steam Vaults encounters: -1 - Hydromancer Thespia Event -2 - Mekgineer Steamrigger Event -3 - Warlord Kalithresh Event -*/ - -bool GOHello_go_main_chambers_access_panel(Player* /*pPlayer*/, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - - if (!pInstance) - return false; - - if (pGo->GetEntry() == ACCESS_PANEL_HYDRO && (pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == DONE || pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL)) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA,SPECIAL); - - if (pGo->GetEntry() == ACCESS_PANEL_MEK && (pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == DONE || pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL)) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER,SPECIAL); - - return true; -} - -struct instance_steam_vault : public ScriptedInstance -{ - instance_steam_vault(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 ThespiaGUID; - uint64 MekgineerGUID; - uint64 KalithreshGUID; - - uint64 MainChambersDoor; - uint64 AccessPanelHydro; - uint64 AccessPanelMek; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - ThespiaGUID = 0; - MekgineerGUID = 0; - KalithreshGUID = 0; - MainChambersDoor = 0; - AccessPanelHydro = 0; - AccessPanelMek = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17797: ThespiaGUID = pCreature->GetGUID(); break; - case 17796: MekgineerGUID = pCreature->GetGUID(); break; - case 17798: KalithreshGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case MAIN_CHAMBERS_DOOR: MainChambersDoor = pGo->GetGUID(); break; - case ACCESS_PANEL_HYDRO: AccessPanelHydro = pGo->GetGUID(); break; - case ACCESS_PANEL_MEK: AccessPanelMek = pGo->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_HYDROMANCER_THESPIA: - if (data == SPECIAL) - { - HandleGameObject(AccessPanelHydro, true); - - if (GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL) - HandleGameObject(MainChambersDoor, true); - - debug_log("TSCR: Instance Steamvault: Access panel used."); - } - m_auiEncounter[0] = data; - break; - case TYPE_MEKGINEER_STEAMRIGGER: - if (data == SPECIAL) - { - HandleGameObject(AccessPanelMek, true); - - if (GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL) - HandleGameObject(MainChambersDoor, true); - - debug_log("TSCR: Instance Steamvault: Access panel used."); - } - m_auiEncounter[1] = data; - break; - case TYPE_WARLORD_KALITHRESH: - m_auiEncounter[2] = data; - break; - case TYPE_DISTILLER: - m_auiEncounter[3] = data; - break; - } - - if (data == DONE || data == SPECIAL) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_HYDROMANCER_THESPIA: - return m_auiEncounter[0]; - case TYPE_MEKGINEER_STEAMRIGGER: - return m_auiEncounter[1]; - case TYPE_WARLORD_KALITHRESH: - return m_auiEncounter[2]; - case TYPE_DISTILLER: - return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THESPIA: - return ThespiaGUID; - case DATA_MEKGINEERSTEAMRIGGER: - return MekgineerGUID; - case DATA_KALITRESH: - return KalithreshGUID; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_steam_vault(Map* pMap) -{ - return new instance_steam_vault(pMap); -} - -void AddSC_instance_steam_vault() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_main_chambers_access_panel"; - newscript->pGOHello = &GOHello_go_main_chambers_access_panel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "instance_steam_vault"; - newscript->GetInstanceData = &GetInstanceData_instance_steam_vault; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/steam_vault/steam_vault.h b/src/server/scripts/outland/coilfang_resevoir/steam_vault/steam_vault.h deleted file mode 100644 index 4b407ac4816..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/steam_vault/steam_vault.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_STEAM_VAULT_H -#define DEF_STEAM_VAULT_H - -#define TYPE_HYDROMANCER_THESPIA 1 -#define TYPE_MEKGINEER_STEAMRIGGER 2 -#define TYPE_WARLORD_KALITHRESH 3 -#define TYPE_DISTILLER 4 - -#define DATA_MEKGINEERSTEAMRIGGER 5 -#define DATA_KALITRESH 6 -#define DATA_THESPIA 7 -#endif - diff --git a/src/server/scripts/outland/coilfang_resevoir/underbog/boss_hungarfen.cpp b/src/server/scripts/outland/coilfang_resevoir/underbog/boss_hungarfen.cpp deleted file mode 100644 index fcfcc1b1a90..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/underbog/boss_hungarfen.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hungarfen -SD%Complete: 95 -SDComment: Need confirmation if spell data are same in both modes. Summons should have faster rate in heroic -SDCategory: Coilfang Resevoir, Underbog -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FOUL_SPORES 31673 -#define SPELL_ACID_GEYSER 38739 - -struct boss_hungarfenAI : public ScriptedAI -{ - boss_hungarfenAI(Creature *c) : ScriptedAI(c) - { - } - - bool Root; - uint32 Mushroom_Timer; - uint32 AcidGeyser_Timer; - - void Reset() - { - Root = false; - Mushroom_Timer = 5000; // 1 mushroom after 5s, then one per 10s. This should be different in heroic mode - AcidGeyser_Timer = 10000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) - { - if (!Root) - { - DoCast(me, SPELL_FOUL_SPORES); - Root = true; - } - } - - if (Mushroom_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - me->SummonCreature(17990, pTarget->GetPositionX()+(rand()%8), pTarget->GetPositionY()+(rand()%8), pTarget->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); - else - me->SummonCreature(17990, me->GetPositionX()+(rand()%8), me->GetPositionY()+(rand()%8), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); - - Mushroom_Timer = 10000; - } else Mushroom_Timer -= diff; - - if (AcidGeyser_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ACID_GEYSER); - AcidGeyser_Timer = 10000+rand()%7500; - } else AcidGeyser_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_hungarfen(Creature* pCreature) -{ - return new boss_hungarfenAI (pCreature); -} - -#define SPELL_SPORE_CLOUD 34168 -#define SPELL_PUTRID_MUSHROOM 31690 -#define SPELL_GROW 31698 - -struct mob_underbog_mushroomAI : public ScriptedAI -{ - mob_underbog_mushroomAI(Creature *c) : ScriptedAI(c) {} - - bool Stop; - uint32 Grow_Timer; - uint32 Shrink_Timer; - - void Reset() - { - Stop = false; - Grow_Timer = 0; - Shrink_Timer = 20000; - - DoCast(me, SPELL_PUTRID_MUSHROOM, true); - DoCast(me, SPELL_SPORE_CLOUD, true); - } - - void MoveInLineOfSight(Unit * /*who*/) {} - - void AttackStart(Unit* /*who*/) {} - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (Stop) - return; - - if (Grow_Timer <= diff) - { - DoCast(me, SPELL_GROW); - Grow_Timer = 3000; - } else Grow_Timer -= diff; - - if (Shrink_Timer <= diff) - { - me->RemoveAurasDueToSpell(SPELL_GROW); - Stop = true; - } else Shrink_Timer -= diff; - } -}; -CreatureAI* GetAI_mob_underbog_mushroom(Creature* pCreature) -{ - return new mob_underbog_mushroomAI (pCreature); -} - -void AddSC_boss_hungarfen() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_hungarfen"; - newscript->GetAI = &GetAI_boss_hungarfen; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_underbog_mushroom"; - newscript->GetAI = &GetAI_mob_underbog_mushroom; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp b/src/server/scripts/outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp deleted file mode 100644 index 3a78660389b..00000000000 --- a/src/server/scripts/outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_the_black_stalker -SD%Complete: 95 -SDComment: Timers may be incorrect -SDCategory: Coilfang Resevoir, Underbog -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_LEVITATE 31704 -#define SPELL_SUSPENSION 31719 -#define SPELL_LEVITATION_PULSE 31701 -#define SPELL_MAGNETIC_PULL 31705 -#define SPELL_CHAIN_LIGHTNING 31717 -#define SPELL_STATIC_CHARGE 31715 -#define SPELL_SUMMON_SPORE_STRIDER 38755 - -#define ENTRY_SPORE_STRIDER 22299 - -struct boss_the_black_stalkerAI : public ScriptedAI -{ - boss_the_black_stalkerAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 SporeStriders_Timer; - uint32 Levitate_Timer; - uint32 ChainLightning_Timer; - uint32 StaticCharge_Timer; - uint64 LevitatedTarget; - uint32 LevitatedTarget_Timer; - bool InAir; - uint32 check_Timer; - std::list Striders; - - void Reset() - { - Levitate_Timer = 12000; - ChainLightning_Timer = 6000; - StaticCharge_Timer = 10000; - SporeStriders_Timer = 10000+rand()%5000; - check_Timer = 5000; - LevitatedTarget = 0; - LevitatedTarget_Timer = 0; - Striders.clear(); - } - - void EnterCombat(Unit * /*who*/) {} - - void JustSummoned(Creature *summon) - { - if (summon && summon->GetEntry() == ENTRY_SPORE_STRIDER) - { - Striders.push_back(summon->GetGUID()); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - summon->AI()->AttackStart(pTarget); - else - if (me->getVictim()) - summon->AI()->AttackStart(me->getVictim()); - } - } - - void JustDied(Unit * /*who*/) - { - for (std::list::const_iterator i = Striders.begin(); i != Striders.end(); ++i) - if (Creature *strider = Unit::GetCreature(*me, *i)) - strider->DisappearAndDie(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Evade if too far - if (check_Timer <= diff) - { - float x,y,z,o; - me->GetHomePosition(x,y,z,o); - if (!me->IsWithinDist3d(x,y,z, 60)) - { - EnterEvadeMode(); - return; - } - check_Timer = 1000; - } else check_Timer -= diff; - - // Spore Striders - if (IsHeroic() && SporeStriders_Timer <= diff) - { - DoCast(me, SPELL_SUMMON_SPORE_STRIDER); - SporeStriders_Timer = 10000+rand()%5000; - } else SporeStriders_Timer -= diff; - - // Levitate - if (LevitatedTarget) - { - if (LevitatedTarget_Timer <= diff) - { - if (Unit *pTarget = Unit::GetUnit(*me, LevitatedTarget)) - { - if (!pTarget->HasAura(SPELL_LEVITATE)) - { - LevitatedTarget = 0; - return; - } - if (InAir) - { - pTarget->AddAura(SPELL_SUSPENSION, pTarget); - LevitatedTarget = 0; - } - else - { - pTarget->CastSpell(pTarget, SPELL_MAGNETIC_PULL, true); - InAir = true; - LevitatedTarget_Timer = 1500; - } - } - else - LevitatedTarget = 0; - } else LevitatedTarget_Timer -= diff; - } - if (Levitate_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - DoCast(pTarget, SPELL_LEVITATE); - LevitatedTarget = pTarget->GetGUID(); - LevitatedTarget_Timer = 2000; - InAir = false; - } - Levitate_Timer = 12000+rand()%3000; - } else Levitate_Timer -= diff; - - // Chain Lightning - if (ChainLightning_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - ChainLightning_Timer = 7000; - } else ChainLightning_Timer -= diff; - - // Static Charge - if (StaticCharge_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true)) - DoCast(pTarget, SPELL_STATIC_CHARGE); - StaticCharge_Timer = 10000; - } else StaticCharge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_the_black_stalker(Creature* pCreature) -{ - return new boss_the_black_stalkerAI (pCreature); -} - -void AddSC_boss_the_black_stalker() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_the_black_stalker"; - newscript->GetAI = &GetAI_boss_the_black_stalker; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/gruuls_lair/boss_gruul.cpp b/src/server/scripts/outland/gruuls_lair/boss_gruul.cpp deleted file mode 100644 index a07ac910598..00000000000 --- a/src/server/scripts/outland/gruuls_lair/boss_gruul.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gruul -SD%Complete: 60 -SDComment: Ground Slam need further development (knock back effect and shatter effect must be added to the core) -SDCategory: Gruul's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "gruuls_lair.h" - -enum eEnums -{ - SAY_AGGRO = -1565010, - SAY_SLAM1 = -1565011, - SAY_SLAM2 = -1565012, - SAY_SHATTER1 = -1565013, - SAY_SHATTER2 = -1565014, - SAY_SLAY1 = -1565015, - SAY_SLAY2 = -1565016, - SAY_SLAY3 = -1565017, - SAY_DEATH = -1565018, - - EMOTE_GROW = -1565019, - - SPELL_GROWTH = 36300, - SPELL_CAVE_IN = 36240, - SPELL_GROUND_SLAM = 33525, //AoE Ground Slam applying Ground Slam to everyone with a script effect (most likely the knock back, we can code it to a set knockback) - SPELL_REVERBERATION = 36297, - SPELL_SHATTER = 33654, - - SPELL_SHATTER_EFFECT = 33671, - SPELL_HURTFUL_STRIKE = 33813, - SPELL_STONED = 33652, //Spell is self cast by target - - SPELL_MAGNETIC_PULL = 28337, - SPELL_KNOCK_BACK = 24199, //Knockback spell until correct implementation is made -}; - -struct boss_gruulAI : public ScriptedAI -{ - boss_gruulAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 m_uiGrowth_Timer; - uint32 m_uiCaveIn_Timer; - uint32 m_uiCaveIn_StaticTimer; - uint32 m_uiGroundSlamTimer; - uint32 m_uiHurtfulStrike_Timer; - uint32 m_uiReverberation_Timer; - - bool m_bPerformingGroundSlam; - - void Reset() - { - m_uiGrowth_Timer= 30000; - m_uiCaveIn_Timer= 27000; - m_uiCaveIn_StaticTimer = 30000; - m_uiGroundSlamTimer= 35000; - m_bPerformingGroundSlam= false; - m_uiHurtfulStrike_Timer= 8000; - m_uiReverberation_Timer= 60000+45000; - - if (pInstance) - pInstance->SetData(DATA_GRUULEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_GRUULEVENT, IN_PROGRESS); - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_GRUULEVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GRUULDOOR), true); // Open the encounter door - } - } - - void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) - { - //This to emulate effect1 (77) of SPELL_GROUND_SLAM, knock back to any direction - //It's initially wrong, since this will cause fall damage, which is by comments, not intended. - if (pSpell->Id == SPELL_GROUND_SLAM) - { - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - switch (urand(0,1)) - { - case 0: pTarget->CastSpell(pTarget, SPELL_MAGNETIC_PULL, true, NULL, NULL, me->GetGUID()); break; - case 1: pTarget->CastSpell(pTarget, SPELL_KNOCK_BACK, true, NULL, NULL, me->GetGUID()); break; - } - } - } - - //this part should be in the core - if (pSpell->Id == SPELL_SHATTER) - { - //this spell must have custom handling in the core, dealing damage based on distance - pTarget->CastSpell(pTarget, SPELL_SHATTER_EFFECT, true); - - if (pTarget->HasAura(SPELL_STONED)) - pTarget->RemoveAurasDueToSpell(SPELL_STONED); - - //clear this, if we are still performing - if (m_bPerformingGroundSlam) - { - m_bPerformingGroundSlam = false; - - //and correct movement, if not already - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) - { - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // Growth - // Gruul can cast this spell up to 30 times - if (m_uiGrowth_Timer <= uiDiff) - { - DoScriptText(EMOTE_GROW, me); - DoCast(me, SPELL_GROWTH); - m_uiGrowth_Timer = 30000; - } - else - m_uiGrowth_Timer -= uiDiff; - - if (m_bPerformingGroundSlam) - { - if (m_uiGroundSlamTimer <= uiDiff) - { - m_uiGroundSlamTimer =120000; - m_uiHurtfulStrike_Timer= 8000; - - if (m_uiReverberation_Timer < 10000) //Give a little time to the players to undo the damage from shatter - m_uiReverberation_Timer += 10000; - - DoCast(me, SPELL_SHATTER); - } - else - m_uiGroundSlamTimer -= uiDiff; - } - else - { - // Hurtful Strike - if (m_uiHurtfulStrike_Timer <= uiDiff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); - - if (pTarget && me->IsWithinMeleeRange(me->getVictim())) - DoCast(pTarget, SPELL_HURTFUL_STRIKE); - else - DoCast(me->getVictim(), SPELL_HURTFUL_STRIKE); - - m_uiHurtfulStrike_Timer= 8000; - } - else - m_uiHurtfulStrike_Timer -= uiDiff; - - // Reverberation - if (m_uiReverberation_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_REVERBERATION, true); - m_uiReverberation_Timer = 15000 + rand()%10000; - } - else - m_uiReverberation_Timer -= uiDiff; - - // Cave In - if (m_uiCaveIn_Timer <= uiDiff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CAVE_IN); - - if (m_uiCaveIn_StaticTimer >= 4000) - m_uiCaveIn_StaticTimer -= 2000; - - m_uiCaveIn_Timer = m_uiCaveIn_StaticTimer; - } - else - m_uiCaveIn_Timer -= uiDiff; - - // Ground Slam, Gronn Lord's Grasp, Stoned, Shatter - if (m_uiGroundSlamTimer <= uiDiff) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - - m_bPerformingGroundSlam= true; - m_uiGroundSlamTimer = 10000; - - DoCast(me, SPELL_GROUND_SLAM); - } - else - m_uiGroundSlamTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - } -}; - -CreatureAI* GetAI_boss_gruul(Creature* pCreature) -{ - return new boss_gruulAI (pCreature); -} - -void AddSC_boss_gruul() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gruul"; - newscript->GetAI = &GetAI_boss_gruul; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/gruuls_lair/boss_high_king_maulgar.cpp b/src/server/scripts/outland/gruuls_lair/boss_high_king_maulgar.cpp deleted file mode 100644 index 482af86225c..00000000000 --- a/src/server/scripts/outland/gruuls_lair/boss_high_king_maulgar.cpp +++ /dev/null @@ -1,783 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_High_King_Maulgar -SD%Complete: 90 -SDComment: Correct timers, after whirlwind melee attack bug, prayer of healing -SDCategory: Gruul's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "gruuls_lair.h" - -#define SAY_AGGRO -1565000 -#define SAY_ENRAGE -1565001 -#define SAY_OGRE_DEATH1 -1565002 -#define SAY_OGRE_DEATH2 -1565003 -#define SAY_OGRE_DEATH3 -1565004 -#define SAY_OGRE_DEATH4 -1565005 -#define SAY_SLAY1 -1565006 -#define SAY_SLAY2 -1565007 -#define SAY_SLAY3 -1565008 -#define SAY_DEATH -1565009 - -// High King Maulgar -#define SPELL_ARCING_SMASH 39144 -#define SPELL_MIGHTY_BLOW 33230 -#define SPELL_WHIRLWIND 33238 -#define SPELL_BERSERKER_C 26561 -#define SPELL_ROAR 16508 -#define SPELL_FLURRY 33232 -#define SPELL_DUAL_WIELD 29651 //used in phase - -// Olm the Summoner -#define SPELL_DARK_DECAY 33129 -#define SPELL_DEATH_COIL 33130 -#define SPELL_SUMMON_WFH 33131 - -//Kiggler the Craed -#define SPELL_GREATER_POLYMORPH 33173 -#define SPELL_LIGHTNING_BOLT 36152 -#define SPELL_ARCANE_SHOCK 33175 -#define SPELL_ARCANE_EXPLOSION 33237 - -//Blindeye the Seer -#define SPELL_GREATER_PW_SHIELD 33147 -#define SPELL_HEAL 33144 -#define SPELL_PRAYER_OH 33152 - -//Krosh Firehand -#define SPELL_GREATER_FIREBALL 33051 -#define SPELL_SPELLSHIELD 33054 -#define SPELL_BLAST_WAVE 33061 - -bool CheckAllBossDied(ScriptedInstance* pInstance, Creature* me) -{ - if (!pInstance || !me) - return false; - - uint64 MaulgarGUID = 0; - uint64 KigglerGUID = 0; - uint64 BlindeyeGUID = 0; - uint64 OlmGUID = 0; - uint64 KroshGUID = 0; - - Creature* Maulgar = NULL; - Creature* Kiggler = NULL; - Creature* Blindeye = NULL; - Creature* Olm = NULL; - Creature* Krosh = NULL; - - MaulgarGUID = pInstance->GetData64(DATA_MAULGAR); - KigglerGUID = pInstance->GetData64(DATA_KIGGLERTHECRAZED); - BlindeyeGUID = pInstance->GetData64(DATA_BLINDEYETHESEER); - OlmGUID = pInstance->GetData64(DATA_OLMTHESUMMONER); - KroshGUID = pInstance->GetData64(DATA_KROSHFIREHAND); - - Maulgar = (Unit::GetCreature((*me), MaulgarGUID)); - Kiggler = (Unit::GetCreature((*me), KigglerGUID)); - Blindeye = (Unit::GetCreature((*me), BlindeyeGUID)); - Olm = (Unit::GetCreature((*me), OlmGUID)); - Krosh = (Unit::GetCreature((*me), KroshGUID)); - - if (!Maulgar || !Kiggler || !Blindeye || !Olm || !Krosh) - return false; - - if (!Maulgar->isAlive() && !Kiggler->isAlive() && !Blindeye->isAlive() && !Olm->isAlive() && !Krosh->isAlive()) - return true; - - return false; -} - -//High King Maulgar AI -struct boss_high_king_maulgarAI : public ScriptedAI -{ - boss_high_king_maulgarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; - } - - ScriptedInstance* pInstance; - - uint32 ArcingSmash_Timer; - uint32 MightyBlow_Timer; - uint32 Whirlwind_Timer; - uint32 Charging_Timer; - uint32 Roar_Timer; - - bool Phase2; - - uint64 Council[4]; - - void Reset() - { - ArcingSmash_Timer = 10000; - MightyBlow_Timer = 40000; - Whirlwind_Timer = 30000; - Charging_Timer = 0; - Roar_Timer = 0; - - DoCast(me, SPELL_DUAL_WIELD, false); - - Phase2 = false; - - Creature *pCreature = NULL; - for (uint8 i = 0; i < 4; ++i) - { - if (Council[i]) - { - pCreature = (Unit::GetCreature((*me), Council[i])); - if (pCreature && !pCreature->isAlive()) - { - pCreature->Respawn(); - pCreature->AI()->EnterEvadeMode(); - } - } - } - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - - void AddDeath() - { - DoScriptText(RAND(SAY_OGRE_DEATH1,SAY_OGRE_DEATH2,SAY_OGRE_DEATH3,SAY_OGRE_DEATH4), me); - } - - void EnterCombat(Unit *who) - { - StartEvent(who); - } - - void GetCouncil() - { - if (pInstance) - { - //get council member's guid to respawn them if needed - Council[0] = pInstance->GetData64(DATA_KIGGLERTHECRAZED); - Council[1] = pInstance->GetData64(DATA_BLINDEYETHESEER); - Council[2] = pInstance->GetData64(DATA_OLMTHESUMMONER); - Council[3] = pInstance->GetData64(DATA_KROSHFIREHAND); - } - } - - void StartEvent(Unit *who) - { - if (!pInstance) - return; - - GetCouncil(); - - DoScriptText(SAY_AGGRO, me); - - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - GetCouncil(); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //ArcingSmash_Timer - if (ArcingSmash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCING_SMASH); - ArcingSmash_Timer = 10000; - } else ArcingSmash_Timer -= diff; - - //Whirlwind_Timer - if (Whirlwind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - Whirlwind_Timer = 55000; - } else Whirlwind_Timer -= diff; - - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTY_BLOW); - MightyBlow_Timer = 30000+rand()%10000; - } else MightyBlow_Timer -= diff; - - //Entering Phase 2 - if (!Phase2 && (me->GetHealth()*100 / me->GetMaxHealth()) < 50) - { - Phase2 = true; - DoScriptText(SAY_ENRAGE, me); - - DoCast(me, SPELL_DUAL_WIELD, true); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - } - - if (Phase2) - { - //Charging_Timer - if (Charging_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - AttackStart(pTarget); - DoCast(pTarget, SPELL_BERSERKER_C); - } - Charging_Timer = 20000; - } else Charging_Timer -= diff; - - //Intimidating Roar - if (Roar_Timer <= diff) - { - DoCast(me, SPELL_ROAR); - Roar_Timer = 40000+(rand()%10000); - } else Roar_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -//Olm The Summoner AI -struct boss_olm_the_summonerAI : public ScriptedAI -{ - boss_olm_the_summonerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 DarkDecay_Timer; - uint32 Summon_Timer; - uint32 DeathCoil_Timer; - - ScriptedInstance* pInstance; - - void Reset() - { - DarkDecay_Timer = 10000; - Summon_Timer = 15000; - DeathCoil_Timer = 20000; - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(pWho, 30.0f); - } - } - - void EnterCombat(Unit *who) - { - if (pInstance) - { - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - Creature *Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //DarkDecay_Timer - if (DarkDecay_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DARK_DECAY); - DarkDecay_Timer = 20000; - } else DarkDecay_Timer -= diff; - - //Summon_Timer - if (Summon_Timer <= diff) - { - DoCast(me, SPELL_SUMMON_WFH); - Summon_Timer = 30000; - } else Summon_Timer -= diff; - - //DeathCoil Timer /need correct timer - if (DeathCoil_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_DEATH_COIL); - DeathCoil_Timer = 20000; - } else DeathCoil_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Kiggler The Crazed AI -struct boss_kiggler_the_crazedAI : public ScriptedAI -{ - boss_kiggler_the_crazedAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 GreaterPolymorph_Timer; - uint32 LightningBolt_Timer; - uint32 ArcaneShock_Timer; - uint32 ArcaneExplosion_Timer; - - ScriptedInstance* pInstance; - - void Reset() - { - GreaterPolymorph_Timer = 5000; - LightningBolt_Timer = 10000; - ArcaneShock_Timer = 20000; - ArcaneExplosion_Timer = 30000; - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - if (pInstance) - { - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - Creature *Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //GreaterPolymorph_Timer - if (GreaterPolymorph_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_GREATER_POLYMORPH); - - GreaterPolymorph_Timer = 15000 + rand()%5000; - } else GreaterPolymorph_Timer -= diff; - - //LightningBolt_Timer - if (LightningBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); - LightningBolt_Timer = 15000; - } else LightningBolt_Timer -= diff; - - //ArcaneShock_Timer - if (ArcaneShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_SHOCK); - ArcaneShock_Timer = 20000; - } else ArcaneShock_Timer -= diff; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); - ArcaneExplosion_Timer = 30000; - } else ArcaneExplosion_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Blindeye The Seer AI -struct boss_blindeye_the_seerAI : public ScriptedAI -{ - boss_blindeye_the_seerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 GreaterPowerWordShield_Timer; - uint32 Heal_Timer; - uint32 PrayerofHealing_Timer; - - ScriptedInstance* pInstance; - - void Reset() - { - GreaterPowerWordShield_Timer = 5000; - Heal_Timer = 25000 + rand()%15000; - PrayerofHealing_Timer = 45000 + rand()%10000; - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - Creature *Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //GreaterPowerWordShield_Timer - if (GreaterPowerWordShield_Timer <= diff) - { - DoCast(me, SPELL_GREATER_PW_SHIELD); - GreaterPowerWordShield_Timer = 40000; - } else GreaterPowerWordShield_Timer -= diff; - - //Heal_Timer - if (Heal_Timer <= diff) - { - DoCast(me, SPELL_HEAL); - Heal_Timer = 15000 + rand()%25000; - } else Heal_Timer -= diff; - - //PrayerofHealing_Timer - if (PrayerofHealing_Timer <= diff) - { - DoCast(me, SPELL_PRAYER_OH); - PrayerofHealing_Timer = 35000 + rand()%15000; - } else PrayerofHealing_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Krosh Firehand AI -struct boss_krosh_firehandAI : public ScriptedAI -{ - boss_krosh_firehandAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 GreaterFireball_Timer; - uint32 SpellShield_Timer; - uint32 BlastWave_Timer; - - ScriptedInstance* pInstance; - - void Reset() - { - GreaterFireball_Timer = 1000; - SpellShield_Timer = 5000; - BlastWave_Timer = 20000; - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - Creature *Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //GreaterFireball_Timer - if (GreaterFireball_Timer < diff || me->IsWithinDist(me->getVictim(), 30)) - { - DoCast(me->getVictim(), SPELL_GREATER_FIREBALL); - GreaterFireball_Timer = 2000; - } else GreaterFireball_Timer -= diff; - - //SpellShield_Timer - if (SpellShield_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me->getVictim(), SPELL_SPELLSHIELD); - SpellShield_Timer = 30000; - } else SpellShield_Timer -= diff; - - //BlastWave_Timer - if (BlastWave_Timer <= diff) - { - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //15 yard radius minimum - if (pTarget && pTarget->IsWithinDist(me, 15,false)) - target_list.push_back(pTarget); - pTarget = NULL; - } - if (target_list.size()) - pTarget = *(target_list.begin()+rand()%target_list.size()); - - me->InterruptNonMeleeSpells(false); - DoCast(pTarget, SPELL_BLAST_WAVE); - BlastWave_Timer = 60000; - } else BlastWave_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_high_king_maulgar(Creature* pCreature) -{ - return new boss_high_king_maulgarAI (pCreature); -} - -CreatureAI* GetAI_boss_olm_the_summoner(Creature* pCreature) -{ - return new boss_olm_the_summonerAI (pCreature); -} - -CreatureAI *GetAI_boss_kiggler_the_crazed(Creature* pCreature) -{ - return new boss_kiggler_the_crazedAI (pCreature); -} - -CreatureAI *GetAI_boss_blindeye_the_seer(Creature* pCreature) -{ - return new boss_blindeye_the_seerAI (pCreature); -} - -CreatureAI *GetAI_boss_krosh_firehand(Creature* pCreature) -{ - return new boss_krosh_firehandAI (pCreature); -} - -void AddSC_boss_high_king_maulgar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_high_king_maulgar"; - newscript->GetAI = &GetAI_boss_high_king_maulgar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_kiggler_the_crazed"; - newscript->GetAI = &GetAI_boss_kiggler_the_crazed; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_blindeye_the_seer"; - newscript->GetAI = &GetAI_boss_blindeye_the_seer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_olm_the_summoner"; - newscript->GetAI = &GetAI_boss_olm_the_summoner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_krosh_firehand"; - newscript->GetAI = &GetAI_boss_krosh_firehand; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/gruuls_lair/gruuls_lair.h b/src/server/scripts/outland/gruuls_lair/gruuls_lair.h deleted file mode 100644 index 7003dcb1e26..00000000000 --- a/src/server/scripts/outland/gruuls_lair/gruuls_lair.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_GRUULS_LAIR_H -#define DEF_GRUULS_LAIR_H - -#define DATA_BLINDEYETHESEER 1 -#define DATA_GRUULEVENT 2 -#define DATA_KIGGLERTHECRAZED 3 -#define DATA_KROSHFIREHAND 4 -#define DATA_MAULGAREVENT 5 -#define DATA_MAULGAREVENT_TANK 6 -#define DATA_OLMTHESUMMONER 7 -#define DATA_MAULGARDOOR 8 -#define DATA_GRUULDOOR 9 -#define DATA_MAULGAR 10 - -#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Gruul's Lair instance (map 565). Encounters will be buggy." -#endif - diff --git a/src/server/scripts/outland/gruuls_lair/instance_gruuls_lair.cpp b/src/server/scripts/outland/gruuls_lair/instance_gruuls_lair.cpp deleted file mode 100644 index bb790a5d4ea..00000000000 --- a/src/server/scripts/outland/gruuls_lair/instance_gruuls_lair.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Gruuls_Lair -SD%Complete: 100 -SDComment: -SDCategory: Gruul's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "gruuls_lair.h" - -#define MAX_ENCOUNTER 2 - -/* Gruuls Lair encounters: -1 - High King Maulgar event -2 - Gruul event -*/ - -struct instance_gruuls_lair : public ScriptedInstance -{ - instance_gruuls_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 MaulgarEvent_Tank; - uint64 KigglerTheCrazed; - uint64 BlindeyeTheSeer; - uint64 OlmTheSummoner; - uint64 KroshFirehand; - uint64 Maulgar; - - uint64 MaulgarDoor; - uint64 GruulDoor; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - MaulgarEvent_Tank = 0; - KigglerTheCrazed = 0; - BlindeyeTheSeer = 0; - OlmTheSummoner = 0; - KroshFirehand = 0; - Maulgar = 0; - - MaulgarDoor = 0; - GruulDoor = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 18835: KigglerTheCrazed = pCreature->GetGUID(); break; - case 18836: BlindeyeTheSeer = pCreature->GetGUID(); break; - case 18834: OlmTheSummoner = pCreature->GetGUID(); break; - case 18832: KroshFirehand = pCreature->GetGUID(); break; - case 18831: Maulgar = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 184468: - MaulgarDoor = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) HandleGameObject(NULL, true, pGo); - break; - case 184662: GruulDoor = pGo->GetGUID(); break; - } - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_MAULGAREVENT_TANK) - MaulgarEvent_Tank = data; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_MAULGAREVENT_TANK: return MaulgarEvent_Tank; - case DATA_KIGGLERTHECRAZED: return KigglerTheCrazed; - case DATA_BLINDEYETHESEER: return BlindeyeTheSeer; - case DATA_OLMTHESUMMONER: return OlmTheSummoner; - case DATA_KROSHFIREHAND: return KroshFirehand; - case DATA_MAULGARDOOR: return MaulgarDoor; - case DATA_GRUULDOOR: return GruulDoor; - case DATA_MAULGAR: return Maulgar; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MAULGAREVENT: - if (data == DONE) HandleGameObject(MaulgarDoor, true); - m_auiEncounter[0] = data; break; - case DATA_GRUULEVENT: - if (data == IN_PROGRESS) HandleGameObject(GruulDoor, false); - else HandleGameObject(GruulDoor, true); - m_auiEncounter[1] = data; break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_MAULGAREVENT: return m_auiEncounter[0]; - case DATA_GRUULEVENT: return m_auiEncounter[1]; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_gruuls_lair(Map* pMap) -{ - return new instance_gruuls_lair(pMap); -} - -void AddSC_instance_gruuls_lair() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_gruuls_lair"; - newscript->GetInstanceData = &GetInstanceData_instance_gruuls_lair; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/blood_furnace/blood_furnace.h b/src/server/scripts/outland/hellfire_citadel/blood_furnace/blood_furnace.h deleted file mode 100644 index b845c66823f..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/blood_furnace/blood_furnace.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BLOOD_FURNACE_H -#define DEF_BLOOD_FURNACE_H - -#define DATA_THE_MAKER 1 -#define DATA_BROGGOK 2 -#define DATA_KELIDAN_THE_MAKER 3 -#define TYPE_THE_MAKER_EVENT 4 -#define TYPE_BROGGOK_EVENT 5 -#define TYPE_KELIDAN_THE_BREAKER_EVENT 6 -#define DATA_DOOR1 7 -#define DATA_DOOR2 8 -#define DATA_DOOR3 9 -#define DATA_DOOR4 10 -#define DATA_DOOR5 11 -#define DATA_DOOR6 12 -#define DATA_PRISON_CELL1 13 -#define DATA_PRISON_CELL2 14 -#define DATA_PRISON_CELL3 15 -#define DATA_PRISON_CELL4 16 -#define DATA_PRISON_CELL5 17 -#define DATA_PRISON_CELL6 18 -#define DATA_PRISON_CELL7 19 -#define DATA_PRISON_CELL8 20 -#endif - diff --git a/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_broggok.cpp b/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_broggok.cpp deleted file mode 100644 index d5fb9bdba49..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_broggok.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Broggok -SD%Complete: 70 -SDComment: pre-event not made -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eEnums -{ - SAY_AGGRO = -1542008, - - SPELL_SLIME_SPRAY = 30913, - SPELL_POISON_CLOUD = 30916, - SPELL_POISON_BOLT = 30917, - - SPELL_POISON = 30914 -}; - -struct boss_broggokAI : public ScriptedAI -{ - boss_broggokAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AcidSpray_Timer; - uint32 PoisonSpawn_Timer; - uint32 PoisonBolt_Timer; - - void Reset() - { - AcidSpray_Timer = 10000; - PoisonSpawn_Timer = 5000; - PoisonBolt_Timer = 7000; - if (pInstance) - { - pInstance->SetData(TYPE_BROGGOK_EVENT, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - pInstance->SetData(TYPE_BROGGOK_EVENT, IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), false); - } - } - - void JustSummoned(Creature *summoned) - { - summoned->setFaction(16); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->CastSpell(summoned,SPELL_POISON,false,0,0,me->GetGUID()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AcidSpray_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLIME_SPRAY); - AcidSpray_Timer = 4000+rand()%8000; - } else AcidSpray_Timer -=diff; - - if (PoisonBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_BOLT); - PoisonBolt_Timer = 4000+rand()%8000; - } else PoisonBolt_Timer -=diff; - - if (PoisonSpawn_Timer <= diff) - { - DoCast(me, SPELL_POISON_CLOUD); - PoisonSpawn_Timer = 20000; - } else PoisonSpawn_Timer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*who*/) - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR5), true); - pInstance->SetData(TYPE_BROGGOK_EVENT, DONE); - } - } - -}; - -CreatureAI* GetAI_boss_broggok(Creature* pCreature) -{ - return new boss_broggokAI (pCreature); -} - -void AddSC_boss_broggok() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_broggok"; - newscript->GetAI = &GetAI_boss_broggok; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp deleted file mode 100644 index a44ad9cc3c8..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kelidan_The_Breaker -SD%Complete: 100 -SDComment: -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -/* ContentData -boss_kelidan_the_breaker -mob_shadowmoon_channeler -EndContentData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eKelidan -{ - SAY_WAKE = -1542000, - SAY_ADD_AGGRO_1 = -1542001, - SAY_ADD_AGGRO_2 = -1542002, - SAY_ADD_AGGRO_3 = -1542003, - SAY_KILL_1 = -1542004, - SAY_KILL_2 = -1542005, - SAY_NOVA = -1542006, - SAY_DIE = -1542007, - - SPELL_CORRUPTION = 30938, - SPELL_EVOCATION = 30935, - - SPELL_FIRE_NOVA = 33132, - H_SPELL_FIRE_NOVA = 37371, - - SPELL_SHADOW_BOLT_VOLLEY = 28599, - H_SPELL_SHADOW_BOLT_VOLLEY = 40070, - - SPELL_BURNING_NOVA = 30940, - SPELL_VORTEX = 37370, - - ENTRY_KELIDAN = 17377, - ENTRY_CHANNELER = 17653 -}; - -const float ShadowmoonChannelers[5][4]= -{ - {302,-87,-24.4,0.157}, - {321,-63.5,-24.6,4.887}, - {346,-74.5,-24.6,3.595}, - {344,-103.5,-24.5,2.356}, - {316,-109,-24.6,1.257} -}; - -struct boss_kelidan_the_breakerAI : public ScriptedAI -{ - boss_kelidan_the_breakerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i=0; i<5; ++i) - Channelers[i] = 0; - } - - ScriptedInstance* pInstance; - - uint32 ShadowVolley_Timer; - uint32 BurningNova_Timer; - uint32 Firenova_Timer; - uint32 Corruption_Timer; - uint32 check_Timer; - bool Firenova; - bool addYell; - uint64 Channelers[5]; - - void Reset() - { - ShadowVolley_Timer = 1000; - BurningNova_Timer = 15000; - Corruption_Timer = 5000; - check_Timer = 0; - Firenova = false; - addYell = false; - SummonChannelers(); - if (pInstance) - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_WAKE, me); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - DoStartMovement(who); - if (pInstance) - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void ChannelerEngaged(Unit* who) - { - if (who && !addYell) - { - addYell = true; - DoScriptText(RAND(SAY_ADD_AGGRO_1,SAY_ADD_AGGRO_2,SAY_ADD_AGGRO_3), me); - } - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (who && channeler && !channeler->isInCombat()) - channeler->AI()->AttackStart(who); - } - } - - void ChannelerDied(Unit* killer) - { - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (channeler && channeler->isAlive()) - return; - } - - if (killer) - me->AI()->AttackStart(killer); - } - - uint64 GetChanneled(Creature *channeler1) - { - SummonChannelers(); - if (!channeler1) return NULL; - uint8 i; - for (i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (channeler && channeler->GetGUID() == channeler1->GetGUID()) - break; - } - return Channelers[(i+2)%5]; - } - - void SummonChannelers() - { - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (!channeler || channeler->isDead()) - channeler = me->SummonCreature(ENTRY_CHANNELER,ShadowmoonChannelers[i][0],ShadowmoonChannelers[i][1],ShadowmoonChannelers[i][2],ShadowmoonChannelers[i][3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,300000); - if (channeler) - Channelers[i] = channeler->GetGUID(); - else - Channelers[i] = 0; - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR1), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR6), true); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (check_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - DoCast(me, SPELL_EVOCATION); - check_Timer = 5000; - } else check_Timer -= diff; - return; - } - - if (Firenova) - { - if (Firenova_Timer <= diff) - { - DoCast(me, SPELL_FIRE_NOVA, true); - Firenova = false; - ShadowVolley_Timer = 2000; - } else Firenova_Timer -=diff; - - return; - } - - if (ShadowVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); - ShadowVolley_Timer = 5000+rand()%8000; - } else ShadowVolley_Timer -=diff; - - if (Corruption_Timer <= diff) - { - DoCast(me, SPELL_CORRUPTION); - Corruption_Timer = 30000+rand()%20000; - } else Corruption_Timer -=diff; - - if (BurningNova_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(SAY_NOVA, me); - - if (SpellEntry *nova = GET_SPELL(SPELL_BURNING_NOVA)) - { - if (Aura * aura = Aura::TryCreate(nova, me, me)) - aura->ApplyForTargets(); - } - - if (IsHeroic()) - DoTeleportAll(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - - BurningNova_Timer = 20000+rand()%8000; - Firenova_Timer= 5000; - Firenova = true; - } else BurningNova_Timer -=diff; - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_boss_kelidan_the_breaker(Creature* pCreature) -{ - return new boss_kelidan_the_breakerAI (pCreature); -} - -/*###### -## mob_shadowmoon_channeler -######*/ - -enum eShadowmoon -{ - SPELL_SHADOW_BOLT = 12739, - H_SPELL_SHADOW_BOLT = 15472, - - SPELL_MARK_OF_SHADOW = 30937, - SPELL_CHANNELING = 39123 -}; - -struct mob_shadowmoon_channelerAI : public ScriptedAI -{ - mob_shadowmoon_channelerAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 ShadowBolt_Timer; - uint32 MarkOfShadow_Timer; - uint32 check_Timer; - - void Reset() - { - ShadowBolt_Timer = 1000+rand()%1000; - MarkOfShadow_Timer = 5000+rand()%2000; - check_Timer = 0; - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - } - - void EnterCombat(Unit* who) - { - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerEngaged(who); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - DoStartMovement(who); - } - - void JustDied(Unit* Killer) - { - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerDied(Killer); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (check_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - { - uint64 channeler = CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->GetChanneled(me); - if (Unit *channeled = Unit::GetUnit(*me, channeler)) - DoCast(channeled, SPELL_CHANNELING); - } - check_Timer = 5000; - } else check_Timer -= diff; - return; - } - - if (MarkOfShadow_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_MARK_OF_SHADOW); - MarkOfShadow_Timer = 15000+rand()%5000; - } else MarkOfShadow_Timer -=diff; - - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - ShadowBolt_Timer = 5000+rand()%1000; - } else ShadowBolt_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_shadowmoon_channeler(Creature* pCreature) -{ - return new mob_shadowmoon_channelerAI (pCreature); -} - -void AddSC_boss_kelidan_the_breaker() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_kelidan_the_breaker"; - newscript->GetAI = &GetAI_boss_kelidan_the_breaker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadowmoon_channeler"; - newscript->GetAI = &GetAI_mob_shadowmoon_channeler; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp b/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp deleted file mode 100644 index 45219b6509b..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_The_Maker -SD%Complete: 80 -SDComment: Mind control no support -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eEnums -{ - SAY_AGGRO_1 = -1542009, - SAY_AGGRO_2 = -1542010, - SAY_AGGRO_3 = -1542011, - SAY_KILL_1 = -1542012, - SAY_KILL_2 = -1542013, - SAY_DIE = -1542014, - - SPELL_ACID_SPRAY = 38153, // heroic 38973 ??? 38153 - SPELL_EXPLODING_BREAKER = 30925, - SPELL_KNOCKDOWN = 20276, - SPELL_DOMINATION = 25772 // ??? -}; - -struct boss_the_makerAI : public ScriptedAI -{ - boss_the_makerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AcidSpray_Timer; - uint32 ExplodingBreaker_Timer; - uint32 Domination_Timer; - uint32 Knockdown_Timer; - - void Reset() - { - AcidSpray_Timer = 15000; - ExplodingBreaker_Timer = 6000; - Domination_Timer = 120000; - Knockdown_Timer = 10000; - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), false); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR3), true); - - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AcidSpray_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ACID_SPRAY); - AcidSpray_Timer = 15000+rand()%8000; - } else AcidSpray_Timer -=diff; - - if (ExplodingBreaker_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_EXPLODING_BREAKER); - ExplodingBreaker_Timer = 4000+rand()%8000; - } else ExplodingBreaker_Timer -=diff; - - /* // Disabled until Core Support for mind control - if (domination_timer_timer <= diff) - { - Unit *pTarget; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - DoCast(pTarget, SPELL_DOMINATION); - - domination_timer = 120000; - } else domination_timer -=diff; - */ - - if (Knockdown_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - Knockdown_Timer = 4000+rand()%8000; - } else Knockdown_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_the_makerAI(Creature* pCreature) -{ - return new boss_the_makerAI (pCreature); -} - -void AddSC_boss_the_maker() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_maker"; - newscript->GetAI = &GetAI_boss_the_makerAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp b/src/server/scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp deleted file mode 100644 index 3a2eb8ba5ee..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Blood_Furnace -SD%Complete: 85 -SDComment: -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -#define ENTRY_SEWER1 181823 -#define ENTRY_SEWER2 181766 -#define MAX_ENCOUNTER 3 - -struct instance_blood_furnace : public ScriptedInstance -{ - instance_blood_furnace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 The_MakerGUID; - uint64 BroggokGUID; - uint64 Kelidan_The_BreakerGUID; - - uint64 Door1GUID; - uint64 Door2GUID; - uint64 Door3GUID; - uint64 Door4GUID; - uint64 Door5GUID; - uint64 Door6GUID; - - uint64 PrisonCell1GUID; - uint64 PrisonCell2GUID; - uint64 PrisonCell3GUID; - uint64 PrisonCell4GUID; - uint64 PrisonCell5GUID; - uint64 PrisonCell6GUID; - uint64 PrisonCell7GUID; - uint64 PrisonCell8GUID; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - The_MakerGUID = 0; - BroggokGUID = 0; - Kelidan_The_BreakerGUID = 0; - - Door1GUID = 0; - Door2GUID = 0; - Door3GUID = 0; - Door4GUID = 0; - Door5GUID = 0; - Door6GUID = 0; - - PrisonCell1GUID = 0; - PrisonCell2GUID = 0; - PrisonCell3GUID = 0; - PrisonCell4GUID = 0; - PrisonCell5GUID = 0; - PrisonCell6GUID = 0; - PrisonCell7GUID = 0; - PrisonCell8GUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - if (!add) - return; - - switch(pCreature->GetEntry()) - { - case 17381: The_MakerGUID = pCreature->GetGUID(); break; - case 17380: BroggokGUID = pCreature->GetGUID(); break; - case 17377: Kelidan_The_BreakerGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if (!add) - return; - - if (pGo->GetEntry() == 181766) //Final exit door - Door1GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181811) //The Maker Front door - Door2GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181812) //The Maker Rear door - Door3GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181822) //Broggok Front door - Door4GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181819) //Broggok Rear door - Door5GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181823) //Kelidan exit door - Door6GUID = pGo->GetGUID(); - - if (pGo->GetEntry() == 181813) //The Maker prison cell front right - PrisonCell1GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181814) //The Maker prison cell back right - PrisonCell2GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181816) //The Maker prison cell front left - PrisonCell3GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181815) //The Maker prison cell back left - PrisonCell4GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181821) //Broggok prison cell front right - PrisonCell5GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181818) //Broggok prison cell back right - PrisonCell6GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181820) //Broggok prison cell front left - PrisonCell7GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181817) //Broggok prison cell back left - PrisonCell8GUID = pGo->GetGUID(); - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THE_MAKER: return The_MakerGUID; - case DATA_BROGGOK: return BroggokGUID; - case DATA_KELIDAN_THE_MAKER: return Kelidan_The_BreakerGUID; - case DATA_DOOR1: return Door1GUID; - case DATA_DOOR2: return Door2GUID; - case DATA_DOOR3: return Door3GUID; - case DATA_DOOR4: return Door4GUID; - case DATA_DOOR5: return Door5GUID; - case DATA_DOOR6: return Door6GUID; - case DATA_PRISON_CELL1: return PrisonCell1GUID; - case DATA_PRISON_CELL2: return PrisonCell2GUID; - case DATA_PRISON_CELL3: return PrisonCell3GUID; - case DATA_PRISON_CELL4: return PrisonCell4GUID; - case DATA_PRISON_CELL5: return PrisonCell5GUID; - case DATA_PRISON_CELL6: return PrisonCell6GUID; - case DATA_PRISON_CELL7: return PrisonCell7GUID; - case DATA_PRISON_CELL8: return PrisonCell8GUID; - } - - return 0; - } - - void SetData(uint32 /*type*/, uint32 data) - { - switch(data) - { - case TYPE_THE_MAKER_EVENT: m_auiEncounter[0] = data; break; - case TYPE_BROGGOK_EVENT: m_auiEncounter[1] = data; break; - case TYPE_KELIDAN_THE_BREAKER_EVENT: m_auiEncounter[2] = data; break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 data) - { - switch(data) - { - case TYPE_THE_MAKER_EVENT: return m_auiEncounter[0]; - case TYPE_BROGGOK_EVENT: return m_auiEncounter[1]; - case TYPE_KELIDAN_THE_BREAKER_EVENT: return m_auiEncounter[2]; - } - - return 0; - } - - const char* Save() - { - return str_data.c_str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS || m_auiEncounter[i] == FAIL) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_blood_furnace(Map* pMap) -{ - return new instance_blood_furnace(pMap); -} - -void AddSC_instance_blood_furnace() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blood_furnace"; - newscript->GetInstanceData = &GetInstanceData_instance_blood_furnace; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp b/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp deleted file mode 100644 index d6c0b2fd401..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Omar_The_Unscarred -SD%Complete: 90 -SDComment: Temporary solution for orbital/shadow whip-ability. Needs more core support before making it more proper. -SDCategory: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1543009 -#define SAY_AGGRO_2 -1543010 -#define SAY_AGGRO_3 -1543011 -#define SAY_SUMMON -1543012 -#define SAY_CURSE -1543013 -#define SAY_KILL_1 -1543014 -#define SAY_DIE -1543015 -#define SAY_WIPE -1543016 - -#define SPELL_ORBITAL_STRIKE 30637 -#define SPELL_SHADOW_WHIP 30638 -#define SPELL_TREACHEROUS_AURA 30695 -#define H_SPELL_BANE_OF_TREACHERY 37566 -#define SPELL_DEMONIC_SHIELD 31901 -#define SPELL_SHADOW_BOLT 30686 -#define H_SPELL_SHADOW_BOLT 39297 -#define SPELL_SUMMON_FIENDISH_HOUND 30707 - -struct boss_omor_the_unscarredAI : public ScriptedAI -{ - boss_omor_the_unscarredAI(Creature *c) : ScriptedAI(c) - { - SetCombatMovement(false); - } - - uint32 OrbitalStrike_Timer; - uint32 ShadowWhip_Timer; - uint32 Aura_Timer; - uint32 DemonicShield_Timer; - uint32 Shadowbolt_Timer; - uint32 Summon_Timer; - uint32 SummonedCount; - uint64 PlayerGUID; - bool CanPullBack; - - void Reset() - { - DoScriptText(SAY_WIPE, me); - - OrbitalStrike_Timer = 25000; - ShadowWhip_Timer = 2000; - Aura_Timer = 10000; - DemonicShield_Timer = 1000; - Shadowbolt_Timer = 2000; - Summon_Timer = 10000; - SummonedCount = 0; - PlayerGUID = 0; - CanPullBack = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(SAY_KILL_1, me); - } - - void JustSummoned(Creature* summoned) - { - DoScriptText(SAY_SUMMON, me); - - if (Unit* random = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(random); - - ++SummonedCount; - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //only two may be wrong, perhaps increase timer and spawn periodically instead. - if (SummonedCount < 2) - { - if (Summon_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SUMMON_FIENDISH_HOUND); - Summon_Timer = 15000+rand()%15000; - } else Summon_Timer -= diff; - } - - if (CanPullBack) - { - if (ShadowWhip_Timer <= diff) - { - if (Player* temp = Unit::GetPlayer(PlayerGUID)) - { - //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) - if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) - { - me->InterruptNonMeleeSpells(false); - DoCast(temp, SPELL_SHADOW_WHIP); - } - } - PlayerGUID = 0; - ShadowWhip_Timer = 2000; - CanPullBack = false; - } else ShadowWhip_Timer -= diff; - } - else if (OrbitalStrike_Timer <= diff) - { - Unit* temp = NULL; - if (me->IsWithinMeleeRange(me->getVictim())) - temp = me->getVictim(); - else temp = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (temp && temp->GetTypeId() == TYPEID_PLAYER) - { - DoCast(temp, SPELL_ORBITAL_STRIKE); - OrbitalStrike_Timer = 14000+rand()%2000; - PlayerGUID = temp->GetGUID(); - - if (PlayerGUID) - CanPullBack = true; - } - } else OrbitalStrike_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) - { - if (DemonicShield_Timer <= diff) - { - DoCast(me, SPELL_DEMONIC_SHIELD); - DemonicShield_Timer = 15000; - } else DemonicShield_Timer -= diff; - } - - if (Aura_Timer <= diff) - { - DoScriptText(SAY_CURSE, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_TREACHEROUS_AURA); - Aura_Timer = 8000+rand()%8000; - } - } else Aura_Timer -= diff; - - if (Shadowbolt_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget) - pTarget = me->getVictim(); - - DoCast(pTarget, SPELL_SHADOW_BOLT); - Shadowbolt_Timer = 4000+rand()%2500; - } - } else Shadowbolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_omor_the_unscarredAI(Creature* pCreature) -{ - return new boss_omor_the_unscarredAI (pCreature); -} - -void AddSC_boss_omor_the_unscarred() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_omor_the_unscarred"; - newscript->GetAI = &GetAI_boss_omor_the_unscarredAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp b/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp deleted file mode 100644 index 181911f77a4..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -Name: Boss_Vazruden_the_Herald -%Complete: 90 -Comment: -Category: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FIREBALL DUNGEON_MODE(34653, 36920) -#define SPELL_CONE_OF_FIRE DUNGEON_MODE(30926, 36921) -#define SPELL_SUMMON_LIQUID_FIRE DUNGEON_MODE(23971, 30928) -#define SPELL_BELLOWING_ROAR 39427 -#define SPELL_REVENGE DUNGEON_MODE(19130, 40392) -#define SPELL_KIDNEY_SHOT 30621 -#define SPELL_FIRE_NOVA_VISUAL 19823 - -#define ENTRY_HELLFIRE_SENTRY 17517 -#define ENTRY_VAZRUDEN_HERALD 17307 -#define ENTRY_VAZRUDEN 17537 -#define ENTRY_NAZAN 17536 -#define ENTRY_LIQUID_FIRE 22515 -#define ENTRY_REINFORCED_FEL_IRON_CHEST DUNGEON_MODE(185168, 185169) - -#define SAY_INTRO -1543017 -#define SAY_WIPE -1543018 -#define SAY_AGGRO_1 -1543019 -#define SAY_AGGRO_2 -1543020 -#define SAY_AGGRO_3 -1543021 -#define SAY_KILL_1 -1543022 -#define SAY_KILL_2 -1543023 -#define SAY_DIE -1543024 -#define EMOTE -1543025 - -#define PATH_ENTRY 2081 - -const float VazrudenMiddle[3] = {-1406.5, 1746.5, 81.2}; -const float VazrudenRing[2][3] = -{ - {-1430, 1705, 112}, - {-1377, 1760, 112} -}; - -struct boss_nazanAI : public ScriptedAI -{ - boss_nazanAI(Creature *c) : ScriptedAI(c) - { - VazrudenGUID = 0; - flight = true; - } - - uint32 Fireball_Timer; - uint32 ConeOfFire_Timer; - uint32 BellowingRoar_Timer; - uint32 Fly_Timer; - uint32 Turn_Timer; - uint32 UnsummonCheck; - bool flight; - uint64 VazrudenGUID; - SpellEntry *liquid_fire; - - void Reset() - { - Fireball_Timer = 4000; - Fly_Timer = 45000; - Turn_Timer = 0; - UnsummonCheck = 5000; - } - - void EnterCombat(Unit* /*who*/) {} - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == ENTRY_LIQUID_FIRE) - { - summoned->SetLevel(me->getLevel()); - summoned->setFaction(me->getFaction()); - summoned->CastSpell(summoned,SPELL_SUMMON_LIQUID_FIRE,true); - summoned->CastSpell(summoned,SPELL_FIRE_NOVA_VISUAL,true); - } - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry* entry) - { - if (pTarget && entry->Id == uint32(SPELL_FIREBALL)) - me->SummonCreature(ENTRY_LIQUID_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),pTarget->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,30000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (UnsummonCheck < diff && me->isAlive()) - me->DisappearAndDie(); - else - UnsummonCheck -= diff; - return; - } - - if (Fireball_Timer <= diff) - { - if (Unit *victim = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(victim, SPELL_FIREBALL, true); - Fireball_Timer = urand(4000,7000); - } else Fireball_Timer -= diff; - - if (flight) // phase 1 - the flight - { - Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); - if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) - { - flight = false; - BellowingRoar_Timer = 6000; - ConeOfFire_Timer = 12000; - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->Clear(); - if (Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) - me->AI()->AttackStart(victim); - DoStartMovement(me->getVictim()); - DoScriptText(EMOTE, me); - return; - } else Fly_Timer -= diff; - - if (Turn_Timer <= diff) - { - uint32 waypoint = (Fly_Timer/10000)%2; - if (me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) - me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); - Turn_Timer = 10000; - } else Turn_Timer -= diff; - } - else // phase 2 - land fight - { - if (ConeOfFire_Timer <= diff) - { - DoCast(me, SPELL_CONE_OF_FIRE); - ConeOfFire_Timer = 12000; - Fireball_Timer = 4000; - } else ConeOfFire_Timer -= diff; - - if (IsHeroic()) - if (BellowingRoar_Timer <= diff) - { - DoCast(me, SPELL_BELLOWING_ROAR); - BellowingRoar_Timer = 45000; - } else BellowingRoar_Timer -= diff; - - DoMeleeAttackIfReady(); - } - } -}; - -struct boss_vazrudenAI : public ScriptedAI -{ - boss_vazrudenAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Revenge_Timer; - bool WipeSaid; - uint32 UnsummonCheck; - - void Reset() - { - Revenge_Timer = 4000; - UnsummonCheck = 2000; - WipeSaid = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void KilledUnit(Unit* who) - { - if (who && who->GetEntry() != ENTRY_VAZRUDEN) - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* who) - { - if (who && who != me) - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (UnsummonCheck < diff && me->isAlive()) - { - if (!WipeSaid) - { - DoScriptText(SAY_WIPE, me); - WipeSaid = true; - } - me->DisappearAndDie(); - } else UnsummonCheck -= diff; - return; - } - - if (Revenge_Timer <= diff) - { - if (Unit *victim = me->getVictim()) - DoCast(victim, SPELL_REVENGE); - Revenge_Timer = 5000; - } else Revenge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_vazruden_the_heraldAI : public ScriptedAI -{ - boss_vazruden_the_heraldAI(Creature *c) : ScriptedAI(c) - { - summoned = false; - sentryDown = false; - NazanGUID = 0; - VazrudenGUID = 0; - } - - uint32 phase; - uint32 waypoint; - uint32 check; - bool sentryDown; - uint64 NazanGUID; - uint64 VazrudenGUID; - bool summoned; - - void Reset() - { - phase = 0; - waypoint = 0; - check = 0; - UnsummonAdds(); - me->GetMotionMaster()->MovePath(PATH_ENTRY, true); - } - - void UnsummonAdds() - { - if (summoned) - { - Creature *Nazan = Unit::GetCreature(*me, NazanGUID); - if (!Nazan) - Nazan = me->FindNearestCreature(ENTRY_NAZAN, 5000); - if (Nazan) - { - Nazan->DisappearAndDie(); - NazanGUID = 0; - } - - Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); - if (!Vazruden) - Vazruden = me->FindNearestCreature(ENTRY_VAZRUDEN, 5000); - if (Vazruden) - { - Vazruden->DisappearAndDie(); - VazrudenGUID = 0; - } - summoned = false; - me->clearUnitState(UNIT_STAT_ROOT); - me->SetVisibility(VISIBILITY_ON); - } - } - - void SummonAdds() - { - if (!summoned) - { - if (Creature* Vazruden = me->SummonCreature(ENTRY_VAZRUDEN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) - VazrudenGUID = Vazruden->GetGUID(); - if (Creature* Nazan = me->SummonCreature(ENTRY_NAZAN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) - NazanGUID = Nazan->GetGUID(); - summoned = true; - me->SetVisibility(VISIBILITY_OFF); - me->addUnitState(UNIT_STAT_ROOT); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (phase == 0) - { - phase = 1; - check = 0; - DoScriptText(SAY_INTRO, me); - } - } - - void JustSummoned(Creature *summoned) - { - if (!summoned) return; - Unit *victim = me->getVictim(); - if (summoned->GetEntry() == ENTRY_NAZAN) - { - CAST_AI(boss_nazanAI, summoned->AI())->VazrudenGUID = VazrudenGUID; - summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - summoned->SetSpeed(MOVE_FLIGHT, 2.5); - if (victim) - AttackStartNoMove(victim); - } - else if (victim) - summoned->AI()->AttackStart(victim); - } - - void SentryDownBy(Unit* killer) - { - if (sentryDown) - { - AttackStartNoMove(killer); - sentryDown = false; - } - else - sentryDown = true; - } - - void UpdateAI(const uint32 diff) - { - switch(phase) - { - case 0: // circle around the platform - return; - break; - case 1: // go to the middle and begin the fight - if (check <= diff) - { - if (!me->IsWithinDist3d(VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],5)) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2]); - check = 1000; - } - else - { - SummonAdds(); - phase = 2; - return; - } - } else check -= diff; - break; - default: // adds do the job now - if (check <= diff) - { - Creature *Nazan = Unit::GetCreature(*me, NazanGUID); - Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); - if (Nazan && Nazan->isAlive() || Vazruden && Vazruden->isAlive()) - { - if (Nazan && Nazan->getVictim() || Vazruden && Vazruden->getVictim()) - return; - else - { - UnsummonAdds(); - EnterEvadeMode(); - return; - } - } - else - { - me->SummonGameObject(ENTRY_REINFORCED_FEL_IRON_CHEST,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,0,0,0,0,0); - me->SetLootRecipient(NULL); // don't think this is necessary.. - me->Kill(me); - } - check = 2000; - } else check -= diff; - break; - } - } -}; - -struct mob_hellfire_sentryAI : public ScriptedAI -{ - mob_hellfire_sentryAI(Creature *c) : ScriptedAI(c) {} - - uint32 KidneyShot_Timer; - - void Reset() - { - KidneyShot_Timer = urand(3000,7000); - } - - void EnterCombat(Unit* /*who*/) {} - - void JustDied(Unit* who) - { - if (Creature *herald = me->FindNearestCreature(ENTRY_VAZRUDEN_HERALD,150)) - CAST_AI(boss_vazruden_the_heraldAI, herald->AI())->SentryDownBy(who); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (KidneyShot_Timer <= diff) - { - if (Unit *victim = me->getVictim()) - DoCast(victim, SPELL_KIDNEY_SHOT); - KidneyShot_Timer = 20000; - } else KidneyShot_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vazruden_the_herald(Creature* pCreature) -{ - return new boss_vazruden_the_heraldAI (pCreature); -} - -CreatureAI* GetAI_boss_vazruden(Creature* pCreature) -{ - return new boss_vazrudenAI (pCreature); -} - -CreatureAI* GetAI_boss_nazan(Creature* pCreature) -{ - return new boss_nazanAI (pCreature); -} - -CreatureAI* GetAI_mob_hellfire_sentry(Creature* pCreature) -{ - return new mob_hellfire_sentryAI (pCreature); -} - -void AddSC_boss_vazruden_the_herald() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vazruden_the_herald"; - newscript->GetAI = &GetAI_boss_vazruden_the_herald; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_vazruden"; - newscript->GetAI = &GetAI_boss_vazruden; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_nazan"; - newscript->GetAI = &GetAI_boss_nazan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_hellfire_sentry"; - newscript->GetAI = &GetAI_mob_hellfire_sentry; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp b/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp deleted file mode 100644 index f0e813d3890..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Watchkeeper_Gargolmar -SD%Complete: 80 -SDComment: Missing adds to heal him. Surge should be used on pTarget furthest away, not random. -SDCategory: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_TAUNT -1543000 -#define SAY_HEAL -1543001 -#define SAY_SURGE -1543002 -#define SAY_AGGRO_1 -1543003 -#define SAY_AGGRO_2 -1543004 -#define SAY_AGGRO_3 -1543005 -#define SAY_KILL_1 -1543006 -#define SAY_KILL_2 -1543007 -#define SAY_DIE -1543008 - -#define SPELL_MORTAL_WOUND 30641 -#define H_SPELL_MORTAL_WOUND 36814 -#define SPELL_SURGE 34645 -#define SPELL_RETALIATION 22857 - -struct boss_watchkeeper_gargolmarAI : public ScriptedAI -{ - boss_watchkeeper_gargolmarAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Surge_Timer; - uint32 MortalWound_Timer; - uint32 Retaliation_Timer; - - bool HasTaunted; - bool YelledForHeal; - - void Reset() - { - Surge_Timer = 5000; - MortalWound_Timer = 4000; - Retaliation_Timer = 0; - - HasTaunted = false; - YelledForHeal = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void MoveInLineOfSight(Unit* who) - { - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (!HasTaunted && me->IsWithinDistInMap(who, 60.0f)) - { - DoScriptText(SAY_TAUNT, me); - HasTaunted = true; - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (MortalWound_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - MortalWound_Timer = 5000+rand()%8000; - } else MortalWound_Timer -= diff; - - if (Surge_Timer <= diff) - { - DoScriptText(SAY_SURGE, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SURGE); - - Surge_Timer = 5000+rand()%8000; - } else Surge_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) - { - if (Retaliation_Timer <= diff) - { - DoCast(me, SPELL_RETALIATION); - Retaliation_Timer = 30000; - } else Retaliation_Timer -= diff; - } - - if (!YelledForHeal) - { - if ((me->GetHealth()*100) / me->GetMaxHealth() < 40) - { - DoScriptText(SAY_HEAL, me); - YelledForHeal = true; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_watchkeeper_gargolmarAI(Creature* pCreature) -{ - return new boss_watchkeeper_gargolmarAI (pCreature); -} - -void AddSC_boss_watchkeeper_gargolmar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_watchkeeper_gargolmar"; - newscript->GetAI = &GetAI_boss_watchkeeper_gargolmarAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h b/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h deleted file mode 100644 index 599aa237774..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_RAMPARTS_H -#define DEF_RAMPARTS_H - -#define MAX_ENCOUNTER 2 - -enum eTypes -{ - TYPE_VAZRUDEN = 1, - TYPE_NAZAN = 2 -}; - -#endif diff --git a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp b/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp deleted file mode 100644 index 29c58675e9c..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Hellfire_Ramparts -SD%Complete: 50 -SDComment: -SDCategory: Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" -#include "hellfire_ramparts.h" - -struct instance_ramparts : public ScriptedInstance -{ - instance_ramparts(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint64 m_uiChestNGUID; - uint64 m_uiChestHGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiChestNGUID = 0; - m_uiChestHGUID = 0; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 185168: m_uiChestNGUID = pGo->GetGUID(); break; - case 185169: m_uiChestHGUID = pGo->GetGUID(); break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - debug_log("TSCR: Instance Ramparts: SetData received for type %u with data %u",uiType,uiData); - - switch(uiType) - { - case TYPE_VAZRUDEN: - if (uiData == DONE && m_auiEncounter[1] == DONE) - DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); - m_auiEncounter[0] = uiData; - break; - case TYPE_NAZAN: - if (uiData == DONE && m_auiEncounter[0] == DONE) - DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); - m_auiEncounter[1] = uiData; - break; - } - } -}; - -InstanceData* GetInstanceData_instance_ramparts(Map* pMap) -{ - return new instance_ramparts(pMap); -} - -void AddSC_instance_ramparts() -{ - Script* pNewScript; - pNewScript = new Script; - pNewScript->Name = "instance_ramparts"; - pNewScript->GetInstanceData = &GetInstanceData_instance_ramparts; - pNewScript->RegisterSelf(); -} diff --git a/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp b/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp deleted file mode 100644 index 5fb381f4065..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/* Copyright(C) 2006 - 2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -*(at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Magtheridon -SD%Complete: 60 -SDComment: In Development -SDCategory: Hellfire Citadel, Magtheridon's lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "magtheridons_lair.h" - -struct Yell -{ - int32 id; -}; - -static Yell RandomTaunt[]= -{ - {-1544000}, - {-1544001}, - {-1544002}, - {-1544003}, - {-1544004}, - {-1544005}, -}; - -#define SAY_FREED -1544006 -#define SAY_AGGRO -1544007 -#define SAY_BANISH -1544008 -#define SAY_CHAMBER_DESTROY -1544009 -#define SAY_PLAYER_KILLED -1544010 -#define SAY_DEATH -1544011 - -#define EMOTE_BERSERK -1544012 -#define EMOTE_BLASTNOVA -1544013 -#define EMOTE_BEGIN -1544014 - -#define MOB_MAGTHERIDON 17257 -#define MOB_ROOM 17516 -#define MOB_CHANNELLER 17256 -#define MOB_ABYSSAL 17454 - -#define SPELL_BLASTNOVA 30616 -#define SPELL_CLEAVE 30619 -#define SPELL_QUAKE_TRIGGER 30657 // must be cast with 30561 as the proc spell -#define SPELL_QUAKE_KNOCKBACK 30571 -#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 -#define SPELL_BLAZE_TRAP 30542 -#define SPELL_DEBRIS_KNOCKDOWN 36449 -#define SPELL_DEBRIS_VISUAL 30632 -#define SPELL_DEBRIS_DAMAGE 30631 // core bug, does not support target 8 -#define SPELL_CAMERA_SHAKE 36455 -#define SPELL_BERSERK 27680 - -#define SPELL_SHADOW_CAGE 30168 -#define SPELL_SHADOW_GRASP 30410 -#define SPELL_SHADOW_GRASP_VISUAL 30166 -#define SPELL_MIND_EXHAUSTION 44032 //Casted by the cubes when channeling ends - -#define SPELL_SHADOW_CAGE_C 30205 -#define SPELL_SHADOW_GRASP_C 30207 - -#define SPELL_SHADOW_BOLT_VOLLEY 30510 -#define SPELL_DARK_MENDING 30528 -#define SPELL_FEAR 30530 //39176 -#define SPELL_BURNING_ABYSSAL 30511 -#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 - -#define SPELL_FIRE_BLAST 37110 - -// count of clickers needed to interrupt blast nova -#define CLICKERS_COUNT 5 - -typedef std::map CubeMap; - -struct mob_abyssalAI : public ScriptedAI -{ - mob_abyssalAI(Creature *c) : ScriptedAI(c) - { - trigger = 0; - Despawn_Timer = 60000; - } - - uint32 FireBlast_Timer; - uint32 Despawn_Timer; - uint32 trigger; - - void Reset() - { - FireBlast_Timer = 6000; - } - - void SpellHit(Unit*, const SpellEntry *spell) - { - if (trigger == 2 && spell->Id == SPELL_BLAZE_TARGET) - { - DoCast(me, SPELL_BLAZE_TRAP, true); - me->SetVisibility(VISIBILITY_OFF); - Despawn_Timer = 130000; - } - } - - void SetTrigger(uint32 _trigger) - { - trigger = _trigger; - me->SetDisplayId(11686); - if (trigger == 1) //debris - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_DEBRIS_VISUAL, true); - FireBlast_Timer = 5000; - Despawn_Timer = 10000; - } - } - - void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} - void AttackStart(Unit *who) {if (!trigger) ScriptedAI::AttackStart(who);} - void MoveInLineOfSight(Unit *who) {if (!trigger) ScriptedAI::MoveInLineOfSight(who);} - - void UpdateAI(const uint32 diff) - { - if (trigger) - { - if (trigger == 1) - { - if (FireBlast_Timer <= diff) - { - DoCast(me, SPELL_DEBRIS_DAMAGE, true); - trigger = 3; - } else FireBlast_Timer -= diff; - } - return; - } - - if (Despawn_Timer <= diff) - { - me->ForcedDespawn(); - } else Despawn_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (FireBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRE_BLAST); - FireBlast_Timer = 5000+rand()%10000; - } else FireBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_magtheridonAI : public ScriptedAI -{ - boss_magtheridonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - - // target 7, random target with certain entry spell, need core fix - SpellEntry *TempSpell; - TempSpell = GET_SPELL(SPELL_BLAZE_TARGET); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 6) - { - TempSpell->EffectImplicitTargetA[0] = 6; - TempSpell->EffectImplicitTargetB[0] = 0; - } - TempSpell = GET_SPELL(SPELL_QUAKE_TRIGGER); - if (TempSpell && TempSpell->EffectTriggerSpell[0] != SPELL_QUAKE_KNOCKBACK) - { - TempSpell->EffectTriggerSpell[0] = SPELL_QUAKE_KNOCKBACK; - } - } - - CubeMap Cube; - - ScriptedInstance* pInstance; - - uint32 Berserk_Timer; - uint32 Quake_Timer; - uint32 Cleave_Timer; - uint32 BlastNova_Timer; - uint32 Blaze_Timer; - uint32 Debris_Timer; - uint32 RandChat_Timer; - - bool Phase3; - bool NeedCheckCube; - - void Reset() - { - Berserk_Timer = 1320000; - Quake_Timer = 40000; - Debris_Timer = 10000; - Blaze_Timer = 10000+rand()%20000; - BlastNova_Timer = 60000; - Cleave_Timer = 15000; - RandChat_Timer = 90000; - - Phase3 = false; - NeedCheckCube = false; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->addUnitState(UNIT_STAT_STUNNED); - DoCast(me, SPELL_SHADOW_CAGE_C, true); - } - - void JustReachedHome() - { - if (pInstance) - { - pInstance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED); - pInstance->SetData(DATA_COLLAPSE, false); - } - } - - void SetClicker(uint64 cubeGUID, uint64 clickerGUID) - { - // to avoid multiclicks from 1 cube - if (uint64 guid = Cube[cubeGUID]) - DebuffClicker(Unit::GetUnit(*me, guid)); - Cube[cubeGUID] = clickerGUID; - NeedCheckCube = true; - } - - //function to interrupt channeling and debuff clicker with mind exh(used if second person clicks with same cube or after dispeling/ending shadow grasp DoT) - void DebuffClicker(Unit *clicker) - { - if (!clicker || !clicker->isAlive()) - return; - - clicker->RemoveAurasDueToSpell(SPELL_SHADOW_GRASP); // cannot interrupt triggered spells - clicker->InterruptNonMeleeSpells(false); - clicker->CastSpell(clicker, SPELL_MIND_EXHAUSTION, true); - } - - void NeedCheckCubeStatus() - { - uint32 ClickerNum = 0; - // now checking if every clicker has debuff from manticron(it is dispelable atm rev 6110 : S) - // if not - apply mind exhaustion and delete from clicker's list - for (CubeMap::iterator i = Cube.begin(); i != Cube.end(); ++i) - { - Unit *clicker = Unit::GetUnit(*me, (*i).second); - if (!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP)) - { - DebuffClicker(clicker); - (*i).second = 0; - } else ++ClickerNum; - } - - // if 5 clickers from other cubes apply shadow cage - if (ClickerNum >= CLICKERS_COUNT && !me->HasAura(SPELL_SHADOW_CAGE)) - { - DoScriptText(SAY_BANISH, me); - DoCast(me, SPELL_SHADOW_CAGE, true); - } - else if (ClickerNum < CLICKERS_COUNT && me->HasAura(SPELL_SHADOW_CAGE)) - me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); - - if (!ClickerNum) NeedCheckCube = false; - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_PLAYER_KILLED, me); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_MAGTHERIDON_EVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void AttackStart(Unit *who) - { - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS); - DoZoneInCombat(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); - - DoScriptText(SAY_FREED, me); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - { - if (RandChat_Timer <= diff) - { - DoScriptText(RandomTaunt[rand()%6].id, me); - RandChat_Timer = 90000; - } else RandChat_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - if (NeedCheckCube) NeedCheckCubeStatus(); - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - DoScriptText(EMOTE_BERSERK, me); - Berserk_Timer = 60000; - } else Berserk_Timer -= diff; - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 10000; - } else Cleave_Timer -= diff; - - if (BlastNova_Timer <= diff) - { - // to avoid earthquake interruption - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - { - DoScriptText(EMOTE_BLASTNOVA, me); - DoCast(me, SPELL_BLASTNOVA); - BlastNova_Timer = 60000; - } - } else BlastNova_Timer -= diff; - - if (Quake_Timer <= diff) - { - // to avoid blastnova interruption - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_QUAKE_TRIGGER, true); - Quake_Timer = 50000; - } - } else Quake_Timer -= diff; - - if (Blaze_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - pTarget->GetPosition(x, y, z); - Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (summon) - { - CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(2); - DoCast(summon, SPELL_BLAZE_TARGET, true); - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - } - Blaze_Timer = 20000 + rand()%20000; - } else Blaze_Timer -= diff; - - if (!Phase3 && me->GetHealth()*10 < me->GetMaxHealth()*3 - && !me->IsNonMeleeSpellCasted(false) // blast nova - && !me->hasUnitState(UNIT_STAT_STUNNED)) // shadow cage and earthquake - { - Phase3 = true; - DoScriptText(SAY_CHAMBER_DESTROY, me); - DoCast(me, SPELL_CAMERA_SHAKE, true); - DoCast(me, SPELL_DEBRIS_KNOCKDOWN, true); - - if (pInstance) - pInstance->SetData(DATA_COLLAPSE, true); - } - - if (Phase3) - { - if (Debris_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - pTarget->GetPosition(x, y, z); - Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (summon) CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(1); - } - Debris_Timer = 10000; - } else Debris_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_hellfire_channelerAI : public ScriptedAI -{ - mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c) - { - pInstance =me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ShadowBoltVolley_Timer; - uint32 DarkMending_Timer; - uint32 Fear_Timer; - uint32 Infernal_Timer; - - uint32 Check_Timer; - - void Reset() - { - ShadowBoltVolley_Timer = 8000 + rand()%2000; - DarkMending_Timer = 10000; - Fear_Timer = 15000 + rand()%5000; - Infernal_Timer = 10000 + rand()%40000; - - Check_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS); - - me->InterruptNonMeleeSpells(false); - DoZoneInCombat(); - } - - void JustReachedHome() - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED); - - DoCast(me, SPELL_SHADOW_GRASP_C, false); - } - - void JustSummoned(Creature *summon) - { - summon->AI()->AttackStart(me->getVictim()); - } - - void DamageTaken(Unit*, uint32 &damage) - { - if (damage >= me->GetHealth()) - DoCast(me, SPELL_SOUL_TRANSFER, true); - } - - void JustDied(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); - ShadowBoltVolley_Timer = 10000 + rand()%10000; - } else ShadowBoltVolley_Timer -= diff; - - if (DarkMending_Timer <= diff) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) - DoCast(me, SPELL_DARK_MENDING); - DarkMending_Timer = 10000 +(rand() % 10000); - } else DarkMending_Timer -= diff; - - if (Fear_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - DoCast(pTarget, SPELL_FEAR); - Fear_Timer = 25000 + rand()%15000; - } else Fear_Timer -= diff; - - if (Infernal_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BURNING_ABYSSAL, true); - Infernal_Timer = 30000 + rand()%10000; - } else Infernal_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Manticron Cube -bool GOHello_go_Manticron_Cube(Player* pPlayer, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - if (!pInstance) - return true; - if (pInstance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) return true; - Creature *Magtheridon =Unit::GetCreature(*pGo, pInstance->GetData64(DATA_MAGTHERIDON)); - if (!Magtheridon || !Magtheridon->isAlive()) return true; - - // if exhausted or already channeling return - if (pPlayer->HasAura(SPELL_MIND_EXHAUSTION) || pPlayer->HasAura(SPELL_SHADOW_GRASP)) - return true; - - pPlayer->InterruptNonMeleeSpells(false); - pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP, true); - pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP_VISUAL, false); - CAST_AI(boss_magtheridonAI, Magtheridon->AI())->SetClicker(pGo->GetGUID(), pPlayer->GetGUID()); - return true; -} - -CreatureAI* GetAI_boss_magtheridon(Creature* pCreature) -{ - return new boss_magtheridonAI(pCreature); -} - -CreatureAI* GetAI_mob_hellfire_channeler(Creature* pCreature) -{ - return new mob_hellfire_channelerAI(pCreature); -} - -CreatureAI* GetAI_mob_abyssalAI(Creature* pCreature) -{ - return new mob_abyssalAI(pCreature); -} - -void AddSC_boss_magtheridon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magtheridon"; - newscript->GetAI = &GetAI_boss_magtheridon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_hellfire_channeler"; - newscript->GetAI = &GetAI_mob_hellfire_channeler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_manticron_cube"; - newscript->pGOHello = &GOHello_go_Manticron_Cube; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_abyssal"; - newscript->GetAI = &GetAI_mob_abyssalAI; - newscript->RegisterSelf(); - -} - diff --git a/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp b/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp deleted file mode 100644 index d5b459a1fa1..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Magtheridons_Lair -SD%Complete: 100 -SDComment: -SDCategory: Hellfire Citadel, Magtheridon's lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "magtheridons_lair.h" - -#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 -#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 - -#define CHAMBER_CENTER_X -15.14 -#define CHAMBER_CENTER_Y 1.8 -#define CHAMBER_CENTER_Z -0.4 - -#define MAX_ENCOUNTER 2 - -#define EMOTE_BONDS_WEAKEN "'s bonds begin to weaken!" - -struct instance_magtheridons_lair : public ScriptedInstance -{ - instance_magtheridons_lair(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - } - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 MagtheridonGUID; - std::set ChannelerGUID; - uint64 DoorGUID; - std::set ColumnGUID; - - uint32 CageTimer; - uint32 RespawnTimer; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - MagtheridonGUID = 0; - ChannelerGUID.clear(); - DoorGUID = 0; - ColumnGUID.clear(); - - CageTimer = 0; - RespawnTimer = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17257: - MagtheridonGUID = pCreature->GetGUID(); - break; - case 17256: - ChannelerGUID.insert(pCreature->GetGUID()); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 181713: - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 0); - break; - case 183847: - DoorGUID = pGo->GetGUID(); - break; - case 184653: // hall - case 184634: // six columns - case 184635: - case 184636: - case 184637: - case 184638: - case 184639: - ColumnGUID.insert(pGo->GetGUID()); - break; - } - } - - uint64 GetData64(uint32 type) - { - switch(type) - { - case DATA_MAGTHERIDON: - return MagtheridonGUID; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MAGTHERIDON_EVENT: - m_auiEncounter[0] = data; - if (data == NOT_STARTED) - RespawnTimer = 10000; - if (data != IN_PROGRESS) - HandleGameObject(DoorGUID, true); - break; - case DATA_CHANNELER_EVENT: - switch(data) - { - case NOT_STARTED: // Reset all channelers once one is reset. - if (m_auiEncounter[1] != NOT_STARTED) - { - m_auiEncounter[1] = NOT_STARTED; - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - if (Creature *Channeler = instance->GetCreature(*i)) - { - if (Channeler->isAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } - } - CageTimer = 0; - HandleGameObject(DoorGUID, true); - } - break; - case IN_PROGRESS: // Event start. - if (m_auiEncounter[1] != IN_PROGRESS) - { - m_auiEncounter[1] = IN_PROGRESS; - // Let all five channelers aggro. - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - Creature *Channeler = instance->GetCreature(*i); - if (Channeler && Channeler->isAlive()) - Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); - } - // Release Magtheridon after two minutes. - Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); - if (Magtheridon && Magtheridon->isAlive()) - { - Magtheridon->MonsterTextEmote(EMOTE_BONDS_WEAKEN, 0); - CageTimer = 120000; - } - HandleGameObject(DoorGUID, false); - } - break; - case DONE: // Add buff and check if all channelers are dead. - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - Creature *Channeler = instance->GetCreature(*i); - if (Channeler && Channeler->isAlive()) - { - //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); - data = IN_PROGRESS; - break; - } - } - break; - } - m_auiEncounter[1] = data; - break; - case DATA_COLLAPSE: - // true - collapse / false - reset - for (std::set::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) - DoUseDoorOrButton(*i); - break; - default: - break; - } - } - - uint32 GetData(uint32 type) - { - if (type == DATA_MAGTHERIDON_EVENT) - return m_auiEncounter[0]; - return 0; - } - - void Update(uint32 diff) - { - if (CageTimer) - { - if (CageTimer <= diff) - { - Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); - if (Magtheridon && Magtheridon->isAlive()) - { - Magtheridon->clearUnitState(UNIT_STAT_STUNNED); - Magtheridon->AI()->AttackStart(Magtheridon->SelectNearestTarget(999)); - } - CageTimer = 0; - } else CageTimer -= diff; - } - - if (RespawnTimer) - { - if (RespawnTimer <= diff) - { - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - if (Creature *Channeler = instance->GetCreature(*i)) - { - if (Channeler->isAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } - } - RespawnTimer = 0; - } else RespawnTimer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_magtheridons_lair(Map* pMap) -{ - return new instance_magtheridons_lair(pMap); -} - -void AddSC_instance_magtheridons_lair() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_magtheridons_lair"; - newscript->GetInstanceData = &GetInstanceData_instance_magtheridons_lair; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h b/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h deleted file mode 100644 index 1b3e525fc54..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_MAGTHERIDONS_LAIR_H -#define DEF_MAGTHERIDONS_LAIR_H - -#define DATA_MAGTHERIDON_EVENT 1 -#define DATA_MAGTHERIDON 3 -#define DATA_CHANNELER_EVENT 2 -#define DATA_COLLAPSE 6 -#define DATA_CHANNELER 9 -#endif - diff --git a/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp b/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp deleted file mode 100644 index e3ded52edc9..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grand_Warlock_Nethekurse -SD%Complete: 75 -SDComment: encounter not fully completed. missing part where boss kill minions. -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -boss_grand_warlock_nethekurse -mob_fel_orc_convert -mob_lesser_shadow_fissure -EndContentData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -struct Say -{ - int32 id; -}; - -static Say PeonAttacked[]= -{ - {-1540001}, - {-1540002}, - {-1540003}, - {-1540004}, -}; -static Say PeonDies[]= -{ - {-1540005}, - {-1540006}, - {-1540007}, - {-1540008}, -}; - -#define SAY_INTRO -1540000 -#define SAY_TAUNT_1 -1540009 -#define SAY_TAUNT_2 -1540010 -#define SAY_TAUNT_3 -1540011 -#define SAY_AGGRO_1 -1540012 -#define SAY_AGGRO_2 -1540013 -#define SAY_AGGRO_3 -1540014 -#define SAY_SLAY_1 -1540015 -#define SAY_SLAY_2 -1540016 -#define SAY_DIE -1540017 - -#define SPELL_DEATH_COIL 30500 -#define SPELL_DARK_SPIN 30502 // core bug spell attack caster :D -#define SPELL_SHADOW_FISSURE 30496 // Summon the ShadowFissure NPC - -#define SPELL_SHADOW_CLEAVE 30495 -#define H_SPELL_SHADOW_SLAM 35953 - -#define SPELL_HEMORRHAGE 30478 - -#define SPELL_CONSUMPTION 30497 -#define SPELL_TEMPORARY_VISUAL 39312 // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should - -struct boss_grand_warlock_nethekurseAI : public ScriptedAI -{ - boss_grand_warlock_nethekurseAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool IntroOnce; - bool IsIntroEvent; - bool IsMainEvent; - bool SpinOnce; - //bool HasTaunted; - bool Phase; - - uint32 PeonEngagedCount; - uint32 PeonKilledCount; - - uint32 IntroEvent_Timer; - uint32 DeathCoil_Timer; - uint32 ShadowFissure_Timer; - uint32 Cleave_Timer; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - IsIntroEvent = false; - IntroOnce = false; - IsMainEvent = false; - //HasTaunted = false; - SpinOnce = false; - Phase = false; - - PeonEngagedCount = 0; - PeonKilledCount = 0; - - IntroEvent_Timer = 90000; //how long before getting bored and kills his minions? - DeathCoil_Timer = 20000; - ShadowFissure_Timer = 8000; - Cleave_Timer = 5000; - } - - void DoYellForPeonAggro() - { - if (PeonEngagedCount >= 4) - return; - - DoScriptText(PeonAttacked[PeonEngagedCount].id, me); - ++PeonEngagedCount; - } - - void DoYellForPeonDeath() - { - if (PeonKilledCount >= 4) - return; - - DoScriptText(PeonDies[PeonKilledCount].id, me); - ++PeonKilledCount; - - if (PeonKilledCount == 4) - { - IsIntroEvent = false; - IsMainEvent = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - - void DoTauntPeons() - { - DoScriptText(RAND(SAY_TAUNT_1,SAY_TAUNT_2,SAY_TAUNT_3), me); - - //TODO: kill the peons first - IsIntroEvent = false; - PeonEngagedCount = 4; - PeonKilledCount = 4; - IsMainEvent = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void AttackStart(Unit* who) - { - if (IsIntroEvent || !IsMainEvent) - return; - - if (me->Attack(who, true)) - { - if (Phase) - DoStartNoMovement(who); - else - DoStartMovement(who); - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!IntroOnce && me->IsWithinDistInMap(who, 50.0f)) - { - if (who->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(SAY_INTRO, me); - IntroOnce = true; - IsIntroEvent = true; - - if (pInstance) - pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); - } - - if (IsIntroEvent || !IsMainEvent) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustSummoned(Creature *summoned) - { - summoned->setFaction(16); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - //triggered spell of consumption does not properly show it's SpellVisual, wrong spellid? - summoned->CastSpell(summoned,SPELL_TEMPORARY_VISUAL,true); - summoned->CastSpell(summoned,SPELL_CONSUMPTION,false,0,0,me->GetGUID()); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_NETHEKURSE,DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_NETHEKURSE_DOOR), true); - } - - void UpdateAI(const uint32 diff) - { - if (IsIntroEvent) - { - if (!pInstance) - return; - - if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) - { - if (IntroEvent_Timer <= diff) - DoTauntPeons(); - else - IntroEvent_Timer -= diff; - } - } - - if (!UpdateVictim()) - return; - - if (!IsMainEvent) - return; - - if (Phase) - { - if (!SpinOnce) - { - DoCast(me->getVictim(), SPELL_DARK_SPIN); - SpinOnce = true; - } - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_CLEAVE); - Cleave_Timer = 6000+rand()%2500; - } else Cleave_Timer -= diff; - } - else - { - if (ShadowFissure_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_FISSURE); - ShadowFissure_Timer = urand(7500,15000); - } else ShadowFissure_Timer -= diff; - - if (DeathCoil_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_DEATH_COIL); - DeathCoil_Timer = urand(15000,20000); - } else DeathCoil_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) - Phase = true; - - DoMeleeAttackIfReady(); - } - } -}; - -struct mob_fel_orc_convertAI : public ScriptedAI -{ - mob_fel_orc_convertAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 Hemorrhage_Timer; - - void Reset() - { - me->SetNoCallAssistance(true); //we don't want any assistance (WE R HEROZ!) - Hemorrhage_Timer = 3000; - } - - void MoveInLineOfSight(Unit * /*who*/) - { - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - { - if (pInstance->GetData64(DATA_NETHEKURSE)) - { - Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE)); - if (pKurse && me->IsWithinDist(pKurse, 45.0f)) - { - CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonAggro(); - - if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) - return; - else - pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); - } - } - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - if (pInstance->GetData(TYPE_NETHEKURSE) != IN_PROGRESS) - return; - if (pInstance->GetData64(DATA_NETHEKURSE)) - if (Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE))) - CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonDeath(); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Hemorrhage_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HEMORRHAGE); - Hemorrhage_Timer = 15000; - } else Hemorrhage_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//NOTE: this Creature are also summoned by other spells, for different creatures -struct mob_lesser_shadow_fissureAI : public ScriptedAI -{ - mob_lesser_shadow_fissureAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - void MoveInLineOfSight(Unit * /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void EnterCombat(Unit* /*who*/) {} -}; - -CreatureAI* GetAI_boss_grand_warlock_nethekurse(Creature* pCreature) -{ - return new boss_grand_warlock_nethekurseAI (pCreature); -} - -CreatureAI* GetAI_mob_fel_orc_convert(Creature* pCreature) -{ - return new mob_fel_orc_convertAI (pCreature); -} - -CreatureAI* GetAI_mob_lesser_shadow_fissure(Creature* pCreature) -{ - return new mob_lesser_shadow_fissureAI (pCreature); -} - -void AddSC_boss_grand_warlock_nethekurse() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_grand_warlock_nethekurse"; - newscript->GetAI = &GetAI_boss_grand_warlock_nethekurse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fel_orc_convert"; - newscript->GetAI = &GetAI_mob_fel_orc_convert; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lesser_shadow_fissure"; - newscript->GetAI = &GetAI_mob_lesser_shadow_fissure; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp b/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp deleted file mode 100644 index 6fa1c9efe33..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warbringer_Omrogg -SD%Complete: 85 -SDComment: Heroic enabled. Spell timing may need additional tweaks -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -mob_omrogg_heads -boss_warbringer_omrogg -EndContentData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -enum eEnums -{ - YELL_DIE_L = -1540039, - YELL_DIE_R = -1540040, - EMOTE_ENRAGE = -1540041, - - SPELL_BLAST_WAVE = 30600, - SPELL_FEAR = 30584, - SPELL_THUNDERCLAP = 30633, - - SPELL_BURNING_MAUL = 30598, - H_SPELL_BURNING_MAUL = 36056, - - NPC_LEFT_HEAD = 19523, - NPC_RIGHT_HEAD = 19524 -}; - -struct Yell -{ - int32 id; - uint32 creature; -}; - -static Yell GoCombat[]= -{ - {-1540018, NPC_LEFT_HEAD}, - {-1540019, NPC_LEFT_HEAD}, - {-1540020, NPC_LEFT_HEAD}, -}; -static Yell GoCombatDelay[]= -{ - {-1540021, NPC_RIGHT_HEAD}, - {-1540022, NPC_RIGHT_HEAD}, - {-1540023, NPC_RIGHT_HEAD}, -}; - -static Yell Threat[]= -{ - {-1540024, NPC_LEFT_HEAD}, - {-1540025, NPC_RIGHT_HEAD}, - {-1540026, NPC_LEFT_HEAD}, - {-1540027, NPC_LEFT_HEAD}, -}; -static Yell ThreatDelay1[]= -{ - {-1540028, NPC_RIGHT_HEAD}, - {-1540029, NPC_LEFT_HEAD}, - {-1540030, NPC_RIGHT_HEAD}, - {-1540031, NPC_RIGHT_HEAD}, -}; -static Yell ThreatDelay2[]= -{ - {-1540032, NPC_LEFT_HEAD}, - {-1540033, NPC_RIGHT_HEAD}, - {-1540034, NPC_LEFT_HEAD}, - {-1540035, NPC_LEFT_HEAD}, -}; - -static Yell Killing[]= -{ - {-1540036, NPC_LEFT_HEAD}, - {-1540037, NPC_RIGHT_HEAD}, -}; -static Yell KillingDelay[]= -{ - {-1540038, NPC_RIGHT_HEAD}, - {-1000000, NPC_LEFT_HEAD}, -}; - -struct mob_omrogg_headsAI : public ScriptedAI -{ - mob_omrogg_headsAI(Creature *c) : ScriptedAI(c) {} - - bool DeathYell; - uint32 Death_Timer; - - void Reset() - { - Death_Timer = 4000; - DeathYell = false; - } - void EnterCombat(Unit* /*who*/) {} - - void DoDeathYell() - { - DeathYell = true; - } - - void UpdateAI(const uint32 diff) - { - if (!DeathYell) - return; - - if (Death_Timer <= diff) - { - DoScriptText(YELL_DIE_R, me); - Death_Timer = false; - me->setDeathState(JUST_DIED); - } else Death_Timer -= diff; - } -}; - -struct boss_warbringer_omroggAI : public ScriptedAI -{ - boss_warbringer_omroggAI(Creature *c) : ScriptedAI(c) - { - LeftHeadGUID = 0; - RightHeadGUID = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 LeftHeadGUID; - uint64 RightHeadGUID; - int iaggro; - int ithreat; - int ikilling; - - bool AggroYell; - bool ThreatYell; - bool ThreatYell2; - bool KillingYell; - - uint32 Delay_Timer; - uint32 BlastWave_Timer; - uint32 BlastCount; - uint32 Fear_Timer; - uint32 BurningMaul_Timer; - uint32 ThunderClap_Timer; - uint32 ResetThreat_Timer; - - void Reset() - { - if (Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) - { - pLeftHead->setDeathState(JUST_DIED); - LeftHeadGUID = 0; - } - - if (Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID)) - { - pRightHead->setDeathState(JUST_DIED); - RightHeadGUID = 0; - } - - AggroYell = false; - ThreatYell = false; - ThreatYell2 = false; - KillingYell = false; - - Delay_Timer = 4000; - BlastWave_Timer = 0; - BlastCount = 0; - Fear_Timer = 8000; - BurningMaul_Timer = 25000; - ThunderClap_Timer = 15000; - ResetThreat_Timer = 30000; - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, NOT_STARTED); //End boss can use this later. O'mrogg must be defeated(DONE) or he will come to aid. - } - - void DoYellForThreat() - { - Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit *pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - ithreat = rand()%4; - - Unit *source = (pLeftHead->GetEntry() == Threat[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(Threat[ithreat].id, source); - - Delay_Timer = 3500; - ThreatYell = true; - } - - void EnterCombat(Unit * /*who*/) - { - me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); - me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); - - if (Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) - { - iaggro = rand()%3; - - DoScriptText(GoCombat[iaggro].id, pLeftHead); - - Delay_Timer = 3500; - AggroYell = true; - } - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, IN_PROGRESS); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == NPC_LEFT_HEAD) - LeftHeadGUID = summoned->GetGUID(); - - if (summoned->GetEntry() == NPC_RIGHT_HEAD) - RightHeadGUID = summoned->GetGUID(); - - //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->SetVisibility(VISIBILITY_OFF); - } - - void KilledUnit(Unit* /*victim*/) - { - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - ikilling = rand()%2; - - Unit *source = (pLeftHead->GetEntry() == Killing[ikilling].creature ? pLeftHead : pRightHead); - - switch(ikilling) - { - case 0: - DoScriptText(Killing[ikilling].id, source); - Delay_Timer = 3500; - KillingYell = true; - break; - case 1: - DoScriptText(Killing[ikilling].id, source); - KillingYell = false; - break; - } - } - - void JustDied(Unit* /*Killer*/) - { - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - DoScriptText(YELL_DIE_L, pLeftHead); - - CAST_AI(mob_omrogg_headsAI, CAST_CRE(pRightHead)->AI())->DoDeathYell(); - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (Delay_Timer <= diff) - { - Delay_Timer = 3500; - - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - if (AggroYell) - { - DoScriptText(GoCombatDelay[iaggro].id, pRightHead); - AggroYell = false; - } - - if (ThreatYell2) - { - Unit *source = (pLeftHead->GetEntry() == ThreatDelay2[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(ThreatDelay2[ithreat].id, source); - ThreatYell2 = false; - } - - if (ThreatYell) - { - Unit *source = (pLeftHead->GetEntry() == ThreatDelay1[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(ThreatDelay1[ithreat].id, source); - ThreatYell = false; - ThreatYell2 = true; - } - - if (KillingYell) - { - Unit *source = (pLeftHead->GetEntry() == KillingDelay[ikilling].creature ? pLeftHead : pRightHead); - - DoScriptText(KillingDelay[ikilling].id, source); - KillingYell = false; - } - } else Delay_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (BlastCount && BlastWave_Timer <= diff) - { - DoCast(me, SPELL_BLAST_WAVE); - BlastWave_Timer = 5000; - ++BlastCount; - - if (BlastCount == 3) - BlastCount = 0; - } else BlastWave_Timer -= diff; - - if (BurningMaul_Timer <= diff) - { - DoScriptText(EMOTE_ENRAGE, me); - DoCast(me, SPELL_BURNING_MAUL); - BurningMaul_Timer = 40000; - BlastWave_Timer = 16000; - BlastCount = 1; - } else BurningMaul_Timer -= diff; - - if (ResetThreat_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoYellForThreat(); - DoResetThreat(); - me->AddThreat(pTarget, 0.0f); - } - ResetThreat_Timer = 25000+rand()%15000; - } else ResetThreat_Timer -= diff; - - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 15000+rand()%20000; - } else Fear_Timer -= diff; - - if (ThunderClap_Timer <= diff) - { - DoCast(me, SPELL_THUNDERCLAP); - ThunderClap_Timer = 15000+rand()%15000; - } else ThunderClap_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_warbringer_omrogg(Creature* pCreature) -{ - return new boss_warbringer_omroggAI (pCreature); -} - -CreatureAI* GetAI_mob_omrogg_heads(Creature* pCreature) -{ - return new mob_omrogg_headsAI (pCreature); -} - -void AddSC_boss_warbringer_omrogg() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_warbringer_omrogg"; - newscript->GetAI = &GetAI_boss_warbringer_omrogg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_omrogg_heads"; - newscript->GetAI = &GetAI_mob_omrogg_heads; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp deleted file mode 100644 index b108077518a..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warchief_Kargath_Bladefist -SD%Complete: 90 -SDComment: -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -boss_warchief_kargath_bladefist -EndContentData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO1 -1540042 -#define SAY_AGGRO2 -1540043 -#define SAY_AGGRO3 -1540044 -#define SAY_SLAY1 -1540045 -#define SAY_SLAY2 -1540046 -#define SAY_DEATH -1540047 - -#define SPELL_BLADE_DANCE 30739 -#define H_SPELL_CHARGE 25821 - -#define TARGET_NUM 5 - -#define MOB_SHATTERED_ASSASSIN 17695 -#define MOB_HEARTHEN_GUARD 17621 -#define MOB_SHARPSHOOTER_GUARD 17622 -#define MOB_REAVER_GUARD 17623 - -float AssassEntrance[3] = {275.136,-84.29,2.3}; // y -8 -float AssassExit[3] = {184.233,-84.29,2.3}; // y -8 -float AddsEntrance[3] = {306.036,-84.29,1.93}; - -struct boss_warchief_kargath_bladefistAI : public ScriptedAI -{ - boss_warchief_kargath_bladefistAI(Creature *c) : ScriptedAI(c) - { - } - - std::vector adds; - std::vector assassins; - - uint32 Charge_timer; - uint32 Blade_Dance_Timer; - uint32 Summon_Assistant_Timer; - uint32 resetcheck_timer; - uint32 Wait_Timer; - - uint32 Assassins_Timer; - - uint32 summoned; - bool InBlade; - - uint32 target_num; - - void Reset() - { - removeAdds(); - - me->SetSpeed(MOVE_RUN,2); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - summoned = 2; - InBlade = false; - Wait_Timer = 0; - - Charge_timer = 0; - Blade_Dance_Timer = 45000; - Summon_Assistant_Timer = 30000; - Assassins_Timer = 5000; - resetcheck_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - } - - void JustSummoned(Creature *summoned) - { - switch(summoned->GetEntry()) - { - case MOB_HEARTHEN_GUARD: - case MOB_SHARPSHOOTER_GUARD: - case MOB_REAVER_GUARD: - summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0)); - adds.push_back(summoned->GetGUID()); - break; - case MOB_SHATTERED_ASSASSIN: - assassins.push_back(summoned->GetGUID()); - break; - } - } - - void KilledUnit(Unit* victim) - { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - removeAdds(); - } - - void MovementInform(uint32 type, uint32 id) - { - if (InBlade) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id != 1) - return; - - if (target_num > 0) // to prevent loops - { - Wait_Timer = 1; - DoCast(me, SPELL_BLADE_DANCE, true); - target_num--; - } - } - } - - void removeAdds() - { - for (std::vector::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) - { - Unit* temp = Unit::GetUnit((*me),*itr); - if (temp && temp->isAlive()) - { - (*temp).GetMotionMaster()->Clear(true); - me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - CAST_CRE(temp)->RemoveCorpse(); - } - } - adds.clear(); - - for (std::vector::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) - { - Unit* temp = Unit::GetUnit((*me),*itr); - if (temp && temp->isAlive()) - { - (*temp).GetMotionMaster()->Clear(true); - me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - CAST_CRE(temp)->RemoveCorpse(); - } - } - assassins.clear(); - } - void SpawnAssassin() - { - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]+8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]-8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]+8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]-8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Assassins_Timer) - if (Assassins_Timer <= diff) - { - SpawnAssassin(); - Assassins_Timer = 0; - } else Assassins_Timer -= diff; - - if (InBlade) - { - if (Wait_Timer) - if (Wait_Timer <= diff) - { - if (target_num <= 0) - { - // stop bladedance - InBlade = false; - me->SetSpeed(MOVE_RUN,2); - me->GetMotionMaster()->MoveChase(me->getVictim()); - Blade_Dance_Timer = 30000; - Wait_Timer = 0; - if (IsHeroic()) - Charge_timer = 5000; - } - else - { - //move in bladedance - float x,y,randx,randy; - randx = (rand()%40); - randy = (rand()%40); - x = 210+ randx ; - y = -60- randy ; - me->GetMotionMaster()->MovePoint(1,x,y,me->GetPositionZ()); - Wait_Timer = 0; - } - } else Wait_Timer -= diff; - } - else - { - if (Blade_Dance_Timer) - if (Blade_Dance_Timer <= diff) - { - target_num = TARGET_NUM; - Wait_Timer = 1; - InBlade = true; - Blade_Dance_Timer = 0; - me->SetSpeed(MOVE_RUN,4); - return; - } else Blade_Dance_Timer -= diff; - - if (Charge_timer) - if (Charge_timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), H_SPELL_CHARGE); - Charge_timer = 0; - } else Charge_timer -= diff; - - if (Summon_Assistant_Timer <= diff) - { - for (uint8 i = 0; i < summoned; ++i) - { - switch (urand(0,2)) - { - case 0: me->SummonCreature(MOB_HEARTHEN_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - case 1: me->SummonCreature(MOB_SHARPSHOOTER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - case 2: me->SummonCreature(MOB_REAVER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - } - } - if (urand(0,9) < 2) - ++summoned; - Summon_Assistant_Timer = urand(25000,35000); - } else Summon_Assistant_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - if (resetcheck_timer <= diff) - { - uint32 tempx,tempy; - tempx = uint32(me->GetPositionX()); - tempy = uint32(me->GetPositionY()); - if (tempx > 255 || tempx < 205) - { - EnterEvadeMode(); - return; - } - resetcheck_timer = 5000; - } else resetcheck_timer -= diff; - } -}; - -CreatureAI* GetAI_boss_warchief_kargath_bladefist(Creature* pCreature) -{ - return new boss_warchief_kargath_bladefistAI (pCreature); -} - -void AddSC_boss_warchief_kargath_bladefist() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_warchief_kargath_bladefist"; - newscript->GetAI = &GetAI_boss_warchief_kargath_bladefist; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp b/src/server/scripts/outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp deleted file mode 100644 index c29df4d6411..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Shattered_Halls -SD%Complete: 50 -SDComment: currently missing info about door. instance not complete -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -#define MAX_ENCOUNTER 2 - -#define DOOR_NETHEKURSE 1 - -struct instance_shattered_halls : public ScriptedInstance -{ - instance_shattered_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint64 nethekurseGUID; - uint64 nethekurseDoorGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - nethekurseGUID = 0; - nethekurseDoorGUID = 0; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case DOOR_NETHEKURSE: nethekurseDoorGUID = pGo->GetGUID(); break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 16807: nethekurseGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_NETHEKURSE: - m_auiEncounter[0] = data; - break; - case TYPE_OMROGG: - m_auiEncounter[1] = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_NETHEKURSE: - return m_auiEncounter[0]; - case TYPE_OMROGG: - return m_auiEncounter[1]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_NETHEKURSE: - return nethekurseGUID; - case DATA_NETHEKURSE_DOOR: - return nethekurseDoorGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_shattered_halls(Map* pMap) -{ - return new instance_shattered_halls(pMap); -} - -void AddSC_instance_shattered_halls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_shattered_halls"; - newscript->GetInstanceData = &GetInstanceData_instance_shattered_halls; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/hellfire_citadel/shattered_halls/shattered_halls.h b/src/server/scripts/outland/hellfire_citadel/shattered_halls/shattered_halls.h deleted file mode 100644 index cbfa23ec4e0..00000000000 --- a/src/server/scripts/outland/hellfire_citadel/shattered_halls/shattered_halls.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SHATTERED_H -#define DEF_SHATTERED_H - -#define TYPE_NETHEKURSE 1 -#define DATA_NETHEKURSE 2 -#define DATA_NETHEKURSE_DOOR 3 - -#define TYPE_OMROGG 4 -#endif - diff --git a/src/server/scripts/outland/hellfire_peninsula.cpp b/src/server/scripts/outland/hellfire_peninsula.cpp deleted file mode 100644 index fce8ac6f59e..00000000000 --- a/src/server/scripts/outland/hellfire_peninsula.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Hellfire_Peninsula -SD%Complete: 100 -SDComment: Quest support: 9375, 9410, 9418, 10129, 10146, 10162, 10163, 10340, 10346, 10347, 10382 (Special flight paths) -SDCategory: Hellfire Peninsula -EndScriptData */ - -/* ContentData -npc_aeranas -npc_ancestral_wolf -go_haaleshi_altar -npc_naladu -npc_tracy_proudwell -npc_trollbane -npc_wounded_blood_elf -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_aeranas -######*/ - -enum eAeranas -{ - SAY_SUMMON = -1000138, - SAY_FREE = -1000139, - - FACTION_HOSTILE = 16, - FACTION_FRIENDLY = 35, - - SPELL_ENVELOPING_WINDS = 15535, - SPELL_SHOCK = 12553, - - C_AERANAS = 17085 -}; - -struct npc_aeranasAI : public ScriptedAI -{ - npc_aeranasAI(Creature* c) : ScriptedAI(c) {} - - uint32 Faction_Timer; - uint32 EnvelopingWinds_Timer; - uint32 Shock_Timer; - - void Reset() - { - Faction_Timer = 8000; - EnvelopingWinds_Timer = 9000; - Shock_Timer = 5000; - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - me->setFaction(FACTION_FRIENDLY); - - DoScriptText(SAY_SUMMON, me); - } - - void UpdateAI(const uint32 diff) - { - if (Faction_Timer) - { - if (Faction_Timer <= diff) - { - me->setFaction(FACTION_HOSTILE); - Faction_Timer = 0; - } else Faction_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - if ((me->GetHealth()*100) / me->GetMaxHealth() < 30) - { - me->setFaction(FACTION_FRIENDLY); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - DoScriptText(SAY_FREE, me); - return; - } - - if (Shock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHOCK); - Shock_Timer = 10000; - } else Shock_Timer -= diff; - - if (EnvelopingWinds_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ENVELOPING_WINDS); - EnvelopingWinds_Timer = 25000; - } else EnvelopingWinds_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_aeranas(Creature* pCreature) -{ - return new npc_aeranasAI (pCreature); -} - -/*###### -## npc_ancestral_wolf -######*/ - -enum eAncestralWolf -{ - EMOTE_WOLF_LIFT_HEAD = -1000496, - EMOTE_WOLF_HOWL = -1000497, - SAY_WOLF_WELCOME = -1000498, - - SPELL_ANCESTRAL_WOLF_BUFF = 29981, - - NPC_RYGA = 17123 -}; - -struct npc_ancestral_wolfAI : public npc_escortAI -{ - npc_ancestral_wolfAI(Creature* pCreature) : npc_escortAI(pCreature) - { - if (pCreature->GetOwner() && pCreature->GetOwner()->GetTypeId() == TYPEID_PLAYER) - Start(false, false, pCreature->GetOwner()->GetGUID()); - else - error_log("TRINITY: npc_ancestral_wolf can not obtain owner or owner is not a player."); - - pCreature->SetSpeed(MOVE_WALK, 1.5f); - Reset(); - } - - Unit* pRyga; - - void Reset() - { - pRyga = NULL; - DoCast(me, SPELL_ANCESTRAL_WOLF_BUFF, true); - } - - void MoveInLineOfSight(Unit* pWho) - { - if (!pRyga && pWho->GetTypeId() == TYPEID_UNIT && pWho->GetEntry() == NPC_RYGA && me->IsWithinDistInMap(pWho, 15.0f)) - pRyga = pWho; - - npc_escortAI::MoveInLineOfSight(pWho); - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 0: - DoScriptText(EMOTE_WOLF_LIFT_HEAD, me); - break; - case 2: - DoScriptText(EMOTE_WOLF_HOWL, me); - break; - case 50: - if (pRyga && pRyga->isAlive() && !pRyga->isInCombat()) - DoScriptText(SAY_WOLF_WELCOME, pRyga); - break; - } - } -}; - -CreatureAI* GetAI_npc_ancestral_wolf(Creature* pCreature) -{ - return new npc_ancestral_wolfAI(pCreature); -} - -/*###### -## go_haaleshi_altar -######*/ - -bool GOHello_go_haaleshi_altar(Player* /*pPlayer*/, GameObject* pGo) -{ - pGo->SummonCreature(C_AERANAS,-1321.79, 4043.80, 116.24, 1.25, TEMPSUMMON_TIMED_DESPAWN, 180000); - return false; -} - -/*###### -## npc_naladu -######*/ - -#define GOSSIP_NALADU_ITEM1 "Why don't you escape?" - -enum eNaladu -{ - GOSSIP_TEXTID_NALADU1 = 9788 -}; - -bool GossipHello_npc_naladu(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_NALADU_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_naladu(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_NALADU1, pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_tracy_proudwell -######*/ - -#define GOSSIP_TEXT_REDEEM_MARKS "I have marks to redeem!" -#define GOSSIP_TRACY_PROUDWELL_ITEM1 "I heard that your dog Fei Fei took Klatu's prayer beads..." -#define GOSSIP_TRACY_PROUDWELL_ITEM2 "" - -enum eTracy -{ - GOSSIP_TEXTID_TRACY_PROUDWELL1 = 10689, - QUEST_DIGGING_FOR_PRAYER_BEADS = 10916 -}; - -bool GossipHello_npc_tracy_proudwell(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_REDEEM_MARKS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - if (pPlayer->GetQuestStatus(QUEST_DIGGING_FOR_PRAYER_BEADS) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TRACY_PROUDWELL_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_tracy_proudwell(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TRACY_PROUDWELL_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TRACY_PROUDWELL1, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - } - - return true; -} - -/*###### -## npc_trollbane -######*/ - -#define GOSSIP_TROLLBANE_ITEM1 "Tell me of the Sons of Lothar." -#define GOSSIP_TROLLBANE_ITEM2 "" -#define GOSSIP_TROLLBANE_ITEM3 "Tell me of your homeland." - -enum eTrollbane -{ - GOSSIP_TEXTID_TROLLBANE1 = 9932, - GOSSIP_TEXTID_TROLLBANE2 = 9933, - GOSSIP_TEXTID_TROLLBANE3 = 8772 -}; - -bool GossipHello_npc_trollbane(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TROLLBANE_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TROLLBANE_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_trollbane(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TROLLBANE_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TROLLBANE1, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TROLLBANE2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TROLLBANE3, pCreature->GetGUID()); - break; - } - - return true; -} - -/*###### -## npc_wounded_blood_elf -######*/ - -enum eWoundedBloodElf -{ - SAY_ELF_START = -1000117, - SAY_ELF_SUMMON1 = -1000118, - SAY_ELF_RESTING = -1000119, - SAY_ELF_SUMMON2 = -1000120, - SAY_ELF_COMPLETE = -1000121, - SAY_ELF_AGGRO = -1000122, - - QUEST_ROAD_TO_FALCON_WATCH = 9375 -}; - -struct npc_wounded_blood_elfAI : public npc_escortAI -{ - npc_wounded_blood_elfAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch (i) - { - case 0: - DoScriptText(SAY_ELF_START, me, pPlayer); - break; - case 9: - DoScriptText(SAY_ELF_SUMMON1, me, pPlayer); - // Spawn two Haal'eshi Talonguard - DoSpawnCreature(16967, -15, -15, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - DoSpawnCreature(16967, -17, -17, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; - case 13: - DoScriptText(SAY_ELF_RESTING, me, pPlayer); - break; - case 14: - DoScriptText(SAY_ELF_SUMMON2, me, pPlayer); - // Spawn two Haal'eshi Windwalker - DoSpawnCreature(16966, -15, -15, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - DoSpawnCreature(16966, -17, -17, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; - case 27: - DoScriptText(SAY_ELF_COMPLETE, me, pPlayer); - // Award quest credit - pPlayer->GroupEventHappens(QUEST_ROAD_TO_FALCON_WATCH,me); - break; - } - } - - void Reset() { } - - void EnterCombat(Unit* /*who*/) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - DoScriptText(SAY_ELF_AGGRO, me); - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } -}; - -CreatureAI* GetAI_npc_wounded_blood_elf(Creature* pCreature) -{ - return new npc_wounded_blood_elfAI(pCreature); -} - -bool QuestAccept_npc_wounded_blood_elf(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_ROAD_TO_FALCON_WATCH) - { - if (npc_escortAI* pEscortAI = CAST_AI(npc_wounded_blood_elfAI, pCreature->AI())) - pEscortAI->Start(true, false, pPlayer->GetGUID()); - - // Change faction so mobs attack - pCreature->setFaction(775); - } - - return true; -} - -/*###### -## npc_fel_guard_hound -######*/ - -enum eFelGuard -{ - SPELL_SUMMON_POO = 37688, - - NPC_DERANGED_HELBOAR = 16863 -}; - -struct npc_fel_guard_houndAI : public ScriptedAI -{ - npc_fel_guard_houndAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiCheckTimer; - uint64 uiHelboarGUID; - - void Reset() - { - uiCheckTimer = 5000; //check for creature every 5 sec - uiHelboarGUID = 0; - } - - void MovementInform(uint32 uiType, uint32 uiId) - { - if (uiType != POINT_MOTION_TYPE || uiId != 1) - return; - - if (Creature* pHelboar = me->GetCreature(*me,uiHelboarGUID)) - { - pHelboar->RemoveCorpse(); - DoCast(SPELL_SUMMON_POO); - - if (Player* pOwner = me->GetCharmerOrOwnerPlayerOrPlayerItself()) - me->GetMotionMaster()->MoveFollow(pOwner,0.0f,0.0f); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (uiCheckTimer <= uiDiff) - { - if (Creature* pHelboar = me->FindNearestCreature(NPC_DERANGED_HELBOAR, 10.0f, false)) - { - if (pHelboar->GetGUID() != uiHelboarGUID && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE && !me->FindCurrentSpellBySpellId(SPELL_SUMMON_POO)) - { - uiHelboarGUID = pHelboar->GetGUID(); - me->GetMotionMaster()->MovePoint(1,pHelboar->GetPositionX(),pHelboar->GetPositionY(),pHelboar->GetPositionZ()); - } - } - uiCheckTimer = 5000; - }else uiCheckTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_fel_guard_hound(Creature* pCreature) -{ - return new npc_fel_guard_houndAI(pCreature); -} - -void AddSC_hellfire_peninsula() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_aeranas"; - newscript->GetAI = &GetAI_npc_aeranas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ancestral_wolf"; - newscript->GetAI = &GetAI_npc_ancestral_wolf; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_haaleshi_altar"; - newscript->pGOHello = &GOHello_go_haaleshi_altar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_naladu"; - newscript->pGossipHello = &GossipHello_npc_naladu; - newscript->pGossipSelect = &GossipSelect_npc_naladu; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tracy_proudwell"; - newscript->pGossipHello = &GossipHello_npc_tracy_proudwell; - newscript->pGossipSelect = &GossipSelect_npc_tracy_proudwell; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_trollbane"; - newscript->pGossipHello = &GossipHello_npc_trollbane; - newscript->pGossipSelect = &GossipSelect_npc_trollbane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_wounded_blood_elf"; - newscript->GetAI = &GetAI_npc_wounded_blood_elf; - newscript->pQuestAccept = &QuestAccept_npc_wounded_blood_elf; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="npc_fel_guard_hound"; - newscript->GetAI = &GetAI_npc_fel_guard_hound; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/nagrand.cpp b/src/server/scripts/outland/nagrand.cpp deleted file mode 100644 index 700ba2cc120..00000000000 --- a/src/server/scripts/outland/nagrand.cpp +++ /dev/null @@ -1,886 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Nagrand -SD%Complete: 90 -SDComment: Quest support: 9849, 9868, 9918, 9874, 9991, 10107, 10108, 10044, 10172, 10646, 10085, 10987. TextId's unknown for altruis_the_sufferer and greatmother_geyah (npc_text) -SDCategory: Nagrand -EndScriptData */ - -/* ContentData -mob_shattered_rumbler -mob_lump -mob_sunspring_villager -npc_altruis_the_sufferer -npc_greatmother_geyah -npc_lantresor_of_the_blade -npc_maghar_captive -npc_creditmarker_visit_with_ancestors -mob_sparrowhawk -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## mob_shattered_rumbler - this should be done with ACID -######*/ - -struct mob_shattered_rumblerAI : public ScriptedAI -{ - bool Spawn; - - mob_shattered_rumblerAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - Spawn = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void SpellHit(Unit *Hitter, const SpellEntry *Spellkind) - { - if (Spellkind->Id == 32001 && !Spawn) - { - float x = me->GetPositionX(); - float y = me->GetPositionY(); - float z = me->GetPositionZ(); - - Hitter->SummonCreature(18181,x+(0.7 * (rand()%30)),y+(rand()%5),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - Hitter->SummonCreature(18181,x+(rand()%5),y-(rand()%5),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - Hitter->SummonCreature(18181,x-(rand()%5),y+(0.5 *(rand()%60)),z,0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - me->setDeathState(CORPSE); - Spawn = true; - } - return; - } -}; -CreatureAI* GetAI_mob_shattered_rumbler(Creature* pCreature) -{ - return new mob_shattered_rumblerAI (pCreature); -} - -/*###### -## mob_lump -######*/ - -#define SPELL_VISUAL_SLEEP 16093 -#define SPELL_SPEAR_THROW 32248 - -#define LUMP_SAY0 -1000190 -#define LUMP_SAY1 -1000191 - -#define LUMP_DEFEAT -1000192 - -#define GOSSIP_HL "I need answers, ogre!" -#define GOSSIP_SL1 "Why are Boulderfist out this far? You know that this is Kurenai territory." -#define GOSSIP_SL2 "And you think you can just eat anything you want? You're obviously trying to eat the Broken of Telaar." -#define GOSSIP_SL3 "This means war, Lump! War I say!" - -struct mob_lumpAI : public ScriptedAI -{ - mob_lumpAI(Creature *c) : ScriptedAI(c) - { - bReset = false; - } - - uint32 Reset_Timer; - uint32 Spear_Throw_Timer; - bool bReset; - - void Reset() - { - Reset_Timer = 60000; - Spear_Throw_Timer = 2000; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void AttackedBy(Unit* pAttacker) - { - if (me->getVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - - void DamageTaken(Unit *done_by, uint32 & damage) - { - if (done_by->GetTypeId() == TYPEID_PLAYER && (me->GetHealth() - damage)*100 / me->GetMaxHealth() < 30) - { - if (!bReset && CAST_PLR(done_by)->GetQuestStatus(9918) == QUEST_STATUS_INCOMPLETE) - { - //Take 0 damage - damage = 0; - - CAST_PLR(done_by)->AttackStop(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->setFaction(1080); //friendly - me->SetStandState(UNIT_STAND_STATE_SIT); - DoScriptText(LUMP_DEFEAT, me); - - bReset = true; - } - } - } - - void EnterCombat(Unit * /*who*/) - { - if (me->HasAura(SPELL_VISUAL_SLEEP)) - me->RemoveAura(SPELL_VISUAL_SLEEP); - - if (!me->IsStandState()) - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoScriptText(RAND(LUMP_SAY0,LUMP_SAY1), me); - } - - void UpdateAI(const uint32 diff) - { - //check if we waiting for a reset - if (bReset) - { - if (Reset_Timer <= diff) - { - EnterEvadeMode(); - bReset = false; - me->setFaction(1711); //hostile - return; - } - else Reset_Timer -= diff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Spear_Throw_Timer - if (Spear_Throw_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SPEAR_THROW); - Spear_Throw_Timer = 20000; - } else Spear_Throw_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_lump(Creature* pCreature) -{ - return new mob_lumpAI(pCreature); -} - -bool GossipHello_mob_lump(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(9918) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(9352, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_mob_lump(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(9353, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(9354, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(9355, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->SEND_GOSSIP_MENU(9356, pCreature->GetGUID()); - pPlayer->TalkedToCreature(18354, pCreature->GetGUID()); - break; - } - return true; -} - -/*#### -# mob_sunspring_villager - should be done with ACID -####*/ - -struct mob_sunspring_villagerAI : public ScriptedAI -{ - mob_sunspring_villagerAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - me->SetStandState(UNIT_STAND_STATE_DEAD); - } - - void EnterCombat(Unit * /*who*/) {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == 32146) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - } - } -}; -CreatureAI* GetAI_mob_sunspring_villager(Creature* pCreature) -{ - return new mob_sunspring_villagerAI (pCreature); -} - -/*###### -## npc_altruis_the_sufferer -######*/ - -#define GOSSIP_HATS1 "I see twisted steel and smell sundered earth." -#define GOSSIP_HATS2 "Well...?" -#define GOSSIP_HATS3 "[PH] Story about Illidan's Pupil" - -#define GOSSIP_SATS1 "Legion?" -#define GOSSIP_SATS2 "And now?" -#define GOSSIP_SATS3 "How do you see them now?" -#define GOSSIP_SATS4 "Forge camps?" -#define GOSSIP_SATS5 "Ok." -#define GOSSIP_SATS6 "[PH] Story done" - -bool GossipHello_npc_altruis_the_sufferer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - //gossip before obtaining Survey the Land - if (pPlayer->GetQuestStatus(9991) == QUEST_STATUS_NONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); - - //gossip when Survey the Land is incomplete (technically, after the flight) - if (pPlayer->GetQuestStatus(9991) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); - - //wowwiki.com/Varedis - if (pPlayer->GetQuestStatus(10646) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+30); - - pPlayer->SEND_GOSSIP_MENU(9419, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_altruis_the_sufferer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+10: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - pPlayer->SEND_GOSSIP_MENU(9420, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); - pPlayer->SEND_GOSSIP_MENU(9421, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+12: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); - pPlayer->SEND_GOSSIP_MENU(9422, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+13: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); - pPlayer->SEND_GOSSIP_MENU(9423, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+14: - pPlayer->SEND_GOSSIP_MENU(9424, pCreature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+20: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); - pPlayer->SEND_GOSSIP_MENU(9427, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+21: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(9991); - break; - - case GOSSIP_ACTION_INFO_DEF+30: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31); - pPlayer->SEND_GOSSIP_MENU(384, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+31: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(10646); - break; - } - return true; -} - -bool QuestAccept_npc_altruis_the_sufferer(Player* pPlayer, Creature* /*pCreature*/, Quest const * /*quest*/) -{ - if (!pPlayer->GetQuestRewardStatus(9991)) //Survey the Land, q-id 9991 - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(532); //TaxiPath 532 - } - return true; -} - -/*###### -## npc_greatmother_geyah -######*/ - -#define GOSSIP_HGG1 "Hello, Greatmother. Garrosh told me that you wanted to speak with me." -#define GOSSIP_HGG2 "Garrosh is beyond redemption, Greatmother. I fear that in helping the Mag'har, I have convinced Garrosh that he is unfit to lead." - -#define GOSSIP_SGG1 "You raised all of the orcs here, Greatmother?" -#define GOSSIP_SGG2 "Do you believe that?" -#define GOSSIP_SGG3 "What can be done? I have tried many different things. I have done my best to help the people of Nagrand. Each time I have approached Garrosh, he has dismissed me." -#define GOSSIP_SGG4 "Left? How can you choose to leave?" -#define GOSSIP_SGG5 "What is this duty?" -#define GOSSIP_SGG6 "Is there anything I can do for you, Greatmother?" -#define GOSSIP_SGG7 "I have done all that I could, Greatmother. I thank you for your kind words." -#define GOSSIP_SGG8 "Greatmother, you are the mother of Durotan?" -#define GOSSIP_SGG9 "Greatmother, I never had the honor. Durotan died long before my time, but his heroics are known to all on my world. The orcs of Azeroth reside in a place known as Durotar, named after your son. And ... (You take a moment to breathe and think through what you are about to tell the Greatmother.)" -#define GOSSIP_SGG10 "It is my Warchief, Greatmother. The leader of my people. From my world. He ... He is the son of Durotan. He is your grandchild." -#define GOSSIP_SGG11 "I will return to Azeroth at once, Greatmother." - -//all the textId's for the below is unknown, but i do believe the gossip item texts are proper. -bool GossipHello_npc_greatmother_geyah(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(10044) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HGG1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - } - else if (pPlayer->GetQuestStatus(10172) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HGG2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - } - else - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_greatmother_geyah(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 7: - pPlayer->AreaExploredOrEventHappens(10044); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - - case GOSSIP_ACTION_INFO_DEF + 10: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 11: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 12: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 13: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 14: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SGG11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 15: - pPlayer->AreaExploredOrEventHappens(10172); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - return true; -} - -/*###### -## npc_lantresor_of_the_blade -######*/ - -#define GOSSIP_HLB "I have killed many of your ogres, Lantresor. I have no fear." -#define GOSSIP_SLB1 "Should I know? You look like an orc to me." -#define GOSSIP_SLB2 "And the other half?" -#define GOSSIP_SLB3 "I have heard of your kind, but I never thought to see the day when I would meet a half-breed." -#define GOSSIP_SLB4 "My apologies. I did not mean to offend. I am here on behalf of my people." -#define GOSSIP_SLB5 "My people ask that you pull back your Boulderfist ogres and cease all attacks on our territories. In return, we will also pull back our forces." -#define GOSSIP_SLB6 "We will fight you until the end, then, Lantresor. We will not stand idly by as you pillage our towns and kill our people." -#define GOSSIP_SLB7 "What do I need to do?" - -bool GossipHello_npc_lantresor_of_the_blade(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(10107) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10108) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HLB, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(9361, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lantresor_of_the_blade(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(9362, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(9363, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(9364, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(9365, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - pPlayer->SEND_GOSSIP_MENU(9366, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - pPlayer->SEND_GOSSIP_MENU(9367, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - pPlayer->SEND_GOSSIP_MENU(9368, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->SEND_GOSSIP_MENU(9369, pCreature->GetGUID()); - if (pPlayer->GetQuestStatus(10107) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(10107); - if (pPlayer->GetQuestStatus(10108) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(10108); - break; - } - return true; -} - -/*##### -## npc_maghar_captive -#####*/ - -enum eMagharCaptive -{ - SAY_MAG_START = -1000482, - SAY_MAG_NO_ESCAPE = -1000483, - SAY_MAG_MORE = -1000484, - SAY_MAG_MORE_REPLY = -1000485, - SAY_MAG_LIGHTNING = -1000486, - SAY_MAG_SHOCK = -1000487, - SAY_MAG_COMPLETE = -1000488, - - SPELL_CHAIN_LIGHTNING = 16006, - SPELL_EARTHBIND_TOTEM = 15786, - SPELL_FROST_SHOCK = 12548, - SPELL_HEALING_WAVE = 12491, - - QUEST_TOTEM_KARDASH_H = 9868, - - NPC_MURK_RAIDER = 18203, - NPC_MURK_BRUTE = 18211, - NPC_MURK_SCAVENGER = 18207, - NPC_MURK_PUTRIFIER = 18202 -}; - -static float m_afAmbushA[]= {-1568.805786, 8533.873047, 1.958}; -static float m_afAmbushB[]= {-1491.554321, 8506.483398, 1.248}; - -struct npc_maghar_captiveAI : public npc_escortAI -{ - npc_maghar_captiveAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); } - - uint32 m_uiChainLightningTimer; - uint32 m_uiHealTimer; - uint32 m_uiFrostShockTimer; - - void Reset() - { - m_uiChainLightningTimer = 1000; - m_uiHealTimer = 0; - m_uiFrostShockTimer = 6000; - } - - void Aggro(Unit* /*pWho*/) - { - DoCast(me, SPELL_EARTHBIND_TOTEM, false); - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 7: - DoScriptText(SAY_MAG_MORE, me); - - if (Creature* pTemp = me->SummonCreature(NPC_MURK_PUTRIFIER, m_afAmbushB[0], m_afAmbushB[1], m_afAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000)) - DoScriptText(SAY_MAG_MORE_REPLY, pTemp); - - me->SummonCreature(NPC_MURK_PUTRIFIER, m_afAmbushB[0]-2.5f, m_afAmbushB[1]-2.5f, m_afAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - - me->SummonCreature(NPC_MURK_SCAVENGER, m_afAmbushB[0]+2.5f, m_afAmbushB[1]+2.5f, m_afAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(NPC_MURK_SCAVENGER, m_afAmbushB[0]+2.5f, m_afAmbushB[1]-2.5f, m_afAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 16: - DoScriptText(SAY_MAG_COMPLETE, me); - - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->GroupEventHappens(QUEST_TOTEM_KARDASH_H, me); - - SetRun(); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_MURK_BRUTE) - DoScriptText(SAY_MAG_NO_ESCAPE, pSummoned); - - if (pSummoned->isTotem()) - return; - - pSummoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pSummoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); - pSummoned->AI()->AttackStart(me); - - } - - void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_CHAIN_LIGHTNING) - { - if (rand()%10) - return; - - DoScriptText(SAY_MAG_LIGHTNING, me); - } - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - if (!me->getVictim()) - return; - - if (m_uiChainLightningTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); - m_uiChainLightningTimer = urand(7000, 14000); - } - else - m_uiChainLightningTimer -= uiDiff; - - if (me->GetHealth()*100 < me->GetMaxHealth()*30) - { - if (m_uiHealTimer <= uiDiff) - { - DoCast(me, SPELL_HEALING_WAVE); - m_uiHealTimer = 5000; - } - else - m_uiHealTimer -= uiDiff; - } - - if (m_uiFrostShockTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_FROST_SHOCK); - m_uiFrostShockTimer = urand(7500, 15000); - } - else - m_uiFrostShockTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -bool QuestAccept_npc_maghar_captive(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_TOTEM_KARDASH_H) - { - if (npc_maghar_captiveAI* pEscortAI = dynamic_cast(pCreature->AI())) - { - pCreature->SetStandState(UNIT_STAND_STATE_STAND); - pCreature->setFaction(232); - - pEscortAI->Start(true, false, pPlayer->GetGUID(), pQuest); - - DoScriptText(SAY_MAG_START, pCreature); - - pCreature->SummonCreature(NPC_MURK_RAIDER, m_afAmbushA[0]+2.5f, m_afAmbushA[1]-2.5f, m_afAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - pCreature->SummonCreature(NPC_MURK_PUTRIFIER, m_afAmbushA[0]-2.5f, m_afAmbushA[1]+2.5f, m_afAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - pCreature->SummonCreature(NPC_MURK_BRUTE, m_afAmbushA[0], m_afAmbushA[1], m_afAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - } - } - return true; -} - -CreatureAI* GetAI_npc_maghar_captive(Creature* pCreature) -{ - return new npc_maghar_captiveAI(pCreature); -} - -/*###### -## npc_creditmarker_visist_with_ancestors -######*/ - -struct npc_creditmarker_visit_with_ancestorsAI : public ScriptedAI -{ - npc_creditmarker_visit_with_ancestorsAI(Creature* c) : ScriptedAI(c) {} - - void Reset() {} - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (!who) - return; - - if (who->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(who)->GetQuestStatus(10085) == QUEST_STATUS_INCOMPLETE) - { - uint32 creditMarkerId = me->GetEntry(); - if ((creditMarkerId >= 18840) && (creditMarkerId <= 18843)) - { - // 18840: Sunspring, 18841: Laughing, 18842: Garadar, 18843: Bleeding - if (!CAST_PLR(who)->GetReqKillOrCastCurrentCount(10085, creditMarkerId)) - CAST_PLR(who)->KilledMonsterCredit(creditMarkerId, me->GetGUID()); - } - } - } - } -}; - -CreatureAI* GetAI_npc_creditmarker_visit_with_ancestors(Creature* pCreature) -{ - return new npc_creditmarker_visit_with_ancestorsAI (pCreature); -} - -/*###### -## mob_sparrowhawk -######*/ - -#define SPELL_SPARROWHAWK_NET 39810 -#define SPELL_ITEM_CAPTIVE_SPARROWHAWK 39812 - -struct mob_sparrowhawkAI : public ScriptedAI -{ - - mob_sparrowhawkAI(Creature *c) : ScriptedAI(c) {} - - uint32 Check_Timer; - uint64 PlayerGUID; - bool fleeing; - - void Reset() - { - me->RemoveAurasDueToSpell(SPELL_SPARROWHAWK_NET); - Check_Timer = 1000; - PlayerGUID = 0; - fleeing = false; - } - void AttackStart(Unit *who) - { - if (PlayerGUID) - return; - - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (!who || PlayerGUID) - return; - - if (!PlayerGUID && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 30) && CAST_PLR(who)->GetQuestStatus(10987) == QUEST_STATUS_INCOMPLETE) - { - PlayerGUID = who->GetGUID(); - return; - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - if (Check_Timer <= diff) - { - if (PlayerGUID) - { - if (fleeing && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != FLEEING_MOTION_TYPE) - fleeing = false; - - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer && me->IsWithinDistInMap(pPlayer, 30)) - { - if (!fleeing) - { - me->DeleteThreatList(); - me->GetMotionMaster()->MoveFleeing(pPlayer); - fleeing = true; - } - } - else if (fleeing) - { - me->GetMotionMaster()->MovementExpired(false); - PlayerGUID = 0; - fleeing = false; - } - } - Check_Timer = 1000; - } else Check_Timer -= diff; - - if (PlayerGUID) - return; - - ScriptedAI::UpdateAI(diff); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - if (spell->Id == SPELL_SPARROWHAWK_NET && CAST_PLR(caster)->GetQuestStatus(10987) == QUEST_STATUS_INCOMPLETE) - { - DoCast(caster, SPELL_ITEM_CAPTIVE_SPARROWHAWK, true); - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - } - return; - } -}; - -CreatureAI* GetAI_mob_sparrowhawk(Creature* pCreature) -{ - return new mob_sparrowhawkAI (pCreature); -} - -/*#### -# -####*/ - -void AddSC_nagrand() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_shattered_rumbler"; - newscript->GetAI = &GetAI_mob_shattered_rumbler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lump"; - newscript->GetAI = &GetAI_mob_lump; - newscript->pGossipHello = &GossipHello_mob_lump; - newscript->pGossipSelect = &GossipSelect_mob_lump; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_sunspring_villager"; - newscript->GetAI = &GetAI_mob_sunspring_villager; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_altruis_the_sufferer"; - newscript->pGossipHello = &GossipHello_npc_altruis_the_sufferer; - newscript->pGossipSelect = &GossipSelect_npc_altruis_the_sufferer; - newscript->pQuestAccept = &QuestAccept_npc_altruis_the_sufferer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_greatmother_geyah"; - newscript->pGossipHello = &GossipHello_npc_greatmother_geyah; - newscript->pGossipSelect = &GossipSelect_npc_greatmother_geyah; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lantresor_of_the_blade"; - newscript->pGossipHello = &GossipHello_npc_lantresor_of_the_blade; - newscript->pGossipSelect = &GossipSelect_npc_lantresor_of_the_blade; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_maghar_captive"; - newscript->GetAI = &GetAI_npc_maghar_captive; - newscript->pQuestAccept = &QuestAccept_npc_maghar_captive; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_creditmarker_visit_with_ancestors"; - newscript->GetAI = &GetAI_npc_creditmarker_visit_with_ancestors; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_sparrowhawk"; - newscript->GetAI = &GetAI_mob_sparrowhawk; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/netherstorm.cpp b/src/server/scripts/outland/netherstorm.cpp deleted file mode 100644 index efe18ad1908..00000000000 --- a/src/server/scripts/outland/netherstorm.cpp +++ /dev/null @@ -1,925 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Netherstorm -SD%Complete: 75 -SDComment: Quest support: 10337, 10438, 10652 (special flight paths), 10299,10321,10322,10323,10329,10330,10338,10365(Shutting Down Manaforge), 10198 -SDCategory: Netherstorm -EndScriptData */ - -/* ContentData -npc_manaforge_control_console -go_manaforge_control_console -npc_commander_dawnforge -npc_bessy -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_manaforge_control_console -######*/ - -//used by 20209,20417,20418,20440, signed for 20209 -#define EMOTE_START -1000211 -#define EMOTE_60 -1000212 -#define EMOTE_30 -1000213 -#define EMOTE_10 -1000214 -#define EMOTE_COMPLETE -1000215 -#define EMOTE_ABORT -1000216 - -#define ENTRY_BNAAR_C_CONSOLE 20209 -#define ENTRY_CORUU_C_CONSOLE 20417 -#define ENTRY_DURO_C_CONSOLE 20418 -#define ENTRY_ARA_C_CONSOLE 20440 - -#define ENTRY_SUNFURY_TECH 20218 -#define ENTRY_SUNFURY_PROT 20436 - -#define ENTRY_ARA_TECH 20438 -#define ENTRY_ARA_ENGI 20439 -#define ENTRY_ARA_GORKLONN 20460 - -#define SPELL_DISABLE_VISUAL 35031 -#define SPELL_INTERRUPT_1 35016 //ACID mobs should cast this -#define SPELL_INTERRUPT_2 35176 //ACID mobs should cast this (Manaforge Ara-version) - -struct npc_manaforge_control_consoleAI : public ScriptedAI -{ - npc_manaforge_control_consoleAI(Creature *c) : ScriptedAI(c) {} - - uint32 Event_Timer; - uint32 Wave_Timer; - uint32 Phase; - bool Wave; - uint64 someplayer; - uint64 goConsole; - Creature* add; - - void Reset() - { - Event_Timer = 3000; - Wave_Timer = 0; - Phase = 1; - Wave = false; - someplayer = 0; - goConsole = 0; - add = NULL; - } - - void EnterCombat(Unit * /*who*/) {} - - /*void SpellHit(Unit *caster, const SpellEntry *spell) - { - //we have no way of telling the Creature was hit by spell -> got aura applied after 10-12 seconds - //then no way for the mobs to actually stop the shutdown as intended. - if (spell->Id == SPELL_INTERRUPT_1) - DoSay("Silence! I kill you!",LANG_UNIVERSAL, NULL); - }*/ - - void JustDied(Unit* /*killer*/) - { - DoScriptText(EMOTE_ABORT, me); - - if (someplayer) - { - Unit* p = Unit::GetUnit((*me),someplayer); - if (p && p->GetTypeId() == TYPEID_PLAYER) - { - switch(me->GetEntry()) - { - case ENTRY_BNAAR_C_CONSOLE: - CAST_PLR(p)->FailQuest(10299); - CAST_PLR(p)->FailQuest(10329); - break; - case ENTRY_CORUU_C_CONSOLE: - CAST_PLR(p)->FailQuest(10321); - CAST_PLR(p)->FailQuest(10330); - break; - case ENTRY_DURO_C_CONSOLE: - CAST_PLR(p)->FailQuest(10322); - CAST_PLR(p)->FailQuest(10338); - break; - case ENTRY_ARA_C_CONSOLE: - CAST_PLR(p)->FailQuest(10323); - CAST_PLR(p)->FailQuest(10365); - break; - } - } - } - - if (goConsole) - { - if (GameObject* pGo = GameObject::GetGameObject((*me),goConsole)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); - } - } - - void DoWaveSpawnForCreature(Creature* pCreature) - { - switch(pCreature->GetEntry()) - { - case ENTRY_BNAAR_C_CONSOLE: - if (rand()%2) - { - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2933.68,4162.55,164.00,1.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2927.36,4212.97,164.00); - } - else - { - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2927.36,4212.97,164.00,4.94,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2933.68,4162.55,164.00); - } - Wave_Timer = 30000; - break; - case ENTRY_CORUU_C_CONSOLE: - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2445.21,2765.26,134.49,3.93,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2424.21,2740.15,133.81); - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2429.86,2731.85,134.53,1.31,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2435.37,2766.04,133.81); - Wave_Timer = 20000; - break; - case ENTRY_DURO_C_CONSOLE: - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2986.80,2205.36,165.37,3.74,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2985.15,2197.32,164.79); - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2952.91,2191.20,165.32,0.22,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2060.01,2185.27,164.67); - Wave_Timer = 15000; - break; - case ENTRY_ARA_C_CONSOLE: - if (rand()%2) - { - add = me->SummonCreature(ENTRY_ARA_TECH,4035.11,4038.97,194.27,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); - add = me->SummonCreature(ENTRY_ARA_TECH,4033.66,4036.79,194.28,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); - add = me->SummonCreature(ENTRY_ARA_TECH,4037.13,4037.30,194.23,2.57,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,4003.42,4040.19,193.49); - } - else - { - add = me->SummonCreature(ENTRY_ARA_TECH,3099.59,4049.30,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); - add = me->SummonCreature(ENTRY_ARA_TECH,3999.72,4046.75,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); - add = me->SummonCreature(ENTRY_ARA_TECH,3996.81,4048.26,194.22,0.05,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,4028.01,4035.17,193.59); - } - Wave_Timer = 15000; - break; - } - } - void DoFinalSpawnForCreature(Creature* pCreature) - { - switch(pCreature->GetEntry()) - { - case ENTRY_BNAAR_C_CONSOLE: - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2946.52,4201.42,163.47,3.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2927.49,4192.81,163.00); - break; - case ENTRY_CORUU_C_CONSOLE: - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2453.88,2737.85,133.27,2.59,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2441.62,2735.32,134.49,1.97,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2450.73,2754.50,134.49,3.29,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2433.96,2751.53,133.85); - break; - case ENTRY_DURO_C_CONSOLE: - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2956.18,2202.85,165.32,5.45,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); - add = me->SummonCreature(ENTRY_SUNFURY_TECH,2975.30,2211.50,165.32,4.55,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); - add = me->SummonCreature(ENTRY_SUNFURY_PROT,2965.02,2217.45,164.16,4.96,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,2972.27,2193.22,164.48); - break; - case ENTRY_ARA_C_CONSOLE: - add = me->SummonCreature(ENTRY_ARA_ENGI,3994.51,4020.46,192.18,0.91,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,4008.35,4035.04,192.70); - add = me->SummonCreature(ENTRY_ARA_GORKLONN,4021.56,4059.35,193.59,4.44,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 120000); - if (add) add->GetMotionMaster()->MovePoint(0,4016.62,4039.89,193.46); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (Event_Timer <= diff) - { - switch(Phase) - { - case 1: - if (someplayer) - { - Unit* u = Unit::GetUnit((*me), someplayer); - if (u && u->GetTypeId() == TYPEID_PLAYER) DoScriptText(EMOTE_START, me, u); - } - Event_Timer = 60000; - Wave = true; - ++Phase; - break; - case 2: - DoScriptText(EMOTE_60, me); - Event_Timer = 30000; - ++Phase; - break; - case 3: - DoScriptText(EMOTE_30, me); - Event_Timer = 20000; - DoFinalSpawnForCreature(me); - ++Phase; - break; - case 4: - DoScriptText(EMOTE_10, me); - Event_Timer = 10000; - Wave = false; - ++Phase; - break; - case 5: - DoScriptText(EMOTE_COMPLETE, me); - if (someplayer) - { - Unit* u = Unit::GetUnit((*me),someplayer); - if (u && u->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(u)->KilledMonsterCredit(me->GetEntry(),me->GetGUID()); - DoCast(me, SPELL_DISABLE_VISUAL); - } - if (goConsole) - { - if (GameObject* pGo = GameObject::GetGameObject((*me),goConsole)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); - } - ++Phase; - break; - } - } else Event_Timer -= diff; - - if (Wave) - { - if (Wave_Timer <= diff) - { - DoWaveSpawnForCreature(me); - } else Wave_Timer -= diff; - } - } -}; -CreatureAI* GetAI_npc_manaforge_control_console(Creature* pCreature) -{ - return new npc_manaforge_control_consoleAI (pCreature); -} - -/*###### -## go_manaforge_control_console -######*/ - -//TODO: clean up this workaround when Trinity adds support to do it properly (with gossip selections instead of instant summon) -bool GOHello_go_manaforge_control_console(Player* pPlayer, GameObject* pGo) -{ - if (pGo->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) - { - pPlayer->PrepareQuestMenu(pGo->GetGUID()); - pPlayer->SendPreparedQuest(pGo->GetGUID()); - } - - Creature* manaforge = NULL; - - switch(pGo->GetAreaId()) - { - case 3726: //b'naar - if ((pPlayer->GetQuestStatus(10299) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10329) == QUEST_STATUS_INCOMPLETE) && - pPlayer->HasItemCount(29366,1)) - manaforge = pPlayer->SummonCreature(ENTRY_BNAAR_C_CONSOLE,2918.95,4189.98,161.88,0.34,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); - break; - case 3730: //coruu - if ((pPlayer->GetQuestStatus(10321) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10330) == QUEST_STATUS_INCOMPLETE) && - pPlayer->HasItemCount(29396,1)) - manaforge = pPlayer->SummonCreature(ENTRY_CORUU_C_CONSOLE,2426.77,2750.38,133.24,2.14,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); - break; - case 3734: //duro - if ((pPlayer->GetQuestStatus(10322) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10338) == QUEST_STATUS_INCOMPLETE) && - pPlayer->HasItemCount(29397,1)) - manaforge = pPlayer->SummonCreature(ENTRY_DURO_C_CONSOLE,2976.48,2183.29,163.20,1.85,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); - break; - case 3722: //ara - if ((pPlayer->GetQuestStatus(10323) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10365) == QUEST_STATUS_INCOMPLETE) && - pPlayer->HasItemCount(29411,1)) - manaforge = pPlayer->SummonCreature(ENTRY_ARA_C_CONSOLE,4013.71,4028.76,192.10,1.25,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,125000); - break; - } - - if (manaforge) - { - CAST_AI(npc_manaforge_control_consoleAI, manaforge->AI())->someplayer = pPlayer->GetGUID(); - CAST_AI(npc_manaforge_control_consoleAI, manaforge->AI())->goConsole = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); - } - return true; -} - -/*###### -## npc_commander_dawnforge -######*/ - -// The Speech of Dawnforge, Ardonis & Pathaleon -#define SAY_COMMANDER_DAWNFORGE_1 -1000128 -#define SAY_ARCANIST_ARDONIS_1 -1000129 -#define SAY_COMMANDER_DAWNFORGE_2 -1000130 -#define SAY_PATHALEON_CULATOR_IMAGE_1 -1000131 -#define SAY_COMMANDER_DAWNFORGE_3 -1000132 -#define SAY_PATHALEON_CULATOR_IMAGE_2 -1000133 -#define SAY_PATHALEON_CULATOR_IMAGE_2_1 -1000134 -#define SAY_PATHALEON_CULATOR_IMAGE_2_2 -1000135 -#define SAY_COMMANDER_DAWNFORGE_4 -1000136 -#define SAY_ARCANIST_ARDONIS_2 -1000136 -#define SAY_COMMANDER_DAWNFORGE_5 -1000137 - -#define QUEST_INFO_GATHERING 10198 -#define SPELL_SUNFURY_DISGUISE 34603 - -// Entries of Arcanist Ardonis, Commander Dawnforge, Pathaleon the Curators Image -const uint32 CreatureEntry[3] = -{ - 19830, // Ardonis - 19831, // Dawnforge - 21504 // Pathaleon -}; - -struct npc_commander_dawnforgeAI : public ScriptedAI -{ - npc_commander_dawnforgeAI(Creature *c) : ScriptedAI(c) { Reset (); } - - uint64 PlayerGUID; - uint64 ardonisGUID; - uint64 pathaleonGUID; - - uint32 Phase; - uint32 PhaseSubphase; - uint32 Phase_Timer; - bool isEvent; - - float angle_dawnforge; - float angle_ardonis; - - void Reset() - { - PlayerGUID = 0; - ardonisGUID = 0; - pathaleonGUID = 0; - - Phase = 1; - PhaseSubphase = 0; - Phase_Timer = 4000; - isEvent = false; - } - - void EnterCombat(Unit * /*who*/) { } - - void JustSummoned(Creature *summoned) - { - pathaleonGUID = summoned->GetGUID(); - } - - // Emote Ardonis and Pathaleon - void Turn_to_Pathaleons_Image() - { - Creature *ardonis = Unit::GetCreature(*me,ardonisGUID); - Creature *pathaleon = Unit::GetCreature(*me,pathaleonGUID); - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - - if (!ardonis || !pathaleon || !pPlayer) - return; - - //Calculate the angle to Pathaleon - angle_dawnforge = me->GetAngle(pathaleon->GetPositionX(), pathaleon->GetPositionY()); - angle_ardonis = ardonis->GetAngle(pathaleon->GetPositionX(), pathaleon->GetPositionY()); - - //Turn Dawnforge and update - me->SetOrientation(angle_dawnforge); - me->SendUpdateToPlayer(pPlayer); - //Turn Ardonis and update - ardonis->SetOrientation(angle_ardonis); - ardonis->SendUpdateToPlayer(pPlayer); - - //Set them to kneel - me->SetStandState(UNIT_STAND_STATE_KNEEL); - ardonis->SetStandState(UNIT_STAND_STATE_KNEEL); - } - - //Set them back to each other - void Turn_to_eachother() - { - if (Unit *ardonis = Unit::GetUnit(*me,ardonisGUID)) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - - if (!pPlayer) - return; - - angle_dawnforge = me->GetAngle(ardonis->GetPositionX(), ardonis->GetPositionY()); - angle_ardonis = ardonis->GetAngle(me->GetPositionX(), me->GetPositionY()); - - //Turn Dawnforge and update - me->SetOrientation(angle_dawnforge); - me->SendUpdateToPlayer(pPlayer); - //Turn Ardonis and update - ardonis->SetOrientation(angle_ardonis); - ardonis->SendUpdateToPlayer(pPlayer); - - //Set state - me->SetStandState(UNIT_STAND_STATE_STAND); - ardonis->SetStandState(UNIT_STAND_STATE_STAND); - } - } - - bool CanStartEvent(Player* pPlayer) - { - if (!isEvent) - { - Creature* ardonis = me->FindNearestCreature(CreatureEntry[0], 10.0f); - if (!ardonis) - return false; - - ardonisGUID = ardonis->GetGUID(); - PlayerGUID = pPlayer->GetGUID(); - - isEvent = true; - - Turn_to_eachother(); - return true; - } - - debug_log("TSCR: npc_commander_dawnforge event already in progress, need to wait."); - return false; - } - - void UpdateAI(const uint32 diff) - { - //Is event even running? - if (!isEvent) - return; - - //Phase timing - if (Phase_Timer >= diff) - { - Phase_Timer -= diff; - return; - } - - Unit *ardonis = Unit::GetUnit(*me,ardonisGUID); - Unit *pathaleon = Unit::GetUnit(*me,pathaleonGUID); - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - - if (!ardonis || !pPlayer) - { - Reset(); - return; - } - - if (Phase > 4 && !pathaleon) - { - Reset(); - return; - } - - //Phase 1 Dawnforge say - switch (Phase) - { - case 1: - DoScriptText(SAY_COMMANDER_DAWNFORGE_1, me); - ++Phase; - Phase_Timer = 16000; - break; - //Phase 2 Ardonis say - case 2: - DoScriptText(SAY_ARCANIST_ARDONIS_1, ardonis); - ++Phase; - Phase_Timer = 16000; - break; - //Phase 3 Dawnforge say - case 3: - DoScriptText(SAY_COMMANDER_DAWNFORGE_2, me); - ++Phase; - Phase_Timer = 16000; - break; - //Phase 4 Pathaleon spawns up to phase 9 - case 4: - //spawn pathaleon's image - me->SummonCreature(CreatureEntry[2], 2325.851563, 2799.534668, 133.084229, 6.038996, TEMPSUMMON_TIMED_DESPAWN, 90000); - ++Phase; - Phase_Timer = 500; - break; - //Phase 5 Pathaleon say - case 5: - DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_1, pathaleon); - ++Phase; - Phase_Timer = 6000; - break; - //Phase 6 - case 6: - switch(PhaseSubphase) - { - //Subphase 1: Turn Dawnforge and Ardonis - case 0: - Turn_to_Pathaleons_Image(); - ++PhaseSubphase; - Phase_Timer = 8000; - break; - //Subphase 2 Dawnforge say - case 1: - DoScriptText(SAY_COMMANDER_DAWNFORGE_3, me); - PhaseSubphase = 0; - ++Phase; - Phase_Timer = 8000; - break; - } - break; - //Phase 7 Pathaleons say 3 Sentence, every sentence need a subphase - case 7: - switch(PhaseSubphase) - { - //Subphase 1 - case 0: - DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2, pathaleon); - ++PhaseSubphase; - Phase_Timer = 12000; - break; - //Subphase 2 - case 1: - DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2_1, pathaleon); - ++PhaseSubphase; - Phase_Timer = 16000; - break; - //Subphase 3 - case 2: - DoScriptText(SAY_PATHALEON_CULATOR_IMAGE_2_2, pathaleon); - PhaseSubphase = 0; - ++Phase; - Phase_Timer = 10000; - break; - } - break; - //Phase 8 Dawnforge & Ardonis say - case 8: - DoScriptText(SAY_COMMANDER_DAWNFORGE_4, me); - DoScriptText(SAY_ARCANIST_ARDONIS_2, ardonis); - ++Phase; - Phase_Timer = 4000; - break; - //Phase 9 Pathaleons Despawn, Reset Dawnforge & Ardonis angle - case 9: - Turn_to_eachother(); - //hide pathaleon, unit will despawn shortly - pathaleon->SetVisibility(VISIBILITY_OFF); - PhaseSubphase = 0; - ++Phase; - Phase_Timer = 3000; - break; - //Phase 10 Dawnforge say - case 10: - DoScriptText(SAY_COMMANDER_DAWNFORGE_5, me); - pPlayer->AreaExploredOrEventHappens(QUEST_INFO_GATHERING); - Reset(); - break; - } - } -}; - -CreatureAI* GetAI_npc_commander_dawnforge(Creature* pCreature) -{ - return new npc_commander_dawnforgeAI(pCreature); -} - -bool AreaTrigger_at_commander_dawnforge(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - //if player lost aura or not have at all, we should not try start event. - if (!pPlayer->HasAura(SPELL_SUNFURY_DISGUISE)) - return false; - - if (pPlayer->isAlive() && pPlayer->GetQuestStatus(QUEST_INFO_GATHERING) == QUEST_STATUS_INCOMPLETE) - { - Creature* Dawnforge = pPlayer->FindNearestCreature(CreatureEntry[1], 30.0f); - - if (!Dawnforge) - return false; - - if (CAST_AI(npc_commander_dawnforgeAI, Dawnforge->AI())->CanStartEvent(pPlayer)) - return true; - } - return false; -} - -/*###### -## npc_professor_dabiri -######*/ - -#define SPELL_PHASE_DISTRUPTOR 35780 -#define GOSSIP_ITEM "I need a new phase distruptor, Professor" -#define WHISPER_DABIRI -1000302 - -#define QUEST_DIMENSIUS 10439 -#define QUEST_ON_NETHERY_WINGS 10438 - -bool GossipHello_npc_professor_dabiri(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_ON_NETHERY_WINGS) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(29778, 1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_professor_dabiri(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pCreature->CastSpell(pPlayer, SPELL_PHASE_DISTRUPTOR, false); - pPlayer->CLOSE_GOSSIP_MENU(); - } - - return true; -} - -bool QuestAccept_npc_professor_dabiri(Player* pPlayer, Creature* pCreature, Quest const *quest) -{ - if (quest->GetQuestId() == QUEST_DIMENSIUS) - DoScriptText(WHISPER_DABIRI, pCreature, pPlayer); - - return true; -} - -/*###### -## mob_phase_hunter -######*/ - -#define QUEST_RECHARGING_THE_BATTERIES 10190 - -#define NPC_PHASE_HUNTER_ENTRY 18879 -#define NPC_DRAINED_PHASE_HUNTER_ENTRY 19595 - -#define EMOTE_WEAK -1000303 - -// Spells -#define SPELL_RECHARGING_BATTERY 34219 -#define SPELL_PHASE_SLIP 36574 -#define SPELL_MANA_BURN 13321 -#define SPELL_MATERIALIZE 34804 -#define SPELL_DE_MATERIALIZE 34814 - -struct mob_phase_hunterAI : public ScriptedAI -{ - mob_phase_hunterAI(Creature *c) : ScriptedAI(c) {} - - bool Weak; - bool Materialize; - bool Drained; - uint8 WeakPercent; - float HpPercent; - - Player *pPlayer; - uint64 PlayerGUID; - - uint32 ManaBurnTimer; - - void Reset() - { - Weak = false; - Materialize = false; - Drained = false; - WeakPercent = 25 + (rand() % 16); // 25-40 - HpPercent = 0.0f; - - PlayerGUID = 0; - - ManaBurnTimer = 5000 + (rand() % 3 * 1000); // 5-8 sec cd - - if (me->GetEntry() == NPC_DRAINED_PHASE_HUNTER_ENTRY) - me->UpdateEntry(NPC_PHASE_HUNTER_ENTRY); - } - - void EnterCombat(Unit * who) - { - if (who->GetTypeId() == TYPEID_PLAYER) - PlayerGUID = who->GetGUID(); - } - - void SpellHit(Unit * /*caster*/, const SpellEntry * /*spell*/) - { - DoCast(me, SPELL_DE_MATERIALIZE); - } - - void UpdateAI(const uint32 diff) - { - if (!Materialize) - { - DoCast(me, SPELL_MATERIALIZE); - Materialize = true; - } - - if (me->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED) || me->hasUnitState(UNIT_STAT_ROOT)) // if the mob is rooted/slowed by spells eg.: Entangling Roots, Frost Nova, Hamstring, Crippling Poison, etc. => remove it - DoCast(me, SPELL_PHASE_SLIP); - - if (!UpdateVictim()) - return; - - // some code to cast spell Mana Burn on random target which has mana - if (ManaBurnTimer <= diff) - { - std::list AggroList = me->getThreatManager().getThreatList(); - std::list UnitsWithMana; - - for (std::list::const_iterator itr = AggroList.begin(); itr != AggroList.end(); ++itr) - { - if (Unit *pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - if (pUnit->GetCreateMana() > 0) - UnitsWithMana.push_back(pUnit); - } - } - if (!UnitsWithMana.empty()) - { - std::list::const_iterator it = UnitsWithMana.begin(); - std::advance(it, rand() % UnitsWithMana.size()); - DoCast(*it, SPELL_MANA_BURN); - ManaBurnTimer = 8000 + (rand() % 10 * 1000); // 8-18 sec cd - } - else - ManaBurnTimer = 3500; - } else ManaBurnTimer -= diff; - - if (Player *pPlayer = Unit::GetPlayer(PlayerGUID)) // start: support for quest 10190 - { - if (!Weak && me->GetHealth() < (me->GetMaxHealth() / 100 * WeakPercent) - && pPlayer->GetQuestStatus(QUEST_RECHARGING_THE_BATTERIES) == QUEST_STATUS_INCOMPLETE) - { - DoScriptText(EMOTE_WEAK, me); - Weak = true; - } - if (Weak && !Drained && me->HasAura(SPELL_RECHARGING_BATTERY)) - { - Drained = true; - HpPercent = float(me->GetHealth()) / float(me->GetMaxHealth()); - - me->UpdateEntry(NPC_DRAINED_PHASE_HUNTER_ENTRY); - - me->SetHealth(me->GetMaxHealth() * HpPercent); - me->LowerPlayerDamageReq(me->GetMaxHealth() - me->GetHealth()); - me->SetInCombatWith(pPlayer); - } - } // end: support for quest 10190 - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_phase_hunter(Creature* pCreature) -{ - return new mob_phase_hunterAI (pCreature); -} - -/*###### -## npc_bessy -######*/ - -#define Q_ALMABTRIEB 10337 -#define N_THADELL 20464 -#define SPAWN_FIRST 20512 -#define SPAWN_SECOND 19881 -#define SAY_THADELL_1 -1000304 -#define SAY_THADELL_2 -1000305 - -struct npc_bessyAI : public npc_escortAI -{ - - npc_bessyAI(Creature *c) : npc_escortAI(c) {} - - void JustDied(Unit* /*killer*/) - { - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->FailQuest(Q_ALMABTRIEB); - } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 3: //first spawn - me->SummonCreature(SPAWN_FIRST, 2449.67, 2183.11, 96.85, 6.20, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(SPAWN_FIRST, 2449.53, 2184.43, 96.36, 6.27, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(SPAWN_FIRST, 2449.85, 2186.34, 97.57, 6.08, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - - case 7: - me->SummonCreature(SPAWN_SECOND, 2309.64, 2186.24, 92.25, 6.06, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(SPAWN_SECOND, 2309.25, 2183.46, 91.75, 6.22, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - - case 12: - if (pPlayer) - pPlayer->GroupEventHappens(Q_ALMABTRIEB, me); - if (Unit* Thadell = me->FindNearestCreature(N_THADELL, 30)) - DoScriptText(SAY_THADELL_1, me); break; - case 13: - if (Unit* Thadell = me->FindNearestCreature(N_THADELL, 30)) - DoScriptText(SAY_THADELL_2, me, pPlayer); break; - } - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void Reset() - { - me->RestoreFaction(); - } - -}; - -bool QuestAccept_npc_bessy(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == Q_ALMABTRIEB) - { - pCreature->setFaction(113); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - } - return true; -} - -CreatureAI* GetAI_npc_bessy(Creature* pCreature) -{ - return new npc_bessyAI(pCreature); -} - -/*###### -## -######*/ - -void AddSC_netherstorm() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_manaforge_control_console"; - newscript->pGOHello = &GOHello_go_manaforge_control_console; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_manaforge_control_console"; - newscript->GetAI = &GetAI_npc_manaforge_control_console; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_commander_dawnforge"; - newscript->GetAI = &GetAI_npc_commander_dawnforge; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_commander_dawnforge"; - newscript->pAreaTrigger = &AreaTrigger_at_commander_dawnforge; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_professor_dabiri"; - newscript->pGossipHello = &GossipHello_npc_professor_dabiri; - newscript->pGossipSelect = &GossipSelect_npc_professor_dabiri; - newscript->pQuestAccept = &QuestAccept_npc_professor_dabiri; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phase_hunter"; - newscript->GetAI = &GetAI_mob_phase_hunter; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_bessy"; - newscript->GetAI = &GetAI_npc_bessy; - newscript->pQuestAccept = &QuestAccept_npc_bessy; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/shadowmoon_valley.cpp b/src/server/scripts/outland/shadowmoon_valley.cpp deleted file mode 100644 index 0e2eb34f0fe..00000000000 --- a/src/server/scripts/outland/shadowmoon_valley.cpp +++ /dev/null @@ -1,1828 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Shadowmoon_Valley -SD%Complete: 100 -SDComment: Quest support: 10519, 10583, 10601, 10814, 10804, 10854, 10458, 10481, 10480, 11082, 10781, 10451. Vendor Drake Dealer Hurlunk. -SDCategory: Shadowmoon Valley -EndScriptData */ - -/* ContentData -mob_mature_netherwing_drake -mob_enslaved_netherwing_drake -npc_drake_dealer_hurlunk -npcs_flanis_swiftwing_and_kagrosh -npc_murkblood_overseer -npc_neltharaku -npc_karynaku -npc_oronok_tornheart -npc_overlord_morghor -npc_earthmender_wilda -mob_torloth_the_magnificent -mob_illidari_spawn -npc_lord_illidan_stormrage -go_crystal_prison -npc_enraged_spirit -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*##### -# mob_mature_netherwing_drake -#####*/ - -enum eMatureNetherwing -{ - SAY_JUST_EATEN = -1000222, - - SPELL_PLACE_CARCASS = 38439, - SPELL_JUST_EATEN = 38502, - SPELL_NETHER_BREATH = 38467, - POINT_ID = 1, - - GO_CARCASS = 185155, - - QUEST_KINDNESS = 10804, - NPC_EVENT_PINGER = 22131 -}; - -struct mob_mature_netherwing_drakeAI : public ScriptedAI -{ - mob_mature_netherwing_drakeAI(Creature* c) : ScriptedAI(c) { } - - uint64 uiPlayerGUID; - - bool bCanEat; - bool bIsEating; - - uint32 EatTimer; - uint32 CastTimer; - - void Reset() - { - uiPlayerGUID = 0; - - bCanEat = false; - bIsEating = false; - - EatTimer = 5000; - CastTimer = 5000; - } - - void SpellHit(Unit* pCaster, SpellEntry const* pSpell) - { - if (bCanEat || bIsEating) - return; - - if (pCaster->GetTypeId() == TYPEID_PLAYER && pSpell->Id == SPELL_PLACE_CARCASS && !me->HasAura(SPELL_JUST_EATEN)) - { - uiPlayerGUID = pCaster->GetGUID(); - bCanEat = true; - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == POINT_ID) - { - bIsEating = true; - EatTimer = 7000; - me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); - } - } - - void UpdateAI(const uint32 diff) - { - if (bCanEat || bIsEating) - { - if (EatTimer <= diff) - { - if (bCanEat && !bIsEating) - { - if (Unit* pUnit = Unit::GetUnit(*me, uiPlayerGUID)) - { - if (GameObject* pGo = pUnit->FindNearestGameObject(GO_CARCASS, 10)) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); - - me->GetMotionMaster()->MovePoint(POINT_ID, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ()); - } - } - bCanEat = false; - } - else if (bIsEating) - { - DoCast(me, SPELL_JUST_EATEN); - DoScriptText(SAY_JUST_EATEN, me); - - if (Player* pPlr = Unit::GetPlayer(uiPlayerGUID)) - { - pPlr->KilledMonsterCredit(NPC_EVENT_PINGER, me->GetGUID()); - - if (GameObject* pGo = pPlr->FindNearestGameObject(GO_CARCASS, 10)) - pGo->Delete(); - } - - Reset(); - me->GetMotionMaster()->Clear(); - } - } - else - EatTimer -= diff; - - return; - } - - if (!UpdateVictim()) - return; - - if (CastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_NETHER_BREATH); - CastTimer = 5000; - } else CastTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_mature_netherwing_drake(Creature* pCreature) -{ - return new mob_mature_netherwing_drakeAI(pCreature); -} - -/*### -# mob_enslaved_netherwing_drake -####*/ - -#define FACTION_DEFAULT 62 -#define FACTION_FRIENDLY 1840 // Not sure if this is correct, it was taken off of Mordenai. - -#define SPELL_HIT_FORCE_OF_NELTHARAKU 38762 -#define SPELL_FORCE_OF_NELTHARAKU 38775 - -#define CREATURE_DRAGONMAW_SUBJUGATOR 21718 -#define CREATURE_ESCAPE_DUMMY 22317 - -struct mob_enslaved_netherwing_drakeAI : public ScriptedAI -{ - mob_enslaved_netherwing_drakeAI(Creature* c) : ScriptedAI(c) - { - PlayerGUID = 0; - Tapped = false; - Reset(); - } - - uint64 PlayerGUID; - uint32 FlyTimer; - bool Tapped; - - void Reset() - { - if (!Tapped) - me->setFaction(FACTION_DEFAULT); - - FlyTimer = 10000; - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SetVisibility(VISIBILITY_ON); - } - - void SpellHit(Unit* caster, const SpellEntry* spell) - { - if (!caster) - return; - - if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_HIT_FORCE_OF_NELTHARAKU && !Tapped) - { - Tapped = true; - PlayerGUID = caster->GetGUID(); - - me->setFaction(FACTION_FRIENDLY); - DoCast(caster, SPELL_FORCE_OF_NELTHARAKU, true); - - Unit* Dragonmaw = me->FindNearestCreature(CREATURE_DRAGONMAW_SUBJUGATOR, 50); - - if (Dragonmaw) - { - me->AddThreat(Dragonmaw, 100000.0f); - AttackStart(Dragonmaw); - } - - HostileReference* ref = me->getThreatManager().getOnlineContainer().getReferenceByTarget(caster); - if (ref) - ref->removeReference(); - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - { - if (PlayerGUID) - { - Unit* plr = Unit::GetUnit((*me), PlayerGUID); - if (plr) - DoCast(plr, SPELL_FORCE_OF_NELTHARAKU, true); - - PlayerGUID = 0; - } - me->SetVisibility(VISIBILITY_OFF); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (Tapped) - if (FlyTimer <= diff) - { - Tapped = false; - if (PlayerGUID) - { - Player* plr = Unit::GetPlayer(PlayerGUID); - if (plr && plr->GetQuestStatus(10854) == QUEST_STATUS_INCOMPLETE) - { - DoCast(plr, SPELL_FORCE_OF_NELTHARAKU, true); - /* - float x,y,z; - me->GetPosition(x,y,z); - - float dx,dy,dz; - me->GetRandomPoint(x, y, z, 20, dx, dy, dz); - dz += 20; // so it's in the air, not ground*/ - - Position pos; - if (Unit* EscapeDummy = me->FindNearestCreature(CREATURE_ESCAPE_DUMMY, 30)) - EscapeDummy->GetPosition(&pos); - else - { - me->GetRandomNearPosition(pos, 20); - pos.m_positionZ += 25; - } - - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->GetMotionMaster()->MovePoint(1, pos); - } - } - } else FlyTimer -= diff; - return; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_enslaved_netherwing_drake(Creature* pCreature) -{ - return new mob_enslaved_netherwing_drakeAI(pCreature); -} - -/*##### -# mob_dragonmaw_peon -#####*/ - -struct mob_dragonmaw_peonAI : public ScriptedAI -{ - mob_dragonmaw_peonAI(Creature* c) : ScriptedAI(c) {} - - uint64 PlayerGUID; - bool Tapped; - uint32 PoisonTimer; - - void Reset() - { - PlayerGUID = 0; - Tapped = false; - PoisonTimer = 0; - } - - void SpellHit(Unit* caster, const SpellEntry* spell) - { - if (!caster) - return; - - if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == 40468 && !Tapped) - { - PlayerGUID = caster->GetGUID(); - - Tapped = true; - float x, y, z; - caster->GetClosePoint(x, y, z, me->GetObjectSize()); - - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->MovePoint(1, x, y, z); - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_EAT); - PoisonTimer = 15000; - } - } - - void UpdateAI(const uint32 diff) - { - if (PoisonTimer) - if (PoisonTimer <= diff) - { - if (PlayerGUID) - { - Player* plr = Unit::GetPlayer(PlayerGUID); - if (plr && plr->GetQuestStatus(11020) == QUEST_STATUS_INCOMPLETE) - plr->KilledMonsterCredit(23209, me->GetGUID()); - } - PoisonTimer = 0; - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } else PoisonTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_dragonmaw_peon(Creature* pCreature) -{ - return new mob_dragonmaw_peonAI(pCreature); -} - -/*###### -## npc_drake_dealer_hurlunk -######*/ - -bool GossipHello_npc_drake_dealer_hurlunk(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isVendor() && pPlayer->GetReputationRank(1015) == REP_EXALTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_drake_dealer_hurlunk(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_flanis_swiftwing_and_kagrosh -######*/ - -#define GOSSIP_HSK1 "Take Flanis's Pack" -#define GOSSIP_HSK2 "Take Kagrosh's Pack" - -bool GossipHello_npcs_flanis_swiftwing_and_kagrosh(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(10583) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(30658,1,true)) - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HSK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - if (pPlayer->GetQuestStatus(10601) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(30659,1,true)) - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HSK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npcs_flanis_swiftwing_and_kagrosh(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30658, 1, false); - if (msg == EQUIP_ERR_OK) - { - pPlayer->StoreNewItem(dest, 30658, 1, true); - pPlayer->PlayerTalkClass->ClearMenus(); - } - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30659, 1, false); - if (msg == EQUIP_ERR_OK) - { - pPlayer->StoreNewItem(dest, 30659, 1, true); - pPlayer->PlayerTalkClass->ClearMenus(); - } - } - return true; -} - -/*###### -## npc_murkblood_overseer -######*/ - -#define QUEST_11082 11082 - -#define GOSSIP_HMO "I am here for you, overseer." -#define GOSSIP_SMO1 "How dare you question an overseer of the Dragonmaw!" -#define GOSSIP_SMO2 "Who speaks of me? What are you talking about, broken?" -#define GOSSIP_SMO3 "Continue please." -#define GOSSIP_SMO4 "Who are these bidders?" -#define GOSSIP_SMO5 "Well... yes." - -bool GossipHello_npc_murkblood_overseer(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_11082) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HMO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_murkblood_overseer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - //correct id not known - pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - //correct id not known - pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - //correct id not known - pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - //correct id not known - pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SMO5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - //correct id not known - pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - //correct id not known - pPlayer->SEND_GOSSIP_MENU(10940, pCreature->GetGUID()); - pCreature->CastSpell(pPlayer,41121,false); - pPlayer->AreaExploredOrEventHappens(QUEST_11082); - break; - } - return true; -} - -/*###### -## npc_neltharaku -######*/ - -#define GOSSIP_HN "I am listening, dragon" -#define GOSSIP_SN1 "But you are dragons! How could orcs do this to you?" -#define GOSSIP_SN2 "Your mate?" -#define GOSSIP_SN3 "I have battled many beasts, dragon. I will help you." - -bool GossipHello_npc_neltharaku(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(10814) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_HN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(10613, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_neltharaku(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(10614, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(10615, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_SN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(10616, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(10814); - break; - } - return true; -} - -/*###### -## npc_oronok -######*/ - -#define GOSSIP_ORONOK1 "I am ready to hear your story, Oronok." -#define GOSSIP_ORONOK2 "How do I find the cipher?" -#define GOSSIP_ORONOK3 "How do you know all of this?" -#define GOSSIP_ORONOK4 "Yet what? What is it, Oronok?" -#define GOSSIP_ORONOK5 "Continue, please." -#define GOSSIP_ORONOK6 "So what of the cipher now? And your boys?" -#define GOSSIP_ORONOK7 "I will find your boys and the cipher, Oronok." - -bool GossipHello_npc_oronok_tornheart(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - if (pPlayer->GetQuestStatus(10519) == QUEST_STATUS_INCOMPLETE) - { - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(10312, pCreature->GetGUID()); - }else - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_oronok_tornheart(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(10313, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(10314, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(10315, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(10316, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(10317, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(10318, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(10519); - break; - } - return true; -} - -/*#### -# npc_karynaku -####*/ - -enum eKarynaku -{ - QUEST_ALLY_OF_NETHER = 10870, - - TAXI_PATH_ID = 649 -}; - -bool QuestAccept_npc_karynaku(Player* pPlayer, Creature* /*pCreature*/, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_ALLY_OF_NETHER) - pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID); //pPlayer->ActivateTaxiPathTo(649); - - return true; -} - -/*#### -# npc_overlord_morghor -####*/ - -#define QUEST_LORD_ILLIDAN_STORMRAGE 11108 - -#define C_ILLIDAN 22083 -#define C_YARZILL 23141 - -#define SPELL_ONE 39990 // Red Lightning Bolt -#define SPELL_TWO 41528 // Mark of Stormrage -#define SPELL_THREE 40216 // Dragonaw Faction -#define SPELL_FOUR 42016 // Dragonaw Trasform - -#define OVERLORD_SAY_1 -1100206 -#define OVERLORD_SAY_2 -1100207 -#define OVERLORD_SAY_3 -1100208 //signed for 28315 -#define OVERLORD_SAY_4 -1100209 -#define OVERLORD_SAY_5 -1100210 -#define OVERLORD_SAY_6 -1100211 - -#define OVERLORD_YELL_1 -1000212 -#define OVERLORD_YELL_2 -1000213 - -#define LORD_ILLIDAN_SAY_1 -1100214 -#define LORD_ILLIDAN_SAY_2 -1100215 -#define LORD_ILLIDAN_SAY_3 -1100216 -#define LORD_ILLIDAN_SAY_4 -1100217 -#define LORD_ILLIDAN_SAY_5 -1100218 -#define LORD_ILLIDAN_SAY_6 -1100219 -#define LORD_ILLIDAN_SAY_7 -1100220 - -#define YARZILL_THE_MERC_SAY -1100221 - -struct npc_overlord_morghorAI : public ScriptedAI -{ - npc_overlord_morghorAI(Creature *c) : ScriptedAI(c) {} - - uint64 PlayerGUID; - uint64 IllidanGUID; - - uint32 ConversationTimer; - uint32 Step; - - bool Event; - - void Reset() - { - PlayerGUID = 0; - IllidanGUID = 0; - - ConversationTimer = 0; - Step = 0; - - Event = false; - me->SetUInt32Value(UNIT_NPC_FLAGS, 2); - } - - void StartEvent() - { - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); - me->SetUInt32Value(UNIT_FIELD_BYTES_1,0); - Unit* Illidan = me->SummonCreature(C_ILLIDAN, -5107.83, 602.584, 85.2393, 4.92598, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Illidan) - { - IllidanGUID = Illidan->GetGUID(); - Illidan->SetVisibility(VISIBILITY_OFF); - } - if (PlayerGUID) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer) - DoScriptText(OVERLORD_SAY_1, me, pPlayer); - } - ConversationTimer = 4200; - Step = 0; - Event = true; - } - - uint32 NextStep(uint32 Step) - { - Unit* plr = Unit::GetUnit((*me), PlayerGUID); - - Unit* Illi = Unit::GetUnit((*me), IllidanGUID); - - if (!plr || !Illi) - { - EnterEvadeMode(); - return 0; - } - - switch(Step) - { - case 0: return 0; break; - case 1: me->GetMotionMaster()->MovePoint(0, -5104.41, 595.297, 85.6838); return 9000; break; - case 2: DoScriptText(OVERLORD_YELL_1, me, plr); return 4500; break; - case 3: me->SetInFront(plr); return 3200; break; - case 4: DoScriptText(OVERLORD_SAY_2, me, plr); return 2000; break; - case 5: Illi->SetVisibility(VISIBILITY_ON); - Illi->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); return 350; break; - case 6: - Illi->CastSpell(Illi, SPELL_ONE, true); - Illi->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - me->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); - return 2000; break; - case 7: DoScriptText(OVERLORD_YELL_2, me); return 4500; break; - case 8: me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); return 2500; break; - case 9: DoScriptText(OVERLORD_SAY_3, me); return 6500; break; - case 10: DoScriptText(LORD_ILLIDAN_SAY_1, Illi); return 5000; break; - case 11: DoScriptText(OVERLORD_SAY_4, me, plr); return 6000; break; - case 12: DoScriptText(LORD_ILLIDAN_SAY_2, Illi); return 5500; break; - case 13: DoScriptText(LORD_ILLIDAN_SAY_3, Illi); return 4000; break; - case 14: Illi->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); return 1500; break; - case 15: DoScriptText(LORD_ILLIDAN_SAY_4, Illi); return 1500; break; - case 16: - if (plr) - { - Illi->CastSpell(plr, SPELL_TWO, true); - plr->RemoveAurasDueToSpell(SPELL_THREE); - plr->RemoveAurasDueToSpell(SPELL_FOUR); - return 5000; - }else{ - CAST_PLR(plr)->FailQuest(QUEST_LORD_ILLIDAN_STORMRAGE); Step = 30; return 100; - } - break; - case 17: DoScriptText(LORD_ILLIDAN_SAY_5, Illi); return 5000; break; - case 18: DoScriptText(LORD_ILLIDAN_SAY_6, Illi); return 5000; break; - case 19: DoScriptText(LORD_ILLIDAN_SAY_7, Illi); return 5000; break; - case 20: - Illi->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - Illi->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - return 500; break; - case 21: DoScriptText(OVERLORD_SAY_5, me); return 500; break; - case 22: - Illi->SetVisibility(VISIBILITY_OFF); - Illi->setDeathState(JUST_DIED); - return 1000; break; - case 23: me->SetUInt32Value(UNIT_FIELD_BYTES_1,0); return 2000; break; - case 24: me->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); return 5000; break; - case 25: DoScriptText(OVERLORD_SAY_6, me); return 2000; break; - case 26: - if (plr) - CAST_PLR(plr)->GroupEventHappens(QUEST_LORD_ILLIDAN_STORMRAGE, me); - return 6000; break; - case 27: - { - Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); - if (Yarzill) - Yarzill->SetUInt64Value(UNIT_FIELD_TARGET, PlayerGUID); - return 500; } - break; - case 28: - plr->RemoveAurasDueToSpell(SPELL_TWO); - plr->RemoveAurasDueToSpell(41519); - plr->CastSpell(plr, SPELL_THREE, true); - plr->CastSpell(plr, SPELL_FOUR, true); - return 1000; break; - case 29: - { - Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); - if (Yarzill) - DoScriptText(YARZILL_THE_MERC_SAY, Yarzill, plr); - return 5000; } - break; - case 30: - { - Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); - if (Yarzill) - Yarzill->SetUInt64Value(UNIT_FIELD_TARGET, 0); - return 5000; } - break; - case 31: - { - Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); - if (Yarzill) - Yarzill->CastSpell(plr, 41540, true); - return 1000;} -break; - case 32: me->GetMotionMaster()->MovePoint(0, -5085.77, 577.231, 86.6719); return 5000; break; - case 33: Reset(); return 100; break; - - default : return 0; - } - } - - void UpdateAI(const uint32 diff) - { - if (!ConversationTimer) - return; - - if (ConversationTimer <= diff) - { - if (Event && IllidanGUID && PlayerGUID) - { - ConversationTimer = NextStep(++Step); - } - } else ConversationTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_overlord_morghor(Creature* pCreature) -{ -return new npc_overlord_morghorAI(pCreature); -} - -bool QuestAccept_npc_overlord_morghor(Player* pPlayer, Creature* pCreature, const Quest *_Quest) -{ - if (_Quest->GetQuestId() == QUEST_LORD_ILLIDAN_STORMRAGE) - { - CAST_AI(npc_overlord_morghorAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); - CAST_AI(npc_overlord_morghorAI, pCreature->AI())->StartEvent(); - return true; - } - return false; -} - -/*#### -# npc_earthmender_wilda -####*/ - -enum eEarthmender -{ - SAY_WIL_START = -1000381, - SAY_WIL_AGGRO1 = -1000382, - SAY_WIL_AGGRO2 = -1000383, - SAY_WIL_PROGRESS1 = -1000384, - SAY_WIL_PROGRESS2 = -1000385, - SAY_WIL_FIND_EXIT = -1000386, - SAY_WIL_PROGRESS4 = -1000387, - SAY_WIL_PROGRESS5 = -1000388, - SAY_WIL_JUST_AHEAD = -1000389, - SAY_WIL_END = -1000390, - - SPELL_CHAIN_LIGHTNING = 16006, - SPELL_EARTHBING_TOTEM = 15786, - SPELL_FROST_SHOCK = 12548, - SPELL_HEALING_WAVE = 12491, - - QUEST_ESCAPE_COILSCAR = 10451, - NPC_COILSKAR_ASSASSIN = 21044, - FACTION_EARTHEN = 1726 //guessed -}; - -struct npc_earthmender_wildaAI : public npc_escortAI -{ - npc_earthmender_wildaAI(Creature* pCreature) : npc_escortAI(pCreature) { } - - uint32 m_uiHealingTimer; - - void Reset() - { - m_uiHealingTimer = 0; - } - - void WaypointReached(uint32 uiPointId) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(uiPointId) - { - case 13: - DoScriptText(SAY_WIL_PROGRESS1, me, pPlayer); - DoSpawnAssassin(); - break; - case 14: - DoSpawnAssassin(); - break; - case 15: - DoScriptText(SAY_WIL_FIND_EXIT, me, pPlayer); - break; - case 19: - DoRandomSay(); - break; - case 20: - DoSpawnAssassin(); - break; - case 26: - DoRandomSay(); - break; - case 27: - DoSpawnAssassin(); - break; - case 33: - DoRandomSay(); - break; - case 34: - DoSpawnAssassin(); - break; - case 37: - DoRandomSay(); - break; - case 38: - DoSpawnAssassin(); - break; - case 39: - DoScriptText(SAY_WIL_JUST_AHEAD, me, pPlayer); - break; - case 43: - DoRandomSay(); - break; - case 44: - DoSpawnAssassin(); - break; - case 50: - DoScriptText(SAY_WIL_END, me, pPlayer); - - if (Player* pPlayer = GetPlayerForEscort()) - pPlayer->GroupEventHappens(QUEST_ESCAPE_COILSCAR, me); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_COILSKAR_ASSASSIN) - pSummoned->AI()->AttackStart(me); - } - - //this is very unclear, random say without no real relevance to script/event - void DoRandomSay() - { - DoScriptText(RAND(SAY_WIL_PROGRESS2,SAY_WIL_PROGRESS4,SAY_WIL_PROGRESS5), me); - } - - void DoSpawnAssassin() - { - //unknown where they actually appear - DoSummon(NPC_COILSKAR_ASSASSIN, me, 15.0f, 5000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT); - } - - void Aggro(Unit* pWho) - { - //don't always use - if (rand()%5) - return; - - //only aggro text if not player - if (pWho->GetTypeId() != TYPEID_PLAYER) - { - //appears to be random - if (urand(0,1)) - DoScriptText(RAND(SAY_WIL_AGGRO1, SAY_WIL_AGGRO2), pWho); - } - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - //TODO: add more abilities - if (me->GetHealth()*100 / me->GetMaxHealth() <= 30) - { - if (m_uiHealingTimer <= uiDiff) - { - DoCast(me, SPELL_HEALING_WAVE); - m_uiHealingTimer = 15000; - } - else - m_uiHealingTimer -= uiDiff; - } - } -}; - -CreatureAI* GetAI_npc_earthmender_wilda(Creature* pCreature) -{ - return new npc_earthmender_wildaAI(pCreature); -} - -bool QuestAccept_npc_earthmender_wilda(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_ESCAPE_COILSCAR) - { - DoScriptText(SAY_WIL_START, pCreature, pPlayer); - pCreature->setFaction(FACTION_EARTHEN); - - if (npc_earthmender_wildaAI* pEscortAI = CAST_AI(npc_earthmender_wildaAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID(), pQuest); - } - return true; -} - -/*##### -# Quest: Battle of the crimson watch -#####*/ - -/* ContentData -Battle of the crimson watch - creatures, gameobjects and defines -mob_illidari_spawn : Adds that are summoned in the Crimson Watch battle. -mob_torloth_the_magnificent : Final Creature that players have to face before quest is completed -npc_lord_illidan_stormrage : Creature that controls the event. -go_crystal_prison : GameObject that begins the event and hands out quest -EndContentData */ - -#define END_TEXT -1000366 //signed for 10646 - -#define QUEST_BATTLE_OF_THE_CRIMSON_WATCH 10781 -#define EVENT_AREA_RADIUS 65 //65yds -#define EVENT_COOLDOWN 30000 //in ms. appear after event completed or failed (should be = Adds despawn time) - -struct TorlothCinematic -{ - int32 TextId; - uint32 pCreature, Timer; -}; - -// Creature 0 - Torloth, 1 - Illidan -static TorlothCinematic TorlothAnim[]= -{ - {-1000367, 0, 2000}, - {-1000368, 1, 7000}, - {-1000369, 0, 3000}, - {NULL, 0, 2000}, // Torloth stand - {-1000370, 0, 1000}, - {NULL, 0, 3000}, - {NULL, 0, NULL} -}; - -struct Location -{ - float x, y, z, o; -}; - -//Cordinates for Spawns -static Location SpawnLocation[]= -{ - //Cords used for: - {-4615.8556, 1342.2532, 139.9, 1.612},//Illidari Soldier - {-4598.9365, 1377.3182, 139.9, 3.917},//Illidari Soldier - {-4598.4697, 1360.8999, 139.9, 2.427},//Illidari Soldier - {-4589.3599, 1369.1061, 139.9, 3.165},//Illidari Soldier - {-4608.3477, 1386.0076, 139.9, 4.108},//Illidari Soldier - {-4633.1889, 1359.8033, 139.9, 0.949},//Illidari Soldier - {-4623.5791, 1351.4574, 139.9, 0.971},//Illidari Soldier - {-4607.2988, 1351.6099, 139.9, 2.416},//Illidari Soldier - {-4633.7764, 1376.0417, 139.9, 5.608},//Illidari Soldier - {-4600.2461, 1369.1240, 139.9, 3.056},//Illidari Mind Breaker - {-4631.7808, 1367.9459, 139.9, 0.020},//Illidari Mind Breaker - {-4600.2461, 1369.1240, 139.9, 3.056},//Illidari Highlord - {-4631.7808, 1367.9459, 139.9, 0.020},//Illidari Highlord - {-4615.5586, 1353.0031, 139.9, 1.540},//Illidari Highlord - {-4616.4736, 1384.2170, 139.9, 4.971},//Illidari Highlord - {-4627.1240, 1378.8752, 139.9, 2.544} //Torloth The Magnificent -}; - -struct WaveData -{ - uint8 SpawnCount, UsedSpawnPoint; - uint32 CreatureId, SpawnTimer,YellTimer; - int32 WaveTextId; -}; - -static WaveData WavesInfo[]= -{ - {9, 0, 22075, 10000, 7000, -1000371}, //Illidari Soldier - {2, 9, 22074, 10000, 7000, -1000372}, //Illidari Mind Breaker - {4, 11, 19797, 10000, 7000, -1000373}, //Illidari Highlord - {1, 15, 22076, 10000, 7000, -1000374} //Torloth The Magnificent -}; - -struct SpawnSpells -{ - uint32 Timer1, Timer2, SpellId; -}; - -static SpawnSpells SpawnCast[]= -{ - {10000, 15000, 35871}, // Illidari Soldier Cast - Spellbreaker - {10000, 10000, 38985}, // Illidari Mind Breake Cast - Focused Bursts - {35000, 35000, 22884}, // Illidari Mind Breake Cast - Psychic Scream - {20000, 20000, 17194}, // Illidari Mind Breake Cast - Mind Blast - {8000, 15000, 38010}, // Illidari Highlord Cast - Curse of Flames - {12000, 20000, 16102}, // Illidari Highlord Cast - Flamestrike - {10000, 15000, 15284}, // Torloth the Magnificent Cast - Cleave - {18000, 20000, 39082}, // Torloth the Magnificent Cast - Shadowfury - {25000, 28000, 33961} // Torloth the Magnificent Cast - Spell Reflection -}; - -/*###### -# mob_illidari_spawn -######*/ - -struct mob_illidari_spawnAI : public ScriptedAI -{ - mob_illidari_spawnAI(Creature* c) : ScriptedAI(c) {} - - uint64 LordIllidanGUID; - uint32 SpellTimer1, SpellTimer2, SpellTimer3; - bool Timers; - - void Reset() - { - LordIllidanGUID = 0; - Timers = false; - } - - void EnterCombat(Unit* /*who*/) {} - void JustDied(Unit* slayer); - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!Timers) - { - if (me->GetEntry() == 22075)//Illidari Soldier - { - SpellTimer1 = SpawnCast[0].Timer1 + (rand()%4 * 1000); - } - if (me->GetEntry() == 22074)//Illidari Mind Breaker - { - SpellTimer1 = SpawnCast[1].Timer1 + (rand()%10 * 1000); - SpellTimer2 = SpawnCast[2].Timer1 + (rand()%4 * 1000); - SpellTimer3 = SpawnCast[3].Timer1 + (rand()%4 * 1000); - } - if (me->GetEntry() == 19797)// Illidari Highlord - { - SpellTimer1 = SpawnCast[4].Timer1 + (rand()%4 * 1000); - SpellTimer2 = SpawnCast[5].Timer1 + (rand()%4 * 1000); - } - Timers = true; - } - //Illidari Soldier - if (me->GetEntry() == 22075) - { - if (SpellTimer1 <= diff) - { - DoCast(me->getVictim(), SpawnCast[0].SpellId);//Spellbreaker - SpellTimer1 = SpawnCast[0].Timer2 + (rand()%5 * 1000); - } else SpellTimer1 -= diff; - } - //Illidari Mind Breaker - if (me->GetEntry() == 22074) - { - if (SpellTimer1 <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, SpawnCast[1].SpellId); //Focused Bursts - SpellTimer1 = SpawnCast[1].Timer2 + (rand()%5 * 1000); - } else SpellTimer1 = 2000; - } - } else SpellTimer1 -= diff; - - if (SpellTimer2 <= diff) - { - DoCast(me->getVictim(), SpawnCast[2].SpellId);//Psychic Scream - SpellTimer2 = SpawnCast[2].Timer2 + (rand()%13 * 1000); - } else SpellTimer2 -= diff; - - if (SpellTimer3 <= diff) - { - DoCast(me->getVictim(), SpawnCast[3].SpellId);//Mind Blast - SpellTimer3 = SpawnCast[3].Timer2 + (rand()%8 * 1000); - } else SpellTimer3 -= diff; - } - //Illidari Highlord - if (me->GetEntry() == 19797) - { - if (SpellTimer1 <= diff) - { - DoCast(me->getVictim(), SpawnCast[4].SpellId);//Curse Of Flames - SpellTimer1 = SpawnCast[4].Timer2 + (rand()%10 * 1000); - } else SpellTimer1 -= diff; - - if (SpellTimer2 <= diff) - { - DoCast(me->getVictim(), SpawnCast[5].SpellId);//Flamestrike - SpellTimer2 = SpawnCast[5].Timer2 + (rand()%7 * 13000); - } else SpellTimer2 -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -/*###### -# mob_torloth_the_magnificent -#####*/ - -struct mob_torloth_the_magnificentAI : public ScriptedAI -{ - mob_torloth_the_magnificentAI(Creature* c) : ScriptedAI(c) {} - - uint32 AnimationTimer, SpellTimer1, SpellTimer2, SpellTimer3; - - uint8 AnimationCount; - - uint64 LordIllidanGUID; - uint64 AggroTargetGUID; - - bool Timers; - - void Reset() - { - AnimationTimer = 4000; - AnimationCount = 0; - LordIllidanGUID = 0; - AggroTargetGUID = 0; - Timers = false; - - me->addUnitState(UNIT_STAT_ROOT); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - } - - void EnterCombat(Unit* /*who*/){} - - void HandleAnimation() - { - Creature* pCreature = me; - - if (TorlothAnim[AnimationCount].pCreature == 1) - { - pCreature = (Unit::GetCreature(*me, LordIllidanGUID)); - - if (!pCreature) - return; - } - - if (TorlothAnim[AnimationCount].TextId) - DoScriptText(TorlothAnim[AnimationCount].TextId, pCreature); - - AnimationTimer = TorlothAnim[AnimationCount].Timer; - - switch(AnimationCount) - { - case 0: - me->SetUInt32Value(UNIT_FIELD_BYTES_1,8); - break; - case 3: - me->RemoveFlag(UNIT_FIELD_BYTES_1,8); - break; - case 5: - if (Player* AggroTarget = (Unit::GetPlayer(AggroTargetGUID))) - { - me->SetUInt64Value(UNIT_FIELD_TARGET, AggroTarget->GetGUID()); - me->AddThreat(AggroTarget, 1); - me->HandleEmoteCommand(EMOTE_ONESHOT_POINT); - } - break; - case 6: - if (Player* AggroTarget = (Unit::GetPlayer(AggroTargetGUID))) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->clearUnitState(UNIT_STAT_ROOT); - - float x, y, z; - AggroTarget->GetPosition(x,y,z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - } - break; - } - ++AnimationCount; - } - - void UpdateAI(const uint32 diff) - { - if (AnimationTimer) - { - if (AnimationTimer <= diff) - { - HandleAnimation(); - } else AnimationTimer -= diff; - } - - if (AnimationCount < 6) - { - me->CombatStop(); - } else if (!Timers) - { - - SpellTimer1 = SpawnCast[6].Timer1; - SpellTimer2 = SpawnCast[7].Timer1; - SpellTimer3 = SpawnCast[8].Timer1; - Timers = true; - } - - if (Timers) - { - if (SpellTimer1 <= diff) - { - DoCast(me->getVictim(), SpawnCast[6].SpellId);//Cleave - SpellTimer1 = SpawnCast[6].Timer2 + (rand()%10 * 1000); - } else SpellTimer1 -= diff; - - if (SpellTimer2 <= diff) - { - DoCast(me->getVictim(), SpawnCast[7].SpellId);//Shadowfury - SpellTimer2 = SpawnCast[7].Timer2 + (rand()%5 * 1000); - } else SpellTimer2 -= diff; - - if (SpellTimer3 <= diff) - { - DoCast(me, SpawnCast[8].SpellId); - SpellTimer3 = SpawnCast[8].Timer2 + (rand()%7 * 1000);//Spell Reflection - } else SpellTimer3 -= diff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* slayer) - { - if (slayer) - switch(slayer->GetTypeId()) - { - case TYPEID_UNIT: - if (Unit *owner = slayer->GetOwner()) - if (owner->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(owner)->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, me); - break; - - case TYPEID_PLAYER: - CAST_PLR(slayer)->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, me); - break; - } - - if (Creature* LordIllidan = (Unit::GetCreature(*me, LordIllidanGUID))) - { - DoScriptText(END_TEXT, LordIllidan, slayer); - LordIllidan->AI()->EnterEvadeMode(); - } - } -}; - -/*##### -# npc_lord_illidan_stormrage -#####*/ - -struct npc_lord_illidan_stormrageAI : public ScriptedAI -{ - npc_lord_illidan_stormrageAI(Creature* c) : ScriptedAI(c) {} - - uint64 PlayerGUID; - - uint32 WaveTimer; - uint32 AnnounceTimer; - - int8 LiveCount; - uint8 WaveCount; - - bool EventStarted; - bool Announced; - bool Failed; - - void Reset() - { - PlayerGUID = 0; - - WaveTimer = 10000; - AnnounceTimer = 7000; - LiveCount = 0; - WaveCount = 0; - - EventStarted = false; - Announced = false; - Failed = false; - - me->SetVisibility(VISIBILITY_OFF); - } - - void EnterCombat(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - - void SummonNextWave() - { - uint8 count = WavesInfo[WaveCount].SpawnCount; - uint8 locIndex = WavesInfo[WaveCount].UsedSpawnPoint; - srand(time(NULL));//initializing random seed - uint8 FelguardCount = 0; - uint8 DreadlordCount = 0; - - for (uint8 i = 0; i < count; ++i) - { - Creature* Spawn = NULL; - float X = SpawnLocation[locIndex + i].x; - float Y = SpawnLocation[locIndex + i].y; - float Z = SpawnLocation[locIndex + i].z; - float O = SpawnLocation[locIndex + i].o; - Spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, X, Y, Z, O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); - ++LiveCount; - - if (Spawn) - { - Spawn->LoadCreaturesAddon(); - - if (WaveCount == 0)//1 Wave - { - if (rand()%3 == 1 && FelguardCount<2) - { - Spawn->SetDisplayId(18654); - ++FelguardCount; - } - else if (DreadlordCount < 3) - { - Spawn->SetDisplayId(19991); - ++DreadlordCount; - } - else if (FelguardCount<2) - { - Spawn->SetDisplayId(18654); - ++FelguardCount; - } - } - - if (WaveCount < 3)//1-3 Wave - { - if (PlayerGUID) - { - if (Player* pTarget = Unit::GetPlayer(PlayerGUID)) - { - float x, y, z; - pTarget->GetPosition(x,y,z); - Spawn->GetMotionMaster()->MovePoint(0,x, y, z); - } - } - CAST_AI(mob_illidari_spawnAI, Spawn->AI())->LordIllidanGUID = me->GetGUID(); - } - - if (WavesInfo[WaveCount].CreatureId == 22076) // Torloth - { - CAST_AI(mob_torloth_the_magnificentAI, Spawn->AI())->LordIllidanGUID = me->GetGUID(); - if (PlayerGUID) - CAST_AI(mob_torloth_the_magnificentAI, Spawn->AI())->AggroTargetGUID = PlayerGUID; - } - } - } - ++WaveCount; - WaveTimer = WavesInfo[WaveCount].SpawnTimer; - AnnounceTimer = WavesInfo[WaveCount].YellTimer; - } - - void CheckEventFail() - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - - if (!pPlayer) - return; - - if (Group *EventGroup = pPlayer->GetGroup()) - { - Player* GroupMember; - - uint8 GroupMemberCount = 0; - uint8 DeadMemberCount = 0; - uint8 FailedMemberCount = 0; - - const Group::MemberSlotList members = EventGroup->GetMemberSlots(); - - for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) - { - GroupMember = (Unit::GetPlayer(itr->guid)); - if (!GroupMember) - continue; - if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) - { - GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); - GroupMember->SetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, QUEST_STATUS_NONE); - ++FailedMemberCount; - } - ++GroupMemberCount; - - if (GroupMember->isDead()) - { - ++DeadMemberCount; - } - } - - if (GroupMemberCount == FailedMemberCount) - { - Failed = true; - } - - if (GroupMemberCount == DeadMemberCount) - { - for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) - { - GroupMember = Unit::GetPlayer(itr->guid); - - if (GroupMember && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) - { - GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); - GroupMember->SetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, QUEST_STATUS_NONE); - } - } - Failed = true; - } - } else if (pPlayer->isDead() || !pPlayer->IsWithinDistInMap(me, EVENT_AREA_RADIUS)) - { - pPlayer->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); - Failed = true; - } - } - - void LiveCounter() - { - --LiveCount; - if (!LiveCount) - Announced = false; - } - - void UpdateAI(const uint32 diff) - { - if (!PlayerGUID || !EventStarted) - return; - - if (!LiveCount && WaveCount < 4) - { - if (!Announced && AnnounceTimer <= diff) - { - DoScriptText(WavesInfo[WaveCount].WaveTextId, me); - Announced = true; - } else AnnounceTimer -= diff; - - if (WaveTimer <= diff) - { - SummonNextWave(); - } else WaveTimer -= diff; - } - CheckEventFail(); - - if (Failed) - EnterEvadeMode(); - } -}; - -void mob_illidari_spawnAI::JustDied(Unit * /*slayer*/) -{ - me->RemoveCorpse(); - if (Creature* LordIllidan = (Unit::GetCreature(*me, LordIllidanGUID))) - if (LordIllidan) - CAST_AI(npc_lord_illidan_stormrageAI, LordIllidan->AI())->LiveCounter(); -} - -/*##### -# go_crystal_prison -######*/ - -bool GOQuestAccept_GO_crystal_prison(Player* plr, GameObject* /*go*/, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_BATTLE_OF_THE_CRIMSON_WATCH) - { - Creature* Illidan = plr->FindNearestCreature(22083, 50); - - if (Illidan && !CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted) - { - CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->PlayerGUID = plr->GetGUID(); - CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->LiveCount = 0; - CAST_AI(npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted=true; - } - } - return true; -} - -CreatureAI* GetAI_npc_lord_illidan_stormrage(Creature* c) -{ - return new npc_lord_illidan_stormrageAI(c); -} - -CreatureAI* GetAI_mob_illidari_spawn(Creature* c) -{ - return new mob_illidari_spawnAI(c); -} - -CreatureAI* GetAI_mob_torloth_the_magnificent(Creature* c) -{ - return new mob_torloth_the_magnificentAI(c); -} - -/*#### -# npc_enraged_spirits -####*/ - -/* QUESTS */ -#define QUEST_ENRAGED_SPIRITS_FIRE_EARTH 10458 -#define QUEST_ENRAGED_SPIRITS_AIR 10481 -#define QUEST_ENRAGED_SPIRITS_WATER 10480 - -/* Totem */ -#define ENTRY_TOTEM_OF_SPIRITS 21071 -#define RADIUS_TOTEM_OF_SPIRITS 15 - -/* SPIRITS */ -#define ENTRY_ENRAGED_EARTH_SPIRIT 21050 -#define ENTRY_ENRAGED_FIRE_SPIRIT 21061 -#define ENTRY_ENRAGED_AIR_SPIRIT 21060 -#define ENTRY_ENRAGED_WATER_SPIRIT 21059 - -/* SOULS */ -#define ENTRY_EARTHEN_SOUL 21073 -#define ENTRY_FIERY_SOUL 21097 -#define ENTRY_ENRAGED_AIRY_SOUL 21116 -#define ENTRY_ENRAGED_WATERY_SOUL 21109 // wrong model - -/* SPELL KILLCREDIT - not working!?! - using KilledMonsterCredit */ -#define SPELL_EARTHEN_SOUL_CAPTURED_CREDIT 36108 -#define SPELL_FIERY_SOUL_CAPTURED_CREDIT 36117 -#define SPELL_AIRY_SOUL_CAPTURED_CREDIT 36182 -#define SPELL_WATERY_SOUL_CAPTURED_CREDIT 36171 - -/* KilledMonsterCredit Workaround */ -#define CREDIT_FIRE 21094 -#define CREDIT_WATER 21095 -#define CREDIT_AIR 21096 -#define CREDIT_EARTH 21092 - -/* Captured Spell/Buff */ -#define SPELL_SOUL_CAPTURED 36115 - -/* Factions */ -#define ENRAGED_SOUL_FRIENDLY 35 -#define ENRAGED_SOUL_HOSTILE 14 - -struct npc_enraged_spiritAI : public ScriptedAI -{ - npc_enraged_spiritAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - - void EnterCombat(Unit * /*who*/){} - - void JustDied(Unit* /*killer*/) - { - // always spawn spirit on death - // if totem around - // move spirit to totem and cast kill count - uint32 entry = 0; - uint32 credit = 0; - - switch(me->GetEntry()) { - case ENTRY_ENRAGED_FIRE_SPIRIT: - entry = ENTRY_FIERY_SOUL; - //credit = SPELL_FIERY_SOUL_CAPTURED_CREDIT; - credit = CREDIT_FIRE; - break; - case ENTRY_ENRAGED_EARTH_SPIRIT: - entry = ENTRY_EARTHEN_SOUL; - //credit = SPELL_EARTHEN_SOUL_CAPTURED_CREDIT; - credit = CREDIT_EARTH; - break; - case ENTRY_ENRAGED_AIR_SPIRIT: - entry = ENTRY_ENRAGED_AIRY_SOUL; - //credit = SPELL_AIRY_SOUL_CAPTURED_CREDIT; - credit = CREDIT_AIR; - break; - case ENTRY_ENRAGED_WATER_SPIRIT: - entry = ENTRY_ENRAGED_WATERY_SOUL; - //credit = SPELL_WATERY_SOUL_CAPTURED_CREDIT; - credit = CREDIT_WATER; - break; - } - - // Spawn Soul on Kill ALWAYS! - Creature* Summoned = NULL; - Unit* totemOspirits = NULL; - - if (entry != 0) - Summoned = DoSpawnCreature(entry, 0, 0, 1, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000); - - // FIND TOTEM, PROCESS QUEST - if (Summoned) - { - totemOspirits = me->FindNearestCreature(ENTRY_TOTEM_OF_SPIRITS, RADIUS_TOTEM_OF_SPIRITS); - if (totemOspirits) - { - Summoned->setFaction(ENRAGED_SOUL_FRIENDLY); - Summoned->GetMotionMaster()->MovePoint(0,totemOspirits->GetPositionX(), totemOspirits->GetPositionY(), Summoned->GetPositionZ()); - - Unit* Owner = totemOspirits->GetOwner(); - if (Owner && Owner->GetTypeId() == TYPEID_PLAYER) - // DoCast(Owner, credit); -- not working! - CAST_PLR(Owner)->KilledMonsterCredit(credit, Summoned->GetGUID()); - DoCast(totemOspirits, SPELL_SOUL_CAPTURED); - } - } - } -}; - -CreatureAI* GetAI_npc_enraged_spirit(Creature* pCreature) -{ -return new npc_enraged_spiritAI(pCreature); -} - -/*##### -# -######*/ - -void AddSC_shadowmoon_valley() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_mature_netherwing_drake"; - newscript->GetAI = &GetAI_mob_mature_netherwing_drake; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_enslaved_netherwing_drake"; - newscript->GetAI = &GetAI_mob_enslaved_netherwing_drake; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_dragonmaw_peon"; - newscript->GetAI = &GetAI_mob_dragonmaw_peon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_drake_dealer_hurlunk"; - newscript->pGossipHello = &GossipHello_npc_drake_dealer_hurlunk; - newscript->pGossipSelect = &GossipSelect_npc_drake_dealer_hurlunk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npcs_flanis_swiftwing_and_kagrosh"; - newscript->pGossipHello = &GossipHello_npcs_flanis_swiftwing_and_kagrosh; - newscript->pGossipSelect = &GossipSelect_npcs_flanis_swiftwing_and_kagrosh; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_murkblood_overseer"; - newscript->pGossipHello = &GossipHello_npc_murkblood_overseer; - newscript->pGossipSelect = &GossipSelect_npc_murkblood_overseer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_neltharaku"; - newscript->pGossipHello = &GossipHello_npc_neltharaku; - newscript->pGossipSelect = &GossipSelect_npc_neltharaku; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_karynaku"; - newscript->pQuestAccept = &QuestAccept_npc_karynaku; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_oronok_tornheart"; - newscript->pGossipHello = &GossipHello_npc_oronok_tornheart; - newscript->pGossipSelect = &GossipSelect_npc_oronok_tornheart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_overlord_morghor"; - newscript->GetAI = &GetAI_npc_overlord_morghor; - newscript->pQuestAccept = &QuestAccept_npc_overlord_morghor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_earthmender_wilda"; - newscript->GetAI = &GetAI_npc_earthmender_wilda; - newscript->pQuestAccept = &QuestAccept_npc_earthmender_wilda; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lord_illidan_stormrage"; - newscript->GetAI = &GetAI_npc_lord_illidan_stormrage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_crystal_prison"; - newscript->pGOQuestAccept = &GOQuestAccept_GO_crystal_prison; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_illidari_spawn"; - newscript->GetAI = &GetAI_mob_illidari_spawn; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_torloth_the_magnificent"; - newscript->GetAI = &GetAI_mob_torloth_the_magnificent; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_enraged_spirit"; - newscript->GetAI = &GetAI_npc_enraged_spirit; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/shattrath_city.cpp b/src/server/scripts/outland/shattrath_city.cpp deleted file mode 100644 index 6acc050db48..00000000000 --- a/src/server/scripts/outland/shattrath_city.cpp +++ /dev/null @@ -1,673 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Shattrath_City -SD%Complete: 100 -SDComment: Quest support: 10004, 10009, 10211, 10231. Flask vendors, Teleport to Caverns of Time -SDCategory: Shattrath City -EndScriptData */ - -/* ContentData -npc_raliq_the_drunk -npc_salsalabim -npc_shattrathflaskvendors -npc_zephyr -npc_kservant -npc_dirty_larry -npc_ishanah -npc_khadgar -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npc_raliq_the_drunk -######*/ - -#define GOSSIP_RALIQ "You owe Sim'salabim money. Hand them over or die!" - -enum eRaliq -{ - SPELL_UPPERCUT = 10966, - QUEST_CRACK_SKULLS = 10009, - FACTION_HOSTILE_RD = 45 -}; - -struct npc_raliq_the_drunkAI : public ScriptedAI -{ - npc_raliq_the_drunkAI(Creature* c) : ScriptedAI(c) - { - m_uiNormFaction = c->getFaction(); - } - - uint32 m_uiNormFaction; - uint32 Uppercut_Timer; - - void Reset() - { - Uppercut_Timer = 5000; - me->RestoreFaction(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Uppercut_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_UPPERCUT); - Uppercut_Timer = 15000; - } else Uppercut_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_raliq_the_drunk(Creature* pCreature) -{ - return new npc_raliq_the_drunkAI (pCreature); -} - -bool GossipHello_npc_raliq_the_drunk(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_RALIQ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(9440, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_raliq_the_drunk(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(FACTION_HOSTILE_RD); - pCreature->AI()->AttackStart(pPlayer); - } - return true; -} - -/*###### -# npc_salsalabim -######*/ - -#define FACTION_HOSTILE_SA 90 -#define FACTION_FRIENDLY_SA 35 -#define QUEST_10004 10004 - -#define SPELL_MAGNETIC_PULL 31705 - -struct npc_salsalabimAI : public ScriptedAI -{ - npc_salsalabimAI(Creature* c) : ScriptedAI(c) {} - - uint32 MagneticPull_Timer; - - void Reset() - { - MagneticPull_Timer = 15000; - me->RestoreFaction(); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetTypeId() == TYPEID_PLAYER) - if ((me->GetHealth()-damage)*100 / me->GetMaxHealth() < 20) - { - CAST_PLR(done_by)->GroupEventHappens(QUEST_10004,me); - damage = 0; - EnterEvadeMode(); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (MagneticPull_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MAGNETIC_PULL); - MagneticPull_Timer = 15000; - } else MagneticPull_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_salsalabim(Creature* pCreature) -{ - return new npc_salsalabimAI (pCreature); -} - -bool GossipHello_npc_salsalabim(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE) - { - pCreature->setFaction(FACTION_HOSTILE_SA); - pCreature->AI()->AttackStart(pPlayer); - } - else - { - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - } - return true; -} - -/* -################################################## -Shattrath City Flask Vendors provides flasks to people exalted with 3 factions: -Haldor the Compulsive -Arcanist Xorith -Both sell special flasks for use in Outlands 25man raids only, -purchasable for one Mark of Illidari each -Purchase requires exalted reputation with Scryers/Aldor, Cenarion Expedition and The Sha'tar -################################################## -*/ - -bool GossipHello_npc_shattrathflaskvendors(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->GetEntry() == 23484) - { - // Aldor vendor - if (pCreature->isVendor() && (pPlayer->GetReputationRank(932) == REP_EXALTED) && (pPlayer->GetReputationRank(935) == REP_EXALTED) && (pPlayer->GetReputationRank(942) == REP_EXALTED)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - pPlayer->SEND_GOSSIP_MENU(11085, pCreature->GetGUID()); - } - else - { - pPlayer->SEND_GOSSIP_MENU(11083, pCreature->GetGUID()); - } - } - - if (pCreature->GetEntry() == 23483) - { - // Scryers vendor - if (pCreature->isVendor() && (pPlayer->GetReputationRank(934) == REP_EXALTED) && (pPlayer->GetReputationRank(935) == REP_EXALTED) && (pPlayer->GetReputationRank(942) == REP_EXALTED)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - pPlayer->SEND_GOSSIP_MENU(11085, pCreature->GetGUID()); - } - else - { - pPlayer->SEND_GOSSIP_MENU(11084, pCreature->GetGUID()); - } - } - - return true; -} - -bool GossipSelect_npc_shattrathflaskvendors(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*###### -# npc_zephyr -######*/ - -#define GOSSIP_HZ "Take me to the Caverns of Time." - -bool GossipHello_npc_zephyr(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetReputationRank(989) >= REP_REVERED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HZ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_zephyr(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - pPlayer->CastSpell(pPlayer,37778,false); - - return true; -} - -/*###### -# npc_kservant -######*/ - -#define SAY1 -1000234 -#define WHISP1 -1000235 -#define WHISP2 -1000236 -#define WHISP3 -1000237 -#define WHISP4 -1000238 -#define WHISP5 -1000239 -#define WHISP6 -1000240 -#define WHISP7 -1000241 -#define WHISP8 -1000242 -#define WHISP9 -1000243 -#define WHISP10 -1000244 -#define WHISP11 -1000245 -#define WHISP12 -1000246 -#define WHISP13 -1000247 -#define WHISP14 -1000248 -#define WHISP15 -1000249 -#define WHISP16 -1000250 -#define WHISP17 -1000251 -#define WHISP18 -1000252 -#define WHISP19 -1000253 -#define WHISP20 -1000254 -#define WHISP21 -1000255 - -struct npc_kservantAI : public npc_escortAI -{ -public: - npc_kservantAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 0: DoScriptText(SAY1, me, pPlayer); break; - case 4: DoScriptText(WHISP1, me, pPlayer); break; - case 6: DoScriptText(WHISP2, me, pPlayer); break; - case 7: DoScriptText(WHISP3, me, pPlayer); break; - case 8: DoScriptText(WHISP4, me, pPlayer); break; - case 17: DoScriptText(WHISP5, me, pPlayer); break; - case 18: DoScriptText(WHISP6, me, pPlayer); break; - case 19: DoScriptText(WHISP7, me, pPlayer); break; - case 33: DoScriptText(WHISP8, me, pPlayer); break; - case 34: DoScriptText(WHISP9, me, pPlayer); break; - case 35: DoScriptText(WHISP10, me, pPlayer); break; - case 36: DoScriptText(WHISP11, me, pPlayer); break; - case 43: DoScriptText(WHISP12, me, pPlayer); break; - case 44: DoScriptText(WHISP13, me, pPlayer); break; - case 49: DoScriptText(WHISP14, me, pPlayer); break; - case 50: DoScriptText(WHISP15, me, pPlayer); break; - case 51: DoScriptText(WHISP16, me, pPlayer); break; - case 52: DoScriptText(WHISP17, me, pPlayer); break; - case 53: DoScriptText(WHISP18, me, pPlayer); break; - case 54: DoScriptText(WHISP19, me, pPlayer); break; - case 55: DoScriptText(WHISP20, me, pPlayer); break; - case 56: DoScriptText(WHISP21, me, pPlayer); - if (pPlayer) - pPlayer->GroupEventHappens(10211,me); - break; - } - } - - void MoveInLineOfSight(Unit* pWho) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - if (pWho->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(pWho)->GetQuestStatus(10211) == QUEST_STATUS_INCOMPLETE) - { - float Radius = 10.0; - if (me->IsWithinDistInMap(pWho, Radius)) - { - Start(false, false, pWho->GetGUID()); - } - } - } - } - - void Reset() {} -}; -CreatureAI* GetAI_npc_kservantAI(Creature* pCreature) -{ - return new npc_kservantAI(pCreature); -} - -/*###### -# npc_dirty_larry -######*/ - -#define GOSSIP_BOOK "Ezekiel said that you might have a certain book..." - -#define SAY_1 -1000274 -#define SAY_2 -1000275 -#define SAY_3 -1000276 -#define SAY_4 -1000277 -#define SAY_5 -1000278 -#define SAY_GIVEUP -1000279 - -#define QUEST_WBI 10231 -#define NPC_CREEPJACK 19726 -#define NPC_MALONE 19725 - -struct npc_dirty_larryAI : public ScriptedAI -{ - npc_dirty_larryAI(Creature* c) : ScriptedAI(c) {} - - bool Event; - bool Attack; - bool Done; - - uint64 PlayerGUID; - - uint32 SayTimer; - uint32 Step; - - void Reset() - { - Event = false; - Attack = false; - Done = false; - - PlayerGUID = 0; - SayTimer = 0; - Step = 0; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->setFaction(1194); - Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); - if (Creepjack) - { - CAST_CRE(Creepjack)->AI()->EnterEvadeMode(); - Creepjack->setFaction(1194); - Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); - if (Malone) - { - CAST_CRE(Malone)->AI()->EnterEvadeMode(); - Malone->setFaction(1194); - Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - - uint32 NextStep(uint32 Step) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - - switch(Step) - { - case 0:{ me->SetInFront(pPlayer); - Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); - if (Creepjack) - Creepjack->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); - if (Malone) - Malone->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); }return 2000; - case 1: DoScriptText(SAY_1, me, pPlayer); return 3000; - case 2: DoScriptText(SAY_2, me, pPlayer); return 5000; - case 3: DoScriptText(SAY_3, me, pPlayer); return 2000; - case 4: DoScriptText(SAY_4, me, pPlayer); return 2000; - case 5: DoScriptText(SAY_5, me, pPlayer); return 2000; - case 6: Attack = true; return 2000; - default: return 0; - } - } - - void EnterCombat(Unit* /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (SayTimer <= diff) - { - if (Event) - SayTimer = NextStep(++Step); - } else SayTimer -= diff; - - if (Attack) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pPlayer) - { - Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); - if (Creepjack) - { - Creepjack->Attack(pPlayer, true); - Creepjack->setFaction(14); - Creepjack->GetMotionMaster()->MoveChase(pPlayer); - Creepjack->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); - if (Malone) - { - Malone->Attack(pPlayer, true); - Malone->setFaction(14); - Malone->GetMotionMaster()->MoveChase(pPlayer); - Malone->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - DoStartMovement(pPlayer); - AttackStart(pPlayer); - } - Attack = false; - } - - if ((me->GetHealth()*100)/me->GetMaxHealth() < 5 && !Done) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAllAuras(); - - Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); - if (Creepjack) - { - CAST_CRE(Creepjack)->AI()->EnterEvadeMode(); - Creepjack->setFaction(1194); - Creepjack->GetMotionMaster()->MoveTargetedHome(); - Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); - if (Malone) - { - CAST_CRE(Malone)->AI()->EnterEvadeMode(); - Malone->setFaction(1194); - Malone->GetMotionMaster()->MoveTargetedHome(); - Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - me->setFaction(1194); - Done = true; - DoScriptText(SAY_GIVEUP, me, NULL); - me->DeleteThreatList(); - me->CombatStop(); - me->GetMotionMaster()->MoveTargetedHome(); - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer) - CAST_PLR(pPlayer)->GroupEventHappens(QUEST_WBI, me); - } - DoMeleeAttackIfReady(); - } -}; - -bool GossipHello_npc_dirty_larry(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_WBI) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BOOK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_dirty_larry(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - CAST_AI(npc_dirty_larryAI, pCreature->AI())->Event = true; - CAST_AI(npc_dirty_larryAI, pCreature->AI())->PlayerGUID = pPlayer->GetGUID(); - pPlayer->CLOSE_GOSSIP_MENU(); - } - - return true; -} - -CreatureAI* GetAI_npc_dirty_larryAI(Creature* pCreature) -{ - return new npc_dirty_larryAI (pCreature); -} - -/*###### -# npc_ishanah -######*/ - -#define ISANAH_GOSSIP_1 "Who are the Sha'tar?" -#define ISANAH_GOSSIP_2 "Isn't Shattrath a draenei city? Why do you allow others here?" - -bool GossipHello_npc_ishanah(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_ishanah(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - pPlayer->SEND_GOSSIP_MENU(9458, pCreature->GetGUID()); - else if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - pPlayer->SEND_GOSSIP_MENU(9459, pCreature->GetGUID()); - - return true; -} - -/*###### -# npc_khadgar -######*/ - -#define KHADGAR_GOSSIP_1 "I've heard your name spoken only in whispers, mage. Who are you?" -#define KHADGAR_GOSSIP_2 "Go on, please." -#define KHADGAR_GOSSIP_3 "I see." //6th too this -#define KHADGAR_GOSSIP_4 "What did you do then?" -#define KHADGAR_GOSSIP_5 "What happened next?" -#define KHADGAR_GOSSIP_7 "There was something else I wanted to ask you." - -bool GossipHello_npc_khadgar(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (!pPlayer->hasQuest(10211)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(9243, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_khadgar(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(9876, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(9877, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(9878, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(9879, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(9880, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - pPlayer->SEND_GOSSIP_MENU(9881, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, KHADGAR_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(9243, pCreature->GetGUID()); - break; - } - return true; -} - -void AddSC_shattrath_city() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_raliq_the_drunk"; - newscript->GetAI = &GetAI_npc_raliq_the_drunk; - newscript->pGossipHello = &GossipHello_npc_raliq_the_drunk; - newscript->pGossipSelect = &GossipSelect_npc_raliq_the_drunk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_salsalabim"; - newscript->GetAI = &GetAI_npc_salsalabim; - newscript->pGossipHello = &GossipHello_npc_salsalabim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_shattrathflaskvendors"; - newscript->pGossipHello = &GossipHello_npc_shattrathflaskvendors; - newscript->pGossipSelect = &GossipSelect_npc_shattrathflaskvendors; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_zephyr"; - newscript->pGossipHello = &GossipHello_npc_zephyr; - newscript->pGossipSelect = &GossipSelect_npc_zephyr; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_kservant"; - newscript->GetAI = &GetAI_npc_kservantAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dirty_larry"; - newscript->GetAI = &GetAI_npc_dirty_larryAI; - newscript->pGossipHello = &GossipHello_npc_dirty_larry; - newscript->pGossipSelect = &GossipSelect_npc_dirty_larry; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ishanah"; - newscript->pGossipHello = &GossipHello_npc_ishanah; - newscript->pGossipSelect = &GossipSelect_npc_ishanah; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_khadgar"; - newscript->pGossipHello = &GossipHello_npc_khadgar; - newscript->pGossipSelect = &GossipSelect_npc_khadgar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp b/src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp deleted file mode 100644 index 69dbc877d89..00000000000 --- a/src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Arcatraz -SD%Complete: 60 -SDComment: Warden Mellichar, event controller for Skyriss event. Millhouse Manastorm. TODO: make better combatAI for Millhouse. -SDCategory: Tempest Keep, The Arcatraz -EndScriptData */ - -/* ContentData -npc_millhouse_manastorm -npc_warden_mellichar -mob_zerekethvoidzone -EndContentData */ - -#include "ScriptedPch.h" -#include "arcatraz.h" - -/*##### -# npc_millhouse_manastorm -#####*/ - -#define SAY_INTRO_1 -1552010 -#define SAY_INTRO_2 -1552011 -#define SAY_WATER -1552012 -#define SAY_BUFFS -1552013 -#define SAY_DRINK -1552014 -#define SAY_READY -1552015 -#define SAY_KILL_1 -1552016 -#define SAY_KILL_2 -1552017 -#define SAY_PYRO -1552018 -#define SAY_ICEBLOCK -1552019 -#define SAY_LOWHP -1552020 -#define SAY_DEATH -1552021 -#define SAY_COMPLETE -1552022 - -#define SPELL_CONJURE_WATER 36879 -#define SPELL_ARCANE_INTELLECT 36880 -#define SPELL_ICE_ARMOR 36881 - -#define SPELL_ARCANE_MISSILES 33833 -#define SPELL_CONE_OF_COLD 12611 -#define SPELL_FIRE_BLAST 13341 -#define SPELL_FIREBALL 14034 -#define SPELL_FROSTBOLT 15497 -#define SPELL_PYROBLAST 33975 - -struct npc_millhouse_manastormAI : public ScriptedAI -{ - npc_millhouse_manastormAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 EventProgress_Timer; - uint32 Phase; - bool Init; - bool LowHp; - - uint32 Pyroblast_Timer; - uint32 Fireball_Timer; - - void Reset() - { - EventProgress_Timer = 2000; - LowHp = false; - Init = false; - Phase = 1; - - Pyroblast_Timer = 1000; - Fireball_Timer = 2500; - - if (pInstance) - { - if (pInstance->GetData(TYPE_WARDEN_2) == DONE) - Init = true; - - if (pInstance->GetData(TYPE_HARBINGERSKYRISS) == DONE) - { - DoScriptText(SAY_COMPLETE, me); - } - } - } - - void AttackStart(Unit* pWho) - { - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(pWho, 25.0f); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - /*for questId 10886 (heroic mode only) - if (pInstance && pInstance->GetData(TYPE_HARBINGERSKYRISS) != DONE) - ->FailQuest();*/ - } - - void UpdateAI(const uint32 diff) - { - if (!Init) - { - if (EventProgress_Timer <= diff) - { - if (Phase < 8) - { - switch(Phase) - { - case 1: - DoScriptText(SAY_INTRO_1, me); - EventProgress_Timer = 18000; - break; - case 2: - DoScriptText(SAY_INTRO_2, me); - EventProgress_Timer = 18000; - break; - case 3: - DoScriptText(SAY_WATER, me); - DoCast(me, SPELL_CONJURE_WATER); - EventProgress_Timer = 7000; - break; - case 4: - DoScriptText(SAY_BUFFS, me); - DoCast(me, SPELL_ICE_ARMOR); - EventProgress_Timer = 7000; - break; - case 5: - DoScriptText(SAY_DRINK, me); - DoCast(me, SPELL_ARCANE_INTELLECT); - EventProgress_Timer = 7000; - break; - case 6: - DoScriptText(SAY_READY, me); - EventProgress_Timer = 6000; - break; - case 7: - if (pInstance) - pInstance->SetData(TYPE_WARDEN_2,DONE); - Init = true; - break; - } - ++Phase; - } - } else EventProgress_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) - { - DoScriptText(SAY_LOWHP, me); - LowHp = true; - } - - if (Pyroblast_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoScriptText(SAY_PYRO, me); - - DoCast(me->getVictim(), SPELL_PYROBLAST); - Pyroblast_Timer = 40000; - } else Pyroblast_Timer -=diff; - - if (Fireball_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL); - Fireball_Timer = 4000; - } else Fireball_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_millhouse_manastorm(Creature* pCreature) -{ - return new npc_millhouse_manastormAI (pCreature); -} - -/*##### -# npc_warden_mellichar -#####*/ - -#define YELL_INTRO1 -1552023 -#define YELL_INTRO2 -1552024 -#define YELL_RELEASE1 -1552025 -#define YELL_RELEASE2A -1552026 -#define YELL_RELEASE2B -1552027 -#define YELL_RELEASE3 -1552028 -#define YELL_RELEASE4 -1552029 -#define YELL_WELCOME -1552030 - -//phase 2(acid mobs) -#define ENTRY_TRICKSTER 20905 -#define ENTRY_PH_HUNTER 20906 -//phase 3 -#define ENTRY_MILLHOUSE 20977 -//phase 4(acid mobs) -#define ENTRY_AKKIRIS 20908 -#define ENTRY_SULFURON 20909 -//phase 5(acid mobs) -#define ENTRY_TW_DRAK 20910 -#define ENTRY_BL_DRAK 20911 -//phase 6 -#define ENTRY_SKYRISS 20912 - -//TARGET_SCRIPT -#define SPELL_TARGET_ALPHA 36856 -#define SPELL_TARGET_BETA 36854 -#define SPELL_TARGET_DELTA 36857 -#define SPELL_TARGET_GAMMA 36858 -#define SPELL_TARGET_OMEGA 36852 -#define SPELL_BUBBLE_VISUAL 36849 - -struct npc_warden_mellicharAI : public ScriptedAI -{ - npc_warden_mellicharAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool IsRunning; - bool CanSpawn; - - uint32 EventProgress_Timer; - uint32 Phase; - - void Reset() - { - IsRunning = false; - CanSpawn = false; - - EventProgress_Timer = 22000; - Phase = 1; - - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - DoCast(me, SPELL_TARGET_OMEGA); - - if (pInstance) - pInstance->SetData(TYPE_HARBINGERSKYRISS,NOT_STARTED); - } - - void AttackStart(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (IsRunning) - return; - - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - if (who->GetTypeId() != TYPEID_PLAYER) - return; - - float attackRadius = me->GetAttackDistance(who)/10; - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - EnterCombat(who); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_INTRO1, me); - DoCast(me, SPELL_BUBBLE_VISUAL); - - if (pInstance) - { - pInstance->SetData(TYPE_HARBINGERSKYRISS,IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), false); - IsRunning = true; - } - } - - bool CanProgress() - { - if (pInstance) - { - if (Phase == 7 && pInstance->GetData(TYPE_WARDEN_4) == DONE) - return true; - if (Phase == 6 && pInstance->GetData(TYPE_WARDEN_3) == DONE) - return true; - if (Phase == 5 && pInstance->GetData(TYPE_WARDEN_2) == DONE) - return true; - if (Phase == 4) - return true; - if (Phase == 3 && pInstance->GetData(TYPE_WARDEN_1) == DONE) - return true; - if (Phase == 2 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS) - return true; - if (Phase == 1 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS) - return true; - return false; - } - return false; - } - - void DoPrepareForPhase() - { - if (pInstance) - { - me->InterruptNonMeleeSpells(true); - me->RemoveAurasByType(SPELL_AURA_DUMMY); - - switch(Phase) - { - case 2: - DoCast(me, SPELL_TARGET_ALPHA); - pInstance->SetData(TYPE_WARDEN_1,IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), false); - break; - case 3: - DoCast(me, SPELL_TARGET_BETA); - pInstance->SetData(TYPE_WARDEN_2,IN_PROGRESS); - break; - case 5: - DoCast(me, SPELL_TARGET_DELTA); - pInstance->SetData(TYPE_WARDEN_3,IN_PROGRESS); - break; - case 6: - DoCast(me, SPELL_TARGET_GAMMA); - pInstance->SetData(TYPE_WARDEN_4,IN_PROGRESS); - break; - case 7: - pInstance->SetData(TYPE_WARDEN_5,IN_PROGRESS); - break; - } - CanSpawn = true; - } - } - - void UpdateAI(const uint32 diff) - { - if (!IsRunning) - return; - - if (EventProgress_Timer <= diff) - { - if (pInstance) - { - if (pInstance->GetData(TYPE_HARBINGERSKYRISS) == FAIL) - { - Reset(); - return; - } - } - - if (CanSpawn) - { - //continue beam omega pod, unless we are about to summon skyriss - if (Phase != 7) - DoCast(me, SPELL_TARGET_OMEGA); - - switch(Phase) - { - case 2: - switch (urand(0,1)) - { - case 0: me->SummonCreature(ENTRY_TRICKSTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - case 1: me->SummonCreature(ENTRY_PH_HUNTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - } - break; - case 3: - me->SummonCreature(ENTRY_MILLHOUSE,413.292,-148.378,42.56,6.27,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); - break; - case 4: - DoScriptText(YELL_RELEASE2B, me); - break; - case 5: - switch (urand(0,1)) - { - case 0: me->SummonCreature(ENTRY_AKKIRIS,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - case 1: me->SummonCreature(ENTRY_SULFURON,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - } - break; - case 6: - switch (urand(0,1)) - { - case 0: me->SummonCreature(ENTRY_TW_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - case 1: me->SummonCreature(ENTRY_BL_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - } - break; - case 7: - me->SummonCreature(ENTRY_SKYRISS,445.763,-191.639,44.64,1.60,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); - DoScriptText(YELL_WELCOME, me); - break; - } - CanSpawn = false; - ++Phase; - } - if (CanProgress()) - { - switch(Phase) - { - case 1: - DoScriptText(YELL_INTRO2, me); - EventProgress_Timer = 10000; - ++Phase; - break; - case 2: - DoScriptText(YELL_RELEASE1, me); - DoPrepareForPhase(); - EventProgress_Timer = 7000; - break; - case 3: - DoScriptText(YELL_RELEASE2A, me); - DoPrepareForPhase(); - EventProgress_Timer = 10000; - break; - case 4: - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 5: - DoScriptText(YELL_RELEASE3, me); - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 6: - DoScriptText(YELL_RELEASE4, me); - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 7: - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - } - } - } else EventProgress_Timer -= diff; - } -}; -CreatureAI* GetAI_npc_warden_mellichar(Creature* pCreature) -{ - return new npc_warden_mellicharAI (pCreature); -} - -/*##### -# mob_zerekethvoidzone (this script probably not needed in future -> `creature_template_addon`.`auras`='36120 0') -#####*/ - -#define SPELL_VOID_ZONE_DAMAGE 36120 - -struct mob_zerekethvoidzoneAI : public ScriptedAI -{ - mob_zerekethvoidzoneAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - me->SetUInt32Value(UNIT_NPC_FLAGS,0); - me->setFaction(16); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - DoCast(me, SPELL_VOID_ZONE_DAMAGE); - } - - void EnterCombat(Unit* /*who*/) {} -}; -CreatureAI* GetAI_mob_zerekethvoidzoneAI(Creature* pCreature) -{ - return new mob_zerekethvoidzoneAI (pCreature); -} - -void AddSC_arcatraz() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_millhouse_manastorm"; - newscript->GetAI = &GetAI_npc_millhouse_manastorm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_warden_mellichar"; - newscript->GetAI = &GetAI_npc_warden_mellichar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_zerekethvoidzone"; - newscript->GetAI = &GetAI_mob_zerekethvoidzoneAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.h b/src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.h deleted file mode 100644 index 3f8dee8bbd0..00000000000 --- a/src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_ARCATRAZ_H -#define DEF_ARCATRAZ_H - -#define TYPE_ZEREKETH 1 -#define TYPE_DALLIAH 2 -#define TYPE_SOCCOTHRATES 3 -#define TYPE_HARBINGERSKYRISS 4 -#define TYPE_WARDEN_1 5 -#define TYPE_WARDEN_2 6 -#define TYPE_WARDEN_3 7 -#define TYPE_WARDEN_4 8 -#define TYPE_WARDEN_5 9 -#define DATA_MELLICHAR 10 -#define TYPE_SHIELD_OPEN 11 -#define DATA_SPHERE_SHIELD 12 -#endif - diff --git a/src/server/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp b/src/server/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp deleted file mode 100644 index 6576974f3ff..00000000000 --- a/src/server/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Harbinger_Skyriss -SD%Complete: 45 -SDComment: CombatAI not fully implemented. Timers will need adjustments. Need more docs on how event fully work. Reset all event and force start over if fail at one point? -SDCategory: Tempest Keep, The Arcatraz -EndScriptData */ - -/* ContentData -boss_harbinger_skyriss -boss_harbinger_skyriss_illusion -EndContentData */ - -#include "ScriptedPch.h" -#include "arcatraz.h" - -#define SAY_INTRO -1552000 -#define SAY_AGGRO -1552001 -#define SAY_KILL_1 -1552002 -#define SAY_KILL_2 -1552003 -#define SAY_MIND_1 -1552004 -#define SAY_MIND_2 -1552005 -#define SAY_FEAR_1 -1552006 -#define SAY_FEAR_2 -1552007 -#define SAY_IMAGE -1552008 -#define SAY_DEATH -1552009 - -#define SPELL_FEAR 39415 - -#define SPELL_MIND_REND 36924 -#define H_SPELL_MIND_REND 39017 - -#define SPELL_DOMINATION 37162 -#define H_SPELL_DOMINATION 39019 - -#define H_SPELL_MANA_BURN 39020 - -#define SPELL_66_ILLUSION 36931 //entry 21466 -#define SPELL_33_ILLUSION 36932 //entry 21467 - -struct boss_harbinger_skyrissAI : public ScriptedAI -{ - boss_harbinger_skyrissAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = false; - } - - ScriptedInstance *pInstance; - - bool Intro; - bool IsImage33; - bool IsImage66; - - uint32 Intro_Phase; - uint32 Intro_Timer; - uint32 MindRend_Timer; - uint32 Fear_Timer; - uint32 Domination_Timer; - uint32 ManaBurn_Timer; - - void Reset() - { - if (!Intro) - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); - - IsImage33 = false; - IsImage66 = false; - - Intro_Phase = 1; - Intro_Timer = 5000; - MindRend_Timer = 3000; - Fear_Timer = 15000; - Domination_Timer = 30000; - ManaBurn_Timer = 25000; - } - - void MoveInLineOfSight(Unit *who) - { - if (!Intro) - { - return; - } - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) {} - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - pInstance->SetData(TYPE_HARBINGERSKYRISS,DONE); - } - - void JustSummoned(Creature *summon) - { - if (!summon) - return; - if (IsImage66) - summon->SetHealth((summon->GetMaxHealth()*33)/100); - else - summon->SetHealth((summon->GetMaxHealth()*66)/100); - if (me->getVictim()) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - summon->AI()->AttackStart(pTarget); - } - - void KilledUnit(Unit* victim) - { - //won't yell killing pet/other unit - if (victim->GetEntry() == 21436) - return; - - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void DoSplit(uint32 val) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoScriptText(SAY_IMAGE, me); - - if (val == 66) - DoCast(me, SPELL_66_ILLUSION); - else - DoCast(me, SPELL_33_ILLUSION); - } - - void UpdateAI(const uint32 diff) - { - if (!Intro) - { - if (!pInstance) - return; - - if (Intro_Timer <= diff) - { - switch(Intro_Phase) - { - case 1: - DoScriptText(SAY_INTRO, me); - pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), true); - ++Intro_Phase; - Intro_Timer = 25000; - break; - case 2: - DoScriptText(SAY_AGGRO, me); - if (Unit *mellic = Unit::GetUnit(*me,pInstance->GetData64(DATA_MELLICHAR))) - { - //should have a better way to do this. possibly spell exist. - mellic->setDeathState(JUST_DIED); - mellic->SetHealth(0); - pInstance->SetData(TYPE_SHIELD_OPEN,IN_PROGRESS); - } - ++Intro_Phase; - Intro_Timer = 3000; - break; - case 3: - me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); - Intro = true; - break; - } - } else Intro_Timer -=diff; - } - - if (!UpdateVictim()) - return; - - if (!IsImage66 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 66)) - { - DoSplit(66); - IsImage66 = true; - } - if (!IsImage33 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 33)) - { - DoSplit(33); - IsImage33 = true; - } - - if (MindRend_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_MIND_REND); - else - DoCast(me->getVictim(), SPELL_MIND_REND); - - MindRend_Timer = 8000; - } else MindRend_Timer -=diff; - - if (Fear_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoScriptText(RAND(SAY_FEAR_1,SAY_FEAR_2), me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_FEAR); - else - DoCast(me->getVictim(), SPELL_FEAR); - - Fear_Timer = 25000; - } else Fear_Timer -=diff; - - if (Domination_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoScriptText(RAND(SAY_MIND_1,SAY_MIND_2), me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_DOMINATION); - else - DoCast(me->getVictim(), SPELL_DOMINATION); - - Domination_Timer = 16000+rand()%16000; - } else Domination_Timer -=diff; - - if (IsHeroic()) - { - if (ManaBurn_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, H_SPELL_MANA_BURN); - - ManaBurn_Timer = 16000+rand()%16000; - } else ManaBurn_Timer -=diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_harbinger_skyriss(Creature* pCreature) -{ - return new boss_harbinger_skyrissAI (pCreature); -} - -#define SPELL_MIND_REND_IMAGE 36929 -#define H_SPELL_MIND_REND_IMAGE 39021 - -struct boss_harbinger_skyriss_illusionAI : public ScriptedAI -{ - boss_harbinger_skyriss_illusionAI(Creature *c) : ScriptedAI(c) - { - } - - void Reset() { } - - void EnterCombat(Unit * /*who*/) { } -}; - -CreatureAI* GetAI_boss_harbinger_skyriss_illusion(Creature* pCreature) -{ - return new boss_harbinger_skyriss_illusionAI (pCreature); -} - -void AddSC_boss_harbinger_skyriss() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_harbinger_skyriss"; - newscript->GetAI = &GetAI_boss_harbinger_skyriss; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_harbinger_skyriss_illusion"; - newscript->GetAI = &GetAI_boss_harbinger_skyriss_illusion; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/arcatraz/instance_arcatraz.cpp b/src/server/scripts/outland/tempest_keep/arcatraz/instance_arcatraz.cpp deleted file mode 100644 index d16975e2af6..00000000000 --- a/src/server/scripts/outland/tempest_keep/arcatraz/instance_arcatraz.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Arcatraz -SD%Complete: 80 -SDComment: Mainly Harbringer Skyriss event -SDCategory: Tempest Keep, The Arcatraz -EndScriptData */ - -#include "ScriptedPch.h" -#include "arcatraz.h" - -#define MAX_ENCOUNTER 9 - -#define CONTAINMENT_CORE_SECURITY_FIELD_ALPHA 184318 //door opened when Wrath-Scryer Soccothrates dies -#define CONTAINMENT_CORE_SECURITY_FIELD_BETA 184319 //door opened when Dalliah the Doomsayer dies -#define POD_ALPHA 183961 //pod first boss wave -#define POD_BETA 183963 //pod second boss wave -#define POD_DELTA 183964 //pod third boss wave -#define POD_GAMMA 183962 //pod fourth boss wave -#define POD_OMEGA 183965 //pod fifth boss wave -#define WARDENS_SHIELD 184802 // warden shield -#define SEAL_SPHERE 184802 //shield 'protecting' mellichar - -#define MELLICHAR 20904 //skyriss will kill this unit - -/* Arcatraz encounters: -1 - Zereketh the Unbound event -2 - Dalliah the Doomsayer event -3 - Wrath-Scryer Soccothrates event -4 - Harbinger Skyriss event, 5 sub-events -*/ - -struct instance_arcatraz : public ScriptedInstance -{ - instance_arcatraz(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 Containment_Core_Security_Field_AlphaGUID; - uint64 Containment_Core_Security_Field_BetaGUID; - uint64 Pod_AlphaGUID; - uint64 Pod_GammaGUID; - uint64 Pod_BetaGUID; - uint64 Pod_DeltaGUID; - uint64 Pod_OmegaGUID; - uint64 Wardens_ShieldGUID; - uint64 GoSphereGUID; - uint64 MellicharGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Containment_Core_Security_Field_AlphaGUID = 0; - Containment_Core_Security_Field_BetaGUID = 0; - Pod_AlphaGUID = 0; - Pod_GammaGUID = 0; - Pod_BetaGUID = 0; - Pod_DeltaGUID = 0; - Pod_OmegaGUID = 0; - Wardens_ShieldGUID = 0; - GoSphereGUID = 0; - MellicharGUID = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case CONTAINMENT_CORE_SECURITY_FIELD_ALPHA: Containment_Core_Security_Field_AlphaGUID = pGo->GetGUID(); break; - case CONTAINMENT_CORE_SECURITY_FIELD_BETA: Containment_Core_Security_Field_BetaGUID = pGo->GetGUID(); break; - case POD_ALPHA: Pod_AlphaGUID = pGo->GetGUID(); break; - case POD_GAMMA: Pod_GammaGUID = pGo->GetGUID(); break; - case POD_BETA: Pod_BetaGUID = pGo->GetGUID(); break; - case POD_DELTA: Pod_DeltaGUID = pGo->GetGUID(); break; - case POD_OMEGA: Pod_OmegaGUID = pGo->GetGUID(); break; - case SEAL_SPHERE: GoSphereGUID = pGo->GetGUID(); break; - //case WARDENS_SHIELD: Wardens_ShieldGUID = pGo->GetGUID(); break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == MELLICHAR) - MellicharGUID = pCreature->GetGUID(); - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_ZEREKETH: - m_auiEncounter[0] = data; - break; - - case TYPE_DALLIAH: - if (data == DONE) - { - if (GameObject *pGo = instance->GetGameObject(Containment_Core_Security_Field_BetaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[1] = data; - break; - - case TYPE_SOCCOTHRATES: - if (data == DONE) - { - if (GameObject *pGo = instance->GetGameObject(Containment_Core_Security_Field_AlphaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[2] = data; - break; - - case TYPE_HARBINGERSKYRISS: - if (data == NOT_STARTED || data == FAIL) - { - m_auiEncounter[4] = NOT_STARTED; - m_auiEncounter[5] = NOT_STARTED; - m_auiEncounter[6] = NOT_STARTED; - m_auiEncounter[7] = NOT_STARTED; - m_auiEncounter[8] = NOT_STARTED; - } - m_auiEncounter[3] = data; - break; - - case TYPE_WARDEN_1: - if (data == IN_PROGRESS) - if (GameObject *pGo = instance->GetGameObject(Pod_AlphaGUID)) - pGo->UseDoorOrButton(); - m_auiEncounter[4] = data; - break; - - case TYPE_WARDEN_2: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Pod_BetaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[5] = data; - break; - - case TYPE_WARDEN_3: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Pod_DeltaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[6] = data; - break; - - case TYPE_WARDEN_4: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Pod_GammaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[7] = data; - break; - - case TYPE_WARDEN_5: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Pod_OmegaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[8] = data; - break; - - case TYPE_SHIELD_OPEN: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Wardens_ShieldGUID)) - pGo->UseDoorOrButton(); - } - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_HARBINGERSKYRISS: return m_auiEncounter[3]; - case TYPE_WARDEN_1: return m_auiEncounter[4]; - case TYPE_WARDEN_2: return m_auiEncounter[5]; - case TYPE_WARDEN_3: return m_auiEncounter[6]; - case TYPE_WARDEN_4: return m_auiEncounter[7]; - case TYPE_WARDEN_5: return m_auiEncounter[8]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_MELLICHAR: return MellicharGUID; - case DATA_SPHERE_SHIELD: return GoSphereGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_arcatraz(Map* pMap) -{ - return new instance_arcatraz(pMap); -} - -void AddSC_instance_arcatraz() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_arcatraz"; - newscript->GetInstanceData = &GetInstanceData_instance_arcatraz; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp b/src/server/scripts/outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp deleted file mode 100644 index 1a077036298..00000000000 --- a/src/server/scripts/outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_High_Botanist_Freywinn -SD%Complete: 90 -SDComment: some strange visual related to tree form(if aura lost before normal duration end). possible make summon&transform -process smoother(transform after delay) -SDCategory: Tempest Keep, The Botanica -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1553000 -#define SAY_KILL_1 -1553001 -#define SAY_KILL_2 -1553002 -#define SAY_TREE_1 -1553003 -#define SAY_TREE_2 -1553004 -#define SAY_DEATH -1553005 - -#define SPELL_TRANQUILITY 34550 -#define SPELL_TREE_FORM 34551 - -#define SPELL_SUMMON_FRAYER 34557 -#define ENTRY_FRAYER 19953 - -#define SPELL_PLANT_WHITE 34759 -#define SPELL_PLANT_GREEN 34761 -#define SPELL_PLANT_BLUE 34762 -#define SPELL_PLANT_RED 34763 - -struct boss_high_botanist_freywinnAI : public ScriptedAI -{ - boss_high_botanist_freywinnAI(Creature *c) : ScriptedAI(c) {} - - std::list Adds_List; - - uint32 SummonSeedling_Timer; - uint32 TreeForm_Timer; - uint32 MoveCheck_Timer; - uint32 DeadAddsCount; - bool MoveFree; - - void Reset() - { - Adds_List.clear(); - - SummonSeedling_Timer = 6000; - TreeForm_Timer = 30000; - MoveCheck_Timer = 1000; - DeadAddsCount = 0; - MoveFree = true; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == ENTRY_FRAYER) - Adds_List.push_back(summoned->GetGUID()); - } - - void DoSummonSeedling() - { - switch(rand()%4) - { - case 0: DoCast(me, SPELL_PLANT_WHITE); break; - case 1: DoCast(me, SPELL_PLANT_GREEN); break; - case 2: DoCast(me, SPELL_PLANT_BLUE); break; - case 3: DoCast(me, SPELL_PLANT_RED); break; - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (TreeForm_Timer <= diff) - { - DoScriptText(RAND(SAY_TREE_1,SAY_TREE_2), me); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - me->RemoveAllAuras(); - - DoCast(me, SPELL_SUMMON_FRAYER, true); - DoCast(me, SPELL_TRANQUILITY, true); - DoCast(me, SPELL_TREE_FORM, true); - - me->GetMotionMaster()->MoveIdle(); - MoveFree = false; - - TreeForm_Timer = 75000; - } else TreeForm_Timer -= diff; - - if (!MoveFree) - { - if (MoveCheck_Timer <= diff) - { - if (!Adds_List.empty()) - { - for (std::list::iterator itr = Adds_List.begin(); itr != Adds_List.end(); ++itr) - { - if (Unit *temp = Unit::GetUnit(*me,*itr)) - { - if (!temp->isAlive()) - { - Adds_List.erase(itr); - ++DeadAddsCount; - break; - } - } - } - } - - if (DeadAddsCount < 3 && TreeForm_Timer-30000 <= diff) - DeadAddsCount = 3; - - if (DeadAddsCount >= 3) - { - Adds_List.clear(); - DeadAddsCount = 0; - - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - MoveFree = true; - } - MoveCheck_Timer = 500; - } - else MoveCheck_Timer -= diff; - - return; - } - - /*if (me->HasAura(SPELL_TREE_FORM,0) || me->HasAura(SPELL_TRANQUILITY,0)) - return;*/ - - //one random seedling every 5 secs, but not in tree form - if (SummonSeedling_Timer <= diff) - { - DoSummonSeedling(); - SummonSeedling_Timer = 6000; - } else SummonSeedling_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_high_botanist_freywinn(Creature* pCreature) -{ - return new boss_high_botanist_freywinnAI (pCreature); -} - -void AddSC_boss_high_botanist_freywinn() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_high_botanist_freywinn"; - newscript->GetAI = &GetAI_boss_high_botanist_freywinn; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/botanica/boss_laj.cpp b/src/server/scripts/outland/tempest_keep/botanica/boss_laj.cpp deleted file mode 100644 index cbf21c2f992..00000000000 --- a/src/server/scripts/outland/tempest_keep/botanica/boss_laj.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Laj -SD%Complete: 90 -SDComment: Immunities are wrong, must be adjusted to use resistance from creature_templates. Most spells require database support. -SDCategory: Tempest Keep, The Botanica -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_SUMMON -1553006 - -#define SPELL_ALLERGIC_REACTION 34697 -#define SPELL_TELEPORT_SELF 34673 - -#define SPELL_SUMMON_LASHER_1 34681 -#define SPELL_SUMMON_FLAYER_1 34682 -#define SPELL_SUMMON_LASHER_2 34684 -#define SPELL_SUMMON_FLAYER_2 34685 -#define SPELL_SUMMON_LASHER_3 34686 -#define SPELL_SUMMON_FLAYER_4 34687 -#define SPELL_SUMMON_LASHER_4 34688 -#define SPELL_SUMMON_FLAYER_3 34690 - -#define MODEL_DEFAULT 13109 -#define MODEL_ARCANE 14213 -#define MODEL_FIRE 13110 -#define MODEL_FROST 14112 -#define MODEL_NATURE 14214 - -struct boss_lajAI : public ScriptedAI -{ - boss_lajAI(Creature *c) : ScriptedAI(c) {} - - bool CanSummon; - uint32 Teleport_Timer; - uint32 Summon_Timer; - uint32 Transform_Timer; - uint32 Allergic_Timer; - - void Reset() - { - me->SetDisplayId(MODEL_DEFAULT); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - - CanSummon = false; - Teleport_Timer = 20000; - Summon_Timer = 2500; - Transform_Timer = 30000; - Allergic_Timer = 5000; - } - - void DoTransform() - { - switch(rand()%5) - { - case 0: - me->SetDisplayId(MODEL_DEFAULT); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - break; - case 1: - me->SetDisplayId(MODEL_ARCANE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - break; - case 2: - me->SetDisplayId(MODEL_FIRE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - break; - case 3: - me->SetDisplayId(MODEL_FROST); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - break; - case 4: - me->SetDisplayId(MODEL_NATURE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - break; - } - } - - void DoSummons() - { - switch(rand()%4) - { - case 0: - DoCast(me, SPELL_SUMMON_LASHER_1, true); - DoCast(me, SPELL_SUMMON_FLAYER_1, true); - break; - case 1: - DoCast(me, SPELL_SUMMON_LASHER_2, true); - DoCast(me, SPELL_SUMMON_FLAYER_2, true); - break; - case 2: - DoCast(me, SPELL_SUMMON_LASHER_3, true); - DoCast(me, SPELL_SUMMON_FLAYER_3, true); - break; - case 3: - DoCast(me, SPELL_SUMMON_LASHER_4, true); - DoCast(me, SPELL_SUMMON_FLAYER_4, true); - break; - } - CanSummon = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustSummoned(Creature *summon) - { - if (summon && me->getVictim()) - summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (CanSummon) - { - if (Summon_Timer <= diff) - { - DoScriptText(EMOTE_SUMMON, me); - DoSummons(); - Summon_Timer = 2500; - } else Summon_Timer -= diff; - } - - if (Allergic_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ALLERGIC_REACTION); - Allergic_Timer = 25000+rand()%15000; - } else Allergic_Timer -= diff; - - if (Teleport_Timer <= diff) - { - DoCast(me, SPELL_TELEPORT_SELF); - Teleport_Timer = 30000+rand()%10000; - CanSummon = true; - } else Teleport_Timer -= diff; - - if (Transform_Timer <= diff) - { - DoTransform(); - Transform_Timer = 25000+rand()%15000; - } else Transform_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_laj(Creature* pCreature) -{ - return new boss_lajAI (pCreature); -} - -void AddSC_boss_laj() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_laj"; - newscript->GetAI = &GetAI_boss_laj; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/botanica/boss_warp_splinter.cpp b/src/server/scripts/outland/tempest_keep/botanica/boss_warp_splinter.cpp deleted file mode 100644 index 48eb03c16d3..00000000000 --- a/src/server/scripts/outland/tempest_keep/botanica/boss_warp_splinter.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Warp_Splinter -SD%Complete: 80 -SDComment: Includes Sapling (need some better control with these). -SDCategory: Tempest Keep, The Botanica -EndScriptData */ - -#include "ScriptedPch.h" - -/*##### -# mob_treant (Sapling) -#####*/ - -#define SPELL_HEAL_FATHER 6262 - -struct mob_treantAI : public ScriptedAI -{ - mob_treantAI (Creature *c) : ScriptedAI(c) - { - WarpGuid = 0; - } - - uint64 WarpGuid; - uint32 check_Timer; - - void Reset() - { - check_Timer = 0; - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (WarpGuid && check_Timer <= diff) - { - if (Unit *Warp = Unit::GetUnit(*me, WarpGuid)) - { - if (me->IsWithinMeleeRange(Warp,2.5f)) - { - int32 CurrentHP_Treant = (int32)me->GetHealth(); - Warp->CastCustomSpell(Warp,SPELL_HEAL_FATHER,&CurrentHP_Treant, 0, 0, true,0 ,0, me->GetGUID()); - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - me->GetMotionMaster()->MoveFollow(Warp,0,0); - } - check_Timer = 1000; - } else check_Timer -= diff; - return; - } - - if (me->getVictim()->GetGUID() != WarpGuid) - DoMeleeAttackIfReady(); - } -}; - -/*##### -# boss_warp_splinter -#####*/ - -#define SAY_AGGRO -1553007 -#define SAY_SLAY_1 -1553008 -#define SAY_SLAY_2 -1553009 -#define SAY_SUMMON_1 -1553010 -#define SAY_SUMMON_2 -1553011 -#define SAY_DEATH -1553012 - -#define WAR_STOMP 34716 -#define SUMMON_TREANTS 34727 // DBC: 34727, 34731, 34733, 34734, 34736, 34739, 34741 (with Ancestral Life spell 34742) // won't work (guardian summon) -#define ARCANE_VOLLEY DUNGEON_MODE(36705, 39133) - -#define CREATURE_TREANT 19949 - -#define TREANT_SPAWN_DIST 50 //50 yards from Warp Splinter's spawn point - -float treant_pos[6][3] = -{ - {24.301233, 427.221100, -27.060635}, - {16.795492, 359.678802, -27.355425}, - {53.493484, 345.381470, -26.196192}, - {61.867096, 439.362732, -25.921030}, - {109.861877, 423.201630, -27.356019}, - {106.780159, 355.582581, -27.593357} -}; - -struct boss_warp_splinterAI : public ScriptedAI -{ - boss_warp_splinterAI(Creature *c) : ScriptedAI(c) - { - Treant_Spawn_Pos_X = c->GetPositionX(); - Treant_Spawn_Pos_Y = c->GetPositionY(); - } - - uint32 War_Stomp_Timer; - uint32 Summon_Treants_Timer; - uint32 Arcane_Volley_Timer; - - float Treant_Spawn_Pos_X; - float Treant_Spawn_Pos_Y; - - void Reset() - { - War_Stomp_Timer = 25000 + rand()%15000; - Summon_Treants_Timer = 45000; - Arcane_Volley_Timer = 8000 + rand()%12000; - - me->SetSpeed(MOVE_RUN, 0.7f, true); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void SummonTreants() - { - for (uint8 i = 0; i < 6; ++i) - { - float angle = (M_PI / 3) * i; - - float X = Treant_Spawn_Pos_X + TREANT_SPAWN_DIST * cos(angle); - float Y = Treant_Spawn_Pos_Y + TREANT_SPAWN_DIST * sin(angle); - float O = - me->GetAngle(X,Y); - - if (Creature *pTreant = me->SummonCreature(CREATURE_TREANT,treant_pos[i][0],treant_pos[i][1],treant_pos[i][2],O,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,25000)) - CAST_AI(mob_treantAI, pTreant->AI())->WarpGuid = me->GetGUID(); - } - DoScriptText(RAND(SAY_SUMMON_1,SAY_SUMMON_2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Check for War Stomp - if (War_Stomp_Timer <= diff) - { - DoCast(me->getVictim(), WAR_STOMP); - War_Stomp_Timer = 25000 + rand()%15000; - } else War_Stomp_Timer -= diff; - - //Check for Arcane Volley - if (Arcane_Volley_Timer <= diff) - { - DoCast(me->getVictim(), ARCANE_VOLLEY); - Arcane_Volley_Timer = 20000 + rand()%15000; - } else Arcane_Volley_Timer -= diff; - - //Check for Summon Treants - if (Summon_Treants_Timer <= diff) - { - SummonTreants(); - Summon_Treants_Timer = 45000; - } else Summon_Treants_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_warp_splinter(Creature* pCreature) -{ - return new boss_warp_splinterAI (pCreature); -} - -CreatureAI* GetAI_mob_treant(Creature* pCreature) -{ - return new mob_treantAI (pCreature); -} - -void AddSC_boss_warp_splinter() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_warp_splinter"; - newscript->GetAI = &GetAI_boss_warp_splinter; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_warp_splinter_treant"; - newscript->GetAI = &GetAI_mob_treant; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_eye/boss_alar.cpp b/src/server/scripts/outland/tempest_keep/the_eye/boss_alar.cpp deleted file mode 100644 index af5f1bd95c1..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_eye/boss_alar.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* Copyright(C) 2006 - 2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -*(at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_alar -SD%Complete: 95 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define SPELL_FLAME_BUFFET 34121 // Flame Buffet - every 1,5 secs in phase 1 if there is no victim in melee range and after Dive Bomb in phase 2 with same conditions -#define SPELL_FLAME_QUILLS 34229 // Randomly after changing position in phase after watching tonns of movies, set probability 20% -#define SPELL_REBIRTH 34342 // Rebirth - beginning of second phase(after loose all health in phase 1) -#define SPELL_REBIRTH_2 35369 // Rebirth(another, without healing to full HP) - after Dive Bomb in phase 2 -#define SPELL_MELT_ARMOR 35410 // Melt Armor - every 60 sec in phase 2 -#define SPELL_CHARGE 35412 // Charge - 30 sec cooldown -#define SPELL_DIVE_BOMB_VISUAL 35367 // Bosskillers says 30 sec cooldown, wowwiki says 30 sec colldown, DBM and BigWigs addons says ~47 sec -#define SPELL_DIVE_BOMB 35181 // after watching tonns of movies, set cooldown to 40+rand()%5. -#define SPELL_BERSERK 45078 // 10 minutes after phase 2 starts(id is wrong, but proper id is unknown) - -#define CREATURE_EMBER_OF_ALAR 19551 // Al'ar summons one Ember of Al'ar every position change in phase 1 and two after Dive Bomb. Also in phase 2 when Ember of Al'ar dies, boss loose 3% health. -#define SPELL_EMBER_BLAST 34133 // When Ember of Al'ar dies, it casts Ember Blast - -#define CREATURE_FLAME_PATCH_ALAR 20602 // Flame Patch - every 30 sec in phase 2 -#define SPELL_FLAME_PATCH 35380 // - -static float waypoint[6][3] = -{ - {340.15, 58.65, 17.71}, - {388.09, 31.54, 20.18}, - {388.18, -32.85, 20.18}, - {340.29, -60.19, 17.72}, - {332, 0.01, 39}, // better not use the same xy coord - {331, 0.01, -2.39} -}; - -enum WaitEventType -{ - WE_NONE = 0, - WE_DUMMY = 1, - WE_PLATFORM = 2, - WE_QUILL = 3, - WE_DIE = 4, - WE_REVIVE = 5, - WE_CHARGE = 6, - WE_METEOR = 7, - WE_DIVE = 8, - WE_LAND = 9, - WE_SUMMON = 10 -}; - -struct boss_alarAI : public ScriptedAI -{ - boss_alarAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - DefaultMoveSpeedRate = c->GetSpeedRate(MOVE_RUN); - } - - ScriptedInstance *pInstance; - - WaitEventType WaitEvent; - uint32 WaitTimer; - - bool AfterMoving; - - uint32 Platforms_Move_Timer; - uint32 DiveBomb_Timer; - uint32 MeltArmor_Timer; - uint32 Charge_Timer; - uint32 FlamePatch_Timer; - uint32 Berserk_Timer; - - float DefaultMoveSpeedRate; - - bool Phase1; - bool ForceMove; - uint32 ForceTimer; - - int8 cur_wp; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, NOT_STARTED); - - Berserk_Timer = 1200000; - Platforms_Move_Timer = 0; - - Phase1 = true; - WaitEvent = WE_NONE; - WaitTimer = 0; - AfterMoving = false; - ForceMove = false; - ForceTimer = 5000; - - cur_wp = 4; - - me->SetDisplayId(me->GetNativeDisplayId()); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); - //me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - //me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->setActive(false); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, IN_PROGRESS); - - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); // after enterevademode will be set walk movement - DoZoneInCombat(); - me->setActive(true); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, DONE); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - summon->AI()->AttackStart(pTarget); - } - - void MoveInLineOfSight(Unit * /*who*/) {} - - void AttackStart(Unit* who) - { - if (Phase1) - AttackStartNoMove(who); - else - ScriptedAI::AttackStart(who); - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth() && Phase1) - { - damage = 0; - if (!WaitEvent) - { - WaitEvent = WE_DIE; - WaitTimer = 0; - me->SetHealth(0); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->AttackStop(); - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - me->SetSpeed(MOVE_RUN, 5.0f); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]); - } - } - } - - void SpellHit(Unit*, const SpellEntry *spell) - { - if (spell->Id == SPELL_DIVE_BOMB_VISUAL) - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - me->SetDisplayId(11686); - //me->SendUpdateObjectToAllExcept(NULL); - } - } - - void MovementInform(uint32 type, uint32 /*id*/) - { - if (type == POINT_MOTION_TYPE) - { - WaitTimer = 1; - AfterMoving = true; - ForceMove = false; - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) // sometimes isincombat but !incombat, faction bug? - return; - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - Berserk_Timer = 60000; - } else Berserk_Timer -= diff; - - if (ForceMove) - { - if (ForceTimer <= diff) - { - me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); - ForceTimer = 5000; - } else ForceTimer -= diff; - - } - if (WaitEvent) - { - if (WaitTimer) - { - if (WaitTimer <= diff) - { - if (AfterMoving) - { - me->GetMotionMaster()->MoveIdle(); - AfterMoving = false; - } - - switch(WaitEvent) - { - case WE_PLATFORM: - Platforms_Move_Timer = 30000+rand()%5000; - break; - case WE_QUILL: - DoCast(me, SPELL_FLAME_QUILLS, true); - Platforms_Move_Timer = 1; - WaitTimer = 10000; - WaitEvent = WE_DUMMY; - return; - case WE_DIE: - ForceMove = false; - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); - WaitTimer = 5000; - WaitEvent = WE_REVIVE; - return; - case WE_REVIVE: - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); - me->SetHealth(me->GetMaxHealth()); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoZoneInCombat(); - DoCast(me, SPELL_REBIRTH, true); - MeltArmor_Timer = 60000; - Charge_Timer = 7000; - DiveBomb_Timer = 40000+rand()%5000; - FlamePatch_Timer = 30000; - Phase1 = false; - break; - case WE_METEOR: - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - DoCast(me, SPELL_DIVE_BOMB_VISUAL, false); - WaitEvent = WE_DIVE; - WaitTimer = 4000; - return; - case WE_DIVE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL); - DoCast(pTarget, SPELL_DIVE_BOMB, true); - float dist = 3.0f; - if (me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f)) - dist = 5.0f; - WaitTimer = 1000 + floor(dist / 80 * 1000.0f); - me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f); - me->StopMoving(); - WaitEvent = WE_LAND; - } - else - { - EnterEvadeMode(); - return; - } - case WE_LAND: - WaitEvent = WE_SUMMON; - WaitTimer = 2000; - return; - case WE_SUMMON: - for (uint8 i = 0; i < 2; ++i) - DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(me->GetNativeDisplayId()); - DoCast(me, SPELL_REBIRTH_2, true); - break; - case WE_DUMMY: - default: - break; - } - - WaitEvent = WE_NONE; - WaitTimer = 0; - } else WaitTimer -= diff; - } - return; - } - - if (Phase1) - { - if (me->getThreatManager().getThreatList().empty()) - { - EnterEvadeMode(); - return; - } - - if (Platforms_Move_Timer <= diff) - { - if (cur_wp == 4) - { - cur_wp = 0; - WaitEvent = WE_PLATFORM; - } - else - { - if (urand(0,4)) // next platform - { - DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (cur_wp == 3) - cur_wp = 0; - else - ++cur_wp; - WaitEvent = WE_PLATFORM; - } - else // flame quill - { - cur_wp = 4; - WaitEvent = WE_QUILL; - } - } - ForceMove = true; - ForceTimer = 5000; - me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); - WaitTimer = 0; - return; - } else Platforms_Move_Timer -= diff; - } - else - { - if (Charge_Timer <= diff) - { - Unit *pTarget= SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - if (pTarget) - DoCast(pTarget, SPELL_CHARGE); - Charge_Timer = 30000; - } else Charge_Timer -= diff; - - if (MeltArmor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MELT_ARMOR); - MeltArmor_Timer = 60000; - } else MeltArmor_Timer -= diff; - - if (DiveBomb_Timer <= diff) - { - me->AttackStop(); - me->GetMotionMaster()->MovePoint(6, waypoint[4][0], waypoint[4][1], waypoint[4][2]); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 50); - WaitEvent = WE_METEOR; - WaitTimer = 0; - DiveBomb_Timer = 40000+rand()%5000; - return; - } else DiveBomb_Timer -= diff; - - if (FlamePatch_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - Creature* Summoned = me->SummonCreature(CREATURE_FLAME_PATCH_ALAR, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000); - if (Summoned) - { - Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Summoned->SetFloatValue(OBJECT_FIELD_SCALE_X, Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); - Summoned->SetDisplayId(11686); - Summoned->setFaction(me->getFaction()); - Summoned->SetLevel(me->getLevel()); - Summoned->CastSpell(Summoned, SPELL_FLAME_PATCH, false); - } - } - FlamePatch_Timer = 30000; - } else FlamePatch_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void DoMeleeAttackIfReady() - { - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - else - { - Unit *pTarget = NULL; - pTarget = me->SelectNearestTargetInAttackDistance(5); - if (pTarget) - me->AI()->AttackStart(pTarget); - else - { - DoCast(me, SPELL_FLAME_BUFFET, true); - me->setAttackTimer(BASE_ATTACK, 1500); - } - } - } - } -}; - -CreatureAI* GetAI_boss_alar(Creature* pCreature) -{ - return new boss_alarAI(pCreature); -} - -struct mob_ember_of_alarAI : public ScriptedAI -{ - mob_ember_of_alarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - c->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - c->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - } - - ScriptedInstance *pInstance; - bool toDie; - - void Reset() {toDie = false;} - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - void EnterEvadeMode() {me->setDeathState(JUST_DIED);} - - void DamageTaken(Unit* pKiller, uint32 &damage) - { - if (damage >= me->GetHealth() && pKiller != me && !toDie) - { - damage = 0; - DoCast(me, SPELL_EMBER_BLAST, true); - me->SetDisplayId(11686); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (pInstance && pInstance->GetData(DATA_ALAREVENT) == 2) - { - if (Unit* Alar = Unit::GetUnit((*me), pInstance->GetData64(DATA_ALAR))) - { - int AlarHealth = Alar->GetHealth() - Alar->GetMaxHealth()*0.03; - if (AlarHealth > 0) - Alar->SetHealth(AlarHealth); - else - Alar->SetHealth(1); - } - } - toDie = true; - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - if (toDie) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - //me->SetVisibility(VISIBILITY_OFF); - } - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_mob_ember_of_alar(Creature* pCreature) -{ - return new mob_ember_of_alarAI(pCreature); -} - -struct mob_flame_patch_alarAI : public ScriptedAI -{ - mob_flame_patch_alarAI(Creature *c) : ScriptedAI(c) {} - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_mob_flame_patch_alar(Creature* pCreature) -{ - return new mob_flame_patch_alarAI(pCreature); -} - -void AddSC_boss_alar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_alar"; - newscript->GetAI = &GetAI_boss_alar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ember_of_alar"; - newscript->GetAI = &GetAI_mob_ember_of_alar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flame_patch_alar"; - newscript->GetAI = &GetAI_mob_flame_patch_alar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_eye/boss_astromancer.cpp b/src/server/scripts/outland/tempest_keep/the_eye/boss_astromancer.cpp deleted file mode 100644 index e9e217a5c62..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_eye/boss_astromancer.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Astromancer -SD%Complete: 80 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -enum eEnums -{ - SAY_AGGRO = -1550007, - SAY_SUMMON1 = -1550008, - SAY_SUMMON2 = -1550009, - SAY_KILL1 = -1550010, - SAY_KILL2 = -1550011, - SAY_KILL3 = -1550012, - SAY_DEATH = -1550013, - SAY_VOIDA = -1550014, - SAY_VOIDB = -1550015, - - SPELL_ARCANE_MISSILES = 33031, - SPELL_WRATH_OF_THE_ASTROMANCER = 42783, - SPELL_BLINDING_LIGHT = 33009, - SPELL_FEAR = 34322, - SPELL_VOID_BOLT = 39329, - - SPELL_SPOTLIGHT = 25824, - NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT = 18928, - - NPC_SOLARIUM_AGENT = 18925, - NPC_SOLARIUM_PRIEST = 18806, - - MODEL_HUMAN = 18239, - MODEL_VOIDWALKER = 18988, - - SPELL_SOLARIUM_GREAT_HEAL = 33387, - SPELL_SOLARIUM_HOLY_SMITE = 25054, - SPELL_SOLARIUM_ARCANE_TORRENT = 33390, - - WV_ARMOR = 31000 -}; - -const float CENTER_X = 432.909f; -const float CENTER_Y = -373.424f; -const float CENTER_Z = 17.9608f; -const float CENTER_O = 1.06421f; -const float SMALL_PORTAL_RADIUS = 12.6f; -const float LARGE_PORTAL_RADIUS = 26.0f; -const float PORTAL_Z = 17.005f; - - // x, y, z, o -static float SolarianPos[4] = {432.909, -373.424, 17.9608, 1.06421}; - -struct boss_high_astromancer_solarianAI : public ScriptedAI -{ - boss_high_astromancer_solarianAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - - defaultarmor = c->GetArmor(); - defaultsize = c->GetFloatValue(OBJECT_FIELD_SCALE_X); - } - - ScriptedInstance *pInstance; - SummonList Summons; - - uint8 Phase; - - uint32 ArcaneMissiles_Timer; - uint32 m_uiWrathOfTheAstromancer_Timer; - uint32 BlindingLight_Timer; - uint32 Fear_Timer; - uint32 VoidBolt_Timer; - uint32 Phase1_Timer; - uint32 Phase2_Timer; - uint32 Phase3_Timer; - uint32 AppearDelay_Timer; - uint32 defaultarmor; - uint32 Wrath_Timer; - - float defaultsize; - float Portals[3][3]; - - bool AppearDelay; - bool BlindingLight; - - void Reset() - { - ArcaneMissiles_Timer = 2000; - m_uiWrathOfTheAstromancer_Timer = 15000; - BlindingLight_Timer = 41000; - Fear_Timer = 20000; - VoidBolt_Timer = 10000; - Phase1_Timer = 50000; - Phase2_Timer = 10000; - Phase3_Timer = 15000; - AppearDelay_Timer = 2000; - BlindingLight = false; - AppearDelay = false; - Wrath_Timer = 20000+rand()%5000;//twice in phase one - Phase = 1; - Wrath_Timer = 20000+rand()%5000;//twice in phase one - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); - - me->SetArmor(defaultarmor); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); - me->SetDisplayId(MODEL_HUMAN); - - Summons.DespawnAll(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2,SAY_KILL3), me); - } - - void JustDied(Unit * /*victim*/) - { - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); - me->SetDisplayId(MODEL_HUMAN); - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); - } - - void SummonMinion(uint32 entry, float x, float y, float z) - { - Creature* Summoned = me->SummonCreature(entry, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (Summoned) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Summoned->AI()->AttackStart(pTarget); - - Summons.Summon(Summoned); - } - } - - float Portal_X(float radius) - { - if (urand(0,1)) - radius = -radius; - - return radius * (float)(rand()%100)/100.0f + CENTER_X; - } - - float Portal_Y(float x, float radius) - { - float z = RAND(1, -1); - - return (z*sqrt(radius*radius - (x - CENTER_X)*(x - CENTER_X)) + CENTER_Y); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AppearDelay) - { - me->StopMoving(); - me->AttackStop(); - if (AppearDelay_Timer <= diff) - { - AppearDelay = false; - if (Phase == 2) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_OFF); - } - AppearDelay_Timer = 2000; - } else AppearDelay_Timer -= diff; - } - - if (Phase == 1) - { - if (BlindingLight_Timer <= diff) - { - BlindingLight = true; - BlindingLight_Timer = 45000; - } else BlindingLight_Timer -= diff; - - if (Wrath_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER, true); - Wrath_Timer = 20000+rand()%5000; - } else Wrath_Timer -= diff; - - if (ArcaneMissiles_Timer <= diff) - { - if (BlindingLight) - { - DoCast(me->getVictim(), SPELL_BLINDING_LIGHT); - BlindingLight = false; - }else{ - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (!me->HasInArc(2.5f, pTarget)) - pTarget = me->getVictim(); - - if (pTarget) - DoCast(pTarget, SPELL_ARCANE_MISSILES); - } - ArcaneMissiles_Timer = 3000; - } else ArcaneMissiles_Timer -= diff; - - if (m_uiWrathOfTheAstromancer_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - - //Target the tank ? - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER); - m_uiWrathOfTheAstromancer_Timer = 25000; - } - else - m_uiWrathOfTheAstromancer_Timer = 1000; - } else m_uiWrathOfTheAstromancer_Timer -= diff; - - //Phase1_Timer - if (Phase1_Timer <= diff) - { - Phase = 2; - Phase1_Timer = 50000; - //After these 50 seconds she portals to the middle of the room and disappears, leaving 3 light portals behind. - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, CENTER_X, CENTER_Y, CENTER_Z, CENTER_O); - for (uint8 i=0; i <= 2; ++i) - { - if (!i) - { - Portals[i][0] = Portal_X(SMALL_PORTAL_RADIUS); - Portals[i][1] = Portal_Y(Portals[i][0], SMALL_PORTAL_RADIUS); - Portals[i][2] = CENTER_Z; - } - else - { - Portals[i][0] = Portal_X(LARGE_PORTAL_RADIUS); - Portals[i][1] = Portal_Y(Portals[i][0], LARGE_PORTAL_RADIUS); - Portals[i][2] = PORTAL_Z; - } - } - if ((abs(Portals[2][0] - Portals[1][0]) < 7) && (abs(Portals[2][1] - Portals[1][1]) < 7)) - { - int i=1; - if (abs(CENTER_X + 26.0f - Portals[2][0]) < 7) - i = -1; - Portals[2][0] = Portals[2][0]+7*i; - Portals[2][1] = Portal_Y(Portals[2][0], LARGE_PORTAL_RADIUS); - } - for (int i=0; i <= 2; ++i) - { - if (Creature* Summoned = me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O, TEMPSUMMON_TIMED_DESPAWN, Phase2_Timer+Phase3_Timer+AppearDelay_Timer+1700)) - { - Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Summoned->CastSpell(Summoned, SPELL_SPOTLIGHT, false); - } - } - AppearDelay = true; - } else Phase1_Timer-=diff; - } - else if (Phase == 2) - { - //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. - me->AttackStop(); - me->StopMoving(); - if (Phase2_Timer <= diff) - { - Phase = 3; - for (int i=0; i <= 2; ++i) - for (int j=1; j <= 4; j++) - SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); - - DoScriptText(SAY_SUMMON1, me); - Phase2_Timer = 10000; - } else Phase2_Timer -= diff; - } - else if (Phase == 3) - { - me->AttackStop(); - me->StopMoving(); - - //Check Phase3_Timer - if (Phase3_Timer <= diff) - { - Phase = 1; - - //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. - int i = rand()%3; - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); - - for (int j=0; j <= 2; j++) - if (j != i) - SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - DoScriptText(SAY_SUMMON2, me); - AppearDelay = true; - Phase3_Timer = 15000; - } else Phase3_Timer -= diff; - } - else if (Phase == 4) - { - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 20000; - } else Fear_Timer -= diff; - - //VoidBolt_Timer - if (VoidBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VOID_BOLT); - VoidBolt_Timer = 10000; - } else VoidBolt_Timer -= diff; - } - - //When Solarian reaches 20% she will transform into a huge void walker. - if (Phase != 4 && ((me->GetHealth()*100 / me->GetMaxHealth())<20)) - { - Phase = 4; - - //To make sure she wont be invisible or not selecatble - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - DoScriptText(SAY_VOIDA, me); - DoScriptText(SAY_VOIDB, me); - me->SetArmor(WV_ARMOR); - me->SetDisplayId(MODEL_VOIDWALKER); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize*2.5f); - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_solarium_priestAI : public ScriptedAI -{ - mob_solarium_priestAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 healTimer; - uint32 holysmiteTimer; - uint32 aoesilenceTimer; - - void Reset() - { - healTimer = 9000; - holysmiteTimer = 1; - aoesilenceTimer = 15000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (healTimer <= diff) - { - Unit *pTarget = NULL; - - switch (urand(0,1)) - { - case 0: - if (pInstance) - pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_ASTROMANCER)); - break; - case 1: - pTarget = me; - break; - } - - if (pTarget) - { - DoCast(pTarget, SPELL_SOLARIUM_GREAT_HEAL); - healTimer = 9000; - } - } else healTimer -= diff; - - if (holysmiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARIUM_HOLY_SMITE); - holysmiteTimer = 4000; - } else holysmiteTimer -= diff; - - if (aoesilenceTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARIUM_ARCANE_TORRENT); - aoesilenceTimer = 13000; - } else aoesilenceTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_solarium_priest(Creature* pCreature) -{ - return new mob_solarium_priestAI (pCreature); -} - -CreatureAI* GetAI_boss_high_astromancer_solarian(Creature* pCreature) -{ - return new boss_high_astromancer_solarianAI (pCreature); -} - -void AddSC_boss_high_astromancer_solarian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_high_astromancer_solarian"; - newscript->GetAI = &GetAI_boss_high_astromancer_solarian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_solarium_priest"; - newscript->GetAI = &GetAI_mob_solarium_priest; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp b/src/server/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp deleted file mode 100644 index 05681fb7539..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp +++ /dev/null @@ -1,1498 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kaelthas -SD%Complete: 60 -SDComment: SQL, weapon scripts, mind control, need correct spells(interruptible/uninterruptible), phoenix spawn location & animation, phoenix behaviour & spawn during gravity lapse -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" -#include "WorldPacket.h" - -enum eEnums -{ - //kael'thas Speech - SAY_INTRO = -1550016, - SAY_INTRO_CAPERNIAN = -1550017, - SAY_INTRO_TELONICUS = -1550018, - SAY_INTRO_THALADRED = -1550019, - SAY_INTRO_SANGUINAR = -1550020, - SAY_PHASE2_WEAPON = -1550021, - SAY_PHASE3_ADVANCE = -1550022, - SAY_PHASE4_INTRO2 = -1550023, - SAY_PHASE5_NUTS = -1550024, - SAY_SLAY1 = -1550025, - SAY_SLAY2 = -1550026, - SAY_SLAY3 = -1550027, - SAY_MINDCONTROL1 = -1550028, - SAY_MINDCONTROL2 = -1550029, - SAY_GRAVITYLAPSE1 = -1550030, - SAY_GRAVITYLAPSE2 = -1550031, - SAY_SUMMON_PHOENIX1 = -1550032, - SAY_SUMMON_PHOENIX2 = -1550033, - SAY_DEATH = -1550034, - - //Thaladred the Darkener speech - SAY_THALADRED_AGGRO = -1550035, - SAY_THALADRED_DEATH = -1550036, - EMOTE_THALADRED_GAZE = -1550037, - - //Lord Sanguinar speech - SAY_SANGUINAR_AGGRO = -1550038, - SAY_SANGUINAR_DEATH = -1550039, - - //Grand Astromancer Capernian speech - SAY_CAPERNIAN_AGGRO = -1550040, - SAY_CAPERNIAN_DEATH = -1550041, - - //Master Engineer Telonicus speech - SAY_TELONICUS_AGGRO = -1550042, - SAY_TELONICUS_DEATH = -1550043, - - //Phase 2 spells - SPELL_SUMMON_WEAPONS = 36976, - SPELL_SUMMON_WEAPONA = 36958, - SPELL_SUMMON_WEAPONB = 36959, - SPELL_SUMMON_WEAPONC = 36960, - SPELL_SUMMON_WEAPOND = 36961, - SPELL_SUMMON_WEAPONE = 36962, - SPELL_SUMMON_WEAPONF = 36963, - SPELL_SUMMON_WEAPONG = 36964, - SPELL_RES_VISUAL = 24171, - - //Phase 4 spells - SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell - SPELL_PYROBLAST = 36819, - SPELL_FLAME_STRIKE = 36735, - SPELL_FLAME_STRIKE_VIS = 36730, - SPELL_FLAME_STRIKE_DMG = 36731, - SPELL_ARCANE_DISRUPTION = 36834, - SPELL_SHOCK_BARRIER = 36815, - SPELL_PHOENIX_ANIMATION = 36723, - SPELL_MIND_CONTROL = 32830, - - //Phase 5 spells - SPELL_EXPLODE = 36092, - SPELL_FULLPOWER = 36187, - SPELL_KNOCKBACK = 11027, - SPELL_GRAVITY_LAPSE = 34480, - SPELL_GRAVITY_LAPSE_AURA = 39432, - SPELL_NETHER_BEAM = 35873, - - //Thaladred the Darkener spells - SPELL_PSYCHIC_BLOW = 10689, - SPELL_SILENCE = 30225, - //Lord Sanguinar spells - SPELL_BELLOWING_ROAR = 40636, - //Grand Astromancer Capernian spells - - SPELL_CAPERNIAN_FIREBALL = 36971, - SPELL_CONFLAGRATION = 37018, - SPELL_ARCANE_EXPLOSION = 36970, - //Master Engineer Telonicus spells - SPELL_BOMB = 37036, - SPELL_REMOTE_TOY = 37027, - //Nether Vapor spell - SPELL_NETHER_VAPOR = 35859, - //Phoenix spell - SPELL_BURN = 36720, - SPELL_EMBER_BLAST = 34341, - SPELL_REBIRTH = 41587, - - //Creature IDs - NPC_PHOENIX = 21362, - NPC_PHOENIX_EGG = 21364, - - //Phoenix egg and phoenix model - MODEL_ID_PHOENIX = 19682, - MODEL_ID_PHOENIX_EGG = 20245, - - MAX_ADVISORS = 4 -}; - -uint32 m_auiSpellSummonWeapon[]= -{ - SPELL_SUMMON_WEAPONA, SPELL_SUMMON_WEAPONB, SPELL_SUMMON_WEAPONC, SPELL_SUMMON_WEAPOND, - SPELL_SUMMON_WEAPONE, SPELL_SUMMON_WEAPONF, SPELL_SUMMON_WEAPONG -}; - -const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target -const float KAEL_VISIBLE_RANGE = 50.0f; - -const float afGravityPos[3] = {795.0f, 0.0f, 70.0f}; - -#define TIME_PHASE_2_3 120000 -#define TIME_PHASE_3_4 180000 - -//Base AI for Advisors -struct advisorbase_ai : public ScriptedAI -{ - advisorbase_ai(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - m_bDoubled_Health = false; - } - - ScriptedInstance* m_pInstance; - bool FakeDeath; - bool m_bDoubled_Health; - uint32 DelayRes_Timer; - uint64 DelayRes_Target; - - void Reset() - { - if (m_bDoubled_Health) - { - me->SetMaxHealth(me->GetMaxHealth() / 2); - m_bDoubled_Health = false; - } - - FakeDeath = false; - DelayRes_Timer = 0; - DelayRes_Target = 0; - - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - //reset encounter - if (m_pInstance && (m_pInstance->GetData(DATA_KAELTHASEVENT) == 1 || m_pInstance->GetData(DATA_KAELTHASEVENT) == 3)) - if (Creature *Kaelthas = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_KAELTHAS))) - Kaelthas->AI()->EnterEvadeMode(); - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void AttackStart(Unit* who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void Revive(Unit* /*Target*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // double health for phase 3 - me->SetMaxHealth(me->GetMaxHealth() * 2); - m_bDoubled_Health = true; - me->SetHealth(me->GetMaxHealth()); - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoCast(me, SPELL_RES_VISUAL, false); - DelayRes_Timer = 2000; - } - - void DamageTaken(Unit* pKiller, uint32 &damage) - { - if (damage < me->GetHealth()) - return; - - //Prevent glitch if in fake death - if (FakeDeath && m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) - { - damage = 0; - return; - } - - //Don't really die in phase 1 & 3, only die after that - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) - { - //prevent death - damage = 0; - FakeDeath = true; - - me->InterruptNonMeleeSpells(false); - me->SetHealth(0); - me->StopMoving(); - me->ClearComboPointHolders(); - me->RemoveAllAurasOnDeath(); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->ClearAllReactives(); - me->SetUInt64Value(UNIT_FIELD_TARGET,0); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - JustDied(pKiller); - } - } - - void UpdateAI(const uint32 diff) - { - if (DelayRes_Timer) - { - if (DelayRes_Timer <= diff) - { - DelayRes_Timer = 0; - FakeDeath = false; - - Unit* Target = Unit::GetUnit((*me), DelayRes_Target); - if (!Target) - Target = me->getVictim(); - - DoResetThreat(); - AttackStart(Target); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(Target); - me->AddThreat(Target, 0.0f); - } else DelayRes_Timer -= diff; - } - } - -}; - -//Kael'thas AI -struct boss_kaelthasAI : public ScriptedAI -{ - boss_kaelthasAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me) - { - m_pInstance = pCreature->GetInstanceData(); - memset(&m_auiAdvisorGuid, 0, sizeof(m_auiAdvisorGuid)); - } - - ScriptedInstance* m_pInstance; - - uint32 Fireball_Timer; - uint32 ArcaneDisruption_Timer; - uint32 Phoenix_Timer; - uint32 ShockBarrier_Timer; - uint32 GravityLapse_Timer; - uint32 GravityLapse_Phase; - uint32 NetherBeam_Timer; - uint32 NetherVapor_Timer; - uint32 FlameStrike_Timer; - uint32 MindControl_Timer; - uint32 Phase; - uint32 PhaseSubphase; //generic - uint32 Phase_Timer; //generic timer - uint32 PyrosCasted; - - bool InGravityLapse; - bool IsCastingFireball; - bool ChainPyros; - - SummonList summons; - - uint64 m_auiAdvisorGuid[MAX_ADVISORS]; - - void Reset() - { - Fireball_Timer = 5000+rand()%10000; - ArcaneDisruption_Timer = 45000; - MindControl_Timer = 40000; - Phoenix_Timer = 50000; - ShockBarrier_Timer = 60000; - FlameStrike_Timer = 30000; - GravityLapse_Timer = 20000; - GravityLapse_Phase = 0; - NetherBeam_Timer = 8000; - NetherVapor_Timer = 10000; - PyrosCasted = 0; - Phase = 0; - InGravityLapse = false; - IsCastingFireball = false; - ChainPyros = false; - - if (me->isInCombat()) - PrepareAdvisors(); - - summons.DespawnAll(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 0); - } - - void PrepareAdvisors() - { - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Creature *pCreature = Unit::GetCreature((*me), m_auiAdvisorGuid[i])) - { - pCreature->Respawn(); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->setFaction(me->getFaction()); - pCreature->AI()->EnterEvadeMode(); - } - } - } - - void StartEvent() - { - if (!m_pInstance) - return; - - m_auiAdvisorGuid[0] = m_pInstance->GetData64(DATA_THALADREDTHEDARKENER); - m_auiAdvisorGuid[1] = m_pInstance->GetData64(DATA_LORDSANGUINAR); - m_auiAdvisorGuid[2] = m_pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN); - m_auiAdvisorGuid[3] = m_pInstance->GetData64(DATA_MASTERENGINEERTELONICUS); - - if (!m_auiAdvisorGuid[0] || !m_auiAdvisorGuid[1] || !m_auiAdvisorGuid[2] || !m_auiAdvisorGuid[3]) - { - error_log("TSCR: Kael'Thas One or more advisors missing, Skipping Phases 1-3"); - - DoScriptText(SAY_PHASE4_INTRO2, me); - - Phase = 4; - - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - AttackStart(pTarget); - - } - else - { - PrepareAdvisors(); - - DoScriptText(SAY_INTRO, me); - - m_pInstance->SetData(DATA_KAELTHASEVENT, 1); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - PhaseSubphase = 0; - Phase_Timer = 23000; - Phase = 1; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!me->hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() && - me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) - { - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - if (!me->getVictim() && Phase >= 4) - { - who->RemoveAurasDueToSpell(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (me->GetMap()->IsDungeon()) - { - if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); - - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } - } - } - } - - void Aggro(Unit * /*who*/) - { - if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustSummoned(Creature* pSummoned) - { - // if not phoenix, then it's one of the 7 weapons - if (pSummoned->GetEntry() != NPC_PHOENIX) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - - summons.Summon(pSummoned); - } - } - - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - - void JustDied(Unit* /*Killer*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - DoScriptText(SAY_DEATH, me); - - summons.DespawnAll(); - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 0); - - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Unit* pAdvisor = Unit::GetUnit((*me), m_auiAdvisorGuid[i])) - pAdvisor->Kill(pAdvisor); - } - } - - void UpdateAI(const uint32 diff) - { - //Phase 1 - switch (Phase) - { - case 1: - { - Unit *pTarget = NULL; - Creature* Advisor = NULL; - - //Subphase switch - switch(PhaseSubphase) - { - //Subphase 1 - Start - case 0: - if (Phase_Timer <= diff) - { - DoScriptText(SAY_INTRO_THALADRED, me); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 1 - Unlock advisor - case 1: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 2 - Start - case 2: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_SANGUINAR, me); - - //start advisor within 12.5 seconds - Phase_Timer = 12500; - ++PhaseSubphase; - } - break; - - //Subphase 2 - Unlock advisor - case 3: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 3 - Start - case 4: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_CAPERNIAN, me); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } - break; - - //Subphase 3 - Unlock advisor - case 5: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 4 - Start - case 6: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_TELONICUS, me); - - //start advisor within 8.4 seconds - Phase_Timer = 8400; - ++PhaseSubphase; - } - break; - - //Subphase 4 - Unlock advisor - case 7: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - Phase_Timer = 3000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //End of phase 1 - case 8: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Phase = 2; - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 2); - - DoScriptText(SAY_PHASE2_WEAPON, me); - - PhaseSubphase = 0; - Phase_Timer = 3500; - DoCast(me, SPELL_SUMMON_WEAPONS); - } - break; - } - } - break; - - case 2: - { - if (PhaseSubphase == 0) - { - if (Phase_Timer <= diff) - { - PhaseSubphase = 1; - } else Phase_Timer -= diff; - } - - //Spawn weapons - if (PhaseSubphase == 1) - { - DoCast(me, SPELL_SUMMON_WEAPONS, false); - - uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32); - - for (uint32 i = 0; i < uiMaxWeapon; ++i) - DoCast(me, m_auiSpellSummonWeapon[i], true); - - PhaseSubphase = 2; - Phase_Timer = TIME_PHASE_2_3; - } - - if (PhaseSubphase == 2) - { - if (Phase_Timer <= diff) - { - DoScriptText(SAY_PHASE3_ADVANCE, me); - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 3); - Phase = 3; - PhaseSubphase = 0; - } else Phase_Timer -= diff; - } - } - break; - - case 3: - { - if (PhaseSubphase == 0) - { - //Respawn advisors - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - Creature *Advisor; - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - Advisor = Unit::GetCreature((*me), m_auiAdvisorGuid[i]); - - if (!Advisor) - error_log("SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); - else - CAST_AI(advisorbase_ai, Advisor->AI())->Revive(pTarget); - } - - PhaseSubphase = 1; - Phase_Timer = TIME_PHASE_3_4; - } - - if (Phase_Timer <= diff) - { - DoScriptText(SAY_PHASE4_INTRO2, me); - Phase = 4; - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - - // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. - DoResetThreat(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - AttackStart(pTarget); - - Phase_Timer = 30000; - } else Phase_Timer -= diff; - } - break; - - case 4: - case 5: - case 6: - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fireball_Timer - if (!InGravityLapse && !ChainPyros && Phase != 5) - { - if (Fireball_Timer <= diff) - { - if (!IsCastingFireball) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - //interruptable - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); - int32 dmg = 20000+rand()%5000; - me->CastCustomSpell(me->getVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); - IsCastingFireball = true; - Fireball_Timer = 2500; - } - } - else - { - //apply resistance - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); - IsCastingFireball = false; - Fireball_Timer = 5000+rand()%10000; - } - } else Fireball_Timer -= diff; - - //ArcaneDisruption_Timer - if (ArcaneDisruption_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_DISRUPTION, true); - ArcaneDisruption_Timer = 60000; - } else ArcaneDisruption_Timer -= diff; - - if (FlameStrike_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_FLAME_STRIKE); - - FlameStrike_Timer = 30000; - } else FlameStrike_Timer -= diff; - - if (MindControl_Timer <= diff) - { - if (me->getThreatManager().getThreatList().size() >= 2) - for (uint32 i = 0; i < 3; ++i) - { - debug_log("SD2: Kael'Thas mind control not supported."); - //DoCast(pUnit, SPELL_MIND_CONTROL); - } - - MindControl_Timer = 60000; - } else MindControl_Timer -= diff; - } - - //Phoenix_Timer - if (Phoenix_Timer <= diff) - { - DoCast(me, SPELL_PHOENIX_ANIMATION); - DoScriptText(RAND(SAY_SUMMON_PHOENIX1,SAY_SUMMON_PHOENIX2), me); - - Phoenix_Timer = 60000; - } else Phoenix_Timer -= diff; - - //Phase 4 specific spells - if (Phase == 4) - { - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - Phase = 5; - Phase_Timer = 10000; - - DoScriptText(SAY_PHASE5_NUTS, me); - - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, 0, 0); - - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_FULLPOWER); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ChainPyros = true; - PyrosCasted = 0; - ShockBarrier_Timer = 60000; - } else ShockBarrier_Timer -= diff; - - //Chain Pyros (3 of them max) - if (ChainPyros && !me->IsNonMeleeSpellCasted(false)) - { - if (PyrosCasted < 3) - { - DoCast(me->getVictim(), SPELL_PYROBLAST); - ++PyrosCasted; - } - else - { - ChainPyros = false; - Fireball_Timer = 2500; - ArcaneDisruption_Timer = 60000; - } - } - } - - if (Phase == 5) - { - if (Phase_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - me->RemoveAurasDueToSpell(SPELL_FULLPOWER); - - DoCast(me, SPELL_EXPLODE); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Phase = 6; - AttackStart(me->getVictim()); - } else Phase_Timer -= diff; - } - - //Phase 5 - if (Phase == 6) - { - - //GravityLapse_Timer - if (GravityLapse_Timer <= diff) - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - switch (GravityLapse_Phase) - { - case 0: - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, MOVEMENTFLAG_NONE, 0); - - // 1) Kael'thas will portal the whole raid right into his body - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - //Use work around packet to prevent player from being dropped from combat - DoTeleportPlayer(pUnit, afGravityPos[0], afGravityPos[1], afGravityPos[2], pUnit->GetOrientation()); - } - } - - GravityLapse_Timer = 500; - ++GravityLapse_Phase; - InGravityLapse = true; - ShockBarrier_Timer = 1000; - NetherBeam_Timer = 5000; - break; - - case 1: - DoScriptText(RAND(SAY_GRAVITYLAPSE1,SAY_GRAVITYLAPSE2), me); - - // 2) At that point he will put a Gravity Lapse debuff on everyone - for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) - { - if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) - { - DoCast(pUnit, SPELL_KNOCKBACK, true); - //Gravity lapse - needs an exception in Spell system to work - - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); - - //Using packet workaround - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - GravityLapse_Timer = 10000; - ++GravityLapse_Phase; - break; - - case 2: - //Cast nether vapor aura on self - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_NETHER_VAPOR); - - GravityLapse_Timer = 20000; - ++GravityLapse_Phase; - break; - - case 3: - //Remove flight - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) - { - //Using packet workaround - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - - me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); - InGravityLapse = false; - GravityLapse_Timer = 60000; - GravityLapse_Phase = 0; - AttackStart(me->getVictim()); - break; - } - } else GravityLapse_Timer -= diff; - - if (InGravityLapse) - { - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ShockBarrier_Timer = 20000; - } else ShockBarrier_Timer -= diff; - - //NetherBeam_Timer - if (NetherBeam_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_NETHER_BEAM); - - NetherBeam_Timer = 4000; - } else NetherBeam_Timer -= diff; - } - } - - if (!InGravityLapse) - DoMeleeAttackIfReady(); - } - } - } -}; - -//Thaladred the Darkener AI -struct boss_thaladred_the_darkenerAI : public advisorbase_ai -{ - boss_thaladred_the_darkenerAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Gaze_Timer; - uint32 Silence_Timer; - uint32 PsychicBlow_Timer; - - void Reset() - { - Gaze_Timer = 100; - Silence_Timer = 20000; - PsychicBlow_Timer = 10000; - - advisorbase_ai::Reset(); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_THALADRED_AGGRO, me); - me->AddThreat(who, 5000000.0f); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_THALADRED_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Gaze_Timer - if (Gaze_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoResetThreat(); - me->AddThreat(pTarget, 5000000.0f); - DoScriptText(EMOTE_THALADRED_GAZE, me, pTarget); - Gaze_Timer = 8500; - } - } else Gaze_Timer -= diff; - - //Silence_Timer - if (Silence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - Silence_Timer = 20000; - } else Silence_Timer -= diff; - - //PsychicBlow_Timer - if (PsychicBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PSYCHIC_BLOW); - PsychicBlow_Timer = 20000+rand()%5000; - } else PsychicBlow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Lord Sanguinar AI -struct boss_lord_sanguinarAI : public advisorbase_ai -{ - boss_lord_sanguinarAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Fear_Timer; - - void Reset() - { - Fear_Timer = 20000; - advisorbase_ai::Reset(); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_SANGUINAR_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_SANGUINAR_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); - Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds - } else Fear_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Grand Astromancer Capernian AI -struct boss_grand_astromancer_capernianAI : public advisorbase_ai -{ - boss_grand_astromancer_capernianAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Fireball_Timer; - uint32 Conflagration_Timer; - uint32 ArcaneExplosion_Timer; - uint32 Yell_Timer; - bool Yell; - - void Reset() - { - Fireball_Timer = 2000; - Conflagration_Timer = 20000; - ArcaneExplosion_Timer = 5000; - Yell_Timer = 2000; - Yell = false; - - advisorbase_ai::Reset(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_CAPERNIAN_DEATH, me); - } - - void AttackStart(Unit* who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(who, CAPERNIAN_DISTANCE); - } - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking Death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Yell_Timer - if (!Yell) - { - if (Yell_Timer <= diff) - { - DoScriptText(SAY_CAPERNIAN_AGGRO, me); - Yell = true; - } else Yell_Timer -= diff; - } - - //Fireball_Timer - if (Fireball_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CAPERNIAN_FIREBALL); - Fireball_Timer = 4000; - } else Fireball_Timer -= diff; - - //Conflagration_Timer - if (Conflagration_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget && me->IsWithinDistInMap(pTarget, 30)) - DoCast(pTarget, SPELL_CONFLAGRATION); - else - DoCast(me->getVictim(), SPELL_CONFLAGRATION); - - Conflagration_Timer = 10000+rand()%5000; - } else Conflagration_Timer -= diff; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - bool InMeleeRange = false; - Unit *pTarget = NULL; - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - //if in melee range - if (pUnit && pUnit->IsWithinDistInMap(me, 5)) - { - InMeleeRange = true; - pTarget = pUnit; - break; - } - } - - if (InMeleeRange) - DoCast(pTarget, SPELL_ARCANE_EXPLOSION); - - ArcaneExplosion_Timer = 4000+rand()%2000; - } else ArcaneExplosion_Timer -= diff; - - //Do NOT deal any melee damage. - } -}; - -//Master Engineer Telonicus AI -struct boss_master_engineer_telonicusAI : public advisorbase_ai -{ - boss_master_engineer_telonicusAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Bomb_Timer; - uint32 RemoteToy_Timer; - - void Reset() - { - Bomb_Timer = 10000; - RemoteToy_Timer = 5000; - - advisorbase_ai::Reset(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_TELONICUS_DEATH, me); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_TELONICUS_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking Death, do nothing - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Bomb_Timer - if (Bomb_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BOMB); - Bomb_Timer = 25000; - } else Bomb_Timer -= diff; - - //RemoteToy_Timer - if (RemoteToy_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_REMOTE_TOY); - - RemoteToy_Timer = 10000+rand()%5000; - } else RemoteToy_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Flame Strike AI -struct mob_kael_flamestrikeAI : public Scripted_NoMovementAI -{ - mob_kael_flamestrikeAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) {} - - uint32 Timer; - bool Casting; - bool KillSelf; - - void Reset() - { - Timer = 5000; - Casting = false; - KillSelf = false; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - } - - void MoveInLineOfSight(Unit * /*who*/) {} - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!Casting) - { - DoCast(me, SPELL_FLAME_STRIKE_VIS); - Casting = true; - } - - //Timer - if (Timer <= diff) - { - if (!KillSelf) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_FLAME_STRIKE_DMG); - } else me->Kill(me); - - KillSelf = true; - Timer = 1000; - } else Timer -= diff; - } -}; - -//Phoenix AI -struct mob_phoenix_tkAI : public ScriptedAI -{ - mob_phoenix_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 Cycle_Timer; - - void Reset() - { - Cycle_Timer = 2000; - DoCast(me, SPELL_BURN, true); - } - - void JustDied(Unit* /*killer*/) - { - //is this spell in use anylonger? - //DoCast(me, SPELL_EMBER_BLAST, true); - me->SummonCreature(NPC_PHOENIX_EGG,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,16000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Cycle_Timer <= diff) - { - //spell Burn should possible do this, but it doesn't, so do this for now. - uint32 dmg = urand(4500,5500); - if (me->GetHealth() > dmg) - me->SetHealth(uint32(me->GetHealth()-dmg)); - Cycle_Timer = 2000; - } else Cycle_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Phoenix Egg AI -struct mob_phoenix_egg_tkAI : public ScriptedAI -{ - mob_phoenix_egg_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 Rebirth_Timer; - - void Reset() - { - Rebirth_Timer = 15000; - } - - //ignore any - void MoveInLineOfSight(Unit* /*who*/) {} - - void AttackStart(Unit* who) - { - if (me->Attack(who, false)) - { - me->SetInCombatWith(who); - who->SetInCombatWith(me); - - DoStartNoMovement(who); - } - } - - void JustSummoned(Creature* summoned) - { - summoned->AddThreat(me->getVictim(), 0.0f); - summoned->CastSpell(summoned,SPELL_REBIRTH,false); - } - - void UpdateAI(const uint32 diff) - { - if (!Rebirth_Timer) - return; - - if (Rebirth_Timer <= diff) - { - me->SummonCreature(NPC_PHOENIX,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,5000); - Rebirth_Timer = 0; - } else Rebirth_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_kaelthas(Creature* pCreature) -{ - return new boss_kaelthasAI(pCreature); -} - -CreatureAI* GetAI_boss_thaladred_the_darkener(Creature* pCreature) -{ - return new boss_thaladred_the_darkenerAI(pCreature); -} - -CreatureAI* GetAI_boss_lord_sanguinar(Creature* pCreature) -{ - return new boss_lord_sanguinarAI(pCreature); -} - -CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature* pCreature) -{ - return new boss_grand_astromancer_capernianAI(pCreature); -} - -CreatureAI* GetAI_boss_master_engineer_telonicus(Creature* pCreature) -{ - return new boss_master_engineer_telonicusAI(pCreature); -} - -CreatureAI* GetAI_mob_kael_flamestrike(Creature* pCreature) -{ - return new mob_kael_flamestrikeAI(pCreature); -} - -CreatureAI* GetAI_mob_phoenix_tk(Creature* pCreature) -{ - return new mob_phoenix_tkAI(pCreature); -} - -CreatureAI* GetAI_mob_phoenix_egg_tk(Creature* pCreature) -{ - return new mob_phoenix_egg_tkAI(pCreature); -} - -void AddSC_boss_kaelthas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kaelthas"; - newscript->GetAI = &GetAI_boss_kaelthas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_thaladred_the_darkener"; - newscript->GetAI = &GetAI_boss_thaladred_the_darkener; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_sanguinar"; - newscript->GetAI = &GetAI_boss_lord_sanguinar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_grand_astromancer_capernian"; - newscript->GetAI = &GetAI_boss_grand_astromancer_capernian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_master_engineer_telonicus"; - newscript->GetAI = &GetAI_boss_master_engineer_telonicus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_kael_flamestrike"; - newscript->GetAI = &GetAI_mob_kael_flamestrike; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phoenix_tk"; - newscript->GetAI = &GetAI_mob_phoenix_tk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phoenix_egg_tk"; - newscript->GetAI = &GetAI_mob_phoenix_egg_tk; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/outland/tempest_keep/the_eye/boss_void_reaver.cpp b/src/server/scripts/outland/tempest_keep/the_eye/boss_void_reaver.cpp deleted file mode 100644 index e1b60b20948..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_eye/boss_void_reaver.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Void_Reaver -SD%Complete: 90 -SDComment: Should reset if raid are out of room. -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -enum eEnums -{ - SAY_AGGRO = -1550000, - SAY_SLAY1 = -1550001, - SAY_SLAY2 = -1550002, - SAY_SLAY3 = -1550003, - SAY_DEATH = -1550004, - SAY_POUNDING1 = -1550005, - SAY_POUNDING2 = -1550006, - - SPELL_POUNDING = 34162, - SPELL_ARCANE_ORB = 34172, - SPELL_KNOCK_AWAY = 25778, - SPELL_BERSERK = 27680 -}; - -struct boss_void_reaverAI : public ScriptedAI -{ - boss_void_reaverAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Pounding_Timer; - uint32 ArcaneOrb_Timer; - uint32 KnockAway_Timer; - uint32 Berserk_Timer; - - bool Enraged; - - void Reset() - { - Pounding_Timer = 15000; - ArcaneOrb_Timer = 3000; - KnockAway_Timer = 30000; - Berserk_Timer = 600000; - - Enraged = false; - - if (pInstance && me->isAlive()) - pInstance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_VOIDREAVEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Pounding - if (Pounding_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POUNDING); - - DoScriptText(RAND(SAY_POUNDING1,SAY_POUNDING2), me); - Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000) - } else Pounding_Timer -= diff; - - // Arcane Orb - if (ArcaneOrb_Timer <= diff) - { - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (!pTarget) - continue; - - // exclude pets & totems - if (pTarget->GetTypeId() != TYPEID_PLAYER) - continue; - - //18 yard radius minimum - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive() && !pTarget->IsWithinDist(me, 18, false)) - target_list.push_back(pTarget); - pTarget = NULL; - } - - if (target_list.size()) - pTarget = *(target_list.begin()+rand()%target_list.size()); - else - pTarget = me->getVictim(); - - if (pTarget) - me->CastSpell(pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(), SPELL_ARCANE_ORB, false, NULL, NULL, NULL, pTarget); - - ArcaneOrb_Timer = 3000; - } else ArcaneOrb_Timer -= diff; - - // Single Target knock back, reduces aggro - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCK_AWAY); - - //Drop 25% aggro - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-25); - - KnockAway_Timer = 30000; - } else KnockAway_Timer -= diff; - - //Berserk - if (Berserk_Timer < diff && !Enraged) - { - DoCast(me, SPELL_BERSERK); - Enraged = true; - } else Berserk_Timer -= diff; - - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_void_reaver(Creature* pCreature) -{ - return new boss_void_reaverAI (pCreature); -} - -void AddSC_boss_void_reaver() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_void_reaver"; - newscript->GetAI = &GetAI_boss_void_reaver; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_eye/instance_the_eye.cpp b/src/server/scripts/outland/tempest_keep/the_eye/instance_the_eye.cpp deleted file mode 100644 index 59c72071238..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_eye/instance_the_eye.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_The_Eye -SD%Complete: 100 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define MAX_ENCOUNTER 5 - -/* The Eye encounters: -0 - Kael'thas event -1 - Al' ar event -2 - Solarian Event -3 - Void Reaver event -*/ - -struct instance_the_eye : public ScriptedInstance -{ - instance_the_eye(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 ThaladredTheDarkener; - uint64 LordSanguinar; - uint64 GrandAstromancerCapernian; - uint64 MasterEngineerTelonicus; - uint64 Kaelthas; - uint64 Astromancer; - uint64 Alar; - - uint8 KaelthasEventPhase; - uint8 AlarEventPhase; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - ThaladredTheDarkener = 0; - LordSanguinar = 0; - GrandAstromancerCapernian = 0; - MasterEngineerTelonicus = 0; - Kaelthas = 0; - Astromancer = 0; - Alar = 0; - - KaelthasEventPhase = 0; - AlarEventPhase = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 20064: ThaladredTheDarkener = pCreature->GetGUID(); break; - case 20063: MasterEngineerTelonicus = pCreature->GetGUID(); break; - case 20062: GrandAstromancerCapernian = pCreature->GetGUID(); break; - case 20060: LordSanguinar = pCreature->GetGUID(); break; - case 19622: Kaelthas = pCreature->GetGUID(); break; - case 18805: Astromancer = pCreature->GetGUID(); break; - case 19514: Alar = pCreature->GetGUID(); break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_THALADREDTHEDARKENER: return ThaladredTheDarkener; - case DATA_LORDSANGUINAR: return LordSanguinar; - case DATA_GRANDASTROMANCERCAPERNIAN: return GrandAstromancerCapernian; - case DATA_MASTERENGINEERTELONICUS: return MasterEngineerTelonicus; - case DATA_KAELTHAS: return Kaelthas; - case DATA_ASTROMANCER: return Astromancer; - case DATA_ALAR: return Alar; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_ALAREVENT: AlarEventPhase = data; m_auiEncounter[0] = data; break; - case DATA_HIGHASTROMANCERSOLARIANEVENT: m_auiEncounter[1] = data; break; - case DATA_VOIDREAVEREVENT: m_auiEncounter[2] = data; break; - case DATA_KAELTHASEVENT: KaelthasEventPhase = data; m_auiEncounter[3] = data; break; - } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_ALAREVENT: return AlarEventPhase; - case DATA_HIGHASTROMANCERSOLARIANEVENT: return m_auiEncounter[1]; - case DATA_VOIDREAVEREVENT: return m_auiEncounter[2]; - case DATA_KAELTHASEVENT: return KaelthasEventPhase; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_the_eye(Map* pMap) -{ - return new instance_the_eye(pMap); -} - -void AddSC_instance_the_eye() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_the_eye"; - newscript->GetInstanceData = &GetInstanceData_instance_the_eye; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_eye/the_eye.cpp b/src/server/scripts/outland/tempest_keep/the_eye/the_eye.cpp deleted file mode 100644 index 97021fdc031..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_eye/the_eye.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: The_Eye -SD%Complete: 100 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -/* ContentData -mob_crystalcore_devastator -EndContentData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define SPELL_COUNTERCHARGE 35035 -#define SPELL_KNOCKAWAY 22893 - -struct mob_crystalcore_devastatorAI : public ScriptedAI -{ - mob_crystalcore_devastatorAI(Creature *c) : ScriptedAI(c) {} - - uint32 Knockaway_Timer; - uint32 Countercharge_Timer; - - void Reset() - { - Countercharge_Timer = 9000; - Knockaway_Timer = 25000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Check if we have a current target - //Knockaway_Timer - if (Knockaway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); - - // current aggro target is knocked away pick new target - Unit* pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - - if (!pTarget || pTarget == me->getVictim()) - pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); - - if (pTarget) - me->TauntApply(pTarget); - - Knockaway_Timer = 23000; - } else Knockaway_Timer -= diff; - - //Countercharge_Timer - if (Countercharge_Timer <= diff) - { - DoCast(me, SPELL_COUNTERCHARGE); - Countercharge_Timer = 45000; - } else Countercharge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_crystalcore_devastator(Creature* pCreature) -{ - return new mob_crystalcore_devastatorAI (pCreature); -} - -void AddSC_the_eye() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_crystalcore_devastator"; - newscript->GetAI = &GetAI_mob_crystalcore_devastator; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_eye/the_eye.h b/src/server/scripts/outland/tempest_keep/the_eye/the_eye.h deleted file mode 100644 index d0d3ea09061..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_eye/the_eye.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_THE_EYE_H -#define DEF_THE_EYE_H - -#define DATA_ALAREVENT 1 -#define DATA_ASTROMANCER 2 -#define DATA_GRANDASTROMANCERCAPERNIAN 3 -#define DATA_HIGHASTROMANCERSOLARIANEVENT 4 -#define DATA_KAELTHAS 5 -#define DATA_KAELTHASEVENT 6 -#define DATA_LORDSANGUINAR 7 -#define DATA_MASTERENGINEERTELONICUS 8 -#define DATA_THALADREDTHEDARKENER 10 -#define DATA_VOIDREAVEREVENT 11 -#define DATA_ALAR 12 -#endif - diff --git a/src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp b/src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp deleted file mode 100644 index b9c365eda65..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gatewatcher_Gyrokill -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -//not used -#define SAY_AGGRO -1554000 -#define SAY_SAW_ATTACK1 -1554001 -#define SAY_SAW_ATTACK2 -1554002 -#define SAY_SLAY1 -1554003 -#define SAY_SLAY2 -1554004 -#define SAY_DEATH -1554005 - -#define SPELL_STREAM_OF_MACHINE_FLUID 35311 -#define SPELL_SAW_BLADE 35318 -#define H_SPELL_SAW_BLADE 39192 -#define SPELL_SHADOW_POWER 35322 -#define H_SPELL_SHADOW_POWER 39193 - diff --git a/src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp b/src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp deleted file mode 100644 index 50c3a6171ce..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Gatewatcher_Ironhand -SD%Complete: 75 -SDComment: -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1554006 -#define SAY_HAMMER_1 -1554007 -#define SAY_HAMMER_2 -1554008 -#define SAY_SLAY_1 -1554009 -#define SAY_SLAY_2 -1554010 -#define SAY_DEATH_1 -1554011 -#define EMOTE_HAMMER -1554012 - -// Spells to be casted -#define SPELL_SHADOW_POWER 35322 -#define H_SPELL_SHADOW_POWER 39193 -#define SPELL_HAMMER_PUNCH 35326 -#define SPELL_JACKHAMMER 35327 -#define H_SPELL_JACKHAMMER 39194 -#define SPELL_STREAM_OF_MACHINE_FLUID 35311 - -// Gatewatcher Iron-Hand AI -struct boss_gatewatcher_iron_handAI : public ScriptedAI -{ - boss_gatewatcher_iron_handAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Shadow_Power_Timer; - uint32 Jackhammer_Timer; - uint32 Stream_of_Machine_Fluid_Timer; - - void Reset() - { - Shadow_Power_Timer = 25000; - Jackhammer_Timer = 45000; - Stream_of_Machine_Fluid_Timer = 55000; - - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO_1, me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH_1, me); - //TODO: Add door check/open code - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Shadow Power - if (Shadow_Power_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_POWER); - Shadow_Power_Timer = 20000 + rand()%8000; - } else Shadow_Power_Timer -= diff; - - //Jack Hammer - if (Jackhammer_Timer <= diff) - { - //TODO: expect cast this about 5 times in a row (?), announce it by emote only once - DoScriptText(EMOTE_HAMMER, me); - DoCast(me->getVictim(), SPELL_JACKHAMMER); - - //chance to yell, but not same time as emote (after spell in fact casted) - if (rand()%2) - return; - - DoScriptText(RAND(SAY_HAMMER_1,SAY_HAMMER_2), me); - Jackhammer_Timer = 30000; - } else Jackhammer_Timer -= diff; - - //Stream of Machine Fluid - if (Stream_of_Machine_Fluid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STREAM_OF_MACHINE_FLUID); - Stream_of_Machine_Fluid_Timer = 35000 + rand()%15000; - } else Stream_of_Machine_Fluid_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gatewatcher_iron_hand(Creature* pCreature) -{ - return new boss_gatewatcher_iron_handAI (pCreature); -} - -void AddSC_boss_gatewatcher_iron_hand() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gatewatcher_iron_hand"; - newscript->GetAI = &GetAI_boss_gatewatcher_iron_hand; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp deleted file mode 100644 index ededec0196d..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Nethermancer_Sepethrea -SD%Complete: 90 -SDComment: Need adjustments to initial summons -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" -#include "mechanar.h" - -#define SAY_AGGRO -1554013 -#define SAY_SUMMON -1554014 -#define SAY_DRAGONS_BREATH_1 -1554015 -#define SAY_DRAGONS_BREATH_2 -1554016 -#define SAY_SLAY1 -1554017 -#define SAY_SLAY2 -1554018 -#define SAY_DEATH -1554019 - -#define SPELL_SUMMON_RAGIN_FLAMES 35275 -#define H_SPELL_SUMMON_RAGIN_FLAMES 39084 - -#define SPELL_FROST_ATTACK 35263 -#define SPELL_ARCANE_BLAST 35314 -#define SPELL_DRAGONS_BREATH 35250 -#define SPELL_KNOCKBACK 37317 -#define SPELL_SOLARBURN 35267 - -struct boss_nethermancer_sepethreaAI : public ScriptedAI -{ - boss_nethermancer_sepethreaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 frost_attack_Timer; - uint32 arcane_blast_Timer; - uint32 dragons_breath_Timer; - uint32 knockback_Timer; - uint32 solarburn_Timer; - - void Reset() - { - frost_attack_Timer = 7000 + rand()%3000; - arcane_blast_Timer = 12000 + rand()%6000; - dragons_breath_Timer = 18000 + rand()%4000; - knockback_Timer = 22000 + rand()%6000; - solarburn_Timer = 30000; - - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, IN_PROGRESS); - - DoScriptText(SAY_AGGRO, me); - DoCast(who, SPELL_SUMMON_RAGIN_FLAMES); - DoScriptText(SAY_SUMMON, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frost Attack - if (frost_attack_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_ATTACK); - frost_attack_Timer = 7000 + rand()%3000; - } else frost_attack_Timer -= diff; - - //Arcane Blast - if (arcane_blast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BLAST); - arcane_blast_Timer = 15000; - } else arcane_blast_Timer -= diff; - - //Dragons Breath - if (dragons_breath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DRAGONS_BREATH); - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_DRAGONS_BREATH_1,SAY_DRAGONS_BREATH_2), me); - } - dragons_breath_Timer = 12000 + rand()%10000; - } else dragons_breath_Timer -= diff; - - //Knockback - if (knockback_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKBACK); - knockback_Timer = 15000 + rand()%10000; - } else knockback_Timer -= diff; - - //Solarburn - if (solarburn_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARBURN); - solarburn_Timer = 30000; - } else solarburn_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_nethermancer_sepethrea(Creature* pCreature) -{ - return new boss_nethermancer_sepethreaAI (pCreature); -} - -#define SPELL_INFERNO 35268 -#define H_SPELL_INFERNO 39346 -#define SPELL_FIRE_TAIL 35278 - -struct mob_ragin_flamesAI : public ScriptedAI -{ - mob_ragin_flamesAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 inferno_Timer; - uint32 flame_timer; - uint32 Check_Timer; - - bool onlyonce; - - void Reset() - { - inferno_Timer = 10000; - flame_timer = 500; - Check_Timer = 2000; - onlyonce = false; - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); - } - - void EnterCombat(Unit* /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Check_Timer - if (Check_Timer <= diff) - { - if (pInstance) - { - if (pInstance->GetData(DATA_NETHERMANCER_EVENT) != IN_PROGRESS) - { - //remove - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } - } - Check_Timer = 1000; - } else Check_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (!onlyonce) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - me->GetMotionMaster()->MoveChase(pTarget); - onlyonce = true; - } - - if (inferno_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_INFERNO); - me->TauntApply(me->getVictim()); - inferno_Timer = 10000; - } else inferno_Timer -= diff; - - if (flame_timer <= diff) - { - DoCast(me, SPELL_FIRE_TAIL); - flame_timer = 500; - } else flame_timer -=diff; - - DoMeleeAttackIfReady(); - } - -}; -CreatureAI* GetAI_mob_ragin_flames(Creature* pCreature) -{ - return new mob_ragin_flamesAI (pCreature); -} -void AddSC_boss_nethermancer_sepethrea() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nethermancer_sepethrea"; - newscript->GetAI = &GetAI_boss_nethermancer_sepethrea; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ragin_flames"; - newscript->GetAI = &GetAI_mob_ragin_flames; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp b/src/server/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp deleted file mode 100644 index c0c06704db7..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss Pathaleon the Calculator -SD%Complete: 50 -SDComment: Event missing. Script for himself 99% blizzlike. -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1554020 -#define SAY_DOMINATION_1 -1554021 -#define SAY_DOMINATION_2 -1554022 -#define SAY_SUMMON -1554023 -#define SAY_ENRAGE -1554024 -#define SAY_SLAY_1 -1554025 -#define SAY_SLAY_2 -1554026 -#define SAY_DEATH -1554027 - -// Spells to be casted -#define SPELL_MANA_TAP 36021 -#define SPELL_ARCANE_TORRENT 36022 -#define SPELL_DOMINATION 35280 -#define H_SPELL_ARCANE_EXPLOSION 15453 -#define SPELL_FRENZY 36992 - -#define SPELL_SUMMON_NETHER_WRAITH_1 35285 //Spells work, but not implemented -#define SPELL_SUMMON_NETHER_WRAITH_2 35286 -#define SPELL_SUMMON_NETHER_WRAITH_3 35287 -#define SPELL_SUMMON_NETHER_WRAITH_4 35288 - -// Add Spells -#define SPELL_DETONATION 35058 -#define SPELL_ARCANE_MISSILES 35034 - -struct boss_pathaleon_the_calculatorAI : public ScriptedAI -{ - boss_pathaleon_the_calculatorAI(Creature *c) : ScriptedAI(c), summons(me) - { - } - - uint32 Summon_Timer; - SummonList summons; - uint32 ManaTap_Timer; - uint32 ArcaneTorrent_Timer; - uint32 Domination_Timer; - uint32 ArcaneExplosion_Timer; - - bool Enraged; - - uint32 Counter; - - void Reset() - { - Summon_Timer = 30000; - ManaTap_Timer = 12000 + rand()%8000; - ArcaneTorrent_Timer = 16000 + rand()%9000; - Domination_Timer = 25000 + rand()%15000; - ArcaneExplosion_Timer = 8000 + rand()%5000; - - Enraged = false; - - Counter = 0; - summons.DespawnAll(); - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - summons.DespawnAll(); - } - - void JustSummoned(Creature *summon) {summons.Summon(summon);} - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Summon_Timer <= diff) - { - for (uint8 i = 0; i < 3; ++i) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - Creature* Wraith = me->SummonCreature(21062,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - if (pTarget && Wraith) - Wraith->AI()->AttackStart(pTarget); - } - DoScriptText(SAY_SUMMON, me); - Summon_Timer = 30000 + rand()%15000; - } else Summon_Timer -= diff; - - if (ManaTap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MANA_TAP); - ManaTap_Timer = 14000 + rand()%8000; - } else ManaTap_Timer -= diff; - - if (ArcaneTorrent_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_TORRENT); - ArcaneTorrent_Timer = 12000 + rand()%6000; - } else ArcaneTorrent_Timer -= diff; - - if (Domination_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - DoScriptText(RAND(SAY_DOMINATION_1,SAY_DOMINATION_2), me); - - DoCast(pTarget, SPELL_DOMINATION); - } - Domination_Timer = 25000 + rand()%5000; - } else Domination_Timer -= diff; - - //Only casting if Heroic Mode is used - if (IsHeroic()) - { - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), H_SPELL_ARCANE_EXPLOSION); - ArcaneExplosion_Timer = 10000 + rand()%4000; - } else ArcaneExplosion_Timer -= diff; - } - - if (!Enraged && me->GetHealth()*100 / me->GetMaxHealth() < 21) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(SAY_ENRAGE, me); - Enraged = true; - - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_pathaleon_the_calculator(Creature* pCreature) -{ - return new boss_pathaleon_the_calculatorAI (pCreature); -} - -struct mob_nether_wraithAI : public ScriptedAI -{ - mob_nether_wraithAI(Creature *c) : ScriptedAI(c) {} - - uint32 ArcaneMissiles_Timer; - uint32 Detonation_Timer; - uint32 Die_Timer; - bool Detonation; - - void Reset() - { - ArcaneMissiles_Timer = 1000 + rand()%3000; - Detonation_Timer = 20000; - Die_Timer = 2200; - Detonation = false; - - } - - void EnterCombat(Unit* /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ArcaneMissiles_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_ARCANE_MISSILES); - else - DoCast(me->getVictim(), SPELL_ARCANE_MISSILES); - - ArcaneMissiles_Timer = 5000 + rand()%5000; - } else ArcaneMissiles_Timer -=diff; - - if (!Detonation) - { - if (Detonation_Timer <= diff) - { - DoCast(me, SPELL_DETONATION); - Detonation = true; - } else Detonation_Timer -= diff; - } - - if (Detonation) - { - if (Die_Timer <= diff) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } else Die_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - -}; -CreatureAI* GetAI_mob_nether_wraith(Creature* pCreature) -{ - return new mob_nether_wraithAI (pCreature); -} - -void AddSC_boss_pathaleon_the_calculator() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_pathaleon_the_calculator"; - newscript->GetAI = &GetAI_boss_pathaleon_the_calculator; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_nether_wraith"; - newscript->GetAI = &GetAI_mob_nether_wraith; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_mechanar/instance_mechanar.cpp b/src/server/scripts/outland/tempest_keep/the_mechanar/instance_mechanar.cpp deleted file mode 100644 index c70da24ea3f..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_mechanar/instance_mechanar.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Mechanar -SD%Complete: 100 -SDComment: -SDCategory: Mechanar -EndScriptData */ - -#include "ScriptedPch.h" -#include "mechanar.h" - -#define MAX_ENCOUNTER 1 - -struct instance_mechanar : public ScriptedInstance -{ - instance_mechanar(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_NETHERMANCER_EVENT: return m_auiEncounter[0]; - } - - return false; - } - - uint64 GetData64 (uint32 /*identifier*/) - { - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_NETHERMANCER_EVENT: m_auiEncounter[0] = data; break; - } - } -}; - -InstanceData* GetInstanceData_instance_mechanar(Map* pMap) -{ - return new instance_mechanar(pMap); -} - -void AddSC_instance_mechanar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_mechanar"; - newscript->GetInstanceData = &GetInstanceData_instance_mechanar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/tempest_keep/the_mechanar/mechanar.h b/src/server/scripts/outland/tempest_keep/the_mechanar/mechanar.h deleted file mode 100644 index d1b53eebf53..00000000000 --- a/src/server/scripts/outland/tempest_keep/the_mechanar/mechanar.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DEF_MECHANAR_H -#define DEF_MECHANAR_H - -#define DATA_NETHERMANCER_EVENT 1 -#endif - diff --git a/src/server/scripts/outland/terokkar_forest.cpp b/src/server/scripts/outland/terokkar_forest.cpp deleted file mode 100644 index d593fdd8ca9..00000000000 --- a/src/server/scripts/outland/terokkar_forest.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Terokkar_Forest -SD%Complete: 85 -SDComment: Quest support: 9889, 10009, 10873, 10896, 10898, 11096, 10052, 10051. Skettis->Ogri'la Flight -SDCategory: Terokkar Forest -EndScriptData */ - -/* ContentData -mob_unkor_the_ruthless -mob_infested_root_walker -mob_rotting_forest_rager -mob_netherweb_victim -npc_floon -npc_isla_starmane -npc_slim -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## mob_unkor_the_ruthless -######*/ - -#define SAY_SUBMIT -1000194 - -#define FACTION_HOSTILE 45 -#define FACTION_FRIENDLY 35 -#define QUEST_DONTKILLTHEFATONE 9889 - -#define SPELL_PULVERIZE 2676 -//#define SPELL_QUID9889 32174 - -struct mob_unkor_the_ruthlessAI : public ScriptedAI -{ - mob_unkor_the_ruthlessAI(Creature* c) : ScriptedAI(c) {} - - bool CanDoQuest; - uint32 UnkorUnfriendly_Timer; - uint32 Pulverize_Timer; - - void Reset() - { - CanDoQuest = false; - UnkorUnfriendly_Timer = 0; - Pulverize_Timer = 3000; - me->SetStandState(UNIT_STAND_STATE_STAND); - me->setFaction(FACTION_HOSTILE); - } - - void EnterCombat(Unit * /*who*/) {} - - void DoNice() - { - DoScriptText(SAY_SUBMIT, me); - me->setFaction(FACTION_FRIENDLY); - me->SetStandState(UNIT_STAND_STATE_SIT); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - UnkorUnfriendly_Timer = 60000; - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetTypeId() == TYPEID_PLAYER) - if ((me->GetHealth()-damage)*100 / me->GetMaxHealth() < 30) - { - if (Group* pGroup = CAST_PLR(done_by)->GetGroup()) - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player *pGroupie = itr->getSource(); - if (pGroupie && - pGroupie->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && - pGroupie->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, 18260) == 10) - { - pGroupie->AreaExploredOrEventHappens(QUEST_DONTKILLTHEFATONE); - if (!CanDoQuest) - CanDoQuest = true; - } - } - } else - if (CAST_PLR(done_by)->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && - CAST_PLR(done_by)->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, 18260) == 10) - { - CAST_PLR(done_by)->AreaExploredOrEventHappens(QUEST_DONTKILLTHEFATONE); - CanDoQuest = true; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (CanDoQuest) - { - if (!UnkorUnfriendly_Timer) - { - //DoCast(me, SPELL_QUID9889); //not using spell for now - DoNice(); - } - else - { - if (UnkorUnfriendly_Timer <= diff) - { - EnterEvadeMode(); - return; - } else UnkorUnfriendly_Timer -= diff; - } - } - - if (!UpdateVictim()) - return; - - if (Pulverize_Timer <= diff) - { - DoCast(me, SPELL_PULVERIZE); - Pulverize_Timer = 9000; - } else Pulverize_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_unkor_the_ruthless(Creature* pCreature) -{ - return new mob_unkor_the_ruthlessAI (pCreature); -} - -/*###### -## mob_infested_root_walker -######*/ - -struct mob_infested_root_walkerAI : public ScriptedAI -{ - mob_infested_root_walkerAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - void EnterCombat(Unit * /*who*/) { } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by && done_by->GetTypeId() == TYPEID_PLAYER) - if (me->GetHealth() <= damage) - if (rand()%100 < 75) - //Summon Wood Mites - DoCast(me, 39130, true); - } -}; -CreatureAI* GetAI_mob_infested_root_walker(Creature* pCreature) -{ - return new mob_infested_root_walkerAI (pCreature); -} - -/*###### -## mob_skywing -######*/ -struct npc_skywingAI : public npc_escortAI -{ -public: - npc_skywingAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - if (!pPlayer) - return; - - switch(i) - { - case 8: - pPlayer->AreaExploredOrEventHappens(10898); - break; - } - } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - if (who->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(who)->GetQuestStatus(10898) == QUEST_STATUS_INCOMPLETE) - { - float Radius = 10.0; - if (me->IsWithinDistInMap(who, Radius)) - { - Start(false, false, who->GetGUID()); - } - } - } - } - - void Reset() {} - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_skywingAI(Creature* pCreature) -{ - return new npc_skywingAI(pCreature); -} - -/*###### -## mob_rotting_forest_rager -######*/ - -struct mob_rotting_forest_ragerAI : public ScriptedAI -{ - mob_rotting_forest_ragerAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - void EnterCombat(Unit * /*who*/) { } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetTypeId() == TYPEID_PLAYER) - if (me->GetHealth() <= damage) - if (rand()%100 < 75) - //Summon Lots of Wood Mights - DoCast(me, 39134, true); - } -}; -CreatureAI* GetAI_mob_rotting_forest_rager(Creature* pCreature) -{ - return new mob_rotting_forest_ragerAI (pCreature); -} - -/*###### -## mob_netherweb_victim -######*/ - -#define QUEST_TARGET 22459 -//#define SPELL_FREE_WEBBED 38950 - -const uint32 netherwebVictims[6] = -{ - 18470, 16805, 21242, 18452, 22482, 21285 -}; -struct mob_netherweb_victimAI : public ScriptedAI -{ - mob_netherweb_victimAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - void EnterCombat(Unit * /*who*/) { } - void MoveInLineOfSight(Unit * /*who*/) { } - - void JustDied(Unit* Killer) - { - if (Killer->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(Killer)->GetQuestStatus(10873) == QUEST_STATUS_INCOMPLETE) - { - if (rand()%100 < 25) - { - me->SummonCreature(QUEST_TARGET, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - CAST_PLR(Killer)->KilledMonsterCredit(QUEST_TARGET, me->GetGUID()); - } - else - me->SummonCreature(netherwebVictims[rand()%6], 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - - if (rand()%100 < 75) - me->SummonCreature(netherwebVictims[rand()%6], 0.0f, 0.0f, 0.0f,0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - me->SummonCreature(netherwebVictims[rand()%6], 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - } - } - } -}; -CreatureAI* GetAI_mob_netherweb_victim(Creature* pCreature) -{ - return new mob_netherweb_victimAI (pCreature); -} - -/*###### -## npc_floon -######*/ - -#define GOSSIP_FLOON1 "You owe Sim'salabim money. Hand them over or die!" -#define GOSSIP_FLOON2 "Hand over the money or die...again!" - -enum eFloon -{ - SAY_FLOON_ATTACK = -1000195, - - SPELL_SILENCE = 6726, - SPELL_FROSTBOLT = 9672, - SPELL_FROST_NOVA = 11831, - - FACTION_HOSTILE_FL = 1738, - QUEST_CRACK_SKULLS = 10009 -}; - -struct npc_floonAI : public ScriptedAI -{ - npc_floonAI(Creature* c) : ScriptedAI(c) - { - m_uiNormFaction = c->getFaction(); - } - - uint32 m_uiNormFaction; - uint32 Silence_Timer; - uint32 Frostbolt_Timer; - uint32 FrostNova_Timer; - - void Reset() - { - Silence_Timer = 2000; - Frostbolt_Timer = 4000; - FrostNova_Timer = 9000; - if (me->getFaction() != m_uiNormFaction) - me->setFaction(m_uiNormFaction); - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Silence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - Silence_Timer = 30000; - } else Silence_Timer -= diff; - - if (FrostNova_Timer <= diff) - { - DoCast(me, SPELL_FROST_NOVA); - FrostNova_Timer = 20000; - } else FrostNova_Timer -= diff; - - if (Frostbolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - Frostbolt_Timer = 5000; - } else Frostbolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_floon(Creature* pCreature) -{ - return new npc_floonAI (pCreature); -} - -bool GossipHello_npc_floon(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FLOON1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(9442, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_floon(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FLOON2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(9443, pCreature->GetGUID()); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(FACTION_HOSTILE_FL); - DoScriptText(SAY_FLOON_ATTACK, pCreature, pPlayer); - pCreature->AI()->AttackStart(pPlayer); - } - return true; -} - -/*###### -## npc_isla_starmane -######*/ - -#define SAY_PROGRESS_1 -1100353 -#define SAY_PROGRESS_2 -1100354 -#define SAY_PROGRESS_3 -1100355 -#define SAY_PROGRESS_4 -1100356 - -#define QUEST_EFTW_H 10052 -#define QUEST_EFTW_A 10051 -#define GO_CAGE 182794 -#define SPELL_CAT 32447 - -struct npc_isla_starmaneAI : public npc_escortAI -{ - npc_isla_starmaneAI(Creature* c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 0: - { - GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 10); - if (Cage) - Cage->SetGoState(GO_STATE_ACTIVE); - } - break; - case 2: DoScriptText(SAY_PROGRESS_1, me, pPlayer); break; - case 5: DoScriptText(SAY_PROGRESS_2, me, pPlayer); break; - case 6: DoScriptText(SAY_PROGRESS_3, me, pPlayer); break; - case 29:DoScriptText(SAY_PROGRESS_4, me, pPlayer); - if (pPlayer) - { - if (pPlayer->GetTeam() == ALLIANCE) - pPlayer->GroupEventHappens(QUEST_EFTW_A, me); - else if (pPlayer->GetTeam() == HORDE) - pPlayer->GroupEventHappens(QUEST_EFTW_H, me); - } - me->SetInFront(pPlayer); break; - case 30: me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); break; - case 31: DoCast(me, SPELL_CAT); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); break; - } - } - - void Reset() - { - me->RestoreFaction(); - } - - void JustDied(Unit* /*killer*/) - { - if (Player* pPlayer = GetPlayerForEscort()) - { - if (pPlayer->GetTeam() == ALLIANCE) - pPlayer->FailQuest(QUEST_EFTW_A); - else if (pPlayer->GetTeam() == HORDE) - pPlayer->FailQuest(QUEST_EFTW_H); - } - } -}; - -bool QuestAccept_npc_isla_starmane(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_EFTW_H || quest->GetQuestId() == QUEST_EFTW_A) - { - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - pCreature->setFaction(113); - } - return true; -} - -CreatureAI* GetAI_npc_isla_starmaneAI(Creature* pCreature) -{ - return new npc_isla_starmaneAI(pCreature); -} - -/*###### -## go_skull_pile -######*/ -#define GOSSIP_S_DARKSCREECHER_AKKARAI "Summon Darkscreecher Akkarai" -#define GOSSIP_S_KARROG "Summon Karrog" -#define GOSSIP_S_GEZZARAK_THE_HUNTRESS "Summon Gezzarak the Huntress" -#define GOSSIP_S_VAKKIZ_THE_WINDRAGER "Summon Vakkiz the Windrager" - -bool GossipHello_go_skull_pile(Player* pPlayer, GameObject* pGo) -{ - if ((pPlayer->GetQuestStatus(11885) == QUEST_STATUS_INCOMPLETE) || pPlayer->GetQuestRewardStatus(11885)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_DARKSCREECHER_AKKARAI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_KARROG, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_GEZZARAK_THE_HUNTRESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_VAKKIZ_THE_WINDRAGER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - } - - pPlayer->SEND_GOSSIP_MENU(pGo->GetGOInfo()->questgiver.gossipID, pGo->GetGUID()); - return true; -} - -void SendActionMenu_go_skull_pile(Player* pPlayer, GameObject* /*pGo*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->CastSpell(pPlayer,40642,false); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->CastSpell(pPlayer,40640,false); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->CastSpell(pPlayer,40632,false); - break; - case GOSSIP_ACTION_INFO_DEF + 4: - pPlayer->CastSpell(pPlayer,40644,false); - break; - } -} - -bool GossipSelect_go_skull_pile(Player* pPlayer, GameObject* pGo, uint32 uiSender, uint32 uiAction) -{ - switch(uiSender) - { - case GOSSIP_SENDER_MAIN: SendActionMenu_go_skull_pile(pPlayer, pGo, uiAction); break; - } - return true; -} - -/*###### -## npc_slim -######*/ - -enum eSlim -{ - FACTION_CONSORTIUM = 933 -}; - -bool GossipHello_npc_slim(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isVendor() && pPlayer->GetReputationRank(FACTION_CONSORTIUM) >= REP_FRIENDLY) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - pPlayer->SEND_GOSSIP_MENU(9896, pCreature->GetGUID()); - } - else - pPlayer->SEND_GOSSIP_MENU(9895, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_slim(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*######## -####npc_akuno -#####*/ - -enum eAkuno -{ - QUEST_ESCAPING_THE_TOMB = 10887, - NPC_CABAL_SKRIMISHER = 21661 -}; - -struct npc_akunoAI : public npc_escortAI -{ - npc_akunoAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 3: - me->SummonCreature(NPC_CABAL_SKRIMISHER,-2795.99,5420.33,-34.53,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - me->SummonCreature(NPC_CABAL_SKRIMISHER,-2793.55,5412.79,-34.53,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 11: - if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) - pPlayer->GroupEventHappens(QUEST_ESCAPING_THE_TOMB,me); - break; - } - } - - void JustSummoned(Creature* summon) - { - summon->AI()->AttackStart(me); - } -}; - -bool QuestAccept_npc_akuno(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_ESCAPING_THE_TOMB) - { - if (npc_akunoAI* pEscortAI = CAST_AI(npc_akunoAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID()); - - if (pPlayer->GetTeamId() == TEAM_ALLIANCE) - pCreature->setFaction(FACTION_ESCORT_A_NEUTRAL_PASSIVE); - else - pCreature->setFaction(FACTION_ESCORT_H_NEUTRAL_PASSIVE); - } - return true; -} - -CreatureAI* GetAI_npc_akuno(Creature* pCreature) -{ - return new npc_akunoAI(pCreature); -} - -void AddSC_terokkar_forest() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_unkor_the_ruthless"; - newscript->GetAI = &GetAI_mob_unkor_the_ruthless; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_infested_root_walker"; - newscript->GetAI = &GetAI_mob_infested_root_walker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_rotting_forest_rager"; - newscript->GetAI = &GetAI_mob_rotting_forest_rager; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_netherweb_victim"; - newscript->GetAI = &GetAI_mob_netherweb_victim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_floon"; - newscript->GetAI = &GetAI_npc_floon; - newscript->pGossipHello = &GossipHello_npc_floon; - newscript->pGossipSelect = &GossipSelect_npc_floon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_isla_starmane"; - newscript->GetAI = &GetAI_npc_isla_starmaneAI; - newscript->pQuestAccept = &QuestAccept_npc_isla_starmane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_skull_pile"; - newscript->pGOHello = &GossipHello_go_skull_pile; - newscript->pGOSelect = &GossipSelect_go_skull_pile; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_skywing"; - newscript->GetAI = &GetAI_npc_skywingAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_slim"; - newscript->pGossipHello = &GossipHello_npc_slim; - newscript->pGossipSelect = &GossipSelect_npc_slim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_akuno"; - newscript->GetAI = &GetAI_npc_akuno; - newscript->pQuestAccept = &QuestAccept_npc_akuno; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/outland/zangarmarsh.cpp b/src/server/scripts/outland/zangarmarsh.cpp deleted file mode 100644 index 5a07165595b..00000000000 --- a/src/server/scripts/outland/zangarmarsh.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Zangarmarsh -SD%Complete: 100 -SDComment: Quest support: 9752, 9785, 9803, 10009. Mark Of ... buffs. -SDCategory: Zangarmarsh -EndScriptData */ - -/* ContentData -npcs_ashyen_and_keleth -npc_cooshcoosh -npc_elder_kuruti -npc_mortog_steamhead -npc_kayra_longmane -npc_timothy_daniels -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -/*###### -## npcs_ashyen_and_keleth -######*/ - -#define GOSSIP_ITEM_BLESS_ASH "Grant me your mark, wise ancient." -#define GOSSIP_ITEM_BLESS_KEL "Grant me your mark, mighty ancient." -//signed for 17900 but used by 17900,17901 -#define GOSSIP_REWARD_BLESS -1000359 -//#define TEXT_BLESSINGS "" - -bool GossipHello_npcs_ashyen_and_keleth(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetReputationRank(942) > REP_NEUTRAL) - { - if (pCreature->GetEntry() == 17900) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BLESS_ASH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - if (pCreature->GetEntry() == 17901) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BLESS_KEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - } - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npcs_ashyen_and_keleth(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pCreature->setPowerType(POWER_MANA); - pCreature->SetMaxPower(POWER_MANA,200); //set a "fake" mana value, we can't depend on database doing it in this case - pCreature->SetPower(POWER_MANA,200); - - if (pCreature->GetEntry() == 17900) //check which Creature we are dealing with - { - switch (pPlayer->GetReputationRank(942)) - { //mark of lore - case REP_FRIENDLY: - pCreature->CastSpell(pPlayer, 31808, true); - DoScriptText(GOSSIP_REWARD_BLESS, pCreature); - break; - case REP_HONORED: - pCreature->CastSpell(pPlayer, 31810, true); - DoScriptText(GOSSIP_REWARD_BLESS, pCreature); - break; - case REP_REVERED: - pCreature->CastSpell(pPlayer, 31811, true); - DoScriptText(GOSSIP_REWARD_BLESS, pCreature); - break; - case REP_EXALTED: - pCreature->CastSpell(pPlayer, 31815, true); - DoScriptText(GOSSIP_REWARD_BLESS, pCreature); - break; - } - } - - if (pCreature->GetEntry() == 17901) - { - switch (pPlayer->GetReputationRank(942)) //mark of war - { - case REP_FRIENDLY: - pCreature->CastSpell(pPlayer, 31807, true); - DoScriptText(GOSSIP_REWARD_BLESS, pCreature); - break; - case REP_HONORED: - pCreature->CastSpell(pPlayer, 31812, true); - DoScriptText(GOSSIP_REWARD_BLESS, pCreature); - break; - case REP_REVERED: - pCreature->CastSpell(pPlayer, 31813, true); - DoScriptText(GOSSIP_REWARD_BLESS, pCreature); - break; - case REP_EXALTED: - pCreature->CastSpell(pPlayer, 31814, true); - DoScriptText(GOSSIP_REWARD_BLESS, pCreature); - break; - } - } - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - } - return true; -} - -/*###### -## npc_cooshcoosh -######*/ - -#define GOSSIP_COOSH "You owe Sim'salabim money. Hand them over or die!" - -enum eCooshhooosh -{ - SPELL_LIGHTNING_BOLT = 9532, - QUEST_CRACK_SKULLS = 10009, - FACTION_HOSTILE_CO = 45 -}; - -struct npc_cooshcooshAI : public ScriptedAI -{ - npc_cooshcooshAI(Creature* c) : ScriptedAI(c) - { - m_uiNormFaction = c->getFaction(); - } - - uint32 m_uiNormFaction; - uint32 LightningBolt_Timer; - - void Reset() - { - LightningBolt_Timer = 2000; - if (me->getFaction() != m_uiNormFaction) - me->setFaction(m_uiNormFaction); - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (LightningBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); - LightningBolt_Timer = 5000; - } else LightningBolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_cooshcoosh(Creature* pCreature) -{ - return new npc_cooshcooshAI (pCreature); -} - -bool GossipHello_npc_cooshcoosh(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_COOSH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(9441, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_cooshcoosh(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(FACTION_HOSTILE_CO); - pCreature->AI()->AttackStart(pPlayer); - } - return true; -} - -/*###### -## npc_elder_kuruti -######*/ - -#define GOSSIP_ITEM_KUR1 "Greetings, elder. It is time for your people to end their hostility towards the draenei and their allies." -#define GOSSIP_ITEM_KUR2 "I did not mean to deceive you, elder. The draenei of Telredor thought to approach you in a way that would seem familiar to you." -#define GOSSIP_ITEM_KUR3 "I will tell them. Farewell, elder." - -bool GossipHello_npc_elder_kuruti(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(9803) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(9226, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_elder_kuruti(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(9227, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KUR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(9229, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - if (!pPlayer->HasItemCount(24573,1)) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 24573, 1, false); - if (msg == EQUIP_ERR_OK) - { - pPlayer->StoreNewItem(dest, 24573, true); - } - else - pPlayer->SendEquipError(msg,NULL,NULL); - } - pPlayer->SEND_GOSSIP_MENU(9231, pCreature->GetGUID()); - break; - } - } - return true; -} - -/*###### -## npc_mortog_steamhead -######*/ - -bool GossipHello_npc_mortog_steamhead(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isVendor() && pPlayer->GetReputationRank(942) == REP_EXALTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_mortog_steamhead(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - { - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - } - return true; -} - -/*###### -## npc_kayra_longmane -######*/ - -enum eKayra -{ - SAY_START = -1000343, - SAY_AMBUSH1 = -1000344, - SAY_PROGRESS = -1000345, - SAY_AMBUSH2 = -1000346, - SAY_NEAR_END = -1000347, - SAY_END = -1000348, //this is signed for 10646 - - QUEST_ESCAPE_FROM = 9752, - NPC_SLAVEBINDER = 18042 -}; - -struct npc_kayra_longmaneAI : public npc_escortAI -{ - npc_kayra_longmaneAI(Creature* c) : npc_escortAI(c) {} - - void Reset() { } - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch(i) - { - case 4: - DoScriptText(SAY_AMBUSH1, me, pPlayer); - DoSpawnCreature(NPC_SLAVEBINDER, -10.0f, -5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - DoSpawnCreature(NPC_SLAVEBINDER, -8.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 5: - DoScriptText(SAY_PROGRESS, me, pPlayer); - SetRun(); - break; - case 16: - DoScriptText(SAY_AMBUSH2, me, pPlayer); - DoSpawnCreature(NPC_SLAVEBINDER, -10.0f, -5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - DoSpawnCreature(NPC_SLAVEBINDER, -8.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - break; - case 17: - SetRun(false); - DoScriptText(SAY_NEAR_END, me, pPlayer); - break; - case 25: - DoScriptText(SAY_END, me, pPlayer); - pPlayer->GroupEventHappens(QUEST_ESCAPE_FROM, me); - break; - } - } -}; - -bool QuestAccept_npc_kayra_longmane(Player* pPlayer, Creature* pCreature, Quest const* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_ESCAPE_FROM) - { - DoScriptText(SAY_START, pCreature, pPlayer); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_kayra_longmaneAI, pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID()); - } - return true; -} - -CreatureAI* GetAI_npc_kayra_longmaneAI(Creature* pCreature) -{ - return new npc_kayra_longmaneAI(pCreature); -} - -/*###### -## npc_timothy_daniels -######*/ - -#define GOSSIP_TIMOTHY_DANIELS_ITEM1 "Specialist, eh? Just what kind of specialist are you, anyway?" -#define GOSSIP_TEXT_BROWSE_POISONS "Let me browse your reagents and poison supplies." - -enum eTimothy -{ - GOSSIP_TEXTID_TIMOTHY_DANIELS1 = 9239 -}; - -bool GossipHello_npc_timothy_daniels(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_POISONS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TIMOTHY_DANIELS_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_timothy_daniels(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_TIMOTHY_DANIELS1, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - } - - return true; -} - -/*###### -## AddSC -######*/ - -void AddSC_zangarmarsh() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npcs_ashyen_and_keleth"; - newscript->pGossipHello = &GossipHello_npcs_ashyen_and_keleth; - newscript->pGossipSelect = &GossipSelect_npcs_ashyen_and_keleth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_cooshcoosh"; - newscript->GetAI = &GetAI_npc_cooshcoosh; - newscript->pGossipHello = &GossipHello_npc_cooshcoosh; - newscript->pGossipSelect = &GossipSelect_npc_cooshcoosh; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_elder_kuruti"; - newscript->pGossipHello = &GossipHello_npc_elder_kuruti; - newscript->pGossipSelect = &GossipSelect_npc_elder_kuruti; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_mortog_steamhead"; - newscript->pGossipHello = &GossipHello_npc_mortog_steamhead; - newscript->pGossipSelect = &GossipSelect_npc_mortog_steamhead; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_kayra_longmane"; - newscript->GetAI = &GetAI_npc_kayra_longmaneAI; - newscript->pQuestAccept = &QuestAccept_npc_kayra_longmane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_timothy_daniels"; - newscript->pGossipHello = &GossipHello_npc_timothy_daniels; - newscript->pGossipSelect = &GossipSelect_npc_timothy_daniels; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/world/areatrigger_scripts.cpp b/src/server/scripts/world/areatrigger_scripts.cpp deleted file mode 100644 index 9a75263d35c..00000000000 --- a/src/server/scripts/world/areatrigger_scripts.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Areatrigger_Scripts -SD%Complete: 100 -SDComment: Scripts for areatriggers -SDCategory: Areatrigger -EndScriptData */ - -/* ContentData -at_aldurthar_gate q13315/q13351 -at_coilfang_waterfall 4591 -at_legion_teleporter 4560 Teleporter TO Invasion Point: Cataclysm -at_ravenholdt -at_warsong_slaughterhouse -at_warsong_grainery -at_torp_farm -at_warsong_farms q11686 -at_stormwright_shelf q12741 -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## AreaTrigger_at_aldurthar_gate -######*/ - -enum eAldurtharGate -{ - TRIGGER_SOUTH = 5284, - - TRIGGER_CENTRAL = 5285, - TRIGGER_NORTH = 5286, - TRIGGER_NORTHWEST = 5287, - - NPC_SOUTH_GATE = 32195, - NPC_CENTRAL_GATE = 32196, - NPC_NORTH_GATE = 32197, - NPC_NORTHWEST_GATE = 32199 -}; - -bool AreaTrigger_at_aldurthar_gate(Player* pPlayer, const AreaTriggerEntry* pAt) -{ - switch(pAt->id) - { - case TRIGGER_SOUTH: pPlayer->KilledMonsterCredit(NPC_SOUTH_GATE, 0); break; - case TRIGGER_CENTRAL: pPlayer->KilledMonsterCredit(NPC_CENTRAL_GATE, 0); break; - case TRIGGER_NORTH: pPlayer->KilledMonsterCredit(NPC_NORTH_GATE, 0); break; - case TRIGGER_NORTHWEST: pPlayer->KilledMonsterCredit(NPC_NORTHWEST_GATE, 0); break; - } - return true; -} - -/*###### -## at_coilfang_waterfall -######*/ - -enum eCoilfangGOs -{ - GO_COILFANG_WATERFALL = 184212 -}; - -bool AreaTrigger_at_coilfang_waterfall(Player *pPlayer, const AreaTriggerEntry * /*pAt*/) -{ - if (GameObject* pGo = GetClosestGameObjectWithEntry(pPlayer, GO_COILFANG_WATERFALL, 35.0f)) - if (pGo->getLootState() == GO_READY) - pGo->UseDoorOrButton(); - - return false; -} - -/*##### -## at_legion_teleporter -#####*/ - -enum eLegionTeleporter -{ - SPELL_TELE_A_TO = 37387, - QUEST_GAINING_ACCESS_A = 10589, - - SPELL_TELE_H_TO = 37389, - QUEST_GAINING_ACCESS_H = 10604 -}; - -bool AreaTrigger_at_legion_teleporter(Player *pPlayer, const AreaTriggerEntry * /*pAt*/) -{ - if (pPlayer->isAlive() && !pPlayer->isInCombat()) - { - if (pPlayer->GetTeam() == ALLIANCE && pPlayer->GetQuestRewardStatus(QUEST_GAINING_ACCESS_A)) - { - pPlayer->CastSpell(pPlayer, SPELL_TELE_A_TO, false); - return true; - } - - if (pPlayer->GetTeam() == HORDE && pPlayer->GetQuestRewardStatus(QUEST_GAINING_ACCESS_H)) - { - pPlayer->CastSpell(pPlayer, SPELL_TELE_H_TO, false); - return true; - } - - return false; - } - return false; -} - -enum eRavenholdt -{ - QUEST_MANOR_RAVENHOLDT = 6681, - NPC_RAVENHOLDT = 13936 -}; - -bool AreaTrigger_at_ravenholdt(Player* pPlayer, const AreaTriggerEntry* /*pAt*/) -{ - if (pPlayer->GetQuestStatus(QUEST_MANOR_RAVENHOLDT) == QUEST_STATUS_INCOMPLETE) - pPlayer->KilledMonsterCredit(NPC_RAVENHOLDT, 0); - - return false; -} - -/*###### -## at_warsong_farms -######*/ - -enum eWarsongFarms -{ - QUEST_THE_WARSONG_FARMS = 11686, - - NPC_CREDIT_SLAUGHTERHOUSE = 25672, - NPC_CREDIT_GRAINERY = 25669, - NPC_CREDIT_TORP_FARM = 25671, - - AT_SLAUGHTERHOUSE = 4873, - AT_GRAINERY = 4871, - AT_TORP_FARM = 4872 -}; - -bool AreaTrigger_at_warsong_farms(Player* pPlayer, const AreaTriggerEntry* pAt) -{ - if (!pPlayer->isDead() && pPlayer->GetQuestStatus(QUEST_THE_WARSONG_FARMS) == QUEST_STATUS_INCOMPLETE) - { - switch(pAt->id) - { - case AT_SLAUGHTERHOUSE: pPlayer->KilledMonsterCredit(NPC_CREDIT_SLAUGHTERHOUSE, 0); break; - case AT_GRAINERY: pPlayer->KilledMonsterCredit(NPC_CREDIT_GRAINERY, 0); break; - case AT_TORP_FARM: pPlayer->KilledMonsterCredit(NPC_CREDIT_TORP_FARM, 0); break; - } - } - return true; - } - -/*###### -## at_stormwright_shelf -######*/ - -enum eStormwrightShelf -{ - QUEST_STRENGTH_OF_THE_TEMPEST = 12741, - - SPELL_CREATE_TRUE_POWER_OF_THE_TEMPEST = 53067 -}; - -bool AreaTrigger_at_stormwright_shelf(Player* pPlayer, const AreaTriggerEntry* /*pAt*/) -{ - if (!pPlayer->isDead() && pPlayer->GetQuestStatus(QUEST_STRENGTH_OF_THE_TEMPEST) == QUEST_STATUS_INCOMPLETE) - pPlayer->CastSpell(pPlayer, SPELL_CREATE_TRUE_POWER_OF_THE_TEMPEST, false); - - return true; -} - -/*###### -## at_scent_larkorwi -######*/ - -enum eScentLarkorwi -{ - QUEST_SCENT_OF_LARKORWI = 4291, - NPC_LARKORWI_MATE = 9683 -}; - -bool AreaTrigger_at_scent_larkorwi(Player* pPlayer, const AreaTriggerEntry* /*pAt*/) -{ - if (!pPlayer->isDead() && pPlayer->GetQuestStatus(QUEST_SCENT_OF_LARKORWI) == QUEST_STATUS_INCOMPLETE) - { - if (!pPlayer->FindNearestCreature(NPC_LARKORWI_MATE,15)) - pPlayer->SummonCreature(NPC_LARKORWI_MATE, pPlayer->GetPositionX()+5, pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 3.3, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 100000); - } - - return false; -} - -/*##### -## at_last_rites -#####*/ - -enum eAtLastRites -{ - QUEST_LAST_RITES = 12019 -}; - -bool AreaTrigger_at_last_rites(Player* pPlayer, const AreaTriggerEntry* pAt) -{ - if (pPlayer->GetQuestStatus(QUEST_LAST_RITES) != QUEST_STATUS_INCOMPLETE) - return false; - - WorldLocation pPosition; - - switch(pAt->id) - { - case 5332: - case 5338: - pPosition = WorldLocation(571,3733.68,3563.25,290.812,3.665192); - break; - case 5334: - pPosition = WorldLocation(571,3802.38,3585.95,49.5765,0); - break; - case 5340: - pPosition = WorldLocation(571,3687.91,3577.28,473.342,0); - break; - default: - return false; - } - - pPlayer->TeleportTo(pPosition); - - return false; -} - -void AddSC_areatrigger_scripts() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "at_aldurthar_gate"; - newscript->pAreaTrigger = &AreaTrigger_at_aldurthar_gate; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_coilfang_waterfall"; - newscript->pAreaTrigger = &AreaTrigger_at_coilfang_waterfall; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_legion_teleporter"; - newscript->pAreaTrigger = &AreaTrigger_at_legion_teleporter; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_ravenholdt"; - newscript->pAreaTrigger = &AreaTrigger_at_ravenholdt; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_warsong_farms"; - newscript->pAreaTrigger = &AreaTrigger_at_warsong_farms; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_stormwright_shelf"; - newscript->pAreaTrigger = &AreaTrigger_at_stormwright_shelf; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_scent_larkorwi"; - newscript->pAreaTrigger = &AreaTrigger_at_scent_larkorwi; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_last_rites"; - newscript->pAreaTrigger = &AreaTrigger_at_last_rites; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/world/boss_emeriss.cpp b/src/server/scripts/world/boss_emeriss.cpp deleted file mode 100644 index 3dc14969786..00000000000 --- a/src/server/scripts/world/boss_emeriss.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Emeriss -SD%Complete: 90 -SDComment: Teleport function & Mark of Nature missing -SDCategory: Bosses -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1000401, - SAY_CASTCORRUPTION = -1000402, //signed for 6182 - - SPELL_SLEEP = 24777, - SPELL_NOXIOUSBREATH = 24818, - SPELL_TAILSWEEP = 15847, - //SPELL_MARKOFNATURE = 25040, // Not working - SPELL_VOLATILEINFECTION = 24928, - SPELL_CORRUPTIONOFEARTH = 24910 -}; - -struct boss_emerissAI : public ScriptedAI -{ - boss_emerissAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiSleep_Timer; - uint32 m_uiNoxiousBreath_Timer; - uint32 m_uiTailSweep_Timer; - //uint32 m_uiMarkOfNature_Timer; - uint32 m_uiVolatileInfection_Timer; - uint32 m_uiCorruptionsCasted; - - void Reset() - { - m_uiSleep_Timer = 15000 + rand()%5000; - m_uiNoxiousBreath_Timer = 8000; - m_uiTailSweep_Timer = 4000; - //m_uiMarkOfNature_Timer = 45000; - m_uiVolatileInfection_Timer = 12000; - m_uiCorruptionsCasted = 0; - } - - void Aggro(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sleep_Timer - if (m_uiSleep_Timer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SLEEP); - - m_uiSleep_Timer = 8000 + rand()%8000; - } - else - m_uiSleep_Timer -= uiDiff; - - //NoxiousBreath_Timer - if (m_uiNoxiousBreath_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); - m_uiNoxiousBreath_Timer = 14000 + rand()%6000; - } - else - m_uiNoxiousBreath_Timer -= uiDiff; - - //Tailsweep every 2 seconds - if (m_uiTailSweep_Timer <= uiDiff) - { - DoCast(me, SPELL_TAILSWEEP); - m_uiTailSweep_Timer = 2000; - } - else - m_uiTailSweep_Timer -= uiDiff; - - //MarkOfNature_Timer - //if (m_uiMarkOfNature_Timer <= uiDiff) - //{ - // DoCast(me->getVictim(), SPELL_MARKOFNATURE); - // m_uiMarkOfNature_Timer = 45000; - //} - //else - // m_uiMarkOfNature_Timer -= uiDiff; - - //VolatileInfection_Timer - if (m_uiVolatileInfection_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_VOLATILEINFECTION); - m_uiVolatileInfection_Timer = 7000 + rand()%5000; - } - else - m_uiVolatileInfection_Timer -= uiDiff; - - //CorruptionofEarth_Timer - //CorruptionofEarth at 75%, 50% and 25% - if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(25*m_uiCorruptionsCasted))) - { - ++m_uiCorruptionsCasted; // prevent casting twice on same hp - DoScriptText(SAY_CASTCORRUPTION, me); - DoCast(me->getVictim(), SPELL_CORRUPTIONOFEARTH); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_emeriss(Creature* pCreature) -{ - return new boss_emerissAI (pCreature); -} - -void AddSC_boss_emeriss() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_emeriss"; - newscript->GetAI = &GetAI_boss_emeriss; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/world/boss_lethon.cpp b/src/server/scripts/world/boss_lethon.cpp deleted file mode 100644 index cc316223a2f..00000000000 --- a/src/server/scripts/world/boss_lethon.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Lethon -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Bosses -EndScriptData */ - -#include "ScriptedPch.h" - diff --git a/src/server/scripts/world/boss_taerar.cpp b/src/server/scripts/world/boss_taerar.cpp deleted file mode 100644 index 079f7b387a8..00000000000 --- a/src/server/scripts/world/boss_taerar.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Taerar -SD%Complete: 70 -SDComment: Mark of Nature & Teleport NYI. Fix the way to be banished. -SDCategory: Bosses -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1000399, //signed for 20021 - SAY_SUMMONSHADE = -1000400, //signed for 20021 - - //Spells of Taerar - SPELL_SLEEP = 24777, - SPELL_NOXIOUSBREATH = 24818, - SPELL_TAILSWEEP = 15847, - // SPELL_MARKOFNATURE = 25040, // Not working - SPELL_ARCANEBLAST = 24857, - SPELL_BELLOWINGROAR = 22686, - - SPELL_SUMMONSHADE_1 = 24841, - SPELL_SUMMONSHADE_2 = 24842, - SPELL_SUMMONSHADE_3 = 24843, - - //Spells of Shades of Taerar - SPELL_POSIONCLOUD = 24840, - SPELL_POSIONBREATH = 20667 -}; - -uint32 m_auiSpellSummonShade[]= -{ - SPELL_SUMMONSHADE_1, SPELL_SUMMONSHADE_2, SPELL_SUMMONSHADE_3 -}; - -struct boss_taerarAI : public ScriptedAI -{ - boss_taerarAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiSleep_Timer; - uint32 m_uiNoxiousBreath_Timer; - uint32 m_uiTailSweep_Timer; - //uint32 m_uiMarkOfNature_Timer; - uint32 m_uiArcaneBlast_Timer; - uint32 m_uiBellowingRoar_Timer; - uint32 m_uiShades_Timer; - uint32 m_uiShadesSummoned; - - bool m_bShades; - - void Reset() - { - m_uiSleep_Timer = 15000 + rand()%5000; - m_uiNoxiousBreath_Timer = 8000; - m_uiTailSweep_Timer = 4000; - //m_uiMarkOfNature_Timer = 45000; - m_uiArcaneBlast_Timer = 12000; - m_uiBellowingRoar_Timer = 30000; - m_uiShades_Timer = 60000; //The time that Taerar is banished - m_uiShadesSummoned = 0; - - m_bShades = false; - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustSummoned(Creature* pSummoned) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_bShades && m_uiShades_Timer <= uiDiff) - { - //Become unbanished again - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_bShades = false; - } - else if (m_bShades) - { - m_uiShades_Timer -= uiDiff; - //Do nothing while banished - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sleep_Timer - if (m_uiSleep_Timer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SLEEP); - - m_uiSleep_Timer = 8000 + rand()%7000; - } - else - m_uiSleep_Timer -= uiDiff; - - //NoxiousBreath_Timer - if (m_uiNoxiousBreath_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); - m_uiNoxiousBreath_Timer = 14000 + rand()%6000; - } - else - m_uiNoxiousBreath_Timer -= uiDiff; - - //Tailsweep every 2 seconds - if (m_uiTailSweep_Timer <= uiDiff) - { - DoCast(me, SPELL_TAILSWEEP); - m_uiTailSweep_Timer = 2000; - } - else - m_uiTailSweep_Timer -= uiDiff; - - //MarkOfNature_Timer - //if (m_uiMarkOfNature_Timer <= uiDiff) - //{ - // DoCast(me->getVictim(), SPELL_MARKOFNATURE); - // m_uiMarkOfNature_Timer = 45000; - //} - //else - // m_uiMarkOfNature_Timer -= uiDiff; - - //ArcaneBlast_Timer - if (m_uiArcaneBlast_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_ARCANEBLAST); - m_uiArcaneBlast_Timer = 7000 + rand()%5000; - } - else - m_uiArcaneBlast_Timer -= uiDiff; - - //BellowingRoar_Timer - if (m_uiBellowingRoar_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BELLOWINGROAR); - m_uiBellowingRoar_Timer = 20000 + rand()%10000; - } - else - m_uiBellowingRoar_Timer -= uiDiff; - - //Summon 3 Shades at 75%, 50% and 25% (if bShades is true we already left in line 117, no need to check here again) - if (!m_bShades && (me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(25*m_uiShadesSummoned))) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - //Inturrupt any spell casting - me->InterruptNonMeleeSpells(false); - - //horrible workaround, need to fix - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - DoScriptText(SAY_SUMMONSHADE, me); - - int iSize = sizeof(m_auiSpellSummonShade) / sizeof(uint32); - - for (int i = 0; i < iSize; ++i) - DoCast(pTarget, m_auiSpellSummonShade[i], true); - - ++m_uiShadesSummoned; // prevent casting twice at same health - m_bShades = true; - } - m_uiShades_Timer = 60000; - } - - DoMeleeAttackIfReady(); - } -}; - -// Shades of Taerar Script -struct boss_shadeoftaerarAI : public ScriptedAI -{ - boss_shadeoftaerarAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiPoisonCloud_Timer; - uint32 m_uiPosionBreath_Timer; - - void Reset() - { - m_uiPoisonCloud_Timer = 8000; - m_uiPosionBreath_Timer = 12000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //PoisonCloud_Timer - if (m_uiPoisonCloud_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_POSIONCLOUD); - m_uiPoisonCloud_Timer = 30000; - } - else - m_uiPoisonCloud_Timer -= uiDiff; - - //PosionBreath_Timer - if (m_uiPosionBreath_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_POSIONBREATH); - m_uiPosionBreath_Timer = 12000; - } - else - m_uiPosionBreath_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_taerar(Creature* pCreature) -{ - return new boss_taerarAI (pCreature); -} - -CreatureAI* GetAI_boss_shadeoftaerar(Creature* pCreature) -{ - return new boss_shadeoftaerarAI (pCreature); -} - -void AddSC_boss_taerar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_taerar"; - newscript->GetAI = &GetAI_boss_taerar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_shade_of_taerar"; - newscript->GetAI = &GetAI_boss_shadeoftaerar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/world/boss_ysondre.cpp b/src/server/scripts/world/boss_ysondre.cpp deleted file mode 100644 index 50b8f724e68..00000000000 --- a/src/server/scripts/world/boss_ysondre.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Ysondre -SD%Complete: 90 -SDComment: Mark of Nature & Teleport missing -SDCategory: Bosses -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1000360, //signed for 17969 - SAY_SUMMONDRUIDS = -1000361, //signed for 17969 - - SPELL_SLEEP = 24777, - SPELL_NOXIOUSBREATH = 24818, - SPELL_TAILSWEEP = 15847, - //SPELL_MARKOFNATURE = 25040, // Not working - SPELL_LIGHTNINGWAVE = 24819, - SPELL_SUMMONDRUIDS = 24795, - - SPELL_SUMMON_PLAYER = 24776, - - //druid spells - SPELL_MOONFIRE = 21669 -}; - -// Ysondre script -struct boss_ysondreAI : public ScriptedAI -{ - boss_ysondreAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 m_uiSleep_Timer; - uint32 m_uiNoxiousBreath_Timer; - uint32 m_uiTailSweep_Timer; - //uint32 m_uiMarkOfNature_Timer; - uint32 m_uiLightningWave_Timer; - uint32 m_uiSummonDruidModifier; - - void Reset() - { - m_uiSleep_Timer = 15000 + rand()%5000; - m_uiNoxiousBreath_Timer = 8000; - m_uiTailSweep_Timer = 4000; - //m_uiMarkOfNature_Timer = 45000; - m_uiLightningWave_Timer = 12000; - m_uiSummonDruidModifier = 0; - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustSummoned(Creature* pSummoned) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //Sleep_Timer - if (m_uiSleep_Timer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SLEEP); - - m_uiSleep_Timer = 8000 + rand()%7000; - } - else - m_uiSleep_Timer -= uiDiff; - - //NoxiousBreath_Timer - if (m_uiNoxiousBreath_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSBREATH); - m_uiNoxiousBreath_Timer = 14000 + rand()%6000; - } - else - m_uiNoxiousBreath_Timer -= uiDiff; - - //Tailsweep every 2 seconds - if (m_uiTailSweep_Timer <= uiDiff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_TAILSWEEP); - - m_uiTailSweep_Timer = 2000; - } - else - m_uiTailSweep_Timer -= uiDiff; - - //MarkOfNature_Timer - //if (m_uiMarkOfNature_Timer <= uiDiff) - //{ - // DoCast(me->getVictim(), SPELL_MARKOFNATURE); - // m_uiMarkOfNature_Timer = 45000; - //} - //else - // m_uiMarkOfNature_Timer -= uiDiff; - - //LightningWave_Timer - if (m_uiLightningWave_Timer <= uiDiff) - { - //Cast LIGHTNINGWAVE on a Random target - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_LIGHTNINGWAVE); - - m_uiLightningWave_Timer = 7000 + rand()%5000; - } - else - m_uiLightningWave_Timer -= uiDiff; - - //Summon Druids - if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(25*m_uiSummonDruidModifier))) - { - DoScriptText(SAY_SUMMONDRUIDS, me); - - for (int i = 0; i < 10; ++i) - DoCast(me, SPELL_SUMMONDRUIDS, true); - - ++m_uiSummonDruidModifier; - } - - DoMeleeAttackIfReady(); - } -}; - -// Summoned druid script -struct mob_dementeddruidsAI : public ScriptedAI -{ - mob_dementeddruidsAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiMoonFire_Timer; - - void Reset() - { - m_uiMoonFire_Timer = 3000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //MoonFire_Timer - if (m_uiMoonFire_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MOONFIRE); - m_uiMoonFire_Timer = 5000; - } - else - m_uiMoonFire_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ysondre(Creature* pCreature) -{ - return new boss_ysondreAI (pCreature); -} - -CreatureAI* GetAI_mob_dementeddruids(Creature* pCreature) -{ - return new mob_dementeddruidsAI (pCreature); -} - -void AddSC_boss_ysondre() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ysondre"; - newscript->GetAI = &GetAI_boss_ysondre; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_dementeddruids"; - newscript->GetAI = &GetAI_mob_dementeddruids; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/world/go_scripts.cpp b/src/server/scripts/world/go_scripts.cpp deleted file mode 100644 index 6f06ac78fd7..00000000000 --- a/src/server/scripts/world/go_scripts.cpp +++ /dev/null @@ -1,1182 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 > -* Copyright (C) 2006 - 20010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: GO_Scripts -SD%Complete: 100 -SDComment: Quest support: 4285,4287,4288(crystal pylons), 4296, 6481, 10990, 10991, 10992, Field_Repair_Bot->Teaches spell 22704. Barov_journal->Teaches spell 26089,12843,12982, 2936. Soulwell -SDCategory: Game Objects -EndScriptData */ - -/* ContentData -go_cat_figurine (the "trap" version of GO, two different exist) -go_northern_crystal_pylon -go_eastern_crystal_pylon -go_western_crystal_pylon -go_barov_journal -go_ethereum_prison -go_ethereum_stasis -go_sacred_fire_of_life -go_shrine_of_the_birds -go_southfury_moonstone -go_field_repair_bot_74A -go_orb_of_command -go_resonite_cask -go_tablet_of_madness -go_tablet_of_the_seven -go_tele_to_dalaran_crystal -go_tele_to_violet_stand -go_rusty_cage -go_scourge_cage -go_jotunheim_cage -go_table_theka -go_soulwell -go_bashir_crystalforge -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## go_cat_figurine -######*/ - -enum eCatFigurine -{ - SPELL_SUMMON_GHOST_SABER = 5968, -}; - -bool GOHello_go_cat_figurine(Player *pPlayer, GameObject * /*pGO*/) -{ - pPlayer->CastSpell(pPlayer,SPELL_SUMMON_GHOST_SABER,true); - return false; -} - -/*###### -## go_crystal_pylons (3x) -######*/ - -bool GOHello_go_northern_crystal_pylon(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) - { - pPlayer->PrepareQuestMenu(pGO->GetGUID()); - pPlayer->SendPreparedQuest(pGO->GetGUID()); - } - - if (pPlayer->GetQuestStatus(4285) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(4285); - - return true; -} - -bool GOHello_go_eastern_crystal_pylon(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) - { - pPlayer->PrepareQuestMenu(pGO->GetGUID()); - pPlayer->SendPreparedQuest(pGO->GetGUID()); - } - - if (pPlayer->GetQuestStatus(4287) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(4287); - - return true; -} - -bool GOHello_go_western_crystal_pylon(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) - { - pPlayer->PrepareQuestMenu(pGO->GetGUID()); - pPlayer->SendPreparedQuest(pGO->GetGUID()); - } - - if (pPlayer->GetQuestStatus(4288) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(4288); - - return true; -} - -/*###### -## go_barov_journal -######*/ - -bool GOHello_go_barov_journal(Player *pPlayer, GameObject * /*pGO*/) -{ - if (pPlayer->HasSkill(SKILL_TAILORING) && pPlayer->GetBaseSkillValue(SKILL_TAILORING) >= 280 && !pPlayer->HasSpell(26086)) - { - pPlayer->CastSpell(pPlayer,26095,false); - } - return true; -} - -/*###### -## go_field_repair_bot_74A -######*/ - -bool GOHello_go_field_repair_bot_74A(Player *pPlayer, GameObject * /*pGO*/) -{ - if (pPlayer->HasSkill(SKILL_ENGINERING) && pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 300 && !pPlayer->HasSpell(22704)) - { - pPlayer->CastSpell(pPlayer,22864,false); - } - return true; -} - -/*###### -## go_gilded_brazier (Paladin First Trail quest (9678)) -######*/ - -enum eGildedBrazier -{ - NPC_STILLBLADE = 17716, -}; - -bool GOHello_go_gilded_brazier(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER) - { - if (pPlayer->GetQuestStatus(9678) == QUEST_STATUS_INCOMPLETE) - { - if (Creature* Stillblade = pPlayer->SummonCreature(NPC_STILLBLADE, 8106.11, -7542.06, 151.775, 3.02598, TEMPSUMMON_DEAD_DESPAWN, 60000)) - Stillblade->AI()->AttackStart(pPlayer); - } - } - return true; -} - -/*###### -## go_orb_of_command -######*/ - -bool GOHello_go_orb_of_command(Player *pPlayer, GameObject * /*pGO*/) -{ - if (pPlayer->GetQuestRewardStatus(7761)) - pPlayer->CastSpell(pPlayer,23460,true); - - return true; -} - -/*###### -## go_tablet_of_madness -######*/ - -bool GOHello_go_tablet_of_madness(Player *pPlayer, GameObject * /*pGO*/) -{ - if (pPlayer->HasSkill(SKILL_ALCHEMY) && pPlayer->GetSkillValue(SKILL_ALCHEMY) >= 300 && !pPlayer->HasSpell(24266)) - { - pPlayer->CastSpell(pPlayer,24267,false); - } - return true; -} - -/*###### -## go_tablet_of_the_seven -######*/ - -//TODO: use gossip option ("Transcript the Tablet") instead, if Trinity adds support. -bool GOHello_go_tablet_of_the_seven(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) - return true; - - if (pPlayer->GetQuestStatus(4296) == QUEST_STATUS_INCOMPLETE) - pPlayer->CastSpell(pPlayer,15065,false); - - return true; -} - -/*##### -## go_jump_a_tron -######*/ - -bool GOHello_go_jump_a_tron(Player *pPlayer, GameObject * /*pGO*/) -{ - if (pPlayer->GetQuestStatus(10111) == QUEST_STATUS_INCOMPLETE) - pPlayer->CastSpell(pPlayer,33382,true); - - return true; -} - -/*###### -## go_ethereum_prison -######*/ - -enum eEthereumPrison -{ - SPELL_REP_LC = 39456, - SPELL_REP_SHAT = 39457, - SPELL_REP_CE = 39460, - SPELL_REP_CON = 39474, - SPELL_REP_KT = 39475, - SPELL_REP_SPOR = 39476 -}; - -const uint32 NpcPrisonEntry[] = -{ - 22810, 22811, 22812, 22813, 22814, 22815, //good guys - 20783, 20784, 20785, 20786, 20788, 20789, 20790 //bad guys -}; - -bool GOHello_go_ethereum_prison(Player *pPlayer, GameObject *pGO) -{ - int Random = rand() % (sizeof(NpcPrisonEntry) / sizeof(uint32)); - - if (Creature* pCreature = pPlayer->SummonCreature(NpcPrisonEntry[Random], - pGO->GetPositionX(), pGO->GetPositionY(), pGO->GetPositionZ(), pGO->GetAngle(pPlayer), - TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - if (!pCreature->IsHostileTo(pPlayer)) - { - uint32 Spell = 0; - - if (FactionTemplateEntry const* pFaction = pCreature->getFactionTemplateEntry()) - { - switch(pFaction->faction) - { - case 1011: Spell = SPELL_REP_LC; break; - case 935: Spell = SPELL_REP_SHAT; break; - case 942: Spell = SPELL_REP_CE; break; - case 933: Spell = SPELL_REP_CON; break; - case 989: Spell = SPELL_REP_KT; break; - case 970: Spell = SPELL_REP_SPOR; break; - } - - if (Spell) - pCreature->CastSpell(pPlayer, Spell, false); - else - error_log("TSCR: go_ethereum_prison summoned Creature (entry %u) but faction (%u) are not expected by script.", pCreature->GetEntry(), pCreature->getFaction()); - } - } - } - - return false; -} - -/*###### -## go_ethereum_stasis -######*/ - -const uint32 NpcStasisEntry[] = -{ - 22825, 20888, 22827, 22826, 22828 -}; - -bool GOHello_go_ethereum_stasis(Player *pPlayer, GameObject *pGO) -{ - int Random = rand() % (sizeof(NpcStasisEntry) / sizeof(uint32)); - - pPlayer->SummonCreature(NpcStasisEntry[Random], - pGO->GetPositionX(), pGO->GetPositionY(), pGO->GetPositionZ(), pGO->GetAngle(pPlayer), - TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - - return false; -} - -/*###### -## go_resonite_cask -######*/ - -enum eResoniteCask -{ - NPC_GOGGEROC = 11920 -}; - -bool GOHello_go_resonite_cask(Player * /*pPlayer*/, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER) - pGO->SummonCreature(NPC_GOGGEROC, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000); - - return false; -} - -/*###### -## go_sacred_fire_of_life -######*/ - -#define NPC_ARIKARA 10882 - -bool GOHello_go_sacred_fire_of_life(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER) - pPlayer->SummonCreature(NPC_ARIKARA, -5008.338, -2118.894, 83.657, 0.874, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - - return true; -} - -/*###### -## go_shrine_of_the_birds -######*/ - -enum eShrineOfTheBirds -{ - NPC_HAWK_GUARD = 22992, - NPC_EAGLE_GUARD = 22993, - NPC_FALCON_GUARD = 22994, - GO_SHRINE_HAWK = 185551, - GO_SHRINE_EAGLE = 185547, - GO_SHRINE_FALCON = 185553 -}; - -bool GOHello_go_shrine_of_the_birds(Player *pPlayer, GameObject *pGO) -{ - uint32 BirdEntry = 0; - - float fX, fY, fZ; - pGO->GetClosePoint(fX, fY, fZ, pGO->GetObjectSize(), INTERACTION_DISTANCE); - - switch(pGO->GetEntry()) - { - case GO_SHRINE_HAWK: - BirdEntry = NPC_HAWK_GUARD; - break; - case GO_SHRINE_EAGLE: - BirdEntry = NPC_EAGLE_GUARD; - break; - case GO_SHRINE_FALCON: - BirdEntry = NPC_FALCON_GUARD; - break; - } - - if (BirdEntry) - pPlayer->SummonCreature(BirdEntry, fX, fY, fZ, pGO->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - - return false; -} - -/*###### -## go_southfury_moonstone -######*/ - -enum eSouthfury -{ - NPC_RIZZLE = 23002, - SPELL_BLACKJACK = 39865, //stuns player - SPELL_SUMMON_RIZZLE = 39866 - -}; - -bool GOHello_go_southfury_moonstone(Player *pPlayer, GameObject * /*pGO*/) -{ - //implicitTarget=48 not implemented as of writing this code, and manual summon may be just ok for our purpose - //pPlayer->CastSpell(pPlayer,SPELL_SUMMON_RIZZLE,false); - - if (Creature* pCreature = pPlayer->SummonCreature(NPC_RIZZLE, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0)) - pCreature->CastSpell(pPlayer,SPELL_BLACKJACK,false); - - return false; -} - -/*###### -## go_tele_to_dalaran_crystal -######*/ - -enum eDalaranCrystal -{ - QUEST_LEARN_LEAVE_RETURN = 12790, - QUEST_TELE_CRYSTAL_FLAG = 12845 -}; - -#define GO_TELE_TO_DALARAN_CRYSTAL_FAILED "This teleport crystal cannot be used until the teleport crystal in Dalaran has been used at least once." - -bool GOHello_go_tele_to_dalaran_crystal(Player *pPlayer, GameObject * /*pGO*/) -{ - if (pPlayer->GetQuestRewardStatus(QUEST_TELE_CRYSTAL_FLAG)) - { - return false; - } - else - pPlayer->GetSession()->SendNotification(GO_TELE_TO_DALARAN_CRYSTAL_FAILED); - - return true; -} - -/*###### -## go_tele_to_violet_stand -######*/ - -bool GOHello_go_tele_to_violet_stand(Player *pPlayer, GameObject * /*pGO*/) -{ - if (pPlayer->GetQuestRewardStatus(QUEST_LEARN_LEAVE_RETURN) || pPlayer->GetQuestStatus(QUEST_LEARN_LEAVE_RETURN) == QUEST_STATUS_INCOMPLETE) - return false; - - return true; -} - -/*###### -## go_fel_crystalforge -######*/ - -#define GOSSIP_FEL_CRYSTALFORGE_TEXT 31000 -#define GOSSIP_FEL_CRYSTALFORGE_ITEM_TEXT_RETURN 31001 -#define GOSSIP_FEL_CRYSTALFORGE_ITEM_1 "Purchase 1 Unstable Flask of the Beast for the cost of 10 Apexis Shards" -#define GOSSIP_FEL_CRYSTALFORGE_ITEM_5 "Purchase 5 Unstable Flask of the Beast for the cost of 50 Apexis Shards" -#define GOSSIP_FEL_CRYSTALFORGE_ITEM_RETURN "Use the fel crystalforge to make another purchase." - -enum eFelCrystalforge -{ - SPELL_CREATE_1_FLASK_OF_BEAST = 40964, - SPELL_CREATE_5_FLASK_OF_BEAST = 40965, -}; - -bool GOHello_go_fel_crystalforge(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) /* != GAMEOBJECT_TYPE_QUESTGIVER) */ - pPlayer->PrepareQuestMenu(pGO->GetGUID()); /* return true*/ - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(GOSSIP_FEL_CRYSTALFORGE_TEXT, pGO->GetGUID()); - - return true; -} - -bool GOSelect_go_fel_crystalforge(Player *pPlayer, GameObject *pGO, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->CastSpell(pPlayer,SPELL_CREATE_1_FLASK_OF_BEAST,false); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_RETURN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_FEL_CRYSTALFORGE_ITEM_TEXT_RETURN, pGO->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->CastSpell(pPlayer,SPELL_CREATE_5_FLASK_OF_BEAST,false); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_RETURN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_FEL_CRYSTALFORGE_ITEM_TEXT_RETURN, pGO->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FEL_CRYSTALFORGE_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_FEL_CRYSTALFORGE_TEXT, pGO->GetGUID()); - break; - } - return true; -} - -/*###### -## go_bashir_crystalforge -######*/ - -#define GOSSIP_BASHIR_CRYSTALFORGE_TEXT 31100 -#define GOSSIP_BASHIR_CRYSTALFORGE_ITEM_TEXT_RETURN 31101 -#define GOSSIP_BASHIR_CRYSTALFORGE_ITEM_1 "Purchase 1 Unstable Flask of the Sorcerer for the cost of 10 Apexis Shards" -#define GOSSIP_BASHIR_CRYSTALFORGE_ITEM_5 "Purchase 5 Unstable Flask of the Sorcerer for the cost of 50 Apexis Shards" -#define GOSSIP_BASHIR_CRYSTALFORGE_ITEM_RETURN "Use the bashir crystalforge to make another purchase." - -enum eBashirCrystalforge -{ - SPELL_CREATE_1_FLASK_OF_SORCERER = 40968, - SPELL_CREATE_5_FLASK_OF_SORCERER = 40970, -}; - -bool GOHello_go_bashir_crystalforge(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) /* != GAMEOBJECT_TYPE_QUESTGIVER) */ - pPlayer->PrepareQuestMenu(pGO->GetGUID()); /* return true*/ - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(GOSSIP_BASHIR_CRYSTALFORGE_TEXT, pGO->GetGUID()); - - return true; -} - -bool GOSelect_go_bashir_crystalforge(Player *pPlayer, GameObject *pGO, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->CastSpell(pPlayer,SPELL_CREATE_1_FLASK_OF_SORCERER,false); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_RETURN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_BASHIR_CRYSTALFORGE_ITEM_TEXT_RETURN, pGO->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->CastSpell(pPlayer,SPELL_CREATE_5_FLASK_OF_SORCERER,false); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_RETURN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_BASHIR_CRYSTALFORGE_ITEM_TEXT_RETURN, pGO->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BASHIR_CRYSTALFORGE_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_BASHIR_CRYSTALFORGE_TEXT, pGO->GetGUID()); - break; - } - return true; -} - -/*###### -## matrix_punchograph -######*/ - -enum eMatrixPunchograph -{ - ITEM_WHITE_PUNCH_CARD = 9279, - ITEM_YELLOW_PUNCH_CARD = 9280, - ITEM_BLUE_PUNCH_CARD = 9282, - ITEM_RED_PUNCH_CARD = 9281, - ITEM_PRISMATIC_PUNCH_CARD = 9316, - SPELL_YELLOW_PUNCH_CARD = 11512, - SPELL_BLUE_PUNCH_CARD = 11525, - SPELL_RED_PUNCH_CARD = 11528, - SPELL_PRISMATIC_PUNCH_CARD = 11545, - MATRIX_PUNCHOGRAPH_3005_A = 142345, - MATRIX_PUNCHOGRAPH_3005_B = 142475, - MATRIX_PUNCHOGRAPH_3005_C = 142476, - MATRIX_PUNCHOGRAPH_3005_D = 142696, -}; - -bool GOHello_go_matrix_punchograph(Player *pPlayer, GameObject *pGO) -{ - switch(pGO->GetEntry()) - { - case MATRIX_PUNCHOGRAPH_3005_A: - if (pPlayer->HasItemCount(ITEM_WHITE_PUNCH_CARD, 1)) - { - pPlayer->DestroyItemCount(ITEM_WHITE_PUNCH_CARD, 1, true); - pPlayer->CastSpell(pPlayer,SPELL_YELLOW_PUNCH_CARD,true); - } - break; - case MATRIX_PUNCHOGRAPH_3005_B: - if (pPlayer->HasItemCount(ITEM_YELLOW_PUNCH_CARD, 1)) - { - pPlayer->DestroyItemCount(ITEM_YELLOW_PUNCH_CARD, 1, true); - pPlayer->CastSpell(pPlayer,SPELL_BLUE_PUNCH_CARD,true); - } - break; - case MATRIX_PUNCHOGRAPH_3005_C: - if (pPlayer->HasItemCount(ITEM_BLUE_PUNCH_CARD, 1)) - { - pPlayer->DestroyItemCount(ITEM_BLUE_PUNCH_CARD, 1, true); - pPlayer->CastSpell(pPlayer,SPELL_RED_PUNCH_CARD,true); - } - break; - case MATRIX_PUNCHOGRAPH_3005_D: - if (pPlayer->HasItemCount(ITEM_RED_PUNCH_CARD, 1)) - { - pPlayer->DestroyItemCount(ITEM_RED_PUNCH_CARD, 1, true); - pPlayer->CastSpell(pPlayer, SPELL_PRISMATIC_PUNCH_CARD, true); - } - break; - default: - break; - } - return false; -} - -/*###### -## go_rusty_cage -######*/ - -enum eRustyCage -{ - NPC_GOBLIN_PRISIONER = 29466 -}; - -bool GOHello_go_rusty_cage(Player *pPlayer, GameObject *pGO) -{ - if (Creature *pGoblinPrisoner = pGO->FindNearestCreature(NPC_GOBLIN_PRISIONER, 5.0f, true)) - { - pGO->SetGoState(GO_STATE_ACTIVE); - pPlayer->KilledMonsterCredit(NPC_GOBLIN_PRISIONER, pGoblinPrisoner->GetGUID()); - pGoblinPrisoner->DisappearAndDie(); - } - - return true; -} - -/*###### -## go_scourge_cage -######*/ - -enum eScourgeCage -{ - NPC_SCOURGE_PRISONER = 25610 -}; - -bool GOHello_go_scourge_cage(Player *pPlayer, GameObject *pGO) -{ - if (Creature *pNearestPrisoner = pGO->FindNearestCreature(NPC_SCOURGE_PRISONER, 5.0f, true)) - { - pGO->SetGoState(GO_STATE_ACTIVE); - pPlayer->KilledMonsterCredit(NPC_SCOURGE_PRISONER, pNearestPrisoner->GetGUID()); - pNearestPrisoner->DisappearAndDie(); - } - - return true; -} - -/*###### -## go_arcane_prison -######*/ - -enum eArcanePrison -{ - QUEST_PRISON_BREAK = 11587, - SPELL_ARCANE_PRISONER_KILL_CREDIT = 45456 -}; - -bool GOHello_go_arcane_prison(Player *pPlayer, GameObject *pGO) -{ - if (pPlayer->GetQuestStatus(QUEST_PRISON_BREAK) == QUEST_STATUS_INCOMPLETE) - { - pGO->SummonCreature(25318, 3485.089844, 6115.7422188, 70.966812, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); - pPlayer->CastSpell(pPlayer, SPELL_ARCANE_PRISONER_KILL_CREDIT, true); - return true; - } else - return false; -} - -/*###### -## go_blood_filled_orb -######*/ - -#define NPC_ZELEMAR 17830 - -bool GOHello_go_blood_filled_orb(Player *pPlayer, GameObject *pGO) -{ - if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER) - pPlayer->SummonCreature(NPC_ZELEMAR, -369.746, 166.759, -21.50, 5.235, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - - return true; -} - -/*###### -## go_jotunheim_cage -######*/ - -enum eJotunheimCage -{ - NPC_EBON_BLADE_PRISONER_HUMAN = 30186, - NPC_EBON_BLADE_PRISONER_NE = 30194, - NPC_EBON_BLADE_PRISONER_TROLL = 30196, - NPC_EBON_BLADE_PRISONER_ORC = 30195, - - SPELL_SUMMON_BLADE_KNIGHT_H = 56207, - SPELL_SUMMON_BLADE_KNIGHT_NE = 56209, - SPELL_SUMMON_BLADE_KNIGHT_ORC = 56212, - SPELL_SUMMON_BLADE_KNIGHT_TROLL = 56214 -}; - -bool GOHello_go_jotunheim_cage(Player* pPlayer, GameObject* pGO) -{ - Creature* pPrisoner = pGO->FindNearestCreature(NPC_EBON_BLADE_PRISONER_HUMAN, 5.0f, true); - if (!pPrisoner) - { - pPrisoner = pGO->FindNearestCreature(NPC_EBON_BLADE_PRISONER_TROLL, 5.0f, true); - if (!pPrisoner) - { - pPrisoner = pGO->FindNearestCreature(NPC_EBON_BLADE_PRISONER_ORC, 5.0f, true); - if (!pPrisoner) - pPrisoner = pGO->FindNearestCreature(NPC_EBON_BLADE_PRISONER_NE, 5.0f, true); - } - } - if (!pPrisoner || !pPrisoner->isAlive()) - return false; - - pPrisoner->DisappearAndDie(); - pPlayer->KilledMonsterCredit(NPC_EBON_BLADE_PRISONER_HUMAN, 0); - switch(pPrisoner->GetEntry()) - { - case NPC_EBON_BLADE_PRISONER_HUMAN: - pPlayer->CastSpell(pPlayer,SPELL_SUMMON_BLADE_KNIGHT_H,true); - break; - case NPC_EBON_BLADE_PRISONER_NE: - pPlayer->CastSpell(pPlayer,SPELL_SUMMON_BLADE_KNIGHT_NE,true); - break; - case NPC_EBON_BLADE_PRISONER_TROLL: - pPlayer->CastSpell(pPlayer,SPELL_SUMMON_BLADE_KNIGHT_TROLL,true); - break; - case NPC_EBON_BLADE_PRISONER_ORC: - pPlayer->CastSpell(pPlayer,SPELL_SUMMON_BLADE_KNIGHT_ORC,true); - break; - } - return true; -} -enum eTableTheka -{ - GOSSIP_TABLE_THEKA = 1653, - - QUEST_SPIDER_GOLD = 2936 -}; - -bool GOHello_go_table_theka(Player* pPlayer, GameObject* pGO) -{ - if (pPlayer->GetQuestStatus(QUEST_SPIDER_GOLD) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_SPIDER_GOLD); - - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TABLE_THEKA, pGO->GetGUID()); - - return true; -} - -/*###### -## go_inconspicuous_landmark -######*/ - -enum eInconspicuousLandmark -{ - SPELL_SUMMON_PIRATES_TREASURE_AND_TRIGGER_MOB = 11462, - ITEM_CUERGOS_KEY = 9275, -}; - -bool GOHello_go_inconspicuous_landmark(Player *pPlayer, GameObject* /*pGO*/) -{ - if (pPlayer->HasItemCount(ITEM_CUERGOS_KEY,1)) - return false; - - pPlayer->CastSpell(pPlayer,SPELL_SUMMON_PIRATES_TREASURE_AND_TRIGGER_MOB,true); - - return true; -} - -/*###### -## go_soulwell -######*/ - -bool GOHello_go_soulwell(Player *pPlayer, GameObject* pGO) -{ - Unit *caster = pGO->GetOwner(false); - if (!caster || caster->GetTypeId() != TYPEID_PLAYER) - return true; - - if (!pPlayer->IsInSameRaidWith(static_cast(caster))) - return true; - - // Repeating this at every use is ugly and inefficient. But as long as we don't have proper - // GO scripting with at least On Create and On Update events, the other options are no less - // ugly and hacky. - uint32 newSpell = 0; - if (pGO->GetEntry() == 193169) // Soulwell for rank 2 - { - if (caster->HasAura(18693)) // Improved Healthstone rank 2 - newSpell = 58898; - else if (caster->HasAura(18692)) // Improved Healthstone rank 1 - newSpell = 58896; - else newSpell = 58890; - } - else if (pGO->GetEntry() == 181621) // Soulwell for rank 1 - { - if (caster->HasAura(18693)) // Improved Healthstone rank 2 - newSpell = 34150; - else if (caster->HasAura(18692)) // Improved Healthstone rank 1 - newSpell = 34149; - else newSpell = 34130; - } - - pGO->AddUse(); - pPlayer->CastSpell(pPlayer, newSpell, true); - return true; -} - -/*###### -## Quest 11255: Prisoners of Wyrmskull -## go_dragonflayer_cage -######*/ - -enum ePrisonersOfWyrmskull -{ - QUEST_PRISONERS_OF_WYRMSKULL = 11255, - NPC_PRISONER_PRIEST = 24086, - NPC_PRISONER_MAGE = 24088, - NPC_PRISONER_WARRIOR = 24089, - NPC_PRISONER_PALADIN = 24090 -}; - -bool GOHello_go_dragonflayer_cage(Player *pPlayer, GameObject *pGO) -{ - if (pPlayer->GetQuestStatus(QUEST_PRISONERS_OF_WYRMSKULL) != QUEST_STATUS_INCOMPLETE) - return true; - - Creature* pPrisoner = pGO->FindNearestCreature(NPC_PRISONER_PRIEST, 2.0f); - if (!pPrisoner) - { - pPrisoner = pGO->FindNearestCreature(NPC_PRISONER_MAGE, 2.0f); - if (!pPrisoner) - { - pPrisoner = pGO->FindNearestCreature(NPC_PRISONER_WARRIOR, 2.0f); - if (!pPrisoner) - pPrisoner = pGO->FindNearestCreature(NPC_PRISONER_PALADIN, 2.0f); - } - } - - if (!pPrisoner || !pPrisoner->isAlive()) - return true; - - Quest const* qInfo = objmgr.GetQuestTemplate(QUEST_PRISONERS_OF_WYRMSKULL); - if (qInfo) - { - //TODO: prisoner should help player for a short period of time - pPlayer->KilledMonsterCredit(qInfo->ReqCreatureOrGOId[0],0); - pPrisoner->DisappearAndDie(); - } - return true; -} - -/*###### -## Quest 11560: Oh Noes, the Tadpoles! -## go_tadpole_cage -######*/ - -enum eTadpoles -{ - QUEST_OH_NOES_THE_TADPOLES = 11560, - NPC_WINTERFIN_TADPOLE = 25201 -}; - -bool GOHello_go_tadpole_cage(Player *pPlayer, GameObject *pGO) -{ - if (pPlayer->GetQuestStatus(QUEST_OH_NOES_THE_TADPOLES) == QUEST_STATUS_INCOMPLETE) - { - Creature *pTadpole = pGO->FindNearestCreature(NPC_WINTERFIN_TADPOLE,1.0f); - if (pTadpole) - { - pGO->UseDoorOrButton(); - pTadpole->DisappearAndDie(); - pPlayer->KilledMonsterCredit(NPC_WINTERFIN_TADPOLE,0); - //FIX: Summon minion tadpole - } - } - return true; -} - -/*###### -## Quest 14096 & 14142: You've Really Done It This Time, Kul -## go_black_cage -######*/ - -enum eReallyDoneItThisTime -{ - QUEST_ALLIANCE_YOU_VE_REALLY_DONE_IT_THIS_TIME_KUL = 14096, - QUEST_HORDE_YOU_VE_REALLY_DONE_IT_THIS_TIME_KUL = 14142, - NPC_CAPTIVE_ASPIRANT = 34716, - NPC_KUL = 34956 -}; - -bool GOHello_go_black_cage(Player *pPlayer, GameObject *pGO) -{ - if ((pPlayer->GetTeamId() == TEAM_ALLIANCE && pPlayer->GetQuestStatus(QUEST_ALLIANCE_YOU_VE_REALLY_DONE_IT_THIS_TIME_KUL) == QUEST_STATUS_INCOMPLETE) || - (pPlayer->GetTeamId() == TEAM_HORDE && pPlayer->GetQuestStatus(QUEST_HORDE_YOU_VE_REALLY_DONE_IT_THIS_TIME_KUL) == QUEST_STATUS_INCOMPLETE)) - { - Creature *pPrisoner = pGO->FindNearestCreature(NPC_CAPTIVE_ASPIRANT,1.0f); - if (!pPrisoner) - pPrisoner = pGO->FindNearestCreature(NPC_KUL,1.0f); - if (pPrisoner) - { - pGO->UseDoorOrButton(); - pPrisoner->DisappearAndDie(); - pPlayer->KilledMonsterCredit(pPrisoner->GetEntry(),0); - } - } - return true; -} - -/*###### -## go_amberpine_outhouse -######*/ - -#define GOSSIP_USE_OUTHOUSE "Use the outhouse." -#define GO_ANDERHOLS_SLIDER_CIDER_NOT_FOUND "Quest item Anderhol's Slider Cider not found." - -enum eAmberpineOuthouse -{ - ITEM_ANDERHOLS_SLIDER_CIDER = 37247, - NPC_OUTHOUSE_BUNNY = 27326, - QUEST_DOING_YOUR_DUTY = 12227, - SPELL_INDISPOSED = 53017, - SPELL_INDISPOSED_III = 48341, - SPELL_CREATE_AMBERSEEDS = 48330, - GOSSIP_OUTHOUSE_INUSE = 12775, - GOSSIP_OUTHOUSE_VACANT = 12779 -}; - -bool GOHello_go_amberpine_outhouse(Player *pPlayer, GameObject *pGO) -{ - if (pPlayer->GetQuestStatus(QUEST_DOING_YOUR_DUTY) == QUEST_STATUS_INCOMPLETE || - (pPlayer->GetQuestStatus(QUEST_DOING_YOUR_DUTY) == QUEST_STATUS_COMPLETE)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_USE_OUTHOUSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_OUTHOUSE_VACANT, pGO->GetGUID()); - return true; - } - else - pPlayer->SEND_GOSSIP_MENU(GOSSIP_OUTHOUSE_INUSE, pGO->GetGUID()); - return true; -} - -bool GOSelect_go_amberpine_outhouse(Player *pPlayer, GameObject *pGO, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF +1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - Creature* pTarget = GetClosestCreatureWithEntry(pPlayer, NPC_OUTHOUSE_BUNNY, 3.0f); - if (pTarget) - { - pTarget->AI()->SetData(1,pPlayer->getGender()); - pGO->CastSpell(pTarget, SPELL_INDISPOSED_III); - } - pGO->CastSpell(pPlayer, SPELL_INDISPOSED); - if (pPlayer->HasItemCount(ITEM_ANDERHOLS_SLIDER_CIDER,1)) - pGO->CastSpell(pPlayer, SPELL_CREATE_AMBERSEEDS); - return true; - } - else - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->GetSession()->SendNotification(GO_ANDERHOLS_SLIDER_CIDER_NOT_FOUND); - return false; -} - -/*###### -## Quest 9544: The Prophecy of Akida -######*/ - -enum eProphecy -{ - QUEST_PROPHECY_OF_AKIDA = 9544, - NPC_STILLPINE_CAPTIVE = 17375 -}; - -bool GOHello_go_stillpine_cage(Player *pPlayer, GameObject *pGO) -{ - if (pPlayer->GetQuestStatus(QUEST_PROPHECY_OF_AKIDA) == QUEST_STATUS_INCOMPLETE) - if (Creature *pPrisoner = pGO->FindNearestCreature(NPC_STILLPINE_CAPTIVE,1.0f)) - { - pGO->UseDoorOrButton(); - pPrisoner->DisappearAndDie(); - pPlayer->KilledMonsterCredit(pPrisoner->GetEntry(),0); - } - return true; -} - -/*###### -## Quest 1126: Hive in the Tower -######*/ - -enum eHives -{ - QUEST_HIVE_IN_THE_TOWER = 9544, - NPC_HIVE_AMBUSHER = 13301 -}; - -bool GOHello_go_hive_pod(Player *pPlayer, GameObject *pGO) -{ - pPlayer->SendLoot(pGO->GetGUID(), LOOT_CORPSE); - pGO->SummonCreature(NPC_HIVE_AMBUSHER,pGO->GetPositionX()+1,pGO->GetPositionY(),pGO->GetPositionZ(),pGO->GetAngle(pPlayer),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); - pGO->SummonCreature(NPC_HIVE_AMBUSHER,pGO->GetPositionX(),pGO->GetPositionY()+1,pGO->GetPositionZ(),pGO->GetAngle(pPlayer),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); - return true; -} - -bool GOHello_go_massive_seaforium_charge(Player* pPlayer, GameObject *pGo) -{ - pGo->SetLootState(GO_JUST_DEACTIVATED); - return true; -} - -void AddSC_go_scripts() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_cat_figurine"; - newscript->pGOHello = &GOHello_go_cat_figurine; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_northern_crystal_pylon"; - newscript->pGOHello = &GOHello_go_northern_crystal_pylon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_eastern_crystal_pylon"; - newscript->pGOHello = &GOHello_go_eastern_crystal_pylon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_western_crystal_pylon"; - newscript->pGOHello = &GOHello_go_western_crystal_pylon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_barov_journal"; - newscript->pGOHello = &GOHello_go_barov_journal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_field_repair_bot_74A"; - newscript->pGOHello = &GOHello_go_field_repair_bot_74A; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_gilded_brazier"; - newscript->pGOHello = &GOHello_go_gilded_brazier; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_orb_of_command"; - newscript->pGOHello = &GOHello_go_orb_of_command; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_shrine_of_the_birds"; - newscript->pGOHello = &GOHello_go_shrine_of_the_birds; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_southfury_moonstone"; - newscript->pGOHello = &GOHello_go_southfury_moonstone; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_tablet_of_madness"; - newscript->pGOHello = &GOHello_go_tablet_of_madness; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_tablet_of_the_seven"; - newscript->pGOHello = &GOHello_go_tablet_of_the_seven; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_jump_a_tron"; - newscript->pGOHello = &GOHello_go_jump_a_tron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_ethereum_prison"; - newscript->pGOHello = &GOHello_go_ethereum_prison; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_ethereum_stasis"; - newscript->pGOHello = &GOHello_go_ethereum_stasis; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_resonite_cask"; - newscript->pGOHello = &GOHello_go_resonite_cask; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_sacred_fire_of_life"; - newscript->pGOHello = &GOHello_go_sacred_fire_of_life; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_tele_to_dalaran_crystal"; - newscript->pGOHello = &GOHello_go_tele_to_dalaran_crystal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_tele_to_violet_stand"; - newscript->pGOHello = &GOHello_go_tele_to_violet_stand; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_fel_crystalforge"; - newscript->pGOHello = &GOHello_go_fel_crystalforge; - newscript->pGOSelect = &GOSelect_go_fel_crystalforge; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_bashir_crystalforge"; - newscript->pGOHello = &GOHello_go_bashir_crystalforge; - newscript->pGOSelect = &GOSelect_go_bashir_crystalforge; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_matrix_punchograph"; - newscript->pGOHello = &GOHello_go_matrix_punchograph; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_rusty_cage"; - newscript->pGOHello = &GOHello_go_rusty_cage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_scourge_cage"; - newscript->pGOHello = &GOHello_go_scourge_cage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_arcane_prison"; - newscript->pGOHello = &GOHello_go_arcane_prison; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_blood_filled_orb"; - newscript->pGOHello = &GOHello_go_blood_filled_orb; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_jotunheim_cage"; - newscript->pGOHello = &GOHello_go_jotunheim_cage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_table_theka"; - newscript->pGOHello = &GOHello_go_table_theka; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_inconspicuous_landmark"; - newscript->pGOHello = &GOHello_go_inconspicuous_landmark; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_soulwell"; - newscript->pGOHello = &GOHello_go_soulwell; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_tadpole_cage"; - newscript->pGOHello = &GOHello_go_tadpole_cage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_dragonflayer_cage"; - newscript->pGOHello = &GOHello_go_dragonflayer_cage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_black_cage"; - newscript->pGOHello = &GOHello_go_black_cage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_stillpine_cage"; - newscript->pGOHello = &GOHello_go_stillpine_cage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_amberpine_outhouse"; - newscript->pGOHello = &GOHello_go_amberpine_outhouse; - newscript->pGOSelect = &GOSelect_go_amberpine_outhouse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_hive_pod"; - newscript->pGOHello = &GOHello_go_hive_pod; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_massive_seaforium_charge"; - newscript->pGOHello = &GOHello_go_massive_seaforium_charge; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/world/guards.cpp b/src/server/scripts/world/guards.cpp deleted file mode 100644 index 5faf9c73f7d..00000000000 --- a/src/server/scripts/world/guards.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Guards -SD%Complete: 100 -SDComment: All Guard gossip data, quite some npc_text-id's still missing, adding constantly as new id's are known. CombatAI should be organized better for future. -SDCategory: Guards -EndScriptData */ - -/* ContentData -guard_generic -guard_orgrimmar -guard_shattrath_aldor -guard_shattrath_scryer -guard_stormwind -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedGuardAI.h" - -/******************************************************* - * guard_generic - *******************************************************/ - -CreatureAI* GetAI_guard_generic(Creature* pCreature) -{ - return new guardAI (pCreature); -} - -/******************************************************* - * guard_orgrimmar - *******************************************************/ - -CreatureAI* GetAI_guard_orgrimmar(Creature* pCreature) -{ - return new guardAI_orgrimmar (pCreature); -} - -/******************************************************* - * guard_shattrath_aldor - *******************************************************/ - -#define SPELL_BANISHED_SHATTRATH_A 36642 -#define SPELL_BANISHED_SHATTRATH_S 36671 -#define SPELL_BANISH_TELEPORT 36643 -#define SPELL_EXILE 39533 - -struct guard_shattrath_aldorAI : public guardAI -{ - guard_shattrath_aldorAI(Creature *c) : guardAI(c) {} - - uint32 Exile_Timer; - uint32 Banish_Timer; - uint64 PlayerGUID; - bool CanTeleport; - - void Reset() - { - Banish_Timer = 5000; - Exile_Timer = 8500; - PlayerGUID = 0; - CanTeleport = false; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (CanTeleport) - { - if (Exile_Timer <= diff) - { - if (Unit* temp = Unit::GetUnit(*me,PlayerGUID)) - { - temp->CastSpell(temp,SPELL_EXILE,true); - temp->CastSpell(temp,SPELL_BANISH_TELEPORT,true); - } - PlayerGUID = 0; - Exile_Timer = 8500; - CanTeleport = false; - } else Exile_Timer -= diff; - } - else if (Banish_Timer <= diff) - { - Unit* temp = me->getVictim(); - if (temp && temp->GetTypeId() == TYPEID_PLAYER) - { - DoCast(temp, SPELL_BANISHED_SHATTRATH_A); - Banish_Timer = 9000; - PlayerGUID = temp->GetGUID(); - if (PlayerGUID) - CanTeleport = true; - } - } else Banish_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_guard_shattrath_aldor(Creature* pCreature) -{ - return new guard_shattrath_aldorAI (pCreature); -} - -/******************************************************* - * guard_shattrath_scryer - *******************************************************/ - -struct guard_shattrath_scryerAI : public guardAI -{ - guard_shattrath_scryerAI(Creature *c) : guardAI(c) {} - - uint32 Exile_Timer; - uint32 Banish_Timer; - uint64 PlayerGUID; - bool CanTeleport; - - void Reset() - { - Banish_Timer = 5000; - Exile_Timer = 8500; - PlayerGUID = 0; - CanTeleport = false; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (CanTeleport) - { - if (Exile_Timer <= diff) - { - if (Unit* temp = Unit::GetUnit(*me,PlayerGUID)) - { - temp->CastSpell(temp,SPELL_EXILE,true); - temp->CastSpell(temp,SPELL_BANISH_TELEPORT,true); - } - PlayerGUID = 0; - Exile_Timer = 8500; - CanTeleport = false; - } else Exile_Timer -= diff; - } - else if (Banish_Timer <= diff) - { - Unit* temp = me->getVictim(); - if (temp && temp->GetTypeId() == TYPEID_PLAYER) - { - DoCast(temp, SPELL_BANISHED_SHATTRATH_S); - Banish_Timer = 9000; - PlayerGUID = temp->GetGUID(); - if (PlayerGUID) - CanTeleport = true; - } - } else Banish_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_guard_shattrath_scryer(Creature* pCreature) -{ - return new guard_shattrath_scryerAI (pCreature); -} - -/******************************************************* - * guard_stormwind - *******************************************************/ - -CreatureAI* GetAI_guard_stormwind(Creature* pCreature) -{ - return new guardAI_stormwind (pCreature); -} - -/******************************************************* - * AddSC - *******************************************************/ - -void AddSC_guards() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "guard_generic"; - newscript->GetAI = &GetAI_guard_generic; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "guard_orgrimmar"; - newscript->GetAI = &GetAI_guard_orgrimmar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "guard_shattrath_aldor"; - newscript->GetAI = &GetAI_guard_shattrath_aldor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "guard_shattrath_scryer"; - newscript->GetAI = &GetAI_guard_shattrath_scryer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "guard_stormwind"; - newscript->GetAI = &GetAI_guard_stormwind; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/world/item_scripts.cpp b/src/server/scripts/world/item_scripts.cpp deleted file mode 100644 index dbf5f3c1a84..00000000000 --- a/src/server/scripts/world/item_scripts.cpp +++ /dev/null @@ -1,479 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Item_Scripts -SD%Complete: 100 -SDComment: Items for a range of different items. See content below (in script) -SDCategory: Items -EndScriptData */ - -/* ContentData -item_draenei_fishing_net(i23654) Hacklike implements chance to spawn item or creature -item_nether_wraith_beacon(i31742) Summons creatures for quest Becoming a Spellfire Tailor (q10832) -item_flying_machine(i34060,i34061) Engineering crafted flying machines -item_gor_dreks_ointment(i30175) Protecting Our Own(q10488) -item_only_for_flight Items which should only useable while flying -EndContentData */ - -#include "ScriptedPch.h" -#include "Spell.h" - -/*##### -# item_only_for_flight -#####*/ - -enum eOnlyForFlight -{ - SPELL_ARCANE_CHARGES = 45072 -}; - -bool ItemUse_item_only_for_flight(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/) -{ - uint32 itemId = pItem->GetEntry(); - bool disabled = false; - - //for special scripts - switch(itemId) - { - case 24538: - if (pPlayer->GetAreaId() != 3628) - disabled = true; - break; - case 34489: - if (pPlayer->GetZoneId() != 4080) - disabled = true; - break; - case 34475: - if (const SpellEntry* pSpellInfo = GetSpellStore()->LookupEntry(SPELL_ARCANE_CHARGES)) - Spell::SendCastResult(pPlayer, pSpellInfo, 1, SPELL_FAILED_NOT_ON_GROUND); - break; - } - - // allow use in flight only - if (pPlayer->isInFlight() && !disabled) - return false; - - // error - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,pItem,NULL); - return true; -} - -/*##### -# item_draenei_fishing_net -#####*/ - -//This is just a hack and should be removed from here. -//Creature/Item are in fact created before spell are sucessfully casted, without any checks at all to ensure proper/expected behavior. -bool ItemUse_item_draenei_fishing_net(Player* pPlayer, Item* /*pItem*/, SpellCastTargets const& /*targets*/) -{ - //if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT && - //targets.getGOTarget()->GetGOInfo()->type == GAMEOBJECT_TYPE_SPELL_FOCUS && targets.getGOTarget()->GetEntry() == 181616) - //{ - if (pPlayer->GetQuestStatus(9452) == QUEST_STATUS_INCOMPLETE) - { - if (urand(0,99) < 35) - { - Creature *Murloc = pPlayer->SummonCreature(17102, pPlayer->GetPositionX(), pPlayer->GetPositionY()+20, pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); - if (Murloc) - Murloc->AI()->AttackStart(pPlayer); - } - else - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 23614, 1); - if (msg == EQUIP_ERR_OK) - { - if (Item* item = pPlayer->StoreNewItem(dest,23614,true)) - pPlayer->SendNewItem(item,1,false,true); - } else - pPlayer->SendEquipError(msg,NULL,NULL); - } - } - //} - return false; -} - -/*##### -# item_nether_wraith_beacon -#####*/ - -bool ItemUse_item_nether_wraith_beacon(Player* pPlayer, Item* /*pItem*/, SpellCastTargets const& /*targets*/) -{ - if (pPlayer->GetQuestStatus(10832) == QUEST_STATUS_INCOMPLETE) - { - Creature *Nether; - Nether = pPlayer->SummonCreature(22408, pPlayer->GetPositionX(), pPlayer->GetPositionY()+20, pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); - Nether = pPlayer->SummonCreature(22408, pPlayer->GetPositionX(), pPlayer->GetPositionY()-20, pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); - if (Nether) - Nether->AI()->AttackStart(pPlayer); - } - return false; -} - -/*##### -# item_flying_machine -#####*/ - -bool ItemUse_item_flying_machine(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/) -{ - uint32 itemId = pItem->GetEntry(); - if (itemId == 34060) - if (pPlayer->GetBaseSkillValue(SKILL_RIDING) >= 225) - return false; - - if (itemId == 34061) - if (pPlayer->GetBaseSkillValue(SKILL_RIDING) == 300) - return false; - - debug_log("TSCR: Player attempt to use item %u, but did not meet riding requirement",itemId); - pPlayer->SendEquipError(EQUIP_ERR_ERR_CANT_EQUIP_SKILL,pItem,NULL); - return true; -} - -/*##### -# item_gor_dreks_ointment -#####*/ - -bool ItemUse_item_gor_dreks_ointment(Player *pPlayer, Item *pItem, SpellCastTargets const& targets) -{ - if (targets.getUnitTarget() && targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT && - targets.getUnitTarget()->GetEntry() == 20748 && !targets.getUnitTarget()->HasAura(32578)) - return false; - - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,pItem,NULL); - return true; -} - -/*##### -# item_incendiary_explosives -#####*/ - -bool ItemUse_item_incendiary_explosives(Player *pPlayer, Item *pItem, SpellCastTargets const & /*targets*/) -{ - if (pPlayer->FindNearestCreature(26248,15) || pPlayer->FindNearestCreature(26249,15)) - return false; - else - { - pPlayer->SendEquipError(EQUIP_ERR_OUT_OF_RANGE,pItem,NULL); - return true; - } -} - -/*##### -# item_mysterious_egg -#####*/ - -bool ItemExpire_item_mysterious_egg(Player *pPlayer, ItemPrototype const * /*pItemProto*/) -{ - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 39883, 1); // Cracked Egg - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, 39883, true, Item::GenerateItemRandomPropertyId(39883)); - - return true; -} - -/*##### -# item_disgusting_jar -#####*/ - -bool ItemExpire_item_disgusting_jar(Player *pPlayer, ItemPrototype const * /*pItemProto*/) -{ - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 44718, 1); // Ripe Disgusting Jar - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, 44718, true, Item::GenerateItemRandomPropertyId(44718)); - - return true; -} - -/*##### -# item_harvesters_gift -#####*/ -#define GHOULS 28845 -bool ItemUse_item_harvesters_gift(Player* pPlayer, Item* /*pItem*/, SpellCastTargets const& /*targets*/) -{ - std::list MinionList; - pPlayer->GetAllMinionsByEntry(MinionList,GHOULS); - - if (pPlayer->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE) - { - if (!MinionList.empty()) - { - if (MinionList.size() < 5) - return false; - else - { - //This should be sent to the player as red text. - pPlayer->Say("You have created enough ghouls. Return to Gothik the Harvester at Death's Breach.",LANG_UNIVERSAL); - return true; - } - } - else - return false; - } - return true; -} - -/*##### -# item_pile_fake_furs -#####*/ - -enum ePileFakeFur -{ - GO_CARIBOU_TRAP_1 = 187982, - GO_CARIBOU_TRAP_2 = 187995, - GO_CARIBOU_TRAP_3 = 187996, - GO_CARIBOU_TRAP_4 = 187997, - GO_CARIBOU_TRAP_5 = 187998, - GO_CARIBOU_TRAP_6 = 187999, - GO_CARIBOU_TRAP_7 = 188000, - GO_CARIBOU_TRAP_8 = 188001, - GO_CARIBOU_TRAP_9 = 188002, - GO_CARIBOU_TRAP_10 = 188003, - GO_CARIBOU_TRAP_11 = 188004, - GO_CARIBOU_TRAP_12 = 188005, - GO_CARIBOU_TRAP_13 = 188006, - GO_CARIBOU_TRAP_14 = 188007, - GO_CARIBOU_TRAP_15 = 188008, - GO_HIGH_QUALITY_FUR = 187983, - NPC_NESINGWARY_TRAPPER = 25835 -}; - -#define CaribouTrapsNum 15 -const uint32 CaribouTraps[CaribouTrapsNum] = -{ - GO_CARIBOU_TRAP_1, GO_CARIBOU_TRAP_2, GO_CARIBOU_TRAP_3, GO_CARIBOU_TRAP_4, GO_CARIBOU_TRAP_5, - GO_CARIBOU_TRAP_6, GO_CARIBOU_TRAP_7, GO_CARIBOU_TRAP_8, GO_CARIBOU_TRAP_9, GO_CARIBOU_TRAP_10, - GO_CARIBOU_TRAP_11, GO_CARIBOU_TRAP_12, GO_CARIBOU_TRAP_13, GO_CARIBOU_TRAP_14, GO_CARIBOU_TRAP_15, -}; - - -bool ItemUse_item_pile_fake_furs(Player *pPlayer, Item * /*pItem*/, SpellCastTargets const & /*targets*/) -{ - GameObject *pGo = NULL; - for (uint8 i = 0; i < CaribouTrapsNum; ++i) - { - pGo = pPlayer->FindNearestGameObject(CaribouTraps[i], 5.0f); - if (pGo) - break; - } - - if (!pGo) - return false; - - if (pGo->FindNearestCreature(NPC_NESINGWARY_TRAPPER, 10.0f, true) || pGo->FindNearestCreature(NPC_NESINGWARY_TRAPPER, 10.0f, false) || pGo->FindNearestGameObject(GO_HIGH_QUALITY_FUR, 2.0f)) - return true; - - float x, y, z; - pGo->GetClosePoint(x, y, z, pGo->GetObjectSize() / 3, 7.0f); - pGo->SummonGameObject(GO_HIGH_QUALITY_FUR, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, 0, 0, 0, 0, 1000); - if (TempSummon* summon = pPlayer->SummonCreature(NPC_NESINGWARY_TRAPPER, x, y, z, pGo->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1000)) - { - summon->SetVisibility(VISIBILITY_OFF); - summon->SetReactState(REACT_PASSIVE); - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - return false; -} - -/*##### -# item_petrov_cluster_bombs -#####*/ - -enum ePetrovClusterBombs -{ - SPELL_PETROV_BOMB = 42406, - AREA_ID_SHATTERED_STRAITS = 4064, - ZONE_ID_HOWLING = 495 -}; - -bool ItemUse_item_petrov_cluster_bombs(Player* pPlayer, Item* pItem, const SpellCastTargets & /*pTargets*/) -{ - if (pPlayer->GetZoneId() != ZONE_ID_HOWLING) - return false; - - if (!pPlayer->GetTransport() || pPlayer->GetAreaId() != AREA_ID_SHATTERED_STRAITS) - { - pPlayer->SendEquipError(EQUIP_ERR_NONE, pItem, NULL); - - if (const SpellEntry* pSpellInfo = GetSpellStore()->LookupEntry(SPELL_PETROV_BOMB)) - Spell::SendCastResult(pPlayer, pSpellInfo, 1, SPELL_FAILED_NOT_HERE); - - return true; - } - - return false; -} - -/*###### -# item_dehta_trap_smasher -# For quest 11876, Help Those That Cannot Help Themselves -######*/ -enum eHelpThemselves -{ - QUEST_CANNOT_HELP_THEMSELVES = 11876, - NPC_TRAPPED_MAMMOTH_CALF = 25850, - GO_MAMMOTH_TRAP_1 = 188022, - GO_MAMMOTH_TRAP_2 = 188024, - GO_MAMMOTH_TRAP_3 = 188025, - GO_MAMMOTH_TRAP_4 = 188026, - GO_MAMMOTH_TRAP_5 = 188027, - GO_MAMMOTH_TRAP_6 = 188028, - GO_MAMMOTH_TRAP_7 = 188029, - GO_MAMMOTH_TRAP_8 = 188030, - GO_MAMMOTH_TRAP_9 = 188031, - GO_MAMMOTH_TRAP_10 = 188032, - GO_MAMMOTH_TRAP_11 = 188033, - GO_MAMMOTH_TRAP_12 = 188034, - GO_MAMMOTH_TRAP_13 = 188035, - GO_MAMMOTH_TRAP_14 = 188036, - GO_MAMMOTH_TRAP_15 = 188037, - GO_MAMMOTH_TRAP_16 = 188038, - GO_MAMMOTH_TRAP_17 = 188039, - GO_MAMMOTH_TRAP_18 = 188040, - GO_MAMMOTH_TRAP_19 = 188041, - GO_MAMMOTH_TRAP_20 = 188042, - GO_MAMMOTH_TRAP_21 = 188043, - GO_MAMMOTH_TRAP_22 = 188044, -}; - -#define MammothTrapsNum 22 -const uint32 MammothTraps[MammothTrapsNum] = -{ - GO_MAMMOTH_TRAP_1, GO_MAMMOTH_TRAP_2, GO_MAMMOTH_TRAP_3, GO_MAMMOTH_TRAP_4, GO_MAMMOTH_TRAP_5, - GO_MAMMOTH_TRAP_6, GO_MAMMOTH_TRAP_7, GO_MAMMOTH_TRAP_8, GO_MAMMOTH_TRAP_9, GO_MAMMOTH_TRAP_10, - GO_MAMMOTH_TRAP_11, GO_MAMMOTH_TRAP_12, GO_MAMMOTH_TRAP_13, GO_MAMMOTH_TRAP_14, GO_MAMMOTH_TRAP_15, - GO_MAMMOTH_TRAP_16, GO_MAMMOTH_TRAP_17, GO_MAMMOTH_TRAP_18, GO_MAMMOTH_TRAP_19, GO_MAMMOTH_TRAP_20, - GO_MAMMOTH_TRAP_21, GO_MAMMOTH_TRAP_22 -}; - -bool ItemUse_item_dehta_trap_smasher(Player* pPlayer, Item* /*pItem*/, const SpellCastTargets & /*pTargets*/) -{ - if (pPlayer->GetQuestStatus(QUEST_CANNOT_HELP_THEMSELVES) != QUEST_STATUS_INCOMPLETE) - return false; - - Creature* pMammoth; - pMammoth = pPlayer->FindNearestCreature(NPC_TRAPPED_MAMMOTH_CALF,5.0f); - if (!pMammoth) - return false; - - GameObject* pTrap; - for (uint8 i = 0; i < MammothTrapsNum; ++i) - { - pTrap = pPlayer->FindNearestGameObject(MammothTraps[i],11.0f); - if (pTrap) - { - pMammoth->AI()->DoAction(1); - pTrap->SetGoState(GO_STATE_READY); - pPlayer->KilledMonsterCredit(NPC_TRAPPED_MAMMOTH_CALF,0); - return true; - } - } - return false; -} - -enum TheEmissary -{ - QUEST_THE_EMISSARY = 11626, - NPC_LEVIROTH = 26452 -}; - -bool ItemUse_item_Trident_of_Nazjan(Player* pPlayer, Item* pItem, const SpellCastTargets & /*pTargets*/) -{ - if (pPlayer->GetQuestStatus(QUEST_THE_EMISSARY) == QUEST_STATUS_INCOMPLETE) - { - if (Creature* pLeviroth = pPlayer->FindNearestCreature(NPC_LEVIROTH, 10.0f)) // spell range - { - pLeviroth->AI()->AttackStart(pPlayer); - return false; - } else - pPlayer->SendEquipError(EQUIP_ERR_OUT_OF_RANGE, pItem, NULL); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW ,pItem, NULL); - return true; -} - -void AddSC_item_scripts() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "item_only_for_flight"; - newscript->pItemUse = &ItemUse_item_only_for_flight; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_draenei_fishing_net"; - newscript->pItemUse = &ItemUse_item_draenei_fishing_net; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_nether_wraith_beacon"; - newscript->pItemUse = &ItemUse_item_nether_wraith_beacon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_flying_machine"; - newscript->pItemUse = &ItemUse_item_flying_machine; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_gor_dreks_ointment"; - newscript->pItemUse = &ItemUse_item_gor_dreks_ointment; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_incendiary_explosives"; - newscript->pItemUse = &ItemUse_item_incendiary_explosives; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_mysterious_egg"; - newscript->pItemExpire = &ItemExpire_item_mysterious_egg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_disgusting_jar"; - newscript->pItemExpire = &ItemExpire_item_disgusting_jar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_harvesters_gift"; - newscript->pItemUse = &ItemUse_item_harvesters_gift; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_pile_fake_furs"; - newscript->pItemUse = &ItemUse_item_pile_fake_furs; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_petrov_cluster_bombs"; - newscript->pItemUse = &ItemUse_item_petrov_cluster_bombs; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_dehta_trap_smasher"; - newscript->pItemUse = &ItemUse_item_dehta_trap_smasher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_Trident_of_Nazjan"; - newscript->pItemUse = &ItemUse_item_Trident_of_Nazjan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/world/mob_generic_creature.cpp b/src/server/scripts/world/mob_generic_creature.cpp deleted file mode 100644 index 3ab515d8206..00000000000 --- a/src/server/scripts/world/mob_generic_creature.cpp +++ /dev/null @@ -1,228 +0,0 @@ - -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Generic_Creature -SD%Complete: 80 -SDComment: Should be replaced with core based AI -SDCategory: Creatures -EndScriptData */ - -#include "ScriptedPch.h" - -#define GENERIC_CREATURE_COOLDOWN 5000 - -struct generic_creatureAI : public ScriptedAI -{ - generic_creatureAI(Creature *c) : ScriptedAI(c) {} - - uint32 GlobalCooldown; //This variable acts like the global cooldown that players have (1.5 seconds) - uint32 BuffTimer; //This variable keeps track of buffs - bool IsSelfRooted; - - void Reset() - { - GlobalCooldown = 0; - BuffTimer = 0; //Rebuff as soon as we can - IsSelfRooted = false; - } - - void EnterCombat(Unit *who) - { - if (!me->IsWithinMeleeRange(who)) - { - IsSelfRooted = true; - } - } - - void UpdateAI(const uint32 diff) - { - //Always decrease our global cooldown first - if (GlobalCooldown > diff) - GlobalCooldown -= diff; - else GlobalCooldown = 0; - - //Buff timer (only buff when we are alive and not in combat - if (!me->isInCombat() && me->isAlive()) - if (BuffTimer <= diff) - { - //Find a spell that targets friendly and applies an aura (these are generally buffs) - SpellEntry const *info = SelectSpell(me, 0, 0, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_AURA); - - if (info && !GlobalCooldown) - { - //Cast the buff spell - DoCastSpell(me, info); - - //Set our global cooldown - GlobalCooldown = GENERIC_CREATURE_COOLDOWN; - - //Set our timer to 10 minutes before rebuff - BuffTimer = 600000; - }//Try agian in 30 seconds - else BuffTimer = 30000; - } else BuffTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - //Make sure our attack is ready and we arn't currently casting - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - bool Healing = false; - SpellEntry const *info = NULL; - - //Select a healing spell if less than 30% hp - if (me->GetHealth()*100 / me->GetMaxHealth() < 30) - info = SelectSpell(me, 0, 0, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); - - //No healing spell available, select a hostile spell - if (info) Healing = true; - else info = SelectSpell(me->getVictim(), 0, 0, SELECT_TARGET_ANY_ENEMY, 0, 0, 0, 0, SELECT_EFFECT_DONTCARE); - - //50% chance if elite or higher, 20% chance if not, to replace our white hit with a spell - if (info && (rand() % (me->GetCreatureInfo()->rank > 1 ? 2 : 5) == 0) && !GlobalCooldown) - { - //Cast the spell - if (Healing)DoCastSpell(me, info); - else DoCastSpell(me->getVictim(), info); - - //Set our global cooldown - GlobalCooldown = GENERIC_CREATURE_COOLDOWN; - } - else me->AttackerStateUpdate(me->getVictim()); - - me->resetAttackTimer(); - } - } - else - { - //Only run this code if we arn't already casting - if (!me->IsNonMeleeSpellCasted(false)) - { - bool Healing = false; - SpellEntry const *info = NULL; - - //Select a healing spell if less than 30% hp ONLY 33% of the time - if (me->GetHealth()*100 / me->GetMaxHealth() < 30 && rand() % 3 == 0) - info = SelectSpell(me, 0, 0, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING); - - //No healing spell available, See if we can cast a ranged spell (Range must be greater than ATTACK_DISTANCE) - if (info) Healing = true; - else info = SelectSpell(me->getVictim(), 0, 0, SELECT_TARGET_ANY_ENEMY, 0, 0, NOMINAL_MELEE_RANGE, 0, SELECT_EFFECT_DONTCARE); - - //Found a spell, check if we arn't on cooldown - if (info && !GlobalCooldown) - { - //If we are currently moving stop us and set the movement generator - if (!IsSelfRooted) - { - IsSelfRooted = true; - } - - //Cast spell - if (Healing) DoCastSpell(me,info); - else DoCastSpell(me->getVictim(),info); - - //Set our global cooldown - GlobalCooldown = GENERIC_CREATURE_COOLDOWN; - - }//If no spells available and we arn't moving run to target - else if (IsSelfRooted) - { - //Cancel our current spell and then allow movement agian - me->InterruptNonMeleeSpells(false); - IsSelfRooted = false; - } - } - } - } -}; - -CreatureAI* GetAI_generic_creature(Creature* pCreature) -{ - return new generic_creatureAI (pCreature); -} - -struct trigger_periodicAI : public NullCreatureAI -{ - trigger_periodicAI(Creature* c) : NullCreatureAI(c) - { - spell = me->m_spells[0] ? GetSpellStore()->LookupEntry(me->m_spells[0]) : NULL; - interval = me->GetAttackTime(BASE_ATTACK); - timer = interval; - } - - uint32 timer, interval; - const SpellEntry * spell; - - void UpdateAI(const uint32 diff) - { - if (timer <= diff) - { - if (spell) - me->CastSpell(me, spell, true); - timer = interval; - } - else - timer -= diff; - } -}; - -struct trigger_deathAI : public NullCreatureAI -{ - trigger_deathAI(Creature* c) : NullCreatureAI(c) {} - void JustDied(Unit *killer) - { - if (me->m_spells[0]) - me->CastSpell(killer, me->m_spells[0], true); - } -}; - -CreatureAI* GetAI_trigger_periodic(Creature* pCreature) -{ - return new trigger_periodicAI (pCreature); -} - -CreatureAI* GetAI_trigger_death(Creature* pCreature) -{ - return new trigger_deathAI (pCreature); -} - -void AddSC_generic_creature() -{ - Script *newscript; - /*newscript = new Script; - newscript->Name = "generic_creature"; - newscript->GetAI = &GetAI_generic_creature; - newscript->RegisterSelf();*/ - - newscript = new Script; - newscript->Name = "trigger_periodic"; - newscript->GetAI = &GetAI_trigger_periodic; - newscript->RegisterSelf(); - - /*newscript = new Script; - newscript->Name = "trigger_death"; - newscript->GetAI = &GetAI_trigger_death; - newscript->RegisterSelf();*/ -} - diff --git a/src/server/scripts/world/npc_innkeeper.cpp b/src/server/scripts/world/npc_innkeeper.cpp deleted file mode 100644 index 9bda7a53516..00000000000 --- a/src/server/scripts/world/npc_innkeeper.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Npc_Innkeeper -SDAuthor: WarHead -SD%Complete: 99% -SDComment: Complete -SDCategory: NPCs -EndScriptData */ - -#include "ScriptedPch.h" - -#define HALLOWEEN_EVENTID 12 -#define SPELL_TRICK_OR_TREATED 24755 -#define SPELL_TREAT 24715 - -#define LOCALE_TRICK_OR_TREAT_0 "Trick or Treat!" -#define LOCALE_TRICK_OR_TREAT_2 "Des bonbons ou des blagues!" -#define LOCALE_TRICK_OR_TREAT_3 "Süßes oder Saures!" -#define LOCALE_TRICK_OR_TREAT_6 "¡Truco o trato!" - -#define LOCALE_INNKEEPER_0 "Make this inn my home." -#define LOCALE_INNKEEPER_3 "Ich möchte dieses Gasthaus zu meinem Heimatort machen." - -bool GossipHello_npc_innkeeper(Player *pPlayer, Creature *pCreature) -{ - if (IsEventActive(HALLOWEEN_EVENTID) && !pPlayer->HasAura(SPELL_TRICK_OR_TREATED)) - { - char* localizedEntry; - switch (pPlayer->GetSession()->GetSessionDbcLocale()) - { - case LOCALE_frFR: localizedEntry = LOCALE_TRICK_OR_TREAT_2; break; - case LOCALE_deDE: localizedEntry = LOCALE_TRICK_OR_TREAT_3; break; - case LOCALE_esES: localizedEntry = LOCALE_TRICK_OR_TREAT_6; break; - case LOCALE_enUS: default: localizedEntry = LOCALE_TRICK_OR_TREAT_0; - } - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, localizedEntry, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+HALLOWEEN_EVENTID); - } - - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - if (pCreature->isInnkeeper()) - { - char* localizedEntry; - switch (pPlayer->GetSession()->GetSessionDbcLocale()) - { - case LOCALE_deDE: localizedEntry = LOCALE_INNKEEPER_3; break; - case LOCALE_enUS: default: localizedEntry = LOCALE_INNKEEPER_0; - } - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_INTERACT_1, localizedEntry, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INN); - } - - pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_innkeeper(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+HALLOWEEN_EVENTID && IsEventActive(HALLOWEEN_EVENTID) && !pPlayer->HasAura(SPELL_TRICK_OR_TREATED)) - { - pPlayer->CastSpell(pPlayer, SPELL_TRICK_OR_TREATED, true); - - if (urand(0, 1)) - pPlayer->CastSpell(pPlayer, SPELL_TREAT, true); - else - { - uint32 trickspell = 0; - switch (urand(0, 13)) - { - case 0: trickspell = 24753; break; // cannot cast, random 30sec - case 1: trickspell = 24713; break; // lepper gnome costume - case 2: trickspell = 24735; break; // male ghost costume - case 3: trickspell = 24736; break; // female ghostcostume - case 4: trickspell = 24710; break; // male ninja costume - case 5: trickspell = 24711; break; // female ninja costume - case 6: trickspell = 24708; break; // male pirate costume - case 7: trickspell = 24709; break; // female pirate costume - case 8: trickspell = 24723; break; // skeleton costume - case 9: trickspell = 24753; break; // Trick - case 10: trickspell = 24924; break; // Hallow's End Candy - case 11: trickspell = 24925; break; // Hallow's End Candy - case 12: trickspell = 24926; break; // Hallow's End Candy - case 13: trickspell = 24927; break; // Hallow's End Candy - } - pPlayer->CastSpell(pPlayer, trickspell, true); - } - pPlayer->CLOSE_GOSSIP_MENU(); - return true; - } - - pPlayer->CLOSE_GOSSIP_MENU(); - - switch (uiAction) - { - case GOSSIP_ACTION_TRADE: pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); break; - case GOSSIP_ACTION_INN: pPlayer->SetBindPoint(pCreature->GetGUID()); break; - } - return true; -} - -void AddSC_npc_innkeeper() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "npc_innkeeper"; - newscript->pGossipHello = &GossipHello_npc_innkeeper; - newscript->pGossipSelect = &GossipSelect_npc_innkeeper; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/world/npc_professions.cpp b/src/server/scripts/world/npc_professions.cpp deleted file mode 100644 index ed22225d0d4..00000000000 --- a/src/server/scripts/world/npc_professions.cpp +++ /dev/null @@ -1,1342 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Npc_Professions -SD%Complete: 80 -SDComment: Provides learn/unlearn/relearn-options for professions. Not supported: Unlearn engineering, re-learn engineering, re-learn leatherworking. -SDCategory: NPCs -EndScriptData */ - -#include "ScriptedPch.h" - -/* -A few notes for future developement: -- A full implementation of gossip for GO's is required. They must have the same scripting capabilities as creatures. Basically, -there is no difference here (except that default text is chosen with `gameobject_template`.`data3` (for GO type2, different dataN for a few others) -- It's possible blacksmithing still require some tweaks and adjustments due to the way we _have_ to use reputation. -*/ - -/* --- UPDATE `gameobject_template` SET `ScriptName` = 'go_soothsaying_for_dummies' WHERE `entry` = 177226; -*/ - -/*### -# to be removed from here (->ncp_text). This is data for database projects. -###*/ -#define TALK_MUST_UNLEARN_WEAPON "You must forget your weapon type specialty before I can help you. Go to Everlook in Winterspring and seek help there." - -#define TALK_HAMMER_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the hammersmith." -#define TALK_AXE_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the axesmith." -#define TALK_SWORD_LEARN "Ah, a seasoned veteran you once were. I know you are capable, you merely need to ask and I shall teach you the way of the swordsmith." - -#define TALK_HAMMER_UNLEARN "Forgetting your Hammersmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Hammersmithing to create!" -#define TALK_AXE_UNLEARN "Forgetting your Axesmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Axesmithing to create!" -#define TALK_SWORD_UNLEARN "Forgetting your Swordsmithing skill is not something to do lightly. If you choose to abandon it you will forget all recipes that require Swordsmithing to create!" - -/*### -# generic defines -###*/ - -#define GOSSIP_SENDER_LEARN 50 -#define GOSSIP_SENDER_UNLEARN 51 -#define GOSSIP_SENDER_CHECK 52 - -/*### -# gossip item and box texts -###*/ - -#define GOSSIP_LEARN_POTION "Please teach me how to become a Master of Potions, Lauranna" -#define GOSSIP_UNLEARN_POTION "I wish to unlearn Potion Mastery" -#define GOSSIP_LEARN_TRANSMUTE "Please teach me how to become a Master of Transmutations, Zarevhi" -#define GOSSIP_UNLEARN_TRANSMUTE "I wish to unlearn Transmutation Mastery" -#define GOSSIP_LEARN_ELIXIR "Please teach me how to become a Master of Elixirs, Lorokeem" -#define GOSSIP_UNLEARN_ELIXIR "I wish to unlearn Elixir Mastery" - -#define BOX_UNLEARN_ALCHEMY_SPEC "Do you really want to unlearn your alchemy specialty and lose all associated recipes? \n Cost: " - -#define GOSSIP_WEAPON_LEARN "Please teach me how to become a Weaponsmith" -#define GOSSIP_WEAPON_UNLEARN "I wish to unlearn the art of Weaponsmithing" -#define GOSSIP_ARMOR_LEARN "Please teach me how to become a Armorsmith" -#define GOSSIP_ARMOR_UNLEARN "I wish to unlearn the art of Armorsmithing" - -#define GOSSIP_UNLEARN_SMITH_SPEC "I wish to unlearn my blacksmith specialty" -#define BOX_UNLEARN_ARMORORWEAPON "Do you really want to unlearn your blacksmith specialty and lose all associated recipes? \n Cost: " - -#define GOSSIP_LEARN_HAMMER "Please teach me how to become a Hammersmith, Lilith" -#define GOSSIP_UNLEARN_HAMMER "I wish to unlearn Hammersmithing" -#define GOSSIP_LEARN_AXE "Please teach me how to become a Axesmith, Kilram" -#define GOSSIP_UNLEARN_AXE "I wish to unlearn Axesmithing" -#define GOSSIP_LEARN_SWORD "Please teach me how to become a Swordsmith, Seril" -#define GOSSIP_UNLEARN_SWORD "I wish to unlearn Swordsmithing" - -#define BOX_UNLEARN_WEAPON_SPEC "Do you really want to unlearn your weaponsmith specialty and lose all associated recipes? \n Cost: " - -#define GOSSIP_LEARN_DRAGON "I am absolutely certain that i want to learn dragonscale leatherworking" -#define GOSSIP_UNLEARN_DRAGON "I wish to unlearn Dragonscale Leatherworking" -#define GOSSIP_LEARN_ELEMENTAL "I am absolutely certain that i want to learn elemental leatherworking" -#define GOSSIP_UNLEARN_ELEMENTAL "I wish to unlearn Elemental Leatherworking" -#define GOSSIP_LEARN_TRIBAL "I am absolutely certain that i want to learn tribal leatherworking" -#define GOSSIP_UNLEARN_TRIBAL "I wish to unlearn Tribal Leatherworking" - -#define BOX_UNLEARN_LEATHER_SPEC "Do you really want to unlearn your leatherworking specialty and lose all associated recipes? \n Cost: " - -#define GOSSIP_LEARN_SPELLFIRE "Please teach me how to become a Spellcloth tailor" -#define GOSSIP_UNLEARN_SPELLFIRE "I wish to unlearn Spellfire Tailoring" -#define GOSSIP_LEARN_MOONCLOTH "Please teach me how to become a Mooncloth tailor" -#define GOSSIP_UNLEARN_MOONCLOTH "I wish to unlearn Mooncloth Tailoring" -#define GOSSIP_LEARN_SHADOWEAVE "Please teach me how to become a Shadoweave tailor" -#define GOSSIP_UNLEARN_SHADOWEAVE "I wish to unlearn Shadoweave Tailoring" - -#define BOX_UNLEARN_TAILOR_SPEC "Do you really want to unlearn your tailoring specialty and lose all associated recipes? \n Cost: " - -#define GOSSIP_LEARN_GOBLIN "I am absolutely certain that i want to learn Goblin engineering" -#define GOSSIP_LEARN_GNOMISH "I am absolutely certain that i want to learn Gnomish engineering" - -/*### -# spells defines -###*/ - -#define S_WEAPON 9787 -#define S_ARMOR 9788 -#define S_HAMMER 17040 -#define S_AXE 17041 -#define S_SWORD 17039 - -#define S_LEARN_WEAPON 9789 -#define S_LEARN_ARMOR 9790 -#define S_LEARN_HAMMER 39099 -#define S_LEARN_AXE 39098 -#define S_LEARN_SWORD 39097 - -#define S_UNLEARN_WEAPON 36436 -#define S_UNLEARN_ARMOR 36435 -#define S_UNLEARN_HAMMER 36441 -#define S_UNLEARN_AXE 36439 -#define S_UNLEARN_SWORD 36438 - -#define S_REP_ARMOR 17451 -#define S_REP_WEAPON 17452 - -#define REP_ARMOR 46 -#define REP_WEAPON 289 -#define REP_HAMMER 569 -#define REP_AXE 570 -#define REP_SWORD 571 - -#define S_DRAGON 10656 -#define S_ELEMENTAL 10658 -#define S_TRIBAL 10660 - -#define S_LEARN_DRAGON 10657 -#define S_LEARN_ELEMENTAL 10659 -#define S_LEARN_TRIBAL 10661 - -#define S_UNLEARN_DRAGON 36434 -#define S_UNLEARN_ELEMENTAL 36328 -#define S_UNLEARN_TRIBAL 36433 - -#define S_GOBLIN 20222 -#define S_GNOMISH 20219 - -#define S_LEARN_GOBLIN 20221 -#define S_LEARN_GNOMISH 20220 - -#define S_SPELLFIRE 26797 -#define S_MOONCLOTH 26798 -#define S_SHADOWEAVE 26801 - -#define S_LEARN_SPELLFIRE 26796 -#define S_LEARN_MOONCLOTH 26799 -#define S_LEARN_SHADOWEAVE 26800 - -#define S_UNLEARN_SPELLFIRE 41299 -#define S_UNLEARN_MOONCLOTH 41558 -#define S_UNLEARN_SHADOWEAVE 41559 - -#define S_TRANSMUTE 28672 -#define S_ELIXIR 28677 -#define S_POTION 28675 - -#define S_LEARN_TRANSMUTE 28674 -#define S_LEARN_ELIXIR 28678 -#define S_LEARN_POTION 28676 - -#define S_UNLEARN_TRANSMUTE 41565 -#define S_UNLEARN_ELIXIR 41564 -#define S_UNLEARN_POTION 41563 - -/*### -# formulas to calculate unlearning cost -###*/ - -int32 DoLearnCost(Player* /*pPlayer*/) //tailor, alchemy -{ - return 200000; -} - -int32 DoHighUnlearnCost(Player* /*pPlayer*/) //tailor, alchemy -{ - return 1500000; -} - -int32 DoMedUnlearnCost(Player* pPlayer) //blacksmith, leatherwork -{ - uint8 level = pPlayer->getLevel(); - if (level < 51) - return 250000; - else if (level < 66) - return 500000; - else - return 1000000; -} - -int32 DoLowUnlearnCost(Player* pPlayer) //blacksmith -{ - uint8 level = pPlayer->getLevel(); - if (level < 66) - return 50000; - else - return 100000; -} - -/*### -# unlearning related profession spells -###*/ - -bool EquippedOk(Player* pPlayer, uint32 spellId) -{ - SpellEntry const* spell = GetSpellStore()->LookupEntry(spellId); - - if (!spell) - return false; - - for (uint8 i = 0; i < 3; ++i) - { - uint32 reqSpell = spell->EffectTriggerSpell[i]; - if (!reqSpell) - continue; - - Item* pItem; - for (uint8 j = EQUIPMENT_SLOT_START; j < EQUIPMENT_SLOT_END; ++j) - { - pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, j); - if (pItem) - if (pItem->GetProto()->RequiredSpell == reqSpell) - { - //player has item equipped that require specialty. Not allow to unlearn, player has to unequip first - debug_log("TSCR: player attempt to unlearn spell %u, but item %u is equipped.",reqSpell,pItem->GetProto()->ItemId); - return false; - } - } - } - return true; -} - -void ProfessionUnlearnSpells(Player* pPlayer, uint32 type) -{ - switch (type) - { - case 36436: // S_UNLEARN_WEAPON - pPlayer->removeSpell(36125); // Light Earthforged Blade - pPlayer->removeSpell(36128); // Light Emberforged Hammer - pPlayer->removeSpell(36126); // Light Skyforged Axe - break; - case 36435: // S_UNLEARN_ARMOR - pPlayer->removeSpell(36122); // Earthforged Leggings - pPlayer->removeSpell(36129); // Heavy Earthforged Breastplate - pPlayer->removeSpell(36130); // Stormforged Hauberk - pPlayer->removeSpell(34533); // Breastplate of Kings - pPlayer->removeSpell(34529); // Nether Chain Shirt - pPlayer->removeSpell(34534); // Bulwark of Kings - pPlayer->removeSpell(36257); // Bulwark of the Ancient Kings - pPlayer->removeSpell(36256); // Embrace of the Twisting Nether - pPlayer->removeSpell(34530); // Twisting Nether Chain Shirt - pPlayer->removeSpell(36124); // Windforged Leggings - break; - case 36441: // S_UNLEARN_HAMMER - pPlayer->removeSpell(36262); // Dragonstrike - pPlayer->removeSpell(34546); // Dragonmaw - pPlayer->removeSpell(34545); // Drakefist Hammer - pPlayer->removeSpell(36136); // Lavaforged Warhammer - pPlayer->removeSpell(34547); // Thunder - pPlayer->removeSpell(34567); // Deep Thunder - pPlayer->removeSpell(36263); // Stormherald - pPlayer->removeSpell(36137); // Great Earthforged Hammer - break; - case 36439: // S_UNLEARN_AXE - pPlayer->removeSpell(36260); // Wicked Edge of the Planes - pPlayer->removeSpell(34562); // Black Planar Edge - pPlayer->removeSpell(34541); // The Planar Edge - pPlayer->removeSpell(36134); // Stormforged Axe - pPlayer->removeSpell(36135); // Skyforged Great Axe - pPlayer->removeSpell(36261); // Bloodmoon - pPlayer->removeSpell(34543); // Lunar Crescent - pPlayer->removeSpell(34544); // Mooncleaver - break; - case 36438: // S_UNLEARN_SWORD - pPlayer->removeSpell(36258); // Blazefury - pPlayer->removeSpell(34537); // Blazeguard - pPlayer->removeSpell(34535); // Fireguard - pPlayer->removeSpell(36131); // Windforged Rapier - pPlayer->removeSpell(36133); // Stoneforged Claymore - pPlayer->removeSpell(34538); // Lionheart Blade - pPlayer->removeSpell(34540); // Lionheart Champion - pPlayer->removeSpell(36259); // Lionheart Executioner - break; - case 36434: // S_UNLEARN_DRAGON - pPlayer->removeSpell(36076); // Dragonstrike Leggings - pPlayer->removeSpell(36079); // Golden Dragonstrike Breastplate - pPlayer->removeSpell(35576); // Ebon Netherscale Belt - pPlayer->removeSpell(35577); // Ebon Netherscale Bracers - pPlayer->removeSpell(35575); // Ebon Netherscale Breastplate - pPlayer->removeSpell(35582); // Netherstrike Belt - pPlayer->removeSpell(35584); // Netherstrike Bracers - pPlayer->removeSpell(35580); // Netherstrike Breastplate - break; - case 36328: // S_UNLEARN_ELEMENTAL - pPlayer->removeSpell(36074); // Blackstorm Leggings - pPlayer->removeSpell(36077); // Primalstorm Breastplate - pPlayer->removeSpell(35590); // Primalstrike Belt - pPlayer->removeSpell(35591); // Primalstrike Bracers - pPlayer->removeSpell(35589); // Primalstrike Vest - break; - case 36433: // S_UNLEARN_TRIBAL - pPlayer->removeSpell(35585); // Windhawk Hauberk - pPlayer->removeSpell(35587); // Windhawk Belt - pPlayer->removeSpell(35588); // Windhawk Bracers - pPlayer->removeSpell(36075); // Wildfeather Leggings - pPlayer->removeSpell(36078); // Living Crystal Breastplate - break; - case 41299: // S_UNLEARN_SPELLFIRE - pPlayer->removeSpell(26752); // Spellfire Belt - pPlayer->removeSpell(26753); // Spellfire Gloves - pPlayer->removeSpell(26754); // Spellfire Robe - break; - case 41558: // S_UNLEARN_MOONCLOTH - pPlayer->removeSpell(26760); // Primal Mooncloth Belt - pPlayer->removeSpell(26761); // Primal Mooncloth Shoulders - pPlayer->removeSpell(26762); // Primal Mooncloth Robe - break; - case 41559: // S_UNLEARN_SHADOWEAVE - pPlayer->removeSpell(26756); // Frozen Shadoweave Shoulders - pPlayer->removeSpell(26757); // Frozen Shadoweave Boots - pPlayer->removeSpell(26758); // Frozen Shadoweave Robe - break; - } -} - -/*### -# start menues alchemy -###*/ - -bool HasAlchemySpell(Player* pPlayer) -{ - if (pPlayer->HasSpell(S_TRANSMUTE) || pPlayer->HasSpell(S_ELIXIR) || pPlayer->HasSpell(S_POTION)) - return true; - return false; -} - -bool GossipHello_npc_prof_alchemy(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - if (pCreature->isTrainer()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); - - uint32 eCreature = pCreature->GetEntry(); - - if (pPlayer->HasSkill(SKILL_ALCHEMY) && pPlayer->GetBaseSkillValue(SKILL_ALCHEMY) >= 350 && pPlayer->getLevel() > 67) - { - if (pPlayer->GetQuestRewardStatus(10899) || pPlayer->GetQuestRewardStatus(10902) || pPlayer->GetQuestRewardStatus(10897)) - { - switch (eCreature) - { - case 22427: //Zarevhi - if (!HasAlchemySpell(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1); - if (pPlayer->HasSpell(S_TRANSMUTE)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); - break; - case 19052: //Lorokeem - if (!HasAlchemySpell(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2); - if (pPlayer->HasSpell(S_ELIXIR)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5); - break; - case 17909: //Lauranna Thar'well - if (!HasAlchemySpell(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_POTION, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3); - if (pPlayer->HasSpell(S_POTION)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 6); - break; - } - } - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -void SendActionMenu_npc_prof_alchemy(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - case GOSSIP_ACTION_TRAIN: - pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); - break; - //Learn Alchemy - case GOSSIP_ACTION_INFO_DEF + 1: - if (!pPlayer->HasSpell(S_TRANSMUTE) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_LEARN_TRANSMUTE, true); - pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - if (!pPlayer->HasSpell(S_ELIXIR) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_LEARN_ELIXIR, true); - pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - if (!pPlayer->HasSpell(S_POTION) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_LEARN_POTION, true); - pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - //Unlearn Alchemy - case GOSSIP_ACTION_INFO_DEF + 4: - if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) - { - pCreature->CastSpell(pPlayer, S_UNLEARN_TRANSMUTE, true); - pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 5: - if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) - { - pCreature->CastSpell(pPlayer, S_UNLEARN_ELIXIR, true); - pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 6: - if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) - { - pCreature->CastSpell(pPlayer, S_UNLEARN_POTION, true); - pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } -} - -void SendConfirmLearn_npc_prof_alchemy(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction) - { - uint32 eCreature = pCreature->GetEntry(); - switch(eCreature) - { - case 22427: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 19052: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 17909: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_POTION, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - } - } -} - -void SendConfirmUnlearn_npc_prof_alchemy(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction) - { - uint32 eCreature = pCreature->GetEntry(); - switch(eCreature) - { - case 22427: //Zarevhi - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 19052: //Lorokeem - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 17909: //Lauranna Thar'well - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - } - } -} - -bool GossipSelect_npc_prof_alchemy(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - switch(uiSender) - { - case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_alchemy(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_alchemy(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_alchemy(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_alchemy(pPlayer, pCreature, uiAction); break; - } - return true; -} - -/*### -# start menues blacksmith -###*/ - -bool HasWeaponSub(Player* pPlayer) -{ - if (pPlayer->HasSpell(S_HAMMER) || pPlayer->HasSpell(S_AXE) || pPlayer->HasSpell(S_SWORD)) - return true; - return false; -} - -bool GossipHello_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - if (pCreature->isTrainer()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); - - uint32 eCreature = pCreature->GetEntry(); - //WEAPONSMITH & ARMORSMITH - if (pPlayer->GetBaseSkillValue(SKILL_BLACKSMITHING) >= 225) - { - switch (eCreature) - { - case 11145: //Myolor Sunderfury - case 11176: //Krathok Moltenfist - if (!pPlayer->HasSpell(S_ARMOR) && !pPlayer->HasSpell(S_WEAPON) && pPlayer->GetReputationRank(REP_ARMOR) >= REP_FRIENDLY) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARMOR_LEARN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - if (!pPlayer->HasSpell(S_WEAPON) && !pPlayer->HasSpell(S_ARMOR) && pPlayer->GetReputationRank(REP_WEAPON) >= REP_FRIENDLY) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEAPON_LEARN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - break; - case 11146: //Ironus Coldsteel - case 11178: //Borgosh Corebender - if (pPlayer->HasSpell(S_WEAPON)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEAPON_UNLEARN, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 3); - break; - case 5164: //Grumnus Steelshaper - case 11177: //Okothos Ironrager - if (pPlayer->HasSpell(S_ARMOR)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARMOR_UNLEARN, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); - break; - } - } - //WEAPONSMITH SPEC - if (pPlayer->HasSpell(S_WEAPON) && pPlayer->getLevel() > 49 && pPlayer->GetBaseSkillValue(SKILL_BLACKSMITHING) >= 250) - { - switch (eCreature) - { - case 11191: //Lilith the Lithe - if (!HasWeaponSub(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_HAMMER, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 5); - if (pPlayer->HasSpell(S_HAMMER)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_HAMMER, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 8); - break; - case 11192: //Kilram - if (!HasWeaponSub(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_AXE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 6); - if (pPlayer->HasSpell(S_AXE)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_AXE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 9); - break; - case 11193: //Seril Scourgebane - if (!HasWeaponSub(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SWORD, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 7); - if (pPlayer->HasSpell(S_SWORD)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_SWORD, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 10); - break; - } - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -void SendActionMenu_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - case GOSSIP_ACTION_TRAIN: - pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); - break; - //Learn Armor/Weapon - case GOSSIP_ACTION_INFO_DEF + 1: - if (!pPlayer->HasSpell(S_ARMOR)) - { - pPlayer->CastSpell(pPlayer, S_LEARN_ARMOR, true); - //_Creature->CastSpell(pPlayer, S_REP_ARMOR, true); - } - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - if (!pPlayer->HasSpell(S_WEAPON)) - { - pPlayer->CastSpell(pPlayer, S_LEARN_WEAPON, true); - //_Creature->CastSpell(pPlayer, S_REP_WEAPON, true); - } - pPlayer->CLOSE_GOSSIP_MENU(); - break; - //Unlearn Armor/Weapon - case GOSSIP_ACTION_INFO_DEF + 3: - if (HasWeaponSub(pPlayer)) - { - //unknown textID (TALK_MUST_UNLEARN_WEAPON) - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - } - else if (EquippedOk(pPlayer,S_UNLEARN_WEAPON)) - { - if (pPlayer->GetMoney() >= DoLowUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_WEAPON, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_WEAPON); - pPlayer->ModifyMoney(-DoLowUnlearnCost(pPlayer)); - pCreature->CastSpell(pPlayer, S_REP_ARMOR, true); - pPlayer->CLOSE_GOSSIP_MENU(); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } - else - { - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - } - break; - case GOSSIP_ACTION_INFO_DEF + 4: - if (EquippedOk(pPlayer,S_UNLEARN_ARMOR)) - { - if (pPlayer->GetMoney() >= DoLowUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_ARMOR, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_ARMOR); - pPlayer->ModifyMoney(-DoLowUnlearnCost(pPlayer)); - pCreature->CastSpell(pPlayer, S_REP_WEAPON, true); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - //Learn Hammer/Axe/Sword - case GOSSIP_ACTION_INFO_DEF + 5: - pPlayer->CastSpell(pPlayer, S_LEARN_HAMMER, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 6: - pPlayer->CastSpell(pPlayer, S_LEARN_AXE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 7: - pPlayer->CastSpell(pPlayer, S_LEARN_SWORD, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - //Unlearn Hammer/Axe/Sword - case GOSSIP_ACTION_INFO_DEF + 8: - if (EquippedOk(pPlayer,S_UNLEARN_HAMMER)) - { - if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_HAMMER, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_HAMMER); - pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 9: - if (EquippedOk(pPlayer,S_UNLEARN_AXE)) - { - if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_AXE, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_AXE); - pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 10: - if (EquippedOk(pPlayer,S_UNLEARN_SWORD)) - { - if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_SWORD, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_SWORD); - pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } -} - -void SendConfirmLearn_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction) - { - uint32 eCreature = pCreature->GetEntry(); - switch(eCreature) - { - case 11191: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_HAMMER, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID (TALK_HAMMER_LEARN) - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 11192: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_AXE, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID (TALK_AXE_LEARN) - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 11193: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SWORD, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID (TALK_SWORD_LEARN) - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - } - } -} - -void SendConfirmUnlearn_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction) - { - uint32 eCreature = pCreature->GetEntry(); - switch(eCreature) - { - case 11146: //Ironus Coldsteel - case 11178: //Borgosh Corebender - case 5164: //Grumnus Steelshaper - case 11177: //Okothos Ironrager - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SMITH_SPEC, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_ARMORORWEAPON, DoLowUnlearnCost(pPlayer),false); - //unknown textID (TALK_UNLEARN_AXEORWEAPON) - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - - case 11191: - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_HAMMER, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(pPlayer),false); - //unknown textID (TALK_HAMMER_UNLEARN) - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 11192: - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_AXE, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(pPlayer),false); - //unknown textID (TALK_AXE_UNLEARN) - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 11193: - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SWORD, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(pPlayer),false); - //unknown textID (TALK_SWORD_UNLEARN) - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - } - } -} - -bool GossipSelect_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - switch(uiSender) - { - case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_blacksmith(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_blacksmith(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_blacksmith(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_blacksmith(pPlayer, pCreature, uiAction); break; - } - return true; -} - -/*bool QuestComplete_npc_prof_blacksmith(Player* pPlayer, Creature* pCreature, Quest const *_Quest) -{ - if ((_Quest->GetQuestId() == 5283) || (_Quest->GetQuestId() == 5301)) //armorsmith - pCreature->CastSpell(pPlayer, 17451, true); - - if ((_Quest->GetQuestId() == 5284) || (_Quest->GetQuestId() == 5302)) //weaponsmith - pCreature->CastSpell(pPlayer, 17452, true); - - return true; -}*/ - -/*### -# engineering trinkets -###*/ - -enum eEngineeringTrinkets -{ - NPC_ZAP = 14742, - NPC_JHORDY = 14743, - NPC_KABLAM = 21493, - NPC_SMILES = 21494, - - SPELL_LEARN_TO_EVERLOOK = 23490, - SPELL_LEARN_TO_GADGET = 23491, - SPELL_LEARN_TO_AREA52 = 36956, - SPELL_LEARN_TO_TOSHLEY = 36957, - - SPELL_TO_EVERLOOK = 23486, - SPELL_TO_GADGET = 23489, - SPELL_TO_AREA52 = 36954, - SPELL_TO_TOSHLEY = 36955, - - ITEM_GNOMISH_CARD = 10790, - ITEM_GOBLIN_CARD = 10791 -}; - -#define GOSSIP_ITEM_ZAP "[PH] Unknown" -#define GOSSIP_ITEM_JHORDY "I must build a beacon for this marvelous device!" -#define GOSSIP_ITEM_KABLAM "[PH] Unknown" -#define GOSSIP_ITEM_SMILES "[PH] Unknown" - -bool GossipHello_npc_engineering_tele_trinket(Player* pPlayer, Creature* pCreature) -{ - uint32 NpcTextId = 0; - std::string GossipItem; - bool CanLearn = false; - - if (pPlayer->HasSkill(SKILL_ENGINERING)) - { - switch(pCreature->GetEntry()) - { - case NPC_ZAP: - NpcTextId = 7249; - if (pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 260 && pPlayer->HasSpell(S_GOBLIN)) - { - if (!pPlayer->HasSpell(SPELL_TO_EVERLOOK)) - { - CanLearn = true; - GossipItem = GOSSIP_ITEM_ZAP; - } - else if (pPlayer->HasSpell(SPELL_TO_EVERLOOK)) - NpcTextId = 0; - } - break; - case NPC_JHORDY: - NpcTextId = 7251; - if (pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 260 && pPlayer->HasSpell(S_GNOMISH)) - { - if (!pPlayer->HasSpell(SPELL_TO_GADGET)) - { - CanLearn = true; - GossipItem = GOSSIP_ITEM_JHORDY; - } - else if (pPlayer->HasSpell(SPELL_TO_GADGET)) - NpcTextId = 7252; - } - break; - case NPC_KABLAM: - NpcTextId = 10365; - if (pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 350 && pPlayer->HasSpell(S_GOBLIN)) - { - if (!pPlayer->HasSpell(SPELL_TO_AREA52)) - { - CanLearn = true; - GossipItem = GOSSIP_ITEM_KABLAM; - } - else if (pPlayer->HasSpell(SPELL_TO_AREA52)) - NpcTextId = 0; - } - break; - case NPC_SMILES: - NpcTextId = 10363; - if (pPlayer->GetBaseSkillValue(SKILL_ENGINERING) >= 350 && pPlayer->HasSpell(S_GNOMISH)) - { - if (!pPlayer->HasSpell(SPELL_TO_TOSHLEY)) - { - CanLearn = true; - GossipItem = GOSSIP_ITEM_SMILES; - } - else if (pPlayer->HasSpell(SPELL_TO_TOSHLEY)) - NpcTextId = 0; - } - break; - } - } - - if (CanLearn) - { - if (pPlayer->HasItemCount(ITEM_GOBLIN_CARD,1) || pPlayer->HasItemCount(ITEM_GNOMISH_CARD,1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GossipItem, pCreature->GetEntry(), GOSSIP_ACTION_INFO_DEF+1); - } - - pPlayer->SEND_GOSSIP_MENU(NpcTextId ? NpcTextId : pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_engineering_tele_trinket(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - pPlayer->CLOSE_GOSSIP_MENU(); - - if (uiSender != pCreature->GetEntry()) - return true; - - switch(uiSender) - { - case NPC_ZAP: - pPlayer->CastSpell(pPlayer, SPELL_LEARN_TO_EVERLOOK, false); - break; - case NPC_JHORDY: - pPlayer->CastSpell(pPlayer, SPELL_LEARN_TO_GADGET, false); - break; - case NPC_KABLAM: - pPlayer->CastSpell(pPlayer, SPELL_LEARN_TO_AREA52, false); - break; - case NPC_SMILES: - pPlayer->CastSpell(pPlayer, SPELL_LEARN_TO_TOSHLEY, false); - break; - } - - return true; -} - -/*### -# start menues leatherworking -###*/ - -bool GossipHello_npc_prof_leather(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - if (pCreature->isTrainer()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); - - uint32 eCreature = pCreature->GetEntry(); - - if (pPlayer->HasSkill(SKILL_LEATHERWORKING) && pPlayer->GetBaseSkillValue(SKILL_LEATHERWORKING) >= 250 && pPlayer->getLevel() > 49) - { - switch (eCreature) - { - case 7866: //Peter Galen - case 7867: //Thorkaf Dragoneye - if (pPlayer->HasSpell(S_DRAGON)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_DRAGON, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 1); - break; - case 7868: //Sarah Tanner - case 7869: //Brumn Winterhoof - if (pPlayer->HasSpell(S_ELEMENTAL)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_ELEMENTAL, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 2); - break; - case 7870: //Caryssia Moonhunter - case 7871: //Se'Jib - if (pPlayer->HasSpell(S_TRIBAL)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_TRIBAL, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 3); - break; - } - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -void SendActionMenu_npc_prof_leather(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - case GOSSIP_ACTION_TRAIN: - pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); - break; - //Unlearn Leather - case GOSSIP_ACTION_INFO_DEF + 1: - if (EquippedOk(pPlayer,S_UNLEARN_DRAGON)) - { - if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_DRAGON, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_DRAGON); - pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - if (EquippedOk(pPlayer,S_UNLEARN_ELEMENTAL)) - { - if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_ELEMENTAL, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_ELEMENTAL); - pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - if (EquippedOk(pPlayer,S_UNLEARN_TRIBAL)) - { - if (pPlayer->GetMoney() >= DoMedUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_TRIBAL, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_TRIBAL); - pPlayer->ModifyMoney(-DoMedUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } -} - -void SendConfirmUnlearn_npc_prof_leather(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction) - { - uint32 eCreature = pCreature->GetEntry(); - switch(eCreature) - { - case 7866: //Peter Galen - case 7867: //Thorkaf Dragoneye - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_DRAGON, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 7868: //Sarah Tanner - case 7869: //Brumn Winterhoof - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_ELEMENTAL, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 7870: //Caryssia Moonhunter - case 7871: //Se'Jib - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_TRIBAL, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - } - } -} - -bool GossipSelect_npc_prof_leather(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - switch(uiSender) - { - case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_leather(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_leather(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_leather(pPlayer, pCreature, uiAction); break; - } - return true; -} - -/*### -# start menues tailoring -###*/ - -bool HasTailorSpell(Player* pPlayer) -{ - if (pPlayer->HasSpell(S_MOONCLOTH) || pPlayer->HasSpell(S_SHADOWEAVE) || pPlayer->HasSpell(S_SPELLFIRE)) - return true; - return false; -} - -bool GossipHello_npc_prof_tailor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - if (pCreature->isTrainer()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); - - uint32 eCreature = pCreature->GetEntry(); - //TAILORING SPEC - if (pPlayer->HasSkill(SKILL_TAILORING) && pPlayer->GetBaseSkillValue(SKILL_TAILORING) >= 350 && pPlayer->getLevel() > 59) - { - if (pPlayer->GetQuestRewardStatus(10831) || pPlayer->GetQuestRewardStatus(10832) || pPlayer->GetQuestRewardStatus(10833)) - { - switch (eCreature) - { - case 22213: //Gidge Spellweaver - if (!HasTailorSpell(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SPELLFIRE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1); - if (pPlayer->HasSpell(S_SPELLFIRE)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_SPELLFIRE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); - break; - case 22208: //Nasmara Moonsong - if (!HasTailorSpell(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_MOONCLOTH, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2); - if (pPlayer->HasSpell(S_MOONCLOTH)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_MOONCLOTH, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5); - break; - case 22212: //Andrion Darkspinner - if (!HasTailorSpell(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SHADOWEAVE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3); - if (pPlayer->HasSpell(S_SHADOWEAVE)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_SHADOWEAVE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 6); - break; - } - } - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -void SendActionMenu_npc_prof_tailor(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - case GOSSIP_ACTION_TRAIN: - pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); - break; - //Learn Tailor - case GOSSIP_ACTION_INFO_DEF + 1: - if (!pPlayer->HasSpell(S_SPELLFIRE) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_LEARN_SPELLFIRE, true); - pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - if (!pPlayer->HasSpell(S_MOONCLOTH) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_LEARN_MOONCLOTH, true); - pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - if (!pPlayer->HasSpell(S_SHADOWEAVE) && pPlayer->GetMoney() >= DoLearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_LEARN_SHADOWEAVE, true); - pPlayer->ModifyMoney(-DoLearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - //Unlearn Tailor - case GOSSIP_ACTION_INFO_DEF + 4: - if (EquippedOk(pPlayer,S_UNLEARN_SPELLFIRE)) - { - if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_SPELLFIRE, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_SPELLFIRE); - pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 5: - if (EquippedOk(pPlayer,S_UNLEARN_MOONCLOTH)) - { - if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_MOONCLOTH, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_MOONCLOTH); - pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - case GOSSIP_ACTION_INFO_DEF + 6: - if (EquippedOk(pPlayer,S_UNLEARN_SHADOWEAVE)) - { - if (pPlayer->GetMoney() >= DoHighUnlearnCost(pPlayer)) - { - pPlayer->CastSpell(pPlayer, S_UNLEARN_SHADOWEAVE, true); - ProfessionUnlearnSpells(pPlayer, S_UNLEARN_SHADOWEAVE); - pPlayer->ModifyMoney(-DoHighUnlearnCost(pPlayer)); - } else - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, 0, 0); - } else - pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW,NULL,NULL); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } -} - -void SendConfirmLearn_npc_prof_tailor(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction) - { - uint32 eCreature = pCreature->GetEntry(); - switch(eCreature) - { - case 22213: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SPELLFIRE, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 22208: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_MOONCLOTH, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 22212: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SHADOWEAVE, GOSSIP_SENDER_CHECK, uiAction); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - } - } -} - -void SendConfirmUnlearn_npc_prof_tailor(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction) - { - uint32 eCreature = pCreature->GetEntry(); - switch(eCreature) - { - case 22213: //Gidge Spellweaver - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SPELLFIRE, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 22208: //Nasmara Moonsong - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_MOONCLOTH, GOSSIP_SENDER_CHECK, uiAction, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - case 22212: //Andrion Darkspinner - pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SHADOWEAVE, GOSSIP_SENDER_CHECK, uiAction,BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(pPlayer),false); - //unknown textID () - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - break; - } - } -} - -bool GossipSelect_npc_prof_tailor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - switch(uiSender) - { - case GOSSIP_SENDER_MAIN: SendActionMenu_npc_prof_tailor(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_LEARN: SendConfirmLearn_npc_prof_tailor(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_UNLEARN: SendConfirmUnlearn_npc_prof_tailor(pPlayer, pCreature, uiAction); break; - case GOSSIP_SENDER_CHECK: SendActionMenu_npc_prof_tailor(pPlayer, pCreature, uiAction); break; - } - return true; -} - -/*### -# start menues for GO (engineering and leatherworking) -###*/ - -/*bool GOHello_go_soothsaying_for_dummies(Player* pPlayer, GameObject* pGo) -{ - pPlayer->PlayerTalkClass->GetGossipMenu()->AddMenuItem(0,GOSSIP_LEARN_DRAGON, GOSSIP_SENDER_INFO, GOSSIP_ACTION_INFO_DEF, "", 0); - - pPlayer->SEND_GOSSIP_MENU(5584, pGo->GetGUID()); - - return true; -}*/ - -/*### -# -###*/ - -void AddSC_npc_professions() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_prof_alchemy"; - newscript->pGossipHello = &GossipHello_npc_prof_alchemy; - newscript->pGossipSelect = &GossipSelect_npc_prof_alchemy; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_prof_blacksmith"; - newscript->pGossipHello = &GossipHello_npc_prof_blacksmith; - newscript->pGossipSelect = &GossipSelect_npc_prof_blacksmith; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_engineering_tele_trinket"; - newscript->pGossipHello = &GossipHello_npc_engineering_tele_trinket; - newscript->pGossipSelect = &GossipSelect_npc_engineering_tele_trinket; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_prof_leather"; - newscript->pGossipHello = &GossipHello_npc_prof_leather; - newscript->pGossipSelect = &GossipSelect_npc_prof_leather; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_prof_tailor"; - newscript->pGossipHello = &GossipHello_npc_prof_tailor; - newscript->pGossipSelect = &GossipSelect_npc_prof_tailor; - newscript->RegisterSelf(); - - /*newscript = new Script; - newscript->Name = "go_soothsaying_for_dummies"; - newscript->pGOHello = &GOHello_go_soothsaying_for_dummies; - //newscript->pGossipSelect = &GossipSelect_go_soothsaying_for_dummies; - newscript->RegisterSelf();*/ -} - diff --git a/src/server/scripts/world/npc_taxi.cpp b/src/server/scripts/world/npc_taxi.cpp deleted file mode 100644 index 2a8efd4e0cb..00000000000 --- a/src/server/scripts/world/npc_taxi.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Npc_Taxi -SD%Complete: 0% -SDComment: To be used for taxi NPCs that are located globally. -SDCategory: NPCs -EndScriptData -*/ - -#include "ScriptedPch.h" - -#define GOSSIP_SUSURRUS "I am ready." -#define GOSSIP_NETHER_DRAKE "I'm ready to fly! Take me up, dragon!" -#define GOSSIP_BRAZEN "I am ready to go to Durnholde Keep." -#define GOSSIP_IRONWING "I'd like to take a flight around Stormwind Harbor." -#define GOSSIP_DABIREE1 "Fly me to Murketh and Shaadraz Gateways" -#define GOSSIP_DABIREE2 "Fly me to Shatter Point" -#define GOSSIP_WINDBELLOW1 "Fly me to The Abyssal Shelf" -#define GOSSIP_WINDBELLOW2 "Fly me to Honor Point" -#define GOSSIP_BRACK1 "Fly me to Murketh and Shaadraz Gateways" -#define GOSSIP_BRACK2 "Fly me to The Abyssal Shelf" -#define GOSSIP_BRACK3 "Fly me to Spinebreaker Post" -#define GOSSIP_IRENA "Fly me to Skettis please" -#define GOSSIP_CLOUDBREAKER1 "Speaking of uiAction, I've been ordered to undertake an air strike." -#define GOSSIP_CLOUDBREAKER2 "I need to intercept the Dawnblade reinforcements." -#define GOSSIP_DRAGONHAWK "" -#define GOSSIP_VERONIA "Fly me to Manaforge Coruu please" -#define GOSSIP_DEESAK "Fly me to Ogri'la please" -#define GOSSIP_AFRASASTRASZ1 "I would like to take a flight to the ground, Lord Of Afrasastrasz." -#define GOSSIP_AFRASASTRASZ2 "My Lord, I must go to the upper floor of the temple." -#define GOSSIP_TARIOLSTRASZ1 "My Lord, I must go to the upper floor of the temple." -#define GOSSIP_TARIOLSTRASZ2 "Can you spare a drake to travel to Lord Of Afrasastrasz, in the middle of the temple?" -#define GOSSIP_TORASTRASZA1 "I would like to see Lord Of Afrasastrasz, in the middle of the temple." -#define GOSSIP_TORASTRASZA2 "Yes, Please. I would like to return to the ground floor of the temple." -#define GOSSIP_CAMILLE1 "I need to fly to the Windrunner Official business!" -#define GOSSIP_CAMILLE2 "" -#define GOSSIP_CRIMSONWING "" -#define GOSSIP_THRICESTAR1 "Do you think I could take a ride on one of those flying machines?" -#define GOSSIP_THRICESTAR2 "Kara, I need to be flown out the Dens of Dying to find Bixie." -#define GOSSIP_WILLIAMKEILAR1 "Take me to Northpass Tower." -#define GOSSIP_WILLIAMKEILAR2 "Take me to Eastwall Tower." -#define GOSSIP_WILLIAMKEILAR3 "Take me to Crown Guard Tower." - -bool GossipHello_npc_taxi(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - switch(pCreature->GetEntry()) { - case 17435: // Azuremyst Isle - Susurrus - if (pPlayer->HasItemCount(23843,1,true)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SUSURRUS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - break; - case 20903: // Netherstorm - Protectorate Nether Drake - if (pPlayer->GetQuestStatus(10438) == QUEST_STATUS_INCOMPLETE && pPlayer->HasItemCount(29778,1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_NETHER_DRAKE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - break; - case 18725: // Old Hillsbrad Foothills - Brazen - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRAZEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - break; - case 29154: // Stormwind City - Thargold Ironwing - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_IRONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - break; - case 19409: // Hellfire Peninsula - Wing Commander Dabir'ee - //Mission: The Murketh and Shaadraz Gateways - if (pPlayer->GetQuestStatus(10146) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DABIREE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - - //Shatter Point - if (!pPlayer->GetQuestRewardStatus(10340)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DABIREE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - break; - case 20235: // Hellfire Peninsula - Gryphoneer Windbellow - //Mission: The Abyssal Shelf || Return to the Abyssal Shelf - if (pPlayer->GetQuestStatus(10163) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10346) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WINDBELLOW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - - //Go to the Front - if (pPlayer->GetQuestStatus(10382) != QUEST_STATUS_NONE && !pPlayer->GetQuestRewardStatus(10382)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WINDBELLOW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - break; - case 19401: // Hellfire Peninsula - Wing Commander Brack - //Mission: The Murketh and Shaadraz Gateways - if (pPlayer->GetQuestStatus(10129) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); - - //Mission: The Abyssal Shelf || Return to the Abyssal Shelf - if (pPlayer->GetQuestStatus(10162) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(10347) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); - - //Spinebreaker Post - if (pPlayer->GetQuestStatus(10242) == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(10242)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); - break; - case 23413: // Blade's Edge Mountains - Skyguard Handler Irena - if (pPlayer->GetReputationRank(1031) >= REP_HONORED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_IRENA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - break; - case 25059: // Isle of Quel'Danas - Ayren Cloudbreaker - if (pPlayer->GetQuestStatus(11532) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(11533) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); - - if (pPlayer->GetQuestStatus(11542) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(11543) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); - break; - case 25236: // Isle of Quel'Danas - Unrestrained Dragonhawk - if (pPlayer->GetQuestStatus(11542) == QUEST_STATUS_COMPLETE || pPlayer->GetQuestStatus(11543) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DRAGONHAWK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); - break; - case 20162: // Netherstorm - Veronia - //Behind Enemy Lines - if (pPlayer->GetQuestStatus(10652) && !pPlayer->GetQuestRewardStatus(10652)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VERONIA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15); - break; - case 23415: // Terokkar Forest - Skyguard Handler Deesak - if (pPlayer->GetReputationRank(1031) >= REP_HONORED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEESAK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 16); - break; - case 27575: // Dragonblight - Lord Afrasastrasz - // middle -> ground - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AFRASASTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 17); - // middle -> top - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_AFRASASTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 18); - break; - case 26443: // Dragonblight - Tariolstrasz //need to check if quests are required before gossip available (12123, 12124) - // ground -> top - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TARIOLSTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 19); - // ground -> middle - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TARIOLSTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 20); - break; - case 26949: // Dragonblight - Torastrasza - // top -> middle - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); - // top -> ground - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TORASTRASZA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); - break; - case 23816: // Howling Fjord - Bat Handler Camille - if (!pPlayer->GetQuestRewardStatus(11229)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CAMILLE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23); - if (pPlayer->GetQuestStatus(11170) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CAMILLE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24); - break; - case 23704: // Dustwallow Marsh - Cassa Crimsonwing - if (pPlayer->GetQuestStatus(11142) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CRIMSONWING,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+25); - break; - case 26602: - if (pCreature->isTaxi()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TAXI, GOSSIP_THRICESTAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26); - if (pPlayer->GetQuestStatus(11692) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_THRICESTAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 27); - break; - case 17209: - pPlayer->SetTaxiCheater(true); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 28); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 29); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WILLIAMKEILAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 30); - break; - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_taxi(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) { - case GOSSIP_ACTION_INFO_DEF: - //spellId is correct, however it gives flight a somewhat funny effect //TaxiPath 506. - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,32474,true); - break; - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(627); //TaxiPath 627 (possibly 627+628(152->153->154->155)) - break; - case GOSSIP_ACTION_INFO_DEF + 2: - if (!pPlayer->HasItemCount(25853,1)) { - pPlayer->SEND_GOSSIP_MENU(9780, pCreature->GetGUID()); - } else { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(534); //TaxiPath 534 - } - break; - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,53335,true); //TaxiPath 1041 (Stormwind Harbor) - break; - case GOSSIP_ACTION_INFO_DEF + 4: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,33768,true); //TaxiPath 585 (Gateways Murket and Shaadraz) - break; - case GOSSIP_ACTION_INFO_DEF + 5: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,35069,true); //TaxiPath 612 (Taxi - Hellfire Peninsula - Expedition Point to Shatter Point) - break; - case GOSSIP_ACTION_INFO_DEF + 6: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,33899,true); //TaxiPath 589 (Aerial Assault Flight (Alliance)) - break; - case GOSSIP_ACTION_INFO_DEF + 7: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,35065,true); //TaxiPath 607 (Taxi - Hellfire Peninsula - Shatter Point to Beach Head) - break; - case GOSSIP_ACTION_INFO_DEF + 8: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,33659,true); //TaxiPath 584 (Gateways Murket and Shaadraz) - break; - case GOSSIP_ACTION_INFO_DEF + 9: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,33825,true); //TaxiPath 587 (Aerial Assault Flight (Horde)) - break; - case GOSSIP_ACTION_INFO_DEF + 10: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,34578,true); //TaxiPath 604 (Taxi - Reaver's Fall to Spinebreaker Ridge) - break; - case GOSSIP_ACTION_INFO_DEF + 11: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,41278,true); //TaxiPath 706 - break; - case GOSSIP_ACTION_INFO_DEF + 12: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,45071,true); //TaxiPath 779 - break; - case GOSSIP_ACTION_INFO_DEF + 13: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,45113,true); //TaxiPath 784 - break; - case GOSSIP_ACTION_INFO_DEF + 14: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,45353,true); //TaxiPath 788 - break; - case GOSSIP_ACTION_INFO_DEF + 15: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,34905,true); //TaxiPath 606 - break; - case GOSSIP_ACTION_INFO_DEF + 16: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,41279,true); //TaxiPath 705 (Taxi - Skettis to Skyguard Outpost) - break; - case GOSSIP_ACTION_INFO_DEF + 17: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(882); - break; - case GOSSIP_ACTION_INFO_DEF + 18: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(881); - break; - case GOSSIP_ACTION_INFO_DEF + 19: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(878); - break; - case GOSSIP_ACTION_INFO_DEF + 20: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(883); - break; - case GOSSIP_ACTION_INFO_DEF + 21: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(880); - break; - case GOSSIP_ACTION_INFO_DEF + 22: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(879); - break; - case GOSSIP_ACTION_INFO_DEF + 23: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,43074,true); //TaxiPath 736 - break; - case GOSSIP_ACTION_INFO_DEF + 24: - pPlayer->CLOSE_GOSSIP_MENU(); - //pPlayer->ActivateTaxiPathTo(738); - pPlayer->CastSpell(pPlayer, 43136, false); - break; - case GOSSIP_ACTION_INFO_DEF + 25: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,42295,true); - break; - case GOSSIP_ACTION_INFO_DEF + 26: - pPlayer->GetSession()->SendTaxiMenu(pCreature); - break; - case GOSSIP_ACTION_INFO_DEF + 27: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, 51446, false); - break; - case GOSSIP_ACTION_INFO_DEF + 28: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(494); - break; - case GOSSIP_ACTION_INFO_DEF + 29: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(495); - break; - case GOSSIP_ACTION_INFO_DEF + 30: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->ActivateTaxiPathTo(496); - break; - } - - return true; -} - -void AddSC_npc_taxi() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_taxi"; - newscript->pGossipHello = &GossipHello_npc_taxi; - newscript->pGossipSelect = &GossipSelect_npc_taxi; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/world/npcs_special.cpp b/src/server/scripts/world/npcs_special.cpp deleted file mode 100644 index cfd1b7698fc..00000000000 --- a/src/server/scripts/world/npcs_special.cpp +++ /dev/null @@ -1,2600 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Npcs_Special -SD%Complete: 100 -SDComment: To be used for special NPCs that are located globally. -SDCategory: NPCs -EndScriptData -*/ - -/* ContentData -npc_air_force_bots 80% support for misc (invisible) guard bots in areas where player allowed to fly. Summon guards after a preset time if tagged by spell -npc_lunaclaw_spirit 80% support for quests 6001/6002 (Body and Heart) -npc_chicken_cluck 100% support for quest 3861 (Cluck!) -npc_dancing_flames 100% midsummer event NPC -npc_guardian 100% guardianAI used to prevent players from accessing off-limits areas. Not in use by SD2 -npc_garments_of_quests 80% NPC's related to all Garments of-quests 5621, 5624, 5625, 5648, 565 -npc_injured_patient 100% patients for triage-quests (6622 and 6624) -npc_doctor 100% Gustaf Vanhowzen and Gregory Victor, quest 6622 and 6624 (Triage) -npc_kingdom_of_dalaran_quests Misc NPC's gossip option related to quests 12791, 12794 and 12796 -npc_mount_vendor 100% Regular mount vendors all over the world. Display gossip if player doesn't meet the requirements to buy -npc_rogue_trainer 80% Scripted trainers, so they are able to offer item 17126 for class quest 6681 -npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given -npc_snake_trap_serpents 80% AI for snakes that summoned by Snake Trap -npc_shadowfiend 100% restore 5% of owner's mana when shadowfiend die from damage -npc_locksmith 75% list of keys needs to be confirmed -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "ObjectMgr.h" -#include "ScriptMgr.h" -#include "World.h" - -/*######## -# npc_air_force_bots -#########*/ - -enum SpawnType -{ - SPAWNTYPE_TRIPWIRE_ROOFTOP, // no warning, summon Creature at smaller range - SPAWNTYPE_ALARMBOT, // cast guards mark and summon npc - if player shows up with that buff duration < 5 seconds attack -}; - -struct SpawnAssociation -{ - uint32 m_uiThisCreatureEntry; - uint32 m_uiSpawnedCreatureEntry; - SpawnType m_SpawnType; -}; - -enum eEnums -{ - SPELL_GUARDS_MARK = 38067, - AURA_DURATION_TIME_LEFT = 5000 -}; - -const float RANGE_TRIPWIRE = 15.0f; -const float RANGE_GUARDS_MARK = 50.0f; - -SpawnAssociation m_aSpawnAssociations[] = -{ - {2614, 15241, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Alliance) - {2615, 15242, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Horde) - {21974, 21976, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Area 52) - {21993, 15242, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Horde - Bat Rider) - {21996, 15241, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Alliance - Gryphon) - {21997, 21976, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Goblin - Area 52 - Zeppelin) - {21999, 15241, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Alliance) - {22001, 15242, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Horde) - {22002, 15242, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Ground (Horde) - {22003, 15241, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Ground (Alliance) - {22063, 21976, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Goblin - Area 52) - {22065, 22064, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Ethereal - Stormspire) - {22066, 22067, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Scryer - Dragonhawk) - {22068, 22064, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Ethereal - Stormspire) - {22069, 22064, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Stormspire) - {22070, 22067, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Scryer) - {22071, 22067, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Scryer) - {22078, 22077, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Aldor) - {22079, 22077, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Aldor - Gryphon) - {22080, 22077, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Aldor) - {22086, 22085, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Sporeggar) - {22087, 22085, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Sporeggar - Spore Bat) - {22088, 22085, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Sporeggar) - {22090, 22089, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Toshley's Station - Flying Machine) - {22124, 22122, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Cenarion) - {22125, 22122, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Cenarion - Stormcrow) - {22126, 22122, SPAWNTYPE_ALARMBOT} //Air Force Trip Wire - Rooftop (Cenarion Expedition) -}; - -struct npc_air_force_botsAI : public ScriptedAI -{ - npc_air_force_botsAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pSpawnAssoc = NULL; - m_uiSpawnedGUID = 0; - - // find the correct spawnhandling - static uint32 uiEntryCount = sizeof(m_aSpawnAssociations)/sizeof(SpawnAssociation); - - for (uint8 i=0; iGetEntry()) - { - m_pSpawnAssoc = &m_aSpawnAssociations[i]; - break; - } - } - - if (!m_pSpawnAssoc) - error_db_log("TCSR: Creature template entry %u has ScriptName npc_air_force_bots, but it's not handled by that script", pCreature->GetEntry()); - else - { - CreatureInfo const* spawnedTemplate = GetCreatureTemplateStore(m_pSpawnAssoc->m_uiSpawnedCreatureEntry); - - if (!spawnedTemplate) - { - m_pSpawnAssoc = NULL; - error_db_log("TCSR: Creature template entry %u does not exist in DB, which is required by npc_air_force_bots", m_pSpawnAssoc->m_uiSpawnedCreatureEntry); - return; - } - } - } - - SpawnAssociation* m_pSpawnAssoc; - uint64 m_uiSpawnedGUID; - - void Reset() {} - - Creature* SummonGuard() - { - Creature* pSummoned = me->SummonCreature(m_pSpawnAssoc->m_uiSpawnedCreatureEntry, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000); - - if (pSummoned) - m_uiSpawnedGUID = pSummoned->GetGUID(); - else - { - error_db_log("TCSR: npc_air_force_bots: wasn't able to spawn Creature %u", m_pSpawnAssoc->m_uiSpawnedCreatureEntry); - m_pSpawnAssoc = NULL; - } - - return pSummoned; - } - - Creature* GetSummonedGuard() - { - Creature* pCreature = Unit::GetCreature(*me, m_uiSpawnedGUID); - - if (pCreature && pCreature->isAlive()) - return pCreature; - - return NULL; - } - - void MoveInLineOfSight(Unit* pWho) - { - if (!m_pSpawnAssoc) - return; - - if (pWho->isTargetableForAttack() && me->IsHostileTo(pWho)) - { - Player* pPlayerTarget = pWho->GetTypeId() == TYPEID_PLAYER ? CAST_PLR(pWho) : NULL; - - // airforce guards only spawn for players - if (!pPlayerTarget) - return; - - Creature* pLastSpawnedGuard = m_uiSpawnedGUID == 0 ? NULL : GetSummonedGuard(); - - // prevent calling Unit::GetUnit at next MoveInLineOfSight call - speedup - if (!pLastSpawnedGuard) - m_uiSpawnedGUID = 0; - - switch(m_pSpawnAssoc->m_SpawnType) - { - case SPAWNTYPE_ALARMBOT: - { - if (!pWho->IsWithinDistInMap(me, RANGE_GUARDS_MARK)) - return; - - Aura* pMarkAura = pWho->GetAura(SPELL_GUARDS_MARK); - if (pMarkAura) - { - // the target wasn't able to move out of our range within 25 seconds - if (!pLastSpawnedGuard) - { - pLastSpawnedGuard = SummonGuard(); - - if (!pLastSpawnedGuard) - return; - } - - if (pMarkAura->GetDuration() < AURA_DURATION_TIME_LEFT) - { - if (!pLastSpawnedGuard->getVictim()) - pLastSpawnedGuard->AI()->AttackStart(pWho); - } - } - else - { - if (!pLastSpawnedGuard) - pLastSpawnedGuard = SummonGuard(); - - if (!pLastSpawnedGuard) - return; - - pLastSpawnedGuard->CastSpell(pWho, SPELL_GUARDS_MARK, true); - } - break; - } - case SPAWNTYPE_TRIPWIRE_ROOFTOP: - { - if (!pWho->IsWithinDistInMap(me, RANGE_TRIPWIRE)) - return; - - if (!pLastSpawnedGuard) - pLastSpawnedGuard = SummonGuard(); - - if (!pLastSpawnedGuard) - return; - - // ROOFTOP only triggers if the player is on the ground - if (!pPlayerTarget->IsFlying()) - { - if (!pLastSpawnedGuard->getVictim()) - pLastSpawnedGuard->AI()->AttackStart(pWho); - } - break; - } - } - } - } -}; - -CreatureAI* GetAI_npc_air_force_bots(Creature* pCreature) -{ - return new npc_air_force_botsAI(pCreature); -} - -/*###### -## npc_lunaclaw_spirit -######*/ - -enum -{ - QUEST_BODY_HEART_A = 6001, - QUEST_BODY_HEART_H = 6002, - - TEXT_ID_DEFAULT = 4714, - TEXT_ID_PROGRESS = 4715 -}; - -#define GOSSIP_ITEM_GRANT "You have thought well, spirit. I ask you to grant me the strength of your body and the strength of your heart." - -bool GossipHello_npc_lunaclaw_spirit(Player *pPlayer, Creature *pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_BODY_HEART_A) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_BODY_HEART_H) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GRANT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_DEFAULT, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_lunaclaw_spirit(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_PROGRESS, pCreature->GetGUID()); - pPlayer->AreaExploredOrEventHappens(pPlayer->GetTeam() == ALLIANCE ? QUEST_BODY_HEART_A : QUEST_BODY_HEART_H); - } - return true; -} - -/*######## -# npc_chicken_cluck -#########*/ - -#define EMOTE_HELLO -1070004 -#define EMOTE_CLUCK_TEXT -1070006 - -#define QUEST_CLUCK 3861 -#define FACTION_FRIENDLY 35 -#define FACTION_CHICKEN 31 - -struct npc_chicken_cluckAI : public ScriptedAI -{ - npc_chicken_cluckAI(Creature *c) : ScriptedAI(c) {} - - uint32 ResetFlagTimer; - - void Reset() - { - ResetFlagTimer = 120000; - me->setFaction(FACTION_CHICKEN); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - // Reset flags after a certain time has passed so that the next player has to start the 'event' again - if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) - { - if (ResetFlagTimer <= diff) - { - EnterEvadeMode(); - return; - } else ResetFlagTimer -= diff; - } - - if (UpdateVictim()) - DoMeleeAttackIfReady(); - } - - void ReceiveEmote(Player* pPlayer, uint32 emote) - { - switch(emote) - { - case TEXTEMOTE_CHICKEN: - if (pPlayer->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE && rand()%30 == 1) - { - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - me->setFaction(FACTION_FRIENDLY); - DoScriptText(EMOTE_HELLO, me); - } - break; - case TEXTEMOTE_CHEER: - if (pPlayer->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_COMPLETE) - { - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - me->setFaction(FACTION_FRIENDLY); - DoScriptText(EMOTE_CLUCK_TEXT, me); - } - break; - } - } -}; - -CreatureAI* GetAI_npc_chicken_cluck(Creature* pCreature) -{ - return new npc_chicken_cluckAI(pCreature); -} - -bool QuestAccept_npc_chicken_cluck(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest) -{ - if (_Quest->GetQuestId() == QUEST_CLUCK) - CAST_AI(npc_chicken_cluckAI, pCreature->AI())->Reset(); - - return true; -} - -bool QuestComplete_npc_chicken_cluck(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest) -{ - if (_Quest->GetQuestId() == QUEST_CLUCK) - CAST_AI(npc_chicken_cluckAI, pCreature->AI())->Reset(); - - return true; -} - -/*###### -## npc_dancing_flames -######*/ - -#define SPELL_BRAZIER 45423 -#define SPELL_SEDUCTION 47057 -#define SPELL_FIERY_AURA 45427 - -struct npc_dancing_flamesAI : public ScriptedAI -{ - npc_dancing_flamesAI(Creature *c) : ScriptedAI(c) {} - - bool active; - uint32 can_iteract; - - void Reset() - { - active = true; - can_iteract = 3500; - DoCast(me, SPELL_BRAZIER, true); - DoCast(me, SPELL_FIERY_AURA, false); - float x, y, z; - me->GetPosition(x,y,z); - me->Relocate(x,y,z + 0.94f); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE); - WorldPacket data; //send update position to client - me->BuildHeartBeatMsg(&data); - me->SendMessageToSet(&data,true); - } - - void UpdateAI(const uint32 diff) - { - if (!active) - { - if (can_iteract <= diff){ - active = true; - can_iteract = 3500; - me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE); - } else can_iteract -= diff; - } - } - - void EnterCombat(Unit* /*who*/){} - - void ReceiveEmote(Player* pPlayer, uint32 emote) - { - if (me->IsWithinLOS(pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ()) && me->IsWithinDistInMap(pPlayer,30.0f)) - { - me->SetInFront(pPlayer); - active = false; - - WorldPacket data; - me->BuildHeartBeatMsg(&data); - me->SendMessageToSet(&data,true); - switch(emote) - { - case TEXTEMOTE_KISS: me->HandleEmoteCommand(EMOTE_ONESHOT_SHY); break; - case TEXTEMOTE_WAVE: me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); break; - case TEXTEMOTE_BOW: me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); break; - case TEXTEMOTE_JOKE: me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); break; - case TEXTEMOTE_DANCE: - { - if (!pPlayer->HasAura(SPELL_SEDUCTION)) - DoCast(pPlayer, SPELL_SEDUCTION, true); - } - break; - } - } - } -}; - -CreatureAI* GetAI_npc_dancing_flames(Creature* pCreature) -{ - return new npc_dancing_flamesAI(pCreature); -} - -/*###### -## Triage quest -######*/ - -//signed for 9623 -#define SAY_DOC1 -1000201 -#define SAY_DOC2 -1000202 -#define SAY_DOC3 -1000203 - -#define DOCTOR_ALLIANCE 12939 -#define DOCTOR_HORDE 12920 -#define ALLIANCE_COORDS 7 -#define HORDE_COORDS 6 - -struct Location -{ - float x, y, z, o; -}; - -static Location AllianceCoords[]= -{ - {-3757.38, -4533.05, 14.16, 3.62}, // Top-far-right bunk as seen from entrance - {-3754.36, -4539.13, 14.16, 5.13}, // Top-far-left bunk - {-3749.54, -4540.25, 14.28, 3.34}, // Far-right bunk - {-3742.10, -4536.85, 14.28, 3.64}, // Right bunk near entrance - {-3755.89, -4529.07, 14.05, 0.57}, // Far-left bunk - {-3749.51, -4527.08, 14.07, 5.26}, // Mid-left bunk - {-3746.37, -4525.35, 14.16, 5.22}, // Left bunk near entrance -}; - -//alliance run to where -#define A_RUNTOX -3742.96 -#define A_RUNTOY -4531.52 -#define A_RUNTOZ 11.91 - -static Location HordeCoords[]= -{ - {-1013.75, -3492.59, 62.62, 4.34}, // Left, Behind - {-1017.72, -3490.92, 62.62, 4.34}, // Right, Behind - {-1015.77, -3497.15, 62.82, 4.34}, // Left, Mid - {-1019.51, -3495.49, 62.82, 4.34}, // Right, Mid - {-1017.25, -3500.85, 62.98, 4.34}, // Left, front - {-1020.95, -3499.21, 62.98, 4.34} // Right, Front -}; - -//horde run to where -#define H_RUNTOX -1016.44 -#define H_RUNTOY -3508.48 -#define H_RUNTOZ 62.96 - -const uint32 AllianceSoldierId[3] = -{ - 12938, // 12938 Injured Alliance Soldier - 12936, // 12936 Badly injured Alliance Soldier - 12937 // 12937 Critically injured Alliance Soldier -}; - -const uint32 HordeSoldierId[3] = -{ - 12923, //12923 Injured Soldier - 12924, //12924 Badly injured Soldier - 12925 //12925 Critically injured Soldier -}; - -/*###### -## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor) -######*/ - -struct npc_doctorAI : public ScriptedAI -{ - npc_doctorAI(Creature *c) : ScriptedAI(c) {} - - uint64 PlayerGUID; - - uint32 SummonPatient_Timer; - uint32 SummonPatientCount; - uint32 PatientDiedCount; - uint32 PatientSavedCount; - - bool Event; - - std::list Patients; - std::vector Coordinates; - - void Reset() - { - PlayerGUID = 0; - - SummonPatient_Timer = 10000; - SummonPatientCount = 0; - PatientDiedCount = 0; - PatientSavedCount = 0; - - Patients.clear(); - Coordinates.clear(); - - Event = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void BeginEvent(Player* pPlayer); - void PatientDied(Location* Point); - void PatientSaved(Creature* soldier, Player* pPlayer, Location* Point); - void UpdateAI(const uint32 diff); - - void EnterCombat(Unit* /*who*/){} -}; - -/*##### -## npc_injured_patient (handles all the patients, no matter Horde or Alliance) -#####*/ - -struct npc_injured_patientAI : public ScriptedAI -{ - npc_injured_patientAI(Creature *c) : ScriptedAI(c) {} - - uint64 Doctorguid; - Location* Coord; - - void Reset() - { - Doctorguid = 0; - Coord = NULL; - - //no select - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - //no regen health - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - - //to make them lay with face down - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); - - uint32 mobId = me->GetEntry(); - - switch (mobId) - { //lower max health - case 12923: - case 12938: //Injured Soldier - me->SetHealth(uint32(me->GetMaxHealth()*.75)); - break; - case 12924: - case 12936: //Badly injured Soldier - me->SetHealth(uint32(me->GetMaxHealth()*.50)); - break; - case 12925: - case 12937: //Critically injured Soldier - me->SetHealth(uint32(me->GetMaxHealth()*.25)); - break; - } - } - - void EnterCombat(Unit* /*who*/){} - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (caster->GetTypeId() == TYPEID_PLAYER && me->isAlive() && spell->Id == 20804) - { - if ((CAST_PLR(caster)->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (CAST_PLR(caster)->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)) - if (Doctorguid) - if (Creature* Doctor = Unit::GetCreature(*me, Doctorguid)) - CAST_AI(npc_doctorAI, Doctor->AI())->PatientSaved(me, CAST_PLR(caster), Coord); - - //make not selectable - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - //regen health - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - - //stand up - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); - - DoScriptText(RAND(SAY_DOC1,SAY_DOC2,SAY_DOC3), me); - - uint32 mobId = me->GetEntry(); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - switch (mobId) - { - case 12923: - case 12924: - case 12925: - me->GetMotionMaster()->MovePoint(0, H_RUNTOX, H_RUNTOY, H_RUNTOZ); - break; - case 12936: - case 12937: - case 12938: - me->GetMotionMaster()->MovePoint(0, A_RUNTOX, A_RUNTOY, A_RUNTOZ); - break; - } - } - } - - void UpdateAI(const uint32 /*diff*/) - { - //lower HP on every world tick makes it a useful counter, not officlone though - if (me->isAlive() && me->GetHealth() > 6) - { - me->SetHealth(uint32(me->GetHealth()-5)); - } - - if (me->isAlive() && me->GetHealth() <= 6) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setDeathState(JUST_DIED); - me->SetFlag(UNIT_DYNAMIC_FLAGS, 32); - - if (Doctorguid) - { - if (Creature* Doctor = Unit::GetCreature((*me), Doctorguid)) - CAST_AI(npc_doctorAI, Doctor->AI())->PatientDied(Coord); - } - } - } -}; - -CreatureAI* GetAI_npc_injured_patient(Creature* pCreature) -{ - return new npc_injured_patientAI (pCreature); -} - -/* -npc_doctor (continue) -*/ - -void npc_doctorAI::BeginEvent(Player* pPlayer) -{ - PlayerGUID = pPlayer->GetGUID(); - - SummonPatient_Timer = 10000; - SummonPatientCount = 0; - PatientDiedCount = 0; - PatientSavedCount = 0; - - switch(me->GetEntry()) - { - case DOCTOR_ALLIANCE: - for (uint8 i = 0; i < ALLIANCE_COORDS; ++i) - Coordinates.push_back(&AllianceCoords[i]); - break; - case DOCTOR_HORDE: - for (uint8 i = 0; i < HORDE_COORDS; ++i) - Coordinates.push_back(&HordeCoords[i]); - break; - } - - Event = true; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); -} - -void npc_doctorAI::PatientDied(Location* Point) -{ - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer && ((pPlayer->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (pPlayer->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))) - { - ++PatientDiedCount; - - if (PatientDiedCount > 5 && Event) - { - if (pPlayer->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) - pPlayer->FailQuest(6624); - else if (pPlayer->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE) - pPlayer->FailQuest(6622); - - Reset(); - return; - } - - Coordinates.push_back(Point); - } - else - // If no player or player abandon quest in progress - Reset(); -} - -void npc_doctorAI::PatientSaved(Creature* /*soldier*/, Player* pPlayer, Location* Point) -{ - if (pPlayer && PlayerGUID == pPlayer->GetGUID()) - { - if ((pPlayer->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (pPlayer->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)) - { - ++PatientSavedCount; - - if (PatientSavedCount == 15) - { - if (!Patients.empty()) - { - std::list::const_iterator itr; - for (itr = Patients.begin(); itr != Patients.end(); ++itr) - { - if (Creature* Patient = Unit::GetCreature((*me), *itr)) - Patient->setDeathState(JUST_DIED); - } - } - - if (pPlayer->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(6624); - else if (pPlayer->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(6622); - - Reset(); - return; - } - - Coordinates.push_back(Point); - } - } -} - -void npc_doctorAI::UpdateAI(const uint32 diff) -{ - if (Event && SummonPatientCount >= 20) - { - Reset(); - return; - } - - if (Event) - { - if (SummonPatient_Timer <= diff) - { - Creature* Patient = NULL; - Location* Point = NULL; - - if (Coordinates.empty()) - return; - - std::vector::iterator itr = Coordinates.begin()+rand()%Coordinates.size(); - uint32 patientEntry = 0; - - switch(me->GetEntry()) - { - case DOCTOR_ALLIANCE: patientEntry = AllianceSoldierId[rand()%3]; break; - case DOCTOR_HORDE: patientEntry = HordeSoldierId[rand()%3]; break; - default: - error_log("TSCR: Invalid entry for Triage doctor. Please check your database"); - return; - } - - Point = *itr; - - Patient = me->SummonCreature(patientEntry, Point->x, Point->y, Point->z, Point->o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - - if (Patient) - { - //303, this flag appear to be required for client side item->spell to work (TARGET_SINGLE_FRIEND) - Patient->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); - - Patients.push_back(Patient->GetGUID()); - CAST_AI(npc_injured_patientAI, Patient->AI())->Doctorguid = me->GetGUID(); - - if (Point) - CAST_AI(npc_injured_patientAI, Patient->AI())->Coord = Point; - - Coordinates.erase(itr); - } - SummonPatient_Timer = 10000; - ++SummonPatientCount; - } else SummonPatient_Timer -= diff; - } -} - -bool QuestAccept_npc_doctor(Player* pPlayer, Creature* pCreature, Quest const *quest) -{ - if ((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622)) - CAST_AI(npc_doctorAI, pCreature->AI())->BeginEvent(pPlayer); - - return true; -} - -CreatureAI* GetAI_npc_doctor(Creature* pCreature) -{ - return new npc_doctorAI (pCreature); -} - -/*###### -## npc_garments_of_quests -######*/ - -//TODO: get text for each NPC - -enum eGarments -{ - SPELL_LESSER_HEAL_R2 = 2052, - SPELL_FORTITUDE_R1 = 1243, - - QUEST_MOON = 5621, - QUEST_LIGHT_1 = 5624, - QUEST_LIGHT_2 = 5625, - QUEST_SPIRIT = 5648, - QUEST_DARKNESS = 5650, - - ENTRY_SHAYA = 12429, - ENTRY_ROBERTS = 12423, - ENTRY_DOLF = 12427, - ENTRY_KORJA = 12430, - ENTRY_DG_KEL = 12428, - - //used by 12429,12423,12427,12430,12428, but signed for 12429 - SAY_COMMON_HEALED = -1000164, - SAY_DG_KEL_THANKS = -1000165, - SAY_DG_KEL_GOODBYE = -1000166, - SAY_ROBERTS_THANKS = -1000167, - SAY_ROBERTS_GOODBYE = -1000168, - SAY_KORJA_THANKS = -1000169, - SAY_KORJA_GOODBYE = -1000170, - SAY_DOLF_THANKS = -1000171, - SAY_DOLF_GOODBYE = -1000172, - SAY_SHAYA_THANKS = -1000173, - SAY_SHAYA_GOODBYE = -1000174, //signed for 21469 -}; - -struct npc_garments_of_questsAI : public npc_escortAI -{ - npc_garments_of_questsAI(Creature *c) : npc_escortAI(c) {Reset();} - - uint64 caster; - - bool bIsHealed; - bool bCanRun; - - uint32 RunAwayTimer; - - void Reset() - { - caster = 0; - - bIsHealed = false; - bCanRun = false; - - RunAwayTimer = 5000; - - me->SetStandState(UNIT_STAND_STATE_KNEEL); - //expect database to have RegenHealth=0 - me->SetHealth(int(me->GetMaxHealth()*0.7)); - } - - void EnterCombat(Unit * /*who*/) {} - - void SpellHit(Unit* pCaster, const SpellEntry *Spell) - { - if (Spell->Id == SPELL_LESSER_HEAL_R2 || Spell->Id == SPELL_FORTITUDE_R1) - { - //not while in combat - if (me->isInCombat()) - return; - - //nothing to be done now - if (bIsHealed && bCanRun) - return; - - if (pCaster->GetTypeId() == TYPEID_PLAYER) - { - switch(me->GetEntry()) - { - case ENTRY_SHAYA: - if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_MOON) == QUEST_STATUS_INCOMPLETE) - { - if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) - { - DoScriptText(SAY_SHAYA_THANKS,me,pCaster); - bCanRun = true; - } - else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) - { - caster = pCaster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_COMMON_HEALED,me,pCaster); - bIsHealed = true; - } - } - break; - case ENTRY_ROBERTS: - if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_LIGHT_1) == QUEST_STATUS_INCOMPLETE) - { - if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) - { - DoScriptText(SAY_ROBERTS_THANKS,me,pCaster); - bCanRun = true; - } - else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) - { - caster = pCaster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_COMMON_HEALED,me,pCaster); - bIsHealed = true; - } - } - break; - case ENTRY_DOLF: - if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_LIGHT_2) == QUEST_STATUS_INCOMPLETE) - { - if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) - { - DoScriptText(SAY_DOLF_THANKS,me,pCaster); - bCanRun = true; - } - else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) - { - caster = pCaster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_COMMON_HEALED,me,pCaster); - bIsHealed = true; - } - } - break; - case ENTRY_KORJA: - if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_SPIRIT) == QUEST_STATUS_INCOMPLETE) - { - if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) - { - DoScriptText(SAY_KORJA_THANKS,me,pCaster); - bCanRun = true; - } - else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) - { - caster = pCaster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_COMMON_HEALED,me,pCaster); - bIsHealed = true; - } - } - break; - case ENTRY_DG_KEL: - if (CAST_PLR(pCaster)->GetQuestStatus(QUEST_DARKNESS) == QUEST_STATUS_INCOMPLETE) - { - if (bIsHealed && !bCanRun && Spell->Id == SPELL_FORTITUDE_R1) - { - DoScriptText(SAY_DG_KEL_THANKS,me,pCaster); - bCanRun = true; - } - else if (!bIsHealed && Spell->Id == SPELL_LESSER_HEAL_R2) - { - caster = pCaster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_COMMON_HEALED,me,pCaster); - bIsHealed = true; - } - } - break; - } - - //give quest credit, not expect any special quest objectives - if (bCanRun) - CAST_PLR(pCaster)->TalkedToCreature(me->GetEntry(),me->GetGUID()); - } - } - } - - void WaypointReached(uint32 /*uiPoint*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (bCanRun && !me->isInCombat()) - { - if (RunAwayTimer <= diff) - { - if (Unit *pUnit = Unit::GetUnit(*me,caster)) - { - switch(me->GetEntry()) - { - case ENTRY_SHAYA: DoScriptText(SAY_SHAYA_GOODBYE,me,pUnit); break; - case ENTRY_ROBERTS: DoScriptText(SAY_ROBERTS_GOODBYE,me,pUnit); break; - case ENTRY_DOLF: DoScriptText(SAY_DOLF_GOODBYE,me,pUnit); break; - case ENTRY_KORJA: DoScriptText(SAY_KORJA_GOODBYE,me,pUnit); break; - case ENTRY_DG_KEL: DoScriptText(SAY_DG_KEL_GOODBYE,me,pUnit); break; - } - - Start(false,true,true); - } - else - EnterEvadeMode(); //something went wrong - - RunAwayTimer = 30000; - } else RunAwayTimer -= diff; - } - - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_garments_of_quests(Creature* pCreature) -{ - return new npc_garments_of_questsAI(pCreature); -} - -/*###### -## npc_guardian -######*/ - -#define SPELL_DEATHTOUCH 5 - -struct npc_guardianAI : public ScriptedAI -{ - npc_guardianAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - if (me->isAttackReady()) - { - DoCast(me->getVictim(), SPELL_DEATHTOUCH, true); - me->resetAttackTimer(); - } - } -}; - -CreatureAI* GetAI_npc_guardian(Creature* pCreature) -{ - return new npc_guardianAI (pCreature); -} - -/*###### -## npc_kingdom_of_dalaran_quests -######*/ - -enum eKingdomDalaran -{ - SPELL_TELEPORT_DALARAN = 53360, - ITEM_KT_SIGNET = 39740, - QUEST_MAGICAL_KINGDOM_A = 12794, - QUEST_MAGICAL_KINGDOM_H = 12791, - QUEST_MAGICAL_KINGDOM_N = 12796 -}; - -#define GOSSIP_ITEM_TELEPORT_TO "I am ready to be teleported to Dalaran." - -bool GossipHello_npc_kingdom_of_dalaran_quests(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->HasItemCount(ITEM_KT_SIGNET,1) && (!pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_A) || - !pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_H) || !pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_N))) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT_TO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_kingdom_of_dalaran_quests(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,SPELL_TELEPORT_DALARAN,false); - } - return true; -} - -/*###### -## npc_mount_vendor -######*/ - -bool GossipHello_npc_mount_vendor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - bool canBuy; - canBuy = false; - uint32 vendor = pCreature->GetEntry(); - uint8 race = pPlayer->getRace(); - - switch (vendor) - { - case 384: //Katie Hunter - case 1460: //Unger Statforth - case 2357: //Merideth Carlson - case 4885: //Gregor MacVince - if (pPlayer->GetReputationRank(72) != REP_EXALTED && race != RACE_HUMAN) - pPlayer->SEND_GOSSIP_MENU(5855, pCreature->GetGUID()); - else canBuy = true; - break; - case 1261: //Veron Amberstill - if (pPlayer->GetReputationRank(47) != REP_EXALTED && race != RACE_DWARF) - pPlayer->SEND_GOSSIP_MENU(5856, pCreature->GetGUID()); - else canBuy = true; - break; - case 3362: //Ogunaro Wolfrunner - if (pPlayer->GetReputationRank(76) != REP_EXALTED && race != RACE_ORC) - pPlayer->SEND_GOSSIP_MENU(5841, pCreature->GetGUID()); - else canBuy = true; - break; - case 3685: //Harb Clawhoof - if (pPlayer->GetReputationRank(81) != REP_EXALTED && race != RACE_TAUREN) - pPlayer->SEND_GOSSIP_MENU(5843, pCreature->GetGUID()); - else canBuy = true; - break; - case 4730: //Lelanai - if (pPlayer->GetReputationRank(69) != REP_EXALTED && race != RACE_NIGHTELF) - pPlayer->SEND_GOSSIP_MENU(5844, pCreature->GetGUID()); - else canBuy = true; - break; - case 4731: //Zachariah Post - if (pPlayer->GetReputationRank(68) != REP_EXALTED && race != RACE_UNDEAD_PLAYER) - pPlayer->SEND_GOSSIP_MENU(5840, pCreature->GetGUID()); - else canBuy = true; - break; - case 7952: //Zjolnir - if (pPlayer->GetReputationRank(530) != REP_EXALTED && race != RACE_TROLL) - pPlayer->SEND_GOSSIP_MENU(5842, pCreature->GetGUID()); - else canBuy = true; - break; - case 7955: //Milli Featherwhistle - if (pPlayer->GetReputationRank(54) != REP_EXALTED && race != RACE_GNOME) - pPlayer->SEND_GOSSIP_MENU(5857, pCreature->GetGUID()); - else canBuy = true; - break; - case 16264: //Winaestra - if (pPlayer->GetReputationRank(911) != REP_EXALTED && race != RACE_BLOODELF) - pPlayer->SEND_GOSSIP_MENU(10305, pCreature->GetGUID()); - else canBuy = true; - break; - case 17584: //Torallius the Pack Handler - if (pPlayer->GetReputationRank(930) != REP_EXALTED && race != RACE_DRAENEI) - pPlayer->SEND_GOSSIP_MENU(10239, pCreature->GetGUID()); - else canBuy = true; - break; - } - - if (canBuy) - { - if (pCreature->isVendor()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_mount_vendor(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_rogue_trainer -######*/ - -#define GOSSIP_HELLO_ROGUE1 "I wish to unlearn my talents" -#define GOSSIP_HELLO_ROGUE2 "" -#define GOSSIP_HELLO_ROGUE3 "Purchase a Dual Talent Specialization." - -bool GossipHello_npc_rogue_trainer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isTrainer()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); - - if (pCreature->isCanTrainingAndResetTalentsOf(pPlayer)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE1, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_UNLEARNTALENTS); - - if (!(pPlayer->GetSpecsCount() == 1 && pCreature->isCanTrainingAndResetTalentsOf(pPlayer) && !(pPlayer->getLevel() < sWorld.getConfig(CONFIG_MIN_DUALSPEC_LEVEL)))) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_HELLO_ROGUE3, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_LEARNDUALSPEC); - - if (pPlayer->getClass() == CLASS_ROGUE && pPlayer->getLevel() >= 24 && !pPlayer->HasItemCount(17126,1) && !pPlayer->GetQuestRewardStatus(6681)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_ROGUE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(5996, pCreature->GetGUID()); - } else - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_rogue_trainer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer,21100,false); - break; - case GOSSIP_ACTION_TRAIN: - pPlayer->SEND_TRAINERLIST(pCreature->GetGUID()); - break; - case GOSSIP_OPTION_UNLEARNTALENTS: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->SendTalentWipeConfirm(pCreature->GetGUID()); - break; - case GOSSIP_OPTION_LEARNDUALSPEC: - if (pPlayer->GetSpecsCount() == 1 && !(pPlayer->getLevel() < sWorld.getConfig(CONFIG_MIN_DUALSPEC_LEVEL))) - { - if (pPlayer->GetMoney() < 10000000) - { - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); - pPlayer->PlayerTalkClass->CloseGossip(); - break; - } - else - { - pPlayer->ModifyMoney(-10000000); - - // Cast spells that teach dual spec - // Both are also ImplicitTarget self and must be cast by player - pPlayer->CastSpell(pPlayer,63680,true,NULL,NULL,pPlayer->GetGUID()); - pPlayer->CastSpell(pPlayer,63624,true,NULL,NULL,pPlayer->GetGUID()); - - // Should show another Gossip text with "Congratulations..." - pPlayer->PlayerTalkClass->CloseGossip(); - } - } - break; - } - return true; -} - -/*###### -## npc_sayge -######*/ - -#define SPELL_DMG 23768 //dmg -#define SPELL_RES 23769 //res -#define SPELL_ARM 23767 //arm -#define SPELL_SPI 23738 //spi -#define SPELL_INT 23766 //int -#define SPELL_STM 23737 //stm -#define SPELL_STR 23735 //str -#define SPELL_AGI 23736 //agi -#define SPELL_FORTUNE 23765 //faire fortune - -#define GOSSIP_HELLO_SAYGE "Yes" -#define GOSSIP_SENDACTION_SAYGE1 "Slay the Man" -#define GOSSIP_SENDACTION_SAYGE2 "Turn him over to liege" -#define GOSSIP_SENDACTION_SAYGE3 "Confiscate the corn" -#define GOSSIP_SENDACTION_SAYGE4 "Let him go and have the corn" -#define GOSSIP_SENDACTION_SAYGE5 "Execute your friend painfully" -#define GOSSIP_SENDACTION_SAYGE6 "Execute your friend painlessly" -#define GOSSIP_SENDACTION_SAYGE7 "Let your friend go" -#define GOSSIP_SENDACTION_SAYGE8 "Confront the diplomat" -#define GOSSIP_SENDACTION_SAYGE9 "Show not so quiet defiance" -#define GOSSIP_SENDACTION_SAYGE10 "Remain quiet" -#define GOSSIP_SENDACTION_SAYGE11 "Speak against your brother openly" -#define GOSSIP_SENDACTION_SAYGE12 "Help your brother in" -#define GOSSIP_SENDACTION_SAYGE13 "Keep your brother out without letting him know" -#define GOSSIP_SENDACTION_SAYGE14 "Take credit, keep gold" -#define GOSSIP_SENDACTION_SAYGE15 "Take credit, share the gold" -#define GOSSIP_SENDACTION_SAYGE16 "Let the knight take credit" -#define GOSSIP_SENDACTION_SAYGE17 "Thanks" - -bool GossipHello_npc_sayge(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->HasSpellCooldown(SPELL_INT) || - pPlayer->HasSpellCooldown(SPELL_ARM) || - pPlayer->HasSpellCooldown(SPELL_DMG) || - pPlayer->HasSpellCooldown(SPELL_RES) || - pPlayer->HasSpellCooldown(SPELL_STR) || - pPlayer->HasSpellCooldown(SPELL_AGI) || - pPlayer->HasSpellCooldown(SPELL_STM) || - pPlayer->HasSpellCooldown(SPELL_SPI)) - pPlayer->SEND_GOSSIP_MENU(7393, pCreature->GetGUID()); - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_SAYGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(7339, pCreature->GetGUID()); - } - - return true; -} - -void SendAction_npc_sayge(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(7340, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE5, GOSSIP_SENDER_MAIN+1, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE6, GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE7, GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(7341, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE8, GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE9, GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE10, GOSSIP_SENDER_MAIN+2, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(7361, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE11, GOSSIP_SENDER_MAIN+6, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE12, GOSSIP_SENDER_MAIN+7, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE13, GOSSIP_SENDER_MAIN+8, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(7362, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE14, GOSSIP_SENDER_MAIN+5, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE15, GOSSIP_SENDER_MAIN+4, GOSSIP_ACTION_INFO_DEF); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE16, GOSSIP_SENDER_MAIN+3, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(7363, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE17, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(7364, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pCreature->CastSpell(pPlayer, SPELL_FORTUNE, false); - pPlayer->SEND_GOSSIP_MENU(7365, pCreature->GetGUID()); - break; - } -} - -bool GossipSelect_npc_sayge(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - switch(uiSender) - { - case GOSSIP_SENDER_MAIN: - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - case GOSSIP_SENDER_MAIN+1: - pCreature->CastSpell(pPlayer, SPELL_DMG, false); - pPlayer->AddSpellCooldown(SPELL_DMG,0,time(NULL) + 7200); - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - case GOSSIP_SENDER_MAIN+2: - pCreature->CastSpell(pPlayer, SPELL_RES, false); - pPlayer->AddSpellCooldown(SPELL_RES,0,time(NULL) + 7200); - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - case GOSSIP_SENDER_MAIN+3: - pCreature->CastSpell(pPlayer, SPELL_ARM, false); - pPlayer->AddSpellCooldown(SPELL_ARM,0,time(NULL) + 7200); - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - case GOSSIP_SENDER_MAIN+4: - pCreature->CastSpell(pPlayer, SPELL_SPI, false); - pPlayer->AddSpellCooldown(SPELL_SPI,0,time(NULL) + 7200); - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - case GOSSIP_SENDER_MAIN+5: - pCreature->CastSpell(pPlayer, SPELL_INT, false); - pPlayer->AddSpellCooldown(SPELL_INT,0,time(NULL) + 7200); - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - case GOSSIP_SENDER_MAIN+6: - pCreature->CastSpell(pPlayer, SPELL_STM, false); - pPlayer->AddSpellCooldown(SPELL_STM,0,time(NULL) + 7200); - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - case GOSSIP_SENDER_MAIN+7: - pCreature->CastSpell(pPlayer, SPELL_STR, false); - pPlayer->AddSpellCooldown(SPELL_STR,0,time(NULL) + 7200); - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - case GOSSIP_SENDER_MAIN+8: - pCreature->CastSpell(pPlayer, SPELL_AGI, false); - pPlayer->AddSpellCooldown(SPELL_AGI,0,time(NULL) + 7200); - SendAction_npc_sayge(pPlayer, pCreature, uiAction); - break; - } - return true; -} - -struct npc_steam_tonkAI : public ScriptedAI -{ - npc_steam_tonkAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - - void OnPossess(bool apply) - { - if (apply) - { - // Initialize the action bar without the melee attack command - me->InitCharmInfo(); - me->GetCharmInfo()->InitEmptyActionBar(false); - - me->SetReactState(REACT_PASSIVE); - } - else - me->SetReactState(REACT_AGGRESSIVE); - } - -}; - -CreatureAI* GetAI_npc_steam_tonk(Creature* pCreature) -{ - return new npc_steam_tonkAI(pCreature); -} - -#define SPELL_TONK_MINE_DETONATE 25099 - -struct npc_tonk_mineAI : public ScriptedAI -{ - npc_tonk_mineAI(Creature *c) : ScriptedAI(c) - { - me->SetReactState(REACT_PASSIVE); - } - - uint32 ExplosionTimer; - - void Reset() - { - ExplosionTimer = 3000; - } - - void EnterCombat(Unit * /*who*/) {} - void AttackStart(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (ExplosionTimer <= diff) - { - DoCast(me, SPELL_TONK_MINE_DETONATE, true); - me->setDeathState(DEAD); // unsummon it - } else - ExplosionTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_tonk_mine(Creature* pCreature) -{ - return new npc_tonk_mineAI(pCreature); -} - -/*#### -## npc_brewfest_reveler -####*/ - -struct npc_brewfest_revelerAI : public ScriptedAI -{ - npc_brewfest_revelerAI(Creature* c) : ScriptedAI(c) {} - void ReceiveEmote(Player* pPlayer, uint32 emote) - { - if (!IsHolidayActive(HOLIDAY_BREWFEST)) - return; - - if (emote == TEXTEMOTE_DANCE) - me->CastSpell(pPlayer, 41586, false); - } -}; - -CreatureAI* GetAI_npc_brewfest_reveler(Creature* pCreature) -{ - return new npc_brewfest_revelerAI(pCreature); -} - -/*#### -## npc_winter_reveler -####*/ - -struct npc_winter_revelerAI : public ScriptedAI -{ - npc_winter_revelerAI(Creature* c) : ScriptedAI(c) {} - void ReceiveEmote(Player* pPlayer, uint32 emote) - { - if (!IsHolidayActive(HOLIDAY_FEAST_OF_WINTER_VEIL)) - return; - //TODO: check auralist. - if (pPlayer->HasAura(26218)) - return; - - if (emote == TEXTEMOTE_KISS) - { - me->CastSpell(me, 26218, false); - pPlayer->CastSpell(pPlayer, 26218, false); - switch (urand(0,2)) - { - case 0: me->CastSpell(pPlayer, 26207, false); break; - case 1: me->CastSpell(pPlayer, 26206, false); break; - case 2: me->CastSpell(pPlayer, 45036, false); break; - } - } - } -}; - -CreatureAI* GetAI_npc_winter_reveler(Creature* pCreature) -{ - return new npc_winter_revelerAI(pCreature); -} - - -/*#### -## npc_snake_trap_serpents -####*/ - -#define SPELL_MIND_NUMBING_POISON 25810 //Viper -#define SPELL_DEADLY_POISON 34655 //Venomous Snake -#define SPELL_CRIPPLING_POISON 30981 //Viper - -#define VENOMOUS_SNAKE_TIMER 1500 -#define VIPER_TIMER 3000 - -#define C_VIPER 19921 - -#define RAND 5 - -struct npc_snake_trap_serpentsAI : public ScriptedAI -{ - npc_snake_trap_serpentsAI(Creature *c) : ScriptedAI(c) {} - - uint32 SpellTimer; - bool IsViper; - bool Spawn; - - void EnterCombat(Unit * /*who*/) {} - - void Reset() - { - Spawn = true; - SpellTimer = 0; - - CreatureInfo const *Info = me->GetCreatureInfo(); - - if (Info->Entry == C_VIPER) - IsViper = true; - else - IsViper = false; - - //Add delta to make them not all hit the same time - uint32 delta = (rand() % 7) * 100; - me->SetStatFloatValue(UNIT_FIELD_BASEATTACKTIME, Info->baseattacktime + delta); - me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER , Info->attackpower); - } - - //Redefined for random target selection: - void MoveInLineOfSight(Unit *who) - { - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - if (!(rand() % RAND)) - { - me->setAttackTimer(BASE_ATTACK, (rand() % 10) * 100); - SpellTimer = (rand() % 10) * 100; - AttackStart(who); - } - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Spawn) - { - Spawn = false; - // Start attacking attacker of owner on first ai update after spawn - move in line of sight may choose better target - if (!me->getVictim() && me->isSummon()) - if (Unit * Owner = CAST_SUM(me)->GetSummoner()) - if (Owner->getAttackerForHelper()) - AttackStart(Owner->getAttackerForHelper()); - } - - if (!me->getVictim()) - { - if (me->isInCombat()) - DoStopAttack(); - return; - } - - if (SpellTimer <= diff) - { - if (IsViper) //Viper - { - if (urand(0,2) == 0) //33% chance to cast - { - uint32 spell; - if (urand(0,1) == 0) - spell = SPELL_MIND_NUMBING_POISON; - else - spell = SPELL_CRIPPLING_POISON; - - DoCast(me->getVictim(), spell); - } - - SpellTimer = VIPER_TIMER; - } - else //Venomous Snake - { - if (urand(0,2) == 0) //33% chance to cast - DoCast(me->getVictim(), SPELL_DEADLY_POISON); - SpellTimer = VENOMOUS_SNAKE_TIMER + (rand() %5)*100; - } - } else SpellTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_snake_trap_serpents(Creature* pCreature) -{ - return new npc_snake_trap_serpentsAI(pCreature); -} - -#define SAY_RANDOM_MOJO0 "Now that's what I call froggy-style!" -#define SAY_RANDOM_MOJO1 "Your lily pad or mine?" -#define SAY_RANDOM_MOJO2 "This won't take long, did it?" -#define SAY_RANDOM_MOJO3 "I thought you'd never ask!" -#define SAY_RANDOM_MOJO4 "I promise not to give you warts..." -#define SAY_RANDOM_MOJO5 "Feelin' a little froggy, are ya?" -#define SAY_RANDOM_MOJO6a "Listen, " -#define SAY_RANDOM_MOJO6b ", I know of a little swamp not too far from here...." -#define SAY_RANDOM_MOJO7 "There's just never enough Mojo to go around..." - -struct mob_mojoAI : public ScriptedAI -{ - mob_mojoAI(Creature *c) : ScriptedAI(c) {Reset();} - uint32 hearts; - uint64 victimGUID; - void Reset() - { - victimGUID = 0; - hearts = 15000; - if (Unit* own = me->GetOwner()) - me->GetMotionMaster()->MoveFollow(own,0,0); - } - void Aggro(Unit * /*who*/){} - void UpdateAI(const uint32 diff) - { - if (me->HasAura(20372)) - { - if (hearts <= diff) - { - me->RemoveAurasDueToSpell(20372); - hearts = 15000; - } hearts -= diff; - } - } - void ReceiveEmote(Player* pPlayer, uint32 emote) - { - me->HandleEmoteCommand(emote); - Unit* own = me->GetOwner(); - if (!own || own->GetTypeId() != TYPEID_PLAYER || CAST_PLR(own)->GetTeam() != pPlayer->GetTeam()) - return; - if (emote == TEXTEMOTE_KISS) - { - std::string whisp = ""; - switch (rand()%8) - { - case 0:whisp.append(SAY_RANDOM_MOJO0);break; - case 1:whisp.append(SAY_RANDOM_MOJO1);break; - case 2:whisp.append(SAY_RANDOM_MOJO2);break; - case 3:whisp.append(SAY_RANDOM_MOJO3);break; - case 4:whisp.append(SAY_RANDOM_MOJO4);break; - case 5:whisp.append(SAY_RANDOM_MOJO5);break; - case 6: - whisp.append(SAY_RANDOM_MOJO6a); - whisp.append(pPlayer->GetName()); - whisp.append(SAY_RANDOM_MOJO6b); - break; - case 7:whisp.append(SAY_RANDOM_MOJO7);break; - } - me->MonsterWhisper(whisp.c_str(),pPlayer->GetGUID()); - if (victimGUID) - { - Player* victim = Unit::GetPlayer(victimGUID); - if (victim) - victim->RemoveAura(43906);//remove polymorph frog thing - } - me->AddAura(43906,pPlayer);//add polymorph frog thing - victimGUID = pPlayer->GetGUID(); - DoCast(me, 20372, true);//tag.hearts - me->GetMotionMaster()->MoveFollow(pPlayer,0,0); - hearts = 15000; - } - } -}; - -CreatureAI* GetAI_mob_mojo(Creature* pCreature) -{ - return new mob_mojoAI (pCreature); -} - -struct npc_mirror_image : CasterAI -{ - npc_mirror_image(Creature *c) : CasterAI(c) {} - - void InitializeAI() - { - CasterAI::InitializeAI(); - Unit * owner = me->GetOwner(); - if (!owner) - return; - // Inherit Master's Threat List (not yet implemented) - owner->CastSpell((Unit*)NULL, 58838, true); - // here mirror image casts on summoner spell (not present in client dbc) 49866 - // here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcasted by mirror images (stats related?) - // Clone Me! - owner->CastSpell(me, 45204, false); - } - - // Do not reload Creature templates on evade mode enter - prevent visual lost - void EnterEvadeMode() - { - if (me->IsInEvadeMode() || !me->isAlive()) - return; - - Unit *owner = me->GetCharmerOrOwner(); - - me->CombatStop(true); - if (owner && !me->hasUnitState(UNIT_STAT_FOLLOW)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE); - } - } -}; - -CreatureAI* GetAI_npc_mirror_image(Creature* pCreature) -{ - return new npc_mirror_image (pCreature); -} - -struct npc_ebon_gargoyleAI : CasterAI -{ - npc_ebon_gargoyleAI(Creature *c) : CasterAI(c) {} - - int despawnTimer; - - void InitializeAI() - { - CasterAI::InitializeAI(); - Unit * owner = me->GetOwner(); - if (!owner) - return; - // Not needed to be despawned now - despawnTimer = 0; - // Find victim of Summon Gargoyle spell - std::list targets; - Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30); - Trinity::UnitListSearcher searcher(me, targets, u_check); - me->VisitNearbyObject(30, searcher); - for (std::list::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) - if ((*iter)->GetAura(49206,owner->GetGUID())) - { - me->Attack((*iter),false); - break; - } - } - - void JustDied(Unit * /*killer*/) - { - // Stop Feeding Gargoyle when it dies - if (Unit *owner = me->GetOwner()) - owner->RemoveAurasDueToSpell(50514); - } - - // Fly away when dismissed - void SpellHit(Unit *source, const SpellEntry *spell) - { - if (spell->Id != 50515 || !me->isAlive()) - return; - - Unit *owner = me->GetOwner(); - - if (!owner || owner != source) - return; - - // Stop Fighting - me->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, true); - // Sanctuary - me->CastSpell(me, 54661, true); - me->SetReactState(REACT_PASSIVE); - - // Fly Away - me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE|MOVEMENTFLAG_ASCEND|MOVEMENTFLAG_FLYING); - me->SetSpeed(MOVE_FLIGHT, 0.75f, true); - me->SetSpeed(MOVE_RUN, 0.75f, true); - float x = me->GetPositionX() + 20 * cos(me->GetOrientation()); - float y = me->GetPositionY() + 20 * sin(me->GetOrientation()); - float z = me->GetPositionZ() + 40; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(0, x, y, z); - - // Despawn as soon as possible - despawnTimer = 4 * IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (despawnTimer > 0) - { - if (despawnTimer > diff) - despawnTimer -= diff; - else - { - me->ForcedDespawn(); - } - return; - } - CasterAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_ebon_gargoyle(Creature* pCreature) -{ - return new npc_ebon_gargoyleAI (pCreature); -} - -struct npc_lightwellAI : public PassiveAI -{ - npc_lightwellAI(Creature *c) : PassiveAI(c) {} - - void Reset() - { - DoCast(me, 59907, false); // Spell for Lightwell Charges - } -}; - -CreatureAI* GetAI_npc_lightwellAI(Creature* pCreature) -{ - return new npc_lightwellAI (pCreature); -} - -struct npc_training_dummy : Scripted_NoMovementAI -{ - npc_training_dummy(Creature *c) : Scripted_NoMovementAI(c) - { - m_Entry = c->GetEntry(); - } - - uint64 m_Entry; - uint32 ResetTimer; - uint32 DespawnTimer; - void Reset() - { - me->SetControlled(true,UNIT_STAT_STUNNED);//disable rotate - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave - me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_STUN, true); - ResetTimer = 10000; - DespawnTimer = 15000; - } - - void EnterEvadeMode() - { - if (!_EnterEvadeMode()) - return; - - Reset(); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - ResetTimer = 10000; - damage = 0; - } - - void EnterCombat(Unit * /*who*/) - { - if (m_Entry != 2674 && m_Entry != 2673) - return; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - me->SetControlled(true,UNIT_STAT_STUNNED);//disable rotate - - if (m_Entry != 2674 && m_Entry != 2673) - { - if (ResetTimer <= diff) - { - EnterEvadeMode(); - ResetTimer = 10000; - } - else - ResetTimer -= diff; - return; - } - else - { - if (DespawnTimer <= diff) - me->ForcedDespawn(); - else - DespawnTimer -= diff; - } - } - void MoveInLineOfSight(Unit * /*who*/){return;} -}; - -CreatureAI* GetAI_npc_training_dummy(Creature* pCreature) -{ - return new npc_training_dummy (pCreature); -} - -/*###### -# npc_shadowfiend -######*/ -#define GLYPH_OF_SHADOWFIEND_MANA 58227 -#define GLYPH_OF_SHADOWFIEND 58228 - -struct npc_shadowfiendAI : public ScriptedAI -{ - npc_shadowfiendAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (me->isSummon()) - if (Unit* pOwner = CAST_SUM(me)->GetSummoner()) - { - if (pOwner->HasAura(GLYPH_OF_SHADOWFIEND)) - if (damage >= me->GetHealth()) - pOwner->CastSpell(pOwner,GLYPH_OF_SHADOWFIEND_MANA,true); - } - } - - void UpdateAI(const uint32 /*diff*/) - { - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_shadowfiend(Creature* pCreature) -{ - return new npc_shadowfiendAI(pCreature); -} - -/*###### -# npc_wormhole -######*/ - -#define GOSSIP_ENGINEERING1 "Borean Tundra." -#define GOSSIP_ENGINEERING2 "Howling Fjord." -#define GOSSIP_ENGINEERING3 "Sholazar Basin." -#define GOSSIP_ENGINEERING4 "Icecrown." -#define GOSSIP_ENGINEERING5 "Storm Peaks." - -enum eWormhole -{ - SPELL_HOWLING_FJORD = 67838, - SPELL_SHOLAZAR_BASIN = 67835, - SPELL_ICECROWN = 67836, - SPELL_STORM_PEAKS = 67837, - - TEXT_WORMHOLE = 907 -}; - -bool GossipHello_npc_wormhole(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isSummon()) - { - if (pPlayer == CAST_SUM(pCreature)->GetSummoner()) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ENGINEERING5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - - pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_WORMHOLE, pCreature->GetGUID()); - } - } - return true; -} - -bool GossipSelect_npc_wormhole(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - bool roll = urand(0,1); - - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: //Borean Tundra - pPlayer->CLOSE_GOSSIP_MENU(); - if (roll) //At the moment we don't have chance on spell_target_position table so we hack this - pPlayer->TeleportTo(571, 4305.505859, 5450.839844, 63.005806, 0.627286); - else - pPlayer->TeleportTo(571, 3201.936279, 5630.123535, 133.658798, 3.855272); - break; - case GOSSIP_ACTION_INFO_DEF + 2: //Howling Fjord - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_HOWLING_FJORD, true); - break; - case GOSSIP_ACTION_INFO_DEF + 3: //Sholazar Basin - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_SHOLAZAR_BASIN, true); - break; - case GOSSIP_ACTION_INFO_DEF + 4: //Icecrown - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_ICECROWN, true); - break; - case GOSSIP_ACTION_INFO_DEF + 5: //Storm peaks - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_STORM_PEAKS, true); - break; - } - return true; -} - -/*###### -## npc_pet_trainer -######*/ - -enum ePetTrainer -{ - TEXT_ISHUNTER = 5838, - TEXT_NOTHUNTER = 5839, - TEXT_PETINFO = 13474, - TEXT_CONFIRM = 7722 -}; - -#define GOSSIP_PET1 "How do I train my pet?" -#define GOSSIP_PET2 "I wish to untrain my pet." -#define GOSSIP_PET_CONFIRM "Yes, please do." - -bool GossipHello_npc_pet_trainer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->getClass() == CLASS_HUNTER) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - if (pPlayer->GetPet() && pPlayer->GetPet()->getPetType() == HUNTER_PET) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_ISHUNTER, pCreature->GetGUID()); - return true; - } - pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_NOTHUNTER, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_pet_trainer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_PETINFO, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_PET_CONFIRM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_CONFIRM, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 3: - { - pPlayer->ResetPetTalents(); - pPlayer->CLOSE_GOSSIP_MENU(); - } - break; - } - return true; -} - -/*###### -## npc_locksmith -######*/ - -enum eLockSmith -{ - QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ = 10704, - QUEST_DARK_IRON_LEGACY = 3802, - QUEST_THE_KEY_TO_SCHOLOMANCE_A = 5505, - QUEST_THE_KEY_TO_SCHOLOMANCE_H = 5511, - QUEST_HOTTER_THAN_HELL_A = 10758, - QUEST_HOTTER_THAN_HELL_H = 10764, - QUEST_RETURN_TO_KHAGDAR = 9837, - QUEST_CONTAINMENT = 13159, - - ITEM_ARCATRAZ_KEY = 31084, - ITEM_SHADOWFORGE_KEY = 11000, - ITEM_SKELETON_KEY = 13704, - ITEM_SHATTERED_HALLS_KEY = 28395, - ITEM_THE_MASTERS_KEY = 24490, - ITEM_VIOLET_HOLD_KEY = 42482, - - SPELL_ARCATRAZ_KEY = 54881, - SPELL_SHADOWFORGE_KEY = 54882, - SPELL_SKELETON_KEY = 54883, - SPELL_SHATTERED_HALLS_KEY = 54884, - SPELL_THE_MASTERS_KEY = 54885, - SPELL_VIOLET_HOLD_KEY = 67253 -}; - -#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz." -#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths." -#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance." -#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls." -#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan." -#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold." - - -bool GossipHello_npc_locksmith(Player* pPlayer, Creature* pCreature) -{ - - // Arcatraz Key - if (pPlayer->GetQuestRewardStatus(QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ) && !pPlayer->HasItemCount(ITEM_ARCATRAZ_KEY, 1, true)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ARCATRAZ_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +1); - - // Shadowforge Key - if (pPlayer->GetQuestRewardStatus(QUEST_DARK_IRON_LEGACY) && !pPlayer->HasItemCount(ITEM_SHADOWFORGE_KEY, 1, true)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHADOWFORGE_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +2); - - // Skeleton Key - if ((pPlayer->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_A) || pPlayer->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_H)) && - !pPlayer->HasItemCount(ITEM_SKELETON_KEY, 1, true)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SKELETON_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +3); - - // Shatered Halls Key - if ((pPlayer->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_A) || pPlayer->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_H)) && - !pPlayer->HasItemCount(ITEM_SHATTERED_HALLS_KEY, 1, true)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHATTERED_HALLS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +4); - - // Master's Key - if (pPlayer->GetQuestRewardStatus(QUEST_RETURN_TO_KHAGDAR) && !pPlayer->HasItemCount(ITEM_THE_MASTERS_KEY, 1, true)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_THE_MASTERS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +5); - - // Violet Hold Key - if (pPlayer->GetQuestRewardStatus(QUEST_CONTAINMENT) && !pPlayer->HasItemCount(ITEM_VIOLET_HOLD_KEY, 1, true)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_VIOLET_HOLD_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +6); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_locksmith(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_ARCATRAZ_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_SHADOWFORGE_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_SKELETON_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_SHATTERED_HALLS_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_THE_MASTERS_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_VIOLET_HOLD_KEY, false); - break; - } - return true; -} - -/*###### -## npc_tabard_vendor -######*/ - -enum -{ - QUEST_TRUE_MASTERS_OF_LIGHT = 9737, - QUEST_THE_UNWRITTEN_PROPHECY = 9762, - QUEST_INTO_THE_BREACH = 10259, - QUEST_BATTLE_OF_THE_CRIMSON_WATCH = 10781, - QUEST_SHARDS_OF_AHUNE = 11972, - - ACHIEVEMENT_EXPLORE_NORTHREND = 45, - ACHIEVEMENT_TWENTYFIVE_TABARDS = 1021, - ACHIEVEMENT_THE_LOREMASTER_A = 1681, - ACHIEVEMENT_THE_LOREMASTER_H = 1682, - - ITEM_TABARD_OF_THE_HAND = 24344, - ITEM_TABARD_OF_THE_BLOOD_KNIGHT = 25549, - ITEM_TABARD_OF_THE_PROTECTOR = 28788, - ITEM_OFFERING_OF_THE_SHATAR = 31408, - ITEM_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI = 31404, - ITEM_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI = 31405, - ITEM_TABARD_OF_THE_SUMMER_SKIES = 35279, - ITEM_TABARD_OF_THE_SUMMER_FLAMES = 35280, - ITEM_TABARD_OF_THE_ACHIEVER = 40643, - ITEM_LOREMASTERS_COLORS = 43300, - ITEM_TABARD_OF_THE_EXPLORER = 43348, - - SPELL_TABARD_OF_THE_BLOOD_KNIGHT = 54974, - SPELL_TABARD_OF_THE_HAND = 54976, - SPELL_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI = 54977, - SPELL_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI = 54982, - SPELL_TABARD_OF_THE_ACHIEVER = 55006, - SPELL_TABARD_OF_THE_PROTECTOR = 55008, - SPELL_LOREMASTERS_COLORS = 58194, - SPELL_TABARD_OF_THE_EXPLORER = 58224, - SPELL_TABARD_OF_SUMMER_SKIES = 62768, - SPELL_TABARD_OF_SUMMER_FLAMES = 62769 -}; - -#define GOSSIP_LOST_TABARD_OF_BLOOD_KNIGHT "I've lost my Tabard of Blood Knight." -#define GOSSIP_LOST_TABARD_OF_THE_HAND "I've lost my Tabard of the Hand." -#define GOSSIP_LOST_TABARD_OF_THE_PROTECTOR "I've lost my Tabard of the Protector." -#define GOSSIP_LOST_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI "I've lost my Green Trophy Tabard of the Illidari." -#define GOSSIP_LOST_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI "I've lost my Purple Trophy Tabard of the Illidari." -#define GOSSIP_LOST_TABARD_OF_SUMMER_SKIES "I've lost my Tabard of Summer Skies." -#define GOSSIP_LOST_TABARD_OF_SUMMER_FLAMES "I've lost my Tabard of Summer Flames." -#define GOSSIP_LOST_LOREMASTERS_COLORS "I've lost my Loremaster's Colors." -#define GOSSIP_LOST_TABARD_OF_THE_EXPLORER "I've lost my Tabard of the Explorer." -#define GOSSIP_LOST_TABARD_OF_THE_ACHIEVER "I've lost my Tabard of the Achiever." - -bool GossipHello_npc_tabard_vendor(Player* pPlayer, Creature* pCreature) -{ - bool m_bLostBloodKnight = false; - bool m_bLostHand = false; - bool m_bLostProtector = false; - bool m_bLostIllidari = false; - bool m_bLostSummer = false; - - //Tabard of the Blood Knight - if (pPlayer->GetQuestRewardStatus(QUEST_TRUE_MASTERS_OF_LIGHT) && !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_BLOOD_KNIGHT, 1, true)) - m_bLostBloodKnight = true; - - //Tabard of the Hand - if (pPlayer->GetQuestRewardStatus(QUEST_THE_UNWRITTEN_PROPHECY) && !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_HAND, 1, true)) - m_bLostHand = true; - - //Tabard of the Protector - if (pPlayer->GetQuestRewardStatus(QUEST_INTO_THE_BREACH) && !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_PROTECTOR, 1, true)) - m_bLostProtector = true; - - //Green Trophy Tabard of the Illidari - //Purple Trophy Tabard of the Illidari - if (pPlayer->GetQuestRewardStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) && - (!pPlayer->HasItemCount(ITEM_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, 1, true) && - !pPlayer->HasItemCount(ITEM_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, 1, true) && - !pPlayer->HasItemCount(ITEM_OFFERING_OF_THE_SHATAR, 1, true))) - m_bLostIllidari = true; - - //Tabard of Summer Skies - //Tabard of Summer Flames - if (pPlayer->GetQuestRewardStatus(QUEST_SHARDS_OF_AHUNE) && - !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_SUMMER_SKIES, 1, true) && - !pPlayer->HasItemCount(ITEM_TABARD_OF_THE_SUMMER_FLAMES, 1, true)) - m_bLostSummer = true; - - if (m_bLostBloodKnight || m_bLostHand || m_bLostProtector || m_bLostIllidari || m_bLostSummer) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - if (m_bLostBloodKnight) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_BLOOD_KNIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +1); - - if (m_bLostHand) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_THE_HAND, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +2); - - if (m_bLostProtector) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_THE_PROTECTOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - - if (m_bLostIllidari) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - } - - if (m_bLostSummer) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_SUMMER_SKIES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_TABARD_OF_SUMMER_FLAMES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - } - - pPlayer->SEND_GOSSIP_MENU(13583, pCreature->GetGUID()); - } - else - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_tabard_vendor(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_TRADE: - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_THE_BLOOD_KNIGHT, false); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_THE_HAND, false); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_THE_PROTECTOR, false); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_GREEN_TROPHY_TABARD_OF_THE_ILLIDARI, false); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_PURPLE_TROPHY_TABARD_OF_THE_ILLIDARI, false); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_SUMMER_SKIES, false); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_TABARD_OF_SUMMER_FLAMES, false); - break; - } - return true; -} - -/*###### -## npc_experience -######*/ - -#define EXP_COST 100000//10 00 00 copper (10golds) -#define GOSSIP_TEXT_EXP 14736 -#define GOSSIP_XP_OFF "I no longer wish to gain experience." -#define GOSSIP_XP_ON "I wish to start gaining experience again." - - -bool GossipHello_npc_experience(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_XP_OFF, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_XP_ON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_EXP, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_experience(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - bool noXPGain = pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); - bool doSwitch = false; - - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1://xp off - { - if (!noXPGain)//does gain xp - doSwitch = true;//switch to don't gain xp - } - break; - case GOSSIP_ACTION_INFO_DEF + 2://xp on - { - if (noXPGain)//doesn't gain xp - doSwitch = true;//switch to gain xp - } - break; - } - if (doSwitch) - { - if (pPlayer->GetMoney() < EXP_COST) - pPlayer->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); - else if (noXPGain) - { - pPlayer->ModifyMoney(-EXP_COST); - pPlayer->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); - } - else if (!noXPGain) - { - pPlayer->ModifyMoney(-EXP_COST); - pPlayer->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); - } - } - pPlayer->PlayerTalkClass->CloseGossip(); - return true; -} - -void AddSC_npcs_special() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_air_force_bots"; - newscript->GetAI = &GetAI_npc_air_force_bots; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lunaclaw_spirit"; - newscript->pGossipHello = &GossipHello_npc_lunaclaw_spirit; - newscript->pGossipSelect = &GossipSelect_npc_lunaclaw_spirit; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_chicken_cluck"; - newscript->GetAI = &GetAI_npc_chicken_cluck; - newscript->pQuestAccept = &QuestAccept_npc_chicken_cluck; - newscript->pQuestComplete = &QuestComplete_npc_chicken_cluck; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dancing_flames"; - newscript->GetAI = &GetAI_npc_dancing_flames; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_injured_patient"; - newscript->GetAI = &GetAI_npc_injured_patient; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_doctor"; - newscript->GetAI = &GetAI_npc_doctor; - newscript->pQuestAccept = &QuestAccept_npc_doctor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_garments_of_quests"; - newscript->GetAI = &GetAI_npc_garments_of_quests; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_guardian"; - newscript->GetAI = &GetAI_npc_guardian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_kingdom_of_dalaran_quests"; - newscript->pGossipHello = &GossipHello_npc_kingdom_of_dalaran_quests; - newscript->pGossipSelect = &GossipSelect_npc_kingdom_of_dalaran_quests; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_mount_vendor"; - newscript->pGossipHello = &GossipHello_npc_mount_vendor; - newscript->pGossipSelect = &GossipSelect_npc_mount_vendor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_rogue_trainer"; - newscript->pGossipHello = &GossipHello_npc_rogue_trainer; - newscript->pGossipSelect = &GossipSelect_npc_rogue_trainer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_sayge"; - newscript->pGossipHello = &GossipHello_npc_sayge; - newscript->pGossipSelect = &GossipSelect_npc_sayge; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_steam_tonk"; - newscript->GetAI = &GetAI_npc_steam_tonk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tonk_mine"; - newscript->GetAI = &GetAI_npc_tonk_mine; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_winter_reveler"; - newscript->GetAI = &GetAI_npc_winter_reveler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_brewfest_reveler"; - newscript->GetAI = &GetAI_npc_winter_reveler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_snake_trap_serpents"; - newscript->GetAI = &GetAI_npc_snake_trap_serpents; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_mirror_image"; - newscript->GetAI = &GetAI_npc_mirror_image; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ebon_gargoyle"; - newscript->GetAI = &GetAI_npc_ebon_gargoyle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lightwell"; - newscript->GetAI = &GetAI_npc_lightwellAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_mojo"; - newscript->GetAI = &GetAI_mob_mojo; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_training_dummy"; - newscript->GetAI = &GetAI_npc_training_dummy; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_shadowfiend"; - newscript->GetAI = &GetAI_npc_shadowfiend; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_wormhole"; - newscript->pGossipHello = &GossipHello_npc_wormhole; - newscript->pGossipSelect = &GossipSelect_npc_wormhole; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_pet_trainer"; - newscript->pGossipHello = &GossipHello_npc_pet_trainer; - newscript->pGossipSelect = &GossipSelect_npc_pet_trainer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_locksmith"; - newscript->pGossipHello = &GossipHello_npc_locksmith; - newscript->pGossipSelect = &GossipSelect_npc_locksmith; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tabard_vendor"; - newscript->pGossipHello = &GossipHello_npc_tabard_vendor; - newscript->pGossipSelect = &GossipSelect_npc_tabard_vendor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_experience"; - newscript->pGossipHello = &GossipHello_npc_experience; - newscript->pGossipSelect = &GossipSelect_npc_experience; - newscript->RegisterSelf(); -} - -- cgit v1.2.3 From dc510c9a143de1977daedea0aefb9589c01adde2 Mon Sep 17 00:00:00 2001 From: click Date: Mon, 7 Jun 2010 00:54:06 +0200 Subject: Some more consistency-renaming of script-zones --HG-- branch : trunk rename : src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp => src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp rename : src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp => src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp rename : src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp => src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp rename : src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp => src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp rename : src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp => src/server/scripts/EasternKingdoms/AlteracValley/boss_vanndar.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h => src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.h rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_ambassador_flamelash.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_anubshiah.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_general_angerforge.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_gorosh_the_dervish.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_grizzle.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_high_interrogator_gerstahn.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_magmus.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_moira_bronzebeard.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/boss_tomb_of_seven.cpp rename : src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp => src/server/scripts/EasternKingdoms/BlackrockDepths/instance_blackrock_depths.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h => src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_halycon.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_highlord_omokk.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_mother_smolderweb.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_overlord_wyrmthalak.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_quartermaster_zigris.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_shadow_hunter_voshgajin.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_the_beast.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/boss_warmaster_voone.cpp rename : src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp => src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp rename : src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp => src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp rename : src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp => src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp rename : src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp => src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp rename : src/server/scripts/EasternKingdoms/deadmines/deadmines.h => src/server/scripts/EasternKingdoms/Deadmines/deadmines.h rename : src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp => src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp rename : src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp => src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp rename : src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h => src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h rename : src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp => src/server/scripts/EasternKingdoms/Gnomeregan/instance_gnomeregan.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp rename : src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp => src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp rename : src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp => src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp rename : src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp => src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp rename : src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp => src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp rename : src/server/scripts/EasternKingdoms/karazhan/karazhan.h => src/server/scripts/EasternKingdoms/Karazhan/karazhan.h rename : src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp => src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp rename : src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp => src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp rename : src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp => src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp rename : src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp => src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp rename : src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp => src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp rename : src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp => src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp rename : src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h => src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h rename : src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_baron_geddon.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_garr.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_gehennas.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_lucifron.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_magmadar.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_majordomo_executus.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_ragnaros.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_shazzrah.cpp rename : src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp => src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp rename : src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp => src/server/scripts/EasternKingdoms/MoltenCore/instance_molten_core.cpp rename : src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp => src/server/scripts/EasternKingdoms/MoltenCore/molten_core.cpp rename : src/server/scripts/EasternKingdoms/molten_core/molten_core.h => src/server/scripts/EasternKingdoms/MoltenCore/molten_core.h rename : src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp => src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp rename : src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp => src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp rename : src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp => src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp rename : src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp => src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp => src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp rename : src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h => src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h rename : src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_death_knight_darkreaver.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_doctor_theolen_krastinov.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_instructor_malicia.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_kormok.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_lord_alexei_barov.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_lorekeeper_polkelt.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_the_ravenian.cpp rename : src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp => src/server/scripts/EasternKingdoms/Scholomance/boss_vectus.cpp rename : src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp => src/server/scripts/EasternKingdoms/Scholomance/instance_scholomance.cpp rename : src/server/scripts/EasternKingdoms/scholomance/scholomance.h => src/server/scripts/EasternKingdoms/Scholomance/scholomance.h rename : src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp => src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp rename : src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp => src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp rename : src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h => src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h rename : src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_baroness_anastari.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_cannon_master_willey.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_dathrohan_balnazzar.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_magistrate_barthilas.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_maleki_the_pallid.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_nerubenkan.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_order_of_silver_hand.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_postmaster_malown.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_ramstein_the_gorger.cpp rename : src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp => src/server/scripts/EasternKingdoms/Stratholme/boss_timmy_the_cruel.cpp rename : src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp => src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp rename : src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp => src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp rename : src/server/scripts/EasternKingdoms/stratholme/stratholme.h => src/server/scripts/EasternKingdoms/Stratholme/stratholme.h rename : src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp => src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp rename : src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp => src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp rename : src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h => src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h rename : src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp => src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp rename : src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp => src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp rename : src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp => src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp rename : src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp => src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp rename : src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp => src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp rename : src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp => src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp rename : src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp => src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp rename : src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp => src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.cpp rename : src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h => src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h rename : src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp => src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp rename : src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp => src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp rename : src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp => src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp rename : src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp => src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp rename : src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp => src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp rename : src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp => src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp rename : src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp => src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp rename : src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp => src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp rename : src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp => src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp rename : src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp => src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp rename : src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp => src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp rename : src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp => src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp rename : src/server/scripts/EasternKingdoms/zulaman/zulaman.h => src/server/scripts/EasternKingdoms/ZulAman/zulaman.h rename : src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp => src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp => src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp rename : src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h => src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h rename : src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp => src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp rename : src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h => src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.h rename : src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp => src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp rename : src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp => src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp rename : src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp => src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp rename : src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp => src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp => src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp => src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp => src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp => src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp => src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp => src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h => src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h rename : src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp => src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp => src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp => src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp => src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h => src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h rename : src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h rename : src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp => src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp => src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp => src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp => src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp => src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp rename : src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h => src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h rename : src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp => src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp rename : src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp => src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp rename : src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp => src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp rename : src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp => src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp rename : src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp => src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp rename : src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp => src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp rename : src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h => src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h rename : src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp => src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp rename : src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp => src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp rename : src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp => src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp rename : src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h => src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h rename : src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp => src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp rename : src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp => src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp rename : src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h => src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.h rename : src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp => src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp rename : src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp => src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp rename : src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp => src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp rename : src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp => src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp rename : src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp => src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp rename : src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp => src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp rename : src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp => src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp rename : src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h => src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp => src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp rename : src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h => src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h rename : src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp => src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp rename : src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp => src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp rename : src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h => src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.h rename : src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp => src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp rename : src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp => src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp rename : src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h => src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h rename : src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp => src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp rename : src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp => src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp rename : src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp => src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_herald_volazj.cpp rename : src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp => src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp rename : src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp => src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp rename : src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp => src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp rename : src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h => src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h rename : src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp => src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp rename : src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp => src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp rename : src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp => src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp rename : src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp => src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp rename : src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp => src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp rename : src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp => src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp rename : src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp => src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp rename : src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp => src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp rename : src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp => src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp rename : src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h => src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h rename : src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp => src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp rename : src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp => src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp rename : src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp => src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp rename : src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp => src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp rename : src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h => src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h rename : src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp => src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp rename : src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp => src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp rename : src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp => src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp rename : src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp => src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp rename : src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h => src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h rename : src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp => src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp rename : src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp => src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp rename : src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp => src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp rename : src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp => src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp rename : src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h => src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h rename : src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp => src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp rename : src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp => src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp rename : src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp => src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp rename : src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp => src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp rename : src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp => src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp rename : src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp => src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp rename : src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h => src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h rename : src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp => src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp rename : src/server/scripts/Northrend/gundrak/boss_eck.cpp => src/server/scripts/Northrend/Gundrak/boss_eck.cpp rename : src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp => src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp rename : src/server/scripts/Northrend/gundrak/boss_moorabi.cpp => src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp rename : src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp => src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp rename : src/server/scripts/Northrend/gundrak/gundrak.h => src/server/scripts/Northrend/Gundrak/gundrak.h rename : src/server/scripts/Northrend/gundrak/instance_gundrak.cpp => src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp rename : src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp => src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp rename : src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp => src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp rename : src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp => src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp rename : src/server/scripts/Northrend/naxxramas/boss_gluth.cpp => src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp rename : src/server/scripts/Northrend/naxxramas/boss_gothik.cpp => src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp rename : src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp => src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp rename : src/server/scripts/Northrend/naxxramas/boss_heigan.cpp => src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp rename : src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp => src/server/scripts/Northrend/Naxxramas/boss_highlord_mograine.cpp rename : src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp => src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp rename : src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp => src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp rename : src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp => src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp rename : src/server/scripts/Northrend/naxxramas/boss_noth.cpp => src/server/scripts/Northrend/Naxxramas/boss_noth.cpp rename : src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp => src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp rename : src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp => src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp rename : src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp => src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp rename : src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp => src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp rename : src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp => src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp rename : src/server/scripts/Northrend/naxxramas/naxxramas.h => src/server/scripts/Northrend/Naxxramas/naxxramas.h rename : src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp => src/server/scripts/Northrend/ObsidianSanctum/boss_sartharion.cpp rename : src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp => src/server/scripts/Northrend/ObsidianSanctum/instance_obsidian_sanctum.cpp rename : src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h => src/server/scripts/Northrend/ObsidianSanctum/obsidian_sanctum.h rename : src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp => src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp rename : src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h => src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h rename : src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp => src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp rename : src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp => src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp rename : src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp => src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp rename : src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp => src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp rename : src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp => src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp rename : src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp => src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp rename : src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp => src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp rename : src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp => src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp rename : src/server/scripts/Northrend/nexus/nexus/nexus.h => src/server/scripts/Northrend/TheNexus/nexus/nexus.h rename : src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp => src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp rename : src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp => src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp rename : src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp => src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp rename : src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp => src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp rename : src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp => src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp rename : src/server/scripts/Northrend/nexus/oculus/oculus.cpp => src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp rename : src/server/scripts/Northrend/nexus/oculus/oculus.h => src/server/scripts/Northrend/TheNexus/oculus/oculus.h rename : src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp => src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp => src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp => src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp => src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h => src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h rename : src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp => src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp => src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp => src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp => src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp => src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp rename : src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h => src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h rename : src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp => src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_algalon.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_auriaya.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_freya.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_general_vezax.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_hodir.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_mimiron.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_thorim.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_xt002.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp => src/server/scripts/Northrend/Ulduar/ulduar/boss_yoggsaron.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp => src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp rename : src/server/scripts/Northrend/ulduar/ulduar/ulduar.h => src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h rename : src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp => src/server/scripts/Northrend/Ulduar/ulduar/ulduar_teleporter.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h => src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h rename : src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp => src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp rename : src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h => src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h rename : src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp => src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp rename : src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp => src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp rename : src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp => src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp rename : src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp => src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp rename : src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp => src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp rename : src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h => src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h rename : src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp => src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp rename : src/server/scripts/Northrend/violet_hold/boss_erekem.cpp => src/server/scripts/Northrend/VioletHold/boss_erekem.cpp rename : src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp => src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp rename : src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp => src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp rename : src/server/scripts/Northrend/violet_hold/boss_moragg.cpp => src/server/scripts/Northrend/VioletHold/boss_moragg.cpp rename : src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp => src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp rename : src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp => src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp rename : src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp => src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp rename : src/server/scripts/Northrend/violet_hold/violet_hold.cpp => src/server/scripts/Northrend/VioletHold/violet_hold.cpp rename : src/server/scripts/Northrend/violet_hold/violet_hold.h => src/server/scripts/Northrend/VioletHold/violet_hold.h rename : src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp => src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp rename : src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp => src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp rename : src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp => src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp rename : src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp => src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp rename : src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp => src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp rename : src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp => src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp rename : src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp => src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp rename : src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h => src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h rename : src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp => src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp rename : src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp => src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp rename : src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp => src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp rename : src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp => src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp rename : src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp => src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp rename : src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h => src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h rename : src/server/scripts/Outland/black_temple/black_temple.cpp => src/server/scripts/Outland/BlackTemple/black_temple.cpp rename : src/server/scripts/Outland/black_temple/black_temple.h => src/server/scripts/Outland/BlackTemple/black_temple.h rename : src/server/scripts/Outland/black_temple/boss_bloodboil.cpp => src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp rename : src/server/scripts/Outland/black_temple/boss_illidan.cpp => src/server/scripts/Outland/BlackTemple/boss_illidan.cpp rename : src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp => src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp rename : src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp => src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp rename : src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp => src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp rename : src/server/scripts/Outland/black_temple/boss_supremus.cpp => src/server/scripts/Outland/BlackTemple/boss_supremus.cpp rename : src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp => src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp rename : src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp => src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp rename : src/server/scripts/Outland/black_temple/illidari_council.cpp => src/server/scripts/Outland/BlackTemple/illidari_council.cpp rename : src/server/scripts/Outland/black_temple/instance_black_temple.cpp => src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp rename : src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp => src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp rename : src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp => src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp rename : src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp => src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp rename : src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp => src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp rename : src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp => src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp rename : src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp => src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp rename : src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp => src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp rename : src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h => src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h rename : src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp => src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp rename : src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp => src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp rename : src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp => src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp rename : src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp => src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp rename : src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h => src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h rename : src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp => src/server/scripts/Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp rename : src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp => src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp rename : src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp => src/server/scripts/Outland/GruulsLair/boss_gruul.cpp rename : src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp => src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp rename : src/server/scripts/Outland/gruuls_lair/gruuls_lair.h => src/server/scripts/Outland/GruulsLair/gruuls_lair.h rename : src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp => src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp rename : src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h => src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h rename : src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp => src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp rename : src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp => src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp rename : src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp => src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp rename : src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp => src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp rename : src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp => src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp rename : src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp => src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp rename : src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp => src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp rename : src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h => src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h rename : src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp => src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp rename : src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp => src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp rename : src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp => src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp rename : src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h => src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h rename : src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp => src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp rename : src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp => src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp rename : src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp => src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp rename : src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp => src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp rename : src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h => src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h rename : src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp => src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp rename : src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h => src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h rename : src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp => src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp rename : src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp => src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp rename : src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp => src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp rename : src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp => src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp rename : src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp => src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp rename : src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp => src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp rename : src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp => src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp rename : src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp => src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp rename : src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp => src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp rename : src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp => src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp rename : src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp => src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp rename : src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h => src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h rename : src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp => src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp rename : src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp => src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp rename : src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp => src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp rename : src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp => src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp rename : src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp => src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp rename : src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h => src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h --- .../AlteracValley/alterac_valley.cpp | 180 ++ .../EasternKingdoms/AlteracValley/boss_balinda.cpp | 203 ++ .../AlteracValley/boss_drekthar.cpp | 138 ++ .../AlteracValley/boss_galvangar.cpp | 129 ++ .../EasternKingdoms/AlteracValley/boss_vanndar.cpp | 129 ++ .../BlackrockDepths/blackrock_depths.cpp | 1338 ++++++++++++ .../BlackrockDepths/blackrock_depths.h | 45 + .../BlackrockDepths/boss_ambassador_flamelash.cpp | 91 + .../BlackrockDepths/boss_anubshiah.cpp | 116 + .../boss_emperor_dagran_thaurissan.cpp | 111 + .../BlackrockDepths/boss_general_angerforge.cpp | 132 ++ .../BlackrockDepths/boss_gorosh_the_dervish.cpp | 84 + .../BlackrockDepths/boss_grizzle.cpp | 94 + .../boss_high_interrogator_gerstahn.cpp | 106 + .../BlackrockDepths/boss_magmus.cpp | 98 + .../BlackrockDepths/boss_moira_bronzebeard.cpp | 98 + .../BlackrockDepths/boss_tomb_of_seven.cpp | 254 +++ .../BlackrockDepths/instance_blackrock_depths.cpp | 460 ++++ .../BlackrockSpire/blackrock_spire.cpp | 77 + .../BlackrockSpire/blackrock_spire.h | 26 + .../BlackrockSpire/boss_drakkisath.cpp | 102 + .../EasternKingdoms/BlackrockSpire/boss_gyth.cpp | 205 ++ .../BlackrockSpire/boss_halycon.cpp | 96 + .../BlackrockSpire/boss_highlord_omokk.cpp | 132 ++ .../BlackrockSpire/boss_mother_smolderweb.cpp | 87 + .../BlackrockSpire/boss_overlord_wyrmthalak.cpp | 126 ++ .../BlackrockSpire/boss_pyroguard_emberseer.cpp | 93 + .../BlackrockSpire/boss_quartermaster_zigris.cpp | 86 + .../BlackrockSpire/boss_rend_blackhand.cpp | 92 + .../boss_shadow_hunter_voshgajin.cpp | 93 + .../BlackrockSpire/boss_the_beast.cpp | 93 + .../BlackrockSpire/boss_warmaster_voone.cpp | 122 ++ .../BlackrockSpire/instance_blackrock_spire.cpp | 104 + .../BlackwingLair/boss_broodlord_lashlayer.cpp | 112 + .../BlackwingLair/boss_chromaggus.cpp | 301 +++ .../EasternKingdoms/BlackwingLair/boss_ebonroc.cpp | 104 + .../EasternKingdoms/BlackwingLair/boss_firemaw.cpp | 95 + .../BlackwingLair/boss_flamegor.cpp | 98 + .../BlackwingLair/boss_nefarian.cpp | 231 ++ .../BlackwingLair/boss_razorgore.cpp | 125 ++ .../BlackwingLair/boss_vaelastrasz.cpp | 262 +++ .../BlackwingLair/boss_victor_nefarius.cpp | 385 ++++ .../BlackwingLair/instance_blackwing_lair.cpp | 25 + .../EasternKingdoms/Deadmines/boss_mr_smite.cpp | 182 ++ .../EasternKingdoms/Deadmines/deadmines.cpp | 60 + .../scripts/EasternKingdoms/Deadmines/deadmines.h | 35 + .../Deadmines/instance_deadmines.cpp | 256 +++ .../EasternKingdoms/Gnomeregan/gnomeregan.cpp | 593 ++++++ .../EasternKingdoms/Gnomeregan/gnomeregan.h | 48 + .../Gnomeregan/instance_gnomeregan.cpp | 141 ++ .../EasternKingdoms/Karazhan/boss_curator.cpp | 196 ++ .../Karazhan/boss_maiden_of_virtue.cpp | 138 ++ .../EasternKingdoms/Karazhan/boss_midnight.cpp | 310 +++ .../EasternKingdoms/Karazhan/boss_moroes.cpp | 785 +++++++ .../EasternKingdoms/Karazhan/boss_netherspite.cpp | 343 +++ .../EasternKingdoms/Karazhan/boss_nightbane.cpp | 418 ++++ .../Karazhan/boss_prince_malchezaar.cpp | 604 ++++++ .../Karazhan/boss_shade_of_aran.cpp | 569 +++++ .../Karazhan/boss_terestian_illhoof.cpp | 417 ++++ .../EasternKingdoms/Karazhan/bosses_opera.cpp | 1494 +++++++++++++ .../EasternKingdoms/Karazhan/instance_karazhan.cpp | 308 +++ .../scripts/EasternKingdoms/Karazhan/karazhan.cpp | 646 ++++++ .../scripts/EasternKingdoms/Karazhan/karazhan.h | 53 + .../MagistersTerrace/boss_felblood_kaelthas.cpp | 680 ++++++ .../MagistersTerrace/boss_priestess_delrissa.cpp | 1321 ++++++++++++ .../MagistersTerrace/boss_selin_fireheart.cpp | 366 ++++ .../MagistersTerrace/boss_vexallus.cpp | 226 ++ .../instance_magisters_terrace.cpp | 205 ++ .../MagistersTerrace/magisters_terrace.cpp | 174 ++ .../MagistersTerrace/magisters_terrace.h | 31 + .../MoltenCore/boss_baron_geddon.cpp | 107 + .../EasternKingdoms/MoltenCore/boss_garr.cpp | 143 ++ .../EasternKingdoms/MoltenCore/boss_gehennas.cpp | 93 + .../EasternKingdoms/MoltenCore/boss_golemagg.cpp | 198 ++ .../EasternKingdoms/MoltenCore/boss_lucifron.cpp | 91 + .../EasternKingdoms/MoltenCore/boss_magmadar.cpp | 100 + .../MoltenCore/boss_majordomo_executus.cpp | 134 ++ .../EasternKingdoms/MoltenCore/boss_ragnaros.cpp | 297 +++ .../EasternKingdoms/MoltenCore/boss_shazzrah.cpp | 121 ++ .../MoltenCore/boss_sulfuron_harbinger.cpp | 205 ++ .../MoltenCore/instance_molten_core.cpp | 266 +++ .../EasternKingdoms/MoltenCore/molten_core.cpp | 81 + .../EasternKingdoms/MoltenCore/molten_core.h | 22 + .../EasternKingdoms/ScarletEnclave/chapter1.cpp | 1079 ++++++++++ .../EasternKingdoms/ScarletEnclave/chapter2.cpp | 995 +++++++++ .../EasternKingdoms/ScarletEnclave/chapter5.cpp | 1684 +++++++++++++++ .../ScarletEnclave/the_scarlet_enclave.cpp | 119 ++ .../ScarletMonastery/boss_arcanist_doan.cpp | 128 ++ .../ScarletMonastery/boss_azshir_the_sleepless.cpp | 98 + .../ScarletMonastery/boss_bloodmage_thalnos.cpp | 124 ++ .../ScarletMonastery/boss_headless_horseman.cpp | 892 ++++++++ .../ScarletMonastery/boss_herod.cpp | 158 ++ .../boss_high_inquisitor_fairbanks.cpp | 133 ++ .../ScarletMonastery/boss_houndmaster_loksey.cpp | 77 + .../ScarletMonastery/boss_interrogator_vishas.cpp | 118 + .../boss_mograine_and_whitemane.cpp | 359 ++++ .../ScarletMonastery/boss_scorn.cpp | 101 + .../instance_scarlet_monastery.cpp | 157 ++ .../ScarletMonastery/scarlet_monastery.h | 18 + .../Scholomance/boss_darkmaster_gandling.cpp | 225 ++ .../Scholomance/boss_death_knight_darkreaver.cpp | 58 + .../Scholomance/boss_doctor_theolen_krastinov.cpp | 117 + .../Scholomance/boss_illucia_barov.cpp | 117 + .../Scholomance/boss_instructor_malicia.cpp | 153 ++ .../Scholomance/boss_jandice_barov.cpp | 201 ++ .../EasternKingdoms/Scholomance/boss_kormok.cpp | 120 ++ .../Scholomance/boss_lord_alexei_barov.cpp | 99 + .../Scholomance/boss_lorekeeper_polkelt.cpp | 114 + .../Scholomance/boss_ras_frostwhisper.cpp | 123 ++ .../Scholomance/boss_the_ravenian.cpp | 117 + .../EasternKingdoms/Scholomance/boss_vectus.cpp | 105 + .../Scholomance/instance_scholomance.cpp | 146 ++ .../EasternKingdoms/Scholomance/scholomance.h | 17 + .../ShadowfangKeep/instance_shadowfang_keep.cpp | 277 +++ .../ShadowfangKeep/shadowfang_keep.cpp | 198 ++ .../ShadowfangKeep/shadowfang_keep.h | 17 + .../Stratholme/boss_baron_rivendare.cpp | 190 ++ .../Stratholme/boss_baroness_anastari.cpp | 127 ++ .../Stratholme/boss_cannon_master_willey.cpp | 220 ++ .../Stratholme/boss_dathrohan_balnazzar.cpp | 217 ++ .../Stratholme/boss_magistrate_barthilas.cpp | 128 ++ .../Stratholme/boss_maleki_the_pallid.cpp | 108 + .../EasternKingdoms/Stratholme/boss_nerubenkan.cpp | 121 ++ .../Stratholme/boss_order_of_silver_hand.cpp | 157 ++ .../Stratholme/boss_postmaster_malown.cpp | 144 ++ .../Stratholme/boss_ramstein_the_gorger.cpp | 102 + .../Stratholme/boss_timmy_the_cruel.cpp | 83 + .../Stratholme/instance_stratholme.cpp | 458 ++++ .../EasternKingdoms/Stratholme/stratholme.cpp | 282 +++ .../EasternKingdoms/Stratholme/stratholme.h | 28 + .../SunkenTemple/instance_sunken_temple.cpp | 204 ++ .../EasternKingdoms/SunkenTemple/sunken_temple.cpp | 71 + .../EasternKingdoms/SunkenTemple/sunken_temple.h | 22 + .../SunwellPlateau/boss_brutallus.cpp | 349 +++ .../SunwellPlateau/boss_eredar_twins.cpp | 762 +++++++ .../SunwellPlateau/boss_felmyst.cpp | 579 +++++ .../SunwellPlateau/boss_kalecgos.cpp | 794 +++++++ .../SunwellPlateau/boss_kiljaeden.cpp | 1408 ++++++++++++ .../EasternKingdoms/SunwellPlateau/boss_muru.cpp | 640 ++++++ .../SunwellPlateau/instance_sunwell_plateau.cpp | 297 +++ .../SunwellPlateau/sunwell_plateau.cpp | 65 + .../SunwellPlateau/sunwell_plateau.h | 95 + .../EasternKingdoms/Uldaman/boss_archaedas.cpp | 497 +++++ .../EasternKingdoms/Uldaman/boss_ironaya.cpp | 106 + .../EasternKingdoms/Uldaman/instance_uldaman.cpp | 300 +++ .../scripts/EasternKingdoms/Uldaman/uldaman.cpp | 205 ++ .../EasternKingdoms/ZulAman/boss_akilzon.cpp | 467 ++++ .../EasternKingdoms/ZulAman/boss_halazzi.cpp | 401 ++++ .../EasternKingdoms/ZulAman/boss_hexlord.cpp | 907 ++++++++ .../EasternKingdoms/ZulAman/boss_janalai.cpp | 687 ++++++ .../EasternKingdoms/ZulAman/boss_nalorakk.cpp | 451 ++++ .../EasternKingdoms/ZulAman/boss_zuljin.cpp | 623 ++++++ .../EasternKingdoms/ZulAman/instance_zulaman.cpp | 320 +++ .../scripts/EasternKingdoms/ZulAman/zulaman.cpp | 192 ++ .../scripts/EasternKingdoms/ZulAman/zulaman.h | 19 + .../EasternKingdoms/ZulGurub/boss_arlokk.cpp | 278 +++ .../EasternKingdoms/ZulGurub/boss_gahzranka.cpp | 93 + .../EasternKingdoms/ZulGurub/boss_grilek.cpp | 93 + .../EasternKingdoms/ZulGurub/boss_hakkar.cpp | 250 +++ .../EasternKingdoms/ZulGurub/boss_hazzarah.cpp | 104 + .../EasternKingdoms/ZulGurub/boss_jeklik.cpp | 291 +++ .../EasternKingdoms/ZulGurub/boss_jindo.cpp | 263 +++ .../EasternKingdoms/ZulGurub/boss_mandokir.cpp | 333 +++ .../EasternKingdoms/ZulGurub/boss_marli.cpp | 261 +++ .../EasternKingdoms/ZulGurub/boss_renataki.cpp | 152 ++ .../EasternKingdoms/ZulGurub/boss_thekal.cpp | 556 +++++ .../EasternKingdoms/ZulGurub/boss_venoxis.cpp | 199 ++ .../EasternKingdoms/ZulGurub/boss_wushoolay.cpp | 85 + .../EasternKingdoms/ZulGurub/instance_zulgurub.cpp | 159 ++ .../scripts/EasternKingdoms/ZulGurub/zulgurub.h | 28 + .../alterac_valley/alterac_valley.cpp | 180 -- .../alterac_valley/boss_balinda.cpp | 203 -- .../alterac_valley/boss_drekthar.cpp | 138 -- .../alterac_valley/boss_galvangar.cpp | 129 -- .../alterac_valley/boss_vanndar.cpp | 129 -- .../blackrock_depths/blackrock_depths.cpp | 1338 ------------ .../blackrock_depths/blackrock_depths.h | 45 - .../blackrock_depths/boss_ambassador_flamelash.cpp | 91 - .../blackrock_depths/boss_anubshiah.cpp | 116 - .../boss_emperor_dagran_thaurissan.cpp | 111 - .../blackrock_depths/boss_general_angerforge.cpp | 132 -- .../blackrock_depths/boss_gorosh_the_dervish.cpp | 84 - .../blackrock_depths/boss_grizzle.cpp | 94 - .../boss_high_interrogator_gerstahn.cpp | 106 - .../blackrock_depths/boss_magmus.cpp | 98 - .../blackrock_depths/boss_moira_bronzebeard.cpp | 98 - .../blackrock_depths/boss_tomb_of_seven.cpp | 254 --- .../blackrock_depths/instance_blackrock_depths.cpp | 460 ---- .../blackrock_spire/blackrock_spire.cpp | 77 - .../blackrock_spire/blackrock_spire.h | 26 - .../blackrock_spire/boss_drakkisath.cpp | 102 - .../EasternKingdoms/blackrock_spire/boss_gyth.cpp | 205 -- .../blackrock_spire/boss_halycon.cpp | 96 - .../blackrock_spire/boss_highlord_omokk.cpp | 132 -- .../blackrock_spire/boss_mother_smolderweb.cpp | 87 - .../blackrock_spire/boss_overlord_wyrmthalak.cpp | 126 -- .../blackrock_spire/boss_pyroguard_emberseer.cpp | 93 - .../blackrock_spire/boss_quartermaster_zigris.cpp | 86 - .../blackrock_spire/boss_rend_blackhand.cpp | 92 - .../boss_shadow_hunter_voshgajin.cpp | 93 - .../blackrock_spire/boss_the_beast.cpp | 93 - .../blackrock_spire/boss_warmaster_voone.cpp | 122 -- .../blackrock_spire/instance_blackrock_spire.cpp | 104 - .../blackwing_lair/boss_broodlord_lashlayer.cpp | 112 - .../blackwing_lair/boss_chromaggus.cpp | 301 --- .../blackwing_lair/boss_ebonroc.cpp | 104 - .../blackwing_lair/boss_firemaw.cpp | 95 - .../blackwing_lair/boss_flamegor.cpp | 98 - .../blackwing_lair/boss_nefarian.cpp | 231 -- .../blackwing_lair/boss_razorgore.cpp | 125 -- .../blackwing_lair/boss_vaelastrasz.cpp | 262 --- .../blackwing_lair/boss_victor_nefarius.cpp | 385 ---- .../blackwing_lair/instance_blackwing_lair.cpp | 25 - .../EasternKingdoms/deadmines/boss_mr_smite.cpp | 182 -- .../EasternKingdoms/deadmines/deadmines.cpp | 60 - .../scripts/EasternKingdoms/deadmines/deadmines.h | 35 - .../deadmines/instance_deadmines.cpp | 256 --- .../EasternKingdoms/gnomeregan/gnomeregan.cpp | 593 ------ .../EasternKingdoms/gnomeregan/gnomeregan.h | 48 - .../gnomeregan/instance_gnomeregan.cpp | 141 -- .../EasternKingdoms/karazhan/boss_curator.cpp | 196 -- .../karazhan/boss_maiden_of_virtue.cpp | 138 -- .../EasternKingdoms/karazhan/boss_midnight.cpp | 310 --- .../EasternKingdoms/karazhan/boss_moroes.cpp | 785 ------- .../EasternKingdoms/karazhan/boss_netherspite.cpp | 343 --- .../EasternKingdoms/karazhan/boss_nightbane.cpp | 418 ---- .../karazhan/boss_prince_malchezaar.cpp | 604 ------ .../karazhan/boss_shade_of_aran.cpp | 569 ----- .../karazhan/boss_terestian_illhoof.cpp | 417 ---- .../EasternKingdoms/karazhan/bosses_opera.cpp | 1494 ------------- .../EasternKingdoms/karazhan/instance_karazhan.cpp | 308 --- .../scripts/EasternKingdoms/karazhan/karazhan.cpp | 646 ------ .../scripts/EasternKingdoms/karazhan/karazhan.h | 53 - .../magisters_terrace/boss_felblood_kaelthas.cpp | 680 ------ .../magisters_terrace/boss_priestess_delrissa.cpp | 1321 ------------ .../magisters_terrace/boss_selin_fireheart.cpp | 366 ---- .../magisters_terrace/boss_vexallus.cpp | 226 -- .../instance_magisters_terrace.cpp | 205 -- .../magisters_terrace/magisters_terrace.cpp | 174 -- .../magisters_terrace/magisters_terrace.h | 31 - .../molten_core/boss_baron_geddon.cpp | 107 - .../EasternKingdoms/molten_core/boss_garr.cpp | 143 -- .../EasternKingdoms/molten_core/boss_gehennas.cpp | 93 - .../EasternKingdoms/molten_core/boss_golemagg.cpp | 198 -- .../EasternKingdoms/molten_core/boss_lucifron.cpp | 91 - .../EasternKingdoms/molten_core/boss_magmadar.cpp | 100 - .../molten_core/boss_majordomo_executus.cpp | 134 -- .../EasternKingdoms/molten_core/boss_ragnaros.cpp | 297 --- .../EasternKingdoms/molten_core/boss_shazzrah.cpp | 121 -- .../molten_core/boss_sulfuron_harbinger.cpp | 205 -- .../molten_core/instance_molten_core.cpp | 266 --- .../EasternKingdoms/molten_core/molten_core.cpp | 81 - .../EasternKingdoms/molten_core/molten_core.h | 22 - .../EasternKingdoms/scarlet_enclave/chapter1.cpp | 1079 ---------- .../EasternKingdoms/scarlet_enclave/chapter2.cpp | 995 --------- .../EasternKingdoms/scarlet_enclave/chapter5.cpp | 1684 --------------- .../scarlet_enclave/the_scarlet_enclave.cpp | 119 -- .../scarlet_monastery/boss_arcanist_doan.cpp | 128 -- .../boss_azshir_the_sleepless.cpp | 98 - .../scarlet_monastery/boss_bloodmage_thalnos.cpp | 124 -- .../scarlet_monastery/boss_headless_horseman.cpp | 892 -------- .../scarlet_monastery/boss_herod.cpp | 158 -- .../boss_high_inquisitor_fairbanks.cpp | 133 -- .../scarlet_monastery/boss_houndmaster_loksey.cpp | 77 - .../scarlet_monastery/boss_interrogator_vishas.cpp | 118 - .../boss_mograine_and_whitemane.cpp | 359 ---- .../scarlet_monastery/boss_scorn.cpp | 101 - .../instance_scarlet_monastery.cpp | 157 -- .../scarlet_monastery/scarlet_monastery.h | 18 - .../scholomance/boss_darkmaster_gandling.cpp | 225 -- .../scholomance/boss_death_knight_darkreaver.cpp | 58 - .../scholomance/boss_doctor_theolen_krastinov.cpp | 117 - .../scholomance/boss_illucia_barov.cpp | 117 - .../scholomance/boss_instructor_malicia.cpp | 153 -- .../scholomance/boss_jandice_barov.cpp | 201 -- .../EasternKingdoms/scholomance/boss_kormok.cpp | 120 -- .../scholomance/boss_lord_alexei_barov.cpp | 99 - .../scholomance/boss_lorekeeper_polkelt.cpp | 114 - .../scholomance/boss_ras_frostwhisper.cpp | 123 -- .../scholomance/boss_the_ravenian.cpp | 117 - .../EasternKingdoms/scholomance/boss_vectus.cpp | 105 - .../scholomance/instance_scholomance.cpp | 146 -- .../EasternKingdoms/scholomance/scholomance.h | 17 - .../shadowfang_keep/instance_shadowfang_keep.cpp | 277 --- .../shadowfang_keep/shadowfang_keep.cpp | 198 -- .../shadowfang_keep/shadowfang_keep.h | 17 - .../stratholme/boss_baron_rivendare.cpp | 190 -- .../stratholme/boss_baroness_anastari.cpp | 127 -- .../stratholme/boss_cannon_master_willey.cpp | 220 -- .../stratholme/boss_dathrohan_balnazzar.cpp | 217 -- .../stratholme/boss_magistrate_barthilas.cpp | 128 -- .../stratholme/boss_maleki_the_pallid.cpp | 108 - .../EasternKingdoms/stratholme/boss_nerubenkan.cpp | 121 -- .../stratholme/boss_order_of_silver_hand.cpp | 157 -- .../stratholme/boss_postmaster_malown.cpp | 144 -- .../stratholme/boss_ramstein_the_gorger.cpp | 102 - .../stratholme/boss_timmy_the_cruel.cpp | 83 - .../stratholme/instance_stratholme.cpp | 458 ---- .../EasternKingdoms/stratholme/stratholme.cpp | 282 --- .../EasternKingdoms/stratholme/stratholme.h | 28 - .../sunken_temple/instance_sunken_temple.cpp | 204 -- .../sunken_temple/sunken_temple.cpp | 71 - .../EasternKingdoms/sunken_temple/sunken_temple.h | 22 - .../sunwell_plateau/boss_brutallus.cpp | 349 --- .../sunwell_plateau/boss_eredar_twins.cpp | 762 ------- .../sunwell_plateau/boss_felmyst.cpp | 579 ----- .../sunwell_plateau/boss_kalecgos.cpp | 794 ------- .../sunwell_plateau/boss_kiljaeden.cpp | 1408 ------------ .../EasternKingdoms/sunwell_plateau/boss_muru.cpp | 640 ------ .../sunwell_plateau/instance_sunwell_plateau.cpp | 297 --- .../sunwell_plateau/sunwell_plateau.cpp | 65 - .../sunwell_plateau/sunwell_plateau.h | 95 - .../EasternKingdoms/uldaman/boss_archaedas.cpp | 497 ----- .../EasternKingdoms/uldaman/boss_ironaya.cpp | 106 - .../EasternKingdoms/uldaman/instance_uldaman.cpp | 300 --- .../scripts/EasternKingdoms/uldaman/uldaman.cpp | 205 -- .../EasternKingdoms/zulaman/boss_akilzon.cpp | 467 ---- .../EasternKingdoms/zulaman/boss_halazzi.cpp | 401 ---- .../EasternKingdoms/zulaman/boss_hexlord.cpp | 907 -------- .../EasternKingdoms/zulaman/boss_janalai.cpp | 687 ------ .../EasternKingdoms/zulaman/boss_nalorakk.cpp | 451 ---- .../EasternKingdoms/zulaman/boss_zuljin.cpp | 623 ------ .../EasternKingdoms/zulaman/instance_zulaman.cpp | 320 --- .../scripts/EasternKingdoms/zulaman/zulaman.cpp | 192 -- .../scripts/EasternKingdoms/zulaman/zulaman.h | 19 - .../EasternKingdoms/zulgurub/boss_arlokk.cpp | 278 --- .../EasternKingdoms/zulgurub/boss_gahzranka.cpp | 93 - .../EasternKingdoms/zulgurub/boss_grilek.cpp | 93 - .../EasternKingdoms/zulgurub/boss_hakkar.cpp | 250 --- .../EasternKingdoms/zulgurub/boss_hazzarah.cpp | 104 - .../EasternKingdoms/zulgurub/boss_jeklik.cpp | 291 --- .../EasternKingdoms/zulgurub/boss_jindo.cpp | 263 --- .../EasternKingdoms/zulgurub/boss_mandokir.cpp | 333 --- .../EasternKingdoms/zulgurub/boss_marli.cpp | 261 --- .../EasternKingdoms/zulgurub/boss_renataki.cpp | 152 -- .../EasternKingdoms/zulgurub/boss_thekal.cpp | 556 ----- .../EasternKingdoms/zulgurub/boss_venoxis.cpp | 199 -- .../EasternKingdoms/zulgurub/boss_wushoolay.cpp | 85 - .../EasternKingdoms/zulgurub/instance_zulgurub.cpp | 159 -- .../scripts/EasternKingdoms/zulgurub/zulgurub.h | 28 - .../BlackfathomDeeps/blackfathom_deeps.cpp | 252 +++ .../Kalimdor/BlackfathomDeeps/blackfathom_deeps.h | 53 + .../Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp | 94 + .../Kalimdor/BlackfathomDeeps/boss_gelihast.cpp | 85 + .../Kalimdor/BlackfathomDeeps/boss_kelris.cpp | 108 + .../instance_blackfathom_deeps.cpp | 259 +++ .../culling_of_stratholme/boss_epoch.cpp | 156 ++ .../culling_of_stratholme/boss_infinite.cpp | 88 + .../culling_of_stratholme/boss_mal_ganis.cpp | 262 +++ .../culling_of_stratholme/boss_meathook.cpp | 140 ++ .../culling_of_stratholme/boss_salramm.cpp | 170 ++ .../culling_of_stratholme.cpp | 1210 +++++++++++ .../culling_of_stratholme/culling_of_stratholme.h | 68 + .../instance_culling_of_stratholme.cpp | 244 +++ .../CavernsOfTime/dark_portal/boss_aeonus.cpp | 145 ++ .../dark_portal/boss_chrono_lord_deja.cpp | 154 ++ .../CavernsOfTime/dark_portal/boss_temporus.cpp | 152 ++ .../CavernsOfTime/dark_portal/dark_portal.cpp | 404 ++++ .../CavernsOfTime/dark_portal/dark_portal.h | 35 + .../dark_portal/instance_dark_portal.cpp | 346 +++ .../CavernsOfTime/hyjal/boss_anetheron.cpp | 309 +++ .../CavernsOfTime/hyjal/boss_archimonde.cpp | 635 ++++++ .../Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp | 285 +++ .../Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp | 197 ++ .../CavernsOfTime/hyjal/boss_rage_winterchill.cpp | 192 ++ .../scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp | 247 +++ .../scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h | 38 + .../Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp | 1157 ++++++++++ .../scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h | 248 +++ .../Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp | 1440 +++++++++++++ .../Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h | 35 + .../CavernsOfTime/hyjal/instance_hyjal.cpp | 324 +++ .../old_hillsbrad/boss_captain_skarloc.cpp | 152 ++ .../old_hillsbrad/boss_epoch_hunter.cpp | 138 ++ .../old_hillsbrad/boss_leutenant_drake.cpp | 190 ++ .../old_hillsbrad/instance_old_hillsbrad.cpp | 238 +++ .../CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp | 658 ++++++ .../CavernsOfTime/old_hillsbrad/old_hillsbrad.h | 19 + .../Kalimdor/Maraudon/boss_celebras_the_cursed.cpp | 98 + .../scripts/Kalimdor/Maraudon/boss_landslide.cpp | 95 + .../scripts/Kalimdor/Maraudon/boss_noxxion.cpp | 131 ++ .../Kalimdor/Maraudon/boss_princess_theradras.cpp | 109 + .../scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp | 500 +++++ .../Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp | 249 +++ .../scripts/Kalimdor/OnyxiasLair/onyxias_lair.h | 65 + .../boss_amnennar_the_coldbringer.cpp | 130 ++ .../RazorfenDowns/instance_razorfen_downs.cpp | 215 ++ .../Kalimdor/RazorfenDowns/razorfen_downs.cpp | 165 ++ .../Kalimdor/RazorfenDowns/razorfen_downs.h | 45 + .../RazorfenKraul/instance_razorfen_kraul.cpp | 104 + .../Kalimdor/RazorfenKraul/razorfen_kraul.cpp | 194 ++ .../Kalimdor/RazorfenKraul/razorfen_kraul.h | 21 + .../Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp | 125 ++ .../scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp | 72 + .../Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp | 143 ++ .../scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp | 162 ++ .../Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp | 79 + .../Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp | 85 + .../RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp | 213 ++ .../Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h | 34 + .../Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp | 346 +++ .../Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp | 1307 ++++++++++++ .../Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp | 206 ++ .../Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp | 148 ++ .../Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp | 140 ++ .../Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp | 297 +++ .../Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp | 298 +++ .../TempleOfAhnQiraj/boss_twinemperors.cpp | 596 ++++++ .../Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp | 30 + .../instance_temple_of_ahnqiraj.cpp | 166 ++ .../TempleOfAhnQiraj/mob_anubisath_sentinel.cpp | 296 +++ .../Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h | 23 + .../WailingCaverns/instance_wailing_caverns.cpp | 142 ++ .../Kalimdor/WailingCaverns/wailing_caverns.cpp | 396 ++++ .../Kalimdor/WailingCaverns/wailing_caverns.h | 24 + .../Kalimdor/ZulFarrak/instance_zulfarrak.cpp | 58 + .../scripts/Kalimdor/ZulFarrak/zulfarrak.cpp | 280 +++ .../blackfathom_depths/blackfathom_deeps.cpp | 252 --- .../blackfathom_depths/blackfathom_deeps.h | 53 - .../Kalimdor/blackfathom_depths/boss_aku_mai.cpp | 94 - .../Kalimdor/blackfathom_depths/boss_gelihast.cpp | 85 - .../Kalimdor/blackfathom_depths/boss_kelris.cpp | 108 - .../instance_blackfathom_deeps.cpp | 259 --- .../culling_of_stratholme/boss_epoch.cpp | 156 -- .../culling_of_stratholme/boss_infinite.cpp | 88 - .../culling_of_stratholme/boss_mal_ganis.cpp | 262 --- .../culling_of_stratholme/boss_meathook.cpp | 140 -- .../culling_of_stratholme/boss_salramm.cpp | 170 -- .../culling_of_stratholme.cpp | 1210 ----------- .../culling_of_stratholme/culling_of_stratholme.h | 68 - .../instance_culling_of_stratholme.cpp | 244 --- .../caverns_of_time/dark_portal/boss_aeonus.cpp | 145 -- .../dark_portal/boss_chrono_lord_deja.cpp | 154 -- .../caverns_of_time/dark_portal/boss_temporus.cpp | 152 -- .../caverns_of_time/dark_portal/dark_portal.cpp | 404 ---- .../caverns_of_time/dark_portal/dark_portal.h | 35 - .../dark_portal/instance_dark_portal.cpp | 346 --- .../caverns_of_time/hyjal/boss_anetheron.cpp | 309 --- .../caverns_of_time/hyjal/boss_archimonde.cpp | 635 ------ .../caverns_of_time/hyjal/boss_azgalor.cpp | 285 --- .../caverns_of_time/hyjal/boss_kazrogal.cpp | 197 -- .../hyjal/boss_rage_winterchill.cpp | 192 -- .../Kalimdor/caverns_of_time/hyjal/hyjal.cpp | 247 --- .../scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h | 38 - .../Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp | 1157 ---------- .../Kalimdor/caverns_of_time/hyjal/hyjalAI.h | 248 --- .../Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp | 1440 ------------- .../Kalimdor/caverns_of_time/hyjal/hyjal_trash.h | 35 - .../caverns_of_time/hyjal/instance_hyjal.cpp | 324 --- .../old_hillsbrad/boss_captain_skarloc.cpp | 152 -- .../old_hillsbrad/boss_epoch_hunter.cpp | 138 -- .../old_hillsbrad/boss_leutenant_drake.cpp | 190 -- .../old_hillsbrad/instance_old_hillsbrad.cpp | 238 --- .../old_hillsbrad/old_hillsbrad.cpp | 658 ------ .../caverns_of_time/old_hillsbrad/old_hillsbrad.h | 19 - .../Kalimdor/maraudon/boss_celebras_the_cursed.cpp | 98 - .../scripts/Kalimdor/maraudon/boss_landslide.cpp | 95 - .../scripts/Kalimdor/maraudon/boss_noxxion.cpp | 131 -- .../Kalimdor/maraudon/boss_princess_theradras.cpp | 109 - .../scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp | 500 ----- .../onyxias_lair/instance_onyxias_lair.cpp | 249 --- .../scripts/Kalimdor/onyxias_lair/onyxias_lair.h | 65 - .../boss_amnennar_the_coldbringer.cpp | 130 -- .../razorfen_downs/instance_razorfen_downs.cpp | 215 -- .../Kalimdor/razorfen_downs/razorfen_downs.cpp | 165 -- .../Kalimdor/razorfen_downs/razorfen_downs.h | 45 - .../razorfen_kraul/instance_razorfen_kraul.cpp | 104 - .../Kalimdor/razorfen_kraul/razorfen_kraul.cpp | 194 -- .../Kalimdor/razorfen_kraul/razorfen_kraul.h | 21 - .../Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp | 125 -- .../Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp | 72 - .../Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp | 143 -- .../Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp | 162 -- .../Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp | 79 - .../Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp | 85 - .../instance_ruins_of_ahnqiraj.cpp | 213 -- .../Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h | 34 - .../Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp | 346 --- .../Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp | 1307 ------------ .../Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp | 206 -- .../Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp | 148 -- .../Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp | 140 -- .../Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp | 297 --- .../Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp | 298 --- .../temple_of_ahnqiraj/boss_twinemperors.cpp | 596 ------ .../Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp | 30 - .../instance_temple_of_ahnqiraj.cpp | 166 -- .../temple_of_ahnqiraj/mob_anubisath_sentinel.cpp | 296 --- .../temple_of_ahnqiraj/temple_of_ahnqiraj.h | 23 - .../wailing_caverns/instance_wailing_caverns.cpp | 142 -- .../Kalimdor/wailing_caverns/wailing_caverns.cpp | 396 ---- .../Kalimdor/wailing_caverns/wailing_caverns.h | 24 - .../Kalimdor/zulfarrak/instance_zulfarrak.cpp | 58 - .../scripts/Kalimdor/zulfarrak/zulfarrak.cpp | 280 --- .../Northrend/AzjolNerub/ahnkahet/ahnkahet.h | 52 + .../AzjolNerub/ahnkahet/boss_amanitar.cpp | 226 ++ .../AzjolNerub/ahnkahet/boss_elder_nadox.cpp | 283 +++ .../AzjolNerub/ahnkahet/boss_herald_volazj.cpp | 328 +++ .../ahnkahet/boss_jedoga_shadowseeker.cpp | 588 +++++ .../AzjolNerub/ahnkahet/boss_prince_taldaram.cpp | 412 ++++ .../AzjolNerub/ahnkahet/instance_ahnkahet.cpp | 313 +++ .../Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h | 38 + .../AzjolNerub/azjol_nerub/boss_anubarak.cpp | 360 ++++ .../AzjolNerub/azjol_nerub/boss_hadronox.cpp | 206 ++ .../azjol_nerub/boss_krikthir_the_gatewatcher.cpp | 553 +++++ .../azjol_nerub/instance_azjol_nerub.cpp | 215 ++ .../boss_argent_challenge.cpp | 512 +++++ .../trial_of_the_champion/boss_black_knight.cpp | 373 ++++ .../trial_of_the_champion/boss_grand_champions.cpp | 993 +++++++++ .../instance_trial_of_the_champion.cpp | 340 +++ .../trial_of_the_champion.cpp | 512 +++++ .../trial_of_the_champion/trial_of_the_champion.h | 115 + .../scripts/Northrend/DraktharonKeep/boss_dred.cpp | 270 +++ .../Northrend/DraktharonKeep/boss_novos.cpp | 328 +++ .../Northrend/DraktharonKeep/boss_tharon_ja.cpp | 260 +++ .../Northrend/DraktharonKeep/boss_trollgore.cpp | 197 ++ .../Northrend/DraktharonKeep/drak_tharon_keep.h | 40 + .../DraktharonKeep/instance_drak_tharon_keep.cpp | 243 +++ .../FrozenHalls/forge_of_souls/boss_bronjahm.cpp | 263 +++ .../forge_of_souls/boss_devourer_of_souls.cpp | 349 +++ .../FrozenHalls/forge_of_souls/forge_of_souls.cpp | 899 ++++++++ .../FrozenHalls/forge_of_souls/forge_of_souls.h | 52 + .../forge_of_souls/instance_forge_of_souls.cpp | 168 ++ .../halls_of_reflection/boss_falric.cpp | 142 ++ .../halls_of_reflection/boss_marwyn.cpp | 133 ++ .../halls_of_reflection/halls_of_reflection.cpp | 1022 +++++++++ .../halls_of_reflection/halls_of_reflection.h | 156 ++ .../instance_halls_of_reflection.cpp | 431 ++++ .../pit_of_saron/boss_forgemaster_garfrost.cpp | 209 ++ .../FrozenHalls/pit_of_saron/boss_krickandick.cpp | 482 +++++ .../pit_of_saron/boss_scourgelord_tyrannus.cpp | 273 +++ .../pit_of_saron/instance_pit_of_saron.cpp | 236 ++ .../FrozenHalls/pit_of_saron/pit_of_saron.cpp | 1101 ++++++++++ .../FrozenHalls/pit_of_saron/pit_of_saron.h | 63 + .../Northrend/Gundrak/boss_drakkari_colossus.cpp | 317 +++ src/server/scripts/Northrend/Gundrak/boss_eck.cpp | 168 ++ .../scripts/Northrend/Gundrak/boss_gal_darah.cpp | 288 +++ .../scripts/Northrend/Gundrak/boss_moorabi.cpp | 175 ++ .../scripts/Northrend/Gundrak/boss_slad_ran.cpp | 266 +++ src/server/scripts/Northrend/Gundrak/gundrak.h | 54 + .../scripts/Northrend/Gundrak/instance_gundrak.cpp | 536 +++++ .../Northrend/Naxxramas/boss_anubrekhan.cpp | 185 ++ .../scripts/Northrend/Naxxramas/boss_faerlina.cpp | 218 ++ .../Northrend/Naxxramas/boss_four_horsemen.cpp | 397 ++++ .../scripts/Northrend/Naxxramas/boss_gluth.cpp | 147 ++ .../scripts/Northrend/Naxxramas/boss_gothik.cpp | 582 +++++ .../scripts/Northrend/Naxxramas/boss_grobbulus.cpp | 142 ++ .../scripts/Northrend/Naxxramas/boss_heigan.cpp | 149 ++ .../Northrend/Naxxramas/boss_highlord_mograine.cpp | 179 ++ .../scripts/Northrend/Naxxramas/boss_kelthuzad.cpp | 706 ++++++ .../scripts/Northrend/Naxxramas/boss_loatheb.cpp | 125 ++ .../scripts/Northrend/Naxxramas/boss_maexxna.cpp | 186 ++ .../scripts/Northrend/Naxxramas/boss_noth.cpp | 212 ++ .../scripts/Northrend/Naxxramas/boss_patchwerk.cpp | 159 ++ .../scripts/Northrend/Naxxramas/boss_razuvious.cpp | 139 ++ .../scripts/Northrend/Naxxramas/boss_sapphiron.cpp | 403 ++++ .../scripts/Northrend/Naxxramas/boss_thaddius.cpp | 400 ++++ .../Northrend/Naxxramas/instance_naxxramas.cpp | 324 +++ src/server/scripts/Northrend/Naxxramas/naxxramas.h | 75 + .../Northrend/ObsidianSanctum/boss_sartharion.cpp | 1421 +++++++++++++ .../ObsidianSanctum/instance_obsidian_sanctum.cpp | 97 + .../Northrend/ObsidianSanctum/obsidian_sanctum.h | 20 + .../TheNexus/eye_of_eternity/boss_malygos.cpp | 175 ++ .../TheNexus/eye_of_eternity/eye_of_eternity.h | 4 + .../eye_of_eternity/instance_eye_of_eternity.cpp | 21 + .../Northrend/TheNexus/nexus/boss_anomalus.cpp | 253 +++ .../Northrend/TheNexus/nexus/boss_keristrasza.cpp | 247 +++ .../TheNexus/nexus/boss_magus_telestra.cpp | 327 +++ .../Northrend/TheNexus/nexus/boss_ormorok.cpp | 298 +++ .../Northrend/TheNexus/nexus/commander_kolurg.cpp | 58 + .../TheNexus/nexus/commander_stoutbeard.cpp | 64 + .../Northrend/TheNexus/nexus/instance_nexus.cpp | 259 +++ .../scripts/Northrend/TheNexus/nexus/nexus.h | 35 + .../Northrend/TheNexus/oculus/boss_drakos.cpp | 218 ++ .../Northrend/TheNexus/oculus/boss_eregos.cpp | 129 ++ .../Northrend/TheNexus/oculus/boss_urom.cpp | 356 ++++ .../Northrend/TheNexus/oculus/boss_varos.cpp | 105 + .../Northrend/TheNexus/oculus/instance_oculus.cpp | 205 ++ .../scripts/Northrend/TheNexus/oculus/oculus.cpp | 174 ++ .../scripts/Northrend/TheNexus/oculus/oculus.h | 34 + .../Ulduar/halls_of_lightning/boss_bjarngrim.cpp | 432 ++++ .../Ulduar/halls_of_lightning/boss_ionar.cpp | 388 ++++ .../Ulduar/halls_of_lightning/boss_loken.cpp | 222 ++ .../Ulduar/halls_of_lightning/boss_volkhan.cpp | 478 +++++ .../Ulduar/halls_of_lightning/halls_of_lightning.h | 34 + .../instance_halls_of_lightning.cpp | 248 +++ .../Ulduar/halls_of_stone/boss_krystallus.cpp | 148 ++ .../Ulduar/halls_of_stone/boss_maiden_of_grief.cpp | 166 ++ .../Ulduar/halls_of_stone/boss_sjonnir.cpp | 300 +++ .../Ulduar/halls_of_stone/halls_of_stone.cpp | 724 +++++++ .../Ulduar/halls_of_stone/halls_of_stone.h | 48 + .../halls_of_stone/instance_halls_of_stone.cpp | 254 +++ .../Northrend/Ulduar/ulduar/boss_algalon.cpp | 384 ++++ .../Ulduar/ulduar/boss_assembly_of_iron.cpp | 589 +++++ .../Northrend/Ulduar/ulduar/boss_auriaya.cpp | 106 + .../Ulduar/ulduar/boss_flame_leviathan.cpp | 574 +++++ .../scripts/Northrend/Ulduar/ulduar/boss_freya.cpp | 125 ++ .../Northrend/Ulduar/ulduar/boss_general_vezax.cpp | 31 + .../scripts/Northrend/Ulduar/ulduar/boss_hodir.cpp | 89 + .../scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp | 137 ++ .../Northrend/Ulduar/ulduar/boss_kologarn.cpp | 166 ++ .../Northrend/Ulduar/ulduar/boss_mimiron.cpp | 44 + .../Northrend/Ulduar/ulduar/boss_razorscale.cpp | 331 +++ .../Northrend/Ulduar/ulduar/boss_thorim.cpp | 103 + .../scripts/Northrend/Ulduar/ulduar/boss_xt002.cpp | 850 ++++++++ .../Northrend/Ulduar/ulduar/boss_yoggsaron.cpp | 55 + .../Northrend/Ulduar/ulduar/instance_ulduar.cpp | 408 ++++ .../scripts/Northrend/Ulduar/ulduar/ulduar.h | 71 + .../Northrend/Ulduar/ulduar/ulduar_teleporter.cpp | 92 + .../utgarde_keep/boss_ingvar_the_plunderer.cpp | 442 ++++ .../UtgardeKeep/utgarde_keep/boss_keleseth.cpp | 361 ++++ .../utgarde_keep/boss_skarvald_dalronn.cpp | 389 ++++ .../utgarde_keep/instance_utgarde_keep.cpp | 312 +++ .../UtgardeKeep/utgarde_keep/utgarde_keep.cpp | 160 ++ .../UtgardeKeep/utgarde_keep/utgarde_keep.h | 35 + .../UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp | 830 ++++++++ .../UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp | 477 +++++ .../UtgardeKeep/utgarde_pinnacle/boss_svala.cpp | 408 ++++ .../UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp | 367 ++++ .../utgarde_pinnacle/instance_pinnacle.cpp | 241 +++ .../utgarde_pinnacle/utgarde_pinnacle.h | 42 + .../Northrend/VaultOfArchavon/boss_archavon.cpp | 218 ++ .../Northrend/VaultOfArchavon/boss_emalon.cpp | 270 +++ .../Northrend/VaultOfArchavon/boss_koralon.cpp | 222 ++ .../Northrend/VaultOfArchavon/boss_toravon.cpp | 301 +++ .../VaultOfArchavon/instance_vault_of_archavon.cpp | 143 ++ .../Northrend/VaultOfArchavon/vault_of_archavon.h | 28 + .../Northrend/VioletHold/boss_cyanigosa.cpp | 156 ++ .../scripts/Northrend/VioletHold/boss_erekem.cpp | 329 +++ .../scripts/Northrend/VioletHold/boss_ichoron.cpp | 394 ++++ .../Northrend/VioletHold/boss_lavanthor.cpp | 155 ++ .../scripts/Northrend/VioletHold/boss_moragg.cpp | 133 ++ .../scripts/Northrend/VioletHold/boss_xevozz.cpp | 307 +++ .../scripts/Northrend/VioletHold/boss_zuramat.cpp | 178 ++ .../Northrend/VioletHold/instance_violet_hold.cpp | 528 +++++ .../scripts/Northrend/VioletHold/violet_hold.cpp | 274 +++ .../scripts/Northrend/VioletHold/violet_hold.h | 71 + .../Northrend/azjol_nerub/ahnkahet/ahnkahet.h | 52 - .../azjol_nerub/ahnkahet/boss_amanitar.cpp | 226 -- .../azjol_nerub/ahnkahet/boss_elder_nadox.cpp | 283 --- .../azjol_nerub/ahnkahet/boss_herald_volazj.cpp | 328 --- .../ahnkahet/boss_jedoga_shadowseeker.cpp | 588 ----- .../azjol_nerub/ahnkahet/boss_prince_taldaram.cpp | 412 ---- .../azjol_nerub/ahnkahet/instance_ahnkahet.cpp | 313 --- .../azjol_nerub/azjol_nerub/azjol_nerub.h | 38 - .../azjol_nerub/azjol_nerub/boss_anubarak.cpp | 360 ---- .../azjol_nerub/azjol_nerub/boss_hadronox.cpp | 206 -- .../azjol_nerub/boss_krikthir_the_gatewatcher.cpp | 553 ----- .../azjol_nerub/instance_azjol_nerub.cpp | 215 -- .../boss_argent_challenge.cpp | 512 ----- .../trial_of_the_champion/boss_black_knight.cpp | 373 ---- .../trial_of_the_champion/boss_grand_champions.cpp | 993 --------- .../instance_trial_of_the_champion.cpp | 340 --- .../trial_of_the_champion.cpp | 512 ----- .../trial_of_the_champion/trial_of_the_champion.h | 115 - .../Northrend/draktharon_keep/boss_dred.cpp | 270 --- .../Northrend/draktharon_keep/boss_novos.cpp | 328 --- .../Northrend/draktharon_keep/boss_tharon_ja.cpp | 260 --- .../Northrend/draktharon_keep/boss_trollgore.cpp | 197 -- .../Northrend/draktharon_keep/drak_tharon_keep.h | 40 - .../draktharon_keep/instance_drak_tharon_keep.cpp | 243 --- .../frozen_halls/forge_of_souls/boss_bronjahm.cpp | 263 --- .../forge_of_souls/boss_devourer_of_souls.cpp | 349 --- .../frozen_halls/forge_of_souls/forge_of_souls.cpp | 899 -------- .../frozen_halls/forge_of_souls/forge_of_souls.h | 52 - .../forge_of_souls/instance_forge_of_souls.cpp | 168 -- .../halls_of_reflection/boss_falric.cpp | 142 -- .../halls_of_reflection/boss_marwyn.cpp | 133 -- .../halls_of_reflection/halls_of_reflection.cpp | 1022 --------- .../halls_of_reflection/halls_of_reflection.h | 156 -- .../instance_halls_of_reflection.cpp | 431 ---- .../pit_of_saron/boss_forgemaster_garfrost.cpp | 209 -- .../frozen_halls/pit_of_saron/boss_krickandick.cpp | 482 ----- .../pit_of_saron/boss_scourgelord_tyrannus.cpp | 273 --- .../pit_of_saron/instance_pit_of_saron.cpp | 236 -- .../frozen_halls/pit_of_saron/pit_of_saron.cpp | 1101 ---------- .../frozen_halls/pit_of_saron/pit_of_saron.h | 63 - .../Northrend/gundrak/boss_drakkari_colossus.cpp | 317 --- src/server/scripts/Northrend/gundrak/boss_eck.cpp | 168 -- .../scripts/Northrend/gundrak/boss_gal_darah.cpp | 288 --- .../scripts/Northrend/gundrak/boss_moorabi.cpp | 175 -- .../scripts/Northrend/gundrak/boss_slad_ran.cpp | 266 --- src/server/scripts/Northrend/gundrak/gundrak.h | 54 - .../scripts/Northrend/gundrak/instance_gundrak.cpp | 536 ----- .../Northrend/naxxramas/boss_anubrekhan.cpp | 185 -- .../scripts/Northrend/naxxramas/boss_faerlina.cpp | 218 -- .../Northrend/naxxramas/boss_four_horsemen.cpp | 397 ---- .../scripts/Northrend/naxxramas/boss_gluth.cpp | 147 -- .../scripts/Northrend/naxxramas/boss_gothik.cpp | 582 ----- .../scripts/Northrend/naxxramas/boss_grobbulus.cpp | 142 -- .../scripts/Northrend/naxxramas/boss_heigan.cpp | 149 -- .../Northrend/naxxramas/boss_highlord_mograine.cpp | 179 -- .../scripts/Northrend/naxxramas/boss_kelthuzad.cpp | 706 ------ .../scripts/Northrend/naxxramas/boss_loatheb.cpp | 125 -- .../scripts/Northrend/naxxramas/boss_maexxna.cpp | 186 -- .../scripts/Northrend/naxxramas/boss_noth.cpp | 212 -- .../scripts/Northrend/naxxramas/boss_patchwerk.cpp | 159 -- .../scripts/Northrend/naxxramas/boss_razuvious.cpp | 139 -- .../scripts/Northrend/naxxramas/boss_sapphiron.cpp | 403 ---- .../scripts/Northrend/naxxramas/boss_thaddius.cpp | 400 ---- .../Northrend/naxxramas/instance_naxxramas.cpp | 324 --- src/server/scripts/Northrend/naxxramas/naxxramas.h | 75 - .../nexus/eye_of_eternity/boss_malygos.cpp | 175 -- .../nexus/eye_of_eternity/eye_of_eternity.h | 4 - .../eye_of_eternity/instance_eye_of_eternity.cpp | 21 - .../Northrend/nexus/nexus/boss_anomalus.cpp | 253 --- .../Northrend/nexus/nexus/boss_keristrasza.cpp | 247 --- .../Northrend/nexus/nexus/boss_magus_telestra.cpp | 327 --- .../scripts/Northrend/nexus/nexus/boss_ormorok.cpp | 298 --- .../Northrend/nexus/nexus/commander_kolurg.cpp | 58 - .../Northrend/nexus/nexus/commander_stoutbeard.cpp | 64 - .../Northrend/nexus/nexus/instance_nexus.cpp | 259 --- src/server/scripts/Northrend/nexus/nexus/nexus.h | 35 - .../scripts/Northrend/nexus/oculus/boss_drakos.cpp | 218 -- .../scripts/Northrend/nexus/oculus/boss_eregos.cpp | 129 -- .../scripts/Northrend/nexus/oculus/boss_urom.cpp | 356 ---- .../scripts/Northrend/nexus/oculus/boss_varos.cpp | 105 - .../Northrend/nexus/oculus/instance_oculus.cpp | 205 -- .../scripts/Northrend/nexus/oculus/oculus.cpp | 174 -- src/server/scripts/Northrend/nexus/oculus/oculus.h | 34 - .../Northrend/obsidian_sanctum/boss_sartharion.cpp | 1421 ------------- .../obsidian_sanctum/instance_obsidian_sanctum.cpp | 97 - .../Northrend/obsidian_sanctum/obsidian_sanctum.h | 20 - .../ulduar/halls_of_lightning/boss_bjarngrim.cpp | 432 ---- .../ulduar/halls_of_lightning/boss_ionar.cpp | 388 ---- .../ulduar/halls_of_lightning/boss_loken.cpp | 222 -- .../ulduar/halls_of_lightning/boss_volkhan.cpp | 478 ----- .../ulduar/halls_of_lightning/halls_of_lightning.h | 34 - .../instance_halls_of_lightning.cpp | 248 --- .../ulduar/halls_of_stone/boss_krystallus.cpp | 148 -- .../ulduar/halls_of_stone/boss_maiden_of_grief.cpp | 166 -- .../ulduar/halls_of_stone/boss_sjonnir.cpp | 300 --- .../ulduar/halls_of_stone/halls_of_stone.cpp | 724 ------- .../ulduar/halls_of_stone/halls_of_stone.h | 48 - .../halls_of_stone/instance_halls_of_stone.cpp | 254 --- .../Northrend/ulduar/ulduar/boss_algalon.cpp | 384 ---- .../ulduar/ulduar/boss_assembly_of_iron.cpp | 589 ----- .../Northrend/ulduar/ulduar/boss_auriaya.cpp | 106 - .../ulduar/ulduar/boss_flame_leviathan.cpp | 574 ----- .../scripts/Northrend/ulduar/ulduar/boss_freya.cpp | 125 -- .../Northrend/ulduar/ulduar/boss_general_vezax.cpp | 31 - .../scripts/Northrend/ulduar/ulduar/boss_hodir.cpp | 89 - .../scripts/Northrend/ulduar/ulduar/boss_ignis.cpp | 137 -- .../Northrend/ulduar/ulduar/boss_kologarn.cpp | 166 -- .../Northrend/ulduar/ulduar/boss_mimiron.cpp | 44 - .../Northrend/ulduar/ulduar/boss_razorscale.cpp | 331 --- .../Northrend/ulduar/ulduar/boss_thorim.cpp | 103 - .../scripts/Northrend/ulduar/ulduar/boss_xt002.cpp | 850 -------- .../Northrend/ulduar/ulduar/boss_yoggsaron.cpp | 55 - .../Northrend/ulduar/ulduar/instance_ulduar.cpp | 408 ---- .../scripts/Northrend/ulduar/ulduar/ulduar.h | 71 - .../Northrend/ulduar/ulduar/ulduar_teleporter.cpp | 92 - .../utgarde_keep/boss_ingvar_the_plunderer.cpp | 442 ---- .../utgarde_keep/utgarde_keep/boss_keleseth.cpp | 361 ---- .../utgarde_keep/boss_skarvald_dalronn.cpp | 389 ---- .../utgarde_keep/instance_utgarde_keep.cpp | 312 --- .../utgarde_keep/utgarde_keep/utgarde_keep.cpp | 160 -- .../utgarde_keep/utgarde_keep/utgarde_keep.h | 35 - .../utgarde_pinnacle/boss_palehoof.cpp | 830 -------- .../utgarde_keep/utgarde_pinnacle/boss_skadi.cpp | 477 ----- .../utgarde_keep/utgarde_pinnacle/boss_svala.cpp | 408 ---- .../utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp | 367 ---- .../utgarde_pinnacle/instance_pinnacle.cpp | 241 --- .../utgarde_pinnacle/utgarde_pinnacle.h | 42 - .../Northrend/vault_of_archavon/boss_archavon.cpp | 218 -- .../Northrend/vault_of_archavon/boss_emalon.cpp | 270 --- .../Northrend/vault_of_archavon/boss_koralon.cpp | 222 -- .../Northrend/vault_of_archavon/boss_toravon.cpp | 301 --- .../instance_vault_of_archavon.cpp | 143 -- .../vault_of_archavon/vault_of_archavon.h | 28 - .../Northrend/violet_hold/boss_cyanigosa.cpp | 156 -- .../scripts/Northrend/violet_hold/boss_erekem.cpp | 329 --- .../scripts/Northrend/violet_hold/boss_ichoron.cpp | 394 ---- .../Northrend/violet_hold/boss_lavanthor.cpp | 155 -- .../scripts/Northrend/violet_hold/boss_moragg.cpp | 133 -- .../scripts/Northrend/violet_hold/boss_xevozz.cpp | 307 --- .../scripts/Northrend/violet_hold/boss_zuramat.cpp | 178 -- .../Northrend/violet_hold/instance_violet_hold.cpp | 528 ----- .../scripts/Northrend/violet_hold/violet_hold.cpp | 274 --- .../scripts/Northrend/violet_hold/violet_hold.h | 71 - .../auchenai_crypts/boss_exarch_maladaar.cpp | 348 +++ .../boss_shirrak_the_dead_watcher.cpp | 211 ++ .../mana_tombs/boss_nexusprince_shaffar.cpp | 358 ++++ .../Auchindoun/mana_tombs/boss_pandemonius.cpp | 126 ++ .../sethekk_halls/boss_darkweaver_syth.cpp | 414 ++++ .../sethekk_halls/boss_tailonking_ikiss.cpp | 213 ++ .../sethekk_halls/instance_sethekk_halls.cpp | 91 + .../Auchindoun/sethekk_halls/sethekk_halls.h | 14 + .../shadow_labyrinth/boss_ambassador_hellmaw.cpp | 206 ++ .../boss_blackheart_the_inciter.cpp | 169 ++ .../shadow_labyrinth/boss_grandmaster_vorpil.cpp | 313 +++ .../Auchindoun/shadow_labyrinth/boss_murmur.cpp | 205 ++ .../shadow_labyrinth/instance_shadow_labyrinth.cpp | 227 ++ .../Auchindoun/shadow_labyrinth/shadow_labyrinth.h | 15 + .../scripts/Outland/BlackTemple/black_temple.cpp | 69 + .../scripts/Outland/BlackTemple/black_temple.h | 39 + .../scripts/Outland/BlackTemple/boss_bloodboil.cpp | 332 +++ .../scripts/Outland/BlackTemple/boss_illidan.cpp | 2248 ++++++++++++++++++++ .../Outland/BlackTemple/boss_mother_shahraz.cpp | 302 +++ .../BlackTemple/boss_reliquary_of_souls.cpp | 690 ++++++ .../Outland/BlackTemple/boss_shade_of_akama.cpp | 871 ++++++++ .../scripts/Outland/BlackTemple/boss_supremus.cpp | 296 +++ .../Outland/BlackTemple/boss_teron_gorefiend.cpp | 508 +++++ .../Outland/BlackTemple/boss_warlord_najentus.cpp | 226 ++ .../Outland/BlackTemple/illidari_council.cpp | 874 ++++++++ .../Outland/BlackTemple/instance_black_temple.cpp | 346 +++ .../serpent_shrine/boss_fathomlord_karathress.cpp | 746 +++++++ .../serpent_shrine/boss_hydross_the_unstable.cpp | 379 ++++ .../serpent_shrine/boss_lady_vashj.cpp | 1039 +++++++++ .../serpent_shrine/boss_leotheras_the_blind.cpp | 787 +++++++ .../serpent_shrine/boss_lurker_below.cpp | 458 ++++ .../serpent_shrine/boss_morogrim_tidewalker.cpp | 369 ++++ .../serpent_shrine/instance_serpent_shrine.cpp | 398 ++++ .../serpent_shrine/serpent_shrine.h | 45 + .../steam_vault/boss_hydromancer_thespia.cpp | 187 ++ .../steam_vault/boss_mekgineer_steamrigger.cpp | 264 +++ .../steam_vault/boss_warlord_kalithresh.cpp | 204 ++ .../steam_vault/instance_steam_vault.cpp | 231 ++ .../CoilfangReservoir/steam_vault/steam_vault.h | 17 + .../CoilfangReservoir/underbog/boss_hungarfen.cpp | 154 ++ .../underbog/boss_the_black_stalker.cpp | 185 ++ .../scripts/Outland/GruulsLair/boss_gruul.cpp | 255 +++ .../Outland/GruulsLair/boss_high_king_maulgar.cpp | 783 +++++++ .../scripts/Outland/GruulsLair/gruuls_lair.h | 21 + .../Outland/GruulsLair/instance_gruuls_lair.cpp | 193 ++ .../HellfireCitadel/blood_furnace/blood_furnace.h | 29 + .../HellfireCitadel/blood_furnace/boss_broggok.cpp | 131 ++ .../blood_furnace/boss_kelidan_the_breaker.cpp | 356 ++++ .../blood_furnace/boss_the_maker.cpp | 152 ++ .../blood_furnace/instance_blood_furnace.cpp | 232 ++ .../hellfire_ramparts/boss_omor_the_unscarred.cpp | 206 ++ .../hellfire_ramparts/boss_vazruden_the_herald.cpp | 467 ++++ .../boss_watchkeeper_gargolmar.cpp | 156 ++ .../hellfire_ramparts/hellfire_ramparts.h | 16 + .../instance_hellfire_ramparts.cpp | 84 + .../magtheridons_lair/boss_magtheridon.cpp | 570 +++++ .../instance_magtheridons_lair.cpp | 254 +++ .../magtheridons_lair/magtheridons_lair.h | 14 + .../shattered_halls/boss_nethekurse.cpp | 396 ++++ .../shattered_halls/boss_warbringer_omrogg.cpp | 404 ++++ .../boss_warchief_kargath_bladefist.cpp | 288 +++ .../shattered_halls/instance_shattered_halls.cpp | 114 + .../shattered_halls/shattered_halls.h | 14 + .../Outland/TempestKeep/arcatraz/arcatraz.cpp | 520 +++++ .../Outland/TempestKeep/arcatraz/arcatraz.h | 21 + .../arcatraz/boss_harbinger_skyriss.cpp | 293 +++ .../TempestKeep/arcatraz/instance_arcatraz.cpp | 240 +++ .../botanica/boss_high_botanist_freywinn.cpp | 191 ++ .../Outland/TempestKeep/botanica/boss_laj.cpp | 205 ++ .../TempestKeep/botanica/boss_warp_splinter.cpp | 216 ++ .../Outland/TempestKeep/the_eye/boss_alar.cpp | 523 +++++ .../TempestKeep/the_eye/boss_astromancer.cpp | 466 ++++ .../Outland/TempestKeep/the_eye/boss_kaelthas.cpp | 1498 +++++++++++++ .../TempestKeep/the_eye/boss_void_reaver.cpp | 179 ++ .../TempestKeep/the_eye/instance_the_eye.cpp | 176 ++ .../Outland/TempestKeep/the_eye/the_eye.cpp | 98 + .../scripts/Outland/TempestKeep/the_eye/the_eye.h | 20 + .../the_mechanar/boss_gatewatcher_gyrokill.cpp | 39 + .../the_mechanar/boss_gatewatcher_ironhand.cpp | 130 ++ .../the_mechanar/boss_nethermancer_sepethrea.cpp | 245 +++ .../the_mechanar/boss_pathaleon_the_calculator.cpp | 246 +++ .../TempestKeep/the_mechanar/instance_mechanar.cpp | 86 + .../Outland/TempestKeep/the_mechanar/mechanar.h | 6 + .../auchenai_crypts/boss_exarch_maladaar.cpp | 348 --- .../boss_shirrak_the_dead_watcher.cpp | 211 -- .../mana_tombs/boss_nexusprince_shaffar.cpp | 358 ---- .../auchindoun/mana_tombs/boss_pandemonius.cpp | 126 -- .../sethekk_halls/boss_darkweaver_syth.cpp | 414 ---- .../sethekk_halls/boss_tailonking_ikiss.cpp | 213 -- .../sethekk_halls/instance_sethekk_halls.cpp | 91 - .../auchindoun/sethekk_halls/sethekk_halls.h | 14 - .../shadow_labyrinth/boss_ambassador_hellmaw.cpp | 206 -- .../boss_blackheart_the_inciter.cpp | 169 -- .../shadow_labyrinth/boss_grandmaster_vorpil.cpp | 313 --- .../auchindoun/shadow_labyrinth/boss_murmur.cpp | 205 -- .../shadow_labyrinth/instance_shadow_labyrinth.cpp | 227 -- .../auchindoun/shadow_labyrinth/shadow_labyrinth.h | 15 - .../scripts/Outland/black_temple/black_temple.cpp | 69 - .../scripts/Outland/black_temple/black_temple.h | 39 - .../Outland/black_temple/boss_bloodboil.cpp | 332 --- .../scripts/Outland/black_temple/boss_illidan.cpp | 2248 -------------------- .../Outland/black_temple/boss_mother_shahraz.cpp | 302 --- .../black_temple/boss_reliquary_of_souls.cpp | 690 ------ .../Outland/black_temple/boss_shade_of_akama.cpp | 871 -------- .../scripts/Outland/black_temple/boss_supremus.cpp | 296 --- .../Outland/black_temple/boss_teron_gorefiend.cpp | 508 ----- .../Outland/black_temple/boss_warlord_najentus.cpp | 226 -- .../Outland/black_temple/illidari_council.cpp | 874 -------- .../Outland/black_temple/instance_black_temple.cpp | 346 --- .../serpent_shrine/boss_fathomlord_karathress.cpp | 746 ------- .../serpent_shrine/boss_hydross_the_unstable.cpp | 379 ---- .../serpent_shrine/boss_lady_vashj.cpp | 1039 --------- .../serpent_shrine/boss_leotheras_the_blind.cpp | 787 ------- .../serpent_shrine/boss_lurker_below.cpp | 458 ---- .../serpent_shrine/boss_morogrim_tidewalker.cpp | 369 ---- .../serpent_shrine/instance_serpent_shrine.cpp | 398 ---- .../serpent_shrine/serpent_shrine.h | 45 - .../steam_vault/boss_hydromancer_thespia.cpp | 187 -- .../steam_vault/boss_mekgineer_steamrigger.cpp | 264 --- .../steam_vault/boss_warlord_kalithresh.cpp | 204 -- .../steam_vault/instance_steam_vault.cpp | 231 -- .../coilfang_resevoir/steam_vault/steam_vault.h | 17 - .../coilfang_resevoir/underbog/boss_hungarfen.cpp | 154 -- .../underbog/boss_the_black_stalker.cpp | 185 -- .../scripts/Outland/gruuls_lair/boss_gruul.cpp | 255 --- .../Outland/gruuls_lair/boss_high_king_maulgar.cpp | 783 ------- .../scripts/Outland/gruuls_lair/gruuls_lair.h | 21 - .../Outland/gruuls_lair/instance_gruuls_lair.cpp | 193 -- .../hellfire_citadel/blood_furnace/blood_furnace.h | 29 - .../blood_furnace/boss_broggok.cpp | 131 -- .../blood_furnace/boss_kelidan_the_breaker.cpp | 356 ---- .../blood_furnace/boss_the_maker.cpp | 152 -- .../blood_furnace/instance_blood_furnace.cpp | 232 -- .../hellfire_ramparts/boss_omor_the_unscarred.cpp | 206 -- .../hellfire_ramparts/boss_vazruden_the_herald.cpp | 467 ---- .../boss_watchkeeper_gargolmar.cpp | 156 -- .../hellfire_ramparts/hellfire_ramparts.h | 16 - .../instance_hellfire_ramparts.cpp | 84 - .../magtheridons_lair/boss_magtheridon.cpp | 570 ----- .../instance_magtheridons_lair.cpp | 254 --- .../magtheridons_lair/magtheridons_lair.h | 14 - .../shattered_halls/boss_nethekurse.cpp | 396 ---- .../shattered_halls/boss_warbringer_omrogg.cpp | 404 ---- .../boss_warchief_kargath_bladefist.cpp | 288 --- .../shattered_halls/instance_shattered_halls.cpp | 114 - .../shattered_halls/shattered_halls.h | 14 - .../Outland/tempest_keep/arcatraz/arcatraz.cpp | 520 ----- .../Outland/tempest_keep/arcatraz/arcatraz.h | 21 - .../arcatraz/boss_harbinger_skyriss.cpp | 293 --- .../tempest_keep/arcatraz/instance_arcatraz.cpp | 240 --- .../botanica/boss_high_botanist_freywinn.cpp | 191 -- .../Outland/tempest_keep/botanica/boss_laj.cpp | 205 -- .../tempest_keep/botanica/boss_warp_splinter.cpp | 216 -- .../Outland/tempest_keep/the_eye/boss_alar.cpp | 523 ----- .../tempest_keep/the_eye/boss_astromancer.cpp | 466 ---- .../Outland/tempest_keep/the_eye/boss_kaelthas.cpp | 1498 ------------- .../tempest_keep/the_eye/boss_void_reaver.cpp | 179 -- .../tempest_keep/the_eye/instance_the_eye.cpp | 176 -- .../Outland/tempest_keep/the_eye/the_eye.cpp | 98 - .../scripts/Outland/tempest_keep/the_eye/the_eye.h | 20 - .../the_mechanar/boss_gatewatcher_gyrokill.cpp | 39 - .../the_mechanar/boss_gatewatcher_ironhand.cpp | 130 -- .../the_mechanar/boss_nethermancer_sepethrea.cpp | 245 --- .../the_mechanar/boss_pathaleon_the_calculator.cpp | 246 --- .../the_mechanar/instance_mechanar.cpp | 86 - .../Outland/tempest_keep/the_mechanar/mechanar.h | 6 - 946 files changed, 128507 insertions(+), 128507 deletions(-) create mode 100644 src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp create mode 100644 src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp create mode 100644 src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp create mode 100644 src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp create mode 100644 src/server/scripts/EasternKingdoms/AlteracValley/boss_vanndar.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.h create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_ambassador_flamelash.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_anubshiah.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_general_angerforge.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_gorosh_the_dervish.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_grizzle.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_high_interrogator_gerstahn.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_magmus.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_moira_bronzebeard.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/boss_tomb_of_seven.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockDepths/instance_blackrock_depths.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_halycon.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_highlord_omokk.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_mother_smolderweb.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_overlord_wyrmthalak.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_quartermaster_zigris.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_shadow_hunter_voshgajin.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_the_beast.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/boss_warmaster_voone.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp create mode 100644 src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp create mode 100644 src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp create mode 100644 src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp create mode 100644 src/server/scripts/EasternKingdoms/Deadmines/deadmines.h create mode 100644 src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp create mode 100644 src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp create mode 100644 src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h create mode 100644 src/server/scripts/EasternKingdoms/Gnomeregan/instance_gnomeregan.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp create mode 100644 src/server/scripts/EasternKingdoms/Karazhan/karazhan.h create mode 100644 src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp create mode 100644 src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp create mode 100644 src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp create mode 100644 src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp create mode 100644 src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp create mode 100644 src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp create mode 100644 src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_baron_geddon.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_garr.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_gehennas.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_lucifron.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_magmadar.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_majordomo_executus.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_ragnaros.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_shazzrah.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/instance_molten_core.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/molten_core.cpp create mode 100644 src/server/scripts/EasternKingdoms/MoltenCore/molten_core.h create mode 100644 src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp create mode 100644 src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_death_knight_darkreaver.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_doctor_theolen_krastinov.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_instructor_malicia.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_kormok.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_lord_alexei_barov.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_lorekeeper_polkelt.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_the_ravenian.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/boss_vectus.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/instance_scholomance.cpp create mode 100644 src/server/scripts/EasternKingdoms/Scholomance/scholomance.h create mode 100644 src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp create mode 100644 src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp create mode 100644 src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_baroness_anastari.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_cannon_master_willey.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_dathrohan_balnazzar.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_magistrate_barthilas.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_maleki_the_pallid.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_nerubenkan.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_order_of_silver_hand.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_postmaster_malown.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_ramstein_the_gorger.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/boss_timmy_the_cruel.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp create mode 100644 src/server/scripts/EasternKingdoms/Stratholme/stratholme.h create mode 100644 src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.cpp create mode 100644 src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h create mode 100644 src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp create mode 100644 src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp create mode 100644 src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp create mode 100644 src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulAman/zulaman.h create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp create mode 100644 src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h delete mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp delete mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp delete mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp delete mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp delete mode 100644 src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp delete mode 100644 src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp delete mode 100644 src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp delete mode 100644 src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp delete mode 100644 src/server/scripts/EasternKingdoms/deadmines/deadmines.h delete mode 100644 src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp delete mode 100644 src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp delete mode 100644 src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h delete mode 100644 src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp delete mode 100644 src/server/scripts/EasternKingdoms/karazhan/karazhan.h delete mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp delete mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp delete mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp delete mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp delete mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp delete mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp delete mode 100644 src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp delete mode 100644 src/server/scripts/EasternKingdoms/molten_core/molten_core.h delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp delete mode 100644 src/server/scripts/EasternKingdoms/scholomance/scholomance.h delete mode 100644 src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp delete mode 100644 src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp delete mode 100644 src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp delete mode 100644 src/server/scripts/EasternKingdoms/stratholme/stratholme.h delete mode 100644 src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp delete mode 100644 src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h delete mode 100644 src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp delete mode 100644 src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp delete mode 100644 src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp delete mode 100644 src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulaman/zulaman.h delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp delete mode 100644 src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h create mode 100644 src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp create mode 100644 src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.h create mode 100644 src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp create mode 100644 src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp create mode 100644 src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp create mode 100644 src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h create mode 100644 src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp create mode 100644 src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp create mode 100644 src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp create mode 100644 src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp create mode 100644 src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp create mode 100644 src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp create mode 100644 src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h create mode 100644 src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp create mode 100644 src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp create mode 100644 src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp create mode 100644 src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h create mode 100644 src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp create mode 100644 src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp create mode 100644 src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.h create mode 100644 src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp create mode 100644 src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp create mode 100644 src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp create mode 100644 src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp create mode 100644 src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp create mode 100644 src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp create mode 100644 src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp create mode 100644 src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp create mode 100644 src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h create mode 100644 src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp create mode 100644 src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp create mode 100644 src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.h create mode 100644 src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp create mode 100644 src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp delete mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp delete mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h delete mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp delete mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp delete mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp delete mode 100644 src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp delete mode 100644 src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h delete mode 100644 src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp delete mode 100644 src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp delete mode 100644 src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp delete mode 100644 src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp delete mode 100644 src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp delete mode 100644 src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp delete mode 100644 src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h delete mode 100644 src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp delete mode 100644 src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp delete mode 100644 src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp delete mode 100644 src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h delete mode 100644 src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp delete mode 100644 src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp delete mode 100644 src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h delete mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp delete mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp delete mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp delete mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp delete mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp delete mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp delete mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp delete mode 100644 src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp delete mode 100644 src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h delete mode 100644 src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp delete mode 100644 src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp delete mode 100644 src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h delete mode 100644 src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp delete mode 100644 src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h create mode 100644 src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_herald_volazj.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h create mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h create mode 100644 src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp create mode 100644 src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp create mode 100644 src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp create mode 100644 src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp create mode 100644 src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h create mode 100644 src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h create mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h create mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h create mode 100644 src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp create mode 100644 src/server/scripts/Northrend/Gundrak/boss_eck.cpp create mode 100644 src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp create mode 100644 src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp create mode 100644 src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp create mode 100644 src/server/scripts/Northrend/Gundrak/gundrak.h create mode 100644 src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_highlord_mograine.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_noth.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp create mode 100644 src/server/scripts/Northrend/Naxxramas/naxxramas.h create mode 100644 src/server/scripts/Northrend/ObsidianSanctum/boss_sartharion.cpp create mode 100644 src/server/scripts/Northrend/ObsidianSanctum/instance_obsidian_sanctum.cpp create mode 100644 src/server/scripts/Northrend/ObsidianSanctum/obsidian_sanctum.h create mode 100644 src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h create mode 100644 src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/nexus/nexus.h create mode 100644 src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp create mode 100644 src/server/scripts/Northrend/TheNexus/oculus/oculus.h create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h create mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_algalon.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_auriaya.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_freya.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_general_vezax.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_hodir.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_mimiron.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_thorim.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_xt002.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/boss_yoggsaron.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h create mode 100644 src/server/scripts/Northrend/Ulduar/ulduar/ulduar_teleporter.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h create mode 100644 src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp create mode 100644 src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp create mode 100644 src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp create mode 100644 src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp create mode 100644 src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp create mode 100644 src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h create mode 100644 src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/boss_erekem.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/boss_moragg.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/violet_hold.cpp create mode 100644 src/server/scripts/Northrend/VioletHold/violet_hold.h delete mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h delete mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h delete mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp delete mode 100644 src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp delete mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp delete mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp delete mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp delete mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp delete mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp delete mode 100644 src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h delete mode 100644 src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp delete mode 100644 src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp delete mode 100644 src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp delete mode 100644 src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp delete mode 100644 src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h delete mode 100644 src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h delete mode 100644 src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h delete mode 100644 src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp delete mode 100644 src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h delete mode 100644 src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp delete mode 100644 src/server/scripts/Northrend/gundrak/boss_eck.cpp delete mode 100644 src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp delete mode 100644 src/server/scripts/Northrend/gundrak/boss_moorabi.cpp delete mode 100644 src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp delete mode 100644 src/server/scripts/Northrend/gundrak/gundrak.h delete mode 100644 src/server/scripts/Northrend/gundrak/instance_gundrak.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_gluth.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_gothik.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_heigan.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_noth.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp delete mode 100644 src/server/scripts/Northrend/naxxramas/naxxramas.h delete mode 100644 src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp delete mode 100644 src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h delete mode 100644 src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp delete mode 100644 src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp delete mode 100644 src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp delete mode 100644 src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp delete mode 100644 src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp delete mode 100644 src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp delete mode 100644 src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp delete mode 100644 src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp delete mode 100644 src/server/scripts/Northrend/nexus/nexus/nexus.h delete mode 100644 src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp delete mode 100644 src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp delete mode 100644 src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp delete mode 100644 src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp delete mode 100644 src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp delete mode 100644 src/server/scripts/Northrend/nexus/oculus/oculus.cpp delete mode 100644 src/server/scripts/Northrend/nexus/oculus/oculus.h delete mode 100644 src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp delete mode 100644 src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp delete mode 100644 src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h delete mode 100644 src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/ulduar.h delete mode 100644 src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp delete mode 100644 src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h delete mode 100644 src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp delete mode 100644 src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp delete mode 100644 src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp delete mode 100644 src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp delete mode 100644 src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp delete mode 100644 src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h delete mode 100644 src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/boss_erekem.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/boss_moragg.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/violet_hold.cpp delete mode 100644 src/server/scripts/Northrend/violet_hold/violet_hold.h create mode 100644 src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h create mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h create mode 100644 src/server/scripts/Outland/BlackTemple/black_temple.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/black_temple.h create mode 100644 src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_illidan.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_supremus.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/illidari_council.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h create mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h create mode 100644 src/server/scripts/Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp create mode 100644 src/server/scripts/Outland/GruulsLair/boss_gruul.cpp create mode 100644 src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp create mode 100644 src/server/scripts/Outland/GruulsLair/gruuls_lair.h create mode 100644 src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h create mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h create mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h create mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h create mode 100644 src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h create mode 100644 src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h create mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h delete mode 100644 src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h delete mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp delete mode 100644 src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h delete mode 100644 src/server/scripts/Outland/black_temple/black_temple.cpp delete mode 100644 src/server/scripts/Outland/black_temple/black_temple.h delete mode 100644 src/server/scripts/Outland/black_temple/boss_bloodboil.cpp delete mode 100644 src/server/scripts/Outland/black_temple/boss_illidan.cpp delete mode 100644 src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp delete mode 100644 src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp delete mode 100644 src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp delete mode 100644 src/server/scripts/Outland/black_temple/boss_supremus.cpp delete mode 100644 src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp delete mode 100644 src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp delete mode 100644 src/server/scripts/Outland/black_temple/illidari_council.cpp delete mode 100644 src/server/scripts/Outland/black_temple/instance_black_temple.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp delete mode 100644 src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp delete mode 100644 src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp delete mode 100644 src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp delete mode 100644 src/server/scripts/Outland/gruuls_lair/gruuls_lair.h delete mode 100644 src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h delete mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h delete mode 100644 src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h delete mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp delete mode 100644 src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h delete mode 100644 src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h delete mode 100644 src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h delete mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp delete mode 100644 src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h (limited to 'src/server') diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp new file mode 100644 index 00000000000..a61fc21d5ba --- /dev/null +++ b/src/server/scripts/EasternKingdoms/AlteracValley/alterac_valley.cpp @@ -0,0 +1,180 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_CHARGE = 22911, + SPELL_CLEAVE = 40504, + SPELL_DEMORALIZING_SHOUT = 23511, + SPELL_ENRAGE = 8599, + SPELL_WHIRLWIND1 = 15589, + SPELL_WHIRLWIND2 = 13736, + SPELL_NORTH_MARSHAL = 45828, + SPELL_SOUTH_MARSHAL = 45829, + SPELL_STONEHEARTH_MARSHAL = 45830, + SPELL_ICEWING_MARSHAL = 45831, + SPELL_ICEBLOOD_WARMASTER = 45822, + SPELL_TOWER_POINT_WARMASTER = 45823, + SPELL_WEST_FROSTWOLF_WARMASTER = 45824, + SPELL_EAST_FROSTWOLF_WARMASTER = 45826 +}; + +enum Creatures +{ + NPC_NORTH_MARSHAL = 14762, + NPC_SOUTH_MARSHAL = 14763, + NPC_ICEWING_MARSHAL = 14764, + NPC_STONEHEARTH_MARSHAL = 14765, + NPC_EAST_FROSTWOLF_WARMASTER = 14772, + NPC_ICEBLOOD_WARMASTER = 14773, + NPC_TOWER_POINT_WARMASTER = 14776, + NPC_WEST_FROSTWOLF_WARMASTER = 14777 +}; + +struct mob_av_marshal_or_warmasterAI : public ScriptedAI +{ + mob_av_marshal_or_warmasterAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiChargeTimer; + uint32 uiCleaveTimer; + uint32 uiDemoralizingShoutTimer; + uint32 uiWhirlwind1Timer; + uint32 uiWhirlwind2Timer; + uint32 uiEnrageTimer; + uint32 uiResetTimer; + + bool bHasAura; + + void Reset() + { + uiChargeTimer = urand(2*IN_MILISECONDS,12*IN_MILISECONDS); + uiCleaveTimer = urand(1*IN_MILISECONDS,11*IN_MILISECONDS); + uiDemoralizingShoutTimer = urand(2*IN_MILISECONDS,2*IN_MILISECONDS); + uiWhirlwind1Timer = urand(1*IN_MILISECONDS,12*IN_MILISECONDS); + uiWhirlwind2Timer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); + uiEnrageTimer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); + uiResetTimer = 5*IN_MILISECONDS; + + bHasAura = false; + } + + void JustRespawned() + { + Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!bHasAura) + { + switch(me->GetEntry()) + { + case NPC_NORTH_MARSHAL: + DoCast(me,SPELL_NORTH_MARSHAL); + break; + case NPC_SOUTH_MARSHAL: + DoCast(me,SPELL_SOUTH_MARSHAL); + break; + case NPC_STONEHEARTH_MARSHAL: + DoCast(me,SPELL_STONEHEARTH_MARSHAL); + break; + case NPC_ICEWING_MARSHAL: + DoCast(me,SPELL_ICEWING_MARSHAL); + break; + case NPC_EAST_FROSTWOLF_WARMASTER: + DoCast(me,SPELL_EAST_FROSTWOLF_WARMASTER); + break; + case NPC_WEST_FROSTWOLF_WARMASTER: + DoCast(me,SPELL_WEST_FROSTWOLF_WARMASTER); + break; + case NPC_ICEBLOOD_WARMASTER: + DoCast(me,SPELL_ICEBLOOD_WARMASTER); + break; + case NPC_TOWER_POINT_WARMASTER: + DoCast(me,SPELL_TOWER_POINT_WARMASTER); + break; + } + + bHasAura = true; + } + + if (!UpdateVictim()) + return; + + if (uiChargeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CHARGE); + uiChargeTimer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiChargeTimer -= diff; + + if (uiCleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + uiCleaveTimer = urand(10*IN_MILISECONDS,16*IN_MILISECONDS); + } else uiCleaveTimer -= diff; + + if (uiDemoralizingShoutTimer <= diff) + { + DoCast(me->getVictim(), SPELL_DEMORALIZING_SHOUT); + uiDemoralizingShoutTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiDemoralizingShoutTimer -= diff; + + if (uiWhirlwind1Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND1); + uiWhirlwind1Timer = urand(6*IN_MILISECONDS,20*IN_MILISECONDS); + } else uiWhirlwind1Timer -= diff; + + if (uiWhirlwind2Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND2); + uiWhirlwind2Timer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiWhirlwind2Timer -= diff; + + if (uiEnrageTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ENRAGE); + uiEnrageTimer = urand(10*IN_MILISECONDS,30*IN_MILISECONDS); + }else uiEnrageTimer -= diff; + + + // check if creature is not outside of building + if (uiResetTimer <= diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + EnterEvadeMode(); + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_av_marshal_or_warmaster(Creature *_Creature) +{ + return new mob_av_marshal_or_warmasterAI (_Creature); +} + +void AddSC_alterac_valley() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_av_marshal_or_warmaster"; + newscript->GetAI = &GetAI_mob_av_marshal_or_warmaster; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp new file mode 100644 index 00000000000..ce2a81c864a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp @@ -0,0 +1,203 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_ARCANE_EXPLOSION = 46608, + SPELL_CONE_OF_COLD = 38384, + SPELL_FIREBALL = 46988, + SPELL_FROSTBOLT = 46987 +}; + +enum Yells +{ + YELL_AGGRO = -2100019, + YELL_EVADE = -2100020 +}; + +enum Creatures +{ + NPC_WATER_ELEMENTAL = 25040 +}; + +enum WaterElementalSpells +{ + SPELL_WATERBOLT = 46983 +}; + +struct mob_water_elementalAI : public ScriptedAI +{ + mob_water_elementalAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWaterBoltTimer; + uint64 uiBalindaGUID; + uint32 uiResetTimer; + + void Reset() + { + uiWaterBoltTimer = 3*IN_MILISECONDS; + uiResetTimer = 5*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWaterBoltTimer < diff) + { + DoCast(me->getVictim(), SPELL_WATERBOLT); + uiWaterBoltTimer = 5*IN_MILISECONDS; + } else uiWaterBoltTimer -= diff; + + // check if creature is not outside of building + if (uiResetTimer < diff) + { + if (Creature *pBalinda = Unit::GetCreature(*me, uiBalindaGUID)) + if (me->GetDistance2d(pBalinda->GetHomePosition().GetPositionX(), pBalinda->GetHomePosition().GetPositionY()) > 50) + EnterEvadeMode(); + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_balindaAI : public ScriptedAI +{ + boss_balindaAI(Creature *c) : ScriptedAI(c), Summons(me) {} + + uint32 uiArcaneExplosionTimer; + uint32 uiConeOfColdTimer; + uint32 uiFireBoltTimer; + uint32 uiFrostboltTimer; + uint32 uiResetTimer; + uint32 uiWaterElementalTimer; + + SummonList Summons; + + void Reset() + { + uiArcaneExplosionTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); + uiConeOfColdTimer = 8*IN_MILISECONDS; + uiFireBoltTimer = 1*IN_MILISECONDS; + uiFrostboltTimer = 4*IN_MILISECONDS; + uiResetTimer = 5*IN_MILISECONDS; + uiWaterElementalTimer = 0; + + Summons.DespawnAll(); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + } + + void JustRespawned() + { + Reset(); + } + + void JustSummoned(Creature* summoned) + { + ((mob_water_elementalAI*)summoned->AI())->uiBalindaGUID = me->GetGUID(); + summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); + summoned->setFaction(me->getFaction()); + Summons.Summon(summoned); + } + + void JustDied(Unit* /*Killer*/) + { + Summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWaterElementalTimer < diff) + { + if (Summons.empty()) + me->SummonCreature(NPC_WATER_ELEMENTAL, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45*IN_MILISECONDS); + uiWaterElementalTimer = 50*IN_MILISECONDS; + } else uiWaterElementalTimer -= diff; + + if (uiArcaneExplosionTimer < diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); + uiArcaneExplosionTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiArcaneExplosionTimer -= diff; + + if (uiConeOfColdTimer < diff) + { + DoCast(me->getVictim(), SPELL_CONE_OF_COLD); + uiConeOfColdTimer = urand(10*IN_MILISECONDS,20*IN_MILISECONDS); + } else uiConeOfColdTimer -= diff; + + if (uiFireBoltTimer < diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL); + uiFireBoltTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); + } else uiFireBoltTimer -= diff; + + if (uiFrostboltTimer < diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + uiFrostboltTimer = urand(4*IN_MILISECONDS,12*IN_MILISECONDS); + } else uiFrostboltTimer -= diff; + + + // check if creature is not outside of building + if (uiResetTimer < diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + { + EnterEvadeMode(); + DoScriptText(YELL_EVADE, me); + } + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_balinda(Creature *_Creature) +{ + return new boss_balindaAI (_Creature); +} + +CreatureAI* GetAI_mob_water_elemental(Creature *_Creature) +{ + return new mob_water_elementalAI (_Creature); +} + +void AddSC_boss_balinda() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_balinda"; + newscript->GetAI = &GetAI_boss_balinda; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_water_elemental"; + newscript->GetAI = &GetAI_mob_water_elemental; + newscript->RegisterSelf(); +}; \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp new file mode 100644 index 00000000000..6477ebe5eaf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_drekthar.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_WHIRLWIND = 15589, + SPELL_WHIRLWIND2 = 13736, + SPELL_KNOCKDOWN = 19128, + SPELL_FRENZY = 8269, + SPELL_SWEEPING_STRIKES = 18765, // not sure + SPELL_CLEAVE = 20677, // not sure + SPELL_WINDFURY = 35886, // not sure + SPELL_STORMPIKE = 51876 // not sure +}; + +enum Yells +{ + YELL_AGGRO = -1810000, + YELL_EVADE = -1810001, + YELL_RESPAWN = -1810002, + YELL_RANDOM1 = -1810003, + YELL_RANDOM2 = -1810004, + YELL_RANDOM3 = -1810005, + YELL_RANDOM4 = -1810006, + YELL_RANDOM5 = -1810007 +}; + +struct boss_drektharAI : public ScriptedAI +{ + boss_drektharAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWhirlwindTimer; + uint32 uiWhirlwind2Timer; + uint32 uiKnockdownTimer; + uint32 uiFrenzyTimer; + uint32 uiYellTimer; + uint32 uiResetTimer; + + void Reset() + { + uiWhirlwindTimer = urand(1*IN_MILISECONDS,20*IN_MILISECONDS); + uiWhirlwind2Timer = urand(1*IN_MILISECONDS,20*IN_MILISECONDS); + uiKnockdownTimer = 12*IN_MILISECONDS; + uiFrenzyTimer = 6*IN_MILISECONDS; + uiResetTimer = 5*IN_MILISECONDS; + uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds + } + + void Aggro(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + } + + void JustRespawned() + { + Reset(); + DoScriptText(YELL_RESPAWN, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWhirlwindTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + uiWhirlwindTimer = urand(8*IN_MILISECONDS,18*IN_MILISECONDS); + } else uiWhirlwindTimer -= diff; + + if (uiWhirlwind2Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND2); + uiWhirlwind2Timer = urand(7*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiWhirlwind2Timer -= diff; + + if (uiKnockdownTimer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + uiKnockdownTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiKnockdownTimer -= diff; + + if (uiFrenzyTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FRENZY); + uiFrenzyTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiFrenzyTimer -= diff; + + if (uiYellTimer <= diff) + { + DoScriptText(RAND(YELL_RANDOM1,YELL_RANDOM2,YELL_RANDOM3,YELL_RANDOM4,YELL_RANDOM5), me); + uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds + } else uiYellTimer -= diff; + + // check if creature is not outside of building + if (uiResetTimer <= diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + { + EnterEvadeMode(); + DoScriptText(YELL_EVADE, me); + } + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_boss_drekthar(Creature *_Creature) +{ + return new boss_drektharAI (_Creature); +} + +void AddSC_boss_drekthar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_drekthar"; + newscript->GetAI = &GetAI_boss_drekthar; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp new file mode 100644 index 00000000000..a12b9f267f9 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_galvangar.cpp @@ -0,0 +1,129 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_CLEAVE = 15284, + SPELL_FRIGHTENING_SHOUT = 19134, + SPELL_WHIRLWIND1 = 15589, + SPELL_WHIRLWIND2 = 13736, + SPELL_MORTAL_STRIKE = 16856 +}; + +enum Yells +{ + YELL_AGGRO = -1810021, + YELL_EVADE = -1810022 +}; + +struct boss_galvangarAI : public ScriptedAI +{ + boss_galvangarAI(Creature *c) : ScriptedAI(c) {} + + + uint32 uiCleaveTimer; + uint32 uiFrighteningShoutTimer; + uint32 uiWhirlwind1Timer; + uint32 uiWhirlwind2Timer; + uint32 uiMortalStrikeTimer; + uint32 uiResetTimer; + + + void Reset() + { + uiCleaveTimer = urand(1*IN_MILISECONDS,9*IN_MILISECONDS); + uiFrighteningShoutTimer = urand(2*IN_MILISECONDS,19*IN_MILISECONDS); + uiWhirlwind1Timer = urand(1*IN_MILISECONDS,13*IN_MILISECONDS); + uiWhirlwind2Timer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); + uiMortalStrikeTimer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); + uiResetTimer = 5*IN_MILISECONDS; + } + + void Aggro(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + } + + void JustRespawned() + { + Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiCleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + uiCleaveTimer = urand(10*IN_MILISECONDS,16*IN_MILISECONDS); + } else uiCleaveTimer -= diff; + + if (uiFrighteningShoutTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); + uiFrighteningShoutTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiFrighteningShoutTimer -= diff; + + if (uiWhirlwind1Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND1); + uiWhirlwind1Timer = urand(6*IN_MILISECONDS,10*IN_MILISECONDS); + } else uiWhirlwind1Timer -= diff; + + if (uiWhirlwind2Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND2); + uiWhirlwind2Timer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiWhirlwind2Timer -= diff; + + if (uiMortalStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + uiMortalStrikeTimer = urand(10*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiMortalStrikeTimer -= diff; + + // check if creature is not outside of building + if (uiResetTimer <= diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + { + EnterEvadeMode(); + DoScriptText(YELL_EVADE, me); + } + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_galvangar(Creature *_Creature) +{ + return new boss_galvangarAI (_Creature); +} + +void AddSC_boss_galvangar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_galvangar"; + newscript->GetAI = &GetAI_boss_galvangar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_vanndar.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_vanndar.cpp new file mode 100644 index 00000000000..785827bc5d9 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_vanndar.cpp @@ -0,0 +1,129 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +enum Yells +{ + YELL_AGGRO = -1810008, + YELL_EVADE = -1810009, + YELL_RESPAWN1 = -1810010, + YELL_RESPAWN2 = -1810011, + YELL_RANDOM1 = -1810012, + YELL_RANDOM2 = -1810013, + YELL_RANDOM3 = -1810014, + YELL_RANDOM4 = -1810015, + YELL_RANDOM5 = -1810016, + YELL_RANDOM6 = -1810017, + YELL_RANDOM7 = -1810018 +}; + +enum Spells +{ + SPELL_AVATAR = 19135, + SPELL_THUNDERCLAP = 15588, + SPELL_STORMBOLT = 20685 // not sure +}; + +struct boss_vanndarAI : public ScriptedAI +{ + boss_vanndarAI(Creature *c) : ScriptedAI(c) {} + + + uint32 uiAvatarTimer; + uint32 uiThunderclapTimer; + uint32 uiStormboltTimer; + uint32 uiResetTimer; + uint32 uiYellTimer; + + + void Reset() + { + uiAvatarTimer = 3*IN_MILISECONDS; + uiThunderclapTimer = 4*IN_MILISECONDS; + uiStormboltTimer = 6*IN_MILISECONDS; + uiResetTimer = 5*IN_MILISECONDS; + uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } + + void Aggro(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + } + + void JustRespawned() + { + Reset(); + DoScriptText(RAND(YELL_RESPAWN1,YELL_RESPAWN2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiAvatarTimer <= diff) + { + DoCast(me->getVictim(), SPELL_AVATAR); + uiAvatarTimer = urand(15*IN_MILISECONDS,20*IN_MILISECONDS); + } else uiAvatarTimer -= diff; + + if (uiThunderclapTimer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + uiThunderclapTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiThunderclapTimer -= diff; + + if (uiStormboltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STORMBOLT); + uiStormboltTimer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiStormboltTimer -= diff; + + if (uiYellTimer <= diff) + { + DoScriptText(RAND(YELL_RANDOM1,YELL_RANDOM2,YELL_RANDOM3,YELL_RANDOM4,YELL_RANDOM5,YELL_RANDOM6,YELL_RANDOM7), me); + uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds + } else uiYellTimer -= diff; + + // check if creature is not outside of building + if (uiResetTimer <= diff) + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) + { + EnterEvadeMode(); + DoScriptText(YELL_EVADE, me); + } + uiResetTimer = 5*IN_MILISECONDS; + } else uiResetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vanndar(Creature *_Creature) +{ + return new boss_vanndarAI (_Creature); +} + +void AddSC_boss_vanndar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vanndar"; + newscript->GetAI = &GetAI_boss_vanndar; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.cpp new file mode 100644 index 00000000000..e04fa8444b2 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.cpp @@ -0,0 +1,1338 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Blackrock_Depths +SD%Complete: 95 +SDComment: Quest support: 4001, 4342, 7604, 4322. Vendor Lokhtos Darkbargainer. Need to rewrite the Jail Break support +SDCategory: Blackrock Depths +EndScriptData */ + +/* ContentData +go_shadowforge_brazier +at_ring_of_law +npc_grimstone +mob_phalanx +npc_kharan_mighthammer +npc_lokhtos_darkbargainer +npc_dughal_stormwing +npc_marshal_windsor +npc_marshal_reginald_windsor +npc_tobias_seecher +npc_rocknot +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "blackrock_depths.h" + +/*###### ++## go_shadowforge_brazier ++######*/ + +bool GOHello_go_shadowforge_brazier(Player* /*pPlayer*/, GameObject* pGo) +{ + if (ScriptedInstance* pInstance = pGo->GetInstanceData()) + { + if (pInstance->GetData(TYPE_LYCEUM) == IN_PROGRESS) + pInstance->SetData(TYPE_LYCEUM, DONE); + else + pInstance->SetData(TYPE_LYCEUM, IN_PROGRESS); + // If used brazier open linked doors (North or South) + if (pGo->GetGUID() == pInstance->GetData64(DATA_SF_BRAZIER_N)) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GOLEM_DOOR_N), true); + else if (pGo->GetGUID() == pInstance->GetData64(DATA_SF_BRAZIER_S)) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GOLEM_DOOR_S), true); + } + return false; +} + +/*###### +## npc_grimstone +######*/ + +enum eGrimstone +{ + NPC_GRIMSTONE = 10096, + NPC_THELDREN = 16059, + + //4 or 6 in total? 1+2+1 / 2+2+2 / 3+3. Depending on this, code should be changed. + MAX_MOB_AMOUNT = 4 +}; + +uint32 RingMob[]= +{ + 8925, // Dredge Worm + 8926, // Deep Stinger + 8927, // Dark Screecher + 8928, // Burrowing Thundersnout + 8933, // Cave Creeper + 8932, // Borer Beetle +}; + +uint32 RingBoss[]= +{ + 9027, // Gorosh + 9028, // Grizzle + 9029, // Eviscerator + 9030, // Ok'thor + 9031, // Anub'shiah + 9032, // Hedrum +}; + +bool AreaTrigger_at_ring_of_law(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + if (ScriptedInstance* pInstance = pPlayer->GetInstanceData()) + { + if (pInstance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || pInstance->GetData(TYPE_RING_OF_LAW) == DONE) + return false; + + pInstance->SetData(TYPE_RING_OF_LAW,IN_PROGRESS); + pPlayer->SummonCreature(NPC_GRIMSTONE,625.559,-205.618,-52.735,2.609,TEMPSUMMON_DEAD_DESPAWN,0); + + return false; + } + return false; +} + +/*###### +## npc_grimstone +######*/ + +enum GrimstoneTexts +{ + SCRIPT_TEXT1 = -1000000, + SCRIPT_TEXT2 = -1000001, + SCRIPT_TEXT3 = -1000002, + SCRIPT_TEXT4 = -1000003, + SCRIPT_TEXT5 = -1000004, + SCRIPT_TEXT6 = -1000005 +}; + +//TODO: implement quest part of event (different end boss) +struct npc_grimstoneAI : public npc_escortAI +{ + npc_grimstoneAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + MobSpawnId = rand()%6; + } + + ScriptedInstance* pInstance; + + uint8 EventPhase; + uint32 Event_Timer; + + uint8 MobSpawnId; + uint8 MobCount; + uint32 MobDeath_Timer; + + uint64 RingMobGUID[4]; + uint64 RingBossGUID; + + bool CanWalk; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + EventPhase = 0; + Event_Timer = 1000; + + MobCount = 0; + MobDeath_Timer = 0; + + for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) + RingMobGUID[i] = 0; + + RingBossGUID = 0; + + CanWalk = false; + } + + //TODO: move them to center + void SummonRingMob() + { + if (Creature* tmp = me->SummonCreature(RingMob[MobSpawnId],608.960,-235.322,-53.907,1.857,TEMPSUMMON_DEAD_DESPAWN,0)) + RingMobGUID[MobCount] = tmp->GetGUID(); + + ++MobCount; + + if (MobCount == MAX_MOB_AMOUNT) + MobDeath_Timer = 2500; + } + + //TODO: move them to center + void SummonRingBoss() + { + if (Creature* tmp = me->SummonCreature(RingBoss[rand()%6],644.300,-175.989,-53.739,3.418,TEMPSUMMON_DEAD_DESPAWN,0)) + RingBossGUID = tmp->GetGUID(); + + MobDeath_Timer = 2500; + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 0: + DoScriptText(SCRIPT_TEXT1, me);//2 + CanWalk = false; + Event_Timer = 5000; + break; + case 1: + DoScriptText(SCRIPT_TEXT2, me);//4 + CanWalk = false; + Event_Timer = 5000; + break; + case 2: + CanWalk = false; + break; + case 3: + DoScriptText(SCRIPT_TEXT3, me);//5 + break; + case 4: + DoScriptText(SCRIPT_TEXT4, me);//6 + CanWalk = false; + Event_Timer = 5000; + break; + case 5: + if (pInstance) + { + pInstance->SetData(TYPE_RING_OF_LAW,DONE); + debug_log("TSCR: npc_grimstone: event reached end and set complete."); + } + break; + } + } + + void HandleGameObject(uint32 id, bool open) + { + pInstance->HandleGameObject(pInstance->GetData64(id), open); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (MobDeath_Timer) + { + if (MobDeath_Timer <= diff) + { + MobDeath_Timer = 2500; + + if (RingBossGUID) + { + Creature *boss = Unit::GetCreature(*me,RingBossGUID); + if (boss && !boss->isAlive() && boss->isDead()) + { + RingBossGUID = 0; + Event_Timer = 5000; + MobDeath_Timer = 0; + return; + } + return; + } + + for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) + { + Creature *mob = Unit::GetCreature(*me,RingMobGUID[i]); + if (mob && !mob->isAlive() && mob->isDead()) + { + RingMobGUID[i] = 0; + --MobCount; + + //seems all are gone, so set timer to continue and discontinue this + if (!MobCount) + { + Event_Timer = 5000; + MobDeath_Timer = 0; + } + } + } + } else MobDeath_Timer -= diff; + } + + if (Event_Timer) + { + if (Event_Timer <= diff) + { + switch(EventPhase) + { + case 0: + DoScriptText(SCRIPT_TEXT5, me);//1 + HandleGameObject(DATA_ARENA4, false); + Start(false, false); + CanWalk = true; + Event_Timer = 0; + break; + case 1: + CanWalk = true; + Event_Timer = 0; + break; + case 2: + Event_Timer = 2000; + break; + case 3: + HandleGameObject(DATA_ARENA1, true); + Event_Timer = 3000; + break; + case 4: + CanWalk = true; + me->SetVisibility(VISIBILITY_OFF); + SummonRingMob(); + Event_Timer = 8000; + break; + case 5: + SummonRingMob(); + SummonRingMob(); + Event_Timer = 8000; + break; + case 6: + SummonRingMob(); + Event_Timer = 0; + break; + case 7: + me->SetVisibility(VISIBILITY_ON); + HandleGameObject(DATA_ARENA1, false); + DoScriptText(SCRIPT_TEXT6, me);//4 + CanWalk = true; + Event_Timer = 0; + break; + case 8: + HandleGameObject(DATA_ARENA2, true); + Event_Timer = 5000; + break; + case 9: + me->SetVisibility(VISIBILITY_OFF); + SummonRingBoss(); + Event_Timer = 0; + break; + case 10: + //if quest, complete + HandleGameObject(DATA_ARENA2, false); + HandleGameObject(DATA_ARENA3, true); + HandleGameObject(DATA_ARENA4, true); + CanWalk = true; + Event_Timer = 0; + break; + } + ++EventPhase; + } else Event_Timer -= diff; + } + + if (CanWalk) + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_grimstone(Creature* pCreature) +{ + return new npc_grimstoneAI(pCreature); +} + +/*###### +## mob_phalanx +######*/ + +enum PhalanxSpells +{ + SPELL_THUNDERCLAP = 8732, + SPELL_FIREBALLVOLLEY = 22425, + SPELL_MIGHTYBLOW = 14099 +}; + +struct mob_phalanxAI : public ScriptedAI +{ + mob_phalanxAI(Creature *c) : ScriptedAI(c) {} + + uint32 ThunderClap_Timer; + uint32 FireballVolley_Timer; + uint32 MightyBlow_Timer; + + void Reset() + { + ThunderClap_Timer = 12000; + FireballVolley_Timer =0; + MightyBlow_Timer = 15000; + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ThunderClap_Timer + if (ThunderClap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + ThunderClap_Timer = 10000; + } else ThunderClap_Timer -= diff; + + //FireballVolley_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + if (FireballVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALLVOLLEY); + FireballVolley_Timer = 15000; + } else FireballVolley_Timer -= diff; + } + + //MightyBlow_Timer + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTYBLOW); + MightyBlow_Timer = 10000; + } else MightyBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_phalanx(Creature* pCreature) +{ + return new mob_phalanxAI (pCreature); +} + +/*###### +## npc_kharan_mighthammer +######*/ + +enum KharamQuests +{ + QUEST_4001 = 4001, + QUEST_4342 = 4342 +}; + +#define GOSSIP_ITEM_KHARAN_1 "I need to know where the princess are, Kharan!" +#define GOSSIP_ITEM_KHARAN_2 "All is not lost, Kharan!" + +#define GOSSIP_ITEM_KHARAN_3 "Gor'shak is my friend, you can trust me." +#define GOSSIP_ITEM_KHARAN_4 "Not enough, you need to tell me more." +#define GOSSIP_ITEM_KHARAN_5 "So what happened?" +#define GOSSIP_ITEM_KHARAN_6 "Continue..." +#define GOSSIP_ITEM_KHARAN_7 "So you suspect that someone on the inside was involved? That they were tipped off?" +#define GOSSIP_ITEM_KHARAN_8 "Continue with your story please." +#define GOSSIP_ITEM_KHARAN_9 "Indeed." +#define GOSSIP_ITEM_KHARAN_10 "The door is open, Kharan. You are a free man." + +bool GossipHello_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_4001) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (pPlayer->GetQuestStatus(4342) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + + if (pPlayer->GetTeam() == HORDE) + pPlayer->SEND_GOSSIP_MENU(2473, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(2474, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(2475, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(2476, pCreature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(2477, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(2478, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(2479, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + pPlayer->SEND_GOSSIP_MENU(2480, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); + pPlayer->SEND_GOSSIP_MENU(2481, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+8: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); + pPlayer->SEND_GOSSIP_MENU(2482, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+9: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pPlayer->GetTeam() == HORDE) + pPlayer->AreaExploredOrEventHappens(QUEST_4001); + else + pPlayer->AreaExploredOrEventHappens(QUEST_4342); + break; + } + return true; +} + +/*###### +## npc_lokhtos_darkbargainer +######*/ + +enum LokhtosItems +{ + ITEM_THRORIUM_BROTHERHOOD_CONTRACT = 18628, + ITEM_SULFURON_INGOT = 17203 +}; + +enum LokhtosQuests +{ + QUEST_A_BINDING_CONTRACT = 7604 +}; + +enum LokhtosSpells +{ + SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059 +}; + +#define GOSSIP_ITEM_SHOW_ACCESS "Show me what I have access to, Lothos." +#define GOSSIP_ITEM_GET_CONTRACT "Get Thorium Brotherhood Contract" + +bool GossipHello_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->isVendor() && pPlayer->GetReputationRank(59) >= REP_FRIENDLY) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_ITEM_SHOW_ACCESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + + if (pPlayer->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 && + !pPlayer->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) && + pPlayer->HasItemCount(ITEM_SULFURON_INGOT, 1)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GET_CONTRACT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + } + + if (pPlayer->GetReputationRank(59) < REP_FRIENDLY) + pPlayer->SEND_GOSSIP_MENU(3673, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(3677, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false); + } + if (uiAction == GOSSIP_ACTION_TRADE) + pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); + + return true; +} + +/*###### +## npc_dughal_stormwing +######*/ + +enum DughalQuests +{ + QUEST_JAIL_BREAK = 4322 +}; + +#define SAY_DUGHAL_FREE "Thank you, $N! I'm free!!!" +#define GOSSIP_DUGHAL "You're free, Dughal! Get out of here!" + +/* +struct npc_dughal_stormwingAI : public npc_escortAI +{ + npc_dughal_stormwingAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + switch(i) + { + case 0:me->Say(SAY_DUGHAL_FREE, LANG_UNIVERSAL, PlayerGUID); break; + case 1:pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_OBJECTIVE_COMPLETED);break; + case 2: + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_ENDED); + break; + } + } + + void EnterCombat(Unit* who) {} + void Reset() {} + + void JustDied(Unit* killer) + { + if (IsBeingEscorted && killer == me) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_ENDED); + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; + if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_ENDED) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_dughal_stormwing(Creature* pCreature) +{ + npc_dughal_stormwingAI* dughal_stormwingAI = new npc_dughal_stormwingAI(pCreature); + + dughal_stormwingAI->AddWaypoint(0, 280.42,-82.86, -77.12,0); + dughal_stormwingAI->AddWaypoint(1, 287.64,-87.01, -76.79,0); + dughal_stormwingAI->AddWaypoint(2, 354.63,-64.95, -67.53,0); + + return dughal_stormwingAI; +} +bool GossipHello_npc_dughal_stormwing(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUGHAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2846, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_dughal_stormwing(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, true, pPlayer->GetGUID()); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_IN_PROGRESS); + } + return true; +} + */ +/*###### +## npc_marshal_windsor +######*/ + +#define SAY_WINDSOR_AGGRO1 "You locked up the wrong Marshal. Prepare to be destroyed!" +#define SAY_WINDSOR_AGGRO2 "I bet you're sorry now, aren't you !?!!" +#define SAY_WINDSOR_AGGRO3 "You better hold me back $N or they are going to feel some prison house beatings." +#define SAY_WINDSOR_1 "Let's get a move on. My gear should be in the storage area up this way..." +#define SAY_WINDSOR_4_1 "Check that cell, $N. If someone is alive in there, we need to get them out." +#define SAY_WINDSOR_4_2 "Get him out of there!" +#define SAY_WINDSOR_4_3 "Good work! We're almost there, $N. This way." +#define SAY_WINDSOR_6 "This is it, $N. My stuff should be in that room. Cover me, I'm going in!" +#define SAY_WINDSOR_9 "Ah, there it is!" +#define MOB_ENTRY_REGINALD_WINDSOR 9682 + +Player* pPlayerStart; +/* +struct npc_marshal_windsorAI : public npc_escortAI +{ + npc_marshal_windsorAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 1: + me->Say(SAY_WINDSOR_1, LANG_UNIVERSAL, PlayerGUID); + break; + case 7: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_WINDSOR_4_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 10: + me->setFaction(534); + break; + case 12: + me->Say(SAY_WINDSOR_6, LANG_UNIVERSAL, PlayerGUID); + pInstance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_IN_PROGRESS); + break; + case 13: + me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK + break; + case 14: + pInstance->SetData(DATA_GATE_SR,0); + me->setFaction(11); + break; + case 16: + me->Say(SAY_WINDSOR_9, LANG_UNIVERSAL, PlayerGUID); + break; + case 17: + me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK + break; + case 18: + pInstance->SetData(DATA_GATE_SC,0); + break; + case 19: + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SummonCreature(MOB_ENTRY_REGINALD_WINDSOR,403.61,-51.71,-63.92,3.600434,TEMPSUMMON_DEAD_DESPAWN ,0); + pInstance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_ENDED); + break; + } + } + + void EnterCombat(Unit* who) + { + switch (urand(0,2)) + { + case 0: me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); break; + case 1: me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); break; + case 2: me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); break; + } + } + + void Reset() {} + + void JustDied(Unit *slayer) + { + pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_FAILED); + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; + if (pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) + SetEscortPaused(false); + if (!pInstance->GetData(DATA_GATE_D) && pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_NOT_STARTED) + { + me->Say(SAY_WINDSOR_4_2, LANG_UNIVERSAL, PlayerGUID); + pInstance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_BEFORE_START); + } + if (pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) + { + me->Say(SAY_WINDSOR_4_3, LANG_UNIVERSAL, PlayerGUID); + pInstance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); + } + if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_SUPPLY_ROOM) == ENCOUNTER_STATE_ENDED) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_marshal_windsor(Creature* pCreature) +{ + npc_marshal_windsorAI* marshal_windsorAI = new npc_marshal_windsorAI(pCreature); + + marshal_windsorAI->AddWaypoint(0, 316.336,-225.528, -77.7258,7000); + marshal_windsorAI->AddWaypoint(1, 316.336,-225.528, -77.7258,2000); + marshal_windsorAI->AddWaypoint(2, 322.96,-207.13, -77.87,0); + marshal_windsorAI->AddWaypoint(3, 281.05,-172.16, -75.12,0); + marshal_windsorAI->AddWaypoint(4, 272.19,-139.14, -70.61,0); + marshal_windsorAI->AddWaypoint(5, 283.62,-116.09, -70.21,0); + marshal_windsorAI->AddWaypoint(6, 296.18,-94.30, -74.08,0); + marshal_windsorAI->AddWaypoint(7, 294.57,-93.11, -74.08,0); + marshal_windsorAI->AddWaypoint(8, 314.31,-74.31, -76.09,0); + marshal_windsorAI->AddWaypoint(9, 360.22,-62.93, -66.77,0); + marshal_windsorAI->AddWaypoint(10, 383.38,-69.40, -63.25,0); + marshal_windsorAI->AddWaypoint(11, 389.99,-67.86, -62.57,0); + marshal_windsorAI->AddWaypoint(12, 400.98,-72.01, -62.31,0); + marshal_windsorAI->AddWaypoint(13, 404.22,-62.30, -63.50,2300); + marshal_windsorAI->AddWaypoint(14, 404.22,-62.30, -63.50,1500); + marshal_windsorAI->AddWaypoint(15, 407.65,-51.86, -63.96,0); + marshal_windsorAI->AddWaypoint(16, 403.61,-51.71, -63.92,1000); + marshal_windsorAI->AddWaypoint(17, 403.61,-51.71, -63.92,2000); + marshal_windsorAI->AddWaypoint(18, 403.61,-51.71, -63.92,1000); + marshal_windsorAI->AddWaypoint(19, 403.61,-51.71, -63.92,0); + + return marshal_windsorAI; +} + +bool QuestAccept_npc_marshal_windsor(Player* pPlayer, Creature* pCreature, Quest const *quest) +{ + if (quest->GetQuestId() == 4322) + {PlayerStart = player; + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) + { + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_IN_PROGRESS); + pCreature->setFaction(11); + } + + } + return false; +} + */ +/*###### +## npc_marshal_reginald_windsor +######*/ + +#define SAY_REGINALD_WINDSOR_0_1 "Can you feel the power, $N??? It's time to ROCK!" +#define SAY_REGINALD_WINDSOR_0_2 "Now we just have to free Tobias and we can get out of here. This way!" +#define SAY_REGINALD_WINDSOR_5_1 "Open it." +#define SAY_REGINALD_WINDSOR_5_2 "I never did like those two. Let's get moving." +#define SAY_REGINALD_WINDSOR_7_1 "Open it and be careful this time!" +#define SAY_REGINALD_WINDSOR_7_2 "That intolerant dirtbag finally got what was coming to him. Good riddance!" +#define SAY_REGINALD_WINDSOR_7_3 "Alright, let's go." +#define SAY_REGINALD_WINDSOR_13_1 "Open it. We need to hurry up. I can smell those Dark Irons coming a mile away and I can tell you one thing, they're COMING!" +#define SAY_REGINALD_WINDSOR_13_2 "Administering fists of fury on Crest Killer!" +#define SAY_REGINALD_WINDSOR_13_3 "He has to be in the last cell. Unless... they killed him." +#define SAY_REGINALD_WINDSOR_14_1 "Get him out of there!" +#define SAY_REGINALD_WINDSOR_14_2 "Excellent work, $N. Let's find the exit. I think I know the way. Follow me!" +#define SAY_REGINALD_WINDSOR_20_1 "We made it!" +#define SAY_REGINALD_WINDSOR_20_2 "Meet me at Maxwell's encampment. We'll go over the next stages of the plan there and figure out a way to decode my tablets without the decryption ring." +#define MOB_ENTRY_SHILL_DINGER 9678 +#define MOB_ENTRY_CREST_KILLER 9680 + +int wp = 0; +/* +struct npc_marshal_reginald_windsorAI : public npc_escortAI +{ + npc_marshal_reginald_windsorAI(Creature *c) : npc_escortAI(c) + { + } + + void WaypointReached(uint32 i) + { + wp=i; + switch(i) + { + case 0: + me->setFaction(11); + me->Say(SAY_REGINALD_WINDSOR_0_1, LANG_UNIVERSAL, PlayerGUID); + break; + case 1: + me->Say(SAY_REGINALD_WINDSOR_0_2, LANG_UNIVERSAL, PlayerGUID); + break; + case 7: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_REGINALD_WINDSOR_5_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 8: + me->Say(SAY_REGINALD_WINDSOR_5_2, LANG_UNIVERSAL, PlayerGUID); + break; + case 11: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_REGINALD_WINDSOR_7_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 12: + me->Say(SAY_REGINALD_WINDSOR_7_2, LANG_UNIVERSAL, PlayerGUID); + break; + case 13: + me->Say(SAY_REGINALD_WINDSOR_7_3, LANG_UNIVERSAL, PlayerGUID); + break; + case 20: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_REGINALD_WINDSOR_13_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 21: + me->Say(SAY_REGINALD_WINDSOR_13_3, LANG_UNIVERSAL, PlayerGUID); + break; + case 23: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + me->Say(SAY_REGINALD_WINDSOR_14_1, LANG_UNIVERSAL, PlayerGUID); + IsOnHold=true; + break; + case 24: + me->Say(SAY_REGINALD_WINDSOR_14_2, LANG_UNIVERSAL, PlayerGUID); + break; + case 31: + me->Say(SAY_REGINALD_WINDSOR_20_1, LANG_UNIVERSAL, PlayerGUID); + break; + case 32: + me->Say(SAY_REGINALD_WINDSOR_20_2, LANG_UNIVERSAL, PlayerGUID); + PlayerStart->GroupEventHappens(QUEST_JAIL_BREAK, me); + pInstance->SetData(DATA_SHILL, ENCOUNTER_STATE_ENDED); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + if (who->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(who)->GetQuestStatus(4322) == QUEST_STATUS_INCOMPLETE) + { + float Radius = 10.0; + if (me->IsWithinDistInMap(who, Radius)) + { + SetEscortPaused(false); + Start(true, false, who->GetGUID()); + } + } + } + } + + void EnterCombat(Unit* who) + { + switch (urand(0,2)) + { + case 0: me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); break; + case 1: me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); break; + case 2: me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); break; + } + } + void Reset() {} + + void JustDied(Unit *slayer) + { + pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_FAILED); + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; + if (wp == 7) + { + if (!pInstance->GetData(DATA_GATE_J) && pInstance->GetData(DATA_JAZ) == ENCOUNTER_STATE_NOT_STARTED) + { + pInstance->SetData(DATA_CREATURE_JAZ,1); + pInstance->SetData(DATA_JAZ,ENCOUNTER_STATE_IN_PROGRESS); + } + if (pInstance->GetData(DATA_CREATURE_JAZ) && pInstance->GetData(DATA_CREATURE_OGRABISI) && pInstance->GetData(DATA_JAZ) == ENCOUNTER_STATE_IN_PROGRESS) + { + SetEscortPaused(false); + pInstance->SetData(DATA_JAZ,ENCOUNTER_STATE_ENDED); + } + } + else if (wp == 11) + { + if (!pInstance->GetData(DATA_GATE_S) && pInstance->GetData(DATA_SHILL) == ENCOUNTER_STATE_NOT_STARTED) + { + pInstance->SetData(DATA_CREATURE_SHILL,1); + pInstance->SetData(DATA_SHILL,ENCOUNTER_STATE_IN_PROGRESS); + } + if (pInstance->GetData(DATA_CREATURE_SHILL) && pInstance->GetData(DATA_SHILL) == ENCOUNTER_STATE_IN_PROGRESS) + { + pInstance->SetData(DATA_SHILL,ENCOUNTER_STATE_ENDED); + SetEscortPaused(false); + } + } + else if (wp == 20) + { + if (!pInstance->GetData(DATA_GATE_C) && pInstance->GetData(DATA_CREST) == ENCOUNTER_STATE_NOT_STARTED) + { + pInstance->SetData(DATA_CREATURE_CREST,1); + me->Say(SAY_REGINALD_WINDSOR_13_2, LANG_UNIVERSAL, PlayerGUID); + pInstance->SetData(DATA_CREST,ENCOUNTER_STATE_IN_PROGRESS); + } + if (pInstance->GetData(DATA_CREATURE_CREST) && pInstance->GetData(DATA_CREST) == ENCOUNTER_STATE_IN_PROGRESS) + { + SetEscortPaused(false); + pInstance->SetData(DATA_CREST,ENCOUNTER_STATE_ENDED); + } + } + if (pInstance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) SetEscortPaused(false); + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_marshal_reginald_windsor(Creature* pCreature) +{ + npc_marshal_reginald_windsorAI* marshal_reginald_windsorAI = new npc_marshal_reginald_windsorAI(pCreature); + + marshal_reginald_windsorAI->AddWaypoint(0, 403.61,-52.71, -63.92,4000); + marshal_reginald_windsorAI->AddWaypoint(1, 403.61,-52.71, -63.92,4000); + marshal_reginald_windsorAI->AddWaypoint(2, 406.33,-54.87, -63.95,0); + marshal_reginald_windsorAI->AddWaypoint(3, 407.99,-73.91, -62.26,0); + marshal_reginald_windsorAI->AddWaypoint(4, 557.03,-119.71, -61.83,0); + marshal_reginald_windsorAI->AddWaypoint(5, 573.40,-124.39, -65.07,0); + marshal_reginald_windsorAI->AddWaypoint(6, 593.91,-130.29, -69.25,0); + marshal_reginald_windsorAI->AddWaypoint(7, 593.21,-132.16, -69.25,0); + marshal_reginald_windsorAI->AddWaypoint(8, 593.21,-132.16, -69.25,3000); + marshal_reginald_windsorAI->AddWaypoint(9, 622.81,-135.55, -71.92,0); + marshal_reginald_windsorAI->AddWaypoint(10, 634.68,-151.29, -70.32,0); + marshal_reginald_windsorAI->AddWaypoint(11, 635.06,-153.25, -70.32,0); + marshal_reginald_windsorAI->AddWaypoint(12, 635.06,-153.25, -70.32,3000); + marshal_reginald_windsorAI->AddWaypoint(13, 635.06,-153.25, -70.32,1500); + marshal_reginald_windsorAI->AddWaypoint(14, 655.25,-172.39, -73.72,0); + marshal_reginald_windsorAI->AddWaypoint(15, 654.79,-226.30, -83.06,0); + marshal_reginald_windsorAI->AddWaypoint(16, 622.85,-268.85, -83.96,0); + marshal_reginald_windsorAI->AddWaypoint(17, 579.45,-275.56, -80.44,0); + marshal_reginald_windsorAI->AddWaypoint(18, 561.19,-266.85, -75.59,0); + marshal_reginald_windsorAI->AddWaypoint(19, 547.91,-253.92, -70.34,0); + marshal_reginald_windsorAI->AddWaypoint(20, 549.20,-252.40, -70.34,0); + marshal_reginald_windsorAI->AddWaypoint(21, 549.20,-252.40, -70.34,4000); + marshal_reginald_windsorAI->AddWaypoint(22, 555.33,-269.16, -74.40,0); + marshal_reginald_windsorAI->AddWaypoint(23, 554.31,-270.88, -74.40,0); + marshal_reginald_windsorAI->AddWaypoint(24, 554.31,-270.88, -74.40,4000); + marshal_reginald_windsorAI->AddWaypoint(25, 536.10,-249.60, -67.47,0); + marshal_reginald_windsorAI->AddWaypoint(26, 520.94,-216.65, -59.28,0); + marshal_reginald_windsorAI->AddWaypoint(27, 505.99,-148.74, -62.17,0); + marshal_reginald_windsorAI->AddWaypoint(28, 484.21,-56.24, -62.43,0); + marshal_reginald_windsorAI->AddWaypoint(29, 470.39,-6.01, -70.10,0); + marshal_reginald_windsorAI->AddWaypoint(30, 451.27,30.85, -70.07,0); + marshal_reginald_windsorAI->AddWaypoint(31, 452.45,29.85, -70.37,1500); + marshal_reginald_windsorAI->AddWaypoint(32, 452.45,29.85, -70.37,7000); + marshal_reginald_windsorAI->AddWaypoint(33, 452.45,29.85, -70.37,10000); + marshal_reginald_windsorAI->AddWaypoint(34, 451.27,31.85, -70.07,0); + + return marshal_reginald_windsorAI; +} +*/ +/*###### +## npc_tobias_seecher +######*/ + +#define SAY_TOBIAS_FREE "Thank you! I will run for safety immediately!" +/* +struct npc_tobias_seecherAI : public npc_escortAI +{ + npc_tobias_seecherAI(Creature *c) :npc_escortAI(c) {} + + void EnterCombat(Unit* who) {} + void Reset() {} + + void JustDied(Unit* killer) + { + if (IsBeingEscorted && killer == me) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_ENDED); + } + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 0:me->Say(SAY_TOBIAS_FREE, LANG_UNIVERSAL, PlayerGUID); break; + case 2: + pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_OBJECTIVE_COMPLETED);break; + case 4: + me->SetVisibility(VISIBILITY_OFF); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_ENDED); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; + if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_ENDED) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_tobias_seecher(Creature* pCreature) +{ + npc_tobias_seecherAI* tobias_seecherAI = new npc_tobias_seecherAI(pCreature); + + tobias_seecherAI->AddWaypoint(0, 549.21, -281.07, -75.27); + tobias_seecherAI->AddWaypoint(1, 554.39, -267.39, -73.68); + tobias_seecherAI->AddWaypoint(2, 533.59, -249.38, -67.04); + tobias_seecherAI->AddWaypoint(3, 519.44, -217.02, -59.34); + tobias_seecherAI->AddWaypoint(4, 506.55, -153.49, -62.34); + + return tobias_seecherAI; +} + +bool GossipHello_npc_tobias_seecher(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Get out of here, Tobias, you're free!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2847, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_tobias_seecher(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, true, pPlayer->GetGUID()); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_IN_PROGRESS); + } + return true; +} +*/ + +/*###### +## npc_rocknot +######*/ + +enum RocknotSays +{ + SAY_GOT_BEER = -1230000 +}; + +enum RocknotSpells +{ + SPELL_DRUNKEN_RAGE = 14872 +}; + +enum RocknotQuests +{ + QUEST_ALE = 4295 +}; + +struct npc_rocknotAI : public npc_escortAI +{ + npc_rocknotAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 BreakKeg_Timer; + uint32 BreakDoor_Timer; + + void Reset() + { + if (HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + BreakKeg_Timer = 0; + BreakDoor_Timer = 0; + } + + void DoGo(uint32 id, uint32 state) + { + if (GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(id))) + pGo->SetGoState((GOState)state); + } + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch(i) + { + case 1: + me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); + break; + case 2: + me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); + break; + case 3: + me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); + break; + case 4: + me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); + break; + case 5: + me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); + BreakKeg_Timer = 2000; + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (BreakKeg_Timer) + { + if (BreakKeg_Timer <= diff) + { + DoGo(DATA_GO_BAR_KEG,0); + BreakKeg_Timer = 0; + BreakDoor_Timer = 1000; + } else BreakKeg_Timer -= diff; + } + + if (BreakDoor_Timer) + { + if (BreakDoor_Timer <= diff) + { + DoGo(DATA_GO_BAR_DOOR,2); + DoGo(DATA_GO_BAR_KEG_TRAP,0); //doesn't work very well, leaving code here for future + //spell by trap has effect61, this indicate the bar go hostile + + if (Unit *tmp = Unit::GetUnit(*me,pInstance->GetData64(DATA_PHALANX))) + tmp->setFaction(14); + + //for later, this event(s) has alot more to it. + //optionally, DONE can trigger bar to go hostile. + pInstance->SetData(TYPE_BAR,DONE); + + BreakDoor_Timer = 0; + } else BreakDoor_Timer -= diff; + } + + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_rocknot(Creature* pCreature) +{ + return new npc_rocknotAI(pCreature); +} + +bool ChooseReward_npc_rocknot(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest, uint32 /*item*/) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (!pInstance) + return true; + + if (pInstance->GetData(TYPE_BAR) == DONE || pInstance->GetData(TYPE_BAR) == SPECIAL) + return true; + + if (_Quest->GetQuestId() == QUEST_ALE) + { + if (pInstance->GetData(TYPE_BAR) != IN_PROGRESS) + pInstance->SetData(TYPE_BAR,IN_PROGRESS); + + pInstance->SetData(TYPE_BAR,SPECIAL); + + //keep track of amount in instance script, returns SPECIAL if amount ok and event in progress + if (pInstance->GetData(TYPE_BAR) == SPECIAL) + { + DoScriptText(SAY_GOT_BEER, pCreature); + pCreature->CastSpell(pCreature,SPELL_DRUNKEN_RAGE,false); + if (npc_escortAI* pEscortAI = CAST_AI(npc_rocknotAI, pCreature->AI())) + pEscortAI->Start(false, false); + } + } + + return true; +} + +/*###### +## +######*/ + +void AddSC_blackrock_depths() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_shadowforge_brazier"; + newscript->pGOHello = &GOHello_go_shadowforge_brazier; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_ring_of_law"; + newscript->pAreaTrigger = &AreaTrigger_at_ring_of_law; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_grimstone"; + newscript->GetAI = &GetAI_npc_grimstone; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phalanx"; + newscript->GetAI = &GetAI_mob_phalanx; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_kharan_mighthammer"; + newscript->pGossipHello = &GossipHello_npc_kharan_mighthammer; + newscript->pGossipSelect = &GossipSelect_npc_kharan_mighthammer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lokhtos_darkbargainer"; + newscript->pGossipHello = &GossipHello_npc_lokhtos_darkbargainer; + newscript->pGossipSelect = &GossipSelect_npc_lokhtos_darkbargainer; + newscript->RegisterSelf(); +/* + newscript = new Script; + newscript->Name = "npc_dughal_stormwing"; + newscript->pGossipHello = &GossipHello_npc_dughal_stormwing; + newscript->pGossipSelect = &GossipSelect_npc_dughal_stormwing; + newscript->GetAI = &GetAI_npc_dughal_stormwing; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tobias_seecher"; + newscript->pGossipHello = &GossipHello_npc_tobias_seecher; + newscript->pGossipSelect = &GossipSelect_npc_tobias_seecher; + newscript->GetAI = &GetAI_npc_tobias_seecher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_marshal_windsor"; + newscript->pQuestAccept = &QuestAccept_npc_marshal_windsor; + newscript->GetAI = &GetAI_npc_marshal_windsor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_marshal_reginald_windsor"; + newscript->GetAI = &GetAI_npc_marshal_reginald_windsor; + newscript->RegisterSelf(); +*/ + newscript = new Script; + newscript->Name = "npc_rocknot"; + newscript->GetAI = &GetAI_npc_rocknot; + newscript->pChooseReward = &ChooseReward_npc_rocknot; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.h b/src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.h new file mode 100644 index 00000000000..edb340252b2 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/blackrock_depths.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BRD_H +#define DEF_BRD_H + +#define FACTION_NEUTRAL 734 +#define FACTION_HOSTILE 754 +#define FACTION_FRIEND 35 + +enum eTypes +{ + TYPE_RING_OF_LAW = 1, + TYPE_VAULT = 2, + TYPE_BAR = 3, + TYPE_TOMB_OF_SEVEN = 4, + TYPE_LYCEUM = 5, + TYPE_IRON_HALL = 6, + + DATA_EMPEROR = 10, + DATA_PHALANX = 11, + + DATA_ARENA1 = 12, + DATA_ARENA2 = 13, + DATA_ARENA3 = 14, + DATA_ARENA4 = 15, + + DATA_GO_BAR_KEG = 16, + DATA_GO_BAR_KEG_TRAP = 17, + DATA_GO_BAR_DOOR = 18, + DATA_GO_CHALICE = 19, + + DATA_GHOSTKILL = 20, + DATA_EVENSTARTER = 21, + + DATA_GOLEM_DOOR_N = 22, + DATA_GOLEM_DOOR_S = 23, + + DATA_THRONE_DOOR = 24, + + DATA_SF_BRAZIER_N = 25, + DATA_SF_BRAZIER_S = 26 +}; +#endif diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_ambassador_flamelash.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_ambassador_flamelash.cpp new file mode 100644 index 00000000000..a387e816951 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_ambassador_flamelash.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ambassador_Flamelash +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_FIREBLAST = 15573 +}; + +struct boss_ambassador_flamelashAI : public ScriptedAI +{ + boss_ambassador_flamelashAI(Creature *c) : ScriptedAI(c) {} + + uint32 FireBlast_Timer; + uint32 Spirit_Timer; + + void Reset() + { + FireBlast_Timer = 2000; + Spirit_Timer = 24000; + } + + void EnterCombat(Unit * /*who*/) {} + + void SummonSpirits(Unit* victim) + { + if (Creature *Spirit = DoSpawnCreature(9178, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) + Spirit->AI()->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FireBlast_Timer + if (FireBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBLAST); + FireBlast_Timer = 7000; + } else FireBlast_Timer -= diff; + + //Spirit_Timer + if (Spirit_Timer <= diff) + { + SummonSpirits(me->getVictim()); + SummonSpirits(me->getVictim()); + SummonSpirits(me->getVictim()); + SummonSpirits(me->getVictim()); + + Spirit_Timer = 30000; + } else Spirit_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ambassador_flamelash(Creature* pCreature) +{ + return new boss_ambassador_flamelashAI (pCreature); +} + +void AddSC_boss_ambassador_flamelash() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ambassador_flamelash"; + newscript->GetAI = &GetAI_boss_ambassador_flamelash; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_anubshiah.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_anubshiah.cpp new file mode 100644 index 00000000000..60e1dec236c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_anubshiah.cpp @@ -0,0 +1,116 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Anubshiah +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_SHADOWBOLT = 17228, + SPELL_CURSEOFTONGUES = 15470, + SPELL_CURSEOFWEAKNESS = 17227, + SPELL_DEMONARMOR = 11735, + SPELL_ENVELOPINGWEB = 15471 +}; + +struct boss_anubshiahAI : public ScriptedAI +{ + boss_anubshiahAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowBolt_Timer; + uint32 CurseOfTongues_Timer; + uint32 CurseOfWeakness_Timer; + uint32 DemonArmor_Timer; + uint32 EnvelopingWeb_Timer; + + void Reset() + { + ShadowBolt_Timer = 7000; + CurseOfTongues_Timer = 24000; + CurseOfWeakness_Timer = 12000; + DemonArmor_Timer = 3000; + EnvelopingWeb_Timer = 16000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLT); + ShadowBolt_Timer = 7000; + } else ShadowBolt_Timer -= diff; + + //CurseOfTongues_Timer + if (CurseOfTongues_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CURSEOFTONGUES); + CurseOfTongues_Timer = 18000; + } else CurseOfTongues_Timer -= diff; + + //CurseOfWeakness_Timer + if (CurseOfWeakness_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); + CurseOfWeakness_Timer = 45000; + } else CurseOfWeakness_Timer -= diff; + + //DemonArmor_Timer + if (DemonArmor_Timer <= diff) + { + DoCast(me, SPELL_DEMONARMOR); + DemonArmor_Timer = 300000; + } else DemonArmor_Timer -= diff; + + //EnvelopingWeb_Timer + if (EnvelopingWeb_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ENVELOPINGWEB); + EnvelopingWeb_Timer = 12000; + } else EnvelopingWeb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_anubshiah(Creature* pCreature) +{ + return new boss_anubshiahAI (pCreature); +} + +void AddSC_boss_anubshiah() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_anubshiah"; + newscript->GetAI = &GetAI_boss_anubshiah; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp new file mode 100644 index 00000000000..29fe219d6ec --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp @@ -0,0 +1,111 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Emperor_Dagran_Thaurissan +SD%Complete: 99 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Yells +{ + SAY_AGGRO = -1230001, + SAY_SLAY = -1230002 +}; + +enum Spells +{ + SPELL_HANDOFTHAURISSAN = 17492, + SPELL_AVATAROFFLAME = 15636 +}; + +struct boss_draganthaurissanAI : public ScriptedAI +{ + boss_draganthaurissanAI(Creature *c) : ScriptedAI(c) {} + + uint32 HandOfThaurissan_Timer; + uint32 AvatarOfFlame_Timer; + //uint32 Counter; + + void Reset() + { + HandOfThaurissan_Timer = 4000; + AvatarOfFlame_Timer = 25000; + //Counter= 0; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + me->CallForHelp(VISIBLE_RANGE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (HandOfThaurissan_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_HANDOFTHAURISSAN); + + //3 Hands of Thaurissan will be casted + //if (Counter < 3) + //{ + // HandOfThaurissan_Timer = 1000; + // ++Counter; + //} + //else + //{ + HandOfThaurissan_Timer = 5000; + //Counter = 0; + //} + } else HandOfThaurissan_Timer -= diff; + + //AvatarOfFlame_Timer + if (AvatarOfFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_AVATAROFFLAME); + AvatarOfFlame_Timer = 18000; + } else AvatarOfFlame_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_draganthaurissan(Creature* pCreature) +{ + return new boss_draganthaurissanAI (pCreature); +} + +void AddSC_boss_draganthaurissan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_emperor_dagran_thaurissan"; + newscript->GetAI = &GetAI_boss_draganthaurissan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_general_angerforge.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_general_angerforge.cpp new file mode 100644 index 00000000000..77d69263133 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_general_angerforge.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_General_Angerforge +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_MIGHTYBLOW = 14099, + SPELL_HAMSTRING = 9080, + SPELL_CLEAVE = 20691 +}; + +struct boss_general_angerforgeAI : public ScriptedAI +{ + boss_general_angerforgeAI(Creature *c) : ScriptedAI(c) {} + + uint32 MightyBlow_Timer; + uint32 HamString_Timer; + uint32 Cleave_Timer; + uint32 Adds_Timer; + bool Medics; + + void Reset() + { + MightyBlow_Timer = 8000; + HamString_Timer = 12000; + Cleave_Timer = 16000; + Adds_Timer = 0; + Medics = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonAdds(Unit* victim) + { + if (Creature *SummonedAdd = DoSpawnCreature(8901, irand(-14,14), irand(-14,14), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedAdd->AI()->AttackStart(victim); + } + + void SummonMedics(Unit* victim) + { + if (Creature *SummonedMedic = DoSpawnCreature(8894, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedMedic->AI()->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //MightyBlow_Timer + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTYBLOW); + MightyBlow_Timer = 18000; + } else MightyBlow_Timer -= diff; + + //HamString_Timer + if (HamString_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + HamString_Timer = 15000; + } else HamString_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 9000; + } else Cleave_Timer -= diff; + + //Adds_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 21) + { + if (Adds_Timer <= diff) + { + // summon 3 Adds every 25s + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + + Adds_Timer = 25000; + } else Adds_Timer -= diff; + } + + //Summon Medics + if (!Medics && me->GetHealth()*100 / me->GetMaxHealth() < 21) + { + SummonMedics(me->getVictim()); + SummonMedics(me->getVictim()); + Medics = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_general_angerforge(Creature* pCreature) +{ + return new boss_general_angerforgeAI (pCreature); +} + +void AddSC_boss_general_angerforge() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_general_angerforge"; + newscript->GetAI = &GetAI_boss_general_angerforge; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_gorosh_the_dervish.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_gorosh_the_dervish.cpp new file mode 100644 index 00000000000..886bc3fc909 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_gorosh_the_dervish.cpp @@ -0,0 +1,84 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gorosh_the_Dervish +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_WHIRLWIND = 15589, + SPELL_MORTALSTRIKE = 24573 +}; + +struct boss_gorosh_the_dervishAI : public ScriptedAI +{ + boss_gorosh_the_dervishAI(Creature *c) : ScriptedAI(c) {} + + uint32 WhirlWind_Timer; + uint32 MortalStrike_Timer; + + void Reset() + { + WhirlWind_Timer = 12000; + MortalStrike_Timer = 22000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //WhirlWind_Timer + if (WhirlWind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + WhirlWind_Timer = 15000; + } else WhirlWind_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 15000; + } else MortalStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gorosh_the_dervish(Creature* pCreature) +{ + return new boss_gorosh_the_dervishAI (pCreature); +} + +void AddSC_boss_gorosh_the_dervish() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gorosh_the_dervish"; + newscript->GetAI = &GetAI_boss_gorosh_the_dervish; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_grizzle.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_grizzle.cpp new file mode 100644 index 00000000000..d3551d38790 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_grizzle.cpp @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grizzle +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Yells +{ + EMOTE_GENERIC_FRENZY_KILL = -1000001 +}; + +enum Spells +{ + SPELL_GROUNDTREMOR = 6524, + SPELL_FRENZY = 28371 +}; + +struct boss_grizzleAI : public ScriptedAI +{ + boss_grizzleAI(Creature *c) : ScriptedAI(c) {} + + uint32 GroundTremor_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + GroundTremor_Timer = 12000; + Frenzy_Timer =0; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //GroundTremor_Timer + if (GroundTremor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GROUNDTREMOR); + GroundTremor_Timer = 8000; + } else GroundTremor_Timer -= diff; + + //Frenzy_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + if (Frenzy_Timer <= diff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); + + Frenzy_Timer = 15000; + } else Frenzy_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grizzle(Creature* pCreature) +{ + return new boss_grizzleAI (pCreature); +} + +void AddSC_boss_grizzle() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grizzle"; + newscript->GetAI = &GetAI_boss_grizzle; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_high_interrogator_gerstahn.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_high_interrogator_gerstahn.cpp new file mode 100644 index 00000000000..2af203826a1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_high_interrogator_gerstahn.cpp @@ -0,0 +1,106 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Interrogator_Gerstahn +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_SHADOWWORDPAIN = 10894, + SPELL_MANABURN = 10876, + SPELL_PSYCHICSCREAM = 8122, + SPELL_SHADOWSHIELD = 22417 +}; + +struct boss_high_interrogator_gerstahnAI : public ScriptedAI +{ + boss_high_interrogator_gerstahnAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowWordPain_Timer; + uint32 ManaBurn_Timer; + uint32 PsychicScream_Timer; + uint32 ShadowShield_Timer; + + void Reset() + { + ShadowWordPain_Timer = 4000; + ManaBurn_Timer = 14000; + PsychicScream_Timer = 32000; + ShadowShield_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 7000; + } else ShadowWordPain_Timer -= diff; + + //ManaBurn_Timer + if (ManaBurn_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_MANABURN); + ManaBurn_Timer = 10000; + } else ManaBurn_Timer -= diff; + + //PsychicScream_Timer + if (PsychicScream_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PSYCHICSCREAM); + PsychicScream_Timer = 30000; + } else PsychicScream_Timer -= diff; + + //ShadowShield_Timer + if (ShadowShield_Timer <= diff) + { + DoCast(me, SPELL_SHADOWSHIELD); + ShadowShield_Timer = 25000; + } else ShadowShield_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_high_interrogator_gerstahn(Creature* pCreature) +{ + return new boss_high_interrogator_gerstahnAI (pCreature); +} + +void AddSC_boss_high_interrogator_gerstahn() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_high_interrogator_gerstahn"; + newscript->GetAI = &GetAI_boss_high_interrogator_gerstahn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_magmus.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_magmus.cpp new file mode 100644 index 00000000000..2a0cf9be133 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_magmus.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Magmus +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_FIERYBURST = 13900, + SPELL_WARSTOMP = 24375 +}; + +enum eEnums +{ + DATA_THRONE_DOOR = 24 // not id or guid of doors but number of enum in blackrock_depths.h +}; + +struct boss_magmusAI : public ScriptedAI +{ + boss_magmusAI(Creature *c) : ScriptedAI(c) {} + + uint32 FieryBurst_Timer; + uint32 WarStomp_Timer; + + void Reset() + { + FieryBurst_Timer = 5000; + WarStomp_Timer =0; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FieryBurst_Timer + if (FieryBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIERYBURST); + FieryBurst_Timer = 6000; + } else FieryBurst_Timer -= diff; + + //WarStomp_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + if (WarStomp_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WARSTOMP); + WarStomp_Timer = 8000; + } else WarStomp_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + // When he die open door to last chamber + void JustDied(Unit *who) + { + if (ScriptedInstance* pInstance = who->GetInstanceData()) + pInstance->HandleGameObject(pInstance->GetData64(DATA_THRONE_DOOR), true); + } +}; +CreatureAI* GetAI_boss_magmus(Creature* pCreature) +{ + return new boss_magmusAI (pCreature); +} + +void AddSC_boss_magmus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magmus"; + newscript->GetAI = &GetAI_boss_magmus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_moira_bronzebeard.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_moira_bronzebeard.cpp new file mode 100644 index 00000000000..1c0ed389287 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_moira_bronzebeard.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moira_Bronzbeard +SD%Complete: 90 +SDComment: Healing of Emperor NYI +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" + +enum Spells +{ + SPELL_HEAL = 10917, + SPELL_RENEW = 10929, + SPELL_SHIELD = 10901, + SPELL_MINDBLAST = 10947, + SPELL_SHADOWWORDPAIN = 10894, + SPELL_SMITE = 10934 +}; + +struct boss_moira_bronzebeardAI : public ScriptedAI +{ + boss_moira_bronzebeardAI(Creature *c) : ScriptedAI(c) {} + + uint32 Heal_Timer; + uint32 MindBlast_Timer; + uint32 ShadowWordPain_Timer; + uint32 Smite_Timer; + + void Reset() + { + Heal_Timer = 12000; //These times are probably wrong + MindBlast_Timer = 16000; + ShadowWordPain_Timer = 2000; + Smite_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //MindBlast_Timer + if (MindBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MINDBLAST); + MindBlast_Timer = 14000; + } else MindBlast_Timer -= diff; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 18000; + } else ShadowWordPain_Timer -= diff; + + //Smite_Timer + if (Smite_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SMITE); + Smite_Timer = 10000; + } else Smite_Timer -= diff; + + } +}; +CreatureAI* GetAI_boss_moira_bronzebeard(Creature* pCreature) +{ + return new boss_moira_bronzebeardAI (pCreature); +} + +void AddSC_boss_moira_bronzebeard() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_moira_bronzebeard"; + newscript->GetAI = &GetAI_boss_moira_bronzebeard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_tomb_of_seven.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_tomb_of_seven.cpp new file mode 100644 index 00000000000..94a37e8da7e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/boss_tomb_of_seven.cpp @@ -0,0 +1,254 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Tomb_Of_Seven +SD%Complete: 90 +SDComment: Learning Smelt Dark Iron if tribute quest rewarded. Missing event. +SDCategory: Blackrock Depths +EndScriptData */ + +#include "ScriptedPch.h" +#include "blackrock_depths.h" + +enum Spells +{ + SPELL_SMELT_DARK_IRON = 14891, + SPELL_LEARN_SMELT = 14894, +}; + +enum Quests +{ + QUEST_SPECTRAL_CHALICE = 4083 +}; + +enum Misc +{ + DATA_SKILLPOINT_MIN = 230 +}; + +#define GOSSIP_ITEM_TEACH_1 "Teach me the art of smelting dark iron" +#define GOSSIP_ITEM_TEACH_2 "Continue..." +#define GOSSIP_ITEM_TEACH_3 "[PH] Continue..." +#define GOSSIP_ITEM_TRIBUTE "I want to pay tribute" + +bool GossipHello_boss_gloomrel(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 1 && pPlayer->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN && !pPlayer->HasSpell(SPELL_SMELT_DARK_IRON)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 0 && pPlayer->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TRIBUTE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_boss_gloomrel(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + pPlayer->SEND_GOSSIP_MENU(2606, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer, SPELL_LEARN_SMELT, false); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); + pPlayer->SEND_GOSSIP_MENU(2604, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+22: + pPlayer->CLOSE_GOSSIP_MENU(); + if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) + { + //are 5 minutes expected? go template may have data to despawn when used at quest + pInstance->DoRespawnGameObject(pInstance->GetData64(DATA_GO_CHALICE),MINUTE*5); + } + break; + } + return true; +} + +enum DoomrelSpells +{ + SPELL_SHADOWBOLTVOLLEY = 15245, + SPELL_IMMOLATE = 12742, + SPELL_CURSEOFWEAKNESS = 12493, + SPELL_DEMONARMOR = 13787, + SPELL_SUMMON_VOIDWALKERS = 15092 +}; + +struct boss_doomrelAI : public ScriptedAI +{ + boss_doomrelAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 ShadowVolley_Timer; + uint32 Immolate_Timer; + uint32 CurseOfWeakness_Timer; + uint32 DemonArmor_Timer; + bool Voidwalkers; + + void Reset() + { + ShadowVolley_Timer = 10000; + Immolate_Timer = 18000; + CurseOfWeakness_Timer = 5000; + DemonArmor_Timer = 16000; + Voidwalkers = false; + + me->setFaction(FACTION_FRIEND); + + // was set before event start, so set again + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + + if (pInstance) + if (pInstance->GetData(DATA_GHOSTKILL) >= 7) + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + else + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void EnterEvadeMode() + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + me->LoadCreaturesAddon(); + if (me->isAlive()) + me->GetMotionMaster()->MoveTargetedHome(); + me->SetLootRecipient(NULL); + if (pInstance) + pInstance->SetData64(DATA_EVENSTARTER, 0); + } + + void JustDied(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_GHOSTKILL, 1); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLTVOLLEY); + ShadowVolley_Timer = 12000; + } else ShadowVolley_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_IMMOLATE); + + Immolate_Timer = 25000; + } else Immolate_Timer -= diff; + + //CurseOfWeakness_Timer + if (CurseOfWeakness_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); + CurseOfWeakness_Timer = 45000; + } else CurseOfWeakness_Timer -= diff; + + //DemonArmor_Timer + if (DemonArmor_Timer <= diff) + { + DoCast(me, SPELL_DEMONARMOR); + DemonArmor_Timer = 300000; + } else DemonArmor_Timer -= diff; + + //Summon Voidwalkers + if (!Voidwalkers && me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + DoCast(me->getVictim(), SPELL_SUMMON_VOIDWALKERS, true); + Voidwalkers = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_doomrel(Creature* pCreature) +{ + return new boss_doomrelAI (pCreature); +} + +#define GOSSIP_ITEM_CHALLENGE "Your bondage is at an end, Doom'rel. I challenge you!" +#define GOSSIP_SELECT_DOOMREL "[PH] Continue..." + +bool GossipHello_boss_doomrel(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(2601, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_boss_doomrel(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_DOOMREL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(2605, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + //start event here + pCreature->setFaction(FACTION_HOSTILE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pCreature->AI()->AttackStart(pPlayer); + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance) + pInstance->SetData64(DATA_EVENSTARTER,pPlayer->GetGUID()); + break; + } + return true; +} + +void AddSC_boss_tomb_of_seven() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_gloomrel"; + newscript->pGossipHello = &GossipHello_boss_gloomrel; + newscript->pGossipSelect = &GossipSelect_boss_gloomrel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_doomrel"; + newscript->GetAI = &GetAI_boss_doomrel; + newscript->pGossipHello = &GossipHello_boss_doomrel; + newscript->pGossipSelect = &GossipSelect_boss_doomrel; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockDepths/instance_blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockDepths/instance_blackrock_depths.cpp new file mode 100644 index 00000000000..7684aa6c6ac --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockDepths/instance_blackrock_depths.cpp @@ -0,0 +1,460 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Blackrock_Depths +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Depths +EndScriptData */ + +/* +update `creature_template` set `npcflag`='1',`ScriptName`='npc_dughal_stormwing' where `entry`='9022'; +update `creature_template` set `ScriptName`='npc_marshal_windsor' where `entry`='9023'; +update `creature_template` set `ScriptName`='npc_marshal_reginald_windsor' where `entry`='9682'; +update `creature_template` set `npcflag`='1',`ScriptName`='npc_tobias_seecher' where `entry`='9679'; +update `instance_template` set `script`='instance_blackrock_depths' where `map`='230'; +*/ + +#include "ScriptedPch.h" +#include "blackrock_depths.h" + +#define TIMER_TOMBOFTHESEVEN 15000 + +enum eEnums +{ + MAX_ENCOUNTER = 6, + + NPC_EMPEROR = 9019, + NPC_PHALANX = 9502, + NPC_ANGERREL = 9035, + NPC_DOPEREL = 9040, + NPC_HATEREL = 9034, + NPC_VILEREL = 9036, + NPC_SEETHREL = 9038, + NPC_GLOOMREL = 9037, + NPC_DOOMREL = 9039, + NPC_MAGMUS = 9938, + + GO_ARENA1 = 161525, + GO_ARENA2 = 161522, + GO_ARENA3 = 161524, + GO_ARENA4 = 161523, + GO_SHADOW_LOCK = 161460, + GO_SHADOW_MECHANISM = 161461, + GO_SHADOW_GIANT_DOOR = 157923, + GO_SHADOW_DUMMY = 161516, + GO_BAR_KEG_SHOT = 170607, + GO_BAR_KEG_TRAP = 171941, + GO_BAR_DOOR = 170571, + GO_TOMB_ENTER = 170576, + GO_TOMB_EXIT = 170577, + GO_LYCEUM = 170558, + GO_SF_N = 174745, // Shadowforge Brazier North + GO_SF_S = 174744, // Shadowforge Brazier South + GO_GOLEM_ROOM_N = 170573, // Magmus door North + GO_GOLEM_ROOM_S = 170574, // Magmus door Soutsh + GO_THRONE_ROOM = 170575, // Throne door + + GO_SPECTRAL_CHALICE = 164869, + GO_CHEST_SEVEN = 169243 +}; + +struct instance_blackrock_depths : public ScriptedInstance +{ + instance_blackrock_depths(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 EmperorGUID; + uint64 PhalanxGUID; + uint64 MagmusGUID; + + uint64 GoArena1GUID; + uint64 GoArena2GUID; + uint64 GoArena3GUID; + uint64 GoArena4GUID; + uint64 GoShadowLockGUID; + uint64 GoShadowMechGUID; + uint64 GoShadowGiantGUID; + uint64 GoShadowDummyGUID; + uint64 GoBarKegGUID; + uint64 GoBarKegTrapGUID; + uint64 GoBarDoorGUID; + uint64 GoTombEnterGUID; + uint64 GoTombExitGUID; + uint64 GoLyceumGUID; + uint64 GoSFSGUID; + uint64 GoSFNGUID; + uint64 GoGolemNGUID; + uint64 GoGolemSGUID; + uint64 GoThroneGUID; + uint64 GoChestGUID; + + uint32 BarAleCount; + uint32 GhostKillCount; + uint64 TombBossGUIDs[7]; + uint64 TombEventStarterGUID; + uint32 TombTimer; + uint32 TombEventCounter; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + EmperorGUID = 0; + PhalanxGUID = 0; + MagmusGUID = 0; + + GoArena1GUID = 0; + GoArena2GUID = 0; + GoArena3GUID = 0; + GoArena4GUID = 0; + GoShadowLockGUID = 0; + GoShadowMechGUID = 0; + GoShadowGiantGUID = 0; + GoShadowDummyGUID = 0; + GoBarKegGUID = 0; + GoBarKegTrapGUID = 0; + GoBarDoorGUID = 0; + GoTombEnterGUID = 0; + GoTombExitGUID = 0; + GoLyceumGUID = 0; + GoSFSGUID = 0; + GoSFNGUID = 0; + GoGolemNGUID = 0; + GoGolemSGUID = 0; + GoThroneGUID = 0; + GoChestGUID = 0; + + BarAleCount = 0; + GhostKillCount = 0; + TombEventStarterGUID = 0; + TombTimer = TIMER_TOMBOFTHESEVEN; + TombEventCounter = 0; + + for (uint8 i = 0; i < 7; ++i) + TombBossGUIDs[i] = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_EMPEROR: EmperorGUID = pCreature->GetGUID(); break; + case NPC_PHALANX: PhalanxGUID = pCreature->GetGUID(); break; + case NPC_DOOMREL: TombBossGUIDs[0] = pCreature->GetGUID(); break; + case NPC_DOPEREL: TombBossGUIDs[1] = pCreature->GetGUID(); break; + case NPC_HATEREL: TombBossGUIDs[2] = pCreature->GetGUID(); break; + case NPC_VILEREL: TombBossGUIDs[3] = pCreature->GetGUID(); break; + case NPC_SEETHREL: TombBossGUIDs[4] = pCreature->GetGUID(); break; + case NPC_GLOOMREL: TombBossGUIDs[5] = pCreature->GetGUID(); break; + case NPC_ANGERREL: TombBossGUIDs[6] = pCreature->GetGUID(); break; + case NPC_MAGMUS: + MagmusGUID = pCreature->GetGUID(); + if (!pCreature->isAlive()) + HandleGameObject(GetData64(DATA_THRONE_DOOR), true); // if Magmus is dead open door to last boss + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_ARENA1: GoArena1GUID = pGo->GetGUID(); break; + case GO_ARENA2: GoArena2GUID = pGo->GetGUID(); break; + case GO_ARENA3: GoArena3GUID = pGo->GetGUID(); break; + case GO_ARENA4: GoArena4GUID = pGo->GetGUID(); break; + case GO_SHADOW_LOCK: GoShadowLockGUID = pGo->GetGUID(); break; + case GO_SHADOW_MECHANISM: GoShadowMechGUID = pGo->GetGUID(); break; + case GO_SHADOW_GIANT_DOOR: GoShadowGiantGUID = pGo->GetGUID(); break; + case GO_SHADOW_DUMMY: GoShadowDummyGUID = pGo->GetGUID(); break; + case GO_BAR_KEG_SHOT: GoBarKegGUID = pGo->GetGUID(); break; + case GO_BAR_KEG_TRAP: GoBarKegTrapGUID = pGo->GetGUID(); break; + case GO_BAR_DOOR: GoBarDoorGUID = pGo->GetGUID(); break; + case GO_TOMB_ENTER: GoTombEnterGUID = pGo->GetGUID(); break; + case GO_TOMB_EXIT: + GoTombExitGUID = pGo->GetGUID(); + if (GhostKillCount >= 7) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + case GO_LYCEUM: GoLyceumGUID = pGo->GetGUID(); break; + case GO_SF_S: GoSFSGUID = pGo->GetGUID(); break; + case GO_SF_N: GoSFNGUID = pGo->GetGUID(); break; + case GO_GOLEM_ROOM_N: GoGolemNGUID = pGo->GetGUID(); break; + case GO_GOLEM_ROOM_S: GoGolemSGUID = pGo->GetGUID(); break; + case GO_THRONE_ROOM: GoThroneGUID = pGo->GetGUID(); break; + case GO_CHEST_SEVEN: GoChestGUID = pGo->GetGUID(); break; + } + } + + void SetData64(uint32 type, uint64 data) + { + debug_log("TSCR: Instance Blackrock Depths: SetData64 update (Type: %u Data %u)", type, data); + + switch(type) + { + case DATA_EVENSTARTER: + TombEventStarterGUID = data; + if (!TombEventStarterGUID) + TombOfSevenReset();//reset + else + TombOfSevenStart();//start + break; + } + } + + void SetData(uint32 type, uint32 data) + { + debug_log("TSCR: Instance Blackrock Depths: SetData update (Type: %u Data %u)", type, data); + + switch(type) + { + case TYPE_RING_OF_LAW: + m_auiEncounter[0] = data; + break; + case TYPE_VAULT: + m_auiEncounter[1] = data; + break; + case TYPE_BAR: + if (data == SPECIAL) + ++BarAleCount; + else + m_auiEncounter[2] = data; + break; + case TYPE_TOMB_OF_SEVEN: + m_auiEncounter[3] = data; + break; + case TYPE_LYCEUM: + m_auiEncounter[4] = data; + break; + case TYPE_IRON_HALL: + m_auiEncounter[5] = data; + break; + case DATA_GHOSTKILL: + GhostKillCount += data; + break; + } + + if (data == DONE || GhostKillCount >= 7) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << GhostKillCount; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_RING_OF_LAW: + return m_auiEncounter[0]; + case TYPE_VAULT: + return m_auiEncounter[1]; + case TYPE_BAR: + if (m_auiEncounter[2] == IN_PROGRESS && BarAleCount == 3) + return SPECIAL; + else + return m_auiEncounter[2]; + case TYPE_TOMB_OF_SEVEN: + return m_auiEncounter[3]; + case TYPE_LYCEUM: + return m_auiEncounter[4]; + case TYPE_IRON_HALL: + return m_auiEncounter[5]; + case DATA_GHOSTKILL: + return GhostKillCount; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_EMPEROR: + return EmperorGUID; + case DATA_PHALANX: + return PhalanxGUID; + case DATA_ARENA1: + return GoArena1GUID; + case DATA_ARENA2: + return GoArena2GUID; + case DATA_ARENA3: + return GoArena3GUID; + case DATA_ARENA4: + return GoArena4GUID; + case DATA_GO_BAR_KEG: + return GoBarKegGUID; + case DATA_GO_BAR_KEG_TRAP: + return GoBarKegTrapGUID; + case DATA_GO_BAR_DOOR: + return GoBarDoorGUID; + case DATA_EVENSTARTER: + return TombEventStarterGUID; + case DATA_SF_BRAZIER_N: + return GoSFNGUID; + case DATA_SF_BRAZIER_S: + return GoSFSGUID; + case DATA_THRONE_DOOR: + return GoThroneGUID; + case DATA_GOLEM_DOOR_N: + return GoGolemNGUID; + case DATA_GOLEM_DOOR_S: + return GoGolemSGUID; + } + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> GhostKillCount; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + if (GhostKillCount > 0 && GhostKillCount < 7) + GhostKillCount = 0;//reset tomb of seven event + if (GhostKillCount >= 7) + GhostKillCount = 7; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void TombOfSevenEvent() + { + if (GhostKillCount < 7 && TombBossGUIDs[TombEventCounter]) + { + if (Creature* boss = instance->GetCreature(TombBossGUIDs[TombEventCounter])) + { + boss->setFaction(FACTION_HOSTILE); + boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + if (Unit *pTarget = boss->SelectNearestTarget(500)) + boss->AI()->AttackStart(pTarget); + } + } + } + + void TombOfSevenReset() + { + HandleGameObject(GoTombExitGUID,false);//event reseted, close exit door + HandleGameObject(GoTombEnterGUID,true);//event reseted, open entrance door + for (uint8 i = 0; i < 7; ++i) + { + if (Creature* boss = instance->GetCreature(TombBossGUIDs[i])) + { + if (!boss->isAlive()) + {//do not call EnterEvadeMode(), it will create infinit loops + boss->Respawn(); + boss->RemoveAllAuras(); + boss->DeleteThreatList(); + boss->CombatStop(true); + boss->LoadCreaturesAddon(); + boss->GetMotionMaster()->MoveTargetedHome(); + boss->SetLootRecipient(NULL); + } + boss->setFaction(FACTION_FRIEND); + } + } + GhostKillCount = 0; + TombEventStarterGUID = 0; + TombEventCounter = 0; + TombTimer = TIMER_TOMBOFTHESEVEN; + SetData(TYPE_TOMB_OF_SEVEN, NOT_STARTED); + } + + void TombOfSevenStart() + { + HandleGameObject(GoTombExitGUID,false);//event started, close exit door + HandleGameObject(GoTombEnterGUID,false);//event started, close entrance door + SetData(TYPE_TOMB_OF_SEVEN, IN_PROGRESS); + } + + void TombOfSevenEnd() + { + DoRespawnGameObject(GoChestGUID,DAY); + HandleGameObject(GoTombExitGUID,true);//event done, open exit door + HandleGameObject(GoTombEnterGUID,true);//event done, open entrance door + TombEventStarterGUID = 0; + SetData(TYPE_TOMB_OF_SEVEN, DONE); + } + void Update(uint32 diff) + { + if (TombEventStarterGUID && GhostKillCount < 7) + { + if (TombTimer <= diff) + { + TombTimer = TIMER_TOMBOFTHESEVEN; + ++TombEventCounter; + TombOfSevenEvent(); + // Check Killed bosses + for (uint8 i = 0; i < 7; ++i) + { + if (Creature* boss = instance->GetCreature(TombBossGUIDs[i])) + { + if (!boss->isAlive()) + { + GhostKillCount = i+1; + } + } + } + } else TombTimer -= diff; + } + if (GhostKillCount >= 7 && TombEventStarterGUID) + TombOfSevenEnd(); + } +}; + +InstanceData* GetInstanceData_instance_blackrock_depths(Map* pMap) +{ + return new instance_blackrock_depths(pMap); +} + + void AddSC_instance_blackrock_depths() + { + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blackrock_depths"; + newscript->GetInstanceData = &GetInstanceData_instance_blackrock_depths; + newscript->RegisterSelf(); + } diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.cpp new file mode 100644 index 00000000000..2ea115e6e0b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.cpp @@ -0,0 +1,77 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "blackrock_spire.h" + +enum Creatures +{ + NPC_ROOKERY_WHELP = 10161 +}; + +struct npc_rookey_whelpAI : public ScriptedAI +{ + npc_rookey_whelpAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void JustDied(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(WHELP_DEATH_COUNT, pInstance->GetData(WHELP_DEATH_COUNT)+1); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_rookey_whelp(Creature* pCreature) +{ + return new npc_rookey_whelpAI(pCreature); +} + +bool GOHello_rookey_egg(Player *pPlayer, GameObject * /*pGO*/) +{ + Position pos; + pPlayer->GetPosition(&pos); + pPlayer->SummonCreature(NPC_ROOKERY_WHELP, pos, TEMPSUMMON_TIMED_DESPAWN, 15*IN_MILISECONDS); + //destroy gobject need to be implemented + + return true; +}; + +void AddSC_blackrock_spire() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_rookey_whelp"; + newscript->GetAI = &GetAI_rookey_whelp; + newscript->RegisterSelf(); + newscript = new Script; + + newscript->Name = "go_rookey_egg"; + newscript->pGOHello = &GOHello_rookey_egg; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h new file mode 100644 index 00000000000..56b6e0cbe23 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_BRS_H +#define DEF_BRS_H + +enum Data +{ + EVENT_LEEEROY, + WHELP_DEATH_COUNT +}; + +#endif diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp new file mode 100644 index 00000000000..b53ddaf23ef --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_drakkisath.cpp @@ -0,0 +1,102 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Drakkisath +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FIRENOVA 23462 +#define SPELL_CLEAVE 20691 +#define SPELL_CONFLIGURATION 16805 +#define SPELL_THUNDERCLAP 15548 //Not sure if right ID. 23931 would be a harder possibility. + +struct boss_drakkisathAI : public ScriptedAI +{ + boss_drakkisathAI(Creature *c) : ScriptedAI(c) {} + + uint32 FireNova_Timer; + uint32 Cleave_Timer; + uint32 Confliguration_Timer; + uint32 Thunderclap_Timer; + + void Reset() + { + FireNova_Timer = 6000; + Cleave_Timer = 8000; + Confliguration_Timer = 15000; + Thunderclap_Timer = 17000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FireNova_Timer + if (FireNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRENOVA); + FireNova_Timer = 10000; + } else FireNova_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 8000; + } else Cleave_Timer -= diff; + + //Confliguration_Timer + if (Confliguration_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CONFLIGURATION); + Confliguration_Timer = 18000; + } else Confliguration_Timer -= diff; + + //Thunderclap_Timer + if (Thunderclap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + Thunderclap_Timer = 20000; + } else Thunderclap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_drakkisath(Creature* pCreature) +{ + return new boss_drakkisathAI (pCreature); +} + +void AddSC_boss_drakkisath() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_drakkisath"; + newscript->GetAI = &GetAI_boss_drakkisath; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp new file mode 100644 index 00000000000..fcd2ea1a6d0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_gyth.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gyth +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CORROSIVEACID 20667 +#define SPELL_FREEZE 18763 +#define SPELL_FLAMEBREATH 20712 + +struct boss_gythAI : public ScriptedAI +{ + boss_gythAI(Creature *c) : ScriptedAI(c) {} + + uint32 Aggro_Timer; + uint32 Dragons_Timer; + uint32 Orc_Timer; + uint32 CorrosiveAcid_Timer; + uint32 Freeze_Timer; + uint32 Flamebreath_Timer; + uint32 Line1Count; + uint32 Line2Count; + + bool Event; + bool SummonedDragons; + bool SummonedOrcs; + bool SummonedRend; + bool bAggro; + bool RootSelf; + + void Reset() + { + Dragons_Timer = 3000; + Orc_Timer = 60000; + Aggro_Timer = 60000; + CorrosiveAcid_Timer = 8000; + Freeze_Timer = 11000; + Flamebreath_Timer = 4000; + Event = false; + SummonedDragons = false; + SummonedOrcs= false; + SummonedRend = false; + bAggro = false; + RootSelf = false; + + // how many times should the two lines of summoned creatures be spawned + // min 2 x 2, max 7 lines of attack in total + Line1Count = rand() % 4 + 2; + if (Line1Count < 5) + Line2Count = rand() % (5 - Line1Count) + 2; + else + Line2Count = 2; + + //Invisible for event start + me->SetDisplayId(11686); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonCreatureWithRandomTarget(uint32 creatureId) + { + Unit* Summoned = me->SummonCreature(creatureId, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240000); + if (Summoned) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Summoned->AddThreat(pTarget, 1.0f); + } + } + + void UpdateAI(const uint32 diff) + { + //char buf[200]; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!RootSelf) + { + //me->m_canMove = true; + DoCast(me, 33356); + RootSelf = true; + } + + if (!bAggro && Line1Count == 0 && Line2Count == 0) + { + if (Aggro_Timer <= diff) + { + bAggro = true; + // Visible now! + me->SetDisplayId(9723); + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } else Aggro_Timer -= diff; + } + + // Summon Dragon pack. 2 Dragons and 3 Whelps + if (!bAggro && !SummonedRend && Line1Count > 0) + { + if (Dragons_Timer <= diff) + { + SummonCreatureWithRandomTarget(10372); + SummonCreatureWithRandomTarget(10372); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + Line1Count = Line1Count - 1; + Dragons_Timer = 60000; + } else Dragons_Timer -= diff; + } + + //Summon Orc pack. 1 Orc Handler 1 Elite Dragonkin and 3 Whelps + if (!bAggro && !SummonedRend && Line1Count == 0 && Line2Count > 0) + { + if (Orc_Timer <= diff) + { + SummonCreatureWithRandomTarget(10447); + SummonCreatureWithRandomTarget(10317); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + SummonCreatureWithRandomTarget(10442); + Line2Count = Line2Count - 1; + Orc_Timer = 60000; + } else Orc_Timer -= diff; + } + + // we take part in the fight + if (bAggro) + { + // CorrosiveAcid_Timer + if (CorrosiveAcid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVEACID); + CorrosiveAcid_Timer = 7000; + } else CorrosiveAcid_Timer -= diff; + + // Freeze_Timer + if (Freeze_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FREEZE); + Freeze_Timer = 16000; + } else Freeze_Timer -= diff; + + // Flamebreath_Timer + if (Flamebreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBREATH); + Flamebreath_Timer = 10500; + } else Flamebreath_Timer -= diff; + + //Summon Rend + if (!SummonedRend && me->GetHealth()*100 / me->GetMaxHealth() < 11 + && me->GetHealth() > 0) + { + //summon Rend and Change model to normal Gyth + //Inturrupt any spell casting + me->InterruptNonMeleeSpells(false); + //Gyth model + me->SetDisplayId(9806); + me->SummonCreature(10429, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000); + SummonedRend = true; + } + + DoMeleeAttackIfReady(); + } // end if Aggro + } +}; + +CreatureAI* GetAI_boss_gyth(Creature* pCreature) +{ + return new boss_gythAI (pCreature); +} + +void AddSC_boss_gyth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gyth"; + newscript->GetAI = &GetAI_boss_gyth; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_halycon.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_halycon.cpp new file mode 100644 index 00000000000..9e78667717a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_halycon.cpp @@ -0,0 +1,96 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Halycon +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CROWDPUMMEL 10887 +#define SPELL_MIGHTYBLOW 14099 + +#define ADD_1X -169.839203 +#define ADD_1Y -324.961395 +#define ADD_1Z 64.401443 +#define ADD_1O 3.124724 + +struct boss_halyconAI : public ScriptedAI +{ + boss_halyconAI(Creature *c) : ScriptedAI(c) {} + + uint32 CrowdPummel_Timer; + uint32 MightyBlow_Timer; + bool Summoned; + + void Reset() + { + CrowdPummel_Timer = 8000; + MightyBlow_Timer = 14000; + Summoned = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //CrowdPummel_Timer + if (CrowdPummel_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CROWDPUMMEL); + CrowdPummel_Timer = 14000; + } else CrowdPummel_Timer -= diff; + + //MightyBlow_Timer + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTYBLOW); + MightyBlow_Timer = 10000; + } else MightyBlow_Timer -= diff; + + //Summon Gizrul + if (!Summoned && me->GetHealth()*100 / me->GetMaxHealth() < 25) + { + me->SummonCreature(10268,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000); + Summoned = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_halycon(Creature* pCreature) +{ + return new boss_halyconAI (pCreature); +} + +void AddSC_boss_halycon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_halycon"; + newscript->GetAI = &GetAI_boss_halycon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_highlord_omokk.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_highlord_omokk.cpp new file mode 100644 index 00000000000..65f1e8081a0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_highlord_omokk.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Highlord_Omokk +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_WARSTOMP 24375 +#define SPELL_CLEAVE 15579 +#define SPELL_STRIKE 18368 +#define SPELL_REND 18106 +#define SPELL_SUNDERARMOR 24317 +#define SPELL_KNOCKAWAY 20686 +#define SPELL_SLOW 22356 + +struct boss_highlordomokkAI : public ScriptedAI +{ + boss_highlordomokkAI(Creature *c) : ScriptedAI(c) {} + + uint32 WarStomp_Timer; + uint32 Cleave_Timer; + uint32 Strike_Timer; + uint32 Rend_Timer; + uint32 SunderArmor_Timer; + uint32 KnockAway_Timer; + uint32 Slow_Timer; + + void Reset() + { + WarStomp_Timer = 15000; + Cleave_Timer = 6000; + Strike_Timer = 10000; + Rend_Timer = 14000; + SunderArmor_Timer = 2000; + KnockAway_Timer = 18000; + Slow_Timer = 24000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //WarStomp_Timer + if (WarStomp_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WARSTOMP); + WarStomp_Timer = 14000; + } else WarStomp_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 8000; + } else Cleave_Timer -= diff; + + //Strike_Timer + if (Strike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STRIKE); + Strike_Timer = 10000; + } else Strike_Timer -= diff; + + //Rend_Timer + if (Rend_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REND); + Rend_Timer = 18000; + } else Rend_Timer -= diff; + + //SunderArmor_Timer + if (SunderArmor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDERARMOR); + SunderArmor_Timer = 25000; + } else SunderArmor_Timer -= diff; + + //KnockAway_Timer + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + KnockAway_Timer = 12000; + } else KnockAway_Timer -= diff; + + //Slow_Timer + if (Slow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLOW); + Slow_Timer = 18000; + } else Slow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_highlordomokk(Creature* pCreature) +{ + return new boss_highlordomokkAI (pCreature); +} + +void AddSC_boss_highlordomokk() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_highlord_omokk"; + newscript->GetAI = &GetAI_boss_highlordomokk; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_mother_smolderweb.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_mother_smolderweb.cpp new file mode 100644 index 00000000000..60dda5a5fab --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_mother_smolderweb.cpp @@ -0,0 +1,87 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mother_Smolderweb +SD%Complete: 100 +SDComment: Uncertain how often mother's milk is casted +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CRYSTALIZE 16104 +#define SPELL_MOTHERSMILK 16468 +#define SPELL_SUMMON_SPIRE_SPIDERLING 16103 + +struct boss_mothersmolderwebAI : public ScriptedAI +{ + boss_mothersmolderwebAI(Creature *c) : ScriptedAI(c) {} + + uint32 Crystalize_Timer; + uint32 MothersMilk_Timer; + + void Reset() + { + Crystalize_Timer = 20000; + MothersMilk_Timer = 10000; + } + + void EnterCombat(Unit * /*who*/) {} + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (me->GetHealth() <= damage) + DoCast(me, SPELL_SUMMON_SPIRE_SPIDERLING, true); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Crystalize_Timer + if (Crystalize_Timer <= diff) + { + DoCast(me, SPELL_CRYSTALIZE); + Crystalize_Timer = 15000; + } else Crystalize_Timer -= diff; + + //MothersMilk_Timer + if (MothersMilk_Timer <= diff) + { + DoCast(me, SPELL_MOTHERSMILK); + MothersMilk_Timer = urand(5000,12500); + } else MothersMilk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_mothersmolderweb(Creature* pCreature) +{ + return new boss_mothersmolderwebAI (pCreature); +} + +void AddSC_boss_mothersmolderweb() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_mother_smolderweb"; + newscript->GetAI = &GetAI_boss_mothersmolderweb; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_overlord_wyrmthalak.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_overlord_wyrmthalak.cpp new file mode 100644 index 00000000000..8846442705b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_overlord_wyrmthalak.cpp @@ -0,0 +1,126 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Overlord_Wyrmthalak +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_BLASTWAVE 11130 +#define SPELL_SHOUT 23511 +#define SPELL_CLEAVE 20691 +#define SPELL_KNOCKAWAY 20686 + +#define ADD_1X -39.355381 +#define ADD_1Y -513.456482 +#define ADD_1Z 88.472046 +#define ADD_1O 4.679872 + +#define ADD_2X -49.875881 +#define ADD_2Y -511.896942 +#define ADD_2Z 88.195160 +#define ADD_2O 4.613114 + +struct boss_overlordwyrmthalakAI : public ScriptedAI +{ + boss_overlordwyrmthalakAI(Creature *c) : ScriptedAI(c) {} + + uint32 BlastWave_Timer; + uint32 Shout_Timer; + uint32 Cleave_Timer; + uint32 Knockaway_Timer; + bool Summoned; + + void Reset() + { + BlastWave_Timer = 20000; + Shout_Timer = 2000; + Cleave_Timer = 6000; + Knockaway_Timer = 12000; + Summoned = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //BlastWave_Timer + if (BlastWave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLASTWAVE); + BlastWave_Timer = 20000; + } else BlastWave_Timer -= diff; + + //Shout_Timer + if (Shout_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHOUT); + Shout_Timer = 10000; + } else Shout_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //Knockaway_Timer + if (Knockaway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + Knockaway_Timer = 14000; + } else Knockaway_Timer -= diff; + + //Summon two Beserks + if (!Summoned && me->GetHealth()*100 / me->GetMaxHealth() < 51) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0, 100, true); + + if (Creature *SummonedCreature = me->SummonCreature(9216,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000)) + SummonedCreature->AI()->AttackStart(pTarget); + if (Creature *SummonedCreature = me->SummonCreature(9268,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,300000)) + SummonedCreature->AI()->AttackStart(pTarget); + Summoned = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_overlordwyrmthalak(Creature* pCreature) +{ + return new boss_overlordwyrmthalakAI (pCreature); +} + +void AddSC_boss_overlordwyrmthalak() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_overlord_wyrmthalak"; + newscript->GetAI = &GetAI_boss_overlordwyrmthalak; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp new file mode 100644 index 00000000000..6cbd6955665 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Pyroguard_Emberseer +SD%Complete: 100 +SDComment: Event to activate Emberseer NYI +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FIRENOVA 23462 +#define SPELL_FLAMEBUFFET 23341 +#define SPELL_PYROBLAST 17274 + +struct boss_pyroguard_emberseerAI : public ScriptedAI +{ + boss_pyroguard_emberseerAI(Creature *c) : ScriptedAI(c) {} + + uint32 FireNova_Timer; + uint32 FlameBuffet_Timer; + uint32 PyroBlast_Timer; + + void Reset() + { + FireNova_Timer = 6000; + FlameBuffet_Timer = 3000; + PyroBlast_Timer = 14000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FireNova_Timer + if (FireNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRENOVA); + FireNova_Timer = 6000; + } else FireNova_Timer -= diff; + + //FlameBuffet_Timer + if (FlameBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBUFFET); + FlameBuffet_Timer = 14000; + } else FlameBuffet_Timer -= diff; + + //PyroBlast_Timer + if (PyroBlast_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_PYROBLAST); + PyroBlast_Timer = 15000; + } else PyroBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_pyroguard_emberseer(Creature* pCreature) +{ + return new boss_pyroguard_emberseerAI (pCreature); +} + +void AddSC_boss_pyroguard_emberseer() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_pyroguard_emberseer"; + newscript->GetAI = &GetAI_boss_pyroguard_emberseer; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_quartermaster_zigris.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_quartermaster_zigris.cpp new file mode 100644 index 00000000000..9058b35cd5c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_quartermaster_zigris.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Quartmaster_Zigris +SD%Complete: 100 +SDComment: Needs revision +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHOOT 16496 +#define SPELL_STUNBOMB 16497 +#define SPELL_HEALING_POTION 15504 +#define SPELL_HOOKEDNET 15609 + +struct boss_quatermasterzigrisAI : public ScriptedAI +{ + boss_quatermasterzigrisAI(Creature *c) : ScriptedAI(c) {} + + uint32 Shoot_Timer; + uint32 StunBomb_Timer; + //uint32 HelingPotion_Timer; + + void Reset() + { + Shoot_Timer = 1000; + StunBomb_Timer = 16000; + //HelingPotion_Timer = 25000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Shoot_Timer + if (Shoot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHOOT); + Shoot_Timer = 500; + } else Shoot_Timer -= diff; + + //StunBomb_Timer + if (StunBomb_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STUNBOMB); + StunBomb_Timer = 14000; + } else StunBomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_quatermasterzigris(Creature* pCreature) +{ + return new boss_quatermasterzigrisAI (pCreature); +} + +void AddSC_boss_quatermasterzigris() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "quartermaster_zigris"; + newscript->GetAI = &GetAI_boss_quatermasterzigris; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp new file mode 100644 index 00000000000..56de5dbb385 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_rend_blackhand.cpp @@ -0,0 +1,92 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Rend_Blackhand +SD%Complete: 100 +SDComment: Intro event NYI +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_WHIRLWIND 26038 +#define SPELL_CLEAVE 20691 +#define SPELL_THUNDERCLAP 23931 //Not sure if he cast this spell + +struct boss_rend_blackhandAI : public ScriptedAI +{ + boss_rend_blackhandAI(Creature *c) : ScriptedAI(c) {} + + uint32 WhirlWind_Timer; + uint32 Cleave_Timer; + uint32 Thunderclap_Timer; + + void Reset() + { + WhirlWind_Timer = 20000; + Cleave_Timer = 5000; + Thunderclap_Timer = 9000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //WhirlWind_Timer + if (WhirlWind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + WhirlWind_Timer = 18000; + } else WhirlWind_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 10000; + } else Cleave_Timer -= diff; + + //Thunderclap_Timer + if (Thunderclap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP); + Thunderclap_Timer = 16000; + } else Thunderclap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_rend_blackhand(Creature* pCreature) +{ + return new boss_rend_blackhandAI (pCreature); +} + +void AddSC_boss_rend_blackhand() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_rend_blackhand"; + newscript->GetAI = &GetAI_boss_rend_blackhand; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_shadow_hunter_voshgajin.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_shadow_hunter_voshgajin.cpp new file mode 100644 index 00000000000..73afc3b5afe --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_shadow_hunter_voshgajin.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shadow_Hunter_Voshgajin +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CURSEOFBLOOD 24673 +#define SPELL_HEX 16708 +#define SPELL_CLEAVE 20691 + +struct boss_shadowvoshAI : public ScriptedAI +{ + boss_shadowvoshAI(Creature *c) : ScriptedAI(c) {} + + uint32 CurseOfBlood_Timer; + uint32 Hex_Timer; + uint32 Cleave_Timer; + + void Reset() + { + CurseOfBlood_Timer = 2000; + Hex_Timer = 8000; + Cleave_Timer = 14000; + + //DoCast(me, SPELL_ICEARMOR, true); + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); + CurseOfBlood_Timer = 45000; + } else CurseOfBlood_Timer -= diff; + + //Hex_Timer + if (Hex_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_HEX); + Hex_Timer = 15000; + } else Hex_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_shadowvosh(Creature* pCreature) +{ + return new boss_shadowvoshAI (pCreature); +} + +void AddSC_boss_shadowvosh() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shadow_hunter_voshgajin"; + newscript->GetAI = &GetAI_boss_shadowvosh; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_the_beast.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_the_beast.cpp new file mode 100644 index 00000000000..499f9cf4ce5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_the_beast.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_The_Best +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FLAMEBREAK 16785 +#define SPELL_IMMOLATE 20294 +#define SPELL_TERRIFYINGROAR 14100 + +struct boss_thebeastAI : public ScriptedAI +{ + boss_thebeastAI(Creature *c) : ScriptedAI(c) {} + + uint32 Flamebreak_Timer; + uint32 Immolate_Timer; + uint32 TerrifyingRoar_Timer; + + void Reset() + { + Flamebreak_Timer = 12000; + Immolate_Timer = 3000; + TerrifyingRoar_Timer = 23000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Flamebreak_Timer + if (Flamebreak_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBREAK); + Flamebreak_Timer = 10000; + } else Flamebreak_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_IMMOLATE); + Immolate_Timer = 8000; + } else Immolate_Timer -= diff; + + //TerrifyingRoar_Timer + if (TerrifyingRoar_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TERRIFYINGROAR); + TerrifyingRoar_Timer = 20000; + } else TerrifyingRoar_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_thebeast(Creature* pCreature) +{ + return new boss_thebeastAI (pCreature); +} + +void AddSC_boss_thebeast() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_beast"; + newscript->GetAI = &GetAI_boss_thebeast; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_warmaster_voone.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_warmaster_voone.cpp new file mode 100644 index 00000000000..50b47c94fc5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_warmaster_voone.cpp @@ -0,0 +1,122 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warmaster_Voone +SD%Complete: 100 +SDComment: +SDCategory: Blackrock Spire +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SNAPKICK 15618 +#define SPELL_CLEAVE 15579 +#define SPELL_UPPERCUT 10966 +#define SPELL_MORTALSTRIKE 16856 +#define SPELL_PUMMEL 15615 +#define SPELL_THROWAXE 16075 + +struct boss_warmastervooneAI : public ScriptedAI +{ + boss_warmastervooneAI(Creature *c) : ScriptedAI(c) {} + + uint32 Snapkick_Timer; + uint32 Cleave_Timer; + uint32 Uppercut_Timer; + uint32 MortalStrike_Timer; + uint32 Pummel_Timer; + uint32 ThrowAxe_Timer; + + void Reset() + { + Snapkick_Timer = 8000; + Cleave_Timer = 14000; + Uppercut_Timer = 20000; + MortalStrike_Timer = 12000; + Pummel_Timer = 32000; + ThrowAxe_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Snapkick_Timer + if (Snapkick_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SNAPKICK); + Snapkick_Timer = 6000; + } else Snapkick_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 12000; + } else Cleave_Timer -= diff; + + //Uppercut_Timer + if (Uppercut_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_UPPERCUT); + Uppercut_Timer = 14000; + } else Uppercut_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 10000; + } else MortalStrike_Timer -= diff; + + //Pummel_Timer + if (Pummel_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PUMMEL); + Pummel_Timer = 16000; + } else Pummel_Timer -= diff; + + //ThrowAxe_Timer + if (ThrowAxe_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THROWAXE); + ThrowAxe_Timer = 8000; + } else ThrowAxe_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_warmastervoone(Creature* pCreature) +{ + return new boss_warmastervooneAI (pCreature); +} + +void AddSC_boss_warmastervoone() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_warmaster_voone"; + newscript->GetAI = &GetAI_boss_warmastervoone; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp new file mode 100644 index 00000000000..f2e2b39fe87 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "blackrock_spire.h" + +enum Achievements +{ + ACHIEV_LEROY_JENKINS = 2188 +}; + +struct instance_blackrock_spire : public ScriptedInstance +{ + instance_blackrock_spire(Map* pMap) : ScriptedInstance(pMap) {} + + uint32 uiLeeroyTimer; + uint32 uiWhelpCount; + uint32 uiLeroyData; + + bool bLeeeeeeeeroy; + + void Initialize() + { + uiLeeroyTimer = 15*IN_MILISECONDS; + uiWhelpCount = 0; + bLeeeeeeeeroy = true; + uiLeroyData = 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case EVENT_LEEEROY: + if (data == DONE) + DoCompleteAchievement(ACHIEV_LEROY_JENKINS); + uiLeroyData = data; + break; + case WHELP_DEATH_COUNT: + if (data == 1) + { + SetData(EVENT_LEEEROY, IN_PROGRESS); + //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Started"); + } + uiWhelpCount = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case EVENT_LEEEROY: return uiLeroyData; + case WHELP_DEATH_COUNT: return uiWhelpCount; + } + return 0; + } + + void Update(uint32 diff) + { + if (GetData(EVENT_LEEEROY) != FAIL && GetData(EVENT_LEEEROY) == IN_PROGRESS) + { + if (uiLeeroyTimer <= diff) + { + SetData(EVENT_LEEEROY, FAIL); + bLeeeeeeeeroy = false; + //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Failed"); + } else uiLeeroyTimer -= diff; + if (uiWhelpCount >= 50 && bLeeeeeeeeroy) + { + SetData(EVENT_LEEEROY, DONE); + //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Success"); + } + } + } +}; + +InstanceData* GetInstanceData_instance_blackrock_spire(Map* pMap) +{ + return new instance_blackrock_spire(pMap); +} + +void AddSC_instance_blackrock_spire() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blackrock_spire"; + newscript->GetInstanceData = &GetInstanceData_instance_blackrock_spire; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp new file mode 100644 index 00000000000..856e1236176 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -0,0 +1,112 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Broodlord_Lashlayer +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1469000 +#define SAY_LEASH -1469001 + +#define SPELL_CLEAVE 26350 +#define SPELL_BLASTWAVE 23331 +#define SPELL_MORTALSTRIKE 24573 +#define SPELL_KNOCKBACK 25778 + +struct boss_broodlordAI : public ScriptedAI +{ + boss_broodlordAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cleave_Timer; + uint32 BlastWave_Timer; + uint32 MortalStrike_Timer; + uint32 KnockBack_Timer; + + void Reset() + { + Cleave_Timer = 8000; //These times are probably wrong + BlastWave_Timer = 12000; + MortalStrike_Timer = 20000; + KnockBack_Timer = 30000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + // BlastWave + if (BlastWave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLASTWAVE); + BlastWave_Timer = urand(8000,16000); + } else BlastWave_Timer -= diff; + + //MortalStrike_Timer + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = urand(25000,35000); + } else MortalStrike_Timer -= diff; + + if (KnockBack_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKBACK); + //Drop 50% aggro + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-50); + + KnockBack_Timer = urand(15000,30000); + } else KnockBack_Timer -= diff; + + if (EnterEvadeIfOutOfCombatArea(diff)) + DoScriptText(SAY_LEASH, me); + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_broodlord(Creature* pCreature) +{ + return new boss_broodlordAI (pCreature); +} + +void AddSC_boss_broodlord() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_broodlord"; + newscript->GetAI = &GetAI_boss_broodlord; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp new file mode 100644 index 00000000000..08bebe95384 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_chromaggus.cpp @@ -0,0 +1,301 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Chromaggus +SD%Complete: 95 +SDComment: Chromatic Mutation disabled due to lack of core support +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +enum Emotes +{ + EMOTE_FRENZY = -1469002, + EMOTE_SHIMMER = -1469003 +}; + +enum Spells +{ + //These spells are actually called elemental shield + //What they do is decrease all damage by 75% then they increase + //One school of damage by 1100% + SPELL_FIRE_VULNERABILITY = 22277, + SPELL_FROST_VULNERABILITY = 22278, + SPELL_SHADOW_VULNERABILITY = 22279, + SPELL_NATURE_VULNERABILITY = 22280, + SPELL_ARCANE_VULNERABILITY = 22281, + //Other spells + SPELL_INCINERATE = 23308, //Incinerate 23308,23309 + SPELL_TIMELAPSE = 23310, //Time lapse 23310, 23311(old threat mod that was removed in 2.01) + SPELL_CORROSIVEACID = 23313, //Corrosive Acid 23313, 23314 + SPELL_IGNITEFLESH = 23315, //Ignite Flesh 23315,23316 + SPELL_FROSTBURN = 23187, //Frost burn 23187, 23189 + //Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them + //Since Scripted spells arn't coded I'll just write a function that does the same thing + SPELL_BROODAF_BLUE = 23153, //Blue affliction 23153 + SPELL_BROODAF_BLACK = 23154, //Black affliction 23154 + SPELL_BROODAF_RED = 23155, //Red affliction 23155 (23168 on death) + SPELL_BROODAF_BRONZE = 23170, //Bronze Affliction 23170 + SPELL_BROODAF_GREEN = 23169, //Brood Affliction Green 23169 + SPELL_CHROMATIC_MUT_1 = 23174, //Spell cast on player if they get all 5 debuffs + SPELL_FRENZY = 28371, //The frenzy spell may be wrong + SPELL_ENRAGE = 28747 +}; + +struct boss_chromaggusAI : public ScriptedAI +{ + boss_chromaggusAI(Creature *c) : ScriptedAI(c) + { + //Select the 2 breaths that we are going to use until despawned + //5 possiblities for the first breath, 4 for the second, 20 total possiblites + //This way we don't end up casting 2 of the same breath + //TL TL would be stupid + switch (urand(0,19)) + { + //B1 - Incin + case 0: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 1: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 2: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 3: + Breath1_Spell = SPELL_INCINERATE; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - TL + case 4: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_INCINERATE; + break; + case 5: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 6: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 7: + Breath1_Spell = SPELL_TIMELAPSE; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Acid + case 8: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_INCINERATE; + break; + case 9: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 10: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + case 11: + Breath1_Spell = SPELL_CORROSIVEACID; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Ignite + case 12: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_INCINERATE; + break; + case 13: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 14: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 15: + Breath1_Spell = SPELL_IGNITEFLESH; + Breath2_Spell = SPELL_FROSTBURN; + break; + + //B1 - Frost + case 16: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_INCINERATE; + break; + case 17: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_TIMELAPSE; + break; + case 18: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_CORROSIVEACID; + break; + case 19: + Breath1_Spell = SPELL_FROSTBURN; + Breath2_Spell = SPELL_IGNITEFLESH; + break; + }; + + EnterEvadeMode(); + } + + uint32 Breath1_Spell; + uint32 Breath2_Spell; + uint32 CurrentVurln_Spell; + + uint32 Shimmer_Timer; + uint32 Breath1_Timer; + uint32 Breath2_Timer; + uint32 Affliction_Timer; + uint32 Frenzy_Timer; + bool Enraged; + + void Reset() + { + CurrentVurln_Spell = 0; //We use this to store our last vulnerabilty spell so we can remove it later + + Shimmer_Timer = 0; //Time till we change vurlnerabilites + Breath1_Timer = 30000; //First breath is 30 seconds + Breath2_Timer = 60000; //Second is 1 minute so that we can alternate + Affliction_Timer = 10000; //This is special - 5 seconds means that we cast this on 1 player every 5 sconds + Frenzy_Timer = 15000; + + Enraged = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Shimmer_Timer Timer + if (Shimmer_Timer <= diff) + { + //Remove old vulnerabilty spell + if (CurrentVurln_Spell) + me->RemoveAurasDueToSpell(CurrentVurln_Spell); + + //Cast new random vulnerabilty on self + uint32 spell = RAND(SPELL_FIRE_VULNERABILITY, SPELL_FROST_VULNERABILITY, + SPELL_SHADOW_VULNERABILITY, SPELL_NATURE_VULNERABILITY, SPELL_ARCANE_VULNERABILITY); + + DoCast(me, spell); + CurrentVurln_Spell = spell; + + DoScriptText(EMOTE_SHIMMER, me); + Shimmer_Timer = 45000; + } else Shimmer_Timer -= diff; + + //Breath1_Timer + if (Breath1_Timer <= diff) + { + DoCast(me->getVictim(), Breath1_Spell); + Breath1_Timer = 60000; + } else Breath1_Timer -= diff; + + //Breath2_Timer + if (Breath2_Timer <= diff) + { + DoCast(me->getVictim(), Breath2_Spell); + Breath2_Timer = 60000; + } else Breath2_Timer -= diff; + + //Affliction_Timer + if (Affliction_Timer <= diff) + { + std::list threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) + { + Unit* pUnit; + if ((*i) && (*i)->getSource()) + { + pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit) + { + //Cast affliction + DoCast(pUnit, RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, + SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN), true); + + //Chromatic mutation if target is effected by all afflictions + if (pUnit->HasAura(SPELL_BROODAF_BLUE) + && pUnit->HasAura(SPELL_BROODAF_BLACK) + && pUnit->HasAura(SPELL_BROODAF_RED) + && pUnit->HasAura(SPELL_BROODAF_BRONZE) + && pUnit->HasAura(SPELL_BROODAF_GREEN)) + { + //pTarget->RemoveAllAuras(); + //DoCast(pTarget, SPELL_CHROMATIC_MUT_1); + + //Chromatic mutation is causing issues + //Assuming it is caused by a lack of core support for Charm + //So instead we instant kill our target + + //WORKAROUND + if (pUnit->GetTypeId() == TYPEID_PLAYER) + pUnit->CastSpell(pUnit, 5, false); + } + } + } + } + + Affliction_Timer = 10000; + } else Affliction_Timer -= diff; + + //Frenzy_Timer + if (Frenzy_Timer <= diff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_FRENZY, me); + Frenzy_Timer = urand(10000,15000); + } else Frenzy_Timer -= diff; + + //Enrage if not already enraged and below 20% + if (!Enraged && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_chromaggus(Creature* pCreature) +{ + return new boss_chromaggusAI (pCreature); +} + +void AddSC_boss_chromaggus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_chromaggus"; + newscript->GetAI = &GetAI_boss_chromaggus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp new file mode 100644 index 00000000000..49a999fc458 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_ebonroc.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ebonroc +SD%Complete: 50 +SDComment: Shadow of Ebonroc needs core support +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 18500 +#define SPELL_SHADOWOFEBONROC 23340 +#define SPELL_HEAL 41386 //Thea Heal spell of his Shadow + +struct boss_ebonrocAI : public ScriptedAI +{ + boss_ebonrocAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 ShadowOfEbonroc_Timer; + uint32 Heal_Timer; + + void Reset() + { + ShadowFlame_Timer = 15000; //These times are probably wrong + WingBuffet_Timer = 30000; + ShadowOfEbonroc_Timer = 45000; + Heal_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Shadowflame Timer + if (ShadowFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWFLAME); + ShadowFlame_Timer = urand(12000,15000); + } else ShadowFlame_Timer -= diff; + + //Wing Buffet Timer + if (WingBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WINGBUFFET); + WingBuffet_Timer = 25000; + } else WingBuffet_Timer -= diff; + + //Shadow of Ebonroc Timer + if (ShadowOfEbonroc_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWOFEBONROC); + ShadowOfEbonroc_Timer = urand(25000,350000); + } else ShadowOfEbonroc_Timer -= diff; + + if (me->getVictim()->HasAura(SPELL_SHADOWOFEBONROC)) + { + if (Heal_Timer <= diff) + { + DoCast(me, SPELL_HEAL); + Heal_Timer = urand(1000,3000); + } else Heal_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ebonroc(Creature* pCreature) +{ + return new boss_ebonrocAI (pCreature); +} + +void AddSC_boss_ebonroc() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ebonroc"; + newscript->GetAI = &GetAI_boss_ebonroc; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp new file mode 100644 index 00000000000..af62b1103bc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_firemaw.cpp @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Firemaw +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 23339 +#define SPELL_FLAMEBUFFET 23341 + +struct boss_firemawAI : public ScriptedAI +{ + boss_firemawAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 FlameBuffet_Timer; + + void Reset() + { + ShadowFlame_Timer = 30000; //These times are probably wrong + WingBuffet_Timer = 24000; + FlameBuffet_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWFLAME); + ShadowFlame_Timer = urand(15000,18000); + } else ShadowFlame_Timer -= diff; + + //WingBuffet_Timer + if (WingBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WINGBUFFET); + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-75); + + WingBuffet_Timer = 25000; + } else WingBuffet_Timer -= diff; + + //FlameBuffet_Timer + if (FlameBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBUFFET); + FlameBuffet_Timer = 5000; + } else FlameBuffet_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_firemaw(Creature* pCreature) +{ + return new boss_firemawAI (pCreature); +} + +void AddSC_boss_firemaw() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_firemaw"; + newscript->GetAI = &GetAI_boss_firemaw; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp new file mode 100644 index 00000000000..b29fe41f2b1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_flamegor.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Flamegor +SD%Complete: 100 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_FRENZY -1469031 + +#define SPELL_SHADOWFLAME 22539 +#define SPELL_WINGBUFFET 23339 +#define SPELL_FRENZY 23342 //This spell periodically triggers fire nova + +struct boss_flamegorAI : public ScriptedAI +{ + boss_flamegorAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowFlame_Timer; + uint32 WingBuffet_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + ShadowFlame_Timer = 21000; //These times are probably wrong + WingBuffet_Timer = 35000; + Frenzy_Timer = 10000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWFLAME); + ShadowFlame_Timer = 15000 + rand()%7000; + } else ShadowFlame_Timer -= diff; + + //WingBuffet_Timer + if (WingBuffet_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WINGBUFFET); + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-75); + + WingBuffet_Timer = 25000; + } else WingBuffet_Timer -= diff; + + //Frenzy_Timer + if (Frenzy_Timer <= diff) + { + DoScriptText(EMOTE_FRENZY, me); + DoCast(me, SPELL_FRENZY); + Frenzy_Timer = urand(8000, 10000); + } else Frenzy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_flamegor(Creature* pCreature) +{ + return new boss_flamegorAI (pCreature); +} + +void AddSC_boss_flamegor() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_flamegor"; + newscript->GetAI = &GetAI_boss_flamegor; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp new file mode 100644 index 00000000000..5ef05be519c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_nefarian.cpp @@ -0,0 +1,231 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Nefarian +SD%Complete: 80 +SDComment: Some issues with class calls effecting more than one class +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1469007 +#define SAY_XHEALTH -1469008 +#define SAY_SHADOWFLAME -1469009 +#define SAY_RAISE_SKELETONS -1469010 +#define SAY_SLAY -1469011 +#define SAY_DEATH -1469012 + +#define SAY_MAGE -1469013 +#define SAY_WARRIOR -1469014 +#define SAY_DRUID -1469015 +#define SAY_PRIEST -1469016 +#define SAY_PALADIN -1469017 +#define SAY_SHAMAN -1469018 +#define SAY_WARLOCK -1469019 +#define SAY_HUNTER -1469020 +#define SAY_ROGUE -1469021 + +#define SPELL_SHADOWFLAME_INITIAL 22972 +#define SPELL_SHADOWFLAME 22539 +#define SPELL_BELLOWINGROAR 22686 +#define SPELL_VEILOFSHADOW 7068 +#define SPELL_CLEAVE 20691 +#define SPELL_TAILLASH 23364 +#define SPELL_BONECONTRUST 23363 //23362, 23361 + +#define SPELL_MAGE 23410 //wild magic +#define SPELL_WARRIOR 23397 //beserk +#define SPELL_DRUID 23398 // cat form +#define SPELL_PRIEST 23401 // corrupted healing +#define SPELL_PALADIN 23418 //syphon blessing +#define SPELL_SHAMAN 23425 //totems +#define SPELL_WARLOCK 23427 //infernals +#define SPELL_HUNTER 23436 //bow broke +#define SPELL_ROGUE 23414 //Paralise + +struct boss_nefarianAI : public ScriptedAI +{ + boss_nefarianAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowFlame_Timer; + uint32 BellowingRoar_Timer; + uint32 VeilOfShadow_Timer; + uint32 Cleave_Timer; + uint32 TailLash_Timer; + uint32 ClassCall_Timer; + bool Phase3; + + uint32 DespawnTimer; + + void Reset() + { + ShadowFlame_Timer = 12000; //These times are probably wrong + BellowingRoar_Timer = 30000; + VeilOfShadow_Timer = 15000; + Cleave_Timer = 7000; + TailLash_Timer = 10000; + ClassCall_Timer = 35000; //35-40 seconds + Phase3 = false; + + DespawnTimer = 5000; + } + + void KilledUnit(Unit* Victim) + { + if (rand()%5) + return; + + DoScriptText(SAY_SLAY, me, Victim); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * who) + { + DoScriptText(RAND(SAY_XHEALTH,SAY_AGGRO,SAY_SHADOWFLAME), me); + + DoCast(who, SPELL_SHADOWFLAME_INITIAL); + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (DespawnTimer <= diff) + { + if (!UpdateVictim()) + me->ForcedDespawn(); + DespawnTimer = 5000; + } else DespawnTimer -= diff; + + if (!UpdateVictim()) + return; + + //ShadowFlame_Timer + if (ShadowFlame_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWFLAME); + ShadowFlame_Timer = 12000; + } else ShadowFlame_Timer -= diff; + + //BellowingRoar_Timer + if (BellowingRoar_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BELLOWINGROAR); + BellowingRoar_Timer = 30000; + } else BellowingRoar_Timer -= diff; + + //VeilOfShadow_Timer + if (VeilOfShadow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VEILOFSHADOW); + VeilOfShadow_Timer = 15000; + } else VeilOfShadow_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //TailLash_Timer + if (TailLash_Timer <= diff) + { + //Cast NYI since we need a better check for behind target + //DoCast(me->getVictim(), SPELL_TAILLASH); + + TailLash_Timer = 10000; + } else TailLash_Timer -= diff; + + //ClassCall_Timer + if (ClassCall_Timer <= diff) + { + //Cast a random class call + //On official it is based on what classes are currently on the hostil list + //but we can't do that yet so just randomly call one + + switch (urand(0,8)) + { + case 0: + DoScriptText(SAY_MAGE, me); + DoCast(me, SPELL_MAGE); + break; + case 1: + DoScriptText(SAY_WARRIOR, me); + DoCast(me, SPELL_WARRIOR); + break; + case 2: + DoScriptText(SAY_DRUID, me); + DoCast(me, SPELL_DRUID); + break; + case 3: + DoScriptText(SAY_PRIEST, me); + DoCast(me, SPELL_PRIEST); + break; + case 4: + DoScriptText(SAY_PALADIN, me); + DoCast(me, SPELL_PALADIN); + break; + case 5: + DoScriptText(SAY_SHAMAN, me); + DoCast(me, SPELL_SHAMAN); + break; + case 6: + DoScriptText(SAY_WARLOCK, me); + DoCast(me, SPELL_WARLOCK); + break; + case 7: + DoScriptText(SAY_HUNTER, me); + DoCast(me, SPELL_HUNTER); + break; + case 8: + DoScriptText(SAY_ROGUE, me); + DoCast(me, SPELL_ROGUE); + break; + } + + ClassCall_Timer = 35000 + (rand() % 5000); + } else ClassCall_Timer -= diff; + + //Phase3 begins when we are below X health + if (!Phase3 && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) + { + Phase3 = true; + DoScriptText(SAY_RAISE_SKELETONS, me); + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_nefarian(Creature* pCreature) +{ + return new boss_nefarianAI (pCreature); +} + +void AddSC_boss_nefarian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nefarian"; + newscript->GetAI = &GetAI_boss_nefarian; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp new file mode 100644 index 00000000000..a095756b18b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_razorgore.cpp @@ -0,0 +1,125 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Razorgore +SD%Complete: 50 +SDComment: Needs additional review. Phase 1 NYI (Grethok the Controller) +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +//Razorgore Phase 2 Script + +#define SAY_EGGS_BROKEN1 -1469022 +#define SAY_EGGS_BROKEN2 -1469023 +#define SAY_EGGS_BROKEN3 -1469024 +#define SAY_DEATH -1469025 + +#define SPELL_CLEAVE 22540 +#define SPELL_WARSTOMP 24375 +#define SPELL_FIREBALLVOLLEY 22425 +#define SPELL_CONFLAGRATION 23023 + +struct boss_razorgoreAI : public ScriptedAI +{ + boss_razorgoreAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cleave_Timer; + uint32 WarStomp_Timer; + uint32 FireballVolley_Timer; + uint32 Conflagration_Timer; + + void Reset() + { + Cleave_Timer = 15000; //These times are probably wrong + WarStomp_Timer = 35000; + FireballVolley_Timer = 7000; + Conflagration_Timer = 12000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = urand(7000,10000); + } else Cleave_Timer -= diff; + + //WarStomp_Timer + if (WarStomp_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WARSTOMP); + WarStomp_Timer = urand(15000,25000); + } else WarStomp_Timer -= diff; + + //FireballVolley_Timer + if (FireballVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALLVOLLEY); + FireballVolley_Timer = urand(12000,15000); + } else FireballVolley_Timer -= diff; + + //Conflagration_Timer + if (Conflagration_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CONFLAGRATION); + //We will remove this threat reduction and add an aura check. + + //if (DoGetThreat(me->getVictim())) + //DoModifyThreatPercent(me->getVictim(),-50); + + Conflagration_Timer = 12000; + } else Conflagration_Timer -= diff; + + // Aura Check. If the gamer is affected by confliguration we attack a random gamer. + if (me->getVictim() && me->getVictim()->HasAura(SPELL_CONFLAGRATION)) + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + me->TauntApply(pTarget); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_razorgore(Creature* pCreature) +{ + return new boss_razorgoreAI (pCreature); +} + +void AddSC_boss_razorgore() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_razorgore"; + newscript->GetAI = &GetAI_boss_razorgore; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp new file mode 100644 index 00000000000..f6e94307f2f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_vaelastrasz.cpp @@ -0,0 +1,262 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vaelastrasz +SD%Complete: 75 +SDComment: Burning Adrenaline not correctly implemented in core +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_LINE1 -1469026 +#define SAY_LINE2 -1469027 +#define SAY_LINE3 -1469028 +#define SAY_HALFLIFE -1469029 +#define SAY_KILLTARGET -1469030 + +#define GOSSIP_ITEM "Start Event " + +#define SPELL_ESSENCEOFTHERED 23513 +#define SPELL_FLAMEBREATH 23461 +#define SPELL_FIRENOVA 23462 +#define SPELL_TAILSWIPE 15847 +#define SPELL_BURNINGADRENALINE 23620 +#define SPELL_CLEAVE 20684 //Chain cleave is most likely named something different and contains a dummy effect + +struct boss_vaelAI : public ScriptedAI +{ + boss_vaelAI(Creature *c) : ScriptedAI(c) + { + c->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + c->setFaction(35); + c->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + uint64 PlayerGUID; + uint32 SpeechTimer; + uint32 SpeechNum; + uint32 Cleave_Timer; + uint32 FlameBreath_Timer; + uint32 FireNova_Timer; + uint32 BurningAdrenalineCaster_Timer; + uint32 BurningAdrenalineTank_Timer; + uint32 TailSwipe_Timer; + bool HasYelled; + bool DoingSpeech; + + void Reset() + { + PlayerGUID = 0; + SpeechTimer = 0; + SpeechNum = 0; + Cleave_Timer = 8000; //These times are probably wrong + FlameBreath_Timer = 11000; + BurningAdrenalineCaster_Timer = 15000; + BurningAdrenalineTank_Timer = 45000; + FireNova_Timer = 5000; + TailSwipe_Timer = 20000; + HasYelled = false; + DoingSpeech = false; + } + + void BeginSpeech(Unit *pTarget) + { + //Stand up and begin speach + PlayerGUID = pTarget->GetGUID(); + + //10 seconds + DoScriptText(SAY_LINE1, me); + + SpeechTimer = 10000; + SpeechNum = 0; + DoingSpeech = true; + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + void KilledUnit(Unit * victim) + { + if (rand()%5) + return; + + DoScriptText(SAY_KILLTARGET, me, victim); + } + + void EnterCombat(Unit * /*who*/) + { + DoCast(me, SPELL_ESSENCEOFTHERED); + DoZoneInCombat(); + me->SetHealth(int(me->GetMaxHealth()*.3)); + } + + void UpdateAI(const uint32 diff) + { + //Speech + if (DoingSpeech) + { + if (SpeechTimer <= diff) + { + switch (SpeechNum) + { + case 0: + //16 seconds till next line + DoScriptText(SAY_LINE2, me); + SpeechTimer = 16000; + ++SpeechNum; + break; + case 1: + //This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!" + DoScriptText(SAY_LINE3, me); + SpeechTimer = 10000; + ++SpeechNum; + break; + case 2: + me->setFaction(103); + if (PlayerGUID && Unit::GetUnit((*me),PlayerGUID)) + { + AttackStart(Unit::GetUnit((*me),PlayerGUID)); + DoCast(me, SPELL_ESSENCEOFTHERED); + } + SpeechTimer = 0; + DoingSpeech = false; + break; + } + } else SpeechTimer -= diff; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + // Yell if hp lower than 15% + if (me->GetHealth()*100 / me->GetMaxHealth() < 15 && !HasYelled) + { + DoScriptText(SAY_HALFLIFE, me); + HasYelled = true; + } + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 15000; + } else Cleave_Timer -= diff; + + //FlameBreath_Timer + if (FlameBreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBREATH); + FlameBreath_Timer = urand(4000,8000); + } else FlameBreath_Timer -= diff; + + //BurningAdrenalineCaster_Timer + if (BurningAdrenalineCaster_Timer <= diff) + { + Unit *pTarget = NULL; + + uint8 i = 0; + while (i < 3) // max 3 tries to get a random target with power_mana + { + ++i; + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); //not aggro leader + if (pTarget && pTarget->getPowerType() == POWER_MANA) + i = 3; + } + if (pTarget) // cast on self (see below) + pTarget->CastSpell(pTarget,SPELL_BURNINGADRENALINE,1); + + BurningAdrenalineCaster_Timer = 15000; + } else BurningAdrenalineCaster_Timer -= diff; + + //BurningAdrenalineTank_Timer + if (BurningAdrenalineTank_Timer <= diff) + { + // have the victim cast the spell on himself otherwise the third effect aura will be applied + // to Vael instead of the player + me->getVictim()->CastSpell(me->getVictim(),SPELL_BURNINGADRENALINE,1); + + BurningAdrenalineTank_Timer = 45000; + } else BurningAdrenalineTank_Timer -= diff; + + //FireNova_Timer + if (FireNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRENOVA); + FireNova_Timer = 5000; + } else FireNova_Timer -= diff; + + //TailSwipe_Timer + if (TailSwipe_Timer <= diff) + { + //Only cast if we are behind + /*if (!me->HasInArc(M_PI, me->getVictim())) + { + DoCast(me->getVictim(), SPELL_TAILSWIPE); + }*/ + + TailSwipe_Timer = 20000; + } else TailSwipe_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void SendDefaultMenu_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(boss_vaelAI, pCreature->AI())->BeginSpeech(pPlayer); + } +} + +bool GossipSelect_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiSender == GOSSIP_SENDER_MAIN) + SendDefaultMenu_boss_vael(pPlayer, pCreature, uiAction); + + return true; +} + +bool GossipHello_boss_vael(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + + return true; +} + +CreatureAI* GetAI_boss_vael(Creature* pCreature) +{ + return new boss_vaelAI (pCreature); +} + +void AddSC_boss_vael() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vaelastrasz"; + newscript->GetAI = &GetAI_boss_vael; + newscript->pGossipHello = &GossipHello_boss_vael; + newscript->pGossipSelect = &GossipSelect_boss_vael; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp new file mode 100644 index 00000000000..dfeb2519bae --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/boss_victor_nefarius.cpp @@ -0,0 +1,385 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Victor_Nefarius +SD%Complete: 75 +SDComment: Missing some text, Vael beginning event, and spawns Nef in wrong place +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_GAMESBEGIN_1 -1469004 +#define SAY_GAMESBEGIN_2 -1469005 +#define SAY_VAEL_INTRO -1469006 //when he corrupts Vaelastrasz + +#define GOSSIP_ITEM_1 "I've made no mistakes." +#define GOSSIP_ITEM_2 "You have lost your mind, Nefarius. You speak in riddles." +#define GOSSIP_ITEM_3 "Please do." + +#define CREATURE_BRONZE_DRAKANOID 14263 +#define CREATURE_BLUE_DRAKANOID 14261 +#define CREATURE_RED_DRAKANOID 14264 +#define CREATURE_GREEN_DRAKANOID 14262 +#define CREATURE_BLACK_DRAKANOID 14265 + +#define CREATURE_CHROMATIC_DRAKANOID 14302 +#define CREATURE_NEFARIAN 11583 + +#define ADD_X1 -7591.151855 +#define ADD_X2 -7514.598633 +#define ADD_Y1 -1204.051880 +#define ADD_Y2 -1150.448853 +#define ADD_Z1 476.800476 +#define ADD_Z2 476.796570 + +#define NEF_X -7445 +#define NEF_Y -1332 +#define NEF_Z 536 + +#define HIDE_X -7592 +#define HIDE_Y -1264 +#define HIDE_Z 481 + +#define SPELL_SHADOWBOLT 21077 +#define SPELL_FEAR 26070 + +//This script is complicated +//Instead of morphing Victor Nefarius we will have him control phase 1 +//And then have him spawn "Nefarian" for phase 2 +//When phase 2 starts Victor Nefarius will go into hiding and stop attacking +//If Nefarian despawns because he killed the players then this guy will EnterEvadeMode +//and allow players to start the event over +//If nefarian dies then he will kill himself then he will kill himself in his hiding place +//To prevent players from doing the event twice + +struct boss_victor_nefariusAI : public ScriptedAI +{ + boss_victor_nefariusAI(Creature *c) : ScriptedAI(c) + { + NefarianGUID = 0; + switch (urand(0,19)) + { + case 0: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 1: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 2: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 3: + DrakType1 = CREATURE_BRONZE_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 4: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 5: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 6: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 7: + DrakType1 = CREATURE_BLUE_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 8: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 9: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 10: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 11: + DrakType1 = CREATURE_RED_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 12: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 13: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 14: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + case 15: + DrakType1 = CREATURE_GREEN_DRAKANOID; + DrakType2 = CREATURE_BLACK_DRAKANOID; + break; + case 16: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_BRONZE_DRAKANOID; + break; + case 17: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_BLUE_DRAKANOID; + break; + case 18: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_GREEN_DRAKANOID; + break; + case 19: + DrakType1 = CREATURE_BLACK_DRAKANOID; + DrakType2 = CREATURE_RED_DRAKANOID; + break; + } + } + + uint32 SpawnedAdds; + uint32 AddSpawnTimer; + uint32 ShadowBoltTimer; + uint32 FearTimer; + uint32 MindControlTimer; + uint32 ResetTimer; + uint32 DrakType1; + uint32 DrakType2; + uint64 NefarianGUID; + uint32 NefCheckTime; + + void Reset() + { + SpawnedAdds = 0; + AddSpawnTimer = 10000; + ShadowBoltTimer = 5000; + FearTimer = 8000; + ResetTimer = 900000; //On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier + NefarianGUID = 0; + NefCheckTime = 2000; + + me->SetUInt32Value(UNIT_NPC_FLAGS,1); + me->setFaction(35); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void BeginEvent(Player *pTarget) + { + DoScriptText(SAY_GAMESBEGIN_2, me); + + //Trinity::Singleton::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); + /* + list ::const_iterator i = MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); + + for (i = MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); i != MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().end(); ++i) + { + AttackStart((*i)); + } + */ + me->SetUInt32Value(UNIT_NPC_FLAGS,0); + me->setFaction(103); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + AttackStart(pTarget); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void MoveInLineOfSight(Unit *who) + { + //We simply use this function to find players until we can use pMap->GetPlayers() + + if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsHostileTo(who)) + { + //Add them to our threat list + me->AddThreat(who, 0.0f); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Only do this if we haven't spawned nef yet + if (SpawnedAdds < 42) + { + //ShadowBoltTimer + if (ShadowBoltTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SHADOWBOLT); + + ShadowBoltTimer = urand(3000,10000); + } else ShadowBoltTimer -= diff; + + //FearTimer + if (FearTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_FEAR); + + FearTimer = 10000 + (rand()%10000); + } else FearTimer -= diff; + + //Add spawning mechanism + if (AddSpawnTimer <= diff) + { + //Spawn 2 random types of creatures at the 2 locations + uint32 CreatureID; + Creature* Spawned = NULL; + Unit *pTarget = NULL; + + //1 in 3 chance it will be a chromatic + if (urand(0,2) == 0) + CreatureID = CREATURE_CHROMATIC_DRAKANOID; + else + CreatureID = DrakType1; + + ++SpawnedAdds; + + //Spawn Creature and force it to start attacking a random target + Spawned = me->SummonCreature(CreatureID,ADD_X1,ADD_Y1,ADD_Z1,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget && Spawned) + { + Spawned->AI()->AttackStart(pTarget); + Spawned->setFaction(103); + } + + //1 in 3 chance it will be a chromatic + if (urand(0,2) == 0) + CreatureID = CREATURE_CHROMATIC_DRAKANOID; + else + CreatureID = DrakType2; + + ++SpawnedAdds; + + Spawned = me->SummonCreature(CreatureID,ADD_X2,ADD_Y2,ADD_Z2,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget && Spawned) + { + Spawned->AI()->AttackStart(pTarget); + Spawned->setFaction(103); + } + + //Begin phase 2 by spawning Nefarian and what not + if (SpawnedAdds >= 42) + { + //Teleport Victor Nefarius way out of the map + //MapManager::Instance().GetMap(me->GetMapId(), me)->CreatureRelocation(me,0,0,-5000,0); + + //Inturrupt any spell casting + me->InterruptNonMeleeSpells(false); + + //Root self + DoCast(me, 33356); + + //Make super invis + DoCast(me, 8149); + + //Teleport self to a hiding spot (this causes errors in the Trinity log but no real issues) + DoTeleportTo(HIDE_X,HIDE_Y,HIDE_Z); + me->addUnitState(UNIT_STAT_FLEEING); + + //Spawn nef and have him attack a random target + Creature* Nefarian = me->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget && Nefarian) + { + Nefarian->AI()->AttackStart(pTarget); + Nefarian->setFaction(103); + NefarianGUID = Nefarian->GetGUID(); + } + else error_log("TSCR: Blackwing Lair: Unable to spawn nefarian properly."); + } + + AddSpawnTimer = 4000; + } else AddSpawnTimer -= diff; + } + else if (NefarianGUID) + { + if (NefCheckTime <= diff) + { + Unit* Nefarian = Unit::GetCreature((*me),NefarianGUID); + + //If nef is dead then we die to so the players get out of combat + //and cannot repeat the event + if (!Nefarian || !Nefarian->isAlive()) + { + NefarianGUID = 0; + me->ForcedDespawn(); + } + + NefCheckTime = 2000; + } else NefCheckTime -= diff; + } + } +}; + +CreatureAI* GetAI_boss_victor_nefarius(Creature* pCreature) +{ + return new boss_victor_nefariusAI (pCreature); +} + +bool GossipHello_boss_victor_nefarius(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1 , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(7134, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_boss_victor_nefarius(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(7198, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(7199, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + DoScriptText(SAY_GAMESBEGIN_1, pCreature); + CAST_AI(boss_victor_nefariusAI, pCreature->AI())->BeginEvent(pPlayer); + break; + } + return true; +} + +void AddSC_boss_victor_nefarius() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_victor_nefarius"; + newscript->GetAI = &GetAI_boss_victor_nefarius; + newscript->pGossipHello = &GossipHello_boss_victor_nefarius; + newscript->pGossipSelect = &GossipSelect_boss_victor_nefarius; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp new file mode 100644 index 00000000000..d6403fa1206 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackwingLair/instance_blackwing_lair.cpp @@ -0,0 +1,25 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Blackwing_Lair +SD%Complete: 0 +SDComment: +SDCategory: Blackwing Lair +EndScriptData */ + +#include "ScriptedPch.h" + diff --git a/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp b/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp new file mode 100644 index 00000000000..5c6bab46e5a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp @@ -0,0 +1,182 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss Mr.Smite +SD%Complete: +SDComment: Timers and say taken from acid script +EndScriptData */ + +#include "ScriptedPch.h" +#include "deadmines.h" + +enum eSpels +{ + SPELL_TRASH = 3391, + SPELL_SMITE_STOMP = 6432, + SPELL_SMITE_SLAM = 6435, + SPELL_NIMBLE_REFLEXES = 6264, + + EQUIP_SWORD = 5191, + EQUIP_MACE = 7230, + + SAY_AGGRO = -1036001 +}; + +struct boss_mr_smiteAI : public ScriptedAI +{ + boss_mr_smiteAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiTrashTimer; + uint32 uiSlamTimer; + uint32 uiNimbleReflexesTimer; + + uint8 uiHealth; + + uint32 uiPhase; + uint32 uiTimer; + + void Reset() + { + uiTrashTimer = urand(5000,9000); + uiSlamTimer = 9000; + uiNimbleReflexesTimer = urand(15500,31600); + + uiHealth = 0; + + uiPhase = 0; + uiTimer = 0; + + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + } + + bool bCheckChances() + { + uint32 uiChances = urand(0,99); + if (uiChances <= 15) + return false; + else + return true; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + /*START ACID-AI*/ + if (uiTrashTimer <= uiDiff) + { + if (bCheckChances()) + DoCast(me, SPELL_TRASH); + uiTrashTimer = urand(6000,15500); + } else uiTrashTimer -= uiDiff; + + if (uiSlamTimer <= uiDiff) + { + if (bCheckChances()) + DoCast(me->getVictim(), SPELL_SMITE_SLAM); + uiSlamTimer = 11000; + } else uiSlamTimer -= uiDiff; + + if (uiNimbleReflexesTimer <= uiDiff) + { + if (bCheckChances()) + DoCast(me, SPELL_NIMBLE_REFLEXES); + uiNimbleReflexesTimer = urand(27300,60100); + } else uiNimbleReflexesTimer -= uiDiff; + /*END ACID-AI*/ + + if (uiHealth == 0 && me->GetHealth()*100 / me->GetMaxHealth() <= 66 || uiHealth == 1 && me->GetHealth()*100 / me->GetMaxHealth() <= 33) + { + ++uiHealth; + DoCastAOE(SPELL_SMITE_STOMP,false); + SetCombatMovement(false); + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_SMITE_CHEST))) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(1,-3.00+pGo->GetPositionX(),pGo->GetPositionY(),pGo->GetPositionZ()); + } + } + + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + me->HandleEmoteCommand(EMOTE_STATE_KNEEL); //dosen't work? + uiTimer = 1000; + uiPhase = 2; + break; + case 2: + if (uiHealth == 1) + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); + else + SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + uiTimer = 500; + uiPhase = 3; + break; + case 3: + SetCombatMovement(true); + me->GetMotionMaster()->MoveChase(me->getVictim(), me->m_CombatDistance); + uiPhase = 0; + break; + + } + } else uiTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + uiTimer = 1500; + uiPhase = 1; + } + +}; +CreatureAI* GetAI_boss_mr_smite(Creature* pCreature) +{ + return new boss_mr_smiteAI (pCreature); +} + +void AddSC_boss_mr_smite() +{ + Script* newscript; + newscript = new Script; + newscript->Name = "boss_mr_smite"; + newscript->GetAI = &GetAI_boss_mr_smite; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp new file mode 100644 index 00000000000..5bc1121bead --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp @@ -0,0 +1,60 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Deadmines +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Deadmines +EndScriptData */ + +#include "ScriptedPch.h" +#include "deadmines.h" +#include "Spell.h" + +/*##### +# item_Defias_Gunpowder +#####*/ + +bool ItemUse_item_defias_gunpowder(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) +{ + ScriptedInstance *pInstance = pPlayer->GetInstanceData(); + + if (!pInstance) + { + pPlayer->GetSession()->SendNotification("Instance script not initialized"); + return true; + } + if (pInstance->GetData(EVENT_STATE)!= CANNON_NOT_USED) + return false; + if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT && + targets.getGOTarget()->GetEntry() == GO_DEFIAS_CANNON) + { + pInstance->SetData(EVENT_STATE, CANNON_GUNPOWDER_USED); + } + + pPlayer->DestroyItemCount(pItem->GetEntry(), 1, true); + return true; +} + +void AddSC_deadmines() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "item_defias_gunpowder"; + newscript->pItemUse = &ItemUse_item_defias_gunpowder; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h new file mode 100644 index 00000000000..203494ad5b7 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h @@ -0,0 +1,35 @@ +#ifndef DEF_DEADMINES_H +#define DEF_DEADMINES_H + +#include "ScriptedPch.h" + +enum CannonState +{ + CANNON_NOT_USED, + CANNON_GUNPOWDER_USED, + CANNON_BLAST_INITIATED, + PIRATES_ATTACK, + EVENT_DONE +}; + +enum Data +{ + EVENT_STATE, + EVENT_RHAHKZOR +}; + +enum Data64 +{ + DATA_SMITE_CHEST +}; + +enum GameObjects +{ + GO_FACTORY_DOOR = 13965, + GO_IRONCLAD_DOOR = 16397, + GO_DEFIAS_CANNON = 16398, + GO_DOOR_LEVER = 101833, + GO_MR_SMITE_CHEST = 144111 +}; +#endif + diff --git a/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp b/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp new file mode 100644 index 00000000000..f1aa0c62b8a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp @@ -0,0 +1,256 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Deadmines +SD%Complete: 100 +SDComment: +SDCategory: Deadmines +EndScriptData */ + +#include "ScriptedPch.h" +#include "deadmines.h" + +enum Sounds +{ + SOUND_CANNONFIRE = 1400, + SOUND_DESTROYDOOR = 3079, + SOUND_MR_SMITE_ALARM1 = 5775, + SOUND_MR_SMITE_ALARM2 = 5777 +}; + +#define SAY_MR_SMITE_ALARM1 "You there, check out that noise!" +#define SAY_MR_SMITE_ALARM2 "We're under attack! A vast, ye swabs! Repel the invaders!" + +enum Misc +{ + DATA_CANNON_BLAST_TIMER = 3000, + DATA_PIRATES_DELAY_TIMER = 1000 +}; + +struct instance_deadmines : public ScriptedInstance +{ + instance_deadmines(Map* pMap) : ScriptedInstance(pMap) { Initialize(); }; + + uint64 FactoryDoorGUID; + uint64 IronCladDoorGUID; + uint64 DefiasCannonGUID; + uint64 DoorLeverGUID; + uint64 DefiasPirate1GUID; + uint64 DefiasPirate2GUID; + uint64 DefiasCompanionGUID; + + uint32 State; + uint32 CannonBlast_Timer; + uint32 PiratesDelay_Timer; + uint64 uiSmiteChestGUID; + + void Initialize() + { + FactoryDoorGUID = 0; + IronCladDoorGUID = 0; + DefiasCannonGUID = 0; + DoorLeverGUID = 0; + DefiasPirate1GUID = 0; + DefiasPirate2GUID = 0; + DefiasCompanionGUID = 0; + + State = CANNON_NOT_USED; + uiSmiteChestGUID = 0; + } + + virtual void Update(uint32 diff) + { + if (!IronCladDoorGUID || !DefiasCannonGUID || !DoorLeverGUID) + return; + + GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID); + if (!pIronCladDoor) + return; + + switch (State) + { + case CANNON_GUNPOWDER_USED: + CannonBlast_Timer = DATA_CANNON_BLAST_TIMER; + // it's a hack - Mr. Smite should do that but his too far away + pIronCladDoor->SetName("Mr. Smite"); + pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM1, LANG_UNIVERSAL, 0); + DoPlaySound(pIronCladDoor, SOUND_MR_SMITE_ALARM1); + State = CANNON_BLAST_INITIATED; + break; + case CANNON_BLAST_INITIATED: + PiratesDelay_Timer = DATA_PIRATES_DELAY_TIMER; + if (CannonBlast_Timer <= diff) + { + SummonCreatures(); + ShootCannon(); + BlastOutDoor(); + LeverStucked(); + pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM2, LANG_UNIVERSAL, 0); + DoPlaySound(pIronCladDoor, SOUND_MR_SMITE_ALARM2); + State = PIRATES_ATTACK; + } else CannonBlast_Timer -= diff; + break; + case PIRATES_ATTACK: + if (PiratesDelay_Timer <= diff) + { + MoveCreaturesInside(); + State = EVENT_DONE; + } else PiratesDelay_Timer -= diff; + break; + } + } + + void SummonCreatures() + { + if (GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID)) + { + Creature *DefiasPirate1 = pIronCladDoor->SummonCreature(657,pIronCladDoor->GetPositionX() - 2,pIronCladDoor->GetPositionY()-7,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + Creature *DefiasPirate2 = pIronCladDoor->SummonCreature(657,pIronCladDoor->GetPositionX() + 3,pIronCladDoor->GetPositionY()-6,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + Creature *DefiasCompanion = pIronCladDoor->SummonCreature(3450,pIronCladDoor->GetPositionX() + 2,pIronCladDoor->GetPositionY()-6,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + + DefiasPirate1GUID = DefiasPirate1->GetGUID(); + DefiasPirate2GUID = DefiasPirate2->GetGUID(); + DefiasCompanionGUID = DefiasCompanion->GetGUID(); + } + } + + void MoveCreaturesInside() + { + if (!DefiasPirate1GUID || !DefiasPirate2GUID || !DefiasCompanionGUID) + return; + + Creature *pDefiasPirate1 = instance->GetCreature(DefiasPirate1GUID); + Creature *pDefiasPirate2 = instance->GetCreature(DefiasPirate2GUID); + Creature *pDefiasCompanion = instance->GetCreature(DefiasCompanionGUID); + if (!pDefiasPirate1 || !pDefiasPirate2 || !pDefiasCompanion) + return; + + MoveCreatureInside(pDefiasPirate1); + MoveCreatureInside(pDefiasPirate2); + MoveCreatureInside(pDefiasCompanion); + } + + void MoveCreatureInside(Creature* pCreature) + { + pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCreature->GetMotionMaster()->MovePoint(0, -102.7,-655.9, pCreature->GetPositionZ()); + } + + void ShootCannon() + { + if (GameObject *pDefiasCannon = instance->GetGameObject(DefiasCannonGUID)) + { + pDefiasCannon->SetGoState(GO_STATE_ACTIVE); + DoPlaySound(pDefiasCannon, SOUND_CANNONFIRE); + } + } + + void BlastOutDoor() + { + if (GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID)) + { + pIronCladDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + DoPlaySound(pIronCladDoor, SOUND_DESTROYDOOR); + } + } + + void LeverStucked() + { + if (GameObject *pDoorLever = instance->GetGameObject(DoorLeverGUID)) + pDoorLever->SetUInt32Value(GAMEOBJECT_FLAGS, 4); + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_FACTORY_DOOR: FactoryDoorGUID = pGo->GetGUID(); break; + case GO_IRONCLAD_DOOR: IronCladDoorGUID = pGo->GetGUID(); break; + case GO_DEFIAS_CANNON: DefiasCannonGUID = pGo->GetGUID(); break; + case GO_DOOR_LEVER: DoorLeverGUID = pGo->GetGUID(); break; + case GO_MR_SMITE_CHEST: uiSmiteChestGUID = pGo->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch (type) + { + case EVENT_STATE: + if (DefiasCannonGUID && IronCladDoorGUID) + State=data; + break; + case EVENT_RHAHKZOR: + if (data == DONE) + if (GameObject* pGo = instance->GetGameObject(FactoryDoorGUID)) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + } + } + + uint32 GetData(uint32 type) + { + switch (type) + { + case EVENT_STATE: + return State; + } + + return 0; + } + + uint64 GetData64(uint32 data) + { + switch (data) + { + case DATA_SMITE_CHEST: + return uiSmiteChestGUID; + } + + return 0; + } + + void DoPlaySound(GameObject* unit, uint32 sound) + { + WorldPacket data(4); + data.SetOpcode(SMSG_PLAY_SOUND); + data << uint32(sound); + unit->SendMessageToSet(&data,false); + } + + void DoPlaySoundCreature(Unit* unit, uint32 sound) + { + WorldPacket data(4); + data.SetOpcode(SMSG_PLAY_SOUND); + data << uint32(sound); + unit->SendMessageToSet(&data,false); + } +}; + +InstanceData* GetInstanceData_instance_deadmines(Map* pMap) +{ + return new instance_deadmines(pMap); +} + +void AddSC_instance_deadmines() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_deadmines"; + newscript->GetInstanceData = &GetInstanceData_instance_deadmines; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp new file mode 100644 index 00000000000..c39bfb69910 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -0,0 +1,593 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Gnomeregan +SDAuthor: Manuel +SD%Complete: 90% +SDComment: Some visual effects are not implemented. +Script Data End */ + +#include "ScriptedPch.h" +#include "gnomeregan.h" +#include "ScriptedEscortAI.h" + +#define GOSSIP_START_EVENT "I am ready to being" + +enum eBlastmasterEmiShortfuse +{ + GOSSIP_TEXT_EMI = 1693, + + SAY_BLASTMASTER_0 = -1090000, + SAY_BLASTMASTER_1 = -1090001, + SAY_BLASTMASTER_2 = -1090002, + SAY_BLASTMASTER_3 = -1090003, + SAY_BLASTMASTER_4 = -1090004, + SAY_BLASTMASTER_5 = -1090005, + SAY_BLASTMASTER_6 = -1090006, + SAY_BLASTMASTER_7 = -1090007, + SAY_BLASTMASTER_8 = -1090008, + SAY_BLASTMASTER_9 = -1090009, + SAY_BLASTMASTER_10 = -1090010, + SAY_BLASTMASTER_11 = -1090011, + SAY_BLASTMASTER_12 = -1090012, + SAY_BLASTMASTER_13 = -1090013, + SAY_BLASTMASTER_14 = -1090014, + SAY_BLASTMASTER_15 = -1090015, + SAY_BLASTMASTER_16 = -1090016, + SAY_BLASTMASTER_17 = -1090017, + SAY_BLASTMASTER_18 = -1090018, + SAY_BLASTMASTER_19 = -1090019, + SAY_BLASTMASTER_20 = -1090020, + SAY_BLASTMASTER_21 = -1090021, + SAY_BLASTMASTER_22 = -1090022, + SAY_BLASTMASTER_23 = -1090023, + SAY_BLASTMASTER_24 = -1090024, + SAY_BLASTMASTER_25 = -1090025, + SAY_BLASTMASTER_26 = -1090026, + SAY_BLASTMASTER_27 = -1090027, + + SAY_GRUBBIS = -1090028 +}; + +const Position SpawnPosition[] = +{ + {-557.630,-114.514,-152.209,0.641}, + {-555.263,-113.802,-152.737,0.311}, + {-552.154,-112.476,-153.349,0.621}, + {-548.692,-111.089,-154.090,0.621}, + {-546.905,-108.340,-154.877,0.729}, + {-547.736,-105.154,-155.176,0.372}, + {-547.274,-114.109,-153.952,0.735}, + {-552.534,-110.012,-153.577,0.747}, + {-550.708,-116.436,-153.103,0.679}, + {-554.030,-115.983,-152.635,0.695}, + {-494.595,-87.516,149.116,3.344}, + {-493.349,-90.845,-148.882,3.717}, + {-491.995,-87.619,-148.197,3.230}, + {-490.732,-90.739,-148.091,3.230}, + {-490.554,-89.114,-148.055,3.230}, + {-495.240,-90.808,-149.493,3.238}, + {-494.195,-89.553,-149.131,3.254} +}; + +struct npc_blastmaster_emi_shortfuseAI : public npc_escortAI +{ + npc_blastmaster_emi_shortfuseAI(Creature* pCreature) : npc_escortAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + pCreature->RestoreFaction(); + Reset(); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiTimer; + + std::list SummonList; + std::list GoSummonList; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + uiTimer = 0; + uiPhase = 0; + + RestoreAll(); + + SummonList.clear(); + GoSummonList.clear(); + } + } + + void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) + { + uiTimer = uiTimerStep; + if (bNextStep) + ++uiPhase; + else + uiPhase = uiPhaseStep; + } + + void CaveDestruction(bool bBool) + { + if (GoSummonList.empty()) + return; + + for (std::list::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) + { + if (GameObject* pGo = GameObject::GetGameObject(*me, *itr)) + { + if (pGo) + { + if (Creature *trigger = pGo->SummonTrigger(pGo->GetPositionX(), pGo->GetPositionY(),pGo->GetPositionZ(), 0, 1)) + { + //visual effects are not working! ¬¬ + trigger->CastSpell(trigger,11542,true); + trigger->CastSpell(trigger,35470,true); + } + pGo->RemoveFromWorld(); + //pGo->CastSpell(me,12158); makes all die?! + } + } + } + + if (bBool) + { + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) + pInstance->HandleGameObject(NULL,false,pGo); + }else + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) + pInstance->HandleGameObject(NULL,false,pGo); + } + + void SetInFace(bool bBool) + { + if (!pInstance) + return; + + if (bBool) + { + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) + me->SetFacingToObject(pGo); + }else + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) + me->SetFacingToObject(pGo); + } + + void RestoreAll() + { + if (!pInstance) + return; + + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) + pInstance->HandleGameObject(NULL,false,pGo); + + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) + pInstance->HandleGameObject(NULL,false,pGo); + + if (!GoSummonList.empty()) + for (std::list::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) + { + if (GameObject* pGo = GameObject::GetGameObject(*me, *itr)) + pGo->RemoveFromWorld(); + } + + if (!SummonList.empty()) + for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) + { + if (Creature* pSummon = Unit::GetCreature(*me, *itr)) + { + if (pSummon->isAlive()) + pSummon->DisappearAndDie(); + else + pSummon->RemoveCorpse(); + } + } + } + + void AggroAllPlayers(Creature* pTemp) + { + Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + pTemp->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(pTemp); + pTemp->AddThreat(pPlayer, 0.0f); + } + } + } + } + + void WaypointReached(uint32 uiPoint) + { + //just in case + if (GetPlayerForEscort()) + if (me->getFaction() != GetPlayerForEscort()->getFaction()) + me->setFaction(GetPlayerForEscort()->getFaction()); + + switch(uiPoint) + { + case 3: + SetEscortPaused(true); + NextStep(2000,false,3); + break; + case 7: + SetEscortPaused(true); + NextStep(2000,false,4); + break; + case 9: + NextStep(1000,false,8); + break; + case 10: + NextStep(25000,false,10); + break; + case 11: + SetEscortPaused(true); + SetInFace(true); + NextStep(1000,false,11); + break; + case 12: + NextStep(25000,false,18); + break; + case 13: + Summon(7); + NextStep(25000,false,19); + break; + case 14: + SetInFace(false); + DoScriptText(SAY_BLASTMASTER_26,me); + SetEscortPaused(true); + NextStep(5000,false,20); + break; + } + } + + void SetData(uint32 uiI,uint32 uiValue) + { + switch(uiI) + { + case 1: + SetEscortPaused(true); + DoScriptText(SAY_BLASTMASTER_0,me); + NextStep(1500,true); + break; + case 2: + if (!pInstance) + return; + + switch(uiValue) + { + case 1: + pInstance->SetData(TYPE_EVENT, IN_PROGRESS); + break; + case 2: + pInstance->SetData(TYPE_EVENT, DONE); + NextStep(5000,false,22); + break; + } + break; + } + } + + void Summon(uint8 uiCase) + { + switch(uiCase) + { + case 1: + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[5], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[6], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[7], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[8], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[9], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + break; + case 2: + if (GameObject* pGo = me->SummonGameObject(183410, -533.140,-105.322,-156.016, 0, 0, 0, 0, 0, 1000)) + { + GoSummonList.push_back(pGo->GetGUID()); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! + } + Summon(3); + break; + case 3: + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + DoScriptText(SAY_BLASTMASTER_19,me); + break; + case 4: + if (GameObject* pGo = me->SummonGameObject(183410, -542.199,-96.854,-155.790, 0, 0, 0, 0, 0, 1000)) + { + GoSummonList.push_back(pGo->GetGUID()); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + } + break; + case 5: + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + DoScriptText(SAY_BLASTMASTER_15,me); + break; + case 6: + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[10], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[11], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[12], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[13], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[14], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + break; + case 7: + if (GameObject* pGo = me->SummonGameObject(183410, -507.820,-103.333,-151.353, 0, 0, 0, 0, 0, 1000)) + { + GoSummonList.push_back(pGo->GetGUID()); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! + Summon(6); + } + break; + case 8: + if (GameObject* pGo = me->SummonGameObject(183410, -511.829,-86.249,-151.431, 0, 0, 0, 0, 0, 1000)) + { + GoSummonList.push_back(pGo->GetGUID()); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! + } + break; + case 9: + if (Creature* pGrubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000)) + DoScriptText(SAY_GRUBBIS,pGrubbis); + me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); + break; + } + } + + void UpdateEscortAI(const uint32 uiDiff) + { + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + DoScriptText(SAY_BLASTMASTER_1,me); + NextStep(1500,true); + break; + case 2: + SetEscortPaused(false); + NextStep(0,false,0); + break; + case 3: + DoScriptText(SAY_BLASTMASTER_2,me); + SetEscortPaused(false); + NextStep(0,false,0); + break; + case 4: + DoScriptText(SAY_BLASTMASTER_3,me); + NextStep(3000,true); + break; + case 5: + DoScriptText(SAY_BLASTMASTER_4,me); + NextStep(3000,true); + break; + case 6: + SetInFace(true); + DoScriptText(SAY_BLASTMASTER_5,me); + Summon(1); + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) + pInstance->HandleGameObject(NULL,true,pGo); + NextStep(3000,true); + break; + case 7: + DoScriptText(SAY_BLASTMASTER_6,me); + SetEscortPaused(false); + NextStep(0,false,0); + break; + case 8: + me->HandleEmoteCommand(EMOTE_STATE_WORK); + NextStep(25000,true); + break; + case 9: + Summon(2); + NextStep(0,false); + break; + case 10: + Summon(4); + NextStep(0,false); + break; + case 11: + DoScriptText(SAY_BLASTMASTER_17,me); + NextStep(5000,true); + break; + case 12: + DoScriptText(SAY_BLASTMASTER_18,me); + NextStep(5000,true); + break; + case 13: + DoScriptText(SAY_BLASTMASTER_20,me); + CaveDestruction(true); + NextStep(8000,true); + break; + case 14: + DoScriptText(SAY_BLASTMASTER_21,me); + NextStep(8500,true); + break; + case 15: + DoScriptText(SAY_BLASTMASTER_22,me); + NextStep(2000,true); + break; + case 16: + DoScriptText(SAY_BLASTMASTER_23,me); + SetInFace(false); + if (pInstance) + if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) + pInstance->HandleGameObject(NULL,true,pGo); + NextStep(2000,true); + break; + case 17: + SetEscortPaused(false); + DoScriptText(SAY_BLASTMASTER_24,me); + Summon(6); + NextStep(0,false); + break; + case 18: + Summon(7); + NextStep(0,false); + break; + case 19: + SetInFace(false); + Summon(8); + DoScriptText(SAY_BLASTMASTER_25,me); + NextStep(0,false); + break; + case 20: + DoScriptText(SAY_BLASTMASTER_27,me); + NextStep(2000,true); + break; + case 21: + Summon(9); + NextStep(0,false); + break; + case 22: + CaveDestruction(false); + DoScriptText(SAY_BLASTMASTER_20,me); + NextStep(0,false); + break; + } + } else uiTimer -= uiDiff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* pSummon) + { + SummonList.push_back(pSummon->GetGUID()); + AggroAllPlayers(pSummon); + } +}; + +CreatureAI* GetAI_npc_blastmaster_emi_shortfuse(Creature* pCreature) +{ + return new npc_blastmaster_emi_shortfuseAI(pCreature); +} + +bool GossipHello_npc_blastmaster_emi_shortfuse(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && pInstance->GetData(TYPE_EVENT) == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_EMI, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_blastmaster_emi_shortfuse(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + if (npc_escortAI* pEscortAI = CAST_AI(npc_blastmaster_emi_shortfuseAI, pCreature->AI())) + pEscortAI->Start(true, false,pPlayer->GetGUID()); + + pCreature->setFaction(pPlayer->getFaction()); + pCreature->AI()->SetData(1,0); + + pPlayer->CLOSE_GOSSIP_MENU(); + } + return true; +} + +struct boss_grubbisAI : public ScriptedAI +{ + boss_grubbisAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SetDataSummoner(); + } + + void SetDataSummoner() + { + if (!me->isSummon()) + return; + + if (Unit* pSummon = CAST_SUM(me)->GetSummoner()) + CAST_CRE(pSummon)->AI()->SetData(2,1); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (!me->isSummon()) + return; + + if (Unit* pSummon = CAST_SUM(me)->GetSummoner()) + CAST_CRE(pSummon)->AI()->SetData(2,2); + } +}; + +CreatureAI* GetAI_boss_grubbis(Creature* pCreature) +{ + return new boss_grubbisAI(pCreature); +} + +void AddSC_gnomeregan() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_blastmaster_emi_shortfuse"; + newscript->pGossipHello = &GossipHello_npc_blastmaster_emi_shortfuse; + newscript->pGossipSelect = &GossipSelect_npc_blastmaster_emi_shortfuse; + newscript->GetAI = &GetAI_npc_blastmaster_emi_shortfuse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_grubbis"; + newscript->GetAI = &GetAI_boss_grubbis; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h new file mode 100644 index 00000000000..e46c811e9b1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_GNOMEREGAN_H +#define DEF_GNOMEREGAN_H + +enum eGameObjects +{ + GO_CAVE_IN_LEFT = 146085, + GO_CAVE_IN_RIGHT = 146086 +}; + +enum eCreatures +{ + NPC_BLASTMASTER_EMI_SHORTFUSE = 7998, + NPC_CAVERNDEEP_AMBUSHER = 6207, + NPC_GRUBBIS = 7361, + NPC_CHOMPER = 6215 +}; + +enum eData +{ + TYPE_EVENT = 1 +}; + +enum eData64 +{ + DATA_GO_CAVE_IN_LEFT, + DATA_GO_CAVE_IN_RIGHT, + DATA_NPC_BASTMASTER_EMI_SHORTFUSE +}; + +#endif diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/instance_gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/instance_gnomeregan.cpp new file mode 100644 index 00000000000..980a6d3552b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/instance_gnomeregan.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "gnomeregan.h" + +#define MAX_ENCOUNTER 1 + +struct instance_gnomeregan : public ScriptedInstance +{ + instance_gnomeregan(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + }; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 uiCaveInLeftGUID; + uint64 uiCaveInRightGUID; + + uint64 uiBastmasterEmiShortfuseGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + uiCaveInLeftGUID = 0; + uiCaveInRightGUID = 0; + + uiBastmasterEmiShortfuseGUID = 0; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) + { + switch(pCreature->GetEntry()) + { + case NPC_BLASTMASTER_EMI_SHORTFUSE: uiBastmasterEmiShortfuseGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*bAdd*/) + { + switch(pGo->GetEntry()) + { + case GO_CAVE_IN_LEFT: + uiCaveInLeftGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE || m_auiEncounter[0] == NOT_STARTED) + HandleGameObject(NULL,false,pGo); + break; + case GO_CAVE_IN_RIGHT: + uiCaveInRightGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE || m_auiEncounter[0] == NOT_STARTED) + HandleGameObject(NULL,false,pGo); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_EVENT: + m_auiEncounter[0] = uiData; + if (uiData == DONE) + SaveToDB(); + break; + } + } + + uint32 GetData(uint32 uiType, uint32 /*uiData*/) + { + switch(uiType) + { + case TYPE_EVENT: return m_auiEncounter[0]; + } + } + + uint64 GetData64(uint32 uiType) + { + switch(uiType) + { + case DATA_GO_CAVE_IN_LEFT: return uiCaveInLeftGUID; + case DATA_GO_CAVE_IN_RIGHT: return uiCaveInRightGUID; + case DATA_NPC_BASTMASTER_EMI_SHORTFUSE: return uiBastmasterEmiShortfuseGUID; + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_gnomeregan(Map* pMap) +{ + return new instance_gnomeregan(pMap); +} + +void AddSC_instance_gnomeregan() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "instance_gnomeregan"; + newscript->GetInstanceData = &GetInstanceData_instance_gnomeregan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp new file mode 100644 index 00000000000..7105d27ca6a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp @@ -0,0 +1,196 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Curator +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1532057 +#define SAY_SUMMON1 -1532058 +#define SAY_SUMMON2 -1532059 +#define SAY_EVOCATE -1532060 +#define SAY_ENRAGE -1532061 +#define SAY_KILL1 -1532062 +#define SAY_KILL2 -1532063 +#define SAY_DEATH -1532064 + +//Flare spell info +#define SPELL_ASTRAL_FLARE_PASSIVE 30234 //Visual effect + Flare damage + +//Curator spell info +#define SPELL_HATEFUL_BOLT 30383 +#define SPELL_EVOCATION 30254 +#define SPELL_ENRAGE 30403 //Arcane Infusion: Transforms Curator and adds damage. +#define SPELL_BERSERK 26662 + +struct boss_curatorAI : public ScriptedAI +{ + boss_curatorAI(Creature *c) : ScriptedAI(c) {} + + uint32 AddTimer; + uint32 HatefulBoltTimer; + uint32 BerserkTimer; + + bool Enraged; + bool Evocating; + + void Reset() + { + AddTimer = 10000; + HatefulBoltTimer = 15000; //This time may be wrong + BerserkTimer = 720000; //12 minutes + Enraged = false; + Evocating = false; + + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //always decrease BerserkTimer + if (BerserkTimer <= diff) + { + //if evocate, then break evocate + if (Evocating) + { + if (me->HasAura(SPELL_EVOCATION)) + me->RemoveAurasDueToSpell(SPELL_EVOCATION); + + Evocating = false; + } + + //may not be correct SAY (generic hard enrage) + DoScriptText(SAY_ENRAGE, me); + + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_BERSERK); + + //don't know if he's supposed to do summon/evocate after hard enrage (probably not) + Enraged = true; + } else BerserkTimer -= diff; + + if (Evocating) + { + //not supposed to do anything while evocate + if (me->HasAura(SPELL_EVOCATION)) + return; + else + Evocating = false; + } + + if (!Enraged) + { + if (AddTimer <= diff) + { + //Summon Astral Flare + Creature* AstralFlare = DoSpawnCreature(17096, rand()%37, rand()%37, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (AstralFlare && pTarget) + { + AstralFlare->CastSpell(AstralFlare, SPELL_ASTRAL_FLARE_PASSIVE, false); + AstralFlare->AI()->AttackStart(pTarget); + } + + //Reduce Mana by 10% of max health + if (int32 mana = me->GetMaxPower(POWER_MANA)) + { + mana /= 10; + me->ModifyPower(POWER_MANA, -mana); + + //if this get's us below 10%, then we evocate (the 10th should be summoned now) + if (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA) < 10) + { + DoScriptText(SAY_EVOCATE, me); + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_EVOCATION); + Evocating = true; + //no AddTimer cooldown, this will make first flare appear instantly after evocate end, like expected + return; + } + else + { + if (urand(0,1) == 0) + { + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + } + } + } + + AddTimer = 10000; + } else AddTimer -= diff; + + if (me->GetHealth()*100 / me->GetMaxHealth() <= 15) + { + Enraged = true; + DoCast(me, SPELL_ENRAGE); + DoScriptText(SAY_ENRAGE, me); + } + } + + if (HatefulBoltTimer <= diff) + { + if (Enraged) + HatefulBoltTimer = 7000; + else + HatefulBoltTimer = 15000; + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1)) + DoCast(pTarget, SPELL_HATEFUL_BOLT); + + } else HatefulBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_curator(Creature* pCreature) +{ + return new boss_curatorAI (pCreature); +} + +void AddSC_boss_curator() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_curator"; + newscript->GetAI = &GetAI_boss_curator; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp new file mode 100644 index 00000000000..21db1be1be3 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Maiden_of_Virtue +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1532018 +#define SAY_SLAY1 -1532019 +#define SAY_SLAY2 -1532020 +#define SAY_SLAY3 -1532021 +#define SAY_REPENTANCE1 -1532022 +#define SAY_REPENTANCE2 -1532023 +#define SAY_DEATH -1532024 + +#define SPELL_REPENTANCE 29511 +#define SPELL_HOLYFIRE 29522 +#define SPELL_HOLYWRATH 32445 +#define SPELL_HOLYGROUND 29512 +#define SPELL_BERSERK 26662 + +struct boss_maiden_of_virtueAI : public ScriptedAI +{ + boss_maiden_of_virtueAI(Creature *c) : ScriptedAI(c) {} + + uint32 Repentance_Timer; + uint32 Holyfire_Timer; + uint32 Holywrath_Timer; + uint32 Holyground_Timer; + uint32 Enrage_Timer; + + bool Enraged; + + void Reset() + { + Repentance_Timer = 25000+(rand()%15000); + Holyfire_Timer = 8000+(rand()%17000); + Holywrath_Timer = 15000+(rand()%10000); + Holyground_Timer = 3000; + Enrage_Timer = 600000; + + Enraged = false; + } + + void KilledUnit(Unit* /*Victim*/) + { + if (urand(0,1) == 0) + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Enrage_Timer < diff && !Enraged) + { + DoCast(me, SPELL_BERSERK, true); + Enraged = true; + } else Enrage_Timer -= diff; + + if (Holyground_Timer <= diff) + { + DoCast(me, SPELL_HOLYGROUND, true); //Triggered so it doesn't interrupt her at all + Holyground_Timer = 3000; + } else Holyground_Timer -= diff; + + if (Repentance_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REPENTANCE); + DoScriptText(RAND(SAY_REPENTANCE1,SAY_REPENTANCE2), me); + + Repentance_Timer = urand(25000,35000); //A little randomness on that spell + } else Repentance_Timer -= diff; + + if (Holyfire_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_HOLYFIRE); + + Holyfire_Timer = urand(8000,23000); //Anywhere from 8 to 23 seconds, good luck having several of those in a row! + } else Holyfire_Timer -= diff; + + if (Holywrath_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_HOLYWRATH); + + Holywrath_Timer = urand(20000,25000); //20-30 secs sounds nice + } else Holywrath_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_maiden_of_virtue(Creature* pCreature) +{ + return new boss_maiden_of_virtueAI (pCreature); +} + +void AddSC_boss_maiden_of_virtue() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_maiden_of_virtue"; + newscript->GetAI = &GetAI_boss_maiden_of_virtue; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp new file mode 100644 index 00000000000..a2f2a8b605e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp @@ -0,0 +1,310 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Midnight +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_MIDNIGHT_KILL -1532000 +#define SAY_APPEAR1 -1532001 +#define SAY_APPEAR2 -1532002 +#define SAY_APPEAR3 -1532003 +#define SAY_MOUNT -1532004 +#define SAY_KILL1 -1532005 +#define SAY_KILL2 -1532006 +#define SAY_DISARMED -1532007 +#define SAY_DEATH -1532008 +#define SAY_RANDOM1 -1532009 +#define SAY_RANDOM2 -1532010 + +#define SPELL_SHADOWCLEAVE 29832 +#define SPELL_INTANGIBLE_PRESENCE 29833 +#define SPELL_BERSERKER_CHARGE 26561 //Only when mounted + +#define MOUNTED_DISPLAYID 16040 + +//Attumen (TODO: Use the summoning spell instead of Creature id. It works , but is not convenient for us) +#define SUMMON_ATTUMEN 15550 + +struct boss_midnightAI : public ScriptedAI +{ + boss_midnightAI(Creature *c) : ScriptedAI(c) {} + + uint64 Attumen; + uint8 Phase; + uint32 Mount_Timer; + + void Reset() + { + Phase = 1; + Attumen = 0; + Mount_Timer = 0; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_ON); + } + + void EnterCombat(Unit* /*who*/) {} + + void KilledUnit(Unit * /*victim*/) + { + if (Phase == 2) + { + if (Unit *pUnit = Unit::GetUnit(*me, Attumen)) + DoScriptText(SAY_MIDNIGHT_KILL, pUnit); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Phase == 1 && (me->GetHealth()*100)/me->GetMaxHealth() < 95) + { + Phase = 2; + if (Creature* pAttumen = me->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000)) + { + Attumen = pAttumen->GetGUID(); + pAttumen->AI()->AttackStart(me->getVictim()); + SetMidnight(pAttumen, me->GetGUID()); + DoScriptText(RAND(SAY_APPEAR1,SAY_APPEAR2,SAY_APPEAR3), pAttumen); + } + } + else if (Phase == 2 && (me->GetHealth()*100)/me->GetMaxHealth() < 25) + { + if (Unit *pAttumen = Unit::GetUnit(*me, Attumen)) + Mount(pAttumen); + } + else if (Phase == 3) + { + if (Mount_Timer) + { + if (Mount_Timer <= diff) + { + Mount_Timer = 0; + me->SetVisibility(VISIBILITY_OFF); + me->GetMotionMaster()->MoveIdle(); + if (Unit *pAttumen = Unit::GetUnit(*me, Attumen)) + { + pAttumen->SetDisplayId(MOUNTED_DISPLAYID); + pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pAttumen->getVictim()) + { + pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim()); + pAttumen->SetUInt64Value(UNIT_FIELD_TARGET, pAttumen->getVictim()->GetGUID()); + } + pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X,1); + } + } else Mount_Timer -= diff; + } + } + + if (Phase != 3) + DoMeleeAttackIfReady(); + } + + void Mount(Unit *pAttumen) + { + DoScriptText(SAY_MOUNT, pAttumen); + Phase = 3; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + float angle = me->GetAngle(pAttumen); + float distance = me->GetDistance2d(pAttumen); + float newX = me->GetPositionX() + cos(angle)*(distance/2) ; + float newY = me->GetPositionY() + sin(angle)*(distance/2) ; + float newZ = 50; + //me->Relocate(newX,newY,newZ,angle); + //me->SendMonsterMove(newX, newY, newZ, 0, true, 1000); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, newX, newY, newZ); + distance += 10; + newX = me->GetPositionX() + cos(angle)*(distance/2) ; + newY = me->GetPositionY() + sin(angle)*(distance/2) ; + pAttumen->GetMotionMaster()->Clear(); + pAttumen->GetMotionMaster()->MovePoint(0, newX, newY, newZ); + //pAttumen->Relocate(newX,newY,newZ,-angle); + //pAttumen->SendMonsterMove(newX, newY, newZ, 0, true, 1000); + Mount_Timer = 1000; + } + + void SetMidnight(Creature *, uint64); //Below .. +}; + +CreatureAI* GetAI_boss_midnight(Creature* pCreature) +{ + return new boss_midnightAI(pCreature); +} + +struct boss_attumenAI : public ScriptedAI +{ + boss_attumenAI(Creature *c) : ScriptedAI(c) + { + Phase = 1; + + CleaveTimer = urand(10000,15000); + CurseTimer = 30000; + RandomYellTimer = urand(30000,60000); //Occasionally yell + ChargeTimer = 20000; + ResetTimer = 0; + } + + uint64 Midnight; + uint8 Phase; + uint32 CleaveTimer; + uint32 CurseTimer; + uint32 RandomYellTimer; + uint32 ChargeTimer; //only when mounted + uint32 ResetTimer; + + void Reset() + { + ResetTimer = 2000; + } + + void EnterCombat(Unit* /*who*/) {} + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + if (Unit *pMidnight = Unit::GetUnit(*me, Midnight)) + pMidnight->Kill(pMidnight); + } + + void UpdateAI(const uint32 diff) + { + if (ResetTimer) + { + if (ResetTimer <= diff) + { + ResetTimer = 0; + Unit *pMidnight = Unit::GetUnit(*me, Midnight); + if (pMidnight) + { + pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pMidnight->SetVisibility(VISIBILITY_ON); + } + Midnight = 0; + me->SetVisibility(VISIBILITY_OFF); + me->Kill(me); + } + } else ResetTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) + return; + + if (CleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWCLEAVE); + CleaveTimer = urand(10000,15000); + } else CleaveTimer -= diff; + + if (CurseTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); + CurseTimer = 30000; + } else CurseTimer -= diff; + + if (RandomYellTimer <= diff) + { + DoScriptText(RAND(SAY_RANDOM1,SAY_RANDOM2), me); + RandomYellTimer = urand(30000,60000); + } else RandomYellTimer -= diff; + + if (me->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID) + { + if (ChargeTimer <= diff) + { + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && !pTarget->IsWithinDist(me, ATTACK_DISTANCE, false)) + target_list.push_back(pTarget); + pTarget = NULL; + } + if (target_list.size()) + pTarget = *(target_list.begin()+rand()%target_list.size()); + + DoCast(pTarget, SPELL_BERSERKER_CHARGE); + ChargeTimer = 20000; + } else ChargeTimer -= diff; + } + else + { + if ((me->GetHealth()*100)/me->GetMaxHealth() < 25) + { + Creature *pMidnight = Unit::GetCreature(*me, Midnight); + if (pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT) + { + CAST_AI(boss_midnightAI, (pMidnight->AI()))->Mount(me); + me->SetHealth(pMidnight->GetHealth()); + DoResetThreat(); + } + } + } + + DoMeleeAttackIfReady(); + } + + void SpellHit(Unit * /*source*/, const SpellEntry *spell) + { + if (spell->Mechanic == MECHANIC_DISARM) + DoScriptText(SAY_DISARMED, me); + } +}; + +void boss_midnightAI::SetMidnight(Creature *pAttumen, uint64 value) +{ + CAST_AI(boss_attumenAI, pAttumen->AI())->Midnight = value; +} + +CreatureAI* GetAI_boss_attumen(Creature* pCreature) +{ + return new boss_attumenAI (pCreature); +} + +void AddSC_boss_attumen() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_attumen"; + newscript->GetAI = &GetAI_boss_attumen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_midnight"; + newscript->GetAI = &GetAI_boss_midnight; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp new file mode 100644 index 00000000000..6c8fabcca35 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp @@ -0,0 +1,785 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moroes +SD%Complete: 95 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define SAY_AGGRO -1532011 +#define SAY_SPECIAL_1 -1532012 +#define SAY_SPECIAL_2 -1532013 +#define SAY_KILL_1 -1532014 +#define SAY_KILL_2 -1532015 +#define SAY_KILL_3 -1532016 +#define SAY_DEATH -1532017 + +#define SPELL_VANISH 29448 +#define SPELL_GARROTE 37066 +#define SPELL_BLIND 34694 +#define SPELL_GOUGE 29425 +#define SPELL_FRENZY 37023 + +#define POS_Z 81.73 + +float Locations[4][3]= +{ + {-10991.0, -1884.33, 0.614315}, + {-10989.4, -1885.88, 0.904913}, + {-10978.1, -1887.07, 2.035550}, + {-10975.9, -1885.81, 2.253890}, +}; + +const uint32 Adds[6]= +{ + 17007, + 19872, + 19873, + 19874, + 19875, + 19876, +}; + +struct boss_moroesAI : public ScriptedAI +{ + boss_moroesAI(Creature *c) : ScriptedAI(c) + { + for (uint8 i = 0; i < 4; ++i) + { + AddId[i] = 0; + } + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint64 AddGUID[4]; + + uint32 Vanish_Timer; + uint32 Blind_Timer; + uint32 Gouge_Timer; + uint32 Wait_Timer; + uint32 CheckAdds_Timer; + uint32 AddId[4]; + + bool InVanish; + bool Enrage; + + void Reset() + { + Vanish_Timer = 30000; + Blind_Timer = 35000; + Gouge_Timer = 23000; + Wait_Timer = 0; + CheckAdds_Timer = 5000; + + Enrage = false; + InVanish = false; + if (me->GetHealth() > 0) + { + SpawnAdds(); + } + + if (pInstance) + pInstance->SetData(TYPE_MOROES, NOT_STARTED); + } + + void StartEvent() + { + if (pInstance) + pInstance->SetData(TYPE_MOROES, IN_PROGRESS); + + DoZoneInCombat(); + } + + void EnterCombat(Unit* /*who*/) + { + StartEvent(); + + DoScriptText(SAY_AGGRO, me); + AddsAttack(); + DoZoneInCombat(); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); + } + + void JustDied(Unit* /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_MOROES, DONE); + + DeSpawnAdds(); + + //remove aura from spell Garrote when Moroes dies + if (pInstance) + pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GARROTE); + } + + void SpawnAdds() + { + DeSpawnAdds(); + if (isAddlistEmpty()) + { + Creature *pCreature = NULL; + std::vector AddList; + + for (uint8 i = 0; i < 6; ++i) + AddList.push_back(Adds[i]); + + while (AddList.size() > 4) + AddList.erase((AddList.begin())+(rand()%AddList.size())); + + uint8 i = 0; + for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr) + { + uint32 entry = *itr; + + pCreature = me->SummonCreature(entry, Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + if (pCreature) + { + AddGUID[i] = pCreature->GetGUID(); + AddId[i] = entry; + } + ++i; + } + }else + { + for (uint8 i = 0; i < 4; ++i) + { + Creature *pCreature = me->SummonCreature(AddId[i], Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + if (pCreature) + { + AddGUID[i] = pCreature->GetGUID(); + } + } + } + } + + bool isAddlistEmpty() + { + for (uint8 i = 0; i < 4; ++i) + { + if (AddId[i] == 0) + return true; + } + return false; + } + + void DeSpawnAdds() + { + for (uint8 i = 0; i < 4 ; ++i) + { + Creature* Temp = NULL; + if (AddGUID[i]) + { + Temp = Creature::GetCreature((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + Temp->DisappearAndDie(); + } + } + } + + void AddsAttack() + { + for (uint8 i = 0; i < 4; ++i) + { + Creature* Temp = NULL; + if (AddGUID[i]) + { + Temp = Creature::GetCreature((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + { + Temp->AI()->AttackStart(me->getVictim()); + DoZoneInCombat(Temp); + } else + EnterEvadeMode(); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (pInstance && !pInstance->GetData(TYPE_MOROES)) + { + EnterEvadeMode(); + return; + } + + if (!Enrage && me->GetHealth()*100 / me->GetMaxHealth() < 30) + { + DoCast(me, SPELL_FRENZY); + Enrage = true; + } + + if (CheckAdds_Timer <= diff) + { + for (uint8 i = 0; i < 4; ++i) + { + Creature* Temp = NULL; + if (AddGUID[i]) + { + Temp = Unit::GetCreature((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + if (!Temp->getVictim()) + Temp->AI()->AttackStart(me->getVictim()); + } + } + CheckAdds_Timer = 5000; + } else CheckAdds_Timer -= diff; + + if (!Enrage) + { + //Cast Vanish, then Garrote random victim + if (Vanish_Timer <= diff) + { + DoCast(me, SPELL_VANISH); + InVanish = true; + Vanish_Timer = 30000; + Wait_Timer = 5000; + } else Vanish_Timer -= diff; + + if (Gouge_Timer <= diff) + { + DoCastVictim(SPELL_GOUGE); + Gouge_Timer = 40000; + } else Gouge_Timer -= diff; + + if (Blind_Timer <= diff) + { + std::list pTargets; + SelectTargetList(pTargets, 5, SELECT_TARGET_RANDOM, me->GetMeleeReach()*5, true); + for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) + if (!me->IsWithinMeleeRange(*i)) + { + DoCast(*i, SPELL_BLIND); + break; + } + Blind_Timer = 40000; + } else Blind_Timer -= diff; + } + + if (InVanish) + { + if (Wait_Timer <= diff) + { + DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2), me); + + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + pTarget->CastSpell(pTarget, SPELL_GARROTE,true); + + InVanish = false; + } else Wait_Timer -= diff; + } + + if (!InVanish) + DoMeleeAttackIfReady(); + } +}; + +struct boss_moroes_guestAI : public ScriptedAI +{ + ScriptedInstance* pInstance; + + uint64 GuestGUID[4]; + + boss_moroes_guestAI(Creature* c) : ScriptedAI(c) + { + for (uint8 i = 0; i < 4; ++i) + GuestGUID[i] = 0; + + pInstance = c->GetInstanceData(); + } + + void Reset() + { + if (pInstance) + pInstance->SetData(TYPE_MOROES, NOT_STARTED); + } + + void AcquireGUID() + { + if (!pInstance) + return; + + uint64 MoroesGUID = pInstance->GetData64(DATA_MOROES); + Creature* Moroes = (Unit::GetCreature((*me), MoroesGUID)); + if (Moroes) + { + for (uint8 i = 0; i < 4; ++i) + { + uint64 GUID = CAST_AI(boss_moroesAI, Moroes->AI())->AddGUID[i]; + if (GUID) + GuestGUID[i] = GUID; + } + } + } + + Unit* SelectGuestTarget() + { + uint64 TempGUID = GuestGUID[rand()%4]; + if (TempGUID) + { + Unit* pUnit = Unit::GetUnit((*me), TempGUID); + if (pUnit && pUnit->isAlive()) + return pUnit; + } + + return me; + } + + void UpdateAI(const uint32 /*diff*/) + { + if (pInstance && !pInstance->GetData(TYPE_MOROES)) + EnterEvadeMode(); + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_MANABURN 29405 +#define SPELL_MINDFLY 29570 +#define SPELL_SWPAIN 34441 +#define SPELL_SHADOWFORM 29406 + +struct boss_baroness_dorothea_millstipeAI : public boss_moroes_guestAI +{ + //Shadow Priest + boss_baroness_dorothea_millstipeAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 ManaBurn_Timer; + uint32 MindFlay_Timer; + uint32 ShadowWordPain_Timer; + + void Reset() + { + ManaBurn_Timer = 7000; + MindFlay_Timer = 1000; + ShadowWordPain_Timer = 6000; + + DoCast(me, SPELL_SHADOWFORM, true); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (MindFlay_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MINDFLY); + MindFlay_Timer = 12000; // 3 sec channeled + } else MindFlay_Timer -= diff; + + if (ManaBurn_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (pTarget->getPowerType() == POWER_MANA) + DoCast(pTarget, SPELL_MANABURN); + ManaBurn_Timer = 5000; // 3 sec cast + } else ManaBurn_Timer -= diff; + + if (ShadowWordPain_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_SWPAIN); + ShadowWordPain_Timer = 7000; + } + } else ShadowWordPain_Timer -= diff; + } +}; + +#define SPELL_HAMMEROFJUSTICE 13005 +#define SPELL_JUDGEMENTOFCOMMAND 29386 +#define SPELL_SEALOFCOMMAND 29385 + +struct boss_baron_rafe_dreugerAI : public boss_moroes_guestAI +{ + //Retr Pally + boss_baron_rafe_dreugerAI(Creature *c) : boss_moroes_guestAI(c){} + + uint32 HammerOfJustice_Timer; + uint32 SealOfCommand_Timer; + uint32 JudgementOfCommand_Timer; + + void Reset() + { + HammerOfJustice_Timer = 1000; + SealOfCommand_Timer = 7000; + JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (SealOfCommand_Timer <= diff) + { + DoCast(me, SPELL_SEALOFCOMMAND); + SealOfCommand_Timer = 32000; + JudgementOfCommand_Timer = 29000; + } else SealOfCommand_Timer -= diff; + + if (JudgementOfCommand_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_JUDGEMENTOFCOMMAND); + JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; + } else JudgementOfCommand_Timer -= diff; + + if (HammerOfJustice_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMMEROFJUSTICE); + HammerOfJustice_Timer = 12000; + } else HammerOfJustice_Timer -= diff; + } +}; + +#define SPELL_DISPELMAGIC 15090 //Self or other guest+Moroes +#define SPELL_GREATERHEAL 29564 //Self or other guest+Moroes +#define SPELL_HOLYFIRE 29563 +#define SPELL_PWSHIELD 29408 + +struct boss_lady_catriona_von_indiAI : public boss_moroes_guestAI +{ + //Holy Priest + boss_lady_catriona_von_indiAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 DispelMagic_Timer; + uint32 GreaterHeal_Timer; + uint32 HolyFire_Timer; + uint32 PowerWordShield_Timer; + + void Reset() + { + DispelMagic_Timer = 11000; + GreaterHeal_Timer = 1500; + HolyFire_Timer = 5000; + PowerWordShield_Timer = 1000; + + AcquireGUID(); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (PowerWordShield_Timer <= diff) + { + DoCast(me, SPELL_PWSHIELD); + PowerWordShield_Timer = 15000; + } else PowerWordShield_Timer -= diff; + + if (GreaterHeal_Timer <= diff) + { + Unit *pTarget = SelectGuestTarget(); + + DoCast(pTarget, SPELL_GREATERHEAL); + GreaterHeal_Timer = 17000; + } else GreaterHeal_Timer -= diff; + + if (HolyFire_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HOLYFIRE); + HolyFire_Timer = 22000; + } else HolyFire_Timer -= diff; + + if (DispelMagic_Timer <= diff) + { + if (Unit *pTarget = RAND(SelectGuestTarget(), SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))) + DoCast(pTarget, SPELL_DISPELMAGIC); + + DispelMagic_Timer = 25000; + } else DispelMagic_Timer -= diff; + } +}; + +#define SPELL_CLEANSE 29380 //Self or other guest+Moroes +#define SPELL_GREATERBLESSOFMIGHT 29381 //Self or other guest+Moroes +#define SPELL_HOLYLIGHT 29562 //Self or other guest+Moroes +#define SPELL_DIVINESHIELD 41367 + +struct boss_lady_keira_berrybuckAI : public boss_moroes_guestAI +{ + //Holy Pally + boss_lady_keira_berrybuckAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Cleanse_Timer; + uint32 GreaterBless_Timer; + uint32 HolyLight_Timer; + uint32 DivineShield_Timer; + + void Reset() + { + Cleanse_Timer = 13000; + GreaterBless_Timer = 1000; + HolyLight_Timer = 7000; + DivineShield_Timer = 31000; + + AcquireGUID(); + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (DivineShield_Timer <= diff) + { + DoCast(me, SPELL_DIVINESHIELD); + DivineShield_Timer = 31000; + } else DivineShield_Timer -= diff; + + if (HolyLight_Timer <= diff) + { + Unit *pTarget = SelectGuestTarget(); + + DoCast(pTarget, SPELL_HOLYLIGHT); + HolyLight_Timer = 10000; + } else HolyLight_Timer -= diff; + + if (GreaterBless_Timer <= diff) + { + Unit *pTarget = SelectGuestTarget(); + + DoCast(pTarget, SPELL_GREATERBLESSOFMIGHT); + + GreaterBless_Timer = 50000; + } else GreaterBless_Timer -= diff; + + if (Cleanse_Timer <= diff) + { + Unit *pTarget = SelectGuestTarget(); + + DoCast(pTarget, SPELL_CLEANSE); + + Cleanse_Timer = 10000; + } else Cleanse_Timer -= diff; + } +}; + +#define SPELL_HAMSTRING 9080 +#define SPELL_MORTALSTRIKE 29572 +#define SPELL_WHIRLWIND 29573 + +struct boss_lord_robin_darisAI : public boss_moroes_guestAI +{ + //Arms Warr + boss_lord_robin_darisAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Hamstring_Timer; + uint32 MortalStrike_Timer; + uint32 WhirlWind_Timer; + + void Reset() + { + Hamstring_Timer = 7000; + MortalStrike_Timer = 10000; + WhirlWind_Timer = 21000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (Hamstring_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + Hamstring_Timer = 12000; + } else Hamstring_Timer -= diff; + + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 18000; + } else MortalStrike_Timer -= diff; + + if (WhirlWind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + WhirlWind_Timer = 21000; + } else WhirlWind_Timer -= diff; + } +}; + +#define SPELL_DISARM 8379 +#define SPELL_HEROICSTRIKE 29567 +#define SPELL_SHIELDBASH 11972 +#define SPELL_SHIELDWALL 29390 + +struct boss_lord_crispin_ferenceAI : public boss_moroes_guestAI +{ + //Arms Warr + boss_lord_crispin_ferenceAI(Creature *c) : boss_moroes_guestAI(c) {} + + uint32 Disarm_Timer; + uint32 HeroicStrike_Timer; + uint32 ShieldBash_Timer; + uint32 ShieldWall_Timer; + + void Reset() + { + Disarm_Timer = 6000; + HeroicStrike_Timer = 10000; + ShieldBash_Timer = 8000; + ShieldWall_Timer = 4000; + + boss_moroes_guestAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_moroes_guestAI::UpdateAI(diff); + + if (Disarm_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DISARM); + Disarm_Timer = 12000; + } else Disarm_Timer -= diff; + + if (HeroicStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HEROICSTRIKE); + HeroicStrike_Timer = 10000; + } else HeroicStrike_Timer -= diff; + + if (ShieldBash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHIELDBASH); + ShieldBash_Timer = 13000; + } else ShieldBash_Timer -= diff; + + if (ShieldWall_Timer <= diff) + { + DoCast(me, SPELL_SHIELDWALL); + ShieldWall_Timer = 21000; + } else ShieldWall_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_moroes(Creature* pCreature) +{ + return new boss_moroesAI (pCreature); +} + +CreatureAI* GetAI_baroness_dorothea_millstipe(Creature* pCreature) +{ + return new boss_baroness_dorothea_millstipeAI (pCreature); +} + +CreatureAI* GetAI_baron_rafe_dreuger(Creature* pCreature) +{ + return new boss_baron_rafe_dreugerAI (pCreature); +} + +CreatureAI* GetAI_lady_catriona_von_indi(Creature* pCreature) +{ + return new boss_lady_catriona_von_indiAI (pCreature); +} + +CreatureAI* GetAI_lady_keira_berrybuck(Creature* pCreature) +{ + return new boss_lady_keira_berrybuckAI (pCreature); +} + +CreatureAI* GetAI_lord_robin_daris(Creature* pCreature) +{ + return new boss_lord_robin_darisAI (pCreature); +} + +CreatureAI* GetAI_lord_crispin_ference(Creature* pCreature) +{ + return new boss_lord_crispin_ferenceAI (pCreature); +} + +void AddSC_boss_moroes() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_moroes"; + newscript->GetAI = &GetAI_boss_moroes; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_baroness_dorothea_millstipe"; + newscript->GetAI = &GetAI_baroness_dorothea_millstipe; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_baron_rafe_dreuger"; + newscript->GetAI = &GetAI_baron_rafe_dreuger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lady_catriona_von_indi"; + newscript->GetAI = &GetAI_lady_catriona_von_indi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lady_keira_berrybuck"; + newscript->GetAI = &GetAI_lady_keira_berrybuck; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_robin_daris"; + newscript->GetAI = &GetAI_lord_robin_daris; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_crispin_ference"; + newscript->GetAI = &GetAI_lord_crispin_ference; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp new file mode 100644 index 00000000000..004f1902bfc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp @@ -0,0 +1,343 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Netherspite +SD%Complete: 90 +SDComment: Not sure about timing and portals placing +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define EMOTE_PHASE_PORTAL -1532089 +#define EMOTE_PHASE_BANISH -1532090 + +#define SPELL_NETHERBURN_AURA 30522 +#define SPELL_VOIDZONE 37063 +#define SPELL_NETHER_INFUSION 38688 +#define SPELL_NETHERBREATH 38523 +#define SPELL_BANISH_VISUAL 39833 +#define SPELL_BANISH_ROOT 42716 +#define SPELL_EMPOWERMENT 38549 +#define SPELL_NETHERSPITE_ROAR 38684 + +const float PortalCoord[3][3] = +{ + {-11195.353516, -1613.237183, 278.237258}, // Left side + {-11137.846680, -1685.607422, 278.239258}, // Right side + {-11094.493164, -1591.969238, 279.949188} // Back side +}; + +enum Netherspite_Portal{ + RED_PORTAL = 0, // Perseverence + GREEN_PORTAL = 1, // Serenity + BLUE_PORTAL = 2 // Dominance +}; + +const uint32 PortalID[3] = {17369, 17367, 17368}; +const uint32 PortalVisual[3] = {30487,30490,30491}; +const uint32 PortalBeam[3] = {30465,30464,30463}; +const uint32 PlayerBuff[3] = {30421,30422,30423}; +const uint32 NetherBuff[3] = {30466,30467,30468}; +const uint32 PlayerDebuff[3] = {38637,38638,38639}; + +struct boss_netherspiteAI : public ScriptedAI +{ + boss_netherspiteAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + + for (int i=0; i<3; ++i) + { + PortalGUID[i] = 0; + BeamTarget[i] = 0; + BeamerGUID[i] = 0; + } + // need core fix + for (int i=0; i<3; ++i) + { + if (SpellEntry *spell = (SpellEntry*)GetSpellStore()->LookupEntry(PlayerBuff[i])) + spell->AttributesEx |= SPELL_ATTR_EX_NEGATIVE; + } + } + + ScriptedInstance* pInstance; + + bool PortalPhase; + bool Berserk; + uint32 PhaseTimer; // timer for phase switching + uint32 VoidZoneTimer; + uint32 NetherInfusionTimer; // berserking timer + uint32 NetherbreathTimer; + uint32 EmpowermentTimer; + uint32 PortalTimer; // timer for beam checking + uint64 PortalGUID[3]; // guid's of portals + uint64 BeamerGUID[3]; // guid's of auxiliary beaming portals + uint64 BeamTarget[3]; // guid's of portals' current targets + + bool IsBetween(WorldObject* u1, WorldObject *pTarget, WorldObject* u2) // the in-line checker + { + if (!u1 || !u2 || !pTarget) + return false; + + float xn, yn, xp, yp, xh, yh; + xn = u1->GetPositionX(); + yn = u1->GetPositionY(); + xp = u2->GetPositionX(); + yp = u2->GetPositionY(); + xh = pTarget->GetPositionX(); + yh = pTarget->GetPositionY(); + + // check if target is between (not checking distance from the beam yet) + if (dist(xn,yn,xh,yh) >= dist(xn,yn,xp,yp) || dist(xp,yp,xh,yh) >= dist(xn,yn,xp,yp)) + return false; + // check distance from the beam + return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn,yn,xp,yp) < 1.5f); + } + + float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance + { + return sqrt((xa-xb)*(xa-xb) + (ya-yb)*(ya-yb)); + } + + void Reset() + { + Berserk = false; + NetherInfusionTimer = 540000; + VoidZoneTimer = 15000; + NetherbreathTimer = 3000; + + HandleDoors(true); + DestroyPortals(); + } + + void SummonPortals() + { + uint8 r = rand()%4; + uint8 pos[3]; + pos[RED_PORTAL] = (r%2 ? (r>1 ? 2: 1): 0); + pos[GREEN_PORTAL] = (r%2 ? 0: (r>1 ? 2: 1)); + pos[BLUE_PORTAL] = (r>1 ? 1: 2); // Blue Portal not on the left side (0) + + for (int i=0; i<3; ++i) + if (Creature *portal = me->SummonCreature(PortalID[i],PortalCoord[pos[i]][0],PortalCoord[pos[i]][1],PortalCoord[pos[i]][2],0,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + PortalGUID[i] = portal->GetGUID(); + portal->AddAura(PortalVisual[i], portal); + } + } + + void DestroyPortals() + { + for (int i=0; i<3; ++i) + { + if (Creature *portal = Unit::GetCreature(*me, PortalGUID[i])) + portal->DisappearAndDie(); + if (Creature *portal = Unit::GetCreature(*me, BeamerGUID[i])) + portal->DisappearAndDie(); + PortalGUID[i] = 0; + BeamTarget[i] = 0; + } + } + + void UpdatePortals() // Here we handle the beams' behavior + { + for (int j=0; j<3; ++j) // j = color + if (Creature *portal = Unit::GetCreature(*me, PortalGUID[j])) + { + // the one who's been casted upon before + Unit *current = Unit::GetUnit(*portal, BeamTarget[j]); + // temporary store for the best suitable beam reciever + Unit *pTarget = me; + + if (Map* map = me->GetMap()) + { + Map::PlayerList const& players = map->GetPlayers(); + + // get the best suitable target + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player* p = i->getSource(); + if (p && p->isAlive() // alive + && (!pTarget || pTarget->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best + && !p->HasAura(PlayerDebuff[j],0) // not exhausted + && !p->HasAura(PlayerBuff[(j+1)%3],0) // not on another beam + && !p->HasAura(PlayerBuff[(j+2)%3],0) + && IsBetween(me, p, portal)) // on the beam + pTarget = p; + } + } + // buff the target + if (pTarget->GetTypeId() == TYPEID_PLAYER) + pTarget->AddAura(PlayerBuff[j], pTarget); + else + pTarget->AddAura(NetherBuff[j], pTarget); + // cast visual beam on the chosen target if switched + // simple target switching isn't working -> using BeamerGUID to cast (workaround) + if (!current || pTarget != current) + { + BeamTarget[j] = pTarget->GetGUID(); + // remove currently beaming portal + if (Creature *beamer = Unit::GetCreature(*portal, BeamerGUID[j])) + { + beamer->CastSpell(pTarget, PortalBeam[j], false); + beamer->DisappearAndDie(); + BeamerGUID[j] = 0; + } + // create new one and start beaming on the target + if (Creature *beamer = portal->SummonCreature(PortalID[j],portal->GetPositionX(),portal->GetPositionY(),portal->GetPositionZ(),portal->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,60000)) + { + beamer->CastSpell(pTarget, PortalBeam[j], false); + BeamerGUID[j] = beamer->GetGUID(); + } + } + // aggro target if Red Beam + if (j == RED_PORTAL && me->getVictim() != pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + me->getThreatManager().addThreat(pTarget, 100000.0f+DoGetThreat(me->getVictim())); + } + } + + void SwitchToPortalPhase() + { + me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT); + me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL); + SummonPortals(); + PhaseTimer = 60000; + PortalPhase = true; + PortalTimer = 10000; + EmpowermentTimer = 10000; + DoScriptText(EMOTE_PHASE_PORTAL,me); + } + + void SwitchToBanishPhase() + { + me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT); + me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA); + DoCast(me, SPELL_BANISH_VISUAL, true); + DoCast(me, SPELL_BANISH_ROOT, true); + DestroyPortals(); + PhaseTimer = 30000; + PortalPhase = false; + DoScriptText(EMOTE_PHASE_BANISH,me); + + for (int i=0; i<3; ++i) + me->RemoveAurasDueToSpell(NetherBuff[i]); + } + + void HandleDoors(bool open) // Massive Door switcher + { + if (GameObject *Door = GameObject::GetGameObject(*me, pInstance ? pInstance->GetData64(DATA_GO_MASSIVE_DOOR) : 0)) + Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY); + } + + void Aggro(Unit * /*who*/) + { + HandleDoors(false); + SwitchToPortalPhase(); + } + + void JustDied(Unit* /*killer*/) + { + HandleDoors(true); + DestroyPortals(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Void Zone + if (VoidZoneTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,45,true),SPELL_VOIDZONE,true); + VoidZoneTimer = 15000; + } else VoidZoneTimer -= diff; + + // NetherInfusion Berserk + if (!Berserk && NetherInfusionTimer <= diff) + { + me->AddAura(SPELL_NETHER_INFUSION, me); + DoCast(me, SPELL_NETHERSPITE_ROAR); + Berserk = true; + } else NetherInfusionTimer -= diff; + + if (PortalPhase) // PORTAL PHASE + { + // Distribute beams and buffs + if (PortalTimer <= diff) + { + UpdatePortals(); + PortalTimer = 1000; + } else PortalTimer -= diff; + + // Empowerment & Nether Burn + if (EmpowermentTimer <= diff) + { + DoCast(me, SPELL_EMPOWERMENT); + me->AddAura(SPELL_NETHERBURN_AURA, me); + EmpowermentTimer = 90000; + } else EmpowermentTimer -= diff; + + if (PhaseTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + SwitchToBanishPhase(); + return; + } + } else PhaseTimer -= diff; + } + else // BANISH PHASE + { + // Netherbreath + if (NetherbreathTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,40,true)) + DoCast(pTarget, SPELL_NETHERBREATH); + NetherbreathTimer = urand(5000,7000); + } else NetherbreathTimer -= diff; + + if (PhaseTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + SwitchToPortalPhase(); + return; + } + } else PhaseTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_netherspite(Creature *pCreature) +{ + return new boss_netherspiteAI(pCreature); +} + +void AddSC_boss_netherspite() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_netherspite"; + newscript->GetAI = GetAI_boss_netherspite; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp new file mode 100644 index 00000000000..2e8b6f51317 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp @@ -0,0 +1,418 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Nightbane +SD%Complete: 80 +SDComment: SDComment: Timers may incorrect +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +//phase 1 +#define SPELL_BELLOWING_ROAR 39427 +#define SPELL_CHARRED_EARTH 30129 +#define SPELL_DISTRACTING_ASH 30130 +#define SPELL_SMOLDERING_BREATH 30210 +#define SPELL_TAIL_SWEEP 25653 +//phase 2 +#define SPELL_RAIN_OF_BONES 37098 +#define SPELL_SMOKING_BLAST 37057 +#define SPELL_FIREBALL_BARRAGE 30282 +#define SPELL_SEARING_CINDERS 30127 +#define SPELL_SUMMON_SKELETON 30170 + +#define EMOTE_SUMMON "An ancient being awakens in the distance..." +#define YELL_AGGRO "What fools! I shall bring a quick end to your suffering!" +#define YELL_FLY_PHASE "Miserable vermin. I shall exterminate you from the air!" +#define YELL_LAND_PHASE_1 "Enough! I shall land and crush you myself!" +#define YELL_LAND_PHASE_2 "Insects! Let me show you my strength up close!" +#define EMOTE_BREATH "takes a deep breath." + +float IntroWay[8][3] = +{ + {-11053.37,-1794.48,149}, + {-11141.07,-1841.40,125}, + {-11187.28,-1890.23,125}, + {-11189.20,-1931.25,125}, + {-11153.76,-1948.93,125}, + {-11128.73,-1929.75,125}, + {-11140 , -1915 ,122}, + {-11163 , -1903 ,91.473} +}; + +struct boss_nightbaneAI : public ScriptedAI +{ + boss_nightbaneAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = true; + } + + ScriptedInstance* pInstance; + + uint32 Phase; + + bool RainBones; + bool Skeletons; + + uint32 BellowingRoarTimer; + uint32 CharredEarthTimer; + uint32 DistractingAshTimer; + uint32 SmolderingBreathTimer; + uint32 TailSweepTimer; + uint32 RainofBonesTimer; + uint32 SmokingBlastTimer; + uint32 FireballBarrageTimer; + uint32 SearingCindersTimer; + + uint32 FlyCount; + uint32 FlyTimer; + + bool Intro; + bool Flying; + bool Movement; + + uint32 WaitTimer; + uint32 MovePhase; + + void Reset() + { + BellowingRoarTimer = 30000; + CharredEarthTimer = 15000; + DistractingAshTimer = 20000; + SmolderingBreathTimer = 10000; + TailSweepTimer = 12000; + RainofBonesTimer = 10000; + SmokingBlastTimer = 20000; + FireballBarrageTimer = 13000; + SearingCindersTimer = 14000; + WaitTimer = 1000; + + Phase =1; + FlyCount = 0; + MovePhase = 0; + + me->SetSpeed(MOVE_RUN, 2.0f); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->setActive(true); + + if (pInstance) + { + if (pInstance->GetData(TYPE_NIGHTBANE) == DONE || pInstance->GetData(TYPE_NIGHTBANE) == IN_PROGRESS) + me->DisappearAndDie(); + else + pInstance->SetData(TYPE_NIGHTBANE, NOT_STARTED); + } + + HandleTerraceDoors(true); + + Flying = false; + Movement = false; + + if (!Intro) + { + me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0); + me->GetMotionMaster()->MoveTargetedHome(); + } + } + + void HandleTerraceDoors(bool open) + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_1), open); + pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_2), open); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(TYPE_NIGHTBANE, IN_PROGRESS); + + HandleTerraceDoors(false); + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + } + + void AttackStart(Unit* who) + { + if (!Intro && !Flying) + ScriptedAI::AttackStart(who); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_NIGHTBANE, DONE); + + HandleTerraceDoors(true); + } + + void MoveInLineOfSight(Unit *who) + { + if (!Intro && !Flying) + ScriptedAI::MoveInLineOfSight(who); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (Intro) + { + if (id >= 8) + { + Intro = false; + me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0); + return; + } + + WaitTimer = 1; + } + + if (Flying) + { + if (id == 0) + { + me->MonsterTextEmote(EMOTE_BREATH, 0, true); + Flying = false; + Phase = 2; + return; + } + + if (id == 3) + { + MovePhase = 4; + WaitTimer = 1; + return; + } + + if (id == 8) + { + Flying = false; + Phase = 1; + Movement = true; + return; + } + + WaitTimer = 1; + } + } + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(me->getVictim()); + } + + void TakeOff() + { + me->MonsterYell(YELL_FLY_PHASE, LANG_UNIVERSAL, NULL); + + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + (*me).GetMotionMaster()->Clear(false); + (*me).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]); + + Flying = true; + + FlyTimer = urand(45000,60000); //timer wrong between 45 and 60 seconds + ++FlyCount; + + RainofBonesTimer = 5000; //timer wrong (maybe) + RainBones = false; + Skeletons = false; + } + + void UpdateAI(const uint32 diff) + { + /* The timer for this was never setup apparently, not sure if the code works properly: + if (WaitTimer <= diff) + { + if (Intro) + { + if (MovePhase >= 7) + { + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); + } + else + { + me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]); + ++MovePhase; + } + } + if (Flying) + { + if (MovePhase >= 7) + { + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); + } + else + { + me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]); + ++MovePhase; + } + } + + WaitTimer = 0; + } else WaitTimer -= diff; + */ + + if (!UpdateVictim()) + return; + + if (Flying) + return; + + // Phase 1 "GROUND FIGHT" + if (Phase == 1) + { + if (Movement) + { + DoStartMovement(me->getVictim()); + Movement = false; + } + + if (BellowingRoarTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); + BellowingRoarTimer = urand(30000,40000); + } else BellowingRoarTimer -= diff; + + if (SmolderingBreathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SMOLDERING_BREATH); + SmolderingBreathTimer = 20000; + } else SmolderingBreathTimer -= diff; + + if (CharredEarthTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CHARRED_EARTH); + CharredEarthTimer = 20000; + } else CharredEarthTimer -= diff; + + if (TailSweepTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (!me->HasInArc(M_PI, pTarget)) + DoCast(pTarget, SPELL_TAIL_SWEEP); + TailSweepTimer = 15000; + } else TailSweepTimer -= diff; + + if (SearingCindersTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SEARING_CINDERS); + SearingCindersTimer = 10000; + } else SearingCindersTimer -= diff; + + uint32 Prozent; + Prozent = (me->GetHealth()*100) / me->GetMaxHealth(); + + if (Prozent < 75 && FlyCount == 0) // first take off 75% + TakeOff(); + + if (Prozent < 50 && FlyCount == 1) // secound take off 50% + TakeOff(); + + if (Prozent < 25 && FlyCount == 2) // third take off 25% + TakeOff(); + + DoMeleeAttackIfReady(); + } + + //Phase 2 "FLYING FIGHT" + if (Phase == 2) + { + if (!RainBones) + { + if (!Skeletons) + { + for (uint8 i = 0; i <= 3; ++i) + { + DoCast(me->getVictim(), SPELL_SUMMON_SKELETON); + Skeletons = true; + } + } + + if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2 + { + DoCast(me->getVictim(), SPELL_RAIN_OF_BONES); + RainBones = true; + SmokingBlastTimer = 20000; + } else RainofBonesTimer -= diff; + + if (DistractingAshTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_DISTRACTING_ASH); + DistractingAshTimer = 2000; //timer wrong + } else DistractingAshTimer -= diff; + } + + if (RainBones) + { + if (SmokingBlastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SMOKING_BLAST); + SmokingBlastTimer = 1500; //timer wrong + } else SmokingBlastTimer -= diff; + } + + if (FireballBarrageTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_FARTHEST, 0)) + DoCast(pTarget, SPELL_FIREBALL_BARRAGE); + FireballBarrageTimer = 20000; + } else FireballBarrageTimer -= diff; + + if (FlyTimer <= diff) //landing + { + me->MonsterYell(RAND(*YELL_LAND_PHASE_1,*YELL_LAND_PHASE_2), LANG_UNIVERSAL, NULL); + + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MovePoint(3,IntroWay[3][0],IntroWay[3][1],IntroWay[3][2]); + + Flying = true; + } else FlyTimer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_nightbane(Creature* pCreature) +{ + return new boss_nightbaneAI (pCreature); +} + +void AddSC_boss_nightbane() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nightbane"; + newscript->GetAI = &GetAI_boss_nightbane; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp new file mode 100644 index 00000000000..1071eae78a0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp @@ -0,0 +1,604 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Prince_Malchezzar +SD%Complete: 100 +SDComment: +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define SAY_AGGRO -1532091 +#define SAY_AXE_TOSS1 -1532092 +#define SAY_AXE_TOSS2 -1532093 +#define SAY_SPECIAL1 -1532094 +#define SAY_SPECIAL2 -1532095 +#define SAY_SPECIAL3 -1532096 +#define SAY_SLAY1 -1532097 +#define SAY_SLAY2 -1532098 +#define SAY_SLAY3 -1532099 +#define SAY_SUMMON1 -1532100 +#define SAY_SUMMON2 -1532101 +#define SAY_DEATH -1532102 + +// 18 Coordinates for Infernal spawns +struct InfernalPoint +{ + float x,y; +}; + +#define INFERNAL_Z 275.5 + +static InfernalPoint InfernalPoints[] = +{ + {-10922.8, -1985.2}, + {-10916.2, -1996.2}, + {-10932.2, -2008.1}, + {-10948.8, -2022.1}, + {-10958.7, -1997.7}, + {-10971.5, -1997.5}, + {-10990.8, -1995.1}, + {-10989.8, -1976.5}, + {-10971.6, -1973.0}, + {-10955.5, -1974.0}, + {-10939.6, -1969.8}, + {-10958.0, -1952.2}, + {-10941.7, -1954.8}, + {-10943.1, -1988.5}, + {-10948.8, -2005.1}, + {-10984.0, -2019.3}, + {-10932.8, -1979.6}, + {-10935.7, -1996.0} +}; + +#define TOTAL_INFERNAL_POINTS 18 + +//Enfeeble is supposed to reduce hp to 1 and then heal player back to full when it ends +//Along with reducing healing and regen while enfeebled to 0% +//This spell effect will only reduce healing + +#define SPELL_ENFEEBLE 30843 //Enfeeble during phase 1 and 2 +#define SPELL_ENFEEBLE_EFFECT 41624 + +#define SPELL_SHADOWNOVA 30852 //Shadownova used during all phases +#define SPELL_SW_PAIN 30854 //Shadow word pain during phase 1 and 3 (different targeting rules though) +#define SPELL_THRASH_PASSIVE 12787 //Extra attack chance during phase 2 +#define SPELL_SUNDER_ARMOR 30901 //Sunder armor during phase 2 +#define SPELL_THRASH_AURA 12787 //Passive proc chance for thrash +#define SPELL_EQUIP_AXES 30857 //Visual for axe equiping +#define SPELL_AMPLIFY_DAMAGE 39095 //Amplifiy during phase 3 +#define SPELL_CLEAVE 30131 //Same as Nightbane. +#define SPELL_HELLFIRE 30859 //Infenals' hellfire aura +#define NETHERSPITE_INFERNAL 17646 //The netherspite infernal creature +#define MALCHEZARS_AXE 17650 //Malchezar's axes (creatures), summoned during phase 3 + +#define INFERNAL_MODEL_INVISIBLE 11686 //Infernal Effects +#define SPELL_INFERNAL_RELAY 30834 + +#define EQUIP_ID_AXE 33542 //Axes info + +//---------Infernal code first +struct netherspite_infernalAI : public ScriptedAI +{ + netherspite_infernalAI(Creature *c) : ScriptedAI(c) , + malchezaar(0), HellfireTimer(0), CleanupTimer(0), point(NULL) {} + + uint32 HellfireTimer; + uint32 CleanupTimer; + uint32 malchezaar; + InfernalPoint *point; + + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (HellfireTimer) + if (HellfireTimer <= diff) + { + DoCast(me, SPELL_HELLFIRE); + HellfireTimer = 0; + } + else HellfireTimer -= diff; + + if (CleanupTimer) + if (CleanupTimer <= diff) + { + Cleanup(); + CleanupTimer = 0; + } else CleanupTimer -= diff; + } + + void KilledUnit(Unit *who) + { + Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar); + if (pMalchezaar) + CAST_CRE(pMalchezaar)->AI()->KilledUnit(who); + } + + void SpellHit(Unit * /*who*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_INFERNAL_RELAY) + { + me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + HellfireTimer = 4000; + CleanupTimer = 170000; + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != malchezaar) + damage = 0; + } + + void Cleanup(); //below ... +}; + +struct boss_malchezaarAI : public ScriptedAI +{ + boss_malchezaarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 EnfeebleTimer; + uint32 EnfeebleResetTimer; + uint32 ShadowNovaTimer; + uint32 SWPainTimer; + uint32 SunderArmorTimer; + uint32 AmplifyDamageTimer; + uint32 Cleave_Timer; + uint32 InfernalTimer; + uint32 AxesTargetSwitchTimer; + uint32 InfernalCleanupTimer; + + std::vector infernals; + std::vector positions; + + uint64 axes[2]; + uint64 enfeeble_targets[5]; + uint64 enfeeble_health[5]; + + uint32 phase; + + void Reset() + { + AxesCleanup(); + ClearWeapons(); + InfernalCleanup(); + positions.clear(); + + for (uint8 i = 0; i < 5; ++i) + enfeeble_targets[i] = 0; + + for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i) + positions.push_back(&InfernalPoints[i]); + + EnfeebleTimer = 30000; + EnfeebleResetTimer = 38000; + ShadowNovaTimer = 35500; + SWPainTimer = 20000; + AmplifyDamageTimer = 5000; + Cleave_Timer = 8000; + InfernalTimer = 45000; + InfernalCleanupTimer = 47000; + AxesTargetSwitchTimer = urand(7500,20000); + SunderArmorTimer = urand(5000,10000); + phase = 1; + + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + AxesCleanup(); + ClearWeapons(); + InfernalCleanup(); + positions.clear(); + + for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i) + positions.push_back(&InfernalPoints[i]); + + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), false); // Open the door leading further in + } + + void InfernalCleanup() + { + //Infernal Cleanup + for (std::vector::const_iterator itr = infernals.begin(); itr != infernals.end(); ++itr) + if (Unit *pInfernal = Unit::GetUnit(*me, *itr)) + if (pInfernal->isAlive()) + { + pInfernal->SetVisibility(VISIBILITY_OFF); + pInfernal->setDeathState(JUST_DIED); + } + + infernals.clear(); + } + + void AxesCleanup() + { + for (uint8 i = 0; i < 2; ++i) + { + Unit *axe = Unit::GetUnit(*me, axes[i]); + if (axe && axe->isAlive()) + axe->Kill(axe); + axes[i] = 0; + } + } + + void ClearWeapons() + { + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + + //damage + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg); + me->UpdateDamagePhysical(BASE_ATTACK); + } + + void EnfeebleHealthEffect() + { + const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT); + if (!info) + return; + + std::list t_list = me->getThreatManager().getThreatList(); + std::vector targets; + + if (!t_list.size()) + return; + + //begin + 1, so we don't target the one with the highest threat + std::list::const_iterator itr = t_list.begin(); + std::advance(itr, 1); + for (; itr != t_list.end(); ++itr) //store the threat list in a different container + if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + if (pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + targets.push_back(pTarget); + + //cut down to size if we have more than 5 targets + while (targets.size() > 5) + targets.erase(targets.begin()+rand()%targets.size()); + + uint32 i = 0; + for (std::vector::const_iterator iter = targets.begin(); iter != targets.end(); ++iter, ++i) + if (Unit *pTarget = *iter) + { + enfeeble_targets[i] = pTarget->GetGUID(); + enfeeble_health[i] = pTarget->GetHealth(); + + pTarget->CastSpell(pTarget, SPELL_ENFEEBLE, true, 0, 0, me->GetGUID()); + pTarget->SetHealth(1); + } + } + + void EnfeebleResetHealth() + { + for (uint8 i = 0; i < 5; ++i) + { + Unit *pTarget = Unit::GetUnit(*me, enfeeble_targets[i]); + if (pTarget && pTarget->isAlive()) + pTarget->SetHealth(enfeeble_health[i]); + enfeeble_targets[i] = 0; + enfeeble_health[i] = 0; + } + } + + void SummonInfernal(const uint32 /*diff*/) + { + InfernalPoint *point = NULL; + Position pos; + if ((me->GetMapId() != 532) || positions.empty()) + me->GetRandomNearPosition(pos, 60); + else + { + std::vector::iterator itr = positions.begin()+rand()%positions.size(); + point = *itr; + positions.erase(itr); + pos.Relocate(point->x, point->y, INFERNAL_Z); + } + + Creature *Infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000); + + if (Infernal) + { + Infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE); + Infernal->setFaction(me->getFaction()); + if (point) + CAST_AI(netherspite_infernalAI, Infernal->AI())->point=point; + CAST_AI(netherspite_infernalAI, Infernal->AI())->malchezaar=me->GetGUID(); + + infernals.push_back(Infernal->GetGUID()); + DoCast(Infernal, SPELL_INFERNAL_RELAY); + } + + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (EnfeebleResetTimer && EnfeebleResetTimer <= diff) // Let's not forget to reset that + { + EnfeebleResetHealth(); + EnfeebleResetTimer = 0; + } else EnfeebleResetTimer -= diff; + + if (me->hasUnitState(UNIT_STAT_STUNNED)) // While shifting to phase 2 malchezaar stuns himself + return; + + if (me->GetUInt64Value(UNIT_FIELD_TARGET) != me->getVictim()->GetGUID()) + me->SetUInt64Value(UNIT_FIELD_TARGET, me->getVictim()->GetGUID()); + + if (phase == 1) + { + if ((me->GetHealth()*100) / me->GetMaxHealth() < 60) + { + me->InterruptNonMeleeSpells(false); + + phase = 2; + + //animation + DoCast(me, SPELL_EQUIP_AXES); + + //text + DoScriptText(SAY_AXE_TOSS1, me); + + //passive thrash aura + DoCast(me, SPELL_THRASH_AURA, true); + + //models + SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE); + + //damage + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg); + me->UpdateDamagePhysical(BASE_ATTACK); + + me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg); + me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg); + //Sigh, updating only works on main attack, do it manually .... + me->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg); + me->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg); + + me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100); + } + } + else if (phase == 2) + { + if ((me->GetHealth()*100) / me->GetMaxHealth() < 30) + { + InfernalTimer = 15000; + + phase = 3; + + ClearWeapons(); + + //remove thrash + me->RemoveAurasDueToSpell(SPELL_THRASH_AURA); + + DoScriptText(SAY_AXE_TOSS2, me); + + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + for (uint8 i = 0; i < 2; ++i) + { + Creature *axe = me->SummonCreature(MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + if (axe) + { + axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + axe->setFaction(me->getFaction()); + axes[i] = axe->GetGUID(); + if (pTarget) + { + axe->AI()->AttackStart(pTarget); + //axe->getThreatManager().tauntApply(pTarget); //Taunt Apply and fade out does not work properly + // So we'll use a hack to add a lot of threat to our target + axe->AddThreat(pTarget, 10000000.0f); + } + } + } + + if (ShadowNovaTimer > 35000) + ShadowNovaTimer = EnfeebleTimer + 5000; + + return; + } + + if (SunderArmorTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDER_ARMOR); + SunderArmorTimer = urand(10000,18000); + + } else SunderArmorTimer -= diff; + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = urand(6000,12000); + + } else Cleave_Timer -= diff; + } + else + { + if (AxesTargetSwitchTimer <= diff) + { + AxesTargetSwitchTimer = urand(7500,20000); + + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Unit *axe = Unit::GetUnit(*me, axes[i])) + { + if (axe->getVictim()) + DoModifyThreatPercent(axe->getVictim(), -100); + if (pTarget) + axe->AddThreat(pTarget, 1000000.0f); + //axe->getThreatManager().tauntFadeOut(axe->getVictim()); + //axe->getThreatManager().tauntApply(pTarget); + } + } + } + } else AxesTargetSwitchTimer -= diff; + + if (AmplifyDamageTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_AMPLIFY_DAMAGE); + AmplifyDamageTimer = urand(20000,30000); + } else AmplifyDamageTimer -= diff; + } + + //Time for global and double timers + if (InfernalTimer <= diff) + { + SummonInfernal(diff); + InfernalTimer = phase == 3 ? 14500 : 44500; // 15 secs in phase 3, 45 otherwise + } else InfernalTimer -= diff; + + if (ShadowNovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWNOVA); + ShadowNovaTimer = phase == 3 ? 31000 : uint32(-1); + } else ShadowNovaTimer -= diff; + + if (phase != 2) + { + if (SWPainTimer <= diff) + { + Unit *pTarget = NULL; + if (phase == 1) + pTarget = me->getVictim(); // the tank + else // anyone but the tank + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + + if (pTarget) + DoCast(pTarget, SPELL_SW_PAIN); + + SWPainTimer = 20000; + } else SWPainTimer -= diff; + } + + if (phase != 3) + { + if (EnfeebleTimer <= diff) + { + EnfeebleHealthEffect(); + EnfeebleTimer = 30000; + ShadowNovaTimer = 5000; + EnfeebleResetTimer = 9000; + } else EnfeebleTimer -= diff; + } + + if (phase == 2) + DoMeleeAttacksIfReady(); + else + DoMeleeAttackIfReady(); + } + + void DoMeleeAttacksIfReady() + { + if (me->IsWithinMeleeRange(me->getVictim()) && !me->IsNonMeleeSpellCasted(false)) + { + //Check for base attack + if (me->isAttackReady() && me->getVictim()) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + //Check for offhand attack + if (me->isAttackReady(OFF_ATTACK) && me->getVictim()) + { + me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK); + me->resetAttackTimer(OFF_ATTACK); + } + } + } + + void Cleanup(Creature *infernal, InfernalPoint *point) + { + for (std::vector::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr) + if (*itr == infernal->GetGUID()) + { + infernals.erase(itr); + break; + } + + positions.push_back(point); + } +}; + +void netherspite_infernalAI::Cleanup() +{ + Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar); + + if (pMalchezaar && pMalchezaar->isAlive()) + CAST_AI(boss_malchezaarAI, CAST_CRE(pMalchezaar)->AI())->Cleanup(me, point); +} + +CreatureAI* GetAI_netherspite_infernal(Creature* pCreature) +{ + return new netherspite_infernalAI (pCreature); +} + +CreatureAI* GetAI_boss_malchezaar(Creature* pCreature) +{ + return new boss_malchezaarAI (pCreature); +} + +void AddSC_boss_malchezaar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_malchezaar"; + newscript->GetAI = &GetAI_boss_malchezaar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "netherspite_infernal"; + newscript->GetAI = &GetAI_netherspite_infernal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp new file mode 100644 index 00000000000..394cff3ccc5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp @@ -0,0 +1,569 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shade_of_Aran +SD%Complete: 95 +SDComment: Flame wreath missing cast animation, mods won't triggere. +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedSimpleAI.h" +#include "karazhan.h" +#include "GameObject.h" + +#define SAY_AGGRO1 -1532073 +#define SAY_AGGRO2 -1532074 +#define SAY_AGGRO3 -1532075 +#define SAY_FLAMEWREATH1 -1532076 +#define SAY_FLAMEWREATH2 -1532077 +#define SAY_BLIZZARD1 -1532078 +#define SAY_BLIZZARD2 -1532079 +#define SAY_EXPLOSION1 -1532080 +#define SAY_EXPLOSION2 -1532081 +#define SAY_DRINK -1532082 //Low Mana / AoE Pyroblast +#define SAY_ELEMENTALS -1532083 +#define SAY_KILL1 -1532084 +#define SAY_KILL2 -1532085 +#define SAY_TIMEOVER -1532086 +#define SAY_DEATH -1532087 +#define SAY_ATIESH -1532088 //Atiesh is equipped by a raid member + +//Spells +#define SPELL_FROSTBOLT 29954 +#define SPELL_FIREBALL 29953 +#define SPELL_ARCMISSLE 29955 +#define SPELL_CHAINSOFICE 29991 +#define SPELL_DRAGONSBREATH 29964 +#define SPELL_MASSSLOW 30035 +#define SPELL_FLAME_WREATH 29946 +#define SPELL_AOE_CS 29961 +#define SPELL_PLAYERPULL 32265 +#define SPELL_AEXPLOSION 29973 +#define SPELL_MASS_POLY 29963 +#define SPELL_BLINK_CENTER 29967 +#define SPELL_ELEMENTALS 29962 +#define SPELL_CONJURE 29975 +#define SPELL_DRINK 30024 +#define SPELL_POTION 32453 +#define SPELL_AOE_PYROBLAST 29978 + +//Creature Spells +#define SPELL_CIRCULAR_BLIZZARD 29951 //29952 is the REAL circular blizzard that leaves persistant blizzards that last for 10 seconds +#define SPELL_WATERBOLT 31012 +#define SPELL_SHADOW_PYRO 29978 + +//Creatures +#define CREATURE_WATER_ELEMENTAL 17167 +#define CREATURE_SHADOW_OF_ARAN 18254 +#define CREATURE_ARAN_BLIZZARD 17161 + +enum SuperSpell +{ + SUPER_FLAME = 0, + SUPER_BLIZZARD, + SUPER_AE, +}; + +struct boss_aranAI : public ScriptedAI +{ + boss_aranAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 SecondarySpellTimer; + uint32 NormalCastTimer; + uint32 SuperCastTimer; + uint32 BerserkTimer; + uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering. + + uint8 LastSuperSpell; + + uint32 FlameWreathTimer; + uint32 FlameWreathCheckTime; + uint64 FlameWreathTarget[3]; + float FWTargPosX[3]; + float FWTargPosY[3]; + + uint32 CurrentNormalSpell; + uint32 ArcaneCooldown; + uint32 FireCooldown; + uint32 FrostCooldown; + + uint32 DrinkInturruptTimer; + + bool ElementalsSpawned; + bool Drinking; + bool DrinkInturrupted; + + void Reset() + { + SecondarySpellTimer = 5000; + NormalCastTimer = 0; + SuperCastTimer = 35000; + BerserkTimer = 720000; + CloseDoorTimer = 15000; + + LastSuperSpell = rand()%3; + + FlameWreathTimer = 0; + FlameWreathCheckTime = 0; + + CurrentNormalSpell = 0; + ArcaneCooldown = 0; + FireCooldown = 0; + FrostCooldown = 0; + + DrinkInturruptTimer = 10000; + + ElementalsSpawned = false; + Drinking = false; + DrinkInturrupted = false; + + if (pInstance) + { + // Not in progress + pInstance->SetData(TYPE_ARAN, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true); + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_ARAN, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + + if (pInstance) + { + pInstance->SetData(TYPE_ARAN, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false); + } + } + + void FlameWreathEffect() + { + std::vector targets; + std::list t_list = me->getThreatManager().getThreatList(); + + if (!t_list.size()) + return; + + //store the threat list in a different container + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //only on alive players + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + targets.push_back(pTarget); + } + + //cut down to size if we have more than 3 targets + while (targets.size() > 3) + targets.erase(targets.begin()+rand()%targets.size()); + + uint32 i = 0; + for (std::vector::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr) + { + if (*itr) + { + FlameWreathTarget[i] = (*itr)->GetGUID(); + FWTargPosX[i] = (*itr)->GetPositionX(); + FWTargPosY[i] = (*itr)->GetPositionY(); + DoCast((*itr), SPELL_FLAME_WREATH, true); + ++i; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (CloseDoorTimer) + { + if (CloseDoorTimer <= diff) + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false); + CloseDoorTimer = 0; + } + } else CloseDoorTimer -= diff; + } + + //Cooldowns for casts + if (ArcaneCooldown) + { + if (ArcaneCooldown >= diff) + ArcaneCooldown -= diff; + else ArcaneCooldown = 0; + } + + if (FireCooldown) + { + if (FireCooldown >= diff) + FireCooldown -= diff; + else FireCooldown = 0; + } + + if (FrostCooldown) + { + if (FrostCooldown >= diff) + FrostCooldown -= diff; + else FrostCooldown = 0; + } + + if (!Drinking && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA)) < 20) + { + Drinking = true; + me->InterruptNonMeleeSpells(false); + + DoScriptText(SAY_DRINK, me); + + if (!DrinkInturrupted) + { + DoCast(me, SPELL_MASS_POLY, true); + DoCast(me, SPELL_CONJURE, false); + DoCast(me, SPELL_DRINK, false); + me->SetStandState(UNIT_STAND_STATE_SIT); + DrinkInturruptTimer = 10000; + } + } + + //Drink Inturrupt + if (Drinking && DrinkInturrupted) + { + Drinking = false; + me->RemoveAurasDueToSpell(SPELL_DRINK); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)-32000); + DoCast(me, SPELL_POTION, false); + } + + //Drink Inturrupt Timer + if (Drinking && !DrinkInturrupted) + if (DrinkInturruptTimer >= diff) + DrinkInturruptTimer -= diff; + else + { + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_POTION, true); + DoCast(me, SPELL_AOE_PYROBLAST, false); + DrinkInturrupted = true; + Drinking = false; + } + + //Don't execute any more code if we are drinking + if (Drinking) + return; + + //Normal casts + if (NormalCastTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!pTarget) + return; + + uint32 Spells[3]; + uint8 AvailableSpells = 0; + + //Check for what spells are not on cooldown + if (!ArcaneCooldown) + { + Spells[AvailableSpells] = SPELL_ARCMISSLE; + ++AvailableSpells; + } + if (!FireCooldown) + { + Spells[AvailableSpells] = SPELL_FIREBALL; + ++AvailableSpells; + } + if (!FrostCooldown) + { + Spells[AvailableSpells] = SPELL_FROSTBOLT; + ++AvailableSpells; + } + + //If no available spells wait 1 second and try again + if (AvailableSpells) + { + CurrentNormalSpell = Spells[rand() % AvailableSpells]; + DoCast(pTarget, CurrentNormalSpell); + } + } + NormalCastTimer = 1000; + } else NormalCastTimer -= diff; + + if (SecondarySpellTimer <= diff) + { + switch (urand(0,1)) + { + case 0: + DoCast(me, SPELL_AOE_CS); + break; + case 1: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CHAINSOFICE); + break; + } + SecondarySpellTimer = urand(5000,20000); + } else SecondarySpellTimer -= diff; + + if (SuperCastTimer <= diff) + { + uint8 Available[2]; + + switch (LastSuperSpell) + { + case SUPER_AE: + Available[0] = SUPER_FLAME; + Available[1] = SUPER_BLIZZARD; + break; + case SUPER_FLAME: + Available[0] = SUPER_AE; + Available[1] = SUPER_BLIZZARD; + break; + case SUPER_BLIZZARD: + Available[0] = SUPER_FLAME; + Available[1] = SUPER_AE; + break; + } + + LastSuperSpell = Available[urand(0,1)]; + + switch (LastSuperSpell) + { + case SUPER_AE: + DoScriptText(RAND(SAY_EXPLOSION1,SAY_EXPLOSION2), me); + + DoCast(me, SPELL_BLINK_CENTER, true); + DoCast(me, SPELL_PLAYERPULL, true); + DoCast(me, SPELL_MASSSLOW, true); + DoCast(me, SPELL_AEXPLOSION, false); + break; + + case SUPER_FLAME: + DoScriptText(RAND(SAY_FLAMEWREATH1,SAY_FLAMEWREATH2), me); + + FlameWreathTimer = 20000; + FlameWreathCheckTime = 500; + + FlameWreathTarget[0] = 0; + FlameWreathTarget[1] = 0; + FlameWreathTarget[2] = 0; + + FlameWreathEffect(); + break; + + case SUPER_BLIZZARD: + DoScriptText(RAND(SAY_BLIZZARD1,SAY_BLIZZARD2), me); + + if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000)) + { + pSpawn->setFaction(me->getFaction()); + pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false); + } + break; + } + + SuperCastTimer = urand(35000,40000); + } else SuperCastTimer -= diff; + + if (!ElementalsSpawned && me->GetHealth()*100 / me->GetMaxHealth() < 40) + { + ElementalsSpawned = true; + + for (uint32 i = 0; i < 4; ++i) + { + if (Creature* pUnit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90000)) + { + pUnit->Attack(me->getVictim(), true); + pUnit->setFaction(me->getFaction()); + } + } + + DoScriptText(SAY_ELEMENTALS, me); + } + + if (BerserkTimer <= diff) + { + for (uint32 i = 0; i < 5; ++i) + { + if (Creature* pUnit = me->SummonCreature(CREATURE_SHADOW_OF_ARAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) + { + pUnit->Attack(me->getVictim(), true); + pUnit->setFaction(me->getFaction()); + } + } + + DoScriptText(SAY_TIMEOVER, me); + + BerserkTimer = 60000; + } else BerserkTimer -= diff; + + //Flame Wreath check + if (FlameWreathTimer) + { + if (FlameWreathTimer >= diff) + FlameWreathTimer -= diff; + else FlameWreathTimer = 0; + + if (FlameWreathCheckTime <= diff) + { + for (uint8 i = 0; i < 3; ++i) + { + if (!FlameWreathTarget[i]) + continue; + + Unit* pUnit = Unit::GetUnit(*me, FlameWreathTarget[i]); + if (pUnit && !pUnit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3)) + { + pUnit->CastSpell(pUnit, 20476, true, 0, 0, me->GetGUID()); + pUnit->CastSpell(pUnit, 11027, true); + FlameWreathTarget[i] = 0; + } + } + FlameWreathCheckTime = 500; + } else FlameWreathCheckTime -= diff; + } + + if (ArcaneCooldown && FireCooldown && FrostCooldown) + DoMeleeAttackIfReady(); + } + + void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) + { + if (!DrinkInturrupted && Drinking && damage) + DrinkInturrupted = true; + } + + void SpellHit(Unit* /*pAttacker*/, const SpellEntry* Spell) + { + //We only care about inturrupt effects and only if they are durring a spell currently being casted + if ((Spell->Effect[0] != SPELL_EFFECT_INTERRUPT_CAST && + Spell->Effect[1] != SPELL_EFFECT_INTERRUPT_CAST && + Spell->Effect[2] != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCasted(false)) + return; + + //Inturrupt effect + me->InterruptNonMeleeSpells(false); + + //Normally we would set the cooldown equal to the spell duration + //but we do not have access to the DurationStore + + switch (CurrentNormalSpell) + { + case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break; + case SPELL_FIREBALL: FireCooldown = 5000; break; + case SPELL_FROSTBOLT: FrostCooldown = 5000; break; + } + } +}; + +struct water_elementalAI : public ScriptedAI +{ + water_elementalAI(Creature *c) : ScriptedAI(c) {} + + uint32 CastTimer; + + void Reset() + { + CastTimer = 2000 + (rand()%3000); + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (CastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WATERBOLT); + CastTimer = urand(2000,5000); + } else CastTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_aran(Creature* pCreature) +{ + return new boss_aranAI (pCreature); +} + +CreatureAI* GetAI_water_elemental(Creature* pCreature) +{ + return new water_elementalAI (pCreature); +} + +// CONVERT TO ACID +CreatureAI* GetAI_shadow_of_aran(Creature* pCreature) +{ + outstring_log("TSCR: Convert simpleAI script for Creature Entry %u to ACID", pCreature->GetEntry()); + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_SHADOW_PYRO; + ai->Spell[0].Cooldown = 5000; + ai->Spell[0].First_Cast = 1000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->EnterEvadeMode(); + + return ai; +} + +void AddSC_boss_shade_of_aran() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shade_of_aran"; + newscript->GetAI = &GetAI_boss_aran; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadow_of_aran"; + newscript->GetAI = &GetAI_shadow_of_aran; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_aran_elemental"; + newscript->GetAI = &GetAI_water_elemental; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp new file mode 100644 index 00000000000..5305cc8d354 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp @@ -0,0 +1,417 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Terestian_Illhoof +SD%Complete: 95 +SDComment: Complete! Needs adjustments to use spell though. +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define SAY_SLAY1 -1532065 +#define SAY_SLAY2 -1532066 +#define SAY_DEATH -1532067 +#define SAY_AGGRO -1532068 +#define SAY_SACRIFICE1 -1532069 +#define SAY_SACRIFICE2 -1532070 +#define SAY_SUMMON1 -1532071 +#define SAY_SUMMON2 -1532072 + +#define SPELL_SUMMON_DEMONCHAINS 30120 // Summons demonic chains that maintain the ritual of sacrifice. +#define SPELL_DEMON_CHAINS 30206 // Instant - Visual Effect +#define SPELL_ENRAGE 23537 // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min. +#define SPELL_SHADOW_BOLT 30055 // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage. +#define SPELL_SACRIFICE 30115 // Teleports and adds the debuff +#define SPELL_BERSERK 32965 // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley. +#define SPELL_SUMMON_FIENDISIMP 30184 // Summons a Fiendish Imp. +#define SPELL_SUMMON_IMP 30066 // Summons Kil'rek + +#define SPELL_FIENDISH_PORTAL 30171 // Opens portal and summons Fiendish Portal, 2 sec cast +#define SPELL_FIENDISH_PORTAL_1 30179 // Opens portal and summons Fiendish Portal, instant cast + +#define SPELL_FIREBOLT 30050 // Blasts a target for 150 Fire damage. +#define SPELL_BROKEN_PACT 30065 // All damage taken increased by 25%. +#define SPELL_AMPLIFY_FLAMES 30053 // Increases the Fire damage taken by an enemy by 500 for 25 sec. + +#define CREATURE_DEMONCHAINS 17248 +#define CREATURE_FIENDISHIMP 17267 +#define CREATURE_PORTAL 17265 +#define CREATURE_KILREK 17229 + +struct mob_kilrekAI : public ScriptedAI +{ + mob_kilrekAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 TerestianGUID; + + uint32 AmplifyTimer; + + void Reset() + { + TerestianGUID = 0; + AmplifyTimer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + if (!pInstance) + { + ERROR_INST_DATA(me); + return; + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + uint64 TerestianGUID = pInstance->GetData64(DATA_TERESTIAN); + if (TerestianGUID) + { + Unit* Terestian = Unit::GetUnit((*me), TerestianGUID); + if (Terestian && Terestian->isAlive()) + DoCast(Terestian, SPELL_BROKEN_PACT, true); + } + } else ERROR_INST_DATA(me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (AmplifyTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES); + + AmplifyTimer = urand(10000,20000); + } else AmplifyTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_demon_chainAI : public ScriptedAI +{ + mob_demon_chainAI(Creature *c) : ScriptedAI(c) {} + + uint64 SacrificeGUID; + + void Reset() + { + SacrificeGUID = 0; + } + + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void JustDied(Unit * /*killer*/) + { + if (SacrificeGUID) + { + Unit* Sacrifice = Unit::GetUnit((*me),SacrificeGUID); + if (Sacrifice) + Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE); + } + } +}; + +struct mob_fiendish_portalAI : public PassiveAI +{ + mob_fiendish_portalAI(Creature *c) : PassiveAI(c),summons(me){} + + SummonList summons; + + void Reset() + { + summons.DespawnAll(); + } + + void JustSummoned(Creature* summon) + { + summons.Summon(summon); + DoZoneInCombat(summon); + } + + void DespawnAllImp() + { + summons.DespawnAll(); + } +}; + +struct boss_terestianAI : public ScriptedAI +{ + boss_terestianAI(Creature *c) : ScriptedAI(c) + { + for (uint8 i = 0; i < 2; ++i) + PortalGUID[i] = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint64 PortalGUID[2]; + uint8 PortalsCount; + + uint32 SacrificeTimer; + uint32 ShadowboltTimer; + uint32 SummonTimer; + uint32 BerserkTimer; + + bool SummonedPortals; + bool Berserk; + + void Reset() + { + for (uint8 i = 0; i < 2; ++i) + { + if (PortalGUID[i]) + { + if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[i])) + { + CAST_AI(mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp(); + pPortal->ForcedDespawn(); + } + + PortalGUID[i] = 0; + } + } + + PortalsCount = 0; + SacrificeTimer = 30000; + ShadowboltTimer = 5000; + SummonTimer = 10000; + BerserkTimer = 600000; + + SummonedPortals = false; + Berserk = false; + + if (pInstance) + pInstance->SetData(TYPE_TERESTIAN, NOT_STARTED); + + me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT); + + if (Minion* Kilrek = me->GetFirstMinion()) + { + if (!Kilrek->isAlive()) + { + Kilrek->UnSummon(); + DoCast(me, SPELL_SUMMON_IMP, true); + } + } + else DoCast(me, SPELL_SUMMON_IMP, true); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == CREATURE_PORTAL) + { + PortalGUID[PortalsCount] = pSummoned->GetGUID(); + ++PortalsCount; + + if (pSummoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1) + { + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + SummonedPortals = true; + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*killer*/) + { + for (uint8 i = 0; i < 2; ++i) + { + if (PortalGUID[i]) + { + if (Creature* pPortal = Unit::GetCreature((*me), PortalGUID[i])) + pPortal->ForcedDespawn(); + + PortalGUID[i] = 0; + } + } + + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_TERESTIAN, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (SacrificeTimer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + if (pTarget && pTarget->isAlive()) + { + DoCast(pTarget, SPELL_SACRIFICE, true); + DoCast(pTarget, SPELL_SUMMON_DEMONCHAINS, true); + + if (Creature* Chains = me->FindNearestCreature(CREATURE_DEMONCHAINS, 5000)) + { + CAST_AI(mob_demon_chainAI, Chains->AI())->SacrificeGUID = pTarget->GetGUID(); + Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true); + DoScriptText(RAND(SAY_SACRIFICE1,SAY_SACRIFICE2), me); + SacrificeTimer = 30000; + } + } + } else SacrificeTimer -= diff; + + if (ShadowboltTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT); + ShadowboltTimer = 10000; + } else ShadowboltTimer -= diff; + + if (SummonTimer <= diff) + { + if (!PortalGUID[0]) + DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL, false); + + if (!PortalGUID[1]) + DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL_1, false); + + if (PortalGUID[0] && PortalGUID[1]) + { + if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0,1)])) + pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false); + SummonTimer = 5000; + } + } else SummonTimer -= diff; + + if (!Berserk) + { + if (BerserkTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + Berserk = true; + } else BerserkTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_FIREBOLT 30050 // Blasts a target for 181-209 Fire damage. + +struct mob_fiendish_impAI : public ScriptedAI +{ + mob_fiendish_impAI(Creature *c) : ScriptedAI(c) {} + + uint32 FireboltTimer; + + void Reset() + { + FireboltTimer = 2000; + + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (FireboltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBOLT); + FireboltTimer = 2200; + } else FireboltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_kilrek(Creature* pCreature) +{ + return new mob_kilrekAI (pCreature); +} + +CreatureAI* GetAI_mob_fiendish_imp(Creature* pCreature) +{ + return new mob_fiendish_impAI (pCreature); +} + +CreatureAI* GetAI_mob_fiendish_portal(Creature* pCreature) +{ + return new mob_fiendish_portalAI (pCreature); +} + +CreatureAI* GetAI_boss_terestian_illhoof(Creature* pCreature) +{ + return new boss_terestianAI (pCreature); +} + +CreatureAI* GetAI_mob_demon_chain(Creature* pCreature) +{ + return new mob_demon_chainAI(pCreature); +} + +void AddSC_boss_terestian_illhoof() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_terestian_illhoof"; + newscript->GetAI = &GetAI_boss_terestian_illhoof; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fiendish_imp"; + newscript->GetAI = &GetAI_mob_fiendish_imp; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name= "mob_fiendish_portal"; + newscript->GetAI = &GetAI_mob_fiendish_portal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_kilrek"; + newscript->GetAI = &GetAI_mob_kilrek; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_demon_chain"; + newscript->GetAI = &GetAI_mob_demon_chain; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp new file mode 100644 index 00000000000..ae6de9c1add --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp @@ -0,0 +1,1494 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Bosses_Opera +SD%Complete: 90 +SDComment: Oz, Hood, and RAJ event implemented. RAJ event requires more testing. +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +/***********************************/ +/*** OPERA WIZARD OF OZ EVENT *****/ +/*********************************/ + +#define SAY_DOROTHEE_DEATH -1532025 +#define SAY_DOROTHEE_SUMMON -1532026 +#define SAY_DOROTHEE_TITO_DEATH -1532027 +#define SAY_DOROTHEE_AGGRO -1532028 + +#define SAY_ROAR_AGGRO -1532029 +#define SAY_ROAR_DEATH -1532030 +#define SAY_ROAR_SLAY -1532031 + +#define SAY_STRAWMAN_AGGRO -1532032 +#define SAY_STRAWMAN_DEATH -1532033 +#define SAY_STRAWMAN_SLAY -1532034 + +#define SAY_TINHEAD_AGGRO -1532035 +#define SAY_TINHEAD_DEATH -1532036 +#define SAY_TINHEAD_SLAY -1532037 +#define EMOTE_RUST -1532038 + +#define SAY_CRONE_AGGRO -1532039 +#define SAY_CRONE_AGGRO2 -1532040 +#define SAY_CRONE_DEATH -1532041 +#define SAY_CRONE_SLAY -1532042 + +/**** Spells ****/ +// Dorothee +#define SPELL_WATERBOLT 31012 +#define SPELL_SCREAM 31013 +#define SPELL_SUMMONTITO 31014 + +// Tito +#define SPELL_YIPPING 31015 + +// Strawman +#define SPELL_BRAIN_BASH 31046 +#define SPELL_BRAIN_WIPE 31069 +#define SPELL_BURNING_STRAW 31075 + +// Tinhead +#define SPELL_CLEAVE 31043 +#define SPELL_RUST 31086 + +// Roar +#define SPELL_MANGLE 31041 +#define SPELL_SHRED 31042 +#define SPELL_FRIGHTENED_SCREAM 31013 + +// Crone +#define SPELL_CHAIN_LIGHTNING 32337 + +// Cyclone +#define SPELL_KNOCKBACK 32334 +#define SPELL_CYCLONE_VISUAL 32332 + +/** Creature Entries **/ +#define CREATURE_TITO 17548 +#define CREATURE_CYCLONE 18412 +#define CREATURE_CRONE 18168 + +void SummonCroneIfReady(ScriptedInstance* pInstance, Creature* pCreature) +{ + pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, SPECIAL); // Increment DeathCount + + if (pInstance->GetData(DATA_OPERA_OZ_DEATHCOUNT) == 4) + { + if (Creature* pCrone = pCreature->SummonCreature(CREATURE_CRONE, -10891.96, -1755.95, pCreature->GetPositionZ(), 4.64, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) + { + if (pCreature->getVictim()) + pCrone->AI()->AttackStart(pCreature->getVictim()); + } + } +}; + +struct boss_dorotheeAI : public ScriptedAI +{ + boss_dorotheeAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + + uint32 WaterBoltTimer; + uint32 FearTimer; + uint32 SummonTitoTimer; + + bool SummonedTito; + bool TitoDied; + + void Reset() + { + AggroTimer = 500; + + WaterBoltTimer = 5000; + FearTimer = 15000; + SummonTitoTimer = 47500; + + SummonedTito = false; + TitoDied = false; + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_DOROTHEE_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void SummonTito(); // See below + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DOROTHEE_DEATH, me); + + if (pInstance) + SummonCroneIfReady(pInstance, me); + } + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + if (AggroTimer) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + } else AggroTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (WaterBoltTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_WATERBOLT); + WaterBoltTimer = TitoDied ? 1500 : 5000; + } else WaterBoltTimer -= diff; + + if (FearTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SCREAM); + FearTimer = 30000; + } else FearTimer -= diff; + + if (!SummonedTito) + { + if (SummonTitoTimer <= diff) + SummonTito(); + else SummonTitoTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_titoAI : public ScriptedAI +{ + mob_titoAI(Creature* c) : ScriptedAI(c) {} + + uint64 DorotheeGUID; + uint32 YipTimer; + + void Reset() + { + DorotheeGUID = 0; + YipTimer = 10000; + } + + void EnterCombat(Unit* /*who*/) {} + + void JustDied(Unit* /*killer*/) + { + if (DorotheeGUID) + { + Creature* Dorothee = (Unit::GetCreature((*me), DorotheeGUID)); + if (Dorothee && Dorothee->isAlive()) + { + CAST_AI(boss_dorotheeAI, Dorothee->AI())->TitoDied = true; + DoScriptText(SAY_DOROTHEE_TITO_DEATH, Dorothee); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (YipTimer <= diff) + { + DoCast(me->getVictim(), SPELL_YIPPING); + YipTimer = 10000; + } else YipTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void boss_dorotheeAI::SummonTito() +{ + if (Creature* pTito = me->SummonCreature(CREATURE_TITO, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + DoScriptText(SAY_DOROTHEE_SUMMON, me); + CAST_AI(mob_titoAI, pTito->AI())->DorotheeGUID = me->GetGUID(); + pTito->AI()->AttackStart(me->getVictim()); + SummonedTito = true; + TitoDied = false; + } +} + +struct boss_strawmanAI : public ScriptedAI +{ + boss_strawmanAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 BrainBashTimer; + uint32 BrainWipeTimer; + + void Reset() + { + AggroTimer = 13000; + BrainBashTimer = 5000; + BrainWipeTimer = 7000; + } + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_STRAWMAN_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry *Spell) + { + if ((Spell->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && (!(rand()%10))) + { + /* + if (not direct damage(aoe,dot)) + return; + */ + + DoCast(me, SPELL_BURNING_STRAW, true); + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_STRAWMAN_DEATH, me); + + if (pInstance) + SummonCroneIfReady(pInstance, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_STRAWMAN_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + if (AggroTimer) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + } else AggroTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (BrainBashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BRAIN_BASH); + BrainBashTimer = 15000; + } else BrainBashTimer -= diff; + + if (BrainWipeTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BRAIN_WIPE); + BrainWipeTimer = 20000; + } else BrainWipeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_tinheadAI : public ScriptedAI +{ + boss_tinheadAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 CleaveTimer; + uint32 RustTimer; + + uint8 RustCount; + + void Reset() + { + AggroTimer = 15000; + CleaveTimer = 5000; + RustTimer = 30000; + + RustCount = 0; + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_TINHEAD_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_TINHEAD_DEATH, me); + + if (pInstance) + SummonCroneIfReady(pInstance, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_TINHEAD_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + if (AggroTimer) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + } else AggroTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (CleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + CleaveTimer = 5000; + } else CleaveTimer -= diff; + + if (RustCount < 8) + { + if (RustTimer <= diff) + { + ++RustCount; + DoScriptText(EMOTE_RUST, me); + DoCast(me, SPELL_RUST); + RustTimer = 6000; + } else RustTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_roarAI : public ScriptedAI +{ + boss_roarAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AggroTimer; + uint32 MangleTimer; + uint32 ShredTimer; + uint32 ScreamTimer; + + void Reset() + { + AggroTimer = 20000; + MangleTimer = 5000; + ShredTimer = 10000; + ScreamTimer = 15000; + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_ROAR_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_ROAR_DEATH, me); + + if (pInstance) + SummonCroneIfReady(pInstance, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_ROAR_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + if (AggroTimer) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer = 0; + } else AggroTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (MangleTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MANGLE); + MangleTimer = urand(5000,8000); + } else MangleTimer -= diff; + + if (ShredTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHRED); + ShredTimer = urand(10000,15000); + } else ShredTimer -= diff; + + if (ScreamTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FRIGHTENED_SCREAM); + ScreamTimer = urand(20000,30000); + } else ScreamTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_croneAI : public ScriptedAI +{ + boss_croneAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 CycloneTimer; + uint32 ChainLightningTimer; + + void Reset() + { + CycloneTimer = 30000; + ChainLightningTimer = 10000; + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(RAND(SAY_CRONE_AGGRO,SAY_CRONE_AGGRO2), me); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_CRONE_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_OPERA, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); + + if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) + pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (CycloneTimer <= diff) + { + if (Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, urand(0,9), urand(0,9), 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000)) + Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_VISUAL, true); + CycloneTimer = 30000; + } else CycloneTimer -= diff; + + if (ChainLightningTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); + ChainLightningTimer = 15000; + } else ChainLightningTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_cycloneAI : public ScriptedAI +{ + mob_cycloneAI(Creature* c) : ScriptedAI(c) {} + + uint32 MoveTimer; + + void Reset() + { + MoveTimer = 1000; + } + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit* /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!me->HasAura(SPELL_KNOCKBACK)) + DoCast(me, SPELL_KNOCKBACK, true); + + if (MoveTimer <= diff) + { + Position pos; + me->GetRandomNearPosition(pos, 10); + me->GetMotionMaster()->MovePoint(0, pos); + MoveTimer = urand(5000,8000); + } else MoveTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_dorothee(Creature* pCreature) +{ + return new boss_dorotheeAI(pCreature); +} + +CreatureAI* GetAI_boss_strawman(Creature* pCreature) +{ + return new boss_strawmanAI(pCreature); +} + +CreatureAI* GetAI_boss_tinhead(Creature* pCreature) +{ + return new boss_tinheadAI(pCreature); +} + +CreatureAI* GetAI_boss_roar(Creature* pCreature) +{ + return new boss_roarAI(pCreature); +} + +CreatureAI* GetAI_boss_crone(Creature* pCreature) +{ + return new boss_croneAI(pCreature); +} + +CreatureAI* GetAI_mob_tito(Creature* pCreature) +{ + return new mob_titoAI(pCreature); +} + +CreatureAI* GetAI_mob_cyclone(Creature* pCreature) +{ + return new mob_cycloneAI(pCreature); +} + +/**************************************/ +/**** Opera Red Riding Hood Event ****/ +/************************************/ + +/**** Yells for the Wolf ****/ +#define SAY_WOLF_AGGRO -1532043 +#define SAY_WOLF_SLAY -1532044 +#define SAY_WOLF_HOOD -1532045 +#define SOUND_WOLF_DEATH 9275 //Only sound on death, no text. + +/**** Spells For The Wolf ****/ +#define SPELL_LITTLE_RED_RIDING_HOOD 30768 +#define SPELL_TERRIFYING_HOWL 30752 +#define SPELL_WIDE_SWIPE 30761 + +#define GOSSIP_GRANDMA "What phat lewtz you have grandmother?" + +/**** The Wolf's Entry ****/ +#define CREATURE_BIG_BAD_WOLF 17521 + +bool GossipHello_npc_grandmother(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GRANDMA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(8990, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_grandmother(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + if (Creature* pBigBadWolf = pCreature->SummonCreature(CREATURE_BIG_BAD_WOLF, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) + pBigBadWolf->AI()->AttackStart(pPlayer); + + pCreature->ForcedDespawn(); + } + + return true; +} + +struct boss_bigbadwolfAI : public ScriptedAI +{ + boss_bigbadwolfAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ChaseTimer; + uint32 FearTimer; + uint32 SwipeTimer; + + uint64 HoodGUID; + float TempThreat; + + bool IsChasing; + + void Reset() + { + ChaseTimer = 30000; + FearTimer = 25000 + rand()%10000; + SwipeTimer = 5000; + + HoodGUID = 0; + TempThreat = 0; + + IsChasing = false; + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_WOLF_AGGRO, me); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void JustDied(Unit* /*killer*/) + { + DoPlaySoundToSet(me, SOUND_WOLF_DEATH); + + if (pInstance) + { + pInstance->SetData(TYPE_OPERA, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); + + if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) + pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + + if (ChaseTimer <= diff) + { + if (!IsChasing) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(SAY_WOLF_HOOD, me); + DoCast(pTarget, SPELL_LITTLE_RED_RIDING_HOOD, true); + TempThreat = DoGetThreat(pTarget); + if (TempThreat) + DoModifyThreatPercent(pTarget, -100); + HoodGUID = pTarget->GetGUID(); + me->AddThreat(pTarget, 1000000.0f); + ChaseTimer = 20000; + IsChasing = true; + } + } + else + { + IsChasing = false; + + if (Unit *pTarget = Unit::GetUnit((*me), HoodGUID)) + { + HoodGUID = 0; + if (DoGetThreat(pTarget)) + DoModifyThreatPercent(pTarget, -100); + me->AddThreat(pTarget, TempThreat); + TempThreat = 0; + } + + ChaseTimer = 40000; + } + } else ChaseTimer -= diff; + + if (IsChasing) + return; + + if (FearTimer <= diff) + { + DoCast(me->getVictim(), SPELL_TERRIFYING_HOWL); + FearTimer = urand(25000,35000); + } else FearTimer -= diff; + + if (SwipeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WIDE_SWIPE); + SwipeTimer = urand(25000,30000); + } else SwipeTimer -= diff; + + } +}; + +CreatureAI* GetAI_boss_bigbadwolf(Creature* pCreature) +{ + return new boss_bigbadwolfAI(pCreature); +} + +/**********************************************/ +/******** Opera Romeo and Juliet Event *******/ +/********************************************/ + +/**** Speech *****/ +#define SAY_JULIANNE_AGGRO -1532046 +#define SAY_JULIANNE_ENTER -1532047 +#define SAY_JULIANNE_DEATH01 -1532048 +#define SAY_JULIANNE_DEATH02 -1532049 +#define SAY_JULIANNE_RESURRECT -1532050 +#define SAY_JULIANNE_SLAY -1532051 + +#define SAY_ROMULO_AGGRO -1532052 +#define SAY_ROMULO_DEATH -1532053 +#define SAY_ROMULO_ENTER -1532054 +#define SAY_ROMULO_RESURRECT -1532055 +#define SAY_ROMULO_SLAY -1532056 + +/***** Spells For Julianne *****/ +#define SPELL_BLINDING_PASSION 30890 +#define SPELL_DEVOTION 30887 +#define SPELL_ETERNAL_AFFECTION 30878 +#define SPELL_POWERFUL_ATTRACTION 30889 +#define SPELL_DRINK_POISON 30907 + +/***** Spells For Romulo ****/ +#define SPELL_BACKWARD_LUNGE 30815 +#define SPELL_DARING 30841 +#define SPELL_DEADLY_SWATHE 30817 +#define SPELL_POISON_THRUST 30822 + +/**** Other Misc. Spells ****/ +#define SPELL_UNDYING_LOVE 30951 +#define SPELL_RES_VISUAL 24171 + +/*** Misc. Information ****/ +#define CREATURE_ROMULO 17533 +#define ROMULO_X -10900 +#define ROMULO_Y -1758 + +enum RAJPhase +{ + PHASE_JULIANNE = 0, + PHASE_ROMULO = 1, + PHASE_BOTH = 2, +}; + +void PretendToDie(Creature* pCreature) +{ + pCreature->InterruptNonMeleeSpells(true); + pCreature->RemoveAllAuras(); + pCreature->SetHealth(0); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->GetMotionMaster()->MovementExpired(false); + pCreature->GetMotionMaster()->MoveIdle(); + pCreature->SetStandState(UNIT_STAND_STATE_DEAD); +}; + +void Resurrect(Creature *pTarget) +{ + pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTarget->SetHealth(pTarget->GetMaxHealth()); + pTarget->SetStandState(UNIT_STAND_STATE_STAND); + pTarget->CastSpell(pTarget, SPELL_RES_VISUAL, true); + if (pTarget->getVictim()) + { + pTarget->GetMotionMaster()->MoveChase(pTarget->getVictim()); + pTarget->AI()->AttackStart(pTarget->getVictim()); + } + else + pTarget->GetMotionMaster()->Initialize(); +}; + +struct boss_julianneAI : public ScriptedAI +{ + boss_julianneAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EntryYellTimer = 1000; + AggroYellTimer = 10000; + IsFakingDeath = false; + } + + ScriptedInstance* pInstance; + + uint32 EntryYellTimer; + uint32 AggroYellTimer; + + uint64 RomuloGUID; + + uint32 Phase; + + uint32 BlindingPassionTimer; + uint32 DevotionTimer; + uint32 EternalAffectionTimer; + uint32 PowerfulAttractionTimer; + uint32 SummonRomuloTimer; + uint32 ResurrectTimer; + uint32 DrinkPoisonTimer; + uint32 ResurrectSelfTimer; + + bool IsFakingDeath; + bool SummonedRomulo; + bool RomuloDead; + + void Reset() + { + RomuloGUID = 0; + Phase = PHASE_JULIANNE; + + BlindingPassionTimer = 30000; + DevotionTimer = 15000; + EternalAffectionTimer = 25000; + PowerfulAttractionTimer = 5000; + SummonRomuloTimer = 10000; + DrinkPoisonTimer = 0; + ResurrectSelfTimer = 0; + + if (IsFakingDeath) + { + Resurrect(me); + IsFakingDeath = false; + } + + SummonedRomulo = false; + RomuloDead = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void AttackStart(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry *Spell) + { + if (Spell->Id == SPELL_DRINK_POISON) + { + DoScriptText(SAY_JULIANNE_DEATH01, me); + DrinkPoisonTimer = 2500; + } + } + + void DamageTaken(Unit* done_by, uint32 &damage); + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_JULIANNE_DEATH02, me); + + if (pInstance) + { + pInstance->SetData(TYPE_OPERA, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); + if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) + pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_JULIANNE_SLAY, me); + } + + void UpdateAI(const uint32 diff); +}; + +struct boss_romuloAI : public ScriptedAI +{ + boss_romuloAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EntryYellTimer = 8000; + AggroYellTimer = 15000; + } + + ScriptedInstance* pInstance; + + uint64 JulianneGUID; + uint32 Phase; + + uint32 EntryYellTimer; + uint32 AggroYellTimer; + uint32 BackwardLungeTimer; + uint32 DaringTimer; + uint32 DeadlySwatheTimer; + uint32 PoisonThrustTimer; + uint32 ResurrectTimer; + + bool IsFakingDeath; + bool JulianneDead; + + void Reset() + { + JulianneGUID = 0; + Phase = PHASE_ROMULO; + + BackwardLungeTimer = 15000; + DaringTimer = 20000; + DeadlySwatheTimer = 25000; + PoisonThrustTimer = 10000; + ResurrectTimer = 10000; + + IsFakingDeath = false; + JulianneDead = false; + } + + void JustReachedHome() + { + me->ForcedDespawn(); + } + + void DamageTaken(Unit* done_by, uint32 &damage); + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_ROMULO_AGGRO, me); + if (JulianneGUID) + { + Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); + if (Julianne && Julianne->getVictim()) + { + me->AddThreat(Julianne->getVictim(), 1.0f); + AttackStart(Julianne->getVictim()); + } + } + } + + void MoveInLineOfSight(Unit* who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_ROMULO_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_OPERA, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); + + if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) + pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_ROMULO_SLAY, me); + } + + void UpdateAI(const uint32 diff); +}; + +void boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32 &damage) +{ + if (damage < me->GetHealth()) + return; + + //anything below only used if incoming damage will kill + + if (Phase == PHASE_JULIANNE) + { + damage = 0; + + //this means already drinking, so return + if (IsFakingDeath) + return; + + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_DRINK_POISON); + + IsFakingDeath = true; + //IS THIS USEFULL? Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); + return; + } + + if (Phase == PHASE_ROMULO) + { + error_log("TSCR: boss_julianneAI: cannot take damage in PHASE_ROMULO, why was i here?"); + damage = 0; + return; + } + + if (Phase == PHASE_BOTH) + { + //if this is true then we have to kill romulo too + if (RomuloDead) + { + if (Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID))) + { + Romulo->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Romulo->GetMotionMaster()->Clear(); + Romulo->setDeathState(JUST_DIED); + Romulo->CombatStop(true); + Romulo->DeleteThreatList(); + Romulo->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + return; + } + + //if not already returned, then romulo is alive and we can pretend die + if (Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID))) + { + PretendToDie(me); + IsFakingDeath = true; + CAST_AI(boss_romuloAI, Romulo->AI())->ResurrectTimer = 10000; + CAST_AI(boss_romuloAI, Romulo->AI())->JulianneDead = true; + damage = 0; + return; + } + } + error_log("TSCR: boss_julianneAI: DamageTaken reach end of code, that should not happen."); +} + +void boss_romuloAI::DamageTaken(Unit* /*done_by*/, uint32 &damage) +{ + if (damage < me->GetHealth()) + return; + + //anything below only used if incoming damage will kill + + if (Phase == PHASE_ROMULO) + { + DoScriptText(SAY_ROMULO_DEATH, me); + PretendToDie(me); + IsFakingDeath = true; + Phase = PHASE_BOTH; + + if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) + { + CAST_AI(boss_julianneAI, Julianne->AI())->RomuloDead = true; + CAST_AI(boss_julianneAI, Julianne->AI())->ResurrectSelfTimer = 10000; + } + + damage = 0; + return; + } + + if (Phase == PHASE_BOTH) + { + if (JulianneDead) + { + if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) + { + Julianne->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Julianne->GetMotionMaster()->Clear(); + Julianne->setDeathState(JUST_DIED); + Julianne->CombatStop(true); + Julianne->DeleteThreatList(); + Julianne->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + return; + } + + if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) + { + PretendToDie(me); + IsFakingDeath = true; + CAST_AI(boss_julianneAI, Julianne->AI())->ResurrectTimer = 10000; + CAST_AI(boss_julianneAI, Julianne->AI())->RomuloDead = true; + damage = 0; + return; + } + } + + error_log("TSCR: boss_romuloAI: DamageTaken reach end of code, that should not happen."); +} + +void boss_julianneAI::UpdateAI(const uint32 diff) +{ + if (EntryYellTimer) + { + if (EntryYellTimer <= diff) + { + DoScriptText(SAY_JULIANNE_ENTER, me); + EntryYellTimer = 0; + } else EntryYellTimer -= diff; + } + + if (AggroYellTimer) + { + if (AggroYellTimer <= diff) + { + DoScriptText(SAY_JULIANNE_AGGRO, me); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->setFaction(16); + AggroYellTimer = 0; + } else AggroYellTimer -= diff; + } + + if (DrinkPoisonTimer) + { + //will do this 2secs after spell hit. this is time to display visual as expected + if (DrinkPoisonTimer <= diff) + { + PretendToDie(me); + Phase = PHASE_ROMULO; + SummonRomuloTimer = 10000; + DrinkPoisonTimer = 0; + } else DrinkPoisonTimer -= diff; + } + + if (Phase == PHASE_ROMULO && !SummonedRomulo) + { + if (SummonRomuloTimer <= diff) + { + if (Creature* pRomulo = me->SummonCreature(CREATURE_ROMULO, ROMULO_X, ROMULO_Y, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) + { + RomuloGUID = pRomulo->GetGUID(); + CAST_AI(boss_romuloAI, pRomulo->AI())->JulianneGUID = me->GetGUID(); + CAST_AI(boss_romuloAI, pRomulo->AI())->Phase = PHASE_ROMULO; + DoZoneInCombat(pRomulo); + + pRomulo->setFaction(16); + } + SummonedRomulo = true; + } else SummonRomuloTimer -= diff; + } + + if (ResurrectSelfTimer) + { + if (ResurrectSelfTimer <= diff) + { + Resurrect(me); + Phase = PHASE_BOTH; + IsFakingDeath = false; + + if (me->getVictim()) + AttackStart(me->getVictim()); + + ResurrectSelfTimer = 0; + ResurrectTimer = 1000; + } else ResurrectSelfTimer -= diff; + } + + if (!UpdateVictim() || IsFakingDeath) + return; + + if (RomuloDead) + { + if (ResurrectTimer <= diff) + { + Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID)); + if (Romulo && CAST_AI(boss_romuloAI, Romulo->AI())->IsFakingDeath) + { + DoScriptText(SAY_JULIANNE_RESURRECT, me); + Resurrect(Romulo); + CAST_AI(boss_romuloAI, Romulo->AI())->IsFakingDeath = false; + RomuloDead = false; + ResurrectTimer = 10000; + } + } else ResurrectTimer -= diff; + } + + if (BlindingPassionTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BLINDING_PASSION); + BlindingPassionTimer = urand(30000,45000); + } else BlindingPassionTimer -= diff; + + if (DevotionTimer <= diff) + { + DoCast(me, SPELL_DEVOTION); + DevotionTimer = urand(15000,45000); + } else DevotionTimer -= diff; + + if (PowerfulAttractionTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_POWERFUL_ATTRACTION); + PowerfulAttractionTimer = urand(5000,30000); + } else PowerfulAttractionTimer -= diff; + + if (EternalAffectionTimer <= diff) + { + if (urand(0,1) && SummonedRomulo) + { + Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID)); + if (Romulo && Romulo->isAlive() && !RomuloDead) + DoCast(Romulo, SPELL_ETERNAL_AFFECTION); + } else DoCast(me, SPELL_ETERNAL_AFFECTION); + + EternalAffectionTimer = urand(45000,60000); + } else EternalAffectionTimer -= diff; + + DoMeleeAttackIfReady(); +} + +void boss_romuloAI::UpdateAI(const uint32 diff) +{ + if (!UpdateVictim() || IsFakingDeath) + return; + + if (JulianneDead) + { + if (ResurrectTimer <= diff) + { + Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); + if (Julianne && CAST_AI(boss_julianneAI, Julianne->AI())->IsFakingDeath) + { + DoScriptText(SAY_ROMULO_RESURRECT, me); + Resurrect(Julianne); + CAST_AI(boss_julianneAI, Julianne->AI())->IsFakingDeath = false; + JulianneDead = false; + ResurrectTimer = 10000; + } + } else ResurrectTimer -= diff; + } + + if (BackwardLungeTimer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + if (pTarget && !me->HasInArc(M_PI, pTarget)) + { + DoCast(pTarget, SPELL_BACKWARD_LUNGE); + BackwardLungeTimer = urand(15000,30000); + } + } else BackwardLungeTimer -= diff; + + if (DaringTimer <= diff) + { + DoCast(me, SPELL_DARING); + DaringTimer = urand(20000,40000); + } else DaringTimer -= diff; + + if (DeadlySwatheTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_DEADLY_SWATHE); + DeadlySwatheTimer = urand(15000,25000); + } else DeadlySwatheTimer -= diff; + + if (PoisonThrustTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_THRUST); + PoisonThrustTimer = urand(10000,20000); + } else PoisonThrustTimer -= diff; + + DoMeleeAttackIfReady(); +} + +CreatureAI* GetAI_boss_julianne(Creature* pCreature) +{ + return new boss_julianneAI(pCreature); +} + +CreatureAI* GetAI_boss_romulo(Creature* pCreature) +{ + return new boss_romuloAI(pCreature); +} + +void AddSC_bosses_opera() +{ + Script* newscript; + + // Oz + newscript = new Script; + newscript->GetAI = &GetAI_boss_dorothee; + newscript->Name = "boss_dorothee"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_strawman; + newscript->Name = "boss_strawman"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_tinhead; + newscript->Name = "boss_tinhead"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_roar; + newscript->Name = "boss_roar"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_crone; + newscript->Name = "boss_crone"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_tito; + newscript->Name = "mob_tito"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_cyclone; + newscript->Name = "mob_cyclone"; + newscript->RegisterSelf(); + + // Hood + newscript = new Script; + newscript->pGossipHello = &GossipHello_npc_grandmother; + newscript->pGossipSelect = &GossipSelect_npc_grandmother; + newscript->Name = "npc_grandmother"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_bigbadwolf; + newscript->Name = "boss_bigbadwolf"; + newscript->RegisterSelf(); + + // Romeo And Juliet + newscript = new Script; + newscript->GetAI = &GetAI_boss_julianne; + newscript->Name = "boss_julianne"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_romulo; + newscript->Name = "boss_romulo"; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp new file mode 100644 index 00000000000..59c1236bcdc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp @@ -0,0 +1,308 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Karazhan +SD%Complete: 70 +SDComment: Instance Script for Karazhan to help in various encounters. TODO: GameObject visibility for Opera event. +SDCategory: Karazhan +EndScriptData */ + +#include "ScriptedPch.h" +#include "karazhan.h" + +#define MAX_ENCOUNTER 12 + +/* +0 - Attumen + Midnight (optional) +1 - Moroes +2 - Maiden of Virtue (optional) +3 - Hyakiss the Lurker / Rokad the Ravager / Shadikith the Glider +4 - Opera Event +5 - Curator +6 - Shade of Aran (optional) +7 - Terestian Illhoof (optional) +8 - Netherspite (optional) +9 - Chess Event +10 - Prince Malchezzar +11 - Nightbane +*/ + +struct instance_karazhan : public ScriptedInstance +{ + instance_karazhan(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string strSaveData; + + uint32 m_uiOperaEvent; + uint32 m_uiOzDeathCount; + + uint64 m_uiCurtainGUID; + uint64 m_uiStageDoorLeftGUID; + uint64 m_uiStageDoorRightGUID; + uint64 m_uiKilrekGUID; + uint64 m_uiTerestianGUID; + uint64 m_uiMoroesGUID; + uint64 m_uiLibraryDoor; // Door at Shade of Aran + uint64 m_uiMassiveDoor; // Door at Netherspite + uint64 m_uiSideEntranceDoor; // Side Entrance + uint64 m_uiGamesmansDoor; // Door before Chess + uint64 m_uiGamesmansExitDoor; // Door after Chess + uint64 m_uiNetherspaceDoor; // Door at Malchezaar + uint64 MastersTerraceDoor[2]; + uint64 ImageGUID; + uint64 DustCoveredChest; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + // 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered. + m_uiOperaEvent = urand(1,3); + m_uiOzDeathCount = 0; + + m_uiCurtainGUID = 0; + m_uiStageDoorLeftGUID = 0; + m_uiStageDoorRightGUID = 0; + + m_uiKilrekGUID = 0; + m_uiTerestianGUID = 0; + m_uiMoroesGUID = 0; + + m_uiLibraryDoor = 0; + m_uiMassiveDoor = 0; + m_uiSideEntranceDoor = 0; + m_uiGamesmansDoor = 0; + m_uiGamesmansExitDoor = 0; + m_uiNetherspaceDoor = 0; + MastersTerraceDoor[0]= 0; + MastersTerraceDoor[1]= 0; + ImageGUID = 0; + DustCoveredChest = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case 17229: m_uiKilrekGUID = pCreature->GetGUID(); break; + case 15688: m_uiTerestianGUID = pCreature->GetGUID(); break; + case 15687: m_uiMoroesGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 uiData) + { + switch (type) + { + case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break; + case TYPE_MOROES: + if (m_auiEncounter[1] == DONE) + break; + m_auiEncounter[1] = uiData; + break; + case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break; + case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break; + case TYPE_OPERA: m_auiEncounter[4] = uiData; break; + case TYPE_CURATOR: m_auiEncounter[5] = uiData; break; + case TYPE_ARAN: m_auiEncounter[6] = uiData; break; + case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break; + case TYPE_NETHERSPITE: m_auiEncounter[8] = uiData; break; + case TYPE_CHESS: + if (uiData == DONE) + DoRespawnGameObject(DustCoveredChest,DAY); + m_auiEncounter[9] = uiData; + break; + case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break; + case TYPE_NIGHTBANE: + if (m_auiEncounter[11] != DONE) + m_auiEncounter[11] = uiData; + break; + case DATA_OPERA_OZ_DEATHCOUNT: + if (uiData == SPECIAL) + ++m_uiOzDeathCount; + else if (uiData == IN_PROGRESS) + m_uiOzDeathCount = 0; + break; + } + + if (uiData == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " + << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11]; + + strSaveData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + void SetData64(uint32 identifier, uint64 data) + { + switch(identifier) + { + case DATA_IMAGE_OF_MEDIVH: ImageGUID = data; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 183932: m_uiCurtainGUID = pGo->GetGUID(); break; + case 184278: + m_uiStageDoorLeftGUID = pGo->GetGUID(); + if (m_auiEncounter[4] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case 184279: + m_uiStageDoorRightGUID = pGo->GetGUID(); + if (m_auiEncounter[4] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case 184517: m_uiLibraryDoor = pGo->GetGUID(); break; + case 185521: m_uiMassiveDoor = pGo->GetGUID(); break; + case 184276: m_uiGamesmansDoor = pGo->GetGUID(); break; + case 184277: m_uiGamesmansExitDoor = pGo->GetGUID(); break; + case 185134: m_uiNetherspaceDoor = pGo->GetGUID(); break; + case 184274: MastersTerraceDoor[0] = pGo->GetGUID(); break; + case 184280: MastersTerraceDoor[1] = pGo->GetGUID(); break; + case 184275: + m_uiSideEntranceDoor = pGo->GetGUID(); + if (m_auiEncounter[4] == DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + else + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + break; + case 185119: DustCoveredChest = pGo->GetGUID(); break; + } + + switch(m_uiOperaEvent) + { + //TODO: Set Object visibilities for Opera based on performance + case EVENT_OZ: + break; + + case EVENT_HOOD: + break; + + case EVENT_RAJ: + break; + } + } + + std::string GetSaveData() + { + return strSaveData; + } + + uint32 GetData(uint32 uiData) + { + switch (uiData) + { + case TYPE_ATTUMEN: return m_auiEncounter[0]; + case TYPE_MOROES: return m_auiEncounter[1]; + case TYPE_MAIDEN: return m_auiEncounter[2]; + case TYPE_OPTIONAL_BOSS: return m_auiEncounter[3]; + case TYPE_OPERA: return m_auiEncounter[4]; + case TYPE_CURATOR: return m_auiEncounter[5]; + case TYPE_ARAN: return m_auiEncounter[6]; + case TYPE_TERESTIAN: return m_auiEncounter[7]; + case TYPE_NETHERSPITE: return m_auiEncounter[8]; + case TYPE_CHESS: return m_auiEncounter[9]; + case TYPE_MALCHEZZAR: return m_auiEncounter[10]; + case TYPE_NIGHTBANE: return m_auiEncounter[11]; + case DATA_OPERA_PERFORMANCE: return m_uiOperaEvent; + case DATA_OPERA_OZ_DEATHCOUNT: return m_uiOzDeathCount; + case DATA_IMAGE_OF_MEDIVH: return ImageGUID; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch (uiData) + { + case DATA_KILREK: return m_uiKilrekGUID; + case DATA_TERESTIAN: return m_uiTerestianGUID; + case DATA_MOROES: return m_uiMoroesGUID; + case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID; + case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID; + case DATA_GO_CURTAINS: return m_uiCurtainGUID; + case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor; + case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor; + case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor; + case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor; + case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor; + case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor; + case DATA_MASTERS_TERRACE_DOOR_1: return MastersTerraceDoor[0]; + case DATA_MASTERS_TERRACE_DOOR_2: return MastersTerraceDoor[1]; + } + + return 0; + } + + void Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + std::istringstream loadStream(chrIn); + + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] + >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_karazhan(Map* pMap) +{ + return new instance_karazhan(pMap); +} + +void AddSC_instance_karazhan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_karazhan"; + newscript->GetInstanceData = &GetInstanceData_instance_karazhan; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp new file mode 100644 index 00000000000..5186a794b0d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp @@ -0,0 +1,646 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Karazhan +SD%Complete: 100 +SDComment: Support for Barnes (Opera controller) and Berthold (Doorman), Support for Quest 9645. +SDCategory: Karazhan +EndScriptData */ + +/* ContentData +npc_barnes +npc_berthold +npc_image_of_medivh +EndContentData */ + +#include "ScriptedPch.h" +#include "karazhan.h" +#include "ScriptedEscortAI.h" + +/*###### +# npc_barnesAI +######*/ + +#define GOSSIP_READY "I'm not an actor." + +#define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!" +#define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?" +#define OZ_GOSSIP1 "I'm not an actor." +#define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!" +#define OZ_GOSSIP2 "Ok, I'll give it a try, then." + +#define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?" +#define RAJ_GOSSIP1 "I've never been more ready." + +#define OZ_GM_GOSSIP1 "[GM] Change event to EVENT_OZ" +#define OZ_GM_GOSSIP2 "[GM] Change event to EVENT_HOOD" +#define OZ_GM_GOSSIP3 "[GM] Change event to EVENT_RAJ" + +struct Dialogue +{ + int32 textid; + uint32 timer; +}; + +static Dialogue OzDialogue[]= +{ + {-1532103, 6000}, + {-1532104, 18000}, + {-1532105, 9000}, + {-1532106, 15000} +}; + +static Dialogue HoodDialogue[]= +{ + {-1532107, 6000}, + {-1532108, 10000}, + {-1532109, 14000}, + {-1532110, 15000} +}; + +static Dialogue RAJDialogue[]= +{ + {-1532111, 5000}, + {-1532112, 7000}, + {-1532113, 14000}, + {-1532114, 14000} +}; + +// Entries and spawn locations for creatures in Oz event +float Spawns[6][2]= +{ + {17535, -10896}, // Dorothee + {17546, -10891}, // Roar + {17547, -10884}, // Tinhead + {17543, -10902}, // Strawman + {17603, -10892}, // Grandmother + {17534, -10900}, // Julianne +}; + +#define CREATURE_SPOTLIGHT 19525 + +#define SPELL_SPOTLIGHT 25824 +#define SPELL_TUXEDO 32616 + +#define SPAWN_Z 90.5 +#define SPAWN_Y -1758 +#define SPAWN_O 4.738 + +struct npc_barnesAI : public npc_escortAI +{ + npc_barnesAI(Creature* c) : npc_escortAI(c) + { + RaidWiped = false; + m_uiEventId = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 m_uiSpotlightGUID; + + uint32 TalkCount; + uint32 TalkTimer; + uint32 WipeTimer; + uint32 m_uiEventId; + + bool PerformanceReady; + bool RaidWiped; + + void Reset() + { + m_uiSpotlightGUID = 0; + + TalkCount = 0; + TalkTimer = 2000; + WipeTimer = 5000; + + PerformanceReady = false; + + if (pInstance) + m_uiEventId = pInstance->GetData(DATA_OPERA_PERFORMANCE); + } + + void StartEvent() + { + if (!pInstance) + return; + + pInstance->SetData(TYPE_OPERA, IN_PROGRESS); + + //resets count for this event, in case earlier failed + if (m_uiEventId == EVENT_OZ) + pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS); + + Start(false, false); + } + + void EnterCombat(Unit* /*who*/) {} + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch(i) + { + case 0: + DoCast(me, SPELL_TUXEDO, false); + pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT)); + break; + case 4: + TalkCount = 0; + SetEscortPaused(true); + + if (Creature* pSpotlight = me->SummonCreature(CREATURE_SPOTLIGHT, + me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f, + TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000)) + { + pSpotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pSpotlight->CastSpell(pSpotlight, SPELL_SPOTLIGHT, false); + m_uiSpotlightGUID = pSpotlight->GetGUID(); + } + break; + case 8: + pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT)); + PerformanceReady = true; + break; + case 9: + PrepareEncounter(); + pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_CURTAINS)); + break; + } + } + + void Talk(uint32 count) + { + int32 text = 0; + + switch(m_uiEventId) + { + case EVENT_OZ: + if (OzDialogue[count].textid) + text = OzDialogue[count].textid; + if (OzDialogue[count].timer) + TalkTimer = OzDialogue[count].timer; + break; + + case EVENT_HOOD: + if (HoodDialogue[count].textid) + text = HoodDialogue[count].textid; + if (HoodDialogue[count].timer) + TalkTimer = HoodDialogue[count].timer; + break; + + case EVENT_RAJ: + if (RAJDialogue[count].textid) + text = RAJDialogue[count].textid; + if (RAJDialogue[count].timer) + TalkTimer = RAJDialogue[count].timer; + break; + } + + if (text) + DoScriptText(text, me); + } + + void PrepareEncounter() + { + debug_log("TSCR: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId); + uint8 index = 0; + uint8 count = 0; + + switch(m_uiEventId) + { + case EVENT_OZ: + index = 0; + count = 4; + break; + case EVENT_HOOD: + index = 4; + count = index+1; + break; + case EVENT_RAJ: + index = 5; + count = index+1; + break; + } + + for (; index < count; ++index) + { + uint32 entry = ((uint32)Spawns[index][0]); + float PosX = Spawns[index][1]; + + if (Creature* pCreature = me->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) + { + // In case database has bad flags + pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + RaidWiped = false; + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (HasEscortState(STATE_ESCORT_PAUSED)) + { + if (TalkTimer <= diff) + { + if (TalkCount > 3) + { + if (Creature* pSpotlight = Unit::GetCreature(*me, m_uiSpotlightGUID)) + pSpotlight->ForcedDespawn(); + + SetEscortPaused(false); + return; + } + + Talk(TalkCount); + ++TalkCount; + } else TalkTimer -= diff; + } + + if (PerformanceReady) + { + if (!RaidWiped) + { + if (WipeTimer <= diff) + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) + return; + + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (PlayerList.isEmpty()) + return; + + RaidWiped = true; + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && !i->getSource()->isGameMaster()) + { + RaidWiped = false; + break; + } + } + + if (RaidWiped) + { + RaidWiped = true; + EnterEvadeMode(); + return; + } + + WipeTimer = 15000; + } else WipeTimer -= diff; + } + + } + } +}; + +CreatureAI* GetAI_npc_barnesAI(Creature* pCreature) +{ + return new npc_barnesAI(pCreature); +} + +bool GossipHello_npc_barnes(Player* pPlayer, Creature* pCreature) +{ + if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) + { + // Check for death of Moroes and if opera event is not done already + if (pInstance->GetData(TYPE_MOROES) == DONE && pInstance->GetData(TYPE_OPERA) != DONE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (pPlayer->isGameMaster()) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + } + + if (npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI,pCreature->AI())) + { + if (!pBarnesAI->RaidWiped) + pPlayer->SEND_GOSSIP_MENU(8970, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(8975, pCreature->GetGUID()); + + return true; + } + } + } + + pPlayer->SEND_GOSSIP_MENU(8978, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_barnes(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI, pCreature->AI()); + + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(8971, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + pBarnesAI->StartEvent(); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + pBarnesAI->m_uiEventId = EVENT_OZ; + outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_OZ",pPlayer->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pBarnesAI->m_uiEventId = EVENT_HOOD; + outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_HOOD",pPlayer->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pBarnesAI->m_uiEventId = EVENT_RAJ; + outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_RAJ",pPlayer->GetGUID()); + break; + } + + return true; +} + +/*### +# npc_berthold +####*/ + +enum eBerthold +{ + SPELL_TELEPORT = 39567 +}; + +#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library" + +bool GossipHello_npc_berthold(Player* pPlayer, Creature* pCreature) +{ + if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) + { + // Check if Shade of Aran event is done + if (pInstance->GetData(TYPE_ARAN) == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_berthold(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, true); + + pPlayer->CLOSE_GOSSIP_MENU(); + return true; +} + +/*### +# npc_image_of_medivh +####*/ + +#define SAY_DIALOG_MEDIVH_1 "You've got my attention, dragon. You'll find I'm not as easily scared as the villagers below." +#define SAY_DIALOG_ARCANAGOS_2 "Your dabbling in the arcane has gone too far, Medivh. You've attracted the attention of powers beyond your understanding. You must leave Karazhan at once!" +#define SAY_DIALOG_MEDIVH_3 "You dare challenge me at my own dwelling? Your arrogance is astounding, even for a dragon!" +#define SAY_DIALOG_ARCANAGOS_4 "A dark power seeks to use you, Medivh! If you stay, dire days will follow. You must hurry, we don't have much time!" +#define SAY_DIALOG_MEDIVH_5 "I do not know what you speak of, dragon... but I will not be bullied by this display of insolence. I'll leave Karazhan when it suits me!" +#define SAY_DIALOG_ARCANAGOS_6 "You leave me no alternative. I will stop you by force if you won't listen to reason!" +#define EMOTE_DIALOG_MEDIVH_7 "begins to cast a spell of great power, weaving his own essence into the magic." +#define SAY_DIALOG_ARCANAGOS_8 "What have you done, wizard? This cannot be! I'm burning from... within!" +#define SAY_DIALOG_MEDIVH_9 "He should not have angered me. I must go... recover my strength now..." + +#define MOB_ARCANAGOS 17652 +#define SPELL_FIRE_BALL 30967 +#define SPELL_UBER_FIREBALL 30971 +#define SPELL_CONFLAGRATION_BLAST 30977 +#define SPELL_MANA_SHIELD 31635 + +static float MedivPos[4] = {-11161.49,-1902.24,91.48,1.94}; +static float ArcanagosPos[4] = {-11169.75,-1881.48,95.39,4.83}; + +struct npc_image_of_medivhAI : public ScriptedAI +{ + npc_image_of_medivhAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint64 ArcanagosGUID; + + uint32 YellTimer; + uint32 Step; + uint32 FireMedivhTimer; + uint32 FireArcanagosTimer; + + bool EventStarted; + + void Reset() + { + ArcanagosGUID = 0; + + if (pInstance && pInstance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0) + { + pInstance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID()); + (*me).GetMotionMaster()->MovePoint(1,MedivPos[0],MedivPos[1],MedivPos[2]); + Step = 0; + }else + { + me->DealDamage(me,me->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + } + } + void EnterCombat(Unit* /*who*/) {} + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + if (id == 1) + { + StartEvent(); + me->SetOrientation(MedivPos[3]); + me->SetOrientation(MedivPos[3]); + } + } + + void StartEvent() + { + Step = 1; + EventStarted = true; + Creature* Arcanagos = me->SummonCreature(MOB_ARCANAGOS,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + if (!Arcanagos) + return; + ArcanagosGUID = Arcanagos->GetGUID(); + Arcanagos->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + (*Arcanagos).GetMotionMaster()->MovePoint(0,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2]); + Arcanagos->SetOrientation(ArcanagosPos[3]); + me->SetOrientation(MedivPos[3]); + YellTimer = 10000; + } + + uint32 NextStep(uint32 Step) + { + Unit* arca = Unit::GetUnit((*me),ArcanagosGUID); + Map* pMap = me->GetMap(); + switch(Step) + { + case 0: return 9999999; + case 1: + me->MonsterYell(SAY_DIALOG_MEDIVH_1,LANG_UNIVERSAL,NULL); + return 10000; + case 2: + if (arca) + CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_2,LANG_UNIVERSAL,NULL); + return 20000; + case 3: + me->MonsterYell(SAY_DIALOG_MEDIVH_3,LANG_UNIVERSAL,NULL); + return 10000; + case 4: + if (arca) + CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, NULL); + return 20000; + case 5: + me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, NULL); + return 20000; + case 6: + if (arca) + CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, NULL); + return 10000; + case 7: + FireArcanagosTimer = 500; + return 5000; + case 8: + FireMedivhTimer = 500; + DoCast(me, SPELL_MANA_SHIELD); + return 10000; + case 9: + me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false); + return 10000; + case 10: + if (arca) + DoCast(arca, SPELL_CONFLAGRATION_BLAST, false); + return 1000; + case 11: + if (arca) + CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL); + return 5000; + case 12: + arca->GetMotionMaster()->MovePoint(0, -11010.82,-1761.18, 156.47); + arca->setActive(true); + arca->InterruptNonMeleeSpells(true); + arca->SetSpeed(MOVE_FLIGHT, 2.0f); + return 10000; + case 13: + me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL); + return 10000; + case 14: + me->SetVisibility(VISIBILITY_OFF); + me->ClearInCombat(); + + if (pMap->IsDungeon()) + { + InstanceMap::PlayerList const &PlayerList = pMap->GetPlayers(); + for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive()) + { + if (i->getSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE) + i->getSource()->CompleteQuest(9645); + } + } + } + return 50000; + case 15: + arca->DealDamage(arca,arca->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return 5000; + default : return 9999999; + } + + } + + void UpdateAI(const uint32 diff) + { + + if (YellTimer <= diff) + { + if (EventStarted) + YellTimer = NextStep(Step++); + } else YellTimer -= diff; + + if (Step >= 7 && Step <= 12) + { + Unit* arca = Unit::GetUnit((*me),ArcanagosGUID); + + if (FireArcanagosTimer <= diff) + { + if (arca) + arca->CastSpell(me, SPELL_FIRE_BALL, false); + FireArcanagosTimer = 6000; + } else FireArcanagosTimer -= diff; + + if (FireMedivhTimer <= diff) + { + if (arca) + DoCast(arca, SPELL_FIRE_BALL); + FireMedivhTimer = 5000; + } else FireMedivhTimer -= diff; + } + } +}; + +CreatureAI* GetAI_npc_image_of_medivh(Creature* pCreature) +{ + return new npc_image_of_medivhAI(pCreature); +} + +void AddSC_karazhan() +{ + Script* newscript; + + newscript = new Script; + newscript->GetAI = &GetAI_npc_barnesAI; + newscript->Name = "npc_barnes"; + newscript->pGossipHello = &GossipHello_npc_barnes; + newscript->pGossipSelect = &GossipSelect_npc_barnes; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_berthold"; + newscript->pGossipHello = &GossipHello_npc_berthold; + newscript->pGossipSelect = &GossipSelect_npc_berthold; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_image_of_medivh"; + newscript->GetAI = &GetAI_npc_image_of_medivh; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h new file mode 100644 index 00000000000..56a6b106332 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_KARAZHAN_H +#define DEF_KARAZHAN_H + +enum eEnums +{ + TYPE_ATTUMEN = 1, + TYPE_MOROES = 2, + TYPE_MAIDEN = 3, + TYPE_OPTIONAL_BOSS = 4, + TYPE_OPERA = 5, + TYPE_CURATOR = 6, + TYPE_ARAN = 7, + TYPE_TERESTIAN = 8, + TYPE_NETHERSPITE = 9, + TYPE_CHESS = 10, + TYPE_MALCHEZZAR = 11, + TYPE_NIGHTBANE = 12, + + DATA_OPERA_PERFORMANCE = 13, + DATA_OPERA_OZ_DEATHCOUNT = 14, + + DATA_KILREK = 15, + DATA_TERESTIAN = 16, + DATA_MOROES = 17, + DATA_GO_CURTAINS = 18, + DATA_GO_STAGEDOORLEFT = 19, + DATA_GO_STAGEDOORRIGHT = 20, + DATA_GO_LIBRARY_DOOR = 21, + DATA_GO_MASSIVE_DOOR = 22, + DATA_GO_NETHER_DOOR = 23, + DATA_GO_GAME_DOOR = 24, + DATA_GO_GAME_EXIT_DOOR = 25, + + DATA_IMAGE_OF_MEDIVH = 26, + DATA_MASTERS_TERRACE_DOOR_1 = 27, + DATA_MASTERS_TERRACE_DOOR_2 = 28, + DATA_GO_SIDE_ENTRANCE_DOOR = 29 +}; + +enum OperaEvents +{ + EVENT_OZ = 1, + EVENT_HOOD = 2, + EVENT_RAJ = 3 +}; + +#define ERROR_INST_DATA(a) error_log("TSCR: Instance Data for Karazhan not set properly. Encounter for Creature Entry %u may not work properly.", a->GetEntry()); +#endif + diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp new file mode 100644 index 00000000000..b5835dfe0a1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -0,0 +1,680 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Felblood_Kaelthas +SD%Complete: 80 +SDComment: Normal and Heroic Support. Issues: Arcane Spheres do not initially follow targets. +SDCategory: Magisters' Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" +#include "WorldPacket.h" + +#define SAY_AGGRO -1585023 //This yell should be done when the room is cleared. For now, set it as a movelineofsight yell. +#define SAY_PHOENIX -1585024 +#define SAY_FLAMESTRIKE -1585025 +#define SAY_GRAVITY_LAPSE -1585026 +#define SAY_TIRED -1585027 +#define SAY_RECAST_GRAVITY -1585028 +#define SAY_DEATH -1585029 + +/*** Spells ***/ + +// Phase 1 spells +#define SPELL_FIREBALL_NORMAL 44189 // Deals 2700-3300 damage at current target +#define SPELL_FIREBALL_HEROIC 46164 // 4950-6050 + +#define SPELL_PHOENIX 44194 // Summons a phoenix (Doesn't work?) +#define SPELL_PHOENIX_BURN 44197 // A spell Phoenix uses to damage everything around +#define SPELL_REBIRTH_DMG 44196 // DMG if a Phoenix rebirth happen + +#define SPELL_FLAMESTRIKE1_NORMAL 44190 // Damage part +#define SPELL_FLAMESTRIKE1_HEROIC 46163 // Heroic damage part +#define SPELL_FLAMESTRIKE2 44191 // Flamestrike indicator before the damage +#define SPELL_FLAMESTRIKE3 44192 // Summons the trigger + animation (projectile) + +#define SPELL_SHOCK_BARRIER 46165 // Heroic only; 10k damage shield, followed by Pyroblast +#define SPELL_PYROBLAST 36819 // Heroic only; 45-55k fire damage + +// Phase 2 spells +#define SPELL_GRAVITY_LAPSE_INITIAL 44224 // Cast at the beginning of every Gravity Lapse +#define SPELL_GRAVITY_LAPSE_CHANNEL 44251 // Channeled; blue beam animation to every enemy in range +#define SPELL_TELEPORT_CENTER 44218 // Should teleport people to the center. Requires DB entry in spell_target_position. +#define SPELL_GRAVITY_LAPSE_FLY 44227 // Hastens flyspeed and allows flying for 1 minute. For some reason removes 44226. +#define SPELL_GRAVITY_LAPSE_DOT 44226 // Knocks up in the air and applies a 300 DPS DoT. +#define SPELL_ARCANE_SPHERE_PASSIVE 44263 // Passive auras on Arcane Spheres +#define SPELL_POWER_FEEDBACK 44233 // Stuns him, making him take 50% more damage for 10 seconds. Cast after Gravity Lapse + +/*** Creatures ***/ +#define CREATURE_PHOENIX 24674 +#define CREATURE_PHOENIX_EGG 24675 +#define CREATURE_ARCANE_SPHERE 24708 + +/** Locations **/ +float KaelLocations[3][2]= +{ + {148.744659, 181.377426}, + {140.823883, 195.403046}, + {156.574188, 195.650482}, +}; + +#define LOCATION_Z -16.727455 + +struct boss_felblood_kaelthasAI : public ScriptedAI +{ + boss_felblood_kaelthasAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 FireballTimer; + uint32 PhoenixTimer; + uint32 FlameStrikeTimer; + uint32 CombatPulseTimer; + + //Heroic only + uint32 PyroblastTimer; + + uint32 GravityLapseTimer; + uint32 GravityLapsePhase; + // 0 = No Gravity Lapse + // 1 = Casting Gravity Lapse visual + // 2 = Teleported people to self + // 3 = Knocked people up in the air + // 4 = Applied an aura that allows them to fly, channeling visual, relased Arcane Orbs. + + bool FirstGravityLapse; + bool HasTaunted; + + uint8 Phase; + // 0 = Not started + // 1 = Fireball; Summon Phoenix; Flamestrike + // 2 = Gravity Lapses + + void Reset() + { + // TODO: Timers + FireballTimer = 0; + PhoenixTimer = 10000; + FlameStrikeTimer = 25000; + CombatPulseTimer = 0; + + PyroblastTimer = 60000; + + GravityLapseTimer = 0; + GravityLapsePhase = 0; + + FirstGravityLapse = true; + HasTaunted = false; + + Phase = 0; + + if (pInstance) + { + pInstance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), true); + // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here) + // Small door opened after event are expected to be closed by default + } + } + + void JustDied(Unit * /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), true); + // Open the encounter door + } + + void DamageTaken(Unit* /*done_by*/, uint32 &damage) + { + if (damage > me->GetHealth()) + RemoveGravityLapse(); // Remove Gravity Lapse so that players fall to ground if they kill him when in air. + } + + void EnterCombat(Unit * /*who*/) + { + if (!pInstance) + return; + + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), false); + //Close the encounter door, open it in JustDied/Reset + } + + void MoveInLineOfSight(Unit *who) + { + if (!HasTaunted && me->IsWithinDistInMap(who, 40.0)) + { + DoScriptText(SAY_AGGRO, me); + HasTaunted = true; + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void SetThreatList(Creature* SummonedUnit) + { + if (!SummonedUnit) + return; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + std::list::const_iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + { + float threat = me->getThreatManager().getThreat(pUnit); + SummonedUnit->AddThreat(pUnit, threat); + } + } + } + + void TeleportPlayersToSelf() + { + float x = KaelLocations[0][0]; + float y = KaelLocations[0][1]; + me->GetMap()->CreatureRelocation(me, x, y, LOCATION_Z, 0.0f); + //me->SendMonsterMove(x, y, LOCATION_Z, 0, 0, 0); // causes some issues... + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + pUnit->CastSpell(pUnit, SPELL_TELEPORT_CENTER, true); + } + DoCast(me, SPELL_TELEPORT_CENTER, true); + } + + void CastGravityLapseKnockUp() + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + // Knockback into the air + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, me->GetGUID()); + } + } + + void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + // Also needs an exception in spell system. + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, me->GetGUID()); + // Use packet hack + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + } + + void RemoveGravityLapse() + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); + pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); + + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + switch(Phase) + { + case 0: + { + // *Heroic mode only: + if (IsHeroic()) + { + if (PyroblastTimer <= diff) + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + DoCast(me, SPELL_SHOCK_BARRIER, true); + DoCast(me->getVictim(), SPELL_PYROBLAST); + PyroblastTimer = 60000; + } else PyroblastTimer -= diff; + } + + if (FireballTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL_NORMAL); + FireballTimer = urand(2000,6000); + } else FireballTimer -= diff; + + if (PhoenixTimer <= diff) + { + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + + uint8 random = urand(1,2); + float x = KaelLocations[random][0]; + float y = KaelLocations[random][1]; + + Creature* Phoenix = me->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + if (Phoenix) + { + Phoenix->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + SetThreatList(Phoenix); + Phoenix->AI()->AttackStart(pTarget); + } + + DoScriptText(SAY_PHOENIX, me); + + PhoenixTimer = 60000; + } else PhoenixTimer -= diff; + + if (FlameStrikeTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + DoCast(pTarget, SPELL_FLAMESTRIKE3, true); + DoScriptText(SAY_FLAMESTRIKE, me); + } + FlameStrikeTimer = urand(15000,25000); + } else FlameStrikeTimer -= diff; + + // Below 50% + if (me->GetMaxHealth() * 0.5 > me->GetHealth()) + { + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + GravityLapseTimer = 0; + GravityLapsePhase = 0; + Phase = 1; + } + + DoMeleeAttackIfReady(); + } + break; + + case 1: + { + if (GravityLapseTimer <= diff) + { + switch(GravityLapsePhase) + { + case 0: + if (FirstGravityLapse) // Different yells at 50%, and at every following Gravity Lapse + { + DoScriptText(SAY_GRAVITY_LAPSE, me); + FirstGravityLapse = false; + + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_STATUE_LEFT), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_STATUE_RIGHT), true); + } + }else + { + DoScriptText(SAY_RECAST_GRAVITY, me); + } + + DoCast(me, SPELL_GRAVITY_LAPSE_INITIAL); + GravityLapseTimer = 2000 + diff;// Don't interrupt the visual spell + GravityLapsePhase = 1; + break; + + case 1: + TeleportPlayersToSelf(); + GravityLapseTimer = 1000; + GravityLapsePhase = 2; + break; + + case 2: + CastGravityLapseKnockUp(); + GravityLapseTimer = 1000; + GravityLapsePhase = 3; + break; + + case 3: + CastGravityLapseFly(); + GravityLapseTimer = 30000; + GravityLapsePhase = 4; + + for (uint8 i = 0; i < 3; ++i) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); + if (Orb && pTarget) + { + Orb->SetSpeed(MOVE_RUN, 0.5f); + Orb->AddThreat(pTarget, 1000000.0f); + Orb->AI()->AttackStart(pTarget); + } + + } + + DoCast(me, SPELL_GRAVITY_LAPSE_CHANNEL); + break; + + case 4: + me->InterruptNonMeleeSpells(false); + DoScriptText(SAY_TIRED, me); + DoCast(me, SPELL_POWER_FEEDBACK); + RemoveGravityLapse(); + GravityLapseTimer = 10000; + GravityLapsePhase = 0; + break; + } + } else GravityLapseTimer -= diff; + } + break; + } + } +}; + +struct mob_felkael_flamestrikeAI : public ScriptedAI +{ + mob_felkael_flamestrikeAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 FlameStrikeTimer; + + void Reset() + { + FlameStrikeTimer = 5000; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + + DoCast(me, SPELL_FLAMESTRIKE2, true); + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (FlameStrikeTimer <= diff) + { + DoCast(me, SPELL_FLAMESTRIKE1_NORMAL, true); + me->Kill(me); + } else FlameStrikeTimer -= diff; + } +}; + +struct mob_felkael_phoenixAI : public ScriptedAI +{ + mob_felkael_phoenixAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 BurnTimer; + uint32 Death_Timer; + bool Rebirth; + bool FakeDeath; + + void Reset() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + DoCast(me, SPELL_PHOENIX_BURN, true); + BurnTimer = 2000; + Death_Timer = 3000; + Rebirth = false; + FakeDeath = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage < me->GetHealth()) + return; + + //Prevent glitch if in fake death + if (FakeDeath) + { + damage = 0; + return; + + } + //Don't really die in all phases of Kael'Thas + if (pInstance && pInstance->GetData(DATA_KAELTHAS_EVENT) == 0) + { + //prevent death + damage = 0; + FakeDeath = true; + + me->InterruptNonMeleeSpells(false); + me->SetHealth(0); + me->StopMoving(); + me->ClearComboPointHolders(); + me->RemoveAllAurasOnDeath(); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->ClearAllReactives(); + me->SetUInt64Value(UNIT_FIELD_TARGET,0); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + + } + + } + + void JustDied(Unit* /*slayer*/) + { + me->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + } + + void UpdateAI(const uint32 diff) + { + + //If we are fake death, we cast revbirth and after that we kill the phoenix to spawn the egg. + if (FakeDeath) + { + if (!Rebirth) + { + DoCast(me, SPELL_REBIRTH_DMG); + Rebirth = true; + } + + if (Rebirth) + { + + if (Death_Timer <= diff) + { + me->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + me->DisappearAndDie(); + Rebirth = false; + } else Death_Timer -= diff; + } + + } + + if (!UpdateVictim()) + return; + + if (BurnTimer <= diff) + { + //spell Burn should possible do this, but it doesn't, so do this for now. + uint16 dmg = urand(1650,2050); + me->DealDamage(me, dmg, 0, DOT, SPELL_SCHOOL_MASK_FIRE, NULL, false); + BurnTimer += 2000; + } BurnTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_felkael_phoenix_eggAI : public ScriptedAI +{ + mob_felkael_phoenix_eggAI(Creature *c) : ScriptedAI(c) {} + + uint32 HatchTimer; + + void Reset() + { + HatchTimer = 10000; + } + + void EnterCombat(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (HatchTimer <= diff) + { + me->SummonCreature(CREATURE_PHOENIX, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + me->Kill(me); + } else HatchTimer -= diff; + + } +}; + +struct mob_arcane_sphereAI : public ScriptedAI +{ + mob_arcane_sphereAI(Creature *c) : ScriptedAI(c) { Reset(); } + + uint32 DespawnTimer; + uint32 ChangeTargetTimer; + + void Reset() + { + DespawnTimer = 30000; + ChangeTargetTimer = urand(6000,12000); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->setFaction(14); + DoCast(me, SPELL_ARCANE_SPHERE_PASSIVE, true); + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (DespawnTimer <= diff) + me->Kill(me); + else + DespawnTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (ChangeTargetTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + } + + ChangeTargetTimer = urand(5000,15000); + } else ChangeTargetTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_felblood_kaelthas(Creature* c) +{ + return new boss_felblood_kaelthasAI(c); +} + +CreatureAI* GetAI_mob_arcane_sphere(Creature* c) +{ + return new mob_arcane_sphereAI(c); +} + +CreatureAI* GetAI_mob_felkael_phoenix(Creature* c) +{ + return new mob_felkael_phoenixAI(c); +} + +CreatureAI* GetAI_mob_felkael_phoenix_egg(Creature* c) +{ + return new mob_felkael_phoenix_eggAI(c); +} + +CreatureAI* GetAI_mob_felkael_flamestrike(Creature* c) +{ + return new mob_felkael_flamestrikeAI(c); +} + +void AddSC_boss_felblood_kaelthas() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_felblood_kaelthas"; + newscript->GetAI = &GetAI_boss_felblood_kaelthas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_arcane_sphere"; + newscript->GetAI = &GetAI_mob_arcane_sphere; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felkael_phoenix"; + newscript->GetAI = &GetAI_mob_felkael_phoenix; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felkael_phoenix_egg"; + newscript->GetAI = &GetAI_mob_felkael_phoenix_egg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felkael_flamestrike"; + newscript->GetAI = &GetAI_mob_felkael_flamestrike; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp new file mode 100644 index 00000000000..2112eaabc87 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp @@ -0,0 +1,1321 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Priestess_Delrissa +SD%Complete: 65 +SDComment: No Heroic support yet. Needs further testing. Several scripts for pets disabled, not seem to require any special script. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" + +struct Speech +{ + int32 id; +}; + +static Speech LackeyDeath[]= +{ + {-1585013}, + {-1585014}, + {-1585015}, + {-1585016}, +}; + +static Speech PlayerDeath[]= +{ + {-1585017}, + {-1585018}, + {-1585019}, + {-1585020}, + {-1585021}, +}; + +enum eEnums +{ + SAY_AGGRO = -1585012, + SAY_DEATH = -1585022, + + SPELL_DISPEL_MAGIC = 27609, + SPELL_FLASH_HEAL = 17843, + SPELL_SW_PAIN_NORMAL = 14032, + SPELL_SW_PAIN_HEROIC = 15654, + SPELL_SHIELD = 44291, + SPELL_RENEW_NORMAL = 44174, + SPELL_RENEW_HEROIC = 46192, + + MAX_ACTIVE_LACKEY = 4 +}; + +const float fOrientation = 4.98; +const float fZLocation = -19.921; + +float LackeyLocations[4][2]= +{ + {123.77, 17.6007}, + {131.731, 15.0827}, + {121.563, 15.6213}, + {129.988, 17.2355}, +}; + +const uint32 m_auiAddEntries[] = +{ + 24557, //Kagani Nightstrike + 24558, //Elris Duskhallow + 24554, //Eramas Brightblaze + 24561, //Yazzaj + 24559, //Warlord Salaris + 24555, //Garaxxas + 24553, //Apoko + 24556, //Zelfan +}; + +struct boss_priestess_delrissaAI : public ScriptedAI +{ + boss_priestess_delrissaAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + memset(&m_auiLackeyGUID, 0, sizeof(m_auiLackeyGUID)); + LackeyEntryList.clear(); + } + + ScriptedInstance* pInstance; + + std::vector LackeyEntryList; + uint64 m_auiLackeyGUID[MAX_ACTIVE_LACKEY]; + + uint8 PlayersKilled; + + uint32 HealTimer; + uint32 RenewTimer; + uint32 ShieldTimer; + uint32 SWPainTimer; + uint32 DispelTimer; + uint32 ResetTimer; + + void Reset() + { + PlayersKilled = 0; + + HealTimer = 15000; + RenewTimer = 10000; + ShieldTimer = 2000; + SWPainTimer = 5000; + DispelTimer = 7500; + ResetTimer = 5000; + + InitializeLackeys(); + } + + //this mean she at some point evaded + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(DATA_DELRISSA_EVENT, FAIL); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + { + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[i])) + { + if (!pAdd->getVictim()) + { + who->SetInCombatWith(pAdd); + pAdd->AddThreat(who, 0.0f); + } + } + } + + if (pInstance) + pInstance->SetData(DATA_DELRISSA_EVENT, IN_PROGRESS); + } + + void InitializeLackeys() + { + //can be called if Creature are dead, so avoid + if (!me->isAlive()) + return; + + uint8 j = 0; + + //it's empty, so first time + if (LackeyEntryList.empty()) + { + //pre-allocate size for speed + LackeyEntryList.resize((sizeof(m_auiAddEntries) / sizeof(uint32))); + + //fill vector array with entries from Creature array + for (uint8 i = 0; i < LackeyEntryList.size(); ++i) + LackeyEntryList[i] = m_auiAddEntries[i]; + + //remove random entries + while (LackeyEntryList.size() > MAX_ACTIVE_LACKEY) + LackeyEntryList.erase(LackeyEntryList.begin() + rand()%LackeyEntryList.size()); + + //summon all the remaining in vector + for (std::vector::const_iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr) + { + if (Creature* pAdd = me->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0)) + m_auiLackeyGUID[j] = pAdd->GetGUID(); + + ++j; + } + } + else + { + for (std::vector::const_iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr) + { + Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[j]); + + //object already removed, not exist + if (!pAdd) + { + if (Creature* pAdd = me->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0)) + m_auiLackeyGUID[j] = pAdd->GetGUID(); + } + ++j; + } + } + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(PlayerDeath[PlayersKilled].id, me); + + if (PlayersKilled < 4) + ++PlayersKilled; + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + if (pInstance->GetData(DATA_DELRISSA_DEATH_COUNT) == MAX_ACTIVE_LACKEY) + pInstance->SetData(DATA_DELRISSA_EVENT, DONE); + else + { + if (me->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ResetTimer <= diff) + { + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + if (me->GetPositionZ() >= z+10) + { + EnterEvadeMode(); + return; + } + ResetTimer = 5000; + } else ResetTimer -= diff; + + if (HealTimer <= diff) + { + uint32 health = me->GetHealth(); + Unit *pTarget = me; + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + { + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[i])) + { + if (pAdd->isAlive() && pAdd->GetHealth() < health) + pTarget = pAdd; + } + } + + DoCast(pTarget, SPELL_FLASH_HEAL); + HealTimer = 15000; + } else HealTimer -= diff; + + if (RenewTimer <= diff) + { + Unit *pTarget = me; + + if (urand(0,1)) + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) + if (pAdd->isAlive()) + pTarget = pAdd; + + DoCast(pTarget, SPELL_RENEW_NORMAL); + RenewTimer = 5000; + } else RenewTimer -= diff; + + if (ShieldTimer <= diff) + { + Unit *pTarget = me; + + if (urand(0,1)) + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) + if (pAdd->isAlive() && !pAdd->HasAura(SPELL_SHIELD)) + pTarget = pAdd; + + DoCast(pTarget, SPELL_SHIELD); + ShieldTimer = 7500; + } else ShieldTimer -= diff; + + if (DispelTimer <= diff) + { + Unit *pTarget = NULL; + bool friendly = false; + + if (urand(0,1)) + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + else + { + friendly = true; + + if (urand(0,1)) + pTarget = me; + else + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) + if (pAdd->isAlive()) + pTarget = pAdd; + } + + if (pTarget) + DoCast(pTarget, SPELL_DISPEL_MAGIC); + + DispelTimer = 12000; + } else DispelTimer -= diff; + + if (SWPainTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SW_PAIN_NORMAL); + + SWPainTimer = 10000; + } else SWPainTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_priestess_delrissa(Creature* pCreature) +{ + return new boss_priestess_delrissaAI(pCreature); +} + +enum eHealingPotion +{ + SPELL_HEALING_POTION = 15503 +}; + +//all 8 possible lackey use this common +struct boss_priestess_lackey_commonAI : public ScriptedAI +{ + boss_priestess_lackey_commonAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + memset(&m_auiLackeyGUIDs, 0, sizeof(m_auiLackeyGUIDs)); + AcquireGUIDs(); + } + + ScriptedInstance* pInstance; + + uint64 m_auiLackeyGUIDs[MAX_ACTIVE_LACKEY]; + uint32 ResetThreatTimer; + + bool UsedPotion; + + void Reset() + { + UsedPotion = false; + + // These guys does not follow normal threat system rules + // For later development, some alternative threat system should be made + // We do not know what this system is based upon, but one theory is class (healers=high threat, dps=medium, etc) + // We reset their threat frequently as an alternative until such a system exist + ResetThreatTimer = urand(5000,20000); + + // in case she is not alive and Reset was for some reason called, respawn her (most likely party wipe after killing her) + if (Creature* pDelrissa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DELRISSA) : 0)) + { + if (!pDelrissa->isAlive()) + pDelrissa->Respawn(); + } + } + + void EnterCombat(Unit* pWho) + { + if (!pWho) + return; + + if (pInstance) + { + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + { + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUIDs[i])) + { + if (!pAdd->getVictim() && pAdd != me) + { + pWho->SetInCombatWith(pAdd); + pAdd->AddThreat(pWho, 0.0f); + } + } + } + + if (Creature* pDelrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA))) + { + if (pDelrissa->isAlive() && !pDelrissa->getVictim()) + { + pWho->SetInCombatWith(pDelrissa); + pDelrissa->AddThreat(pWho, 0.0f); + } + } + } + } + + void JustDied(Unit* /*killer*/) + { + if (!pInstance) + return; + + Creature* pDelrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA)); + uint32 uiLackeyDeathCount = pInstance->GetData(DATA_DELRISSA_DEATH_COUNT); + + if (!pDelrissa) + return; + + //should delrissa really yell if dead? + DoScriptText(LackeyDeath[uiLackeyDeathCount].id, pDelrissa); + + pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, SPECIAL); + + //increase local var, since we now may have four dead + ++uiLackeyDeathCount; + + if (uiLackeyDeathCount == MAX_ACTIVE_LACKEY) + { + //time to make her lootable and complete event if she died before lackeys + if (!pDelrissa->isAlive()) + { + if (!pDelrissa->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) + pDelrissa->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + pInstance->SetData(DATA_DELRISSA_EVENT, DONE); + } + } + } + + void KilledUnit(Unit* victim) + { + if (!pInstance) + return; + + if (Creature* Delrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA))) + Delrissa->AI()->KilledUnit(victim); + } + + void AcquireGUIDs() + { + if (!pInstance) + return; + + if (Creature* Delrissa = (Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA)))) + { + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + m_auiLackeyGUIDs[i] = CAST_AI(boss_priestess_delrissaAI, Delrissa->AI())->m_auiLackeyGUID[i]; + } + } + + void UpdateAI(const uint32 diff) + { + if (!UsedPotion && (me->GetHealth()*100 / me->GetMaxHealth()) < 25) + { + DoCast(me, SPELL_HEALING_POTION); + UsedPotion = true; + } + + if (ResetThreatTimer <= diff) + { + DoResetThreat(); + ResetThreatTimer = 5000 + rand()%15000; + } else ResetThreatTimer -= diff; + } +}; + +enum eRogueSpells +{ + SPELL_KIDNEY_SHOT = 27615, + SPELL_GOUGE = 12540, + SPELL_KICK = 27613, + SPELL_VANISH = 44290, + SPELL_BACKSTAB = 15657, + SPELL_EVISCERATE = 27611 +}; + +struct boss_kagani_nightstrikeAI : public boss_priestess_lackey_commonAI +{ + //Rogue + boss_kagani_nightstrikeAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Gouge_Timer; + uint32 Kick_Timer; + uint32 Vanish_Timer; + uint32 Eviscerate_Timer; + uint32 Wait_Timer; + bool InVanish; + + void Reset() + { + Gouge_Timer = 5500; + Kick_Timer = 7000; + Vanish_Timer = 2000; + Eviscerate_Timer = 6000; + Wait_Timer = 5000; + InVanish = false; + me->SetVisibility(VISIBILITY_ON); + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Vanish_Timer <= diff) + { + DoCast(me, SPELL_VANISH); + + Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0); + + DoResetThreat(); + + if (pUnit) + me->AddThreat(pUnit, 1000.0f); + + InVanish = true; + Vanish_Timer = 30000; + Wait_Timer = 10000; + } else Vanish_Timer -= diff; + + if (InVanish) + { + if (Wait_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BACKSTAB, true); + DoCast(me->getVictim(), SPELL_KIDNEY_SHOT, true); + me->SetVisibility(VISIBILITY_ON); // ...? Hacklike + InVanish = false; + } else Wait_Timer -= diff; + } + + if (Gouge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GOUGE); + Gouge_Timer = 5500; + } else Gouge_Timer -= diff; + + if (Kick_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KICK); + Kick_Timer = 7000; + } else Kick_Timer -= diff; + + if (Eviscerate_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_EVISCERATE); + Eviscerate_Timer = 4000; + } else Eviscerate_Timer -= diff; + + if (!InVanish) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kagani_nightstrike(Creature* pCreature) +{ + return new boss_kagani_nightstrikeAI(pCreature); +} + +enum eWarlockSpells +{ + SPELL_IMMOLATE = 44267, + SPELL_SHADOW_BOLT = 12471, + SPELL_SEED_OF_CORRUPTION = 44141, + SPELL_CURSE_OF_AGONY = 14875, + SPELL_FEAR = 38595, + SPELL_IMP_FIREBALL = 44164, + SPELL_SUMMON_IMP = 44163 +}; + +struct boss_ellris_duskhallowAI : public boss_priestess_lackey_commonAI +{ + //Warlock + boss_ellris_duskhallowAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Immolate_Timer; + uint32 Shadow_Bolt_Timer; + uint32 Seed_of_Corruption_Timer; + uint32 Curse_of_Agony_Timer; + uint32 Fear_Timer; + + void Reset() + { + Immolate_Timer = 6000; + Shadow_Bolt_Timer = 3000; + Seed_of_Corruption_Timer = 2000; + Curse_of_Agony_Timer = 1000; + Fear_Timer = 10000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void Aggro(Unit* /*pWho*/) + { + DoCast(me, SPELL_SUMMON_IMP); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Immolate_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_IMMOLATE); + Immolate_Timer = 6000; + } else Immolate_Timer -= diff; + + if (Shadow_Bolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + Shadow_Bolt_Timer = 5000; + } else Shadow_Bolt_Timer -= diff; + + if (Seed_of_Corruption_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_SEED_OF_CORRUPTION); + + Seed_of_Corruption_Timer = 10000; + } else Seed_of_Corruption_Timer -= diff; + + if (Curse_of_Agony_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_CURSE_OF_AGONY); + + Curse_of_Agony_Timer = 13000; + } else Curse_of_Agony_Timer -= diff; + + if (Fear_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_FEAR); + + Fear_Timer = 10000; + } else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_ellris_duskhallow(Creature* pCreature) +{ + return new boss_ellris_duskhallowAI(pCreature); +} + +enum eKickDown +{ + SPELL_KNOCKDOWN = 11428, + SPELL_SNAP_KICK = 46182 +}; + +struct boss_eramas_brightblazeAI : public boss_priestess_lackey_commonAI +{ + //Monk + boss_eramas_brightblazeAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Knockdown_Timer; + uint32 Snap_Kick_Timer; + + void Reset() + { + Knockdown_Timer = 6000; + Snap_Kick_Timer = 4500; + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Knockdown_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + Knockdown_Timer = 6000; + } else Knockdown_Timer -= diff; + + if (Snap_Kick_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SNAP_KICK); + Snap_Kick_Timer = 4500; + } else Snap_Kick_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_eramas_brightblaze(Creature* pCreature) +{ + return new boss_eramas_brightblazeAI(pCreature); +} + +enum eMageSpells +{ + SPELL_POLYMORPH = 13323, + SPELL_ICE_BLOCK = 27619, + SPELL_BLIZZARD = 44178, + SPELL_ICE_LANCE = 46194, + SPELL_CONE_OF_COLD = 38384, + SPELL_FROSTBOLT = 15043, + SPELL_BLINK = 14514 +}; + +struct boss_yazzaiAI : public boss_priestess_lackey_commonAI +{ + //Mage + boss_yazzaiAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + bool HasIceBlocked; + + uint32 Polymorph_Timer; + uint32 Ice_Block_Timer; + uint32 Wait_Timer; + uint32 Blizzard_Timer; + uint32 Ice_Lance_Timer; + uint32 Cone_of_Cold_Timer; + uint32 Frostbolt_Timer; + uint32 Blink_Timer; + + void Reset() + { + HasIceBlocked = false; + + Polymorph_Timer = 1000; + Ice_Block_Timer = 20000; + Wait_Timer = 10000; + Blizzard_Timer = 8000; + Ice_Lance_Timer = 12000; + Cone_of_Cold_Timer = 10000; + Frostbolt_Timer = 3000; + Blink_Timer = 8000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Polymorph_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_POLYMORPH); + Polymorph_Timer = 20000; + } + } else Polymorph_Timer -= diff; + + if (((me->GetHealth()*100 / me->GetMaxHealth()) < 35) && !HasIceBlocked) + { + DoCast(me, SPELL_ICE_BLOCK); + HasIceBlocked = true; + } + + if (Blizzard_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_BLIZZARD); + + Blizzard_Timer = 8000; + } else Blizzard_Timer -= diff; + + if (Ice_Lance_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ICE_LANCE); + Ice_Lance_Timer = 12000; + } else Ice_Lance_Timer -= diff; + + if (Cone_of_Cold_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CONE_OF_COLD); + Cone_of_Cold_Timer = 10000; + } else Cone_of_Cold_Timer -= diff; + + if (Frostbolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 8000; + } else Frostbolt_Timer -= diff; + + if (Blink_Timer <= diff) + { + bool InMeleeRange = false; + std::list& t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + //if in melee range + if (pTarget->IsWithinDistInMap(me, 5)) + { + InMeleeRange = true; + break; + } + } + } + + //if anybody is in melee range than escape by blink + if (InMeleeRange) + DoCast(me, SPELL_BLINK); + + Blink_Timer = 8000; + } else Blink_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_yazzai(Creature* pCreature) +{ + return new boss_yazzaiAI(pCreature); +} + +enum eWarriorSpells +{ + SPELL_INTERCEPT_STUN = 27577, + SPELL_DISARM = 27581, + SPELL_PIERCING_HOWL = 23600, + SPELL_FRIGHTENING_SHOUT = 19134, + SPELL_HAMSTRING = 27584, + SPELL_BATTLE_SHOUT = 27578, + SPELL_MORTAL_STRIKE = 44268 +}; + +struct boss_warlord_salarisAI : public boss_priestess_lackey_commonAI +{ + //Warrior + boss_warlord_salarisAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Intercept_Stun_Timer; + uint32 Disarm_Timer; + uint32 Piercing_Howl_Timer; + uint32 Frightening_Shout_Timer; + uint32 Hamstring_Timer; + uint32 Mortal_Strike_Timer; + + void Reset() + { + Intercept_Stun_Timer = 500; + Disarm_Timer = 6000; + Piercing_Howl_Timer = 10000; + Frightening_Shout_Timer = 18000; + Hamstring_Timer = 4500; + Mortal_Strike_Timer = 8000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_BATTLE_SHOUT); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Intercept_Stun_Timer <= diff) + { + bool InMeleeRange = false; + std::list& t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + //if in melee range + if (pTarget->IsWithinDistInMap(me, ATTACK_DISTANCE)) + { + InMeleeRange = true; + break; + } + } + } + + //if nobody is in melee range than try to use Intercept + if (!InMeleeRange) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_INTERCEPT_STUN); + } + + Intercept_Stun_Timer = 10000; + } else Intercept_Stun_Timer -= diff; + + if (Disarm_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DISARM); + Disarm_Timer = 6000; + } else Disarm_Timer -= diff; + + if (Hamstring_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + Hamstring_Timer = 4500; + } else Hamstring_Timer -= diff; + + if (Mortal_Strike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + Mortal_Strike_Timer = 4500; + } else Mortal_Strike_Timer -= diff; + + if (Piercing_Howl_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PIERCING_HOWL); + Piercing_Howl_Timer = 10000; + } else Piercing_Howl_Timer -= diff; + + if (Frightening_Shout_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); + Frightening_Shout_Timer = 18000; + } else Frightening_Shout_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_warlord_salaris(Creature* pCreature) +{ + return new boss_warlord_salarisAI(pCreature); +} + +enum eHunterSpells +{ + SPELL_AIMED_SHOT = 44271, + SPELL_SHOOT = 15620, + SPELL_CONCUSSIVE_SHOT = 27634, + SPELL_MULTI_SHOT = 31942, + SPELL_WING_CLIP = 44286, + SPELL_FREEZING_TRAP = 44136, + + NPC_SLIVER = 24552 +}; + +struct boss_garaxxasAI : public boss_priestess_lackey_commonAI +{ + //Hunter + boss_garaxxasAI(Creature *c) : boss_priestess_lackey_commonAI(c) { m_uiPetGUID = 0; } + + uint64 m_uiPetGUID; + + uint32 Aimed_Shot_Timer; + uint32 Shoot_Timer; + uint32 Concussive_Shot_Timer; + uint32 Multi_Shot_Timer; + uint32 Wing_Clip_Timer; + uint32 Freezing_Trap_Timer; + + void Reset() + { + Aimed_Shot_Timer = 6000; + Shoot_Timer = 2500; + Concussive_Shot_Timer = 8000; + Multi_Shot_Timer = 10000; + Wing_Clip_Timer = 4000; + Freezing_Trap_Timer = 15000; + + Unit* pPet = Unit::GetUnit(*me,m_uiPetGUID); + if (!pPet) + me->SummonCreature(NPC_SLIVER, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + + boss_priestess_lackey_commonAI::Reset(); + } + + void JustSummoned(Creature* pSummoned) + { + m_uiPetGUID = pSummoned->GetGUID(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (me->IsWithinDistInMap(me->getVictim(), ATTACK_DISTANCE)) + { + if (Wing_Clip_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WING_CLIP); + Wing_Clip_Timer = 4000; + } else Wing_Clip_Timer -= diff; + + if (Freezing_Trap_Timer <= diff) + { + //attempt find go summoned from spell (casted by me) + GameObject* pGo = me->GetGameObject(SPELL_FREEZING_TRAP); + + //if we have a pGo, we need to wait (only one trap at a time) + if (pGo) + Freezing_Trap_Timer = 2500; + else + { + //if pGo does not exist, then we can cast + DoCast(me->getVictim(), SPELL_FREEZING_TRAP); + Freezing_Trap_Timer = 15000; + } + } else Freezing_Trap_Timer -= diff; + + DoMeleeAttackIfReady(); + } + else + { + if (Concussive_Shot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CONCUSSIVE_SHOT); + Concussive_Shot_Timer = 8000; + } else Concussive_Shot_Timer -= diff; + + if (Multi_Shot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MULTI_SHOT); + Multi_Shot_Timer = 10000; + } else Multi_Shot_Timer -= diff; + + if (Aimed_Shot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_AIMED_SHOT); + Aimed_Shot_Timer = 6000; + } else Aimed_Shot_Timer -= diff; + + if (Shoot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHOOT); + Shoot_Timer = 2500; + } else Shoot_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_garaxxas(Creature* pCreature) +{ + return new boss_garaxxasAI(pCreature); +} + +enum Spells +{ + SPELL_WINDFURY_TOTEM = 27621, + SPELL_WAR_STOMP = 46026, + SPELL_PURGE = 27626, + SPELL_LESSER_HEALING_WAVE = 44256, + SPELL_FROST_SHOCK = 21401, + SPELL_FIRE_NOVA_TOTEM = 44257, + SPELL_EARTHBIND_TOTEM = 15786 +}; + +struct boss_apokoAI : public boss_priestess_lackey_commonAI +{ + //Shaman + boss_apokoAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Totem_Timer; + uint8 Totem_Amount; + uint32 War_Stomp_Timer; + uint32 Purge_Timer; + uint32 Healing_Wave_Timer; + uint32 Frost_Shock_Timer; + + void Reset() + { + Totem_Timer = 2000; + Totem_Amount = 1; + War_Stomp_Timer = 10000; + Purge_Timer = 8000; + Healing_Wave_Timer = 5000; + Frost_Shock_Timer = 7000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Totem_Timer <= diff) + { + DoCast(me, RAND(SPELL_WINDFURY_TOTEM,SPELL_FIRE_NOVA_TOTEM,SPELL_EARTHBIND_TOTEM)); + ++Totem_Amount; + Totem_Timer = Totem_Amount*2000; + } else Totem_Timer -= diff; + + if (War_Stomp_Timer <= diff) + { + DoCast(me, SPELL_WAR_STOMP); + War_Stomp_Timer = 10000; + } else War_Stomp_Timer -= diff; + + if (Purge_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_PURGE); + + Purge_Timer = 15000; + } else Purge_Timer -= diff; + + if (Frost_Shock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_SHOCK); + Frost_Shock_Timer = 7000; + } else Frost_Shock_Timer -= diff; + + if (Healing_Wave_Timer <= diff) + { + // std::vector::const_iterator itr = Group.begin() + rand()%Group.size(); + // uint64 guid = (*itr)->guid; + // if (guid) + // { + // Unit* pAdd = Unit::GetUnit(*me, (*itr)->guid); + // if (pAdd && pAdd->isAlive()) + // { + DoCast(me, SPELL_LESSER_HEALING_WAVE); + Healing_Wave_Timer = 5000; + // } + // } + } else Healing_Wave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_apoko(Creature* pCreature) +{ + return new boss_apokoAI(pCreature); +} + +enum eEngineerSpells +{ + SPELL_GOBLIN_DRAGON_GUN = 44272, + SPELL_ROCKET_LAUNCH = 44137, + SPELL_RECOMBOBULATE = 44274, + SPELL_HIGH_EXPLOSIVE_SHEEP = 44276, + SPELL_FEL_IRON_BOMB = 46024, + SPELL_SHEEP_EXPLOSION = 44279 +}; + +struct boss_zelfanAI : public boss_priestess_lackey_commonAI +{ + //Engineer + boss_zelfanAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} + + uint32 Goblin_Dragon_Gun_Timer; + uint32 Rocket_Launch_Timer; + uint32 Recombobulate_Timer; + uint32 High_Explosive_Sheep_Timer; + uint32 Fel_Iron_Bomb_Timer; + + void Reset() + { + Goblin_Dragon_Gun_Timer = 20000; + Rocket_Launch_Timer = 7000; + Recombobulate_Timer = 4000; + High_Explosive_Sheep_Timer = 10000; + Fel_Iron_Bomb_Timer = 15000; + + boss_priestess_lackey_commonAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + boss_priestess_lackey_commonAI::UpdateAI(diff); + + if (Goblin_Dragon_Gun_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GOBLIN_DRAGON_GUN); + Goblin_Dragon_Gun_Timer = 10000; + } else Goblin_Dragon_Gun_Timer -= diff; + + if (Rocket_Launch_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ROCKET_LAUNCH); + Rocket_Launch_Timer = 9000; + } else Rocket_Launch_Timer -= diff; + + if (Fel_Iron_Bomb_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FEL_IRON_BOMB); + Fel_Iron_Bomb_Timer = 15000; + } else Fel_Iron_Bomb_Timer -= diff; + + if (Recombobulate_Timer <= diff) + { + for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) + { + if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUIDs[i])) + { + if (pAdd->IsPolymorphed()) + { + DoCast(pAdd, SPELL_RECOMBOBULATE); + break; + } + } + } + Recombobulate_Timer = 2000; + } else Recombobulate_Timer -= diff; + + if (High_Explosive_Sheep_Timer <= diff) + { + DoCast(me, SPELL_HIGH_EXPLOSIVE_SHEEP); + High_Explosive_Sheep_Timer = 65000; + } else High_Explosive_Sheep_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_zelfan(Creature* pCreature) +{ + return new boss_zelfanAI(pCreature); +} + +//struct mob_high_explosive_sheepAI : public ScriptedAI +//{ +// mob_high_explosive_sheepAI(Creature *c) : ScriptedAI(c) {} +// +// uint32 Explosion_Timer; +// +// void Reset() +// { +// Explosion_Timer = 60000; +// } +// +// void JustDied(Unit *Killer){} +// +// void EnterCombat(Unit * /*who*/){} +// +// void UpdateAI(const uint32 diff) +// { +// if (Explosion_Timer <= diff) +// { +// DoCast(me->getVictim(), SPELL_SHEEP_EXPLOSION); +// }else +// Explosion_Timer -= diff; +// } +//}; + +//CreatureAI* GetAI_mob_high_explosive_sheep(Creature* pCreature) +//{ +// return new mob_high_explosive_sheepAI (pCreature); +//}; + +void AddSC_boss_priestess_delrissa() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_priestess_delrissa"; + newscript->GetAI = &GetAI_boss_priestess_delrissa; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_kagani_nightstrike"; + newscript->GetAI = &GetAI_boss_kagani_nightstrike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_ellris_duskhallow"; + newscript->GetAI = &GetAI_ellris_duskhallow; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_eramas_brightblaze"; + newscript->GetAI = &GetAI_eramas_brightblaze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_yazzai"; + newscript->GetAI = &GetAI_yazzai; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_warlord_salaris"; + newscript->GetAI = &GetAI_warlord_salaris; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_garaxxas"; + newscript->GetAI = &GetAI_garaxxas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_apoko"; + newscript->GetAI = &GetAI_apoko; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_zelfan"; + newscript->GetAI = &GetAI_zelfan; + newscript->RegisterSelf(); + + /*newscript = new Script; + newscript->Name = "mob_high_explosive_sheep"; + newscript->GetAI = &GetAI_mob_high_explosive_sheep; + newscript->RegisterSelf();*/ +} + diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp new file mode 100644 index 00000000000..adb0700eabf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp @@ -0,0 +1,366 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Selin_Fireheart +SD%Complete: 90 +SDComment: Heroic and Normal Support. Needs further testing. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" + +#define SAY_AGGRO -1585000 +#define SAY_ENERGY -1585001 +#define SAY_EMPOWERED -1585002 +#define SAY_KILL_1 -1585003 +#define SAY_KILL_2 -1585004 +#define SAY_DEATH -1585005 +#define EMOTE_CRYSTAL -1585006 + +//Crystal effect spells +#define SPELL_FEL_CRYSTAL_COSMETIC 44374 +#define SPELL_FEL_CRYSTAL_DUMMY 44329 +#define SPELL_FEL_CRYSTAL_VISUAL 44355 +#define SPELL_MANA_RAGE 44320 // This spell triggers 44321, which changes scale and regens mana Requires an entry in spell_script_target + +//Selin's spells +#define SPELL_DRAIN_LIFE 44294 +#define SPELL_FEL_EXPLOSION 44314 + +#define SPELL_DRAIN_MANA 46153 // Heroic only + +#define CRYSTALS_NUMBER 5 +#define DATA_CRYSTALS 6 + +#define CREATURE_FEL_CRYSTAL 24722 + +struct boss_selin_fireheartAI : public ScriptedAI +{ + boss_selin_fireheartAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + + Crystals.clear(); + //GUIDs per instance is static, so we only need to load them once. + if (pInstance) + { + uint32 size = pInstance->GetData(DATA_FEL_CRYSTAL_SIZE); + for (uint8 i = 0; i < size; ++i) + { + uint64 guid = pInstance->GetData64(DATA_FEL_CRYSTAL); + debug_log("TSCR: Selin: Adding Fel Crystal %u to list", guid); + Crystals.push_back(guid); + } + } + } + + ScriptedInstance* pInstance; + + std::list Crystals; + + uint32 DrainLifeTimer; + uint32 DrainManaTimer; + uint32 FelExplosionTimer; + uint32 DrainCrystalTimer; + uint32 EmpowerTimer; + + bool IsDraining; + bool DrainingCrystal; + + uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course). + + void Reset() + { + if (pInstance) + { + //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + //Unit* pUnit = Unit::GetUnit(*me, FelCrystals[i]); + Unit* pUnit = Unit::GetUnit(*me, *itr); + if (pUnit) + { + if (!pUnit->isAlive()) + CAST_CRE(pUnit)->Respawn(); // Let the core handle setting death state, etc. + + // Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here. + pUnit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + + pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); + // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here) + // Small door opened after event are expected to be closed by default + // Set Inst data for encounter + pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED); + } else error_log(ERROR_INST_DATA); + + DrainLifeTimer = 3000 + rand()%4000; + DrainManaTimer = DrainLifeTimer + 5000; + FelExplosionTimer = 2100; + DrainCrystalTimer = 10000 + rand()%5000; + DrainCrystalTimer = 20000 + rand()%5000; + EmpowerTimer = 10000; + + IsDraining = false; + DrainingCrystal = false; + CrystalGUID = 0; + } + + void SelectNearestCrystal() + { + if (Crystals.empty()) + return; + + //float ShortestDistance = 0; + CrystalGUID = 0; + Unit* pCrystal = NULL; + Unit* CrystalChosen = NULL; + //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + pCrystal = NULL; + //pCrystal = Unit::GetUnit(*me, FelCrystals[i]); + pCrystal = Unit::GetUnit(*me, *itr); + if (pCrystal && pCrystal->isAlive()) + { + // select nearest + if (!CrystalChosen || me->GetDistanceOrder(pCrystal, CrystalChosen, false)) + { + CrystalGUID = pCrystal->GetGUID(); + CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell. + } + } + } + if (CrystalChosen) + { + DoScriptText(SAY_ENERGY, me); + DoScriptText(EMOTE_CRYSTAL, me); + + CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true); + + float x, y, z; // coords that we move to, close to the crystal. + CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE); + + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->MovePoint(1, x, y, z); + DrainingCrystal = true; + } + } + + void ShatterRemainingCrystals() + { + if (Crystals.empty()) + return; + + //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) + for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) + { + //Creature* pCrystal = (Unit::GetCreature(*me, FelCrystals[i])); + Creature* pCrystal = Unit::GetCreature(*me, *itr); + if (pCrystal && pCrystal->isAlive()) + pCrystal->Kill(pCrystal); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), false); + //Close the encounter door, open it in JustDied/Reset + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type == POINT_MOTION_TYPE && id == 1) + { + Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID); + if (CrystalChosen && CrystalChosen->isAlive()) + { + // Make the crystal attackable + // We also remove NON_ATTACKABLE in case the database has it set. + CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + CrystalChosen->CastSpell(me, SPELL_MANA_RAGE, true); + IsDraining = true; + } + else + { + // Make an error message in case something weird happened here + error_log("TSCR: Selin Fireheart unable to drain crystal as the crystal is either dead or despawned"); + DrainingCrystal = false; + } + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + pInstance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete! + pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); // Open the encounter door + pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_DOOR), true); // Open the door leading further in + ShatterRemainingCrystals(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!DrainingCrystal) + { + uint32 maxPowerMana = me->GetMaxPower(POWER_MANA); + if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10)) + { + if (DrainLifeTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE); + DrainLifeTimer = 10000; + } else DrainLifeTimer -= diff; + + // Heroic only + if (IsHeroic()) + { + if (DrainManaTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_DRAIN_MANA); + DrainManaTimer = 10000; + } else DrainManaTimer -= diff; + } + } + + if (FelExplosionTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_FEL_EXPLOSION); + FelExplosionTimer = 2000; + } + } else FelExplosionTimer -= diff; + + // If below 10% mana, start recharging + maxPowerMana = me->GetMaxPower(POWER_MANA); + if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10)) + { + if (DrainCrystalTimer <= diff) + { + SelectNearestCrystal(); + if (IsHeroic()) + DrainCrystalTimer = 10000 + rand()%5000; + else + DrainCrystalTimer = 20000 + rand()%5000; + } else DrainCrystalTimer -= diff; + } + + }else + { + if (IsDraining) + { + if (EmpowerTimer <= diff) + { + IsDraining = false; + DrainingCrystal = false; + + DoScriptText(SAY_EMPOWERED, me); + + Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID); + if (CrystalChosen && CrystalChosen->isAlive()) + // Use Deal Damage to kill it, not setDeathState. + CrystalChosen->Kill(CrystalChosen); + + CrystalGUID = 0; + + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } else EmpowerTimer -= diff; + } + } + + DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun. + } +}; + +CreatureAI* GetAI_boss_selin_fireheart(Creature* pCreature) +{ + return new boss_selin_fireheartAI (pCreature); +}; + +struct mob_fel_crystalAI : public ScriptedAI +{ + mob_fel_crystalAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} + + void JustDied(Unit* /*killer*/) + { + if (ScriptedInstance* pInstance = me->GetInstanceData()) + { + Creature* Selin = (Unit::GetCreature(*me, pInstance->GetData64(DATA_SELIN))); + if (Selin && Selin->isAlive()) + { + if (CAST_AI(boss_selin_fireheartAI, Selin->AI())->CrystalGUID == me->GetGUID()) + { + // Set this to false if we are the Creature that Selin is draining so his AI flows properly + CAST_AI(boss_selin_fireheartAI, Selin->AI())->DrainingCrystal = false; + CAST_AI(boss_selin_fireheartAI, Selin->AI())->IsDraining = false; + CAST_AI(boss_selin_fireheartAI, Selin->AI())->EmpowerTimer = 10000; + if (Selin->getVictim()) + { + Selin->AI()->AttackStart(Selin->getVictim()); + Selin->GetMotionMaster()->MoveChase(Selin->getVictim()); + } + } + } + } else error_log(ERROR_INST_DATA); + } +}; + +CreatureAI* GetAI_mob_fel_crystal(Creature* pCreature) +{ + return new mob_fel_crystalAI (pCreature); +}; + +void AddSC_boss_selin_fireheart() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_selin_fireheart"; + newscript->GetAI = &GetAI_boss_selin_fireheart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_crystal"; + newscript->GetAI = &GetAI_mob_fel_crystal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp new file mode 100644 index 00000000000..bc8bd5cec30 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp @@ -0,0 +1,226 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vexallus +SD%Complete: 90 +SDComment: Heroic and Normal support. Needs further testing. +SDCategory: Magister's Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" + +enum eEnums +{ + SAY_AGGRO = -1585007, + SAY_ENERGY = -1585008, + SAY_OVERLOAD = -1585009, + SAY_KILL = -1585010, + EMOTE_DISCHARGE_ENERGY = -1585011, + + //is this text for real? + //#define SAY_DEATH "What...happen...ed." + + //Pure energy spell info + SPELL_ENERGY_BOLT = 46156, + SPELL_ENERGY_FEEDBACK = 44335, + + //Vexallus spell info + SPELL_CHAIN_LIGHTNING = 44318, + SPELL_H_CHAIN_LIGHTNING = 46380, //heroic spell + SPELL_OVERLOAD = 44353, + SPELL_ARCANE_SHOCK = 44319, + SPELL_H_ARCANE_SHOCK = 46381, //heroic spell + + SPELL_SUMMON_PURE_ENERGY = 44322, //mod scale -10 + H_SPELL_SUMMON_PURE_ENERGY1 = 46154, //mod scale -5 + H_SPELL_SUMMON_PURE_ENERGY2 = 46159, //mod scale -5 + + //Creatures + NPC_PURE_ENERGY = 24745, + + INTERVAL_MODIFIER = 15, + INTERVAL_SWITCH = 6 +}; + +struct boss_vexallusAI : public ScriptedAI +{ + boss_vexallusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ChainLightningTimer; + uint32 ArcaneShockTimer; + uint32 OverloadTimer; + uint32 IntervalHealthAmount; + bool Enraged; + + void Reset() + { + ChainLightningTimer = 8000; + ArcaneShockTimer = 5000; + OverloadTimer = 1200; + IntervalHealthAmount = 1; + Enraged = false; + + if (pInstance) + pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_VEXALLUS_EVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature *summoned) + { + if (Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 0)) + summoned->GetMotionMaster()->MoveFollow(temp,0,0); + + //spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok + summoned->CastSpell(summoned,SPELL_ENERGY_BOLT,false,0,0,me->GetGUID()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!Enraged) + { + //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25% + if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(INTERVAL_MODIFIER*IntervalHealthAmount))) + { + //increase amount, unless we're at 10%, then we switch and return + if (IntervalHealthAmount == INTERVAL_SWITCH) + { + Enraged = true; + return; + } + else + ++IntervalHealthAmount; + + DoScriptText(SAY_ENERGY, me); + DoScriptText(EMOTE_DISCHARGE_ENERGY, me); + + if (IsHeroic()) + { + DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false); + DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false); + } + else + DoCast(me, SPELL_SUMMON_PURE_ENERGY, false); + + //below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core + me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (IsHeroic()) + me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + } + + if (ChainLightningTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + + ChainLightningTimer = 8000; + } else ChainLightningTimer -= diff; + + if (ArcaneShockTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + if (pTarget) + DoCast(pTarget, SPELL_ARCANE_SHOCK); + + ArcaneShockTimer = 8000; + } else ArcaneShockTimer -= diff; + } + else + { + if (OverloadTimer <= diff) + { + DoCast(me->getVictim(), SPELL_OVERLOAD); + + OverloadTimer = 2000; + } else OverloadTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vexallus(Creature* pCreature) +{ + return new boss_vexallusAI (pCreature); +}; + +struct mob_pure_energyAI : public ScriptedAI +{ + mob_pure_energyAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + + void JustDied(Unit* slayer) + { + if (Unit *temp = me->GetOwner()) + { + if (temp && temp->isAlive()) + slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID()); + } + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + void AttackStart(Unit * /*who*/) {} +}; + +CreatureAI* GetAI_mob_pure_energy(Creature* pCreature) +{ + return new mob_pure_energyAI (pCreature); +}; + +void AddSC_boss_vexallus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_vexallus"; + newscript->GetAI = &GetAI_boss_vexallus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_pure_energy"; + newscript->GetAI = &GetAI_mob_pure_energy; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp new file mode 100644 index 00000000000..455c03739bc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Magisters_Terrace +SD%Complete: 60 +SDComment: Designed only for Selin Fireheart +SDCategory: Magister's Terrace +EndScriptData */ + +#include "ScriptedPch.h" +#include "magisters_terrace.h" + +#define MAX_ENCOUNTER 4 + +/* +0 - Selin Fireheart +1 - Vexallus +2 - Priestess Delrissa +3 - Kael'thas Sunstrider +*/ + +struct instance_magisters_terrace : public ScriptedInstance +{ + instance_magisters_terrace(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 DelrissaDeathCount; + + std::list FelCrystals; + std::list::const_iterator CrystalItr; + + uint64 SelinGUID; + uint64 DelrissaGUID; + uint64 VexallusDoorGUID; + uint64 SelinDoorGUID; + uint64 SelinEncounterDoorGUID; + uint64 DelrissaDoorGUID; + uint64 KaelDoorGUID; + uint64 KaelStatue[2]; + + bool InitializedItr; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + FelCrystals.clear(); + + DelrissaDeathCount = 0; + + SelinGUID = 0; + DelrissaGUID = 0; + VexallusDoorGUID = 0; + SelinDoorGUID = 0; + SelinEncounterDoorGUID = 0; + DelrissaDoorGUID = 0; + KaelDoorGUID = 0; + KaelStatue[0] = 0; + KaelStatue[1] = 0; + + InitializedItr = false; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + return false; + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_SELIN_EVENT: return m_auiEncounter[0]; + case DATA_VEXALLUS_EVENT: return m_auiEncounter[1]; + case DATA_DELRISSA_EVENT: return m_auiEncounter[2]; + case DATA_KAELTHAS_EVENT: return m_auiEncounter[3]; + case DATA_DELRISSA_DEATH_COUNT: return DelrissaDeathCount; + case DATA_FEL_CRYSTAL_SIZE: return FelCrystals.size(); + } + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch(identifier) + { + case DATA_SELIN_EVENT: m_auiEncounter[0] = data; break; + case DATA_VEXALLUS_EVENT: + if (data == DONE) + DoUseDoorOrButton(VexallusDoorGUID); + m_auiEncounter[1] = data; + break; + case DATA_DELRISSA_EVENT: + if (data == DONE) + DoUseDoorOrButton(DelrissaDoorGUID); + if (data == IN_PROGRESS) + DelrissaDeathCount = 0; + m_auiEncounter[2] = data; + break; + case DATA_KAELTHAS_EVENT: m_auiEncounter[3] = data; break; + + case DATA_DELRISSA_DEATH_COUNT: + if (data == SPECIAL) + ++DelrissaDeathCount; + else + DelrissaDeathCount = 0; + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 24723: SelinGUID = pCreature->GetGUID(); break; + case 24560: DelrissaGUID = pCreature->GetGUID(); break; + case 24722: FelCrystals.push_back(pCreature->GetGUID()); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 187896: VexallusDoorGUID = pGo->GetGUID(); break; + //SunwellRaid Gate 02 + case 187979: SelinDoorGUID = pGo->GetGUID(); break; + //Assembly Chamber Door + case 188065: SelinEncounterDoorGUID = pGo->GetGUID(); break; + case 187770: DelrissaDoorGUID = pGo->GetGUID(); break; + case 188064: KaelDoorGUID = pGo->GetGUID(); break; + case 188165: KaelStatue[0] = pGo->GetGUID(); break; + case 188166: KaelStatue[1] = pGo->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_SELIN: return SelinGUID; + case DATA_DELRISSA: return DelrissaGUID; + case DATA_VEXALLUS_DOOR: return VexallusDoorGUID; + case DATA_SELIN_DOOR: return SelinDoorGUID; + case DATA_SELIN_ENCOUNTER_DOOR: return SelinEncounterDoorGUID; + case DATA_DELRISSA_DOOR: return DelrissaDoorGUID; + case DATA_KAEL_DOOR: return KaelDoorGUID; + case DATA_KAEL_STATUE_LEFT: return KaelStatue[0]; + case DATA_KAEL_STATUE_RIGHT: return KaelStatue[1]; + + case DATA_FEL_CRYSTAL: + { + if (FelCrystals.empty()) + { + error_log("TSCR: Magisters Terrace: No Fel Crystals loaded in Inst Data"); + return 0; + } + + if (!InitializedItr) + { + CrystalItr = FelCrystals.begin(); + InitializedItr = true; + } + + uint64 guid = *CrystalItr; + ++CrystalItr; + return guid; + } + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_magisters_terrace(Map* pMap) +{ + return new instance_magisters_terrace(pMap); +} + +void AddSC_instance_magisters_terrace() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_magisters_terrace"; + newscript->GetInstanceData = &GetInstanceData_instance_magisters_terrace; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp new file mode 100644 index 00000000000..e46da9cb1bf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Magisters_Terrace +SD%Complete: 100 +SDComment: Quest support: 11490(post-event) +SDCategory: Magisters Terrace +EndScriptData */ + +/* ContentData +npc_kalecgos +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_kalecgos +######*/ + +enum eEnums +{ + SPELL_TRANSFORM_TO_KAEL = 44670, + SPELL_ORB_KILL_CREDIT = 46307, + NPC_KAEL = 24848, //human form entry + POINT_ID_LAND = 1 +}; + +const float afKaelLandPoint[] = {225.045, -276.236, -5.434}; + +#define GOSSIP_ITEM_KAEL_1 "Who are you?" +#define GOSSIP_ITEM_KAEL_2 "What can we do to assist you?" +#define GOSSIP_ITEM_KAEL_3 "What brings you to the Sunwell?" +#define GOSSIP_ITEM_KAEL_4 "You're not alone here?" +#define GOSSIP_ITEM_KAEL_5 "What would Kil'jaeden want with a mortal woman?" + +// This is friendly keal that appear after used Orb. +// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is +struct npc_kalecgosAI : public ScriptedAI +{ + npc_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 m_uiTransformTimer; + + void Reset() + { + m_uiTransformTimer = 0; + + // we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here + if (me->GetEntry() != NPC_KAEL) + me->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (uiPointId == POINT_ID_LAND) + m_uiTransformTimer = MINUTE*IN_MILISECONDS; + } + + // some targeting issues with the spell, so use this workaround as temporary solution + void DoWorkaroundForQuestCredit() + { + Map* pMap = me->GetMap(); + + if (!pMap || pMap->IsHeroic()) + return; + + Map::PlayerList const &lList = pMap->GetPlayers(); + + if (lList.isEmpty()) + return; + + SpellEntry const* pSpell = GetSpellStore()->LookupEntry(SPELL_ORB_KILL_CREDIT); + + for (Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pSpell && pSpell->EffectMiscValue[0]) + pPlayer->KilledMonsterCredit(pSpell->EffectMiscValue[0], 0); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiTransformTimer) + { + if (m_uiTransformTimer <= uiDiff) + { + DoCast(me, SPELL_ORB_KILL_CREDIT, false); + DoWorkaroundForQuestCredit(); + + // Transform and update entry, now ready for quest/read gossip + DoCast(me, SPELL_TRANSFORM_TO_KAEL, false); + me->UpdateEntry(NPC_KAEL); + + m_uiTransformTimer = 0; + } else m_uiTransformTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_kalecgos(Creature* pCreature) +{ + return new npc_kalecgosAI(pCreature); +} + +bool GossipHello_npc_kalecgos(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(12498, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_kalecgos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(12500, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(12502, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(12606, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(12607, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->SEND_GOSSIP_MENU(12608, pCreature->GetGUID()); + break; + } + + return true; +} + +void AddSC_magisters_terrace() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_kalecgos"; + newscript->GetAI = &GetAI_npc_kalecgos; + newscript->pGossipHello = &GossipHello_npc_kalecgos; + newscript->pGossipSelect = &GossipSelect_npc_kalecgos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h new file mode 100644 index 00000000000..d6419ea409c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MAGISTERS_TERRACE_H +#define DEF_MAGISTERS_TERRACE_H + +#define DATA_SELIN_EVENT 1 +#define DATA_VEXALLUS_EVENT 2 +#define DATA_DELRISSA_EVENT 3 +#define DATA_KAELTHAS_EVENT 4 + +#define DATA_SELIN 5 +#define DATA_FEL_CRYSTAL 6 +#define DATA_FEL_CRYSTAL_SIZE 7 + +#define DATA_VEXALLUS_DOOR 8 +#define DATA_SELIN_DOOR 9 +#define DATA_DELRISSA 10 +#define DATA_DELRISSA_DOOR 11 +#define DATA_SELIN_ENCOUNTER_DOOR 12 + +#define DATA_KAEL_DOOR 13 +#define DATA_KAEL_STATUE_LEFT 14 +#define DATA_KAEL_STATUE_RIGHT 15 + +#define DATA_DELRISSA_DEATH_COUNT 16 + +#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy." +#endif + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_baron_geddon.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_baron_geddon.cpp new file mode 100644 index 00000000000..77c6fafa10a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_baron_geddon.cpp @@ -0,0 +1,107 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Baron_Geddon +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_SERVICE -1409000 + +#define SPELL_INFERNO 19695 +#define SPELL_IGNITEMANA 19659 +#define SPELL_LIVINGBOMB 20475 +#define SPELL_ARMAGEDDOM 20479 + +struct boss_baron_geddonAI : public ScriptedAI +{ + boss_baron_geddonAI(Creature *c) : ScriptedAI(c) {} + + uint32 Inferno_Timer; + uint32 IgniteMana_Timer; + uint32 LivingBomb_Timer; + + void Reset() + { + Inferno_Timer = 45000; //These times are probably wrong + IgniteMana_Timer = 30000; + LivingBomb_Timer = 35000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <2% hp cast Armageddom + if (me->GetHealth()*100 / me->GetMaxHealth() <= 2) + { + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_ARMAGEDDOM); + DoScriptText(EMOTE_SERVICE, me); + return; + } + + //Inferno_Timer + if (Inferno_Timer <= diff) + { + DoCast(me, SPELL_INFERNO); + Inferno_Timer = 45000; + } else Inferno_Timer -= diff; + + //IgniteMana_Timer + if (IgniteMana_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_IGNITEMANA); + + IgniteMana_Timer = 30000; + } else IgniteMana_Timer -= diff; + + //LivingBomb_Timer + if (LivingBomb_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LIVINGBOMB); + + LivingBomb_Timer = 35000; + } else LivingBomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_baron_geddon(Creature* pCreature) +{ + return new boss_baron_geddonAI (pCreature); +} + +void AddSC_boss_baron_geddon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_baron_geddon"; + newscript->GetAI = &GetAI_boss_baron_geddon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_garr.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_garr.cpp new file mode 100644 index 00000000000..75891cf8c43 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_garr.cpp @@ -0,0 +1,143 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Garr +SD%Complete: 50 +SDComment: Adds NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +// Garr spells +#define SPELL_ANTIMAGICPULSE 19492 +#define SPELL_MAGMASHACKLES 19496 +#define SPELL_ENRAGE 19516 //Stacking enrage (stacks to 10 times) + +//Add spells +#define SPELL_ERUPTION 19497 +#define SPELL_IMMOLATE 20294 + +struct boss_garrAI : public ScriptedAI +{ + boss_garrAI(Creature *c) : ScriptedAI(c) {} + + uint32 AntiMagicPulse_Timer; + uint32 MagmaShackles_Timer; + uint32 CheckAdds_Timer; + uint64 Add[8]; + bool Enraged[8]; + + void Reset() + { + AntiMagicPulse_Timer = 25000; //These times are probably wrong + MagmaShackles_Timer = 15000; + CheckAdds_Timer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //AntiMagicPulse_Timer + if (AntiMagicPulse_Timer <= diff) + { + DoCast(me, SPELL_ANTIMAGICPULSE); + AntiMagicPulse_Timer = 10000 + rand()%5000; + } else AntiMagicPulse_Timer -= diff; + + //MagmaShackles_Timer + if (MagmaShackles_Timer <= diff) + { + DoCast(me, SPELL_MAGMASHACKLES); + MagmaShackles_Timer = 8000 + rand()%4000; + } else MagmaShackles_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_fireswornAI : public ScriptedAI +{ + mob_fireswornAI(Creature *c) : ScriptedAI(c) {} + + uint32 Immolate_Timer; + + void Reset() + { + Immolate_Timer = 4000; //These times are probably wrong + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_IMMOLATE); + + Immolate_Timer = urand(5000,10000); + } else Immolate_Timer -= diff; + + //Cast Erruption and let them die + if (me->GetHealth() <= me->GetMaxHealth() * 0.10) + { + DoCast(me->getVictim(), SPELL_ERUPTION); + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_garr(Creature* pCreature) +{ + return new boss_garrAI (pCreature); +} + +CreatureAI* GetAI_mob_firesworn(Creature* pCreature) +{ + return new mob_fireswornAI (pCreature); +} + +void AddSC_boss_garr() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_garr"; + newscript->GetAI = &GetAI_boss_garr; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_firesworn"; + newscript->GetAI = &GetAI_mob_firesworn; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_gehennas.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_gehennas.cpp new file mode 100644 index 00000000000..9ebe69c0c4e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_gehennas.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gehennas +SD%Complete: 90 +SDComment: Adds MC NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWBOLT 19728 +#define SPELL_RAINOFFIRE 19717 +#define SPELL_GEHENNASCURSE 19716 + +struct boss_gehennasAI : public ScriptedAI +{ + boss_gehennasAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowBolt_Timer; + uint32 RainOfFire_Timer; + uint32 GehennasCurse_Timer; + + void Reset() + { + ShadowBolt_Timer = 6000; + RainOfFire_Timer = 10000; + GehennasCurse_Timer = 12000; + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_SHADOWBOLT); + + ShadowBolt_Timer = 7000; + } else ShadowBolt_Timer -= diff; + + //RainOfFire_Timer + if (RainOfFire_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_RAINOFFIRE); + + RainOfFire_Timer = urand(4000,12000); + } else RainOfFire_Timer -= diff; + + //GehennasCurse_Timer + if (GehennasCurse_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GEHENNASCURSE); + GehennasCurse_Timer = urand(22000,30000); + } else GehennasCurse_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gehennas(Creature* pCreature) +{ + return new boss_gehennasAI (pCreature); +} + +void AddSC_boss_gehennas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gehennas"; + newscript->GetAI = &GetAI_boss_gehennas; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp new file mode 100644 index 00000000000..2aba378d399 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_golemagg.cpp @@ -0,0 +1,198 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Golemagg +SD%Complete: 90 +SDComment: Timers need to be confirmed, Golemagg's Trust need to be checked +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" +#include "molten_core.h" + +enum eEnums +{ + SPELL_MAGMASPLASH = 13879, + SPELL_PYROBLAST = 20228, + SPELL_EARTHQUAKE = 19798, + SPELL_ENRAGE = 19953, + SPELL_GOLEMAGG_TRUST = 20553, + + // Core Rager + EMOTE_LOWHP = -1409002, + SPELL_MANGLE = 19820 +}; + +struct boss_golemaggAI : public ScriptedAI +{ + boss_golemaggAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiPyroblastTimer; + uint32 m_uiEarthquakeTimer; + uint32 m_uiBuffTimer; + bool m_bEnraged; + + void Reset() + { + m_uiPyroblastTimer = 7*IN_MILISECONDS; // These timers are probably wrong + m_uiEarthquakeTimer = 3*IN_MILISECONDS; + m_uiBuffTimer = 2.5*IN_MILISECONDS; + m_bEnraged = false; + + DoCast(me, SPELL_MAGMASPLASH, true); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance) + m_pInstance->SetData(DATA_GOLEMAGG_DEATH, 0); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //Pyroblast + if (m_uiPyroblastTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_PYROBLAST); + + m_uiPyroblastTimer = 7*IN_MILISECONDS; + } + else + m_uiPyroblastTimer -= uiDiff; + + // Enrage + if (!m_bEnraged && me->GetHealth()*100 < me->GetMaxHealth()*10) + { + DoCast(me, SPELL_ENRAGE); + m_bEnraged = true; + } + + // Earthquake + if (m_bEnraged) + { + if (m_uiEarthquakeTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_EARTHQUAKE); + m_uiEarthquakeTimer = 3*IN_MILISECONDS; + } + else + m_uiEarthquakeTimer -= uiDiff; + } + + /* + // Golemagg's Trust + if (m_uiBuffTimer <= uidiff) + { + DoCast(me, SPELL_GOLEMAGG_TRUST); + m_uiBuffTimer = 2.5*IN_MILISECONDS; + } + else + m_uiBuffTimer -= uiDiff; + */ + + DoMeleeAttackIfReady(); + } +}; + +struct mob_core_ragerAI : public ScriptedAI +{ + mob_core_ragerAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiMangleTimer; + + void Reset() + { + m_uiMangleTimer = 7*IN_MILISECONDS; // These times are probably wrong + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) + { + if (me->GetHealth()*100 < me->GetMaxHealth()*50) + { + if (m_pInstance) + { + if (Creature* pGolemagg = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_GOLEMAGG))) + { + if (pGolemagg->isAlive()) + { + DoScriptText(EMOTE_LOWHP, me); + me->SetHealth(me->GetMaxHealth()); + } + else + uiDamage = me->GetHealth(); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + // Mangle + if (m_uiMangleTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MANGLE); + m_uiMangleTimer = 10*IN_MILISECONDS; + } + else + m_uiMangleTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_golemagg(Creature* pCreature) +{ + return new boss_golemaggAI (pCreature); +} + +CreatureAI* GetAI_mob_core_rager(Creature* pCreature) +{ + return new mob_core_ragerAI (pCreature); +} + +void AddSC_boss_golemagg() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_golemagg"; + newscript->GetAI = &GetAI_boss_golemagg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_core_rager"; + newscript->GetAI = &GetAI_mob_core_rager; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_lucifron.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_lucifron.cpp new file mode 100644 index 00000000000..50601f04147 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_lucifron.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lucifron +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_IMPENDINGDOOM 19702 +#define SPELL_LUCIFRONCURSE 19703 +#define SPELL_SHADOWSHOCK 20603 + +struct boss_lucifronAI : public ScriptedAI +{ + boss_lucifronAI(Creature *c) : ScriptedAI(c) {} + + uint32 ImpendingDoom_Timer; + uint32 LucifronCurse_Timer; + uint32 ShadowShock_Timer; + + void Reset() + { + ImpendingDoom_Timer = 10000; //Initial cast after 10 seconds so the debuffs alternate + LucifronCurse_Timer = 20000; //Initial cast after 20 seconds + ShadowShock_Timer = 6000; //6 seconds + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Impending doom timer + if (ImpendingDoom_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_IMPENDINGDOOM); + ImpendingDoom_Timer = 20000; + } else ImpendingDoom_Timer -= diff; + + //Lucifron's curse timer + if (LucifronCurse_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LUCIFRONCURSE); + LucifronCurse_Timer = 15000; + } else LucifronCurse_Timer -= diff; + + //Shadowshock + if (ShadowShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWSHOCK); + ShadowShock_Timer = 6000; + } else ShadowShock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lucifron(Creature* pCreature) +{ + return new boss_lucifronAI (pCreature); +} + +void AddSC_boss_lucifron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lucifron"; + newscript->GetAI = &GetAI_boss_lucifron; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_magmadar.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_magmadar.cpp new file mode 100644 index 00000000000..f612003b076 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_magmadar.cpp @@ -0,0 +1,100 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Magmadar +SD%Complete: 75 +SDComment: Conflag on ground nyi, fear causes issues without VMAPs +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_FRENZY -1409001 + +#define SPELL_FRENZY 19451 +#define SPELL_MAGMASPIT 19449 //This is actually a buff he gives himself +#define SPELL_PANIC 19408 +#define SPELL_LAVABOMB 19411 //This calls a dummy server side effect that isn't implemented yet +#define SPELL_LAVABOMB_ALT 19428 //This is the spell that the lava bomb casts + +struct boss_magmadarAI : public ScriptedAI +{ + boss_magmadarAI(Creature *c) : ScriptedAI(c) {} + + uint32 Frenzy_Timer; + uint32 Panic_Timer; + uint32 Lavabomb_Timer; + + void Reset() + { + Frenzy_Timer = 30000; + Panic_Timer = 20000; + Lavabomb_Timer = 12000; + + DoCast(me, SPELL_MAGMASPIT, true); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Frenzy_Timer + if (Frenzy_Timer <= diff) + { + DoScriptText(EMOTE_FRENZY, me); + DoCast(me, SPELL_FRENZY); + Frenzy_Timer = 15000; + } else Frenzy_Timer -= diff; + + //Panic_Timer + if (Panic_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PANIC); + Panic_Timer = 35000; + } else Panic_Timer -= diff; + + //Lavabomb_Timer + if (Lavabomb_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LAVABOMB_ALT); + + Lavabomb_Timer = 12000; + } else Lavabomb_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_magmadar(Creature* pCreature) +{ + return new boss_magmadarAI (pCreature); +} + +void AddSC_boss_magmadar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magmadar"; + newscript->GetAI = &GetAI_boss_magmadar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_majordomo_executus.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_majordomo_executus.cpp new file mode 100644 index 00000000000..11ae70befcf --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_majordomo_executus.cpp @@ -0,0 +1,134 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Majordomo_Executus +SD%Complete: 30 +SDComment: Correct spawning and Event NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1409003 +#define SAY_SPAWN -1409004 +#define SAY_SLAY -1409005 +#define SAY_SPECIAL -1409006 +#define SAY_DEFEAT -1409007 + +#define SAY_SUMMON_MAJ -1409008 +#define SAY_ARRIVAL1_RAG -1409009 +#define SAY_ARRIVAL2_MAJ -1409010 +#define SAY_ARRIVAL3_RAG -1409011 +#define SAY_ARRIVAL5_RAG -1409012 + +#define SPAWN_RAG_X 838.51 +#define SPAWN_RAG_Y -829.84 +#define SPAWN_RAG_Z -232.00 +#define SPAWN_RAG_O 1.70 + +#define SPELL_MAGIC_REFLECTION 20619 +#define SPELL_DAMAGE_REFLECTION 21075 + +#define SPELL_BLASTWAVE 20229 +#define SPELL_AEGIS 20620 //This is self casted whenever we are below 50% +#define SPELL_TELEPORT 20618 +#define SPELL_SUMMON_RAGNAROS 19774 + +#define ENTRY_FLAMEWALKER_HEALER 11663 +#define ENTRY_FLAMEWALKER_ELITE 11664 + +struct boss_majordomoAI : public ScriptedAI +{ + boss_majordomoAI(Creature *c) : ScriptedAI(c) {} + + uint32 MagicReflection_Timer; + uint32 DamageReflection_Timer; + uint32 Blastwave_Timer; + + void Reset() + { + MagicReflection_Timer = 30000; //Damage reflection first so we alternate + DamageReflection_Timer = 15000; + Blastwave_Timer = 10000; + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%5) + return; + + DoScriptText(SAY_SLAY, me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Cast Ageis if less than 50% hp + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + DoCast(me, SPELL_AEGIS); + } + + //MagicReflection_Timer + // if (MagicReflection_Timer <= diff) + // { + // DoCast(me, SPELL_MAGICREFLECTION); + + //60 seconds until we should cast this agian + // MagicReflection_Timer = 30000; + // } else MagicReflection_Timer -= diff; + + //DamageReflection_Timer + // if (DamageReflection_Timer <= diff) + // { + // DoCast(me, SPELL_DAMAGEREFLECTION); + + //60 seconds until we should cast this agian + // DamageReflection_Timer = 30000; + // } else DamageReflection_Timer -= diff; + + //Blastwave_Timer + if (Blastwave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLASTWAVE); + Blastwave_Timer = 10000; + } else Blastwave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_majordomo(Creature* pCreature) +{ + return new boss_majordomoAI (pCreature); +} + +void AddSC_boss_majordomo() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_majordomo"; + newscript->GetAI = &GetAI_boss_majordomo; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_ragnaros.cpp new file mode 100644 index 00000000000..71c0b40de3f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_ragnaros.cpp @@ -0,0 +1,297 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ragnaros +SD%Complete: 75 +SDComment: Intro Dialog and event NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_REINFORCEMENTS1 -1409013 +#define SAY_REINFORCEMENTS2 -1409014 +#define SAY_HAND -1409015 +#define SAY_WRATH -1409016 +#define SAY_KILL -1409017 +#define SAY_MAGMABURST -1409018 + +#define SPELL_HANDOFRAGNAROS 19780 +#define SPELL_WRATHOFRAGNAROS 20566 +#define SPELL_LAVABURST 21158 + +#define SPELL_MAGMABURST 20565 //Ranged attack + +#define SPELL_SONSOFFLAME_DUMMY 21108 //Server side effect +#define SPELL_RAGSUBMERGE 21107 //Stealth aura +#define SPELL_RAGEMERGE 20568 +#define SPELL_MELTWEAPON 21388 +#define SPELL_ELEMENTALFIRE 20564 +#define SPELL_ERRUPTION 17731 + +#define ADD_1X 848.740356 +#define ADD_1Y -816.103455 +#define ADD_1Z -229.74327 +#define ADD_1O 2.615287 + +#define ADD_2X 852.560791 +#define ADD_2Y -849.861511 +#define ADD_2Z -228.560974 +#define ADD_2O 2.836073 + +#define ADD_3X 808.710632 +#define ADD_3Y -852.845764 +#define ADD_3Z -227.914963 +#define ADD_3O 0.964207 + +#define ADD_4X 786.597107 +#define ADD_4Y -821.132874 +#define ADD_4Z -226.350128 +#define ADD_4O 0.949377 + +#define ADD_5X 796.219116 +#define ADD_5Y -800.948059 +#define ADD_5Z -226.010361 +#define ADD_5O 0.560603 + +#define ADD_6X 821.602539 +#define ADD_6Y -782.744109 +#define ADD_6Z -226.023575 +#define ADD_6O 6.157440 + +#define ADD_7X 844.924744 +#define ADD_7Y -769.453735 +#define ADD_7Z -225.521698 +#define ADD_7O 4.4539958 + +#define ADD_8X 839.823364 +#define ADD_8Y -810.869385 +#define ADD_8Z -229.683182 +#define ADD_8O 4.693108 + +struct boss_ragnarosAI : public ScriptedAI +{ + boss_ragnarosAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 WrathOfRagnaros_Timer; + uint32 HandOfRagnaros_Timer; + uint32 LavaBurst_Timer; + uint32 MagmaBurst_Timer; + uint32 ElementalFire_Timer; + uint32 Erruption_Timer; + uint32 Submerge_Timer; + uint32 Attack_Timer; + + bool HasYelledMagmaBurst; + bool HasSubmergedOnce; + bool WasBanished; + bool HasAura; + + void Reset() + { + WrathOfRagnaros_Timer = 30000; + HandOfRagnaros_Timer = 25000; + LavaBurst_Timer = 10000; + MagmaBurst_Timer = 2000; + Erruption_Timer = 15000; + ElementalFire_Timer = 3000; + Submerge_Timer = 180000; + Attack_Timer = 90000; + HasYelledMagmaBurst = false; + HasSubmergedOnce = false; + WasBanished = false; + + DoCast(me, SPELL_MELTWEAPON, true); + HasAura = true; + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%5) + return; + + DoScriptText(SAY_KILL, me); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (WasBanished && Attack_Timer <= diff) + { + //Become unbanished again + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_RAGEMERGE); + WasBanished = false; + } else if (WasBanished) + { + Attack_Timer -= diff; + //Do nothing while banished + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //WrathOfRagnaros_Timer + if (WrathOfRagnaros_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WRATHOFRAGNAROS); + + if (urand(0,1)) + DoScriptText(SAY_WRATH, me); + + WrathOfRagnaros_Timer = 30000; + } else WrathOfRagnaros_Timer -= diff; + + //HandOfRagnaros_Timer + if (HandOfRagnaros_Timer <= diff) + { + DoCast(me, SPELL_HANDOFRAGNAROS); + + if (urand(0,1)) + DoScriptText(SAY_HAND, me); + + HandOfRagnaros_Timer = 25000; + } else HandOfRagnaros_Timer -= diff; + + //LavaBurst_Timer + if (LavaBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LAVABURST); + LavaBurst_Timer = 10000; + } else LavaBurst_Timer -= diff; + + //Erruption_Timer + if (LavaBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ERRUPTION); + Erruption_Timer = urand(20000,45000); + } else Erruption_Timer -= diff; + + //ElementalFire_Timer + if (ElementalFire_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ELEMENTALFIRE); + ElementalFire_Timer = urand(10000,14000); + } else ElementalFire_Timer -= diff; + + //Submerge_Timer + if (!WasBanished && Submerge_Timer <= diff) + { + //Creature spawning and ragnaros becomming unattackable + //is not very well supported in the core + //so added normaly spawning and banish workaround and attack again after 90 secs. + + me->InterruptNonMeleeSpells(false); + //Root self + DoCast(me, 23973); + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + + if (!HasSubmergedOnce) + { + DoScriptText(SAY_REINFORCEMENTS1, me); + + // summon 10 elementals + for (uint8 i = 0; i < 9; ++i) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (Creature* pSummoned = me->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000)) + pSummoned->AI()->AttackStart(pTarget); + } + } + + HasSubmergedOnce = true; + WasBanished = true; + DoCast(me, SPELL_RAGSUBMERGE); + Attack_Timer = 90000; + + } + else + { + DoScriptText(SAY_REINFORCEMENTS2, me); + + for (uint8 i = 0; i < 9; ++i) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (Creature* pSummoned = me->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000)) + pSummoned->AI()->AttackStart(pTarget); + } + } + + WasBanished = true; + DoCast(me, SPELL_RAGSUBMERGE); + Attack_Timer = 90000; + } + + Submerge_Timer = 180000; + } else Submerge_Timer -= diff; + + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + //Make sure our attack is ready and we arn't currently casting + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + else + { + //MagmaBurst_Timer + if (MagmaBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MAGMABURST); + + if (!HasYelledMagmaBurst) + { + //Say our dialog + DoScriptText(SAY_MAGMABURST, me); + HasYelledMagmaBurst = true; + } + + MagmaBurst_Timer = 2500; + } else MagmaBurst_Timer -= diff; + } + } +}; +CreatureAI* GetAI_boss_ragnaros(Creature* pCreature) +{ + return new boss_ragnarosAI (pCreature); +} + +void AddSC_boss_ragnaros() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ragnaros"; + newscript->GetAI = &GetAI_boss_ragnaros; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_shazzrah.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_shazzrah.cpp new file mode 100644 index 00000000000..4b0774cdc54 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_shazzrah.cpp @@ -0,0 +1,121 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shazzrah +SD%Complete: 75 +SDComment: Teleport NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_ARCANEEXPLOSION 19712 +#define SPELL_SHAZZRAHCURSE 19713 +#define SPELL_DEADENMAGIC 19714 +#define SPELL_COUNTERSPELL 19715 + +struct boss_shazzrahAI : public ScriptedAI +{ + boss_shazzrahAI(Creature *c) : ScriptedAI(c) {} + + uint32 ArcaneExplosion_Timer; + uint32 ShazzrahCurse_Timer; + uint32 DeadenMagic_Timer; + uint32 Countspell_Timer; + uint32 Blink_Timer; + + void Reset() + { + ArcaneExplosion_Timer = 6000; //These times are probably wrong + ShazzrahCurse_Timer = 10000; + DeadenMagic_Timer = 24000; + Countspell_Timer = 15000; + Blink_Timer = 30000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANEEXPLOSION); + ArcaneExplosion_Timer = 5000 + rand()%4000; + } else ArcaneExplosion_Timer -= diff; + + //ShazzrahCurse_Timer + if (ShazzrahCurse_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_SHAZZRAHCURSE); + + ShazzrahCurse_Timer = 25000 + rand()%5000; + } else ShazzrahCurse_Timer -= diff; + + //DeadenMagic_Timer + if (DeadenMagic_Timer <= diff) + { + DoCast(me, SPELL_DEADENMAGIC); + DeadenMagic_Timer = 35000; + } else DeadenMagic_Timer -= diff; + + //Countspell_Timer + if (Countspell_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_COUNTERSPELL); + Countspell_Timer = 16000 + rand()%4000; + } else Countspell_Timer -= diff; + + //Blink_Timer + if (Blink_Timer <= diff) + { + // Teleporting him to a random gamer and casting Arcane Explosion after that. + // Blink is not working cause of LoS System we need to do this hardcoded. + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0, 100, true)) + { + DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); + DoCast(pTarget, SPELL_ARCANEEXPLOSION); + DoResetThreat(); + } + + Blink_Timer = 45000; + } else Blink_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_shazzrah(Creature* pCreature) +{ + return new boss_shazzrahAI (pCreature); +} + +void AddSC_boss_shazzrah() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shazzrah"; + newscript->GetAI = &GetAI_boss_shazzrah; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp new file mode 100644 index 00000000000..83288fe003b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/boss_sulfuron_harbinger.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Sulfuron_Harbringer +SD%Complete: 80 +SDComment: Adds NYI +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" +#include "molten_core.h" + +#define SPELL_DARKSTRIKE 19777 +#define SPELL_DEMORALIZINGSHOUT 19778 +#define SPELL_INSPIRE 19779 +#define SPELL_KNOCKDOWN 19780 +#define SPELL_FLAMESPEAR 19781 + +//Adds Spells +#define SPELL_HEAL 19775 +#define SPELL_SHADOWWORDPAIN 19776 +#define SPELL_IMMOLATE 20294 + +struct boss_sulfuronAI : public ScriptedAI +{ + boss_sulfuronAI(Creature *c) : ScriptedAI(c) {} + + uint32 Darkstrike_Timer; + uint32 DemoralizingShout_Timer; + uint32 Inspire_Timer; + uint32 Knockdown_Timer; + uint32 Flamespear_Timer; + + void Reset() + { + Darkstrike_Timer=10000; //These times are probably wrong + DemoralizingShout_Timer = 15000; + Inspire_Timer = 13000; + Knockdown_Timer = 6000; + Flamespear_Timer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //DemoralizingShout_Timer + if (DemoralizingShout_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DEMORALIZINGSHOUT); + DemoralizingShout_Timer = 15000 + rand()%5000; + } else DemoralizingShout_Timer -= diff; + + //Inspire_Timer + if (Inspire_Timer <= diff) + { + Creature *pTarget = NULL; + std::list pList = DoFindFriendlyMissingBuff(45.0f,SPELL_INSPIRE); + if (!pList.empty()) + { + std::list::const_iterator i = pList.begin(); + advance(i, (rand()%pList.size())); + pTarget = (*i); + } + + if (pTarget) + DoCast(pTarget, SPELL_INSPIRE); + + DoCast(me, SPELL_INSPIRE); + + Inspire_Timer = 20000 + rand()%6000; + } else Inspire_Timer -= diff; + + //Knockdown_Timer + if (Knockdown_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + Knockdown_Timer = 12000 + rand()%3000; + } else Knockdown_Timer -= diff; + + //Flamespear_Timer + if (Flamespear_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_FLAMESPEAR); + + Flamespear_Timer = 12000 + rand()%4000; + } else Flamespear_Timer -= diff; + + //DarkStrike_Timer + if (Darkstrike_Timer <= diff) + { + DoCast(me, SPELL_DARKSTRIKE); + Darkstrike_Timer = 15000 + rand()%3000; + } else Darkstrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_flamewaker_priestAI : public ScriptedAI +{ + mob_flamewaker_priestAI(Creature *c) : ScriptedAI(c) {} + + uint32 Heal_Timer; + uint32 ShadowWordPain_Timer; + uint32 Immolate_Timer; + + void Reset() + { + Heal_Timer = 15000+rand()%15000; + ShadowWordPain_Timer = 2000; + Immolate_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Casting Heal to Sulfuron or other Guards. + if (Heal_Timer <= diff) + { + Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1); + if (!pUnit) + return; + + DoCast(pUnit, SPELL_HEAL); + + Heal_Timer = 15000+rand()%5000; + } else Heal_Timer -= diff; + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_SHADOWWORDPAIN); + + ShadowWordPain_Timer = 18000+rand()%8000; + } else ShadowWordPain_Timer -= diff; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); + + Immolate_Timer = 15000+rand()%10000; + } else Immolate_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_sulfuron(Creature* pCreature) +{ + return new boss_sulfuronAI (pCreature); +} + +CreatureAI* GetAI_mob_flamewaker_priest(Creature* pCreature) +{ + return new mob_flamewaker_priestAI (pCreature); +} + +void AddSC_boss_sulfuron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sulfuron"; + newscript->GetAI = &GetAI_boss_sulfuron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flamewaker_priest"; + newscript->GetAI = &GetAI_mob_flamewaker_priest; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/instance_molten_core.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/instance_molten_core.cpp new file mode 100644 index 00000000000..eb79c234134 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/instance_molten_core.cpp @@ -0,0 +1,266 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Molten_Core +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Molten Core +EndScriptData */ + +#include "ScriptedPch.h" +#include "molten_core.h" + +#define MAX_ENCOUNTER 9 + +#define ID_LUCIFRON 12118 +#define ID_MAGMADAR 11982 +#define ID_GEHENNAS 12259 +#define ID_GARR 12057 +#define ID_GEDDON 12056 +#define ID_SHAZZRAH 12264 +#define ID_GOLEMAGG 11988 +#define ID_SULFURON 12098 +#define ID_DOMO 12018 +#define ID_RAGNAROS 11502 +#define ID_FLAMEWAKERPRIEST 11662 + +struct instance_molten_core : public ScriptedInstance +{ + instance_molten_core(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 Lucifron, Magmadar, Gehennas, Garr, Geddon, Shazzrah, Sulfuron, Golemagg, Domo, Ragnaros, FlamewakerPriest; + uint64 RuneKoro, RuneZeth, RuneMazj, RuneTheri, RuneBlaz, RuneKress, RuneMohn, m_uiFirelordCacheGUID; + + //If all Bosses are dead. + bool IsBossDied[9]; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Lucifron = 0; + Magmadar = 0; + Gehennas = 0; + Garr = 0; + Geddon = 0; + Shazzrah = 0; + Sulfuron = 0; + Golemagg = 0; + Domo = 0; + Ragnaros = 0; + FlamewakerPriest = 0; + + RuneKoro = 0; + RuneZeth = 0; + RuneMazj = 0; + RuneTheri = 0; + RuneBlaz = 0; + RuneKress = 0; + RuneMohn = 0; + + m_uiFirelordCacheGUID = 0; + + IsBossDied[0] = false; + IsBossDied[1] = false; + IsBossDied[2] = false; + IsBossDied[3] = false; + IsBossDied[4] = false; + IsBossDied[5] = false; + IsBossDied[6] = false; + + IsBossDied[7] = false; + IsBossDied[8] = false; + } + + bool IsEncounterInProgress() const + { + return false; + }; + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 176951: //Sulfuron + RuneKoro = pGo->GetGUID(); + break; + case 176952: //Geddon + RuneZeth = pGo->GetGUID(); + break; + case 176953: //Shazzrah + RuneMazj = pGo->GetGUID(); + break; + case 176954: //Golemagg + RuneTheri = pGo->GetGUID(); + break; + case 176955: //Garr + RuneBlaz = pGo->GetGUID(); + break; + case 176956: //Magmadar + RuneKress = pGo->GetGUID(); + break; + case 176957: //Gehennas + RuneMohn = pGo->GetGUID(); + break; + case 179703: + m_uiFirelordCacheGUID = pGo->GetGUID(); //when majordomo event == DONE DoRespawnGameObject(m_uiFirelordCacheGUID,); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case ID_LUCIFRON: + Lucifron = pCreature->GetGUID(); + break; + + case ID_MAGMADAR: + Magmadar = pCreature->GetGUID(); + break; + + case ID_GEHENNAS: + Gehennas = pCreature->GetGUID(); + break; + + case ID_GARR: + Garr = pCreature->GetGUID(); + break; + + case ID_GEDDON: + Geddon = pCreature->GetGUID(); + break; + + case ID_SHAZZRAH: + Shazzrah = pCreature->GetGUID(); + break; + + case ID_SULFURON: + Sulfuron = pCreature->GetGUID(); + break; + + case ID_GOLEMAGG: + Golemagg = pCreature->GetGUID(); + break; + + case ID_DOMO: + Domo = pCreature->GetGUID(); + break; + + case ID_RAGNAROS: + Ragnaros = pCreature->GetGUID(); + break; + + case ID_FLAMEWAKERPRIEST: + FlamewakerPriest = pCreature->GetGUID(); + break; + } + } + + uint64 GetData64 (uint32 identifier) + { + switch(identifier) + { + case DATA_SULFURON: + return Sulfuron; + case DATA_GOLEMAGG: + return Golemagg; + + case DATA_FLAMEWAKERPRIEST: + return FlamewakerPriest; + } + + return 0; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_LUCIFRONISDEAD: + if (IsBossDied[0]) + return 1; + break; + + case DATA_MAGMADARISDEAD: + if (IsBossDied[1]) + return 1; + break; + + case DATA_GEHENNASISDEAD: + if (IsBossDied[2]) + return 1; + break; + + case DATA_GARRISDEAD: + if (IsBossDied[3]) + return 1; + break; + + case DATA_GEDDONISDEAD: + if (IsBossDied[4]) + return 1; + break; + + case DATA_SHAZZRAHISDEAD: + if (IsBossDied[5]) + return 1; + break; + + case DATA_SULFURONISDEAD: + if (IsBossDied[6]) + return 1; + break; + + case DATA_GOLEMAGGISDEAD: + if (IsBossDied[7]) + return 1; + break; + + case DATA_MAJORDOMOISDEAD: + if (IsBossDied[8]) + return 1; + break; + } + + return 0; + } + + void SetData(uint32 type, uint32 /*data*/) + { + if (type == DATA_GOLEMAGG_DEATH) + IsBossDied[7] = true; + } +}; + +InstanceData* GetInstance_instance_molten_core(Map* pMap) +{ + return new instance_molten_core (pMap); +} + +void AddSC_instance_molten_core() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_molten_core"; + newscript->GetInstanceData = &GetInstance_instance_molten_core; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/molten_core.cpp b/src/server/scripts/EasternKingdoms/MoltenCore/molten_core.cpp new file mode 100644 index 00000000000..f8fe5bf1477 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/molten_core.cpp @@ -0,0 +1,81 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Molten_Core +SD%Complete: 100 +SDComment: +SDCategory: Molten Core +EndScriptData */ + +/* ContentData +mob_ancient_core_hound +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedSimpleAI.h" + +#define SPELL_CONE_OF_FIRE 19630 +#define SPELL_BITE 19771 + +//Random Debuff (each hound has only one of these) +#define SPELL_GROUND_STOMP 19364 +#define SPELL_ANCIENT_DREAD 19365 +#define SPELL_CAUTERIZING_FLAMES 19366 +#define SPELL_WITHERING_HEAT 19367 +#define SPELL_ANCIENT_DESPAIR 19369 +#define SPELL_ANCIENT_HYSTERIA 19372 + +CreatureAI* GetAI_mob_ancient_core_hound(Creature* pCreature) +{ + SimpleAI *ai = new SimpleAI(pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_CONE_OF_FIRE; + ai->Spell[0].Cooldown = 7000; + ai->Spell[0].First_Cast = 10000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + uint32 RandDebuff = RAND(SPELL_GROUND_STOMP,SPELL_ANCIENT_DREAD,SPELL_CAUTERIZING_FLAMES, + SPELL_WITHERING_HEAT,SPELL_ANCIENT_DESPAIR,SPELL_ANCIENT_HYSTERIA); + + ai->Spell[1].Enabled = true; + ai->Spell[1].Spell_Id = RandDebuff; + ai->Spell[1].Cooldown = 24000; + ai->Spell[1].First_Cast = 15000; + ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->Spell[2].Enabled = true; + ai->Spell[2].Spell_Id = SPELL_BITE; + ai->Spell[2].Cooldown = 6000; + ai->Spell[2].First_Cast = 4000; + ai->Spell[2].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->EnterEvadeMode(); + + return ai; +} + +void AddSC_molten_core() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_ancient_core_hound"; + newscript->GetAI = &GetAI_mob_ancient_core_hound; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/MoltenCore/molten_core.h b/src/server/scripts/EasternKingdoms/MoltenCore/molten_core.h new file mode 100644 index 00000000000..5874d8b9408 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/MoltenCore/molten_core.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MOLTEN_CORE_H +#define DEF_MOLTEN_CORE_H + +#define DATA_FLAMEWAKERPRIEST 1 +#define DATA_GARRISDEAD 2 +#define DATA_GEDDONISDEAD 3 +#define DATA_GEHENNASISDEAD 4 +#define DATA_GOLEMAGGISDEAD 5 +#define DATA_GOLEMAGG_DEATH 6 +#define DATA_LUCIFRONISDEAD 7 +#define DATA_MAGMADARISDEAD 8 +#define DATA_MAJORDOMOISDEAD 9 +#define DATA_SHAZZRAHISDEAD 10 +#define DATA_SULFURON 11 +#define DATA_SULFURONISDEAD 12 +#define DATA_GOLEMAGG 13 +#endif + diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp new file mode 100644 index 00000000000..bdbf6b7c081 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -0,0 +1,1079 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "Vehicle.h" +#include "ObjectMgr.h" +#include "ScriptedEscortAI.h" + +/*###### +##Quest 12848 +######*/ + +#define GCD_CAST 1 + +enum eDeathKnightSpells +{ + SPELL_SOUL_PRISON_CHAIN_SELF = 54612, + SPELL_SOUL_PRISON_CHAIN = 54613, + SPELL_DK_INITIATE_VISUAL = 51519, + + SPELL_ICY_TOUCH = 52372, + SPELL_PLAGUE_STRIKE = 52373, + SPELL_BLOOD_STRIKE = 52374, + SPELL_DEATH_COIL = 52375 +}; + +#define EVENT_ICY_TOUCH 1 +#define EVENT_PLAGUE_STRIKE 2 +#define EVENT_BLOOD_STRIKE 3 +#define EVENT_DEATH_COIL 4 + +//used by 29519,29520,29565,29566,29567 but signed for 29519 +int32 say_event_start[8] = +{ + -1609000,-1609001,-1609002,-1609003, + -1609004,-1609005,-1609006,-1609007 +}; + +int32 say_event_attack[9] = +{ + -1609008,-1609009,-1609010,-1609011,-1609012, + -1609013,-1609014,-1609015,-1609016 +}; + +uint32 acherus_soul_prison[12] = +{ + 191577, + 191580, + 191581, + 191582, + 191583, + 191584, + 191585, + 191586, + 191587, + 191588, + 191589, + 191590 +}; + +uint32 acherus_unworthy_initiate[5] = +{ + 29519, + 29520, + 29565, + 29566, + 29567 +}; + +enum UnworthyInitiatePhase +{ + PHASE_CHAINED, + PHASE_TO_EQUIP, + PHASE_EQUIPING, + PHASE_TO_ATTACK, + PHASE_ATTACKING, +}; + +struct npc_unworthy_initiateAI : public ScriptedAI +{ + npc_unworthy_initiateAI(Creature *c) : ScriptedAI(c) + { + me->SetReactState(REACT_PASSIVE); + if (!me->GetEquipmentId()) + if (const CreatureInfo *info = GetCreatureInfo(28406)) + if (info->equipmentId) + const_cast(me->GetCreatureInfo())->equipmentId = info->equipmentId; + } + + uint64 playerGUID; + UnworthyInitiatePhase phase; + uint32 wait_timer; + float anchorX, anchorY; + uint64 anchorGUID; + + EventMap events; + + void Reset() + { + anchorGUID = 0; + phase = PHASE_CHAINED; + events.Reset(); + me->setFaction(7); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); + me->LoadEquipment(0, true); + } + + void EnterCombat(Unit * /*who*/) + { + events.ScheduleEvent(EVENT_ICY_TOUCH, 1000, GCD_CAST); + events.ScheduleEvent(EVENT_PLAGUE_STRIKE, 3000, GCD_CAST); + events.ScheduleEvent(EVENT_BLOOD_STRIKE, 2000, GCD_CAST); + events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + { + wait_timer = 5000; + me->CastSpell(me, SPELL_DK_INITIATE_VISUAL, true); + + if (Player* starter = Unit::GetPlayer(playerGUID)) + DoScriptText(say_event_attack[rand()%9], me, starter); + + phase = PHASE_TO_ATTACK; + } + } + + void EventStart(Creature* anchor, Player *pTarget) + { + wait_timer = 5000; + phase = PHASE_TO_EQUIP; + + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN_SELF); + me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN); + + float z; + anchor->GetContactPoint(me, anchorX, anchorY, z, 1.0f); + + playerGUID = pTarget->GetGUID(); + DoScriptText(say_event_start[rand()%8], me, pTarget); + } + + void UpdateAI(const uint32 diff); +}; + +CreatureAI* GetAI_npc_unworthy_initiate(Creature* pCreature) +{ + return new npc_unworthy_initiateAI(pCreature); +} + +struct npc_unworthy_initiate_anchorAI : public PassiveAI +{ + npc_unworthy_initiate_anchorAI(Creature *c) : PassiveAI(c), prisonerGUID(0) {} + + uint64 prisonerGUID; + + void SetGUID(const uint64 &guid, int32 /*id*/) + { + if (!prisonerGUID) + prisonerGUID = guid; + } + + uint64 GetGUID(int32 /*id*/) { return prisonerGUID; } +}; + +void npc_unworthy_initiateAI::UpdateAI(const uint32 diff) +{ + switch(phase) + { + case PHASE_CHAINED: + if (!anchorGUID) + { + if (Creature *anchor = me->FindNearestCreature(29521, 30)) + { + anchor->AI()->SetGUID(me->GetGUID()); + anchor->CastSpell(me, SPELL_SOUL_PRISON_CHAIN, true); + anchorGUID = anchor->GetGUID(); + } + else + error_log("npc_unworthy_initiateAI: unable to find anchor!"); + + float dist = 99.0f; + GameObject *prison = NULL; + + for (uint8 i = 0; i < 12; ++i) + { + if (GameObject* temp_prison = me->FindNearestGameObject(acherus_soul_prison[i],30)) + { + if (me->IsWithinDist(temp_prison, dist, false)) + { + dist = me->GetDistance2d(temp_prison); + prison = temp_prison; + } + } + } + + if (prison) + prison->ResetDoorOrButton(); + else + error_log("npc_unworthy_initiateAI: unable to find prison!"); + } + return; + case PHASE_TO_EQUIP: + if (wait_timer) + { + if (wait_timer > diff) + wait_timer -= diff; + else + { + me->GetMotionMaster()->MovePoint(1, anchorX, anchorY, me->GetPositionZ()); + //debug_log("npc_unworthy_initiateAI: move to %f %f %f", anchorX, anchorY, me->GetPositionZ()); + phase = PHASE_EQUIPING; + wait_timer = 0; + } + } + return; + case PHASE_TO_ATTACK: + if (wait_timer) + { + if (wait_timer > diff) + wait_timer -= diff; + else + { + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + phase = PHASE_ATTACKING; + + if (Player *pTarget = Unit::GetPlayer(playerGUID)) + me->AI()->AttackStart(pTarget); + wait_timer = 0; + } + } + return; + case PHASE_ATTACKING: + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ICY_TOUCH: + DoCast(me->getVictim(), SPELL_ICY_TOUCH); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_ICY_TOUCH, 5000, GCD_CAST); + break; + case EVENT_PLAGUE_STRIKE: + DoCast(me->getVictim(), SPELL_PLAGUE_STRIKE); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(SPELL_PLAGUE_STRIKE, 5000, GCD_CAST); + break; + case EVENT_BLOOD_STRIKE: + DoCast(me->getVictim(), SPELL_BLOOD_STRIKE); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_BLOOD_STRIKE, 5000, GCD_CAST); + break; + case EVENT_DEATH_COIL: + DoCast(me->getVictim(), SPELL_DEATH_COIL); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); + break; + } + } + + DoMeleeAttackIfReady(); + } +} + +CreatureAI* GetAI_npc_unworthy_initiate_anchor(Creature* pCreature) +{ + return new npc_unworthy_initiate_anchorAI(pCreature); +} + +bool GOHello_go_acherus_soul_prison(Player* pPlayer, GameObject* pGo) +{ + if (Creature *anchor = pGo->FindNearestCreature(29521, 15)) + if (uint64 prisonerGUID = anchor->AI()->GetGUID()) + if (Creature* prisoner = Creature::GetCreature(*pPlayer, prisonerGUID)) + CAST_AI(npc_unworthy_initiateAI, prisoner->AI())->EventStart(anchor, pPlayer); + + return false; +} + +/*###### +## npc_death_knight_initiate +######*/ + +#define GOSSIP_ACCEPT_DUEL "I challenge you, death knight!" + +enum eDuelEnums +{ + SAY_DUEL_A = -1609080, + SAY_DUEL_B = -1609081, + SAY_DUEL_C = -1609082, + SAY_DUEL_D = -1609083, + SAY_DUEL_E = -1609084, + SAY_DUEL_F = -1609085, + SAY_DUEL_G = -1609086, + SAY_DUEL_H = -1609087, + SAY_DUEL_I = -1609088, + + SPELL_DUEL = 52996, + //SPELL_DUEL_TRIGGERED = 52990, + SPELL_DUEL_VICTORY = 52994, + SPELL_DUEL_FLAG = 52991, + + QUEST_DEATH_CHALLENGE = 12733, + FACTION_HOSTILE = 2068 +}; + +int32 m_auiRandomSay[] = +{ + SAY_DUEL_A, SAY_DUEL_B, SAY_DUEL_C, SAY_DUEL_D, SAY_DUEL_E, SAY_DUEL_F, SAY_DUEL_G, SAY_DUEL_H, SAY_DUEL_I +}; + +struct npc_death_knight_initiateAI : public CombatAI +{ + npc_death_knight_initiateAI(Creature* pCreature) : CombatAI(pCreature) + { + m_bIsDuelInProgress = false; + } + + bool lose; + uint64 m_uiDuelerGUID; + uint32 m_uiDuelTimer; + bool m_bIsDuelInProgress; + + void Reset() + { + lose = false; + me->RestoreFaction(); + CombatAI::Reset(); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); + + m_uiDuelerGUID = 0; + m_uiDuelTimer = 5000; + m_bIsDuelInProgress = false; + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if (!m_bIsDuelInProgress && pSpell->Id == SPELL_DUEL) + { + m_uiDuelerGUID = pCaster->GetGUID(); + m_bIsDuelInProgress = true; + } + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (m_bIsDuelInProgress && pDoneBy->IsControlledByPlayer()) + { + if (pDoneBy->GetGUID() != m_uiDuelerGUID && pDoneBy->GetOwnerGUID() != m_uiDuelerGUID) // other players cannot help + uiDamage = 0; + else if (uiDamage >= me->GetHealth()) + { + uiDamage = 0; + + if (!lose) + { + pDoneBy->RemoveGameObject(SPELL_DUEL_FLAG, true); + pDoneBy->AttackStop(); + me->CastSpell(pDoneBy, SPELL_DUEL_VICTORY, true); + lose = true; + me->CastSpell(me, 7267, true); + me->RestoreFaction(); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + { + if (m_bIsDuelInProgress) + { + if (m_uiDuelTimer <= uiDiff) + { + me->setFaction(FACTION_HOSTILE); + + if (Unit* pUnit = Unit::GetUnit(*me, m_uiDuelerGUID)) + AttackStart(pUnit); + } + else + m_uiDuelTimer -= uiDiff; + } + return; + } + + if (m_bIsDuelInProgress) + { + if (lose) + { + if (!me->HasAura(7267)) + EnterEvadeMode(); + return; + } + else if (me->getVictim()->GetTypeId() == TYPEID_PLAYER + && me->getVictim()->GetHealth() * 10 < me->getVictim()->GetMaxHealth()) + { + me->getVictim()->CastSpell(me->getVictim(), 7267, true); // beg + me->getVictim()->RemoveGameObject(SPELL_DUEL_FLAG, true); + EnterEvadeMode(); + return; + } + } + + // TODO: spells + + CombatAI::UpdateAI(uiDiff); + } +}; + +CreatureAI* GetAI_npc_death_knight_initiate(Creature* pCreature) +{ + return new npc_death_knight_initiateAI(pCreature); +} + +bool GossipHello_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_DEATH_CHALLENGE) == QUEST_STATUS_INCOMPLETE && pCreature->GetHealth() == pCreature->GetMaxHealth()) + { + if (pPlayer->GetHealth() * 10 < pPlayer->GetMaxHealth()) + return true; + + if (pPlayer->isInCombat() || pCreature->isInCombat()) + return true; + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ACCEPT_DUEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature),pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pPlayer->isInCombat() || pCreature->isInCombat()) + return true; + + if (npc_death_knight_initiateAI* pInitiateAI = CAST_AI(npc_death_knight_initiateAI, pCreature->AI())) + { + if (pInitiateAI->m_bIsDuelInProgress) + return true; + } + + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); + + int32 uiSayId = rand()% (sizeof(m_auiRandomSay)/sizeof(int32)); + DoScriptText(m_auiRandomSay[uiSayId], pCreature, pPlayer); + + pPlayer->CastSpell(pCreature, SPELL_DUEL, false); + pPlayer->CastSpell(pPlayer, SPELL_DUEL_FLAG, true); + } + return true; +} + +/*###### +## npc_dark_rider_of_acherus +######*/ + +#define DESPAWN_HORSE 52267 +#define SAY_DARK_RIDER "The realm of shadows awaits..." + +struct npc_dark_rider_of_acherusAI : public ScriptedAI +{ + npc_dark_rider_of_acherusAI(Creature *c) : ScriptedAI(c) {} + + uint32 PhaseTimer; + uint32 Phase; + bool Intro; + uint64 TargetGUID; + + void Reset() + { + PhaseTimer = 4000; + Phase = 0; + Intro = false; + TargetGUID = 0; + } + + void UpdateAI(const uint32 diff) + { + if (!Intro || !TargetGUID) + return; + + if (PhaseTimer <= diff) + { + switch(Phase) + { + case 0: + me->MonsterSay(SAY_DARK_RIDER, LANG_UNIVERSAL, 0); + PhaseTimer = 5000; + Phase = 1; + break; + case 1: + if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID)) + DoCast(pTarget, DESPAWN_HORSE, true); + PhaseTimer = 3000; + Phase = 2; + break; + case 2: + me->SetVisibility(VISIBILITY_OFF); + PhaseTimer = 2000; + Phase = 3; + break; + case 3: + me->ForcedDespawn(); + break; + default: + break; + } + } else PhaseTimer -= diff; + + } + + void InitDespawnHorse(Unit *who) + { + if (!who) + return; + + TargetGUID = who->GetGUID(); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->SetSpeed(MOVE_RUN, 0.4f); + me->GetMotionMaster()->MoveChase(who); + me->SetUInt64Value(UNIT_FIELD_TARGET, TargetGUID); + Intro = true; + } + +}; + +CreatureAI* GetAI_npc_dark_rider_of_acherus(Creature* pCreature) +{ + return new npc_dark_rider_of_acherusAI(pCreature); +} + +/*###### +## npc_salanar_the_horseman +######*/ + +enum eSalanar +{ + REALM_OF_SHADOWS = 52693, + EFFECT_STOLEN_HORSE = 52263, + DELIVER_STOLEN_HORSE = 52264, + CALL_DARK_RIDER = 52266, + SPELL_EFFECT_OVERTAKE = 52349 +}; + +struct npc_salanar_the_horsemanAI : public ScriptedAI +{ + npc_salanar_the_horsemanAI(Creature *c) : ScriptedAI(c) {} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == DELIVER_STOLEN_HORSE) + { + if (caster->GetTypeId() == TYPEID_UNIT && caster->IsVehicle()) + { + if (Unit *charmer = caster->GetCharmer()) + { + charmer->RemoveAurasDueToSpell(EFFECT_STOLEN_HORSE); + caster->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + caster->setFaction(35); + DoCast(caster, CALL_DARK_RIDER, true); + if (Creature* Dark_Rider = me->FindNearestCreature(28654, 15)) + CAST_AI(npc_dark_rider_of_acherusAI, Dark_Rider->AI())->InitDespawnHorse(caster); + } + } + } + } + + void MoveInLineOfSight(Unit *who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (who->GetTypeId() == TYPEID_UNIT && who->IsVehicle() && me->IsWithinDistInMap(who, 5.0f)) + { + if (Unit *charmer = who->GetCharmer()) + { + if (charmer->GetTypeId() == TYPEID_PLAYER) + { + // for quest Into the Realm of Shadows(12687) + if (me->GetEntry() == 28788 && CAST_PLR(charmer)->GetQuestStatus(12687) == QUEST_STATUS_INCOMPLETE) + { + CAST_PLR(charmer)->GroupEventHappens(12687, me); + charmer->RemoveAurasDueToSpell(SPELL_EFFECT_OVERTAKE); + CAST_CRE(who)->ForcedDespawn(); + //CAST_CRE(who)->Respawn(true); + } + + if (CAST_PLR(charmer)->HasAura(REALM_OF_SHADOWS)) + charmer->RemoveAurasDueToSpell(REALM_OF_SHADOWS); + } + } + } + } +}; + +CreatureAI* GetAI_npc_salanar_the_horseman(Creature* pCreature) +{ + return new npc_salanar_the_horsemanAI(pCreature); +} + +/*###### +## npc_ros_dark_rider +######*/ + +struct npc_ros_dark_riderAI : public ScriptedAI +{ + npc_ros_dark_riderAI(Creature *c) : ScriptedAI(c) {} + + void EnterCombat(Unit * /*who*/) + { + me->ExitVehicle(); + } + + void Reset() + { + Creature* deathcharger = me->FindNearestCreature(28782, 30); + if (!deathcharger) return; + deathcharger->RestoreFaction(); + deathcharger->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + deathcharger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (!me->GetVehicle() && deathcharger->IsVehicle() && deathcharger->GetVehicleKit()->HasEmptySeat(0)) + me->EnterVehicle(deathcharger); + } + + void JustDied(Unit *killer) + { + Creature* deathcharger = me->FindNearestCreature(28782, 30); + if (!deathcharger) return; + if (killer->GetTypeId() == TYPEID_PLAYER && deathcharger->GetTypeId() == TYPEID_UNIT && deathcharger->IsVehicle()) + { + deathcharger->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + deathcharger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + deathcharger->setFaction(2096); + } + } +}; + +CreatureAI* GetAI_npc_ros_dark_rider(Creature* pCreature) +{ + return new npc_ros_dark_riderAI(pCreature); +} + +// correct way: 52312 52314 52555 ... +enum SG +{ + GHOULS = 28845, + GHOSTS = 28846, +}; +struct npc_dkc1_gothikAI : public ScriptedAI +{ + npc_dkc1_gothikAI(Creature *c) : ScriptedAI(c) {} + + void MoveInLineOfSight(Unit *who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (who->GetEntry() == GHOULS && me->IsWithinDistInMap(who, 10.0f)) + { + if (Unit *owner = who->GetOwner()) + { + if (owner->GetTypeId() == TYPEID_PLAYER) + { + if (CAST_PLR(owner)->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE) + { + //CAST_CRE(who)->CastSpell(owner, 52517, true); + CAST_PLR(owner)->KilledMonsterCredit(GHOULS, me->GetGUID()); + } + //Todo: Creatures must not be removed, but, must instead + // stand next to Gothik and be commanded into the pit + // and dig into the ground. + CAST_CRE(who)->ForcedDespawn(); + + if (CAST_PLR(owner)->GetQuestStatus(12698) == QUEST_STATUS_COMPLETE) + owner->RemoveAllMinionsByEntry(GHOULS); + } + } + } + } +}; + +CreatureAI* GetAI_npc_dkc1_gothik(Creature* pCreature) +{ + return new npc_dkc1_gothikAI(pCreature); +} + +struct npc_scarlet_ghoulAI : public ScriptedAI +{ + npc_scarlet_ghoulAI(Creature *c) : ScriptedAI(c) + { + // Ghouls should display their Birth Animation + // Crawling out of the ground + //DoCast(me, 35177, true); + //me->MonsterSay("Mommy?",LANG_UNIVERSAL,0); + me->SetReactState(REACT_DEFENSIVE); + } + + void FindMinions(Unit *owner) + { + std::list MinionList; + owner->GetAllMinionsByEntry(MinionList,GHOULS); + + if (!MinionList.empty()) + { + for (std::list::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr) + { + if (CAST_CRE(*itr)->GetOwner()->GetGUID() == me->GetOwner()->GetGUID()) + { + if (CAST_CRE(*itr)->isInCombat() && CAST_CRE(*itr)->getAttackerForHelper()) + { + AttackStart(CAST_CRE(*itr)->getAttackerForHelper()); + } + } + } + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!me->isInCombat()) + { + if (Unit *owner = me->GetOwner()) + { + if (owner->GetTypeId() == TYPEID_PLAYER && CAST_PLR(owner)->isInCombat()) + { + if (CAST_PLR(owner)->getAttackerForHelper() && CAST_PLR(owner)->getAttackerForHelper()->GetEntry() == GHOSTS) + { + AttackStart(CAST_PLR(owner)->getAttackerForHelper()); + } + else + { + FindMinions(owner); + } + } + } + } + + if (!UpdateVictim()) + return; + + //ScriptedAI::UpdateAI(diff); + //Check if we have a current target + if (me->getVictim()->GetEntry() == GHOSTS) + { + if (me->isAttackReady()) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + } + } +}; + +CreatureAI* GetAI_npc_scarlet_ghoul(Creature* pCreature) +{ + return new npc_scarlet_ghoulAI(pCreature); +} + +/*#### +## npc_scarlet_miner_cart +####*/ + +#define SPELL_CART_CHECK 54173 +#define SPELL_CART_DRAG 52465 + +struct npc_scarlet_miner_cartAI : public PassiveAI +{ + npc_scarlet_miner_cartAI(Creature *c) : PassiveAI(c), minerGUID(0) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetDisplayId(me->GetCreatureInfo()->Modelid1); // H0 is horse + } + + uint64 minerGUID; + + void SetGUID(const uint64 &guid, int32 /*id*/) + { + minerGUID = guid; + } + + void DoAction(const int32 /*param*/) + { + if (Creature *miner = Unit::GetCreature(*me, minerGUID)) + { + // very bad visual effect + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + //me->SetSpeed(MOVE_WALK, miner->GetSpeed(MOVE_WALK)); + me->SetSpeed(MOVE_RUN, miner->GetSpeed(MOVE_RUN)); + me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); + } + } + + void PassengerBoarded(Unit * /*who*/, int8 /*seatId*/, bool apply) + { + if (!apply) + if (Creature *miner = Unit::GetCreature(*me, minerGUID)) + miner->DisappearAndDie(); + } +}; + +CreatureAI* GetAI_npc_scarlet_miner_cart(Creature *_Creature) +{ + return new npc_scarlet_miner_cartAI(_Creature); +} + +/*#### +## npc_scarlet_miner +####*/ + +#define SAY_SCARLET_MINER1 "Where'd this come from? I better get this down to the ships before the foreman sees it!" +#define SAY_SCARLET_MINER2 "Now I can have a rest!" + +struct npc_scarlet_minerAI : public npc_escortAI +{ + npc_scarlet_minerAI(Creature *c) : npc_escortAI(c) + { + me->SetReactState(REACT_PASSIVE); + } + + uint32 IntroTimer; + uint32 IntroPhase; + uint64 carGUID; + + void Reset() + { + carGUID = 0; + IntroTimer = 0; + IntroPhase = 0; + } + + void InitWaypoint() + { + AddWaypoint(1, 2389.03, -5902.74, 109.014, 5000); + AddWaypoint(2, 2341.812012, -5900.484863, 102.619743); + AddWaypoint(3, 2306.561279, -5901.738281, 91.792419); + AddWaypoint(4, 2300.098389, -5912.618652, 86.014885); + AddWaypoint(5, 2294.142090, -5927.274414, 75.316849); + AddWaypoint(6, 2286.984375, -5944.955566, 63.714966); + AddWaypoint(7, 2280.001709, -5961.186035, 54.228283); + AddWaypoint(8, 2259.389648, -5974.197754, 42.359348); + AddWaypoint(9, 2242.882812, -5984.642578, 32.827850); + AddWaypoint(10, 2217.265625, -6028.959473, 7.675705); + AddWaypoint(11, 2202.595947, -6061.325684, 5.882018); + AddWaypoint(12, 2188.974609, -6080.866699, 3.370027); + + if (urand(0,1)) + { + AddWaypoint(13, 2176.483887, -6110.407227, 1.855181); + AddWaypoint(14, 2172.516602, -6146.752441, 1.074235); + AddWaypoint(15, 2138.918457, -6158.920898, 1.342926); + AddWaypoint(16, 2129.866699, -6174.107910, 4.380779); + AddWaypoint(17, 2117.709473, -6193.830078, 13.3542, 10000); + } + else + { + AddWaypoint(13, 2184.190186, -6166.447266, 0.968877); + AddWaypoint(14, 2234.265625, -6163.741211, 0.916021); + AddWaypoint(15, 2268.071777, -6158.750977, 1.822252); + AddWaypoint(16, 2270.028320, -6176.505859, 6.340538); + AddWaypoint(17, 2271.739014, -6195.401855, 13.3542, 10000); + } + } + + void InitCartQuest(Player *who) + { + carGUID = who->GetVehicleBase()->GetGUID(); + InitWaypoint(); + Start(false, false, who->GetGUID()); + SetDespawnAtFar(false); + } + + void WaypointReached(uint32 i) + { + switch (i) + { + case 1: + if (Unit *car = Unit::GetCreature(*me, carGUID)) + { + me->SetInFront(car); + me->SendMovementFlagUpdate(); + } + me->MonsterSay(SAY_SCARLET_MINER1,LANG_UNIVERSAL,NULL); + SetRun(true); + IntroTimer = 4000; + IntroPhase = 1; + break; + case 17: + if (Unit *car = Unit::GetCreature(*me, carGUID)) + { + me->SetInFront(car); + me->SendMovementFlagUpdate(); + car->Relocate(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ()); + car->SendMonsterStop(); + //this make player fall under ground, dunno why + //car->GetMotionMaster()->MovePoint(0, car->GetPositionX(), car->GetPositionY(), me->GetPositionZ()); + car->RemoveAura(SPELL_CART_DRAG); + } + me->MonsterSay(SAY_SCARLET_MINER2,LANG_UNIVERSAL,NULL); + break; + default: + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (IntroPhase) + { + if (IntroTimer <= diff) + { + if (IntroPhase == 1) + { + if (Creature *car = Unit::GetCreature(*me, carGUID)) + DoCast(car, SPELL_CART_DRAG); + IntroTimer = 800; + IntroPhase = 2; + } + else + { + if (Creature *car = Unit::GetCreature(*me, carGUID)) + car->AI()->DoAction(); + IntroPhase = 0; + } + } else IntroTimer-=diff; + } + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_npc_scarlet_miner(Creature *_Creature) +{ + return new npc_scarlet_minerAI(_Creature); +} + +/*###### +## go_inconspicuous_mine_car +######*/ + +#define SPELL_CART_SUMM 52463 + +bool GOHello_go_inconspicuous_mine_car(Player* pPlayer, GameObject* /*pGO*/) +{ + if (pPlayer->GetQuestStatus(12701) == QUEST_STATUS_INCOMPLETE) + { + // Hack Why Trinity Dont Support Custom Summon Location + if (Creature *miner = pPlayer->SummonCreature(28841, 2383.869629, -5900.312500, 107.996086, pPlayer->GetOrientation(),TEMPSUMMON_DEAD_DESPAWN, 1)) + { + pPlayer->CastSpell(pPlayer, SPELL_CART_SUMM, true); + if (Creature *car = pPlayer->GetVehicleCreatureBase()) + { + if (car->GetEntry() == 28817) + { + car->AI()->SetGUID(miner->GetGUID()); + CAST_AI(npc_scarlet_minerAI, miner->AI())->InitCartQuest(pPlayer); + } else error_log("TSCR: GOHello_go_inconspicuous_mine_car vehicle entry is not correct."); + } else error_log("TSCR: GOHello_go_inconspicuous_mine_car player is not on the vehicle."); + } else error_log("TSCR: GOHello_go_inconspicuous_mine_car Scarlet Miner cant be found by script."); + } + return true; +} + +// npc 28912 quest 17217 boss 29001 mob 29007 go 191092 + +void AddSC_the_scarlet_enclave_c1() +{ + Script *newscript; + + // 12848 The Endless Hunger + newscript = new Script; + newscript->Name = "npc_unworthy_initiate"; + newscript->GetAI = &GetAI_npc_unworthy_initiate; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_unworthy_initiate_anchor"; + newscript->GetAI = &GetAI_npc_unworthy_initiate_anchor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_acherus_soul_prison"; + newscript->pGOHello = &GOHello_go_acherus_soul_prison; + newscript->RegisterSelf(); + + // Death's Challenge + newscript = new Script; + newscript->Name = "npc_death_knight_initiate"; + newscript->GetAI = &GetAI_npc_death_knight_initiate; + newscript->pGossipHello = &GossipHello_npc_death_knight_initiate; + newscript->pGossipSelect = &GossipSelect_npc_death_knight_initiate; + newscript->RegisterSelf(); + + // 12680 Grand Theft Palomino + newscript = new Script; + newscript->Name = "npc_salanar_the_horseman"; + newscript->GetAI = &GetAI_npc_salanar_the_horseman; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dark_rider_of_acherus"; + newscript->GetAI = &GetAI_npc_dark_rider_of_acherus; + newscript->RegisterSelf(); + + // 12687 Into the Realm of Shadows + newscript = new Script; + newscript->Name = "npc_ros_dark_rider"; + newscript->GetAI = &GetAI_npc_ros_dark_rider; + newscript->RegisterSelf(); + + // 12698 The Gift That Keeps On Giving + newscript = new Script; + newscript->Name = "npc_dkc1_gothik"; + newscript->GetAI = &GetAI_npc_dkc1_gothik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_scarlet_ghoul"; + newscript->GetAI = &GetAI_npc_scarlet_ghoul; + newscript->RegisterSelf(); + + // Massacre At Light's Point + newscript = new Script; + newscript->Name = "npc_scarlet_miner"; + newscript->GetAI = &GetAI_npc_scarlet_miner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_scarlet_miner_cart"; + newscript->GetAI = &GetAI_npc_scarlet_miner_cart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_inconspicuous_mine_car"; + newscript->pGOHello = &GOHello_go_inconspicuous_mine_car; + newscript->RegisterSelf(); +} + +/* +DELETE FROM `script_texts` WHERE `entry` IN(-1609301, -1609302); +INSERT INTO `script_texts` (`entry`,`content_default`,`type`,`language`,`emote`,`comment`) VALUES +(-1609301, 'Come, weakling! Strike me down!', 0, 0, 0, 'SAY_DEATH_RIDER_FINAL'), +(-1609302, '%s rears up, beckoning you to ride it.', 2, 0, 0, 'SAY_DEATH_CHARGER'); +*/ diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp new file mode 100644 index 00000000000..91f7e0e6cbe --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp @@ -0,0 +1,995 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +//How to win friends and influence enemies +// texts signed for creature 28939 but used for 28939,28940,28610 +enum win_friends +{ + SAY_PERSUADE1 = -1609501, + SAY_PERSUADE2 = -1609502, + SAY_PERSUADE3 = -1609503, + SAY_PERSUADE4 = -1609504, + SAY_PERSUADE5 = -1609505, + SAY_PERSUADE6 = -1609506, + SAY_PERSUADE7 = -1609507, + SAY_CRUSADER1 = -1609508, + SAY_CRUSADER2 = -1609509, + SAY_CRUSADER3 = -1609510, + SAY_CRUSADER4 = -1609511, + SAY_CRUSADER5 = -1609512, + SAY_CRUSADER6 = -1609513, + SAY_PERSUADED1 = -1609514, + SAY_PERSUADED2 = -1609515, + SAY_PERSUADED3 = -1609516, + SAY_PERSUADED4 = -1609517, + SAY_PERSUADED5 = -1609518, + SAY_PERSUADED6 = -1609519, + SPELL_PERSUASIVE_STRIKE = 52781 +}; + +struct npc_crusade_persuadedAI : public ScriptedAI +{ + npc_crusade_persuadedAI(Creature *pCreature) : ScriptedAI(pCreature) {} + + uint32 uiSpeech_timer; + uint32 uiSpeech_counter; + uint64 uiPlayerGUID; + + void Reset() + { + uiSpeech_timer = 0; + uiSpeech_counter = 0; + uiPlayerGUID = 0; + me->SetReactState(REACT_AGGRESSIVE); + me->RestoreFaction(); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_PERSUASIVE_STRIKE && caster->GetTypeId() == TYPEID_PLAYER && me->isAlive() && !uiSpeech_counter) + { + if (CAST_PLR(caster)->GetQuestStatus(12720) == QUEST_STATUS_INCOMPLETE) + { + uiPlayerGUID = caster->GetGUID(); + uiSpeech_timer = 1000; + uiSpeech_counter = 1; + me->setFaction(caster->getFaction()); + me->CombatStop(true); + me->GetMotionMaster()->MoveIdle(); + me->SetReactState(REACT_PASSIVE); + DoCastAOE(58111, true); + + DoScriptText(RAND(SAY_PERSUADE1,SAY_PERSUADE2,SAY_PERSUADE3, + SAY_PERSUADE4,SAY_PERSUADE5,SAY_PERSUADE6, + SAY_PERSUADE7), caster); + + DoScriptText(RAND(SAY_CRUSADER1,SAY_CRUSADER2,SAY_CRUSADER3, + SAY_CRUSADER4,SAY_CRUSADER5,SAY_CRUSADER6), me); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (uiSpeech_counter) + { + if (uiSpeech_timer <= diff) + { + Player* pPlayer = Unit::GetPlayer(uiPlayerGUID); + if (!pPlayer) + { + EnterEvadeMode(); + return; + } + + switch(uiSpeech_counter) + { + case 1: DoScriptText(SAY_PERSUADED1, me); uiSpeech_timer = 8000; break; + case 2: DoScriptText(SAY_PERSUADED2, me); uiSpeech_timer = 8000; break; + case 3: DoScriptText(SAY_PERSUADED3, me); uiSpeech_timer = 8000; break; + case 4: DoScriptText(SAY_PERSUADED4, me); uiSpeech_timer = 8000; break; + case 5: DoScriptText(SAY_PERSUADED5, pPlayer); uiSpeech_timer = 8000; break; + case 6: DoScriptText(SAY_PERSUADED6, me); + pPlayer->Kill(me); + //me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiSpeech_counter = 0; + pPlayer->GroupEventHappens(12720, me); + return; + } + + ++uiSpeech_counter; + DoCastAOE(58111, true); + } else uiSpeech_timer -= diff; + + return; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_crusade_persuaded(Creature* pCreature) +{ + return new npc_crusade_persuadedAI (pCreature); +} + +/*###### +## npc_koltira_deathweaver +######*/ + +enum eKoltira +{ + SAY_BREAKOUT1 = -1609561, + SAY_BREAKOUT2 = -1609562, + SAY_BREAKOUT3 = -1609563, + SAY_BREAKOUT4 = -1609564, + SAY_BREAKOUT5 = -1609565, + SAY_BREAKOUT6 = -1609566, + SAY_BREAKOUT7 = -1609567, + SAY_BREAKOUT8 = -1609568, + SAY_BREAKOUT9 = -1609569, + SAY_BREAKOUT10 = -1609570, + + SPELL_KOLTIRA_TRANSFORM = 52899, + SPELL_ANTI_MAGIC_ZONE = 52894, + + QUEST_BREAKOUT = 12727, + + NPC_CRIMSON_ACOLYTE = 29007, + NPC_HIGH_INQUISITOR_VALROTH = 29001, + NPC_KOLTIRA_ALT = 28447, + + //not sure about this id + //NPC_DEATH_KNIGHT_MOUNT = 29201, + MODEL_DEATH_KNIGHT_MOUNT = 25278 +}; + +struct npc_koltira_deathweaverAI : public npc_escortAI +{ + npc_koltira_deathweaverAI(Creature *pCreature) : npc_escortAI(pCreature) + { + me->SetReactState(REACT_DEFENSIVE); + } + + uint32 m_uiWave; + uint32 m_uiWave_Timer; + uint64 m_uiValrothGUID; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + m_uiWave = 0; + m_uiWave_Timer = 3000; + m_uiValrothGUID = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->LoadEquipment(0, true); + me->RemoveAura(SPELL_ANTI_MAGIC_ZONE); + } + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 0: + DoScriptText(SAY_BREAKOUT1, me); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + break; + case 1: + me->SetStandState(UNIT_STAND_STATE_KNEEL); + break; + case 2: + me->SetStandState(UNIT_STAND_STATE_STAND); + //me->UpdateEntry(NPC_KOLTIRA_ALT); //unclear if we must update or not + DoCast(me, SPELL_KOLTIRA_TRANSFORM); + me->LoadEquipment(me->GetEquipmentId()); + break; + case 3: + SetEscortPaused(true); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(SAY_BREAKOUT2, me); + DoCast(me, SPELL_ANTI_MAGIC_ZONE); // cast again that makes bubble up + break; + case 4: + SetRun(true); + break; + case 9: + me->Mount(MODEL_DEATH_KNIGHT_MOUNT); + break; + case 10: + me->Unmount(); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + if (Player* pPlayer = GetPlayerForEscort()) + { + pSummoned->AI()->AttackStart(pPlayer); + } + + if (pSummoned->GetEntry() == NPC_HIGH_INQUISITOR_VALROTH) + m_uiValrothGUID = pSummoned->GetGUID(); + + pSummoned->AddThreat(me, 0.0f); + pSummoned->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + void SummonAcolyte(uint32 uiAmount) + { + for (uint32 i = 0; i < uiAmount; ++i) + me->SummonCreature(NPC_CRIMSON_ACOLYTE, 1642.329, -6045.818, 127.583, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (HasEscortState(STATE_ESCORT_PAUSED)) + { + if (m_uiWave_Timer <= uiDiff) + { + switch(m_uiWave) + { + case 0: + DoScriptText(SAY_BREAKOUT3, me); + SummonAcolyte(3); + m_uiWave_Timer = 20000; + break; + case 1: + DoScriptText(SAY_BREAKOUT4, me); + SummonAcolyte(3); + m_uiWave_Timer = 20000; + break; + case 2: + DoScriptText(SAY_BREAKOUT5, me); + SummonAcolyte(4); + m_uiWave_Timer = 20000; + break; + case 3: + DoScriptText(SAY_BREAKOUT6, me); + me->SummonCreature(NPC_HIGH_INQUISITOR_VALROTH, 1642.329, -6045.818, 127.583, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + m_uiWave_Timer = 1000; + break; + case 4: + { + Creature* pTemp = Unit::GetCreature(*me, m_uiValrothGUID); + + if (!pTemp || !pTemp->isAlive()) + { + DoScriptText(SAY_BREAKOUT8, me); + m_uiWave_Timer = 5000; + } + else + { + m_uiWave_Timer = 2500; + return; //return, we don't want m_uiWave to increment now + } + break; + } + case 5: + DoScriptText(SAY_BREAKOUT9, me); + me->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); + // i do not know why the armor will also be removed + m_uiWave_Timer = 2500; + break; + case 6: + DoScriptText(SAY_BREAKOUT10, me); + SetEscortPaused(false); + break; + } + + ++m_uiWave; + } + else + m_uiWave_Timer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_koltira_deathweaver(Creature* pCreature) +{ + return new npc_koltira_deathweaverAI(pCreature); +} + +bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_BREAKOUT) + { + pCreature->SetStandState(UNIT_STAND_STATE_STAND); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_koltira_deathweaverAI,pCreature->AI())) + pEscortAI->Start(false, false, pPlayer->GetGUID()); + } + return true; +} + +//Scarlet courier +enum ScarletCourierEnum +{ + SAY_TREE1 = -1609531, + SAY_TREE2 = -1609532, + SPELL_SHOOT = 52818, + GO_INCONSPICUOUS_TREE = 191144, + NPC_SCARLET_COURIER = 29076 +}; + +struct mob_scarlet_courierAI : public ScriptedAI +{ + mob_scarlet_courierAI(Creature *pCreature) : ScriptedAI(pCreature) {} + + uint32 uiStage; + uint32 uiStage_timer; + + void Reset() + { + me->Mount(14338); // not sure about this id + uiStage = 1; + uiStage_timer = 3000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_TREE2, me); + me->Unmount(); + uiStage = 0; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + uiStage = 2; + } + + void UpdateAI(const uint32 diff) + { + if (uiStage && !me->isInCombat()) + { + if (uiStage_timer <= diff) + { + switch(uiStage) + { + case 1: + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + if (GameObject* tree = me->FindNearestGameObject(GO_INCONSPICUOUS_TREE, 40.0f)) + { + DoScriptText(SAY_TREE1, me); + float x, y, z; + tree->GetContactPoint(me, x, y, z); + me->GetMotionMaster()->MovePoint(1, x, y, z); + } + break; + case 2: + if (GameObject* tree = me->FindNearestGameObject(GO_INCONSPICUOUS_TREE, 40.0f)) + if (Unit *unit = tree->GetOwner()) + AttackStart(unit); + break; + } + uiStage_timer = 3000; + uiStage = 0; + } else uiStage_timer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_scarlet_courier(Creature* pCreature) +{ + return new mob_scarlet_courierAI (pCreature); +} + +//Koltira & Valroth- Breakout + +enum valroth +{ + SAY_VALROTH1 = -1609581, + SAY_VALROTH2 = -1609582, + SAY_VALROTH3 = -1609583, + SAY_VALROTH4 = -1609584, + SAY_VALROTH5 = -1609585, + SAY_VALROTH6 = -1609586, + SPELL_RENEW = 38210, + SPELL_INQUISITOR_PENANCE = 52922, + SPELL_VALROTH_SMITE = 52926, + SPELL_SUMMON_VALROTH_REMAINS = 52929 +}; + +struct mob_high_inquisitor_valrothAI : public ScriptedAI +{ + mob_high_inquisitor_valrothAI(Creature *pCreature) : ScriptedAI(pCreature) {} + + uint32 uiRenew_timer; + uint32 uiInquisitor_Penance_timer; + uint32 uiValroth_Smite_timer; + + void Reset() + { + uiRenew_timer = 1000; + uiInquisitor_Penance_timer = 2000; + uiValroth_Smite_timer = 1000; + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_VALROTH2, me); + DoCast(who, SPELL_VALROTH_SMITE); + } + + void UpdateAI(const uint32 diff) + { + if (uiRenew_timer <= diff) + { + Shout(); + DoCast(me, SPELL_RENEW); + uiRenew_timer = 1000 + rand()%5000; + } else uiRenew_timer -= diff; + + if (uiInquisitor_Penance_timer <= diff) + { + Shout(); + DoCast(me->getVictim(), SPELL_INQUISITOR_PENANCE); + uiInquisitor_Penance_timer = 2000 + rand()%5000; + } else uiInquisitor_Penance_timer -= diff; + + if (uiValroth_Smite_timer <= diff) + { + Shout(); + DoCast(me->getVictim(), SPELL_VALROTH_SMITE); + uiValroth_Smite_timer = 1000 + rand()%5000; + } else uiValroth_Smite_timer -= diff; + + DoMeleeAttackIfReady(); + } + + void Shout() + { + if (rand()%100 < 15) + DoScriptText(RAND(SAY_VALROTH3,SAY_VALROTH4,SAY_VALROTH5), me); + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_VALROTH6, me); + killer->CastSpell(me, SPELL_SUMMON_VALROTH_REMAINS, true); + } +}; + +CreatureAI* GetAI_mob_high_inquisitor_valroth(Creature* pCreature) +{ + return new mob_high_inquisitor_valrothAI (pCreature); +} + +/*###### +## npc_a_special_surprise +######*/ +//used by 29032,29061,29065,29067,29068,29070,29074,29072,29073,29071 but signed for 29032 +enum SpecialSurprise +{ + SAY_EXEC_START_1 = -1609025, // speech for all + SAY_EXEC_START_2 = -1609026, + SAY_EXEC_START_3 = -1609027, + SAY_EXEC_PROG_1 = -1609028, + SAY_EXEC_PROG_2 = -1609029, + SAY_EXEC_PROG_3 = -1609030, + SAY_EXEC_PROG_4 = -1609031, + SAY_EXEC_PROG_5 = -1609032, + SAY_EXEC_PROG_6 = -1609033, + SAY_EXEC_PROG_7 = -1609034, + SAY_EXEC_NAME_1 = -1609035, + SAY_EXEC_NAME_2 = -1609036, + SAY_EXEC_RECOG_1 = -1609037, + SAY_EXEC_RECOG_2 = -1609038, + SAY_EXEC_RECOG_3 = -1609039, + SAY_EXEC_RECOG_4 = -1609040, + SAY_EXEC_RECOG_5 = -1609041, + SAY_EXEC_RECOG_6 = -1609042, + SAY_EXEC_NOREM_1 = -1609043, + SAY_EXEC_NOREM_2 = -1609044, + SAY_EXEC_NOREM_3 = -1609045, + SAY_EXEC_NOREM_4 = -1609046, + SAY_EXEC_NOREM_5 = -1609047, + SAY_EXEC_NOREM_6 = -1609048, + SAY_EXEC_NOREM_7 = -1609049, + SAY_EXEC_NOREM_8 = -1609050, + SAY_EXEC_NOREM_9 = -1609051, + SAY_EXEC_THINK_1 = -1609052, + SAY_EXEC_THINK_2 = -1609053, + SAY_EXEC_THINK_3 = -1609054, + SAY_EXEC_THINK_4 = -1609055, + SAY_EXEC_THINK_5 = -1609056, + SAY_EXEC_THINK_6 = -1609057, + SAY_EXEC_THINK_7 = -1609058, + SAY_EXEC_THINK_8 = -1609059, + SAY_EXEC_THINK_9 = -1609060, + SAY_EXEC_THINK_10 = -1609061, + SAY_EXEC_LISTEN_1 = -1609062, + SAY_EXEC_LISTEN_2 = -1609063, + SAY_EXEC_LISTEN_3 = -1609064, + SAY_EXEC_LISTEN_4 = -1609065, + SAY_PLAGUEFIST = -1609066, + SAY_EXEC_TIME_1 = -1609067, + SAY_EXEC_TIME_2 = -1609068, + SAY_EXEC_TIME_3 = -1609069, + SAY_EXEC_TIME_4 = -1609070, + SAY_EXEC_TIME_5 = -1609071, + SAY_EXEC_TIME_6 = -1609072, + SAY_EXEC_TIME_7 = -1609073, + SAY_EXEC_TIME_8 = -1609074, + SAY_EXEC_TIME_9 = -1609075, + SAY_EXEC_TIME_10 = -1609076, + SAY_EXEC_WAITING = -1609077, + EMOTE_DIES = -1609078, + + NPC_PLAGUEFIST = 29053 +}; + +struct npc_a_special_surpriseAI : public ScriptedAI +{ + npc_a_special_surpriseAI(Creature *pCreature) : ScriptedAI(pCreature) {} + + uint32 ExecuteSpeech_Timer; + uint32 ExecuteSpeech_Counter; + uint64 PlayerGUID; + + void Reset() + { + ExecuteSpeech_Timer = 0; + ExecuteSpeech_Counter = 0; + PlayerGUID = 0; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + bool MeetQuestCondition(Unit* pPlayer) + { + switch(me->GetEntry()) + { + case 29061: // Ellen Stanbridge + if (CAST_PLR(pPlayer)->GetQuestStatus(12742) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29072: // Kug Ironjaw + if (CAST_PLR(pPlayer)->GetQuestStatus(12748) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29067: // Donovan Pulfrost + if (CAST_PLR(pPlayer)->GetQuestStatus(12744) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29065: // Yazmina Oakenthorn + if (CAST_PLR(pPlayer)->GetQuestStatus(12743) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29071: // Antoine Brack + if (CAST_PLR(pPlayer)->GetQuestStatus(12750) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29032: // Malar Bravehorn + if (CAST_PLR(pPlayer)->GetQuestStatus(12739) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29068: // Goby Blastenheimer + if (CAST_PLR(pPlayer)->GetQuestStatus(12745) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29073: // Iggy Darktusk + if (CAST_PLR(pPlayer)->GetQuestStatus(12749) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29074: // Lady Eonys + if (CAST_PLR(pPlayer)->GetQuestStatus(12747) == QUEST_STATUS_INCOMPLETE) + return true; + break; + case 29070: // Valok the Righteous + if (CAST_PLR(pPlayer)->GetQuestStatus(12746) == QUEST_STATUS_INCOMPLETE) + return true; + break; + } + + return false; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (PlayerGUID || pWho->GetTypeId() != TYPEID_PLAYER || !pWho->IsWithinDist(me, INTERACTION_DISTANCE)) + return; + + if (MeetQuestCondition(pWho)) + PlayerGUID = pWho->GetGUID(); + } + + void UpdateAI(const uint32 diff) + { + if (PlayerGUID && !me->getVictim() && me->isAlive()) + { + if (ExecuteSpeech_Timer <= diff) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + + if (!pPlayer) + { + Reset(); + return; + } + + //TODO: simplify text's selection + + switch(pPlayer->getRace()) + { + case RACE_HUMAN: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_5, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_5, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_7, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_6, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_ORC: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_6, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_7, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_8, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_8, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_DWARF: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_2, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_2, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_3, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_2, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_5, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_2, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_3, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_NIGHTELF: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_5, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_6, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_2, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_7, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_UNDEAD_PLAYER: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_3, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_4, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_3, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_1, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_3, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_4, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_TAUREN: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_5, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_8, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_9, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_9, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_GNOME: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_4, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_4, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_6, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_5, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_TROLL: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_3, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_7, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_2, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_6, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_9, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_10, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_4, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_10, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_BLOODELF: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; + //case 5: //unknown + case 6: DoScriptText(SAY_EXEC_THINK_3, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_1, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + case RACE_DRAENEI: + switch(ExecuteSpeech_Counter) + { + case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; + case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; + case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; + case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; + case 4: DoScriptText(SAY_EXEC_RECOG_2, me, pPlayer); break; + case 5: DoScriptText(SAY_EXEC_NOREM_1, me, pPlayer); break; + case 6: DoScriptText(SAY_EXEC_THINK_4, me, pPlayer); break; + case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; + case 8: + if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) + DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); + break; + case 9: + DoScriptText(SAY_EXEC_TIME_2, me, pPlayer); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + break; + case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; + case 11: + DoScriptText(EMOTE_DIES, me); + me->setDeathState(JUST_DIED); + me->SetHealth(0); + return; + } + break; + } + + if (ExecuteSpeech_Counter >= 9) + ExecuteSpeech_Timer = 15000; + else + ExecuteSpeech_Timer = 7000; + + ++ExecuteSpeech_Counter; + } + else + ExecuteSpeech_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_npc_a_special_surprise(Creature* pCreature) +{ + return new npc_a_special_surpriseAI(pCreature); +} + +void AddSC_the_scarlet_enclave_c2() +{ + Script *newscript; + + // How to win friends and influence enemies + newscript = new Script; + newscript->Name = "npc_crusade_persuaded"; + newscript->GetAI = &GetAI_npc_crusade_persuaded; + newscript->RegisterSelf(); + + // Ambush At The Overlook + newscript = new Script; + newscript->Name = "mob_scarlet_courier"; + newscript->GetAI = &GetAI_mob_scarlet_courier; + newscript->RegisterSelf(); + + // 12727 Bloody Breakout + newscript = new Script; + newscript->Name = "npc_koltira_deathweaver"; + newscript->GetAI = &GetAI_npc_koltira_deathweaver; + newscript->pQuestAccept = &QuestAccept_npc_koltira_deathweaver; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_high_inquisitor_valroth"; + newscript->GetAI = &GetAI_mob_high_inquisitor_valroth; + newscript->RegisterSelf(); + + // A Special Suprise + newscript = new Script; + newscript->Name = "npc_a_special_surprise"; + newscript->GetAI = &GetAI_npc_a_special_surprise; + newscript->RegisterSelf(); +} + +/* +-- Bloody Breakout +UPDATE `creature_template` SET `ScriptName`='npc_koltira_deathweaver' WHERE `entry`='28912'; +UPDATE `creature_template` SET `ScriptName`='mob_high_inquisitor_valroth',minmana=6489,maxmana=6489,unit_flags=32768 WHERE `entry`='29001'; +UPDATE `creature_template` SET `ScriptName`='mob_eventai', `AIName`='EventAI',minmana=1020,maxmana=1058,unit_flags=32768 WHERE (`entry`='29007'); +DELETE FROM creature_ai_scripts WHERE id BETWEEN 90030 AND 90033; +INSERT INTO `creature_ai_scripts` VALUES ('90030', '29007', '0', '0', '100', '1', '1000', '4000', '1000', '4000', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Smite'); +INSERT INTO `creature_ai_scripts` VALUES ('90031', '29007', '0', '0', '100', '1', '1000', '10000', '20000', '21000', '11', '34809', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Fury'); +INSERT INTO `creature_ai_scripts` VALUES ('90032', '29007', '0', '0', '100', '1', '1000', '5000', '1000', '5000', '11', '19725', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Turn Undead'); +INSERT INTO `creature_ai_scripts` VALUES ('90033', '29007', '4', '0', '100', '0', '0', '0', '0', '0', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte aggro'); +*/ diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp new file mode 100644 index 00000000000..3b0ce186592 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -0,0 +1,1684 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +#define LESS_MOB // if you do not have a good server and do not want it to be laggy as hell +//Light of Dawn +enum mograine +{ +#ifdef LESS_MOB + ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - + ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data + ENCOUNTER_DEFENDER_NUMBER = 10, // how many of defender + ENCOUNTER_EARTHSHATTER_NUMBER = 1, // how many of earthshatter + ENCOUNTER_ABOMINATION_NUMBER = 2, // how many of abomination + ENCOUNTER_BEHEMOTH_NUMBER = 1, // how many of behemoth + ENCOUNTER_GHOUL_NUMBER = 5, // how many of ghoul + ENCOUNTER_WARRIOR_NUMBER = 1, // how many of warrior +#else + ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - + ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data + ENCOUNTER_DEFENDER_NUMBER = 20, // how many of defender + ENCOUNTER_EARTHSHATTER_NUMBER = 20, // how many of earthshatter + ENCOUNTER_ABOMINATION_NUMBER = 3, // how many of abomination + ENCOUNTER_BEHEMOTH_NUMBER = 2, // how many of behemoth + ENCOUNTER_GHOUL_NUMBER = 10, // how many of ghoul + ENCOUNTER_WARRIOR_NUMBER = 2, // how many of warrior +#endif + ENCOUNTER_TOTAL_DAWN = 300, // Total number + ENCOUNTER_TOTAL_SCOURGE = 10000, + + WORLD_STATE_REMAINS = 3592, + WORLD_STATE_COUNTDOWN = 3603, + WORLD_STATE_EVENT_BEGIN = 3605, + + SAY_LIGHT_OF_DAWN01 = -1609201, // pre text + SAY_LIGHT_OF_DAWN02 = -1609202, + SAY_LIGHT_OF_DAWN03 = -1609203, + SAY_LIGHT_OF_DAWN04 = -1609204, // intro + SAY_LIGHT_OF_DAWN05 = -1609205, + SAY_LIGHT_OF_DAWN06 = -1609206, + SAY_LIGHT_OF_DAWN07 = -1609207, // During the fight - Korfax, Champion of the Light + SAY_LIGHT_OF_DAWN08 = -1609208, // Lord Maxwell Tyrosus + SAY_LIGHT_OF_DAWN09 = -1609209, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN10 = -1609210, + SAY_LIGHT_OF_DAWN11 = -1609211, + SAY_LIGHT_OF_DAWN12 = -1609212, + SAY_LIGHT_OF_DAWN13 = -1609213, + SAY_LIGHT_OF_DAWN14 = -1609214, + SAY_LIGHT_OF_DAWN15 = -1609215, + SAY_LIGHT_OF_DAWN16 = -1609216, + SAY_LIGHT_OF_DAWN17 = -1609217, + SAY_LIGHT_OF_DAWN18 = -1609218, + SAY_LIGHT_OF_DAWN19 = -1609219, + SAY_LIGHT_OF_DAWN20 = -1609220, + SAY_LIGHT_OF_DAWN21 = -1609221, + SAY_LIGHT_OF_DAWN22 = -1609222, + SAY_LIGHT_OF_DAWN23 = -1609223, + SAY_LIGHT_OF_DAWN24 = -1609224, + SAY_LIGHT_OF_DAWN25 = -1609225, // After the fight + SAY_LIGHT_OF_DAWN26 = -1609226, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN27 = -1609227, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN28 = -1609228, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN29 = -1609229, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN30 = -1609230, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN31 = -1609231, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN32 = -1609232, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN33 = -1609233, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN34 = -1609234, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN35 = -1609235, // Darion Mograine + SAY_LIGHT_OF_DAWN36 = -1609236, // Darion Mograine + SAY_LIGHT_OF_DAWN37 = -1609237, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN38 = -1609238, // Darion Mograine + SAY_LIGHT_OF_DAWN39 = -1609239, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN40 = -1609240, // Darion Mograine + SAY_LIGHT_OF_DAWN41 = -1609241, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN42 = -1609242, // Highlord Alexandros Mograine + SAY_LIGHT_OF_DAWN43 = -1609243, // The Lich King + SAY_LIGHT_OF_DAWN44 = -1609244, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN45 = -1609245, // The Lich King + SAY_LIGHT_OF_DAWN46 = -1609246, // The Lich King + SAY_LIGHT_OF_DAWN47 = -1609247, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN48 = -1609248, // The Lich King + SAY_LIGHT_OF_DAWN49 = -1609249, // The Lich King + SAY_LIGHT_OF_DAWN50 = -1609250, // Lord Maxwell Tyrosus + SAY_LIGHT_OF_DAWN51 = -1609251, // The Lich King + SAY_LIGHT_OF_DAWN52 = -1609252, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN53 = -1609253, // Highlord Darion Mograine + SAY_LIGHT_OF_DAWN54 = -1609254, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN55 = -1609255, // The Lich King + SAY_LIGHT_OF_DAWN56 = -1609256, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN57 = -1609257, // The Lich King + SAY_LIGHT_OF_DAWN58 = -1609258, // The Lich King + SAY_LIGHT_OF_DAWN59 = -1609259, // The Lich King + SAY_LIGHT_OF_DAWN60 = -1609260, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN61 = -1609261, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN62 = -1609262, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN63 = -1609263, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN64 = -1609264, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN65 = -1609265, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN66 = -1609266, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN67 = -1609267, // Highlord Tirion Fordring + SAY_LIGHT_OF_DAWN68 = -1609268, // Highlord Darion Mograine + + EMOTE_LIGHT_OF_DAWN01 = -1609269, // Emotes + EMOTE_LIGHT_OF_DAWN02 = -1609270, + EMOTE_LIGHT_OF_DAWN03 = -1609271, + EMOTE_LIGHT_OF_DAWN04 = -1609272, + EMOTE_LIGHT_OF_DAWN05 = -1609273, + EMOTE_LIGHT_OF_DAWN06 = -1609274, + EMOTE_LIGHT_OF_DAWN07 = -1609275, + EMOTE_LIGHT_OF_DAWN08 = -1609276, + EMOTE_LIGHT_OF_DAWN09 = -1609277, + EMOTE_LIGHT_OF_DAWN10 = -1609278, + EMOTE_LIGHT_OF_DAWN11 = -1609279, + EMOTE_LIGHT_OF_DAWN12 = -1609280, + EMOTE_LIGHT_OF_DAWN13 = -1609281, + EMOTE_LIGHT_OF_DAWN14 = -1609282, + EMOTE_LIGHT_OF_DAWN15 = -1609283, + EMOTE_LIGHT_OF_DAWN16 = -1609284, + EMOTE_LIGHT_OF_DAWN17 = -1609285, + EMOTE_LIGHT_OF_DAWN18 = -1609286, + + GO_LIGHT_OF_DAWN = 191330, + SPELL_THE_LIGHT_OF_DAWN_Q = 53606, // quest credit + + // ---- Dark Knight npc -------------------- + // Highlord Darion Mograine + NPC_HIGHLORD_DARION_MOGRAINE = 29173, + SPELL_ANTI_MAGIC_ZONE1 = 52893, + SPELL_DEATH_STRIKE = 53639, + SPELL_DEATH_EMBRACE = 53635, + SPELL_ICY_TOUCH1 = 49723, + SPELL_THE_LIGHT_OF_DAWN = 53658, + SPELL_THE_MIGHT_OF_MOGRAINE = 53642, // on players when begins + SPELL_UNHOLY_BLIGHT = 53640, + SPELL_ALEXANDROS_MOGRAINE_SPAWN = 53667, + SPELL_MOGRAINE_CHARGE = 53679, + SPELL_ASHBRINGER = 53701, + + // Koltira Deathweaver & Orbaz Bloodbane are using the same abilities + NPC_KOLTIRA_DEATHWEAVER = 29199, + NPC_ORBAZ_BLOODBANE = 29204, // this guy fleed + NPC_THASSARIAN = 29200, // he also does SPELL_THE_LIGHT_OF_DAWN 53658 + SPELL_BLOOD_STRIKE1 = 52374, + SPELL_DEATH_GRIP = 49576, + SPELL_ICY_TOUCH2 = 52372, + SPELL_PLAGUE_STRIKE1 = 50668, + // all do SPELL_HERO_AGGRO_AURA 53627 + + // Lich King + NPC_THE_LICH_KING = 29183, // show up at end + SPELL_APOCALYPSE = 53210, + SPELL_TELEPORT_VISUAL = 52233, + SPELL_SOUL_FEAST_ALEX = 53677, // on Alexandros + SPELL_SOUL_FEAST_TIRION = 53685, // on Tirion + SPELL_ICEBOUND_VISAGE = 53274, // not sure what is it for + SPELL_REBUKE = 53680, + + // others + NPC_RAMPAGING_ABOMINATION = 29186, + SPELL_CLEAVE1 = 53633, + SPELL_SCOURGE_HOOK = 50335, + SPELL_SCOURGE_AGGRO_AURA = 53624, + + NPC_FLESH_BEHEMOTH = 29190, // giant guy + SPELL_STOMP = 53634, + SPELL_THUNDERCLAP = 36706, + SPELL_HERO_AGGRO_AURA = 53627, + + NPC_ACHERUS_GHOUL = 29219, // just ghoul.... + SPELL_GHOULPLOSION = 53632, + + NPC_WARRIOR_OF_THE_FROZEN_WASTES = 29206, // use SPELL_CLEAVE 53631 + + NPC_HIGHLORD_ALEXANDROS_MOGRAINE = 29227, // ghost + NPC_DARION_MOGRAINE = 29228, // ghost + + // ---- Dawn npc -------------------- + // Highlord Tirion Fordring + NPC_HIGHLORD_TIRION_FORDRING = 29175, + EQUIP_HIGHLORD_TIRION_FORDRING = 13262, + SPELL_LAY_ON_HANDS = 53778, + SPELL_REBIRTH_OF_THE_ASHBRINGER = 53702, + SPELL_TIRION_CHARGE = 53705, + SPELL_TIRION_CHARGE_VISUAL = 53706, + + // others + NPC_KORFAX_CHAMPION_OF_THE_LIGHT = 29176, + SPELL_CLEAVE = 53631, + SPELL_HEROIC_LEAP = 53625, + + NPC_LORD_MAXWELL_TYROSUS = 29178, + NPC_LEONID_BARTHALOMEW_THE_REVERED = 29179, + NPC_DUKE_NICHOLAS_ZVERENHOFF = 29180, + + NPC_COMMANDER_ELIGOR_DAWNBRINGER = 29177, + SPELL_HOLY_LIGHT2 = 37979, + + NPC_RAYNE = 29181, + SPELL_REJUVENATION = 20664, + SPELL_STARFALL = 20678, + SPELL_TRANQUILITY = 25817, + SPELL_WRATH = 21807, + + NPC_DEFENDER_OF_THE_LIGHT = 29174, // also does SPELL_HEROIC_LEAP 53625 + SPELL_HOLY_LIGHT1 = 29427, + SPELL_HOLY_STRIKE = 53643, + SPELL_HOLY_WRATH = 53638, + SPELL_UPPERCUT = 53629, + + NPC_RIMBLAT_EARTHSHATTER = 29182, + SPELL_CHAIN_HEAL = 33642, + SPELL_THUNDER = 53630 +}; + +struct Locations +{ + float x, y, z, o; + uint32 id; +}; + +void UpdateWorldState(Map *map, uint32 id, uint32 state) +{ + Map::PlayerList const& players = map->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->SendUpdateWorldState(id,state); + } + } +} + +static Locations LightofDawnLoc[]= +{ + {2281.335, -5300.409, 85.170, 0}, // 0 Tirion Fordring loc + {2283.896, -5287.914, 83.066, 1.55}, // 1 Tirion Fordring loc2 + {2281.461, -5263.014, 81.164, 0}, // 2 Tirion charges + {2262.277, -5293.477, 82.167, 0}, // 3 Tirion run + {2270.286, -5287.73, 82.262, 0}, // 4 Tirion relocate + {2269.511, -5288.289, 82.225, 0}, // 5 Tirion forward + {2262.277, -5293.477, 82.167, 0}, // 6 Tirion runs to Darion + {2270.286, -5287.73, 82.262, 0}, + {2269.511, -5288.289, 82.225, 0}, + {2273.205, -5288.848, 82.617, 0}, // 9 Korfax loc1 + {2274.739, -5287.926, 82.684, 0}, // 10 Korfax loc2 + {2253.673, -5318.004, 81.724, 0}, // 11 Korfax kicked + {2287.028, -5309.644, 87.253, 0}, // 12 Maxwell loc1 + {2286.978, -5308.025, 86.83, 0}, // 13 Maxwell loc2 + {2248.877, -5307.586, 82.166, 0}, // 14 maxwell kicked + {2278.58, -5316.933, 88.319, 0}, // 15 Eligor loc1 + {2278.535, -5315.479, 88.08, 0}, // 16 Eligor loc2 + {2259.416, -5304.505, 82.149, 0}, // 17 eligor kicked + {2289.259, -5280.355, 82.112, 0}, // 18 Koltira loc1 + {2289.02, -5281.985, 82.207, 0}, // 19 Koltira loc2 + {2273.289, -5273.675, 81.701, 0}, // 20 Thassarian loc1 + {2273.332, -5275.544, 81.849, 0}, // 21 Thassarian loc2 + {2281.198, -5257.397, 80.224, 4.66}, // 22 Alexandros loc1 + {2281.156, -5259.934, 80.647, 0}, // 23 Alexandros loc2 + {2281.294, -5281.895, 82.445, 1.35}, // 24 Darion loc1 + {2281.093, -5263.013, 81.125, 0}, // 25 Darion loc1 + {2281.313, -5250.282, 79.322, 4.69}, // 26 Lich King spawns + {2281.523, -5261.058, 80.877, 0}, // 27 Lich king move forwards + {2272.709, -5255.552, 78.226, 0}, // 28 Lich king kicked + {2273.972, -5257.676, 78.862, 0} // 29 Lich king moves forward +}; + +struct npc_highlord_darion_mograineAI : public npc_escortAI +{ + npc_highlord_darion_mograineAI(Creature *pCreature) : npc_escortAI(pCreature) + { + Reset(); + } + + bool bIsBattle; + uint32 uiStep; + uint32 uiPhase_timer; + uint32 uiFight_duration; + uint32 uiTotal_dawn; + uint32 uiTotal_scourge; + uint32 uiSummon_counter; + + // Darion Mograine + uint32 uiAnti_magic_zone; + uint32 uiDeath_strike; + uint32 uiDeath_embrace; + uint32 uiIcy_touch; + uint32 uiUnholy_blight; + uint32 uiFight_speech; + uint32 uiSpawncheck; + uint32 uiTargetcheck; + + // Dawn + uint64 uiTirionGUID; + uint64 uiAlexandrosGUID; + uint64 uiDarionGUID; + uint64 uiKorfaxGUID; + uint64 uiMaxwellGUID; + uint64 uiEligorGUID; + uint64 uiRayneGUID; + uint64 uiDefenderGUID[ENCOUNTER_DEFENDER_NUMBER]; + uint64 uiEarthshatterGUID[ENCOUNTER_EARTHSHATTER_NUMBER]; + + // Death + uint64 uiKoltiraGUID; + uint64 uiOrbazGUID; + uint64 uiThassarianGUID; + uint64 uiLichKingGUID; + uint64 uiAbominationGUID[ENCOUNTER_ABOMINATION_NUMBER]; + uint64 uiBehemothGUID[ENCOUNTER_BEHEMOTH_NUMBER]; + uint64 uiGhoulGUID[ENCOUNTER_GHOUL_NUMBER]; + uint64 uiWarriorGUID[ENCOUNTER_WARRIOR_NUMBER]; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + bIsBattle = false; + uiStep = 0; + uiPhase_timer = 3000; + uiFight_duration = 300000; // 5 minutes + uiTotal_dawn = ENCOUNTER_TOTAL_DAWN; + uiTotal_scourge = ENCOUNTER_TOTAL_SCOURGE; + uiSummon_counter = 0; + + uiAnti_magic_zone = urand(1000,6000); + uiDeath_strike = urand(5000,10000); + uiDeath_embrace = urand(5000,10000); + uiIcy_touch = urand(5000,10000); + uiUnholy_blight = urand(5000,10000); + + uiFight_speech = 15000; + uiSpawncheck = 1000; + uiTargetcheck = 10000; + + me->SetStandState(UNIT_STAND_STATE_STAND); + me->Mount(25279); + me->SetVisibility(VISIBILITY_ON); + + UpdateWorldState(me->GetMap(), WORLD_STATE_REMAINS, 0); + //UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 0); + UpdateWorldState(me->GetMap(), WORLD_STATE_EVENT_BEGIN, 0); + + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiRayneGUID)) + pTemp->setDeathState(JUST_DIED); + + uiTirionGUID = NULL; + uiKorfaxGUID = NULL; + uiMaxwellGUID = NULL; + uiEligorGUID = NULL; + uiRayneGUID = NULL; + + for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiDefenderGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiDefenderGUID[i] = 0; + } + for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiEarthshatterGUID[i] = 0; + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + pTemp->setDeathState(JUST_DIED); + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->setDeathState(JUST_DIED); + + uiKoltiraGUID = NULL; + uiOrbazGUID = NULL; + uiThassarianGUID = NULL; + uiLichKingGUID = NULL; + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiAbominationGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiAbominationGUID[i] = 0; + } + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiBehemothGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiBehemothGUID[i] = 0; + } + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiGhoulGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiGhoulGUID[i] = 0; + } + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + { + if (Creature* pTemp = Unit::GetCreature(*me, uiWarriorGUID[i])) + pTemp->setDeathState(JUST_DIED); + uiWarriorGUID[i] = 0; + } + } + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who == me) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void MoveInLineOfSight(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack() && me->IsHostileTo(who)) + if (me->IsWithinDistInMap(who, 20) && me->IsWithinLOSInMap(who)) + AttackStart(who); + } + + void SetHoldState(bool bOnHold) + { + SetEscortPaused(bOnHold); + } + + void WaypointReached(uint32 i) + { + switch (i) + { + case 0: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + SetHoldState(true); + break; + case 1: + SetHoldState(true); + + SpawnNPC(); + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN07, pTemp); + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN08, pTemp); + + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + NPCChangeTarget(uiGhoulGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + NPCChangeTarget(uiWarriorGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + NPCChangeTarget(uiAbominationGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + NPCChangeTarget(uiBehemothGUID[i]); + NPCChangeTarget(uiKoltiraGUID); + NPCChangeTarget(uiOrbazGUID); + NPCChangeTarget(uiThassarianGUID); + + me->Unmount(); + me->CastSpell(me, SPELL_THE_MIGHT_OF_MOGRAINE, true); // need to fix, on player only + + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + pTemp->Unmount(); + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + pTemp->Unmount(); + + bIsBattle = true; + break; + case 2: + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + DoCast(me, SPELL_THE_LIGHT_OF_DAWN); + break; + case 3: + { + //Unit* pTirion = Unit::GetCreature(*me, uiTirionGUID); + + DoScriptText(EMOTE_LIGHT_OF_DAWN05, me); + if (me->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) + me->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + { + if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) + pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[19].x, LightofDawnLoc[19].y, LightofDawnLoc[19].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + { + if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) + pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[21].x, LightofDawnLoc[21].y, LightofDawnLoc[21].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + { + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[10].x, LightofDawnLoc[10].y, LightofDawnLoc[10].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + { + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[13].x, LightofDawnLoc[13].y, LightofDawnLoc[13].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + { + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[16].x, LightofDawnLoc[16].y, LightofDawnLoc[16].z); + } + JumpToNextStep(10000); + } break; + case 4: + DoScriptText(SAY_LIGHT_OF_DAWN27, me); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); + SetHoldState(true); + break; + case 5: + DoScriptText(SAY_LIGHT_OF_DAWN33, me); + SetHoldState(true); + break; + case 6: + SetHoldState(true); + me->HandleEmoteCommand(EMOTE_ONESHOT_SPECIALATTACK1H); + JumpToNextStep(1000); + break; + case 7: + SetHoldState(true); + JumpToNextStep(2000); + break; + case 8: + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + me->CastSpell(pTemp, SPELL_ASHBRINGER, true); + DoScriptText(EMOTE_LIGHT_OF_DAWN14, me); + SetHoldState(true); + break; + } + } + + void EnterEvadeMode() + { + if (!bIsBattle)//do not reset self if we are in battle + npc_escortAI::EnterEvadeMode(); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (!bIsBattle) + { + if (uiPhase_timer <= diff) + { + // ******* Before battle ***************************************************************** + switch (uiStep) + { + case 0: // countdown + //UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 1); + break; + + case 1: // just delay + //UpdateWorldState(me->GetMap(), WORLD_STATE_REMAINS, 1); + UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 0); + UpdateWorldState(me->GetMap(), WORLD_STATE_EVENT_BEGIN, 1); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + JumpToNextStep(3000); + break; + + case 2: + DoScriptText(SAY_LIGHT_OF_DAWN04, me); + if (Creature* pKoltira = GetClosestCreatureWithEntry(me, NPC_KOLTIRA_DEATHWEAVER, 50.0f)) + uiKoltiraGUID = pKoltira->GetGUID(); + if (Creature* pOrbaz = GetClosestCreatureWithEntry(me, NPC_ORBAZ_BLOODBANE, 50.0f)) + uiOrbazGUID = pOrbaz->GetGUID(); + if (Creature* pThassarian = GetClosestCreatureWithEntry(me, NPC_THASSARIAN, 50.0f)) + uiThassarianGUID = pThassarian->GetGUID(); + JumpToNextStep(10000); + break; + + case 3: // rise + DoScriptText(SAY_LIGHT_OF_DAWN05, me); + JumpToNextStep(3000); + break; + + case 4: // summon ghoul + // Dunno whats the summon spell, so workaround + DoCast(me, 33271); // shack effect + uiPhase_timer = 500; + if (uiSummon_counter < ENCOUNTER_GHOUL_NUMBER) + { + Unit* pTemp = me->SummonCreature(NPC_ACHERUS_GHOUL, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->setFaction(2084); + uiGhoulGUID[uiSummon_counter] = pTemp->GetGUID(); + ++uiSummon_counter; + } + else + { + uiSummon_counter = 0; + ++uiStep; + } + break; + + case 5: // summon abomination + DoCast(me, 33271); // shack effect + uiPhase_timer = 500; + if (uiSummon_counter < ENCOUNTER_ABOMINATION_NUMBER) + { + Unit* pTemp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->setFaction(2084); + uiAbominationGUID[uiSummon_counter] = pTemp->GetGUID(); + ++uiSummon_counter; + } + else + { + uiSummon_counter = 0; + ++uiStep; + } + break; + + case 6: // summon warrior + DoCast(me, 33271); // shack effect + uiPhase_timer = 500; + if (uiSummon_counter < ENCOUNTER_WARRIOR_NUMBER) + { + Unit* pTemp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->setFaction(2084); + uiWarriorGUID[uiSummon_counter] = pTemp->GetGUID(); + ++uiSummon_counter; + } + else + { + uiSummon_counter = 0; + ++uiStep; + } + break; + + case 7: // summon warrior + DoCast(me, 33271); // shack effect + uiPhase_timer = 500; + if (uiSummon_counter < ENCOUNTER_BEHEMOTH_NUMBER) + { + Unit* pTemp = me->SummonCreature(NPC_FLESH_BEHEMOTH, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->setFaction(2084); + uiBehemothGUID[uiSummon_counter] = pTemp->GetGUID(); + ++uiSummon_counter; + } + else + { + uiSummon_counter = 0; + ++uiStep; + } + break; + + case 8: // summon announce + DoScriptText(SAY_LIGHT_OF_DAWN06, me); + JumpToNextStep(5000); + break; + + case 9: // charge begins + SetHoldState(false); + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + { + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) + { + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + { + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + } + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiAbominationGUID[i])) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiBehemothGUID[i])) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiGhoulGUID[i])) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiWarriorGUID[i])) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); + JumpToNextStep(5000); + break; + + // ******* After battle ***************************************************************** + case 11: // Tirion starts to speak + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN28, pTemp); + JumpToNextStep(21000); + break; + + case 12: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN29, pTemp); + JumpToNextStep(13000); + break; + + case 13: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN30, pTemp); + JumpToNextStep(13000); + break; + + case 14: + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_LIGHT_OF_DAWN31, me); + JumpToNextStep(7000); + break; + + case 15: // summon gate + if (Unit* pTemp = me->SummonCreature(NPC_HIGHLORD_ALEXANDROS_MOGRAINE, LightofDawnLoc[22].x, LightofDawnLoc[22].y, LightofDawnLoc[22].z, LightofDawnLoc[22].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) + { + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->CastSpell(pTemp, SPELL_ALEXANDROS_MOGRAINE_SPAWN, true); + DoScriptText(EMOTE_LIGHT_OF_DAWN06, pTemp); + uiAlexandrosGUID = pTemp->GetGUID(); + } + JumpToNextStep(4000); + break; + + case 16: // Alexandros out + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[23].x, LightofDawnLoc[23].y, LightofDawnLoc[23].z); + DoScriptText(SAY_LIGHT_OF_DAWN32, pTemp); + } + SetHoldState(false); // makes darion turns back + JumpToNextStep(5000); + break; + + case 17: + me->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(SAY_LIGHT_OF_DAWN34, me); + JumpToNextStep(5000); + break; + + case 18: // Darion's spirit out + if (Unit* pTemp = me->SummonCreature(NPC_DARION_MOGRAINE, LightofDawnLoc[24].x, LightofDawnLoc[24].y, LightofDawnLoc[24].z, LightofDawnLoc[24].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) + { + DoScriptText(SAY_LIGHT_OF_DAWN35, pTemp); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + uiDarionGUID = pTemp->GetGUID(); + } + JumpToNextStep(4000); + break; + + case 19: // runs to father + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + { + DoScriptText(EMOTE_LIGHT_OF_DAWN07, pTemp); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[25].x, LightofDawnLoc[25].y, LightofDawnLoc[25].z); + } + JumpToNextStep(4000); + break; + + case 20: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN36, pTemp); + JumpToNextStep(4000); + break; + + case 21: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + DoScriptText(EMOTE_LIGHT_OF_DAWN08, pTemp); + JumpToNextStep(4000); + break; + + case 22: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN37, pTemp); + JumpToNextStep(8000); + break; + + case 23: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN38, pTemp); + JumpToNextStep(8000); + break; + + case 24: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN39, pTemp); + + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) // Tirion moves forward here + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[1].x, LightofDawnLoc[1].y, LightofDawnLoc[1].z); + + JumpToNextStep(15000); + break; + + case 25: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN40, pTemp); + JumpToNextStep(11000); + break; + + case 26: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN41, pTemp); + JumpToNextStep(5000); + break; + + case 27: + if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) + pTemp->setDeathState(JUST_DIED); + JumpToNextStep(24000); + break; + + case 28: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN42, pTemp); + JumpToNextStep(6000); + break; + + case 29: // lich king spawns + if (Unit* pTemp = me->SummonCreature(NPC_THE_LICH_KING, LightofDawnLoc[26].x, LightofDawnLoc[26].y, LightofDawnLoc[26].z, LightofDawnLoc[26].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) + { + DoScriptText(SAY_LIGHT_OF_DAWN43, pTemp); + uiLichKingGUID = pTemp->GetGUID(); + if (Unit* pAlex = Unit::GetCreature(*me, uiAlexandrosGUID)) + pTemp->CastSpell(pAlex, SPELL_SOUL_FEAST_ALEX, false); + } + JumpToNextStep(2000); + break; + + case 30: + if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) // just hide him + { + DoScriptText(EMOTE_LIGHT_OF_DAWN09, pTemp); + pTemp->SetVisibility(VISIBILITY_OFF); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + pTemp->InterruptNonMeleeSpells(false); + DoScriptText(SAY_LIGHT_OF_DAWN45, pTemp); + } + JumpToNextStep(3000); + break; + + case 31: + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(EMOTE_LIGHT_OF_DAWN10, me); + DoScriptText(SAY_LIGHT_OF_DAWN44, me); + JumpToNextStep(3000); + break; + + case 32: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[27].x, LightofDawnLoc[27].y, LightofDawnLoc[27].z); + JumpToNextStep(6000); + break; + + case 33: // Darion supports to jump to lich king here + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoCast(me, SPELL_MOGRAINE_CHARGE); // jumping charge +// doesn't make it looks well, so workarounds, Darion charges, looks better + me->SetSpeed(MOVE_RUN, 3.0f); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + SetHoldState(false); + JumpToNextStep(0); + break; + + case 35: // Lich king counterattacks + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + pTemp->HandleEmoteCommand(EMOTE_ONESHOT_KICK); + DoScriptText(SAY_LIGHT_OF_DAWN46, pTemp); + } + me->SetSpeed(MOVE_RUN, 6.0f); + me->SetStandState(UNIT_STAND_STATE_DEAD); + SetHoldState(false); // Darion got kicked by lich king + JumpToNextStep(0); + break; + + case 37: // Lich king counterattacks + me->SetStandState(UNIT_STAND_STATE_KNEEL); + JumpToNextStep(3000); + break; + + case 38: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN47, pTemp); + JumpToNextStep(8000); + break; + + case 39: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN48, pTemp); + JumpToNextStep(15000); + break; + + case 40: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN49, pTemp); + JumpToNextStep(17000); + break; + + case 41: // Lich king - Apocalypse + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + DoScriptText(EMOTE_LIGHT_OF_DAWN11, pTemp); + DoScriptText(SAY_LIGHT_OF_DAWN51, pTemp); + if (Unit* pTirion = Unit::GetCreature(*me, uiTirionGUID)) + { + pTirion->SetStandState(UNIT_STAND_STATE_KNEEL); + //pTemp->CastSpell(pTirion, SPELL_APOCALYPSE, false); // not working + pTemp->CastSpell(pTirion, SPELL_SOUL_FEAST_TIRION, false); + DoScriptText(EMOTE_LIGHT_OF_DAWN12, pTirion); + } + } + JumpToNextStep(2000); + break; + + case 42: // Maxwell yells for attack + { + float fLichPositionX = 0, + fLichPositionY = 0, + fLichPositionZ = 0; + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + fLichPositionX = pTemp->GetPositionX(); + fLichPositionY = pTemp->GetPositionY(); + fLichPositionZ = pTemp->GetPositionZ(); + } + + if (fLichPositionX && fLichPositionY) + { + Unit* pTemp; + pTemp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->setFaction(me->getFaction()); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + uiDefenderGUID[0] = pTemp->GetGUID(); + + pTemp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->setFaction(me->getFaction()); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + uiEarthshatterGUID[0] = pTemp->GetGUID(); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + DoScriptText(SAY_LIGHT_OF_DAWN50, pTemp); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->HandleEmoteCommand(EMOTE_STATE_ATTACK_UNARMED); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->SetSpeed(MOVE_RUN, 2.0f); + pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); + } + } + JumpToNextStep(4500); + break; + + case 43: // They all got kicked + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(EMOTE_LIGHT_OF_DAWN13, pTemp); + + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[14].x, LightofDawnLoc[14].y, LightofDawnLoc[14].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[11].x, LightofDawnLoc[11].y, LightofDawnLoc[11].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[17].x, LightofDawnLoc[17].y, LightofDawnLoc[17].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiDefenderGUID[0])) + { + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[0])) + { + pTemp->SetSpeed(MOVE_RUN, 6.0f); + pTemp->SetStandState(UNIT_STAND_STATE_DEAD); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z); + } + JumpToNextStep(3000); + break; + + case 44: // make them stand up + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + JumpToNextStep(1000); + break; + + case 45: + DoScriptText(SAY_LIGHT_OF_DAWN52, me); + JumpToNextStep(5000); + break; + + case 46: // Darion stand up, "not today" + me->SetSpeed(MOVE_RUN, 1.0f); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_LIGHT_OF_DAWN53, me); + SetHoldState(false); // Darion throws sword + JumpToNextStep(7000); + break; + + case 47: // Ashbringer rebirth + me->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(EMOTE_LIGHT_OF_DAWN15, me); + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_HIGHLORD_TIRION_FORDRING)); + pTemp->CastSpell(pTemp, SPELL_REBIRTH_OF_THE_ASHBRINGER, false); + } + JumpToNextStep(1000); + break; + + case 48: // Show the cleansing effect (dawn of light) + //if (GameObject* pGo = me->GetMap()->GetGameObject(uiDawnofLightGUID)) + // pGo->SetPhaseMask(128, true); + me->SummonGameObject(GO_LIGHT_OF_DAWN, 2283.896, -5287.914, 83.066, 0, 0, 0, 0, 0, 30000); + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + if (pTemp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER, 0)) + pTemp->RemoveAurasDueToSpell(SPELL_REBIRTH_OF_THE_ASHBRINGER); + pTemp->CastSpell(pTemp, 41542, false); // workarounds, light expoded, makes it cool + pTemp->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + } + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->InterruptNonMeleeSpells(false); + JumpToNextStep(2500); + break; + + case 49: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN54, pTemp); + JumpToNextStep(4000); + break; + + case 50: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN55, pTemp); + JumpToNextStep(5000); + break; + + case 51: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN56, pTemp); + JumpToNextStep(1000); + break; + + case 52: // Tiron charges + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + DoScriptText(EMOTE_LIGHT_OF_DAWN16, pTemp); + pTemp->CastSpell(pTemp, SPELL_TIRION_CHARGE, false); // jumping charge + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); + pTemp->SetSpeed(MOVE_RUN, 3.0f); // workarounds, make Tirion still running + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2].x, LightofDawnLoc[2].y, LightofDawnLoc[2].z); + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->Relocate(LightofDawnLoc[28].x, LightofDawnLoc[28].y, LightofDawnLoc[28].z); // workarounds, he should kick back by Tirion, but here we relocate him + } + JumpToNextStep(1500); + break; + + case 53: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN57, pTemp); + JumpToNextStep(1000); + break; + + case 54: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + { + pTemp->SetSpeed(MOVE_RUN, 1.0f); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29].x, LightofDawnLoc[29].y, LightofDawnLoc[29].z); // 26 + } + JumpToNextStep(4000); + break; + + case 55: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); + JumpToNextStep(2000); + break; + + case 56: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_STAND); + JumpToNextStep(1500); + break; + + case 57: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN58, pTemp); + JumpToNextStep(10000); + break; + + case 58: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN59, pTemp); + JumpToNextStep(10000); + break; + + case 59: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) + pTemp->CastSpell(pTemp, SPELL_TELEPORT_VISUAL, false); + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) // Tirion runs to Darion + { + pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + pTemp->SetSpeed(MOVE_RUN, 1.0f); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[6].x, LightofDawnLoc[6].y, LightofDawnLoc[6].z); + } + JumpToNextStep(2500); + break; + + case 60: + if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) // Lich king disappears here + { + DoScriptText(EMOTE_LIGHT_OF_DAWN17, pTemp); + pTemp->Kill(pTemp); + } + JumpToNextStep(10000); + break; + + case 61: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN60, pTemp); + JumpToNextStep(3000); + break; + + case 62: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[7].x, LightofDawnLoc[7].y, LightofDawnLoc[7].z); + } + JumpToNextStep(5500); + break; + + case 63: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + { + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[8].x, LightofDawnLoc[8].y, LightofDawnLoc[8].z); + DoScriptText(SAY_LIGHT_OF_DAWN61, pTemp); + } + JumpToNextStep(15000); + break; + + case 64: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN62, pTemp); + JumpToNextStep(7000); + break; + + case 65: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN63, pTemp); + JumpToNextStep(10000); + break; + + case 66: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN64, pTemp); + JumpToNextStep(11000); + break; + + case 67: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN65, pTemp); + JumpToNextStep(10000); + break; + + case 68: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN66, pTemp); + JumpToNextStep(8000); + break; + + case 69: + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN67, pTemp); + JumpToNextStep(10000); + break; + + case 70: + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_LIGHT_OF_DAWN68, me); + JumpToNextStep(10000); + break; + + case 71: + //if (GameObject* pGo = me->GetMap()->GetGameObject(uiDawnofLightGUID)) // Turn off dawn of light + // pGo->SetPhaseMask(0, true); + + { + Map *map = me->GetMap(); // search players with in 50 yards for quest credit + Map::PlayerList const &PlayerList = map->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->isAlive() && me->IsWithinDistInMap(i->getSource(), 50)) + i->getSource()->CastSpell(i->getSource(), SPELL_THE_LIGHT_OF_DAWN_Q, false); + } + } + me->SetVisibility(VISIBILITY_OFF); // respawns another Darion for quest turn in + me->SummonCreature(NPC_HIGHLORD_DARION_MOGRAINE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); + JumpToNextStep(1000); + break; + + case 72: + SetHoldState(false); // Escort ends + JumpToNextStep(25000); + break; + + case 73: + me->ForcedDespawn(); + break; + } + + } else uiPhase_timer -= diff; + } + + // ******* During battle ***************************************************************** + else + { + if (uiAnti_magic_zone <= diff) + { + DoCast(me, SPELL_ANTI_MAGIC_ZONE1); + uiAnti_magic_zone = 25000 + rand()%5000; + } else uiAnti_magic_zone -= diff; + + if (uiDeath_strike <= diff) + { + DoCast(me->getVictim(), SPELL_DEATH_STRIKE); + uiDeath_strike = 5000 + rand()%5000; + } else uiDeath_strike -= diff; + + if (uiDeath_embrace <= diff) + { + DoCast(me->getVictim(), SPELL_DEATH_EMBRACE); + uiDeath_embrace = 5000 + rand()%5000; + } else uiDeath_embrace -= diff; + + if (uiIcy_touch <= diff) + { + DoCast(me->getVictim(), SPELL_ICY_TOUCH1); + uiIcy_touch = 5000 + rand()%5000; + } else uiIcy_touch -= diff; + + if (uiUnholy_blight <= diff) + { + DoCast(me->getVictim(), SPELL_UNHOLY_BLIGHT); + uiUnholy_blight = 5000 + rand()%5000; + } else uiUnholy_blight -= diff; + + if (uiFight_speech <= diff) + { + DoScriptText(RAND(SAY_LIGHT_OF_DAWN09,SAY_LIGHT_OF_DAWN10,SAY_LIGHT_OF_DAWN11, + SAY_LIGHT_OF_DAWN12,SAY_LIGHT_OF_DAWN13,SAY_LIGHT_OF_DAWN14, + SAY_LIGHT_OF_DAWN15,SAY_LIGHT_OF_DAWN16,SAY_LIGHT_OF_DAWN17, + SAY_LIGHT_OF_DAWN18,SAY_LIGHT_OF_DAWN19,SAY_LIGHT_OF_DAWN20, + SAY_LIGHT_OF_DAWN21,SAY_LIGHT_OF_DAWN22,SAY_LIGHT_OF_DAWN23, + SAY_LIGHT_OF_DAWN24), me); + uiFight_speech = 15000 + rand()%5000; + } else uiFight_speech -= diff; + + // Check spawns + if (uiSpawncheck <= diff) + { + SpawnNPC(); + uiSpawncheck = 1000; + } else uiSpawncheck -= diff; + + // Check targets + if (uiTargetcheck <= diff) + { + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + NPCChangeTarget(uiGhoulGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + NPCChangeTarget(uiWarriorGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + NPCChangeTarget(uiAbominationGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + NPCChangeTarget(uiBehemothGUID[i]); + NPCChangeTarget(uiKoltiraGUID); + NPCChangeTarget(uiOrbazGUID); + NPCChangeTarget(uiThassarianGUID); + + uiTargetcheck = 10000; + } else uiTargetcheck -= diff; + + // Battle end + if (uiFight_duration <= diff + 5000) + { + if (!uiTirionGUID) + if (Unit* pTemp = me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING, LightofDawnLoc[0].x, LightofDawnLoc[0].y, LightofDawnLoc[0].z, 1.528, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000)) + { + pTemp->setFaction(me->getFaction()); + pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); + DoScriptText(SAY_LIGHT_OF_DAWN25, pTemp); + uiTirionGUID = pTemp->GetGUID(); + } + } + if (uiFight_duration <= diff) + { + bIsBattle = false; + uiFight_duration = 300000; + + if (me->HasAura(SPELL_THE_MIGHT_OF_MOGRAINE, 0)) + me->RemoveAurasDueToSpell(SPELL_THE_MIGHT_OF_MOGRAINE); + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + me->InterruptNonMeleeSpells(false); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) + DespawnNPC(uiDefenderGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) + DespawnNPC(uiEarthshatterGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + DespawnNPC(uiAbominationGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + DespawnNPC(uiBehemothGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + DespawnNPC(uiGhoulGUID[i]); + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + DespawnNPC(uiWarriorGUID[i]); + + if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[9].x, LightofDawnLoc[9].y, LightofDawnLoc[9].z); + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[12].x, LightofDawnLoc[12].y, LightofDawnLoc[12].z); + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[15].x, LightofDawnLoc[15].y, LightofDawnLoc[15].z); + } + DespawnNPC(uiRayneGUID); + + if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[18].x, LightofDawnLoc[18].y, LightofDawnLoc[18].z); + pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false); + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) + DoScriptText(EMOTE_LIGHT_OF_DAWN04, pTemp); + + if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) + { + pTemp->RemoveAllAuras(); + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->AttackStop(); + pTemp->setFaction(me->getFaction()); + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[20].x, LightofDawnLoc[20].y, LightofDawnLoc[20].z); + pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false); + } + + if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) + DoScriptText(SAY_LIGHT_OF_DAWN26, pTemp); + + SetHoldState(false); + + } else uiFight_duration -= diff; + + DoMeleeAttackIfReady(); + } + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhase_timer = uiTimer; + ++uiStep; + } + + void NPCChangeTarget(uint64 ui_GUID) + { + if (Creature* pTemp = Unit::GetCreature(*me, ui_GUID)) + if (pTemp->isAlive()) + if (Unit* pTarger = SelectUnit(SELECT_TARGET_RANDOM,0)) + if (pTarger->isAlive()) + { + // pTemp->DeleteThreatList(); + pTemp->AddThreat(pTarger, 0.0f); + pTemp->AI()->AttackStart(pTarger); + pTemp->SetInCombatWith(pTarger); + pTarger->SetInCombatWith(pTemp); + // pTemp->GetMotionMaster()->MoveChase(pTarger, 20.0f); + } + } + + void SpawnNPC() + { + Unit* pTemp = NULL; + + // Death + for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiGhoulGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_ACHERUS_GHOUL, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2084); + uiGhoulGUID[i] = pTemp->GetGUID(); + } + } + for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiAbominationGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2084); + uiAbominationGUID[i] = pTemp->GetGUID(); + } + } + for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiWarriorGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2084); + uiWarriorGUID[i] = pTemp->GetGUID(); + } + } + for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiBehemothGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_FLESH_BEHEMOTH, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2084); + uiBehemothGUID[i] = pTemp->GetGUID(); + } + } + + // Dawn + for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiDefenderGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiDefenderGUID[i] = pTemp->GetGUID(); + } + } + for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) + { + pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[i]); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiEarthshatterGUID[i] = pTemp->GetGUID(); + } + } + pTemp = Unit::GetCreature(*me, uiKorfaxGUID); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_KORFAX_CHAMPION_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiKorfaxGUID = pTemp->GetGUID(); + } + pTemp = Unit::GetCreature(*me, uiMaxwellGUID); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_LORD_MAXWELL_TYROSUS, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiMaxwellGUID = pTemp->GetGUID(); + } + pTemp = Unit::GetCreature(*me, uiEligorGUID); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_COMMANDER_ELIGOR_DAWNBRINGER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiEligorGUID = pTemp->GetGUID(); + } + pTemp = Unit::GetCreature(*me, uiRayneGUID); + if (!pTemp) + { + pTemp = me->SummonCreature(NPC_RAYNE, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); + pTemp->setFaction(2089); + me->AddThreat(pTemp, 0.0f); + uiRayneGUID = pTemp->GetGUID(); + } + } + + void DespawnNPC(uint64 pGUID) + { + if (Creature* pTemp = Unit::GetCreature(*me, pGUID)) + if (pTemp->isAlive()) + { + pTemp->SetVisibility(VISIBILITY_OFF); + pTemp->Kill(pTemp); + } + } +}; + +bool GossipHello_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(12801) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(0, "I am ready.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_highlord_darion_mograineAI, pCreature->AI())->uiStep = 1; + CAST_AI(npc_highlord_darion_mograineAI, pCreature->AI())->Start(true, false, pPlayer->GetGUID()); + break; + } + return true; +} + +/*###### +## npc the lich king in dawn of light +######*/ +struct npc_the_lich_king_tirion_dawnAI : public ScriptedAI +{ + npc_the_lich_king_tirion_dawnAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + void Reset() {} + void AttackStart(Unit * /*who*/) {} // very sample, just don't make them aggreesive + void UpdateAI(const uint32 /*diff*/) {} + void JustDied(Unit* /*killer*/) {} +}; + +CreatureAI* GetAI_npc_highlord_darion_mograine(Creature* pCreature) +{ + return new npc_highlord_darion_mograineAI(pCreature); +} + +CreatureAI* GetAI_npc_the_lich_king_tirion_dawn(Creature* pCreature) +{ + return new npc_the_lich_king_tirion_dawnAI (pCreature); +} + +void AddSC_the_scarlet_enclave_c5() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_highlord_darion_mograine"; + newscript->GetAI = &GetAI_npc_highlord_darion_mograine; + newscript->pGossipHello = &GossipHello_npc_highlord_darion_mograine; + newscript->pGossipSelect = &GossipSelect_npc_highlord_darion_mograine; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_the_lich_king_tirion_dawn"; + newscript->GetAI = &GetAI_npc_the_lich_king_tirion_dawn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave.cpp new file mode 100644 index 00000000000..cdfd69234fb --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" + +/*#### +## npc_valkyr_battle_maiden +####*/ +#define SPELL_REVIVE 51918 +#define VALK_WHISPER "It is not yet your time, champion. Rise! Rise and fight once more!" + +struct npc_valkyr_battle_maidenAI : public PassiveAI +{ + npc_valkyr_battle_maidenAI(Creature *c) : PassiveAI(c) {} + + uint32 FlyBackTimer; + float x, y, z; + uint32 phase; + + void Reset() + { + me->setActive(true); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlying(true); + FlyBackTimer = 500; + phase = 0; + + me->GetPosition(x, y, z); + z += 4; x -= 3.5; y -= 5; + me->GetMotionMaster()->Clear(false); + me->GetMap()->CreatureRelocation(me, x, y, z, 0.0f); + } + + void UpdateAI(const uint32 diff) + { + if (FlyBackTimer <= diff) + { + Player *plr = NULL; + if (me->isSummon()) + if (Unit *summoner = CAST_SUM(me)->GetSummoner()) + if (summoner->GetTypeId() == TYPEID_PLAYER) + plr = CAST_PLR(summoner); + + if (!plr) + phase = 3; + + switch(phase) + { + case 0: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->HandleEmoteCommand(EMOTE_STATE_FLYGRABCLOSED); + FlyBackTimer = 500; + break; + case 1: + plr->GetClosePoint(x,y,z, me->GetObjectSize()); + z += 2.5; x -= 2; y -= 1.5; + me->GetMotionMaster()->MovePoint(0, x, y, z); + me->SetUInt64Value(UNIT_FIELD_TARGET, plr->GetGUID()); + me->SetVisibility(VISIBILITY_ON); + FlyBackTimer = 4500; + break; + case 2: + if (!plr->isRessurectRequested()) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_CUSTOMSPELL01); + DoCast(plr, SPELL_REVIVE, true); + me->MonsterWhisper(VALK_WHISPER, plr->GetGUID()); + } + FlyBackTimer = 5000; + break; + case 3: + me->SetVisibility(VISIBILITY_OFF); + FlyBackTimer = 3000; + break; + case 4: + me->DisappearAndDie(); + break; + default: + //Nothing To DO + break; + } + ++phase; + } else FlyBackTimer-=diff; + } +}; + +CreatureAI* GetAI_npc_valkyr_battle_maiden(Creature* pCreature) +{ + return new npc_valkyr_battle_maidenAI (pCreature); +} + +void AddSC_the_scarlet_enclave() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_valkyr_battle_maiden"; + newscript->GetAI = &GetAI_npc_valkyr_battle_maiden; + newscript->RegisterSelf(); + + // Chapter 3: Scarlet Armies Approach... - An End To All Things... + // Chapter 4: An End To All Things... - An End To All Things... +} diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp new file mode 100644 index 00000000000..cb6ed1daf22 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp @@ -0,0 +1,128 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Arcanist_Doan +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1189019, + SAY_SPECIALAE = -1189020, + + SPELL_POLYMORPH = 13323, + SPELL_AOESILENCE = 8988, + SPELL_ARCANEEXPLOSION = 9433, + SPELL_FIREAOE = 9435, + SPELL_ARCANEBUBBLE = 9438, +}; + +struct boss_arcanist_doanAI : public ScriptedAI +{ + boss_arcanist_doanAI(Creature *c) : ScriptedAI(c) {} + + uint32 Polymorph_Timer; + uint32 AoESilence_Timer; + uint32 ArcaneExplosion_Timer; + bool bCanDetonate; + bool bShielded; + + void Reset() + { + Polymorph_Timer = 20000; + AoESilence_Timer = 15000; + ArcaneExplosion_Timer = 3000; + bCanDetonate = false; + bShielded = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (bShielded && bCanDetonate) + { + DoCast(me, SPELL_FIREAOE); + bCanDetonate = false; + } + + if (me->HasAura(SPELL_ARCANEBUBBLE)) + return; + + //If we are <50% hp cast Arcane Bubble + if (!bShielded && me->GetHealth()*100 / me->GetMaxHealth() <= 50) + { + //wait if we already casting + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoScriptText(SAY_SPECIALAE, me); + DoCast(me, SPELL_ARCANEBUBBLE); + + bCanDetonate = true; + bShielded = true; + } + + if (Polymorph_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_POLYMORPH); + + Polymorph_Timer = 20000; + } else Polymorph_Timer -= diff; + + //AoESilence_Timer + if (AoESilence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_AOESILENCE); + AoESilence_Timer = 15000 + rand()%5000; + } else AoESilence_Timer -= diff; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANEEXPLOSION); + ArcaneExplosion_Timer = 8000; + } else ArcaneExplosion_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_arcanist_doan(Creature* pCreature) +{ + return new boss_arcanist_doanAI (pCreature); +} + +void AddSC_boss_arcanist_doan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_arcanist_doan"; + newscript->GetAI = &GetAI_boss_arcanist_doan; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp new file mode 100644 index 00000000000..6b6efa0f934 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Azshir_the_Sleepless +SD%Complete: 80 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CALLOFTHEGRAVE 17831 +#define SPELL_TERRIFY 7399 +#define SPELL_SOULSIPHON 7290 + +struct boss_azshir_the_sleeplessAI : public ScriptedAI +{ + boss_azshir_the_sleeplessAI(Creature *c) : ScriptedAI(c) {} + + uint32 SoulSiphon_Timer; + uint32 CallOftheGrave_Timer; + uint32 Terrify_Timer; + + void Reset() + { + SoulSiphon_Timer = 1; + CallOftheGrave_Timer = 30000; + Terrify_Timer = 20000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <50% hp cast Soul Siphon rank 1 + if (me->GetHealth()*100 / me->GetMaxHealth() <= 50 && !me->IsNonMeleeSpellCasted(false)) + { + //SoulSiphon_Timer + if (SoulSiphon_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOULSIPHON); + return; + + //SoulSiphon_Timer = 20000; + } else SoulSiphon_Timer -= diff; + } + + //CallOfTheGrave_Timer + if (CallOftheGrave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CALLOFTHEGRAVE); + CallOftheGrave_Timer = 30000; + } else CallOftheGrave_Timer -= diff; + + //Terrify_Timer + if (Terrify_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TERRIFY); + Terrify_Timer = 20000; + } else Terrify_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_azshir_the_sleepless(Creature* pCreature) +{ + return new boss_azshir_the_sleeplessAI (pCreature); +} + +void AddSC_boss_azshir_the_sleepless() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_azshir_the_sleepless"; + newscript->GetAI = &GetAI_boss_azshir_the_sleepless; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp new file mode 100644 index 00000000000..f7b6b7cce4b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp @@ -0,0 +1,124 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Bloodmage_Thalnos +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1189016, + SAY_HEALTH = -1189017, + SAY_KILL = -1189018, + + SPELL_FLAMESHOCK = 8053, + SPELL_SHADOWBOLT = 1106, + SPELL_FLAMESPIKE = 8814, + SPELL_FIRENOVA = 16079, +}; + +struct boss_bloodmage_thalnosAI : public ScriptedAI +{ + boss_bloodmage_thalnosAI(Creature *c) : ScriptedAI(c) {} + + bool HpYell; + uint32 FlameShock_Timer; + uint32 ShadowBolt_Timer; + uint32 FlameSpike_Timer; + uint32 FireNova_Timer; + + void Reset() + { + HpYell = false; + FlameShock_Timer = 10000; + ShadowBolt_Timer = 2000; + FlameSpike_Timer = 8000; + FireNova_Timer = 40000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*Victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <35% hp + if (!HpYell && ((me->GetHealth()*100) / me->GetMaxHealth() <= 35)) + { + DoScriptText(SAY_HEALTH, me); + HpYell = true; + } + + //FlameShock_Timer + if (FlameShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMESHOCK); + FlameShock_Timer = 10000 + rand()%5000; + } else FlameShock_Timer -= diff; + + //FlameSpike_Timer + if (FlameSpike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMESPIKE); + FlameSpike_Timer = 30000; + } else FlameSpike_Timer -= diff; + + //FireNova_Timer + if (FireNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRENOVA); + FireNova_Timer = 40000; + } else FireNova_Timer -= diff; + + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLT); + ShadowBolt_Timer = 2000; + } else ShadowBolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bloodmage_thalnos(Creature* pCreature) +{ + return new boss_bloodmage_thalnosAI (pCreature); +} + +void AddSC_boss_bloodmage_thalnos() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_bloodmage_thalnos"; + newscript->GetAI = &GetAI_boss_bloodmage_thalnos; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp new file mode 100644 index 00000000000..17bbf0c23c6 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp @@ -0,0 +1,892 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Headless_Horseman +SD%Complete: +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "SpellMgr.h" +#include "scarlet_monastery.h" + +//this texts are already used by 3975 and 3976 +#define SAY_ENTRANCE -1189001 +#define SAY_REJOINED -1189002 +#define SAY_LOST_HEAD -1189003 +#define SAY_CONFLAGRATION -1189004 +#define SAY_SPROUTING_PUMPKINS -1189005 +#define SAY_PLAYER_DEATH -1189006 +#define SAY_DEATH -1189007 + +uint32 RandomLaugh[] = {11965, 11975, 11976}; + + // Entryes +#define HH_MOUNTED 23682 +#define HH_UNHORSED 23800 +#define HEAD 23775 +#define PULSING_PUMPKIN 23694 +#define PUMPKIN_FIEND 23545 +#define HELPER 23686 +#define WISP_INVIS 24034 + + //Spells +#define SPELL_CLEAVE 42587 +#define SPELL_CONFLAGRATION 42380 //Phase 2, can't find real spell(Dim Fire?) +//#define SPELL_CONFL_SPEED 22587 //8% increase speed, value 22587 from SPELL_CONFLAGRATION mains that spell? +#define SPELL_SUMMON_PUMPKIN 42394 + +#define SPELL_WHIRLWIND 43116 +#define SPELL_IMMUNE 42556 +#define SPELL_BODY_REGEN 42403 +#define SPELL_CONFUSE 43105 + +#define SPELL_FLYING_HEAD 42399 //visual flying head +#define SPELL_HEAD 42413 //visual buff, "head" +#define SPELL_HEAD_IS_DEAD 42428 //at killing head, Phase 3 + +#define SPELL_PUMPKIN_AURA 42280 +#define SPELL_PUMPKIN_AURA_GREEN 42294 +#define SPELL_SQUASH_SOUL 42514 +#define SPELL_SPROUTING 42281 +#define SPELL_SPROUT_BODY 42285 + + //Effects +#define SPELL_RHYME_BIG 42909 +//#define SPELL_RHYME_SMALL 42910 +#define SPELL_HEAD_SPEAKS 43129 +#define SPELL_HEAD_LANDS 42400 +#define SPELL_BODY_FLAME 42074 +#define SPELL_HEAD_FLAME 42971 +//#define SPELL_ENRAGE_VISUAL 42438 // he uses this spell? +#define SPELL_WISP_BLUE 42821 +#define SPELL_WISP_FLIGHT_PORT 42818 +//#define SPELL_WISP_INVIS 42823 +#define SPELL_SMOKE 42355 +#define SPELL_DEATH 42566 //not correct spell + +struct Locations +{ + float x, y, z; +}; + +static Locations FlightPoint[]= +{ + {1754.00,1346.00,17.50}, + {1765.00,1347.00,19.00}, + {1784.00,1346.80,25.40}, + {1803.30,1347.60,33.00}, + {1824.00,1350.00,42.60}, + {1838.80,1353.20,49.80}, + {1852.00,1357.60,55.70}, + {1861.30,1364.00,59.40}, + {1866.30,1374.80,61.70}, + {1864.00,1387.30,63.20}, + {1854.80,1399.40,64.10}, + {1844.00,1406.90,64.10}, + {1824.30,1411.40,63.30}, + {1801.00,1412.30,60.40}, + {1782.00,1410.10,55.50}, + {1770.50,1405.20,50.30}, + {1765.20,1400.70,46.60}, + {1761.40,1393.40,41.70}, + {1759.10,1386.70,36.60}, + {1757.80,1378.20,29.00}, + {1758.00,1367.00,19.51} +}; + +static Locations Spawn[]= +{ + {1776.27,1348.74,19.20}, //spawn point for pumpkin shrine mob + {1765.28,1347.46,17.55} //spawn point for smoke +}; + +static const char* Text[]= +{ + "Horseman rise...", + "Your time is nigh...", + "You felt death once...", + "Now, know demise!" +}; + +#define EMOTE_LAUGHS "Headless Horseman laughs" + +struct mob_wisp_invisAI : public ScriptedAI +{ + mob_wisp_invisAI(Creature *c) : ScriptedAI(c) + { + Creaturetype = delay = spell = spell2 = 0; + //that's hack but there are no info about range of this spells in dbc + SpellEntry *wisp = GET_SPELL(SPELL_WISP_BLUE); + if (wisp) + wisp->rangeIndex = 6; //100 yards + SpellEntry *port = GET_SPELL(SPELL_WISP_FLIGHT_PORT); + if (port) + port->rangeIndex = 6; + } + + uint32 Creaturetype; + uint32 delay; + uint32 spell; + uint32 spell2; + void Reset(){} + void EnterCombat(Unit * /*who*/){} + void SetType(uint32 _type) + { + switch(Creaturetype = _type) + { + case 1: + spell = SPELL_PUMPKIN_AURA_GREEN; + break; + case 2: + delay = 15000; + spell = SPELL_BODY_FLAME; + spell2 = SPELL_DEATH; + break; + case 3: + delay = 15000; + spell = SPELL_SMOKE; + break; + case 4: + delay = 7000; + spell2 = SPELL_WISP_BLUE; + break; + } + if (spell) + DoCast(me, spell); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_WISP_FLIGHT_PORT && Creaturetype == 4) + me->SetDisplayId(2027); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || Creaturetype != 1 || !who->isTargetableForAttack()) + return; + + if (me->IsWithinDist(who, 0.1, false) && !who->HasAura(SPELL_SQUASH_SOUL)) + DoCast(who, SPELL_SQUASH_SOUL); + } + + void UpdateAI(const uint32 diff) + { + if (delay) + { + if (delay <= diff) + { + me->RemoveAurasDueToSpell(SPELL_SMOKE); + if (spell2) + DoCast(me, spell2); + delay = 0; + } else delay -= diff; + } + } +}; + +struct mob_headAI : public ScriptedAI +{ + mob_headAI(Creature *c) : ScriptedAI(c) {} + + uint64 bodyGUID; + + uint32 Phase; + uint32 laugh; + uint32 wait; + + bool withbody; + bool die; + + void Reset() + { + Phase = 0; + bodyGUID = 0; + die = false; + withbody = true; + wait = 1000; + laugh = urand(15000,30000); + } + + void EnterCombat(Unit * /*who*/) {} + void SaySound(int32 textEntry, Unit *pTarget = 0) + { + DoScriptText(textEntry, me, pTarget); + //DoCast(me, SPELL_HEAD_SPEAKS, true); + Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000); + if (speaker) + speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); + laugh += 3000; + } + + void DamageTaken(Unit* /*done_by*/,uint32 &damage) + { + if (withbody) + return; + + switch(Phase) + { + case 1: + if (((me->GetHealth() - damage)*100)/me->GetMaxHealth() < 67) + Disappear(); + break; + case 2: + if (((me->GetHealth() - damage)*100)/me->GetMaxHealth() < 34) + Disappear(); + break; + case 3: + if (damage >= me->GetHealth()) + { + die = true; + withbody = true; + wait = 300; + damage = me->GetHealth() - me->GetMaxHealth()/100; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->StopMoving(); + //me->GetMotionMaster()->MoveIdle(); + DoCast(me, SPELL_HEAD_IS_DEAD); + } + break; + } + } + + void SpellHit(Unit *caster, const SpellEntry* spell) + { + if (!withbody) + return; + + if (spell->Id == SPELL_FLYING_HEAD) + { + if (Phase < 3) ++Phase; + else Phase = 3; + withbody = false; + if (!bodyGUID) + bodyGUID = caster->GetGUID(); + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_HEAD_LANDS, true); + DoCast(me, SPELL_HEAD, false); + SaySound(SAY_LOST_HEAD); + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveFleeing(caster->getVictim()); + } + } + void Disappear();//we must set returned=true(this will prevent from "body calls head" while head flying to body), see function below + void UpdateAI(const uint32 diff) + { + if (!withbody) + { + if (wait <= diff) + { + wait = 1000; + if (!me->getVictim()) return; + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveFleeing(me->getVictim()); + } else wait -= diff; + + if (laugh <= diff) + { + laugh = urand(15000,30000); + DoPlaySoundToSet(me, RandomLaugh[urand(0,2)]); + //DoCast(me, SPELL_HEAD_SPEAKS, true); //this spell remove buff "head" + Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000); + if (speaker) + speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); + me->MonsterTextEmote(EMOTE_LAUGHS,NULL); + } else laugh -= diff; + } + else + { + if (die) + { + if (wait <= diff) + { + die = false; + if (Unit *body = Unit::GetUnit((*me), bodyGUID)) + body->Kill(body); + me->Kill(me); + } else wait -= diff; + } + } + } +}; + +struct boss_headless_horsemanAI : public ScriptedAI +{ + boss_headless_horsemanAI(Creature *c) : ScriptedAI(c) + { + SpellEntry *confl = GET_SPELL(SPELL_CONFLAGRATION); + if (confl) + { + confl->EffectApplyAuraName[0] = SPELL_AURA_PERIODIC_DAMAGE_PERCENT; + confl->EffectBasePoints[0] = 10; + //confl->EffectBaseDice[0] = 10; + confl->DmgMultiplier[0] = 1; + } +/* + if (SpellEntry *confl = GET_SPELL(SPELL_CONFLAGRATION)) + confl->EffectTriggerSpell[1] = 22587; + + if (SpellEntry *speed = GET_SPELL(22587)) + { + speed->Effect[1] = SPELL_EFFECT_APPLY_AURA; + speed->EffectApplyAuraName[1] = SPELL_AURA_MOD_CONFUSE; + } +*/ + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint64 headGUID; + uint64 PlayerGUID; + + uint32 Phase; + uint32 id; + uint32 count; + uint32 say_timer; + + uint32 conflagrate; + uint32 summonadds; + uint32 cleave; + uint32 regen; + uint32 whirlwind; + uint32 laugh; + uint32 burn; + + bool withhead; + bool returned; + bool IsFlying; + bool wp_reached; + bool burned; + + void Reset() + { + Phase = 1; + conflagrate = 15000; + summonadds = 15000; + laugh = urand(16000,20000); + cleave = 2000; + regen = 1000; + burn = 6000; + count = 0; + say_timer = 3000; + + withhead = true; + returned = true; + burned = false; + IsFlying = false; + DoCast(me, SPELL_HEAD); + if (headGUID) + { + if (Creature* Head = Unit::GetCreature((*me), headGUID)) + Head->DisappearAndDie(); + + headGUID = 0; + } + + //if (pInstance) + // pInstance->SetData(DATA_HORSEMAN_EVENT, NOT_STARTED); + } + + void FlyMode() + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + me->SetSpeed(MOVE_WALK,5.0f,true); + wp_reached = false; + count = 0; + say_timer = 3000; + id = 0; + Phase = 0; + } + + void MovementInform(uint32 type, uint32 i) + { + if (type != POINT_MOTION_TYPE || !IsFlying || i != id) + return; + + wp_reached = true; + + switch (id) + { + case 0: + me->SetVisibility(VISIBILITY_ON); + break; + case 1: + { + if (Creature *smoke = me->SummonCreature(HELPER,Spawn[1].x,Spawn[1].y,Spawn[1].z,0,TEMPSUMMON_TIMED_DESPAWN,20000)) + CAST_AI(mob_wisp_invisAI, smoke->AI())->SetType(3); + DoCast(me, SPELL_RHYME_BIG); + break; + } + case 6: + if (pInstance) + pInstance->SetData(GAMEOBJECT_PUMPKIN_SHRINE, 0); //hide gameobject + break; + case 19: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + break; + case 20: + { + Phase = 1; + IsFlying = false; + wp_reached = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SaySound(SAY_ENTRANCE); + if (Unit *plr = Unit::GetUnit((*me),PlayerGUID)) + DoStartMovement(plr); + break; + } + } + ++id; + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); + DoZoneInCombat(); + } + void AttackStart(Unit* who) {ScriptedAI::AttackStart(who);} + void MoveInLineOfSight(Unit *who) + { + if (withhead && Phase != 0) + ScriptedAI::MoveInLineOfSight(who); + } + void KilledUnit(Unit *plr) + { + if (plr->GetTypeId() == TYPEID_PLAYER) + { + if (withhead) + SaySound(SAY_PLAYER_DEATH); + //maybe possible when player dies from conflagration + else if (Creature *Head = Unit::GetCreature((*me), headGUID)) + CAST_AI(mob_headAI, Head->AI())->SaySound(SAY_PLAYER_DEATH); + } + } + + void SaySound(int32 textEntry, Unit *pTarget = 0) + { + DoScriptText(textEntry, me, pTarget); + laugh += 4000; + } + + Player* SelectRandomPlayer(float range = 0.0f, bool checkLoS = true) + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) return NULL; + + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + Map::PlayerList::const_iterator i; + if (PlayerList.isEmpty()) return NULL; + + std::list temp; + std::list::const_iterator j; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if ((me->IsWithinLOSInMap(i->getSource()) || !checkLoS) && me->getVictim() != i->getSource() && + me->IsWithinDistInMap(i->getSource(), range) && i->getSource()->isAlive()) + temp.push_back(i->getSource()); + + if (temp.size()) + { + j = temp.begin(); + advance(j, rand()%temp.size()); + return (*j); + } + return NULL; + } + + void SpellHitTarget(Unit* unit, const SpellEntry* spell) + { + if (spell->Id == SPELL_CONFLAGRATION && unit->HasAura(SPELL_CONFLAGRATION)) + SaySound(SAY_CONFLAGRATION,unit); + } + + void JustDied(Unit* /*killer*/) + { + me->StopMoving(); + //me->GetMotionMaster()->MoveIdle(); + SaySound(SAY_DEATH); + if (Creature *flame = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000)) + flame->CastSpell(flame,SPELL_BODY_FLAME,false); + if (Creature *wisp = DoSpawnCreature(WISP_INVIS,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000)) + CAST_AI(mob_wisp_invisAI, wisp->AI())->SetType(4); + if (pInstance) + pInstance->SetData(DATA_HORSEMAN_EVENT, DONE); + } + + void SpellHit(Unit *caster, const SpellEntry* spell) + { + if (withhead) + return; + + if (spell->Id == SPELL_FLYING_HEAD) + { + if (Phase < 3) + ++Phase; + else + Phase = 3; + withhead = true; + me->RemoveAllAuras(); + me->SetName("Headless Horseman"); + me->SetHealth(me->GetMaxHealth()); + SaySound(SAY_REJOINED); + DoCast(me, SPELL_HEAD); + caster->GetMotionMaster()->Clear(false); + caster->GetMotionMaster()->MoveFollow(me,6,urand(0,5)); + //DoResetThreat();//not sure if need + std::list::const_iterator itr; + for (itr = caster->getThreatManager().getThreatList().begin(); itr != caster->getThreatManager().getThreatList().end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive() && pUnit != caster) + me->AddThreat(pUnit,caster->getThreatManager().getThreat(pUnit)); + } + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && withhead) + { + withhead = false; + returned = false; + damage = me->GetHealth() - me->GetMaxHealth()/100; + me->RemoveAllAuras(); + me->SetName("Headless Horseman, Unhorsed"); + + if (!headGUID) + headGUID = DoSpawnCreature(HEAD,rand()%6,rand()%6,0,0,TEMPSUMMON_DEAD_DESPAWN,0)->GetGUID(); + Unit* Head = Unit::GetUnit((*me), headGUID); + if (Head && Head->isAlive()) + { + Head->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //Head->CastSpell(Head,SPELL_HEAD_INVIS,false); + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_IMMUNE, true); + DoCast(me, SPELL_BODY_REGEN, true); + DoCast(Head, SPELL_FLYING_HEAD, true); + DoCast(me, SPELL_CONFUSE, false); //test + done_by->ProcDamageAndSpell(me,PROC_FLAG_KILL,PROC_FLAG_KILLED,PROC_EX_NONE,0); + whirlwind = urand(4000,8000); + regen = 0; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (withhead) + { + switch(Phase) + { + case 0: + { + if (!IsFlying) + { + if (say_timer <= diff) + { + say_timer = 3000; + Player *plr = SelectRandomPlayer(100.0f,false); + if (count < 3) + { + if (plr) + plr->Say(Text[count],0); + } + else + { + DoCast(me, SPELL_RHYME_BIG); + if (plr) + { + plr->Say(Text[count],0); + plr->HandleEmoteCommand(ANIM_EMOTE_SHOUT); + } + wp_reached = true; + IsFlying = true; + count = 0; + break; + } + ++count; + } else say_timer -= diff; + } + else + { + if (wp_reached) + { + wp_reached = false; + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MovePoint(id,FlightPoint[id].x,FlightPoint[id].y,FlightPoint[id].z); + } + } + } + break; + case 1: + if (burned) + break; + if (burn <= diff) + { + if (Creature *flame = me->SummonCreature(HELPER,Spawn[0].x,Spawn[0].y,Spawn[0].z,0,TEMPSUMMON_TIMED_DESPAWN,17000)) + CAST_AI(mob_wisp_invisAI, flame->AI())->SetType(2); + burned = true; + } else burn -= diff; + break; + case 2: + if (conflagrate <= diff) + { + if (Unit *plr = SelectRandomPlayer(30.0f)) + DoCast(plr, SPELL_CONFLAGRATION, false); + conflagrate = urand(10000,16000); + } else conflagrate -= diff; + break; + case 3: + if (summonadds <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUMMON_PUMPKIN); + SaySound(SAY_SPROUTING_PUMPKINS); + summonadds = urand(25000,35000); + } else summonadds -= diff; + break; + } + + if (laugh <= diff) + { + laugh = urand(11000,22000); + me->MonsterTextEmote(EMOTE_LAUGHS,NULL); + DoPlaySoundToSet(me, RandomLaugh[rand()%3]); + } else laugh -= diff; + + if (UpdateVictim()) + { + DoMeleeAttackIfReady(); + if (cleave <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + cleave = urand(2000,6000); //1 cleave per 2.0-6.0sec + } else cleave -= diff; + } + } + else + { + if (regen <= diff) + { + regen = 1000; //"body calls head" + if (me->GetHealth()/me->GetMaxHealth() == 1 && !returned) + { + if (Phase > 1) + --Phase; + else + Phase = 1; + Creature* Head = Unit::GetCreature((*me), headGUID); + if (Head && Head->isAlive()) + { + CAST_AI(mob_headAI, Head->AI())->Phase = Phase; + CAST_AI(mob_headAI, Head->AI())->Disappear(); + } + return; + } + } + else regen -= diff; + + if (whirlwind <= diff) + { + whirlwind = urand(4000,8000); + if (urand(0,1)) + { + me->RemoveAurasDueToSpell(SPELL_CONFUSE); + DoCast(me, SPELL_WHIRLWIND, true); + DoCast(me, SPELL_CONFUSE); + } else + me->RemoveAurasDueToSpell(SPELL_WHIRLWIND); + } else whirlwind -= diff; + } + } +}; + +void mob_headAI::Disappear() +{ + if (withbody) + return; + if (bodyGUID) + { + Creature *body = Unit::GetCreature((*me), bodyGUID); + if (body && body->isAlive()) + { + withbody = true; + me->RemoveAllAuras(); + body->RemoveAurasDueToSpell(SPELL_IMMUNE);//hack, SpellHit doesn't calls if body has immune aura + DoCast(body, SPELL_FLYING_HEAD); + me->SetHealth(me->GetMaxHealth()); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->MoveIdle(); + CAST_AI(boss_headless_horsemanAI, body->AI())->returned = true; + } + } +} + +struct mob_pulsing_pumpkinAI : public ScriptedAI +{ + mob_pulsing_pumpkinAI(Creature *c) : ScriptedAI(c) {} + + bool sprouted; + uint64 debuffGUID; + + void Reset() + { + float x, y, z; + me->GetPosition(x, y, z); //this visual aura some under ground + me->GetMap()->CreatureRelocation(me, x,y,z + 0.35f, 0.0f); + Despawn(); + Creature *debuff = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,14500); + if (debuff) + { + debuff->SetDisplayId(me->GetDisplayId()); + debuff->CastSpell(debuff,SPELL_PUMPKIN_AURA_GREEN,false); + CAST_AI(mob_wisp_invisAI, debuff->AI())->SetType(1); + debuffGUID = debuff->GetGUID(); + } + sprouted = false; + DoCast(me, SPELL_PUMPKIN_AURA, true); + DoCast(me, SPELL_SPROUTING); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); + } + + void EnterCombat(Unit * /*who*/){} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_SPROUTING) + { + sprouted = true; + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); + DoCast(me, SPELL_SPROUT_BODY, true); + me->UpdateEntry(PUMPKIN_FIEND); + DoStartMovement(me->getVictim()); + } + } + + void Despawn() + { + if (!debuffGUID) return; + Unit *debuff = Unit::GetUnit((*me),debuffGUID); + if (debuff) + debuff->SetVisibility(VISIBILITY_OFF); + debuffGUID = 0; + } + + void JustDied(Unit * /*killer*/) { if (!sprouted) Despawn(); } + + void MoveInLineOfSight(Unit *who) + { + if (!who || !who->isTargetableForAttack() || !me->IsHostileTo(who) || me->getVictim()) + return; + + me->AddThreat(who,0.0f); + if (sprouted) + DoStartMovement(who); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (sprouted && UpdateVictim()) + DoMeleeAttackIfReady(); + } +}; + +bool GOHello_go_loosely_turned_soil(Player* pPlayer, GameObject* soil) +{ + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (pInstance) + { + if (pInstance->GetData(DATA_HORSEMAN_EVENT) != NOT_STARTED) + return true; + pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); + } +/* if (soil->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER && plr->getLevel() > 64) + { + plr->PrepareQuestMenu(soil->GetGUID()); + plr->SendPreparedQuest(soil->GetGUID()); + } + if (plr->GetQuestStatus(11405) == QUEST_STATUS_INCOMPLETE && plr->getLevel() > 64) + { */ + pPlayer->AreaExploredOrEventHappens(11405); + if (Creature *horseman = soil->SummonCreature(HH_MOUNTED,FlightPoint[20].x,FlightPoint[20].y,FlightPoint[20].z,0,TEMPSUMMON_MANUAL_DESPAWN,0)) + { + CAST_AI(boss_headless_horsemanAI, horseman->AI())->PlayerGUID = pPlayer->GetGUID(); + CAST_AI(boss_headless_horsemanAI, horseman->AI())->FlyMode(); + } + //} + return true; +} + +CreatureAI* GetAI_mob_head(Creature* pCreature) +{ + return new mob_headAI (pCreature); +} + +CreatureAI* GetAI_boss_headless_horseman(Creature* pCreature) +{ + return new boss_headless_horsemanAI (pCreature); +} + +CreatureAI* GetAI_mob_pulsing_pumpkin(Creature* pCreature) +{ + return new mob_pulsing_pumpkinAI (pCreature); +} + +CreatureAI* GetAI_mob_wisp_invis(Creature* pCreature) +{ + return new mob_wisp_invisAI (pCreature); +} + +void AddSC_boss_headless_horseman() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_headless_horseman"; + newscript->GetAI = &GetAI_boss_headless_horseman; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_head"; + newscript->GetAI = &GetAI_mob_head; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_pulsing_pumpkin"; + newscript->GetAI = &GetAI_mob_pulsing_pumpkin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_wisp_invis"; + newscript->GetAI = &GetAI_mob_wisp_invis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_loosely_turned_soil"; + newscript->pGOHello = &GOHello_go_loosely_turned_soil; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp new file mode 100644 index 00000000000..e0db29aa240 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_herod.cpp @@ -0,0 +1,158 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Herod +SD%Complete: 95 +SDComment: Should in addition spawn Myrmidons in the hallway outside +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" + +#define SAY_AGGRO -1189000 +#define SAY_WHIRLWIND -1189001 +#define SAY_ENRAGE -1189002 +#define SAY_KILL -1189003 +#define EMOTE_ENRAGE -1189004 + +#define SPELL_RUSHINGCHARGE 8260 +#define SPELL_CLEAVE 15496 +#define SPELL_WHIRLWIND 8989 +#define SPELL_FRENZY 8269 + +#define ENTRY_SCARLET_TRAINEE 6575 +#define ENTRY_SCARLET_MYRMIDON 4295 + +struct boss_herodAI : public ScriptedAI +{ + boss_herodAI(Creature *c) : ScriptedAI(c) {} + + bool Enrage; + + uint32 Cleave_Timer; + uint32 Whirlwind_Timer; + + void Reset() + { + Enrage = false; + Cleave_Timer = 12000; + Whirlwind_Timer = 60000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_RUSHINGCHARGE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*killer*/) + { + for (uint8 i = 0; i < 20; ++i) + me->SummonCreature(ENTRY_SCARLET_TRAINEE, 1939.18, -431.58, 17.09, 6.22, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <30% hp goes Enraged + if (!Enrage && me->GetHealth()*100 / me->GetMaxHealth() <= 30 && !me->IsNonMeleeSpellCasted(false)) + { + DoScriptText(EMOTE_ENRAGE, me); + DoScriptText(SAY_ENRAGE, me); + DoCast(me, SPELL_FRENZY); + Enrage = true; + } + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 12000; + } else Cleave_Timer -= diff; + + // Whirlwind_Timer + if (Whirlwind_Timer <= diff) + { + DoScriptText(SAY_WHIRLWIND, me); + DoCast(me->getVictim(), SPELL_WHIRLWIND); + Whirlwind_Timer = 30000; + } else Whirlwind_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_herod(Creature* pCreature) +{ + return new boss_herodAI(pCreature); +} + +struct mob_scarlet_traineeAI : public npc_escortAI +{ + mob_scarlet_traineeAI(Creature *c) : npc_escortAI(c) + { + Start_Timer = urand(1000,6000); + } + + uint32 Start_Timer; + + void Reset() {} + void WaypointReached(uint32 /*uiPoint*/) {} + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (Start_Timer) + { + if (Start_Timer <= diff) + { + Start(true,true); + Start_Timer = 0; + } else Start_Timer -= diff; + } + + npc_escortAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_mob_scarlet_trainee(Creature* pCreature) +{ + return new mob_scarlet_traineeAI(pCreature); +} + +void AddSC_boss_herod() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_herod"; + newscript->GetAI = &GetAI_boss_herod; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_scarlet_trainee"; + newscript->GetAI = &GetAI_mob_scarlet_trainee; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp new file mode 100644 index 00000000000..b9b15f34508 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp @@ -0,0 +1,133 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Inquisitor_Fairbanks +SD%Complete: 100 +SDComment: TODO: if this guy not involved in some special event, remove (and let ACID script) +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +enum eSpells +{ + SPELL_CURSEOFBLOOD = 8282, + SPELL_DISPELMAGIC = 15090, + SPELL_FEAR = 12096, + SPELL_HEAL = 12039, + SPELL_POWERWORDSHIELD = 11647, + SPELL_SLEEP = 8399 +}; + +struct boss_high_inquisitor_fairbanksAI : public ScriptedAI +{ + boss_high_inquisitor_fairbanksAI(Creature *c) : ScriptedAI(c) {} + + uint32 CurseOfBlood_Timer; + uint32 DispelMagic_Timer; + uint32 Fear_Timer; + uint32 Heal_Timer; + uint32 Sleep_Timer; + uint32 Dispel_Timer; + bool PowerWordShield; + + void Reset() + { + CurseOfBlood_Timer = 10000; + DispelMagic_Timer = 30000; + Fear_Timer = 40000; + Heal_Timer = 30000; + Sleep_Timer = 30000; + Dispel_Timer = 20000; + PowerWordShield = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <25% hp cast Heal + if (me->GetHealth()*100 / me->GetMaxHealth() <= 25 && !me->IsNonMeleeSpellCasted(false) && Heal_Timer <= diff) + { + DoCast(me, SPELL_HEAL); + Heal_Timer = 30000; + } else Heal_Timer -= diff; + + //Fear_Timer + if (Fear_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_FEAR); + + Fear_Timer = 40000; + } else Fear_Timer -= diff; + + //Sleep_Timer + if (Sleep_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,0)) + DoCast(pTarget, SPELL_SLEEP); + + Sleep_Timer = 30000; + } else Sleep_Timer -= diff; + + //PowerWordShield_Timer + if (!PowerWordShield && me->GetHealth()*100 / me->GetMaxHealth() <= 25) + { + DoCast(me, SPELL_POWERWORDSHIELD); + PowerWordShield = true; + } + + //Dispel_Timer + if (Dispel_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_DISPELMAGIC); + + DispelMagic_Timer = 30000; + } else DispelMagic_Timer -= diff; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); + CurseOfBlood_Timer = 25000; + } else CurseOfBlood_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_high_inquisitor_fairbanks(Creature* pCreature) +{ + return new boss_high_inquisitor_fairbanksAI (pCreature); +} + +void AddSC_boss_high_inquisitor_fairbanks() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_high_inquisitor_fairbanks"; + newscript->GetAI = &GetAI_boss_high_inquisitor_fairbanks; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp new file mode 100644 index 00000000000..300e69611cd --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp @@ -0,0 +1,77 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Houndmaster_Loksey +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + SAY_AGGRO = -1189021, + SPELL_SUMMONSCARLETHOUND = 17164, + SPELL_BLOODLUST = 6742 +}; + +struct boss_houndmaster_lokseyAI : public ScriptedAI +{ + boss_houndmaster_lokseyAI(Creature *c) : ScriptedAI(c) {} + + uint32 BloodLust_Timer; + + void Reset() + { + BloodLust_Timer = 20000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BloodLust_Timer <= diff) + { + DoCast(me, SPELL_BLOODLUST); + BloodLust_Timer = 20000; + } else BloodLust_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_houndmaster_loksey(Creature* pCreature) +{ + return new boss_houndmaster_lokseyAI (pCreature); +} + +void AddSC_boss_houndmaster_loksey() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_houndmaster_loksey"; + newscript->GetAI = &GetAI_boss_houndmaster_loksey; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp new file mode 100644 index 00000000000..b4b84fc8059 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp @@ -0,0 +1,118 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Interrogator_Vishas +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "scarlet_monastery.h" + +enum eEnums +{ + SAY_AGGRO = -1189011, + SAY_HEALTH1 = -1189012, + SAY_HEALTH2 = -1189013, + SAY_KILL = -1189014, + SAY_TRIGGER_VORREL = -1189015, + + SPELL_SHADOWWORDPAIN = 2767, +}; + +struct boss_interrogator_vishasAI : public ScriptedAI +{ + boss_interrogator_vishasAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool Yell30; + bool Yell60; + uint32 ShadowWordPain_Timer; + + void Reset() + { + ShadowWordPain_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*Victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (!pInstance) + return; + + //Any other actions to do with vorrel? setStandState? + if (Unit *vorrel = Unit::GetUnit(*me,pInstance->GetData64(DATA_VORREL))) + DoScriptText(SAY_TRIGGER_VORREL, vorrel); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are low on hp Do sayings + if (!Yell60 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 60)) + { + DoScriptText(SAY_HEALTH1, me); + Yell60 = true; + } + + if (!Yell30 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 30)) + { + DoScriptText(SAY_HEALTH2, me); + Yell30 = true; + } + + //ShadowWordPain_Timer + if (ShadowWordPain_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); + ShadowWordPain_Timer = 5000 + rand()%10000; + } else ShadowWordPain_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_interrogator_vishas(Creature* pCreature) +{ + return new boss_interrogator_vishasAI (pCreature); +} + +void AddSC_boss_interrogator_vishas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_interrogator_vishas"; + newscript->GetAI = &GetAI_boss_interrogator_vishas; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp new file mode 100644 index 00000000000..32b85e214a0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp @@ -0,0 +1,359 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mograine_And_Whitemane +SD%Complete: 90 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "scarlet_monastery.h" + +enum eEnums +{ + //Mograine says + SAY_MO_AGGRO = -1189005, + SAY_MO_KILL = -1189006, + SAY_MO_RESSURECTED = -1189007, + + //Whitemane says + SAY_WH_INTRO = -1189008, + SAY_WH_KILL = -1189009, + SAY_WH_RESSURECT = -1189010, + + //Mograine Spells + SPELL_CRUSADERSTRIKE = 14518, + SPELL_HAMMEROFJUSTICE = 5589, + SPELL_LAYONHANDS = 9257, + SPELL_RETRIBUTIONAURA = 8990, + + //Whitemanes Spells + SPELL_DEEPSLEEP = 9256, + SPELL_SCARLETRESURRECTION = 9232, + SPELL_DOMINATEMIND = 14515, + SPELL_HOLYSMITE = 9481, + SPELL_HEAL = 12039, + SPELL_POWERWORDSHIELD = 22187 +}; + +struct boss_scarlet_commander_mograineAI : public ScriptedAI +{ + boss_scarlet_commander_mograineAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiCrusaderStrike_Timer; + uint32 m_uiHammerOfJustice_Timer; + + bool m_bHasDied; + bool m_bHeal; + bool m_bFakeDeath; + + void Reset() + { + m_uiCrusaderStrike_Timer = 10000; + m_uiHammerOfJustice_Timer = 10000; + + //Incase wipe during phase that mograine fake death + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + + if (m_pInstance) + if (me->isAlive()) + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT,NOT_STARTED); + + m_bHasDied = false; + m_bHeal = false; + m_bFakeDeath = false; + } + + void JustReachedHome() + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT != NOT_STARTED)) + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, FAIL); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_MO_AGGRO, me); + DoCast(me, SPELL_RETRIBUTIONAURA); + + me->CallForHelp(VISIBLE_RANGE); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(SAY_MO_KILL, me); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) + { + if (uiDamage < me->GetHealth() || m_bHasDied || m_bFakeDeath) + return; + + if (!m_pInstance) + return; + + //On first death, fake death and open door, as well as initiate whitemane if exist + if (Unit* Whitemane = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_WHITEMANE))) + { + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS); + + Whitemane->GetMotionMaster()->MovePoint(1,1163.113370,1398.856812,32.527786); + + me->GetMotionMaster()->MovementExpired(); + me->GetMotionMaster()->MoveIdle(); + + me->SetHealth(0); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + me->ClearComboPointHolders(); + me->RemoveAllAuras(); + me->ClearAllReactives(); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_DEAD); + + m_bHasDied = true; + m_bFakeDeath = true; + + uiDamage = 0; + } + } + + void SpellHit(Unit* /*pWho*/, const SpellEntry* pSpell) + { + //When hit with ressurection say text + if (pSpell->Id == SPELL_SCARLETRESURRECTION) + { + DoScriptText(SAY_MO_RESSURECTED, me); + m_bFakeDeath = false; + + if (m_pInstance) + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, SPECIAL); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_bHasDied && !m_bHeal && m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL) + { + //On ressurection, stop fake death and heal whitemane and resume fight + if (Unit* Whitemane = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_WHITEMANE))) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(Whitemane, SPELL_LAYONHANDS); + + m_uiCrusaderStrike_Timer = 10000; + m_uiHammerOfJustice_Timer = 10000; + + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + + m_bHeal = true; + } + } + + //This if-check to make sure mograine does not attack while fake death + if (m_bFakeDeath) + return; + + //m_uiCrusaderStrike_Timer + if (m_uiCrusaderStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CRUSADERSTRIKE); + m_uiCrusaderStrike_Timer = 10000; + } else m_uiCrusaderStrike_Timer -= uiDiff; + + //m_uiHammerOfJustice_Timer + if (m_uiHammerOfJustice_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_HAMMEROFJUSTICE); + m_uiHammerOfJustice_Timer = 60000; + } else m_uiHammerOfJustice_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_high_inquisitor_whitemaneAI : public ScriptedAI +{ + boss_high_inquisitor_whitemaneAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiHeal_Timer; + uint32 m_uiPowerWordShield_Timer; + uint32 m_uiHolySmite_Timer; + uint32 m_uiWait_Timer; + + bool m_bCanResurrectCheck; + bool m_bCanResurrect; + + void Reset() + { + m_uiWait_Timer = 7000; + m_uiHeal_Timer = 10000; + m_uiPowerWordShield_Timer = 15000; + m_uiHolySmite_Timer = 6000; + + m_bCanResurrectCheck = false; + m_bCanResurrect = false; + + if (m_pInstance) + if (me->isAlive()) + m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, NOT_STARTED); + } + + void AttackStart(Unit* pWho) + { + if (m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED) + return; + + ScriptedAI::AttackStart(pWho); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_WH_INTRO, me); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(SAY_WH_KILL, me); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (m_bCanResurrect) + { + //When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out + if (m_pInstance && m_uiWait_Timer <= uiDiff) + { + if (Unit* Mograine = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_MOGRAINE))) + { + DoCast(Mograine, SPELL_SCARLETRESURRECTION); + DoScriptText(SAY_WH_RESSURECT, me); + m_bCanResurrect = false; + } + } + else m_uiWait_Timer -= uiDiff; + } + + //Cast Deep sleep when health is less than 50% + if (!m_bCanResurrectCheck && me->GetHealth()*100 / me->GetMaxHealth() <= 50) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me->getVictim(), SPELL_DEEPSLEEP); + m_bCanResurrectCheck = true; + m_bCanResurrect = true; + return; + } + + //while in "resurrect-mode", don't do anything + if (m_bCanResurrect) + return; + + //If we are <75% hp cast healing spells at self or Mograine + if (m_uiHeal_Timer <= uiDiff) + { + Creature* pTarget = NULL; + + if (me->GetHealth() <= me->GetMaxHealth()*0.75f) + pTarget = me; + + if (m_pInstance) + { + if (Creature* pMograine = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_MOGRAINE))) + { + // checking m_bCanResurrectCheck prevents her healing Mograine while he is "faking death" + if (m_bCanResurrectCheck && pMograine->isAlive() && pMograine->GetHealth() <= pMograine->GetMaxHealth()*0.75f) + pTarget = pMograine; + } + } + + if (pTarget) + DoCast(pTarget, SPELL_HEAL); + + m_uiHeal_Timer = 13000; + } else m_uiHeal_Timer -= uiDiff; + + //m_uiPowerWordShield_Timer + if (m_uiPowerWordShield_Timer <= uiDiff) + { + DoCast(me, SPELL_POWERWORDSHIELD); + m_uiPowerWordShield_Timer = 15000; + } else m_uiPowerWordShield_Timer -= uiDiff; + + //m_uiHolySmite_Timer + if (m_uiHolySmite_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_HOLYSMITE); + m_uiHolySmite_Timer = 6000; + } else m_uiHolySmite_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_scarlet_commander_mograine(Creature* pCreature) +{ + return new boss_scarlet_commander_mograineAI (pCreature); +} + +CreatureAI* GetAI_boss_high_inquisitor_whitemane(Creature* pCreature) +{ + return new boss_high_inquisitor_whitemaneAI (pCreature); +} + +void AddSC_boss_mograine_and_whitemane() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_scarlet_commander_mograine"; + newscript->GetAI = &GetAI_boss_scarlet_commander_mograine; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_high_inquisitor_whitemane"; + newscript->GetAI = &GetAI_boss_high_inquisitor_whitemane; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp new file mode 100644 index 00000000000..5d0a3b3792f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_scorn.cpp @@ -0,0 +1,101 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Scorn +SD%Complete: 100 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_LICHSLAP 28873 +#define SPELL_FROSTBOLTVOLLEY 8398 +#define SPELL_MINDFLAY 17313 +#define SPELL_FROSTNOVA 15531 + +struct boss_scornAI : public ScriptedAI +{ + boss_scornAI(Creature *c) : ScriptedAI(c) {} + + uint32 LichSlap_Timer; + uint32 FrostboltVolley_Timer; + uint32 MindFlay_Timer; + uint32 FrostNova_Timer; + + void Reset() + { + LichSlap_Timer = 45000; + FrostboltVolley_Timer = 30000; + MindFlay_Timer = 30000; + FrostNova_Timer = 30000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //LichSlap_Timer + if (LichSlap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LICHSLAP); + LichSlap_Timer = 45000; + } else LichSlap_Timer -= diff; + + //FrostboltVolley_Timer + if (FrostboltVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLTVOLLEY); + FrostboltVolley_Timer = 20000; + } else FrostboltVolley_Timer -= diff; + + //MindFlay_Timer + if (MindFlay_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MINDFLAY); + MindFlay_Timer = 20000; + } else MindFlay_Timer -= diff; + + //FrostNova_Timer + if (FrostNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTNOVA); + FrostNova_Timer = 15000; + } else FrostNova_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_scorn(Creature* pCreature) +{ + return new boss_scornAI (pCreature); +} + +void AddSC_boss_scorn() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_scorn"; + newscript->GetAI = &GetAI_boss_scorn; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp new file mode 100644 index 00000000000..33642d4511c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp @@ -0,0 +1,157 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Scarlet_Monastery +SD%Complete: 50 +SDComment: +SDCategory: Scarlet Monastery +EndScriptData */ + +#include "ScriptedPch.h" +#include "scarlet_monastery.h" + +#define ENTRY_PUMPKIN_SHRINE 186267 +#define ENTRY_HORSEMAN 23682 +#define ENTRY_HEAD 23775 +#define ENTRY_PUMPKIN 23694 + +#define MAX_ENCOUNTER 2 + +struct instance_scarlet_monastery : public ScriptedInstance +{ + instance_scarlet_monastery(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 PumpkinShrineGUID; + uint64 HorsemanGUID; + uint64 HeadGUID; + std::set HorsemanAdds; + + uint64 MograineGUID; + uint64 WhitemaneGUID; + uint64 VorrelGUID; + uint64 DoorHighInquisitorGUID; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + PumpkinShrineGUID = 0; + HorsemanGUID = 0; + HeadGUID = 0; + HorsemanAdds.clear(); + + MograineGUID = 0; + WhitemaneGUID = 0; + VorrelGUID = 0; + DoorHighInquisitorGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case ENTRY_PUMPKIN_SHRINE: PumpkinShrineGUID = pGo->GetGUID();break; + case 104600: DoorHighInquisitorGUID = pGo->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case ENTRY_HORSEMAN: HorsemanGUID = pCreature->GetGUID(); break; + case ENTRY_HEAD: HeadGUID = pCreature->GetGUID(); break; + case ENTRY_PUMPKIN: HorsemanAdds.insert(pCreature->GetGUID());break; + case 3976: MograineGUID = pCreature->GetGUID(); break; + case 3977: WhitemaneGUID = pCreature->GetGUID(); break; + case 3981: VorrelGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_MOGRAINE_AND_WHITE_EVENT: + if (data == IN_PROGRESS) + DoUseDoorOrButton(DoorHighInquisitorGUID); + if (data == FAIL) + DoUseDoorOrButton(DoorHighInquisitorGUID); + + m_auiEncounter[0] = data; + break; + case GAMEOBJECT_PUMPKIN_SHRINE: + HandleGameObject(PumpkinShrineGUID, false); + break; + case DATA_HORSEMAN_EVENT: + m_auiEncounter[1] = data; + if (data == DONE) + { + for (std::set::const_iterator itr = HorsemanAdds.begin(); itr != HorsemanAdds.end(); ++itr) + { + Creature* add = instance->GetCreature(*itr); + if (add && add->isAlive()) + add->Kill(add); + } + HorsemanAdds.clear(); + HandleGameObject(PumpkinShrineGUID, false); + } + break; + } + } + + uint64 GetData64(uint32 type) + { + switch(type) + { + //case GAMEOBJECT_PUMPKIN_SHRINE: return PumpkinShrineGUID; + //case DATA_HORSEMAN: return HorsemanGUID; + //case DATA_HEAD: return HeadGUID; + case DATA_MOGRAINE: return MograineGUID; + case DATA_WHITEMANE: return WhitemaneGUID; + case DATA_VORREL: return VorrelGUID; + case DATA_DOOR_WHITEMANE: return DoorHighInquisitorGUID; + } + return 0; + } + + uint32 GetData(uint32 type) + { + if (type == TYPE_MOGRAINE_AND_WHITE_EVENT) + return m_auiEncounter[0]; + if (type == DATA_HORSEMAN_EVENT) + return m_auiEncounter[1]; + return 0; + } +}; + +InstanceData* GetInstanceData_instance_scarlet_monastery(Map* pMap) +{ + return new instance_scarlet_monastery(pMap); +} + +void AddSC_instance_scarlet_monastery() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_scarlet_monastery"; + newscript->GetInstanceData = &GetInstanceData_instance_scarlet_monastery; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h b/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h new file mode 100644 index 00000000000..2b6399ae3e4 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/scarlet_monastery.h @@ -0,0 +1,18 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SCARLET_M +#define DEF_SCARLET_M + +#define TYPE_MOGRAINE_AND_WHITE_EVENT 1 +#define DATA_MOGRAINE 2 +#define DATA_WHITEMANE 3 +#define DATA_DOOR_WHITEMANE 4 + +#define DATA_HORSEMAN_EVENT 5 +#define GAMEOBJECT_PUMPKIN_SHRINE 6 + +#define DATA_VORREL 7 +#endif + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp new file mode 100644 index 00000000000..50a9e204566 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp @@ -0,0 +1,225 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Darkmaster_Gandling +SD%Complete: 75 +SDComment: Doors missing in instance script. +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_ARCANEMISSILES 22272 +#define SPELL_SHADOWSHIELD 22417 //Not right ID. But 12040 is wrong either. +#define SPELL_CURSE 18702 + +#define ADD_1X 170.205 +#define ADD_1Y 99.413 +#define ADD_1Z 104.733 +#define ADD_1O 3.16 + +#define ADD_2X 170.813 +#define ADD_2Y 97.857 +#define ADD_2Z 104.713 +#define ADD_2O 3.16 + +#define ADD_3X 170.720 +#define ADD_3Y 100.900 +#define ADD_3Z 104.739 +#define ADD_3O 3.16 + +#define ADD_4X 171.866 +#define ADD_4Y 99.373 +#define ADD_4Z 104.732 +#define ADD_4O 3.16 + +struct boss_darkmaster_gandlingAI : public ScriptedAI +{ + boss_darkmaster_gandlingAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ArcaneMissiles_Timer; + uint32 ShadowShield_Timer; + uint32 Curse_Timer; + uint32 Teleport_Timer; + + void Reset() + { + ArcaneMissiles_Timer = 4500; + ShadowShield_Timer = 12000; + Curse_Timer = 2000; + Teleport_Timer = 16000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_GANDLING, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ArcaneMissiles_Timer + if (ArcaneMissiles_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANEMISSILES); + ArcaneMissiles_Timer = 8000; + } else ArcaneMissiles_Timer -= diff; + + //ShadowShield_Timer + if (ShadowShield_Timer <= diff) + { + DoCast(me, SPELL_SHADOWSHIELD); + ShadowShield_Timer = 14000 + rand()%14000; + } else ShadowShield_Timer -= diff; + + //Curse_Timer + if (Curse_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSE); + Curse_Timer = 15000 + rand()%12000; + } else Curse_Timer -= diff; + + //Teleporting Random Target to one of the six pre boss rooms and spawn 3-4 skeletons near the gamer. + //We will only telport if gandling has more than 3% of hp so teleported gamers can always loot. + if (me->GetHealth()*100 / me->GetMaxHealth() > 3) + { + if (Teleport_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + if (DoGetThreat(pTarget)) + DoModifyThreatPercent(pTarget, -100); + + Creature *Summoned = NULL; + switch(rand()%6) + { + case 0: + DoTeleportPlayer(pTarget, 250.0696,0.3921,84.8408,3.149); + Summoned = me->SummonCreature(16119,254.2325,0.3417,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,257.7133,4.0226,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,258.6702,-2.60656,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 1: + DoTeleportPlayer(pTarget, 181.4220,-91.9481,84.8410,1.608); + Summoned = me->SummonCreature(16119,184.0519,-73.5649,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,179.5951,-73.7045,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,180.6452,-78.2143,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,283.2274,-78.1518,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 2: + DoTeleportPlayer(pTarget, 95.1547,-1.8173,85.2289,0.043); + Summoned = me->SummonCreature(16119,100.9404,-1.8016,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,101.3729,0.4882,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,101.4596,-4.4740,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 3: + DoTeleportPlayer(pTarget, 250.0696,0.3921,72.6722,3.149); + Summoned = me->SummonCreature(16119,240.34481,0.7368,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,240.3633,-2.9520,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,240.6702,3.34949,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 4: + DoTeleportPlayer(pTarget, 181.4220,-91.9481,70.7734,1.608); + Summoned = me->SummonCreature(16119,184.0519,-73.5649,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,179.5951,-73.7045,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,180.6452,-78.2143,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,283.2274,-78.1518,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + case 5: + DoTeleportPlayer(pTarget, 106.1541,-1.8994,75.3663,0.043); + Summoned = me->SummonCreature(16119,115.3945,-1.5555,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,257.7133,1.8066,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + Summoned = me->SummonCreature(16119,258.6702,-5.1001,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); + if (Summoned) + Summoned->AI()->AttackStart(pTarget); + break; + } + } + Teleport_Timer = 20000 + rand()%15000; + } else Teleport_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_darkmaster_gandling(Creature* pCreature) +{ + return new boss_darkmaster_gandlingAI (pCreature); +} + +void AddSC_boss_darkmaster_gandling() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_darkmaster_gandling"; + newscript->GetAI = &GetAI_boss_darkmaster_gandling; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_death_knight_darkreaver.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_death_knight_darkreaver.cpp new file mode 100644 index 00000000000..8bb9ec68aca --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_death_knight_darkreaver.cpp @@ -0,0 +1,58 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Death_knight_darkreaver +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +struct boss_death_knight_darkreaverAI : public ScriptedAI +{ + boss_death_knight_darkreaverAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (me->GetHealth() <= damage) + DoCast(me, 23261, true); //Summon Darkreaver's Fallen Charger + } + + void EnterCombat(Unit * /*who*/) + { + } +}; +CreatureAI* GetAI_boss_death_knight_darkreaver(Creature* pCreature) +{ + return new boss_death_knight_darkreaverAI (pCreature); +} + +void AddSC_boss_death_knight_darkreaver() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_death_knight_darkreaver"; + newscript->GetAI = &GetAI_boss_death_knight_darkreaver; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_doctor_theolen_krastinov.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_doctor_theolen_krastinov.cpp new file mode 100644 index 00000000000..5ff01d48623 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_doctor_theolen_krastinov.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Doctor_Theolen_Krastinov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +enum eEnums +{ + EMOTE_GENERIC_FRENZY_KILL = -1000001, + + SPELL_REND = 16509, + SPELL_BACKHAND = 18103, + SPELL_FRENZY = 8269 +}; + +struct boss_theolenkrastinovAI : public ScriptedAI +{ + boss_theolenkrastinovAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiRend_Timer; + uint32 m_uiBackhand_Timer; + uint32 m_uiFrenzy_Timer; + + void Reset() + { + m_uiRend_Timer = 8000; + m_uiBackhand_Timer = 9000; + m_uiFrenzy_Timer = 1000; + } + + void JustDied(Unit* /*pKiller*/) + { + ScriptedInstance* pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_DOCTORTHEOLENKRASTINOV_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //Rend_Timer + if (m_uiRend_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_REND); + m_uiRend_Timer = 10000; + } + else + m_uiRend_Timer -= uiDiff; + + //Backhand_Timer + if (m_uiBackhand_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_BACKHAND); + m_uiBackhand_Timer = 10000; + } + else + m_uiBackhand_Timer -= uiDiff; + + //Frenzy_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 26) + { + if (m_uiFrenzy_Timer <= uiDiff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); + + m_uiFrenzy_Timer = 120000; + } + else + m_uiFrenzy_Timer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_theolenkrastinov(Creature* pCreature) +{ + return new boss_theolenkrastinovAI (pCreature); +} + +void AddSC_boss_theolenkrastinov() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_doctor_theolen_krastinov"; + newscript->GetAI = &GetAI_boss_theolenkrastinov; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp new file mode 100644 index 00000000000..a038fc7a0b8 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_illucia_barov.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Illucia_Barov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_CURSEOFAGONY 18671 +#define SPELL_SHADOWSHOCK 20603 +#define SPELL_SILENCE 15487 +#define SPELL_FEAR 6215 + +struct boss_illuciabarovAI : public ScriptedAI +{ + boss_illuciabarovAI(Creature *c) : ScriptedAI(c) {} + + uint32 CurseOfAgony_Timer; + uint32 ShadowShock_Timer; + uint32 Silence_Timer; + uint32 Fear_Timer; + + void Reset() + { + CurseOfAgony_Timer = 18000; + ShadowShock_Timer = 9000; + Silence_Timer = 5000; + Fear_Timer = 30000; + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_LADYILLUCIABAROV_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //CurseOfAgony_Timer + if (CurseOfAgony_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSEOFAGONY); + CurseOfAgony_Timer = 30000; + } else CurseOfAgony_Timer -= diff; + + //ShadowShock_Timer + if (ShadowShock_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_SHADOWSHOCK); + + ShadowShock_Timer = 12000; + } else ShadowShock_Timer -= diff; + + //Silence_Timer + if (Silence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + Silence_Timer = 14000; + } else Silence_Timer -= diff; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + Fear_Timer = 30000; + } else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_illuciabarov(Creature* pCreature) +{ + return new boss_illuciabarovAI (pCreature); +} + +void AddSC_boss_illuciabarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_illucia_barov"; + newscript->GetAI = &GetAI_boss_illuciabarov; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_instructor_malicia.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_instructor_malicia.cpp new file mode 100644 index 00000000000..c4c0f95d8d1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_instructor_malicia.cpp @@ -0,0 +1,153 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_instructormalicia +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_CALLOFGRAVES 17831 +#define SPELL_CORRUPTION 11672 +#define SPELL_FLASHHEAL 10917 +#define SPELL_RENEW 10929 +#define SPELL_HEALINGTOUCH 9889 + +struct boss_instructormaliciaAI : public ScriptedAI +{ + boss_instructormaliciaAI(Creature *c) : ScriptedAI(c) {} + + uint32 CallOfGraves_Timer; + uint32 Corruption_Timer; + uint32 FlashHeal_Timer; + uint32 Renew_Timer; + uint32 HealingTouch_Timer; + uint32 FlashCounter; + uint32 TouchCounter; + + void Reset() + { + CallOfGraves_Timer = 4000; + Corruption_Timer = 8000; + FlashHeal_Timer = 38000; + Renew_Timer = 32000; + HealingTouch_Timer = 45000; + FlashCounter = 0; + TouchCounter = 0; + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_INSTRUCTORMALICIA_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //CallOfGraves_Timer + if (CallOfGraves_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CALLOFGRAVES); + CallOfGraves_Timer = 65000; + } else CallOfGraves_Timer -= diff; + + //Corruption_Timer + if (Corruption_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_CORRUPTION); + + Corruption_Timer = 24000; + } else Corruption_Timer -= diff; + + //Renew_Timer + if (Renew_Timer <= diff) + { + DoCast(me, SPELL_RENEW); + Renew_Timer = 10000; + } else Renew_Timer -= diff; + + //FlashHeal_Timer + if (FlashHeal_Timer <= diff) + { + DoCast(me, SPELL_FLASHHEAL); + + //5 Flashheals will be casted + if (FlashCounter < 2) + { + FlashHeal_Timer = 5000; + ++FlashCounter; + } + else + { + FlashCounter=0; + FlashHeal_Timer = 30000; + } + } else FlashHeal_Timer -= diff; + + //HealingTouch_Timer + if (HealingTouch_Timer <= diff) + { + DoCast(me, SPELL_HEALINGTOUCH); + + //3 Healingtouchs will be casted + if (HealingTouch_Timer < 2) + { + HealingTouch_Timer = 5500; + ++TouchCounter; + } + else + { + TouchCounter=0; + HealingTouch_Timer = 30000; + } + } else HealingTouch_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_instructormalicia(Creature* pCreature) +{ + return new boss_instructormaliciaAI (pCreature); +} + +void AddSC_boss_instructormalicia() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_instructor_malicia"; + newscript->GetAI = &GetAI_boss_instructormalicia; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp new file mode 100644 index 00000000000..f8d8520e394 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp @@ -0,0 +1,201 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_jandicebarov +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_CURSEOFBLOOD 24673 +//#define SPELL_ILLUSION 17773 + +//Spells of Illusion of Jandice Barov +#define SPELL_CLEAVE 15584 + +struct boss_jandicebarovAI : public ScriptedAI +{ + boss_jandicebarovAI(Creature *c) : ScriptedAI(c) {} + + uint32 CurseOfBlood_Timer; + uint32 Illusion_Timer; + //uint32 Illusioncounter; + uint32 Invisible_Timer; + bool Invisible; + + void Reset() + { + CurseOfBlood_Timer = 15000; + Illusion_Timer = 30000; + Invisible_Timer = 3000; //Too much too low? + Invisible = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonIllusions(Unit* victim) + { + if (Creature *Illusion = DoSpawnCreature(11439, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) + Illusion->AI()->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (Invisible && Invisible_Timer <= diff) + { + //Become visible again + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(11073); //Jandice Model + Invisible = false; + } else if (Invisible) + { + Invisible_Timer -= diff; + //Do nothing while invisible + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //CurseOfBlood_Timer + if (CurseOfBlood_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); + + //45 seconds + CurseOfBlood_Timer = 30000; + } else CurseOfBlood_Timer -= diff; + + //Illusion_Timer + if (!Invisible && Illusion_Timer <= diff) + { + + //Inturrupt any spell casting + me->InterruptNonMeleeSpells(false); + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(11686); // Invisible Model + DoModifyThreatPercent(me->getVictim(),-99); + + //Summon 10 Illusions attacking random gamers + Unit *pTarget = NULL; + for (uint8 i = 0; i < 10; ++i) + { + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + SummonIllusions(pTarget); + } + Invisible = true; + Invisible_Timer = 3000; + + //25 seconds until we should cast this agian + Illusion_Timer = 25000; + } else Illusion_Timer -= diff; + + // //Illusion_Timer + // if (Illusion_Timer <= diff) + // { + // //Cast + // DoCast(me->getVictim(), SPELL_ILLUSION); + // + // //3 Illusion will be summoned + // if (Illusioncounter < 3) + // { + // Illusion_Timer = 500; + // ++Illusioncounter; + // } + // else { + // //15 seconds until we should cast this again + // Illusion_Timer = 15000; + // Illusioncounter = 0; + // } + // + // } else Illusion_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +// Illusion of Jandice Barov Script + +struct mob_illusionofjandicebarovAI : public ScriptedAI +{ + mob_illusionofjandicebarovAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cleave_Timer; + + void Reset() + { + Cleave_Timer = 2000 + rand()%6000; + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_CLEAVE); + + //5-8 seconds + Cleave_Timer = 5000 + rand()%3000; + } else Cleave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jandicebarov(Creature* pCreature) +{ + return new boss_jandicebarovAI (pCreature); +} + +CreatureAI* GetAI_mob_illusionofjandicebarov(Creature* pCreature) +{ + return new mob_illusionofjandicebarovAI (pCreature); +} + +void AddSC_boss_jandicebarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_jandice_barov"; + newscript->GetAI = &GetAI_boss_jandicebarov; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_illusionofjandicebarov"; + newscript->GetAI = &GetAI_mob_illusionofjandicebarov; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_kormok.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_kormok.cpp new file mode 100644 index 00000000000..c4ae5cc490e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_kormok.cpp @@ -0,0 +1,120 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kormok +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SHADOWBOLTVOLLEY 20741 +#define SPELL_BONESHIELD 27688 + +struct boss_kormokAI : public ScriptedAI +{ + boss_kormokAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowVolley_Timer; + uint32 BoneShield_Timer; + uint32 Minion_Timer; + uint32 Mage_Timer; + bool Mages; + + void Reset() + { + ShadowVolley_Timer = 10000; + BoneShield_Timer = 2000; + Minion_Timer = 15000; + Mage_Timer = 0; + Mages = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonMinions(Unit* victim) + { + if (Creature *SummonedMinion = DoSpawnCreature(16119, irand(-7,7), irand(-7,7), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedMinion->AI()->AttackStart(victim); + } + + void SummonMages(Unit* victim) + { + if (Creature *SummonedMage = DoSpawnCreature(16120, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedMage->AI()->AttackStart(victim); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowVolley_Timer + if (ShadowVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLTVOLLEY); + ShadowVolley_Timer = 15000; + } else ShadowVolley_Timer -= diff; + + //BoneShield_Timer + if (BoneShield_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BONESHIELD); + BoneShield_Timer = 45000; + } else BoneShield_Timer -= diff; + + //Minion_Timer + if (Minion_Timer <= diff) + { + //Cast + SummonMinions(me->getVictim()); + SummonMinions(me->getVictim()); + SummonMinions(me->getVictim()); + SummonMinions(me->getVictim()); + + Minion_Timer = 12000; + } else Minion_Timer -= diff; + + //Summon 2 Bone Mages + if (!Mages && me->GetHealth()*100 / me->GetMaxHealth() < 26) + { + //Cast + SummonMages(me->getVictim()); + SummonMages(me->getVictim()); + Mages = true; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_kormok(Creature* pCreature) +{ + return new boss_kormokAI (pCreature); +} + +void AddSC_boss_kormok() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kormok"; + newscript->GetAI = &GetAI_boss_kormok; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_lord_alexei_barov.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_lord_alexei_barov.cpp new file mode 100644 index 00000000000..0956a04d824 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_lord_alexei_barov.cpp @@ -0,0 +1,99 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lord_Alexei_Barov +SD%Complete: 100 +SDComment: aura applied/defined in database +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_IMMOLATE 20294 // Old ID was 15570 +#define SPELL_VEILOFSHADOW 17820 + +struct boss_lordalexeibarovAI : public ScriptedAI +{ + boss_lordalexeibarovAI(Creature *c) : ScriptedAI(c) {} + + uint32 Immolate_Timer; + uint32 VeilofShadow_Timer; + + void Reset() + { + Immolate_Timer = 7000; + VeilofShadow_Timer = 15000; + + me->LoadCreaturesAddon(); + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_LORDALEXEIBAROV_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Immolate_Timer + if (Immolate_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); + + Immolate_Timer = 12000; + } else Immolate_Timer -= diff; + + //VeilofShadow_Timer + if (VeilofShadow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VEILOFSHADOW); + VeilofShadow_Timer = 20000; + } else VeilofShadow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lordalexeibarov(Creature* pCreature) +{ + return new boss_lordalexeibarovAI (pCreature); +} + +void AddSC_boss_lordalexeibarov() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lord_alexei_barov"; + newscript->GetAI = &GetAI_boss_lordalexeibarov; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_lorekeeper_polkelt.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_lorekeeper_polkelt.cpp new file mode 100644 index 00000000000..d3b75900202 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_lorekeeper_polkelt.cpp @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Lorekeeper_Polkelt +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_VOLATILEINFECTION 24928 +#define SPELL_DARKPLAGUE 18270 +#define SPELL_CORROSIVEACID 23313 +#define SPELL_NOXIOUSCATALYST 18151 + +struct boss_lorekeeperpolkeltAI : public ScriptedAI +{ + boss_lorekeeperpolkeltAI(Creature *c) : ScriptedAI(c) {} + + uint32 VolatileInfection_Timer; + uint32 Darkplague_Timer; + uint32 CorrosiveAcid_Timer; + uint32 NoxiousCatalyst_Timer; + + void Reset() + { + VolatileInfection_Timer = 38000; + Darkplague_Timer = 8000; + CorrosiveAcid_Timer = 45000; + NoxiousCatalyst_Timer = 35000; + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_LOREKEEPERPOLKELT_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //VolatileInfection_Timer + if (VolatileInfection_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VOLATILEINFECTION); + VolatileInfection_Timer = 32000; + } else VolatileInfection_Timer -= diff; + + //Darkplague_Timer + if (Darkplague_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DARKPLAGUE); + Darkplague_Timer = 8000; + } else Darkplague_Timer -= diff; + + //CorrosiveAcid_Timer + if (CorrosiveAcid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVEACID); + CorrosiveAcid_Timer = 25000; + } else CorrosiveAcid_Timer -= diff; + + //NoxiousCatalyst_Timer + if (NoxiousCatalyst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_NOXIOUSCATALYST); + NoxiousCatalyst_Timer = 38000; + } else NoxiousCatalyst_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_lorekeeperpolkelt(Creature* pCreature) +{ + return new boss_lorekeeperpolkeltAI (pCreature); +} + +void AddSC_boss_lorekeeperpolkelt() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lorekeeper_polkelt"; + newscript->GetAI = &GetAI_boss_lorekeeperpolkelt; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp new file mode 100644 index 00000000000..63837e04ad5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp @@ -0,0 +1,123 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ras_Frostwhisper +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FROSTBOLT 21369 +#define SPELL_ICEARMOR 18100 //This is actually a buff he gives himself +#define SPELL_FREEZE 18763 +#define SPELL_FEAR 26070 +#define SPELL_CHILLNOVA 18099 +#define SPELL_FROSTVOLLEY 8398 + +struct boss_rasfrostAI : public ScriptedAI +{ + boss_rasfrostAI(Creature *c) : ScriptedAI(c) {} + + uint32 IceArmor_Timer; + uint32 Frostbolt_Timer; + uint32 Freeze_Timer; + uint32 Fear_Timer; + uint32 ChillNova_Timer; + uint32 FrostVolley_Timer; + + void Reset() + { + IceArmor_Timer = 2000; + Frostbolt_Timer = 8000; + ChillNova_Timer = 12000; + Freeze_Timer = 18000; + FrostVolley_Timer = 24000; + Fear_Timer = 45000; + + DoCast(me, SPELL_ICEARMOR, true); + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //IceArmor_Timer + if (IceArmor_Timer <= diff) + { + DoCast(me, SPELL_ICEARMOR); + IceArmor_Timer = 180000; + } else IceArmor_Timer -= diff; + + //Frostbolt_Timer + if (Frostbolt_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_FROSTBOLT); + + Frostbolt_Timer = 8000; + } else Frostbolt_Timer -= diff; + + //Freeze_Timer + if (Freeze_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FREEZE); + Freeze_Timer = 24000; + } else Freeze_Timer -= diff; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + Fear_Timer = 30000; + } else Fear_Timer -= diff; + + //ChillNova_Timer + if (ChillNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CHILLNOVA); + ChillNova_Timer = 14000; + } else ChillNova_Timer -= diff; + + //FrostVolley_Timer + if (FrostVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTVOLLEY); + FrostVolley_Timer = 15000; + } else FrostVolley_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_rasfrost(Creature* pCreature) +{ + return new boss_rasfrostAI (pCreature); +} + +void AddSC_boss_rasfrost() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_boss_ras_frostwhisper"; + newscript->GetAI = &GetAI_boss_rasfrost; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_the_ravenian.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_the_ravenian.cpp new file mode 100644 index 00000000000..6340f2b0e2d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_the_ravenian.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_the_ravenian +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define SPELL_TRAMPLE 15550 +#define SPELL_CLEAVE 20691 +#define SPELL_SUNDERINCLEAVE 25174 +#define SPELL_KNOCKAWAY 10101 + +struct boss_theravenianAI : public ScriptedAI +{ + boss_theravenianAI(Creature *c) : ScriptedAI(c) {} + + uint32 Trample_Timer; + uint32 Cleave_Timer; + uint32 SunderingCleave_Timer; + uint32 KnockAway_Timer; + bool HasYelled; + + void Reset() + { + Trample_Timer = 24000; + Cleave_Timer = 15000; + SunderingCleave_Timer = 40000; + KnockAway_Timer = 32000; + HasYelled = false; + } + + void JustDied(Unit * /*killer*/) + { + ScriptedInstance *pInstance = me->GetInstanceData(); + if (pInstance) + { + pInstance->SetData(DATA_THERAVENIAN_DEATH, 0); + + if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) + me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Trample_Timer + if (Trample_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TRAMPLE); + Trample_Timer = 10000; + } else Trample_Timer -= diff; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //SunderingCleave_Timer + if (SunderingCleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDERINCLEAVE); + SunderingCleave_Timer = 20000; + } else SunderingCleave_Timer -= diff; + + //KnockAway_Timer + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + KnockAway_Timer = 12000; + } else KnockAway_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_theravenian(Creature* pCreature) +{ + return new boss_theravenianAI (pCreature); +} + +void AddSC_boss_theravenian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_ravenian"; + newscript->GetAI = &GetAI_boss_theravenian; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_vectus.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_vectus.cpp new file mode 100644 index 00000000000..a38369faab0 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_vectus.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Vectus +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + EMOTE_GENERIC_FRENZY_KILL = -1000001, + + SPELL_FLAMESTRIKE = 18399, + SPELL_BLAST_WAVE = 16046, + SPELL_FIRESHIELD = 19626, + SPELL_FRENZY = 8269 //28371, +}; + +struct boss_vectusAI : public ScriptedAI +{ + boss_vectusAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiFireShield_Timer; + uint32 m_uiBlastWave_Timer; + uint32 m_uiFrenzy_Timer; + + void Reset() + { + m_uiFireShield_Timer = 2000; + m_uiBlastWave_Timer = 14000; + m_uiFrenzy_Timer = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //FireShield_Timer + if (m_uiFireShield_Timer <= uiDiff) + { + DoCast(me, SPELL_FIRESHIELD); + m_uiFireShield_Timer = 90000; + } + else + m_uiFireShield_Timer -= uiDiff; + + //BlastWave_Timer + if (m_uiBlastWave_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_BLAST_WAVE); + m_uiBlastWave_Timer = 12000; + } + else + m_uiBlastWave_Timer -= uiDiff; + + //Frenzy_Timer + if (me->GetHealth()*100 / me->GetMaxHealth() < 25) + { + if (m_uiFrenzy_Timer <= uiDiff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); + + m_uiFrenzy_Timer = 24000; + } + else + m_uiFrenzy_Timer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vectus(Creature* pCreature) +{ + return new boss_vectusAI (pCreature); +} + +void AddSC_boss_vectus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vectus"; + newscript->GetAI = &GetAI_boss_vectus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/instance_scholomance.cpp b/src/server/scripts/EasternKingdoms/Scholomance/instance_scholomance.cpp new file mode 100644 index 00000000000..992849cff1b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/instance_scholomance.cpp @@ -0,0 +1,146 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Scholomance +SD%Complete: 100 +SDComment: +SDCategory: Scholomance +EndScriptData */ + +#include "ScriptedPch.h" +#include "scholomance.h" + +#define GO_GATE_KIRTONOS 175570 +#define GO_GATE_GANDLING 177374 +#define GO_GATE_MALICIA 177375 +#define GO_GATE_THEOLEN 177377 +#define GO_GATE_POLKELT 177376 +#define GO_GATE_RAVENIAN 177372 +#define GO_GATE_BAROV 177373 +#define GO_GATE_ILLUCIA 177371 + +#define MAX_ENCOUNTER 2 + +struct instance_scholomance : public ScriptedInstance +{ + instance_scholomance(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + //Lord Alexei Barov, Doctor Theolen Krastinov, The Ravenian, Lorekeeper Polkelt, Instructor Malicia and the Lady Illucia Barov. + bool IsBossDied[6]; + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 GateKirtonosGUID; + uint64 GateGandlingGUID; + uint64 GateMiliciaGUID; + uint64 GateTheolenGUID; + uint64 GatePolkeltGUID; + uint64 GateRavenianGUID; + uint64 GateBarovGUID; + uint64 GateIlluciaGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + GateKirtonosGUID = 0; + GateGandlingGUID = 0; + GateMiliciaGUID = 0; + GateTheolenGUID = 0; + GatePolkeltGUID = 0; + GateRavenianGUID = 0; + GateBarovGUID = 0; + GateIlluciaGUID = 0; + + for (uint8 i = 0; i < 6; ++i) + IsBossDied[i] = false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_GATE_KIRTONOS: GateKirtonosGUID = pGo->GetGUID(); break; + case GO_GATE_GANDLING: GateGandlingGUID = pGo->GetGUID(); break; + case GO_GATE_MALICIA: GateMiliciaGUID = pGo->GetGUID(); break; + case GO_GATE_THEOLEN: GateTheolenGUID = pGo->GetGUID(); break; + case GO_GATE_POLKELT: GatePolkeltGUID = pGo->GetGUID(); break; + case GO_GATE_RAVENIAN: GateRavenianGUID = pGo->GetGUID(); break; + case GO_GATE_BAROV: GateBarovGUID = pGo->GetGUID(); break; + case GO_GATE_ILLUCIA: GateIlluciaGUID = pGo->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_LORDALEXEIBAROV_DEATH: + IsBossDied[0] = true; + break; + case DATA_DOCTORTHEOLENKRASTINOV_DEATH: + IsBossDied[1] = true; + break; + case DATA_THERAVENIAN_DEATH: + IsBossDied[2] = true; + break; + case DATA_LOREKEEPERPOLKELT_DEATH: + IsBossDied[3] = true; + break; + case DATA_INSTRUCTORMALICIA_DEATH: + IsBossDied[4] = true; + break; + case DATA_LADYILLUCIABAROV_DEATH: + IsBossDied[5] = true; + break; + case TYPE_GANDLING: + m_auiEncounter[0] = data; + break; + case TYPE_KIRTONOS: + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + if (type == TYPE_GANDLING) + { + if (IsBossDied[0] && IsBossDied[1] && IsBossDied[2] && IsBossDied[3] && IsBossDied[4] && IsBossDied[5]) + { + m_auiEncounter[0] = IN_PROGRESS; + return IN_PROGRESS; + } + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_scholomance(Map* pMap) +{ + return new instance_scholomance(pMap); +} + +void AddSC_instance_scholomance() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_scholomance"; + newscript->GetInstanceData = &GetInstanceData_instance_scholomance; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Scholomance/scholomance.h b/src/server/scripts/EasternKingdoms/Scholomance/scholomance.h new file mode 100644 index 00000000000..83ce26c9687 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Scholomance/scholomance.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SCHOLOMANCE_H +#define DEF_SCHOLOMANCE_H + +#define TYPE_GANDLING 1 +#define DATA_DOCTORTHEOLENKRASTINOV_DEATH 2 +#define DATA_INSTRUCTORMALICIA_DEATH 3 +#define DATA_LADYILLUCIABAROV_DEATH 4 +#define DATA_LORDALEXEIBAROV_DEATH 5 +#define DATA_LOREKEEPERPOLKELT_DEATH 6 +#define DATA_THERAVENIAN_DEATH 7 +#define TYPE_KIRTONOS 8 +#endif + diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp new file mode 100644 index 00000000000..20959641889 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp @@ -0,0 +1,277 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shadowfang_Keep +SD%Complete: 90 +SDComment: +SDCategory: Shadowfang Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadowfang_keep.h" + +#define MAX_ENCOUNTER 4 + +enum eEnums +{ + SAY_BOSS_DIE_AD = -1033007, + SAY_BOSS_DIE_AS = -1033008, + SAY_ARCHMAGE = -1033009, + + NPC_ASH = 3850, + NPC_ADA = 3849, + NPC_ARCHMAGE_ARUGAL = 4275, + NPC_ARUGAL_VOIDWALKER = 4627, + + GO_COURTYARD_DOOR = 18895, //door to open when talking to NPC's + GO_SORCERER_DOOR = 18972, //door to open when Fenrus the Devourer + GO_ARUGAL_DOOR = 18971, //door to open when Wolf Master Nandos + + SPELL_ASHCROMBE_TELEPORT = 15742 +}; + +const Position SpawnLocation[] = +{ + {-148.199,2165.647,128.448,1.026}, + {-153.110,2168.620,128.448,1.026}, + {-145.905,2180.520,128.448,4.183}, + {-140.794,2178.037,128.448,4.090}, + {-138.640,2170.159,136.577,2.737} +}; +struct instance_shadowfang_keep : public ScriptedInstance +{ + instance_shadowfang_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 uiAshGUID; + uint64 uiAdaGUID; + uint64 uiArchmageArugalGUID; + + uint64 DoorCourtyardGUID; + uint64 DoorSorcererGUID; + uint64 DoorArugalGUID; + + uint8 uiPhase; + uint16 uiTimer; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + uiAshGUID = 0; + uiAdaGUID = 0; + uiArchmageArugalGUID = 0; + + DoorCourtyardGUID = 0; + DoorSorcererGUID = 0; + DoorArugalGUID = 0; + + uiPhase = 0; + uiTimer = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_ASH: uiAshGUID = pCreature->GetGUID(); break; + case NPC_ADA: uiAdaGUID = pCreature->GetGUID(); break; + case NPC_ARCHMAGE_ARUGAL: uiArchmageArugalGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_COURTYARD_DOOR: + DoorCourtyardGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + HandleGameObject(NULL, true, pGo); + break; + case GO_SORCERER_DOOR: + DoorSorcererGUID = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + HandleGameObject(NULL, true, pGo); + break; + case GO_ARUGAL_DOOR: + DoorArugalGUID = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(NULL, true, pGo); + break; + } + } + + void DoSpeech() + { + Creature* pAda = instance->GetCreature(uiAdaGUID); + Creature* pAsh = instance->GetCreature(uiAshGUID); + + if (pAda && pAda->isAlive() && pAsh && pAsh->isAlive()) + { + DoScriptText(SAY_BOSS_DIE_AD,pAda); + DoScriptText(SAY_BOSS_DIE_AS,pAsh); + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_FREE_NPC: + if (data == DONE) + DoUseDoorOrButton(DoorCourtyardGUID); + m_auiEncounter[0] = data; + break; + case TYPE_RETHILGORE: + if (data == DONE) + DoSpeech(); + m_auiEncounter[1] = data; + break; + case TYPE_FENRUS: + switch(data) + { + case DONE: + uiTimer = 1000; + uiPhase = 1; + break; + case 7: + DoUseDoorOrButton(DoorSorcererGUID); + break; + } + m_auiEncounter[2] = data; + break; + case TYPE_NANDOS: + if (data == DONE) + DoUseDoorOrButton(DoorArugalGUID); + m_auiEncounter[3] = data; + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_FREE_NPC: + return m_auiEncounter[0]; + case TYPE_RETHILGORE: + return m_auiEncounter[1]; + case TYPE_FENRUS: + return m_auiEncounter[2]; + case TYPE_NANDOS: + return m_auiEncounter[3]; + } + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void Update(uint32 uiDiff) + { + if (GetData(TYPE_FENRUS) != DONE) + return; + + Creature* pArchmage = instance->GetCreature(uiArchmageArugalGUID); + Creature* pSummon = NULL; + + if (!pArchmage || !pArchmage->isAlive()) + return; + + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + pSummon = pArchmage->SummonCreature(pArchmage->GetEntry(),SpawnLocation[4],TEMPSUMMON_TIMED_DESPAWN,10000); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pSummon->SetReactState(REACT_DEFENSIVE); + pSummon->CastSpell(pSummon,SPELL_ASHCROMBE_TELEPORT,true); + DoScriptText(SAY_ARCHMAGE,pSummon); + uiTimer = 2000; + uiPhase = 2; + break; + case 2: + pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[0],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[1],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[2],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); + uiPhase = 0; + break; + + } + } else uiTimer -= uiDiff; + } + } +}; + +InstanceData* GetInstanceData_instance_shadowfang_keep(Map* pMap) +{ + return new instance_shadowfang_keep(pMap); +} + +void AddSC_instance_shadowfang_keep() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shadowfang_keep"; + newscript->GetInstanceData = &GetInstanceData_instance_shadowfang_keep; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp new file mode 100644 index 00000000000..23b8ad89160 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp @@ -0,0 +1,198 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Shadowfang_Keep +SD%Complete: 75 +SDComment: npc_shadowfang_prisoner using escortAI for movement to door. Might need additional code in case being attacked. Add proper texts/say(). +SDCategory: Shadowfang Keep +EndScriptData */ + +/* ContentData +npc_shadowfang_prisoner +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "shadowfang_keep.h" + +/*###### +## npc_shadowfang_prisoner +######*/ + +enum eEnums +{ + SAY_FREE_AS = -1033000, + SAY_OPEN_DOOR_AS = -1033001, + SAY_POST_DOOR_AS = -1033002, + SAY_FREE_AD = -1033003, + SAY_OPEN_DOOR_AD = -1033004, + SAY_POST1_DOOR_AD = -1033005, + SAY_POST2_DOOR_AD = -1033006, + + SPELL_UNLOCK = 6421, + NPC_ASH = 3850, + + SPELL_DARK_OFFERING = 7154 +}; + +#define GOSSIP_ITEM_DOOR "Thanks, I'll follow you to the door." + +struct npc_shadowfang_prisonerAI : public npc_escortAI +{ + npc_shadowfang_prisonerAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + uiNpcEntry = c->GetEntry(); + } + + ScriptedInstance *pInstance; + uint32 uiNpcEntry; + + void WaypointReached(uint32 uiPoint) + { + switch(uiPoint) + { + case 0: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_FREE_AS, me); + else + DoScriptText(SAY_FREE_AD, me); + break; + case 10: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_OPEN_DOOR_AS, me); + else + DoScriptText(SAY_OPEN_DOOR_AD, me); + break; + case 11: + if (uiNpcEntry == NPC_ASH) + DoCast(me, SPELL_UNLOCK); + break; + case 12: + if (uiNpcEntry == NPC_ASH) + DoScriptText(SAY_POST_DOOR_AS, me); + else + DoScriptText(SAY_POST1_DOOR_AD, me); + + if (pInstance) + pInstance->SetData(TYPE_FREE_NPC, DONE); + break; + case 13: + if (uiNpcEntry != NPC_ASH) + DoScriptText(SAY_POST2_DOOR_AD, me); + break; + } + } + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} +}; + +CreatureAI* GetAI_npc_shadowfang_prisoner(Creature* pCreature) +{ + return new npc_shadowfang_prisonerAI(pCreature); +} + +bool GossipHello_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && pInstance->GetData(TYPE_FREE_NPC) != DONE && pInstance->GetData(TYPE_RETHILGORE) == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DOOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_shadowfang_prisonerAI, pCreature->AI())) + pEscortAI->Start(false, false); + } + return true; +} + +struct npc_arugal_voidwalkerAI : public ScriptedAI +{ + npc_arugal_voidwalkerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiDarkOffering; + + void Reset() + { + uiDarkOffering = urand(290,10); + } + + void UpdateAI(uint32 const uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiDarkOffering <= uiDiff) + { + if (Creature* pFriend = me->FindNearestCreature(me->GetEntry(),25.0f,true)) + { + if (pFriend) + DoCast(pFriend,SPELL_DARK_OFFERING); + } + else + DoCast(me,SPELL_DARK_OFFERING); + uiDarkOffering = urand(4400,12500); + } else uiDarkOffering -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(TYPE_FENRUS, pInstance->GetData(TYPE_FENRUS) + 1); + } +}; + +CreatureAI* GetAI_npc_arugal_voidwalker(Creature* pCreature) +{ + return new npc_arugal_voidwalkerAI(pCreature); +} + +void AddSC_shadowfang_keep() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_shadowfang_prisoner"; + newscript->pGossipHello = &GossipHello_npc_shadowfang_prisoner; + newscript->pGossipSelect = &GossipSelect_npc_shadowfang_prisoner; + newscript->GetAI = &GetAI_npc_shadowfang_prisoner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_arugal_voidwalker"; + newscript->GetAI = &GetAI_npc_arugal_voidwalker; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h new file mode 100644 index 00000000000..a1a59789632 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHADOWFANG_H +#define DEF_SHADOWFANG_H + +enum eData +{ + TYPE_FREE_NPC = 1, + TYPE_RETHILGORE = 2, + TYPE_FENRUS = 3, + TYPE_NANDOS = 4 +}; + +#endif + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp new file mode 100644 index 00000000000..de17717e289 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp @@ -0,0 +1,190 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Baron_Rivendare +SD%Complete: 70 +SDComment: aura applied/defined in database +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SAY_0 "Intruders! More pawns of the Argent Dawn, no doubt. I already count one of their number among my prisoners. Withdraw from my domain before she is executed!" +#define SAY_1 "You're still here? Your foolishness is amusing! The Argent Dawn wench needn't suffer in vain. Leave at once and she shall be spared!" +#define SAY_2 "I shall take great pleasure in taking this poor wretch's life! It's not too late, she needn't suffer in vain. Turn back and her death shall be merciful!" +#define SAY_3 "May this prisoner's death serve as a warning. None shall defy the Scourge and live!" +#define SAY_4 "So you see fit to toy with the Lich King's creations? Ramstein, be sure to give the intruders a proper greeting." +#define SAY_5 "Time to take matters into my own hands. Come. Enter my domain and challenge the might of the Scourge!" + +#define ADD_1X 4017.403809 +#define ADD_1Y -3339.703369 +#define ADD_1Z 115.057655 +#define ADD_1O 5.487860 + +#define ADD_2X 4013.189209 +#define ADD_2Y -3351.808350 +#define ADD_2Z 115.052254 +#define ADD_2O 0.134280 + +#define ADD_3X 4017.738037 +#define ADD_3Y -3363.478016 +#define ADD_3Z 115.057274 +#define ADD_3O 0.723313 + +#define ADD_4X 4048.877197 +#define ADD_4Y -3363.223633 +#define ADD_4Z 115.054253 +#define ADD_4O 3.627735 + +#define ADD_5X 4051.777588 +#define ADD_5Y -3350.893311 +#define ADD_5Z 115.055351 +#define ADD_5O 3.066176 + +#define ADD_6X 4048.375977 +#define ADD_6Y -3339.966309 +#define ADD_6Z 115.055222 +#define ADD_6O 2.457497 + +#define SPELL_SHADOWBOLT 17393 +#define SPELL_CLEAVE 15284 +#define SPELL_MORTALSTRIKE 15708 + +#define SPELL_UNHOLY_AURA 17467 +#define SPELL_RAISEDEAD 17473 //triggers death pact (17471) + +#define SPELL_RAISE_DEAD1 17475 +#define SPELL_RAISE_DEAD2 17476 +#define SPELL_RAISE_DEAD3 17477 +#define SPELL_RAISE_DEAD4 17478 +#define SPELL_RAISE_DEAD5 17479 +#define SPELL_RAISE_DEAD6 17480 + +struct boss_baron_rivendareAI : public ScriptedAI +{ + boss_baron_rivendareAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ShadowBolt_Timer; + uint32 Cleave_Timer; + uint32 MortalStrike_Timer; + // uint32 RaiseDead_Timer; + uint32 SummonSkeletons_Timer; + + void Reset() + { + ShadowBolt_Timer = 5000; + Cleave_Timer = 8000; + MortalStrike_Timer = 12000; + // RaiseDead_Timer = 30000; + SummonSkeletons_Timer = 34000; + if (pInstance && pInstance->GetData(TYPE_RAMSTEIN) == DONE) + pInstance->SetData(TYPE_BARON,NOT_STARTED); + } + + void AttackStart(Unit* who) + { + if (pInstance)//can't use entercombat(), boss' dmg aura sets near players in combat, before entering the room's door + pInstance->SetData(TYPE_BARON,IN_PROGRESS); + ScriptedAI::AttackStart(who); + } + + void JustSummoned(Creature* summoned) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(pTarget); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_BARON,DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ShadowBolt + if (ShadowBolt_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(me->getVictim(), SPELL_SHADOWBOLT); + + ShadowBolt_Timer = 10000; + } else ShadowBolt_Timer -= diff; + + //Cleave + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + //13 seconds until we should cast this again + Cleave_Timer = 7000 + (rand()%10000); + } else Cleave_Timer -= diff; + + //MortalStrike + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALSTRIKE); + MortalStrike_Timer = 10000 + (rand()%15000); + } else MortalStrike_Timer -= diff; + + //RaiseDead + // if (RaiseDead_Timer <= diff) + // { + // DoCast(me, SPELL_RAISEDEAD); + // RaiseDead_Timer = 45000; + // } else RaiseDead_Timer -= diff; + + //SummonSkeletons + if (SummonSkeletons_Timer <= diff) + { + me->SummonCreature(11197,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,29000); + me->SummonCreature(11197,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,29000); + + //34 seconds until we should cast this again + SummonSkeletons_Timer = 40000; + } else SummonSkeletons_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_baron_rivendare(Creature* pCreature) +{ + return new boss_baron_rivendareAI (pCreature); +} + +void AddSC_boss_baron_rivendare() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_baron_rivendare"; + newscript->GetAI = &GetAI_boss_baron_rivendare; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_baroness_anastari.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_baroness_anastari.cpp new file mode 100644 index 00000000000..cff4fe3fbae --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_baroness_anastari.cpp @@ -0,0 +1,127 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Baroness_Anastari +SD%Complete: 90 +SDComment: MC disabled +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_BANSHEEWAIL 16565 +#define SPELL_BANSHEECURSE 16867 +#define SPELL_SILENCE 18327 +//#define SPELL_POSSESS 17244 + +struct boss_baroness_anastariAI : public ScriptedAI +{ + boss_baroness_anastariAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 BansheeWail_Timer; + uint32 BansheeCurse_Timer; + uint32 Silence_Timer; + //uint32 Possess_Timer; + + void Reset() + { + BansheeWail_Timer = 1000; + BansheeCurse_Timer = 11000; + Silence_Timer = 13000; + //Possess_Timer = 35000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_BARONESS,IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //BansheeWail + if (BansheeWail_Timer <= diff) + { + if (rand()%100 < 95) + DoCast(me->getVictim(), SPELL_BANSHEEWAIL); + //4 seconds until we should cast this again + BansheeWail_Timer = 4000; + } else BansheeWail_Timer -= diff; + + //BansheeCurse + if (BansheeCurse_Timer <= diff) + { + if (rand()%100 < 75) + DoCast(me->getVictim(), SPELL_BANSHEECURSE); + //18 seconds until we should cast this again + BansheeCurse_Timer = 18000; + } else BansheeCurse_Timer -= diff; + + //Silence + if (Silence_Timer <= diff) + { + if (rand()%100 < 80) + DoCast(me->getVictim(), SPELL_SILENCE); + //13 seconds until we should cast this again + Silence_Timer = 13000; + } else Silence_Timer -= diff; + + //Possess + /* if (Possess_Timer <= diff) + { + //Cast + if (rand()%100 < 65) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget)DoCast(pTarget, SPELL_POSSESS); + } + //50 seconds until we should cast this again + Possess_Timer = 50000; + } else Possess_Timer -= diff; + */ + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_baroness_anastari(Creature* pCreature) +{ + return new boss_baroness_anastariAI (pCreature); +} + +void AddSC_boss_baroness_anastari() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_baroness_anastari"; + newscript->GetAI = &GetAI_boss_baroness_anastari; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_cannon_master_willey.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_cannon_master_willey.cpp new file mode 100644 index 00000000000..c12f7b9ad04 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_cannon_master_willey.cpp @@ -0,0 +1,220 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_cannon_master_willey +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" + +//front, left +#define ADD_1X 3553.851807 +#define ADD_1Y -2945.885986 +#define ADD_1Z 125.001015 +#define ADD_1O 0.592007 +//front, right +#define ADD_2X 3559.206299 +#define ADD_2Y -2952.929932 +#define ADD_2Z 125.001015 +#define ADD_2O 0.592007 +//mid, left +#define ADD_3X 3552.417480 +#define ADD_3Y -2948.667236 +#define ADD_3Z 125.001015 +#define ADD_3O 0.592007 +//mid, right +#define ADD_4X 3555.651855 +#define ADD_4Y -2953.519043 +#define ADD_4Z 125.001015 +#define ADD_4O 0.592007 +//back, left +#define ADD_5X 3547.927246 +#define ADD_5Y -2950.977295 +#define ADD_5Z 125.001015 +#define ADD_5O 0.592007 +//back, mid +#define ADD_6X 3553.094697 +#define ADD_6Y -2952.123291 +#define ADD_6Z 125.001015 +#define ADD_6O 0.592007 +//back, right +#define ADD_7X 3552.727539 +#define ADD_7Y -2957.776123 +#define ADD_7Z 125.001015 +#define ADD_7O 0.592007 +//behind, left +#define ADD_8X 3547.156250 +#define ADD_8Y -2953.162354 +#define ADD_8Z 125.001015 +#define ADD_8O 0.592007 +//behind, right +#define ADD_9X 3550.202148 +#define ADD_9Y -2957.437744 +#define ADD_9Z 125.001015 +#define ADD_9O 0.592007 + +#define SPELL_KNOCKAWAY 10101 +#define SPELL_PUMMEL 15615 +#define SPELL_SHOOT 16496 +//#define SPELL_SUMMONCRIMSONRIFLEMAN 17279 + +struct boss_cannon_master_willeyAI : public ScriptedAI +{ + boss_cannon_master_willeyAI(Creature *c) : ScriptedAI(c) {} + + uint32 KnockAway_Timer; + uint32 Pummel_Timer; + uint32 Shoot_Timer; + uint32 SummonRifleman_Timer; + + void Reset() + { + Shoot_Timer = 1000; + Pummel_Timer = 7000; + KnockAway_Timer = 11000; + SummonRifleman_Timer = 15000; + } + + void JustDied(Unit* /*Victim*/) + { + me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Pummel + if (Pummel_Timer <= diff) + { + //Cast + if (rand()%100 < 90) //90% chance to cast + { + DoCast(me->getVictim(), SPELL_PUMMEL); + } + //12 seconds until we should cast this again + Pummel_Timer = 12000; + } else Pummel_Timer -= diff; + + //KnockAway + if (KnockAway_Timer <= diff) + { + //Cast + if (rand()%100 < 80) //80% chance to cast + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + } + //14 seconds until we should cast this again + KnockAway_Timer = 14000; + } else KnockAway_Timer -= diff; + + //Shoot + if (Shoot_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_SHOOT); + //1 seconds until we should cast this again + Shoot_Timer = 1000; + } else Shoot_Timer -= diff; + + //SummonRifleman + if (SummonRifleman_Timer <= diff) + { + //Cast + switch (rand()%9) + { + case 0: + me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 1: + me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 2: + me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 3: + me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 4: + me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 5: + me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 6: + me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 7: + me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + case 8: + me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); + me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); + break; + } + //30 seconds until we should cast this again + SummonRifleman_Timer = 30000; + } else SummonRifleman_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_cannon_master_willey(Creature* pCreature) +{ + return new boss_cannon_master_willeyAI (pCreature); +} + +void AddSC_boss_cannon_master_willey() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_cannon_master_willey"; + newscript->GetAI = &GetAI_boss_cannon_master_willey; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_dathrohan_balnazzar.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_dathrohan_balnazzar.cpp new file mode 100644 index 00000000000..a8489a7f549 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_dathrohan_balnazzar.cpp @@ -0,0 +1,217 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Dathrohan_Balnazzar +SD%Complete: 95 +SDComment: Possibly need to fix/improve summons after death +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" + +enum eEnums +{ + //Dathrohan spells + SPELL_CRUSADERSHAMMER = 17286, //AOE stun + SPELL_CRUSADERSTRIKE = 17281, + SPELL_HOLYSTRIKE = 17284, //weapon dmg +3 + + //Transform + SPELL_BALNAZZARTRANSFORM = 17288, //restore full HP/mana, trigger spell Balnazzar Transform Stun + + //Balnazzar spells + SPELL_SHADOWSHOCK = 17399, + SPELL_MINDBLAST = 17287, + SPELL_PSYCHICSCREAM = 13704, + SPELL_SLEEP = 12098, + SPELL_MINDCONTROL = 15690, + + NPC_DATHROHAN = 10812, + NPC_BALNAZZAR = 10813, + NPC_ZOMBIE = 10698 //probably incorrect +}; + +struct SummonDef +{ + float m_fX, m_fY, m_fZ, m_fOrient; +}; + +SummonDef m_aSummonPoint[]= +{ + {3444.156, -3090.626, 135.002, 2.240}, //G1 front, left + {3449.123, -3087.009, 135.002, 2.240}, //G1 front, right + {3446.246, -3093.466, 135.002, 2.240}, //G1 back left + {3451.160, -3089.904, 135.002, 2.240}, //G1 back, right + + {3457.995, -3080.916, 135.002, 3.784}, //G2 front, left + {3454.302, -3076.330, 135.002, 3.784}, //G2 front, right + {3460.975, -3078.901, 135.002, 3.784}, //G2 back left + {3457.338, -3073.979, 135.002, 3.784} //G2 back, right +}; + +struct boss_dathrohan_balnazzarAI : public ScriptedAI +{ + boss_dathrohan_balnazzarAI(Creature *c) : ScriptedAI(c) {} + + uint32 m_uiCrusadersHammer_Timer; + uint32 m_uiCrusaderStrike_Timer; + uint32 m_uiMindBlast_Timer; + uint32 m_uiHolyStrike_Timer; + uint32 m_uiShadowShock_Timer; + uint32 m_uiPsychicScream_Timer; + uint32 m_uiDeepSleep_Timer; + uint32 m_uiMindControl_Timer; + bool m_bTransformed; + + void Reset() + { + m_uiCrusadersHammer_Timer = 8000; + m_uiCrusaderStrike_Timer = 12000; + m_uiMindBlast_Timer = 6000; + m_uiHolyStrike_Timer = 18000; + m_uiShadowShock_Timer = 4000; + m_uiPsychicScream_Timer = 16000; + m_uiDeepSleep_Timer = 20000; + m_uiMindControl_Timer = 10000; + m_bTransformed = false; + + if (me->GetEntry() == NPC_BALNAZZAR) + me->UpdateEntry(NPC_DATHROHAN); + } + + void JustDied(Unit* /*Victim*/) + { + static uint32 uiCount = sizeof(m_aSummonPoint)/sizeof(SummonDef); + + for (uint8 i=0; iSummonCreature(NPC_ZOMBIE, + m_aSummonPoint[i].m_fX, m_aSummonPoint[i].m_fY, m_aSummonPoint[i].m_fZ, m_aSummonPoint[i].m_fOrient, + TEMPSUMMON_TIMED_DESPAWN, HOUR*IN_MILISECONDS); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //START NOT TRANSFORMED + if (!m_bTransformed) + { + //MindBlast + if (m_uiMindBlast_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MINDBLAST); + m_uiMindBlast_Timer = 15000 + rand()%5000; + } else m_uiMindBlast_Timer -= uiDiff; + + //CrusadersHammer + if (m_uiCrusadersHammer_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CRUSADERSHAMMER); + m_uiCrusadersHammer_Timer = 12000; + } else m_uiCrusadersHammer_Timer -= uiDiff; + + //CrusaderStrike + if (m_uiCrusaderStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CRUSADERSTRIKE); + m_uiCrusaderStrike_Timer = 15000; + } else m_uiCrusaderStrike_Timer -= uiDiff; + + //HolyStrike + if (m_uiHolyStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_HOLYSTRIKE); + m_uiHolyStrike_Timer = 15000; + } else m_uiHolyStrike_Timer -= uiDiff; + + //BalnazzarTransform + if (me->GetHealth()*100 / me->GetMaxHealth() < 40) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + //restore hp, mana and stun + DoCast(me, SPELL_BALNAZZARTRANSFORM); + me->UpdateEntry(NPC_BALNAZZAR); + m_bTransformed = true; + } + } + else + { + //MindBlast + if (m_uiMindBlast_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MINDBLAST); + m_uiMindBlast_Timer = 15000 + rand()%5000; + } else m_uiMindBlast_Timer -= uiDiff; + + //ShadowShock + if (m_uiShadowShock_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SHADOWSHOCK); + m_uiShadowShock_Timer = 11000; + } else m_uiShadowShock_Timer -= uiDiff; + + //PsychicScream + if (m_uiPsychicScream_Timer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_PSYCHICSCREAM); + + m_uiPsychicScream_Timer = 20000; + } else m_uiPsychicScream_Timer -= uiDiff; + + //DeepSleep + if (m_uiDeepSleep_Timer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SLEEP); + + m_uiDeepSleep_Timer = 15000; + } else m_uiDeepSleep_Timer -= uiDiff; + + //MindControl + if (m_uiMindControl_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MINDCONTROL); + m_uiMindControl_Timer = 15000; + } else m_uiMindControl_Timer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_dathrohan_balnazzar(Creature* pCreature) +{ + return new boss_dathrohan_balnazzarAI (pCreature); +} + +void AddSC_boss_dathrohan_balnazzar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_dathrohan_balnazzar"; + newscript->GetAI = &GetAI_boss_dathrohan_balnazzar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_magistrate_barthilas.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_magistrate_barthilas.cpp new file mode 100644 index 00000000000..89de7dbc207 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_magistrate_barthilas.cpp @@ -0,0 +1,128 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Magistrate_Barthilas +SD%Complete: 70 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_DRAININGBLOW 16793 +#define SPELL_CROWDPUMMEL 10887 +#define SPELL_MIGHTYBLOW 14099 +#define SPELL_FURIOUS_ANGER 16791 + +#define MODEL_NORMAL 10433 +#define MODEL_HUMAN 3637 + +struct boss_magistrate_barthilasAI : public ScriptedAI +{ + boss_magistrate_barthilasAI(Creature *c) : ScriptedAI(c) {} + + uint32 DrainingBlow_Timer; + uint32 CrowdPummel_Timer; + uint32 MightyBlow_Timer; + uint32 FuriousAnger_Timer; + uint32 AngerCount; + + void Reset() + { + DrainingBlow_Timer = 20000; + CrowdPummel_Timer = 15000; + MightyBlow_Timer = 10000; + FuriousAnger_Timer = 5000; + AngerCount = 0; + + if (me->isAlive()) + me->SetDisplayId(MODEL_NORMAL); + else + me->SetDisplayId(MODEL_HUMAN); + } + + void MoveInLineOfSight(Unit *who) + { + //nothing to see here yet + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit* /*Killer*/) + { + me->SetDisplayId(MODEL_HUMAN); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (FuriousAnger_Timer <= diff) + { + FuriousAnger_Timer = 4000; + if (AngerCount > 25) + return; + + ++AngerCount; + DoCast(me, SPELL_FURIOUS_ANGER, false); + } else FuriousAnger_Timer -= diff; + + //DrainingBlow + if (DrainingBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DRAININGBLOW); + DrainingBlow_Timer = 15000; + } else DrainingBlow_Timer -= diff; + + //CrowdPummel + if (CrowdPummel_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CROWDPUMMEL); + CrowdPummel_Timer = 15000; + } else CrowdPummel_Timer -= diff; + + //MightyBlow + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTYBLOW); + MightyBlow_Timer = 20000; + } else MightyBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_magistrate_barthilas(Creature* pCreature) +{ + return new boss_magistrate_barthilasAI (pCreature); +} + +void AddSC_boss_magistrate_barthilas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magistrate_barthilas"; + newscript->GetAI = &GetAI_boss_magistrate_barthilas; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_maleki_the_pallid.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_maleki_the_pallid.cpp new file mode 100644 index 00000000000..0c1cf011d5e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_maleki_the_pallid.cpp @@ -0,0 +1,108 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_maleki_the_pallid +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_FROSTBOLT 17503 +#define SPELL_DRAINLIFE 20743 +#define SPELL_DRAIN_MANA 17243 +#define SPELL_ICETOMB 16869 + +struct boss_maleki_the_pallidAI : public ScriptedAI +{ + boss_maleki_the_pallidAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Frostbolt_Timer; + uint32 IceTomb_Timer; + uint32 DrainLife_Timer; + + void Reset() + { + Frostbolt_Timer = 1000; + IceTomb_Timer = 16000; + DrainLife_Timer = 31000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_PALLID,IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frostbolt + if (Frostbolt_Timer <= diff) + { + if (rand()%100 < 90) + DoCast(me->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 3500; + } else Frostbolt_Timer -= diff; + + //IceTomb + if (IceTomb_Timer <= diff) + { + if (rand()%100 < 65) + DoCast(me->getVictim(), SPELL_ICETOMB); + IceTomb_Timer = 28000; + } else IceTomb_Timer -= diff; + + //DrainLife + if (DrainLife_Timer <= diff) + { + if (rand()%100 < 55) + DoCast(me->getVictim(), SPELL_DRAINLIFE); + DrainLife_Timer = 31000; + } else DrainLife_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_maleki_the_pallid(Creature* pCreature) +{ + return new boss_maleki_the_pallidAI (pCreature); +} + +void AddSC_boss_maleki_the_pallid() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_maleki_the_pallid"; + newscript->GetAI = &GetAI_boss_maleki_the_pallid; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_nerubenkan.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_nerubenkan.cpp new file mode 100644 index 00000000000..ae7299071f4 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_nerubenkan.cpp @@ -0,0 +1,121 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Nerubenkan +SD%Complete: 70 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_ENCASINGWEBS 4962 +#define SPELL_PIERCEARMOR 6016 +#define SPELL_CRYPT_SCARABS 31602 +#define SPELL_RAISEUNDEADSCARAB 17235 + +struct boss_nerubenkanAI : public ScriptedAI +{ + boss_nerubenkanAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 EncasingWebs_Timer; + uint32 PierceArmor_Timer; + uint32 CryptScarabs_Timer; + uint32 RaiseUndeadScarab_Timer; + + void Reset() + { + CryptScarabs_Timer = 3000; + EncasingWebs_Timer = 7000; + PierceArmor_Timer = 19000; + RaiseUndeadScarab_Timer = 3000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_NERUB,IN_PROGRESS); + } + + void RaiseUndeadScarab(Unit* pVictim) + { + if (Creature* pUndeadScarab = DoSpawnCreature(10876, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000)) + if (pUndeadScarab->AI()) + pUndeadScarab->AI()->AttackStart(pVictim); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //EncasingWebs + if (EncasingWebs_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ENCASINGWEBS); + EncasingWebs_Timer = 30000; + } else EncasingWebs_Timer -= diff; + + //PierceArmor + if (PierceArmor_Timer <= diff) + { + if (urand(0,3) < 2) + DoCast(me->getVictim(), SPELL_PIERCEARMOR); + PierceArmor_Timer = 35000; + } else PierceArmor_Timer -= diff; + + //CryptScarabs_Timer + if (CryptScarabs_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CRYPT_SCARABS); + CryptScarabs_Timer = 20000; + } else CryptScarabs_Timer -= diff; + + //RaiseUndeadScarab + if (RaiseUndeadScarab_Timer <= diff) + { + RaiseUndeadScarab(me->getVictim()); + RaiseUndeadScarab_Timer = 16000; + } else RaiseUndeadScarab_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_nerubenkan(Creature* pCreature) +{ + return new boss_nerubenkanAI (pCreature); +} + +void AddSC_boss_nerubenkan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nerubenkan"; + newscript->GetAI = &GetAI_boss_nerubenkan; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_order_of_silver_hand.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_order_of_silver_hand.cpp new file mode 100644 index 00000000000..905feb9fffc --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_order_of_silver_hand.cpp @@ -0,0 +1,157 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Silver_Hand_Bosses +SD%Complete: 40 +SDComment: Basic script to have support for Horde paladin epic mount (quest 9737). All 5 members of Order of the Silver Hand running this script (least for now) +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +/*##### +# Additional: +# Although this is a working solution, the correct would be in addition to check if Aurius is dead. +# Once player extinguish the eternal flame (cast spell 31497->start event 11206) Aurius should become hostile. +# Once Aurius is defeated, he should be the one summoning the ghosts. +#####*/ + +#define SH_GREGOR 17910 +#define SH_CATHELA 17911 +#define SH_NEMAS 17912 +#define SH_AELMAR 17913 +#define SH_VICAR 17914 +#define SH_QUEST_CREDIT 17915 + +#define SPELL_HOLY_LIGHT 25263 +#define SPELL_DIVINE_SHIELD 13874 + +struct boss_silver_hand_bossesAI : public ScriptedAI +{ + boss_silver_hand_bossesAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 HolyLight_Timer; + uint32 DivineShield_Timer; + + void Reset() + { + HolyLight_Timer = 20000; + DivineShield_Timer = 20000; + + if (pInstance) + { + switch(me->GetEntry()) + { + case SH_AELMAR: + pInstance->SetData(TYPE_SH_AELMAR, 0); + break; + case SH_CATHELA: + pInstance->SetData(TYPE_SH_CATHELA, 0); + break; + case SH_GREGOR: + pInstance->SetData(TYPE_SH_GREGOR, 0); + break; + case SH_NEMAS: + pInstance->SetData(TYPE_SH_NEMAS, 0); + break; + case SH_VICAR: + pInstance->SetData(TYPE_SH_VICAR, 0); + break; + } + } + } + + void EnterCombat(Unit* /*who*/) + { + } + + void JustDied(Unit* Killer) + { + if (pInstance) + { + switch(me->GetEntry()) + { + case SH_AELMAR: + pInstance->SetData(TYPE_SH_AELMAR, 2); + break; + case SH_CATHELA: + pInstance->SetData(TYPE_SH_CATHELA, 2); + break; + case SH_GREGOR: + pInstance->SetData(TYPE_SH_GREGOR, 2); + break; + case SH_NEMAS: + pInstance->SetData(TYPE_SH_NEMAS, 2); + break; + case SH_VICAR: + pInstance->SetData(TYPE_SH_VICAR, 2); + break; + } + if (pInstance->GetData(TYPE_SH_QUEST) && Killer->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(Killer)->KilledMonsterCredit(SH_QUEST_CREDIT,me->GetGUID()); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (HolyLight_Timer <= diff) + { + if (me->GetHealth()*5 < me->GetMaxHealth()) + { + DoCast(me, SPELL_HOLY_LIGHT); + HolyLight_Timer = 20000; + } + } else HolyLight_Timer -= diff; + + if (DivineShield_Timer <= diff) + { + if (me->GetHealth()*20 < me->GetMaxHealth()) + { + DoCast(me, SPELL_DIVINE_SHIELD); + DivineShield_Timer = 40000; + } + } else DivineShield_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_boss_silver_hand_bossesAI(Creature* pCreature) +{ + return new boss_silver_hand_bossesAI (pCreature); +} + +void AddSC_boss_order_of_silver_hand() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_silver_hand_bosses"; + newscript->GetAI = &GetAI_boss_silver_hand_bossesAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_postmaster_malown.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_postmaster_malown.cpp new file mode 100644 index 00000000000..c04bae15468 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_postmaster_malown.cpp @@ -0,0 +1,144 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_postmaster_malown +SD%Complete: 50 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" + +//Spell ID to summon this guy is 24627 "Summon Postmaster Malown" +//He should be spawned along with three other elites once the third postbox has been opened + +#define SAY_MALOWNED "You just got MALOWNED!" + +#define SPELL_WAILINGDEAD 7713 +#define SPELL_BACKHAND 6253 +#define SPELL_CURSEOFWEAKNESS 8552 +#define SPELL_CURSEOFTONGUES 12889 +#define SPELL_CALLOFTHEGRAVE 17831 + +struct boss_postmaster_malownAI : public ScriptedAI +{ + boss_postmaster_malownAI(Creature *c) : ScriptedAI(c) {} + + uint32 WailingDead_Timer; + uint32 Backhand_Timer; + uint32 CurseOfWeakness_Timer; + uint32 CurseOfTongues_Timer; + uint32 CallOfTheGrave_Timer; + bool HasYelled; + + void Reset() + { + WailingDead_Timer = 19000; //lasts 6 sec + Backhand_Timer = 8000; //2 sec stun + CurseOfWeakness_Timer = 20000; //lasts 2 mins + CurseOfTongues_Timer = 22000; + CallOfTheGrave_Timer = 25000; + HasYelled = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //WailingDead + if (WailingDead_Timer <= diff) + { + //Cast + if (rand()%100 < 65) //65% chance to cast + { + DoCast(me->getVictim(), SPELL_WAILINGDEAD); + } + //19 seconds until we should cast this again + WailingDead_Timer = 19000; + } else WailingDead_Timer -= diff; + + //Backhand + if (Backhand_Timer <= diff) + { + //Cast + if (rand()%100 < 45) //45% chance to cast + { + DoCast(me->getVictim(), SPELL_BACKHAND); + } + //8 seconds until we should cast this again + Backhand_Timer = 8000; + } else Backhand_Timer -= diff; + + //CurseOfWeakness + if (CurseOfWeakness_Timer <= diff) + { + //Cast + if (rand()%100 < 3) //3% chance to cast + { + DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); + } + //20 seconds until we should cast this again + CurseOfWeakness_Timer = 20000; + } else CurseOfWeakness_Timer -= diff; + + //CurseOfTongues + if (CurseOfTongues_Timer <= diff) + { + //Cast + if (rand()%100 < 3) //3% chance to cast + { + DoCast(me->getVictim(), SPELL_CURSEOFTONGUES); + } + //22 seconds until we should cast this again + CurseOfTongues_Timer = 22000; + } else CurseOfTongues_Timer -= diff; + + //CallOfTheGrave + if (CallOfTheGrave_Timer <= diff) + { + //Cast + if (rand()%100 < 5) //5% chance to cast + { + DoCast(me->getVictim(), SPELL_CALLOFTHEGRAVE); + } + //25 seconds until we should cast this again + CallOfTheGrave_Timer = 25000; + } else CallOfTheGrave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_postmaster_malown(Creature* pCreature) +{ + return new boss_postmaster_malownAI (pCreature); +} + +void AddSC_boss_postmaster_malown() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_postmaster_malown"; + newscript->GetAI = &GetAI_boss_postmaster_malown; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_ramstein_the_gorger.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_ramstein_the_gorger.cpp new file mode 100644 index 00000000000..3a3ae60c9c9 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_ramstein_the_gorger.cpp @@ -0,0 +1,102 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Ramstein_The_Gorger +SD%Complete: 70 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define SPELL_TRAMPLE 5568 +#define SPELL_KNOCKOUT 17307 + + #define C_MINDLESS_UNDEAD 11030 + +struct boss_ramstein_the_gorgerAI : public ScriptedAI +{ + boss_ramstein_the_gorgerAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Trample_Timer; + uint32 Knockout_Timer; + + void Reset() + { + Trample_Timer = 3000; + Knockout_Timer = 12000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + for (uint8 i = 0; i < 30; ++i) + { + if (Creature* mob = me->SummonCreature(C_MINDLESS_UNDEAD,3969.35+irand(-10,10),-3391.87+irand(-10,10),119.11,5.91,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000)) + mob->AI()->AttackStart(me->SelectNearestTarget(500)); + } + + if (pInstance) + pInstance->SetData(TYPE_RAMSTEIN,DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Trample + if (Trample_Timer <= diff) + { + DoCast(me, SPELL_TRAMPLE); + Trample_Timer = 7000; + } else Trample_Timer -= diff; + + //Knockout + if (Knockout_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKOUT); + Knockout_Timer = 10000; + } else Knockout_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ramstein_the_gorger(Creature* pCreature) +{ + return new boss_ramstein_the_gorgerAI (pCreature); +} + +void AddSC_boss_ramstein_the_gorger() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ramstein_the_gorger"; + newscript->GetAI = &GetAI_boss_ramstein_the_gorger; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_timmy_the_cruel.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_timmy_the_cruel.cpp new file mode 100644 index 00000000000..f15eb59ba47 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_timmy_the_cruel.cpp @@ -0,0 +1,83 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_timmy_the_cruel +SD%Complete: 100 +SDComment: +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_SPAWN "TIMMY!" + +#define SPELL_RAVENOUSCLAW 17470 + +struct boss_timmy_the_cruelAI : public ScriptedAI +{ + boss_timmy_the_cruelAI(Creature *c) : ScriptedAI(c) {} + + uint32 RavenousClaw_Timer; + bool HasYelled; + + void Reset() + { + RavenousClaw_Timer = 10000; + HasYelled = false; + } + + void EnterCombat(Unit * /*who*/) + { + if (!HasYelled) + { + me->MonsterYell(SAY_SPAWN,LANG_UNIVERSAL,NULL); + HasYelled = true; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //RavenousClaw + if (RavenousClaw_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_RAVENOUSCLAW); + //15 seconds until we should cast this again + RavenousClaw_Timer = 15000; + } else RavenousClaw_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_timmy_the_cruel(Creature* pCreature) +{ + return new boss_timmy_the_cruelAI (pCreature); +} + +void AddSC_boss_timmy_the_cruel() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_timmy_the_cruel"; + newscript->GetAI = &GetAI_boss_timmy_the_cruel; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp b/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp new file mode 100644 index 00000000000..ffeaa070a26 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp @@ -0,0 +1,458 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: instance_stratholme +SD%Complete: 50 +SDComment: In progress. Undead side 75% implemented. Save/load not implemented. +SDCategory: Stratholme +EndScriptData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +#define GO_SERVICE_ENTRANCE 175368 +#define GO_GAUNTLET_GATE1 175357 +#define GO_ZIGGURAT1 175380 //baroness +#define GO_ZIGGURAT2 175379 //nerub'enkan +#define GO_ZIGGURAT3 175381 //maleki +#define GO_ZIGGURAT4 175405 //rammstein +#define GO_ZIGGURAT5 175796 //baron +#define GO_PORT_GAUNTLET 175374 //port from gauntlet to slaugther +#define GO_PORT_SLAUGTHER 175373 //port at slaugther +#define GO_PORT_ELDERS 175377 //port at elders square + +#define C_CRYSTAL 10415 //three ziggurat crystals +#define C_BARON 10440 +#define C_YSIDA_TRIGGER 16100 + +#define C_RAMSTEIN 10439 +#define C_ABOM_BILE 10416 +#define C_ABOM_VENOM 10417 +#define C_BLACK_GUARD 10394 +#define C_YSIDA 16031 + +#define MAX_ENCOUNTER 6 + +struct instance_stratholme : public ScriptedInstance +{ + instance_stratholme(Map* pMap) : ScriptedInstance(pMap) {} + + uint32 Encounter[MAX_ENCOUNTER]; + + bool IsSilverHandDead[5]; + + uint32 BaronRun_Timer; + uint32 SlaugtherSquare_Timer; + + uint64 serviceEntranceGUID; + uint64 gauntletGate1GUID; + uint64 ziggurat1GUID; + uint64 ziggurat2GUID; + uint64 ziggurat3GUID; + uint64 ziggurat4GUID; + uint64 ziggurat5GUID; + uint64 portGauntletGUID; + uint64 portSlaugtherGUID; + uint64 portElderGUID; + + uint64 baronGUID; + uint64 ysidaTriggerGUID; + std::set crystalsGUID; + std::set abomnationGUID; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + Encounter[i] = NOT_STARTED; + + for (uint8 i = 0; i < 5; ++i) + IsSilverHandDead[i] = false; + + BaronRun_Timer = 0; + SlaugtherSquare_Timer = 0; + + serviceEntranceGUID = 0; + gauntletGate1GUID = 0; + ziggurat1GUID = 0; + ziggurat2GUID = 0; + ziggurat3GUID = 0; + ziggurat4GUID = 0; + ziggurat5GUID = 0; + portGauntletGUID = 0; + portSlaugtherGUID = 0; + portElderGUID = 0; + + baronGUID = 0; + ysidaTriggerGUID = 0; + crystalsGUID.clear(); + abomnationGUID.clear(); + } + + bool StartSlaugtherSquare() + { + //change to DONE when crystals implemented + if (Encounter[1] == IN_PROGRESS && Encounter[2] == IN_PROGRESS && Encounter[3] == IN_PROGRESS) + { + HandleGameObject(portGauntletGUID, true); + HandleGameObject(portSlaugtherGUID, true); + return true; + } + + debug_log("TSCR: Instance Stratholme: Cannot open slaugther square yet."); + return false; + } + + //if withRestoreTime true, then newState will be ignored and GO should be restored to original state after 10 seconds + void UpdateGoState(uint64 goGuid, uint32 newState, bool withRestoreTime) + { + if (!goGuid) + return; + + if (GameObject* pGo = instance->GetGameObject(goGuid)) + { + if (withRestoreTime) + pGo->UseDoorOrButton(10); + else + pGo->SetGoState((GOState)newState); + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case C_BARON: baronGUID = pCreature->GetGUID(); break; + case C_YSIDA_TRIGGER: ysidaTriggerGUID = pCreature->GetGUID(); break; + case C_CRYSTAL: crystalsGUID.insert(pCreature->GetGUID()); break; + case C_ABOM_BILE: + case C_ABOM_VENOM: abomnationGUID.insert(pCreature->GetGUID()); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_SERVICE_ENTRANCE: + serviceEntranceGUID = pGo->GetGUID(); + break; + case GO_GAUNTLET_GATE1: + //weird, but unless flag is set, client will not respond as expected. DB bug? + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_LOCKED); + gauntletGate1GUID = pGo->GetGUID(); + break; + case GO_ZIGGURAT1: + ziggurat1GUID = pGo->GetGUID(); + if (GetData(TYPE_BARONESS) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_ZIGGURAT2: + ziggurat2GUID = pGo->GetGUID(); + if (GetData(TYPE_NERUB) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_ZIGGURAT3: + ziggurat3GUID = pGo->GetGUID(); + if (GetData(TYPE_PALLID) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_ZIGGURAT4: + ziggurat4GUID = pGo->GetGUID(); + if (GetData(TYPE_BARON) == DONE || GetData(TYPE_RAMSTEIN) == DONE) + HandleGameObject(0, true, pGo); + break; + case GO_ZIGGURAT5: + ziggurat5GUID = pGo->GetGUID(); + if (GetData(TYPE_BARON) == DONE || GetData(TYPE_RAMSTEIN) == DONE) + HandleGameObject(0, true, pGo); + break; + case GO_PORT_GAUNTLET: + portGauntletGUID = pGo->GetGUID(); + if (GetData(TYPE_BARONESS) == IN_PROGRESS && GetData(TYPE_NERUB) == IN_PROGRESS && GetData(TYPE_PALLID) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_PORT_SLAUGTHER: + portSlaugtherGUID = pGo->GetGUID(); + if (GetData(TYPE_BARONESS) == IN_PROGRESS && GetData(TYPE_NERUB) == IN_PROGRESS && GetData(TYPE_PALLID) == IN_PROGRESS) + HandleGameObject(0, true, pGo); + break; + case GO_PORT_ELDERS: + portElderGUID = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_BARON_RUN: + switch(data) + { + case IN_PROGRESS: + if (Encounter[0] == IN_PROGRESS || Encounter[0] == FAIL) + break; + Encounter[0] = data; + BaronRun_Timer = 2700000; + debug_log("TSCR: Instance Stratholme: Baron run in progress."); + break; + case FAIL: + //may add code to remove aura from players, but in theory the time should be up already and removed. + Encounter[0] = data; + break; + case DONE: + Encounter[0] = data; + if (Creature* pYsidaT = instance->GetCreature(ysidaTriggerGUID)) + pYsidaT->SummonCreature(C_YSIDA, + pYsidaT->GetPositionX(),pYsidaT->GetPositionY(),pYsidaT->GetPositionZ(),pYsidaT->GetOrientation(), + TEMPSUMMON_TIMED_DESPAWN,1800000); + BaronRun_Timer = 0; + break; + } + break; + case TYPE_BARONESS: + Encounter[1] = data; + if (data == IN_PROGRESS) + HandleGameObject(ziggurat1GUID, true); + if (data == IN_PROGRESS) //change to DONE when crystals implemented + StartSlaugtherSquare(); + break; + case TYPE_NERUB: + Encounter[2] = data; + if (data == IN_PROGRESS) + HandleGameObject(ziggurat2GUID, true); + if (data == IN_PROGRESS) //change to DONE when crystals implemented + StartSlaugtherSquare(); + break; + case TYPE_PALLID: + Encounter[3] = data; + if (data == IN_PROGRESS) + HandleGameObject(ziggurat3GUID, true); + if (data == IN_PROGRESS) //change to DONE when crystals implemented + StartSlaugtherSquare(); + break; + case TYPE_RAMSTEIN: + if (data == IN_PROGRESS) + { + HandleGameObject(portGauntletGUID, false); + + uint32 count = abomnationGUID.size(); + for (std::set::const_iterator i = abomnationGUID.begin(); i != abomnationGUID.end(); ++i) + { + if (Creature* pAbom = instance->GetCreature(*i)) + { + if (!pAbom->isAlive()) + --count; + } + } + + if (!count) + { + //a bit itchy, it should close the door after 10 secs, but it doesn't. skipping it for now. + //UpdateGoState(ziggurat4GUID,0,true); + if (Creature* pBaron = instance->GetCreature(baronGUID)) + pBaron->SummonCreature(C_RAMSTEIN,4032.84,-3390.24,119.73,4.71,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000); + debug_log("TSCR: Instance Stratholme: Ramstein spawned."); + } + else + debug_log("TSCR: Instance Stratholme: %u Abomnation left to kill.",count); + } + + if (data == NOT_STARTED) + HandleGameObject(portGauntletGUID, true); + + if (data == DONE) + { + SlaugtherSquare_Timer = 300000; + debug_log("TSCR: Instance Stratholme: Slaugther event will continue in 5 minutes."); + } + Encounter[4] = data; + break; + case TYPE_BARON: + if (data == IN_PROGRESS) + { + HandleGameObject(ziggurat4GUID, false); + HandleGameObject(ziggurat5GUID, false); + if (GetData(TYPE_BARON_RUN) == IN_PROGRESS) + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if (pPlayer->HasAura(SPELL_BARON_ULTIMATUM)) + pPlayer->RemoveAurasDueToSpell(SPELL_BARON_ULTIMATUM); + + if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_DEAD_MAN_PLEA); + } + } + } + + SetData(TYPE_BARON_RUN,DONE); + } + } + if (data == DONE || data == NOT_STARTED) + { + HandleGameObject(ziggurat4GUID, true); + HandleGameObject(ziggurat5GUID, true); + } + if (data == DONE) + HandleGameObject(portGauntletGUID, true); + Encounter[5] = data; + break; + case TYPE_SH_AELMAR: + IsSilverHandDead[0] = (data) ? true : false; + break; + case TYPE_SH_CATHELA: + IsSilverHandDead[1] = (data) ? true : false; + break; + case TYPE_SH_GREGOR: + IsSilverHandDead[2] = (data) ? true : false; + break; + case TYPE_SH_NEMAS: + IsSilverHandDead[3] = (data) ? true : false; + break; + case TYPE_SH_VICAR: + IsSilverHandDead[4] = (data) ? true : false; + break; + } + if (data == DONE)SaveToDB(); + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << Encounter[0] << " " << Encounter[1] << " " << Encounter[2] << " " + << Encounter[3] << " " << Encounter[4] << " " << Encounter[5]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> Encounter[0] >> Encounter[1] >> Encounter[2] >> Encounter[3] + >> Encounter[4] >> Encounter[5]; + + // Do not reset 1, 2 and 3. they are not set to done, yet . + if (Encounter[0] == IN_PROGRESS) + Encounter[0] = NOT_STARTED; + if (Encounter[4] == IN_PROGRESS) + Encounter[4] = NOT_STARTED; + if (Encounter[5] == IN_PROGRESS) + Encounter[5] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_SH_QUEST: + if (IsSilverHandDead[0] && IsSilverHandDead[1] && IsSilverHandDead[2] && IsSilverHandDead[3] && IsSilverHandDead[4]) + return 1; + return 0; + case TYPE_BARON_RUN: + return Encounter[0]; + case TYPE_BARONESS: + return Encounter[1]; + case TYPE_NERUB: + return Encounter[2]; + case TYPE_PALLID: + return Encounter[3]; + case TYPE_RAMSTEIN: + return Encounter[4]; + case TYPE_BARON: + return Encounter[5]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_BARON: + return baronGUID; + case DATA_YSIDA_TRIGGER: + return ysidaTriggerGUID; + } + return 0; + } + + void Update(uint32 diff) + { + if (BaronRun_Timer) + { + if (BaronRun_Timer <= diff) + { + if (GetData(TYPE_BARON_RUN) != DONE) + SetData(TYPE_BARON_RUN, FAIL); + BaronRun_Timer = 0; + debug_log("TSCR: Instance Stratholme: Baron run event reached end. Event has state %u.",GetData(TYPE_BARON_RUN)); + } else BaronRun_Timer -= diff; + } + + if (SlaugtherSquare_Timer) + { + if (SlaugtherSquare_Timer <= diff) + { + if (Creature* pBaron = instance->GetCreature(baronGUID)) + { + for (uint8 i = 0; i < 4; ++i) + pBaron->SummonCreature(C_BLACK_GUARD,4032.84,-3390.24,119.73,4.71,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000); + + HandleGameObject(ziggurat4GUID, true); + HandleGameObject(ziggurat5GUID, true); + debug_log("TSCR: Instance Stratholme: Black guard sentries spawned. Opening gates to baron."); + } + SlaugtherSquare_Timer = 0; + } else SlaugtherSquare_Timer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_stratholme(Map* pMap) +{ + return new instance_stratholme(pMap); +} + +void AddSC_instance_stratholme() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_stratholme"; + newscript->GetInstanceData = &GetInstanceData_instance_stratholme; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp new file mode 100644 index 00000000000..035fca68b95 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp @@ -0,0 +1,282 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Stratholme +SD%Complete: 100 +SDComment: Misc mobs for instance. pGo-script to apply aura and start event for quest 8945 +SDCategory: Stratholme +EndScriptData */ + +/* ContentData +go_gauntlet_gate +mob_freed_soul +mob_restless_soul +mobs_spectral_ghostly_citizen +EndContentData */ + +#include "ScriptedPch.h" +#include "stratholme.h" + +/*###### +## go_gauntlet_gate (this is the _first_ of the gauntlet gates, two exist) +######*/ + +bool GOHello_go_gauntlet_gate(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + + if (!pInstance) + return false; + + if (pInstance->GetData(TYPE_BARON_RUN) != NOT_STARTED) + return false; + + if (Group *pGroup = pPlayer->GetGroup()) + { + for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* pGroupie = itr->getSource(); + if (!pGroupie) + continue; + + if (pGroupie->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && + !pGroupie->HasAura(SPELL_BARON_ULTIMATUM) && + pGroupie->GetMap() == pGo->GetMap()) + pGroupie->CastSpell(pGroupie,SPELL_BARON_ULTIMATUM,true); + } + } else if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && + !pPlayer->HasAura(SPELL_BARON_ULTIMATUM) && + pPlayer->GetMap() == pGo->GetMap()) + pPlayer->CastSpell(pPlayer,SPELL_BARON_ULTIMATUM,true); + + pInstance->SetData(TYPE_BARON_RUN,IN_PROGRESS); + return false; +} + +/*###### +## mob_freed_soul +######*/ + +//Possibly more of these quotes around. +#define SAY_ZAPPED0 -1329000 +#define SAY_ZAPPED1 -1329001 +#define SAY_ZAPPED2 -1329002 +#define SAY_ZAPPED3 -1329003 + +struct mob_freed_soulAI : public ScriptedAI +{ + mob_freed_soulAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + DoScriptText(RAND(SAY_ZAPPED0,SAY_ZAPPED1,SAY_ZAPPED2,SAY_ZAPPED3), me); + } + + void EnterCombat(Unit* /*who*/) {} +}; + +CreatureAI* GetAI_mob_freed_soul(Creature* pCreature) +{ + return new mob_freed_soulAI (pCreature); +} + +/*###### +## mob_restless_soul +######*/ + +#define SPELL_EGAN_BLASTER 17368 +#define SPELL_SOUL_FREED 17370 +#define QUEST_RESTLESS_SOUL 5282 +#define ENTRY_RESTLESS 11122 +#define ENTRY_FREED 11136 + +struct mob_restless_soulAI : public ScriptedAI +{ + mob_restless_soulAI(Creature *c) : ScriptedAI(c) {} + + uint64 Tagger; + uint32 Die_Timer; + bool Tagged; + + void Reset() + { + Tagger = 0; + Die_Timer = 5000; + Tagged = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + if (!Tagged && spell->Id == SPELL_EGAN_BLASTER && CAST_PLR(caster)->GetQuestStatus(QUEST_RESTLESS_SOUL) == QUEST_STATUS_INCOMPLETE) + { + Tagged = true; + Tagger = caster->GetGUID(); + } + } + } + + void JustSummoned(Creature *summoned) + { + summoned->CastSpell(summoned,SPELL_SOUL_FREED,false); + } + + void JustDied(Unit* /*Killer*/) + { + if (Tagged) + me->SummonCreature(ENTRY_FREED, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 300000); + } + + void UpdateAI(const uint32 diff) + { + if (Tagged) + { + if (Die_Timer <= diff) + { + if (Unit* pTemp = Unit::GetUnit(*me,Tagger)) + { + CAST_PLR(pTemp)->KilledMonsterCredit(ENTRY_RESTLESS, me->GetGUID()); + me->Kill(me); + } + } else Die_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_mob_restless_soul(Creature* pCreature) +{ + return new mob_restless_soulAI (pCreature); +} + +/*###### +## mobs_spectral_ghostly_citizen +######*/ + +enum eGhostlyCitizenSpells +{ + SPELL_HAUNTING_PHANTOM = 16336, + SPELL_SLAP = 6754 +}; + +struct mobs_spectral_ghostly_citizenAI : public ScriptedAI +{ + mobs_spectral_ghostly_citizenAI(Creature *c) : ScriptedAI(c) {} + + uint32 Die_Timer; + bool Tagged; + + void Reset() + { + Die_Timer = 5000; + Tagged = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (!Tagged && spell->Id == SPELL_EGAN_BLASTER) + Tagged = true; + } + + void JustDied(Unit* /*Killer*/) + { + if (Tagged) + { + for (uint32 i = 1; i <= 4; ++i) + { + //100%, 50%, 33%, 25% chance to spawn + if (urand(1,i) == 1) + DoSummon(ENTRY_RESTLESS, me, 20.0f, 600000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Tagged) + { + if (Die_Timer <= diff) + me->Kill(me); + else Die_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + switch(emote) + { + case TEXTEMOTE_DANCE: + EnterEvadeMode(); + break; + case TEXTEMOTE_RUDE: + if (me->IsWithinDistInMap(pPlayer, 5)) + DoCast(pPlayer, SPELL_SLAP, false); + else + me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE); + break; + case TEXTEMOTE_WAVE: + me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); + break; + case TEXTEMOTE_BOW: + me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); + break; + case TEXTEMOTE_KISS: + me->HandleEmoteCommand(EMOTE_ONESHOT_FLEX); + break; + } + } +}; + +CreatureAI* GetAI_mobs_spectral_ghostly_citizen(Creature* pCreature) +{ + return new mobs_spectral_ghostly_citizenAI (pCreature); +} + +void AddSC_stratholme() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_gauntlet_gate"; + newscript->pGOHello = &GOHello_go_gauntlet_gate; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_freed_soul"; + newscript->GetAI = &GetAI_mob_freed_soul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_restless_soul"; + newscript->GetAI = &GetAI_mob_restless_soul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mobs_spectral_ghostly_citizen"; + newscript->GetAI = &GetAI_mobs_spectral_ghostly_citizen; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.h b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.h new file mode 100644 index 00000000000..b9246091a7c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_STRATHOLME_H +#define DEF_STRATHOLME_H + +#define TYPE_BARON_RUN 1 +#define TYPE_BARONESS 2 +#define TYPE_NERUB 3 +#define TYPE_PALLID 4 +#define TYPE_RAMSTEIN 5 +#define TYPE_BARON 6 + +#define DATA_BARON 10 +#define DATA_YSIDA_TRIGGER 11 + +#define TYPE_SH_QUEST 20 +#define TYPE_SH_CATHELA 21 +#define TYPE_SH_GREGOR 22 +#define TYPE_SH_NEMAS 23 +#define TYPE_SH_VICAR 24 +#define TYPE_SH_AELMAR 25 + +#define QUEST_DEAD_MAN_PLEA 8945 +#define SPELL_BARON_ULTIMATUM 27861 +#endif + diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp new file mode 100644 index 00000000000..6fe65cf963d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp @@ -0,0 +1,204 @@ +/* Copyright (C) 2006 - 2009 kb_z + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Sunken_Temple +SD%Complete: 100 +SDComment:Place Holder +SDCategory: Sunken Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunken_temple.h" + +#define GO_ATALAI_STATUE1 148830 +#define GO_ATALAI_STATUE2 148831 +#define GO_ATALAI_STATUE3 148832 +#define GO_ATALAI_STATUE4 148833 +#define GO_ATALAI_STATUE5 148834 +#define GO_ATALAI_STATUE6 148835 +#define GO_ATALAI_IDOL 148836 + +#define GO_ATALAI_LIGHT1 148883 +#define GO_ATALAI_LIGHT2 148937 + +#define NPC_MALFURION_STORMRAGE 15362 + +struct instance_sunken_temple : public ScriptedInstance +{ + instance_sunken_temple(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + }; + + uint64 GOAtalaiStatue1; + uint64 GOAtalaiStatue2; + uint64 GOAtalaiStatue3; + uint64 GOAtalaiStatue4; + uint64 GOAtalaiStatue5; + uint64 GOAtalaiStatue6; + uint64 GOAtalaiIdol; + + uint32 State; + + bool s1; + bool s2; + bool s3; + bool s4; + bool s5; + bool s6; + + void Initialize() + { + GOAtalaiStatue1 = 0; + GOAtalaiStatue2 = 0; + GOAtalaiStatue3 = 0; + GOAtalaiStatue4 = 0; + GOAtalaiStatue5 = 0; + GOAtalaiStatue6 = 0; + GOAtalaiIdol = 0; + + State = 0; + + s1 = false; + s2 = false; + s3 = false; + s4 = false; + s5 = false; + s6 = false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_ATALAI_STATUE1: GOAtalaiStatue1 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE2: GOAtalaiStatue2 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE3: GOAtalaiStatue3 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE4: GOAtalaiStatue4 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE5: GOAtalaiStatue5 = pGo->GetGUID(); break; + case GO_ATALAI_STATUE6: GOAtalaiStatue6 = pGo->GetGUID(); break; + case GO_ATALAI_IDOL: GOAtalaiIdol = pGo->GetGUID(); break; + } + } + + virtual void Update(uint32 /*diff*/) // correct order goes form 1-6 + { + switch(State) + { + case GO_ATALAI_STATUE1: + if (!s1 && !s2 && !s3 && !s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue1 = instance->GetGameObject(GOAtalaiStatue1)) + UseStatue(pAtalaiStatue1); + s1 = true; + State = 0; + }; + break; + case GO_ATALAI_STATUE2: + if (s1 && !s2 && !s3 && !s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue2 = instance->GetGameObject(GOAtalaiStatue2)) + UseStatue(pAtalaiStatue2); + s2 = true; + State = 0; + }; + break; + case GO_ATALAI_STATUE3: + if (s1 && s2 && !s3 && !s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue3 = instance->GetGameObject(GOAtalaiStatue3)) + UseStatue(pAtalaiStatue3); + s3 = true; + State = 0; + }; + break; + case GO_ATALAI_STATUE4: + if (s1 && s2 && s3 && !s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue4 = instance->GetGameObject(GOAtalaiStatue4)) + UseStatue(pAtalaiStatue4); + s4 = true; + State = 0; + } + break; + case GO_ATALAI_STATUE5: + if (s1 && s2 && s3 && s4 && !s5 && !s6) + { + if (GameObject *pAtalaiStatue5 = instance->GetGameObject(GOAtalaiStatue5)) + UseStatue(pAtalaiStatue5); + s5 = true; + State = 0; + } + break; + case GO_ATALAI_STATUE6: + if (s1 && s2 && s3 && s4 && s5 && !s6) + { + if (GameObject *pAtalaiStatue6 = instance->GetGameObject(GOAtalaiStatue6)) + UseStatue(pAtalaiStatue6); + s6 = true; + State = 0; + } + break; + } + }; + + void UseStatue(GameObject* pGo) + { + pGo->SummonGameObject(GO_ATALAI_LIGHT1,pGo->GetPositionX(),pGo->GetPositionY(),pGo->GetPositionZ(),0,0,0,0,0,0); + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 4); + } + + /* + void UseLastStatue(GameObject* pGo) + { + AtalaiStatue1->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue1->GetPositionX(),AtalaiStatue1->GetPositionY(),AtalaiStatue1->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue2->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue2->GetPositionX(),AtalaiStatue2->GetPositionY(),AtalaiStatue2->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue3->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue3->GetPositionX(),AtalaiStatue3->GetPositionY(),AtalaiStatue3->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue4->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue4->GetPositionX(),AtalaiStatue4->GetPositionY(),AtalaiStatue4->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue5->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue5->GetPositionX(),AtalaiStatue5->GetPositionY(),AtalaiStatue5->GetPositionZ(),0,0,0,0,0,100000); + AtalaiStatue6->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue6->GetPositionX(),AtalaiStatue6->GetPositionY(),AtalaiStatue6->GetPositionZ(),0,0,0,0,0,100000); + pGo->SummonGameObject(148838,-488.997,96.61,-189.019,-1.52,0,0,0,0,100000); + } + */ + + void SetData(uint32 type, uint32 data) + { + if (type == EVENT_STATE) + State = data; + } + + uint32 GetData(uint32 type) + { + if (type == EVENT_STATE) + return State; + return 0; + } +}; + +InstanceData* GetInstanceData_instance_sunken_temple(Map* pMap) +{ + return new instance_sunken_temple(pMap); +} + +void AddSC_instance_sunken_temple() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_sunken_temple"; + newscript->GetInstanceData = &GetInstanceData_instance_sunken_temple; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp new file mode 100644 index 00000000000..7f0ca126d78 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp @@ -0,0 +1,71 @@ +/* Copyright (C) 2006 - 2009 kb_z + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Sunken_Temple +SD%Complete: 100 +SDComment: Area Trigger + Puzzle event support +SDCategory: Sunken Temple +EndScriptData */ + +/* ContentData +at_malfurion_Stormrage_trigger +EndContentData */ + +#include "ScriptedPch.h" +#include "sunken_temple.h" + +/*##### +# at_malfurion_Stormrage_trigger +#####*/ + +bool AreaTrigger_at_malfurion_stormrage(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + if (ScriptedInstance* pInstance = pPlayer->GetInstanceData()) + { + if (!pPlayer->FindNearestCreature(15362,15)) + pPlayer->SummonCreature(15362, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), -1.52, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 100000); + return false; + } +return false; +} +/*##### +# go_atalai_statue +#####*/ + +bool GOHello_go_atalai_statue(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (!pInstance) + return false; + pInstance->SetData(EVENT_STATE,pGo->GetEntry()); + return false; +} + +void AddSC_sunken_temple() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "at_malfurion_stormrage"; + newscript->pAreaTrigger = &AreaTrigger_at_malfurion_stormrage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_atalai_statue"; + newscript->pGOHello = &GOHello_go_atalai_statue; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h new file mode 100644 index 00000000000..82245095c31 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2006 - 2009 kb_z + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SUNKEN_TEMPLE_H +#define DEF_SUNKEN_TEMPLE_H + +#define TROLLBOSS1_DEATH 1 +#define TROLLBOSS2_DEATH 2 +#define TROLLBOSS3_DEATH 3 +#define TROLLBOSS4_DEATH 4 +#define TROLLBOSS5_DEATH 5 +#define TROLLBOSS6_DEATH 6 +#define JAMMALAN_DEATH 7 +#define MORPHAZ_DEATH 8 +#define HAZZAS_DEATH 9 +#define ERANIKUS_DEATH 10 +#define ATALALARION_DEATH 11 //optional + +#define EVENT_STATE 1 +#endif + diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp new file mode 100644 index 00000000000..59e58d6df1a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp @@ -0,0 +1,349 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Brutallus +SD%Complete: 80 +SDComment: Find a way to start the intro, best code for the intro +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +enum Quotes +{ + YELL_INTRO = -1580017, + YELL_INTRO_BREAK_ICE = -1580018, + YELL_INTRO_CHARGE = -1580019, + YELL_INTRO_KILL_MADRIGOSA = -1580020, + YELL_INTRO_TAUNT = -1580021, + + YELL_MADR_ICE_BARRIER = -1580031, + YELL_MADR_INTRO = -1580032, + YELL_MADR_ICE_BLOCK = -1580033, + YELL_MADR_TRAP = -1580034, + YELL_MADR_DEATH = -1580035, + + YELL_AGGRO = -1580022, + YELL_KILL1 = -1580023, + YELL_KILL2 = -1580024, + YELL_KILL3 = -1580025, + YELL_LOVE1 = -1580026, + YELL_LOVE2 = -1580027, + YELL_LOVE3 = -1580028, + YELL_BERSERK = -1580029, + YELL_DEATH = -1580030 +}; + +enum Spells +{ + SPELL_METEOR_SLASH = 45150, + SPELL_BURN = 46394, + SPELL_STOMP = 45185, + SPELL_BERSERK = 26662, + SPELL_DUAL_WIELD = 42459, + + SPELL_INTRO_FROST_BLAST = 45203, + SPELL_INTRO_FROSTBOLT = 44843, + SPELL_INTRO_ENCAPSULATE = 45665, + SPELL_INTRO_ENCAPSULATE_CHANELLING = 45661 +}; + +#define FELMYST 25038 + +struct boss_brutallusAI : public ScriptedAI +{ + boss_brutallusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = true; + } + + ScriptedInstance* pInstance; + + uint32 SlashTimer; + uint32 BurnTimer; + uint32 StompTimer; + uint32 BerserkTimer; + + uint32 IntroPhase; + uint32 IntroPhaseTimer; + uint32 IntroFrostBoltTimer; + + bool Intro; + bool IsIntro; + bool Enraged; + + void Reset() + { + SlashTimer = 11000; + StompTimer = 30000; + BurnTimer = 60000; + BerserkTimer = 360000; + + IntroPhase = 0; + IntroPhaseTimer = 0; + IntroFrostBoltTimer = 0; + + IsIntro = false; + Enraged = false; + + DoCast(me, SPELL_DUAL_WIELD, true); + + if (pInstance) + pInstance->SetData(DATA_BRUTALLUS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_BRUTALLUS_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(YELL_KILL1,YELL_KILL2,YELL_KILL3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(YELL_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_BRUTALLUS_EVENT, DONE); + float x,y,z; + me->GetPosition(x,y,z); + me->SummonCreature(FELMYST, x,y, z+30, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0); + } + } + + void EnterEvadeMode() + { + if (!Intro) + ScriptedAI::EnterEvadeMode(); + } + + void StartIntro() + { + if (!Intro || IsIntro) + return; + error_log("Start Intro"); + Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0); + if (Madrigosa) + { + Madrigosa->Respawn(); + Madrigosa->setActive(true); + IsIntro = true; + Madrigosa->SetMaxHealth(me->GetMaxHealth()); + Madrigosa->SetHealth(me->GetMaxHealth()); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->Attack(Madrigosa, true); + Madrigosa->Attack(me, true); + }else + { + //Madrigosa not found, end intro + error_log("Madrigosa was not found"); + EndIntro(); + } + } + + void EndIntro() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Intro = false; + IsIntro = false; + error_log("End Intro"); + } + + void AttackStart(Unit* pWho) + { + if (!pWho || Intro || IsIntro) + return; + ScriptedAI::AttackStart(pWho); + } + + void DoIntro() + { + Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0); + if (!Madrigosa) + return; + + switch (IntroPhase) + { + case 0: + DoScriptText(YELL_MADR_ICE_BARRIER, Madrigosa); + IntroPhaseTimer = 7000; + ++IntroPhase; + break; + case 1: + me->SetInFront(Madrigosa); + Madrigosa->SetInFront(me); + DoScriptText(YELL_MADR_INTRO, Madrigosa, me); + IntroPhaseTimer = 9000; + ++IntroPhase; + break; + case 2: + DoScriptText(YELL_INTRO, me, Madrigosa); + IntroPhaseTimer = 13000; + ++IntroPhase; + break; + case 3: + DoCast(me, SPELL_INTRO_FROST_BLAST); + Madrigosa->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->AttackStop(); + Madrigosa->AttackStop(); + IntroFrostBoltTimer = 3000; + IntroPhaseTimer = 28000; + ++IntroPhase; + break; + case 4: + DoScriptText(YELL_INTRO_BREAK_ICE, me); + IntroPhaseTimer = 6000; + ++IntroPhase; + break; + case 5: + Madrigosa->CastSpell(me, SPELL_INTRO_ENCAPSULATE_CHANELLING, false); + DoScriptText(YELL_MADR_TRAP, Madrigosa); + DoCast(me, SPELL_INTRO_ENCAPSULATE); + IntroPhaseTimer = 11000; + ++IntroPhase; + break; + case 6: + DoScriptText(YELL_INTRO_CHARGE, me); + IntroPhaseTimer = 5000; + ++IntroPhase; + break; + case 7: + me->Kill(Madrigosa); + DoScriptText(YELL_MADR_DEATH, Madrigosa); + me->SetHealth(me->GetMaxHealth()); + me->AttackStop(); + IntroPhaseTimer = 4000; + ++IntroPhase; + break; + case 8: + DoScriptText(YELL_INTRO_KILL_MADRIGOSA, me); + me->SetOrientation(0.14f); + me->StopMoving(); + Madrigosa->setDeathState(CORPSE); + IntroPhaseTimer = 8000; + ++IntroPhase; + break; + case 9: + DoScriptText(YELL_INTRO_TAUNT, me); + IntroPhaseTimer = 5000; + ++IntroPhase; + break; + case 10: + EndIntro(); + break; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who->isTargetableForAttack() || !me->IsHostileTo(who)) + return; + if (pInstance && Intro) + pInstance->SetData(DATA_BRUTALLUS_EVENT, SPECIAL); + + if (Intro && !IsIntro) + StartIntro(); + if (!Intro) + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + if (IsIntro) + { + if (IntroPhaseTimer <= diff) + DoIntro(); + else IntroPhaseTimer -= diff; + + if (IntroPhase == 3 + 1) + { + if (IntroFrostBoltTimer <= diff) + { + if (Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0)) + { + Madrigosa->CastSpell(me, SPELL_INTRO_FROSTBOLT, true); + IntroFrostBoltTimer = 2000; + } + } else IntroFrostBoltTimer -= diff; + } + if (!UpdateVictim()) + return; + DoMeleeAttackIfReady(); + } + + if (!UpdateVictim() || IsIntro) + return; + + if (SlashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_METEOR_SLASH); + SlashTimer = 11000; + } else SlashTimer -= diff; + + if (StompTimer <= diff) + { + DoScriptText(RAND(YELL_LOVE1,YELL_LOVE2,YELL_LOVE3), me); + DoCast(me->getVictim(), SPELL_STOMP); + StompTimer = 30000; + } else StompTimer -= diff; + + if (BurnTimer <= diff) + { + std::list pTargets; + SelectTargetList(pTargets, 10, SELECT_TARGET_RANDOM, 100, true); + for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) + if (!(*i)->HasAura(SPELL_BURN)) + { + (*i)->CastSpell((*i), SPELL_BURN, true); + break; + } + BurnTimer = urand(60000,180000); + } else BurnTimer -= diff; + + if (BerserkTimer < diff && !Enraged) + { + DoScriptText(YELL_BERSERK, me); + DoCast(me, SPELL_BERSERK); + Enraged = true; + } else BerserkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_brutallus(Creature* pCreature) +{ + return new boss_brutallusAI (pCreature); +} + +void AddSC_boss_brutallus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_brutallus"; + newscript->GetAI = &GetAI_boss_brutallus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp new file mode 100644 index 00000000000..602f12065fa --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp @@ -0,0 +1,762 @@ +/* Copyright (C) 2009 Trinity +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Eredar_Twins +SD%Complete: 100 +SDComment: +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +enum Quotes +{ + //Alytesh + YELL_CANFLAGRATION = -1580044, + YELL_SISTER_SACROLASH_DEAD = -1580045, + YELL_ALY_KILL_1 = -1580046, + YELL_ALY_KILL_2 = -1580047, + YELL_ALY_DEAD = -1580048, + YELL_BERSERK = -1580049, + + //Sacrolash + YELL_SHADOW_NOVA = -1580050, + YELL_SISTER_ALYTHESS_DEAD = -1580051, + YELL_SAC_KILL_1 = -1580052, + YELL_SAC_KILL_2 = -1580053, + SAY_SAC_DEAD = -1580054, + YELL_ENRAGE = -1580055, + + //Intro + YELL_INTRO_SAC_1 = -1580056, + YELL_INTRO_ALY_2 = -1580057, + YELL_INTRO_SAC_3 = -1580058, + YELL_INTRO_ALY_4 = -1580059, + YELL_INTRO_SAC_5 = -1580060, + YELL_INTRO_ALY_6 = -1580061, + YELL_INTRO_SAC_7 = -1580062, + YELL_INTRO_ALY_8 = -1580063, + + //Emote + EMOTE_SHADOW_NOVA = -1580064, + EMOTE_CONFLAGRATION = -1580065 +}; + +enum Spells +{ + //Lady Sacrolash spells + SPELL_DARK_TOUCHED = 45347, + SPELL_SHADOW_BLADES = 45248, //10 secs + SPELL_DARK_STRIKE = 45271, + SPELL_SHADOW_NOVA = 45329, //30-35 secs + SPELL_CONFOUNDING_BLOW = 45256, //25 secs + + //Shadow Image spells + SPELL_SHADOW_FURY = 45270, + SPELL_IMAGE_VISUAL = 45263, + + //Misc spells + SPELL_ENRAGE = 46587, + SPELL_EMPOWER = 45366, + SPELL_DARK_FLAME = 45345, + + //Grand Warlock Alythess spells + SPELL_PYROGENICS = 45230, //15secs + SPELL_FLAME_TOUCHED = 45348, + SPELL_CONFLAGRATION = 45342, //30-35 secs + SPELL_BLAZE = 45235, //on main target every 3 secs + SPELL_FLAME_SEAR = 46771, + SPELL_BLAZE_SUMMON = 45236, //187366 GO + SPELL_BLAZE_BURN = 45246 +}; + +struct boss_sacrolashAI : public ScriptedAI +{ + boss_sacrolashAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + bool SisterDeath; + bool Enraged; + + uint32 ShadowbladesTimer; + uint32 ShadownovaTimer; + uint32 ConfoundingblowTimer; + uint32 ShadowimageTimer; + uint32 ConflagrationTimer; + uint32 EnrageTimer; + + void Reset() + { + Enraged = false; + + if (pInstance) + { + Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); + if (Temp) + if (Temp->isDead()) + { + CAST_CRE(Temp)->Respawn(); + }else + { + if (Temp->getVictim()) + { + me->getThreatManager().addThreat(Temp->getVictim(),0.0f); + } + } + } + + if (!me->isInCombat()) + { + ShadowbladesTimer = 10000; + ShadownovaTimer = 30000; + ConfoundingblowTimer = 25000; + ShadowimageTimer = 20000; + ConflagrationTimer = 30000; + EnrageTimer = 360000; + + SisterDeath = false; + } + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * who) + { + DoZoneInCombat(); + + if (pInstance) + { + Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); + if (Temp && Temp->isAlive() && !(Temp->getVictim())) + CAST_CRE(Temp)->AI()->AttackStart(who); + } + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + if (rand()%4 == 0) + DoScriptText(RAND(YELL_SAC_KILL_1,YELL_SAC_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + // only if ALY death + if (SisterDeath) + { + DoScriptText(SAY_SAC_DEAD, me); + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, DONE); + } + else + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) + { + switch(spell->Id) + { + case SPELL_SHADOW_BLADES: + case SPELL_SHADOW_NOVA: + case SPELL_CONFOUNDING_BLOW: + case SPELL_SHADOW_FURY: + HandleTouchedSpells(pTarget, SPELL_DARK_TOUCHED); + break; + case SPELL_CONFLAGRATION: + HandleTouchedSpells(pTarget, SPELL_FLAME_TOUCHED); + break; + } + } + + void HandleTouchedSpells(Unit *pTarget, uint32 TouchedType) + { + switch(TouchedType) + { + case SPELL_FLAME_TOUCHED: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_DARK_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_DARK_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + } else pTarget->CastSpell(pTarget, SPELL_FLAME_TOUCHED, true); + } + break; + case SPELL_DARK_TOUCHED: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + } else pTarget->CastSpell(pTarget, SPELL_DARK_TOUCHED, true); + } + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!SisterDeath) + { + if (pInstance) + { + Unit* Temp = NULL; + Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); + if (Temp && Temp->isDead()) + { + DoScriptText(YELL_SISTER_ALYTHESS_DEAD, me); + DoCast(me, SPELL_EMPOWER); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + SisterDeath = true; + } + } + } + + if (!UpdateVictim()) + return; + + if (SisterDeath) + { + if (ConflagrationTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_CONFLAGRATION); + ConflagrationTimer = 30000+(rand()%5000); + } + } else ConflagrationTimer -= diff; + } + else + { + if (ShadownovaTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_SHADOW_NOVA); + + if (!SisterDeath) + { + if (pTarget) + DoScriptText(EMOTE_SHADOW_NOVA, me, pTarget); + DoScriptText(YELL_SHADOW_NOVA, me); + } + ShadownovaTimer = 30000+(rand()%5000); + } + } else ShadownovaTimer -=diff; + } + + if (ConfoundingblowTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_CONFOUNDING_BLOW); + ConfoundingblowTimer = 20000 + (rand()%5000); + } + } else ConfoundingblowTimer -=diff; + + if (ShadowimageTimer <= diff) + { + Unit *pTarget = NULL; + Creature* temp = NULL; + for (uint8 i = 0; i<3; ++i) + { + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + temp = DoSpawnCreature(MOB_SHADOW_IMAGE,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN,10000); + if (temp && pTarget) + { + temp->AddThreat(pTarget,1000000);//don't change target(healers) + temp->AI()->AttackStart(pTarget); + } + } + ShadowimageTimer = 20000; + } else ShadowimageTimer -=diff; + + if (ShadowbladesTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_SHADOW_BLADES); + ShadowbladesTimer = 10000; + } + } else ShadowbladesTimer -=diff; + + if (EnrageTimer < diff && !Enraged) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + DoScriptText(YELL_ENRAGE, me); + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else EnrageTimer -= diff; + + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + HandleTouchedSpells(me->getVictim(), SPELL_DARK_TOUCHED); + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + } +}; + +CreatureAI* GetAI_boss_sacrolash(Creature* pCreature) +{ + return new boss_sacrolashAI (pCreature); +}; + +struct boss_alythessAI : public Scripted_NoMovementAI +{ + boss_alythessAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); + IntroStepCounter = 10; + } + + ScriptedInstance *pInstance; + + bool SisterDeath; + bool Enraged; + + uint32 IntroStepCounter; + uint32 IntroYellTimer; + + uint32 ConflagrationTimer; + uint32 BlazeTimer; + uint32 PyrogenicsTimer; + uint32 ShadownovaTimer; + uint32 FlamesearTimer; + uint32 EnrageTimer; + + void Reset() + { + Enraged = false; + + if (pInstance) + { + Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); + if (Temp) + if (Temp->isDead()) + { + CAST_CRE(Temp)->Respawn(); + }else + { + if (Temp->getVictim()) + { + me->getThreatManager().addThreat(Temp->getVictim(),0.0f); + } + } + } + + if (!me->isInCombat()) + { + ConflagrationTimer = 45000; + BlazeTimer = 100; + PyrogenicsTimer = 15000; + ShadownovaTimer = 40000; + EnrageTimer = 360000; + FlamesearTimer = 15000; + IntroYellTimer = 10000; + + SisterDeath = false; + } + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * who) + { + DoZoneInCombat(); + + if (pInstance) + { + Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); + if (Temp && Temp->isAlive() && !(Temp->getVictim())) + CAST_CRE(Temp)->AI()->AttackStart(who); + } + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit *who) + { + if (!me->isInCombat()) + { + Scripted_NoMovementAI::AttackStart(who); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) + { + if (!me->isInCombat()) + { + DoStartNoMovement(who); + } + } + } + else if (IntroStepCounter == 10 && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 30)) + { + IntroStepCounter = 0; + } + } + + void KilledUnit(Unit * /*victim*/) + { + if (rand()%4 == 0) + { + DoScriptText(RAND(YELL_ALY_KILL_1,YELL_ALY_KILL_2), me); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (SisterDeath) + { + DoScriptText(YELL_ALY_DEAD, me); + + if (pInstance) + pInstance->SetData(DATA_EREDAR_TWINS_EVENT, DONE); + } + else + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) + { + switch(spell->Id) + { + + case SPELL_BLAZE: + pTarget->CastSpell(pTarget, SPELL_BLAZE_SUMMON, true); + case SPELL_CONFLAGRATION: + case SPELL_FLAME_SEAR: + HandleTouchedSpells(pTarget, SPELL_FLAME_TOUCHED); + break; + case SPELL_SHADOW_NOVA: + HandleTouchedSpells(pTarget, SPELL_DARK_TOUCHED); + break; + } + } + + void HandleTouchedSpells(Unit *pTarget, uint32 TouchedType) + { + switch(TouchedType) + { + case SPELL_FLAME_TOUCHED: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_DARK_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_DARK_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + }else + { + pTarget->CastSpell(pTarget, SPELL_FLAME_TOUCHED, true); + } + } + break; + case SPELL_DARK_TOUCHED: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + } else pTarget->CastSpell(pTarget, SPELL_DARK_TOUCHED, true); + } + break; + } + } + + uint32 IntroStep(uint32 step) + { + Creature* Sacrolash = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_SACROLASH) : 0); + switch (step) + { + case 0: return 0; + case 1: + if (Sacrolash) + DoScriptText(YELL_INTRO_SAC_1, Sacrolash); + return 1000; + case 2: DoScriptText(YELL_INTRO_ALY_2, me); return 1000; + case 3: + if (Sacrolash) + DoScriptText(YELL_INTRO_SAC_3, Sacrolash); + return 2000; + case 4: DoScriptText(YELL_INTRO_ALY_4, me); return 1000; + case 5: + if (Sacrolash) + DoScriptText(YELL_INTRO_SAC_5, Sacrolash); + return 2000; + case 6: DoScriptText(YELL_INTRO_ALY_6, me); return 1000; + case 7: + if (Sacrolash) + DoScriptText(YELL_INTRO_SAC_7, Sacrolash); + return 3000; + case 8: DoScriptText(YELL_INTRO_ALY_8, me); return 900000; + } + return 10000; + } + + void UpdateAI(const uint32 diff) + { + if (IntroStepCounter < 9) + { + if (IntroYellTimer <= diff) + { + IntroYellTimer = IntroStep(++IntroStepCounter); + } else IntroYellTimer -= diff; + } + + if (!SisterDeath) + { + if (pInstance) + { + Unit* Temp = NULL; + Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); + if (Temp && Temp->isDead()) + { + DoScriptText(YELL_SISTER_SACROLASH_DEAD, me); + DoCast(me, SPELL_EMPOWER); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + SisterDeath = true; + } + } + } + if (!me->getVictim()) + { + if (pInstance) + { + Creature* sisiter = Unit::GetCreature((*me),pInstance->GetData64(DATA_SACROLASH)); + if (sisiter && !sisiter->isDead() && sisiter->getVictim()) + { + me->AddThreat(sisiter->getVictim(),0.0f); + DoStartNoMovement(sisiter->getVictim()); + me->Attack(sisiter->getVictim(),false); + } + } + } + + if (!UpdateVictim()) + return; + + if (SisterDeath) + { + if (ShadownovaTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_SHADOW_NOVA); + ShadownovaTimer= 30000+(rand()%5000); + } + } else ShadownovaTimer -=diff; + } + else + { + if (ConflagrationTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_CONFLAGRATION); + ConflagrationTimer = 30000+(rand()%5000); + + if (!SisterDeath) + { + if (pTarget) + DoScriptText(EMOTE_CONFLAGRATION, me, pTarget); + DoScriptText(YELL_CANFLAGRATION, me); + } + + BlazeTimer = 4000; + } + } else ConflagrationTimer -= diff; + } + + if (FlamesearTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_FLAME_SEAR); + FlamesearTimer = 15000; + } + } else FlamesearTimer -=diff; + + if (PyrogenicsTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_PYROGENICS, true); + PyrogenicsTimer = 15000; + } + } else PyrogenicsTimer -= diff; + + if (BlazeTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me->getVictim(), SPELL_BLAZE); + BlazeTimer = 3800; + } + } else BlazeTimer -= diff; + + if (EnrageTimer < diff && !Enraged) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + DoScriptText(YELL_BERSERK, me); + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else EnrageTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_alythess(Creature* pCreature) +{ + return new boss_alythessAI (pCreature); +}; + +struct mob_shadow_imageAI : public ScriptedAI +{ + mob_shadow_imageAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowfuryTimer; + uint32 KillTimer; + uint32 DarkstrikeTimer; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + ShadowfuryTimer = 5000 + (rand()%15000); + DarkstrikeTimer = 3000; + KillTimer = 15000; + } + + void EnterCombat(Unit * /*who*/){} + + void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) + { + switch(spell->Id) + { + + case SPELL_SHADOW_FURY: + case SPELL_DARK_STRIKE: + if (!pTarget->HasAura(SPELL_DARK_FLAME)) + { + if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) + { + pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); + pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); + } else pTarget->CastSpell(pTarget,SPELL_DARK_TOUCHED,true); + } + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->HasAura(SPELL_IMAGE_VISUAL)) + DoCast(me, SPELL_IMAGE_VISUAL); + + if (KillTimer <= diff) + { + me->Kill(me); + KillTimer = 9999999; + } else KillTimer -= diff; + + if (!UpdateVictim()) + return; + + if (ShadowfuryTimer <= diff) + { + DoCast(me, SPELL_SHADOW_FURY); + ShadowfuryTimer = 10000; + } else ShadowfuryTimer -=diff; + + if (DarkstrikeTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + DoCast(me->getVictim(), SPELL_DARK_STRIKE); + } + DarkstrikeTimer = 3000; + } else DarkstrikeTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_shadow_image(Creature* pCreature) +{ + return new mob_shadow_imageAI (pCreature); +}; + +void AddSC_boss_eredar_twins() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sacrolash"; + newscript->GetAI = &GetAI_boss_sacrolash; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_alythess"; + newscript->GetAI = &GetAI_boss_alythess; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadow_image"; + newscript->GetAI = &GetAI_mob_shadow_image; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp new file mode 100644 index 00000000000..88ad2dbab11 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp @@ -0,0 +1,579 @@ +/* Copyright (C) 2009 Trinity +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Felmyst +SD%Complete: 0 +SDComment: +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +enum Yells +{ + YELL_BIRTH = -1580036, + YELL_KILL1 = -1580037, + YELL_KILL2 = -1580038, + YELL_BREATH = -1580039, + YELL_TAKEOFF = -1580040, + YELL_BERSERK = -1580041, + YELL_DEATH = -1580042, + YELL_KALECGOS = -1580043, // after felmyst's death spawned and say this +}; + +enum Spells +{ + //Aura + AURA_SUNWELL_RADIANCE = 45769, + AURA_NOXIOUS_FUMES = 47002, + + //Land phase + SPELL_CLEAVE = 19983, + SPELL_CORROSION = 45866, + SPELL_GAS_NOVA = 45855, + SPELL_ENCAPSULATE_CHANNEL = 45661, + // SPELL_ENCAPSULATE_EFFECT = 45665, + // SPELL_ENCAPSULATE_AOE = 45662, + + //Flight phase + SPELL_VAPOR_SELECT = 45391, // fel to player, force cast 45392, 50000y selete target + SPELL_VAPOR_SUMMON = 45392, // player summon vapor, radius around caster, 5y, + SPELL_VAPOR_FORCE = 45388, // vapor to fel, force cast 45389 + SPELL_VAPOR_CHANNEL = 45389, // fel to vapor, green beam channel + SPELL_VAPOR_TRIGGER = 45411, // linked to 45389, vapor to self, trigger 45410 and 46931 + SPELL_VAPOR_DAMAGE = 46931, // vapor damage, 4000 + SPELL_TRAIL_SUMMON = 45410, // vapor summon trail + SPELL_TRAIL_TRIGGER = 45399, // trail to self, trigger 45402 + SPELL_TRAIL_DAMAGE = 45402, // trail damage, 2000 + 2000 dot + SPELL_DEAD_SUMMON = 45400, // summon blazing dead, 5min + SPELL_DEAD_PASSIVE = 45415, + SPELL_FOG_BREATH = 45495, // fel to self, speed burst + SPELL_FOG_TRIGGER = 45582, // fog to self, trigger 45782 + SPELL_FOG_FORCE = 45782, // fog to player, force cast 45714 + SPELL_FOG_INFORM = 45714, // player let fel cast 45717, script effect + SPELL_FOG_CHARM = 45717, // fel to player + SPELL_FOG_CHARM2 = 45726, // link to 45717 + + SPELL_TRANSFORM_TRIGGER = 44885, // madrigosa to self, trigger 46350 + SPELL_TRANSFORM_VISUAL = 46350, // 46411stun? + SPELL_TRANSFORM_FELMYST = 45068, // become fel + SPELL_FELMYST_SUMMON = 45069, + + //Other + SPELL_BERSERK = 45078, + SPELL_CLOUD_VISUAL = 45212, + SPELL_CLOUD_SUMMON = 45884, +}; + +enum PhaseFelmyst +{ + PHASE_NONE, + PHASE_GROUND, + PHASE_FLIGHT, +}; + +enum EventFelmyst +{ + EVENT_NONE, + EVENT_BERSERK, + + EVENT_CLEAVE, + EVENT_CORROSION, + EVENT_GAS_NOVA, + EVENT_ENCAPSULATE, + EVENT_FLIGHT, + + EVENT_FLIGHT_SEQUENCE, + EVENT_SUMMON_DEAD, + EVENT_SUMMON_FOG, +}; + +struct boss_felmystAI : public ScriptedAI +{ + boss_felmystAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + + // wait for core patch be accepted + /*SpellEntry *TempSpell = GET_SPELL(SPELL_ENCAPSULATE_EFFECT); + if (TempSpell->SpellIconID == 2294) + TempSpell->SpellIconID = 2295; + TempSpell = GET_SPELL(SPELL_VAPOR_TRIGGER); + if ((TempSpell->Attributes & SPELL_ATTR_PASSIVE) == 0) + TempSpell->Attributes |= SPELL_ATTR_PASSIVE; + TempSpell = GET_SPELL(SPELL_FOG_CHARM2); + if ((TempSpell->Attributes & SPELL_ATTR_PASSIVE) == 0) + TempSpell->Attributes |= SPELL_ATTR_PASSIVE;*/ + } + + ScriptedInstance *pInstance; + PhaseFelmyst phase; + EventMap events; + + uint32 uiFlightCount; + uint32 uiBreathCount; + + float breathX, breathY; + + void Reset() + { + phase = PHASE_NONE; + + events.Reset(); + + uiFlightCount = 0; + + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + + DespawnSummons(MOB_VAPOR_TRAIL); + me->setActive(false); + + if (pInstance) + pInstance->SetData(DATA_FELMYST_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + events.ScheduleEvent(EVENT_BERSERK, 600000); + + me->setActive(true); + DoZoneInCombat(); + DoCast(me, AURA_SUNWELL_RADIANCE, true); + DoCast(me, AURA_NOXIOUS_FUMES, true); + EnterPhase(PHASE_GROUND); + + if (pInstance) + pInstance->SetData(DATA_FELMYST_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit *who) + { + if (phase != PHASE_FLIGHT) + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (phase != PHASE_FLIGHT) + ScriptedAI::MoveInLineOfSight(who); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(YELL_KILL1,YELL_KILL2), me); + } + + void JustRespawned() + { + DoScriptText(YELL_BIRTH, me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(YELL_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FELMYST_EVENT, DONE); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + // workaround for linked aura + /*if (spell->Id == SPELL_VAPOR_FORCE) + { + caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true); + }*/ + // workaround for mind control + if (spell->Id == SPELL_FOG_INFORM) + { + float x, y, z; + caster->GetPosition(x, y, z); + if (Unit* summon = me->SummonCreature(MOB_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) + { + summon->SetMaxHealth(caster->GetMaxHealth()); + summon->SetHealth(caster->GetMaxHealth()); + summon->CastSpell(summon, SPELL_FOG_CHARM, true); + summon->CastSpell(summon, SPELL_FOG_CHARM2, true); + } + me->DealDamage(caster, caster->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == MOB_DEAD) + { + summon->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); + DoZoneInCombat(summon); + summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true); + } + } + + void MovementInform(uint32, uint32) + { + if (phase == PHASE_FLIGHT) + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); + } + + void DamageTaken(Unit*, uint32 &damage) + { + if (phase != PHASE_GROUND && damage >= me->GetHealth()) + damage = 0; + } + + void EnterPhase(PhaseFelmyst NextPhase) + { + switch(NextPhase) + { + case PHASE_GROUND: + me->CastStop(SPELL_FOG_BREATH); + me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); + me->SetUnitMovementFlags(MOVEMENTFLAG_NONE); + me->SetSpeed(MOVE_RUN, 2.0); + + events.ScheduleEvent(EVENT_CLEAVE, urand(5000, 10000)); + events.ScheduleEvent(EVENT_CORROSION, urand(10000, 20000)); + events.ScheduleEvent(EVENT_GAS_NOVA, urand(15000, 20000)); + events.ScheduleEvent(EVENT_ENCAPSULATE, urand(20000, 25000)); + events.ScheduleEvent(EVENT_FLIGHT, 60000); + break; + case PHASE_FLIGHT: + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1000); + uiFlightCount = 0; + uiBreathCount = 0; + break; + } + phase = NextPhase; + } + + void HandleFlightSequence() + { + switch(uiFlightCount) + { + case 0: + //me->AttackStop(); + me->GetMotionMaster()->Clear(false); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->StopMoving(); + DoScriptText(YELL_TAKEOFF, me); + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 2000); + break; + case 1: + me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+1, me->GetPositionY(), me->GetPositionZ()+10); + break; + case 2: + { + Unit *pTarget = pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); + if (!pTarget) + pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); + + if (!pTarget) + { + EnterEvadeMode(); + return; + } + + Creature* Vapor = me->SummonCreature(MOB_VAPOR, pTarget->GetPositionX()-5+rand()%10, pTarget->GetPositionY()-5+rand()%10, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + if (Vapor) + { + Vapor->AI()->AttackStart(pTarget); + me->InterruptNonMeleeSpells(false); + DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug + Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true); + } + + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); + break; + } + case 3: + { + DespawnSummons(MOB_VAPOR_TRAIL); + //DoCast(me, SPELL_VAPOR_SELECT); need core support + + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); + if (!pTarget) + pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); + + if (!pTarget) + { + EnterEvadeMode(); + return; + } + + //pTarget->CastSpell(pTarget, SPELL_VAPOR_SUMMON, true); need core support + Creature* pVapor = me->SummonCreature(MOB_VAPOR, pTarget->GetPositionX()-5+rand()%10, pTarget->GetPositionY()-5+rand()%10, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + if (pVapor) + { + if (pVapor->AI()) + pVapor->AI()->AttackStart(pTarget); + me->InterruptNonMeleeSpells(false); + DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug + pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true); + } + + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); + break; + } + case 4: + DespawnSummons(MOB_VAPOR_TRAIL); + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); + break; + case 5: + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); + if (!pTarget) + pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); + + if (!pTarget) + { + EnterEvadeMode(); + return; + } + + breathX = pTarget->GetPositionX(); + breathY = pTarget->GetPositionY(); + float x, y, z; + pTarget->GetContactPoint(me, x, y, z, 70); + me->GetMotionMaster()->MovePoint(0, x, y, z+10); + break; + } + case 6: + me->SetOrientation(me->GetAngle(breathX, breathY)); + me->StopMoving(); + //DoTextEmote("takes a deep breath.", NULL); + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); + break; + case 7: + { + DoCast(me, SPELL_FOG_BREATH, true); + float x, y, z; + me->GetPosition(x, y, z); + x = 2 * breathX - x; + y = 2 * breathY - y; + me->GetMotionMaster()->MovePoint(0, x, y, z); + events.ScheduleEvent(EVENT_SUMMON_FOG, 1); + break; + } + case 8: + me->CastStop(SPELL_FOG_BREATH); + me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); + ++uiBreathCount; + events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); + if (uiBreathCount < 3) + uiFlightCount = 4; + break; + case 9: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO)) + DoStartMovement(pTarget); + else + { + EnterEvadeMode(); + return; + } + break; + case 10: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + EnterPhase(PHASE_GROUND); + AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO)); + break; + } + ++uiFlightCount; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (phase == PHASE_FLIGHT && !me->IsInEvadeMode()) + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->IsNonMeleeSpellCasted(false)) + return; + + if (phase == PHASE_GROUND) + { + switch(events.ExecuteEvent()) + { + case EVENT_BERSERK: + DoScriptText(YELL_BERSERK, me); + DoCast(me, SPELL_BERSERK, true); + events.ScheduleEvent(EVENT_BERSERK, 10000); + break; + case EVENT_CLEAVE: + DoCast(me->getVictim(), SPELL_CLEAVE, false); + events.ScheduleEvent(EVENT_CLEAVE, urand(5000,10000)); + break; + case EVENT_CORROSION: + DoCast(me->getVictim(), SPELL_CORROSION, false); + events.ScheduleEvent(EVENT_CORROSION, urand(20000,30000)); + break; + case EVENT_GAS_NOVA: + DoCast(me, SPELL_GAS_NOVA, false); + events.ScheduleEvent(EVENT_GAS_NOVA, urand(20000,25000)); + break; + case EVENT_ENCAPSULATE: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true)) + DoCast(pTarget, SPELL_ENCAPSULATE_CHANNEL, false); + events.ScheduleEvent(EVENT_ENCAPSULATE, urand(25000,30000)); + break; + case EVENT_FLIGHT: + EnterPhase(PHASE_FLIGHT); + break; + default: + DoMeleeAttackIfReady(); + break; + } + } + + if (phase == PHASE_FLIGHT) + { + switch(events.ExecuteEvent()) + { + case EVENT_BERSERK: + DoScriptText(YELL_BERSERK, me); + DoCast(me, SPELL_BERSERK, true); + break; + case EVENT_FLIGHT_SEQUENCE: + HandleFlightSequence(); + break; + case EVENT_SUMMON_FOG: + { + float x, y, z; + me->GetPosition(x, y, z); + me->UpdateGroundPositionZ(x, y, z); + if (Creature *Fog = me->SummonCreature(MOB_VAPOR_TRAIL, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 10000)) + { + Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER); + Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true); + me->CastSpell(Fog, SPELL_FOG_FORCE, true); + } + } + events.ScheduleEvent(EVENT_SUMMON_FOG, 1000); + break; + } + } + } + + void DespawnSummons(uint32 entry) + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllCreaturesOfEntryInRange check(me, entry, 100); + Trinity::CreatureListSearcher searcher(me, templist, check); + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + cell.Visit(pair, cSearcher, *(me->GetMap())); + + for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) + { + if (entry == MOB_VAPOR_TRAIL && phase == PHASE_FLIGHT) + { + (*i)->GetPosition(x, y, z); + me->SummonCreature(MOB_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + } + (*i)->SetVisibility(VISIBILITY_OFF); + (*i)->setDeathState(JUST_DIED); + if ((*i)->getDeathState() == CORPSE) + (*i)->RemoveCorpse(); + } + } +}; + +struct mob_felmyst_vaporAI : public ScriptedAI +{ + mob_felmyst_vaporAI(Creature *c) : ScriptedAI(c) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetSpeed(MOVE_RUN, 0.8); + } + void Reset() {} + void EnterCombat(Unit* /*who*/) + { + DoZoneInCombat(); + //DoCast(me, SPELL_VAPOR_FORCE, true); core bug + } + void UpdateAI(const uint32 /*diff*/) + { + if (!me->getVictim()) + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + AttackStart(pTarget); + } +}; + +struct mob_felmyst_trailAI : public ScriptedAI +{ + mob_felmyst_trailAI(Creature *c) : ScriptedAI(c) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_TRAIL_TRIGGER, true); + me->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 0.01); // core bug + } + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_boss_felmyst(Creature* pCreature) +{ + return new boss_felmystAI(pCreature); +} + +CreatureAI* GetAI_mob_felmyst_vapor(Creature* pCreature) +{ + return new mob_felmyst_vaporAI(pCreature); +} + +CreatureAI* GetAI_mob_felmyst_trail(Creature* pCreature) +{ + return new mob_felmyst_trailAI(pCreature); +} + +void AddSC_boss_felmyst() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_felmyst"; + newscript->GetAI = &GetAI_boss_felmyst; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felmyst_vapor"; + newscript->GetAI = &GetAI_mob_felmyst_vapor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_felmyst_trail"; + newscript->GetAI = &GetAI_mob_felmyst_trail; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp new file mode 100644 index 00000000000..146771325eb --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -0,0 +1,794 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kalecgos +SD%Complete: 95 +SDComment: +SDCategory: Sunwell_Plateau +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +enum Yells +{ + //Kalecgos dragon form + SAY_EVIL_AGGRO = -1580000, + SAY_EVIL_SPELL1 = -1580001, + SAY_EVIL_SPELL2 = -1580002, + SAY_EVIL_SLAY1 = -1580003, + SAY_EVIL_SLAY2 = -1580004, + SAY_EVIL_ENRAGE = -1580005, + + //Kalecgos humanoid form + SAY_GOOD_AGGRO = -1580006, + SAY_GOOD_NEAR_DEATH = -1580007, + SAY_GOOD_NEAR_DEATH2 = -1580008, + SAY_GOOD_PLRWIN = -1580009, + + //Sathrovarr + SAY_SATH_AGGRO = -1580010, + SAY_SATH_DEATH = -1580011, + SAY_SATH_SPELL1 = -1580012, + SAY_SATH_SPELL2 = -1580013, + SAY_SATH_SLAY1 = -1580014, + SAY_SATH_SLAY2 = -1580015, + SAY_SATH_ENRAGE = -1580016, +}; + +enum Spells +{ + AURA_SUNWELL_RADIANCE = 45769, + AURA_SPECTRAL_EXHAUSTION = 44867, + AURA_SPECTRAL_REALM = 46021, + AURA_SPECTRAL_INVISIBILITY = 44801, + AURA_DEMONIC_VISUAL = 44800, + + SPELL_SPECTRAL_BLAST = 44869, + SPELL_TELEPORT_SPECTRAL = 46019, + SPELL_ARCANE_BUFFET = 45018, + SPELL_FROST_BREATH = 44799, + SPELL_TAIL_LASH = 45122, + + SPELL_BANISH = 44836, + SPELL_TRANSFORM_KALEC = 44670, + SPELL_ENRAGE = 44807, + + SPELL_CORRUPTION_STRIKE = 45029, + SPELL_AGONY_CURSE = 45032, + SPELL_SHADOW_BOLT = 45031, + + SPELL_HEROIC_STRIKE = 45026, + SPELL_REVITALIZE = 45027 +}; + +enum SWPActions +{ + DO_ENRAGE = 1, + DO_BANISH = 2, +}; + +#define GO_FAILED "You are unable to use this currently." + +#define EMOTE_UNABLE_TO_FIND "is unable to find Kalecgos" + +#define FLY_X 1679 +#define FLY_Y 900 +#define FLY_Z 82 + +#define CENTER_X 1705 +#define CENTER_Y 930 +#define RADIUS 30 + +#define DRAGON_REALM_Z 53.079 +#define DEMON_REALM_Z -74.558 + +#define MAX_PLAYERS_IN_SPECTRAL_REALM 0 //over this, teleport object won't work, 0 disables check + +uint32 WildMagic[] = { 44978, 45001, 45002, 45004, 45006, 45010 }; + +struct boss_kalecgosAI : public ScriptedAI +{ + boss_kalecgosAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + SathGUID = 0; + DoorGUID = 0; + bJustReset = false; + me->setActive(true); + SpellEntry *TempSpell = GET_SPELL(SPELL_SPECTRAL_BLAST); + if (TempSpell) + TempSpell->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ENEMY; + } + + ScriptedInstance *pInstance; + + uint32 ArcaneBuffetTimer; + uint32 FrostBreathTimer; + uint32 WildMagicTimer; + uint32 SpectralBlastTimer; + uint32 TailLashTimer; + uint32 CheckTimer; + uint32 TalkTimer; + uint32 TalkSequence; + uint32 ResetTimer; + + bool isFriendly; + bool isEnraged; + bool isBanished; + bool bJustReset; + + uint64 SathGUID; + uint64 DoorGUID; + + void Reset() + { + if (pInstance) + { + SathGUID = pInstance->GetData64(DATA_SATHROVARR); + pInstance->SetData(DATA_KALECGOS_EVENT, NOT_STARTED); + } + + if (Creature *Sath = Unit::GetCreature(*me, SathGUID)) + Sath->AI()->EnterEvadeMode(); + + me->setFaction(14); + if (!bJustReset) //first reset at create + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetVisibility(VISIBILITY_ON); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + } + me->SetHealth(me->GetMaxHealth());//dunno why it does not resets health at evade.. + ArcaneBuffetTimer = 8000; + FrostBreathTimer = 15000; + WildMagicTimer = 10000; + TailLashTimer = 25000; + SpectralBlastTimer = urand(20000,25000); + CheckTimer = 1000; + ResetTimer = 30000; + + TalkTimer = 0; + TalkSequence = 0; + isFriendly = false; + isEnraged = false; + isBanished = false; + } + + void EnterEvadeMode() + { + bJustReset = true; + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + ScriptedAI::EnterEvadeMode(); + } + + void DoAction(const int32 param) + { + switch (param) + { + case DO_ENRAGE: + isEnraged = true; + me->CastSpell(me, SPELL_ENRAGE, true); + break; + case DO_BANISH: + isBanished = true; + me->CastSpell(me, SPELL_BANISH, true); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (TalkTimer) + { + if (!TalkSequence) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(); + ++TalkSequence; + } + if (TalkTimer <= diff) + { + if (isFriendly) + GoodEnding(); + else + BadEnding(); + ++TalkSequence; + } else TalkTimer -= diff; + } + else + { + if (bJustReset) + { + if (ResetTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SetVisibility(VISIBILITY_ON); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + ResetTimer = 10000; + bJustReset = false; + } else ResetTimer -= diff; + return; + } + if (!UpdateVictim()) + return; + + if (CheckTimer <= diff) + { + if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75) + { + me->AI()->EnterEvadeMode(); + return; + } + if (HealthBelowPct(10) && !isEnraged) + { + if (Creature* Sath = Unit::GetCreature(*me, SathGUID)) + Sath->AI()->DoAction(DO_ENRAGE); + DoAction(DO_ENRAGE); + } + if (!isBanished && HealthBelowPct(1)) + { + if (Creature* Sath = Unit::GetCreature(*me, SathGUID)) + { + if (Sath->HasAura(SPELL_BANISH)) + { + Sath->DealDamage(Sath, Sath->GetHealth()); + return; + } + else + DoAction(DO_BANISH); + } + else + { + error_log("TSCR: Didn't find Shathrowar. Kalecgos event reseted."); + EnterEvadeMode(); + return; + } + } + CheckTimer = 1000; + } else CheckTimer -= diff; + + if (ArcaneBuffetTimer <= diff) + { + DoCastAOE(SPELL_ARCANE_BUFFET); + ArcaneBuffetTimer = 8000; + } else ArcaneBuffetTimer -= diff; + + if (FrostBreathTimer <= diff) + { + DoCastAOE(SPELL_FROST_BREATH); + FrostBreathTimer = 15000; + } else FrostBreathTimer -= diff; + + if (TailLashTimer <= diff) + { + DoCastAOE(SPELL_TAIL_LASH); + TailLashTimer = 15000; + } else TailLashTimer -= diff; + + if (WildMagicTimer <= diff) + { + DoCastAOE(WildMagic[rand()%6]); + WildMagicTimer = 20000; + } else WildMagicTimer -= diff; + + if (SpectralBlastTimer <= diff) + { + std::list &m_threatlist = me->getThreatManager().getThreatList(); + std::list targetList; + for (std::list::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) + if ((*itr)->getTarget() && (*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->GetGUID() != me->getVictim()->GetGUID() && !(*itr)->getTarget()->HasAura(AURA_SPECTRAL_EXHAUSTION) && (*itr)->getTarget()->GetPositionZ() > me->GetPositionZ()-5) + targetList.push_back((*itr)->getTarget()); + if (targetList.empty()) + { + SpectralBlastTimer = 1000; + return; + } + std::list::const_iterator i = targetList.begin(); + advance(i, rand()%targetList.size()); + if ((*i)) + { + (*i)->CastSpell((*i), SPELL_SPECTRAL_BLAST,true); + SpectralBlastTimer = 20000+rand()%5000; + } else SpectralBlastTimer = 1000; + } else SpectralBlastTimer -= diff; + + DoMeleeAttackIfReady(); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (bJustReset)//boss is invisible, don't attack + return; + + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius)) + AttackStart(who); + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = 0; + } + + void EnterCombat(Unit* /*who*/) + { + me->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_EVIL_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_KALECGOS_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_EVIL_SLAY1,SAY_EVIL_SLAY2), me); + } + + void MovementInform(uint32 type,uint32 /*id*/) + { + if (type != POINT_MOTION_TYPE) + return; + me->SetVisibility(VISIBILITY_OFF); + if (isFriendly) + { + me->setDeathState(JUST_DIED); + + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer) + ((InstanceMap*)me->GetMap())->PermBindAllPlayers(pPlayer); + } + } + } + else + { + me->GetMotionMaster()->MoveTargetedHome(); + TalkTimer = 1000; + } + } + + void GoodEnding() + { + switch(TalkSequence) + { + case 1: + me->setFaction(35); + TalkTimer = 1000; + break; + case 2: + DoScriptText(SAY_GOOD_PLRWIN, me); + TalkTimer = 10000; + break; + case 3: + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); + TalkTimer = 600000; + break; + default: + break; + } + } + + void BadEnding() + { + switch(TalkSequence) + { + case 1: + DoScriptText(SAY_EVIL_ENRAGE, me); + TalkTimer = 3000; + break; + case 2: + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); + TalkTimer = 15000; + break; + case 3: + EnterEvadeMode(); + break; + default: + break; + } + } +}; + +struct boss_sathrovarrAI : public ScriptedAI +{ + boss_sathrovarrAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + KalecGUID = 0; + KalecgosGUID = 0; + } + + ScriptedInstance *pInstance; + + uint32 CorruptionStrikeTimer; + uint32 AgonyCurseTimer; + uint32 ShadowBoltTimer; + uint32 CheckTimer; + uint32 ResetThreat; + + uint64 KalecGUID; + uint64 KalecgosGUID; + + bool isEnraged; + bool isBanished; + + void Reset() + { + me->SetHealth(me->GetMaxHealth());//dunno why it does not resets health at evade.. + me->setActive(true); + if (pInstance) + { + KalecgosGUID = pInstance->GetData64(DATA_KALECGOS_DRAGON); + pInstance->SetData(DATA_KALECGOS_EVENT, NOT_STARTED); + } + if (KalecGUID) + { + if (Creature* Kalec = Unit::GetCreature(*me, KalecGUID)) + Kalec->setDeathState(JUST_DIED); + KalecGUID = 0; + } + + ShadowBoltTimer = 7000 + rand()%3 * 1000; + AgonyCurseTimer = 20000; + CorruptionStrikeTimer = 13000; + CheckTimer = 1000; + ResetThreat = 1000; + isEnraged = false; + isBanished = false; + + me->CastSpell(me, AURA_DEMONIC_VISUAL, true); + TeleportAllPlayersBack(); + } + + void EnterCombat(Unit* /*who*/) + { + if (Creature *Kalec = me->SummonCreature(MOB_KALEC, me->GetPositionX() + 10, me->GetPositionY() + 5, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) + { + KalecGUID = Kalec->GetGUID(); + me->CombatStart(Kalec); + me->AddThreat(Kalec, 100.0f); + Kalec->setActive(true); + } + DoScriptText(SAY_SATH_AGGRO, me); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = 0; + } + + void KilledUnit(Unit *pTarget) + { + if (pTarget->GetGUID() == KalecGUID) + { + TeleportAllPlayersBack(); + if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) + { + CAST_AI(boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1; + CAST_AI(boss_kalecgosAI, Kalecgos->AI())->isFriendly = false; + } + EnterEvadeMode(); + return; + } + DoScriptText(RAND(SAY_SATH_SLAY1,SAY_SATH_SLAY2), me); + } + + void JustDied(Unit * /*killer*/) + { + DoScriptText(SAY_SATH_DEATH, me); + me->GetMap()->CreatureRelocation(me, me->GetPositionX(), me->GetPositionY(), DRAGON_REALM_Z, me->GetOrientation()); + TeleportAllPlayersBack(); + if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) + { + CAST_AI(boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1; + CAST_AI(boss_kalecgosAI, Kalecgos->AI())->isFriendly = true; + } + + if (pInstance) + pInstance->SetData(DATA_KALECGOS_EVENT, DONE); + } + + void TeleportAllPlayersBack() + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) return; + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->GetPositionZ() <= DRAGON_REALM_Z-5) + { + i->getSource()->RemoveAura(AURA_SPECTRAL_REALM); + i->getSource()->TeleportTo(me->GetMap()->GetId(),i->getSource()->GetPositionX(),i->getSource()->GetPositionY(),DRAGON_REALM_Z+5,i->getSource()->GetOrientation()); + } + } + } + + void DoAction(const int32 param) + { + switch (param) + { + case DO_ENRAGE: + isEnraged = true; + me->CastSpell(me, SPELL_ENRAGE, true); + break; + case DO_BANISH: + isBanished = true; + me->CastSpell(me, SPELL_BANISH, true); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) + me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); + if (!UpdateVictim()) + return; + + if (CheckTimer <= diff) + { + Creature *Kalec = Unit::GetCreature(*me, KalecGUID); + if (!Kalec || (Kalec && !Kalec->isAlive())) + { + if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) + Kalecgos->AI()->EnterEvadeMode(); + return; + } + if (HealthBelowPct(10) && !isEnraged) + { + if (Creature* Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) + Kalecgos->AI()->DoAction(DO_ENRAGE); + DoAction(DO_ENRAGE); + } + Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID); + if (Kalecgos) + { + if (!Kalecgos->isInCombat()) + { + me->AI()->EnterEvadeMode(); + return; + } + } + if (!isBanished && HealthBelowPct(1)) + { + if (Kalecgos) + { + if (Kalecgos->HasAura(SPELL_BANISH)) + { + me->DealDamage(me, me->GetHealth()); + return; + } + else + DoAction(DO_BANISH); + } + else + { + me->MonsterTextEmote(EMOTE_UNABLE_TO_FIND, NULL); + EnterEvadeMode(); + return; + } + } + CheckTimer = 1000; + } else CheckTimer -= diff; + + if (ResetThreat <= diff) + { + for (std::list::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) + { + if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) + { + if (pUnit->GetPositionZ() > me->GetPositionZ()+5) + { + me->getThreatManager().modifyThreatPercent(pUnit,-100); + } + } + } + ResetThreat = 1000; + } else ResetThreat -= diff; + + if (ShadowBoltTimer <= diff) + { + if (!(rand()%5))DoScriptText(SAY_SATH_SPELL1, me); + DoCast(me, SPELL_SHADOW_BOLT); + ShadowBoltTimer = 7000+(rand()%3000); + } else ShadowBoltTimer -= diff; + + if (AgonyCurseTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!pTarget) pTarget = me->getVictim(); + DoCast(pTarget, SPELL_AGONY_CURSE); + AgonyCurseTimer = 20000; + } else AgonyCurseTimer -= diff; + + if (CorruptionStrikeTimer <= diff) + { + if (!(rand()%5))DoScriptText(SAY_SATH_SPELL2, me); + DoCast(me->getVictim(), SPELL_CORRUPTION_STRIKE); + CorruptionStrikeTimer = 13000; + } else CorruptionStrikeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_kalecAI : public ScriptedAI +{ + ScriptedInstance *pInstance; + + uint32 RevitalizeTimer; + uint32 HeroicStrikeTimer; + uint32 YellTimer; + uint32 YellSequence; + + uint64 SathGUID; + + bool isEnraged; // if demon is enraged + + boss_kalecAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() + { + if (pInstance) + SathGUID = pInstance->GetData64(DATA_SATHROVARR); + + RevitalizeTimer = 5000; + HeroicStrikeTimer = 3000; + YellTimer = 5000; + YellSequence = 0; + + isEnraged = false; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != SathGUID) + damage = 0; + else if (isEnraged) + damage *= 3; + } + + void UpdateAI(const uint32 diff) + { + if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) + me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); + if (!UpdateVictim()) + return; + + if (YellTimer <= diff) + { + switch(YellSequence) + { + case 0: + DoScriptText(SAY_GOOD_AGGRO, me); + ++YellSequence; + break; + case 1: + if (HealthBelowPct(50)) + { + DoScriptText(SAY_GOOD_NEAR_DEATH, me); + ++YellSequence; + } + break; + case 2: + if (HealthBelowPct(10)) + { + DoScriptText(SAY_GOOD_NEAR_DEATH2, me); + ++YellSequence; + } + break; + default: + break; + } + YellTimer = 5000; + } + + if (RevitalizeTimer <= diff) + { + DoCast(me, SPELL_REVITALIZE); + RevitalizeTimer = 5000; + } else RevitalizeTimer -= diff; + + if (HeroicStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HEROIC_STRIKE); + HeroicStrikeTimer = 2000; + } else HeroicStrikeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +bool GOkalecgos_teleporter(Player* pPlayer, GameObject* pGo) +{ + uint32 SpectralPlayers = 0; + Map* pMap = pGo->GetMap(); + if (!pMap->IsDungeon()) return true; + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->GetPositionZ() < DEMON_REALM_Z + 5) + ++SpectralPlayers; + } + if (pPlayer->HasAura(AURA_SPECTRAL_EXHAUSTION) || (MAX_PLAYERS_IN_SPECTRAL_REALM && SpectralPlayers >= MAX_PLAYERS_IN_SPECTRAL_REALM)) + pPlayer->GetSession()->SendNotification(GO_FAILED); + else + pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_SPECTRAL, true); + return true; +} + +CreatureAI* GetAI_boss_kalecgos(Creature* pCreature) +{ + return new boss_kalecgosAI (pCreature); +} + +CreatureAI* GetAI_boss_Sathrovarr(Creature* pCreature) +{ + return new boss_sathrovarrAI (pCreature); +} + +CreatureAI* GetAI_boss_kalec(Creature* pCreature) +{ + return new boss_kalecAI (pCreature); +} + +void AddSC_boss_kalecgos() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kalecgos"; + newscript->GetAI = &GetAI_boss_kalecgos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_sathrovarr"; + newscript->GetAI = &GetAI_boss_Sathrovarr; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_kalec"; + newscript->GetAI = &GetAI_boss_kalec; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "kalecgos_teleporter"; + newscript->pGOHello = &GOkalecgos_teleporter; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp new file mode 100644 index 00000000000..f1c3a769b28 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -0,0 +1,1408 @@ +/* Copyright (C) 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kiljaeden +SD%Complete: 80 +SDComment: Sinister Reflection Model, Armageddon Visual, SAY_KJ_SHADOWSPIKE3, Emote, End Sequence +SDCategory: Sunwell_Plateau +EndScriptData */ + +//TODO rewrite Armageddon + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" +#include + +/*** Speech and sounds***/ +enum Yells +{ + // These are used throughout Sunwell and Magisters(?). Players can hear this while running through the instances. + SAY_KJ_OFFCOMBAT1 = -1580066, + SAY_KJ_OFFCOMBAT2 = -1580067, + SAY_KJ_OFFCOMBAT3 = -1580068, + SAY_KJ_OFFCOMBAT4 = -1580069, + SAY_KJ_OFFCOMBAT5 = -1580070, + + // Encounter speech and sounds + SAY_KJ_EMERGE = -1580071, + SAY_KJ_SLAY1 = -1580072, + SAY_KJ_SLAY2 = -1580073, + SAY_KJ_REFLECTION1 = -1580074, + SAY_KJ_REFLECTION2 = -1580075, + SAY_KJ_DARKNESS1 = -1580076, + SAY_KJ_DARKNESS2 = -1580077, + SAY_KJ_DARKNESS3 = -1580078, + SAY_KJ_PHASE3 = -1580079, + SAY_KJ_PHASE4 = -1580080, + SAY_KJ_PHASE5 = -1580081, + SAY_KJ_DEATH = -1580093, + EMOTE_KJ_DARKNESS = -1580094, + + /*** Kalecgos - Anveena speech at the beginning of Phase 5; Anveena's sacrifice ***/ + SAY_KALECGOS_AWAKEN = -1580082, + SAY_ANVEENA_IMPRISONED = -1580083, + SAY_KALECGOS_LETGO = -1580084, + SAY_ANVEENA_LOST = -1580085, + SAY_KALECGOS_FOCUS = -1580086, + SAY_ANVEENA_KALEC = -1580087, + SAY_KALECGOS_FATE = -1580088, + SAY_ANVEENA_GOODBYE = -1580089, + SAY_KALECGOS_GOODBYE = -1580090, + SAY_KALECGOS_ENCOURAGE = -1580091, + + /*** Kalecgos says throughout the fight ***/ + SAY_KALECGOS_JOIN = -1580092, + SAY_KALEC_ORB_READY1 = -1580095, + SAY_KALEC_ORB_READY2 = -1580096, + SAY_KALEC_ORB_READY3 = -1580097, + SAY_KALEC_ORB_READY4 = -1580098 +}; + +/*** Spells used during the encounter ***/ +enum Spells +{ + /* Hand of the Deceiver's spells and cosmetics */ + SPELL_SHADOW_BOLT_VOLLEY = 45770, // ~30 yard range Shadow Bolt Volley for ~2k(?) damage + SPELL_SHADOW_INFUSION = 45772, // They gain this at 20% - Immunity to Stun/Silence and makes them look angry! + SPELL_FELFIRE_PORTAL = 46875, // Creates a portal that spawns Felfire Fiends (LIVE FOR THE SWARM!1 FOR THE OVERMIND!) + SPELL_SHADOW_CHANNELING = 46757, // Channeling animation out of combat + + /* Volatile Felfire Fiend's spells */ + SPELL_FELFIRE_FISSION = 45779, // Felfire Fiends explode when they die or get close to target. + + /* Kil'Jaeden's spells and cosmetics */ + SPELL_TRANS = 23188, // Surprisingly, this seems to be the right spell.. (Where is it used?) + SPELL_REBIRTH = 44200, // Emerge from the Sunwell + SPELL_SOUL_FLAY = 45442, // 9k Shadow damage over 3 seconds. Spammed throughout all the fight. + SPELL_SOUL_FLAY_SLOW = 47106, + SPELL_LEGION_LIGHTNING = 45664, // Chain Lightning, 4 targets, ~3k Shadow damage, 1.5k mana burn + SPELL_FIRE_BLOOM = 45641, // Places a debuff on 5 raid members, which causes them to deal 2k Fire damage to nearby allies and selves. MIGHT NOT WORK + SPELL_DESTROY_ALL_DRAKES = 46707, // when he use it? + + SPELL_SINISTER_REFLECTION = 45785, // Summon shadow copies of 5 raid members that fight against KJ's enemies//dont work + // 45892 // right one for SPELL_SINISTER_REFLECTION but no EffectScriptEffect + SPELL_COPY_WEAPON = 41055, // } + SPELL_COPY_WEAPON2 = 41054, // } + SPELL_COPY_OFFHAND = 45206, // }- Spells used in Sinister Reflection creation + SPELL_COPY_OFFHAND_WEAPON = 45205, // } + + SPELL_SHADOW_SPIKE = 46680, // Bombard random raid members with Shadow Spikes (Very similar to Void Reaver orbs) + SPELL_FLAME_DART = 45737, // Bombards the raid with flames every 3(?) seconds + SPELL_DARKNESS_OF_A_THOUSAND_SOULS = 46605, // Begins a 8-second channeling, after which he will deal 50'000 damage to the raid + SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE = 45657, + + /* Armageddon spells wrong visual */ + SPELL_ARMAGEDDON_TRIGGER = 45909, // Meteor spell trigger missile should cast Creature on himself + SPELL_ARMAGEDDON_VISUAL = 45911, // Does the hellfire visual to indicate where the meteor missle lands + SPELL_ARMAGEDDON_VISUAL2 = 45914, // Does the light visual to indicate where the meteor missle lands + SPELL_ARMAGEDDON_VISUAL3 = 24207, // This shouldn't correct but same as seen on the movie + SPELL_ARMAGEDDON_SUMMON_TRIGGER = 45921, // Summons the triggers that cast the spells on himself need random target select + SPELL_ARMAGEDDON_DAMAGE = 45915, // This does the area damage + + /* Shield Orb Spells*/ + SPELL_SHADOW_BOLT = 45680, //45679 would be correct but triggers to often //TODO fix console error + + /* Anveena's spells and cosmetics (Or, generally, everything that has "Anveena" in name) */ + SPELL_ANVEENA_PRISON = 46367, // She hovers locked within a bubble + SPELL_ANVEENA_ENERGY_DRAIN = 46410, // Sunwell energy glow animation (Control mob uses this) + SPELL_SACRIFICE_OF_ANVEENA = 46474, // This is cast on Kil'Jaeden when Anveena sacrifices herself into the Sunwell + + /* Sinister Reflection Spells */ + SPELL_SR_CURSE_OF_AGONY = 46190, + SPELL_SR_SHADOW_BOLT = 47076, + + SPELL_SR_EARTH_SHOCK = 47071, + + SPELL_SR_FIREBALL = 47074, + + SPELL_SR_HEMORRHAGE = 45897, + + SPELL_SR_HOLY_SHOCK = 38921, + SPELL_SR_HAMMER_OF_JUSTICE = 37369, + + SPELL_SR_HOLY_SMITE = 47077, + SPELL_SR_RENEW = 47079, + + SPELL_SR_SHOOT = 16496, + SPELL_SR_MULTI_SHOT = 48098, + SPELL_SR_WING_CLIP = 40652, + + SPELL_SR_WHIRLWIND = 17207, + + SPELL_SR_MOONFIRE = 47072, + //SPELL_SR_PLAGU STRIKE = 58843, Dk Spell! + + /*** Other Spells (used by players, etc) ***/ + SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT = 45839, // Possess the blue dragon from the orb to help the raid. + SPELL_ENTROPIUS_BODY = 46819, // Visual for Entropius at the Epilogue + SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated +}; + +/*** Error messages ***/ +#define ERROR_KJ_NOT_SUMMONED "TSCR ERROR: Unable to summon Kil'Jaeden for some reason" + +/*** Others ***/ +#define FLOOR_Z 28.050388 +#define SHIELD_ORB_Z 45.000 + +enum Phase +{ + PHASE_DECEIVERS = 1, // Fight 3 adds + PHASE_NORMAL = 2, // Kil'Jaeden emerges from the sunwell + PHASE_DARKNESS = 3, // At 85%, he gains few abilities; Kalecgos joins the fight + PHASE_ARMAGEDDON = 4, // At 55%, he gains even more abilities + PHASE_SACRIFICE = 5, // At 25%, Anveena sacrifices herself into the Sunwell; at this point he becomes enraged and has *significally* shorter cooldowns. +}; + +//Timers +enum KilJaedenTimers +{ + TIMER_SPEECH = 0, + + //Phase 2 Timer + TIMER_SOUL_FLAY = 1, + TIMER_LEGION_LIGHTNING = 2, + TIMER_FIRE_BLOOM = 3, + TIMER_SUMMON_SHILEDORB = 4, + + //Phase 3 Timer + TIMER_SHADOW_SPIKE = 5, + TIMER_FLAME_DART = 6, + TIMER_DARKNESS = 7, + TIMER_ORBS_EMPOWER = 8, + + //Phase 4 Timer + TIMER_ARMAGEDDON = 9 +}; + +// Locations of the Hand of Deceiver adds +Position DeceiverLocations[3]= +{ + {1682.045, 631.299, 5.936}, + {1684.099, 618.848, 0.589}, + {1694.170, 612.272, 1.416}, +}; + +// Locations, where Shield Orbs will spawn +float ShieldOrbLocations[4][2]= +{ + {1698.900, 627.870}, // middle pont of Sunwell + {12, 3.14}, // First one spawns northeast of KJ + {12, 3.14/0.7}, // Second one spawns southeast + {12, 3.14*3.8} // Third one spawns (?) +}; + +struct Speech +{ + int32 textid; + uint32 pCreature, timer; +}; + +// Timers +static Speech Speeches[]= +{ + //Kil Phase 1 -> Phase 2 + {SAY_KJ_EMERGE, DATA_KILJAEDEN, 0}, + {SAY_KALECGOS_JOIN, DATA_KALECGOS_KJ, 26000}, + //Kil Phase 2 -> Phase 3 + {SAY_KALECGOS_AWAKEN, DATA_KALECGOS_KJ, 10000}, + {SAY_ANVEENA_IMPRISONED, DATA_ANVEENA, 5000}, + {SAY_KJ_PHASE3, DATA_KILJAEDEN, 5000}, + //Kil Phase 3 -> Phase 4 + {SAY_KALECGOS_LETGO, DATA_KALECGOS_KJ, 10000}, + {SAY_ANVEENA_LOST, DATA_ANVEENA, 8000}, + {SAY_KJ_PHASE4, DATA_KILJAEDEN, 7000}, + //Kil Phase 4 -> Phase 5 + {SAY_KALECGOS_FOCUS, DATA_KALECGOS_KJ, 4000}, + {SAY_ANVEENA_KALEC, DATA_ANVEENA, 11000}, + {SAY_KALECGOS_FATE, DATA_KALECGOS_KJ, 2000}, + {SAY_ANVEENA_GOODBYE, DATA_ANVEENA, 6000}, + {SAY_KJ_PHASE5, DATA_KILJAEDEN, 5500}, + + // use in End sequence? + {SAY_KALECGOS_GOODBYE, DATA_KALECGOS_KJ, 12000}, +}; + +//AI for Kalecgos +struct boss_kalecgos_kjAI : public ScriptedAI +{ + boss_kalecgos_kjAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint8 OrbsEmpowered; + uint8 EmpowerCount; + + void Reset() + { + OrbsEmpowered = 0; + EmpowerCount = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setActive(true); + + for (uint8 i = 0; i < 4; ++i) + if (GameObject* pOrb = GetOrb(i)) + pOrb->SetGoType(GAMEOBJECT_TYPE_BUTTON); + } + + GameObject* GetOrb(int32 index) + { + if (!pInstance) + return NULL; + + switch(index) + { + case 0: + return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1)); + case 1: + return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2)); + case 2: + return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3)); + case 3: + return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4)); + } + + return NULL; + } + + void ResetOrbs() + { + me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); + for (uint8 i = 0; i < 4; ++i) + if (GameObject* pOrb = GetOrb(i)) + pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 0); + } + + void EmpowerOrb(bool all) + { + GameObject* pOrbEmpowered = GetOrb(OrbsEmpowered); + if (!pOrbEmpowered) + return; + + if (all) + { + me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); + for (uint8 i = 0; i < 4; ++i) + { + if (GameObject* pOrb = GetOrb(i)) + { + pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); + pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 35); + pOrb->setActive(true); + pOrb->Refresh(); + } + } + DoScriptText(SAY_KALECGOS_ENCOURAGE, me); + } + else + { + if (GameObject* pOrb = GetOrb(urand(0,3))) + { + pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); + pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 35); + pOrb->setActive(true); + pOrb->Refresh(); + + OrbsEmpowered = (OrbsEmpowered+1)%4; + + ++EmpowerCount; + switch(EmpowerCount) + { + case 1: DoScriptText(SAY_KALEC_ORB_READY1, me); break; + case 2: DoScriptText(SAY_KALEC_ORB_READY2, me); break; + case 3: DoScriptText(SAY_KALEC_ORB_READY3, me); break; + case 4: DoScriptText(SAY_KALEC_ORB_READY4, me); break; + } + } + } + } + + void UpdateAI(const uint32 diff) + { + } + + void SetRingOfBlueFlames() + { + me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); + for (uint8 i = 0; i < 4; ++i) + { + if (GameObject* pOrb = GetOrb(i)) + { + if (pOrb->GetUInt32Value(GAMEOBJECT_FACTION) == 35) + { + pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); + pOrb->setActive(true); + pOrb->Refresh(); + } + } + } + } +}; + +CreatureAI* GetAI_boss_kalecgos_kj(Creature* pCreature) +{ + return new boss_kalecgos_kjAI (pCreature); +} + +bool GOHello_go_orb_of_the_blue_flight(Player* pPlayer, GameObject* pGo) +{ + if (pGo->GetUInt32Value(GAMEOBJECT_FACTION) == 35) + { + ScriptedInstance* pInstance = pGo->GetInstanceData(); + pPlayer->SummonCreature(CREATURE_POWER_OF_THE_BLUE_DRAGONFLIGHT, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 121000); + pPlayer->CastSpell(pPlayer, SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT, false); + pGo->SetUInt32Value(GAMEOBJECT_FACTION, 0); + + if (Creature* pKalec = Unit::GetCreature(*pPlayer, pInstance->GetData64(DATA_KALECGOS_KJ))) + CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->SetRingOfBlueFlames(); + + pGo->Refresh(); + } + return true; +} + +//AI for Kil'jaeden Event Controller +struct mob_kiljaeden_controllerAI : public Scripted_NoMovementAI +{ + mob_kiljaeden_controllerAI(Creature* c) : Scripted_NoMovementAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + SummonList summons; + + bool bSummonedDeceivers; + bool bKiljaedenDeath; + + uint32 uiRandomSayTimer; + uint32 phase; + uint8 deceiverDeathCount; + + void InitializeAI() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->addUnitState(UNIT_STAT_STUNNED); + + ScriptedAI::InitializeAI(); + } + + void Reset() + { + phase = PHASE_DECEIVERS; + + if (Creature* pKalecKJ = Unit::GetCreature((*me), pInstance->GetData64(DATA_KALECGOS_KJ))) + CAST_AI(boss_kalecgos_kjAI, pKalecKJ->AI())->ResetOrbs(); + deceiverDeathCount = 0; + bSummonedDeceivers = false; + bKiljaedenDeath = false; + uiRandomSayTimer = 30000; + summons.DespawnAll(); + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + case CREATURE_HAND_OF_THE_DECEIVER: + summoned->CastSpell(summoned, SPELL_SHADOW_CHANNELING, false); + break; + case CREATURE_ANVEENA: + summoned->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); + summoned->CastSpell(summoned, SPELL_ANVEENA_PRISON, true); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + break; + case CREATURE_KILJAEDEN: + summoned->CastSpell(summoned, SPELL_REBIRTH, false); + summoned->AddThreat(me->getVictim(), 1.0f); + break; + } + summons.Summon(summoned); + } + + void UpdateAI(const uint32 diff) + { + if (uiRandomSayTimer < diff) + { + if (pInstance && pInstance->GetData(DATA_MURU_EVENT) != DONE && pInstance->GetData(DATA_KILJAEDEN_EVENT) == NOT_STARTED) + DoScriptText(RAND(SAY_KJ_OFFCOMBAT1,SAY_KJ_OFFCOMBAT2,SAY_KJ_OFFCOMBAT3,SAY_KJ_OFFCOMBAT4,SAY_KJ_OFFCOMBAT5), me); + uiRandomSayTimer = 30000; + } else uiRandomSayTimer -= diff; + + if (!bSummonedDeceivers) + { + for (uint8 i = 0; i < 3; ++i) + me->SummonCreature(CREATURE_HAND_OF_THE_DECEIVER, DeceiverLocations[i], TEMPSUMMON_DEAD_DESPAWN, 0); + + DoSpawnCreature(CREATURE_ANVEENA, 0, 0, 40, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + DoCast(me, SPELL_ANVEENA_ENERGY_DRAIN); + bSummonedDeceivers = true; + } + + if (deceiverDeathCount > 2 && phase == PHASE_DECEIVERS) + { + me->RemoveAurasDueToSpell(SPELL_ANVEENA_ENERGY_DRAIN); + phase = PHASE_NORMAL; + DoSpawnCreature(CREATURE_KILJAEDEN, 0, 0,0, 0, TEMPSUMMON_MANUAL_DESPAWN, 0); + } + } +}; + +CreatureAI* GetAI_mob_kiljaeden_controller(Creature* pCreature) +{ + return new mob_kiljaeden_controllerAI (pCreature); +} + +//AI for Kil'jaeden +struct boss_kiljaedenAI : public Scripted_NoMovementAI +{ + boss_kiljaedenAI(Creature* c) : Scripted_NoMovementAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + SummonList summons; + + uint8 Phase; + uint8 ActiveTimers; + uint32 SpeechTimer; + + uint32 Timer[10]; + uint32 WaitTimer; + uint8 speechCount; + uint8 speechPhaseEnd; + + /* Boolean */ + bool IsInDarkness; + bool TimerIsDeactivated[10]; + bool IsWaiting; + bool OrbActivated; + bool SpeechBegins; + + void InitializeAI() + { + Scripted_NoMovementAI::InitializeAI(); + } + + void Reset() + { + TimerIsDeactivated[TIMER_SPEECH] = false; + Timer[TIMER_SPEECH] = 0; + + //Phase 2 Timer + Timer[TIMER_SOUL_FLAY] = 11000; + Timer[TIMER_LEGION_LIGHTNING] = 30000; + Timer[TIMER_FIRE_BLOOM] = 20000; + Timer[TIMER_SUMMON_SHILEDORB] = 35000; + + //Phase 3 Timer + Timer[TIMER_SHADOW_SPIKE] = 4000; + Timer[TIMER_FLAME_DART] = 3000; + Timer[TIMER_DARKNESS] = 45000; + Timer[TIMER_ORBS_EMPOWER] = 35000; + + //Phase 4 Timer + Timer[TIMER_ARMAGEDDON] = 2000; + + ActiveTimers = 5; + WaitTimer = 0; + speechCount = 0; + SpeechTimer = 0; + + Phase = PHASE_NORMAL; + + IsInDarkness = false; + IsWaiting = false; + OrbActivated = false; + SpeechBegins = true; + + if (pInstance) + { + if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ))) + pKalec->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); + } + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 12); + ChangeTimers(false, 0); + summons.DespawnAll(); + } + + void ChangeTimers(bool status, uint32 WTimer) + { + for (uint8 i = 1; i < ActiveTimers; ++i) + TimerIsDeactivated[i] = status; + + if (WTimer > 0) + { + IsWaiting = true; + WaitTimer = WTimer; + } + + if (OrbActivated) + TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true; + if (Timer[TIMER_SHADOW_SPIKE] == 0) + TimerIsDeactivated[TIMER_SHADOW_SPIKE] = true; + if (Phase == PHASE_SACRIFICE) + TimerIsDeactivated[TIMER_SUMMON_SHILEDORB] = true; + } + + void JustSummoned(Creature* summoned) + { + if (summoned->GetEntry() == CREATURE_ARMAGEDDON_TARGET) + { + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + // summoned->SetVisibility(VISIBILITY_OFF); //with this we cant see the armageddon visuals + } + else + summoned->SetLevel(me->getLevel()); + + summoned->setFaction(me->getFaction()); + summons.Summon(summoned); + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_KJ_DEATH, me); + summons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_KILJAEDEN_EVENT, DONE); + } + + void KilledUnit(Unit* victim) + { + DoScriptText(RAND(SAY_KJ_SLAY1,SAY_KJ_SLAY2), me); + } + + void EnterEvadeMode() + { + Scripted_NoMovementAI::EnterEvadeMode(); + summons.DespawnAll(); + + // Reset the controller + if (pInstance) + { + if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) + CAST_AI(mob_kiljaeden_controllerAI, pControl->AI())->Reset(); + } + } + + void EnterCombat(Unit* who) + { + DoZoneInCombat(); + } + + void EnterNextPhase() + { + SpeechBegins = true; + OrbActivated = false; + ChangeTimers(true, 0);//stop every cast Shadow spike will reactivate em all + TimerIsDeactivated[TIMER_SHADOW_SPIKE] = false; + Timer[TIMER_SHADOW_SPIKE] = 100; + // empowered orbs before darkness + Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(10000,40000); + Timer[TIMER_ORBS_EMPOWER] = (Phase == PHASE_SACRIFICE) ? 10000 : 5000; + } + + void CastSinisterReflection() + { + DoScriptText(RAND(SAY_KJ_REFLECTION1,SAY_KJ_REFLECTION2), me); + for (uint8 i = 0; i < 4; ++i) + { + float x,y,z; + Unit *pTarget; + for (uint8 z = 0; z < 6; ++z) + { + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0))break; + } + if (pTarget) + { + pTarget->GetPosition(x,y,z); + if (Creature* pSinisterReflection = me->SummonCreature(CREATURE_SINISTER_REFLECTION, x,y,z,0, TEMPSUMMON_CORPSE_DESPAWN, 0)) + { + pSinisterReflection->SetDisplayId(pTarget->GetDisplayId()); + pSinisterReflection->AI()->AttackStart(pTarget); + } + } + } + } + + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || Phase < PHASE_NORMAL) + return; + + if (IsWaiting) + { + if (WaitTimer <= diff) + { + IsWaiting = false; + ChangeTimers(false, 0); + } else WaitTimer -= diff; + } + + for (uint8 t = 0; t < ActiveTimers; ++t) + { + if (Timer[t] < diff && !TimerIsDeactivated[t]) + { + switch(t) + { + case TIMER_SPEECH: + if (SpeechBegins) + { + SpeechBegins=false; + switch(Phase) + { + case PHASE_NORMAL: + speechPhaseEnd=1; + break; + case PHASE_DARKNESS: + speechPhaseEnd=4; + break; + case PHASE_ARMAGEDDON: + speechPhaseEnd=7; + break; + case PHASE_SACRIFICE: + speechPhaseEnd=12; + break; + } + } + if (Speeches[speechCount].timer < SpeechTimer) + { + SpeechTimer = 0; + if (Creature* pSpeechCreature = Unit::GetCreature(*me, pInstance->GetData64(Speeches[speechCount].pCreature))) + DoScriptText(Speeches[speechCount].textid, pSpeechCreature); + if (speechCount == 12) + if (Creature* pAnveena = Unit::GetCreature(*me, pInstance->GetData64(DATA_ANVEENA))) + pAnveena->CastSpell(me, SPELL_SACRIFICE_OF_ANVEENA, false); + // ChangeTimers(true, 10000); // Kil should do an emote while screaming without attacking for 10 seconds + if (speechCount == speechPhaseEnd) + TimerIsDeactivated[TIMER_SPEECH]=true; + speechCount++; + } + SpeechTimer += diff; + break; + case TIMER_SOUL_FLAY: + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me->getVictim(), SPELL_SOUL_FLAY_SLOW, false); + DoCast(me->getVictim(), SPELL_SOUL_FLAY, false); + Timer[TIMER_SOUL_FLAY] = 3500; + } + break; + case TIMER_LEGION_LIGHTNING: + if (!me->IsNonMeleeSpellCasted(false)) + { + Unit* pRandomPlayer; + + me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY); + for (uint8 z = 0; z < 6; ++z) + { + pRandomPlayer = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!pRandomPlayer->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) + break; + } + + if (pRandomPlayer) + DoCast(pRandomPlayer, SPELL_LEGION_LIGHTNING, false); + else + error_log("try to cast SPELL_LEGION_LIGHTNING on invalid target"); + + Timer[TIMER_LEGION_LIGHTNING] = (Phase == PHASE_SACRIFICE) ? 18000 : 30000; // 18 seconds in PHASE_SACRIFICE + Timer[TIMER_SOUL_FLAY] = 2500; + } + break; + case TIMER_FIRE_BLOOM: + if (!me->IsNonMeleeSpellCasted(false)) + { + me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY); + DoCastAOE(SPELL_FIRE_BLOOM, false); + Timer[TIMER_FIRE_BLOOM] = (Phase == PHASE_SACRIFICE) ? 25000 : 40000; // 25 seconds in PHASE_SACRIFICE + Timer[TIMER_SOUL_FLAY] = 1000; + } + break; + case TIMER_SUMMON_SHILEDORB: + for (uint8 i = 1; i < Phase; ++i) + { + float sx, sy; + sx = ShieldOrbLocations[0][0] + sin(ShieldOrbLocations[i][0]); + sy = ShieldOrbLocations[0][1] + sin(ShieldOrbLocations[i][1]); + me->SummonCreature(CREATURE_SHIELD_ORB, sx, sy, SHIELD_ORB_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + } + Timer[TIMER_SUMMON_SHILEDORB] = urand(30000,60000); // 30-60seconds cooldown + Timer[TIMER_SOUL_FLAY] = 2000; + break; + case TIMER_SHADOW_SPIKE: //Phase 3 + if (!me->IsNonMeleeSpellCasted(false)) + { + CastSinisterReflection(); + DoCastAOE(SPELL_SHADOW_SPIKE, false); + ChangeTimers(true, 30000); + Timer[TIMER_SHADOW_SPIKE] = 0; + TimerIsDeactivated[TIMER_SPEECH] = false; + } + break; + case TIMER_FLAME_DART: //Phase 3 + DoCastAOE(SPELL_FLAME_DART, false); + Timer[TIMER_FLAME_DART] = 3000; //TODO Timer + break; + case TIMER_DARKNESS: //Phase 3 + if (!me->IsNonMeleeSpellCasted(false)) + { + // Begins to channel for 8 seconds, then deals 50'000 damage to all raid members. + if (!IsInDarkness) + { + DoScriptText(EMOTE_KJ_DARKNESS, me); + DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS, false); + ChangeTimers(true, 9000); + Timer[TIMER_DARKNESS] = 8750; + TimerIsDeactivated[TIMER_DARKNESS] = false; + if (Phase == PHASE_SACRIFICE) + TimerIsDeactivated[TIMER_ARMAGEDDON] = false; + IsInDarkness = true; + } + else + { + Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(40000,70000); + IsInDarkness = false; + DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE); + DoScriptText(RAND(SAY_KJ_DARKNESS1,SAY_KJ_DARKNESS2,SAY_KJ_DARKNESS3), me); + } + Timer[TIMER_SOUL_FLAY] = 9000; + } + break; + case TIMER_ORBS_EMPOWER: //Phase 3 + if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ))) + { + switch (Phase) + { + case PHASE_SACRIFICE: + CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(true); + break; + default: + CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(false); + break; + } + } + OrbActivated = true; + TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true; + break; + case TIMER_ARMAGEDDON: //Phase 4 + Unit *pTarget; + for (uint8 z = 0; z < 6; ++z) + { + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break; + } + if (pTarget) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + me->SummonCreature(CREATURE_ARMAGEDDON_TARGET, x,y,z,0, TEMPSUMMON_TIMED_DESPAWN,15000); + } + Timer[TIMER_ARMAGEDDON] = 2000; // No, I'm not kidding + break; + } + } + } + DoMeleeAttackIfReady(); + //Time runs over! + for (uint8 i = 0; i < ActiveTimers; ++i) + if (!TimerIsDeactivated[i]) + { + Timer[i] -= diff; + if (((int32)Timer[i]) < 0) Timer[i] = 0; + } + + //Phase 3 + if (Phase <= PHASE_NORMAL && !IsInDarkness) + { + if (Phase == PHASE_NORMAL && HealthBelowPct(85)) + { + Phase = PHASE_DARKNESS; + ActiveTimers = 9; + EnterNextPhase(); + } + else return; + } + + //Phase 4 + if (Phase <= PHASE_DARKNESS && !IsInDarkness) + { + if (Phase == PHASE_DARKNESS && HealthBelowPct(55)) + { + Phase = PHASE_ARMAGEDDON; + ActiveTimers = 10; + EnterNextPhase(); + } + else return; + } + + //Phase 5 specific spells all we can + if (Phase <= PHASE_ARMAGEDDON && !IsInDarkness) + { + if (Phase == PHASE_ARMAGEDDON && HealthBelowPct(25)) + { + Phase = PHASE_SACRIFICE; + EnterNextPhase(); + } + else return; + } + } +}; + +CreatureAI* GetAI_boss_kiljaeden(Creature* pCreature) +{ + return new boss_kiljaedenAI (pCreature); +} + +//AI for Hand of the Deceiver +struct mob_hand_of_the_deceiverAI : public ScriptedAI +{ + mob_hand_of_the_deceiverAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ShadowBoltVolleyTimer; + uint32 FelfirePortalTimer; + + void Reset() + { + // TODO: Timers! + ShadowBoltVolleyTimer = urand(8000,14000); // So they don't all cast it in the same moment. + FelfirePortalTimer = 20000; + if (pInstance) + pInstance->SetData(DATA_KILJAEDEN_EVENT, NOT_STARTED); + } + + void JustSummoned(Creature* summoned) + { + summoned->setFaction(me->getFaction()); + summoned->SetLevel(me->getLevel()); + } + + void EnterCombat(Unit* who) + { + if (pInstance) + { + pInstance->SetData(DATA_KILJAEDEN_EVENT, IN_PROGRESS); + if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) + pControl->AddThreat(who, 1.0f); + } + me->InterruptNonMeleeSpells(true); + } + + void JustDied(Unit* killer) + { + if (!pInstance) + return; + + if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) + ++(CAST_AI(mob_kiljaeden_controllerAI, pControl->AI())->deceiverDeathCount); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + DoCast(me, SPELL_SHADOW_CHANNELING); + + if (!UpdateVictim()) + return; + + // Gain Shadow Infusion at 20% health + if (HealthBelowPct(20) && !me->HasAura(SPELL_SHADOW_INFUSION, 0)) + DoCast(me, SPELL_SHADOW_INFUSION, true); + + // Shadow Bolt Volley - Shoots Shadow Bolts at all enemies within 30 yards, for ~2k Shadow damage. + if (ShadowBoltVolleyTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); + ShadowBoltVolleyTimer = 12000; + } + else + ShadowBoltVolleyTimer -= diff; + + // Felfire Portal - Creatres a portal, that spawns Volatile Felfire Fiends, which do suicide bombing. + if (FelfirePortalTimer <= diff) + { + if (Creature* pPortal = DoSpawnCreature(CREATURE_FELFIRE_PORTAL, 0, 0,0, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) + { + std::list::iterator itr; + for (itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) + { + Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pUnit) + pPortal->AddThreat(pUnit, 1.0f); + } + } + FelfirePortalTimer = 20000; + } else FelfirePortalTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_hand_of_the_deceiver(Creature* pCreature) +{ + return new mob_hand_of_the_deceiverAI (pCreature); +} + +//AI for Felfire Portal +struct mob_felfire_portalAI : public Scripted_NoMovementAI +{ + mob_felfire_portalAI(Creature* c) : Scripted_NoMovementAI(c) {} + + uint32 uiSpawnFiendTimer; + + void Reset() + { + uiSpawnFiendTimer = 5000; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + } + + void JustSummoned(Creature* summoned) + { + summoned->setFaction(me->getFaction()); + summoned->SetLevel(me->getLevel()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiSpawnFiendTimer <= diff) + { + if (Creature* pFiend = DoSpawnCreature(CREATURE_VOLATILE_FELFIRE_FIEND, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) + pFiend->AddThreat(SelectUnit(SELECT_TARGET_RANDOM,0), 100000.0f); + uiSpawnFiendTimer = urand(4000,8000); + } else uiSpawnFiendTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_felfire_portal(Creature* pCreature) +{ + return new mob_felfire_portalAI (pCreature); +} + +//AI for Felfire Fiend +struct mob_volatile_felfire_fiendAI : public ScriptedAI +{ + mob_volatile_felfire_fiendAI(Creature* c) : ScriptedAI(c) {} + + uint32 uiExplodeTimer; + + bool bLockedTarget; + + void Reset() + { + uiExplodeTimer = 2000; + bLockedTarget = false; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage > me->GetHealth()) + DoCast(me, SPELL_FELFIRE_FISSION, true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!bLockedTarget) + { + me->AddThreat(me->getVictim(), 10000000.0f); + bLockedTarget = true; + } + + if (uiExplodeTimer) + { + if (uiExplodeTimer <= diff) + uiExplodeTimer = 0; + else uiExplodeTimer -= diff; + } + else if (me->IsWithinDistInMap(me->getVictim(), 3)) // Explode if it's close enough to it's target + { + DoCast(me->getVictim(), SPELL_FELFIRE_FISSION); + me->Kill(me); + } + } +}; + +CreatureAI* GetAI_mob_volatile_felfire_fiend(Creature* pCreature) +{ + return new mob_volatile_felfire_fiendAI (pCreature); +} + +//AI for Armageddon target +struct mob_armageddonAI : public Scripted_NoMovementAI +{ + mob_armageddonAI(Creature* c) : Scripted_NoMovementAI(c) {} + + uint8 spell; + uint32 uiTimer; + + void Reset() + { + spell = 0; + uiTimer = 0; + } + + void UpdateAI(const uint32 diff) + { + if (uiTimer <= diff) + { + switch(spell) + { + case 0: + DoCast(me, SPELL_ARMAGEDDON_VISUAL, true); + ++spell; + break; + case 1: + DoCast(me, SPELL_ARMAGEDDON_VISUAL2, true); + uiTimer = 9000; + ++spell; + break; + case 2: + DoCast(me, SPELL_ARMAGEDDON_TRIGGER, true); + ++spell; + uiTimer = 5000; + break; + case 3: + me->Kill(me); + me->RemoveCorpse(); + break; + } + } else uiTimer -=diff; + } +}; + +CreatureAI* GetAI_mob_armageddon(Creature* pCreature) +{ + return new mob_armageddonAI (pCreature); +} + +//AI for Shield Orbs +struct mob_shield_orbAI : public ScriptedAI +{ + mob_shield_orbAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bPointReached; + bool bClockwise; + uint32 uiTimer; + uint32 uiCheckTimer; + float x, y, r, c, mx, my; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + bPointReached = true; + uiTimer = urand(500,1000); + uiCheckTimer = 1000; + r = 17; + c = 0; + mx = ShieldOrbLocations[0][0]; + my = ShieldOrbLocations[0][1]; + bClockwise = urand(0,1); + } + + void UpdateAI(const uint32 diff) + { + if (bPointReached) + { + if (bClockwise) + { + y = my - r * sin(c); + x = mx - r * cos(c); + } + else + { + y = my + r * sin(c); + x = mx + r * cos(c); + } + bPointReached = false; + uiCheckTimer = 1000; + me->GetMotionMaster()->MovePoint(1,x, y, SHIELD_ORB_Z); + c += M_PI/32; + if (c >= 2*M_PI) c = 0; + } + else + { + if (uiCheckTimer <= diff) + { + DoTeleportTo(x,y,SHIELD_ORB_Z); + bPointReached = true; + } + else uiCheckTimer -= diff; + } + + if (uiTimer <= diff) + { + if (Unit* random = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0)) + DoCast(random, SPELL_SHADOW_BOLT, false); + uiTimer = urand(500,1000); + } else uiTimer -= diff; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + bPointReached = true; + } +}; + +CreatureAI* GetAI_mob_shield_orb(Creature* pCreature) +{ + return new mob_shield_orbAI (pCreature); +} + +//AI for Sinister Reflection +struct mob_sinster_reflectionAI : public ScriptedAI +{ + mob_sinster_reflectionAI(Creature* c) : ScriptedAI(c) {} + + uint8 victimClass; + uint32 uiTimer[3]; + + void Reset() + { + uiTimer[0] = 0; + uiTimer[1] = 0; + uiTimer[2] = 0; + victimClass = 0; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if ((victimClass == 0) && me->getVictim()) + { + victimClass = me->getVictim()->getClass(); + switch (victimClass) + { + case CLASS_DRUID: + break; + case CLASS_HUNTER: + break; + case CLASS_MAGE: + break; + case CLASS_WARLOCK: + break; + case CLASS_WARRIOR: + me->SetCanDualWield(true); + break; + case CLASS_PALADIN: + break; + case CLASS_PRIEST: + break; + case CLASS_SHAMAN: + me->SetCanDualWield(true); + break; + case CLASS_ROGUE: + me->SetCanDualWield(true); + break; + } + } + + switch(victimClass) { + case CLASS_DRUID: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_MOONFIRE, false); + uiTimer[1] = urand(2000,4000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_HUNTER: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_MULTI_SHOT, false); + uiTimer[1] = urand(8000,10000); + } + if (uiTimer[2] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_SHOOT, false); + uiTimer[2] = urand(4000,6000); + } + if (me->IsWithinMeleeRange(me->getVictim(), 6)) + { + if (uiTimer[0] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_MULTI_SHOT, false); + uiTimer[0] = urand(6000,8000); + } + DoMeleeAttackIfReady(); + } + break; + case CLASS_MAGE: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_FIREBALL, false); + uiTimer[1] = urand(2000,4000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_WARLOCK: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_SHADOW_BOLT, false); + uiTimer[1] = urand(3000,5000); + } + if (uiTimer[2] <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_SR_CURSE_OF_AGONY, true); + uiTimer[2] = urand(2000,4000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_WARRIOR: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_WHIRLWIND, false); + uiTimer[1] = urand(9000,11000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_PALADIN: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_HAMMER_OF_JUSTICE, false); + uiTimer[1] = urand(6000,8000); + } + if (uiTimer[2] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_HOLY_SHOCK, false); + uiTimer[2] = urand(2000,4000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_PRIEST: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_HOLY_SMITE, false); + uiTimer[1] = urand(4000,6000); + } + if (uiTimer[2] <= diff) + { + DoCast(me, SPELL_SR_RENEW, false); + uiTimer[2] = urand(6000,8000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_SHAMAN: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_EARTH_SHOCK, false); + uiTimer[1] = urand(4000,6000); + } + DoMeleeAttackIfReady(); + break; + case CLASS_ROGUE: + if (uiTimer[1] <= diff) + { + DoCast(me->getVictim(), SPELL_SR_HEMORRHAGE, true); + uiTimer[1] = urand(4000,6000); + } + DoMeleeAttackIfReady(); + break; + } + debug_log("Sinister-Timer"); + for (uint8 i = 0; i < 3; ++i) + uiTimer[i] -= diff; + } +}; + +CreatureAI* GetAI_mob_sinster_reflection(Creature* pCreature) +{ + return new mob_sinster_reflectionAI (pCreature); +} + +void AddSC_boss_kiljaeden() +{ + Script* newscript; + + newscript = new Script; + newscript->pGOHello = &GOHello_go_orb_of_the_blue_flight; + newscript->Name = "go_orb_of_the_blue_flight"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_kalecgos_kj; + newscript->Name = "boss_kalecgos_kj"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_boss_kiljaeden; + newscript->Name = "boss_kiljaeden"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_kiljaeden_controller; + newscript->Name = "mob_kiljaeden_controller"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_hand_of_the_deceiver; + newscript->Name = "mob_hand_of_the_deceiver"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_felfire_portal; + newscript->Name = "mob_felfire_portal"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_volatile_felfire_fiend; + newscript->Name = "mob_volatile_felfire_fiend"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_armageddon; + newscript->Name = "mob_armageddon"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_shield_orb; + newscript->Name = "mob_shield_orb"; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->GetAI = &GetAI_mob_sinster_reflection; + newscript->Name = "mob_sinster_reflection"; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp new file mode 100644 index 00000000000..9dca453ade6 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -0,0 +1,640 @@ +/* Copyright (C) 2009 Trinity +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Muru +SD%Complete: 80 +SDComment: all sounds, black hole effect triggers to often (46228) +*/ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +// Muru & Entropius's spells +enum Spells +{ + SPELL_ENRAGE = 26662, + + // Muru's spells + SPELL_NEGATIVE_ENERGY = 46009, //(this trigger 46008) + SPELL_DARKNESS = 45999, + SPELL_OPEN_ALL_PORTALS = 46177, + SPELL_OPEN_PORTAL = 45977, + SPELL_OPEN_PORTAL_2 = 45976, + SPELL_SUMMON_BERSERKER = 46037, + SPELL_SUMNON_FURY_MAGE = 46038, + SPELL_SUMMON_VOID_SENTINEL = 45988, + SPELL_SUMMON_ENTROPIUS = 46217, + + // Entropius's spells + SPELL_DARKNESS_E = 46269, + SPELL_BLACKHOLE = 46282, + SPELL_NEGATIVE_ENERGY_E = 46284, + SPELL_ENTROPIUS_SPAWN = 46223, + + // Shadowsword Berserker's spells + SPELL_FLURRY = 46160, + SPELL_DUAL_WIELD = 29651, + + // Shadowsword Fury Mage's spells + SPELL_FEL_FIREBALL = 46101, + SPELL_SPELL_FURY = 46102, + + // Void Sentinel's spells + SPELL_SHADOW_PULSE = 46087, + SPELL_VOID_BLAST = 46161, + + // Void Spawn's spells + SPELL_SHADOW_BOLT_VOLLEY = 46082, + + //Dark Fiend Spells + SPELL_DARKFIEND_AOE = 45944, + SPELL_DARKFIEND_VISUAL = 45936, + SPELL_DARKFIEND_SKIN = 45934, + + //Black Hole Spells + SPELL_BLACKHOLE_SPAWN = 46242, + SPELL_BLACKHOLE_GROW = 46228 +}; + +enum BossTimers{ + TIMER_DARKNESS = 0, + TIMER_HUMANOIDES = 1, + TIMER_PHASE = 2, + TIMER_SENTINEL = 3 +}; + +float DarkFiends[8][4] = +{ + {1819.9, 609.80, 69.74, 1.94}, + {1829.39, 617.89, 69.73, 2.61}, + {1801.98, 633.62, 69.74, 5.71}, + {1830.88, 629.99, 69.73, 3.52}, + {1800.38, 621.41, 69.74, 0.22}, + {1808.3 , 612.45, 69.73, 1.02}, + {1823.9 , 639.69, 69.74, 4.12}, + {1811.85, 640.46, 69.73, 4.97} +}; + +float Humanoides[6][5] = +{ + {CREATURE_FURY_MAGE, 1780.16, 666.83, 71.19, 5.21}, + {CREATURE_FURY_MAGE, 1847.93, 600.30, 71.30, 2.57}, + {CREATURE_BERSERKER, 1779.97, 660.64, 71.19, 5.28}, + {CREATURE_BERSERKER, 1786.2 , 661.01, 71.19, 4.51}, + {CREATURE_BERSERKER, 1845.17, 602.63, 71.28, 2.43}, + {CREATURE_BERSERKER, 1842.91, 599.93, 71.23, 2.44} +}; + +uint32 EnrageTimer = 600000; +struct boss_entropiusAI : public ScriptedAI +{ + boss_entropiusAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + SummonList Summons; + + uint32 BlackHoleSummonTimer; + + void Reset() + { + BlackHoleSummonTimer = 15000; + DoCastAOE(SPELL_NEGATIVE_ENERGY_E, false); + + Summons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoCastAOE(SPELL_NEGATIVE_ENERGY_E, true); + DoCast(me, SPELL_ENTROPIUS_SPAWN, false); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + case CREATURE_DARK_FIENDS: + summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false); + break; + case CREATURE_DARKNESS: + summoned->addUnitState(UNIT_STAT_STUNNED); + float x,y,z,o; + summoned->GetHomePosition(x,y,z,o); + me->SummonCreature(CREATURE_DARK_FIENDS, x,y,z,o, TEMPSUMMON_CORPSE_DESPAWN, 0); + break; + } + summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); + Summons.Summon(summoned); + } + + void JustDied(Unit* /*killer*/) + { + Summons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (EnrageTimer < diff && !me->HasAura(SPELL_ENRAGE, 0)) + { + DoCast(me, SPELL_ENRAGE, false); + } else EnrageTimer -= diff; + + if (BlackHoleSummonTimer <= diff) + { + Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!random) + return; + + DoCast(random, SPELL_DARKNESS_E, false); + + random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (!random) + return; + + random->CastSpell(random, SPELL_BLACKHOLE, false); + BlackHoleSummonTimer = 15000; + } else BlackHoleSummonTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_entropius(Creature* pCreature) +{ + return new boss_entropiusAI (pCreature); +} + +struct boss_muruAI : public Scripted_NoMovementAI +{ + boss_muruAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + SummonList Summons; + + uint8 Phase; + uint32 Timer[4]; + + bool DarkFiend; + + void Reset() + { + DarkFiend = false; + Phase = 1; + + EnrageTimer = 600000; + Timer[TIMER_DARKNESS] = 45000; + Timer[TIMER_HUMANOIDES] = 10000; + Timer[TIMER_PHASE] = 2000; + Timer[TIMER_SENTINEL] = 31500; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + Summons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoCastAOE(SPELL_NEGATIVE_ENERGY,false); + + if (pInstance) + pInstance->SetData(DATA_MURU_EVENT, IN_PROGRESS); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage > me->GetHealth() && Phase == 1) + { + damage = 0; + Phase = 2; + me->RemoveAllAuras(); + DoCast(me, SPELL_OPEN_ALL_PORTALS, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + if (Phase > 1 && Phase < 4) + damage = 0; + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + case BOSS_ENTROPIUS: + me->SetVisibility(VISIBILITY_OFF); + break; + case CREATURE_DARK_FIENDS: + summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false); + break; + } + summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); + Summons.Summon(summoned); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Phase == 3) + { + if (Timer[TIMER_PHASE] <= diff) + { + if (!pInstance) + return; + switch(pInstance->GetData(DATA_MURU_EVENT)) + { + case NOT_STARTED: + Reset(); + break; + case DONE: + Phase = 4; + me->DisappearAndDie(); + break; + } + Timer[TIMER_PHASE] = 3000; + } else Timer[TIMER_PHASE] -= diff; + return; + } + + if (EnrageTimer < diff && !me->HasAura(SPELL_ENRAGE, 0)) + { + DoCast(me, SPELL_ENRAGE, false); + } else EnrageTimer -= diff; + + for (uint8 i = 0; i < 4; ++i) + { + if (Timer[i] <= diff) + { + switch(i) + { + case TIMER_DARKNESS: + if (!DarkFiend) + { + DoCastAOE(SPELL_DARKNESS, false); + Timer[TIMER_DARKNESS] = 3000; + DarkFiend = true; + } + else + { + DarkFiend = false; + for (uint8 i = 0; i < 8; ++i) + me->SummonCreature(CREATURE_DARK_FIENDS,DarkFiends[i][0],DarkFiends[i][1],DarkFiends[i][2], DarkFiends[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + Timer[TIMER_DARKNESS] = 42000; + } + break; + case TIMER_HUMANOIDES: + for (uint8 i = 0; i < 6; ++i) + me->SummonCreature(Humanoides[i][0],Humanoides[i][1],Humanoides[i][2],Humanoides[i][3], Humanoides[i][4], TEMPSUMMON_CORPSE_DESPAWN, 0); + Timer[TIMER_HUMANOIDES] = 60000; + break; + case TIMER_PHASE: + me->RemoveAllAuras(); + DoCast(me, SPELL_SUMMON_ENTROPIUS, false); + Timer[TIMER_PHASE] = 3000; + Phase = 3; + return; + case TIMER_SENTINEL: + DoCastAOE(SPELL_OPEN_PORTAL_2, false); + Timer[TIMER_SENTINEL] = 30000; + break; + } + break; + } + } + + //Timer + for (uint8 i = 0; i < 4; ++i) + { + if (i != TIMER_PHASE)Timer[i] -= diff; + else if (Phase == 2) Timer[i] -= diff; + } + } +}; + +CreatureAI* GetAI_boss_muru(Creature* pCreature) +{ + return new boss_muruAI (pCreature); +} + +struct npc_muru_portalAI : public Scripted_NoMovementAI +{ + npc_muru_portalAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + SummonList Summons; + + bool SummonSentinel; + bool InAction; + + uint32 SummonTimer; + + void Reset() + { + SummonTimer = 5000; + + InAction = false; + SummonSentinel = false; + + me->addUnitState(UNIT_STAT_STUNNED); + + Summons.DespawnAll(); + } + + void JustSummoned(Creature* summoned) + { + if (pInstance) + if (Player* Target = Unit::GetPlayer(pInstance->GetData64(DATA_PLAYER_GUID))) + summoned->AI()->AttackStart(Target); + + Summons.Summon(summoned); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry* Spell) + { + float x,y,z,o; + me->GetHomePosition(x,y,z,o); + DoTeleportTo(x,y,z); + InAction = true; + switch(Spell->Id) + { + case SPELL_OPEN_ALL_PORTALS: + DoCastAOE(SPELL_OPEN_PORTAL, false); + break; + case SPELL_OPEN_PORTAL_2: + DoCastAOE(SPELL_OPEN_PORTAL, false); + SummonSentinel = true; + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!SummonSentinel) + { + if (InAction && pInstance && pInstance->GetData(DATA_MURU_EVENT) == NOT_STARTED) + Reset(); + return; + } + if (SummonTimer <= diff) + { + DoCastAOE(SPELL_SUMMON_VOID_SENTINEL, false); + SummonTimer = 5000; + SummonSentinel = false; + } else SummonTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_muru_portal(Creature* pCreature) +{ + return new npc_muru_portalAI (pCreature); +} + +struct npc_dark_fiendAI : public ScriptedAI +{ + npc_dark_fiendAI(Creature *c) : ScriptedAI(c) {} + + uint32 WaitTimer; + bool InAction; + + void Reset() + { + WaitTimer = 2000; + InAction = false; + + me->addUnitState(UNIT_STAT_STUNNED); + } + + void SpellHit(Unit* /*caster*/, const SpellEntry* Spell) + { + for (uint8 i = 0; i < 3; ++i) + if (Spell->Effect[i] == 38) + me->DisappearAndDie(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (WaitTimer <= diff) + { + if (!InAction) + { + me->clearUnitState(UNIT_STAT_STUNNED); + DoCastAOE(SPELL_DARKFIEND_SKIN, false); + AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)); + InAction = true; + WaitTimer = 500; + } + else + { + + if (me->IsWithinDist(me->getVictim(), 5)) + { + DoCastAOE(SPELL_DARKFIEND_AOE, false); + me->DisappearAndDie(); + } + WaitTimer = 500; + } + } else WaitTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_dark_fiend(Creature* pCreature) +{ + return new npc_dark_fiendAI (pCreature); +} + +struct npc_void_sentinelAI : public ScriptedAI +{ + npc_void_sentinelAI(Creature *c) : ScriptedAI(c){} + + uint32 PulseTimer; + uint32 VoidBlastTimer; + + void Reset() + { + PulseTimer = 3000; + VoidBlastTimer = 45000; //is this a correct timer? + + float x,y,z,o; + me->GetHomePosition(x,y,z,o); + DoTeleportTo(x,y,71); + } + + void JustDied(Unit* /*killer*/) + { + for (uint8 i = 0; i < 8; ++i) + me->SummonCreature(CREATURE_VOID_SPAWN, me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(), rand()%6, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (PulseTimer <= diff) + { + DoCastAOE(SPELL_SHADOW_PULSE, true); + PulseTimer = 3000; + } else PulseTimer -= diff; + + if (VoidBlastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_VOID_BLAST, false); + VoidBlastTimer = 45000; + } else VoidBlastTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_void_sentinel(Creature* pCreature) +{ + return new npc_void_sentinelAI (pCreature); +} + +struct npc_blackholeAI : public ScriptedAI +{ + npc_blackholeAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 DespawnTimer; + uint32 SpellTimer; + uint8 Phase; + uint8 NeedForAHack; + + void Reset() + { + DespawnTimer = 15000; + SpellTimer = 5000; + Phase = 0; + + me->addUnitState(UNIT_STAT_STUNNED); + DoCastAOE(SPELL_BLACKHOLE_SPAWN, true); + } + + void UpdateAI(const uint32 diff) + { + if (SpellTimer <= diff) + { + Unit* Victim = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); + switch (NeedForAHack) + { + case 0: + me->clearUnitState(UNIT_STAT_STUNNED); + DoCastAOE(SPELL_BLACKHOLE_GROW, false); + if (Victim) + AttackStart(Victim); + SpellTimer = 700; + NeedForAHack = 2; + break; + case 1: + me->AddAura(SPELL_BLACKHOLE_GROW, me); + NeedForAHack = 2; + SpellTimer = 600; + break; + case 2: + SpellTimer = 400; + NeedForAHack = 3; + me->RemoveAura(SPELL_BLACKHOLE_GROW, 1); + break; + case 3: + SpellTimer = urand(400,900); + NeedForAHack = 1; + if (Unit* Temp = me->getVictim()) + { + if (Temp->GetPositionZ() > 73 && Victim) + AttackStart(Victim); + } else + return; + } + } else SpellTimer -= diff; + + if (DespawnTimer <= diff) + me->DisappearAndDie(); + else DespawnTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_blackhole(Creature* pCreature) +{ + return new npc_blackholeAI (pCreature); +} + +void AddSC_boss_muru() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_muru"; + newscript->GetAI = &GetAI_boss_muru; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_entropius"; + newscript->GetAI = &GetAI_boss_entropius; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_muru_portal"; + newscript->GetAI = &GetAI_npc_muru_portal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dark_fiend"; + newscript->GetAI = &GetAI_npc_dark_fiend; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_void_sentinel"; + newscript->GetAI = &GetAI_npc_void_sentinel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_blackhole"; + newscript->GetAI = &GetAI_npc_blackhole; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp new file mode 100644 index 00000000000..94b7bf4b735 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp @@ -0,0 +1,297 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +/* ScriptData +SDName: Instance_Sunwell_Plateau +SD%Complete: 25 +SDComment: VERIFY SCRIPT +SDCategory: Sunwell_Plateau +EndScriptData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +#define MAX_ENCOUNTER 6 + +/* Sunwell Plateau: +0 - Kalecgos and Sathrovarr +1 - Brutallus +2 - Felmyst +3 - Eredar Twins (Alythess and Sacrolash) +4 - M'uru +5 - Kil'Jaeden +*/ + +struct instance_sunwell_plateau : public ScriptedInstance +{ + instance_sunwell_plateau(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + /** Creatures **/ + uint64 Kalecgos_Dragon; + uint64 Kalecgos_Human; + uint64 Sathrovarr; + uint64 Brutallus; + uint64 Madrigosa; + uint64 Felmyst; + uint64 Alythess; + uint64 Sacrolash; + uint64 Muru; + uint64 KilJaeden; + uint64 KilJaedenController; + uint64 Anveena; + uint64 KalecgosKJ; + uint32 SpectralPlayers; + + /** GameObjects **/ + uint64 ForceField; // Kalecgos Encounter + uint64 KalecgosWall[2]; + uint64 FireBarrier; // Felmysts Encounter + uint64 MurusGate[2]; // Murus Encounter + + /*** Misc ***/ + uint32 SpectralRealmTimer; + std::vector SpectralRealmList; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + /*** Creatures ***/ + Kalecgos_Dragon = 0; + Kalecgos_Human = 0; + Sathrovarr = 0; + Brutallus = 0; + Madrigosa = 0; + Felmyst = 0; + Alythess = 0; + Sacrolash = 0; + Muru = 0; + KilJaeden = 0; + KilJaedenController = 0; + Anveena = 0; + KalecgosKJ = 0; + SpectralPlayers = 0; + + /*** GameObjects ***/ + ForceField = 0; + FireBarrier = 0; + MurusGate[0] = 0; + MurusGate[1] = 0; + KalecgosWall[0] = 0; + KalecgosWall[1] = 0; + + /*** Misc ***/ + SpectralRealmTimer = 5000; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* plr = itr->getSource(); + if (plr && !plr->HasAura(45839,0)) + return plr; + } + } + + debug_log("TSCR: Instance Sunwell Plateau: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 24850: Kalecgos_Dragon = pCreature->GetGUID(); break; + case 24891: Kalecgos_Human = pCreature->GetGUID(); break; + case 24892: Sathrovarr = pCreature->GetGUID(); break; + case 24882: Brutallus = pCreature->GetGUID(); break; + case 24895: Madrigosa = pCreature->GetGUID(); break; + case 25038: Felmyst = pCreature->GetGUID(); break; + case 25166: Alythess = pCreature->GetGUID(); break; + case 25165: Sacrolash = pCreature->GetGUID(); break; + case 25741: Muru = pCreature->GetGUID(); break; + case 25315: KilJaeden = pCreature->GetGUID(); break; + case 25608: KilJaedenController = pCreature->GetGUID(); break; + case 26046: Anveena = pCreature->GetGUID(); break; + case 25319: KalecgosKJ = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 188421: ForceField = pGo->GetGUID(); break; + case 188523: KalecgosWall[0] = pGo->GetGUID(); break; + case 188524: KalecgosWall[0] = pGo->GetGUID(); break; + case 188075: + if (m_auiEncounter[2] == DONE) + HandleGameObject(NULL, true, pGo); + FireBarrier = pGo->GetGUID(); + break; + case 187990: MurusGate[0] = pGo->GetGUID(); break; + case 188118: + if (m_auiEncounter[4] == DONE) + HandleGameObject(NULL, true, pGo); + MurusGate[1]= pGo->GetGUID(); + break; + } + } + + uint32 GetData(uint32 id) + { + switch(id) + { + case DATA_KALECGOS_EVENT: return m_auiEncounter[0]; + case DATA_BRUTALLUS_EVENT: return m_auiEncounter[1]; + case DATA_FELMYST_EVENT: return m_auiEncounter[2]; + case DATA_EREDAR_TWINS_EVENT: return m_auiEncounter[3]; + case DATA_MURU_EVENT: return m_auiEncounter[4]; + case DATA_KILJAEDEN_EVENT: return m_auiEncounter[5]; + } + return 0; + } + + uint64 GetData64(uint32 id) + { + switch(id) + { + case DATA_KALECGOS_DRAGON: return Kalecgos_Dragon; + case DATA_KALECGOS_HUMAN: return Kalecgos_Human; + case DATA_SATHROVARR: return Sathrovarr; + case DATA_GO_FORCEFIELD: return ForceField; + case DATA_BRUTALLUS: return Brutallus; + case DATA_MADRIGOSA: return Madrigosa; + case DATA_FELMYST: return Felmyst; + case DATA_ALYTHESS: return Alythess; + case DATA_SACROLASH: return Sacrolash; + case DATA_MURU: return Muru; + case DATA_KILJAEDEN: return KilJaeden; + case DATA_KILJAEDEN_CONTROLLER: return KilJaedenController; + case DATA_ANVEENA: return Anveena; + case DATA_KALECGOS_KJ: return KalecgosKJ; + case DATA_PLAYER_GUID: + Player* Target = GetPlayerInMap(); + return Target->GetGUID(); + } + return 0; + } + + void SetData(uint32 id, uint32 data) + { + switch(id) + { + case DATA_KALECGOS_EVENT: + { + if (data == NOT_STARTED || data == DONE) + { + HandleGameObject(ForceField,true); + HandleGameObject(KalecgosWall[0],true); + HandleGameObject(KalecgosWall[1],true); + } + else if (data == IN_PROGRESS) + { + HandleGameObject(ForceField,false); + HandleGameObject(KalecgosWall[0],false); + HandleGameObject(KalecgosWall[1],false); + } + m_auiEncounter[0] = data; + } + break; + case DATA_BRUTALLUS_EVENT: m_auiEncounter[1] = data; break; + case DATA_FELMYST_EVENT: + if (data == DONE) + HandleGameObject(FireBarrier, true); + m_auiEncounter[2] = data; break; + case DATA_EREDAR_TWINS_EVENT: m_auiEncounter[3] = data; break; + case DATA_MURU_EVENT: + switch(data) + { + case DONE: + HandleGameObject(MurusGate[0], true); + HandleGameObject(MurusGate[1], true); + break; + case IN_PROGRESS: + HandleGameObject(MurusGate[0], false); + HandleGameObject(MurusGate[1], false); + break; + case NOT_STARTED: + HandleGameObject(MurusGate[0], true); + HandleGameObject(MurusGate[1], false); + break; + } + m_auiEncounter[4] = data; break; + case DATA_KILJAEDEN_EVENT: m_auiEncounter[5] = data; break; + } + + if (data == DONE) + SaveToDB(); + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " + << m_auiEncounter[4] << " " << m_auiEncounter[5]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_sunwell_plateau(Map* pMap) +{ + return new instance_sunwell_plateau(pMap); +} + +void AddSC_instance_sunwell_plateau() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_sunwell_plateau"; + newscript->GetInstanceData = &GetInstanceData_instance_sunwell_plateau; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.cpp new file mode 100644 index 00000000000..dbf67d5f26e --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.cpp @@ -0,0 +1,65 @@ +/* Copyright (C) 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Sunwell_Plateau +SD%Complete: 0 +SDComment: Placeholder, Epilogue after Kil'jaeden, Captain Selana Gossips +EndScriptData */ + +/* ContentData +npc_prophet_velen +npc_captain_selana +EndContentData */ + +#include "ScriptedPch.h" +#include "sunwell_plateau.h" + +/*###### +## npc_prophet_velen +######*/ + +enum ProphetSpeeches +{ + PROPHET_SAY1 = -1580099, + PROPHET_SAY2 = -1580100, + PROPHET_SAY3 = -1580101, + PROPHET_SAY4 = -1580102, + PROPHET_SAY5 = -1580103, + PROPHET_SAY6 = -1580104, + PROPHET_SAY7 = -1580105, + PROPHET_SAY8 = -1580106 +}; + +enum LiadrinnSpeeches +{ + LIADRIN_SAY1 = -1580107, + LIADRIN_SAY2 = -1580108, + LIADRIN_SAY3 = -1580109 +}; + +/*###### +## npc_captain_selana +######*/ + +#define CS_GOSSIP1 "Give me a situation report, Captain." +#define CS_GOSSIP2 "What went wrong?" +#define CS_GOSSIP3 "Why did they stop?" +#define CS_GOSSIP4 "Your insight is appreciated." + +void AddSC_sunwell_plateau() +{ +} diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h new file mode 100644 index 00000000000..9f1a2480c96 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SUNWELLPLATEAU_H +#define DEF_SUNWELLPLATEAU_H + +/*** Encounters ***/ +enum Data +{ + DATA_KALECGOS_EVENT, + DATA_BRUTALLUS_EVENT, + DATA_FELMYST_EVENT, + DATA_EREDAR_TWINS_EVENT, + DATA_MURU_EVENT, + DATA_KILJAEDEN_EVENT, +}; + +enum Data64 +{ + /*** Creatures ***/ + DATA_KALECGOS_DRAGON, + DATA_KALECGOS_HUMAN, + DATA_SATHROVARR, + DATA_BRUTALLUS, + DATA_MADRIGOSA, + DATA_FELMYST, + DATA_ALYTHESS, + DATA_SACROLASH, + DATA_MURU, + DATA_KILJAEDEN, + DATA_KILJAEDEN_CONTROLLER, + DATA_ANVEENA, + DATA_KALECGOS_KJ, + + /*** GameObjects ***/ + DATA_GO_FORCEFIELD, + DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1, + DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2, + DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3, + DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4, + + /*** Misc ***/ + DATA_PLAYER_GUID, +}; + +enum Creatures +{ + BOSS_MURU = 25741, + BOSS_ENTROPIUS = 25840, + MOB_KALECGOS = 24850, + MOB_KALEC = 24891, + MOB_SATHROVARR = 24892, + + MOB_DEAD = 25268, + MOB_FLIGHT_LEFT = 25357, + MOB_FLIGHT_RIGHT = 25358, + MOB_DEATH_CLOUD = 25703, + MOB_VAPOR = 25265, + MOB_VAPOR_TRAIL = 25267, + + MOB_GRAND_WARLOCK_ALYTHESS = 25166, + MOB_SHADOW_IMAGE = 25214, + MOB_LADY_SACROLASH = 25165, + + CREATURE_ANVEENA = 26046, // Embodiment of the Sunwell + CREATURE_KALECGOS = 25319, // Helps the raid throughout the fight + CREATURE_PROPHET = 26246, // Outro + CREATURE_KILJAEDEN = 25315, // Give it to 'em KJ! + CREATURE_HAND_OF_THE_DECEIVER = 25588, // Adds found before KJ emerges + CREATURE_FELFIRE_PORTAL = 25603, // Portal spawned be Hand of the Deceivers + CREATURE_VOLATILE_FELFIRE_FIEND = 25598, // Fiends spawned by the above portal + CREATURE_ARMAGEDDON_TARGET = 25735, // This mob casts meteor on itself.. I think + CREATURE_SHIELD_ORB = 25502, // Shield orbs circle the room raining shadow bolts on raid + CREATURE_THE_CORE_OF_ENTROPIUS = 26262, // Used in the ending cinematic? + CREATURE_POWER_OF_THE_BLUE_DRAGONFLIGHT = 25653, // NPC that players possess when using the Orb of the Blue Dragonflight + CREATURE_SPIKE_TARGET1 = 30598, // Should summon these under Shadow Spike Channel on targets place + CREATURE_SPIKE_TARGET2 = 30614, + CREATURE_SINISTER_REFLECTION = 25708, // Sinister Relection spawnd on Phase swichtes + + CREATURE_DARKNESS = 25879, + CREATURE_DARK_FIENDS = 25744, + CREATURE_BERSERKER = 25798, + CREATURE_FURY_MAGE = 25799, + CREATURE_VOID_SENTINEL = 25772, + CREATURE_VOID_SPAWN = 25824, + CREATURE_BLACK_HOLE = 25855, +}; + +enum GameObjects +{ + GAMEOBJECT_ORB_OF_THE_BLUE_DRAGONFLIGHT = 188415, +}; + +#endif diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp new file mode 100644 index 00000000000..cd3bc5fc219 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp @@ -0,0 +1,497 @@ +/* Copyright (C) 2006,2007 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_archaedas +SD%Complete: 100 +SDComment: Archaedas is activated when 1 person (was 3, changed in 3.0.8) clicks on his altar. +Every 10 seconds he will awaken one of his minions along the wall. +At 66%, he will awaken the 6 Guardians. +At 33%, he will awaken the Vault Walkers +On his death the vault door opens. +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO "Who dares awaken Archaedas? Who dares the wrath of the makers!" +#define SOUND_AGGRO 5855 + +#define SAY_SUMMON "Awake ye servants, defend the discs!" +#define SOUND_SUMMON 5856 + +#define SAY_SUMMON2 "To my side, brothers. For the makers!" +#define SOUND_SUMMON2 5857 + +#define SAY_KILL "Reckless mortal." +#define SOUND_KILL 5858 + +#define SPELL_GROUND_TREMOR 6524 +#define SPELL_ARCHAEDAS_AWAKEN 10347 +#define SPELL_BOSS_OBJECT_VISUAL 11206 +#define SPELL_BOSS_AGGRO 10340 +#define SPELL_SUB_BOSS_AGGRO 11568 +#define SPELL_AWAKEN_VAULT_WALKER 10258 +#define SPELL_AWAKEN_EARTHEN_GUARDIAN 10252 + +struct boss_archaedasAI : public ScriptedAI +{ + boss_archaedasAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + uint32 Tremor_Timer; + int32 Awaken_Timer; + uint32 WallMinionTimer; + bool wakingUp; + + bool guardiansAwake; + bool vaultWalkersAwake; + ScriptedInstance* pInstance; + + void Reset() + { + Tremor_Timer = 60000; + Awaken_Timer = 0; + WallMinionTimer = 10000; + + wakingUp = false; + guardiansAwake = false; + vaultWalkersAwake = false; + + if (pInstance) + pInstance->SetData (NULL, 5); // respawn any dead minions + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + } + + void ActivateMinion (uint64 guid, bool flag) + { + Unit *minion = Unit::GetUnit(*me, guid); + + if (minion && minion->isAlive()) + { + DoCast (minion, SPELL_AWAKEN_VAULT_WALKER, flag); + minion->CastSpell(minion, SPELL_ARCHAEDAS_AWAKEN,true); + } + } + + void EnterCombat(Unit * /*who*/) + { + me->setFaction (14); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); + } + + void SpellHit (Unit* /*caster*/, const SpellEntry *spell) + { + // Being woken up from the altar, start the awaken sequence + if (spell == GetSpellStore()->LookupEntry(SPELL_ARCHAEDAS_AWAKEN)) { + me->MonsterYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_AGGRO); + Awaken_Timer = 4000; + wakingUp = true; + } + } + + void KilledUnit(Unit * /*victim*/) + { + me->MonsterYell(SAY_KILL,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + // we're still doing awaken animation + if (wakingUp && Awaken_Timer >= 0) { + Awaken_Timer -= diff; + return; // dont do anything until we are done + } else if (wakingUp && Awaken_Timer <= 0) { + wakingUp = false; + AttackStart(Unit::GetUnit(*me, pInstance->GetData64(0))); + return; // dont want to continue until we finish the AttackStart method + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + // wake a wall minion + if (WallMinionTimer <= diff) { + pInstance->SetData (NULL, 2); + + WallMinionTimer = 10000; + } else WallMinionTimer -= diff; + + //If we are <66 summon the guardians + if (!guardiansAwake && me->GetHealth()*100 / me->GetMaxHealth() <= 66) { + ActivateMinion(pInstance->GetData64(5),true); // EarthenGuardian1 + ActivateMinion(pInstance->GetData64(6),true); // EarthenGuardian2 + ActivateMinion(pInstance->GetData64(7),true); // EarthenGuardian3 + ActivateMinion(pInstance->GetData64(8),true); // EarthenGuardian4 + ActivateMinion(pInstance->GetData64(9),true); // EarthenGuardian5 + ActivateMinion(pInstance->GetData64(10),false); // EarthenGuardian6 + me->MonsterYell(SAY_SUMMON,LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_SUMMON); + guardiansAwake = true; + } + + //If we are <33 summon the vault walkers + if (!vaultWalkersAwake && me->GetHealth()*100 / me->GetMaxHealth() <= 33) { + ActivateMinion(pInstance->GetData64(1),true); // VaultWalker1 + ActivateMinion(pInstance->GetData64(2),true); // VaultWalker2 + ActivateMinion(pInstance->GetData64(3),true); // VaultWalker3 + ActivateMinion(pInstance->GetData64(4),false); // VaultWalker4 + me->MonsterYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_SUMMON2); + vaultWalkersAwake = true; + } + + if (Tremor_Timer <= diff) + { + //Cast + DoCast(me->getVictim(), SPELL_GROUND_TREMOR); + + //45 seconds until we should cast this agian + Tremor_Timer = 45000; + } else Tremor_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied (Unit * /*killer*/) { + if (pInstance) + { + pInstance->SetData(NULL,3); // open the vault door + pInstance->SetData(NULL,4); // deactivate his minions + } + } + +}; + +CreatureAI* GetAI_boss_archaedas(Creature* pCreature) +{ + return new boss_archaedasAI (pCreature); +} + +/* ScriptData +SDName: mob_archaedas_minions +SD%Complete: 100 +SDComment: These mobs are initially frozen until Archaedas awakens them +one at a time. +EndScriptData */ + +#define SPELL_ARCHAEDAS_AWAKEN 10347 + +struct mob_archaedas_minionsAI : public ScriptedAI +{ + mob_archaedas_minionsAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + uint32 Arcing_Timer; + int32 Awaken_Timer; + bool wakingUp; + + bool amIAwake; + ScriptedInstance* pInstance; + + void Reset() + { + Arcing_Timer = 3000; + Awaken_Timer = 0; + + wakingUp = false; + amIAwake = false; + + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveAllAuras(); + } + + void EnterCombat(Unit * /*who*/) + { + me->setFaction (14); + me->RemoveAllAuras(); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + amIAwake = true; + } + + void SpellHit (Unit* /*caster*/, const SpellEntry *spell) { + // time to wake up, start animation + if (spell == GetSpellStore()->LookupEntry(SPELL_ARCHAEDAS_AWAKEN)){ + Awaken_Timer = 5000; + wakingUp = true; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (amIAwake) + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + // we're still in the awaken animation + if (wakingUp && Awaken_Timer >= 0) { + Awaken_Timer -= diff; + return; // dont do anything until we are done + } else if (wakingUp && Awaken_Timer <= 0) { + wakingUp = false; + amIAwake = true; + // AttackStart(Unit::GetUnit(*me, pInstance->GetData64(0))); // whoWokeArchaedasGUID + return; // dont want to continue until we finish the AttackStart method + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_archaedas_minions(Creature* pCreature) +{ + return new mob_archaedas_minionsAI (pCreature); +} + +/* ScriptData +SDName: go_altar_archaedas +SD%Complete: 100 +SDComment: Needs 1 person to activate the Archaedas script +SDCategory: Uldaman +EndScriptData */ + +#define OBJECT_ALTAR_OF_ARCHAEDAS 133234 + +#define NUMBER_NEEDED_TO_ACTIVATE 1 // as of patch 3.0.8 the altars can be opened by a single player (previously 3) + +#define SPELL_BOSS_OBJECT_VISUAL 11206 + +//uint64 altarOfArchaedasCount[5]; +//int32 altarOfArchaedasCounter=0; + +bool GOHello_go_altar_of_archaedas(Player* pPlayer, GameObject* /*pGo*/) +{ + //bool alreadyUsed; + //pGo->AddUse (); + + /* + alreadyUsed = false; + for (uint32 loop=0; loop<5; loop++) { + if (altarOfArchaedasCount[loop] == pPlayer->GetGUID()) alreadyUsed = true; + } + if (!alreadyUsed) + altarOfArchaedasCount[altarOfArchaedasCounter++] = pPlayer->GetGUID(); + */ + + pPlayer->CastSpell (pPlayer, SPELL_BOSS_OBJECT_VISUAL, false); + + /* + if (altarOfArchaedasCounter < NUMBER_NEEDED_TO_ACTIVATE) + return false; // not enough people yet + + // Check to make sure at least three people are still casting + uint8 count = 0; + Unit *pTarget; + for (uint8 x = 0; x <= 5; ++x) + { + pTarget = Unit::GetUnit(*pPlayer, altarOfArchaedasCount[x]); + if (!pTarget) + continue; + if (pTarget->IsNonMeleeSpellCasted(true)) + ++count; + if (count >= NUMBER_NEEDED_TO_ACTIVATE) + break; + } + + if (count < NUMBER_NEEDED_TO_ACTIVATE) + return false; // not enough people + */ + + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (!pInstance) + return false; + + pInstance->SetData(NULL,0); + pInstance->SetData64(0,pPlayer->GetGUID()); // activate archaedas + + return false; +} + +/* ScriptData +SDName: mob_stonekeepers +SD%Complete: 100 +SDComment: After activating the altar of the keepers, the stone keepers will +wake up one by one. +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_SELF_DESTRUCT 9874 + +struct mob_stonekeepersAI : public ScriptedAI +{ + mob_stonekeepersAI(Creature *c) : ScriptedAI(c) + { + pInstance = (me->GetInstanceData()); + } + + ScriptedInstance* pInstance; + + void Reset() + { + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveAllAuras(); + } + + void EnterCombat(Unit * /*who*/) + { + me->setFaction (14); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + + void UpdateAI(const uint32 /*diff*/) + { + + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit * /*attacker*/) + { + DoCast (me, SPELL_SELF_DESTRUCT,true); + if (pInstance) + pInstance->SetData(NULL, 1); // activate next stonekeeper + } + +}; + +CreatureAI* GetAI_mob_stonekeepers(Creature* pCreature) +{ + return new mob_stonekeepersAI (pCreature); +} + +/* ScriptData +SDName: go_altar_of_the_keepers +SD%Complete: 100 +SDComment: Need 1 person to activate to open the altar. One by one the StoneKeepers will activate. After all four are dead than the door will open. +SDCategory: Uldaman +EndScriptData */ + +#define SPELL_BOSS_OBJECT_VISUAL 11206 + +#define NUMBER_NEEDED_TO_ACTIVATE 1 // as of patch 3.0.8 the altars can be opened by a single player (previously 3) + +//static uint64 altarOfTheKeeperCount[5]; +//static uint32 altarOfTheKeeperCounter=0; + +bool GOHello_go_altar_of_the_keepers(Player* pPlayer, GameObject* /*pGo*/) +{ + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (!pInstance) + return true; + + //bool alreadyUsed; + + //pGo->AddUse(); + + //alreadyUsed = false; + //for (uint32 loop=0; loop<5; ++loop) + //{ + // if (altarOfTheKeeperCount[loop] == pPlayer->GetGUID()) + //alreadyUsed = true; + //} + //if (!alreadyUsed && altarOfTheKeeperCounter < 5) + // altarOfTheKeeperCount[altarOfTheKeeperCounter++] = pPlayer->GetGUID(); + pPlayer->CastSpell (pPlayer, SPELL_BOSS_OBJECT_VISUAL, false); + + //if (altarOfTheKeeperCounter < NUMBER_NEEDED_TO_ACTIVATE) + //{ + //error_log("not enough people yet, altarOfTheKeeperCounter = %d", altarOfTheKeeperCounter); + // return false; // not enough people yet + //} +/* + // Check to make sure at least three people are still casting + uint8 count = 0; + Unit *pTarget; + for (uint8 x = 0; x < 5; ++x) + { + pTarget = Unit::GetUnit(*pPlayer, altarOfTheKeeperCount[x]); + //error_log("number of people currently activating it: %d", x+1); + if (!pTarget) + continue; + if (pTarget->IsNonMeleeSpellCasted(true)) + ++count; + if (count >= NUMBER_NEEDED_TO_ACTIVATE) + break; + } + + if (count < NUMBER_NEEDED_TO_ACTIVATE) + { + //error_log("still not enough people"); + return true; // not enough people + } +*/ + //error_log ("activating stone keepers"); + pInstance->SetData(NULL,1); // activate the Stone Keepers + return true; +} + +void AddSC_boss_archaedas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_archaedas"; + newscript->GetAI = &GetAI_boss_archaedas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_altar_of_archaedas"; + newscript->pGOHello = &GOHello_go_altar_of_archaedas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_archaedas_minions"; + newscript->GetAI = &GetAI_mob_archaedas_minions; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_altar_of_the_keepers"; + newscript->pGOHello = &GOHello_go_altar_of_the_keepers; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stonekeepers"; + newscript->GetAI = &GetAI_mob_stonekeepers; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp new file mode 100644 index 00000000000..9b6d5dba642 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp @@ -0,0 +1,106 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ironaya +SD%Complete: 100 +SDComment: +SDCategory: Uldaman +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1070000 + +#define SPELL_ARCINGSMASH 8374 +#define SPELL_KNOCKAWAY 10101 +#define SPELL_WSTOMP 11876 + +struct boss_ironayaAI : public ScriptedAI +{ + boss_ironayaAI(Creature *c) : ScriptedAI(c) {} + + uint32 Arcing_Timer; + bool hasCastedWstomp; + bool hasCastedKnockaway; + + void Reset() + { + Arcing_Timer = 3000; + hasCastedKnockaway = false; + hasCastedWstomp = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //If we are <50% hp do knockaway ONCE + if (!hasCastedKnockaway && me->GetHealth()*2 < me->GetMaxHealth()) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); + + // current aggro target is knocked away pick new target + Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!Target || Target == me->getVictim()) + Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + + if (Target) + me->TauntApply(Target); + + //Shouldn't cast this agian + hasCastedKnockaway = true; + } + + //Arcing_Timer + if (Arcing_Timer <= diff) + { + DoCast(me, SPELL_ARCINGSMASH); + Arcing_Timer = 13000; + } else Arcing_Timer -= diff; + + if (!hasCastedWstomp && me->GetHealth()*4 < me->GetMaxHealth()) + { + DoCast(me, SPELL_WSTOMP); + hasCastedWstomp = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ironaya(Creature* pCreature) +{ + return new boss_ironayaAI (pCreature); +} + +void AddSC_boss_ironaya() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ironaya"; + newscript->GetAI = &GetAI_boss_ironaya; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp new file mode 100644 index 00000000000..a519ad678b7 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp @@ -0,0 +1,300 @@ +/* Copyright (C) 2006,2007 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" + +#define SPELL_ARCHAEDAS_AWAKEN 10347 +#define SPELL_AWAKEN_VAULT_WALKER 10258 + +#define ARCHAEDAS_TEMPLE_DOOR 141869 +#define ALTAR_OF_ARCHAEDAS 133234 + +#define ALTAR_OF_THE_KEEPER_TEMPLE_DOOR 124367 +#define ALTAR_OF_THE_KEEPER_TEMPLE 130511 + +#define ANCIENT_VAULT_DOOR 124369 + +struct instance_uldaman : public ScriptedInstance +{ + instance_uldaman(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + }; + + void Initialize() + { + archaedasGUID = 0; + altarOfTheKeeperTempleDoor = 0; + archaedasTempleDoor = 0; + ancientVaultDoor = 0; + whoWokeArchaedasGUID = 0; + } + + uint64 archaedasGUID; + uint64 altarOfTheKeeperTempleDoor; + uint64 archaedasTempleDoor; + uint64 ancientVaultDoor; + uint64 whoWokeArchaedasGUID; + + std::vector stoneKeeper; + std::vector altarOfTheKeeperCount; + std::vector vaultWalker; + std::vector earthenGuardian; + std::vector archaedasWallMinions; // minions lined up around the wall + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch (pGo->GetEntry()) + { + case ALTAR_OF_THE_KEEPER_TEMPLE_DOOR: // lock the door + altarOfTheKeeperTempleDoor = pGo->GetGUID(); + break; + + case ARCHAEDAS_TEMPLE_DOOR: + archaedasTempleDoor = pGo->GetGUID(); + break; + + case ANCIENT_VAULT_DOOR: + pGo->SetGoState(GO_STATE_READY); + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33); + ancientVaultDoor = pGo->GetGUID(); + break; + } + } + + void SetFrozenState(Creature* pCreature) + { + pCreature->setFaction(35); + pCreature->RemoveAllAuras(); + //creature->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_ANIMATION_FROZEN); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + + void OpenDoor(uint64 guid) + { + GameObject* pGo = instance->GetGameObject(guid); + if (!pGo) + return; + + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33); + pGo->SetGoState(GO_STATE_ACTIVE); + } + + void ActivateStoneKeepers() + { + for (std::vector::const_iterator i = stoneKeeper.begin(); i != stoneKeeper.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || !pTarget->isAlive() || pTarget->getFaction() == 14) + continue; + pTarget->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); + pTarget->setFaction(14); + pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + return; // only want the first one we find + } + // if we get this far than all four are dead so open the door + SetData (NULL, 0); + } + + void ActivateWallMinions() + { + Creature *archaedas = instance->GetCreature(archaedasGUID); + if (!archaedas) + return; + + for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || !pTarget->isAlive() || pTarget->getFaction() == 14) + continue; + archaedas->CastSpell(pTarget, SPELL_AWAKEN_VAULT_WALKER, true); + pTarget->CastSpell(pTarget, SPELL_ARCHAEDAS_AWAKEN,true); + return; // only want the first one we find + } + } + + // used when Archaedas dies. All active minions must be despawned. + void DeActivateMinions() + { + // first despawn any aggroed wall minions + for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) + continue; + pTarget->setDeathState(JUST_DIED); + pTarget->RemoveCorpse(); + } + + // Vault Walkers + for (std::vector::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) + continue; + pTarget->setDeathState(JUST_DIED); + pTarget->RemoveCorpse(); + } + + // Earthen Guardians + for (std::vector::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) + continue; + pTarget->setDeathState(JUST_DIED); + pTarget->RemoveCorpse(); + } + } + + void ActivateArchaedas(uint64 target) + { + Creature *archaedas = instance->GetCreature(archaedasGUID); + if (!archaedas) + return; + + if (Unit *victim = Unit::GetUnit(*archaedas, target)) + { + archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN,false); + whoWokeArchaedasGUID = target; + } + } + + void RespawnMinions() + { + // first respawn any aggroed wall minions + for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (pTarget && pTarget->isDead()) + { + pTarget->Respawn(); + pTarget->GetMotionMaster()->MoveTargetedHome(); + SetFrozenState(pTarget); + } + } + + // Vault Walkers + for (std::vector::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (pTarget && pTarget->isDead()) + { + pTarget->Respawn(); + pTarget->GetMotionMaster()->MoveTargetedHome(); + SetFrozenState(pTarget); + } + } + + // Earthen Guardians + for (std::vector::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i) + { + Creature *pTarget = instance->GetCreature(*i); + if (pTarget && pTarget->isDead()) + { + pTarget->Respawn(); + pTarget->GetMotionMaster()->MoveTargetedHome(); + SetFrozenState(pTarget); + } + } + } + + void SetData (uint32 /*type*/, uint32 data) + { + //error_log ("SetData: data = %d", data); + if (data == 0) OpenDoor (altarOfTheKeeperTempleDoor); + if (data == 0) OpenDoor (archaedasTempleDoor); + if (data == 3) OpenDoor (ancientVaultDoor); + if (data == 1) ActivateStoneKeepers(); + if (data == 2) ActivateWallMinions(); + if (data == 4) DeActivateMinions(); + if (data == 5) RespawnMinions(); + } + + void SetData64 (uint32 type, uint64 data) + { + // Archaedas + if (type == 0) + { + ActivateArchaedas (data); + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) { + case 4857: // Stone Keeper + SetFrozenState (pCreature); + stoneKeeper.push_back(pCreature->GetGUID()); + break; + + case 7309: // Earthen Custodian + archaedasWallMinions.push_back(pCreature->GetGUID()); + break; + + case 7077: // Earthen Hallshaper + archaedasWallMinions.push_back(pCreature->GetGUID()); + break; + + case 7076: // Earthen Guardian + earthenGuardian.push_back(pCreature->GetGUID()); + break; + + case 10120: // Vault Walker + vaultWalker.push_back(pCreature->GetGUID()); + break; + + case 2748: // Archaedas + archaedasGUID = pCreature->GetGUID(); + break; + + } // end switch + } // end OnCreatureCreate + + uint64 GetData64 (uint32 identifier) + { + if (identifier == 0) return whoWokeArchaedasGUID; + if (identifier == 1) return vaultWalker[0]; // VaultWalker1 + if (identifier == 2) return vaultWalker[1]; // VaultWalker2 + if (identifier == 3) return vaultWalker[2]; // VaultWalker3 + if (identifier == 4) return vaultWalker[3]; // VaultWalker4 + + if (identifier == 5) return earthenGuardian[0]; + if (identifier == 6) return earthenGuardian[1]; + if (identifier == 7) return earthenGuardian[2]; + if (identifier == 8) return earthenGuardian[3]; + if (identifier == 9) return earthenGuardian[4]; + if (identifier == 10) return earthenGuardian[5]; + + return 0; + } // end GetData64 +}; + +InstanceData* GetInstanceData_instance_uldaman(Map* pMap) +{ + return new instance_uldaman(pMap); +} + +void AddSC_instance_uldaman() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_uldaman"; + newscript->GetInstanceData = &GetInstanceData_instance_uldaman; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp new file mode 100644 index 00000000000..2bd8387efa5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Uldaman +SD%Complete: 100 +SDComment: Quest support: 2278 + 1 trash mob. +SDCategory: Uldaman +EndScriptData */ + +/* ContentData +mob_jadespine_basilisk +npc_lore_keeper_of_norgannon +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## mob_jadespine_basilisk +######*/ + +#define SPELL_CSLUMBER 3636 + +struct mob_jadespine_basiliskAI : public ScriptedAI +{ + mob_jadespine_basiliskAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cslumber_Timer; + + void Reset() + { + Cslumber_Timer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Cslumber_Timer + if (Cslumber_Timer <= diff) + { + //Cast + // DoCast(me->getVictim(), SPELL_CSLUMBER); + DoCast(me->getVictim(), SPELL_CSLUMBER, true); + + //Stop attacking target thast asleep and pick new target + Cslumber_Timer = 28000; + + Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!Target || Target == me->getVictim()) + Target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + + if (Target) + me->TauntApply(Target); + + } else Cslumber_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_jadespine_basilisk(Creature* pCreature) +{ + return new mob_jadespine_basiliskAI (pCreature); +} + +/*###### +## npc_lore_keeper_of_norgannon +######*/ + +#define GOSSIP_HELLO_KEEPER "Who are the Earthen?" +#define GOSSIP_SELECT_KEEPER1 "What is a \"subterranean being matrix\"?" +#define GOSSIP_SELECT_KEEPER2 "What are the anomalies you speak of?" +#define GOSSIP_SELECT_KEEPER3 "What is a resilient foundation of construction?" +#define GOSSIP_SELECT_KEEPER4 "So... the Earthen were made out of stone?" +#define GOSSIP_SELECT_KEEPER5 "Anything else I should know about the Earthen?" +#define GOSSIP_SELECT_KEEPER6 "I think I understand the Creators' design intent for the Earthen now. What are the Earthen's anomalies that you spoke of earlier?" +#define GOSSIP_SELECT_KEEPER7 "What high-stress environments would cause the Earthen to destabilize?" +#define GOSSIP_SELECT_KEEPER8 "What happens when the Earthen destabilize?" +#define GOSSIP_SELECT_KEEPER9 "Troggs?! Are the troggs you mention the same as the ones in the world today?" +#define GOSSIP_SELECT_KEEPER10 "You mentioned two results when the Earthen destabilize. What is the second?" +#define GOSSIP_SELECT_KEEPER11 "Dwarves!!! Now you're telling me that dwarves originally came from the Earthen?!" +#define GOSSIP_SELECT_KEEPER12 "These dwarves are the same ones today, yes? Do the dwarves maintain any other links to the Earthen?" +#define GOSSIP_SELECT_KEEPER13 "Who are the Creators?" +#define GOSSIP_SELECT_KEEPER14 "This is a lot to think about." +#define GOSSIP_SELECT_KEEPER15 "I will access the discs now." + +bool GossipHello_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(2278) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KEEPER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(1079, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(1080, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(1081, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(1082, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(1083, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + pPlayer->SEND_GOSSIP_MENU(1084, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + pPlayer->SEND_GOSSIP_MENU(1085, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+7: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); + pPlayer->SEND_GOSSIP_MENU(1086, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+8: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); + pPlayer->SEND_GOSSIP_MENU(1087, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+9: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); + pPlayer->SEND_GOSSIP_MENU(1088, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+10: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+11); + pPlayer->SEND_GOSSIP_MENU(1089, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+11: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+12); + pPlayer->SEND_GOSSIP_MENU(1090, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+12: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+13); + pPlayer->SEND_GOSSIP_MENU(1091, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+13: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+14); + pPlayer->SEND_GOSSIP_MENU(1092, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+14: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+15); + pPlayer->SEND_GOSSIP_MENU(1093, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+15: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+16); + pPlayer->SEND_GOSSIP_MENU(1094, pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+16: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->AreaExploredOrEventHappens(2278); + break; + } + return true; +} + +void AddSC_uldaman() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_jadespine_basilisk"; + newscript->GetAI = &GetAI_mob_jadespine_basilisk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lore_keeper_of_norgannon"; + newscript->pGossipHello = &GossipHello_npc_lore_keeper_of_norgannon; + newscript->pGossipSelect = &GossipSelect_npc_lore_keeper_of_norgannon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp new file mode 100644 index 00000000000..f516065cc03 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp @@ -0,0 +1,467 @@ +/* Copyright ?2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_Akilzon +SD%Complete: 75% +SDComment: Missing timer for Call Lightning and Sound ID's +SQLUpdate: +#Temporary fix for Soaring Eagles + +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" +#include "Weather.h" + +#define SPELL_STATIC_DISRUPTION 43622 +#define SPELL_STATIC_VISUAL 45265 +#define SPELL_CALL_LIGHTNING 43661 //Missing timer +#define SPELL_GUST_OF_WIND 43621 +#define SPELL_ELECTRICAL_STORM 43648 +#define SPELL_BERSERK 45078 +#define SPELL_ELECTRICAL_DAMAGE 43657 +#define SPELL_ELECTRICAL_OVERLOAD 43658 +#define SPELL_EAGLE_SWOOP 44732 + +//"Your death gonna be quick, strangers. You shoulda never have come to this place..." +#define SAY_ONAGGRO "I be da predator! You da prey..." +#define SAY_ONDEATH "You can't... kill... me spirit!" +#define SAY_ONSLAY1 "Ya got nothin'!" +#define SAY_ONSLAY2 "Stop your cryin'!" +#define SAY_ONSUMMON "Feed, me bruddahs!" +#define SAY_ONENRAGE "All you be doing is wasting my time!" +#define SOUND_ONAGGRO 12013 +#define SOUND_ONDEATH 12019 +#define SOUND_ONSLAY1 12017 +#define SOUND_ONSLAY2 12018 +#define SOUND_ONSUMMON 12014 +#define SOUND_ONENRAGE 12016 + +#define MOB_SOARING_EAGLE 24858 +#define SE_LOC_X_MAX 400 +#define SE_LOC_X_MIN 335 +#define SE_LOC_Y_MAX 1435 +#define SE_LOC_Y_MIN 1370 + +struct boss_akilzonAI : public ScriptedAI +{ + boss_akilzonAI(Creature *c) : ScriptedAI(c) + { + SpellEntry *TempSpell = GET_SPELL(SPELL_ELECTRICAL_DAMAGE); + if (TempSpell) + TempSpell->EffectBasePoints[1] = 49;//disable bugged lightning until fixed in core + pInstance = c->GetInstanceData(); + } + ScriptedInstance *pInstance; + + uint64 BirdGUIDs[8]; + uint64 TargetGUID; + uint64 CycloneGUID; + uint64 CloudGUID; + + uint32 StaticDisruption_Timer; + uint32 GustOfWind_Timer; + uint32 CallLighting_Timer; + uint32 ElectricalStorm_Timer; + uint32 SummonEagles_Timer; + uint32 Enrage_Timer; + + uint32 StormCount; + uint32 StormSequenceTimer; + + bool isRaining; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_AKILZONEVENT, NOT_STARTED); + + StaticDisruption_Timer = urand(10000,20000); //10 to 20 seconds (bosskillers) + GustOfWind_Timer = urand(20000,30000); //20 to 30 seconds(bosskillers) + CallLighting_Timer = urand(10000,20000); //totaly random timer. can't find any info on this + ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) + Enrage_Timer = 10*MINUTE*IN_MILISECONDS; //10 minutes till enrage(bosskillers) + SummonEagles_Timer = 99999; + + TargetGUID = 0; + CloudGUID = 0; + CycloneGUID = 0; + DespawnSummons(); + for (uint8 i = 0; i < 8; ++i) + BirdGUIDs[i] = 0; + + StormCount = 0; + StormSequenceTimer = 0; + + isRaining = false; + + SetWeather(WEATHER_STATE_FINE, 0.0f); + } + + void EnterCombat(Unit * /*who*/) + { + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + //DoZoneInCombat(); + if (pInstance) + pInstance->SetData(DATA_AKILZONEVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*Killer*/) + { + me->MonsterYell(SAY_ONDEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me, SOUND_ONDEATH); + if (pInstance) + pInstance->SetData(DATA_AKILZONEVENT, DONE); + DespawnSummons(); + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,1)) + { + case 0: + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONSLAY1); + break; + case 1: + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONSLAY2); + break; + } + } + + void DespawnSummons() + { + for (uint8 i = 0; i < 8; ++i) + { + Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]); + if (bird && bird->isAlive()) + { + bird->SetVisibility(VISIBILITY_OFF); + bird->setDeathState(JUST_DIED); + } + } + } + + void SetWeather(uint32 weather, float grade) + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) + return; + + WorldPacket data(SMSG_WEATHER, (4+4+4)); + data << uint32(weather) << float(grade) << uint8(0); + + pMap->SendToPlayers(&data); + } + + void HandleStormSequence(Unit *Cloud) // 1: begin, 2-9: tick, 10: end + { + if (StormCount < 10 && StormCount > 1) + { + // deal damage + int32 bp0 = 800; + for (uint8 i = 2; i < StormCount; ++i) + bp0 *= 2; + + CellPair p(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list tempUnitMap; + + { + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, 999); + Trinity::UnitListSearcher searcher(me, tempUnitMap, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + cell.Visit(p, world_unit_searcher, *(me->GetMap())); + cell.Visit(p, grid_unit_searcher, *(me->GetMap())); + } + //dealdamege + for (std::list::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i) + { + if (!Cloud->IsWithinDist(*i, 6, false)) + { + Cloud->CastCustomSpell(*i, 43137, &bp0, NULL, NULL, true, 0, 0, me->GetGUID()); + } + } + // visual + float x,y,z; + z = me->GetPositionZ(); + for (uint8 i = 0; i < 5+rand()%5; ++i) + { + x = 343+rand()%60; + y = 1380+rand()%60; + if (Unit *trigger = me->SummonTrigger(x, y, z, 0, 2000)) + { + trigger->setFaction(35); + trigger->SetMaxHealth(100000); + trigger->SetHealth(100000); + trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (Cloud) + Cloud->CastCustomSpell(trigger, /*43661*/43137, &bp0, NULL, NULL,true, 0, 0, Cloud->GetGUID()); + } + } + } + ++StormCount; + if (StormCount > 10) + { + StormCount = 0; // finish + SummonEagles_Timer = 5000; + me->InterruptNonMeleeSpells(false); + CloudGUID = 0; + if (Cloud) + Cloud->DealDamage(Cloud, Cloud->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + SetWeather(WEATHER_STATE_FINE, 0.0f); + isRaining = false; + } + StormSequenceTimer = 1000; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (StormCount) + { + Unit *pTarget = Unit::GetUnit(*me, CloudGUID); + if (!pTarget || !pTarget->isAlive()) + { + EnterEvadeMode(); + return; + } + else if (Unit* Cyclone = Unit::GetUnit(*me, CycloneGUID)) + Cyclone->CastSpell(pTarget, 25160, true); // keep casting or... + + if (StormSequenceTimer <= diff) + HandleStormSequence(pTarget); + else + StormSequenceTimer -= diff; + + return; + } + + if (Enrage_Timer <= diff) + { + me->MonsterYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONENRAGE); + DoCast(me, SPELL_BERSERK, true); + Enrage_Timer = 600000; + } else Enrage_Timer -= diff; + + if (StaticDisruption_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) pTarget = me->getVictim(); + TargetGUID = pTarget->GetGUID(); + DoCast(pTarget, SPELL_STATIC_DISRUPTION, false); + me->SetInFront(me->getVictim()); + StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s + + /*if (float dist = me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f) dist = 5.0f; + SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/ + } else StaticDisruption_Timer -= diff; + + if (GustOfWind_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) pTarget = me->getVictim(); + DoCast(pTarget, SPELL_GUST_OF_WIND); + GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers) + } else GustOfWind_Timer -= diff; + + if (CallLighting_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CALL_LIGHTNING); + CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this + } else CallLighting_Timer -= diff; + + if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000) + { + SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f); + isRaining = true; + } + + if (ElectricalStorm_Timer <= diff) { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); + if (!pTarget) + { + EnterEvadeMode(); + return; + } + pTarget->CastSpell(pTarget, 44007, true);//cloud visual + DoCast(pTarget, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual + float x,y,z; + pTarget->GetPosition(x,y,z); + if (pTarget) + { + pTarget->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + pTarget->SendMonsterMove(x,y,me->GetPositionZ()+15,0); + } + Unit *Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000); + if (Cloud) + { + CloudGUID = Cloud->GetGUID(); + Cloud->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + Cloud->StopMoving(); + Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + Cloud->setFaction(35); + Cloud->SetMaxHealth(9999999); + Cloud->SetHealth(9999999); + Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) + StormCount = 1; + StormSequenceTimer = 0; + } else ElectricalStorm_Timer -= diff; + + if (SummonEagles_Timer <= diff) + { + me->MonsterYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_ONSUMMON); + + float x, y, z; + me->GetPosition(x, y, z); + + for (uint8 i = 0; i < 8; ++i) + { + Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]); + if (!bird) //they despawned on die + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + x = pTarget->GetPositionX() + irand(-10,10); + y = pTarget->GetPositionY() + irand(-10,10); + z = pTarget->GetPositionZ() + urand(16,20); + if (z > 95) + z = 95 - urand(0,5); + } + Creature *pCreature = me->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (pCreature) + { + pCreature->AddThreat(me->getVictim(), 1.0f); + pCreature->AI()->AttackStart(me->getVictim()); + BirdGUIDs[i] = pCreature->GetGUID(); + } + } + } + SummonEagles_Timer = 999999; + } else SummonEagles_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soaring_eagleAI : public ScriptedAI +{ + mob_soaring_eagleAI(Creature *c) : ScriptedAI(c) {} + + uint32 EagleSwoop_Timer; + bool arrived; + uint32 TargetGUID; + + void Reset() + { + EagleSwoop_Timer = 5000 + rand()%5000; + arrived = true; + TargetGUID = 0; + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + } + + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + + void MoveInLineOfSight(Unit* /*who*/) {} + + void MovementInform(uint32, uint32) + { + arrived = true; + if (TargetGUID) + { + if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID)) + DoCast(pTarget, SPELL_EAGLE_SWOOP, true); + TargetGUID = 0; + me->SetSpeed(MOVE_RUN, 1.2f); + EagleSwoop_Timer = 5000 + rand()%5000; + } + } + + void UpdateAI(const uint32 diff) + { + if (EagleSwoop_Timer <= diff) + EagleSwoop_Timer = 0; + else + EagleSwoop_Timer -= diff; + + if (arrived) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + if (EagleSwoop_Timer) + { + x = pTarget->GetPositionX() + irand(-10,10); + y = pTarget->GetPositionY() + irand(-10,10); + z = pTarget->GetPositionZ() + urand(10,15); + if (z > 95) + z = 95 - urand(0,5); + } + else + { + pTarget->GetContactPoint(me, x, y, z); + z += 2; + me->SetSpeed(MOVE_RUN, 5.0f); + TargetGUID = pTarget->GetGUID(); + } + me->GetMotionMaster()->MovePoint(0, x, y, z); + arrived = false; + } + } + } +}; + +//Soaring Eagle +CreatureAI* GetAI_mob_soaring_eagle(Creature* pCreature) +{ + return new mob_soaring_eagleAI(pCreature); +} + +CreatureAI* GetAI_boss_akilzon(Creature* pCreature) +{ + return new boss_akilzonAI(pCreature); +} + +void AddSC_boss_akilzon() +{ + Script *newscript = NULL; + + newscript = new Script; + newscript->Name = "boss_akilzon"; + newscript->GetAI = &GetAI_boss_akilzon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_akilzon_eagle"; + newscript->GetAI = &GetAI_mob_soaring_eagle; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp new file mode 100644 index 00000000000..aee0a8a59ea --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp @@ -0,0 +1,401 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_Halazzi +SD%Complete: 80 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" +//#include "spell.h" + +#define YELL_AGGRO "Get on your knees and bow to da fang and claw!" +#define SOUND_AGGRO 12020 +#define YELL_SABER_ONE "You gonna leave in pieces!" +#define YELL_SABER_TWO "Me gonna carve ya now!" +#define YELL_SPLIT "Me gonna carve ya now!" +#define SOUND_SPLIT 12021 +#define YELL_MERGE "Spirit, come back to me!" +#define SOUND_MERGE 12022 +#define YELL_KILL_ONE "You cant fight the power!" +#define SOUND_KILL_ONE 12026 +#define YELL_KILL_TWO "You gonna fail!" +#define SOUND_KILL_TWO 12027 +#define YELL_DEATH "Chaga... choka'jinn." +#define SOUND_DEATH 12028 +#define YELL_BERSERK "Whatch you be doing? Pissin' yourselves..." +#define SOUND_BERSERK 12025 + +#define SPELL_DUAL_WIELD 29651 +#define SPELL_SABER_LASH 43267 +#define SPELL_FRENZY 43139 +#define SPELL_FLAMESHOCK 43303 +#define SPELL_EARTHSHOCK 43305 +#define SPELL_TRANSFORM_SPLIT 43142 +#define SPELL_TRANSFORM_SPLIT2 43573 +#define SPELL_TRANSFORM_MERGE 43271 +#define SPELL_SUMMON_LYNX 43143 +#define SPELL_SUMMON_TOTEM 43302 +#define SPELL_BERSERK 45078 + +#define MOB_SPIRIT_LYNX 24143 +#define SPELL_LYNX_FRENZY 43290 +#define SPELL_SHRED_ARMOR 43243 + +#define MOB_TOTEM 24224 +#define SPELL_LIGHTNING 43301 + +enum PhaseHalazzi +{ + PHASE_NONE = 0, + PHASE_LYNX = 1, + PHASE_SPLIT = 2, + PHASE_HUMAN = 3, + PHASE_MERGE = 4, + PHASE_ENRAGE = 5 +}; + +struct boss_halazziAI : public ScriptedAI +{ + boss_halazziAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + // need to find out what controls totem's spell cooldown + SpellEntry *TempSpell = GET_SPELL(SPELL_LIGHTNING); + if (TempSpell && TempSpell->CastingTimeIndex != 5) + TempSpell->CastingTimeIndex = 5; // 2000 ms casting time + } + + ScriptedInstance *pInstance; + + uint32 FrenzyTimer; + uint32 SaberlashTimer; + uint32 ShockTimer; + uint32 TotemTimer; + uint32 CheckTimer; + uint32 BerserkTimer; + + uint32 TransformCount; + + PhaseHalazzi Phase; + + uint64 LynxGUID; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_HALAZZIEVENT, NOT_STARTED); + + TransformCount = 0; + BerserkTimer = 600000; + CheckTimer = 1000; + + DoCast(me, SPELL_DUAL_WIELD, true); + + Phase = PHASE_NONE; + EnterPhase(PHASE_LYNX); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS); + + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_AGGRO); + + EnterPhase(PHASE_LYNX); + } + + void JustSummoned(Creature* summon) + { + summon->AI()->AttackStart(me->getVictim()); + if (summon->GetEntry() == MOB_SPIRIT_LYNX) + LynxGUID = summon->GetGUID(); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE) + damage = 0; + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (spell->Id == SPELL_TRANSFORM_SPLIT2) + EnterPhase(PHASE_HUMAN); + } + + void AttackStart(Unit *who) + { + if (Phase != PHASE_MERGE) ScriptedAI::AttackStart(who); + } + + void EnterPhase(PhaseHalazzi NextPhase) + { + switch(NextPhase) + { + case PHASE_LYNX: + case PHASE_ENRAGE: + if (Phase == PHASE_MERGE) + { + DoCast(me, SPELL_TRANSFORM_MERGE, true); + me->Attack(me->getVictim(), true); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + if (Creature *Lynx = Unit::GetCreature(*me, LynxGUID)) + Lynx->DisappearAndDie(); + me->SetMaxHealth(600000); + me->SetHealth(600000 - 150000 * TransformCount); + FrenzyTimer = 16000; + SaberlashTimer = 20000; + ShockTimer = 10000; + TotemTimer = 12000; + break; + case PHASE_SPLIT: + me->MonsterYell(YELL_SPLIT, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_SPLIT); + DoCast(me, SPELL_TRANSFORM_SPLIT, true); + break; + case PHASE_HUMAN: + //DoCast(me, SPELL_SUMMON_LYNX, true); + DoSpawnCreature(MOB_SPIRIT_LYNX, 5,5,0,0, TEMPSUMMON_CORPSE_DESPAWN, 0); + me->SetMaxHealth(400000); + me->SetHealth(400000); + ShockTimer = 10000; + TotemTimer = 12000; + break; + case PHASE_MERGE: + if (Unit *pLynx = Unit::GetUnit(*me, LynxGUID)) + { + me->MonsterYell(YELL_MERGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_MERGE); + pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pLynx->GetMotionMaster()->Clear(); + pLynx->GetMotionMaster()->MoveFollow(me, 0, 0); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(pLynx, 0, 0); + ++TransformCount; + } + break; + default: + break; + } + Phase = NextPhase; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BerserkTimer <= diff) + { + me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_BERSERK); + DoCast(me, SPELL_BERSERK, true); + BerserkTimer = 60000; + } else BerserkTimer -= diff; + + if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE) + { + if (SaberlashTimer <= diff) + { + // A tank with more than 490 defense skills should receive no critical hit + //DoCast(me, 41296, true); + DoCast(me->getVictim(), SPELL_SABER_LASH, true); + //me->RemoveAurasDueToSpell(41296); + SaberlashTimer = 30000; + } else SaberlashTimer -= diff; + + if (FrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + FrenzyTimer = urand(10000,15000); + } else FrenzyTimer -= diff; + + if (Phase == PHASE_LYNX) + if (CheckTimer <= diff) + { + if (me->GetHealth() * 4 < me->GetMaxHealth() * (3 - TransformCount)) + EnterPhase(PHASE_SPLIT); + CheckTimer = 1000; + } else CheckTimer -= diff; + } + + if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE) + { + if (TotemTimer <= diff) + { + DoCast(me, SPELL_SUMMON_TOTEM); + TotemTimer = 20000; + } else TotemTimer -= diff; + + if (ShockTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget->IsNonMeleeSpellCasted(false)) + DoCast(pTarget, SPELL_EARTHSHOCK); + else + DoCast(pTarget, SPELL_FLAMESHOCK); + ShockTimer = 10000 + rand()%5000; + } + } else ShockTimer -= diff; + + if (Phase == PHASE_HUMAN) + if (CheckTimer <= diff) + { + if (((me->GetHealth()*100) / me->GetMaxHealth() <= 20)/*me->GetHealth() * 10 < me->GetMaxHealth()*/) + EnterPhase(PHASE_MERGE); + else + { + Unit *Lynx = Unit::GetUnit(*me, LynxGUID); + if (Lynx && ((Lynx->GetHealth()*100) / Lynx->GetMaxHealth() <= 20)/*Lynx->GetHealth() * 10 < Lynx->GetMaxHealth()*/) + EnterPhase(PHASE_MERGE); + } + CheckTimer = 1000; + } else CheckTimer -= diff; + } + + if (Phase == PHASE_MERGE) + { + if (CheckTimer <= diff) + { + Unit *Lynx = Unit::GetUnit(*me, LynxGUID); + if (Lynx) + { + Lynx->GetMotionMaster()->MoveFollow(me, 0, 0); + me->GetMotionMaster()->MoveFollow(Lynx, 0, 0); + if (me->IsWithinDistInMap(Lynx, 6.0f)) + { + if (TransformCount < 3) + EnterPhase(PHASE_LYNX); + else + EnterPhase(PHASE_ENRAGE); + } + } + CheckTimer = 1000; + } else CheckTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,1)) + { + case 0: + me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL_ONE); + break; + + case 1: + me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL_TWO); + break; + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_HALAZZIEVENT, DONE); + + me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_DEATH); + } +}; + +// Spirits Lynx AI + +struct boss_spiritlynxAI : public ScriptedAI +{ + boss_spiritlynxAI(Creature *c) : ScriptedAI(c) {} + + uint32 FrenzyTimer; + uint32 shredder_timer; + + void Reset() + { + FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds + shredder_timer = 4000; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + damage = 0; + } + + void AttackStart(Unit *who) + { + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (FrenzyTimer <= diff) + { + DoCast(me, SPELL_LYNX_FRENZY); + FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds + } else FrenzyTimer -= diff; + + if (shredder_timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHRED_ARMOR); + shredder_timer = 4000; + } else shredder_timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_halazziAI(Creature* pCreature) +{ + return new boss_halazziAI (pCreature); +} + +CreatureAI* GetAI_boss_spiritlynxAI(Creature* pCreature) +{ + return new boss_spiritlynxAI (pCreature); +} + +void AddSC_boss_halazzi() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_halazzi"; + newscript->GetAI = &GetAI_boss_halazziAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_halazzi_lynx"; + newscript->GetAI = &GetAI_boss_spiritlynxAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp new file mode 100644 index 00000000000..7baa9292142 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp @@ -0,0 +1,907 @@ +/* Copyright ?2006,2007 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Hex_Lord_Malacrass +SD%Complete: +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" + +#define YELL_AGGRO "Da shadow gonna fall on you... " +#define SOUND_YELL_AGGRO 12041 +#define YELL_SPIRIT_BOLTS "Your soul gonna bleed!" +#define SOUND_YELL_SPIRIT_BOLTS 12047 +#define YELL_DRAIN_POWER "Darkness comin\' for you" +#define SOUND_YELL_DRAIN_POWER 12046 +#define YELL_KILL_ONE "Dis a nightmare ya don\' wake up from!" +#define SOUND_YELL_KILL_ONE 12043 +#define YELL_KILL_TWO "Azzaga choogo zinn!" +#define SOUND_YELL_KILL_TWO 12044 +#define YELL_DEATH "Dis not... da end of me..." +#define SOUND_YELL_DEATH 12051 + +#define SPELL_SPIRIT_BOLTS 43383 +#define SPELL_DRAIN_POWER 44131 +#define SPELL_SIPHON_SOUL 43501 + +#define MOB_TEMP_TRIGGER 23920 + +//Defines for various powers he uses after using soul drain + +//Druid +#define SPELL_DR_LIFEBLOOM 43421 +#define SPELL_DR_THORNS 43420 +#define SPELL_DR_MOONFIRE 43545 + +//Hunter +#define SPELL_HU_EXPLOSIVE_TRAP 43444 +#define SPELL_HU_FREEZING_TRAP 43447 +#define SPELL_HU_SNAKE_TRAP 43449 + +//Mage +#define SPELL_MG_FIREBALL 41383 +#define SPELL_MG_FROSTBOLT 43428 +#define SPELL_MG_FROST_NOVA 43426 +#define SPELL_MG_ICE_LANCE 43427 + +//Paladin +#define SPELL_PA_CONSECRATION 43429 +#define SPELL_PA_HOLY_LIGHT 43451 +#define SPELL_PA_AVENGING_WRATH 43430 + +//Priest +#define SPELL_PR_HEAL 41372 +#define SPELL_PR_MIND_CONTROL 43550 +#define SPELL_PR_MIND_BLAST 41374 +#define SPELL_PR_SW_DEATH 41375 +#define SPELL_PR_PSYCHIC_SCREAM 43432 +#define SPELL_PR_PAIN_SUPP 44416 + +//Rogue +#define SPELL_RO_BLIND 43433 +#define SPELL_RO_SLICE_DICE 43457 +#define SPELL_RO_WOUND_POISON 39665 + +//Shaman +#define SPELL_SH_FIRE_NOVA 43436 +#define SPELL_SH_HEALING_WAVE 43548 +#define SPELL_SH_CHAIN_LIGHT 43435 + +//Warlock +#define SPELL_WL_CURSE_OF_DOOM 43439 +#define SPELL_WL_RAIN_OF_FIRE 43440 +#define SPELL_WL_UNSTABLE_AFFL 35183 + +//Warrior +#define SPELL_WR_SPELL_REFLECT 43443 +#define SPELL_WR_WHIRLWIND 43442 +#define SPELL_WR_MORTAL_STRIKE 43441 + +#define ORIENT 1.5696 +#define POS_Y 921.2795 +#define POS_Z 33.8883 + +static float Pos_X[4] = {112.8827, 107.8827, 122.8827, 127.8827}; + +static uint32 AddEntryList[8]= +{ + 24240, //Alyson Antille + 24241, //Thurg + 24242, //Slither + 24243, //Lord Raadan + 24244, //Gazakroth + 24245, //Fenstalker + 24246, //Darkheart + 24247 //Koragg +}; + +enum AbilityTarget +{ + ABILITY_TARGET_SELF = 0, + ABILITY_TARGET_VICTIM = 1, + ABILITY_TARGET_ENEMY = 2, + ABILITY_TARGET_HEAL = 3, + ABILITY_TARGET_BUFF = 4, + ABILITY_TARGET_SPECIAL = 5 +}; + +struct PlayerAbilityStruct +{ + uint32 spell; + AbilityTarget target; + uint32 cooldown; +}; + +static PlayerAbilityStruct PlayerAbility[][3] = +{ + // 1 warrior + {{SPELL_WR_SPELL_REFLECT, ABILITY_TARGET_SELF, 10000}, + {SPELL_WR_WHIRLWIND, ABILITY_TARGET_SELF, 10000}, + {SPELL_WR_MORTAL_STRIKE, ABILITY_TARGET_VICTIM, 6000}}, + // 2 paladin + {{SPELL_PA_CONSECRATION, ABILITY_TARGET_SELF, 10000}, + {SPELL_PA_HOLY_LIGHT, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PA_AVENGING_WRATH, ABILITY_TARGET_SELF, 10000}}, + // 3 hunter + {{SPELL_HU_EXPLOSIVE_TRAP, ABILITY_TARGET_SELF, 10000}, + {SPELL_HU_FREEZING_TRAP, ABILITY_TARGET_SELF, 10000}, + {SPELL_HU_SNAKE_TRAP, ABILITY_TARGET_SELF, 10000}}, + // 4 rogue + {{SPELL_RO_WOUND_POISON, ABILITY_TARGET_VICTIM, 3000}, + {SPELL_RO_SLICE_DICE, ABILITY_TARGET_SELF, 10000}, + {SPELL_RO_BLIND, ABILITY_TARGET_ENEMY, 10000}}, + // 5 priest + {{SPELL_PR_PAIN_SUPP, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PR_HEAL, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PR_PSYCHIC_SCREAM, ABILITY_TARGET_SELF, 10000}}, + // 5* shadow priest + {{SPELL_PR_MIND_CONTROL, ABILITY_TARGET_ENEMY, 15000}, + {SPELL_PR_MIND_BLAST, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_PR_SW_DEATH, ABILITY_TARGET_ENEMY, 10000}}, + // 7 shaman + {{SPELL_SH_FIRE_NOVA, ABILITY_TARGET_SELF, 10000}, + {SPELL_SH_HEALING_WAVE, ABILITY_TARGET_HEAL, 10000}, + {SPELL_SH_CHAIN_LIGHT, ABILITY_TARGET_ENEMY, 8000}}, + // 8 mage + {{SPELL_MG_FIREBALL, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_MG_FROSTBOLT, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_MG_ICE_LANCE, ABILITY_TARGET_SPECIAL, 2000}}, + // 9 warlock + {{SPELL_WL_CURSE_OF_DOOM, ABILITY_TARGET_ENEMY, 10000}, + {SPELL_WL_RAIN_OF_FIRE, ABILITY_TARGET_ENEMY, 10000}, + {SPELL_WL_UNSTABLE_AFFL, ABILITY_TARGET_ENEMY, 10000}}, + // 11 druid + {{SPELL_DR_LIFEBLOOM, ABILITY_TARGET_HEAL, 10000}, + {SPELL_DR_THORNS, ABILITY_TARGET_SELF, 10000}, + {SPELL_DR_MOONFIRE, ABILITY_TARGET_ENEMY, 8000}} +}; + +struct boss_hexlord_addAI : public ScriptedAI +{ + ScriptedInstance* pInstance; + + boss_hexlord_addAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() {} + + void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} + + void UpdateAI(const uint32 /*diff*/) + { + if (pInstance && pInstance->GetData(DATA_HEXLORDEVENT) != IN_PROGRESS) + { + EnterEvadeMode(); + return; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_hex_lord_malacrassAI : public ScriptedAI +{ + boss_hex_lord_malacrassAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + SelectAddEntry(); + for (uint8 i = 0; i < 4; ++i) + AddGUID[i] = 0; + } + + ScriptedInstance *pInstance; + + uint64 AddGUID[4]; + uint32 AddEntry[4]; + + uint64 PlayerGUID; + + uint32 SpiritBolts_Timer; + uint32 DrainPower_Timer; + uint32 SiphonSoul_Timer; + uint32 PlayerAbility_Timer; + uint32 CheckAddState_Timer; + uint32 ResetTimer; + + uint32 PlayerClass; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_HEXLORDEVENT, NOT_STARTED); + + SpiritBolts_Timer = 20000; + DrainPower_Timer = 60000; + SiphonSoul_Timer = 100000; + PlayerAbility_Timer = 99999; + CheckAddState_Timer = 5000; + ResetTimer = 5000; + + SpawnAdds(); + + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 46916); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HEXLORDEVENT, IN_PROGRESS); + + DoZoneInCombat(); + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_AGGRO); + + for (uint8 i = 0; i < 4; ++i) + { + Unit* Temp = Unit::GetUnit((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + CAST_CRE(Temp)->AI()->AttackStart(me->getVictim()); + else + { + EnterEvadeMode(); + break; + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,1)) + { + case 0: + me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); + break; + case 1: + me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); + break; + } + } + + void JustDied(Unit* /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_HEXLORDEVENT, DONE); + + me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_DEATH); + + for (uint8 i = 0; i < 4 ; ++i) + { + Unit* Temp = Unit::GetUnit((*me),AddGUID[i]); + if (Temp && Temp->isAlive()) + Temp->DealDamage(Temp, Temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void SelectAddEntry() + { + std::vector AddList; + + for (uint8 i = 0; i < 8; ++i) + AddList.push_back(AddEntryList[i]); + + while (AddList.size() > 4) + AddList.erase(AddList.begin()+rand()%AddList.size()); + + uint8 i = 0; + for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr, ++i) + AddEntry[i] = *itr; + } + + void SpawnAdds() + { + for (uint8 i = 0; i < 4; ++i) + { + Creature *pCreature = (Unit::GetCreature((*me), AddGUID[i])); + if (!pCreature || !pCreature->isAlive()) + { + if (pCreature) pCreature->setDeathState(DEAD); + pCreature = me->SummonCreature(AddEntry[i], Pos_X[i], POS_Y, POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0); + if (pCreature) AddGUID[i] = pCreature->GetGUID(); + } + else + { + pCreature->AI()->EnterEvadeMode(); + pCreature->GetMap()->CreatureRelocation(me, Pos_X[i], POS_Y, POS_Z, ORIENT); + pCreature->StopMoving(); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ResetTimer <= diff) + { + if (me->IsWithinDist3d(119.223, 1035.45, 29.4481, 10)) + { + EnterEvadeMode(); + return; + } + ResetTimer = 5000; + } else ResetTimer -= diff; + + if (CheckAddState_Timer <= diff) + { + for (uint8 i = 0; i < 4; ++i) + if (Creature *pTemp = Unit::GetCreature(*me, AddGUID[i])) + if (pTemp->isAlive() && !pTemp->getVictim()) + pTemp->AI()->AttackStart(me->getVictim()); + + CheckAddState_Timer = 5000; + } else CheckAddState_Timer -= diff; + + if (DrainPower_Timer <= diff) + { + DoCast(me, SPELL_DRAIN_POWER, true); + me->MonsterYell(YELL_DRAIN_POWER, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_DRAIN_POWER); + DrainPower_Timer = urand(40000,55000); // must cast in 60 sec, or buff/debuff will disappear + } else DrainPower_Timer -= diff; + + if (SpiritBolts_Timer <= diff) + { + if (DrainPower_Timer < 12000) // channel 10 sec + SpiritBolts_Timer = 13000; // cast drain power first + else + { + DoCast(me, SPELL_SPIRIT_BOLTS, false); + me->MonsterYell(YELL_SPIRIT_BOLTS, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_SPIRIT_BOLTS); + SpiritBolts_Timer = 40000; + SiphonSoul_Timer = 10000; // ready to drain + PlayerAbility_Timer = 99999; + } + } else SpiritBolts_Timer -= diff; + + if (SiphonSoul_Timer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 70, true); + Unit *trigger = DoSpawnCreature(MOB_TEMP_TRIGGER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); + if (!pTarget || !trigger) + { + EnterEvadeMode(); + return; + } + else + { + trigger->SetDisplayId(11686); + trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + trigger->CastSpell(pTarget, SPELL_SIPHON_SOUL, true); + trigger->GetMotionMaster()->MoveChase(me); + + //DoCast(pTarget, SPELL_SIPHON_SOUL, true); + //me->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pTarget->GetGUID()); + //me->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SIPHON_SOUL); + + PlayerGUID = pTarget->GetGUID(); + PlayerAbility_Timer = urand(8000,10000); + PlayerClass = pTarget->getClass() - 1; + + if (PlayerClass == CLASS_DRUID-1) + PlayerClass = CLASS_DRUID; + else if (PlayerClass == CLASS_PRIEST-1 && pTarget->HasSpell(15473)) + PlayerClass = CLASS_PRIEST; // shadow priest + + SiphonSoul_Timer = 99999; // buff lasts 30 sec + } + } else SiphonSoul_Timer -= diff; + + if (PlayerAbility_Timer <= diff) + { + //Unit *pTarget = Unit::GetUnit(*me, PlayerGUID); + //if (pTarget && pTarget->isAlive()) + //{ + UseAbility(); + PlayerAbility_Timer = urand(8000,10000); + //} + } else PlayerAbility_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + void UseAbility() + { + uint8 random = urand(0,2); + Unit *pTarget = NULL; + switch(PlayerAbility[PlayerClass][random].target) + { + case ABILITY_TARGET_SELF: + pTarget = me; + break; + case ABILITY_TARGET_VICTIM: + pTarget = me->getVictim(); + break; + case ABILITY_TARGET_ENEMY: + default: + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + break; + case ABILITY_TARGET_HEAL: + pTarget = DoSelectLowestHpFriendly(50, 0); + break; + case ABILITY_TARGET_BUFF: + { + std::list templist = DoFindFriendlyMissingBuff(50, PlayerAbility[PlayerClass][random].spell); + if (!templist.empty()) + pTarget = *(templist.begin()); + } + break; + } + if (pTarget) + DoCast(pTarget, PlayerAbility[PlayerClass][random].spell, false); + } +}; + +#define SPELL_BLOODLUST 43578 +#define SPELL_CLEAVE 15496 + +struct boss_thurgAI : public boss_hexlord_addAI +{ + + boss_thurgAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 bloodlust_timer; + uint32 cleave_timer; + + void Reset() + { + bloodlust_timer = 15000; + cleave_timer = 10000; + + boss_hexlord_addAI::Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (bloodlust_timer <= diff) + { + std::list templist = DoFindFriendlyMissingBuff(50, SPELL_BLOODLUST); + if (!templist.empty()) + { + if (Unit *pTarget = *(templist.begin())) + DoCast(pTarget, SPELL_BLOODLUST, false); + } + bloodlust_timer = 12000; + } else bloodlust_timer -= diff; + + if (cleave_timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE, false); + cleave_timer = 12000; //3 sec cast + } else cleave_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_FLASH_HEAL 43575 +#define SPELL_DISPEL_MAGIC 43577 + +struct boss_alyson_antilleAI : public boss_hexlord_addAI +{ + //Holy Priest + boss_alyson_antilleAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 flashheal_timer; + uint32 dispelmagic_timer; + + void Reset() + { + flashheal_timer = 2500; + dispelmagic_timer = 10000; + + //AcquireGUID(); + + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (flashheal_timer <= diff) + { + Unit *pTarget = DoSelectLowestHpFriendly(99, 30000); + if (pTarget) + { + if (pTarget->IsWithinDistInMap(me, 50)) + DoCast(pTarget, SPELL_FLASH_HEAL, false); + else + { + // bugged + //me->GetMotionMaster()->Clear(); + //me->GetMotionMaster()->MoveChase(pTarget, 20); + } + } + else + { + if (urand(0,1)) + pTarget = DoSelectLowestHpFriendly(50, 0); + else + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_DISPEL_MAGIC, false); + } + flashheal_timer = 2500; + } else flashheal_timer -= diff; + + /*if (dispelmagic_timer <= diff) + { + if (urand(0,1)) + { + Unit *pTarget = SelectTarget(); + + DoCast(pTarget, SPELL_DISPEL_MAGIC, false); + } + else + me->CastSpell(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DISPEL_MAGIC, false); + + dispelmagic_timer = 12000; + } else dispelmagic_timer -= diff;*/ + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_FIREBOLT 43584 + +struct boss_gazakrothAI : public boss_hexlord_addAI +{ + boss_gazakrothAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 firebolt_timer; + + void Reset() + { + firebolt_timer = 2000; + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (firebolt_timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBOLT, false); + firebolt_timer = 700; + } else firebolt_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_FLAME_BREATH 43582 +#define SPELL_THUNDERCLAP 43583 + +struct boss_lord_raadanAI : public boss_hexlord_addAI +{ + boss_lord_raadanAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 flamebreath_timer; + uint32 thunderclap_timer; + + void Reset() + { + flamebreath_timer = 8000; + thunderclap_timer = 13000; + + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (thunderclap_timer <= diff) + { + DoCast(me->getVictim(), SPELL_THUNDERCLAP, false); + thunderclap_timer = 12000; + } else thunderclap_timer -= diff; + + if (flamebreath_timer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAME_BREATH, false); + flamebreath_timer = 12000; + } else flamebreath_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_PSYCHIC_WAIL 43590 + +struct boss_darkheartAI : public boss_hexlord_addAI +{ + boss_darkheartAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 psychicwail_timer; + + void Reset() + { + psychicwail_timer = 8000; + boss_hexlord_addAI::Reset(); + } + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (psychicwail_timer <= diff) + { + DoCast(me->getVictim(), SPELL_PSYCHIC_WAIL, false); + psychicwail_timer = 12000; + } else psychicwail_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +#define SPELL_VENOM_SPIT 43579 + +struct boss_slitherAI : public boss_hexlord_addAI +{ + boss_slitherAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 venomspit_timer; + + void Reset() + { + venomspit_timer = 5000; + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (venomspit_timer <= diff) + { + if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(victim, SPELL_VENOM_SPIT, false); + venomspit_timer = 2500; + } else venomspit_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +//Fenstalker +#define SPELL_VOLATILE_INFECTION 43586 + +struct boss_fenstalkerAI : public boss_hexlord_addAI +{ + boss_fenstalkerAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 volatileinf_timer; + + void Reset() + { + volatileinf_timer = 15000; + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (volatileinf_timer <= diff) + { + // core bug + me->getVictim()->CastSpell(me->getVictim(),SPELL_VOLATILE_INFECTION, false); + volatileinf_timer = 12000; + } else volatileinf_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +//Koragg +#define SPELL_COLD_STARE 43593 +#define SPELL_MIGHTY_BLOW 43592 + +struct boss_koraggAI : public boss_hexlord_addAI +{ + boss_koraggAI(Creature *c) : boss_hexlord_addAI(c) {} + + uint32 coldstare_timer; + uint32 mightyblow_timer; + + void Reset() + { + coldstare_timer = 15000; + mightyblow_timer = 10000; + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (mightyblow_timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, false); + mightyblow_timer = 12000; + } + if (coldstare_timer <= diff) + { + if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(victim, SPELL_COLD_STARE, false); + coldstare_timer = 12000; + } + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_boss_hex_lord_malacrass(Creature* pCreature) +{ + return new boss_hex_lord_malacrassAI (pCreature); +} + +CreatureAI* GetAI_boss_thurg(Creature* pCreature) +{ + return new boss_thurgAI (pCreature); +} + +CreatureAI* GetAI_boss_alyson_antille(Creature* pCreature) +{ + return new boss_alyson_antilleAI (pCreature); +} + +CreatureAI* GetAI_boss_gazakroth(Creature* pCreature) +{ + return new boss_gazakrothAI (pCreature); +} + +CreatureAI* GetAI_boss_lord_raadan(Creature* pCreature) +{ + return new boss_lord_raadanAI (pCreature); +} + +CreatureAI* GetAI_boss_darkheart(Creature* pCreature) +{ + return new boss_darkheartAI (pCreature); +} + +CreatureAI* GetAI_boss_slither(Creature* pCreature) +{ + return new boss_slitherAI (pCreature); +} + +CreatureAI* GetAI_boss_fenstalker(Creature* pCreature) +{ + return new boss_fenstalkerAI (pCreature); +} + +CreatureAI* GetAI_boss_koragg(Creature* pCreature) +{ + return new boss_koraggAI (pCreature); +} +void AddSC_boss_hex_lord_malacrass() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hexlord_malacrass"; + newscript->GetAI = &GetAI_boss_hex_lord_malacrass; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_thurg"; + newscript->GetAI = &GetAI_boss_thurg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_gazakroth"; + newscript->GetAI = &GetAI_boss_gazakroth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_raadan"; + newscript->GetAI = &GetAI_boss_lord_raadan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_darkheart"; + newscript->GetAI = &GetAI_boss_darkheart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_slither"; + newscript->GetAI = &GetAI_boss_slither; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fenstalker"; + newscript->GetAI = &GetAI_boss_fenstalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_koragg"; + newscript->GetAI = &GetAI_boss_koragg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_alyson_antille"; + newscript->GetAI = &GetAI_boss_alyson_antille; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp new file mode 100644 index 00000000000..9ac54976241 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp @@ -0,0 +1,687 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +*(at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Janalai +SD%Complete: 100 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" +#include "GridNotifiers.h" + +enum eEnums +{ + SAY_AGGRO = -1568000, + SAY_FIRE_BOMBS = -1568001, + SAY_SUMMON_HATCHER = -1568002, + SAY_ALL_EGGS = -1568003, + SAY_BERSERK = -1568004, + SAY_SLAY_1 = -1568005, + SAY_SLAY_2 = -1568006, + SAY_DEATH = -1568007, + SAY_EVENT_STRANGERS = -1568008, + SAY_EVENT_FRIENDS = -1568009, + +// Jan'alai + SPELL_FLAME_BREATH = 43140, + SPELL_FIRE_WALL = 43113, + SPELL_ENRAGE = 44779, + SPELL_SUMMON_PLAYERS = 43097, + SPELL_TELE_TO_CENTER = 43098, // coord + SPELL_HATCH_ALL = 43144, + SPELL_BERSERK = 45078, + +// -- Fire Bob Spells + SPELL_FIRE_BOMB_CHANNEL = 42621, // last forever + SPELL_FIRE_BOMB_THROW = 42628, // throw visual + SPELL_FIRE_BOMB_DUMMY = 42629, // bomb visual + SPELL_FIRE_BOMB_DAMAGE = 42630, + +// --Summons + MOB_AMANI_HATCHER = 23818, + MOB_HATCHLING = 23598, // 42493 + MOB_EGG = 23817, + MOB_FIRE_BOMB = 23920, + +// -- Hatcher Spells + SPELL_HATCH_EGG = 43734, // 42471 + +// -- Hatchling Spells + SPELL_FLAMEBUFFET = 43299 +}; + +const int area_dx = 44; +const int area_dy = 51; + +float JanalainPos[1][3] = +{ + {-33.93, 1149.27, 19} +}; + +float FireWallCoords[4][4] = +{ + {-10.13, 1149.27, 19, 3.1415}, + {-33.93, 1123.90, 19, 0.5*3.1415}, + {-54.80, 1150.08, 19, 0}, + {-33.93, 1175.68, 19, 1.5*3.1415} +}; + +float hatcherway[2][5][3] = +{ + { + {-87.46,1170.09,6}, + {-74.41,1154.75,6}, + {-52.74,1153.32,19}, + {-33.37,1172.46,19}, + {-33.09,1203.87,19} + }, + { + {-86.57,1132.85,6}, + {-73.94,1146.00,6}, + {-52.29,1146.51,19}, + {-33.57,1125.72,19}, + {-34.29,1095.22,19} + } +}; + +struct boss_janalaiAI : public ScriptedAI +{ + boss_janalaiAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + + SpellEntry *TempSpell = GET_SPELL(SPELL_HATCH_EGG); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) + { + TempSpell->EffectImplicitTargetA[0] = 1; + TempSpell->EffectImplicitTargetB[0] = 0; + } + } + + ScriptedInstance *pInstance; + + uint32 FireBreathTimer; + uint32 BombTimer; + uint32 BombSequenceTimer; + uint32 BombCount; + uint32 HatcherTimer; + uint32 EnrageTimer; + + bool noeggs; + bool enraged; + bool isBombing; + + bool isFlameBreathing; + + uint64 FireBombGUIDs[40]; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_JANALAIEVENT, NOT_STARTED); + + FireBreathTimer = 8000; + BombTimer = 30000; + BombSequenceTimer = 1000; + BombCount = 0; + HatcherTimer = 10000; + EnrageTimer = MINUTE*5*IN_MILISECONDS; + + noeggs = false; + isBombing =false; + enraged = false; + + isFlameBreathing = false; + + for (uint8 i = 0; i < 40; ++i) + FireBombGUIDs[i] = 0; + + HatchAllEggs(1); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_JANALAIEVENT, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_JANALAIEVENT, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, me); +// DoZoneInCombat(); + } + + void DamageDeal(Unit *pTarget, uint32 &damage) + { + if (isFlameBreathing) + { + if (!me->HasInArc(M_PI/6, pTarget)) + damage = 0; + } + } + + void FireWall() + { + uint8 WallNum; + Creature* wall = NULL; + for (uint8 i = 0; i < 4; ++i) + { + if (i == 0 || i == 2) + WallNum = 3; + else + WallNum = 2; + + for (uint8 j = 0; j < WallNum; j++) + { + if (WallNum == 3) + wall = me->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0],FireWallCoords[i][1]+5*(j-1),FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000); + else + wall = me->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0]-2+4*j,FireWallCoords[i][1],FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000); + if (wall) wall->CastSpell(wall, SPELL_FIRE_WALL, true); + } + } + } + + void SpawnBombs() + { + float dx, dy; + for (int i(0); i < 40; ++i) + { + dx = irand(-area_dx/2, area_dx/2); + dy = irand(-area_dy/2, area_dy/2); + + Creature* bomb = DoSpawnCreature(MOB_FIRE_BOMB, dx, dy, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); + if (bomb) FireBombGUIDs[i] = bomb->GetGUID(); + } + BombCount = 0; + } + + bool HatchAllEggs(uint32 uiAction) //1: reset, 2: isHatching all + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllCreaturesOfEntryInRange check(me, MOB_EGG, 100); + Trinity::CreatureListSearcher searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap())); + } + + //error_log("Eggs %d at middle", templist.size()); + if (!templist.size()) + return false; + + for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) + { + if (uiAction == 1) + (*i)->SetDisplayId(10056); + else if (uiAction == 2 &&(*i)->GetDisplayId() != 11686) + (*i)->CastSpell(*i, SPELL_HATCH_EGG, false); + } + return true; + } + + void Boom() + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllCreaturesOfEntryInRange check(me, MOB_FIRE_BOMB, 100); + Trinity::CreatureListSearcher searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap())); + } + for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) + { + (*i)->CastSpell(*i, SPELL_FIRE_BOMB_DAMAGE, true); + (*i)->RemoveAllAuras(); + } + } + + void HandleBombSequence() + { + if (BombCount < 40) + { + if (Unit *FireBomb = Unit::GetUnit((*me), FireBombGUIDs[BombCount])) + { + FireBomb->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(FireBomb, SPELL_FIRE_BOMB_THROW, true); + FireBomb->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + ++BombCount; + if (BombCount == 40) + { + BombSequenceTimer = 5000; + } else BombSequenceTimer = 100; + } + else + { + Boom(); + isBombing = false; + BombTimer = urand(20000,40000); + me->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_CHANNEL); + if (EnrageTimer <= 10000) + EnrageTimer = 0; + else + EnrageTimer -= 10000; + } + } + + void UpdateAI(const uint32 diff) + { + if (isFlameBreathing) + { + if (!me->IsNonMeleeSpellCasted(false)) + isFlameBreathing = false; + else + return; + } + + if (isBombing) + { + if (BombSequenceTimer <= diff) + HandleBombSequence(); + else + BombSequenceTimer -= diff; + return; + } + + if (!UpdateVictim()) + return; + + //enrage if under 25% hp before 5 min. + if (!enraged && me->GetHealth() * 4 < me->GetMaxHealth()) + EnrageTimer = 0; + + if (EnrageTimer <= diff) + { + if (!enraged) + { + DoCast(me, SPELL_ENRAGE, true); + enraged = true; + EnrageTimer = 300000; + } + else + { + DoScriptText(SAY_BERSERK, me); + DoCast(me, SPELL_BERSERK, true); + EnrageTimer = 300000; + } + } else EnrageTimer -= diff; + + if (BombTimer <= diff) + { + DoScriptText(SAY_FIRE_BOMBS, me); + + me->AttackStop(); + me->GetMotionMaster()->Clear(); + DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); + me->StopMoving(); + DoCast(me, SPELL_FIRE_BOMB_CHANNEL, false); + //DoTeleportPlayer(me, JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2], 0); + //DoCast(me, SPELL_TELE_TO_CENTER, true); + + FireWall(); + SpawnBombs(); + isBombing = true; + BombSequenceTimer = 100; + + //Teleport every Player into the middle + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) return; + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* i_pl = i->getSource()) + if (i_pl->isAlive()) + DoTeleportPlayer(i_pl, JanalainPos[0][0]-5+rand()%10, JanalainPos[0][1]-5+rand()%10, JanalainPos[0][2], 0); + //DoCast(Temp, SPELL_SUMMON_PLAYERS, true) // core bug, spell does not work if too far + return; + } else BombTimer -= diff; + + if (!noeggs) + { + if (100 * me->GetHealth() < 35 * me->GetMaxHealth()) + { + DoScriptText(SAY_ALL_EGGS, me); + + me->AttackStop(); + me->GetMotionMaster()->Clear(); + DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); + me->StopMoving(); + DoCast(me, SPELL_HATCH_ALL, false); + HatchAllEggs(2); + noeggs = true; + } + else if (HatcherTimer <= diff) + { + if (HatchAllEggs(0)) + { + DoScriptText(SAY_SUMMON_HATCHER, me); + me->SummonCreature(MOB_AMANI_HATCHER,hatcherway[0][0][0],hatcherway[0][0][1],hatcherway[0][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); + me->SummonCreature(MOB_AMANI_HATCHER,hatcherway[1][0][0],hatcherway[1][0][1],hatcherway[1][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); + HatcherTimer = 90000; + } + else + noeggs = true; + } else HatcherTimer -= diff; + } + + EnterEvadeIfOutOfCombatArea(diff); + + DoMeleeAttackIfReady(); + + if (FireBreathTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + me->AttackStop(); + me->GetMotionMaster()->Clear(); + DoCast(pTarget, SPELL_FLAME_BREATH, false); + me->StopMoving(); + isFlameBreathing = true; + } + FireBreathTimer = 8000; + } else FireBreathTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_janalaiAI(Creature* pCreature) +{ + return new boss_janalaiAI(pCreature); +} + +struct mob_janalai_firebombAI : public ScriptedAI +{ + mob_janalai_firebombAI(Creature *c) : ScriptedAI(c){} + + void Reset() {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_FIRE_BOMB_THROW) + DoCast(me, SPELL_FIRE_BOMB_DUMMY, true); + } + + void EnterCombat(Unit* /*who*/) {} + + void AttackStart(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_mob_janalai_firebombAI(Creature* pCreature) +{ + return new mob_janalai_firebombAI(pCreature); +} + +struct mob_amanishi_hatcherAI : public ScriptedAI +{ + mob_amanishi_hatcherAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 waypoint; + uint32 HatchNum; + uint32 WaitTimer; + + bool side; + bool hasChangedSide; + bool isHatching; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + side =(me->GetPositionY() < 1150); + waypoint = 0; + isHatching = false; + hasChangedSide = false; + WaitTimer = 1; + HatchNum = 0; + } + + bool HatchEggs(uint32 num) + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllCreaturesOfEntryInRange check(me, 23817, 50); + Trinity::CreatureListSearcher searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap())); + } + + //error_log("Eggs %d at %d", templist.size(), side); + + for (std::list::const_iterator i = templist.begin(); i != templist.end() && num > 0; ++i) + if ((*i)->GetDisplayId() != 11686) + { + (*i)->CastSpell(*i, SPELL_HATCH_EGG, false); + num--; + } + + return num == 0; // if num == 0, no more templist + } + + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void MovementInform(uint32, uint32) + { + if (waypoint == 5) + { + isHatching = true; + HatchNum = 1; + WaitTimer = 5000; + } + else + WaitTimer = 1; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance || !(pInstance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS)) + { + me->DisappearAndDie(); + return; + } + + if (!isHatching) + { + if (WaitTimer) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,hatcherway[side][waypoint][0],hatcherway[side][waypoint][1],hatcherway[side][waypoint][2]); + ++waypoint; + WaitTimer = 0; + } + } + else + { + if (WaitTimer <= diff) + { + if (HatchEggs(HatchNum)) + { + ++HatchNum; + WaitTimer = 10000; + } + else if (!hasChangedSide) + { + side = side ? 0 : 1; + isHatching = false; + waypoint = 3; + WaitTimer = 1; + hasChangedSide = true; + } + else + me->DisappearAndDie(); + + } else WaitTimer -= diff; + } + } +}; + +CreatureAI* GetAI_mob_amanishi_hatcherAI(Creature* pCreature) +{ + return new mob_amanishi_hatcherAI(pCreature); +} + +struct mob_hatchlingAI : public ScriptedAI +{ + mob_hatchlingAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 BuffetTimer; + + void Reset() + { + BuffetTimer = 7000; + if (me->GetPositionY() > 1150) + me->GetMotionMaster()->MovePoint(0, hatcherway[0][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[0][3][2]); + else + me->GetMotionMaster()->MovePoint(0,hatcherway[1][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[1][3][2]); + + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + } + + void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/} + + void UpdateAI(const uint32 diff) + { + if (!pInstance || !(pInstance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS)) + { + me->DisappearAndDie(); + return; + } + + if (!UpdateVictim()) + return; + + if (BuffetTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAMEBUFFET, false); + BuffetTimer = 10000; + } else BuffetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_hatchlingAI(Creature* pCreature) +{ + return new mob_hatchlingAI(pCreature); +} + +struct mob_eggAI : public ScriptedAI +{ + mob_eggAI(Creature *c) : ScriptedAI(c){} + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_HATCH_EGG) + { + DoSpawnCreature(MOB_HATCHLING, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + me->SetDisplayId(11686); + } + } +}; + +CreatureAI* GetAI_mob_eggAI(Creature* pCreature) +{ + return new mob_eggAI(pCreature); +} + +void AddSC_boss_janalai() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_janalai"; + newscript->GetAI = &GetAI_boss_janalaiAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_janalai_firebomb"; + newscript->GetAI = &GetAI_mob_janalai_firebombAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_janalai_hatcher"; + newscript->GetAI = &GetAI_mob_amanishi_hatcherAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_janalai_hatchling"; + newscript->GetAI = &GetAI_mob_hatchlingAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_janalai_egg"; + newscript->GetAI = &GetAI_mob_eggAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp new file mode 100644 index 00000000000..ae5c6596d2d --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -0,0 +1,451 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Nalorakk +SD%Complete: 100 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" +#include "GridNotifiers.h" + +//Trash Waves +float NalorakkWay[8][3] = +{ + { 18.569, 1414.512, 11.42},// waypoint 1 + {-17.264, 1419.551, 12.62}, + {-52.642, 1419.357, 27.31},// waypoint 2 + {-69.908, 1419.721, 27.31}, + {-79.929, 1395.958, 27.31}, + {-80.072, 1374.555, 40.87},// waypoint 3 + {-80.072, 1314.398, 40.87}, + {-80.072, 1295.775, 48.60} // waypoint 4 +}; + +#define YELL_NALORAKK_WAVE1 "Get da move on, guards! It be killin' time!" +#define SOUND_NALORAKK_WAVE1 12066 +#define YELL_NALORAKK_WAVE2 "Guards, go already! Who you more afraid of, dem... or me?" +#define SOUND_NALORAKK_WAVE2 12067 +#define YELL_NALORAKK_WAVE3 "Ride now! Ride out dere and bring me back some heads!" +#define SOUND_NALORAKK_WAVE3 12068 +#define YELL_NALORAKK_WAVE4 "I be losin' me patience! Go on: make dem wish dey was never born!" +#define SOUND_NALORAKK_WAVE4 12069 + +//Unimplemented SoundIDs +/* +#define SOUND_NALORAKK_EVENT1 12078 +#define SOUND_NALORAKK_EVENT2 12079 +*/ + +//General defines +#define YELL_AGGRO "You be dead soon enough!" +#define SOUND_YELL_AGGRO 12070 +#define YELL_KILL_ONE "Mua-ha-ha! Now whatchoo got to say?" +#define SOUND_YELL_KILL_ONE 12075 +#define YELL_KILL_TWO "Da Amani gonna rule again!" +#define SOUND_YELL_KILL_TWO 12076 +#define YELL_DEATH "I... be waitin' on da udda side...." +#define SOUND_YELL_DEATH 12077 +#define YELL_BERSERK "You had your chance, now it be too late!" //Never seen this being used, so just guessing from what I hear. +#define SOUND_YELL_BERSERK 12074 + +#define SPELL_BERSERK 45078 + +//Defines for Troll form +#define SPELL_BRUTALSWIPE 42384 +#define SPELL_MANGLE 42389 +#define SPELL_MANGLEEFFECT 44955 +#define SPELL_SURGE 42402 +#define SPELL_BEARFORM 42377 + +#define YELL_SURGE "I bring da pain!" +#define SOUND_YELL_SURGE 12071 + +#define YELL_SHIFTEDTOTROLL "Make way for Nalorakk!" +#define SOUND_YELL_TOTROLL 12073 + +//Defines for Bear form +#define SPELL_LACERATINGSLASH 42395 +#define SPELL_RENDFLESH 42397 +#define SPELL_DEAFENINGROAR 42398 + +#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!" +#define SOUND_YELL_TOBEAR 12072 + +struct boss_nalorakkAI : public ScriptedAI +{ + boss_nalorakkAI(Creature *c) : ScriptedAI(c) + { + MoveEvent = true; + MovePhase = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 BrutalSwipe_Timer; + uint32 Mangle_Timer; + uint32 Surge_Timer; + + uint32 LaceratingSlash_Timer; + uint32 RendFlesh_Timer; + uint32 DeafeningRoar_Timer; + + uint32 ShapeShift_Timer; + uint32 Berserk_Timer; + + bool inBearForm; + bool MoveEvent; + bool inMove; + uint32 MovePhase; + uint32 waitTimer; + + void Reset() + { + if (MoveEvent) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + inMove = false; + waitTimer = 0; + me->SetSpeed(MOVE_RUN,2); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + }else + { + (*me).GetMotionMaster()->MovePoint(0,NalorakkWay[7][0],NalorakkWay[7][1],NalorakkWay[7][2]); + } + + if (pInstance) + pInstance->SetData(DATA_NALORAKKEVENT, NOT_STARTED); + + Surge_Timer = 15000 + rand()%5000; + BrutalSwipe_Timer = 7000 + rand()%5000; + Mangle_Timer = 10000 + rand()%5000; + ShapeShift_Timer = 45000 + rand()%5000; + Berserk_Timer = 600000; + + inBearForm = false; + // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); // TODO: find the correct equipment id + } + + void SendAttacker(Unit *pTarget) + { + std::list templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::AllFriendlyCreaturesInGrid check(me); + Trinity::CreatureListSearcher searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap())); + } + + if (!templist.size()) + return; + + for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) + { + if ((*i) && me->IsWithinDistInMap((*i),25)) + { + (*i)->SetNoCallAssistance(true); + (*i)->AI()->AttackStart(pTarget); + } + } + } + + void AttackStart(Unit* who) + { + if (!MoveEvent) + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (!MoveEvent) + { + ScriptedAI::MoveInLineOfSight(who); + } + else + { + if (me->IsHostileTo(who)) + { + if (!inMove) + { + switch(MovePhase) + { + case 0: + if (me->IsWithinDistInMap(who, 50)) + { + me->MonsterYell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1); + + (*me).GetMotionMaster()->MovePoint(1,NalorakkWay[1][0],NalorakkWay[1][1],NalorakkWay[1][2]); + MovePhase ++; + inMove = true; + + SendAttacker(who); + } + break; + case 2: + if (me->IsWithinDistInMap(who, 40)) + { + me->MonsterYell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2); + + (*me).GetMotionMaster()->MovePoint(3,NalorakkWay[3][0],NalorakkWay[3][1],NalorakkWay[3][2]); + MovePhase ++; + inMove = true; + + SendAttacker(who); + } + break; + case 5: + if (me->IsWithinDistInMap(who, 40)) + { + me->MonsterYell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3); + + (*me).GetMotionMaster()->MovePoint(6,NalorakkWay[6][0],NalorakkWay[6][1],NalorakkWay[6][2]); + MovePhase ++; + inMove = true; + + SendAttacker(who); + } + break; + case 7: + if (me->IsWithinDistInMap(who, 50)) + { + SendAttacker(who); + + me->MonsterYell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + MoveEvent = false; + } + break; + } + } + } + } + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS); + + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_AGGRO); + DoZoneInCombat(); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_NALORAKKEVENT, DONE); + + me->MonsterYell(YELL_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me, SOUND_YELL_DEATH); + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,1)) + { + case 0: + me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); + break; + case 1: + me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); + break; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (MoveEvent) + { + if (type != POINT_MOTION_TYPE) + return; + + if (!inMove) + return; + + if (MovePhase != id) + return; + + switch(MovePhase) + { + case 2: + me->SetOrientation(3.1415*2); + inMove = false; + return; + case 1: + case 3: + case 4: + case 6: + MovePhase ++; + waitTimer = 1; + inMove = true; + return; + case 5: + me->SetOrientation(3.1415*0.5); + inMove = false; + return; + case 7: + me->SetOrientation(3.1415*0.5); + inMove = false; + return; + } + + } + } + + void UpdateAI(const uint32 diff) + { + if (waitTimer) + { + if (inMove) + if (waitTimer <= diff) + { + (*me).GetMotionMaster()->MovementExpired(); + (*me).GetMotionMaster()->MovePoint(MovePhase,NalorakkWay[MovePhase][0],NalorakkWay[MovePhase][1],NalorakkWay[MovePhase][2]); + waitTimer = 0; + } else waitTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_BERSERK); + Berserk_Timer = 600000; + } else Berserk_Timer -= diff; + + if (ShapeShift_Timer <= diff) + { + if (inBearForm) + { + // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); + me->MonsterYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_TOTROLL); + me->RemoveAurasDueToSpell(SPELL_BEARFORM); + Surge_Timer = 15000 + rand()%5000; + BrutalSwipe_Timer = 7000 + rand()%5000; + Mangle_Timer = 10000 + rand()%5000; + ShapeShift_Timer = 45000 + rand()%5000; + inBearForm = false; + } + else + { + // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0); + me->MonsterYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_TOBEAR); + DoCast(me, SPELL_BEARFORM, true); + LaceratingSlash_Timer = 2000; // dur 18s + RendFlesh_Timer = 3000; // dur 5s + DeafeningRoar_Timer = 5000 + rand()%5000; // dur 2s + ShapeShift_Timer = 20000 + rand()%5000; // dur 30s + inBearForm = true; + } + } else ShapeShift_Timer -= diff; + + if (!inBearForm) + { + if (BrutalSwipe_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BRUTALSWIPE); + BrutalSwipe_Timer = 7000 + rand()%5000; + } else BrutalSwipe_Timer -= diff; + + if (Mangle_Timer <= diff) + { + if (me->getVictim() && !me->getVictim()->HasAura(SPELL_MANGLEEFFECT)) + { + DoCast(me->getVictim(), SPELL_MANGLE); + Mangle_Timer = 1000; + } + else Mangle_Timer = 10000 + rand()%5000; + } else Mangle_Timer -= diff; + + if (Surge_Timer <= diff) + { + me->MonsterYell(YELL_SURGE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_YELL_SURGE); + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true); + if (pTarget) + DoCast(pTarget, SPELL_SURGE); + Surge_Timer = 15000 + rand()%5000; + } else Surge_Timer -= diff; + } + else + { + if (LaceratingSlash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LACERATINGSLASH); + LaceratingSlash_Timer = 18000 + rand()%5000; + } else LaceratingSlash_Timer -= diff; + + if (RendFlesh_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_RENDFLESH); + RendFlesh_Timer = 5000 + rand()%5000; + } else RendFlesh_Timer -= diff; + + if (DeafeningRoar_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DEAFENINGROAR); + DeafeningRoar_Timer = 15000 + rand()%5000; + } else DeafeningRoar_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nalorakk(Creature* pCreature) +{ + return new boss_nalorakkAI (pCreature); +} + +void AddSC_boss_nalorakk() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nalorakk"; + newscript->GetAI = &GetAI_boss_nalorakk; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp new file mode 100644 index 00000000000..91cfa728f89 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp @@ -0,0 +1,623 @@ +/* Copyright (C) 2006,2007,2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_ZulJin +SD%Complete: 85% +SDComment: +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" + +//Speech +#define YELL_TRANSFORM_TO_LYNX "Let me introduce to you my new bruddahs: fang and claw!" +#define SOUND_TRANSFORM_TO_LYNX 12094 + +#define YELL_TRANSFORM_TO_BEAR "Got me some new tricks...like me bruddah bear!" +#define SOUND_TRANSFORM_TO_BEAR 12092 + +#define YELL_TRANSFORM_TO_DRAGONHAWK "Ya don' have to look to da sky to see da dragonhawk!" +#define SOUND_TRANSFORM_TO_DRAGONHAWK 12095 + +#define YELL_TRANSFORM_TO_EAGLE "Dere be no hidin' from da eagle!" +#define SOUND_TRANSFORM_TO_EAGLE 12093 + +#define YELL_KILL_ONE "Da Amani de chuka!" +#define SOUND_KILL_ONE 12098 + +#define YELL_KILL_TWO "Lot more gonna fall like you!" +#define SOUND_KILL_TWO 12099 + +#define YELL_FIRE_BREATH "Fire kill you just as quick!" +#define SOUND_FIRE_BRETH 12096 + +#define YELL_AGGRO "Nobody badduh dan me!" +#define SOUND_AGGRO 12091 + +#define YELL_BERSERK "You too slow! Me too strong!" +#define SOUND_BERSERK 12097 + +#define YELL_DEATH "Mebbe me fall...but da Amani empire...never gonna die..." +#define SOUND_DEATH 12100 + +//Still not used, need more info +#define YELL_INTRO "Everybody always wanna take from us. Now we gonna start takin' back. Anybody who get in our way...gonna drown in their own blood! De Amani empire be back now...seekin' vengeance. And we gonna start...with you!" +#define SOUND_INTRO 12090 + +//Spells: +//====== Troll Form +#define SPELL_WHIRLWIND 17207 +#define SPELL_GRIEVOUS_THROW 43093 // remove debuff after full healed +//====== Bear Form +#define SPELL_CREEPING_PARALYSIS 43095 // should cast on the whole raid +#define SPELL_OVERPOWER 43456 // use after melee attack dodged +//====== Eagle Form +#define SPELL_ENERGY_STORM 43983 // enemy area aura, trigger 42577 +#define SPELL_ZAP_INFORM 42577 +#define SPELL_ZAP_DAMAGE 43137 // 1250 damage +#define SPELL_SUMMON_CYCLONE 43112 // summon four feather vortex +#define CREATURE_FEATHER_VORTEX 24136 +#define SPELL_CYCLONE_VISUAL 43119 // trigger 43147 visual +#define SPELL_CYCLONE_PASSIVE 43120 // trigger 43121 (4y aoe) every second +//Lynx Form +#define SPELL_CLAW_RAGE_HASTE 42583 +#define SPELL_CLAW_RAGE_TRIGGER 43149 +#define SPELL_CLAW_RAGE_DAMAGE 43150 +#define SPELL_LYNX_RUSH_HASTE 43152 +#define SPELL_LYNX_RUSH_DAMAGE 43153 +//Dragonhawk Form +#define SPELL_FLAME_WHIRL 43213 // trigger two spells +#define SPELL_FLAME_BREATH 43215 +#define SPELL_SUMMON_PILLAR 43216 // summon 24187 +#define CREATURE_COLUMN_OF_FIRE 24187 +#define SPELL_PILLAR_TRIGGER 43218 // trigger 43217 + +//cosmetic +#define SPELL_SPIRIT_AURA 42466 +#define SPELL_SIPHON_SOUL 43501 + +//Transforms: +#define SPELL_SHAPE_OF_THE_BEAR 42594 // 15% dmg +#define SPELL_SHAPE_OF_THE_EAGLE 42606 +#define SPELL_SHAPE_OF_THE_LYNX 42607 // haste melee 30% +#define SPELL_SHAPE_OF_THE_DRAGONHAWK 42608 + +#define SPELL_BERSERK 45078 + +#define PHASE_BEAR 0 +#define PHASE_EAGLE 1 +#define PHASE_LYNX 2 +#define PHASE_DRAGONHAWK 3 +#define PHASE_TROLL 4 + +//coords for going for changing form +#define CENTER_X 120.148811 +#define CENTER_Y 703.713684 +#define CENTER_Z 45.111477 + +struct SpiritInfoStruct +{ + uint32 entry; + float x, y, z, orient; +}; + +static SpiritInfoStruct SpiritInfo[] = +{ + {23878, 147.87, 706.51, 45.11, 3.04}, + {23880, 88.95, 705.49, 45.11, 6.11}, + {23877, 137.23, 725.98, 45.11, 3.71}, + {23879, 104.29, 726.43, 45.11, 5.43} +}; + +struct TransformStruct +{ + uint32 sound; + char* text; + uint32 spell, unaura; +}; + +static TransformStruct Transform[] = +{ + {SOUND_TRANSFORM_TO_BEAR, YELL_TRANSFORM_TO_BEAR, SPELL_SHAPE_OF_THE_BEAR, SPELL_WHIRLWIND}, + {SOUND_TRANSFORM_TO_EAGLE, YELL_TRANSFORM_TO_EAGLE, SPELL_SHAPE_OF_THE_EAGLE, SPELL_SHAPE_OF_THE_BEAR}, + {SOUND_TRANSFORM_TO_LYNX, YELL_TRANSFORM_TO_LYNX, SPELL_SHAPE_OF_THE_LYNX, SPELL_SHAPE_OF_THE_EAGLE}, + {SOUND_TRANSFORM_TO_DRAGONHAWK, YELL_TRANSFORM_TO_DRAGONHAWK, SPELL_SHAPE_OF_THE_DRAGONHAWK, SPELL_SHAPE_OF_THE_LYNX} +}; + +struct boss_zuljinAI : public ScriptedAI +{ + boss_zuljinAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + ScriptedInstance *pInstance; + + uint64 SpiritGUID[4]; + uint64 ClawTargetGUID; + uint64 TankGUID; + + uint32 Phase; + uint32 health_20; + + uint32 Intro_Timer; + uint32 Berserk_Timer; + + uint32 Whirlwind_Timer; + uint32 Grievous_Throw_Timer; + + uint32 Creeping_Paralysis_Timer; + uint32 Overpower_Timer; + + uint32 Claw_Rage_Timer; + uint32 Lynx_Rush_Timer; + uint32 Claw_Counter; + uint32 Claw_Loop_Timer; + + uint32 Flame_Whirl_Timer; + uint32 Flame_Breath_Timer; + uint32 Pillar_Of_Fire_Timer; + + SummonList Summons; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_ZULJINEVENT, NOT_STARTED); + + Phase = 0; + + health_20 = me->GetMaxHealth()*0.2; + + Intro_Timer = 37000; + Berserk_Timer = 600000; + + Whirlwind_Timer = 7000; + Grievous_Throw_Timer = 8000; + + Creeping_Paralysis_Timer = 7000; + Overpower_Timer = 0; + + Claw_Rage_Timer = 5000; + Lynx_Rush_Timer = 14000; + Claw_Loop_Timer = 0; + Claw_Counter = 0; + + Flame_Whirl_Timer = 5000; + Flame_Breath_Timer = 6000; + Pillar_Of_Fire_Timer = 7000; + + ClawTargetGUID = 0; + TankGUID = 0; + + Summons.DespawnAll(); + + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 47174); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674); + //me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_ZULJINEVENT, IN_PROGRESS); + + DoZoneInCombat(); + + me->MonsterYell(YELL_INTRO,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me, SOUND_INTRO); + SpawnAdds(); + EnterPhase(0); + } + + void KilledUnit(Unit* /*victim*/) + { + if (Intro_Timer) + return; + + switch (urand(0,1)) + { + case 0: + me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL_ONE); + break; + case 1: + me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_KILL_TWO); + break; + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ZULJINEVENT, DONE); + + me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_DEATH); + Summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE); + + if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[3])) + Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); + } + + void AttackStart(Unit *who) + { + if (Phase == 2) + AttackStartNoMove(who); + else + ScriptedAI::AttackStart(who); + } + + void DoMeleeAttackIfReady() + { + if (!me->IsNonMeleeSpellCasted(false)) + { + if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim())) + { + if (Phase == 1 && !Overpower_Timer) + { + uint32 health = me->getVictim()->GetHealth(); + me->AttackerStateUpdate(me->getVictim()); + if (me->getVictim() && health == me->getVictim()->GetHealth()) + { + DoCast(me->getVictim(), SPELL_OVERPOWER, false); + Overpower_Timer = 5000; + } + } else me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + } + + void SpawnAdds() + { + Creature *pCreature = NULL; + for (uint8 i = 0; i < 4; ++i) + { + pCreature = me->SummonCreature(SpiritInfo[i].entry, SpiritInfo[i].x, SpiritInfo[i].y, SpiritInfo[i].z, SpiritInfo[i].orient, TEMPSUMMON_DEAD_DESPAWN, 0); + if (pCreature) + { + pCreature->CastSpell(pCreature, SPELL_SPIRIT_AURA, true); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + SpiritGUID[i] = pCreature->GetGUID(); + } + } + } + + void DespawnAdds() + { + for (uint8 i = 0; i < 4; ++i) + { + Unit* Temp = NULL; + if (SpiritGUID[i]) + { + if (Temp = Unit::GetUnit(*me, SpiritGUID[i])) + { + Temp->SetVisibility(VISIBILITY_OFF); + Temp->setDeathState(DEAD); + } + } + SpiritGUID[i] = 0; + } + } + + void JustSummoned(Creature *summon) + { + Summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature *summon) + { + Summons.Despawn(summon); + } + + void EnterPhase(uint32 NextPhase) + { + switch(NextPhase) + { + case 0: + break; + case 1: + case 2: + case 3: + case 4: + DoTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, 100); + DoResetThreat(); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + me->RemoveAurasDueToSpell(Transform[Phase].unaura); + DoCast(me, Transform[Phase].spell); + me->MonsterYell(Transform[Phase].text, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, Transform[Phase].sound); + if (Phase > 0) + { + if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[Phase - 1])) + Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); + } + if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[NextPhase - 1])) + Temp->CastSpell(me, SPELL_SIPHON_SOUL, false); // should m cast on temp + if (NextPhase == 2) + { + me->GetMotionMaster()->Clear(); + DoCast(me, SPELL_ENERGY_STORM, true); // enemy aura + for (uint8 i = 0; i < 4; ++i) + { + Creature* Vortex = DoSpawnCreature(CREATURE_FEATHER_VORTEX, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Vortex) + { + Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true); + Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true); + Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Vortex->SetSpeed(MOVE_RUN, 1.0f); + Vortex->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + DoZoneInCombat(Vortex); + } + } + } + else + me->AI()->AttackStart(me->getVictim()); + if (NextPhase == 3) + { + me->RemoveAurasDueToSpell(SPELL_ENERGY_STORM); + Summons.DespawnEntry(CREATURE_FEATHER_VORTEX); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + break; + default: + break; + } + Phase = NextPhase; + } + + void UpdateAI(const uint32 diff) + { + if (!TankGUID) + { + if (!UpdateVictim()) + return; + + if (me->GetHealth() < health_20 * (4 - Phase)) + EnterPhase(Phase + 1); + } + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_BERSERK); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + switch (Phase) + { + case 0: + if (Intro_Timer) + { + if (Intro_Timer <= diff) + { + me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_AGGRO); + Intro_Timer = 0; + } else Intro_Timer -= diff; + } + + if (Whirlwind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + Whirlwind_Timer = 15000 + rand()%5000; + } else Whirlwind_Timer -= diff; + + if (Grievous_Throw_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_GRIEVOUS_THROW, false); + Grievous_Throw_Timer = 10000; + } else Grievous_Throw_Timer -= diff; + break; + + case 1: + if (Creeping_Paralysis_Timer <= diff) + { + DoCast(me, SPELL_CREEPING_PARALYSIS); + Creeping_Paralysis_Timer = 20000; + } else Creeping_Paralysis_Timer -= diff; + + if (Overpower_Timer <= diff) + { + // implemented in DoMeleeAttackIfReady() + Overpower_Timer = 0; + } else Overpower_Timer -= diff; + break; + + case 2: + return; + + case 3: + if (Claw_Rage_Timer <= diff) + { + if (!TankGUID) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + TankGUID = me->getVictim()->GetGUID(); + me->SetSpeed(MOVE_RUN, 5.0f); + AttackStart(pTarget); // change victim + Claw_Rage_Timer = 0; + Claw_Loop_Timer = 500; + Claw_Counter = 0; + } + } + else if (!Claw_Rage_Timer) // do not do this when Lynx_Rush + { + if (Claw_Loop_Timer <= diff) + { + Unit *pTarget = me->getVictim(); + if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = Unit::GetUnit(*me, TankGUID); + if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + AttackStart(pTarget); + if (me->IsWithinMeleeRange(pTarget)) + { + DoCast(pTarget, SPELL_CLAW_RAGE_DAMAGE, true); + ++Claw_Counter; + if (Claw_Counter == 12) + { + Claw_Rage_Timer = 15000 + rand()%5000; + me->SetSpeed(MOVE_RUN, 1.2f); + AttackStart(Unit::GetUnit(*me, TankGUID)); + TankGUID = 0; + return; + } + else + Claw_Loop_Timer = 500; + } + } + else + { + EnterEvadeMode(); // if (pTarget) + return; + } + } else Claw_Loop_Timer -= diff; + } //if (TankGUID) + } else Claw_Rage_Timer -= diff; + + if (Lynx_Rush_Timer <= diff) + { + if (!TankGUID) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + TankGUID = me->getVictim()->GetGUID(); + me->SetSpeed(MOVE_RUN, 5.0f); + AttackStart(pTarget); // change victim + Lynx_Rush_Timer = 0; + Claw_Counter = 0; + } + } + else if (!Lynx_Rush_Timer) + { + Unit *pTarget = me->getVictim(); + if (!pTarget || !pTarget->isTargetableForAttack()) + { + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + AttackStart(pTarget); + } + if (pTarget) + { + if (me->IsWithinMeleeRange(pTarget)) + { + DoCast(pTarget, SPELL_LYNX_RUSH_DAMAGE, true); + ++Claw_Counter; + if (Claw_Counter == 9) + { + Lynx_Rush_Timer = 15000 + rand()%5000; + me->SetSpeed(MOVE_RUN, 1.2f); + AttackStart(Unit::GetUnit(*me, TankGUID)); + TankGUID = 0; + } + else + AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + } + } + else + { + EnterEvadeMode(); // if (pTarget) + return; + } + } //if (TankGUID) + } else Lynx_Rush_Timer -= diff; + + break; + case 4: + if (Flame_Whirl_Timer <= diff) + { + DoCast(me, SPELL_FLAME_WHIRL); + Flame_Whirl_Timer = 12000; + }Flame_Whirl_Timer -= diff; + + if (Pillar_Of_Fire_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SUMMON_PILLAR); + Pillar_Of_Fire_Timer = 10000; + } else Pillar_Of_Fire_Timer -= diff; + + if (Flame_Breath_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + me->SetInFront(pTarget); + DoCast(me, SPELL_FLAME_BREATH); + Flame_Breath_Timer = 10000; + } else Flame_Breath_Timer -= diff; + break; + + default: + break; + } + + if (!TankGUID) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_zuljin(Creature* pCreature) +{ + return new boss_zuljinAI (pCreature); +} + +struct feather_vortexAI : public ScriptedAI +{ + feather_vortexAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + + void EnterCombat(Unit * /*pTarget*/) {} + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_ZAP_INFORM) + DoCast(caster, SPELL_ZAP_DAMAGE, true); + } + + void UpdateAI(const uint32 /*diff*/) + { + //if the vortex reach the target, it change his target to another player + if (me->IsWithinMeleeRange(me->getVictim())) + AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + } +}; + +CreatureAI* GetAI_feather_vortexAI(Creature* pCreature) +{ + return new feather_vortexAI (pCreature); +} + +void AddSC_boss_zuljin() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_zuljin"; + newscript->GetAI = &GetAI_boss_zuljin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_zuljin_vortex"; + newscript->GetAI = &GetAI_feather_vortexAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp new file mode 100644 index 00000000000..897330691a6 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp @@ -0,0 +1,320 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: instance_zulaman +SD%Complete: 80 +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulaman.h" + +#define MAX_ENCOUNTER 6 +#define RAND_VENDOR 2 + +//187021 //Harkor's Satchel +//186648 //Tanzar's Trunk +//186672 //Ashli's Bag +//186667 //Kraz's Package +// Chests spawn at bear/eagle/dragonhawk/lynx bosses +// The loots depend on how many bosses have been killed, but not the entries of the chests +// But we cannot add loots to gameobject, so we have to use the fixed loot_template +struct SHostageInfo +{ + uint32 npc, pGo; + float x, y, z, o; +}; + +static SHostageInfo HostageInfo[] = +{ + {23790, 186648, -57, 1343, 40.77, 3.2}, // bear + {23999, 187021, 400, 1414, 74.36, 3.3}, // eagle + {24001, 186672, -35, 1134, 18.71, 1.9}, // dragonhawk + {24024, 186667, 413, 1117, 6.32, 3.1} // lynx + +}; + +struct instance_zulaman : public ScriptedInstance +{ + instance_zulaman(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 HarkorsSatchelGUID; + uint64 TanzarsTrunkGUID; + uint64 AshlisBagGUID; + uint64 KrazsPackageGUID; + + uint64 HexLordGateGUID; + uint64 ZulJinGateGUID; + uint64 AkilzonDoorGUID; + uint64 ZulJinDoorGUID; + uint64 HalazziDoorGUID; + + uint32 QuestTimer; + uint16 BossKilled; + uint16 QuestMinute; + uint16 ChestLooted; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 RandVendor[RAND_VENDOR]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + HarkorsSatchelGUID = 0; + TanzarsTrunkGUID = 0; + AshlisBagGUID = 0; + KrazsPackageGUID = 0; + + HexLordGateGUID = 0; + ZulJinGateGUID = 0; + AkilzonDoorGUID = 0; + HalazziDoorGUID = 0; + ZulJinDoorGUID = 0; + + QuestTimer = 0; + QuestMinute = 21; + BossKilled = 0; + ChestLooted = 0; + + for (uint8 i = 0; i < RAND_VENDOR; ++i) + RandVendor[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 23578://janalai + case 23863://zuljin + case 24239://hexlord + case 23577://halazzi + case 23576://nalorakk + default: break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 186303: HalazziDoorGUID = pGo->GetGUID(); break; + case 186304: ZulJinGateGUID = pGo->GetGUID(); break; + case 186305: HexLordGateGUID = pGo->GetGUID(); break; + case 186858: AkilzonDoorGUID = pGo->GetGUID(); break; + case 186859: ZulJinDoorGUID = pGo->GetGUID(); break; + + case 187021: HarkorsSatchelGUID = pGo->GetGUID(); break; + case 186648: TanzarsTrunkGUID = pGo->GetGUID(); break; + case 186672: AshlisBagGUID = pGo->GetGUID(); break; + case 186667: KrazsPackageGUID = pGo->GetGUID(); break; + default: break; + + } + CheckInstanceStatus(); + } + + void SummonHostage(uint8 num) + { + if (!QuestMinute) + return; + + Map::PlayerList const &PlayerList = instance->GetPlayers(); + if (PlayerList.isEmpty()) + return; + + Map::PlayerList::const_iterator i = PlayerList.begin(); + if (Player* i_pl = i->getSource()) + { + if (Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0)) + { + Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + } + } + + void CheckInstanceStatus() + { + if (BossKilled >= 4) + HandleGameObject(HexLordGateGUID, true); + + if (BossKilled >= 5) + HandleGameObject(ZulJinGateGUID, true); + } + + std::string GetSaveData() + { + std::ostringstream ss; + ss << "S " << BossKilled << " " << ChestLooted << " " << QuestMinute; + char* data = new char[ss.str().length()+1]; + strcpy(data, ss.str().c_str()); + //error_log("TSCR: Zul'aman saved, %s.", data); + return data; + } + + void Load(const char* load) + { + if (!load) return; + std::istringstream ss(load); + //error_log("TSCR: Zul'aman loaded, %s.", ss.str().c_str()); + char dataHead; // S + uint16 data1, data2, data3; + ss >> dataHead >> data1 >> data2 >> data3; + //error_log("TSCR: Zul'aman loaded, %d %d %d.", data1, data2, data3); + if (dataHead == 'S') + { + BossKilled = data1; + ChestLooted = data2; + QuestMinute = data3; + } else error_log("TSCR: Zul'aman: corrupted save data."); + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_NALORAKKEVENT: + m_auiEncounter[0] = data; + if (data == DONE) + { + if (QuestMinute) + { + QuestMinute += 15; + DoUpdateWorldState(3106, QuestMinute); + } + SummonHostage(0); + } + break; + case DATA_AKILZONEVENT: + m_auiEncounter[1] = data; + HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS); + if (data == DONE) + { + if (QuestMinute) + { + QuestMinute += 10; + DoUpdateWorldState(3106, QuestMinute); + } + SummonHostage(1); + } + break; + case DATA_JANALAIEVENT: + m_auiEncounter[2] = data; + if (data == DONE) SummonHostage(2); + break; + case DATA_HALAZZIEVENT: + m_auiEncounter[3] = data; + HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS); + if (data == DONE) SummonHostage(3); + break; + case DATA_HEXLORDEVENT: + m_auiEncounter[4] = data; + if (data == IN_PROGRESS) + HandleGameObject(HexLordGateGUID, false); + else if (data == NOT_STARTED) + CheckInstanceStatus(); + break; + case DATA_ZULJINEVENT: + m_auiEncounter[5] = data; + HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS); + break; + case DATA_CHESTLOOTED: + ++ChestLooted; + SaveToDB(); + break; + case TYPE_RAND_VENDOR_1: + RandVendor[0] = data; + break; + case TYPE_RAND_VENDOR_2: + RandVendor[1] = data; + break; + } + + if (data == DONE) + { + ++BossKilled; + if (QuestMinute && BossKilled >= 4) + { + QuestMinute = 0; + DoUpdateWorldState(3104, 0); + } + CheckInstanceStatus(); + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_NALORAKKEVENT: return m_auiEncounter[0]; + case DATA_AKILZONEVENT: return m_auiEncounter[1]; + case DATA_JANALAIEVENT: return m_auiEncounter[2]; + case DATA_HALAZZIEVENT: return m_auiEncounter[3]; + case DATA_HEXLORDEVENT: return m_auiEncounter[4]; + case DATA_ZULJINEVENT: return m_auiEncounter[5]; + case DATA_CHESTLOOTED: return ChestLooted; + case TYPE_RAND_VENDOR_1: return RandVendor[0]; + case TYPE_RAND_VENDOR_2: return RandVendor[1]; + default: return 0; + } + } + + void Update(uint32 diff) + { + if (QuestMinute) + { + if (QuestTimer <= diff) + { + QuestMinute--; + SaveToDB(); + QuestTimer += 60000; + if (QuestMinute) + { + DoUpdateWorldState(3104, 1); + DoUpdateWorldState(3106, QuestMinute); + } else DoUpdateWorldState(3104, 0); + } + QuestTimer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_zulaman(Map* pMap) +{ + return new instance_zulaman(pMap); +} + +void AddSC_instance_zulaman() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_zulaman"; + newscript->GetInstanceData = &GetInstanceData_instance_zulaman; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp new file mode 100644 index 00000000000..067ae687644 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp @@ -0,0 +1,192 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Zulaman +SD%Complete: 90 +SDComment: Forest Frog will turn into different NPC's. Workaround to prevent new entry from running this script +SDCategory: Zul'Aman +EndScriptData */ + +/* ContentData +npc_forest_frog +EndContentData */ + +#include "ScriptedPch.h" +#include "zulaman.h" + +/*###### +## npc_forest_frog +######*/ + +#define SPELL_REMOVE_AMANI_CURSE 43732 +#define SPELL_PUSH_MOJO 43923 +#define ENTRY_FOREST_FROG 24396 + +struct npc_forest_frogAI : public ScriptedAI +{ + npc_forest_frogAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() {} + + void EnterCombat(Unit * /*who*/) {} + + void DoSpawnRandom() + { + if (pInstance) + { + uint32 cEntry = 0; + switch(rand()%10) + { + case 0: cEntry = 24397; break; //Mannuth + case 1: cEntry = 24403; break; //Deez + case 2: cEntry = 24404; break; //Galathryn + case 3: cEntry = 24405; break; //Adarrah + case 4: cEntry = 24406; break; //Fudgerick + case 5: cEntry = 24407; break; //Darwen + case 6: cEntry = 24445; break; //Mitzi + case 7: cEntry = 24448; break; //Christian + case 8: cEntry = 24453; break; //Brennan + case 9: cEntry = 24455; break; //Hollee + } + + if (!pInstance->GetData(TYPE_RAND_VENDOR_1)) + if (rand()%10 == 1) cEntry = 24408; //Gunter + if (!pInstance->GetData(TYPE_RAND_VENDOR_2)) + if (rand()%10 == 1) cEntry = 24409; //Kyren + + if (cEntry) me->UpdateEntry(cEntry); + + if (cEntry == 24408) pInstance->SetData(TYPE_RAND_VENDOR_1,DONE); + if (cEntry == 24409) pInstance->SetData(TYPE_RAND_VENDOR_2,DONE); + } + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && me->GetEntry() == ENTRY_FOREST_FROG) + { + //increase or decrease chance of mojo? + if (rand()%99 == 50) DoCast(caster, SPELL_PUSH_MOJO, true); + else DoSpawnRandom(); + } + } +}; +CreatureAI* GetAI_npc_forest_frog(Creature* pCreature) +{ + return new npc_forest_frogAI (pCreature); +} + +/*###### +## npc_zulaman_hostage +######*/ + +#define GOSSIP_HOSTAGE1 "I am glad to help you." + +static uint32 HostageEntry[] = {23790, 23999, 24024, 24001}; +static uint32 ChestEntry[] = {186648, 187021, 186672, 186667}; + +struct npc_zulaman_hostageAI : public ScriptedAI +{ + npc_zulaman_hostageAI(Creature *c) : ScriptedAI(c) {IsLoot = false;} + bool IsLoot; + uint64 PlayerGUID; + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + void JustDied(Unit* /*who*/) + { + Player* pPlayer = Unit::GetPlayer(PlayerGUID); + if (pPlayer) pPlayer->SendLoot(me->GetGUID(), LOOT_CORPSE); + } + void UpdateAI(const uint32 /*diff*/) + { + if (IsLoot) + DoCast(me, 7, false); + } +}; + +bool GossipHello_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HOSTAGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + pPlayer->CLOSE_GOSSIP_MENU(); + + if (!pCreature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) + return true; + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance) + { + //uint8 progress = pInstance->GetData(DATA_CHESTLOOTED); + pInstance->SetData(DATA_CHESTLOOTED, 0); + float x, y, z; + pCreature->GetPosition(x, y, z); + uint32 entry = pCreature->GetEntry(); + for (uint8 i = 0; i < 4; ++i) + { + if (HostageEntry[i] == entry) + { + pCreature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0); + break; + } + } + /*Creature* summon = pCreature->SummonCreature(HostageInfo[progress], x-2, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + if (summon) + { + CAST_AI(npc_zulaman_hostageAI, summon->AI())->PlayerGUID = pPlayer->GetGUID(); + CAST_AI(npc_zulaman_hostageAI, summon->AI())->IsLoot = true; + summon->SetDisplayId(10056); + summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + }*/ + } + return true; +} + +CreatureAI* GetAI_npc_zulaman_hostage(Creature* pCreature) +{ + return new npc_zulaman_hostageAI(pCreature); +} + +void AddSC_zulaman() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_forest_frog"; + newscript->GetAI = &GetAI_npc_forest_frog; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_zulaman_hostage"; + newscript->GetAI = &GetAI_npc_zulaman_hostage; + newscript->pGossipHello = &GossipHello_npc_zulaman_hostage; + newscript->pGossipSelect = &GossipSelect_npc_zulaman_hostage; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h new file mode 100644 index 00000000000..6fb0ef173bd --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ZULAMAN_H +#define DEF_ZULAMAN_H + +#define DATA_NALORAKKEVENT 1 +#define DATA_AKILZONEVENT 2 +#define DATA_JANALAIEVENT 3 +#define DATA_HALAZZIEVENT 4 +#define DATA_HEXLORDEVENT 5 +#define DATA_ZULJINEVENT 6 +#define DATA_CHESTLOOTED 7 +#define TYPE_RAND_VENDOR_1 8 +#define TYPE_RAND_VENDOR_2 9 + +#endif + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp new file mode 100644 index 00000000000..cbbe6c4dc4c --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -0,0 +1,278 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Arlokk +SD%Complete: 95 +SDComment: Wrong cleave and red aura is missing. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +bool GOHello_go_gong_of_bethekk(Player* /*pPlayer*/, GameObject* pGo) +{ + if (ScriptedInstance* m_pInstance = pGo->GetInstanceData()) + { + if (m_pInstance->GetData(TYPE_ARLOKK) == DONE || m_pInstance->GetData(TYPE_ARLOKK) == IN_PROGRESS) + return true; + + m_pInstance->SetData(TYPE_ARLOKK, IN_PROGRESS); + return true; + } + + return true; +} + +enum eEnums +{ + SAY_AGGRO = -1309011, + SAY_FEAST_PANTHER = -1309012, + SAY_DEATH = -1309013, + + SPELL_SHADOWWORDPAIN = 23952, + SPELL_GOUGE = 24698, + SPELL_MARK = 24210, + SPELL_CLEAVE = 26350, //Perhaps not right. Not a red aura... + SPELL_PANTHER_TRANSFORM = 24190, + + MODEL_ID_NORMAL = 15218, + MODEL_ID_PANTHER = 15215, + MODEL_ID_BLANK = 11686, + + NPC_ZULIAN_PROWLER = 15101 +}; + +struct boss_arlokkAI : public ScriptedAI +{ + boss_arlokkAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiShadowWordPain_Timer; + uint32 m_uiGouge_Timer; + uint32 m_uiMark_Timer; + uint32 m_uiCleave_Timer; + uint32 m_uiVanish_Timer; + uint32 m_uiVisible_Timer; + + uint32 m_uiSummon_Timer; + uint32 m_uiSummonCount; + + Unit* m_pMarkedTarget; + uint64 MarkedTargetGUID; + + bool m_bIsPhaseTwo; + bool m_bIsVanished; + + void Reset() + { + m_uiShadowWordPain_Timer = 8000; + m_uiGouge_Timer = 14000; + m_uiMark_Timer = 35000; + m_uiCleave_Timer = 4000; + m_uiVanish_Timer = 60000; + m_uiVisible_Timer = 6000; + + m_uiSummon_Timer = 5000; + m_uiSummonCount = 0; + + m_bIsPhaseTwo = false; + m_bIsVanished = false; + + MarkedTargetGUID = 0; + + me->SetDisplayId(MODEL_ID_NORMAL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_ARLOKK, NOT_STARTED); + + //we should be summoned, so despawn + me->ForcedDespawn(); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + me->SetDisplayId(MODEL_ID_NORMAL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (m_pInstance) + m_pInstance->SetData(TYPE_ARLOKK, DONE); + } + + void DoSummonPhanters() + { + if (Unit *pMarkedTarget = Unit::GetUnit(*me, MarkedTargetGUID)) + DoScriptText(SAY_FEAST_PANTHER, me, pMarkedTarget); + + me->SummonCreature(NPC_ZULIAN_PROWLER, -11532.7998, -1649.6734, 41.4800, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + me->SummonCreature(NPC_ZULIAN_PROWLER, -11532.9970, -1606.4840, 41.2979, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + } + + void JustSummoned(Creature* pSummoned) + { + if (Unit *pMarkedTarget = Unit::GetUnit(*me, MarkedTargetGUID)) + pSummoned->AI()->AttackStart(pMarkedTarget); + + ++m_uiSummonCount; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (!m_bIsPhaseTwo) + { + if (m_uiShadowWordPain_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); + m_uiShadowWordPain_Timer = 15000; + } + else + m_uiShadowWordPain_Timer -= uiDiff; + + if (m_uiMark_Timer <= uiDiff) + { + Unit *pMarkedTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (pMarkedTarget) + { + DoCast(pMarkedTarget, SPELL_MARK); + MarkedTargetGUID = pMarkedTarget->GetGUID(); + } + else + error_log("TSCR: boss_arlokk could not accuire pMarkedTarget."); + + m_uiMark_Timer = 15000; + } + else + m_uiMark_Timer -= uiDiff; + } + else + { + //Cleave_Timer + if (m_uiCleave_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + m_uiCleave_Timer = 16000; + } + else + m_uiCleave_Timer -= uiDiff; + + //Gouge_Timer + if (m_uiGouge_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_GOUGE); + + DoModifyThreatPercent(me->getVictim(),-80); + + m_uiGouge_Timer = 17000+rand()%10000; + } + else + m_uiGouge_Timer -= uiDiff; + } + + if (m_uiSummonCount <= 30) + { + if (m_uiSummon_Timer <= uiDiff) + { + DoSummonPhanters(); + m_uiSummon_Timer = 5000; + } + else + m_uiSummon_Timer -= uiDiff; + } + + if (m_uiVanish_Timer <= uiDiff) + { + //Invisble Model + me->SetDisplayId(MODEL_ID_BLANK); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + me->AttackStop(); + DoResetThreat(); + + m_bIsVanished = true; + + m_uiVanish_Timer = 45000; + m_uiVisible_Timer = 6000; + } + else + m_uiVanish_Timer -= uiDiff; + + if (m_bIsVanished) + { + if (m_uiVisible_Timer <= uiDiff) + { + //The Panther Model + me->SetDisplayId(MODEL_ID_PANTHER); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); + me->UpdateDamagePhysical(BASE_ATTACK); + + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + AttackStart(pTarget); + + m_bIsPhaseTwo = true; + m_bIsVanished = false; + } + else + m_uiVisible_Timer -= uiDiff; + } + else + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_arlokk(Creature* pCreature) +{ + return new boss_arlokkAI (pCreature); +} + +void AddSC_boss_arlokk() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_gong_of_bethekk"; + newscript->pGOHello = &GOHello_go_gong_of_bethekk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_arlokk"; + newscript->GetAI = &GetAI_boss_arlokk; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp new file mode 100644 index 00000000000..0201235be70 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gahz'ranka +SD%Complete: 85 +SDComment: Massive Geyser with knockback not working. Spell buggy. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FROSTBREATH 16099 +#define SPELL_MASSIVEGEYSER 22421 //Not working. Cause its a summon... +#define SPELL_SLAM 24326 + +struct boss_gahzrankaAI : public ScriptedAI +{ + boss_gahzrankaAI(Creature *c) : ScriptedAI(c) {} + uint32 Frostbreath_Timer; + uint32 MassiveGeyser_Timer; + uint32 Slam_Timer; + + void Reset() + { + Frostbreath_Timer = 8000; + MassiveGeyser_Timer = 25000; + Slam_Timer = 17000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frostbreath_Timer + if (Frostbreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBREATH); + Frostbreath_Timer = 7000 + rand()%4000; + } else Frostbreath_Timer -= diff; + + //MassiveGeyser_Timer + if (MassiveGeyser_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MASSIVEGEYSER); + DoResetThreat(); + + MassiveGeyser_Timer = 22000 + rand()%10000; + } else MassiveGeyser_Timer -= diff; + + //Slam_Timer + if (Slam_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLAM); + Slam_Timer = 12000 + rand()%8000; + } else Slam_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gahzranka(Creature* pCreature) +{ + return new boss_gahzrankaAI (pCreature); +} + +void AddSC_boss_gahzranka() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gahzranka"; + newscript->GetAI = &GetAI_boss_gahzranka; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp new file mode 100644 index 00000000000..67de135674a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp @@ -0,0 +1,93 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grilek +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SPELL_AVARTAR 24646 //The Enrage Spell +#define SPELL_GROUNDTREMOR 6524 + +struct boss_grilekAI : public ScriptedAI +{ + boss_grilekAI(Creature *c) : ScriptedAI(c) {} + + uint32 Avartar_Timer; + uint32 GroundTremor_Timer; + + void Reset() + { + Avartar_Timer = 15000 + rand()%10000; + GroundTremor_Timer = 8000 + rand()%8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Avartar_Timer + if (Avartar_Timer <= diff) + { + + DoCast(me, SPELL_AVARTAR); + Unit *pTarget = NULL; + + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-50); + if (pTarget) + AttackStart(pTarget); + + Avartar_Timer = 25000 + rand()%10000; + } else Avartar_Timer -= diff; + + //GroundTremor_Timer + if (GroundTremor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GROUNDTREMOR); + GroundTremor_Timer = 12000 + rand()%4000; + } else GroundTremor_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grilek(Creature* pCreature) +{ + return new boss_grilekAI (pCreature); +} + +void AddSC_boss_grilek() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grilek"; + newscript->GetAI = &GetAI_boss_grilek; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp new file mode 100644 index 00000000000..d7dd5020b74 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp @@ -0,0 +1,250 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hakkar +SD%Complete: 95 +SDComment: Blood siphon spell buggy cause of Core Issue. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309020 +#define SAY_FLEEING -1309021 +#define SAY_MINION_DESTROY -1309022 //where does it belong? +#define SAY_PROTECT_ALTAR -1309023 //where does it belong? + +#define SPELL_BLOODSIPHON 24322 +#define SPELL_CORRUPTEDBLOOD 24328 +#define SPELL_CAUSEINSANITY 24327 //Not working disabled. +#define SPELL_WILLOFHAKKAR 24178 +#define SPELL_ENRAGE 24318 + +// The Aspects of all High Priests +#define SPELL_ASPECT_OF_JEKLIK 24687 +#define SPELL_ASPECT_OF_VENOXIS 24688 +#define SPELL_ASPECT_OF_MARLI 24686 +#define SPELL_ASPECT_OF_THEKAL 24689 +#define SPELL_ASPECT_OF_ARLOKK 24690 + +struct boss_hakkarAI : public ScriptedAI +{ + boss_hakkarAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 BloodSiphon_Timer; + uint32 CorruptedBlood_Timer; + uint32 CauseInsanity_Timer; + uint32 WillOfHakkar_Timer; + uint32 Enrage_Timer; + + uint32 CheckJeklik_Timer; + uint32 CheckVenoxis_Timer; + uint32 CheckMarli_Timer; + uint32 CheckThekal_Timer; + uint32 CheckArlokk_Timer; + + uint32 AspectOfJeklik_Timer; + uint32 AspectOfVenoxis_Timer; + uint32 AspectOfMarli_Timer; + uint32 AspectOfThekal_Timer; + uint32 AspectOfArlokk_Timer; + + bool Enraged; + + void Reset() + { + BloodSiphon_Timer = 90000; + CorruptedBlood_Timer = 25000; + CauseInsanity_Timer = 17000; + WillOfHakkar_Timer = 17000; + Enrage_Timer = 600000; + + CheckJeklik_Timer = 1000; + CheckVenoxis_Timer = 2000; + CheckMarli_Timer = 3000; + CheckThekal_Timer = 4000; + CheckArlokk_Timer = 5000; + + AspectOfJeklik_Timer = 4000; + AspectOfVenoxis_Timer = 7000; + AspectOfMarli_Timer = 12000; + AspectOfThekal_Timer = 8000; + AspectOfArlokk_Timer = 18000; + + Enraged = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //BloodSiphon_Timer + if (BloodSiphon_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLOODSIPHON); + BloodSiphon_Timer = 90000; + } else BloodSiphon_Timer -= diff; + + //CorruptedBlood_Timer + if (CorruptedBlood_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORRUPTEDBLOOD); + CorruptedBlood_Timer = 30000 + rand()%15000; + } else CorruptedBlood_Timer -= diff; + + //CauseInsanity_Timer + /*if (CauseInsanity_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CAUSEINSANITY); + + CauseInsanity_Timer = 35000 + rand()%8000; + } else CauseInsanity_Timer -= diff;*/ + + //WillOfHakkar_Timer + if (WillOfHakkar_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_WILLOFHAKKAR); + + WillOfHakkar_Timer = 25000 + rand()%10000; + } else WillOfHakkar_Timer -= diff; + + if (!Enraged && Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else Enrage_Timer -= diff; + + //Checking if Jeklik is dead. If not we cast her Aspect + if (CheckJeklik_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_JEKLIK) != DONE) + { + if (AspectOfJeklik_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ASPECT_OF_JEKLIK); + AspectOfJeklik_Timer = 10000 + rand()%4000; + } else AspectOfJeklik_Timer -= diff; + } + } + CheckJeklik_Timer = 1000; + } else CheckJeklik_Timer -= diff; + + //Checking if Venoxis is dead. If not we cast his Aspect + if (CheckVenoxis_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_VENOXIS) != DONE) + { + if (AspectOfVenoxis_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ASPECT_OF_VENOXIS); + AspectOfVenoxis_Timer = 8000; + } else AspectOfVenoxis_Timer -= diff; + } + } + CheckVenoxis_Timer = 1000; + } else CheckVenoxis_Timer -= diff; + + //Checking if Marli is dead. If not we cast her Aspect + if (CheckMarli_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_MARLI) != DONE) + { + if (AspectOfMarli_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); + AspectOfMarli_Timer = 10000; + } else AspectOfMarli_Timer -= diff; + + } + } + CheckMarli_Timer = 1000; + } else CheckMarli_Timer -= diff; + + //Checking if Thekal is dead. If not we cast his Aspect + if (CheckThekal_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_THEKAL) != DONE) + { + if (AspectOfThekal_Timer <= diff) + { + DoCast(me, SPELL_ASPECT_OF_THEKAL); + AspectOfThekal_Timer = 15000; + } else AspectOfThekal_Timer -= diff; + } + } + CheckThekal_Timer = 1000; + } else CheckThekal_Timer -= diff; + + //Checking if Arlokk is dead. If yes we cast her Aspect + if (CheckArlokk_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_ARLOKK) != DONE) + { + if (AspectOfArlokk_Timer <= diff) + { + DoCast(me, SPELL_ASPECT_OF_ARLOKK); + DoResetThreat(); + + AspectOfArlokk_Timer = 10000 + rand()%5000; + } else AspectOfArlokk_Timer -= diff; + } + } + CheckArlokk_Timer = 1000; + } else CheckArlokk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_hakkar(Creature* pCreature) +{ + return new boss_hakkarAI (pCreature); +} + +void AddSC_boss_hakkar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hakkar"; + newscript->GetAI = &GetAI_boss_hakkar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp new file mode 100644 index 00000000000..ca67d0842c3 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hazzarah +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SPELL_MANABURN 26046 +#define SPELL_SLEEP 24664 + +struct boss_hazzarahAI : public ScriptedAI +{ + boss_hazzarahAI(Creature *c) : ScriptedAI(c) {} + + uint32 ManaBurn_Timer; + uint32 Sleep_Timer; + uint32 Illusions_Timer; + + void Reset() + { + ManaBurn_Timer = 4000 + rand()%6000; + Sleep_Timer = 10000 + rand()%8000; + Illusions_Timer = 10000 + rand()%8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //ManaBurn_Timer + if (ManaBurn_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MANABURN); + ManaBurn_Timer = 8000 + rand()%8000; + } else ManaBurn_Timer -= diff; + + //Sleep_Timer + if (Sleep_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLEEP); + Sleep_Timer = 12000 + rand()%8000; + } else Sleep_Timer -= diff; + + //Illusions_Timer + if (Illusions_Timer <= diff) + { + //We will summon 3 illusions that will spawn on a random gamer and attack this gamer + //We will just use one model for the beginning + Unit *pTarget = NULL; + for (uint8 i = 0; i < 3; ++i) + { + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget) + return; + + Creature *Illusion = me->SummonCreature(15163,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,30000); + if (Illusion) + Illusion->AI()->AttackStart(pTarget); + } + + Illusions_Timer = 15000 + rand()%10000; + } else Illusions_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hazzarah(Creature* pCreature) +{ + return new boss_hazzarahAI (pCreature); +} + +void AddSC_boss_hazzarah() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hazzarah"; + newscript->GetAI = &GetAI_boss_hazzarah; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp new file mode 100644 index 00000000000..fae05fcf384 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp @@ -0,0 +1,291 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Jeklik +SD%Complete: 85 +SDComment: Problem in finding the right flying batriders for spawning and making them fly. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309002 +#define SAY_RAIN_FIRE -1309003 +#define SAY_DEATH -1309004 + +#define SPELL_CHARGE 22911 +#define SPELL_SONICBURST 23918 +#define SPELL_SCREECH 6605 +#define SPELL_SHADOW_WORD_PAIN 23952 +#define SPELL_MIND_FLAY 23953 +#define SPELL_CHAIN_MIND_FLAY 26044 //Right ID unknown. So disabled +#define SPELL_GREATERHEAL 23954 +#define SPELL_BAT_FORM 23966 + +// Batriders Spell + +#define SPELL_BOMB 40332 //Wrong ID but Magmadars bomb is not working... + +struct boss_jeklikAI : public ScriptedAI +{ + boss_jeklikAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 Charge_Timer; + uint32 SonicBurst_Timer; + uint32 Screech_Timer; + uint32 SpawnBats_Timer; + uint32 ShadowWordPain_Timer; + uint32 MindFlay_Timer; + uint32 ChainMindFlay_Timer; + uint32 GreaterHeal_Timer; + uint32 SpawnFlyingBats_Timer; + + bool PhaseTwo; + + void Reset() + { + Charge_Timer = 20000; + SonicBurst_Timer = 8000; + Screech_Timer = 13000; + SpawnBats_Timer = 60000; + ShadowWordPain_Timer = 6000; + MindFlay_Timer = 11000; + ChainMindFlay_Timer = 26000; + GreaterHeal_Timer = 50000; + SpawnFlyingBats_Timer = 10000; + + PhaseTwo = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_BAT_FORM); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_JEKLIK, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->getVictim() && me->isAlive()) + { + if ((me->GetHealth()*100 / me->GetMaxHealth() > 50)) + { + if (Charge_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_CHARGE); + AttackStart(pTarget); + } + + Charge_Timer = 15000 + rand()%15000; + } else Charge_Timer -= diff; + + if (SonicBurst_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SONICBURST); + SonicBurst_Timer = 8000 + rand()%5000; + } else SonicBurst_Timer -= diff; + + if (Screech_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SCREECH); + Screech_Timer = 18000 + rand()%8000; + } else Screech_Timer -= diff; + + if (SpawnBats_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + Creature* Bat = NULL; + Bat = me->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + Bat = me->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + Bat = me->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + Bat = me->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + Bat = me->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + Bat = me->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); + + SpawnBats_Timer = 60000; + } else SpawnBats_Timer -= diff; + } + else + { + if (PhaseTwo) + { + if (PhaseTwo && ShadowWordPain_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); + ShadowWordPain_Timer = 12000 + rand()%6000; + } + }ShadowWordPain_Timer -=diff; + + if (MindFlay_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIND_FLAY); + MindFlay_Timer = 16000; + }MindFlay_Timer -=diff; + + if (ChainMindFlay_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me->getVictim(), SPELL_CHAIN_MIND_FLAY); + ChainMindFlay_Timer = 15000 + rand()%15000; + }ChainMindFlay_Timer -=diff; + + if (GreaterHeal_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_GREATERHEAL); + GreaterHeal_Timer = 25000 + rand()%10000; + }GreaterHeal_Timer -=diff; + + if (SpawnFlyingBats_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!pTarget) + return; + + Creature* FlyingBat = me->SummonCreature(14965, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (FlyingBat) + FlyingBat->AI()->AttackStart(pTarget); + + SpawnFlyingBats_Timer = 10000 + rand()%5000; + } else SpawnFlyingBats_Timer -=diff; + } + else + { + me->SetDisplayId(15219); + DoResetThreat(); + PhaseTwo = true; + } + } + + DoMeleeAttackIfReady(); + } + } +}; + +//Flying Bat +struct mob_batriderAI : public ScriptedAI +{ + mob_batriderAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 Bomb_Timer; + uint32 Check_Timer; + + void Reset() + { + Bomb_Timer = 2000; + Check_Timer = 1000; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI (const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Bomb_Timer + if (Bomb_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_BOMB); + Bomb_Timer = 5000; + } + } else Bomb_Timer -= diff; + + //Check_Timer + if (Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_JEKLIK) == DONE) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + return; + } + } + + Check_Timer = 1000; + } else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jeklik(Creature* pCreature) +{ + return new boss_jeklikAI (pCreature); +} + +CreatureAI* GetAI_mob_batrider(Creature* pCreature) +{ + return new mob_batriderAI (pCreature); +} + +void AddSC_boss_jeklik() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_jeklik"; + newscript->GetAI = &GetAI_boss_jeklik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_batrider"; + newscript->GetAI = &GetAI_mob_batrider; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp new file mode 100644 index 00000000000..58f91f85a95 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp @@ -0,0 +1,263 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Jin'do the Hexxer +SD%Complete: 85 +SDComment: Mind Control not working because of core bug. Shades visible for all. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309014 + +#define SPELL_BRAINWASHTOTEM 24262 +#define SPELL_POWERFULLHEALINGWARD 24309 //We will not use this spell. We will summon a totem by script cause the spell totems will not cast. +#define SPELL_HEX 24053 +#define SPELL_DELUSIONSOFJINDO 24306 +#define SPELL_SHADEOFJINDO 24308 //We will not use this spell. We will summon a shade by script. + +//Healing Ward Spell +#define SPELL_HEAL 38588 //Totems are not working right. Right heal spell ID is 24311 but this spell is not casting... + +//Shade of Jindo Spell +#define SPELL_SHADOWSHOCK 19460 +#define SPELL_INVISIBLE 24699 + +struct boss_jindoAI : public ScriptedAI +{ + boss_jindoAI(Creature *c) : ScriptedAI(c) {} + + uint32 BrainWashTotem_Timer; + uint32 HealingWard_Timer; + uint32 Hex_Timer; + uint32 Delusions_Timer; + uint32 Teleport_Timer; + + void Reset() + { + BrainWashTotem_Timer = 20000; + HealingWard_Timer = 16000; + Hex_Timer = 8000; + Delusions_Timer = 10000; + Teleport_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //BrainWashTotem_Timer + if (BrainWashTotem_Timer <= diff) + { + DoCast(me, SPELL_BRAINWASHTOTEM); + BrainWashTotem_Timer = 18000 + rand()%8000; + } else BrainWashTotem_Timer -= diff; + + //HealingWard_Timer + if (HealingWard_Timer <= diff) + { + //DoCast(me, SPELL_POWERFULLHEALINGWARD); + me->SummonCreature(14987, me->GetPositionX()+3, me->GetPositionY()-2, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,30000); + HealingWard_Timer = 14000 + rand()%6000; + } else HealingWard_Timer -= diff; + + //Hex_Timer + if (Hex_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HEX); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-80); + + Hex_Timer = 12000 + rand()%8000; + } else Hex_Timer -= diff; + + //Casting the delusion curse with a shade. So shade will attack the same target with the curse. + if (Delusions_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_DELUSIONSOFJINDO); + + Creature *Shade = me->SummonCreature(14986, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Shade) + Shade->AI()->AttackStart(pTarget); + } + + Delusions_Timer = 4000 + rand()%8000; + } else Delusions_Timer -= diff; + + //Teleporting a random gamer and spawning 9 skeletons that will attack this gamer + if (Teleport_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoTeleportPlayer(pTarget, -11583.7783,-1249.4278,77.5471,4.745); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(pTarget,-100); + + Creature *Skeletons; + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+2, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()-2, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+4, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()-4, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()+2, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()-2, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()+4, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()-4, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+3, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Skeletons) + Skeletons->AI()->AttackStart(pTarget); + } + + Teleport_Timer = 15000 + rand()%8000; + } else Teleport_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Healing Ward +struct mob_healing_wardAI : public ScriptedAI +{ + mob_healing_wardAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 Heal_Timer; + + ScriptedInstance *pInstance; + + void Reset() + { + Heal_Timer = 2000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI (const uint32 diff) + { + //Heal_Timer + if (Heal_Timer <= diff) + { + if (pInstance) + { + Unit *pJindo = Unit::GetUnit((*me), pInstance->GetData64(DATA_JINDO)); + if (pJindo) + DoCast(pJindo, SPELL_HEAL); + } + Heal_Timer = 3000; + } else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Shade of Jindo +struct mob_shade_of_jindoAI : public ScriptedAI +{ + mob_shade_of_jindoAI(Creature *c) : ScriptedAI(c) {} + + uint32 ShadowShock_Timer; + + void Reset() + { + ShadowShock_Timer = 1000; + DoCast(me, SPELL_INVISIBLE, true); + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI (const uint32 diff) + { + + //ShadowShock_Timer + if (ShadowShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWSHOCK); + ShadowShock_Timer = 2000; + } else ShadowShock_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_jindo(Creature* pCreature) +{ + return new boss_jindoAI (pCreature); +} + +CreatureAI* GetAI_mob_healing_ward(Creature* pCreature) +{ + return new mob_healing_wardAI (pCreature); +} + +CreatureAI* GetAI_mob_shade_of_jindo(Creature* pCreature) +{ + return new mob_shade_of_jindoAI (pCreature); +} + +void AddSC_boss_jindo() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_jindo"; + newscript->GetAI = &GetAI_boss_jindo; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_healing_ward"; + newscript->GetAI = &GetAI_mob_healing_ward; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shade_of_jindo"; + newscript->GetAI = &GetAI_mob_shade_of_jindo; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp new file mode 100644 index 00000000000..4609605f3c1 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -0,0 +1,333 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mandokir +SD%Complete: 90 +SDComment: Ohgan function needs improvements. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309015 +#define SAY_DING_KILL -1309016 +#define SAY_GRATS_JINDO -1309017 +#define SAY_WATCH -1309018 +#define SAY_WATCH_WHISPER -1309019 //is this text for real? easter egg? + +#define SPELL_CHARGE 24315 +#define SPELL_CLEAVE 20691 +#define SPELL_FEAR 29321 +#define SPELL_WHIRLWIND 24236 +#define SPELL_MORTAL_STRIKE 24573 +#define SPELL_ENRAGE 23537 +#define SPELL_WATCH 24314 +#define SPELL_LEVEL_UP 24312 + +//Ohgans Spells +#define SPELL_SUNDERARMOR 24317 + +struct boss_mandokirAI : public ScriptedAI +{ + boss_mandokirAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 KillCount; + uint32 Watch_Timer; + uint32 TargetInRange; + uint32 Cleave_Timer; + uint32 Whirlwind_Timer; + uint32 Fear_Timer; + uint32 MortalStrike_Timer; + uint32 Check_Timer; + float targetX; + float targetY; + float targetZ; + + ScriptedInstance *m_pInstance; + + bool endWatch; + bool someWatched; + bool RaptorDead; + bool CombatStart; + + uint64 WatchTarget; + + void Reset() + { + KillCount = 0; + Watch_Timer = 33000; + Cleave_Timer = 7000; + Whirlwind_Timer = 20000; + Fear_Timer = 1000; + MortalStrike_Timer = 1000; + Check_Timer = 1000; + + targetX = 0.0; + targetY = 0.0; + targetZ = 0.0; + TargetInRange = 0; + + WatchTarget = 0; + + someWatched = false; + endWatch = false; + RaptorDead = false; + CombatStart = false; + + DoCast(me, 23243); + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + { + ++KillCount; + + if (KillCount == 3) + { + DoScriptText(SAY_DING_KILL, me); + + if (m_pInstance) + { + uint64 JindoGUID = m_pInstance->GetData64(DATA_JINDO); + if (JindoGUID) + { + if (Unit* jTemp = Unit::GetUnit(*me,JindoGUID)) + { + if (jTemp->isAlive()) + DoScriptText(SAY_GRATS_JINDO, jTemp); + } + } + } + DoCast(me, SPELL_LEVEL_UP, true); + KillCount = 0; + } + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->getVictim() && me->isAlive()) + { + if (!CombatStart) + { + //At combat Start Mandokir is mounted so we must unmount it first + me->Unmount(); + + //And summon his raptor + me->SummonCreature(14988, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000); + CombatStart = true; + } + + if (Watch_Timer <= diff) //Every 20 Sec Mandokir will check this + { + if (WatchTarget) //If someone is watched and If the Position of the watched target is different from the one stored, or are attacking, mandokir will charge him + { + Unit* pUnit = Unit::GetUnit(*me, WatchTarget); + + if (pUnit && ( + targetX != pUnit->GetPositionX() || + targetY != pUnit->GetPositionY() || + targetZ != pUnit->GetPositionZ() || + pUnit->isInCombat())) + { + if (me->IsWithinMeleeRange(pUnit)) + { + DoCast(pUnit, 24316); + } + else + { + DoCast(pUnit, SPELL_CHARGE); + //me->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true,1); + AttackStart(pUnit); + } + } + } + someWatched = false; + Watch_Timer = 20000; + } else Watch_Timer -= diff; + + if ((Watch_Timer < 8000) && !someWatched) //8 sec(cast time + expire time) before the check for the watch effect mandokir will cast watch debuff on a random target + { + if (Unit* p = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoScriptText(SAY_WATCH, me, p); + DoCast(p, SPELL_WATCH); + WatchTarget = p->GetGUID(); + someWatched = true; + endWatch = true; + } + } + + if ((Watch_Timer < 1000) && endWatch) //1 sec before the debuf expire, store the target position + { + Unit* pUnit = Unit::GetUnit(*me, WatchTarget); + if (pUnit) + { + targetX = pUnit->GetPositionX(); + targetY = pUnit->GetPositionY(); + targetZ = pUnit->GetPositionZ(); + } + endWatch = false; + } + + if (!someWatched) + { + //Cleave + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 7000; + } else Cleave_Timer -= diff; + + //Whirlwind + if (Whirlwind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + Whirlwind_Timer = 18000; + } else Whirlwind_Timer -= diff; + + //If more then 3 targets in melee range mandokir will cast fear + if (Fear_Timer <= diff) + { + TargetInRange = 0; + + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit(*me, (*i)->getUnitGuid()); + if (pUnit && me->IsWithinMeleeRange(pUnit)) + ++TargetInRange; + } + + if (TargetInRange > 3) + DoCast(me->getVictim(), SPELL_FEAR); + + Fear_Timer = 4000; + } else Fear_Timer -=diff; + + //Mortal Strike if target below 50% hp + if (me->getVictim() && me->getVictim()->GetHealth() < me->getVictim()->GetMaxHealth()*0.5) + { + if (MortalStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + MortalStrike_Timer = 15000; + } else MortalStrike_Timer -= diff; + } + } + //Checking if Ohgan is dead. If yes Mandokir will enrage. + if (Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_OHGAN) == DONE) + { + if (!RaptorDead) + { + DoCast(me, SPELL_ENRAGE); + RaptorDead = true; + } + } + } + + Check_Timer = 1000; + } else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +//Ohgan +struct mob_ohganAI : public ScriptedAI +{ + mob_ohganAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 SunderArmor_Timer; + ScriptedInstance *m_pInstance; + + void Reset() + { + SunderArmor_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) {} + + void JustDied(Unit* /*Killer*/) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_OHGAN, DONE); + } + + void UpdateAI (const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //SunderArmor_Timer + if (SunderArmor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUNDERARMOR); + SunderArmor_Timer = 10000 + rand()%5000; + } else SunderArmor_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_mandokir(Creature* pCreature) +{ + return new boss_mandokirAI (pCreature); +} + +CreatureAI* GetAI_mob_ohgan(Creature* pCreature) +{ + return new mob_ohganAI (pCreature); +} + +void AddSC_boss_mandokir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_mandokir"; + newscript->GetAI = &GetAI_boss_mandokir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ohgan"; + newscript->GetAI = &GetAI_mob_ohgan; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp new file mode 100644 index 00000000000..77e9f9b929f --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp @@ -0,0 +1,261 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Marli +SD%Complete: 80 +SDComment: Charging healers and casters not working. Perhaps wrong Spell Timers. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309005 +#define SAY_TRANSFORM -1309006 +#define SAY_SPIDER_SPAWN -1309007 +#define SAY_DEATH -1309008 + +#define SPELL_CHARGE 22911 +#define SPELL_ASPECT_OF_MARLI 24686 // A stun spell +#define SPELL_ENVOLWINGWEB 24110 +#define SPELL_POISONVOLLEY 24099 +#define SPELL_SPIDER_FORM 24084 + +//The Spider Spells +#define SPELL_LEVELUP 24312 //Not right Spell. + +struct boss_marliAI : public ScriptedAI +{ + boss_marliAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 SpawnStartSpiders_Timer; + uint32 PoisonVolley_Timer; + uint32 SpawnSpider_Timer; + uint32 Charge_Timer; + uint32 Aspect_Timer; + uint32 Transform_Timer; + uint32 TransformBack_Timer; + + bool Spawned; + bool PhaseTwo; + + void Reset() + { + SpawnStartSpiders_Timer = 1000; + PoisonVolley_Timer = 15000; + SpawnSpider_Timer = 30000; + Charge_Timer = 1500; + Aspect_Timer = 12000; + Transform_Timer = 45000; + TransformBack_Timer = 25000; + + Spawned = false; + PhaseTwo = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + if (m_pInstance) + m_pInstance->SetData(TYPE_MARLI, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->getVictim() && me->isAlive()) + { + if (PoisonVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISONVOLLEY); + PoisonVolley_Timer = 10000 + rand()%10000; + } else PoisonVolley_Timer -= diff; + + if (!PhaseTwo && Aspect_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); + Aspect_Timer = 13000 + rand()%5000; + } else Aspect_Timer -= diff; + + if (!Spawned && SpawnStartSpiders_Timer <= diff) + { + DoScriptText(SAY_SPIDER_SPAWN, me); + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget) + return; + + Creature *Spider = NULL; + + Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + + Spawned = true; + } else SpawnStartSpiders_Timer -= diff; + + if (SpawnSpider_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget) + return; + + Creature *Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Spider) + Spider->AI()->AttackStart(pTarget); + SpawnSpider_Timer = 12000 + rand()%5000; + } else SpawnSpider_Timer -= diff; + + if (!PhaseTwo && Transform_Timer <= diff) + { + DoScriptText(SAY_TRANSFORM, me); + DoCast(me, SPELL_SPIDER_FORM); + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); + me->UpdateDamagePhysical(BASE_ATTACK); + DoCast(me->getVictim(), SPELL_ENVOLWINGWEB); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-100); + + PhaseTwo = true; + Transform_Timer = urand(35000,60000); + } else Transform_Timer -= diff; + + if (PhaseTwo) + { + if (Charge_Timer <= diff) + { + Unit *pTarget = NULL; + int i = 0; + while (i < 3) // max 3 tries to get a random target with power_mana + { + ++i; + pTarget = SelectTarget(SELECT_TARGET_RANDOM,1, 100, true); // not aggro leader + if (pTarget && pTarget->getPowerType() == POWER_MANA) + i = 3; + } + if (pTarget) + { + DoCast(pTarget, SPELL_CHARGE); + //me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); + //me->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, true,1); + AttackStart(pTarget); + } + + Charge_Timer = 8000; + } else Charge_Timer -= diff; + + if (TransformBack_Timer <= diff) + { + me->SetDisplayId(15220); + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1))); + me->UpdateDamagePhysical(BASE_ATTACK); + + PhaseTwo = false; + TransformBack_Timer = urand(25000,40000); + } else TransformBack_Timer -= diff; + + } + + DoMeleeAttackIfReady(); + } + } +}; + +//Spawn of Marli +struct mob_spawn_of_marliAI : public ScriptedAI +{ + mob_spawn_of_marliAI(Creature *c) : ScriptedAI(c) {} + + uint32 LevelUp_Timer; + + void Reset() + { + LevelUp_Timer = 3000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI (const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //LevelUp_Timer + if (LevelUp_Timer <= diff) + { + DoCast(me, SPELL_LEVELUP); + LevelUp_Timer = 3000; + } else LevelUp_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_marli(Creature* pCreature) +{ + return new boss_marliAI (pCreature); +} + +CreatureAI* GetAI_mob_spawn_of_marli(Creature* pCreature) +{ + return new mob_spawn_of_marliAI (pCreature); +} + +void AddSC_boss_marli() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_marli"; + newscript->GetAI = &GetAI_boss_marli; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_spawn_of_marli"; + newscript->GetAI = &GetAI_mob_spawn_of_marli; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp new file mode 100644 index 00000000000..f7b01b26e19 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Renataki +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SPELL_AMBUSH 24337 +#define SPELL_THOUSANDBLADES 24649 + +#define EQUIP_ID_MAIN_HAND 0 //was item display id 31818, but this id does not exist + +struct boss_renatakiAI : public ScriptedAI +{ + boss_renatakiAI(Creature *c) : ScriptedAI(c) {} + + uint32 Invisible_Timer; + uint32 Ambush_Timer; + uint32 Visible_Timer; + uint32 Aggro_Timer; + uint32 ThousandBlades_Timer; + + bool Invisible; + bool Ambushed; + + void Reset() + { + Invisible_Timer = 8000 + rand()%10000; + Ambush_Timer = 3000; + Visible_Timer = 4000; + Aggro_Timer = 15000 + rand()%10000; + ThousandBlades_Timer = 4000 + rand()%4000; + + Invisible = false; + Ambushed = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Invisible_Timer + if (Invisible_Timer <= diff) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + me->SetDisplayId(11686); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Invisible = true; + + Invisible_Timer = 15000 + rand()%15000; + } else Invisible_Timer -= diff; + + if (Invisible) + { + if (Ambush_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + { + DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); + DoCast(pTarget, SPELL_AMBUSH); + } + + Ambushed = true; + Ambush_Timer = 3000; + } else Ambush_Timer -= diff; + } + + if (Ambushed) + { + if (Visible_Timer <= diff) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + + me->SetDisplayId(15268); + SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Invisible = false; + + Visible_Timer = 4000; + } else Visible_Timer -= diff; + } + + //Resetting some aggro so he attacks other gamers + if (!Invisible) + if (Aggro_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-50); + + if (pTarget) + AttackStart(pTarget); + + Aggro_Timer = 7000 + rand()%13000; + } else Aggro_Timer -= diff; + + if (!Invisible) + if (ThousandBlades_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_THOUSANDBLADES); + ThousandBlades_Timer = 7000 + rand()%5000; + } else ThousandBlades_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_renataki(Creature* pCreature) +{ + return new boss_renatakiAI (pCreature); +} + +void AddSC_boss_renataki() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_renataki"; + newscript->GetAI = &GetAI_boss_renataki; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp new file mode 100644 index 00000000000..179700d36e7 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp @@ -0,0 +1,556 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Thekal +SD%Complete: 95 +SDComment: Almost finished. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_AGGRO -1309009 +#define SAY_DEATH -1309010 + +#define SPELL_MORTALCLEAVE 22859 +#define SPELL_SILENCE 23207 +#define SPELL_FRENZY 23342 +#define SPELL_FORCEPUNCH 24189 +#define SPELL_CHARGE 24408 +#define SPELL_ENRAGE 23537 +#define SPELL_SUMMONTIGERS 24183 +#define SPELL_TIGER_FORM 24169 +#define SPELL_RESURRECT 24173 //We will not use this spell. + +//Zealot Lor'Khan Spells +#define SPELL_SHIELD 25020 +#define SPELL_BLOODLUST 24185 +#define SPELL_GREATERHEAL 24208 +#define SPELL_DISARM 22691 + +//Zealot Lor'Khan Spells +#define SPELL_SWEEPINGSTRIKES 18765 +#define SPELL_SINISTERSTRIKE 15667 +#define SPELL_GOUGE 24698 +#define SPELL_KICK 15614 +#define SPELL_BLIND 21060 + +struct boss_thekalAI : public ScriptedAI +{ + boss_thekalAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 MortalCleave_Timer; + uint32 Silence_Timer; + uint32 Frenzy_Timer; + uint32 ForcePunch_Timer; + uint32 Charge_Timer; + uint32 Enrage_Timer; + uint32 SummonTigers_Timer; + uint32 Check_Timer; + uint32 Resurrect_Timer; + + ScriptedInstance *m_pInstance; + bool Enraged; + bool PhaseTwo; + bool WasDead; + + void Reset() + { + MortalCleave_Timer = 4000; + Silence_Timer = 9000; + Frenzy_Timer = 30000; + ForcePunch_Timer = 4000; + Charge_Timer = 12000; + Enrage_Timer = 32000; + SummonTigers_Timer = 25000; + Check_Timer = 10000; + Resurrect_Timer = 10000; + + Enraged = false; + PhaseTwo = false; + WasDead = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + if (m_pInstance) + m_pInstance->SetData(TYPE_THEKAL, DONE); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_THEKAL, NOT_STARTED); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Check_Timer for the death of LorKhan and Zath. + if (!WasDead && Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL) + { + //Resurrect LorKhan + if (Unit *pLorKhan = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_LORKHAN))) + { + pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pLorKhan->setFaction(14); + pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); + + m_pInstance->SetData(TYPE_LORKHAN, DONE); + } + } + + if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL) + { + //Resurrect Zath + Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH)); + if (pZath) + { + pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pZath->setFaction(14); + pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); + + m_pInstance->SetData(TYPE_ZATH, DONE); + } + } + } + + Check_Timer = 5000; + } else Check_Timer -= diff; + + if (!PhaseTwo && MortalCleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALCLEAVE); + MortalCleave_Timer = 15000 + rand()%5000; + } else MortalCleave_Timer -= diff; + + if (!PhaseTwo && Silence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + Silence_Timer = 20000 + rand()%5000; + } else Silence_Timer -= diff; + + if (!PhaseTwo && !WasDead && me->GetHealth() <= me->GetMaxHealth() * 0.05) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + me->AttackStop(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_THEKAL, SPECIAL); + + WasDead=true; + } + + //Thekal will transform to Tiger if he died and was not resurrected after 10 seconds. + if (!PhaseTwo && WasDead) + { + if (Resurrect_Timer <= diff) + { + DoCast(me, SPELL_TIGER_FORM); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetHealth(int(me->GetMaxHealth()*1.0)); + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40))); + me->UpdateDamagePhysical(BASE_ATTACK); + DoResetThreat(); + PhaseTwo = true; + } else Resurrect_Timer -= diff; + } + + if ((me->GetHealth()*100 / me->GetMaxHealth() == 100) && WasDead) + { + WasDead = false; + } + + if (PhaseTwo) + { + if (Charge_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_CHARGE); + DoResetThreat(); + AttackStart(pTarget); + } + + Charge_Timer = 15000 + rand()%7000; + } else Charge_Timer -= diff; + + if (Frenzy_Timer <= diff) + { + DoCast(me, SPELL_FRENZY); + Frenzy_Timer = 30000; + } else Frenzy_Timer -= diff; + + if (ForcePunch_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + ForcePunch_Timer = 16000 + rand()%5000; + } else ForcePunch_Timer -= diff; + + if (SummonTigers_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUMMONTIGERS); + SummonTigers_Timer = 10000 + rand()%4000; + } else SummonTigers_Timer -= diff; + + if ((me->GetHealth()*100 / me->GetMaxHealth() < 11) && !Enraged) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } + } + + DoMeleeAttackIfReady(); + + } +}; + +//Zealot Lor'Khan +struct mob_zealot_lorkhanAI : public ScriptedAI +{ + mob_zealot_lorkhanAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 Shield_Timer; + uint32 BloodLust_Timer; + uint32 GreaterHeal_Timer; + uint32 Disarm_Timer; + uint32 Check_Timer; + + bool FakeDeath; + + ScriptedInstance *m_pInstance; + + void Reset() + { + Shield_Timer = 1000; + BloodLust_Timer = 16000; + GreaterHeal_Timer = 32000; + Disarm_Timer = 6000; + Check_Timer = 10000; + + FakeDeath = false; + + if (m_pInstance) + m_pInstance->SetData(TYPE_LORKHAN, NOT_STARTED); + + me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI (const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Shield_Timer + if (Shield_Timer <= diff) + { + DoCast(me, SPELL_SHIELD); + Shield_Timer = 61000; + } else Shield_Timer -= diff; + + //BloodLust_Timer + if (BloodLust_Timer <= diff) + { + DoCast(me, SPELL_BLOODLUST); + BloodLust_Timer = 20000+rand()%8000; + } else BloodLust_Timer -= diff; + + //Casting Greaterheal to Thekal or Zath if they are in meele range. + if (GreaterHeal_Timer <= diff) + { + if (m_pInstance) + { + Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL)); + Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH)); + + if (!pThekal || !pZath) + return; + + switch (urand(0,1)) + { + case 0: + if (me->IsWithinMeleeRange(pThekal)) + DoCast(pThekal, SPELL_GREATERHEAL); + break; + case 1: + if (me->IsWithinMeleeRange(pZath)) + DoCast(pZath, SPELL_GREATERHEAL); + break; + } + } + + GreaterHeal_Timer = 15000+rand()%5000; + } else GreaterHeal_Timer -= diff; + + //Disarm_Timer + if (Disarm_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DISARM); + Disarm_Timer = 15000+rand()%10000; + } else Disarm_Timer -= diff; + + //Check_Timer for the death of LorKhan and Zath. + if (!FakeDeath && Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL) + { + //Resurrect Thekal + if (Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL))) + { + pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pThekal->setFaction(14); + pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); + } + } + + if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL) + { + //Resurrect Zath + if (Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH))) + { + pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pZath->setFaction(14); + pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); + } + } + } + + Check_Timer = 5000; + } else Check_Timer -= diff; + + if (me->GetHealth() <= me->GetMaxHealth() * 0.05) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + me->setFaction(35); + me->AttackStop(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_LORKHAN, SPECIAL); + + FakeDeath = true; + } + + DoMeleeAttackIfReady(); + } +}; + +//Zealot Zath +struct mob_zealot_zathAI : public ScriptedAI +{ + mob_zealot_zathAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + uint32 SweepingStrikes_Timer; + uint32 SinisterStrike_Timer; + uint32 Gouge_Timer; + uint32 Kick_Timer; + uint32 Blind_Timer; + uint32 Check_Timer; + + bool FakeDeath; + + ScriptedInstance *m_pInstance; + + void Reset() + { + SweepingStrikes_Timer = 13000; + SinisterStrike_Timer = 8000; + Gouge_Timer = 25000; + Kick_Timer = 18000; + Blind_Timer = 5000; + Check_Timer = 10000; + + FakeDeath = false; + + if (m_pInstance) + m_pInstance->SetData(TYPE_ZATH, NOT_STARTED); + + me->SetStandState(UNIT_STAND_STATE_STAND); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI (const uint32 diff) + { + if (!UpdateVictim()) + return; + + //SweepingStrikes_Timer + if (SweepingStrikes_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SWEEPINGSTRIKES); + SweepingStrikes_Timer = 22000+rand()%4000; + } else SweepingStrikes_Timer -= diff; + + //SinisterStrike_Timer + if (SinisterStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SINISTERSTRIKE); + SinisterStrike_Timer = 8000+rand()%8000; + } else SinisterStrike_Timer -= diff; + + //Gouge_Timer + if (Gouge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_GOUGE); + + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-100); + + Gouge_Timer = 17000+rand()%10000; + } else Gouge_Timer -= diff; + + //Kick_Timer + if (Kick_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KICK); + Kick_Timer = 15000+rand()%10000; + } else Kick_Timer -= diff; + + //Blind_Timer + if (Blind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BLIND); + Blind_Timer = 10000+rand()%10000; + } else Blind_Timer -= diff; + + //Check_Timer for the death of LorKhan and Zath. + if (!FakeDeath && Check_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL) + { + //Resurrect LorKhan + if (Unit *pLorKhan = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_LORKHAN))) + { + pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pLorKhan->setFaction(14); + pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); + } + } + + if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL) + { + //Resurrect Thekal + if (Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL))) + { + pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pThekal->setFaction(14); + pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); + } + } + } + + Check_Timer = 5000; + } else Check_Timer -= diff; + + if (me->GetHealth() <= me->GetMaxHealth() * 0.05) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetStandState(UNIT_STAND_STATE_SLEEP); + me->setFaction(35); + me->AttackStop(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_ZATH, SPECIAL); + + FakeDeath = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thekal(Creature* pCreature) +{ + return new boss_thekalAI (pCreature); +} + +CreatureAI* GetAI_mob_zealot_lorkhan(Creature* pCreature) +{ + return new mob_zealot_lorkhanAI (pCreature); +} + +CreatureAI* GetAI_mob_zealot_zath(Creature* pCreature) +{ + return new mob_zealot_zathAI (pCreature); +} + +void AddSC_boss_thekal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_thekal"; + newscript->GetAI = &GetAI_boss_thekal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_zealot_lorkhan"; + newscript->GetAI = &GetAI_mob_zealot_lorkhan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_zealot_zath"; + newscript->GetAI = &GetAI_mob_zealot_zath; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp new file mode 100644 index 00000000000..ec1a7a142b5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp @@ -0,0 +1,199 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Venoxis +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SAY_TRANSFORM -1309000 +#define SAY_DEATH -1309001 + +#define SPELL_HOLY_FIRE 23860 +#define SPELL_HOLY_WRATH 28883 //Not sure if this or 23979 +#define SPELL_VENOMSPIT 23862 +#define SPELL_HOLY_NOVA 23858 +#define SPELL_POISON_CLOUD 23861 +#define SPELL_SNAKE_FORM 23849 +#define SPELL_RENEW 23895 +#define SPELL_BERSERK 23537 +#define SPELL_DISPELL 23859 + +struct boss_venoxisAI : public ScriptedAI +{ + boss_venoxisAI(Creature *c) : ScriptedAI(c) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance *m_pInstance; + + uint32 HolyFire_Timer; + uint32 HolyWrath_Timer; + uint32 VenomSpit_Timer; + uint32 Renew_Timer; + uint32 PoisonCloud_Timer; + uint32 HolyNova_Timer; + uint32 Dispell_Timer; + uint32 TargetInRange; + + bool PhaseTwo; + bool InBerserk; + + void Reset() + { + HolyFire_Timer = 10000; + HolyWrath_Timer = 60500; + VenomSpit_Timer = 5500; + Renew_Timer = 30500; + PoisonCloud_Timer = 2000; + HolyNova_Timer = 5000; + Dispell_Timer = 35000; + TargetInRange = 0; + + PhaseTwo = false; + InBerserk= false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + if (m_pInstance) + m_pInstance->SetData(TYPE_VENOXIS, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if ((me->GetHealth()*100 / me->GetMaxHealth() > 50)) + { + if (Dispell_Timer <= diff) + { + DoCast(me, SPELL_DISPELL); + Dispell_Timer = 15000 + rand()%15000; + } else Dispell_Timer -= diff; + + if (Renew_Timer <= diff) + { + DoCast(me, SPELL_RENEW); + Renew_Timer = 20000 + rand()%10000; + } else Renew_Timer -= diff; + + if (HolyWrath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HOLY_WRATH); + HolyWrath_Timer = 15000 + rand()%10000; + } else HolyWrath_Timer -= diff; + + if (HolyNova_Timer <= diff) + { + TargetInRange = 0; + for (uint8 i = 0; i < 10; ++i) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,i)) + if (me->IsWithinMeleeRange(pTarget)) + ++TargetInRange; + } + + if (TargetInRange > 1) + { + DoCast(me->getVictim(), SPELL_HOLY_NOVA); + HolyNova_Timer = 1000; + } + else + { + HolyNova_Timer = 2000; + } + + } else HolyNova_Timer -= diff; + + if (HolyFire_Timer < diff && TargetInRange < 3) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_HOLY_FIRE); + + HolyFire_Timer = 8000; + } else HolyFire_Timer -= diff; + } + else + { + if (!PhaseTwo) + { + DoScriptText(SAY_TRANSFORM, me); + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SNAKE_FORM); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); + const CreatureInfo *cinfo = me->GetCreatureInfo(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 25))); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 25))); + me->UpdateDamagePhysical(BASE_ATTACK); + DoResetThreat(); + PhaseTwo = true; + } + + if (PhaseTwo && PoisonCloud_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_CLOUD); + PoisonCloud_Timer = 15000; + }PoisonCloud_Timer -=diff; + + if (PhaseTwo && VenomSpit_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_VENOMSPIT); + + VenomSpit_Timer = 15000 + rand()%5000; + } else VenomSpit_Timer -= diff; + + if (PhaseTwo && (me->GetHealth()*100 / me->GetMaxHealth() < 11)) + { + if (!InBerserk) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_BERSERK); + InBerserk = true; + } + } + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_venoxis(Creature* pCreature) +{ + return new boss_venoxisAI (pCreature); +} + +void AddSC_boss_venoxis() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_venoxis"; + newscript->GetAI = &GetAI_boss_venoxis; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp new file mode 100644 index 00000000000..a71d7e0504a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Wushoolay +SD%Complete: 100 +SDComment: +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +#define SPELL_LIGHTNINGCLOUD 25033 +#define SPELL_LIGHTNINGWAVE 24819 + +struct boss_wushoolayAI : public ScriptedAI +{ + boss_wushoolayAI(Creature *c) : ScriptedAI(c) {} + + uint32 LightningCloud_Timer; + uint32 LightningWave_Timer; + + void Reset() + { + LightningCloud_Timer = 5000 + rand()%5000; + LightningWave_Timer = 8000 + rand()%8000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //LightningCloud_Timer + if (LightningCloud_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LIGHTNINGCLOUD); + LightningCloud_Timer = 15000 + rand()%5000; + } else LightningCloud_Timer -= diff; + + //LightningWave_Timer + if (LightningWave_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) DoCast(pTarget, SPELL_LIGHTNINGWAVE); + + LightningWave_Timer = 12000 + rand()%4000; + } else LightningWave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_wushoolay(Creature* pCreature) +{ + return new boss_wushoolayAI (pCreature); +} + +void AddSC_boss_wushoolay() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_wushoolay"; + newscript->GetAI = &GetAI_boss_wushoolay; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp new file mode 100644 index 00000000000..aaed1c6df3a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp @@ -0,0 +1,159 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_ZulGurub +SD%Complete: 80 +SDComment: Missing reset function after killing a boss for Ohgan, Thekal. +SDCategory: Zul'Gurub +EndScriptData */ + +#include "ScriptedPch.h" +#include "zulgurub.h" + +struct instance_zulgurub : public ScriptedInstance +{ + instance_zulgurub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. + uint32 m_auiEncounter[MAX_ENCOUNTERS]; + + //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. + uint64 m_uiLorKhanGUID; + uint64 m_uiZathGUID; + uint64 m_uiThekalGUID; + uint64 m_uiJindoGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiLorKhanGUID = 0; + m_uiZathGUID = 0; + m_uiThekalGUID = 0; + m_uiJindoGUID = 0; + } + + bool IsEncounterInProgress() const + { + //not active in Zul'Gurub + return false; + } + + void OnCreatureCreate(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case 11347: m_uiLorKhanGUID = pCreature->GetGUID(); break; + case 11348: m_uiZathGUID = pCreature->GetGUID(); break; + case 14509: m_uiThekalGUID = pCreature->GetGUID(); break; + case 11380: m_uiJindoGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_ARLOKK: + m_auiEncounter[0] = uiData; + break; + + case TYPE_JEKLIK: + m_auiEncounter[1] = uiData; + break; + + case TYPE_VENOXIS: + m_auiEncounter[2] = uiData; + break; + + case TYPE_MARLI: + m_auiEncounter[3] = uiData; + break; + + case TYPE_THEKAL: + m_auiEncounter[4] = uiData; + break; + + case TYPE_LORKHAN: + m_auiEncounter[5] = uiData; + break; + + case TYPE_ZATH: + m_auiEncounter[6] = uiData; + break; + + case TYPE_OHGAN: + m_auiEncounter[7] = uiData; + break; + } + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_ARLOKK: + return m_auiEncounter[0]; + case TYPE_JEKLIK: + return m_auiEncounter[1]; + case TYPE_VENOXIS: + return m_auiEncounter[2]; + case TYPE_MARLI: + return m_auiEncounter[3]; + case TYPE_THEKAL: + return m_auiEncounter[4]; + case TYPE_LORKHAN: + return m_auiEncounter[5]; + case TYPE_ZATH: + return m_auiEncounter[6]; + case TYPE_OHGAN: + return m_auiEncounter[7]; + } + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_LORKHAN: + return m_uiLorKhanGUID; + case DATA_ZATH: + return m_uiZathGUID; + case DATA_THEKAL: + return m_uiThekalGUID; + case DATA_JINDO: + return m_uiJindoGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_zulgurub(Map* pMap) +{ + return new instance_zulgurub(pMap); +} + +void AddSC_instance_zulgurub() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_zulgurub"; + newscript->GetInstanceData = &GetInstanceData_instance_zulgurub; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h new file mode 100644 index 00000000000..bf55a54c1d5 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ZULGURUB_H +#define DEF_ZULGURUB_H + +enum eTypes +{ + MAX_ENCOUNTERS = 8, + + TYPE_ARLOKK = 1, + TYPE_JEKLIK = 2, + TYPE_VENOXIS = 3, + TYPE_MARLI = 4, + TYPE_OHGAN = 5, + TYPE_THEKAL = 6, + TYPE_ZATH = 7, + TYPE_LORKHAN = 8, + + DATA_JINDO = 10, + DATA_LORKHAN = 11, + DATA_THEKAL = 12, + DATA_ZATH = 13 +}; + +#endif + diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp deleted file mode 100644 index a61fc21d5ba..00000000000 --- a/src/server/scripts/EasternKingdoms/alterac_valley/alterac_valley.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_CHARGE = 22911, - SPELL_CLEAVE = 40504, - SPELL_DEMORALIZING_SHOUT = 23511, - SPELL_ENRAGE = 8599, - SPELL_WHIRLWIND1 = 15589, - SPELL_WHIRLWIND2 = 13736, - SPELL_NORTH_MARSHAL = 45828, - SPELL_SOUTH_MARSHAL = 45829, - SPELL_STONEHEARTH_MARSHAL = 45830, - SPELL_ICEWING_MARSHAL = 45831, - SPELL_ICEBLOOD_WARMASTER = 45822, - SPELL_TOWER_POINT_WARMASTER = 45823, - SPELL_WEST_FROSTWOLF_WARMASTER = 45824, - SPELL_EAST_FROSTWOLF_WARMASTER = 45826 -}; - -enum Creatures -{ - NPC_NORTH_MARSHAL = 14762, - NPC_SOUTH_MARSHAL = 14763, - NPC_ICEWING_MARSHAL = 14764, - NPC_STONEHEARTH_MARSHAL = 14765, - NPC_EAST_FROSTWOLF_WARMASTER = 14772, - NPC_ICEBLOOD_WARMASTER = 14773, - NPC_TOWER_POINT_WARMASTER = 14776, - NPC_WEST_FROSTWOLF_WARMASTER = 14777 -}; - -struct mob_av_marshal_or_warmasterAI : public ScriptedAI -{ - mob_av_marshal_or_warmasterAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiChargeTimer; - uint32 uiCleaveTimer; - uint32 uiDemoralizingShoutTimer; - uint32 uiWhirlwind1Timer; - uint32 uiWhirlwind2Timer; - uint32 uiEnrageTimer; - uint32 uiResetTimer; - - bool bHasAura; - - void Reset() - { - uiChargeTimer = urand(2*IN_MILISECONDS,12*IN_MILISECONDS); - uiCleaveTimer = urand(1*IN_MILISECONDS,11*IN_MILISECONDS); - uiDemoralizingShoutTimer = urand(2*IN_MILISECONDS,2*IN_MILISECONDS); - uiWhirlwind1Timer = urand(1*IN_MILISECONDS,12*IN_MILISECONDS); - uiWhirlwind2Timer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); - uiEnrageTimer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); - uiResetTimer = 5*IN_MILISECONDS; - - bHasAura = false; - } - - void JustRespawned() - { - Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!bHasAura) - { - switch(me->GetEntry()) - { - case NPC_NORTH_MARSHAL: - DoCast(me,SPELL_NORTH_MARSHAL); - break; - case NPC_SOUTH_MARSHAL: - DoCast(me,SPELL_SOUTH_MARSHAL); - break; - case NPC_STONEHEARTH_MARSHAL: - DoCast(me,SPELL_STONEHEARTH_MARSHAL); - break; - case NPC_ICEWING_MARSHAL: - DoCast(me,SPELL_ICEWING_MARSHAL); - break; - case NPC_EAST_FROSTWOLF_WARMASTER: - DoCast(me,SPELL_EAST_FROSTWOLF_WARMASTER); - break; - case NPC_WEST_FROSTWOLF_WARMASTER: - DoCast(me,SPELL_WEST_FROSTWOLF_WARMASTER); - break; - case NPC_ICEBLOOD_WARMASTER: - DoCast(me,SPELL_ICEBLOOD_WARMASTER); - break; - case NPC_TOWER_POINT_WARMASTER: - DoCast(me,SPELL_TOWER_POINT_WARMASTER); - break; - } - - bHasAura = true; - } - - if (!UpdateVictim()) - return; - - if (uiChargeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CHARGE); - uiChargeTimer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiChargeTimer -= diff; - - if (uiCleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = urand(10*IN_MILISECONDS,16*IN_MILISECONDS); - } else uiCleaveTimer -= diff; - - if (uiDemoralizingShoutTimer <= diff) - { - DoCast(me->getVictim(), SPELL_DEMORALIZING_SHOUT); - uiDemoralizingShoutTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiDemoralizingShoutTimer -= diff; - - if (uiWhirlwind1Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND1); - uiWhirlwind1Timer = urand(6*IN_MILISECONDS,20*IN_MILISECONDS); - } else uiWhirlwind1Timer -= diff; - - if (uiWhirlwind2Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND2); - uiWhirlwind2Timer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiWhirlwind2Timer -= diff; - - if (uiEnrageTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ENRAGE); - uiEnrageTimer = urand(10*IN_MILISECONDS,30*IN_MILISECONDS); - }else uiEnrageTimer -= diff; - - - // check if creature is not outside of building - if (uiResetTimer <= diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - EnterEvadeMode(); - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_av_marshal_or_warmaster(Creature *_Creature) -{ - return new mob_av_marshal_or_warmasterAI (_Creature); -} - -void AddSC_alterac_valley() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_av_marshal_or_warmaster"; - newscript->GetAI = &GetAI_mob_av_marshal_or_warmaster; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp deleted file mode 100644 index ce2a81c864a..00000000000 --- a/src/server/scripts/EasternKingdoms/alterac_valley/boss_balinda.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_ARCANE_EXPLOSION = 46608, - SPELL_CONE_OF_COLD = 38384, - SPELL_FIREBALL = 46988, - SPELL_FROSTBOLT = 46987 -}; - -enum Yells -{ - YELL_AGGRO = -2100019, - YELL_EVADE = -2100020 -}; - -enum Creatures -{ - NPC_WATER_ELEMENTAL = 25040 -}; - -enum WaterElementalSpells -{ - SPELL_WATERBOLT = 46983 -}; - -struct mob_water_elementalAI : public ScriptedAI -{ - mob_water_elementalAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWaterBoltTimer; - uint64 uiBalindaGUID; - uint32 uiResetTimer; - - void Reset() - { - uiWaterBoltTimer = 3*IN_MILISECONDS; - uiResetTimer = 5*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWaterBoltTimer < diff) - { - DoCast(me->getVictim(), SPELL_WATERBOLT); - uiWaterBoltTimer = 5*IN_MILISECONDS; - } else uiWaterBoltTimer -= diff; - - // check if creature is not outside of building - if (uiResetTimer < diff) - { - if (Creature *pBalinda = Unit::GetCreature(*me, uiBalindaGUID)) - if (me->GetDistance2d(pBalinda->GetHomePosition().GetPositionX(), pBalinda->GetHomePosition().GetPositionY()) > 50) - EnterEvadeMode(); - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_balindaAI : public ScriptedAI -{ - boss_balindaAI(Creature *c) : ScriptedAI(c), Summons(me) {} - - uint32 uiArcaneExplosionTimer; - uint32 uiConeOfColdTimer; - uint32 uiFireBoltTimer; - uint32 uiFrostboltTimer; - uint32 uiResetTimer; - uint32 uiWaterElementalTimer; - - SummonList Summons; - - void Reset() - { - uiArcaneExplosionTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); - uiConeOfColdTimer = 8*IN_MILISECONDS; - uiFireBoltTimer = 1*IN_MILISECONDS; - uiFrostboltTimer = 4*IN_MILISECONDS; - uiResetTimer = 5*IN_MILISECONDS; - uiWaterElementalTimer = 0; - - Summons.DespawnAll(); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - } - - void JustRespawned() - { - Reset(); - } - - void JustSummoned(Creature* summoned) - { - ((mob_water_elementalAI*)summoned->AI())->uiBalindaGUID = me->GetGUID(); - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); - summoned->setFaction(me->getFaction()); - Summons.Summon(summoned); - } - - void JustDied(Unit* /*Killer*/) - { - Summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWaterElementalTimer < diff) - { - if (Summons.empty()) - me->SummonCreature(NPC_WATER_ELEMENTAL, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45*IN_MILISECONDS); - uiWaterElementalTimer = 50*IN_MILISECONDS; - } else uiWaterElementalTimer -= diff; - - if (uiArcaneExplosionTimer < diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); - uiArcaneExplosionTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiArcaneExplosionTimer -= diff; - - if (uiConeOfColdTimer < diff) - { - DoCast(me->getVictim(), SPELL_CONE_OF_COLD); - uiConeOfColdTimer = urand(10*IN_MILISECONDS,20*IN_MILISECONDS); - } else uiConeOfColdTimer -= diff; - - if (uiFireBoltTimer < diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL); - uiFireBoltTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); - } else uiFireBoltTimer -= diff; - - if (uiFrostboltTimer < diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - uiFrostboltTimer = urand(4*IN_MILISECONDS,12*IN_MILISECONDS); - } else uiFrostboltTimer -= diff; - - - // check if creature is not outside of building - if (uiResetTimer < diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - { - EnterEvadeMode(); - DoScriptText(YELL_EVADE, me); - } - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_balinda(Creature *_Creature) -{ - return new boss_balindaAI (_Creature); -} - -CreatureAI* GetAI_mob_water_elemental(Creature *_Creature) -{ - return new mob_water_elementalAI (_Creature); -} - -void AddSC_boss_balinda() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_balinda"; - newscript->GetAI = &GetAI_boss_balinda; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_water_elemental"; - newscript->GetAI = &GetAI_mob_water_elemental; - newscript->RegisterSelf(); -}; \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp deleted file mode 100644 index 6477ebe5eaf..00000000000 --- a/src/server/scripts/EasternKingdoms/alterac_valley/boss_drekthar.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_WHIRLWIND = 15589, - SPELL_WHIRLWIND2 = 13736, - SPELL_KNOCKDOWN = 19128, - SPELL_FRENZY = 8269, - SPELL_SWEEPING_STRIKES = 18765, // not sure - SPELL_CLEAVE = 20677, // not sure - SPELL_WINDFURY = 35886, // not sure - SPELL_STORMPIKE = 51876 // not sure -}; - -enum Yells -{ - YELL_AGGRO = -1810000, - YELL_EVADE = -1810001, - YELL_RESPAWN = -1810002, - YELL_RANDOM1 = -1810003, - YELL_RANDOM2 = -1810004, - YELL_RANDOM3 = -1810005, - YELL_RANDOM4 = -1810006, - YELL_RANDOM5 = -1810007 -}; - -struct boss_drektharAI : public ScriptedAI -{ - boss_drektharAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWhirlwindTimer; - uint32 uiWhirlwind2Timer; - uint32 uiKnockdownTimer; - uint32 uiFrenzyTimer; - uint32 uiYellTimer; - uint32 uiResetTimer; - - void Reset() - { - uiWhirlwindTimer = urand(1*IN_MILISECONDS,20*IN_MILISECONDS); - uiWhirlwind2Timer = urand(1*IN_MILISECONDS,20*IN_MILISECONDS); - uiKnockdownTimer = 12*IN_MILISECONDS; - uiFrenzyTimer = 6*IN_MILISECONDS; - uiResetTimer = 5*IN_MILISECONDS; - uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds - } - - void Aggro(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - } - - void JustRespawned() - { - Reset(); - DoScriptText(YELL_RESPAWN, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWhirlwindTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - uiWhirlwindTimer = urand(8*IN_MILISECONDS,18*IN_MILISECONDS); - } else uiWhirlwindTimer -= diff; - - if (uiWhirlwind2Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND2); - uiWhirlwind2Timer = urand(7*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiWhirlwind2Timer -= diff; - - if (uiKnockdownTimer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - uiKnockdownTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiKnockdownTimer -= diff; - - if (uiFrenzyTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FRENZY); - uiFrenzyTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiFrenzyTimer -= diff; - - if (uiYellTimer <= diff) - { - DoScriptText(RAND(YELL_RANDOM1,YELL_RANDOM2,YELL_RANDOM3,YELL_RANDOM4,YELL_RANDOM5), me); - uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds - } else uiYellTimer -= diff; - - // check if creature is not outside of building - if (uiResetTimer <= diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - { - EnterEvadeMode(); - DoScriptText(YELL_EVADE, me); - } - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - - -CreatureAI* GetAI_boss_drekthar(Creature *_Creature) -{ - return new boss_drektharAI (_Creature); -} - -void AddSC_boss_drekthar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_drekthar"; - newscript->GetAI = &GetAI_boss_drekthar; - newscript->RegisterSelf(); -} \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp deleted file mode 100644 index a12b9f267f9..00000000000 --- a/src/server/scripts/EasternKingdoms/alterac_valley/boss_galvangar.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_CLEAVE = 15284, - SPELL_FRIGHTENING_SHOUT = 19134, - SPELL_WHIRLWIND1 = 15589, - SPELL_WHIRLWIND2 = 13736, - SPELL_MORTAL_STRIKE = 16856 -}; - -enum Yells -{ - YELL_AGGRO = -1810021, - YELL_EVADE = -1810022 -}; - -struct boss_galvangarAI : public ScriptedAI -{ - boss_galvangarAI(Creature *c) : ScriptedAI(c) {} - - - uint32 uiCleaveTimer; - uint32 uiFrighteningShoutTimer; - uint32 uiWhirlwind1Timer; - uint32 uiWhirlwind2Timer; - uint32 uiMortalStrikeTimer; - uint32 uiResetTimer; - - - void Reset() - { - uiCleaveTimer = urand(1*IN_MILISECONDS,9*IN_MILISECONDS); - uiFrighteningShoutTimer = urand(2*IN_MILISECONDS,19*IN_MILISECONDS); - uiWhirlwind1Timer = urand(1*IN_MILISECONDS,13*IN_MILISECONDS); - uiWhirlwind2Timer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); - uiMortalStrikeTimer = urand(5*IN_MILISECONDS,20*IN_MILISECONDS); - uiResetTimer = 5*IN_MILISECONDS; - } - - void Aggro(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - } - - void JustRespawned() - { - Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiCleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = urand(10*IN_MILISECONDS,16*IN_MILISECONDS); - } else uiCleaveTimer -= diff; - - if (uiFrighteningShoutTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); - uiFrighteningShoutTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiFrighteningShoutTimer -= diff; - - if (uiWhirlwind1Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND1); - uiWhirlwind1Timer = urand(6*IN_MILISECONDS,10*IN_MILISECONDS); - } else uiWhirlwind1Timer -= diff; - - if (uiWhirlwind2Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND2); - uiWhirlwind2Timer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiWhirlwind2Timer -= diff; - - if (uiMortalStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - uiMortalStrikeTimer = urand(10*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiMortalStrikeTimer -= diff; - - // check if creature is not outside of building - if (uiResetTimer <= diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - { - EnterEvadeMode(); - DoScriptText(YELL_EVADE, me); - } - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_galvangar(Creature *_Creature) -{ - return new boss_galvangarAI (_Creature); -} - -void AddSC_boss_galvangar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_galvangar"; - newscript->GetAI = &GetAI_boss_galvangar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp b/src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp deleted file mode 100644 index 785827bc5d9..00000000000 --- a/src/server/scripts/EasternKingdoms/alterac_valley/boss_vanndar.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -enum Yells -{ - YELL_AGGRO = -1810008, - YELL_EVADE = -1810009, - YELL_RESPAWN1 = -1810010, - YELL_RESPAWN2 = -1810011, - YELL_RANDOM1 = -1810012, - YELL_RANDOM2 = -1810013, - YELL_RANDOM3 = -1810014, - YELL_RANDOM4 = -1810015, - YELL_RANDOM5 = -1810016, - YELL_RANDOM6 = -1810017, - YELL_RANDOM7 = -1810018 -}; - -enum Spells -{ - SPELL_AVATAR = 19135, - SPELL_THUNDERCLAP = 15588, - SPELL_STORMBOLT = 20685 // not sure -}; - -struct boss_vanndarAI : public ScriptedAI -{ - boss_vanndarAI(Creature *c) : ScriptedAI(c) {} - - - uint32 uiAvatarTimer; - uint32 uiThunderclapTimer; - uint32 uiStormboltTimer; - uint32 uiResetTimer; - uint32 uiYellTimer; - - - void Reset() - { - uiAvatarTimer = 3*IN_MILISECONDS; - uiThunderclapTimer = 4*IN_MILISECONDS; - uiStormboltTimer = 6*IN_MILISECONDS; - uiResetTimer = 5*IN_MILISECONDS; - uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } - - void Aggro(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - } - - void JustRespawned() - { - Reset(); - DoScriptText(RAND(YELL_RESPAWN1,YELL_RESPAWN2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiAvatarTimer <= diff) - { - DoCast(me->getVictim(), SPELL_AVATAR); - uiAvatarTimer = urand(15*IN_MILISECONDS,20*IN_MILISECONDS); - } else uiAvatarTimer -= diff; - - if (uiThunderclapTimer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - uiThunderclapTimer = urand(5*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiThunderclapTimer -= diff; - - if (uiStormboltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STORMBOLT); - uiStormboltTimer = urand(10*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiStormboltTimer -= diff; - - if (uiYellTimer <= diff) - { - DoScriptText(RAND(YELL_RANDOM1,YELL_RANDOM2,YELL_RANDOM3,YELL_RANDOM4,YELL_RANDOM5,YELL_RANDOM6,YELL_RANDOM7), me); - uiYellTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); //20 to 30 seconds - } else uiYellTimer -= diff; - - // check if creature is not outside of building - if (uiResetTimer <= diff) - { - if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50) - { - EnterEvadeMode(); - DoScriptText(YELL_EVADE, me); - } - uiResetTimer = 5*IN_MILISECONDS; - } else uiResetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vanndar(Creature *_Creature) -{ - return new boss_vanndarAI (_Creature); -} - -void AddSC_boss_vanndar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vanndar"; - newscript->GetAI = &GetAI_boss_vanndar; - newscript->RegisterSelf(); -} \ No newline at end of file diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp deleted file mode 100644 index e04fa8444b2..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.cpp +++ /dev/null @@ -1,1338 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Blackrock_Depths -SD%Complete: 95 -SDComment: Quest support: 4001, 4342, 7604, 4322. Vendor Lokhtos Darkbargainer. Need to rewrite the Jail Break support -SDCategory: Blackrock Depths -EndScriptData */ - -/* ContentData -go_shadowforge_brazier -at_ring_of_law -npc_grimstone -mob_phalanx -npc_kharan_mighthammer -npc_lokhtos_darkbargainer -npc_dughal_stormwing -npc_marshal_windsor -npc_marshal_reginald_windsor -npc_tobias_seecher -npc_rocknot -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "blackrock_depths.h" - -/*###### -+## go_shadowforge_brazier -+######*/ - -bool GOHello_go_shadowforge_brazier(Player* /*pPlayer*/, GameObject* pGo) -{ - if (ScriptedInstance* pInstance = pGo->GetInstanceData()) - { - if (pInstance->GetData(TYPE_LYCEUM) == IN_PROGRESS) - pInstance->SetData(TYPE_LYCEUM, DONE); - else - pInstance->SetData(TYPE_LYCEUM, IN_PROGRESS); - // If used brazier open linked doors (North or South) - if (pGo->GetGUID() == pInstance->GetData64(DATA_SF_BRAZIER_N)) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GOLEM_DOOR_N), true); - else if (pGo->GetGUID() == pInstance->GetData64(DATA_SF_BRAZIER_S)) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GOLEM_DOOR_S), true); - } - return false; -} - -/*###### -## npc_grimstone -######*/ - -enum eGrimstone -{ - NPC_GRIMSTONE = 10096, - NPC_THELDREN = 16059, - - //4 or 6 in total? 1+2+1 / 2+2+2 / 3+3. Depending on this, code should be changed. - MAX_MOB_AMOUNT = 4 -}; - -uint32 RingMob[]= -{ - 8925, // Dredge Worm - 8926, // Deep Stinger - 8927, // Dark Screecher - 8928, // Burrowing Thundersnout - 8933, // Cave Creeper - 8932, // Borer Beetle -}; - -uint32 RingBoss[]= -{ - 9027, // Gorosh - 9028, // Grizzle - 9029, // Eviscerator - 9030, // Ok'thor - 9031, // Anub'shiah - 9032, // Hedrum -}; - -bool AreaTrigger_at_ring_of_law(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - if (ScriptedInstance* pInstance = pPlayer->GetInstanceData()) - { - if (pInstance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || pInstance->GetData(TYPE_RING_OF_LAW) == DONE) - return false; - - pInstance->SetData(TYPE_RING_OF_LAW,IN_PROGRESS); - pPlayer->SummonCreature(NPC_GRIMSTONE,625.559,-205.618,-52.735,2.609,TEMPSUMMON_DEAD_DESPAWN,0); - - return false; - } - return false; -} - -/*###### -## npc_grimstone -######*/ - -enum GrimstoneTexts -{ - SCRIPT_TEXT1 = -1000000, - SCRIPT_TEXT2 = -1000001, - SCRIPT_TEXT3 = -1000002, - SCRIPT_TEXT4 = -1000003, - SCRIPT_TEXT5 = -1000004, - SCRIPT_TEXT6 = -1000005 -}; - -//TODO: implement quest part of event (different end boss) -struct npc_grimstoneAI : public npc_escortAI -{ - npc_grimstoneAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - MobSpawnId = rand()%6; - } - - ScriptedInstance* pInstance; - - uint8 EventPhase; - uint32 Event_Timer; - - uint8 MobSpawnId; - uint8 MobCount; - uint32 MobDeath_Timer; - - uint64 RingMobGUID[4]; - uint64 RingBossGUID; - - bool CanWalk; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - EventPhase = 0; - Event_Timer = 1000; - - MobCount = 0; - MobDeath_Timer = 0; - - for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) - RingMobGUID[i] = 0; - - RingBossGUID = 0; - - CanWalk = false; - } - - //TODO: move them to center - void SummonRingMob() - { - if (Creature* tmp = me->SummonCreature(RingMob[MobSpawnId],608.960,-235.322,-53.907,1.857,TEMPSUMMON_DEAD_DESPAWN,0)) - RingMobGUID[MobCount] = tmp->GetGUID(); - - ++MobCount; - - if (MobCount == MAX_MOB_AMOUNT) - MobDeath_Timer = 2500; - } - - //TODO: move them to center - void SummonRingBoss() - { - if (Creature* tmp = me->SummonCreature(RingBoss[rand()%6],644.300,-175.989,-53.739,3.418,TEMPSUMMON_DEAD_DESPAWN,0)) - RingBossGUID = tmp->GetGUID(); - - MobDeath_Timer = 2500; - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 0: - DoScriptText(SCRIPT_TEXT1, me);//2 - CanWalk = false; - Event_Timer = 5000; - break; - case 1: - DoScriptText(SCRIPT_TEXT2, me);//4 - CanWalk = false; - Event_Timer = 5000; - break; - case 2: - CanWalk = false; - break; - case 3: - DoScriptText(SCRIPT_TEXT3, me);//5 - break; - case 4: - DoScriptText(SCRIPT_TEXT4, me);//6 - CanWalk = false; - Event_Timer = 5000; - break; - case 5: - if (pInstance) - { - pInstance->SetData(TYPE_RING_OF_LAW,DONE); - debug_log("TSCR: npc_grimstone: event reached end and set complete."); - } - break; - } - } - - void HandleGameObject(uint32 id, bool open) - { - pInstance->HandleGameObject(pInstance->GetData64(id), open); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (MobDeath_Timer) - { - if (MobDeath_Timer <= diff) - { - MobDeath_Timer = 2500; - - if (RingBossGUID) - { - Creature *boss = Unit::GetCreature(*me,RingBossGUID); - if (boss && !boss->isAlive() && boss->isDead()) - { - RingBossGUID = 0; - Event_Timer = 5000; - MobDeath_Timer = 0; - return; - } - return; - } - - for (uint8 i = 0; i < MAX_MOB_AMOUNT; ++i) - { - Creature *mob = Unit::GetCreature(*me,RingMobGUID[i]); - if (mob && !mob->isAlive() && mob->isDead()) - { - RingMobGUID[i] = 0; - --MobCount; - - //seems all are gone, so set timer to continue and discontinue this - if (!MobCount) - { - Event_Timer = 5000; - MobDeath_Timer = 0; - } - } - } - } else MobDeath_Timer -= diff; - } - - if (Event_Timer) - { - if (Event_Timer <= diff) - { - switch(EventPhase) - { - case 0: - DoScriptText(SCRIPT_TEXT5, me);//1 - HandleGameObject(DATA_ARENA4, false); - Start(false, false); - CanWalk = true; - Event_Timer = 0; - break; - case 1: - CanWalk = true; - Event_Timer = 0; - break; - case 2: - Event_Timer = 2000; - break; - case 3: - HandleGameObject(DATA_ARENA1, true); - Event_Timer = 3000; - break; - case 4: - CanWalk = true; - me->SetVisibility(VISIBILITY_OFF); - SummonRingMob(); - Event_Timer = 8000; - break; - case 5: - SummonRingMob(); - SummonRingMob(); - Event_Timer = 8000; - break; - case 6: - SummonRingMob(); - Event_Timer = 0; - break; - case 7: - me->SetVisibility(VISIBILITY_ON); - HandleGameObject(DATA_ARENA1, false); - DoScriptText(SCRIPT_TEXT6, me);//4 - CanWalk = true; - Event_Timer = 0; - break; - case 8: - HandleGameObject(DATA_ARENA2, true); - Event_Timer = 5000; - break; - case 9: - me->SetVisibility(VISIBILITY_OFF); - SummonRingBoss(); - Event_Timer = 0; - break; - case 10: - //if quest, complete - HandleGameObject(DATA_ARENA2, false); - HandleGameObject(DATA_ARENA3, true); - HandleGameObject(DATA_ARENA4, true); - CanWalk = true; - Event_Timer = 0; - break; - } - ++EventPhase; - } else Event_Timer -= diff; - } - - if (CanWalk) - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_grimstone(Creature* pCreature) -{ - return new npc_grimstoneAI(pCreature); -} - -/*###### -## mob_phalanx -######*/ - -enum PhalanxSpells -{ - SPELL_THUNDERCLAP = 8732, - SPELL_FIREBALLVOLLEY = 22425, - SPELL_MIGHTYBLOW = 14099 -}; - -struct mob_phalanxAI : public ScriptedAI -{ - mob_phalanxAI(Creature *c) : ScriptedAI(c) {} - - uint32 ThunderClap_Timer; - uint32 FireballVolley_Timer; - uint32 MightyBlow_Timer; - - void Reset() - { - ThunderClap_Timer = 12000; - FireballVolley_Timer =0; - MightyBlow_Timer = 15000; - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ThunderClap_Timer - if (ThunderClap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - ThunderClap_Timer = 10000; - } else ThunderClap_Timer -= diff; - - //FireballVolley_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - if (FireballVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALLVOLLEY); - FireballVolley_Timer = 15000; - } else FireballVolley_Timer -= diff; - } - - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTYBLOW); - MightyBlow_Timer = 10000; - } else MightyBlow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_mob_phalanx(Creature* pCreature) -{ - return new mob_phalanxAI (pCreature); -} - -/*###### -## npc_kharan_mighthammer -######*/ - -enum KharamQuests -{ - QUEST_4001 = 4001, - QUEST_4342 = 4342 -}; - -#define GOSSIP_ITEM_KHARAN_1 "I need to know where the princess are, Kharan!" -#define GOSSIP_ITEM_KHARAN_2 "All is not lost, Kharan!" - -#define GOSSIP_ITEM_KHARAN_3 "Gor'shak is my friend, you can trust me." -#define GOSSIP_ITEM_KHARAN_4 "Not enough, you need to tell me more." -#define GOSSIP_ITEM_KHARAN_5 "So what happened?" -#define GOSSIP_ITEM_KHARAN_6 "Continue..." -#define GOSSIP_ITEM_KHARAN_7 "So you suspect that someone on the inside was involved? That they were tipped off?" -#define GOSSIP_ITEM_KHARAN_8 "Continue with your story please." -#define GOSSIP_ITEM_KHARAN_9 "Indeed." -#define GOSSIP_ITEM_KHARAN_10 "The door is open, Kharan. You are a free man." - -bool GossipHello_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_4001) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - if (pPlayer->GetQuestStatus(4342) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - - if (pPlayer->GetTeam() == HORDE) - pPlayer->SEND_GOSSIP_MENU(2473, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(2474, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(2475, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(2476, pCreature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(2477, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(2478, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(2479, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - pPlayer->SEND_GOSSIP_MENU(2480, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); - pPlayer->SEND_GOSSIP_MENU(2481, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+8: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); - pPlayer->SEND_GOSSIP_MENU(2482, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+9: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pPlayer->GetTeam() == HORDE) - pPlayer->AreaExploredOrEventHappens(QUEST_4001); - else - pPlayer->AreaExploredOrEventHappens(QUEST_4342); - break; - } - return true; -} - -/*###### -## npc_lokhtos_darkbargainer -######*/ - -enum LokhtosItems -{ - ITEM_THRORIUM_BROTHERHOOD_CONTRACT = 18628, - ITEM_SULFURON_INGOT = 17203 -}; - -enum LokhtosQuests -{ - QUEST_A_BINDING_CONTRACT = 7604 -}; - -enum LokhtosSpells -{ - SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059 -}; - -#define GOSSIP_ITEM_SHOW_ACCESS "Show me what I have access to, Lothos." -#define GOSSIP_ITEM_GET_CONTRACT "Get Thorium Brotherhood Contract" - -bool GossipHello_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->isVendor() && pPlayer->GetReputationRank(59) >= REP_FRIENDLY) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_ITEM_SHOW_ACCESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - if (pPlayer->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 && - !pPlayer->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) && - pPlayer->HasItemCount(ITEM_SULFURON_INGOT, 1)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GET_CONTRACT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - } - - if (pPlayer->GetReputationRank(59) < REP_FRIENDLY) - pPlayer->SEND_GOSSIP_MENU(3673, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(3677, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false); - } - if (uiAction == GOSSIP_ACTION_TRADE) - pPlayer->SEND_VENDORLIST(pCreature->GetGUID()); - - return true; -} - -/*###### -## npc_dughal_stormwing -######*/ - -enum DughalQuests -{ - QUEST_JAIL_BREAK = 4322 -}; - -#define SAY_DUGHAL_FREE "Thank you, $N! I'm free!!!" -#define GOSSIP_DUGHAL "You're free, Dughal! Get out of here!" - -/* -struct npc_dughal_stormwingAI : public npc_escortAI -{ - npc_dughal_stormwingAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - switch(i) - { - case 0:me->Say(SAY_DUGHAL_FREE, LANG_UNIVERSAL, PlayerGUID); break; - case 1:pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_OBJECTIVE_COMPLETED);break; - case 2: - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_ENDED); - break; - } - } - - void EnterCombat(Unit* who) {} - void Reset() {} - - void JustDied(Unit* killer) - { - if (IsBeingEscorted && killer == me) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pInstance->SetData(DATA_DUGHAL,ENCOUNTER_STATE_ENDED); - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_ENDED) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_dughal_stormwing(Creature* pCreature) -{ - npc_dughal_stormwingAI* dughal_stormwingAI = new npc_dughal_stormwingAI(pCreature); - - dughal_stormwingAI->AddWaypoint(0, 280.42,-82.86, -77.12,0); - dughal_stormwingAI->AddWaypoint(1, 287.64,-87.01, -76.79,0); - dughal_stormwingAI->AddWaypoint(2, 354.63,-64.95, -67.53,0); - - return dughal_stormwingAI; -} -bool GossipHello_npc_dughal_stormwing(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUGHAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2846, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_dughal_stormwing(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, true, pPlayer->GetGUID()); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_IN_PROGRESS); - } - return true; -} - */ -/*###### -## npc_marshal_windsor -######*/ - -#define SAY_WINDSOR_AGGRO1 "You locked up the wrong Marshal. Prepare to be destroyed!" -#define SAY_WINDSOR_AGGRO2 "I bet you're sorry now, aren't you !?!!" -#define SAY_WINDSOR_AGGRO3 "You better hold me back $N or they are going to feel some prison house beatings." -#define SAY_WINDSOR_1 "Let's get a move on. My gear should be in the storage area up this way..." -#define SAY_WINDSOR_4_1 "Check that cell, $N. If someone is alive in there, we need to get them out." -#define SAY_WINDSOR_4_2 "Get him out of there!" -#define SAY_WINDSOR_4_3 "Good work! We're almost there, $N. This way." -#define SAY_WINDSOR_6 "This is it, $N. My stuff should be in that room. Cover me, I'm going in!" -#define SAY_WINDSOR_9 "Ah, there it is!" -#define MOB_ENTRY_REGINALD_WINDSOR 9682 - -Player* pPlayerStart; -/* -struct npc_marshal_windsorAI : public npc_escortAI -{ - npc_marshal_windsorAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 1: - me->Say(SAY_WINDSOR_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 7: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_WINDSOR_4_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 10: - me->setFaction(534); - break; - case 12: - me->Say(SAY_WINDSOR_6, LANG_UNIVERSAL, PlayerGUID); - pInstance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_IN_PROGRESS); - break; - case 13: - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK - break; - case 14: - pInstance->SetData(DATA_GATE_SR,0); - me->setFaction(11); - break; - case 16: - me->Say(SAY_WINDSOR_9, LANG_UNIVERSAL, PlayerGUID); - break; - case 17: - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK - break; - case 18: - pInstance->SetData(DATA_GATE_SC,0); - break; - case 19: - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SummonCreature(MOB_ENTRY_REGINALD_WINDSOR,403.61,-51.71,-63.92,3.600434,TEMPSUMMON_DEAD_DESPAWN ,0); - pInstance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_ENDED); - break; - } - } - - void EnterCombat(Unit* who) - { - switch (urand(0,2)) - { - case 0: me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); break; - case 1: me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); break; - case 2: me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); break; - } - } - - void Reset() {} - - void JustDied(Unit *slayer) - { - pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_FAILED); - } - - void UpdateAI(const uint32 diff) - { - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if (pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) - SetEscortPaused(false); - if (!pInstance->GetData(DATA_GATE_D) && pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_NOT_STARTED) - { - me->Say(SAY_WINDSOR_4_2, LANG_UNIVERSAL, PlayerGUID); - pInstance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_BEFORE_START); - } - if (pInstance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) - { - me->Say(SAY_WINDSOR_4_3, LANG_UNIVERSAL, PlayerGUID); - pInstance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); - } - if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_SUPPLY_ROOM) == ENCOUNTER_STATE_ENDED) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_marshal_windsor(Creature* pCreature) -{ - npc_marshal_windsorAI* marshal_windsorAI = new npc_marshal_windsorAI(pCreature); - - marshal_windsorAI->AddWaypoint(0, 316.336,-225.528, -77.7258,7000); - marshal_windsorAI->AddWaypoint(1, 316.336,-225.528, -77.7258,2000); - marshal_windsorAI->AddWaypoint(2, 322.96,-207.13, -77.87,0); - marshal_windsorAI->AddWaypoint(3, 281.05,-172.16, -75.12,0); - marshal_windsorAI->AddWaypoint(4, 272.19,-139.14, -70.61,0); - marshal_windsorAI->AddWaypoint(5, 283.62,-116.09, -70.21,0); - marshal_windsorAI->AddWaypoint(6, 296.18,-94.30, -74.08,0); - marshal_windsorAI->AddWaypoint(7, 294.57,-93.11, -74.08,0); - marshal_windsorAI->AddWaypoint(8, 314.31,-74.31, -76.09,0); - marshal_windsorAI->AddWaypoint(9, 360.22,-62.93, -66.77,0); - marshal_windsorAI->AddWaypoint(10, 383.38,-69.40, -63.25,0); - marshal_windsorAI->AddWaypoint(11, 389.99,-67.86, -62.57,0); - marshal_windsorAI->AddWaypoint(12, 400.98,-72.01, -62.31,0); - marshal_windsorAI->AddWaypoint(13, 404.22,-62.30, -63.50,2300); - marshal_windsorAI->AddWaypoint(14, 404.22,-62.30, -63.50,1500); - marshal_windsorAI->AddWaypoint(15, 407.65,-51.86, -63.96,0); - marshal_windsorAI->AddWaypoint(16, 403.61,-51.71, -63.92,1000); - marshal_windsorAI->AddWaypoint(17, 403.61,-51.71, -63.92,2000); - marshal_windsorAI->AddWaypoint(18, 403.61,-51.71, -63.92,1000); - marshal_windsorAI->AddWaypoint(19, 403.61,-51.71, -63.92,0); - - return marshal_windsorAI; -} - -bool QuestAccept_npc_marshal_windsor(Player* pPlayer, Creature* pCreature, Quest const *quest) -{ - if (quest->GetQuestId() == 4322) - {PlayerStart = player; - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - { - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_IN_PROGRESS); - pCreature->setFaction(11); - } - - } - return false; -} - */ -/*###### -## npc_marshal_reginald_windsor -######*/ - -#define SAY_REGINALD_WINDSOR_0_1 "Can you feel the power, $N??? It's time to ROCK!" -#define SAY_REGINALD_WINDSOR_0_2 "Now we just have to free Tobias and we can get out of here. This way!" -#define SAY_REGINALD_WINDSOR_5_1 "Open it." -#define SAY_REGINALD_WINDSOR_5_2 "I never did like those two. Let's get moving." -#define SAY_REGINALD_WINDSOR_7_1 "Open it and be careful this time!" -#define SAY_REGINALD_WINDSOR_7_2 "That intolerant dirtbag finally got what was coming to him. Good riddance!" -#define SAY_REGINALD_WINDSOR_7_3 "Alright, let's go." -#define SAY_REGINALD_WINDSOR_13_1 "Open it. We need to hurry up. I can smell those Dark Irons coming a mile away and I can tell you one thing, they're COMING!" -#define SAY_REGINALD_WINDSOR_13_2 "Administering fists of fury on Crest Killer!" -#define SAY_REGINALD_WINDSOR_13_3 "He has to be in the last cell. Unless... they killed him." -#define SAY_REGINALD_WINDSOR_14_1 "Get him out of there!" -#define SAY_REGINALD_WINDSOR_14_2 "Excellent work, $N. Let's find the exit. I think I know the way. Follow me!" -#define SAY_REGINALD_WINDSOR_20_1 "We made it!" -#define SAY_REGINALD_WINDSOR_20_2 "Meet me at Maxwell's encampment. We'll go over the next stages of the plan there and figure out a way to decode my tablets without the decryption ring." -#define MOB_ENTRY_SHILL_DINGER 9678 -#define MOB_ENTRY_CREST_KILLER 9680 - -int wp = 0; -/* -struct npc_marshal_reginald_windsorAI : public npc_escortAI -{ - npc_marshal_reginald_windsorAI(Creature *c) : npc_escortAI(c) - { - } - - void WaypointReached(uint32 i) - { - wp=i; - switch(i) - { - case 0: - me->setFaction(11); - me->Say(SAY_REGINALD_WINDSOR_0_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - me->Say(SAY_REGINALD_WINDSOR_0_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 7: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_5_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 8: - me->Say(SAY_REGINALD_WINDSOR_5_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 11: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_7_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 12: - me->Say(SAY_REGINALD_WINDSOR_7_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 13: - me->Say(SAY_REGINALD_WINDSOR_7_3, LANG_UNIVERSAL, PlayerGUID); - break; - case 20: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_13_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 21: - me->Say(SAY_REGINALD_WINDSOR_13_3, LANG_UNIVERSAL, PlayerGUID); - break; - case 23: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_14_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 24: - me->Say(SAY_REGINALD_WINDSOR_14_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 31: - me->Say(SAY_REGINALD_WINDSOR_20_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 32: - me->Say(SAY_REGINALD_WINDSOR_20_2, LANG_UNIVERSAL, PlayerGUID); - PlayerStart->GroupEventHappens(QUEST_JAIL_BREAK, me); - pInstance->SetData(DATA_SHILL, ENCOUNTER_STATE_ENDED); - break; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - if (who->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(who)->GetQuestStatus(4322) == QUEST_STATUS_INCOMPLETE) - { - float Radius = 10.0; - if (me->IsWithinDistInMap(who, Radius)) - { - SetEscortPaused(false); - Start(true, false, who->GetGUID()); - } - } - } - } - - void EnterCombat(Unit* who) - { - switch (urand(0,2)) - { - case 0: me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); break; - case 1: me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); break; - case 2: me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); break; - } - } - void Reset() {} - - void JustDied(Unit *slayer) - { - pInstance->SetData(DATA_QUEST_JAIL_BREAK,ENCOUNTER_STATE_FAILED); - } - - void UpdateAI(const uint32 diff) - { - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if (wp == 7) - { - if (!pInstance->GetData(DATA_GATE_J) && pInstance->GetData(DATA_JAZ) == ENCOUNTER_STATE_NOT_STARTED) - { - pInstance->SetData(DATA_CREATURE_JAZ,1); - pInstance->SetData(DATA_JAZ,ENCOUNTER_STATE_IN_PROGRESS); - } - if (pInstance->GetData(DATA_CREATURE_JAZ) && pInstance->GetData(DATA_CREATURE_OGRABISI) && pInstance->GetData(DATA_JAZ) == ENCOUNTER_STATE_IN_PROGRESS) - { - SetEscortPaused(false); - pInstance->SetData(DATA_JAZ,ENCOUNTER_STATE_ENDED); - } - } - else if (wp == 11) - { - if (!pInstance->GetData(DATA_GATE_S) && pInstance->GetData(DATA_SHILL) == ENCOUNTER_STATE_NOT_STARTED) - { - pInstance->SetData(DATA_CREATURE_SHILL,1); - pInstance->SetData(DATA_SHILL,ENCOUNTER_STATE_IN_PROGRESS); - } - if (pInstance->GetData(DATA_CREATURE_SHILL) && pInstance->GetData(DATA_SHILL) == ENCOUNTER_STATE_IN_PROGRESS) - { - pInstance->SetData(DATA_SHILL,ENCOUNTER_STATE_ENDED); - SetEscortPaused(false); - } - } - else if (wp == 20) - { - if (!pInstance->GetData(DATA_GATE_C) && pInstance->GetData(DATA_CREST) == ENCOUNTER_STATE_NOT_STARTED) - { - pInstance->SetData(DATA_CREATURE_CREST,1); - me->Say(SAY_REGINALD_WINDSOR_13_2, LANG_UNIVERSAL, PlayerGUID); - pInstance->SetData(DATA_CREST,ENCOUNTER_STATE_IN_PROGRESS); - } - if (pInstance->GetData(DATA_CREATURE_CREST) && pInstance->GetData(DATA_CREST) == ENCOUNTER_STATE_IN_PROGRESS) - { - SetEscortPaused(false); - pInstance->SetData(DATA_CREST,ENCOUNTER_STATE_ENDED); - } - } - if (pInstance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) SetEscortPaused(false); - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_marshal_reginald_windsor(Creature* pCreature) -{ - npc_marshal_reginald_windsorAI* marshal_reginald_windsorAI = new npc_marshal_reginald_windsorAI(pCreature); - - marshal_reginald_windsorAI->AddWaypoint(0, 403.61,-52.71, -63.92,4000); - marshal_reginald_windsorAI->AddWaypoint(1, 403.61,-52.71, -63.92,4000); - marshal_reginald_windsorAI->AddWaypoint(2, 406.33,-54.87, -63.95,0); - marshal_reginald_windsorAI->AddWaypoint(3, 407.99,-73.91, -62.26,0); - marshal_reginald_windsorAI->AddWaypoint(4, 557.03,-119.71, -61.83,0); - marshal_reginald_windsorAI->AddWaypoint(5, 573.40,-124.39, -65.07,0); - marshal_reginald_windsorAI->AddWaypoint(6, 593.91,-130.29, -69.25,0); - marshal_reginald_windsorAI->AddWaypoint(7, 593.21,-132.16, -69.25,0); - marshal_reginald_windsorAI->AddWaypoint(8, 593.21,-132.16, -69.25,3000); - marshal_reginald_windsorAI->AddWaypoint(9, 622.81,-135.55, -71.92,0); - marshal_reginald_windsorAI->AddWaypoint(10, 634.68,-151.29, -70.32,0); - marshal_reginald_windsorAI->AddWaypoint(11, 635.06,-153.25, -70.32,0); - marshal_reginald_windsorAI->AddWaypoint(12, 635.06,-153.25, -70.32,3000); - marshal_reginald_windsorAI->AddWaypoint(13, 635.06,-153.25, -70.32,1500); - marshal_reginald_windsorAI->AddWaypoint(14, 655.25,-172.39, -73.72,0); - marshal_reginald_windsorAI->AddWaypoint(15, 654.79,-226.30, -83.06,0); - marshal_reginald_windsorAI->AddWaypoint(16, 622.85,-268.85, -83.96,0); - marshal_reginald_windsorAI->AddWaypoint(17, 579.45,-275.56, -80.44,0); - marshal_reginald_windsorAI->AddWaypoint(18, 561.19,-266.85, -75.59,0); - marshal_reginald_windsorAI->AddWaypoint(19, 547.91,-253.92, -70.34,0); - marshal_reginald_windsorAI->AddWaypoint(20, 549.20,-252.40, -70.34,0); - marshal_reginald_windsorAI->AddWaypoint(21, 549.20,-252.40, -70.34,4000); - marshal_reginald_windsorAI->AddWaypoint(22, 555.33,-269.16, -74.40,0); - marshal_reginald_windsorAI->AddWaypoint(23, 554.31,-270.88, -74.40,0); - marshal_reginald_windsorAI->AddWaypoint(24, 554.31,-270.88, -74.40,4000); - marshal_reginald_windsorAI->AddWaypoint(25, 536.10,-249.60, -67.47,0); - marshal_reginald_windsorAI->AddWaypoint(26, 520.94,-216.65, -59.28,0); - marshal_reginald_windsorAI->AddWaypoint(27, 505.99,-148.74, -62.17,0); - marshal_reginald_windsorAI->AddWaypoint(28, 484.21,-56.24, -62.43,0); - marshal_reginald_windsorAI->AddWaypoint(29, 470.39,-6.01, -70.10,0); - marshal_reginald_windsorAI->AddWaypoint(30, 451.27,30.85, -70.07,0); - marshal_reginald_windsorAI->AddWaypoint(31, 452.45,29.85, -70.37,1500); - marshal_reginald_windsorAI->AddWaypoint(32, 452.45,29.85, -70.37,7000); - marshal_reginald_windsorAI->AddWaypoint(33, 452.45,29.85, -70.37,10000); - marshal_reginald_windsorAI->AddWaypoint(34, 451.27,31.85, -70.07,0); - - return marshal_reginald_windsorAI; -} -*/ -/*###### -## npc_tobias_seecher -######*/ - -#define SAY_TOBIAS_FREE "Thank you! I will run for safety immediately!" -/* -struct npc_tobias_seecherAI : public npc_escortAI -{ - npc_tobias_seecherAI(Creature *c) :npc_escortAI(c) {} - - void EnterCombat(Unit* who) {} - void Reset() {} - - void JustDied(Unit* killer) - { - if (IsBeingEscorted && killer == me) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_ENDED); - } - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 0:me->Say(SAY_TOBIAS_FREE, LANG_UNIVERSAL, PlayerGUID); break; - case 2: - pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_OBJECTIVE_COMPLETED);break; - case 4: - me->SetVisibility(VISIBILITY_OFF); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_ENDED); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if ((pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& pInstance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_ENDED) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_tobias_seecher(Creature* pCreature) -{ - npc_tobias_seecherAI* tobias_seecherAI = new npc_tobias_seecherAI(pCreature); - - tobias_seecherAI->AddWaypoint(0, 549.21, -281.07, -75.27); - tobias_seecherAI->AddWaypoint(1, 554.39, -267.39, -73.68); - tobias_seecherAI->AddWaypoint(2, 533.59, -249.38, -67.04); - tobias_seecherAI->AddWaypoint(3, 519.44, -217.02, -59.34); - tobias_seecherAI->AddWaypoint(4, 506.55, -153.49, -62.34); - - return tobias_seecherAI; -} - -bool GossipHello_npc_tobias_seecher(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && pInstance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Get out of here, Tobias, you're free!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2847, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_tobias_seecher(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, true, pPlayer->GetGUID()); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pInstance->SetData(DATA_TOBIAS,ENCOUNTER_STATE_IN_PROGRESS); - } - return true; -} -*/ - -/*###### -## npc_rocknot -######*/ - -enum RocknotSays -{ - SAY_GOT_BEER = -1230000 -}; - -enum RocknotSpells -{ - SPELL_DRUNKEN_RAGE = 14872 -}; - -enum RocknotQuests -{ - QUEST_ALE = 4295 -}; - -struct npc_rocknotAI : public npc_escortAI -{ - npc_rocknotAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 BreakKeg_Timer; - uint32 BreakDoor_Timer; - - void Reset() - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - BreakKeg_Timer = 0; - BreakDoor_Timer = 0; - } - - void DoGo(uint32 id, uint32 state) - { - if (GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(id))) - pGo->SetGoState((GOState)state); - } - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch(i) - { - case 1: - me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - break; - case 2: - me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); - break; - case 3: - me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACKUNARMED); - break; - case 4: - me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - break; - case 5: - me->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - BreakKeg_Timer = 2000; - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (BreakKeg_Timer) - { - if (BreakKeg_Timer <= diff) - { - DoGo(DATA_GO_BAR_KEG,0); - BreakKeg_Timer = 0; - BreakDoor_Timer = 1000; - } else BreakKeg_Timer -= diff; - } - - if (BreakDoor_Timer) - { - if (BreakDoor_Timer <= diff) - { - DoGo(DATA_GO_BAR_DOOR,2); - DoGo(DATA_GO_BAR_KEG_TRAP,0); //doesn't work very well, leaving code here for future - //spell by trap has effect61, this indicate the bar go hostile - - if (Unit *tmp = Unit::GetUnit(*me,pInstance->GetData64(DATA_PHALANX))) - tmp->setFaction(14); - - //for later, this event(s) has alot more to it. - //optionally, DONE can trigger bar to go hostile. - pInstance->SetData(TYPE_BAR,DONE); - - BreakDoor_Timer = 0; - } else BreakDoor_Timer -= diff; - } - - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_rocknot(Creature* pCreature) -{ - return new npc_rocknotAI(pCreature); -} - -bool ChooseReward_npc_rocknot(Player* /*pPlayer*/, Creature* pCreature, const Quest *_Quest, uint32 /*item*/) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (!pInstance) - return true; - - if (pInstance->GetData(TYPE_BAR) == DONE || pInstance->GetData(TYPE_BAR) == SPECIAL) - return true; - - if (_Quest->GetQuestId() == QUEST_ALE) - { - if (pInstance->GetData(TYPE_BAR) != IN_PROGRESS) - pInstance->SetData(TYPE_BAR,IN_PROGRESS); - - pInstance->SetData(TYPE_BAR,SPECIAL); - - //keep track of amount in instance script, returns SPECIAL if amount ok and event in progress - if (pInstance->GetData(TYPE_BAR) == SPECIAL) - { - DoScriptText(SAY_GOT_BEER, pCreature); - pCreature->CastSpell(pCreature,SPELL_DRUNKEN_RAGE,false); - if (npc_escortAI* pEscortAI = CAST_AI(npc_rocknotAI, pCreature->AI())) - pEscortAI->Start(false, false); - } - } - - return true; -} - -/*###### -## -######*/ - -void AddSC_blackrock_depths() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_shadowforge_brazier"; - newscript->pGOHello = &GOHello_go_shadowforge_brazier; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_ring_of_law"; - newscript->pAreaTrigger = &AreaTrigger_at_ring_of_law; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_grimstone"; - newscript->GetAI = &GetAI_npc_grimstone; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phalanx"; - newscript->GetAI = &GetAI_mob_phalanx; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_kharan_mighthammer"; - newscript->pGossipHello = &GossipHello_npc_kharan_mighthammer; - newscript->pGossipSelect = &GossipSelect_npc_kharan_mighthammer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lokhtos_darkbargainer"; - newscript->pGossipHello = &GossipHello_npc_lokhtos_darkbargainer; - newscript->pGossipSelect = &GossipSelect_npc_lokhtos_darkbargainer; - newscript->RegisterSelf(); -/* - newscript = new Script; - newscript->Name = "npc_dughal_stormwing"; - newscript->pGossipHello = &GossipHello_npc_dughal_stormwing; - newscript->pGossipSelect = &GossipSelect_npc_dughal_stormwing; - newscript->GetAI = &GetAI_npc_dughal_stormwing; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tobias_seecher"; - newscript->pGossipHello = &GossipHello_npc_tobias_seecher; - newscript->pGossipSelect = &GossipSelect_npc_tobias_seecher; - newscript->GetAI = &GetAI_npc_tobias_seecher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_marshal_windsor"; - newscript->pQuestAccept = &QuestAccept_npc_marshal_windsor; - newscript->GetAI = &GetAI_npc_marshal_windsor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_marshal_reginald_windsor"; - newscript->GetAI = &GetAI_npc_marshal_reginald_windsor; - newscript->RegisterSelf(); -*/ - newscript = new Script; - newscript->Name = "npc_rocknot"; - newscript->GetAI = &GetAI_npc_rocknot; - newscript->pChooseReward = &ChooseReward_npc_rocknot; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h b/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h deleted file mode 100644 index edb340252b2..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/blackrock_depths.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BRD_H -#define DEF_BRD_H - -#define FACTION_NEUTRAL 734 -#define FACTION_HOSTILE 754 -#define FACTION_FRIEND 35 - -enum eTypes -{ - TYPE_RING_OF_LAW = 1, - TYPE_VAULT = 2, - TYPE_BAR = 3, - TYPE_TOMB_OF_SEVEN = 4, - TYPE_LYCEUM = 5, - TYPE_IRON_HALL = 6, - - DATA_EMPEROR = 10, - DATA_PHALANX = 11, - - DATA_ARENA1 = 12, - DATA_ARENA2 = 13, - DATA_ARENA3 = 14, - DATA_ARENA4 = 15, - - DATA_GO_BAR_KEG = 16, - DATA_GO_BAR_KEG_TRAP = 17, - DATA_GO_BAR_DOOR = 18, - DATA_GO_CHALICE = 19, - - DATA_GHOSTKILL = 20, - DATA_EVENSTARTER = 21, - - DATA_GOLEM_DOOR_N = 22, - DATA_GOLEM_DOOR_S = 23, - - DATA_THRONE_DOOR = 24, - - DATA_SF_BRAZIER_N = 25, - DATA_SF_BRAZIER_S = 26 -}; -#endif diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp deleted file mode 100644 index a387e816951..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_ambassador_flamelash.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ambassador_Flamelash -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_FIREBLAST = 15573 -}; - -struct boss_ambassador_flamelashAI : public ScriptedAI -{ - boss_ambassador_flamelashAI(Creature *c) : ScriptedAI(c) {} - - uint32 FireBlast_Timer; - uint32 Spirit_Timer; - - void Reset() - { - FireBlast_Timer = 2000; - Spirit_Timer = 24000; - } - - void EnterCombat(Unit * /*who*/) {} - - void SummonSpirits(Unit* victim) - { - if (Creature *Spirit = DoSpawnCreature(9178, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) - Spirit->AI()->AttackStart(victim); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FireBlast_Timer - if (FireBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBLAST); - FireBlast_Timer = 7000; - } else FireBlast_Timer -= diff; - - //Spirit_Timer - if (Spirit_Timer <= diff) - { - SummonSpirits(me->getVictim()); - SummonSpirits(me->getVictim()); - SummonSpirits(me->getVictim()); - SummonSpirits(me->getVictim()); - - Spirit_Timer = 30000; - } else Spirit_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ambassador_flamelash(Creature* pCreature) -{ - return new boss_ambassador_flamelashAI (pCreature); -} - -void AddSC_boss_ambassador_flamelash() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ambassador_flamelash"; - newscript->GetAI = &GetAI_boss_ambassador_flamelash; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp deleted file mode 100644 index 60e1dec236c..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_anubshiah.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Anubshiah -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_SHADOWBOLT = 17228, - SPELL_CURSEOFTONGUES = 15470, - SPELL_CURSEOFWEAKNESS = 17227, - SPELL_DEMONARMOR = 11735, - SPELL_ENVELOPINGWEB = 15471 -}; - -struct boss_anubshiahAI : public ScriptedAI -{ - boss_anubshiahAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowBolt_Timer; - uint32 CurseOfTongues_Timer; - uint32 CurseOfWeakness_Timer; - uint32 DemonArmor_Timer; - uint32 EnvelopingWeb_Timer; - - void Reset() - { - ShadowBolt_Timer = 7000; - CurseOfTongues_Timer = 24000; - CurseOfWeakness_Timer = 12000; - DemonArmor_Timer = 3000; - EnvelopingWeb_Timer = 16000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLT); - ShadowBolt_Timer = 7000; - } else ShadowBolt_Timer -= diff; - - //CurseOfTongues_Timer - if (CurseOfTongues_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CURSEOFTONGUES); - CurseOfTongues_Timer = 18000; - } else CurseOfTongues_Timer -= diff; - - //CurseOfWeakness_Timer - if (CurseOfWeakness_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); - CurseOfWeakness_Timer = 45000; - } else CurseOfWeakness_Timer -= diff; - - //DemonArmor_Timer - if (DemonArmor_Timer <= diff) - { - DoCast(me, SPELL_DEMONARMOR); - DemonArmor_Timer = 300000; - } else DemonArmor_Timer -= diff; - - //EnvelopingWeb_Timer - if (EnvelopingWeb_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ENVELOPINGWEB); - EnvelopingWeb_Timer = 12000; - } else EnvelopingWeb_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_anubshiah(Creature* pCreature) -{ - return new boss_anubshiahAI (pCreature); -} - -void AddSC_boss_anubshiah() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_anubshiah"; - newscript->GetAI = &GetAI_boss_anubshiah; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp deleted file mode 100644 index 29fe219d6ec..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Emperor_Dagran_Thaurissan -SD%Complete: 99 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Yells -{ - SAY_AGGRO = -1230001, - SAY_SLAY = -1230002 -}; - -enum Spells -{ - SPELL_HANDOFTHAURISSAN = 17492, - SPELL_AVATAROFFLAME = 15636 -}; - -struct boss_draganthaurissanAI : public ScriptedAI -{ - boss_draganthaurissanAI(Creature *c) : ScriptedAI(c) {} - - uint32 HandOfThaurissan_Timer; - uint32 AvatarOfFlame_Timer; - //uint32 Counter; - - void Reset() - { - HandOfThaurissan_Timer = 4000; - AvatarOfFlame_Timer = 25000; - //Counter= 0; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - me->CallForHelp(VISIBLE_RANGE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (HandOfThaurissan_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_HANDOFTHAURISSAN); - - //3 Hands of Thaurissan will be casted - //if (Counter < 3) - //{ - // HandOfThaurissan_Timer = 1000; - // ++Counter; - //} - //else - //{ - HandOfThaurissan_Timer = 5000; - //Counter = 0; - //} - } else HandOfThaurissan_Timer -= diff; - - //AvatarOfFlame_Timer - if (AvatarOfFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_AVATAROFFLAME); - AvatarOfFlame_Timer = 18000; - } else AvatarOfFlame_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_draganthaurissan(Creature* pCreature) -{ - return new boss_draganthaurissanAI (pCreature); -} - -void AddSC_boss_draganthaurissan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_emperor_dagran_thaurissan"; - newscript->GetAI = &GetAI_boss_draganthaurissan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp deleted file mode 100644 index 77d69263133..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_general_angerforge.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_General_Angerforge -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_MIGHTYBLOW = 14099, - SPELL_HAMSTRING = 9080, - SPELL_CLEAVE = 20691 -}; - -struct boss_general_angerforgeAI : public ScriptedAI -{ - boss_general_angerforgeAI(Creature *c) : ScriptedAI(c) {} - - uint32 MightyBlow_Timer; - uint32 HamString_Timer; - uint32 Cleave_Timer; - uint32 Adds_Timer; - bool Medics; - - void Reset() - { - MightyBlow_Timer = 8000; - HamString_Timer = 12000; - Cleave_Timer = 16000; - Adds_Timer = 0; - Medics = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonAdds(Unit* victim) - { - if (Creature *SummonedAdd = DoSpawnCreature(8901, irand(-14,14), irand(-14,14), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedAdd->AI()->AttackStart(victim); - } - - void SummonMedics(Unit* victim) - { - if (Creature *SummonedMedic = DoSpawnCreature(8894, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedMedic->AI()->AttackStart(victim); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTYBLOW); - MightyBlow_Timer = 18000; - } else MightyBlow_Timer -= diff; - - //HamString_Timer - if (HamString_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - HamString_Timer = 15000; - } else HamString_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 9000; - } else Cleave_Timer -= diff; - - //Adds_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 21) - { - if (Adds_Timer <= diff) - { - // summon 3 Adds every 25s - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - - Adds_Timer = 25000; - } else Adds_Timer -= diff; - } - - //Summon Medics - if (!Medics && me->GetHealth()*100 / me->GetMaxHealth() < 21) - { - SummonMedics(me->getVictim()); - SummonMedics(me->getVictim()); - Medics = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_general_angerforge(Creature* pCreature) -{ - return new boss_general_angerforgeAI (pCreature); -} - -void AddSC_boss_general_angerforge() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_general_angerforge"; - newscript->GetAI = &GetAI_boss_general_angerforge; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp deleted file mode 100644 index 886bc3fc909..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gorosh_the_Dervish -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_WHIRLWIND = 15589, - SPELL_MORTALSTRIKE = 24573 -}; - -struct boss_gorosh_the_dervishAI : public ScriptedAI -{ - boss_gorosh_the_dervishAI(Creature *c) : ScriptedAI(c) {} - - uint32 WhirlWind_Timer; - uint32 MortalStrike_Timer; - - void Reset() - { - WhirlWind_Timer = 12000; - MortalStrike_Timer = 22000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //WhirlWind_Timer - if (WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - WhirlWind_Timer = 15000; - } else WhirlWind_Timer -= diff; - - //MortalStrike_Timer - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = 15000; - } else MortalStrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gorosh_the_dervish(Creature* pCreature) -{ - return new boss_gorosh_the_dervishAI (pCreature); -} - -void AddSC_boss_gorosh_the_dervish() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gorosh_the_dervish"; - newscript->GetAI = &GetAI_boss_gorosh_the_dervish; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp deleted file mode 100644 index d3551d38790..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_grizzle.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grizzle -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Yells -{ - EMOTE_GENERIC_FRENZY_KILL = -1000001 -}; - -enum Spells -{ - SPELL_GROUNDTREMOR = 6524, - SPELL_FRENZY = 28371 -}; - -struct boss_grizzleAI : public ScriptedAI -{ - boss_grizzleAI(Creature *c) : ScriptedAI(c) {} - - uint32 GroundTremor_Timer; - uint32 Frenzy_Timer; - - void Reset() - { - GroundTremor_Timer = 12000; - Frenzy_Timer =0; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //GroundTremor_Timer - if (GroundTremor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GROUNDTREMOR); - GroundTremor_Timer = 8000; - } else GroundTremor_Timer -= diff; - - //Frenzy_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - if (Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); - - Frenzy_Timer = 15000; - } else Frenzy_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_grizzle(Creature* pCreature) -{ - return new boss_grizzleAI (pCreature); -} - -void AddSC_boss_grizzle() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grizzle"; - newscript->GetAI = &GetAI_boss_grizzle; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp deleted file mode 100644 index 2af203826a1..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_High_Interrogator_Gerstahn -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_SHADOWWORDPAIN = 10894, - SPELL_MANABURN = 10876, - SPELL_PSYCHICSCREAM = 8122, - SPELL_SHADOWSHIELD = 22417 -}; - -struct boss_high_interrogator_gerstahnAI : public ScriptedAI -{ - boss_high_interrogator_gerstahnAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowWordPain_Timer; - uint32 ManaBurn_Timer; - uint32 PsychicScream_Timer; - uint32 ShadowShield_Timer; - - void Reset() - { - ShadowWordPain_Timer = 4000; - ManaBurn_Timer = 14000; - PsychicScream_Timer = 32000; - ShadowShield_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SHADOWWORDPAIN); - ShadowWordPain_Timer = 7000; - } else ShadowWordPain_Timer -= diff; - - //ManaBurn_Timer - if (ManaBurn_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_MANABURN); - ManaBurn_Timer = 10000; - } else ManaBurn_Timer -= diff; - - //PsychicScream_Timer - if (PsychicScream_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PSYCHICSCREAM); - PsychicScream_Timer = 30000; - } else PsychicScream_Timer -= diff; - - //ShadowShield_Timer - if (ShadowShield_Timer <= diff) - { - DoCast(me, SPELL_SHADOWSHIELD); - ShadowShield_Timer = 25000; - } else ShadowShield_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_high_interrogator_gerstahn(Creature* pCreature) -{ - return new boss_high_interrogator_gerstahnAI (pCreature); -} - -void AddSC_boss_high_interrogator_gerstahn() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_high_interrogator_gerstahn"; - newscript->GetAI = &GetAI_boss_high_interrogator_gerstahn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp deleted file mode 100644 index 2a0cf9be133..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_magmus.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Magmus -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_FIERYBURST = 13900, - SPELL_WARSTOMP = 24375 -}; - -enum eEnums -{ - DATA_THRONE_DOOR = 24 // not id or guid of doors but number of enum in blackrock_depths.h -}; - -struct boss_magmusAI : public ScriptedAI -{ - boss_magmusAI(Creature *c) : ScriptedAI(c) {} - - uint32 FieryBurst_Timer; - uint32 WarStomp_Timer; - - void Reset() - { - FieryBurst_Timer = 5000; - WarStomp_Timer =0; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FieryBurst_Timer - if (FieryBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIERYBURST); - FieryBurst_Timer = 6000; - } else FieryBurst_Timer -= diff; - - //WarStomp_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - if (WarStomp_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WARSTOMP); - WarStomp_Timer = 8000; - } else WarStomp_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - // When he die open door to last chamber - void JustDied(Unit *who) - { - if (ScriptedInstance* pInstance = who->GetInstanceData()) - pInstance->HandleGameObject(pInstance->GetData64(DATA_THRONE_DOOR), true); - } -}; -CreatureAI* GetAI_boss_magmus(Creature* pCreature) -{ - return new boss_magmusAI (pCreature); -} - -void AddSC_boss_magmus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magmus"; - newscript->GetAI = &GetAI_boss_magmus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp deleted file mode 100644 index 1c0ed389287..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_moira_bronzebeard.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Moira_Bronzbeard -SD%Complete: 90 -SDComment: Healing of Emperor NYI -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" - -enum Spells -{ - SPELL_HEAL = 10917, - SPELL_RENEW = 10929, - SPELL_SHIELD = 10901, - SPELL_MINDBLAST = 10947, - SPELL_SHADOWWORDPAIN = 10894, - SPELL_SMITE = 10934 -}; - -struct boss_moira_bronzebeardAI : public ScriptedAI -{ - boss_moira_bronzebeardAI(Creature *c) : ScriptedAI(c) {} - - uint32 Heal_Timer; - uint32 MindBlast_Timer; - uint32 ShadowWordPain_Timer; - uint32 Smite_Timer; - - void Reset() - { - Heal_Timer = 12000; //These times are probably wrong - MindBlast_Timer = 16000; - ShadowWordPain_Timer = 2000; - Smite_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //MindBlast_Timer - if (MindBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MINDBLAST); - MindBlast_Timer = 14000; - } else MindBlast_Timer -= diff; - - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); - ShadowWordPain_Timer = 18000; - } else ShadowWordPain_Timer -= diff; - - //Smite_Timer - if (Smite_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SMITE); - Smite_Timer = 10000; - } else Smite_Timer -= diff; - - } -}; -CreatureAI* GetAI_boss_moira_bronzebeard(Creature* pCreature) -{ - return new boss_moira_bronzebeardAI (pCreature); -} - -void AddSC_boss_moira_bronzebeard() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_moira_bronzebeard"; - newscript->GetAI = &GetAI_boss_moira_bronzebeard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp deleted file mode 100644 index 94a37e8da7e..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/boss_tomb_of_seven.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Tomb_Of_Seven -SD%Complete: 90 -SDComment: Learning Smelt Dark Iron if tribute quest rewarded. Missing event. -SDCategory: Blackrock Depths -EndScriptData */ - -#include "ScriptedPch.h" -#include "blackrock_depths.h" - -enum Spells -{ - SPELL_SMELT_DARK_IRON = 14891, - SPELL_LEARN_SMELT = 14894, -}; - -enum Quests -{ - QUEST_SPECTRAL_CHALICE = 4083 -}; - -enum Misc -{ - DATA_SKILLPOINT_MIN = 230 -}; - -#define GOSSIP_ITEM_TEACH_1 "Teach me the art of smelting dark iron" -#define GOSSIP_ITEM_TEACH_2 "Continue..." -#define GOSSIP_ITEM_TEACH_3 "[PH] Continue..." -#define GOSSIP_ITEM_TRIBUTE "I want to pay tribute" - -bool GossipHello_boss_gloomrel(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 1 && pPlayer->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN && !pPlayer->HasSpell(SPELL_SMELT_DARK_IRON)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) == 0 && pPlayer->GetSkillValue(SKILL_MINING) >= DATA_SKILLPOINT_MIN) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TRIBUTE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_boss_gloomrel(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - pPlayer->SEND_GOSSIP_MENU(2606, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer, SPELL_LEARN_SMELT, false); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22); - pPlayer->SEND_GOSSIP_MENU(2604, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+22: - pPlayer->CLOSE_GOSSIP_MENU(); - if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) - { - //are 5 minutes expected? go template may have data to despawn when used at quest - pInstance->DoRespawnGameObject(pInstance->GetData64(DATA_GO_CHALICE),MINUTE*5); - } - break; - } - return true; -} - -enum DoomrelSpells -{ - SPELL_SHADOWBOLTVOLLEY = 15245, - SPELL_IMMOLATE = 12742, - SPELL_CURSEOFWEAKNESS = 12493, - SPELL_DEMONARMOR = 13787, - SPELL_SUMMON_VOIDWALKERS = 15092 -}; - -struct boss_doomrelAI : public ScriptedAI -{ - boss_doomrelAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 ShadowVolley_Timer; - uint32 Immolate_Timer; - uint32 CurseOfWeakness_Timer; - uint32 DemonArmor_Timer; - bool Voidwalkers; - - void Reset() - { - ShadowVolley_Timer = 10000; - Immolate_Timer = 18000; - CurseOfWeakness_Timer = 5000; - DemonArmor_Timer = 16000; - Voidwalkers = false; - - me->setFaction(FACTION_FRIEND); - - // was set before event start, so set again - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - - if (pInstance) - if (pInstance->GetData(DATA_GHOSTKILL) >= 7) - me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); - else - me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void EnterEvadeMode() - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->LoadCreaturesAddon(); - if (me->isAlive()) - me->GetMotionMaster()->MoveTargetedHome(); - me->SetLootRecipient(NULL); - if (pInstance) - pInstance->SetData64(DATA_EVENSTARTER, 0); - } - - void JustDied(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_GHOSTKILL, 1); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowVolley_Timer - if (ShadowVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLTVOLLEY); - ShadowVolley_Timer = 12000; - } else ShadowVolley_Timer -= diff; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_IMMOLATE); - - Immolate_Timer = 25000; - } else Immolate_Timer -= diff; - - //CurseOfWeakness_Timer - if (CurseOfWeakness_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); - CurseOfWeakness_Timer = 45000; - } else CurseOfWeakness_Timer -= diff; - - //DemonArmor_Timer - if (DemonArmor_Timer <= diff) - { - DoCast(me, SPELL_DEMONARMOR); - DemonArmor_Timer = 300000; - } else DemonArmor_Timer -= diff; - - //Summon Voidwalkers - if (!Voidwalkers && me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - DoCast(me->getVictim(), SPELL_SUMMON_VOIDWALKERS, true); - Voidwalkers = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_doomrel(Creature* pCreature) -{ - return new boss_doomrelAI (pCreature); -} - -#define GOSSIP_ITEM_CHALLENGE "Your bondage is at an end, Doom'rel. I challenge you!" -#define GOSSIP_SELECT_DOOMREL "[PH] Continue..." - -bool GossipHello_boss_doomrel(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(2601, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_boss_doomrel(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_DOOMREL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(2605, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - //start event here - pCreature->setFaction(FACTION_HOSTILE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - pCreature->AI()->AttackStart(pPlayer); - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance) - pInstance->SetData64(DATA_EVENSTARTER,pPlayer->GetGUID()); - break; - } - return true; -} - -void AddSC_boss_tomb_of_seven() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_gloomrel"; - newscript->pGossipHello = &GossipHello_boss_gloomrel; - newscript->pGossipSelect = &GossipSelect_boss_gloomrel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_doomrel"; - newscript->GetAI = &GetAI_boss_doomrel; - newscript->pGossipHello = &GossipHello_boss_doomrel; - newscript->pGossipSelect = &GossipSelect_boss_doomrel; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp deleted file mode 100644 index 7684aa6c6ac..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_depths/instance_blackrock_depths.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Blackrock_Depths -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Depths -EndScriptData */ - -/* -update `creature_template` set `npcflag`='1',`ScriptName`='npc_dughal_stormwing' where `entry`='9022'; -update `creature_template` set `ScriptName`='npc_marshal_windsor' where `entry`='9023'; -update `creature_template` set `ScriptName`='npc_marshal_reginald_windsor' where `entry`='9682'; -update `creature_template` set `npcflag`='1',`ScriptName`='npc_tobias_seecher' where `entry`='9679'; -update `instance_template` set `script`='instance_blackrock_depths' where `map`='230'; -*/ - -#include "ScriptedPch.h" -#include "blackrock_depths.h" - -#define TIMER_TOMBOFTHESEVEN 15000 - -enum eEnums -{ - MAX_ENCOUNTER = 6, - - NPC_EMPEROR = 9019, - NPC_PHALANX = 9502, - NPC_ANGERREL = 9035, - NPC_DOPEREL = 9040, - NPC_HATEREL = 9034, - NPC_VILEREL = 9036, - NPC_SEETHREL = 9038, - NPC_GLOOMREL = 9037, - NPC_DOOMREL = 9039, - NPC_MAGMUS = 9938, - - GO_ARENA1 = 161525, - GO_ARENA2 = 161522, - GO_ARENA3 = 161524, - GO_ARENA4 = 161523, - GO_SHADOW_LOCK = 161460, - GO_SHADOW_MECHANISM = 161461, - GO_SHADOW_GIANT_DOOR = 157923, - GO_SHADOW_DUMMY = 161516, - GO_BAR_KEG_SHOT = 170607, - GO_BAR_KEG_TRAP = 171941, - GO_BAR_DOOR = 170571, - GO_TOMB_ENTER = 170576, - GO_TOMB_EXIT = 170577, - GO_LYCEUM = 170558, - GO_SF_N = 174745, // Shadowforge Brazier North - GO_SF_S = 174744, // Shadowforge Brazier South - GO_GOLEM_ROOM_N = 170573, // Magmus door North - GO_GOLEM_ROOM_S = 170574, // Magmus door Soutsh - GO_THRONE_ROOM = 170575, // Throne door - - GO_SPECTRAL_CHALICE = 164869, - GO_CHEST_SEVEN = 169243 -}; - -struct instance_blackrock_depths : public ScriptedInstance -{ - instance_blackrock_depths(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 EmperorGUID; - uint64 PhalanxGUID; - uint64 MagmusGUID; - - uint64 GoArena1GUID; - uint64 GoArena2GUID; - uint64 GoArena3GUID; - uint64 GoArena4GUID; - uint64 GoShadowLockGUID; - uint64 GoShadowMechGUID; - uint64 GoShadowGiantGUID; - uint64 GoShadowDummyGUID; - uint64 GoBarKegGUID; - uint64 GoBarKegTrapGUID; - uint64 GoBarDoorGUID; - uint64 GoTombEnterGUID; - uint64 GoTombExitGUID; - uint64 GoLyceumGUID; - uint64 GoSFSGUID; - uint64 GoSFNGUID; - uint64 GoGolemNGUID; - uint64 GoGolemSGUID; - uint64 GoThroneGUID; - uint64 GoChestGUID; - - uint32 BarAleCount; - uint32 GhostKillCount; - uint64 TombBossGUIDs[7]; - uint64 TombEventStarterGUID; - uint32 TombTimer; - uint32 TombEventCounter; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - EmperorGUID = 0; - PhalanxGUID = 0; - MagmusGUID = 0; - - GoArena1GUID = 0; - GoArena2GUID = 0; - GoArena3GUID = 0; - GoArena4GUID = 0; - GoShadowLockGUID = 0; - GoShadowMechGUID = 0; - GoShadowGiantGUID = 0; - GoShadowDummyGUID = 0; - GoBarKegGUID = 0; - GoBarKegTrapGUID = 0; - GoBarDoorGUID = 0; - GoTombEnterGUID = 0; - GoTombExitGUID = 0; - GoLyceumGUID = 0; - GoSFSGUID = 0; - GoSFNGUID = 0; - GoGolemNGUID = 0; - GoGolemSGUID = 0; - GoThroneGUID = 0; - GoChestGUID = 0; - - BarAleCount = 0; - GhostKillCount = 0; - TombEventStarterGUID = 0; - TombTimer = TIMER_TOMBOFTHESEVEN; - TombEventCounter = 0; - - for (uint8 i = 0; i < 7; ++i) - TombBossGUIDs[i] = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_EMPEROR: EmperorGUID = pCreature->GetGUID(); break; - case NPC_PHALANX: PhalanxGUID = pCreature->GetGUID(); break; - case NPC_DOOMREL: TombBossGUIDs[0] = pCreature->GetGUID(); break; - case NPC_DOPEREL: TombBossGUIDs[1] = pCreature->GetGUID(); break; - case NPC_HATEREL: TombBossGUIDs[2] = pCreature->GetGUID(); break; - case NPC_VILEREL: TombBossGUIDs[3] = pCreature->GetGUID(); break; - case NPC_SEETHREL: TombBossGUIDs[4] = pCreature->GetGUID(); break; - case NPC_GLOOMREL: TombBossGUIDs[5] = pCreature->GetGUID(); break; - case NPC_ANGERREL: TombBossGUIDs[6] = pCreature->GetGUID(); break; - case NPC_MAGMUS: - MagmusGUID = pCreature->GetGUID(); - if (!pCreature->isAlive()) - HandleGameObject(GetData64(DATA_THRONE_DOOR), true); // if Magmus is dead open door to last boss - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_ARENA1: GoArena1GUID = pGo->GetGUID(); break; - case GO_ARENA2: GoArena2GUID = pGo->GetGUID(); break; - case GO_ARENA3: GoArena3GUID = pGo->GetGUID(); break; - case GO_ARENA4: GoArena4GUID = pGo->GetGUID(); break; - case GO_SHADOW_LOCK: GoShadowLockGUID = pGo->GetGUID(); break; - case GO_SHADOW_MECHANISM: GoShadowMechGUID = pGo->GetGUID(); break; - case GO_SHADOW_GIANT_DOOR: GoShadowGiantGUID = pGo->GetGUID(); break; - case GO_SHADOW_DUMMY: GoShadowDummyGUID = pGo->GetGUID(); break; - case GO_BAR_KEG_SHOT: GoBarKegGUID = pGo->GetGUID(); break; - case GO_BAR_KEG_TRAP: GoBarKegTrapGUID = pGo->GetGUID(); break; - case GO_BAR_DOOR: GoBarDoorGUID = pGo->GetGUID(); break; - case GO_TOMB_ENTER: GoTombEnterGUID = pGo->GetGUID(); break; - case GO_TOMB_EXIT: - GoTombExitGUID = pGo->GetGUID(); - if (GhostKillCount >= 7) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - case GO_LYCEUM: GoLyceumGUID = pGo->GetGUID(); break; - case GO_SF_S: GoSFSGUID = pGo->GetGUID(); break; - case GO_SF_N: GoSFNGUID = pGo->GetGUID(); break; - case GO_GOLEM_ROOM_N: GoGolemNGUID = pGo->GetGUID(); break; - case GO_GOLEM_ROOM_S: GoGolemSGUID = pGo->GetGUID(); break; - case GO_THRONE_ROOM: GoThroneGUID = pGo->GetGUID(); break; - case GO_CHEST_SEVEN: GoChestGUID = pGo->GetGUID(); break; - } - } - - void SetData64(uint32 type, uint64 data) - { - debug_log("TSCR: Instance Blackrock Depths: SetData64 update (Type: %u Data %u)", type, data); - - switch(type) - { - case DATA_EVENSTARTER: - TombEventStarterGUID = data; - if (!TombEventStarterGUID) - TombOfSevenReset();//reset - else - TombOfSevenStart();//start - break; - } - } - - void SetData(uint32 type, uint32 data) - { - debug_log("TSCR: Instance Blackrock Depths: SetData update (Type: %u Data %u)", type, data); - - switch(type) - { - case TYPE_RING_OF_LAW: - m_auiEncounter[0] = data; - break; - case TYPE_VAULT: - m_auiEncounter[1] = data; - break; - case TYPE_BAR: - if (data == SPECIAL) - ++BarAleCount; - else - m_auiEncounter[2] = data; - break; - case TYPE_TOMB_OF_SEVEN: - m_auiEncounter[3] = data; - break; - case TYPE_LYCEUM: - m_auiEncounter[4] = data; - break; - case TYPE_IRON_HALL: - m_auiEncounter[5] = data; - break; - case DATA_GHOSTKILL: - GhostKillCount += data; - break; - } - - if (data == DONE || GhostKillCount >= 7) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << GhostKillCount; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_RING_OF_LAW: - return m_auiEncounter[0]; - case TYPE_VAULT: - return m_auiEncounter[1]; - case TYPE_BAR: - if (m_auiEncounter[2] == IN_PROGRESS && BarAleCount == 3) - return SPECIAL; - else - return m_auiEncounter[2]; - case TYPE_TOMB_OF_SEVEN: - return m_auiEncounter[3]; - case TYPE_LYCEUM: - return m_auiEncounter[4]; - case TYPE_IRON_HALL: - return m_auiEncounter[5]; - case DATA_GHOSTKILL: - return GhostKillCount; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_EMPEROR: - return EmperorGUID; - case DATA_PHALANX: - return PhalanxGUID; - case DATA_ARENA1: - return GoArena1GUID; - case DATA_ARENA2: - return GoArena2GUID; - case DATA_ARENA3: - return GoArena3GUID; - case DATA_ARENA4: - return GoArena4GUID; - case DATA_GO_BAR_KEG: - return GoBarKegGUID; - case DATA_GO_BAR_KEG_TRAP: - return GoBarKegTrapGUID; - case DATA_GO_BAR_DOOR: - return GoBarDoorGUID; - case DATA_EVENSTARTER: - return TombEventStarterGUID; - case DATA_SF_BRAZIER_N: - return GoSFNGUID; - case DATA_SF_BRAZIER_S: - return GoSFSGUID; - case DATA_THRONE_DOOR: - return GoThroneGUID; - case DATA_GOLEM_DOOR_N: - return GoGolemNGUID; - case DATA_GOLEM_DOOR_S: - return GoGolemSGUID; - } - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> GhostKillCount; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - if (GhostKillCount > 0 && GhostKillCount < 7) - GhostKillCount = 0;//reset tomb of seven event - if (GhostKillCount >= 7) - GhostKillCount = 7; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void TombOfSevenEvent() - { - if (GhostKillCount < 7 && TombBossGUIDs[TombEventCounter]) - { - if (Creature* boss = instance->GetCreature(TombBossGUIDs[TombEventCounter])) - { - boss->setFaction(FACTION_HOSTILE); - boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - if (Unit *pTarget = boss->SelectNearestTarget(500)) - boss->AI()->AttackStart(pTarget); - } - } - } - - void TombOfSevenReset() - { - HandleGameObject(GoTombExitGUID,false);//event reseted, close exit door - HandleGameObject(GoTombEnterGUID,true);//event reseted, open entrance door - for (uint8 i = 0; i < 7; ++i) - { - if (Creature* boss = instance->GetCreature(TombBossGUIDs[i])) - { - if (!boss->isAlive()) - {//do not call EnterEvadeMode(), it will create infinit loops - boss->Respawn(); - boss->RemoveAllAuras(); - boss->DeleteThreatList(); - boss->CombatStop(true); - boss->LoadCreaturesAddon(); - boss->GetMotionMaster()->MoveTargetedHome(); - boss->SetLootRecipient(NULL); - } - boss->setFaction(FACTION_FRIEND); - } - } - GhostKillCount = 0; - TombEventStarterGUID = 0; - TombEventCounter = 0; - TombTimer = TIMER_TOMBOFTHESEVEN; - SetData(TYPE_TOMB_OF_SEVEN, NOT_STARTED); - } - - void TombOfSevenStart() - { - HandleGameObject(GoTombExitGUID,false);//event started, close exit door - HandleGameObject(GoTombEnterGUID,false);//event started, close entrance door - SetData(TYPE_TOMB_OF_SEVEN, IN_PROGRESS); - } - - void TombOfSevenEnd() - { - DoRespawnGameObject(GoChestGUID,DAY); - HandleGameObject(GoTombExitGUID,true);//event done, open exit door - HandleGameObject(GoTombEnterGUID,true);//event done, open entrance door - TombEventStarterGUID = 0; - SetData(TYPE_TOMB_OF_SEVEN, DONE); - } - void Update(uint32 diff) - { - if (TombEventStarterGUID && GhostKillCount < 7) - { - if (TombTimer <= diff) - { - TombTimer = TIMER_TOMBOFTHESEVEN; - ++TombEventCounter; - TombOfSevenEvent(); - // Check Killed bosses - for (uint8 i = 0; i < 7; ++i) - { - if (Creature* boss = instance->GetCreature(TombBossGUIDs[i])) - { - if (!boss->isAlive()) - { - GhostKillCount = i+1; - } - } - } - } else TombTimer -= diff; - } - if (GhostKillCount >= 7 && TombEventStarterGUID) - TombOfSevenEnd(); - } -}; - -InstanceData* GetInstanceData_instance_blackrock_depths(Map* pMap) -{ - return new instance_blackrock_depths(pMap); -} - - void AddSC_instance_blackrock_depths() - { - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blackrock_depths"; - newscript->GetInstanceData = &GetInstanceData_instance_blackrock_depths; - newscript->RegisterSelf(); - } diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp deleted file mode 100644 index 2ea115e6e0b..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "blackrock_spire.h" - -enum Creatures -{ - NPC_ROOKERY_WHELP = 10161 -}; - -struct npc_rookey_whelpAI : public ScriptedAI -{ - npc_rookey_whelpAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void JustDied(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(WHELP_DEATH_COUNT, pInstance->GetData(WHELP_DEATH_COUNT)+1); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_rookey_whelp(Creature* pCreature) -{ - return new npc_rookey_whelpAI(pCreature); -} - -bool GOHello_rookey_egg(Player *pPlayer, GameObject * /*pGO*/) -{ - Position pos; - pPlayer->GetPosition(&pos); - pPlayer->SummonCreature(NPC_ROOKERY_WHELP, pos, TEMPSUMMON_TIMED_DESPAWN, 15*IN_MILISECONDS); - //destroy gobject need to be implemented - - return true; -}; - -void AddSC_blackrock_spire() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_rookey_whelp"; - newscript->GetAI = &GetAI_rookey_whelp; - newscript->RegisterSelf(); - newscript = new Script; - - newscript->Name = "go_rookey_egg"; - newscript->pGOHello = &GOHello_rookey_egg; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h deleted file mode 100644 index 56b6e0cbe23..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/blackrock_spire.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_BRS_H -#define DEF_BRS_H - -enum Data -{ - EVENT_LEEEROY, - WHELP_DEATH_COUNT -}; - -#endif diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp deleted file mode 100644 index b53ddaf23ef..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_drakkisath.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Drakkisath -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FIRENOVA 23462 -#define SPELL_CLEAVE 20691 -#define SPELL_CONFLIGURATION 16805 -#define SPELL_THUNDERCLAP 15548 //Not sure if right ID. 23931 would be a harder possibility. - -struct boss_drakkisathAI : public ScriptedAI -{ - boss_drakkisathAI(Creature *c) : ScriptedAI(c) {} - - uint32 FireNova_Timer; - uint32 Cleave_Timer; - uint32 Confliguration_Timer; - uint32 Thunderclap_Timer; - - void Reset() - { - FireNova_Timer = 6000; - Cleave_Timer = 8000; - Confliguration_Timer = 15000; - Thunderclap_Timer = 17000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRENOVA); - FireNova_Timer = 10000; - } else FireNova_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 8000; - } else Cleave_Timer -= diff; - - //Confliguration_Timer - if (Confliguration_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CONFLIGURATION); - Confliguration_Timer = 18000; - } else Confliguration_Timer -= diff; - - //Thunderclap_Timer - if (Thunderclap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - Thunderclap_Timer = 20000; - } else Thunderclap_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_drakkisath(Creature* pCreature) -{ - return new boss_drakkisathAI (pCreature); -} - -void AddSC_boss_drakkisath() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_drakkisath"; - newscript->GetAI = &GetAI_boss_drakkisath; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp deleted file mode 100644 index fcd2ea1a6d0..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_gyth.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gyth -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CORROSIVEACID 20667 -#define SPELL_FREEZE 18763 -#define SPELL_FLAMEBREATH 20712 - -struct boss_gythAI : public ScriptedAI -{ - boss_gythAI(Creature *c) : ScriptedAI(c) {} - - uint32 Aggro_Timer; - uint32 Dragons_Timer; - uint32 Orc_Timer; - uint32 CorrosiveAcid_Timer; - uint32 Freeze_Timer; - uint32 Flamebreath_Timer; - uint32 Line1Count; - uint32 Line2Count; - - bool Event; - bool SummonedDragons; - bool SummonedOrcs; - bool SummonedRend; - bool bAggro; - bool RootSelf; - - void Reset() - { - Dragons_Timer = 3000; - Orc_Timer = 60000; - Aggro_Timer = 60000; - CorrosiveAcid_Timer = 8000; - Freeze_Timer = 11000; - Flamebreath_Timer = 4000; - Event = false; - SummonedDragons = false; - SummonedOrcs= false; - SummonedRend = false; - bAggro = false; - RootSelf = false; - - // how many times should the two lines of summoned creatures be spawned - // min 2 x 2, max 7 lines of attack in total - Line1Count = rand() % 4 + 2; - if (Line1Count < 5) - Line2Count = rand() % (5 - Line1Count) + 2; - else - Line2Count = 2; - - //Invisible for event start - me->SetDisplayId(11686); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonCreatureWithRandomTarget(uint32 creatureId) - { - Unit* Summoned = me->SummonCreature(creatureId, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240000); - if (Summoned) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Summoned->AddThreat(pTarget, 1.0f); - } - } - - void UpdateAI(const uint32 diff) - { - //char buf[200]; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!RootSelf) - { - //me->m_canMove = true; - DoCast(me, 33356); - RootSelf = true; - } - - if (!bAggro && Line1Count == 0 && Line2Count == 0) - { - if (Aggro_Timer <= diff) - { - bAggro = true; - // Visible now! - me->SetDisplayId(9723); - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } else Aggro_Timer -= diff; - } - - // Summon Dragon pack. 2 Dragons and 3 Whelps - if (!bAggro && !SummonedRend && Line1Count > 0) - { - if (Dragons_Timer <= diff) - { - SummonCreatureWithRandomTarget(10372); - SummonCreatureWithRandomTarget(10372); - SummonCreatureWithRandomTarget(10442); - SummonCreatureWithRandomTarget(10442); - SummonCreatureWithRandomTarget(10442); - Line1Count = Line1Count - 1; - Dragons_Timer = 60000; - } else Dragons_Timer -= diff; - } - - //Summon Orc pack. 1 Orc Handler 1 Elite Dragonkin and 3 Whelps - if (!bAggro && !SummonedRend && Line1Count == 0 && Line2Count > 0) - { - if (Orc_Timer <= diff) - { - SummonCreatureWithRandomTarget(10447); - SummonCreatureWithRandomTarget(10317); - SummonCreatureWithRandomTarget(10442); - SummonCreatureWithRandomTarget(10442); - SummonCreatureWithRandomTarget(10442); - Line2Count = Line2Count - 1; - Orc_Timer = 60000; - } else Orc_Timer -= diff; - } - - // we take part in the fight - if (bAggro) - { - // CorrosiveAcid_Timer - if (CorrosiveAcid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVEACID); - CorrosiveAcid_Timer = 7000; - } else CorrosiveAcid_Timer -= diff; - - // Freeze_Timer - if (Freeze_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FREEZE); - Freeze_Timer = 16000; - } else Freeze_Timer -= diff; - - // Flamebreath_Timer - if (Flamebreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBREATH); - Flamebreath_Timer = 10500; - } else Flamebreath_Timer -= diff; - - //Summon Rend - if (!SummonedRend && me->GetHealth()*100 / me->GetMaxHealth() < 11 - && me->GetHealth() > 0) - { - //summon Rend and Change model to normal Gyth - //Inturrupt any spell casting - me->InterruptNonMeleeSpells(false); - //Gyth model - me->SetDisplayId(9806); - me->SummonCreature(10429, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000); - SummonedRend = true; - } - - DoMeleeAttackIfReady(); - } // end if Aggro - } -}; - -CreatureAI* GetAI_boss_gyth(Creature* pCreature) -{ - return new boss_gythAI (pCreature); -} - -void AddSC_boss_gyth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gyth"; - newscript->GetAI = &GetAI_boss_gyth; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp deleted file mode 100644 index 9e78667717a..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_halycon.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Halycon -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CROWDPUMMEL 10887 -#define SPELL_MIGHTYBLOW 14099 - -#define ADD_1X -169.839203 -#define ADD_1Y -324.961395 -#define ADD_1Z 64.401443 -#define ADD_1O 3.124724 - -struct boss_halyconAI : public ScriptedAI -{ - boss_halyconAI(Creature *c) : ScriptedAI(c) {} - - uint32 CrowdPummel_Timer; - uint32 MightyBlow_Timer; - bool Summoned; - - void Reset() - { - CrowdPummel_Timer = 8000; - MightyBlow_Timer = 14000; - Summoned = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //CrowdPummel_Timer - if (CrowdPummel_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CROWDPUMMEL); - CrowdPummel_Timer = 14000; - } else CrowdPummel_Timer -= diff; - - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTYBLOW); - MightyBlow_Timer = 10000; - } else MightyBlow_Timer -= diff; - - //Summon Gizrul - if (!Summoned && me->GetHealth()*100 / me->GetMaxHealth() < 25) - { - me->SummonCreature(10268,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000); - Summoned = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_halycon(Creature* pCreature) -{ - return new boss_halyconAI (pCreature); -} - -void AddSC_boss_halycon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_halycon"; - newscript->GetAI = &GetAI_boss_halycon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp deleted file mode 100644 index 65f1e8081a0..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_highlord_omokk.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Highlord_Omokk -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_WARSTOMP 24375 -#define SPELL_CLEAVE 15579 -#define SPELL_STRIKE 18368 -#define SPELL_REND 18106 -#define SPELL_SUNDERARMOR 24317 -#define SPELL_KNOCKAWAY 20686 -#define SPELL_SLOW 22356 - -struct boss_highlordomokkAI : public ScriptedAI -{ - boss_highlordomokkAI(Creature *c) : ScriptedAI(c) {} - - uint32 WarStomp_Timer; - uint32 Cleave_Timer; - uint32 Strike_Timer; - uint32 Rend_Timer; - uint32 SunderArmor_Timer; - uint32 KnockAway_Timer; - uint32 Slow_Timer; - - void Reset() - { - WarStomp_Timer = 15000; - Cleave_Timer = 6000; - Strike_Timer = 10000; - Rend_Timer = 14000; - SunderArmor_Timer = 2000; - KnockAway_Timer = 18000; - Slow_Timer = 24000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //WarStomp_Timer - if (WarStomp_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WARSTOMP); - WarStomp_Timer = 14000; - } else WarStomp_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 8000; - } else Cleave_Timer -= diff; - - //Strike_Timer - if (Strike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STRIKE); - Strike_Timer = 10000; - } else Strike_Timer -= diff; - - //Rend_Timer - if (Rend_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REND); - Rend_Timer = 18000; - } else Rend_Timer -= diff; - - //SunderArmor_Timer - if (SunderArmor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDERARMOR); - SunderArmor_Timer = 25000; - } else SunderArmor_Timer -= diff; - - //KnockAway_Timer - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - KnockAway_Timer = 12000; - } else KnockAway_Timer -= diff; - - //Slow_Timer - if (Slow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLOW); - Slow_Timer = 18000; - } else Slow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_highlordomokk(Creature* pCreature) -{ - return new boss_highlordomokkAI (pCreature); -} - -void AddSC_boss_highlordomokk() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_highlord_omokk"; - newscript->GetAI = &GetAI_boss_highlordomokk; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp deleted file mode 100644 index 60dda5a5fab..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_mother_smolderweb.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mother_Smolderweb -SD%Complete: 100 -SDComment: Uncertain how often mother's milk is casted -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CRYSTALIZE 16104 -#define SPELL_MOTHERSMILK 16468 -#define SPELL_SUMMON_SPIRE_SPIDERLING 16103 - -struct boss_mothersmolderwebAI : public ScriptedAI -{ - boss_mothersmolderwebAI(Creature *c) : ScriptedAI(c) {} - - uint32 Crystalize_Timer; - uint32 MothersMilk_Timer; - - void Reset() - { - Crystalize_Timer = 20000; - MothersMilk_Timer = 10000; - } - - void EnterCombat(Unit * /*who*/) {} - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (me->GetHealth() <= damage) - DoCast(me, SPELL_SUMMON_SPIRE_SPIDERLING, true); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Crystalize_Timer - if (Crystalize_Timer <= diff) - { - DoCast(me, SPELL_CRYSTALIZE); - Crystalize_Timer = 15000; - } else Crystalize_Timer -= diff; - - //MothersMilk_Timer - if (MothersMilk_Timer <= diff) - { - DoCast(me, SPELL_MOTHERSMILK); - MothersMilk_Timer = urand(5000,12500); - } else MothersMilk_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_mothersmolderweb(Creature* pCreature) -{ - return new boss_mothersmolderwebAI (pCreature); -} - -void AddSC_boss_mothersmolderweb() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_mother_smolderweb"; - newscript->GetAI = &GetAI_boss_mothersmolderweb; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp deleted file mode 100644 index 8846442705b..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Overlord_Wyrmthalak -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_BLASTWAVE 11130 -#define SPELL_SHOUT 23511 -#define SPELL_CLEAVE 20691 -#define SPELL_KNOCKAWAY 20686 - -#define ADD_1X -39.355381 -#define ADD_1Y -513.456482 -#define ADD_1Z 88.472046 -#define ADD_1O 4.679872 - -#define ADD_2X -49.875881 -#define ADD_2Y -511.896942 -#define ADD_2Z 88.195160 -#define ADD_2O 4.613114 - -struct boss_overlordwyrmthalakAI : public ScriptedAI -{ - boss_overlordwyrmthalakAI(Creature *c) : ScriptedAI(c) {} - - uint32 BlastWave_Timer; - uint32 Shout_Timer; - uint32 Cleave_Timer; - uint32 Knockaway_Timer; - bool Summoned; - - void Reset() - { - BlastWave_Timer = 20000; - Shout_Timer = 2000; - Cleave_Timer = 6000; - Knockaway_Timer = 12000; - Summoned = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //BlastWave_Timer - if (BlastWave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLASTWAVE); - BlastWave_Timer = 20000; - } else BlastWave_Timer -= diff; - - //Shout_Timer - if (Shout_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHOUT); - Shout_Timer = 10000; - } else Shout_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //Knockaway_Timer - if (Knockaway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - Knockaway_Timer = 14000; - } else Knockaway_Timer -= diff; - - //Summon two Beserks - if (!Summoned && me->GetHealth()*100 / me->GetMaxHealth() < 51) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0, 100, true); - - if (Creature *SummonedCreature = me->SummonCreature(9216,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000)) - SummonedCreature->AI()->AttackStart(pTarget); - if (Creature *SummonedCreature = me->SummonCreature(9268,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,300000)) - SummonedCreature->AI()->AttackStart(pTarget); - Summoned = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_overlordwyrmthalak(Creature* pCreature) -{ - return new boss_overlordwyrmthalakAI (pCreature); -} - -void AddSC_boss_overlordwyrmthalak() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_overlord_wyrmthalak"; - newscript->GetAI = &GetAI_boss_overlordwyrmthalak; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp deleted file mode 100644 index 6cbd6955665..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Pyroguard_Emberseer -SD%Complete: 100 -SDComment: Event to activate Emberseer NYI -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FIRENOVA 23462 -#define SPELL_FLAMEBUFFET 23341 -#define SPELL_PYROBLAST 17274 - -struct boss_pyroguard_emberseerAI : public ScriptedAI -{ - boss_pyroguard_emberseerAI(Creature *c) : ScriptedAI(c) {} - - uint32 FireNova_Timer; - uint32 FlameBuffet_Timer; - uint32 PyroBlast_Timer; - - void Reset() - { - FireNova_Timer = 6000; - FlameBuffet_Timer = 3000; - PyroBlast_Timer = 14000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRENOVA); - FireNova_Timer = 6000; - } else FireNova_Timer -= diff; - - //FlameBuffet_Timer - if (FlameBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBUFFET); - FlameBuffet_Timer = 14000; - } else FlameBuffet_Timer -= diff; - - //PyroBlast_Timer - if (PyroBlast_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_PYROBLAST); - PyroBlast_Timer = 15000; - } else PyroBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_pyroguard_emberseer(Creature* pCreature) -{ - return new boss_pyroguard_emberseerAI (pCreature); -} - -void AddSC_boss_pyroguard_emberseer() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_pyroguard_emberseer"; - newscript->GetAI = &GetAI_boss_pyroguard_emberseer; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp deleted file mode 100644 index 9058b35cd5c..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_quartermaster_zigris.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Quartmaster_Zigris -SD%Complete: 100 -SDComment: Needs revision -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHOOT 16496 -#define SPELL_STUNBOMB 16497 -#define SPELL_HEALING_POTION 15504 -#define SPELL_HOOKEDNET 15609 - -struct boss_quatermasterzigrisAI : public ScriptedAI -{ - boss_quatermasterzigrisAI(Creature *c) : ScriptedAI(c) {} - - uint32 Shoot_Timer; - uint32 StunBomb_Timer; - //uint32 HelingPotion_Timer; - - void Reset() - { - Shoot_Timer = 1000; - StunBomb_Timer = 16000; - //HelingPotion_Timer = 25000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Shoot_Timer - if (Shoot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHOOT); - Shoot_Timer = 500; - } else Shoot_Timer -= diff; - - //StunBomb_Timer - if (StunBomb_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STUNBOMB); - StunBomb_Timer = 14000; - } else StunBomb_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_quatermasterzigris(Creature* pCreature) -{ - return new boss_quatermasterzigrisAI (pCreature); -} - -void AddSC_boss_quatermasterzigris() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "quartermaster_zigris"; - newscript->GetAI = &GetAI_boss_quatermasterzigris; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp deleted file mode 100644 index 56de5dbb385..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_rend_blackhand.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Rend_Blackhand -SD%Complete: 100 -SDComment: Intro event NYI -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_WHIRLWIND 26038 -#define SPELL_CLEAVE 20691 -#define SPELL_THUNDERCLAP 23931 //Not sure if he cast this spell - -struct boss_rend_blackhandAI : public ScriptedAI -{ - boss_rend_blackhandAI(Creature *c) : ScriptedAI(c) {} - - uint32 WhirlWind_Timer; - uint32 Cleave_Timer; - uint32 Thunderclap_Timer; - - void Reset() - { - WhirlWind_Timer = 20000; - Cleave_Timer = 5000; - Thunderclap_Timer = 9000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //WhirlWind_Timer - if (WhirlWind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - WhirlWind_Timer = 18000; - } else WhirlWind_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 10000; - } else Cleave_Timer -= diff; - - //Thunderclap_Timer - if (Thunderclap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP); - Thunderclap_Timer = 16000; - } else Thunderclap_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_rend_blackhand(Creature* pCreature) -{ - return new boss_rend_blackhandAI (pCreature); -} - -void AddSC_boss_rend_blackhand() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_rend_blackhand"; - newscript->GetAI = &GetAI_boss_rend_blackhand; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp deleted file mode 100644 index 73afc3b5afe..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Shadow_Hunter_Voshgajin -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CURSEOFBLOOD 24673 -#define SPELL_HEX 16708 -#define SPELL_CLEAVE 20691 - -struct boss_shadowvoshAI : public ScriptedAI -{ - boss_shadowvoshAI(Creature *c) : ScriptedAI(c) {} - - uint32 CurseOfBlood_Timer; - uint32 Hex_Timer; - uint32 Cleave_Timer; - - void Reset() - { - CurseOfBlood_Timer = 2000; - Hex_Timer = 8000; - Cleave_Timer = 14000; - - //DoCast(me, SPELL_ICEARMOR, true); - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //CurseOfBlood_Timer - if (CurseOfBlood_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); - CurseOfBlood_Timer = 45000; - } else CurseOfBlood_Timer -= diff; - - //Hex_Timer - if (Hex_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_HEX); - Hex_Timer = 15000; - } else Hex_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_shadowvosh(Creature* pCreature) -{ - return new boss_shadowvoshAI (pCreature); -} - -void AddSC_boss_shadowvosh() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shadow_hunter_voshgajin"; - newscript->GetAI = &GetAI_boss_shadowvosh; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp deleted file mode 100644 index 499f9cf4ce5..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_the_beast.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_The_Best -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FLAMEBREAK 16785 -#define SPELL_IMMOLATE 20294 -#define SPELL_TERRIFYINGROAR 14100 - -struct boss_thebeastAI : public ScriptedAI -{ - boss_thebeastAI(Creature *c) : ScriptedAI(c) {} - - uint32 Flamebreak_Timer; - uint32 Immolate_Timer; - uint32 TerrifyingRoar_Timer; - - void Reset() - { - Flamebreak_Timer = 12000; - Immolate_Timer = 3000; - TerrifyingRoar_Timer = 23000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Flamebreak_Timer - if (Flamebreak_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBREAK); - Flamebreak_Timer = 10000; - } else Flamebreak_Timer -= diff; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_IMMOLATE); - Immolate_Timer = 8000; - } else Immolate_Timer -= diff; - - //TerrifyingRoar_Timer - if (TerrifyingRoar_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TERRIFYINGROAR); - TerrifyingRoar_Timer = 20000; - } else TerrifyingRoar_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_thebeast(Creature* pCreature) -{ - return new boss_thebeastAI (pCreature); -} - -void AddSC_boss_thebeast() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_beast"; - newscript->GetAI = &GetAI_boss_thebeast; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp deleted file mode 100644 index 50b47c94fc5..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/boss_warmaster_voone.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warmaster_Voone -SD%Complete: 100 -SDComment: -SDCategory: Blackrock Spire -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SNAPKICK 15618 -#define SPELL_CLEAVE 15579 -#define SPELL_UPPERCUT 10966 -#define SPELL_MORTALSTRIKE 16856 -#define SPELL_PUMMEL 15615 -#define SPELL_THROWAXE 16075 - -struct boss_warmastervooneAI : public ScriptedAI -{ - boss_warmastervooneAI(Creature *c) : ScriptedAI(c) {} - - uint32 Snapkick_Timer; - uint32 Cleave_Timer; - uint32 Uppercut_Timer; - uint32 MortalStrike_Timer; - uint32 Pummel_Timer; - uint32 ThrowAxe_Timer; - - void Reset() - { - Snapkick_Timer = 8000; - Cleave_Timer = 14000; - Uppercut_Timer = 20000; - MortalStrike_Timer = 12000; - Pummel_Timer = 32000; - ThrowAxe_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Snapkick_Timer - if (Snapkick_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SNAPKICK); - Snapkick_Timer = 6000; - } else Snapkick_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 12000; - } else Cleave_Timer -= diff; - - //Uppercut_Timer - if (Uppercut_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_UPPERCUT); - Uppercut_Timer = 14000; - } else Uppercut_Timer -= diff; - - //MortalStrike_Timer - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = 10000; - } else MortalStrike_Timer -= diff; - - //Pummel_Timer - if (Pummel_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PUMMEL); - Pummel_Timer = 16000; - } else Pummel_Timer -= diff; - - //ThrowAxe_Timer - if (ThrowAxe_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THROWAXE); - ThrowAxe_Timer = 8000; - } else ThrowAxe_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_warmastervoone(Creature* pCreature) -{ - return new boss_warmastervooneAI (pCreature); -} - -void AddSC_boss_warmastervoone() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_warmaster_voone"; - newscript->GetAI = &GetAI_boss_warmastervoone; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp deleted file mode 100644 index f2e2b39fe87..00000000000 --- a/src/server/scripts/EasternKingdoms/blackrock_spire/instance_blackrock_spire.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "blackrock_spire.h" - -enum Achievements -{ - ACHIEV_LEROY_JENKINS = 2188 -}; - -struct instance_blackrock_spire : public ScriptedInstance -{ - instance_blackrock_spire(Map* pMap) : ScriptedInstance(pMap) {} - - uint32 uiLeeroyTimer; - uint32 uiWhelpCount; - uint32 uiLeroyData; - - bool bLeeeeeeeeroy; - - void Initialize() - { - uiLeeroyTimer = 15*IN_MILISECONDS; - uiWhelpCount = 0; - bLeeeeeeeeroy = true; - uiLeroyData = 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case EVENT_LEEEROY: - if (data == DONE) - DoCompleteAchievement(ACHIEV_LEROY_JENKINS); - uiLeroyData = data; - break; - case WHELP_DEATH_COUNT: - if (data == 1) - { - SetData(EVENT_LEEEROY, IN_PROGRESS); - //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Started"); - } - uiWhelpCount = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case EVENT_LEEEROY: return uiLeroyData; - case WHELP_DEATH_COUNT: return uiWhelpCount; - } - return 0; - } - - void Update(uint32 diff) - { - if (GetData(EVENT_LEEEROY) != FAIL && GetData(EVENT_LEEEROY) == IN_PROGRESS) - { - if (uiLeeroyTimer <= diff) - { - SetData(EVENT_LEEEROY, FAIL); - bLeeeeeeeeroy = false; - //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Failed"); - } else uiLeeroyTimer -= diff; - if (uiWhelpCount >= 50 && bLeeeeeeeeroy) - { - SetData(EVENT_LEEEROY, DONE); - //DoSendNotifyToInstance("Leeeeeeeeeeeeeroy! Success"); - } - } - } -}; - -InstanceData* GetInstanceData_instance_blackrock_spire(Map* pMap) -{ - return new instance_blackrock_spire(pMap); -} - -void AddSC_instance_blackrock_spire() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blackrock_spire"; - newscript->GetInstanceData = &GetInstanceData_instance_blackrock_spire; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp deleted file mode 100644 index 856e1236176..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Broodlord_Lashlayer -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1469000 -#define SAY_LEASH -1469001 - -#define SPELL_CLEAVE 26350 -#define SPELL_BLASTWAVE 23331 -#define SPELL_MORTALSTRIKE 24573 -#define SPELL_KNOCKBACK 25778 - -struct boss_broodlordAI : public ScriptedAI -{ - boss_broodlordAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cleave_Timer; - uint32 BlastWave_Timer; - uint32 MortalStrike_Timer; - uint32 KnockBack_Timer; - - void Reset() - { - Cleave_Timer = 8000; //These times are probably wrong - BlastWave_Timer = 12000; - MortalStrike_Timer = 20000; - KnockBack_Timer = 30000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - // BlastWave - if (BlastWave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLASTWAVE); - BlastWave_Timer = urand(8000,16000); - } else BlastWave_Timer -= diff; - - //MortalStrike_Timer - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = urand(25000,35000); - } else MortalStrike_Timer -= diff; - - if (KnockBack_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKBACK); - //Drop 50% aggro - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-50); - - KnockBack_Timer = urand(15000,30000); - } else KnockBack_Timer -= diff; - - if (EnterEvadeIfOutOfCombatArea(diff)) - DoScriptText(SAY_LEASH, me); - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_broodlord(Creature* pCreature) -{ - return new boss_broodlordAI (pCreature); -} - -void AddSC_boss_broodlord() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_broodlord"; - newscript->GetAI = &GetAI_boss_broodlord; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp deleted file mode 100644 index 08bebe95384..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_chromaggus.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Chromaggus -SD%Complete: 95 -SDComment: Chromatic Mutation disabled due to lack of core support -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -enum Emotes -{ - EMOTE_FRENZY = -1469002, - EMOTE_SHIMMER = -1469003 -}; - -enum Spells -{ - //These spells are actually called elemental shield - //What they do is decrease all damage by 75% then they increase - //One school of damage by 1100% - SPELL_FIRE_VULNERABILITY = 22277, - SPELL_FROST_VULNERABILITY = 22278, - SPELL_SHADOW_VULNERABILITY = 22279, - SPELL_NATURE_VULNERABILITY = 22280, - SPELL_ARCANE_VULNERABILITY = 22281, - //Other spells - SPELL_INCINERATE = 23308, //Incinerate 23308,23309 - SPELL_TIMELAPSE = 23310, //Time lapse 23310, 23311(old threat mod that was removed in 2.01) - SPELL_CORROSIVEACID = 23313, //Corrosive Acid 23313, 23314 - SPELL_IGNITEFLESH = 23315, //Ignite Flesh 23315,23316 - SPELL_FROSTBURN = 23187, //Frost burn 23187, 23189 - //Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them - //Since Scripted spells arn't coded I'll just write a function that does the same thing - SPELL_BROODAF_BLUE = 23153, //Blue affliction 23153 - SPELL_BROODAF_BLACK = 23154, //Black affliction 23154 - SPELL_BROODAF_RED = 23155, //Red affliction 23155 (23168 on death) - SPELL_BROODAF_BRONZE = 23170, //Bronze Affliction 23170 - SPELL_BROODAF_GREEN = 23169, //Brood Affliction Green 23169 - SPELL_CHROMATIC_MUT_1 = 23174, //Spell cast on player if they get all 5 debuffs - SPELL_FRENZY = 28371, //The frenzy spell may be wrong - SPELL_ENRAGE = 28747 -}; - -struct boss_chromaggusAI : public ScriptedAI -{ - boss_chromaggusAI(Creature *c) : ScriptedAI(c) - { - //Select the 2 breaths that we are going to use until despawned - //5 possiblities for the first breath, 4 for the second, 20 total possiblites - //This way we don't end up casting 2 of the same breath - //TL TL would be stupid - switch (urand(0,19)) - { - //B1 - Incin - case 0: - Breath1_Spell = SPELL_INCINERATE; - Breath2_Spell = SPELL_TIMELAPSE; - break; - case 1: - Breath1_Spell = SPELL_INCINERATE; - Breath2_Spell = SPELL_CORROSIVEACID; - break; - case 2: - Breath1_Spell = SPELL_INCINERATE; - Breath2_Spell = SPELL_IGNITEFLESH; - break; - case 3: - Breath1_Spell = SPELL_INCINERATE; - Breath2_Spell = SPELL_FROSTBURN; - break; - - //B1 - TL - case 4: - Breath1_Spell = SPELL_TIMELAPSE; - Breath2_Spell = SPELL_INCINERATE; - break; - case 5: - Breath1_Spell = SPELL_TIMELAPSE; - Breath2_Spell = SPELL_CORROSIVEACID; - break; - case 6: - Breath1_Spell = SPELL_TIMELAPSE; - Breath2_Spell = SPELL_IGNITEFLESH; - break; - case 7: - Breath1_Spell = SPELL_TIMELAPSE; - Breath2_Spell = SPELL_FROSTBURN; - break; - - //B1 - Acid - case 8: - Breath1_Spell = SPELL_CORROSIVEACID; - Breath2_Spell = SPELL_INCINERATE; - break; - case 9: - Breath1_Spell = SPELL_CORROSIVEACID; - Breath2_Spell = SPELL_TIMELAPSE; - break; - case 10: - Breath1_Spell = SPELL_CORROSIVEACID; - Breath2_Spell = SPELL_IGNITEFLESH; - break; - case 11: - Breath1_Spell = SPELL_CORROSIVEACID; - Breath2_Spell = SPELL_FROSTBURN; - break; - - //B1 - Ignite - case 12: - Breath1_Spell = SPELL_IGNITEFLESH; - Breath2_Spell = SPELL_INCINERATE; - break; - case 13: - Breath1_Spell = SPELL_IGNITEFLESH; - Breath2_Spell = SPELL_CORROSIVEACID; - break; - case 14: - Breath1_Spell = SPELL_IGNITEFLESH; - Breath2_Spell = SPELL_TIMELAPSE; - break; - case 15: - Breath1_Spell = SPELL_IGNITEFLESH; - Breath2_Spell = SPELL_FROSTBURN; - break; - - //B1 - Frost - case 16: - Breath1_Spell = SPELL_FROSTBURN; - Breath2_Spell = SPELL_INCINERATE; - break; - case 17: - Breath1_Spell = SPELL_FROSTBURN; - Breath2_Spell = SPELL_TIMELAPSE; - break; - case 18: - Breath1_Spell = SPELL_FROSTBURN; - Breath2_Spell = SPELL_CORROSIVEACID; - break; - case 19: - Breath1_Spell = SPELL_FROSTBURN; - Breath2_Spell = SPELL_IGNITEFLESH; - break; - }; - - EnterEvadeMode(); - } - - uint32 Breath1_Spell; - uint32 Breath2_Spell; - uint32 CurrentVurln_Spell; - - uint32 Shimmer_Timer; - uint32 Breath1_Timer; - uint32 Breath2_Timer; - uint32 Affliction_Timer; - uint32 Frenzy_Timer; - bool Enraged; - - void Reset() - { - CurrentVurln_Spell = 0; //We use this to store our last vulnerabilty spell so we can remove it later - - Shimmer_Timer = 0; //Time till we change vurlnerabilites - Breath1_Timer = 30000; //First breath is 30 seconds - Breath2_Timer = 60000; //Second is 1 minute so that we can alternate - Affliction_Timer = 10000; //This is special - 5 seconds means that we cast this on 1 player every 5 sconds - Frenzy_Timer = 15000; - - Enraged = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Shimmer_Timer Timer - if (Shimmer_Timer <= diff) - { - //Remove old vulnerabilty spell - if (CurrentVurln_Spell) - me->RemoveAurasDueToSpell(CurrentVurln_Spell); - - //Cast new random vulnerabilty on self - uint32 spell = RAND(SPELL_FIRE_VULNERABILITY, SPELL_FROST_VULNERABILITY, - SPELL_SHADOW_VULNERABILITY, SPELL_NATURE_VULNERABILITY, SPELL_ARCANE_VULNERABILITY); - - DoCast(me, spell); - CurrentVurln_Spell = spell; - - DoScriptText(EMOTE_SHIMMER, me); - Shimmer_Timer = 45000; - } else Shimmer_Timer -= diff; - - //Breath1_Timer - if (Breath1_Timer <= diff) - { - DoCast(me->getVictim(), Breath1_Spell); - Breath1_Timer = 60000; - } else Breath1_Timer -= diff; - - //Breath2_Timer - if (Breath2_Timer <= diff) - { - DoCast(me->getVictim(), Breath2_Spell); - Breath2_Timer = 60000; - } else Breath2_Timer -= diff; - - //Affliction_Timer - if (Affliction_Timer <= diff) - { - std::list threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) - { - Unit* pUnit; - if ((*i) && (*i)->getSource()) - { - pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit) - { - //Cast affliction - DoCast(pUnit, RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, - SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN), true); - - //Chromatic mutation if target is effected by all afflictions - if (pUnit->HasAura(SPELL_BROODAF_BLUE) - && pUnit->HasAura(SPELL_BROODAF_BLACK) - && pUnit->HasAura(SPELL_BROODAF_RED) - && pUnit->HasAura(SPELL_BROODAF_BRONZE) - && pUnit->HasAura(SPELL_BROODAF_GREEN)) - { - //pTarget->RemoveAllAuras(); - //DoCast(pTarget, SPELL_CHROMATIC_MUT_1); - - //Chromatic mutation is causing issues - //Assuming it is caused by a lack of core support for Charm - //So instead we instant kill our target - - //WORKAROUND - if (pUnit->GetTypeId() == TYPEID_PLAYER) - pUnit->CastSpell(pUnit, 5, false); - } - } - } - } - - Affliction_Timer = 10000; - } else Affliction_Timer -= diff; - - //Frenzy_Timer - if (Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_FRENZY, me); - Frenzy_Timer = urand(10000,15000); - } else Frenzy_Timer -= diff; - - //Enrage if not already enraged and below 20% - if (!Enraged && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_chromaggus(Creature* pCreature) -{ - return new boss_chromaggusAI (pCreature); -} - -void AddSC_boss_chromaggus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_chromaggus"; - newscript->GetAI = &GetAI_boss_chromaggus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp deleted file mode 100644 index 49a999fc458..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_ebonroc.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ebonroc -SD%Complete: 50 -SDComment: Shadow of Ebonroc needs core support -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWFLAME 22539 -#define SPELL_WINGBUFFET 18500 -#define SPELL_SHADOWOFEBONROC 23340 -#define SPELL_HEAL 41386 //Thea Heal spell of his Shadow - -struct boss_ebonrocAI : public ScriptedAI -{ - boss_ebonrocAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 ShadowOfEbonroc_Timer; - uint32 Heal_Timer; - - void Reset() - { - ShadowFlame_Timer = 15000; //These times are probably wrong - WingBuffet_Timer = 30000; - ShadowOfEbonroc_Timer = 45000; - Heal_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Shadowflame Timer - if (ShadowFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWFLAME); - ShadowFlame_Timer = urand(12000,15000); - } else ShadowFlame_Timer -= diff; - - //Wing Buffet Timer - if (WingBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WINGBUFFET); - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; - - //Shadow of Ebonroc Timer - if (ShadowOfEbonroc_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWOFEBONROC); - ShadowOfEbonroc_Timer = urand(25000,350000); - } else ShadowOfEbonroc_Timer -= diff; - - if (me->getVictim()->HasAura(SPELL_SHADOWOFEBONROC)) - { - if (Heal_Timer <= diff) - { - DoCast(me, SPELL_HEAL); - Heal_Timer = urand(1000,3000); - } else Heal_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ebonroc(Creature* pCreature) -{ - return new boss_ebonrocAI (pCreature); -} - -void AddSC_boss_ebonroc() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ebonroc"; - newscript->GetAI = &GetAI_boss_ebonroc; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp deleted file mode 100644 index af62b1103bc..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_firemaw.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Firemaw -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWFLAME 22539 -#define SPELL_WINGBUFFET 23339 -#define SPELL_FLAMEBUFFET 23341 - -struct boss_firemawAI : public ScriptedAI -{ - boss_firemawAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 FlameBuffet_Timer; - - void Reset() - { - ShadowFlame_Timer = 30000; //These times are probably wrong - WingBuffet_Timer = 24000; - FlameBuffet_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWFLAME); - ShadowFlame_Timer = urand(15000,18000); - } else ShadowFlame_Timer -= diff; - - //WingBuffet_Timer - if (WingBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WINGBUFFET); - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-75); - - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; - - //FlameBuffet_Timer - if (FlameBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBUFFET); - FlameBuffet_Timer = 5000; - } else FlameBuffet_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_firemaw(Creature* pCreature) -{ - return new boss_firemawAI (pCreature); -} - -void AddSC_boss_firemaw() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_firemaw"; - newscript->GetAI = &GetAI_boss_firemaw; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp deleted file mode 100644 index b29fe41f2b1..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_flamegor.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Flamegor -SD%Complete: 100 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_FRENZY -1469031 - -#define SPELL_SHADOWFLAME 22539 -#define SPELL_WINGBUFFET 23339 -#define SPELL_FRENZY 23342 //This spell periodically triggers fire nova - -struct boss_flamegorAI : public ScriptedAI -{ - boss_flamegorAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowFlame_Timer; - uint32 WingBuffet_Timer; - uint32 Frenzy_Timer; - - void Reset() - { - ShadowFlame_Timer = 21000; //These times are probably wrong - WingBuffet_Timer = 35000; - Frenzy_Timer = 10000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWFLAME); - ShadowFlame_Timer = 15000 + rand()%7000; - } else ShadowFlame_Timer -= diff; - - //WingBuffet_Timer - if (WingBuffet_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WINGBUFFET); - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-75); - - WingBuffet_Timer = 25000; - } else WingBuffet_Timer -= diff; - - //Frenzy_Timer - if (Frenzy_Timer <= diff) - { - DoScriptText(EMOTE_FRENZY, me); - DoCast(me, SPELL_FRENZY); - Frenzy_Timer = urand(8000, 10000); - } else Frenzy_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_flamegor(Creature* pCreature) -{ - return new boss_flamegorAI (pCreature); -} - -void AddSC_boss_flamegor() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_flamegor"; - newscript->GetAI = &GetAI_boss_flamegor; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp deleted file mode 100644 index 5ef05be519c..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_nefarian.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Nefarian -SD%Complete: 80 -SDComment: Some issues with class calls effecting more than one class -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1469007 -#define SAY_XHEALTH -1469008 -#define SAY_SHADOWFLAME -1469009 -#define SAY_RAISE_SKELETONS -1469010 -#define SAY_SLAY -1469011 -#define SAY_DEATH -1469012 - -#define SAY_MAGE -1469013 -#define SAY_WARRIOR -1469014 -#define SAY_DRUID -1469015 -#define SAY_PRIEST -1469016 -#define SAY_PALADIN -1469017 -#define SAY_SHAMAN -1469018 -#define SAY_WARLOCK -1469019 -#define SAY_HUNTER -1469020 -#define SAY_ROGUE -1469021 - -#define SPELL_SHADOWFLAME_INITIAL 22972 -#define SPELL_SHADOWFLAME 22539 -#define SPELL_BELLOWINGROAR 22686 -#define SPELL_VEILOFSHADOW 7068 -#define SPELL_CLEAVE 20691 -#define SPELL_TAILLASH 23364 -#define SPELL_BONECONTRUST 23363 //23362, 23361 - -#define SPELL_MAGE 23410 //wild magic -#define SPELL_WARRIOR 23397 //beserk -#define SPELL_DRUID 23398 // cat form -#define SPELL_PRIEST 23401 // corrupted healing -#define SPELL_PALADIN 23418 //syphon blessing -#define SPELL_SHAMAN 23425 //totems -#define SPELL_WARLOCK 23427 //infernals -#define SPELL_HUNTER 23436 //bow broke -#define SPELL_ROGUE 23414 //Paralise - -struct boss_nefarianAI : public ScriptedAI -{ - boss_nefarianAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowFlame_Timer; - uint32 BellowingRoar_Timer; - uint32 VeilOfShadow_Timer; - uint32 Cleave_Timer; - uint32 TailLash_Timer; - uint32 ClassCall_Timer; - bool Phase3; - - uint32 DespawnTimer; - - void Reset() - { - ShadowFlame_Timer = 12000; //These times are probably wrong - BellowingRoar_Timer = 30000; - VeilOfShadow_Timer = 15000; - Cleave_Timer = 7000; - TailLash_Timer = 10000; - ClassCall_Timer = 35000; //35-40 seconds - Phase3 = false; - - DespawnTimer = 5000; - } - - void KilledUnit(Unit* Victim) - { - if (rand()%5) - return; - - DoScriptText(SAY_SLAY, me, Victim); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * who) - { - DoScriptText(RAND(SAY_XHEALTH,SAY_AGGRO,SAY_SHADOWFLAME), me); - - DoCast(who, SPELL_SHADOWFLAME_INITIAL); - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (DespawnTimer <= diff) - { - if (!UpdateVictim()) - me->ForcedDespawn(); - DespawnTimer = 5000; - } else DespawnTimer -= diff; - - if (!UpdateVictim()) - return; - - //ShadowFlame_Timer - if (ShadowFlame_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWFLAME); - ShadowFlame_Timer = 12000; - } else ShadowFlame_Timer -= diff; - - //BellowingRoar_Timer - if (BellowingRoar_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BELLOWINGROAR); - BellowingRoar_Timer = 30000; - } else BellowingRoar_Timer -= diff; - - //VeilOfShadow_Timer - if (VeilOfShadow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VEILOFSHADOW); - VeilOfShadow_Timer = 15000; - } else VeilOfShadow_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //TailLash_Timer - if (TailLash_Timer <= diff) - { - //Cast NYI since we need a better check for behind target - //DoCast(me->getVictim(), SPELL_TAILLASH); - - TailLash_Timer = 10000; - } else TailLash_Timer -= diff; - - //ClassCall_Timer - if (ClassCall_Timer <= diff) - { - //Cast a random class call - //On official it is based on what classes are currently on the hostil list - //but we can't do that yet so just randomly call one - - switch (urand(0,8)) - { - case 0: - DoScriptText(SAY_MAGE, me); - DoCast(me, SPELL_MAGE); - break; - case 1: - DoScriptText(SAY_WARRIOR, me); - DoCast(me, SPELL_WARRIOR); - break; - case 2: - DoScriptText(SAY_DRUID, me); - DoCast(me, SPELL_DRUID); - break; - case 3: - DoScriptText(SAY_PRIEST, me); - DoCast(me, SPELL_PRIEST); - break; - case 4: - DoScriptText(SAY_PALADIN, me); - DoCast(me, SPELL_PALADIN); - break; - case 5: - DoScriptText(SAY_SHAMAN, me); - DoCast(me, SPELL_SHAMAN); - break; - case 6: - DoScriptText(SAY_WARLOCK, me); - DoCast(me, SPELL_WARLOCK); - break; - case 7: - DoScriptText(SAY_HUNTER, me); - DoCast(me, SPELL_HUNTER); - break; - case 8: - DoScriptText(SAY_ROGUE, me); - DoCast(me, SPELL_ROGUE); - break; - } - - ClassCall_Timer = 35000 + (rand() % 5000); - } else ClassCall_Timer -= diff; - - //Phase3 begins when we are below X health - if (!Phase3 && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) - { - Phase3 = true; - DoScriptText(SAY_RAISE_SKELETONS, me); - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_nefarian(Creature* pCreature) -{ - return new boss_nefarianAI (pCreature); -} - -void AddSC_boss_nefarian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nefarian"; - newscript->GetAI = &GetAI_boss_nefarian; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp deleted file mode 100644 index a095756b18b..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_razorgore.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Razorgore -SD%Complete: 50 -SDComment: Needs additional review. Phase 1 NYI (Grethok the Controller) -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -//Razorgore Phase 2 Script - -#define SAY_EGGS_BROKEN1 -1469022 -#define SAY_EGGS_BROKEN2 -1469023 -#define SAY_EGGS_BROKEN3 -1469024 -#define SAY_DEATH -1469025 - -#define SPELL_CLEAVE 22540 -#define SPELL_WARSTOMP 24375 -#define SPELL_FIREBALLVOLLEY 22425 -#define SPELL_CONFLAGRATION 23023 - -struct boss_razorgoreAI : public ScriptedAI -{ - boss_razorgoreAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cleave_Timer; - uint32 WarStomp_Timer; - uint32 FireballVolley_Timer; - uint32 Conflagration_Timer; - - void Reset() - { - Cleave_Timer = 15000; //These times are probably wrong - WarStomp_Timer = 35000; - FireballVolley_Timer = 7000; - Conflagration_Timer = 12000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = urand(7000,10000); - } else Cleave_Timer -= diff; - - //WarStomp_Timer - if (WarStomp_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WARSTOMP); - WarStomp_Timer = urand(15000,25000); - } else WarStomp_Timer -= diff; - - //FireballVolley_Timer - if (FireballVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALLVOLLEY); - FireballVolley_Timer = urand(12000,15000); - } else FireballVolley_Timer -= diff; - - //Conflagration_Timer - if (Conflagration_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CONFLAGRATION); - //We will remove this threat reduction and add an aura check. - - //if (DoGetThreat(me->getVictim())) - //DoModifyThreatPercent(me->getVictim(),-50); - - Conflagration_Timer = 12000; - } else Conflagration_Timer -= diff; - - // Aura Check. If the gamer is affected by confliguration we attack a random gamer. - if (me->getVictim() && me->getVictim()->HasAura(SPELL_CONFLAGRATION)) - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - me->TauntApply(pTarget); - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_razorgore(Creature* pCreature) -{ - return new boss_razorgoreAI (pCreature); -} - -void AddSC_boss_razorgore() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_razorgore"; - newscript->GetAI = &GetAI_boss_razorgore; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp deleted file mode 100644 index f6e94307f2f..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_vaelastrasz.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Vaelastrasz -SD%Complete: 75 -SDComment: Burning Adrenaline not correctly implemented in core -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_LINE1 -1469026 -#define SAY_LINE2 -1469027 -#define SAY_LINE3 -1469028 -#define SAY_HALFLIFE -1469029 -#define SAY_KILLTARGET -1469030 - -#define GOSSIP_ITEM "Start Event " - -#define SPELL_ESSENCEOFTHERED 23513 -#define SPELL_FLAMEBREATH 23461 -#define SPELL_FIRENOVA 23462 -#define SPELL_TAILSWIPE 15847 -#define SPELL_BURNINGADRENALINE 23620 -#define SPELL_CLEAVE 20684 //Chain cleave is most likely named something different and contains a dummy effect - -struct boss_vaelAI : public ScriptedAI -{ - boss_vaelAI(Creature *c) : ScriptedAI(c) - { - c->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - c->setFaction(35); - c->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - uint64 PlayerGUID; - uint32 SpeechTimer; - uint32 SpeechNum; - uint32 Cleave_Timer; - uint32 FlameBreath_Timer; - uint32 FireNova_Timer; - uint32 BurningAdrenalineCaster_Timer; - uint32 BurningAdrenalineTank_Timer; - uint32 TailSwipe_Timer; - bool HasYelled; - bool DoingSpeech; - - void Reset() - { - PlayerGUID = 0; - SpeechTimer = 0; - SpeechNum = 0; - Cleave_Timer = 8000; //These times are probably wrong - FlameBreath_Timer = 11000; - BurningAdrenalineCaster_Timer = 15000; - BurningAdrenalineTank_Timer = 45000; - FireNova_Timer = 5000; - TailSwipe_Timer = 20000; - HasYelled = false; - DoingSpeech = false; - } - - void BeginSpeech(Unit *pTarget) - { - //Stand up and begin speach - PlayerGUID = pTarget->GetGUID(); - - //10 seconds - DoScriptText(SAY_LINE1, me); - - SpeechTimer = 10000; - SpeechNum = 0; - DoingSpeech = true; - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - void KilledUnit(Unit * victim) - { - if (rand()%5) - return; - - DoScriptText(SAY_KILLTARGET, me, victim); - } - - void EnterCombat(Unit * /*who*/) - { - DoCast(me, SPELL_ESSENCEOFTHERED); - DoZoneInCombat(); - me->SetHealth(int(me->GetMaxHealth()*.3)); - } - - void UpdateAI(const uint32 diff) - { - //Speech - if (DoingSpeech) - { - if (SpeechTimer <= diff) - { - switch (SpeechNum) - { - case 0: - //16 seconds till next line - DoScriptText(SAY_LINE2, me); - SpeechTimer = 16000; - ++SpeechNum; - break; - case 1: - //This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!" - DoScriptText(SAY_LINE3, me); - SpeechTimer = 10000; - ++SpeechNum; - break; - case 2: - me->setFaction(103); - if (PlayerGUID && Unit::GetUnit((*me),PlayerGUID)) - { - AttackStart(Unit::GetUnit((*me),PlayerGUID)); - DoCast(me, SPELL_ESSENCEOFTHERED); - } - SpeechTimer = 0; - DoingSpeech = false; - break; - } - } else SpeechTimer -= diff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - // Yell if hp lower than 15% - if (me->GetHealth()*100 / me->GetMaxHealth() < 15 && !HasYelled) - { - DoScriptText(SAY_HALFLIFE, me); - HasYelled = true; - } - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 15000; - } else Cleave_Timer -= diff; - - //FlameBreath_Timer - if (FlameBreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBREATH); - FlameBreath_Timer = urand(4000,8000); - } else FlameBreath_Timer -= diff; - - //BurningAdrenalineCaster_Timer - if (BurningAdrenalineCaster_Timer <= diff) - { - Unit *pTarget = NULL; - - uint8 i = 0; - while (i < 3) // max 3 tries to get a random target with power_mana - { - ++i; - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); //not aggro leader - if (pTarget && pTarget->getPowerType() == POWER_MANA) - i = 3; - } - if (pTarget) // cast on self (see below) - pTarget->CastSpell(pTarget,SPELL_BURNINGADRENALINE,1); - - BurningAdrenalineCaster_Timer = 15000; - } else BurningAdrenalineCaster_Timer -= diff; - - //BurningAdrenalineTank_Timer - if (BurningAdrenalineTank_Timer <= diff) - { - // have the victim cast the spell on himself otherwise the third effect aura will be applied - // to Vael instead of the player - me->getVictim()->CastSpell(me->getVictim(),SPELL_BURNINGADRENALINE,1); - - BurningAdrenalineTank_Timer = 45000; - } else BurningAdrenalineTank_Timer -= diff; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRENOVA); - FireNova_Timer = 5000; - } else FireNova_Timer -= diff; - - //TailSwipe_Timer - if (TailSwipe_Timer <= diff) - { - //Only cast if we are behind - /*if (!me->HasInArc(M_PI, me->getVictim())) - { - DoCast(me->getVictim(), SPELL_TAILSWIPE); - }*/ - - TailSwipe_Timer = 20000; - } else TailSwipe_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -void SendDefaultMenu_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(boss_vaelAI, pCreature->AI())->BeginSpeech(pPlayer); - } -} - -bool GossipSelect_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - if (uiSender == GOSSIP_SENDER_MAIN) - SendDefaultMenu_boss_vael(pPlayer, pCreature, uiAction); - - return true; -} - -bool GossipHello_boss_vael(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - - return true; -} - -CreatureAI* GetAI_boss_vael(Creature* pCreature) -{ - return new boss_vaelAI (pCreature); -} - -void AddSC_boss_vael() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vaelastrasz"; - newscript->GetAI = &GetAI_boss_vael; - newscript->pGossipHello = &GossipHello_boss_vael; - newscript->pGossipSelect = &GossipSelect_boss_vael; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp deleted file mode 100644 index dfeb2519bae..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/boss_victor_nefarius.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Victor_Nefarius -SD%Complete: 75 -SDComment: Missing some text, Vael beginning event, and spawns Nef in wrong place -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_GAMESBEGIN_1 -1469004 -#define SAY_GAMESBEGIN_2 -1469005 -#define SAY_VAEL_INTRO -1469006 //when he corrupts Vaelastrasz - -#define GOSSIP_ITEM_1 "I've made no mistakes." -#define GOSSIP_ITEM_2 "You have lost your mind, Nefarius. You speak in riddles." -#define GOSSIP_ITEM_3 "Please do." - -#define CREATURE_BRONZE_DRAKANOID 14263 -#define CREATURE_BLUE_DRAKANOID 14261 -#define CREATURE_RED_DRAKANOID 14264 -#define CREATURE_GREEN_DRAKANOID 14262 -#define CREATURE_BLACK_DRAKANOID 14265 - -#define CREATURE_CHROMATIC_DRAKANOID 14302 -#define CREATURE_NEFARIAN 11583 - -#define ADD_X1 -7591.151855 -#define ADD_X2 -7514.598633 -#define ADD_Y1 -1204.051880 -#define ADD_Y2 -1150.448853 -#define ADD_Z1 476.800476 -#define ADD_Z2 476.796570 - -#define NEF_X -7445 -#define NEF_Y -1332 -#define NEF_Z 536 - -#define HIDE_X -7592 -#define HIDE_Y -1264 -#define HIDE_Z 481 - -#define SPELL_SHADOWBOLT 21077 -#define SPELL_FEAR 26070 - -//This script is complicated -//Instead of morphing Victor Nefarius we will have him control phase 1 -//And then have him spawn "Nefarian" for phase 2 -//When phase 2 starts Victor Nefarius will go into hiding and stop attacking -//If Nefarian despawns because he killed the players then this guy will EnterEvadeMode -//and allow players to start the event over -//If nefarian dies then he will kill himself then he will kill himself in his hiding place -//To prevent players from doing the event twice - -struct boss_victor_nefariusAI : public ScriptedAI -{ - boss_victor_nefariusAI(Creature *c) : ScriptedAI(c) - { - NefarianGUID = 0; - switch (urand(0,19)) - { - case 0: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 1: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 2: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 3: - DrakType1 = CREATURE_BRONZE_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 4: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 5: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 6: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 7: - DrakType1 = CREATURE_BLUE_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 8: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 9: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 10: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 11: - DrakType1 = CREATURE_RED_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 12: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 13: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 14: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - case 15: - DrakType1 = CREATURE_GREEN_DRAKANOID; - DrakType2 = CREATURE_BLACK_DRAKANOID; - break; - case 16: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_BRONZE_DRAKANOID; - break; - case 17: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_BLUE_DRAKANOID; - break; - case 18: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_GREEN_DRAKANOID; - break; - case 19: - DrakType1 = CREATURE_BLACK_DRAKANOID; - DrakType2 = CREATURE_RED_DRAKANOID; - break; - } - } - - uint32 SpawnedAdds; - uint32 AddSpawnTimer; - uint32 ShadowBoltTimer; - uint32 FearTimer; - uint32 MindControlTimer; - uint32 ResetTimer; - uint32 DrakType1; - uint32 DrakType2; - uint64 NefarianGUID; - uint32 NefCheckTime; - - void Reset() - { - SpawnedAdds = 0; - AddSpawnTimer = 10000; - ShadowBoltTimer = 5000; - FearTimer = 8000; - ResetTimer = 900000; //On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier - NefarianGUID = 0; - NefCheckTime = 2000; - - me->SetUInt32Value(UNIT_NPC_FLAGS,1); - me->setFaction(35); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void BeginEvent(Player *pTarget) - { - DoScriptText(SAY_GAMESBEGIN_2, me); - - //Trinity::Singleton::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); - /* - list ::const_iterator i = MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); - - for (i = MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().begin(); i != MapManager::Instance().GetMap(me->GetMapId(), me)->GetPlayers().end(); ++i) - { - AttackStart((*i)); - } - */ - me->SetUInt32Value(UNIT_NPC_FLAGS,0); - me->setFaction(103); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - AttackStart(pTarget); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void MoveInLineOfSight(Unit *who) - { - //We simply use this function to find players until we can use pMap->GetPlayers() - - if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsHostileTo(who)) - { - //Add them to our threat list - me->AddThreat(who, 0.0f); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Only do this if we haven't spawned nef yet - if (SpawnedAdds < 42) - { - //ShadowBoltTimer - if (ShadowBoltTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SHADOWBOLT); - - ShadowBoltTimer = urand(3000,10000); - } else ShadowBoltTimer -= diff; - - //FearTimer - if (FearTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_FEAR); - - FearTimer = 10000 + (rand()%10000); - } else FearTimer -= diff; - - //Add spawning mechanism - if (AddSpawnTimer <= diff) - { - //Spawn 2 random types of creatures at the 2 locations - uint32 CreatureID; - Creature* Spawned = NULL; - Unit *pTarget = NULL; - - //1 in 3 chance it will be a chromatic - if (urand(0,2) == 0) - CreatureID = CREATURE_CHROMATIC_DRAKANOID; - else - CreatureID = DrakType1; - - ++SpawnedAdds; - - //Spawn Creature and force it to start attacking a random target - Spawned = me->SummonCreature(CreatureID,ADD_X1,ADD_Y1,ADD_Z1,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget && Spawned) - { - Spawned->AI()->AttackStart(pTarget); - Spawned->setFaction(103); - } - - //1 in 3 chance it will be a chromatic - if (urand(0,2) == 0) - CreatureID = CREATURE_CHROMATIC_DRAKANOID; - else - CreatureID = DrakType2; - - ++SpawnedAdds; - - Spawned = me->SummonCreature(CreatureID,ADD_X2,ADD_Y2,ADD_Z2,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget && Spawned) - { - Spawned->AI()->AttackStart(pTarget); - Spawned->setFaction(103); - } - - //Begin phase 2 by spawning Nefarian and what not - if (SpawnedAdds >= 42) - { - //Teleport Victor Nefarius way out of the map - //MapManager::Instance().GetMap(me->GetMapId(), me)->CreatureRelocation(me,0,0,-5000,0); - - //Inturrupt any spell casting - me->InterruptNonMeleeSpells(false); - - //Root self - DoCast(me, 33356); - - //Make super invis - DoCast(me, 8149); - - //Teleport self to a hiding spot (this causes errors in the Trinity log but no real issues) - DoTeleportTo(HIDE_X,HIDE_Y,HIDE_Z); - me->addUnitState(UNIT_STAT_FLEEING); - - //Spawn nef and have him attack a random target - Creature* Nefarian = me->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget && Nefarian) - { - Nefarian->AI()->AttackStart(pTarget); - Nefarian->setFaction(103); - NefarianGUID = Nefarian->GetGUID(); - } - else error_log("TSCR: Blackwing Lair: Unable to spawn nefarian properly."); - } - - AddSpawnTimer = 4000; - } else AddSpawnTimer -= diff; - } - else if (NefarianGUID) - { - if (NefCheckTime <= diff) - { - Unit* Nefarian = Unit::GetCreature((*me),NefarianGUID); - - //If nef is dead then we die to so the players get out of combat - //and cannot repeat the event - if (!Nefarian || !Nefarian->isAlive()) - { - NefarianGUID = 0; - me->ForcedDespawn(); - } - - NefCheckTime = 2000; - } else NefCheckTime -= diff; - } - } -}; - -CreatureAI* GetAI_boss_victor_nefarius(Creature* pCreature) -{ - return new boss_victor_nefariusAI (pCreature); -} - -bool GossipHello_boss_victor_nefarius(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1 , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(7134, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_boss_victor_nefarius(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(7198, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(7199, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - DoScriptText(SAY_GAMESBEGIN_1, pCreature); - CAST_AI(boss_victor_nefariusAI, pCreature->AI())->BeginEvent(pPlayer); - break; - } - return true; -} - -void AddSC_boss_victor_nefarius() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_victor_nefarius"; - newscript->GetAI = &GetAI_boss_victor_nefarius; - newscript->pGossipHello = &GossipHello_boss_victor_nefarius; - newscript->pGossipSelect = &GossipSelect_boss_victor_nefarius; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp deleted file mode 100644 index d6403fa1206..00000000000 --- a/src/server/scripts/EasternKingdoms/blackwing_lair/instance_blackwing_lair.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Blackwing_Lair -SD%Complete: 0 -SDComment: -SDCategory: Blackwing Lair -EndScriptData */ - -#include "ScriptedPch.h" - diff --git a/src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp b/src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp deleted file mode 100644 index 5c6bab46e5a..00000000000 --- a/src/server/scripts/EasternKingdoms/deadmines/boss_mr_smite.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss Mr.Smite -SD%Complete: -SDComment: Timers and say taken from acid script -EndScriptData */ - -#include "ScriptedPch.h" -#include "deadmines.h" - -enum eSpels -{ - SPELL_TRASH = 3391, - SPELL_SMITE_STOMP = 6432, - SPELL_SMITE_SLAM = 6435, - SPELL_NIMBLE_REFLEXES = 6264, - - EQUIP_SWORD = 5191, - EQUIP_MACE = 7230, - - SAY_AGGRO = -1036001 -}; - -struct boss_mr_smiteAI : public ScriptedAI -{ - boss_mr_smiteAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiTrashTimer; - uint32 uiSlamTimer; - uint32 uiNimbleReflexesTimer; - - uint8 uiHealth; - - uint32 uiPhase; - uint32 uiTimer; - - void Reset() - { - uiTrashTimer = urand(5000,9000); - uiSlamTimer = 9000; - uiNimbleReflexesTimer = urand(15500,31600); - - uiHealth = 0; - - uiPhase = 0; - uiTimer = 0; - - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - bool bCheckChances() - { - uint32 uiChances = urand(0,99); - if (uiChances <= 15) - return false; - else - return true; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - /*START ACID-AI*/ - if (uiTrashTimer <= uiDiff) - { - if (bCheckChances()) - DoCast(me, SPELL_TRASH); - uiTrashTimer = urand(6000,15500); - } else uiTrashTimer -= uiDiff; - - if (uiSlamTimer <= uiDiff) - { - if (bCheckChances()) - DoCast(me->getVictim(), SPELL_SMITE_SLAM); - uiSlamTimer = 11000; - } else uiSlamTimer -= uiDiff; - - if (uiNimbleReflexesTimer <= uiDiff) - { - if (bCheckChances()) - DoCast(me, SPELL_NIMBLE_REFLEXES); - uiNimbleReflexesTimer = urand(27300,60100); - } else uiNimbleReflexesTimer -= uiDiff; - /*END ACID-AI*/ - - if (uiHealth == 0 && me->GetHealth()*100 / me->GetMaxHealth() <= 66 || uiHealth == 1 && me->GetHealth()*100 / me->GetMaxHealth() <= 33) - { - ++uiHealth; - DoCastAOE(SPELL_SMITE_STOMP,false); - SetCombatMovement(false); - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_SMITE_CHEST))) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(1,-3.00+pGo->GetPositionX(),pGo->GetPositionY(),pGo->GetPositionZ()); - } - } - - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - me->HandleEmoteCommand(EMOTE_STATE_KNEEL); //dosen't work? - uiTimer = 1000; - uiPhase = 2; - break; - case 2: - if (uiHealth == 1) - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); - else - SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - uiTimer = 500; - uiPhase = 3; - break; - case 3: - SetCombatMovement(true); - me->GetMotionMaster()->MoveChase(me->getVictim(), me->m_CombatDistance); - uiPhase = 0; - break; - - } - } else uiTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - uiTimer = 1500; - uiPhase = 1; - } - -}; -CreatureAI* GetAI_boss_mr_smite(Creature* pCreature) -{ - return new boss_mr_smiteAI (pCreature); -} - -void AddSC_boss_mr_smite() -{ - Script* newscript; - newscript = new Script; - newscript->Name = "boss_mr_smite"; - newscript->GetAI = &GetAI_boss_mr_smite; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp b/src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp deleted file mode 100644 index 5bc1121bead..00000000000 --- a/src/server/scripts/EasternKingdoms/deadmines/deadmines.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Deadmines -SD%Complete: 0 -SDComment: Placeholder -SDCategory: Deadmines -EndScriptData */ - -#include "ScriptedPch.h" -#include "deadmines.h" -#include "Spell.h" - -/*##### -# item_Defias_Gunpowder -#####*/ - -bool ItemUse_item_defias_gunpowder(Player* pPlayer, Item* pItem, SpellCastTargets const& targets) -{ - ScriptedInstance *pInstance = pPlayer->GetInstanceData(); - - if (!pInstance) - { - pPlayer->GetSession()->SendNotification("Instance script not initialized"); - return true; - } - if (pInstance->GetData(EVENT_STATE)!= CANNON_NOT_USED) - return false; - if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT && - targets.getGOTarget()->GetEntry() == GO_DEFIAS_CANNON) - { - pInstance->SetData(EVENT_STATE, CANNON_GUNPOWDER_USED); - } - - pPlayer->DestroyItemCount(pItem->GetEntry(), 1, true); - return true; -} - -void AddSC_deadmines() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "item_defias_gunpowder"; - newscript->pItemUse = &ItemUse_item_defias_gunpowder; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/deadmines/deadmines.h b/src/server/scripts/EasternKingdoms/deadmines/deadmines.h deleted file mode 100644 index 203494ad5b7..00000000000 --- a/src/server/scripts/EasternKingdoms/deadmines/deadmines.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef DEF_DEADMINES_H -#define DEF_DEADMINES_H - -#include "ScriptedPch.h" - -enum CannonState -{ - CANNON_NOT_USED, - CANNON_GUNPOWDER_USED, - CANNON_BLAST_INITIATED, - PIRATES_ATTACK, - EVENT_DONE -}; - -enum Data -{ - EVENT_STATE, - EVENT_RHAHKZOR -}; - -enum Data64 -{ - DATA_SMITE_CHEST -}; - -enum GameObjects -{ - GO_FACTORY_DOOR = 13965, - GO_IRONCLAD_DOOR = 16397, - GO_DEFIAS_CANNON = 16398, - GO_DOOR_LEVER = 101833, - GO_MR_SMITE_CHEST = 144111 -}; -#endif - diff --git a/src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp b/src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp deleted file mode 100644 index f1aa0c62b8a..00000000000 --- a/src/server/scripts/EasternKingdoms/deadmines/instance_deadmines.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Deadmines -SD%Complete: 100 -SDComment: -SDCategory: Deadmines -EndScriptData */ - -#include "ScriptedPch.h" -#include "deadmines.h" - -enum Sounds -{ - SOUND_CANNONFIRE = 1400, - SOUND_DESTROYDOOR = 3079, - SOUND_MR_SMITE_ALARM1 = 5775, - SOUND_MR_SMITE_ALARM2 = 5777 -}; - -#define SAY_MR_SMITE_ALARM1 "You there, check out that noise!" -#define SAY_MR_SMITE_ALARM2 "We're under attack! A vast, ye swabs! Repel the invaders!" - -enum Misc -{ - DATA_CANNON_BLAST_TIMER = 3000, - DATA_PIRATES_DELAY_TIMER = 1000 -}; - -struct instance_deadmines : public ScriptedInstance -{ - instance_deadmines(Map* pMap) : ScriptedInstance(pMap) { Initialize(); }; - - uint64 FactoryDoorGUID; - uint64 IronCladDoorGUID; - uint64 DefiasCannonGUID; - uint64 DoorLeverGUID; - uint64 DefiasPirate1GUID; - uint64 DefiasPirate2GUID; - uint64 DefiasCompanionGUID; - - uint32 State; - uint32 CannonBlast_Timer; - uint32 PiratesDelay_Timer; - uint64 uiSmiteChestGUID; - - void Initialize() - { - FactoryDoorGUID = 0; - IronCladDoorGUID = 0; - DefiasCannonGUID = 0; - DoorLeverGUID = 0; - DefiasPirate1GUID = 0; - DefiasPirate2GUID = 0; - DefiasCompanionGUID = 0; - - State = CANNON_NOT_USED; - uiSmiteChestGUID = 0; - } - - virtual void Update(uint32 diff) - { - if (!IronCladDoorGUID || !DefiasCannonGUID || !DoorLeverGUID) - return; - - GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID); - if (!pIronCladDoor) - return; - - switch (State) - { - case CANNON_GUNPOWDER_USED: - CannonBlast_Timer = DATA_CANNON_BLAST_TIMER; - // it's a hack - Mr. Smite should do that but his too far away - pIronCladDoor->SetName("Mr. Smite"); - pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM1, LANG_UNIVERSAL, 0); - DoPlaySound(pIronCladDoor, SOUND_MR_SMITE_ALARM1); - State = CANNON_BLAST_INITIATED; - break; - case CANNON_BLAST_INITIATED: - PiratesDelay_Timer = DATA_PIRATES_DELAY_TIMER; - if (CannonBlast_Timer <= diff) - { - SummonCreatures(); - ShootCannon(); - BlastOutDoor(); - LeverStucked(); - pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM2, LANG_UNIVERSAL, 0); - DoPlaySound(pIronCladDoor, SOUND_MR_SMITE_ALARM2); - State = PIRATES_ATTACK; - } else CannonBlast_Timer -= diff; - break; - case PIRATES_ATTACK: - if (PiratesDelay_Timer <= diff) - { - MoveCreaturesInside(); - State = EVENT_DONE; - } else PiratesDelay_Timer -= diff; - break; - } - } - - void SummonCreatures() - { - if (GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID)) - { - Creature *DefiasPirate1 = pIronCladDoor->SummonCreature(657,pIronCladDoor->GetPositionX() - 2,pIronCladDoor->GetPositionY()-7,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - Creature *DefiasPirate2 = pIronCladDoor->SummonCreature(657,pIronCladDoor->GetPositionX() + 3,pIronCladDoor->GetPositionY()-6,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - Creature *DefiasCompanion = pIronCladDoor->SummonCreature(3450,pIronCladDoor->GetPositionX() + 2,pIronCladDoor->GetPositionY()-6,pIronCladDoor->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - - DefiasPirate1GUID = DefiasPirate1->GetGUID(); - DefiasPirate2GUID = DefiasPirate2->GetGUID(); - DefiasCompanionGUID = DefiasCompanion->GetGUID(); - } - } - - void MoveCreaturesInside() - { - if (!DefiasPirate1GUID || !DefiasPirate2GUID || !DefiasCompanionGUID) - return; - - Creature *pDefiasPirate1 = instance->GetCreature(DefiasPirate1GUID); - Creature *pDefiasPirate2 = instance->GetCreature(DefiasPirate2GUID); - Creature *pDefiasCompanion = instance->GetCreature(DefiasCompanionGUID); - if (!pDefiasPirate1 || !pDefiasPirate2 || !pDefiasCompanion) - return; - - MoveCreatureInside(pDefiasPirate1); - MoveCreatureInside(pDefiasPirate2); - MoveCreatureInside(pDefiasCompanion); - } - - void MoveCreatureInside(Creature* pCreature) - { - pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pCreature->GetMotionMaster()->MovePoint(0, -102.7,-655.9, pCreature->GetPositionZ()); - } - - void ShootCannon() - { - if (GameObject *pDefiasCannon = instance->GetGameObject(DefiasCannonGUID)) - { - pDefiasCannon->SetGoState(GO_STATE_ACTIVE); - DoPlaySound(pDefiasCannon, SOUND_CANNONFIRE); - } - } - - void BlastOutDoor() - { - if (GameObject *pIronCladDoor = instance->GetGameObject(IronCladDoorGUID)) - { - pIronCladDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - DoPlaySound(pIronCladDoor, SOUND_DESTROYDOOR); - } - } - - void LeverStucked() - { - if (GameObject *pDoorLever = instance->GetGameObject(DoorLeverGUID)) - pDoorLever->SetUInt32Value(GAMEOBJECT_FLAGS, 4); - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_FACTORY_DOOR: FactoryDoorGUID = pGo->GetGUID(); break; - case GO_IRONCLAD_DOOR: IronCladDoorGUID = pGo->GetGUID(); break; - case GO_DEFIAS_CANNON: DefiasCannonGUID = pGo->GetGUID(); break; - case GO_DOOR_LEVER: DoorLeverGUID = pGo->GetGUID(); break; - case GO_MR_SMITE_CHEST: uiSmiteChestGUID = pGo->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch (type) - { - case EVENT_STATE: - if (DefiasCannonGUID && IronCladDoorGUID) - State=data; - break; - case EVENT_RHAHKZOR: - if (data == DONE) - if (GameObject* pGo = instance->GetGameObject(FactoryDoorGUID)) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - } - } - - uint32 GetData(uint32 type) - { - switch (type) - { - case EVENT_STATE: - return State; - } - - return 0; - } - - uint64 GetData64(uint32 data) - { - switch (data) - { - case DATA_SMITE_CHEST: - return uiSmiteChestGUID; - } - - return 0; - } - - void DoPlaySound(GameObject* unit, uint32 sound) - { - WorldPacket data(4); - data.SetOpcode(SMSG_PLAY_SOUND); - data << uint32(sound); - unit->SendMessageToSet(&data,false); - } - - void DoPlaySoundCreature(Unit* unit, uint32 sound) - { - WorldPacket data(4); - data.SetOpcode(SMSG_PLAY_SOUND); - data << uint32(sound); - unit->SendMessageToSet(&data,false); - } -}; - -InstanceData* GetInstanceData_instance_deadmines(Map* pMap) -{ - return new instance_deadmines(pMap); -} - -void AddSC_instance_deadmines() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_deadmines"; - newscript->GetInstanceData = &GetInstanceData_instance_deadmines; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp deleted file mode 100644 index c39bfb69910..00000000000 --- a/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.cpp +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Gnomeregan -SDAuthor: Manuel -SD%Complete: 90% -SDComment: Some visual effects are not implemented. -Script Data End */ - -#include "ScriptedPch.h" -#include "gnomeregan.h" -#include "ScriptedEscortAI.h" - -#define GOSSIP_START_EVENT "I am ready to being" - -enum eBlastmasterEmiShortfuse -{ - GOSSIP_TEXT_EMI = 1693, - - SAY_BLASTMASTER_0 = -1090000, - SAY_BLASTMASTER_1 = -1090001, - SAY_BLASTMASTER_2 = -1090002, - SAY_BLASTMASTER_3 = -1090003, - SAY_BLASTMASTER_4 = -1090004, - SAY_BLASTMASTER_5 = -1090005, - SAY_BLASTMASTER_6 = -1090006, - SAY_BLASTMASTER_7 = -1090007, - SAY_BLASTMASTER_8 = -1090008, - SAY_BLASTMASTER_9 = -1090009, - SAY_BLASTMASTER_10 = -1090010, - SAY_BLASTMASTER_11 = -1090011, - SAY_BLASTMASTER_12 = -1090012, - SAY_BLASTMASTER_13 = -1090013, - SAY_BLASTMASTER_14 = -1090014, - SAY_BLASTMASTER_15 = -1090015, - SAY_BLASTMASTER_16 = -1090016, - SAY_BLASTMASTER_17 = -1090017, - SAY_BLASTMASTER_18 = -1090018, - SAY_BLASTMASTER_19 = -1090019, - SAY_BLASTMASTER_20 = -1090020, - SAY_BLASTMASTER_21 = -1090021, - SAY_BLASTMASTER_22 = -1090022, - SAY_BLASTMASTER_23 = -1090023, - SAY_BLASTMASTER_24 = -1090024, - SAY_BLASTMASTER_25 = -1090025, - SAY_BLASTMASTER_26 = -1090026, - SAY_BLASTMASTER_27 = -1090027, - - SAY_GRUBBIS = -1090028 -}; - -const Position SpawnPosition[] = -{ - {-557.630,-114.514,-152.209,0.641}, - {-555.263,-113.802,-152.737,0.311}, - {-552.154,-112.476,-153.349,0.621}, - {-548.692,-111.089,-154.090,0.621}, - {-546.905,-108.340,-154.877,0.729}, - {-547.736,-105.154,-155.176,0.372}, - {-547.274,-114.109,-153.952,0.735}, - {-552.534,-110.012,-153.577,0.747}, - {-550.708,-116.436,-153.103,0.679}, - {-554.030,-115.983,-152.635,0.695}, - {-494.595,-87.516,149.116,3.344}, - {-493.349,-90.845,-148.882,3.717}, - {-491.995,-87.619,-148.197,3.230}, - {-490.732,-90.739,-148.091,3.230}, - {-490.554,-89.114,-148.055,3.230}, - {-495.240,-90.808,-149.493,3.238}, - {-494.195,-89.553,-149.131,3.254} -}; - -struct npc_blastmaster_emi_shortfuseAI : public npc_escortAI -{ - npc_blastmaster_emi_shortfuseAI(Creature* pCreature) : npc_escortAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - pCreature->RestoreFaction(); - Reset(); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiTimer; - - std::list SummonList; - std::list GoSummonList; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - uiTimer = 0; - uiPhase = 0; - - RestoreAll(); - - SummonList.clear(); - GoSummonList.clear(); - } - } - - void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) - { - uiTimer = uiTimerStep; - if (bNextStep) - ++uiPhase; - else - uiPhase = uiPhaseStep; - } - - void CaveDestruction(bool bBool) - { - if (GoSummonList.empty()) - return; - - for (std::list::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) - { - if (GameObject* pGo = GameObject::GetGameObject(*me, *itr)) - { - if (pGo) - { - if (Creature *trigger = pGo->SummonTrigger(pGo->GetPositionX(), pGo->GetPositionY(),pGo->GetPositionZ(), 0, 1)) - { - //visual effects are not working! ¬¬ - trigger->CastSpell(trigger,11542,true); - trigger->CastSpell(trigger,35470,true); - } - pGo->RemoveFromWorld(); - //pGo->CastSpell(me,12158); makes all die?! - } - } - } - - if (bBool) - { - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - pInstance->HandleGameObject(NULL,false,pGo); - }else - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) - pInstance->HandleGameObject(NULL,false,pGo); - } - - void SetInFace(bool bBool) - { - if (!pInstance) - return; - - if (bBool) - { - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - me->SetFacingToObject(pGo); - }else - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) - me->SetFacingToObject(pGo); - } - - void RestoreAll() - { - if (!pInstance) - return; - - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - pInstance->HandleGameObject(NULL,false,pGo); - - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) - pInstance->HandleGameObject(NULL,false,pGo); - - if (!GoSummonList.empty()) - for (std::list::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) - { - if (GameObject* pGo = GameObject::GetGameObject(*me, *itr)) - pGo->RemoveFromWorld(); - } - - if (!SummonList.empty()) - for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) - { - if (Creature* pSummon = Unit::GetCreature(*me, *itr)) - { - if (pSummon->isAlive()) - pSummon->DisappearAndDie(); - else - pSummon->RemoveCorpse(); - } - } - } - - void AggroAllPlayers(Creature* pTemp) - { - Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - pTemp->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(pTemp); - pTemp->AddThreat(pPlayer, 0.0f); - } - } - } - } - - void WaypointReached(uint32 uiPoint) - { - //just in case - if (GetPlayerForEscort()) - if (me->getFaction() != GetPlayerForEscort()->getFaction()) - me->setFaction(GetPlayerForEscort()->getFaction()); - - switch(uiPoint) - { - case 3: - SetEscortPaused(true); - NextStep(2000,false,3); - break; - case 7: - SetEscortPaused(true); - NextStep(2000,false,4); - break; - case 9: - NextStep(1000,false,8); - break; - case 10: - NextStep(25000,false,10); - break; - case 11: - SetEscortPaused(true); - SetInFace(true); - NextStep(1000,false,11); - break; - case 12: - NextStep(25000,false,18); - break; - case 13: - Summon(7); - NextStep(25000,false,19); - break; - case 14: - SetInFace(false); - DoScriptText(SAY_BLASTMASTER_26,me); - SetEscortPaused(true); - NextStep(5000,false,20); - break; - } - } - - void SetData(uint32 uiI,uint32 uiValue) - { - switch(uiI) - { - case 1: - SetEscortPaused(true); - DoScriptText(SAY_BLASTMASTER_0,me); - NextStep(1500,true); - break; - case 2: - if (!pInstance) - return; - - switch(uiValue) - { - case 1: - pInstance->SetData(TYPE_EVENT, IN_PROGRESS); - break; - case 2: - pInstance->SetData(TYPE_EVENT, DONE); - NextStep(5000,false,22); - break; - } - break; - } - } - - void Summon(uint8 uiCase) - { - switch(uiCase) - { - case 1: - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[5], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[6], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[7], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[8], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[9], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - break; - case 2: - if (GameObject* pGo = me->SummonGameObject(183410, -533.140,-105.322,-156.016, 0, 0, 0, 0, 0, 1000)) - { - GoSummonList.push_back(pGo->GetGUID()); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! - } - Summon(3); - break; - case 3: - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - DoScriptText(SAY_BLASTMASTER_19,me); - break; - case 4: - if (GameObject* pGo = me->SummonGameObject(183410, -542.199,-96.854,-155.790, 0, 0, 0, 0, 0, 1000)) - { - GoSummonList.push_back(pGo->GetGUID()); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - } - break; - case 5: - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - DoScriptText(SAY_BLASTMASTER_15,me); - break; - case 6: - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[10], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[11], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[12], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[13], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[14], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - break; - case 7: - if (GameObject* pGo = me->SummonGameObject(183410, -507.820,-103.333,-151.353, 0, 0, 0, 0, 0, 1000)) - { - GoSummonList.push_back(pGo->GetGUID()); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! - Summon(6); - } - break; - case 8: - if (GameObject* pGo = me->SummonGameObject(183410, -511.829,-86.249,-151.431, 0, 0, 0, 0, 0, 1000)) - { - GoSummonList.push_back(pGo->GetGUID()); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); //We can't use it! - } - break; - case 9: - if (Creature* pGrubbis = me->SummonCreature(NPC_GRUBBIS, SpawnPosition[15], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000)) - DoScriptText(SAY_GRUBBIS,pGrubbis); - me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); - break; - } - } - - void UpdateEscortAI(const uint32 uiDiff) - { - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - DoScriptText(SAY_BLASTMASTER_1,me); - NextStep(1500,true); - break; - case 2: - SetEscortPaused(false); - NextStep(0,false,0); - break; - case 3: - DoScriptText(SAY_BLASTMASTER_2,me); - SetEscortPaused(false); - NextStep(0,false,0); - break; - case 4: - DoScriptText(SAY_BLASTMASTER_3,me); - NextStep(3000,true); - break; - case 5: - DoScriptText(SAY_BLASTMASTER_4,me); - NextStep(3000,true); - break; - case 6: - SetInFace(true); - DoScriptText(SAY_BLASTMASTER_5,me); - Summon(1); - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_RIGHT))) - pInstance->HandleGameObject(NULL,true,pGo); - NextStep(3000,true); - break; - case 7: - DoScriptText(SAY_BLASTMASTER_6,me); - SetEscortPaused(false); - NextStep(0,false,0); - break; - case 8: - me->HandleEmoteCommand(EMOTE_STATE_WORK); - NextStep(25000,true); - break; - case 9: - Summon(2); - NextStep(0,false); - break; - case 10: - Summon(4); - NextStep(0,false); - break; - case 11: - DoScriptText(SAY_BLASTMASTER_17,me); - NextStep(5000,true); - break; - case 12: - DoScriptText(SAY_BLASTMASTER_18,me); - NextStep(5000,true); - break; - case 13: - DoScriptText(SAY_BLASTMASTER_20,me); - CaveDestruction(true); - NextStep(8000,true); - break; - case 14: - DoScriptText(SAY_BLASTMASTER_21,me); - NextStep(8500,true); - break; - case 15: - DoScriptText(SAY_BLASTMASTER_22,me); - NextStep(2000,true); - break; - case 16: - DoScriptText(SAY_BLASTMASTER_23,me); - SetInFace(false); - if (pInstance) - if (GameObject* pGo = GameObject::GetGameObject((*me),pInstance->GetData64(DATA_GO_CAVE_IN_LEFT))) - pInstance->HandleGameObject(NULL,true,pGo); - NextStep(2000,true); - break; - case 17: - SetEscortPaused(false); - DoScriptText(SAY_BLASTMASTER_24,me); - Summon(6); - NextStep(0,false); - break; - case 18: - Summon(7); - NextStep(0,false); - break; - case 19: - SetInFace(false); - Summon(8); - DoScriptText(SAY_BLASTMASTER_25,me); - NextStep(0,false); - break; - case 20: - DoScriptText(SAY_BLASTMASTER_27,me); - NextStep(2000,true); - break; - case 21: - Summon(9); - NextStep(0,false); - break; - case 22: - CaveDestruction(false); - DoScriptText(SAY_BLASTMASTER_20,me); - NextStep(0,false); - break; - } - } else uiTimer -= uiDiff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* pSummon) - { - SummonList.push_back(pSummon->GetGUID()); - AggroAllPlayers(pSummon); - } -}; - -CreatureAI* GetAI_npc_blastmaster_emi_shortfuse(Creature* pCreature) -{ - return new npc_blastmaster_emi_shortfuseAI(pCreature); -} - -bool GossipHello_npc_blastmaster_emi_shortfuse(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && pInstance->GetData(TYPE_EVENT) == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_EMI, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_blastmaster_emi_shortfuse(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - if (npc_escortAI* pEscortAI = CAST_AI(npc_blastmaster_emi_shortfuseAI, pCreature->AI())) - pEscortAI->Start(true, false,pPlayer->GetGUID()); - - pCreature->setFaction(pPlayer->getFaction()); - pCreature->AI()->SetData(1,0); - - pPlayer->CLOSE_GOSSIP_MENU(); - } - return true; -} - -struct boss_grubbisAI : public ScriptedAI -{ - boss_grubbisAI(Creature* pCreature) : ScriptedAI(pCreature) - { - SetDataSummoner(); - } - - void SetDataSummoner() - { - if (!me->isSummon()) - return; - - if (Unit* pSummon = CAST_SUM(me)->GetSummoner()) - CAST_CRE(pSummon)->AI()->SetData(2,1); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (!me->isSummon()) - return; - - if (Unit* pSummon = CAST_SUM(me)->GetSummoner()) - CAST_CRE(pSummon)->AI()->SetData(2,2); - } -}; - -CreatureAI* GetAI_boss_grubbis(Creature* pCreature) -{ - return new boss_grubbisAI(pCreature); -} - -void AddSC_gnomeregan() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_blastmaster_emi_shortfuse"; - newscript->pGossipHello = &GossipHello_npc_blastmaster_emi_shortfuse; - newscript->pGossipSelect = &GossipSelect_npc_blastmaster_emi_shortfuse; - newscript->GetAI = &GetAI_npc_blastmaster_emi_shortfuse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_grubbis"; - newscript->GetAI = &GetAI_boss_grubbis; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h b/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h deleted file mode 100644 index e46c811e9b1..00000000000 --- a/src/server/scripts/EasternKingdoms/gnomeregan/gnomeregan.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_GNOMEREGAN_H -#define DEF_GNOMEREGAN_H - -enum eGameObjects -{ - GO_CAVE_IN_LEFT = 146085, - GO_CAVE_IN_RIGHT = 146086 -}; - -enum eCreatures -{ - NPC_BLASTMASTER_EMI_SHORTFUSE = 7998, - NPC_CAVERNDEEP_AMBUSHER = 6207, - NPC_GRUBBIS = 7361, - NPC_CHOMPER = 6215 -}; - -enum eData -{ - TYPE_EVENT = 1 -}; - -enum eData64 -{ - DATA_GO_CAVE_IN_LEFT, - DATA_GO_CAVE_IN_RIGHT, - DATA_NPC_BASTMASTER_EMI_SHORTFUSE -}; - -#endif diff --git a/src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp b/src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp deleted file mode 100644 index 980a6d3552b..00000000000 --- a/src/server/scripts/EasternKingdoms/gnomeregan/instance_gnomeregan.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "gnomeregan.h" - -#define MAX_ENCOUNTER 1 - -struct instance_gnomeregan : public ScriptedInstance -{ - instance_gnomeregan(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - }; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 uiCaveInLeftGUID; - uint64 uiCaveInRightGUID; - - uint64 uiBastmasterEmiShortfuseGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - uiCaveInLeftGUID = 0; - uiCaveInRightGUID = 0; - - uiBastmasterEmiShortfuseGUID = 0; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) - { - switch(pCreature->GetEntry()) - { - case NPC_BLASTMASTER_EMI_SHORTFUSE: uiBastmasterEmiShortfuseGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*bAdd*/) - { - switch(pGo->GetEntry()) - { - case GO_CAVE_IN_LEFT: - uiCaveInLeftGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE || m_auiEncounter[0] == NOT_STARTED) - HandleGameObject(NULL,false,pGo); - break; - case GO_CAVE_IN_RIGHT: - uiCaveInRightGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE || m_auiEncounter[0] == NOT_STARTED) - HandleGameObject(NULL,false,pGo); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_EVENT: - m_auiEncounter[0] = uiData; - if (uiData == DONE) - SaveToDB(); - break; - } - } - - uint32 GetData(uint32 uiType, uint32 /*uiData*/) - { - switch(uiType) - { - case TYPE_EVENT: return m_auiEncounter[0]; - } - } - - uint64 GetData64(uint32 uiType) - { - switch(uiType) - { - case DATA_GO_CAVE_IN_LEFT: return uiCaveInLeftGUID; - case DATA_GO_CAVE_IN_RIGHT: return uiCaveInRightGUID; - case DATA_NPC_BASTMASTER_EMI_SHORTFUSE: return uiBastmasterEmiShortfuseGUID; - } - - return 0; - } -}; - -InstanceData* GetInstanceData_instance_gnomeregan(Map* pMap) -{ - return new instance_gnomeregan(pMap); -} - -void AddSC_instance_gnomeregan() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "instance_gnomeregan"; - newscript->GetInstanceData = &GetInstanceData_instance_gnomeregan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp deleted file mode 100644 index 7105d27ca6a..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_curator.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Curator -SD%Complete: 100 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1532057 -#define SAY_SUMMON1 -1532058 -#define SAY_SUMMON2 -1532059 -#define SAY_EVOCATE -1532060 -#define SAY_ENRAGE -1532061 -#define SAY_KILL1 -1532062 -#define SAY_KILL2 -1532063 -#define SAY_DEATH -1532064 - -//Flare spell info -#define SPELL_ASTRAL_FLARE_PASSIVE 30234 //Visual effect + Flare damage - -//Curator spell info -#define SPELL_HATEFUL_BOLT 30383 -#define SPELL_EVOCATION 30254 -#define SPELL_ENRAGE 30403 //Arcane Infusion: Transforms Curator and adds damage. -#define SPELL_BERSERK 26662 - -struct boss_curatorAI : public ScriptedAI -{ - boss_curatorAI(Creature *c) : ScriptedAI(c) {} - - uint32 AddTimer; - uint32 HatefulBoltTimer; - uint32 BerserkTimer; - - bool Enraged; - bool Evocating; - - void Reset() - { - AddTimer = 10000; - HatefulBoltTimer = 15000; //This time may be wrong - BerserkTimer = 720000; //12 minutes - Enraged = false; - Evocating = false; - - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //always decrease BerserkTimer - if (BerserkTimer <= diff) - { - //if evocate, then break evocate - if (Evocating) - { - if (me->HasAura(SPELL_EVOCATION)) - me->RemoveAurasDueToSpell(SPELL_EVOCATION); - - Evocating = false; - } - - //may not be correct SAY (generic hard enrage) - DoScriptText(SAY_ENRAGE, me); - - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_BERSERK); - - //don't know if he's supposed to do summon/evocate after hard enrage (probably not) - Enraged = true; - } else BerserkTimer -= diff; - - if (Evocating) - { - //not supposed to do anything while evocate - if (me->HasAura(SPELL_EVOCATION)) - return; - else - Evocating = false; - } - - if (!Enraged) - { - if (AddTimer <= diff) - { - //Summon Astral Flare - Creature* AstralFlare = DoSpawnCreature(17096, rand()%37, rand()%37, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (AstralFlare && pTarget) - { - AstralFlare->CastSpell(AstralFlare, SPELL_ASTRAL_FLARE_PASSIVE, false); - AstralFlare->AI()->AttackStart(pTarget); - } - - //Reduce Mana by 10% of max health - if (int32 mana = me->GetMaxPower(POWER_MANA)) - { - mana /= 10; - me->ModifyPower(POWER_MANA, -mana); - - //if this get's us below 10%, then we evocate (the 10th should be summoned now) - if (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA) < 10) - { - DoScriptText(SAY_EVOCATE, me); - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_EVOCATION); - Evocating = true; - //no AddTimer cooldown, this will make first flare appear instantly after evocate end, like expected - return; - } - else - { - if (urand(0,1) == 0) - { - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - } - } - } - - AddTimer = 10000; - } else AddTimer -= diff; - - if (me->GetHealth()*100 / me->GetMaxHealth() <= 15) - { - Enraged = true; - DoCast(me, SPELL_ENRAGE); - DoScriptText(SAY_ENRAGE, me); - } - } - - if (HatefulBoltTimer <= diff) - { - if (Enraged) - HatefulBoltTimer = 7000; - else - HatefulBoltTimer = 15000; - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1)) - DoCast(pTarget, SPELL_HATEFUL_BOLT); - - } else HatefulBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_curator(Creature* pCreature) -{ - return new boss_curatorAI (pCreature); -} - -void AddSC_boss_curator() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_curator"; - newscript->GetAI = &GetAI_boss_curator; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp deleted file mode 100644 index 21db1be1be3..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_maiden_of_virtue.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Maiden_of_Virtue -SD%Complete: 100 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1532018 -#define SAY_SLAY1 -1532019 -#define SAY_SLAY2 -1532020 -#define SAY_SLAY3 -1532021 -#define SAY_REPENTANCE1 -1532022 -#define SAY_REPENTANCE2 -1532023 -#define SAY_DEATH -1532024 - -#define SPELL_REPENTANCE 29511 -#define SPELL_HOLYFIRE 29522 -#define SPELL_HOLYWRATH 32445 -#define SPELL_HOLYGROUND 29512 -#define SPELL_BERSERK 26662 - -struct boss_maiden_of_virtueAI : public ScriptedAI -{ - boss_maiden_of_virtueAI(Creature *c) : ScriptedAI(c) {} - - uint32 Repentance_Timer; - uint32 Holyfire_Timer; - uint32 Holywrath_Timer; - uint32 Holyground_Timer; - uint32 Enrage_Timer; - - bool Enraged; - - void Reset() - { - Repentance_Timer = 25000+(rand()%15000); - Holyfire_Timer = 8000+(rand()%17000); - Holywrath_Timer = 15000+(rand()%10000); - Holyground_Timer = 3000; - Enrage_Timer = 600000; - - Enraged = false; - } - - void KilledUnit(Unit* /*Victim*/) - { - if (urand(0,1) == 0) - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Enrage_Timer < diff && !Enraged) - { - DoCast(me, SPELL_BERSERK, true); - Enraged = true; - } else Enrage_Timer -= diff; - - if (Holyground_Timer <= diff) - { - DoCast(me, SPELL_HOLYGROUND, true); //Triggered so it doesn't interrupt her at all - Holyground_Timer = 3000; - } else Holyground_Timer -= diff; - - if (Repentance_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REPENTANCE); - DoScriptText(RAND(SAY_REPENTANCE1,SAY_REPENTANCE2), me); - - Repentance_Timer = urand(25000,35000); //A little randomness on that spell - } else Repentance_Timer -= diff; - - if (Holyfire_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_HOLYFIRE); - - Holyfire_Timer = urand(8000,23000); //Anywhere from 8 to 23 seconds, good luck having several of those in a row! - } else Holyfire_Timer -= diff; - - if (Holywrath_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_HOLYWRATH); - - Holywrath_Timer = urand(20000,25000); //20-30 secs sounds nice - } else Holywrath_Timer -= diff; - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_boss_maiden_of_virtue(Creature* pCreature) -{ - return new boss_maiden_of_virtueAI (pCreature); -} - -void AddSC_boss_maiden_of_virtue() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_maiden_of_virtue"; - newscript->GetAI = &GetAI_boss_maiden_of_virtue; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp deleted file mode 100644 index a2f2a8b605e..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_midnight.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Midnight -SD%Complete: 100 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_MIDNIGHT_KILL -1532000 -#define SAY_APPEAR1 -1532001 -#define SAY_APPEAR2 -1532002 -#define SAY_APPEAR3 -1532003 -#define SAY_MOUNT -1532004 -#define SAY_KILL1 -1532005 -#define SAY_KILL2 -1532006 -#define SAY_DISARMED -1532007 -#define SAY_DEATH -1532008 -#define SAY_RANDOM1 -1532009 -#define SAY_RANDOM2 -1532010 - -#define SPELL_SHADOWCLEAVE 29832 -#define SPELL_INTANGIBLE_PRESENCE 29833 -#define SPELL_BERSERKER_CHARGE 26561 //Only when mounted - -#define MOUNTED_DISPLAYID 16040 - -//Attumen (TODO: Use the summoning spell instead of Creature id. It works , but is not convenient for us) -#define SUMMON_ATTUMEN 15550 - -struct boss_midnightAI : public ScriptedAI -{ - boss_midnightAI(Creature *c) : ScriptedAI(c) {} - - uint64 Attumen; - uint8 Phase; - uint32 Mount_Timer; - - void Reset() - { - Phase = 1; - Attumen = 0; - Mount_Timer = 0; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_ON); - } - - void EnterCombat(Unit* /*who*/) {} - - void KilledUnit(Unit * /*victim*/) - { - if (Phase == 2) - { - if (Unit *pUnit = Unit::GetUnit(*me, Attumen)) - DoScriptText(SAY_MIDNIGHT_KILL, pUnit); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Phase == 1 && (me->GetHealth()*100)/me->GetMaxHealth() < 95) - { - Phase = 2; - if (Creature* pAttumen = me->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000)) - { - Attumen = pAttumen->GetGUID(); - pAttumen->AI()->AttackStart(me->getVictim()); - SetMidnight(pAttumen, me->GetGUID()); - DoScriptText(RAND(SAY_APPEAR1,SAY_APPEAR2,SAY_APPEAR3), pAttumen); - } - } - else if (Phase == 2 && (me->GetHealth()*100)/me->GetMaxHealth() < 25) - { - if (Unit *pAttumen = Unit::GetUnit(*me, Attumen)) - Mount(pAttumen); - } - else if (Phase == 3) - { - if (Mount_Timer) - { - if (Mount_Timer <= diff) - { - Mount_Timer = 0; - me->SetVisibility(VISIBILITY_OFF); - me->GetMotionMaster()->MoveIdle(); - if (Unit *pAttumen = Unit::GetUnit(*me, Attumen)) - { - pAttumen->SetDisplayId(MOUNTED_DISPLAYID); - pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pAttumen->getVictim()) - { - pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim()); - pAttumen->SetUInt64Value(UNIT_FIELD_TARGET, pAttumen->getVictim()->GetGUID()); - } - pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X,1); - } - } else Mount_Timer -= diff; - } - } - - if (Phase != 3) - DoMeleeAttackIfReady(); - } - - void Mount(Unit *pAttumen) - { - DoScriptText(SAY_MOUNT, pAttumen); - Phase = 3; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - float angle = me->GetAngle(pAttumen); - float distance = me->GetDistance2d(pAttumen); - float newX = me->GetPositionX() + cos(angle)*(distance/2) ; - float newY = me->GetPositionY() + sin(angle)*(distance/2) ; - float newZ = 50; - //me->Relocate(newX,newY,newZ,angle); - //me->SendMonsterMove(newX, newY, newZ, 0, true, 1000); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, newX, newY, newZ); - distance += 10; - newX = me->GetPositionX() + cos(angle)*(distance/2) ; - newY = me->GetPositionY() + sin(angle)*(distance/2) ; - pAttumen->GetMotionMaster()->Clear(); - pAttumen->GetMotionMaster()->MovePoint(0, newX, newY, newZ); - //pAttumen->Relocate(newX,newY,newZ,-angle); - //pAttumen->SendMonsterMove(newX, newY, newZ, 0, true, 1000); - Mount_Timer = 1000; - } - - void SetMidnight(Creature *, uint64); //Below .. -}; - -CreatureAI* GetAI_boss_midnight(Creature* pCreature) -{ - return new boss_midnightAI(pCreature); -} - -struct boss_attumenAI : public ScriptedAI -{ - boss_attumenAI(Creature *c) : ScriptedAI(c) - { - Phase = 1; - - CleaveTimer = urand(10000,15000); - CurseTimer = 30000; - RandomYellTimer = urand(30000,60000); //Occasionally yell - ChargeTimer = 20000; - ResetTimer = 0; - } - - uint64 Midnight; - uint8 Phase; - uint32 CleaveTimer; - uint32 CurseTimer; - uint32 RandomYellTimer; - uint32 ChargeTimer; //only when mounted - uint32 ResetTimer; - - void Reset() - { - ResetTimer = 2000; - } - - void EnterCombat(Unit* /*who*/) {} - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - if (Unit *pMidnight = Unit::GetUnit(*me, Midnight)) - pMidnight->Kill(pMidnight); - } - - void UpdateAI(const uint32 diff) - { - if (ResetTimer) - { - if (ResetTimer <= diff) - { - ResetTimer = 0; - Unit *pMidnight = Unit::GetUnit(*me, Midnight); - if (pMidnight) - { - pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pMidnight->SetVisibility(VISIBILITY_ON); - } - Midnight = 0; - me->SetVisibility(VISIBILITY_OFF); - me->Kill(me); - } - } else ResetTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) - return; - - if (CleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWCLEAVE); - CleaveTimer = urand(10000,15000); - } else CleaveTimer -= diff; - - if (CurseTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE); - CurseTimer = 30000; - } else CurseTimer -= diff; - - if (RandomYellTimer <= diff) - { - DoScriptText(RAND(SAY_RANDOM1,SAY_RANDOM2), me); - RandomYellTimer = urand(30000,60000); - } else RandomYellTimer -= diff; - - if (me->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID) - { - if (ChargeTimer <= diff) - { - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && !pTarget->IsWithinDist(me, ATTACK_DISTANCE, false)) - target_list.push_back(pTarget); - pTarget = NULL; - } - if (target_list.size()) - pTarget = *(target_list.begin()+rand()%target_list.size()); - - DoCast(pTarget, SPELL_BERSERKER_CHARGE); - ChargeTimer = 20000; - } else ChargeTimer -= diff; - } - else - { - if ((me->GetHealth()*100)/me->GetMaxHealth() < 25) - { - Creature *pMidnight = Unit::GetCreature(*me, Midnight); - if (pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT) - { - CAST_AI(boss_midnightAI, (pMidnight->AI()))->Mount(me); - me->SetHealth(pMidnight->GetHealth()); - DoResetThreat(); - } - } - } - - DoMeleeAttackIfReady(); - } - - void SpellHit(Unit * /*source*/, const SpellEntry *spell) - { - if (spell->Mechanic == MECHANIC_DISARM) - DoScriptText(SAY_DISARMED, me); - } -}; - -void boss_midnightAI::SetMidnight(Creature *pAttumen, uint64 value) -{ - CAST_AI(boss_attumenAI, pAttumen->AI())->Midnight = value; -} - -CreatureAI* GetAI_boss_attumen(Creature* pCreature) -{ - return new boss_attumenAI (pCreature); -} - -void AddSC_boss_attumen() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_attumen"; - newscript->GetAI = &GetAI_boss_attumen; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_midnight"; - newscript->GetAI = &GetAI_boss_midnight; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp deleted file mode 100644 index 6c8fabcca35..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_moroes.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Moroes -SD%Complete: 95 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define SAY_AGGRO -1532011 -#define SAY_SPECIAL_1 -1532012 -#define SAY_SPECIAL_2 -1532013 -#define SAY_KILL_1 -1532014 -#define SAY_KILL_2 -1532015 -#define SAY_KILL_3 -1532016 -#define SAY_DEATH -1532017 - -#define SPELL_VANISH 29448 -#define SPELL_GARROTE 37066 -#define SPELL_BLIND 34694 -#define SPELL_GOUGE 29425 -#define SPELL_FRENZY 37023 - -#define POS_Z 81.73 - -float Locations[4][3]= -{ - {-10991.0, -1884.33, 0.614315}, - {-10989.4, -1885.88, 0.904913}, - {-10978.1, -1887.07, 2.035550}, - {-10975.9, -1885.81, 2.253890}, -}; - -const uint32 Adds[6]= -{ - 17007, - 19872, - 19873, - 19874, - 19875, - 19876, -}; - -struct boss_moroesAI : public ScriptedAI -{ - boss_moroesAI(Creature *c) : ScriptedAI(c) - { - for (uint8 i = 0; i < 4; ++i) - { - AddId[i] = 0; - } - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint64 AddGUID[4]; - - uint32 Vanish_Timer; - uint32 Blind_Timer; - uint32 Gouge_Timer; - uint32 Wait_Timer; - uint32 CheckAdds_Timer; - uint32 AddId[4]; - - bool InVanish; - bool Enrage; - - void Reset() - { - Vanish_Timer = 30000; - Blind_Timer = 35000; - Gouge_Timer = 23000; - Wait_Timer = 0; - CheckAdds_Timer = 5000; - - Enrage = false; - InVanish = false; - if (me->GetHealth() > 0) - { - SpawnAdds(); - } - - if (pInstance) - pInstance->SetData(TYPE_MOROES, NOT_STARTED); - } - - void StartEvent() - { - if (pInstance) - pInstance->SetData(TYPE_MOROES, IN_PROGRESS); - - DoZoneInCombat(); - } - - void EnterCombat(Unit* /*who*/) - { - StartEvent(); - - DoScriptText(SAY_AGGRO, me); - AddsAttack(); - DoZoneInCombat(); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); - } - - void JustDied(Unit* /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_MOROES, DONE); - - DeSpawnAdds(); - - //remove aura from spell Garrote when Moroes dies - if (pInstance) - pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GARROTE); - } - - void SpawnAdds() - { - DeSpawnAdds(); - if (isAddlistEmpty()) - { - Creature *pCreature = NULL; - std::vector AddList; - - for (uint8 i = 0; i < 6; ++i) - AddList.push_back(Adds[i]); - - while (AddList.size() > 4) - AddList.erase((AddList.begin())+(rand()%AddList.size())); - - uint8 i = 0; - for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr) - { - uint32 entry = *itr; - - pCreature = me->SummonCreature(entry, Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - if (pCreature) - { - AddGUID[i] = pCreature->GetGUID(); - AddId[i] = entry; - } - ++i; - } - }else - { - for (uint8 i = 0; i < 4; ++i) - { - Creature *pCreature = me->SummonCreature(AddId[i], Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - if (pCreature) - { - AddGUID[i] = pCreature->GetGUID(); - } - } - } - } - - bool isAddlistEmpty() - { - for (uint8 i = 0; i < 4; ++i) - { - if (AddId[i] == 0) - return true; - } - return false; - } - - void DeSpawnAdds() - { - for (uint8 i = 0; i < 4 ; ++i) - { - Creature* Temp = NULL; - if (AddGUID[i]) - { - Temp = Creature::GetCreature((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - Temp->DisappearAndDie(); - } - } - } - - void AddsAttack() - { - for (uint8 i = 0; i < 4; ++i) - { - Creature* Temp = NULL; - if (AddGUID[i]) - { - Temp = Creature::GetCreature((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - { - Temp->AI()->AttackStart(me->getVictim()); - DoZoneInCombat(Temp); - } else - EnterEvadeMode(); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (pInstance && !pInstance->GetData(TYPE_MOROES)) - { - EnterEvadeMode(); - return; - } - - if (!Enrage && me->GetHealth()*100 / me->GetMaxHealth() < 30) - { - DoCast(me, SPELL_FRENZY); - Enrage = true; - } - - if (CheckAdds_Timer <= diff) - { - for (uint8 i = 0; i < 4; ++i) - { - Creature* Temp = NULL; - if (AddGUID[i]) - { - Temp = Unit::GetCreature((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - if (!Temp->getVictim()) - Temp->AI()->AttackStart(me->getVictim()); - } - } - CheckAdds_Timer = 5000; - } else CheckAdds_Timer -= diff; - - if (!Enrage) - { - //Cast Vanish, then Garrote random victim - if (Vanish_Timer <= diff) - { - DoCast(me, SPELL_VANISH); - InVanish = true; - Vanish_Timer = 30000; - Wait_Timer = 5000; - } else Vanish_Timer -= diff; - - if (Gouge_Timer <= diff) - { - DoCastVictim(SPELL_GOUGE); - Gouge_Timer = 40000; - } else Gouge_Timer -= diff; - - if (Blind_Timer <= diff) - { - std::list pTargets; - SelectTargetList(pTargets, 5, SELECT_TARGET_RANDOM, me->GetMeleeReach()*5, true); - for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) - if (!me->IsWithinMeleeRange(*i)) - { - DoCast(*i, SPELL_BLIND); - break; - } - Blind_Timer = 40000; - } else Blind_Timer -= diff; - } - - if (InVanish) - { - if (Wait_Timer <= diff) - { - DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2), me); - - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - pTarget->CastSpell(pTarget, SPELL_GARROTE,true); - - InVanish = false; - } else Wait_Timer -= diff; - } - - if (!InVanish) - DoMeleeAttackIfReady(); - } -}; - -struct boss_moroes_guestAI : public ScriptedAI -{ - ScriptedInstance* pInstance; - - uint64 GuestGUID[4]; - - boss_moroes_guestAI(Creature* c) : ScriptedAI(c) - { - for (uint8 i = 0; i < 4; ++i) - GuestGUID[i] = 0; - - pInstance = c->GetInstanceData(); - } - - void Reset() - { - if (pInstance) - pInstance->SetData(TYPE_MOROES, NOT_STARTED); - } - - void AcquireGUID() - { - if (!pInstance) - return; - - uint64 MoroesGUID = pInstance->GetData64(DATA_MOROES); - Creature* Moroes = (Unit::GetCreature((*me), MoroesGUID)); - if (Moroes) - { - for (uint8 i = 0; i < 4; ++i) - { - uint64 GUID = CAST_AI(boss_moroesAI, Moroes->AI())->AddGUID[i]; - if (GUID) - GuestGUID[i] = GUID; - } - } - } - - Unit* SelectGuestTarget() - { - uint64 TempGUID = GuestGUID[rand()%4]; - if (TempGUID) - { - Unit* pUnit = Unit::GetUnit((*me), TempGUID); - if (pUnit && pUnit->isAlive()) - return pUnit; - } - - return me; - } - - void UpdateAI(const uint32 /*diff*/) - { - if (pInstance && !pInstance->GetData(TYPE_MOROES)) - EnterEvadeMode(); - - DoMeleeAttackIfReady(); - } -}; - -#define SPELL_MANABURN 29405 -#define SPELL_MINDFLY 29570 -#define SPELL_SWPAIN 34441 -#define SPELL_SHADOWFORM 29406 - -struct boss_baroness_dorothea_millstipeAI : public boss_moroes_guestAI -{ - //Shadow Priest - boss_baroness_dorothea_millstipeAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 ManaBurn_Timer; - uint32 MindFlay_Timer; - uint32 ShadowWordPain_Timer; - - void Reset() - { - ManaBurn_Timer = 7000; - MindFlay_Timer = 1000; - ShadowWordPain_Timer = 6000; - - DoCast(me, SPELL_SHADOWFORM, true); - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (MindFlay_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MINDFLY); - MindFlay_Timer = 12000; // 3 sec channeled - } else MindFlay_Timer -= diff; - - if (ManaBurn_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (pTarget->getPowerType() == POWER_MANA) - DoCast(pTarget, SPELL_MANABURN); - ManaBurn_Timer = 5000; // 3 sec cast - } else ManaBurn_Timer -= diff; - - if (ShadowWordPain_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, SPELL_SWPAIN); - ShadowWordPain_Timer = 7000; - } - } else ShadowWordPain_Timer -= diff; - } -}; - -#define SPELL_HAMMEROFJUSTICE 13005 -#define SPELL_JUDGEMENTOFCOMMAND 29386 -#define SPELL_SEALOFCOMMAND 29385 - -struct boss_baron_rafe_dreugerAI : public boss_moroes_guestAI -{ - //Retr Pally - boss_baron_rafe_dreugerAI(Creature *c) : boss_moroes_guestAI(c){} - - uint32 HammerOfJustice_Timer; - uint32 SealOfCommand_Timer; - uint32 JudgementOfCommand_Timer; - - void Reset() - { - HammerOfJustice_Timer = 1000; - SealOfCommand_Timer = 7000; - JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (SealOfCommand_Timer <= diff) - { - DoCast(me, SPELL_SEALOFCOMMAND); - SealOfCommand_Timer = 32000; - JudgementOfCommand_Timer = 29000; - } else SealOfCommand_Timer -= diff; - - if (JudgementOfCommand_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_JUDGEMENTOFCOMMAND); - JudgementOfCommand_Timer = SealOfCommand_Timer + 29000; - } else JudgementOfCommand_Timer -= diff; - - if (HammerOfJustice_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMMEROFJUSTICE); - HammerOfJustice_Timer = 12000; - } else HammerOfJustice_Timer -= diff; - } -}; - -#define SPELL_DISPELMAGIC 15090 //Self or other guest+Moroes -#define SPELL_GREATERHEAL 29564 //Self or other guest+Moroes -#define SPELL_HOLYFIRE 29563 -#define SPELL_PWSHIELD 29408 - -struct boss_lady_catriona_von_indiAI : public boss_moroes_guestAI -{ - //Holy Priest - boss_lady_catriona_von_indiAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 DispelMagic_Timer; - uint32 GreaterHeal_Timer; - uint32 HolyFire_Timer; - uint32 PowerWordShield_Timer; - - void Reset() - { - DispelMagic_Timer = 11000; - GreaterHeal_Timer = 1500; - HolyFire_Timer = 5000; - PowerWordShield_Timer = 1000; - - AcquireGUID(); - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (PowerWordShield_Timer <= diff) - { - DoCast(me, SPELL_PWSHIELD); - PowerWordShield_Timer = 15000; - } else PowerWordShield_Timer -= diff; - - if (GreaterHeal_Timer <= diff) - { - Unit *pTarget = SelectGuestTarget(); - - DoCast(pTarget, SPELL_GREATERHEAL); - GreaterHeal_Timer = 17000; - } else GreaterHeal_Timer -= diff; - - if (HolyFire_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HOLYFIRE); - HolyFire_Timer = 22000; - } else HolyFire_Timer -= diff; - - if (DispelMagic_Timer <= diff) - { - if (Unit *pTarget = RAND(SelectGuestTarget(), SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))) - DoCast(pTarget, SPELL_DISPELMAGIC); - - DispelMagic_Timer = 25000; - } else DispelMagic_Timer -= diff; - } -}; - -#define SPELL_CLEANSE 29380 //Self or other guest+Moroes -#define SPELL_GREATERBLESSOFMIGHT 29381 //Self or other guest+Moroes -#define SPELL_HOLYLIGHT 29562 //Self or other guest+Moroes -#define SPELL_DIVINESHIELD 41367 - -struct boss_lady_keira_berrybuckAI : public boss_moroes_guestAI -{ - //Holy Pally - boss_lady_keira_berrybuckAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 Cleanse_Timer; - uint32 GreaterBless_Timer; - uint32 HolyLight_Timer; - uint32 DivineShield_Timer; - - void Reset() - { - Cleanse_Timer = 13000; - GreaterBless_Timer = 1000; - HolyLight_Timer = 7000; - DivineShield_Timer = 31000; - - AcquireGUID(); - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (DivineShield_Timer <= diff) - { - DoCast(me, SPELL_DIVINESHIELD); - DivineShield_Timer = 31000; - } else DivineShield_Timer -= diff; - - if (HolyLight_Timer <= diff) - { - Unit *pTarget = SelectGuestTarget(); - - DoCast(pTarget, SPELL_HOLYLIGHT); - HolyLight_Timer = 10000; - } else HolyLight_Timer -= diff; - - if (GreaterBless_Timer <= diff) - { - Unit *pTarget = SelectGuestTarget(); - - DoCast(pTarget, SPELL_GREATERBLESSOFMIGHT); - - GreaterBless_Timer = 50000; - } else GreaterBless_Timer -= diff; - - if (Cleanse_Timer <= diff) - { - Unit *pTarget = SelectGuestTarget(); - - DoCast(pTarget, SPELL_CLEANSE); - - Cleanse_Timer = 10000; - } else Cleanse_Timer -= diff; - } -}; - -#define SPELL_HAMSTRING 9080 -#define SPELL_MORTALSTRIKE 29572 -#define SPELL_WHIRLWIND 29573 - -struct boss_lord_robin_darisAI : public boss_moroes_guestAI -{ - //Arms Warr - boss_lord_robin_darisAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 Hamstring_Timer; - uint32 MortalStrike_Timer; - uint32 WhirlWind_Timer; - - void Reset() - { - Hamstring_Timer = 7000; - MortalStrike_Timer = 10000; - WhirlWind_Timer = 21000; - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (Hamstring_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - Hamstring_Timer = 12000; - } else Hamstring_Timer -= diff; - - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = 18000; - } else MortalStrike_Timer -= diff; - - if (WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - WhirlWind_Timer = 21000; - } else WhirlWind_Timer -= diff; - } -}; - -#define SPELL_DISARM 8379 -#define SPELL_HEROICSTRIKE 29567 -#define SPELL_SHIELDBASH 11972 -#define SPELL_SHIELDWALL 29390 - -struct boss_lord_crispin_ferenceAI : public boss_moroes_guestAI -{ - //Arms Warr - boss_lord_crispin_ferenceAI(Creature *c) : boss_moroes_guestAI(c) {} - - uint32 Disarm_Timer; - uint32 HeroicStrike_Timer; - uint32 ShieldBash_Timer; - uint32 ShieldWall_Timer; - - void Reset() - { - Disarm_Timer = 6000; - HeroicStrike_Timer = 10000; - ShieldBash_Timer = 8000; - ShieldWall_Timer = 4000; - - boss_moroes_guestAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_moroes_guestAI::UpdateAI(diff); - - if (Disarm_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DISARM); - Disarm_Timer = 12000; - } else Disarm_Timer -= diff; - - if (HeroicStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HEROICSTRIKE); - HeroicStrike_Timer = 10000; - } else HeroicStrike_Timer -= diff; - - if (ShieldBash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHIELDBASH); - ShieldBash_Timer = 13000; - } else ShieldBash_Timer -= diff; - - if (ShieldWall_Timer <= diff) - { - DoCast(me, SPELL_SHIELDWALL); - ShieldWall_Timer = 21000; - } else ShieldWall_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_moroes(Creature* pCreature) -{ - return new boss_moroesAI (pCreature); -} - -CreatureAI* GetAI_baroness_dorothea_millstipe(Creature* pCreature) -{ - return new boss_baroness_dorothea_millstipeAI (pCreature); -} - -CreatureAI* GetAI_baron_rafe_dreuger(Creature* pCreature) -{ - return new boss_baron_rafe_dreugerAI (pCreature); -} - -CreatureAI* GetAI_lady_catriona_von_indi(Creature* pCreature) -{ - return new boss_lady_catriona_von_indiAI (pCreature); -} - -CreatureAI* GetAI_lady_keira_berrybuck(Creature* pCreature) -{ - return new boss_lady_keira_berrybuckAI (pCreature); -} - -CreatureAI* GetAI_lord_robin_daris(Creature* pCreature) -{ - return new boss_lord_robin_darisAI (pCreature); -} - -CreatureAI* GetAI_lord_crispin_ference(Creature* pCreature) -{ - return new boss_lord_crispin_ferenceAI (pCreature); -} - -void AddSC_boss_moroes() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_moroes"; - newscript->GetAI = &GetAI_boss_moroes; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_baroness_dorothea_millstipe"; - newscript->GetAI = &GetAI_baroness_dorothea_millstipe; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_baron_rafe_dreuger"; - newscript->GetAI = &GetAI_baron_rafe_dreuger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lady_catriona_von_indi"; - newscript->GetAI = &GetAI_lady_catriona_von_indi; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lady_keira_berrybuck"; - newscript->GetAI = &GetAI_lady_keira_berrybuck; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_robin_daris"; - newscript->GetAI = &GetAI_lord_robin_daris; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_crispin_ference"; - newscript->GetAI = &GetAI_lord_crispin_ference; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp deleted file mode 100644 index 004f1902bfc..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_netherspite.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Netherspite -SD%Complete: 90 -SDComment: Not sure about timing and portals placing -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define EMOTE_PHASE_PORTAL -1532089 -#define EMOTE_PHASE_BANISH -1532090 - -#define SPELL_NETHERBURN_AURA 30522 -#define SPELL_VOIDZONE 37063 -#define SPELL_NETHER_INFUSION 38688 -#define SPELL_NETHERBREATH 38523 -#define SPELL_BANISH_VISUAL 39833 -#define SPELL_BANISH_ROOT 42716 -#define SPELL_EMPOWERMENT 38549 -#define SPELL_NETHERSPITE_ROAR 38684 - -const float PortalCoord[3][3] = -{ - {-11195.353516, -1613.237183, 278.237258}, // Left side - {-11137.846680, -1685.607422, 278.239258}, // Right side - {-11094.493164, -1591.969238, 279.949188} // Back side -}; - -enum Netherspite_Portal{ - RED_PORTAL = 0, // Perseverence - GREEN_PORTAL = 1, // Serenity - BLUE_PORTAL = 2 // Dominance -}; - -const uint32 PortalID[3] = {17369, 17367, 17368}; -const uint32 PortalVisual[3] = {30487,30490,30491}; -const uint32 PortalBeam[3] = {30465,30464,30463}; -const uint32 PlayerBuff[3] = {30421,30422,30423}; -const uint32 NetherBuff[3] = {30466,30467,30468}; -const uint32 PlayerDebuff[3] = {38637,38638,38639}; - -struct boss_netherspiteAI : public ScriptedAI -{ - boss_netherspiteAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - - for (int i=0; i<3; ++i) - { - PortalGUID[i] = 0; - BeamTarget[i] = 0; - BeamerGUID[i] = 0; - } - // need core fix - for (int i=0; i<3; ++i) - { - if (SpellEntry *spell = (SpellEntry*)GetSpellStore()->LookupEntry(PlayerBuff[i])) - spell->AttributesEx |= SPELL_ATTR_EX_NEGATIVE; - } - } - - ScriptedInstance* pInstance; - - bool PortalPhase; - bool Berserk; - uint32 PhaseTimer; // timer for phase switching - uint32 VoidZoneTimer; - uint32 NetherInfusionTimer; // berserking timer - uint32 NetherbreathTimer; - uint32 EmpowermentTimer; - uint32 PortalTimer; // timer for beam checking - uint64 PortalGUID[3]; // guid's of portals - uint64 BeamerGUID[3]; // guid's of auxiliary beaming portals - uint64 BeamTarget[3]; // guid's of portals' current targets - - bool IsBetween(WorldObject* u1, WorldObject *pTarget, WorldObject* u2) // the in-line checker - { - if (!u1 || !u2 || !pTarget) - return false; - - float xn, yn, xp, yp, xh, yh; - xn = u1->GetPositionX(); - yn = u1->GetPositionY(); - xp = u2->GetPositionX(); - yp = u2->GetPositionY(); - xh = pTarget->GetPositionX(); - yh = pTarget->GetPositionY(); - - // check if target is between (not checking distance from the beam yet) - if (dist(xn,yn,xh,yh) >= dist(xn,yn,xp,yp) || dist(xp,yp,xh,yh) >= dist(xn,yn,xp,yp)) - return false; - // check distance from the beam - return (abs((xn-xp)*yh+(yp-yn)*xh-xn*yp+xp*yn)/dist(xn,yn,xp,yp) < 1.5f); - } - - float dist(float xa, float ya, float xb, float yb) // auxiliary method for distance - { - return sqrt((xa-xb)*(xa-xb) + (ya-yb)*(ya-yb)); - } - - void Reset() - { - Berserk = false; - NetherInfusionTimer = 540000; - VoidZoneTimer = 15000; - NetherbreathTimer = 3000; - - HandleDoors(true); - DestroyPortals(); - } - - void SummonPortals() - { - uint8 r = rand()%4; - uint8 pos[3]; - pos[RED_PORTAL] = (r%2 ? (r>1 ? 2: 1): 0); - pos[GREEN_PORTAL] = (r%2 ? 0: (r>1 ? 2: 1)); - pos[BLUE_PORTAL] = (r>1 ? 1: 2); // Blue Portal not on the left side (0) - - for (int i=0; i<3; ++i) - if (Creature *portal = me->SummonCreature(PortalID[i],PortalCoord[pos[i]][0],PortalCoord[pos[i]][1],PortalCoord[pos[i]][2],0,TEMPSUMMON_TIMED_DESPAWN,60000)) - { - PortalGUID[i] = portal->GetGUID(); - portal->AddAura(PortalVisual[i], portal); - } - } - - void DestroyPortals() - { - for (int i=0; i<3; ++i) - { - if (Creature *portal = Unit::GetCreature(*me, PortalGUID[i])) - portal->DisappearAndDie(); - if (Creature *portal = Unit::GetCreature(*me, BeamerGUID[i])) - portal->DisappearAndDie(); - PortalGUID[i] = 0; - BeamTarget[i] = 0; - } - } - - void UpdatePortals() // Here we handle the beams' behavior - { - for (int j=0; j<3; ++j) // j = color - if (Creature *portal = Unit::GetCreature(*me, PortalGUID[j])) - { - // the one who's been casted upon before - Unit *current = Unit::GetUnit(*portal, BeamTarget[j]); - // temporary store for the best suitable beam reciever - Unit *pTarget = me; - - if (Map* map = me->GetMap()) - { - Map::PlayerList const& players = map->GetPlayers(); - - // get the best suitable target - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player* p = i->getSource(); - if (p && p->isAlive() // alive - && (!pTarget || pTarget->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best - && !p->HasAura(PlayerDebuff[j],0) // not exhausted - && !p->HasAura(PlayerBuff[(j+1)%3],0) // not on another beam - && !p->HasAura(PlayerBuff[(j+2)%3],0) - && IsBetween(me, p, portal)) // on the beam - pTarget = p; - } - } - // buff the target - if (pTarget->GetTypeId() == TYPEID_PLAYER) - pTarget->AddAura(PlayerBuff[j], pTarget); - else - pTarget->AddAura(NetherBuff[j], pTarget); - // cast visual beam on the chosen target if switched - // simple target switching isn't working -> using BeamerGUID to cast (workaround) - if (!current || pTarget != current) - { - BeamTarget[j] = pTarget->GetGUID(); - // remove currently beaming portal - if (Creature *beamer = Unit::GetCreature(*portal, BeamerGUID[j])) - { - beamer->CastSpell(pTarget, PortalBeam[j], false); - beamer->DisappearAndDie(); - BeamerGUID[j] = 0; - } - // create new one and start beaming on the target - if (Creature *beamer = portal->SummonCreature(PortalID[j],portal->GetPositionX(),portal->GetPositionY(),portal->GetPositionZ(),portal->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,60000)) - { - beamer->CastSpell(pTarget, PortalBeam[j], false); - BeamerGUID[j] = beamer->GetGUID(); - } - } - // aggro target if Red Beam - if (j == RED_PORTAL && me->getVictim() != pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - me->getThreatManager().addThreat(pTarget, 100000.0f+DoGetThreat(me->getVictim())); - } - } - - void SwitchToPortalPhase() - { - me->RemoveAurasDueToSpell(SPELL_BANISH_ROOT); - me->RemoveAurasDueToSpell(SPELL_BANISH_VISUAL); - SummonPortals(); - PhaseTimer = 60000; - PortalPhase = true; - PortalTimer = 10000; - EmpowermentTimer = 10000; - DoScriptText(EMOTE_PHASE_PORTAL,me); - } - - void SwitchToBanishPhase() - { - me->RemoveAurasDueToSpell(SPELL_EMPOWERMENT); - me->RemoveAurasDueToSpell(SPELL_NETHERBURN_AURA); - DoCast(me, SPELL_BANISH_VISUAL, true); - DoCast(me, SPELL_BANISH_ROOT, true); - DestroyPortals(); - PhaseTimer = 30000; - PortalPhase = false; - DoScriptText(EMOTE_PHASE_BANISH,me); - - for (int i=0; i<3; ++i) - me->RemoveAurasDueToSpell(NetherBuff[i]); - } - - void HandleDoors(bool open) // Massive Door switcher - { - if (GameObject *Door = GameObject::GetGameObject(*me, pInstance ? pInstance->GetData64(DATA_GO_MASSIVE_DOOR) : 0)) - Door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY); - } - - void Aggro(Unit * /*who*/) - { - HandleDoors(false); - SwitchToPortalPhase(); - } - - void JustDied(Unit* /*killer*/) - { - HandleDoors(true); - DestroyPortals(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Void Zone - if (VoidZoneTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,45,true),SPELL_VOIDZONE,true); - VoidZoneTimer = 15000; - } else VoidZoneTimer -= diff; - - // NetherInfusion Berserk - if (!Berserk && NetherInfusionTimer <= diff) - { - me->AddAura(SPELL_NETHER_INFUSION, me); - DoCast(me, SPELL_NETHERSPITE_ROAR); - Berserk = true; - } else NetherInfusionTimer -= diff; - - if (PortalPhase) // PORTAL PHASE - { - // Distribute beams and buffs - if (PortalTimer <= diff) - { - UpdatePortals(); - PortalTimer = 1000; - } else PortalTimer -= diff; - - // Empowerment & Nether Burn - if (EmpowermentTimer <= diff) - { - DoCast(me, SPELL_EMPOWERMENT); - me->AddAura(SPELL_NETHERBURN_AURA, me); - EmpowermentTimer = 90000; - } else EmpowermentTimer -= diff; - - if (PhaseTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - SwitchToBanishPhase(); - return; - } - } else PhaseTimer -= diff; - } - else // BANISH PHASE - { - // Netherbreath - if (NetherbreathTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,40,true)) - DoCast(pTarget, SPELL_NETHERBREATH); - NetherbreathTimer = urand(5000,7000); - } else NetherbreathTimer -= diff; - - if (PhaseTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - SwitchToPortalPhase(); - return; - } - } else PhaseTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_netherspite(Creature *pCreature) -{ - return new boss_netherspiteAI(pCreature); -} - -void AddSC_boss_netherspite() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_netherspite"; - newscript->GetAI = GetAI_boss_netherspite; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp deleted file mode 100644 index 2e8b6f51317..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_nightbane.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Nightbane -SD%Complete: 80 -SDComment: SDComment: Timers may incorrect -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -//phase 1 -#define SPELL_BELLOWING_ROAR 39427 -#define SPELL_CHARRED_EARTH 30129 -#define SPELL_DISTRACTING_ASH 30130 -#define SPELL_SMOLDERING_BREATH 30210 -#define SPELL_TAIL_SWEEP 25653 -//phase 2 -#define SPELL_RAIN_OF_BONES 37098 -#define SPELL_SMOKING_BLAST 37057 -#define SPELL_FIREBALL_BARRAGE 30282 -#define SPELL_SEARING_CINDERS 30127 -#define SPELL_SUMMON_SKELETON 30170 - -#define EMOTE_SUMMON "An ancient being awakens in the distance..." -#define YELL_AGGRO "What fools! I shall bring a quick end to your suffering!" -#define YELL_FLY_PHASE "Miserable vermin. I shall exterminate you from the air!" -#define YELL_LAND_PHASE_1 "Enough! I shall land and crush you myself!" -#define YELL_LAND_PHASE_2 "Insects! Let me show you my strength up close!" -#define EMOTE_BREATH "takes a deep breath." - -float IntroWay[8][3] = -{ - {-11053.37,-1794.48,149}, - {-11141.07,-1841.40,125}, - {-11187.28,-1890.23,125}, - {-11189.20,-1931.25,125}, - {-11153.76,-1948.93,125}, - {-11128.73,-1929.75,125}, - {-11140 , -1915 ,122}, - {-11163 , -1903 ,91.473} -}; - -struct boss_nightbaneAI : public ScriptedAI -{ - boss_nightbaneAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = true; - } - - ScriptedInstance* pInstance; - - uint32 Phase; - - bool RainBones; - bool Skeletons; - - uint32 BellowingRoarTimer; - uint32 CharredEarthTimer; - uint32 DistractingAshTimer; - uint32 SmolderingBreathTimer; - uint32 TailSweepTimer; - uint32 RainofBonesTimer; - uint32 SmokingBlastTimer; - uint32 FireballBarrageTimer; - uint32 SearingCindersTimer; - - uint32 FlyCount; - uint32 FlyTimer; - - bool Intro; - bool Flying; - bool Movement; - - uint32 WaitTimer; - uint32 MovePhase; - - void Reset() - { - BellowingRoarTimer = 30000; - CharredEarthTimer = 15000; - DistractingAshTimer = 20000; - SmolderingBreathTimer = 10000; - TailSweepTimer = 12000; - RainofBonesTimer = 10000; - SmokingBlastTimer = 20000; - FireballBarrageTimer = 13000; - SearingCindersTimer = 14000; - WaitTimer = 1000; - - Phase =1; - FlyCount = 0; - MovePhase = 0; - - me->SetSpeed(MOVE_RUN, 2.0f); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->setActive(true); - - if (pInstance) - { - if (pInstance->GetData(TYPE_NIGHTBANE) == DONE || pInstance->GetData(TYPE_NIGHTBANE) == IN_PROGRESS) - me->DisappearAndDie(); - else - pInstance->SetData(TYPE_NIGHTBANE, NOT_STARTED); - } - - HandleTerraceDoors(true); - - Flying = false; - Movement = false; - - if (!Intro) - { - me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0); - me->GetMotionMaster()->MoveTargetedHome(); - } - } - - void HandleTerraceDoors(bool open) - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_1), open); - pInstance->HandleGameObject(pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_2), open); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(TYPE_NIGHTBANE, IN_PROGRESS); - - HandleTerraceDoors(false); - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - } - - void AttackStart(Unit* who) - { - if (!Intro && !Flying) - ScriptedAI::AttackStart(who); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_NIGHTBANE, DONE); - - HandleTerraceDoors(true); - } - - void MoveInLineOfSight(Unit *who) - { - if (!Intro && !Flying) - ScriptedAI::MoveInLineOfSight(who); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (Intro) - { - if (id >= 8) - { - Intro = false; - me->SetHomePosition(IntroWay[7][0],IntroWay[7][1],IntroWay[7][2],0); - return; - } - - WaitTimer = 1; - } - - if (Flying) - { - if (id == 0) - { - me->MonsterTextEmote(EMOTE_BREATH, 0, true); - Flying = false; - Phase = 2; - return; - } - - if (id == 3) - { - MovePhase = 4; - WaitTimer = 1; - return; - } - - if (id == 8) - { - Flying = false; - Phase = 1; - Movement = true; - return; - } - - WaitTimer = 1; - } - } - - void JustSummoned(Creature *summoned) - { - summoned->AI()->AttackStart(me->getVictim()); - } - - void TakeOff() - { - me->MonsterYell(YELL_FLY_PHASE, LANG_UNIVERSAL, NULL); - - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - (*me).GetMotionMaster()->Clear(false); - (*me).GetMotionMaster()->MovePoint(0,IntroWay[2][0],IntroWay[2][1],IntroWay[2][2]); - - Flying = true; - - FlyTimer = urand(45000,60000); //timer wrong between 45 and 60 seconds - ++FlyCount; - - RainofBonesTimer = 5000; //timer wrong (maybe) - RainBones = false; - Skeletons = false; - } - - void UpdateAI(const uint32 diff) - { - /* The timer for this was never setup apparently, not sure if the code works properly: - if (WaitTimer <= diff) - { - if (Intro) - { - if (MovePhase >= 7) - { - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); - } - else - { - me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]); - ++MovePhase; - } - } - if (Flying) - { - if (MovePhase >= 7) - { - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - me->GetMotionMaster()->MovePoint(8,IntroWay[7][0],IntroWay[7][1],IntroWay[7][2]); - } - else - { - me->GetMotionMaster()->MovePoint(MovePhase,IntroWay[MovePhase][0],IntroWay[MovePhase][1],IntroWay[MovePhase][2]); - ++MovePhase; - } - } - - WaitTimer = 0; - } else WaitTimer -= diff; - */ - - if (!UpdateVictim()) - return; - - if (Flying) - return; - - // Phase 1 "GROUND FIGHT" - if (Phase == 1) - { - if (Movement) - { - DoStartMovement(me->getVictim()); - Movement = false; - } - - if (BellowingRoarTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); - BellowingRoarTimer = urand(30000,40000); - } else BellowingRoarTimer -= diff; - - if (SmolderingBreathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SMOLDERING_BREATH); - SmolderingBreathTimer = 20000; - } else SmolderingBreathTimer -= diff; - - if (CharredEarthTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CHARRED_EARTH); - CharredEarthTimer = 20000; - } else CharredEarthTimer -= diff; - - if (TailSweepTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (!me->HasInArc(M_PI, pTarget)) - DoCast(pTarget, SPELL_TAIL_SWEEP); - TailSweepTimer = 15000; - } else TailSweepTimer -= diff; - - if (SearingCindersTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SEARING_CINDERS); - SearingCindersTimer = 10000; - } else SearingCindersTimer -= diff; - - uint32 Prozent; - Prozent = (me->GetHealth()*100) / me->GetMaxHealth(); - - if (Prozent < 75 && FlyCount == 0) // first take off 75% - TakeOff(); - - if (Prozent < 50 && FlyCount == 1) // secound take off 50% - TakeOff(); - - if (Prozent < 25 && FlyCount == 2) // third take off 25% - TakeOff(); - - DoMeleeAttackIfReady(); - } - - //Phase 2 "FLYING FIGHT" - if (Phase == 2) - { - if (!RainBones) - { - if (!Skeletons) - { - for (uint8 i = 0; i <= 3; ++i) - { - DoCast(me->getVictim(), SPELL_SUMMON_SKELETON); - Skeletons = true; - } - } - - if (RainofBonesTimer < diff && !RainBones) // only once at the beginning of phase 2 - { - DoCast(me->getVictim(), SPELL_RAIN_OF_BONES); - RainBones = true; - SmokingBlastTimer = 20000; - } else RainofBonesTimer -= diff; - - if (DistractingAshTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_DISTRACTING_ASH); - DistractingAshTimer = 2000; //timer wrong - } else DistractingAshTimer -= diff; - } - - if (RainBones) - { - if (SmokingBlastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SMOKING_BLAST); - SmokingBlastTimer = 1500; //timer wrong - } else SmokingBlastTimer -= diff; - } - - if (FireballBarrageTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_FARTHEST, 0)) - DoCast(pTarget, SPELL_FIREBALL_BARRAGE); - FireballBarrageTimer = 20000; - } else FireballBarrageTimer -= diff; - - if (FlyTimer <= diff) //landing - { - me->MonsterYell(RAND(*YELL_LAND_PHASE_1,*YELL_LAND_PHASE_2), LANG_UNIVERSAL, NULL); - - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(3,IntroWay[3][0],IntroWay[3][1],IntroWay[3][2]); - - Flying = true; - } else FlyTimer -= diff; - } - } -}; - -CreatureAI* GetAI_boss_nightbane(Creature* pCreature) -{ - return new boss_nightbaneAI (pCreature); -} - -void AddSC_boss_nightbane() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nightbane"; - newscript->GetAI = &GetAI_boss_nightbane; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp deleted file mode 100644 index 1071eae78a0..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_prince_malchezaar.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Prince_Malchezzar -SD%Complete: 100 -SDComment: -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define SAY_AGGRO -1532091 -#define SAY_AXE_TOSS1 -1532092 -#define SAY_AXE_TOSS2 -1532093 -#define SAY_SPECIAL1 -1532094 -#define SAY_SPECIAL2 -1532095 -#define SAY_SPECIAL3 -1532096 -#define SAY_SLAY1 -1532097 -#define SAY_SLAY2 -1532098 -#define SAY_SLAY3 -1532099 -#define SAY_SUMMON1 -1532100 -#define SAY_SUMMON2 -1532101 -#define SAY_DEATH -1532102 - -// 18 Coordinates for Infernal spawns -struct InfernalPoint -{ - float x,y; -}; - -#define INFERNAL_Z 275.5 - -static InfernalPoint InfernalPoints[] = -{ - {-10922.8, -1985.2}, - {-10916.2, -1996.2}, - {-10932.2, -2008.1}, - {-10948.8, -2022.1}, - {-10958.7, -1997.7}, - {-10971.5, -1997.5}, - {-10990.8, -1995.1}, - {-10989.8, -1976.5}, - {-10971.6, -1973.0}, - {-10955.5, -1974.0}, - {-10939.6, -1969.8}, - {-10958.0, -1952.2}, - {-10941.7, -1954.8}, - {-10943.1, -1988.5}, - {-10948.8, -2005.1}, - {-10984.0, -2019.3}, - {-10932.8, -1979.6}, - {-10935.7, -1996.0} -}; - -#define TOTAL_INFERNAL_POINTS 18 - -//Enfeeble is supposed to reduce hp to 1 and then heal player back to full when it ends -//Along with reducing healing and regen while enfeebled to 0% -//This spell effect will only reduce healing - -#define SPELL_ENFEEBLE 30843 //Enfeeble during phase 1 and 2 -#define SPELL_ENFEEBLE_EFFECT 41624 - -#define SPELL_SHADOWNOVA 30852 //Shadownova used during all phases -#define SPELL_SW_PAIN 30854 //Shadow word pain during phase 1 and 3 (different targeting rules though) -#define SPELL_THRASH_PASSIVE 12787 //Extra attack chance during phase 2 -#define SPELL_SUNDER_ARMOR 30901 //Sunder armor during phase 2 -#define SPELL_THRASH_AURA 12787 //Passive proc chance for thrash -#define SPELL_EQUIP_AXES 30857 //Visual for axe equiping -#define SPELL_AMPLIFY_DAMAGE 39095 //Amplifiy during phase 3 -#define SPELL_CLEAVE 30131 //Same as Nightbane. -#define SPELL_HELLFIRE 30859 //Infenals' hellfire aura -#define NETHERSPITE_INFERNAL 17646 //The netherspite infernal creature -#define MALCHEZARS_AXE 17650 //Malchezar's axes (creatures), summoned during phase 3 - -#define INFERNAL_MODEL_INVISIBLE 11686 //Infernal Effects -#define SPELL_INFERNAL_RELAY 30834 - -#define EQUIP_ID_AXE 33542 //Axes info - -//---------Infernal code first -struct netherspite_infernalAI : public ScriptedAI -{ - netherspite_infernalAI(Creature *c) : ScriptedAI(c) , - malchezaar(0), HellfireTimer(0), CleanupTimer(0), point(NULL) {} - - uint32 HellfireTimer; - uint32 CleanupTimer; - uint32 malchezaar; - InfernalPoint *point; - - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (HellfireTimer) - if (HellfireTimer <= diff) - { - DoCast(me, SPELL_HELLFIRE); - HellfireTimer = 0; - } - else HellfireTimer -= diff; - - if (CleanupTimer) - if (CleanupTimer <= diff) - { - Cleanup(); - CleanupTimer = 0; - } else CleanupTimer -= diff; - } - - void KilledUnit(Unit *who) - { - Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar); - if (pMalchezaar) - CAST_CRE(pMalchezaar)->AI()->KilledUnit(who); - } - - void SpellHit(Unit * /*who*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_INFERNAL_RELAY) - { - me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - HellfireTimer = 4000; - CleanupTimer = 170000; - } - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != malchezaar) - damage = 0; - } - - void Cleanup(); //below ... -}; - -struct boss_malchezaarAI : public ScriptedAI -{ - boss_malchezaarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 EnfeebleTimer; - uint32 EnfeebleResetTimer; - uint32 ShadowNovaTimer; - uint32 SWPainTimer; - uint32 SunderArmorTimer; - uint32 AmplifyDamageTimer; - uint32 Cleave_Timer; - uint32 InfernalTimer; - uint32 AxesTargetSwitchTimer; - uint32 InfernalCleanupTimer; - - std::vector infernals; - std::vector positions; - - uint64 axes[2]; - uint64 enfeeble_targets[5]; - uint64 enfeeble_health[5]; - - uint32 phase; - - void Reset() - { - AxesCleanup(); - ClearWeapons(); - InfernalCleanup(); - positions.clear(); - - for (uint8 i = 0; i < 5; ++i) - enfeeble_targets[i] = 0; - - for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i) - positions.push_back(&InfernalPoints[i]); - - EnfeebleTimer = 30000; - EnfeebleResetTimer = 38000; - ShadowNovaTimer = 35500; - SWPainTimer = 20000; - AmplifyDamageTimer = 5000; - Cleave_Timer = 8000; - InfernalTimer = 45000; - InfernalCleanupTimer = 47000; - AxesTargetSwitchTimer = urand(7500,20000); - SunderArmorTimer = urand(5000,10000); - phase = 1; - - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - AxesCleanup(); - ClearWeapons(); - InfernalCleanup(); - positions.clear(); - - for (uint8 i = 0; i < TOTAL_INFERNAL_POINTS; ++i) - positions.push_back(&InfernalPoints[i]); - - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), true); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_NETHER_DOOR), false); // Open the door leading further in - } - - void InfernalCleanup() - { - //Infernal Cleanup - for (std::vector::const_iterator itr = infernals.begin(); itr != infernals.end(); ++itr) - if (Unit *pInfernal = Unit::GetUnit(*me, *itr)) - if (pInfernal->isAlive()) - { - pInfernal->SetVisibility(VISIBILITY_OFF); - pInfernal->setDeathState(JUST_DIED); - } - - infernals.clear(); - } - - void AxesCleanup() - { - for (uint8 i = 0; i < 2; ++i) - { - Unit *axe = Unit::GetUnit(*me, axes[i]); - if (axe && axe->isAlive()) - axe->Kill(axe); - axes[i] = 0; - } - } - - void ClearWeapons() - { - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - - //damage - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg); - me->UpdateDamagePhysical(BASE_ATTACK); - } - - void EnfeebleHealthEffect() - { - const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT); - if (!info) - return; - - std::list t_list = me->getThreatManager().getThreatList(); - std::vector targets; - - if (!t_list.size()) - return; - - //begin + 1, so we don't target the one with the highest threat - std::list::const_iterator itr = t_list.begin(); - std::advance(itr, 1); - for (; itr != t_list.end(); ++itr) //store the threat list in a different container - if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - if (pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - targets.push_back(pTarget); - - //cut down to size if we have more than 5 targets - while (targets.size() > 5) - targets.erase(targets.begin()+rand()%targets.size()); - - uint32 i = 0; - for (std::vector::const_iterator iter = targets.begin(); iter != targets.end(); ++iter, ++i) - if (Unit *pTarget = *iter) - { - enfeeble_targets[i] = pTarget->GetGUID(); - enfeeble_health[i] = pTarget->GetHealth(); - - pTarget->CastSpell(pTarget, SPELL_ENFEEBLE, true, 0, 0, me->GetGUID()); - pTarget->SetHealth(1); - } - } - - void EnfeebleResetHealth() - { - for (uint8 i = 0; i < 5; ++i) - { - Unit *pTarget = Unit::GetUnit(*me, enfeeble_targets[i]); - if (pTarget && pTarget->isAlive()) - pTarget->SetHealth(enfeeble_health[i]); - enfeeble_targets[i] = 0; - enfeeble_health[i] = 0; - } - } - - void SummonInfernal(const uint32 /*diff*/) - { - InfernalPoint *point = NULL; - Position pos; - if ((me->GetMapId() != 532) || positions.empty()) - me->GetRandomNearPosition(pos, 60); - else - { - std::vector::iterator itr = positions.begin()+rand()%positions.size(); - point = *itr; - positions.erase(itr); - pos.Relocate(point->x, point->y, INFERNAL_Z); - } - - Creature *Infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000); - - if (Infernal) - { - Infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE); - Infernal->setFaction(me->getFaction()); - if (point) - CAST_AI(netherspite_infernalAI, Infernal->AI())->point=point; - CAST_AI(netherspite_infernalAI, Infernal->AI())->malchezaar=me->GetGUID(); - - infernals.push_back(Infernal->GetGUID()); - DoCast(Infernal, SPELL_INFERNAL_RELAY); - } - - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (EnfeebleResetTimer && EnfeebleResetTimer <= diff) // Let's not forget to reset that - { - EnfeebleResetHealth(); - EnfeebleResetTimer = 0; - } else EnfeebleResetTimer -= diff; - - if (me->hasUnitState(UNIT_STAT_STUNNED)) // While shifting to phase 2 malchezaar stuns himself - return; - - if (me->GetUInt64Value(UNIT_FIELD_TARGET) != me->getVictim()->GetGUID()) - me->SetUInt64Value(UNIT_FIELD_TARGET, me->getVictim()->GetGUID()); - - if (phase == 1) - { - if ((me->GetHealth()*100) / me->GetMaxHealth() < 60) - { - me->InterruptNonMeleeSpells(false); - - phase = 2; - - //animation - DoCast(me, SPELL_EQUIP_AXES); - - //text - DoScriptText(SAY_AXE_TOSS1, me); - - //passive thrash aura - DoCast(me, SPELL_THRASH_AURA, true); - - //models - SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE); - - //damage - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg); - me->UpdateDamagePhysical(BASE_ATTACK); - - me->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg); - me->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg); - //Sigh, updating only works on main attack, do it manually .... - me->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg); - me->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg); - - me->SetAttackTime(OFF_ATTACK, (me->GetAttackTime(BASE_ATTACK)*150)/100); - } - } - else if (phase == 2) - { - if ((me->GetHealth()*100) / me->GetMaxHealth() < 30) - { - InfernalTimer = 15000; - - phase = 3; - - ClearWeapons(); - - //remove thrash - me->RemoveAurasDueToSpell(SPELL_THRASH_AURA); - - DoScriptText(SAY_AXE_TOSS2, me); - - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - for (uint8 i = 0; i < 2; ++i) - { - Creature *axe = me->SummonCreature(MALCHEZARS_AXE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); - if (axe) - { - axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - axe->setFaction(me->getFaction()); - axes[i] = axe->GetGUID(); - if (pTarget) - { - axe->AI()->AttackStart(pTarget); - //axe->getThreatManager().tauntApply(pTarget); //Taunt Apply and fade out does not work properly - // So we'll use a hack to add a lot of threat to our target - axe->AddThreat(pTarget, 10000000.0f); - } - } - } - - if (ShadowNovaTimer > 35000) - ShadowNovaTimer = EnfeebleTimer + 5000; - - return; - } - - if (SunderArmorTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDER_ARMOR); - SunderArmorTimer = urand(10000,18000); - - } else SunderArmorTimer -= diff; - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = urand(6000,12000); - - } else Cleave_Timer -= diff; - } - else - { - if (AxesTargetSwitchTimer <= diff) - { - AxesTargetSwitchTimer = urand(7500,20000); - - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Unit *axe = Unit::GetUnit(*me, axes[i])) - { - if (axe->getVictim()) - DoModifyThreatPercent(axe->getVictim(), -100); - if (pTarget) - axe->AddThreat(pTarget, 1000000.0f); - //axe->getThreatManager().tauntFadeOut(axe->getVictim()); - //axe->getThreatManager().tauntApply(pTarget); - } - } - } - } else AxesTargetSwitchTimer -= diff; - - if (AmplifyDamageTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_AMPLIFY_DAMAGE); - AmplifyDamageTimer = urand(20000,30000); - } else AmplifyDamageTimer -= diff; - } - - //Time for global and double timers - if (InfernalTimer <= diff) - { - SummonInfernal(diff); - InfernalTimer = phase == 3 ? 14500 : 44500; // 15 secs in phase 3, 45 otherwise - } else InfernalTimer -= diff; - - if (ShadowNovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWNOVA); - ShadowNovaTimer = phase == 3 ? 31000 : uint32(-1); - } else ShadowNovaTimer -= diff; - - if (phase != 2) - { - if (SWPainTimer <= diff) - { - Unit *pTarget = NULL; - if (phase == 1) - pTarget = me->getVictim(); // the tank - else // anyone but the tank - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - - if (pTarget) - DoCast(pTarget, SPELL_SW_PAIN); - - SWPainTimer = 20000; - } else SWPainTimer -= diff; - } - - if (phase != 3) - { - if (EnfeebleTimer <= diff) - { - EnfeebleHealthEffect(); - EnfeebleTimer = 30000; - ShadowNovaTimer = 5000; - EnfeebleResetTimer = 9000; - } else EnfeebleTimer -= diff; - } - - if (phase == 2) - DoMeleeAttacksIfReady(); - else - DoMeleeAttackIfReady(); - } - - void DoMeleeAttacksIfReady() - { - if (me->IsWithinMeleeRange(me->getVictim()) && !me->IsNonMeleeSpellCasted(false)) - { - //Check for base attack - if (me->isAttackReady() && me->getVictim()) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - //Check for offhand attack - if (me->isAttackReady(OFF_ATTACK) && me->getVictim()) - { - me->AttackerStateUpdate(me->getVictim(), OFF_ATTACK); - me->resetAttackTimer(OFF_ATTACK); - } - } - } - - void Cleanup(Creature *infernal, InfernalPoint *point) - { - for (std::vector::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr) - if (*itr == infernal->GetGUID()) - { - infernals.erase(itr); - break; - } - - positions.push_back(point); - } -}; - -void netherspite_infernalAI::Cleanup() -{ - Unit *pMalchezaar = Unit::GetUnit(*me, malchezaar); - - if (pMalchezaar && pMalchezaar->isAlive()) - CAST_AI(boss_malchezaarAI, CAST_CRE(pMalchezaar)->AI())->Cleanup(me, point); -} - -CreatureAI* GetAI_netherspite_infernal(Creature* pCreature) -{ - return new netherspite_infernalAI (pCreature); -} - -CreatureAI* GetAI_boss_malchezaar(Creature* pCreature) -{ - return new boss_malchezaarAI (pCreature); -} - -void AddSC_boss_malchezaar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_malchezaar"; - newscript->GetAI = &GetAI_boss_malchezaar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "netherspite_infernal"; - newscript->GetAI = &GetAI_netherspite_infernal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp deleted file mode 100644 index 394cff3ccc5..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_shade_of_aran.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Shade_of_Aran -SD%Complete: 95 -SDComment: Flame wreath missing cast animation, mods won't triggere. -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedSimpleAI.h" -#include "karazhan.h" -#include "GameObject.h" - -#define SAY_AGGRO1 -1532073 -#define SAY_AGGRO2 -1532074 -#define SAY_AGGRO3 -1532075 -#define SAY_FLAMEWREATH1 -1532076 -#define SAY_FLAMEWREATH2 -1532077 -#define SAY_BLIZZARD1 -1532078 -#define SAY_BLIZZARD2 -1532079 -#define SAY_EXPLOSION1 -1532080 -#define SAY_EXPLOSION2 -1532081 -#define SAY_DRINK -1532082 //Low Mana / AoE Pyroblast -#define SAY_ELEMENTALS -1532083 -#define SAY_KILL1 -1532084 -#define SAY_KILL2 -1532085 -#define SAY_TIMEOVER -1532086 -#define SAY_DEATH -1532087 -#define SAY_ATIESH -1532088 //Atiesh is equipped by a raid member - -//Spells -#define SPELL_FROSTBOLT 29954 -#define SPELL_FIREBALL 29953 -#define SPELL_ARCMISSLE 29955 -#define SPELL_CHAINSOFICE 29991 -#define SPELL_DRAGONSBREATH 29964 -#define SPELL_MASSSLOW 30035 -#define SPELL_FLAME_WREATH 29946 -#define SPELL_AOE_CS 29961 -#define SPELL_PLAYERPULL 32265 -#define SPELL_AEXPLOSION 29973 -#define SPELL_MASS_POLY 29963 -#define SPELL_BLINK_CENTER 29967 -#define SPELL_ELEMENTALS 29962 -#define SPELL_CONJURE 29975 -#define SPELL_DRINK 30024 -#define SPELL_POTION 32453 -#define SPELL_AOE_PYROBLAST 29978 - -//Creature Spells -#define SPELL_CIRCULAR_BLIZZARD 29951 //29952 is the REAL circular blizzard that leaves persistant blizzards that last for 10 seconds -#define SPELL_WATERBOLT 31012 -#define SPELL_SHADOW_PYRO 29978 - -//Creatures -#define CREATURE_WATER_ELEMENTAL 17167 -#define CREATURE_SHADOW_OF_ARAN 18254 -#define CREATURE_ARAN_BLIZZARD 17161 - -enum SuperSpell -{ - SUPER_FLAME = 0, - SUPER_BLIZZARD, - SUPER_AE, -}; - -struct boss_aranAI : public ScriptedAI -{ - boss_aranAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 SecondarySpellTimer; - uint32 NormalCastTimer; - uint32 SuperCastTimer; - uint32 BerserkTimer; - uint32 CloseDoorTimer; // Don't close the door right on aggro in case some people are still entering. - - uint8 LastSuperSpell; - - uint32 FlameWreathTimer; - uint32 FlameWreathCheckTime; - uint64 FlameWreathTarget[3]; - float FWTargPosX[3]; - float FWTargPosY[3]; - - uint32 CurrentNormalSpell; - uint32 ArcaneCooldown; - uint32 FireCooldown; - uint32 FrostCooldown; - - uint32 DrinkInturruptTimer; - - bool ElementalsSpawned; - bool Drinking; - bool DrinkInturrupted; - - void Reset() - { - SecondarySpellTimer = 5000; - NormalCastTimer = 0; - SuperCastTimer = 35000; - BerserkTimer = 720000; - CloseDoorTimer = 15000; - - LastSuperSpell = rand()%3; - - FlameWreathTimer = 0; - FlameWreathCheckTime = 0; - - CurrentNormalSpell = 0; - ArcaneCooldown = 0; - FireCooldown = 0; - FrostCooldown = 0; - - DrinkInturruptTimer = 10000; - - ElementalsSpawned = false; - Drinking = false; - DrinkInturrupted = false; - - if (pInstance) - { - // Not in progress - pInstance->SetData(TYPE_ARAN, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true); - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_ARAN, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), true); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - - if (pInstance) - { - pInstance->SetData(TYPE_ARAN, IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false); - } - } - - void FlameWreathEffect() - { - std::vector targets; - std::list t_list = me->getThreatManager().getThreatList(); - - if (!t_list.size()) - return; - - //store the threat list in a different container - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //only on alive players - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - targets.push_back(pTarget); - } - - //cut down to size if we have more than 3 targets - while (targets.size() > 3) - targets.erase(targets.begin()+rand()%targets.size()); - - uint32 i = 0; - for (std::vector::const_iterator itr = targets.begin(); itr!= targets.end(); ++itr) - { - if (*itr) - { - FlameWreathTarget[i] = (*itr)->GetGUID(); - FWTargPosX[i] = (*itr)->GetPositionX(); - FWTargPosY[i] = (*itr)->GetPositionY(); - DoCast((*itr), SPELL_FLAME_WREATH, true); - ++i; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (CloseDoorTimer) - { - if (CloseDoorTimer <= diff) - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_LIBRARY_DOOR), false); - CloseDoorTimer = 0; - } - } else CloseDoorTimer -= diff; - } - - //Cooldowns for casts - if (ArcaneCooldown) - { - if (ArcaneCooldown >= diff) - ArcaneCooldown -= diff; - else ArcaneCooldown = 0; - } - - if (FireCooldown) - { - if (FireCooldown >= diff) - FireCooldown -= diff; - else FireCooldown = 0; - } - - if (FrostCooldown) - { - if (FrostCooldown >= diff) - FrostCooldown -= diff; - else FrostCooldown = 0; - } - - if (!Drinking && me->GetMaxPower(POWER_MANA) && (me->GetPower(POWER_MANA)*100 / me->GetMaxPower(POWER_MANA)) < 20) - { - Drinking = true; - me->InterruptNonMeleeSpells(false); - - DoScriptText(SAY_DRINK, me); - - if (!DrinkInturrupted) - { - DoCast(me, SPELL_MASS_POLY, true); - DoCast(me, SPELL_CONJURE, false); - DoCast(me, SPELL_DRINK, false); - me->SetStandState(UNIT_STAND_STATE_SIT); - DrinkInturruptTimer = 10000; - } - } - - //Drink Inturrupt - if (Drinking && DrinkInturrupted) - { - Drinking = false; - me->RemoveAurasDueToSpell(SPELL_DRINK); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA)-32000); - DoCast(me, SPELL_POTION, false); - } - - //Drink Inturrupt Timer - if (Drinking && !DrinkInturrupted) - if (DrinkInturruptTimer >= diff) - DrinkInturruptTimer -= diff; - else - { - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_POTION, true); - DoCast(me, SPELL_AOE_PYROBLAST, false); - DrinkInturrupted = true; - Drinking = false; - } - - //Don't execute any more code if we are drinking - if (Drinking) - return; - - //Normal casts - if (NormalCastTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!pTarget) - return; - - uint32 Spells[3]; - uint8 AvailableSpells = 0; - - //Check for what spells are not on cooldown - if (!ArcaneCooldown) - { - Spells[AvailableSpells] = SPELL_ARCMISSLE; - ++AvailableSpells; - } - if (!FireCooldown) - { - Spells[AvailableSpells] = SPELL_FIREBALL; - ++AvailableSpells; - } - if (!FrostCooldown) - { - Spells[AvailableSpells] = SPELL_FROSTBOLT; - ++AvailableSpells; - } - - //If no available spells wait 1 second and try again - if (AvailableSpells) - { - CurrentNormalSpell = Spells[rand() % AvailableSpells]; - DoCast(pTarget, CurrentNormalSpell); - } - } - NormalCastTimer = 1000; - } else NormalCastTimer -= diff; - - if (SecondarySpellTimer <= diff) - { - switch (urand(0,1)) - { - case 0: - DoCast(me, SPELL_AOE_CS); - break; - case 1: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CHAINSOFICE); - break; - } - SecondarySpellTimer = urand(5000,20000); - } else SecondarySpellTimer -= diff; - - if (SuperCastTimer <= diff) - { - uint8 Available[2]; - - switch (LastSuperSpell) - { - case SUPER_AE: - Available[0] = SUPER_FLAME; - Available[1] = SUPER_BLIZZARD; - break; - case SUPER_FLAME: - Available[0] = SUPER_AE; - Available[1] = SUPER_BLIZZARD; - break; - case SUPER_BLIZZARD: - Available[0] = SUPER_FLAME; - Available[1] = SUPER_AE; - break; - } - - LastSuperSpell = Available[urand(0,1)]; - - switch (LastSuperSpell) - { - case SUPER_AE: - DoScriptText(RAND(SAY_EXPLOSION1,SAY_EXPLOSION2), me); - - DoCast(me, SPELL_BLINK_CENTER, true); - DoCast(me, SPELL_PLAYERPULL, true); - DoCast(me, SPELL_MASSSLOW, true); - DoCast(me, SPELL_AEXPLOSION, false); - break; - - case SUPER_FLAME: - DoScriptText(RAND(SAY_FLAMEWREATH1,SAY_FLAMEWREATH2), me); - - FlameWreathTimer = 20000; - FlameWreathCheckTime = 500; - - FlameWreathTarget[0] = 0; - FlameWreathTarget[1] = 0; - FlameWreathTarget[2] = 0; - - FlameWreathEffect(); - break; - - case SUPER_BLIZZARD: - DoScriptText(RAND(SAY_BLIZZARD1,SAY_BLIZZARD2), me); - - if (Creature* pSpawn = me->SummonCreature(CREATURE_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000)) - { - pSpawn->setFaction(me->getFaction()); - pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false); - } - break; - } - - SuperCastTimer = urand(35000,40000); - } else SuperCastTimer -= diff; - - if (!ElementalsSpawned && me->GetHealth()*100 / me->GetMaxHealth() < 40) - { - ElementalsSpawned = true; - - for (uint32 i = 0; i < 4; ++i) - { - if (Creature* pUnit = me->SummonCreature(CREATURE_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90000)) - { - pUnit->Attack(me->getVictim(), true); - pUnit->setFaction(me->getFaction()); - } - } - - DoScriptText(SAY_ELEMENTALS, me); - } - - if (BerserkTimer <= diff) - { - for (uint32 i = 0; i < 5; ++i) - { - if (Creature* pUnit = me->SummonCreature(CREATURE_SHADOW_OF_ARAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) - { - pUnit->Attack(me->getVictim(), true); - pUnit->setFaction(me->getFaction()); - } - } - - DoScriptText(SAY_TIMEOVER, me); - - BerserkTimer = 60000; - } else BerserkTimer -= diff; - - //Flame Wreath check - if (FlameWreathTimer) - { - if (FlameWreathTimer >= diff) - FlameWreathTimer -= diff; - else FlameWreathTimer = 0; - - if (FlameWreathCheckTime <= diff) - { - for (uint8 i = 0; i < 3; ++i) - { - if (!FlameWreathTarget[i]) - continue; - - Unit* pUnit = Unit::GetUnit(*me, FlameWreathTarget[i]); - if (pUnit && !pUnit->IsWithinDist2d(FWTargPosX[i], FWTargPosY[i], 3)) - { - pUnit->CastSpell(pUnit, 20476, true, 0, 0, me->GetGUID()); - pUnit->CastSpell(pUnit, 11027, true); - FlameWreathTarget[i] = 0; - } - } - FlameWreathCheckTime = 500; - } else FlameWreathCheckTime -= diff; - } - - if (ArcaneCooldown && FireCooldown && FrostCooldown) - DoMeleeAttackIfReady(); - } - - void DamageTaken(Unit* /*pAttacker*/, uint32 &damage) - { - if (!DrinkInturrupted && Drinking && damage) - DrinkInturrupted = true; - } - - void SpellHit(Unit* /*pAttacker*/, const SpellEntry* Spell) - { - //We only care about inturrupt effects and only if they are durring a spell currently being casted - if ((Spell->Effect[0] != SPELL_EFFECT_INTERRUPT_CAST && - Spell->Effect[1] != SPELL_EFFECT_INTERRUPT_CAST && - Spell->Effect[2] != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCasted(false)) - return; - - //Inturrupt effect - me->InterruptNonMeleeSpells(false); - - //Normally we would set the cooldown equal to the spell duration - //but we do not have access to the DurationStore - - switch (CurrentNormalSpell) - { - case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break; - case SPELL_FIREBALL: FireCooldown = 5000; break; - case SPELL_FROSTBOLT: FrostCooldown = 5000; break; - } - } -}; - -struct water_elementalAI : public ScriptedAI -{ - water_elementalAI(Creature *c) : ScriptedAI(c) {} - - uint32 CastTimer; - - void Reset() - { - CastTimer = 2000 + (rand()%3000); - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (CastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WATERBOLT); - CastTimer = urand(2000,5000); - } else CastTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_aran(Creature* pCreature) -{ - return new boss_aranAI (pCreature); -} - -CreatureAI* GetAI_water_elemental(Creature* pCreature) -{ - return new water_elementalAI (pCreature); -} - -// CONVERT TO ACID -CreatureAI* GetAI_shadow_of_aran(Creature* pCreature) -{ - outstring_log("TSCR: Convert simpleAI script for Creature Entry %u to ACID", pCreature->GetEntry()); - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = SPELL_SHADOW_PYRO; - ai->Spell[0].Cooldown = 5000; - ai->Spell[0].First_Cast = 1000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->EnterEvadeMode(); - - return ai; -} - -void AddSC_boss_shade_of_aran() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shade_of_aran"; - newscript->GetAI = &GetAI_boss_aran; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadow_of_aran"; - newscript->GetAI = &GetAI_shadow_of_aran; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_aran_elemental"; - newscript->GetAI = &GetAI_water_elemental; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp b/src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp deleted file mode 100644 index 5305cc8d354..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/boss_terestian_illhoof.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Terestian_Illhoof -SD%Complete: 95 -SDComment: Complete! Needs adjustments to use spell though. -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define SAY_SLAY1 -1532065 -#define SAY_SLAY2 -1532066 -#define SAY_DEATH -1532067 -#define SAY_AGGRO -1532068 -#define SAY_SACRIFICE1 -1532069 -#define SAY_SACRIFICE2 -1532070 -#define SAY_SUMMON1 -1532071 -#define SAY_SUMMON2 -1532072 - -#define SPELL_SUMMON_DEMONCHAINS 30120 // Summons demonic chains that maintain the ritual of sacrifice. -#define SPELL_DEMON_CHAINS 30206 // Instant - Visual Effect -#define SPELL_ENRAGE 23537 // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min. -#define SPELL_SHADOW_BOLT 30055 // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage. -#define SPELL_SACRIFICE 30115 // Teleports and adds the debuff -#define SPELL_BERSERK 32965 // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley. -#define SPELL_SUMMON_FIENDISIMP 30184 // Summons a Fiendish Imp. -#define SPELL_SUMMON_IMP 30066 // Summons Kil'rek - -#define SPELL_FIENDISH_PORTAL 30171 // Opens portal and summons Fiendish Portal, 2 sec cast -#define SPELL_FIENDISH_PORTAL_1 30179 // Opens portal and summons Fiendish Portal, instant cast - -#define SPELL_FIREBOLT 30050 // Blasts a target for 150 Fire damage. -#define SPELL_BROKEN_PACT 30065 // All damage taken increased by 25%. -#define SPELL_AMPLIFY_FLAMES 30053 // Increases the Fire damage taken by an enemy by 500 for 25 sec. - -#define CREATURE_DEMONCHAINS 17248 -#define CREATURE_FIENDISHIMP 17267 -#define CREATURE_PORTAL 17265 -#define CREATURE_KILREK 17229 - -struct mob_kilrekAI : public ScriptedAI -{ - mob_kilrekAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 TerestianGUID; - - uint32 AmplifyTimer; - - void Reset() - { - TerestianGUID = 0; - AmplifyTimer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - if (!pInstance) - { - ERROR_INST_DATA(me); - return; - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - uint64 TerestianGUID = pInstance->GetData64(DATA_TERESTIAN); - if (TerestianGUID) - { - Unit* Terestian = Unit::GetUnit((*me), TerestianGUID); - if (Terestian && Terestian->isAlive()) - DoCast(Terestian, SPELL_BROKEN_PACT, true); - } - } else ERROR_INST_DATA(me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (AmplifyTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me->getVictim(), SPELL_AMPLIFY_FLAMES); - - AmplifyTimer = urand(10000,20000); - } else AmplifyTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_demon_chainAI : public ScriptedAI -{ - mob_demon_chainAI(Creature *c) : ScriptedAI(c) {} - - uint64 SacrificeGUID; - - void Reset() - { - SacrificeGUID = 0; - } - - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void JustDied(Unit * /*killer*/) - { - if (SacrificeGUID) - { - Unit* Sacrifice = Unit::GetUnit((*me),SacrificeGUID); - if (Sacrifice) - Sacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE); - } - } -}; - -struct mob_fiendish_portalAI : public PassiveAI -{ - mob_fiendish_portalAI(Creature *c) : PassiveAI(c),summons(me){} - - SummonList summons; - - void Reset() - { - summons.DespawnAll(); - } - - void JustSummoned(Creature* summon) - { - summons.Summon(summon); - DoZoneInCombat(summon); - } - - void DespawnAllImp() - { - summons.DespawnAll(); - } -}; - -struct boss_terestianAI : public ScriptedAI -{ - boss_terestianAI(Creature *c) : ScriptedAI(c) - { - for (uint8 i = 0; i < 2; ++i) - PortalGUID[i] = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint64 PortalGUID[2]; - uint8 PortalsCount; - - uint32 SacrificeTimer; - uint32 ShadowboltTimer; - uint32 SummonTimer; - uint32 BerserkTimer; - - bool SummonedPortals; - bool Berserk; - - void Reset() - { - for (uint8 i = 0; i < 2; ++i) - { - if (PortalGUID[i]) - { - if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[i])) - { - CAST_AI(mob_fiendish_portalAI, pPortal->AI())->DespawnAllImp(); - pPortal->ForcedDespawn(); - } - - PortalGUID[i] = 0; - } - } - - PortalsCount = 0; - SacrificeTimer = 30000; - ShadowboltTimer = 5000; - SummonTimer = 10000; - BerserkTimer = 600000; - - SummonedPortals = false; - Berserk = false; - - if (pInstance) - pInstance->SetData(TYPE_TERESTIAN, NOT_STARTED); - - me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT); - - if (Minion* Kilrek = me->GetFirstMinion()) - { - if (!Kilrek->isAlive()) - { - Kilrek->UnSummon(); - DoCast(me, SPELL_SUMMON_IMP, true); - } - } - else DoCast(me, SPELL_SUMMON_IMP, true); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == CREATURE_PORTAL) - { - PortalGUID[PortalsCount] = pSummoned->GetGUID(); - ++PortalsCount; - - if (pSummoned->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_FIENDISH_PORTAL_1) - { - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - SummonedPortals = true; - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*killer*/) - { - for (uint8 i = 0; i < 2; ++i) - { - if (PortalGUID[i]) - { - if (Creature* pPortal = Unit::GetCreature((*me), PortalGUID[i])) - pPortal->ForcedDespawn(); - - PortalGUID[i] = 0; - } - } - - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_TERESTIAN, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (SacrificeTimer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - if (pTarget && pTarget->isAlive()) - { - DoCast(pTarget, SPELL_SACRIFICE, true); - DoCast(pTarget, SPELL_SUMMON_DEMONCHAINS, true); - - if (Creature* Chains = me->FindNearestCreature(CREATURE_DEMONCHAINS, 5000)) - { - CAST_AI(mob_demon_chainAI, Chains->AI())->SacrificeGUID = pTarget->GetGUID(); - Chains->CastSpell(Chains, SPELL_DEMON_CHAINS, true); - DoScriptText(RAND(SAY_SACRIFICE1,SAY_SACRIFICE2), me); - SacrificeTimer = 30000; - } - } - } else SacrificeTimer -= diff; - - if (ShadowboltTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO, 0), SPELL_SHADOW_BOLT); - ShadowboltTimer = 10000; - } else ShadowboltTimer -= diff; - - if (SummonTimer <= diff) - { - if (!PortalGUID[0]) - DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL, false); - - if (!PortalGUID[1]) - DoCast(me->getVictim(), SPELL_FIENDISH_PORTAL_1, false); - - if (PortalGUID[0] && PortalGUID[1]) - { - if (Creature* pPortal = Unit::GetCreature(*me, PortalGUID[urand(0,1)])) - pPortal->CastSpell(me->getVictim(), SPELL_SUMMON_FIENDISIMP, false); - SummonTimer = 5000; - } - } else SummonTimer -= diff; - - if (!Berserk) - { - if (BerserkTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - Berserk = true; - } else BerserkTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -#define SPELL_FIREBOLT 30050 // Blasts a target for 181-209 Fire damage. - -struct mob_fiendish_impAI : public ScriptedAI -{ - mob_fiendish_impAI(Creature *c) : ScriptedAI(c) {} - - uint32 FireboltTimer; - - void Reset() - { - FireboltTimer = 2000; - - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (FireboltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBOLT); - FireboltTimer = 2200; - } else FireboltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_kilrek(Creature* pCreature) -{ - return new mob_kilrekAI (pCreature); -} - -CreatureAI* GetAI_mob_fiendish_imp(Creature* pCreature) -{ - return new mob_fiendish_impAI (pCreature); -} - -CreatureAI* GetAI_mob_fiendish_portal(Creature* pCreature) -{ - return new mob_fiendish_portalAI (pCreature); -} - -CreatureAI* GetAI_boss_terestian_illhoof(Creature* pCreature) -{ - return new boss_terestianAI (pCreature); -} - -CreatureAI* GetAI_mob_demon_chain(Creature* pCreature) -{ - return new mob_demon_chainAI(pCreature); -} - -void AddSC_boss_terestian_illhoof() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_terestian_illhoof"; - newscript->GetAI = &GetAI_boss_terestian_illhoof; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fiendish_imp"; - newscript->GetAI = &GetAI_mob_fiendish_imp; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name= "mob_fiendish_portal"; - newscript->GetAI = &GetAI_mob_fiendish_portal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_kilrek"; - newscript->GetAI = &GetAI_mob_kilrek; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_demon_chain"; - newscript->GetAI = &GetAI_mob_demon_chain; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp deleted file mode 100644 index ae6de9c1add..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/bosses_opera.cpp +++ /dev/null @@ -1,1494 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Bosses_Opera -SD%Complete: 90 -SDComment: Oz, Hood, and RAJ event implemented. RAJ event requires more testing. -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -/***********************************/ -/*** OPERA WIZARD OF OZ EVENT *****/ -/*********************************/ - -#define SAY_DOROTHEE_DEATH -1532025 -#define SAY_DOROTHEE_SUMMON -1532026 -#define SAY_DOROTHEE_TITO_DEATH -1532027 -#define SAY_DOROTHEE_AGGRO -1532028 - -#define SAY_ROAR_AGGRO -1532029 -#define SAY_ROAR_DEATH -1532030 -#define SAY_ROAR_SLAY -1532031 - -#define SAY_STRAWMAN_AGGRO -1532032 -#define SAY_STRAWMAN_DEATH -1532033 -#define SAY_STRAWMAN_SLAY -1532034 - -#define SAY_TINHEAD_AGGRO -1532035 -#define SAY_TINHEAD_DEATH -1532036 -#define SAY_TINHEAD_SLAY -1532037 -#define EMOTE_RUST -1532038 - -#define SAY_CRONE_AGGRO -1532039 -#define SAY_CRONE_AGGRO2 -1532040 -#define SAY_CRONE_DEATH -1532041 -#define SAY_CRONE_SLAY -1532042 - -/**** Spells ****/ -// Dorothee -#define SPELL_WATERBOLT 31012 -#define SPELL_SCREAM 31013 -#define SPELL_SUMMONTITO 31014 - -// Tito -#define SPELL_YIPPING 31015 - -// Strawman -#define SPELL_BRAIN_BASH 31046 -#define SPELL_BRAIN_WIPE 31069 -#define SPELL_BURNING_STRAW 31075 - -// Tinhead -#define SPELL_CLEAVE 31043 -#define SPELL_RUST 31086 - -// Roar -#define SPELL_MANGLE 31041 -#define SPELL_SHRED 31042 -#define SPELL_FRIGHTENED_SCREAM 31013 - -// Crone -#define SPELL_CHAIN_LIGHTNING 32337 - -// Cyclone -#define SPELL_KNOCKBACK 32334 -#define SPELL_CYCLONE_VISUAL 32332 - -/** Creature Entries **/ -#define CREATURE_TITO 17548 -#define CREATURE_CYCLONE 18412 -#define CREATURE_CRONE 18168 - -void SummonCroneIfReady(ScriptedInstance* pInstance, Creature* pCreature) -{ - pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, SPECIAL); // Increment DeathCount - - if (pInstance->GetData(DATA_OPERA_OZ_DEATHCOUNT) == 4) - { - if (Creature* pCrone = pCreature->SummonCreature(CREATURE_CRONE, -10891.96, -1755.95, pCreature->GetPositionZ(), 4.64, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) - { - if (pCreature->getVictim()) - pCrone->AI()->AttackStart(pCreature->getVictim()); - } - } -}; - -struct boss_dorotheeAI : public ScriptedAI -{ - boss_dorotheeAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AggroTimer; - - uint32 WaterBoltTimer; - uint32 FearTimer; - uint32 SummonTitoTimer; - - bool SummonedTito; - bool TitoDied; - - void Reset() - { - AggroTimer = 500; - - WaterBoltTimer = 5000; - FearTimer = 15000; - SummonTitoTimer = 47500; - - SummonedTito = false; - TitoDied = false; - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_DOROTHEE_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void SummonTito(); // See below - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DOROTHEE_DEATH, me); - - if (pInstance) - SummonCroneIfReady(pInstance, me); - } - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - if (AggroTimer) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer = 0; - } else AggroTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (WaterBoltTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_WATERBOLT); - WaterBoltTimer = TitoDied ? 1500 : 5000; - } else WaterBoltTimer -= diff; - - if (FearTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SCREAM); - FearTimer = 30000; - } else FearTimer -= diff; - - if (!SummonedTito) - { - if (SummonTitoTimer <= diff) - SummonTito(); - else SummonTitoTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_titoAI : public ScriptedAI -{ - mob_titoAI(Creature* c) : ScriptedAI(c) {} - - uint64 DorotheeGUID; - uint32 YipTimer; - - void Reset() - { - DorotheeGUID = 0; - YipTimer = 10000; - } - - void EnterCombat(Unit* /*who*/) {} - - void JustDied(Unit* /*killer*/) - { - if (DorotheeGUID) - { - Creature* Dorothee = (Unit::GetCreature((*me), DorotheeGUID)); - if (Dorothee && Dorothee->isAlive()) - { - CAST_AI(boss_dorotheeAI, Dorothee->AI())->TitoDied = true; - DoScriptText(SAY_DOROTHEE_TITO_DEATH, Dorothee); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (YipTimer <= diff) - { - DoCast(me->getVictim(), SPELL_YIPPING); - YipTimer = 10000; - } else YipTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -void boss_dorotheeAI::SummonTito() -{ - if (Creature* pTito = me->SummonCreature(CREATURE_TITO, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - DoScriptText(SAY_DOROTHEE_SUMMON, me); - CAST_AI(mob_titoAI, pTito->AI())->DorotheeGUID = me->GetGUID(); - pTito->AI()->AttackStart(me->getVictim()); - SummonedTito = true; - TitoDied = false; - } -} - -struct boss_strawmanAI : public ScriptedAI -{ - boss_strawmanAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AggroTimer; - uint32 BrainBashTimer; - uint32 BrainWipeTimer; - - void Reset() - { - AggroTimer = 13000; - BrainBashTimer = 5000; - BrainWipeTimer = 7000; - } - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_STRAWMAN_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry *Spell) - { - if ((Spell->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && (!(rand()%10))) - { - /* - if (not direct damage(aoe,dot)) - return; - */ - - DoCast(me, SPELL_BURNING_STRAW, true); - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_STRAWMAN_DEATH, me); - - if (pInstance) - SummonCroneIfReady(pInstance, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_STRAWMAN_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - if (AggroTimer) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer = 0; - } else AggroTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (BrainBashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BRAIN_BASH); - BrainBashTimer = 15000; - } else BrainBashTimer -= diff; - - if (BrainWipeTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BRAIN_WIPE); - BrainWipeTimer = 20000; - } else BrainWipeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_tinheadAI : public ScriptedAI -{ - boss_tinheadAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AggroTimer; - uint32 CleaveTimer; - uint32 RustTimer; - - uint8 RustCount; - - void Reset() - { - AggroTimer = 15000; - CleaveTimer = 5000; - RustTimer = 30000; - - RustCount = 0; - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_TINHEAD_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_TINHEAD_DEATH, me); - - if (pInstance) - SummonCroneIfReady(pInstance, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_TINHEAD_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - if (AggroTimer) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer = 0; - } else AggroTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (CleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - CleaveTimer = 5000; - } else CleaveTimer -= diff; - - if (RustCount < 8) - { - if (RustTimer <= diff) - { - ++RustCount; - DoScriptText(EMOTE_RUST, me); - DoCast(me, SPELL_RUST); - RustTimer = 6000; - } else RustTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_roarAI : public ScriptedAI -{ - boss_roarAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AggroTimer; - uint32 MangleTimer; - uint32 ShredTimer; - uint32 ScreamTimer; - - void Reset() - { - AggroTimer = 20000; - MangleTimer = 5000; - ShredTimer = 10000; - ScreamTimer = 15000; - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_ROAR_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_ROAR_DEATH, me); - - if (pInstance) - SummonCroneIfReady(pInstance, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_ROAR_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - if (AggroTimer) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer = 0; - } else AggroTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (MangleTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MANGLE); - MangleTimer = urand(5000,8000); - } else MangleTimer -= diff; - - if (ShredTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHRED); - ShredTimer = urand(10000,15000); - } else ShredTimer -= diff; - - if (ScreamTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FRIGHTENED_SCREAM); - ScreamTimer = urand(20000,30000); - } else ScreamTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_croneAI : public ScriptedAI -{ - boss_croneAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 CycloneTimer; - uint32 ChainLightningTimer; - - void Reset() - { - CycloneTimer = 30000; - ChainLightningTimer = 10000; - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(RAND(SAY_CRONE_AGGRO,SAY_CRONE_AGGRO2), me); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_CRONE_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_OPERA, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (CycloneTimer <= diff) - { - if (Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, urand(0,9), urand(0,9), 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000)) - Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_VISUAL, true); - CycloneTimer = 30000; - } else CycloneTimer -= diff; - - if (ChainLightningTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); - ChainLightningTimer = 15000; - } else ChainLightningTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_cycloneAI : public ScriptedAI -{ - mob_cycloneAI(Creature* c) : ScriptedAI(c) {} - - uint32 MoveTimer; - - void Reset() - { - MoveTimer = 1000; - } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit* /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!me->HasAura(SPELL_KNOCKBACK)) - DoCast(me, SPELL_KNOCKBACK, true); - - if (MoveTimer <= diff) - { - Position pos; - me->GetRandomNearPosition(pos, 10); - me->GetMotionMaster()->MovePoint(0, pos); - MoveTimer = urand(5000,8000); - } else MoveTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_dorothee(Creature* pCreature) -{ - return new boss_dorotheeAI(pCreature); -} - -CreatureAI* GetAI_boss_strawman(Creature* pCreature) -{ - return new boss_strawmanAI(pCreature); -} - -CreatureAI* GetAI_boss_tinhead(Creature* pCreature) -{ - return new boss_tinheadAI(pCreature); -} - -CreatureAI* GetAI_boss_roar(Creature* pCreature) -{ - return new boss_roarAI(pCreature); -} - -CreatureAI* GetAI_boss_crone(Creature* pCreature) -{ - return new boss_croneAI(pCreature); -} - -CreatureAI* GetAI_mob_tito(Creature* pCreature) -{ - return new mob_titoAI(pCreature); -} - -CreatureAI* GetAI_mob_cyclone(Creature* pCreature) -{ - return new mob_cycloneAI(pCreature); -} - -/**************************************/ -/**** Opera Red Riding Hood Event ****/ -/************************************/ - -/**** Yells for the Wolf ****/ -#define SAY_WOLF_AGGRO -1532043 -#define SAY_WOLF_SLAY -1532044 -#define SAY_WOLF_HOOD -1532045 -#define SOUND_WOLF_DEATH 9275 //Only sound on death, no text. - -/**** Spells For The Wolf ****/ -#define SPELL_LITTLE_RED_RIDING_HOOD 30768 -#define SPELL_TERRIFYING_HOWL 30752 -#define SPELL_WIDE_SWIPE 30761 - -#define GOSSIP_GRANDMA "What phat lewtz you have grandmother?" - -/**** The Wolf's Entry ****/ -#define CREATURE_BIG_BAD_WOLF 17521 - -bool GossipHello_npc_grandmother(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GRANDMA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(8990, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_grandmother(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - if (Creature* pBigBadWolf = pCreature->SummonCreature(CREATURE_BIG_BAD_WOLF, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) - pBigBadWolf->AI()->AttackStart(pPlayer); - - pCreature->ForcedDespawn(); - } - - return true; -} - -struct boss_bigbadwolfAI : public ScriptedAI -{ - boss_bigbadwolfAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ChaseTimer; - uint32 FearTimer; - uint32 SwipeTimer; - - uint64 HoodGUID; - float TempThreat; - - bool IsChasing; - - void Reset() - { - ChaseTimer = 30000; - FearTimer = 25000 + rand()%10000; - SwipeTimer = 5000; - - HoodGUID = 0; - TempThreat = 0; - - IsChasing = false; - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_WOLF_AGGRO, me); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void JustDied(Unit* /*killer*/) - { - DoPlaySoundToSet(me, SOUND_WOLF_DEATH); - - if (pInstance) - { - pInstance->SetData(TYPE_OPERA, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - - if (ChaseTimer <= diff) - { - if (!IsChasing) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(SAY_WOLF_HOOD, me); - DoCast(pTarget, SPELL_LITTLE_RED_RIDING_HOOD, true); - TempThreat = DoGetThreat(pTarget); - if (TempThreat) - DoModifyThreatPercent(pTarget, -100); - HoodGUID = pTarget->GetGUID(); - me->AddThreat(pTarget, 1000000.0f); - ChaseTimer = 20000; - IsChasing = true; - } - } - else - { - IsChasing = false; - - if (Unit *pTarget = Unit::GetUnit((*me), HoodGUID)) - { - HoodGUID = 0; - if (DoGetThreat(pTarget)) - DoModifyThreatPercent(pTarget, -100); - me->AddThreat(pTarget, TempThreat); - TempThreat = 0; - } - - ChaseTimer = 40000; - } - } else ChaseTimer -= diff; - - if (IsChasing) - return; - - if (FearTimer <= diff) - { - DoCast(me->getVictim(), SPELL_TERRIFYING_HOWL); - FearTimer = urand(25000,35000); - } else FearTimer -= diff; - - if (SwipeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WIDE_SWIPE); - SwipeTimer = urand(25000,30000); - } else SwipeTimer -= diff; - - } -}; - -CreatureAI* GetAI_boss_bigbadwolf(Creature* pCreature) -{ - return new boss_bigbadwolfAI(pCreature); -} - -/**********************************************/ -/******** Opera Romeo and Juliet Event *******/ -/********************************************/ - -/**** Speech *****/ -#define SAY_JULIANNE_AGGRO -1532046 -#define SAY_JULIANNE_ENTER -1532047 -#define SAY_JULIANNE_DEATH01 -1532048 -#define SAY_JULIANNE_DEATH02 -1532049 -#define SAY_JULIANNE_RESURRECT -1532050 -#define SAY_JULIANNE_SLAY -1532051 - -#define SAY_ROMULO_AGGRO -1532052 -#define SAY_ROMULO_DEATH -1532053 -#define SAY_ROMULO_ENTER -1532054 -#define SAY_ROMULO_RESURRECT -1532055 -#define SAY_ROMULO_SLAY -1532056 - -/***** Spells For Julianne *****/ -#define SPELL_BLINDING_PASSION 30890 -#define SPELL_DEVOTION 30887 -#define SPELL_ETERNAL_AFFECTION 30878 -#define SPELL_POWERFUL_ATTRACTION 30889 -#define SPELL_DRINK_POISON 30907 - -/***** Spells For Romulo ****/ -#define SPELL_BACKWARD_LUNGE 30815 -#define SPELL_DARING 30841 -#define SPELL_DEADLY_SWATHE 30817 -#define SPELL_POISON_THRUST 30822 - -/**** Other Misc. Spells ****/ -#define SPELL_UNDYING_LOVE 30951 -#define SPELL_RES_VISUAL 24171 - -/*** Misc. Information ****/ -#define CREATURE_ROMULO 17533 -#define ROMULO_X -10900 -#define ROMULO_Y -1758 - -enum RAJPhase -{ - PHASE_JULIANNE = 0, - PHASE_ROMULO = 1, - PHASE_BOTH = 2, -}; - -void PretendToDie(Creature* pCreature) -{ - pCreature->InterruptNonMeleeSpells(true); - pCreature->RemoveAllAuras(); - pCreature->SetHealth(0); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->GetMotionMaster()->MovementExpired(false); - pCreature->GetMotionMaster()->MoveIdle(); - pCreature->SetStandState(UNIT_STAND_STATE_DEAD); -}; - -void Resurrect(Creature *pTarget) -{ - pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTarget->SetHealth(pTarget->GetMaxHealth()); - pTarget->SetStandState(UNIT_STAND_STATE_STAND); - pTarget->CastSpell(pTarget, SPELL_RES_VISUAL, true); - if (pTarget->getVictim()) - { - pTarget->GetMotionMaster()->MoveChase(pTarget->getVictim()); - pTarget->AI()->AttackStart(pTarget->getVictim()); - } - else - pTarget->GetMotionMaster()->Initialize(); -}; - -struct boss_julianneAI : public ScriptedAI -{ - boss_julianneAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EntryYellTimer = 1000; - AggroYellTimer = 10000; - IsFakingDeath = false; - } - - ScriptedInstance* pInstance; - - uint32 EntryYellTimer; - uint32 AggroYellTimer; - - uint64 RomuloGUID; - - uint32 Phase; - - uint32 BlindingPassionTimer; - uint32 DevotionTimer; - uint32 EternalAffectionTimer; - uint32 PowerfulAttractionTimer; - uint32 SummonRomuloTimer; - uint32 ResurrectTimer; - uint32 DrinkPoisonTimer; - uint32 ResurrectSelfTimer; - - bool IsFakingDeath; - bool SummonedRomulo; - bool RomuloDead; - - void Reset() - { - RomuloGUID = 0; - Phase = PHASE_JULIANNE; - - BlindingPassionTimer = 30000; - DevotionTimer = 15000; - EternalAffectionTimer = 25000; - PowerfulAttractionTimer = 5000; - SummonRomuloTimer = 10000; - DrinkPoisonTimer = 0; - ResurrectSelfTimer = 0; - - if (IsFakingDeath) - { - Resurrect(me); - IsFakingDeath = false; - } - - SummonedRomulo = false; - RomuloDead = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void AttackStart(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry *Spell) - { - if (Spell->Id == SPELL_DRINK_POISON) - { - DoScriptText(SAY_JULIANNE_DEATH01, me); - DrinkPoisonTimer = 2500; - } - } - - void DamageTaken(Unit* done_by, uint32 &damage); - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_JULIANNE_DEATH02, me); - - if (pInstance) - { - pInstance->SetData(TYPE_OPERA, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); - if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_JULIANNE_SLAY, me); - } - - void UpdateAI(const uint32 diff); -}; - -struct boss_romuloAI : public ScriptedAI -{ - boss_romuloAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EntryYellTimer = 8000; - AggroYellTimer = 15000; - } - - ScriptedInstance* pInstance; - - uint64 JulianneGUID; - uint32 Phase; - - uint32 EntryYellTimer; - uint32 AggroYellTimer; - uint32 BackwardLungeTimer; - uint32 DaringTimer; - uint32 DeadlySwatheTimer; - uint32 PoisonThrustTimer; - uint32 ResurrectTimer; - - bool IsFakingDeath; - bool JulianneDead; - - void Reset() - { - JulianneGUID = 0; - Phase = PHASE_ROMULO; - - BackwardLungeTimer = 15000; - DaringTimer = 20000; - DeadlySwatheTimer = 25000; - PoisonThrustTimer = 10000; - ResurrectTimer = 10000; - - IsFakingDeath = false; - JulianneDead = false; - } - - void JustReachedHome() - { - me->ForcedDespawn(); - } - - void DamageTaken(Unit* done_by, uint32 &damage); - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_ROMULO_AGGRO, me); - if (JulianneGUID) - { - Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); - if (Julianne && Julianne->getVictim()) - { - me->AddThreat(Julianne->getVictim(), 1.0f); - AttackStart(Julianne->getVictim()); - } - } - } - - void MoveInLineOfSight(Unit* who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_ROMULO_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_OPERA, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORLEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_ROMULO_SLAY, me); - } - - void UpdateAI(const uint32 diff); -}; - -void boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32 &damage) -{ - if (damage < me->GetHealth()) - return; - - //anything below only used if incoming damage will kill - - if (Phase == PHASE_JULIANNE) - { - damage = 0; - - //this means already drinking, so return - if (IsFakingDeath) - return; - - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_DRINK_POISON); - - IsFakingDeath = true; - //IS THIS USEFULL? Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); - return; - } - - if (Phase == PHASE_ROMULO) - { - error_log("TSCR: boss_julianneAI: cannot take damage in PHASE_ROMULO, why was i here?"); - damage = 0; - return; - } - - if (Phase == PHASE_BOTH) - { - //if this is true then we have to kill romulo too - if (RomuloDead) - { - if (Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID))) - { - Romulo->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Romulo->GetMotionMaster()->Clear(); - Romulo->setDeathState(JUST_DIED); - Romulo->CombatStop(true); - Romulo->DeleteThreatList(); - Romulo->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - - return; - } - - //if not already returned, then romulo is alive and we can pretend die - if (Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID))) - { - PretendToDie(me); - IsFakingDeath = true; - CAST_AI(boss_romuloAI, Romulo->AI())->ResurrectTimer = 10000; - CAST_AI(boss_romuloAI, Romulo->AI())->JulianneDead = true; - damage = 0; - return; - } - } - error_log("TSCR: boss_julianneAI: DamageTaken reach end of code, that should not happen."); -} - -void boss_romuloAI::DamageTaken(Unit* /*done_by*/, uint32 &damage) -{ - if (damage < me->GetHealth()) - return; - - //anything below only used if incoming damage will kill - - if (Phase == PHASE_ROMULO) - { - DoScriptText(SAY_ROMULO_DEATH, me); - PretendToDie(me); - IsFakingDeath = true; - Phase = PHASE_BOTH; - - if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) - { - CAST_AI(boss_julianneAI, Julianne->AI())->RomuloDead = true; - CAST_AI(boss_julianneAI, Julianne->AI())->ResurrectSelfTimer = 10000; - } - - damage = 0; - return; - } - - if (Phase == PHASE_BOTH) - { - if (JulianneDead) - { - if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) - { - Julianne->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Julianne->GetMotionMaster()->Clear(); - Julianne->setDeathState(JUST_DIED); - Julianne->CombatStop(true); - Julianne->DeleteThreatList(); - Julianne->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - return; - } - - if (Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID))) - { - PretendToDie(me); - IsFakingDeath = true; - CAST_AI(boss_julianneAI, Julianne->AI())->ResurrectTimer = 10000; - CAST_AI(boss_julianneAI, Julianne->AI())->RomuloDead = true; - damage = 0; - return; - } - } - - error_log("TSCR: boss_romuloAI: DamageTaken reach end of code, that should not happen."); -} - -void boss_julianneAI::UpdateAI(const uint32 diff) -{ - if (EntryYellTimer) - { - if (EntryYellTimer <= diff) - { - DoScriptText(SAY_JULIANNE_ENTER, me); - EntryYellTimer = 0; - } else EntryYellTimer -= diff; - } - - if (AggroYellTimer) - { - if (AggroYellTimer <= diff) - { - DoScriptText(SAY_JULIANNE_AGGRO, me); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->setFaction(16); - AggroYellTimer = 0; - } else AggroYellTimer -= diff; - } - - if (DrinkPoisonTimer) - { - //will do this 2secs after spell hit. this is time to display visual as expected - if (DrinkPoisonTimer <= diff) - { - PretendToDie(me); - Phase = PHASE_ROMULO; - SummonRomuloTimer = 10000; - DrinkPoisonTimer = 0; - } else DrinkPoisonTimer -= diff; - } - - if (Phase == PHASE_ROMULO && !SummonedRomulo) - { - if (SummonRomuloTimer <= diff) - { - if (Creature* pRomulo = me->SummonCreature(CREATURE_ROMULO, ROMULO_X, ROMULO_Y, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) - { - RomuloGUID = pRomulo->GetGUID(); - CAST_AI(boss_romuloAI, pRomulo->AI())->JulianneGUID = me->GetGUID(); - CAST_AI(boss_romuloAI, pRomulo->AI())->Phase = PHASE_ROMULO; - DoZoneInCombat(pRomulo); - - pRomulo->setFaction(16); - } - SummonedRomulo = true; - } else SummonRomuloTimer -= diff; - } - - if (ResurrectSelfTimer) - { - if (ResurrectSelfTimer <= diff) - { - Resurrect(me); - Phase = PHASE_BOTH; - IsFakingDeath = false; - - if (me->getVictim()) - AttackStart(me->getVictim()); - - ResurrectSelfTimer = 0; - ResurrectTimer = 1000; - } else ResurrectSelfTimer -= diff; - } - - if (!UpdateVictim() || IsFakingDeath) - return; - - if (RomuloDead) - { - if (ResurrectTimer <= diff) - { - Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID)); - if (Romulo && CAST_AI(boss_romuloAI, Romulo->AI())->IsFakingDeath) - { - DoScriptText(SAY_JULIANNE_RESURRECT, me); - Resurrect(Romulo); - CAST_AI(boss_romuloAI, Romulo->AI())->IsFakingDeath = false; - RomuloDead = false; - ResurrectTimer = 10000; - } - } else ResurrectTimer -= diff; - } - - if (BlindingPassionTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BLINDING_PASSION); - BlindingPassionTimer = urand(30000,45000); - } else BlindingPassionTimer -= diff; - - if (DevotionTimer <= diff) - { - DoCast(me, SPELL_DEVOTION); - DevotionTimer = urand(15000,45000); - } else DevotionTimer -= diff; - - if (PowerfulAttractionTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_POWERFUL_ATTRACTION); - PowerfulAttractionTimer = urand(5000,30000); - } else PowerfulAttractionTimer -= diff; - - if (EternalAffectionTimer <= diff) - { - if (urand(0,1) && SummonedRomulo) - { - Creature* Romulo = (Unit::GetCreature((*me), RomuloGUID)); - if (Romulo && Romulo->isAlive() && !RomuloDead) - DoCast(Romulo, SPELL_ETERNAL_AFFECTION); - } else DoCast(me, SPELL_ETERNAL_AFFECTION); - - EternalAffectionTimer = urand(45000,60000); - } else EternalAffectionTimer -= diff; - - DoMeleeAttackIfReady(); -} - -void boss_romuloAI::UpdateAI(const uint32 diff) -{ - if (!UpdateVictim() || IsFakingDeath) - return; - - if (JulianneDead) - { - if (ResurrectTimer <= diff) - { - Creature* Julianne = (Unit::GetCreature((*me), JulianneGUID)); - if (Julianne && CAST_AI(boss_julianneAI, Julianne->AI())->IsFakingDeath) - { - DoScriptText(SAY_ROMULO_RESURRECT, me); - Resurrect(Julianne); - CAST_AI(boss_julianneAI, Julianne->AI())->IsFakingDeath = false; - JulianneDead = false; - ResurrectTimer = 10000; - } - } else ResurrectTimer -= diff; - } - - if (BackwardLungeTimer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - if (pTarget && !me->HasInArc(M_PI, pTarget)) - { - DoCast(pTarget, SPELL_BACKWARD_LUNGE); - BackwardLungeTimer = urand(15000,30000); - } - } else BackwardLungeTimer -= diff; - - if (DaringTimer <= diff) - { - DoCast(me, SPELL_DARING); - DaringTimer = urand(20000,40000); - } else DaringTimer -= diff; - - if (DeadlySwatheTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_DEADLY_SWATHE); - DeadlySwatheTimer = urand(15000,25000); - } else DeadlySwatheTimer -= diff; - - if (PoisonThrustTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_THRUST); - PoisonThrustTimer = urand(10000,20000); - } else PoisonThrustTimer -= diff; - - DoMeleeAttackIfReady(); -} - -CreatureAI* GetAI_boss_julianne(Creature* pCreature) -{ - return new boss_julianneAI(pCreature); -} - -CreatureAI* GetAI_boss_romulo(Creature* pCreature) -{ - return new boss_romuloAI(pCreature); -} - -void AddSC_bosses_opera() -{ - Script* newscript; - - // Oz - newscript = new Script; - newscript->GetAI = &GetAI_boss_dorothee; - newscript->Name = "boss_dorothee"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_strawman; - newscript->Name = "boss_strawman"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_tinhead; - newscript->Name = "boss_tinhead"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_roar; - newscript->Name = "boss_roar"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_crone; - newscript->Name = "boss_crone"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_tito; - newscript->Name = "mob_tito"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_cyclone; - newscript->Name = "mob_cyclone"; - newscript->RegisterSelf(); - - // Hood - newscript = new Script; - newscript->pGossipHello = &GossipHello_npc_grandmother; - newscript->pGossipSelect = &GossipSelect_npc_grandmother; - newscript->Name = "npc_grandmother"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_bigbadwolf; - newscript->Name = "boss_bigbadwolf"; - newscript->RegisterSelf(); - - // Romeo And Juliet - newscript = new Script; - newscript->GetAI = &GetAI_boss_julianne; - newscript->Name = "boss_julianne"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_romulo; - newscript->Name = "boss_romulo"; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp b/src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp deleted file mode 100644 index 59c1236bcdc..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/instance_karazhan.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Karazhan -SD%Complete: 70 -SDComment: Instance Script for Karazhan to help in various encounters. TODO: GameObject visibility for Opera event. -SDCategory: Karazhan -EndScriptData */ - -#include "ScriptedPch.h" -#include "karazhan.h" - -#define MAX_ENCOUNTER 12 - -/* -0 - Attumen + Midnight (optional) -1 - Moroes -2 - Maiden of Virtue (optional) -3 - Hyakiss the Lurker / Rokad the Ravager / Shadikith the Glider -4 - Opera Event -5 - Curator -6 - Shade of Aran (optional) -7 - Terestian Illhoof (optional) -8 - Netherspite (optional) -9 - Chess Event -10 - Prince Malchezzar -11 - Nightbane -*/ - -struct instance_karazhan : public ScriptedInstance -{ - instance_karazhan(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string strSaveData; - - uint32 m_uiOperaEvent; - uint32 m_uiOzDeathCount; - - uint64 m_uiCurtainGUID; - uint64 m_uiStageDoorLeftGUID; - uint64 m_uiStageDoorRightGUID; - uint64 m_uiKilrekGUID; - uint64 m_uiTerestianGUID; - uint64 m_uiMoroesGUID; - uint64 m_uiLibraryDoor; // Door at Shade of Aran - uint64 m_uiMassiveDoor; // Door at Netherspite - uint64 m_uiSideEntranceDoor; // Side Entrance - uint64 m_uiGamesmansDoor; // Door before Chess - uint64 m_uiGamesmansExitDoor; // Door after Chess - uint64 m_uiNetherspaceDoor; // Door at Malchezaar - uint64 MastersTerraceDoor[2]; - uint64 ImageGUID; - uint64 DustCoveredChest; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - // 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered. - m_uiOperaEvent = urand(1,3); - m_uiOzDeathCount = 0; - - m_uiCurtainGUID = 0; - m_uiStageDoorLeftGUID = 0; - m_uiStageDoorRightGUID = 0; - - m_uiKilrekGUID = 0; - m_uiTerestianGUID = 0; - m_uiMoroesGUID = 0; - - m_uiLibraryDoor = 0; - m_uiMassiveDoor = 0; - m_uiSideEntranceDoor = 0; - m_uiGamesmansDoor = 0; - m_uiGamesmansExitDoor = 0; - m_uiNetherspaceDoor = 0; - MastersTerraceDoor[0]= 0; - MastersTerraceDoor[1]= 0; - ImageGUID = 0; - DustCoveredChest = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case 17229: m_uiKilrekGUID = pCreature->GetGUID(); break; - case 15688: m_uiTerestianGUID = pCreature->GetGUID(); break; - case 15687: m_uiMoroesGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 uiData) - { - switch (type) - { - case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break; - case TYPE_MOROES: - if (m_auiEncounter[1] == DONE) - break; - m_auiEncounter[1] = uiData; - break; - case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break; - case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break; - case TYPE_OPERA: m_auiEncounter[4] = uiData; break; - case TYPE_CURATOR: m_auiEncounter[5] = uiData; break; - case TYPE_ARAN: m_auiEncounter[6] = uiData; break; - case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break; - case TYPE_NETHERSPITE: m_auiEncounter[8] = uiData; break; - case TYPE_CHESS: - if (uiData == DONE) - DoRespawnGameObject(DustCoveredChest,DAY); - m_auiEncounter[9] = uiData; - break; - case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break; - case TYPE_NIGHTBANE: - if (m_auiEncounter[11] != DONE) - m_auiEncounter[11] = uiData; - break; - case DATA_OPERA_OZ_DEATHCOUNT: - if (uiData == SPECIAL) - ++m_uiOzDeathCount; - else if (uiData == IN_PROGRESS) - m_uiOzDeathCount = 0; - break; - } - - if (uiData == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " - << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11]; - - strSaveData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - void SetData64(uint32 identifier, uint64 data) - { - switch(identifier) - { - case DATA_IMAGE_OF_MEDIVH: ImageGUID = data; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 183932: m_uiCurtainGUID = pGo->GetGUID(); break; - case 184278: - m_uiStageDoorLeftGUID = pGo->GetGUID(); - if (m_auiEncounter[4] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case 184279: - m_uiStageDoorRightGUID = pGo->GetGUID(); - if (m_auiEncounter[4] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case 184517: m_uiLibraryDoor = pGo->GetGUID(); break; - case 185521: m_uiMassiveDoor = pGo->GetGUID(); break; - case 184276: m_uiGamesmansDoor = pGo->GetGUID(); break; - case 184277: m_uiGamesmansExitDoor = pGo->GetGUID(); break; - case 185134: m_uiNetherspaceDoor = pGo->GetGUID(); break; - case 184274: MastersTerraceDoor[0] = pGo->GetGUID(); break; - case 184280: MastersTerraceDoor[1] = pGo->GetGUID(); break; - case 184275: - m_uiSideEntranceDoor = pGo->GetGUID(); - if (m_auiEncounter[4] == DONE) - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - else - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - break; - case 185119: DustCoveredChest = pGo->GetGUID(); break; - } - - switch(m_uiOperaEvent) - { - //TODO: Set Object visibilities for Opera based on performance - case EVENT_OZ: - break; - - case EVENT_HOOD: - break; - - case EVENT_RAJ: - break; - } - } - - std::string GetSaveData() - { - return strSaveData; - } - - uint32 GetData(uint32 uiData) - { - switch (uiData) - { - case TYPE_ATTUMEN: return m_auiEncounter[0]; - case TYPE_MOROES: return m_auiEncounter[1]; - case TYPE_MAIDEN: return m_auiEncounter[2]; - case TYPE_OPTIONAL_BOSS: return m_auiEncounter[3]; - case TYPE_OPERA: return m_auiEncounter[4]; - case TYPE_CURATOR: return m_auiEncounter[5]; - case TYPE_ARAN: return m_auiEncounter[6]; - case TYPE_TERESTIAN: return m_auiEncounter[7]; - case TYPE_NETHERSPITE: return m_auiEncounter[8]; - case TYPE_CHESS: return m_auiEncounter[9]; - case TYPE_MALCHEZZAR: return m_auiEncounter[10]; - case TYPE_NIGHTBANE: return m_auiEncounter[11]; - case DATA_OPERA_PERFORMANCE: return m_uiOperaEvent; - case DATA_OPERA_OZ_DEATHCOUNT: return m_uiOzDeathCount; - case DATA_IMAGE_OF_MEDIVH: return ImageGUID; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch (uiData) - { - case DATA_KILREK: return m_uiKilrekGUID; - case DATA_TERESTIAN: return m_uiTerestianGUID; - case DATA_MOROES: return m_uiMoroesGUID; - case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID; - case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID; - case DATA_GO_CURTAINS: return m_uiCurtainGUID; - case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor; - case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor; - case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor; - case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor; - case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor; - case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor; - case DATA_MASTERS_TERRACE_DOOR_1: return MastersTerraceDoor[0]; - case DATA_MASTERS_TERRACE_DOOR_2: return MastersTerraceDoor[1]; - } - - return 0; - } - - void Load(const char* chrIn) - { - if (!chrIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(chrIn); - std::istringstream loadStream(chrIn); - - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] - >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_karazhan(Map* pMap) -{ - return new instance_karazhan(pMap); -} - -void AddSC_instance_karazhan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_karazhan"; - newscript->GetInstanceData = &GetInstanceData_instance_karazhan; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp deleted file mode 100644 index 5186a794b0d..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/karazhan.cpp +++ /dev/null @@ -1,646 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Karazhan -SD%Complete: 100 -SDComment: Support for Barnes (Opera controller) and Berthold (Doorman), Support for Quest 9645. -SDCategory: Karazhan -EndScriptData */ - -/* ContentData -npc_barnes -npc_berthold -npc_image_of_medivh -EndContentData */ - -#include "ScriptedPch.h" -#include "karazhan.h" -#include "ScriptedEscortAI.h" - -/*###### -# npc_barnesAI -######*/ - -#define GOSSIP_READY "I'm not an actor." - -#define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!" -#define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?" -#define OZ_GOSSIP1 "I'm not an actor." -#define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!" -#define OZ_GOSSIP2 "Ok, I'll give it a try, then." - -#define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?" -#define RAJ_GOSSIP1 "I've never been more ready." - -#define OZ_GM_GOSSIP1 "[GM] Change event to EVENT_OZ" -#define OZ_GM_GOSSIP2 "[GM] Change event to EVENT_HOOD" -#define OZ_GM_GOSSIP3 "[GM] Change event to EVENT_RAJ" - -struct Dialogue -{ - int32 textid; - uint32 timer; -}; - -static Dialogue OzDialogue[]= -{ - {-1532103, 6000}, - {-1532104, 18000}, - {-1532105, 9000}, - {-1532106, 15000} -}; - -static Dialogue HoodDialogue[]= -{ - {-1532107, 6000}, - {-1532108, 10000}, - {-1532109, 14000}, - {-1532110, 15000} -}; - -static Dialogue RAJDialogue[]= -{ - {-1532111, 5000}, - {-1532112, 7000}, - {-1532113, 14000}, - {-1532114, 14000} -}; - -// Entries and spawn locations for creatures in Oz event -float Spawns[6][2]= -{ - {17535, -10896}, // Dorothee - {17546, -10891}, // Roar - {17547, -10884}, // Tinhead - {17543, -10902}, // Strawman - {17603, -10892}, // Grandmother - {17534, -10900}, // Julianne -}; - -#define CREATURE_SPOTLIGHT 19525 - -#define SPELL_SPOTLIGHT 25824 -#define SPELL_TUXEDO 32616 - -#define SPAWN_Z 90.5 -#define SPAWN_Y -1758 -#define SPAWN_O 4.738 - -struct npc_barnesAI : public npc_escortAI -{ - npc_barnesAI(Creature* c) : npc_escortAI(c) - { - RaidWiped = false; - m_uiEventId = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 m_uiSpotlightGUID; - - uint32 TalkCount; - uint32 TalkTimer; - uint32 WipeTimer; - uint32 m_uiEventId; - - bool PerformanceReady; - bool RaidWiped; - - void Reset() - { - m_uiSpotlightGUID = 0; - - TalkCount = 0; - TalkTimer = 2000; - WipeTimer = 5000; - - PerformanceReady = false; - - if (pInstance) - m_uiEventId = pInstance->GetData(DATA_OPERA_PERFORMANCE); - } - - void StartEvent() - { - if (!pInstance) - return; - - pInstance->SetData(TYPE_OPERA, IN_PROGRESS); - - //resets count for this event, in case earlier failed - if (m_uiEventId == EVENT_OZ) - pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS); - - Start(false, false); - } - - void EnterCombat(Unit* /*who*/) {} - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch(i) - { - case 0: - DoCast(me, SPELL_TUXEDO, false); - pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT)); - break; - case 4: - TalkCount = 0; - SetEscortPaused(true); - - if (Creature* pSpotlight = me->SummonCreature(CREATURE_SPOTLIGHT, - me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f, - TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000)) - { - pSpotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pSpotlight->CastSpell(pSpotlight, SPELL_SPOTLIGHT, false); - m_uiSpotlightGUID = pSpotlight->GetGUID(); - } - break; - case 8: - pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_STAGEDOORLEFT)); - PerformanceReady = true; - break; - case 9: - PrepareEncounter(); - pInstance->DoUseDoorOrButton(pInstance->GetData64(DATA_GO_CURTAINS)); - break; - } - } - - void Talk(uint32 count) - { - int32 text = 0; - - switch(m_uiEventId) - { - case EVENT_OZ: - if (OzDialogue[count].textid) - text = OzDialogue[count].textid; - if (OzDialogue[count].timer) - TalkTimer = OzDialogue[count].timer; - break; - - case EVENT_HOOD: - if (HoodDialogue[count].textid) - text = HoodDialogue[count].textid; - if (HoodDialogue[count].timer) - TalkTimer = HoodDialogue[count].timer; - break; - - case EVENT_RAJ: - if (RAJDialogue[count].textid) - text = RAJDialogue[count].textid; - if (RAJDialogue[count].timer) - TalkTimer = RAJDialogue[count].timer; - break; - } - - if (text) - DoScriptText(text, me); - } - - void PrepareEncounter() - { - debug_log("TSCR: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId); - uint8 index = 0; - uint8 count = 0; - - switch(m_uiEventId) - { - case EVENT_OZ: - index = 0; - count = 4; - break; - case EVENT_HOOD: - index = 4; - count = index+1; - break; - case EVENT_RAJ: - index = 5; - count = index+1; - break; - } - - for (; index < count; ++index) - { - uint32 entry = ((uint32)Spawns[index][0]); - float PosX = Spawns[index][1]; - - if (Creature* pCreature = me->SummonCreature(entry, PosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILISECONDS)) - { - // In case database has bad flags - pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - - RaidWiped = false; - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (HasEscortState(STATE_ESCORT_PAUSED)) - { - if (TalkTimer <= diff) - { - if (TalkCount > 3) - { - if (Creature* pSpotlight = Unit::GetCreature(*me, m_uiSpotlightGUID)) - pSpotlight->ForcedDespawn(); - - SetEscortPaused(false); - return; - } - - Talk(TalkCount); - ++TalkCount; - } else TalkTimer -= diff; - } - - if (PerformanceReady) - { - if (!RaidWiped) - { - if (WipeTimer <= diff) - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) - return; - - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (PlayerList.isEmpty()) - return; - - RaidWiped = true; - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive() && !i->getSource()->isGameMaster()) - { - RaidWiped = false; - break; - } - } - - if (RaidWiped) - { - RaidWiped = true; - EnterEvadeMode(); - return; - } - - WipeTimer = 15000; - } else WipeTimer -= diff; - } - - } - } -}; - -CreatureAI* GetAI_npc_barnesAI(Creature* pCreature) -{ - return new npc_barnesAI(pCreature); -} - -bool GossipHello_npc_barnes(Player* pPlayer, Creature* pCreature) -{ - if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) - { - // Check for death of Moroes and if opera event is not done already - if (pInstance->GetData(TYPE_MOROES) == DONE && pInstance->GetData(TYPE_OPERA) != DONE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (pPlayer->isGameMaster()) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - } - - if (npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI,pCreature->AI())) - { - if (!pBarnesAI->RaidWiped) - pPlayer->SEND_GOSSIP_MENU(8970, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(8975, pCreature->GetGUID()); - - return true; - } - } - } - - pPlayer->SEND_GOSSIP_MENU(8978, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_barnes(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - npc_barnesAI* pBarnesAI = CAST_AI(npc_barnesAI, pCreature->AI()); - - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(8971, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - pBarnesAI->StartEvent(); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - pBarnesAI->m_uiEventId = EVENT_OZ; - outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_OZ",pPlayer->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->CLOSE_GOSSIP_MENU(); - pBarnesAI->m_uiEventId = EVENT_HOOD; - outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_HOOD",pPlayer->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->CLOSE_GOSSIP_MENU(); - pBarnesAI->m_uiEventId = EVENT_RAJ; - outstring_log("TSCR: player (GUID %i) manually set Opera event to EVENT_RAJ",pPlayer->GetGUID()); - break; - } - - return true; -} - -/*### -# npc_berthold -####*/ - -enum eBerthold -{ - SPELL_TELEPORT = 39567 -}; - -#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library" - -bool GossipHello_npc_berthold(Player* pPlayer, Creature* pCreature) -{ - if (ScriptedInstance* pInstance = pCreature->GetInstanceData()) - { - // Check if Shade of Aran event is done - if (pInstance->GetData(TYPE_ARAN) == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - } - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_berthold(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, true); - - pPlayer->CLOSE_GOSSIP_MENU(); - return true; -} - -/*### -# npc_image_of_medivh -####*/ - -#define SAY_DIALOG_MEDIVH_1 "You've got my attention, dragon. You'll find I'm not as easily scared as the villagers below." -#define SAY_DIALOG_ARCANAGOS_2 "Your dabbling in the arcane has gone too far, Medivh. You've attracted the attention of powers beyond your understanding. You must leave Karazhan at once!" -#define SAY_DIALOG_MEDIVH_3 "You dare challenge me at my own dwelling? Your arrogance is astounding, even for a dragon!" -#define SAY_DIALOG_ARCANAGOS_4 "A dark power seeks to use you, Medivh! If you stay, dire days will follow. You must hurry, we don't have much time!" -#define SAY_DIALOG_MEDIVH_5 "I do not know what you speak of, dragon... but I will not be bullied by this display of insolence. I'll leave Karazhan when it suits me!" -#define SAY_DIALOG_ARCANAGOS_6 "You leave me no alternative. I will stop you by force if you won't listen to reason!" -#define EMOTE_DIALOG_MEDIVH_7 "begins to cast a spell of great power, weaving his own essence into the magic." -#define SAY_DIALOG_ARCANAGOS_8 "What have you done, wizard? This cannot be! I'm burning from... within!" -#define SAY_DIALOG_MEDIVH_9 "He should not have angered me. I must go... recover my strength now..." - -#define MOB_ARCANAGOS 17652 -#define SPELL_FIRE_BALL 30967 -#define SPELL_UBER_FIREBALL 30971 -#define SPELL_CONFLAGRATION_BLAST 30977 -#define SPELL_MANA_SHIELD 31635 - -static float MedivPos[4] = {-11161.49,-1902.24,91.48,1.94}; -static float ArcanagosPos[4] = {-11169.75,-1881.48,95.39,4.83}; - -struct npc_image_of_medivhAI : public ScriptedAI -{ - npc_image_of_medivhAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint64 ArcanagosGUID; - - uint32 YellTimer; - uint32 Step; - uint32 FireMedivhTimer; - uint32 FireArcanagosTimer; - - bool EventStarted; - - void Reset() - { - ArcanagosGUID = 0; - - if (pInstance && pInstance->GetData64(DATA_IMAGE_OF_MEDIVH) == 0) - { - pInstance->SetData64(DATA_IMAGE_OF_MEDIVH, me->GetGUID()); - (*me).GetMotionMaster()->MovePoint(1,MedivPos[0],MedivPos[1],MedivPos[2]); - Step = 0; - }else - { - me->DealDamage(me,me->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - } - } - void EnterCombat(Unit* /*who*/) {} - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - if (id == 1) - { - StartEvent(); - me->SetOrientation(MedivPos[3]); - me->SetOrientation(MedivPos[3]); - } - } - - void StartEvent() - { - Step = 1; - EventStarted = true; - Creature* Arcanagos = me->SummonCreature(MOB_ARCANAGOS,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - if (!Arcanagos) - return; - ArcanagosGUID = Arcanagos->GetGUID(); - Arcanagos->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - (*Arcanagos).GetMotionMaster()->MovePoint(0,ArcanagosPos[0],ArcanagosPos[1],ArcanagosPos[2]); - Arcanagos->SetOrientation(ArcanagosPos[3]); - me->SetOrientation(MedivPos[3]); - YellTimer = 10000; - } - - uint32 NextStep(uint32 Step) - { - Unit* arca = Unit::GetUnit((*me),ArcanagosGUID); - Map* pMap = me->GetMap(); - switch(Step) - { - case 0: return 9999999; - case 1: - me->MonsterYell(SAY_DIALOG_MEDIVH_1,LANG_UNIVERSAL,NULL); - return 10000; - case 2: - if (arca) - CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_2,LANG_UNIVERSAL,NULL); - return 20000; - case 3: - me->MonsterYell(SAY_DIALOG_MEDIVH_3,LANG_UNIVERSAL,NULL); - return 10000; - case 4: - if (arca) - CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL, NULL); - return 20000; - case 5: - me->MonsterYell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL, NULL); - return 20000; - case 6: - if (arca) - CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL, NULL); - return 10000; - case 7: - FireArcanagosTimer = 500; - return 5000; - case 8: - FireMedivhTimer = 500; - DoCast(me, SPELL_MANA_SHIELD); - return 10000; - case 9: - me->MonsterTextEmote(EMOTE_DIALOG_MEDIVH_7, 0, false); - return 10000; - case 10: - if (arca) - DoCast(arca, SPELL_CONFLAGRATION_BLAST, false); - return 1000; - case 11: - if (arca) - CAST_CRE(arca)->MonsterYell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL, NULL); - return 5000; - case 12: - arca->GetMotionMaster()->MovePoint(0, -11010.82,-1761.18, 156.47); - arca->setActive(true); - arca->InterruptNonMeleeSpells(true); - arca->SetSpeed(MOVE_FLIGHT, 2.0f); - return 10000; - case 13: - me->MonsterYell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL, NULL); - return 10000; - case 14: - me->SetVisibility(VISIBILITY_OFF); - me->ClearInCombat(); - - if (pMap->IsDungeon()) - { - InstanceMap::PlayerList const &PlayerList = pMap->GetPlayers(); - for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive()) - { - if (i->getSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE) - i->getSource()->CompleteQuest(9645); - } - } - } - return 50000; - case 15: - arca->DealDamage(arca,arca->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return 5000; - default : return 9999999; - } - - } - - void UpdateAI(const uint32 diff) - { - - if (YellTimer <= diff) - { - if (EventStarted) - YellTimer = NextStep(Step++); - } else YellTimer -= diff; - - if (Step >= 7 && Step <= 12) - { - Unit* arca = Unit::GetUnit((*me),ArcanagosGUID); - - if (FireArcanagosTimer <= diff) - { - if (arca) - arca->CastSpell(me, SPELL_FIRE_BALL, false); - FireArcanagosTimer = 6000; - } else FireArcanagosTimer -= diff; - - if (FireMedivhTimer <= diff) - { - if (arca) - DoCast(arca, SPELL_FIRE_BALL); - FireMedivhTimer = 5000; - } else FireMedivhTimer -= diff; - } - } -}; - -CreatureAI* GetAI_npc_image_of_medivh(Creature* pCreature) -{ - return new npc_image_of_medivhAI(pCreature); -} - -void AddSC_karazhan() -{ - Script* newscript; - - newscript = new Script; - newscript->GetAI = &GetAI_npc_barnesAI; - newscript->Name = "npc_barnes"; - newscript->pGossipHello = &GossipHello_npc_barnes; - newscript->pGossipSelect = &GossipSelect_npc_barnes; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_berthold"; - newscript->pGossipHello = &GossipHello_npc_berthold; - newscript->pGossipSelect = &GossipSelect_npc_berthold; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_image_of_medivh"; - newscript->GetAI = &GetAI_npc_image_of_medivh; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/karazhan/karazhan.h b/src/server/scripts/EasternKingdoms/karazhan/karazhan.h deleted file mode 100644 index 56a6b106332..00000000000 --- a/src/server/scripts/EasternKingdoms/karazhan/karazhan.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_KARAZHAN_H -#define DEF_KARAZHAN_H - -enum eEnums -{ - TYPE_ATTUMEN = 1, - TYPE_MOROES = 2, - TYPE_MAIDEN = 3, - TYPE_OPTIONAL_BOSS = 4, - TYPE_OPERA = 5, - TYPE_CURATOR = 6, - TYPE_ARAN = 7, - TYPE_TERESTIAN = 8, - TYPE_NETHERSPITE = 9, - TYPE_CHESS = 10, - TYPE_MALCHEZZAR = 11, - TYPE_NIGHTBANE = 12, - - DATA_OPERA_PERFORMANCE = 13, - DATA_OPERA_OZ_DEATHCOUNT = 14, - - DATA_KILREK = 15, - DATA_TERESTIAN = 16, - DATA_MOROES = 17, - DATA_GO_CURTAINS = 18, - DATA_GO_STAGEDOORLEFT = 19, - DATA_GO_STAGEDOORRIGHT = 20, - DATA_GO_LIBRARY_DOOR = 21, - DATA_GO_MASSIVE_DOOR = 22, - DATA_GO_NETHER_DOOR = 23, - DATA_GO_GAME_DOOR = 24, - DATA_GO_GAME_EXIT_DOOR = 25, - - DATA_IMAGE_OF_MEDIVH = 26, - DATA_MASTERS_TERRACE_DOOR_1 = 27, - DATA_MASTERS_TERRACE_DOOR_2 = 28, - DATA_GO_SIDE_ENTRANCE_DOOR = 29 -}; - -enum OperaEvents -{ - EVENT_OZ = 1, - EVENT_HOOD = 2, - EVENT_RAJ = 3 -}; - -#define ERROR_INST_DATA(a) error_log("TSCR: Instance Data for Karazhan not set properly. Encounter for Creature Entry %u may not work properly.", a->GetEntry()); -#endif - diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp deleted file mode 100644 index b5835dfe0a1..00000000000 --- a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_felblood_kaelthas.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Felblood_Kaelthas -SD%Complete: 80 -SDComment: Normal and Heroic Support. Issues: Arcane Spheres do not initially follow targets. -SDCategory: Magisters' Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" -#include "WorldPacket.h" - -#define SAY_AGGRO -1585023 //This yell should be done when the room is cleared. For now, set it as a movelineofsight yell. -#define SAY_PHOENIX -1585024 -#define SAY_FLAMESTRIKE -1585025 -#define SAY_GRAVITY_LAPSE -1585026 -#define SAY_TIRED -1585027 -#define SAY_RECAST_GRAVITY -1585028 -#define SAY_DEATH -1585029 - -/*** Spells ***/ - -// Phase 1 spells -#define SPELL_FIREBALL_NORMAL 44189 // Deals 2700-3300 damage at current target -#define SPELL_FIREBALL_HEROIC 46164 // 4950-6050 - -#define SPELL_PHOENIX 44194 // Summons a phoenix (Doesn't work?) -#define SPELL_PHOENIX_BURN 44197 // A spell Phoenix uses to damage everything around -#define SPELL_REBIRTH_DMG 44196 // DMG if a Phoenix rebirth happen - -#define SPELL_FLAMESTRIKE1_NORMAL 44190 // Damage part -#define SPELL_FLAMESTRIKE1_HEROIC 46163 // Heroic damage part -#define SPELL_FLAMESTRIKE2 44191 // Flamestrike indicator before the damage -#define SPELL_FLAMESTRIKE3 44192 // Summons the trigger + animation (projectile) - -#define SPELL_SHOCK_BARRIER 46165 // Heroic only; 10k damage shield, followed by Pyroblast -#define SPELL_PYROBLAST 36819 // Heroic only; 45-55k fire damage - -// Phase 2 spells -#define SPELL_GRAVITY_LAPSE_INITIAL 44224 // Cast at the beginning of every Gravity Lapse -#define SPELL_GRAVITY_LAPSE_CHANNEL 44251 // Channeled; blue beam animation to every enemy in range -#define SPELL_TELEPORT_CENTER 44218 // Should teleport people to the center. Requires DB entry in spell_target_position. -#define SPELL_GRAVITY_LAPSE_FLY 44227 // Hastens flyspeed and allows flying for 1 minute. For some reason removes 44226. -#define SPELL_GRAVITY_LAPSE_DOT 44226 // Knocks up in the air and applies a 300 DPS DoT. -#define SPELL_ARCANE_SPHERE_PASSIVE 44263 // Passive auras on Arcane Spheres -#define SPELL_POWER_FEEDBACK 44233 // Stuns him, making him take 50% more damage for 10 seconds. Cast after Gravity Lapse - -/*** Creatures ***/ -#define CREATURE_PHOENIX 24674 -#define CREATURE_PHOENIX_EGG 24675 -#define CREATURE_ARCANE_SPHERE 24708 - -/** Locations **/ -float KaelLocations[3][2]= -{ - {148.744659, 181.377426}, - {140.823883, 195.403046}, - {156.574188, 195.650482}, -}; - -#define LOCATION_Z -16.727455 - -struct boss_felblood_kaelthasAI : public ScriptedAI -{ - boss_felblood_kaelthasAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 FireballTimer; - uint32 PhoenixTimer; - uint32 FlameStrikeTimer; - uint32 CombatPulseTimer; - - //Heroic only - uint32 PyroblastTimer; - - uint32 GravityLapseTimer; - uint32 GravityLapsePhase; - // 0 = No Gravity Lapse - // 1 = Casting Gravity Lapse visual - // 2 = Teleported people to self - // 3 = Knocked people up in the air - // 4 = Applied an aura that allows them to fly, channeling visual, relased Arcane Orbs. - - bool FirstGravityLapse; - bool HasTaunted; - - uint8 Phase; - // 0 = Not started - // 1 = Fireball; Summon Phoenix; Flamestrike - // 2 = Gravity Lapses - - void Reset() - { - // TODO: Timers - FireballTimer = 0; - PhoenixTimer = 10000; - FlameStrikeTimer = 25000; - CombatPulseTimer = 0; - - PyroblastTimer = 60000; - - GravityLapseTimer = 0; - GravityLapsePhase = 0; - - FirstGravityLapse = true; - HasTaunted = false; - - Phase = 0; - - if (pInstance) - { - pInstance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), true); - // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here) - // Small door opened after event are expected to be closed by default - } - } - - void JustDied(Unit * /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), true); - // Open the encounter door - } - - void DamageTaken(Unit* /*done_by*/, uint32 &damage) - { - if (damage > me->GetHealth()) - RemoveGravityLapse(); // Remove Gravity Lapse so that players fall to ground if they kill him when in air. - } - - void EnterCombat(Unit * /*who*/) - { - if (!pInstance) - return; - - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_DOOR), false); - //Close the encounter door, open it in JustDied/Reset - } - - void MoveInLineOfSight(Unit *who) - { - if (!HasTaunted && me->IsWithinDistInMap(who, 40.0)) - { - DoScriptText(SAY_AGGRO, me); - HasTaunted = true; - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void SetThreatList(Creature* SummonedUnit) - { - if (!SummonedUnit) - return; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - std::list::const_iterator i = m_threatlist.begin(); - for (i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - { - float threat = me->getThreatManager().getThreat(pUnit); - SummonedUnit->AddThreat(pUnit, threat); - } - } - } - - void TeleportPlayersToSelf() - { - float x = KaelLocations[0][0]; - float y = KaelLocations[0][1]; - me->GetMap()->CreatureRelocation(me, x, y, LOCATION_Z, 0.0f); - //me->SendMonsterMove(x, y, LOCATION_Z, 0, 0, 0); // causes some issues... - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - pUnit->CastSpell(pUnit, SPELL_TELEPORT_CENTER, true); - } - DoCast(me, SPELL_TELEPORT_CENTER, true); - } - - void CastGravityLapseKnockUp() - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - // Knockback into the air - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, me->GetGUID()); - } - } - - void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - // Also needs an exception in spell system. - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, me->GetGUID()); - // Use packet hack - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - } - - void RemoveGravityLapse() - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); - pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); - - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - switch(Phase) - { - case 0: - { - // *Heroic mode only: - if (IsHeroic()) - { - if (PyroblastTimer <= diff) - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - DoCast(me, SPELL_SHOCK_BARRIER, true); - DoCast(me->getVictim(), SPELL_PYROBLAST); - PyroblastTimer = 60000; - } else PyroblastTimer -= diff; - } - - if (FireballTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL_NORMAL); - FireballTimer = urand(2000,6000); - } else FireballTimer -= diff; - - if (PhoenixTimer <= diff) - { - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - - uint8 random = urand(1,2); - float x = KaelLocations[random][0]; - float y = KaelLocations[random][1]; - - Creature* Phoenix = me->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - if (Phoenix) - { - Phoenix->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - SetThreatList(Phoenix); - Phoenix->AI()->AttackStart(pTarget); - } - - DoScriptText(SAY_PHOENIX, me); - - PhoenixTimer = 60000; - } else PhoenixTimer -= diff; - - if (FlameStrikeTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - DoCast(pTarget, SPELL_FLAMESTRIKE3, true); - DoScriptText(SAY_FLAMESTRIKE, me); - } - FlameStrikeTimer = urand(15000,25000); - } else FlameStrikeTimer -= diff; - - // Below 50% - if (me->GetMaxHealth() * 0.5 > me->GetHealth()) - { - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - GravityLapseTimer = 0; - GravityLapsePhase = 0; - Phase = 1; - } - - DoMeleeAttackIfReady(); - } - break; - - case 1: - { - if (GravityLapseTimer <= diff) - { - switch(GravityLapsePhase) - { - case 0: - if (FirstGravityLapse) // Different yells at 50%, and at every following Gravity Lapse - { - DoScriptText(SAY_GRAVITY_LAPSE, me); - FirstGravityLapse = false; - - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_STATUE_LEFT), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_KAEL_STATUE_RIGHT), true); - } - }else - { - DoScriptText(SAY_RECAST_GRAVITY, me); - } - - DoCast(me, SPELL_GRAVITY_LAPSE_INITIAL); - GravityLapseTimer = 2000 + diff;// Don't interrupt the visual spell - GravityLapsePhase = 1; - break; - - case 1: - TeleportPlayersToSelf(); - GravityLapseTimer = 1000; - GravityLapsePhase = 2; - break; - - case 2: - CastGravityLapseKnockUp(); - GravityLapseTimer = 1000; - GravityLapsePhase = 3; - break; - - case 3: - CastGravityLapseFly(); - GravityLapseTimer = 30000; - GravityLapsePhase = 4; - - for (uint8 i = 0; i < 3; ++i) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); - if (Orb && pTarget) - { - Orb->SetSpeed(MOVE_RUN, 0.5f); - Orb->AddThreat(pTarget, 1000000.0f); - Orb->AI()->AttackStart(pTarget); - } - - } - - DoCast(me, SPELL_GRAVITY_LAPSE_CHANNEL); - break; - - case 4: - me->InterruptNonMeleeSpells(false); - DoScriptText(SAY_TIRED, me); - DoCast(me, SPELL_POWER_FEEDBACK); - RemoveGravityLapse(); - GravityLapseTimer = 10000; - GravityLapsePhase = 0; - break; - } - } else GravityLapseTimer -= diff; - } - break; - } - } -}; - -struct mob_felkael_flamestrikeAI : public ScriptedAI -{ - mob_felkael_flamestrikeAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 FlameStrikeTimer; - - void Reset() - { - FlameStrikeTimer = 5000; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - - DoCast(me, SPELL_FLAMESTRIKE2, true); - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (FlameStrikeTimer <= diff) - { - DoCast(me, SPELL_FLAMESTRIKE1_NORMAL, true); - me->Kill(me); - } else FlameStrikeTimer -= diff; - } -}; - -struct mob_felkael_phoenixAI : public ScriptedAI -{ - mob_felkael_phoenixAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 BurnTimer; - uint32 Death_Timer; - bool Rebirth; - bool FakeDeath; - - void Reset() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - DoCast(me, SPELL_PHOENIX_BURN, true); - BurnTimer = 2000; - Death_Timer = 3000; - Rebirth = false; - FakeDeath = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage < me->GetHealth()) - return; - - //Prevent glitch if in fake death - if (FakeDeath) - { - damage = 0; - return; - - } - //Don't really die in all phases of Kael'Thas - if (pInstance && pInstance->GetData(DATA_KAELTHAS_EVENT) == 0) - { - //prevent death - damage = 0; - FakeDeath = true; - - me->InterruptNonMeleeSpells(false); - me->SetHealth(0); - me->StopMoving(); - me->ClearComboPointHolders(); - me->RemoveAllAurasOnDeath(); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->ClearAllReactives(); - me->SetUInt64Value(UNIT_FIELD_TARGET,0); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - - } - - } - - void JustDied(Unit* /*slayer*/) - { - me->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); - } - - void UpdateAI(const uint32 diff) - { - - //If we are fake death, we cast revbirth and after that we kill the phoenix to spawn the egg. - if (FakeDeath) - { - if (!Rebirth) - { - DoCast(me, SPELL_REBIRTH_DMG); - Rebirth = true; - } - - if (Rebirth) - { - - if (Death_Timer <= diff) - { - me->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); - me->DisappearAndDie(); - Rebirth = false; - } else Death_Timer -= diff; - } - - } - - if (!UpdateVictim()) - return; - - if (BurnTimer <= diff) - { - //spell Burn should possible do this, but it doesn't, so do this for now. - uint16 dmg = urand(1650,2050); - me->DealDamage(me, dmg, 0, DOT, SPELL_SCHOOL_MASK_FIRE, NULL, false); - BurnTimer += 2000; - } BurnTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_felkael_phoenix_eggAI : public ScriptedAI -{ - mob_felkael_phoenix_eggAI(Creature *c) : ScriptedAI(c) {} - - uint32 HatchTimer; - - void Reset() - { - HatchTimer = 10000; - } - - void EnterCombat(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (HatchTimer <= diff) - { - me->SummonCreature(CREATURE_PHOENIX, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - me->Kill(me); - } else HatchTimer -= diff; - - } -}; - -struct mob_arcane_sphereAI : public ScriptedAI -{ - mob_arcane_sphereAI(Creature *c) : ScriptedAI(c) { Reset(); } - - uint32 DespawnTimer; - uint32 ChangeTargetTimer; - - void Reset() - { - DespawnTimer = 30000; - ChangeTargetTimer = urand(6000,12000); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->setFaction(14); - DoCast(me, SPELL_ARCANE_SPHERE_PASSIVE, true); - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (DespawnTimer <= diff) - me->Kill(me); - else - DespawnTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (ChangeTargetTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - } - - ChangeTargetTimer = urand(5000,15000); - } else ChangeTargetTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_felblood_kaelthas(Creature* c) -{ - return new boss_felblood_kaelthasAI(c); -} - -CreatureAI* GetAI_mob_arcane_sphere(Creature* c) -{ - return new mob_arcane_sphereAI(c); -} - -CreatureAI* GetAI_mob_felkael_phoenix(Creature* c) -{ - return new mob_felkael_phoenixAI(c); -} - -CreatureAI* GetAI_mob_felkael_phoenix_egg(Creature* c) -{ - return new mob_felkael_phoenix_eggAI(c); -} - -CreatureAI* GetAI_mob_felkael_flamestrike(Creature* c) -{ - return new mob_felkael_flamestrikeAI(c); -} - -void AddSC_boss_felblood_kaelthas() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_felblood_kaelthas"; - newscript->GetAI = &GetAI_boss_felblood_kaelthas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_arcane_sphere"; - newscript->GetAI = &GetAI_mob_arcane_sphere; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felkael_phoenix"; - newscript->GetAI = &GetAI_mob_felkael_phoenix; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felkael_phoenix_egg"; - newscript->GetAI = &GetAI_mob_felkael_phoenix_egg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felkael_flamestrike"; - newscript->GetAI = &GetAI_mob_felkael_flamestrike; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp deleted file mode 100644 index 2112eaabc87..00000000000 --- a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_priestess_delrissa.cpp +++ /dev/null @@ -1,1321 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Priestess_Delrissa -SD%Complete: 65 -SDComment: No Heroic support yet. Needs further testing. Several scripts for pets disabled, not seem to require any special script. -SDCategory: Magister's Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" - -struct Speech -{ - int32 id; -}; - -static Speech LackeyDeath[]= -{ - {-1585013}, - {-1585014}, - {-1585015}, - {-1585016}, -}; - -static Speech PlayerDeath[]= -{ - {-1585017}, - {-1585018}, - {-1585019}, - {-1585020}, - {-1585021}, -}; - -enum eEnums -{ - SAY_AGGRO = -1585012, - SAY_DEATH = -1585022, - - SPELL_DISPEL_MAGIC = 27609, - SPELL_FLASH_HEAL = 17843, - SPELL_SW_PAIN_NORMAL = 14032, - SPELL_SW_PAIN_HEROIC = 15654, - SPELL_SHIELD = 44291, - SPELL_RENEW_NORMAL = 44174, - SPELL_RENEW_HEROIC = 46192, - - MAX_ACTIVE_LACKEY = 4 -}; - -const float fOrientation = 4.98; -const float fZLocation = -19.921; - -float LackeyLocations[4][2]= -{ - {123.77, 17.6007}, - {131.731, 15.0827}, - {121.563, 15.6213}, - {129.988, 17.2355}, -}; - -const uint32 m_auiAddEntries[] = -{ - 24557, //Kagani Nightstrike - 24558, //Elris Duskhallow - 24554, //Eramas Brightblaze - 24561, //Yazzaj - 24559, //Warlord Salaris - 24555, //Garaxxas - 24553, //Apoko - 24556, //Zelfan -}; - -struct boss_priestess_delrissaAI : public ScriptedAI -{ - boss_priestess_delrissaAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - memset(&m_auiLackeyGUID, 0, sizeof(m_auiLackeyGUID)); - LackeyEntryList.clear(); - } - - ScriptedInstance* pInstance; - - std::vector LackeyEntryList; - uint64 m_auiLackeyGUID[MAX_ACTIVE_LACKEY]; - - uint8 PlayersKilled; - - uint32 HealTimer; - uint32 RenewTimer; - uint32 ShieldTimer; - uint32 SWPainTimer; - uint32 DispelTimer; - uint32 ResetTimer; - - void Reset() - { - PlayersKilled = 0; - - HealTimer = 15000; - RenewTimer = 10000; - ShieldTimer = 2000; - SWPainTimer = 5000; - DispelTimer = 7500; - ResetTimer = 5000; - - InitializeLackeys(); - } - - //this mean she at some point evaded - void JustReachedHome() - { - if (pInstance) - pInstance->SetData(DATA_DELRISSA_EVENT, FAIL); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me); - - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[i])) - { - if (!pAdd->getVictim()) - { - who->SetInCombatWith(pAdd); - pAdd->AddThreat(who, 0.0f); - } - } - } - - if (pInstance) - pInstance->SetData(DATA_DELRISSA_EVENT, IN_PROGRESS); - } - - void InitializeLackeys() - { - //can be called if Creature are dead, so avoid - if (!me->isAlive()) - return; - - uint8 j = 0; - - //it's empty, so first time - if (LackeyEntryList.empty()) - { - //pre-allocate size for speed - LackeyEntryList.resize((sizeof(m_auiAddEntries) / sizeof(uint32))); - - //fill vector array with entries from Creature array - for (uint8 i = 0; i < LackeyEntryList.size(); ++i) - LackeyEntryList[i] = m_auiAddEntries[i]; - - //remove random entries - while (LackeyEntryList.size() > MAX_ACTIVE_LACKEY) - LackeyEntryList.erase(LackeyEntryList.begin() + rand()%LackeyEntryList.size()); - - //summon all the remaining in vector - for (std::vector::const_iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr) - { - if (Creature* pAdd = me->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0)) - m_auiLackeyGUID[j] = pAdd->GetGUID(); - - ++j; - } - } - else - { - for (std::vector::const_iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr) - { - Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[j]); - - //object already removed, not exist - if (!pAdd) - { - if (Creature* pAdd = me->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0)) - m_auiLackeyGUID[j] = pAdd->GetGUID(); - } - ++j; - } - } - } - - void KilledUnit(Unit* victim) - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(PlayerDeath[PlayersKilled].id, me); - - if (PlayersKilled < 4) - ++PlayersKilled; - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - if (pInstance->GetData(DATA_DELRISSA_DEATH_COUNT) == MAX_ACTIVE_LACKEY) - pInstance->SetData(DATA_DELRISSA_EVENT, DONE); - else - { - if (me->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ResetTimer <= diff) - { - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - if (me->GetPositionZ() >= z+10) - { - EnterEvadeMode(); - return; - } - ResetTimer = 5000; - } else ResetTimer -= diff; - - if (HealTimer <= diff) - { - uint32 health = me->GetHealth(); - Unit *pTarget = me; - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[i])) - { - if (pAdd->isAlive() && pAdd->GetHealth() < health) - pTarget = pAdd; - } - } - - DoCast(pTarget, SPELL_FLASH_HEAL); - HealTimer = 15000; - } else HealTimer -= diff; - - if (RenewTimer <= diff) - { - Unit *pTarget = me; - - if (urand(0,1)) - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) - if (pAdd->isAlive()) - pTarget = pAdd; - - DoCast(pTarget, SPELL_RENEW_NORMAL); - RenewTimer = 5000; - } else RenewTimer -= diff; - - if (ShieldTimer <= diff) - { - Unit *pTarget = me; - - if (urand(0,1)) - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) - if (pAdd->isAlive() && !pAdd->HasAura(SPELL_SHIELD)) - pTarget = pAdd; - - DoCast(pTarget, SPELL_SHIELD); - ShieldTimer = 7500; - } else ShieldTimer -= diff; - - if (DispelTimer <= diff) - { - Unit *pTarget = NULL; - bool friendly = false; - - if (urand(0,1)) - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - else - { - friendly = true; - - if (urand(0,1)) - pTarget = me; - else - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY])) - if (pAdd->isAlive()) - pTarget = pAdd; - } - - if (pTarget) - DoCast(pTarget, SPELL_DISPEL_MAGIC); - - DispelTimer = 12000; - } else DispelTimer -= diff; - - if (SWPainTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SW_PAIN_NORMAL); - - SWPainTimer = 10000; - } else SWPainTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_priestess_delrissa(Creature* pCreature) -{ - return new boss_priestess_delrissaAI(pCreature); -} - -enum eHealingPotion -{ - SPELL_HEALING_POTION = 15503 -}; - -//all 8 possible lackey use this common -struct boss_priestess_lackey_commonAI : public ScriptedAI -{ - boss_priestess_lackey_commonAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - memset(&m_auiLackeyGUIDs, 0, sizeof(m_auiLackeyGUIDs)); - AcquireGUIDs(); - } - - ScriptedInstance* pInstance; - - uint64 m_auiLackeyGUIDs[MAX_ACTIVE_LACKEY]; - uint32 ResetThreatTimer; - - bool UsedPotion; - - void Reset() - { - UsedPotion = false; - - // These guys does not follow normal threat system rules - // For later development, some alternative threat system should be made - // We do not know what this system is based upon, but one theory is class (healers=high threat, dps=medium, etc) - // We reset their threat frequently as an alternative until such a system exist - ResetThreatTimer = urand(5000,20000); - - // in case she is not alive and Reset was for some reason called, respawn her (most likely party wipe after killing her) - if (Creature* pDelrissa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DELRISSA) : 0)) - { - if (!pDelrissa->isAlive()) - pDelrissa->Respawn(); - } - } - - void EnterCombat(Unit* pWho) - { - if (!pWho) - return; - - if (pInstance) - { - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUIDs[i])) - { - if (!pAdd->getVictim() && pAdd != me) - { - pWho->SetInCombatWith(pAdd); - pAdd->AddThreat(pWho, 0.0f); - } - } - } - - if (Creature* pDelrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA))) - { - if (pDelrissa->isAlive() && !pDelrissa->getVictim()) - { - pWho->SetInCombatWith(pDelrissa); - pDelrissa->AddThreat(pWho, 0.0f); - } - } - } - } - - void JustDied(Unit* /*killer*/) - { - if (!pInstance) - return; - - Creature* pDelrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA)); - uint32 uiLackeyDeathCount = pInstance->GetData(DATA_DELRISSA_DEATH_COUNT); - - if (!pDelrissa) - return; - - //should delrissa really yell if dead? - DoScriptText(LackeyDeath[uiLackeyDeathCount].id, pDelrissa); - - pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, SPECIAL); - - //increase local var, since we now may have four dead - ++uiLackeyDeathCount; - - if (uiLackeyDeathCount == MAX_ACTIVE_LACKEY) - { - //time to make her lootable and complete event if she died before lackeys - if (!pDelrissa->isAlive()) - { - if (!pDelrissa->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) - pDelrissa->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - - pInstance->SetData(DATA_DELRISSA_EVENT, DONE); - } - } - } - - void KilledUnit(Unit* victim) - { - if (!pInstance) - return; - - if (Creature* Delrissa = Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA))) - Delrissa->AI()->KilledUnit(victim); - } - - void AcquireGUIDs() - { - if (!pInstance) - return; - - if (Creature* Delrissa = (Unit::GetCreature(*me, pInstance->GetData64(DATA_DELRISSA)))) - { - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - m_auiLackeyGUIDs[i] = CAST_AI(boss_priestess_delrissaAI, Delrissa->AI())->m_auiLackeyGUID[i]; - } - } - - void UpdateAI(const uint32 diff) - { - if (!UsedPotion && (me->GetHealth()*100 / me->GetMaxHealth()) < 25) - { - DoCast(me, SPELL_HEALING_POTION); - UsedPotion = true; - } - - if (ResetThreatTimer <= diff) - { - DoResetThreat(); - ResetThreatTimer = 5000 + rand()%15000; - } else ResetThreatTimer -= diff; - } -}; - -enum eRogueSpells -{ - SPELL_KIDNEY_SHOT = 27615, - SPELL_GOUGE = 12540, - SPELL_KICK = 27613, - SPELL_VANISH = 44290, - SPELL_BACKSTAB = 15657, - SPELL_EVISCERATE = 27611 -}; - -struct boss_kagani_nightstrikeAI : public boss_priestess_lackey_commonAI -{ - //Rogue - boss_kagani_nightstrikeAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Gouge_Timer; - uint32 Kick_Timer; - uint32 Vanish_Timer; - uint32 Eviscerate_Timer; - uint32 Wait_Timer; - bool InVanish; - - void Reset() - { - Gouge_Timer = 5500; - Kick_Timer = 7000; - Vanish_Timer = 2000; - Eviscerate_Timer = 6000; - Wait_Timer = 5000; - InVanish = false; - me->SetVisibility(VISIBILITY_ON); - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Vanish_Timer <= diff) - { - DoCast(me, SPELL_VANISH); - - Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0); - - DoResetThreat(); - - if (pUnit) - me->AddThreat(pUnit, 1000.0f); - - InVanish = true; - Vanish_Timer = 30000; - Wait_Timer = 10000; - } else Vanish_Timer -= diff; - - if (InVanish) - { - if (Wait_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BACKSTAB, true); - DoCast(me->getVictim(), SPELL_KIDNEY_SHOT, true); - me->SetVisibility(VISIBILITY_ON); // ...? Hacklike - InVanish = false; - } else Wait_Timer -= diff; - } - - if (Gouge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GOUGE); - Gouge_Timer = 5500; - } else Gouge_Timer -= diff; - - if (Kick_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KICK); - Kick_Timer = 7000; - } else Kick_Timer -= diff; - - if (Eviscerate_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_EVISCERATE); - Eviscerate_Timer = 4000; - } else Eviscerate_Timer -= diff; - - if (!InVanish) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kagani_nightstrike(Creature* pCreature) -{ - return new boss_kagani_nightstrikeAI(pCreature); -} - -enum eWarlockSpells -{ - SPELL_IMMOLATE = 44267, - SPELL_SHADOW_BOLT = 12471, - SPELL_SEED_OF_CORRUPTION = 44141, - SPELL_CURSE_OF_AGONY = 14875, - SPELL_FEAR = 38595, - SPELL_IMP_FIREBALL = 44164, - SPELL_SUMMON_IMP = 44163 -}; - -struct boss_ellris_duskhallowAI : public boss_priestess_lackey_commonAI -{ - //Warlock - boss_ellris_duskhallowAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Immolate_Timer; - uint32 Shadow_Bolt_Timer; - uint32 Seed_of_Corruption_Timer; - uint32 Curse_of_Agony_Timer; - uint32 Fear_Timer; - - void Reset() - { - Immolate_Timer = 6000; - Shadow_Bolt_Timer = 3000; - Seed_of_Corruption_Timer = 2000; - Curse_of_Agony_Timer = 1000; - Fear_Timer = 10000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void Aggro(Unit* /*pWho*/) - { - DoCast(me, SPELL_SUMMON_IMP); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Immolate_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_IMMOLATE); - Immolate_Timer = 6000; - } else Immolate_Timer -= diff; - - if (Shadow_Bolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - Shadow_Bolt_Timer = 5000; - } else Shadow_Bolt_Timer -= diff; - - if (Seed_of_Corruption_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_SEED_OF_CORRUPTION); - - Seed_of_Corruption_Timer = 10000; - } else Seed_of_Corruption_Timer -= diff; - - if (Curse_of_Agony_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_CURSE_OF_AGONY); - - Curse_of_Agony_Timer = 13000; - } else Curse_of_Agony_Timer -= diff; - - if (Fear_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_FEAR); - - Fear_Timer = 10000; - } else Fear_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_ellris_duskhallow(Creature* pCreature) -{ - return new boss_ellris_duskhallowAI(pCreature); -} - -enum eKickDown -{ - SPELL_KNOCKDOWN = 11428, - SPELL_SNAP_KICK = 46182 -}; - -struct boss_eramas_brightblazeAI : public boss_priestess_lackey_commonAI -{ - //Monk - boss_eramas_brightblazeAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Knockdown_Timer; - uint32 Snap_Kick_Timer; - - void Reset() - { - Knockdown_Timer = 6000; - Snap_Kick_Timer = 4500; - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Knockdown_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - Knockdown_Timer = 6000; - } else Knockdown_Timer -= diff; - - if (Snap_Kick_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SNAP_KICK); - Snap_Kick_Timer = 4500; - } else Snap_Kick_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_eramas_brightblaze(Creature* pCreature) -{ - return new boss_eramas_brightblazeAI(pCreature); -} - -enum eMageSpells -{ - SPELL_POLYMORPH = 13323, - SPELL_ICE_BLOCK = 27619, - SPELL_BLIZZARD = 44178, - SPELL_ICE_LANCE = 46194, - SPELL_CONE_OF_COLD = 38384, - SPELL_FROSTBOLT = 15043, - SPELL_BLINK = 14514 -}; - -struct boss_yazzaiAI : public boss_priestess_lackey_commonAI -{ - //Mage - boss_yazzaiAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - bool HasIceBlocked; - - uint32 Polymorph_Timer; - uint32 Ice_Block_Timer; - uint32 Wait_Timer; - uint32 Blizzard_Timer; - uint32 Ice_Lance_Timer; - uint32 Cone_of_Cold_Timer; - uint32 Frostbolt_Timer; - uint32 Blink_Timer; - - void Reset() - { - HasIceBlocked = false; - - Polymorph_Timer = 1000; - Ice_Block_Timer = 20000; - Wait_Timer = 10000; - Blizzard_Timer = 8000; - Ice_Lance_Timer = 12000; - Cone_of_Cold_Timer = 10000; - Frostbolt_Timer = 3000; - Blink_Timer = 8000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Polymorph_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_POLYMORPH); - Polymorph_Timer = 20000; - } - } else Polymorph_Timer -= diff; - - if (((me->GetHealth()*100 / me->GetMaxHealth()) < 35) && !HasIceBlocked) - { - DoCast(me, SPELL_ICE_BLOCK); - HasIceBlocked = true; - } - - if (Blizzard_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_BLIZZARD); - - Blizzard_Timer = 8000; - } else Blizzard_Timer -= diff; - - if (Ice_Lance_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ICE_LANCE); - Ice_Lance_Timer = 12000; - } else Ice_Lance_Timer -= diff; - - if (Cone_of_Cold_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CONE_OF_COLD); - Cone_of_Cold_Timer = 10000; - } else Cone_of_Cold_Timer -= diff; - - if (Frostbolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - Frostbolt_Timer = 8000; - } else Frostbolt_Timer -= diff; - - if (Blink_Timer <= diff) - { - bool InMeleeRange = false; - std::list& t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - //if in melee range - if (pTarget->IsWithinDistInMap(me, 5)) - { - InMeleeRange = true; - break; - } - } - } - - //if anybody is in melee range than escape by blink - if (InMeleeRange) - DoCast(me, SPELL_BLINK); - - Blink_Timer = 8000; - } else Blink_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_yazzai(Creature* pCreature) -{ - return new boss_yazzaiAI(pCreature); -} - -enum eWarriorSpells -{ - SPELL_INTERCEPT_STUN = 27577, - SPELL_DISARM = 27581, - SPELL_PIERCING_HOWL = 23600, - SPELL_FRIGHTENING_SHOUT = 19134, - SPELL_HAMSTRING = 27584, - SPELL_BATTLE_SHOUT = 27578, - SPELL_MORTAL_STRIKE = 44268 -}; - -struct boss_warlord_salarisAI : public boss_priestess_lackey_commonAI -{ - //Warrior - boss_warlord_salarisAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Intercept_Stun_Timer; - uint32 Disarm_Timer; - uint32 Piercing_Howl_Timer; - uint32 Frightening_Shout_Timer; - uint32 Hamstring_Timer; - uint32 Mortal_Strike_Timer; - - void Reset() - { - Intercept_Stun_Timer = 500; - Disarm_Timer = 6000; - Piercing_Howl_Timer = 10000; - Frightening_Shout_Timer = 18000; - Hamstring_Timer = 4500; - Mortal_Strike_Timer = 8000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_BATTLE_SHOUT); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Intercept_Stun_Timer <= diff) - { - bool InMeleeRange = false; - std::list& t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - if (Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - //if in melee range - if (pTarget->IsWithinDistInMap(me, ATTACK_DISTANCE)) - { - InMeleeRange = true; - break; - } - } - } - - //if nobody is in melee range than try to use Intercept - if (!InMeleeRange) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_INTERCEPT_STUN); - } - - Intercept_Stun_Timer = 10000; - } else Intercept_Stun_Timer -= diff; - - if (Disarm_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DISARM); - Disarm_Timer = 6000; - } else Disarm_Timer -= diff; - - if (Hamstring_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - Hamstring_Timer = 4500; - } else Hamstring_Timer -= diff; - - if (Mortal_Strike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - Mortal_Strike_Timer = 4500; - } else Mortal_Strike_Timer -= diff; - - if (Piercing_Howl_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PIERCING_HOWL); - Piercing_Howl_Timer = 10000; - } else Piercing_Howl_Timer -= diff; - - if (Frightening_Shout_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); - Frightening_Shout_Timer = 18000; - } else Frightening_Shout_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_warlord_salaris(Creature* pCreature) -{ - return new boss_warlord_salarisAI(pCreature); -} - -enum eHunterSpells -{ - SPELL_AIMED_SHOT = 44271, - SPELL_SHOOT = 15620, - SPELL_CONCUSSIVE_SHOT = 27634, - SPELL_MULTI_SHOT = 31942, - SPELL_WING_CLIP = 44286, - SPELL_FREEZING_TRAP = 44136, - - NPC_SLIVER = 24552 -}; - -struct boss_garaxxasAI : public boss_priestess_lackey_commonAI -{ - //Hunter - boss_garaxxasAI(Creature *c) : boss_priestess_lackey_commonAI(c) { m_uiPetGUID = 0; } - - uint64 m_uiPetGUID; - - uint32 Aimed_Shot_Timer; - uint32 Shoot_Timer; - uint32 Concussive_Shot_Timer; - uint32 Multi_Shot_Timer; - uint32 Wing_Clip_Timer; - uint32 Freezing_Trap_Timer; - - void Reset() - { - Aimed_Shot_Timer = 6000; - Shoot_Timer = 2500; - Concussive_Shot_Timer = 8000; - Multi_Shot_Timer = 10000; - Wing_Clip_Timer = 4000; - Freezing_Trap_Timer = 15000; - - Unit* pPet = Unit::GetUnit(*me,m_uiPetGUID); - if (!pPet) - me->SummonCreature(NPC_SLIVER, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - - boss_priestess_lackey_commonAI::Reset(); - } - - void JustSummoned(Creature* pSummoned) - { - m_uiPetGUID = pSummoned->GetGUID(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (me->IsWithinDistInMap(me->getVictim(), ATTACK_DISTANCE)) - { - if (Wing_Clip_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WING_CLIP); - Wing_Clip_Timer = 4000; - } else Wing_Clip_Timer -= diff; - - if (Freezing_Trap_Timer <= diff) - { - //attempt find go summoned from spell (casted by me) - GameObject* pGo = me->GetGameObject(SPELL_FREEZING_TRAP); - - //if we have a pGo, we need to wait (only one trap at a time) - if (pGo) - Freezing_Trap_Timer = 2500; - else - { - //if pGo does not exist, then we can cast - DoCast(me->getVictim(), SPELL_FREEZING_TRAP); - Freezing_Trap_Timer = 15000; - } - } else Freezing_Trap_Timer -= diff; - - DoMeleeAttackIfReady(); - } - else - { - if (Concussive_Shot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CONCUSSIVE_SHOT); - Concussive_Shot_Timer = 8000; - } else Concussive_Shot_Timer -= diff; - - if (Multi_Shot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MULTI_SHOT); - Multi_Shot_Timer = 10000; - } else Multi_Shot_Timer -= diff; - - if (Aimed_Shot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_AIMED_SHOT); - Aimed_Shot_Timer = 6000; - } else Aimed_Shot_Timer -= diff; - - if (Shoot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHOOT); - Shoot_Timer = 2500; - } else Shoot_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_garaxxas(Creature* pCreature) -{ - return new boss_garaxxasAI(pCreature); -} - -enum Spells -{ - SPELL_WINDFURY_TOTEM = 27621, - SPELL_WAR_STOMP = 46026, - SPELL_PURGE = 27626, - SPELL_LESSER_HEALING_WAVE = 44256, - SPELL_FROST_SHOCK = 21401, - SPELL_FIRE_NOVA_TOTEM = 44257, - SPELL_EARTHBIND_TOTEM = 15786 -}; - -struct boss_apokoAI : public boss_priestess_lackey_commonAI -{ - //Shaman - boss_apokoAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Totem_Timer; - uint8 Totem_Amount; - uint32 War_Stomp_Timer; - uint32 Purge_Timer; - uint32 Healing_Wave_Timer; - uint32 Frost_Shock_Timer; - - void Reset() - { - Totem_Timer = 2000; - Totem_Amount = 1; - War_Stomp_Timer = 10000; - Purge_Timer = 8000; - Healing_Wave_Timer = 5000; - Frost_Shock_Timer = 7000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Totem_Timer <= diff) - { - DoCast(me, RAND(SPELL_WINDFURY_TOTEM,SPELL_FIRE_NOVA_TOTEM,SPELL_EARTHBIND_TOTEM)); - ++Totem_Amount; - Totem_Timer = Totem_Amount*2000; - } else Totem_Timer -= diff; - - if (War_Stomp_Timer <= diff) - { - DoCast(me, SPELL_WAR_STOMP); - War_Stomp_Timer = 10000; - } else War_Stomp_Timer -= diff; - - if (Purge_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_PURGE); - - Purge_Timer = 15000; - } else Purge_Timer -= diff; - - if (Frost_Shock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_SHOCK); - Frost_Shock_Timer = 7000; - } else Frost_Shock_Timer -= diff; - - if (Healing_Wave_Timer <= diff) - { - // std::vector::const_iterator itr = Group.begin() + rand()%Group.size(); - // uint64 guid = (*itr)->guid; - // if (guid) - // { - // Unit* pAdd = Unit::GetUnit(*me, (*itr)->guid); - // if (pAdd && pAdd->isAlive()) - // { - DoCast(me, SPELL_LESSER_HEALING_WAVE); - Healing_Wave_Timer = 5000; - // } - // } - } else Healing_Wave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_apoko(Creature* pCreature) -{ - return new boss_apokoAI(pCreature); -} - -enum eEngineerSpells -{ - SPELL_GOBLIN_DRAGON_GUN = 44272, - SPELL_ROCKET_LAUNCH = 44137, - SPELL_RECOMBOBULATE = 44274, - SPELL_HIGH_EXPLOSIVE_SHEEP = 44276, - SPELL_FEL_IRON_BOMB = 46024, - SPELL_SHEEP_EXPLOSION = 44279 -}; - -struct boss_zelfanAI : public boss_priestess_lackey_commonAI -{ - //Engineer - boss_zelfanAI(Creature *c) : boss_priestess_lackey_commonAI(c) {} - - uint32 Goblin_Dragon_Gun_Timer; - uint32 Rocket_Launch_Timer; - uint32 Recombobulate_Timer; - uint32 High_Explosive_Sheep_Timer; - uint32 Fel_Iron_Bomb_Timer; - - void Reset() - { - Goblin_Dragon_Gun_Timer = 20000; - Rocket_Launch_Timer = 7000; - Recombobulate_Timer = 4000; - High_Explosive_Sheep_Timer = 10000; - Fel_Iron_Bomb_Timer = 15000; - - boss_priestess_lackey_commonAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - boss_priestess_lackey_commonAI::UpdateAI(diff); - - if (Goblin_Dragon_Gun_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GOBLIN_DRAGON_GUN); - Goblin_Dragon_Gun_Timer = 10000; - } else Goblin_Dragon_Gun_Timer -= diff; - - if (Rocket_Launch_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ROCKET_LAUNCH); - Rocket_Launch_Timer = 9000; - } else Rocket_Launch_Timer -= diff; - - if (Fel_Iron_Bomb_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FEL_IRON_BOMB); - Fel_Iron_Bomb_Timer = 15000; - } else Fel_Iron_Bomb_Timer -= diff; - - if (Recombobulate_Timer <= diff) - { - for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { - if (Unit* pAdd = Unit::GetUnit(*me, m_auiLackeyGUIDs[i])) - { - if (pAdd->IsPolymorphed()) - { - DoCast(pAdd, SPELL_RECOMBOBULATE); - break; - } - } - } - Recombobulate_Timer = 2000; - } else Recombobulate_Timer -= diff; - - if (High_Explosive_Sheep_Timer <= diff) - { - DoCast(me, SPELL_HIGH_EXPLOSIVE_SHEEP); - High_Explosive_Sheep_Timer = 65000; - } else High_Explosive_Sheep_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_zelfan(Creature* pCreature) -{ - return new boss_zelfanAI(pCreature); -} - -//struct mob_high_explosive_sheepAI : public ScriptedAI -//{ -// mob_high_explosive_sheepAI(Creature *c) : ScriptedAI(c) {} -// -// uint32 Explosion_Timer; -// -// void Reset() -// { -// Explosion_Timer = 60000; -// } -// -// void JustDied(Unit *Killer){} -// -// void EnterCombat(Unit * /*who*/){} -// -// void UpdateAI(const uint32 diff) -// { -// if (Explosion_Timer <= diff) -// { -// DoCast(me->getVictim(), SPELL_SHEEP_EXPLOSION); -// }else -// Explosion_Timer -= diff; -// } -//}; - -//CreatureAI* GetAI_mob_high_explosive_sheep(Creature* pCreature) -//{ -// return new mob_high_explosive_sheepAI (pCreature); -//}; - -void AddSC_boss_priestess_delrissa() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_priestess_delrissa"; - newscript->GetAI = &GetAI_boss_priestess_delrissa; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_kagani_nightstrike"; - newscript->GetAI = &GetAI_boss_kagani_nightstrike; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_ellris_duskhallow"; - newscript->GetAI = &GetAI_ellris_duskhallow; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_eramas_brightblaze"; - newscript->GetAI = &GetAI_eramas_brightblaze; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_yazzai"; - newscript->GetAI = &GetAI_yazzai; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_warlord_salaris"; - newscript->GetAI = &GetAI_warlord_salaris; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_garaxxas"; - newscript->GetAI = &GetAI_garaxxas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_apoko"; - newscript->GetAI = &GetAI_apoko; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_zelfan"; - newscript->GetAI = &GetAI_zelfan; - newscript->RegisterSelf(); - - /*newscript = new Script; - newscript->Name = "mob_high_explosive_sheep"; - newscript->GetAI = &GetAI_mob_high_explosive_sheep; - newscript->RegisterSelf();*/ -} - diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp deleted file mode 100644 index adb0700eabf..00000000000 --- a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_selin_fireheart.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Selin_Fireheart -SD%Complete: 90 -SDComment: Heroic and Normal Support. Needs further testing. -SDCategory: Magister's Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" - -#define SAY_AGGRO -1585000 -#define SAY_ENERGY -1585001 -#define SAY_EMPOWERED -1585002 -#define SAY_KILL_1 -1585003 -#define SAY_KILL_2 -1585004 -#define SAY_DEATH -1585005 -#define EMOTE_CRYSTAL -1585006 - -//Crystal effect spells -#define SPELL_FEL_CRYSTAL_COSMETIC 44374 -#define SPELL_FEL_CRYSTAL_DUMMY 44329 -#define SPELL_FEL_CRYSTAL_VISUAL 44355 -#define SPELL_MANA_RAGE 44320 // This spell triggers 44321, which changes scale and regens mana Requires an entry in spell_script_target - -//Selin's spells -#define SPELL_DRAIN_LIFE 44294 -#define SPELL_FEL_EXPLOSION 44314 - -#define SPELL_DRAIN_MANA 46153 // Heroic only - -#define CRYSTALS_NUMBER 5 -#define DATA_CRYSTALS 6 - -#define CREATURE_FEL_CRYSTAL 24722 - -struct boss_selin_fireheartAI : public ScriptedAI -{ - boss_selin_fireheartAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - - Crystals.clear(); - //GUIDs per instance is static, so we only need to load them once. - if (pInstance) - { - uint32 size = pInstance->GetData(DATA_FEL_CRYSTAL_SIZE); - for (uint8 i = 0; i < size; ++i) - { - uint64 guid = pInstance->GetData64(DATA_FEL_CRYSTAL); - debug_log("TSCR: Selin: Adding Fel Crystal %u to list", guid); - Crystals.push_back(guid); - } - } - } - - ScriptedInstance* pInstance; - - std::list Crystals; - - uint32 DrainLifeTimer; - uint32 DrainManaTimer; - uint32 FelExplosionTimer; - uint32 DrainCrystalTimer; - uint32 EmpowerTimer; - - bool IsDraining; - bool DrainingCrystal; - - uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course). - - void Reset() - { - if (pInstance) - { - //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) - for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) - { - //Unit* pUnit = Unit::GetUnit(*me, FelCrystals[i]); - Unit* pUnit = Unit::GetUnit(*me, *itr); - if (pUnit) - { - if (!pUnit->isAlive()) - CAST_CRE(pUnit)->Respawn(); // Let the core handle setting death state, etc. - - // Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here. - pUnit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - } - - pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); - // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here) - // Small door opened after event are expected to be closed by default - // Set Inst data for encounter - pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED); - } else error_log(ERROR_INST_DATA); - - DrainLifeTimer = 3000 + rand()%4000; - DrainManaTimer = DrainLifeTimer + 5000; - FelExplosionTimer = 2100; - DrainCrystalTimer = 10000 + rand()%5000; - DrainCrystalTimer = 20000 + rand()%5000; - EmpowerTimer = 10000; - - IsDraining = false; - DrainingCrystal = false; - CrystalGUID = 0; - } - - void SelectNearestCrystal() - { - if (Crystals.empty()) - return; - - //float ShortestDistance = 0; - CrystalGUID = 0; - Unit* pCrystal = NULL; - Unit* CrystalChosen = NULL; - //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) - for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) - { - pCrystal = NULL; - //pCrystal = Unit::GetUnit(*me, FelCrystals[i]); - pCrystal = Unit::GetUnit(*me, *itr); - if (pCrystal && pCrystal->isAlive()) - { - // select nearest - if (!CrystalChosen || me->GetDistanceOrder(pCrystal, CrystalChosen, false)) - { - CrystalGUID = pCrystal->GetGUID(); - CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell. - } - } - } - if (CrystalChosen) - { - DoScriptText(SAY_ENERGY, me); - DoScriptText(EMOTE_CRYSTAL, me); - - CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true); - - float x, y, z; // coords that we move to, close to the crystal. - CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE); - - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->MovePoint(1, x, y, z); - DrainingCrystal = true; - } - } - - void ShatterRemainingCrystals() - { - if (Crystals.empty()) - return; - - //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i) - for (std::list::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr) - { - //Creature* pCrystal = (Unit::GetCreature(*me, FelCrystals[i])); - Creature* pCrystal = Unit::GetCreature(*me, *itr); - if (pCrystal && pCrystal->isAlive()) - pCrystal->Kill(pCrystal); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), false); - //Close the encounter door, open it in JustDied/Reset - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type == POINT_MOTION_TYPE && id == 1) - { - Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID); - if (CrystalChosen && CrystalChosen->isAlive()) - { - // Make the crystal attackable - // We also remove NON_ATTACKABLE in case the database has it set. - CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - CrystalChosen->CastSpell(me, SPELL_MANA_RAGE, true); - IsDraining = true; - } - else - { - // Make an error message in case something weird happened here - error_log("TSCR: Selin Fireheart unable to drain crystal as the crystal is either dead or despawned"); - DrainingCrystal = false; - } - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - pInstance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete! - pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); // Open the encounter door - pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_DOOR), true); // Open the door leading further in - ShatterRemainingCrystals(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!DrainingCrystal) - { - uint32 maxPowerMana = me->GetMaxPower(POWER_MANA); - if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10)) - { - if (DrainLifeTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE); - DrainLifeTimer = 10000; - } else DrainLifeTimer -= diff; - - // Heroic only - if (IsHeroic()) - { - if (DrainManaTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_DRAIN_MANA); - DrainManaTimer = 10000; - } else DrainManaTimer -= diff; - } - } - - if (FelExplosionTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_FEL_EXPLOSION); - FelExplosionTimer = 2000; - } - } else FelExplosionTimer -= diff; - - // If below 10% mana, start recharging - maxPowerMana = me->GetMaxPower(POWER_MANA); - if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10)) - { - if (DrainCrystalTimer <= diff) - { - SelectNearestCrystal(); - if (IsHeroic()) - DrainCrystalTimer = 10000 + rand()%5000; - else - DrainCrystalTimer = 20000 + rand()%5000; - } else DrainCrystalTimer -= diff; - } - - }else - { - if (IsDraining) - { - if (EmpowerTimer <= diff) - { - IsDraining = false; - DrainingCrystal = false; - - DoScriptText(SAY_EMPOWERED, me); - - Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID); - if (CrystalChosen && CrystalChosen->isAlive()) - // Use Deal Damage to kill it, not setDeathState. - CrystalChosen->Kill(CrystalChosen); - - CrystalGUID = 0; - - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } else EmpowerTimer -= diff; - } - } - - DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun. - } -}; - -CreatureAI* GetAI_boss_selin_fireheart(Creature* pCreature) -{ - return new boss_selin_fireheartAI (pCreature); -}; - -struct mob_fel_crystalAI : public ScriptedAI -{ - mob_fel_crystalAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} - - void JustDied(Unit* /*killer*/) - { - if (ScriptedInstance* pInstance = me->GetInstanceData()) - { - Creature* Selin = (Unit::GetCreature(*me, pInstance->GetData64(DATA_SELIN))); - if (Selin && Selin->isAlive()) - { - if (CAST_AI(boss_selin_fireheartAI, Selin->AI())->CrystalGUID == me->GetGUID()) - { - // Set this to false if we are the Creature that Selin is draining so his AI flows properly - CAST_AI(boss_selin_fireheartAI, Selin->AI())->DrainingCrystal = false; - CAST_AI(boss_selin_fireheartAI, Selin->AI())->IsDraining = false; - CAST_AI(boss_selin_fireheartAI, Selin->AI())->EmpowerTimer = 10000; - if (Selin->getVictim()) - { - Selin->AI()->AttackStart(Selin->getVictim()); - Selin->GetMotionMaster()->MoveChase(Selin->getVictim()); - } - } - } - } else error_log(ERROR_INST_DATA); - } -}; - -CreatureAI* GetAI_mob_fel_crystal(Creature* pCreature) -{ - return new mob_fel_crystalAI (pCreature); -}; - -void AddSC_boss_selin_fireheart() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_selin_fireheart"; - newscript->GetAI = &GetAI_boss_selin_fireheart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fel_crystal"; - newscript->GetAI = &GetAI_mob_fel_crystal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp deleted file mode 100644 index bc8bd5cec30..00000000000 --- a/src/server/scripts/EasternKingdoms/magisters_terrace/boss_vexallus.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Vexallus -SD%Complete: 90 -SDComment: Heroic and Normal support. Needs further testing. -SDCategory: Magister's Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" - -enum eEnums -{ - SAY_AGGRO = -1585007, - SAY_ENERGY = -1585008, - SAY_OVERLOAD = -1585009, - SAY_KILL = -1585010, - EMOTE_DISCHARGE_ENERGY = -1585011, - - //is this text for real? - //#define SAY_DEATH "What...happen...ed." - - //Pure energy spell info - SPELL_ENERGY_BOLT = 46156, - SPELL_ENERGY_FEEDBACK = 44335, - - //Vexallus spell info - SPELL_CHAIN_LIGHTNING = 44318, - SPELL_H_CHAIN_LIGHTNING = 46380, //heroic spell - SPELL_OVERLOAD = 44353, - SPELL_ARCANE_SHOCK = 44319, - SPELL_H_ARCANE_SHOCK = 46381, //heroic spell - - SPELL_SUMMON_PURE_ENERGY = 44322, //mod scale -10 - H_SPELL_SUMMON_PURE_ENERGY1 = 46154, //mod scale -5 - H_SPELL_SUMMON_PURE_ENERGY2 = 46159, //mod scale -5 - - //Creatures - NPC_PURE_ENERGY = 24745, - - INTERVAL_MODIFIER = 15, - INTERVAL_SWITCH = 6 -}; - -struct boss_vexallusAI : public ScriptedAI -{ - boss_vexallusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ChainLightningTimer; - uint32 ArcaneShockTimer; - uint32 OverloadTimer; - uint32 IntervalHealthAmount; - bool Enraged; - - void Reset() - { - ChainLightningTimer = 8000; - ArcaneShockTimer = 5000; - OverloadTimer = 1200; - IntervalHealthAmount = 1; - Enraged = false; - - if (pInstance) - pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_VEXALLUS_EVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature *summoned) - { - if (Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 0)) - summoned->GetMotionMaster()->MoveFollow(temp,0,0); - - //spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok - summoned->CastSpell(summoned,SPELL_ENERGY_BOLT,false,0,0,me->GetGUID()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!Enraged) - { - //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25% - if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(INTERVAL_MODIFIER*IntervalHealthAmount))) - { - //increase amount, unless we're at 10%, then we switch and return - if (IntervalHealthAmount == INTERVAL_SWITCH) - { - Enraged = true; - return; - } - else - ++IntervalHealthAmount; - - DoScriptText(SAY_ENERGY, me); - DoScriptText(EMOTE_DISCHARGE_ENERGY, me); - - if (IsHeroic()) - { - DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false); - DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false); - } - else - DoCast(me, SPELL_SUMMON_PURE_ENERGY, false); - - //below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core - me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (IsHeroic()) - me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - } - - if (ChainLightningTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - - ChainLightningTimer = 8000; - } else ChainLightningTimer -= diff; - - if (ArcaneShockTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - if (pTarget) - DoCast(pTarget, SPELL_ARCANE_SHOCK); - - ArcaneShockTimer = 8000; - } else ArcaneShockTimer -= diff; - } - else - { - if (OverloadTimer <= diff) - { - DoCast(me->getVictim(), SPELL_OVERLOAD); - - OverloadTimer = 2000; - } else OverloadTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vexallus(Creature* pCreature) -{ - return new boss_vexallusAI (pCreature); -}; - -struct mob_pure_energyAI : public ScriptedAI -{ - mob_pure_energyAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - - void JustDied(Unit* slayer) - { - if (Unit *temp = me->GetOwner()) - { - if (temp && temp->isAlive()) - slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID()); - } - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - void AttackStart(Unit * /*who*/) {} -}; - -CreatureAI* GetAI_mob_pure_energy(Creature* pCreature) -{ - return new mob_pure_energyAI (pCreature); -}; - -void AddSC_boss_vexallus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_vexallus"; - newscript->GetAI = &GetAI_boss_vexallus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_pure_energy"; - newscript->GetAI = &GetAI_mob_pure_energy; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp deleted file mode 100644 index 455c03739bc..00000000000 --- a/src/server/scripts/EasternKingdoms/magisters_terrace/instance_magisters_terrace.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Magisters_Terrace -SD%Complete: 60 -SDComment: Designed only for Selin Fireheart -SDCategory: Magister's Terrace -EndScriptData */ - -#include "ScriptedPch.h" -#include "magisters_terrace.h" - -#define MAX_ENCOUNTER 4 - -/* -0 - Selin Fireheart -1 - Vexallus -2 - Priestess Delrissa -3 - Kael'thas Sunstrider -*/ - -struct instance_magisters_terrace : public ScriptedInstance -{ - instance_magisters_terrace(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 DelrissaDeathCount; - - std::list FelCrystals; - std::list::const_iterator CrystalItr; - - uint64 SelinGUID; - uint64 DelrissaGUID; - uint64 VexallusDoorGUID; - uint64 SelinDoorGUID; - uint64 SelinEncounterDoorGUID; - uint64 DelrissaDoorGUID; - uint64 KaelDoorGUID; - uint64 KaelStatue[2]; - - bool InitializedItr; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - FelCrystals.clear(); - - DelrissaDeathCount = 0; - - SelinGUID = 0; - DelrissaGUID = 0; - VexallusDoorGUID = 0; - SelinDoorGUID = 0; - SelinEncounterDoorGUID = 0; - DelrissaDoorGUID = 0; - KaelDoorGUID = 0; - KaelStatue[0] = 0; - KaelStatue[1] = 0; - - InitializedItr = false; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - return false; - } - - uint32 GetData(uint32 identifier) - { - switch(identifier) - { - case DATA_SELIN_EVENT: return m_auiEncounter[0]; - case DATA_VEXALLUS_EVENT: return m_auiEncounter[1]; - case DATA_DELRISSA_EVENT: return m_auiEncounter[2]; - case DATA_KAELTHAS_EVENT: return m_auiEncounter[3]; - case DATA_DELRISSA_DEATH_COUNT: return DelrissaDeathCount; - case DATA_FEL_CRYSTAL_SIZE: return FelCrystals.size(); - } - return 0; - } - - void SetData(uint32 identifier, uint32 data) - { - switch(identifier) - { - case DATA_SELIN_EVENT: m_auiEncounter[0] = data; break; - case DATA_VEXALLUS_EVENT: - if (data == DONE) - DoUseDoorOrButton(VexallusDoorGUID); - m_auiEncounter[1] = data; - break; - case DATA_DELRISSA_EVENT: - if (data == DONE) - DoUseDoorOrButton(DelrissaDoorGUID); - if (data == IN_PROGRESS) - DelrissaDeathCount = 0; - m_auiEncounter[2] = data; - break; - case DATA_KAELTHAS_EVENT: m_auiEncounter[3] = data; break; - - case DATA_DELRISSA_DEATH_COUNT: - if (data == SPECIAL) - ++DelrissaDeathCount; - else - DelrissaDeathCount = 0; - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 24723: SelinGUID = pCreature->GetGUID(); break; - case 24560: DelrissaGUID = pCreature->GetGUID(); break; - case 24722: FelCrystals.push_back(pCreature->GetGUID()); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 187896: VexallusDoorGUID = pGo->GetGUID(); break; - //SunwellRaid Gate 02 - case 187979: SelinDoorGUID = pGo->GetGUID(); break; - //Assembly Chamber Door - case 188065: SelinEncounterDoorGUID = pGo->GetGUID(); break; - case 187770: DelrissaDoorGUID = pGo->GetGUID(); break; - case 188064: KaelDoorGUID = pGo->GetGUID(); break; - case 188165: KaelStatue[0] = pGo->GetGUID(); break; - case 188166: KaelStatue[1] = pGo->GetGUID(); break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_SELIN: return SelinGUID; - case DATA_DELRISSA: return DelrissaGUID; - case DATA_VEXALLUS_DOOR: return VexallusDoorGUID; - case DATA_SELIN_DOOR: return SelinDoorGUID; - case DATA_SELIN_ENCOUNTER_DOOR: return SelinEncounterDoorGUID; - case DATA_DELRISSA_DOOR: return DelrissaDoorGUID; - case DATA_KAEL_DOOR: return KaelDoorGUID; - case DATA_KAEL_STATUE_LEFT: return KaelStatue[0]; - case DATA_KAEL_STATUE_RIGHT: return KaelStatue[1]; - - case DATA_FEL_CRYSTAL: - { - if (FelCrystals.empty()) - { - error_log("TSCR: Magisters Terrace: No Fel Crystals loaded in Inst Data"); - return 0; - } - - if (!InitializedItr) - { - CrystalItr = FelCrystals.begin(); - InitializedItr = true; - } - - uint64 guid = *CrystalItr; - ++CrystalItr; - return guid; - } - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_magisters_terrace(Map* pMap) -{ - return new instance_magisters_terrace(pMap); -} - -void AddSC_instance_magisters_terrace() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_magisters_terrace"; - newscript->GetInstanceData = &GetInstanceData_instance_magisters_terrace; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp deleted file mode 100644 index e46da9cb1bf..00000000000 --- a/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Magisters_Terrace -SD%Complete: 100 -SDComment: Quest support: 11490(post-event) -SDCategory: Magisters Terrace -EndScriptData */ - -/* ContentData -npc_kalecgos -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_kalecgos -######*/ - -enum eEnums -{ - SPELL_TRANSFORM_TO_KAEL = 44670, - SPELL_ORB_KILL_CREDIT = 46307, - NPC_KAEL = 24848, //human form entry - POINT_ID_LAND = 1 -}; - -const float afKaelLandPoint[] = {225.045, -276.236, -5.434}; - -#define GOSSIP_ITEM_KAEL_1 "Who are you?" -#define GOSSIP_ITEM_KAEL_2 "What can we do to assist you?" -#define GOSSIP_ITEM_KAEL_3 "What brings you to the Sunwell?" -#define GOSSIP_ITEM_KAEL_4 "You're not alone here?" -#define GOSSIP_ITEM_KAEL_5 "What would Kil'jaeden want with a mortal woman?" - -// This is friendly keal that appear after used Orb. -// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is -struct npc_kalecgosAI : public ScriptedAI -{ - npc_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 m_uiTransformTimer; - - void Reset() - { - m_uiTransformTimer = 0; - - // we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here - if (me->GetEntry() != NPC_KAEL) - me->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]); - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (uiPointId == POINT_ID_LAND) - m_uiTransformTimer = MINUTE*IN_MILISECONDS; - } - - // some targeting issues with the spell, so use this workaround as temporary solution - void DoWorkaroundForQuestCredit() - { - Map* pMap = me->GetMap(); - - if (!pMap || pMap->IsHeroic()) - return; - - Map::PlayerList const &lList = pMap->GetPlayers(); - - if (lList.isEmpty()) - return; - - SpellEntry const* pSpell = GetSpellStore()->LookupEntry(SPELL_ORB_KILL_CREDIT); - - for (Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pSpell && pSpell->EffectMiscValue[0]) - pPlayer->KilledMonsterCredit(pSpell->EffectMiscValue[0], 0); - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_uiTransformTimer) - { - if (m_uiTransformTimer <= uiDiff) - { - DoCast(me, SPELL_ORB_KILL_CREDIT, false); - DoWorkaroundForQuestCredit(); - - // Transform and update entry, now ready for quest/read gossip - DoCast(me, SPELL_TRANSFORM_TO_KAEL, false); - me->UpdateEntry(NPC_KAEL); - - m_uiTransformTimer = 0; - } else m_uiTransformTimer -= uiDiff; - } - } -}; - -CreatureAI* GetAI_npc_kalecgos(Creature* pCreature) -{ - return new npc_kalecgosAI(pCreature); -} - -bool GossipHello_npc_kalecgos(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(12498, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_kalecgos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(12500, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(12502, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(12606, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - pPlayer->SEND_GOSSIP_MENU(12607, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->SEND_GOSSIP_MENU(12608, pCreature->GetGUID()); - break; - } - - return true; -} - -void AddSC_magisters_terrace() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_kalecgos"; - newscript->GetAI = &GetAI_npc_kalecgos; - newscript->pGossipHello = &GossipHello_npc_kalecgos; - newscript->pGossipSelect = &GossipSelect_npc_kalecgos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h deleted file mode 100644 index d6419ea409c..00000000000 --- a/src/server/scripts/EasternKingdoms/magisters_terrace/magisters_terrace.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_MAGISTERS_TERRACE_H -#define DEF_MAGISTERS_TERRACE_H - -#define DATA_SELIN_EVENT 1 -#define DATA_VEXALLUS_EVENT 2 -#define DATA_DELRISSA_EVENT 3 -#define DATA_KAELTHAS_EVENT 4 - -#define DATA_SELIN 5 -#define DATA_FEL_CRYSTAL 6 -#define DATA_FEL_CRYSTAL_SIZE 7 - -#define DATA_VEXALLUS_DOOR 8 -#define DATA_SELIN_DOOR 9 -#define DATA_DELRISSA 10 -#define DATA_DELRISSA_DOOR 11 -#define DATA_SELIN_ENCOUNTER_DOOR 12 - -#define DATA_KAEL_DOOR 13 -#define DATA_KAEL_STATUE_LEFT 14 -#define DATA_KAEL_STATUE_RIGHT 15 - -#define DATA_DELRISSA_DEATH_COUNT 16 - -#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy." -#endif - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp deleted file mode 100644 index 77c6fafa10a..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_baron_geddon.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Baron_Geddon -SD%Complete: 100 -SDComment: -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_SERVICE -1409000 - -#define SPELL_INFERNO 19695 -#define SPELL_IGNITEMANA 19659 -#define SPELL_LIVINGBOMB 20475 -#define SPELL_ARMAGEDDOM 20479 - -struct boss_baron_geddonAI : public ScriptedAI -{ - boss_baron_geddonAI(Creature *c) : ScriptedAI(c) {} - - uint32 Inferno_Timer; - uint32 IgniteMana_Timer; - uint32 LivingBomb_Timer; - - void Reset() - { - Inferno_Timer = 45000; //These times are probably wrong - IgniteMana_Timer = 30000; - LivingBomb_Timer = 35000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <2% hp cast Armageddom - if (me->GetHealth()*100 / me->GetMaxHealth() <= 2) - { - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_ARMAGEDDOM); - DoScriptText(EMOTE_SERVICE, me); - return; - } - - //Inferno_Timer - if (Inferno_Timer <= diff) - { - DoCast(me, SPELL_INFERNO); - Inferno_Timer = 45000; - } else Inferno_Timer -= diff; - - //IgniteMana_Timer - if (IgniteMana_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_IGNITEMANA); - - IgniteMana_Timer = 30000; - } else IgniteMana_Timer -= diff; - - //LivingBomb_Timer - if (LivingBomb_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LIVINGBOMB); - - LivingBomb_Timer = 35000; - } else LivingBomb_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_baron_geddon(Creature* pCreature) -{ - return new boss_baron_geddonAI (pCreature); -} - -void AddSC_boss_baron_geddon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_baron_geddon"; - newscript->GetAI = &GetAI_boss_baron_geddon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp deleted file mode 100644 index 75891cf8c43..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_garr.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Garr -SD%Complete: 50 -SDComment: Adds NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -// Garr spells -#define SPELL_ANTIMAGICPULSE 19492 -#define SPELL_MAGMASHACKLES 19496 -#define SPELL_ENRAGE 19516 //Stacking enrage (stacks to 10 times) - -//Add spells -#define SPELL_ERUPTION 19497 -#define SPELL_IMMOLATE 20294 - -struct boss_garrAI : public ScriptedAI -{ - boss_garrAI(Creature *c) : ScriptedAI(c) {} - - uint32 AntiMagicPulse_Timer; - uint32 MagmaShackles_Timer; - uint32 CheckAdds_Timer; - uint64 Add[8]; - bool Enraged[8]; - - void Reset() - { - AntiMagicPulse_Timer = 25000; //These times are probably wrong - MagmaShackles_Timer = 15000; - CheckAdds_Timer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //AntiMagicPulse_Timer - if (AntiMagicPulse_Timer <= diff) - { - DoCast(me, SPELL_ANTIMAGICPULSE); - AntiMagicPulse_Timer = 10000 + rand()%5000; - } else AntiMagicPulse_Timer -= diff; - - //MagmaShackles_Timer - if (MagmaShackles_Timer <= diff) - { - DoCast(me, SPELL_MAGMASHACKLES); - MagmaShackles_Timer = 8000 + rand()%4000; - } else MagmaShackles_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_fireswornAI : public ScriptedAI -{ - mob_fireswornAI(Creature *c) : ScriptedAI(c) {} - - uint32 Immolate_Timer; - - void Reset() - { - Immolate_Timer = 4000; //These times are probably wrong - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_IMMOLATE); - - Immolate_Timer = urand(5000,10000); - } else Immolate_Timer -= diff; - - //Cast Erruption and let them die - if (me->GetHealth() <= me->GetMaxHealth() * 0.10) - { - DoCast(me->getVictim(), SPELL_ERUPTION); - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_garr(Creature* pCreature) -{ - return new boss_garrAI (pCreature); -} - -CreatureAI* GetAI_mob_firesworn(Creature* pCreature) -{ - return new mob_fireswornAI (pCreature); -} - -void AddSC_boss_garr() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_garr"; - newscript->GetAI = &GetAI_boss_garr; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_firesworn"; - newscript->GetAI = &GetAI_mob_firesworn; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp deleted file mode 100644 index 9ebe69c0c4e..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_gehennas.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gehennas -SD%Complete: 90 -SDComment: Adds MC NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWBOLT 19728 -#define SPELL_RAINOFFIRE 19717 -#define SPELL_GEHENNASCURSE 19716 - -struct boss_gehennasAI : public ScriptedAI -{ - boss_gehennasAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowBolt_Timer; - uint32 RainOfFire_Timer; - uint32 GehennasCurse_Timer; - - void Reset() - { - ShadowBolt_Timer = 6000; - RainOfFire_Timer = 10000; - GehennasCurse_Timer = 12000; - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - DoCast(pTarget, SPELL_SHADOWBOLT); - - ShadowBolt_Timer = 7000; - } else ShadowBolt_Timer -= diff; - - //RainOfFire_Timer - if (RainOfFire_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_RAINOFFIRE); - - RainOfFire_Timer = urand(4000,12000); - } else RainOfFire_Timer -= diff; - - //GehennasCurse_Timer - if (GehennasCurse_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GEHENNASCURSE); - GehennasCurse_Timer = urand(22000,30000); - } else GehennasCurse_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gehennas(Creature* pCreature) -{ - return new boss_gehennasAI (pCreature); -} - -void AddSC_boss_gehennas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gehennas"; - newscript->GetAI = &GetAI_boss_gehennas; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp deleted file mode 100644 index 2aba378d399..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_golemagg.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Golemagg -SD%Complete: 90 -SDComment: Timers need to be confirmed, Golemagg's Trust need to be checked -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" -#include "molten_core.h" - -enum eEnums -{ - SPELL_MAGMASPLASH = 13879, - SPELL_PYROBLAST = 20228, - SPELL_EARTHQUAKE = 19798, - SPELL_ENRAGE = 19953, - SPELL_GOLEMAGG_TRUST = 20553, - - // Core Rager - EMOTE_LOWHP = -1409002, - SPELL_MANGLE = 19820 -}; - -struct boss_golemaggAI : public ScriptedAI -{ - boss_golemaggAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiPyroblastTimer; - uint32 m_uiEarthquakeTimer; - uint32 m_uiBuffTimer; - bool m_bEnraged; - - void Reset() - { - m_uiPyroblastTimer = 7*IN_MILISECONDS; // These timers are probably wrong - m_uiEarthquakeTimer = 3*IN_MILISECONDS; - m_uiBuffTimer = 2.5*IN_MILISECONDS; - m_bEnraged = false; - - DoCast(me, SPELL_MAGMASPLASH, true); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance) - m_pInstance->SetData(DATA_GOLEMAGG_DEATH, 0); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //Pyroblast - if (m_uiPyroblastTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_PYROBLAST); - - m_uiPyroblastTimer = 7*IN_MILISECONDS; - } - else - m_uiPyroblastTimer -= uiDiff; - - // Enrage - if (!m_bEnraged && me->GetHealth()*100 < me->GetMaxHealth()*10) - { - DoCast(me, SPELL_ENRAGE); - m_bEnraged = true; - } - - // Earthquake - if (m_bEnraged) - { - if (m_uiEarthquakeTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_EARTHQUAKE); - m_uiEarthquakeTimer = 3*IN_MILISECONDS; - } - else - m_uiEarthquakeTimer -= uiDiff; - } - - /* - // Golemagg's Trust - if (m_uiBuffTimer <= uidiff) - { - DoCast(me, SPELL_GOLEMAGG_TRUST); - m_uiBuffTimer = 2.5*IN_MILISECONDS; - } - else - m_uiBuffTimer -= uiDiff; - */ - - DoMeleeAttackIfReady(); - } -}; - -struct mob_core_ragerAI : public ScriptedAI -{ - mob_core_ragerAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiMangleTimer; - - void Reset() - { - m_uiMangleTimer = 7*IN_MILISECONDS; // These times are probably wrong - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) - { - if (me->GetHealth()*100 < me->GetMaxHealth()*50) - { - if (m_pInstance) - { - if (Creature* pGolemagg = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_GOLEMAGG))) - { - if (pGolemagg->isAlive()) - { - DoScriptText(EMOTE_LOWHP, me); - me->SetHealth(me->GetMaxHealth()); - } - else - uiDamage = me->GetHealth(); - } - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - // Mangle - if (m_uiMangleTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MANGLE); - m_uiMangleTimer = 10*IN_MILISECONDS; - } - else - m_uiMangleTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_golemagg(Creature* pCreature) -{ - return new boss_golemaggAI (pCreature); -} - -CreatureAI* GetAI_mob_core_rager(Creature* pCreature) -{ - return new mob_core_ragerAI (pCreature); -} - -void AddSC_boss_golemagg() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_golemagg"; - newscript->GetAI = &GetAI_boss_golemagg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_core_rager"; - newscript->GetAI = &GetAI_mob_core_rager; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp deleted file mode 100644 index 50601f04147..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_lucifron.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Lucifron -SD%Complete: 100 -SDComment: -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_IMPENDINGDOOM 19702 -#define SPELL_LUCIFRONCURSE 19703 -#define SPELL_SHADOWSHOCK 20603 - -struct boss_lucifronAI : public ScriptedAI -{ - boss_lucifronAI(Creature *c) : ScriptedAI(c) {} - - uint32 ImpendingDoom_Timer; - uint32 LucifronCurse_Timer; - uint32 ShadowShock_Timer; - - void Reset() - { - ImpendingDoom_Timer = 10000; //Initial cast after 10 seconds so the debuffs alternate - LucifronCurse_Timer = 20000; //Initial cast after 20 seconds - ShadowShock_Timer = 6000; //6 seconds - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Impending doom timer - if (ImpendingDoom_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_IMPENDINGDOOM); - ImpendingDoom_Timer = 20000; - } else ImpendingDoom_Timer -= diff; - - //Lucifron's curse timer - if (LucifronCurse_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LUCIFRONCURSE); - LucifronCurse_Timer = 15000; - } else LucifronCurse_Timer -= diff; - - //Shadowshock - if (ShadowShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWSHOCK); - ShadowShock_Timer = 6000; - } else ShadowShock_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_lucifron(Creature* pCreature) -{ - return new boss_lucifronAI (pCreature); -} - -void AddSC_boss_lucifron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lucifron"; - newscript->GetAI = &GetAI_boss_lucifron; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp deleted file mode 100644 index f612003b076..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_magmadar.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Magmadar -SD%Complete: 75 -SDComment: Conflag on ground nyi, fear causes issues without VMAPs -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_FRENZY -1409001 - -#define SPELL_FRENZY 19451 -#define SPELL_MAGMASPIT 19449 //This is actually a buff he gives himself -#define SPELL_PANIC 19408 -#define SPELL_LAVABOMB 19411 //This calls a dummy server side effect that isn't implemented yet -#define SPELL_LAVABOMB_ALT 19428 //This is the spell that the lava bomb casts - -struct boss_magmadarAI : public ScriptedAI -{ - boss_magmadarAI(Creature *c) : ScriptedAI(c) {} - - uint32 Frenzy_Timer; - uint32 Panic_Timer; - uint32 Lavabomb_Timer; - - void Reset() - { - Frenzy_Timer = 30000; - Panic_Timer = 20000; - Lavabomb_Timer = 12000; - - DoCast(me, SPELL_MAGMASPIT, true); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Frenzy_Timer - if (Frenzy_Timer <= diff) - { - DoScriptText(EMOTE_FRENZY, me); - DoCast(me, SPELL_FRENZY); - Frenzy_Timer = 15000; - } else Frenzy_Timer -= diff; - - //Panic_Timer - if (Panic_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PANIC); - Panic_Timer = 35000; - } else Panic_Timer -= diff; - - //Lavabomb_Timer - if (Lavabomb_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LAVABOMB_ALT); - - Lavabomb_Timer = 12000; - } else Lavabomb_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_magmadar(Creature* pCreature) -{ - return new boss_magmadarAI (pCreature); -} - -void AddSC_boss_magmadar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magmadar"; - newscript->GetAI = &GetAI_boss_magmadar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp deleted file mode 100644 index 11ae70befcf..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_majordomo_executus.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Majordomo_Executus -SD%Complete: 30 -SDComment: Correct spawning and Event NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1409003 -#define SAY_SPAWN -1409004 -#define SAY_SLAY -1409005 -#define SAY_SPECIAL -1409006 -#define SAY_DEFEAT -1409007 - -#define SAY_SUMMON_MAJ -1409008 -#define SAY_ARRIVAL1_RAG -1409009 -#define SAY_ARRIVAL2_MAJ -1409010 -#define SAY_ARRIVAL3_RAG -1409011 -#define SAY_ARRIVAL5_RAG -1409012 - -#define SPAWN_RAG_X 838.51 -#define SPAWN_RAG_Y -829.84 -#define SPAWN_RAG_Z -232.00 -#define SPAWN_RAG_O 1.70 - -#define SPELL_MAGIC_REFLECTION 20619 -#define SPELL_DAMAGE_REFLECTION 21075 - -#define SPELL_BLASTWAVE 20229 -#define SPELL_AEGIS 20620 //This is self casted whenever we are below 50% -#define SPELL_TELEPORT 20618 -#define SPELL_SUMMON_RAGNAROS 19774 - -#define ENTRY_FLAMEWALKER_HEALER 11663 -#define ENTRY_FLAMEWALKER_ELITE 11664 - -struct boss_majordomoAI : public ScriptedAI -{ - boss_majordomoAI(Creature *c) : ScriptedAI(c) {} - - uint32 MagicReflection_Timer; - uint32 DamageReflection_Timer; - uint32 Blastwave_Timer; - - void Reset() - { - MagicReflection_Timer = 30000; //Damage reflection first so we alternate - DamageReflection_Timer = 15000; - Blastwave_Timer = 10000; - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%5) - return; - - DoScriptText(SAY_SLAY, me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Cast Ageis if less than 50% hp - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - DoCast(me, SPELL_AEGIS); - } - - //MagicReflection_Timer - // if (MagicReflection_Timer <= diff) - // { - // DoCast(me, SPELL_MAGICREFLECTION); - - //60 seconds until we should cast this agian - // MagicReflection_Timer = 30000; - // } else MagicReflection_Timer -= diff; - - //DamageReflection_Timer - // if (DamageReflection_Timer <= diff) - // { - // DoCast(me, SPELL_DAMAGEREFLECTION); - - //60 seconds until we should cast this agian - // DamageReflection_Timer = 30000; - // } else DamageReflection_Timer -= diff; - - //Blastwave_Timer - if (Blastwave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLASTWAVE); - Blastwave_Timer = 10000; - } else Blastwave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_majordomo(Creature* pCreature) -{ - return new boss_majordomoAI (pCreature); -} - -void AddSC_boss_majordomo() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_majordomo"; - newscript->GetAI = &GetAI_boss_majordomo; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp deleted file mode 100644 index 71c0b40de3f..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_ragnaros.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ragnaros -SD%Complete: 75 -SDComment: Intro Dialog and event NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_REINFORCEMENTS1 -1409013 -#define SAY_REINFORCEMENTS2 -1409014 -#define SAY_HAND -1409015 -#define SAY_WRATH -1409016 -#define SAY_KILL -1409017 -#define SAY_MAGMABURST -1409018 - -#define SPELL_HANDOFRAGNAROS 19780 -#define SPELL_WRATHOFRAGNAROS 20566 -#define SPELL_LAVABURST 21158 - -#define SPELL_MAGMABURST 20565 //Ranged attack - -#define SPELL_SONSOFFLAME_DUMMY 21108 //Server side effect -#define SPELL_RAGSUBMERGE 21107 //Stealth aura -#define SPELL_RAGEMERGE 20568 -#define SPELL_MELTWEAPON 21388 -#define SPELL_ELEMENTALFIRE 20564 -#define SPELL_ERRUPTION 17731 - -#define ADD_1X 848.740356 -#define ADD_1Y -816.103455 -#define ADD_1Z -229.74327 -#define ADD_1O 2.615287 - -#define ADD_2X 852.560791 -#define ADD_2Y -849.861511 -#define ADD_2Z -228.560974 -#define ADD_2O 2.836073 - -#define ADD_3X 808.710632 -#define ADD_3Y -852.845764 -#define ADD_3Z -227.914963 -#define ADD_3O 0.964207 - -#define ADD_4X 786.597107 -#define ADD_4Y -821.132874 -#define ADD_4Z -226.350128 -#define ADD_4O 0.949377 - -#define ADD_5X 796.219116 -#define ADD_5Y -800.948059 -#define ADD_5Z -226.010361 -#define ADD_5O 0.560603 - -#define ADD_6X 821.602539 -#define ADD_6Y -782.744109 -#define ADD_6Z -226.023575 -#define ADD_6O 6.157440 - -#define ADD_7X 844.924744 -#define ADD_7Y -769.453735 -#define ADD_7Z -225.521698 -#define ADD_7O 4.4539958 - -#define ADD_8X 839.823364 -#define ADD_8Y -810.869385 -#define ADD_8Z -229.683182 -#define ADD_8O 4.693108 - -struct boss_ragnarosAI : public ScriptedAI -{ - boss_ragnarosAI(Creature *c) : ScriptedAI(c) - { - SetCombatMovement(false); - } - - uint32 WrathOfRagnaros_Timer; - uint32 HandOfRagnaros_Timer; - uint32 LavaBurst_Timer; - uint32 MagmaBurst_Timer; - uint32 ElementalFire_Timer; - uint32 Erruption_Timer; - uint32 Submerge_Timer; - uint32 Attack_Timer; - - bool HasYelledMagmaBurst; - bool HasSubmergedOnce; - bool WasBanished; - bool HasAura; - - void Reset() - { - WrathOfRagnaros_Timer = 30000; - HandOfRagnaros_Timer = 25000; - LavaBurst_Timer = 10000; - MagmaBurst_Timer = 2000; - Erruption_Timer = 15000; - ElementalFire_Timer = 3000; - Submerge_Timer = 180000; - Attack_Timer = 90000; - HasYelledMagmaBurst = false; - HasSubmergedOnce = false; - WasBanished = false; - - DoCast(me, SPELL_MELTWEAPON, true); - HasAura = true; - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%5) - return; - - DoScriptText(SAY_KILL, me); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (WasBanished && Attack_Timer <= diff) - { - //Become unbanished again - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_RAGEMERGE); - WasBanished = false; - } else if (WasBanished) - { - Attack_Timer -= diff; - //Do nothing while banished - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //WrathOfRagnaros_Timer - if (WrathOfRagnaros_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WRATHOFRAGNAROS); - - if (urand(0,1)) - DoScriptText(SAY_WRATH, me); - - WrathOfRagnaros_Timer = 30000; - } else WrathOfRagnaros_Timer -= diff; - - //HandOfRagnaros_Timer - if (HandOfRagnaros_Timer <= diff) - { - DoCast(me, SPELL_HANDOFRAGNAROS); - - if (urand(0,1)) - DoScriptText(SAY_HAND, me); - - HandOfRagnaros_Timer = 25000; - } else HandOfRagnaros_Timer -= diff; - - //LavaBurst_Timer - if (LavaBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LAVABURST); - LavaBurst_Timer = 10000; - } else LavaBurst_Timer -= diff; - - //Erruption_Timer - if (LavaBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ERRUPTION); - Erruption_Timer = urand(20000,45000); - } else Erruption_Timer -= diff; - - //ElementalFire_Timer - if (ElementalFire_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ELEMENTALFIRE); - ElementalFire_Timer = urand(10000,14000); - } else ElementalFire_Timer -= diff; - - //Submerge_Timer - if (!WasBanished && Submerge_Timer <= diff) - { - //Creature spawning and ragnaros becomming unattackable - //is not very well supported in the core - //so added normaly spawning and banish workaround and attack again after 90 secs. - - me->InterruptNonMeleeSpells(false); - //Root self - DoCast(me, 23973); - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); - - if (!HasSubmergedOnce) - { - DoScriptText(SAY_REINFORCEMENTS1, me); - - // summon 10 elementals - for (uint8 i = 0; i < 9; ++i) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (Creature* pSummoned = me->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000)) - pSummoned->AI()->AttackStart(pTarget); - } - } - - HasSubmergedOnce = true; - WasBanished = true; - DoCast(me, SPELL_RAGSUBMERGE); - Attack_Timer = 90000; - - } - else - { - DoScriptText(SAY_REINFORCEMENTS2, me); - - for (uint8 i = 0; i < 9; ++i) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (Creature* pSummoned = me->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000)) - pSummoned->AI()->AttackStart(pTarget); - } - } - - WasBanished = true; - DoCast(me, SPELL_RAGSUBMERGE); - Attack_Timer = 90000; - } - - Submerge_Timer = 180000; - } else Submerge_Timer -= diff; - - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - //Make sure our attack is ready and we arn't currently casting - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - else - { - //MagmaBurst_Timer - if (MagmaBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MAGMABURST); - - if (!HasYelledMagmaBurst) - { - //Say our dialog - DoScriptText(SAY_MAGMABURST, me); - HasYelledMagmaBurst = true; - } - - MagmaBurst_Timer = 2500; - } else MagmaBurst_Timer -= diff; - } - } -}; -CreatureAI* GetAI_boss_ragnaros(Creature* pCreature) -{ - return new boss_ragnarosAI (pCreature); -} - -void AddSC_boss_ragnaros() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ragnaros"; - newscript->GetAI = &GetAI_boss_ragnaros; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp deleted file mode 100644 index 4b0774cdc54..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_shazzrah.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Shazzrah -SD%Complete: 75 -SDComment: Teleport NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_ARCANEEXPLOSION 19712 -#define SPELL_SHAZZRAHCURSE 19713 -#define SPELL_DEADENMAGIC 19714 -#define SPELL_COUNTERSPELL 19715 - -struct boss_shazzrahAI : public ScriptedAI -{ - boss_shazzrahAI(Creature *c) : ScriptedAI(c) {} - - uint32 ArcaneExplosion_Timer; - uint32 ShazzrahCurse_Timer; - uint32 DeadenMagic_Timer; - uint32 Countspell_Timer; - uint32 Blink_Timer; - - void Reset() - { - ArcaneExplosion_Timer = 6000; //These times are probably wrong - ShazzrahCurse_Timer = 10000; - DeadenMagic_Timer = 24000; - Countspell_Timer = 15000; - Blink_Timer = 30000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANEEXPLOSION); - ArcaneExplosion_Timer = 5000 + rand()%4000; - } else ArcaneExplosion_Timer -= diff; - - //ShazzrahCurse_Timer - if (ShazzrahCurse_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_SHAZZRAHCURSE); - - ShazzrahCurse_Timer = 25000 + rand()%5000; - } else ShazzrahCurse_Timer -= diff; - - //DeadenMagic_Timer - if (DeadenMagic_Timer <= diff) - { - DoCast(me, SPELL_DEADENMAGIC); - DeadenMagic_Timer = 35000; - } else DeadenMagic_Timer -= diff; - - //Countspell_Timer - if (Countspell_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_COUNTERSPELL); - Countspell_Timer = 16000 + rand()%4000; - } else Countspell_Timer -= diff; - - //Blink_Timer - if (Blink_Timer <= diff) - { - // Teleporting him to a random gamer and casting Arcane Explosion after that. - // Blink is not working cause of LoS System we need to do this hardcoded. - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0, 100, true)) - { - DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); - DoCast(pTarget, SPELL_ARCANEEXPLOSION); - DoResetThreat(); - } - - Blink_Timer = 45000; - } else Blink_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_shazzrah(Creature* pCreature) -{ - return new boss_shazzrahAI (pCreature); -} - -void AddSC_boss_shazzrah() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shazzrah"; - newscript->GetAI = &GetAI_boss_shazzrah; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp b/src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp deleted file mode 100644 index 83288fe003b..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/boss_sulfuron_harbinger.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Sulfuron_Harbringer -SD%Complete: 80 -SDComment: Adds NYI -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" -#include "molten_core.h" - -#define SPELL_DARKSTRIKE 19777 -#define SPELL_DEMORALIZINGSHOUT 19778 -#define SPELL_INSPIRE 19779 -#define SPELL_KNOCKDOWN 19780 -#define SPELL_FLAMESPEAR 19781 - -//Adds Spells -#define SPELL_HEAL 19775 -#define SPELL_SHADOWWORDPAIN 19776 -#define SPELL_IMMOLATE 20294 - -struct boss_sulfuronAI : public ScriptedAI -{ - boss_sulfuronAI(Creature *c) : ScriptedAI(c) {} - - uint32 Darkstrike_Timer; - uint32 DemoralizingShout_Timer; - uint32 Inspire_Timer; - uint32 Knockdown_Timer; - uint32 Flamespear_Timer; - - void Reset() - { - Darkstrike_Timer=10000; //These times are probably wrong - DemoralizingShout_Timer = 15000; - Inspire_Timer = 13000; - Knockdown_Timer = 6000; - Flamespear_Timer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //DemoralizingShout_Timer - if (DemoralizingShout_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DEMORALIZINGSHOUT); - DemoralizingShout_Timer = 15000 + rand()%5000; - } else DemoralizingShout_Timer -= diff; - - //Inspire_Timer - if (Inspire_Timer <= diff) - { - Creature *pTarget = NULL; - std::list pList = DoFindFriendlyMissingBuff(45.0f,SPELL_INSPIRE); - if (!pList.empty()) - { - std::list::const_iterator i = pList.begin(); - advance(i, (rand()%pList.size())); - pTarget = (*i); - } - - if (pTarget) - DoCast(pTarget, SPELL_INSPIRE); - - DoCast(me, SPELL_INSPIRE); - - Inspire_Timer = 20000 + rand()%6000; - } else Inspire_Timer -= diff; - - //Knockdown_Timer - if (Knockdown_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - Knockdown_Timer = 12000 + rand()%3000; - } else Knockdown_Timer -= diff; - - //Flamespear_Timer - if (Flamespear_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_FLAMESPEAR); - - Flamespear_Timer = 12000 + rand()%4000; - } else Flamespear_Timer -= diff; - - //DarkStrike_Timer - if (Darkstrike_Timer <= diff) - { - DoCast(me, SPELL_DARKSTRIKE); - Darkstrike_Timer = 15000 + rand()%3000; - } else Darkstrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_flamewaker_priestAI : public ScriptedAI -{ - mob_flamewaker_priestAI(Creature *c) : ScriptedAI(c) {} - - uint32 Heal_Timer; - uint32 ShadowWordPain_Timer; - uint32 Immolate_Timer; - - void Reset() - { - Heal_Timer = 15000+rand()%15000; - ShadowWordPain_Timer = 2000; - Immolate_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Casting Heal to Sulfuron or other Guards. - if (Heal_Timer <= diff) - { - Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1); - if (!pUnit) - return; - - DoCast(pUnit, SPELL_HEAL); - - Heal_Timer = 15000+rand()%5000; - } else Heal_Timer -= diff; - - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_SHADOWWORDPAIN); - - ShadowWordPain_Timer = 18000+rand()%8000; - } else ShadowWordPain_Timer -= diff; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); - - Immolate_Timer = 15000+rand()%10000; - } else Immolate_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_sulfuron(Creature* pCreature) -{ - return new boss_sulfuronAI (pCreature); -} - -CreatureAI* GetAI_mob_flamewaker_priest(Creature* pCreature) -{ - return new mob_flamewaker_priestAI (pCreature); -} - -void AddSC_boss_sulfuron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sulfuron"; - newscript->GetAI = &GetAI_boss_sulfuron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flamewaker_priest"; - newscript->GetAI = &GetAI_mob_flamewaker_priest; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp b/src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp deleted file mode 100644 index eb79c234134..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/instance_molten_core.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Molten_Core -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Molten Core -EndScriptData */ - -#include "ScriptedPch.h" -#include "molten_core.h" - -#define MAX_ENCOUNTER 9 - -#define ID_LUCIFRON 12118 -#define ID_MAGMADAR 11982 -#define ID_GEHENNAS 12259 -#define ID_GARR 12057 -#define ID_GEDDON 12056 -#define ID_SHAZZRAH 12264 -#define ID_GOLEMAGG 11988 -#define ID_SULFURON 12098 -#define ID_DOMO 12018 -#define ID_RAGNAROS 11502 -#define ID_FLAMEWAKERPRIEST 11662 - -struct instance_molten_core : public ScriptedInstance -{ - instance_molten_core(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 Lucifron, Magmadar, Gehennas, Garr, Geddon, Shazzrah, Sulfuron, Golemagg, Domo, Ragnaros, FlamewakerPriest; - uint64 RuneKoro, RuneZeth, RuneMazj, RuneTheri, RuneBlaz, RuneKress, RuneMohn, m_uiFirelordCacheGUID; - - //If all Bosses are dead. - bool IsBossDied[9]; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Lucifron = 0; - Magmadar = 0; - Gehennas = 0; - Garr = 0; - Geddon = 0; - Shazzrah = 0; - Sulfuron = 0; - Golemagg = 0; - Domo = 0; - Ragnaros = 0; - FlamewakerPriest = 0; - - RuneKoro = 0; - RuneZeth = 0; - RuneMazj = 0; - RuneTheri = 0; - RuneBlaz = 0; - RuneKress = 0; - RuneMohn = 0; - - m_uiFirelordCacheGUID = 0; - - IsBossDied[0] = false; - IsBossDied[1] = false; - IsBossDied[2] = false; - IsBossDied[3] = false; - IsBossDied[4] = false; - IsBossDied[5] = false; - IsBossDied[6] = false; - - IsBossDied[7] = false; - IsBossDied[8] = false; - } - - bool IsEncounterInProgress() const - { - return false; - }; - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 176951: //Sulfuron - RuneKoro = pGo->GetGUID(); - break; - case 176952: //Geddon - RuneZeth = pGo->GetGUID(); - break; - case 176953: //Shazzrah - RuneMazj = pGo->GetGUID(); - break; - case 176954: //Golemagg - RuneTheri = pGo->GetGUID(); - break; - case 176955: //Garr - RuneBlaz = pGo->GetGUID(); - break; - case 176956: //Magmadar - RuneKress = pGo->GetGUID(); - break; - case 176957: //Gehennas - RuneMohn = pGo->GetGUID(); - break; - case 179703: - m_uiFirelordCacheGUID = pGo->GetGUID(); //when majordomo event == DONE DoRespawnGameObject(m_uiFirelordCacheGUID,); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case ID_LUCIFRON: - Lucifron = pCreature->GetGUID(); - break; - - case ID_MAGMADAR: - Magmadar = pCreature->GetGUID(); - break; - - case ID_GEHENNAS: - Gehennas = pCreature->GetGUID(); - break; - - case ID_GARR: - Garr = pCreature->GetGUID(); - break; - - case ID_GEDDON: - Geddon = pCreature->GetGUID(); - break; - - case ID_SHAZZRAH: - Shazzrah = pCreature->GetGUID(); - break; - - case ID_SULFURON: - Sulfuron = pCreature->GetGUID(); - break; - - case ID_GOLEMAGG: - Golemagg = pCreature->GetGUID(); - break; - - case ID_DOMO: - Domo = pCreature->GetGUID(); - break; - - case ID_RAGNAROS: - Ragnaros = pCreature->GetGUID(); - break; - - case ID_FLAMEWAKERPRIEST: - FlamewakerPriest = pCreature->GetGUID(); - break; - } - } - - uint64 GetData64 (uint32 identifier) - { - switch(identifier) - { - case DATA_SULFURON: - return Sulfuron; - case DATA_GOLEMAGG: - return Golemagg; - - case DATA_FLAMEWAKERPRIEST: - return FlamewakerPriest; - } - - return 0; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_LUCIFRONISDEAD: - if (IsBossDied[0]) - return 1; - break; - - case DATA_MAGMADARISDEAD: - if (IsBossDied[1]) - return 1; - break; - - case DATA_GEHENNASISDEAD: - if (IsBossDied[2]) - return 1; - break; - - case DATA_GARRISDEAD: - if (IsBossDied[3]) - return 1; - break; - - case DATA_GEDDONISDEAD: - if (IsBossDied[4]) - return 1; - break; - - case DATA_SHAZZRAHISDEAD: - if (IsBossDied[5]) - return 1; - break; - - case DATA_SULFURONISDEAD: - if (IsBossDied[6]) - return 1; - break; - - case DATA_GOLEMAGGISDEAD: - if (IsBossDied[7]) - return 1; - break; - - case DATA_MAJORDOMOISDEAD: - if (IsBossDied[8]) - return 1; - break; - } - - return 0; - } - - void SetData(uint32 type, uint32 /*data*/) - { - if (type == DATA_GOLEMAGG_DEATH) - IsBossDied[7] = true; - } -}; - -InstanceData* GetInstance_instance_molten_core(Map* pMap) -{ - return new instance_molten_core (pMap); -} - -void AddSC_instance_molten_core() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_molten_core"; - newscript->GetInstanceData = &GetInstance_instance_molten_core; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp b/src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp deleted file mode 100644 index f8fe5bf1477..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/molten_core.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Molten_Core -SD%Complete: 100 -SDComment: -SDCategory: Molten Core -EndScriptData */ - -/* ContentData -mob_ancient_core_hound -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedSimpleAI.h" - -#define SPELL_CONE_OF_FIRE 19630 -#define SPELL_BITE 19771 - -//Random Debuff (each hound has only one of these) -#define SPELL_GROUND_STOMP 19364 -#define SPELL_ANCIENT_DREAD 19365 -#define SPELL_CAUTERIZING_FLAMES 19366 -#define SPELL_WITHERING_HEAT 19367 -#define SPELL_ANCIENT_DESPAIR 19369 -#define SPELL_ANCIENT_HYSTERIA 19372 - -CreatureAI* GetAI_mob_ancient_core_hound(Creature* pCreature) -{ - SimpleAI *ai = new SimpleAI(pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = SPELL_CONE_OF_FIRE; - ai->Spell[0].Cooldown = 7000; - ai->Spell[0].First_Cast = 10000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - uint32 RandDebuff = RAND(SPELL_GROUND_STOMP,SPELL_ANCIENT_DREAD,SPELL_CAUTERIZING_FLAMES, - SPELL_WITHERING_HEAT,SPELL_ANCIENT_DESPAIR,SPELL_ANCIENT_HYSTERIA); - - ai->Spell[1].Enabled = true; - ai->Spell[1].Spell_Id = RandDebuff; - ai->Spell[1].Cooldown = 24000; - ai->Spell[1].First_Cast = 15000; - ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->Spell[2].Enabled = true; - ai->Spell[2].Spell_Id = SPELL_BITE; - ai->Spell[2].Cooldown = 6000; - ai->Spell[2].First_Cast = 4000; - ai->Spell[2].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->EnterEvadeMode(); - - return ai; -} - -void AddSC_molten_core() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_ancient_core_hound"; - newscript->GetAI = &GetAI_mob_ancient_core_hound; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/molten_core/molten_core.h b/src/server/scripts/EasternKingdoms/molten_core/molten_core.h deleted file mode 100644 index 5874d8b9408..00000000000 --- a/src/server/scripts/EasternKingdoms/molten_core/molten_core.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_MOLTEN_CORE_H -#define DEF_MOLTEN_CORE_H - -#define DATA_FLAMEWAKERPRIEST 1 -#define DATA_GARRISDEAD 2 -#define DATA_GEDDONISDEAD 3 -#define DATA_GEHENNASISDEAD 4 -#define DATA_GOLEMAGGISDEAD 5 -#define DATA_GOLEMAGG_DEATH 6 -#define DATA_LUCIFRONISDEAD 7 -#define DATA_MAGMADARISDEAD 8 -#define DATA_MAJORDOMOISDEAD 9 -#define DATA_SHAZZRAHISDEAD 10 -#define DATA_SULFURON 11 -#define DATA_SULFURONISDEAD 12 -#define DATA_GOLEMAGG 13 -#endif - diff --git a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp deleted file mode 100644 index bdbf6b7c081..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter1.cpp +++ /dev/null @@ -1,1079 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "Vehicle.h" -#include "ObjectMgr.h" -#include "ScriptedEscortAI.h" - -/*###### -##Quest 12848 -######*/ - -#define GCD_CAST 1 - -enum eDeathKnightSpells -{ - SPELL_SOUL_PRISON_CHAIN_SELF = 54612, - SPELL_SOUL_PRISON_CHAIN = 54613, - SPELL_DK_INITIATE_VISUAL = 51519, - - SPELL_ICY_TOUCH = 52372, - SPELL_PLAGUE_STRIKE = 52373, - SPELL_BLOOD_STRIKE = 52374, - SPELL_DEATH_COIL = 52375 -}; - -#define EVENT_ICY_TOUCH 1 -#define EVENT_PLAGUE_STRIKE 2 -#define EVENT_BLOOD_STRIKE 3 -#define EVENT_DEATH_COIL 4 - -//used by 29519,29520,29565,29566,29567 but signed for 29519 -int32 say_event_start[8] = -{ - -1609000,-1609001,-1609002,-1609003, - -1609004,-1609005,-1609006,-1609007 -}; - -int32 say_event_attack[9] = -{ - -1609008,-1609009,-1609010,-1609011,-1609012, - -1609013,-1609014,-1609015,-1609016 -}; - -uint32 acherus_soul_prison[12] = -{ - 191577, - 191580, - 191581, - 191582, - 191583, - 191584, - 191585, - 191586, - 191587, - 191588, - 191589, - 191590 -}; - -uint32 acherus_unworthy_initiate[5] = -{ - 29519, - 29520, - 29565, - 29566, - 29567 -}; - -enum UnworthyInitiatePhase -{ - PHASE_CHAINED, - PHASE_TO_EQUIP, - PHASE_EQUIPING, - PHASE_TO_ATTACK, - PHASE_ATTACKING, -}; - -struct npc_unworthy_initiateAI : public ScriptedAI -{ - npc_unworthy_initiateAI(Creature *c) : ScriptedAI(c) - { - me->SetReactState(REACT_PASSIVE); - if (!me->GetEquipmentId()) - if (const CreatureInfo *info = GetCreatureInfo(28406)) - if (info->equipmentId) - const_cast(me->GetCreatureInfo())->equipmentId = info->equipmentId; - } - - uint64 playerGUID; - UnworthyInitiatePhase phase; - uint32 wait_timer; - float anchorX, anchorY; - uint64 anchorGUID; - - EventMap events; - - void Reset() - { - anchorGUID = 0; - phase = PHASE_CHAINED; - events.Reset(); - me->setFaction(7); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); - me->LoadEquipment(0, true); - } - - void EnterCombat(Unit * /*who*/) - { - events.ScheduleEvent(EVENT_ICY_TOUCH, 1000, GCD_CAST); - events.ScheduleEvent(EVENT_PLAGUE_STRIKE, 3000, GCD_CAST); - events.ScheduleEvent(EVENT_BLOOD_STRIKE, 2000, GCD_CAST); - events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - { - wait_timer = 5000; - me->CastSpell(me, SPELL_DK_INITIATE_VISUAL, true); - - if (Player* starter = Unit::GetPlayer(playerGUID)) - DoScriptText(say_event_attack[rand()%9], me, starter); - - phase = PHASE_TO_ATTACK; - } - } - - void EventStart(Creature* anchor, Player *pTarget) - { - wait_timer = 5000; - phase = PHASE_TO_EQUIP; - - me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN_SELF); - me->RemoveAurasDueToSpell(SPELL_SOUL_PRISON_CHAIN); - - float z; - anchor->GetContactPoint(me, anchorX, anchorY, z, 1.0f); - - playerGUID = pTarget->GetGUID(); - DoScriptText(say_event_start[rand()%8], me, pTarget); - } - - void UpdateAI(const uint32 diff); -}; - -CreatureAI* GetAI_npc_unworthy_initiate(Creature* pCreature) -{ - return new npc_unworthy_initiateAI(pCreature); -} - -struct npc_unworthy_initiate_anchorAI : public PassiveAI -{ - npc_unworthy_initiate_anchorAI(Creature *c) : PassiveAI(c), prisonerGUID(0) {} - - uint64 prisonerGUID; - - void SetGUID(const uint64 &guid, int32 /*id*/) - { - if (!prisonerGUID) - prisonerGUID = guid; - } - - uint64 GetGUID(int32 /*id*/) { return prisonerGUID; } -}; - -void npc_unworthy_initiateAI::UpdateAI(const uint32 diff) -{ - switch(phase) - { - case PHASE_CHAINED: - if (!anchorGUID) - { - if (Creature *anchor = me->FindNearestCreature(29521, 30)) - { - anchor->AI()->SetGUID(me->GetGUID()); - anchor->CastSpell(me, SPELL_SOUL_PRISON_CHAIN, true); - anchorGUID = anchor->GetGUID(); - } - else - error_log("npc_unworthy_initiateAI: unable to find anchor!"); - - float dist = 99.0f; - GameObject *prison = NULL; - - for (uint8 i = 0; i < 12; ++i) - { - if (GameObject* temp_prison = me->FindNearestGameObject(acherus_soul_prison[i],30)) - { - if (me->IsWithinDist(temp_prison, dist, false)) - { - dist = me->GetDistance2d(temp_prison); - prison = temp_prison; - } - } - } - - if (prison) - prison->ResetDoorOrButton(); - else - error_log("npc_unworthy_initiateAI: unable to find prison!"); - } - return; - case PHASE_TO_EQUIP: - if (wait_timer) - { - if (wait_timer > diff) - wait_timer -= diff; - else - { - me->GetMotionMaster()->MovePoint(1, anchorX, anchorY, me->GetPositionZ()); - //debug_log("npc_unworthy_initiateAI: move to %f %f %f", anchorX, anchorY, me->GetPositionZ()); - phase = PHASE_EQUIPING; - wait_timer = 0; - } - } - return; - case PHASE_TO_ATTACK: - if (wait_timer) - { - if (wait_timer > diff) - wait_timer -= diff; - else - { - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - phase = PHASE_ATTACKING; - - if (Player *pTarget = Unit::GetPlayer(playerGUID)) - me->AI()->AttackStart(pTarget); - wait_timer = 0; - } - } - return; - case PHASE_ATTACKING: - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ICY_TOUCH: - DoCast(me->getVictim(), SPELL_ICY_TOUCH); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(EVENT_ICY_TOUCH, 5000, GCD_CAST); - break; - case EVENT_PLAGUE_STRIKE: - DoCast(me->getVictim(), SPELL_PLAGUE_STRIKE); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(SPELL_PLAGUE_STRIKE, 5000, GCD_CAST); - break; - case EVENT_BLOOD_STRIKE: - DoCast(me->getVictim(), SPELL_BLOOD_STRIKE); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(EVENT_BLOOD_STRIKE, 5000, GCD_CAST); - break; - case EVENT_DEATH_COIL: - DoCast(me->getVictim(), SPELL_DEATH_COIL); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(EVENT_DEATH_COIL, 5000, GCD_CAST); - break; - } - } - - DoMeleeAttackIfReady(); - } -} - -CreatureAI* GetAI_npc_unworthy_initiate_anchor(Creature* pCreature) -{ - return new npc_unworthy_initiate_anchorAI(pCreature); -} - -bool GOHello_go_acherus_soul_prison(Player* pPlayer, GameObject* pGo) -{ - if (Creature *anchor = pGo->FindNearestCreature(29521, 15)) - if (uint64 prisonerGUID = anchor->AI()->GetGUID()) - if (Creature* prisoner = Creature::GetCreature(*pPlayer, prisonerGUID)) - CAST_AI(npc_unworthy_initiateAI, prisoner->AI())->EventStart(anchor, pPlayer); - - return false; -} - -/*###### -## npc_death_knight_initiate -######*/ - -#define GOSSIP_ACCEPT_DUEL "I challenge you, death knight!" - -enum eDuelEnums -{ - SAY_DUEL_A = -1609080, - SAY_DUEL_B = -1609081, - SAY_DUEL_C = -1609082, - SAY_DUEL_D = -1609083, - SAY_DUEL_E = -1609084, - SAY_DUEL_F = -1609085, - SAY_DUEL_G = -1609086, - SAY_DUEL_H = -1609087, - SAY_DUEL_I = -1609088, - - SPELL_DUEL = 52996, - //SPELL_DUEL_TRIGGERED = 52990, - SPELL_DUEL_VICTORY = 52994, - SPELL_DUEL_FLAG = 52991, - - QUEST_DEATH_CHALLENGE = 12733, - FACTION_HOSTILE = 2068 -}; - -int32 m_auiRandomSay[] = -{ - SAY_DUEL_A, SAY_DUEL_B, SAY_DUEL_C, SAY_DUEL_D, SAY_DUEL_E, SAY_DUEL_F, SAY_DUEL_G, SAY_DUEL_H, SAY_DUEL_I -}; - -struct npc_death_knight_initiateAI : public CombatAI -{ - npc_death_knight_initiateAI(Creature* pCreature) : CombatAI(pCreature) - { - m_bIsDuelInProgress = false; - } - - bool lose; - uint64 m_uiDuelerGUID; - uint32 m_uiDuelTimer; - bool m_bIsDuelInProgress; - - void Reset() - { - lose = false; - me->RestoreFaction(); - CombatAI::Reset(); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); - - m_uiDuelerGUID = 0; - m_uiDuelTimer = 5000; - m_bIsDuelInProgress = false; - } - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - if (!m_bIsDuelInProgress && pSpell->Id == SPELL_DUEL) - { - m_uiDuelerGUID = pCaster->GetGUID(); - m_bIsDuelInProgress = true; - } - } - - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) - { - if (m_bIsDuelInProgress && pDoneBy->IsControlledByPlayer()) - { - if (pDoneBy->GetGUID() != m_uiDuelerGUID && pDoneBy->GetOwnerGUID() != m_uiDuelerGUID) // other players cannot help - uiDamage = 0; - else if (uiDamage >= me->GetHealth()) - { - uiDamage = 0; - - if (!lose) - { - pDoneBy->RemoveGameObject(SPELL_DUEL_FLAG, true); - pDoneBy->AttackStop(); - me->CastSpell(pDoneBy, SPELL_DUEL_VICTORY, true); - lose = true; - me->CastSpell(me, 7267, true); - me->RestoreFaction(); - } - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - { - if (m_bIsDuelInProgress) - { - if (m_uiDuelTimer <= uiDiff) - { - me->setFaction(FACTION_HOSTILE); - - if (Unit* pUnit = Unit::GetUnit(*me, m_uiDuelerGUID)) - AttackStart(pUnit); - } - else - m_uiDuelTimer -= uiDiff; - } - return; - } - - if (m_bIsDuelInProgress) - { - if (lose) - { - if (!me->HasAura(7267)) - EnterEvadeMode(); - return; - } - else if (me->getVictim()->GetTypeId() == TYPEID_PLAYER - && me->getVictim()->GetHealth() * 10 < me->getVictim()->GetMaxHealth()) - { - me->getVictim()->CastSpell(me->getVictim(), 7267, true); // beg - me->getVictim()->RemoveGameObject(SPELL_DUEL_FLAG, true); - EnterEvadeMode(); - return; - } - } - - // TODO: spells - - CombatAI::UpdateAI(uiDiff); - } -}; - -CreatureAI* GetAI_npc_death_knight_initiate(Creature* pCreature) -{ - return new npc_death_knight_initiateAI(pCreature); -} - -bool GossipHello_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(QUEST_DEATH_CHALLENGE) == QUEST_STATUS_INCOMPLETE && pCreature->GetHealth() == pCreature->GetMaxHealth()) - { - if (pPlayer->GetHealth() * 10 < pPlayer->GetMaxHealth()) - return true; - - if (pPlayer->isInCombat() || pCreature->isInCombat()) - return true; - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ACCEPT_DUEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature),pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pPlayer->isInCombat() || pCreature->isInCombat()) - return true; - - if (npc_death_knight_initiateAI* pInitiateAI = CAST_AI(npc_death_knight_initiateAI, pCreature->AI())) - { - if (pInitiateAI->m_bIsDuelInProgress) - return true; - } - - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); - - int32 uiSayId = rand()% (sizeof(m_auiRandomSay)/sizeof(int32)); - DoScriptText(m_auiRandomSay[uiSayId], pCreature, pPlayer); - - pPlayer->CastSpell(pCreature, SPELL_DUEL, false); - pPlayer->CastSpell(pPlayer, SPELL_DUEL_FLAG, true); - } - return true; -} - -/*###### -## npc_dark_rider_of_acherus -######*/ - -#define DESPAWN_HORSE 52267 -#define SAY_DARK_RIDER "The realm of shadows awaits..." - -struct npc_dark_rider_of_acherusAI : public ScriptedAI -{ - npc_dark_rider_of_acherusAI(Creature *c) : ScriptedAI(c) {} - - uint32 PhaseTimer; - uint32 Phase; - bool Intro; - uint64 TargetGUID; - - void Reset() - { - PhaseTimer = 4000; - Phase = 0; - Intro = false; - TargetGUID = 0; - } - - void UpdateAI(const uint32 diff) - { - if (!Intro || !TargetGUID) - return; - - if (PhaseTimer <= diff) - { - switch(Phase) - { - case 0: - me->MonsterSay(SAY_DARK_RIDER, LANG_UNIVERSAL, 0); - PhaseTimer = 5000; - Phase = 1; - break; - case 1: - if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID)) - DoCast(pTarget, DESPAWN_HORSE, true); - PhaseTimer = 3000; - Phase = 2; - break; - case 2: - me->SetVisibility(VISIBILITY_OFF); - PhaseTimer = 2000; - Phase = 3; - break; - case 3: - me->ForcedDespawn(); - break; - default: - break; - } - } else PhaseTimer -= diff; - - } - - void InitDespawnHorse(Unit *who) - { - if (!who) - return; - - TargetGUID = who->GetGUID(); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->SetSpeed(MOVE_RUN, 0.4f); - me->GetMotionMaster()->MoveChase(who); - me->SetUInt64Value(UNIT_FIELD_TARGET, TargetGUID); - Intro = true; - } - -}; - -CreatureAI* GetAI_npc_dark_rider_of_acherus(Creature* pCreature) -{ - return new npc_dark_rider_of_acherusAI(pCreature); -} - -/*###### -## npc_salanar_the_horseman -######*/ - -enum eSalanar -{ - REALM_OF_SHADOWS = 52693, - EFFECT_STOLEN_HORSE = 52263, - DELIVER_STOLEN_HORSE = 52264, - CALL_DARK_RIDER = 52266, - SPELL_EFFECT_OVERTAKE = 52349 -}; - -struct npc_salanar_the_horsemanAI : public ScriptedAI -{ - npc_salanar_the_horsemanAI(Creature *c) : ScriptedAI(c) {} - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == DELIVER_STOLEN_HORSE) - { - if (caster->GetTypeId() == TYPEID_UNIT && caster->IsVehicle()) - { - if (Unit *charmer = caster->GetCharmer()) - { - charmer->RemoveAurasDueToSpell(EFFECT_STOLEN_HORSE); - caster->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - caster->setFaction(35); - DoCast(caster, CALL_DARK_RIDER, true); - if (Creature* Dark_Rider = me->FindNearestCreature(28654, 15)) - CAST_AI(npc_dark_rider_of_acherusAI, Dark_Rider->AI())->InitDespawnHorse(caster); - } - } - } - } - - void MoveInLineOfSight(Unit *who) - { - ScriptedAI::MoveInLineOfSight(who); - - if (who->GetTypeId() == TYPEID_UNIT && who->IsVehicle() && me->IsWithinDistInMap(who, 5.0f)) - { - if (Unit *charmer = who->GetCharmer()) - { - if (charmer->GetTypeId() == TYPEID_PLAYER) - { - // for quest Into the Realm of Shadows(12687) - if (me->GetEntry() == 28788 && CAST_PLR(charmer)->GetQuestStatus(12687) == QUEST_STATUS_INCOMPLETE) - { - CAST_PLR(charmer)->GroupEventHappens(12687, me); - charmer->RemoveAurasDueToSpell(SPELL_EFFECT_OVERTAKE); - CAST_CRE(who)->ForcedDespawn(); - //CAST_CRE(who)->Respawn(true); - } - - if (CAST_PLR(charmer)->HasAura(REALM_OF_SHADOWS)) - charmer->RemoveAurasDueToSpell(REALM_OF_SHADOWS); - } - } - } - } -}; - -CreatureAI* GetAI_npc_salanar_the_horseman(Creature* pCreature) -{ - return new npc_salanar_the_horsemanAI(pCreature); -} - -/*###### -## npc_ros_dark_rider -######*/ - -struct npc_ros_dark_riderAI : public ScriptedAI -{ - npc_ros_dark_riderAI(Creature *c) : ScriptedAI(c) {} - - void EnterCombat(Unit * /*who*/) - { - me->ExitVehicle(); - } - - void Reset() - { - Creature* deathcharger = me->FindNearestCreature(28782, 30); - if (!deathcharger) return; - deathcharger->RestoreFaction(); - deathcharger->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - deathcharger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (!me->GetVehicle() && deathcharger->IsVehicle() && deathcharger->GetVehicleKit()->HasEmptySeat(0)) - me->EnterVehicle(deathcharger); - } - - void JustDied(Unit *killer) - { - Creature* deathcharger = me->FindNearestCreature(28782, 30); - if (!deathcharger) return; - if (killer->GetTypeId() == TYPEID_PLAYER && deathcharger->GetTypeId() == TYPEID_UNIT && deathcharger->IsVehicle()) - { - deathcharger->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - deathcharger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - deathcharger->setFaction(2096); - } - } -}; - -CreatureAI* GetAI_npc_ros_dark_rider(Creature* pCreature) -{ - return new npc_ros_dark_riderAI(pCreature); -} - -// correct way: 52312 52314 52555 ... -enum SG -{ - GHOULS = 28845, - GHOSTS = 28846, -}; -struct npc_dkc1_gothikAI : public ScriptedAI -{ - npc_dkc1_gothikAI(Creature *c) : ScriptedAI(c) {} - - void MoveInLineOfSight(Unit *who) - { - ScriptedAI::MoveInLineOfSight(who); - - if (who->GetEntry() == GHOULS && me->IsWithinDistInMap(who, 10.0f)) - { - if (Unit *owner = who->GetOwner()) - { - if (owner->GetTypeId() == TYPEID_PLAYER) - { - if (CAST_PLR(owner)->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE) - { - //CAST_CRE(who)->CastSpell(owner, 52517, true); - CAST_PLR(owner)->KilledMonsterCredit(GHOULS, me->GetGUID()); - } - //Todo: Creatures must not be removed, but, must instead - // stand next to Gothik and be commanded into the pit - // and dig into the ground. - CAST_CRE(who)->ForcedDespawn(); - - if (CAST_PLR(owner)->GetQuestStatus(12698) == QUEST_STATUS_COMPLETE) - owner->RemoveAllMinionsByEntry(GHOULS); - } - } - } - } -}; - -CreatureAI* GetAI_npc_dkc1_gothik(Creature* pCreature) -{ - return new npc_dkc1_gothikAI(pCreature); -} - -struct npc_scarlet_ghoulAI : public ScriptedAI -{ - npc_scarlet_ghoulAI(Creature *c) : ScriptedAI(c) - { - // Ghouls should display their Birth Animation - // Crawling out of the ground - //DoCast(me, 35177, true); - //me->MonsterSay("Mommy?",LANG_UNIVERSAL,0); - me->SetReactState(REACT_DEFENSIVE); - } - - void FindMinions(Unit *owner) - { - std::list MinionList; - owner->GetAllMinionsByEntry(MinionList,GHOULS); - - if (!MinionList.empty()) - { - for (std::list::const_iterator itr = MinionList.begin(); itr != MinionList.end(); ++itr) - { - if (CAST_CRE(*itr)->GetOwner()->GetGUID() == me->GetOwner()->GetGUID()) - { - if (CAST_CRE(*itr)->isInCombat() && CAST_CRE(*itr)->getAttackerForHelper()) - { - AttackStart(CAST_CRE(*itr)->getAttackerForHelper()); - } - } - } - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!me->isInCombat()) - { - if (Unit *owner = me->GetOwner()) - { - if (owner->GetTypeId() == TYPEID_PLAYER && CAST_PLR(owner)->isInCombat()) - { - if (CAST_PLR(owner)->getAttackerForHelper() && CAST_PLR(owner)->getAttackerForHelper()->GetEntry() == GHOSTS) - { - AttackStart(CAST_PLR(owner)->getAttackerForHelper()); - } - else - { - FindMinions(owner); - } - } - } - } - - if (!UpdateVictim()) - return; - - //ScriptedAI::UpdateAI(diff); - //Check if we have a current target - if (me->getVictim()->GetEntry() == GHOSTS) - { - if (me->isAttackReady()) - { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - } - } -}; - -CreatureAI* GetAI_npc_scarlet_ghoul(Creature* pCreature) -{ - return new npc_scarlet_ghoulAI(pCreature); -} - -/*#### -## npc_scarlet_miner_cart -####*/ - -#define SPELL_CART_CHECK 54173 -#define SPELL_CART_DRAG 52465 - -struct npc_scarlet_miner_cartAI : public PassiveAI -{ - npc_scarlet_miner_cartAI(Creature *c) : PassiveAI(c), minerGUID(0) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetDisplayId(me->GetCreatureInfo()->Modelid1); // H0 is horse - } - - uint64 minerGUID; - - void SetGUID(const uint64 &guid, int32 /*id*/) - { - minerGUID = guid; - } - - void DoAction(const int32 /*param*/) - { - if (Creature *miner = Unit::GetCreature(*me, minerGUID)) - { - // very bad visual effect - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - //me->SetSpeed(MOVE_WALK, miner->GetSpeed(MOVE_WALK)); - me->SetSpeed(MOVE_RUN, miner->GetSpeed(MOVE_RUN)); - me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); - } - } - - void PassengerBoarded(Unit * /*who*/, int8 /*seatId*/, bool apply) - { - if (!apply) - if (Creature *miner = Unit::GetCreature(*me, minerGUID)) - miner->DisappearAndDie(); - } -}; - -CreatureAI* GetAI_npc_scarlet_miner_cart(Creature *_Creature) -{ - return new npc_scarlet_miner_cartAI(_Creature); -} - -/*#### -## npc_scarlet_miner -####*/ - -#define SAY_SCARLET_MINER1 "Where'd this come from? I better get this down to the ships before the foreman sees it!" -#define SAY_SCARLET_MINER2 "Now I can have a rest!" - -struct npc_scarlet_minerAI : public npc_escortAI -{ - npc_scarlet_minerAI(Creature *c) : npc_escortAI(c) - { - me->SetReactState(REACT_PASSIVE); - } - - uint32 IntroTimer; - uint32 IntroPhase; - uint64 carGUID; - - void Reset() - { - carGUID = 0; - IntroTimer = 0; - IntroPhase = 0; - } - - void InitWaypoint() - { - AddWaypoint(1, 2389.03, -5902.74, 109.014, 5000); - AddWaypoint(2, 2341.812012, -5900.484863, 102.619743); - AddWaypoint(3, 2306.561279, -5901.738281, 91.792419); - AddWaypoint(4, 2300.098389, -5912.618652, 86.014885); - AddWaypoint(5, 2294.142090, -5927.274414, 75.316849); - AddWaypoint(6, 2286.984375, -5944.955566, 63.714966); - AddWaypoint(7, 2280.001709, -5961.186035, 54.228283); - AddWaypoint(8, 2259.389648, -5974.197754, 42.359348); - AddWaypoint(9, 2242.882812, -5984.642578, 32.827850); - AddWaypoint(10, 2217.265625, -6028.959473, 7.675705); - AddWaypoint(11, 2202.595947, -6061.325684, 5.882018); - AddWaypoint(12, 2188.974609, -6080.866699, 3.370027); - - if (urand(0,1)) - { - AddWaypoint(13, 2176.483887, -6110.407227, 1.855181); - AddWaypoint(14, 2172.516602, -6146.752441, 1.074235); - AddWaypoint(15, 2138.918457, -6158.920898, 1.342926); - AddWaypoint(16, 2129.866699, -6174.107910, 4.380779); - AddWaypoint(17, 2117.709473, -6193.830078, 13.3542, 10000); - } - else - { - AddWaypoint(13, 2184.190186, -6166.447266, 0.968877); - AddWaypoint(14, 2234.265625, -6163.741211, 0.916021); - AddWaypoint(15, 2268.071777, -6158.750977, 1.822252); - AddWaypoint(16, 2270.028320, -6176.505859, 6.340538); - AddWaypoint(17, 2271.739014, -6195.401855, 13.3542, 10000); - } - } - - void InitCartQuest(Player *who) - { - carGUID = who->GetVehicleBase()->GetGUID(); - InitWaypoint(); - Start(false, false, who->GetGUID()); - SetDespawnAtFar(false); - } - - void WaypointReached(uint32 i) - { - switch (i) - { - case 1: - if (Unit *car = Unit::GetCreature(*me, carGUID)) - { - me->SetInFront(car); - me->SendMovementFlagUpdate(); - } - me->MonsterSay(SAY_SCARLET_MINER1,LANG_UNIVERSAL,NULL); - SetRun(true); - IntroTimer = 4000; - IntroPhase = 1; - break; - case 17: - if (Unit *car = Unit::GetCreature(*me, carGUID)) - { - me->SetInFront(car); - me->SendMovementFlagUpdate(); - car->Relocate(car->GetPositionX(), car->GetPositionY(), me->GetPositionZ()); - car->SendMonsterStop(); - //this make player fall under ground, dunno why - //car->GetMotionMaster()->MovePoint(0, car->GetPositionX(), car->GetPositionY(), me->GetPositionZ()); - car->RemoveAura(SPELL_CART_DRAG); - } - me->MonsterSay(SAY_SCARLET_MINER2,LANG_UNIVERSAL,NULL); - break; - default: - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (IntroPhase) - { - if (IntroTimer <= diff) - { - if (IntroPhase == 1) - { - if (Creature *car = Unit::GetCreature(*me, carGUID)) - DoCast(car, SPELL_CART_DRAG); - IntroTimer = 800; - IntroPhase = 2; - } - else - { - if (Creature *car = Unit::GetCreature(*me, carGUID)) - car->AI()->DoAction(); - IntroPhase = 0; - } - } else IntroTimer-=diff; - } - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_npc_scarlet_miner(Creature *_Creature) -{ - return new npc_scarlet_minerAI(_Creature); -} - -/*###### -## go_inconspicuous_mine_car -######*/ - -#define SPELL_CART_SUMM 52463 - -bool GOHello_go_inconspicuous_mine_car(Player* pPlayer, GameObject* /*pGO*/) -{ - if (pPlayer->GetQuestStatus(12701) == QUEST_STATUS_INCOMPLETE) - { - // Hack Why Trinity Dont Support Custom Summon Location - if (Creature *miner = pPlayer->SummonCreature(28841, 2383.869629, -5900.312500, 107.996086, pPlayer->GetOrientation(),TEMPSUMMON_DEAD_DESPAWN, 1)) - { - pPlayer->CastSpell(pPlayer, SPELL_CART_SUMM, true); - if (Creature *car = pPlayer->GetVehicleCreatureBase()) - { - if (car->GetEntry() == 28817) - { - car->AI()->SetGUID(miner->GetGUID()); - CAST_AI(npc_scarlet_minerAI, miner->AI())->InitCartQuest(pPlayer); - } else error_log("TSCR: GOHello_go_inconspicuous_mine_car vehicle entry is not correct."); - } else error_log("TSCR: GOHello_go_inconspicuous_mine_car player is not on the vehicle."); - } else error_log("TSCR: GOHello_go_inconspicuous_mine_car Scarlet Miner cant be found by script."); - } - return true; -} - -// npc 28912 quest 17217 boss 29001 mob 29007 go 191092 - -void AddSC_the_scarlet_enclave_c1() -{ - Script *newscript; - - // 12848 The Endless Hunger - newscript = new Script; - newscript->Name = "npc_unworthy_initiate"; - newscript->GetAI = &GetAI_npc_unworthy_initiate; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_unworthy_initiate_anchor"; - newscript->GetAI = &GetAI_npc_unworthy_initiate_anchor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_acherus_soul_prison"; - newscript->pGOHello = &GOHello_go_acherus_soul_prison; - newscript->RegisterSelf(); - - // Death's Challenge - newscript = new Script; - newscript->Name = "npc_death_knight_initiate"; - newscript->GetAI = &GetAI_npc_death_knight_initiate; - newscript->pGossipHello = &GossipHello_npc_death_knight_initiate; - newscript->pGossipSelect = &GossipSelect_npc_death_knight_initiate; - newscript->RegisterSelf(); - - // 12680 Grand Theft Palomino - newscript = new Script; - newscript->Name = "npc_salanar_the_horseman"; - newscript->GetAI = &GetAI_npc_salanar_the_horseman; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dark_rider_of_acherus"; - newscript->GetAI = &GetAI_npc_dark_rider_of_acherus; - newscript->RegisterSelf(); - - // 12687 Into the Realm of Shadows - newscript = new Script; - newscript->Name = "npc_ros_dark_rider"; - newscript->GetAI = &GetAI_npc_ros_dark_rider; - newscript->RegisterSelf(); - - // 12698 The Gift That Keeps On Giving - newscript = new Script; - newscript->Name = "npc_dkc1_gothik"; - newscript->GetAI = &GetAI_npc_dkc1_gothik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_scarlet_ghoul"; - newscript->GetAI = &GetAI_npc_scarlet_ghoul; - newscript->RegisterSelf(); - - // Massacre At Light's Point - newscript = new Script; - newscript->Name = "npc_scarlet_miner"; - newscript->GetAI = &GetAI_npc_scarlet_miner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_scarlet_miner_cart"; - newscript->GetAI = &GetAI_npc_scarlet_miner_cart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_inconspicuous_mine_car"; - newscript->pGOHello = &GOHello_go_inconspicuous_mine_car; - newscript->RegisterSelf(); -} - -/* -DELETE FROM `script_texts` WHERE `entry` IN(-1609301, -1609302); -INSERT INTO `script_texts` (`entry`,`content_default`,`type`,`language`,`emote`,`comment`) VALUES -(-1609301, 'Come, weakling! Strike me down!', 0, 0, 0, 'SAY_DEATH_RIDER_FINAL'), -(-1609302, '%s rears up, beckoning you to ride it.', 2, 0, 0, 'SAY_DEATH_CHARGER'); -*/ diff --git a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp deleted file mode 100644 index 91f7e0e6cbe..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter2.cpp +++ /dev/null @@ -1,995 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -//How to win friends and influence enemies -// texts signed for creature 28939 but used for 28939,28940,28610 -enum win_friends -{ - SAY_PERSUADE1 = -1609501, - SAY_PERSUADE2 = -1609502, - SAY_PERSUADE3 = -1609503, - SAY_PERSUADE4 = -1609504, - SAY_PERSUADE5 = -1609505, - SAY_PERSUADE6 = -1609506, - SAY_PERSUADE7 = -1609507, - SAY_CRUSADER1 = -1609508, - SAY_CRUSADER2 = -1609509, - SAY_CRUSADER3 = -1609510, - SAY_CRUSADER4 = -1609511, - SAY_CRUSADER5 = -1609512, - SAY_CRUSADER6 = -1609513, - SAY_PERSUADED1 = -1609514, - SAY_PERSUADED2 = -1609515, - SAY_PERSUADED3 = -1609516, - SAY_PERSUADED4 = -1609517, - SAY_PERSUADED5 = -1609518, - SAY_PERSUADED6 = -1609519, - SPELL_PERSUASIVE_STRIKE = 52781 -}; - -struct npc_crusade_persuadedAI : public ScriptedAI -{ - npc_crusade_persuadedAI(Creature *pCreature) : ScriptedAI(pCreature) {} - - uint32 uiSpeech_timer; - uint32 uiSpeech_counter; - uint64 uiPlayerGUID; - - void Reset() - { - uiSpeech_timer = 0; - uiSpeech_counter = 0; - uiPlayerGUID = 0; - me->SetReactState(REACT_AGGRESSIVE); - me->RestoreFaction(); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_PERSUASIVE_STRIKE && caster->GetTypeId() == TYPEID_PLAYER && me->isAlive() && !uiSpeech_counter) - { - if (CAST_PLR(caster)->GetQuestStatus(12720) == QUEST_STATUS_INCOMPLETE) - { - uiPlayerGUID = caster->GetGUID(); - uiSpeech_timer = 1000; - uiSpeech_counter = 1; - me->setFaction(caster->getFaction()); - me->CombatStop(true); - me->GetMotionMaster()->MoveIdle(); - me->SetReactState(REACT_PASSIVE); - DoCastAOE(58111, true); - - DoScriptText(RAND(SAY_PERSUADE1,SAY_PERSUADE2,SAY_PERSUADE3, - SAY_PERSUADE4,SAY_PERSUADE5,SAY_PERSUADE6, - SAY_PERSUADE7), caster); - - DoScriptText(RAND(SAY_CRUSADER1,SAY_CRUSADER2,SAY_CRUSADER3, - SAY_CRUSADER4,SAY_CRUSADER5,SAY_CRUSADER6), me); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (uiSpeech_counter) - { - if (uiSpeech_timer <= diff) - { - Player* pPlayer = Unit::GetPlayer(uiPlayerGUID); - if (!pPlayer) - { - EnterEvadeMode(); - return; - } - - switch(uiSpeech_counter) - { - case 1: DoScriptText(SAY_PERSUADED1, me); uiSpeech_timer = 8000; break; - case 2: DoScriptText(SAY_PERSUADED2, me); uiSpeech_timer = 8000; break; - case 3: DoScriptText(SAY_PERSUADED3, me); uiSpeech_timer = 8000; break; - case 4: DoScriptText(SAY_PERSUADED4, me); uiSpeech_timer = 8000; break; - case 5: DoScriptText(SAY_PERSUADED5, pPlayer); uiSpeech_timer = 8000; break; - case 6: DoScriptText(SAY_PERSUADED6, me); - pPlayer->Kill(me); - //me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - uiSpeech_counter = 0; - pPlayer->GroupEventHappens(12720, me); - return; - } - - ++uiSpeech_counter; - DoCastAOE(58111, true); - } else uiSpeech_timer -= diff; - - return; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_crusade_persuaded(Creature* pCreature) -{ - return new npc_crusade_persuadedAI (pCreature); -} - -/*###### -## npc_koltira_deathweaver -######*/ - -enum eKoltira -{ - SAY_BREAKOUT1 = -1609561, - SAY_BREAKOUT2 = -1609562, - SAY_BREAKOUT3 = -1609563, - SAY_BREAKOUT4 = -1609564, - SAY_BREAKOUT5 = -1609565, - SAY_BREAKOUT6 = -1609566, - SAY_BREAKOUT7 = -1609567, - SAY_BREAKOUT8 = -1609568, - SAY_BREAKOUT9 = -1609569, - SAY_BREAKOUT10 = -1609570, - - SPELL_KOLTIRA_TRANSFORM = 52899, - SPELL_ANTI_MAGIC_ZONE = 52894, - - QUEST_BREAKOUT = 12727, - - NPC_CRIMSON_ACOLYTE = 29007, - NPC_HIGH_INQUISITOR_VALROTH = 29001, - NPC_KOLTIRA_ALT = 28447, - - //not sure about this id - //NPC_DEATH_KNIGHT_MOUNT = 29201, - MODEL_DEATH_KNIGHT_MOUNT = 25278 -}; - -struct npc_koltira_deathweaverAI : public npc_escortAI -{ - npc_koltira_deathweaverAI(Creature *pCreature) : npc_escortAI(pCreature) - { - me->SetReactState(REACT_DEFENSIVE); - } - - uint32 m_uiWave; - uint32 m_uiWave_Timer; - uint64 m_uiValrothGUID; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - m_uiWave = 0; - m_uiWave_Timer = 3000; - m_uiValrothGUID = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->LoadEquipment(0, true); - me->RemoveAura(SPELL_ANTI_MAGIC_ZONE); - } - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 0: - DoScriptText(SAY_BREAKOUT1, me); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - break; - case 1: - me->SetStandState(UNIT_STAND_STATE_KNEEL); - break; - case 2: - me->SetStandState(UNIT_STAND_STATE_STAND); - //me->UpdateEntry(NPC_KOLTIRA_ALT); //unclear if we must update or not - DoCast(me, SPELL_KOLTIRA_TRANSFORM); - me->LoadEquipment(me->GetEquipmentId()); - break; - case 3: - SetEscortPaused(true); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - DoScriptText(SAY_BREAKOUT2, me); - DoCast(me, SPELL_ANTI_MAGIC_ZONE); // cast again that makes bubble up - break; - case 4: - SetRun(true); - break; - case 9: - me->Mount(MODEL_DEATH_KNIGHT_MOUNT); - break; - case 10: - me->Unmount(); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - if (Player* pPlayer = GetPlayerForEscort()) - { - pSummoned->AI()->AttackStart(pPlayer); - } - - if (pSummoned->GetEntry() == NPC_HIGH_INQUISITOR_VALROTH) - m_uiValrothGUID = pSummoned->GetGUID(); - - pSummoned->AddThreat(me, 0.0f); - pSummoned->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - void SummonAcolyte(uint32 uiAmount) - { - for (uint32 i = 0; i < uiAmount; ++i) - me->SummonCreature(NPC_CRIMSON_ACOLYTE, 1642.329, -6045.818, 127.583, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (HasEscortState(STATE_ESCORT_PAUSED)) - { - if (m_uiWave_Timer <= uiDiff) - { - switch(m_uiWave) - { - case 0: - DoScriptText(SAY_BREAKOUT3, me); - SummonAcolyte(3); - m_uiWave_Timer = 20000; - break; - case 1: - DoScriptText(SAY_BREAKOUT4, me); - SummonAcolyte(3); - m_uiWave_Timer = 20000; - break; - case 2: - DoScriptText(SAY_BREAKOUT5, me); - SummonAcolyte(4); - m_uiWave_Timer = 20000; - break; - case 3: - DoScriptText(SAY_BREAKOUT6, me); - me->SummonCreature(NPC_HIGH_INQUISITOR_VALROTH, 1642.329, -6045.818, 127.583, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); - m_uiWave_Timer = 1000; - break; - case 4: - { - Creature* pTemp = Unit::GetCreature(*me, m_uiValrothGUID); - - if (!pTemp || !pTemp->isAlive()) - { - DoScriptText(SAY_BREAKOUT8, me); - m_uiWave_Timer = 5000; - } - else - { - m_uiWave_Timer = 2500; - return; //return, we don't want m_uiWave to increment now - } - break; - } - case 5: - DoScriptText(SAY_BREAKOUT9, me); - me->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); - // i do not know why the armor will also be removed - m_uiWave_Timer = 2500; - break; - case 6: - DoScriptText(SAY_BREAKOUT10, me); - SetEscortPaused(false); - break; - } - - ++m_uiWave; - } - else - m_uiWave_Timer -= uiDiff; - } - } -}; - -CreatureAI* GetAI_npc_koltira_deathweaver(Creature* pCreature) -{ - return new npc_koltira_deathweaverAI(pCreature); -} - -bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - if (pQuest->GetQuestId() == QUEST_BREAKOUT) - { - pCreature->SetStandState(UNIT_STAND_STATE_STAND); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_koltira_deathweaverAI,pCreature->AI())) - pEscortAI->Start(false, false, pPlayer->GetGUID()); - } - return true; -} - -//Scarlet courier -enum ScarletCourierEnum -{ - SAY_TREE1 = -1609531, - SAY_TREE2 = -1609532, - SPELL_SHOOT = 52818, - GO_INCONSPICUOUS_TREE = 191144, - NPC_SCARLET_COURIER = 29076 -}; - -struct mob_scarlet_courierAI : public ScriptedAI -{ - mob_scarlet_courierAI(Creature *pCreature) : ScriptedAI(pCreature) {} - - uint32 uiStage; - uint32 uiStage_timer; - - void Reset() - { - me->Mount(14338); // not sure about this id - uiStage = 1; - uiStage_timer = 3000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_TREE2, me); - me->Unmount(); - uiStage = 0; - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - uiStage = 2; - } - - void UpdateAI(const uint32 diff) - { - if (uiStage && !me->isInCombat()) - { - if (uiStage_timer <= diff) - { - switch(uiStage) - { - case 1: - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - if (GameObject* tree = me->FindNearestGameObject(GO_INCONSPICUOUS_TREE, 40.0f)) - { - DoScriptText(SAY_TREE1, me); - float x, y, z; - tree->GetContactPoint(me, x, y, z); - me->GetMotionMaster()->MovePoint(1, x, y, z); - } - break; - case 2: - if (GameObject* tree = me->FindNearestGameObject(GO_INCONSPICUOUS_TREE, 40.0f)) - if (Unit *unit = tree->GetOwner()) - AttackStart(unit); - break; - } - uiStage_timer = 3000; - uiStage = 0; - } else uiStage_timer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_scarlet_courier(Creature* pCreature) -{ - return new mob_scarlet_courierAI (pCreature); -} - -//Koltira & Valroth- Breakout - -enum valroth -{ - SAY_VALROTH1 = -1609581, - SAY_VALROTH2 = -1609582, - SAY_VALROTH3 = -1609583, - SAY_VALROTH4 = -1609584, - SAY_VALROTH5 = -1609585, - SAY_VALROTH6 = -1609586, - SPELL_RENEW = 38210, - SPELL_INQUISITOR_PENANCE = 52922, - SPELL_VALROTH_SMITE = 52926, - SPELL_SUMMON_VALROTH_REMAINS = 52929 -}; - -struct mob_high_inquisitor_valrothAI : public ScriptedAI -{ - mob_high_inquisitor_valrothAI(Creature *pCreature) : ScriptedAI(pCreature) {} - - uint32 uiRenew_timer; - uint32 uiInquisitor_Penance_timer; - uint32 uiValroth_Smite_timer; - - void Reset() - { - uiRenew_timer = 1000; - uiInquisitor_Penance_timer = 2000; - uiValroth_Smite_timer = 1000; - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_VALROTH2, me); - DoCast(who, SPELL_VALROTH_SMITE); - } - - void UpdateAI(const uint32 diff) - { - if (uiRenew_timer <= diff) - { - Shout(); - DoCast(me, SPELL_RENEW); - uiRenew_timer = 1000 + rand()%5000; - } else uiRenew_timer -= diff; - - if (uiInquisitor_Penance_timer <= diff) - { - Shout(); - DoCast(me->getVictim(), SPELL_INQUISITOR_PENANCE); - uiInquisitor_Penance_timer = 2000 + rand()%5000; - } else uiInquisitor_Penance_timer -= diff; - - if (uiValroth_Smite_timer <= diff) - { - Shout(); - DoCast(me->getVictim(), SPELL_VALROTH_SMITE); - uiValroth_Smite_timer = 1000 + rand()%5000; - } else uiValroth_Smite_timer -= diff; - - DoMeleeAttackIfReady(); - } - - void Shout() - { - if (rand()%100 < 15) - DoScriptText(RAND(SAY_VALROTH3,SAY_VALROTH4,SAY_VALROTH5), me); - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_VALROTH6, me); - killer->CastSpell(me, SPELL_SUMMON_VALROTH_REMAINS, true); - } -}; - -CreatureAI* GetAI_mob_high_inquisitor_valroth(Creature* pCreature) -{ - return new mob_high_inquisitor_valrothAI (pCreature); -} - -/*###### -## npc_a_special_surprise -######*/ -//used by 29032,29061,29065,29067,29068,29070,29074,29072,29073,29071 but signed for 29032 -enum SpecialSurprise -{ - SAY_EXEC_START_1 = -1609025, // speech for all - SAY_EXEC_START_2 = -1609026, - SAY_EXEC_START_3 = -1609027, - SAY_EXEC_PROG_1 = -1609028, - SAY_EXEC_PROG_2 = -1609029, - SAY_EXEC_PROG_3 = -1609030, - SAY_EXEC_PROG_4 = -1609031, - SAY_EXEC_PROG_5 = -1609032, - SAY_EXEC_PROG_6 = -1609033, - SAY_EXEC_PROG_7 = -1609034, - SAY_EXEC_NAME_1 = -1609035, - SAY_EXEC_NAME_2 = -1609036, - SAY_EXEC_RECOG_1 = -1609037, - SAY_EXEC_RECOG_2 = -1609038, - SAY_EXEC_RECOG_3 = -1609039, - SAY_EXEC_RECOG_4 = -1609040, - SAY_EXEC_RECOG_5 = -1609041, - SAY_EXEC_RECOG_6 = -1609042, - SAY_EXEC_NOREM_1 = -1609043, - SAY_EXEC_NOREM_2 = -1609044, - SAY_EXEC_NOREM_3 = -1609045, - SAY_EXEC_NOREM_4 = -1609046, - SAY_EXEC_NOREM_5 = -1609047, - SAY_EXEC_NOREM_6 = -1609048, - SAY_EXEC_NOREM_7 = -1609049, - SAY_EXEC_NOREM_8 = -1609050, - SAY_EXEC_NOREM_9 = -1609051, - SAY_EXEC_THINK_1 = -1609052, - SAY_EXEC_THINK_2 = -1609053, - SAY_EXEC_THINK_3 = -1609054, - SAY_EXEC_THINK_4 = -1609055, - SAY_EXEC_THINK_5 = -1609056, - SAY_EXEC_THINK_6 = -1609057, - SAY_EXEC_THINK_7 = -1609058, - SAY_EXEC_THINK_8 = -1609059, - SAY_EXEC_THINK_9 = -1609060, - SAY_EXEC_THINK_10 = -1609061, - SAY_EXEC_LISTEN_1 = -1609062, - SAY_EXEC_LISTEN_2 = -1609063, - SAY_EXEC_LISTEN_3 = -1609064, - SAY_EXEC_LISTEN_4 = -1609065, - SAY_PLAGUEFIST = -1609066, - SAY_EXEC_TIME_1 = -1609067, - SAY_EXEC_TIME_2 = -1609068, - SAY_EXEC_TIME_3 = -1609069, - SAY_EXEC_TIME_4 = -1609070, - SAY_EXEC_TIME_5 = -1609071, - SAY_EXEC_TIME_6 = -1609072, - SAY_EXEC_TIME_7 = -1609073, - SAY_EXEC_TIME_8 = -1609074, - SAY_EXEC_TIME_9 = -1609075, - SAY_EXEC_TIME_10 = -1609076, - SAY_EXEC_WAITING = -1609077, - EMOTE_DIES = -1609078, - - NPC_PLAGUEFIST = 29053 -}; - -struct npc_a_special_surpriseAI : public ScriptedAI -{ - npc_a_special_surpriseAI(Creature *pCreature) : ScriptedAI(pCreature) {} - - uint32 ExecuteSpeech_Timer; - uint32 ExecuteSpeech_Counter; - uint64 PlayerGUID; - - void Reset() - { - ExecuteSpeech_Timer = 0; - ExecuteSpeech_Counter = 0; - PlayerGUID = 0; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - bool MeetQuestCondition(Unit* pPlayer) - { - switch(me->GetEntry()) - { - case 29061: // Ellen Stanbridge - if (CAST_PLR(pPlayer)->GetQuestStatus(12742) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29072: // Kug Ironjaw - if (CAST_PLR(pPlayer)->GetQuestStatus(12748) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29067: // Donovan Pulfrost - if (CAST_PLR(pPlayer)->GetQuestStatus(12744) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29065: // Yazmina Oakenthorn - if (CAST_PLR(pPlayer)->GetQuestStatus(12743) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29071: // Antoine Brack - if (CAST_PLR(pPlayer)->GetQuestStatus(12750) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29032: // Malar Bravehorn - if (CAST_PLR(pPlayer)->GetQuestStatus(12739) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29068: // Goby Blastenheimer - if (CAST_PLR(pPlayer)->GetQuestStatus(12745) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29073: // Iggy Darktusk - if (CAST_PLR(pPlayer)->GetQuestStatus(12749) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29074: // Lady Eonys - if (CAST_PLR(pPlayer)->GetQuestStatus(12747) == QUEST_STATUS_INCOMPLETE) - return true; - break; - case 29070: // Valok the Righteous - if (CAST_PLR(pPlayer)->GetQuestStatus(12746) == QUEST_STATUS_INCOMPLETE) - return true; - break; - } - - return false; - } - - void MoveInLineOfSight(Unit* pWho) - { - if (PlayerGUID || pWho->GetTypeId() != TYPEID_PLAYER || !pWho->IsWithinDist(me, INTERACTION_DISTANCE)) - return; - - if (MeetQuestCondition(pWho)) - PlayerGUID = pWho->GetGUID(); - } - - void UpdateAI(const uint32 diff) - { - if (PlayerGUID && !me->getVictim() && me->isAlive()) - { - if (ExecuteSpeech_Timer <= diff) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - - if (!pPlayer) - { - Reset(); - return; - } - - //TODO: simplify text's selection - - switch(pPlayer->getRace()) - { - case RACE_HUMAN: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_5, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_5, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_7, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_6, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_ORC: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_6, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_7, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_8, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_8, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_DWARF: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_2, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_2, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_3, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_2, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_5, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_2, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_3, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_NIGHTELF: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_5, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_6, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_2, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_7, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_UNDEAD_PLAYER: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_3, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_4, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_3, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_1, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_3, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_4, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_TAUREN: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_5, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_8, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_9, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_9, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_GNOME: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_4, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_4, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_6, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_5, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_TROLL: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_3, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_7, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_2, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_6, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_9, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_10, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_4, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_10, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_BLOODELF: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_1, me, pPlayer); break; - //case 5: //unknown - case 6: DoScriptText(SAY_EXEC_THINK_3, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_1, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - case RACE_DRAENEI: - switch(ExecuteSpeech_Counter) - { - case 0: DoScriptText(SAY_EXEC_START_1, me, pPlayer); break; - case 1: me->SetStandState(UNIT_STAND_STATE_STAND); break; - case 2: DoScriptText(SAY_EXEC_PROG_1, me, pPlayer); break; - case 3: DoScriptText(SAY_EXEC_NAME_1, me, pPlayer); break; - case 4: DoScriptText(SAY_EXEC_RECOG_2, me, pPlayer); break; - case 5: DoScriptText(SAY_EXEC_NOREM_1, me, pPlayer); break; - case 6: DoScriptText(SAY_EXEC_THINK_4, me, pPlayer); break; - case 7: DoScriptText(SAY_EXEC_LISTEN_1, me, pPlayer); break; - case 8: - if (Creature* Plaguefist = GetClosestCreatureWithEntry(me, NPC_PLAGUEFIST, 85.0f)) - DoScriptText(SAY_PLAGUEFIST, Plaguefist, pPlayer); - break; - case 9: - DoScriptText(SAY_EXEC_TIME_2, me, pPlayer); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - break; - case 10: DoScriptText(SAY_EXEC_WAITING, me, pPlayer); break; - case 11: - DoScriptText(EMOTE_DIES, me); - me->setDeathState(JUST_DIED); - me->SetHealth(0); - return; - } - break; - } - - if (ExecuteSpeech_Counter >= 9) - ExecuteSpeech_Timer = 15000; - else - ExecuteSpeech_Timer = 7000; - - ++ExecuteSpeech_Counter; - } - else - ExecuteSpeech_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_npc_a_special_surprise(Creature* pCreature) -{ - return new npc_a_special_surpriseAI(pCreature); -} - -void AddSC_the_scarlet_enclave_c2() -{ - Script *newscript; - - // How to win friends and influence enemies - newscript = new Script; - newscript->Name = "npc_crusade_persuaded"; - newscript->GetAI = &GetAI_npc_crusade_persuaded; - newscript->RegisterSelf(); - - // Ambush At The Overlook - newscript = new Script; - newscript->Name = "mob_scarlet_courier"; - newscript->GetAI = &GetAI_mob_scarlet_courier; - newscript->RegisterSelf(); - - // 12727 Bloody Breakout - newscript = new Script; - newscript->Name = "npc_koltira_deathweaver"; - newscript->GetAI = &GetAI_npc_koltira_deathweaver; - newscript->pQuestAccept = &QuestAccept_npc_koltira_deathweaver; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_high_inquisitor_valroth"; - newscript->GetAI = &GetAI_mob_high_inquisitor_valroth; - newscript->RegisterSelf(); - - // A Special Suprise - newscript = new Script; - newscript->Name = "npc_a_special_surprise"; - newscript->GetAI = &GetAI_npc_a_special_surprise; - newscript->RegisterSelf(); -} - -/* --- Bloody Breakout -UPDATE `creature_template` SET `ScriptName`='npc_koltira_deathweaver' WHERE `entry`='28912'; -UPDATE `creature_template` SET `ScriptName`='mob_high_inquisitor_valroth',minmana=6489,maxmana=6489,unit_flags=32768 WHERE `entry`='29001'; -UPDATE `creature_template` SET `ScriptName`='mob_eventai', `AIName`='EventAI',minmana=1020,maxmana=1058,unit_flags=32768 WHERE (`entry`='29007'); -DELETE FROM creature_ai_scripts WHERE id BETWEEN 90030 AND 90033; -INSERT INTO `creature_ai_scripts` VALUES ('90030', '29007', '0', '0', '100', '1', '1000', '4000', '1000', '4000', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Smite'); -INSERT INTO `creature_ai_scripts` VALUES ('90031', '29007', '0', '0', '100', '1', '1000', '10000', '20000', '21000', '11', '34809', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Fury'); -INSERT INTO `creature_ai_scripts` VALUES ('90032', '29007', '0', '0', '100', '1', '1000', '5000', '1000', '5000', '11', '19725', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Turn Undead'); -INSERT INTO `creature_ai_scripts` VALUES ('90033', '29007', '4', '0', '100', '0', '0', '0', '0', '0', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte aggro'); -*/ diff --git a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp deleted file mode 100644 index 3b0ce186592..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_enclave/chapter5.cpp +++ /dev/null @@ -1,1684 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -#define LESS_MOB // if you do not have a good server and do not want it to be laggy as hell -//Light of Dawn -enum mograine -{ -#ifdef LESS_MOB - ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - - ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data - ENCOUNTER_DEFENDER_NUMBER = 10, // how many of defender - ENCOUNTER_EARTHSHATTER_NUMBER = 1, // how many of earthshatter - ENCOUNTER_ABOMINATION_NUMBER = 2, // how many of abomination - ENCOUNTER_BEHEMOTH_NUMBER = 1, // how many of behemoth - ENCOUNTER_GHOUL_NUMBER = 5, // how many of ghoul - ENCOUNTER_WARRIOR_NUMBER = 1, // how many of warrior -#else - ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - - ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data - ENCOUNTER_DEFENDER_NUMBER = 20, // how many of defender - ENCOUNTER_EARTHSHATTER_NUMBER = 20, // how many of earthshatter - ENCOUNTER_ABOMINATION_NUMBER = 3, // how many of abomination - ENCOUNTER_BEHEMOTH_NUMBER = 2, // how many of behemoth - ENCOUNTER_GHOUL_NUMBER = 10, // how many of ghoul - ENCOUNTER_WARRIOR_NUMBER = 2, // how many of warrior -#endif - ENCOUNTER_TOTAL_DAWN = 300, // Total number - ENCOUNTER_TOTAL_SCOURGE = 10000, - - WORLD_STATE_REMAINS = 3592, - WORLD_STATE_COUNTDOWN = 3603, - WORLD_STATE_EVENT_BEGIN = 3605, - - SAY_LIGHT_OF_DAWN01 = -1609201, // pre text - SAY_LIGHT_OF_DAWN02 = -1609202, - SAY_LIGHT_OF_DAWN03 = -1609203, - SAY_LIGHT_OF_DAWN04 = -1609204, // intro - SAY_LIGHT_OF_DAWN05 = -1609205, - SAY_LIGHT_OF_DAWN06 = -1609206, - SAY_LIGHT_OF_DAWN07 = -1609207, // During the fight - Korfax, Champion of the Light - SAY_LIGHT_OF_DAWN08 = -1609208, // Lord Maxwell Tyrosus - SAY_LIGHT_OF_DAWN09 = -1609209, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN10 = -1609210, - SAY_LIGHT_OF_DAWN11 = -1609211, - SAY_LIGHT_OF_DAWN12 = -1609212, - SAY_LIGHT_OF_DAWN13 = -1609213, - SAY_LIGHT_OF_DAWN14 = -1609214, - SAY_LIGHT_OF_DAWN15 = -1609215, - SAY_LIGHT_OF_DAWN16 = -1609216, - SAY_LIGHT_OF_DAWN17 = -1609217, - SAY_LIGHT_OF_DAWN18 = -1609218, - SAY_LIGHT_OF_DAWN19 = -1609219, - SAY_LIGHT_OF_DAWN20 = -1609220, - SAY_LIGHT_OF_DAWN21 = -1609221, - SAY_LIGHT_OF_DAWN22 = -1609222, - SAY_LIGHT_OF_DAWN23 = -1609223, - SAY_LIGHT_OF_DAWN24 = -1609224, - SAY_LIGHT_OF_DAWN25 = -1609225, // After the fight - SAY_LIGHT_OF_DAWN26 = -1609226, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN27 = -1609227, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN28 = -1609228, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN29 = -1609229, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN30 = -1609230, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN31 = -1609231, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN32 = -1609232, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN33 = -1609233, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN34 = -1609234, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN35 = -1609235, // Darion Mograine - SAY_LIGHT_OF_DAWN36 = -1609236, // Darion Mograine - SAY_LIGHT_OF_DAWN37 = -1609237, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN38 = -1609238, // Darion Mograine - SAY_LIGHT_OF_DAWN39 = -1609239, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN40 = -1609240, // Darion Mograine - SAY_LIGHT_OF_DAWN41 = -1609241, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN42 = -1609242, // Highlord Alexandros Mograine - SAY_LIGHT_OF_DAWN43 = -1609243, // The Lich King - SAY_LIGHT_OF_DAWN44 = -1609244, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN45 = -1609245, // The Lich King - SAY_LIGHT_OF_DAWN46 = -1609246, // The Lich King - SAY_LIGHT_OF_DAWN47 = -1609247, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN48 = -1609248, // The Lich King - SAY_LIGHT_OF_DAWN49 = -1609249, // The Lich King - SAY_LIGHT_OF_DAWN50 = -1609250, // Lord Maxwell Tyrosus - SAY_LIGHT_OF_DAWN51 = -1609251, // The Lich King - SAY_LIGHT_OF_DAWN52 = -1609252, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN53 = -1609253, // Highlord Darion Mograine - SAY_LIGHT_OF_DAWN54 = -1609254, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN55 = -1609255, // The Lich King - SAY_LIGHT_OF_DAWN56 = -1609256, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN57 = -1609257, // The Lich King - SAY_LIGHT_OF_DAWN58 = -1609258, // The Lich King - SAY_LIGHT_OF_DAWN59 = -1609259, // The Lich King - SAY_LIGHT_OF_DAWN60 = -1609260, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN61 = -1609261, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN62 = -1609262, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN63 = -1609263, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN64 = -1609264, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN65 = -1609265, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN66 = -1609266, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN67 = -1609267, // Highlord Tirion Fordring - SAY_LIGHT_OF_DAWN68 = -1609268, // Highlord Darion Mograine - - EMOTE_LIGHT_OF_DAWN01 = -1609269, // Emotes - EMOTE_LIGHT_OF_DAWN02 = -1609270, - EMOTE_LIGHT_OF_DAWN03 = -1609271, - EMOTE_LIGHT_OF_DAWN04 = -1609272, - EMOTE_LIGHT_OF_DAWN05 = -1609273, - EMOTE_LIGHT_OF_DAWN06 = -1609274, - EMOTE_LIGHT_OF_DAWN07 = -1609275, - EMOTE_LIGHT_OF_DAWN08 = -1609276, - EMOTE_LIGHT_OF_DAWN09 = -1609277, - EMOTE_LIGHT_OF_DAWN10 = -1609278, - EMOTE_LIGHT_OF_DAWN11 = -1609279, - EMOTE_LIGHT_OF_DAWN12 = -1609280, - EMOTE_LIGHT_OF_DAWN13 = -1609281, - EMOTE_LIGHT_OF_DAWN14 = -1609282, - EMOTE_LIGHT_OF_DAWN15 = -1609283, - EMOTE_LIGHT_OF_DAWN16 = -1609284, - EMOTE_LIGHT_OF_DAWN17 = -1609285, - EMOTE_LIGHT_OF_DAWN18 = -1609286, - - GO_LIGHT_OF_DAWN = 191330, - SPELL_THE_LIGHT_OF_DAWN_Q = 53606, // quest credit - - // ---- Dark Knight npc -------------------- - // Highlord Darion Mograine - NPC_HIGHLORD_DARION_MOGRAINE = 29173, - SPELL_ANTI_MAGIC_ZONE1 = 52893, - SPELL_DEATH_STRIKE = 53639, - SPELL_DEATH_EMBRACE = 53635, - SPELL_ICY_TOUCH1 = 49723, - SPELL_THE_LIGHT_OF_DAWN = 53658, - SPELL_THE_MIGHT_OF_MOGRAINE = 53642, // on players when begins - SPELL_UNHOLY_BLIGHT = 53640, - SPELL_ALEXANDROS_MOGRAINE_SPAWN = 53667, - SPELL_MOGRAINE_CHARGE = 53679, - SPELL_ASHBRINGER = 53701, - - // Koltira Deathweaver & Orbaz Bloodbane are using the same abilities - NPC_KOLTIRA_DEATHWEAVER = 29199, - NPC_ORBAZ_BLOODBANE = 29204, // this guy fleed - NPC_THASSARIAN = 29200, // he also does SPELL_THE_LIGHT_OF_DAWN 53658 - SPELL_BLOOD_STRIKE1 = 52374, - SPELL_DEATH_GRIP = 49576, - SPELL_ICY_TOUCH2 = 52372, - SPELL_PLAGUE_STRIKE1 = 50668, - // all do SPELL_HERO_AGGRO_AURA 53627 - - // Lich King - NPC_THE_LICH_KING = 29183, // show up at end - SPELL_APOCALYPSE = 53210, - SPELL_TELEPORT_VISUAL = 52233, - SPELL_SOUL_FEAST_ALEX = 53677, // on Alexandros - SPELL_SOUL_FEAST_TIRION = 53685, // on Tirion - SPELL_ICEBOUND_VISAGE = 53274, // not sure what is it for - SPELL_REBUKE = 53680, - - // others - NPC_RAMPAGING_ABOMINATION = 29186, - SPELL_CLEAVE1 = 53633, - SPELL_SCOURGE_HOOK = 50335, - SPELL_SCOURGE_AGGRO_AURA = 53624, - - NPC_FLESH_BEHEMOTH = 29190, // giant guy - SPELL_STOMP = 53634, - SPELL_THUNDERCLAP = 36706, - SPELL_HERO_AGGRO_AURA = 53627, - - NPC_ACHERUS_GHOUL = 29219, // just ghoul.... - SPELL_GHOULPLOSION = 53632, - - NPC_WARRIOR_OF_THE_FROZEN_WASTES = 29206, // use SPELL_CLEAVE 53631 - - NPC_HIGHLORD_ALEXANDROS_MOGRAINE = 29227, // ghost - NPC_DARION_MOGRAINE = 29228, // ghost - - // ---- Dawn npc -------------------- - // Highlord Tirion Fordring - NPC_HIGHLORD_TIRION_FORDRING = 29175, - EQUIP_HIGHLORD_TIRION_FORDRING = 13262, - SPELL_LAY_ON_HANDS = 53778, - SPELL_REBIRTH_OF_THE_ASHBRINGER = 53702, - SPELL_TIRION_CHARGE = 53705, - SPELL_TIRION_CHARGE_VISUAL = 53706, - - // others - NPC_KORFAX_CHAMPION_OF_THE_LIGHT = 29176, - SPELL_CLEAVE = 53631, - SPELL_HEROIC_LEAP = 53625, - - NPC_LORD_MAXWELL_TYROSUS = 29178, - NPC_LEONID_BARTHALOMEW_THE_REVERED = 29179, - NPC_DUKE_NICHOLAS_ZVERENHOFF = 29180, - - NPC_COMMANDER_ELIGOR_DAWNBRINGER = 29177, - SPELL_HOLY_LIGHT2 = 37979, - - NPC_RAYNE = 29181, - SPELL_REJUVENATION = 20664, - SPELL_STARFALL = 20678, - SPELL_TRANQUILITY = 25817, - SPELL_WRATH = 21807, - - NPC_DEFENDER_OF_THE_LIGHT = 29174, // also does SPELL_HEROIC_LEAP 53625 - SPELL_HOLY_LIGHT1 = 29427, - SPELL_HOLY_STRIKE = 53643, - SPELL_HOLY_WRATH = 53638, - SPELL_UPPERCUT = 53629, - - NPC_RIMBLAT_EARTHSHATTER = 29182, - SPELL_CHAIN_HEAL = 33642, - SPELL_THUNDER = 53630 -}; - -struct Locations -{ - float x, y, z, o; - uint32 id; -}; - -void UpdateWorldState(Map *map, uint32 id, uint32 state) -{ - Map::PlayerList const& players = map->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->SendUpdateWorldState(id,state); - } - } -} - -static Locations LightofDawnLoc[]= -{ - {2281.335, -5300.409, 85.170, 0}, // 0 Tirion Fordring loc - {2283.896, -5287.914, 83.066, 1.55}, // 1 Tirion Fordring loc2 - {2281.461, -5263.014, 81.164, 0}, // 2 Tirion charges - {2262.277, -5293.477, 82.167, 0}, // 3 Tirion run - {2270.286, -5287.73, 82.262, 0}, // 4 Tirion relocate - {2269.511, -5288.289, 82.225, 0}, // 5 Tirion forward - {2262.277, -5293.477, 82.167, 0}, // 6 Tirion runs to Darion - {2270.286, -5287.73, 82.262, 0}, - {2269.511, -5288.289, 82.225, 0}, - {2273.205, -5288.848, 82.617, 0}, // 9 Korfax loc1 - {2274.739, -5287.926, 82.684, 0}, // 10 Korfax loc2 - {2253.673, -5318.004, 81.724, 0}, // 11 Korfax kicked - {2287.028, -5309.644, 87.253, 0}, // 12 Maxwell loc1 - {2286.978, -5308.025, 86.83, 0}, // 13 Maxwell loc2 - {2248.877, -5307.586, 82.166, 0}, // 14 maxwell kicked - {2278.58, -5316.933, 88.319, 0}, // 15 Eligor loc1 - {2278.535, -5315.479, 88.08, 0}, // 16 Eligor loc2 - {2259.416, -5304.505, 82.149, 0}, // 17 eligor kicked - {2289.259, -5280.355, 82.112, 0}, // 18 Koltira loc1 - {2289.02, -5281.985, 82.207, 0}, // 19 Koltira loc2 - {2273.289, -5273.675, 81.701, 0}, // 20 Thassarian loc1 - {2273.332, -5275.544, 81.849, 0}, // 21 Thassarian loc2 - {2281.198, -5257.397, 80.224, 4.66}, // 22 Alexandros loc1 - {2281.156, -5259.934, 80.647, 0}, // 23 Alexandros loc2 - {2281.294, -5281.895, 82.445, 1.35}, // 24 Darion loc1 - {2281.093, -5263.013, 81.125, 0}, // 25 Darion loc1 - {2281.313, -5250.282, 79.322, 4.69}, // 26 Lich King spawns - {2281.523, -5261.058, 80.877, 0}, // 27 Lich king move forwards - {2272.709, -5255.552, 78.226, 0}, // 28 Lich king kicked - {2273.972, -5257.676, 78.862, 0} // 29 Lich king moves forward -}; - -struct npc_highlord_darion_mograineAI : public npc_escortAI -{ - npc_highlord_darion_mograineAI(Creature *pCreature) : npc_escortAI(pCreature) - { - Reset(); - } - - bool bIsBattle; - uint32 uiStep; - uint32 uiPhase_timer; - uint32 uiFight_duration; - uint32 uiTotal_dawn; - uint32 uiTotal_scourge; - uint32 uiSummon_counter; - - // Darion Mograine - uint32 uiAnti_magic_zone; - uint32 uiDeath_strike; - uint32 uiDeath_embrace; - uint32 uiIcy_touch; - uint32 uiUnholy_blight; - uint32 uiFight_speech; - uint32 uiSpawncheck; - uint32 uiTargetcheck; - - // Dawn - uint64 uiTirionGUID; - uint64 uiAlexandrosGUID; - uint64 uiDarionGUID; - uint64 uiKorfaxGUID; - uint64 uiMaxwellGUID; - uint64 uiEligorGUID; - uint64 uiRayneGUID; - uint64 uiDefenderGUID[ENCOUNTER_DEFENDER_NUMBER]; - uint64 uiEarthshatterGUID[ENCOUNTER_EARTHSHATTER_NUMBER]; - - // Death - uint64 uiKoltiraGUID; - uint64 uiOrbazGUID; - uint64 uiThassarianGUID; - uint64 uiLichKingGUID; - uint64 uiAbominationGUID[ENCOUNTER_ABOMINATION_NUMBER]; - uint64 uiBehemothGUID[ENCOUNTER_BEHEMOTH_NUMBER]; - uint64 uiGhoulGUID[ENCOUNTER_GHOUL_NUMBER]; - uint64 uiWarriorGUID[ENCOUNTER_WARRIOR_NUMBER]; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - bIsBattle = false; - uiStep = 0; - uiPhase_timer = 3000; - uiFight_duration = 300000; // 5 minutes - uiTotal_dawn = ENCOUNTER_TOTAL_DAWN; - uiTotal_scourge = ENCOUNTER_TOTAL_SCOURGE; - uiSummon_counter = 0; - - uiAnti_magic_zone = urand(1000,6000); - uiDeath_strike = urand(5000,10000); - uiDeath_embrace = urand(5000,10000); - uiIcy_touch = urand(5000,10000); - uiUnholy_blight = urand(5000,10000); - - uiFight_speech = 15000; - uiSpawncheck = 1000; - uiTargetcheck = 10000; - - me->SetStandState(UNIT_STAND_STATE_STAND); - me->Mount(25279); - me->SetVisibility(VISIBILITY_ON); - - UpdateWorldState(me->GetMap(), WORLD_STATE_REMAINS, 0); - //UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 0); - UpdateWorldState(me->GetMap(), WORLD_STATE_EVENT_BEGIN, 0); - - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiRayneGUID)) - pTemp->setDeathState(JUST_DIED); - - uiTirionGUID = NULL; - uiKorfaxGUID = NULL; - uiMaxwellGUID = NULL; - uiEligorGUID = NULL; - uiRayneGUID = NULL; - - for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiDefenderGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiDefenderGUID[i] = 0; - } - for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiEarthshatterGUID[i] = 0; - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - pTemp->setDeathState(JUST_DIED); - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->setDeathState(JUST_DIED); - - uiKoltiraGUID = NULL; - uiOrbazGUID = NULL; - uiThassarianGUID = NULL; - uiLichKingGUID = NULL; - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiAbominationGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiAbominationGUID[i] = 0; - } - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiBehemothGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiBehemothGUID[i] = 0; - } - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiGhoulGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiGhoulGUID[i] = 0; - } - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - { - if (Creature* pTemp = Unit::GetCreature(*me, uiWarriorGUID[i])) - pTemp->setDeathState(JUST_DIED); - uiWarriorGUID[i] = 0; - } - } - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who == me) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void MoveInLineOfSight(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack() && me->IsHostileTo(who)) - if (me->IsWithinDistInMap(who, 20) && me->IsWithinLOSInMap(who)) - AttackStart(who); - } - - void SetHoldState(bool bOnHold) - { - SetEscortPaused(bOnHold); - } - - void WaypointReached(uint32 i) - { - switch (i) - { - case 0: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - SetHoldState(true); - break; - case 1: - SetHoldState(true); - - SpawnNPC(); - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN07, pTemp); - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN08, pTemp); - - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - NPCChangeTarget(uiGhoulGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - NPCChangeTarget(uiWarriorGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - NPCChangeTarget(uiAbominationGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - NPCChangeTarget(uiBehemothGUID[i]); - NPCChangeTarget(uiKoltiraGUID); - NPCChangeTarget(uiOrbazGUID); - NPCChangeTarget(uiThassarianGUID); - - me->Unmount(); - me->CastSpell(me, SPELL_THE_MIGHT_OF_MOGRAINE, true); // need to fix, on player only - - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - pTemp->Unmount(); - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - pTemp->Unmount(); - - bIsBattle = true; - break; - case 2: - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - DoCast(me, SPELL_THE_LIGHT_OF_DAWN); - break; - case 3: - { - //Unit* pTirion = Unit::GetCreature(*me, uiTirionGUID); - - DoScriptText(EMOTE_LIGHT_OF_DAWN05, me); - if (me->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) - me->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - { - if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) - pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[19].x, LightofDawnLoc[19].y, LightofDawnLoc[19].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - { - if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, 0)) - pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[21].x, LightofDawnLoc[21].y, LightofDawnLoc[21].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - { - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[10].x, LightofDawnLoc[10].y, LightofDawnLoc[10].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - { - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[13].x, LightofDawnLoc[13].y, LightofDawnLoc[13].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - { - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[16].x, LightofDawnLoc[16].y, LightofDawnLoc[16].z); - } - JumpToNextStep(10000); - } break; - case 4: - DoScriptText(SAY_LIGHT_OF_DAWN27, me); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); - SetHoldState(true); - break; - case 5: - DoScriptText(SAY_LIGHT_OF_DAWN33, me); - SetHoldState(true); - break; - case 6: - SetHoldState(true); - me->HandleEmoteCommand(EMOTE_ONESHOT_SPECIALATTACK1H); - JumpToNextStep(1000); - break; - case 7: - SetHoldState(true); - JumpToNextStep(2000); - break; - case 8: - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - me->CastSpell(pTemp, SPELL_ASHBRINGER, true); - DoScriptText(EMOTE_LIGHT_OF_DAWN14, me); - SetHoldState(true); - break; - } - } - - void EnterEvadeMode() - { - if (!bIsBattle)//do not reset self if we are in battle - npc_escortAI::EnterEvadeMode(); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (!bIsBattle) - { - if (uiPhase_timer <= diff) - { - // ******* Before battle ***************************************************************** - switch (uiStep) - { - case 0: // countdown - //UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 1); - break; - - case 1: // just delay - //UpdateWorldState(me->GetMap(), WORLD_STATE_REMAINS, 1); - UpdateWorldState(me->GetMap(), WORLD_STATE_COUNTDOWN, 0); - UpdateWorldState(me->GetMap(), WORLD_STATE_EVENT_BEGIN, 1); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - JumpToNextStep(3000); - break; - - case 2: - DoScriptText(SAY_LIGHT_OF_DAWN04, me); - if (Creature* pKoltira = GetClosestCreatureWithEntry(me, NPC_KOLTIRA_DEATHWEAVER, 50.0f)) - uiKoltiraGUID = pKoltira->GetGUID(); - if (Creature* pOrbaz = GetClosestCreatureWithEntry(me, NPC_ORBAZ_BLOODBANE, 50.0f)) - uiOrbazGUID = pOrbaz->GetGUID(); - if (Creature* pThassarian = GetClosestCreatureWithEntry(me, NPC_THASSARIAN, 50.0f)) - uiThassarianGUID = pThassarian->GetGUID(); - JumpToNextStep(10000); - break; - - case 3: // rise - DoScriptText(SAY_LIGHT_OF_DAWN05, me); - JumpToNextStep(3000); - break; - - case 4: // summon ghoul - // Dunno whats the summon spell, so workaround - DoCast(me, 33271); // shack effect - uiPhase_timer = 500; - if (uiSummon_counter < ENCOUNTER_GHOUL_NUMBER) - { - Unit* pTemp = me->SummonCreature(NPC_ACHERUS_GHOUL, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->setFaction(2084); - uiGhoulGUID[uiSummon_counter] = pTemp->GetGUID(); - ++uiSummon_counter; - } - else - { - uiSummon_counter = 0; - ++uiStep; - } - break; - - case 5: // summon abomination - DoCast(me, 33271); // shack effect - uiPhase_timer = 500; - if (uiSummon_counter < ENCOUNTER_ABOMINATION_NUMBER) - { - Unit* pTemp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->setFaction(2084); - uiAbominationGUID[uiSummon_counter] = pTemp->GetGUID(); - ++uiSummon_counter; - } - else - { - uiSummon_counter = 0; - ++uiStep; - } - break; - - case 6: // summon warrior - DoCast(me, 33271); // shack effect - uiPhase_timer = 500; - if (uiSummon_counter < ENCOUNTER_WARRIOR_NUMBER) - { - Unit* pTemp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->setFaction(2084); - uiWarriorGUID[uiSummon_counter] = pTemp->GetGUID(); - ++uiSummon_counter; - } - else - { - uiSummon_counter = 0; - ++uiStep; - } - break; - - case 7: // summon warrior - DoCast(me, 33271); // shack effect - uiPhase_timer = 500; - if (uiSummon_counter < ENCOUNTER_BEHEMOTH_NUMBER) - { - Unit* pTemp = me->SummonCreature(NPC_FLESH_BEHEMOTH, (me->GetPositionX()-20)+rand()%40, (me->GetPositionY()-20)+rand()%40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->setFaction(2084); - uiBehemothGUID[uiSummon_counter] = pTemp->GetGUID(); - ++uiSummon_counter; - } - else - { - uiSummon_counter = 0; - ++uiStep; - } - break; - - case 8: // summon announce - DoScriptText(SAY_LIGHT_OF_DAWN06, me); - JumpToNextStep(5000); - break; - - case 9: // charge begins - SetHoldState(false); - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - { - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) - { - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - { - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - } - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiAbominationGUID[i])) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiBehemothGUID[i])) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiGhoulGUID[i])) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiWarriorGUID[i])) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z); - JumpToNextStep(5000); - break; - - // ******* After battle ***************************************************************** - case 11: // Tirion starts to speak - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN28, pTemp); - JumpToNextStep(21000); - break; - - case 12: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN29, pTemp); - JumpToNextStep(13000); - break; - - case 13: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN30, pTemp); - JumpToNextStep(13000); - break; - - case 14: - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_LIGHT_OF_DAWN31, me); - JumpToNextStep(7000); - break; - - case 15: // summon gate - if (Unit* pTemp = me->SummonCreature(NPC_HIGHLORD_ALEXANDROS_MOGRAINE, LightofDawnLoc[22].x, LightofDawnLoc[22].y, LightofDawnLoc[22].z, LightofDawnLoc[22].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) - { - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->CastSpell(pTemp, SPELL_ALEXANDROS_MOGRAINE_SPAWN, true); - DoScriptText(EMOTE_LIGHT_OF_DAWN06, pTemp); - uiAlexandrosGUID = pTemp->GetGUID(); - } - JumpToNextStep(4000); - break; - - case 16: // Alexandros out - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - { - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[23].x, LightofDawnLoc[23].y, LightofDawnLoc[23].z); - DoScriptText(SAY_LIGHT_OF_DAWN32, pTemp); - } - SetHoldState(false); // makes darion turns back - JumpToNextStep(5000); - break; - - case 17: - me->SetStandState(UNIT_STAND_STATE_KNEEL); - DoScriptText(SAY_LIGHT_OF_DAWN34, me); - JumpToNextStep(5000); - break; - - case 18: // Darion's spirit out - if (Unit* pTemp = me->SummonCreature(NPC_DARION_MOGRAINE, LightofDawnLoc[24].x, LightofDawnLoc[24].y, LightofDawnLoc[24].z, LightofDawnLoc[24].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) - { - DoScriptText(SAY_LIGHT_OF_DAWN35, pTemp); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - uiDarionGUID = pTemp->GetGUID(); - } - JumpToNextStep(4000); - break; - - case 19: // runs to father - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - { - DoScriptText(EMOTE_LIGHT_OF_DAWN07, pTemp); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[25].x, LightofDawnLoc[25].y, LightofDawnLoc[25].z); - } - JumpToNextStep(4000); - break; - - case 20: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN36, pTemp); - JumpToNextStep(4000); - break; - - case 21: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - DoScriptText(EMOTE_LIGHT_OF_DAWN08, pTemp); - JumpToNextStep(4000); - break; - - case 22: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN37, pTemp); - JumpToNextStep(8000); - break; - - case 23: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN38, pTemp); - JumpToNextStep(8000); - break; - - case 24: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN39, pTemp); - - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) // Tirion moves forward here - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[1].x, LightofDawnLoc[1].y, LightofDawnLoc[1].z); - - JumpToNextStep(15000); - break; - - case 25: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN40, pTemp); - JumpToNextStep(11000); - break; - - case 26: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN41, pTemp); - JumpToNextStep(5000); - break; - - case 27: - if (Creature* pTemp = Unit::GetCreature(*me, uiDarionGUID)) - pTemp->setDeathState(JUST_DIED); - JumpToNextStep(24000); - break; - - case 28: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN42, pTemp); - JumpToNextStep(6000); - break; - - case 29: // lich king spawns - if (Unit* pTemp = me->SummonCreature(NPC_THE_LICH_KING, LightofDawnLoc[26].x, LightofDawnLoc[26].y, LightofDawnLoc[26].z, LightofDawnLoc[26].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000)) - { - DoScriptText(SAY_LIGHT_OF_DAWN43, pTemp); - uiLichKingGUID = pTemp->GetGUID(); - if (Unit* pAlex = Unit::GetCreature(*me, uiAlexandrosGUID)) - pTemp->CastSpell(pAlex, SPELL_SOUL_FEAST_ALEX, false); - } - JumpToNextStep(2000); - break; - - case 30: - if (Creature* pTemp = Unit::GetCreature(*me, uiAlexandrosGUID)) // just hide him - { - DoScriptText(EMOTE_LIGHT_OF_DAWN09, pTemp); - pTemp->SetVisibility(VISIBILITY_OFF); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - pTemp->InterruptNonMeleeSpells(false); - DoScriptText(SAY_LIGHT_OF_DAWN45, pTemp); - } - JumpToNextStep(3000); - break; - - case 31: - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(EMOTE_LIGHT_OF_DAWN10, me); - DoScriptText(SAY_LIGHT_OF_DAWN44, me); - JumpToNextStep(3000); - break; - - case 32: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[27].x, LightofDawnLoc[27].y, LightofDawnLoc[27].z); - JumpToNextStep(6000); - break; - - case 33: // Darion supports to jump to lich king here - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoCast(me, SPELL_MOGRAINE_CHARGE); // jumping charge -// doesn't make it looks well, so workarounds, Darion charges, looks better - me->SetSpeed(MOVE_RUN, 3.0f); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - SetHoldState(false); - JumpToNextStep(0); - break; - - case 35: // Lich king counterattacks - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - pTemp->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - DoScriptText(SAY_LIGHT_OF_DAWN46, pTemp); - } - me->SetSpeed(MOVE_RUN, 6.0f); - me->SetStandState(UNIT_STAND_STATE_DEAD); - SetHoldState(false); // Darion got kicked by lich king - JumpToNextStep(0); - break; - - case 37: // Lich king counterattacks - me->SetStandState(UNIT_STAND_STATE_KNEEL); - JumpToNextStep(3000); - break; - - case 38: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN47, pTemp); - JumpToNextStep(8000); - break; - - case 39: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN48, pTemp); - JumpToNextStep(15000); - break; - - case 40: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN49, pTemp); - JumpToNextStep(17000); - break; - - case 41: // Lich king - Apocalypse - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - DoScriptText(EMOTE_LIGHT_OF_DAWN11, pTemp); - DoScriptText(SAY_LIGHT_OF_DAWN51, pTemp); - if (Unit* pTirion = Unit::GetCreature(*me, uiTirionGUID)) - { - pTirion->SetStandState(UNIT_STAND_STATE_KNEEL); - //pTemp->CastSpell(pTirion, SPELL_APOCALYPSE, false); // not working - pTemp->CastSpell(pTirion, SPELL_SOUL_FEAST_TIRION, false); - DoScriptText(EMOTE_LIGHT_OF_DAWN12, pTirion); - } - } - JumpToNextStep(2000); - break; - - case 42: // Maxwell yells for attack - { - float fLichPositionX = 0, - fLichPositionY = 0, - fLichPositionZ = 0; - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - fLichPositionX = pTemp->GetPositionX(); - fLichPositionY = pTemp->GetPositionY(); - fLichPositionZ = pTemp->GetPositionZ(); - } - - if (fLichPositionX && fLichPositionY) - { - Unit* pTemp; - pTemp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->setFaction(me->getFaction()); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - uiDefenderGUID[0] = pTemp->GetGUID(); - - pTemp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->setFaction(me->getFaction()); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - uiEarthshatterGUID[0] = pTemp->GetGUID(); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - DoScriptText(SAY_LIGHT_OF_DAWN50, pTemp); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->HandleEmoteCommand(EMOTE_STATE_ATTACK_UNARMED); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->SetSpeed(MOVE_RUN, 2.0f); - pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); - } - } - JumpToNextStep(4500); - break; - - case 43: // They all got kicked - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(EMOTE_LIGHT_OF_DAWN13, pTemp); - - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[14].x, LightofDawnLoc[14].y, LightofDawnLoc[14].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[11].x, LightofDawnLoc[11].y, LightofDawnLoc[11].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[17].x, LightofDawnLoc[17].y, LightofDawnLoc[17].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiDefenderGUID[0])) - { - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[0])) - { - pTemp->SetSpeed(MOVE_RUN, 6.0f); - pTemp->SetStandState(UNIT_STAND_STATE_DEAD); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z); - } - JumpToNextStep(3000); - break; - - case 44: // make them stand up - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - JumpToNextStep(1000); - break; - - case 45: - DoScriptText(SAY_LIGHT_OF_DAWN52, me); - JumpToNextStep(5000); - break; - - case 46: // Darion stand up, "not today" - me->SetSpeed(MOVE_RUN, 1.0f); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_LIGHT_OF_DAWN53, me); - SetHoldState(false); // Darion throws sword - JumpToNextStep(7000); - break; - - case 47: // Ashbringer rebirth - me->SetStandState(UNIT_STAND_STATE_KNEEL); - DoScriptText(EMOTE_LIGHT_OF_DAWN15, me); - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_HIGHLORD_TIRION_FORDRING)); - pTemp->CastSpell(pTemp, SPELL_REBIRTH_OF_THE_ASHBRINGER, false); - } - JumpToNextStep(1000); - break; - - case 48: // Show the cleansing effect (dawn of light) - //if (GameObject* pGo = me->GetMap()->GetGameObject(uiDawnofLightGUID)) - // pGo->SetPhaseMask(128, true); - me->SummonGameObject(GO_LIGHT_OF_DAWN, 2283.896, -5287.914, 83.066, 0, 0, 0, 0, 0, 30000); - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - if (pTemp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER, 0)) - pTemp->RemoveAurasDueToSpell(SPELL_REBIRTH_OF_THE_ASHBRINGER); - pTemp->CastSpell(pTemp, 41542, false); // workarounds, light expoded, makes it cool - pTemp->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); - } - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->InterruptNonMeleeSpells(false); - JumpToNextStep(2500); - break; - - case 49: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN54, pTemp); - JumpToNextStep(4000); - break; - - case 50: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN55, pTemp); - JumpToNextStep(5000); - break; - - case 51: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN56, pTemp); - JumpToNextStep(1000); - break; - - case 52: // Tiron charges - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - DoScriptText(EMOTE_LIGHT_OF_DAWN16, pTemp); - pTemp->CastSpell(pTemp, SPELL_TIRION_CHARGE, false); // jumping charge - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - pTemp->SetSpeed(MOVE_RUN, 3.0f); // workarounds, make Tirion still running - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2].x, LightofDawnLoc[2].y, LightofDawnLoc[2].z); - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->Relocate(LightofDawnLoc[28].x, LightofDawnLoc[28].y, LightofDawnLoc[28].z); // workarounds, he should kick back by Tirion, but here we relocate him - } - JumpToNextStep(1500); - break; - - case 53: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN57, pTemp); - JumpToNextStep(1000); - break; - - case 54: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - { - pTemp->SetSpeed(MOVE_RUN, 1.0f); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29].x, LightofDawnLoc[29].y, LightofDawnLoc[29].z); // 26 - } - JumpToNextStep(4000); - break; - - case 55: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); - JumpToNextStep(2000); - break; - - case 56: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->SetStandState(UNIT_STAND_STATE_STAND); - JumpToNextStep(1500); - break; - - case 57: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN58, pTemp); - JumpToNextStep(10000); - break; - - case 58: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN59, pTemp); - JumpToNextStep(10000); - break; - - case 59: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) - pTemp->CastSpell(pTemp, SPELL_TELEPORT_VISUAL, false); - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) // Tirion runs to Darion - { - pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - pTemp->SetSpeed(MOVE_RUN, 1.0f); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[6].x, LightofDawnLoc[6].y, LightofDawnLoc[6].z); - } - JumpToNextStep(2500); - break; - - case 60: - if (Creature* pTemp = Unit::GetCreature(*me, uiLichKingGUID)) // Lich king disappears here - { - DoScriptText(EMOTE_LIGHT_OF_DAWN17, pTemp); - pTemp->Kill(pTemp); - } - JumpToNextStep(10000); - break; - - case 61: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN60, pTemp); - JumpToNextStep(3000); - break; - - case 62: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[7].x, LightofDawnLoc[7].y, LightofDawnLoc[7].z); - } - JumpToNextStep(5500); - break; - - case 63: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - { - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[8].x, LightofDawnLoc[8].y, LightofDawnLoc[8].z); - DoScriptText(SAY_LIGHT_OF_DAWN61, pTemp); - } - JumpToNextStep(15000); - break; - - case 64: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN62, pTemp); - JumpToNextStep(7000); - break; - - case 65: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN63, pTemp); - JumpToNextStep(10000); - break; - - case 66: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN64, pTemp); - JumpToNextStep(11000); - break; - - case 67: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN65, pTemp); - JumpToNextStep(10000); - break; - - case 68: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN66, pTemp); - JumpToNextStep(8000); - break; - - case 69: - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN67, pTemp); - JumpToNextStep(10000); - break; - - case 70: - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_LIGHT_OF_DAWN68, me); - JumpToNextStep(10000); - break; - - case 71: - //if (GameObject* pGo = me->GetMap()->GetGameObject(uiDawnofLightGUID)) // Turn off dawn of light - // pGo->SetPhaseMask(0, true); - - { - Map *map = me->GetMap(); // search players with in 50 yards for quest credit - Map::PlayerList const &PlayerList = map->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource()->isAlive() && me->IsWithinDistInMap(i->getSource(), 50)) - i->getSource()->CastSpell(i->getSource(), SPELL_THE_LIGHT_OF_DAWN_Q, false); - } - } - me->SetVisibility(VISIBILITY_OFF); // respawns another Darion for quest turn in - me->SummonCreature(NPC_HIGHLORD_DARION_MOGRAINE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); - JumpToNextStep(1000); - break; - - case 72: - SetHoldState(false); // Escort ends - JumpToNextStep(25000); - break; - - case 73: - me->ForcedDespawn(); - break; - } - - } else uiPhase_timer -= diff; - } - - // ******* During battle ***************************************************************** - else - { - if (uiAnti_magic_zone <= diff) - { - DoCast(me, SPELL_ANTI_MAGIC_ZONE1); - uiAnti_magic_zone = 25000 + rand()%5000; - } else uiAnti_magic_zone -= diff; - - if (uiDeath_strike <= diff) - { - DoCast(me->getVictim(), SPELL_DEATH_STRIKE); - uiDeath_strike = 5000 + rand()%5000; - } else uiDeath_strike -= diff; - - if (uiDeath_embrace <= diff) - { - DoCast(me->getVictim(), SPELL_DEATH_EMBRACE); - uiDeath_embrace = 5000 + rand()%5000; - } else uiDeath_embrace -= diff; - - if (uiIcy_touch <= diff) - { - DoCast(me->getVictim(), SPELL_ICY_TOUCH1); - uiIcy_touch = 5000 + rand()%5000; - } else uiIcy_touch -= diff; - - if (uiUnholy_blight <= diff) - { - DoCast(me->getVictim(), SPELL_UNHOLY_BLIGHT); - uiUnholy_blight = 5000 + rand()%5000; - } else uiUnholy_blight -= diff; - - if (uiFight_speech <= diff) - { - DoScriptText(RAND(SAY_LIGHT_OF_DAWN09,SAY_LIGHT_OF_DAWN10,SAY_LIGHT_OF_DAWN11, - SAY_LIGHT_OF_DAWN12,SAY_LIGHT_OF_DAWN13,SAY_LIGHT_OF_DAWN14, - SAY_LIGHT_OF_DAWN15,SAY_LIGHT_OF_DAWN16,SAY_LIGHT_OF_DAWN17, - SAY_LIGHT_OF_DAWN18,SAY_LIGHT_OF_DAWN19,SAY_LIGHT_OF_DAWN20, - SAY_LIGHT_OF_DAWN21,SAY_LIGHT_OF_DAWN22,SAY_LIGHT_OF_DAWN23, - SAY_LIGHT_OF_DAWN24), me); - uiFight_speech = 15000 + rand()%5000; - } else uiFight_speech -= diff; - - // Check spawns - if (uiSpawncheck <= diff) - { - SpawnNPC(); - uiSpawncheck = 1000; - } else uiSpawncheck -= diff; - - // Check targets - if (uiTargetcheck <= diff) - { - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - NPCChangeTarget(uiGhoulGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - NPCChangeTarget(uiWarriorGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - NPCChangeTarget(uiAbominationGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - NPCChangeTarget(uiBehemothGUID[i]); - NPCChangeTarget(uiKoltiraGUID); - NPCChangeTarget(uiOrbazGUID); - NPCChangeTarget(uiThassarianGUID); - - uiTargetcheck = 10000; - } else uiTargetcheck -= diff; - - // Battle end - if (uiFight_duration <= diff + 5000) - { - if (!uiTirionGUID) - if (Unit* pTemp = me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING, LightofDawnLoc[0].x, LightofDawnLoc[0].y, LightofDawnLoc[0].z, 1.528, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000)) - { - pTemp->setFaction(me->getFaction()); - pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); - DoScriptText(SAY_LIGHT_OF_DAWN25, pTemp); - uiTirionGUID = pTemp->GetGUID(); - } - } - if (uiFight_duration <= diff) - { - bIsBattle = false; - uiFight_duration = 300000; - - if (me->HasAura(SPELL_THE_MIGHT_OF_MOGRAINE, 0)) - me->RemoveAurasDueToSpell(SPELL_THE_MIGHT_OF_MOGRAINE); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->InterruptNonMeleeSpells(false); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) - DespawnNPC(uiDefenderGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) - DespawnNPC(uiEarthshatterGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - DespawnNPC(uiAbominationGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - DespawnNPC(uiBehemothGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - DespawnNPC(uiGhoulGUID[i]); - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - DespawnNPC(uiWarriorGUID[i]); - - if (Creature* pTemp = Unit::GetCreature(*me, uiKorfaxGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[9].x, LightofDawnLoc[9].y, LightofDawnLoc[9].z); - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiMaxwellGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[12].x, LightofDawnLoc[12].y, LightofDawnLoc[12].z); - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiEligorGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[15].x, LightofDawnLoc[15].y, LightofDawnLoc[15].z); - } - DespawnNPC(uiRayneGUID); - - if (Creature* pTemp = Unit::GetCreature(*me, uiKoltiraGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[18].x, LightofDawnLoc[18].y, LightofDawnLoc[18].z); - pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false); - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiOrbazGUID)) - DoScriptText(EMOTE_LIGHT_OF_DAWN04, pTemp); - - if (Creature* pTemp = Unit::GetCreature(*me, uiThassarianGUID)) - { - pTemp->RemoveAllAuras(); - pTemp->DeleteThreatList(); - pTemp->CombatStop(true); - pTemp->AttackStop(); - pTemp->setFaction(me->getFaction()); - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[20].x, LightofDawnLoc[20].y, LightofDawnLoc[20].z); - pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false); - } - - if (Creature* pTemp = Unit::GetCreature(*me, uiTirionGUID)) - DoScriptText(SAY_LIGHT_OF_DAWN26, pTemp); - - SetHoldState(false); - - } else uiFight_duration -= diff; - - DoMeleeAttackIfReady(); - } - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhase_timer = uiTimer; - ++uiStep; - } - - void NPCChangeTarget(uint64 ui_GUID) - { - if (Creature* pTemp = Unit::GetCreature(*me, ui_GUID)) - if (pTemp->isAlive()) - if (Unit* pTarger = SelectUnit(SELECT_TARGET_RANDOM,0)) - if (pTarger->isAlive()) - { - // pTemp->DeleteThreatList(); - pTemp->AddThreat(pTarger, 0.0f); - pTemp->AI()->AttackStart(pTarger); - pTemp->SetInCombatWith(pTarger); - pTarger->SetInCombatWith(pTemp); - // pTemp->GetMotionMaster()->MoveChase(pTarger, 20.0f); - } - } - - void SpawnNPC() - { - Unit* pTemp = NULL; - - // Death - for (uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiGhoulGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_ACHERUS_GHOUL, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2084); - uiGhoulGUID[i] = pTemp->GetGUID(); - } - } - for (uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiAbominationGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2084); - uiAbominationGUID[i] = pTemp->GetGUID(); - } - } - for (uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiWarriorGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2084); - uiWarriorGUID[i] = pTemp->GetGUID(); - } - } - for (uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiBehemothGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_FLESH_BEHEMOTH, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2084); - uiBehemothGUID[i] = pTemp->GetGUID(); - } - } - - // Dawn - for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiDefenderGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiDefenderGUID[i] = pTemp->GetGUID(); - } - } - for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) - { - pTemp = Unit::GetCreature(*me, uiEarthshatterGUID[i]); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiEarthshatterGUID[i] = pTemp->GetGUID(); - } - } - pTemp = Unit::GetCreature(*me, uiKorfaxGUID); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_KORFAX_CHAMPION_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiKorfaxGUID = pTemp->GetGUID(); - } - pTemp = Unit::GetCreature(*me, uiMaxwellGUID); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_LORD_MAXWELL_TYROSUS, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiMaxwellGUID = pTemp->GetGUID(); - } - pTemp = Unit::GetCreature(*me, uiEligorGUID); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_COMMANDER_ELIGOR_DAWNBRINGER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiEligorGUID = pTemp->GetGUID(); - } - pTemp = Unit::GetCreature(*me, uiRayneGUID); - if (!pTemp) - { - pTemp = me->SummonCreature(NPC_RAYNE, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - pTemp->setFaction(2089); - me->AddThreat(pTemp, 0.0f); - uiRayneGUID = pTemp->GetGUID(); - } - } - - void DespawnNPC(uint64 pGUID) - { - if (Creature* pTemp = Unit::GetCreature(*me, pGUID)) - if (pTemp->isAlive()) - { - pTemp->SetVisibility(VISIBILITY_OFF); - pTemp->Kill(pTemp); - } - } -}; - -bool GossipHello_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(12801) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(0, "I am ready.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_highlord_darion_mograineAI, pCreature->AI())->uiStep = 1; - CAST_AI(npc_highlord_darion_mograineAI, pCreature->AI())->Start(true, false, pPlayer->GetGUID()); - break; - } - return true; -} - -/*###### -## npc the lich king in dawn of light -######*/ -struct npc_the_lich_king_tirion_dawnAI : public ScriptedAI -{ - npc_the_lich_king_tirion_dawnAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } - void Reset() {} - void AttackStart(Unit * /*who*/) {} // very sample, just don't make them aggreesive - void UpdateAI(const uint32 /*diff*/) {} - void JustDied(Unit* /*killer*/) {} -}; - -CreatureAI* GetAI_npc_highlord_darion_mograine(Creature* pCreature) -{ - return new npc_highlord_darion_mograineAI(pCreature); -} - -CreatureAI* GetAI_npc_the_lich_king_tirion_dawn(Creature* pCreature) -{ - return new npc_the_lich_king_tirion_dawnAI (pCreature); -} - -void AddSC_the_scarlet_enclave_c5() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_highlord_darion_mograine"; - newscript->GetAI = &GetAI_npc_highlord_darion_mograine; - newscript->pGossipHello = &GossipHello_npc_highlord_darion_mograine; - newscript->pGossipSelect = &GossipSelect_npc_highlord_darion_mograine; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_the_lich_king_tirion_dawn"; - newscript->GetAI = &GetAI_npc_the_lich_king_tirion_dawn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp deleted file mode 100644 index cdfd69234fb..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_enclave/the_scarlet_enclave.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" - -/*#### -## npc_valkyr_battle_maiden -####*/ -#define SPELL_REVIVE 51918 -#define VALK_WHISPER "It is not yet your time, champion. Rise! Rise and fight once more!" - -struct npc_valkyr_battle_maidenAI : public PassiveAI -{ - npc_valkyr_battle_maidenAI(Creature *c) : PassiveAI(c) {} - - uint32 FlyBackTimer; - float x, y, z; - uint32 phase; - - void Reset() - { - me->setActive(true); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlying(true); - FlyBackTimer = 500; - phase = 0; - - me->GetPosition(x, y, z); - z += 4; x -= 3.5; y -= 5; - me->GetMotionMaster()->Clear(false); - me->GetMap()->CreatureRelocation(me, x, y, z, 0.0f); - } - - void UpdateAI(const uint32 diff) - { - if (FlyBackTimer <= diff) - { - Player *plr = NULL; - if (me->isSummon()) - if (Unit *summoner = CAST_SUM(me)->GetSummoner()) - if (summoner->GetTypeId() == TYPEID_PLAYER) - plr = CAST_PLR(summoner); - - if (!plr) - phase = 3; - - switch(phase) - { - case 0: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->HandleEmoteCommand(EMOTE_STATE_FLYGRABCLOSED); - FlyBackTimer = 500; - break; - case 1: - plr->GetClosePoint(x,y,z, me->GetObjectSize()); - z += 2.5; x -= 2; y -= 1.5; - me->GetMotionMaster()->MovePoint(0, x, y, z); - me->SetUInt64Value(UNIT_FIELD_TARGET, plr->GetGUID()); - me->SetVisibility(VISIBILITY_ON); - FlyBackTimer = 4500; - break; - case 2: - if (!plr->isRessurectRequested()) - { - me->HandleEmoteCommand(EMOTE_ONESHOT_CUSTOMSPELL01); - DoCast(plr, SPELL_REVIVE, true); - me->MonsterWhisper(VALK_WHISPER, plr->GetGUID()); - } - FlyBackTimer = 5000; - break; - case 3: - me->SetVisibility(VISIBILITY_OFF); - FlyBackTimer = 3000; - break; - case 4: - me->DisappearAndDie(); - break; - default: - //Nothing To DO - break; - } - ++phase; - } else FlyBackTimer-=diff; - } -}; - -CreatureAI* GetAI_npc_valkyr_battle_maiden(Creature* pCreature) -{ - return new npc_valkyr_battle_maidenAI (pCreature); -} - -void AddSC_the_scarlet_enclave() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_valkyr_battle_maiden"; - newscript->GetAI = &GetAI_npc_valkyr_battle_maiden; - newscript->RegisterSelf(); - - // Chapter 3: Scarlet Armies Approach... - An End To All Things... - // Chapter 4: An End To All Things... - An End To All Things... -} diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp deleted file mode 100644 index cb6ed1daf22..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_arcanist_doan.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Arcanist_Doan -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1189019, - SAY_SPECIALAE = -1189020, - - SPELL_POLYMORPH = 13323, - SPELL_AOESILENCE = 8988, - SPELL_ARCANEEXPLOSION = 9433, - SPELL_FIREAOE = 9435, - SPELL_ARCANEBUBBLE = 9438, -}; - -struct boss_arcanist_doanAI : public ScriptedAI -{ - boss_arcanist_doanAI(Creature *c) : ScriptedAI(c) {} - - uint32 Polymorph_Timer; - uint32 AoESilence_Timer; - uint32 ArcaneExplosion_Timer; - bool bCanDetonate; - bool bShielded; - - void Reset() - { - Polymorph_Timer = 20000; - AoESilence_Timer = 15000; - ArcaneExplosion_Timer = 3000; - bCanDetonate = false; - bShielded = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (bShielded && bCanDetonate) - { - DoCast(me, SPELL_FIREAOE); - bCanDetonate = false; - } - - if (me->HasAura(SPELL_ARCANEBUBBLE)) - return; - - //If we are <50% hp cast Arcane Bubble - if (!bShielded && me->GetHealth()*100 / me->GetMaxHealth() <= 50) - { - //wait if we already casting - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoScriptText(SAY_SPECIALAE, me); - DoCast(me, SPELL_ARCANEBUBBLE); - - bCanDetonate = true; - bShielded = true; - } - - if (Polymorph_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_POLYMORPH); - - Polymorph_Timer = 20000; - } else Polymorph_Timer -= diff; - - //AoESilence_Timer - if (AoESilence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_AOESILENCE); - AoESilence_Timer = 15000 + rand()%5000; - } else AoESilence_Timer -= diff; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANEEXPLOSION); - ArcaneExplosion_Timer = 8000; - } else ArcaneExplosion_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_arcanist_doan(Creature* pCreature) -{ - return new boss_arcanist_doanAI (pCreature); -} - -void AddSC_boss_arcanist_doan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_arcanist_doan"; - newscript->GetAI = &GetAI_boss_arcanist_doan; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp deleted file mode 100644 index 6b6efa0f934..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Azshir_the_Sleepless -SD%Complete: 80 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CALLOFTHEGRAVE 17831 -#define SPELL_TERRIFY 7399 -#define SPELL_SOULSIPHON 7290 - -struct boss_azshir_the_sleeplessAI : public ScriptedAI -{ - boss_azshir_the_sleeplessAI(Creature *c) : ScriptedAI(c) {} - - uint32 SoulSiphon_Timer; - uint32 CallOftheGrave_Timer; - uint32 Terrify_Timer; - - void Reset() - { - SoulSiphon_Timer = 1; - CallOftheGrave_Timer = 30000; - Terrify_Timer = 20000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <50% hp cast Soul Siphon rank 1 - if (me->GetHealth()*100 / me->GetMaxHealth() <= 50 && !me->IsNonMeleeSpellCasted(false)) - { - //SoulSiphon_Timer - if (SoulSiphon_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOULSIPHON); - return; - - //SoulSiphon_Timer = 20000; - } else SoulSiphon_Timer -= diff; - } - - //CallOfTheGrave_Timer - if (CallOftheGrave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CALLOFTHEGRAVE); - CallOftheGrave_Timer = 30000; - } else CallOftheGrave_Timer -= diff; - - //Terrify_Timer - if (Terrify_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TERRIFY); - Terrify_Timer = 20000; - } else Terrify_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_azshir_the_sleepless(Creature* pCreature) -{ - return new boss_azshir_the_sleeplessAI (pCreature); -} - -void AddSC_boss_azshir_the_sleepless() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_azshir_the_sleepless"; - newscript->GetAI = &GetAI_boss_azshir_the_sleepless; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp deleted file mode 100644 index f7b6b7cce4b..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Bloodmage_Thalnos -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1189016, - SAY_HEALTH = -1189017, - SAY_KILL = -1189018, - - SPELL_FLAMESHOCK = 8053, - SPELL_SHADOWBOLT = 1106, - SPELL_FLAMESPIKE = 8814, - SPELL_FIRENOVA = 16079, -}; - -struct boss_bloodmage_thalnosAI : public ScriptedAI -{ - boss_bloodmage_thalnosAI(Creature *c) : ScriptedAI(c) {} - - bool HpYell; - uint32 FlameShock_Timer; - uint32 ShadowBolt_Timer; - uint32 FlameSpike_Timer; - uint32 FireNova_Timer; - - void Reset() - { - HpYell = false; - FlameShock_Timer = 10000; - ShadowBolt_Timer = 2000; - FlameSpike_Timer = 8000; - FireNova_Timer = 40000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*Victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <35% hp - if (!HpYell && ((me->GetHealth()*100) / me->GetMaxHealth() <= 35)) - { - DoScriptText(SAY_HEALTH, me); - HpYell = true; - } - - //FlameShock_Timer - if (FlameShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMESHOCK); - FlameShock_Timer = 10000 + rand()%5000; - } else FlameShock_Timer -= diff; - - //FlameSpike_Timer - if (FlameSpike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMESPIKE); - FlameSpike_Timer = 30000; - } else FlameSpike_Timer -= diff; - - //FireNova_Timer - if (FireNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRENOVA); - FireNova_Timer = 40000; - } else FireNova_Timer -= diff; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLT); - ShadowBolt_Timer = 2000; - } else ShadowBolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_bloodmage_thalnos(Creature* pCreature) -{ - return new boss_bloodmage_thalnosAI (pCreature); -} - -void AddSC_boss_bloodmage_thalnos() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_bloodmage_thalnos"; - newscript->GetAI = &GetAI_boss_bloodmage_thalnos; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp deleted file mode 100644 index 17bbf0c23c6..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_headless_horseman.cpp +++ /dev/null @@ -1,892 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Headless_Horseman -SD%Complete: -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "SpellMgr.h" -#include "scarlet_monastery.h" - -//this texts are already used by 3975 and 3976 -#define SAY_ENTRANCE -1189001 -#define SAY_REJOINED -1189002 -#define SAY_LOST_HEAD -1189003 -#define SAY_CONFLAGRATION -1189004 -#define SAY_SPROUTING_PUMPKINS -1189005 -#define SAY_PLAYER_DEATH -1189006 -#define SAY_DEATH -1189007 - -uint32 RandomLaugh[] = {11965, 11975, 11976}; - - // Entryes -#define HH_MOUNTED 23682 -#define HH_UNHORSED 23800 -#define HEAD 23775 -#define PULSING_PUMPKIN 23694 -#define PUMPKIN_FIEND 23545 -#define HELPER 23686 -#define WISP_INVIS 24034 - - //Spells -#define SPELL_CLEAVE 42587 -#define SPELL_CONFLAGRATION 42380 //Phase 2, can't find real spell(Dim Fire?) -//#define SPELL_CONFL_SPEED 22587 //8% increase speed, value 22587 from SPELL_CONFLAGRATION mains that spell? -#define SPELL_SUMMON_PUMPKIN 42394 - -#define SPELL_WHIRLWIND 43116 -#define SPELL_IMMUNE 42556 -#define SPELL_BODY_REGEN 42403 -#define SPELL_CONFUSE 43105 - -#define SPELL_FLYING_HEAD 42399 //visual flying head -#define SPELL_HEAD 42413 //visual buff, "head" -#define SPELL_HEAD_IS_DEAD 42428 //at killing head, Phase 3 - -#define SPELL_PUMPKIN_AURA 42280 -#define SPELL_PUMPKIN_AURA_GREEN 42294 -#define SPELL_SQUASH_SOUL 42514 -#define SPELL_SPROUTING 42281 -#define SPELL_SPROUT_BODY 42285 - - //Effects -#define SPELL_RHYME_BIG 42909 -//#define SPELL_RHYME_SMALL 42910 -#define SPELL_HEAD_SPEAKS 43129 -#define SPELL_HEAD_LANDS 42400 -#define SPELL_BODY_FLAME 42074 -#define SPELL_HEAD_FLAME 42971 -//#define SPELL_ENRAGE_VISUAL 42438 // he uses this spell? -#define SPELL_WISP_BLUE 42821 -#define SPELL_WISP_FLIGHT_PORT 42818 -//#define SPELL_WISP_INVIS 42823 -#define SPELL_SMOKE 42355 -#define SPELL_DEATH 42566 //not correct spell - -struct Locations -{ - float x, y, z; -}; - -static Locations FlightPoint[]= -{ - {1754.00,1346.00,17.50}, - {1765.00,1347.00,19.00}, - {1784.00,1346.80,25.40}, - {1803.30,1347.60,33.00}, - {1824.00,1350.00,42.60}, - {1838.80,1353.20,49.80}, - {1852.00,1357.60,55.70}, - {1861.30,1364.00,59.40}, - {1866.30,1374.80,61.70}, - {1864.00,1387.30,63.20}, - {1854.80,1399.40,64.10}, - {1844.00,1406.90,64.10}, - {1824.30,1411.40,63.30}, - {1801.00,1412.30,60.40}, - {1782.00,1410.10,55.50}, - {1770.50,1405.20,50.30}, - {1765.20,1400.70,46.60}, - {1761.40,1393.40,41.70}, - {1759.10,1386.70,36.60}, - {1757.80,1378.20,29.00}, - {1758.00,1367.00,19.51} -}; - -static Locations Spawn[]= -{ - {1776.27,1348.74,19.20}, //spawn point for pumpkin shrine mob - {1765.28,1347.46,17.55} //spawn point for smoke -}; - -static const char* Text[]= -{ - "Horseman rise...", - "Your time is nigh...", - "You felt death once...", - "Now, know demise!" -}; - -#define EMOTE_LAUGHS "Headless Horseman laughs" - -struct mob_wisp_invisAI : public ScriptedAI -{ - mob_wisp_invisAI(Creature *c) : ScriptedAI(c) - { - Creaturetype = delay = spell = spell2 = 0; - //that's hack but there are no info about range of this spells in dbc - SpellEntry *wisp = GET_SPELL(SPELL_WISP_BLUE); - if (wisp) - wisp->rangeIndex = 6; //100 yards - SpellEntry *port = GET_SPELL(SPELL_WISP_FLIGHT_PORT); - if (port) - port->rangeIndex = 6; - } - - uint32 Creaturetype; - uint32 delay; - uint32 spell; - uint32 spell2; - void Reset(){} - void EnterCombat(Unit * /*who*/){} - void SetType(uint32 _type) - { - switch(Creaturetype = _type) - { - case 1: - spell = SPELL_PUMPKIN_AURA_GREEN; - break; - case 2: - delay = 15000; - spell = SPELL_BODY_FLAME; - spell2 = SPELL_DEATH; - break; - case 3: - delay = 15000; - spell = SPELL_SMOKE; - break; - case 4: - delay = 7000; - spell2 = SPELL_WISP_BLUE; - break; - } - if (spell) - DoCast(me, spell); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_WISP_FLIGHT_PORT && Creaturetype == 4) - me->SetDisplayId(2027); - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || Creaturetype != 1 || !who->isTargetableForAttack()) - return; - - if (me->IsWithinDist(who, 0.1, false) && !who->HasAura(SPELL_SQUASH_SOUL)) - DoCast(who, SPELL_SQUASH_SOUL); - } - - void UpdateAI(const uint32 diff) - { - if (delay) - { - if (delay <= diff) - { - me->RemoveAurasDueToSpell(SPELL_SMOKE); - if (spell2) - DoCast(me, spell2); - delay = 0; - } else delay -= diff; - } - } -}; - -struct mob_headAI : public ScriptedAI -{ - mob_headAI(Creature *c) : ScriptedAI(c) {} - - uint64 bodyGUID; - - uint32 Phase; - uint32 laugh; - uint32 wait; - - bool withbody; - bool die; - - void Reset() - { - Phase = 0; - bodyGUID = 0; - die = false; - withbody = true; - wait = 1000; - laugh = urand(15000,30000); - } - - void EnterCombat(Unit * /*who*/) {} - void SaySound(int32 textEntry, Unit *pTarget = 0) - { - DoScriptText(textEntry, me, pTarget); - //DoCast(me, SPELL_HEAD_SPEAKS, true); - Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000); - if (speaker) - speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); - laugh += 3000; - } - - void DamageTaken(Unit* /*done_by*/,uint32 &damage) - { - if (withbody) - return; - - switch(Phase) - { - case 1: - if (((me->GetHealth() - damage)*100)/me->GetMaxHealth() < 67) - Disappear(); - break; - case 2: - if (((me->GetHealth() - damage)*100)/me->GetMaxHealth() < 34) - Disappear(); - break; - case 3: - if (damage >= me->GetHealth()) - { - die = true; - withbody = true; - wait = 300; - damage = me->GetHealth() - me->GetMaxHealth()/100; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->StopMoving(); - //me->GetMotionMaster()->MoveIdle(); - DoCast(me, SPELL_HEAD_IS_DEAD); - } - break; - } - } - - void SpellHit(Unit *caster, const SpellEntry* spell) - { - if (!withbody) - return; - - if (spell->Id == SPELL_FLYING_HEAD) - { - if (Phase < 3) ++Phase; - else Phase = 3; - withbody = false; - if (!bodyGUID) - bodyGUID = caster->GetGUID(); - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_HEAD_LANDS, true); - DoCast(me, SPELL_HEAD, false); - SaySound(SAY_LOST_HEAD); - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFleeing(caster->getVictim()); - } - } - void Disappear();//we must set returned=true(this will prevent from "body calls head" while head flying to body), see function below - void UpdateAI(const uint32 diff) - { - if (!withbody) - { - if (wait <= diff) - { - wait = 1000; - if (!me->getVictim()) return; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveFleeing(me->getVictim()); - } else wait -= diff; - - if (laugh <= diff) - { - laugh = urand(15000,30000); - DoPlaySoundToSet(me, RandomLaugh[urand(0,2)]); - //DoCast(me, SPELL_HEAD_SPEAKS, true); //this spell remove buff "head" - Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000); - if (speaker) - speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); - me->MonsterTextEmote(EMOTE_LAUGHS,NULL); - } else laugh -= diff; - } - else - { - if (die) - { - if (wait <= diff) - { - die = false; - if (Unit *body = Unit::GetUnit((*me), bodyGUID)) - body->Kill(body); - me->Kill(me); - } else wait -= diff; - } - } - } -}; - -struct boss_headless_horsemanAI : public ScriptedAI -{ - boss_headless_horsemanAI(Creature *c) : ScriptedAI(c) - { - SpellEntry *confl = GET_SPELL(SPELL_CONFLAGRATION); - if (confl) - { - confl->EffectApplyAuraName[0] = SPELL_AURA_PERIODIC_DAMAGE_PERCENT; - confl->EffectBasePoints[0] = 10; - //confl->EffectBaseDice[0] = 10; - confl->DmgMultiplier[0] = 1; - } -/* - if (SpellEntry *confl = GET_SPELL(SPELL_CONFLAGRATION)) - confl->EffectTriggerSpell[1] = 22587; - - if (SpellEntry *speed = GET_SPELL(22587)) - { - speed->Effect[1] = SPELL_EFFECT_APPLY_AURA; - speed->EffectApplyAuraName[1] = SPELL_AURA_MOD_CONFUSE; - } -*/ - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint64 headGUID; - uint64 PlayerGUID; - - uint32 Phase; - uint32 id; - uint32 count; - uint32 say_timer; - - uint32 conflagrate; - uint32 summonadds; - uint32 cleave; - uint32 regen; - uint32 whirlwind; - uint32 laugh; - uint32 burn; - - bool withhead; - bool returned; - bool IsFlying; - bool wp_reached; - bool burned; - - void Reset() - { - Phase = 1; - conflagrate = 15000; - summonadds = 15000; - laugh = urand(16000,20000); - cleave = 2000; - regen = 1000; - burn = 6000; - count = 0; - say_timer = 3000; - - withhead = true; - returned = true; - burned = false; - IsFlying = false; - DoCast(me, SPELL_HEAD); - if (headGUID) - { - if (Creature* Head = Unit::GetCreature((*me), headGUID)) - Head->DisappearAndDie(); - - headGUID = 0; - } - - //if (pInstance) - // pInstance->SetData(DATA_HORSEMAN_EVENT, NOT_STARTED); - } - - void FlyMode() - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); - me->SetSpeed(MOVE_WALK,5.0f,true); - wp_reached = false; - count = 0; - say_timer = 3000; - id = 0; - Phase = 0; - } - - void MovementInform(uint32 type, uint32 i) - { - if (type != POINT_MOTION_TYPE || !IsFlying || i != id) - return; - - wp_reached = true; - - switch (id) - { - case 0: - me->SetVisibility(VISIBILITY_ON); - break; - case 1: - { - if (Creature *smoke = me->SummonCreature(HELPER,Spawn[1].x,Spawn[1].y,Spawn[1].z,0,TEMPSUMMON_TIMED_DESPAWN,20000)) - CAST_AI(mob_wisp_invisAI, smoke->AI())->SetType(3); - DoCast(me, SPELL_RHYME_BIG); - break; - } - case 6: - if (pInstance) - pInstance->SetData(GAMEOBJECT_PUMPKIN_SHRINE, 0); //hide gameobject - break; - case 19: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); - break; - case 20: - { - Phase = 1; - IsFlying = false; - wp_reached = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - SaySound(SAY_ENTRANCE); - if (Unit *plr = Unit::GetUnit((*me),PlayerGUID)) - DoStartMovement(plr); - break; - } - } - ++id; - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); - DoZoneInCombat(); - } - void AttackStart(Unit* who) {ScriptedAI::AttackStart(who);} - void MoveInLineOfSight(Unit *who) - { - if (withhead && Phase != 0) - ScriptedAI::MoveInLineOfSight(who); - } - void KilledUnit(Unit *plr) - { - if (plr->GetTypeId() == TYPEID_PLAYER) - { - if (withhead) - SaySound(SAY_PLAYER_DEATH); - //maybe possible when player dies from conflagration - else if (Creature *Head = Unit::GetCreature((*me), headGUID)) - CAST_AI(mob_headAI, Head->AI())->SaySound(SAY_PLAYER_DEATH); - } - } - - void SaySound(int32 textEntry, Unit *pTarget = 0) - { - DoScriptText(textEntry, me, pTarget); - laugh += 4000; - } - - Player* SelectRandomPlayer(float range = 0.0f, bool checkLoS = true) - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) return NULL; - - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - Map::PlayerList::const_iterator i; - if (PlayerList.isEmpty()) return NULL; - - std::list temp; - std::list::const_iterator j; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if ((me->IsWithinLOSInMap(i->getSource()) || !checkLoS) && me->getVictim() != i->getSource() && - me->IsWithinDistInMap(i->getSource(), range) && i->getSource()->isAlive()) - temp.push_back(i->getSource()); - - if (temp.size()) - { - j = temp.begin(); - advance(j, rand()%temp.size()); - return (*j); - } - return NULL; - } - - void SpellHitTarget(Unit* unit, const SpellEntry* spell) - { - if (spell->Id == SPELL_CONFLAGRATION && unit->HasAura(SPELL_CONFLAGRATION)) - SaySound(SAY_CONFLAGRATION,unit); - } - - void JustDied(Unit* /*killer*/) - { - me->StopMoving(); - //me->GetMotionMaster()->MoveIdle(); - SaySound(SAY_DEATH); - if (Creature *flame = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000)) - flame->CastSpell(flame,SPELL_BODY_FLAME,false); - if (Creature *wisp = DoSpawnCreature(WISP_INVIS,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,60000)) - CAST_AI(mob_wisp_invisAI, wisp->AI())->SetType(4); - if (pInstance) - pInstance->SetData(DATA_HORSEMAN_EVENT, DONE); - } - - void SpellHit(Unit *caster, const SpellEntry* spell) - { - if (withhead) - return; - - if (spell->Id == SPELL_FLYING_HEAD) - { - if (Phase < 3) - ++Phase; - else - Phase = 3; - withhead = true; - me->RemoveAllAuras(); - me->SetName("Headless Horseman"); - me->SetHealth(me->GetMaxHealth()); - SaySound(SAY_REJOINED); - DoCast(me, SPELL_HEAD); - caster->GetMotionMaster()->Clear(false); - caster->GetMotionMaster()->MoveFollow(me,6,urand(0,5)); - //DoResetThreat();//not sure if need - std::list::const_iterator itr; - for (itr = caster->getThreatManager().getThreatList().begin(); itr != caster->getThreatManager().getThreatList().end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive() && pUnit != caster) - me->AddThreat(pUnit,caster->getThreatManager().getThreat(pUnit)); - } - } - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && withhead) - { - withhead = false; - returned = false; - damage = me->GetHealth() - me->GetMaxHealth()/100; - me->RemoveAllAuras(); - me->SetName("Headless Horseman, Unhorsed"); - - if (!headGUID) - headGUID = DoSpawnCreature(HEAD,rand()%6,rand()%6,0,0,TEMPSUMMON_DEAD_DESPAWN,0)->GetGUID(); - Unit* Head = Unit::GetUnit((*me), headGUID); - if (Head && Head->isAlive()) - { - Head->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //Head->CastSpell(Head,SPELL_HEAD_INVIS,false); - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_IMMUNE, true); - DoCast(me, SPELL_BODY_REGEN, true); - DoCast(Head, SPELL_FLYING_HEAD, true); - DoCast(me, SPELL_CONFUSE, false); //test - done_by->ProcDamageAndSpell(me,PROC_FLAG_KILL,PROC_FLAG_KILLED,PROC_EX_NONE,0); - whirlwind = urand(4000,8000); - regen = 0; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (withhead) - { - switch(Phase) - { - case 0: - { - if (!IsFlying) - { - if (say_timer <= diff) - { - say_timer = 3000; - Player *plr = SelectRandomPlayer(100.0f,false); - if (count < 3) - { - if (plr) - plr->Say(Text[count],0); - } - else - { - DoCast(me, SPELL_RHYME_BIG); - if (plr) - { - plr->Say(Text[count],0); - plr->HandleEmoteCommand(ANIM_EMOTE_SHOUT); - } - wp_reached = true; - IsFlying = true; - count = 0; - break; - } - ++count; - } else say_timer -= diff; - } - else - { - if (wp_reached) - { - wp_reached = false; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(id,FlightPoint[id].x,FlightPoint[id].y,FlightPoint[id].z); - } - } - } - break; - case 1: - if (burned) - break; - if (burn <= diff) - { - if (Creature *flame = me->SummonCreature(HELPER,Spawn[0].x,Spawn[0].y,Spawn[0].z,0,TEMPSUMMON_TIMED_DESPAWN,17000)) - CAST_AI(mob_wisp_invisAI, flame->AI())->SetType(2); - burned = true; - } else burn -= diff; - break; - case 2: - if (conflagrate <= diff) - { - if (Unit *plr = SelectRandomPlayer(30.0f)) - DoCast(plr, SPELL_CONFLAGRATION, false); - conflagrate = urand(10000,16000); - } else conflagrate -= diff; - break; - case 3: - if (summonadds <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SUMMON_PUMPKIN); - SaySound(SAY_SPROUTING_PUMPKINS); - summonadds = urand(25000,35000); - } else summonadds -= diff; - break; - } - - if (laugh <= diff) - { - laugh = urand(11000,22000); - me->MonsterTextEmote(EMOTE_LAUGHS,NULL); - DoPlaySoundToSet(me, RandomLaugh[rand()%3]); - } else laugh -= diff; - - if (UpdateVictim()) - { - DoMeleeAttackIfReady(); - if (cleave <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - cleave = urand(2000,6000); //1 cleave per 2.0-6.0sec - } else cleave -= diff; - } - } - else - { - if (regen <= diff) - { - regen = 1000; //"body calls head" - if (me->GetHealth()/me->GetMaxHealth() == 1 && !returned) - { - if (Phase > 1) - --Phase; - else - Phase = 1; - Creature* Head = Unit::GetCreature((*me), headGUID); - if (Head && Head->isAlive()) - { - CAST_AI(mob_headAI, Head->AI())->Phase = Phase; - CAST_AI(mob_headAI, Head->AI())->Disappear(); - } - return; - } - } - else regen -= diff; - - if (whirlwind <= diff) - { - whirlwind = urand(4000,8000); - if (urand(0,1)) - { - me->RemoveAurasDueToSpell(SPELL_CONFUSE); - DoCast(me, SPELL_WHIRLWIND, true); - DoCast(me, SPELL_CONFUSE); - } else - me->RemoveAurasDueToSpell(SPELL_WHIRLWIND); - } else whirlwind -= diff; - } - } -}; - -void mob_headAI::Disappear() -{ - if (withbody) - return; - if (bodyGUID) - { - Creature *body = Unit::GetCreature((*me), bodyGUID); - if (body && body->isAlive()) - { - withbody = true; - me->RemoveAllAuras(); - body->RemoveAurasDueToSpell(SPELL_IMMUNE);//hack, SpellHit doesn't calls if body has immune aura - DoCast(body, SPELL_FLYING_HEAD); - me->SetHealth(me->GetMaxHealth()); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->GetMotionMaster()->MoveIdle(); - CAST_AI(boss_headless_horsemanAI, body->AI())->returned = true; - } - } -} - -struct mob_pulsing_pumpkinAI : public ScriptedAI -{ - mob_pulsing_pumpkinAI(Creature *c) : ScriptedAI(c) {} - - bool sprouted; - uint64 debuffGUID; - - void Reset() - { - float x, y, z; - me->GetPosition(x, y, z); //this visual aura some under ground - me->GetMap()->CreatureRelocation(me, x,y,z + 0.35f, 0.0f); - Despawn(); - Creature *debuff = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,14500); - if (debuff) - { - debuff->SetDisplayId(me->GetDisplayId()); - debuff->CastSpell(debuff,SPELL_PUMPKIN_AURA_GREEN,false); - CAST_AI(mob_wisp_invisAI, debuff->AI())->SetType(1); - debuffGUID = debuff->GetGUID(); - } - sprouted = false; - DoCast(me, SPELL_PUMPKIN_AURA, true); - DoCast(me, SPELL_SPROUTING); - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); - } - - void EnterCombat(Unit * /*who*/){} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SPROUTING) - { - sprouted = true; - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); - DoCast(me, SPELL_SPROUT_BODY, true); - me->UpdateEntry(PUMPKIN_FIEND); - DoStartMovement(me->getVictim()); - } - } - - void Despawn() - { - if (!debuffGUID) return; - Unit *debuff = Unit::GetUnit((*me),debuffGUID); - if (debuff) - debuff->SetVisibility(VISIBILITY_OFF); - debuffGUID = 0; - } - - void JustDied(Unit * /*killer*/) { if (!sprouted) Despawn(); } - - void MoveInLineOfSight(Unit *who) - { - if (!who || !who->isTargetableForAttack() || !me->IsHostileTo(who) || me->getVictim()) - return; - - me->AddThreat(who,0.0f); - if (sprouted) - DoStartMovement(who); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (sprouted && UpdateVictim()) - DoMeleeAttackIfReady(); - } -}; - -bool GOHello_go_loosely_turned_soil(Player* pPlayer, GameObject* soil) -{ - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (pInstance) - { - if (pInstance->GetData(DATA_HORSEMAN_EVENT) != NOT_STARTED) - return true; - pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); - } -/* if (soil->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER && plr->getLevel() > 64) - { - plr->PrepareQuestMenu(soil->GetGUID()); - plr->SendPreparedQuest(soil->GetGUID()); - } - if (plr->GetQuestStatus(11405) == QUEST_STATUS_INCOMPLETE && plr->getLevel() > 64) - { */ - pPlayer->AreaExploredOrEventHappens(11405); - if (Creature *horseman = soil->SummonCreature(HH_MOUNTED,FlightPoint[20].x,FlightPoint[20].y,FlightPoint[20].z,0,TEMPSUMMON_MANUAL_DESPAWN,0)) - { - CAST_AI(boss_headless_horsemanAI, horseman->AI())->PlayerGUID = pPlayer->GetGUID(); - CAST_AI(boss_headless_horsemanAI, horseman->AI())->FlyMode(); - } - //} - return true; -} - -CreatureAI* GetAI_mob_head(Creature* pCreature) -{ - return new mob_headAI (pCreature); -} - -CreatureAI* GetAI_boss_headless_horseman(Creature* pCreature) -{ - return new boss_headless_horsemanAI (pCreature); -} - -CreatureAI* GetAI_mob_pulsing_pumpkin(Creature* pCreature) -{ - return new mob_pulsing_pumpkinAI (pCreature); -} - -CreatureAI* GetAI_mob_wisp_invis(Creature* pCreature) -{ - return new mob_wisp_invisAI (pCreature); -} - -void AddSC_boss_headless_horseman() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_headless_horseman"; - newscript->GetAI = &GetAI_boss_headless_horseman; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_head"; - newscript->GetAI = &GetAI_mob_head; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_pulsing_pumpkin"; - newscript->GetAI = &GetAI_mob_pulsing_pumpkin; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_wisp_invis"; - newscript->GetAI = &GetAI_mob_wisp_invis; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_loosely_turned_soil"; - newscript->pGOHello = &GOHello_go_loosely_turned_soil; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp deleted file mode 100644 index e0db29aa240..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_herod.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Herod -SD%Complete: 95 -SDComment: Should in addition spawn Myrmidons in the hallway outside -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" - -#define SAY_AGGRO -1189000 -#define SAY_WHIRLWIND -1189001 -#define SAY_ENRAGE -1189002 -#define SAY_KILL -1189003 -#define EMOTE_ENRAGE -1189004 - -#define SPELL_RUSHINGCHARGE 8260 -#define SPELL_CLEAVE 15496 -#define SPELL_WHIRLWIND 8989 -#define SPELL_FRENZY 8269 - -#define ENTRY_SCARLET_TRAINEE 6575 -#define ENTRY_SCARLET_MYRMIDON 4295 - -struct boss_herodAI : public ScriptedAI -{ - boss_herodAI(Creature *c) : ScriptedAI(c) {} - - bool Enrage; - - uint32 Cleave_Timer; - uint32 Whirlwind_Timer; - - void Reset() - { - Enrage = false; - Cleave_Timer = 12000; - Whirlwind_Timer = 60000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_RUSHINGCHARGE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*killer*/) - { - for (uint8 i = 0; i < 20; ++i) - me->SummonCreature(ENTRY_SCARLET_TRAINEE, 1939.18, -431.58, 17.09, 6.22, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <30% hp goes Enraged - if (!Enrage && me->GetHealth()*100 / me->GetMaxHealth() <= 30 && !me->IsNonMeleeSpellCasted(false)) - { - DoScriptText(EMOTE_ENRAGE, me); - DoScriptText(SAY_ENRAGE, me); - DoCast(me, SPELL_FRENZY); - Enrage = true; - } - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 12000; - } else Cleave_Timer -= diff; - - // Whirlwind_Timer - if (Whirlwind_Timer <= diff) - { - DoScriptText(SAY_WHIRLWIND, me); - DoCast(me->getVictim(), SPELL_WHIRLWIND); - Whirlwind_Timer = 30000; - } else Whirlwind_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_herod(Creature* pCreature) -{ - return new boss_herodAI(pCreature); -} - -struct mob_scarlet_traineeAI : public npc_escortAI -{ - mob_scarlet_traineeAI(Creature *c) : npc_escortAI(c) - { - Start_Timer = urand(1000,6000); - } - - uint32 Start_Timer; - - void Reset() {} - void WaypointReached(uint32 /*uiPoint*/) {} - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (Start_Timer) - { - if (Start_Timer <= diff) - { - Start(true,true); - Start_Timer = 0; - } else Start_Timer -= diff; - } - - npc_escortAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_mob_scarlet_trainee(Creature* pCreature) -{ - return new mob_scarlet_traineeAI(pCreature); -} - -void AddSC_boss_herod() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_herod"; - newscript->GetAI = &GetAI_boss_herod; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_scarlet_trainee"; - newscript->GetAI = &GetAI_mob_scarlet_trainee; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp deleted file mode 100644 index b9b15f34508..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_High_Inquisitor_Fairbanks -SD%Complete: 100 -SDComment: TODO: if this guy not involved in some special event, remove (and let ACID script) -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -enum eSpells -{ - SPELL_CURSEOFBLOOD = 8282, - SPELL_DISPELMAGIC = 15090, - SPELL_FEAR = 12096, - SPELL_HEAL = 12039, - SPELL_POWERWORDSHIELD = 11647, - SPELL_SLEEP = 8399 -}; - -struct boss_high_inquisitor_fairbanksAI : public ScriptedAI -{ - boss_high_inquisitor_fairbanksAI(Creature *c) : ScriptedAI(c) {} - - uint32 CurseOfBlood_Timer; - uint32 DispelMagic_Timer; - uint32 Fear_Timer; - uint32 Heal_Timer; - uint32 Sleep_Timer; - uint32 Dispel_Timer; - bool PowerWordShield; - - void Reset() - { - CurseOfBlood_Timer = 10000; - DispelMagic_Timer = 30000; - Fear_Timer = 40000; - Heal_Timer = 30000; - Sleep_Timer = 30000; - Dispel_Timer = 20000; - PowerWordShield = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <25% hp cast Heal - if (me->GetHealth()*100 / me->GetMaxHealth() <= 25 && !me->IsNonMeleeSpellCasted(false) && Heal_Timer <= diff) - { - DoCast(me, SPELL_HEAL); - Heal_Timer = 30000; - } else Heal_Timer -= diff; - - //Fear_Timer - if (Fear_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_FEAR); - - Fear_Timer = 40000; - } else Fear_Timer -= diff; - - //Sleep_Timer - if (Sleep_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,0)) - DoCast(pTarget, SPELL_SLEEP); - - Sleep_Timer = 30000; - } else Sleep_Timer -= diff; - - //PowerWordShield_Timer - if (!PowerWordShield && me->GetHealth()*100 / me->GetMaxHealth() <= 25) - { - DoCast(me, SPELL_POWERWORDSHIELD); - PowerWordShield = true; - } - - //Dispel_Timer - if (Dispel_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_DISPELMAGIC); - - DispelMagic_Timer = 30000; - } else DispelMagic_Timer -= diff; - - //CurseOfBlood_Timer - if (CurseOfBlood_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); - CurseOfBlood_Timer = 25000; - } else CurseOfBlood_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_high_inquisitor_fairbanks(Creature* pCreature) -{ - return new boss_high_inquisitor_fairbanksAI (pCreature); -} - -void AddSC_boss_high_inquisitor_fairbanks() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_high_inquisitor_fairbanks"; - newscript->GetAI = &GetAI_boss_high_inquisitor_fairbanks; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp deleted file mode 100644 index 300e69611cd..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Houndmaster_Loksey -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - SAY_AGGRO = -1189021, - SPELL_SUMMONSCARLETHOUND = 17164, - SPELL_BLOODLUST = 6742 -}; - -struct boss_houndmaster_lokseyAI : public ScriptedAI -{ - boss_houndmaster_lokseyAI(Creature *c) : ScriptedAI(c) {} - - uint32 BloodLust_Timer; - - void Reset() - { - BloodLust_Timer = 20000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BloodLust_Timer <= diff) - { - DoCast(me, SPELL_BLOODLUST); - BloodLust_Timer = 20000; - } else BloodLust_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_houndmaster_loksey(Creature* pCreature) -{ - return new boss_houndmaster_lokseyAI (pCreature); -} - -void AddSC_boss_houndmaster_loksey() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_houndmaster_loksey"; - newscript->GetAI = &GetAI_boss_houndmaster_loksey; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp deleted file mode 100644 index b4b84fc8059..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_interrogator_vishas.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Interrogator_Vishas -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "scarlet_monastery.h" - -enum eEnums -{ - SAY_AGGRO = -1189011, - SAY_HEALTH1 = -1189012, - SAY_HEALTH2 = -1189013, - SAY_KILL = -1189014, - SAY_TRIGGER_VORREL = -1189015, - - SPELL_SHADOWWORDPAIN = 2767, -}; - -struct boss_interrogator_vishasAI : public ScriptedAI -{ - boss_interrogator_vishasAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool Yell30; - bool Yell60; - uint32 ShadowWordPain_Timer; - - void Reset() - { - ShadowWordPain_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*Victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*Killer*/) - { - if (!pInstance) - return; - - //Any other actions to do with vorrel? setStandState? - if (Unit *vorrel = Unit::GetUnit(*me,pInstance->GetData64(DATA_VORREL))) - DoScriptText(SAY_TRIGGER_VORREL, vorrel); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are low on hp Do sayings - if (!Yell60 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 60)) - { - DoScriptText(SAY_HEALTH1, me); - Yell60 = true; - } - - if (!Yell30 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 30)) - { - DoScriptText(SAY_HEALTH2, me); - Yell30 = true; - } - - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); - ShadowWordPain_Timer = 5000 + rand()%10000; - } else ShadowWordPain_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_interrogator_vishas(Creature* pCreature) -{ - return new boss_interrogator_vishasAI (pCreature); -} - -void AddSC_boss_interrogator_vishas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_interrogator_vishas"; - newscript->GetAI = &GetAI_boss_interrogator_vishas; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp deleted file mode 100644 index 32b85e214a0..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mograine_And_Whitemane -SD%Complete: 90 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "scarlet_monastery.h" - -enum eEnums -{ - //Mograine says - SAY_MO_AGGRO = -1189005, - SAY_MO_KILL = -1189006, - SAY_MO_RESSURECTED = -1189007, - - //Whitemane says - SAY_WH_INTRO = -1189008, - SAY_WH_KILL = -1189009, - SAY_WH_RESSURECT = -1189010, - - //Mograine Spells - SPELL_CRUSADERSTRIKE = 14518, - SPELL_HAMMEROFJUSTICE = 5589, - SPELL_LAYONHANDS = 9257, - SPELL_RETRIBUTIONAURA = 8990, - - //Whitemanes Spells - SPELL_DEEPSLEEP = 9256, - SPELL_SCARLETRESURRECTION = 9232, - SPELL_DOMINATEMIND = 14515, - SPELL_HOLYSMITE = 9481, - SPELL_HEAL = 12039, - SPELL_POWERWORDSHIELD = 22187 -}; - -struct boss_scarlet_commander_mograineAI : public ScriptedAI -{ - boss_scarlet_commander_mograineAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiCrusaderStrike_Timer; - uint32 m_uiHammerOfJustice_Timer; - - bool m_bHasDied; - bool m_bHeal; - bool m_bFakeDeath; - - void Reset() - { - m_uiCrusaderStrike_Timer = 10000; - m_uiHammerOfJustice_Timer = 10000; - - //Incase wipe during phase that mograine fake death - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - - if (m_pInstance) - if (me->isAlive()) - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT,NOT_STARTED); - - m_bHasDied = false; - m_bHeal = false; - m_bFakeDeath = false; - } - - void JustReachedHome() - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT != NOT_STARTED)) - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, FAIL); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_MO_AGGRO, me); - DoCast(me, SPELL_RETRIBUTIONAURA); - - me->CallForHelp(VISIBLE_RANGE); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(SAY_MO_KILL, me); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) - { - if (uiDamage < me->GetHealth() || m_bHasDied || m_bFakeDeath) - return; - - if (!m_pInstance) - return; - - //On first death, fake death and open door, as well as initiate whitemane if exist - if (Unit* Whitemane = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_WHITEMANE))) - { - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS); - - Whitemane->GetMotionMaster()->MovePoint(1,1163.113370,1398.856812,32.527786); - - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MoveIdle(); - - me->SetHealth(0); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - me->ClearComboPointHolders(); - me->RemoveAllAuras(); - me->ClearAllReactives(); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_DEAD); - - m_bHasDied = true; - m_bFakeDeath = true; - - uiDamage = 0; - } - } - - void SpellHit(Unit* /*pWho*/, const SpellEntry* pSpell) - { - //When hit with ressurection say text - if (pSpell->Id == SPELL_SCARLETRESURRECTION) - { - DoScriptText(SAY_MO_RESSURECTED, me); - m_bFakeDeath = false; - - if (m_pInstance) - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, SPECIAL); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (m_bHasDied && !m_bHeal && m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL) - { - //On ressurection, stop fake death and heal whitemane and resume fight - if (Unit* Whitemane = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_WHITEMANE))) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(Whitemane, SPELL_LAYONHANDS); - - m_uiCrusaderStrike_Timer = 10000; - m_uiHammerOfJustice_Timer = 10000; - - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - - m_bHeal = true; - } - } - - //This if-check to make sure mograine does not attack while fake death - if (m_bFakeDeath) - return; - - //m_uiCrusaderStrike_Timer - if (m_uiCrusaderStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CRUSADERSTRIKE); - m_uiCrusaderStrike_Timer = 10000; - } else m_uiCrusaderStrike_Timer -= uiDiff; - - //m_uiHammerOfJustice_Timer - if (m_uiHammerOfJustice_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_HAMMEROFJUSTICE); - m_uiHammerOfJustice_Timer = 60000; - } else m_uiHammerOfJustice_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_high_inquisitor_whitemaneAI : public ScriptedAI -{ - boss_high_inquisitor_whitemaneAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiHeal_Timer; - uint32 m_uiPowerWordShield_Timer; - uint32 m_uiHolySmite_Timer; - uint32 m_uiWait_Timer; - - bool m_bCanResurrectCheck; - bool m_bCanResurrect; - - void Reset() - { - m_uiWait_Timer = 7000; - m_uiHeal_Timer = 10000; - m_uiPowerWordShield_Timer = 15000; - m_uiHolySmite_Timer = 6000; - - m_bCanResurrectCheck = false; - m_bCanResurrect = false; - - if (m_pInstance) - if (me->isAlive()) - m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, NOT_STARTED); - } - - void AttackStart(Unit* pWho) - { - if (m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED) - return; - - ScriptedAI::AttackStart(pWho); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_WH_INTRO, me); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(SAY_WH_KILL, me); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (m_bCanResurrect) - { - //When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out - if (m_pInstance && m_uiWait_Timer <= uiDiff) - { - if (Unit* Mograine = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_MOGRAINE))) - { - DoCast(Mograine, SPELL_SCARLETRESURRECTION); - DoScriptText(SAY_WH_RESSURECT, me); - m_bCanResurrect = false; - } - } - else m_uiWait_Timer -= uiDiff; - } - - //Cast Deep sleep when health is less than 50% - if (!m_bCanResurrectCheck && me->GetHealth()*100 / me->GetMaxHealth() <= 50) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me->getVictim(), SPELL_DEEPSLEEP); - m_bCanResurrectCheck = true; - m_bCanResurrect = true; - return; - } - - //while in "resurrect-mode", don't do anything - if (m_bCanResurrect) - return; - - //If we are <75% hp cast healing spells at self or Mograine - if (m_uiHeal_Timer <= uiDiff) - { - Creature* pTarget = NULL; - - if (me->GetHealth() <= me->GetMaxHealth()*0.75f) - pTarget = me; - - if (m_pInstance) - { - if (Creature* pMograine = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_MOGRAINE))) - { - // checking m_bCanResurrectCheck prevents her healing Mograine while he is "faking death" - if (m_bCanResurrectCheck && pMograine->isAlive() && pMograine->GetHealth() <= pMograine->GetMaxHealth()*0.75f) - pTarget = pMograine; - } - } - - if (pTarget) - DoCast(pTarget, SPELL_HEAL); - - m_uiHeal_Timer = 13000; - } else m_uiHeal_Timer -= uiDiff; - - //m_uiPowerWordShield_Timer - if (m_uiPowerWordShield_Timer <= uiDiff) - { - DoCast(me, SPELL_POWERWORDSHIELD); - m_uiPowerWordShield_Timer = 15000; - } else m_uiPowerWordShield_Timer -= uiDiff; - - //m_uiHolySmite_Timer - if (m_uiHolySmite_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_HOLYSMITE); - m_uiHolySmite_Timer = 6000; - } else m_uiHolySmite_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_scarlet_commander_mograine(Creature* pCreature) -{ - return new boss_scarlet_commander_mograineAI (pCreature); -} - -CreatureAI* GetAI_boss_high_inquisitor_whitemane(Creature* pCreature) -{ - return new boss_high_inquisitor_whitemaneAI (pCreature); -} - -void AddSC_boss_mograine_and_whitemane() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_scarlet_commander_mograine"; - newscript->GetAI = &GetAI_boss_scarlet_commander_mograine; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_high_inquisitor_whitemane"; - newscript->GetAI = &GetAI_boss_high_inquisitor_whitemane; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp deleted file mode 100644 index 5d0a3b3792f..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/boss_scorn.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Scorn -SD%Complete: 100 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_LICHSLAP 28873 -#define SPELL_FROSTBOLTVOLLEY 8398 -#define SPELL_MINDFLAY 17313 -#define SPELL_FROSTNOVA 15531 - -struct boss_scornAI : public ScriptedAI -{ - boss_scornAI(Creature *c) : ScriptedAI(c) {} - - uint32 LichSlap_Timer; - uint32 FrostboltVolley_Timer; - uint32 MindFlay_Timer; - uint32 FrostNova_Timer; - - void Reset() - { - LichSlap_Timer = 45000; - FrostboltVolley_Timer = 30000; - MindFlay_Timer = 30000; - FrostNova_Timer = 30000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //LichSlap_Timer - if (LichSlap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LICHSLAP); - LichSlap_Timer = 45000; - } else LichSlap_Timer -= diff; - - //FrostboltVolley_Timer - if (FrostboltVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLTVOLLEY); - FrostboltVolley_Timer = 20000; - } else FrostboltVolley_Timer -= diff; - - //MindFlay_Timer - if (MindFlay_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MINDFLAY); - MindFlay_Timer = 20000; - } else MindFlay_Timer -= diff; - - //FrostNova_Timer - if (FrostNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTNOVA); - FrostNova_Timer = 15000; - } else FrostNova_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_scorn(Creature* pCreature) -{ - return new boss_scornAI (pCreature); -} - -void AddSC_boss_scorn() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_scorn"; - newscript->GetAI = &GetAI_boss_scorn; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp b/src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp deleted file mode 100644 index 33642d4511c..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/instance_scarlet_monastery.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Scarlet_Monastery -SD%Complete: 50 -SDComment: -SDCategory: Scarlet Monastery -EndScriptData */ - -#include "ScriptedPch.h" -#include "scarlet_monastery.h" - -#define ENTRY_PUMPKIN_SHRINE 186267 -#define ENTRY_HORSEMAN 23682 -#define ENTRY_HEAD 23775 -#define ENTRY_PUMPKIN 23694 - -#define MAX_ENCOUNTER 2 - -struct instance_scarlet_monastery : public ScriptedInstance -{ - instance_scarlet_monastery(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 PumpkinShrineGUID; - uint64 HorsemanGUID; - uint64 HeadGUID; - std::set HorsemanAdds; - - uint64 MograineGUID; - uint64 WhitemaneGUID; - uint64 VorrelGUID; - uint64 DoorHighInquisitorGUID; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - PumpkinShrineGUID = 0; - HorsemanGUID = 0; - HeadGUID = 0; - HorsemanAdds.clear(); - - MograineGUID = 0; - WhitemaneGUID = 0; - VorrelGUID = 0; - DoorHighInquisitorGUID = 0; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case ENTRY_PUMPKIN_SHRINE: PumpkinShrineGUID = pGo->GetGUID();break; - case 104600: DoorHighInquisitorGUID = pGo->GetGUID(); break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case ENTRY_HORSEMAN: HorsemanGUID = pCreature->GetGUID(); break; - case ENTRY_HEAD: HeadGUID = pCreature->GetGUID(); break; - case ENTRY_PUMPKIN: HorsemanAdds.insert(pCreature->GetGUID());break; - case 3976: MograineGUID = pCreature->GetGUID(); break; - case 3977: WhitemaneGUID = pCreature->GetGUID(); break; - case 3981: VorrelGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_MOGRAINE_AND_WHITE_EVENT: - if (data == IN_PROGRESS) - DoUseDoorOrButton(DoorHighInquisitorGUID); - if (data == FAIL) - DoUseDoorOrButton(DoorHighInquisitorGUID); - - m_auiEncounter[0] = data; - break; - case GAMEOBJECT_PUMPKIN_SHRINE: - HandleGameObject(PumpkinShrineGUID, false); - break; - case DATA_HORSEMAN_EVENT: - m_auiEncounter[1] = data; - if (data == DONE) - { - for (std::set::const_iterator itr = HorsemanAdds.begin(); itr != HorsemanAdds.end(); ++itr) - { - Creature* add = instance->GetCreature(*itr); - if (add && add->isAlive()) - add->Kill(add); - } - HorsemanAdds.clear(); - HandleGameObject(PumpkinShrineGUID, false); - } - break; - } - } - - uint64 GetData64(uint32 type) - { - switch(type) - { - //case GAMEOBJECT_PUMPKIN_SHRINE: return PumpkinShrineGUID; - //case DATA_HORSEMAN: return HorsemanGUID; - //case DATA_HEAD: return HeadGUID; - case DATA_MOGRAINE: return MograineGUID; - case DATA_WHITEMANE: return WhitemaneGUID; - case DATA_VORREL: return VorrelGUID; - case DATA_DOOR_WHITEMANE: return DoorHighInquisitorGUID; - } - return 0; - } - - uint32 GetData(uint32 type) - { - if (type == TYPE_MOGRAINE_AND_WHITE_EVENT) - return m_auiEncounter[0]; - if (type == DATA_HORSEMAN_EVENT) - return m_auiEncounter[1]; - return 0; - } -}; - -InstanceData* GetInstanceData_instance_scarlet_monastery(Map* pMap) -{ - return new instance_scarlet_monastery(pMap); -} - -void AddSC_instance_scarlet_monastery() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_scarlet_monastery"; - newscript->GetInstanceData = &GetInstanceData_instance_scarlet_monastery; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h b/src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h deleted file mode 100644 index 2b6399ae3e4..00000000000 --- a/src/server/scripts/EasternKingdoms/scarlet_monastery/scarlet_monastery.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SCARLET_M -#define DEF_SCARLET_M - -#define TYPE_MOGRAINE_AND_WHITE_EVENT 1 -#define DATA_MOGRAINE 2 -#define DATA_WHITEMANE 3 -#define DATA_DOOR_WHITEMANE 4 - -#define DATA_HORSEMAN_EVENT 5 -#define GAMEOBJECT_PUMPKIN_SHRINE 6 - -#define DATA_VORREL 7 -#endif - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp deleted file mode 100644 index 50a9e204566..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_darkmaster_gandling.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Darkmaster_Gandling -SD%Complete: 75 -SDComment: Doors missing in instance script. -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_ARCANEMISSILES 22272 -#define SPELL_SHADOWSHIELD 22417 //Not right ID. But 12040 is wrong either. -#define SPELL_CURSE 18702 - -#define ADD_1X 170.205 -#define ADD_1Y 99.413 -#define ADD_1Z 104.733 -#define ADD_1O 3.16 - -#define ADD_2X 170.813 -#define ADD_2Y 97.857 -#define ADD_2Z 104.713 -#define ADD_2O 3.16 - -#define ADD_3X 170.720 -#define ADD_3Y 100.900 -#define ADD_3Z 104.739 -#define ADD_3O 3.16 - -#define ADD_4X 171.866 -#define ADD_4Y 99.373 -#define ADD_4Z 104.732 -#define ADD_4O 3.16 - -struct boss_darkmaster_gandlingAI : public ScriptedAI -{ - boss_darkmaster_gandlingAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ArcaneMissiles_Timer; - uint32 ShadowShield_Timer; - uint32 Curse_Timer; - uint32 Teleport_Timer; - - void Reset() - { - ArcaneMissiles_Timer = 4500; - ShadowShield_Timer = 12000; - Curse_Timer = 2000; - Teleport_Timer = 16000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_GANDLING, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ArcaneMissiles_Timer - if (ArcaneMissiles_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANEMISSILES); - ArcaneMissiles_Timer = 8000; - } else ArcaneMissiles_Timer -= diff; - - //ShadowShield_Timer - if (ShadowShield_Timer <= diff) - { - DoCast(me, SPELL_SHADOWSHIELD); - ShadowShield_Timer = 14000 + rand()%14000; - } else ShadowShield_Timer -= diff; - - //Curse_Timer - if (Curse_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSE); - Curse_Timer = 15000 + rand()%12000; - } else Curse_Timer -= diff; - - //Teleporting Random Target to one of the six pre boss rooms and spawn 3-4 skeletons near the gamer. - //We will only telport if gandling has more than 3% of hp so teleported gamers can always loot. - if (me->GetHealth()*100 / me->GetMaxHealth() > 3) - { - if (Teleport_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - if (DoGetThreat(pTarget)) - DoModifyThreatPercent(pTarget, -100); - - Creature *Summoned = NULL; - switch(rand()%6) - { - case 0: - DoTeleportPlayer(pTarget, 250.0696,0.3921,84.8408,3.149); - Summoned = me->SummonCreature(16119,254.2325,0.3417,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,257.7133,4.0226,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,258.6702,-2.60656,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 1: - DoTeleportPlayer(pTarget, 181.4220,-91.9481,84.8410,1.608); - Summoned = me->SummonCreature(16119,184.0519,-73.5649,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,179.5951,-73.7045,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,180.6452,-78.2143,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,283.2274,-78.1518,84.8407,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 2: - DoTeleportPlayer(pTarget, 95.1547,-1.8173,85.2289,0.043); - Summoned = me->SummonCreature(16119,100.9404,-1.8016,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,101.3729,0.4882,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,101.4596,-4.4740,85.2289,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 3: - DoTeleportPlayer(pTarget, 250.0696,0.3921,72.6722,3.149); - Summoned = me->SummonCreature(16119,240.34481,0.7368,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,240.3633,-2.9520,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,240.6702,3.34949,72.6722,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 4: - DoTeleportPlayer(pTarget, 181.4220,-91.9481,70.7734,1.608); - Summoned = me->SummonCreature(16119,184.0519,-73.5649,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,179.5951,-73.7045,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,180.6452,-78.2143,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,283.2274,-78.1518,70.7734,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - case 5: - DoTeleportPlayer(pTarget, 106.1541,-1.8994,75.3663,0.043); - Summoned = me->SummonCreature(16119,115.3945,-1.5555,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,257.7133,1.8066,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - Summoned = me->SummonCreature(16119,258.6702,-5.1001,75.3663,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000); - if (Summoned) - Summoned->AI()->AttackStart(pTarget); - break; - } - } - Teleport_Timer = 20000 + rand()%15000; - } else Teleport_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_darkmaster_gandling(Creature* pCreature) -{ - return new boss_darkmaster_gandlingAI (pCreature); -} - -void AddSC_boss_darkmaster_gandling() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_darkmaster_gandling"; - newscript->GetAI = &GetAI_boss_darkmaster_gandling; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp deleted file mode 100644 index 8bb9ec68aca..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_death_knight_darkreaver.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Death_knight_darkreaver -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -struct boss_death_knight_darkreaverAI : public ScriptedAI -{ - boss_death_knight_darkreaverAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (me->GetHealth() <= damage) - DoCast(me, 23261, true); //Summon Darkreaver's Fallen Charger - } - - void EnterCombat(Unit * /*who*/) - { - } -}; -CreatureAI* GetAI_boss_death_knight_darkreaver(Creature* pCreature) -{ - return new boss_death_knight_darkreaverAI (pCreature); -} - -void AddSC_boss_death_knight_darkreaver() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_death_knight_darkreaver"; - newscript->GetAI = &GetAI_boss_death_knight_darkreaver; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp deleted file mode 100644 index 5ff01d48623..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_doctor_theolen_krastinov.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 .sourceforge.net/> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Doctor_Theolen_Krastinov -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -enum eEnums -{ - EMOTE_GENERIC_FRENZY_KILL = -1000001, - - SPELL_REND = 16509, - SPELL_BACKHAND = 18103, - SPELL_FRENZY = 8269 -}; - -struct boss_theolenkrastinovAI : public ScriptedAI -{ - boss_theolenkrastinovAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiRend_Timer; - uint32 m_uiBackhand_Timer; - uint32 m_uiFrenzy_Timer; - - void Reset() - { - m_uiRend_Timer = 8000; - m_uiBackhand_Timer = 9000; - m_uiFrenzy_Timer = 1000; - } - - void JustDied(Unit* /*pKiller*/) - { - ScriptedInstance* pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_DOCTORTHEOLENKRASTINOV_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //Rend_Timer - if (m_uiRend_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_REND); - m_uiRend_Timer = 10000; - } - else - m_uiRend_Timer -= uiDiff; - - //Backhand_Timer - if (m_uiBackhand_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BACKHAND); - m_uiBackhand_Timer = 10000; - } - else - m_uiBackhand_Timer -= uiDiff; - - //Frenzy_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 26) - { - if (m_uiFrenzy_Timer <= uiDiff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); - - m_uiFrenzy_Timer = 120000; - } - else - m_uiFrenzy_Timer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_theolenkrastinov(Creature* pCreature) -{ - return new boss_theolenkrastinovAI (pCreature); -} - -void AddSC_boss_theolenkrastinov() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_doctor_theolen_krastinov"; - newscript->GetAI = &GetAI_boss_theolenkrastinov; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp deleted file mode 100644 index a038fc7a0b8..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_illucia_barov.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Illucia_Barov -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_CURSEOFAGONY 18671 -#define SPELL_SHADOWSHOCK 20603 -#define SPELL_SILENCE 15487 -#define SPELL_FEAR 6215 - -struct boss_illuciabarovAI : public ScriptedAI -{ - boss_illuciabarovAI(Creature *c) : ScriptedAI(c) {} - - uint32 CurseOfAgony_Timer; - uint32 ShadowShock_Timer; - uint32 Silence_Timer; - uint32 Fear_Timer; - - void Reset() - { - CurseOfAgony_Timer = 18000; - ShadowShock_Timer = 9000; - Silence_Timer = 5000; - Fear_Timer = 30000; - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_LADYILLUCIABAROV_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //CurseOfAgony_Timer - if (CurseOfAgony_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSEOFAGONY); - CurseOfAgony_Timer = 30000; - } else CurseOfAgony_Timer -= diff; - - //ShadowShock_Timer - if (ShadowShock_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_SHADOWSHOCK); - - ShadowShock_Timer = 12000; - } else ShadowShock_Timer -= diff; - - //Silence_Timer - if (Silence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - Silence_Timer = 14000; - } else Silence_Timer -= diff; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - Fear_Timer = 30000; - } else Fear_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_illuciabarov(Creature* pCreature) -{ - return new boss_illuciabarovAI (pCreature); -} - -void AddSC_boss_illuciabarov() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_illucia_barov"; - newscript->GetAI = &GetAI_boss_illuciabarov; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp deleted file mode 100644 index c4c0f95d8d1..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_instructor_malicia.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_instructormalicia -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_CALLOFGRAVES 17831 -#define SPELL_CORRUPTION 11672 -#define SPELL_FLASHHEAL 10917 -#define SPELL_RENEW 10929 -#define SPELL_HEALINGTOUCH 9889 - -struct boss_instructormaliciaAI : public ScriptedAI -{ - boss_instructormaliciaAI(Creature *c) : ScriptedAI(c) {} - - uint32 CallOfGraves_Timer; - uint32 Corruption_Timer; - uint32 FlashHeal_Timer; - uint32 Renew_Timer; - uint32 HealingTouch_Timer; - uint32 FlashCounter; - uint32 TouchCounter; - - void Reset() - { - CallOfGraves_Timer = 4000; - Corruption_Timer = 8000; - FlashHeal_Timer = 38000; - Renew_Timer = 32000; - HealingTouch_Timer = 45000; - FlashCounter = 0; - TouchCounter = 0; - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_INSTRUCTORMALICIA_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //CallOfGraves_Timer - if (CallOfGraves_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CALLOFGRAVES); - CallOfGraves_Timer = 65000; - } else CallOfGraves_Timer -= diff; - - //Corruption_Timer - if (Corruption_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_CORRUPTION); - - Corruption_Timer = 24000; - } else Corruption_Timer -= diff; - - //Renew_Timer - if (Renew_Timer <= diff) - { - DoCast(me, SPELL_RENEW); - Renew_Timer = 10000; - } else Renew_Timer -= diff; - - //FlashHeal_Timer - if (FlashHeal_Timer <= diff) - { - DoCast(me, SPELL_FLASHHEAL); - - //5 Flashheals will be casted - if (FlashCounter < 2) - { - FlashHeal_Timer = 5000; - ++FlashCounter; - } - else - { - FlashCounter=0; - FlashHeal_Timer = 30000; - } - } else FlashHeal_Timer -= diff; - - //HealingTouch_Timer - if (HealingTouch_Timer <= diff) - { - DoCast(me, SPELL_HEALINGTOUCH); - - //3 Healingtouchs will be casted - if (HealingTouch_Timer < 2) - { - HealingTouch_Timer = 5500; - ++TouchCounter; - } - else - { - TouchCounter=0; - HealingTouch_Timer = 30000; - } - } else HealingTouch_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_instructormalicia(Creature* pCreature) -{ - return new boss_instructormaliciaAI (pCreature); -} - -void AddSC_boss_instructormalicia() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_instructor_malicia"; - newscript->GetAI = &GetAI_boss_instructormalicia; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp deleted file mode 100644 index f8d8520e394..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_jandice_barov.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_jandicebarov -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_CURSEOFBLOOD 24673 -//#define SPELL_ILLUSION 17773 - -//Spells of Illusion of Jandice Barov -#define SPELL_CLEAVE 15584 - -struct boss_jandicebarovAI : public ScriptedAI -{ - boss_jandicebarovAI(Creature *c) : ScriptedAI(c) {} - - uint32 CurseOfBlood_Timer; - uint32 Illusion_Timer; - //uint32 Illusioncounter; - uint32 Invisible_Timer; - bool Invisible; - - void Reset() - { - CurseOfBlood_Timer = 15000; - Illusion_Timer = 30000; - Invisible_Timer = 3000; //Too much too low? - Invisible = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonIllusions(Unit* victim) - { - if (Creature *Illusion = DoSpawnCreature(11439, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) - Illusion->AI()->AttackStart(victim); - } - - void UpdateAI(const uint32 diff) - { - if (Invisible && Invisible_Timer <= diff) - { - //Become visible again - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(11073); //Jandice Model - Invisible = false; - } else if (Invisible) - { - Invisible_Timer -= diff; - //Do nothing while invisible - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //CurseOfBlood_Timer - if (CurseOfBlood_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_CURSEOFBLOOD); - - //45 seconds - CurseOfBlood_Timer = 30000; - } else CurseOfBlood_Timer -= diff; - - //Illusion_Timer - if (!Invisible && Illusion_Timer <= diff) - { - - //Inturrupt any spell casting - me->InterruptNonMeleeSpells(false); - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(11686); // Invisible Model - DoModifyThreatPercent(me->getVictim(),-99); - - //Summon 10 Illusions attacking random gamers - Unit *pTarget = NULL; - for (uint8 i = 0; i < 10; ++i) - { - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - SummonIllusions(pTarget); - } - Invisible = true; - Invisible_Timer = 3000; - - //25 seconds until we should cast this agian - Illusion_Timer = 25000; - } else Illusion_Timer -= diff; - - // //Illusion_Timer - // if (Illusion_Timer <= diff) - // { - // //Cast - // DoCast(me->getVictim(), SPELL_ILLUSION); - // - // //3 Illusion will be summoned - // if (Illusioncounter < 3) - // { - // Illusion_Timer = 500; - // ++Illusioncounter; - // } - // else { - // //15 seconds until we should cast this again - // Illusion_Timer = 15000; - // Illusioncounter = 0; - // } - // - // } else Illusion_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -// Illusion of Jandice Barov Script - -struct mob_illusionofjandicebarovAI : public ScriptedAI -{ - mob_illusionofjandicebarovAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cleave_Timer; - - void Reset() - { - Cleave_Timer = 2000 + rand()%6000; - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_CLEAVE); - - //5-8 seconds - Cleave_Timer = 5000 + rand()%3000; - } else Cleave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_jandicebarov(Creature* pCreature) -{ - return new boss_jandicebarovAI (pCreature); -} - -CreatureAI* GetAI_mob_illusionofjandicebarov(Creature* pCreature) -{ - return new mob_illusionofjandicebarovAI (pCreature); -} - -void AddSC_boss_jandicebarov() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_jandice_barov"; - newscript->GetAI = &GetAI_boss_jandicebarov; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_illusionofjandicebarov"; - newscript->GetAI = &GetAI_mob_illusionofjandicebarov; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp deleted file mode 100644 index c4ae5cc490e..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_kormok.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kormok -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SHADOWBOLTVOLLEY 20741 -#define SPELL_BONESHIELD 27688 - -struct boss_kormokAI : public ScriptedAI -{ - boss_kormokAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowVolley_Timer; - uint32 BoneShield_Timer; - uint32 Minion_Timer; - uint32 Mage_Timer; - bool Mages; - - void Reset() - { - ShadowVolley_Timer = 10000; - BoneShield_Timer = 2000; - Minion_Timer = 15000; - Mage_Timer = 0; - Mages = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonMinions(Unit* victim) - { - if (Creature *SummonedMinion = DoSpawnCreature(16119, irand(-7,7), irand(-7,7), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedMinion->AI()->AttackStart(victim); - } - - void SummonMages(Unit* victim) - { - if (Creature *SummonedMage = DoSpawnCreature(16120, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedMage->AI()->AttackStart(victim); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowVolley_Timer - if (ShadowVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLTVOLLEY); - ShadowVolley_Timer = 15000; - } else ShadowVolley_Timer -= diff; - - //BoneShield_Timer - if (BoneShield_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BONESHIELD); - BoneShield_Timer = 45000; - } else BoneShield_Timer -= diff; - - //Minion_Timer - if (Minion_Timer <= diff) - { - //Cast - SummonMinions(me->getVictim()); - SummonMinions(me->getVictim()); - SummonMinions(me->getVictim()); - SummonMinions(me->getVictim()); - - Minion_Timer = 12000; - } else Minion_Timer -= diff; - - //Summon 2 Bone Mages - if (!Mages && me->GetHealth()*100 / me->GetMaxHealth() < 26) - { - //Cast - SummonMages(me->getVictim()); - SummonMages(me->getVictim()); - Mages = true; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_kormok(Creature* pCreature) -{ - return new boss_kormokAI (pCreature); -} - -void AddSC_boss_kormok() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kormok"; - newscript->GetAI = &GetAI_boss_kormok; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp deleted file mode 100644 index 0956a04d824..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_lord_alexei_barov.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Lord_Alexei_Barov -SD%Complete: 100 -SDComment: aura applied/defined in database -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_IMMOLATE 20294 // Old ID was 15570 -#define SPELL_VEILOFSHADOW 17820 - -struct boss_lordalexeibarovAI : public ScriptedAI -{ - boss_lordalexeibarovAI(Creature *c) : ScriptedAI(c) {} - - uint32 Immolate_Timer; - uint32 VeilofShadow_Timer; - - void Reset() - { - Immolate_Timer = 7000; - VeilofShadow_Timer = 15000; - - me->LoadCreaturesAddon(); - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_LORDALEXEIBAROV_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Immolate_Timer - if (Immolate_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_IMMOLATE); - - Immolate_Timer = 12000; - } else Immolate_Timer -= diff; - - //VeilofShadow_Timer - if (VeilofShadow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VEILOFSHADOW); - VeilofShadow_Timer = 20000; - } else VeilofShadow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_lordalexeibarov(Creature* pCreature) -{ - return new boss_lordalexeibarovAI (pCreature); -} - -void AddSC_boss_lordalexeibarov() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lord_alexei_barov"; - newscript->GetAI = &GetAI_boss_lordalexeibarov; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp deleted file mode 100644 index d3b75900202..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_lorekeeper_polkelt.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Lorekeeper_Polkelt -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_VOLATILEINFECTION 24928 -#define SPELL_DARKPLAGUE 18270 -#define SPELL_CORROSIVEACID 23313 -#define SPELL_NOXIOUSCATALYST 18151 - -struct boss_lorekeeperpolkeltAI : public ScriptedAI -{ - boss_lorekeeperpolkeltAI(Creature *c) : ScriptedAI(c) {} - - uint32 VolatileInfection_Timer; - uint32 Darkplague_Timer; - uint32 CorrosiveAcid_Timer; - uint32 NoxiousCatalyst_Timer; - - void Reset() - { - VolatileInfection_Timer = 38000; - Darkplague_Timer = 8000; - CorrosiveAcid_Timer = 45000; - NoxiousCatalyst_Timer = 35000; - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_LOREKEEPERPOLKELT_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //VolatileInfection_Timer - if (VolatileInfection_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VOLATILEINFECTION); - VolatileInfection_Timer = 32000; - } else VolatileInfection_Timer -= diff; - - //Darkplague_Timer - if (Darkplague_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DARKPLAGUE); - Darkplague_Timer = 8000; - } else Darkplague_Timer -= diff; - - //CorrosiveAcid_Timer - if (CorrosiveAcid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVEACID); - CorrosiveAcid_Timer = 25000; - } else CorrosiveAcid_Timer -= diff; - - //NoxiousCatalyst_Timer - if (NoxiousCatalyst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSCATALYST); - NoxiousCatalyst_Timer = 38000; - } else NoxiousCatalyst_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_lorekeeperpolkelt(Creature* pCreature) -{ - return new boss_lorekeeperpolkeltAI (pCreature); -} - -void AddSC_boss_lorekeeperpolkelt() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lorekeeper_polkelt"; - newscript->GetAI = &GetAI_boss_lorekeeperpolkelt; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp deleted file mode 100644 index 63837e04ad5..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_ras_frostwhisper.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ras_Frostwhisper -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FROSTBOLT 21369 -#define SPELL_ICEARMOR 18100 //This is actually a buff he gives himself -#define SPELL_FREEZE 18763 -#define SPELL_FEAR 26070 -#define SPELL_CHILLNOVA 18099 -#define SPELL_FROSTVOLLEY 8398 - -struct boss_rasfrostAI : public ScriptedAI -{ - boss_rasfrostAI(Creature *c) : ScriptedAI(c) {} - - uint32 IceArmor_Timer; - uint32 Frostbolt_Timer; - uint32 Freeze_Timer; - uint32 Fear_Timer; - uint32 ChillNova_Timer; - uint32 FrostVolley_Timer; - - void Reset() - { - IceArmor_Timer = 2000; - Frostbolt_Timer = 8000; - ChillNova_Timer = 12000; - Freeze_Timer = 18000; - FrostVolley_Timer = 24000; - Fear_Timer = 45000; - - DoCast(me, SPELL_ICEARMOR, true); - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //IceArmor_Timer - if (IceArmor_Timer <= diff) - { - DoCast(me, SPELL_ICEARMOR); - IceArmor_Timer = 180000; - } else IceArmor_Timer -= diff; - - //Frostbolt_Timer - if (Frostbolt_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_FROSTBOLT); - - Frostbolt_Timer = 8000; - } else Frostbolt_Timer -= diff; - - //Freeze_Timer - if (Freeze_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FREEZE); - Freeze_Timer = 24000; - } else Freeze_Timer -= diff; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - Fear_Timer = 30000; - } else Fear_Timer -= diff; - - //ChillNova_Timer - if (ChillNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CHILLNOVA); - ChillNova_Timer = 14000; - } else ChillNova_Timer -= diff; - - //FrostVolley_Timer - if (FrostVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTVOLLEY); - FrostVolley_Timer = 15000; - } else FrostVolley_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_rasfrost(Creature* pCreature) -{ - return new boss_rasfrostAI (pCreature); -} - -void AddSC_boss_rasfrost() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_boss_ras_frostwhisper"; - newscript->GetAI = &GetAI_boss_rasfrost; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp deleted file mode 100644 index 6340f2b0e2d..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_the_ravenian.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_the_ravenian -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define SPELL_TRAMPLE 15550 -#define SPELL_CLEAVE 20691 -#define SPELL_SUNDERINCLEAVE 25174 -#define SPELL_KNOCKAWAY 10101 - -struct boss_theravenianAI : public ScriptedAI -{ - boss_theravenianAI(Creature *c) : ScriptedAI(c) {} - - uint32 Trample_Timer; - uint32 Cleave_Timer; - uint32 SunderingCleave_Timer; - uint32 KnockAway_Timer; - bool HasYelled; - - void Reset() - { - Trample_Timer = 24000; - Cleave_Timer = 15000; - SunderingCleave_Timer = 40000; - KnockAway_Timer = 32000; - HasYelled = false; - } - - void JustDied(Unit * /*killer*/) - { - ScriptedInstance *pInstance = me->GetInstanceData(); - if (pInstance) - { - pInstance->SetData(DATA_THERAVENIAN_DEATH, 0); - - if (pInstance->GetData(TYPE_GANDLING) == IN_PROGRESS) - me->SummonCreature(1853, 180.73, -9.43856, 75.507, 1.61399, TEMPSUMMON_DEAD_DESPAWN, 0); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Trample_Timer - if (Trample_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TRAMPLE); - Trample_Timer = 10000; - } else Trample_Timer -= diff; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //SunderingCleave_Timer - if (SunderingCleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDERINCLEAVE); - SunderingCleave_Timer = 20000; - } else SunderingCleave_Timer -= diff; - - //KnockAway_Timer - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - KnockAway_Timer = 12000; - } else KnockAway_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_theravenian(Creature* pCreature) -{ - return new boss_theravenianAI (pCreature); -} - -void AddSC_boss_theravenian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_ravenian"; - newscript->GetAI = &GetAI_boss_theravenian; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp b/src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp deleted file mode 100644 index a38369faab0..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/boss_vectus.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Vectus -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - EMOTE_GENERIC_FRENZY_KILL = -1000001, - - SPELL_FLAMESTRIKE = 18399, - SPELL_BLAST_WAVE = 16046, - SPELL_FIRESHIELD = 19626, - SPELL_FRENZY = 8269 //28371, -}; - -struct boss_vectusAI : public ScriptedAI -{ - boss_vectusAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiFireShield_Timer; - uint32 m_uiBlastWave_Timer; - uint32 m_uiFrenzy_Timer; - - void Reset() - { - m_uiFireShield_Timer = 2000; - m_uiBlastWave_Timer = 14000; - m_uiFrenzy_Timer = 0; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //FireShield_Timer - if (m_uiFireShield_Timer <= uiDiff) - { - DoCast(me, SPELL_FIRESHIELD); - m_uiFireShield_Timer = 90000; - } - else - m_uiFireShield_Timer -= uiDiff; - - //BlastWave_Timer - if (m_uiBlastWave_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BLAST_WAVE); - m_uiBlastWave_Timer = 12000; - } - else - m_uiBlastWave_Timer -= uiDiff; - - //Frenzy_Timer - if (me->GetHealth()*100 / me->GetMaxHealth() < 25) - { - if (m_uiFrenzy_Timer <= uiDiff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); - - m_uiFrenzy_Timer = 24000; - } - else - m_uiFrenzy_Timer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vectus(Creature* pCreature) -{ - return new boss_vectusAI (pCreature); -} - -void AddSC_boss_vectus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vectus"; - newscript->GetAI = &GetAI_boss_vectus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp b/src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp deleted file mode 100644 index 992849cff1b..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/instance_scholomance.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Scholomance -SD%Complete: 100 -SDComment: -SDCategory: Scholomance -EndScriptData */ - -#include "ScriptedPch.h" -#include "scholomance.h" - -#define GO_GATE_KIRTONOS 175570 -#define GO_GATE_GANDLING 177374 -#define GO_GATE_MALICIA 177375 -#define GO_GATE_THEOLEN 177377 -#define GO_GATE_POLKELT 177376 -#define GO_GATE_RAVENIAN 177372 -#define GO_GATE_BAROV 177373 -#define GO_GATE_ILLUCIA 177371 - -#define MAX_ENCOUNTER 2 - -struct instance_scholomance : public ScriptedInstance -{ - instance_scholomance(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - //Lord Alexei Barov, Doctor Theolen Krastinov, The Ravenian, Lorekeeper Polkelt, Instructor Malicia and the Lady Illucia Barov. - bool IsBossDied[6]; - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 GateKirtonosGUID; - uint64 GateGandlingGUID; - uint64 GateMiliciaGUID; - uint64 GateTheolenGUID; - uint64 GatePolkeltGUID; - uint64 GateRavenianGUID; - uint64 GateBarovGUID; - uint64 GateIlluciaGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - GateKirtonosGUID = 0; - GateGandlingGUID = 0; - GateMiliciaGUID = 0; - GateTheolenGUID = 0; - GatePolkeltGUID = 0; - GateRavenianGUID = 0; - GateBarovGUID = 0; - GateIlluciaGUID = 0; - - for (uint8 i = 0; i < 6; ++i) - IsBossDied[i] = false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_GATE_KIRTONOS: GateKirtonosGUID = pGo->GetGUID(); break; - case GO_GATE_GANDLING: GateGandlingGUID = pGo->GetGUID(); break; - case GO_GATE_MALICIA: GateMiliciaGUID = pGo->GetGUID(); break; - case GO_GATE_THEOLEN: GateTheolenGUID = pGo->GetGUID(); break; - case GO_GATE_POLKELT: GatePolkeltGUID = pGo->GetGUID(); break; - case GO_GATE_RAVENIAN: GateRavenianGUID = pGo->GetGUID(); break; - case GO_GATE_BAROV: GateBarovGUID = pGo->GetGUID(); break; - case GO_GATE_ILLUCIA: GateIlluciaGUID = pGo->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_LORDALEXEIBAROV_DEATH: - IsBossDied[0] = true; - break; - case DATA_DOCTORTHEOLENKRASTINOV_DEATH: - IsBossDied[1] = true; - break; - case DATA_THERAVENIAN_DEATH: - IsBossDied[2] = true; - break; - case DATA_LOREKEEPERPOLKELT_DEATH: - IsBossDied[3] = true; - break; - case DATA_INSTRUCTORMALICIA_DEATH: - IsBossDied[4] = true; - break; - case DATA_LADYILLUCIABAROV_DEATH: - IsBossDied[5] = true; - break; - case TYPE_GANDLING: - m_auiEncounter[0] = data; - break; - case TYPE_KIRTONOS: - m_auiEncounter[1] = data; - break; - } - } - - uint32 GetData(uint32 type) - { - if (type == TYPE_GANDLING) - { - if (IsBossDied[0] && IsBossDied[1] && IsBossDied[2] && IsBossDied[3] && IsBossDied[4] && IsBossDied[5]) - { - m_auiEncounter[0] = IN_PROGRESS; - return IN_PROGRESS; - } - } - - return 0; - } -}; - -InstanceData* GetInstanceData_instance_scholomance(Map* pMap) -{ - return new instance_scholomance(pMap); -} - -void AddSC_instance_scholomance() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_scholomance"; - newscript->GetInstanceData = &GetInstanceData_instance_scholomance; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/scholomance/scholomance.h b/src/server/scripts/EasternKingdoms/scholomance/scholomance.h deleted file mode 100644 index 83ce26c9687..00000000000 --- a/src/server/scripts/EasternKingdoms/scholomance/scholomance.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SCHOLOMANCE_H -#define DEF_SCHOLOMANCE_H - -#define TYPE_GANDLING 1 -#define DATA_DOCTORTHEOLENKRASTINOV_DEATH 2 -#define DATA_INSTRUCTORMALICIA_DEATH 3 -#define DATA_LADYILLUCIABAROV_DEATH 4 -#define DATA_LORDALEXEIBAROV_DEATH 5 -#define DATA_LOREKEEPERPOLKELT_DEATH 6 -#define DATA_THERAVENIAN_DEATH 7 -#define TYPE_KIRTONOS 8 -#endif - diff --git a/src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp deleted file mode 100644 index 20959641889..00000000000 --- a/src/server/scripts/EasternKingdoms/shadowfang_keep/instance_shadowfang_keep.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Shadowfang_Keep -SD%Complete: 90 -SDComment: -SDCategory: Shadowfang Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadowfang_keep.h" - -#define MAX_ENCOUNTER 4 - -enum eEnums -{ - SAY_BOSS_DIE_AD = -1033007, - SAY_BOSS_DIE_AS = -1033008, - SAY_ARCHMAGE = -1033009, - - NPC_ASH = 3850, - NPC_ADA = 3849, - NPC_ARCHMAGE_ARUGAL = 4275, - NPC_ARUGAL_VOIDWALKER = 4627, - - GO_COURTYARD_DOOR = 18895, //door to open when talking to NPC's - GO_SORCERER_DOOR = 18972, //door to open when Fenrus the Devourer - GO_ARUGAL_DOOR = 18971, //door to open when Wolf Master Nandos - - SPELL_ASHCROMBE_TELEPORT = 15742 -}; - -const Position SpawnLocation[] = -{ - {-148.199,2165.647,128.448,1.026}, - {-153.110,2168.620,128.448,1.026}, - {-145.905,2180.520,128.448,4.183}, - {-140.794,2178.037,128.448,4.090}, - {-138.640,2170.159,136.577,2.737} -}; -struct instance_shadowfang_keep : public ScriptedInstance -{ - instance_shadowfang_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 uiAshGUID; - uint64 uiAdaGUID; - uint64 uiArchmageArugalGUID; - - uint64 DoorCourtyardGUID; - uint64 DoorSorcererGUID; - uint64 DoorArugalGUID; - - uint8 uiPhase; - uint16 uiTimer; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - uiAshGUID = 0; - uiAdaGUID = 0; - uiArchmageArugalGUID = 0; - - DoorCourtyardGUID = 0; - DoorSorcererGUID = 0; - DoorArugalGUID = 0; - - uiPhase = 0; - uiTimer = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_ASH: uiAshGUID = pCreature->GetGUID(); break; - case NPC_ADA: uiAdaGUID = pCreature->GetGUID(); break; - case NPC_ARCHMAGE_ARUGAL: uiArchmageArugalGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_COURTYARD_DOOR: - DoorCourtyardGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - HandleGameObject(NULL, true, pGo); - break; - case GO_SORCERER_DOOR: - DoorSorcererGUID = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - HandleGameObject(NULL, true, pGo); - break; - case GO_ARUGAL_DOOR: - DoorArugalGUID = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(NULL, true, pGo); - break; - } - } - - void DoSpeech() - { - Creature* pAda = instance->GetCreature(uiAdaGUID); - Creature* pAsh = instance->GetCreature(uiAshGUID); - - if (pAda && pAda->isAlive() && pAsh && pAsh->isAlive()) - { - DoScriptText(SAY_BOSS_DIE_AD,pAda); - DoScriptText(SAY_BOSS_DIE_AS,pAsh); - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_FREE_NPC: - if (data == DONE) - DoUseDoorOrButton(DoorCourtyardGUID); - m_auiEncounter[0] = data; - break; - case TYPE_RETHILGORE: - if (data == DONE) - DoSpeech(); - m_auiEncounter[1] = data; - break; - case TYPE_FENRUS: - switch(data) - { - case DONE: - uiTimer = 1000; - uiPhase = 1; - break; - case 7: - DoUseDoorOrButton(DoorSorcererGUID); - break; - } - m_auiEncounter[2] = data; - break; - case TYPE_NANDOS: - if (data == DONE) - DoUseDoorOrButton(DoorArugalGUID); - m_auiEncounter[3] = data; - break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_FREE_NPC: - return m_auiEncounter[0]; - case TYPE_RETHILGORE: - return m_auiEncounter[1]; - case TYPE_FENRUS: - return m_auiEncounter[2]; - case TYPE_NANDOS: - return m_auiEncounter[3]; - } - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void Update(uint32 uiDiff) - { - if (GetData(TYPE_FENRUS) != DONE) - return; - - Creature* pArchmage = instance->GetCreature(uiArchmageArugalGUID); - Creature* pSummon = NULL; - - if (!pArchmage || !pArchmage->isAlive()) - return; - - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - pSummon = pArchmage->SummonCreature(pArchmage->GetEntry(),SpawnLocation[4],TEMPSUMMON_TIMED_DESPAWN,10000); - pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - pSummon->SetReactState(REACT_DEFENSIVE); - pSummon->CastSpell(pSummon,SPELL_ASHCROMBE_TELEPORT,true); - DoScriptText(SAY_ARCHMAGE,pSummon); - uiTimer = 2000; - uiPhase = 2; - break; - case 2: - pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[0],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[1],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[2],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - pArchmage->SummonCreature(NPC_ARUGAL_VOIDWALKER,SpawnLocation[3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,60000); - uiPhase = 0; - break; - - } - } else uiTimer -= uiDiff; - } - } -}; - -InstanceData* GetInstanceData_instance_shadowfang_keep(Map* pMap) -{ - return new instance_shadowfang_keep(pMap); -} - -void AddSC_instance_shadowfang_keep() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_shadowfang_keep"; - newscript->GetInstanceData = &GetInstanceData_instance_shadowfang_keep; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp deleted file mode 100644 index 23b8ad89160..00000000000 --- a/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.cpp +++ /dev/null @@ -1,198 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Shadowfang_Keep -SD%Complete: 75 -SDComment: npc_shadowfang_prisoner using escortAI for movement to door. Might need additional code in case being attacked. Add proper texts/say(). -SDCategory: Shadowfang Keep -EndScriptData */ - -/* ContentData -npc_shadowfang_prisoner -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "shadowfang_keep.h" - -/*###### -## npc_shadowfang_prisoner -######*/ - -enum eEnums -{ - SAY_FREE_AS = -1033000, - SAY_OPEN_DOOR_AS = -1033001, - SAY_POST_DOOR_AS = -1033002, - SAY_FREE_AD = -1033003, - SAY_OPEN_DOOR_AD = -1033004, - SAY_POST1_DOOR_AD = -1033005, - SAY_POST2_DOOR_AD = -1033006, - - SPELL_UNLOCK = 6421, - NPC_ASH = 3850, - - SPELL_DARK_OFFERING = 7154 -}; - -#define GOSSIP_ITEM_DOOR "Thanks, I'll follow you to the door." - -struct npc_shadowfang_prisonerAI : public npc_escortAI -{ - npc_shadowfang_prisonerAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - uiNpcEntry = c->GetEntry(); - } - - ScriptedInstance *pInstance; - uint32 uiNpcEntry; - - void WaypointReached(uint32 uiPoint) - { - switch(uiPoint) - { - case 0: - if (uiNpcEntry == NPC_ASH) - DoScriptText(SAY_FREE_AS, me); - else - DoScriptText(SAY_FREE_AD, me); - break; - case 10: - if (uiNpcEntry == NPC_ASH) - DoScriptText(SAY_OPEN_DOOR_AS, me); - else - DoScriptText(SAY_OPEN_DOOR_AD, me); - break; - case 11: - if (uiNpcEntry == NPC_ASH) - DoCast(me, SPELL_UNLOCK); - break; - case 12: - if (uiNpcEntry == NPC_ASH) - DoScriptText(SAY_POST_DOOR_AS, me); - else - DoScriptText(SAY_POST1_DOOR_AD, me); - - if (pInstance) - pInstance->SetData(TYPE_FREE_NPC, DONE); - break; - case 13: - if (uiNpcEntry != NPC_ASH) - DoScriptText(SAY_POST2_DOOR_AD, me); - break; - } - } - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} -}; - -CreatureAI* GetAI_npc_shadowfang_prisoner(Creature* pCreature) -{ - return new npc_shadowfang_prisonerAI(pCreature); -} - -bool GossipHello_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && pInstance->GetData(TYPE_FREE_NPC) != DONE && pInstance->GetData(TYPE_RETHILGORE) == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DOOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_shadowfang_prisonerAI, pCreature->AI())) - pEscortAI->Start(false, false); - } - return true; -} - -struct npc_arugal_voidwalkerAI : public ScriptedAI -{ - npc_arugal_voidwalkerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiDarkOffering; - - void Reset() - { - uiDarkOffering = urand(290,10); - } - - void UpdateAI(uint32 const uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiDarkOffering <= uiDiff) - { - if (Creature* pFriend = me->FindNearestCreature(me->GetEntry(),25.0f,true)) - { - if (pFriend) - DoCast(pFriend,SPELL_DARK_OFFERING); - } - else - DoCast(me,SPELL_DARK_OFFERING); - uiDarkOffering = urand(4400,12500); - } else uiDarkOffering -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(TYPE_FENRUS, pInstance->GetData(TYPE_FENRUS) + 1); - } -}; - -CreatureAI* GetAI_npc_arugal_voidwalker(Creature* pCreature) -{ - return new npc_arugal_voidwalkerAI(pCreature); -} - -void AddSC_shadowfang_keep() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_shadowfang_prisoner"; - newscript->pGossipHello = &GossipHello_npc_shadowfang_prisoner; - newscript->pGossipSelect = &GossipSelect_npc_shadowfang_prisoner; - newscript->GetAI = &GetAI_npc_shadowfang_prisoner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_arugal_voidwalker"; - newscript->GetAI = &GetAI_npc_arugal_voidwalker; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h b/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h deleted file mode 100644 index a1a59789632..00000000000 --- a/src/server/scripts/EasternKingdoms/shadowfang_keep/shadowfang_keep.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SHADOWFANG_H -#define DEF_SHADOWFANG_H - -enum eData -{ - TYPE_FREE_NPC = 1, - TYPE_RETHILGORE = 2, - TYPE_FENRUS = 3, - TYPE_NANDOS = 4 -}; - -#endif - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp deleted file mode 100644 index de17717e289..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_baron_rivendare.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Baron_Rivendare -SD%Complete: 70 -SDComment: aura applied/defined in database -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SAY_0 "Intruders! More pawns of the Argent Dawn, no doubt. I already count one of their number among my prisoners. Withdraw from my domain before she is executed!" -#define SAY_1 "You're still here? Your foolishness is amusing! The Argent Dawn wench needn't suffer in vain. Leave at once and she shall be spared!" -#define SAY_2 "I shall take great pleasure in taking this poor wretch's life! It's not too late, she needn't suffer in vain. Turn back and her death shall be merciful!" -#define SAY_3 "May this prisoner's death serve as a warning. None shall defy the Scourge and live!" -#define SAY_4 "So you see fit to toy with the Lich King's creations? Ramstein, be sure to give the intruders a proper greeting." -#define SAY_5 "Time to take matters into my own hands. Come. Enter my domain and challenge the might of the Scourge!" - -#define ADD_1X 4017.403809 -#define ADD_1Y -3339.703369 -#define ADD_1Z 115.057655 -#define ADD_1O 5.487860 - -#define ADD_2X 4013.189209 -#define ADD_2Y -3351.808350 -#define ADD_2Z 115.052254 -#define ADD_2O 0.134280 - -#define ADD_3X 4017.738037 -#define ADD_3Y -3363.478016 -#define ADD_3Z 115.057274 -#define ADD_3O 0.723313 - -#define ADD_4X 4048.877197 -#define ADD_4Y -3363.223633 -#define ADD_4Z 115.054253 -#define ADD_4O 3.627735 - -#define ADD_5X 4051.777588 -#define ADD_5Y -3350.893311 -#define ADD_5Z 115.055351 -#define ADD_5O 3.066176 - -#define ADD_6X 4048.375977 -#define ADD_6Y -3339.966309 -#define ADD_6Z 115.055222 -#define ADD_6O 2.457497 - -#define SPELL_SHADOWBOLT 17393 -#define SPELL_CLEAVE 15284 -#define SPELL_MORTALSTRIKE 15708 - -#define SPELL_UNHOLY_AURA 17467 -#define SPELL_RAISEDEAD 17473 //triggers death pact (17471) - -#define SPELL_RAISE_DEAD1 17475 -#define SPELL_RAISE_DEAD2 17476 -#define SPELL_RAISE_DEAD3 17477 -#define SPELL_RAISE_DEAD4 17478 -#define SPELL_RAISE_DEAD5 17479 -#define SPELL_RAISE_DEAD6 17480 - -struct boss_baron_rivendareAI : public ScriptedAI -{ - boss_baron_rivendareAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ShadowBolt_Timer; - uint32 Cleave_Timer; - uint32 MortalStrike_Timer; - // uint32 RaiseDead_Timer; - uint32 SummonSkeletons_Timer; - - void Reset() - { - ShadowBolt_Timer = 5000; - Cleave_Timer = 8000; - MortalStrike_Timer = 12000; - // RaiseDead_Timer = 30000; - SummonSkeletons_Timer = 34000; - if (pInstance && pInstance->GetData(TYPE_RAMSTEIN) == DONE) - pInstance->SetData(TYPE_BARON,NOT_STARTED); - } - - void AttackStart(Unit* who) - { - if (pInstance)//can't use entercombat(), boss' dmg aura sets near players in combat, before entering the room's door - pInstance->SetData(TYPE_BARON,IN_PROGRESS); - ScriptedAI::AttackStart(who); - } - - void JustSummoned(Creature* summoned) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(pTarget); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_BARON,DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ShadowBolt - if (ShadowBolt_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(me->getVictim(), SPELL_SHADOWBOLT); - - ShadowBolt_Timer = 10000; - } else ShadowBolt_Timer -= diff; - - //Cleave - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - //13 seconds until we should cast this again - Cleave_Timer = 7000 + (rand()%10000); - } else Cleave_Timer -= diff; - - //MortalStrike - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALSTRIKE); - MortalStrike_Timer = 10000 + (rand()%15000); - } else MortalStrike_Timer -= diff; - - //RaiseDead - // if (RaiseDead_Timer <= diff) - // { - // DoCast(me, SPELL_RAISEDEAD); - // RaiseDead_Timer = 45000; - // } else RaiseDead_Timer -= diff; - - //SummonSkeletons - if (SummonSkeletons_Timer <= diff) - { - me->SummonCreature(11197,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,29000); - me->SummonCreature(11197,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,29000); - - //34 seconds until we should cast this again - SummonSkeletons_Timer = 40000; - } else SummonSkeletons_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_baron_rivendare(Creature* pCreature) -{ - return new boss_baron_rivendareAI (pCreature); -} - -void AddSC_boss_baron_rivendare() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_baron_rivendare"; - newscript->GetAI = &GetAI_boss_baron_rivendare; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp deleted file mode 100644 index cff4fe3fbae..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_baroness_anastari.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Baroness_Anastari -SD%Complete: 90 -SDComment: MC disabled -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_BANSHEEWAIL 16565 -#define SPELL_BANSHEECURSE 16867 -#define SPELL_SILENCE 18327 -//#define SPELL_POSSESS 17244 - -struct boss_baroness_anastariAI : public ScriptedAI -{ - boss_baroness_anastariAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 BansheeWail_Timer; - uint32 BansheeCurse_Timer; - uint32 Silence_Timer; - //uint32 Possess_Timer; - - void Reset() - { - BansheeWail_Timer = 1000; - BansheeCurse_Timer = 11000; - Silence_Timer = 13000; - //Possess_Timer = 35000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_BARONESS,IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //BansheeWail - if (BansheeWail_Timer <= diff) - { - if (rand()%100 < 95) - DoCast(me->getVictim(), SPELL_BANSHEEWAIL); - //4 seconds until we should cast this again - BansheeWail_Timer = 4000; - } else BansheeWail_Timer -= diff; - - //BansheeCurse - if (BansheeCurse_Timer <= diff) - { - if (rand()%100 < 75) - DoCast(me->getVictim(), SPELL_BANSHEECURSE); - //18 seconds until we should cast this again - BansheeCurse_Timer = 18000; - } else BansheeCurse_Timer -= diff; - - //Silence - if (Silence_Timer <= diff) - { - if (rand()%100 < 80) - DoCast(me->getVictim(), SPELL_SILENCE); - //13 seconds until we should cast this again - Silence_Timer = 13000; - } else Silence_Timer -= diff; - - //Possess - /* if (Possess_Timer <= diff) - { - //Cast - if (rand()%100 < 65) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget)DoCast(pTarget, SPELL_POSSESS); - } - //50 seconds until we should cast this again - Possess_Timer = 50000; - } else Possess_Timer -= diff; - */ - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_baroness_anastari(Creature* pCreature) -{ - return new boss_baroness_anastariAI (pCreature); -} - -void AddSC_boss_baroness_anastari() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_baroness_anastari"; - newscript->GetAI = &GetAI_boss_baroness_anastari; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp deleted file mode 100644 index c12f7b9ad04..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_cannon_master_willey.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_cannon_master_willey -SD%Complete: 100 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" - -//front, left -#define ADD_1X 3553.851807 -#define ADD_1Y -2945.885986 -#define ADD_1Z 125.001015 -#define ADD_1O 0.592007 -//front, right -#define ADD_2X 3559.206299 -#define ADD_2Y -2952.929932 -#define ADD_2Z 125.001015 -#define ADD_2O 0.592007 -//mid, left -#define ADD_3X 3552.417480 -#define ADD_3Y -2948.667236 -#define ADD_3Z 125.001015 -#define ADD_3O 0.592007 -//mid, right -#define ADD_4X 3555.651855 -#define ADD_4Y -2953.519043 -#define ADD_4Z 125.001015 -#define ADD_4O 0.592007 -//back, left -#define ADD_5X 3547.927246 -#define ADD_5Y -2950.977295 -#define ADD_5Z 125.001015 -#define ADD_5O 0.592007 -//back, mid -#define ADD_6X 3553.094697 -#define ADD_6Y -2952.123291 -#define ADD_6Z 125.001015 -#define ADD_6O 0.592007 -//back, right -#define ADD_7X 3552.727539 -#define ADD_7Y -2957.776123 -#define ADD_7Z 125.001015 -#define ADD_7O 0.592007 -//behind, left -#define ADD_8X 3547.156250 -#define ADD_8Y -2953.162354 -#define ADD_8Z 125.001015 -#define ADD_8O 0.592007 -//behind, right -#define ADD_9X 3550.202148 -#define ADD_9Y -2957.437744 -#define ADD_9Z 125.001015 -#define ADD_9O 0.592007 - -#define SPELL_KNOCKAWAY 10101 -#define SPELL_PUMMEL 15615 -#define SPELL_SHOOT 16496 -//#define SPELL_SUMMONCRIMSONRIFLEMAN 17279 - -struct boss_cannon_master_willeyAI : public ScriptedAI -{ - boss_cannon_master_willeyAI(Creature *c) : ScriptedAI(c) {} - - uint32 KnockAway_Timer; - uint32 Pummel_Timer; - uint32 Shoot_Timer; - uint32 SummonRifleman_Timer; - - void Reset() - { - Shoot_Timer = 1000; - Pummel_Timer = 7000; - KnockAway_Timer = 11000; - SummonRifleman_Timer = 15000; - } - - void JustDied(Unit* /*Victim*/) - { - me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Pummel - if (Pummel_Timer <= diff) - { - //Cast - if (rand()%100 < 90) //90% chance to cast - { - DoCast(me->getVictim(), SPELL_PUMMEL); - } - //12 seconds until we should cast this again - Pummel_Timer = 12000; - } else Pummel_Timer -= diff; - - //KnockAway - if (KnockAway_Timer <= diff) - { - //Cast - if (rand()%100 < 80) //80% chance to cast - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - } - //14 seconds until we should cast this again - KnockAway_Timer = 14000; - } else KnockAway_Timer -= diff; - - //Shoot - if (Shoot_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_SHOOT); - //1 seconds until we should cast this again - Shoot_Timer = 1000; - } else Shoot_Timer -= diff; - - //SummonRifleman - if (SummonRifleman_Timer <= diff) - { - //Cast - switch (rand()%9) - { - case 0: - me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 1: - me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 2: - me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 3: - me->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 4: - me->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 5: - me->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 6: - me->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 7: - me->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - case 8: - me->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000); - me->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000); - break; - } - //30 seconds until we should cast this again - SummonRifleman_Timer = 30000; - } else SummonRifleman_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_cannon_master_willey(Creature* pCreature) -{ - return new boss_cannon_master_willeyAI (pCreature); -} - -void AddSC_boss_cannon_master_willey() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_cannon_master_willey"; - newscript->GetAI = &GetAI_boss_cannon_master_willey; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp deleted file mode 100644 index a8489a7f549..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_dathrohan_balnazzar.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Dathrohan_Balnazzar -SD%Complete: 95 -SDComment: Possibly need to fix/improve summons after death -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" - -enum eEnums -{ - //Dathrohan spells - SPELL_CRUSADERSHAMMER = 17286, //AOE stun - SPELL_CRUSADERSTRIKE = 17281, - SPELL_HOLYSTRIKE = 17284, //weapon dmg +3 - - //Transform - SPELL_BALNAZZARTRANSFORM = 17288, //restore full HP/mana, trigger spell Balnazzar Transform Stun - - //Balnazzar spells - SPELL_SHADOWSHOCK = 17399, - SPELL_MINDBLAST = 17287, - SPELL_PSYCHICSCREAM = 13704, - SPELL_SLEEP = 12098, - SPELL_MINDCONTROL = 15690, - - NPC_DATHROHAN = 10812, - NPC_BALNAZZAR = 10813, - NPC_ZOMBIE = 10698 //probably incorrect -}; - -struct SummonDef -{ - float m_fX, m_fY, m_fZ, m_fOrient; -}; - -SummonDef m_aSummonPoint[]= -{ - {3444.156, -3090.626, 135.002, 2.240}, //G1 front, left - {3449.123, -3087.009, 135.002, 2.240}, //G1 front, right - {3446.246, -3093.466, 135.002, 2.240}, //G1 back left - {3451.160, -3089.904, 135.002, 2.240}, //G1 back, right - - {3457.995, -3080.916, 135.002, 3.784}, //G2 front, left - {3454.302, -3076.330, 135.002, 3.784}, //G2 front, right - {3460.975, -3078.901, 135.002, 3.784}, //G2 back left - {3457.338, -3073.979, 135.002, 3.784} //G2 back, right -}; - -struct boss_dathrohan_balnazzarAI : public ScriptedAI -{ - boss_dathrohan_balnazzarAI(Creature *c) : ScriptedAI(c) {} - - uint32 m_uiCrusadersHammer_Timer; - uint32 m_uiCrusaderStrike_Timer; - uint32 m_uiMindBlast_Timer; - uint32 m_uiHolyStrike_Timer; - uint32 m_uiShadowShock_Timer; - uint32 m_uiPsychicScream_Timer; - uint32 m_uiDeepSleep_Timer; - uint32 m_uiMindControl_Timer; - bool m_bTransformed; - - void Reset() - { - m_uiCrusadersHammer_Timer = 8000; - m_uiCrusaderStrike_Timer = 12000; - m_uiMindBlast_Timer = 6000; - m_uiHolyStrike_Timer = 18000; - m_uiShadowShock_Timer = 4000; - m_uiPsychicScream_Timer = 16000; - m_uiDeepSleep_Timer = 20000; - m_uiMindControl_Timer = 10000; - m_bTransformed = false; - - if (me->GetEntry() == NPC_BALNAZZAR) - me->UpdateEntry(NPC_DATHROHAN); - } - - void JustDied(Unit* /*Victim*/) - { - static uint32 uiCount = sizeof(m_aSummonPoint)/sizeof(SummonDef); - - for (uint8 i=0; iSummonCreature(NPC_ZOMBIE, - m_aSummonPoint[i].m_fX, m_aSummonPoint[i].m_fY, m_aSummonPoint[i].m_fZ, m_aSummonPoint[i].m_fOrient, - TEMPSUMMON_TIMED_DESPAWN, HOUR*IN_MILISECONDS); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //START NOT TRANSFORMED - if (!m_bTransformed) - { - //MindBlast - if (m_uiMindBlast_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MINDBLAST); - m_uiMindBlast_Timer = 15000 + rand()%5000; - } else m_uiMindBlast_Timer -= uiDiff; - - //CrusadersHammer - if (m_uiCrusadersHammer_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CRUSADERSHAMMER); - m_uiCrusadersHammer_Timer = 12000; - } else m_uiCrusadersHammer_Timer -= uiDiff; - - //CrusaderStrike - if (m_uiCrusaderStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CRUSADERSTRIKE); - m_uiCrusaderStrike_Timer = 15000; - } else m_uiCrusaderStrike_Timer -= uiDiff; - - //HolyStrike - if (m_uiHolyStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_HOLYSTRIKE); - m_uiHolyStrike_Timer = 15000; - } else m_uiHolyStrike_Timer -= uiDiff; - - //BalnazzarTransform - if (me->GetHealth()*100 / me->GetMaxHealth() < 40) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - //restore hp, mana and stun - DoCast(me, SPELL_BALNAZZARTRANSFORM); - me->UpdateEntry(NPC_BALNAZZAR); - m_bTransformed = true; - } - } - else - { - //MindBlast - if (m_uiMindBlast_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MINDBLAST); - m_uiMindBlast_Timer = 15000 + rand()%5000; - } else m_uiMindBlast_Timer -= uiDiff; - - //ShadowShock - if (m_uiShadowShock_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SHADOWSHOCK); - m_uiShadowShock_Timer = 11000; - } else m_uiShadowShock_Timer -= uiDiff; - - //PsychicScream - if (m_uiPsychicScream_Timer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_PSYCHICSCREAM); - - m_uiPsychicScream_Timer = 20000; - } else m_uiPsychicScream_Timer -= uiDiff; - - //DeepSleep - if (m_uiDeepSleep_Timer <= uiDiff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SLEEP); - - m_uiDeepSleep_Timer = 15000; - } else m_uiDeepSleep_Timer -= uiDiff; - - //MindControl - if (m_uiMindControl_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MINDCONTROL); - m_uiMindControl_Timer = 15000; - } else m_uiMindControl_Timer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_dathrohan_balnazzar(Creature* pCreature) -{ - return new boss_dathrohan_balnazzarAI (pCreature); -} - -void AddSC_boss_dathrohan_balnazzar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_dathrohan_balnazzar"; - newscript->GetAI = &GetAI_boss_dathrohan_balnazzar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp deleted file mode 100644 index 89de7dbc207..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_magistrate_barthilas.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Magistrate_Barthilas -SD%Complete: 70 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_DRAININGBLOW 16793 -#define SPELL_CROWDPUMMEL 10887 -#define SPELL_MIGHTYBLOW 14099 -#define SPELL_FURIOUS_ANGER 16791 - -#define MODEL_NORMAL 10433 -#define MODEL_HUMAN 3637 - -struct boss_magistrate_barthilasAI : public ScriptedAI -{ - boss_magistrate_barthilasAI(Creature *c) : ScriptedAI(c) {} - - uint32 DrainingBlow_Timer; - uint32 CrowdPummel_Timer; - uint32 MightyBlow_Timer; - uint32 FuriousAnger_Timer; - uint32 AngerCount; - - void Reset() - { - DrainingBlow_Timer = 20000; - CrowdPummel_Timer = 15000; - MightyBlow_Timer = 10000; - FuriousAnger_Timer = 5000; - AngerCount = 0; - - if (me->isAlive()) - me->SetDisplayId(MODEL_NORMAL); - else - me->SetDisplayId(MODEL_HUMAN); - } - - void MoveInLineOfSight(Unit *who) - { - //nothing to see here yet - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit* /*Killer*/) - { - me->SetDisplayId(MODEL_HUMAN); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (FuriousAnger_Timer <= diff) - { - FuriousAnger_Timer = 4000; - if (AngerCount > 25) - return; - - ++AngerCount; - DoCast(me, SPELL_FURIOUS_ANGER, false); - } else FuriousAnger_Timer -= diff; - - //DrainingBlow - if (DrainingBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DRAININGBLOW); - DrainingBlow_Timer = 15000; - } else DrainingBlow_Timer -= diff; - - //CrowdPummel - if (CrowdPummel_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CROWDPUMMEL); - CrowdPummel_Timer = 15000; - } else CrowdPummel_Timer -= diff; - - //MightyBlow - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTYBLOW); - MightyBlow_Timer = 20000; - } else MightyBlow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_magistrate_barthilas(Creature* pCreature) -{ - return new boss_magistrate_barthilasAI (pCreature); -} - -void AddSC_boss_magistrate_barthilas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magistrate_barthilas"; - newscript->GetAI = &GetAI_boss_magistrate_barthilas; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp deleted file mode 100644 index 0c1cf011d5e..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_maleki_the_pallid.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_maleki_the_pallid -SD%Complete: 100 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_FROSTBOLT 17503 -#define SPELL_DRAINLIFE 20743 -#define SPELL_DRAIN_MANA 17243 -#define SPELL_ICETOMB 16869 - -struct boss_maleki_the_pallidAI : public ScriptedAI -{ - boss_maleki_the_pallidAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Frostbolt_Timer; - uint32 IceTomb_Timer; - uint32 DrainLife_Timer; - - void Reset() - { - Frostbolt_Timer = 1000; - IceTomb_Timer = 16000; - DrainLife_Timer = 31000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_PALLID,IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frostbolt - if (Frostbolt_Timer <= diff) - { - if (rand()%100 < 90) - DoCast(me->getVictim(), SPELL_FROSTBOLT); - Frostbolt_Timer = 3500; - } else Frostbolt_Timer -= diff; - - //IceTomb - if (IceTomb_Timer <= diff) - { - if (rand()%100 < 65) - DoCast(me->getVictim(), SPELL_ICETOMB); - IceTomb_Timer = 28000; - } else IceTomb_Timer -= diff; - - //DrainLife - if (DrainLife_Timer <= diff) - { - if (rand()%100 < 55) - DoCast(me->getVictim(), SPELL_DRAINLIFE); - DrainLife_Timer = 31000; - } else DrainLife_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_maleki_the_pallid(Creature* pCreature) -{ - return new boss_maleki_the_pallidAI (pCreature); -} - -void AddSC_boss_maleki_the_pallid() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_maleki_the_pallid"; - newscript->GetAI = &GetAI_boss_maleki_the_pallid; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp deleted file mode 100644 index ae7299071f4..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_nerubenkan.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Nerubenkan -SD%Complete: 70 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_ENCASINGWEBS 4962 -#define SPELL_PIERCEARMOR 6016 -#define SPELL_CRYPT_SCARABS 31602 -#define SPELL_RAISEUNDEADSCARAB 17235 - -struct boss_nerubenkanAI : public ScriptedAI -{ - boss_nerubenkanAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 EncasingWebs_Timer; - uint32 PierceArmor_Timer; - uint32 CryptScarabs_Timer; - uint32 RaiseUndeadScarab_Timer; - - void Reset() - { - CryptScarabs_Timer = 3000; - EncasingWebs_Timer = 7000; - PierceArmor_Timer = 19000; - RaiseUndeadScarab_Timer = 3000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_NERUB,IN_PROGRESS); - } - - void RaiseUndeadScarab(Unit* pVictim) - { - if (Creature* pUndeadScarab = DoSpawnCreature(10876, irand(-9,9), irand(-9,9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000)) - if (pUndeadScarab->AI()) - pUndeadScarab->AI()->AttackStart(pVictim); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //EncasingWebs - if (EncasingWebs_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ENCASINGWEBS); - EncasingWebs_Timer = 30000; - } else EncasingWebs_Timer -= diff; - - //PierceArmor - if (PierceArmor_Timer <= diff) - { - if (urand(0,3) < 2) - DoCast(me->getVictim(), SPELL_PIERCEARMOR); - PierceArmor_Timer = 35000; - } else PierceArmor_Timer -= diff; - - //CryptScarabs_Timer - if (CryptScarabs_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CRYPT_SCARABS); - CryptScarabs_Timer = 20000; - } else CryptScarabs_Timer -= diff; - - //RaiseUndeadScarab - if (RaiseUndeadScarab_Timer <= diff) - { - RaiseUndeadScarab(me->getVictim()); - RaiseUndeadScarab_Timer = 16000; - } else RaiseUndeadScarab_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_nerubenkan(Creature* pCreature) -{ - return new boss_nerubenkanAI (pCreature); -} - -void AddSC_boss_nerubenkan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nerubenkan"; - newscript->GetAI = &GetAI_boss_nerubenkan; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp deleted file mode 100644 index 905feb9fffc..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_order_of_silver_hand.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Silver_Hand_Bosses -SD%Complete: 40 -SDComment: Basic script to have support for Horde paladin epic mount (quest 9737). All 5 members of Order of the Silver Hand running this script (least for now) -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -/*##### -# Additional: -# Although this is a working solution, the correct would be in addition to check if Aurius is dead. -# Once player extinguish the eternal flame (cast spell 31497->start event 11206) Aurius should become hostile. -# Once Aurius is defeated, he should be the one summoning the ghosts. -#####*/ - -#define SH_GREGOR 17910 -#define SH_CATHELA 17911 -#define SH_NEMAS 17912 -#define SH_AELMAR 17913 -#define SH_VICAR 17914 -#define SH_QUEST_CREDIT 17915 - -#define SPELL_HOLY_LIGHT 25263 -#define SPELL_DIVINE_SHIELD 13874 - -struct boss_silver_hand_bossesAI : public ScriptedAI -{ - boss_silver_hand_bossesAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 HolyLight_Timer; - uint32 DivineShield_Timer; - - void Reset() - { - HolyLight_Timer = 20000; - DivineShield_Timer = 20000; - - if (pInstance) - { - switch(me->GetEntry()) - { - case SH_AELMAR: - pInstance->SetData(TYPE_SH_AELMAR, 0); - break; - case SH_CATHELA: - pInstance->SetData(TYPE_SH_CATHELA, 0); - break; - case SH_GREGOR: - pInstance->SetData(TYPE_SH_GREGOR, 0); - break; - case SH_NEMAS: - pInstance->SetData(TYPE_SH_NEMAS, 0); - break; - case SH_VICAR: - pInstance->SetData(TYPE_SH_VICAR, 0); - break; - } - } - } - - void EnterCombat(Unit* /*who*/) - { - } - - void JustDied(Unit* Killer) - { - if (pInstance) - { - switch(me->GetEntry()) - { - case SH_AELMAR: - pInstance->SetData(TYPE_SH_AELMAR, 2); - break; - case SH_CATHELA: - pInstance->SetData(TYPE_SH_CATHELA, 2); - break; - case SH_GREGOR: - pInstance->SetData(TYPE_SH_GREGOR, 2); - break; - case SH_NEMAS: - pInstance->SetData(TYPE_SH_NEMAS, 2); - break; - case SH_VICAR: - pInstance->SetData(TYPE_SH_VICAR, 2); - break; - } - if (pInstance->GetData(TYPE_SH_QUEST) && Killer->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(Killer)->KilledMonsterCredit(SH_QUEST_CREDIT,me->GetGUID()); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (HolyLight_Timer <= diff) - { - if (me->GetHealth()*5 < me->GetMaxHealth()) - { - DoCast(me, SPELL_HOLY_LIGHT); - HolyLight_Timer = 20000; - } - } else HolyLight_Timer -= diff; - - if (DivineShield_Timer <= diff) - { - if (me->GetHealth()*20 < me->GetMaxHealth()) - { - DoCast(me, SPELL_DIVINE_SHIELD); - DivineShield_Timer = 40000; - } - } else DivineShield_Timer -= diff; - - DoMeleeAttackIfReady(); - } - -}; -CreatureAI* GetAI_boss_silver_hand_bossesAI(Creature* pCreature) -{ - return new boss_silver_hand_bossesAI (pCreature); -} - -void AddSC_boss_order_of_silver_hand() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_silver_hand_bosses"; - newscript->GetAI = &GetAI_boss_silver_hand_bossesAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp deleted file mode 100644 index c04bae15468..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_postmaster_malown.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_postmaster_malown -SD%Complete: 50 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" - -//Spell ID to summon this guy is 24627 "Summon Postmaster Malown" -//He should be spawned along with three other elites once the third postbox has been opened - -#define SAY_MALOWNED "You just got MALOWNED!" - -#define SPELL_WAILINGDEAD 7713 -#define SPELL_BACKHAND 6253 -#define SPELL_CURSEOFWEAKNESS 8552 -#define SPELL_CURSEOFTONGUES 12889 -#define SPELL_CALLOFTHEGRAVE 17831 - -struct boss_postmaster_malownAI : public ScriptedAI -{ - boss_postmaster_malownAI(Creature *c) : ScriptedAI(c) {} - - uint32 WailingDead_Timer; - uint32 Backhand_Timer; - uint32 CurseOfWeakness_Timer; - uint32 CurseOfTongues_Timer; - uint32 CallOfTheGrave_Timer; - bool HasYelled; - - void Reset() - { - WailingDead_Timer = 19000; //lasts 6 sec - Backhand_Timer = 8000; //2 sec stun - CurseOfWeakness_Timer = 20000; //lasts 2 mins - CurseOfTongues_Timer = 22000; - CallOfTheGrave_Timer = 25000; - HasYelled = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //WailingDead - if (WailingDead_Timer <= diff) - { - //Cast - if (rand()%100 < 65) //65% chance to cast - { - DoCast(me->getVictim(), SPELL_WAILINGDEAD); - } - //19 seconds until we should cast this again - WailingDead_Timer = 19000; - } else WailingDead_Timer -= diff; - - //Backhand - if (Backhand_Timer <= diff) - { - //Cast - if (rand()%100 < 45) //45% chance to cast - { - DoCast(me->getVictim(), SPELL_BACKHAND); - } - //8 seconds until we should cast this again - Backhand_Timer = 8000; - } else Backhand_Timer -= diff; - - //CurseOfWeakness - if (CurseOfWeakness_Timer <= diff) - { - //Cast - if (rand()%100 < 3) //3% chance to cast - { - DoCast(me->getVictim(), SPELL_CURSEOFWEAKNESS); - } - //20 seconds until we should cast this again - CurseOfWeakness_Timer = 20000; - } else CurseOfWeakness_Timer -= diff; - - //CurseOfTongues - if (CurseOfTongues_Timer <= diff) - { - //Cast - if (rand()%100 < 3) //3% chance to cast - { - DoCast(me->getVictim(), SPELL_CURSEOFTONGUES); - } - //22 seconds until we should cast this again - CurseOfTongues_Timer = 22000; - } else CurseOfTongues_Timer -= diff; - - //CallOfTheGrave - if (CallOfTheGrave_Timer <= diff) - { - //Cast - if (rand()%100 < 5) //5% chance to cast - { - DoCast(me->getVictim(), SPELL_CALLOFTHEGRAVE); - } - //25 seconds until we should cast this again - CallOfTheGrave_Timer = 25000; - } else CallOfTheGrave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_postmaster_malown(Creature* pCreature) -{ - return new boss_postmaster_malownAI (pCreature); -} - -void AddSC_boss_postmaster_malown() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_postmaster_malown"; - newscript->GetAI = &GetAI_boss_postmaster_malown; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp deleted file mode 100644 index 3a3ae60c9c9..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_ramstein_the_gorger.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Ramstein_The_Gorger -SD%Complete: 70 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define SPELL_TRAMPLE 5568 -#define SPELL_KNOCKOUT 17307 - - #define C_MINDLESS_UNDEAD 11030 - -struct boss_ramstein_the_gorgerAI : public ScriptedAI -{ - boss_ramstein_the_gorgerAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Trample_Timer; - uint32 Knockout_Timer; - - void Reset() - { - Trample_Timer = 3000; - Knockout_Timer = 12000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - for (uint8 i = 0; i < 30; ++i) - { - if (Creature* mob = me->SummonCreature(C_MINDLESS_UNDEAD,3969.35+irand(-10,10),-3391.87+irand(-10,10),119.11,5.91,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000)) - mob->AI()->AttackStart(me->SelectNearestTarget(500)); - } - - if (pInstance) - pInstance->SetData(TYPE_RAMSTEIN,DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Trample - if (Trample_Timer <= diff) - { - DoCast(me, SPELL_TRAMPLE); - Trample_Timer = 7000; - } else Trample_Timer -= diff; - - //Knockout - if (Knockout_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKOUT); - Knockout_Timer = 10000; - } else Knockout_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ramstein_the_gorger(Creature* pCreature) -{ - return new boss_ramstein_the_gorgerAI (pCreature); -} - -void AddSC_boss_ramstein_the_gorger() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ramstein_the_gorger"; - newscript->GetAI = &GetAI_boss_ramstein_the_gorger; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp b/src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp deleted file mode 100644 index f15eb59ba47..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/boss_timmy_the_cruel.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_timmy_the_cruel -SD%Complete: 100 -SDComment: -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_SPAWN "TIMMY!" - -#define SPELL_RAVENOUSCLAW 17470 - -struct boss_timmy_the_cruelAI : public ScriptedAI -{ - boss_timmy_the_cruelAI(Creature *c) : ScriptedAI(c) {} - - uint32 RavenousClaw_Timer; - bool HasYelled; - - void Reset() - { - RavenousClaw_Timer = 10000; - HasYelled = false; - } - - void EnterCombat(Unit * /*who*/) - { - if (!HasYelled) - { - me->MonsterYell(SAY_SPAWN,LANG_UNIVERSAL,NULL); - HasYelled = true; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //RavenousClaw - if (RavenousClaw_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_RAVENOUSCLAW); - //15 seconds until we should cast this again - RavenousClaw_Timer = 15000; - } else RavenousClaw_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_timmy_the_cruel(Creature* pCreature) -{ - return new boss_timmy_the_cruelAI (pCreature); -} - -void AddSC_boss_timmy_the_cruel() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_timmy_the_cruel"; - newscript->GetAI = &GetAI_boss_timmy_the_cruel; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp b/src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp deleted file mode 100644 index ffeaa070a26..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/instance_stratholme.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: instance_stratholme -SD%Complete: 50 -SDComment: In progress. Undead side 75% implemented. Save/load not implemented. -SDCategory: Stratholme -EndScriptData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -#define GO_SERVICE_ENTRANCE 175368 -#define GO_GAUNTLET_GATE1 175357 -#define GO_ZIGGURAT1 175380 //baroness -#define GO_ZIGGURAT2 175379 //nerub'enkan -#define GO_ZIGGURAT3 175381 //maleki -#define GO_ZIGGURAT4 175405 //rammstein -#define GO_ZIGGURAT5 175796 //baron -#define GO_PORT_GAUNTLET 175374 //port from gauntlet to slaugther -#define GO_PORT_SLAUGTHER 175373 //port at slaugther -#define GO_PORT_ELDERS 175377 //port at elders square - -#define C_CRYSTAL 10415 //three ziggurat crystals -#define C_BARON 10440 -#define C_YSIDA_TRIGGER 16100 - -#define C_RAMSTEIN 10439 -#define C_ABOM_BILE 10416 -#define C_ABOM_VENOM 10417 -#define C_BLACK_GUARD 10394 -#define C_YSIDA 16031 - -#define MAX_ENCOUNTER 6 - -struct instance_stratholme : public ScriptedInstance -{ - instance_stratholme(Map* pMap) : ScriptedInstance(pMap) {} - - uint32 Encounter[MAX_ENCOUNTER]; - - bool IsSilverHandDead[5]; - - uint32 BaronRun_Timer; - uint32 SlaugtherSquare_Timer; - - uint64 serviceEntranceGUID; - uint64 gauntletGate1GUID; - uint64 ziggurat1GUID; - uint64 ziggurat2GUID; - uint64 ziggurat3GUID; - uint64 ziggurat4GUID; - uint64 ziggurat5GUID; - uint64 portGauntletGUID; - uint64 portSlaugtherGUID; - uint64 portElderGUID; - - uint64 baronGUID; - uint64 ysidaTriggerGUID; - std::set crystalsGUID; - std::set abomnationGUID; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - Encounter[i] = NOT_STARTED; - - for (uint8 i = 0; i < 5; ++i) - IsSilverHandDead[i] = false; - - BaronRun_Timer = 0; - SlaugtherSquare_Timer = 0; - - serviceEntranceGUID = 0; - gauntletGate1GUID = 0; - ziggurat1GUID = 0; - ziggurat2GUID = 0; - ziggurat3GUID = 0; - ziggurat4GUID = 0; - ziggurat5GUID = 0; - portGauntletGUID = 0; - portSlaugtherGUID = 0; - portElderGUID = 0; - - baronGUID = 0; - ysidaTriggerGUID = 0; - crystalsGUID.clear(); - abomnationGUID.clear(); - } - - bool StartSlaugtherSquare() - { - //change to DONE when crystals implemented - if (Encounter[1] == IN_PROGRESS && Encounter[2] == IN_PROGRESS && Encounter[3] == IN_PROGRESS) - { - HandleGameObject(portGauntletGUID, true); - HandleGameObject(portSlaugtherGUID, true); - return true; - } - - debug_log("TSCR: Instance Stratholme: Cannot open slaugther square yet."); - return false; - } - - //if withRestoreTime true, then newState will be ignored and GO should be restored to original state after 10 seconds - void UpdateGoState(uint64 goGuid, uint32 newState, bool withRestoreTime) - { - if (!goGuid) - return; - - if (GameObject* pGo = instance->GetGameObject(goGuid)) - { - if (withRestoreTime) - pGo->UseDoorOrButton(10); - else - pGo->SetGoState((GOState)newState); - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case C_BARON: baronGUID = pCreature->GetGUID(); break; - case C_YSIDA_TRIGGER: ysidaTriggerGUID = pCreature->GetGUID(); break; - case C_CRYSTAL: crystalsGUID.insert(pCreature->GetGUID()); break; - case C_ABOM_BILE: - case C_ABOM_VENOM: abomnationGUID.insert(pCreature->GetGUID()); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_SERVICE_ENTRANCE: - serviceEntranceGUID = pGo->GetGUID(); - break; - case GO_GAUNTLET_GATE1: - //weird, but unless flag is set, client will not respond as expected. DB bug? - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_LOCKED); - gauntletGate1GUID = pGo->GetGUID(); - break; - case GO_ZIGGURAT1: - ziggurat1GUID = pGo->GetGUID(); - if (GetData(TYPE_BARONESS) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_ZIGGURAT2: - ziggurat2GUID = pGo->GetGUID(); - if (GetData(TYPE_NERUB) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_ZIGGURAT3: - ziggurat3GUID = pGo->GetGUID(); - if (GetData(TYPE_PALLID) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_ZIGGURAT4: - ziggurat4GUID = pGo->GetGUID(); - if (GetData(TYPE_BARON) == DONE || GetData(TYPE_RAMSTEIN) == DONE) - HandleGameObject(0, true, pGo); - break; - case GO_ZIGGURAT5: - ziggurat5GUID = pGo->GetGUID(); - if (GetData(TYPE_BARON) == DONE || GetData(TYPE_RAMSTEIN) == DONE) - HandleGameObject(0, true, pGo); - break; - case GO_PORT_GAUNTLET: - portGauntletGUID = pGo->GetGUID(); - if (GetData(TYPE_BARONESS) == IN_PROGRESS && GetData(TYPE_NERUB) == IN_PROGRESS && GetData(TYPE_PALLID) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_PORT_SLAUGTHER: - portSlaugtherGUID = pGo->GetGUID(); - if (GetData(TYPE_BARONESS) == IN_PROGRESS && GetData(TYPE_NERUB) == IN_PROGRESS && GetData(TYPE_PALLID) == IN_PROGRESS) - HandleGameObject(0, true, pGo); - break; - case GO_PORT_ELDERS: - portElderGUID = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_BARON_RUN: - switch(data) - { - case IN_PROGRESS: - if (Encounter[0] == IN_PROGRESS || Encounter[0] == FAIL) - break; - Encounter[0] = data; - BaronRun_Timer = 2700000; - debug_log("TSCR: Instance Stratholme: Baron run in progress."); - break; - case FAIL: - //may add code to remove aura from players, but in theory the time should be up already and removed. - Encounter[0] = data; - break; - case DONE: - Encounter[0] = data; - if (Creature* pYsidaT = instance->GetCreature(ysidaTriggerGUID)) - pYsidaT->SummonCreature(C_YSIDA, - pYsidaT->GetPositionX(),pYsidaT->GetPositionY(),pYsidaT->GetPositionZ(),pYsidaT->GetOrientation(), - TEMPSUMMON_TIMED_DESPAWN,1800000); - BaronRun_Timer = 0; - break; - } - break; - case TYPE_BARONESS: - Encounter[1] = data; - if (data == IN_PROGRESS) - HandleGameObject(ziggurat1GUID, true); - if (data == IN_PROGRESS) //change to DONE when crystals implemented - StartSlaugtherSquare(); - break; - case TYPE_NERUB: - Encounter[2] = data; - if (data == IN_PROGRESS) - HandleGameObject(ziggurat2GUID, true); - if (data == IN_PROGRESS) //change to DONE when crystals implemented - StartSlaugtherSquare(); - break; - case TYPE_PALLID: - Encounter[3] = data; - if (data == IN_PROGRESS) - HandleGameObject(ziggurat3GUID, true); - if (data == IN_PROGRESS) //change to DONE when crystals implemented - StartSlaugtherSquare(); - break; - case TYPE_RAMSTEIN: - if (data == IN_PROGRESS) - { - HandleGameObject(portGauntletGUID, false); - - uint32 count = abomnationGUID.size(); - for (std::set::const_iterator i = abomnationGUID.begin(); i != abomnationGUID.end(); ++i) - { - if (Creature* pAbom = instance->GetCreature(*i)) - { - if (!pAbom->isAlive()) - --count; - } - } - - if (!count) - { - //a bit itchy, it should close the door after 10 secs, but it doesn't. skipping it for now. - //UpdateGoState(ziggurat4GUID,0,true); - if (Creature* pBaron = instance->GetCreature(baronGUID)) - pBaron->SummonCreature(C_RAMSTEIN,4032.84,-3390.24,119.73,4.71,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000); - debug_log("TSCR: Instance Stratholme: Ramstein spawned."); - } - else - debug_log("TSCR: Instance Stratholme: %u Abomnation left to kill.",count); - } - - if (data == NOT_STARTED) - HandleGameObject(portGauntletGUID, true); - - if (data == DONE) - { - SlaugtherSquare_Timer = 300000; - debug_log("TSCR: Instance Stratholme: Slaugther event will continue in 5 minutes."); - } - Encounter[4] = data; - break; - case TYPE_BARON: - if (data == IN_PROGRESS) - { - HandleGameObject(ziggurat4GUID, false); - HandleGameObject(ziggurat5GUID, false); - if (GetData(TYPE_BARON_RUN) == IN_PROGRESS) - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - { - if (pPlayer->HasAura(SPELL_BARON_ULTIMATUM)) - pPlayer->RemoveAurasDueToSpell(SPELL_BARON_ULTIMATUM); - - if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_DEAD_MAN_PLEA); - } - } - } - - SetData(TYPE_BARON_RUN,DONE); - } - } - if (data == DONE || data == NOT_STARTED) - { - HandleGameObject(ziggurat4GUID, true); - HandleGameObject(ziggurat5GUID, true); - } - if (data == DONE) - HandleGameObject(portGauntletGUID, true); - Encounter[5] = data; - break; - case TYPE_SH_AELMAR: - IsSilverHandDead[0] = (data) ? true : false; - break; - case TYPE_SH_CATHELA: - IsSilverHandDead[1] = (data) ? true : false; - break; - case TYPE_SH_GREGOR: - IsSilverHandDead[2] = (data) ? true : false; - break; - case TYPE_SH_NEMAS: - IsSilverHandDead[3] = (data) ? true : false; - break; - case TYPE_SH_VICAR: - IsSilverHandDead[4] = (data) ? true : false; - break; - } - if (data == DONE)SaveToDB(); - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << Encounter[0] << " " << Encounter[1] << " " << Encounter[2] << " " - << Encounter[3] << " " << Encounter[4] << " " << Encounter[5]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> Encounter[0] >> Encounter[1] >> Encounter[2] >> Encounter[3] - >> Encounter[4] >> Encounter[5]; - - // Do not reset 1, 2 and 3. they are not set to done, yet . - if (Encounter[0] == IN_PROGRESS) - Encounter[0] = NOT_STARTED; - if (Encounter[4] == IN_PROGRESS) - Encounter[4] = NOT_STARTED; - if (Encounter[5] == IN_PROGRESS) - Encounter[5] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_SH_QUEST: - if (IsSilverHandDead[0] && IsSilverHandDead[1] && IsSilverHandDead[2] && IsSilverHandDead[3] && IsSilverHandDead[4]) - return 1; - return 0; - case TYPE_BARON_RUN: - return Encounter[0]; - case TYPE_BARONESS: - return Encounter[1]; - case TYPE_NERUB: - return Encounter[2]; - case TYPE_PALLID: - return Encounter[3]; - case TYPE_RAMSTEIN: - return Encounter[4]; - case TYPE_BARON: - return Encounter[5]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_BARON: - return baronGUID; - case DATA_YSIDA_TRIGGER: - return ysidaTriggerGUID; - } - return 0; - } - - void Update(uint32 diff) - { - if (BaronRun_Timer) - { - if (BaronRun_Timer <= diff) - { - if (GetData(TYPE_BARON_RUN) != DONE) - SetData(TYPE_BARON_RUN, FAIL); - BaronRun_Timer = 0; - debug_log("TSCR: Instance Stratholme: Baron run event reached end. Event has state %u.",GetData(TYPE_BARON_RUN)); - } else BaronRun_Timer -= diff; - } - - if (SlaugtherSquare_Timer) - { - if (SlaugtherSquare_Timer <= diff) - { - if (Creature* pBaron = instance->GetCreature(baronGUID)) - { - for (uint8 i = 0; i < 4; ++i) - pBaron->SummonCreature(C_BLACK_GUARD,4032.84,-3390.24,119.73,4.71,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000); - - HandleGameObject(ziggurat4GUID, true); - HandleGameObject(ziggurat5GUID, true); - debug_log("TSCR: Instance Stratholme: Black guard sentries spawned. Opening gates to baron."); - } - SlaugtherSquare_Timer = 0; - } else SlaugtherSquare_Timer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_stratholme(Map* pMap) -{ - return new instance_stratholme(pMap); -} - -void AddSC_instance_stratholme() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_stratholme"; - newscript->GetInstanceData = &GetInstanceData_instance_stratholme; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp b/src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp deleted file mode 100644 index 035fca68b95..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/stratholme.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Stratholme -SD%Complete: 100 -SDComment: Misc mobs for instance. pGo-script to apply aura and start event for quest 8945 -SDCategory: Stratholme -EndScriptData */ - -/* ContentData -go_gauntlet_gate -mob_freed_soul -mob_restless_soul -mobs_spectral_ghostly_citizen -EndContentData */ - -#include "ScriptedPch.h" -#include "stratholme.h" - -/*###### -## go_gauntlet_gate (this is the _first_ of the gauntlet gates, two exist) -######*/ - -bool GOHello_go_gauntlet_gate(Player* pPlayer, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - - if (!pInstance) - return false; - - if (pInstance->GetData(TYPE_BARON_RUN) != NOT_STARTED) - return false; - - if (Group *pGroup = pPlayer->GetGroup()) - { - for (GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* pGroupie = itr->getSource(); - if (!pGroupie) - continue; - - if (pGroupie->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && - !pGroupie->HasAura(SPELL_BARON_ULTIMATUM) && - pGroupie->GetMap() == pGo->GetMap()) - pGroupie->CastSpell(pGroupie,SPELL_BARON_ULTIMATUM,true); - } - } else if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE && - !pPlayer->HasAura(SPELL_BARON_ULTIMATUM) && - pPlayer->GetMap() == pGo->GetMap()) - pPlayer->CastSpell(pPlayer,SPELL_BARON_ULTIMATUM,true); - - pInstance->SetData(TYPE_BARON_RUN,IN_PROGRESS); - return false; -} - -/*###### -## mob_freed_soul -######*/ - -//Possibly more of these quotes around. -#define SAY_ZAPPED0 -1329000 -#define SAY_ZAPPED1 -1329001 -#define SAY_ZAPPED2 -1329002 -#define SAY_ZAPPED3 -1329003 - -struct mob_freed_soulAI : public ScriptedAI -{ - mob_freed_soulAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - DoScriptText(RAND(SAY_ZAPPED0,SAY_ZAPPED1,SAY_ZAPPED2,SAY_ZAPPED3), me); - } - - void EnterCombat(Unit* /*who*/) {} -}; - -CreatureAI* GetAI_mob_freed_soul(Creature* pCreature) -{ - return new mob_freed_soulAI (pCreature); -} - -/*###### -## mob_restless_soul -######*/ - -#define SPELL_EGAN_BLASTER 17368 -#define SPELL_SOUL_FREED 17370 -#define QUEST_RESTLESS_SOUL 5282 -#define ENTRY_RESTLESS 11122 -#define ENTRY_FREED 11136 - -struct mob_restless_soulAI : public ScriptedAI -{ - mob_restless_soulAI(Creature *c) : ScriptedAI(c) {} - - uint64 Tagger; - uint32 Die_Timer; - bool Tagged; - - void Reset() - { - Tagger = 0; - Die_Timer = 5000; - Tagged = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - if (!Tagged && spell->Id == SPELL_EGAN_BLASTER && CAST_PLR(caster)->GetQuestStatus(QUEST_RESTLESS_SOUL) == QUEST_STATUS_INCOMPLETE) - { - Tagged = true; - Tagger = caster->GetGUID(); - } - } - } - - void JustSummoned(Creature *summoned) - { - summoned->CastSpell(summoned,SPELL_SOUL_FREED,false); - } - - void JustDied(Unit* /*Killer*/) - { - if (Tagged) - me->SummonCreature(ENTRY_FREED, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 300000); - } - - void UpdateAI(const uint32 diff) - { - if (Tagged) - { - if (Die_Timer <= diff) - { - if (Unit* pTemp = Unit::GetUnit(*me,Tagger)) - { - CAST_PLR(pTemp)->KilledMonsterCredit(ENTRY_RESTLESS, me->GetGUID()); - me->Kill(me); - } - } else Die_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_mob_restless_soul(Creature* pCreature) -{ - return new mob_restless_soulAI (pCreature); -} - -/*###### -## mobs_spectral_ghostly_citizen -######*/ - -enum eGhostlyCitizenSpells -{ - SPELL_HAUNTING_PHANTOM = 16336, - SPELL_SLAP = 6754 -}; - -struct mobs_spectral_ghostly_citizenAI : public ScriptedAI -{ - mobs_spectral_ghostly_citizenAI(Creature *c) : ScriptedAI(c) {} - - uint32 Die_Timer; - bool Tagged; - - void Reset() - { - Die_Timer = 5000; - Tagged = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (!Tagged && spell->Id == SPELL_EGAN_BLASTER) - Tagged = true; - } - - void JustDied(Unit* /*Killer*/) - { - if (Tagged) - { - for (uint32 i = 1; i <= 4; ++i) - { - //100%, 50%, 33%, 25% chance to spawn - if (urand(1,i) == 1) - DoSummon(ENTRY_RESTLESS, me, 20.0f, 600000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Tagged) - { - if (Die_Timer <= diff) - me->Kill(me); - else Die_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void ReceiveEmote(Player* pPlayer, uint32 emote) - { - switch(emote) - { - case TEXTEMOTE_DANCE: - EnterEvadeMode(); - break; - case TEXTEMOTE_RUDE: - if (me->IsWithinDistInMap(pPlayer, 5)) - DoCast(pPlayer, SPELL_SLAP, false); - else - me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE); - break; - case TEXTEMOTE_WAVE: - me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); - break; - case TEXTEMOTE_BOW: - me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); - break; - case TEXTEMOTE_KISS: - me->HandleEmoteCommand(EMOTE_ONESHOT_FLEX); - break; - } - } -}; - -CreatureAI* GetAI_mobs_spectral_ghostly_citizen(Creature* pCreature) -{ - return new mobs_spectral_ghostly_citizenAI (pCreature); -} - -void AddSC_stratholme() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_gauntlet_gate"; - newscript->pGOHello = &GOHello_go_gauntlet_gate; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_freed_soul"; - newscript->GetAI = &GetAI_mob_freed_soul; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_restless_soul"; - newscript->GetAI = &GetAI_mob_restless_soul; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mobs_spectral_ghostly_citizen"; - newscript->GetAI = &GetAI_mobs_spectral_ghostly_citizen; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/stratholme/stratholme.h b/src/server/scripts/EasternKingdoms/stratholme/stratholme.h deleted file mode 100644 index b9246091a7c..00000000000 --- a/src/server/scripts/EasternKingdoms/stratholme/stratholme.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_STRATHOLME_H -#define DEF_STRATHOLME_H - -#define TYPE_BARON_RUN 1 -#define TYPE_BARONESS 2 -#define TYPE_NERUB 3 -#define TYPE_PALLID 4 -#define TYPE_RAMSTEIN 5 -#define TYPE_BARON 6 - -#define DATA_BARON 10 -#define DATA_YSIDA_TRIGGER 11 - -#define TYPE_SH_QUEST 20 -#define TYPE_SH_CATHELA 21 -#define TYPE_SH_GREGOR 22 -#define TYPE_SH_NEMAS 23 -#define TYPE_SH_VICAR 24 -#define TYPE_SH_AELMAR 25 - -#define QUEST_DEAD_MAN_PLEA 8945 -#define SPELL_BARON_ULTIMATUM 27861 -#endif - diff --git a/src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp deleted file mode 100644 index 6fe65cf963d..00000000000 --- a/src/server/scripts/EasternKingdoms/sunken_temple/instance_sunken_temple.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (C) 2006 - 2009 kb_z - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Sunken_Temple -SD%Complete: 100 -SDComment:Place Holder -SDCategory: Sunken Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunken_temple.h" - -#define GO_ATALAI_STATUE1 148830 -#define GO_ATALAI_STATUE2 148831 -#define GO_ATALAI_STATUE3 148832 -#define GO_ATALAI_STATUE4 148833 -#define GO_ATALAI_STATUE5 148834 -#define GO_ATALAI_STATUE6 148835 -#define GO_ATALAI_IDOL 148836 - -#define GO_ATALAI_LIGHT1 148883 -#define GO_ATALAI_LIGHT2 148937 - -#define NPC_MALFURION_STORMRAGE 15362 - -struct instance_sunken_temple : public ScriptedInstance -{ - instance_sunken_temple(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - }; - - uint64 GOAtalaiStatue1; - uint64 GOAtalaiStatue2; - uint64 GOAtalaiStatue3; - uint64 GOAtalaiStatue4; - uint64 GOAtalaiStatue5; - uint64 GOAtalaiStatue6; - uint64 GOAtalaiIdol; - - uint32 State; - - bool s1; - bool s2; - bool s3; - bool s4; - bool s5; - bool s6; - - void Initialize() - { - GOAtalaiStatue1 = 0; - GOAtalaiStatue2 = 0; - GOAtalaiStatue3 = 0; - GOAtalaiStatue4 = 0; - GOAtalaiStatue5 = 0; - GOAtalaiStatue6 = 0; - GOAtalaiIdol = 0; - - State = 0; - - s1 = false; - s2 = false; - s3 = false; - s4 = false; - s5 = false; - s6 = false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_ATALAI_STATUE1: GOAtalaiStatue1 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE2: GOAtalaiStatue2 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE3: GOAtalaiStatue3 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE4: GOAtalaiStatue4 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE5: GOAtalaiStatue5 = pGo->GetGUID(); break; - case GO_ATALAI_STATUE6: GOAtalaiStatue6 = pGo->GetGUID(); break; - case GO_ATALAI_IDOL: GOAtalaiIdol = pGo->GetGUID(); break; - } - } - - virtual void Update(uint32 /*diff*/) // correct order goes form 1-6 - { - switch(State) - { - case GO_ATALAI_STATUE1: - if (!s1 && !s2 && !s3 && !s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue1 = instance->GetGameObject(GOAtalaiStatue1)) - UseStatue(pAtalaiStatue1); - s1 = true; - State = 0; - }; - break; - case GO_ATALAI_STATUE2: - if (s1 && !s2 && !s3 && !s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue2 = instance->GetGameObject(GOAtalaiStatue2)) - UseStatue(pAtalaiStatue2); - s2 = true; - State = 0; - }; - break; - case GO_ATALAI_STATUE3: - if (s1 && s2 && !s3 && !s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue3 = instance->GetGameObject(GOAtalaiStatue3)) - UseStatue(pAtalaiStatue3); - s3 = true; - State = 0; - }; - break; - case GO_ATALAI_STATUE4: - if (s1 && s2 && s3 && !s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue4 = instance->GetGameObject(GOAtalaiStatue4)) - UseStatue(pAtalaiStatue4); - s4 = true; - State = 0; - } - break; - case GO_ATALAI_STATUE5: - if (s1 && s2 && s3 && s4 && !s5 && !s6) - { - if (GameObject *pAtalaiStatue5 = instance->GetGameObject(GOAtalaiStatue5)) - UseStatue(pAtalaiStatue5); - s5 = true; - State = 0; - } - break; - case GO_ATALAI_STATUE6: - if (s1 && s2 && s3 && s4 && s5 && !s6) - { - if (GameObject *pAtalaiStatue6 = instance->GetGameObject(GOAtalaiStatue6)) - UseStatue(pAtalaiStatue6); - s6 = true; - State = 0; - } - break; - } - }; - - void UseStatue(GameObject* pGo) - { - pGo->SummonGameObject(GO_ATALAI_LIGHT1,pGo->GetPositionX(),pGo->GetPositionY(),pGo->GetPositionZ(),0,0,0,0,0,0); - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 4); - } - - /* - void UseLastStatue(GameObject* pGo) - { - AtalaiStatue1->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue1->GetPositionX(),AtalaiStatue1->GetPositionY(),AtalaiStatue1->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue2->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue2->GetPositionX(),AtalaiStatue2->GetPositionY(),AtalaiStatue2->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue3->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue3->GetPositionX(),AtalaiStatue3->GetPositionY(),AtalaiStatue3->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue4->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue4->GetPositionX(),AtalaiStatue4->GetPositionY(),AtalaiStatue4->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue5->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue5->GetPositionX(),AtalaiStatue5->GetPositionY(),AtalaiStatue5->GetPositionZ(),0,0,0,0,0,100000); - AtalaiStatue6->SummonGameObject(GO_ATALAI_LIGHT2,AtalaiStatue6->GetPositionX(),AtalaiStatue6->GetPositionY(),AtalaiStatue6->GetPositionZ(),0,0,0,0,0,100000); - pGo->SummonGameObject(148838,-488.997,96.61,-189.019,-1.52,0,0,0,0,100000); - } - */ - - void SetData(uint32 type, uint32 data) - { - if (type == EVENT_STATE) - State = data; - } - - uint32 GetData(uint32 type) - { - if (type == EVENT_STATE) - return State; - return 0; - } -}; - -InstanceData* GetInstanceData_instance_sunken_temple(Map* pMap) -{ - return new instance_sunken_temple(pMap); -} - -void AddSC_instance_sunken_temple() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_sunken_temple"; - newscript->GetInstanceData = &GetInstanceData_instance_sunken_temple; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp b/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp deleted file mode 100644 index 7f0ca126d78..00000000000 --- a/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2006 - 2009 kb_z - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Sunken_Temple -SD%Complete: 100 -SDComment: Area Trigger + Puzzle event support -SDCategory: Sunken Temple -EndScriptData */ - -/* ContentData -at_malfurion_Stormrage_trigger -EndContentData */ - -#include "ScriptedPch.h" -#include "sunken_temple.h" - -/*##### -# at_malfurion_Stormrage_trigger -#####*/ - -bool AreaTrigger_at_malfurion_stormrage(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - if (ScriptedInstance* pInstance = pPlayer->GetInstanceData()) - { - if (!pPlayer->FindNearestCreature(15362,15)) - pPlayer->SummonCreature(15362, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), -1.52, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 100000); - return false; - } -return false; -} -/*##### -# go_atalai_statue -#####*/ - -bool GOHello_go_atalai_statue(Player* pPlayer, GameObject* pGo) -{ - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (!pInstance) - return false; - pInstance->SetData(EVENT_STATE,pGo->GetEntry()); - return false; -} - -void AddSC_sunken_temple() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "at_malfurion_stormrage"; - newscript->pAreaTrigger = &AreaTrigger_at_malfurion_stormrage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_atalai_statue"; - newscript->pGOHello = &GOHello_go_atalai_statue; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h b/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h deleted file mode 100644 index 82245095c31..00000000000 --- a/src/server/scripts/EasternKingdoms/sunken_temple/sunken_temple.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2006 - 2009 kb_z - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SUNKEN_TEMPLE_H -#define DEF_SUNKEN_TEMPLE_H - -#define TROLLBOSS1_DEATH 1 -#define TROLLBOSS2_DEATH 2 -#define TROLLBOSS3_DEATH 3 -#define TROLLBOSS4_DEATH 4 -#define TROLLBOSS5_DEATH 5 -#define TROLLBOSS6_DEATH 6 -#define JAMMALAN_DEATH 7 -#define MORPHAZ_DEATH 8 -#define HAZZAS_DEATH 9 -#define ERANIKUS_DEATH 10 -#define ATALALARION_DEATH 11 //optional - -#define EVENT_STATE 1 -#endif - diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp deleted file mode 100644 index 59e58d6df1a..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_brutallus.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Brutallus -SD%Complete: 80 -SDComment: Find a way to start the intro, best code for the intro -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -enum Quotes -{ - YELL_INTRO = -1580017, - YELL_INTRO_BREAK_ICE = -1580018, - YELL_INTRO_CHARGE = -1580019, - YELL_INTRO_KILL_MADRIGOSA = -1580020, - YELL_INTRO_TAUNT = -1580021, - - YELL_MADR_ICE_BARRIER = -1580031, - YELL_MADR_INTRO = -1580032, - YELL_MADR_ICE_BLOCK = -1580033, - YELL_MADR_TRAP = -1580034, - YELL_MADR_DEATH = -1580035, - - YELL_AGGRO = -1580022, - YELL_KILL1 = -1580023, - YELL_KILL2 = -1580024, - YELL_KILL3 = -1580025, - YELL_LOVE1 = -1580026, - YELL_LOVE2 = -1580027, - YELL_LOVE3 = -1580028, - YELL_BERSERK = -1580029, - YELL_DEATH = -1580030 -}; - -enum Spells -{ - SPELL_METEOR_SLASH = 45150, - SPELL_BURN = 46394, - SPELL_STOMP = 45185, - SPELL_BERSERK = 26662, - SPELL_DUAL_WIELD = 42459, - - SPELL_INTRO_FROST_BLAST = 45203, - SPELL_INTRO_FROSTBOLT = 44843, - SPELL_INTRO_ENCAPSULATE = 45665, - SPELL_INTRO_ENCAPSULATE_CHANELLING = 45661 -}; - -#define FELMYST 25038 - -struct boss_brutallusAI : public ScriptedAI -{ - boss_brutallusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = true; - } - - ScriptedInstance* pInstance; - - uint32 SlashTimer; - uint32 BurnTimer; - uint32 StompTimer; - uint32 BerserkTimer; - - uint32 IntroPhase; - uint32 IntroPhaseTimer; - uint32 IntroFrostBoltTimer; - - bool Intro; - bool IsIntro; - bool Enraged; - - void Reset() - { - SlashTimer = 11000; - StompTimer = 30000; - BurnTimer = 60000; - BerserkTimer = 360000; - - IntroPhase = 0; - IntroPhaseTimer = 0; - IntroFrostBoltTimer = 0; - - IsIntro = false; - Enraged = false; - - DoCast(me, SPELL_DUAL_WIELD, true); - - if (pInstance) - pInstance->SetData(DATA_BRUTALLUS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_BRUTALLUS_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(YELL_KILL1,YELL_KILL2,YELL_KILL3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(YELL_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_BRUTALLUS_EVENT, DONE); - float x,y,z; - me->GetPosition(x,y,z); - me->SummonCreature(FELMYST, x,y, z+30, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0); - } - } - - void EnterEvadeMode() - { - if (!Intro) - ScriptedAI::EnterEvadeMode(); - } - - void StartIntro() - { - if (!Intro || IsIntro) - return; - error_log("Start Intro"); - Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0); - if (Madrigosa) - { - Madrigosa->Respawn(); - Madrigosa->setActive(true); - IsIntro = true; - Madrigosa->SetMaxHealth(me->GetMaxHealth()); - Madrigosa->SetHealth(me->GetMaxHealth()); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->Attack(Madrigosa, true); - Madrigosa->Attack(me, true); - }else - { - //Madrigosa not found, end intro - error_log("Madrigosa was not found"); - EndIntro(); - } - } - - void EndIntro() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Intro = false; - IsIntro = false; - error_log("End Intro"); - } - - void AttackStart(Unit* pWho) - { - if (!pWho || Intro || IsIntro) - return; - ScriptedAI::AttackStart(pWho); - } - - void DoIntro() - { - Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0); - if (!Madrigosa) - return; - - switch (IntroPhase) - { - case 0: - DoScriptText(YELL_MADR_ICE_BARRIER, Madrigosa); - IntroPhaseTimer = 7000; - ++IntroPhase; - break; - case 1: - me->SetInFront(Madrigosa); - Madrigosa->SetInFront(me); - DoScriptText(YELL_MADR_INTRO, Madrigosa, me); - IntroPhaseTimer = 9000; - ++IntroPhase; - break; - case 2: - DoScriptText(YELL_INTRO, me, Madrigosa); - IntroPhaseTimer = 13000; - ++IntroPhase; - break; - case 3: - DoCast(me, SPELL_INTRO_FROST_BLAST); - Madrigosa->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->AttackStop(); - Madrigosa->AttackStop(); - IntroFrostBoltTimer = 3000; - IntroPhaseTimer = 28000; - ++IntroPhase; - break; - case 4: - DoScriptText(YELL_INTRO_BREAK_ICE, me); - IntroPhaseTimer = 6000; - ++IntroPhase; - break; - case 5: - Madrigosa->CastSpell(me, SPELL_INTRO_ENCAPSULATE_CHANELLING, false); - DoScriptText(YELL_MADR_TRAP, Madrigosa); - DoCast(me, SPELL_INTRO_ENCAPSULATE); - IntroPhaseTimer = 11000; - ++IntroPhase; - break; - case 6: - DoScriptText(YELL_INTRO_CHARGE, me); - IntroPhaseTimer = 5000; - ++IntroPhase; - break; - case 7: - me->Kill(Madrigosa); - DoScriptText(YELL_MADR_DEATH, Madrigosa); - me->SetHealth(me->GetMaxHealth()); - me->AttackStop(); - IntroPhaseTimer = 4000; - ++IntroPhase; - break; - case 8: - DoScriptText(YELL_INTRO_KILL_MADRIGOSA, me); - me->SetOrientation(0.14f); - me->StopMoving(); - Madrigosa->setDeathState(CORPSE); - IntroPhaseTimer = 8000; - ++IntroPhase; - break; - case 9: - DoScriptText(YELL_INTRO_TAUNT, me); - IntroPhaseTimer = 5000; - ++IntroPhase; - break; - case 10: - EndIntro(); - break; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!who->isTargetableForAttack() || !me->IsHostileTo(who)) - return; - if (pInstance && Intro) - pInstance->SetData(DATA_BRUTALLUS_EVENT, SPECIAL); - - if (Intro && !IsIntro) - StartIntro(); - if (!Intro) - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - if (IsIntro) - { - if (IntroPhaseTimer <= diff) - DoIntro(); - else IntroPhaseTimer -= diff; - - if (IntroPhase == 3 + 1) - { - if (IntroFrostBoltTimer <= diff) - { - if (Creature *Madrigosa = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_MADRIGOSA) : 0)) - { - Madrigosa->CastSpell(me, SPELL_INTRO_FROSTBOLT, true); - IntroFrostBoltTimer = 2000; - } - } else IntroFrostBoltTimer -= diff; - } - if (!UpdateVictim()) - return; - DoMeleeAttackIfReady(); - } - - if (!UpdateVictim() || IsIntro) - return; - - if (SlashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_METEOR_SLASH); - SlashTimer = 11000; - } else SlashTimer -= diff; - - if (StompTimer <= diff) - { - DoScriptText(RAND(YELL_LOVE1,YELL_LOVE2,YELL_LOVE3), me); - DoCast(me->getVictim(), SPELL_STOMP); - StompTimer = 30000; - } else StompTimer -= diff; - - if (BurnTimer <= diff) - { - std::list pTargets; - SelectTargetList(pTargets, 10, SELECT_TARGET_RANDOM, 100, true); - for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) - if (!(*i)->HasAura(SPELL_BURN)) - { - (*i)->CastSpell((*i), SPELL_BURN, true); - break; - } - BurnTimer = urand(60000,180000); - } else BurnTimer -= diff; - - if (BerserkTimer < diff && !Enraged) - { - DoScriptText(YELL_BERSERK, me); - DoCast(me, SPELL_BERSERK); - Enraged = true; - } else BerserkTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_brutallus(Creature* pCreature) -{ - return new boss_brutallusAI (pCreature); -} - -void AddSC_boss_brutallus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_brutallus"; - newscript->GetAI = &GetAI_boss_brutallus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp deleted file mode 100644 index 602f12065fa..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_eredar_twins.cpp +++ /dev/null @@ -1,762 +0,0 @@ -/* Copyright (C) 2009 Trinity -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Eredar_Twins -SD%Complete: 100 -SDComment: -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -enum Quotes -{ - //Alytesh - YELL_CANFLAGRATION = -1580044, - YELL_SISTER_SACROLASH_DEAD = -1580045, - YELL_ALY_KILL_1 = -1580046, - YELL_ALY_KILL_2 = -1580047, - YELL_ALY_DEAD = -1580048, - YELL_BERSERK = -1580049, - - //Sacrolash - YELL_SHADOW_NOVA = -1580050, - YELL_SISTER_ALYTHESS_DEAD = -1580051, - YELL_SAC_KILL_1 = -1580052, - YELL_SAC_KILL_2 = -1580053, - SAY_SAC_DEAD = -1580054, - YELL_ENRAGE = -1580055, - - //Intro - YELL_INTRO_SAC_1 = -1580056, - YELL_INTRO_ALY_2 = -1580057, - YELL_INTRO_SAC_3 = -1580058, - YELL_INTRO_ALY_4 = -1580059, - YELL_INTRO_SAC_5 = -1580060, - YELL_INTRO_ALY_6 = -1580061, - YELL_INTRO_SAC_7 = -1580062, - YELL_INTRO_ALY_8 = -1580063, - - //Emote - EMOTE_SHADOW_NOVA = -1580064, - EMOTE_CONFLAGRATION = -1580065 -}; - -enum Spells -{ - //Lady Sacrolash spells - SPELL_DARK_TOUCHED = 45347, - SPELL_SHADOW_BLADES = 45248, //10 secs - SPELL_DARK_STRIKE = 45271, - SPELL_SHADOW_NOVA = 45329, //30-35 secs - SPELL_CONFOUNDING_BLOW = 45256, //25 secs - - //Shadow Image spells - SPELL_SHADOW_FURY = 45270, - SPELL_IMAGE_VISUAL = 45263, - - //Misc spells - SPELL_ENRAGE = 46587, - SPELL_EMPOWER = 45366, - SPELL_DARK_FLAME = 45345, - - //Grand Warlock Alythess spells - SPELL_PYROGENICS = 45230, //15secs - SPELL_FLAME_TOUCHED = 45348, - SPELL_CONFLAGRATION = 45342, //30-35 secs - SPELL_BLAZE = 45235, //on main target every 3 secs - SPELL_FLAME_SEAR = 46771, - SPELL_BLAZE_SUMMON = 45236, //187366 GO - SPELL_BLAZE_BURN = 45246 -}; - -struct boss_sacrolashAI : public ScriptedAI -{ - boss_sacrolashAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - bool SisterDeath; - bool Enraged; - - uint32 ShadowbladesTimer; - uint32 ShadownovaTimer; - uint32 ConfoundingblowTimer; - uint32 ShadowimageTimer; - uint32 ConflagrationTimer; - uint32 EnrageTimer; - - void Reset() - { - Enraged = false; - - if (pInstance) - { - Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); - if (Temp) - if (Temp->isDead()) - { - CAST_CRE(Temp)->Respawn(); - }else - { - if (Temp->getVictim()) - { - me->getThreatManager().addThreat(Temp->getVictim(),0.0f); - } - } - } - - if (!me->isInCombat()) - { - ShadowbladesTimer = 10000; - ShadownovaTimer = 30000; - ConfoundingblowTimer = 25000; - ShadowimageTimer = 20000; - ConflagrationTimer = 30000; - EnrageTimer = 360000; - - SisterDeath = false; - } - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * who) - { - DoZoneInCombat(); - - if (pInstance) - { - Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); - if (Temp && Temp->isAlive() && !(Temp->getVictim())) - CAST_CRE(Temp)->AI()->AttackStart(who); - } - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - if (rand()%4 == 0) - DoScriptText(RAND(YELL_SAC_KILL_1,YELL_SAC_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - // only if ALY death - if (SisterDeath) - { - DoScriptText(SAY_SAC_DEAD, me); - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, DONE); - } - else - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - - void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) - { - switch(spell->Id) - { - case SPELL_SHADOW_BLADES: - case SPELL_SHADOW_NOVA: - case SPELL_CONFOUNDING_BLOW: - case SPELL_SHADOW_FURY: - HandleTouchedSpells(pTarget, SPELL_DARK_TOUCHED); - break; - case SPELL_CONFLAGRATION: - HandleTouchedSpells(pTarget, SPELL_FLAME_TOUCHED); - break; - } - } - - void HandleTouchedSpells(Unit *pTarget, uint32 TouchedType) - { - switch(TouchedType) - { - case SPELL_FLAME_TOUCHED: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_DARK_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_DARK_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - } else pTarget->CastSpell(pTarget, SPELL_FLAME_TOUCHED, true); - } - break; - case SPELL_DARK_TOUCHED: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - } else pTarget->CastSpell(pTarget, SPELL_DARK_TOUCHED, true); - } - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!SisterDeath) - { - if (pInstance) - { - Unit* Temp = NULL; - Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_ALYTHESS)); - if (Temp && Temp->isDead()) - { - DoScriptText(YELL_SISTER_ALYTHESS_DEAD, me); - DoCast(me, SPELL_EMPOWER); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - SisterDeath = true; - } - } - } - - if (!UpdateVictim()) - return; - - if (SisterDeath) - { - if (ConflagrationTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_CONFLAGRATION); - ConflagrationTimer = 30000+(rand()%5000); - } - } else ConflagrationTimer -= diff; - } - else - { - if (ShadownovaTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_SHADOW_NOVA); - - if (!SisterDeath) - { - if (pTarget) - DoScriptText(EMOTE_SHADOW_NOVA, me, pTarget); - DoScriptText(YELL_SHADOW_NOVA, me); - } - ShadownovaTimer = 30000+(rand()%5000); - } - } else ShadownovaTimer -=diff; - } - - if (ConfoundingblowTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_CONFOUNDING_BLOW); - ConfoundingblowTimer = 20000 + (rand()%5000); - } - } else ConfoundingblowTimer -=diff; - - if (ShadowimageTimer <= diff) - { - Unit *pTarget = NULL; - Creature* temp = NULL; - for (uint8 i = 0; i<3; ++i) - { - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - temp = DoSpawnCreature(MOB_SHADOW_IMAGE,0,0,0,0,TEMPSUMMON_CORPSE_DESPAWN,10000); - if (temp && pTarget) - { - temp->AddThreat(pTarget,1000000);//don't change target(healers) - temp->AI()->AttackStart(pTarget); - } - } - ShadowimageTimer = 20000; - } else ShadowimageTimer -=diff; - - if (ShadowbladesTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_SHADOW_BLADES); - ShadowbladesTimer = 10000; - } - } else ShadowbladesTimer -=diff; - - if (EnrageTimer < diff && !Enraged) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - DoScriptText(YELL_ENRAGE, me); - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else EnrageTimer -= diff; - - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - HandleTouchedSpells(me->getVictim(), SPELL_DARK_TOUCHED); - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - } -}; - -CreatureAI* GetAI_boss_sacrolash(Creature* pCreature) -{ - return new boss_sacrolashAI (pCreature); -}; - -struct boss_alythessAI : public Scripted_NoMovementAI -{ - boss_alythessAI(Creature *c) : Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); - IntroStepCounter = 10; - } - - ScriptedInstance *pInstance; - - bool SisterDeath; - bool Enraged; - - uint32 IntroStepCounter; - uint32 IntroYellTimer; - - uint32 ConflagrationTimer; - uint32 BlazeTimer; - uint32 PyrogenicsTimer; - uint32 ShadownovaTimer; - uint32 FlamesearTimer; - uint32 EnrageTimer; - - void Reset() - { - Enraged = false; - - if (pInstance) - { - Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); - if (Temp) - if (Temp->isDead()) - { - CAST_CRE(Temp)->Respawn(); - }else - { - if (Temp->getVictim()) - { - me->getThreatManager().addThreat(Temp->getVictim(),0.0f); - } - } - } - - if (!me->isInCombat()) - { - ConflagrationTimer = 45000; - BlazeTimer = 100; - PyrogenicsTimer = 15000; - ShadownovaTimer = 40000; - EnrageTimer = 360000; - FlamesearTimer = 15000; - IntroYellTimer = 10000; - - SisterDeath = false; - } - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * who) - { - DoZoneInCombat(); - - if (pInstance) - { - Unit* Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); - if (Temp && Temp->isAlive() && !(Temp->getVictim())) - CAST_CRE(Temp)->AI()->AttackStart(who); - } - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit *who) - { - if (!me->isInCombat()) - { - Scripted_NoMovementAI::AttackStart(who); - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) - { - if (!me->isInCombat()) - { - DoStartNoMovement(who); - } - } - } - else if (IntroStepCounter == 10 && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 30)) - { - IntroStepCounter = 0; - } - } - - void KilledUnit(Unit * /*victim*/) - { - if (rand()%4 == 0) - { - DoScriptText(RAND(YELL_ALY_KILL_1,YELL_ALY_KILL_2), me); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (SisterDeath) - { - DoScriptText(YELL_ALY_DEAD, me); - - if (pInstance) - pInstance->SetData(DATA_EREDAR_TWINS_EVENT, DONE); - } - else - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - - void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) - { - switch(spell->Id) - { - - case SPELL_BLAZE: - pTarget->CastSpell(pTarget, SPELL_BLAZE_SUMMON, true); - case SPELL_CONFLAGRATION: - case SPELL_FLAME_SEAR: - HandleTouchedSpells(pTarget, SPELL_FLAME_TOUCHED); - break; - case SPELL_SHADOW_NOVA: - HandleTouchedSpells(pTarget, SPELL_DARK_TOUCHED); - break; - } - } - - void HandleTouchedSpells(Unit *pTarget, uint32 TouchedType) - { - switch(TouchedType) - { - case SPELL_FLAME_TOUCHED: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_DARK_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_DARK_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - }else - { - pTarget->CastSpell(pTarget, SPELL_FLAME_TOUCHED, true); - } - } - break; - case SPELL_DARK_TOUCHED: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - } else pTarget->CastSpell(pTarget, SPELL_DARK_TOUCHED, true); - } - break; - } - } - - uint32 IntroStep(uint32 step) - { - Creature* Sacrolash = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_SACROLASH) : 0); - switch (step) - { - case 0: return 0; - case 1: - if (Sacrolash) - DoScriptText(YELL_INTRO_SAC_1, Sacrolash); - return 1000; - case 2: DoScriptText(YELL_INTRO_ALY_2, me); return 1000; - case 3: - if (Sacrolash) - DoScriptText(YELL_INTRO_SAC_3, Sacrolash); - return 2000; - case 4: DoScriptText(YELL_INTRO_ALY_4, me); return 1000; - case 5: - if (Sacrolash) - DoScriptText(YELL_INTRO_SAC_5, Sacrolash); - return 2000; - case 6: DoScriptText(YELL_INTRO_ALY_6, me); return 1000; - case 7: - if (Sacrolash) - DoScriptText(YELL_INTRO_SAC_7, Sacrolash); - return 3000; - case 8: DoScriptText(YELL_INTRO_ALY_8, me); return 900000; - } - return 10000; - } - - void UpdateAI(const uint32 diff) - { - if (IntroStepCounter < 9) - { - if (IntroYellTimer <= diff) - { - IntroYellTimer = IntroStep(++IntroStepCounter); - } else IntroYellTimer -= diff; - } - - if (!SisterDeath) - { - if (pInstance) - { - Unit* Temp = NULL; - Temp = Unit::GetUnit((*me),pInstance->GetData64(DATA_SACROLASH)); - if (Temp && Temp->isDead()) - { - DoScriptText(YELL_SISTER_SACROLASH_DEAD, me); - DoCast(me, SPELL_EMPOWER); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - SisterDeath = true; - } - } - } - if (!me->getVictim()) - { - if (pInstance) - { - Creature* sisiter = Unit::GetCreature((*me),pInstance->GetData64(DATA_SACROLASH)); - if (sisiter && !sisiter->isDead() && sisiter->getVictim()) - { - me->AddThreat(sisiter->getVictim(),0.0f); - DoStartNoMovement(sisiter->getVictim()); - me->Attack(sisiter->getVictim(),false); - } - } - } - - if (!UpdateVictim()) - return; - - if (SisterDeath) - { - if (ShadownovaTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_SHADOW_NOVA); - ShadownovaTimer= 30000+(rand()%5000); - } - } else ShadownovaTimer -=diff; - } - else - { - if (ConflagrationTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_CONFLAGRATION); - ConflagrationTimer = 30000+(rand()%5000); - - if (!SisterDeath) - { - if (pTarget) - DoScriptText(EMOTE_CONFLAGRATION, me, pTarget); - DoScriptText(YELL_CANFLAGRATION, me); - } - - BlazeTimer = 4000; - } - } else ConflagrationTimer -= diff; - } - - if (FlamesearTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_FLAME_SEAR); - FlamesearTimer = 15000; - } - } else FlamesearTimer -=diff; - - if (PyrogenicsTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_PYROGENICS, true); - PyrogenicsTimer = 15000; - } - } else PyrogenicsTimer -= diff; - - if (BlazeTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me->getVictim(), SPELL_BLAZE); - BlazeTimer = 3800; - } - } else BlazeTimer -= diff; - - if (EnrageTimer < diff && !Enraged) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - DoScriptText(YELL_BERSERK, me); - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else EnrageTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_alythess(Creature* pCreature) -{ - return new boss_alythessAI (pCreature); -}; - -struct mob_shadow_imageAI : public ScriptedAI -{ - mob_shadow_imageAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowfuryTimer; - uint32 KillTimer; - uint32 DarkstrikeTimer; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - ShadowfuryTimer = 5000 + (rand()%15000); - DarkstrikeTimer = 3000; - KillTimer = 15000; - } - - void EnterCombat(Unit * /*who*/){} - - void SpellHitTarget(Unit *pTarget,const SpellEntry* spell) - { - switch(spell->Id) - { - - case SPELL_SHADOW_FURY: - case SPELL_DARK_STRIKE: - if (!pTarget->HasAura(SPELL_DARK_FLAME)) - { - if (pTarget->HasAura(SPELL_FLAME_TOUCHED)) - { - pTarget->RemoveAurasDueToSpell(SPELL_FLAME_TOUCHED); - pTarget->CastSpell(pTarget, SPELL_DARK_FLAME, true); - } else pTarget->CastSpell(pTarget,SPELL_DARK_TOUCHED,true); - } - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->HasAura(SPELL_IMAGE_VISUAL)) - DoCast(me, SPELL_IMAGE_VISUAL); - - if (KillTimer <= diff) - { - me->Kill(me); - KillTimer = 9999999; - } else KillTimer -= diff; - - if (!UpdateVictim()) - return; - - if (ShadowfuryTimer <= diff) - { - DoCast(me, SPELL_SHADOW_FURY); - ShadowfuryTimer = 10000; - } else ShadowfuryTimer -=diff; - - if (DarkstrikeTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - DoCast(me->getVictim(), SPELL_DARK_STRIKE); - } - DarkstrikeTimer = 3000; - } else DarkstrikeTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_shadow_image(Creature* pCreature) -{ - return new mob_shadow_imageAI (pCreature); -}; - -void AddSC_boss_eredar_twins() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sacrolash"; - newscript->GetAI = &GetAI_boss_sacrolash; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_alythess"; - newscript->GetAI = &GetAI_boss_alythess; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadow_image"; - newscript->GetAI = &GetAI_mob_shadow_image; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp deleted file mode 100644 index 88ad2dbab11..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_felmyst.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/* Copyright (C) 2009 Trinity -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Felmyst -SD%Complete: 0 -SDComment: -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -enum Yells -{ - YELL_BIRTH = -1580036, - YELL_KILL1 = -1580037, - YELL_KILL2 = -1580038, - YELL_BREATH = -1580039, - YELL_TAKEOFF = -1580040, - YELL_BERSERK = -1580041, - YELL_DEATH = -1580042, - YELL_KALECGOS = -1580043, // after felmyst's death spawned and say this -}; - -enum Spells -{ - //Aura - AURA_SUNWELL_RADIANCE = 45769, - AURA_NOXIOUS_FUMES = 47002, - - //Land phase - SPELL_CLEAVE = 19983, - SPELL_CORROSION = 45866, - SPELL_GAS_NOVA = 45855, - SPELL_ENCAPSULATE_CHANNEL = 45661, - // SPELL_ENCAPSULATE_EFFECT = 45665, - // SPELL_ENCAPSULATE_AOE = 45662, - - //Flight phase - SPELL_VAPOR_SELECT = 45391, // fel to player, force cast 45392, 50000y selete target - SPELL_VAPOR_SUMMON = 45392, // player summon vapor, radius around caster, 5y, - SPELL_VAPOR_FORCE = 45388, // vapor to fel, force cast 45389 - SPELL_VAPOR_CHANNEL = 45389, // fel to vapor, green beam channel - SPELL_VAPOR_TRIGGER = 45411, // linked to 45389, vapor to self, trigger 45410 and 46931 - SPELL_VAPOR_DAMAGE = 46931, // vapor damage, 4000 - SPELL_TRAIL_SUMMON = 45410, // vapor summon trail - SPELL_TRAIL_TRIGGER = 45399, // trail to self, trigger 45402 - SPELL_TRAIL_DAMAGE = 45402, // trail damage, 2000 + 2000 dot - SPELL_DEAD_SUMMON = 45400, // summon blazing dead, 5min - SPELL_DEAD_PASSIVE = 45415, - SPELL_FOG_BREATH = 45495, // fel to self, speed burst - SPELL_FOG_TRIGGER = 45582, // fog to self, trigger 45782 - SPELL_FOG_FORCE = 45782, // fog to player, force cast 45714 - SPELL_FOG_INFORM = 45714, // player let fel cast 45717, script effect - SPELL_FOG_CHARM = 45717, // fel to player - SPELL_FOG_CHARM2 = 45726, // link to 45717 - - SPELL_TRANSFORM_TRIGGER = 44885, // madrigosa to self, trigger 46350 - SPELL_TRANSFORM_VISUAL = 46350, // 46411stun? - SPELL_TRANSFORM_FELMYST = 45068, // become fel - SPELL_FELMYST_SUMMON = 45069, - - //Other - SPELL_BERSERK = 45078, - SPELL_CLOUD_VISUAL = 45212, - SPELL_CLOUD_SUMMON = 45884, -}; - -enum PhaseFelmyst -{ - PHASE_NONE, - PHASE_GROUND, - PHASE_FLIGHT, -}; - -enum EventFelmyst -{ - EVENT_NONE, - EVENT_BERSERK, - - EVENT_CLEAVE, - EVENT_CORROSION, - EVENT_GAS_NOVA, - EVENT_ENCAPSULATE, - EVENT_FLIGHT, - - EVENT_FLIGHT_SEQUENCE, - EVENT_SUMMON_DEAD, - EVENT_SUMMON_FOG, -}; - -struct boss_felmystAI : public ScriptedAI -{ - boss_felmystAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - - // wait for core patch be accepted - /*SpellEntry *TempSpell = GET_SPELL(SPELL_ENCAPSULATE_EFFECT); - if (TempSpell->SpellIconID == 2294) - TempSpell->SpellIconID = 2295; - TempSpell = GET_SPELL(SPELL_VAPOR_TRIGGER); - if ((TempSpell->Attributes & SPELL_ATTR_PASSIVE) == 0) - TempSpell->Attributes |= SPELL_ATTR_PASSIVE; - TempSpell = GET_SPELL(SPELL_FOG_CHARM2); - if ((TempSpell->Attributes & SPELL_ATTR_PASSIVE) == 0) - TempSpell->Attributes |= SPELL_ATTR_PASSIVE;*/ - } - - ScriptedInstance *pInstance; - PhaseFelmyst phase; - EventMap events; - - uint32 uiFlightCount; - uint32 uiBreathCount; - - float breathX, breathY; - - void Reset() - { - phase = PHASE_NONE; - - events.Reset(); - - uiFlightCount = 0; - - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - - DespawnSummons(MOB_VAPOR_TRAIL); - me->setActive(false); - - if (pInstance) - pInstance->SetData(DATA_FELMYST_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - events.ScheduleEvent(EVENT_BERSERK, 600000); - - me->setActive(true); - DoZoneInCombat(); - DoCast(me, AURA_SUNWELL_RADIANCE, true); - DoCast(me, AURA_NOXIOUS_FUMES, true); - EnterPhase(PHASE_GROUND); - - if (pInstance) - pInstance->SetData(DATA_FELMYST_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit *who) - { - if (phase != PHASE_FLIGHT) - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (phase != PHASE_FLIGHT) - ScriptedAI::MoveInLineOfSight(who); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(YELL_KILL1,YELL_KILL2), me); - } - - void JustRespawned() - { - DoScriptText(YELL_BIRTH, me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(YELL_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_FELMYST_EVENT, DONE); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - // workaround for linked aura - /*if (spell->Id == SPELL_VAPOR_FORCE) - { - caster->CastSpell(caster, SPELL_VAPOR_TRIGGER, true); - }*/ - // workaround for mind control - if (spell->Id == SPELL_FOG_INFORM) - { - float x, y, z; - caster->GetPosition(x, y, z); - if (Unit* summon = me->SummonCreature(MOB_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) - { - summon->SetMaxHealth(caster->GetMaxHealth()); - summon->SetHealth(caster->GetMaxHealth()); - summon->CastSpell(summon, SPELL_FOG_CHARM, true); - summon->CastSpell(summon, SPELL_FOG_CHARM2, true); - } - me->DealDamage(caster, caster->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == MOB_DEAD) - { - summon->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); - DoZoneInCombat(summon); - summon->CastSpell(summon, SPELL_DEAD_PASSIVE, true); - } - } - - void MovementInform(uint32, uint32) - { - if (phase == PHASE_FLIGHT) - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); - } - - void DamageTaken(Unit*, uint32 &damage) - { - if (phase != PHASE_GROUND && damage >= me->GetHealth()) - damage = 0; - } - - void EnterPhase(PhaseFelmyst NextPhase) - { - switch(NextPhase) - { - case PHASE_GROUND: - me->CastStop(SPELL_FOG_BREATH); - me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); - me->SetUnitMovementFlags(MOVEMENTFLAG_NONE); - me->SetSpeed(MOVE_RUN, 2.0); - - events.ScheduleEvent(EVENT_CLEAVE, urand(5000, 10000)); - events.ScheduleEvent(EVENT_CORROSION, urand(10000, 20000)); - events.ScheduleEvent(EVENT_GAS_NOVA, urand(15000, 20000)); - events.ScheduleEvent(EVENT_ENCAPSULATE, urand(20000, 25000)); - events.ScheduleEvent(EVENT_FLIGHT, 60000); - break; - case PHASE_FLIGHT: - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1000); - uiFlightCount = 0; - uiBreathCount = 0; - break; - } - phase = NextPhase; - } - - void HandleFlightSequence() - { - switch(uiFlightCount) - { - case 0: - //me->AttackStop(); - me->GetMotionMaster()->Clear(false); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->StopMoving(); - DoScriptText(YELL_TAKEOFF, me); - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 2000); - break; - case 1: - me->GetMotionMaster()->MovePoint(0, me->GetPositionX()+1, me->GetPositionY(), me->GetPositionZ()+10); - break; - case 2: - { - Unit *pTarget = pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); - if (!pTarget) - pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); - - if (!pTarget) - { - EnterEvadeMode(); - return; - } - - Creature* Vapor = me->SummonCreature(MOB_VAPOR, pTarget->GetPositionX()-5+rand()%10, pTarget->GetPositionY()-5+rand()%10, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); - if (Vapor) - { - Vapor->AI()->AttackStart(pTarget); - me->InterruptNonMeleeSpells(false); - DoCast(Vapor, SPELL_VAPOR_CHANNEL, false); // core bug - Vapor->CastSpell(Vapor, SPELL_VAPOR_TRIGGER, true); - } - - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); - break; - } - case 3: - { - DespawnSummons(MOB_VAPOR_TRAIL); - //DoCast(me, SPELL_VAPOR_SELECT); need core support - - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); - if (!pTarget) - pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); - - if (!pTarget) - { - EnterEvadeMode(); - return; - } - - //pTarget->CastSpell(pTarget, SPELL_VAPOR_SUMMON, true); need core support - Creature* pVapor = me->SummonCreature(MOB_VAPOR, pTarget->GetPositionX()-5+rand()%10, pTarget->GetPositionY()-5+rand()%10, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000); - if (pVapor) - { - if (pVapor->AI()) - pVapor->AI()->AttackStart(pTarget); - me->InterruptNonMeleeSpells(false); - DoCast(pVapor, SPELL_VAPOR_CHANNEL, false); // core bug - pVapor->CastSpell(pVapor, SPELL_VAPOR_TRIGGER, true); - } - - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); - break; - } - case 4: - DespawnSummons(MOB_VAPOR_TRAIL); - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); - break; - case 5: - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true); - if (!pTarget) - pTarget = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); - - if (!pTarget) - { - EnterEvadeMode(); - return; - } - - breathX = pTarget->GetPositionX(); - breathY = pTarget->GetPositionY(); - float x, y, z; - pTarget->GetContactPoint(me, x, y, z, 70); - me->GetMotionMaster()->MovePoint(0, x, y, z+10); - break; - } - case 6: - me->SetOrientation(me->GetAngle(breathX, breathY)); - me->StopMoving(); - //DoTextEmote("takes a deep breath.", NULL); - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 10000); - break; - case 7: - { - DoCast(me, SPELL_FOG_BREATH, true); - float x, y, z; - me->GetPosition(x, y, z); - x = 2 * breathX - x; - y = 2 * breathY - y; - me->GetMotionMaster()->MovePoint(0, x, y, z); - events.ScheduleEvent(EVENT_SUMMON_FOG, 1); - break; - } - case 8: - me->CastStop(SPELL_FOG_BREATH); - me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); - ++uiBreathCount; - events.ScheduleEvent(EVENT_FLIGHT_SEQUENCE, 1); - if (uiBreathCount < 3) - uiFlightCount = 4; - break; - case 9: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO)) - DoStartMovement(pTarget); - else - { - EnterEvadeMode(); - return; - } - break; - case 10: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - EnterPhase(PHASE_GROUND); - AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO)); - break; - } - ++uiFlightCount; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (phase == PHASE_FLIGHT && !me->IsInEvadeMode()) - EnterEvadeMode(); - return; - } - - events.Update(diff); - - if (me->IsNonMeleeSpellCasted(false)) - return; - - if (phase == PHASE_GROUND) - { - switch(events.ExecuteEvent()) - { - case EVENT_BERSERK: - DoScriptText(YELL_BERSERK, me); - DoCast(me, SPELL_BERSERK, true); - events.ScheduleEvent(EVENT_BERSERK, 10000); - break; - case EVENT_CLEAVE: - DoCast(me->getVictim(), SPELL_CLEAVE, false); - events.ScheduleEvent(EVENT_CLEAVE, urand(5000,10000)); - break; - case EVENT_CORROSION: - DoCast(me->getVictim(), SPELL_CORROSION, false); - events.ScheduleEvent(EVENT_CORROSION, urand(20000,30000)); - break; - case EVENT_GAS_NOVA: - DoCast(me, SPELL_GAS_NOVA, false); - events.ScheduleEvent(EVENT_GAS_NOVA, urand(20000,25000)); - break; - case EVENT_ENCAPSULATE: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 150, true)) - DoCast(pTarget, SPELL_ENCAPSULATE_CHANNEL, false); - events.ScheduleEvent(EVENT_ENCAPSULATE, urand(25000,30000)); - break; - case EVENT_FLIGHT: - EnterPhase(PHASE_FLIGHT); - break; - default: - DoMeleeAttackIfReady(); - break; - } - } - - if (phase == PHASE_FLIGHT) - { - switch(events.ExecuteEvent()) - { - case EVENT_BERSERK: - DoScriptText(YELL_BERSERK, me); - DoCast(me, SPELL_BERSERK, true); - break; - case EVENT_FLIGHT_SEQUENCE: - HandleFlightSequence(); - break; - case EVENT_SUMMON_FOG: - { - float x, y, z; - me->GetPosition(x, y, z); - me->UpdateGroundPositionZ(x, y, z); - if (Creature *Fog = me->SummonCreature(MOB_VAPOR_TRAIL, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 10000)) - { - Fog->RemoveAurasDueToSpell(SPELL_TRAIL_TRIGGER); - Fog->CastSpell(Fog, SPELL_FOG_TRIGGER, true); - me->CastSpell(Fog, SPELL_FOG_FORCE, true); - } - } - events.ScheduleEvent(EVENT_SUMMON_FOG, 1000); - break; - } - } - } - - void DespawnSummons(uint32 entry) - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllCreaturesOfEntryInRange check(me, entry, 100); - Trinity::CreatureListSearcher searcher(me, templist, check); - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - cell.Visit(pair, cSearcher, *(me->GetMap())); - - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - if (entry == MOB_VAPOR_TRAIL && phase == PHASE_FLIGHT) - { - (*i)->GetPosition(x, y, z); - me->SummonCreature(MOB_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - } - (*i)->SetVisibility(VISIBILITY_OFF); - (*i)->setDeathState(JUST_DIED); - if ((*i)->getDeathState() == CORPSE) - (*i)->RemoveCorpse(); - } - } -}; - -struct mob_felmyst_vaporAI : public ScriptedAI -{ - mob_felmyst_vaporAI(Creature *c) : ScriptedAI(c) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetSpeed(MOVE_RUN, 0.8); - } - void Reset() {} - void EnterCombat(Unit* /*who*/) - { - DoZoneInCombat(); - //DoCast(me, SPELL_VAPOR_FORCE, true); core bug - } - void UpdateAI(const uint32 /*diff*/) - { - if (!me->getVictim()) - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - AttackStart(pTarget); - } -}; - -struct mob_felmyst_trailAI : public ScriptedAI -{ - mob_felmyst_trailAI(Creature *c) : ScriptedAI(c) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_TRAIL_TRIGGER, true); - me->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 0.01); // core bug - } - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_boss_felmyst(Creature* pCreature) -{ - return new boss_felmystAI(pCreature); -} - -CreatureAI* GetAI_mob_felmyst_vapor(Creature* pCreature) -{ - return new mob_felmyst_vaporAI(pCreature); -} - -CreatureAI* GetAI_mob_felmyst_trail(Creature* pCreature) -{ - return new mob_felmyst_trailAI(pCreature); -} - -void AddSC_boss_felmyst() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_felmyst"; - newscript->GetAI = &GetAI_boss_felmyst; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felmyst_vapor"; - newscript->GetAI = &GetAI_mob_felmyst_vapor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_felmyst_trail"; - newscript->GetAI = &GetAI_mob_felmyst_trail; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp deleted file mode 100644 index 146771325eb..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kalecgos.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kalecgos -SD%Complete: 95 -SDComment: -SDCategory: Sunwell_Plateau -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -enum Yells -{ - //Kalecgos dragon form - SAY_EVIL_AGGRO = -1580000, - SAY_EVIL_SPELL1 = -1580001, - SAY_EVIL_SPELL2 = -1580002, - SAY_EVIL_SLAY1 = -1580003, - SAY_EVIL_SLAY2 = -1580004, - SAY_EVIL_ENRAGE = -1580005, - - //Kalecgos humanoid form - SAY_GOOD_AGGRO = -1580006, - SAY_GOOD_NEAR_DEATH = -1580007, - SAY_GOOD_NEAR_DEATH2 = -1580008, - SAY_GOOD_PLRWIN = -1580009, - - //Sathrovarr - SAY_SATH_AGGRO = -1580010, - SAY_SATH_DEATH = -1580011, - SAY_SATH_SPELL1 = -1580012, - SAY_SATH_SPELL2 = -1580013, - SAY_SATH_SLAY1 = -1580014, - SAY_SATH_SLAY2 = -1580015, - SAY_SATH_ENRAGE = -1580016, -}; - -enum Spells -{ - AURA_SUNWELL_RADIANCE = 45769, - AURA_SPECTRAL_EXHAUSTION = 44867, - AURA_SPECTRAL_REALM = 46021, - AURA_SPECTRAL_INVISIBILITY = 44801, - AURA_DEMONIC_VISUAL = 44800, - - SPELL_SPECTRAL_BLAST = 44869, - SPELL_TELEPORT_SPECTRAL = 46019, - SPELL_ARCANE_BUFFET = 45018, - SPELL_FROST_BREATH = 44799, - SPELL_TAIL_LASH = 45122, - - SPELL_BANISH = 44836, - SPELL_TRANSFORM_KALEC = 44670, - SPELL_ENRAGE = 44807, - - SPELL_CORRUPTION_STRIKE = 45029, - SPELL_AGONY_CURSE = 45032, - SPELL_SHADOW_BOLT = 45031, - - SPELL_HEROIC_STRIKE = 45026, - SPELL_REVITALIZE = 45027 -}; - -enum SWPActions -{ - DO_ENRAGE = 1, - DO_BANISH = 2, -}; - -#define GO_FAILED "You are unable to use this currently." - -#define EMOTE_UNABLE_TO_FIND "is unable to find Kalecgos" - -#define FLY_X 1679 -#define FLY_Y 900 -#define FLY_Z 82 - -#define CENTER_X 1705 -#define CENTER_Y 930 -#define RADIUS 30 - -#define DRAGON_REALM_Z 53.079 -#define DEMON_REALM_Z -74.558 - -#define MAX_PLAYERS_IN_SPECTRAL_REALM 0 //over this, teleport object won't work, 0 disables check - -uint32 WildMagic[] = { 44978, 45001, 45002, 45004, 45006, 45010 }; - -struct boss_kalecgosAI : public ScriptedAI -{ - boss_kalecgosAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - SathGUID = 0; - DoorGUID = 0; - bJustReset = false; - me->setActive(true); - SpellEntry *TempSpell = GET_SPELL(SPELL_SPECTRAL_BLAST); - if (TempSpell) - TempSpell->EffectImplicitTargetB[0] = TARGET_UNIT_TARGET_ENEMY; - } - - ScriptedInstance *pInstance; - - uint32 ArcaneBuffetTimer; - uint32 FrostBreathTimer; - uint32 WildMagicTimer; - uint32 SpectralBlastTimer; - uint32 TailLashTimer; - uint32 CheckTimer; - uint32 TalkTimer; - uint32 TalkSequence; - uint32 ResetTimer; - - bool isFriendly; - bool isEnraged; - bool isBanished; - bool bJustReset; - - uint64 SathGUID; - uint64 DoorGUID; - - void Reset() - { - if (pInstance) - { - SathGUID = pInstance->GetData64(DATA_SATHROVARR); - pInstance->SetData(DATA_KALECGOS_EVENT, NOT_STARTED); - } - - if (Creature *Sath = Unit::GetCreature(*me, SathGUID)) - Sath->AI()->EnterEvadeMode(); - - me->setFaction(14); - if (!bJustReset) //first reset at create - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SetVisibility(VISIBILITY_ON); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - } - me->SetHealth(me->GetMaxHealth());//dunno why it does not resets health at evade.. - ArcaneBuffetTimer = 8000; - FrostBreathTimer = 15000; - WildMagicTimer = 10000; - TailLashTimer = 25000; - SpectralBlastTimer = urand(20000,25000); - CheckTimer = 1000; - ResetTimer = 30000; - - TalkTimer = 0; - TalkSequence = 0; - isFriendly = false; - isEnraged = false; - isBanished = false; - } - - void EnterEvadeMode() - { - bJustReset = true; - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - ScriptedAI::EnterEvadeMode(); - } - - void DoAction(const int32 param) - { - switch (param) - { - case DO_ENRAGE: - isEnraged = true; - me->CastSpell(me, SPELL_ENRAGE, true); - break; - case DO_BANISH: - isBanished = true; - me->CastSpell(me, SPELL_BANISH, true); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (TalkTimer) - { - if (!TalkSequence) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(); - ++TalkSequence; - } - if (TalkTimer <= diff) - { - if (isFriendly) - GoodEnding(); - else - BadEnding(); - ++TalkSequence; - } else TalkTimer -= diff; - } - else - { - if (bJustReset) - { - if (ResetTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SetVisibility(VISIBILITY_ON); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - ResetTimer = 10000; - bJustReset = false; - } else ResetTimer -= diff; - return; - } - if (!UpdateVictim()) - return; - - if (CheckTimer <= diff) - { - if (me->GetDistance(CENTER_X, CENTER_Y, DRAGON_REALM_Z) >= 75) - { - me->AI()->EnterEvadeMode(); - return; - } - if (HealthBelowPct(10) && !isEnraged) - { - if (Creature* Sath = Unit::GetCreature(*me, SathGUID)) - Sath->AI()->DoAction(DO_ENRAGE); - DoAction(DO_ENRAGE); - } - if (!isBanished && HealthBelowPct(1)) - { - if (Creature* Sath = Unit::GetCreature(*me, SathGUID)) - { - if (Sath->HasAura(SPELL_BANISH)) - { - Sath->DealDamage(Sath, Sath->GetHealth()); - return; - } - else - DoAction(DO_BANISH); - } - else - { - error_log("TSCR: Didn't find Shathrowar. Kalecgos event reseted."); - EnterEvadeMode(); - return; - } - } - CheckTimer = 1000; - } else CheckTimer -= diff; - - if (ArcaneBuffetTimer <= diff) - { - DoCastAOE(SPELL_ARCANE_BUFFET); - ArcaneBuffetTimer = 8000; - } else ArcaneBuffetTimer -= diff; - - if (FrostBreathTimer <= diff) - { - DoCastAOE(SPELL_FROST_BREATH); - FrostBreathTimer = 15000; - } else FrostBreathTimer -= diff; - - if (TailLashTimer <= diff) - { - DoCastAOE(SPELL_TAIL_LASH); - TailLashTimer = 15000; - } else TailLashTimer -= diff; - - if (WildMagicTimer <= diff) - { - DoCastAOE(WildMagic[rand()%6]); - WildMagicTimer = 20000; - } else WildMagicTimer -= diff; - - if (SpectralBlastTimer <= diff) - { - std::list &m_threatlist = me->getThreatManager().getThreatList(); - std::list targetList; - for (std::list::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) - if ((*itr)->getTarget() && (*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->GetGUID() != me->getVictim()->GetGUID() && !(*itr)->getTarget()->HasAura(AURA_SPECTRAL_EXHAUSTION) && (*itr)->getTarget()->GetPositionZ() > me->GetPositionZ()-5) - targetList.push_back((*itr)->getTarget()); - if (targetList.empty()) - { - SpectralBlastTimer = 1000; - return; - } - std::list::const_iterator i = targetList.begin(); - advance(i, rand()%targetList.size()); - if ((*i)) - { - (*i)->CastSpell((*i), SPELL_SPECTRAL_BLAST,true); - SpectralBlastTimer = 20000+rand()%5000; - } else SpectralBlastTimer = 1000; - } else SpectralBlastTimer -= diff; - - DoMeleeAttackIfReady(); - } - } - - void MoveInLineOfSight(Unit *who) - { - if (bJustReset)//boss is invisible, don't attack - return; - - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius)) - AttackStart(who); - } - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = 0; - } - - void EnterCombat(Unit* /*who*/) - { - me->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_EVIL_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_KALECGOS_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_EVIL_SLAY1,SAY_EVIL_SLAY2), me); - } - - void MovementInform(uint32 type,uint32 /*id*/) - { - if (type != POINT_MOTION_TYPE) - return; - me->SetVisibility(VISIBILITY_OFF); - if (isFriendly) - { - me->setDeathState(JUST_DIED); - - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer) - ((InstanceMap*)me->GetMap())->PermBindAllPlayers(pPlayer); - } - } - } - else - { - me->GetMotionMaster()->MoveTargetedHome(); - TalkTimer = 1000; - } - } - - void GoodEnding() - { - switch(TalkSequence) - { - case 1: - me->setFaction(35); - TalkTimer = 1000; - break; - case 2: - DoScriptText(SAY_GOOD_PLRWIN, me); - TalkTimer = 10000; - break; - case 3: - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); - TalkTimer = 600000; - break; - default: - break; - } - } - - void BadEnding() - { - switch(TalkSequence) - { - case 1: - DoScriptText(SAY_EVIL_ENRAGE, me); - TalkTimer = 3000; - break; - case 2: - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->GetMotionMaster()->MovePoint(0,FLY_X,FLY_Y,FLY_Z); - TalkTimer = 15000; - break; - case 3: - EnterEvadeMode(); - break; - default: - break; - } - } -}; - -struct boss_sathrovarrAI : public ScriptedAI -{ - boss_sathrovarrAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - KalecGUID = 0; - KalecgosGUID = 0; - } - - ScriptedInstance *pInstance; - - uint32 CorruptionStrikeTimer; - uint32 AgonyCurseTimer; - uint32 ShadowBoltTimer; - uint32 CheckTimer; - uint32 ResetThreat; - - uint64 KalecGUID; - uint64 KalecgosGUID; - - bool isEnraged; - bool isBanished; - - void Reset() - { - me->SetHealth(me->GetMaxHealth());//dunno why it does not resets health at evade.. - me->setActive(true); - if (pInstance) - { - KalecgosGUID = pInstance->GetData64(DATA_KALECGOS_DRAGON); - pInstance->SetData(DATA_KALECGOS_EVENT, NOT_STARTED); - } - if (KalecGUID) - { - if (Creature* Kalec = Unit::GetCreature(*me, KalecGUID)) - Kalec->setDeathState(JUST_DIED); - KalecGUID = 0; - } - - ShadowBoltTimer = 7000 + rand()%3 * 1000; - AgonyCurseTimer = 20000; - CorruptionStrikeTimer = 13000; - CheckTimer = 1000; - ResetThreat = 1000; - isEnraged = false; - isBanished = false; - - me->CastSpell(me, AURA_DEMONIC_VISUAL, true); - TeleportAllPlayersBack(); - } - - void EnterCombat(Unit* /*who*/) - { - if (Creature *Kalec = me->SummonCreature(MOB_KALEC, me->GetPositionX() + 10, me->GetPositionY() + 5, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) - { - KalecGUID = Kalec->GetGUID(); - me->CombatStart(Kalec); - me->AddThreat(Kalec, 100.0f); - Kalec->setActive(true); - } - DoScriptText(SAY_SATH_AGGRO, me); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = 0; - } - - void KilledUnit(Unit *pTarget) - { - if (pTarget->GetGUID() == KalecGUID) - { - TeleportAllPlayersBack(); - if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) - { - CAST_AI(boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1; - CAST_AI(boss_kalecgosAI, Kalecgos->AI())->isFriendly = false; - } - EnterEvadeMode(); - return; - } - DoScriptText(RAND(SAY_SATH_SLAY1,SAY_SATH_SLAY2), me); - } - - void JustDied(Unit * /*killer*/) - { - DoScriptText(SAY_SATH_DEATH, me); - me->GetMap()->CreatureRelocation(me, me->GetPositionX(), me->GetPositionY(), DRAGON_REALM_Z, me->GetOrientation()); - TeleportAllPlayersBack(); - if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) - { - CAST_AI(boss_kalecgosAI, Kalecgos->AI())->TalkTimer = 1; - CAST_AI(boss_kalecgosAI, Kalecgos->AI())->isFriendly = true; - } - - if (pInstance) - pInstance->SetData(DATA_KALECGOS_EVENT, DONE); - } - - void TeleportAllPlayersBack() - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) return; - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->GetPositionZ() <= DRAGON_REALM_Z-5) - { - i->getSource()->RemoveAura(AURA_SPECTRAL_REALM); - i->getSource()->TeleportTo(me->GetMap()->GetId(),i->getSource()->GetPositionX(),i->getSource()->GetPositionY(),DRAGON_REALM_Z+5,i->getSource()->GetOrientation()); - } - } - } - - void DoAction(const int32 param) - { - switch (param) - { - case DO_ENRAGE: - isEnraged = true; - me->CastSpell(me, SPELL_ENRAGE, true); - break; - case DO_BANISH: - isBanished = true; - me->CastSpell(me, SPELL_BANISH, true); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) - me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); - if (!UpdateVictim()) - return; - - if (CheckTimer <= diff) - { - Creature *Kalec = Unit::GetCreature(*me, KalecGUID); - if (!Kalec || (Kalec && !Kalec->isAlive())) - { - if (Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) - Kalecgos->AI()->EnterEvadeMode(); - return; - } - if (HealthBelowPct(10) && !isEnraged) - { - if (Creature* Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) - Kalecgos->AI()->DoAction(DO_ENRAGE); - DoAction(DO_ENRAGE); - } - Creature *Kalecgos = Unit::GetCreature(*me, KalecgosGUID); - if (Kalecgos) - { - if (!Kalecgos->isInCombat()) - { - me->AI()->EnterEvadeMode(); - return; - } - } - if (!isBanished && HealthBelowPct(1)) - { - if (Kalecgos) - { - if (Kalecgos->HasAura(SPELL_BANISH)) - { - me->DealDamage(me, me->GetHealth()); - return; - } - else - DoAction(DO_BANISH); - } - else - { - me->MonsterTextEmote(EMOTE_UNABLE_TO_FIND, NULL); - EnterEvadeMode(); - return; - } - } - CheckTimer = 1000; - } else CheckTimer -= diff; - - if (ResetThreat <= diff) - { - for (std::list::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) - { - if (Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - { - if (pUnit->GetPositionZ() > me->GetPositionZ()+5) - { - me->getThreatManager().modifyThreatPercent(pUnit,-100); - } - } - } - ResetThreat = 1000; - } else ResetThreat -= diff; - - if (ShadowBoltTimer <= diff) - { - if (!(rand()%5))DoScriptText(SAY_SATH_SPELL1, me); - DoCast(me, SPELL_SHADOW_BOLT); - ShadowBoltTimer = 7000+(rand()%3000); - } else ShadowBoltTimer -= diff; - - if (AgonyCurseTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (!pTarget) pTarget = me->getVictim(); - DoCast(pTarget, SPELL_AGONY_CURSE); - AgonyCurseTimer = 20000; - } else AgonyCurseTimer -= diff; - - if (CorruptionStrikeTimer <= diff) - { - if (!(rand()%5))DoScriptText(SAY_SATH_SPELL2, me); - DoCast(me->getVictim(), SPELL_CORRUPTION_STRIKE); - CorruptionStrikeTimer = 13000; - } else CorruptionStrikeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_kalecAI : public ScriptedAI -{ - ScriptedInstance *pInstance; - - uint32 RevitalizeTimer; - uint32 HeroicStrikeTimer; - uint32 YellTimer; - uint32 YellSequence; - - uint64 SathGUID; - - bool isEnraged; // if demon is enraged - - boss_kalecAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() - { - if (pInstance) - SathGUID = pInstance->GetData64(DATA_SATHROVARR); - - RevitalizeTimer = 5000; - HeroicStrikeTimer = 3000; - YellTimer = 5000; - YellSequence = 0; - - isEnraged = false; - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != SathGUID) - damage = 0; - else if (isEnraged) - damage *= 3; - } - - void UpdateAI(const uint32 diff) - { - if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) - me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); - if (!UpdateVictim()) - return; - - if (YellTimer <= diff) - { - switch(YellSequence) - { - case 0: - DoScriptText(SAY_GOOD_AGGRO, me); - ++YellSequence; - break; - case 1: - if (HealthBelowPct(50)) - { - DoScriptText(SAY_GOOD_NEAR_DEATH, me); - ++YellSequence; - } - break; - case 2: - if (HealthBelowPct(10)) - { - DoScriptText(SAY_GOOD_NEAR_DEATH2, me); - ++YellSequence; - } - break; - default: - break; - } - YellTimer = 5000; - } - - if (RevitalizeTimer <= diff) - { - DoCast(me, SPELL_REVITALIZE); - RevitalizeTimer = 5000; - } else RevitalizeTimer -= diff; - - if (HeroicStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HEROIC_STRIKE); - HeroicStrikeTimer = 2000; - } else HeroicStrikeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -bool GOkalecgos_teleporter(Player* pPlayer, GameObject* pGo) -{ - uint32 SpectralPlayers = 0; - Map* pMap = pGo->GetMap(); - if (!pMap->IsDungeon()) return true; - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->GetPositionZ() < DEMON_REALM_Z + 5) - ++SpectralPlayers; - } - if (pPlayer->HasAura(AURA_SPECTRAL_EXHAUSTION) || (MAX_PLAYERS_IN_SPECTRAL_REALM && SpectralPlayers >= MAX_PLAYERS_IN_SPECTRAL_REALM)) - pPlayer->GetSession()->SendNotification(GO_FAILED); - else - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_SPECTRAL, true); - return true; -} - -CreatureAI* GetAI_boss_kalecgos(Creature* pCreature) -{ - return new boss_kalecgosAI (pCreature); -} - -CreatureAI* GetAI_boss_Sathrovarr(Creature* pCreature) -{ - return new boss_sathrovarrAI (pCreature); -} - -CreatureAI* GetAI_boss_kalec(Creature* pCreature) -{ - return new boss_kalecAI (pCreature); -} - -void AddSC_boss_kalecgos() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kalecgos"; - newscript->GetAI = &GetAI_boss_kalecgos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_sathrovarr"; - newscript->GetAI = &GetAI_boss_Sathrovarr; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_kalec"; - newscript->GetAI = &GetAI_boss_kalec; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "kalecgos_teleporter"; - newscript->pGOHello = &GOkalecgos_teleporter; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp deleted file mode 100644 index f1c3a769b28..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_kiljaeden.cpp +++ /dev/null @@ -1,1408 +0,0 @@ -/* Copyright (C) 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kiljaeden -SD%Complete: 80 -SDComment: Sinister Reflection Model, Armageddon Visual, SAY_KJ_SHADOWSPIKE3, Emote, End Sequence -SDCategory: Sunwell_Plateau -EndScriptData */ - -//TODO rewrite Armageddon - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" -#include - -/*** Speech and sounds***/ -enum Yells -{ - // These are used throughout Sunwell and Magisters(?). Players can hear this while running through the instances. - SAY_KJ_OFFCOMBAT1 = -1580066, - SAY_KJ_OFFCOMBAT2 = -1580067, - SAY_KJ_OFFCOMBAT3 = -1580068, - SAY_KJ_OFFCOMBAT4 = -1580069, - SAY_KJ_OFFCOMBAT5 = -1580070, - - // Encounter speech and sounds - SAY_KJ_EMERGE = -1580071, - SAY_KJ_SLAY1 = -1580072, - SAY_KJ_SLAY2 = -1580073, - SAY_KJ_REFLECTION1 = -1580074, - SAY_KJ_REFLECTION2 = -1580075, - SAY_KJ_DARKNESS1 = -1580076, - SAY_KJ_DARKNESS2 = -1580077, - SAY_KJ_DARKNESS3 = -1580078, - SAY_KJ_PHASE3 = -1580079, - SAY_KJ_PHASE4 = -1580080, - SAY_KJ_PHASE5 = -1580081, - SAY_KJ_DEATH = -1580093, - EMOTE_KJ_DARKNESS = -1580094, - - /*** Kalecgos - Anveena speech at the beginning of Phase 5; Anveena's sacrifice ***/ - SAY_KALECGOS_AWAKEN = -1580082, - SAY_ANVEENA_IMPRISONED = -1580083, - SAY_KALECGOS_LETGO = -1580084, - SAY_ANVEENA_LOST = -1580085, - SAY_KALECGOS_FOCUS = -1580086, - SAY_ANVEENA_KALEC = -1580087, - SAY_KALECGOS_FATE = -1580088, - SAY_ANVEENA_GOODBYE = -1580089, - SAY_KALECGOS_GOODBYE = -1580090, - SAY_KALECGOS_ENCOURAGE = -1580091, - - /*** Kalecgos says throughout the fight ***/ - SAY_KALECGOS_JOIN = -1580092, - SAY_KALEC_ORB_READY1 = -1580095, - SAY_KALEC_ORB_READY2 = -1580096, - SAY_KALEC_ORB_READY3 = -1580097, - SAY_KALEC_ORB_READY4 = -1580098 -}; - -/*** Spells used during the encounter ***/ -enum Spells -{ - /* Hand of the Deceiver's spells and cosmetics */ - SPELL_SHADOW_BOLT_VOLLEY = 45770, // ~30 yard range Shadow Bolt Volley for ~2k(?) damage - SPELL_SHADOW_INFUSION = 45772, // They gain this at 20% - Immunity to Stun/Silence and makes them look angry! - SPELL_FELFIRE_PORTAL = 46875, // Creates a portal that spawns Felfire Fiends (LIVE FOR THE SWARM!1 FOR THE OVERMIND!) - SPELL_SHADOW_CHANNELING = 46757, // Channeling animation out of combat - - /* Volatile Felfire Fiend's spells */ - SPELL_FELFIRE_FISSION = 45779, // Felfire Fiends explode when they die or get close to target. - - /* Kil'Jaeden's spells and cosmetics */ - SPELL_TRANS = 23188, // Surprisingly, this seems to be the right spell.. (Where is it used?) - SPELL_REBIRTH = 44200, // Emerge from the Sunwell - SPELL_SOUL_FLAY = 45442, // 9k Shadow damage over 3 seconds. Spammed throughout all the fight. - SPELL_SOUL_FLAY_SLOW = 47106, - SPELL_LEGION_LIGHTNING = 45664, // Chain Lightning, 4 targets, ~3k Shadow damage, 1.5k mana burn - SPELL_FIRE_BLOOM = 45641, // Places a debuff on 5 raid members, which causes them to deal 2k Fire damage to nearby allies and selves. MIGHT NOT WORK - SPELL_DESTROY_ALL_DRAKES = 46707, // when he use it? - - SPELL_SINISTER_REFLECTION = 45785, // Summon shadow copies of 5 raid members that fight against KJ's enemies//dont work - // 45892 // right one for SPELL_SINISTER_REFLECTION but no EffectScriptEffect - SPELL_COPY_WEAPON = 41055, // } - SPELL_COPY_WEAPON2 = 41054, // } - SPELL_COPY_OFFHAND = 45206, // }- Spells used in Sinister Reflection creation - SPELL_COPY_OFFHAND_WEAPON = 45205, // } - - SPELL_SHADOW_SPIKE = 46680, // Bombard random raid members with Shadow Spikes (Very similar to Void Reaver orbs) - SPELL_FLAME_DART = 45737, // Bombards the raid with flames every 3(?) seconds - SPELL_DARKNESS_OF_A_THOUSAND_SOULS = 46605, // Begins a 8-second channeling, after which he will deal 50'000 damage to the raid - SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE = 45657, - - /* Armageddon spells wrong visual */ - SPELL_ARMAGEDDON_TRIGGER = 45909, // Meteor spell trigger missile should cast Creature on himself - SPELL_ARMAGEDDON_VISUAL = 45911, // Does the hellfire visual to indicate where the meteor missle lands - SPELL_ARMAGEDDON_VISUAL2 = 45914, // Does the light visual to indicate where the meteor missle lands - SPELL_ARMAGEDDON_VISUAL3 = 24207, // This shouldn't correct but same as seen on the movie - SPELL_ARMAGEDDON_SUMMON_TRIGGER = 45921, // Summons the triggers that cast the spells on himself need random target select - SPELL_ARMAGEDDON_DAMAGE = 45915, // This does the area damage - - /* Shield Orb Spells*/ - SPELL_SHADOW_BOLT = 45680, //45679 would be correct but triggers to often //TODO fix console error - - /* Anveena's spells and cosmetics (Or, generally, everything that has "Anveena" in name) */ - SPELL_ANVEENA_PRISON = 46367, // She hovers locked within a bubble - SPELL_ANVEENA_ENERGY_DRAIN = 46410, // Sunwell energy glow animation (Control mob uses this) - SPELL_SACRIFICE_OF_ANVEENA = 46474, // This is cast on Kil'Jaeden when Anveena sacrifices herself into the Sunwell - - /* Sinister Reflection Spells */ - SPELL_SR_CURSE_OF_AGONY = 46190, - SPELL_SR_SHADOW_BOLT = 47076, - - SPELL_SR_EARTH_SHOCK = 47071, - - SPELL_SR_FIREBALL = 47074, - - SPELL_SR_HEMORRHAGE = 45897, - - SPELL_SR_HOLY_SHOCK = 38921, - SPELL_SR_HAMMER_OF_JUSTICE = 37369, - - SPELL_SR_HOLY_SMITE = 47077, - SPELL_SR_RENEW = 47079, - - SPELL_SR_SHOOT = 16496, - SPELL_SR_MULTI_SHOT = 48098, - SPELL_SR_WING_CLIP = 40652, - - SPELL_SR_WHIRLWIND = 17207, - - SPELL_SR_MOONFIRE = 47072, - //SPELL_SR_PLAGU STRIKE = 58843, Dk Spell! - - /*** Other Spells (used by players, etc) ***/ - SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT = 45839, // Possess the blue dragon from the orb to help the raid. - SPELL_ENTROPIUS_BODY = 46819, // Visual for Entropius at the Epilogue - SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated -}; - -/*** Error messages ***/ -#define ERROR_KJ_NOT_SUMMONED "TSCR ERROR: Unable to summon Kil'Jaeden for some reason" - -/*** Others ***/ -#define FLOOR_Z 28.050388 -#define SHIELD_ORB_Z 45.000 - -enum Phase -{ - PHASE_DECEIVERS = 1, // Fight 3 adds - PHASE_NORMAL = 2, // Kil'Jaeden emerges from the sunwell - PHASE_DARKNESS = 3, // At 85%, he gains few abilities; Kalecgos joins the fight - PHASE_ARMAGEDDON = 4, // At 55%, he gains even more abilities - PHASE_SACRIFICE = 5, // At 25%, Anveena sacrifices herself into the Sunwell; at this point he becomes enraged and has *significally* shorter cooldowns. -}; - -//Timers -enum KilJaedenTimers -{ - TIMER_SPEECH = 0, - - //Phase 2 Timer - TIMER_SOUL_FLAY = 1, - TIMER_LEGION_LIGHTNING = 2, - TIMER_FIRE_BLOOM = 3, - TIMER_SUMMON_SHILEDORB = 4, - - //Phase 3 Timer - TIMER_SHADOW_SPIKE = 5, - TIMER_FLAME_DART = 6, - TIMER_DARKNESS = 7, - TIMER_ORBS_EMPOWER = 8, - - //Phase 4 Timer - TIMER_ARMAGEDDON = 9 -}; - -// Locations of the Hand of Deceiver adds -Position DeceiverLocations[3]= -{ - {1682.045, 631.299, 5.936}, - {1684.099, 618.848, 0.589}, - {1694.170, 612.272, 1.416}, -}; - -// Locations, where Shield Orbs will spawn -float ShieldOrbLocations[4][2]= -{ - {1698.900, 627.870}, // middle pont of Sunwell - {12, 3.14}, // First one spawns northeast of KJ - {12, 3.14/0.7}, // Second one spawns southeast - {12, 3.14*3.8} // Third one spawns (?) -}; - -struct Speech -{ - int32 textid; - uint32 pCreature, timer; -}; - -// Timers -static Speech Speeches[]= -{ - //Kil Phase 1 -> Phase 2 - {SAY_KJ_EMERGE, DATA_KILJAEDEN, 0}, - {SAY_KALECGOS_JOIN, DATA_KALECGOS_KJ, 26000}, - //Kil Phase 2 -> Phase 3 - {SAY_KALECGOS_AWAKEN, DATA_KALECGOS_KJ, 10000}, - {SAY_ANVEENA_IMPRISONED, DATA_ANVEENA, 5000}, - {SAY_KJ_PHASE3, DATA_KILJAEDEN, 5000}, - //Kil Phase 3 -> Phase 4 - {SAY_KALECGOS_LETGO, DATA_KALECGOS_KJ, 10000}, - {SAY_ANVEENA_LOST, DATA_ANVEENA, 8000}, - {SAY_KJ_PHASE4, DATA_KILJAEDEN, 7000}, - //Kil Phase 4 -> Phase 5 - {SAY_KALECGOS_FOCUS, DATA_KALECGOS_KJ, 4000}, - {SAY_ANVEENA_KALEC, DATA_ANVEENA, 11000}, - {SAY_KALECGOS_FATE, DATA_KALECGOS_KJ, 2000}, - {SAY_ANVEENA_GOODBYE, DATA_ANVEENA, 6000}, - {SAY_KJ_PHASE5, DATA_KILJAEDEN, 5500}, - - // use in End sequence? - {SAY_KALECGOS_GOODBYE, DATA_KALECGOS_KJ, 12000}, -}; - -//AI for Kalecgos -struct boss_kalecgos_kjAI : public ScriptedAI -{ - boss_kalecgos_kjAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint8 OrbsEmpowered; - uint8 EmpowerCount; - - void Reset() - { - OrbsEmpowered = 0; - EmpowerCount = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setActive(true); - - for (uint8 i = 0; i < 4; ++i) - if (GameObject* pOrb = GetOrb(i)) - pOrb->SetGoType(GAMEOBJECT_TYPE_BUTTON); - } - - GameObject* GetOrb(int32 index) - { - if (!pInstance) - return NULL; - - switch(index) - { - case 0: - return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1)); - case 1: - return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2)); - case 2: - return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3)); - case 3: - return pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4)); - } - - return NULL; - } - - void ResetOrbs() - { - me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); - for (uint8 i = 0; i < 4; ++i) - if (GameObject* pOrb = GetOrb(i)) - pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 0); - } - - void EmpowerOrb(bool all) - { - GameObject* pOrbEmpowered = GetOrb(OrbsEmpowered); - if (!pOrbEmpowered) - return; - - if (all) - { - me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); - for (uint8 i = 0; i < 4; ++i) - { - if (GameObject* pOrb = GetOrb(i)) - { - pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); - pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 35); - pOrb->setActive(true); - pOrb->Refresh(); - } - } - DoScriptText(SAY_KALECGOS_ENCOURAGE, me); - } - else - { - if (GameObject* pOrb = GetOrb(urand(0,3))) - { - pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); - pOrb->SetUInt32Value(GAMEOBJECT_FACTION, 35); - pOrb->setActive(true); - pOrb->Refresh(); - - OrbsEmpowered = (OrbsEmpowered+1)%4; - - ++EmpowerCount; - switch(EmpowerCount) - { - case 1: DoScriptText(SAY_KALEC_ORB_READY1, me); break; - case 2: DoScriptText(SAY_KALEC_ORB_READY2, me); break; - case 3: DoScriptText(SAY_KALEC_ORB_READY3, me); break; - case 4: DoScriptText(SAY_KALEC_ORB_READY4, me); break; - } - } - } - } - - void UpdateAI(const uint32 diff) - { - } - - void SetRingOfBlueFlames() - { - me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); - for (uint8 i = 0; i < 4; ++i) - { - if (GameObject* pOrb = GetOrb(i)) - { - if (pOrb->GetUInt32Value(GAMEOBJECT_FACTION) == 35) - { - pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); - pOrb->setActive(true); - pOrb->Refresh(); - } - } - } - } -}; - -CreatureAI* GetAI_boss_kalecgos_kj(Creature* pCreature) -{ - return new boss_kalecgos_kjAI (pCreature); -} - -bool GOHello_go_orb_of_the_blue_flight(Player* pPlayer, GameObject* pGo) -{ - if (pGo->GetUInt32Value(GAMEOBJECT_FACTION) == 35) - { - ScriptedInstance* pInstance = pGo->GetInstanceData(); - pPlayer->SummonCreature(CREATURE_POWER_OF_THE_BLUE_DRAGONFLIGHT, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 121000); - pPlayer->CastSpell(pPlayer, SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT, false); - pGo->SetUInt32Value(GAMEOBJECT_FACTION, 0); - - if (Creature* pKalec = Unit::GetCreature(*pPlayer, pInstance->GetData64(DATA_KALECGOS_KJ))) - CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->SetRingOfBlueFlames(); - - pGo->Refresh(); - } - return true; -} - -//AI for Kil'jaeden Event Controller -struct mob_kiljaeden_controllerAI : public Scripted_NoMovementAI -{ - mob_kiljaeden_controllerAI(Creature* c) : Scripted_NoMovementAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - SummonList summons; - - bool bSummonedDeceivers; - bool bKiljaedenDeath; - - uint32 uiRandomSayTimer; - uint32 phase; - uint8 deceiverDeathCount; - - void InitializeAI() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->addUnitState(UNIT_STAT_STUNNED); - - ScriptedAI::InitializeAI(); - } - - void Reset() - { - phase = PHASE_DECEIVERS; - - if (Creature* pKalecKJ = Unit::GetCreature((*me), pInstance->GetData64(DATA_KALECGOS_KJ))) - CAST_AI(boss_kalecgos_kjAI, pKalecKJ->AI())->ResetOrbs(); - deceiverDeathCount = 0; - bSummonedDeceivers = false; - bKiljaedenDeath = false; - uiRandomSayTimer = 30000; - summons.DespawnAll(); - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - case CREATURE_HAND_OF_THE_DECEIVER: - summoned->CastSpell(summoned, SPELL_SHADOW_CHANNELING, false); - break; - case CREATURE_ANVEENA: - summoned->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT | MOVEMENTFLAG_LEVITATING); - summoned->CastSpell(summoned, SPELL_ANVEENA_PRISON, true); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - break; - case CREATURE_KILJAEDEN: - summoned->CastSpell(summoned, SPELL_REBIRTH, false); - summoned->AddThreat(me->getVictim(), 1.0f); - break; - } - summons.Summon(summoned); - } - - void UpdateAI(const uint32 diff) - { - if (uiRandomSayTimer < diff) - { - if (pInstance && pInstance->GetData(DATA_MURU_EVENT) != DONE && pInstance->GetData(DATA_KILJAEDEN_EVENT) == NOT_STARTED) - DoScriptText(RAND(SAY_KJ_OFFCOMBAT1,SAY_KJ_OFFCOMBAT2,SAY_KJ_OFFCOMBAT3,SAY_KJ_OFFCOMBAT4,SAY_KJ_OFFCOMBAT5), me); - uiRandomSayTimer = 30000; - } else uiRandomSayTimer -= diff; - - if (!bSummonedDeceivers) - { - for (uint8 i = 0; i < 3; ++i) - me->SummonCreature(CREATURE_HAND_OF_THE_DECEIVER, DeceiverLocations[i], TEMPSUMMON_DEAD_DESPAWN, 0); - - DoSpawnCreature(CREATURE_ANVEENA, 0, 0, 40, 0, TEMPSUMMON_DEAD_DESPAWN, 0); - DoCast(me, SPELL_ANVEENA_ENERGY_DRAIN); - bSummonedDeceivers = true; - } - - if (deceiverDeathCount > 2 && phase == PHASE_DECEIVERS) - { - me->RemoveAurasDueToSpell(SPELL_ANVEENA_ENERGY_DRAIN); - phase = PHASE_NORMAL; - DoSpawnCreature(CREATURE_KILJAEDEN, 0, 0,0, 0, TEMPSUMMON_MANUAL_DESPAWN, 0); - } - } -}; - -CreatureAI* GetAI_mob_kiljaeden_controller(Creature* pCreature) -{ - return new mob_kiljaeden_controllerAI (pCreature); -} - -//AI for Kil'jaeden -struct boss_kiljaedenAI : public Scripted_NoMovementAI -{ - boss_kiljaedenAI(Creature* c) : Scripted_NoMovementAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - SummonList summons; - - uint8 Phase; - uint8 ActiveTimers; - uint32 SpeechTimer; - - uint32 Timer[10]; - uint32 WaitTimer; - uint8 speechCount; - uint8 speechPhaseEnd; - - /* Boolean */ - bool IsInDarkness; - bool TimerIsDeactivated[10]; - bool IsWaiting; - bool OrbActivated; - bool SpeechBegins; - - void InitializeAI() - { - Scripted_NoMovementAI::InitializeAI(); - } - - void Reset() - { - TimerIsDeactivated[TIMER_SPEECH] = false; - Timer[TIMER_SPEECH] = 0; - - //Phase 2 Timer - Timer[TIMER_SOUL_FLAY] = 11000; - Timer[TIMER_LEGION_LIGHTNING] = 30000; - Timer[TIMER_FIRE_BLOOM] = 20000; - Timer[TIMER_SUMMON_SHILEDORB] = 35000; - - //Phase 3 Timer - Timer[TIMER_SHADOW_SPIKE] = 4000; - Timer[TIMER_FLAME_DART] = 3000; - Timer[TIMER_DARKNESS] = 45000; - Timer[TIMER_ORBS_EMPOWER] = 35000; - - //Phase 4 Timer - Timer[TIMER_ARMAGEDDON] = 2000; - - ActiveTimers = 5; - WaitTimer = 0; - speechCount = 0; - SpeechTimer = 0; - - Phase = PHASE_NORMAL; - - IsInDarkness = false; - IsWaiting = false; - OrbActivated = false; - SpeechBegins = true; - - if (pInstance) - { - if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ))) - pKalec->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); - } - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 12); - ChangeTimers(false, 0); - summons.DespawnAll(); - } - - void ChangeTimers(bool status, uint32 WTimer) - { - for (uint8 i = 1; i < ActiveTimers; ++i) - TimerIsDeactivated[i] = status; - - if (WTimer > 0) - { - IsWaiting = true; - WaitTimer = WTimer; - } - - if (OrbActivated) - TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true; - if (Timer[TIMER_SHADOW_SPIKE] == 0) - TimerIsDeactivated[TIMER_SHADOW_SPIKE] = true; - if (Phase == PHASE_SACRIFICE) - TimerIsDeactivated[TIMER_SUMMON_SHILEDORB] = true; - } - - void JustSummoned(Creature* summoned) - { - if (summoned->GetEntry() == CREATURE_ARMAGEDDON_TARGET) - { - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - // summoned->SetVisibility(VISIBILITY_OFF); //with this we cant see the armageddon visuals - } - else - summoned->SetLevel(me->getLevel()); - - summoned->setFaction(me->getFaction()); - summons.Summon(summoned); - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_KJ_DEATH, me); - summons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_KILJAEDEN_EVENT, DONE); - } - - void KilledUnit(Unit* victim) - { - DoScriptText(RAND(SAY_KJ_SLAY1,SAY_KJ_SLAY2), me); - } - - void EnterEvadeMode() - { - Scripted_NoMovementAI::EnterEvadeMode(); - summons.DespawnAll(); - - // Reset the controller - if (pInstance) - { - if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) - CAST_AI(mob_kiljaeden_controllerAI, pControl->AI())->Reset(); - } - } - - void EnterCombat(Unit* who) - { - DoZoneInCombat(); - } - - void EnterNextPhase() - { - SpeechBegins = true; - OrbActivated = false; - ChangeTimers(true, 0);//stop every cast Shadow spike will reactivate em all - TimerIsDeactivated[TIMER_SHADOW_SPIKE] = false; - Timer[TIMER_SHADOW_SPIKE] = 100; - // empowered orbs before darkness - Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(10000,40000); - Timer[TIMER_ORBS_EMPOWER] = (Phase == PHASE_SACRIFICE) ? 10000 : 5000; - } - - void CastSinisterReflection() - { - DoScriptText(RAND(SAY_KJ_REFLECTION1,SAY_KJ_REFLECTION2), me); - for (uint8 i = 0; i < 4; ++i) - { - float x,y,z; - Unit *pTarget; - for (uint8 z = 0; z < 6; ++z) - { - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0))break; - } - if (pTarget) - { - pTarget->GetPosition(x,y,z); - if (Creature* pSinisterReflection = me->SummonCreature(CREATURE_SINISTER_REFLECTION, x,y,z,0, TEMPSUMMON_CORPSE_DESPAWN, 0)) - { - pSinisterReflection->SetDisplayId(pTarget->GetDisplayId()); - pSinisterReflection->AI()->AttackStart(pTarget); - } - } - } - } - - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim() || Phase < PHASE_NORMAL) - return; - - if (IsWaiting) - { - if (WaitTimer <= diff) - { - IsWaiting = false; - ChangeTimers(false, 0); - } else WaitTimer -= diff; - } - - for (uint8 t = 0; t < ActiveTimers; ++t) - { - if (Timer[t] < diff && !TimerIsDeactivated[t]) - { - switch(t) - { - case TIMER_SPEECH: - if (SpeechBegins) - { - SpeechBegins=false; - switch(Phase) - { - case PHASE_NORMAL: - speechPhaseEnd=1; - break; - case PHASE_DARKNESS: - speechPhaseEnd=4; - break; - case PHASE_ARMAGEDDON: - speechPhaseEnd=7; - break; - case PHASE_SACRIFICE: - speechPhaseEnd=12; - break; - } - } - if (Speeches[speechCount].timer < SpeechTimer) - { - SpeechTimer = 0; - if (Creature* pSpeechCreature = Unit::GetCreature(*me, pInstance->GetData64(Speeches[speechCount].pCreature))) - DoScriptText(Speeches[speechCount].textid, pSpeechCreature); - if (speechCount == 12) - if (Creature* pAnveena = Unit::GetCreature(*me, pInstance->GetData64(DATA_ANVEENA))) - pAnveena->CastSpell(me, SPELL_SACRIFICE_OF_ANVEENA, false); - // ChangeTimers(true, 10000); // Kil should do an emote while screaming without attacking for 10 seconds - if (speechCount == speechPhaseEnd) - TimerIsDeactivated[TIMER_SPEECH]=true; - speechCount++; - } - SpeechTimer += diff; - break; - case TIMER_SOUL_FLAY: - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me->getVictim(), SPELL_SOUL_FLAY_SLOW, false); - DoCast(me->getVictim(), SPELL_SOUL_FLAY, false); - Timer[TIMER_SOUL_FLAY] = 3500; - } - break; - case TIMER_LEGION_LIGHTNING: - if (!me->IsNonMeleeSpellCasted(false)) - { - Unit* pRandomPlayer; - - me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY); - for (uint8 z = 0; z < 6; ++z) - { - pRandomPlayer = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!pRandomPlayer->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) - break; - } - - if (pRandomPlayer) - DoCast(pRandomPlayer, SPELL_LEGION_LIGHTNING, false); - else - error_log("try to cast SPELL_LEGION_LIGHTNING on invalid target"); - - Timer[TIMER_LEGION_LIGHTNING] = (Phase == PHASE_SACRIFICE) ? 18000 : 30000; // 18 seconds in PHASE_SACRIFICE - Timer[TIMER_SOUL_FLAY] = 2500; - } - break; - case TIMER_FIRE_BLOOM: - if (!me->IsNonMeleeSpellCasted(false)) - { - me->RemoveAurasDueToSpell(SPELL_SOUL_FLAY); - DoCastAOE(SPELL_FIRE_BLOOM, false); - Timer[TIMER_FIRE_BLOOM] = (Phase == PHASE_SACRIFICE) ? 25000 : 40000; // 25 seconds in PHASE_SACRIFICE - Timer[TIMER_SOUL_FLAY] = 1000; - } - break; - case TIMER_SUMMON_SHILEDORB: - for (uint8 i = 1; i < Phase; ++i) - { - float sx, sy; - sx = ShieldOrbLocations[0][0] + sin(ShieldOrbLocations[i][0]); - sy = ShieldOrbLocations[0][1] + sin(ShieldOrbLocations[i][1]); - me->SummonCreature(CREATURE_SHIELD_ORB, sx, sy, SHIELD_ORB_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); - } - Timer[TIMER_SUMMON_SHILEDORB] = urand(30000,60000); // 30-60seconds cooldown - Timer[TIMER_SOUL_FLAY] = 2000; - break; - case TIMER_SHADOW_SPIKE: //Phase 3 - if (!me->IsNonMeleeSpellCasted(false)) - { - CastSinisterReflection(); - DoCastAOE(SPELL_SHADOW_SPIKE, false); - ChangeTimers(true, 30000); - Timer[TIMER_SHADOW_SPIKE] = 0; - TimerIsDeactivated[TIMER_SPEECH] = false; - } - break; - case TIMER_FLAME_DART: //Phase 3 - DoCastAOE(SPELL_FLAME_DART, false); - Timer[TIMER_FLAME_DART] = 3000; //TODO Timer - break; - case TIMER_DARKNESS: //Phase 3 - if (!me->IsNonMeleeSpellCasted(false)) - { - // Begins to channel for 8 seconds, then deals 50'000 damage to all raid members. - if (!IsInDarkness) - { - DoScriptText(EMOTE_KJ_DARKNESS, me); - DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS, false); - ChangeTimers(true, 9000); - Timer[TIMER_DARKNESS] = 8750; - TimerIsDeactivated[TIMER_DARKNESS] = false; - if (Phase == PHASE_SACRIFICE) - TimerIsDeactivated[TIMER_ARMAGEDDON] = false; - IsInDarkness = true; - } - else - { - Timer[TIMER_DARKNESS] = (Phase == PHASE_SACRIFICE) ? 15000 : urand(40000,70000); - IsInDarkness = false; - DoCastAOE(SPELL_DARKNESS_OF_A_THOUSAND_SOULS_DAMAGE); - DoScriptText(RAND(SAY_KJ_DARKNESS1,SAY_KJ_DARKNESS2,SAY_KJ_DARKNESS3), me); - } - Timer[TIMER_SOUL_FLAY] = 9000; - } - break; - case TIMER_ORBS_EMPOWER: //Phase 3 - if (Creature* pKalec = Unit::GetCreature(*me, pInstance->GetData64(DATA_KALECGOS_KJ))) - { - switch (Phase) - { - case PHASE_SACRIFICE: - CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(true); - break; - default: - CAST_AI(boss_kalecgos_kjAI, pKalec->AI())->EmpowerOrb(false); - break; - } - } - OrbActivated = true; - TimerIsDeactivated[TIMER_ORBS_EMPOWER] = true; - break; - case TIMER_ARMAGEDDON: //Phase 4 - Unit *pTarget; - for (uint8 z = 0; z < 6; ++z) - { - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!pTarget->HasAura(SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT,0)) break; - } - if (pTarget) - { - float x, y, z; - pTarget->GetPosition(x, y, z); - me->SummonCreature(CREATURE_ARMAGEDDON_TARGET, x,y,z,0, TEMPSUMMON_TIMED_DESPAWN,15000); - } - Timer[TIMER_ARMAGEDDON] = 2000; // No, I'm not kidding - break; - } - } - } - DoMeleeAttackIfReady(); - //Time runs over! - for (uint8 i = 0; i < ActiveTimers; ++i) - if (!TimerIsDeactivated[i]) - { - Timer[i] -= diff; - if (((int32)Timer[i]) < 0) Timer[i] = 0; - } - - //Phase 3 - if (Phase <= PHASE_NORMAL && !IsInDarkness) - { - if (Phase == PHASE_NORMAL && HealthBelowPct(85)) - { - Phase = PHASE_DARKNESS; - ActiveTimers = 9; - EnterNextPhase(); - } - else return; - } - - //Phase 4 - if (Phase <= PHASE_DARKNESS && !IsInDarkness) - { - if (Phase == PHASE_DARKNESS && HealthBelowPct(55)) - { - Phase = PHASE_ARMAGEDDON; - ActiveTimers = 10; - EnterNextPhase(); - } - else return; - } - - //Phase 5 specific spells all we can - if (Phase <= PHASE_ARMAGEDDON && !IsInDarkness) - { - if (Phase == PHASE_ARMAGEDDON && HealthBelowPct(25)) - { - Phase = PHASE_SACRIFICE; - EnterNextPhase(); - } - else return; - } - } -}; - -CreatureAI* GetAI_boss_kiljaeden(Creature* pCreature) -{ - return new boss_kiljaedenAI (pCreature); -} - -//AI for Hand of the Deceiver -struct mob_hand_of_the_deceiverAI : public ScriptedAI -{ - mob_hand_of_the_deceiverAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ShadowBoltVolleyTimer; - uint32 FelfirePortalTimer; - - void Reset() - { - // TODO: Timers! - ShadowBoltVolleyTimer = urand(8000,14000); // So they don't all cast it in the same moment. - FelfirePortalTimer = 20000; - if (pInstance) - pInstance->SetData(DATA_KILJAEDEN_EVENT, NOT_STARTED); - } - - void JustSummoned(Creature* summoned) - { - summoned->setFaction(me->getFaction()); - summoned->SetLevel(me->getLevel()); - } - - void EnterCombat(Unit* who) - { - if (pInstance) - { - pInstance->SetData(DATA_KILJAEDEN_EVENT, IN_PROGRESS); - if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) - pControl->AddThreat(who, 1.0f); - } - me->InterruptNonMeleeSpells(true); - } - - void JustDied(Unit* killer) - { - if (!pInstance) - return; - - if (Creature* pControl = Unit::GetCreature(*me, pInstance->GetData64(DATA_KILJAEDEN_CONTROLLER))) - ++(CAST_AI(mob_kiljaeden_controllerAI, pControl->AI())->deceiverDeathCount); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - DoCast(me, SPELL_SHADOW_CHANNELING); - - if (!UpdateVictim()) - return; - - // Gain Shadow Infusion at 20% health - if (HealthBelowPct(20) && !me->HasAura(SPELL_SHADOW_INFUSION, 0)) - DoCast(me, SPELL_SHADOW_INFUSION, true); - - // Shadow Bolt Volley - Shoots Shadow Bolts at all enemies within 30 yards, for ~2k Shadow damage. - if (ShadowBoltVolleyTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); - ShadowBoltVolleyTimer = 12000; - } - else - ShadowBoltVolleyTimer -= diff; - - // Felfire Portal - Creatres a portal, that spawns Volatile Felfire Fiends, which do suicide bombing. - if (FelfirePortalTimer <= diff) - { - if (Creature* pPortal = DoSpawnCreature(CREATURE_FELFIRE_PORTAL, 0, 0,0, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) - { - std::list::iterator itr; - for (itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) - { - Unit* pUnit = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pUnit) - pPortal->AddThreat(pUnit, 1.0f); - } - } - FelfirePortalTimer = 20000; - } else FelfirePortalTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_hand_of_the_deceiver(Creature* pCreature) -{ - return new mob_hand_of_the_deceiverAI (pCreature); -} - -//AI for Felfire Portal -struct mob_felfire_portalAI : public Scripted_NoMovementAI -{ - mob_felfire_portalAI(Creature* c) : Scripted_NoMovementAI(c) {} - - uint32 uiSpawnFiendTimer; - - void Reset() - { - uiSpawnFiendTimer = 5000; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); - } - - void JustSummoned(Creature* summoned) - { - summoned->setFaction(me->getFaction()); - summoned->SetLevel(me->getLevel()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiSpawnFiendTimer <= diff) - { - if (Creature* pFiend = DoSpawnCreature(CREATURE_VOLATILE_FELFIRE_FIEND, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) - pFiend->AddThreat(SelectUnit(SELECT_TARGET_RANDOM,0), 100000.0f); - uiSpawnFiendTimer = urand(4000,8000); - } else uiSpawnFiendTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_felfire_portal(Creature* pCreature) -{ - return new mob_felfire_portalAI (pCreature); -} - -//AI for Felfire Fiend -struct mob_volatile_felfire_fiendAI : public ScriptedAI -{ - mob_volatile_felfire_fiendAI(Creature* c) : ScriptedAI(c) {} - - uint32 uiExplodeTimer; - - bool bLockedTarget; - - void Reset() - { - uiExplodeTimer = 2000; - bLockedTarget = false; - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage > me->GetHealth()) - DoCast(me, SPELL_FELFIRE_FISSION, true); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!bLockedTarget) - { - me->AddThreat(me->getVictim(), 10000000.0f); - bLockedTarget = true; - } - - if (uiExplodeTimer) - { - if (uiExplodeTimer <= diff) - uiExplodeTimer = 0; - else uiExplodeTimer -= diff; - } - else if (me->IsWithinDistInMap(me->getVictim(), 3)) // Explode if it's close enough to it's target - { - DoCast(me->getVictim(), SPELL_FELFIRE_FISSION); - me->Kill(me); - } - } -}; - -CreatureAI* GetAI_mob_volatile_felfire_fiend(Creature* pCreature) -{ - return new mob_volatile_felfire_fiendAI (pCreature); -} - -//AI for Armageddon target -struct mob_armageddonAI : public Scripted_NoMovementAI -{ - mob_armageddonAI(Creature* c) : Scripted_NoMovementAI(c) {} - - uint8 spell; - uint32 uiTimer; - - void Reset() - { - spell = 0; - uiTimer = 0; - } - - void UpdateAI(const uint32 diff) - { - if (uiTimer <= diff) - { - switch(spell) - { - case 0: - DoCast(me, SPELL_ARMAGEDDON_VISUAL, true); - ++spell; - break; - case 1: - DoCast(me, SPELL_ARMAGEDDON_VISUAL2, true); - uiTimer = 9000; - ++spell; - break; - case 2: - DoCast(me, SPELL_ARMAGEDDON_TRIGGER, true); - ++spell; - uiTimer = 5000; - break; - case 3: - me->Kill(me); - me->RemoveCorpse(); - break; - } - } else uiTimer -=diff; - } -}; - -CreatureAI* GetAI_mob_armageddon(Creature* pCreature) -{ - return new mob_armageddonAI (pCreature); -} - -//AI for Shield Orbs -struct mob_shield_orbAI : public ScriptedAI -{ - mob_shield_orbAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bPointReached; - bool bClockwise; - uint32 uiTimer; - uint32 uiCheckTimer; - float x, y, r, c, mx, my; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - bPointReached = true; - uiTimer = urand(500,1000); - uiCheckTimer = 1000; - r = 17; - c = 0; - mx = ShieldOrbLocations[0][0]; - my = ShieldOrbLocations[0][1]; - bClockwise = urand(0,1); - } - - void UpdateAI(const uint32 diff) - { - if (bPointReached) - { - if (bClockwise) - { - y = my - r * sin(c); - x = mx - r * cos(c); - } - else - { - y = my + r * sin(c); - x = mx + r * cos(c); - } - bPointReached = false; - uiCheckTimer = 1000; - me->GetMotionMaster()->MovePoint(1,x, y, SHIELD_ORB_Z); - c += M_PI/32; - if (c >= 2*M_PI) c = 0; - } - else - { - if (uiCheckTimer <= diff) - { - DoTeleportTo(x,y,SHIELD_ORB_Z); - bPointReached = true; - } - else uiCheckTimer -= diff; - } - - if (uiTimer <= diff) - { - if (Unit* random = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0)) - DoCast(random, SPELL_SHADOW_BOLT, false); - uiTimer = urand(500,1000); - } else uiTimer -= diff; - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - bPointReached = true; - } -}; - -CreatureAI* GetAI_mob_shield_orb(Creature* pCreature) -{ - return new mob_shield_orbAI (pCreature); -} - -//AI for Sinister Reflection -struct mob_sinster_reflectionAI : public ScriptedAI -{ - mob_sinster_reflectionAI(Creature* c) : ScriptedAI(c) {} - - uint8 victimClass; - uint32 uiTimer[3]; - - void Reset() - { - uiTimer[0] = 0; - uiTimer[1] = 0; - uiTimer[2] = 0; - victimClass = 0; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if ((victimClass == 0) && me->getVictim()) - { - victimClass = me->getVictim()->getClass(); - switch (victimClass) - { - case CLASS_DRUID: - break; - case CLASS_HUNTER: - break; - case CLASS_MAGE: - break; - case CLASS_WARLOCK: - break; - case CLASS_WARRIOR: - me->SetCanDualWield(true); - break; - case CLASS_PALADIN: - break; - case CLASS_PRIEST: - break; - case CLASS_SHAMAN: - me->SetCanDualWield(true); - break; - case CLASS_ROGUE: - me->SetCanDualWield(true); - break; - } - } - - switch(victimClass) { - case CLASS_DRUID: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_MOONFIRE, false); - uiTimer[1] = urand(2000,4000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_HUNTER: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_MULTI_SHOT, false); - uiTimer[1] = urand(8000,10000); - } - if (uiTimer[2] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_SHOOT, false); - uiTimer[2] = urand(4000,6000); - } - if (me->IsWithinMeleeRange(me->getVictim(), 6)) - { - if (uiTimer[0] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_MULTI_SHOT, false); - uiTimer[0] = urand(6000,8000); - } - DoMeleeAttackIfReady(); - } - break; - case CLASS_MAGE: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_FIREBALL, false); - uiTimer[1] = urand(2000,4000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_WARLOCK: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_SHADOW_BOLT, false); - uiTimer[1] = urand(3000,5000); - } - if (uiTimer[2] <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_SR_CURSE_OF_AGONY, true); - uiTimer[2] = urand(2000,4000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_WARRIOR: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_WHIRLWIND, false); - uiTimer[1] = urand(9000,11000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_PALADIN: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_HAMMER_OF_JUSTICE, false); - uiTimer[1] = urand(6000,8000); - } - if (uiTimer[2] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_HOLY_SHOCK, false); - uiTimer[2] = urand(2000,4000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_PRIEST: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_HOLY_SMITE, false); - uiTimer[1] = urand(4000,6000); - } - if (uiTimer[2] <= diff) - { - DoCast(me, SPELL_SR_RENEW, false); - uiTimer[2] = urand(6000,8000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_SHAMAN: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_EARTH_SHOCK, false); - uiTimer[1] = urand(4000,6000); - } - DoMeleeAttackIfReady(); - break; - case CLASS_ROGUE: - if (uiTimer[1] <= diff) - { - DoCast(me->getVictim(), SPELL_SR_HEMORRHAGE, true); - uiTimer[1] = urand(4000,6000); - } - DoMeleeAttackIfReady(); - break; - } - debug_log("Sinister-Timer"); - for (uint8 i = 0; i < 3; ++i) - uiTimer[i] -= diff; - } -}; - -CreatureAI* GetAI_mob_sinster_reflection(Creature* pCreature) -{ - return new mob_sinster_reflectionAI (pCreature); -} - -void AddSC_boss_kiljaeden() -{ - Script* newscript; - - newscript = new Script; - newscript->pGOHello = &GOHello_go_orb_of_the_blue_flight; - newscript->Name = "go_orb_of_the_blue_flight"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_kalecgos_kj; - newscript->Name = "boss_kalecgos_kj"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_boss_kiljaeden; - newscript->Name = "boss_kiljaeden"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_kiljaeden_controller; - newscript->Name = "mob_kiljaeden_controller"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_hand_of_the_deceiver; - newscript->Name = "mob_hand_of_the_deceiver"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_felfire_portal; - newscript->Name = "mob_felfire_portal"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_volatile_felfire_fiend; - newscript->Name = "mob_volatile_felfire_fiend"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_armageddon; - newscript->Name = "mob_armageddon"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_shield_orb; - newscript->Name = "mob_shield_orb"; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->GetAI = &GetAI_mob_sinster_reflection; - newscript->Name = "mob_sinster_reflection"; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp deleted file mode 100644 index 9dca453ade6..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/boss_muru.cpp +++ /dev/null @@ -1,640 +0,0 @@ -/* Copyright (C) 2009 Trinity -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Muru -SD%Complete: 80 -SDComment: all sounds, black hole effect triggers to often (46228) -*/ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -// Muru & Entropius's spells -enum Spells -{ - SPELL_ENRAGE = 26662, - - // Muru's spells - SPELL_NEGATIVE_ENERGY = 46009, //(this trigger 46008) - SPELL_DARKNESS = 45999, - SPELL_OPEN_ALL_PORTALS = 46177, - SPELL_OPEN_PORTAL = 45977, - SPELL_OPEN_PORTAL_2 = 45976, - SPELL_SUMMON_BERSERKER = 46037, - SPELL_SUMNON_FURY_MAGE = 46038, - SPELL_SUMMON_VOID_SENTINEL = 45988, - SPELL_SUMMON_ENTROPIUS = 46217, - - // Entropius's spells - SPELL_DARKNESS_E = 46269, - SPELL_BLACKHOLE = 46282, - SPELL_NEGATIVE_ENERGY_E = 46284, - SPELL_ENTROPIUS_SPAWN = 46223, - - // Shadowsword Berserker's spells - SPELL_FLURRY = 46160, - SPELL_DUAL_WIELD = 29651, - - // Shadowsword Fury Mage's spells - SPELL_FEL_FIREBALL = 46101, - SPELL_SPELL_FURY = 46102, - - // Void Sentinel's spells - SPELL_SHADOW_PULSE = 46087, - SPELL_VOID_BLAST = 46161, - - // Void Spawn's spells - SPELL_SHADOW_BOLT_VOLLEY = 46082, - - //Dark Fiend Spells - SPELL_DARKFIEND_AOE = 45944, - SPELL_DARKFIEND_VISUAL = 45936, - SPELL_DARKFIEND_SKIN = 45934, - - //Black Hole Spells - SPELL_BLACKHOLE_SPAWN = 46242, - SPELL_BLACKHOLE_GROW = 46228 -}; - -enum BossTimers{ - TIMER_DARKNESS = 0, - TIMER_HUMANOIDES = 1, - TIMER_PHASE = 2, - TIMER_SENTINEL = 3 -}; - -float DarkFiends[8][4] = -{ - {1819.9, 609.80, 69.74, 1.94}, - {1829.39, 617.89, 69.73, 2.61}, - {1801.98, 633.62, 69.74, 5.71}, - {1830.88, 629.99, 69.73, 3.52}, - {1800.38, 621.41, 69.74, 0.22}, - {1808.3 , 612.45, 69.73, 1.02}, - {1823.9 , 639.69, 69.74, 4.12}, - {1811.85, 640.46, 69.73, 4.97} -}; - -float Humanoides[6][5] = -{ - {CREATURE_FURY_MAGE, 1780.16, 666.83, 71.19, 5.21}, - {CREATURE_FURY_MAGE, 1847.93, 600.30, 71.30, 2.57}, - {CREATURE_BERSERKER, 1779.97, 660.64, 71.19, 5.28}, - {CREATURE_BERSERKER, 1786.2 , 661.01, 71.19, 4.51}, - {CREATURE_BERSERKER, 1845.17, 602.63, 71.28, 2.43}, - {CREATURE_BERSERKER, 1842.91, 599.93, 71.23, 2.44} -}; - -uint32 EnrageTimer = 600000; -struct boss_entropiusAI : public ScriptedAI -{ - boss_entropiusAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - SummonList Summons; - - uint32 BlackHoleSummonTimer; - - void Reset() - { - BlackHoleSummonTimer = 15000; - DoCastAOE(SPELL_NEGATIVE_ENERGY_E, false); - - Summons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoCastAOE(SPELL_NEGATIVE_ENERGY_E, true); - DoCast(me, SPELL_ENTROPIUS_SPAWN, false); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - case CREATURE_DARK_FIENDS: - summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false); - break; - case CREATURE_DARKNESS: - summoned->addUnitState(UNIT_STAT_STUNNED); - float x,y,z,o; - summoned->GetHomePosition(x,y,z,o); - me->SummonCreature(CREATURE_DARK_FIENDS, x,y,z,o, TEMPSUMMON_CORPSE_DESPAWN, 0); - break; - } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); - Summons.Summon(summoned); - } - - void JustDied(Unit* /*killer*/) - { - Summons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (EnrageTimer < diff && !me->HasAura(SPELL_ENRAGE, 0)) - { - DoCast(me, SPELL_ENRAGE, false); - } else EnrageTimer -= diff; - - if (BlackHoleSummonTimer <= diff) - { - Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!random) - return; - - DoCast(random, SPELL_DARKNESS_E, false); - - random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (!random) - return; - - random->CastSpell(random, SPELL_BLACKHOLE, false); - BlackHoleSummonTimer = 15000; - } else BlackHoleSummonTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_entropius(Creature* pCreature) -{ - return new boss_entropiusAI (pCreature); -} - -struct boss_muruAI : public Scripted_NoMovementAI -{ - boss_muruAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - SummonList Summons; - - uint8 Phase; - uint32 Timer[4]; - - bool DarkFiend; - - void Reset() - { - DarkFiend = false; - Phase = 1; - - EnrageTimer = 600000; - Timer[TIMER_DARKNESS] = 45000; - Timer[TIMER_HUMANOIDES] = 10000; - Timer[TIMER_PHASE] = 2000; - Timer[TIMER_SENTINEL] = 31500; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - Summons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoCastAOE(SPELL_NEGATIVE_ENERGY,false); - - if (pInstance) - pInstance->SetData(DATA_MURU_EVENT, IN_PROGRESS); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage > me->GetHealth() && Phase == 1) - { - damage = 0; - Phase = 2; - me->RemoveAllAuras(); - DoCast(me, SPELL_OPEN_ALL_PORTALS, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - if (Phase > 1 && Phase < 4) - damage = 0; - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - case BOSS_ENTROPIUS: - me->SetVisibility(VISIBILITY_OFF); - break; - case CREATURE_DARK_FIENDS: - summoned->CastSpell(summoned,SPELL_DARKFIEND_VISUAL,false); - break; - } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM,0, 50, true)); - Summons.Summon(summoned); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Phase == 3) - { - if (Timer[TIMER_PHASE] <= diff) - { - if (!pInstance) - return; - switch(pInstance->GetData(DATA_MURU_EVENT)) - { - case NOT_STARTED: - Reset(); - break; - case DONE: - Phase = 4; - me->DisappearAndDie(); - break; - } - Timer[TIMER_PHASE] = 3000; - } else Timer[TIMER_PHASE] -= diff; - return; - } - - if (EnrageTimer < diff && !me->HasAura(SPELL_ENRAGE, 0)) - { - DoCast(me, SPELL_ENRAGE, false); - } else EnrageTimer -= diff; - - for (uint8 i = 0; i < 4; ++i) - { - if (Timer[i] <= diff) - { - switch(i) - { - case TIMER_DARKNESS: - if (!DarkFiend) - { - DoCastAOE(SPELL_DARKNESS, false); - Timer[TIMER_DARKNESS] = 3000; - DarkFiend = true; - } - else - { - DarkFiend = false; - for (uint8 i = 0; i < 8; ++i) - me->SummonCreature(CREATURE_DARK_FIENDS,DarkFiends[i][0],DarkFiends[i][1],DarkFiends[i][2], DarkFiends[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); - Timer[TIMER_DARKNESS] = 42000; - } - break; - case TIMER_HUMANOIDES: - for (uint8 i = 0; i < 6; ++i) - me->SummonCreature(Humanoides[i][0],Humanoides[i][1],Humanoides[i][2],Humanoides[i][3], Humanoides[i][4], TEMPSUMMON_CORPSE_DESPAWN, 0); - Timer[TIMER_HUMANOIDES] = 60000; - break; - case TIMER_PHASE: - me->RemoveAllAuras(); - DoCast(me, SPELL_SUMMON_ENTROPIUS, false); - Timer[TIMER_PHASE] = 3000; - Phase = 3; - return; - case TIMER_SENTINEL: - DoCastAOE(SPELL_OPEN_PORTAL_2, false); - Timer[TIMER_SENTINEL] = 30000; - break; - } - break; - } - } - - //Timer - for (uint8 i = 0; i < 4; ++i) - { - if (i != TIMER_PHASE)Timer[i] -= diff; - else if (Phase == 2) Timer[i] -= diff; - } - } -}; - -CreatureAI* GetAI_boss_muru(Creature* pCreature) -{ - return new boss_muruAI (pCreature); -} - -struct npc_muru_portalAI : public Scripted_NoMovementAI -{ - npc_muru_portalAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - SummonList Summons; - - bool SummonSentinel; - bool InAction; - - uint32 SummonTimer; - - void Reset() - { - SummonTimer = 5000; - - InAction = false; - SummonSentinel = false; - - me->addUnitState(UNIT_STAT_STUNNED); - - Summons.DespawnAll(); - } - - void JustSummoned(Creature* summoned) - { - if (pInstance) - if (Player* Target = Unit::GetPlayer(pInstance->GetData64(DATA_PLAYER_GUID))) - summoned->AI()->AttackStart(Target); - - Summons.Summon(summoned); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry* Spell) - { - float x,y,z,o; - me->GetHomePosition(x,y,z,o); - DoTeleportTo(x,y,z); - InAction = true; - switch(Spell->Id) - { - case SPELL_OPEN_ALL_PORTALS: - DoCastAOE(SPELL_OPEN_PORTAL, false); - break; - case SPELL_OPEN_PORTAL_2: - DoCastAOE(SPELL_OPEN_PORTAL, false); - SummonSentinel = true; - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!SummonSentinel) - { - if (InAction && pInstance && pInstance->GetData(DATA_MURU_EVENT) == NOT_STARTED) - Reset(); - return; - } - if (SummonTimer <= diff) - { - DoCastAOE(SPELL_SUMMON_VOID_SENTINEL, false); - SummonTimer = 5000; - SummonSentinel = false; - } else SummonTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_muru_portal(Creature* pCreature) -{ - return new npc_muru_portalAI (pCreature); -} - -struct npc_dark_fiendAI : public ScriptedAI -{ - npc_dark_fiendAI(Creature *c) : ScriptedAI(c) {} - - uint32 WaitTimer; - bool InAction; - - void Reset() - { - WaitTimer = 2000; - InAction = false; - - me->addUnitState(UNIT_STAT_STUNNED); - } - - void SpellHit(Unit* /*caster*/, const SpellEntry* Spell) - { - for (uint8 i = 0; i < 3; ++i) - if (Spell->Effect[i] == 38) - me->DisappearAndDie(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (WaitTimer <= diff) - { - if (!InAction) - { - me->clearUnitState(UNIT_STAT_STUNNED); - DoCastAOE(SPELL_DARKFIEND_SKIN, false); - AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)); - InAction = true; - WaitTimer = 500; - } - else - { - - if (me->IsWithinDist(me->getVictim(), 5)) - { - DoCastAOE(SPELL_DARKFIEND_AOE, false); - me->DisappearAndDie(); - } - WaitTimer = 500; - } - } else WaitTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_dark_fiend(Creature* pCreature) -{ - return new npc_dark_fiendAI (pCreature); -} - -struct npc_void_sentinelAI : public ScriptedAI -{ - npc_void_sentinelAI(Creature *c) : ScriptedAI(c){} - - uint32 PulseTimer; - uint32 VoidBlastTimer; - - void Reset() - { - PulseTimer = 3000; - VoidBlastTimer = 45000; //is this a correct timer? - - float x,y,z,o; - me->GetHomePosition(x,y,z,o); - DoTeleportTo(x,y,71); - } - - void JustDied(Unit* /*killer*/) - { - for (uint8 i = 0; i < 8; ++i) - me->SummonCreature(CREATURE_VOID_SPAWN, me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(), rand()%6, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (PulseTimer <= diff) - { - DoCastAOE(SPELL_SHADOW_PULSE, true); - PulseTimer = 3000; - } else PulseTimer -= diff; - - if (VoidBlastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_VOID_BLAST, false); - VoidBlastTimer = 45000; - } else VoidBlastTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_void_sentinel(Creature* pCreature) -{ - return new npc_void_sentinelAI (pCreature); -} - -struct npc_blackholeAI : public ScriptedAI -{ - npc_blackholeAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 DespawnTimer; - uint32 SpellTimer; - uint8 Phase; - uint8 NeedForAHack; - - void Reset() - { - DespawnTimer = 15000; - SpellTimer = 5000; - Phase = 0; - - me->addUnitState(UNIT_STAT_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_SPAWN, true); - } - - void UpdateAI(const uint32 diff) - { - if (SpellTimer <= diff) - { - Unit* Victim = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_PLAYER_GUID) : 0); - switch (NeedForAHack) - { - case 0: - me->clearUnitState(UNIT_STAT_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_GROW, false); - if (Victim) - AttackStart(Victim); - SpellTimer = 700; - NeedForAHack = 2; - break; - case 1: - me->AddAura(SPELL_BLACKHOLE_GROW, me); - NeedForAHack = 2; - SpellTimer = 600; - break; - case 2: - SpellTimer = 400; - NeedForAHack = 3; - me->RemoveAura(SPELL_BLACKHOLE_GROW, 1); - break; - case 3: - SpellTimer = urand(400,900); - NeedForAHack = 1; - if (Unit* Temp = me->getVictim()) - { - if (Temp->GetPositionZ() > 73 && Victim) - AttackStart(Victim); - } else - return; - } - } else SpellTimer -= diff; - - if (DespawnTimer <= diff) - me->DisappearAndDie(); - else DespawnTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_blackhole(Creature* pCreature) -{ - return new npc_blackholeAI (pCreature); -} - -void AddSC_boss_muru() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_muru"; - newscript->GetAI = &GetAI_boss_muru; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_entropius"; - newscript->GetAI = &GetAI_boss_entropius; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_muru_portal"; - newscript->GetAI = &GetAI_npc_muru_portal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_dark_fiend"; - newscript->GetAI = &GetAI_npc_dark_fiend; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_void_sentinel"; - newscript->GetAI = &GetAI_npc_void_sentinel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_blackhole"; - newscript->GetAI = &GetAI_npc_blackhole; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp deleted file mode 100644 index 94b7bf4b735..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/instance_sunwell_plateau.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -/* ScriptData -SDName: Instance_Sunwell_Plateau -SD%Complete: 25 -SDComment: VERIFY SCRIPT -SDCategory: Sunwell_Plateau -EndScriptData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -#define MAX_ENCOUNTER 6 - -/* Sunwell Plateau: -0 - Kalecgos and Sathrovarr -1 - Brutallus -2 - Felmyst -3 - Eredar Twins (Alythess and Sacrolash) -4 - M'uru -5 - Kil'Jaeden -*/ - -struct instance_sunwell_plateau : public ScriptedInstance -{ - instance_sunwell_plateau(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - /** Creatures **/ - uint64 Kalecgos_Dragon; - uint64 Kalecgos_Human; - uint64 Sathrovarr; - uint64 Brutallus; - uint64 Madrigosa; - uint64 Felmyst; - uint64 Alythess; - uint64 Sacrolash; - uint64 Muru; - uint64 KilJaeden; - uint64 KilJaedenController; - uint64 Anveena; - uint64 KalecgosKJ; - uint32 SpectralPlayers; - - /** GameObjects **/ - uint64 ForceField; // Kalecgos Encounter - uint64 KalecgosWall[2]; - uint64 FireBarrier; // Felmysts Encounter - uint64 MurusGate[2]; // Murus Encounter - - /*** Misc ***/ - uint32 SpectralRealmTimer; - std::vector SpectralRealmList; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - /*** Creatures ***/ - Kalecgos_Dragon = 0; - Kalecgos_Human = 0; - Sathrovarr = 0; - Brutallus = 0; - Madrigosa = 0; - Felmyst = 0; - Alythess = 0; - Sacrolash = 0; - Muru = 0; - KilJaeden = 0; - KilJaedenController = 0; - Anveena = 0; - KalecgosKJ = 0; - SpectralPlayers = 0; - - /*** GameObjects ***/ - ForceField = 0; - FireBarrier = 0; - MurusGate[0] = 0; - MurusGate[1] = 0; - KalecgosWall[0] = 0; - KalecgosWall[1] = 0; - - /*** Misc ***/ - SpectralRealmTimer = 5000; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* plr = itr->getSource(); - if (plr && !plr->HasAura(45839,0)) - return plr; - } - } - - debug_log("TSCR: Instance Sunwell Plateau: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 24850: Kalecgos_Dragon = pCreature->GetGUID(); break; - case 24891: Kalecgos_Human = pCreature->GetGUID(); break; - case 24892: Sathrovarr = pCreature->GetGUID(); break; - case 24882: Brutallus = pCreature->GetGUID(); break; - case 24895: Madrigosa = pCreature->GetGUID(); break; - case 25038: Felmyst = pCreature->GetGUID(); break; - case 25166: Alythess = pCreature->GetGUID(); break; - case 25165: Sacrolash = pCreature->GetGUID(); break; - case 25741: Muru = pCreature->GetGUID(); break; - case 25315: KilJaeden = pCreature->GetGUID(); break; - case 25608: KilJaedenController = pCreature->GetGUID(); break; - case 26046: Anveena = pCreature->GetGUID(); break; - case 25319: KalecgosKJ = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 188421: ForceField = pGo->GetGUID(); break; - case 188523: KalecgosWall[0] = pGo->GetGUID(); break; - case 188524: KalecgosWall[0] = pGo->GetGUID(); break; - case 188075: - if (m_auiEncounter[2] == DONE) - HandleGameObject(NULL, true, pGo); - FireBarrier = pGo->GetGUID(); - break; - case 187990: MurusGate[0] = pGo->GetGUID(); break; - case 188118: - if (m_auiEncounter[4] == DONE) - HandleGameObject(NULL, true, pGo); - MurusGate[1]= pGo->GetGUID(); - break; - } - } - - uint32 GetData(uint32 id) - { - switch(id) - { - case DATA_KALECGOS_EVENT: return m_auiEncounter[0]; - case DATA_BRUTALLUS_EVENT: return m_auiEncounter[1]; - case DATA_FELMYST_EVENT: return m_auiEncounter[2]; - case DATA_EREDAR_TWINS_EVENT: return m_auiEncounter[3]; - case DATA_MURU_EVENT: return m_auiEncounter[4]; - case DATA_KILJAEDEN_EVENT: return m_auiEncounter[5]; - } - return 0; - } - - uint64 GetData64(uint32 id) - { - switch(id) - { - case DATA_KALECGOS_DRAGON: return Kalecgos_Dragon; - case DATA_KALECGOS_HUMAN: return Kalecgos_Human; - case DATA_SATHROVARR: return Sathrovarr; - case DATA_GO_FORCEFIELD: return ForceField; - case DATA_BRUTALLUS: return Brutallus; - case DATA_MADRIGOSA: return Madrigosa; - case DATA_FELMYST: return Felmyst; - case DATA_ALYTHESS: return Alythess; - case DATA_SACROLASH: return Sacrolash; - case DATA_MURU: return Muru; - case DATA_KILJAEDEN: return KilJaeden; - case DATA_KILJAEDEN_CONTROLLER: return KilJaedenController; - case DATA_ANVEENA: return Anveena; - case DATA_KALECGOS_KJ: return KalecgosKJ; - case DATA_PLAYER_GUID: - Player* Target = GetPlayerInMap(); - return Target->GetGUID(); - } - return 0; - } - - void SetData(uint32 id, uint32 data) - { - switch(id) - { - case DATA_KALECGOS_EVENT: - { - if (data == NOT_STARTED || data == DONE) - { - HandleGameObject(ForceField,true); - HandleGameObject(KalecgosWall[0],true); - HandleGameObject(KalecgosWall[1],true); - } - else if (data == IN_PROGRESS) - { - HandleGameObject(ForceField,false); - HandleGameObject(KalecgosWall[0],false); - HandleGameObject(KalecgosWall[1],false); - } - m_auiEncounter[0] = data; - } - break; - case DATA_BRUTALLUS_EVENT: m_auiEncounter[1] = data; break; - case DATA_FELMYST_EVENT: - if (data == DONE) - HandleGameObject(FireBarrier, true); - m_auiEncounter[2] = data; break; - case DATA_EREDAR_TWINS_EVENT: m_auiEncounter[3] = data; break; - case DATA_MURU_EVENT: - switch(data) - { - case DONE: - HandleGameObject(MurusGate[0], true); - HandleGameObject(MurusGate[1], true); - break; - case IN_PROGRESS: - HandleGameObject(MurusGate[0], false); - HandleGameObject(MurusGate[1], false); - break; - case NOT_STARTED: - HandleGameObject(MurusGate[0], true); - HandleGameObject(MurusGate[1], false); - break; - } - m_auiEncounter[4] = data; break; - case DATA_KILJAEDEN_EVENT: m_auiEncounter[5] = data; break; - } - - if (data == DONE) - SaveToDB(); - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " - << m_auiEncounter[4] << " " << m_auiEncounter[5]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_sunwell_plateau(Map* pMap) -{ - return new instance_sunwell_plateau(pMap); -} - -void AddSC_instance_sunwell_plateau() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_sunwell_plateau"; - newscript->GetInstanceData = &GetInstanceData_instance_sunwell_plateau; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp deleted file mode 100644 index dbf67d5f26e..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Sunwell_Plateau -SD%Complete: 0 -SDComment: Placeholder, Epilogue after Kil'jaeden, Captain Selana Gossips -EndScriptData */ - -/* ContentData -npc_prophet_velen -npc_captain_selana -EndContentData */ - -#include "ScriptedPch.h" -#include "sunwell_plateau.h" - -/*###### -## npc_prophet_velen -######*/ - -enum ProphetSpeeches -{ - PROPHET_SAY1 = -1580099, - PROPHET_SAY2 = -1580100, - PROPHET_SAY3 = -1580101, - PROPHET_SAY4 = -1580102, - PROPHET_SAY5 = -1580103, - PROPHET_SAY6 = -1580104, - PROPHET_SAY7 = -1580105, - PROPHET_SAY8 = -1580106 -}; - -enum LiadrinnSpeeches -{ - LIADRIN_SAY1 = -1580107, - LIADRIN_SAY2 = -1580108, - LIADRIN_SAY3 = -1580109 -}; - -/*###### -## npc_captain_selana -######*/ - -#define CS_GOSSIP1 "Give me a situation report, Captain." -#define CS_GOSSIP2 "What went wrong?" -#define CS_GOSSIP3 "Why did they stop?" -#define CS_GOSSIP4 "Your insight is appreciated." - -void AddSC_sunwell_plateau() -{ -} diff --git a/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h deleted file mode 100644 index 9f1a2480c96..00000000000 --- a/src/server/scripts/EasternKingdoms/sunwell_plateau/sunwell_plateau.h +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SUNWELLPLATEAU_H -#define DEF_SUNWELLPLATEAU_H - -/*** Encounters ***/ -enum Data -{ - DATA_KALECGOS_EVENT, - DATA_BRUTALLUS_EVENT, - DATA_FELMYST_EVENT, - DATA_EREDAR_TWINS_EVENT, - DATA_MURU_EVENT, - DATA_KILJAEDEN_EVENT, -}; - -enum Data64 -{ - /*** Creatures ***/ - DATA_KALECGOS_DRAGON, - DATA_KALECGOS_HUMAN, - DATA_SATHROVARR, - DATA_BRUTALLUS, - DATA_MADRIGOSA, - DATA_FELMYST, - DATA_ALYTHESS, - DATA_SACROLASH, - DATA_MURU, - DATA_KILJAEDEN, - DATA_KILJAEDEN_CONTROLLER, - DATA_ANVEENA, - DATA_KALECGOS_KJ, - - /*** GameObjects ***/ - DATA_GO_FORCEFIELD, - DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1, - DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_2, - DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_3, - DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_4, - - /*** Misc ***/ - DATA_PLAYER_GUID, -}; - -enum Creatures -{ - BOSS_MURU = 25741, - BOSS_ENTROPIUS = 25840, - MOB_KALECGOS = 24850, - MOB_KALEC = 24891, - MOB_SATHROVARR = 24892, - - MOB_DEAD = 25268, - MOB_FLIGHT_LEFT = 25357, - MOB_FLIGHT_RIGHT = 25358, - MOB_DEATH_CLOUD = 25703, - MOB_VAPOR = 25265, - MOB_VAPOR_TRAIL = 25267, - - MOB_GRAND_WARLOCK_ALYTHESS = 25166, - MOB_SHADOW_IMAGE = 25214, - MOB_LADY_SACROLASH = 25165, - - CREATURE_ANVEENA = 26046, // Embodiment of the Sunwell - CREATURE_KALECGOS = 25319, // Helps the raid throughout the fight - CREATURE_PROPHET = 26246, // Outro - CREATURE_KILJAEDEN = 25315, // Give it to 'em KJ! - CREATURE_HAND_OF_THE_DECEIVER = 25588, // Adds found before KJ emerges - CREATURE_FELFIRE_PORTAL = 25603, // Portal spawned be Hand of the Deceivers - CREATURE_VOLATILE_FELFIRE_FIEND = 25598, // Fiends spawned by the above portal - CREATURE_ARMAGEDDON_TARGET = 25735, // This mob casts meteor on itself.. I think - CREATURE_SHIELD_ORB = 25502, // Shield orbs circle the room raining shadow bolts on raid - CREATURE_THE_CORE_OF_ENTROPIUS = 26262, // Used in the ending cinematic? - CREATURE_POWER_OF_THE_BLUE_DRAGONFLIGHT = 25653, // NPC that players possess when using the Orb of the Blue Dragonflight - CREATURE_SPIKE_TARGET1 = 30598, // Should summon these under Shadow Spike Channel on targets place - CREATURE_SPIKE_TARGET2 = 30614, - CREATURE_SINISTER_REFLECTION = 25708, // Sinister Relection spawnd on Phase swichtes - - CREATURE_DARKNESS = 25879, - CREATURE_DARK_FIENDS = 25744, - CREATURE_BERSERKER = 25798, - CREATURE_FURY_MAGE = 25799, - CREATURE_VOID_SENTINEL = 25772, - CREATURE_VOID_SPAWN = 25824, - CREATURE_BLACK_HOLE = 25855, -}; - -enum GameObjects -{ - GAMEOBJECT_ORB_OF_THE_BLUE_DRAGONFLIGHT = 188415, -}; - -#endif diff --git a/src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp deleted file mode 100644 index cd3bc5fc219..00000000000 --- a/src/server/scripts/EasternKingdoms/uldaman/boss_archaedas.cpp +++ /dev/null @@ -1,497 +0,0 @@ -/* Copyright (C) 2006,2007 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_archaedas -SD%Complete: 100 -SDComment: Archaedas is activated when 1 person (was 3, changed in 3.0.8) clicks on his altar. -Every 10 seconds he will awaken one of his minions along the wall. -At 66%, he will awaken the 6 Guardians. -At 33%, he will awaken the Vault Walkers -On his death the vault door opens. -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO "Who dares awaken Archaedas? Who dares the wrath of the makers!" -#define SOUND_AGGRO 5855 - -#define SAY_SUMMON "Awake ye servants, defend the discs!" -#define SOUND_SUMMON 5856 - -#define SAY_SUMMON2 "To my side, brothers. For the makers!" -#define SOUND_SUMMON2 5857 - -#define SAY_KILL "Reckless mortal." -#define SOUND_KILL 5858 - -#define SPELL_GROUND_TREMOR 6524 -#define SPELL_ARCHAEDAS_AWAKEN 10347 -#define SPELL_BOSS_OBJECT_VISUAL 11206 -#define SPELL_BOSS_AGGRO 10340 -#define SPELL_SUB_BOSS_AGGRO 11568 -#define SPELL_AWAKEN_VAULT_WALKER 10258 -#define SPELL_AWAKEN_EARTHEN_GUARDIAN 10252 - -struct boss_archaedasAI : public ScriptedAI -{ - boss_archaedasAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - uint32 Tremor_Timer; - int32 Awaken_Timer; - uint32 WallMinionTimer; - bool wakingUp; - - bool guardiansAwake; - bool vaultWalkersAwake; - ScriptedInstance* pInstance; - - void Reset() - { - Tremor_Timer = 60000; - Awaken_Timer = 0; - WallMinionTimer = 10000; - - wakingUp = false; - guardiansAwake = false; - vaultWalkersAwake = false; - - if (pInstance) - pInstance->SetData (NULL, 5); // respawn any dead minions - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - - } - - void ActivateMinion (uint64 guid, bool flag) - { - Unit *minion = Unit::GetUnit(*me, guid); - - if (minion && minion->isAlive()) - { - DoCast (minion, SPELL_AWAKEN_VAULT_WALKER, flag); - minion->CastSpell(minion, SPELL_ARCHAEDAS_AWAKEN,true); - } - } - - void EnterCombat(Unit * /*who*/) - { - me->setFaction (14); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); - } - - void SpellHit (Unit* /*caster*/, const SpellEntry *spell) - { - // Being woken up from the altar, start the awaken sequence - if (spell == GetSpellStore()->LookupEntry(SPELL_ARCHAEDAS_AWAKEN)) { - me->MonsterYell(SAY_AGGRO,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_AGGRO); - Awaken_Timer = 4000; - wakingUp = true; - } - } - - void KilledUnit(Unit * /*victim*/) - { - me->MonsterYell(SAY_KILL,LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - // we're still doing awaken animation - if (wakingUp && Awaken_Timer >= 0) { - Awaken_Timer -= diff; - return; // dont do anything until we are done - } else if (wakingUp && Awaken_Timer <= 0) { - wakingUp = false; - AttackStart(Unit::GetUnit(*me, pInstance->GetData64(0))); - return; // dont want to continue until we finish the AttackStart method - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - // wake a wall minion - if (WallMinionTimer <= diff) { - pInstance->SetData (NULL, 2); - - WallMinionTimer = 10000; - } else WallMinionTimer -= diff; - - //If we are <66 summon the guardians - if (!guardiansAwake && me->GetHealth()*100 / me->GetMaxHealth() <= 66) { - ActivateMinion(pInstance->GetData64(5),true); // EarthenGuardian1 - ActivateMinion(pInstance->GetData64(6),true); // EarthenGuardian2 - ActivateMinion(pInstance->GetData64(7),true); // EarthenGuardian3 - ActivateMinion(pInstance->GetData64(8),true); // EarthenGuardian4 - ActivateMinion(pInstance->GetData64(9),true); // EarthenGuardian5 - ActivateMinion(pInstance->GetData64(10),false); // EarthenGuardian6 - me->MonsterYell(SAY_SUMMON,LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_SUMMON); - guardiansAwake = true; - } - - //If we are <33 summon the vault walkers - if (!vaultWalkersAwake && me->GetHealth()*100 / me->GetMaxHealth() <= 33) { - ActivateMinion(pInstance->GetData64(1),true); // VaultWalker1 - ActivateMinion(pInstance->GetData64(2),true); // VaultWalker2 - ActivateMinion(pInstance->GetData64(3),true); // VaultWalker3 - ActivateMinion(pInstance->GetData64(4),false); // VaultWalker4 - me->MonsterYell(SAY_SUMMON2, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_SUMMON2); - vaultWalkersAwake = true; - } - - if (Tremor_Timer <= diff) - { - //Cast - DoCast(me->getVictim(), SPELL_GROUND_TREMOR); - - //45 seconds until we should cast this agian - Tremor_Timer = 45000; - } else Tremor_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied (Unit * /*killer*/) { - if (pInstance) - { - pInstance->SetData(NULL,3); // open the vault door - pInstance->SetData(NULL,4); // deactivate his minions - } - } - -}; - -CreatureAI* GetAI_boss_archaedas(Creature* pCreature) -{ - return new boss_archaedasAI (pCreature); -} - -/* ScriptData -SDName: mob_archaedas_minions -SD%Complete: 100 -SDComment: These mobs are initially frozen until Archaedas awakens them -one at a time. -EndScriptData */ - -#define SPELL_ARCHAEDAS_AWAKEN 10347 - -struct mob_archaedas_minionsAI : public ScriptedAI -{ - mob_archaedas_minionsAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - uint32 Arcing_Timer; - int32 Awaken_Timer; - bool wakingUp; - - bool amIAwake; - ScriptedInstance* pInstance; - - void Reset() - { - Arcing_Timer = 3000; - Awaken_Timer = 0; - - wakingUp = false; - amIAwake = false; - - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->RemoveAllAuras(); - } - - void EnterCombat(Unit * /*who*/) - { - me->setFaction (14); - me->RemoveAllAuras(); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - amIAwake = true; - } - - void SpellHit (Unit* /*caster*/, const SpellEntry *spell) { - // time to wake up, start animation - if (spell == GetSpellStore()->LookupEntry(SPELL_ARCHAEDAS_AWAKEN)){ - Awaken_Timer = 5000; - wakingUp = true; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (amIAwake) - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - // we're still in the awaken animation - if (wakingUp && Awaken_Timer >= 0) { - Awaken_Timer -= diff; - return; // dont do anything until we are done - } else if (wakingUp && Awaken_Timer <= 0) { - wakingUp = false; - amIAwake = true; - // AttackStart(Unit::GetUnit(*me, pInstance->GetData64(0))); // whoWokeArchaedasGUID - return; // dont want to continue until we finish the AttackStart method - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_archaedas_minions(Creature* pCreature) -{ - return new mob_archaedas_minionsAI (pCreature); -} - -/* ScriptData -SDName: go_altar_archaedas -SD%Complete: 100 -SDComment: Needs 1 person to activate the Archaedas script -SDCategory: Uldaman -EndScriptData */ - -#define OBJECT_ALTAR_OF_ARCHAEDAS 133234 - -#define NUMBER_NEEDED_TO_ACTIVATE 1 // as of patch 3.0.8 the altars can be opened by a single player (previously 3) - -#define SPELL_BOSS_OBJECT_VISUAL 11206 - -//uint64 altarOfArchaedasCount[5]; -//int32 altarOfArchaedasCounter=0; - -bool GOHello_go_altar_of_archaedas(Player* pPlayer, GameObject* /*pGo*/) -{ - //bool alreadyUsed; - //pGo->AddUse (); - - /* - alreadyUsed = false; - for (uint32 loop=0; loop<5; loop++) { - if (altarOfArchaedasCount[loop] == pPlayer->GetGUID()) alreadyUsed = true; - } - if (!alreadyUsed) - altarOfArchaedasCount[altarOfArchaedasCounter++] = pPlayer->GetGUID(); - */ - - pPlayer->CastSpell (pPlayer, SPELL_BOSS_OBJECT_VISUAL, false); - - /* - if (altarOfArchaedasCounter < NUMBER_NEEDED_TO_ACTIVATE) - return false; // not enough people yet - - // Check to make sure at least three people are still casting - uint8 count = 0; - Unit *pTarget; - for (uint8 x = 0; x <= 5; ++x) - { - pTarget = Unit::GetUnit(*pPlayer, altarOfArchaedasCount[x]); - if (!pTarget) - continue; - if (pTarget->IsNonMeleeSpellCasted(true)) - ++count; - if (count >= NUMBER_NEEDED_TO_ACTIVATE) - break; - } - - if (count < NUMBER_NEEDED_TO_ACTIVATE) - return false; // not enough people - */ - - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (!pInstance) - return false; - - pInstance->SetData(NULL,0); - pInstance->SetData64(0,pPlayer->GetGUID()); // activate archaedas - - return false; -} - -/* ScriptData -SDName: mob_stonekeepers -SD%Complete: 100 -SDComment: After activating the altar of the keepers, the stone keepers will -wake up one by one. -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_SELF_DESTRUCT 9874 - -struct mob_stonekeepersAI : public ScriptedAI -{ - mob_stonekeepersAI(Creature *c) : ScriptedAI(c) - { - pInstance = (me->GetInstanceData()); - } - - ScriptedInstance* pInstance; - - void Reset() - { - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->RemoveAllAuras(); - } - - void EnterCombat(Unit * /*who*/) - { - me->setFaction (14); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - } - - void UpdateAI(const uint32 /*diff*/) - { - - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit * /*attacker*/) - { - DoCast (me, SPELL_SELF_DESTRUCT,true); - if (pInstance) - pInstance->SetData(NULL, 1); // activate next stonekeeper - } - -}; - -CreatureAI* GetAI_mob_stonekeepers(Creature* pCreature) -{ - return new mob_stonekeepersAI (pCreature); -} - -/* ScriptData -SDName: go_altar_of_the_keepers -SD%Complete: 100 -SDComment: Need 1 person to activate to open the altar. One by one the StoneKeepers will activate. After all four are dead than the door will open. -SDCategory: Uldaman -EndScriptData */ - -#define SPELL_BOSS_OBJECT_VISUAL 11206 - -#define NUMBER_NEEDED_TO_ACTIVATE 1 // as of patch 3.0.8 the altars can be opened by a single player (previously 3) - -//static uint64 altarOfTheKeeperCount[5]; -//static uint32 altarOfTheKeeperCounter=0; - -bool GOHello_go_altar_of_the_keepers(Player* pPlayer, GameObject* /*pGo*/) -{ - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (!pInstance) - return true; - - //bool alreadyUsed; - - //pGo->AddUse(); - - //alreadyUsed = false; - //for (uint32 loop=0; loop<5; ++loop) - //{ - // if (altarOfTheKeeperCount[loop] == pPlayer->GetGUID()) - //alreadyUsed = true; - //} - //if (!alreadyUsed && altarOfTheKeeperCounter < 5) - // altarOfTheKeeperCount[altarOfTheKeeperCounter++] = pPlayer->GetGUID(); - pPlayer->CastSpell (pPlayer, SPELL_BOSS_OBJECT_VISUAL, false); - - //if (altarOfTheKeeperCounter < NUMBER_NEEDED_TO_ACTIVATE) - //{ - //error_log("not enough people yet, altarOfTheKeeperCounter = %d", altarOfTheKeeperCounter); - // return false; // not enough people yet - //} -/* - // Check to make sure at least three people are still casting - uint8 count = 0; - Unit *pTarget; - for (uint8 x = 0; x < 5; ++x) - { - pTarget = Unit::GetUnit(*pPlayer, altarOfTheKeeperCount[x]); - //error_log("number of people currently activating it: %d", x+1); - if (!pTarget) - continue; - if (pTarget->IsNonMeleeSpellCasted(true)) - ++count; - if (count >= NUMBER_NEEDED_TO_ACTIVATE) - break; - } - - if (count < NUMBER_NEEDED_TO_ACTIVATE) - { - //error_log("still not enough people"); - return true; // not enough people - } -*/ - //error_log ("activating stone keepers"); - pInstance->SetData(NULL,1); // activate the Stone Keepers - return true; -} - -void AddSC_boss_archaedas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_archaedas"; - newscript->GetAI = &GetAI_boss_archaedas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_altar_of_archaedas"; - newscript->pGOHello = &GOHello_go_altar_of_archaedas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_archaedas_minions"; - newscript->GetAI = &GetAI_mob_archaedas_minions; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_altar_of_the_keepers"; - newscript->pGOHello = &GOHello_go_altar_of_the_keepers; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stonekeepers"; - newscript->GetAI = &GetAI_mob_stonekeepers; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp b/src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp deleted file mode 100644 index 9b6d5dba642..00000000000 --- a/src/server/scripts/EasternKingdoms/uldaman/boss_ironaya.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ironaya -SD%Complete: 100 -SDComment: -SDCategory: Uldaman -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1070000 - -#define SPELL_ARCINGSMASH 8374 -#define SPELL_KNOCKAWAY 10101 -#define SPELL_WSTOMP 11876 - -struct boss_ironayaAI : public ScriptedAI -{ - boss_ironayaAI(Creature *c) : ScriptedAI(c) {} - - uint32 Arcing_Timer; - bool hasCastedWstomp; - bool hasCastedKnockaway; - - void Reset() - { - Arcing_Timer = 3000; - hasCastedKnockaway = false; - hasCastedWstomp = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //If we are <50% hp do knockaway ONCE - if (!hasCastedKnockaway && me->GetHealth()*2 < me->GetMaxHealth()) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); - - // current aggro target is knocked away pick new target - Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - - if (!Target || Target == me->getVictim()) - Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); - - if (Target) - me->TauntApply(Target); - - //Shouldn't cast this agian - hasCastedKnockaway = true; - } - - //Arcing_Timer - if (Arcing_Timer <= diff) - { - DoCast(me, SPELL_ARCINGSMASH); - Arcing_Timer = 13000; - } else Arcing_Timer -= diff; - - if (!hasCastedWstomp && me->GetHealth()*4 < me->GetMaxHealth()) - { - DoCast(me, SPELL_WSTOMP); - hasCastedWstomp = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ironaya(Creature* pCreature) -{ - return new boss_ironayaAI (pCreature); -} - -void AddSC_boss_ironaya() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ironaya"; - newscript->GetAI = &GetAI_boss_ironaya; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp b/src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp deleted file mode 100644 index a519ad678b7..00000000000 --- a/src/server/scripts/EasternKingdoms/uldaman/instance_uldaman.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright (C) 2006,2007 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" - -#define SPELL_ARCHAEDAS_AWAKEN 10347 -#define SPELL_AWAKEN_VAULT_WALKER 10258 - -#define ARCHAEDAS_TEMPLE_DOOR 141869 -#define ALTAR_OF_ARCHAEDAS 133234 - -#define ALTAR_OF_THE_KEEPER_TEMPLE_DOOR 124367 -#define ALTAR_OF_THE_KEEPER_TEMPLE 130511 - -#define ANCIENT_VAULT_DOOR 124369 - -struct instance_uldaman : public ScriptedInstance -{ - instance_uldaman(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - }; - - void Initialize() - { - archaedasGUID = 0; - altarOfTheKeeperTempleDoor = 0; - archaedasTempleDoor = 0; - ancientVaultDoor = 0; - whoWokeArchaedasGUID = 0; - } - - uint64 archaedasGUID; - uint64 altarOfTheKeeperTempleDoor; - uint64 archaedasTempleDoor; - uint64 ancientVaultDoor; - uint64 whoWokeArchaedasGUID; - - std::vector stoneKeeper; - std::vector altarOfTheKeeperCount; - std::vector vaultWalker; - std::vector earthenGuardian; - std::vector archaedasWallMinions; // minions lined up around the wall - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch (pGo->GetEntry()) - { - case ALTAR_OF_THE_KEEPER_TEMPLE_DOOR: // lock the door - altarOfTheKeeperTempleDoor = pGo->GetGUID(); - break; - - case ARCHAEDAS_TEMPLE_DOOR: - archaedasTempleDoor = pGo->GetGUID(); - break; - - case ANCIENT_VAULT_DOOR: - pGo->SetGoState(GO_STATE_READY); - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33); - ancientVaultDoor = pGo->GetGUID(); - break; - } - } - - void SetFrozenState(Creature* pCreature) - { - pCreature->setFaction(35); - pCreature->RemoveAllAuras(); - //creature->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_ANIMATION_FROZEN); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - } - - void OpenDoor(uint64 guid) - { - GameObject* pGo = instance->GetGameObject(guid); - if (!pGo) - return; - - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33); - pGo->SetGoState(GO_STATE_ACTIVE); - } - - void ActivateStoneKeepers() - { - for (std::vector::const_iterator i = stoneKeeper.begin(); i != stoneKeeper.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || !pTarget->isAlive() || pTarget->getFaction() == 14) - continue; - pTarget->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE); - pTarget->setFaction(14); - pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - return; // only want the first one we find - } - // if we get this far than all four are dead so open the door - SetData (NULL, 0); - } - - void ActivateWallMinions() - { - Creature *archaedas = instance->GetCreature(archaedasGUID); - if (!archaedas) - return; - - for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || !pTarget->isAlive() || pTarget->getFaction() == 14) - continue; - archaedas->CastSpell(pTarget, SPELL_AWAKEN_VAULT_WALKER, true); - pTarget->CastSpell(pTarget, SPELL_ARCHAEDAS_AWAKEN,true); - return; // only want the first one we find - } - } - - // used when Archaedas dies. All active minions must be despawned. - void DeActivateMinions() - { - // first despawn any aggroed wall minions - for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) - continue; - pTarget->setDeathState(JUST_DIED); - pTarget->RemoveCorpse(); - } - - // Vault Walkers - for (std::vector::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) - continue; - pTarget->setDeathState(JUST_DIED); - pTarget->RemoveCorpse(); - } - - // Earthen Guardians - for (std::vector::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (!pTarget || pTarget->isDead() || pTarget->getFaction() != 14) - continue; - pTarget->setDeathState(JUST_DIED); - pTarget->RemoveCorpse(); - } - } - - void ActivateArchaedas(uint64 target) - { - Creature *archaedas = instance->GetCreature(archaedasGUID); - if (!archaedas) - return; - - if (Unit *victim = Unit::GetUnit(*archaedas, target)) - { - archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN,false); - whoWokeArchaedasGUID = target; - } - } - - void RespawnMinions() - { - // first respawn any aggroed wall minions - for (std::vector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (pTarget && pTarget->isDead()) - { - pTarget->Respawn(); - pTarget->GetMotionMaster()->MoveTargetedHome(); - SetFrozenState(pTarget); - } - } - - // Vault Walkers - for (std::vector::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (pTarget && pTarget->isDead()) - { - pTarget->Respawn(); - pTarget->GetMotionMaster()->MoveTargetedHome(); - SetFrozenState(pTarget); - } - } - - // Earthen Guardians - for (std::vector::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i) - { - Creature *pTarget = instance->GetCreature(*i); - if (pTarget && pTarget->isDead()) - { - pTarget->Respawn(); - pTarget->GetMotionMaster()->MoveTargetedHome(); - SetFrozenState(pTarget); - } - } - } - - void SetData (uint32 /*type*/, uint32 data) - { - //error_log ("SetData: data = %d", data); - if (data == 0) OpenDoor (altarOfTheKeeperTempleDoor); - if (data == 0) OpenDoor (archaedasTempleDoor); - if (data == 3) OpenDoor (ancientVaultDoor); - if (data == 1) ActivateStoneKeepers(); - if (data == 2) ActivateWallMinions(); - if (data == 4) DeActivateMinions(); - if (data == 5) RespawnMinions(); - } - - void SetData64 (uint32 type, uint64 data) - { - // Archaedas - if (type == 0) - { - ActivateArchaedas (data); - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) { - case 4857: // Stone Keeper - SetFrozenState (pCreature); - stoneKeeper.push_back(pCreature->GetGUID()); - break; - - case 7309: // Earthen Custodian - archaedasWallMinions.push_back(pCreature->GetGUID()); - break; - - case 7077: // Earthen Hallshaper - archaedasWallMinions.push_back(pCreature->GetGUID()); - break; - - case 7076: // Earthen Guardian - earthenGuardian.push_back(pCreature->GetGUID()); - break; - - case 10120: // Vault Walker - vaultWalker.push_back(pCreature->GetGUID()); - break; - - case 2748: // Archaedas - archaedasGUID = pCreature->GetGUID(); - break; - - } // end switch - } // end OnCreatureCreate - - uint64 GetData64 (uint32 identifier) - { - if (identifier == 0) return whoWokeArchaedasGUID; - if (identifier == 1) return vaultWalker[0]; // VaultWalker1 - if (identifier == 2) return vaultWalker[1]; // VaultWalker2 - if (identifier == 3) return vaultWalker[2]; // VaultWalker3 - if (identifier == 4) return vaultWalker[3]; // VaultWalker4 - - if (identifier == 5) return earthenGuardian[0]; - if (identifier == 6) return earthenGuardian[1]; - if (identifier == 7) return earthenGuardian[2]; - if (identifier == 8) return earthenGuardian[3]; - if (identifier == 9) return earthenGuardian[4]; - if (identifier == 10) return earthenGuardian[5]; - - return 0; - } // end GetData64 -}; - -InstanceData* GetInstanceData_instance_uldaman(Map* pMap) -{ - return new instance_uldaman(pMap); -} - -void AddSC_instance_uldaman() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_uldaman"; - newscript->GetInstanceData = &GetInstanceData_instance_uldaman; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp b/src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp deleted file mode 100644 index 2bd8387efa5..00000000000 --- a/src/server/scripts/EasternKingdoms/uldaman/uldaman.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Uldaman -SD%Complete: 100 -SDComment: Quest support: 2278 + 1 trash mob. -SDCategory: Uldaman -EndScriptData */ - -/* ContentData -mob_jadespine_basilisk -npc_lore_keeper_of_norgannon -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## mob_jadespine_basilisk -######*/ - -#define SPELL_CSLUMBER 3636 - -struct mob_jadespine_basiliskAI : public ScriptedAI -{ - mob_jadespine_basiliskAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cslumber_Timer; - - void Reset() - { - Cslumber_Timer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Cslumber_Timer - if (Cslumber_Timer <= diff) - { - //Cast - // DoCast(me->getVictim(), SPELL_CSLUMBER); - DoCast(me->getVictim(), SPELL_CSLUMBER, true); - - //Stop attacking target thast asleep and pick new target - Cslumber_Timer = 28000; - - Unit* Target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - - if (!Target || Target == me->getVictim()) - Target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - - if (Target) - me->TauntApply(Target); - - } else Cslumber_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_jadespine_basilisk(Creature* pCreature) -{ - return new mob_jadespine_basiliskAI (pCreature); -} - -/*###### -## npc_lore_keeper_of_norgannon -######*/ - -#define GOSSIP_HELLO_KEEPER "Who are the Earthen?" -#define GOSSIP_SELECT_KEEPER1 "What is a \"subterranean being matrix\"?" -#define GOSSIP_SELECT_KEEPER2 "What are the anomalies you speak of?" -#define GOSSIP_SELECT_KEEPER3 "What is a resilient foundation of construction?" -#define GOSSIP_SELECT_KEEPER4 "So... the Earthen were made out of stone?" -#define GOSSIP_SELECT_KEEPER5 "Anything else I should know about the Earthen?" -#define GOSSIP_SELECT_KEEPER6 "I think I understand the Creators' design intent for the Earthen now. What are the Earthen's anomalies that you spoke of earlier?" -#define GOSSIP_SELECT_KEEPER7 "What high-stress environments would cause the Earthen to destabilize?" -#define GOSSIP_SELECT_KEEPER8 "What happens when the Earthen destabilize?" -#define GOSSIP_SELECT_KEEPER9 "Troggs?! Are the troggs you mention the same as the ones in the world today?" -#define GOSSIP_SELECT_KEEPER10 "You mentioned two results when the Earthen destabilize. What is the second?" -#define GOSSIP_SELECT_KEEPER11 "Dwarves!!! Now you're telling me that dwarves originally came from the Earthen?!" -#define GOSSIP_SELECT_KEEPER12 "These dwarves are the same ones today, yes? Do the dwarves maintain any other links to the Earthen?" -#define GOSSIP_SELECT_KEEPER13 "Who are the Creators?" -#define GOSSIP_SELECT_KEEPER14 "This is a lot to think about." -#define GOSSIP_SELECT_KEEPER15 "I will access the discs now." - -bool GossipHello_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(2278) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KEEPER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(1079, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(1080, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(1081, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(1082, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(1083, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - pPlayer->SEND_GOSSIP_MENU(1084, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - pPlayer->SEND_GOSSIP_MENU(1085, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); - pPlayer->SEND_GOSSIP_MENU(1086, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+8: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); - pPlayer->SEND_GOSSIP_MENU(1087, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+9: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); - pPlayer->SEND_GOSSIP_MENU(1088, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+10: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+11); - pPlayer->SEND_GOSSIP_MENU(1089, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+12); - pPlayer->SEND_GOSSIP_MENU(1090, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+12: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+13); - pPlayer->SEND_GOSSIP_MENU(1091, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+13: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+14); - pPlayer->SEND_GOSSIP_MENU(1092, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+14: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+15); - pPlayer->SEND_GOSSIP_MENU(1093, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+15: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_KEEPER15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+16); - pPlayer->SEND_GOSSIP_MENU(1094, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+16: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->AreaExploredOrEventHappens(2278); - break; - } - return true; -} - -void AddSC_uldaman() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_jadespine_basilisk"; - newscript->GetAI = &GetAI_mob_jadespine_basilisk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_lore_keeper_of_norgannon"; - newscript->pGossipHello = &GossipHello_npc_lore_keeper_of_norgannon; - newscript->pGossipSelect = &GossipSelect_npc_lore_keeper_of_norgannon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp deleted file mode 100644 index f516065cc03..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/boss_akilzon.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* Copyright ?2006 - 2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_Akilzon -SD%Complete: 75% -SDComment: Missing timer for Call Lightning and Sound ID's -SQLUpdate: -#Temporary fix for Soaring Eagles - -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" -#include "Weather.h" - -#define SPELL_STATIC_DISRUPTION 43622 -#define SPELL_STATIC_VISUAL 45265 -#define SPELL_CALL_LIGHTNING 43661 //Missing timer -#define SPELL_GUST_OF_WIND 43621 -#define SPELL_ELECTRICAL_STORM 43648 -#define SPELL_BERSERK 45078 -#define SPELL_ELECTRICAL_DAMAGE 43657 -#define SPELL_ELECTRICAL_OVERLOAD 43658 -#define SPELL_EAGLE_SWOOP 44732 - -//"Your death gonna be quick, strangers. You shoulda never have come to this place..." -#define SAY_ONAGGRO "I be da predator! You da prey..." -#define SAY_ONDEATH "You can't... kill... me spirit!" -#define SAY_ONSLAY1 "Ya got nothin'!" -#define SAY_ONSLAY2 "Stop your cryin'!" -#define SAY_ONSUMMON "Feed, me bruddahs!" -#define SAY_ONENRAGE "All you be doing is wasting my time!" -#define SOUND_ONAGGRO 12013 -#define SOUND_ONDEATH 12019 -#define SOUND_ONSLAY1 12017 -#define SOUND_ONSLAY2 12018 -#define SOUND_ONSUMMON 12014 -#define SOUND_ONENRAGE 12016 - -#define MOB_SOARING_EAGLE 24858 -#define SE_LOC_X_MAX 400 -#define SE_LOC_X_MIN 335 -#define SE_LOC_Y_MAX 1435 -#define SE_LOC_Y_MIN 1370 - -struct boss_akilzonAI : public ScriptedAI -{ - boss_akilzonAI(Creature *c) : ScriptedAI(c) - { - SpellEntry *TempSpell = GET_SPELL(SPELL_ELECTRICAL_DAMAGE); - if (TempSpell) - TempSpell->EffectBasePoints[1] = 49;//disable bugged lightning until fixed in core - pInstance = c->GetInstanceData(); - } - ScriptedInstance *pInstance; - - uint64 BirdGUIDs[8]; - uint64 TargetGUID; - uint64 CycloneGUID; - uint64 CloudGUID; - - uint32 StaticDisruption_Timer; - uint32 GustOfWind_Timer; - uint32 CallLighting_Timer; - uint32 ElectricalStorm_Timer; - uint32 SummonEagles_Timer; - uint32 Enrage_Timer; - - uint32 StormCount; - uint32 StormSequenceTimer; - - bool isRaining; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_AKILZONEVENT, NOT_STARTED); - - StaticDisruption_Timer = urand(10000,20000); //10 to 20 seconds (bosskillers) - GustOfWind_Timer = urand(20000,30000); //20 to 30 seconds(bosskillers) - CallLighting_Timer = urand(10000,20000); //totaly random timer. can't find any info on this - ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) - Enrage_Timer = 10*MINUTE*IN_MILISECONDS; //10 minutes till enrage(bosskillers) - SummonEagles_Timer = 99999; - - TargetGUID = 0; - CloudGUID = 0; - CycloneGUID = 0; - DespawnSummons(); - for (uint8 i = 0; i < 8; ++i) - BirdGUIDs[i] = 0; - - StormCount = 0; - StormSequenceTimer = 0; - - isRaining = false; - - SetWeather(WEATHER_STATE_FINE, 0.0f); - } - - void EnterCombat(Unit * /*who*/) - { - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - //DoZoneInCombat(); - if (pInstance) - pInstance->SetData(DATA_AKILZONEVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*Killer*/) - { - me->MonsterYell(SAY_ONDEATH,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me, SOUND_ONDEATH); - if (pInstance) - pInstance->SetData(DATA_AKILZONEVENT, DONE); - DespawnSummons(); - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,1)) - { - case 0: - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONSLAY1); - break; - case 1: - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONSLAY2); - break; - } - } - - void DespawnSummons() - { - for (uint8 i = 0; i < 8; ++i) - { - Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]); - if (bird && bird->isAlive()) - { - bird->SetVisibility(VISIBILITY_OFF); - bird->setDeathState(JUST_DIED); - } - } - } - - void SetWeather(uint32 weather, float grade) - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) - return; - - WorldPacket data(SMSG_WEATHER, (4+4+4)); - data << uint32(weather) << float(grade) << uint8(0); - - pMap->SendToPlayers(&data); - } - - void HandleStormSequence(Unit *Cloud) // 1: begin, 2-9: tick, 10: end - { - if (StormCount < 10 && StormCount > 1) - { - // deal damage - int32 bp0 = 800; - for (uint8 i = 2; i < StormCount; ++i) - bp0 *= 2; - - CellPair p(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - std::list tempUnitMap; - - { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, 999); - Trinity::UnitListSearcher searcher(me, tempUnitMap, u_check); - - TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); - TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); - - cell.Visit(p, world_unit_searcher, *(me->GetMap())); - cell.Visit(p, grid_unit_searcher, *(me->GetMap())); - } - //dealdamege - for (std::list::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i) - { - if (!Cloud->IsWithinDist(*i, 6, false)) - { - Cloud->CastCustomSpell(*i, 43137, &bp0, NULL, NULL, true, 0, 0, me->GetGUID()); - } - } - // visual - float x,y,z; - z = me->GetPositionZ(); - for (uint8 i = 0; i < 5+rand()%5; ++i) - { - x = 343+rand()%60; - y = 1380+rand()%60; - if (Unit *trigger = me->SummonTrigger(x, y, z, 0, 2000)) - { - trigger->setFaction(35); - trigger->SetMaxHealth(100000); - trigger->SetHealth(100000); - trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (Cloud) - Cloud->CastCustomSpell(trigger, /*43661*/43137, &bp0, NULL, NULL,true, 0, 0, Cloud->GetGUID()); - } - } - } - ++StormCount; - if (StormCount > 10) - { - StormCount = 0; // finish - SummonEagles_Timer = 5000; - me->InterruptNonMeleeSpells(false); - CloudGUID = 0; - if (Cloud) - Cloud->DealDamage(Cloud, Cloud->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - SetWeather(WEATHER_STATE_FINE, 0.0f); - isRaining = false; - } - StormSequenceTimer = 1000; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (StormCount) - { - Unit *pTarget = Unit::GetUnit(*me, CloudGUID); - if (!pTarget || !pTarget->isAlive()) - { - EnterEvadeMode(); - return; - } - else if (Unit* Cyclone = Unit::GetUnit(*me, CycloneGUID)) - Cyclone->CastSpell(pTarget, 25160, true); // keep casting or... - - if (StormSequenceTimer <= diff) - HandleStormSequence(pTarget); - else - StormSequenceTimer -= diff; - - return; - } - - if (Enrage_Timer <= diff) - { - me->MonsterYell(SAY_ONENRAGE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONENRAGE); - DoCast(me, SPELL_BERSERK, true); - Enrage_Timer = 600000; - } else Enrage_Timer -= diff; - - if (StaticDisruption_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) pTarget = me->getVictim(); - TargetGUID = pTarget->GetGUID(); - DoCast(pTarget, SPELL_STATIC_DISRUPTION, false); - me->SetInFront(me->getVictim()); - StaticDisruption_Timer = (10+rand()%8)*1000; // < 20s - - /*if (float dist = me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f) dist = 5.0f; - SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/ - } else StaticDisruption_Timer -= diff; - - if (GustOfWind_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) pTarget = me->getVictim(); - DoCast(pTarget, SPELL_GUST_OF_WIND); - GustOfWind_Timer = (20+rand()%10)*1000; //20 to 30 seconds(bosskillers) - } else GustOfWind_Timer -= diff; - - if (CallLighting_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CALL_LIGHTNING); - CallLighting_Timer = (12 + rand()%5)*1000; //totaly random timer. can't find any info on this - } else CallLighting_Timer -= diff; - - if (!isRaining && ElectricalStorm_Timer < 8000 + rand()%5000) - { - SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f); - isRaining = true; - } - - if (ElectricalStorm_Timer <= diff) { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); - if (!pTarget) - { - EnterEvadeMode(); - return; - } - pTarget->CastSpell(pTarget, 44007, true);//cloud visual - DoCast(pTarget, SPELL_ELECTRICAL_STORM, false);//storm cyclon + visual - float x,y,z; - pTarget->GetPosition(x,y,z); - if (pTarget) - { - pTarget->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - pTarget->SendMonsterMove(x,y,me->GetPositionZ()+15,0); - } - Unit *Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000); - if (Cloud) - { - CloudGUID = Cloud->GetGUID(); - Cloud->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - Cloud->StopMoving(); - Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); - Cloud->setFaction(35); - Cloud->SetMaxHealth(9999999); - Cloud->SetHealth(9999999); - Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - ElectricalStorm_Timer = 60000; //60 seconds(bosskillers) - StormCount = 1; - StormSequenceTimer = 0; - } else ElectricalStorm_Timer -= diff; - - if (SummonEagles_Timer <= diff) - { - me->MonsterYell(SAY_ONSUMMON, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_ONSUMMON); - - float x, y, z; - me->GetPosition(x, y, z); - - for (uint8 i = 0; i < 8; ++i) - { - Unit* bird = Unit::GetUnit(*me,BirdGUIDs[i]); - if (!bird) //they despawned on die - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - x = pTarget->GetPositionX() + irand(-10,10); - y = pTarget->GetPositionY() + irand(-10,10); - z = pTarget->GetPositionZ() + urand(16,20); - if (z > 95) - z = 95 - urand(0,5); - } - Creature *pCreature = me->SummonCreature(MOB_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (pCreature) - { - pCreature->AddThreat(me->getVictim(), 1.0f); - pCreature->AI()->AttackStart(me->getVictim()); - BirdGUIDs[i] = pCreature->GetGUID(); - } - } - } - SummonEagles_Timer = 999999; - } else SummonEagles_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soaring_eagleAI : public ScriptedAI -{ - mob_soaring_eagleAI(Creature *c) : ScriptedAI(c) {} - - uint32 EagleSwoop_Timer; - bool arrived; - uint32 TargetGUID; - - void Reset() - { - EagleSwoop_Timer = 5000 + rand()%5000; - arrived = true; - TargetGUID = 0; - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - } - - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - - void MoveInLineOfSight(Unit* /*who*/) {} - - void MovementInform(uint32, uint32) - { - arrived = true; - if (TargetGUID) - { - if (Unit *pTarget = Unit::GetUnit(*me, TargetGUID)) - DoCast(pTarget, SPELL_EAGLE_SWOOP, true); - TargetGUID = 0; - me->SetSpeed(MOVE_RUN, 1.2f); - EagleSwoop_Timer = 5000 + rand()%5000; - } - } - - void UpdateAI(const uint32 diff) - { - if (EagleSwoop_Timer <= diff) - EagleSwoop_Timer = 0; - else - EagleSwoop_Timer -= diff; - - if (arrived) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - if (EagleSwoop_Timer) - { - x = pTarget->GetPositionX() + irand(-10,10); - y = pTarget->GetPositionY() + irand(-10,10); - z = pTarget->GetPositionZ() + urand(10,15); - if (z > 95) - z = 95 - urand(0,5); - } - else - { - pTarget->GetContactPoint(me, x, y, z); - z += 2; - me->SetSpeed(MOVE_RUN, 5.0f); - TargetGUID = pTarget->GetGUID(); - } - me->GetMotionMaster()->MovePoint(0, x, y, z); - arrived = false; - } - } - } -}; - -//Soaring Eagle -CreatureAI* GetAI_mob_soaring_eagle(Creature* pCreature) -{ - return new mob_soaring_eagleAI(pCreature); -} - -CreatureAI* GetAI_boss_akilzon(Creature* pCreature) -{ - return new boss_akilzonAI(pCreature); -} - -void AddSC_boss_akilzon() -{ - Script *newscript = NULL; - - newscript = new Script; - newscript->Name = "boss_akilzon"; - newscript->GetAI = &GetAI_boss_akilzon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_akilzon_eagle"; - newscript->GetAI = &GetAI_mob_soaring_eagle; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp deleted file mode 100644 index aee0a8a59ea..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/boss_halazzi.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_Halazzi -SD%Complete: 80 -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" -//#include "spell.h" - -#define YELL_AGGRO "Get on your knees and bow to da fang and claw!" -#define SOUND_AGGRO 12020 -#define YELL_SABER_ONE "You gonna leave in pieces!" -#define YELL_SABER_TWO "Me gonna carve ya now!" -#define YELL_SPLIT "Me gonna carve ya now!" -#define SOUND_SPLIT 12021 -#define YELL_MERGE "Spirit, come back to me!" -#define SOUND_MERGE 12022 -#define YELL_KILL_ONE "You cant fight the power!" -#define SOUND_KILL_ONE 12026 -#define YELL_KILL_TWO "You gonna fail!" -#define SOUND_KILL_TWO 12027 -#define YELL_DEATH "Chaga... choka'jinn." -#define SOUND_DEATH 12028 -#define YELL_BERSERK "Whatch you be doing? Pissin' yourselves..." -#define SOUND_BERSERK 12025 - -#define SPELL_DUAL_WIELD 29651 -#define SPELL_SABER_LASH 43267 -#define SPELL_FRENZY 43139 -#define SPELL_FLAMESHOCK 43303 -#define SPELL_EARTHSHOCK 43305 -#define SPELL_TRANSFORM_SPLIT 43142 -#define SPELL_TRANSFORM_SPLIT2 43573 -#define SPELL_TRANSFORM_MERGE 43271 -#define SPELL_SUMMON_LYNX 43143 -#define SPELL_SUMMON_TOTEM 43302 -#define SPELL_BERSERK 45078 - -#define MOB_SPIRIT_LYNX 24143 -#define SPELL_LYNX_FRENZY 43290 -#define SPELL_SHRED_ARMOR 43243 - -#define MOB_TOTEM 24224 -#define SPELL_LIGHTNING 43301 - -enum PhaseHalazzi -{ - PHASE_NONE = 0, - PHASE_LYNX = 1, - PHASE_SPLIT = 2, - PHASE_HUMAN = 3, - PHASE_MERGE = 4, - PHASE_ENRAGE = 5 -}; - -struct boss_halazziAI : public ScriptedAI -{ - boss_halazziAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - // need to find out what controls totem's spell cooldown - SpellEntry *TempSpell = GET_SPELL(SPELL_LIGHTNING); - if (TempSpell && TempSpell->CastingTimeIndex != 5) - TempSpell->CastingTimeIndex = 5; // 2000 ms casting time - } - - ScriptedInstance *pInstance; - - uint32 FrenzyTimer; - uint32 SaberlashTimer; - uint32 ShockTimer; - uint32 TotemTimer; - uint32 CheckTimer; - uint32 BerserkTimer; - - uint32 TransformCount; - - PhaseHalazzi Phase; - - uint64 LynxGUID; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_HALAZZIEVENT, NOT_STARTED); - - TransformCount = 0; - BerserkTimer = 600000; - CheckTimer = 1000; - - DoCast(me, SPELL_DUAL_WIELD, true); - - Phase = PHASE_NONE; - EnterPhase(PHASE_LYNX); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS); - - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_AGGRO); - - EnterPhase(PHASE_LYNX); - } - - void JustSummoned(Creature* summon) - { - summon->AI()->AttackStart(me->getVictim()); - if (summon->GetEntry() == MOB_SPIRIT_LYNX) - LynxGUID = summon->GetGUID(); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE) - damage = 0; - } - - void SpellHit(Unit*, const SpellEntry *spell) - { - if (spell->Id == SPELL_TRANSFORM_SPLIT2) - EnterPhase(PHASE_HUMAN); - } - - void AttackStart(Unit *who) - { - if (Phase != PHASE_MERGE) ScriptedAI::AttackStart(who); - } - - void EnterPhase(PhaseHalazzi NextPhase) - { - switch(NextPhase) - { - case PHASE_LYNX: - case PHASE_ENRAGE: - if (Phase == PHASE_MERGE) - { - DoCast(me, SPELL_TRANSFORM_MERGE, true); - me->Attack(me->getVictim(), true); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - if (Creature *Lynx = Unit::GetCreature(*me, LynxGUID)) - Lynx->DisappearAndDie(); - me->SetMaxHealth(600000); - me->SetHealth(600000 - 150000 * TransformCount); - FrenzyTimer = 16000; - SaberlashTimer = 20000; - ShockTimer = 10000; - TotemTimer = 12000; - break; - case PHASE_SPLIT: - me->MonsterYell(YELL_SPLIT, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_SPLIT); - DoCast(me, SPELL_TRANSFORM_SPLIT, true); - break; - case PHASE_HUMAN: - //DoCast(me, SPELL_SUMMON_LYNX, true); - DoSpawnCreature(MOB_SPIRIT_LYNX, 5,5,0,0, TEMPSUMMON_CORPSE_DESPAWN, 0); - me->SetMaxHealth(400000); - me->SetHealth(400000); - ShockTimer = 10000; - TotemTimer = 12000; - break; - case PHASE_MERGE: - if (Unit *pLynx = Unit::GetUnit(*me, LynxGUID)) - { - me->MonsterYell(YELL_MERGE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_MERGE); - pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pLynx->GetMotionMaster()->Clear(); - pLynx->GetMotionMaster()->MoveFollow(me, 0, 0); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveFollow(pLynx, 0, 0); - ++TransformCount; - } - break; - default: - break; - } - Phase = NextPhase; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BerserkTimer <= diff) - { - me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_BERSERK); - DoCast(me, SPELL_BERSERK, true); - BerserkTimer = 60000; - } else BerserkTimer -= diff; - - if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE) - { - if (SaberlashTimer <= diff) - { - // A tank with more than 490 defense skills should receive no critical hit - //DoCast(me, 41296, true); - DoCast(me->getVictim(), SPELL_SABER_LASH, true); - //me->RemoveAurasDueToSpell(41296); - SaberlashTimer = 30000; - } else SaberlashTimer -= diff; - - if (FrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - FrenzyTimer = urand(10000,15000); - } else FrenzyTimer -= diff; - - if (Phase == PHASE_LYNX) - if (CheckTimer <= diff) - { - if (me->GetHealth() * 4 < me->GetMaxHealth() * (3 - TransformCount)) - EnterPhase(PHASE_SPLIT); - CheckTimer = 1000; - } else CheckTimer -= diff; - } - - if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE) - { - if (TotemTimer <= diff) - { - DoCast(me, SPELL_SUMMON_TOTEM); - TotemTimer = 20000; - } else TotemTimer -= diff; - - if (ShockTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget->IsNonMeleeSpellCasted(false)) - DoCast(pTarget, SPELL_EARTHSHOCK); - else - DoCast(pTarget, SPELL_FLAMESHOCK); - ShockTimer = 10000 + rand()%5000; - } - } else ShockTimer -= diff; - - if (Phase == PHASE_HUMAN) - if (CheckTimer <= diff) - { - if (((me->GetHealth()*100) / me->GetMaxHealth() <= 20)/*me->GetHealth() * 10 < me->GetMaxHealth()*/) - EnterPhase(PHASE_MERGE); - else - { - Unit *Lynx = Unit::GetUnit(*me, LynxGUID); - if (Lynx && ((Lynx->GetHealth()*100) / Lynx->GetMaxHealth() <= 20)/*Lynx->GetHealth() * 10 < Lynx->GetMaxHealth()*/) - EnterPhase(PHASE_MERGE); - } - CheckTimer = 1000; - } else CheckTimer -= diff; - } - - if (Phase == PHASE_MERGE) - { - if (CheckTimer <= diff) - { - Unit *Lynx = Unit::GetUnit(*me, LynxGUID); - if (Lynx) - { - Lynx->GetMotionMaster()->MoveFollow(me, 0, 0); - me->GetMotionMaster()->MoveFollow(Lynx, 0, 0); - if (me->IsWithinDistInMap(Lynx, 6.0f)) - { - if (TransformCount < 3) - EnterPhase(PHASE_LYNX); - else - EnterPhase(PHASE_ENRAGE); - } - } - CheckTimer = 1000; - } else CheckTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,1)) - { - case 0: - me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL_ONE); - break; - - case 1: - me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL_TWO); - break; - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_HALAZZIEVENT, DONE); - - me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_DEATH); - } -}; - -// Spirits Lynx AI - -struct boss_spiritlynxAI : public ScriptedAI -{ - boss_spiritlynxAI(Creature *c) : ScriptedAI(c) {} - - uint32 FrenzyTimer; - uint32 shredder_timer; - - void Reset() - { - FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds - shredder_timer = 4000; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - damage = 0; - } - - void AttackStart(Unit *who) - { - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (FrenzyTimer <= diff) - { - DoCast(me, SPELL_LYNX_FRENZY); - FrenzyTimer = urand(30000,50000); //frenzy every 30-50 seconds - } else FrenzyTimer -= diff; - - if (shredder_timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHRED_ARMOR); - shredder_timer = 4000; - } else shredder_timer -= diff; - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_boss_halazziAI(Creature* pCreature) -{ - return new boss_halazziAI (pCreature); -} - -CreatureAI* GetAI_boss_spiritlynxAI(Creature* pCreature) -{ - return new boss_spiritlynxAI (pCreature); -} - -void AddSC_boss_halazzi() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_halazzi"; - newscript->GetAI = &GetAI_boss_halazziAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_halazzi_lynx"; - newscript->GetAI = &GetAI_boss_spiritlynxAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp deleted file mode 100644 index 7baa9292142..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/boss_hexlord.cpp +++ /dev/null @@ -1,907 +0,0 @@ -/* Copyright ?2006,2007 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Hex_Lord_Malacrass -SD%Complete: -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" - -#define YELL_AGGRO "Da shadow gonna fall on you... " -#define SOUND_YELL_AGGRO 12041 -#define YELL_SPIRIT_BOLTS "Your soul gonna bleed!" -#define SOUND_YELL_SPIRIT_BOLTS 12047 -#define YELL_DRAIN_POWER "Darkness comin\' for you" -#define SOUND_YELL_DRAIN_POWER 12046 -#define YELL_KILL_ONE "Dis a nightmare ya don\' wake up from!" -#define SOUND_YELL_KILL_ONE 12043 -#define YELL_KILL_TWO "Azzaga choogo zinn!" -#define SOUND_YELL_KILL_TWO 12044 -#define YELL_DEATH "Dis not... da end of me..." -#define SOUND_YELL_DEATH 12051 - -#define SPELL_SPIRIT_BOLTS 43383 -#define SPELL_DRAIN_POWER 44131 -#define SPELL_SIPHON_SOUL 43501 - -#define MOB_TEMP_TRIGGER 23920 - -//Defines for various powers he uses after using soul drain - -//Druid -#define SPELL_DR_LIFEBLOOM 43421 -#define SPELL_DR_THORNS 43420 -#define SPELL_DR_MOONFIRE 43545 - -//Hunter -#define SPELL_HU_EXPLOSIVE_TRAP 43444 -#define SPELL_HU_FREEZING_TRAP 43447 -#define SPELL_HU_SNAKE_TRAP 43449 - -//Mage -#define SPELL_MG_FIREBALL 41383 -#define SPELL_MG_FROSTBOLT 43428 -#define SPELL_MG_FROST_NOVA 43426 -#define SPELL_MG_ICE_LANCE 43427 - -//Paladin -#define SPELL_PA_CONSECRATION 43429 -#define SPELL_PA_HOLY_LIGHT 43451 -#define SPELL_PA_AVENGING_WRATH 43430 - -//Priest -#define SPELL_PR_HEAL 41372 -#define SPELL_PR_MIND_CONTROL 43550 -#define SPELL_PR_MIND_BLAST 41374 -#define SPELL_PR_SW_DEATH 41375 -#define SPELL_PR_PSYCHIC_SCREAM 43432 -#define SPELL_PR_PAIN_SUPP 44416 - -//Rogue -#define SPELL_RO_BLIND 43433 -#define SPELL_RO_SLICE_DICE 43457 -#define SPELL_RO_WOUND_POISON 39665 - -//Shaman -#define SPELL_SH_FIRE_NOVA 43436 -#define SPELL_SH_HEALING_WAVE 43548 -#define SPELL_SH_CHAIN_LIGHT 43435 - -//Warlock -#define SPELL_WL_CURSE_OF_DOOM 43439 -#define SPELL_WL_RAIN_OF_FIRE 43440 -#define SPELL_WL_UNSTABLE_AFFL 35183 - -//Warrior -#define SPELL_WR_SPELL_REFLECT 43443 -#define SPELL_WR_WHIRLWIND 43442 -#define SPELL_WR_MORTAL_STRIKE 43441 - -#define ORIENT 1.5696 -#define POS_Y 921.2795 -#define POS_Z 33.8883 - -static float Pos_X[4] = {112.8827, 107.8827, 122.8827, 127.8827}; - -static uint32 AddEntryList[8]= -{ - 24240, //Alyson Antille - 24241, //Thurg - 24242, //Slither - 24243, //Lord Raadan - 24244, //Gazakroth - 24245, //Fenstalker - 24246, //Darkheart - 24247 //Koragg -}; - -enum AbilityTarget -{ - ABILITY_TARGET_SELF = 0, - ABILITY_TARGET_VICTIM = 1, - ABILITY_TARGET_ENEMY = 2, - ABILITY_TARGET_HEAL = 3, - ABILITY_TARGET_BUFF = 4, - ABILITY_TARGET_SPECIAL = 5 -}; - -struct PlayerAbilityStruct -{ - uint32 spell; - AbilityTarget target; - uint32 cooldown; -}; - -static PlayerAbilityStruct PlayerAbility[][3] = -{ - // 1 warrior - {{SPELL_WR_SPELL_REFLECT, ABILITY_TARGET_SELF, 10000}, - {SPELL_WR_WHIRLWIND, ABILITY_TARGET_SELF, 10000}, - {SPELL_WR_MORTAL_STRIKE, ABILITY_TARGET_VICTIM, 6000}}, - // 2 paladin - {{SPELL_PA_CONSECRATION, ABILITY_TARGET_SELF, 10000}, - {SPELL_PA_HOLY_LIGHT, ABILITY_TARGET_HEAL, 10000}, - {SPELL_PA_AVENGING_WRATH, ABILITY_TARGET_SELF, 10000}}, - // 3 hunter - {{SPELL_HU_EXPLOSIVE_TRAP, ABILITY_TARGET_SELF, 10000}, - {SPELL_HU_FREEZING_TRAP, ABILITY_TARGET_SELF, 10000}, - {SPELL_HU_SNAKE_TRAP, ABILITY_TARGET_SELF, 10000}}, - // 4 rogue - {{SPELL_RO_WOUND_POISON, ABILITY_TARGET_VICTIM, 3000}, - {SPELL_RO_SLICE_DICE, ABILITY_TARGET_SELF, 10000}, - {SPELL_RO_BLIND, ABILITY_TARGET_ENEMY, 10000}}, - // 5 priest - {{SPELL_PR_PAIN_SUPP, ABILITY_TARGET_HEAL, 10000}, - {SPELL_PR_HEAL, ABILITY_TARGET_HEAL, 10000}, - {SPELL_PR_PSYCHIC_SCREAM, ABILITY_TARGET_SELF, 10000}}, - // 5* shadow priest - {{SPELL_PR_MIND_CONTROL, ABILITY_TARGET_ENEMY, 15000}, - {SPELL_PR_MIND_BLAST, ABILITY_TARGET_ENEMY, 5000}, - {SPELL_PR_SW_DEATH, ABILITY_TARGET_ENEMY, 10000}}, - // 7 shaman - {{SPELL_SH_FIRE_NOVA, ABILITY_TARGET_SELF, 10000}, - {SPELL_SH_HEALING_WAVE, ABILITY_TARGET_HEAL, 10000}, - {SPELL_SH_CHAIN_LIGHT, ABILITY_TARGET_ENEMY, 8000}}, - // 8 mage - {{SPELL_MG_FIREBALL, ABILITY_TARGET_ENEMY, 5000}, - {SPELL_MG_FROSTBOLT, ABILITY_TARGET_ENEMY, 5000}, - {SPELL_MG_ICE_LANCE, ABILITY_TARGET_SPECIAL, 2000}}, - // 9 warlock - {{SPELL_WL_CURSE_OF_DOOM, ABILITY_TARGET_ENEMY, 10000}, - {SPELL_WL_RAIN_OF_FIRE, ABILITY_TARGET_ENEMY, 10000}, - {SPELL_WL_UNSTABLE_AFFL, ABILITY_TARGET_ENEMY, 10000}}, - // 11 druid - {{SPELL_DR_LIFEBLOOM, ABILITY_TARGET_HEAL, 10000}, - {SPELL_DR_THORNS, ABILITY_TARGET_SELF, 10000}, - {SPELL_DR_MOONFIRE, ABILITY_TARGET_ENEMY, 8000}} -}; - -struct boss_hexlord_addAI : public ScriptedAI -{ - ScriptedInstance* pInstance; - - boss_hexlord_addAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() {} - - void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} - - void UpdateAI(const uint32 /*diff*/) - { - if (pInstance && pInstance->GetData(DATA_HEXLORDEVENT) != IN_PROGRESS) - { - EnterEvadeMode(); - return; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_hex_lord_malacrassAI : public ScriptedAI -{ - boss_hex_lord_malacrassAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - SelectAddEntry(); - for (uint8 i = 0; i < 4; ++i) - AddGUID[i] = 0; - } - - ScriptedInstance *pInstance; - - uint64 AddGUID[4]; - uint32 AddEntry[4]; - - uint64 PlayerGUID; - - uint32 SpiritBolts_Timer; - uint32 DrainPower_Timer; - uint32 SiphonSoul_Timer; - uint32 PlayerAbility_Timer; - uint32 CheckAddState_Timer; - uint32 ResetTimer; - - uint32 PlayerClass; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_HEXLORDEVENT, NOT_STARTED); - - SpiritBolts_Timer = 20000; - DrainPower_Timer = 60000; - SiphonSoul_Timer = 100000; - PlayerAbility_Timer = 99999; - CheckAddState_Timer = 5000; - ResetTimer = 5000; - - SpawnAdds(); - - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 46916); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HEXLORDEVENT, IN_PROGRESS); - - DoZoneInCombat(); - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_AGGRO); - - for (uint8 i = 0; i < 4; ++i) - { - Unit* Temp = Unit::GetUnit((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - CAST_CRE(Temp)->AI()->AttackStart(me->getVictim()); - else - { - EnterEvadeMode(); - break; - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,1)) - { - case 0: - me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); - break; - case 1: - me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); - break; - } - } - - void JustDied(Unit* /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_HEXLORDEVENT, DONE); - - me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_DEATH); - - for (uint8 i = 0; i < 4 ; ++i) - { - Unit* Temp = Unit::GetUnit((*me),AddGUID[i]); - if (Temp && Temp->isAlive()) - Temp->DealDamage(Temp, Temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - void SelectAddEntry() - { - std::vector AddList; - - for (uint8 i = 0; i < 8; ++i) - AddList.push_back(AddEntryList[i]); - - while (AddList.size() > 4) - AddList.erase(AddList.begin()+rand()%AddList.size()); - - uint8 i = 0; - for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr, ++i) - AddEntry[i] = *itr; - } - - void SpawnAdds() - { - for (uint8 i = 0; i < 4; ++i) - { - Creature *pCreature = (Unit::GetCreature((*me), AddGUID[i])); - if (!pCreature || !pCreature->isAlive()) - { - if (pCreature) pCreature->setDeathState(DEAD); - pCreature = me->SummonCreature(AddEntry[i], Pos_X[i], POS_Y, POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0); - if (pCreature) AddGUID[i] = pCreature->GetGUID(); - } - else - { - pCreature->AI()->EnterEvadeMode(); - pCreature->GetMap()->CreatureRelocation(me, Pos_X[i], POS_Y, POS_Z, ORIENT); - pCreature->StopMoving(); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ResetTimer <= diff) - { - if (me->IsWithinDist3d(119.223, 1035.45, 29.4481, 10)) - { - EnterEvadeMode(); - return; - } - ResetTimer = 5000; - } else ResetTimer -= diff; - - if (CheckAddState_Timer <= diff) - { - for (uint8 i = 0; i < 4; ++i) - if (Creature *pTemp = Unit::GetCreature(*me, AddGUID[i])) - if (pTemp->isAlive() && !pTemp->getVictim()) - pTemp->AI()->AttackStart(me->getVictim()); - - CheckAddState_Timer = 5000; - } else CheckAddState_Timer -= diff; - - if (DrainPower_Timer <= diff) - { - DoCast(me, SPELL_DRAIN_POWER, true); - me->MonsterYell(YELL_DRAIN_POWER, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_DRAIN_POWER); - DrainPower_Timer = urand(40000,55000); // must cast in 60 sec, or buff/debuff will disappear - } else DrainPower_Timer -= diff; - - if (SpiritBolts_Timer <= diff) - { - if (DrainPower_Timer < 12000) // channel 10 sec - SpiritBolts_Timer = 13000; // cast drain power first - else - { - DoCast(me, SPELL_SPIRIT_BOLTS, false); - me->MonsterYell(YELL_SPIRIT_BOLTS, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_SPIRIT_BOLTS); - SpiritBolts_Timer = 40000; - SiphonSoul_Timer = 10000; // ready to drain - PlayerAbility_Timer = 99999; - } - } else SpiritBolts_Timer -= diff; - - if (SiphonSoul_Timer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 70, true); - Unit *trigger = DoSpawnCreature(MOB_TEMP_TRIGGER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); - if (!pTarget || !trigger) - { - EnterEvadeMode(); - return; - } - else - { - trigger->SetDisplayId(11686); - trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - trigger->CastSpell(pTarget, SPELL_SIPHON_SOUL, true); - trigger->GetMotionMaster()->MoveChase(me); - - //DoCast(pTarget, SPELL_SIPHON_SOUL, true); - //me->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pTarget->GetGUID()); - //me->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SIPHON_SOUL); - - PlayerGUID = pTarget->GetGUID(); - PlayerAbility_Timer = urand(8000,10000); - PlayerClass = pTarget->getClass() - 1; - - if (PlayerClass == CLASS_DRUID-1) - PlayerClass = CLASS_DRUID; - else if (PlayerClass == CLASS_PRIEST-1 && pTarget->HasSpell(15473)) - PlayerClass = CLASS_PRIEST; // shadow priest - - SiphonSoul_Timer = 99999; // buff lasts 30 sec - } - } else SiphonSoul_Timer -= diff; - - if (PlayerAbility_Timer <= diff) - { - //Unit *pTarget = Unit::GetUnit(*me, PlayerGUID); - //if (pTarget && pTarget->isAlive()) - //{ - UseAbility(); - PlayerAbility_Timer = urand(8000,10000); - //} - } else PlayerAbility_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - void UseAbility() - { - uint8 random = urand(0,2); - Unit *pTarget = NULL; - switch(PlayerAbility[PlayerClass][random].target) - { - case ABILITY_TARGET_SELF: - pTarget = me; - break; - case ABILITY_TARGET_VICTIM: - pTarget = me->getVictim(); - break; - case ABILITY_TARGET_ENEMY: - default: - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - break; - case ABILITY_TARGET_HEAL: - pTarget = DoSelectLowestHpFriendly(50, 0); - break; - case ABILITY_TARGET_BUFF: - { - std::list templist = DoFindFriendlyMissingBuff(50, PlayerAbility[PlayerClass][random].spell); - if (!templist.empty()) - pTarget = *(templist.begin()); - } - break; - } - if (pTarget) - DoCast(pTarget, PlayerAbility[PlayerClass][random].spell, false); - } -}; - -#define SPELL_BLOODLUST 43578 -#define SPELL_CLEAVE 15496 - -struct boss_thurgAI : public boss_hexlord_addAI -{ - - boss_thurgAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 bloodlust_timer; - uint32 cleave_timer; - - void Reset() - { - bloodlust_timer = 15000; - cleave_timer = 10000; - - boss_hexlord_addAI::Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (bloodlust_timer <= diff) - { - std::list templist = DoFindFriendlyMissingBuff(50, SPELL_BLOODLUST); - if (!templist.empty()) - { - if (Unit *pTarget = *(templist.begin())) - DoCast(pTarget, SPELL_BLOODLUST, false); - } - bloodlust_timer = 12000; - } else bloodlust_timer -= diff; - - if (cleave_timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE, false); - cleave_timer = 12000; //3 sec cast - } else cleave_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_FLASH_HEAL 43575 -#define SPELL_DISPEL_MAGIC 43577 - -struct boss_alyson_antilleAI : public boss_hexlord_addAI -{ - //Holy Priest - boss_alyson_antilleAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 flashheal_timer; - uint32 dispelmagic_timer; - - void Reset() - { - flashheal_timer = 2500; - dispelmagic_timer = 10000; - - //AcquireGUID(); - - boss_hexlord_addAI::Reset(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack()) - { - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, 20); - me->AddThreat(who, 0.0f); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (flashheal_timer <= diff) - { - Unit *pTarget = DoSelectLowestHpFriendly(99, 30000); - if (pTarget) - { - if (pTarget->IsWithinDistInMap(me, 50)) - DoCast(pTarget, SPELL_FLASH_HEAL, false); - else - { - // bugged - //me->GetMotionMaster()->Clear(); - //me->GetMotionMaster()->MoveChase(pTarget, 20); - } - } - else - { - if (urand(0,1)) - pTarget = DoSelectLowestHpFriendly(50, 0); - else - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_DISPEL_MAGIC, false); - } - flashheal_timer = 2500; - } else flashheal_timer -= diff; - - /*if (dispelmagic_timer <= diff) - { - if (urand(0,1)) - { - Unit *pTarget = SelectTarget(); - - DoCast(pTarget, SPELL_DISPEL_MAGIC, false); - } - else - me->CastSpell(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DISPEL_MAGIC, false); - - dispelmagic_timer = 12000; - } else dispelmagic_timer -= diff;*/ - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_FIREBOLT 43584 - -struct boss_gazakrothAI : public boss_hexlord_addAI -{ - boss_gazakrothAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 firebolt_timer; - - void Reset() - { - firebolt_timer = 2000; - boss_hexlord_addAI::Reset(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack()) - { - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, 20); - me->AddThreat(who, 0.0f); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (firebolt_timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBOLT, false); - firebolt_timer = 700; - } else firebolt_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_FLAME_BREATH 43582 -#define SPELL_THUNDERCLAP 43583 - -struct boss_lord_raadanAI : public boss_hexlord_addAI -{ - boss_lord_raadanAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 flamebreath_timer; - uint32 thunderclap_timer; - - void Reset() - { - flamebreath_timer = 8000; - thunderclap_timer = 13000; - - boss_hexlord_addAI::Reset(); - - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (thunderclap_timer <= diff) - { - DoCast(me->getVictim(), SPELL_THUNDERCLAP, false); - thunderclap_timer = 12000; - } else thunderclap_timer -= diff; - - if (flamebreath_timer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAME_BREATH, false); - flamebreath_timer = 12000; - } else flamebreath_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_PSYCHIC_WAIL 43590 - -struct boss_darkheartAI : public boss_hexlord_addAI -{ - boss_darkheartAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 psychicwail_timer; - - void Reset() - { - psychicwail_timer = 8000; - boss_hexlord_addAI::Reset(); - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (psychicwail_timer <= diff) - { - DoCast(me->getVictim(), SPELL_PSYCHIC_WAIL, false); - psychicwail_timer = 12000; - } else psychicwail_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -#define SPELL_VENOM_SPIT 43579 - -struct boss_slitherAI : public boss_hexlord_addAI -{ - boss_slitherAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 venomspit_timer; - - void Reset() - { - venomspit_timer = 5000; - boss_hexlord_addAI::Reset(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack()) - { - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, 20); - me->AddThreat(who, 0.0f); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (venomspit_timer <= diff) - { - if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(victim, SPELL_VENOM_SPIT, false); - venomspit_timer = 2500; - } else venomspit_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -//Fenstalker -#define SPELL_VOLATILE_INFECTION 43586 - -struct boss_fenstalkerAI : public boss_hexlord_addAI -{ - boss_fenstalkerAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 volatileinf_timer; - - void Reset() - { - volatileinf_timer = 15000; - boss_hexlord_addAI::Reset(); - - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (volatileinf_timer <= diff) - { - // core bug - me->getVictim()->CastSpell(me->getVictim(),SPELL_VOLATILE_INFECTION, false); - volatileinf_timer = 12000; - } else volatileinf_timer -= diff; - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -//Koragg -#define SPELL_COLD_STARE 43593 -#define SPELL_MIGHTY_BLOW 43592 - -struct boss_koraggAI : public boss_hexlord_addAI -{ - boss_koraggAI(Creature *c) : boss_hexlord_addAI(c) {} - - uint32 coldstare_timer; - uint32 mightyblow_timer; - - void Reset() - { - coldstare_timer = 15000; - mightyblow_timer = 10000; - boss_hexlord_addAI::Reset(); - - } - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (mightyblow_timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, false); - mightyblow_timer = 12000; - } - if (coldstare_timer <= diff) - { - if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(victim, SPELL_COLD_STARE, false); - coldstare_timer = 12000; - } - - boss_hexlord_addAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_boss_hex_lord_malacrass(Creature* pCreature) -{ - return new boss_hex_lord_malacrassAI (pCreature); -} - -CreatureAI* GetAI_boss_thurg(Creature* pCreature) -{ - return new boss_thurgAI (pCreature); -} - -CreatureAI* GetAI_boss_alyson_antille(Creature* pCreature) -{ - return new boss_alyson_antilleAI (pCreature); -} - -CreatureAI* GetAI_boss_gazakroth(Creature* pCreature) -{ - return new boss_gazakrothAI (pCreature); -} - -CreatureAI* GetAI_boss_lord_raadan(Creature* pCreature) -{ - return new boss_lord_raadanAI (pCreature); -} - -CreatureAI* GetAI_boss_darkheart(Creature* pCreature) -{ - return new boss_darkheartAI (pCreature); -} - -CreatureAI* GetAI_boss_slither(Creature* pCreature) -{ - return new boss_slitherAI (pCreature); -} - -CreatureAI* GetAI_boss_fenstalker(Creature* pCreature) -{ - return new boss_fenstalkerAI (pCreature); -} - -CreatureAI* GetAI_boss_koragg(Creature* pCreature) -{ - return new boss_koraggAI (pCreature); -} -void AddSC_boss_hex_lord_malacrass() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hexlord_malacrass"; - newscript->GetAI = &GetAI_boss_hex_lord_malacrass; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_thurg"; - newscript->GetAI = &GetAI_boss_thurg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_gazakroth"; - newscript->GetAI = &GetAI_boss_gazakroth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_raadan"; - newscript->GetAI = &GetAI_boss_lord_raadan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_darkheart"; - newscript->GetAI = &GetAI_boss_darkheart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_slither"; - newscript->GetAI = &GetAI_boss_slither; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fenstalker"; - newscript->GetAI = &GetAI_boss_fenstalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_koragg"; - newscript->GetAI = &GetAI_boss_koragg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_alyson_antille"; - newscript->GetAI = &GetAI_boss_alyson_antille; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp deleted file mode 100644 index 9ac54976241..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/boss_janalai.cpp +++ /dev/null @@ -1,687 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -*(at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Janalai -SD%Complete: 100 -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" -#include "GridNotifiers.h" - -enum eEnums -{ - SAY_AGGRO = -1568000, - SAY_FIRE_BOMBS = -1568001, - SAY_SUMMON_HATCHER = -1568002, - SAY_ALL_EGGS = -1568003, - SAY_BERSERK = -1568004, - SAY_SLAY_1 = -1568005, - SAY_SLAY_2 = -1568006, - SAY_DEATH = -1568007, - SAY_EVENT_STRANGERS = -1568008, - SAY_EVENT_FRIENDS = -1568009, - -// Jan'alai - SPELL_FLAME_BREATH = 43140, - SPELL_FIRE_WALL = 43113, - SPELL_ENRAGE = 44779, - SPELL_SUMMON_PLAYERS = 43097, - SPELL_TELE_TO_CENTER = 43098, // coord - SPELL_HATCH_ALL = 43144, - SPELL_BERSERK = 45078, - -// -- Fire Bob Spells - SPELL_FIRE_BOMB_CHANNEL = 42621, // last forever - SPELL_FIRE_BOMB_THROW = 42628, // throw visual - SPELL_FIRE_BOMB_DUMMY = 42629, // bomb visual - SPELL_FIRE_BOMB_DAMAGE = 42630, - -// --Summons - MOB_AMANI_HATCHER = 23818, - MOB_HATCHLING = 23598, // 42493 - MOB_EGG = 23817, - MOB_FIRE_BOMB = 23920, - -// -- Hatcher Spells - SPELL_HATCH_EGG = 43734, // 42471 - -// -- Hatchling Spells - SPELL_FLAMEBUFFET = 43299 -}; - -const int area_dx = 44; -const int area_dy = 51; - -float JanalainPos[1][3] = -{ - {-33.93, 1149.27, 19} -}; - -float FireWallCoords[4][4] = -{ - {-10.13, 1149.27, 19, 3.1415}, - {-33.93, 1123.90, 19, 0.5*3.1415}, - {-54.80, 1150.08, 19, 0}, - {-33.93, 1175.68, 19, 1.5*3.1415} -}; - -float hatcherway[2][5][3] = -{ - { - {-87.46,1170.09,6}, - {-74.41,1154.75,6}, - {-52.74,1153.32,19}, - {-33.37,1172.46,19}, - {-33.09,1203.87,19} - }, - { - {-86.57,1132.85,6}, - {-73.94,1146.00,6}, - {-52.29,1146.51,19}, - {-33.57,1125.72,19}, - {-34.29,1095.22,19} - } -}; - -struct boss_janalaiAI : public ScriptedAI -{ - boss_janalaiAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - - SpellEntry *TempSpell = GET_SPELL(SPELL_HATCH_EGG); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) - { - TempSpell->EffectImplicitTargetA[0] = 1; - TempSpell->EffectImplicitTargetB[0] = 0; - } - } - - ScriptedInstance *pInstance; - - uint32 FireBreathTimer; - uint32 BombTimer; - uint32 BombSequenceTimer; - uint32 BombCount; - uint32 HatcherTimer; - uint32 EnrageTimer; - - bool noeggs; - bool enraged; - bool isBombing; - - bool isFlameBreathing; - - uint64 FireBombGUIDs[40]; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_JANALAIEVENT, NOT_STARTED); - - FireBreathTimer = 8000; - BombTimer = 30000; - BombSequenceTimer = 1000; - BombCount = 0; - HatcherTimer = 10000; - EnrageTimer = MINUTE*5*IN_MILISECONDS; - - noeggs = false; - isBombing =false; - enraged = false; - - isFlameBreathing = false; - - for (uint8 i = 0; i < 40; ++i) - FireBombGUIDs[i] = 0; - - HatchAllEggs(1); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_JANALAIEVENT, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_JANALAIEVENT, IN_PROGRESS); - - DoScriptText(SAY_AGGRO, me); -// DoZoneInCombat(); - } - - void DamageDeal(Unit *pTarget, uint32 &damage) - { - if (isFlameBreathing) - { - if (!me->HasInArc(M_PI/6, pTarget)) - damage = 0; - } - } - - void FireWall() - { - uint8 WallNum; - Creature* wall = NULL; - for (uint8 i = 0; i < 4; ++i) - { - if (i == 0 || i == 2) - WallNum = 3; - else - WallNum = 2; - - for (uint8 j = 0; j < WallNum; j++) - { - if (WallNum == 3) - wall = me->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0],FireWallCoords[i][1]+5*(j-1),FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000); - else - wall = me->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0]-2+4*j,FireWallCoords[i][1],FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000); - if (wall) wall->CastSpell(wall, SPELL_FIRE_WALL, true); - } - } - } - - void SpawnBombs() - { - float dx, dy; - for (int i(0); i < 40; ++i) - { - dx = irand(-area_dx/2, area_dx/2); - dy = irand(-area_dy/2, area_dy/2); - - Creature* bomb = DoSpawnCreature(MOB_FIRE_BOMB, dx, dy, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); - if (bomb) FireBombGUIDs[i] = bomb->GetGUID(); - } - BombCount = 0; - } - - bool HatchAllEggs(uint32 uiAction) //1: reset, 2: isHatching all - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllCreaturesOfEntryInRange check(me, MOB_EGG, 100); - Trinity::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap())); - } - - //error_log("Eggs %d at middle", templist.size()); - if (!templist.size()) - return false; - - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - if (uiAction == 1) - (*i)->SetDisplayId(10056); - else if (uiAction == 2 &&(*i)->GetDisplayId() != 11686) - (*i)->CastSpell(*i, SPELL_HATCH_EGG, false); - } - return true; - } - - void Boom() - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllCreaturesOfEntryInRange check(me, MOB_FIRE_BOMB, 100); - Trinity::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap())); - } - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - (*i)->CastSpell(*i, SPELL_FIRE_BOMB_DAMAGE, true); - (*i)->RemoveAllAuras(); - } - } - - void HandleBombSequence() - { - if (BombCount < 40) - { - if (Unit *FireBomb = Unit::GetUnit((*me), FireBombGUIDs[BombCount])) - { - FireBomb->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(FireBomb, SPELL_FIRE_BOMB_THROW, true); - FireBomb->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - ++BombCount; - if (BombCount == 40) - { - BombSequenceTimer = 5000; - } else BombSequenceTimer = 100; - } - else - { - Boom(); - isBombing = false; - BombTimer = urand(20000,40000); - me->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_CHANNEL); - if (EnrageTimer <= 10000) - EnrageTimer = 0; - else - EnrageTimer -= 10000; - } - } - - void UpdateAI(const uint32 diff) - { - if (isFlameBreathing) - { - if (!me->IsNonMeleeSpellCasted(false)) - isFlameBreathing = false; - else - return; - } - - if (isBombing) - { - if (BombSequenceTimer <= diff) - HandleBombSequence(); - else - BombSequenceTimer -= diff; - return; - } - - if (!UpdateVictim()) - return; - - //enrage if under 25% hp before 5 min. - if (!enraged && me->GetHealth() * 4 < me->GetMaxHealth()) - EnrageTimer = 0; - - if (EnrageTimer <= diff) - { - if (!enraged) - { - DoCast(me, SPELL_ENRAGE, true); - enraged = true; - EnrageTimer = 300000; - } - else - { - DoScriptText(SAY_BERSERK, me); - DoCast(me, SPELL_BERSERK, true); - EnrageTimer = 300000; - } - } else EnrageTimer -= diff; - - if (BombTimer <= diff) - { - DoScriptText(SAY_FIRE_BOMBS, me); - - me->AttackStop(); - me->GetMotionMaster()->Clear(); - DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); - me->StopMoving(); - DoCast(me, SPELL_FIRE_BOMB_CHANNEL, false); - //DoTeleportPlayer(me, JanalainPos[0][0], JanalainPos[0][1],JanalainPos[0][2], 0); - //DoCast(me, SPELL_TELE_TO_CENTER, true); - - FireWall(); - SpawnBombs(); - isBombing = true; - BombSequenceTimer = 100; - - //Teleport every Player into the middle - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) return; - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* i_pl = i->getSource()) - if (i_pl->isAlive()) - DoTeleportPlayer(i_pl, JanalainPos[0][0]-5+rand()%10, JanalainPos[0][1]-5+rand()%10, JanalainPos[0][2], 0); - //DoCast(Temp, SPELL_SUMMON_PLAYERS, true) // core bug, spell does not work if too far - return; - } else BombTimer -= diff; - - if (!noeggs) - { - if (100 * me->GetHealth() < 35 * me->GetMaxHealth()) - { - DoScriptText(SAY_ALL_EGGS, me); - - me->AttackStop(); - me->GetMotionMaster()->Clear(); - DoTeleportTo(JanalainPos[0][0],JanalainPos[0][1],JanalainPos[0][2]); - me->StopMoving(); - DoCast(me, SPELL_HATCH_ALL, false); - HatchAllEggs(2); - noeggs = true; - } - else if (HatcherTimer <= diff) - { - if (HatchAllEggs(0)) - { - DoScriptText(SAY_SUMMON_HATCHER, me); - me->SummonCreature(MOB_AMANI_HATCHER,hatcherway[0][0][0],hatcherway[0][0][1],hatcherway[0][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); - me->SummonCreature(MOB_AMANI_HATCHER,hatcherway[1][0][0],hatcherway[1][0][1],hatcherway[1][0][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,10000); - HatcherTimer = 90000; - } - else - noeggs = true; - } else HatcherTimer -= diff; - } - - EnterEvadeIfOutOfCombatArea(diff); - - DoMeleeAttackIfReady(); - - if (FireBreathTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - me->AttackStop(); - me->GetMotionMaster()->Clear(); - DoCast(pTarget, SPELL_FLAME_BREATH, false); - me->StopMoving(); - isFlameBreathing = true; - } - FireBreathTimer = 8000; - } else FireBreathTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_janalaiAI(Creature* pCreature) -{ - return new boss_janalaiAI(pCreature); -} - -struct mob_janalai_firebombAI : public ScriptedAI -{ - mob_janalai_firebombAI(Creature *c) : ScriptedAI(c){} - - void Reset() {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_FIRE_BOMB_THROW) - DoCast(me, SPELL_FIRE_BOMB_DUMMY, true); - } - - void EnterCombat(Unit* /*who*/) {} - - void AttackStart(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_mob_janalai_firebombAI(Creature* pCreature) -{ - return new mob_janalai_firebombAI(pCreature); -} - -struct mob_amanishi_hatcherAI : public ScriptedAI -{ - mob_amanishi_hatcherAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 waypoint; - uint32 HatchNum; - uint32 WaitTimer; - - bool side; - bool hasChangedSide; - bool isHatching; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - side =(me->GetPositionY() < 1150); - waypoint = 0; - isHatching = false; - hasChangedSide = false; - WaitTimer = 1; - HatchNum = 0; - } - - bool HatchEggs(uint32 num) - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllCreaturesOfEntryInRange check(me, 23817, 50); - Trinity::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap())); - } - - //error_log("Eggs %d at %d", templist.size(), side); - - for (std::list::const_iterator i = templist.begin(); i != templist.end() && num > 0; ++i) - if ((*i)->GetDisplayId() != 11686) - { - (*i)->CastSpell(*i, SPELL_HATCH_EGG, false); - num--; - } - - return num == 0; // if num == 0, no more templist - } - - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void MovementInform(uint32, uint32) - { - if (waypoint == 5) - { - isHatching = true; - HatchNum = 1; - WaitTimer = 5000; - } - else - WaitTimer = 1; - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance || !(pInstance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS)) - { - me->DisappearAndDie(); - return; - } - - if (!isHatching) - { - if (WaitTimer) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0,hatcherway[side][waypoint][0],hatcherway[side][waypoint][1],hatcherway[side][waypoint][2]); - ++waypoint; - WaitTimer = 0; - } - } - else - { - if (WaitTimer <= diff) - { - if (HatchEggs(HatchNum)) - { - ++HatchNum; - WaitTimer = 10000; - } - else if (!hasChangedSide) - { - side = side ? 0 : 1; - isHatching = false; - waypoint = 3; - WaitTimer = 1; - hasChangedSide = true; - } - else - me->DisappearAndDie(); - - } else WaitTimer -= diff; - } - } -}; - -CreatureAI* GetAI_mob_amanishi_hatcherAI(Creature* pCreature) -{ - return new mob_amanishi_hatcherAI(pCreature); -} - -struct mob_hatchlingAI : public ScriptedAI -{ - mob_hatchlingAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 BuffetTimer; - - void Reset() - { - BuffetTimer = 7000; - if (me->GetPositionY() > 1150) - me->GetMotionMaster()->MovePoint(0, hatcherway[0][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[0][3][2]); - else - me->GetMotionMaster()->MovePoint(0,hatcherway[1][3][0]+rand()%4-2,1150+rand()%4-2,hatcherway[1][3][2]); - - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - } - - void EnterCombat(Unit * /*who*/) {/*DoZoneInCombat();*/} - - void UpdateAI(const uint32 diff) - { - if (!pInstance || !(pInstance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS)) - { - me->DisappearAndDie(); - return; - } - - if (!UpdateVictim()) - return; - - if (BuffetTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAMEBUFFET, false); - BuffetTimer = 10000; - } else BuffetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_hatchlingAI(Creature* pCreature) -{ - return new mob_hatchlingAI(pCreature); -} - -struct mob_eggAI : public ScriptedAI -{ - mob_eggAI(Creature *c) : ScriptedAI(c){} - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_HATCH_EGG) - { - DoSpawnCreature(MOB_HATCHLING, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - me->SetDisplayId(11686); - } - } -}; - -CreatureAI* GetAI_mob_eggAI(Creature* pCreature) -{ - return new mob_eggAI(pCreature); -} - -void AddSC_boss_janalai() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_janalai"; - newscript->GetAI = &GetAI_boss_janalaiAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_janalai_firebomb"; - newscript->GetAI = &GetAI_mob_janalai_firebombAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_janalai_hatcher"; - newscript->GetAI = &GetAI_mob_amanishi_hatcherAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_janalai_hatchling"; - newscript->GetAI = &GetAI_mob_hatchlingAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_janalai_egg"; - newscript->GetAI = &GetAI_mob_eggAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp deleted file mode 100644 index ae5c6596d2d..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/boss_nalorakk.cpp +++ /dev/null @@ -1,451 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Nalorakk -SD%Complete: 100 -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" -#include "GridNotifiers.h" - -//Trash Waves -float NalorakkWay[8][3] = -{ - { 18.569, 1414.512, 11.42},// waypoint 1 - {-17.264, 1419.551, 12.62}, - {-52.642, 1419.357, 27.31},// waypoint 2 - {-69.908, 1419.721, 27.31}, - {-79.929, 1395.958, 27.31}, - {-80.072, 1374.555, 40.87},// waypoint 3 - {-80.072, 1314.398, 40.87}, - {-80.072, 1295.775, 48.60} // waypoint 4 -}; - -#define YELL_NALORAKK_WAVE1 "Get da move on, guards! It be killin' time!" -#define SOUND_NALORAKK_WAVE1 12066 -#define YELL_NALORAKK_WAVE2 "Guards, go already! Who you more afraid of, dem... or me?" -#define SOUND_NALORAKK_WAVE2 12067 -#define YELL_NALORAKK_WAVE3 "Ride now! Ride out dere and bring me back some heads!" -#define SOUND_NALORAKK_WAVE3 12068 -#define YELL_NALORAKK_WAVE4 "I be losin' me patience! Go on: make dem wish dey was never born!" -#define SOUND_NALORAKK_WAVE4 12069 - -//Unimplemented SoundIDs -/* -#define SOUND_NALORAKK_EVENT1 12078 -#define SOUND_NALORAKK_EVENT2 12079 -*/ - -//General defines -#define YELL_AGGRO "You be dead soon enough!" -#define SOUND_YELL_AGGRO 12070 -#define YELL_KILL_ONE "Mua-ha-ha! Now whatchoo got to say?" -#define SOUND_YELL_KILL_ONE 12075 -#define YELL_KILL_TWO "Da Amani gonna rule again!" -#define SOUND_YELL_KILL_TWO 12076 -#define YELL_DEATH "I... be waitin' on da udda side...." -#define SOUND_YELL_DEATH 12077 -#define YELL_BERSERK "You had your chance, now it be too late!" //Never seen this being used, so just guessing from what I hear. -#define SOUND_YELL_BERSERK 12074 - -#define SPELL_BERSERK 45078 - -//Defines for Troll form -#define SPELL_BRUTALSWIPE 42384 -#define SPELL_MANGLE 42389 -#define SPELL_MANGLEEFFECT 44955 -#define SPELL_SURGE 42402 -#define SPELL_BEARFORM 42377 - -#define YELL_SURGE "I bring da pain!" -#define SOUND_YELL_SURGE 12071 - -#define YELL_SHIFTEDTOTROLL "Make way for Nalorakk!" -#define SOUND_YELL_TOTROLL 12073 - -//Defines for Bear form -#define SPELL_LACERATINGSLASH 42395 -#define SPELL_RENDFLESH 42397 -#define SPELL_DEAFENINGROAR 42398 - -#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!" -#define SOUND_YELL_TOBEAR 12072 - -struct boss_nalorakkAI : public ScriptedAI -{ - boss_nalorakkAI(Creature *c) : ScriptedAI(c) - { - MoveEvent = true; - MovePhase = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 BrutalSwipe_Timer; - uint32 Mangle_Timer; - uint32 Surge_Timer; - - uint32 LaceratingSlash_Timer; - uint32 RendFlesh_Timer; - uint32 DeafeningRoar_Timer; - - uint32 ShapeShift_Timer; - uint32 Berserk_Timer; - - bool inBearForm; - bool MoveEvent; - bool inMove; - uint32 MovePhase; - uint32 waitTimer; - - void Reset() - { - if (MoveEvent) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - inMove = false; - waitTimer = 0; - me->SetSpeed(MOVE_RUN,2); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - }else - { - (*me).GetMotionMaster()->MovePoint(0,NalorakkWay[7][0],NalorakkWay[7][1],NalorakkWay[7][2]); - } - - if (pInstance) - pInstance->SetData(DATA_NALORAKKEVENT, NOT_STARTED); - - Surge_Timer = 15000 + rand()%5000; - BrutalSwipe_Timer = 7000 + rand()%5000; - Mangle_Timer = 10000 + rand()%5000; - ShapeShift_Timer = 45000 + rand()%5000; - Berserk_Timer = 600000; - - inBearForm = false; - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); // TODO: find the correct equipment id - } - - void SendAttacker(Unit *pTarget) - { - std::list templist; - float x, y, z; - me->GetPosition(x, y, z); - - { - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AllFriendlyCreaturesInGrid check(me); - Trinity::CreatureListSearcher searcher(me, templist, check); - - TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); - - cell.Visit(pair, cSearcher, *(me->GetMap())); - } - - if (!templist.size()) - return; - - for (std::list::const_iterator i = templist.begin(); i != templist.end(); ++i) - { - if ((*i) && me->IsWithinDistInMap((*i),25)) - { - (*i)->SetNoCallAssistance(true); - (*i)->AI()->AttackStart(pTarget); - } - } - } - - void AttackStart(Unit* who) - { - if (!MoveEvent) - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (!MoveEvent) - { - ScriptedAI::MoveInLineOfSight(who); - } - else - { - if (me->IsHostileTo(who)) - { - if (!inMove) - { - switch(MovePhase) - { - case 0: - if (me->IsWithinDistInMap(who, 50)) - { - me->MonsterYell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1); - - (*me).GetMotionMaster()->MovePoint(1,NalorakkWay[1][0],NalorakkWay[1][1],NalorakkWay[1][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 2: - if (me->IsWithinDistInMap(who, 40)) - { - me->MonsterYell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2); - - (*me).GetMotionMaster()->MovePoint(3,NalorakkWay[3][0],NalorakkWay[3][1],NalorakkWay[3][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 5: - if (me->IsWithinDistInMap(who, 40)) - { - me->MonsterYell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3); - - (*me).GetMotionMaster()->MovePoint(6,NalorakkWay[6][0],NalorakkWay[6][1],NalorakkWay[6][2]); - MovePhase ++; - inMove = true; - - SendAttacker(who); - } - break; - case 7: - if (me->IsWithinDistInMap(who, 50)) - { - SendAttacker(who); - - me->MonsterYell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - MoveEvent = false; - } - break; - } - } - } - } - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS); - - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_AGGRO); - DoZoneInCombat(); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_NALORAKKEVENT, DONE); - - me->MonsterYell(YELL_DEATH,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me, SOUND_YELL_DEATH); - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,1)) - { - case 0: - me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); - break; - case 1: - me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); - break; - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (MoveEvent) - { - if (type != POINT_MOTION_TYPE) - return; - - if (!inMove) - return; - - if (MovePhase != id) - return; - - switch(MovePhase) - { - case 2: - me->SetOrientation(3.1415*2); - inMove = false; - return; - case 1: - case 3: - case 4: - case 6: - MovePhase ++; - waitTimer = 1; - inMove = true; - return; - case 5: - me->SetOrientation(3.1415*0.5); - inMove = false; - return; - case 7: - me->SetOrientation(3.1415*0.5); - inMove = false; - return; - } - - } - } - - void UpdateAI(const uint32 diff) - { - if (waitTimer) - { - if (inMove) - if (waitTimer <= diff) - { - (*me).GetMotionMaster()->MovementExpired(); - (*me).GetMotionMaster()->MovePoint(MovePhase,NalorakkWay[MovePhase][0],NalorakkWay[MovePhase][1],NalorakkWay[MovePhase][2]); - waitTimer = 0; - } else waitTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_BERSERK); - Berserk_Timer = 600000; - } else Berserk_Timer -= diff; - - if (ShapeShift_Timer <= diff) - { - if (inBearForm) - { - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); - me->MonsterYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_TOTROLL); - me->RemoveAurasDueToSpell(SPELL_BEARFORM); - Surge_Timer = 15000 + rand()%5000; - BrutalSwipe_Timer = 7000 + rand()%5000; - Mangle_Timer = 10000 + rand()%5000; - ShapeShift_Timer = 45000 + rand()%5000; - inBearForm = false; - } - else - { - // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0); - me->MonsterYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_TOBEAR); - DoCast(me, SPELL_BEARFORM, true); - LaceratingSlash_Timer = 2000; // dur 18s - RendFlesh_Timer = 3000; // dur 5s - DeafeningRoar_Timer = 5000 + rand()%5000; // dur 2s - ShapeShift_Timer = 20000 + rand()%5000; // dur 30s - inBearForm = true; - } - } else ShapeShift_Timer -= diff; - - if (!inBearForm) - { - if (BrutalSwipe_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BRUTALSWIPE); - BrutalSwipe_Timer = 7000 + rand()%5000; - } else BrutalSwipe_Timer -= diff; - - if (Mangle_Timer <= diff) - { - if (me->getVictim() && !me->getVictim()->HasAura(SPELL_MANGLEEFFECT)) - { - DoCast(me->getVictim(), SPELL_MANGLE); - Mangle_Timer = 1000; - } - else Mangle_Timer = 10000 + rand()%5000; - } else Mangle_Timer -= diff; - - if (Surge_Timer <= diff) - { - me->MonsterYell(YELL_SURGE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_YELL_SURGE); - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true); - if (pTarget) - DoCast(pTarget, SPELL_SURGE); - Surge_Timer = 15000 + rand()%5000; - } else Surge_Timer -= diff; - } - else - { - if (LaceratingSlash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LACERATINGSLASH); - LaceratingSlash_Timer = 18000 + rand()%5000; - } else LaceratingSlash_Timer -= diff; - - if (RendFlesh_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_RENDFLESH); - RendFlesh_Timer = 5000 + rand()%5000; - } else RendFlesh_Timer -= diff; - - if (DeafeningRoar_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DEAFENINGROAR); - DeafeningRoar_Timer = 15000 + rand()%5000; - } else DeafeningRoar_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_nalorakk(Creature* pCreature) -{ - return new boss_nalorakkAI (pCreature); -} - -void AddSC_boss_nalorakk() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nalorakk"; - newscript->GetAI = &GetAI_boss_nalorakk; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp b/src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp deleted file mode 100644 index 91cfa728f89..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/boss_zuljin.cpp +++ /dev/null @@ -1,623 +0,0 @@ -/* Copyright (C) 2006,2007,2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_ZulJin -SD%Complete: 85% -SDComment: -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" - -//Speech -#define YELL_TRANSFORM_TO_LYNX "Let me introduce to you my new bruddahs: fang and claw!" -#define SOUND_TRANSFORM_TO_LYNX 12094 - -#define YELL_TRANSFORM_TO_BEAR "Got me some new tricks...like me bruddah bear!" -#define SOUND_TRANSFORM_TO_BEAR 12092 - -#define YELL_TRANSFORM_TO_DRAGONHAWK "Ya don' have to look to da sky to see da dragonhawk!" -#define SOUND_TRANSFORM_TO_DRAGONHAWK 12095 - -#define YELL_TRANSFORM_TO_EAGLE "Dere be no hidin' from da eagle!" -#define SOUND_TRANSFORM_TO_EAGLE 12093 - -#define YELL_KILL_ONE "Da Amani de chuka!" -#define SOUND_KILL_ONE 12098 - -#define YELL_KILL_TWO "Lot more gonna fall like you!" -#define SOUND_KILL_TWO 12099 - -#define YELL_FIRE_BREATH "Fire kill you just as quick!" -#define SOUND_FIRE_BRETH 12096 - -#define YELL_AGGRO "Nobody badduh dan me!" -#define SOUND_AGGRO 12091 - -#define YELL_BERSERK "You too slow! Me too strong!" -#define SOUND_BERSERK 12097 - -#define YELL_DEATH "Mebbe me fall...but da Amani empire...never gonna die..." -#define SOUND_DEATH 12100 - -//Still not used, need more info -#define YELL_INTRO "Everybody always wanna take from us. Now we gonna start takin' back. Anybody who get in our way...gonna drown in their own blood! De Amani empire be back now...seekin' vengeance. And we gonna start...with you!" -#define SOUND_INTRO 12090 - -//Spells: -//====== Troll Form -#define SPELL_WHIRLWIND 17207 -#define SPELL_GRIEVOUS_THROW 43093 // remove debuff after full healed -//====== Bear Form -#define SPELL_CREEPING_PARALYSIS 43095 // should cast on the whole raid -#define SPELL_OVERPOWER 43456 // use after melee attack dodged -//====== Eagle Form -#define SPELL_ENERGY_STORM 43983 // enemy area aura, trigger 42577 -#define SPELL_ZAP_INFORM 42577 -#define SPELL_ZAP_DAMAGE 43137 // 1250 damage -#define SPELL_SUMMON_CYCLONE 43112 // summon four feather vortex -#define CREATURE_FEATHER_VORTEX 24136 -#define SPELL_CYCLONE_VISUAL 43119 // trigger 43147 visual -#define SPELL_CYCLONE_PASSIVE 43120 // trigger 43121 (4y aoe) every second -//Lynx Form -#define SPELL_CLAW_RAGE_HASTE 42583 -#define SPELL_CLAW_RAGE_TRIGGER 43149 -#define SPELL_CLAW_RAGE_DAMAGE 43150 -#define SPELL_LYNX_RUSH_HASTE 43152 -#define SPELL_LYNX_RUSH_DAMAGE 43153 -//Dragonhawk Form -#define SPELL_FLAME_WHIRL 43213 // trigger two spells -#define SPELL_FLAME_BREATH 43215 -#define SPELL_SUMMON_PILLAR 43216 // summon 24187 -#define CREATURE_COLUMN_OF_FIRE 24187 -#define SPELL_PILLAR_TRIGGER 43218 // trigger 43217 - -//cosmetic -#define SPELL_SPIRIT_AURA 42466 -#define SPELL_SIPHON_SOUL 43501 - -//Transforms: -#define SPELL_SHAPE_OF_THE_BEAR 42594 // 15% dmg -#define SPELL_SHAPE_OF_THE_EAGLE 42606 -#define SPELL_SHAPE_OF_THE_LYNX 42607 // haste melee 30% -#define SPELL_SHAPE_OF_THE_DRAGONHAWK 42608 - -#define SPELL_BERSERK 45078 - -#define PHASE_BEAR 0 -#define PHASE_EAGLE 1 -#define PHASE_LYNX 2 -#define PHASE_DRAGONHAWK 3 -#define PHASE_TROLL 4 - -//coords for going for changing form -#define CENTER_X 120.148811 -#define CENTER_Y 703.713684 -#define CENTER_Z 45.111477 - -struct SpiritInfoStruct -{ - uint32 entry; - float x, y, z, orient; -}; - -static SpiritInfoStruct SpiritInfo[] = -{ - {23878, 147.87, 706.51, 45.11, 3.04}, - {23880, 88.95, 705.49, 45.11, 6.11}, - {23877, 137.23, 725.98, 45.11, 3.71}, - {23879, 104.29, 726.43, 45.11, 5.43} -}; - -struct TransformStruct -{ - uint32 sound; - char* text; - uint32 spell, unaura; -}; - -static TransformStruct Transform[] = -{ - {SOUND_TRANSFORM_TO_BEAR, YELL_TRANSFORM_TO_BEAR, SPELL_SHAPE_OF_THE_BEAR, SPELL_WHIRLWIND}, - {SOUND_TRANSFORM_TO_EAGLE, YELL_TRANSFORM_TO_EAGLE, SPELL_SHAPE_OF_THE_EAGLE, SPELL_SHAPE_OF_THE_BEAR}, - {SOUND_TRANSFORM_TO_LYNX, YELL_TRANSFORM_TO_LYNX, SPELL_SHAPE_OF_THE_LYNX, SPELL_SHAPE_OF_THE_EAGLE}, - {SOUND_TRANSFORM_TO_DRAGONHAWK, YELL_TRANSFORM_TO_DRAGONHAWK, SPELL_SHAPE_OF_THE_DRAGONHAWK, SPELL_SHAPE_OF_THE_LYNX} -}; - -struct boss_zuljinAI : public ScriptedAI -{ - boss_zuljinAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - ScriptedInstance *pInstance; - - uint64 SpiritGUID[4]; - uint64 ClawTargetGUID; - uint64 TankGUID; - - uint32 Phase; - uint32 health_20; - - uint32 Intro_Timer; - uint32 Berserk_Timer; - - uint32 Whirlwind_Timer; - uint32 Grievous_Throw_Timer; - - uint32 Creeping_Paralysis_Timer; - uint32 Overpower_Timer; - - uint32 Claw_Rage_Timer; - uint32 Lynx_Rush_Timer; - uint32 Claw_Counter; - uint32 Claw_Loop_Timer; - - uint32 Flame_Whirl_Timer; - uint32 Flame_Breath_Timer; - uint32 Pillar_Of_Fire_Timer; - - SummonList Summons; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_ZULJINEVENT, NOT_STARTED); - - Phase = 0; - - health_20 = me->GetMaxHealth()*0.2; - - Intro_Timer = 37000; - Berserk_Timer = 600000; - - Whirlwind_Timer = 7000; - Grievous_Throw_Timer = 8000; - - Creeping_Paralysis_Timer = 7000; - Overpower_Timer = 0; - - Claw_Rage_Timer = 5000; - Lynx_Rush_Timer = 14000; - Claw_Loop_Timer = 0; - Claw_Counter = 0; - - Flame_Whirl_Timer = 5000; - Flame_Breath_Timer = 6000; - Pillar_Of_Fire_Timer = 7000; - - ClawTargetGUID = 0; - TankGUID = 0; - - Summons.DespawnAll(); - - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 47174); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674); - //me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_ZULJINEVENT, IN_PROGRESS); - - DoZoneInCombat(); - - me->MonsterYell(YELL_INTRO,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me, SOUND_INTRO); - SpawnAdds(); - EnterPhase(0); - } - - void KilledUnit(Unit* /*victim*/) - { - if (Intro_Timer) - return; - - switch (urand(0,1)) - { - case 0: - me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL_ONE); - break; - case 1: - me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_KILL_TWO); - break; - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ZULJINEVENT, DONE); - - me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_DEATH); - Summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE); - - if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[3])) - Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); - } - - void AttackStart(Unit *who) - { - if (Phase == 2) - AttackStartNoMove(who); - else - ScriptedAI::AttackStart(who); - } - - void DoMeleeAttackIfReady() - { - if (!me->IsNonMeleeSpellCasted(false)) - { - if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim())) - { - if (Phase == 1 && !Overpower_Timer) - { - uint32 health = me->getVictim()->GetHealth(); - me->AttackerStateUpdate(me->getVictim()); - if (me->getVictim() && health == me->getVictim()->GetHealth()) - { - DoCast(me->getVictim(), SPELL_OVERPOWER, false); - Overpower_Timer = 5000; - } - } else me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - } - - void SpawnAdds() - { - Creature *pCreature = NULL; - for (uint8 i = 0; i < 4; ++i) - { - pCreature = me->SummonCreature(SpiritInfo[i].entry, SpiritInfo[i].x, SpiritInfo[i].y, SpiritInfo[i].z, SpiritInfo[i].orient, TEMPSUMMON_DEAD_DESPAWN, 0); - if (pCreature) - { - pCreature->CastSpell(pCreature, SPELL_SPIRIT_AURA, true); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - SpiritGUID[i] = pCreature->GetGUID(); - } - } - } - - void DespawnAdds() - { - for (uint8 i = 0; i < 4; ++i) - { - Unit* Temp = NULL; - if (SpiritGUID[i]) - { - if (Temp = Unit::GetUnit(*me, SpiritGUID[i])) - { - Temp->SetVisibility(VISIBILITY_OFF); - Temp->setDeathState(DEAD); - } - } - SpiritGUID[i] = 0; - } - } - - void JustSummoned(Creature *summon) - { - Summons.Summon(summon); - } - - void SummonedCreatureDespawn(Creature *summon) - { - Summons.Despawn(summon); - } - - void EnterPhase(uint32 NextPhase) - { - switch(NextPhase) - { - case 0: - break; - case 1: - case 2: - case 3: - case 4: - DoTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, 100); - DoResetThreat(); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); - me->RemoveAurasDueToSpell(Transform[Phase].unaura); - DoCast(me, Transform[Phase].spell); - me->MonsterYell(Transform[Phase].text, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, Transform[Phase].sound); - if (Phase > 0) - { - if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[Phase - 1])) - Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); - } - if (Unit *Temp = Unit::GetUnit(*me, SpiritGUID[NextPhase - 1])) - Temp->CastSpell(me, SPELL_SIPHON_SOUL, false); // should m cast on temp - if (NextPhase == 2) - { - me->GetMotionMaster()->Clear(); - DoCast(me, SPELL_ENERGY_STORM, true); // enemy aura - for (uint8 i = 0; i < 4; ++i) - { - Creature* Vortex = DoSpawnCreature(CREATURE_FEATHER_VORTEX, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Vortex) - { - Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true); - Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true); - Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Vortex->SetSpeed(MOVE_RUN, 1.0f); - Vortex->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); - DoZoneInCombat(Vortex); - } - } - } - else - me->AI()->AttackStart(me->getVictim()); - if (NextPhase == 3) - { - me->RemoveAurasDueToSpell(SPELL_ENERGY_STORM); - Summons.DespawnEntry(CREATURE_FEATHER_VORTEX); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - break; - default: - break; - } - Phase = NextPhase; - } - - void UpdateAI(const uint32 diff) - { - if (!TankGUID) - { - if (!UpdateVictim()) - return; - - if (me->GetHealth() < health_20 * (4 - Phase)) - EnterPhase(Phase + 1); - } - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_BERSERK); - Berserk_Timer = 60000; - } else Berserk_Timer -= diff; - - switch (Phase) - { - case 0: - if (Intro_Timer) - { - if (Intro_Timer <= diff) - { - me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_AGGRO); - Intro_Timer = 0; - } else Intro_Timer -= diff; - } - - if (Whirlwind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - Whirlwind_Timer = 15000 + rand()%5000; - } else Whirlwind_Timer -= diff; - - if (Grievous_Throw_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_GRIEVOUS_THROW, false); - Grievous_Throw_Timer = 10000; - } else Grievous_Throw_Timer -= diff; - break; - - case 1: - if (Creeping_Paralysis_Timer <= diff) - { - DoCast(me, SPELL_CREEPING_PARALYSIS); - Creeping_Paralysis_Timer = 20000; - } else Creeping_Paralysis_Timer -= diff; - - if (Overpower_Timer <= diff) - { - // implemented in DoMeleeAttackIfReady() - Overpower_Timer = 0; - } else Overpower_Timer -= diff; - break; - - case 2: - return; - - case 3: - if (Claw_Rage_Timer <= diff) - { - if (!TankGUID) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - TankGUID = me->getVictim()->GetGUID(); - me->SetSpeed(MOVE_RUN, 5.0f); - AttackStart(pTarget); // change victim - Claw_Rage_Timer = 0; - Claw_Loop_Timer = 500; - Claw_Counter = 0; - } - } - else if (!Claw_Rage_Timer) // do not do this when Lynx_Rush - { - if (Claw_Loop_Timer <= diff) - { - Unit *pTarget = me->getVictim(); - if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = Unit::GetUnit(*me, TankGUID); - if (!pTarget || !pTarget->isTargetableForAttack()) pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - AttackStart(pTarget); - if (me->IsWithinMeleeRange(pTarget)) - { - DoCast(pTarget, SPELL_CLAW_RAGE_DAMAGE, true); - ++Claw_Counter; - if (Claw_Counter == 12) - { - Claw_Rage_Timer = 15000 + rand()%5000; - me->SetSpeed(MOVE_RUN, 1.2f); - AttackStart(Unit::GetUnit(*me, TankGUID)); - TankGUID = 0; - return; - } - else - Claw_Loop_Timer = 500; - } - } - else - { - EnterEvadeMode(); // if (pTarget) - return; - } - } else Claw_Loop_Timer -= diff; - } //if (TankGUID) - } else Claw_Rage_Timer -= diff; - - if (Lynx_Rush_Timer <= diff) - { - if (!TankGUID) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - TankGUID = me->getVictim()->GetGUID(); - me->SetSpeed(MOVE_RUN, 5.0f); - AttackStart(pTarget); // change victim - Lynx_Rush_Timer = 0; - Claw_Counter = 0; - } - } - else if (!Lynx_Rush_Timer) - { - Unit *pTarget = me->getVictim(); - if (!pTarget || !pTarget->isTargetableForAttack()) - { - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - AttackStart(pTarget); - } - if (pTarget) - { - if (me->IsWithinMeleeRange(pTarget)) - { - DoCast(pTarget, SPELL_LYNX_RUSH_DAMAGE, true); - ++Claw_Counter; - if (Claw_Counter == 9) - { - Lynx_Rush_Timer = 15000 + rand()%5000; - me->SetSpeed(MOVE_RUN, 1.2f); - AttackStart(Unit::GetUnit(*me, TankGUID)); - TankGUID = 0; - } - else - AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); - } - } - else - { - EnterEvadeMode(); // if (pTarget) - return; - } - } //if (TankGUID) - } else Lynx_Rush_Timer -= diff; - - break; - case 4: - if (Flame_Whirl_Timer <= diff) - { - DoCast(me, SPELL_FLAME_WHIRL); - Flame_Whirl_Timer = 12000; - }Flame_Whirl_Timer -= diff; - - if (Pillar_Of_Fire_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SUMMON_PILLAR); - Pillar_Of_Fire_Timer = 10000; - } else Pillar_Of_Fire_Timer -= diff; - - if (Flame_Breath_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - me->SetInFront(pTarget); - DoCast(me, SPELL_FLAME_BREATH); - Flame_Breath_Timer = 10000; - } else Flame_Breath_Timer -= diff; - break; - - default: - break; - } - - if (!TankGUID) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_zuljin(Creature* pCreature) -{ - return new boss_zuljinAI (pCreature); -} - -struct feather_vortexAI : public ScriptedAI -{ - feather_vortexAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - - void EnterCombat(Unit * /*pTarget*/) {} - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_ZAP_INFORM) - DoCast(caster, SPELL_ZAP_DAMAGE, true); - } - - void UpdateAI(const uint32 /*diff*/) - { - //if the vortex reach the target, it change his target to another player - if (me->IsWithinMeleeRange(me->getVictim())) - AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); - } -}; - -CreatureAI* GetAI_feather_vortexAI(Creature* pCreature) -{ - return new feather_vortexAI (pCreature); -} - -void AddSC_boss_zuljin() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_zuljin"; - newscript->GetAI = &GetAI_boss_zuljin; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_zuljin_vortex"; - newscript->GetAI = &GetAI_feather_vortexAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp deleted file mode 100644 index 897330691a6..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/instance_zulaman.cpp +++ /dev/null @@ -1,320 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: instance_zulaman -SD%Complete: 80 -SDComment: -SDCategory: Zul'Aman -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulaman.h" - -#define MAX_ENCOUNTER 6 -#define RAND_VENDOR 2 - -//187021 //Harkor's Satchel -//186648 //Tanzar's Trunk -//186672 //Ashli's Bag -//186667 //Kraz's Package -// Chests spawn at bear/eagle/dragonhawk/lynx bosses -// The loots depend on how many bosses have been killed, but not the entries of the chests -// But we cannot add loots to gameobject, so we have to use the fixed loot_template -struct SHostageInfo -{ - uint32 npc, pGo; - float x, y, z, o; -}; - -static SHostageInfo HostageInfo[] = -{ - {23790, 186648, -57, 1343, 40.77, 3.2}, // bear - {23999, 187021, 400, 1414, 74.36, 3.3}, // eagle - {24001, 186672, -35, 1134, 18.71, 1.9}, // dragonhawk - {24024, 186667, 413, 1117, 6.32, 3.1} // lynx - -}; - -struct instance_zulaman : public ScriptedInstance -{ - instance_zulaman(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 HarkorsSatchelGUID; - uint64 TanzarsTrunkGUID; - uint64 AshlisBagGUID; - uint64 KrazsPackageGUID; - - uint64 HexLordGateGUID; - uint64 ZulJinGateGUID; - uint64 AkilzonDoorGUID; - uint64 ZulJinDoorGUID; - uint64 HalazziDoorGUID; - - uint32 QuestTimer; - uint16 BossKilled; - uint16 QuestMinute; - uint16 ChestLooted; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 RandVendor[RAND_VENDOR]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - HarkorsSatchelGUID = 0; - TanzarsTrunkGUID = 0; - AshlisBagGUID = 0; - KrazsPackageGUID = 0; - - HexLordGateGUID = 0; - ZulJinGateGUID = 0; - AkilzonDoorGUID = 0; - HalazziDoorGUID = 0; - ZulJinDoorGUID = 0; - - QuestTimer = 0; - QuestMinute = 21; - BossKilled = 0; - ChestLooted = 0; - - for (uint8 i = 0; i < RAND_VENDOR; ++i) - RandVendor[i] = NOT_STARTED; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 23578://janalai - case 23863://zuljin - case 24239://hexlord - case 23577://halazzi - case 23576://nalorakk - default: break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 186303: HalazziDoorGUID = pGo->GetGUID(); break; - case 186304: ZulJinGateGUID = pGo->GetGUID(); break; - case 186305: HexLordGateGUID = pGo->GetGUID(); break; - case 186858: AkilzonDoorGUID = pGo->GetGUID(); break; - case 186859: ZulJinDoorGUID = pGo->GetGUID(); break; - - case 187021: HarkorsSatchelGUID = pGo->GetGUID(); break; - case 186648: TanzarsTrunkGUID = pGo->GetGUID(); break; - case 186672: AshlisBagGUID = pGo->GetGUID(); break; - case 186667: KrazsPackageGUID = pGo->GetGUID(); break; - default: break; - - } - CheckInstanceStatus(); - } - - void SummonHostage(uint8 num) - { - if (!QuestMinute) - return; - - Map::PlayerList const &PlayerList = instance->GetPlayers(); - if (PlayerList.isEmpty()) - return; - - Map::PlayerList::const_iterator i = PlayerList.begin(); - if (Player* i_pl = i->getSource()) - { - if (Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0)) - { - Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - } - } - - void CheckInstanceStatus() - { - if (BossKilled >= 4) - HandleGameObject(HexLordGateGUID, true); - - if (BossKilled >= 5) - HandleGameObject(ZulJinGateGUID, true); - } - - std::string GetSaveData() - { - std::ostringstream ss; - ss << "S " << BossKilled << " " << ChestLooted << " " << QuestMinute; - char* data = new char[ss.str().length()+1]; - strcpy(data, ss.str().c_str()); - //error_log("TSCR: Zul'aman saved, %s.", data); - return data; - } - - void Load(const char* load) - { - if (!load) return; - std::istringstream ss(load); - //error_log("TSCR: Zul'aman loaded, %s.", ss.str().c_str()); - char dataHead; // S - uint16 data1, data2, data3; - ss >> dataHead >> data1 >> data2 >> data3; - //error_log("TSCR: Zul'aman loaded, %d %d %d.", data1, data2, data3); - if (dataHead == 'S') - { - BossKilled = data1; - ChestLooted = data2; - QuestMinute = data3; - } else error_log("TSCR: Zul'aman: corrupted save data."); - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_NALORAKKEVENT: - m_auiEncounter[0] = data; - if (data == DONE) - { - if (QuestMinute) - { - QuestMinute += 15; - DoUpdateWorldState(3106, QuestMinute); - } - SummonHostage(0); - } - break; - case DATA_AKILZONEVENT: - m_auiEncounter[1] = data; - HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS); - if (data == DONE) - { - if (QuestMinute) - { - QuestMinute += 10; - DoUpdateWorldState(3106, QuestMinute); - } - SummonHostage(1); - } - break; - case DATA_JANALAIEVENT: - m_auiEncounter[2] = data; - if (data == DONE) SummonHostage(2); - break; - case DATA_HALAZZIEVENT: - m_auiEncounter[3] = data; - HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS); - if (data == DONE) SummonHostage(3); - break; - case DATA_HEXLORDEVENT: - m_auiEncounter[4] = data; - if (data == IN_PROGRESS) - HandleGameObject(HexLordGateGUID, false); - else if (data == NOT_STARTED) - CheckInstanceStatus(); - break; - case DATA_ZULJINEVENT: - m_auiEncounter[5] = data; - HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS); - break; - case DATA_CHESTLOOTED: - ++ChestLooted; - SaveToDB(); - break; - case TYPE_RAND_VENDOR_1: - RandVendor[0] = data; - break; - case TYPE_RAND_VENDOR_2: - RandVendor[1] = data; - break; - } - - if (data == DONE) - { - ++BossKilled; - if (QuestMinute && BossKilled >= 4) - { - QuestMinute = 0; - DoUpdateWorldState(3104, 0); - } - CheckInstanceStatus(); - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_NALORAKKEVENT: return m_auiEncounter[0]; - case DATA_AKILZONEVENT: return m_auiEncounter[1]; - case DATA_JANALAIEVENT: return m_auiEncounter[2]; - case DATA_HALAZZIEVENT: return m_auiEncounter[3]; - case DATA_HEXLORDEVENT: return m_auiEncounter[4]; - case DATA_ZULJINEVENT: return m_auiEncounter[5]; - case DATA_CHESTLOOTED: return ChestLooted; - case TYPE_RAND_VENDOR_1: return RandVendor[0]; - case TYPE_RAND_VENDOR_2: return RandVendor[1]; - default: return 0; - } - } - - void Update(uint32 diff) - { - if (QuestMinute) - { - if (QuestTimer <= diff) - { - QuestMinute--; - SaveToDB(); - QuestTimer += 60000; - if (QuestMinute) - { - DoUpdateWorldState(3104, 1); - DoUpdateWorldState(3106, QuestMinute); - } else DoUpdateWorldState(3104, 0); - } - QuestTimer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_zulaman(Map* pMap) -{ - return new instance_zulaman(pMap); -} - -void AddSC_instance_zulaman() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_zulaman"; - newscript->GetInstanceData = &GetInstanceData_instance_zulaman; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp b/src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp deleted file mode 100644 index 067ae687644..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/zulaman.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Zulaman -SD%Complete: 90 -SDComment: Forest Frog will turn into different NPC's. Workaround to prevent new entry from running this script -SDCategory: Zul'Aman -EndScriptData */ - -/* ContentData -npc_forest_frog -EndContentData */ - -#include "ScriptedPch.h" -#include "zulaman.h" - -/*###### -## npc_forest_frog -######*/ - -#define SPELL_REMOVE_AMANI_CURSE 43732 -#define SPELL_PUSH_MOJO 43923 -#define ENTRY_FOREST_FROG 24396 - -struct npc_forest_frogAI : public ScriptedAI -{ - npc_forest_frogAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() {} - - void EnterCombat(Unit * /*who*/) {} - - void DoSpawnRandom() - { - if (pInstance) - { - uint32 cEntry = 0; - switch(rand()%10) - { - case 0: cEntry = 24397; break; //Mannuth - case 1: cEntry = 24403; break; //Deez - case 2: cEntry = 24404; break; //Galathryn - case 3: cEntry = 24405; break; //Adarrah - case 4: cEntry = 24406; break; //Fudgerick - case 5: cEntry = 24407; break; //Darwen - case 6: cEntry = 24445; break; //Mitzi - case 7: cEntry = 24448; break; //Christian - case 8: cEntry = 24453; break; //Brennan - case 9: cEntry = 24455; break; //Hollee - } - - if (!pInstance->GetData(TYPE_RAND_VENDOR_1)) - if (rand()%10 == 1) cEntry = 24408; //Gunter - if (!pInstance->GetData(TYPE_RAND_VENDOR_2)) - if (rand()%10 == 1) cEntry = 24409; //Kyren - - if (cEntry) me->UpdateEntry(cEntry); - - if (cEntry == 24408) pInstance->SetData(TYPE_RAND_VENDOR_1,DONE); - if (cEntry == 24409) pInstance->SetData(TYPE_RAND_VENDOR_2,DONE); - } - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && me->GetEntry() == ENTRY_FOREST_FROG) - { - //increase or decrease chance of mojo? - if (rand()%99 == 50) DoCast(caster, SPELL_PUSH_MOJO, true); - else DoSpawnRandom(); - } - } -}; -CreatureAI* GetAI_npc_forest_frog(Creature* pCreature) -{ - return new npc_forest_frogAI (pCreature); -} - -/*###### -## npc_zulaman_hostage -######*/ - -#define GOSSIP_HOSTAGE1 "I am glad to help you." - -static uint32 HostageEntry[] = {23790, 23999, 24024, 24001}; -static uint32 ChestEntry[] = {186648, 187021, 186672, 186667}; - -struct npc_zulaman_hostageAI : public ScriptedAI -{ - npc_zulaman_hostageAI(Creature *c) : ScriptedAI(c) {IsLoot = false;} - bool IsLoot; - uint64 PlayerGUID; - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - void JustDied(Unit* /*who*/) - { - Player* pPlayer = Unit::GetPlayer(PlayerGUID); - if (pPlayer) pPlayer->SendLoot(me->GetGUID(), LOOT_CORPSE); - } - void UpdateAI(const uint32 /*diff*/) - { - if (IsLoot) - DoCast(me, 7, false); - } -}; - -bool GossipHello_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HOSTAGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_zulaman_hostage(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - pPlayer->CLOSE_GOSSIP_MENU(); - - if (!pCreature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - return true; - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance) - { - //uint8 progress = pInstance->GetData(DATA_CHESTLOOTED); - pInstance->SetData(DATA_CHESTLOOTED, 0); - float x, y, z; - pCreature->GetPosition(x, y, z); - uint32 entry = pCreature->GetEntry(); - for (uint8 i = 0; i < 4; ++i) - { - if (HostageEntry[i] == entry) - { - pCreature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0); - break; - } - } - /*Creature* summon = pCreature->SummonCreature(HostageInfo[progress], x-2, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 0); - if (summon) - { - CAST_AI(npc_zulaman_hostageAI, summon->AI())->PlayerGUID = pPlayer->GetGUID(); - CAST_AI(npc_zulaman_hostageAI, summon->AI())->IsLoot = true; - summon->SetDisplayId(10056); - summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summon->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - }*/ - } - return true; -} - -CreatureAI* GetAI_npc_zulaman_hostage(Creature* pCreature) -{ - return new npc_zulaman_hostageAI(pCreature); -} - -void AddSC_zulaman() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_forest_frog"; - newscript->GetAI = &GetAI_npc_forest_frog; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_zulaman_hostage"; - newscript->GetAI = &GetAI_npc_zulaman_hostage; - newscript->pGossipHello = &GossipHello_npc_zulaman_hostage; - newscript->pGossipSelect = &GossipSelect_npc_zulaman_hostage; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulaman/zulaman.h b/src/server/scripts/EasternKingdoms/zulaman/zulaman.h deleted file mode 100644 index 6fb0ef173bd..00000000000 --- a/src/server/scripts/EasternKingdoms/zulaman/zulaman.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_ZULAMAN_H -#define DEF_ZULAMAN_H - -#define DATA_NALORAKKEVENT 1 -#define DATA_AKILZONEVENT 2 -#define DATA_JANALAIEVENT 3 -#define DATA_HALAZZIEVENT 4 -#define DATA_HEXLORDEVENT 5 -#define DATA_ZULJINEVENT 6 -#define DATA_CHESTLOOTED 7 -#define TYPE_RAND_VENDOR_1 8 -#define TYPE_RAND_VENDOR_2 9 - -#endif - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp deleted file mode 100644 index cbbe6c4dc4c..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_arlokk.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Arlokk -SD%Complete: 95 -SDComment: Wrong cleave and red aura is missing. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -bool GOHello_go_gong_of_bethekk(Player* /*pPlayer*/, GameObject* pGo) -{ - if (ScriptedInstance* m_pInstance = pGo->GetInstanceData()) - { - if (m_pInstance->GetData(TYPE_ARLOKK) == DONE || m_pInstance->GetData(TYPE_ARLOKK) == IN_PROGRESS) - return true; - - m_pInstance->SetData(TYPE_ARLOKK, IN_PROGRESS); - return true; - } - - return true; -} - -enum eEnums -{ - SAY_AGGRO = -1309011, - SAY_FEAST_PANTHER = -1309012, - SAY_DEATH = -1309013, - - SPELL_SHADOWWORDPAIN = 23952, - SPELL_GOUGE = 24698, - SPELL_MARK = 24210, - SPELL_CLEAVE = 26350, //Perhaps not right. Not a red aura... - SPELL_PANTHER_TRANSFORM = 24190, - - MODEL_ID_NORMAL = 15218, - MODEL_ID_PANTHER = 15215, - MODEL_ID_BLANK = 11686, - - NPC_ZULIAN_PROWLER = 15101 -}; - -struct boss_arlokkAI : public ScriptedAI -{ - boss_arlokkAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiShadowWordPain_Timer; - uint32 m_uiGouge_Timer; - uint32 m_uiMark_Timer; - uint32 m_uiCleave_Timer; - uint32 m_uiVanish_Timer; - uint32 m_uiVisible_Timer; - - uint32 m_uiSummon_Timer; - uint32 m_uiSummonCount; - - Unit* m_pMarkedTarget; - uint64 MarkedTargetGUID; - - bool m_bIsPhaseTwo; - bool m_bIsVanished; - - void Reset() - { - m_uiShadowWordPain_Timer = 8000; - m_uiGouge_Timer = 14000; - m_uiMark_Timer = 35000; - m_uiCleave_Timer = 4000; - m_uiVanish_Timer = 60000; - m_uiVisible_Timer = 6000; - - m_uiSummon_Timer = 5000; - m_uiSummonCount = 0; - - m_bIsPhaseTwo = false; - m_bIsVanished = false; - - MarkedTargetGUID = 0; - - me->SetDisplayId(MODEL_ID_NORMAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustReachedHome() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_ARLOKK, NOT_STARTED); - - //we should be summoned, so despawn - me->ForcedDespawn(); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - me->SetDisplayId(MODEL_ID_NORMAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (m_pInstance) - m_pInstance->SetData(TYPE_ARLOKK, DONE); - } - - void DoSummonPhanters() - { - if (Unit *pMarkedTarget = Unit::GetUnit(*me, MarkedTargetGUID)) - DoScriptText(SAY_FEAST_PANTHER, me, pMarkedTarget); - - me->SummonCreature(NPC_ZULIAN_PROWLER, -11532.7998, -1649.6734, 41.4800, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(NPC_ZULIAN_PROWLER, -11532.9970, -1606.4840, 41.2979, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - } - - void JustSummoned(Creature* pSummoned) - { - if (Unit *pMarkedTarget = Unit::GetUnit(*me, MarkedTargetGUID)) - pSummoned->AI()->AttackStart(pMarkedTarget); - - ++m_uiSummonCount; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (!m_bIsPhaseTwo) - { - if (m_uiShadowWordPain_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SHADOWWORDPAIN); - m_uiShadowWordPain_Timer = 15000; - } - else - m_uiShadowWordPain_Timer -= uiDiff; - - if (m_uiMark_Timer <= uiDiff) - { - Unit *pMarkedTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (pMarkedTarget) - { - DoCast(pMarkedTarget, SPELL_MARK); - MarkedTargetGUID = pMarkedTarget->GetGUID(); - } - else - error_log("TSCR: boss_arlokk could not accuire pMarkedTarget."); - - m_uiMark_Timer = 15000; - } - else - m_uiMark_Timer -= uiDiff; - } - else - { - //Cleave_Timer - if (m_uiCleave_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - m_uiCleave_Timer = 16000; - } - else - m_uiCleave_Timer -= uiDiff; - - //Gouge_Timer - if (m_uiGouge_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_GOUGE); - - DoModifyThreatPercent(me->getVictim(),-80); - - m_uiGouge_Timer = 17000+rand()%10000; - } - else - m_uiGouge_Timer -= uiDiff; - } - - if (m_uiSummonCount <= 30) - { - if (m_uiSummon_Timer <= uiDiff) - { - DoSummonPhanters(); - m_uiSummon_Timer = 5000; - } - else - m_uiSummon_Timer -= uiDiff; - } - - if (m_uiVanish_Timer <= uiDiff) - { - //Invisble Model - me->SetDisplayId(MODEL_ID_BLANK); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - me->AttackStop(); - DoResetThreat(); - - m_bIsVanished = true; - - m_uiVanish_Timer = 45000; - m_uiVisible_Timer = 6000; - } - else - m_uiVanish_Timer -= uiDiff; - - if (m_bIsVanished) - { - if (m_uiVisible_Timer <= uiDiff) - { - //The Panther Model - me->SetDisplayId(MODEL_ID_PANTHER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); - me->UpdateDamagePhysical(BASE_ATTACK); - - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - AttackStart(pTarget); - - m_bIsPhaseTwo = true; - m_bIsVanished = false; - } - else - m_uiVisible_Timer -= uiDiff; - } - else - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_arlokk(Creature* pCreature) -{ - return new boss_arlokkAI (pCreature); -} - -void AddSC_boss_arlokk() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_gong_of_bethekk"; - newscript->pGOHello = &GOHello_go_gong_of_bethekk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_arlokk"; - newscript->GetAI = &GetAI_boss_arlokk; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp deleted file mode 100644 index 0201235be70..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_gahzranka.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gahz'ranka -SD%Complete: 85 -SDComment: Massive Geyser with knockback not working. Spell buggy. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FROSTBREATH 16099 -#define SPELL_MASSIVEGEYSER 22421 //Not working. Cause its a summon... -#define SPELL_SLAM 24326 - -struct boss_gahzrankaAI : public ScriptedAI -{ - boss_gahzrankaAI(Creature *c) : ScriptedAI(c) {} - uint32 Frostbreath_Timer; - uint32 MassiveGeyser_Timer; - uint32 Slam_Timer; - - void Reset() - { - Frostbreath_Timer = 8000; - MassiveGeyser_Timer = 25000; - Slam_Timer = 17000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frostbreath_Timer - if (Frostbreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBREATH); - Frostbreath_Timer = 7000 + rand()%4000; - } else Frostbreath_Timer -= diff; - - //MassiveGeyser_Timer - if (MassiveGeyser_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MASSIVEGEYSER); - DoResetThreat(); - - MassiveGeyser_Timer = 22000 + rand()%10000; - } else MassiveGeyser_Timer -= diff; - - //Slam_Timer - if (Slam_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLAM); - Slam_Timer = 12000 + rand()%8000; - } else Slam_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gahzranka(Creature* pCreature) -{ - return new boss_gahzrankaAI (pCreature); -} - -void AddSC_boss_gahzranka() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gahzranka"; - newscript->GetAI = &GetAI_boss_gahzranka; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp deleted file mode 100644 index 67de135674a..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_grilek.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grilek -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SPELL_AVARTAR 24646 //The Enrage Spell -#define SPELL_GROUNDTREMOR 6524 - -struct boss_grilekAI : public ScriptedAI -{ - boss_grilekAI(Creature *c) : ScriptedAI(c) {} - - uint32 Avartar_Timer; - uint32 GroundTremor_Timer; - - void Reset() - { - Avartar_Timer = 15000 + rand()%10000; - GroundTremor_Timer = 8000 + rand()%8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Avartar_Timer - if (Avartar_Timer <= diff) - { - - DoCast(me, SPELL_AVARTAR); - Unit *pTarget = NULL; - - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-50); - if (pTarget) - AttackStart(pTarget); - - Avartar_Timer = 25000 + rand()%10000; - } else Avartar_Timer -= diff; - - //GroundTremor_Timer - if (GroundTremor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GROUNDTREMOR); - GroundTremor_Timer = 12000 + rand()%4000; - } else GroundTremor_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_grilek(Creature* pCreature) -{ - return new boss_grilekAI (pCreature); -} - -void AddSC_boss_grilek() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grilek"; - newscript->GetAI = &GetAI_boss_grilek; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp deleted file mode 100644 index d7dd5020b74..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_hakkar.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hakkar -SD%Complete: 95 -SDComment: Blood siphon spell buggy cause of Core Issue. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309020 -#define SAY_FLEEING -1309021 -#define SAY_MINION_DESTROY -1309022 //where does it belong? -#define SAY_PROTECT_ALTAR -1309023 //where does it belong? - -#define SPELL_BLOODSIPHON 24322 -#define SPELL_CORRUPTEDBLOOD 24328 -#define SPELL_CAUSEINSANITY 24327 //Not working disabled. -#define SPELL_WILLOFHAKKAR 24178 -#define SPELL_ENRAGE 24318 - -// The Aspects of all High Priests -#define SPELL_ASPECT_OF_JEKLIK 24687 -#define SPELL_ASPECT_OF_VENOXIS 24688 -#define SPELL_ASPECT_OF_MARLI 24686 -#define SPELL_ASPECT_OF_THEKAL 24689 -#define SPELL_ASPECT_OF_ARLOKK 24690 - -struct boss_hakkarAI : public ScriptedAI -{ - boss_hakkarAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 BloodSiphon_Timer; - uint32 CorruptedBlood_Timer; - uint32 CauseInsanity_Timer; - uint32 WillOfHakkar_Timer; - uint32 Enrage_Timer; - - uint32 CheckJeklik_Timer; - uint32 CheckVenoxis_Timer; - uint32 CheckMarli_Timer; - uint32 CheckThekal_Timer; - uint32 CheckArlokk_Timer; - - uint32 AspectOfJeklik_Timer; - uint32 AspectOfVenoxis_Timer; - uint32 AspectOfMarli_Timer; - uint32 AspectOfThekal_Timer; - uint32 AspectOfArlokk_Timer; - - bool Enraged; - - void Reset() - { - BloodSiphon_Timer = 90000; - CorruptedBlood_Timer = 25000; - CauseInsanity_Timer = 17000; - WillOfHakkar_Timer = 17000; - Enrage_Timer = 600000; - - CheckJeklik_Timer = 1000; - CheckVenoxis_Timer = 2000; - CheckMarli_Timer = 3000; - CheckThekal_Timer = 4000; - CheckArlokk_Timer = 5000; - - AspectOfJeklik_Timer = 4000; - AspectOfVenoxis_Timer = 7000; - AspectOfMarli_Timer = 12000; - AspectOfThekal_Timer = 8000; - AspectOfArlokk_Timer = 18000; - - Enraged = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //BloodSiphon_Timer - if (BloodSiphon_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLOODSIPHON); - BloodSiphon_Timer = 90000; - } else BloodSiphon_Timer -= diff; - - //CorruptedBlood_Timer - if (CorruptedBlood_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORRUPTEDBLOOD); - CorruptedBlood_Timer = 30000 + rand()%15000; - } else CorruptedBlood_Timer -= diff; - - //CauseInsanity_Timer - /*if (CauseInsanity_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CAUSEINSANITY); - - CauseInsanity_Timer = 35000 + rand()%8000; - } else CauseInsanity_Timer -= diff;*/ - - //WillOfHakkar_Timer - if (WillOfHakkar_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_WILLOFHAKKAR); - - WillOfHakkar_Timer = 25000 + rand()%10000; - } else WillOfHakkar_Timer -= diff; - - if (!Enraged && Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else Enrage_Timer -= diff; - - //Checking if Jeklik is dead. If not we cast her Aspect - if (CheckJeklik_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_JEKLIK) != DONE) - { - if (AspectOfJeklik_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASPECT_OF_JEKLIK); - AspectOfJeklik_Timer = 10000 + rand()%4000; - } else AspectOfJeklik_Timer -= diff; - } - } - CheckJeklik_Timer = 1000; - } else CheckJeklik_Timer -= diff; - - //Checking if Venoxis is dead. If not we cast his Aspect - if (CheckVenoxis_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_VENOXIS) != DONE) - { - if (AspectOfVenoxis_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASPECT_OF_VENOXIS); - AspectOfVenoxis_Timer = 8000; - } else AspectOfVenoxis_Timer -= diff; - } - } - CheckVenoxis_Timer = 1000; - } else CheckVenoxis_Timer -= diff; - - //Checking if Marli is dead. If not we cast her Aspect - if (CheckMarli_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_MARLI) != DONE) - { - if (AspectOfMarli_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); - AspectOfMarli_Timer = 10000; - } else AspectOfMarli_Timer -= diff; - - } - } - CheckMarli_Timer = 1000; - } else CheckMarli_Timer -= diff; - - //Checking if Thekal is dead. If not we cast his Aspect - if (CheckThekal_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_THEKAL) != DONE) - { - if (AspectOfThekal_Timer <= diff) - { - DoCast(me, SPELL_ASPECT_OF_THEKAL); - AspectOfThekal_Timer = 15000; - } else AspectOfThekal_Timer -= diff; - } - } - CheckThekal_Timer = 1000; - } else CheckThekal_Timer -= diff; - - //Checking if Arlokk is dead. If yes we cast her Aspect - if (CheckArlokk_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_ARLOKK) != DONE) - { - if (AspectOfArlokk_Timer <= diff) - { - DoCast(me, SPELL_ASPECT_OF_ARLOKK); - DoResetThreat(); - - AspectOfArlokk_Timer = 10000 + rand()%5000; - } else AspectOfArlokk_Timer -= diff; - } - } - CheckArlokk_Timer = 1000; - } else CheckArlokk_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_hakkar(Creature* pCreature) -{ - return new boss_hakkarAI (pCreature); -} - -void AddSC_boss_hakkar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hakkar"; - newscript->GetAI = &GetAI_boss_hakkar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp deleted file mode 100644 index ca67d0842c3..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_hazzarah.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hazzarah -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SPELL_MANABURN 26046 -#define SPELL_SLEEP 24664 - -struct boss_hazzarahAI : public ScriptedAI -{ - boss_hazzarahAI(Creature *c) : ScriptedAI(c) {} - - uint32 ManaBurn_Timer; - uint32 Sleep_Timer; - uint32 Illusions_Timer; - - void Reset() - { - ManaBurn_Timer = 4000 + rand()%6000; - Sleep_Timer = 10000 + rand()%8000; - Illusions_Timer = 10000 + rand()%8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //ManaBurn_Timer - if (ManaBurn_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MANABURN); - ManaBurn_Timer = 8000 + rand()%8000; - } else ManaBurn_Timer -= diff; - - //Sleep_Timer - if (Sleep_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLEEP); - Sleep_Timer = 12000 + rand()%8000; - } else Sleep_Timer -= diff; - - //Illusions_Timer - if (Illusions_Timer <= diff) - { - //We will summon 3 illusions that will spawn on a random gamer and attack this gamer - //We will just use one model for the beginning - Unit *pTarget = NULL; - for (uint8 i = 0; i < 3; ++i) - { - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget) - return; - - Creature *Illusion = me->SummonCreature(15163,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,30000); - if (Illusion) - Illusion->AI()->AttackStart(pTarget); - } - - Illusions_Timer = 15000 + rand()%10000; - } else Illusions_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_hazzarah(Creature* pCreature) -{ - return new boss_hazzarahAI (pCreature); -} - -void AddSC_boss_hazzarah() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hazzarah"; - newscript->GetAI = &GetAI_boss_hazzarah; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp deleted file mode 100644 index fae05fcf384..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_jeklik.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Jeklik -SD%Complete: 85 -SDComment: Problem in finding the right flying batriders for spawning and making them fly. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309002 -#define SAY_RAIN_FIRE -1309003 -#define SAY_DEATH -1309004 - -#define SPELL_CHARGE 22911 -#define SPELL_SONICBURST 23918 -#define SPELL_SCREECH 6605 -#define SPELL_SHADOW_WORD_PAIN 23952 -#define SPELL_MIND_FLAY 23953 -#define SPELL_CHAIN_MIND_FLAY 26044 //Right ID unknown. So disabled -#define SPELL_GREATERHEAL 23954 -#define SPELL_BAT_FORM 23966 - -// Batriders Spell - -#define SPELL_BOMB 40332 //Wrong ID but Magmadars bomb is not working... - -struct boss_jeklikAI : public ScriptedAI -{ - boss_jeklikAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 Charge_Timer; - uint32 SonicBurst_Timer; - uint32 Screech_Timer; - uint32 SpawnBats_Timer; - uint32 ShadowWordPain_Timer; - uint32 MindFlay_Timer; - uint32 ChainMindFlay_Timer; - uint32 GreaterHeal_Timer; - uint32 SpawnFlyingBats_Timer; - - bool PhaseTwo; - - void Reset() - { - Charge_Timer = 20000; - SonicBurst_Timer = 8000; - Screech_Timer = 13000; - SpawnBats_Timer = 60000; - ShadowWordPain_Timer = 6000; - MindFlay_Timer = 11000; - ChainMindFlay_Timer = 26000; - GreaterHeal_Timer = 50000; - SpawnFlyingBats_Timer = 10000; - - PhaseTwo = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_BAT_FORM); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_JEKLIK, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->getVictim() && me->isAlive()) - { - if ((me->GetHealth()*100 / me->GetMaxHealth() > 50)) - { - if (Charge_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_CHARGE); - AttackStart(pTarget); - } - - Charge_Timer = 15000 + rand()%15000; - } else Charge_Timer -= diff; - - if (SonicBurst_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SONICBURST); - SonicBurst_Timer = 8000 + rand()%5000; - } else SonicBurst_Timer -= diff; - - if (Screech_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SCREECH); - Screech_Timer = 18000 + rand()%8000; - } else Screech_Timer -= diff; - - if (SpawnBats_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - Creature* Bat = NULL; - Bat = me->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - Bat = me->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - Bat = me->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - Bat = me->SummonCreature(11368,-12291.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - Bat = me->SummonCreature(11368,-12289.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - Bat = me->SummonCreature(11368,-12293.6220,-1380.2640,144.8304,5.483, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (pTarget && Bat) Bat ->AI()->AttackStart(pTarget); - - SpawnBats_Timer = 60000; - } else SpawnBats_Timer -= diff; - } - else - { - if (PhaseTwo) - { - if (PhaseTwo && ShadowWordPain_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); - ShadowWordPain_Timer = 12000 + rand()%6000; - } - }ShadowWordPain_Timer -=diff; - - if (MindFlay_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIND_FLAY); - MindFlay_Timer = 16000; - }MindFlay_Timer -=diff; - - if (ChainMindFlay_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me->getVictim(), SPELL_CHAIN_MIND_FLAY); - ChainMindFlay_Timer = 15000 + rand()%15000; - }ChainMindFlay_Timer -=diff; - - if (GreaterHeal_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_GREATERHEAL); - GreaterHeal_Timer = 25000 + rand()%10000; - }GreaterHeal_Timer -=diff; - - if (SpawnFlyingBats_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (!pTarget) - return; - - Creature* FlyingBat = me->SummonCreature(14965, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (FlyingBat) - FlyingBat->AI()->AttackStart(pTarget); - - SpawnFlyingBats_Timer = 10000 + rand()%5000; - } else SpawnFlyingBats_Timer -=diff; - } - else - { - me->SetDisplayId(15219); - DoResetThreat(); - PhaseTwo = true; - } - } - - DoMeleeAttackIfReady(); - } - } -}; - -//Flying Bat -struct mob_batriderAI : public ScriptedAI -{ - mob_batriderAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 Bomb_Timer; - uint32 Check_Timer; - - void Reset() - { - Bomb_Timer = 2000; - Check_Timer = 1000; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI (const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Bomb_Timer - if (Bomb_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_BOMB); - Bomb_Timer = 5000; - } - } else Bomb_Timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_JEKLIK) == DONE) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_jeklik(Creature* pCreature) -{ - return new boss_jeklikAI (pCreature); -} - -CreatureAI* GetAI_mob_batrider(Creature* pCreature) -{ - return new mob_batriderAI (pCreature); -} - -void AddSC_boss_jeklik() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_jeklik"; - newscript->GetAI = &GetAI_boss_jeklik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_batrider"; - newscript->GetAI = &GetAI_mob_batrider; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp deleted file mode 100644 index 58f91f85a95..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_jindo.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Jin'do the Hexxer -SD%Complete: 85 -SDComment: Mind Control not working because of core bug. Shades visible for all. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309014 - -#define SPELL_BRAINWASHTOTEM 24262 -#define SPELL_POWERFULLHEALINGWARD 24309 //We will not use this spell. We will summon a totem by script cause the spell totems will not cast. -#define SPELL_HEX 24053 -#define SPELL_DELUSIONSOFJINDO 24306 -#define SPELL_SHADEOFJINDO 24308 //We will not use this spell. We will summon a shade by script. - -//Healing Ward Spell -#define SPELL_HEAL 38588 //Totems are not working right. Right heal spell ID is 24311 but this spell is not casting... - -//Shade of Jindo Spell -#define SPELL_SHADOWSHOCK 19460 -#define SPELL_INVISIBLE 24699 - -struct boss_jindoAI : public ScriptedAI -{ - boss_jindoAI(Creature *c) : ScriptedAI(c) {} - - uint32 BrainWashTotem_Timer; - uint32 HealingWard_Timer; - uint32 Hex_Timer; - uint32 Delusions_Timer; - uint32 Teleport_Timer; - - void Reset() - { - BrainWashTotem_Timer = 20000; - HealingWard_Timer = 16000; - Hex_Timer = 8000; - Delusions_Timer = 10000; - Teleport_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //BrainWashTotem_Timer - if (BrainWashTotem_Timer <= diff) - { - DoCast(me, SPELL_BRAINWASHTOTEM); - BrainWashTotem_Timer = 18000 + rand()%8000; - } else BrainWashTotem_Timer -= diff; - - //HealingWard_Timer - if (HealingWard_Timer <= diff) - { - //DoCast(me, SPELL_POWERFULLHEALINGWARD); - me->SummonCreature(14987, me->GetPositionX()+3, me->GetPositionY()-2, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,30000); - HealingWard_Timer = 14000 + rand()%6000; - } else HealingWard_Timer -= diff; - - //Hex_Timer - if (Hex_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HEX); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-80); - - Hex_Timer = 12000 + rand()%8000; - } else Hex_Timer -= diff; - - //Casting the delusion curse with a shade. So shade will attack the same target with the curse. - if (Delusions_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_DELUSIONSOFJINDO); - - Creature *Shade = me->SummonCreature(14986, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Shade) - Shade->AI()->AttackStart(pTarget); - } - - Delusions_Timer = 4000 + rand()%8000; - } else Delusions_Timer -= diff; - - //Teleporting a random gamer and spawning 9 skeletons that will attack this gamer - if (Teleport_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoTeleportPlayer(pTarget, -11583.7783,-1249.4278,77.5471,4.745); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(pTarget,-100); - - Creature *Skeletons; - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+2, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()-2, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+4, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()-4, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()+2, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()-2, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()+4, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX(), pTarget->GetPositionY()-4, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - Skeletons = me->SummonCreature(14826, pTarget->GetPositionX()+3, pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Skeletons) - Skeletons->AI()->AttackStart(pTarget); - } - - Teleport_Timer = 15000 + rand()%8000; - } else Teleport_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Healing Ward -struct mob_healing_wardAI : public ScriptedAI -{ - mob_healing_wardAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 Heal_Timer; - - ScriptedInstance *pInstance; - - void Reset() - { - Heal_Timer = 2000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI (const uint32 diff) - { - //Heal_Timer - if (Heal_Timer <= diff) - { - if (pInstance) - { - Unit *pJindo = Unit::GetUnit((*me), pInstance->GetData64(DATA_JINDO)); - if (pJindo) - DoCast(pJindo, SPELL_HEAL); - } - Heal_Timer = 3000; - } else Heal_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Shade of Jindo -struct mob_shade_of_jindoAI : public ScriptedAI -{ - mob_shade_of_jindoAI(Creature *c) : ScriptedAI(c) {} - - uint32 ShadowShock_Timer; - - void Reset() - { - ShadowShock_Timer = 1000; - DoCast(me, SPELL_INVISIBLE, true); - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI (const uint32 diff) - { - - //ShadowShock_Timer - if (ShadowShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWSHOCK); - ShadowShock_Timer = 2000; - } else ShadowShock_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_jindo(Creature* pCreature) -{ - return new boss_jindoAI (pCreature); -} - -CreatureAI* GetAI_mob_healing_ward(Creature* pCreature) -{ - return new mob_healing_wardAI (pCreature); -} - -CreatureAI* GetAI_mob_shade_of_jindo(Creature* pCreature) -{ - return new mob_shade_of_jindoAI (pCreature); -} - -void AddSC_boss_jindo() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_jindo"; - newscript->GetAI = &GetAI_boss_jindo; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_healing_ward"; - newscript->GetAI = &GetAI_mob_healing_ward; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shade_of_jindo"; - newscript->GetAI = &GetAI_mob_shade_of_jindo; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp deleted file mode 100644 index 4609605f3c1..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_mandokir.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mandokir -SD%Complete: 90 -SDComment: Ohgan function needs improvements. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309015 -#define SAY_DING_KILL -1309016 -#define SAY_GRATS_JINDO -1309017 -#define SAY_WATCH -1309018 -#define SAY_WATCH_WHISPER -1309019 //is this text for real? easter egg? - -#define SPELL_CHARGE 24315 -#define SPELL_CLEAVE 20691 -#define SPELL_FEAR 29321 -#define SPELL_WHIRLWIND 24236 -#define SPELL_MORTAL_STRIKE 24573 -#define SPELL_ENRAGE 23537 -#define SPELL_WATCH 24314 -#define SPELL_LEVEL_UP 24312 - -//Ohgans Spells -#define SPELL_SUNDERARMOR 24317 - -struct boss_mandokirAI : public ScriptedAI -{ - boss_mandokirAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 KillCount; - uint32 Watch_Timer; - uint32 TargetInRange; - uint32 Cleave_Timer; - uint32 Whirlwind_Timer; - uint32 Fear_Timer; - uint32 MortalStrike_Timer; - uint32 Check_Timer; - float targetX; - float targetY; - float targetZ; - - ScriptedInstance *m_pInstance; - - bool endWatch; - bool someWatched; - bool RaptorDead; - bool CombatStart; - - uint64 WatchTarget; - - void Reset() - { - KillCount = 0; - Watch_Timer = 33000; - Cleave_Timer = 7000; - Whirlwind_Timer = 20000; - Fear_Timer = 1000; - MortalStrike_Timer = 1000; - Check_Timer = 1000; - - targetX = 0.0; - targetY = 0.0; - targetZ = 0.0; - TargetInRange = 0; - - WatchTarget = 0; - - someWatched = false; - endWatch = false; - RaptorDead = false; - CombatStart = false; - - DoCast(me, 23243); - } - - void KilledUnit(Unit* victim) - { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - ++KillCount; - - if (KillCount == 3) - { - DoScriptText(SAY_DING_KILL, me); - - if (m_pInstance) - { - uint64 JindoGUID = m_pInstance->GetData64(DATA_JINDO); - if (JindoGUID) - { - if (Unit* jTemp = Unit::GetUnit(*me,JindoGUID)) - { - if (jTemp->isAlive()) - DoScriptText(SAY_GRATS_JINDO, jTemp); - } - } - } - DoCast(me, SPELL_LEVEL_UP, true); - KillCount = 0; - } - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->getVictim() && me->isAlive()) - { - if (!CombatStart) - { - //At combat Start Mandokir is mounted so we must unmount it first - me->Unmount(); - - //And summon his raptor - me->SummonCreature(14988, me->getVictim()->GetPositionX(), me->getVictim()->GetPositionY(), me->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000); - CombatStart = true; - } - - if (Watch_Timer <= diff) //Every 20 Sec Mandokir will check this - { - if (WatchTarget) //If someone is watched and If the Position of the watched target is different from the one stored, or are attacking, mandokir will charge him - { - Unit* pUnit = Unit::GetUnit(*me, WatchTarget); - - if (pUnit && ( - targetX != pUnit->GetPositionX() || - targetY != pUnit->GetPositionY() || - targetZ != pUnit->GetPositionZ() || - pUnit->isInCombat())) - { - if (me->IsWithinMeleeRange(pUnit)) - { - DoCast(pUnit, 24316); - } - else - { - DoCast(pUnit, SPELL_CHARGE); - //me->SendMonsterMove(pUnit->GetPositionX(), pUnit->GetPositionY(), pUnit->GetPositionZ(), 0, true,1); - AttackStart(pUnit); - } - } - } - someWatched = false; - Watch_Timer = 20000; - } else Watch_Timer -= diff; - - if ((Watch_Timer < 8000) && !someWatched) //8 sec(cast time + expire time) before the check for the watch effect mandokir will cast watch debuff on a random target - { - if (Unit* p = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoScriptText(SAY_WATCH, me, p); - DoCast(p, SPELL_WATCH); - WatchTarget = p->GetGUID(); - someWatched = true; - endWatch = true; - } - } - - if ((Watch_Timer < 1000) && endWatch) //1 sec before the debuf expire, store the target position - { - Unit* pUnit = Unit::GetUnit(*me, WatchTarget); - if (pUnit) - { - targetX = pUnit->GetPositionX(); - targetY = pUnit->GetPositionY(); - targetZ = pUnit->GetPositionZ(); - } - endWatch = false; - } - - if (!someWatched) - { - //Cleave - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 7000; - } else Cleave_Timer -= diff; - - //Whirlwind - if (Whirlwind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - Whirlwind_Timer = 18000; - } else Whirlwind_Timer -= diff; - - //If more then 3 targets in melee range mandokir will cast fear - if (Fear_Timer <= diff) - { - TargetInRange = 0; - - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit(*me, (*i)->getUnitGuid()); - if (pUnit && me->IsWithinMeleeRange(pUnit)) - ++TargetInRange; - } - - if (TargetInRange > 3) - DoCast(me->getVictim(), SPELL_FEAR); - - Fear_Timer = 4000; - } else Fear_Timer -=diff; - - //Mortal Strike if target below 50% hp - if (me->getVictim() && me->getVictim()->GetHealth() < me->getVictim()->GetMaxHealth()*0.5) - { - if (MortalStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - MortalStrike_Timer = 15000; - } else MortalStrike_Timer -= diff; - } - } - //Checking if Ohgan is dead. If yes Mandokir will enrage. - if (Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_OHGAN) == DONE) - { - if (!RaptorDead) - { - DoCast(me, SPELL_ENRAGE); - RaptorDead = true; - } - } - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - - DoMeleeAttackIfReady(); - } - } -}; - -//Ohgan -struct mob_ohganAI : public ScriptedAI -{ - mob_ohganAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 SunderArmor_Timer; - ScriptedInstance *m_pInstance; - - void Reset() - { - SunderArmor_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) {} - - void JustDied(Unit* /*Killer*/) - { - if (m_pInstance) - m_pInstance->SetData(TYPE_OHGAN, DONE); - } - - void UpdateAI (const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //SunderArmor_Timer - if (SunderArmor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUNDERARMOR); - SunderArmor_Timer = 10000 + rand()%5000; - } else SunderArmor_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_mandokir(Creature* pCreature) -{ - return new boss_mandokirAI (pCreature); -} - -CreatureAI* GetAI_mob_ohgan(Creature* pCreature) -{ - return new mob_ohganAI (pCreature); -} - -void AddSC_boss_mandokir() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_mandokir"; - newscript->GetAI = &GetAI_boss_mandokir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ohgan"; - newscript->GetAI = &GetAI_mob_ohgan; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp deleted file mode 100644 index 77e9f9b929f..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_marli.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Marli -SD%Complete: 80 -SDComment: Charging healers and casters not working. Perhaps wrong Spell Timers. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309005 -#define SAY_TRANSFORM -1309006 -#define SAY_SPIDER_SPAWN -1309007 -#define SAY_DEATH -1309008 - -#define SPELL_CHARGE 22911 -#define SPELL_ASPECT_OF_MARLI 24686 // A stun spell -#define SPELL_ENVOLWINGWEB 24110 -#define SPELL_POISONVOLLEY 24099 -#define SPELL_SPIDER_FORM 24084 - -//The Spider Spells -#define SPELL_LEVELUP 24312 //Not right Spell. - -struct boss_marliAI : public ScriptedAI -{ - boss_marliAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 SpawnStartSpiders_Timer; - uint32 PoisonVolley_Timer; - uint32 SpawnSpider_Timer; - uint32 Charge_Timer; - uint32 Aspect_Timer; - uint32 Transform_Timer; - uint32 TransformBack_Timer; - - bool Spawned; - bool PhaseTwo; - - void Reset() - { - SpawnStartSpiders_Timer = 1000; - PoisonVolley_Timer = 15000; - SpawnSpider_Timer = 30000; - Charge_Timer = 1500; - Aspect_Timer = 12000; - Transform_Timer = 45000; - TransformBack_Timer = 25000; - - Spawned = false; - PhaseTwo = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - if (m_pInstance) - m_pInstance->SetData(TYPE_MARLI, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->getVictim() && me->isAlive()) - { - if (PoisonVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISONVOLLEY); - PoisonVolley_Timer = 10000 + rand()%10000; - } else PoisonVolley_Timer -= diff; - - if (!PhaseTwo && Aspect_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ASPECT_OF_MARLI); - Aspect_Timer = 13000 + rand()%5000; - } else Aspect_Timer -= diff; - - if (!Spawned && SpawnStartSpiders_Timer <= diff) - { - DoScriptText(SAY_SPIDER_SPAWN, me); - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget) - return; - - Creature *Spider = NULL; - - Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - - Spawned = true; - } else SpawnStartSpiders_Timer -= diff; - - if (SpawnSpider_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget) - return; - - Creature *Spider = me->SummonCreature(15041,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Spider) - Spider->AI()->AttackStart(pTarget); - SpawnSpider_Timer = 12000 + rand()%5000; - } else SpawnSpider_Timer -= diff; - - if (!PhaseTwo && Transform_Timer <= diff) - { - DoScriptText(SAY_TRANSFORM, me); - DoCast(me, SPELL_SPIDER_FORM); - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); - me->UpdateDamagePhysical(BASE_ATTACK); - DoCast(me->getVictim(), SPELL_ENVOLWINGWEB); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-100); - - PhaseTwo = true; - Transform_Timer = urand(35000,60000); - } else Transform_Timer -= diff; - - if (PhaseTwo) - { - if (Charge_Timer <= diff) - { - Unit *pTarget = NULL; - int i = 0; - while (i < 3) // max 3 tries to get a random target with power_mana - { - ++i; - pTarget = SelectTarget(SELECT_TARGET_RANDOM,1, 100, true); // not aggro leader - if (pTarget && pTarget->getPowerType() == POWER_MANA) - i = 3; - } - if (pTarget) - { - DoCast(pTarget, SPELL_CHARGE); - //me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); - //me->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, true,1); - AttackStart(pTarget); - } - - Charge_Timer = 8000; - } else Charge_Timer -= diff; - - if (TransformBack_Timer <= diff) - { - me->SetDisplayId(15220); - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1))); - me->UpdateDamagePhysical(BASE_ATTACK); - - PhaseTwo = false; - TransformBack_Timer = urand(25000,40000); - } else TransformBack_Timer -= diff; - - } - - DoMeleeAttackIfReady(); - } - } -}; - -//Spawn of Marli -struct mob_spawn_of_marliAI : public ScriptedAI -{ - mob_spawn_of_marliAI(Creature *c) : ScriptedAI(c) {} - - uint32 LevelUp_Timer; - - void Reset() - { - LevelUp_Timer = 3000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI (const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //LevelUp_Timer - if (LevelUp_Timer <= diff) - { - DoCast(me, SPELL_LEVELUP); - LevelUp_Timer = 3000; - } else LevelUp_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_marli(Creature* pCreature) -{ - return new boss_marliAI (pCreature); -} - -CreatureAI* GetAI_mob_spawn_of_marli(Creature* pCreature) -{ - return new mob_spawn_of_marliAI (pCreature); -} - -void AddSC_boss_marli() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_marli"; - newscript->GetAI = &GetAI_boss_marli; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_spawn_of_marli"; - newscript->GetAI = &GetAI_mob_spawn_of_marli; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp deleted file mode 100644 index f7b01b26e19..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_renataki.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Renataki -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SPELL_AMBUSH 24337 -#define SPELL_THOUSANDBLADES 24649 - -#define EQUIP_ID_MAIN_HAND 0 //was item display id 31818, but this id does not exist - -struct boss_renatakiAI : public ScriptedAI -{ - boss_renatakiAI(Creature *c) : ScriptedAI(c) {} - - uint32 Invisible_Timer; - uint32 Ambush_Timer; - uint32 Visible_Timer; - uint32 Aggro_Timer; - uint32 ThousandBlades_Timer; - - bool Invisible; - bool Ambushed; - - void Reset() - { - Invisible_Timer = 8000 + rand()%10000; - Ambush_Timer = 3000; - Visible_Timer = 4000; - Aggro_Timer = 15000 + rand()%10000; - ThousandBlades_Timer = 4000 + rand()%4000; - - Invisible = false; - Ambushed = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Invisible_Timer - if (Invisible_Timer <= diff) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - me->SetDisplayId(11686); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Invisible = true; - - Invisible_Timer = 15000 + rand()%15000; - } else Invisible_Timer -= diff; - - if (Invisible) - { - if (Ambush_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - { - DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); - DoCast(pTarget, SPELL_AMBUSH); - } - - Ambushed = true; - Ambush_Timer = 3000; - } else Ambush_Timer -= diff; - } - - if (Ambushed) - { - if (Visible_Timer <= diff) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - - me->SetDisplayId(15268); - SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Invisible = false; - - Visible_Timer = 4000; - } else Visible_Timer -= diff; - } - - //Resetting some aggro so he attacks other gamers - if (!Invisible) - if (Aggro_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-50); - - if (pTarget) - AttackStart(pTarget); - - Aggro_Timer = 7000 + rand()%13000; - } else Aggro_Timer -= diff; - - if (!Invisible) - if (ThousandBlades_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_THOUSANDBLADES); - ThousandBlades_Timer = 7000 + rand()%5000; - } else ThousandBlades_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_renataki(Creature* pCreature) -{ - return new boss_renatakiAI (pCreature); -} - -void AddSC_boss_renataki() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_renataki"; - newscript->GetAI = &GetAI_boss_renataki; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp deleted file mode 100644 index 179700d36e7..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_thekal.cpp +++ /dev/null @@ -1,556 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Thekal -SD%Complete: 95 -SDComment: Almost finished. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_AGGRO -1309009 -#define SAY_DEATH -1309010 - -#define SPELL_MORTALCLEAVE 22859 -#define SPELL_SILENCE 23207 -#define SPELL_FRENZY 23342 -#define SPELL_FORCEPUNCH 24189 -#define SPELL_CHARGE 24408 -#define SPELL_ENRAGE 23537 -#define SPELL_SUMMONTIGERS 24183 -#define SPELL_TIGER_FORM 24169 -#define SPELL_RESURRECT 24173 //We will not use this spell. - -//Zealot Lor'Khan Spells -#define SPELL_SHIELD 25020 -#define SPELL_BLOODLUST 24185 -#define SPELL_GREATERHEAL 24208 -#define SPELL_DISARM 22691 - -//Zealot Lor'Khan Spells -#define SPELL_SWEEPINGSTRIKES 18765 -#define SPELL_SINISTERSTRIKE 15667 -#define SPELL_GOUGE 24698 -#define SPELL_KICK 15614 -#define SPELL_BLIND 21060 - -struct boss_thekalAI : public ScriptedAI -{ - boss_thekalAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 MortalCleave_Timer; - uint32 Silence_Timer; - uint32 Frenzy_Timer; - uint32 ForcePunch_Timer; - uint32 Charge_Timer; - uint32 Enrage_Timer; - uint32 SummonTigers_Timer; - uint32 Check_Timer; - uint32 Resurrect_Timer; - - ScriptedInstance *m_pInstance; - bool Enraged; - bool PhaseTwo; - bool WasDead; - - void Reset() - { - MortalCleave_Timer = 4000; - Silence_Timer = 9000; - Frenzy_Timer = 30000; - ForcePunch_Timer = 4000; - Charge_Timer = 12000; - Enrage_Timer = 32000; - SummonTigers_Timer = 25000; - Check_Timer = 10000; - Resurrect_Timer = 10000; - - Enraged = false; - PhaseTwo = false; - WasDead = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - if (m_pInstance) - m_pInstance->SetData(TYPE_THEKAL, DONE); - } - - void JustReachedHome() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_THEKAL, NOT_STARTED); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Check_Timer for the death of LorKhan and Zath. - if (!WasDead && Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL) - { - //Resurrect LorKhan - if (Unit *pLorKhan = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_LORKHAN))) - { - pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pLorKhan->setFaction(14); - pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); - - m_pInstance->SetData(TYPE_LORKHAN, DONE); - } - } - - if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL) - { - //Resurrect Zath - Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH)); - if (pZath) - { - pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pZath->setFaction(14); - pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); - - m_pInstance->SetData(TYPE_ZATH, DONE); - } - } - } - - Check_Timer = 5000; - } else Check_Timer -= diff; - - if (!PhaseTwo && MortalCleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALCLEAVE); - MortalCleave_Timer = 15000 + rand()%5000; - } else MortalCleave_Timer -= diff; - - if (!PhaseTwo && Silence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - Silence_Timer = 20000 + rand()%5000; - } else Silence_Timer -= diff; - - if (!PhaseTwo && !WasDead && me->GetHealth() <= me->GetMaxHealth() * 0.05) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - me->AttackStop(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_THEKAL, SPECIAL); - - WasDead=true; - } - - //Thekal will transform to Tiger if he died and was not resurrected after 10 seconds. - if (!PhaseTwo && WasDead) - { - if (Resurrect_Timer <= diff) - { - DoCast(me, SPELL_TIGER_FORM); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetHealth(int(me->GetMaxHealth()*1.0)); - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40))); - me->UpdateDamagePhysical(BASE_ATTACK); - DoResetThreat(); - PhaseTwo = true; - } else Resurrect_Timer -= diff; - } - - if ((me->GetHealth()*100 / me->GetMaxHealth() == 100) && WasDead) - { - WasDead = false; - } - - if (PhaseTwo) - { - if (Charge_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_CHARGE); - DoResetThreat(); - AttackStart(pTarget); - } - - Charge_Timer = 15000 + rand()%7000; - } else Charge_Timer -= diff; - - if (Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - Frenzy_Timer = 30000; - } else Frenzy_Timer -= diff; - - if (ForcePunch_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - ForcePunch_Timer = 16000 + rand()%5000; - } else ForcePunch_Timer -= diff; - - if (SummonTigers_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUMMONTIGERS); - SummonTigers_Timer = 10000 + rand()%4000; - } else SummonTigers_Timer -= diff; - - if ((me->GetHealth()*100 / me->GetMaxHealth() < 11) && !Enraged) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } - } - - DoMeleeAttackIfReady(); - - } -}; - -//Zealot Lor'Khan -struct mob_zealot_lorkhanAI : public ScriptedAI -{ - mob_zealot_lorkhanAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 Shield_Timer; - uint32 BloodLust_Timer; - uint32 GreaterHeal_Timer; - uint32 Disarm_Timer; - uint32 Check_Timer; - - bool FakeDeath; - - ScriptedInstance *m_pInstance; - - void Reset() - { - Shield_Timer = 1000; - BloodLust_Timer = 16000; - GreaterHeal_Timer = 32000; - Disarm_Timer = 6000; - Check_Timer = 10000; - - FakeDeath = false; - - if (m_pInstance) - m_pInstance->SetData(TYPE_LORKHAN, NOT_STARTED); - - me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI (const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Shield_Timer - if (Shield_Timer <= diff) - { - DoCast(me, SPELL_SHIELD); - Shield_Timer = 61000; - } else Shield_Timer -= diff; - - //BloodLust_Timer - if (BloodLust_Timer <= diff) - { - DoCast(me, SPELL_BLOODLUST); - BloodLust_Timer = 20000+rand()%8000; - } else BloodLust_Timer -= diff; - - //Casting Greaterheal to Thekal or Zath if they are in meele range. - if (GreaterHeal_Timer <= diff) - { - if (m_pInstance) - { - Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL)); - Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH)); - - if (!pThekal || !pZath) - return; - - switch (urand(0,1)) - { - case 0: - if (me->IsWithinMeleeRange(pThekal)) - DoCast(pThekal, SPELL_GREATERHEAL); - break; - case 1: - if (me->IsWithinMeleeRange(pZath)) - DoCast(pZath, SPELL_GREATERHEAL); - break; - } - } - - GreaterHeal_Timer = 15000+rand()%5000; - } else GreaterHeal_Timer -= diff; - - //Disarm_Timer - if (Disarm_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DISARM); - Disarm_Timer = 15000+rand()%10000; - } else Disarm_Timer -= diff; - - //Check_Timer for the death of LorKhan and Zath. - if (!FakeDeath && Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL) - { - //Resurrect Thekal - if (Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL))) - { - pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pThekal->setFaction(14); - pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); - } - } - - if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL) - { - //Resurrect Zath - if (Unit *pZath = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_ZATH))) - { - pZath->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pZath->setFaction(14); - pZath->SetHealth(int(pZath->GetMaxHealth()*1.0)); - } - } - } - - Check_Timer = 5000; - } else Check_Timer -= diff; - - if (me->GetHealth() <= me->GetMaxHealth() * 0.05) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - me->setFaction(35); - me->AttackStop(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_LORKHAN, SPECIAL); - - FakeDeath = true; - } - - DoMeleeAttackIfReady(); - } -}; - -//Zealot Zath -struct mob_zealot_zathAI : public ScriptedAI -{ - mob_zealot_zathAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - uint32 SweepingStrikes_Timer; - uint32 SinisterStrike_Timer; - uint32 Gouge_Timer; - uint32 Kick_Timer; - uint32 Blind_Timer; - uint32 Check_Timer; - - bool FakeDeath; - - ScriptedInstance *m_pInstance; - - void Reset() - { - SweepingStrikes_Timer = 13000; - SinisterStrike_Timer = 8000; - Gouge_Timer = 25000; - Kick_Timer = 18000; - Blind_Timer = 5000; - Check_Timer = 10000; - - FakeDeath = false; - - if (m_pInstance) - m_pInstance->SetData(TYPE_ZATH, NOT_STARTED); - - me->SetStandState(UNIT_STAND_STATE_STAND); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI (const uint32 diff) - { - if (!UpdateVictim()) - return; - - //SweepingStrikes_Timer - if (SweepingStrikes_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SWEEPINGSTRIKES); - SweepingStrikes_Timer = 22000+rand()%4000; - } else SweepingStrikes_Timer -= diff; - - //SinisterStrike_Timer - if (SinisterStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SINISTERSTRIKE); - SinisterStrike_Timer = 8000+rand()%8000; - } else SinisterStrike_Timer -= diff; - - //Gouge_Timer - if (Gouge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_GOUGE); - - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-100); - - Gouge_Timer = 17000+rand()%10000; - } else Gouge_Timer -= diff; - - //Kick_Timer - if (Kick_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KICK); - Kick_Timer = 15000+rand()%10000; - } else Kick_Timer -= diff; - - //Blind_Timer - if (Blind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BLIND); - Blind_Timer = 10000+rand()%10000; - } else Blind_Timer -= diff; - - //Check_Timer for the death of LorKhan and Zath. - if (!FakeDeath && Check_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL) - { - //Resurrect LorKhan - if (Unit *pLorKhan = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_LORKHAN))) - { - pLorKhan->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pLorKhan->setFaction(14); - pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0)); - } - } - - if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL) - { - //Resurrect Thekal - if (Unit *pThekal = Unit::GetUnit((*me), m_pInstance->GetData64(DATA_THEKAL))) - { - pThekal->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pThekal->setFaction(14); - pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0)); - } - } - } - - Check_Timer = 5000; - } else Check_Timer -= diff; - - if (me->GetHealth() <= me->GetMaxHealth() * 0.05) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetStandState(UNIT_STAND_STATE_SLEEP); - me->setFaction(35); - me->AttackStop(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_ZATH, SPECIAL); - - FakeDeath = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_thekal(Creature* pCreature) -{ - return new boss_thekalAI (pCreature); -} - -CreatureAI* GetAI_mob_zealot_lorkhan(Creature* pCreature) -{ - return new mob_zealot_lorkhanAI (pCreature); -} - -CreatureAI* GetAI_mob_zealot_zath(Creature* pCreature) -{ - return new mob_zealot_zathAI (pCreature); -} - -void AddSC_boss_thekal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_thekal"; - newscript->GetAI = &GetAI_boss_thekal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_zealot_lorkhan"; - newscript->GetAI = &GetAI_mob_zealot_lorkhan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_zealot_zath"; - newscript->GetAI = &GetAI_mob_zealot_zath; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp deleted file mode 100644 index ec1a7a142b5..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_venoxis.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Venoxis -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SAY_TRANSFORM -1309000 -#define SAY_DEATH -1309001 - -#define SPELL_HOLY_FIRE 23860 -#define SPELL_HOLY_WRATH 28883 //Not sure if this or 23979 -#define SPELL_VENOMSPIT 23862 -#define SPELL_HOLY_NOVA 23858 -#define SPELL_POISON_CLOUD 23861 -#define SPELL_SNAKE_FORM 23849 -#define SPELL_RENEW 23895 -#define SPELL_BERSERK 23537 -#define SPELL_DISPELL 23859 - -struct boss_venoxisAI : public ScriptedAI -{ - boss_venoxisAI(Creature *c) : ScriptedAI(c) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance *m_pInstance; - - uint32 HolyFire_Timer; - uint32 HolyWrath_Timer; - uint32 VenomSpit_Timer; - uint32 Renew_Timer; - uint32 PoisonCloud_Timer; - uint32 HolyNova_Timer; - uint32 Dispell_Timer; - uint32 TargetInRange; - - bool PhaseTwo; - bool InBerserk; - - void Reset() - { - HolyFire_Timer = 10000; - HolyWrath_Timer = 60500; - VenomSpit_Timer = 5500; - Renew_Timer = 30500; - PoisonCloud_Timer = 2000; - HolyNova_Timer = 5000; - Dispell_Timer = 35000; - TargetInRange = 0; - - PhaseTwo = false; - InBerserk= false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - if (m_pInstance) - m_pInstance->SetData(TYPE_VENOXIS, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if ((me->GetHealth()*100 / me->GetMaxHealth() > 50)) - { - if (Dispell_Timer <= diff) - { - DoCast(me, SPELL_DISPELL); - Dispell_Timer = 15000 + rand()%15000; - } else Dispell_Timer -= diff; - - if (Renew_Timer <= diff) - { - DoCast(me, SPELL_RENEW); - Renew_Timer = 20000 + rand()%10000; - } else Renew_Timer -= diff; - - if (HolyWrath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HOLY_WRATH); - HolyWrath_Timer = 15000 + rand()%10000; - } else HolyWrath_Timer -= diff; - - if (HolyNova_Timer <= diff) - { - TargetInRange = 0; - for (uint8 i = 0; i < 10; ++i) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,i)) - if (me->IsWithinMeleeRange(pTarget)) - ++TargetInRange; - } - - if (TargetInRange > 1) - { - DoCast(me->getVictim(), SPELL_HOLY_NOVA); - HolyNova_Timer = 1000; - } - else - { - HolyNova_Timer = 2000; - } - - } else HolyNova_Timer -= diff; - - if (HolyFire_Timer < diff && TargetInRange < 3) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_HOLY_FIRE); - - HolyFire_Timer = 8000; - } else HolyFire_Timer -= diff; - } - else - { - if (!PhaseTwo) - { - DoScriptText(SAY_TRANSFORM, me); - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SNAKE_FORM); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); - const CreatureInfo *cinfo = me->GetCreatureInfo(); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 25))); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 25))); - me->UpdateDamagePhysical(BASE_ATTACK); - DoResetThreat(); - PhaseTwo = true; - } - - if (PhaseTwo && PoisonCloud_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_CLOUD); - PoisonCloud_Timer = 15000; - }PoisonCloud_Timer -=diff; - - if (PhaseTwo && VenomSpit_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_VENOMSPIT); - - VenomSpit_Timer = 15000 + rand()%5000; - } else VenomSpit_Timer -= diff; - - if (PhaseTwo && (me->GetHealth()*100 / me->GetMaxHealth() < 11)) - { - if (!InBerserk) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_BERSERK); - InBerserk = true; - } - } - } - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_venoxis(Creature* pCreature) -{ - return new boss_venoxisAI (pCreature); -} - -void AddSC_boss_venoxis() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_venoxis"; - newscript->GetAI = &GetAI_boss_venoxis; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp b/src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp deleted file mode 100644 index a71d7e0504a..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/boss_wushoolay.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Wushoolay -SD%Complete: 100 -SDComment: -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -#define SPELL_LIGHTNINGCLOUD 25033 -#define SPELL_LIGHTNINGWAVE 24819 - -struct boss_wushoolayAI : public ScriptedAI -{ - boss_wushoolayAI(Creature *c) : ScriptedAI(c) {} - - uint32 LightningCloud_Timer; - uint32 LightningWave_Timer; - - void Reset() - { - LightningCloud_Timer = 5000 + rand()%5000; - LightningWave_Timer = 8000 + rand()%8000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //LightningCloud_Timer - if (LightningCloud_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LIGHTNINGCLOUD); - LightningCloud_Timer = 15000 + rand()%5000; - } else LightningCloud_Timer -= diff; - - //LightningWave_Timer - if (LightningWave_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) DoCast(pTarget, SPELL_LIGHTNINGWAVE); - - LightningWave_Timer = 12000 + rand()%4000; - } else LightningWave_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_wushoolay(Creature* pCreature) -{ - return new boss_wushoolayAI (pCreature); -} - -void AddSC_boss_wushoolay() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_wushoolay"; - newscript->GetAI = &GetAI_boss_wushoolay; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp deleted file mode 100644 index aaed1c6df3a..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/instance_zulgurub.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_ZulGurub -SD%Complete: 80 -SDComment: Missing reset function after killing a boss for Ohgan, Thekal. -SDCategory: Zul'Gurub -EndScriptData */ - -#include "ScriptedPch.h" -#include "zulgurub.h" - -struct instance_zulgurub : public ScriptedInstance -{ - instance_zulgurub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. - uint32 m_auiEncounter[MAX_ENCOUNTERS]; - - //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. - uint64 m_uiLorKhanGUID; - uint64 m_uiZathGUID; - uint64 m_uiThekalGUID; - uint64 m_uiJindoGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiLorKhanGUID = 0; - m_uiZathGUID = 0; - m_uiThekalGUID = 0; - m_uiJindoGUID = 0; - } - - bool IsEncounterInProgress() const - { - //not active in Zul'Gurub - return false; - } - - void OnCreatureCreate(Creature* pCreature) - { - switch(pCreature->GetEntry()) - { - case 11347: m_uiLorKhanGUID = pCreature->GetGUID(); break; - case 11348: m_uiZathGUID = pCreature->GetGUID(); break; - case 14509: m_uiThekalGUID = pCreature->GetGUID(); break; - case 11380: m_uiJindoGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_ARLOKK: - m_auiEncounter[0] = uiData; - break; - - case TYPE_JEKLIK: - m_auiEncounter[1] = uiData; - break; - - case TYPE_VENOXIS: - m_auiEncounter[2] = uiData; - break; - - case TYPE_MARLI: - m_auiEncounter[3] = uiData; - break; - - case TYPE_THEKAL: - m_auiEncounter[4] = uiData; - break; - - case TYPE_LORKHAN: - m_auiEncounter[5] = uiData; - break; - - case TYPE_ZATH: - m_auiEncounter[6] = uiData; - break; - - case TYPE_OHGAN: - m_auiEncounter[7] = uiData; - break; - } - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case TYPE_ARLOKK: - return m_auiEncounter[0]; - case TYPE_JEKLIK: - return m_auiEncounter[1]; - case TYPE_VENOXIS: - return m_auiEncounter[2]; - case TYPE_MARLI: - return m_auiEncounter[3]; - case TYPE_THEKAL: - return m_auiEncounter[4]; - case TYPE_LORKHAN: - return m_auiEncounter[5]; - case TYPE_ZATH: - return m_auiEncounter[6]; - case TYPE_OHGAN: - return m_auiEncounter[7]; - } - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_LORKHAN: - return m_uiLorKhanGUID; - case DATA_ZATH: - return m_uiZathGUID; - case DATA_THEKAL: - return m_uiThekalGUID; - case DATA_JINDO: - return m_uiJindoGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_zulgurub(Map* pMap) -{ - return new instance_zulgurub(pMap); -} - -void AddSC_instance_zulgurub() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_zulgurub"; - newscript->GetInstanceData = &GetInstanceData_instance_zulgurub; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h b/src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h deleted file mode 100644 index bf55a54c1d5..00000000000 --- a/src/server/scripts/EasternKingdoms/zulgurub/zulgurub.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_ZULGURUB_H -#define DEF_ZULGURUB_H - -enum eTypes -{ - MAX_ENCOUNTERS = 8, - - TYPE_ARLOKK = 1, - TYPE_JEKLIK = 2, - TYPE_VENOXIS = 3, - TYPE_MARLI = 4, - TYPE_OHGAN = 5, - TYPE_THEKAL = 6, - TYPE_ZATH = 7, - TYPE_LORKHAN = 8, - - DATA_JINDO = 10, - DATA_LORKHAN = 11, - DATA_THEKAL = 12, - DATA_ZATH = 13 -}; - -#endif - diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp new file mode 100644 index 00000000000..a3fd42a0fe7 --- /dev/null +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp @@ -0,0 +1,252 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" +#include "ScriptedEscortAI.h" + +enum eSpells +{ + SPELL_BLESSING_OF_BLACKFATHOM = 8733, + SPELL_RAVAGE = 8391, + SPELL_FROST_NOVA = 865, + SPELL_FROST_BOLT_VOLLEY = 8398, + SPELL_TELEPORT_DARNASSUS = 9268 +}; + +#define GOSSIP_ITEM_MORRIDUNE "Please port me to Darnassus" + +const Position HomePosition = {-815.817,-145.299,-25.870, 0}; + +bool GoHello_blackfathom_altar(Player *pPlayer, GameObject* /*pGo*/) +{ + if (!pPlayer->HasAura(SPELL_BLESSING_OF_BLACKFATHOM)) + pPlayer->AddAura(SPELL_BLESSING_OF_BLACKFATHOM,pPlayer); + return true; +} + +bool GoHello_blackfathom_fire(Player * /*pPlayer*/, GameObject* pGo) +{ + ScriptedInstance *pInstance = pGo->GetInstanceData(); + + if (pInstance) + { + pGo->SetGoState(GO_STATE_ACTIVE); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pInstance->SetData(DATA_FIRE, pInstance->GetData(DATA_FIRE) + 1); + return true; + } + return false; +} + +struct npc_blackfathom_deeps_eventAI : public ScriptedAI +{ + npc_blackfathom_deeps_eventAI(Creature* pCreature) : ScriptedAI(pCreature) + { + if (pCreature->isSummon()) + { + pCreature->SetHomePosition(HomePosition); + AttackPlayer(); + } + + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiRavageTimer; + uint32 uiFrostNovaTimer; + uint32 uiFrostBoltVolleyTimer; + + bool bFlee; + + void Reset() + { + bFlee = false; + + uiRavageTimer = urand(5000,8000); + uiFrostNovaTimer = urand(9000,12000); + uiFrostBoltVolleyTimer = urand(2000,4000); + } + + void AttackPlayer() + { + Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + me->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(me); + me->AddThreat(pPlayer, 0.0f); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + switch (me->GetEntry()) + { + case NPC_AKU_MAI_SNAPJAW: + { + if (uiRavageTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_RAVAGE); + uiRavageTimer = urand(9000,14000); + } else uiRavageTimer -= uiDiff; + break; + } + case NPC_MURKSHALLOW_SOFTSHELL: + case NPC_BARBED_CRUSTACEAN: + { + if (!bFlee && HealthBelowPct(15)) + { + bFlee = true; + me->DoFleeToGetAssistance(); + } + break; + } + case NPC_AKU_MAI_SERVANT: + { + if (uiFrostBoltVolleyTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget) + DoCast(pTarget, SPELL_FROST_BOLT_VOLLEY); + } + uiFrostBoltVolleyTimer = urand(5000,8000); + } else uiFrostBoltVolleyTimer -= uiDiff; + if (uiFrostNovaTimer <= uiDiff) + { + DoCastAOE(SPELL_FROST_NOVA,false); + uiFrostNovaTimer = urand(25000,30000); + } else uiFrostNovaTimer -= uiDiff; + break; + } + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (me->isSummon()) //we are not a normal spawn. + if (pInstance) + pInstance->SetData(DATA_EVENT, pInstance->GetData(DATA_EVENT) + 1); + } +}; + +CreatureAI* GetAI_npc_blackfathom_deeps_event(Creature* pCreature) +{ + return new npc_blackfathom_deeps_eventAI (pCreature); +} + +enum eMorridune +{ + SAY_MORRIDUNE_1 = -1048003, + SAY_MORRIDUNE_2 = -1048004 +}; + +struct npc_morriduneAI : public npc_escortAI +{ + npc_morriduneAI(Creature* pCreature) : npc_escortAI(pCreature) + { + DoScriptText(SAY_MORRIDUNE_1,pCreature); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + Start(false,false,NULL); + } + + void WaypointReached(uint32 uiPoint) + { + switch(uiPoint) + { + case 4: + SetEscortPaused(true); + me->SetOrientation(1.775791); + me->SendMovementFlagUpdate(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + DoScriptText(SAY_MORRIDUNE_2,me); + break; + } + } +}; + +CreatureAI* GetAI_npc_morridune(Creature* pCreature) +{ + return new npc_morriduneAI (pCreature); +} + +bool GossipHello_npc_morridune(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MORRIDUNE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_morridune(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->TeleportTo(1,9952.239,2284.277,1341.394,1.595); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +void AddSC_blackfathom_deeps() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "go_blackfathom_altar"; + newscript->pGOHello = &GoHello_blackfathom_altar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_blackfathom_fire"; + newscript->pGOHello = &GoHello_blackfathom_fire; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_blackfathom_deeps_event"; + newscript->GetAI = &GetAI_npc_blackfathom_deeps_event; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_morridune"; + newscript->GetAI = &GetAI_npc_morridune; + newscript->pGossipHello = &GossipHello_npc_morridune; + newscript->pGossipSelect = &GossipSelect_npc_morridune; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.h b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.h new file mode 100644 index 00000000000..e8bbab9f105 --- /dev/null +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BFD_H +#define DEF_BFD_H + +enum Data64 +{ + DATA_SHRINE1, + DATA_SHRINE2, + DATA_SHRINE3, + DATA_SHRINE4, + DATA_TWILIGHT_LORD_KELRIS, + DATA_SHRINE_OF_GELIHAST, + DATA_ALTAR_OF_THE_DEEPS, + DATA_MAINDOOR, +}; + +enum Data +{ + TYPE_GELIHAST, + TYPE_KELRIS, + TYPE_SHRINE, + TYPE_AKU_MAI, + DATA_FIRE, + DATA_EVENT +}; + +enum Creatures +{ + NPC_TWILIGHT_LORD_KELRIS = 4832, + NPC_LORGUS_JETT = 12902, + + NPC_AKU_MAI_SNAPJAW = 4825, + NPC_MURKSHALLOW_SOFTSHELL = 4977, + NPC_AKU_MAI_SERVANT = 4978, + NPC_BARBED_CRUSTACEAN = 4823, + + NPC_MORRIDUNE = 6729 +}; + +enum GameObjects +{ + GO_SHRINE_OF_GELIHAST = 103015, + GO_FIRE_OF_AKU_MAI_1 = 21118, + GO_FIRE_OF_AKU_MAI_2 = 21119, + GO_FIRE_OF_AKU_MAI_3 = 21120, + GO_FIRE_OF_AKU_MAI_4 = 21121, + GO_AKU_MAI_DOOR = 21117, + GO_ALTAR_OF_THE_DEEPS = 103016 +}; +#endif diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp new file mode 100644 index 00000000000..a4b7a160be8 --- /dev/null +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp @@ -0,0 +1,94 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" + +enum Spells +{ + SPELL_POISON_CLOUD = 3815, + SPELL_FRENZIED_RAGE = 3490 +}; + +struct boss_aku_maiAI : public ScriptedAI +{ + boss_aku_maiAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiPoisonCloudTimer; + bool bIsEnraged; + + ScriptedInstance *pInstance; + + void Reset() + { + uiPoisonCloudTimer = urand(5000,9000); + bIsEnraged = false; + if (pInstance) + pInstance->SetData(TYPE_AKU_MAI, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(TYPE_AKU_MAI, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_AKU_MAI, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiPoisonCloudTimer < diff) + { + DoCastVictim(SPELL_POISON_CLOUD); + uiPoisonCloudTimer = urand(25000,50000); + } else uiPoisonCloudTimer -= diff; + + if (!bIsEnraged && HealthBelowPct(30)) + { + DoCast(me,SPELL_FRENZIED_RAGE); + bIsEnraged = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_aku_mai(Creature* pCreature) +{ + return new boss_aku_maiAI (pCreature); +} + +void AddSC_boss_aku_mai() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_aku_mai"; + newscript->GetAI = &GetAI_boss_aku_mai; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp new file mode 100644 index 00000000000..374a526f098 --- /dev/null +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp @@ -0,0 +1,85 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" + +enum Spells +{ + SPELL_NET = 6533 +}; + +struct boss_gelihastAI : public ScriptedAI +{ + boss_gelihastAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiNetTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiNetTimer = urand(2000,4000); + if (pInstance) + pInstance->SetData(TYPE_GELIHAST, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(TYPE_GELIHAST, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(TYPE_GELIHAST, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiNetTimer < diff) + { + DoCastVictim(SPELL_NET); + uiNetTimer = urand(4000,7000); + } else uiNetTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_gelihast(Creature* pCreature) +{ + return new boss_gelihastAI (pCreature); +} + +void AddSC_boss_gelihast() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_gelihast"; + newscript->GetAI = &GetAI_boss_gelihast; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp new file mode 100644 index 00000000000..bd7e1014d1a --- /dev/null +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp @@ -0,0 +1,108 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" + +enum Spells +{ + SPELL_MIND_BLAST = 15587, + SPELL_SLEEP = 8399, +}; + +//Id's from ACID +enum Yells +{ + SAY_AGGRO = -1048002, + SAY_SLEEP = -1048001, + SAY_DEATH = -1048000 +}; + +struct boss_kelrisAI : public ScriptedAI +{ + boss_kelrisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiMindBlastTimer; + uint32 uiSleepTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiMindBlastTimer = urand(2000,5000); + uiSleepTimer = urand(9000,12000); + if (pInstance) + pInstance->SetData(TYPE_KELRIS, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(TYPE_KELRIS, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + pInstance->SetData(TYPE_KELRIS, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiMindBlastTimer < diff) + { + DoCastVictim(SPELL_MIND_BLAST); + uiMindBlastTimer = urand(7000,9000); + } else uiMindBlastTimer -= diff; + + if (uiSleepTimer < diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(SAY_SLEEP, me); + DoCast(pTarget, SPELL_SLEEP); + } + uiSleepTimer = urand(15000,20000); + } else uiSleepTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kelris(Creature* pCreature) +{ + return new boss_kelrisAI (pCreature); +} + +void AddSC_boss_kelris() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_kelris"; + newscript->GetAI = &GetAI_boss_kelris; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp new file mode 100644 index 00000000000..a485684e699 --- /dev/null +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp @@ -0,0 +1,259 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Blackfathom_Deeps +SD%Complete: 50 +SDComment: +SDCategory: Blackfathom Deeps +EndScriptData */ + +#include "ScriptedPch.h" +#include "blackfathom_deeps.h" + +#define MAX_ENCOUNTER 4 + +/* Encounter 0 = Gelihast + Encounter 1 = Twilight Lord Kelris + Encounter 2 = Shrine event + Encounter 3 = Aku'Mai + */ + +const Position LorgusPosition[4] = +{ + { -458.500610, -38.343079, -33.474445 }, + { -469.423615, -88.400513, -39.265102 }, + { -622.354980, -10.350100, -22.777000 }, + { -759.640564, 16.658913, -29.159529 } +}; + +const Position SpawnsLocation[] = +{ + {-775.431, -153.853, -25.871, 3.207}, + {-775.404, -174.132, -25.871, 3.185}, + {-862.430, -154.937, -25.871, 0.060}, + {-862.193, -174.251, -25.871, 6.182}, + {-863.895, -458.899, -33.891, 5.637} +}; + +struct instance_blackfathom_deeps : public ScriptedInstance +{ + instance_blackfathom_deeps(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 m_uiTwilightLordKelrisGUID; + uint64 m_uiShrine1GUID; + uint64 m_uiShrine2GUID; + uint64 m_uiShrine3GUID; + uint64 m_uiShrine4GUID; + uint64 m_uiShrineOfGelihastGUID; + uint64 m_uiAltarOfTheDeepsGUID; + uint64 m_uiMainDoorGUID; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + uint8 m_uiCountFires; + uint8 uiDeathTimes; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiTwilightLordKelrisGUID = 0; + m_uiShrine1GUID = 0; + m_uiShrine2GUID = 0; + m_uiShrine3GUID = 0; + m_uiShrine4GUID = 0; + m_uiShrineOfGelihastGUID = 0; + m_uiAltarOfTheDeepsGUID = 0; + m_uiMainDoorGUID = 0; + m_uiCountFires = 0; + uiDeathTimes = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case NPC_TWILIGHT_LORD_KELRIS: + m_uiTwilightLordKelrisGUID = pCreature->GetGUID(); + break; + case NPC_LORGUS_JETT: + pCreature->SetHomePosition(LorgusPosition[urand(0,3)]); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_FIRE_OF_AKU_MAI_1: + m_uiShrine1GUID = pGo->GetGUID(); + break; + case GO_FIRE_OF_AKU_MAI_2: + m_uiShrine2GUID = pGo->GetGUID(); + break; + case GO_FIRE_OF_AKU_MAI_3: + m_uiShrine3GUID = pGo->GetGUID(); + break; + case GO_FIRE_OF_AKU_MAI_4: + m_uiShrine4GUID = pGo->GetGUID(); + break; + case GO_SHRINE_OF_GELIHAST: + m_uiShrineOfGelihastGUID = pGo->GetGUID(); + if (m_auiEncounter[0] != DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case GO_ALTAR_OF_THE_DEEPS: + m_uiAltarOfTheDeepsGUID = pGo->GetGUID(); + if (m_auiEncounter[3] != DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case GO_AKU_MAI_DOOR: + if (m_auiEncounter[2] == DONE) + HandleGameObject(NULL,true,pGo); + m_uiMainDoorGUID = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_GELIHAST: + m_auiEncounter[0] = uiData; + if (uiData == DONE) + if (GameObject *pGo = instance->GetGameObject(m_uiShrineOfGelihastGUID)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case TYPE_AKU_MAI: + m_auiEncounter[3] = uiData; + if (uiData == DONE) + if (GameObject *pGo = instance->GetGameObject(m_uiAltarOfTheDeepsGUID)) + { + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGo->SummonCreature(NPC_MORRIDUNE,SpawnsLocation[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + break; + case DATA_FIRE: + m_uiCountFires = uiData; + switch (m_uiCountFires) + { + case 1: + if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) + { + pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + break; + case 2: + if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) + { + for (uint8 i = 0; i < 2; ++i) + { + pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + } + break; + case 3: + if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) + { + pGO->SummonCreature(NPC_AKU_MAI_SERVANT, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_AKU_MAI_SERVANT, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + break; + case 4: + if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) + { + pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + } + break; + } + break; + case DATA_EVENT: + uiDeathTimes = uiData; + if (uiDeathTimes == 18) + HandleGameObject(m_uiMainDoorGUID,true); + break; + } + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_GELIHAST: + return m_auiEncounter[0]; + case TYPE_KELRIS: + return m_auiEncounter[1]; + case TYPE_SHRINE: + return m_auiEncounter[2]; + case TYPE_AKU_MAI: + return m_auiEncounter[3]; + case DATA_FIRE: + return m_uiCountFires; + case DATA_EVENT: + return uiDeathTimes; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_TWILIGHT_LORD_KELRIS: + return m_uiTwilightLordKelrisGUID; + case DATA_SHRINE1: + return m_uiShrine1GUID; + case DATA_SHRINE2: + return m_uiShrine2GUID; + case DATA_SHRINE3: + return m_uiShrine3GUID; + case DATA_SHRINE4: + return m_uiShrine4GUID; + case DATA_SHRINE_OF_GELIHAST: + return m_uiShrineOfGelihastGUID; + case DATA_MAINDOOR: + return m_uiMainDoorGUID; + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_blackfathom_deeps(Map* pMap) +{ + return new instance_blackfathom_deeps(pMap); +} + +void AddSC_instance_blackfathom_deeps() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blackfathom_deeps"; + newscript->GetInstanceData = &GetInstanceData_instance_blackfathom_deeps; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp new file mode 100644 index 00000000000..287d3cf8e9b --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp @@ -0,0 +1,156 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* Script Data Start +SDName: Boss epoch +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro, consecutive attacks to a random target durin time wrap, adjust timers +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CURSE_OF_EXERTION = 52772, + SPELL_TIME_WARP = 52766, //Time slows down, reducing attack, casting and movement speed by 70% for 6 sec. + SPELL_TIME_STOP = 58848, //Stops time in a 50 yard sphere for 2 sec. + SPELL_WOUNDING_STRIKE = 52771, //Used only on the tank + H_SPELL_WOUNDING_STRIKE = 58830 +}; + +enum Yells +{ + SAY_INTRO = -1595000, //"Prince Arthas Menethil, on this day, a powerful darkness has taken hold of your soul. The death you are destined to visit upon others will this day be your own." + SAY_AGGRO = -1595001, //"We'll see about that, young prince." + SAY_TIME_WARP_1 = -1595002, //"Tick tock, tick tock..." + SAY_TIME_WARP_2 = -1595003, //"Not quick enough!" + SAY_TIME_WARP_3 = -1595004, //"Let's get this over with. " + SAY_SLAY_1 = -1595005, //"There is no future for you." + SAY_SLAY_2 = -1595006, //"This is the hour of our greatest triumph!" + SAY_SLAY_3 = -1595007, //"You were destined to fail. " + SAY_DEATH = -1595008 //"*gurgles*" +}; + +struct boss_epochAI : public ScriptedAI +{ + boss_epochAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint8 uiStep; + + uint32 uiStepTimer; + uint32 uiWoundingStrikeTimer; + uint32 uiTimeWarpTimer; + uint32 uiTimeStopTimer; + uint32 uiCurseOfExertionTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiStep = 1; + uiStepTimer = 26000; + uiCurseOfExertionTimer = 9300; + uiTimeWarpTimer = 25300; + uiTimeStopTimer = 21300; + uiWoundingStrikeTimer = 5300; + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiCurseOfExertionTimer < diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CURSE_OF_EXERTION); + uiCurseOfExertionTimer = 9300; + } else uiCurseOfExertionTimer -= diff; + + if (uiWoundingStrikeTimer < diff) + { + DoCastVictim(SPELL_WOUNDING_STRIKE); + uiWoundingStrikeTimer = 5300; + } else uiWoundingStrikeTimer -= diff; + + if (uiTimeStopTimer < diff) + { + DoCastAOE(SPELL_TIME_STOP); + uiTimeStopTimer = 21300; + } else uiTimeStopTimer -= diff; + + if (uiTimeWarpTimer < diff) + { + DoScriptText(RAND(SAY_TIME_WARP_1,SAY_TIME_WARP_2,SAY_TIME_WARP_3), me); + DoCastAOE(SPELL_TIME_WARP); + uiTimeWarpTimer = 25300; + } else uiTimeWarpTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_epoch(Creature* pCreature) +{ + return new boss_epochAI (pCreature); +} + +void AddSC_boss_epoch() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_epoch"; + newscript->GetAI = &GetAI_boss_epoch; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp new file mode 100644 index 00000000000..12cdf00f2a5 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp @@ -0,0 +1,88 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CORRUPTING_BLIGHT = 60588, + SPELL_VOID_STRIKE = 60590 +}; + +enum Yells +{ + SAY_AGGRO = -1595045, + SAY_FAIL = -1595046, + SAY_DEATH = -1595047 +}; + + +struct boss_infinite_corruptorAI : public ScriptedAI +{ + boss_infinite_corruptorAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, DONE); + } +}; + +CreatureAI* GetAI_boss_infinite_corruptor(Creature* pCreature) +{ + return new boss_infinite_corruptorAI(pCreature); +} + +void AddSC_boss_infinite_corruptor() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_infinite_corruptor"; + newscript->GetAI = &GetAI_boss_infinite_corruptor; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp new file mode 100644 index 00000000000..a39f3289a5a --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp @@ -0,0 +1,262 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss mal_ganis +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro & outro +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_mal_ganis' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CARRION_SWARM = 52720, //A cresting wave of chaotic magic splashes over enemies in front of the caster, dealing 3230 to 3570 Shadow damage and 380 to 420 Shadow damage every 3 sec. for 15 sec. + H_SPELL_CARRION_SWARM = 58852, + SPELL_MIND_BLAST = 52722, //Inflicts 4163 to 4837 Shadow damage to an enemy. + H_SPELL_MIND_BLAST = 58850, + SPELL_SLEEP = 52721, //Puts an enemy to sleep for up to 10 sec. Any damage caused will awaken the target. + H_SPELL_SLEEP = 58849, + SPELL_VAMPIRIC_TOUCH = 52723 //Heals the caster for half the damage dealt by a melee attack. +}; + +enum Yells +{ + SAY_INTRO_1 = -1595009, + SAY_INTRO_2 = -1595010, + SAY_AGGRO = -1595011, + SAY_KILL_1 = -1595012, + SAY_KILL_2 = -1595013, + SAY_KILL_3 = -1595014, + SAY_SLAY_1 = -1595015, + SAY_SLAY_2 = -1595016, + SAY_SLAY_3 = -1595017, + SAY_SLAY_4 = -1595018, + SAY_SLEEP_1 = -1595019, + SAY_SLEEP_2 = -1595020, + SAY_30HEALTH = -1595021, + SAY_15HEALTH = -1595022, + SAY_ESCAPE_SPEECH_1 = -1595023, + SAY_ESCAPE_SPEECH_2 = -1595024, + SAY_OUTRO = -1595025, +}; + +enum CombatPhases +{ + COMBAT, + OUTRO +}; + +struct boss_mal_ganisAI : public ScriptedAI +{ + boss_mal_ganisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiCarrionSwarmTimer; + uint32 uiMindBlastTimer; + uint32 uiVampiricTouchTimer; + uint32 uiSleepTimer; + + uint8 uiOutroStep; + uint32 uiOutroTimer; + + bool bYelled; + bool bYelled2; + + CombatPhases Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + bYelled = false; + bYelled2 = false; + Phase = COMBAT; + uiCarrionSwarmTimer = 6000; + uiMindBlastTimer = 11000; + uiVampiricTouchTimer = urand(10000,15000); + uiSleepTimer = urand(15000,20000); + uiOutroTimer = 1000; + + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, IN_PROGRESS); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = me->GetHealth()-1; + } + + void UpdateAI(const uint32 diff) + { + switch(Phase) + { + case COMBAT: + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bYelled && HealthBelowPct(30)) + { + DoScriptText(SAY_30HEALTH, me); + bYelled = true; + } + + if (!bYelled2 && HealthBelowPct(15)) + { + DoScriptText(SAY_15HEALTH, me); + bYelled2 = true; + } + + if (HealthBelowPct(1)) + { + //Handle Escape Event: Don't forget to add Player::RewardPlayerAndGroupAtEvent + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + uiOutroStep = 1; + Phase = OUTRO; + return; + } + + if (Creature* pArthas = me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0)) + if (pArthas->isDead()) + { + EnterEvadeMode(); + me->DisappearAndDie(); + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, FAIL); + } + + if (uiCarrionSwarmTimer < diff) + { + DoCastVictim(SPELL_CARRION_SWARM); + uiCarrionSwarmTimer = 7000; + } else uiCarrionSwarmTimer -= diff; + + if (uiMindBlastTimer < diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_MIND_BLAST); + uiMindBlastTimer = 6000; + } else uiMindBlastTimer -= diff; + + if (uiVampiricTouchTimer < diff) + { + DoCast(me, SPELL_VAMPIRIC_TOUCH); + uiVampiricTouchTimer = 32000; + } else uiVampiricTouchTimer -= diff; + + if (uiSleepTimer < diff) + { + DoScriptText(RAND(SAY_SLEEP_1,SAY_SLEEP_2), me); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SLEEP); + uiSleepTimer = urand(15000,20000); + } else uiSleepTimer -= diff; + + DoMeleeAttackIfReady(); + break; + case OUTRO: + if (uiOutroTimer < diff) + { + switch(uiOutroStep) + { + case 1: + DoScriptText(SAY_ESCAPE_SPEECH_1, me); + me->GetMotionMaster()->MoveTargetedHome(); + ++uiOutroStep; + uiOutroTimer = 8000; + break; + case 2: + me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0); + me->HandleEmoteCommand(29); + DoScriptText(SAY_ESCAPE_SPEECH_2, me); + ++uiOutroStep; + uiOutroTimer = 9000; + break; + case 3: + DoScriptText(SAY_OUTRO, me); + ++uiOutroStep; + uiOutroTimer = 16000; + break; + case 4: + me->HandleEmoteCommand(33); + ++uiOutroStep; + uiOutroTimer = 500; + break; + case 5: + me->SetVisibility(VISIBILITY_OFF); + me->Kill(me); + break; + + } + } else uiOutroTimer -= diff; + break; + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_MAL_GANIS_EVENT, DONE); + + // give achievement credit to players. criteria use spell 58630 which doesn't exist. + if (pInstance) + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 58630); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } +}; + +CreatureAI* GetAI_boss_mal_ganis(Creature* pCreature) +{ + return new boss_mal_ganisAI (pCreature); +} + +void AddSC_boss_mal_ganis() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_mal_ganis"; + newscript->GetAI = &GetAI_boss_mal_ganis; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp new file mode 100644 index 00000000000..eba9733c745 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp @@ -0,0 +1,140 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss meathook +SDAuthor: Tartalo +SD%Complete: 100 +SDComment: It may need timer adjustment +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CONSTRICTING_CHAINS = 52696, //Encases the targets in chains, dealing 1800 Physical damage every 1 sec. and stunning the target for 5 sec. + H_SPELL_CONSTRICTING_CHAINS = 58823, + SPELL_DISEASE_EXPULSION = 52666, //Meathook belches out a cloud of disease, dealing 1710 to 1890 Nature damage and interrupting the spell casting of nearby enemy targets for 4 sec. + H_SPELL_DISEASE_EXPULSION = 58824, + SPELL_FRENZY = 58841 //Increases the caster's Physical damage by 10% for 30 sec. +}; + +enum Yells +{ + SAY_AGGRO = -1595026, + SAY_SLAY_1 = -1595027, + SAY_SLAY_2 = -1595028, + SAY_SLAY_3 = -1595029, + SAY_SPAWN = -1595030, + SAY_DEATH = -1595031 +}; + +struct boss_meathookAI : public ScriptedAI +{ + boss_meathookAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + DoScriptText(SAY_SPAWN,me); + } + + uint32 uiChainTimer; + uint32 uiDiseaseTimer; + uint32 uiFrenzyTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiChainTimer = urand(12000,17000); //seen on video 13, 17, 15, 12, 16 + uiDiseaseTimer = urand(2000,4000); //approx 3s + uiFrenzyTimer = urand(21000,26000); //made it up + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiDiseaseTimer <= diff) + { + DoCastAOE(SPELL_DISEASE_EXPULSION); + uiDiseaseTimer = urand(1500,4000); + } else uiDiseaseTimer -= diff; + + if (uiFrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + uiFrenzyTimer = urand(21000,26000); + } else uiFrenzyTimer -= diff; + + if (uiChainTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CONSTRICTING_CHAINS); //anyone but the tank + uiChainTimer = urand(2000,4000); + } else uiChainTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_meathook(Creature* pCreature) +{ + return new boss_meathookAI (pCreature); +} + +void AddSC_boss_meathook() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_meathook"; + newscript->GetAI = &GetAI_boss_meathook; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp new file mode 100644 index 00000000000..da1c8098517 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp @@ -0,0 +1,170 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss salramm +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_salramm' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CURSE_OF_TWISTED_FLESH = 58845, + SPELL_EXPLODE_GHOUL = 52480, + H_SPELL_EXPLODE_GHOUL = 58825, + SPELL_SHADOW_BOLT = 57725, + H_SPELL_SHADOW_BOLT = 58828, + SPELL_STEAL_FLESH = 52708, + SPELL_SUMMON_GHOULS = 52451 +}; + +enum Yells +{ + SAY_AGGRO = -1595032, + SAY_SPAWN = -1595033, + SAY_SLAY_1 = -1595034, + SAY_SLAY_2 = -1595035, + SAY_SLAY_3 = -1595036, + SAY_DEATH = -1595037, + SAY_EXPLODE_GHOUL_1 = -1595038, + SAY_EXPLODE_GHOUL_2 = -1595039, + SAY_STEAL_FLESH_1 = -1595040, + SAY_STEAL_FLESH_2 = -1595041, + SAY_STEAL_FLESH_3 = -1595042, + SAY_SUMMON_GHOULS_1 = -1595043, + SAY_SUMMON_GHOULS_2 = -1595044 +}; + +struct boss_salrammAI : public ScriptedAI +{ + boss_salrammAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + DoScriptText(SAY_SPAWN,me); + } + + uint32 uiCurseFleshTimer; + uint32 uiExplodeGhoulTimer; + uint32 uiShadowBoltTimer; + uint32 uiStealFleshTimer; + uint32 uiSummonGhoulsTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiCurseFleshTimer = 30000; //30s DBM + uiExplodeGhoulTimer = urand(25000,28000); //approx 6 sec after summon ghouls + uiShadowBoltTimer = urand(8000,12000); // approx 10s + uiStealFleshTimer = 12345; + uiSummonGhoulsTimer = urand(19000,24000); //on a video approx 24s after aggro + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Curse of twisted flesh timer + if (uiCurseFleshTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSE_OF_TWISTED_FLESH); + uiCurseFleshTimer = 37000; + } else uiCurseFleshTimer -= diff; + + //Shadow bolt timer + if (uiShadowBoltTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + uiShadowBoltTimer = urand(8000,12000); + } else uiShadowBoltTimer -= diff; + + //Steal Flesh timer + if (uiStealFleshTimer <= diff) + { + DoScriptText(RAND(SAY_STEAL_FLESH_1,SAY_STEAL_FLESH_2,SAY_STEAL_FLESH_3), me); + if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(random_pTarget, SPELL_STEAL_FLESH); + uiStealFleshTimer = 10000; + } else uiStealFleshTimer -= diff; + + //Summon ghouls timer + if (uiSummonGhoulsTimer <= diff) + { + DoScriptText(RAND(SAY_SUMMON_GHOULS_1,SAY_SUMMON_GHOULS_2), me); + if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(random_pTarget, SPELL_SUMMON_GHOULS); + uiSummonGhoulsTimer = 10000; + } else uiSummonGhoulsTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_salramm(Creature* pCreature) +{ + return new boss_salrammAI (pCreature); +} + +void AddSC_boss_salramm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_salramm"; + newscript->GetAI = &GetAI_boss_salramm; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp new file mode 100644 index 00000000000..faaed2eb6db --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp @@ -0,0 +1,1210 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" +#include "ScriptedEscortAI.h" + +enum Says +{ + //First Act - Uther and Jaina Dialog + SAY_PHASE101 = -1595070, //Arthas + SAY_PHASE102 = -1595071, //Uther + SAY_PHASE103 = -1595072, //Arthas + SAY_PHASE104 = -1595073, //Arthas + SAY_PHASE105 = -1595074, //Uther + SAY_PHASE106 = -1595075, //Arthas + SAY_PHASE107 = -1595076, //Uther + SAY_PHASE108 = -1595077, //Arthas + SAY_PHASE109 = -1595078, //Arthas + SAY_PHASE110 = -1595079, //Uther + SAY_PHASE111 = -1595080, //Arthas + SAY_PHASE112 = -1595081, //Uther + SAY_PHASE113 = -1595082, //Jaina + SAY_PHASE114 = -1595083, //Arthas + SAY_PHASE115 = -1595084, //Uther + SAY_PHASE116 = -1595085, //Arthas + SAY_PHASE117 = -1595086, //Jaina + SAY_PHASE118 = -1595087, //Arthas + //Second Act - City Streets + SAY_PHASE201 = -1595088, //Arthas + SAY_PHASE202 = -1595089, //Cityman + SAY_PHASE203 = -1595090, //Arthas + SAY_PHASE204 = -1595091, //Crazyman + SAY_PHASE205 = -1595092, //Arthas + SAY_PHASE206 = -1595009, //Malganis + SAY_PHASE207 = -1595010, //Malganis + SAY_PHASE208 = -1595093, //Arthas + SAY_PHASE209 = -1595094, //Arthas + SAY_PHASE210 = -1595095, //Arthas + //Third Act - Town Hall + SAY_PHASE301 = -1595096, //Arthas + SAY_PHASE302 = -1595097, //Drakonian + SAY_PHASE303 = -1595098, //Arthas + SAY_PHASE304 = -1595099, //Arthas + SAY_PHASE305 = -1595100, //Drakonian + SAY_PHASE306 = -1595101, //Arthas + SAY_PHASE307 = -1595102, //Arthas + SAY_PHASE308 = -1595103, //Arthas + SAY_PHASE309 = -1595104, //Arthas + SAY_PHASE310 = -1595105, //Arthas + SAY_PHASE311 = -1595106, //Arthas + SAY_PHASE312 = -1595107, //Arthas + SAY_PHASE313 = -1595108, //Arthas + SAY_PHASE314 = -1595000, //Epoch + SAY_PHASE315 = -1595109, //Arthas + //Fourth Act - Fire Corridor + SAY_PHASE401 = -1595110, //Arthas + SAY_PHASE402 = -1595111, //Arthas + SAY_PHASE403 = -1595112, //Arthas + SAY_PHASE404 = -1595113, //Arthas + SAY_PHASE405 = -1595114, //Arthas + SAY_PHASE406 = -1595115, //Arthas + SAY_PHASE407 = -1595116, //Arthas + //Fifth Act - Mal'Ganis Fight + SAY_PHASE501 = -1595117, //Arthas + SAY_PHASE502 = -1595118, //Arthas + SAY_PHASE503 = -1595119, //Arthas + SAY_PHASE504 = -1595120, //Arthas +}; + +enum NPCs +{ + NPC_INFINITE_ADVERSARY = 27742, + NPC_INFINITE_HUNTER = 27743, + NPC_INFINITE_AGENT = 27744, + NPC_TIME_RIFT = 28409, + NPC_ZOMBIE = 27737, + NPC_GHOUL = 28249, + NPC_NECROMANCER = 28200, + NPC_STALKER = 28199, + NPC_FIEND = 27734, + NPC_GOLEM = 28201, + NPC_EGHOUL = 27729, + NPC_CONSTRUCT = 27736, + + NPC_INVIS_TARGET = 20562, + + NPC_KNIGHT_ESCORT = 27745, + NPC_PRIEST_ESCORT = 27747, + NPC_CITY_MAN = 28167, + NPC_CITY_MAN2 = 28169, + NPC_CITY_MAN3 = 31126, + NPC_CITY_MAN4 = 31127, +}; + +enum Spells +{ + SPELL_FEAR = 39176, + SPELL_ARTHAS_AURA = 52442, + SPELL_EXORCISM_N = 52445, + SPELL_EXORCISM_H = 58822, + SPELL_HOLY_LIGHT = 52444, +}; + +enum GossipMenuArthas +{ + GOSSIP_MENU_ARTHAS_1 = 100001, + GOSSIP_MENU_ARTHAS_2 = 100002, + GOSSIP_MENU_ARTHAS_3 = 100003, + GOSSIP_MENU_ARTHAS_4 = 100004, + GOSSIP_MENU_ARTHAS_5 = 100005 +}; + +enum +{ + ENCOUNTER_WAVES_NUMBER = 8, + ENCOUNTER_WAVES_MAX_SPAWNS = 5, + ENCOUNTER_DRACONIAN_NUMBER = 4, + ENCOUNTER_CHRONO_SPAWNS = 19 +}; + +// Locations for necromancers and add to spawn +float WavesLocations[ENCOUNTER_WAVES_NUMBER][ENCOUNTER_WAVES_MAX_SPAWNS][5]= +{ + { + {NPC_ZOMBIE, 2164.698975, 1255.392944, 135.040878, 0.490202}, + {NPC_ZOMBIE, 2183.501465, 1263.079102, 134.859055, 3.169981}, + {NPC_GHOUL, 2177.512939, 1247.313843, 135.846695, 1.696574}, + {NPC_GHOUL, 2171.991943, 1246.615845, 135.745026, 1.696574}, + {0, 0, 0, 0, 0} + }, + { + {NPC_GHOUL, 2254.434326, 1163.427612, 138.055038, 2.077358}, + {NPC_GHOUL, 2254.703613, 1158.867798, 138.212234, 2.345532}, + {NPC_GHOUL, 2257.615723, 1162.310913, 138.091202, 2.077358}, + {NPC_NECROMANCER, 2258.258057, 1157.250732, 138.272873, 2.387766}, + {0, 0, 0, 0, 0} + }, + { + {NPC_STALKER, 2348.120117, 1202.302490, 130.491104, 4.698538}, + {NPC_GHOUL, 2352.863525, 1207.819092, 130.424271, 4.949865}, + {NPC_GHOUL, 2343.593750, 1207.915039, 130.781311, 4.321547}, + {NPC_NECROMANCER, 2348.257324, 1212.202515, 130.670135, 4.450352}, + {0, 0, 0, 0, 0} + }, + { + {NPC_STALKER, 2139.825195, 1356.277100, 132.199615, 5.820131}, + {NPC_GHOUL, 2137.073486, 1362.464844, 132.271637, 5.820131}, + {NPC_GHOUL, 2134.075684, 1354.148071, 131.885864, 5.820131}, + {NPC_NECROMANCER, 2133.302246, 1358.907837, 132.037689, 5.820131}, + {0, 0, 0, 0, 0} + }, + { + {NPC_NECROMANCER, 2264.013428, 1174.055908, 138.093094, 2.860481}, + {NPC_GHOUL, 2264.207764, 1170.892700, 138.034973, 2.860481}, + {NPC_GHOUL, 2266.948975, 1176.898926, 137.976929, 2.860481}, + {NPC_STALKER, 2269.215576, 1170.109253, 137.742691, 2.860481}, + {NPC_FIEND, 2273.106689, 1176.101074, 137.880508, 2.860481} + }, + { + {NPC_GOLEM, 2349.701660, 1188.436646, 130.428864, 3.908642}, + {NPC_GHOUL, 2349.909180, 1194.582642, 130.417816, 3.577001}, + {NPC_EGHOUL, 2354.662598, 1185.692017, 130.552032, 3.577001}, + {NPC_EGHOUL, 2354.716797, 1191.614380, 130.539810, 3.577001}, + {0, 0, 0, 0, 0} + }, + { + {NPC_CONSTRUCT, 2145.212891, 1355.288086, 132.288773, 6.004838}, + {NPC_NECROMANCER, 2137.078613, 1357.612671, 132.173340, 6.004838}, + {NPC_EGHOUL, 2139.402100, 1352.541626, 132.127518, 5.812850}, + {NPC_EGHOUL, 2142.408447, 1360.760620, 132.321564, 5.812850}, + {0, 0, 0, 0, 0} + }, + { + {NPC_GHOUL, 2172.686279, 1259.618164, 134.391754, 1.865499}, + {NPC_FIEND, 2177.649170, 1256.061157, 135.096512, 1.849572}, + {NPC_CONSTRUCT, 2170.782959, 1253.594849, 134.973022, 1.849572}, + {NPC_NECROMANCER, 2175.595703, 1249.041992, 135.603531, 1.849572}, + {0, 0, 0, 0, 0} + } +}; + +// Locations for rifts to spawn and draconians to go +float RiftAndSpawnsLocations[ENCOUNTER_CHRONO_SPAWNS][5]= +{ + {NPC_TIME_RIFT, 2431.790039, 1190.670044, 148.076004, 0.187923}, + {NPC_INFINITE_ADVERSARY, 2433.857910, 1185.612061, 148.075974, 4.566168}, + {NPC_INFINITE_ADVERSARY, 2437.577881, 1188.241089, 148.075974, 0.196999}, + {NPC_INFINITE_AGENT, 2437.165527, 1192.294922, 148.075974, 0.169247}, + {NPC_INFINITE_HUNTER, 2434.989990, 1197.679565, 148.075974, 0.715971}, + {NPC_TIME_RIFT, 2403.954834, 1178.815430, 148.075943, 4.966126}, + {NPC_INFINITE_AGENT, 2403.676758, 1171.495850, 148.075607, 4.902797}, + {NPC_INFINITE_HUNTER, 2407.691162, 1172.162720, 148.075607, 4.963010}, + {NPC_TIME_RIFT, 2414.217041, 1133.446167, 148.076050, 1.706972}, + {NPC_INFINITE_ADVERSARY, 2416.024658, 1139.456177, 148.076431, 1.752129}, + {NPC_INFINITE_HUNTER, 2410.866699, 1139.680542, 148.076431, 1.752129}, + {NPC_TIME_RIFT, 2433.081543, 1099.869751, 148.076157, 1.809509}, + {NPC_INFINITE_ADVERSARY, 2426.947998, 1107.471680, 148.076019, 1.877580}, + {NPC_INFINITE_HUNTER, 2432.944580, 1108.896362, 148.208160, 2.199241}, + {NPC_TIME_RIFT, 2444.077637, 1114.366089, 148.076157, 3.049565}, + {NPC_INFINITE_ADVERSARY, 2438.190674, 1118.368164, 148.076172, 3.139232}, + {NPC_INFINITE_AGENT, 2435.861328, 1113.402954, 148.169327, 2.390271}, + {NPC_TIME_RIFT, 2463.131592, 1115.391724, 152.473129, 3.409651}, + {NPC_EPOCH, 2451.809326, 1112.901245, 149.220459, 3.363617} +}; + +struct npc_arthasAI : public npc_escortAI +{ + npc_arthasAI(Creature *pCreature) : npc_escortAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + + bool bStepping; + uint32 uiStep; + uint32 uiPhaseTimer; + uint32 uiGossipStep; + uint32 uiPlayerFaction; + uint32 uiBossEvent; + uint32 uiWave; + + uint64 uiUtherGUID; + uint64 uiJainaGUID; + uint64 uiCitymenGUID[2]; + uint64 uiWaveGUID[ENCOUNTER_WAVES_MAX_SPAWNS]; + uint64 uiInfiniteDraconianGUID[ENCOUNTER_DRACONIAN_NUMBER]; + uint64 uiStalkerGUID; + + uint64 uiBossGUID; //uiMeathookGUID || uiSalrammGUID + uint64 uiEpochGUID; + uint64 uiMalganisGUID; + uint64 uiInfiniteGUID; + + uint32 uiExorcismTimer; + + void Reset() + { + uiUtherGUID = 0; + uiJainaGUID = 0; + + for (uint8 i = 0; i < 2; ++i) + uiCitymenGUID[i] = 0; + + for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + uiWaveGUID[i] = 0; + + for (uint8 i = 0; i < ENCOUNTER_DRACONIAN_NUMBER; ++i) + uiInfiniteDraconianGUID[i] = 0; + + uiStalkerGUID = 0; + uiBossGUID = 0; + uiEpochGUID = 0; + uiMalganisGUID = 0; + uiInfiniteGUID = 0; + + if (pInstance) { + pInstance->SetData(DATA_ARTHAS_EVENT, NOT_STARTED); + switch(pInstance->GetData(DATA_ARTHAS_EVENT)) + { + case NOT_STARTED: + bStepping = true; + uiStep = 0; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + uiBossEvent = DATA_MEATHOOK_EVENT; + uiGossipStep = 0; + break; + } + uiPhaseTimer = 1000; + uiExorcismTimer = 7300; + uiWave = 0; + } + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_ARTHAS_AURA); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ARTHAS_EVENT, FAIL); + } + + void SpawnTimeRift(uint32 timeRiftID, uint64* guidVector) + { + me->SummonCreature((uint32)RiftAndSpawnsLocations[timeRiftID][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_DESPAWN,11000); + + for (uint32 i = timeRiftID+1; i < ENCOUNTER_CHRONO_SPAWNS; ++i) + { + if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_TIME_RIFT) break; + if (Creature* pTemp = me->SummonCreature((uint32)RiftAndSpawnsLocations[i][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + guidVector[i-timeRiftID-1] = pTemp->GetGUID(); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pTemp->SetReactState(REACT_PASSIVE); + pTemp->GetMotionMaster()->MovePoint(0, RiftAndSpawnsLocations[i][1],RiftAndSpawnsLocations[i][2],RiftAndSpawnsLocations[i][3]); + if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_EPOCH) + uiEpochGUID = pTemp->GetGUID(); + } + } + } + + void SpawnWaveGroup(uint32 waveID, uint64* guidVector) + { + for (uint32 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + { + if ((uint32)WavesLocations[waveID][i][0] == 0) break; + if (Creature* pTemp = me->SummonCreature((uint32)WavesLocations[waveID][i][0],WavesLocations[waveID][i][1],WavesLocations[waveID][i][2],WavesLocations[waveID][i][3],WavesLocations[waveID][i][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + guidVector[i] = pTemp->GetGUID(); + } + } + } + + void SetHoldState(bool bOnHold) + { + SetEscortPaused(bOnHold); + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhaseTimer = uiTimer; + ++uiStep; + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 0: + case 1: + case 3: + case 9: + case 10: + case 11: + case 22: + case 23: + case 26: + case 55: + case 56: + SetHoldState(true); + bStepping = true; + break; + case 7: + if (Unit* pCityman0 = me->SummonCreature(NPC_CITY_MAN,2091.977f,1275.021f,140.757f,0.558f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) + uiCitymenGUID[0] = pCityman0->GetGUID(); + if (Unit* pCityman1 = me->SummonCreature(NPC_CITY_MAN2,2093.514f,1275.842f,140.408f,3.801f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) + uiCitymenGUID[1] = pCityman1->GetGUID(); + break; + case 8: + uiGossipStep = 1; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + case 12: + SetRun(true); + DoScriptText(SAY_PHASE210, me); + if (Unit* pDisguised0 = me->SummonCreature(NPC_CITY_MAN3,2398.14f,1207.81f,134.04f,5.155249f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[0] = pDisguised0->GetGUID(); + if (Unit* pDisguised1 = me->SummonCreature(NPC_CITY_MAN4,2403.22f,1205.54f,134.04f,3.311264f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[1] = pDisguised1->GetGUID(); + + if (Unit* pDisguised2 = me->SummonCreature(NPC_CITY_MAN,2400.82f,1201.69f,134.01f,1.534082f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[2] = pDisguised2->GetGUID(); + pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); + pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[0]); + pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); + } + } + } + break; + case 20: + uiGossipStep = 2; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetRun(false); + SetHoldState(true); + break; + case 21: + DoScriptText(SAY_PHASE301, me); + break; + case 25: + SetRun(false); + SpawnTimeRift(0,&uiInfiniteDraconianGUID[0]); + DoScriptText(SAY_PHASE307,me); + break; + case 29: + SetRun(false); + SpawnTimeRift(5,&uiInfiniteDraconianGUID[0]); + SpawnTimeRift(8,&uiInfiniteDraconianGUID[2]); + DoScriptText(SAY_PHASE309,me); + SetHoldState(true); + bStepping = true; + break; + case 31: + SetRun(false); + SpawnTimeRift(11,&uiInfiniteDraconianGUID[0]); + SpawnTimeRift(14,&uiInfiniteDraconianGUID[2]); + DoScriptText(SAY_PHASE311,me); + SetHoldState(true); + bStepping = true; + break; + case 32: + DoScriptText(SAY_PHASE401,me); + break; + case 34: + DoScriptText(SAY_PHASE402,me); + break; + case 35: + DoScriptText(SAY_PHASE403,me); + break; + case 36: + if (pInstance) + { + GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SHKAF_GATE)); + pGate->SetGoState(GO_STATE_ACTIVE); + } + break; + case 45: + SetRun(true); + SetDespawnAtFar(false); + uiGossipStep = 4; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + case 47: + SetRun(false); + DoScriptText(SAY_PHASE405,me); + break; + case 48: + SetRun(true); + DoScriptText(SAY_PHASE406,me); + break; + case 53: + DoScriptText(SAY_PHASE407,me); + break; + case 54: + uiGossipStep = 5; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + } + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + DoMeleeAttackIfReady(); + + if (bStepping) + { + if (uiPhaseTimer <= diff) + { + switch(uiStep) + { + //After reset + case 0: + if (Unit* pJaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f)) + uiJainaGUID = pJaina->GetGUID(); + else if (Unit* pJaina = me->SummonCreature(NPC_JAINA,1895.48f,1292.66f,143.706f,0.023475f,TEMPSUMMON_DEAD_DESPAWN,180000)) + uiJainaGUID = pJaina->GetGUID(); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 0 + case 1: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + if (Unit* pUther = me->SummonCreature(NPC_UTHER,1794.357f,1272.183f,140.558f,1.37f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiUtherGUID = pUther->GetGUID(); + pUther->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pUther->GetMotionMaster()->MovePoint(0, 1897.018f, 1287.487f, 143.481f); + pUther->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiUtherGUID); + } + JumpToNextStep(17000); + break; + case 2: + DoScriptText(SAY_PHASE101, me); + JumpToNextStep(2000); + break; + case 3: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + { + DoScriptText(SAY_PHASE102, pUther); + } + JumpToNextStep(8000); + break; + case 4: + SetEscortPaused(false); + bStepping = false; + SetRun(false); + DoScriptText(SAY_PHASE103, me); + JumpToNextStep(0); + break; + //After waypoint 1 + case 5: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + pJaina->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + DoScriptText(SAY_PHASE104, me); + JumpToNextStep(10000); + break; + case 6: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE105, pUther); + JumpToNextStep(1000); + break; + case 7: + DoScriptText(SAY_PHASE106, me); + JumpToNextStep(4000); + break; + case 8: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE107, pUther); + JumpToNextStep(6000); + break; + case 9: + DoScriptText(SAY_PHASE108, me); + JumpToNextStep(4000); + break; + case 10: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE109, pUther); + JumpToNextStep(8000); + break; + case 11: + DoScriptText(SAY_PHASE110, me); + JumpToNextStep(4000); + break; + case 12: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE111, pUther); + JumpToNextStep(4000); + break; + case 13: + DoScriptText(SAY_PHASE112, me); + JumpToNextStep(11000); + break; + case 14: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + DoScriptText(SAY_PHASE113, pJaina); + JumpToNextStep(3000); + break; + case 15: + DoScriptText(SAY_PHASE114, me); + JumpToNextStep(9000); + break; + case 16: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE115, pUther); + JumpToNextStep(4000); + break; + case 17: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + { + pUther->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pUther->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); + } + JumpToNextStep(1000); + break; + case 18: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + { + me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); + pJaina->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pJaina->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); + } + JumpToNextStep(1000); + break; + case 19: + DoScriptText(SAY_PHASE116, me); + JumpToNextStep(1000); + break; + case 20: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + DoScriptText(SAY_PHASE117, pJaina); + JumpToNextStep(3000); + break; + case 21: + SetEscortPaused(false); + bStepping = false; + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After waypoint 3 + case 22: + DoScriptText(SAY_PHASE118, me); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); + JumpToNextStep(10000); + break; + case 23: + SetEscortPaused(false); + bStepping = false; + SetRun(true); + + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + pJaina->DisappearAndDie(); + + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + pUther->DisappearAndDie(); + + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After Gossip 1 (waypoint 8) + case 24: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2026.469f,1287.088f,143.596f,1.37f,TEMPSUMMON_TIMED_DESPAWN,14000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + JumpToNextStep(1000); + break; + case 25: + DoScriptText(SAY_PHASE201, me); + JumpToNextStep(12000); + break; + case 26: + SetEscortPaused(false); + bStepping = false; + SetRun(false); + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After waypoint 9 + case 27: + me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[0]); + if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) + { + pCityman->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + pCityman->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCityman->GetMotionMaster()->MovePoint(0, 2088.625f,1279.191f,140.743f); + } + JumpToNextStep(2000); + break; + case 28: + if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) + DoScriptText(SAY_PHASE202, pCityman); + JumpToNextStep(4000); + break; + case 29: + SetEscortPaused(false); + bStepping = false; + DoScriptText(SAY_PHASE203, me); + JumpToNextStep(0); + break; + //After waypoint 10 + case 30: + me->HandleEmoteCommand(37); + JumpToNextStep(1000); + break; + case 31: + SetEscortPaused(false); + bStepping = false; + if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) + { + DoScriptText(SAY_PHASE204, pCityman1); + pCityman1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pCityman0 = Unit::GetCreature(*me, uiCitymenGUID[0])) + pCityman0->Kill(pCityman0); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[1]); + } + JumpToNextStep(0); + break; + //After waypoint 11 + case 32: + me->HandleEmoteCommand(37); + JumpToNextStep(1000); + break; + case 33: + if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) + pCityman1->Kill(pCityman1); + JumpToNextStep(1000); + break; + case 34: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + DoScriptText(SAY_PHASE205, me); + JumpToNextStep(3000); + break; + case 35: + if (Unit* pStalkerM = me->SummonCreature(NPC_INVIS_TARGET,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + uiStalkerGUID = pStalkerM->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + JumpToNextStep(1000); + break; + case 36: + if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + if (Creature* pStalkerM = Unit::GetCreature(*me, uiStalkerGUID)) + pMalganis->CastSpell(pStalkerM,63793,false); + + uiMalganisGUID = pMalganis->GetGUID(); + DoScriptText(SAY_PHASE206, pMalganis); + pMalganis->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + pMalganis->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(11000); + break; + case 37: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + { + if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN, 100.0f)) + pZombie->UpdateEntry(NPC_ZOMBIE, 0); + else if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN2, 100.0f)) + pZombie->UpdateEntry(NPC_ZOMBIE, 0); + else //There's no one else to transform + uiStep++; + } + else + uiStep++; + uiPhaseTimer = 500; + break; + case 38: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + DoScriptText(SAY_PHASE207, pMalganis); + JumpToNextStep(17000); + break; + case 39: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + pMalganis->SetVisibility(VISIBILITY_OFF); + DoScriptText(SAY_PHASE208, me); + JumpToNextStep(7000); + break; + case 40: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + DoScriptText(SAY_PHASE209, me); + + uiBossEvent = DATA_MEATHOOK_EVENT; + if (pInstance) + pInstance->SetData(DATA_ARTHAS_EVENT, IN_PROGRESS); + + me->SetReactState(REACT_DEFENSIVE); + SetDespawnAtFar(false); + JumpToNextStep(5000); + break; + case 41: //Summon wave group + case 43: + case 45: + case 47: + case 51: + case 53: + case 55: + case 57: + if (pInstance->GetData(uiBossEvent) != DONE) + { + SpawnWaveGroup(uiWave, uiWaveGUID); + uiWave++; + } + JumpToNextStep(500); + break; + case 42: //Wait group to die + case 44: + case 46: + case 48: + case 52: + case 54: + case 56: + case 58: + if (pInstance->GetData(uiBossEvent) != DONE) + { + uint32 mobCounter = 0; + uint32 deadCounter = 0; + for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + { + if (uiWaveGUID[i] == 0) + break; + ++mobCounter; + Unit* pTemp = Unit::GetCreature(*me, uiWaveGUID[i]); + if (!pTemp || pTemp->isDead()) + ++deadCounter; + } + + if (mobCounter <= deadCounter) //If group is dead + JumpToNextStep(1000); + else + uiPhaseTimer = 1000; + } + else + JumpToNextStep(500); + break; + case 49: //Summon Boss + case 59: + if (pInstance->GetData(uiBossEvent) != DONE) + { + uint32 uiBossID = 0; + if (uiBossEvent == DATA_MEATHOOK_EVENT) + uiBossID = NPC_MEATHOOK; + else if (uiBossEvent == DATA_SALRAMM_EVENT) + uiBossID = NPC_SALRAMM; + + if (Unit* pBoss = me->SummonCreature(uiBossID,2232.19f,1331.933f,126.662f,3.15f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + uiBossGUID = pBoss->GetGUID(); + pBoss->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pBoss->GetMotionMaster()->MovePoint(0, 2194.110f,1332.00f,130.00f); + } + } + JumpToNextStep(30000); + break; + case 50: //Wait Boss death + case 60: + if (pInstance) + { + if (pInstance->GetData(uiBossEvent) == DONE) + { + JumpToNextStep(1000); + if (uiBossEvent == DATA_MEATHOOK_EVENT) + uiBossEvent = DATA_SALRAMM_EVENT; + else if (uiBossEvent == DATA_SALRAMM_EVENT) + { + SetHoldState(false); + bStepping = false; + uiBossEvent = DATA_EPOCH_EVENT; + } + } + else if (pInstance->GetData(uiBossEvent) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After Gossip 2 (waypoint 22) + case 61: + me->SetReactState(REACT_AGGRESSIVE); + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) + pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) + pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + JumpToNextStep(1000); + break; + case 62: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + DoScriptText(SAY_PHASE302, pDisguised0); + JumpToNextStep(7000); + break; + case 63: + DoScriptText(SAY_PHASE303, me); + SetHoldState(false); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 23 + case 64: + me->HandleEmoteCommand(54); + JumpToNextStep(1000); + break; + case 65: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + pDisguised0->HandleEmoteCommand(11); + JumpToNextStep(1000); + break; + case 66: + DoScriptText(SAY_PHASE304,me); + JumpToNextStep(2000); + break; + case 67: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + DoScriptText(SAY_PHASE305,pDisguised0); + JumpToNextStep(1000); + break; + case 68: + if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) + { + pDisguised2->UpdateEntry(NPC_INFINITE_HUNTER, 0); + //Make them unattackable + pDisguised2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised2->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 69: + if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) + { + pDisguised1->UpdateEntry(NPC_INFINITE_AGENT, 0); + //Make them unattackable + pDisguised1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised1->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 70: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + { + pDisguised0->UpdateEntry(NPC_INFINITE_ADVERSARY, 0); + //Make them unattackable + pDisguised0->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised0->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 71: + //After waypoint 26,29,31 + case 73: + case 75: + case 77: + //Make cratures attackable + for (uint32 i = 0; i< ENCOUNTER_DRACONIAN_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiInfiniteDraconianGUID[i])) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pTemp->SetReactState(REACT_AGGRESSIVE); + } + JumpToNextStep(5000); + break; + case 72: + case 74: + case 76: + if (me->isInCombat()) + uiPhaseTimer = 1000; + else + { + if (uiStep == 72) DoScriptText(SAY_PHASE308,me); + if (uiStep == 74) DoScriptText(SAY_PHASE308,me); + if (uiStep == 76) DoScriptText(SAY_PHASE310,me); + SetHoldState(false); + bStepping = false; + SetRun(true); + JumpToNextStep(2000); + } + break; + case 78: + if (me->isInCombat()) + uiPhaseTimer = 1000; + else + { + DoScriptText(SAY_PHASE312,me); + JumpToNextStep(5000); + } + break; + case 79: + DoScriptText(SAY_PHASE313,me); + JumpToNextStep(1000); + break; + case 80: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + { + SpawnTimeRift(17,&uiEpochGUID); + if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) + DoScriptText(SAY_PHASE314,pEpoch); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiEpochGUID); + } + JumpToNextStep(18000); + break; + case 81: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + DoScriptText(SAY_PHASE315, me); + JumpToNextStep(6000); + break; + case 82: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + { + if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) + { + //Make Epoch attackable + pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pEpoch->SetReactState(REACT_AGGRESSIVE); + } + + } + JumpToNextStep(1000); + break; + case 83: + if (pInstance) + { + if (pInstance->GetData(DATA_EPOCH_EVENT) == DONE) + { + uiGossipStep = 3; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + bStepping = false; + uiBossEvent = DATA_MAL_GANIS_EVENT; + JumpToNextStep(15000); + } + else if (pInstance->GetData(DATA_EPOCH_EVENT) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After Gossip 4 + case 84: + DoScriptText(SAY_PHASE404,me); + SetHoldState(false); + bStepping = false; + break; + //After Gossip 5 + case 85: + DoScriptText(SAY_PHASE501, me); + if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2296.665f,1502.362f,128.362f,4.961f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + uiMalganisGUID = pMalganis->GetGUID(); + pMalganis->SetReactState(REACT_PASSIVE); + } + if (pInstance) + { + GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAL_GANIS_GATE_1)); + pGate->SetGoState(GO_STATE_ACTIVE); + } + SetHoldState(false); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 55 + case 86: + DoScriptText(SAY_PHASE502, me); + JumpToNextStep(6000); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); + break; + case 87: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + { + pMalganis->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_6 | UNIT_FLAG_UNK_9 | UNIT_FLAG_UNK_15); + pMalganis->SetReactState(REACT_AGGRESSIVE); + } + JumpToNextStep(1000); + break; + case 88: + if (pInstance) + { + if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == DONE) + { + SetHoldState(false); + JumpToNextStep(1000); + } + else if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After waypoint 56 + case 89: + SetRun(true); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); + DoScriptText(SAY_PHASE503, me); + JumpToNextStep(7000); + break; + case 90: + if (pInstance) + { + pInstance->SetData(DATA_ARTHAS_EVENT, DONE); //Rewards: Achiev & Chest ;D + me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance->GetData64(DATA_MAL_GANIS_GATE_2)); //Look behind + } + DoScriptText(SAY_PHASE504, me); + bStepping = false; + break; + } + } else uiPhaseTimer -= diff; + } + + //Battling skills + if (!me->getVictim()) + return; + + if (uiExorcismTimer < diff) + { + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(target, SPELL_EXORCISM_N); + uiExorcismTimer = 7300; + } else uiExorcismTimer -= diff; + + if (HealthBelowPct(40)) + DoCast(me, SPELL_HOLY_LIGHT); + } +}; + +CreatureAI* GetAI_npc_arthas(Creature* pCreature) +{ + return new npc_arthasAI(pCreature); +} + +#define GOSSIP_ITEM_ARTHAS_0 "I'm ready to start Culling of Stratholme." +#define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready." +#define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness." +#define GOSSIP_ITEM_ARTHAS_3 "I'm ready." +#define GOSSIP_ITEM_ARTHAS_4 "For Lordaeron!" +#define GOSSIP_ITEM_ARTHAS_5 "I'm ready to battle the dreadlord, sire." + +bool GossipHello_npc_arthas(Player* pPlayer, Creature* pCreature) +{ + npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); + + if (pAI && pAI->bStepping == false) + { + switch (pAI->uiGossipStep) + { + case 0: //This one is a workaround since the very beggining of the script is wrong. + if (pPlayer->GetQuestStatus(13149) != QUEST_STATUS_COMPLETE) + return false; + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + break; + case 1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_1, pCreature->GetGUID()); + break; + case 2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_2, pCreature->GetGUID()); + break; + case 3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_3, pCreature->GetGUID()); + break; + case 4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_4, pCreature->GetGUID()); + break; + case 5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_5, pCreature->GetGUID()); + break; + default: + return false; + } + } + return true; +} + + +bool GossipSelect_npc_arthas(Player *pPlayer, Creature *pCreature, uint32 /*sender*/, uint32 action) +{ + npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); + + if (!pAI) + return false; + + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + pAI->Start(true,true,pPlayer->GetGUID(),0,false,false); + pAI->SetDespawnAtEnd(false); + pAI->bStepping = false; + pAI->uiStep = 1; + break; + case GOSSIP_ACTION_INFO_DEF+1: + pAI->bStepping = true; + pAI->uiStep = 24; + break; + case GOSSIP_ACTION_INFO_DEF+2: + pAI->SetHoldState(false); + pAI->bStepping = false; + pAI->uiStep = 61; + break; + case GOSSIP_ACTION_INFO_DEF+3: + pAI->SetHoldState(false); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pAI->bStepping = true; + pAI->uiStep = 84; + break; + case GOSSIP_ACTION_INFO_DEF+5: + pAI->bStepping = true; + pAI->uiStep = 85; + break; + } + pPlayer->CLOSE_GOSSIP_MENU(); + pAI->SetDespawnAtFar(true); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + return true; +} + +void AddSC_culling_of_stratholme() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_arthas"; + newscript->GetAI = &GetAI_npc_arthas; + newscript->pGossipHello = &GossipHello_npc_arthas; + newscript->pGossipSelect = &GossipSelect_npc_arthas; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h new file mode 100644 index 00000000000..4278ad46500 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h @@ -0,0 +1,68 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DEF_CULLING_OF_STRATHOLME_H +#define DEF_CULLING_OF_STRATHOLME_H + +enum Data +{ + DATA_MEATHOOK_EVENT, + DATA_SALRAMM_EVENT, + DATA_EPOCH_EVENT, + DATA_MAL_GANIS_EVENT, + DATA_INFINITE_EVENT, + DATA_ARTHAS_EVENT +}; + +enum Data64 +{ + DATA_ARTHAS, + DATA_MEATHOOK, + DATA_SALRAMM, + DATA_EPOCH, + DATA_MAL_GANIS, + DATA_INFINITE, + DATA_SHKAF_GATE, + DATA_MAL_GANIS_GATE_1, + DATA_MAL_GANIS_GATE_2, + DATA_EXIT_GATE, + DATA_MAL_GANIS_CHEST +}; + +enum Creatures +{ + NPC_MEATHOOK = 26529, + NPC_SALRAMM = 26530, + NPC_EPOCH = 26532, + NPC_MAL_GANIS = 26533, + NPC_INFINITE = 32273, + NPC_ARTHAS = 26499, + NPC_JAINA = 26497, + NPC_UTHER = 26528 +}; + +enum GameObjects +{ + GO_SHKAF_GATE = 188686, + GO_MALGANIS_GATE_1 = 187711, + GO_MALGANIS_GATE_2 = 187723, + GO_EXIT_GATE = 191788, + GO_MALGANIS_CHEST_N = 190663, + GO_MALGANIS_CHEST_H = 193597 +}; +#endif diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp new file mode 100644 index 00000000000..73742a1e748 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp @@ -0,0 +1,244 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +#define MAX_ENCOUNTER 5 + +/* Culling of Stratholme encounters: +0 - Meathook +1 - Salramm the Fleshcrafter +2 - Chrono-Lord Epoch +3 - Mal'Ganis +4 - Infinite Corruptor (Heroic only) +*/ + +struct instance_culling_of_stratholme : public ScriptedInstance +{ + instance_culling_of_stratholme(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiArthas; + uint64 uiMeathook; + uint64 uiSalramm; + uint64 uiEpoch; + uint64 uiMalGanis; + uint64 uiInfinite; + + uint64 uiShkafGate; + uint64 uiMalGanisGate1; + uint64 uiMalGanisGate2; + uint64 uiExitGate; + uint64 uiMalGanisChest; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_ARTHAS: + uiArthas = pCreature->GetGUID(); + break; + case NPC_MEATHOOK: + uiMeathook = pCreature->GetGUID(); + break; + case NPC_SALRAMM: + uiSalramm = pCreature->GetGUID(); + break; + case NPC_EPOCH: + uiEpoch = pCreature->GetGUID(); + break; + case NPC_MAL_GANIS: + uiMalGanis = pCreature->GetGUID(); + break; + case NPC_INFINITE: + uiInfinite = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_SHKAF_GATE: + uiShkafGate = pGo->GetGUID(); + break; + case GO_MALGANIS_GATE_1: + uiMalGanisGate1 = pGo->GetGUID(); + break; + case GO_MALGANIS_GATE_2: + uiMalGanisGate2 = pGo->GetGUID(); + break; + case GO_EXIT_GATE: + uiExitGate = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(uiExitGate,true); + break; + case GO_MALGANIS_CHEST_N: + case GO_MALGANIS_CHEST_H: + uiMalGanisChest = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MEATHOOK_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_SALRAMM_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_EPOCH_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_MAL_GANIS_EVENT: + m_auiEncounter[3] = data; + + switch(m_auiEncounter[3]) + { + case NOT_STARTED: + HandleGameObject(uiMalGanisGate2,true); + break; + case IN_PROGRESS: + HandleGameObject(uiMalGanisGate2,false); + break; + case DONE: + HandleGameObject(uiExitGate, true); + if (GameObject *pGo = instance->GetGameObject(uiMalGanisChest)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + } + break; + case DATA_INFINITE_EVENT: + m_auiEncounter[4] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_MEATHOOK_EVENT: return m_auiEncounter[0]; + case DATA_SALRAMM_EVENT: return m_auiEncounter[1]; + case DATA_EPOCH_EVENT: return m_auiEncounter[2]; + case DATA_MAL_GANIS_EVENT: return m_auiEncounter[3]; + case DATA_INFINITE_EVENT: return m_auiEncounter[4]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_ARTHAS: return uiArthas; + case DATA_MEATHOOK: return uiMeathook; + case DATA_SALRAMM: return uiSalramm; + case DATA_EPOCH: return uiEpoch; + case DATA_MAL_GANIS: return uiMalGanis; + case DATA_INFINITE: return uiInfinite; + case DATA_SHKAF_GATE: return uiShkafGate; + case DATA_MAL_GANIS_GATE_1: return uiMalGanisGate1; + case DATA_MAL_GANIS_GATE_2: return uiMalGanisGate2; + case DATA_EXIT_GATE: return uiExitGate; + case DATA_MAL_GANIS_CHEST: return uiMalGanisChest; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "C S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; + + if (dataHead1 == 'C' && dataHead2 == 'S') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap) +{ + return new instance_culling_of_stratholme(pMap); +} + +void AddSC_instance_culling_of_stratholme() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_culling_of_stratholme"; + newscript->GetInstanceData = &GetInstanceData_instance_culling_of_stratholme; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp new file mode 100644 index 00000000000..49cf7cd4433 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp @@ -0,0 +1,145 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Aeonus +SD%Complete: 80 +SDComment: Some spells not implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269012, + SAY_AGGRO = -1269013, + SAY_BANISH = -1269014, + SAY_SLAY1 = -1269015, + SAY_SLAY2 = -1269016, + SAY_DEATH = -1269017, + EMOTE_FRENZY = -1269018, + + SPELL_CLEAVE = 40504, + SPELL_TIME_STOP = 31422, + SPELL_ENRAGE = 37605, + SPELL_SAND_BREATH = 31473, + H_SPELL_SAND_BREATH = 39049 +}; + +struct boss_aeonusAI : public ScriptedAI +{ + boss_aeonusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SandBreath_Timer; + uint32 TimeStop_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + SandBreath_Timer = 15000+rand()%15000; + TimeStop_Timer = 10000+rand()%5000; + Frenzy_Timer = 30000+rand()%15000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_RIFT,DONE); + pInstance->SetData(TYPE_MEDIVH,DONE);//FIXME: later should be removed + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sand Breath + if (SandBreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SAND_BREATH); + SandBreath_Timer = 15000+rand()%10000; + } else SandBreath_Timer -= diff; + + //Time Stop + if (TimeStop_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIME_STOP); + TimeStop_Timer = 20000+rand()%15000; + } else TimeStop_Timer -= diff; + + //Frenzy + if (Frenzy_Timer <= diff) + { + DoScriptText(EMOTE_FRENZY, me); + DoCast(me, SPELL_ENRAGE); + Frenzy_Timer = 20000+rand()%15000; + } else Frenzy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_aeonus(Creature* pCreature) +{ + return new boss_aeonusAI (pCreature); +} + +void AddSC_boss_aeonus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_aeonus"; + newscript->GetAI = &GetAI_boss_aeonus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp new file mode 100644 index 00000000000..1f2b4a80612 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp @@ -0,0 +1,154 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Chrono_Lord_Deja +SD%Complete: 65 +SDComment: All abilities not implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269006, + SAY_AGGRO = -1269007, + SAY_BANISH = -1269008, + SAY_SLAY1 = -1269009, + SAY_SLAY2 = -1269010, + SAY_DEATH = -1269011, + + SPELL_ARCANE_BLAST = 31457, + H_SPELL_ARCANE_BLAST = 38538, + SPELL_ARCANE_DISCHARGE = 31472, + H_SPELL_ARCANE_DISCHARGE = 38539, + SPELL_TIME_LAPSE = 31467, + SPELL_ATTRACTION = 38540 //Not Implemented (Heroic mode) +}; + +struct boss_chrono_lord_dejaAI : public ScriptedAI +{ + boss_chrono_lord_dejaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 ArcaneBlast_Timer; + uint32 TimeLapse_Timer; + uint32 Attraction_Timer; + uint32 ArcaneDischarge_Timer; + + void Reset() + { + ArcaneBlast_Timer = 18000+rand()%5000; + TimeLapse_Timer = 10000+rand()%5000; + ArcaneDischarge_Timer = 20000+rand()%10000; + Attraction_Timer = 25000+rand()%10000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Arcane Blast + if (ArcaneBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BLAST); + ArcaneBlast_Timer = 15000+rand()%10000; + } else ArcaneBlast_Timer -= diff; + + //Arcane Discharge + if (ArcaneDischarge_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(pTarget, SPELL_ARCANE_DISCHARGE); + ArcaneDischarge_Timer = 20000+rand()%10000; + } else ArcaneDischarge_Timer -= diff; + + //Time Lapse + if (TimeLapse_Timer <= diff) + { + DoScriptText(SAY_BANISH, me); + DoCast(me, SPELL_TIME_LAPSE); + TimeLapse_Timer = 15000+rand()%10000; + } else TimeLapse_Timer -= diff; + + if (IsHeroic()) + { + if (Attraction_Timer <= diff) + { + DoCast(me, SPELL_ATTRACTION); + Attraction_Timer = 25000+rand()%10000; + } else Attraction_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_chrono_lord_deja(Creature* pCreature) +{ + return new boss_chrono_lord_dejaAI (pCreature); +} + +void AddSC_boss_chrono_lord_deja() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_chrono_lord_deja"; + newscript->GetAI = &GetAI_boss_chrono_lord_deja; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp new file mode 100644 index 00000000000..04b4b020ead --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Temporus +SD%Complete: 75 +SDComment: More abilities need to be implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269000, + SAY_AGGRO = -1269001, + SAY_BANISH = -1269002, + SAY_SLAY1 = -1269003, + SAY_SLAY2 = -1269004, + SAY_DEATH = -1269005, + + SPELL_HASTE = 31458, + SPELL_MORTAL_WOUND = 31464, + SPELL_WING_BUFFET = 31475, + H_SPELL_WING_BUFFET = 38593, + SPELL_REFLECT = 38592 //Not Implemented (Heroic mod) +}; + +struct boss_temporusAI : public ScriptedAI +{ + boss_temporusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Haste_Timer; + uint32 SpellReflection_Timer; + uint32 MortalWound_Timer; + uint32 WingBuffet_Timer; + + void Reset() + { + Haste_Timer = 15000+rand()%8000; + SpellReflection_Timer = 30000; + MortalWound_Timer = 8000; + WingBuffet_Timer = 25000+rand()%10000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Attack Haste + if (Haste_Timer <= diff) + { + DoCast(me, SPELL_HASTE); + Haste_Timer = 20000+rand()%5000; + } else Haste_Timer -= diff; + + //MortalWound_Timer + if (MortalWound_Timer <= diff) + { + DoCast(me, SPELL_MORTAL_WOUND); + MortalWound_Timer = 10000+rand()%10000; + } else MortalWound_Timer -= diff; + + //Wing ruffet + if (WingBuffet_Timer <= diff) + { + DoCast(me, SPELL_WING_BUFFET); + WingBuffet_Timer = 20000+rand()%10000; + } else WingBuffet_Timer -= diff; + + if (IsHeroic()) + { + if (SpellReflection_Timer <= diff) + { + DoCast(me, SPELL_REFLECT); + SpellReflection_Timer = 25000+rand()%10000; + } else SpellReflection_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_temporus(Creature* pCreature) +{ + return new boss_temporusAI (pCreature); +} + +void AddSC_boss_temporus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_temporus"; + newscript->GetAI = &GetAI_boss_temporus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp new file mode 100644 index 00000000000..b0432a9b57c --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp @@ -0,0 +1,404 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Dark_Portal +SD%Complete: 30 +SDComment: Misc NPC's and mobs for instance. Most here far from complete. +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +/* ContentData +npc_medivh_bm +npc_time_rift +npc_saat +EndContentData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +#define SAY_ENTER -1269020 //where does this belong? +#define SAY_INTRO -1269021 +#define SAY_WEAK75 -1269022 +#define SAY_WEAK50 -1269023 +#define SAY_WEAK25 -1269024 +#define SAY_DEATH -1269025 +#define SAY_WIN -1269026 +#define SAY_ORCS_ENTER -1269027 +#define SAY_ORCS_ANSWER -1269028 + +#define SPELL_CHANNEL 31556 +#define SPELL_PORTAL_RUNE 32570 //aura(portal on ground effect) + +#define SPELL_BLACK_CRYSTAL 32563 //aura +#define SPELL_PORTAL_CRYSTAL 32564 //summon + +#define SPELL_BANISH_PURPLE 32566 //aura +#define SPELL_BANISH_GREEN 32567 //aura + +#define SPELL_CORRUPT 31326 +#define SPELL_CORRUPT_AEONUS 37853 + +#define C_COUNCIL_ENFORCER 17023 + +struct npc_medivh_bmAI : public ScriptedAI +{ + npc_medivh_bmAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SpellCorrupt_Timer; + uint32 Check_Timer; + + bool Life75; + bool Life50; + bool Life25; + + void Reset() + { + SpellCorrupt_Timer = 0; + + if (!pInstance) + return; + + if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) + DoCast(me, SPELL_CHANNEL, true); + else if (me->HasAura(SPELL_CHANNEL)) + me->RemoveAura(SPELL_CHANNEL); + + DoCast(me, SPELL_PORTAL_RUNE, true); + } + + void MoveInLineOfSight(Unit *who) + { + if (!pInstance) + return; + + if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 10.0f)) + { + if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS || pInstance->GetData(TYPE_MEDIVH) == DONE) + return; + + DoScriptText(SAY_INTRO, me); + pInstance->SetData(TYPE_MEDIVH,IN_PROGRESS); + DoCast(me, SPELL_CHANNEL, false); + Check_Timer = 5000; + } + else if (who->GetTypeId() == TYPEID_UNIT && me->IsWithinDistInMap(who, 15.0f)) + { + if (pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) + return; + + uint32 entry = who->GetEntry(); + if (entry == C_ASSAS || entry == C_WHELP || entry == C_CHRON || entry == C_EXECU || entry == C_VANQU) + { + who->StopMoving(); + who->CastSpell(me,SPELL_CORRUPT,false); + } + else if (entry == C_AEONUS) + { + who->StopMoving(); + who->CastSpell(me,SPELL_CORRUPT_AEONUS,false); + } + } + } + + void AttackStart(Unit * /*who*/) + { + //if (pInstance && pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) + //return; + + //ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) {} + + void SpellHit(Unit* /*caster*/, const SpellEntry* spell) + { + if (SpellCorrupt_Timer) + return; + + if (spell->Id == SPELL_CORRUPT_AEONUS) + SpellCorrupt_Timer = 1000; + + if (spell->Id == SPELL_CORRUPT) + SpellCorrupt_Timer = 3000; + } + + void JustDied(Unit* Killer) + { + if (Killer->GetEntry() == me->GetEntry()) + return; + + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (SpellCorrupt_Timer) + { + if (SpellCorrupt_Timer <= diff) + { + pInstance->SetData(TYPE_MEDIVH,SPECIAL); + + if (me->HasAura(SPELL_CORRUPT_AEONUS)) + SpellCorrupt_Timer = 1000; + else if (me->HasAura(SPELL_CORRUPT)) + SpellCorrupt_Timer = 3000; + else + SpellCorrupt_Timer = 0; + } else SpellCorrupt_Timer -= diff; + } + + if (Check_Timer) + { + if (Check_Timer <= diff) + { + uint32 pct = pInstance->GetData(DATA_SHIELD); + + Check_Timer = 5000; + + if (Life25 && pct <= 25) + { + DoScriptText(SAY_WEAK25, me); + Life25 = false; + } + else if (Life50 && pct <= 50) + { + DoScriptText(SAY_WEAK50, me); + Life50 = false; + } + else if (Life75 && pct <= 75) + { + DoScriptText(SAY_WEAK75, me); + Life75 = false; + } + + //if we reach this it means event was running but at some point reset. + if (pInstance->GetData(TYPE_MEDIVH) == NOT_STARTED) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + me->Respawn(); + return; + } + + if (pInstance->GetData(TYPE_RIFT) == DONE) + { + DoScriptText(SAY_WIN, me); + Check_Timer = 0; + + if (me->HasAura(SPELL_CHANNEL)) + me->RemoveAura(SPELL_CHANNEL); + + //TODO: start the post-event here + pInstance->SetData(TYPE_MEDIVH,DONE); + } + } else Check_Timer -= diff; + } + + //if (!UpdateVictim()) + //return; + + //DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_medivh_bm(Creature* pCreature) +{ + return new npc_medivh_bmAI (pCreature); +} + +struct Wave +{ + uint32 PortalMob[4]; //spawns for portal waves (in order) +}; + +static Wave PortalWaves[]= +{ + {C_ASSAS, C_WHELP, C_CHRON, 0}, + {C_EXECU, C_CHRON, C_WHELP, C_ASSAS}, + {C_EXECU, C_VANQU, C_CHRON, C_ASSAS} +}; + +struct npc_time_riftAI : public ScriptedAI +{ + npc_time_riftAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 TimeRiftWave_Timer; + uint8 mRiftWaveCount; + uint8 mPortalCount; + uint8 mWaveId; + + void Reset() + { + + TimeRiftWave_Timer = 15000; + mRiftWaveCount = 0; + + if (!pInstance) + return; + + mPortalCount = pInstance->GetData(DATA_PORTAL_COUNT); + + if (mPortalCount < 6) + mWaveId = 0; + else if (mPortalCount > 12) + mWaveId = 2; + else mWaveId = 1; + + } + void EnterCombat(Unit * /*who*/) {} + + void DoSummonAtRift(uint32 creature_entry) + { + if (!creature_entry) + return; + + if (pInstance && pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) + { + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + return; + } + + Position pos; + me->GetRandomNearPosition(pos, 10.0f); + + //normalize Z-level if we can, if rift is not at ground level. + pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + + if (Unit *Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) + if (Unit *temp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_MEDIVH) : 0)) + Summon->AddThreat(temp,0.0f); + } + + void DoSelectSummon() + { + uint32 entry = 0; + + if ((mRiftWaveCount > 2 && mWaveId < 1) || mRiftWaveCount > 3) + mRiftWaveCount = 0; + + entry = PortalWaves[mWaveId].PortalMob[mRiftWaveCount]; + debug_log("TSCR: npc_time_rift: summoning wave Creature (Wave %u, Entry %u).",mRiftWaveCount,entry); + + ++mRiftWaveCount; + + if (entry == C_WHELP) + { + for (uint8 i = 0; i < 3; ++i) + DoSummonAtRift(entry); + } else DoSummonAtRift(entry); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (TimeRiftWave_Timer <= diff) + { + DoSelectSummon(); + TimeRiftWave_Timer = 15000; + } else TimeRiftWave_Timer -= diff; + + if (me->IsNonMeleeSpellCasted(false)) + return; + + debug_log("TSCR: npc_time_rift: not casting anylonger, i need to die."); + me->setDeathState(JUST_DIED); + + if (pInstance->GetData(TYPE_RIFT) == IN_PROGRESS) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } +}; + +CreatureAI* GetAI_npc_time_rift(Creature* pCreature) +{ + return new npc_time_riftAI (pCreature); +} + +#define SAY_SAAT_WELCOME -1269019 + +#define GOSSIP_ITEM_OBTAIN "[PH] Obtain Chrono-Beacon" +#define SPELL_CHRONO_BEACON 34975 +#define ITEM_CHRONO_BEACON 24289 + +bool GossipHello_npc_saat(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(10000, pCreature->GetGUID()); + return true; + } + else if (pPlayer->GetQuestRewardStatus(QUEST_OPENING_PORTAL) && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(10001, pCreature->GetGUID()); + return true; + } + + pPlayer->SEND_GOSSIP_MENU(10002, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_saat(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer,SPELL_CHRONO_BEACON,false); + } + return true; +} + +void AddSC_dark_portal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_medivh_bm"; + newscript->GetAI = &GetAI_npc_medivh_bm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_time_rift"; + newscript->GetAI = &GetAI_npc_time_rift; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_saat"; + newscript->pGossipHello = &GossipHello_npc_saat; + newscript->pGossipSelect = &GossipSelect_npc_saat; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h new file mode 100644 index 00000000000..7bfd8c917d7 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_DARKPORTAL_H +#define DEF_DARKPORTAL_H + +#define TYPE_MEDIVH 1 +#define TYPE_RIFT 2 + +#define DATA_MEDIVH 10 +#define DATA_PORTAL_COUNT 11 +#define DATA_SHIELD 12 + +#define WORLD_STATE_BM 2541 +#define WORLD_STATE_BM_SHIELD 2540 +#define WORLD_STATE_BM_RIFT 2784 + +#define QUEST_OPENING_PORTAL 10297 +#define QUEST_MASTER_TOUCH 9836 + +#define C_TIME_KEEPER 17918 +#define C_RKEEP 21104 +#define C_RLORD 17839 +#define C_DEJA 17879 +#define C_TEMPO 17880 +#define C_AEONUS 17881 +#define C_ASSAS 17835 +#define C_WHELP 21818 +#define C_CHRON 17892 +#define C_EXECU 18994 +#define C_VANQU 18995 + +#endif + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp new file mode 100644 index 00000000000..d1280230808 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp @@ -0,0 +1,346 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Dark_Portal +SD%Complete: 50 +SDComment: Quest support: 9836, 10297. Currently in progress. +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +#define MAX_ENCOUNTER 2 + +#define C_MEDIVH 15608 +#define C_TIME_RIFT 17838 + +#define SPELL_RIFT_CHANNEL 31387 + +#define RIFT_BOSS 1 + +inline uint32 RandRiftBoss() { return ((rand()%2) ? C_RKEEP : C_RLORD); } + +float PortalLocation[4][4]= +{ + {-2041.06, 7042.08, 29.99, 1.30}, + {-1968.18, 7042.11, 21.93, 2.12}, + {-1885.82, 7107.36, 22.32, 3.07}, + {-1928.11, 7175.95, 22.11, 3.44} +}; + +struct Wave +{ + uint32 PortalBoss; //protector of current portal + uint32 NextPortalTime; //time to next portal, or 0 if portal boss need to be killed +}; + +static Wave RiftWaves[]= +{ + {RIFT_BOSS, 0}, + {C_DEJA, 0}, + {RIFT_BOSS, 120000}, + {C_TEMPO, 140000}, + {RIFT_BOSS, 120000}, + {C_AEONUS, 0} +}; + +struct instance_dark_portal : public ScriptedInstance +{ + instance_dark_portal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint32 mRiftPortalCount; + uint32 mShieldPercent; + uint8 mRiftWaveCount; + uint8 mRiftWaveId; + + uint32 NextPortal_Timer; + + uint64 MedivhGUID; + uint8 CurrentRiftId; + + void Initialize() + { + MedivhGUID = 0; + Clear(); + } + + void Clear() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + mRiftPortalCount = 0; + mShieldPercent = 100; + mRiftWaveCount = 0; + mRiftWaveId = 0; + + CurrentRiftId = 0; + + NextPortal_Timer = 0; + } + + void InitWorldState(bool Enable = true) + { + DoUpdateWorldState(WORLD_STATE_BM,Enable ? 1 : 0); + DoUpdateWorldState(WORLD_STATE_BM_SHIELD, 100); + DoUpdateWorldState(WORLD_STATE_BM_RIFT, 0); + } + + bool IsEncounterInProgress() + { + if (GetData(TYPE_MEDIVH) == IN_PROGRESS) + return true; + + return false; + } + + void OnPlayerEnter(Player* pPlayer) + { + if (GetData(TYPE_MEDIVH) == IN_PROGRESS) + return; + + pPlayer->SendUpdateWorldState(WORLD_STATE_BM,0); + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == C_MEDIVH) + MedivhGUID = pCreature->GetGUID(); + } + + //what other conditions to check? + bool CanProgressEvent() + { + if (instance->GetPlayers().isEmpty()) + return false; + + return true; + } + + uint8 GetRiftWaveId() + { + switch(mRiftPortalCount) + { + case 6: + mRiftWaveId = 2; + return 1; + case 12: + mRiftWaveId = 4; + return 3; + case 18: + return 5; + default: + return mRiftWaveId; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_MEDIVH: + if (data == SPECIAL && m_auiEncounter[0] == IN_PROGRESS) + { + --mShieldPercent; + + DoUpdateWorldState(WORLD_STATE_BM_SHIELD, mShieldPercent); + + if (!mShieldPercent) + { + if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) + { + if (pMedivh->isAlive()) + { + pMedivh->DealDamage(pMedivh, pMedivh->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_auiEncounter[0] = FAIL; + m_auiEncounter[1] = NOT_STARTED; + } + } + } + } + else + { + if (data == IN_PROGRESS) + { + debug_log("TSCR: Instance Dark Portal: Starting event."); + InitWorldState(); + m_auiEncounter[1] = IN_PROGRESS; + NextPortal_Timer = 15000; + } + + if (data == DONE) + { + //this may be completed further out in the post-event + debug_log("TSCR: Instance Dark Portal: Event completed."); + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL); + + if (pPlayer->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH); + } + } + } + } + + m_auiEncounter[0] = data; + } + break; + case TYPE_RIFT: + if (data == SPECIAL) + { + if (mRiftPortalCount < 7) + NextPortal_Timer = 5000; + } + else + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_MEDIVH: + return m_auiEncounter[0]; + case TYPE_RIFT: + return m_auiEncounter[1]; + case DATA_PORTAL_COUNT: + return mRiftPortalCount; + case DATA_SHIELD: + return mShieldPercent; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + if (data == DATA_MEDIVH) + return MedivhGUID; + + return 0; + } + + Creature* SummonedPortalBoss(Creature* me) + { + uint32 entry = RiftWaves[GetRiftWaveId()].PortalBoss; + + if (entry == RIFT_BOSS) + entry = RandRiftBoss(); + + debug_log("TSCR: Instance Dark Portal: Summoning rift boss entry %u.",entry); + + Position pos; + me->GetRandomNearPosition(pos, 10.0f); + + //normalize Z-level if we can, if rift is not at ground level. + pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + + if (Creature *summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) + return summon; + + debug_log("TSCR: Instance Dark Portal: What just happened there? No boss, no loot, no fun..."); + return NULL; + } + + void DoSpawnPortal() + { + if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) + { + uint8 tmp = urand(0,2); + + if (tmp >= CurrentRiftId) + ++tmp; + + debug_log("TSCR: Instance Dark Portal: Creating Time Rift at locationId %i (old locationId was %u).",tmp,CurrentRiftId); + + CurrentRiftId = tmp; + + Creature *pTemp = pMedivh->SummonCreature(C_TIME_RIFT, + PortalLocation[tmp][0],PortalLocation[tmp][1],PortalLocation[tmp][2],PortalLocation[tmp][3], + TEMPSUMMON_CORPSE_DESPAWN,0); + if (pTemp) + { + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (Creature *pBoss = SummonedPortalBoss(pTemp)) + { + if (pBoss->GetEntry() == C_AEONUS) + pBoss->AddThreat(pMedivh,0.0f); + else + { + pBoss->AddThreat(pTemp,0.0f); + pTemp->CastSpell(pBoss,SPELL_RIFT_CHANNEL,false); + } + } + } + } + } + + void Update(uint32 diff) + { + if (m_auiEncounter[1] != IN_PROGRESS) + return; + + //add delay timer? + if (!CanProgressEvent()) + { + Clear(); + return; + } + + if (NextPortal_Timer) + { + if (NextPortal_Timer <= diff) + { + ++mRiftPortalCount; + + DoUpdateWorldState(WORLD_STATE_BM_RIFT, mRiftPortalCount); + + DoSpawnPortal(); + NextPortal_Timer = RiftWaves[GetRiftWaveId()].NextPortalTime; + } else NextPortal_Timer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_dark_portal(Map* pMap) +{ + return new instance_dark_portal(pMap); +} + +void AddSC_instance_dark_portal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_dark_portal"; + newscript->GetInstanceData = &GetInstanceData_instance_dark_portal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp new file mode 100644 index 00000000000..14ce4a59b37 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp @@ -0,0 +1,309 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_CARRION_SWARM 31306 +#define SPELL_SLEEP 31298 +#define SPELL_VAMPIRIC_AURA 38196 +#define SPELL_INFERNO 31299 + +#define SAY_ONDEATH "The clock... is still... ticking." +#define SOUND_ONDEATH 10982 + +#define SAY_ONSLAY1 "Your hopes are lost!" +#define SAY_ONSLAY2 "Scream for me!" +#define SAY_ONSLAY3 "Pity, no time for a slow death!" +#define SOUND_ONSLAY1 10981 +#define SOUND_ONSLAY2 11038 +#define SOUND_ONSLAY3 11039 + +#define SAY_SWARM1 "The swarm is eager to feed!" +#define SAY_SWARM2 "Pestilence upon you!" +#define SOUND_SWARM1 10979 +#define SOUND_SWARM2 11037 + +#define SAY_SLEEP1 "You look tired..." +#define SAY_SLEEP2 "Sweet dreams..." +#define SOUND_SLEEP1 10978 +#define SOUND_SLEEP2 11545 + +#define SAY_INFERNO1 "Let fire rain from above!" +#define SAY_INFERNO2 "Earth and sky shall burn!" +#define SOUND_INFERNO1 10980 +#define SOUND_INFERNO2 11036 + +#define SAY_ONAGGRO "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!" +#define SOUND_ONAGGRO 10977 + +struct boss_anetheronAI : public hyjal_trashAI +{ + boss_anetheronAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_SLEEP); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) + { + TempSpell->EffectImplicitTargetA[0] = 1; + TempSpell->EffectImplicitTargetB[0] = 0; + } + } + + uint32 SwarmTimer; + uint32 SleepTimer; + uint32 AuraTimer; + uint32 InfernoTimer; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + SwarmTimer = 45000; + SleepTimer = 60000; + AuraTimer = 5000; + InfernoTimer = 45000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, 0); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 4896.08, -1576.35, 1333.65); + AddWaypoint(1, 4898.68, -1615.02, 1329.48); + AddWaypoint(2, 4907.12, -1667.08, 1321.00); + AddWaypoint(3, 4963.18, -1699.35, 1340.51); + AddWaypoint(4, 4989.16, -1716.67, 1335.74); + AddWaypoint(5, 5026.27, -1736.89, 1323.02); + AddWaypoint(6, 5037.77, -1770.56, 1324.36); + AddWaypoint(7, 5067.23, -1789.95, 1321.17); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (SwarmTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CARRION_SWARM); + + SwarmTimer = urand(45000,60000); + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_SWARM1); + me->MonsterYell(SAY_SWARM1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_SWARM2); + me->MonsterYell(SAY_SWARM2, LANG_UNIVERSAL, 0); + break; + } + } else SwarmTimer -= diff; + + if (SleepTimer <= diff) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + pTarget->CastSpell(pTarget,SPELL_SLEEP,true); + } + SleepTimer = 60000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_SLEEP1); + me->MonsterYell(SAY_SLEEP1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_SLEEP2); + me->MonsterYell(SAY_SLEEP2, LANG_UNIVERSAL, 0); + break; + } + } else SleepTimer -= diff; + if (AuraTimer <= diff) + { + DoCast(me, SPELL_VAMPIRIC_AURA, true); + AuraTimer = urand(10000,20000); + } else AuraTimer -= diff; + if (InfernoTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_INFERNO); + InfernoTimer = 45000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_INFERNO1); + me->MonsterYell(SAY_INFERNO1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_INFERNO2); + me->MonsterYell(SAY_INFERNO2, LANG_UNIVERSAL, 0); + break; + } + } else InfernoTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_anetheron(Creature* pCreature) +{ + return new boss_anetheronAI (pCreature); +} + +#define SPELL_IMMOLATION 31303 +#define SPELL_INFERNO_EFFECT 31302 + +struct mob_towering_infernalAI : public ScriptedAI +{ + mob_towering_infernalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + AnetheronGUID = pInstance->GetData64(DATA_ANETHERON); + } + + uint32 ImmolationTimer; + uint32 CheckTimer; + uint64 AnetheronGUID; + ScriptedInstance* pInstance; + + void Reset() + { + DoCast(me, SPELL_INFERNO_EFFECT); + ImmolationTimer = 5000; + CheckTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + } + + void JustDied(Unit * /*victim*/) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) + AttackStart(who); + } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (AnetheronGUID) + { + Creature* boss = Unit::GetCreature((*me),AnetheronGUID); + if (!boss || (boss && boss->isDead())) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + return; + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (ImmolationTimer <= diff) + { + DoCast(me, SPELL_IMMOLATION); + ImmolationTimer = 5000; + } else ImmolationTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_towering_infernal(Creature* pCreature) +{ + return new mob_towering_infernalAI (pCreature); +} + +void AddSC_boss_anetheron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_anetheron"; + newscript->GetAI = &GetAI_boss_anetheron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_towering_infernal"; + newscript->GetAI = &GetAI_mob_towering_infernal; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp new file mode 100644 index 00000000000..8e1fa378e07 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp @@ -0,0 +1,635 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Archimonde +SD%Complete: 85 +SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented. +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "SpellAuras.h" +#include "hyjal_trash.h" + +//text id -1534018 are the text used when previous events complete. Not part of this script. +#define SAY_AGGRO -1534019 +#define SAY_DOOMFIRE1 -1534020 +#define SAY_DOOMFIRE2 -1534021 +#define SAY_AIR_BURST1 -1534022 +#define SAY_AIR_BURST2 -1534023 +#define SAY_SLAY1 -1534024 +#define SAY_SLAY2 -1534025 +#define SAY_SLAY3 -1534026 +#define SAY_ENRAGE -1534027 +#define SAY_DEATH -1534028 +#define SAY_SOUL_CHARGE1 -1534029 +#define SAY_SOUL_CHARGE2 -1534030 + +#define SPELL_DENOUEMENT_WISP 32124 +#define SPELL_ANCIENT_SPARK 39349 +#define SPELL_PROTECTION_OF_ELUNE 38528 + +#define SPELL_DRAIN_WORLD_TREE 39140 +#define SPELL_DRAIN_WORLD_TREE_2 39141 + +#define SPELL_FINGER_OF_DEATH 31984 +#define SPELL_HAND_OF_DEATH 35354 +#define SPELL_AIR_BURST 32014 +#define SPELL_GRIP_OF_THE_LEGION 31972 +#define SPELL_DOOMFIRE_STRIKE 31903 //summons two creatures +#define SPELL_DOOMFIRE_SPAWN 32074 +#define SPELL_DOOMFIRE 31945 +#define SPELL_SOUL_CHARGE_YELLOW 32045 +#define SPELL_SOUL_CHARGE_GREEN 32051 +#define SPELL_SOUL_CHARGE_RED 32052 +#define SPELL_UNLEASH_SOUL_YELLOW 32054 +#define SPELL_UNLEASH_SOUL_GREEN 32057 +#define SPELL_UNLEASH_SOUL_RED 32053 +#define SPELL_FEAR 31970 + +#define CREATURE_ARCHIMONDE 17968 +#define CREATURE_DOOMFIRE 18095 +#define CREATURE_DOOMFIRE_SPIRIT 18104 +#define CREATURE_ANCIENT_WISP 17946 +#define CREATURE_CHANNEL_TARGET 22418 + +#define NORDRASSIL_X 5503.713 +#define NORDRASSIL_Y -3523.436 +#define NORDRASSIL_Z 1608.781 + +struct mob_ancient_wispAI : public ScriptedAI +{ + mob_ancient_wispAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + ArchimondeGUID = 0; + } + + ScriptedInstance* pInstance; + uint64 ArchimondeGUID; + uint32 CheckTimer; + + void Reset() + { + CheckTimer = 1000; + + if (pInstance) + ArchimondeGUID = pInstance->GetData64(DATA_ARCHIMONDE); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void EnterCombat(Unit* /*who*/) {} + + void DamageTaken(Unit* /*done_by*/, uint32 &damage) { damage = 0; } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (Unit* Archimonde = Unit::GetUnit((*me), ArchimondeGUID)) + { + if ((((Archimonde->GetHealth()*100) / Archimonde->GetMaxHealth()) < 2) || !Archimonde->isAlive()) + DoCast(me, SPELL_DENOUEMENT_WISP); + else + DoCast(Archimonde, SPELL_ANCIENT_SPARK); + } + CheckTimer = 1000; + } else CheckTimer -= diff; + } +}; + +/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will + MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */ +struct mob_doomfireAI : public ScriptedAI +{ + mob_doomfireAI(Creature* c) : ScriptedAI(c) {} + + void Reset() { } + + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit* /*who*/) {} + void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } +}; + +/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or + travels in random directions if pTarget cannot be found. */ +struct mob_doomfire_targettingAI : public ScriptedAI +{ + mob_doomfire_targettingAI(Creature* c) : ScriptedAI(c) {} + + uint64 TargetGUID; + uint32 ChangeTargetTimer; + + void Reset() + { + TargetGUID = 0; + ChangeTargetTimer = 5000; + } + + void MoveInLineOfSight(Unit* who) + { + //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0 + //when UpdateAI needs it, it will be forced to select randomPoint + if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER) + TargetGUID = who->GetGUID(); + } + + void EnterCombat(Unit* /*who*/) {} + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } + + void UpdateAI(const uint32 diff) + { + if (ChangeTargetTimer <= diff) + { + if (Unit *temp = Unit::GetUnit(*me,TargetGUID)) + { + me->GetMotionMaster()->MoveFollow(temp,0.0f,0.0f); + TargetGUID = 0; + } + else + { + Position pos; + me->GetRandomNearPosition(pos, 40); + me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ); + } + + ChangeTargetTimer = 5000; + } else ChangeTargetTimer -= diff; + } +}; + +/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers. + The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the + hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then + select a random pTarget and cast the spell on them. However, if someone IS in melee range, and this + is NOT the main tank (creature's victim), then we aggro that player and they become the new victim. + For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will + randomly select it's pTarget to follow and then we create the random movement making it unpredictable. */ + +struct boss_archimondeAI : public hyjal_trashAI +{ + boss_archimondeAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 DoomfireSpiritGUID; + uint64 WorldTreeGUID; + + uint32 DrainNordrassilTimer; + uint32 FearTimer; + uint32 AirBurstTimer; + uint32 GripOfTheLegionTimer; + uint32 DoomfireTimer; + uint32 SoulChargeTimer; + uint32 SoulChargeCount; + uint32 MeleeRangeCheckTimer; + uint32 HandOfDeathTimer; + uint32 SummonWispTimer; + uint32 WispCount; + uint32 EnrageTimer; + uint32 CheckDistanceTimer; + + bool Enraged; + bool BelowTenPercent; + bool HasProtected; + bool IsChanneling; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); + + DoomfireSpiritGUID = 0; + damageTaken = 0; + WorldTreeGUID = 0; + + DrainNordrassilTimer = 0; + FearTimer = 42000; + AirBurstTimer = 30000; + GripOfTheLegionTimer = urand(5000,25000); + DoomfireTimer = 20000; + SoulChargeTimer = urand(2000,30000); + SoulChargeCount = 0; + MeleeRangeCheckTimer = 15000; + HandOfDeathTimer = 2000; + WispCount = 0; // When ~30 wisps are summoned, Archimonde dies + EnrageTimer = 600000; // 10 minutes + CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage + SummonWispTimer = 0; + + Enraged = false; + BelowTenPercent = false; + HasProtected = false; + IsChanneling = false; + } + + void EnterCombat(Unit * /*who*/) + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * victim) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + + if (victim && (victim->GetTypeId() == TYPEID_PLAYER)) + GainSoulCharge(CAST_PLR(victim)); + } + + void GainSoulCharge(Player* victim) + { + switch(victim->getClass()) + { + case CLASS_PRIEST: + case CLASS_PALADIN: + case CLASS_WARLOCK: + victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); + break; + case CLASS_MAGE: + case CLASS_ROGUE: + case CLASS_WARRIOR: + victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); + break; + case CLASS_DRUID: + case CLASS_SHAMAN: + case CLASS_HUNTER: + victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); + break; + } + + SoulChargeTimer = urand(2000,30000); + ++SoulChargeCount; + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, DONE); + } + + bool CanUseFingerOfDeath() + { + // First we check if our current victim is in melee range or not. + Unit* victim = me->getVictim(); + if (victim && me->IsWithinDistInMap(victim, me->GetAttackDistance(victim))) + return false; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + if (m_threatlist.empty()) + return false; + + std::list targets; + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + targets.push_back(pUnit); + } + + if (targets.empty()) + return false; + + targets.sort(Trinity::ObjectDistanceOrderPred(me)); + Unit *pTarget = targets.front(); + if (pTarget) + { + if (!me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) + return true; // Cast Finger of Death + else // This target is closest, he is our new tank + me->AddThreat(pTarget, me->getThreatManager().getThreat(me->getVictim())); + } + + return false; + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == CREATURE_ANCIENT_WISP) + summoned->AI()->AttackStart(me); + else + { + summoned->setFaction(me->getFaction()); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) + { + DoomfireSpiritGUID = summoned->GetGUID(); + } + + if (summoned->GetEntry() == CREATURE_DOOMFIRE) + { + summoned->CastSpell(summoned,SPELL_DOOMFIRE_SPAWN,false); + summoned->CastSpell(summoned,SPELL_DOOMFIRE,true,0,0,me->GetGUID()); + + if (Unit *DoomfireSpirit = Unit::GetUnit(*me, DoomfireSpiritGUID)) + { + summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit,0.0f,0.0f); + DoomfireSpiritGUID = 0; + } + } + } + + //this is code doing close to what the summoning spell would do (spell 31903) + void SummonDoomfire(Unit *pTarget) + { + me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, + pTarget->GetPositionX()+15.0,pTarget->GetPositionY()+15.0,pTarget->GetPositionZ(),0, + TEMPSUMMON_TIMED_DESPAWN, 27000); + + me->SummonCreature(CREATURE_DOOMFIRE, + pTarget->GetPositionX()-15.0,pTarget->GetPositionY()-15.0,pTarget->GetPositionZ(),0, + TEMPSUMMON_TIMED_DESPAWN, 27000); + } + + void UnleashSoulCharge() + { + me->InterruptNonMeleeSpells(false); + + bool HasCast = false; + uint32 chargeSpell = 0; + uint32 unleashSpell = 0; + + switch (urand(0,2)) + { + case 0: + chargeSpell = SPELL_SOUL_CHARGE_RED; + unleashSpell = SPELL_UNLEASH_SOUL_RED; + break; + case 1: + chargeSpell = SPELL_SOUL_CHARGE_YELLOW; + unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; + break; + case 2: + chargeSpell = SPELL_SOUL_CHARGE_GREEN; + unleashSpell = SPELL_UNLEASH_SOUL_GREEN; + break; + } + + if (me->HasAura(chargeSpell)) + { + me->RemoveAuraFromStack(chargeSpell); + DoCast(me->getVictim(), unleashSpell); + HasCast = true; + SoulChargeCount--; + } + + if (HasCast) + SoulChargeTimer = urand(2000,30000); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + { + if (pInstance) + { + // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. + if ((pInstance->GetData(DATA_AZGALOREVENT) < DONE) && ((me->GetVisibility() != VISIBILITY_OFF) || (me->getFaction() != 35))) + { + me->SetVisibility(VISIBILITY_OFF); + me->setFaction(35); + } + else if ((pInstance->GetData(DATA_AZGALOREVENT) >= DONE) && ((me->GetVisibility() != VISIBILITY_ON) || (me->getFaction() == 35))) + { + me->setFaction(1720); + me->SetVisibility(VISIBILITY_ON); + } + } + + if (DrainNordrassilTimer <= diff) + { + if (!IsChanneling) + { + Creature *temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 1200000); + + if (temp) + WorldTreeGUID = temp->GetGUID(); + + if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) + { + Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Nordrassil->SetDisplayId(11686); + DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); + IsChanneling = true; + } + } + + if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) + { + Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); + DrainNordrassilTimer = 1000; + } + } else DrainNordrassilTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !BelowTenPercent && !Enraged) + BelowTenPercent = true; + + if (!Enraged) + { + if (EnrageTimer <= diff) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) > 10) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + Enraged = true; + DoScriptText(SAY_ENRAGE, me); + } + } else EnrageTimer -= diff; + + if (CheckDistanceTimer <= diff) + { + // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature + Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000); + if (Check) + { + Check->SetVisibility(VISIBILITY_OFF); + + if (me->IsWithinDistInMap(Check, 75)) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + Enraged = true; + DoScriptText(SAY_ENRAGE, me); + } + } + CheckDistanceTimer = 5000; + } else CheckDistanceTimer -= diff; + } + + if (BelowTenPercent) + { + if (!HasProtected) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + + //all members of raid must get this buff + DoCast(me->getVictim(), SPELL_PROTECTION_OF_ELUNE); + HasProtected = true; + Enraged = true; + } + + if (SummonWispTimer <= diff) + { + DoSpawnCreature(CREATURE_ANCIENT_WISP, rand()%40, rand()%40, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SummonWispTimer = 1500; + ++WispCount; + } else SummonWispTimer -= diff; + + if (WispCount >= 30) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (Enraged) + { + if (HandOfDeathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HAND_OF_DEATH); + HandOfDeathTimer = 2000; + } else HandOfDeathTimer -= diff; + return; // Don't do anything after this point. + } + + if (SoulChargeCount) + { + if (SoulChargeTimer <= diff) + UnleashSoulCharge(); + else SoulChargeTimer -= diff; + } + + if (GripOfTheLegionTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); + GripOfTheLegionTimer = urand(5000,25000); + } else GripOfTheLegionTimer -= diff; + + if (AirBurstTimer <= diff) + { + if (urand(0,1)) + DoScriptText(SAY_AIR_BURST1, me); + else + DoScriptText(SAY_AIR_BURST2, me); + + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank + AirBurstTimer = urand(25000,40000); + } else AirBurstTimer -= diff; + + if (FearTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + FearTimer = 42000; + } else FearTimer -= diff; + + if (DoomfireTimer <= diff) + { + if (urand(0,1)) + DoScriptText(SAY_DOOMFIRE1, me); + else + DoScriptText(SAY_DOOMFIRE2, me); + + Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!temp) + temp = me->getVictim(); + + //replace with spell cast 31903 once implicitTarget 73 implemented + SummonDoomfire(temp); + + //supposedly three doomfire can be up at the same time + DoomfireTimer = 20000; + } else DoomfireTimer -= diff; + + if (MeleeRangeCheckTimer <= diff) + { + if (CanUseFingerOfDeath()) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); + MeleeRangeCheckTimer = 1000; + } + + MeleeRangeCheckTimer = 5000; + } else MeleeRangeCheckTimer -= diff; + + DoMeleeAttackIfReady(); + } + void WaypointReached(uint32 /*i*/){} +}; + +CreatureAI* GetAI_boss_archimonde(Creature* pCreature) +{ + return new boss_archimondeAI (pCreature); +} + +CreatureAI* GetAI_mob_doomfire(Creature* pCreature) +{ + return new mob_doomfireAI(pCreature); +} + +CreatureAI* GetAI_mob_doomfire_targetting(Creature* pCreature) +{ + return new mob_doomfire_targettingAI(pCreature); +} + +CreatureAI* GetAI_mob_ancient_wisp(Creature* pCreature) +{ + return new mob_ancient_wispAI(pCreature); +} + +void AddSC_boss_archimonde() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_archimonde"; + newscript->GetAI = &GetAI_boss_archimonde; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_doomfire"; + newscript->GetAI = &GetAI_mob_doomfire; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_doomfire_targetting"; + newscript->GetAI = &GetAI_mob_doomfire_targetting; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ancient_wisp"; + newscript->GetAI = &GetAI_mob_ancient_wisp; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp new file mode 100644 index 00000000000..69e37f7f740 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp @@ -0,0 +1,285 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_RAIN_OF_FIRE 31340 +#define SPELL_DOOM 31347 +#define SPELL_HOWL_OF_AZGALOR 31344 +#define SPELL_CLEAVE 31345 +#define SPELL_BERSERK 26662 + +#define SAY_ONDEATH "Your time is almost... up" +#define SOUND_ONDEATH 11002 + +#define SAY_ONSLAY1 "Reesh, hokta!" +#define SAY_ONSLAY2 "Don't fight it" +#define SAY_ONSLAY3 "No one is going to save you" +#define SOUND_ONSLAY1 11001 +#define SOUND_ONSLAY2 11048 +#define SOUND_ONSLAY3 11047 + +#define SAY_DOOM1 "Just a taste... of what awaits you" +#define SAY_DOOM2 "Suffer you despicable insect!" +#define SOUND_DOOM1 11046 +#define SOUND_DOOM2 11000 + +#define SAY_ONAGGRO "Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!" +#define SOUND_ONAGGRO 10999 + +struct boss_azgalorAI : public hyjal_trashAI +{ + boss_azgalorAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_HOWL_OF_AZGALOR); + if (TempSpell) + TempSpell->EffectRadiusIndex[0] = 12;//100yards instead of 50000?! + } + + uint32 RainTimer; + uint32 DoomTimer; + uint32 HowlTimer; + uint32 CleaveTimer; + uint32 EnrageTimer; + bool enraged; + + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + RainTimer = 20000; + DoomTimer = 50000; + HowlTimer = 30000; + CleaveTimer = 10000; + EnrageTimer = 600000; + enraged = false; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 5492.91, -2404.61, 1462.63); + AddWaypoint(1, 5531.76, -2460.87, 1469.55); + AddWaypoint(2, 5554.58, -2514.66, 1476.12); + AddWaypoint(3, 5554.16, -2567.23, 1479.90); + AddWaypoint(4, 5540.67, -2625.99, 1480.89); + AddWaypoint(5, 5508.16, -2659.2, 1480.15); + AddWaypoint(6, 5489.62, -2704.05, 1482.18); + AddWaypoint(7, 5457.04, -2726.26, 1485.10); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (RainTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,30,true), SPELL_RAIN_OF_FIRE); + RainTimer = 20000+rand()%15000; + } else RainTimer -= diff; + + if (DoomTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,100,true), SPELL_DOOM);//never on tank + DoomTimer = 45000+rand()%5000; + } else DoomTimer -= diff; + + if (HowlTimer <= diff) + { + DoCast(me, SPELL_HOWL_OF_AZGALOR); + HowlTimer = 30000; + } else HowlTimer -= diff; + + if (CleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + CleaveTimer = 10000+rand()%5000; + } else CleaveTimer -= diff; + + if (EnrageTimer < diff && !enraged) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_BERSERK, true); + enraged = true; + EnrageTimer = 600000; + } else EnrageTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_azgalor(Creature* pCreature) +{ + return new boss_azgalorAI (pCreature); +} + +#define SPELL_THRASH 12787 +#define SPELL_CRIPPLE 31406 +#define SPELL_WARSTOMP 31408 + +struct mob_lesser_doomguardAI : public hyjal_trashAI +{ + mob_lesser_doomguardAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + AzgalorGUID = pInstance->GetData64(DATA_AZGALOR); + } + + uint32 CrippleTimer; + uint32 WarstompTimer; + uint32 CheckTimer; + uint64 AzgalorGUID; + ScriptedInstance* pInstance; + + void Reset() + { + CrippleTimer = 50000; + WarstompTimer = 10000; + DoCast(me, SPELL_THRASH); + CheckTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + } + + void WaypointReached(uint32 /*i*/) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) + AttackStart(who); + } + + void JustDied(Unit * /*victim*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (AzgalorGUID) + { + Creature* boss = Unit::GetCreature((*me),AzgalorGUID); + if (!boss || (boss && boss->isDead())) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + return; + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (WarstompTimer <= diff) + { + DoCast(me, SPELL_WARSTOMP); + WarstompTimer = 10000+rand()%5000; + } else WarstompTimer -= diff; + + if (CrippleTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_CRIPPLE); + CrippleTimer = 25000+rand()%5000; + } else CrippleTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_lesser_doomguard(Creature* pCreature) +{ + return new mob_lesser_doomguardAI (pCreature); +} + +void AddSC_boss_azgalor() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_azgalor"; + newscript->GetAI = &GetAI_boss_azgalor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lesser_doomguard"; + newscript->GetAI = &GetAI_mob_lesser_doomguard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp new file mode 100644 index 00000000000..b52d22842e3 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp @@ -0,0 +1,197 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_CLEAVE 31436 +#define SPELL_WARSTOMP 31480 +#define SPELL_MARK 31447 + +#define SOUND_ONDEATH 11018 + +#define SAY_ONSLAY1 "Shaza-Kiel!" +#define SAY_ONSLAY2 "You... are nothing!" +#define SAY_ONSLAY3 "Miserable nuisance!" +#define SOUND_ONSLAY1 11017 +#define SOUND_ONSLAY2 11053 +#define SOUND_ONSLAY3 11054 + +#define SAY_MARK1 "Your death will be a painful one." +#define SAY_MARK2 "You... are marked." +#define SOUND_MARK1 11016 +#define SOUND_MARK2 11052 + +#define SAY_ONAGGRO "Cry for mercy! Your meaningless lives will soon be forfeit." +#define SOUND_ONAGGRO 11015 + +struct boss_kazrogalAI : public hyjal_trashAI +{ + boss_kazrogalAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_MARK); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) + { + TempSpell->EffectImplicitTargetA[0] = 1; + TempSpell->EffectImplicitTargetB[0] = 0; + } + } + + uint32 CleaveTimer; + uint32 WarStompTimer; + uint32 MarkTimer; + uint32 MarkTimerBase; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + CleaveTimer = 5000; + WarStompTimer = 15000; + MarkTimer = 45000; + MarkTimerBase = 45000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 5492.91, -2404.61, 1462.63); + AddWaypoint(1, 5531.76, -2460.87, 1469.55); + AddWaypoint(2, 5554.58, -2514.66, 1476.12); + AddWaypoint(3, 5554.16, -2567.23, 1479.90); + AddWaypoint(4, 5540.67, -2625.99, 1480.89); + AddWaypoint(5, 5508.16, -2659.2, 1480.15); + AddWaypoint(6, 5489.62, -2704.05, 1482.18); + AddWaypoint(7, 5457.04, -2726.26, 1485.10); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (CleaveTimer <= diff) + { + DoCast(me, SPELL_CLEAVE); + CleaveTimer = 6000+rand()%15000; + } else CleaveTimer -= diff; + + if (WarStompTimer <= diff) + { + DoCast(me, SPELL_WARSTOMP); + WarStompTimer = 60000; + } else WarStompTimer -= diff; + + if (me->HasAura(SPELL_MARK)) + me->RemoveAurasDueToSpell(SPELL_MARK); + if (MarkTimer <= diff) + { + //cast dummy, useful for bos addons + me->CastCustomSpell(me, SPELL_MARK, NULL, NULL, NULL, false, NULL, NULL, me->GetGUID()); + + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->getPowerType() == POWER_MANA) + { + pTarget->CastSpell(pTarget, SPELL_MARK,true);//only cast on mana users + } + } + MarkTimerBase -= 5000; + if (MarkTimerBase < 5500) + MarkTimerBase = 5500; + MarkTimer = MarkTimerBase; + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_MARK1); + me->MonsterYell(SAY_MARK1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_MARK2); + me->MonsterYell(SAY_MARK2, LANG_UNIVERSAL, NULL); + break; + } + } else MarkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kazrogal(Creature* pCreature) +{ + return new boss_kazrogalAI (pCreature); +} + +void AddSC_boss_kazrogal() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kazrogal"; + newscript->GetAI = &GetAI_boss_kazrogal; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp new file mode 100644 index 00000000000..7465b997117 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp @@ -0,0 +1,192 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_FROST_ARMOR 31256 +#define SPELL_DEATH_AND_DECAY 31258 + +#define SPELL_FROST_NOVA 31250 +#define SPELL_ICEBOLT 31249 + +#define SAY_ONDEATH "You have won this battle, but not... the... war" +#define SOUND_ONDEATH 11026 + +#define SAY_ONSLAY1 "All life must perish!" +#define SAY_ONSLAY2 "Victory to the Legion!" +#define SOUND_ONSLAY1 11025 +#define SOUND_ONSLAY2 11057 + +#define SAY_DECAY1 "Crumble and rot!" +#define SAY_DECAY2 "Ashes to ashes, dust to dust" +#define SOUND_DECAY1 11023 +#define SOUND_DECAY2 11055 + +#define SAY_NOVA1 "Succumb to the icy chill... of death!" +#define SAY_NOVA2 "It will be much colder in your grave" +#define SOUND_NOVA1 11024 +#define SOUND_NOVA2 11058 + +#define SAY_ONAGGRO "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!" +#define SOUND_ONAGGRO 11022 + +struct boss_rage_winterchillAI : public hyjal_trashAI +{ + boss_rage_winterchillAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + } + + uint32 FrostArmorTimer; + uint32 DecayTimer; + uint32 NovaTimer; + uint32 IceboltTimer; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + FrostArmorTimer = 37000; + DecayTimer = 45000; + NovaTimer = 15000; + IceboltTimer = 10000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0f); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, NULL); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 4896.08, -1576.35, 1333.65); + AddWaypoint(1, 4898.68, -1615.02, 1329.48); + AddWaypoint(2, 4907.12, -1667.08, 1321.00); + AddWaypoint(3, 4963.18, -1699.35, 1340.51); + AddWaypoint(4, 4989.16, -1716.67, 1335.74); + AddWaypoint(5, 5026.27, -1736.89, 1323.02); + AddWaypoint(6, 5037.77, -1770.56, 1324.36); + AddWaypoint(7, 5067.23, -1789.95, 1321.17); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (FrostArmorTimer <= diff) + { + DoCast(me, SPELL_FROST_ARMOR); + FrostArmorTimer = 40000+rand()%20000; + } else FrostArmorTimer -= diff; + if (DecayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_DEATH_AND_DECAY); + DecayTimer = 60000+rand()%20000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_DECAY1); + me->MonsterYell(SAY_DECAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_DECAY2); + me->MonsterYell(SAY_DECAY2, LANG_UNIVERSAL, NULL); + break; + } + } else DecayTimer -= diff; + if (NovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_NOVA); + NovaTimer = 30000+rand()%15000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_NOVA1); + me->MonsterYell(SAY_NOVA1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_NOVA2); + me->MonsterYell(SAY_NOVA2, LANG_UNIVERSAL, NULL); + break; + } + } else NovaTimer -= diff; + if (IceboltTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,40,true), SPELL_ICEBOLT); + IceboltTimer = 11000+rand()%20000; + } else IceboltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_rage_winterchill(Creature* pCreature) +{ + return new boss_rage_winterchillAI (pCreature); +} + +void AddSC_boss_rage_winterchill() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_rage_winterchill"; + newscript->GetAI = &GetAI_boss_rage_winterchill; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp new file mode 100644 index 00000000000..16a050939cc --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp @@ -0,0 +1,247 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Hyjal +SD%Complete: 80 +SDComment: gossip text id's unknown +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +/* ContentData +npc_jaina_proudmoore +npc_thrall +npc_tyrande_whisperwind +EndContentData */ + +#include "ScriptedPch.h" +#include "hyjalAI.h" + +#define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore." +#define GOSSIP_ITEM_ANETHERON "We are ready for whatever Archimonde might send our way, Lady Proudmoore." + +#define GOSSIP_ITEM_BEGIN_HORDE "I am with you, Thrall." +#define GOSSIP_ITEM_AZGALOR "We have nothing to fear." + +#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!" + +#define GOSSIP_ITEM_TYRANDE "Aid us in defending Nordrassil" +#define ITEM_TEAR_OF_GODDESS 24494 + +#define GOSSIP_ITEM_GM1 "[GM] Toggle Debug Timers" + +CreatureAI* GetAI_npc_jaina_proudmoore(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + + ai->Reset(); + ai->EnterEvadeMode(); + + ai->Spell[0].SpellId = SPELL_BLIZZARD; + ai->Spell[0].Cooldown = 15000 + rand()%20000; + ai->Spell[0].TargetType = TARGETTYPE_RANDOM; + + ai->Spell[1].SpellId = SPELL_PYROBLAST; + ai->Spell[1].Cooldown = 5500 + rand()%4000; + ai->Spell[1].TargetType = TARGETTYPE_RANDOM; + + ai->Spell[2].SpellId = SPELL_SUMMON_ELEMENTALS; + ai->Spell[2].Cooldown = 15000 + rand()%30000; + ai->Spell[2].TargetType = TARGETTYPE_SELF; + + return ai; +} + +bool GossipHello_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + if (ai->EventBegun) + return false; + + uint32 RageEncounter = ai->GetInstanceData(DATA_RAGEWINTERCHILLEVENT); + uint32 AnetheronEncounter = ai->GetInstanceData(DATA_ANETHERONEVENT); + if (RageEncounter == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + else if (RageEncounter == DONE && AnetheronEncounter == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + else if (RageEncounter == DONE && AnetheronEncounter == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + if (pPlayer->isGameMaster()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + ai->FirstBossDead = true; + ai->WaveCount = 9; + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + ai->Retreat(); + break; + case GOSSIP_ACTION_INFO_DEF: + ai->Debug = !ai->Debug; + debug_log("TSCR: HyjalAI - Debug mode has been toggled"); + break; + } + return true; +} + +CreatureAI* GetAI_npc_thrall(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + + ai->Reset(); + ai->EnterEvadeMode(); + + ai->Spell[0].SpellId = SPELL_CHAIN_LIGHTNING; + ai->Spell[0].Cooldown = 3000 + rand()%5000; + ai->Spell[0].TargetType = TARGETTYPE_VICTIM; + + ai->Spell[1].SpellId = SPELL_SUMMON_DIRE_WOLF; + ai->Spell[1].Cooldown = 6000 + rand()%35000; + ai->Spell[1].TargetType = TARGETTYPE_RANDOM; + + return ai; +} + +bool GossipHello_npc_thrall(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + if (ai->EventBegun) + return false; + + uint32 AnetheronEvent = ai->GetInstanceData(DATA_ANETHERONEVENT); + // Only let them start the Horde phases if Anetheron is dead. + if (AnetheronEvent == DONE && ai->GetInstanceData(DATA_ALLIANCE_RETREAT)) + { + uint32 KazrogalEvent = ai->GetInstanceData(DATA_KAZROGALEVENT); + uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); + if (KazrogalEvent == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + else if (KazrogalEvent == DONE && AzgalorEvent == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + else if (AzgalorEvent == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + } + + if (pPlayer->isGameMaster()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_thrall(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + ai->DeSpawnVeins();//despawn the alliance veins + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + ai->FirstBossDead = true; + ai->WaveCount = 9; + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + ai->Retreat(); + break; + case GOSSIP_ACTION_INFO_DEF: + ai->Debug = !ai->Debug; + debug_log("TSCR: HyjalAI - Debug mode has been toggled"); + break; + } + return true; +} + +CreatureAI* GetAI_npc_tyrande_whisperwind(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + ai->Reset(); + ai->EnterEvadeMode(); + return ai; +} + +bool GossipHello_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); + + // Only let them get item if Azgalor is dead. + if (AzgalorEvent == DONE && !pPlayer->HasItemCount(ITEM_TEAR_OF_GODDESS,1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TYRANDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_TEAR_OF_GODDESS, 1); + if (msg == EQUIP_ERR_OK) + { + Item* item = pPlayer->StoreNewItem(dest, ITEM_TEAR_OF_GODDESS, true); + if (item && pPlayer) + pPlayer->SendNewItem(item,1,true,false,true); + } + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + CAST_AI(hyjalAI, pCreature->AI()); + } + return true; +} + +void AddSC_hyjal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_jaina_proudmoore"; + newscript->GetAI = &GetAI_npc_jaina_proudmoore; + newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore; + newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thrall"; + newscript->GetAI = &GetAI_npc_thrall; + newscript->pGossipHello = &GossipHello_npc_thrall; + newscript->pGossipSelect = &GossipSelect_npc_thrall; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tyrande_whisperwind"; + newscript->pGossipHello = &GossipHello_npc_tyrande_whisperwind; + newscript->pGossipSelect = &GossipSelect_npc_tyrande_whisperwind; + newscript->GetAI = &GetAI_npc_tyrande_whisperwind; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h new file mode 100644 index 00000000000..bfc9a54dfd9 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_HYJAL_H +#define DEF_HYJAL_H + +#define ERROR_INST_DATA "TSCR: Instance data not set properly for Mount Hyjal. Encounters will be buggy." + +enum eTypes +{ + WORLD_STATE_WAVES = 2842, + WORLD_STATE_ENEMY = 2453, + WORLD_STATE_ENEMYCOUNT = 2454, + + DATA_ANETHERON = 1, + DATA_ANETHERONEVENT = 2, + DATA_ARCHIMONDE = 3, + DATA_ARCHIMONDEEVENT = 4, + DATA_AZGALOR = 5, + DATA_AZGALOREVENT = 6, + DATA_JAINAPROUDMOORE = 7, + DATA_KAZROGAL = 8, + DATA_KAZROGALEVENT = 9, + DATA_RAGEWINTERCHILL = 10, + DATA_RAGEWINTERCHILLEVENT = 11, + DATA_THRALL = 12, + DATA_TYRANDEWHISPERWIND = 13, + DATA_TRASH = 14, + DATA_RESET_TRASH_COUNT = 15, + DATA_ALLIANCE_RETREAT = 16, + DATA_HORDE_RETREAT = 17, + DATA_RAIDDAMAGE = 18, + DATA_RESET_RAIDDAMAGE = 19, + TYPE_RETREAT = 20 +}; +#endif + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp new file mode 100644 index 00000000000..3c12b54f3f4 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp @@ -0,0 +1,1157 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: HyjalAI +SD%Complete: 90 +SDComment: +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjalAI.h" +#include "hyjal_trash.h" +#include "MapManager.h" +#include "Language.h" +#include "Chat.h" +#include "Object.h" + +#define SPAWN_GARG_GATE 0 +#define SPAWN_WYRM_GATE 1 +#define SPAWN_NEAR_TOWER 2 + +#define YELL_HURRY "Hurry, we don't have much time" + +// Locations for summoning gargoyls and frost wyrms in special cases +float SpawnPointSpecial[3][3]= +{ + {5497.08, -2493.23, 1535.72}, //spawn point for the gargoyles near the horde gate + {5624.53, -2548.12, 1551.54}, //spawn point for the frost wyrm near the horde gate + {5604.41, -2811.98, 1547.77} //spawn point for the gargoyles and wyrms near the horde tower +}; + +// Locations for summoning waves in Alliance base +float AllianceBase[4][3]= +{ + {4928.48, -1526.38, 1326.83}, + {4923.54, -1514.29, 1327.98}, + {4928.41, -1510.35, 1327.99}, + {4938.35, -1521.00, 1326.69} +}; + +float JainaDummySpawn[2][4]= +{ + {5497.01, -2719.03, 1483.08, 2.90426}, + {5484.98, -2721.69, 1483.39, 6.00656} +}; + +// Locations for summoning waves in Horde base +float HordeBase[4][3]= +{ + {5458.01, -2340.27, 1459.60}, + {5466.01, -2334.69, 1460.06}, + {5468.45, -2355.13, 1459.99}, + {5479.06, -2344.16, 1461.74} +}; + +// Lady Jaina's waypoints when retreathing +float JainaWPs[2][3]= +{ + {5078.56, -1789.79, 1320.73},//next to the small stairs + {5037.38, -1778.39, 1322.61},//center of alliance base +}; + +float InfernalPos[8][3]=//spawn points for the infernals in the horde base +{ + {5453.59, -2764.52, 1493.50}, + {5478.4, -2781.77, 1497.52}, + {5506.09, -2780.53, 1496.32}, + {5532.1, -2763.42, 1492.37}, + {5544.16, -2733.99, 1487.14}, + {5536.19, -2708.18, 1480.01}, + {5510.16, -2691.75, 1479.66}, + {5482.39, -2689.19, 1481.09} +}; + +float InfernalSPWP[26][4]=//spawn points for the infernals in the horde base used in the cleaning wave +{ + {5490.96, -2718.72, 1482.96, 0.49773}, + {5449.51, -2723.32, 1485.69, 2.69685}, + {5520.83, -2624.68, 1483.82, 1.20459}, + {5558.28, -2629.26, 1485.76, 0.37992}, + {5567.97, -2758.69, 1494.10, 5.04125}, + {5384.90, -2793.47, 1503.90, 5.55412}, + {5495.33, -2814.06, 1501.56, 1.12055}, + {5472.63, -2929.39, 1538.31, 1.95777}, + {5334.72, -2952.29, 1534.34, 0.50869}, + {5398.36, -2872.46, 1512.38, 0.76787}, + {5514.39, -2768.63, 1492.30, 1.55721}, + {5598.91, -2703.75, 1495.64, 2.56644}, + {5467.80, -2655.93, 1482.27, 0.85819}, + {5399.83, -2985.24, 1545.04, 5.92559}, + {5232.13, -2967.05, 1553.09, 5.41351}, + {5272.02, -3082.52, 1567.09, 3.40681}, + {5343.26, -3120.71, 1582.92, 3.16727}, + {5371.26, -3175.24, 1587.41, 6.10466}, + {5434.67, -3177.91, 1579.25, 2.77850}, + {5237.39, -3149.25, 1593.59, 0.83855}, + {5202.15, -3016.64, 1566.28, 3.31256}, + {5302.54, -2914.37, 1528.53, 3.37146}, + {5439.04, -2834.81, 1508.80, 2.14231}, + {5421.33, -2771.04, 1494.28, 6.06223}, + {5549.76, -2692.93, 1482.68, 2.19414}, + {5459.78, -2755.71, 1490.68, 1.05139} +}; + +float VeinPos[14][8]=//spawn points of the ancient gem veins +{ + {5184.84, -1982.59, 1382.66, 2.58079, 0, 0, 0.960944, 0.276742}, //alliance + {5107.66, -2071.16, 1368.37, 2.65148, 0, 0, 0.970124, 0.242611}, //alliance + {5040.53, -2227.65, 1403.17, 3.35049, 0, 0, 0.99455, -0.104257}, //alliance + {5187.59, -2453.12, 1455.51, 5.87943, 0, 0, 0.20051, -0.979692}, //alliance + {5429.43, -2340.65, 1465.38, 4.7681, 0, 0, 0.687138, -0.726527}, //alliance + {5463.99, -2315.95, 1470.29, 1.52045, 0, 0, 0.689084, 0.724682}, //alliance + {5624.65, -2495.09, 1510.11, 0.0124869, 0, 0, 0.00624342, 0.999981}, //alliance + {5285.41, -3348.32, 1663.01, 1.57152, 0, 0, 0.707362, 0.706852}, //horde + {5417.69, -3372.52, 1656.31, 0.361993, 0, 0, 0.18001, 0.983665}, //horde + {5315.34, -3238.32, 1622.88, 3.03627, 0, 0, 0.998614, 0.0526347}, //horde + {5303.4, -3096.44, 1596.41, 1.72073, 0, 0, 0.758081, 0.65216}, //horde + {5265.13, -3177.27, 1616.22, 0.813604, 0, 0, 0.395674, 0.918391}, //horde + {5374.3, -3420.59, 1653.43, 1.45762, 0, 0, 0.665981, 0.745969}, //horde + {5441.54, -3321.59, 1651.55, 0.258306, 0, 0, 0.128794, 0.991671} //horde +}; + +float AllianceOverrunGargPos[5][4]=//gargoyle spawn points in the alliance overrun +{ + {5279.94, -2049.68, 1311.38, 0},//garg1 + {5289.15, -2219.06, 1291.12, 0},//garg2 + {5202.07, -2136.10, 1305.07, 2.8},//garg3 + {5071.52, -2425.63, 1454.48, 5.54},//garg4 + {5120.65, -2467.92, 1463.93, 2.54}//garg5 +}; + +float AllianceFirePos[92][8]=//spawn points for the fire visuals (GO) in the alliance base +{ + {5039.9, -1796.84, 1323.88, 2.59222, 0, 0, 0.962511, 0.271243}, + {5087.2, -1795.2, 1320.68, 1.03946, 0, 0, 0.496644, 0.867954}, + {5112.68, -1806.66, 1359.93, 1.37799, 0, 0, 0.63576, 0.771887}, + {5095.61, -1793.27, 1359.78, 0.580806, 0, 0, 0.286338, 0.958129}, + {5090.43, -1784.45, 1360.44, 0.796784, 0, 0, 0.387937, 0.921686}, + {5139.25, -1783.11, 1359.39, 3.30849, 0, 0, 0.99652, -0.0833509}, + {5112.16, -1763.72, 1361.35, 5.10312, 0, 0, 0.556388, -0.830922}, + {4981.18, -1793.98, 1335.7, 3.23072, 0, 0, 0.999007, -0.0445498}, + {4996.57, -1766.75, 1341.62, 3.5331, 0, 0, 0.980902, -0.194505}, + {4983.74, -1769.25, 1345.75, 3.79228, 0, 0, 0.947541, -0.319635}, + {4996.01, -1774.43, 1330.71, 3.07364, 0, 0, 0.999423, 0.0339693}, + {5094.2, -1726.13, 1330.55, 1.56175, 0, 0, 0.703901, 0.710298}, + {5079.82, -1721.24, 1336.26, 1.18868, 0, 0, 0.559964, 0.828517}, + {5077.68, -1717.15, 1327.78, 0.0145145, 0, 0, 0.00725717, 0.999974}, + {5122.27, -1738.22, 1341.67, 0.835256, 0, 0, 0.405593, 0.914054}, + {5131.88, -1741.15, 1335.25, 2.15472, 0, 0, 0.880712, 0.473653}, + {5196.93, -1772.99, 1345.2, 0.128397, 0, 0, 0.0641544, 0.99794}, + {5225.33, -1756.06, 1344.17, 3.04223, 0, 0, 0.998766, 0.0496599}, + {5224.84, -1767.05, 1360.06, 3.19538, 0, 0, 0.999638, -0.0268922}, + {5202.05, -1763.47, 1361.68, 2.59455, 0, 0, 0.962826, 0.270122}, + {5194.74, -1766.66, 1356.94, 0.0734191, 0, 0, 0.0367013, 0.999326}, + {5159.67, -1832.97, 1344.5, 5.17457, 0, 0, 0.526356, -0.850264}, + {5096.17, -1858.73, 1332.46, 5.30021, 0, 0, 0.471939, -0.881631}, + {5110.7, -1856.59, 1342.84, 5.97564, 0, 0, 0.153167, -0.9882}, + {5109.76, -1855.3, 1332.38, 4.89572, 0, 0, 0.639411, -0.768865}, + {5068.95, -1837.37, 1328.81, 2.61569, 0, 0, 0.965628, 0.25993}, + {5064.4, -1824.77, 1329.02, 2.16409, 0, 0, 0.88292, 0.469524}, + {5059.89, -1848.79, 1329.59, 0.0709955, 0, 0, 0.0354903, 0.99937}, + {5014.37, -1851.39, 1322.56, 4.66949, 0, 0, 0.722111, -0.691777}, + {5025.1, -1848.27, 1323.39, 4.44565, 0, 0, 0.794854, -0.606801}, + {4942.63, -1890.13, 1326.59, 3.28719, 0, 0, 0.997351, -0.0727343}, + {4937.95, -1888.71, 1352.41, 3.41678, 0, 0, 0.990549, -0.13716}, + {4922.48, -1881.92, 1352.41, 5.03077, 0, 0, 0.586075, -0.810257}, + {4915.35, -1894.32, 1351.24, 6.22457, 0, 0, 0.0293048, -0.999571}, + {4922.71, -1904.84, 1352.56, 1.37866, 0, 0, 0.63602, 0.771672}, + {4932.89, -1905.49, 1352.56, 1.89702, 0, 0, 0.812549, 0.582893}, + {5011.83, -1861.05, 1345.86, 4.43777, 0, 0, 0.797239, -0.603664}, + {5011.83, -1861.05, 1363.26, 4.748, 0, 0, 0.694406, -0.719583}, + {5021.46, -1858.35, 1342.17, 4.86188, 0, 0, 0.652329, -0.757936}, + {4995.02, -1698.3, 1370.38, 6.15779, 0, 0, 0.0626579, -0.998035}, + {5119.85, -1728.9, 1336.04, 5.87112, 0, 0, 0.204579, -0.97885}, + {5214.75, -1751.02, 1342.5, 5.08965, 0, 0, 0.561972, -0.827156}, + {5075.04, -1822.43, 1328.87, 3.99951, 0, 0, 0.9094, -0.415924}, + {5057.09, -1823.32, 1350.35, 3.88169, 0, 0, 0.93231, -0.361659}, + {4984.6, -1816.99, 1329.21, 3.05308, 0, 0, 0.999021, 0.0442417}, + {4983.35, -1811.55, 1356.82, 3.33975, 0, 0, 0.995096, -0.098917}, + {4984.11, -1825.73, 1350.76, 2.26375, 0, 0, 0.905211, 0.424962}, + {4968.47, -1786.46, 1354.09, 3.07663, 0, 0, 0.999473, 0.0324733}, + {5061.82, -1751.16, 1339.07, 5.94727, 0, 0, 0.167171, -0.985928}, + {5063.75, -1763, 1351.91, 0.759707, 0, 0, 0.370784, 0.928719}, + {5078.65, -1708.26, 1353.9, 1.27022, 0, 0, 0.593264, 0.805008}, + {4983.19, -1755.96, 1331.13, 4.28221, 0, 0, 0.841733, -0.539894}, + {4972.76, -1755.3, 1332.5, 4.21938, 0, 0, 0.858276, -0.513188}, + {4961.65, -1760.82, 1351.69, 3.56515, 0, 0, 0.977659, -0.210198}, + {5086.45, -1779.83, 1321.62, 6.23157, 0, 0, 0.0258051, -0.999667}, + {5063.15, -1756.74, 1328.56, 0.886926, 0, 0, 0.42907, 0.903271}, + {5042.45, -1800.61, 1323.88, 2.50093, 0, 0, 0.949131, 0.31488}, + {5084.74, -1725.35, 1327.89, 1.65034, 0, 0, 0.734663, 0.678432}, + {4993.25, -1758.1, 1331.07, 3.49995, 0, 0, 0.98399, -0.178223}, + {5078.53, -1867.85, 1348.91, 5.85612, 0, 0, 0.211913, -0.977288}, + {5080.74, -1869.73, 1333.18, 6.18206, 0, 0, 0.0505424, -0.998722}, + {5089.55, -1894.13, 1356.08, 1.52072, 0, 0, 0.689181, 0.724589}, + {5113.24, -1899.49, 1363.77, 1.50108, 0, 0, 0.682034, 0.731321}, + {4984.18, -1907.69, 1325.62, 3.82193, 0, 0, 0.942698, -0.333646}, + {5094.14, -2432.08, 1429.38, 4.70083, 0, 0, 0.711182, -0.703007}, + {5329.89, -2113.30, 1281.06, 5.60560, 0, 0, 0.332347, -0.943157}, + {5170.87, -2148.13, 1278.32, 1.63540, 0, 0, 0.729573, 0.683903 }, + {5132.94, -1960.25, 1367.8, 3.69787, 0, 0, 0.961568, -0.274566}, + {5280.82, -2351.55, 1431.57, 4.46913, 0, 0, 0.787677, -0.616088}, + {5176.78, -2121.43, 1295.27, 3.24153, 0, 0, 0.998752, -0.04995}, + {5332.75, -2101.41, 1296.37, 5.50350, 0, 0, 0.380043, -0.924969}, + {5265.70, -2050.27, 1287.57, 0.50051, 0, 0, 0.247655, 0.968848 }, + {5194.21, -2129.89, 1274.04, 3.08053, 0, 0, 0.999534, 0.0305272}, + {5225.81, -1985.50, 1364.15, 0.37247, 0, 0, 0.185163, 0.982708 }, + {5339.46, -2204.47, 1280.45, 0.99921, 0, 0, 0.479081, 0.877771 }, + {5269.63, -2020.57, 1299.62, 3.00201, 0, 0, 0.997566, 0.0697332}, + {5111.54, -2445.70, 1435.31, 2.70983, 0, 0, 0.976788, 0.214207 }, + {5111.24, -1901.14, 1355.33, 1.61028, 0, 0, 0.720929, 0.693009 }, + {5310.42, -2207.82, 1277.46, 0.50441, 0, 0, 0.249544, 0.968363 }, + {5150.81, -2042.13, 1394.3, 2.21031, 0, 0, 0.893534, 0.448995 }, + {5224.84, -2376.61, 1366.33, 5.0621, 0, 0, 0.573311, -0.819338}, + {5105.41, -2454.86, 1446.16, 4.64584, 0, 0, 0.730239, -0.683191}, + {5309.65, -2188.28, 1266.84, 5.56631, 0, 0, 0.350811, -0.936446}, + {5281.46, -2047.82, 1287.67, 2.44909, 0, 0, 0.940652, 0.339373 }, + {5325.45, -2189.41, 1309.6, 6.23783, 0, 0, 0.0226771, -0.999743}, + {5190.96, -2142.54, 1293.03, 6.25668, 0, 0, 0.0132544, -0.999912}, + {5089.99, -2467.49, 1441.8, 0.77381, 0, 0, 0.377326, 0.92608 }, + {5195.08, -2129.01, 1285.36, 3.55727, 0, 0, 0.978480, -0.206344}, + {5353.76, -2116.28, 1299.27, 6.17894, 0, 0, 0.0521006, -0.998642}, + {5271.14, -2037.38, 1299.24, 4.07879, 0, 0, 0.892201, -0.451638}, + {5332.5 , -2181.28, 1279.95, 4.6906, 0, 0, 0.714768, -0.699362}, + {5108.2 , -2429.84, 1427.73, 4.5194, 0, 0, 0.771943, -0.635691} +}; + +float HordeFirePos[65][8]=//spawn points for the fire visuals (GO) in the horde base +{ + {5524.11, -2612.73, 1483.38, 1.96198, 0, 0, 0.831047, 0.556202}, + {5514.42, -2617.19, 1505.77, 1.82453, 0, 0, 0.790892, 0.611956}, + {5510.21, -2624.77, 1485.34, 1.71065, 0, 0, 0.754783, 0.655974}, + {5570.72, -2619.04, 1487.62, 0.728898, 0, 0, 0.356435, 0.93432}, + {5570.29, -2639.37, 1487.31, 1.49308, 0, 0, 0.679104, 0.734042}, + {5583.56, -2637.2, 1503.78, 1.46559, 0, 0, 0.668951, 0.743307}, + {5571.53, -2626.81, 1510.99, 0.362107, 0, 0, 0.180066, 0.983654}, + {5545.97, -2659.62, 1489.64, 5.07055, 0, 0, 0.569845, -0.821752}, + {5557.44, -2675.91, 1482.58, 1.70118, 0, 0, 0.751671, 0.659539}, + {5594.98, -2742.31, 1495.51, 4.5993, 0, 0, 0.74594, -0.666013}, + {5599.65, -2755.6, 1505.05, 1.66896, 0, 0, 0.740947, 0.671564}, + {5565.95, -2774.75, 1499.48, 6.22425, 0, 0, 0.0294611, -0.999566}, + {5567.1, -2769.7, 1511.17, 5.99257, 0, 0, 0.144799, -0.989461}, + {5572.84, -2774.16, 1527.06, 0.836428, 0, 0, 0.406129, 0.913816}, + {5538.32, -2805.94, 1498.87, 4.30082, 0, 0, 0.836674, -0.547701}, + {5515.66, -2801.74, 1503.53, 5.57316, 0, 0, 0.347602, -0.937642}, + {5516.76, -2827.14, 1501.15, 0.35026, 0, 0, 0.174236, 0.984704}, + {5536.13, -2813.51, 1537.21, 4.51681, 0, 0, 0.772765, -0.634692}, + {5525.05, -2825.16, 1538.53, 0.489275, 0, 0, 0.242205, 0.970225}, + {5534.42, -2815.45, 1562.84, 4.62834, 0, 0, 0.736191, -0.676774}, + {5519.64, -2831.12, 1526.46, 0.611008, 0, 0, 0.300774, 0.953696}, + {5551.04, -2827.55, 1523.5, 3.35206, 0, 0, 0.994468, -0.10504}, + {5469.22, -2802.87, 1503.5, 4.99509, 0, 0, 0.600436, -0.799673}, + {5427.8, -2737.26, 1487.12, 1.78673, 0, 0, 0.779186, 0.626793}, + {5454.1, -2709.1, 1485.92, 3.03552, 0, 0, 0.998594, 0.0530137}, + {5436.3, -2718.2, 1506.02, 2.7567, 0, 0, 0.981539, 0.191261}, + {5412.6, -2740.55, 1510.79, 2.98446, 0, 0, 0.996915, 0.0784832}, + {5406.12, -2752.48, 1521.01, 2.05769, 0, 0, 0.856705, 0.515807}, + {5445.24, -2676.35, 1521.89, 2.91378, 0, 0, 0.99352, 0.113661}, + {5481.4, -2665.08, 1482.23, 4.30001, 0, 0, 0.836895, -0.547363}, + {5443.51, -2675.44, 1487.12, 2.90986, 0, 0, 0.993295, 0.115606}, + {5391.72, -2647.3, 1528.9, 3.76987, 0, 0, 0.951063, -0.308997}, + {5421.09, -2734.12, 1521.01, 2.70567, 0, 0, 0.97634, 0.216242}, + {5405.39, -2710.33, 1533.77, 2.51324, 0, 0, 0.951052, 0.309032}, + {5423.96, -2703.76, 1516.34, 2.79206, 0, 0, 0.984767, 0.173879}, + {5444.75, -2735.23, 1486.37, 2.22657, 0, 0, 0.897155, 0.441715}, + {5570.98, -2747.91, 1495.7, 5.14433, 0, 0, 0.53915, -0.84221}, + {5567.79, -2673.9, 1484.66, 2.72529, 0, 0, 0.978415, 0.20665}, + {5600.71, -2696.8, 1500.42, 0.443704, 0, 0, 0.220036, 0.975492}, + {5600.7, -2693.04, 1515.2, 5.16003, 0, 0, 0.532522, -0.846416}, + {5627.56, -2839.66, 1510.53, 5.41527, 0, 0, 0.420463, -0.907309}, + {5622.02, -2868.71, 1516.22, 2.25482, 0, 0, 0.903303, 0.429002}, + {5586.61, -2878.97, 1510.34, 4.55604, 0, 0, 0.76017, -0.649724}, + {5583.78, -2843.71, 1509.54, 5.35715, 0, 0, 0.44665, -0.894709}, + {5580.95, -2811.3, 1513.3, 3.57587, 0, 0, 0.976518, -0.215434}, + {5542.52, -2869.31, 1523.13, 5.23304, 0, 0, 0.501275, -0.865288}, + {5557.35, -2866.36, 1518.76, 4.48299, 0, 0, 0.783388, -0.621533}, + {5380.91, -2849.36, 1512.81, 3.90962, 0, 0, 0.927168, -0.374646}, + {5395.76, -2881.41, 1521.11, 4.28426, 0, 0, 0.84118, -0.540755}, + {5374.87, -2859.63, 1528.98, 3.30252, 0, 0, 0.996765, -0.0803745}, + {5356.07, -2854.66, 1520.34, 5.83933, 0, 0, 0.220108, -0.975475}, + {5363.01, -2975.72, 1539.02, 4.13738, 0, 0, 0.87859, -0.477576}, + {5336.85, -2980.74, 1561.24, 5.11126, 0, 0, 0.553001, -0.83318}, + {5335.23, -2974.62, 1540.05, 5.04451, 0, 0, 0.580496, -0.814263}, + {5422.37, -2998.87, 1549.98, 4.51831, 0, 0, 0.772288, -0.635272}, + {5405.54, -3014.6, 1562.16, 5.86761, 0, 0, 0.206298, -0.978489}, + {5427.96, -3019.4, 1561.58, 3.53498, 0, 0, 0.980718, -0.19543}, + {5348.12, -2977.84, 1582.47, 3.94025, 0, 0, 0.921323, -0.388799}, + {5331.12, -2993.71, 1576.14, 0.0642734, 0, 0, 0.0321311, 0.999484}, + {5321.63, -2986.55, 1552.2, 5.29503, 0, 0, 0.474219, -0.880407}, + {5292.1, -2914.36, 1529.52, 2.9742, 0, 0, 0.996499, 0.083601}, + {5281.77, -2926.5, 1530.62, 1.67829, 0, 0, 0.744071, 0.6681}, + {5287.19, -2909.94, 1543.49, 3.31192, 0, 0, 0.996376, -0.0850591}, + {5534.15, -2679.35, 1483.61, 0.428685, 0, 0, 0.212705, 0.977116}, + {5545.43, -2647.82, 1483.05, 5.38848, 0, 0, 0.432578, -0.901596} +}; + +hyjalAI::hyjalAI(Creature *c) : npc_escortAI(c), Summons(me) +{ + pInstance = c->GetInstanceData(); + VeinsSpawned[0] = false; + VeinsSpawned[1] = false; + for (uint8 i=0; i<14; ++i) + VeinGUID[i] = 0; + InfernalCount = 0; + TeleportTimer = 1000; + Overrun = false; + Teleported = false; + WaitForTeleport = false; + OverrunCounter = 0; + OverrunCounter2 = 0; + InfernalPoint = 0; + RespawnTimer = 10000; + DoRespawn = false; + DoHide = false; + MassTeleportTimer = 0; + DoMassTeleport = false; +} + +void hyjalAI::JustSummoned(Creature *summoned) +{ + Summons.Summon(summoned); +} + +void hyjalAI::SummonedCreatureDespawn(Creature* summoned) +{ + Summons.Despawn(summoned); +} + +void hyjalAI::Reset() +{ + IsDummy = false; + me->setActive(true); + // GUIDs + PlayerGUID = 0; + BossGUID[0] = 0; + BossGUID[1] = 0; + + // Timers + NextWaveTimer = 10000; + CheckTimer = 0; + RetreatTimer = 1000; + + // Misc + WaveCount = 0; + EnemyCount = 0; + + // Set faction properly based on Creature entry + switch(me->GetEntry()) + { + case JAINA: + Faction = 0; + DoCast(me, SPELL_BRILLIANCE_AURA, true); + break; + + case THRALL: + Faction = 1; + break; + + case TYRANDE: + Faction = 2; + break; + } + + //Bools + EventBegun = false; + FirstBossDead = false; + SecondBossDead = false; + Summon = false; + bRetreat = false; + Debug = false; + + //Flags + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + //Initialize spells + memset(Spell, 0, sizeof(Spell)); + + //Reset Instance Data for trash count + if (pInstance) + { + if ((!pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == JAINA) || (pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == THRALL)) + { + //Reset World States + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); + pInstance->SetData(DATA_RESET_TRASH_COUNT, 0); + } + } else error_log(ERROR_INST_DATA); + + //Visibility + DoHide = true; +} + +void hyjalAI::EnterEvadeMode() +{ + if (me->GetEntry() != JAINA) + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + me->LoadCreaturesAddon(); + + if (me->isAlive()) + me->GetMotionMaster()->MoveTargetedHome(); + + me->SetLootRecipient(NULL); +} + +void hyjalAI::EnterCombat(Unit * /*who*/) +{ + if (IsDummy)return; + for (uint8 i = 0; i < 3; ++i) + if (Spell[i].Cooldown) + SpellTimer[i] = Spell[i].Cooldown; + + Talk(ATTACKED); +} + +void hyjalAI::MoveInLineOfSight(Unit *who) +{ + if (IsDummy) + return; + + npc_escortAI::MoveInLineOfSight(who); +} + +void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) +{ + uint32 random = rand()%4; + float SpawnLoc[3]; + + for (uint8 i = 0; i < 3; ++i) + { + SpawnLoc[i] = Base[random][i]; + } + Creature* pCreature = NULL; + switch(entry) + { + case 17906: //GARGOYLE + + if (!FirstBossDead && (WaveCount == 1 || WaveCount == 3)) + {//summon at tower + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][1]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + if (pCreature) + CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; + }else{//summon at gate + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_GARG_GATE][0]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][1]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + } + break; + case 17907: //FROST_WYRM , + if (FirstBossDead && WaveCount == 1) //summon at gate + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_WYRM_GATE][0],SpawnPointSpecial[SPAWN_WYRM_GATE][1],SpawnPointSpecial[SPAWN_WYRM_GATE][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + else + { + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0], SpawnPointSpecial[SPAWN_NEAR_TOWER][1],SpawnPointSpecial[SPAWN_NEAR_TOWER][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + if (pCreature) + CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; + } + break; + case 17908: //GIANT_INFERNAL + ++InfernalCount; + if (InfernalCount > 7) + InfernalCount = 0; + pCreature = me->SummonCreature(entry, InfernalPos[InfernalCount][0], InfernalPos[InfernalCount][1], InfernalPos[InfernalCount][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + default: + pCreature = me->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + + } + + if (pCreature) + { + // Increment Enemy Count to be used in World States and instance script + ++EnemyCount; + + pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCreature->setActive(true); + switch(entry) + { + case NECROMANCER: + case ABOMINATION: + case GHOUL: + case BANSHEE: + case CRYPT_FIEND: + case GARGOYLE: + case FROST_WYRM: + case GIANT_INFERNAL: + case FEL_STALKER: + case RAGE_WINTERCHILL: + case ANETHERON: + case KAZROGAL: + case AZGALOR: + CAST_AI(hyjal_trashAI, pCreature->AI())->IsEvent = true; + break; + } + if (pInstance) + { + if (pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE) + pCreature->SetDisableReputationGain(true);//no repu for solo farming + } + // Check if Creature is a boss. + if (pCreature->isWorldBoss()) + { + if (!FirstBossDead) BossGUID[0] = pCreature->GetGUID(); + else BossGUID[1] = pCreature->GetGUID(); + CheckTimer = 5000; + } + } +} + +void hyjalAI::SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]) +{ + // 1 in 4 chance we give a rally yell. Not sure if the chance is offilike. + if (rand()%4 == 0) + Talk(RALLY); + + if (!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + InfernalCount = 0;//reset infernal count every new wave + + EnemyCount = pInstance->GetData(DATA_TRASH); + for (uint8 i = 0; i < 18; ++i) + { + if (wave[Count].Mob[i]) + SummonCreature(wave[Count].Mob[i], Base); + } + + if (!wave[Count].IsBoss) + { + uint32 stateValue = Count+1; + if (FirstBossDead) + stateValue -= 9; // Subtract 9 from it to give the proper wave number if we are greater than 8 + + // Set world state to our current wave number + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, stateValue); // Set world state to our current wave number + // Enable world state + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); // Enable world state + + pInstance->SetData(DATA_TRASH, EnemyCount); // Send data for instance script to update count + + if (!Debug) + NextWaveTimer = wave[Count].WaveTimer; + else + { + NextWaveTimer = 15000; + debug_log("TSCR: HyjalAI: debug mode is enabled. Next Wave in 15 seconds"); + } + } + else + { + // Set world state for waves to 0 to disable it. + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); + + // Set World State for enemies invading to 1. + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 1); + + Summon = false; + } + CheckTimer = 5000; +} + +void hyjalAI::StartEvent(Player* pPlayer) +{ + if (!pPlayer || IsDummy || !pInstance) + return; + + Talk(BEGIN); + + EventBegun = true; + Summon = true; + + NextWaveTimer = 15000; + CheckTimer = 5000; + PlayerGUID = pPlayer->GetGUID(); + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); + + DeSpawnVeins(); +} + +uint32 hyjalAI::GetInstanceData(uint32 Event) +{ + if (pInstance) + return pInstance->GetData(Event); + else error_log(ERROR_INST_DATA); + + return 0; +} + +void hyjalAI::Talk(uint32 id) +{ + std::list index; + for (uint8 i = 0; i < 9; ++i) + { + if (Faction == 0) // Alliance + { + if (JainaQuotes[i].id == id) + index.push_back(i); + } + else if (Faction == 1) // Horde + { + if (ThrallQuotes[i].id == id) + index.push_back(i); + } + } + + if (index.empty()) + return; // No quotes found, no use to continue + + uint8 ind = *(index.begin()) + rand()%index.size(); + + int32 YellId = 0; + if (Faction == 0) // Alliance + { + YellId = JainaQuotes[ind].textid; + } + else if (Faction == 1) // Horde + { + YellId = ThrallQuotes[ind].textid; + } + + if (YellId) + DoScriptText(YellId, me); +} + +void hyjalAI::Retreat() +{ + if (pInstance) + { + pInstance->SetData(TYPE_RETREAT,SPECIAL); + + if (Faction == 0) + { + pInstance->SetData(DATA_ALLIANCE_RETREAT, 1); + AddWaypoint(0,JainaWPs[0][0],JainaWPs[0][1],JainaWPs[0][2]); + AddWaypoint(1,JainaWPs[1][0],JainaWPs[1][1],JainaWPs[1][2]); + Start(false, false); + SetDespawnAtEnd(false);//move to center of alliance base + } + if (Faction == 1) + { + pInstance->SetData(DATA_HORDE_RETREAT, 1); + Creature* JainaDummy = me->SummonCreature(JAINA,JainaDummySpawn[0][0],JainaDummySpawn[0][1],JainaDummySpawn[0][2],JainaDummySpawn[0][3],TEMPSUMMON_TIMED_DESPAWN,60000); + if (JainaDummy) + { + JainaDummy->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + CAST_AI(hyjalAI, JainaDummy->AI())->IsDummy = true; + DummyGuid = JainaDummy->GetGUID(); + } + AddWaypoint(0,JainaDummySpawn[1][0],JainaDummySpawn[1][1],JainaDummySpawn[1][2]); + Start(false, false); + SetDespawnAtEnd(false);//move to center of alliance base + } + } + SpawnVeins(); + Overrun = true; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//cant talk after overrun event started +} + +void hyjalAI::SpawnVeins() +{ + if (Faction == 0) + { + if (VeinsSpawned[0])//prevent any buggers + return; + for (uint8 i = 0; i<7; ++i) + { + GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); + if (gem) + VeinGUID[i]=gem->GetGUID(); + } + VeinsSpawned[0] = true; + }else{ + if (VeinsSpawned[1]) + return; + for (uint8 i = 7; i<14; ++i) + { + GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); + if (gem) + VeinGUID[i]=gem->GetGUID(); + } + VeinsSpawned[1] = true; + } +} + +void hyjalAI::DeSpawnVeins() +{ + if (!pInstance) + return; + if (Faction == 1) + { + Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (!pUnit)return; + hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); + if (!ai)return; + for (uint8 i = 0; i<7; ++i) + { + if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) + gem->Delete(); + } + } else if (Faction) + { + Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_THRALL)); + if (!pUnit)return; + hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); + if (!ai)return; + for (uint8 i = 7; i<14; ++i) + { + if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) + gem->Delete(); + } + } +} + +void hyjalAI::UpdateAI(const uint32 diff) +{ + if (IsDummy) + { + if (MassTeleportTimer < diff && DoMassTeleport) + { + DoCast(me, SPELL_MASS_TELEPORT, false); + DoMassTeleport = false; + } else MassTeleportTimer -= diff; + return; + } + if (DoHide) + { + DoHide = false; + switch(me->GetEntry()) + { + case JAINA: + if (pInstance && pInstance->GetData(DATA_ALLIANCE_RETREAT)) + { + me->SetVisibility(VISIBILITY_OFF); + HideNearPos(me->GetPositionX(), me->GetPositionY()); + HideNearPos(5037.76, -1889.71); + for (uint8 i = 0; i < 92; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); + + } + else me->SetVisibility(VISIBILITY_ON); + break; + case THRALL: //thrall + if (pInstance && pInstance->GetData(DATA_HORDE_RETREAT)) + { + me->SetVisibility(VISIBILITY_OFF); + HideNearPos(me->GetPositionX(), me->GetPositionY()); + HideNearPos(5563, -2763.19); + HideNearPos(5542.2, -2629.36); + for (uint8 i = 0; i < 65; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); + + } + else me->SetVisibility(VISIBILITY_ON); + break; + } + } + if (DoRespawn) + { + if (RespawnTimer <= diff) + { + DoRespawn = false; + RespawnNearPos(me->GetPositionX(), me->GetPositionY()); + if (Faction == 0) + { + RespawnNearPos(5037.76, -1889.71); + } else if (Faction == 1) + { + RespawnNearPos(5563, -2763.19); + RespawnNearPos(5542.2, -2629.36); + } + me->SetVisibility(VISIBILITY_ON); + }else{ + RespawnTimer -= diff; + me->SetVisibility(VISIBILITY_OFF); + } + return; + } + if (Overrun) + DoOverrun(Faction, diff); + if (bRetreat) + { + if (RetreatTimer <= diff) + { + IsDummy = true; + bRetreat = false; + HideNearPos(me->GetPositionX(), me->GetPositionY()); + switch(me->GetEntry()) + { + case JAINA://jaina + HideNearPos(5037.76, -1889.71); + break; + case THRALL://thrall + HideNearPos(5563, -2763.19); + HideNearPos(5542.2, -2629.36); + HideNearPos(5603.75, -2853.12); + break; + } + me->SetVisibility(VISIBILITY_OFF); + } else RetreatTimer -= diff; + } + + if (!EventBegun) + return; + + if (Summon) + { + if (pInstance && EnemyCount) + { + EnemyCount = pInstance->GetData(DATA_TRASH); + if (!EnemyCount) + NextWaveTimer = 5000; + } + + if (NextWaveTimer <= diff) + { + if (Faction == 0) + SummonNextWave(AllianceWaves, WaveCount, AllianceBase); + else if (Faction == 1) + SummonNextWave(HordeWaves, WaveCount, HordeBase); + ++WaveCount; + } else NextWaveTimer -= diff; + } + + if (CheckTimer <= diff) + { + for (uint8 i = 0; i < 2; ++i) + { + if (BossGUID[i]) + { + Unit* pUnit = Unit::GetUnit((*me), BossGUID[i]); + if (pUnit && (!pUnit->isAlive())) + { + if (BossGUID[i] == BossGUID[0]) + { + Talk(INCOMING); + FirstBossDead = true; + } + else if (BossGUID[i] == BossGUID[1]) + { + Talk(SUCCESS); + SecondBossDead = true; + } + EventBegun = false; + CheckTimer = 0; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + BossGUID[i] = 0; + if (pInstance) + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); // Reset world state for enemies to disable it + } + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + if (!UpdateVictim()) + return; + + for (uint8 i = 0; i < 3; ++i) + { + if (Spell[i].SpellId) + { + if (SpellTimer[i] <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + Unit *pTarget = NULL; + + switch(Spell[i].TargetType) + { + case TARGETTYPE_SELF: pTarget = me; break; + case TARGETTYPE_RANDOM: pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); break; + case TARGETTYPE_VICTIM: pTarget = me->getVictim(); break; + } + + if (pTarget && pTarget->isAlive()) + { + DoCast(pTarget, Spell[i].SpellId); + SpellTimer[i] = Spell[i].Cooldown; + } + } else SpellTimer[i] -= diff; + } + } + + DoMeleeAttackIfReady(); +} +void hyjalAI::JustDied(Unit* /*killer*/) +{ + if (IsDummy)return; + me->Respawn(); + me->SetVisibility(VISIBILITY_OFF); + DoRespawn = true; + RespawnTimer = 120000; + Talk(DEATH); + Summons.DespawnAll();//despawn all wave's summons + if (pInstance) + {//reset encounter if boss is despawned (ex: thrall is killed, boss despawns, event stucks at inprogress) + if (pInstance->GetData(DATA_RAGEWINTERCHILLEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_ANETHERONEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_KAZROGALEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_AZGALOREVENT) == IN_PROGRESS) + pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); + pInstance->SetData(DATA_RESET_RAIDDAMAGE, NULL);//reset damage on die + } +} +void hyjalAI::HideNearPos(float x, float y) +{ + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + // First get all creatures. + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + // Get Creatures + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + (*itr)->SetVisibility(VISIBILITY_OFF); + (*itr)->setFaction(35);//make them friendly so mobs won't attack them + } + } +} +void hyjalAI::RespawnNearPos(float x, float y) +{ + CellPair p(Trinity::ComputeCellPair(x, y)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::RespawnDo u_do; + Trinity::WorldObjectWorker worker(me, u_do); + TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); + cell.Visit(p, obj_worker, *me->GetMap()); +} +void hyjalAI::WaypointReached(uint32 i) +{ + if (i == 1 || (i == 0 && me->GetEntry() == THRALL)) + { + me->MonsterYell(YELL_HURRY,0,0); + WaitForTeleport = true; + TeleportTimer = 20000; + if (me->GetEntry() == JAINA) + DoCast(me, SPELL_MASS_TELEPORT, false); + if (me->GetEntry() == THRALL && DummyGuid) + { + Unit* Dummy = Unit::GetUnit((*me),DummyGuid); + if (Dummy) + { + CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->DoMassTeleport = true; + CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->MassTeleportTimer = 20000; + Dummy->CastSpell(me, SPELL_MASS_TELEPORT, false); + } + } + //do some talking + //all alive guards walk near here + CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + // First get all creatures. + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive() && (*itr) != me && (*itr)->GetEntry() != JAINA) + { + if (!(*itr)->IsWithinDist(me, 60)) + (*itr)->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + float x, y, z; + (*itr)->SetDefaultMovementType(IDLE_MOTION_TYPE); + (*itr)->GetMotionMaster()->Initialize(); + float range = 10; + if (me->GetEntry() == THRALL)range = 20; + me->GetNearPoint(me, x, y, z, range, 0, me->GetAngle((*itr))); + (*itr)->GetMotionMaster()->MovePoint(0, x+irand(-5,5), y+irand(-5,5), me->GetPositionZ()); + } + } + } + } +} +void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) +{ + npc_escortAI::UpdateAI(diff); + if (WaitForTeleport) + { + if (TeleportTimer <= diff) + { + CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive()) + { + (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); + (*itr)->setFaction(35);//make them friendly so mobs won't attack them + (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + DoCast(me, SPELL_TELEPORT_VISUAL); + bRetreat = true; + RetreatTimer = 1000; + } + + WaitForTeleport = false; + Teleported = true; + }TeleportTimer -= diff; + } + if (!Teleported) + return; + Overrun = false;//execute once + switch(faction) + { + case 0://alliance + for (uint8 i = 0; i < 92; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); + + for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(GHOUL, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 3; ++i)//summon 3 abominations + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(ABOMINATION, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles + { + Creature* pUnit = me->SummonCreature(GARGOYLE, AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + pUnit->SetHomePosition(AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3]); + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + break; + case 1://horde + for (uint8 i = 0; i < 65; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); + + for (uint8 i = 0; i < 26; ++i)//summon infernals + { + Creature* pUnit = me->SummonCreature(GIANT_INFERNAL, InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + pUnit->SetHomePosition(InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3]); + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(GHOUL, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 5; ++i)//summon 5 abominations + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(ABOMINATION, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + break; + } +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h new file mode 100644 index 00000000000..5c75465b7b4 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h @@ -0,0 +1,248 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_HYJALAI_H +#define SC_HYJALAI_H + +#include "hyjal.h" +#include "ScriptedEscortAI.h" + +// Trash Mobs summoned in waves +#define NECROMANCER 17899//done +#define ABOMINATION 17898//done +#define GHOUL 17895//done +#define BANSHEE 17905//done +#define CRYPT_FIEND 17897//done +#define GARGOYLE 17906//done +#define FROST_WYRM 17907//done +#define GIANT_INFERNAL 17908//done +#define FEL_STALKER 17916//done + +#define JAINA 17772 +#define THRALL 17852 +#define TYRANDE 17948 + +#define ANCIENT_VEIN 185557 +#define FLAMEOBJECT 182592 + +// Bosses summoned after every 8 waves +#define RAGE_WINTERCHILL 17767 +#define ANETHERON 17808 +#define KAZROGAL 17888 +#define AZGALOR 17842 +#define ARCHIMONDE 17968 + +#define SPELL_TELEPORT_VISUAL 41232 +#define SPELL_MASS_TELEPORT 16807 + +//Spells for Jaina +#define SPELL_BRILLIANCE_AURA 31260 // The database must handle this spell via creature_addon(it should, but is removed in evade..) +#define SPELL_BLIZZARD 31266 +#define SPELL_PYROBLAST 31263 +#define SPELL_SUMMON_ELEMENTALS 31264 + +//Thrall spells +#define SPELL_CHAIN_LIGHTNING 31330 +#define SPELL_SUMMON_DIRE_WOLF 31331 + +struct Wave +{ + uint32 Mob[18]; // Stores Creature Entries to be summoned in Waves + uint32 WaveTimer; // The timer before the next wave is summoned + bool IsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that +}; + +static Wave AllianceWaves[]= // Waves that will be summoned in the Alliance Base +{ // Rage Winterchill Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron + {RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, + // Anetheron Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, GHOUL, GHOUL, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + // All 8 Waves are summoned, summon Anatheron + {ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} +}; + +static Wave HordeWaves[]= // Waves that are summoned in the Horde base +{ // Kaz'Rogal Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, + // All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor + {KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, + // Azgalor Wave 1-8 + {ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, FROST_WYRM, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, + {GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, 0, 0, 0, 0, 180000, false}, + {FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, + // All 8 Waves are summoned, summon Azgalor + {AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} +}; + +enum TargetType // Used in the spell cast system for the AI +{ + TARGETTYPE_SELF = 0, + TARGETTYPE_RANDOM = 1, + TARGETTYPE_VICTIM = 2, +}; + +struct Yells +{ + uint32 id; // Used to determine the type of yell (attack, rally, etc) + int32 textid; // The text id to be yelled +}; + +enum YellId +{ + ATTACKED = 0, // Used when attacked and set in combat + BEGIN = 1, // Used when the event is begun + INCOMING = 2, // Used to warn the raid that another wave phase is coming + RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned + FAILURE = 4, // Used when raid has failed (unsure where to place) + SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase + DEATH = 6, // Used on death +}; + +static Yells JainaQuotes[]= +{ + {ATTACKED, -1534000}, + {ATTACKED, -1534001}, + {INCOMING, -1534002}, + {BEGIN, -1534003}, + {RALLY, -1534004}, + {RALLY, -1534005}, + {FAILURE, -1534006}, + {SUCCESS, -1534007}, + {DEATH, -1534008}, +}; + +static Yells ThrallQuotes[]= +{ + {ATTACKED, -1534009}, + {ATTACKED, -1534010}, + {INCOMING, -1534011}, + {BEGIN, -1534012}, + {RALLY, -1534013}, + {RALLY, -1534014}, + {FAILURE, -1534015}, + {SUCCESS, -1534016}, + {DEATH, -1534017}, +}; + +struct hyjalAI : public npc_escortAI +{ + hyjalAI(Creature *c); + + void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat + + void EnterEvadeMode(); // Send creature back to spawn location and evade. + + void EnterCombat(Unit * /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack + + void UpdateAI(const uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells. + + void JustDied(Unit* /*killer*/); // Called on death, informs the raid that they have failed. + + void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal + { + Faction = _faction; + } + + void Retreat(); // "Teleport" (teleport visual + set invisible) all friendly creatures away from the base. + + void SpawnVeins(); + void DeSpawnVeins(); + void JustSummoned(Creature *summoned); + void SummonedCreatureDespawn(Creature* summoned); + void HideNearPos(float x, float y); + void RespawnNearPos(float x, float y); + void WaypointReached(uint32 i); + void DoOverrun(uint32 faction, const uint32 diff); + void MoveInLineOfSight(Unit *who); + + void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base + + // Summons the next wave, calls SummonCreature + void SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]); + + void StartEvent(Player* player); // Begins the event by gossip click + + uint32 GetInstanceData(uint32 Event); // Gets instance data for this instance, used to check if raid has gotten past a certain point and can access the next phase + + void Talk(uint32 id); // Searches for the appropriate yell and sound and uses it to inform the raid of various things + + public: + ScriptedInstance* pInstance; + + uint64 PlayerGUID; + uint64 BossGUID[2]; + uint64 VeinGUID[14]; + + uint32 NextWaveTimer; + uint32 WaveCount; + uint32 CheckTimer; + uint32 Faction; + uint32 EnemyCount; + uint32 RetreatTimer; + + bool EventBegun; + bool FirstBossDead; + bool SecondBossDead; + bool Summon; + bool bRetreat; + bool Debug; + bool VeinsSpawned[2]; + uint8 InfernalCount; + SummonList Summons; + bool Overrun; + bool Teleported; + bool WaitForTeleport; + uint32 TeleportTimer; + uint32 OverrunCounter; + uint32 OverrunCounter2; + uint32 InfernalPoint; + uint32 RespawnTimer; + bool DoRespawn; + bool DoHide; + bool IsDummy; + uint32 MassTeleportTimer; + bool DoMassTeleport; + uint64 DummyGuid; + + struct Spell + { + uint32 SpellId; + uint32 Cooldown; + uint32 TargetType; + }Spell[3]; + + private: + uint32 SpellTimer[3]; + //std::list CreatureList; +}; +#endif + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp new file mode 100644 index 00000000000..c4cf9ede397 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp @@ -0,0 +1,1440 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" +#include "hyjalAI.h" + +#define SPELL_METEOR 33814 //infernal visual +#define SPELL_IMMOLATION 37059 +#define SPELL_FLAME_BUFFET 31724 +#define NPC_TRIGGER 21987 //World Trigger (Tiny) +#define MODEL_INVIS 11686 //invisible model + +float HordeWPs[8][3]=//basic waypoints from spawn to leader +{ + {5492.91, -2404.61, 1462.63}, + {5531.76, -2460.87, 1469.55}, + {5554.58, -2514.66, 1476.12}, + {5554.16, -2567.23, 1479.90}, + {5540.67, -2625.99, 1480.89}, + {5508.16, -2659.20, 1480.15},//random rush starts from here + {5489.62, -2704.05, 1482.18}, + {5457.04, -2726.26, 1485.10} +}; +float AllianceWPs[8][3]=//basic waypoints from spawn to leader +{ + {4896.08, -1576.35, 1333.65}, + {4898.68, -1615.02, 1329.48}, + {4907.12, -1667.08, 1321.00}, + {4963.18, -1699.35, 1340.51}, + {4989.16, -1716.67, 1335.74},//first WP in the base, after the gate + {5026.27, -1736.89, 1323.02}, + {5037.77, -1770.56, 1324.36}, + {5067.23, -1789.95, 1321.17} +}; + +float FrostWyrmWPs[3][3]=//waypoints for the frost wyrms in horde base +{ + {5580.82, -2628.83, 1528.28}, + {5550.90, -2667.16, 1505.45}, + {5459.64, -2725.91, 1484.83} +}; + +float GargoyleWPs[3][3]=//waypoints for the gargoyles in horde base +{ + {5533.66, -2634.32, 1495.33}, + {5517.88, -2712.05, 1490.54}, + {5459.64, -2725.91, 1484.83} +}; + +float FlyPathWPs[3][3]=//waypoints for the gargoyls and frost wyrms in horde base in wave 1/3 +{ + {5531.96, -2772.83, 1516.68}, + {5498.32, -2734.84, 1497.01}, + {5456.67, -2725.48, 1493.08} +}; + +float AllianceOverrunWP[55][3]=//waypoints in the alliance base used in the end in the cleaning wave +{ + {4976.37,-1708.02,1339.43},//0spawn + {4994.83,-1725.52,1333.25},//1 start + {4982.92,-1753.7,1330.69},//2 end + {4996.75,-1721.47,1332.95},//3 start + {5015.74,-1755.05,1322.49},//4 + {4998.68,-1773.44,1329.59},//5 + {4994.83,-1725.52,1333.25},//6 start + {5022.8,-1735.46,1323.53},//7 + {5052.15,-1729.02,1320.88},//8 + {5082.43,-1726.29,1327.87},//9 + {4994.83,-1725.52,1333.25},//10 start + {5018.92,-1751.14,1322.19},//11 + {5040.09,-1792.09,1322.1},//12 + {4994.83,-1725.52,1333.25},//13 start + {5023.47,-1748.1,1322.51},//14 + {5013.43,-1842.39,1322.07},//15 + {4994.83,-1725.52,1333.25},//16 start + {5020.8,-1756.86,1322.2},//17 + {5019.53,-1824.6,1321.96},//18 + {5043.42,-1853.75,1324.52},//19 + {5053.02,-1864.13,1330.36},//20 + {5062.49,-1852.47,1330.49},//21 + {5015.27, -1738.77, 1324.83},//35//start 22 + {5027.97, -1775.25, 1321.87},//34 23 + {5015.94, -1821.24, 1321.86},//33 24 + {4983.25, -1857.4, 1320.48},//32 25 + {4981.51, -1883.7, 1322.34},//31 26 + {5002.33, -1893.98, 1325.88},//30 27 + {5049.32, -1886.54, 1331.69},//29 28 + {5089.68, -1846.88, 1328.99},//28 29 + {5127.90, -1825.14, 1335.58},//27 30 + {5163.27, -1789.08, 1337.04},//26 31 + {5138.97, -1755.88, 1334.57},//25 32 + {5096.63, -1742.22, 1329.61},//24 33 + {5065.81, -1729.43, 1325.66},//23 34 + {5049.32, -1726.31, 1320.64},//22 start + {5081.07, -1902.10, 1346.36},//36 abo start + {5107.65, -1912.03, 1356.49},//37 + {5132.83, -1927.07, 1362.42},//38 + {5147.78, -1954.41, 1365.98},//39 + {5164.96, -1966.48, 1367.04},//40 + {5189.04, -1961.06, 1367.90},//41 + {5212.27, -1975.30, 1365.58},//42 + {5221.82, -1994.18, 1364.97},//43 end1 + {5202.23, -1994.94, 1367.59},//44 end2 + {5279.94, -2049.68, 1311.38},//45 garg1 + {5289.15, -2219.06, 1291.12},//46 garg2 + {5202.07, -2136.10, 1305.07},//47 garg3 + {5071.52, -2425.63, 1454.48},//48 garg4 + {5120.65, -2467.92, 1463.93},//49 garg5 + {5283.04, -2043.26, 1300.11},//50 garg target1 + {5313.22, -2207.60, 1290.06},//51 garg target2 + {5180.41, -2121.87, 1292.62},//52 garg target3 + {5088.68, -2432.04, 1441.73},//53 garg target4 + {5111.26, -2454.73, 1449.63}//54 garg target5 + +}; + +float HordeOverrunWP[21][3]=//waypoints in the horde base used in the end in the cleaning wave +{ + {5490.72,-2702.94,1482.14},//0 start + {5469.77,-2741.34,1486.95}, + {5439.47,-2771.02,1494.59}, + {5408.85,-2811.92,1505.68}, + {5423.87,-2857.80,1515.55}, + {5428.19,-2898.15,1524.61}, + {5394.59,-2930.05,1528.23}, + {5351.11,-2935.80,1532.24}, + {5312.37,-2959.06,1536.21}, + {5264.93,-2989.80,1545.70}, + {5256.63,-3056.16,1559.24}, + {5267.32,-3119.55,1575.36}, + {5305.61,-3139.88,1586.38}, + {5330.56,-3135.37,1588.58}, + {5365.87,-3139.78,1583.96}, + {5389.39,-3163.57,1582.57},//15 end + {5500.86,-2669.89,1481.04},//16 start + {5472.08,-2715.14,1483.55}, + {5450.11,-2721.47,1485.61}, + {5433.25,-2712.93,1493.02},//19 end 1 + {5429.91,-2718.44,1493.42}//20 end 2 +}; + +hyjal_trashAI::hyjal_trashAI(Creature *c) : npc_escortAI(c) +{ + pInstance = c->GetInstanceData(); + IsEvent = false; + Delay = 0; + LastOverronPos = 0; + IsOverrun = false; + OverrunType = 0; + SetupOverrun = false; + faction = 0; + useFlyPath = false; + damageTaken = 0; + Reset(); +} + +void hyjal_trashAI::DamageTaken(Unit *done_by, uint32 &damage) +{ + if (done_by->GetTypeId() == TYPEID_PLAYER || (done_by->GetTypeId() == TYPEID_UNIT && CAST_CRE(done_by)->isPet())) + { + damageTaken += damage; + if (pInstance) + pInstance->SetData(DATA_RAIDDAMAGE,damage);//store raid's damage + } +} + +void hyjal_trashAI::UpdateAI(const uint32 /*diff*/) +{ + if (IsOverrun && !SetupOverrun) + { + SetupOverrun = true; + if (faction == 0) + { + if (me->GetEntry() == GARGOYLE) + { + DummyTarget[0] = AllianceOverrunWP[50+OverrunType][0]; //+OverrunType 0 - 4 + DummyTarget[1] = AllianceOverrunWP[50+OverrunType][1]; + DummyTarget[2] = AllianceOverrunWP[50+OverrunType][2]; + } + if (me->GetEntry() == ABOMINATION) + { + for (uint8 i = 0; i < 4; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); + AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); + AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); + AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); + AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); + AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); + AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); + + AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); + AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); + AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); + AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); + AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); + AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); + AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); + AddWaypoint(18, AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2]); + me->SetHomePosition(AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 18; + Start(true, true); + break; + case 1: + AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); + AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); + AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); + AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); + AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); + AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); + AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); + + AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); + AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); + AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); + AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); + AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); + AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); + AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); + AddWaypoint(18, AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2]); + me->SetHomePosition(AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 18; + Start(true, true); + break; + default: + for (uint8 i = 22; i < 36; ++i) + AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); + + SetDespawnAtEnd(true); + LastOverronPos = 17; + Start(true, true); + break; + } + } + if (me->GetEntry() == GHOUL) + { + for (uint8 i = 0; i < 4; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(4, AllianceOverrunWP[1][0]+irand(-3,3), AllianceOverrunWP[1][1]+irand(-3,3), AllianceOverrunWP[1][2]); + AddWaypoint(5, AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2]); + me->SetHomePosition(AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 5; + Start(true, true); + break; + case 1: + AddWaypoint(4, AllianceOverrunWP[3][0]+irand(-3,3), AllianceOverrunWP[3][1]+irand(-3,3), AllianceOverrunWP[3][2]); + AddWaypoint(5, AllianceOverrunWP[4][0]+irand(-3,3), AllianceOverrunWP[4][1]+irand(-3,3), AllianceOverrunWP[4][2]); + AddWaypoint(6, AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2]); + me->SetHomePosition(AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 2: + AddWaypoint(4, AllianceOverrunWP[6][0]+irand(-3,3), AllianceOverrunWP[6][1]+irand(-3,3), AllianceOverrunWP[6][2]); + AddWaypoint(5, AllianceOverrunWP[7][0]+irand(-3,3), AllianceOverrunWP[7][1]+irand(-3,3), AllianceOverrunWP[7][2]); + AddWaypoint(6, AllianceOverrunWP[8][0]+irand(-3,3), AllianceOverrunWP[8][1]+irand(-3,3), AllianceOverrunWP[8][2]); + AddWaypoint(7, AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2]); + me->SetHomePosition(AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 7; + Start(true, true); + break; + case 3: + AddWaypoint(4, AllianceOverrunWP[10][0]+irand(-3,3), AllianceOverrunWP[10][1]+irand(-3,3), AllianceOverrunWP[10][2]); + AddWaypoint(5, AllianceOverrunWP[11][0]+irand(-3,3), AllianceOverrunWP[11][1]+irand(-3,3), AllianceOverrunWP[11][2]); + AddWaypoint(6, AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2]); + me->SetHomePosition(AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 4: + AddWaypoint(4, AllianceOverrunWP[13][0]+irand(-3,3), AllianceOverrunWP[13][1]+irand(-3,3), AllianceOverrunWP[13][2]); + AddWaypoint(5, AllianceOverrunWP[14][0]+irand(-3,3), AllianceOverrunWP[14][1]+irand(-3,3), AllianceOverrunWP[14][2]); + AddWaypoint(6, AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2]); + me->SetHomePosition(AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 5: + AddWaypoint(4, AllianceOverrunWP[16][0]+irand(-3,3), AllianceOverrunWP[16][1]+irand(-3,3), AllianceOverrunWP[16][2]); + AddWaypoint(5, AllianceOverrunWP[17][0]+irand(-3,3), AllianceOverrunWP[17][1]+irand(-3,3), AllianceOverrunWP[17][2]); + AddWaypoint(6, AllianceOverrunWP[18][0]+irand(-3,3), AllianceOverrunWP[18][1]+irand(-3,3), AllianceOverrunWP[18][2]); + AddWaypoint(7, AllianceOverrunWP[19][0]+irand(-3,3), AllianceOverrunWP[19][1]+irand(-3,3), AllianceOverrunWP[19][2]); + AddWaypoint(8, AllianceOverrunWP[20][0]+irand(-3,3), AllianceOverrunWP[20][1]+irand(-3,3), AllianceOverrunWP[20][2]); + AddWaypoint(9, AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2]); + me->SetHomePosition(AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 9; + Start(true, true); + break; + default: + for (uint8 i = 22; i < 36; ++i) + AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 17; + Start(true, true); + break; + } + } + } + if (faction == 1) + { + if (me->GetEntry() == GHOUL) + { + for (uint8 i = 0; i < 6; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); + AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); + AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); + AddWaypoint(8, HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2]); + me->SetHomePosition(HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 8; + Start(true, true); + break; + case 1: + AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); + AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); + AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); + AddWaypoint(8, HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2]); + me->SetHomePosition(HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 8; + Start(true, true); + break; + default: + for (uint8 i = 0; i < 16; ++i) + AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 21; + Start(true, true); + break; + } + } + if (me->GetEntry() == ABOMINATION) + { + for (uint8 i = 0; i < 6; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-10,10), HordeWPs[i][1]+irand(-10,10), HordeWPs[i][2]); + for (uint8 i = 0; i < 16; ++i) + AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 21; + Start(true, true); + } + } + } +} + +void hyjal_trashAI::JustDied(Unit * /*victim*/) +{ + if (!pInstance) + return; + if (IsEvent && !me->isWorldBoss()) + pInstance->SetData(DATA_TRASH, 0);//signal trash is dead + + if ((pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE && !me->isWorldBoss()) || (damageTaken < me->GetMaxHealth()/4 && me->isWorldBoss())) + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);//no loot +} + +struct mob_giant_infernalAI : public hyjal_trashAI +{ + mob_giant_infernalAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + meteor = false;//call once! + CanMove = false; + Delay = rand()%30000; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(MODEL_INVIS); + pGo = false; + pos = 0; + Reset(); + } + + bool meteor; + bool CanMove; + bool WpEnabled; + bool pGo; + uint32 pos; + uint32 spawnTimer; + uint32 FlameBuffetTimer; + bool imol; + + void Reset() + { + spawnTimer = 2000; + FlameBuffetTimer= 2000; + imol = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 0 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Delay <= diff) + { + Delay=0; + }else{ + Delay-=diff; + return; + } + if (!meteor) + { + float x,y,z; + me->GetPosition(x,y,z); + Creature* trigger = me->SummonCreature(NPC_TRIGGER,x+8,y+8,z+25+rand()%10,me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,1000); + if (trigger) + { + trigger->SetVisibility(VISIBILITY_OFF); + trigger->setFaction(me->getFaction()); + trigger->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + trigger->CastSpell(me,SPELL_METEOR,true); + } + me->GetMotionMaster()->Clear(); + meteor = true; + } else if (!CanMove){ + if (spawnTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); + CanMove = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && !pInstance->GetData(DATA_HORDE_RETREAT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } else if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && pInstance->GetData(DATA_HORDE_RETREAT)){ + //do overrun + } + } + } else spawnTimer -= diff; + } + if (!CanMove)return; + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, HordeWPs[7][0]+irand(-3,3), HordeWPs[7][1]+irand(-3,3), HordeWPs[7][2]);//HordeWPs[7] infront of thrall + Start(true, true); + SetDespawnAtEnd(false); + } + } + } + + if (!UpdateVictim()) + return; + if (!imol) + { + DoCast(me, SPELL_IMMOLATION); + imol=true; + } + if (FlameBuffetTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAME_BUFFET, true); + FlameBuffetTimer = 7000; + } else FlameBuffetTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_giant_infernal(Creature* pCreature) +{ + return new mob_giant_infernalAI(pCreature); +} + +#define SPELL_DISEASE_CLOUD 31607 +#define SPELL_KNOCKDOWN 31610 + +struct mob_abominationAI : public hyjal_trashAI +{ + mob_abominationAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 KnockDownTimer; + uint32 pos; + void Reset() + { + KnockDownTimer = 10000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + if (i == LastOverronPos && IsOverrun) + { + if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) + { + me->setDeathState(DEAD); + me->RemoveCorpse(); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!me->HasAura(SPELL_DISEASE_CLOUD)) + DoCast(me, SPELL_DISEASE_CLOUD); + if (!UpdateVictim()) + return; + if (KnockDownTimer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + KnockDownTimer = 15000+rand()%10000; + } else KnockDownTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_abomination(Creature* pCreature) +{ + return new mob_abominationAI(pCreature); +} + +#define SPELL_FRENZY 31540 + +struct mob_ghoulAI : public hyjal_trashAI +{ + mob_ghoulAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 FrenzyTimer; + uint32 pos; + uint32 MoveTimer; + bool RandomMove; + void Reset() + { + FrenzyTimer = 5000+rand()%5000; + MoveTimer = 2000; + RandomMove = false; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + if (i == LastOverronPos && IsOverrun) + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); + if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) + { + me->setDeathState(DEAD); + me->RemoveCorpse(); + } + + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (FrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + FrenzyTimer = 15000+rand()%15000; + } else FrenzyTimer -= diff; + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_ghoul(Creature* pCreature) +{ + return new mob_ghoulAI(pCreature); +} + +#define SPELL_RAISE_DEAD_1 31617 +#define SPELL_RAISE_DEAD_2 31624 +#define SPELL_RAISE_DEAD_3 31625 +#define SPELL_SHADOW_BOLT 31627 + +struct mob_necromancerAI : public hyjal_trashAI +{ + mob_necromancerAI(Creature* c) : hyjal_trashAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + SummonList summons; + bool pGo; + uint32 ShadowBoltTimer; + uint32 pos; + void Reset() + { + ShadowBoltTimer = 1000+rand()%5000; + summons.DespawnAll(); + } + + void JustSummoned(Creature* summon) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true); + if (pTarget && summon) + summon->Attack(pTarget,false); + summons.Summon(summon); + } + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoSpawnCreature(17902,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + DoSpawnCreature(17902,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + case 1: + DoSpawnCreature(17903,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + DoSpawnCreature(17903,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + case 2: + DoSpawnCreature(RAND(17902,17903),3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(true, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(true, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (ShadowBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + ShadowBoltTimer = 20000+rand()%10000; + } else ShadowBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_necromancer(Creature* pCreature) +{ + return new mob_necromancerAI(pCreature); +} + +#define SPELL_BANSHEE_CURSE 31651 +#define SPELL_BANSHEE_WAIL 38183 +#define SPELL_ANTI_MAGIC_SHELL 31662 + +struct mob_bansheeAI : public hyjal_trashAI +{ + mob_bansheeAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 CourseTimer; + uint32 WailTimer; + uint32 ShellTimer; + uint32 pos; + void Reset() + { + CourseTimer = 20000+rand()%5000; + WailTimer = 15000+rand()%5000; + ShellTimer = 50000+rand()%10000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (CourseTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BANSHEE_CURSE); + CourseTimer = 20000+rand()%5000; + } else CourseTimer -= diff; + if (WailTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BANSHEE_WAIL); + WailTimer = 15000+rand()%5000; + } else WailTimer -= diff; + if (ShellTimer <= diff) + { + DoCast(me, SPELL_ANTI_MAGIC_SHELL); + ShellTimer = 50000+rand()%10000; + } else ShellTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_banshee(Creature* pCreature) +{ + return new mob_bansheeAI(pCreature); +} + +#define SPELL_WEB 28991 + +struct mob_crypt_fiendAI : public hyjal_trashAI +{ + mob_crypt_fiendAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 WebTimer; + uint32 pos; + void Reset() + { + WebTimer = 20000+rand()%5000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + + } + } + } + if (!UpdateVictim()) + return; + if (WebTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WEB); + WebTimer = 20000+rand()%5000; + } else WebTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_crypt_fiend(Creature* pCreature) +{ + return new mob_crypt_fiendAI(pCreature); +} + +#define SPELL_MANA_BURN 31729 + +struct mob_fel_stalkerAI : public hyjal_trashAI +{ + mob_fel_stalkerAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 ManaBurnTimer; + uint32 pos; + void Reset() + { + ManaBurnTimer = 9000+rand()%5000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + + } + } + } + if (!UpdateVictim()) + return; + if (ManaBurnTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MANA_BURN); + ManaBurnTimer = 9000+rand()%5000; + } else ManaBurnTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_fel_stalker(Creature* pCreature) +{ + return new mob_fel_stalkerAI(pCreature); +} + +#define SPELL_FROST_BREATH 31688 + +struct mob_frost_wyrmAI : public hyjal_trashAI +{ + mob_frost_wyrmAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 FrostBreathTimer; + uint32 pos; + uint32 MoveTimer; + + void Reset() + { + FrostBreathTimer = 5000; + MoveTimer = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 2 && pInstance && !IsOverrun) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + { + me->AddThreat(pTarget,0.0); + DoCast(pTarget, SPELL_FROST_BREATH, true); + } + } + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_TRASH, 0);//signal trash is dead + + float x,y,z; + me->GetPosition(x,y,z); + z = me->GetMap()->GetHeight(x, y, z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + me->GetMap()->CreatureRelocation(me, x,y,z,0); + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + { + CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); + npc_escortAI::UpdateAI(diff); + } + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (!useFlyPath) + { + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FrostWyrmWPs[i][0], FrostWyrmWPs[i][1], FrostWyrmWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else{//fly path FlyPathWPs + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (!me->IsWithinDist(me->getVictim(), 25)){ + if (MoveTimer <= diff) + { + me->GetMotionMaster()->MoveChase(me->getVictim()); + MoveTimer = 2000; + } else MoveTimer-=diff; + } + + if (FrostBreathTimer <= diff) + { + if (!me->IsWithinDist(me->getVictim(), 25)) + { + DoCast(me->getVictim(), SPELL_FROST_BREATH); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + FrostBreathTimer = 4000; + } + } else FrostBreathTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_frost_wyrm(Creature* pCreature) +{ + return new mob_frost_wyrmAI(pCreature); +} + +#define SPELL_GARGOYLE_STRIKE 31664 + +struct mob_gargoyleAI : public hyjal_trashAI +{ + mob_gargoyleAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + DummyTarget[0] = 0;DummyTarget[1] = 0;DummyTarget[2] = 0; + Reset(); + } + + bool pGo; + uint32 StrikeTimer; + uint32 pos; + uint32 MoveTimer; + float Zpos; + bool forcemove; + + void Reset() + { + forcemove = true; + Zpos = 10.0; + StrikeTimer = 2000+rand()%5000; + MoveTimer = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 2 && pInstance && !IsOverrun) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + { + me->AddThreat(pTarget,0.0); + DoCast(pTarget, SPELL_GARGOYLE_STRIKE, true); + } + } + } + + void JustDied(Unit *victim) + { + float x,y,z; + me->GetPosition(x,y,z); + z = me->GetMap()->GetHeight(x, y, z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + me->GetMap()->CreatureRelocation(me, x,y,z,0); + hyjal_trashAI::JustDied(victim); + } + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + { + CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); + npc_escortAI::UpdateAI(diff); + } + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (!useFlyPath) + { + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, GargoyleWPs[i][0]+irand(-10,10), GargoyleWPs[i][1]+irand(-10,10), GargoyleWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else{//fly path FlyPathWPs + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (IsOverrun && !UpdateVictim()) + { + if (faction == 0)//alliance + { + if (StrikeTimer <= diff) + { + me->CastSpell(DummyTarget[0],DummyTarget[1],DummyTarget[2],SPELL_GARGOYLE_STRIKE,false); + StrikeTimer = 2000+rand()%1000; + } else StrikeTimer -= diff; + } + } + if (!UpdateVictim()) + return; + if (!me->IsWithinDist(me->getVictim(), 20) || forcemove) + { + forcemove = false; + if (forcemove) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + me->Attack(pTarget,false); + } + if (MoveTimer <= diff) + { + float x,y,z; + me->getVictim()->GetPosition(x,y,z); + me->GetMotionMaster()->MovePoint(0,x,y,z+Zpos); + Zpos-=1.0; + if (Zpos <= 0)Zpos=0; + MoveTimer = 2000; + } else MoveTimer-=diff; + } + if (StrikeTimer <= diff) + { + if (me->IsWithinDist(me->getVictim(), 20)) + { + DoCast(me->getVictim(), SPELL_GARGOYLE_STRIKE); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + StrikeTimer = 2000+rand()%1000; + } else StrikeTimer=0; + } else StrikeTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_gargoyle(Creature* pCreature) +{ + return new mob_gargoyleAI(pCreature); +} + +#define SPELL_EXPLODING_SHOT 7896 + +struct alliance_riflemanAI : public Scripted_NoMovementAI +{ + alliance_riflemanAI(Creature *c) : Scripted_NoMovementAI(c) + { + Reset(); + } + + uint32 ExplodeTimer; + + void JustDied(Unit* /*who*/) + { + } + + void Reset() + { + ExplodeTimer = 5000+rand()%5000; + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && me->IsHostileTo(who)) + { + //float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, 30)) + AttackStart(who); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + if (ExplodeTimer <= diff) + { + if (!me->IsWithinDistInMap(me->getVictim(), 30)) + { + EnterEvadeMode(); + return; + } + int dmg = 500+rand()%700; + me->CastCustomSpell(me->getVictim(), SPELL_EXPLODING_SHOT, &dmg, 0, 0, false); + ExplodeTimer = 5000+rand()%5000; + } else ExplodeTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_alliance_rifleman(Creature* pCreature) +{ + return new alliance_riflemanAI(pCreature); +} + +void AddSC_hyjal_trash() +{ + Script *newscript = new Script; + newscript->Name = "mob_giant_infernal"; + newscript->GetAI = &GetAI_mob_giant_infernal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_abomination"; + newscript->GetAI = &GetAI_mob_abomination; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ghoul"; + newscript->GetAI = &GetAI_mob_ghoul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_necromancer"; + newscript->GetAI = &GetAI_mob_necromancer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_banshee"; + newscript->GetAI = &GetAI_mob_banshee; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crypt_fiend"; + newscript->GetAI = &GetAI_mob_crypt_fiend; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_stalker"; + newscript->GetAI = &GetAI_mob_fel_stalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_wyrm"; + newscript->GetAI = &GetAI_mob_frost_wyrm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_gargoyle"; + newscript->GetAI = &GetAI_mob_gargoyle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "alliance_rifleman"; + newscript->GetAI = &GetAI_alliance_rifleman; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h new file mode 100644 index 00000000000..21ee4bc06cc --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h @@ -0,0 +1,35 @@ + +#ifndef SC_HYJAL_TRASH_AI_H +#define SC_HYJAL_TRASH_AI_H + +#include "hyjal.h" +#include "ScriptedEscortAI.h" + +#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies + +struct hyjal_trashAI : public npc_escortAI +{ + hyjal_trashAI(Creature *c); + + void UpdateAI(const uint32 diff); + + void JustDied(Unit* /*killer*/); + + void DamageTaken(Unit *done_by, uint32 &damage); + + public: + ScriptedInstance* pInstance; + bool IsEvent; + uint32 Delay; + uint32 LastOverronPos; + bool IsOverrun; + bool SetupOverrun; + uint32 OverrunType; + uint8 faction; + bool useFlyPath; + uint32 damageTaken; + float DummyTarget[3]; + + //private: +}; +#endif diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp new file mode 100644 index 00000000000..e89d518c5bc --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp @@ -0,0 +1,324 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Mount_Hyjal +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +enum eEnums +{ + MAX_ENCOUNTER = 5, + + GO_ANCIENT_GEM = 185557 +}; +/* Battle of Mount Hyjal encounters: +0 - Rage Winterchill event +1 - Anetheron event +2 - Kaz'rogal event +3 - Azgalor event +4 - Archimonde event +*/ + +struct instance_mount_hyjal : public ScriptedInstance +{ + instance_mount_hyjal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + std::list m_uiAncientGemGUID; + + uint64 RageWinterchill; + uint64 Anetheron; + uint64 Kazrogal; + uint64 Azgalor; + uint64 Archimonde; + uint64 JainaProudmoore; + uint64 Thrall; + uint64 TyrandeWhisperwind; + uint64 HordeGate; + uint64 ElfGate; + + uint32 Trash; + + uint32 hordeRetreat; + uint32 allianceRetreat; + bool ArchiYell; + + uint32 RaidDamage; + + #define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more." + #define YELL_EFFORTS_NAME "Archimonde" + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiAncientGemGUID.clear(); + + RageWinterchill = 0; + Anetheron = 0; + Kazrogal = 0; + Azgalor = 0; + Archimonde = 0; + JainaProudmoore = 0; + Thrall = 0; + TyrandeWhisperwind = 0; + HordeGate = 0; + ElfGate = 0; + ArchiYell = false; + RaidDamage = 0; + + Trash = 0; + + hordeRetreat = 0; + allianceRetreat = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 182060: + HordeGate = pGo->GetGUID(); + if (allianceRetreat) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + case 182061: + ElfGate = pGo->GetGUID(); + if (hordeRetreat) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + case GO_ANCIENT_GEM: + m_uiAncientGemGUID.push_back(pGo->GetGUID()); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17767: RageWinterchill = pCreature->GetGUID(); break; + case 17808: Anetheron = pCreature->GetGUID(); break; + case 17888: Kazrogal = pCreature->GetGUID(); break; + case 17842: Azgalor = pCreature->GetGUID(); break; + case 17968: Archimonde = pCreature->GetGUID(); break; + case 17772: JainaProudmoore = pCreature->GetGUID(); break; + case 17852: Thrall = pCreature->GetGUID(); break; + case 17948: TyrandeWhisperwind = pCreature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_RAGEWINTERCHILL: return RageWinterchill; + case DATA_ANETHERON: return Anetheron; + case DATA_KAZROGAL: return Kazrogal; + case DATA_AZGALOR: return Azgalor; + case DATA_ARCHIMONDE: return Archimonde; + case DATA_JAINAPROUDMOORE: return JainaProudmoore; + case DATA_THRALL: return Thrall; + case DATA_TYRANDEWHISPERWIND: return TyrandeWhisperwind; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_RAGEWINTERCHILLEVENT: m_auiEncounter[0] = data; break; + case DATA_ANETHERONEVENT: + m_auiEncounter[1] = data; + break; + case DATA_KAZROGALEVENT: m_auiEncounter[2] = data; break; + case DATA_AZGALOREVENT: + { + m_auiEncounter[3] = data; + if (data == DONE) + { + if (ArchiYell)break; + ArchiYell = true; + + Creature* pCreature = instance->GetCreature(Azgalor); + if (pCreature) + { + Creature* pUnit = pCreature->SummonCreature(21987,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,10000); + + Map* pMap = pCreature->GetMap(); + if (pMap->IsDungeon() && pUnit) + { + pUnit->SetVisibility(VISIBILITY_OFF); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()) + { + WorldPacket data(SMSG_MESSAGECHAT, 200); + pUnit->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,YELL_EFFORTS,0,YELL_EFFORTS_NAME,i->getSource()->GetGUID()); + i->getSource()->GetSession()->SendPacket(&data); + + WorldPacket data2(SMSG_PLAY_SOUND, 4); + data2 << 10986; + i->getSource()->GetSession()->SendPacket(&data2); + } + } + } + } + } + } + break; + case DATA_ARCHIMONDEEVENT: m_auiEncounter[4] = data; break; + case DATA_RESET_TRASH_COUNT: Trash = 0; break; + + case DATA_TRASH: + if (data) Trash = data; + else Trash--; + DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash); + break; + case TYPE_RETREAT: + if (data == SPECIAL) + { + if (!m_uiAncientGemGUID.empty()) + { + for (std::list::const_iterator itr = m_uiAncientGemGUID.begin(); itr != m_uiAncientGemGUID.end(); ++itr) + { + //don't know how long it expected + DoRespawnGameObject(*itr,DAY); + } + } + } + break; + case DATA_ALLIANCE_RETREAT: + allianceRetreat = data; + HandleGameObject(HordeGate, true); + SaveToDB(); + break; + case DATA_HORDE_RETREAT: + hordeRetreat = data; + HandleGameObject(ElfGate, true); + SaveToDB(); + break; + case DATA_RAIDDAMAGE: + RaidDamage += data; + if (RaidDamage >= MINRAIDDAMAGE) + RaidDamage = MINRAIDDAMAGE; + break; + case DATA_RESET_RAIDDAMAGE: + RaidDamage = 0; + break; + } + + debug_log("TSCR: Instance Hyjal: Instance data updated for event %u (Data=%u)",type,data); + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] + << " " << allianceRetreat << " " << hordeRetreat + << " " << RaidDamage; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_RAGEWINTERCHILLEVENT: return m_auiEncounter[0]; + case DATA_ANETHERONEVENT: return m_auiEncounter[1]; + case DATA_KAZROGALEVENT: return m_auiEncounter[2]; + case DATA_AZGALOREVENT: return m_auiEncounter[3]; + case DATA_ARCHIMONDEEVENT: return m_auiEncounter[4]; + case DATA_TRASH: return Trash; + case DATA_ALLIANCE_RETREAT: return allianceRetreat; + case DATA_HORDE_RETREAT: return hordeRetreat; + case DATA_RAIDDAMAGE: return RaidDamage; + } + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4] >> allianceRetreat >> hordeRetreat >> RaidDamage; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_mount_hyjal(Map* pMap) +{ + return new instance_mount_hyjal(pMap); +} + +void AddSC_instance_mount_hyjal() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_hyjal"; + newscript->GetInstanceData = &GetInstanceData_instance_mount_hyjal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp new file mode 100644 index 00000000000..91c9e274b83 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Captain_Skarloc +SD%Complete: 75 +SDComment: Missing adds, missing waypoints to move up to Thrall once spawned + speech before enter combat. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define SAY_ENTER -1560000 +#define SAY_TAUNT1 -1560001 +#define SAY_TAUNT2 -1560002 +#define SAY_SLAY1 -1560003 +#define SAY_SLAY2 -1560004 +#define SAY_DEATH -1560005 + +#define SPELL_HOLY_LIGHT 29427 +#define SPELL_CLEANSE 29380 +#define SPELL_HAMMER_OF_JUSTICE 13005 +#define SPELL_HOLY_SHIELD 31904 +#define SPELL_DEVOTION_AURA 8258 +#define SPELL_CONSECRATION 38385 + +struct boss_captain_skarlocAI : public ScriptedAI +{ + boss_captain_skarlocAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Holy_Light_Timer; + uint32 Cleanse_Timer; + uint32 HammerOfJustice_Timer; + uint32 HolyShield_Timer; + uint32 DevotionAura_Timer; + uint32 Consecration_Timer; + + void Reset() + { + Holy_Light_Timer = 20000 + rand()%10000; + Cleanse_Timer = 10000; + HammerOfJustice_Timer = 20000 + rand()%15000; + HolyShield_Timer = 240000; + DevotionAura_Timer = 3000; + Consecration_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + //This is not correct. Should taunt Thrall before engage in combat + DoScriptText(SAY_TAUNT1, me); + DoScriptText(SAY_TAUNT2, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + pInstance->SetData(TYPE_THRALL_PART1, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Holy_Light + if (Holy_Light_Timer <= diff) + { + DoCast(me, SPELL_HOLY_LIGHT); + Holy_Light_Timer = 30000; + } else Holy_Light_Timer -= diff; + + //Cleanse + if (Cleanse_Timer <= diff) + { + DoCast(me, SPELL_CLEANSE); + Cleanse_Timer = 10000; + } else Cleanse_Timer -= diff; + + //Hammer of Justice + if (HammerOfJustice_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); + HammerOfJustice_Timer = 60000; + } else HammerOfJustice_Timer -= diff; + + //Holy Shield + if (HolyShield_Timer <= diff) + { + DoCast(me, SPELL_HOLY_SHIELD); + HolyShield_Timer = 240000; + } else HolyShield_Timer -= diff; + + //Devotion_Aura + if (DevotionAura_Timer <= diff) + { + DoCast(me, SPELL_DEVOTION_AURA); + DevotionAura_Timer = 45000 + rand()%10000; + } else DevotionAura_Timer -= diff; + + //Consecration + if (Consecration_Timer <= diff) + { + //DoCast(me->getVictim(), SPELL_CONSECRATION); + Consecration_Timer = 5000 + rand()%5000; + } else Consecration_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_captain_skarloc(Creature* pCreature) +{ + return new boss_captain_skarlocAI (pCreature); +} + +void AddSC_boss_captain_skarloc() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_captain_skarloc"; + newscript->GetAI = &GetAI_boss_captain_skarloc; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp new file mode 100644 index 00000000000..2c2ad96ddb7 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Epoch_Hunter +SD%Complete: 60 +SDComment: Missing spawns pre-event, missing speech to be coordinated with rest of escort event. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define SAY_ENTER1 -1560013 +#define SAY_ENTER2 -1560014 +#define SAY_ENTER3 -1560015 +#define SAY_AGGRO1 -1560016 +#define SAY_AGGRO2 -1560017 +#define SAY_SLAY1 -1560018 +#define SAY_SLAY2 -1560019 +#define SAY_BREATH1 -1560020 +#define SAY_BREATH2 -1560021 +#define SAY_DEATH -1560022 + +#define SPELL_SAND_BREATH 31914 +#define SPELL_IMPENDING_DEATH 31916 +#define SPELL_MAGIC_DISRUPTION_AURA 33834 +#define SPELL_WING_BUFFET 31475 + +struct boss_epoch_hunterAI : public ScriptedAI +{ + boss_epoch_hunterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SandBreath_Timer; + uint32 ImpendingDeath_Timer; + uint32 WingBuffet_Timer; + uint32 Mda_Timer; + + void Reset() + { + SandBreath_Timer = 8000 + rand()%8000; + ImpendingDeath_Timer = 25000 + rand()%5000; + WingBuffet_Timer = 35000; + Mda_Timer = 40000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2), me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + pInstance->SetData(TYPE_THRALL_PART4, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sand Breath + if (SandBreath_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me->getVictim(), SPELL_SAND_BREATH); + + DoScriptText(RAND(SAY_BREATH1,SAY_BREATH2), me); + + SandBreath_Timer = 10000 + rand()%10000; + } else SandBreath_Timer -= diff; + + if (ImpendingDeath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_IMPENDING_DEATH); + ImpendingDeath_Timer = 25000+rand()%5000; + } else ImpendingDeath_Timer -= diff; + + if (WingBuffet_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_WING_BUFFET); + WingBuffet_Timer = 25000+rand()%10000; + } else WingBuffet_Timer -= diff; + + if (Mda_Timer <= diff) + { + DoCast(me, SPELL_MAGIC_DISRUPTION_AURA); + Mda_Timer = 15000; + } else Mda_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_epoch_hunter(Creature* pCreature) +{ + return new boss_epoch_hunterAI (pCreature); +} + +void AddSC_boss_epoch_hunter() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_epoch_hunter"; + newscript->GetAI = &GetAI_boss_epoch_hunter; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp new file mode 100644 index 00000000000..dae0f5390b1 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp @@ -0,0 +1,190 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Luetenant_Drake +SD%Complete: 70 +SDComment: Missing proper code for patrolling area after being spawned. Script for GO (barrels) quest 10283 +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" +#include "ScriptedEscortAI.h" + +/*###### +## go_barrel_old_hillsbrad +######*/ + +bool GOHello_go_barrel_old_hillsbrad(Player* /*pPlayer*/, GameObject* pGO) +{ + if (ScriptedInstance* pInstance = pGO->GetInstanceData()) + { + if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE) + return false; + + pInstance->SetData(TYPE_BARREL_DIVERSION, IN_PROGRESS); + } + + return false; +} + +/*###### +## boss_lieutenant_drake +######*/ + +#define SAY_ENTER -1560006 +#define SAY_AGGRO -1560007 +#define SAY_SLAY1 -1560008 +#define SAY_SLAY2 -1560009 +#define SAY_MORTAL -1560010 +#define SAY_SHOUT -1560011 +#define SAY_DEATH -1560012 + +#define SPELL_WHIRLWIND 31909 +#define SPELL_HAMSTRING 9080 +#define SPELL_MORTAL_STRIKE 31911 +#define SPELL_FRIGHTENING_SHOUT 33789 + +struct Location +{ + uint32 wpId; + float x; + float y; + float z; +}; + +static Location DrakeWP[]= +{ + {0, 2125.84, 88.2535, 54.8830}, + {1, 2111.01, 93.8022, 52.6356}, + {2, 2106.70, 114.753, 53.1965}, + {3, 2107.76, 138.746, 52.5109}, + {4, 2114.83, 160.142, 52.4738}, + {5, 2125.24, 178.909, 52.7283}, + {6, 2151.02, 208.901, 53.1551}, + {7, 2177.00, 233.069, 52.4409}, + {8, 2190.71, 227.831, 53.2742}, + {9, 2178.14, 214.219, 53.0779}, + {10, 2154.99, 202.795, 52.6446}, + {11, 2132.00, 191.834, 52.5709}, + {12, 2117.59, 166.708, 52.7686}, + {13, 2093.61, 139.441, 52.7616}, + {14, 2086.29, 104.950, 52.9246}, + {15, 2094.23, 81.2788, 52.6946}, + {16, 2108.70, 85.3075, 53.3294}, + {17, 2125.50, 88.9481, 54.7953}, + {18, 2128.20, 70.9763, 64.4221} +}; + +struct boss_lieutenant_drakeAI : public ScriptedAI +{ + boss_lieutenant_drakeAI(Creature *c) : ScriptedAI(c) {} + + bool CanPatrol; + uint32 wpId; + + uint32 Whirlwind_Timer; + uint32 Fear_Timer; + uint32 MortalStrike_Timer; + uint32 ExplodingShout_Timer; + + void Reset() + { + CanPatrol = true; + wpId = 0; + + Whirlwind_Timer = 20000; + Fear_Timer = 30000; + MortalStrike_Timer = 45000; + ExplodingShout_Timer = 25000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + //TODO: make this work + if (CanPatrol && wpId == 0) + { + me->GetMotionMaster()->MovePoint(DrakeWP[0].wpId, DrakeWP[0].x, DrakeWP[0].y, DrakeWP[0].z); + ++wpId; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Whirlwind + if (Whirlwind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + Whirlwind_Timer = 20000+rand()%5000; + } else Whirlwind_Timer -= diff; + + //Fear + if (Fear_Timer <= diff) + { + DoScriptText(SAY_SHOUT, me); + DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); + Fear_Timer = 25000+rand()%10000; + } else Fear_Timer -= diff; + + //Mortal Strike + if (MortalStrike_Timer <= diff) + { + DoScriptText(SAY_MORTAL, me); + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + MortalStrike_Timer = 20000+rand()%10000; + } else MortalStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_lieutenant_drake(Creature* pCreature) +{ + return new boss_lieutenant_drakeAI (pCreature); +} + +void AddSC_boss_lieutenant_drake() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_barrel_old_hillsbrad"; + newscript->pGOHello = &GOHello_go_barrel_old_hillsbrad; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lieutenant_drake"; + newscript->GetAI = &GetAI_boss_lieutenant_drake; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp new file mode 100644 index 00000000000..fa0b7c14595 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp @@ -0,0 +1,238 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Old_Hillsbrad +SD%Complete: 75 +SDComment: If thrall escort fail, all parts will reset. In future, save sub-parts and continue from last known. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define MAX_ENCOUNTER 6 + +#define THRALL_ENTRY 17876 +#define TARETHA_ENTRY 18887 +#define EPOCH_ENTRY 18096 + +#define DRAKE_ENTRY 17848 + +#define QUEST_ENTRY_DIVERSION 10283 +#define LODGE_QUEST_TRIGGER 20155 + +struct instance_old_hillsbrad : public ScriptedInstance +{ + instance_old_hillsbrad(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 mBarrelCount; + uint32 mThrallEventCount; + + uint64 ThrallGUID; + uint64 TarethaGUID; + uint64 EpochGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + mBarrelCount = 0; + mThrallEventCount = 0; + ThrallGUID = 0; + TarethaGUID = 0; + EpochGUID = 0; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Old Hillsbrad: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void UpdateQuestCredit() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->KilledMonsterCredit(LODGE_QUEST_TRIGGER,0); + } + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case THRALL_ENTRY: + ThrallGUID = pCreature->GetGUID(); + break; + case TARETHA_ENTRY: + TarethaGUID = pCreature->GetGUID(); + break; + case EPOCH_ENTRY: + EpochGUID = pCreature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + Player* pPlayer = GetPlayerInMap(); + + if (!pPlayer) + { + debug_log("TSCR: Instance Old Hillsbrad: SetData (Type: %u Data %u) cannot find any player.", type, data); + return; + } + + switch(type) + { + case TYPE_BARREL_DIVERSION: + { + if (data == IN_PROGRESS) + { + if (mBarrelCount >= 5) + return; + + ++mBarrelCount; + DoUpdateWorldState(WORLD_STATE_OH, mBarrelCount); + + debug_log("TSCR: Instance Old Hillsbrad: go_barrel_old_hillsbrad count %u",mBarrelCount); + + m_auiEncounter[0] = IN_PROGRESS; + + if (mBarrelCount == 5) + { + UpdateQuestCredit(); + pPlayer->SummonCreature(DRAKE_ENTRY, 2128.43, 71.01, 64.42, 1.74, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000); + m_auiEncounter[0] = DONE; + } + } + break; + } + case TYPE_THRALL_EVENT: + { + if (data == FAIL) + { + if (mThrallEventCount <= 20) + { + ++mThrallEventCount; + m_auiEncounter[1] = NOT_STARTED; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); + m_auiEncounter[2] = NOT_STARTED; + m_auiEncounter[3] = NOT_STARTED; + m_auiEncounter[4] = NOT_STARTED; + m_auiEncounter[5] = NOT_STARTED; + } + else if (mThrallEventCount > 20) + { + m_auiEncounter[1] = data; + m_auiEncounter[2] = data; + m_auiEncounter[3] = data; + m_auiEncounter[4] = data; + m_auiEncounter[5] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); + } + } + else + m_auiEncounter[1] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall escort event adjusted to data %u.",data); + break; + } + case TYPE_THRALL_PART1: + m_auiEncounter[2] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part I adjusted to data %u.",data); + break; + case TYPE_THRALL_PART2: + m_auiEncounter[3] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part II adjusted to data %u.",data); + break; + case TYPE_THRALL_PART3: + m_auiEncounter[4] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part III adjusted to data %u.",data); + break; + case TYPE_THRALL_PART4: + m_auiEncounter[5] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part IV adjusted to data %u.",data); + break; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_BARREL_DIVERSION: + return m_auiEncounter[0]; + case TYPE_THRALL_EVENT: + return m_auiEncounter[1]; + case TYPE_THRALL_PART1: + return m_auiEncounter[2]; + case TYPE_THRALL_PART2: + return m_auiEncounter[3]; + case TYPE_THRALL_PART3: + return m_auiEncounter[4]; + case TYPE_THRALL_PART4: + return m_auiEncounter[5]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THRALL: + return ThrallGUID; + case DATA_TARETHA: + return TarethaGUID; + case DATA_EPOCH: + return EpochGUID; + } + return 0; + } +}; +InstanceData* GetInstanceData_instance_old_hillsbrad(Map* pMap) +{ + return new instance_old_hillsbrad(pMap); +} + +void AddSC_instance_old_hillsbrad() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_old_hillsbrad"; + newscript->GetInstanceData = &GetInstanceData_instance_old_hillsbrad; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp new file mode 100644 index 00000000000..08c63954db5 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp @@ -0,0 +1,658 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Old_Hillsbrad +SD%Complete: 40 +SDComment: Quest support: 10283, 10284. All friendly NPC's. Thrall waypoints fairly complete, missing many details, but possible to complete escort. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +/* ContentData +npc_erozion +npc_thrall_old_hillsbrad +npc_taretha +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "old_hillsbrad.h" + +#define QUEST_ENTRY_HILLSBRAD 10282 +#define QUEST_ENTRY_DIVERSION 10283 +#define QUEST_ENTRY_ESCAPE 10284 +#define QUEST_ENTRY_RETURN 10285 +#define ITEM_ENTRY_BOMBS 25853 + +#define GOSSIP_HELLO_EROZION1 "I need a pack of Incendiary Bombs." +#define GOSSIP_HELLO_EROZION2 "[PH] Teleport please, i'm tired." + +/*###### +## npc_erozion +######*/ + +bool GossipHello_npc_erozion(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance && pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE && !pPlayer->HasItemCount(ITEM_ENTRY_BOMBS,1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (!pPlayer->GetQuestRewardStatus(QUEST_ENTRY_RETURN) && pPlayer->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(9778, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_erozion(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_ENTRY_BOMBS, 1); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, ITEM_ENTRY_BOMBS, true); + } + pPlayer->SEND_GOSSIP_MENU(9515, pCreature->GetGUID()); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + } + return true; +} + +/*###### +## npc_thrall_old_hillsbrad +######*/ + +//Thrall texts +#define SAY_TH_START_EVENT_PART1 -1560023 +#define SAY_TH_ARMORY -1560024 +#define SAY_TH_SKARLOC_MEET -1560025 +#define SAY_TH_SKARLOC_TAUNT -1560026 +#define SAY_TH_START_EVENT_PART2 -1560027 +#define SAY_TH_MOUNTS_UP -1560028 +#define SAY_TH_CHURCH_END -1560029 +#define SAY_TH_MEET_TARETHA -1560030 +#define SAY_TH_EPOCH_WONDER -1560031 +#define SAY_TH_EPOCH_KILL_TARETHA -1560032 +#define SAY_TH_EVENT_COMPLETE -1560033 + +#define SAY_TH_RANDOM_LOW_HP1 -1560034 +#define SAY_TH_RANDOM_LOW_HP2 -1560035 + +#define SAY_TH_RANDOM_DIE1 -1560036 +#define SAY_TH_RANDOM_DIE2 -1560037 + +#define SAY_TH_RANDOM_AGGRO1 -1560038 +#define SAY_TH_RANDOM_AGGRO2 -1560039 +#define SAY_TH_RANDOM_AGGRO3 -1560040 +#define SAY_TH_RANDOM_AGGRO4 -1560041 + +#define SAY_TH_RANDOM_KILL1 -1560042 +#define SAY_TH_RANDOM_KILL2 -1560043 +#define SAY_TH_RANDOM_KILL3 -1560044 + +#define SAY_TH_LEAVE_COMBAT1 -1560045 +#define SAY_TH_LEAVE_COMBAT2 -1560046 +#define SAY_TH_LEAVE_COMBAT3 -1560047 + +//Taretha texts +#define SAY_TA_FREE -1560048 +#define SAY_TA_ESCAPED -1560049 + +//Misc for Thrall +#define SPELL_STRIKE 14516 +#define SPELL_SHIELD_BLOCK 12169 +#define SPELL_SUMMON_EROZION_IMAGE 33954 //if thrall dies during escort? + +#define SPEED_WALK (0.5f) +#define SPEED_RUN (1.0f) +#define SPEED_MOUNT (1.6f) + +#define THRALL_WEAPON_MODEL 22106 +#define THRALL_WEAPON_INFO 218169346 +#define THRALL_SHIELD_MODEL 18662 +#define THRALL_SHIELD_INFO 234948100 +#define THRALL_MODEL_UNEQUIPPED 17292 +#define THRALL_MODEL_EQUIPPED 18165 + +//Misc Creature entries +#define ENTRY_ARMORER 18764 +#define ENTRY_SCARLOC 17862 + +#define MOB_ENTRY_RIFLE 17820 +#define MOB_ENTRY_WARDEN 17833 +#define MOB_ENTRY_VETERAN 17860 +#define MOB_ENTRY_WATCHMAN 17814 +#define MOB_ENTRY_SENTRY 17815 + +#define MOB_ENTRY_BARN_GUARDSMAN 18092 +#define MOB_ENTRY_BARN_PROTECTOR 18093 +#define MOB_ENTRY_BARN_LOOKOUT 18094 + +#define MOB_ENTRY_CHURCH_GUARDSMAN 23175 +#define MOB_ENTRY_CHURCH_PROTECTOR 23179 +#define MOB_ENTRY_CHURCH_LOOKOUT 23177 + +#define MOB_ENTRY_INN_GUARDSMAN 23176 +#define MOB_ENTRY_INN_PROTECTOR 23180 +#define MOB_ENTRY_INN_LOOKOUT 23178 + +#define SKARLOC_MOUNT 18798 +#define SKARLOC_MOUNT_MODEL 18223 +#define EROZION_ENTRY 18723 +#define ENTRY_EPOCH 18096 + +//gossip items +#define GOSSIP_ID_START 9568 +#define GOSSIP_ID_SKARLOC1 9614 //I'm glad Taretha is alive. We now must find a way to free her... +#define GOSSIP_ITEM_SKARLOC1 "Taretha cannot see you, Thrall." +#define GOSSIP_ID_SKARLOC2 9579 //What do you mean by this? Is Taretha in danger? +#define GOSSIP_ITEM_SKARLOC2 "The situation is rather complicated, Thrall. It would be best for you to head into the mountains now, before more of Blackmoore's men show up. We'll make sure Taretha is safe." +#define GOSSIP_ID_SKARLOC3 9580 + +#define GOSSIP_ID_TARREN 9597 //tarren mill is beyond these trees +#define GOSSIP_ITEM_TARREN "We're ready, Thrall." + +#define GOSSIP_ID_COMPLETE 9578 //Thank you friends, I owe my freedom to you. Where is Taretha? I hoped to see her + +#define GOSSIP_ITEM_WALKING "[PH] Start walking." + +struct npc_thrall_old_hillsbradAI : public npc_escortAI +{ + npc_thrall_old_hillsbradAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + HadMount = false; + me->setActive(true); + } + + ScriptedInstance *pInstance; + + uint64 TarethaGUID; + + bool LowHp; + bool HadMount; + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch(i) + { + case 8: + SetRun(false); + me->SummonCreature(18764,2181.87,112.46,89.45,0.26,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 9: + DoScriptText(SAY_TH_ARMORY, me); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_MODEL); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_MODEL); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); + break; + case 10: + me->SetDisplayId(THRALL_MODEL_EQUIPPED); + break; + case 11: + SetRun(); + break; + case 15: + me->SummonCreature(MOB_ENTRY_RIFLE,2200.28,137.37,87.93,5.07,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2197.44,131.83,87.93,0.78,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2203.62,135.40,87.93,3.70,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2200.75,130.13,87.93,1.48,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 21: + me->SummonCreature(MOB_ENTRY_RIFLE,2135.80,154.01,67.45,4.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2144.36,151.87,67.74,4.46,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2142.12,154.41,67.12,4.56,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2138.08,155.38,67.24,4.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 25: + me->SummonCreature(MOB_ENTRY_RIFLE,2102.98,192.17,65.24,6.02,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2108.48,198.75,65.18,5.15,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2106.11,197.29,65.18,5.63,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2104.18,194.82,65.18,5.75,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 29: + DoScriptText(SAY_TH_SKARLOC_MEET, me); + me->SummonCreature(ENTRY_SCARLOC,2036.48,271.22,63.43,5.27,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + //temporary,skarloc should rather be triggered to walk up to thrall + break; + case 30: + SetEscortPaused(true); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetRun(false); + break; + case 31: + DoScriptText(SAY_TH_MOUNTS_UP, me); + DoMount(); + SetRun(); + break; + case 37: + //possibly regular patrollers? If so, remove this and let database handle them + me->SummonCreature(MOB_ENTRY_WATCHMAN,2124.26,522.16,56.87,3.99,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WATCHMAN,2121.69,525.37,57.11,4.01,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_SENTRY,2124.65,524.55,56.63,3.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 59: + me->SummonCreature(SKARLOC_MOUNT,2488.64,625.77,58.26,4.71,TEMPSUMMON_TIMED_DESPAWN,10000); + DoUnmount(); + HadMount = false; + SetRun(false); + break; + case 60: + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + //make horsie run off + SetEscortPaused(true); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(TYPE_THRALL_PART2, DONE); + SetRun(); + break; + case 64: + SetRun(false); + break; + case 68: + me->SummonCreature(MOB_ENTRY_BARN_PROTECTOR,2500.22,692.60,55.50,2.84,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_LOOKOUT,2500.13,696.55,55.51,3.38,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.55,693.64,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.94,695.81,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 71: + SetRun(); + break; + case 81: + SetRun(false); + break; + case 83: + me->SummonCreature(MOB_ENTRY_CHURCH_PROTECTOR,2627.33,646.82,56.03,4.28,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_LOOKOUT,2624.14,648.03,56.03,4.50,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2625.32,649.60,56.03,4.38,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2627.22,649.00,56.03,4.34,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + break; + case 84: + DoScriptText(SAY_TH_CHURCH_END, me); + SetRun(); + break; + case 91: + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + SetRun(false); + break; + case 93: + me->SummonCreature(MOB_ENTRY_INN_PROTECTOR,2652.71,660.31,61.93,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_LOOKOUT,2648.96,662.59,61.93,0.79,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2657.36,662.34,61.93,2.68,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2656.39,659.77,61.93,2.61,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 94: + if (uint64 TarethaGUID = pInstance->GetData64(DATA_TARETHA)) + { + if (Unit* Taretha = Unit::GetUnit((*me), TarethaGUID)) + DoScriptText(SAY_TA_ESCAPED, Taretha, me); + } + break; + case 95: + DoScriptText(SAY_TH_MEET_TARETHA, me); + pInstance->SetData(TYPE_THRALL_PART3,DONE); + SetEscortPaused(true); + break; + case 96: + DoScriptText(SAY_TH_EPOCH_WONDER, me); + break; + case 97: + DoScriptText(SAY_TH_EPOCH_KILL_TARETHA, me); + SetRun(); + break; + case 98: + //trigger epoch Yell("Thrall! Come outside and face your fate! ....") + //from here, thrall should not never be allowed to move to point 106 which he currently does. + break; + + case 106: + { + //trigger taretha to run down outside + if (Creature* Taretha = pInstance->instance->GetCreature(pInstance->GetData64(DATA_TARETHA))) + { + if (Player* pPlayer = GetPlayerForEscort()) + CAST_AI(npc_escortAI, (Taretha->AI()))->Start(false, true, pPlayer->GetGUID()); + } + + //kill credit Creature for quest + Map* pMap = me->GetMap(); + Map::PlayerList const& players = pMap->GetPlayers(); + if (!players.isEmpty() && pMap->IsDungeon()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->KilledMonsterCredit(20156,me->GetGUID()); + } + } + + //alot will happen here, thrall and taretha talk, erozion appear at spot to explain + me->SummonCreature(EROZION_ENTRY,2646.47,680.416,55.38,4.16,TEMPSUMMON_TIMED_DESPAWN,120000); + } + break; + case 108: + //last waypoint, just set Thrall invisible, respawn is turned off + me->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void Reset() + { + LowHp = false; + + if (HadMount) + DoMount(); + + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + DoUnmount(); + HadMount = false; + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + me->SetDisplayId(THRALL_MODEL_UNEQUIPPED); + } + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + DoScriptText(RAND(SAY_TH_LEAVE_COMBAT1,SAY_TH_LEAVE_COMBAT2,SAY_TH_LEAVE_COMBAT3), me); + } + } + void StartWP() + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetEscortPaused(false); + } + void DoMount() + { + me->Mount(SKARLOC_MOUNT_MODEL); + me->SetSpeed(MOVE_RUN,SPEED_MOUNT); + } + void DoUnmount() + { + me->Unmount(); + me->SetSpeed(MOVE_RUN,SPEED_RUN); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(RAND(SAY_TH_RANDOM_AGGRO1,SAY_TH_RANDOM_AGGRO2,SAY_TH_RANDOM_AGGRO3,SAY_TH_RANDOM_AGGRO4), me); + if (me->IsMounted()) + { + DoUnmount(); + HadMount = true; + } + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + //TODO: make Scarloc start into event instead, and not start attack directly + case MOB_ENTRY_BARN_GUARDSMAN: + case MOB_ENTRY_BARN_PROTECTOR: + case MOB_ENTRY_BARN_LOOKOUT: + case SKARLOC_MOUNT: + case EROZION_ENTRY: + break; + default: + summoned->AI()->AttackStart(me); + break; + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_TH_RANDOM_KILL1,SAY_TH_RANDOM_KILL2,SAY_TH_RANDOM_KILL3), me); + } + void JustDied(Unit *slayer) + { + if (pInstance) + pInstance->SetData(TYPE_THRALL_EVENT,FAIL); + + // Don't do a yell if he kills self (if player goes too far or at the end). + if (slayer == me) + return; + + DoScriptText(RAND(SAY_TH_RANDOM_DIE1,SAY_TH_RANDOM_DIE2), me); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + //TODO: add his abilities'n-crap here + if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) + { + DoScriptText(RAND(SAY_TH_RANDOM_LOW_HP1,SAY_TH_RANDOM_LOW_HP2), me); + LowHp = true; + } + } +}; + +CreatureAI* GetAI_npc_thrall_old_hillsbrad(Creature* pCreature) +{ + return new npc_thrall_old_hillsbradAI(pCreature); +} + +bool GossipHello_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + { + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + pPlayer->SendPreparedQuest(pCreature->GetGUID()); + } + + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance) + { + if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE && !pInstance->GetData(TYPE_THRALL_EVENT)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WALKING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START, pCreature->GetGUID()); + } + + if (pInstance->GetData(TYPE_THRALL_PART1) == DONE && !pInstance->GetData(TYPE_THRALL_PART2)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC1, pCreature->GetGUID()); + } + + if (pInstance->GetData(TYPE_THRALL_PART2) == DONE && !pInstance->GetData(TYPE_THRALL_PART3)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TARREN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_TARREN, pCreature->GetGUID()); + } + } + return true; +} + +bool GossipSelect_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pInstance) + { + pInstance->SetData(TYPE_THRALL_EVENT,IN_PROGRESS); + pInstance->SetData(TYPE_THRALL_PART1,IN_PROGRESS); + } + + DoScriptText(SAY_TH_START_EVENT_PART1, pCreature); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())) + pEscortAI->Start(true, true, pPlayer->GetGUID()); + + CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(100.0f);//not really needed, because it will not despawn if player is too far + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); + break; + + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC2, pCreature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+20: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC3, pCreature->GetGUID()); + pCreature->SummonCreature(SKARLOC_MOUNT,2038.81,270.26,63.20,5.41,TEMPSUMMON_TIMED_DESPAWN,12000); + if (pInstance) + pInstance->SetData(TYPE_THRALL_PART2,IN_PROGRESS); + + DoScriptText(SAY_TH_START_EVENT_PART2, pCreature); + + CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); + break; + + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pInstance) + pInstance->SetData(TYPE_THRALL_PART3,IN_PROGRESS); + CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); + break; + } + return true; +} + +/*###### +## npc_taretha +######*/ + +#define GOSSIP_ID_EPOCH1 9610 //Thank you for helping Thrall escape, friends. Now I only hope +#define GOSSIP_ITEM_EPOCH1 "Strange wizard?" +#define GOSSIP_ID_EPOCH2 9613 //Yes, friends. This man was no wizard of +#define GOSSIP_ITEM_EPOCH2 "We'll get you out. Taretha. Don't worry. I doubt the wizard would wander too far away." + +struct npc_tarethaAI : public npc_escortAI +{ + npc_tarethaAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void WaypointReached(uint32 i) + { + switch(i) + { + case 6: + DoScriptText(SAY_TA_FREE, me); + break; + case 7: + me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); + break; + } + } + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_taretha(Creature* pCreature) +{ + return new npc_tarethaAI(pCreature); +} + +bool GossipHello_npc_taretha(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance && pInstance->GetData(TYPE_THRALL_PART3) == DONE && pInstance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH1, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_taretha(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH2, pCreature->GetGUID()); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + { + pInstance->SetData(TYPE_THRALL_PART4,IN_PROGRESS); + if (pInstance->GetData64(DATA_EPOCH) == 0) + pCreature->SummonCreature(ENTRY_EPOCH,2639.13,698.55,65.43,4.59,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); + + if (uint64 ThrallGUID = pInstance->GetData64(DATA_THRALL)) + { + Creature* Thrall = (Unit::GetCreature((*pCreature), ThrallGUID)); + if (Thrall) + CAST_AI(npc_thrall_old_hillsbradAI, Thrall->AI())->StartWP(); + } + } + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_old_hillsbrad() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_erozion"; + newscript->pGossipHello = &GossipHello_npc_erozion; + newscript->pGossipSelect = &GossipSelect_npc_erozion; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thrall_old_hillsbrad"; + newscript->pGossipHello = &GossipHello_npc_thrall_old_hillsbrad; + newscript->pGossipSelect = &GossipSelect_npc_thrall_old_hillsbrad; + newscript->GetAI = &GetAI_npc_thrall_old_hillsbrad; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_taretha"; + newscript->pGossipHello = &GossipHello_npc_taretha; + newscript->pGossipSelect = &GossipSelect_npc_taretha; + newscript->GetAI = &GetAI_npc_taretha; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h new file mode 100644 index 00000000000..5c398cc2647 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_OLD_HILLSBRAD_H +#define DEF_OLD_HILLSBRAD_H + +#define TYPE_BARREL_DIVERSION 1 +#define TYPE_THRALL_EVENT 2 +#define TYPE_THRALL_PART1 3 +#define TYPE_THRALL_PART2 4 +#define TYPE_THRALL_PART3 5 +#define TYPE_THRALL_PART4 6 +#define DATA_THRALL 7 +#define DATA_TARETHA 8 +#define DATA_EPOCH 9 +#define WORLD_STATE_OH 2436 +#endif + diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp new file mode 100644 index 00000000000..6f6b9d1baa9 --- /dev/null +++ b/src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Celebras_the_Cursed +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_WRATH 21807 +#define SPELL_ENTANGLINGROOTS 12747 +#define SPELL_CORRUPT_FORCES 21968 + +struct celebras_the_cursedAI : public ScriptedAI +{ + celebras_the_cursedAI(Creature *c) : ScriptedAI(c) {} + + uint32 Wrath_Timer; + uint32 EntanglingRoots_Timer; + uint32 CorruptForces_Timer; + + void Reset() + { + Wrath_Timer = 8000; + EntanglingRoots_Timer = 2000; + CorruptForces_Timer = 30000; + } + + void EnterCombat(Unit * /*who*/) { } + + void JustDied(Unit* /*Killer*/) + { + me->SummonCreature(13716, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Wrath + if (Wrath_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + DoCast(pTarget, SPELL_WRATH); + Wrath_Timer = 8000; + } else Wrath_Timer -= diff; + + //EntanglingRoots + if (EntanglingRoots_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ENTANGLINGROOTS); + EntanglingRoots_Timer = 20000; + } else EntanglingRoots_Timer -= diff; + + //CorruptForces + if (CorruptForces_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_CORRUPT_FORCES); + CorruptForces_Timer = 20000; + } else CorruptForces_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_celebras_the_cursed(Creature* pCreature) +{ + return new celebras_the_cursedAI (pCreature); +} + +void AddSC_boss_celebras_the_cursed() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "celebras_the_cursed"; + newscript->GetAI = &GetAI_celebras_the_cursed; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp new file mode 100644 index 00000000000..d5b03ff218f --- /dev/null +++ b/src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp @@ -0,0 +1,95 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Landslide +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_KNOCKAWAY 18670 +#define SPELL_TRAMPLE 5568 +#define SPELL_LANDSLIDE 21808 + +struct boss_landslideAI : public ScriptedAI +{ + boss_landslideAI(Creature *c) : ScriptedAI(c) {} + + uint32 KnockAway_Timer; + uint32 Trample_Timer; + uint32 Landslide_Timer; + + void Reset() + { + KnockAway_Timer = 8000; + Trample_Timer = 2000; + Landslide_Timer = 0; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //KnockAway_Timer + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY); + KnockAway_Timer = 15000; + } else KnockAway_Timer -= diff; + + //Trample_Timer + if (Trample_Timer <= diff) + { + DoCast(me, SPELL_TRAMPLE); + Trample_Timer = 8000; + } else Trample_Timer -= diff; + + //Landslide + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + if (Landslide_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_LANDSLIDE); + Landslide_Timer = 60000; + } else Landslide_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_landslide(Creature* pCreature) +{ + return new boss_landslideAI (pCreature); +} + +void AddSC_boss_landslide() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_landslide"; + newscript->GetAI = &GetAI_boss_landslide; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp new file mode 100644 index 00000000000..b49b1a5d71f --- /dev/null +++ b/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp @@ -0,0 +1,131 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Noxxion +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_TOXICVOLLEY 21687 +#define SPELL_UPPERCUT 22916 + +struct boss_noxxionAI : public ScriptedAI +{ + boss_noxxionAI(Creature *c) : ScriptedAI(c) {} + + uint32 ToxicVolley_Timer; + uint32 Uppercut_Timer; + uint32 Adds_Timer; + uint32 Invisible_Timer; + bool Invisible; + + void Reset() + { + ToxicVolley_Timer = 7000; + Uppercut_Timer = 16000; + Adds_Timer = 19000; + Invisible_Timer = 15000; //Too much too low? + Invisible = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void SummonAdds(Unit* pVictim) + { + if (Creature *Add = DoSpawnCreature(13456, irand(-7,7), irand(-7,7), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 90000)) + Add->AI()->AttackStart(pVictim); + } + + void UpdateAI(const uint32 diff) + { + if (Invisible && Invisible_Timer <= diff) + { + //Become visible again + me->setFaction(14); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //Noxxion model + me->SetDisplayId(11172); + Invisible = false; + //me->m_canMove = true; + } else if (Invisible) + { + Invisible_Timer -= diff; + //Do nothing while invisible + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //ToxicVolley_Timer + if (ToxicVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TOXICVOLLEY); + ToxicVolley_Timer = 9000; + } else ToxicVolley_Timer -= diff; + + //Uppercut_Timer + if (Uppercut_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_UPPERCUT); + Uppercut_Timer = 12000; + } else Uppercut_Timer -= diff; + + //Adds_Timer + if (!Invisible && Adds_Timer <= diff) + { + //Inturrupt any spell casting + //me->m_canMove = true; + me->InterruptNonMeleeSpells(false); + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Invisible Model + me->SetDisplayId(11686); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + SummonAdds(me->getVictim()); + Invisible = true; + Invisible_Timer = 15000; + + Adds_Timer = 40000; + } else Adds_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_noxxion(Creature* pCreature) +{ + return new boss_noxxionAI (pCreature); +} + +void AddSC_boss_noxxion() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_noxxion"; + newscript->GetAI = &GetAI_boss_noxxion; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp new file mode 100644 index 00000000000..963863e89c8 --- /dev/null +++ b/src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp @@ -0,0 +1,109 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Princess_Theradras +SD%Complete: 100 +SDComment: +SDCategory: Maraudon +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_DUSTFIELD 21909 +#define SPELL_BOULDER 21832 +#define SPELL_THRASH 3391 +#define SPELL_REPULSIVEGAZE 21869 + +struct boss_ptheradrasAI : public ScriptedAI +{ + boss_ptheradrasAI(Creature *c) : ScriptedAI(c) {} + + uint32 Dustfield_Timer; + uint32 Boulder_Timer; + uint32 Thrash_Timer; + uint32 RepulsiveGaze_Timer; + + void Reset() + { + Dustfield_Timer = 8000; + Boulder_Timer = 2000; + Thrash_Timer = 5000; + RepulsiveGaze_Timer = 23000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*killer*/) + { + me->SummonCreature(12238,28.067,61.875,-123.405,4.67,TEMPSUMMON_TIMED_DESPAWN,600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Dustfield_Timer + if (Dustfield_Timer <= diff) + { + DoCast(me, SPELL_DUSTFIELD); + Dustfield_Timer = 14000; + } else Dustfield_Timer -= diff; + + //Boulder_Timer + if (Boulder_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + DoCast(pTarget, SPELL_BOULDER); + Boulder_Timer = 10000; + } else Boulder_Timer -= diff; + + //RepulsiveGaze_Timer + if (RepulsiveGaze_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REPULSIVEGAZE); + RepulsiveGaze_Timer = 20000; + } else RepulsiveGaze_Timer -= diff; + + //Thrash_Timer + if (Thrash_Timer <= diff) + { + DoCast(me, SPELL_THRASH); + Thrash_Timer = 18000; + } else Thrash_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ptheradras(Creature* pCreature) +{ + return new boss_ptheradrasAI (pCreature); +} + +void AddSC_boss_ptheradras() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_princess_theradras"; + newscript->GetAI = &GetAI_boss_ptheradras; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp new file mode 100644 index 00000000000..2d351d6c6a2 --- /dev/null +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -0,0 +1,500 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Onyxia +SD%Complete: 95 +SDComment: + Ground visual for Deep Breath effect; + Wing Buffet not ignoring armor; + Not summoning whelps on phase 3 (lacks info) + +SDCategory: Onyxia's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "onyxias_lair.h" + +enum eYells +{ + SAY_AGGRO = -1249000, + SAY_KILL = -1249001, + SAY_PHASE_2_TRANS = -1249002, + SAY_PHASE_3_TRANS = -1249003, + EMOTE_BREATH = -1249004, +}; + +enum eSpells +{ + // Phase 1 spells + SPELL_WING_BUFFET = 18500, + SPELL_FLAME_BREATH = 18435, + SPELL_CLEAVE = 68868, + SPELL_TAIL_SWEEP = 68867, + + // Phase 2 spells + SPELL_DEEP_BREATH = 23461, + SPELL_FIREBALL = 18392, + + //Not much choise about these. We have to make own defintion on the direction/start-end point + SPELL_BREATH_NORTH_TO_SOUTH = 17086, // 20x in "array" + SPELL_BREATH_SOUTH_TO_NORTH = 18351, // 11x in "array" + + SPELL_BREATH_EAST_TO_WEST = 18576, // 7x in "array" + SPELL_BREATH_WEST_TO_EAST = 18609, // 7x in "array" + + SPELL_BREATH_SE_TO_NW = 18564, // 12x in "array" + SPELL_BREATH_NW_TO_SE = 18584, // 12x in "array" + SPELL_BREATH_SW_TO_NE = 18596, // 12x in "array" + SPELL_BREATH_NE_TO_SW = 18617, // 12x in "array" + + //SPELL_BREATH = 21131, // 8x in "array", different initial cast than the other arrays + + // Phase 3 spells + SPELL_BELLOWING_ROAR = 18431, +}; + +struct sOnyxMove +{ + uint32 uiLocId; + uint32 uiLocIdEnd; + uint32 uiSpellId; + float fX, fY, fZ; +}; + +static sOnyxMove aMoveData[]= +{ + {0, 1, SPELL_BREATH_WEST_TO_EAST, -33.5561f, -182.682f, -56.9457f},//west + {1, 0, SPELL_BREATH_EAST_TO_WEST, -31.4963f, -250.123f, -55.1278f},//east + {2, 4, SPELL_BREATH_NW_TO_SE, 6.8951f, -180.246f, -55.896f},//north-west + {3, 5, SPELL_BREATH_NE_TO_SW, 10.2191f, -247.912f, -55.896f},//north-east + {4, 2, SPELL_BREATH_SE_TO_NW, -63.5156f, -240.096f, -55.477f},//south-east + {5, 3, SPELL_BREATH_SW_TO_NE, -58.2509f, -189.020f, -55.790f},//south-west + {6, 7, SPELL_BREATH_SOUTH_TO_NORTH, -65.8444f, -213.809f, -55.2985f},//south + {7, 6, SPELL_BREATH_NORTH_TO_SOUTH, 22.8763f, -217.152f, -55.0548f},//north +}; + +const Position MiddleRoomLocation = {-23.6155, -215.357, -55.7344}; + +static Position aSpawnLocations[3]= +{ + //Whelps + {-30.127, -254.463, -89.440}, + {-30.817, -177.106, -89.258}, + //Lair Guard + {-145.950, -212.831, -68.659} +}; + +struct boss_onyxiaAI : public ScriptedAI +{ + boss_onyxiaAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) + { + m_pInstance = pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + SummonList Summons; + + uint32 m_uiPhase; + + uint32 m_uiFlameBreathTimer; + uint32 m_uiCleaveTimer; + uint32 m_uiTailSweepTimer; + uint32 m_uiWingBuffetTimer; + + uint32 m_uiMovePoint; + uint32 m_uiMovementTimer; + sOnyxMove* m_pPointData; + + uint32 m_uiFireballTimer; + uint32 m_uiWhelpTimer; + uint32 m_uiLairGuardTimer; + uint32 m_uiDeepBreathTimer; + + uint32 m_uiBellowingRoarTimer; + + uint8 m_uiSummonWhelpCount; + uint8 m_uiSummonLairGuardCount; + bool m_bIsMoving; + + void Reset() + { + if (!IsCombatMovement()) + SetCombatMovement(true); + + m_uiPhase = PHASE_START; + + m_uiFlameBreathTimer = urand(10000, 20000); + m_uiTailSweepTimer = urand(15000, 20000); + m_uiCleaveTimer = urand(2000, 5000); + m_uiWingBuffetTimer = urand(10000, 20000); + + m_uiMovePoint = urand(0, 5); + m_uiMovementTimer = 20000; + m_pPointData = GetMoveData(); + + m_uiFireballTimer = 15000; + m_uiWhelpTimer = 1000; + m_uiLairGuardTimer = 15000; + m_uiDeepBreathTimer = 85000; + + m_uiBellowingRoarTimer = 30000; + + Summons.DespawnAll(); + m_uiSummonWhelpCount = 0; + m_uiSummonLairGuardCount = 0; + m_bIsMoving = false; + + if (m_pInstance) + { + m_pInstance->SetData(DATA_ONYXIA, NOT_STARTED); + m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void EnterCombat(Unit* pWho) + { + DoScriptText(SAY_AGGRO, me); + me->SetInCombatWithZone(); + + if (m_pInstance) + { + m_pInstance->SetData(DATA_ONYXIA, IN_PROGRESS); + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + sLog.outBasic("[Onyxia] DoStartTimedAchievement(%u,%u)",ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void JustDied(Unit* killer) + { + if (m_pInstance) + m_pInstance->SetData(DATA_ONYXIA, DONE); + + Summons.DespawnAll(); + } + + void JustSummoned(Creature *pSummoned) + { + pSummoned->SetInCombatWithZone(); + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + pSummoned->AI()->AttackStart(pTarget); + + switch (pSummoned->GetEntry()) + { + case NPC_WHELP: + ++m_uiSummonWhelpCount; + break; + case NPC_LAIRGUARD: + pSummoned->setActive(true); + ++m_uiSummonLairGuardCount; + break; + } + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature *summon) + { + Summons.Despawn(summon); + } + + void KilledUnit(Unit* pVictim) + { + DoScriptText(SAY_KILL, me); + } + + void SpellHit(Unit *pCaster, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_BREATH_EAST_TO_WEST || + pSpell->Id == SPELL_BREATH_WEST_TO_EAST || + pSpell->Id == SPELL_BREATH_SE_TO_NW || + pSpell->Id == SPELL_BREATH_NW_TO_SE || + pSpell->Id == SPELL_BREATH_SW_TO_NE || + pSpell->Id == SPELL_BREATH_NE_TO_SW) + { + m_pPointData = GetMoveData(); + m_uiMovePoint = m_pPointData->uiLocIdEnd; + + me->SetSpeed(MOVE_FLIGHT, 1.5f); + me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type == POINT_MOTION_TYPE) + { + switch (id) + { + case 8: + m_pPointData = GetMoveData(); + if (m_pPointData) + { + me->SetSpeed(MOVE_FLIGHT, 1.0f); + me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); + } + break; + case 9: + me->GetMotionMaster()->MoveChase(me->getVictim()); + m_uiBellowingRoarTimer = 1000; + break; + default: + m_bIsMoving = false; + break; + } + } + } + + void SpellHitTarget(Unit* target, const SpellEntry* pSpell) + { + //Workaround - Couldn't find a way to group this spells (All Eruption) + if (((pSpell->Id >= 17086 && pSpell->Id <= 17095) || + (pSpell->Id == 17097) || + (pSpell->Id >= 18351 && pSpell->Id <= 18361) || + (pSpell->Id >= 18564 && pSpell->Id <= 18576) || + (pSpell->Id >= 18578 && pSpell->Id <= 18607) || + (pSpell->Id == 18609) || + (pSpell->Id >= 18611 && pSpell->Id <= 18628) || + (pSpell->Id >= 21132 && pSpell->Id <= 21133) || + (pSpell->Id >= 21135 && pSpell->Id <= 21139) || + (pSpell->Id >= 22191 && pSpell->Id <= 22202) || + (pSpell->Id >= 22267 && pSpell->Id <= 22268)) && + (target->GetTypeId() == TYPEID_PLAYER)) + { + if (m_pInstance) + { + m_pInstance->SetData(DATA_SHE_DEEP_BREATH_MORE, FAIL); + } + } + } + + sOnyxMove* GetMoveData() + { + uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); + + for (uint32 i = 0; i < uiMaxCount; ++i) + { + if (aMoveData[i].uiLocId == m_uiMovePoint) + return &aMoveData[i]; + } + + return NULL; + } + + void SetNextRandomPoint() + { + uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); + + int iTemp = rand()%(uiMaxCount-1); + + if (iTemp >= m_uiMovePoint) + ++iTemp; + + m_uiMovePoint = iTemp; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //Common to PHASE_START && PHASE_END + if (m_uiPhase == PHASE_START || m_uiPhase == PHASE_END) + { + //Specific to PHASE_START || PHASE_END + if (m_uiPhase == PHASE_START) + { + if (me->GetHealth()*100 / me->GetMaxHealth() < 60) + { + m_uiPhase = PHASE_BREATH; + + if (m_pInstance) + m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); + + SetCombatMovement(false); + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + me->SetFlying(true); + + DoScriptText(SAY_PHASE_2_TRANS, me); + + if (m_pPointData) + me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); + + m_uiWhelpTimer = 1000; + return; + } + } + else + { + if (m_uiBellowingRoarTimer <= uiDiff) + { + DoCastVictim(SPELL_BELLOWING_ROAR); + // Eruption + GameObject* pFloor = NULL; + Trinity::GameObjectInRangeCheck check(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 15); + Trinity::GameObjectLastSearcher searcher(me, pFloor, check); + me->VisitNearbyGridObject(30, searcher); + if (m_pInstance && pFloor) + m_pInstance->SetData64(DATA_FLOOR_ERUPTION_GUID, pFloor->GetGUID()); + m_uiBellowingRoarTimer = 30000; + } + else + m_uiBellowingRoarTimer -= uiDiff; + } + + if (m_uiFlameBreathTimer <= uiDiff) + { + DoCastVictim(SPELL_FLAME_BREATH); + m_uiFlameBreathTimer = urand(10000, 20000); + } + else + m_uiFlameBreathTimer -= uiDiff; + + if (m_uiTailSweepTimer <= uiDiff) + { + DoCastAOE(SPELL_TAIL_SWEEP); + m_uiTailSweepTimer = urand(15000, 20000); + } + else + m_uiTailSweepTimer -= uiDiff; + + if (m_uiCleaveTimer <= uiDiff) + { + DoCastVictim(SPELL_CLEAVE); + m_uiCleaveTimer = urand(2000, 5000); + } + else + m_uiCleaveTimer -= uiDiff; + + if (m_uiWingBuffetTimer <= uiDiff) + { + DoCastVictim(SPELL_WING_BUFFET); + m_uiWingBuffetTimer = urand(15000, 30000); + } + else + m_uiWingBuffetTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + else + { + if (me->GetHealth()*100 / me->GetMaxHealth() < 40) + { + m_uiPhase = PHASE_END; + if (m_pInstance) + m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); + DoScriptText(SAY_PHASE_3_TRANS, me); + + SetCombatMovement(true); + me->SetFlying(false); + m_bIsMoving = false; + me->GetMotionMaster()->MovePoint(9,me->GetHomePosition()); + return; + } + + if (m_uiDeepBreathTimer <= uiDiff) + { + if (!m_bIsMoving) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoScriptText(EMOTE_BREATH, me); + DoCast(me, m_pPointData->uiSpellId); + m_uiDeepBreathTimer = 70000; + } + } + else + m_uiDeepBreathTimer -= uiDiff; + + if (m_uiMovementTimer <= uiDiff) + { + if (!m_bIsMoving) + { + SetNextRandomPoint(); + m_pPointData = GetMoveData(); + + if (!m_pPointData) + return; + + me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); + m_bIsMoving = true; + m_uiMovementTimer = 25000; + } + } + else + m_uiMovementTimer -= uiDiff; + + if (m_uiFireballTimer <= uiDiff) + { + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FIREBALL); + + m_uiFireballTimer = 8000; + } + } + else + m_uiFireballTimer -= uiDiff; + + if (m_uiLairGuardTimer <= uiDiff) + { + me->SummonCreature(NPC_LAIRGUARD, aSpawnLocations[2].GetPositionX(), aSpawnLocations[2].GetPositionY(), aSpawnLocations[2].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); + if (m_uiSummonLairGuardCount >= RAID_MODE(1,2)) + { + m_uiSummonLairGuardCount = 0; + m_uiLairGuardTimer = 30000; + } + else + m_uiLairGuardTimer = 2000; + } + else + m_uiLairGuardTimer -= uiDiff; + + if (m_uiWhelpTimer <= uiDiff) + { + me->SummonCreature(NPC_WHELP, aSpawnLocations[0].GetPositionX(), aSpawnLocations[0].GetPositionY(), aSpawnLocations[0].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); + me->SummonCreature(NPC_WHELP, aSpawnLocations[1].GetPositionX(), aSpawnLocations[1].GetPositionY(), aSpawnLocations[1].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); + if (m_uiSummonWhelpCount >= RAID_MODE(20,40)) + { + m_uiSummonWhelpCount = 0; + m_uiWhelpTimer = 90000; + } + else + m_uiWhelpTimer = 500; + } + else + m_uiWhelpTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_boss_onyxiaAI(Creature* pCreature) +{ + return new boss_onyxiaAI (pCreature); +} + +void AddSC_boss_onyxia() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_onyxia"; + newscript->GetAI = &GetAI_boss_onyxiaAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp new file mode 100644 index 00000000000..cfd66bf80f4 --- /dev/null +++ b/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp @@ -0,0 +1,249 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Onyxias_Lair +SD%Complete: 100 +SDComment: +SDCategory: Onyxia's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "onyxias_lair.h" + +struct instance_onyxias_lair : public ScriptedInstance +{ + instance_onyxias_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + //Eruption is a BFS graph problem + //One map to remember all floor, one map to keep floor that still need to erupt and one queue to know what needs to be removed + std::map FloorEruptionGUID[2]; + std::queue FloorEruptionGUIDQueue; + + uint64 m_uiOnyxiasGUID; + uint32 m_uiOnyxiaLiftoffTimer; + uint32 m_uiManyWhelpsCounter; + uint32 m_uiEruptTimer; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + + bool m_bAchievManyWhelpsHandleIt; + bool m_bAchievSheDeepBreathMore; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiOnyxiasGUID = 0; + m_uiOnyxiaLiftoffTimer = 0; + m_uiManyWhelpsCounter = 0; + m_bAchievManyWhelpsHandleIt = false; + m_bAchievSheDeepBreathMore = true; + + m_uiEruptTimer = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + switch (pCreature->GetEntry()) + { + case NPC_ONYXIA: + m_uiOnyxiasGUID = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if ((pGo->GetGOInfo()->displayId == 4392 || pGo->GetGOInfo()->displayId == 4472) && pGo->GetGOInfo()->trap.spellId == 17731) + { + if (add) + FloorEruptionGUID[0].insert(std::make_pair(pGo->GetGUID(),0)); + else + FloorEruptionGUID[0].erase(pGo->GetGUID()); + return; + } + + switch(pGo->GetEntry()) + { + case GO_WHELP_SPAWNER: + Position pGoPos; + pGo->GetPosition(&pGoPos); + if (Creature* pTemp = pGo->SummonCreature(NPC_WHELP,pGoPos,TEMPSUMMON_CORPSE_DESPAWN)) + { + pTemp->SetInCombatWithZone(); + ++m_uiManyWhelpsCounter; + } + break; + } + } + + void FloorEruption(uint64 floorEruptedGUID) + { + if (GameObject *pFloorEruption = instance->GetGameObject(floorEruptedGUID)) + { + //THIS GOB IS A TRAP - What shall i do? =( + //Cast it spell? Copyed Heigan method + pFloorEruption->SendCustomAnim(); + pFloorEruption->CastSpell(NULL, Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL ? 17731 : 69294); //pFloorEruption->GetGOInfo()->trap.spellId + + //Get all immediatly nearby floors + std::list nearFloorList; + Trinity::GameObjectInRangeCheck check(pFloorEruption->GetPositionX(), pFloorEruption->GetPositionY(), pFloorEruption->GetPositionZ(), 15); + Trinity::GameObjectListSearcher searcher(pFloorEruption, nearFloorList, check); + pFloorEruption->VisitNearbyGridObject(999, searcher); + //remove all that are not present on FloorEruptionGUID[1] and update treeLen on each GUID + for (std::list::const_iterator itr = nearFloorList.begin(); itr != nearFloorList.end(); ++itr) + { + if (((*itr)->GetGOInfo()->displayId == 4392 || (*itr)->GetGOInfo()->displayId == 4472) && (*itr)->GetGOInfo()->trap.spellId == 17731) + { + uint64 nearFloorGUID = (*itr)->GetGUID(); + if (FloorEruptionGUID[1].find(nearFloorGUID) != FloorEruptionGUID[1].end() && (*FloorEruptionGUID[1].find(nearFloorGUID)).second == 0) + { + (*FloorEruptionGUID[1].find(nearFloorGUID)).second = (*FloorEruptionGUID[1].find(floorEruptedGUID)).second+1; + FloorEruptionGUIDQueue.push(nearFloorGUID); + } + } + } + } + FloorEruptionGUID[1].erase(floorEruptedGUID); + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case DATA_ONYXIA: + m_auiEncounter[0] = uiData; + if (uiData == IN_PROGRESS) + SetData(DATA_SHE_DEEP_BREATH_MORE, IN_PROGRESS); + break; + case DATA_ONYXIA_PHASE: + if (uiData == PHASE_BREATH) //Used to mark the liftoff phase + { + m_bAchievManyWhelpsHandleIt = false; + m_uiManyWhelpsCounter = 0; + m_uiOnyxiaLiftoffTimer = 10*IN_MILISECONDS; + } + break; + case DATA_SHE_DEEP_BREATH_MORE: + if (uiData == IN_PROGRESS) + { + m_bAchievSheDeepBreathMore = true; + } + else if (uiData == FAIL) + { + m_bAchievSheDeepBreathMore = false; + } + break; + } + + if (uiType < MAX_ENCOUNTER && uiData == DONE) + SaveToDB(); + } + + void SetData64(uint32 uiType, uint64 uiData) + { + switch(uiType) + { + case DATA_FLOOR_ERUPTION_GUID: + FloorEruptionGUID[1] = FloorEruptionGUID[0]; + FloorEruptionGUIDQueue.push(uiData); + m_uiEruptTimer = 2500; + break; + } + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case DATA_ONYXIA: + return m_auiEncounter[0]; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_ONYXIA_GUID: + return m_uiOnyxiasGUID; + } + + return 0; + } + + void Update(uint32 uiDiff) + { + if (GetData(DATA_ONYXIA) == IN_PROGRESS) + { + if (m_uiOnyxiaLiftoffTimer && m_uiOnyxiaLiftoffTimer <= uiDiff) + { + m_uiOnyxiaLiftoffTimer = 0; + if (m_uiManyWhelpsCounter >= 50) + m_bAchievManyWhelpsHandleIt = true; + } else m_uiOnyxiaLiftoffTimer -= uiDiff; + } + + if (!FloorEruptionGUIDQueue.empty()) + { + if (m_uiEruptTimer <= uiDiff) + { + uint32 treeHeight = 0; + do + { + treeHeight = (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second; + FloorEruption(FloorEruptionGUIDQueue.front()); + FloorEruptionGUIDQueue.pop(); + } while (!FloorEruptionGUIDQueue.empty() && (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second == treeHeight); + m_uiEruptTimer = 1000; + } + else + m_uiEruptTimer -= uiDiff; + } + } + + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* target = NULL, uint32 miscvalue1 = 0) + { + switch(criteria_id) + { + case ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER: // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s + case ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER: // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s + return m_bAchievManyWhelpsHandleIt; + case ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER: // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath + case ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER: // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath + return m_bAchievSheDeepBreathMore; + } + return false; + } +}; + +InstanceData* GetInstanceData_instance_onyxias_lair(Map* pMap) +{ + return new instance_onyxias_lair(pMap); +} + +void AddSC_instance_onyxias_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_onyxias_lair"; + newscript->GetInstanceData = &GetInstanceData_instance_onyxias_lair; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h b/src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h new file mode 100644 index 00000000000..cadd5b5a2d5 --- /dev/null +++ b/src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_ONYXIAS_LAIR_H +#define DEF_ONYXIAS_LAIR_H + +enum eData64 +{ + DATA_ONYXIA_GUID, + DATA_FLOOR_ERUPTION_GUID +}; + +enum eInstanceData +{ + DATA_ONYXIA, + MAX_ENCOUNTER, + + DATA_ONYXIA_PHASE, + DATA_SHE_DEEP_BREATH_MORE, + DATA_MANY_WHELPS_COUNT +}; + +enum eCreatures +{ + NPC_WHELP = 11262, + NPC_LAIRGUARD = 36561, + + NPC_ONYXIA = 10184 +}; + +enum eOnyxiaPhases +{ + PHASE_START = 1, + PHASE_BREATH = 2, + PHASE_END = 3 +}; + +enum eGameObjects +{ + GO_WHELP_SPAWNER = 176510, + GO_WHELP_EGG = 176511 +}; + +enum eAchievementData +{ + ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER = 12565, // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s + ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER = 12568, // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s + ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER = 12566, // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath + ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER = 12569, // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath + ACHIEV_TIMED_START_EVENT = 6601, // Timed event for achievement 4402, 4005: More Dots! (10,25 player) 5 min kill +}; +#endif diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp new file mode 100644 index 00000000000..711c4f0b2c1 --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp @@ -0,0 +1,130 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Amnennar_the_coldbringer +SD%Complete: 100 +SDComment: +SDCategory: Razorfen Downs +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1129000 +#define SAY_SUMMON60 -1129001 +#define SAY_SUMMON30 -1129002 +#define SAY_HP -1129003 +#define SAY_KILL -1129004 + +#define SPELL_AMNENNARSWRATH 13009 +#define SPELL_FROSTBOLT 15530 +#define SPELL_FROST_NOVA 15531 +#define SPELL_FROST_SPECTRES 12642 + +struct boss_amnennar_the_coldbringerAI : public ScriptedAI +{ + boss_amnennar_the_coldbringerAI(Creature *c) : ScriptedAI(c) {} + + uint32 AmnenarsWrath_Timer; + uint32 FrostBolt_Timer; + uint32 FrostNova_Timer; + bool Spectrals60; + bool Spectrals30; + bool Hp; + + void Reset() + { + AmnenarsWrath_Timer = 8000; + FrostBolt_Timer = 1000; + FrostNova_Timer = 10000 + rand()%5000; + Spectrals30 = false; + Spectrals60 = false; + Hp = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit() + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //AmnenarsWrath_Timer + if (AmnenarsWrath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_AMNENNARSWRATH); + AmnenarsWrath_Timer = 12000; + } else AmnenarsWrath_Timer -= diff; + + //FrostBolt_Timer + if (FrostBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + FrostBolt_Timer = 8000; + } else FrostBolt_Timer -= diff; + + if (FrostNova_Timer <= diff) + { + DoCast(me, SPELL_FROST_NOVA); + FrostNova_Timer = 15000; + } else FrostNova_Timer -= diff; + + if (!Spectrals60 && me->GetHealth()*100 / me->GetMaxHealth() < 60) + { + DoScriptText(SAY_SUMMON60, me); + DoCast(me->getVictim(), SPELL_FROST_SPECTRES); + Spectrals60 = true; + } + + if (!Hp && me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + DoScriptText(SAY_HP, me); + Hp = true; + } + + if (!Spectrals30 && me->GetHealth()*100 / me->GetMaxHealth() < 30) + { + DoScriptText(SAY_SUMMON30, me); + DoCast(me->getVictim(), SPELL_FROST_SPECTRES); + Spectrals30 = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_amnennar_the_coldbringer(Creature* pCreature) +{ + return new boss_amnennar_the_coldbringerAI (pCreature); +} + +void AddSC_boss_amnennar_the_coldbringer() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_amnennar_the_coldbringer"; + newscript->GetAI = &GetAI_boss_amnennar_the_coldbringer; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp new file mode 100644 index 00000000000..04904f08a57 --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "razorfen_downs.h" + +#define MAX_ENCOUNTER 1 + +struct instance_razorfen_downs : public ScriptedInstance +{ + instance_razorfen_downs(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + }; + + uint64 uiGongGUID; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint8 uiGongWaves; + + std::string str_data; + + void Initialize() + { + uiGongGUID = 0; + + uiGongWaves = 0; + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + saveStream << "T C " << m_auiEncounter[0] + << " " << uiGongWaves; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; + + if (dataHead1 == 'T' && dataHead2 == 'C') + { + m_auiEncounter[0] = data0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + uiGongWaves = data1; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*bAdd*/) + { + switch(pGo->GetEntry()) + { + case GO_GONG: + uiGongGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + break; + default: + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + if (uiType == DATA_GONG_WAVES) + { + uiGongWaves = uiData; + + switch(uiGongWaves) + { + case 9: + case 14: + if (GameObject* pGo = instance->GetGameObject(uiGongGUID)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + break; + case 1: + case 10: + case 16: + { + GameObject* pGo = instance->GetGameObject(uiGongGUID); + + if (!pGo) + return; + + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + + uint32 uiCreature = 0; + uint8 uiSummonTimes = 0; + + switch(uiGongWaves) + { + case 1: + uiCreature = CREATURE_TOMB_FIEND; + uiSummonTimes = 7; + break; + case 10: + uiCreature = CREATURE_TOMB_REAVER; + uiSummonTimes = 3; + break; + case 16: + uiCreature = CREATURE_TUTEN_KASH; + break; + default: + break; + } + + + if (Creature* pCreature = pGo->SummonCreature(uiCreature,2502.635,844.140,46.896,0.633)) + { + if (uiGongWaves == 10 || uiGongWaves == 1) + { + for (uint8 i = 0; i < uiSummonTimes; ++i) + { + if (Creature* pSummon = pGo->SummonCreature(uiCreature,2502.635 + float(irand(-5,5)),844.140 + float(irand(-5,5)),46.896,0.633)) + pSummon->GetMotionMaster()->MovePoint(0,2533.479 + float(irand(-5,5)),870.020 + float(irand(-5,5)),47.678); + } + } + pCreature->GetMotionMaster()->MovePoint(0,2533.479 + float(irand(-5,5)),870.020 + float(irand(-5,5)),47.678); + } + break; + } + default: + break; + } + } + + if (uiType == BOSS_TUTEN_KASH) + { + m_auiEncounter[0] = uiData; + + if (uiData == DONE) + SaveToDB(); + } + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case DATA_GONG_WAVES: + return uiGongWaves; + } + + return 0; + } + + uint64 GetData64(uint32 uiType) + { + switch(uiType) + { + case DATA_GONG: return uiGongGUID; + } + + return 0; + } +}; + +InstanceData* GetInstanceData_instance_razorfen_downs(Map* pMap) +{ + return new instance_razorfen_downs(pMap); +} + +void AddSC_instance_razorfen_downs() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "instance_razorfen_downs"; + newscript->GetInstanceData = &GetInstanceData_instance_razorfen_downs; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp new file mode 100644 index 00000000000..3e8f4049a37 --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp @@ -0,0 +1,165 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Razorfen_Downs +SD%Complete: 100 +SDComment: Support for Henry Stern(2 recipes) +SDCategory: Razorfen Downs +EndScriptData */ + +/* ContentData +npc_henry_stern +EndContentData */ + +#include "ScriptedPch.h" +#include "razorfen_downs.h" + +/*### +# npc_henry_stern +####*/ + +enum eEnums +{ + SPELL_GOLDTHORN_TEA = 13028, + SPELL_TEACHING_GOLDTHORN_TEA = 13029, + SPELL_MIGHT_TROLLS_BLOOD_POTION = 3451, + SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION = 13030, + GOSSIP_TEXT_TEA_ANSWER = 2114, + GOSSIP_TEXT_POTION_ANSWER = 2115, +}; + +#define GOSSIP_ITEM_TEA "Teach me the cooking recipe" +#define GOSSIP_ITEM_POTION "Teach me the alchemy recipe" + +bool GossipHello_npc_henry_stern (Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetBaseSkillValue(SKILL_COOKING) >= 175 && !pPlayer->HasSpell(SPELL_GOLDTHORN_TEA)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + if (pPlayer->GetBaseSkillValue(SKILL_ALCHEMY) >= 180 && !pPlayer->HasSpell(SPELL_MIGHT_TROLLS_BLOOD_POTION)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_POTION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_henry_stern (Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CastSpell(pPlayer, SPELL_TEACHING_GOLDTHORN_TEA, true); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_TEA_ANSWER, pCreature->GetGUID()); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF + 2) + { + pPlayer->CastSpell(pPlayer, SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION, true); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_POTION_ANSWER, pCreature->GetGUID()); + } + + return true; +} + +/*###### +## go_gong +######*/ + +bool GOHello_go_gong(Player* /*pPlayer*/, GameObject* pGO) +{ + //basic support, not blizzlike data is missing... + ScriptedInstance* pInstance = pGO->GetInstanceData(); + + if (pInstance) + { + pInstance->SetData(DATA_GONG_WAVES,pInstance->GetData(DATA_GONG_WAVES)+1); + return true; + } + + return false; +} + +enum eTombCreature +{ + SPELL_WEB = 745 +}; + +struct npc_tomb_creatureAI : public ScriptedAI +{ + npc_tomb_creatureAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiWebTimer; + + void Reset() + { + uiWebTimer = urand(5000,8000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + //from acid + if (me->GetEntry() == CREATURE_TOMB_REAVER) + { + if (uiWebTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_WEB); + uiWebTimer = urand(7000,16000); + } else uiWebTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(DATA_GONG_WAVES,pInstance->GetData(DATA_GONG_WAVES)+1); + } +}; + +CreatureAI* GetAI_npc_tomb_creature(Creature* pCreature) +{ + return new npc_tomb_creatureAI (pCreature); +} + +void AddSC_razorfen_downs() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_henry_stern"; + newscript->pGossipHello = &GossipHello_npc_henry_stern; + newscript->pGossipSelect = &GossipSelect_npc_henry_stern; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_gong"; + newscript->pGOHello = &GOHello_go_gong; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tomb_creature"; + newscript->GetAI = &GetAI_npc_tomb_creature; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h new file mode 100644 index 00000000000..a67b4223c4a --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_RAZORFEN_DOWNS_H +#define DEF_RAZORFEN_DOWNS_H + +enum eData +{ + BOSS_TUTEN_KASH, + DATA_GONG_WAVES +}; + +enum eData64 +{ + DATA_GONG +}; + +enum eGameObject +{ + GO_GONG = 148917 +}; + +enum eCreature +{ + CREATURE_TOMB_FIEND = 7349, + CREATURE_TOMB_REAVER = 7351, + CREATURE_TUTEN_KASH = 7355 +}; + +#endif diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp new file mode 100644 index 00000000000..8a92d3d4d89 --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp @@ -0,0 +1,104 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Razorfen_Kraul +SD%Complete: +SDComment: +SDCategory: Razorfen Kraul +EndScriptData */ + +#include "ScriptedPch.h" +#include "razorfen_kraul.h" + +#define WARD_KEEPERS_NR 2 + +struct instance_razorfen_kraul : public ScriptedInstance +{ + instance_razorfen_kraul(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 DoorWardGUID; + uint32 WardCheck_Timer; + int WardKeeperAlive; + + void Initialize() + { + WardKeeperAlive = 1; + WardCheck_Timer = 4000; + DoorWardGUID = 0; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + debug_log("TSCR: Instance Razorfen Kraul: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*apply*/) + { + switch(pGo->GetEntry()) + { + case 21099: DoorWardGUID = pGo->GetGUID(); break; + } + } + + void Update(uint32 diff) + { + if (WardCheck_Timer <= diff) + { + HandleGameObject(DoorWardGUID, WardKeeperAlive); + WardKeeperAlive = 0; + WardCheck_Timer = 4000; + }else + WardCheck_Timer -= diff; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_WARD_KEEPERS: + if (data == NOT_STARTED) + WardKeeperAlive = 1; + break; + } + } + +}; + +InstanceData* GetInstanceData_instance_razorfen_kraul(Map* pMap) +{ + return new instance_razorfen_kraul(pMap); +} + +void AddSC_instance_razorfen_kraul() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_razorfen_kraul"; + newscript->GetInstanceData = &GetInstanceData_instance_razorfen_kraul; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp new file mode 100644 index 00000000000..8470fa6c7ac --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp @@ -0,0 +1,194 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Razorfen Kraul +SD%Complete: 100 +SDComment: Quest support: 1144 +SDCategory: Razorfen Kraul +EndScriptData */ + +/* ContentData +npc_willix +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "razorfen_kraul.h" + +#define SAY_READY -1047000 +#define SAY_POINT -1047001 +#define SAY_AGGRO1 -1047002 +#define SAY_BLUELEAF -1047003 +#define SAY_DANGER -1047004 +#define SAY_BAD -1047005 +#define SAY_THINK -1047006 +#define SAY_SOON -1047007 +#define SAY_FINALY -1047008 +#define SAY_WIN -1047009 +#define SAY_END -1047010 + +#define QUEST_WILLIX_THE_IMPORTER 1144 +#define ENTRY_BOAR 4514 +#define SPELL_QUILLBOAR_CHANNELING 7083 + +struct npc_willixAI : public npc_escortAI +{ + npc_willixAI(Creature *c) : npc_escortAI(c) {} + + void WaypointReached(uint32 i) + { + Player* pPlayer = GetPlayerForEscort(); + + if (!pPlayer) + return; + + switch (i) + { + case 3: + me->HandleEmoteCommand(EMOTE_STATE_POINT); + DoScriptText(SAY_POINT, me, pPlayer); + break; + case 4: + me->SummonCreature(ENTRY_BOAR, 2137.66, 1843.98, 48.08, 1.54, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + case 8: + DoScriptText(SAY_BLUELEAF, me, pPlayer); + break; + case 9: + DoScriptText(SAY_DANGER, me, pPlayer); + break; + case 13: + DoScriptText(SAY_BAD, me, pPlayer); + break; + case 14: + me->SummonCreature(ENTRY_BOAR, 2078.91, 1704.54, 56.77, 1.54, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + case 25: + DoScriptText(SAY_THINK, me, pPlayer); + break; + case 31: + DoScriptText(SAY_SOON, me, pPlayer); + break; + case 42: + DoScriptText(SAY_FINALY, me, pPlayer); + break; + case 43: + me->SummonCreature(ENTRY_BOAR, 1956.43, 1596.97, 81.75, 1.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + case 45: + DoScriptText(SAY_WIN, me, pPlayer); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) + CAST_PLR(pPlayer)->GroupEventHappens(QUEST_WILLIX_THE_IMPORTER,me); + break; + case 46: + DoScriptText(SAY_END, me, pPlayer); + break; + } + } + + void Reset() {} + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO1, me, NULL); + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void JustDied(Unit* /*killer*/) + { + if (Player* pPlayer = GetPlayerForEscort()) + CAST_PLR(pPlayer)->FailQuest(QUEST_WILLIX_THE_IMPORTER); + } +}; + +bool QuestAccept_npc_willix(Player* pPlayer, Creature* pCreature, Quest const* quest) +{ + if (quest->GetQuestId() == QUEST_WILLIX_THE_IMPORTER) + { + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); + DoScriptText(SAY_READY, pCreature, pPlayer); + pCreature->setFaction(113); + } + + return true; +} + +struct npc_deaths_head_ward_keeperAI : public ScriptedAI +{ + npc_deaths_head_ward_keeperAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 QuillboarChanneling_Timer; + + void Reset() + { + QuillboarChanneling_Timer = 1500; + } + + void UpdateAI(const uint32 diff) + { + if (!me->isAlive()) + return; + + if (pInstance) + pInstance->SetData(TYPE_WARD_KEEPERS, NOT_STARTED); + + if (QuillboarChanneling_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_QUILLBOAR_CHANNELING); + QuillboarChanneling_Timer = 1100; + } else QuillboarChanneling_Timer -= diff; + + } +}; + +CreatureAI* GetAI_npc_deaths_head_ward_keeper(Creature* pCreature) +{ + return new npc_deaths_head_ward_keeperAI(pCreature); +} + +CreatureAI* GetAI_npc_willix(Creature* pCreature) +{ + return new npc_willixAI(pCreature); +} + +void AddSC_razorfen_kraul() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_willix"; + newscript->GetAI = &GetAI_npc_willix; + newscript->pQuestAccept = &QuestAccept_npc_willix; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_deaths_head_ward_keeper"; + newscript->GetAI = &GetAI_npc_deaths_head_ward_keeper; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.h b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.h new file mode 100644 index 00000000000..e2219986f63 --- /dev/null +++ b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_RAZORFEN_KRAUL_H +#define DEF_RAZORFEN_KRAUL_H + +#define TYPE_WARD_KEEPERS 1 +#endif diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp new file mode 100644 index 00000000000..f6dc75558c8 --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -0,0 +1,125 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ayamiss +SD%Complete: 50 +SDComment: VERIFY SCRIPT +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +/* +To do: +make him fly from 70-100% +*/ + +enum Spells +{ + SPELL_STINGERSPRAY = 25749, + SPELL_POISONSTINGER = 25748, //only used in phase1 + SPELL_SUMMONSWARMER = 25844, //might be 25708 + SPELL_PARALYZE = 23414 //doesnt work correct (core) +}; + +struct boss_ayamissAI : public ScriptedAI +{ + boss_ayamissAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 STINGERSPRAY_Timer; + uint32 POISONSTINGER_Timer; + uint32 SUMMONSWARMER_Timer; + uint32 phase; + + ScriptedInstance *pInstance; + + void Reset() + { + STINGERSPRAY_Timer = 30000; + POISONSTINGER_Timer = 30000; + SUMMONSWARMER_Timer = 60000; + phase=1; + + if (pInstance) + pInstance->SetData(DATA_AYAMISS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_AYAMISS_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_AYAMISS_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If he is 70% start phase 2 + if (phase == 1 && me->GetHealth()*100 / me->GetMaxHealth() <= 70 && !me->IsNonMeleeSpellCasted(false)) + { + phase=2; + } + + //STINGERSPRAY_Timer (only in phase2) + if (phase == 2 && STINGERSPRAY_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STINGERSPRAY); + STINGERSPRAY_Timer = 30000; + } else STINGERSPRAY_Timer -= diff; + + //POISONSTINGER_Timer (only in phase1) + if (phase == 1 && POISONSTINGER_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISONSTINGER); + POISONSTINGER_Timer = 30000; + } else POISONSTINGER_Timer -= diff; + + //SUMMONSWARMER_Timer (only in phase1) + if (SUMMONSWARMER_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUMMONSWARMER); + SUMMONSWARMER_Timer = 60000; + } else SUMMONSWARMER_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_ayamiss(Creature* pCreature) +{ + return new boss_ayamissAI (pCreature); +} + +void AddSC_boss_ayamiss() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ayamiss"; + newscript->GetAI = &GetAI_boss_ayamiss; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp new file mode 100644 index 00000000000..86a2c559543 --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp @@ -0,0 +1,72 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Buru +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Yells +{ + EMOTE_TARGET = -1509002 +}; + +struct boss_buruAI : public ScriptedAI +{ + boss_buruAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_BURU_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_BURU_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_BURU_EVENT, DONE); + } +}; +CreatureAI* GetAI_boss_buru(Creature* pCreature) +{ + return new boss_buruAI (pCreature); +} + +void AddSC_boss_buru() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_buru"; + newscript->GetAI = &GetAI_boss_buru; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp new file mode 100644 index 00000000000..44f11bf4b60 --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp @@ -0,0 +1,143 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kurinnaxx +SD%Complete: 100 +SDComment: VERIFY SCRIPT AND SQL +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Spells +{ + SPELL_MORTALWOUND = 25646, + SPELL_SANDTRAP = 25656, + SPELL_ENRAGE = 28798, + SPELL_SUMMON_PLAYER = 26446, + SPELL_TRASH = 3391, + SPELL_WIDE_SLASH = 25814 +}; + +struct boss_kurinnaxxAI : public ScriptedAI +{ + boss_kurinnaxxAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiMortalWoundTimer; + uint32 uiSandtrapTimer; + uint32 uiWideSlashTimer; + uint32 uiSummonPlayerTimer; + uint32 uiTrashTimer; + bool bIsEnraged; + + ScriptedInstance* pInstance; + + void Reset() + { + bIsEnraged = false; + uiMortalWoundTimer = urand(2000,7000); + uiSandtrapTimer = urand(20000,30000); + uiWideSlashTimer = urand(10000,15000); + uiTrashTimer = urand(20000,25000); + uiSummonPlayerTimer = urand(30000,40000); + + if (pInstance) + pInstance->SetData(DATA_KURINNAXX_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_KURINNAXX_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_KURINNAXX_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //If we are <30% cast enrage + if (!bIsEnraged && me->GetHealth()*100 / me->GetMaxHealth() <= 30 && !me->IsNonMeleeSpellCasted(false)) + { + bIsEnraged = true; + DoCast(me, SPELL_ENRAGE); + } + + //Mortal Wound spell + if (uiMortalWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTALWOUND); + uiMortalWoundTimer = urand(2000,7000); + } else uiMortalWoundTimer -= diff; + + //Santrap spell + if (uiSandtrapTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SANDTRAP); + uiSandtrapTimer = 30000; + } else uiSandtrapTimer -= diff; + + //Wide Slash spell + if (uiWideSlashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WIDE_SLASH); + uiWideSlashTimer = urand(10000,15000); + } else uiWideSlashTimer -= diff; + + //Trash spell + if (uiTrashTimer <= diff) + { + DoCast(me, SPELL_TRASH); + uiTrashTimer = urand(20000,25000); + } else uiTrashTimer -= diff; + + //Summon Player spell + if (uiSummonPlayerTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SUMMON_PLAYER); + uiSummonPlayerTimer = urand(30000,40000); + } else uiSummonPlayerTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_kurinnaxx(Creature* pCreature) +{ + return new boss_kurinnaxxAI (pCreature); +} + +void AddSC_boss_kurinnaxx() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kurinnaxx"; + newscript->GetAI = &GetAI_boss_kurinnaxx; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp new file mode 100644 index 00000000000..1882adc8fbb --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp @@ -0,0 +1,162 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Moam +SD%Complete: 90 +SDComment: TODO: Adjust timer, correct Stone phase buff +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Emotes +{ + EMOTE_AGGRO = -1509000, + EMOTE_MANA_FULL = -1509001 +}; + +enum Spells +{ + SPELL_TRAMPLE = 15550, + SPELL_DRAINMANA = 27256, //Doesn't exist ? + SPELL_ARCANEERUPTION = 25672, + SPELL_SUMMONMANA = 25681, //Summon Mana fiend. It only summons one so exec it three times + SPELL_GRDRSLEEP = 24360 //Greater Dreamless Sleep +}; + +enum Creatures +{ + CREATURE_MANA_FIEND = 15527 +}; + +enum CombatPhase +{ + NORMAL, + STONE +}; + +struct boss_moamAI : public ScriptedAI +{ + boss_moamAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiTrampleTimer; + uint32 uiDrainManaTimer; + uint32 uiPhaseTimer; + CombatPhase Phase; + + ScriptedInstance *pInstance; + + void Reset() + { + uiTrampleTimer = urand(3000,7000); + uiDrainManaTimer = urand(3000,7000); + uiPhaseTimer = 90000; + Phase = NORMAL; + me->SetPower(POWER_MANA,0); + + if (pInstance) + pInstance->SetData(DATA_MOAM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(EMOTE_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MOAM_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_MOAM_EVENT, DONE); + } + + void DrainMana() + { + for (uint8 i=0;i<6;++i) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + pTarget->ModifyPower(POWER_MANA, -500); + me->ModifyPower(POWER_MANA, 1000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Phase == NORMAL) + { + if (!UpdateVictim()) + return; + + //If we are 100%MANA cast Arcane Erruption + if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA)) + { + DoCast(me->getVictim(), SPELL_ARCANEERUPTION); + DoScriptText(EMOTE_MANA_FULL, me); + me->SetPower(POWER_MANA,0); + } + + //Trample Spell + if (uiTrampleTimer <= diff) + { + DoCast(me->getVictim(), SPELL_TRAMPLE); + uiTrampleTimer = urand(3000,7000); + } else uiTrampleTimer -= diff; + + //Drain Mana + if (uiDrainManaTimer <= diff) + { + DrainMana(); + uiDrainManaTimer = urand(3000,7000); + } else uiDrainManaTimer -= diff; + + DoMeleeAttackIfReady(); + + //After 90secs change phase + if (uiPhaseTimer <= diff) + { + Phase = STONE; + DoCast(me, SPELL_SUMMONMANA); + DoCast(me, SPELL_SUMMONMANA); + DoCast(me, SPELL_SUMMONMANA); + DoCast(me, SPELL_GRDRSLEEP); + } else uiPhaseTimer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_moam(Creature* pCreature) +{ + return new boss_moamAI (pCreature); +} + +void AddSC_boss_moam() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_moam"; + newscript->GetAI = &GetAI_boss_moam; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp new file mode 100644 index 00000000000..57ba8d9da7f --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -0,0 +1,79 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ossirian +SD%Complete: 0 +SDComment: Place holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Yells +{ + SAY_SURPREME2 = -1509019, + SAY_SURPREME3 = -1509020, + SAY_RAND_INTRO1 = -1509021, + SAY_RAND_INTRO2 = -1509022, + SAY_RAND_INTRO3 = -1509023, + SAY_RAND_INTRO4 = -1509024, //possibly old? + SAY_AGGRO = -1509025, + SAY_SLAY = -1509026, + SAY_DEATH = -1509027 +}; + +struct boss_ossirianAI : public ScriptedAI +{ + boss_ossirianAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_OSSIRIAN_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_OSSIRIAN_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_OSSIRIAN_EVENT, DONE); + } +}; +CreatureAI* GetAI_boss_ossirian(Creature* pCreature) +{ + return new boss_ossirianAI (pCreature); +} + +void AddSC_boss_ossirian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ossirian"; + newscript->GetAI = &GetAI_boss_ossirian; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp new file mode 100644 index 00000000000..5be60dc0ca0 --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Rajaxx +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +enum Yells +{ + SAY_ANDOROV_INTRO = -1509003, + SAY_ANDOROV_ATTACK = -1509004, + SAY_WAVE3 = -1509005, + SAY_WAVE4 = -1509006, + SAY_WAVE5 = -1509007, + SAY_WAVE6 = -1509008, + SAY_WAVE7 = -1509009, + SAY_INTRO = -1509010, + SAY_UNK1 = -1509011, + SAY_UNK2 = -1509012, + SAY_UNK3 = -1509013, + SAY_UNK4 = -1509014, + SAY_DEAGGRO = -1509015, + SAY_KILLS_ANDOROV = -1509016, + SAY_COMPLETE_QUEST = -1509017 //Yell when realm complete quest 8743 for world event +}; + +struct boss_rajaxxAI : public ScriptedAI +{ + boss_rajaxxAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_RAJAXX_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_RAJAXX_EVENT, IN_PROGRESS); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_RAJAXX_EVENT, DONE); + } +}; +CreatureAI* GetAI_boss_rajaxx(Creature* pCreature) +{ + return new boss_rajaxxAI (pCreature); +} + +void AddSC_boss_rajaxx() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_rajaxx"; + newscript->GetAI = &GetAI_boss_rajaxx; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp new file mode 100644 index 00000000000..ba7471bdbd2 --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp @@ -0,0 +1,213 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Ruins_of_Ahnqiraj +SD%Complete: 0 +SDComment: Place holder +SDCategory: Ruins of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "ruins_of_ahnqiraj.h" + +#define MAX_ENCOUNTER 6 + +/* Ruins of Ahn'Qiraj encounters: +0 - Kurinnaxx +1 - General Rajaxx +2 - Moam +3 - Buru the Gorger +4 - Ayamiss the Hunter +5 - Ossirian the Unscarred */ + +struct instance_ruins_of_ahn_qiraj : public ScriptedInstance +{ + instance_ruins_of_ahn_qiraj(Map* pMap) : ScriptedInstance(pMap) { Initialize(); } + + uint64 uiKurinaxx; + uint64 uiRajaxx; + uint64 uiMoam; + uint64 uiBuru; + uint64 uiAyamiss; + uint64 uiOssirian; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + uiKurinaxx = 0; + uiRajaxx = 0; + uiMoam = 0; + uiBuru = 0; + uiAyamiss = 0; + uiOssirian = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case CREATURE_KURINAXX: + uiKurinaxx = pCreature->GetGUID(); + break; + case CREATURE_RAJAXX: + uiRajaxx = pCreature->GetGUID(); + break; + case CREATURE_MOAM: + uiMoam = pCreature->GetGUID(); + break; + case CREATURE_BURU: + uiBuru = pCreature->GetGUID(); + break; + case CREATURE_AYAMISS: + uiAyamiss = pCreature->GetGUID(); + break; + case CREATURE_OSSIRIAN: + uiOssirian = pCreature->GetGUID(); + break; + } + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_KURINNAXX_EVENT: return m_auiEncounter[0]; + case DATA_RAJAXX_EVENT: return m_auiEncounter[1]; + case DATA_MOAM_EVENT: return m_auiEncounter[2]; + case DATA_BURU_EVENT: return m_auiEncounter[3]; + case DATA_AYAMISS_EVENT: return m_auiEncounter[4]; + case DATA_OSSIRIAN_EVENT: return m_auiEncounter[5]; + } + + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch(identifier) + { + case DATA_KURINNAXX_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_RAJAXX_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_MOAM_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_BURU_EVENT: + m_auiEncounter[3] = data; + break; + case DATA_AYAMISS_EVENT: + m_auiEncounter[4] = data; + break; + case DATA_OSSIRIAN_EVENT: + m_auiEncounter[5] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint64 GetData64(uint32 uiIdentifier) + { + switch(uiIdentifier) + { + case DATA_KURINNAXX: return uiKurinaxx; + case DATA_RAJAXX: return uiRajaxx; + case DATA_MOAM: return uiMoam; + case DATA_BURU: return uiBuru; + case DATA_AYAMISS: return uiAyamiss; + case DATA_OSSIRIAN: return uiOssirian; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "R A " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + + if (dataHead1 == 'R' && dataHead2 == 'A') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + m_auiEncounter[5] = data5; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + } +}; + +InstanceData* GetInstanceData_instance_ruins_of_ahn_qiraj(Map* pMap) +{ + return new instance_ruins_of_ahn_qiraj(pMap); +} + +void AddSC_instance_ruins_of_ahnqiraj() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_ruins_of_ahnqiraj"; + newscript->GetInstanceData = &GetInstanceData_instance_ruins_of_ahn_qiraj; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h new file mode 100644 index 00000000000..33fd75d557a --- /dev/null +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h @@ -0,0 +1,34 @@ +#ifndef DEF_RUINS_OF_AHNQIRAJ_H +#define DEF_RUINS_OF_AHNQIRAJ_H + +enum Data +{ + DATA_KURINNAXX_EVENT, + DATA_RAJAXX_EVENT, + DATA_MOAM_EVENT, + DATA_BURU_EVENT, + DATA_AYAMISS_EVENT, + DATA_OSSIRIAN_EVENT +}; + +enum Data64 +{ + DATA_KURINNAXX, + DATA_RAJAXX, + DATA_MOAM, + DATA_BURU, + DATA_AYAMISS, + DATA_OSSIRIAN +}; + +enum Bosses +{ + CREATURE_KURINAXX = 15348, + CREATURE_RAJAXX = 15341, + CREATURE_MOAM = 15340, + CREATURE_BURU = 15370, + CREATURE_AYAMISS = 15369, + CREATURE_OSSIRIAN = 15339 +}; + +#endif diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp new file mode 100644 index 00000000000..f6e3b0c741b --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp @@ -0,0 +1,346 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_kri, boss_yauj, boss_vem : The Bug Trio +SD%Complete: 100 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" + +#define SPELL_CLEAVE 26350 +#define SPELL_TOXIC_VOLLEY 25812 +#define SPELL_POISON_CLOUD 38718 //Only Spell with right dmg. +#define SPELL_ENRAGE 34624 //Changed cause 25790 is casted on gamers too. Same prob with old explosion of twin emperors. + +#define SPELL_CHARGE 26561 +#define SPELL_KNOCKBACK 26027 + +#define SPELL_HEAL 25807 +#define SPELL_FEAR 19408 + +struct boss_kriAI : public ScriptedAI +{ + boss_kriAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Cleave_Timer; + uint32 ToxicVolley_Timer; + uint32 Check_Timer; + + bool VemDead; + bool Death; + + void Reset() + { + Cleave_Timer = 4000 + rand()%4000; + ToxicVolley_Timer = 6000 + rand()%6000; + Check_Timer = 2000; + + VemDead = false; + Death = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + } + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Cleave_Timer + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 5000 + rand()%7000; + } else Cleave_Timer -= diff; + + //ToxicVolley_Timer + if (ToxicVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TOXIC_VOLLEY); + ToxicVolley_Timer = 10000 + rand()%5000; + } else ToxicVolley_Timer -= diff; + + if (me->GetHealth() <= me->GetMaxHealth() * 0.05 && !Death) + { + DoCast(me->getVictim(), SPELL_POISON_CLOUD); + Death = true; + } + + if (!VemDead) + { + //Checking if Vem is dead. If yes we will enrage. + if (Check_Timer <= diff) + { + if (pInstance && pInstance->GetData(DATA_VEMISDEAD)) + { + DoCast(me, SPELL_ENRAGE); + VemDead = true; + } + Check_Timer = 2000; + } else Check_Timer -=diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_vemAI : public ScriptedAI +{ + boss_vemAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Charge_Timer; + uint32 KnockBack_Timer; + uint32 Enrage_Timer; + + bool Enraged; + + void Reset() + { + Charge_Timer = 15000 + rand()%12000; + KnockBack_Timer = 8000 + rand()%12000; + Enrage_Timer = 120000; + + Enraged = false; + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_VEM_DEATH, 0); + if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Charge_Timer + if (Charge_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget) + { + DoCast(pTarget, SPELL_CHARGE); + //me->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, true,1); + AttackStart(pTarget); + } + + Charge_Timer = 8000 + rand()%8000; + } else Charge_Timer -= diff; + + //KnockBack_Timer + if (KnockBack_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKBACK); + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-80); + KnockBack_Timer = 15000 + rand()%10000; + } else KnockBack_Timer -= diff; + + //Enrage_Timer + if (!Enraged && Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else Charge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_yaujAI : public ScriptedAI +{ + boss_yaujAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Heal_Timer; + uint32 Fear_Timer; + uint32 Check_Timer; + + bool VemDead; + + void Reset() + { + Heal_Timer = 25000 + rand()%15000; + Fear_Timer = 12000 + rand()%12000; + Check_Timer = 2000; + + VemDead = false; + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) + // Unlootable if death + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); + } + + for (uint8 i = 0; i < 10; ++i) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + Creature* Summoned = me->SummonCreature(15621,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,90000); + if (Summoned && pTarget) + Summoned->AI()->AttackStart(pTarget); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + DoResetThreat(); + Fear_Timer = 20000; + } else Fear_Timer -= diff; + + //Casting Heal to other twins or herself. + if (Heal_Timer <= diff) + { + if (pInstance) + { + Unit *pKri = Unit::GetUnit((*me), pInstance->GetData64(DATA_KRI)); + Unit *pVem = Unit::GetUnit((*me), pInstance->GetData64(DATA_VEM)); + + switch (urand(0,2)) + { + case 0: + if (pKri) + DoCast(pKri, SPELL_HEAL); + break; + case 1: + if (pVem) + DoCast(pVem, SPELL_HEAL); + break; + case 2: + DoCast(me, SPELL_HEAL); + break; + } + } + + Heal_Timer = 15000+rand()%15000; + } else Heal_Timer -= diff; + + //Checking if Vem is dead. If yes we will enrage. + if (Check_Timer <= diff) + { + if (!VemDead) + { + if (pInstance) + { + if (pInstance->GetData(DATA_VEMISDEAD)) + { + DoCast(me, SPELL_ENRAGE); + VemDead = true; + } + } + } + Check_Timer = 2000; + } else Check_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_yauj(Creature* pCreature) +{ + return new boss_yaujAI (pCreature); +} + +CreatureAI* GetAI_boss_vem(Creature* pCreature) +{ + return new boss_vemAI (pCreature); +} + +CreatureAI* GetAI_boss_kri(Creature* pCreature) +{ + return new boss_kriAI (pCreature); +} + +void AddSC_bug_trio() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kri"; + newscript->GetAI = &GetAI_boss_kri; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_vem"; + newscript->GetAI = &GetAI_boss_vem; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_yauj"; + newscript->GetAI = &GetAI_boss_yauj; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp new file mode 100644 index 00000000000..3e42d16be3a --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp @@ -0,0 +1,1307 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Cthun +SD%Complete: 95 +SDComment: Darkglare tracking issue +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" + +/* + * This is a 2 phases events. Here follows an explanation of the main events and transition between phases and sub-phases. + * + * The first phase is the EYE phase: the Eye of C'Thun is active and C'thun is not active. + * During this phase, the "Eye of C'Thun" alternates between 2 sub-phases: + * - PHASE_EYE_GREEN_BEAM: + * 50 sec phase during which the Eye mainly casts its Green Beam every 3 sec. + * - PHASE_EYE_RED_BEAM: + * 35 sec phase during which the Eye casts its red beam every sec. + * This EYE phase ends when the "Eye of C'Thun" is killed. Then starts the CTHUN phase. + * + * The second phase is the CTHUN phase. The Eye of C'Thun is not active and C'Thun is active. + * This phase starts with the transformation of the Eye into C'Thun (PHASE_CTHUN_TRANSITION). + * After the transformation, C'Thun alternates between 2 sub-phases: + * - PHASE_CTHUN_STOMACH: + * - C'Thun is almost insensible to all damage (99% damage reduction). + * - It spawns 2 tentacles in its stomach. + * - C'Thun swallows players. + * - This sub-phase ends when the 2 tentacles are killed. Swallowed players are regurgitate. + * + * - PHASE_CTHUN_WEAK: + * - weakened C'Thun takes normal damage. + * - This sub-phase ends after 45 secs. + * + * This CTHUN phase ends when C'Thun is killed + * + * Note: + * - the current phase is stored in the instance data to be easily shared between the eye and cthun. + */ + +#define PI 3.14 + +enum Phases +{ + PHASE_NOT_STARTED = 0, + + // Main Phase 1 - EYE + PHASE_EYE_GREEN_BEAM = 1, + PHASE_EYE_RED_BEAM = 2, + + // Main Phase 2 - CTHUN + PHASE_CTHUN_TRANSITION = 3, + PHASE_CTHUN_STOMACH = 4, + PHASE_CTHUN_WEAK = 5, + + PHASE_CTHUN_DONE = 6, +}; + +enum Creatures +{ + MOB_CTHUN_PORTAL = 15896, + + //***** Main Phase 1 ******** + BOSS_EYE_OF_CTHUN = 15589, + MOB_CLAW_TENTACLE = 15725, + MOB_EYE_TENTACLE = 15726, + MOB_SMALL_PORTAL = 15904, + + //***** Main Phase 2 ******** + MOB_BODY_OF_CTHUN = 15809, + MOB_GIANT_CLAW_TENTACLE = 15728, + MOB_GIANT_EYE_TENTACLE = 15334, + MOB_FLESH_TENTACLE = 15802, + MOB_GIANT_PORTAL = 15910, +}; + +enum Spells +{ + //***** Main Phase 1 ******** + //Eye Spells + SPELL_FREEZE_ANIM = 16245, + SPELL_GREEN_BEAM = 26134, + SPELL_DARK_GLARE = 26029, + SPELL_RED_COLORATION = 22518, //Probably not the right spell but looks similar + + //Eye Tentacles Spells + SPELL_MIND_FLAY = 26143, + + //Claw Tentacles Spells + SPELL_GROUND_RUPTURE = 26139, + SPELL_HAMSTRING = 26141, + + //***** Main Phase 2 ****** + //Body spells + //#define SPELL_CARAPACE_CTHUN 26156 //Was removed from client dbcs + SPELL_TRANSFORM = 26232, + SPELL_PURPLE_COLORATION = 22581, //Probably not the right spell but looks similar + + //Eye Tentacles Spells + //SAME AS PHASE1 + + //Giant Claw Tentacles + SPELL_MASSIVE_GROUND_RUPTURE = 26100, + + //Also casts Hamstring + SPELL_THRASH = 3391, + + //Giant Eye Tentacles + //CHAIN CASTS "SPELL_GREEN_BEAM" + + //Stomach Spells + SPELL_MOUTH_TENTACLE = 26332, + SPELL_EXIT_STOMACH_KNOCKBACK = 25383, + SPELL_DIGESTIVE_ACID = 26476, +}; + +enum Actions +{ + ACTION_FLESH_TENTACLE_KILLED = 1, +}; + +enum Yells +{ + //Text emote + EMOTE_WEAKENED = -1531011, + + //****** Out of Combat ****** + // Random Wispers - No txt only sound + // The random sound is chosen by the client. + RANDOM_SOUND_WHISPER = 8663, +}; + +//Stomach Teleport positions +#define STOMACH_X -8562.0f +#define STOMACH_Y 2037.0f +#define STOMACH_Z -70.0f +#define STOMACH_O 5.05f + +//Flesh tentacle positions +const Position FleshTentaclePos[2] = +{ + { -8571.0f, 1990.0f, -98.0f, 1.22f}, + { -8525.0f, 1994.0f, -98.0f, 2.12f}, +}; + +//Kick out position +const Position KickPos = { -8545.0f, 1984.0f, -96.0f}; + +struct eye_of_cthunAI : public Scripted_NoMovementAI +{ + eye_of_cthunAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInst = c->GetInstanceData(); + if (!pInst) + error_log("TSCR: No Instance eye_of_cthunAI"); + } + + ScriptedInstance* pInst; + + //Global variables + uint32 PhaseTimer; + + //Eye beam phase + uint32 BeamTimer; + uint32 EyeTentacleTimer; + uint32 ClawTentacleTimer; + + //Dark Glare phase + uint32 DarkGlareTick; + uint32 DarkGlareTickTimer; + float DarkGlareAngle; + bool ClockWise; + + void Reset() + { + //Phase information + PhaseTimer = 50000; //First dark glare in 50 seconds + + //Eye beam phase 50 seconds + BeamTimer = 3000; + EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam + ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam) + + //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks) + DarkGlareTick = 0; + DarkGlareTickTimer = 1000; + DarkGlareAngle = 0; + ClockWise = false; + + //Reset flags + me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_ON); + + //Reset Phase + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); + + //to avoid having a following void zone + Creature* pPortal= me->FindNearestCreature(MOB_CTHUN_PORTAL, 10); + if (pPortal) + pPortal->SetReactState(REACT_PASSIVE); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); + } + + void SpawnEyeTentacle(float x, float y) + { + if (Creature* Spawned = DoSpawnCreature(MOB_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500)) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + if (Spawned->AI()) + Spawned->AI()->AttackStart(pTarget); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //No instance + if (!pInst) + return; + + uint32 currentPhase = pInst->GetData(DATA_CTHUN_PHASE); + if (currentPhase == PHASE_EYE_GREEN_BEAM || currentPhase == PHASE_EYE_RED_BEAM) + { + // EyeTentacleTimer + if (EyeTentacleTimer <= diff) + { + //Spawn the 8 Eye Tentacles in the corret spots + SpawnEyeTentacle(0, 20); //south + SpawnEyeTentacle(10, 10); //south west + SpawnEyeTentacle(20, 0); //west + SpawnEyeTentacle(10, -10); //north west + + SpawnEyeTentacle(0, -20); //north + SpawnEyeTentacle(-10, -10); //north east + SpawnEyeTentacle(-20, 0); // east + SpawnEyeTentacle(-10, 10); // south east + + EyeTentacleTimer = 45000; + } else EyeTentacleTimer -= diff; + } + + switch (currentPhase) + { + case PHASE_EYE_GREEN_BEAM: + //BeamTimer + if (BeamTimer <= diff) + { + //SPELL_GREEN_BEAM + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + me->InterruptNonMeleeSpells(false); + DoCast(pTarget, SPELL_GREEN_BEAM); + + //Correctly update our target + me->SetUInt64Value(UNIT_FIELD_TARGET, pTarget->GetGUID()); + } + + //Beam every 3 seconds + BeamTimer = 3000; + } else BeamTimer -= diff; + + //ClawTentacleTimer + if (ClawTentacleTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + Creature* Spawned = NULL; + + //Spawn claw tentacle on the random target + Spawned = me->SummonCreature(MOB_CLAW_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500); + + if (Spawned && Spawned->AI()) + Spawned->AI()->AttackStart(pTarget); + } + + //One claw tentacle every 12.5 seconds + ClawTentacleTimer = 12500; + } else ClawTentacleTimer -= diff; + + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch to Dark Beam + pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_RED_BEAM); + + me->InterruptNonMeleeSpells(false); + me->SetReactState(REACT_PASSIVE); + + //Remove any target + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Select random target for dark beam to start on + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + //Face our target + DarkGlareAngle = me->GetAngle(pTarget); + DarkGlareTickTimer = 1000; + DarkGlareTick = 0; + ClockWise = RAND(true, false); + } + + //Add red coloration to C'thun + DoCast(me, SPELL_RED_COLORATION, true); + + //Freeze animation + DoCast(me, SPELL_FREEZE_ANIM); + me->SetOrientation(DarkGlareAngle); + me->StopMoving(); + + //Darkbeam for 35 seconds + PhaseTimer = 35000; + } else PhaseTimer -= diff; + + break; + + case PHASE_EYE_RED_BEAM: + if (DarkGlareTick < 35) + if (DarkGlareTickTimer <= diff) + { + //Set angle and cast + if (ClockWise) + me->SetOrientation(DarkGlareAngle + ((float)DarkGlareTick*PI/35)); + else + me->SetOrientation(DarkGlareAngle - ((float)DarkGlareTick*PI/35)); + + me->StopMoving(); + + //Actual dark glare cast, maybe something missing here? + DoCast(me, SPELL_DARK_GLARE, false); + + //Increase tick + ++DarkGlareTick; + + //1 second per tick + DarkGlareTickTimer = 1000; + } else DarkGlareTickTimer -= diff; + + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch to Eye Beam + pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); + + BeamTimer = 3000; + ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam) + + me->InterruptNonMeleeSpells(false); + + //Remove Red coloration from c'thun + me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + + //set it back to aggressive + me->SetReactState(REACT_AGGRESSIVE); + + //Eye Beam for 50 seconds + PhaseTimer = 50000; + } else PhaseTimer -= diff; + + break; + + //Transition phase + case PHASE_CTHUN_TRANSITION: + //Remove any target + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + me->SetHealth(0); + me->SetVisibility(VISIBILITY_OFF); + break; + + //Dead phase + case PHASE_CTHUN_DONE: + Creature* pPortal= me->FindNearestCreature(MOB_CTHUN_PORTAL, 10); + if (pPortal) + pPortal->ForcedDespawn(); + + me->ForcedDespawn(); + break; + } + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + //No instance + if (!pInst) + return; + + switch (pInst->GetData(DATA_CTHUN_PHASE)) + { + case PHASE_EYE_GREEN_BEAM: + case PHASE_EYE_RED_BEAM: + //Only if it will kill + if (damage < me->GetHealth()) + return; + + //Fake death in phase 0 or 1 (green beam or dark glare phase) + me->InterruptNonMeleeSpells(false); + + //Remove Red coloration from c'thun + me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); + + //Reset to normal emote state and prevent select and attack + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Remove Target field + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Death animation/respawning; + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_TRANSITION); + + me->SetHealth(0); + damage = 0; + + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + break; + + case PHASE_CTHUN_DONE: + //Allow death here + return; + + default: + //Prevent death in these phases + damage = 0; + return; + } + } +}; + +struct cthunAI : public Scripted_NoMovementAI +{ + cthunAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + + pInst = c->GetInstanceData(); + if (!pInst) + error_log("TSCR: No Instance eye_of_cthunAI"); + } + + ScriptedInstance* pInst; + + //Out of combat whisper timer + uint32 WisperTimer; + + //Global variables + uint32 PhaseTimer; + + //------------------- + + //Phase transition + uint64 HoldPlayer; + + //Body Phase + uint32 EyeTentacleTimer; + uint8 FleshTentaclesKilled; + uint32 GiantClawTentacleTimer; + uint32 GiantEyeTentacleTimer; + uint32 StomachAcidTimer; + uint32 StomachEnterTimer; + uint32 StomachEnterVisTimer; + uint64 StomachEnterTarget; + + //Stomach map, bool = true then in stomach + UNORDERED_MAP Stomach_Map; + + void Reset() + { + //One random wisper every 90 - 300 seconds + WisperTimer = 90000; + + //Phase information + PhaseTimer = 10000; //Emerge in 10 seconds + + //No hold player for transition + HoldPlayer = 0; + + //Body Phase + EyeTentacleTimer = 30000; + FleshTentaclesKilled = 0; + GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat) + GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat) + StomachAcidTimer = 4000; //Every 4 seconds + StomachEnterTimer = 10000; //Every 10 seconds + StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer + StomachEnterTarget = 0; //Target to be teleported to stomach + + //Clear players in stomach and outside + Stomach_Map.clear(); + + //Reset flags + me->RemoveAurasDueToSpell(SPELL_TRANSFORM); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_OFF); + + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void SpawnEyeTentacle(float x, float y) + { + Creature* Spawned; + Spawned = DoSpawnCreature(MOB_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500); + if (Spawned && Spawned->AI()) + if (Unit *pTarget = SelectRandomNotStomach()) + Spawned->AI()->AttackStart(pTarget); + } + + Unit* SelectRandomNotStomach() + { + if (Stomach_Map.empty()) + return NULL; + + UNORDERED_MAP::const_iterator i = Stomach_Map.begin(); + + std::list temp; + std::list::const_iterator j; + + //Get all players in map + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*me, i->first); + + //Only units out of stomach + if (pUnit && i->second == false) + temp.push_back(pUnit); + + ++i; + } + + if (temp.empty()) + return NULL; + + j = temp.begin(); + + //Get random but only if we have more than one unit on threat list + if (temp.size() > 1) + advance (j , rand() % (temp.size() - 1)); + + return (*j); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + { + //No target so we'll use this section to do our random wispers instance wide + //WisperTimer + if (WisperTimer <= diff) + { + Map* pMap = me->GetMap(); + if (!pMap->IsDungeon()) return; + + //Play random sound to the zone + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) + { + if (Player* pPlr = itr->getSource()) + pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER,pPlr); + } + } + + //One random wisper every 90 - 300 seconds + WisperTimer = urand(90000,300000); + } else WisperTimer -= diff; + + return; + } + + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //No instance + if (!pInst) + return; + + uint32 currentPhase = pInst->GetData(DATA_CTHUN_PHASE); + if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK) + { + // EyeTentacleTimer + if (EyeTentacleTimer <= diff) + { + //Spawn the 8 Eye Tentacles in the corret spots + SpawnEyeTentacle(0, 20); //south + SpawnEyeTentacle(10, 10); //south west + SpawnEyeTentacle(20, 0); //west + SpawnEyeTentacle(10, -10); //north west + + SpawnEyeTentacle(0, -20); //north + SpawnEyeTentacle(-10, -10); //north east + SpawnEyeTentacle(-20, 0); // east + SpawnEyeTentacle(-10, 10); // south east + + EyeTentacleTimer = 30000; // every 30sec in phase 2 + } else EyeTentacleTimer -= diff; + } + + switch (currentPhase) + { + //Transition phase + case PHASE_CTHUN_TRANSITION: + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); + + //Switch to c'thun model + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_TRANSFORM, false); + me->SetHealth(me->GetMaxHealth()); + + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + //Emerging phase + //AttackStart(Unit::GetUnit(*me, HoldpPlayer)); + DoZoneInCombat(); + + //Place all units in threat list on outside of stomach + Stomach_Map.clear(); + + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + //Outside stomach + Stomach_Map[(*i)->getUnitGuid()] = false; + } + + //Spawn 2 flesh tentacles + FleshTentaclesKilled = 0; + + //Spawn flesh tentacle + for (uint8 i = 0; i < 2; i++) + { + Creature* spawned = me->SummonCreature(MOB_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); + if (!spawned) + ++FleshTentaclesKilled; + } + + PhaseTimer = 0; + } else PhaseTimer -= diff; + + break; + + //Body Phase + case PHASE_CTHUN_STOMACH: + //Remove Target field + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + //Weaken + if (FleshTentaclesKilled > 1) + { + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_WEAK); + + DoScriptText(EMOTE_WEAKENED, me); + PhaseTimer = 45000; + + DoCast(me, SPELL_PURPLE_COLORATION, true); + + UNORDERED_MAP::iterator i = Stomach_Map.begin(); + + //Kick all players out of stomach + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*me, i->first); + + //Only move units in stomach + if (pUnit && i->second == true) + { + //Teleport each player out + DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+10, rand()%6); + + //Cast knockback on them + DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); + + //Remove the acid debuff + pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); + + i->second = false; + } + ++i; + } + + return; + } + + //Stomach acid + if (StomachAcidTimer <= diff) + { + //Apply aura to all players in stomach + UNORDERED_MAP::iterator i = Stomach_Map.begin(); + + while (i != Stomach_Map.end()) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*me, i->first); + + //Only apply to units in stomach + if (pUnit && i->second == true) + { + //Cast digestive acid on them + DoCast(pUnit, SPELL_DIGESTIVE_ACID, true); + + //Check if player should be kicked from stomach + if (pUnit->IsWithinDist3d(&KickPos, 15.0f)) + { + //Teleport each player out + DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+10, rand()%6); + + //Cast knockback on them + DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); + + //Remove the acid debuff + pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); + + i->second = false; + } + } + ++i; + } + + StomachAcidTimer = 4000; + } else StomachAcidTimer -= diff; + + //Stomach Enter Timer + if (StomachEnterTimer <= diff) + { + if (Unit *pTarget = SelectRandomNotStomach()) + { + //Set target in stomach + Stomach_Map[pTarget->GetGUID()] = true; + pTarget->InterruptNonMeleeSpells(false); + pTarget->CastSpell(pTarget, SPELL_MOUTH_TENTACLE, true, NULL, NULL, me->GetGUID()); + StomachEnterTarget = pTarget->GetGUID(); + StomachEnterVisTimer = 3800; + } + + StomachEnterTimer = 13800; + } else StomachEnterTimer -= diff; + + if (StomachEnterVisTimer && StomachEnterTarget) + if (StomachEnterVisTimer <= diff) + { + //Check for valid player + Unit* pUnit = Unit::GetUnit(*me, StomachEnterTarget); + + if (pUnit) + { + DoTeleportPlayer(pUnit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O); + } + + StomachEnterTarget = 0; + StomachEnterVisTimer = 0; + } else StomachEnterVisTimer -= diff; + + //GientClawTentacleTimer + if (GiantClawTentacleTimer <= diff) + { + if (Unit *pTarget = SelectRandomNotStomach()) + { + //Spawn claw tentacle on the random target + if (Creature* spawned = me->SummonCreature(MOB_GIANT_CLAW_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500)) + if (spawned->AI()) + spawned->AI()->AttackStart(pTarget); + } + + //One giant claw tentacle every minute + GiantClawTentacleTimer = 60000; + } else GiantClawTentacleTimer -= diff; + + //GiantEyeTentacleTimer + if (GiantEyeTentacleTimer <= diff) + { + if (Unit *pTarget = SelectRandomNotStomach()) + { + //Spawn claw tentacle on the random target + if (Creature* spawned = me->SummonCreature(MOB_GIANT_EYE_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500)) + if (spawned->AI()) + spawned->AI()->AttackStart(pTarget); + } + + //One giant eye tentacle every minute + GiantEyeTentacleTimer = 60000; + } else GiantEyeTentacleTimer -= diff; + + break; + + //Weakened state + case PHASE_CTHUN_WEAK: + //PhaseTimer + if (PhaseTimer <= diff) + { + //Switch + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); + + //Remove purple coloration + me->RemoveAurasDueToSpell(SPELL_PURPLE_COLORATION); + + //Spawn 2 flesh tentacles + FleshTentaclesKilled = 0; + + //Spawn flesh tentacle + for (uint8 i = 0; i < 2; i++) + { + Creature* spawned = me->SummonCreature(MOB_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); + if (!spawned) + ++FleshTentaclesKilled; + } + + PhaseTimer = 0; + } else PhaseTimer -= diff; + + break; + } + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInst) + pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + //No instance + if (!pInst) + return; + + switch (pInst->GetData(DATA_CTHUN_PHASE)) + { + case PHASE_CTHUN_STOMACH: + //Not weakened so reduce damage by 99% + damage /= 100; + if (damage == 0) + damage = 1; + + //Prevent death in non-weakened state + if (damage >= me->GetHealth()) + damage = 0; + + return; + + case PHASE_CTHUN_WEAK: + //Weakened - takes normal damage + return; + + default: + damage = 0; + break; + } + } + + void DoAction(const int32 param) + { + switch(param) + { + case ACTION_FLESH_TENTACLE_KILLED: + ++FleshTentaclesKilled; + break; + } + } +}; + +struct eye_tentacleAI : public Scripted_NoMovementAI +{ + eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + } + + uint32 MindflayTimer; + uint32 KillSelfTimer; + uint64 Portal; + + void JustDied(Unit* /*who*/) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + } + + void Reset() + { + //Mind flay half a second after we spawn + MindflayTimer = 500; + + //This prevents eyes from overlapping + KillSelfTimer = 35000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //KillSelfTimer + if (KillSelfTimer <= diff) + { + me->Kill(me); + return; + } else KillSelfTimer -= diff; + + //MindflayTimer + if (MindflayTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && !pTarget->HasAura(SPELL_DIGESTIVE_ACID)) + DoCast(pTarget, SPELL_MIND_FLAY); + + //Mindflay every 10 seconds + MindflayTimer = 10000; + } else MindflayTimer -= diff; + } +}; + +struct claw_tentacleAI : public Scripted_NoMovementAI +{ + claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + + if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + } + + uint32 GroundRuptureTimer; + uint32 HamstringTimer; + uint32 EvadeTimer; + uint64 Portal; + + void JustDied(Unit* /*who*/) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + } + + void Reset() + { + //First rupture should happen half a second after we spawn + GroundRuptureTimer = 500; + HamstringTimer = 2000; + EvadeTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //EvadeTimer + if (!me->IsWithinMeleeRange(me->getVictim())) + if (EvadeTimer <= diff) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + + //Dissapear and reappear at new position + me->SetVisibility(VISIBILITY_OFF); + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget) + { + me->Kill(me); + return; + } + + if (!pTarget->HasAura(SPELL_DIGESTIVE_ACID)) + { + me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); + if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + + GroundRuptureTimer = 500; + HamstringTimer = 2000; + EvadeTimer = 5000; + AttackStart(pTarget); + } + + me->SetVisibility(VISIBILITY_ON); + } else EvadeTimer -= diff; + + //GroundRuptureTimer + if (GroundRuptureTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); + GroundRuptureTimer = 30000; + } else GroundRuptureTimer -= diff; + + //HamstringTimer + if (HamstringTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + HamstringTimer = 5000; + } else HamstringTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct giant_claw_tentacleAI : public Scripted_NoMovementAI +{ + giant_claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + + if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + } + + uint32 GroundRuptureTimer; + uint32 ThrashTimer; + uint32 HamstringTimer; + uint32 EvadeTimer; + uint64 Portal; + + void JustDied(Unit* /*who*/) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + } + + void Reset() + { + //First rupture should happen half a second after we spawn + GroundRuptureTimer = 500; + HamstringTimer = 2000; + ThrashTimer = 5000; + EvadeTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //EvadeTimer + if (!me->IsWithinMeleeRange(me->getVictim())) + if (EvadeTimer <= diff) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + + //Dissapear and reappear at new position + me->SetVisibility(VISIBILITY_OFF); + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!pTarget) + { + me->Kill(me); + return; + } + + if (!pTarget->HasAura(SPELL_DIGESTIVE_ACID)) + { + me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); + if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + + GroundRuptureTimer = 500; + HamstringTimer = 2000; + ThrashTimer = 5000; + EvadeTimer = 5000; + AttackStart(pTarget); + } + + me->SetVisibility(VISIBILITY_ON); + + } else EvadeTimer -= diff; + + //GroundRuptureTimer + if (GroundRuptureTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); + GroundRuptureTimer = 30000; + } else GroundRuptureTimer -= diff; + + //ThrashTimer + if (ThrashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_THRASH); + ThrashTimer = 10000; + } else ThrashTimer -= diff; + + //HamstringTimer + if (HamstringTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMSTRING); + HamstringTimer = 10000; + } else HamstringTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct giant_eye_tentacleAI : public Scripted_NoMovementAI +{ + giant_eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + + if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) + { + pPortal->SetReactState(REACT_PASSIVE); + Portal = pPortal->GetGUID(); + } + } + + uint32 BeamTimer; + uint64 Portal; + + void JustDied(Unit* /*who*/) + { + if (Unit* p = Unit::GetUnit(*me, Portal)) + p->Kill(p); + } + + void Reset() + { + //Green Beam half a second after we spawn + BeamTimer = 500; + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + + //BeamTimer + if (BeamTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && !pTarget->HasAura(SPELL_DIGESTIVE_ACID)) + DoCast(pTarget, SPELL_GREEN_BEAM); + + //Beam every 2 seconds + BeamTimer = 2100; + } else BeamTimer -= diff; + } +}; + +struct flesh_tentacleAI : public Scripted_NoMovementAI +{ + flesh_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) + { + SetCombatMovement(false); + } + + void JustDied(Unit* /*killer*/) + { + if (CAST_SUM(me)) + if (Creature* pSummoner = CAST_CRE(CAST_SUM(me)->GetSummoner())) + if (pSummoner->AI()) + pSummoner->AI()->DoAction(ACTION_FLESH_TENTACLE_KILLED); + } +}; + +//GetAIs +CreatureAI* GetAI_eye_of_cthun(Creature* pCreature) +{ + return new eye_of_cthunAI (pCreature); +} + +CreatureAI* GetAI_cthun(Creature* pCreature) +{ + return new cthunAI (pCreature); +} + +CreatureAI* GetAI_eye_tentacle(Creature* pCreature) +{ + return new eye_tentacleAI (pCreature); +} + +CreatureAI* GetAI_claw_tentacle(Creature* pCreature) +{ + return new claw_tentacleAI (pCreature); +} + +CreatureAI* GetAI_giant_claw_tentacle(Creature* pCreature) +{ + return new giant_claw_tentacleAI (pCreature); +} + +CreatureAI* GetAI_giant_eye_tentacle(Creature* pCreature) +{ + return new giant_eye_tentacleAI (pCreature); +} + +CreatureAI* GetAI_flesh_tentacle(Creature* pCreature) +{ + return new flesh_tentacleAI (pCreature); +} + +void AddSC_boss_cthun() +{ + Script *newscript; + + //Eye + newscript = new Script; + newscript->Name = "boss_eye_of_cthun"; + newscript->GetAI = &GetAI_eye_of_cthun; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_cthun"; + newscript->GetAI = &GetAI_cthun; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_eye_tentacle"; + newscript->GetAI = &GetAI_eye_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_claw_tentacle"; + newscript->GetAI = &GetAI_claw_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_giant_claw_tentacle"; + newscript->GetAI = &GetAI_giant_claw_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_giant_eye_tentacle"; + newscript->GetAI = &GetAI_giant_eye_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_giant_flesh_tentacle"; + newscript->GetAI = &GetAI_flesh_tentacle; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp new file mode 100644 index 00000000000..32d5ec1c3df --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Fankriss +SD%Complete: 100 +SDComment: sound not implemented +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" + +#define SOUND_SENTENCE_YOU 8588 +#define SOUND_SERVE_TO 8589 +#define SOUND_LAWS 8590 +#define SOUND_TRESPASS 8591 +#define SOUND_WILL_BE 8592 + +#define SPELL_MORTAL_WOUND 28467 +#define SPELL_ROOT 28858 + +// Enrage for his spawns +#define SPELL_ENRAGE 28798 + +struct boss_fankrissAI : public ScriptedAI +{ + boss_fankrissAI(Creature *c) : ScriptedAI(c) {} + + uint32 MortalWound_Timer; + uint32 SpawnHatchlings_Timer; + uint32 SpawnSpawns_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Hatchling; + Creature* Spawn; + + void Reset() + { + MortalWound_Timer = 10000 + rand()%5000; + SpawnHatchlings_Timer = 6000 + rand()%6000; + SpawnSpawns_Timer = 15000 + rand()%30000; + } + + void SummonSpawn(Unit* victim) + { + if (!victim) + return; + + Rand = 10 + (rand()%10); + switch (rand()%2) + { + case 0: RandX = 0 - Rand; break; + case 1: RandX = 0 + Rand; break; + } + Rand = 0; + Rand = 10 + (rand()%10); + switch (rand()%2) + { + case 0: RandY = 0 - Rand; break; + case 1: RandY = 0 + Rand; break; + } + Rand = 0; + Spawn = DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); + if (Spawn) + Spawn->AI()->AttackStart(victim); + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //MortalWound_Timer + if (MortalWound_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + MortalWound_Timer = 10000 + rand()%10000; + } else MortalWound_Timer -= diff; + + //Summon 1-3 Spawns of Fankriss at random time. + if (SpawnSpawns_Timer <= diff) + { + switch (urand(0,2)) + { + case 0: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + case 1: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + case 2: + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); + break; + } + SpawnSpawns_Timer = 30000 + rand()%30000; + } else SpawnSpawns_Timer -= diff; + + // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer. + //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot. + if (me->GetHealth()*100 / me->GetMaxHealth() > 3) + { + if (SpawnHatchlings_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SPELL_ROOT); + + if (DoGetThreat(pTarget)) + DoModifyThreatPercent(pTarget, -100); + + switch(urand(0,2)) + { + case 0: + DoTeleportPlayer(pTarget, -8106.0142,1289.2900,-74.419533,5.112); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + break; + case 1: + DoTeleportPlayer(pTarget, -7990.135354,1155.1907,-78.849319,2.608); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + break; + case 2: + DoTeleportPlayer(pTarget,-8159.7753,1127.9064,-76.868660,0.675); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (Hatchling) + Hatchling->AI()->AttackStart(pTarget); + break; + } + } + SpawnHatchlings_Timer = 45000 + rand()%15000; + } else SpawnHatchlings_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_fankriss(Creature* pCreature) +{ + return new boss_fankrissAI (pCreature); +} + +void AddSC_boss_fankriss() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_fankriss"; + newscript->GetAI = &GetAI_boss_fankriss; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp new file mode 100644 index 00000000000..f0e3a425edd --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp @@ -0,0 +1,148 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Huhuran +SD%Complete: 100 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_GENERIC_FRENZY_KILL -1000001 +#define EMOTE_GENERIC_BERSERK -1000004 + +#define SPELL_FRENZY 26051 +#define SPELL_BERSERK 26068 +#define SPELL_POISONBOLT 26052 +#define SPELL_NOXIOUSPOISON 26053 +#define SPELL_WYVERNSTING 26180 +#define SPELL_ACIDSPIT 26050 + +struct boss_huhuranAI : public ScriptedAI +{ + boss_huhuranAI(Creature *c) : ScriptedAI(c) {} + + uint32 Frenzy_Timer; + uint32 Wyvern_Timer; + uint32 Spit_Timer; + uint32 PoisonBolt_Timer; + uint32 NoxiousPoison_Timer; + uint32 FrenzyBack_Timer; + + bool Frenzy; + bool Berserk; + + void Reset() + { + Frenzy_Timer = 25000 + rand()%10000; + Wyvern_Timer = 18000 + rand()%10000; + Spit_Timer = 8000; + PoisonBolt_Timer = 4000; + NoxiousPoison_Timer = 10000 + rand()%10000; + FrenzyBack_Timer = 15000; + + Frenzy = false; + Berserk = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frenzy_Timer + if (!Frenzy && Frenzy_Timer <= diff) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); + Frenzy = true; + PoisonBolt_Timer = 3000; + Frenzy_Timer = 25000 + rand()%10000; + } else Frenzy_Timer -= diff; + + // Wyvern Timer + if (Wyvern_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_WYVERNSTING); + Wyvern_Timer = 15000 + rand()%17000; + } else Wyvern_Timer -= diff; + + //Spit Timer + if (Spit_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ACIDSPIT); + Spit_Timer = 5000 + rand()%5000; + } else Spit_Timer -= diff; + + //NoxiousPoison_Timer + if (NoxiousPoison_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_NOXIOUSPOISON); + NoxiousPoison_Timer = 12000 + rand()%12000; + } else NoxiousPoison_Timer -= diff; + + //PoisonBolt only if frenzy or berserk + if (Frenzy || Berserk) + { + if (PoisonBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISONBOLT); + PoisonBolt_Timer = 3000; + } else PoisonBolt_Timer -= diff; + } + + //FrenzyBack_Timer + if (Frenzy && FrenzyBack_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + Frenzy = false; + FrenzyBack_Timer = 15000; + } else FrenzyBack_Timer -= diff; + + if (!Berserk && me->GetHealth()*100 / me->GetMaxHealth() < 31) + { + me->InterruptNonMeleeSpells(false); + DoScriptText(EMOTE_GENERIC_BERSERK, me); + DoCast(me, SPELL_BERSERK); + Berserk = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_huhuran(Creature* pCreature) +{ + return new boss_huhuranAI (pCreature); +} + +void AddSC_boss_huhuran() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_huhuran"; + newscript->GetAI = &GetAI_boss_huhuran; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp new file mode 100644 index 00000000000..1dd642c38f4 --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp @@ -0,0 +1,140 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ouro +SD%Complete: 85 +SDComment: No model for submerging. Currently just invisible. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" + +#define SPELL_SWEEP 26103 +#define SPELL_SANDBLAST 26102 +#define SPELL_GROUND_RUPTURE 26100 +#define SPELL_BIRTH 26262 //The Birth Animation + +#define SPELL_DIRTMOUND_PASSIVE 26092 + +struct boss_ouroAI : public ScriptedAI +{ + boss_ouroAI(Creature *c) : ScriptedAI(c) {} + + uint32 Sweep_Timer; + uint32 SandBlast_Timer; + uint32 Submerge_Timer; + uint32 Back_Timer; + uint32 ChangeTarget_Timer; + uint32 Spawn_Timer; + + bool Enrage; + bool Submerged; + + void Reset() + { + Sweep_Timer = 5000 + rand()%5000; + SandBlast_Timer = 20000 + rand()%15000; + Submerge_Timer = 90000 + rand()%60000; + Back_Timer = 30000 + rand()%15000; + ChangeTarget_Timer = 5000 + rand()%3000; + Spawn_Timer = 10000 + rand()%10000; + + Enrage = false; + Submerged = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoCast(me->getVictim(), SPELL_BIRTH); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sweep_Timer + if (!Submerged && Sweep_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SWEEP); + Sweep_Timer = 15000 + rand()%15000; + } else Sweep_Timer -= diff; + + //SandBlast_Timer + if (!Submerged && SandBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SANDBLAST); + SandBlast_Timer = 20000 + rand()%15000; + } else SandBlast_Timer -= diff; + + //Submerge_Timer + if (!Submerged && Submerge_Timer <= diff) + { + //Cast + me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(35); + DoCast(me, SPELL_DIRTMOUND_PASSIVE); + + Submerged = true; + Back_Timer = 30000 + rand()%15000; + } else Submerge_Timer -= diff; + + //ChangeTarget_Timer + if (Submerged && ChangeTarget_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (pTarget) + DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); + + ChangeTarget_Timer = 10000 + rand()%10000; + } else ChangeTarget_Timer -= diff; + + //Back_Timer + if (Submerged && Back_Timer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + + DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); + + Submerged = false; + Submerge_Timer = 60000 + rand()%60000; + } else Back_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ouro(Creature* pCreature) +{ + return new boss_ouroAI (pCreature); +} + +void AddSC_boss_ouro() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ouro"; + newscript->GetAI = &GetAI_boss_ouro; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp new file mode 100644 index 00000000000..282a25b7215 --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp @@ -0,0 +1,297 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Sartura +SD%Complete: 95 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1531008 +#define SAY_SLAY -1531009 +#define SAY_DEATH -1531010 + +#define SPELL_WHIRLWIND 26083 +#define SPELL_ENRAGE 28747 //Not sure if right ID. +#define SPELL_ENRAGEHARD 28798 + +//Guard Spell +#define SPELL_WHIRLWINDADD 26038 +#define SPELL_KNOCKBACK 26027 + +struct boss_sarturaAI : public ScriptedAI +{ + boss_sarturaAI(Creature *c) : ScriptedAI(c) {} + + uint32 WhirlWind_Timer; + uint32 WhirlWindRandom_Timer; + uint32 WhirlWindEnd_Timer; + uint32 AggroReset_Timer; + uint32 AggroResetEnd_Timer; + uint32 EnrageHard_Timer; + + bool Enraged; + bool EnragedHard; + bool WhirlWind; + bool AggroReset; + + void Reset() + { + WhirlWind_Timer = 30000; + WhirlWindRandom_Timer = 3000 + rand()%4000; + WhirlWindEnd_Timer = 15000; + AggroReset_Timer = 45000 + rand()%10000; + AggroResetEnd_Timer = 5000; + EnrageHard_Timer = 10*60000; + + WhirlWind = false; + AggroReset = false; + Enraged = false; + EnragedHard = false; + + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_SLAY, me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (WhirlWind) + { + if (WhirlWindRandom_Timer <= diff) + { + //Attack random Gamers + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget) + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + + WhirlWindRandom_Timer = 3000 + rand()%4000; + } else WhirlWindRandom_Timer -= diff; + + if (WhirlWindEnd_Timer <= diff) + { + WhirlWind = false; + WhirlWind_Timer = 25000 + rand()%15000; + } else WhirlWindEnd_Timer -= diff; + } + + if (!WhirlWind) + { + if (WhirlWind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + WhirlWind = true; + WhirlWindEnd_Timer = 15000; + } else WhirlWind_Timer -= diff; + + if (AggroReset_Timer <= diff) + { + //Attack random Gamers + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget) + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + + AggroReset = true; + AggroReset_Timer = 2000 + rand()%3000; + } else AggroReset_Timer -= diff; + + if (AggroReset) + { + if (AggroResetEnd_Timer <= diff) + { + AggroReset = false; + AggroResetEnd_Timer = 5000; + AggroReset_Timer = 35000 + rand()%10000; + } else AggroResetEnd_Timer -= diff; + } + + //If she is 20% enrage + if (!Enraged) + { + if (me->GetHealth()*100 / me->GetMaxHealth() <= 20 && !me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } + } + + //After 10 minutes hard enrage + if (!EnragedHard) + { + if (EnrageHard_Timer <= diff) + { + DoCast(me, SPELL_ENRAGEHARD); + EnragedHard = true; + } else EnrageHard_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + } +}; + +struct mob_sartura_royal_guardAI : public ScriptedAI +{ + mob_sartura_royal_guardAI(Creature *c) : ScriptedAI(c) {} + + uint32 WhirlWind_Timer; + uint32 WhirlWindRandom_Timer; + uint32 WhirlWindEnd_Timer; + uint32 AggroReset_Timer; + uint32 AggroResetEnd_Timer; + uint32 KnockBack_Timer; + + bool WhirlWind; + bool AggroReset; + + void Reset() + { + WhirlWind_Timer = 30000; + WhirlWindRandom_Timer = 3000 + rand()%4000; + WhirlWindEnd_Timer = 15000; + AggroReset_Timer = 45000 + rand()%10000; + AggroResetEnd_Timer = 5000; + KnockBack_Timer = 10000; + + WhirlWind = false; + AggroReset = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!WhirlWind && WhirlWind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWINDADD); + WhirlWind = true; + WhirlWind_Timer = 25000 + rand()%15000; + WhirlWindEnd_Timer = 15000; + } else WhirlWind_Timer -= diff; + + if (WhirlWind) + { + if (WhirlWindRandom_Timer <= diff) + { + //Attack random Gamers + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget) + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + + WhirlWindRandom_Timer = 3000 + rand()%4000; + } else WhirlWindRandom_Timer -= diff; + + if (WhirlWindEnd_Timer <= diff) + { + WhirlWind = false; + } else WhirlWindEnd_Timer -= diff; + } + + if (!WhirlWind) + { + if (AggroReset_Timer <= diff) + { + //Attack random Gamers + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget) + me->AddThreat(pTarget, 1.0f); + me->TauntApply(pTarget); + AttackStart(pTarget); + + AggroReset = true; + AggroReset_Timer = 2000 + rand()%3000; + } else AggroReset_Timer -= diff; + + if (KnockBack_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWINDADD); + KnockBack_Timer = 10000 + rand()%10000; + } else KnockBack_Timer -= diff; + } + + if (AggroReset) + { + if (AggroResetEnd_Timer <= diff) + { + AggroReset = false; + AggroResetEnd_Timer = 5000; + AggroReset_Timer = 30000 + rand()%10000; + } else AggroResetEnd_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_sartura(Creature* pCreature) +{ + return new boss_sarturaAI (pCreature); +} + +CreatureAI* GetAI_mob_sartura_royal_guard(Creature* pCreature) +{ + return new mob_sartura_royal_guardAI (pCreature); +} + +void AddSC_boss_sartura() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_sartura"; + newscript->GetAI = &GetAI_boss_sartura; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_sartura_royal_guard"; + newscript->GetAI = &GetAI_mob_sartura_royal_guard; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp new file mode 100644 index 00000000000..7e52bed750c --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -0,0 +1,298 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Skeram +SD%Complete: 75 +SDComment: Mind Control buggy. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" +#include "Group.h" + +#define SAY_AGGRO1 -1531000 +#define SAY_AGGRO2 -1531001 +#define SAY_AGGRO3 -1531002 +#define SAY_SLAY1 -1531003 +#define SAY_SLAY2 -1531004 +#define SAY_SLAY3 -1531005 +#define SAY_SPLIT -1531006 +#define SAY_DEATH -1531007 + +#define SPELL_ARCANE_EXPLOSION 25679 +#define SPELL_EARTH_SHOCK 26194 +#define SPELL_TRUE_FULFILLMENT4 26526 +#define SPELL_BLINK 28391 + +class ov_mycoordinates +{ + public: + float x,y,z,r; + ov_mycoordinates(float cx, float cy, float cz, float cr) + { + x = cx; y = cy; z = cz; r = cr; + } +}; + +struct boss_skeramAI : public ScriptedAI +{ + boss_skeramAI(Creature *c) : ScriptedAI(c) + { + IsImage = false; + } + + uint32 ArcaneExplosion_Timer; + uint32 EarthShock_Timer; + uint32 FullFillment_Timer; + uint32 Blink_Timer; + uint32 Invisible_Timer; + + bool Images75; + bool Images50; + bool Images25; + bool IsImage; + bool Invisible; + + void Reset() + { + ArcaneExplosion_Timer = 6000 + rand()%6000; + EarthShock_Timer = 2000; + FullFillment_Timer = 15000; + Blink_Timer = 8000 + rand()%12000; + Invisible_Timer = 500; + + Images75 = false; + Images50 = false; + Images25 = false; + Invisible = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + if (IsImage) + me->setDeathState(JUST_DIED); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit* /*Killer*/) + { + if (!IsImage) + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + if (IsImage || Images75) + return; + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 8000 + rand()%10000; + } else ArcaneExplosion_Timer -= diff; + + //If we are within range melee the target + if (me->IsWithinMeleeRange(me->getVictim())) + { + //Make sure our attack is ready and we arn't currently casting + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + }else + { + //EarthShock_Timer + if (EarthShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_EARTH_SHOCK); + EarthShock_Timer = 1000; + } else EarthShock_Timer -= diff; + } + + //Blink_Timer + if (Blink_Timer <= diff) + { + //DoCast(me, SPELL_BLINK); + switch (urand(0,2)) + { + case 0: + me->GetMap()->CreatureRelocation(me, -8340.782227,2083.814453,125.648788,0.0f); + DoResetThreat(); + break; + case 1: + me->GetMap()->CreatureRelocation(me, -8341.546875,2118.504639,133.058151,0.0f); + DoResetThreat(); + break; + case 2: + me->GetMap()->CreatureRelocation(me, -8318.822266,2058.231201,133.058151,0.0f); + DoResetThreat(); + break; + } + DoStopAttack(); + + Blink_Timer= 20000 + rand()%20000; + } else Blink_Timer -= diff; + + int procent = (int) (me->GetHealth()*100 / me->GetMaxHealth() +0.5); + + //Summoning 2 Images and teleporting to a random position on 75% health + if ((!Images75 && !IsImage) && (procent <= 75 && procent > 70)) + DoSplit(75); + + //Summoning 2 Images and teleporting to a random position on 50% health + if ((!Images50 && !IsImage) && + (procent <= 50 && procent > 45)) + DoSplit(50); + + //Summoning 2 Images and teleporting to a random position on 25% health + if ((!Images25 && !IsImage) && (procent <= 25 && procent > 20)) + DoSplit(25); + + //Invisible_Timer + if (Invisible) + { + if (Invisible_Timer <= diff) + { + //Making Skeram visible after telporting + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + Invisible_Timer = 2500; + Invisible = false; + } else Invisible_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void DoSplit(int atPercent /* 75 50 25 */) + { + DoScriptText(SAY_SPLIT, me); + + ov_mycoordinates *place1 = new ov_mycoordinates(-8340.782227,2083.814453,125.648788,0); + ov_mycoordinates *place2 = new ov_mycoordinates(-8341.546875,2118.504639,133.058151,0); + ov_mycoordinates *place3 = new ov_mycoordinates(-8318.822266,2058.231201,133.058151,0); + + ov_mycoordinates *bossc=place1, *i1=place2, *i2=place3; + + switch (urand(0,2)) + { + case 0: + bossc=place1; + i1=place2; + i2=place3; + break; + case 1: + bossc=place2; + i1=place1; + i2=place3; + break; + case 2: + bossc=place3; + i1=place1; + i2=place2; + break; + } + + for (uint16 i = 0; i < 41; ++i) + { + if (Player *pTarget = CAST_PLR(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))) + { + if (Group *pGrp = pTarget->GetGroup()) + for (uint8 ico = 0; ico < TARGETICONCOUNT; ++ico) + { + //if (grp->m_targetIcons[ico] == me->GetGUID()) -- private member :( + pGrp->SetTargetIcon(ico, 0, 0); + } + + break; + } + } + + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_OFF); + me->GetMap()->CreatureRelocation(me, bossc->x, bossc->y, bossc->z, bossc->r); + Invisible = true; + delete place1; + delete place2; + delete place3; + DoResetThreat(); + DoStopAttack(); + + switch (atPercent) + { + case 75: Images75 = true; break; + case 50: Images50 = true; break; + case 25: Images25 = true; break; + } + + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + Creature *Image1 = me->SummonCreature(15263, i1->x, i1->y, i1->z, i1->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); + if (Image1) + { + Image1->SetMaxHealth(me->GetMaxHealth() / 5); + Image1->SetHealth(me->GetHealth() / 5); + if (pTarget) + Image1->AI()->AttackStart(pTarget); + CAST_AI(boss_skeramAI, Image1->AI())->IsImage = true; + } + + Creature *Image2 = me->SummonCreature(15263,i2->x, i2->y, i2->z, i2->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); + if (Image2) + { + Image2->SetMaxHealth(me->GetMaxHealth() / 5); + Image2->SetHealth(me->GetHealth() / 5); + if (pTarget) + Image2->AI()->AttackStart(pTarget); + CAST_AI(boss_skeramAI, Image2->AI())->IsImage = true; + } + Invisible = true; + } + +}; + +CreatureAI* GetAI_boss_skeram(Creature* pCreature) +{ + return new boss_skeramAI (pCreature); +} + +void AddSC_boss_skeram() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_skeram"; + newscript->GetAI = &GetAI_boss_skeram; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp new file mode 100644 index 00000000000..73f17485f7f --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -0,0 +1,596 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Twinemperors +SD%Complete: 95 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" +#include "WorldPacket.h" + +#include "Item.h" +#include "Spell.h" + +#define SPELL_HEAL_BROTHER 7393 +#define SPELL_TWIN_TELEPORT 800 // CTRA watches for this spell to start its teleport timer +#define SPELL_TWIN_TELEPORT_VISUAL 26638 // visual + +#define SPELL_EXPLODEBUG 804 +#define SPELL_MUTATE_BUG 802 + +#define SOUND_VN_DEATH 8660 //8660 - Death - Feel +#define SOUND_VN_AGGRO 8661 //8661 - Aggro - Let none +#define SOUND_VN_KILL 8662 //8661 - Kill - your fate + +#define SOUND_VL_AGGRO 8657 //8657 - Aggro - To Late +#define SOUND_VL_KILL 8658 //8658 - Kill - You will not +#define SOUND_VL_DEATH 8659 //8659 - Death + +#define PULL_RANGE 50 +#define ABUSE_BUG_RANGE 20 +#define SPELL_BERSERK 26662 +#define TELEPORTTIME 30000 + +#define SPELL_UPPERCUT 26007 +#define SPELL_UNBALANCING_STRIKE 26613 + +#define VEKLOR_DIST 20 // VL will not come to melee when attacking + +#define SPELL_SHADOWBOLT 26006 +#define SPELL_BLIZZARD 26607 +#define SPELL_ARCANEBURST 568 + +struct boss_twinemperorsAI : public ScriptedAI +{ + boss_twinemperorsAI(Creature *c): ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Heal_Timer; + uint32 Teleport_Timer; + bool AfterTeleport; + uint32 AfterTeleportTimer; + bool DontYellWhenDead; + uint32 Abuse_Bug_Timer, BugsTimer; + bool tspellcasted; + uint32 EnrageTimer; + + virtual bool IAmVeklor() = 0; + virtual void Reset() = 0; + virtual void CastSpellOnBug(Creature *pTarget) = 0; + + void TwinReset() + { + Heal_Timer = 0; // first heal immediately when they get close together + Teleport_Timer = TELEPORTTIME; + AfterTeleport = false; + tspellcasted = false; + AfterTeleportTimer = 0; + Abuse_Bug_Timer = 10000 + rand()%7000; + BugsTimer = 2000; + me->clearUnitState(UNIT_STAT_STUNNED); + DontYellWhenDead = false; + EnrageTimer = 15*60000; + } + + Creature *GetOtherBoss() + { + if (pInstance) + return Unit::GetCreature(*me, pInstance->GetData64(IAmVeklor() ? DATA_VEKNILASH : DATA_VEKLOR)); + else + return NULL; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + Unit *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + float dPercent = ((float)damage) / ((float)me->GetMaxHealth()); + int odmg = (int)(dPercent * ((float)pOtherBoss->GetMaxHealth())); + int ohealth = pOtherBoss->GetHealth()-odmg; + pOtherBoss->SetHealth(ohealth > 0 ? ohealth : 0); + if (ohealth <= 0) + { + pOtherBoss->setDeathState(JUST_DIED); + pOtherBoss->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + } + + void JustDied(Unit* /*Killer*/) + { + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + pOtherBoss->SetHealth(0); + pOtherBoss->setDeathState(JUST_DIED); + pOtherBoss->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + CAST_AI(boss_twinemperorsAI, pOtherBoss->AI())->DontYellWhenDead = true; + } + if (!DontYellWhenDead) // I hope AI is not threaded + DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_DEATH : SOUND_VN_DEATH); + } + + void KilledUnit(Unit* /*victim*/) + { + DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_KILL : SOUND_VN_KILL); + } + + void EnterCombat(Unit * who) + { + DoZoneInCombat(); + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + // TODO: we should activate the other boss location so he can start attackning even if nobody + // is near I dont know how to do that + ScriptedAI *otherAI = CAST_AI(ScriptedAI, pOtherBoss->AI()); + if (!pOtherBoss->isInCombat()) + { + DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_AGGRO : SOUND_VN_AGGRO); + otherAI->AttackStart(who); + otherAI->DoZoneInCombat(); + } + } + } + + void SpellHit(Unit *caster, const SpellEntry *entry) + { + if (caster == me) + return; + + Creature *pOtherBoss = GetOtherBoss(); + if (entry->Id != SPELL_HEAL_BROTHER || !pOtherBoss) + return; + + // add health so we keep same percentage for both brothers + uint32 mytotal = me->GetMaxHealth(), histotal = pOtherBoss->GetMaxHealth(); + float mult = ((float)mytotal) / ((float)histotal); + if (mult < 1) + mult = 1.0f/mult; + #define HEAL_BROTHER_AMOUNT 30000.0f + uint32 largerAmount = (uint32)((HEAL_BROTHER_AMOUNT * mult) - HEAL_BROTHER_AMOUNT); + + if (mytotal > histotal) + { + uint32 h = me->GetHealth()+largerAmount; + me->SetHealth(std::min(mytotal, h)); + } + else + { + uint32 h = pOtherBoss->GetHealth()+largerAmount; + pOtherBoss->SetHealth(std::min(histotal, h)); + } + } + + void TryHealBrother(uint32 diff) + { + if (IAmVeklor()) // this spell heals caster and the other brother so let VN cast it + return; + + if (Heal_Timer <= diff) + { + Unit *pOtherBoss = GetOtherBoss(); + if (pOtherBoss && pOtherBoss->IsWithinDist(me,60)) + { + DoCast(pOtherBoss, SPELL_HEAL_BROTHER); + Heal_Timer = 1000; + } + } else Heal_Timer -= diff; + } + + void TeleportToMyBrother() + { + if (!pInstance) + return; + + Teleport_Timer = TELEPORTTIME; + + if (IAmVeklor()) + return; // mechanics handled by veknilash so they teleport exactly at the same time and to correct coordinates + + Creature *pOtherBoss = GetOtherBoss(); + if (pOtherBoss) + { + //me->MonsterYell("Teleporting ...", LANG_UNIVERSAL, 0); + float other_x = pOtherBoss->GetPositionX(); + float other_y = pOtherBoss->GetPositionY(); + float other_z = pOtherBoss->GetPositionZ(); + float other_o = pOtherBoss->GetOrientation(); + + Map *thismap = me->GetMap(); + thismap->CreatureRelocation(pOtherBoss, me->GetPositionX(), + me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + thismap->CreatureRelocation(me, other_x, other_y, other_z, other_o); + + SetAfterTeleport(); + CAST_AI(boss_twinemperorsAI, pOtherBoss->AI())->SetAfterTeleport(); + } + } + + void SetAfterTeleport() + { + me->InterruptNonMeleeSpells(false); + DoStopAttack(); + DoResetThreat(); + DoCast(me, SPELL_TWIN_TELEPORT_VISUAL); + me->addUnitState(UNIT_STAT_STUNNED); + AfterTeleport = true; + AfterTeleportTimer = 2000; + tspellcasted = false; + } + + bool TryActivateAfterTTelep(uint32 diff) + { + if (AfterTeleport) + { + if (!tspellcasted) + { + me->clearUnitState(UNIT_STAT_STUNNED); + DoCast(me, SPELL_TWIN_TELEPORT); + me->addUnitState(UNIT_STAT_STUNNED); + } + + tspellcasted = true; + + if (AfterTeleportTimer <= diff) + { + AfterTeleport = false; + me->clearUnitState(UNIT_STAT_STUNNED); + if (Unit *nearu = me->SelectNearestTarget(100)) + { + //DoYell(nearu->GetName(), LANG_UNIVERSAL, 0); + AttackStart(nearu); + me->AddThreat(nearu, 10000); + } + return true; + } + else + { + AfterTeleportTimer -= diff; + // update important timers which would otherwise get skipped + if (EnrageTimer > diff) + EnrageTimer -= diff; + else + EnrageTimer = 0; + if (Teleport_Timer > diff) + Teleport_Timer -= diff; + else + Teleport_Timer = 0; + return false; + } + } + else + { + return true; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + float attackRadius = me->GetAttackDistance(who); + if (attackRadius < PULL_RANGE) + attackRadius = PULL_RANGE; + if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= /*CREATURE_Z_ATTACK_RANGE*/7 /*there are stairs*/) + { + //if (who->HasStealthAura()) + // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + } + + Creature *RespawnNearbyBugsAndGetOne() + { + std::list lUnitList; + me->GetCreatureListWithEntryInGrid(lUnitList,15316,150.0f); + me->GetCreatureListWithEntryInGrid(lUnitList,15317,150.0f); + + if (lUnitList.empty()) + return NULL; + + Creature *nearb = NULL; + + for (std::list::const_iterator iter = lUnitList.begin(); iter != lUnitList.end(); ++iter) + { + Creature *c = *iter; + if (c) + { + if (c->isDead()) + { + c->Respawn(); + c->setFaction(7); + c->RemoveAllAuras(); + } + if (c->IsWithinDistInMap(me, ABUSE_BUG_RANGE)) + { + if (!nearb || (rand()%4) == 0) + nearb = c; + } + } + } + return nearb; + } + + void HandleBugs(uint32 diff) + { + if (BugsTimer < diff || Abuse_Bug_Timer <= diff) + { + Creature *c = RespawnNearbyBugsAndGetOne(); + if (Abuse_Bug_Timer <= diff) + { + if (c) + { + CastSpellOnBug(c); + Abuse_Bug_Timer = 10000 + rand()%7000; + } + else + { + Abuse_Bug_Timer = 1000; + } + } + else + { + Abuse_Bug_Timer -= diff; + } + BugsTimer = 2000; + } + else + { + BugsTimer -= diff; + Abuse_Bug_Timer -= diff; + } + } + + void CheckEnrage(uint32 diff) + { + if (EnrageTimer <= diff) + { + if (!me->IsNonMeleeSpellCasted(true)) + { + DoCast(me, SPELL_BERSERK); + EnrageTimer = 60*60000; + } else EnrageTimer = 0; + } else EnrageTimer-=diff; + } +}; + +struct boss_veknilashAI : public boss_twinemperorsAI +{ + bool IAmVeklor() {return false;} + boss_veknilashAI(Creature *c) : boss_twinemperorsAI(c) {} + + uint32 UpperCut_Timer; + uint32 UnbalancingStrike_Timer; + uint32 Scarabs_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Summoned; + + void Reset() + { + TwinReset(); + UpperCut_Timer = 14000 + rand()%15000; + UnbalancingStrike_Timer = 8000 + rand()%10000; + Scarabs_Timer = 7000 + rand()%7000; + + //Added. Can be removed if its included in DB. + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + } + + void CastSpellOnBug(Creature *pTarget) + { + pTarget->setFaction(14); + pTarget->AI()->AttackStart(me->getThreatManager().getHostilTarget()); + pTarget->AddAura(SPELL_MUTATE_BUG, pTarget); + pTarget->SetHealth(pTarget->GetMaxHealth()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!TryActivateAfterTTelep(diff)) + return; + + //UnbalancingStrike_Timer + if (UnbalancingStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE); + UnbalancingStrike_Timer = 8000+rand()%12000; + } else UnbalancingStrike_Timer -= diff; + + if (UpperCut_Timer <= diff) + { + Unit* randomMelee = SelectTarget(SELECT_TARGET_RANDOM, 0, NOMINAL_MELEE_RANGE, true); + if (randomMelee) + DoCast(randomMelee, SPELL_UPPERCUT); + UpperCut_Timer = 15000+rand()%15000; + } else UpperCut_Timer -= diff; + + HandleBugs(diff); + + //Heal brother when 60yrds close + TryHealBrother(diff); + + //Teleporting to brother + if (Teleport_Timer <= diff) + { + TeleportToMyBrother(); + } else Teleport_Timer -= diff; + + CheckEnrage(diff); + + DoMeleeAttackIfReady(); + } +}; + +struct boss_veklorAI : public boss_twinemperorsAI +{ + bool IAmVeklor() {return true;} + boss_veklorAI(Creature *c) : boss_twinemperorsAI(c) {} + + uint32 ShadowBolt_Timer; + uint32 Blizzard_Timer; + uint32 ArcaneBurst_Timer; + uint32 Scorpions_Timer; + int Rand; + int RandX; + int RandY; + + Creature* Summoned; + + void Reset() + { + TwinReset(); + ShadowBolt_Timer = 0; + Blizzard_Timer = 15000 + rand()%5000; + ArcaneBurst_Timer = 1000; + Scorpions_Timer = 7000 + rand()%7000; + + //Added. Can be removed if its included in DB. + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0); + } + + void CastSpellOnBug(Creature *pTarget) + { + pTarget->setFaction(14); + pTarget->AddAura(SPELL_EXPLODEBUG, pTarget); + pTarget->SetHealth(pTarget->GetMaxHealth()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // reset arcane burst after teleport - we need to do this because + // when VL jumps to VN's location there will be a warrior who will get only 2s to run away + // which is almost impossible + if (AfterTeleport) + ArcaneBurst_Timer = 5000; + if (!TryActivateAfterTTelep(diff)) + return; + + //ShadowBolt_Timer + if (ShadowBolt_Timer <= diff) + { + if (!me->IsWithinDist(me->getVictim(), 45.0f)) + me->GetMotionMaster()->MoveChase(me->getVictim(), VEKLOR_DIST, 0); + else + DoCast(me->getVictim(), SPELL_SHADOWBOLT); + ShadowBolt_Timer = 2000; + } else ShadowBolt_Timer -= diff; + + //Blizzard_Timer + if (Blizzard_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45, true); + if (pTarget) + DoCast(pTarget, SPELL_BLIZZARD); + Blizzard_Timer = 15000+rand()%15000; + } else Blizzard_Timer -= diff; + + if (ArcaneBurst_Timer <= diff) + { + Unit *mvic; + if ((mvic=SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) != NULL) + { + DoCast(mvic, SPELL_ARCANEBURST); + ArcaneBurst_Timer = 5000; + } + } else ArcaneBurst_Timer -= diff; + + HandleBugs(diff); + + //Heal brother when 60yrds close + TryHealBrother(diff); + + //Teleporting to brother + if (Teleport_Timer <= diff) + { + TeleportToMyBrother(); + } else Teleport_Timer -= diff; + + CheckEnrage(diff); + + //VL doesn't melee + //DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + // VL doesn't melee + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); + me->AddThreat(who, 0.0f); + } + } + } +}; + +CreatureAI* GetAI_boss_veknilash(Creature* pCreature) +{ + return new boss_veknilashAI (pCreature); +} + +CreatureAI* GetAI_boss_veklor(Creature* pCreature) +{ + return new boss_veklorAI (pCreature); +} + +void AddSC_boss_twinemperors() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_veknilash"; + newscript->GetAI = &GetAI_boss_veknilash; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_veklor"; + newscript->GetAI = &GetAI_boss_veklor; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp new file mode 100644 index 00000000000..f5e71a35bae --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp @@ -0,0 +1,30 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Viscidus +SD%Complete: 0 +SDComment: place holder +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_POISON_SHOCK 25993 +#define SPELL_POISONBOLT_VOLLEY 25991 + +#define SPELL_TOXIN_CLOUD 25989 + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp new file mode 100644 index 00000000000..1125a0c8623 --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp @@ -0,0 +1,166 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Temple_of_Ahnqiraj +SD%Complete: 80 +SDComment: +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "temple_of_ahnqiraj.h" + +struct instance_temple_of_ahnqiraj : public ScriptedInstance +{ + instance_temple_of_ahnqiraj(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + //If Vem is dead... + bool IsBossDied[3]; + + //Storing Skeram, Vem and Kri. + uint64 SkeramGUID; + uint64 VemGUID; + uint64 KriGUID; + uint64 VeklorGUID; + uint64 VeknilashGUID; + + uint32 BugTrioDeathCount; + + uint32 CthunPhase; + + void Initialize() + { + IsBossDied[0] = false; + IsBossDied[1] = false; + IsBossDied[2] = false; + + SkeramGUID = 0; + VemGUID = 0; + KriGUID = 0; + VeklorGUID = 0; + VeknilashGUID = 0; + + BugTrioDeathCount = 0; + + CthunPhase = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch (pCreature->GetEntry()) + { + case 15263: SkeramGUID = pCreature->GetGUID(); break; + case 15544: VemGUID = pCreature->GetGUID(); break; + case 15511: KriGUID = pCreature->GetGUID(); break; + case 15276: VeklorGUID = pCreature->GetGUID(); break; + case 15275: VeknilashGUID = pCreature->GetGUID(); break; + } + } + + bool IsEncounterInProgress() const + { + //not active in AQ40 + return false; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_VEMISDEAD: + if (IsBossDied[0]) + return 1; + break; + + case DATA_VEKLORISDEAD: + if (IsBossDied[1]) + return 1; + break; + + case DATA_VEKNILASHISDEAD: + if (IsBossDied[2]) + return 1; + break; + + case DATA_BUG_TRIO_DEATH: + return BugTrioDeathCount; + + case DATA_CTHUN_PHASE: + return CthunPhase; + } + return 0; + } + + uint64 GetData64 (uint32 identifier) + { + switch(identifier) + { + case DATA_SKERAM: + return SkeramGUID; + case DATA_VEM: + return VemGUID; + case DATA_KRI: + return KriGUID; + case DATA_VEKLOR: + return VeklorGUID; + case DATA_VEKNILASH: + return VeknilashGUID; + } + return 0; + } // end GetData64 + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_VEM_DEATH: + IsBossDied[0] = true; + break; + + case DATA_BUG_TRIO_DEATH: + ++BugTrioDeathCount; + break; + + case DATA_VEKLOR_DEATH: + IsBossDied[1] = true; + break; + + case DATA_VEKNILASH_DEATH: + IsBossDied[2] = true; + break; + + case DATA_CTHUN_PHASE: + CthunPhase = data; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_temple_of_ahnqiraj(Map* pMap) +{ + return new instance_temple_of_ahnqiraj(pMap); +} + +void AddSC_instance_temple_of_ahnqiraj() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_temple_of_ahnqiraj"; + newscript->GetInstanceData = &GetInstanceData_instance_temple_of_ahnqiraj; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp new file mode 100644 index 00000000000..074f9ed68ae --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp @@ -0,0 +1,296 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: mob_anubisath_sentinel +SD%Complete: 95 +SDComment: Shadow storm is not properly implemented in core it should only pTarget ppl outside of melee range. +SDCategory: Temple of Ahn'Qiraj +EndScriptData */ + +#include "ScriptedPch.h" +#include "WorldPacket.h" + +#include "Item.h" +#include "Player.h" +#include "Spell.h" + +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" + +#define SPELL_MENDING_BUFF 2147 + +#define SPELL_KNOCK_BUFF 21737 +#define SPELL_KNOCK 25778 +#define SPELL_MANAB_BUFF 812 +#define SPELL_MANAB 25779 + +#define SPELL_REFLECTAF_BUFF 13022 +#define SPELL_REFLECTSFr_BUFF 19595 +#define SPELL_THORNS_BUFF 25777 + +#define SPELL_THUNDER_BUFF 2834 +#define SPELL_THUNDER 8732 + +#define SPELL_MSTRIKE_BUFF 9347 +#define SPELL_MSTRIKE 24573 + +#define SPELL_STORM_BUFF 2148 +#define SPELL_STORM 26546 + +struct aqsentinelAI : public ScriptedAI +{ + uint32 ability; + int abselected; + + void selectAbility(int asel) + { + switch (asel) + { + case 0: ability = SPELL_MENDING_BUFF;break; + case 1: ability = SPELL_KNOCK_BUFF;break; + case 2: ability = SPELL_MANAB_BUFF;break; + case 3: ability = SPELL_REFLECTAF_BUFF;break; + case 4: ability = SPELL_REFLECTSFr_BUFF;break; + case 5: ability = SPELL_THORNS_BUFF;break; + case 6: ability = SPELL_THUNDER_BUFF;break; + case 7: ability = SPELL_MSTRIKE_BUFF;break; + case 8: ability = SPELL_STORM_BUFF;break; + } + } + + aqsentinelAI(Creature *c) : ScriptedAI(c) + { + ClearBuddyList(); + abselected = 0; // just initialization of variable + } + + uint64 NearbyGUID[3]; + + void ClearBuddyList() + { + NearbyGUID[0] = NearbyGUID[1] = NearbyGUID[2] = 0; + } + + void AddBuddyToList(uint64 CreatureGUID) + { + if (CreatureGUID == me->GetGUID()) + return; + + for (int i=0; i<3; ++i) + { + if (NearbyGUID[i] == CreatureGUID) + return; + if (!NearbyGUID[i]) + { + NearbyGUID[i] = CreatureGUID; + return; + } + } + } + + void GiveBuddyMyList(Creature *c) + { + aqsentinelAI *cai = CAST_AI(aqsentinelAI, (c)->AI()); + for (int i=0; i<3; ++i) + if (NearbyGUID[i] && NearbyGUID[i] != c->GetGUID()) + cai->AddBuddyToList(NearbyGUID[i]); + cai->AddBuddyToList(me->GetGUID()); + } + + void SendMyListToBuddies() + { + for (int i=0; i<3; ++i) + if (Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[i])) + GiveBuddyMyList(pNearby); + } + + void CallBuddiesToAttack(Unit *who) + { + for (int i=0; i<3; ++i) + { + Creature *c = Unit::GetCreature(*me, NearbyGUID[i]); + if (c) + { + if (!c->isInCombat()) + { + c->SetNoCallAssistance(true); + if (c->AI()) + c->AI()->AttackStart(who); + } + } + } + } + + void AddSentinelsNear(Unit * /*nears*/) + { + std::list assistList; + me->GetCreatureListWithEntryInGrid(assistList,15264,70.0f); + + if (assistList.empty()) + return; + + for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + AddBuddyToList((*iter)->GetGUID()); + } + + int pickAbilityRandom(bool *chosenAbilities) + { + for (int t = 0; t < 2; ++t) + { + for (int i = !t ? (rand()%9) : 0; i < 9; ++i) + { + if (!chosenAbilities[i]) + { + chosenAbilities[i] = true; + return i; + } + } + } + return 0; // should never happen + } + + void GetOtherSentinels(Unit *who) + { + bool *chosenAbilities = new bool[9]; + memset(chosenAbilities, 0, 9*sizeof(bool)); + selectAbility(pickAbilityRandom(chosenAbilities)); + + ClearBuddyList(); + AddSentinelsNear(me); + int bli; + for (bli = 0; bli < 3; ++bli) + { + if (!NearbyGUID[bli]) + break; + + Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[bli]); + if (!pNearby) + break; + + AddSentinelsNear(pNearby); + CAST_AI(aqsentinelAI, pNearby->AI())->gatherOthersWhenAggro = false; + CAST_AI(aqsentinelAI, pNearby->AI())->selectAbility(pickAbilityRandom(chosenAbilities)); + } + /*if (bli < 3) + DoYell("I dont have enough buddies.", LANG_NEUTRAL, 0);*/ + SendMyListToBuddies(); + CallBuddiesToAttack(who); + + delete[] chosenAbilities; + } + + bool gatherOthersWhenAggro; + + void Reset() + { + if (!me->isDead()) + { + for (int i=0; i<3; ++i) + { + if (!NearbyGUID[i]) + continue; + if (Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[i])) + { + if (pNearby->isDead()) + pNearby->Respawn(); + } + } + } + ClearBuddyList(); + gatherOthersWhenAggro = true; + } + + void GainSentinelAbility(uint32 id) + { + me->AddAura(id, me); + } + + void EnterCombat(Unit * who) + { + if (gatherOthersWhenAggro) + GetOtherSentinels(who); + + GainSentinelAbility(ability); + DoZoneInCombat(); + } + + void JustDied(Unit* /*who*/) + { + for (int ni=0; ni<3; ++ni) + { + Creature *sent = Unit::GetCreature(*me, NearbyGUID[ni]); + if (!sent) + continue; + if (sent->isDead()) + continue; + int h = sent->GetHealth() + (sent->GetMaxHealth() / 2); + if (h > sent->GetMaxHealth()) + h = sent->GetMaxHealth(); + sent->SetHealth(h); + CAST_AI(aqsentinelAI, sent->AI())->GainSentinelAbility(ability); + } + } + + Unit *GetHatedManaUser() const + { + std::list::const_iterator i; + for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit->getPowerType() == POWER_MANA) + return pUnit; + } + return NULL; + } + + Unit* GetAuraEffectTriggerTarget(uint32 spellId, uint8 /*effIndex*/) const + { + switch (spellId) + { + case SPELL_KNOCK_BUFF: + case SPELL_THUNDER_BUFF: + case SPELL_MSTRIKE_BUFF: + case SPELL_STORM_BUFF: + return me->getVictim(); + + case SPELL_MANAB_BUFF: + return GetHatedManaUser(); + + case SPELL_MENDING_BUFF: + case SPELL_REFLECTAF_BUFF: + case SPELL_REFLECTSFr_BUFF: + case SPELL_THORNS_BUFF: + default: + return me; + } + } +}; +CreatureAI* GetAI_mob_anubisath_sentinelAI(Creature* pCreature) +{ + return new aqsentinelAI (pCreature); +} + +void AddSC_mob_anubisath_sentinel() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_anubisath_sentinel"; + newscript->GetAI = &GetAI_mob_anubisath_sentinelAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h new file mode 100644 index 00000000000..5d545ed7c74 --- /dev/null +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h @@ -0,0 +1,23 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_TEMPLE_OF_AHNQIRAJ_H +#define DEF_TEMPLE_OF_AHNQIRAJ_H + +#define DATA_SKERAM 1 +#define DATA_KRI 2 +#define DATA_VEM 3 +#define DATA_VEMISDEAD 4 +#define DATA_VEM_DEATH 5 +#define DATA_VEKLOR 6 +#define DATA_VEKLORISDEAD 7 +#define DATA_VEKLOR_DEATH 8 +#define DATA_VEKNILASH 9 +#define DATA_VEKNILASHISDEAD 10 +#define DATA_VEKNILASH_DEATH 11 +#define DATA_BUG_TRIO_DEATH 14 + +#define DATA_CTHUN_PHASE 20 +#endif + diff --git a/src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp b/src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp new file mode 100644 index 00000000000..287b5db6d57 --- /dev/null +++ b/src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Wailing_Caverns +SD%Complete: 99 +SDComment: Everything seems to work, still need some checking +SDCategory: Wailing Caverns +EndScriptData */ + +#include "ScriptedPch.h" +#include "wailing_caverns.h" + +#define MAX_ENCOUNTER 9 + +struct instance_wailing_caverns : public ScriptedInstance +{ + instance_wailing_caverns(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + bool yelled; + uint64 NaralexGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + yelled = false; + NaralexGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == DATA_NARALEX) + NaralexGUID = pCreature->GetGUID(); + } + + void SetData(uint32 type, uint32 data) + { + switch (type) + { + case TYPE_LORD_COBRAHN: m_auiEncounter[0] = data;break; + case TYPE_LORD_PYTHAS: m_auiEncounter[1] = data;break; + case TYPE_LADY_ANACONDRA: m_auiEncounter[2] = data;break; + case TYPE_LORD_SERPENTIS: m_auiEncounter[3] = data;break; + case TYPE_NARALEX_EVENT: m_auiEncounter[4] = data;break; + case TYPE_NARALEX_PART1: m_auiEncounter[5] = data;break; + case TYPE_NARALEX_PART2: m_auiEncounter[6] = data;break; + case TYPE_NARALEX_PART3: m_auiEncounter[7] = data;break; + case TYPE_MUTANUS_THE_DEVOURER: m_auiEncounter[8] = data;break; + case TYPE_NARALEX_YELLED: yelled = true; break; + } + if (data == DONE)SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch (type) + { + case TYPE_LORD_COBRAHN: return m_auiEncounter[0]; + case TYPE_LORD_PYTHAS: return m_auiEncounter[1]; + case TYPE_LADY_ANACONDRA: return m_auiEncounter[2]; + case TYPE_LORD_SERPENTIS: return m_auiEncounter[3]; + case TYPE_NARALEX_EVENT: return m_auiEncounter[4]; + case TYPE_NARALEX_PART1: return m_auiEncounter[5]; + case TYPE_NARALEX_PART2: return m_auiEncounter[6]; + case TYPE_NARALEX_PART3: return m_auiEncounter[7]; + case TYPE_MUTANUS_THE_DEVOURER: return m_auiEncounter[8]; + case TYPE_NARALEX_YELLED: return yelled; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + if (data == DATA_NARALEX)return NaralexGUID; + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " + << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] >> m_auiEncounter[8]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] != DONE) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } + +}; + +InstanceData* GetInstanceData_instance_wailing_caverns(Map* pMap) +{ + return new instance_wailing_caverns(pMap); +} + +void AddSC_instance_wailing_caverns() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_wailing_caverns"; + newscript->GetInstanceData = &GetInstanceData_instance_wailing_caverns; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp new file mode 100644 index 00000000000..544c119fc93 --- /dev/null +++ b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp @@ -0,0 +1,396 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Wailing Caverns +SD%Complete: 95 +SDComment: Need to add skill usage for Disciple of Naralex +SDCategory: Wailing Caverns +EndScriptData */ + +/* ContentData +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "wailing_caverns.h" + +/*###### +## npc_disciple_of_naralex +######*/ + +enum eEnums +{ + //say + SAY_MAKE_PREPARATIONS = -1043001, + SAY_TEMPLE_OF_PROMISE = -1043002, + SAY_MUST_CONTINUE = -1043003, + SAY_BANISH_THE_SPIRITS = -1043004, + SAY_CAVERNS_PURIFIED = -1043005, + SAY_BEYOND_THIS_CORRIDOR = -1043006, + SAY_EMERALD_DREAM = -1043007, + SAY_MUTANUS_THE_DEVOURER = -1043012, + SAY_NARALEX_AWAKES = -1043014, + SAY_THANK_YOU = -1043015, + SAY_FAREWELL = -1043016, + SAY_ATTACKED = -1043017, + //yell + SAY_AT_LAST = -1043000, + SAY_I_AM_AWAKE = -1043013, + //emote + EMOTE_AWAKENING_RITUAL = -1043008, + EMOTE_TROUBLED_SLEEP = -1043009, + EMOTE_WRITHE_IN_AGONY = -1043010, + EMOTE_HORRENDOUS_VISION = -1043011, + //spell + SPELL_MARK_OF_THE_WILD_RANK_2 = 5232, + SPELL_SERPENTINE_CLEANSING = 6270, + SPELL_NARALEXS_AWAKENING = 6271, + SPELL_FLIGHT_FORM = 33943, + //npc entry + NPC_DEVIATE_RAVAGER = 3636, + NPC_DEVIATE_VIPER = 5755, + NPC_DEVIATE_MOCCASIN = 5762, + NPC_NIGHTMARE_ECTOPLASM = 5763, + NPC_MUTANUS_THE_DEVOURER = 3654, +}; + +#define GOSSIP_ID_START_1 698 //Naralex sleeps again! +#define GOSSIP_ID_START_2 699 //The fanglords are dead! +#define GOSSIP_ITEM_NARALEX "Let the event begin!" +#define ACHIEVEMENT_WAILING_CAVERNS 630 + +struct npc_disciple_of_naralexAI : public npc_escortAI +{ + npc_disciple_of_naralexAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + eventTimer = 0; + currentEvent = 0; + eventProgress = 0; + me->setActive(true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + uint32 eventTimer; + uint32 currentEvent; + uint32 eventProgress; + ScriptedInstance *pInstance; + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch (i) + { + case 4: + eventProgress = 1; + currentEvent = TYPE_NARALEX_PART1; + pInstance->SetData(TYPE_NARALEX_PART1, IN_PROGRESS); + break; + case 5: + DoScriptText(SAY_MUST_CONTINUE, me); + pInstance->SetData(TYPE_NARALEX_PART1, DONE); + break; + case 11: + eventProgress = 1; + currentEvent = TYPE_NARALEX_PART2; + pInstance->SetData(TYPE_NARALEX_PART2, IN_PROGRESS); + break; + case 19: + DoScriptText(SAY_BEYOND_THIS_CORRIDOR, me); + break; + case 24: + eventProgress = 1; + currentEvent = TYPE_NARALEX_PART3; + pInstance->SetData(TYPE_NARALEX_PART3, IN_PROGRESS); + break; + } + } + + void Reset() + { + + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_ATTACKED, me, who); + } + + void JustDied(Unit * /*slayer*/) + { + if (pInstance) + { + pInstance->SetData(TYPE_NARALEX_EVENT, FAIL); + pInstance->SetData(TYPE_NARALEX_PART1, FAIL); + pInstance->SetData(TYPE_NARALEX_PART2, FAIL); + pInstance->SetData(TYPE_NARALEX_PART3, FAIL); + } + } + + void JustSummoned(Creature* summoned) + { + summoned->AI()->AttackStart(me); + } + + void UpdateAI(const uint32 diff) + { + if (currentEvent != TYPE_NARALEX_PART3) + npc_escortAI::UpdateAI(diff); + + if (!pInstance) + return; + if (eventTimer <= diff) + { + eventTimer = 0; + if (pInstance->GetData(currentEvent) == IN_PROGRESS) + { + switch (currentEvent) + { + case TYPE_NARALEX_PART1: + if (eventProgress == 1) + { + ++eventProgress; + DoScriptText(SAY_TEMPLE_OF_PROMISE, me); + me->SummonCreature(NPC_DEVIATE_RAVAGER, -82.1763, 227.874, -93.3233, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + me->SummonCreature(NPC_DEVIATE_RAVAGER, -72.9506, 216.645, -93.6756, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + } + break; + case TYPE_NARALEX_PART2: + if (eventProgress == 1) + { + ++eventProgress; + DoScriptText(SAY_BANISH_THE_SPIRITS, me); + DoCast(me, SPELL_SERPENTINE_CLEANSING); + //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(false); + eventTimer = 30000; + me->SummonCreature(NPC_DEVIATE_VIPER, -61.5261, 273.676, -92.8442, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + me->SummonCreature(NPC_DEVIATE_VIPER, -58.4658, 280.799, -92.8393, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + me->SummonCreature(NPC_DEVIATE_VIPER, -50.002, 278.578, -92.8442, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + } + else + if (eventProgress == 2) + { + //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(true); + DoScriptText(SAY_CAVERNS_PURIFIED, me); + pInstance->SetData(TYPE_NARALEX_PART2, DONE); + if (me->HasAura(SPELL_SERPENTINE_CLEANSING)) + me->RemoveAura(SPELL_SERPENTINE_CLEANSING); + } + break; + case TYPE_NARALEX_PART3: + if (eventProgress == 1) + { + ++eventProgress; + eventTimer = 4000; + me->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(SAY_EMERALD_DREAM, me); + } + else + if (eventProgress == 2) + { + ++eventProgress; + eventTimer = 15000; + //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(false); + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoCast(naralex, SPELL_NARALEXS_AWAKENING, true); + DoScriptText(EMOTE_AWAKENING_RITUAL, me); + } + else + if (eventProgress == 3) + { + ++eventProgress; + eventTimer = 15000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoScriptText(EMOTE_TROUBLED_SLEEP, naralex); + me->SummonCreature(NPC_DEVIATE_MOCCASIN, 135.943, 199.701, -103.529, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_DEVIATE_MOCCASIN, 151.08, 221.13, -103.609, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_DEVIATE_MOCCASIN, 128.007, 227.428, -97.421, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + } + else + if (eventProgress == 4) + { + ++eventProgress; + eventTimer = 30000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoScriptText(EMOTE_WRITHE_IN_AGONY, naralex); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 133.413, 207.188, -102.469, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 142.857, 218.645, -102.905, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 105.102, 227.211, -102.752, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 153.372, 235.149, -102.826, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 149.524, 251.113, -102.558, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 136.208, 266.466, -102.977, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 126.167, 274.759, -102.962, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + } + else + if (eventProgress == 5) + { + ++eventProgress; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoScriptText(EMOTE_HORRENDOUS_VISION, naralex); + me->SummonCreature(NPC_MUTANUS_THE_DEVOURER, 150.872, 262.905, -103.503, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); + DoScriptText(SAY_MUTANUS_THE_DEVOURER, me); + pInstance->SetData(TYPE_MUTANUS_THE_DEVOURER, IN_PROGRESS); + } + else + if (eventProgress == 6 && pInstance->GetData(TYPE_MUTANUS_THE_DEVOURER) == DONE) + { + ++eventProgress; + eventTimer = 3000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + { + AchievementEntry const *AchievWC = GetAchievementStore()->LookupEntry(ACHIEVEMENT_WAILING_CAVERNS); + if (AchievWC) + { + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievWC); + } + } + if (me->HasAura(SPELL_NARALEXS_AWAKENING)) + me->RemoveAura(SPELL_NARALEXS_AWAKENING); + naralex->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_I_AM_AWAKE, naralex); + } + DoScriptText(SAY_NARALEX_AWAKES, me); + } + else + if (eventProgress == 7) + { + ++eventProgress; + eventTimer = 6000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + DoScriptText(SAY_THANK_YOU, naralex); + } + else + if (eventProgress == 8) + { + ++eventProgress; + eventTimer = 8000; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + { + DoScriptText(SAY_FAREWELL, naralex); + naralex->AddAura(SPELL_FLIGHT_FORM, naralex); + } + SetRun(); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->AddAura(SPELL_FLIGHT_FORM, me); + } + else + if (eventProgress == 9) + { + ++eventProgress; + eventTimer = 1500; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + naralex->GetMotionMaster()->MovePoint(25, naralex->GetPositionX(), naralex->GetPositionY(), naralex->GetPositionZ()); + } + else + if (eventProgress == 10) + { + ++eventProgress; + eventTimer = 2500; + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + { + naralex->GetMotionMaster()->MovePoint(0, 117.095512, 247.107971, -96.167870); + naralex->GetMotionMaster()->MovePoint(1, 90.388809, 276.135406, -83.389801); + } + me->GetMotionMaster()->MovePoint(26, 117.095512, 247.107971, -96.167870); + me->GetMotionMaster()->MovePoint(27, 144.375443, 281.045837, -82.477135); + } + else + if (eventProgress == 11) + { + if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) + naralex->SetVisibility(VISIBILITY_OFF); + me->SetVisibility(VISIBILITY_OFF); + pInstance->SetData(TYPE_NARALEX_PART3, DONE); + } + break; + } + } + } else eventTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_disciple_of_naralex(Creature* pCreature) +{ + return new npc_disciple_of_naralexAI(pCreature); +} + +bool GossipHello_npc_disciple_of_naralex(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance *pInstance = pCreature->GetInstanceData(); + + if (pInstance) + { + pCreature->CastSpell(pPlayer, SPELL_MARK_OF_THE_WILD_RANK_2, true); + if ((pInstance->GetData(TYPE_LORD_COBRAHN) == DONE) && (pInstance->GetData(TYPE_LORD_PYTHAS) == DONE) && + (pInstance->GetData(TYPE_LADY_ANACONDRA) == DONE) && (pInstance->GetData(TYPE_LORD_SERPENTIS) == DONE)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NARALEX, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START_2, pCreature->GetGUID()); + + if (!pInstance->GetData(TYPE_NARALEX_YELLED)) + { + DoScriptText(SAY_AT_LAST, pCreature); + pInstance->SetData(TYPE_NARALEX_YELLED, 1); + } + } + else + { + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START_1, pCreature->GetGUID()); + } + } + return true; +} + +bool GossipSelect_npc_disciple_of_naralex(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + ScriptedInstance *pInstance = pCreature->GetInstanceData(); + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + if (pInstance) + pInstance->SetData(TYPE_NARALEX_EVENT, IN_PROGRESS); + + DoScriptText(SAY_MAKE_PREPARATIONS, pCreature); + + pCreature->setFaction(250); + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + + CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); + } + return true; +} + +void AddSC_wailing_caverns() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_disciple_of_naralex"; + newscript->pGossipHello = &GossipHello_npc_disciple_of_naralex; + newscript->pGossipSelect = &GossipSelect_npc_disciple_of_naralex; + newscript->GetAI = &GetAI_npc_disciple_of_naralex; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.h b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.h new file mode 100644 index 00000000000..6ef1a673c59 --- /dev/null +++ b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.h @@ -0,0 +1,24 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_WAILING_CAVERNS_H +#define DEF_WAILING_CAVERNS_H + +enum eTypes +{ + TYPE_LORD_COBRAHN = 1, + TYPE_LORD_PYTHAS = 2, + TYPE_LADY_ANACONDRA = 3, + TYPE_LORD_SERPENTIS = 4, + TYPE_NARALEX_EVENT = 5, + TYPE_NARALEX_PART1 = 6, + TYPE_NARALEX_PART2 = 7, + TYPE_NARALEX_PART3 = 8, + TYPE_MUTANUS_THE_DEVOURER = 9, + TYPE_NARALEX_YELLED = 10, + + DATA_NARALEX = 3679, +}; + +#endif diff --git a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp new file mode 100644 index 00000000000..530ef30f44c --- /dev/null +++ b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp @@ -0,0 +1,58 @@ + /* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" + +#define NPC_GAHZRILLA 7273 + +struct instance_zulfarrak : public ScriptedInstance +{ + instance_zulfarrak(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 GahzRillaEncounter; + + void Initialize() + { + GahzRillaEncounter = NOT_STARTED; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == NPC_GAHZRILLA) + { + if (GahzRillaEncounter >= IN_PROGRESS) + pCreature->DisappearAndDie(); + else + GahzRillaEncounter = IN_PROGRESS; + } + } +}; + +InstanceData* GetInstanceData_instance_zulfarrak(Map* pMap) +{ + return new instance_zulfarrak(pMap); +} + +void AddSC_instance_zulfarrak() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_zulfarrak"; + newscript->GetInstanceData = &GetInstanceData_instance_zulfarrak; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp b/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp new file mode 100644 index 00000000000..2ca053c23b6 --- /dev/null +++ b/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp @@ -0,0 +1,280 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Zulfarrak +SD%Complete: 50 +SDComment: Consider it temporary, no instance script made for this instance yet. +SDCategory: Zul'Farrak +EndScriptData */ + +/* ContentData +npc_sergeant_bly +npc_weegli_blastfuse +EndContentData */ + +#include "ScriptedPch.h" + +/*###### +## npc_sergeant_bly +######*/ + +#define FACTION_HOSTILE 14 +#define FACTION_FRIENDLY 35 + +#define SPELL_SHIELD_BASH 11972 +#define SPELL_REVENGE 12170 + +#define GOSSIP_BLY "[PH] In that case, I will take my reward!" + +struct npc_sergeant_blyAI : public ScriptedAI +{ + npc_sergeant_blyAI(Creature *c) : ScriptedAI(c) + { + //pInstance = c->GetInstanceData(); + } + + //ScriptedInstance* pInstance; + + uint32 ShieldBash_Timer; + uint32 Revenge_Timer; //this is wrong, spell should never be used unless me->getVictim() dodge, parry or block attack. Trinity support required. + + void Reset() + { + ShieldBash_Timer = 5000; + Revenge_Timer = 8000; + + me->setFaction(FACTION_FRIENDLY); + + /*if (pInstance) + pInstance->SetData(0, NOT_STARTED);*/ + } + + void EnterCombat(Unit * /*who*/) + { + /*if (pInstance) + pInstance->SetData(0, IN_PROGRESS);*/ + } + + void JustDied(Unit * /*victim*/) + { + /*if (pInstance) + pInstance->SetData(0, DONE);*/ + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShieldBash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHIELD_BASH); + ShieldBash_Timer = 15000; + } else ShieldBash_Timer -= diff; + + if (Revenge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_REVENGE); + Revenge_Timer = 10000; + } else Revenge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_sergeant_bly(Creature* pCreature) +{ + return new npc_sergeant_blyAI (pCreature); +} + +bool GossipHello_npc_sergeant_bly(Player* pPlayer, Creature* pCreature) +{ + /*if (pInstance->GetData(0) == DONE) + {*/ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(1517, pCreature->GetGUID()); + /*} + else if (pInstance->GetData(0) == IN_PROGRESS) + pPlayer->SEND_GOSSIP_MENU(1516, pCreature->GetGUID()); + else + pPlayer->SEND_GOSSIP_MENU(1515, pCreature->GetGUID());*/ + + return true; +} + +bool GossipSelect_npc_sergeant_bly(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->setFaction(FACTION_HOSTILE); + CAST_AI(npc_sergeant_blyAI, pCreature->AI())->AttackStart(pPlayer); + } + return true; +} + +/*###### +## npc_weegli_blastfuse +######*/ + +#define SPELL_BOMB 8858 +#define SPELL_GOBLIN_LAND_MINE 21688 +#define SPELL_SHOOT 6660 +#define SPELL_WEEGLIS_BARREL 10772 + +#define GOSSIP_WEEGLI "[PH] Please blow up the door." + +struct npc_weegli_blastfuseAI : public ScriptedAI +{ + npc_weegli_blastfuseAI(Creature *c) : ScriptedAI(c) + { + //pInstance = c->GetInstanceData(); + } + + //ScriptedInstance* pInstance; + + void Reset() + { + /*if (pInstance) + pInstance->SetData(0, NOT_STARTED);*/ + } + + void EnterCombat(Unit * /*who*/) + { + /*if (pInstance) + pInstance->SetData(0, IN_PROGRESS);*/ + } + + void JustDied(Unit * /*victim*/) + { + /*if (pInstance) + pInstance->SetData(0, DONE);*/ + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_npc_weegli_blastfuse(Creature* pCreature) +{ + return new npc_weegli_blastfuseAI (pCreature); +} + +bool GossipHello_npc_weegli_blastfuse(Player* pPlayer, Creature* pCreature) +{ + //event not implemented yet, this is only placeholder for future developement + /*if (pInstance->GetData(0) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEEGLI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(1514, pCreature->GetGUID());//if event can proceed to end + } + else if (pInstance->GetData(0) == IN_PROGRESS) + pPlayer->SEND_GOSSIP_MENU(1513, pCreature->GetGUID());//if event are in progress + else*/ + pPlayer->SEND_GOSSIP_MENU(1511, pCreature->GetGUID()); //if event not started + return true; +} + +bool GossipSelect_npc_weegli_blastfuse(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + //here we make him run to door, set the charge and run away off to nowhere + } + return true; +} + +/*###### +## go_shallow_grave +######*/ + +enum { + ZOMBIE = 7286, + DEAD_HERO = 7276, + ZOMBIE_CHANCE = 65, + DEAD_HERO_CHANCE = 10 +}; + +bool GOHello_go_shallow_grave(Player* /*pPlayer*/, GameObject* pGo) +{ + // randomly summon a zombie or dead hero the first time a grave is used + if (pGo->GetUseCount() == 0) + { + uint32 randomchance = urand(0,100); + if (randomchance < ZOMBIE_CHANCE) + pGo->SummonCreature(ZOMBIE, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + else if ((randomchance-ZOMBIE_CHANCE) < DEAD_HERO_CHANCE) + pGo->SummonCreature(DEAD_HERO, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + } + pGo->AddUse(); + return false; +} + +/*###### +## at_zumrah +######*/ + +enum { + ZUMRAH_ID = 7271, + ZUMRAH_HOSTILE_FACTION = 37 +}; + +bool AreaTrigger_at_zumrah(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + Creature* Zumrah = pPlayer->FindNearestCreature(ZUMRAH_ID, 30.0f); + + if (!Zumrah) + return false; + + Zumrah->setFaction(ZUMRAH_HOSTILE_FACTION); + Zumrah->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + return true; +} + +void AddSC_zulfarrak() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sergeant_bly"; + newscript->GetAI = &GetAI_npc_sergeant_bly; + newscript->pGossipHello = &GossipHello_npc_sergeant_bly; + newscript->pGossipSelect = &GossipSelect_npc_sergeant_bly; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_weegli_blastfuse"; + newscript->GetAI = &GetAI_npc_weegli_blastfuse; + newscript->pGossipHello = &GossipHello_npc_weegli_blastfuse; + newscript->pGossipSelect = &GossipSelect_npc_weegli_blastfuse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_shallow_grave"; + newscript->pGOHello = &GOHello_go_shallow_grave; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_zumrah"; + newscript->pAreaTrigger = &AreaTrigger_at_zumrah; + newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp deleted file mode 100644 index a3fd42a0fe7..00000000000 --- a/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" -#include "ScriptedEscortAI.h" - -enum eSpells -{ - SPELL_BLESSING_OF_BLACKFATHOM = 8733, - SPELL_RAVAGE = 8391, - SPELL_FROST_NOVA = 865, - SPELL_FROST_BOLT_VOLLEY = 8398, - SPELL_TELEPORT_DARNASSUS = 9268 -}; - -#define GOSSIP_ITEM_MORRIDUNE "Please port me to Darnassus" - -const Position HomePosition = {-815.817,-145.299,-25.870, 0}; - -bool GoHello_blackfathom_altar(Player *pPlayer, GameObject* /*pGo*/) -{ - if (!pPlayer->HasAura(SPELL_BLESSING_OF_BLACKFATHOM)) - pPlayer->AddAura(SPELL_BLESSING_OF_BLACKFATHOM,pPlayer); - return true; -} - -bool GoHello_blackfathom_fire(Player * /*pPlayer*/, GameObject* pGo) -{ - ScriptedInstance *pInstance = pGo->GetInstanceData(); - - if (pInstance) - { - pGo->SetGoState(GO_STATE_ACTIVE); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pInstance->SetData(DATA_FIRE, pInstance->GetData(DATA_FIRE) + 1); - return true; - } - return false; -} - -struct npc_blackfathom_deeps_eventAI : public ScriptedAI -{ - npc_blackfathom_deeps_eventAI(Creature* pCreature) : ScriptedAI(pCreature) - { - if (pCreature->isSummon()) - { - pCreature->SetHomePosition(HomePosition); - AttackPlayer(); - } - - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiRavageTimer; - uint32 uiFrostNovaTimer; - uint32 uiFrostBoltVolleyTimer; - - bool bFlee; - - void Reset() - { - bFlee = false; - - uiRavageTimer = urand(5000,8000); - uiFrostNovaTimer = urand(9000,12000); - uiFrostBoltVolleyTimer = urand(2000,4000); - } - - void AttackPlayer() - { - Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - me->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(me); - me->AddThreat(pPlayer, 0.0f); - } - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - switch (me->GetEntry()) - { - case NPC_AKU_MAI_SNAPJAW: - { - if (uiRavageTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_RAVAGE); - uiRavageTimer = urand(9000,14000); - } else uiRavageTimer -= uiDiff; - break; - } - case NPC_MURKSHALLOW_SOFTSHELL: - case NPC_BARBED_CRUSTACEAN: - { - if (!bFlee && HealthBelowPct(15)) - { - bFlee = true; - me->DoFleeToGetAssistance(); - } - break; - } - case NPC_AKU_MAI_SERVANT: - { - if (uiFrostBoltVolleyTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget) - DoCast(pTarget, SPELL_FROST_BOLT_VOLLEY); - } - uiFrostBoltVolleyTimer = urand(5000,8000); - } else uiFrostBoltVolleyTimer -= uiDiff; - if (uiFrostNovaTimer <= uiDiff) - { - DoCastAOE(SPELL_FROST_NOVA,false); - uiFrostNovaTimer = urand(25000,30000); - } else uiFrostNovaTimer -= uiDiff; - break; - } - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (me->isSummon()) //we are not a normal spawn. - if (pInstance) - pInstance->SetData(DATA_EVENT, pInstance->GetData(DATA_EVENT) + 1); - } -}; - -CreatureAI* GetAI_npc_blackfathom_deeps_event(Creature* pCreature) -{ - return new npc_blackfathom_deeps_eventAI (pCreature); -} - -enum eMorridune -{ - SAY_MORRIDUNE_1 = -1048003, - SAY_MORRIDUNE_2 = -1048004 -}; - -struct npc_morriduneAI : public npc_escortAI -{ - npc_morriduneAI(Creature* pCreature) : npc_escortAI(pCreature) - { - DoScriptText(SAY_MORRIDUNE_1,pCreature); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - Start(false,false,NULL); - } - - void WaypointReached(uint32 uiPoint) - { - switch(uiPoint) - { - case 4: - SetEscortPaused(true); - me->SetOrientation(1.775791); - me->SendMovementFlagUpdate(); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - DoScriptText(SAY_MORRIDUNE_2,me); - break; - } - } -}; - -CreatureAI* GetAI_npc_morridune(Creature* pCreature) -{ - return new npc_morriduneAI (pCreature); -} - -bool GossipHello_npc_morridune(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MORRIDUNE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_morridune(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->TeleportTo(1,9952.239,2284.277,1341.394,1.595); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - return true; -} - -void AddSC_blackfathom_deeps() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "go_blackfathom_altar"; - newscript->pGOHello = &GoHello_blackfathom_altar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_blackfathom_fire"; - newscript->pGOHello = &GoHello_blackfathom_fire; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_blackfathom_deeps_event"; - newscript->GetAI = &GetAI_npc_blackfathom_deeps_event; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_morridune"; - newscript->GetAI = &GetAI_npc_morridune; - newscript->pGossipHello = &GossipHello_npc_morridune; - newscript->pGossipSelect = &GossipSelect_npc_morridune; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h b/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h deleted file mode 100644 index e8bbab9f105..00000000000 --- a/src/server/scripts/Kalimdor/blackfathom_depths/blackfathom_deeps.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BFD_H -#define DEF_BFD_H - -enum Data64 -{ - DATA_SHRINE1, - DATA_SHRINE2, - DATA_SHRINE3, - DATA_SHRINE4, - DATA_TWILIGHT_LORD_KELRIS, - DATA_SHRINE_OF_GELIHAST, - DATA_ALTAR_OF_THE_DEEPS, - DATA_MAINDOOR, -}; - -enum Data -{ - TYPE_GELIHAST, - TYPE_KELRIS, - TYPE_SHRINE, - TYPE_AKU_MAI, - DATA_FIRE, - DATA_EVENT -}; - -enum Creatures -{ - NPC_TWILIGHT_LORD_KELRIS = 4832, - NPC_LORGUS_JETT = 12902, - - NPC_AKU_MAI_SNAPJAW = 4825, - NPC_MURKSHALLOW_SOFTSHELL = 4977, - NPC_AKU_MAI_SERVANT = 4978, - NPC_BARBED_CRUSTACEAN = 4823, - - NPC_MORRIDUNE = 6729 -}; - -enum GameObjects -{ - GO_SHRINE_OF_GELIHAST = 103015, - GO_FIRE_OF_AKU_MAI_1 = 21118, - GO_FIRE_OF_AKU_MAI_2 = 21119, - GO_FIRE_OF_AKU_MAI_3 = 21120, - GO_FIRE_OF_AKU_MAI_4 = 21121, - GO_AKU_MAI_DOOR = 21117, - GO_ALTAR_OF_THE_DEEPS = 103016 -}; -#endif diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp deleted file mode 100644 index a4b7a160be8..00000000000 --- a/src/server/scripts/Kalimdor/blackfathom_depths/boss_aku_mai.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" - -enum Spells -{ - SPELL_POISON_CLOUD = 3815, - SPELL_FRENZIED_RAGE = 3490 -}; - -struct boss_aku_maiAI : public ScriptedAI -{ - boss_aku_maiAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiPoisonCloudTimer; - bool bIsEnraged; - - ScriptedInstance *pInstance; - - void Reset() - { - uiPoisonCloudTimer = urand(5000,9000); - bIsEnraged = false; - if (pInstance) - pInstance->SetData(TYPE_AKU_MAI, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(TYPE_AKU_MAI, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_AKU_MAI, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiPoisonCloudTimer < diff) - { - DoCastVictim(SPELL_POISON_CLOUD); - uiPoisonCloudTimer = urand(25000,50000); - } else uiPoisonCloudTimer -= diff; - - if (!bIsEnraged && HealthBelowPct(30)) - { - DoCast(me,SPELL_FRENZIED_RAGE); - bIsEnraged = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_aku_mai(Creature* pCreature) -{ - return new boss_aku_maiAI (pCreature); -} - -void AddSC_boss_aku_mai() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_aku_mai"; - newscript->GetAI = &GetAI_boss_aku_mai; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp deleted file mode 100644 index 374a526f098..00000000000 --- a/src/server/scripts/Kalimdor/blackfathom_depths/boss_gelihast.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" - -enum Spells -{ - SPELL_NET = 6533 -}; - -struct boss_gelihastAI : public ScriptedAI -{ - boss_gelihastAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiNetTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiNetTimer = urand(2000,4000); - if (pInstance) - pInstance->SetData(TYPE_GELIHAST, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(TYPE_GELIHAST, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(TYPE_GELIHAST, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiNetTimer < diff) - { - DoCastVictim(SPELL_NET); - uiNetTimer = urand(4000,7000); - } else uiNetTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_gelihast(Creature* pCreature) -{ - return new boss_gelihastAI (pCreature); -} - -void AddSC_boss_gelihast() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_gelihast"; - newscript->GetAI = &GetAI_boss_gelihast; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp deleted file mode 100644 index bd7e1014d1a..00000000000 --- a/src/server/scripts/Kalimdor/blackfathom_depths/boss_kelris.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" - -enum Spells -{ - SPELL_MIND_BLAST = 15587, - SPELL_SLEEP = 8399, -}; - -//Id's from ACID -enum Yells -{ - SAY_AGGRO = -1048002, - SAY_SLEEP = -1048001, - SAY_DEATH = -1048000 -}; - -struct boss_kelrisAI : public ScriptedAI -{ - boss_kelrisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiMindBlastTimer; - uint32 uiSleepTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiMindBlastTimer = urand(2000,5000); - uiSleepTimer = urand(9000,12000); - if (pInstance) - pInstance->SetData(TYPE_KELRIS, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(TYPE_KELRIS, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - pInstance->SetData(TYPE_KELRIS, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiMindBlastTimer < diff) - { - DoCastVictim(SPELL_MIND_BLAST); - uiMindBlastTimer = urand(7000,9000); - } else uiMindBlastTimer -= diff; - - if (uiSleepTimer < diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(SAY_SLEEP, me); - DoCast(pTarget, SPELL_SLEEP); - } - uiSleepTimer = urand(15000,20000); - } else uiSleepTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kelris(Creature* pCreature) -{ - return new boss_kelrisAI (pCreature); -} - -void AddSC_boss_kelris() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_kelris"; - newscript->GetAI = &GetAI_boss_kelris; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp deleted file mode 100644 index a485684e699..00000000000 --- a/src/server/scripts/Kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Blackfathom_Deeps -SD%Complete: 50 -SDComment: -SDCategory: Blackfathom Deeps -EndScriptData */ - -#include "ScriptedPch.h" -#include "blackfathom_deeps.h" - -#define MAX_ENCOUNTER 4 - -/* Encounter 0 = Gelihast - Encounter 1 = Twilight Lord Kelris - Encounter 2 = Shrine event - Encounter 3 = Aku'Mai - */ - -const Position LorgusPosition[4] = -{ - { -458.500610, -38.343079, -33.474445 }, - { -469.423615, -88.400513, -39.265102 }, - { -622.354980, -10.350100, -22.777000 }, - { -759.640564, 16.658913, -29.159529 } -}; - -const Position SpawnsLocation[] = -{ - {-775.431, -153.853, -25.871, 3.207}, - {-775.404, -174.132, -25.871, 3.185}, - {-862.430, -154.937, -25.871, 0.060}, - {-862.193, -174.251, -25.871, 6.182}, - {-863.895, -458.899, -33.891, 5.637} -}; - -struct instance_blackfathom_deeps : public ScriptedInstance -{ - instance_blackfathom_deeps(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 m_uiTwilightLordKelrisGUID; - uint64 m_uiShrine1GUID; - uint64 m_uiShrine2GUID; - uint64 m_uiShrine3GUID; - uint64 m_uiShrine4GUID; - uint64 m_uiShrineOfGelihastGUID; - uint64 m_uiAltarOfTheDeepsGUID; - uint64 m_uiMainDoorGUID; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - uint8 m_uiCountFires; - uint8 uiDeathTimes; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiTwilightLordKelrisGUID = 0; - m_uiShrine1GUID = 0; - m_uiShrine2GUID = 0; - m_uiShrine3GUID = 0; - m_uiShrine4GUID = 0; - m_uiShrineOfGelihastGUID = 0; - m_uiAltarOfTheDeepsGUID = 0; - m_uiMainDoorGUID = 0; - m_uiCountFires = 0; - uiDeathTimes = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case NPC_TWILIGHT_LORD_KELRIS: - m_uiTwilightLordKelrisGUID = pCreature->GetGUID(); - break; - case NPC_LORGUS_JETT: - pCreature->SetHomePosition(LorgusPosition[urand(0,3)]); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_FIRE_OF_AKU_MAI_1: - m_uiShrine1GUID = pGo->GetGUID(); - break; - case GO_FIRE_OF_AKU_MAI_2: - m_uiShrine2GUID = pGo->GetGUID(); - break; - case GO_FIRE_OF_AKU_MAI_3: - m_uiShrine3GUID = pGo->GetGUID(); - break; - case GO_FIRE_OF_AKU_MAI_4: - m_uiShrine4GUID = pGo->GetGUID(); - break; - case GO_SHRINE_OF_GELIHAST: - m_uiShrineOfGelihastGUID = pGo->GetGUID(); - if (m_auiEncounter[0] != DONE) - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case GO_ALTAR_OF_THE_DEEPS: - m_uiAltarOfTheDeepsGUID = pGo->GetGUID(); - if (m_auiEncounter[3] != DONE) - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case GO_AKU_MAI_DOOR: - if (m_auiEncounter[2] == DONE) - HandleGameObject(NULL,true,pGo); - m_uiMainDoorGUID = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_GELIHAST: - m_auiEncounter[0] = uiData; - if (uiData == DONE) - if (GameObject *pGo = instance->GetGameObject(m_uiShrineOfGelihastGUID)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case TYPE_AKU_MAI: - m_auiEncounter[3] = uiData; - if (uiData == DONE) - if (GameObject *pGo = instance->GetGameObject(m_uiAltarOfTheDeepsGUID)) - { - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGo->SummonCreature(NPC_MORRIDUNE,SpawnsLocation[4], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - break; - case DATA_FIRE: - m_uiCountFires = uiData; - switch (m_uiCountFires) - { - case 1: - if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) - { - pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_AKU_MAI_SNAPJAW, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - break; - case 2: - if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) - { - for (uint8 i = 0; i < 2; ++i) - { - pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_MURKSHALLOW_SOFTSHELL, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - } - break; - case 3: - if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) - { - pGO->SummonCreature(NPC_AKU_MAI_SERVANT, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_AKU_MAI_SERVANT, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - break; - case 4: - if (GameObject* pGO = instance->GetGameObject(m_uiShrine1GUID)) - { - pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - pGO->SummonCreature(NPC_BARBED_CRUSTACEAN, SpawnsLocation[3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - } - break; - } - break; - case DATA_EVENT: - uiDeathTimes = uiData; - if (uiDeathTimes == 18) - HandleGameObject(m_uiMainDoorGUID,true); - break; - } - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case TYPE_GELIHAST: - return m_auiEncounter[0]; - case TYPE_KELRIS: - return m_auiEncounter[1]; - case TYPE_SHRINE: - return m_auiEncounter[2]; - case TYPE_AKU_MAI: - return m_auiEncounter[3]; - case DATA_FIRE: - return m_uiCountFires; - case DATA_EVENT: - return uiDeathTimes; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_TWILIGHT_LORD_KELRIS: - return m_uiTwilightLordKelrisGUID; - case DATA_SHRINE1: - return m_uiShrine1GUID; - case DATA_SHRINE2: - return m_uiShrine2GUID; - case DATA_SHRINE3: - return m_uiShrine3GUID; - case DATA_SHRINE4: - return m_uiShrine4GUID; - case DATA_SHRINE_OF_GELIHAST: - return m_uiShrineOfGelihastGUID; - case DATA_MAINDOOR: - return m_uiMainDoorGUID; - } - - return 0; - } -}; - -InstanceData* GetInstanceData_instance_blackfathom_deeps(Map* pMap) -{ - return new instance_blackfathom_deeps(pMap); -} - -void AddSC_instance_blackfathom_deeps() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blackfathom_deeps"; - newscript->GetInstanceData = &GetInstanceData_instance_blackfathom_deeps; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp deleted file mode 100644 index 287d3cf8e9b..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -/* Script Data Start -SDName: Boss epoch -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro, consecutive attacks to a random target durin time wrap, adjust timers -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CURSE_OF_EXERTION = 52772, - SPELL_TIME_WARP = 52766, //Time slows down, reducing attack, casting and movement speed by 70% for 6 sec. - SPELL_TIME_STOP = 58848, //Stops time in a 50 yard sphere for 2 sec. - SPELL_WOUNDING_STRIKE = 52771, //Used only on the tank - H_SPELL_WOUNDING_STRIKE = 58830 -}; - -enum Yells -{ - SAY_INTRO = -1595000, //"Prince Arthas Menethil, on this day, a powerful darkness has taken hold of your soul. The death you are destined to visit upon others will this day be your own." - SAY_AGGRO = -1595001, //"We'll see about that, young prince." - SAY_TIME_WARP_1 = -1595002, //"Tick tock, tick tock..." - SAY_TIME_WARP_2 = -1595003, //"Not quick enough!" - SAY_TIME_WARP_3 = -1595004, //"Let's get this over with. " - SAY_SLAY_1 = -1595005, //"There is no future for you." - SAY_SLAY_2 = -1595006, //"This is the hour of our greatest triumph!" - SAY_SLAY_3 = -1595007, //"You were destined to fail. " - SAY_DEATH = -1595008 //"*gurgles*" -}; - -struct boss_epochAI : public ScriptedAI -{ - boss_epochAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint8 uiStep; - - uint32 uiStepTimer; - uint32 uiWoundingStrikeTimer; - uint32 uiTimeWarpTimer; - uint32 uiTimeStopTimer; - uint32 uiCurseOfExertionTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiStep = 1; - uiStepTimer = 26000; - uiCurseOfExertionTimer = 9300; - uiTimeWarpTimer = 25300; - uiTimeStopTimer = 21300; - uiWoundingStrikeTimer = 5300; - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiCurseOfExertionTimer < diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CURSE_OF_EXERTION); - uiCurseOfExertionTimer = 9300; - } else uiCurseOfExertionTimer -= diff; - - if (uiWoundingStrikeTimer < diff) - { - DoCastVictim(SPELL_WOUNDING_STRIKE); - uiWoundingStrikeTimer = 5300; - } else uiWoundingStrikeTimer -= diff; - - if (uiTimeStopTimer < diff) - { - DoCastAOE(SPELL_TIME_STOP); - uiTimeStopTimer = 21300; - } else uiTimeStopTimer -= diff; - - if (uiTimeWarpTimer < diff) - { - DoScriptText(RAND(SAY_TIME_WARP_1,SAY_TIME_WARP_2,SAY_TIME_WARP_3), me); - DoCastAOE(SPELL_TIME_WARP); - uiTimeWarpTimer = 25300; - } else uiTimeWarpTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_epoch(Creature* pCreature) -{ - return new boss_epochAI (pCreature); -} - -void AddSC_boss_epoch() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_epoch"; - newscript->GetAI = &GetAI_boss_epoch; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp deleted file mode 100644 index 12cdf00f2a5..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CORRUPTING_BLIGHT = 60588, - SPELL_VOID_STRIKE = 60590 -}; - -enum Yells -{ - SAY_AGGRO = -1595045, - SAY_FAIL = -1595046, - SAY_DEATH = -1595047 -}; - - -struct boss_infinite_corruptorAI : public ScriptedAI -{ - boss_infinite_corruptorAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, DONE); - } -}; - -CreatureAI* GetAI_boss_infinite_corruptor(Creature* pCreature) -{ - return new boss_infinite_corruptorAI(pCreature); -} - -void AddSC_boss_infinite_corruptor() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_infinite_corruptor"; - newscript->GetAI = &GetAI_boss_infinite_corruptor; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp deleted file mode 100644 index a39f3289a5a..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss mal_ganis -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro & outro -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_mal_ganis' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CARRION_SWARM = 52720, //A cresting wave of chaotic magic splashes over enemies in front of the caster, dealing 3230 to 3570 Shadow damage and 380 to 420 Shadow damage every 3 sec. for 15 sec. - H_SPELL_CARRION_SWARM = 58852, - SPELL_MIND_BLAST = 52722, //Inflicts 4163 to 4837 Shadow damage to an enemy. - H_SPELL_MIND_BLAST = 58850, - SPELL_SLEEP = 52721, //Puts an enemy to sleep for up to 10 sec. Any damage caused will awaken the target. - H_SPELL_SLEEP = 58849, - SPELL_VAMPIRIC_TOUCH = 52723 //Heals the caster for half the damage dealt by a melee attack. -}; - -enum Yells -{ - SAY_INTRO_1 = -1595009, - SAY_INTRO_2 = -1595010, - SAY_AGGRO = -1595011, - SAY_KILL_1 = -1595012, - SAY_KILL_2 = -1595013, - SAY_KILL_3 = -1595014, - SAY_SLAY_1 = -1595015, - SAY_SLAY_2 = -1595016, - SAY_SLAY_3 = -1595017, - SAY_SLAY_4 = -1595018, - SAY_SLEEP_1 = -1595019, - SAY_SLEEP_2 = -1595020, - SAY_30HEALTH = -1595021, - SAY_15HEALTH = -1595022, - SAY_ESCAPE_SPEECH_1 = -1595023, - SAY_ESCAPE_SPEECH_2 = -1595024, - SAY_OUTRO = -1595025, -}; - -enum CombatPhases -{ - COMBAT, - OUTRO -}; - -struct boss_mal_ganisAI : public ScriptedAI -{ - boss_mal_ganisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiCarrionSwarmTimer; - uint32 uiMindBlastTimer; - uint32 uiVampiricTouchTimer; - uint32 uiSleepTimer; - - uint8 uiOutroStep; - uint32 uiOutroTimer; - - bool bYelled; - bool bYelled2; - - CombatPhases Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - bYelled = false; - bYelled2 = false; - Phase = COMBAT; - uiCarrionSwarmTimer = 6000; - uiMindBlastTimer = 11000; - uiVampiricTouchTimer = urand(10000,15000); - uiSleepTimer = urand(15000,20000); - uiOutroTimer = 1000; - - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, IN_PROGRESS); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = me->GetHealth()-1; - } - - void UpdateAI(const uint32 diff) - { - switch(Phase) - { - case COMBAT: - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bYelled && HealthBelowPct(30)) - { - DoScriptText(SAY_30HEALTH, me); - bYelled = true; - } - - if (!bYelled2 && HealthBelowPct(15)) - { - DoScriptText(SAY_15HEALTH, me); - bYelled2 = true; - } - - if (HealthBelowPct(1)) - { - //Handle Escape Event: Don't forget to add Player::RewardPlayerAndGroupAtEvent - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - uiOutroStep = 1; - Phase = OUTRO; - return; - } - - if (Creature* pArthas = me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0)) - if (pArthas->isDead()) - { - EnterEvadeMode(); - me->DisappearAndDie(); - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, FAIL); - } - - if (uiCarrionSwarmTimer < diff) - { - DoCastVictim(SPELL_CARRION_SWARM); - uiCarrionSwarmTimer = 7000; - } else uiCarrionSwarmTimer -= diff; - - if (uiMindBlastTimer < diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_MIND_BLAST); - uiMindBlastTimer = 6000; - } else uiMindBlastTimer -= diff; - - if (uiVampiricTouchTimer < diff) - { - DoCast(me, SPELL_VAMPIRIC_TOUCH); - uiVampiricTouchTimer = 32000; - } else uiVampiricTouchTimer -= diff; - - if (uiSleepTimer < diff) - { - DoScriptText(RAND(SAY_SLEEP_1,SAY_SLEEP_2), me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SLEEP); - uiSleepTimer = urand(15000,20000); - } else uiSleepTimer -= diff; - - DoMeleeAttackIfReady(); - break; - case OUTRO: - if (uiOutroTimer < diff) - { - switch(uiOutroStep) - { - case 1: - DoScriptText(SAY_ESCAPE_SPEECH_1, me); - me->GetMotionMaster()->MoveTargetedHome(); - ++uiOutroStep; - uiOutroTimer = 8000; - break; - case 2: - me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0); - me->HandleEmoteCommand(29); - DoScriptText(SAY_ESCAPE_SPEECH_2, me); - ++uiOutroStep; - uiOutroTimer = 9000; - break; - case 3: - DoScriptText(SAY_OUTRO, me); - ++uiOutroStep; - uiOutroTimer = 16000; - break; - case 4: - me->HandleEmoteCommand(33); - ++uiOutroStep; - uiOutroTimer = 500; - break; - case 5: - me->SetVisibility(VISIBILITY_OFF); - me->Kill(me); - break; - - } - } else uiOutroTimer -= diff; - break; - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_MAL_GANIS_EVENT, DONE); - - // give achievement credit to players. criteria use spell 58630 which doesn't exist. - if (pInstance) - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 58630); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } -}; - -CreatureAI* GetAI_boss_mal_ganis(Creature* pCreature) -{ - return new boss_mal_ganisAI (pCreature); -} - -void AddSC_boss_mal_ganis() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_mal_ganis"; - newscript->GetAI = &GetAI_boss_mal_ganis; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp deleted file mode 100644 index eba9733c745..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss meathook -SDAuthor: Tartalo -SD%Complete: 100 -SDComment: It may need timer adjustment -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CONSTRICTING_CHAINS = 52696, //Encases the targets in chains, dealing 1800 Physical damage every 1 sec. and stunning the target for 5 sec. - H_SPELL_CONSTRICTING_CHAINS = 58823, - SPELL_DISEASE_EXPULSION = 52666, //Meathook belches out a cloud of disease, dealing 1710 to 1890 Nature damage and interrupting the spell casting of nearby enemy targets for 4 sec. - H_SPELL_DISEASE_EXPULSION = 58824, - SPELL_FRENZY = 58841 //Increases the caster's Physical damage by 10% for 30 sec. -}; - -enum Yells -{ - SAY_AGGRO = -1595026, - SAY_SLAY_1 = -1595027, - SAY_SLAY_2 = -1595028, - SAY_SLAY_3 = -1595029, - SAY_SPAWN = -1595030, - SAY_DEATH = -1595031 -}; - -struct boss_meathookAI : public ScriptedAI -{ - boss_meathookAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - DoScriptText(SAY_SPAWN,me); - } - - uint32 uiChainTimer; - uint32 uiDiseaseTimer; - uint32 uiFrenzyTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiChainTimer = urand(12000,17000); //seen on video 13, 17, 15, 12, 16 - uiDiseaseTimer = urand(2000,4000); //approx 3s - uiFrenzyTimer = urand(21000,26000); //made it up - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiDiseaseTimer <= diff) - { - DoCastAOE(SPELL_DISEASE_EXPULSION); - uiDiseaseTimer = urand(1500,4000); - } else uiDiseaseTimer -= diff; - - if (uiFrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - uiFrenzyTimer = urand(21000,26000); - } else uiFrenzyTimer -= diff; - - if (uiChainTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CONSTRICTING_CHAINS); //anyone but the tank - uiChainTimer = urand(2000,4000); - } else uiChainTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_meathook(Creature* pCreature) -{ - return new boss_meathookAI (pCreature); -} - -void AddSC_boss_meathook() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_meathook"; - newscript->GetAI = &GetAI_boss_meathook; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp deleted file mode 100644 index da1c8098517..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss salramm -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_salramm' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CURSE_OF_TWISTED_FLESH = 58845, - SPELL_EXPLODE_GHOUL = 52480, - H_SPELL_EXPLODE_GHOUL = 58825, - SPELL_SHADOW_BOLT = 57725, - H_SPELL_SHADOW_BOLT = 58828, - SPELL_STEAL_FLESH = 52708, - SPELL_SUMMON_GHOULS = 52451 -}; - -enum Yells -{ - SAY_AGGRO = -1595032, - SAY_SPAWN = -1595033, - SAY_SLAY_1 = -1595034, - SAY_SLAY_2 = -1595035, - SAY_SLAY_3 = -1595036, - SAY_DEATH = -1595037, - SAY_EXPLODE_GHOUL_1 = -1595038, - SAY_EXPLODE_GHOUL_2 = -1595039, - SAY_STEAL_FLESH_1 = -1595040, - SAY_STEAL_FLESH_2 = -1595041, - SAY_STEAL_FLESH_3 = -1595042, - SAY_SUMMON_GHOULS_1 = -1595043, - SAY_SUMMON_GHOULS_2 = -1595044 -}; - -struct boss_salrammAI : public ScriptedAI -{ - boss_salrammAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - DoScriptText(SAY_SPAWN,me); - } - - uint32 uiCurseFleshTimer; - uint32 uiExplodeGhoulTimer; - uint32 uiShadowBoltTimer; - uint32 uiStealFleshTimer; - uint32 uiSummonGhoulsTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiCurseFleshTimer = 30000; //30s DBM - uiExplodeGhoulTimer = urand(25000,28000); //approx 6 sec after summon ghouls - uiShadowBoltTimer = urand(8000,12000); // approx 10s - uiStealFleshTimer = 12345; - uiSummonGhoulsTimer = urand(19000,24000); //on a video approx 24s after aggro - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Curse of twisted flesh timer - if (uiCurseFleshTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSE_OF_TWISTED_FLESH); - uiCurseFleshTimer = 37000; - } else uiCurseFleshTimer -= diff; - - //Shadow bolt timer - if (uiShadowBoltTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - uiShadowBoltTimer = urand(8000,12000); - } else uiShadowBoltTimer -= diff; - - //Steal Flesh timer - if (uiStealFleshTimer <= diff) - { - DoScriptText(RAND(SAY_STEAL_FLESH_1,SAY_STEAL_FLESH_2,SAY_STEAL_FLESH_3), me); - if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(random_pTarget, SPELL_STEAL_FLESH); - uiStealFleshTimer = 10000; - } else uiStealFleshTimer -= diff; - - //Summon ghouls timer - if (uiSummonGhoulsTimer <= diff) - { - DoScriptText(RAND(SAY_SUMMON_GHOULS_1,SAY_SUMMON_GHOULS_2), me); - if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(random_pTarget, SPELL_SUMMON_GHOULS); - uiSummonGhoulsTimer = 10000; - } else uiSummonGhoulsTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_salramm(Creature* pCreature) -{ - return new boss_salrammAI (pCreature); -} - -void AddSC_boss_salramm() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_salramm"; - newscript->GetAI = &GetAI_boss_salramm; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp deleted file mode 100644 index faaed2eb6db..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp +++ /dev/null @@ -1,1210 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" -#include "ScriptedEscortAI.h" - -enum Says -{ - //First Act - Uther and Jaina Dialog - SAY_PHASE101 = -1595070, //Arthas - SAY_PHASE102 = -1595071, //Uther - SAY_PHASE103 = -1595072, //Arthas - SAY_PHASE104 = -1595073, //Arthas - SAY_PHASE105 = -1595074, //Uther - SAY_PHASE106 = -1595075, //Arthas - SAY_PHASE107 = -1595076, //Uther - SAY_PHASE108 = -1595077, //Arthas - SAY_PHASE109 = -1595078, //Arthas - SAY_PHASE110 = -1595079, //Uther - SAY_PHASE111 = -1595080, //Arthas - SAY_PHASE112 = -1595081, //Uther - SAY_PHASE113 = -1595082, //Jaina - SAY_PHASE114 = -1595083, //Arthas - SAY_PHASE115 = -1595084, //Uther - SAY_PHASE116 = -1595085, //Arthas - SAY_PHASE117 = -1595086, //Jaina - SAY_PHASE118 = -1595087, //Arthas - //Second Act - City Streets - SAY_PHASE201 = -1595088, //Arthas - SAY_PHASE202 = -1595089, //Cityman - SAY_PHASE203 = -1595090, //Arthas - SAY_PHASE204 = -1595091, //Crazyman - SAY_PHASE205 = -1595092, //Arthas - SAY_PHASE206 = -1595009, //Malganis - SAY_PHASE207 = -1595010, //Malganis - SAY_PHASE208 = -1595093, //Arthas - SAY_PHASE209 = -1595094, //Arthas - SAY_PHASE210 = -1595095, //Arthas - //Third Act - Town Hall - SAY_PHASE301 = -1595096, //Arthas - SAY_PHASE302 = -1595097, //Drakonian - SAY_PHASE303 = -1595098, //Arthas - SAY_PHASE304 = -1595099, //Arthas - SAY_PHASE305 = -1595100, //Drakonian - SAY_PHASE306 = -1595101, //Arthas - SAY_PHASE307 = -1595102, //Arthas - SAY_PHASE308 = -1595103, //Arthas - SAY_PHASE309 = -1595104, //Arthas - SAY_PHASE310 = -1595105, //Arthas - SAY_PHASE311 = -1595106, //Arthas - SAY_PHASE312 = -1595107, //Arthas - SAY_PHASE313 = -1595108, //Arthas - SAY_PHASE314 = -1595000, //Epoch - SAY_PHASE315 = -1595109, //Arthas - //Fourth Act - Fire Corridor - SAY_PHASE401 = -1595110, //Arthas - SAY_PHASE402 = -1595111, //Arthas - SAY_PHASE403 = -1595112, //Arthas - SAY_PHASE404 = -1595113, //Arthas - SAY_PHASE405 = -1595114, //Arthas - SAY_PHASE406 = -1595115, //Arthas - SAY_PHASE407 = -1595116, //Arthas - //Fifth Act - Mal'Ganis Fight - SAY_PHASE501 = -1595117, //Arthas - SAY_PHASE502 = -1595118, //Arthas - SAY_PHASE503 = -1595119, //Arthas - SAY_PHASE504 = -1595120, //Arthas -}; - -enum NPCs -{ - NPC_INFINITE_ADVERSARY = 27742, - NPC_INFINITE_HUNTER = 27743, - NPC_INFINITE_AGENT = 27744, - NPC_TIME_RIFT = 28409, - NPC_ZOMBIE = 27737, - NPC_GHOUL = 28249, - NPC_NECROMANCER = 28200, - NPC_STALKER = 28199, - NPC_FIEND = 27734, - NPC_GOLEM = 28201, - NPC_EGHOUL = 27729, - NPC_CONSTRUCT = 27736, - - NPC_INVIS_TARGET = 20562, - - NPC_KNIGHT_ESCORT = 27745, - NPC_PRIEST_ESCORT = 27747, - NPC_CITY_MAN = 28167, - NPC_CITY_MAN2 = 28169, - NPC_CITY_MAN3 = 31126, - NPC_CITY_MAN4 = 31127, -}; - -enum Spells -{ - SPELL_FEAR = 39176, - SPELL_ARTHAS_AURA = 52442, - SPELL_EXORCISM_N = 52445, - SPELL_EXORCISM_H = 58822, - SPELL_HOLY_LIGHT = 52444, -}; - -enum GossipMenuArthas -{ - GOSSIP_MENU_ARTHAS_1 = 100001, - GOSSIP_MENU_ARTHAS_2 = 100002, - GOSSIP_MENU_ARTHAS_3 = 100003, - GOSSIP_MENU_ARTHAS_4 = 100004, - GOSSIP_MENU_ARTHAS_5 = 100005 -}; - -enum -{ - ENCOUNTER_WAVES_NUMBER = 8, - ENCOUNTER_WAVES_MAX_SPAWNS = 5, - ENCOUNTER_DRACONIAN_NUMBER = 4, - ENCOUNTER_CHRONO_SPAWNS = 19 -}; - -// Locations for necromancers and add to spawn -float WavesLocations[ENCOUNTER_WAVES_NUMBER][ENCOUNTER_WAVES_MAX_SPAWNS][5]= -{ - { - {NPC_ZOMBIE, 2164.698975, 1255.392944, 135.040878, 0.490202}, - {NPC_ZOMBIE, 2183.501465, 1263.079102, 134.859055, 3.169981}, - {NPC_GHOUL, 2177.512939, 1247.313843, 135.846695, 1.696574}, - {NPC_GHOUL, 2171.991943, 1246.615845, 135.745026, 1.696574}, - {0, 0, 0, 0, 0} - }, - { - {NPC_GHOUL, 2254.434326, 1163.427612, 138.055038, 2.077358}, - {NPC_GHOUL, 2254.703613, 1158.867798, 138.212234, 2.345532}, - {NPC_GHOUL, 2257.615723, 1162.310913, 138.091202, 2.077358}, - {NPC_NECROMANCER, 2258.258057, 1157.250732, 138.272873, 2.387766}, - {0, 0, 0, 0, 0} - }, - { - {NPC_STALKER, 2348.120117, 1202.302490, 130.491104, 4.698538}, - {NPC_GHOUL, 2352.863525, 1207.819092, 130.424271, 4.949865}, - {NPC_GHOUL, 2343.593750, 1207.915039, 130.781311, 4.321547}, - {NPC_NECROMANCER, 2348.257324, 1212.202515, 130.670135, 4.450352}, - {0, 0, 0, 0, 0} - }, - { - {NPC_STALKER, 2139.825195, 1356.277100, 132.199615, 5.820131}, - {NPC_GHOUL, 2137.073486, 1362.464844, 132.271637, 5.820131}, - {NPC_GHOUL, 2134.075684, 1354.148071, 131.885864, 5.820131}, - {NPC_NECROMANCER, 2133.302246, 1358.907837, 132.037689, 5.820131}, - {0, 0, 0, 0, 0} - }, - { - {NPC_NECROMANCER, 2264.013428, 1174.055908, 138.093094, 2.860481}, - {NPC_GHOUL, 2264.207764, 1170.892700, 138.034973, 2.860481}, - {NPC_GHOUL, 2266.948975, 1176.898926, 137.976929, 2.860481}, - {NPC_STALKER, 2269.215576, 1170.109253, 137.742691, 2.860481}, - {NPC_FIEND, 2273.106689, 1176.101074, 137.880508, 2.860481} - }, - { - {NPC_GOLEM, 2349.701660, 1188.436646, 130.428864, 3.908642}, - {NPC_GHOUL, 2349.909180, 1194.582642, 130.417816, 3.577001}, - {NPC_EGHOUL, 2354.662598, 1185.692017, 130.552032, 3.577001}, - {NPC_EGHOUL, 2354.716797, 1191.614380, 130.539810, 3.577001}, - {0, 0, 0, 0, 0} - }, - { - {NPC_CONSTRUCT, 2145.212891, 1355.288086, 132.288773, 6.004838}, - {NPC_NECROMANCER, 2137.078613, 1357.612671, 132.173340, 6.004838}, - {NPC_EGHOUL, 2139.402100, 1352.541626, 132.127518, 5.812850}, - {NPC_EGHOUL, 2142.408447, 1360.760620, 132.321564, 5.812850}, - {0, 0, 0, 0, 0} - }, - { - {NPC_GHOUL, 2172.686279, 1259.618164, 134.391754, 1.865499}, - {NPC_FIEND, 2177.649170, 1256.061157, 135.096512, 1.849572}, - {NPC_CONSTRUCT, 2170.782959, 1253.594849, 134.973022, 1.849572}, - {NPC_NECROMANCER, 2175.595703, 1249.041992, 135.603531, 1.849572}, - {0, 0, 0, 0, 0} - } -}; - -// Locations for rifts to spawn and draconians to go -float RiftAndSpawnsLocations[ENCOUNTER_CHRONO_SPAWNS][5]= -{ - {NPC_TIME_RIFT, 2431.790039, 1190.670044, 148.076004, 0.187923}, - {NPC_INFINITE_ADVERSARY, 2433.857910, 1185.612061, 148.075974, 4.566168}, - {NPC_INFINITE_ADVERSARY, 2437.577881, 1188.241089, 148.075974, 0.196999}, - {NPC_INFINITE_AGENT, 2437.165527, 1192.294922, 148.075974, 0.169247}, - {NPC_INFINITE_HUNTER, 2434.989990, 1197.679565, 148.075974, 0.715971}, - {NPC_TIME_RIFT, 2403.954834, 1178.815430, 148.075943, 4.966126}, - {NPC_INFINITE_AGENT, 2403.676758, 1171.495850, 148.075607, 4.902797}, - {NPC_INFINITE_HUNTER, 2407.691162, 1172.162720, 148.075607, 4.963010}, - {NPC_TIME_RIFT, 2414.217041, 1133.446167, 148.076050, 1.706972}, - {NPC_INFINITE_ADVERSARY, 2416.024658, 1139.456177, 148.076431, 1.752129}, - {NPC_INFINITE_HUNTER, 2410.866699, 1139.680542, 148.076431, 1.752129}, - {NPC_TIME_RIFT, 2433.081543, 1099.869751, 148.076157, 1.809509}, - {NPC_INFINITE_ADVERSARY, 2426.947998, 1107.471680, 148.076019, 1.877580}, - {NPC_INFINITE_HUNTER, 2432.944580, 1108.896362, 148.208160, 2.199241}, - {NPC_TIME_RIFT, 2444.077637, 1114.366089, 148.076157, 3.049565}, - {NPC_INFINITE_ADVERSARY, 2438.190674, 1118.368164, 148.076172, 3.139232}, - {NPC_INFINITE_AGENT, 2435.861328, 1113.402954, 148.169327, 2.390271}, - {NPC_TIME_RIFT, 2463.131592, 1115.391724, 152.473129, 3.409651}, - {NPC_EPOCH, 2451.809326, 1112.901245, 149.220459, 3.363617} -}; - -struct npc_arthasAI : public npc_escortAI -{ - npc_arthasAI(Creature *pCreature) : npc_escortAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* pInstance; - - bool bStepping; - uint32 uiStep; - uint32 uiPhaseTimer; - uint32 uiGossipStep; - uint32 uiPlayerFaction; - uint32 uiBossEvent; - uint32 uiWave; - - uint64 uiUtherGUID; - uint64 uiJainaGUID; - uint64 uiCitymenGUID[2]; - uint64 uiWaveGUID[ENCOUNTER_WAVES_MAX_SPAWNS]; - uint64 uiInfiniteDraconianGUID[ENCOUNTER_DRACONIAN_NUMBER]; - uint64 uiStalkerGUID; - - uint64 uiBossGUID; //uiMeathookGUID || uiSalrammGUID - uint64 uiEpochGUID; - uint64 uiMalganisGUID; - uint64 uiInfiniteGUID; - - uint32 uiExorcismTimer; - - void Reset() - { - uiUtherGUID = 0; - uiJainaGUID = 0; - - for (uint8 i = 0; i < 2; ++i) - uiCitymenGUID[i] = 0; - - for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - uiWaveGUID[i] = 0; - - for (uint8 i = 0; i < ENCOUNTER_DRACONIAN_NUMBER; ++i) - uiInfiniteDraconianGUID[i] = 0; - - uiStalkerGUID = 0; - uiBossGUID = 0; - uiEpochGUID = 0; - uiMalganisGUID = 0; - uiInfiniteGUID = 0; - - if (pInstance) { - pInstance->SetData(DATA_ARTHAS_EVENT, NOT_STARTED); - switch(pInstance->GetData(DATA_ARTHAS_EVENT)) - { - case NOT_STARTED: - bStepping = true; - uiStep = 0; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - uiBossEvent = DATA_MEATHOOK_EVENT; - uiGossipStep = 0; - break; - } - uiPhaseTimer = 1000; - uiExorcismTimer = 7300; - uiWave = 0; - } - } - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_ARTHAS_AURA); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ARTHAS_EVENT, FAIL); - } - - void SpawnTimeRift(uint32 timeRiftID, uint64* guidVector) - { - me->SummonCreature((uint32)RiftAndSpawnsLocations[timeRiftID][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_DESPAWN,11000); - - for (uint32 i = timeRiftID+1; i < ENCOUNTER_CHRONO_SPAWNS; ++i) - { - if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_TIME_RIFT) break; - if (Creature* pTemp = me->SummonCreature((uint32)RiftAndSpawnsLocations[i][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - guidVector[i-timeRiftID-1] = pTemp->GetGUID(); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pTemp->SetReactState(REACT_PASSIVE); - pTemp->GetMotionMaster()->MovePoint(0, RiftAndSpawnsLocations[i][1],RiftAndSpawnsLocations[i][2],RiftAndSpawnsLocations[i][3]); - if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_EPOCH) - uiEpochGUID = pTemp->GetGUID(); - } - } - } - - void SpawnWaveGroup(uint32 waveID, uint64* guidVector) - { - for (uint32 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - { - if ((uint32)WavesLocations[waveID][i][0] == 0) break; - if (Creature* pTemp = me->SummonCreature((uint32)WavesLocations[waveID][i][0],WavesLocations[waveID][i][1],WavesLocations[waveID][i][2],WavesLocations[waveID][i][3],WavesLocations[waveID][i][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - guidVector[i] = pTemp->GetGUID(); - } - } - } - - void SetHoldState(bool bOnHold) - { - SetEscortPaused(bOnHold); - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhaseTimer = uiTimer; - ++uiStep; - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 0: - case 1: - case 3: - case 9: - case 10: - case 11: - case 22: - case 23: - case 26: - case 55: - case 56: - SetHoldState(true); - bStepping = true; - break; - case 7: - if (Unit* pCityman0 = me->SummonCreature(NPC_CITY_MAN,2091.977f,1275.021f,140.757f,0.558f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) - uiCitymenGUID[0] = pCityman0->GetGUID(); - if (Unit* pCityman1 = me->SummonCreature(NPC_CITY_MAN2,2093.514f,1275.842f,140.408f,3.801f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) - uiCitymenGUID[1] = pCityman1->GetGUID(); - break; - case 8: - uiGossipStep = 1; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - case 12: - SetRun(true); - DoScriptText(SAY_PHASE210, me); - if (Unit* pDisguised0 = me->SummonCreature(NPC_CITY_MAN3,2398.14f,1207.81f,134.04f,5.155249f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[0] = pDisguised0->GetGUID(); - if (Unit* pDisguised1 = me->SummonCreature(NPC_CITY_MAN4,2403.22f,1205.54f,134.04f,3.311264f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[1] = pDisguised1->GetGUID(); - - if (Unit* pDisguised2 = me->SummonCreature(NPC_CITY_MAN,2400.82f,1201.69f,134.01f,1.534082f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[2] = pDisguised2->GetGUID(); - pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); - pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[0]); - pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); - } - } - } - break; - case 20: - uiGossipStep = 2; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetRun(false); - SetHoldState(true); - break; - case 21: - DoScriptText(SAY_PHASE301, me); - break; - case 25: - SetRun(false); - SpawnTimeRift(0,&uiInfiniteDraconianGUID[0]); - DoScriptText(SAY_PHASE307,me); - break; - case 29: - SetRun(false); - SpawnTimeRift(5,&uiInfiniteDraconianGUID[0]); - SpawnTimeRift(8,&uiInfiniteDraconianGUID[2]); - DoScriptText(SAY_PHASE309,me); - SetHoldState(true); - bStepping = true; - break; - case 31: - SetRun(false); - SpawnTimeRift(11,&uiInfiniteDraconianGUID[0]); - SpawnTimeRift(14,&uiInfiniteDraconianGUID[2]); - DoScriptText(SAY_PHASE311,me); - SetHoldState(true); - bStepping = true; - break; - case 32: - DoScriptText(SAY_PHASE401,me); - break; - case 34: - DoScriptText(SAY_PHASE402,me); - break; - case 35: - DoScriptText(SAY_PHASE403,me); - break; - case 36: - if (pInstance) - { - GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SHKAF_GATE)); - pGate->SetGoState(GO_STATE_ACTIVE); - } - break; - case 45: - SetRun(true); - SetDespawnAtFar(false); - uiGossipStep = 4; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - case 47: - SetRun(false); - DoScriptText(SAY_PHASE405,me); - break; - case 48: - SetRun(true); - DoScriptText(SAY_PHASE406,me); - break; - case 53: - DoScriptText(SAY_PHASE407,me); - break; - case 54: - uiGossipStep = 5; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - } - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - DoMeleeAttackIfReady(); - - if (bStepping) - { - if (uiPhaseTimer <= diff) - { - switch(uiStep) - { - //After reset - case 0: - if (Unit* pJaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f)) - uiJainaGUID = pJaina->GetGUID(); - else if (Unit* pJaina = me->SummonCreature(NPC_JAINA,1895.48f,1292.66f,143.706f,0.023475f,TEMPSUMMON_DEAD_DESPAWN,180000)) - uiJainaGUID = pJaina->GetGUID(); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 0 - case 1: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - if (Unit* pUther = me->SummonCreature(NPC_UTHER,1794.357f,1272.183f,140.558f,1.37f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiUtherGUID = pUther->GetGUID(); - pUther->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pUther->GetMotionMaster()->MovePoint(0, 1897.018f, 1287.487f, 143.481f); - pUther->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiUtherGUID); - } - JumpToNextStep(17000); - break; - case 2: - DoScriptText(SAY_PHASE101, me); - JumpToNextStep(2000); - break; - case 3: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - { - DoScriptText(SAY_PHASE102, pUther); - } - JumpToNextStep(8000); - break; - case 4: - SetEscortPaused(false); - bStepping = false; - SetRun(false); - DoScriptText(SAY_PHASE103, me); - JumpToNextStep(0); - break; - //After waypoint 1 - case 5: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - pJaina->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - DoScriptText(SAY_PHASE104, me); - JumpToNextStep(10000); - break; - case 6: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE105, pUther); - JumpToNextStep(1000); - break; - case 7: - DoScriptText(SAY_PHASE106, me); - JumpToNextStep(4000); - break; - case 8: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE107, pUther); - JumpToNextStep(6000); - break; - case 9: - DoScriptText(SAY_PHASE108, me); - JumpToNextStep(4000); - break; - case 10: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE109, pUther); - JumpToNextStep(8000); - break; - case 11: - DoScriptText(SAY_PHASE110, me); - JumpToNextStep(4000); - break; - case 12: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE111, pUther); - JumpToNextStep(4000); - break; - case 13: - DoScriptText(SAY_PHASE112, me); - JumpToNextStep(11000); - break; - case 14: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - DoScriptText(SAY_PHASE113, pJaina); - JumpToNextStep(3000); - break; - case 15: - DoScriptText(SAY_PHASE114, me); - JumpToNextStep(9000); - break; - case 16: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE115, pUther); - JumpToNextStep(4000); - break; - case 17: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - { - pUther->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pUther->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); - } - JumpToNextStep(1000); - break; - case 18: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - { - me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); - pJaina->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pJaina->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); - } - JumpToNextStep(1000); - break; - case 19: - DoScriptText(SAY_PHASE116, me); - JumpToNextStep(1000); - break; - case 20: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - DoScriptText(SAY_PHASE117, pJaina); - JumpToNextStep(3000); - break; - case 21: - SetEscortPaused(false); - bStepping = false; - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After waypoint 3 - case 22: - DoScriptText(SAY_PHASE118, me); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); - JumpToNextStep(10000); - break; - case 23: - SetEscortPaused(false); - bStepping = false; - SetRun(true); - - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - pJaina->DisappearAndDie(); - - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - pUther->DisappearAndDie(); - - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After Gossip 1 (waypoint 8) - case 24: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2026.469f,1287.088f,143.596f,1.37f,TEMPSUMMON_TIMED_DESPAWN,14000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - JumpToNextStep(1000); - break; - case 25: - DoScriptText(SAY_PHASE201, me); - JumpToNextStep(12000); - break; - case 26: - SetEscortPaused(false); - bStepping = false; - SetRun(false); - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After waypoint 9 - case 27: - me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[0]); - if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) - { - pCityman->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - pCityman->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pCityman->GetMotionMaster()->MovePoint(0, 2088.625f,1279.191f,140.743f); - } - JumpToNextStep(2000); - break; - case 28: - if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) - DoScriptText(SAY_PHASE202, pCityman); - JumpToNextStep(4000); - break; - case 29: - SetEscortPaused(false); - bStepping = false; - DoScriptText(SAY_PHASE203, me); - JumpToNextStep(0); - break; - //After waypoint 10 - case 30: - me->HandleEmoteCommand(37); - JumpToNextStep(1000); - break; - case 31: - SetEscortPaused(false); - bStepping = false; - if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) - { - DoScriptText(SAY_PHASE204, pCityman1); - pCityman1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pCityman0 = Unit::GetCreature(*me, uiCitymenGUID[0])) - pCityman0->Kill(pCityman0); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[1]); - } - JumpToNextStep(0); - break; - //After waypoint 11 - case 32: - me->HandleEmoteCommand(37); - JumpToNextStep(1000); - break; - case 33: - if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) - pCityman1->Kill(pCityman1); - JumpToNextStep(1000); - break; - case 34: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - DoScriptText(SAY_PHASE205, me); - JumpToNextStep(3000); - break; - case 35: - if (Unit* pStalkerM = me->SummonCreature(NPC_INVIS_TARGET,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) - { - uiStalkerGUID = pStalkerM->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - JumpToNextStep(1000); - break; - case 36: - if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) - { - if (Creature* pStalkerM = Unit::GetCreature(*me, uiStalkerGUID)) - pMalganis->CastSpell(pStalkerM,63793,false); - - uiMalganisGUID = pMalganis->GetGUID(); - DoScriptText(SAY_PHASE206, pMalganis); - pMalganis->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - pMalganis->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(11000); - break; - case 37: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - { - if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN, 100.0f)) - pZombie->UpdateEntry(NPC_ZOMBIE, 0); - else if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN2, 100.0f)) - pZombie->UpdateEntry(NPC_ZOMBIE, 0); - else //There's no one else to transform - uiStep++; - } - else - uiStep++; - uiPhaseTimer = 500; - break; - case 38: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - DoScriptText(SAY_PHASE207, pMalganis); - JumpToNextStep(17000); - break; - case 39: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - pMalganis->SetVisibility(VISIBILITY_OFF); - DoScriptText(SAY_PHASE208, me); - JumpToNextStep(7000); - break; - case 40: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - DoScriptText(SAY_PHASE209, me); - - uiBossEvent = DATA_MEATHOOK_EVENT; - if (pInstance) - pInstance->SetData(DATA_ARTHAS_EVENT, IN_PROGRESS); - - me->SetReactState(REACT_DEFENSIVE); - SetDespawnAtFar(false); - JumpToNextStep(5000); - break; - case 41: //Summon wave group - case 43: - case 45: - case 47: - case 51: - case 53: - case 55: - case 57: - if (pInstance->GetData(uiBossEvent) != DONE) - { - SpawnWaveGroup(uiWave, uiWaveGUID); - uiWave++; - } - JumpToNextStep(500); - break; - case 42: //Wait group to die - case 44: - case 46: - case 48: - case 52: - case 54: - case 56: - case 58: - if (pInstance->GetData(uiBossEvent) != DONE) - { - uint32 mobCounter = 0; - uint32 deadCounter = 0; - for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - { - if (uiWaveGUID[i] == 0) - break; - ++mobCounter; - Unit* pTemp = Unit::GetCreature(*me, uiWaveGUID[i]); - if (!pTemp || pTemp->isDead()) - ++deadCounter; - } - - if (mobCounter <= deadCounter) //If group is dead - JumpToNextStep(1000); - else - uiPhaseTimer = 1000; - } - else - JumpToNextStep(500); - break; - case 49: //Summon Boss - case 59: - if (pInstance->GetData(uiBossEvent) != DONE) - { - uint32 uiBossID = 0; - if (uiBossEvent == DATA_MEATHOOK_EVENT) - uiBossID = NPC_MEATHOOK; - else if (uiBossEvent == DATA_SALRAMM_EVENT) - uiBossID = NPC_SALRAMM; - - if (Unit* pBoss = me->SummonCreature(uiBossID,2232.19f,1331.933f,126.662f,3.15f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - uiBossGUID = pBoss->GetGUID(); - pBoss->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pBoss->GetMotionMaster()->MovePoint(0, 2194.110f,1332.00f,130.00f); - } - } - JumpToNextStep(30000); - break; - case 50: //Wait Boss death - case 60: - if (pInstance) - { - if (pInstance->GetData(uiBossEvent) == DONE) - { - JumpToNextStep(1000); - if (uiBossEvent == DATA_MEATHOOK_EVENT) - uiBossEvent = DATA_SALRAMM_EVENT; - else if (uiBossEvent == DATA_SALRAMM_EVENT) - { - SetHoldState(false); - bStepping = false; - uiBossEvent = DATA_EPOCH_EVENT; - } - } - else if (pInstance->GetData(uiBossEvent) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After Gossip 2 (waypoint 22) - case 61: - me->SetReactState(REACT_AGGRESSIVE); - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) - pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) - pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - JumpToNextStep(1000); - break; - case 62: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - DoScriptText(SAY_PHASE302, pDisguised0); - JumpToNextStep(7000); - break; - case 63: - DoScriptText(SAY_PHASE303, me); - SetHoldState(false); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 23 - case 64: - me->HandleEmoteCommand(54); - JumpToNextStep(1000); - break; - case 65: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - pDisguised0->HandleEmoteCommand(11); - JumpToNextStep(1000); - break; - case 66: - DoScriptText(SAY_PHASE304,me); - JumpToNextStep(2000); - break; - case 67: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - DoScriptText(SAY_PHASE305,pDisguised0); - JumpToNextStep(1000); - break; - case 68: - if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) - { - pDisguised2->UpdateEntry(NPC_INFINITE_HUNTER, 0); - //Make them unattackable - pDisguised2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised2->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 69: - if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) - { - pDisguised1->UpdateEntry(NPC_INFINITE_AGENT, 0); - //Make them unattackable - pDisguised1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised1->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 70: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - { - pDisguised0->UpdateEntry(NPC_INFINITE_ADVERSARY, 0); - //Make them unattackable - pDisguised0->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised0->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 71: - //After waypoint 26,29,31 - case 73: - case 75: - case 77: - //Make cratures attackable - for (uint32 i = 0; i< ENCOUNTER_DRACONIAN_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiInfiniteDraconianGUID[i])) - { - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pTemp->SetReactState(REACT_AGGRESSIVE); - } - JumpToNextStep(5000); - break; - case 72: - case 74: - case 76: - if (me->isInCombat()) - uiPhaseTimer = 1000; - else - { - if (uiStep == 72) DoScriptText(SAY_PHASE308,me); - if (uiStep == 74) DoScriptText(SAY_PHASE308,me); - if (uiStep == 76) DoScriptText(SAY_PHASE310,me); - SetHoldState(false); - bStepping = false; - SetRun(true); - JumpToNextStep(2000); - } - break; - case 78: - if (me->isInCombat()) - uiPhaseTimer = 1000; - else - { - DoScriptText(SAY_PHASE312,me); - JumpToNextStep(5000); - } - break; - case 79: - DoScriptText(SAY_PHASE313,me); - JumpToNextStep(1000); - break; - case 80: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - { - SpawnTimeRift(17,&uiEpochGUID); - if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) - DoScriptText(SAY_PHASE314,pEpoch); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiEpochGUID); - } - JumpToNextStep(18000); - break; - case 81: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - DoScriptText(SAY_PHASE315, me); - JumpToNextStep(6000); - break; - case 82: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - { - if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) - { - //Make Epoch attackable - pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pEpoch->SetReactState(REACT_AGGRESSIVE); - } - - } - JumpToNextStep(1000); - break; - case 83: - if (pInstance) - { - if (pInstance->GetData(DATA_EPOCH_EVENT) == DONE) - { - uiGossipStep = 3; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - bStepping = false; - uiBossEvent = DATA_MAL_GANIS_EVENT; - JumpToNextStep(15000); - } - else if (pInstance->GetData(DATA_EPOCH_EVENT) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After Gossip 4 - case 84: - DoScriptText(SAY_PHASE404,me); - SetHoldState(false); - bStepping = false; - break; - //After Gossip 5 - case 85: - DoScriptText(SAY_PHASE501, me); - if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2296.665f,1502.362f,128.362f,4.961f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - uiMalganisGUID = pMalganis->GetGUID(); - pMalganis->SetReactState(REACT_PASSIVE); - } - if (pInstance) - { - GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAL_GANIS_GATE_1)); - pGate->SetGoState(GO_STATE_ACTIVE); - } - SetHoldState(false); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 55 - case 86: - DoScriptText(SAY_PHASE502, me); - JumpToNextStep(6000); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); - break; - case 87: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - { - pMalganis->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_6 | UNIT_FLAG_UNK_9 | UNIT_FLAG_UNK_15); - pMalganis->SetReactState(REACT_AGGRESSIVE); - } - JumpToNextStep(1000); - break; - case 88: - if (pInstance) - { - if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == DONE) - { - SetHoldState(false); - JumpToNextStep(1000); - } - else if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After waypoint 56 - case 89: - SetRun(true); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); - DoScriptText(SAY_PHASE503, me); - JumpToNextStep(7000); - break; - case 90: - if (pInstance) - { - pInstance->SetData(DATA_ARTHAS_EVENT, DONE); //Rewards: Achiev & Chest ;D - me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance->GetData64(DATA_MAL_GANIS_GATE_2)); //Look behind - } - DoScriptText(SAY_PHASE504, me); - bStepping = false; - break; - } - } else uiPhaseTimer -= diff; - } - - //Battling skills - if (!me->getVictim()) - return; - - if (uiExorcismTimer < diff) - { - if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(target, SPELL_EXORCISM_N); - uiExorcismTimer = 7300; - } else uiExorcismTimer -= diff; - - if (HealthBelowPct(40)) - DoCast(me, SPELL_HOLY_LIGHT); - } -}; - -CreatureAI* GetAI_npc_arthas(Creature* pCreature) -{ - return new npc_arthasAI(pCreature); -} - -#define GOSSIP_ITEM_ARTHAS_0 "I'm ready to start Culling of Stratholme." -#define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready." -#define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness." -#define GOSSIP_ITEM_ARTHAS_3 "I'm ready." -#define GOSSIP_ITEM_ARTHAS_4 "For Lordaeron!" -#define GOSSIP_ITEM_ARTHAS_5 "I'm ready to battle the dreadlord, sire." - -bool GossipHello_npc_arthas(Player* pPlayer, Creature* pCreature) -{ - npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); - - if (pAI && pAI->bStepping == false) - { - switch (pAI->uiGossipStep) - { - case 0: //This one is a workaround since the very beggining of the script is wrong. - if (pPlayer->GetQuestStatus(13149) != QUEST_STATUS_COMPLETE) - return false; - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - break; - case 1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_1, pCreature->GetGUID()); - break; - case 2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_2, pCreature->GetGUID()); - break; - case 3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_3, pCreature->GetGUID()); - break; - case 4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_4, pCreature->GetGUID()); - break; - case 5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_5, pCreature->GetGUID()); - break; - default: - return false; - } - } - return true; -} - - -bool GossipSelect_npc_arthas(Player *pPlayer, Creature *pCreature, uint32 /*sender*/, uint32 action) -{ - npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); - - if (!pAI) - return false; - - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - pAI->Start(true,true,pPlayer->GetGUID(),0,false,false); - pAI->SetDespawnAtEnd(false); - pAI->bStepping = false; - pAI->uiStep = 1; - break; - case GOSSIP_ACTION_INFO_DEF+1: - pAI->bStepping = true; - pAI->uiStep = 24; - break; - case GOSSIP_ACTION_INFO_DEF+2: - pAI->SetHoldState(false); - pAI->bStepping = false; - pAI->uiStep = 61; - break; - case GOSSIP_ACTION_INFO_DEF+3: - pAI->SetHoldState(false); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pAI->bStepping = true; - pAI->uiStep = 84; - break; - case GOSSIP_ACTION_INFO_DEF+5: - pAI->bStepping = true; - pAI->uiStep = 85; - break; - } - pPlayer->CLOSE_GOSSIP_MENU(); - pAI->SetDespawnAtFar(true); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - return true; -} - -void AddSC_culling_of_stratholme() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_arthas"; - newscript->GetAI = &GetAI_npc_arthas; - newscript->pGossipHello = &GossipHello_npc_arthas; - newscript->pGossipSelect = &GossipSelect_npc_arthas; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h deleted file mode 100644 index 4278ad46500..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef DEF_CULLING_OF_STRATHOLME_H -#define DEF_CULLING_OF_STRATHOLME_H - -enum Data -{ - DATA_MEATHOOK_EVENT, - DATA_SALRAMM_EVENT, - DATA_EPOCH_EVENT, - DATA_MAL_GANIS_EVENT, - DATA_INFINITE_EVENT, - DATA_ARTHAS_EVENT -}; - -enum Data64 -{ - DATA_ARTHAS, - DATA_MEATHOOK, - DATA_SALRAMM, - DATA_EPOCH, - DATA_MAL_GANIS, - DATA_INFINITE, - DATA_SHKAF_GATE, - DATA_MAL_GANIS_GATE_1, - DATA_MAL_GANIS_GATE_2, - DATA_EXIT_GATE, - DATA_MAL_GANIS_CHEST -}; - -enum Creatures -{ - NPC_MEATHOOK = 26529, - NPC_SALRAMM = 26530, - NPC_EPOCH = 26532, - NPC_MAL_GANIS = 26533, - NPC_INFINITE = 32273, - NPC_ARTHAS = 26499, - NPC_JAINA = 26497, - NPC_UTHER = 26528 -}; - -enum GameObjects -{ - GO_SHKAF_GATE = 188686, - GO_MALGANIS_GATE_1 = 187711, - GO_MALGANIS_GATE_2 = 187723, - GO_EXIT_GATE = 191788, - GO_MALGANIS_CHEST_N = 190663, - GO_MALGANIS_CHEST_H = 193597 -}; -#endif diff --git a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp deleted file mode 100644 index 73742a1e748..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -#define MAX_ENCOUNTER 5 - -/* Culling of Stratholme encounters: -0 - Meathook -1 - Salramm the Fleshcrafter -2 - Chrono-Lord Epoch -3 - Mal'Ganis -4 - Infinite Corruptor (Heroic only) -*/ - -struct instance_culling_of_stratholme : public ScriptedInstance -{ - instance_culling_of_stratholme(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiArthas; - uint64 uiMeathook; - uint64 uiSalramm; - uint64 uiEpoch; - uint64 uiMalGanis; - uint64 uiInfinite; - - uint64 uiShkafGate; - uint64 uiMalGanisGate1; - uint64 uiMalGanisGate2; - uint64 uiExitGate; - uint64 uiMalGanisChest; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_ARTHAS: - uiArthas = pCreature->GetGUID(); - break; - case NPC_MEATHOOK: - uiMeathook = pCreature->GetGUID(); - break; - case NPC_SALRAMM: - uiSalramm = pCreature->GetGUID(); - break; - case NPC_EPOCH: - uiEpoch = pCreature->GetGUID(); - break; - case NPC_MAL_GANIS: - uiMalGanis = pCreature->GetGUID(); - break; - case NPC_INFINITE: - uiInfinite = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_SHKAF_GATE: - uiShkafGate = pGo->GetGUID(); - break; - case GO_MALGANIS_GATE_1: - uiMalGanisGate1 = pGo->GetGUID(); - break; - case GO_MALGANIS_GATE_2: - uiMalGanisGate2 = pGo->GetGUID(); - break; - case GO_EXIT_GATE: - uiExitGate = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(uiExitGate,true); - break; - case GO_MALGANIS_CHEST_N: - case GO_MALGANIS_CHEST_H: - uiMalGanisChest = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MEATHOOK_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_SALRAMM_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_EPOCH_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_MAL_GANIS_EVENT: - m_auiEncounter[3] = data; - - switch(m_auiEncounter[3]) - { - case NOT_STARTED: - HandleGameObject(uiMalGanisGate2,true); - break; - case IN_PROGRESS: - HandleGameObject(uiMalGanisGate2,false); - break; - case DONE: - HandleGameObject(uiExitGate, true); - if (GameObject *pGo = instance->GetGameObject(uiMalGanisChest)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - } - break; - case DATA_INFINITE_EVENT: - m_auiEncounter[4] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_MEATHOOK_EVENT: return m_auiEncounter[0]; - case DATA_SALRAMM_EVENT: return m_auiEncounter[1]; - case DATA_EPOCH_EVENT: return m_auiEncounter[2]; - case DATA_MAL_GANIS_EVENT: return m_auiEncounter[3]; - case DATA_INFINITE_EVENT: return m_auiEncounter[4]; - } - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_ARTHAS: return uiArthas; - case DATA_MEATHOOK: return uiMeathook; - case DATA_SALRAMM: return uiSalramm; - case DATA_EPOCH: return uiEpoch; - case DATA_MAL_GANIS: return uiMalGanis; - case DATA_INFINITE: return uiInfinite; - case DATA_SHKAF_GATE: return uiShkafGate; - case DATA_MAL_GANIS_GATE_1: return uiMalGanisGate1; - case DATA_MAL_GANIS_GATE_2: return uiMalGanisGate2; - case DATA_EXIT_GATE: return uiExitGate; - case DATA_MAL_GANIS_CHEST: return uiMalGanisChest; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "C S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; - - if (dataHead1 == 'C' && dataHead2 == 'S') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap) -{ - return new instance_culling_of_stratholme(pMap); -} - -void AddSC_instance_culling_of_stratholme() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_culling_of_stratholme"; - newscript->GetInstanceData = &GetInstanceData_instance_culling_of_stratholme; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp deleted file mode 100644 index 49cf7cd4433..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Aeonus -SD%Complete: 80 -SDComment: Some spells not implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269012, - SAY_AGGRO = -1269013, - SAY_BANISH = -1269014, - SAY_SLAY1 = -1269015, - SAY_SLAY2 = -1269016, - SAY_DEATH = -1269017, - EMOTE_FRENZY = -1269018, - - SPELL_CLEAVE = 40504, - SPELL_TIME_STOP = 31422, - SPELL_ENRAGE = 37605, - SPELL_SAND_BREATH = 31473, - H_SPELL_SAND_BREATH = 39049 -}; - -struct boss_aeonusAI : public ScriptedAI -{ - boss_aeonusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SandBreath_Timer; - uint32 TimeStop_Timer; - uint32 Frenzy_Timer; - - void Reset() - { - SandBreath_Timer = 15000+rand()%15000; - TimeStop_Timer = 10000+rand()%5000; - Frenzy_Timer = 30000+rand()%15000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_RIFT,DONE); - pInstance->SetData(TYPE_MEDIVH,DONE);//FIXME: later should be removed - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sand Breath - if (SandBreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SAND_BREATH); - SandBreath_Timer = 15000+rand()%10000; - } else SandBreath_Timer -= diff; - - //Time Stop - if (TimeStop_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIME_STOP); - TimeStop_Timer = 20000+rand()%15000; - } else TimeStop_Timer -= diff; - - //Frenzy - if (Frenzy_Timer <= diff) - { - DoScriptText(EMOTE_FRENZY, me); - DoCast(me, SPELL_ENRAGE); - Frenzy_Timer = 20000+rand()%15000; - } else Frenzy_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_aeonus(Creature* pCreature) -{ - return new boss_aeonusAI (pCreature); -} - -void AddSC_boss_aeonus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_aeonus"; - newscript->GetAI = &GetAI_boss_aeonus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp deleted file mode 100644 index 1f2b4a80612..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Chrono_Lord_Deja -SD%Complete: 65 -SDComment: All abilities not implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269006, - SAY_AGGRO = -1269007, - SAY_BANISH = -1269008, - SAY_SLAY1 = -1269009, - SAY_SLAY2 = -1269010, - SAY_DEATH = -1269011, - - SPELL_ARCANE_BLAST = 31457, - H_SPELL_ARCANE_BLAST = 38538, - SPELL_ARCANE_DISCHARGE = 31472, - H_SPELL_ARCANE_DISCHARGE = 38539, - SPELL_TIME_LAPSE = 31467, - SPELL_ATTRACTION = 38540 //Not Implemented (Heroic mode) -}; - -struct boss_chrono_lord_dejaAI : public ScriptedAI -{ - boss_chrono_lord_dejaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 ArcaneBlast_Timer; - uint32 TimeLapse_Timer; - uint32 Attraction_Timer; - uint32 ArcaneDischarge_Timer; - - void Reset() - { - ArcaneBlast_Timer = 18000+rand()%5000; - TimeLapse_Timer = 10000+rand()%5000; - ArcaneDischarge_Timer = 20000+rand()%10000; - Attraction_Timer = 25000+rand()%10000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Arcane Blast - if (ArcaneBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BLAST); - ArcaneBlast_Timer = 15000+rand()%10000; - } else ArcaneBlast_Timer -= diff; - - //Arcane Discharge - if (ArcaneDischarge_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - DoCast(pTarget, SPELL_ARCANE_DISCHARGE); - ArcaneDischarge_Timer = 20000+rand()%10000; - } else ArcaneDischarge_Timer -= diff; - - //Time Lapse - if (TimeLapse_Timer <= diff) - { - DoScriptText(SAY_BANISH, me); - DoCast(me, SPELL_TIME_LAPSE); - TimeLapse_Timer = 15000+rand()%10000; - } else TimeLapse_Timer -= diff; - - if (IsHeroic()) - { - if (Attraction_Timer <= diff) - { - DoCast(me, SPELL_ATTRACTION); - Attraction_Timer = 25000+rand()%10000; - } else Attraction_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_chrono_lord_deja(Creature* pCreature) -{ - return new boss_chrono_lord_dejaAI (pCreature); -} - -void AddSC_boss_chrono_lord_deja() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_chrono_lord_deja"; - newscript->GetAI = &GetAI_boss_chrono_lord_deja; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp deleted file mode 100644 index 04b4b020ead..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Temporus -SD%Complete: 75 -SDComment: More abilities need to be implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269000, - SAY_AGGRO = -1269001, - SAY_BANISH = -1269002, - SAY_SLAY1 = -1269003, - SAY_SLAY2 = -1269004, - SAY_DEATH = -1269005, - - SPELL_HASTE = 31458, - SPELL_MORTAL_WOUND = 31464, - SPELL_WING_BUFFET = 31475, - H_SPELL_WING_BUFFET = 38593, - SPELL_REFLECT = 38592 //Not Implemented (Heroic mod) -}; - -struct boss_temporusAI : public ScriptedAI -{ - boss_temporusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Haste_Timer; - uint32 SpellReflection_Timer; - uint32 MortalWound_Timer; - uint32 WingBuffet_Timer; - - void Reset() - { - Haste_Timer = 15000+rand()%8000; - SpellReflection_Timer = 30000; - MortalWound_Timer = 8000; - WingBuffet_Timer = 25000+rand()%10000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Attack Haste - if (Haste_Timer <= diff) - { - DoCast(me, SPELL_HASTE); - Haste_Timer = 20000+rand()%5000; - } else Haste_Timer -= diff; - - //MortalWound_Timer - if (MortalWound_Timer <= diff) - { - DoCast(me, SPELL_MORTAL_WOUND); - MortalWound_Timer = 10000+rand()%10000; - } else MortalWound_Timer -= diff; - - //Wing ruffet - if (WingBuffet_Timer <= diff) - { - DoCast(me, SPELL_WING_BUFFET); - WingBuffet_Timer = 20000+rand()%10000; - } else WingBuffet_Timer -= diff; - - if (IsHeroic()) - { - if (SpellReflection_Timer <= diff) - { - DoCast(me, SPELL_REFLECT); - SpellReflection_Timer = 25000+rand()%10000; - } else SpellReflection_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_temporus(Creature* pCreature) -{ - return new boss_temporusAI (pCreature); -} - -void AddSC_boss_temporus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_temporus"; - newscript->GetAI = &GetAI_boss_temporus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp deleted file mode 100644 index b0432a9b57c..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Dark_Portal -SD%Complete: 30 -SDComment: Misc NPC's and mobs for instance. Most here far from complete. -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -/* ContentData -npc_medivh_bm -npc_time_rift -npc_saat -EndContentData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -#define SAY_ENTER -1269020 //where does this belong? -#define SAY_INTRO -1269021 -#define SAY_WEAK75 -1269022 -#define SAY_WEAK50 -1269023 -#define SAY_WEAK25 -1269024 -#define SAY_DEATH -1269025 -#define SAY_WIN -1269026 -#define SAY_ORCS_ENTER -1269027 -#define SAY_ORCS_ANSWER -1269028 - -#define SPELL_CHANNEL 31556 -#define SPELL_PORTAL_RUNE 32570 //aura(portal on ground effect) - -#define SPELL_BLACK_CRYSTAL 32563 //aura -#define SPELL_PORTAL_CRYSTAL 32564 //summon - -#define SPELL_BANISH_PURPLE 32566 //aura -#define SPELL_BANISH_GREEN 32567 //aura - -#define SPELL_CORRUPT 31326 -#define SPELL_CORRUPT_AEONUS 37853 - -#define C_COUNCIL_ENFORCER 17023 - -struct npc_medivh_bmAI : public ScriptedAI -{ - npc_medivh_bmAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SpellCorrupt_Timer; - uint32 Check_Timer; - - bool Life75; - bool Life50; - bool Life25; - - void Reset() - { - SpellCorrupt_Timer = 0; - - if (!pInstance) - return; - - if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) - DoCast(me, SPELL_CHANNEL, true); - else if (me->HasAura(SPELL_CHANNEL)) - me->RemoveAura(SPELL_CHANNEL); - - DoCast(me, SPELL_PORTAL_RUNE, true); - } - - void MoveInLineOfSight(Unit *who) - { - if (!pInstance) - return; - - if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 10.0f)) - { - if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS || pInstance->GetData(TYPE_MEDIVH) == DONE) - return; - - DoScriptText(SAY_INTRO, me); - pInstance->SetData(TYPE_MEDIVH,IN_PROGRESS); - DoCast(me, SPELL_CHANNEL, false); - Check_Timer = 5000; - } - else if (who->GetTypeId() == TYPEID_UNIT && me->IsWithinDistInMap(who, 15.0f)) - { - if (pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) - return; - - uint32 entry = who->GetEntry(); - if (entry == C_ASSAS || entry == C_WHELP || entry == C_CHRON || entry == C_EXECU || entry == C_VANQU) - { - who->StopMoving(); - who->CastSpell(me,SPELL_CORRUPT,false); - } - else if (entry == C_AEONUS) - { - who->StopMoving(); - who->CastSpell(me,SPELL_CORRUPT_AEONUS,false); - } - } - } - - void AttackStart(Unit * /*who*/) - { - //if (pInstance && pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) - //return; - - //ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit * /*who*/) {} - - void SpellHit(Unit* /*caster*/, const SpellEntry* spell) - { - if (SpellCorrupt_Timer) - return; - - if (spell->Id == SPELL_CORRUPT_AEONUS) - SpellCorrupt_Timer = 1000; - - if (spell->Id == SPELL_CORRUPT) - SpellCorrupt_Timer = 3000; - } - - void JustDied(Unit* Killer) - { - if (Killer->GetEntry() == me->GetEntry()) - return; - - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (SpellCorrupt_Timer) - { - if (SpellCorrupt_Timer <= diff) - { - pInstance->SetData(TYPE_MEDIVH,SPECIAL); - - if (me->HasAura(SPELL_CORRUPT_AEONUS)) - SpellCorrupt_Timer = 1000; - else if (me->HasAura(SPELL_CORRUPT)) - SpellCorrupt_Timer = 3000; - else - SpellCorrupt_Timer = 0; - } else SpellCorrupt_Timer -= diff; - } - - if (Check_Timer) - { - if (Check_Timer <= diff) - { - uint32 pct = pInstance->GetData(DATA_SHIELD); - - Check_Timer = 5000; - - if (Life25 && pct <= 25) - { - DoScriptText(SAY_WEAK25, me); - Life25 = false; - } - else if (Life50 && pct <= 50) - { - DoScriptText(SAY_WEAK50, me); - Life50 = false; - } - else if (Life75 && pct <= 75) - { - DoScriptText(SAY_WEAK75, me); - Life75 = false; - } - - //if we reach this it means event was running but at some point reset. - if (pInstance->GetData(TYPE_MEDIVH) == NOT_STARTED) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - me->Respawn(); - return; - } - - if (pInstance->GetData(TYPE_RIFT) == DONE) - { - DoScriptText(SAY_WIN, me); - Check_Timer = 0; - - if (me->HasAura(SPELL_CHANNEL)) - me->RemoveAura(SPELL_CHANNEL); - - //TODO: start the post-event here - pInstance->SetData(TYPE_MEDIVH,DONE); - } - } else Check_Timer -= diff; - } - - //if (!UpdateVictim()) - //return; - - //DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_medivh_bm(Creature* pCreature) -{ - return new npc_medivh_bmAI (pCreature); -} - -struct Wave -{ - uint32 PortalMob[4]; //spawns for portal waves (in order) -}; - -static Wave PortalWaves[]= -{ - {C_ASSAS, C_WHELP, C_CHRON, 0}, - {C_EXECU, C_CHRON, C_WHELP, C_ASSAS}, - {C_EXECU, C_VANQU, C_CHRON, C_ASSAS} -}; - -struct npc_time_riftAI : public ScriptedAI -{ - npc_time_riftAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 TimeRiftWave_Timer; - uint8 mRiftWaveCount; - uint8 mPortalCount; - uint8 mWaveId; - - void Reset() - { - - TimeRiftWave_Timer = 15000; - mRiftWaveCount = 0; - - if (!pInstance) - return; - - mPortalCount = pInstance->GetData(DATA_PORTAL_COUNT); - - if (mPortalCount < 6) - mWaveId = 0; - else if (mPortalCount > 12) - mWaveId = 2; - else mWaveId = 1; - - } - void EnterCombat(Unit * /*who*/) {} - - void DoSummonAtRift(uint32 creature_entry) - { - if (!creature_entry) - return; - - if (pInstance && pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) - { - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - return; - } - - Position pos; - me->GetRandomNearPosition(pos, 10.0f); - - //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); - - if (Unit *Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) - if (Unit *temp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_MEDIVH) : 0)) - Summon->AddThreat(temp,0.0f); - } - - void DoSelectSummon() - { - uint32 entry = 0; - - if ((mRiftWaveCount > 2 && mWaveId < 1) || mRiftWaveCount > 3) - mRiftWaveCount = 0; - - entry = PortalWaves[mWaveId].PortalMob[mRiftWaveCount]; - debug_log("TSCR: npc_time_rift: summoning wave Creature (Wave %u, Entry %u).",mRiftWaveCount,entry); - - ++mRiftWaveCount; - - if (entry == C_WHELP) - { - for (uint8 i = 0; i < 3; ++i) - DoSummonAtRift(entry); - } else DoSummonAtRift(entry); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (TimeRiftWave_Timer <= diff) - { - DoSelectSummon(); - TimeRiftWave_Timer = 15000; - } else TimeRiftWave_Timer -= diff; - - if (me->IsNonMeleeSpellCasted(false)) - return; - - debug_log("TSCR: npc_time_rift: not casting anylonger, i need to die."); - me->setDeathState(JUST_DIED); - - if (pInstance->GetData(TYPE_RIFT) == IN_PROGRESS) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } -}; - -CreatureAI* GetAI_npc_time_rift(Creature* pCreature) -{ - return new npc_time_riftAI (pCreature); -} - -#define SAY_SAAT_WELCOME -1269019 - -#define GOSSIP_ITEM_OBTAIN "[PH] Obtain Chrono-Beacon" -#define SPELL_CHRONO_BEACON 34975 -#define ITEM_CHRONO_BEACON 24289 - -bool GossipHello_npc_saat(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(10000, pCreature->GetGUID()); - return true; - } - else if (pPlayer->GetQuestRewardStatus(QUEST_OPENING_PORTAL) && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(10001, pCreature->GetGUID()); - return true; - } - - pPlayer->SEND_GOSSIP_MENU(10002, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_saat(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer,SPELL_CHRONO_BEACON,false); - } - return true; -} - -void AddSC_dark_portal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_medivh_bm"; - newscript->GetAI = &GetAI_npc_medivh_bm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_time_rift"; - newscript->GetAI = &GetAI_npc_time_rift; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_saat"; - newscript->pGossipHello = &GossipHello_npc_saat; - newscript->pGossipSelect = &GossipSelect_npc_saat; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h deleted file mode 100644 index 7bfd8c917d7..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/dark_portal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_DARKPORTAL_H -#define DEF_DARKPORTAL_H - -#define TYPE_MEDIVH 1 -#define TYPE_RIFT 2 - -#define DATA_MEDIVH 10 -#define DATA_PORTAL_COUNT 11 -#define DATA_SHIELD 12 - -#define WORLD_STATE_BM 2541 -#define WORLD_STATE_BM_SHIELD 2540 -#define WORLD_STATE_BM_RIFT 2784 - -#define QUEST_OPENING_PORTAL 10297 -#define QUEST_MASTER_TOUCH 9836 - -#define C_TIME_KEEPER 17918 -#define C_RKEEP 21104 -#define C_RLORD 17839 -#define C_DEJA 17879 -#define C_TEMPO 17880 -#define C_AEONUS 17881 -#define C_ASSAS 17835 -#define C_WHELP 21818 -#define C_CHRON 17892 -#define C_EXECU 18994 -#define C_VANQU 18995 - -#endif - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp deleted file mode 100644 index d1280230808..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Dark_Portal -SD%Complete: 50 -SDComment: Quest support: 9836, 10297. Currently in progress. -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -#define MAX_ENCOUNTER 2 - -#define C_MEDIVH 15608 -#define C_TIME_RIFT 17838 - -#define SPELL_RIFT_CHANNEL 31387 - -#define RIFT_BOSS 1 - -inline uint32 RandRiftBoss() { return ((rand()%2) ? C_RKEEP : C_RLORD); } - -float PortalLocation[4][4]= -{ - {-2041.06, 7042.08, 29.99, 1.30}, - {-1968.18, 7042.11, 21.93, 2.12}, - {-1885.82, 7107.36, 22.32, 3.07}, - {-1928.11, 7175.95, 22.11, 3.44} -}; - -struct Wave -{ - uint32 PortalBoss; //protector of current portal - uint32 NextPortalTime; //time to next portal, or 0 if portal boss need to be killed -}; - -static Wave RiftWaves[]= -{ - {RIFT_BOSS, 0}, - {C_DEJA, 0}, - {RIFT_BOSS, 120000}, - {C_TEMPO, 140000}, - {RIFT_BOSS, 120000}, - {C_AEONUS, 0} -}; - -struct instance_dark_portal : public ScriptedInstance -{ - instance_dark_portal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint32 mRiftPortalCount; - uint32 mShieldPercent; - uint8 mRiftWaveCount; - uint8 mRiftWaveId; - - uint32 NextPortal_Timer; - - uint64 MedivhGUID; - uint8 CurrentRiftId; - - void Initialize() - { - MedivhGUID = 0; - Clear(); - } - - void Clear() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - mRiftPortalCount = 0; - mShieldPercent = 100; - mRiftWaveCount = 0; - mRiftWaveId = 0; - - CurrentRiftId = 0; - - NextPortal_Timer = 0; - } - - void InitWorldState(bool Enable = true) - { - DoUpdateWorldState(WORLD_STATE_BM,Enable ? 1 : 0); - DoUpdateWorldState(WORLD_STATE_BM_SHIELD, 100); - DoUpdateWorldState(WORLD_STATE_BM_RIFT, 0); - } - - bool IsEncounterInProgress() - { - if (GetData(TYPE_MEDIVH) == IN_PROGRESS) - return true; - - return false; - } - - void OnPlayerEnter(Player* pPlayer) - { - if (GetData(TYPE_MEDIVH) == IN_PROGRESS) - return; - - pPlayer->SendUpdateWorldState(WORLD_STATE_BM,0); - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == C_MEDIVH) - MedivhGUID = pCreature->GetGUID(); - } - - //what other conditions to check? - bool CanProgressEvent() - { - if (instance->GetPlayers().isEmpty()) - return false; - - return true; - } - - uint8 GetRiftWaveId() - { - switch(mRiftPortalCount) - { - case 6: - mRiftWaveId = 2; - return 1; - case 12: - mRiftWaveId = 4; - return 3; - case 18: - return 5; - default: - return mRiftWaveId; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_MEDIVH: - if (data == SPECIAL && m_auiEncounter[0] == IN_PROGRESS) - { - --mShieldPercent; - - DoUpdateWorldState(WORLD_STATE_BM_SHIELD, mShieldPercent); - - if (!mShieldPercent) - { - if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) - { - if (pMedivh->isAlive()) - { - pMedivh->DealDamage(pMedivh, pMedivh->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - m_auiEncounter[0] = FAIL; - m_auiEncounter[1] = NOT_STARTED; - } - } - } - } - else - { - if (data == IN_PROGRESS) - { - debug_log("TSCR: Instance Dark Portal: Starting event."); - InitWorldState(); - m_auiEncounter[1] = IN_PROGRESS; - NextPortal_Timer = 15000; - } - - if (data == DONE) - { - //this may be completed further out in the post-event - debug_log("TSCR: Instance Dark Portal: Event completed."); - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - { - if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL); - - if (pPlayer->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH); - } - } - } - } - - m_auiEncounter[0] = data; - } - break; - case TYPE_RIFT: - if (data == SPECIAL) - { - if (mRiftPortalCount < 7) - NextPortal_Timer = 5000; - } - else - m_auiEncounter[1] = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_MEDIVH: - return m_auiEncounter[0]; - case TYPE_RIFT: - return m_auiEncounter[1]; - case DATA_PORTAL_COUNT: - return mRiftPortalCount; - case DATA_SHIELD: - return mShieldPercent; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - if (data == DATA_MEDIVH) - return MedivhGUID; - - return 0; - } - - Creature* SummonedPortalBoss(Creature* me) - { - uint32 entry = RiftWaves[GetRiftWaveId()].PortalBoss; - - if (entry == RIFT_BOSS) - entry = RandRiftBoss(); - - debug_log("TSCR: Instance Dark Portal: Summoning rift boss entry %u.",entry); - - Position pos; - me->GetRandomNearPosition(pos, 10.0f); - - //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); - - if (Creature *summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) - return summon; - - debug_log("TSCR: Instance Dark Portal: What just happened there? No boss, no loot, no fun..."); - return NULL; - } - - void DoSpawnPortal() - { - if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) - { - uint8 tmp = urand(0,2); - - if (tmp >= CurrentRiftId) - ++tmp; - - debug_log("TSCR: Instance Dark Portal: Creating Time Rift at locationId %i (old locationId was %u).",tmp,CurrentRiftId); - - CurrentRiftId = tmp; - - Creature *pTemp = pMedivh->SummonCreature(C_TIME_RIFT, - PortalLocation[tmp][0],PortalLocation[tmp][1],PortalLocation[tmp][2],PortalLocation[tmp][3], - TEMPSUMMON_CORPSE_DESPAWN,0); - if (pTemp) - { - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (Creature *pBoss = SummonedPortalBoss(pTemp)) - { - if (pBoss->GetEntry() == C_AEONUS) - pBoss->AddThreat(pMedivh,0.0f); - else - { - pBoss->AddThreat(pTemp,0.0f); - pTemp->CastSpell(pBoss,SPELL_RIFT_CHANNEL,false); - } - } - } - } - } - - void Update(uint32 diff) - { - if (m_auiEncounter[1] != IN_PROGRESS) - return; - - //add delay timer? - if (!CanProgressEvent()) - { - Clear(); - return; - } - - if (NextPortal_Timer) - { - if (NextPortal_Timer <= diff) - { - ++mRiftPortalCount; - - DoUpdateWorldState(WORLD_STATE_BM_RIFT, mRiftPortalCount); - - DoSpawnPortal(); - NextPortal_Timer = RiftWaves[GetRiftWaveId()].NextPortalTime; - } else NextPortal_Timer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_dark_portal(Map* pMap) -{ - return new instance_dark_portal(pMap); -} - -void AddSC_instance_dark_portal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_dark_portal"; - newscript->GetInstanceData = &GetInstanceData_instance_dark_portal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp deleted file mode 100644 index 14ce4a59b37..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp +++ /dev/null @@ -1,309 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_CARRION_SWARM 31306 -#define SPELL_SLEEP 31298 -#define SPELL_VAMPIRIC_AURA 38196 -#define SPELL_INFERNO 31299 - -#define SAY_ONDEATH "The clock... is still... ticking." -#define SOUND_ONDEATH 10982 - -#define SAY_ONSLAY1 "Your hopes are lost!" -#define SAY_ONSLAY2 "Scream for me!" -#define SAY_ONSLAY3 "Pity, no time for a slow death!" -#define SOUND_ONSLAY1 10981 -#define SOUND_ONSLAY2 11038 -#define SOUND_ONSLAY3 11039 - -#define SAY_SWARM1 "The swarm is eager to feed!" -#define SAY_SWARM2 "Pestilence upon you!" -#define SOUND_SWARM1 10979 -#define SOUND_SWARM2 11037 - -#define SAY_SLEEP1 "You look tired..." -#define SAY_SLEEP2 "Sweet dreams..." -#define SOUND_SLEEP1 10978 -#define SOUND_SLEEP2 11545 - -#define SAY_INFERNO1 "Let fire rain from above!" -#define SAY_INFERNO2 "Earth and sky shall burn!" -#define SOUND_INFERNO1 10980 -#define SOUND_INFERNO2 11036 - -#define SAY_ONAGGRO "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!" -#define SOUND_ONAGGRO 10977 - -struct boss_anetheronAI : public hyjal_trashAI -{ - boss_anetheronAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_SLEEP); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) - { - TempSpell->EffectImplicitTargetA[0] = 1; - TempSpell->EffectImplicitTargetB[0] = 0; - } - } - - uint32 SwarmTimer; - uint32 SleepTimer; - uint32 AuraTimer; - uint32 InfernoTimer; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - SwarmTimer = 45000; - SleepTimer = 60000; - AuraTimer = 5000; - InfernoTimer = 45000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, 0); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 4896.08, -1576.35, 1333.65); - AddWaypoint(1, 4898.68, -1615.02, 1329.48); - AddWaypoint(2, 4907.12, -1667.08, 1321.00); - AddWaypoint(3, 4963.18, -1699.35, 1340.51); - AddWaypoint(4, 4989.16, -1716.67, 1335.74); - AddWaypoint(5, 5026.27, -1736.89, 1323.02); - AddWaypoint(6, 5037.77, -1770.56, 1324.36); - AddWaypoint(7, 5067.23, -1789.95, 1321.17); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (SwarmTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CARRION_SWARM); - - SwarmTimer = urand(45000,60000); - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_SWARM1); - me->MonsterYell(SAY_SWARM1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_SWARM2); - me->MonsterYell(SAY_SWARM2, LANG_UNIVERSAL, 0); - break; - } - } else SwarmTimer -= diff; - - if (SleepTimer <= diff) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - pTarget->CastSpell(pTarget,SPELL_SLEEP,true); - } - SleepTimer = 60000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_SLEEP1); - me->MonsterYell(SAY_SLEEP1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_SLEEP2); - me->MonsterYell(SAY_SLEEP2, LANG_UNIVERSAL, 0); - break; - } - } else SleepTimer -= diff; - if (AuraTimer <= diff) - { - DoCast(me, SPELL_VAMPIRIC_AURA, true); - AuraTimer = urand(10000,20000); - } else AuraTimer -= diff; - if (InfernoTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_INFERNO); - InfernoTimer = 45000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_INFERNO1); - me->MonsterYell(SAY_INFERNO1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_INFERNO2); - me->MonsterYell(SAY_INFERNO2, LANG_UNIVERSAL, 0); - break; - } - } else InfernoTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_anetheron(Creature* pCreature) -{ - return new boss_anetheronAI (pCreature); -} - -#define SPELL_IMMOLATION 31303 -#define SPELL_INFERNO_EFFECT 31302 - -struct mob_towering_infernalAI : public ScriptedAI -{ - mob_towering_infernalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - AnetheronGUID = pInstance->GetData64(DATA_ANETHERON); - } - - uint32 ImmolationTimer; - uint32 CheckTimer; - uint64 AnetheronGUID; - ScriptedInstance* pInstance; - - void Reset() - { - DoCast(me, SPELL_INFERNO_EFFECT); - ImmolationTimer = 5000; - CheckTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - } - - void JustDied(Unit * /*victim*/) - { - } - - void MoveInLineOfSight(Unit *who) - { - if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) - AttackStart(who); - } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (AnetheronGUID) - { - Creature* boss = Unit::GetCreature((*me),AnetheronGUID); - if (!boss || (boss && boss->isDead())) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (ImmolationTimer <= diff) - { - DoCast(me, SPELL_IMMOLATION); - ImmolationTimer = 5000; - } else ImmolationTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_towering_infernal(Creature* pCreature) -{ - return new mob_towering_infernalAI (pCreature); -} - -void AddSC_boss_anetheron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_anetheron"; - newscript->GetAI = &GetAI_boss_anetheron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_towering_infernal"; - newscript->GetAI = &GetAI_mob_towering_infernal; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp deleted file mode 100644 index 8e1fa378e07..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Archimonde -SD%Complete: 85 -SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented. -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "SpellAuras.h" -#include "hyjal_trash.h" - -//text id -1534018 are the text used when previous events complete. Not part of this script. -#define SAY_AGGRO -1534019 -#define SAY_DOOMFIRE1 -1534020 -#define SAY_DOOMFIRE2 -1534021 -#define SAY_AIR_BURST1 -1534022 -#define SAY_AIR_BURST2 -1534023 -#define SAY_SLAY1 -1534024 -#define SAY_SLAY2 -1534025 -#define SAY_SLAY3 -1534026 -#define SAY_ENRAGE -1534027 -#define SAY_DEATH -1534028 -#define SAY_SOUL_CHARGE1 -1534029 -#define SAY_SOUL_CHARGE2 -1534030 - -#define SPELL_DENOUEMENT_WISP 32124 -#define SPELL_ANCIENT_SPARK 39349 -#define SPELL_PROTECTION_OF_ELUNE 38528 - -#define SPELL_DRAIN_WORLD_TREE 39140 -#define SPELL_DRAIN_WORLD_TREE_2 39141 - -#define SPELL_FINGER_OF_DEATH 31984 -#define SPELL_HAND_OF_DEATH 35354 -#define SPELL_AIR_BURST 32014 -#define SPELL_GRIP_OF_THE_LEGION 31972 -#define SPELL_DOOMFIRE_STRIKE 31903 //summons two creatures -#define SPELL_DOOMFIRE_SPAWN 32074 -#define SPELL_DOOMFIRE 31945 -#define SPELL_SOUL_CHARGE_YELLOW 32045 -#define SPELL_SOUL_CHARGE_GREEN 32051 -#define SPELL_SOUL_CHARGE_RED 32052 -#define SPELL_UNLEASH_SOUL_YELLOW 32054 -#define SPELL_UNLEASH_SOUL_GREEN 32057 -#define SPELL_UNLEASH_SOUL_RED 32053 -#define SPELL_FEAR 31970 - -#define CREATURE_ARCHIMONDE 17968 -#define CREATURE_DOOMFIRE 18095 -#define CREATURE_DOOMFIRE_SPIRIT 18104 -#define CREATURE_ANCIENT_WISP 17946 -#define CREATURE_CHANNEL_TARGET 22418 - -#define NORDRASSIL_X 5503.713 -#define NORDRASSIL_Y -3523.436 -#define NORDRASSIL_Z 1608.781 - -struct mob_ancient_wispAI : public ScriptedAI -{ - mob_ancient_wispAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - ArchimondeGUID = 0; - } - - ScriptedInstance* pInstance; - uint64 ArchimondeGUID; - uint32 CheckTimer; - - void Reset() - { - CheckTimer = 1000; - - if (pInstance) - ArchimondeGUID = pInstance->GetData64(DATA_ARCHIMONDE); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void EnterCombat(Unit* /*who*/) {} - - void DamageTaken(Unit* /*done_by*/, uint32 &damage) { damage = 0; } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (Unit* Archimonde = Unit::GetUnit((*me), ArchimondeGUID)) - { - if ((((Archimonde->GetHealth()*100) / Archimonde->GetMaxHealth()) < 2) || !Archimonde->isAlive()) - DoCast(me, SPELL_DENOUEMENT_WISP); - else - DoCast(Archimonde, SPELL_ANCIENT_SPARK); - } - CheckTimer = 1000; - } else CheckTimer -= diff; - } -}; - -/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will - MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */ -struct mob_doomfireAI : public ScriptedAI -{ - mob_doomfireAI(Creature* c) : ScriptedAI(c) {} - - void Reset() { } - - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit* /*who*/) {} - void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } -}; - -/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or - travels in random directions if pTarget cannot be found. */ -struct mob_doomfire_targettingAI : public ScriptedAI -{ - mob_doomfire_targettingAI(Creature* c) : ScriptedAI(c) {} - - uint64 TargetGUID; - uint32 ChangeTargetTimer; - - void Reset() - { - TargetGUID = 0; - ChangeTargetTimer = 5000; - } - - void MoveInLineOfSight(Unit* who) - { - //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0 - //when UpdateAI needs it, it will be forced to select randomPoint - if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER) - TargetGUID = who->GetGUID(); - } - - void EnterCombat(Unit* /*who*/) {} - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } - - void UpdateAI(const uint32 diff) - { - if (ChangeTargetTimer <= diff) - { - if (Unit *temp = Unit::GetUnit(*me,TargetGUID)) - { - me->GetMotionMaster()->MoveFollow(temp,0.0f,0.0f); - TargetGUID = 0; - } - else - { - Position pos; - me->GetRandomNearPosition(pos, 40); - me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - } - - ChangeTargetTimer = 5000; - } else ChangeTargetTimer -= diff; - } -}; - -/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers. - The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the - hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then - select a random pTarget and cast the spell on them. However, if someone IS in melee range, and this - is NOT the main tank (creature's victim), then we aggro that player and they become the new victim. - For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will - randomly select it's pTarget to follow and then we create the random movement making it unpredictable. */ - -struct boss_archimondeAI : public hyjal_trashAI -{ - boss_archimondeAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 DoomfireSpiritGUID; - uint64 WorldTreeGUID; - - uint32 DrainNordrassilTimer; - uint32 FearTimer; - uint32 AirBurstTimer; - uint32 GripOfTheLegionTimer; - uint32 DoomfireTimer; - uint32 SoulChargeTimer; - uint32 SoulChargeCount; - uint32 MeleeRangeCheckTimer; - uint32 HandOfDeathTimer; - uint32 SummonWispTimer; - uint32 WispCount; - uint32 EnrageTimer; - uint32 CheckDistanceTimer; - - bool Enraged; - bool BelowTenPercent; - bool HasProtected; - bool IsChanneling; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); - - DoomfireSpiritGUID = 0; - damageTaken = 0; - WorldTreeGUID = 0; - - DrainNordrassilTimer = 0; - FearTimer = 42000; - AirBurstTimer = 30000; - GripOfTheLegionTimer = urand(5000,25000); - DoomfireTimer = 20000; - SoulChargeTimer = urand(2000,30000); - SoulChargeCount = 0; - MeleeRangeCheckTimer = 15000; - HandOfDeathTimer = 2000; - WispCount = 0; // When ~30 wisps are summoned, Archimonde dies - EnrageTimer = 600000; // 10 minutes - CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage - SummonWispTimer = 0; - - Enraged = false; - BelowTenPercent = false; - HasProtected = false; - IsChanneling = false; - } - - void EnterCombat(Unit * /*who*/) - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * victim) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - - if (victim && (victim->GetTypeId() == TYPEID_PLAYER)) - GainSoulCharge(CAST_PLR(victim)); - } - - void GainSoulCharge(Player* victim) - { - switch(victim->getClass()) - { - case CLASS_PRIEST: - case CLASS_PALADIN: - case CLASS_WARLOCK: - victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); - break; - case CLASS_MAGE: - case CLASS_ROGUE: - case CLASS_WARRIOR: - victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); - break; - case CLASS_DRUID: - case CLASS_SHAMAN: - case CLASS_HUNTER: - victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); - break; - } - - SoulChargeTimer = urand(2000,30000); - ++SoulChargeCount; - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, DONE); - } - - bool CanUseFingerOfDeath() - { - // First we check if our current victim is in melee range or not. - Unit* victim = me->getVictim(); - if (victim && me->IsWithinDistInMap(victim, me->GetAttackDistance(victim))) - return false; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - if (m_threatlist.empty()) - return false; - - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - targets.push_back(pUnit); - } - - if (targets.empty()) - return false; - - targets.sort(Trinity::ObjectDistanceOrderPred(me)); - Unit *pTarget = targets.front(); - if (pTarget) - { - if (!me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) - return true; // Cast Finger of Death - else // This target is closest, he is our new tank - me->AddThreat(pTarget, me->getThreatManager().getThreat(me->getVictim())); - } - - return false; - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == CREATURE_ANCIENT_WISP) - summoned->AI()->AttackStart(me); - else - { - summoned->setFaction(me->getFaction()); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) - { - DoomfireSpiritGUID = summoned->GetGUID(); - } - - if (summoned->GetEntry() == CREATURE_DOOMFIRE) - { - summoned->CastSpell(summoned,SPELL_DOOMFIRE_SPAWN,false); - summoned->CastSpell(summoned,SPELL_DOOMFIRE,true,0,0,me->GetGUID()); - - if (Unit *DoomfireSpirit = Unit::GetUnit(*me, DoomfireSpiritGUID)) - { - summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit,0.0f,0.0f); - DoomfireSpiritGUID = 0; - } - } - } - - //this is code doing close to what the summoning spell would do (spell 31903) - void SummonDoomfire(Unit *pTarget) - { - me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, - pTarget->GetPositionX()+15.0,pTarget->GetPositionY()+15.0,pTarget->GetPositionZ(),0, - TEMPSUMMON_TIMED_DESPAWN, 27000); - - me->SummonCreature(CREATURE_DOOMFIRE, - pTarget->GetPositionX()-15.0,pTarget->GetPositionY()-15.0,pTarget->GetPositionZ(),0, - TEMPSUMMON_TIMED_DESPAWN, 27000); - } - - void UnleashSoulCharge() - { - me->InterruptNonMeleeSpells(false); - - bool HasCast = false; - uint32 chargeSpell = 0; - uint32 unleashSpell = 0; - - switch (urand(0,2)) - { - case 0: - chargeSpell = SPELL_SOUL_CHARGE_RED; - unleashSpell = SPELL_UNLEASH_SOUL_RED; - break; - case 1: - chargeSpell = SPELL_SOUL_CHARGE_YELLOW; - unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; - break; - case 2: - chargeSpell = SPELL_SOUL_CHARGE_GREEN; - unleashSpell = SPELL_UNLEASH_SOUL_GREEN; - break; - } - - if (me->HasAura(chargeSpell)) - { - me->RemoveAuraFromStack(chargeSpell); - DoCast(me->getVictim(), unleashSpell); - HasCast = true; - SoulChargeCount--; - } - - if (HasCast) - SoulChargeTimer = urand(2000,30000); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - { - if (pInstance) - { - // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. - if ((pInstance->GetData(DATA_AZGALOREVENT) < DONE) && ((me->GetVisibility() != VISIBILITY_OFF) || (me->getFaction() != 35))) - { - me->SetVisibility(VISIBILITY_OFF); - me->setFaction(35); - } - else if ((pInstance->GetData(DATA_AZGALOREVENT) >= DONE) && ((me->GetVisibility() != VISIBILITY_ON) || (me->getFaction() == 35))) - { - me->setFaction(1720); - me->SetVisibility(VISIBILITY_ON); - } - } - - if (DrainNordrassilTimer <= diff) - { - if (!IsChanneling) - { - Creature *temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 1200000); - - if (temp) - WorldTreeGUID = temp->GetGUID(); - - if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Nordrassil->SetDisplayId(11686); - DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); - IsChanneling = true; - } - } - - if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); - DrainNordrassilTimer = 1000; - } - } else DrainNordrassilTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !BelowTenPercent && !Enraged) - BelowTenPercent = true; - - if (!Enraged) - { - if (EnrageTimer <= diff) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) > 10) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - DoScriptText(SAY_ENRAGE, me); - } - } else EnrageTimer -= diff; - - if (CheckDistanceTimer <= diff) - { - // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature - Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000); - if (Check) - { - Check->SetVisibility(VISIBILITY_OFF); - - if (me->IsWithinDistInMap(Check, 75)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - DoScriptText(SAY_ENRAGE, me); - } - } - CheckDistanceTimer = 5000; - } else CheckDistanceTimer -= diff; - } - - if (BelowTenPercent) - { - if (!HasProtected) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - - //all members of raid must get this buff - DoCast(me->getVictim(), SPELL_PROTECTION_OF_ELUNE); - HasProtected = true; - Enraged = true; - } - - if (SummonWispTimer <= diff) - { - DoSpawnCreature(CREATURE_ANCIENT_WISP, rand()%40, rand()%40, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - SummonWispTimer = 1500; - ++WispCount; - } else SummonWispTimer -= diff; - - if (WispCount >= 30) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (Enraged) - { - if (HandOfDeathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HAND_OF_DEATH); - HandOfDeathTimer = 2000; - } else HandOfDeathTimer -= diff; - return; // Don't do anything after this point. - } - - if (SoulChargeCount) - { - if (SoulChargeTimer <= diff) - UnleashSoulCharge(); - else SoulChargeTimer -= diff; - } - - if (GripOfTheLegionTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); - GripOfTheLegionTimer = urand(5000,25000); - } else GripOfTheLegionTimer -= diff; - - if (AirBurstTimer <= diff) - { - if (urand(0,1)) - DoScriptText(SAY_AIR_BURST1, me); - else - DoScriptText(SAY_AIR_BURST2, me); - - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank - AirBurstTimer = urand(25000,40000); - } else AirBurstTimer -= diff; - - if (FearTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - FearTimer = 42000; - } else FearTimer -= diff; - - if (DoomfireTimer <= diff) - { - if (urand(0,1)) - DoScriptText(SAY_DOOMFIRE1, me); - else - DoScriptText(SAY_DOOMFIRE2, me); - - Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!temp) - temp = me->getVictim(); - - //replace with spell cast 31903 once implicitTarget 73 implemented - SummonDoomfire(temp); - - //supposedly three doomfire can be up at the same time - DoomfireTimer = 20000; - } else DoomfireTimer -= diff; - - if (MeleeRangeCheckTimer <= diff) - { - if (CanUseFingerOfDeath()) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); - MeleeRangeCheckTimer = 1000; - } - - MeleeRangeCheckTimer = 5000; - } else MeleeRangeCheckTimer -= diff; - - DoMeleeAttackIfReady(); - } - void WaypointReached(uint32 /*i*/){} -}; - -CreatureAI* GetAI_boss_archimonde(Creature* pCreature) -{ - return new boss_archimondeAI (pCreature); -} - -CreatureAI* GetAI_mob_doomfire(Creature* pCreature) -{ - return new mob_doomfireAI(pCreature); -} - -CreatureAI* GetAI_mob_doomfire_targetting(Creature* pCreature) -{ - return new mob_doomfire_targettingAI(pCreature); -} - -CreatureAI* GetAI_mob_ancient_wisp(Creature* pCreature) -{ - return new mob_ancient_wispAI(pCreature); -} - -void AddSC_boss_archimonde() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_archimonde"; - newscript->GetAI = &GetAI_boss_archimonde; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_doomfire"; - newscript->GetAI = &GetAI_mob_doomfire; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_doomfire_targetting"; - newscript->GetAI = &GetAI_mob_doomfire_targetting; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ancient_wisp"; - newscript->GetAI = &GetAI_mob_ancient_wisp; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp deleted file mode 100644 index 69e37f7f740..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp +++ /dev/null @@ -1,285 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_RAIN_OF_FIRE 31340 -#define SPELL_DOOM 31347 -#define SPELL_HOWL_OF_AZGALOR 31344 -#define SPELL_CLEAVE 31345 -#define SPELL_BERSERK 26662 - -#define SAY_ONDEATH "Your time is almost... up" -#define SOUND_ONDEATH 11002 - -#define SAY_ONSLAY1 "Reesh, hokta!" -#define SAY_ONSLAY2 "Don't fight it" -#define SAY_ONSLAY3 "No one is going to save you" -#define SOUND_ONSLAY1 11001 -#define SOUND_ONSLAY2 11048 -#define SOUND_ONSLAY3 11047 - -#define SAY_DOOM1 "Just a taste... of what awaits you" -#define SAY_DOOM2 "Suffer you despicable insect!" -#define SOUND_DOOM1 11046 -#define SOUND_DOOM2 11000 - -#define SAY_ONAGGRO "Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!" -#define SOUND_ONAGGRO 10999 - -struct boss_azgalorAI : public hyjal_trashAI -{ - boss_azgalorAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_HOWL_OF_AZGALOR); - if (TempSpell) - TempSpell->EffectRadiusIndex[0] = 12;//100yards instead of 50000?! - } - - uint32 RainTimer; - uint32 DoomTimer; - uint32 HowlTimer; - uint32 CleaveTimer; - uint32 EnrageTimer; - bool enraged; - - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - RainTimer = 20000; - DoomTimer = 50000; - HowlTimer = 30000; - CleaveTimer = 10000; - EnrageTimer = 600000; - enraged = false; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 5492.91, -2404.61, 1462.63); - AddWaypoint(1, 5531.76, -2460.87, 1469.55); - AddWaypoint(2, 5554.58, -2514.66, 1476.12); - AddWaypoint(3, 5554.16, -2567.23, 1479.90); - AddWaypoint(4, 5540.67, -2625.99, 1480.89); - AddWaypoint(5, 5508.16, -2659.2, 1480.15); - AddWaypoint(6, 5489.62, -2704.05, 1482.18); - AddWaypoint(7, 5457.04, -2726.26, 1485.10); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (RainTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,30,true), SPELL_RAIN_OF_FIRE); - RainTimer = 20000+rand()%15000; - } else RainTimer -= diff; - - if (DoomTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,100,true), SPELL_DOOM);//never on tank - DoomTimer = 45000+rand()%5000; - } else DoomTimer -= diff; - - if (HowlTimer <= diff) - { - DoCast(me, SPELL_HOWL_OF_AZGALOR); - HowlTimer = 30000; - } else HowlTimer -= diff; - - if (CleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - CleaveTimer = 10000+rand()%5000; - } else CleaveTimer -= diff; - - if (EnrageTimer < diff && !enraged) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_BERSERK, true); - enraged = true; - EnrageTimer = 600000; - } else EnrageTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_azgalor(Creature* pCreature) -{ - return new boss_azgalorAI (pCreature); -} - -#define SPELL_THRASH 12787 -#define SPELL_CRIPPLE 31406 -#define SPELL_WARSTOMP 31408 - -struct mob_lesser_doomguardAI : public hyjal_trashAI -{ - mob_lesser_doomguardAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - AzgalorGUID = pInstance->GetData64(DATA_AZGALOR); - } - - uint32 CrippleTimer; - uint32 WarstompTimer; - uint32 CheckTimer; - uint64 AzgalorGUID; - ScriptedInstance* pInstance; - - void Reset() - { - CrippleTimer = 50000; - WarstompTimer = 10000; - DoCast(me, SPELL_THRASH); - CheckTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - } - - void WaypointReached(uint32 /*i*/) - { - } - - void MoveInLineOfSight(Unit *who) - { - if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) - AttackStart(who); - } - - void JustDied(Unit * /*victim*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (AzgalorGUID) - { - Creature* boss = Unit::GetCreature((*me),AzgalorGUID); - if (!boss || (boss && boss->isDead())) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (WarstompTimer <= diff) - { - DoCast(me, SPELL_WARSTOMP); - WarstompTimer = 10000+rand()%5000; - } else WarstompTimer -= diff; - - if (CrippleTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_CRIPPLE); - CrippleTimer = 25000+rand()%5000; - } else CrippleTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_lesser_doomguard(Creature* pCreature) -{ - return new mob_lesser_doomguardAI (pCreature); -} - -void AddSC_boss_azgalor() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_azgalor"; - newscript->GetAI = &GetAI_boss_azgalor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lesser_doomguard"; - newscript->GetAI = &GetAI_mob_lesser_doomguard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp deleted file mode 100644 index b52d22842e3..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp +++ /dev/null @@ -1,197 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_CLEAVE 31436 -#define SPELL_WARSTOMP 31480 -#define SPELL_MARK 31447 - -#define SOUND_ONDEATH 11018 - -#define SAY_ONSLAY1 "Shaza-Kiel!" -#define SAY_ONSLAY2 "You... are nothing!" -#define SAY_ONSLAY3 "Miserable nuisance!" -#define SOUND_ONSLAY1 11017 -#define SOUND_ONSLAY2 11053 -#define SOUND_ONSLAY3 11054 - -#define SAY_MARK1 "Your death will be a painful one." -#define SAY_MARK2 "You... are marked." -#define SOUND_MARK1 11016 -#define SOUND_MARK2 11052 - -#define SAY_ONAGGRO "Cry for mercy! Your meaningless lives will soon be forfeit." -#define SOUND_ONAGGRO 11015 - -struct boss_kazrogalAI : public hyjal_trashAI -{ - boss_kazrogalAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_MARK); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) - { - TempSpell->EffectImplicitTargetA[0] = 1; - TempSpell->EffectImplicitTargetB[0] = 0; - } - } - - uint32 CleaveTimer; - uint32 WarStompTimer; - uint32 MarkTimer; - uint32 MarkTimerBase; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - CleaveTimer = 5000; - WarStompTimer = 15000; - MarkTimer = 45000; - MarkTimerBase = 45000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 5492.91, -2404.61, 1462.63); - AddWaypoint(1, 5531.76, -2460.87, 1469.55); - AddWaypoint(2, 5554.58, -2514.66, 1476.12); - AddWaypoint(3, 5554.16, -2567.23, 1479.90); - AddWaypoint(4, 5540.67, -2625.99, 1480.89); - AddWaypoint(5, 5508.16, -2659.2, 1480.15); - AddWaypoint(6, 5489.62, -2704.05, 1482.18); - AddWaypoint(7, 5457.04, -2726.26, 1485.10); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (CleaveTimer <= diff) - { - DoCast(me, SPELL_CLEAVE); - CleaveTimer = 6000+rand()%15000; - } else CleaveTimer -= diff; - - if (WarStompTimer <= diff) - { - DoCast(me, SPELL_WARSTOMP); - WarStompTimer = 60000; - } else WarStompTimer -= diff; - - if (me->HasAura(SPELL_MARK)) - me->RemoveAurasDueToSpell(SPELL_MARK); - if (MarkTimer <= diff) - { - //cast dummy, useful for bos addons - me->CastCustomSpell(me, SPELL_MARK, NULL, NULL, NULL, false, NULL, NULL, me->GetGUID()); - - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->getPowerType() == POWER_MANA) - { - pTarget->CastSpell(pTarget, SPELL_MARK,true);//only cast on mana users - } - } - MarkTimerBase -= 5000; - if (MarkTimerBase < 5500) - MarkTimerBase = 5500; - MarkTimer = MarkTimerBase; - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_MARK1); - me->MonsterYell(SAY_MARK1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_MARK2); - me->MonsterYell(SAY_MARK2, LANG_UNIVERSAL, NULL); - break; - } - } else MarkTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kazrogal(Creature* pCreature) -{ - return new boss_kazrogalAI (pCreature); -} - -void AddSC_boss_kazrogal() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kazrogal"; - newscript->GetAI = &GetAI_boss_kazrogal; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp deleted file mode 100644 index 7465b997117..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp +++ /dev/null @@ -1,192 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_FROST_ARMOR 31256 -#define SPELL_DEATH_AND_DECAY 31258 - -#define SPELL_FROST_NOVA 31250 -#define SPELL_ICEBOLT 31249 - -#define SAY_ONDEATH "You have won this battle, but not... the... war" -#define SOUND_ONDEATH 11026 - -#define SAY_ONSLAY1 "All life must perish!" -#define SAY_ONSLAY2 "Victory to the Legion!" -#define SOUND_ONSLAY1 11025 -#define SOUND_ONSLAY2 11057 - -#define SAY_DECAY1 "Crumble and rot!" -#define SAY_DECAY2 "Ashes to ashes, dust to dust" -#define SOUND_DECAY1 11023 -#define SOUND_DECAY2 11055 - -#define SAY_NOVA1 "Succumb to the icy chill... of death!" -#define SAY_NOVA2 "It will be much colder in your grave" -#define SOUND_NOVA1 11024 -#define SOUND_NOVA2 11058 - -#define SAY_ONAGGRO "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!" -#define SOUND_ONAGGRO 11022 - -struct boss_rage_winterchillAI : public hyjal_trashAI -{ - boss_rage_winterchillAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - } - - uint32 FrostArmorTimer; - uint32 DecayTimer; - uint32 NovaTimer; - uint32 IceboltTimer; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - FrostArmorTimer = 37000; - DecayTimer = 45000; - NovaTimer = 15000; - IceboltTimer = 10000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0f); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, NULL); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 4896.08, -1576.35, 1333.65); - AddWaypoint(1, 4898.68, -1615.02, 1329.48); - AddWaypoint(2, 4907.12, -1667.08, 1321.00); - AddWaypoint(3, 4963.18, -1699.35, 1340.51); - AddWaypoint(4, 4989.16, -1716.67, 1335.74); - AddWaypoint(5, 5026.27, -1736.89, 1323.02); - AddWaypoint(6, 5037.77, -1770.56, 1324.36); - AddWaypoint(7, 5067.23, -1789.95, 1321.17); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (FrostArmorTimer <= diff) - { - DoCast(me, SPELL_FROST_ARMOR); - FrostArmorTimer = 40000+rand()%20000; - } else FrostArmorTimer -= diff; - if (DecayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_DEATH_AND_DECAY); - DecayTimer = 60000+rand()%20000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_DECAY1); - me->MonsterYell(SAY_DECAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_DECAY2); - me->MonsterYell(SAY_DECAY2, LANG_UNIVERSAL, NULL); - break; - } - } else DecayTimer -= diff; - if (NovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_NOVA); - NovaTimer = 30000+rand()%15000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_NOVA1); - me->MonsterYell(SAY_NOVA1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_NOVA2); - me->MonsterYell(SAY_NOVA2, LANG_UNIVERSAL, NULL); - break; - } - } else NovaTimer -= diff; - if (IceboltTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,40,true), SPELL_ICEBOLT); - IceboltTimer = 11000+rand()%20000; - } else IceboltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_rage_winterchill(Creature* pCreature) -{ - return new boss_rage_winterchillAI (pCreature); -} - -void AddSC_boss_rage_winterchill() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_rage_winterchill"; - newscript->GetAI = &GetAI_boss_rage_winterchill; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp deleted file mode 100644 index 16a050939cc..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.cpp +++ /dev/null @@ -1,247 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Hyjal -SD%Complete: 80 -SDComment: gossip text id's unknown -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -/* ContentData -npc_jaina_proudmoore -npc_thrall -npc_tyrande_whisperwind -EndContentData */ - -#include "ScriptedPch.h" -#include "hyjalAI.h" - -#define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore." -#define GOSSIP_ITEM_ANETHERON "We are ready for whatever Archimonde might send our way, Lady Proudmoore." - -#define GOSSIP_ITEM_BEGIN_HORDE "I am with you, Thrall." -#define GOSSIP_ITEM_AZGALOR "We have nothing to fear." - -#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!" - -#define GOSSIP_ITEM_TYRANDE "Aid us in defending Nordrassil" -#define ITEM_TEAR_OF_GODDESS 24494 - -#define GOSSIP_ITEM_GM1 "[GM] Toggle Debug Timers" - -CreatureAI* GetAI_npc_jaina_proudmoore(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - - ai->Reset(); - ai->EnterEvadeMode(); - - ai->Spell[0].SpellId = SPELL_BLIZZARD; - ai->Spell[0].Cooldown = 15000 + rand()%20000; - ai->Spell[0].TargetType = TARGETTYPE_RANDOM; - - ai->Spell[1].SpellId = SPELL_PYROBLAST; - ai->Spell[1].Cooldown = 5500 + rand()%4000; - ai->Spell[1].TargetType = TARGETTYPE_RANDOM; - - ai->Spell[2].SpellId = SPELL_SUMMON_ELEMENTALS; - ai->Spell[2].Cooldown = 15000 + rand()%30000; - ai->Spell[2].TargetType = TARGETTYPE_SELF; - - return ai; -} - -bool GossipHello_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - if (ai->EventBegun) - return false; - - uint32 RageEncounter = ai->GetInstanceData(DATA_RAGEWINTERCHILLEVENT); - uint32 AnetheronEncounter = ai->GetInstanceData(DATA_ANETHERONEVENT); - if (RageEncounter == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - else if (RageEncounter == DONE && AnetheronEncounter == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - else if (RageEncounter == DONE && AnetheronEncounter == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - - if (pPlayer->isGameMaster()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - ai->FirstBossDead = true; - ai->WaveCount = 9; - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - ai->Retreat(); - break; - case GOSSIP_ACTION_INFO_DEF: - ai->Debug = !ai->Debug; - debug_log("TSCR: HyjalAI - Debug mode has been toggled"); - break; - } - return true; -} - -CreatureAI* GetAI_npc_thrall(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - - ai->Reset(); - ai->EnterEvadeMode(); - - ai->Spell[0].SpellId = SPELL_CHAIN_LIGHTNING; - ai->Spell[0].Cooldown = 3000 + rand()%5000; - ai->Spell[0].TargetType = TARGETTYPE_VICTIM; - - ai->Spell[1].SpellId = SPELL_SUMMON_DIRE_WOLF; - ai->Spell[1].Cooldown = 6000 + rand()%35000; - ai->Spell[1].TargetType = TARGETTYPE_RANDOM; - - return ai; -} - -bool GossipHello_npc_thrall(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - if (ai->EventBegun) - return false; - - uint32 AnetheronEvent = ai->GetInstanceData(DATA_ANETHERONEVENT); - // Only let them start the Horde phases if Anetheron is dead. - if (AnetheronEvent == DONE && ai->GetInstanceData(DATA_ALLIANCE_RETREAT)) - { - uint32 KazrogalEvent = ai->GetInstanceData(DATA_KAZROGALEVENT); - uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); - if (KazrogalEvent == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - else if (KazrogalEvent == DONE && AzgalorEvent == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - else if (AzgalorEvent == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - } - - if (pPlayer->isGameMaster()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_thrall(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - ai->DeSpawnVeins();//despawn the alliance veins - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - ai->FirstBossDead = true; - ai->WaveCount = 9; - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - ai->Retreat(); - break; - case GOSSIP_ACTION_INFO_DEF: - ai->Debug = !ai->Debug; - debug_log("TSCR: HyjalAI - Debug mode has been toggled"); - break; - } - return true; -} - -CreatureAI* GetAI_npc_tyrande_whisperwind(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - ai->Reset(); - ai->EnterEvadeMode(); - return ai; -} - -bool GossipHello_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); - - // Only let them get item if Azgalor is dead. - if (AzgalorEvent == DONE && !pPlayer->HasItemCount(ITEM_TEAR_OF_GODDESS,1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TYRANDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_TEAR_OF_GODDESS, 1); - if (msg == EQUIP_ERR_OK) - { - Item* item = pPlayer->StoreNewItem(dest, ITEM_TEAR_OF_GODDESS, true); - if (item && pPlayer) - pPlayer->SendNewItem(item,1,true,false,true); - } - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - CAST_AI(hyjalAI, pCreature->AI()); - } - return true; -} - -void AddSC_hyjal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_jaina_proudmoore"; - newscript->GetAI = &GetAI_npc_jaina_proudmoore; - newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore; - newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thrall"; - newscript->GetAI = &GetAI_npc_thrall; - newscript->pGossipHello = &GossipHello_npc_thrall; - newscript->pGossipSelect = &GossipSelect_npc_thrall; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tyrande_whisperwind"; - newscript->pGossipHello = &GossipHello_npc_tyrande_whisperwind; - newscript->pGossipSelect = &GossipSelect_npc_tyrande_whisperwind; - newscript->GetAI = &GetAI_npc_tyrande_whisperwind; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h deleted file mode 100644 index bfc9a54dfd9..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_HYJAL_H -#define DEF_HYJAL_H - -#define ERROR_INST_DATA "TSCR: Instance data not set properly for Mount Hyjal. Encounters will be buggy." - -enum eTypes -{ - WORLD_STATE_WAVES = 2842, - WORLD_STATE_ENEMY = 2453, - WORLD_STATE_ENEMYCOUNT = 2454, - - DATA_ANETHERON = 1, - DATA_ANETHERONEVENT = 2, - DATA_ARCHIMONDE = 3, - DATA_ARCHIMONDEEVENT = 4, - DATA_AZGALOR = 5, - DATA_AZGALOREVENT = 6, - DATA_JAINAPROUDMOORE = 7, - DATA_KAZROGAL = 8, - DATA_KAZROGALEVENT = 9, - DATA_RAGEWINTERCHILL = 10, - DATA_RAGEWINTERCHILLEVENT = 11, - DATA_THRALL = 12, - DATA_TYRANDEWHISPERWIND = 13, - DATA_TRASH = 14, - DATA_RESET_TRASH_COUNT = 15, - DATA_ALLIANCE_RETREAT = 16, - DATA_HORDE_RETREAT = 17, - DATA_RAIDDAMAGE = 18, - DATA_RESET_RAIDDAMAGE = 19, - TYPE_RETREAT = 20 -}; -#endif - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp deleted file mode 100644 index 3c12b54f3f4..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.cpp +++ /dev/null @@ -1,1157 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: HyjalAI -SD%Complete: 90 -SDComment: -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjalAI.h" -#include "hyjal_trash.h" -#include "MapManager.h" -#include "Language.h" -#include "Chat.h" -#include "Object.h" - -#define SPAWN_GARG_GATE 0 -#define SPAWN_WYRM_GATE 1 -#define SPAWN_NEAR_TOWER 2 - -#define YELL_HURRY "Hurry, we don't have much time" - -// Locations for summoning gargoyls and frost wyrms in special cases -float SpawnPointSpecial[3][3]= -{ - {5497.08, -2493.23, 1535.72}, //spawn point for the gargoyles near the horde gate - {5624.53, -2548.12, 1551.54}, //spawn point for the frost wyrm near the horde gate - {5604.41, -2811.98, 1547.77} //spawn point for the gargoyles and wyrms near the horde tower -}; - -// Locations for summoning waves in Alliance base -float AllianceBase[4][3]= -{ - {4928.48, -1526.38, 1326.83}, - {4923.54, -1514.29, 1327.98}, - {4928.41, -1510.35, 1327.99}, - {4938.35, -1521.00, 1326.69} -}; - -float JainaDummySpawn[2][4]= -{ - {5497.01, -2719.03, 1483.08, 2.90426}, - {5484.98, -2721.69, 1483.39, 6.00656} -}; - -// Locations for summoning waves in Horde base -float HordeBase[4][3]= -{ - {5458.01, -2340.27, 1459.60}, - {5466.01, -2334.69, 1460.06}, - {5468.45, -2355.13, 1459.99}, - {5479.06, -2344.16, 1461.74} -}; - -// Lady Jaina's waypoints when retreathing -float JainaWPs[2][3]= -{ - {5078.56, -1789.79, 1320.73},//next to the small stairs - {5037.38, -1778.39, 1322.61},//center of alliance base -}; - -float InfernalPos[8][3]=//spawn points for the infernals in the horde base -{ - {5453.59, -2764.52, 1493.50}, - {5478.4, -2781.77, 1497.52}, - {5506.09, -2780.53, 1496.32}, - {5532.1, -2763.42, 1492.37}, - {5544.16, -2733.99, 1487.14}, - {5536.19, -2708.18, 1480.01}, - {5510.16, -2691.75, 1479.66}, - {5482.39, -2689.19, 1481.09} -}; - -float InfernalSPWP[26][4]=//spawn points for the infernals in the horde base used in the cleaning wave -{ - {5490.96, -2718.72, 1482.96, 0.49773}, - {5449.51, -2723.32, 1485.69, 2.69685}, - {5520.83, -2624.68, 1483.82, 1.20459}, - {5558.28, -2629.26, 1485.76, 0.37992}, - {5567.97, -2758.69, 1494.10, 5.04125}, - {5384.90, -2793.47, 1503.90, 5.55412}, - {5495.33, -2814.06, 1501.56, 1.12055}, - {5472.63, -2929.39, 1538.31, 1.95777}, - {5334.72, -2952.29, 1534.34, 0.50869}, - {5398.36, -2872.46, 1512.38, 0.76787}, - {5514.39, -2768.63, 1492.30, 1.55721}, - {5598.91, -2703.75, 1495.64, 2.56644}, - {5467.80, -2655.93, 1482.27, 0.85819}, - {5399.83, -2985.24, 1545.04, 5.92559}, - {5232.13, -2967.05, 1553.09, 5.41351}, - {5272.02, -3082.52, 1567.09, 3.40681}, - {5343.26, -3120.71, 1582.92, 3.16727}, - {5371.26, -3175.24, 1587.41, 6.10466}, - {5434.67, -3177.91, 1579.25, 2.77850}, - {5237.39, -3149.25, 1593.59, 0.83855}, - {5202.15, -3016.64, 1566.28, 3.31256}, - {5302.54, -2914.37, 1528.53, 3.37146}, - {5439.04, -2834.81, 1508.80, 2.14231}, - {5421.33, -2771.04, 1494.28, 6.06223}, - {5549.76, -2692.93, 1482.68, 2.19414}, - {5459.78, -2755.71, 1490.68, 1.05139} -}; - -float VeinPos[14][8]=//spawn points of the ancient gem veins -{ - {5184.84, -1982.59, 1382.66, 2.58079, 0, 0, 0.960944, 0.276742}, //alliance - {5107.66, -2071.16, 1368.37, 2.65148, 0, 0, 0.970124, 0.242611}, //alliance - {5040.53, -2227.65, 1403.17, 3.35049, 0, 0, 0.99455, -0.104257}, //alliance - {5187.59, -2453.12, 1455.51, 5.87943, 0, 0, 0.20051, -0.979692}, //alliance - {5429.43, -2340.65, 1465.38, 4.7681, 0, 0, 0.687138, -0.726527}, //alliance - {5463.99, -2315.95, 1470.29, 1.52045, 0, 0, 0.689084, 0.724682}, //alliance - {5624.65, -2495.09, 1510.11, 0.0124869, 0, 0, 0.00624342, 0.999981}, //alliance - {5285.41, -3348.32, 1663.01, 1.57152, 0, 0, 0.707362, 0.706852}, //horde - {5417.69, -3372.52, 1656.31, 0.361993, 0, 0, 0.18001, 0.983665}, //horde - {5315.34, -3238.32, 1622.88, 3.03627, 0, 0, 0.998614, 0.0526347}, //horde - {5303.4, -3096.44, 1596.41, 1.72073, 0, 0, 0.758081, 0.65216}, //horde - {5265.13, -3177.27, 1616.22, 0.813604, 0, 0, 0.395674, 0.918391}, //horde - {5374.3, -3420.59, 1653.43, 1.45762, 0, 0, 0.665981, 0.745969}, //horde - {5441.54, -3321.59, 1651.55, 0.258306, 0, 0, 0.128794, 0.991671} //horde -}; - -float AllianceOverrunGargPos[5][4]=//gargoyle spawn points in the alliance overrun -{ - {5279.94, -2049.68, 1311.38, 0},//garg1 - {5289.15, -2219.06, 1291.12, 0},//garg2 - {5202.07, -2136.10, 1305.07, 2.8},//garg3 - {5071.52, -2425.63, 1454.48, 5.54},//garg4 - {5120.65, -2467.92, 1463.93, 2.54}//garg5 -}; - -float AllianceFirePos[92][8]=//spawn points for the fire visuals (GO) in the alliance base -{ - {5039.9, -1796.84, 1323.88, 2.59222, 0, 0, 0.962511, 0.271243}, - {5087.2, -1795.2, 1320.68, 1.03946, 0, 0, 0.496644, 0.867954}, - {5112.68, -1806.66, 1359.93, 1.37799, 0, 0, 0.63576, 0.771887}, - {5095.61, -1793.27, 1359.78, 0.580806, 0, 0, 0.286338, 0.958129}, - {5090.43, -1784.45, 1360.44, 0.796784, 0, 0, 0.387937, 0.921686}, - {5139.25, -1783.11, 1359.39, 3.30849, 0, 0, 0.99652, -0.0833509}, - {5112.16, -1763.72, 1361.35, 5.10312, 0, 0, 0.556388, -0.830922}, - {4981.18, -1793.98, 1335.7, 3.23072, 0, 0, 0.999007, -0.0445498}, - {4996.57, -1766.75, 1341.62, 3.5331, 0, 0, 0.980902, -0.194505}, - {4983.74, -1769.25, 1345.75, 3.79228, 0, 0, 0.947541, -0.319635}, - {4996.01, -1774.43, 1330.71, 3.07364, 0, 0, 0.999423, 0.0339693}, - {5094.2, -1726.13, 1330.55, 1.56175, 0, 0, 0.703901, 0.710298}, - {5079.82, -1721.24, 1336.26, 1.18868, 0, 0, 0.559964, 0.828517}, - {5077.68, -1717.15, 1327.78, 0.0145145, 0, 0, 0.00725717, 0.999974}, - {5122.27, -1738.22, 1341.67, 0.835256, 0, 0, 0.405593, 0.914054}, - {5131.88, -1741.15, 1335.25, 2.15472, 0, 0, 0.880712, 0.473653}, - {5196.93, -1772.99, 1345.2, 0.128397, 0, 0, 0.0641544, 0.99794}, - {5225.33, -1756.06, 1344.17, 3.04223, 0, 0, 0.998766, 0.0496599}, - {5224.84, -1767.05, 1360.06, 3.19538, 0, 0, 0.999638, -0.0268922}, - {5202.05, -1763.47, 1361.68, 2.59455, 0, 0, 0.962826, 0.270122}, - {5194.74, -1766.66, 1356.94, 0.0734191, 0, 0, 0.0367013, 0.999326}, - {5159.67, -1832.97, 1344.5, 5.17457, 0, 0, 0.526356, -0.850264}, - {5096.17, -1858.73, 1332.46, 5.30021, 0, 0, 0.471939, -0.881631}, - {5110.7, -1856.59, 1342.84, 5.97564, 0, 0, 0.153167, -0.9882}, - {5109.76, -1855.3, 1332.38, 4.89572, 0, 0, 0.639411, -0.768865}, - {5068.95, -1837.37, 1328.81, 2.61569, 0, 0, 0.965628, 0.25993}, - {5064.4, -1824.77, 1329.02, 2.16409, 0, 0, 0.88292, 0.469524}, - {5059.89, -1848.79, 1329.59, 0.0709955, 0, 0, 0.0354903, 0.99937}, - {5014.37, -1851.39, 1322.56, 4.66949, 0, 0, 0.722111, -0.691777}, - {5025.1, -1848.27, 1323.39, 4.44565, 0, 0, 0.794854, -0.606801}, - {4942.63, -1890.13, 1326.59, 3.28719, 0, 0, 0.997351, -0.0727343}, - {4937.95, -1888.71, 1352.41, 3.41678, 0, 0, 0.990549, -0.13716}, - {4922.48, -1881.92, 1352.41, 5.03077, 0, 0, 0.586075, -0.810257}, - {4915.35, -1894.32, 1351.24, 6.22457, 0, 0, 0.0293048, -0.999571}, - {4922.71, -1904.84, 1352.56, 1.37866, 0, 0, 0.63602, 0.771672}, - {4932.89, -1905.49, 1352.56, 1.89702, 0, 0, 0.812549, 0.582893}, - {5011.83, -1861.05, 1345.86, 4.43777, 0, 0, 0.797239, -0.603664}, - {5011.83, -1861.05, 1363.26, 4.748, 0, 0, 0.694406, -0.719583}, - {5021.46, -1858.35, 1342.17, 4.86188, 0, 0, 0.652329, -0.757936}, - {4995.02, -1698.3, 1370.38, 6.15779, 0, 0, 0.0626579, -0.998035}, - {5119.85, -1728.9, 1336.04, 5.87112, 0, 0, 0.204579, -0.97885}, - {5214.75, -1751.02, 1342.5, 5.08965, 0, 0, 0.561972, -0.827156}, - {5075.04, -1822.43, 1328.87, 3.99951, 0, 0, 0.9094, -0.415924}, - {5057.09, -1823.32, 1350.35, 3.88169, 0, 0, 0.93231, -0.361659}, - {4984.6, -1816.99, 1329.21, 3.05308, 0, 0, 0.999021, 0.0442417}, - {4983.35, -1811.55, 1356.82, 3.33975, 0, 0, 0.995096, -0.098917}, - {4984.11, -1825.73, 1350.76, 2.26375, 0, 0, 0.905211, 0.424962}, - {4968.47, -1786.46, 1354.09, 3.07663, 0, 0, 0.999473, 0.0324733}, - {5061.82, -1751.16, 1339.07, 5.94727, 0, 0, 0.167171, -0.985928}, - {5063.75, -1763, 1351.91, 0.759707, 0, 0, 0.370784, 0.928719}, - {5078.65, -1708.26, 1353.9, 1.27022, 0, 0, 0.593264, 0.805008}, - {4983.19, -1755.96, 1331.13, 4.28221, 0, 0, 0.841733, -0.539894}, - {4972.76, -1755.3, 1332.5, 4.21938, 0, 0, 0.858276, -0.513188}, - {4961.65, -1760.82, 1351.69, 3.56515, 0, 0, 0.977659, -0.210198}, - {5086.45, -1779.83, 1321.62, 6.23157, 0, 0, 0.0258051, -0.999667}, - {5063.15, -1756.74, 1328.56, 0.886926, 0, 0, 0.42907, 0.903271}, - {5042.45, -1800.61, 1323.88, 2.50093, 0, 0, 0.949131, 0.31488}, - {5084.74, -1725.35, 1327.89, 1.65034, 0, 0, 0.734663, 0.678432}, - {4993.25, -1758.1, 1331.07, 3.49995, 0, 0, 0.98399, -0.178223}, - {5078.53, -1867.85, 1348.91, 5.85612, 0, 0, 0.211913, -0.977288}, - {5080.74, -1869.73, 1333.18, 6.18206, 0, 0, 0.0505424, -0.998722}, - {5089.55, -1894.13, 1356.08, 1.52072, 0, 0, 0.689181, 0.724589}, - {5113.24, -1899.49, 1363.77, 1.50108, 0, 0, 0.682034, 0.731321}, - {4984.18, -1907.69, 1325.62, 3.82193, 0, 0, 0.942698, -0.333646}, - {5094.14, -2432.08, 1429.38, 4.70083, 0, 0, 0.711182, -0.703007}, - {5329.89, -2113.30, 1281.06, 5.60560, 0, 0, 0.332347, -0.943157}, - {5170.87, -2148.13, 1278.32, 1.63540, 0, 0, 0.729573, 0.683903 }, - {5132.94, -1960.25, 1367.8, 3.69787, 0, 0, 0.961568, -0.274566}, - {5280.82, -2351.55, 1431.57, 4.46913, 0, 0, 0.787677, -0.616088}, - {5176.78, -2121.43, 1295.27, 3.24153, 0, 0, 0.998752, -0.04995}, - {5332.75, -2101.41, 1296.37, 5.50350, 0, 0, 0.380043, -0.924969}, - {5265.70, -2050.27, 1287.57, 0.50051, 0, 0, 0.247655, 0.968848 }, - {5194.21, -2129.89, 1274.04, 3.08053, 0, 0, 0.999534, 0.0305272}, - {5225.81, -1985.50, 1364.15, 0.37247, 0, 0, 0.185163, 0.982708 }, - {5339.46, -2204.47, 1280.45, 0.99921, 0, 0, 0.479081, 0.877771 }, - {5269.63, -2020.57, 1299.62, 3.00201, 0, 0, 0.997566, 0.0697332}, - {5111.54, -2445.70, 1435.31, 2.70983, 0, 0, 0.976788, 0.214207 }, - {5111.24, -1901.14, 1355.33, 1.61028, 0, 0, 0.720929, 0.693009 }, - {5310.42, -2207.82, 1277.46, 0.50441, 0, 0, 0.249544, 0.968363 }, - {5150.81, -2042.13, 1394.3, 2.21031, 0, 0, 0.893534, 0.448995 }, - {5224.84, -2376.61, 1366.33, 5.0621, 0, 0, 0.573311, -0.819338}, - {5105.41, -2454.86, 1446.16, 4.64584, 0, 0, 0.730239, -0.683191}, - {5309.65, -2188.28, 1266.84, 5.56631, 0, 0, 0.350811, -0.936446}, - {5281.46, -2047.82, 1287.67, 2.44909, 0, 0, 0.940652, 0.339373 }, - {5325.45, -2189.41, 1309.6, 6.23783, 0, 0, 0.0226771, -0.999743}, - {5190.96, -2142.54, 1293.03, 6.25668, 0, 0, 0.0132544, -0.999912}, - {5089.99, -2467.49, 1441.8, 0.77381, 0, 0, 0.377326, 0.92608 }, - {5195.08, -2129.01, 1285.36, 3.55727, 0, 0, 0.978480, -0.206344}, - {5353.76, -2116.28, 1299.27, 6.17894, 0, 0, 0.0521006, -0.998642}, - {5271.14, -2037.38, 1299.24, 4.07879, 0, 0, 0.892201, -0.451638}, - {5332.5 , -2181.28, 1279.95, 4.6906, 0, 0, 0.714768, -0.699362}, - {5108.2 , -2429.84, 1427.73, 4.5194, 0, 0, 0.771943, -0.635691} -}; - -float HordeFirePos[65][8]=//spawn points for the fire visuals (GO) in the horde base -{ - {5524.11, -2612.73, 1483.38, 1.96198, 0, 0, 0.831047, 0.556202}, - {5514.42, -2617.19, 1505.77, 1.82453, 0, 0, 0.790892, 0.611956}, - {5510.21, -2624.77, 1485.34, 1.71065, 0, 0, 0.754783, 0.655974}, - {5570.72, -2619.04, 1487.62, 0.728898, 0, 0, 0.356435, 0.93432}, - {5570.29, -2639.37, 1487.31, 1.49308, 0, 0, 0.679104, 0.734042}, - {5583.56, -2637.2, 1503.78, 1.46559, 0, 0, 0.668951, 0.743307}, - {5571.53, -2626.81, 1510.99, 0.362107, 0, 0, 0.180066, 0.983654}, - {5545.97, -2659.62, 1489.64, 5.07055, 0, 0, 0.569845, -0.821752}, - {5557.44, -2675.91, 1482.58, 1.70118, 0, 0, 0.751671, 0.659539}, - {5594.98, -2742.31, 1495.51, 4.5993, 0, 0, 0.74594, -0.666013}, - {5599.65, -2755.6, 1505.05, 1.66896, 0, 0, 0.740947, 0.671564}, - {5565.95, -2774.75, 1499.48, 6.22425, 0, 0, 0.0294611, -0.999566}, - {5567.1, -2769.7, 1511.17, 5.99257, 0, 0, 0.144799, -0.989461}, - {5572.84, -2774.16, 1527.06, 0.836428, 0, 0, 0.406129, 0.913816}, - {5538.32, -2805.94, 1498.87, 4.30082, 0, 0, 0.836674, -0.547701}, - {5515.66, -2801.74, 1503.53, 5.57316, 0, 0, 0.347602, -0.937642}, - {5516.76, -2827.14, 1501.15, 0.35026, 0, 0, 0.174236, 0.984704}, - {5536.13, -2813.51, 1537.21, 4.51681, 0, 0, 0.772765, -0.634692}, - {5525.05, -2825.16, 1538.53, 0.489275, 0, 0, 0.242205, 0.970225}, - {5534.42, -2815.45, 1562.84, 4.62834, 0, 0, 0.736191, -0.676774}, - {5519.64, -2831.12, 1526.46, 0.611008, 0, 0, 0.300774, 0.953696}, - {5551.04, -2827.55, 1523.5, 3.35206, 0, 0, 0.994468, -0.10504}, - {5469.22, -2802.87, 1503.5, 4.99509, 0, 0, 0.600436, -0.799673}, - {5427.8, -2737.26, 1487.12, 1.78673, 0, 0, 0.779186, 0.626793}, - {5454.1, -2709.1, 1485.92, 3.03552, 0, 0, 0.998594, 0.0530137}, - {5436.3, -2718.2, 1506.02, 2.7567, 0, 0, 0.981539, 0.191261}, - {5412.6, -2740.55, 1510.79, 2.98446, 0, 0, 0.996915, 0.0784832}, - {5406.12, -2752.48, 1521.01, 2.05769, 0, 0, 0.856705, 0.515807}, - {5445.24, -2676.35, 1521.89, 2.91378, 0, 0, 0.99352, 0.113661}, - {5481.4, -2665.08, 1482.23, 4.30001, 0, 0, 0.836895, -0.547363}, - {5443.51, -2675.44, 1487.12, 2.90986, 0, 0, 0.993295, 0.115606}, - {5391.72, -2647.3, 1528.9, 3.76987, 0, 0, 0.951063, -0.308997}, - {5421.09, -2734.12, 1521.01, 2.70567, 0, 0, 0.97634, 0.216242}, - {5405.39, -2710.33, 1533.77, 2.51324, 0, 0, 0.951052, 0.309032}, - {5423.96, -2703.76, 1516.34, 2.79206, 0, 0, 0.984767, 0.173879}, - {5444.75, -2735.23, 1486.37, 2.22657, 0, 0, 0.897155, 0.441715}, - {5570.98, -2747.91, 1495.7, 5.14433, 0, 0, 0.53915, -0.84221}, - {5567.79, -2673.9, 1484.66, 2.72529, 0, 0, 0.978415, 0.20665}, - {5600.71, -2696.8, 1500.42, 0.443704, 0, 0, 0.220036, 0.975492}, - {5600.7, -2693.04, 1515.2, 5.16003, 0, 0, 0.532522, -0.846416}, - {5627.56, -2839.66, 1510.53, 5.41527, 0, 0, 0.420463, -0.907309}, - {5622.02, -2868.71, 1516.22, 2.25482, 0, 0, 0.903303, 0.429002}, - {5586.61, -2878.97, 1510.34, 4.55604, 0, 0, 0.76017, -0.649724}, - {5583.78, -2843.71, 1509.54, 5.35715, 0, 0, 0.44665, -0.894709}, - {5580.95, -2811.3, 1513.3, 3.57587, 0, 0, 0.976518, -0.215434}, - {5542.52, -2869.31, 1523.13, 5.23304, 0, 0, 0.501275, -0.865288}, - {5557.35, -2866.36, 1518.76, 4.48299, 0, 0, 0.783388, -0.621533}, - {5380.91, -2849.36, 1512.81, 3.90962, 0, 0, 0.927168, -0.374646}, - {5395.76, -2881.41, 1521.11, 4.28426, 0, 0, 0.84118, -0.540755}, - {5374.87, -2859.63, 1528.98, 3.30252, 0, 0, 0.996765, -0.0803745}, - {5356.07, -2854.66, 1520.34, 5.83933, 0, 0, 0.220108, -0.975475}, - {5363.01, -2975.72, 1539.02, 4.13738, 0, 0, 0.87859, -0.477576}, - {5336.85, -2980.74, 1561.24, 5.11126, 0, 0, 0.553001, -0.83318}, - {5335.23, -2974.62, 1540.05, 5.04451, 0, 0, 0.580496, -0.814263}, - {5422.37, -2998.87, 1549.98, 4.51831, 0, 0, 0.772288, -0.635272}, - {5405.54, -3014.6, 1562.16, 5.86761, 0, 0, 0.206298, -0.978489}, - {5427.96, -3019.4, 1561.58, 3.53498, 0, 0, 0.980718, -0.19543}, - {5348.12, -2977.84, 1582.47, 3.94025, 0, 0, 0.921323, -0.388799}, - {5331.12, -2993.71, 1576.14, 0.0642734, 0, 0, 0.0321311, 0.999484}, - {5321.63, -2986.55, 1552.2, 5.29503, 0, 0, 0.474219, -0.880407}, - {5292.1, -2914.36, 1529.52, 2.9742, 0, 0, 0.996499, 0.083601}, - {5281.77, -2926.5, 1530.62, 1.67829, 0, 0, 0.744071, 0.6681}, - {5287.19, -2909.94, 1543.49, 3.31192, 0, 0, 0.996376, -0.0850591}, - {5534.15, -2679.35, 1483.61, 0.428685, 0, 0, 0.212705, 0.977116}, - {5545.43, -2647.82, 1483.05, 5.38848, 0, 0, 0.432578, -0.901596} -}; - -hyjalAI::hyjalAI(Creature *c) : npc_escortAI(c), Summons(me) -{ - pInstance = c->GetInstanceData(); - VeinsSpawned[0] = false; - VeinsSpawned[1] = false; - for (uint8 i=0; i<14; ++i) - VeinGUID[i] = 0; - InfernalCount = 0; - TeleportTimer = 1000; - Overrun = false; - Teleported = false; - WaitForTeleport = false; - OverrunCounter = 0; - OverrunCounter2 = 0; - InfernalPoint = 0; - RespawnTimer = 10000; - DoRespawn = false; - DoHide = false; - MassTeleportTimer = 0; - DoMassTeleport = false; -} - -void hyjalAI::JustSummoned(Creature *summoned) -{ - Summons.Summon(summoned); -} - -void hyjalAI::SummonedCreatureDespawn(Creature* summoned) -{ - Summons.Despawn(summoned); -} - -void hyjalAI::Reset() -{ - IsDummy = false; - me->setActive(true); - // GUIDs - PlayerGUID = 0; - BossGUID[0] = 0; - BossGUID[1] = 0; - - // Timers - NextWaveTimer = 10000; - CheckTimer = 0; - RetreatTimer = 1000; - - // Misc - WaveCount = 0; - EnemyCount = 0; - - // Set faction properly based on Creature entry - switch(me->GetEntry()) - { - case JAINA: - Faction = 0; - DoCast(me, SPELL_BRILLIANCE_AURA, true); - break; - - case THRALL: - Faction = 1; - break; - - case TYRANDE: - Faction = 2; - break; - } - - //Bools - EventBegun = false; - FirstBossDead = false; - SecondBossDead = false; - Summon = false; - bRetreat = false; - Debug = false; - - //Flags - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - //Initialize spells - memset(Spell, 0, sizeof(Spell)); - - //Reset Instance Data for trash count - if (pInstance) - { - if ((!pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == JAINA) || (pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == THRALL)) - { - //Reset World States - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); - pInstance->SetData(DATA_RESET_TRASH_COUNT, 0); - } - } else error_log(ERROR_INST_DATA); - - //Visibility - DoHide = true; -} - -void hyjalAI::EnterEvadeMode() -{ - if (me->GetEntry() != JAINA) - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->LoadCreaturesAddon(); - - if (me->isAlive()) - me->GetMotionMaster()->MoveTargetedHome(); - - me->SetLootRecipient(NULL); -} - -void hyjalAI::EnterCombat(Unit * /*who*/) -{ - if (IsDummy)return; - for (uint8 i = 0; i < 3; ++i) - if (Spell[i].Cooldown) - SpellTimer[i] = Spell[i].Cooldown; - - Talk(ATTACKED); -} - -void hyjalAI::MoveInLineOfSight(Unit *who) -{ - if (IsDummy) - return; - - npc_escortAI::MoveInLineOfSight(who); -} - -void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) -{ - uint32 random = rand()%4; - float SpawnLoc[3]; - - for (uint8 i = 0; i < 3; ++i) - { - SpawnLoc[i] = Base[random][i]; - } - Creature* pCreature = NULL; - switch(entry) - { - case 17906: //GARGOYLE - - if (!FirstBossDead && (WaveCount == 1 || WaveCount == 3)) - {//summon at tower - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][1]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - if (pCreature) - CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; - }else{//summon at gate - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_GARG_GATE][0]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][1]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - } - break; - case 17907: //FROST_WYRM , - if (FirstBossDead && WaveCount == 1) //summon at gate - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_WYRM_GATE][0],SpawnPointSpecial[SPAWN_WYRM_GATE][1],SpawnPointSpecial[SPAWN_WYRM_GATE][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - else - { - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0], SpawnPointSpecial[SPAWN_NEAR_TOWER][1],SpawnPointSpecial[SPAWN_NEAR_TOWER][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - if (pCreature) - CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; - } - break; - case 17908: //GIANT_INFERNAL - ++InfernalCount; - if (InfernalCount > 7) - InfernalCount = 0; - pCreature = me->SummonCreature(entry, InfernalPos[InfernalCount][0], InfernalPos[InfernalCount][1], InfernalPos[InfernalCount][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - break; - default: - pCreature = me->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - break; - - } - - if (pCreature) - { - // Increment Enemy Count to be used in World States and instance script - ++EnemyCount; - - pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pCreature->setActive(true); - switch(entry) - { - case NECROMANCER: - case ABOMINATION: - case GHOUL: - case BANSHEE: - case CRYPT_FIEND: - case GARGOYLE: - case FROST_WYRM: - case GIANT_INFERNAL: - case FEL_STALKER: - case RAGE_WINTERCHILL: - case ANETHERON: - case KAZROGAL: - case AZGALOR: - CAST_AI(hyjal_trashAI, pCreature->AI())->IsEvent = true; - break; - } - if (pInstance) - { - if (pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE) - pCreature->SetDisableReputationGain(true);//no repu for solo farming - } - // Check if Creature is a boss. - if (pCreature->isWorldBoss()) - { - if (!FirstBossDead) BossGUID[0] = pCreature->GetGUID(); - else BossGUID[1] = pCreature->GetGUID(); - CheckTimer = 5000; - } - } -} - -void hyjalAI::SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]) -{ - // 1 in 4 chance we give a rally yell. Not sure if the chance is offilike. - if (rand()%4 == 0) - Talk(RALLY); - - if (!pInstance) - { - error_log(ERROR_INST_DATA); - return; - } - InfernalCount = 0;//reset infernal count every new wave - - EnemyCount = pInstance->GetData(DATA_TRASH); - for (uint8 i = 0; i < 18; ++i) - { - if (wave[Count].Mob[i]) - SummonCreature(wave[Count].Mob[i], Base); - } - - if (!wave[Count].IsBoss) - { - uint32 stateValue = Count+1; - if (FirstBossDead) - stateValue -= 9; // Subtract 9 from it to give the proper wave number if we are greater than 8 - - // Set world state to our current wave number - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, stateValue); // Set world state to our current wave number - // Enable world state - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); // Enable world state - - pInstance->SetData(DATA_TRASH, EnemyCount); // Send data for instance script to update count - - if (!Debug) - NextWaveTimer = wave[Count].WaveTimer; - else - { - NextWaveTimer = 15000; - debug_log("TSCR: HyjalAI: debug mode is enabled. Next Wave in 15 seconds"); - } - } - else - { - // Set world state for waves to 0 to disable it. - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); - - // Set World State for enemies invading to 1. - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 1); - - Summon = false; - } - CheckTimer = 5000; -} - -void hyjalAI::StartEvent(Player* pPlayer) -{ - if (!pPlayer || IsDummy || !pInstance) - return; - - Talk(BEGIN); - - EventBegun = true; - Summon = true; - - NextWaveTimer = 15000; - CheckTimer = 5000; - PlayerGUID = pPlayer->GetGUID(); - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); - - DeSpawnVeins(); -} - -uint32 hyjalAI::GetInstanceData(uint32 Event) -{ - if (pInstance) - return pInstance->GetData(Event); - else error_log(ERROR_INST_DATA); - - return 0; -} - -void hyjalAI::Talk(uint32 id) -{ - std::list index; - for (uint8 i = 0; i < 9; ++i) - { - if (Faction == 0) // Alliance - { - if (JainaQuotes[i].id == id) - index.push_back(i); - } - else if (Faction == 1) // Horde - { - if (ThrallQuotes[i].id == id) - index.push_back(i); - } - } - - if (index.empty()) - return; // No quotes found, no use to continue - - uint8 ind = *(index.begin()) + rand()%index.size(); - - int32 YellId = 0; - if (Faction == 0) // Alliance - { - YellId = JainaQuotes[ind].textid; - } - else if (Faction == 1) // Horde - { - YellId = ThrallQuotes[ind].textid; - } - - if (YellId) - DoScriptText(YellId, me); -} - -void hyjalAI::Retreat() -{ - if (pInstance) - { - pInstance->SetData(TYPE_RETREAT,SPECIAL); - - if (Faction == 0) - { - pInstance->SetData(DATA_ALLIANCE_RETREAT, 1); - AddWaypoint(0,JainaWPs[0][0],JainaWPs[0][1],JainaWPs[0][2]); - AddWaypoint(1,JainaWPs[1][0],JainaWPs[1][1],JainaWPs[1][2]); - Start(false, false); - SetDespawnAtEnd(false);//move to center of alliance base - } - if (Faction == 1) - { - pInstance->SetData(DATA_HORDE_RETREAT, 1); - Creature* JainaDummy = me->SummonCreature(JAINA,JainaDummySpawn[0][0],JainaDummySpawn[0][1],JainaDummySpawn[0][2],JainaDummySpawn[0][3],TEMPSUMMON_TIMED_DESPAWN,60000); - if (JainaDummy) - { - JainaDummy->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - CAST_AI(hyjalAI, JainaDummy->AI())->IsDummy = true; - DummyGuid = JainaDummy->GetGUID(); - } - AddWaypoint(0,JainaDummySpawn[1][0],JainaDummySpawn[1][1],JainaDummySpawn[1][2]); - Start(false, false); - SetDespawnAtEnd(false);//move to center of alliance base - } - } - SpawnVeins(); - Overrun = true; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//cant talk after overrun event started -} - -void hyjalAI::SpawnVeins() -{ - if (Faction == 0) - { - if (VeinsSpawned[0])//prevent any buggers - return; - for (uint8 i = 0; i<7; ++i) - { - GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); - if (gem) - VeinGUID[i]=gem->GetGUID(); - } - VeinsSpawned[0] = true; - }else{ - if (VeinsSpawned[1]) - return; - for (uint8 i = 7; i<14; ++i) - { - GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); - if (gem) - VeinGUID[i]=gem->GetGUID(); - } - VeinsSpawned[1] = true; - } -} - -void hyjalAI::DeSpawnVeins() -{ - if (!pInstance) - return; - if (Faction == 1) - { - Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (!pUnit)return; - hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); - if (!ai)return; - for (uint8 i = 0; i<7; ++i) - { - if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) - gem->Delete(); - } - } else if (Faction) - { - Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_THRALL)); - if (!pUnit)return; - hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); - if (!ai)return; - for (uint8 i = 7; i<14; ++i) - { - if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) - gem->Delete(); - } - } -} - -void hyjalAI::UpdateAI(const uint32 diff) -{ - if (IsDummy) - { - if (MassTeleportTimer < diff && DoMassTeleport) - { - DoCast(me, SPELL_MASS_TELEPORT, false); - DoMassTeleport = false; - } else MassTeleportTimer -= diff; - return; - } - if (DoHide) - { - DoHide = false; - switch(me->GetEntry()) - { - case JAINA: - if (pInstance && pInstance->GetData(DATA_ALLIANCE_RETREAT)) - { - me->SetVisibility(VISIBILITY_OFF); - HideNearPos(me->GetPositionX(), me->GetPositionY()); - HideNearPos(5037.76, -1889.71); - for (uint8 i = 0; i < 92; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); - - } - else me->SetVisibility(VISIBILITY_ON); - break; - case THRALL: //thrall - if (pInstance && pInstance->GetData(DATA_HORDE_RETREAT)) - { - me->SetVisibility(VISIBILITY_OFF); - HideNearPos(me->GetPositionX(), me->GetPositionY()); - HideNearPos(5563, -2763.19); - HideNearPos(5542.2, -2629.36); - for (uint8 i = 0; i < 65; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); - - } - else me->SetVisibility(VISIBILITY_ON); - break; - } - } - if (DoRespawn) - { - if (RespawnTimer <= diff) - { - DoRespawn = false; - RespawnNearPos(me->GetPositionX(), me->GetPositionY()); - if (Faction == 0) - { - RespawnNearPos(5037.76, -1889.71); - } else if (Faction == 1) - { - RespawnNearPos(5563, -2763.19); - RespawnNearPos(5542.2, -2629.36); - } - me->SetVisibility(VISIBILITY_ON); - }else{ - RespawnTimer -= diff; - me->SetVisibility(VISIBILITY_OFF); - } - return; - } - if (Overrun) - DoOverrun(Faction, diff); - if (bRetreat) - { - if (RetreatTimer <= diff) - { - IsDummy = true; - bRetreat = false; - HideNearPos(me->GetPositionX(), me->GetPositionY()); - switch(me->GetEntry()) - { - case JAINA://jaina - HideNearPos(5037.76, -1889.71); - break; - case THRALL://thrall - HideNearPos(5563, -2763.19); - HideNearPos(5542.2, -2629.36); - HideNearPos(5603.75, -2853.12); - break; - } - me->SetVisibility(VISIBILITY_OFF); - } else RetreatTimer -= diff; - } - - if (!EventBegun) - return; - - if (Summon) - { - if (pInstance && EnemyCount) - { - EnemyCount = pInstance->GetData(DATA_TRASH); - if (!EnemyCount) - NextWaveTimer = 5000; - } - - if (NextWaveTimer <= diff) - { - if (Faction == 0) - SummonNextWave(AllianceWaves, WaveCount, AllianceBase); - else if (Faction == 1) - SummonNextWave(HordeWaves, WaveCount, HordeBase); - ++WaveCount; - } else NextWaveTimer -= diff; - } - - if (CheckTimer <= diff) - { - for (uint8 i = 0; i < 2; ++i) - { - if (BossGUID[i]) - { - Unit* pUnit = Unit::GetUnit((*me), BossGUID[i]); - if (pUnit && (!pUnit->isAlive())) - { - if (BossGUID[i] == BossGUID[0]) - { - Talk(INCOMING); - FirstBossDead = true; - } - else if (BossGUID[i] == BossGUID[1]) - { - Talk(SUCCESS); - SecondBossDead = true; - } - EventBegun = false; - CheckTimer = 0; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - BossGUID[i] = 0; - if (pInstance) - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); // Reset world state for enemies to disable it - } - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - if (!UpdateVictim()) - return; - - for (uint8 i = 0; i < 3; ++i) - { - if (Spell[i].SpellId) - { - if (SpellTimer[i] <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - Unit *pTarget = NULL; - - switch(Spell[i].TargetType) - { - case TARGETTYPE_SELF: pTarget = me; break; - case TARGETTYPE_RANDOM: pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); break; - case TARGETTYPE_VICTIM: pTarget = me->getVictim(); break; - } - - if (pTarget && pTarget->isAlive()) - { - DoCast(pTarget, Spell[i].SpellId); - SpellTimer[i] = Spell[i].Cooldown; - } - } else SpellTimer[i] -= diff; - } - } - - DoMeleeAttackIfReady(); -} -void hyjalAI::JustDied(Unit* /*killer*/) -{ - if (IsDummy)return; - me->Respawn(); - me->SetVisibility(VISIBILITY_OFF); - DoRespawn = true; - RespawnTimer = 120000; - Talk(DEATH); - Summons.DespawnAll();//despawn all wave's summons - if (pInstance) - {//reset encounter if boss is despawned (ex: thrall is killed, boss despawns, event stucks at inprogress) - if (pInstance->GetData(DATA_RAGEWINTERCHILLEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_ANETHERONEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_KAZROGALEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_AZGALOREVENT) == IN_PROGRESS) - pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); - pInstance->SetData(DATA_RESET_RAIDDAMAGE, NULL);//reset damage on die - } -} -void hyjalAI::HideNearPos(float x, float y) -{ - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - // First get all creatures. - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - // Get Creatures - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - (*itr)->SetVisibility(VISIBILITY_OFF); - (*itr)->setFaction(35);//make them friendly so mobs won't attack them - } - } -} -void hyjalAI::RespawnNearPos(float x, float y) -{ - CellPair p(Trinity::ComputeCellPair(x, y)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::RespawnDo u_do; - Trinity::WorldObjectWorker worker(me, u_do); - TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); - cell.Visit(p, obj_worker, *me->GetMap()); -} -void hyjalAI::WaypointReached(uint32 i) -{ - if (i == 1 || (i == 0 && me->GetEntry() == THRALL)) - { - me->MonsterYell(YELL_HURRY,0,0); - WaitForTeleport = true; - TeleportTimer = 20000; - if (me->GetEntry() == JAINA) - DoCast(me, SPELL_MASS_TELEPORT, false); - if (me->GetEntry() == THRALL && DummyGuid) - { - Unit* Dummy = Unit::GetUnit((*me),DummyGuid); - if (Dummy) - { - CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->DoMassTeleport = true; - CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->MassTeleportTimer = 20000; - Dummy->CastSpell(me, SPELL_MASS_TELEPORT, false); - } - } - //do some talking - //all alive guards walk near here - CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - // First get all creatures. - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive() && (*itr) != me && (*itr)->GetEntry() != JAINA) - { - if (!(*itr)->IsWithinDist(me, 60)) - (*itr)->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - float x, y, z; - (*itr)->SetDefaultMovementType(IDLE_MOTION_TYPE); - (*itr)->GetMotionMaster()->Initialize(); - float range = 10; - if (me->GetEntry() == THRALL)range = 20; - me->GetNearPoint(me, x, y, z, range, 0, me->GetAngle((*itr))); - (*itr)->GetMotionMaster()->MovePoint(0, x+irand(-5,5), y+irand(-5,5), me->GetPositionZ()); - } - } - } - } -} -void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) -{ - npc_escortAI::UpdateAI(diff); - if (WaitForTeleport) - { - if (TeleportTimer <= diff) - { - CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive()) - { - (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); - (*itr)->setFaction(35);//make them friendly so mobs won't attack them - (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - DoCast(me, SPELL_TELEPORT_VISUAL); - bRetreat = true; - RetreatTimer = 1000; - } - - WaitForTeleport = false; - Teleported = true; - }TeleportTimer -= diff; - } - if (!Teleported) - return; - Overrun = false;//execute once - switch(faction) - { - case 0://alliance - for (uint8 i = 0; i < 92; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); - - for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(GHOUL, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 3; ++i)//summon 3 abominations - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(ABOMINATION, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles - { - Creature* pUnit = me->SummonCreature(GARGOYLE, AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - pUnit->SetHomePosition(AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3]); - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - break; - case 1://horde - for (uint8 i = 0; i < 65; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); - - for (uint8 i = 0; i < 26; ++i)//summon infernals - { - Creature* pUnit = me->SummonCreature(GIANT_INFERNAL, InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - pUnit->SetHomePosition(InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3]); - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(GHOUL, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 5; ++i)//summon 5 abominations - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(ABOMINATION, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - break; - } -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h deleted file mode 100644 index 5c75465b7b4..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjalAI.h +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef SC_HYJALAI_H -#define SC_HYJALAI_H - -#include "hyjal.h" -#include "ScriptedEscortAI.h" - -// Trash Mobs summoned in waves -#define NECROMANCER 17899//done -#define ABOMINATION 17898//done -#define GHOUL 17895//done -#define BANSHEE 17905//done -#define CRYPT_FIEND 17897//done -#define GARGOYLE 17906//done -#define FROST_WYRM 17907//done -#define GIANT_INFERNAL 17908//done -#define FEL_STALKER 17916//done - -#define JAINA 17772 -#define THRALL 17852 -#define TYRANDE 17948 - -#define ANCIENT_VEIN 185557 -#define FLAMEOBJECT 182592 - -// Bosses summoned after every 8 waves -#define RAGE_WINTERCHILL 17767 -#define ANETHERON 17808 -#define KAZROGAL 17888 -#define AZGALOR 17842 -#define ARCHIMONDE 17968 - -#define SPELL_TELEPORT_VISUAL 41232 -#define SPELL_MASS_TELEPORT 16807 - -//Spells for Jaina -#define SPELL_BRILLIANCE_AURA 31260 // The database must handle this spell via creature_addon(it should, but is removed in evade..) -#define SPELL_BLIZZARD 31266 -#define SPELL_PYROBLAST 31263 -#define SPELL_SUMMON_ELEMENTALS 31264 - -//Thrall spells -#define SPELL_CHAIN_LIGHTNING 31330 -#define SPELL_SUMMON_DIRE_WOLF 31331 - -struct Wave -{ - uint32 Mob[18]; // Stores Creature Entries to be summoned in Waves - uint32 WaveTimer; // The timer before the next wave is summoned - bool IsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that -}; - -static Wave AllianceWaves[]= // Waves that will be summoned in the Alliance Base -{ // Rage Winterchill Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron - {RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, - // Anetheron Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, GHOUL, GHOUL, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - // All 8 Waves are summoned, summon Anatheron - {ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} -}; - -static Wave HordeWaves[]= // Waves that are summoned in the Horde base -{ // Kaz'Rogal Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, - // All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor - {KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, - // Azgalor Wave 1-8 - {ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, FROST_WYRM, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, - {GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, 0, 0, 0, 0, 180000, false}, - {FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, - // All 8 Waves are summoned, summon Azgalor - {AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} -}; - -enum TargetType // Used in the spell cast system for the AI -{ - TARGETTYPE_SELF = 0, - TARGETTYPE_RANDOM = 1, - TARGETTYPE_VICTIM = 2, -}; - -struct Yells -{ - uint32 id; // Used to determine the type of yell (attack, rally, etc) - int32 textid; // The text id to be yelled -}; - -enum YellId -{ - ATTACKED = 0, // Used when attacked and set in combat - BEGIN = 1, // Used when the event is begun - INCOMING = 2, // Used to warn the raid that another wave phase is coming - RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned - FAILURE = 4, // Used when raid has failed (unsure where to place) - SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase - DEATH = 6, // Used on death -}; - -static Yells JainaQuotes[]= -{ - {ATTACKED, -1534000}, - {ATTACKED, -1534001}, - {INCOMING, -1534002}, - {BEGIN, -1534003}, - {RALLY, -1534004}, - {RALLY, -1534005}, - {FAILURE, -1534006}, - {SUCCESS, -1534007}, - {DEATH, -1534008}, -}; - -static Yells ThrallQuotes[]= -{ - {ATTACKED, -1534009}, - {ATTACKED, -1534010}, - {INCOMING, -1534011}, - {BEGIN, -1534012}, - {RALLY, -1534013}, - {RALLY, -1534014}, - {FAILURE, -1534015}, - {SUCCESS, -1534016}, - {DEATH, -1534017}, -}; - -struct hyjalAI : public npc_escortAI -{ - hyjalAI(Creature *c); - - void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat - - void EnterEvadeMode(); // Send creature back to spawn location and evade. - - void EnterCombat(Unit * /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack - - void UpdateAI(const uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells. - - void JustDied(Unit* /*killer*/); // Called on death, informs the raid that they have failed. - - void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal - { - Faction = _faction; - } - - void Retreat(); // "Teleport" (teleport visual + set invisible) all friendly creatures away from the base. - - void SpawnVeins(); - void DeSpawnVeins(); - void JustSummoned(Creature *summoned); - void SummonedCreatureDespawn(Creature* summoned); - void HideNearPos(float x, float y); - void RespawnNearPos(float x, float y); - void WaypointReached(uint32 i); - void DoOverrun(uint32 faction, const uint32 diff); - void MoveInLineOfSight(Unit *who); - - void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base - - // Summons the next wave, calls SummonCreature - void SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]); - - void StartEvent(Player* player); // Begins the event by gossip click - - uint32 GetInstanceData(uint32 Event); // Gets instance data for this instance, used to check if raid has gotten past a certain point and can access the next phase - - void Talk(uint32 id); // Searches for the appropriate yell and sound and uses it to inform the raid of various things - - public: - ScriptedInstance* pInstance; - - uint64 PlayerGUID; - uint64 BossGUID[2]; - uint64 VeinGUID[14]; - - uint32 NextWaveTimer; - uint32 WaveCount; - uint32 CheckTimer; - uint32 Faction; - uint32 EnemyCount; - uint32 RetreatTimer; - - bool EventBegun; - bool FirstBossDead; - bool SecondBossDead; - bool Summon; - bool bRetreat; - bool Debug; - bool VeinsSpawned[2]; - uint8 InfernalCount; - SummonList Summons; - bool Overrun; - bool Teleported; - bool WaitForTeleport; - uint32 TeleportTimer; - uint32 OverrunCounter; - uint32 OverrunCounter2; - uint32 InfernalPoint; - uint32 RespawnTimer; - bool DoRespawn; - bool DoHide; - bool IsDummy; - uint32 MassTeleportTimer; - bool DoMassTeleport; - uint64 DummyGuid; - - struct Spell - { - uint32 SpellId; - uint32 Cooldown; - uint32 TargetType; - }Spell[3]; - - private: - uint32 SpellTimer[3]; - //std::list CreatureList; -}; -#endif - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp deleted file mode 100644 index c4cf9ede397..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp +++ /dev/null @@ -1,1440 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" -#include "hyjalAI.h" - -#define SPELL_METEOR 33814 //infernal visual -#define SPELL_IMMOLATION 37059 -#define SPELL_FLAME_BUFFET 31724 -#define NPC_TRIGGER 21987 //World Trigger (Tiny) -#define MODEL_INVIS 11686 //invisible model - -float HordeWPs[8][3]=//basic waypoints from spawn to leader -{ - {5492.91, -2404.61, 1462.63}, - {5531.76, -2460.87, 1469.55}, - {5554.58, -2514.66, 1476.12}, - {5554.16, -2567.23, 1479.90}, - {5540.67, -2625.99, 1480.89}, - {5508.16, -2659.20, 1480.15},//random rush starts from here - {5489.62, -2704.05, 1482.18}, - {5457.04, -2726.26, 1485.10} -}; -float AllianceWPs[8][3]=//basic waypoints from spawn to leader -{ - {4896.08, -1576.35, 1333.65}, - {4898.68, -1615.02, 1329.48}, - {4907.12, -1667.08, 1321.00}, - {4963.18, -1699.35, 1340.51}, - {4989.16, -1716.67, 1335.74},//first WP in the base, after the gate - {5026.27, -1736.89, 1323.02}, - {5037.77, -1770.56, 1324.36}, - {5067.23, -1789.95, 1321.17} -}; - -float FrostWyrmWPs[3][3]=//waypoints for the frost wyrms in horde base -{ - {5580.82, -2628.83, 1528.28}, - {5550.90, -2667.16, 1505.45}, - {5459.64, -2725.91, 1484.83} -}; - -float GargoyleWPs[3][3]=//waypoints for the gargoyles in horde base -{ - {5533.66, -2634.32, 1495.33}, - {5517.88, -2712.05, 1490.54}, - {5459.64, -2725.91, 1484.83} -}; - -float FlyPathWPs[3][3]=//waypoints for the gargoyls and frost wyrms in horde base in wave 1/3 -{ - {5531.96, -2772.83, 1516.68}, - {5498.32, -2734.84, 1497.01}, - {5456.67, -2725.48, 1493.08} -}; - -float AllianceOverrunWP[55][3]=//waypoints in the alliance base used in the end in the cleaning wave -{ - {4976.37,-1708.02,1339.43},//0spawn - {4994.83,-1725.52,1333.25},//1 start - {4982.92,-1753.7,1330.69},//2 end - {4996.75,-1721.47,1332.95},//3 start - {5015.74,-1755.05,1322.49},//4 - {4998.68,-1773.44,1329.59},//5 - {4994.83,-1725.52,1333.25},//6 start - {5022.8,-1735.46,1323.53},//7 - {5052.15,-1729.02,1320.88},//8 - {5082.43,-1726.29,1327.87},//9 - {4994.83,-1725.52,1333.25},//10 start - {5018.92,-1751.14,1322.19},//11 - {5040.09,-1792.09,1322.1},//12 - {4994.83,-1725.52,1333.25},//13 start - {5023.47,-1748.1,1322.51},//14 - {5013.43,-1842.39,1322.07},//15 - {4994.83,-1725.52,1333.25},//16 start - {5020.8,-1756.86,1322.2},//17 - {5019.53,-1824.6,1321.96},//18 - {5043.42,-1853.75,1324.52},//19 - {5053.02,-1864.13,1330.36},//20 - {5062.49,-1852.47,1330.49},//21 - {5015.27, -1738.77, 1324.83},//35//start 22 - {5027.97, -1775.25, 1321.87},//34 23 - {5015.94, -1821.24, 1321.86},//33 24 - {4983.25, -1857.4, 1320.48},//32 25 - {4981.51, -1883.7, 1322.34},//31 26 - {5002.33, -1893.98, 1325.88},//30 27 - {5049.32, -1886.54, 1331.69},//29 28 - {5089.68, -1846.88, 1328.99},//28 29 - {5127.90, -1825.14, 1335.58},//27 30 - {5163.27, -1789.08, 1337.04},//26 31 - {5138.97, -1755.88, 1334.57},//25 32 - {5096.63, -1742.22, 1329.61},//24 33 - {5065.81, -1729.43, 1325.66},//23 34 - {5049.32, -1726.31, 1320.64},//22 start - {5081.07, -1902.10, 1346.36},//36 abo start - {5107.65, -1912.03, 1356.49},//37 - {5132.83, -1927.07, 1362.42},//38 - {5147.78, -1954.41, 1365.98},//39 - {5164.96, -1966.48, 1367.04},//40 - {5189.04, -1961.06, 1367.90},//41 - {5212.27, -1975.30, 1365.58},//42 - {5221.82, -1994.18, 1364.97},//43 end1 - {5202.23, -1994.94, 1367.59},//44 end2 - {5279.94, -2049.68, 1311.38},//45 garg1 - {5289.15, -2219.06, 1291.12},//46 garg2 - {5202.07, -2136.10, 1305.07},//47 garg3 - {5071.52, -2425.63, 1454.48},//48 garg4 - {5120.65, -2467.92, 1463.93},//49 garg5 - {5283.04, -2043.26, 1300.11},//50 garg target1 - {5313.22, -2207.60, 1290.06},//51 garg target2 - {5180.41, -2121.87, 1292.62},//52 garg target3 - {5088.68, -2432.04, 1441.73},//53 garg target4 - {5111.26, -2454.73, 1449.63}//54 garg target5 - -}; - -float HordeOverrunWP[21][3]=//waypoints in the horde base used in the end in the cleaning wave -{ - {5490.72,-2702.94,1482.14},//0 start - {5469.77,-2741.34,1486.95}, - {5439.47,-2771.02,1494.59}, - {5408.85,-2811.92,1505.68}, - {5423.87,-2857.80,1515.55}, - {5428.19,-2898.15,1524.61}, - {5394.59,-2930.05,1528.23}, - {5351.11,-2935.80,1532.24}, - {5312.37,-2959.06,1536.21}, - {5264.93,-2989.80,1545.70}, - {5256.63,-3056.16,1559.24}, - {5267.32,-3119.55,1575.36}, - {5305.61,-3139.88,1586.38}, - {5330.56,-3135.37,1588.58}, - {5365.87,-3139.78,1583.96}, - {5389.39,-3163.57,1582.57},//15 end - {5500.86,-2669.89,1481.04},//16 start - {5472.08,-2715.14,1483.55}, - {5450.11,-2721.47,1485.61}, - {5433.25,-2712.93,1493.02},//19 end 1 - {5429.91,-2718.44,1493.42}//20 end 2 -}; - -hyjal_trashAI::hyjal_trashAI(Creature *c) : npc_escortAI(c) -{ - pInstance = c->GetInstanceData(); - IsEvent = false; - Delay = 0; - LastOverronPos = 0; - IsOverrun = false; - OverrunType = 0; - SetupOverrun = false; - faction = 0; - useFlyPath = false; - damageTaken = 0; - Reset(); -} - -void hyjal_trashAI::DamageTaken(Unit *done_by, uint32 &damage) -{ - if (done_by->GetTypeId() == TYPEID_PLAYER || (done_by->GetTypeId() == TYPEID_UNIT && CAST_CRE(done_by)->isPet())) - { - damageTaken += damage; - if (pInstance) - pInstance->SetData(DATA_RAIDDAMAGE,damage);//store raid's damage - } -} - -void hyjal_trashAI::UpdateAI(const uint32 /*diff*/) -{ - if (IsOverrun && !SetupOverrun) - { - SetupOverrun = true; - if (faction == 0) - { - if (me->GetEntry() == GARGOYLE) - { - DummyTarget[0] = AllianceOverrunWP[50+OverrunType][0]; //+OverrunType 0 - 4 - DummyTarget[1] = AllianceOverrunWP[50+OverrunType][1]; - DummyTarget[2] = AllianceOverrunWP[50+OverrunType][2]; - } - if (me->GetEntry() == ABOMINATION) - { - for (uint8 i = 0; i < 4; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); - AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); - AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); - AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); - AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); - AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); - AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); - - AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); - AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); - AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); - AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); - AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); - AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); - AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); - AddWaypoint(18, AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2]); - me->SetHomePosition(AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 18; - Start(true, true); - break; - case 1: - AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); - AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); - AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); - AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); - AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); - AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); - AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); - - AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); - AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); - AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); - AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); - AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); - AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); - AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); - AddWaypoint(18, AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2]); - me->SetHomePosition(AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 18; - Start(true, true); - break; - default: - for (uint8 i = 22; i < 36; ++i) - AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); - - SetDespawnAtEnd(true); - LastOverronPos = 17; - Start(true, true); - break; - } - } - if (me->GetEntry() == GHOUL) - { - for (uint8 i = 0; i < 4; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(4, AllianceOverrunWP[1][0]+irand(-3,3), AllianceOverrunWP[1][1]+irand(-3,3), AllianceOverrunWP[1][2]); - AddWaypoint(5, AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2]); - me->SetHomePosition(AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 5; - Start(true, true); - break; - case 1: - AddWaypoint(4, AllianceOverrunWP[3][0]+irand(-3,3), AllianceOverrunWP[3][1]+irand(-3,3), AllianceOverrunWP[3][2]); - AddWaypoint(5, AllianceOverrunWP[4][0]+irand(-3,3), AllianceOverrunWP[4][1]+irand(-3,3), AllianceOverrunWP[4][2]); - AddWaypoint(6, AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2]); - me->SetHomePosition(AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 2: - AddWaypoint(4, AllianceOverrunWP[6][0]+irand(-3,3), AllianceOverrunWP[6][1]+irand(-3,3), AllianceOverrunWP[6][2]); - AddWaypoint(5, AllianceOverrunWP[7][0]+irand(-3,3), AllianceOverrunWP[7][1]+irand(-3,3), AllianceOverrunWP[7][2]); - AddWaypoint(6, AllianceOverrunWP[8][0]+irand(-3,3), AllianceOverrunWP[8][1]+irand(-3,3), AllianceOverrunWP[8][2]); - AddWaypoint(7, AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2]); - me->SetHomePosition(AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 7; - Start(true, true); - break; - case 3: - AddWaypoint(4, AllianceOverrunWP[10][0]+irand(-3,3), AllianceOverrunWP[10][1]+irand(-3,3), AllianceOverrunWP[10][2]); - AddWaypoint(5, AllianceOverrunWP[11][0]+irand(-3,3), AllianceOverrunWP[11][1]+irand(-3,3), AllianceOverrunWP[11][2]); - AddWaypoint(6, AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2]); - me->SetHomePosition(AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 4: - AddWaypoint(4, AllianceOverrunWP[13][0]+irand(-3,3), AllianceOverrunWP[13][1]+irand(-3,3), AllianceOverrunWP[13][2]); - AddWaypoint(5, AllianceOverrunWP[14][0]+irand(-3,3), AllianceOverrunWP[14][1]+irand(-3,3), AllianceOverrunWP[14][2]); - AddWaypoint(6, AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2]); - me->SetHomePosition(AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 5: - AddWaypoint(4, AllianceOverrunWP[16][0]+irand(-3,3), AllianceOverrunWP[16][1]+irand(-3,3), AllianceOverrunWP[16][2]); - AddWaypoint(5, AllianceOverrunWP[17][0]+irand(-3,3), AllianceOverrunWP[17][1]+irand(-3,3), AllianceOverrunWP[17][2]); - AddWaypoint(6, AllianceOverrunWP[18][0]+irand(-3,3), AllianceOverrunWP[18][1]+irand(-3,3), AllianceOverrunWP[18][2]); - AddWaypoint(7, AllianceOverrunWP[19][0]+irand(-3,3), AllianceOverrunWP[19][1]+irand(-3,3), AllianceOverrunWP[19][2]); - AddWaypoint(8, AllianceOverrunWP[20][0]+irand(-3,3), AllianceOverrunWP[20][1]+irand(-3,3), AllianceOverrunWP[20][2]); - AddWaypoint(9, AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2]); - me->SetHomePosition(AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 9; - Start(true, true); - break; - default: - for (uint8 i = 22; i < 36; ++i) - AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 17; - Start(true, true); - break; - } - } - } - if (faction == 1) - { - if (me->GetEntry() == GHOUL) - { - for (uint8 i = 0; i < 6; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); - AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); - AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); - AddWaypoint(8, HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2]); - me->SetHomePosition(HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 8; - Start(true, true); - break; - case 1: - AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); - AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); - AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); - AddWaypoint(8, HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2]); - me->SetHomePosition(HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 8; - Start(true, true); - break; - default: - for (uint8 i = 0; i < 16; ++i) - AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 21; - Start(true, true); - break; - } - } - if (me->GetEntry() == ABOMINATION) - { - for (uint8 i = 0; i < 6; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-10,10), HordeWPs[i][1]+irand(-10,10), HordeWPs[i][2]); - for (uint8 i = 0; i < 16; ++i) - AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 21; - Start(true, true); - } - } - } -} - -void hyjal_trashAI::JustDied(Unit * /*victim*/) -{ - if (!pInstance) - return; - if (IsEvent && !me->isWorldBoss()) - pInstance->SetData(DATA_TRASH, 0);//signal trash is dead - - if ((pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE && !me->isWorldBoss()) || (damageTaken < me->GetMaxHealth()/4 && me->isWorldBoss())) - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);//no loot -} - -struct mob_giant_infernalAI : public hyjal_trashAI -{ - mob_giant_infernalAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - meteor = false;//call once! - CanMove = false; - Delay = rand()%30000; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(MODEL_INVIS); - pGo = false; - pos = 0; - Reset(); - } - - bool meteor; - bool CanMove; - bool WpEnabled; - bool pGo; - uint32 pos; - uint32 spawnTimer; - uint32 FlameBuffetTimer; - bool imol; - - void Reset() - { - spawnTimer = 2000; - FlameBuffetTimer= 2000; - imol = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 0 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Delay <= diff) - { - Delay=0; - }else{ - Delay-=diff; - return; - } - if (!meteor) - { - float x,y,z; - me->GetPosition(x,y,z); - Creature* trigger = me->SummonCreature(NPC_TRIGGER,x+8,y+8,z+25+rand()%10,me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,1000); - if (trigger) - { - trigger->SetVisibility(VISIBILITY_OFF); - trigger->setFaction(me->getFaction()); - trigger->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - trigger->CastSpell(me,SPELL_METEOR,true); - } - me->GetMotionMaster()->Clear(); - meteor = true; - } else if (!CanMove){ - if (spawnTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); - CanMove = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && !pInstance->GetData(DATA_HORDE_RETREAT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } else if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && pInstance->GetData(DATA_HORDE_RETREAT)){ - //do overrun - } - } - } else spawnTimer -= diff; - } - if (!CanMove)return; - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, HordeWPs[7][0]+irand(-3,3), HordeWPs[7][1]+irand(-3,3), HordeWPs[7][2]);//HordeWPs[7] infront of thrall - Start(true, true); - SetDespawnAtEnd(false); - } - } - } - - if (!UpdateVictim()) - return; - if (!imol) - { - DoCast(me, SPELL_IMMOLATION); - imol=true; - } - if (FlameBuffetTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAME_BUFFET, true); - FlameBuffetTimer = 7000; - } else FlameBuffetTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_giant_infernal(Creature* pCreature) -{ - return new mob_giant_infernalAI(pCreature); -} - -#define SPELL_DISEASE_CLOUD 31607 -#define SPELL_KNOCKDOWN 31610 - -struct mob_abominationAI : public hyjal_trashAI -{ - mob_abominationAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 KnockDownTimer; - uint32 pos; - void Reset() - { - KnockDownTimer = 10000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - if (i == LastOverronPos && IsOverrun) - { - if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) - { - me->setDeathState(DEAD); - me->RemoveCorpse(); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!me->HasAura(SPELL_DISEASE_CLOUD)) - DoCast(me, SPELL_DISEASE_CLOUD); - if (!UpdateVictim()) - return; - if (KnockDownTimer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - KnockDownTimer = 15000+rand()%10000; - } else KnockDownTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_abomination(Creature* pCreature) -{ - return new mob_abominationAI(pCreature); -} - -#define SPELL_FRENZY 31540 - -struct mob_ghoulAI : public hyjal_trashAI -{ - mob_ghoulAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 FrenzyTimer; - uint32 pos; - uint32 MoveTimer; - bool RandomMove; - void Reset() - { - FrenzyTimer = 5000+rand()%5000; - MoveTimer = 2000; - RandomMove = false; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - if (i == LastOverronPos && IsOverrun) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); - if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) - { - me->setDeathState(DEAD); - me->RemoveCorpse(); - } - - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (FrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - FrenzyTimer = 15000+rand()%15000; - } else FrenzyTimer -= diff; - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_ghoul(Creature* pCreature) -{ - return new mob_ghoulAI(pCreature); -} - -#define SPELL_RAISE_DEAD_1 31617 -#define SPELL_RAISE_DEAD_2 31624 -#define SPELL_RAISE_DEAD_3 31625 -#define SPELL_SHADOW_BOLT 31627 - -struct mob_necromancerAI : public hyjal_trashAI -{ - mob_necromancerAI(Creature* c) : hyjal_trashAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - SummonList summons; - bool pGo; - uint32 ShadowBoltTimer; - uint32 pos; - void Reset() - { - ShadowBoltTimer = 1000+rand()%5000; - summons.DespawnAll(); - } - - void JustSummoned(Creature* summon) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true); - if (pTarget && summon) - summon->Attack(pTarget,false); - summons.Summon(summon); - } - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoSpawnCreature(17902,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - DoSpawnCreature(17902,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - case 1: - DoSpawnCreature(17903,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - DoSpawnCreature(17903,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - case 2: - DoSpawnCreature(RAND(17902,17903),3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(true, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(true, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (ShadowBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - ShadowBoltTimer = 20000+rand()%10000; - } else ShadowBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_necromancer(Creature* pCreature) -{ - return new mob_necromancerAI(pCreature); -} - -#define SPELL_BANSHEE_CURSE 31651 -#define SPELL_BANSHEE_WAIL 38183 -#define SPELL_ANTI_MAGIC_SHELL 31662 - -struct mob_bansheeAI : public hyjal_trashAI -{ - mob_bansheeAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 CourseTimer; - uint32 WailTimer; - uint32 ShellTimer; - uint32 pos; - void Reset() - { - CourseTimer = 20000+rand()%5000; - WailTimer = 15000+rand()%5000; - ShellTimer = 50000+rand()%10000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (CourseTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BANSHEE_CURSE); - CourseTimer = 20000+rand()%5000; - } else CourseTimer -= diff; - if (WailTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BANSHEE_WAIL); - WailTimer = 15000+rand()%5000; - } else WailTimer -= diff; - if (ShellTimer <= diff) - { - DoCast(me, SPELL_ANTI_MAGIC_SHELL); - ShellTimer = 50000+rand()%10000; - } else ShellTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_banshee(Creature* pCreature) -{ - return new mob_bansheeAI(pCreature); -} - -#define SPELL_WEB 28991 - -struct mob_crypt_fiendAI : public hyjal_trashAI -{ - mob_crypt_fiendAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 WebTimer; - uint32 pos; - void Reset() - { - WebTimer = 20000+rand()%5000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - - } - } - } - if (!UpdateVictim()) - return; - if (WebTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WEB); - WebTimer = 20000+rand()%5000; - } else WebTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_crypt_fiend(Creature* pCreature) -{ - return new mob_crypt_fiendAI(pCreature); -} - -#define SPELL_MANA_BURN 31729 - -struct mob_fel_stalkerAI : public hyjal_trashAI -{ - mob_fel_stalkerAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 ManaBurnTimer; - uint32 pos; - void Reset() - { - ManaBurnTimer = 9000+rand()%5000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - - } - } - } - if (!UpdateVictim()) - return; - if (ManaBurnTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MANA_BURN); - ManaBurnTimer = 9000+rand()%5000; - } else ManaBurnTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_fel_stalker(Creature* pCreature) -{ - return new mob_fel_stalkerAI(pCreature); -} - -#define SPELL_FROST_BREATH 31688 - -struct mob_frost_wyrmAI : public hyjal_trashAI -{ - mob_frost_wyrmAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 FrostBreathTimer; - uint32 pos; - uint32 MoveTimer; - - void Reset() - { - FrostBreathTimer = 5000; - MoveTimer = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 2 && pInstance && !IsOverrun) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - { - me->AddThreat(pTarget,0.0); - DoCast(pTarget, SPELL_FROST_BREATH, true); - } - } - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_TRASH, 0);//signal trash is dead - - float x,y,z; - me->GetPosition(x,y,z); - z = me->GetMap()->GetHeight(x, y, z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - me->GetMap()->CreatureRelocation(me, x,y,z,0); - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - { - CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); - npc_escortAI::UpdateAI(diff); - } - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (!useFlyPath) - { - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FrostWyrmWPs[i][0], FrostWyrmWPs[i][1], FrostWyrmWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else{//fly path FlyPathWPs - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (!me->IsWithinDist(me->getVictim(), 25)){ - if (MoveTimer <= diff) - { - me->GetMotionMaster()->MoveChase(me->getVictim()); - MoveTimer = 2000; - } else MoveTimer-=diff; - } - - if (FrostBreathTimer <= diff) - { - if (!me->IsWithinDist(me->getVictim(), 25)) - { - DoCast(me->getVictim(), SPELL_FROST_BREATH); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - FrostBreathTimer = 4000; - } - } else FrostBreathTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_frost_wyrm(Creature* pCreature) -{ - return new mob_frost_wyrmAI(pCreature); -} - -#define SPELL_GARGOYLE_STRIKE 31664 - -struct mob_gargoyleAI : public hyjal_trashAI -{ - mob_gargoyleAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - DummyTarget[0] = 0;DummyTarget[1] = 0;DummyTarget[2] = 0; - Reset(); - } - - bool pGo; - uint32 StrikeTimer; - uint32 pos; - uint32 MoveTimer; - float Zpos; - bool forcemove; - - void Reset() - { - forcemove = true; - Zpos = 10.0; - StrikeTimer = 2000+rand()%5000; - MoveTimer = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 2 && pInstance && !IsOverrun) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - { - me->AddThreat(pTarget,0.0); - DoCast(pTarget, SPELL_GARGOYLE_STRIKE, true); - } - } - } - - void JustDied(Unit *victim) - { - float x,y,z; - me->GetPosition(x,y,z); - z = me->GetMap()->GetHeight(x, y, z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - me->GetMap()->CreatureRelocation(me, x,y,z,0); - hyjal_trashAI::JustDied(victim); - } - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - { - CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); - npc_escortAI::UpdateAI(diff); - } - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (!useFlyPath) - { - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, GargoyleWPs[i][0]+irand(-10,10), GargoyleWPs[i][1]+irand(-10,10), GargoyleWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else{//fly path FlyPathWPs - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (IsOverrun && !UpdateVictim()) - { - if (faction == 0)//alliance - { - if (StrikeTimer <= diff) - { - me->CastSpell(DummyTarget[0],DummyTarget[1],DummyTarget[2],SPELL_GARGOYLE_STRIKE,false); - StrikeTimer = 2000+rand()%1000; - } else StrikeTimer -= diff; - } - } - if (!UpdateVictim()) - return; - if (!me->IsWithinDist(me->getVictim(), 20) || forcemove) - { - forcemove = false; - if (forcemove) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - me->Attack(pTarget,false); - } - if (MoveTimer <= diff) - { - float x,y,z; - me->getVictim()->GetPosition(x,y,z); - me->GetMotionMaster()->MovePoint(0,x,y,z+Zpos); - Zpos-=1.0; - if (Zpos <= 0)Zpos=0; - MoveTimer = 2000; - } else MoveTimer-=diff; - } - if (StrikeTimer <= diff) - { - if (me->IsWithinDist(me->getVictim(), 20)) - { - DoCast(me->getVictim(), SPELL_GARGOYLE_STRIKE); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - StrikeTimer = 2000+rand()%1000; - } else StrikeTimer=0; - } else StrikeTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_gargoyle(Creature* pCreature) -{ - return new mob_gargoyleAI(pCreature); -} - -#define SPELL_EXPLODING_SHOT 7896 - -struct alliance_riflemanAI : public Scripted_NoMovementAI -{ - alliance_riflemanAI(Creature *c) : Scripted_NoMovementAI(c) - { - Reset(); - } - - uint32 ExplodeTimer; - - void JustDied(Unit* /*who*/) - { - } - - void Reset() - { - ExplodeTimer = 5000+rand()%5000; - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && me->IsHostileTo(who)) - { - //float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, 30)) - AttackStart(who); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - if (ExplodeTimer <= diff) - { - if (!me->IsWithinDistInMap(me->getVictim(), 30)) - { - EnterEvadeMode(); - return; - } - int dmg = 500+rand()%700; - me->CastCustomSpell(me->getVictim(), SPELL_EXPLODING_SHOT, &dmg, 0, 0, false); - ExplodeTimer = 5000+rand()%5000; - } else ExplodeTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_alliance_rifleman(Creature* pCreature) -{ - return new alliance_riflemanAI(pCreature); -} - -void AddSC_hyjal_trash() -{ - Script *newscript = new Script; - newscript->Name = "mob_giant_infernal"; - newscript->GetAI = &GetAI_mob_giant_infernal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_abomination"; - newscript->GetAI = &GetAI_mob_abomination; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ghoul"; - newscript->GetAI = &GetAI_mob_ghoul; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_necromancer"; - newscript->GetAI = &GetAI_mob_necromancer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_banshee"; - newscript->GetAI = &GetAI_mob_banshee; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crypt_fiend"; - newscript->GetAI = &GetAI_mob_crypt_fiend; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fel_stalker"; - newscript->GetAI = &GetAI_mob_fel_stalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frost_wyrm"; - newscript->GetAI = &GetAI_mob_frost_wyrm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_gargoyle"; - newscript->GetAI = &GetAI_mob_gargoyle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "alliance_rifleman"; - newscript->GetAI = &GetAI_alliance_rifleman; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h deleted file mode 100644 index 21ee4bc06cc..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/hyjal_trash.h +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef SC_HYJAL_TRASH_AI_H -#define SC_HYJAL_TRASH_AI_H - -#include "hyjal.h" -#include "ScriptedEscortAI.h" - -#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies - -struct hyjal_trashAI : public npc_escortAI -{ - hyjal_trashAI(Creature *c); - - void UpdateAI(const uint32 diff); - - void JustDied(Unit* /*killer*/); - - void DamageTaken(Unit *done_by, uint32 &damage); - - public: - ScriptedInstance* pInstance; - bool IsEvent; - uint32 Delay; - uint32 LastOverronPos; - bool IsOverrun; - bool SetupOverrun; - uint32 OverrunType; - uint8 faction; - bool useFlyPath; - uint32 damageTaken; - float DummyTarget[3]; - - //private: -}; -#endif diff --git a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp deleted file mode 100644 index e89d518c5bc..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp +++ /dev/null @@ -1,324 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Mount_Hyjal -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -enum eEnums -{ - MAX_ENCOUNTER = 5, - - GO_ANCIENT_GEM = 185557 -}; -/* Battle of Mount Hyjal encounters: -0 - Rage Winterchill event -1 - Anetheron event -2 - Kaz'rogal event -3 - Azgalor event -4 - Archimonde event -*/ - -struct instance_mount_hyjal : public ScriptedInstance -{ - instance_mount_hyjal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - std::list m_uiAncientGemGUID; - - uint64 RageWinterchill; - uint64 Anetheron; - uint64 Kazrogal; - uint64 Azgalor; - uint64 Archimonde; - uint64 JainaProudmoore; - uint64 Thrall; - uint64 TyrandeWhisperwind; - uint64 HordeGate; - uint64 ElfGate; - - uint32 Trash; - - uint32 hordeRetreat; - uint32 allianceRetreat; - bool ArchiYell; - - uint32 RaidDamage; - - #define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more." - #define YELL_EFFORTS_NAME "Archimonde" - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiAncientGemGUID.clear(); - - RageWinterchill = 0; - Anetheron = 0; - Kazrogal = 0; - Azgalor = 0; - Archimonde = 0; - JainaProudmoore = 0; - Thrall = 0; - TyrandeWhisperwind = 0; - HordeGate = 0; - ElfGate = 0; - ArchiYell = false; - RaidDamage = 0; - - Trash = 0; - - hordeRetreat = 0; - allianceRetreat = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 182060: - HordeGate = pGo->GetGUID(); - if (allianceRetreat) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - case 182061: - ElfGate = pGo->GetGUID(); - if (hordeRetreat) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - case GO_ANCIENT_GEM: - m_uiAncientGemGUID.push_back(pGo->GetGUID()); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17767: RageWinterchill = pCreature->GetGUID(); break; - case 17808: Anetheron = pCreature->GetGUID(); break; - case 17888: Kazrogal = pCreature->GetGUID(); break; - case 17842: Azgalor = pCreature->GetGUID(); break; - case 17968: Archimonde = pCreature->GetGUID(); break; - case 17772: JainaProudmoore = pCreature->GetGUID(); break; - case 17852: Thrall = pCreature->GetGUID(); break; - case 17948: TyrandeWhisperwind = pCreature->GetGUID(); break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_RAGEWINTERCHILL: return RageWinterchill; - case DATA_ANETHERON: return Anetheron; - case DATA_KAZROGAL: return Kazrogal; - case DATA_AZGALOR: return Azgalor; - case DATA_ARCHIMONDE: return Archimonde; - case DATA_JAINAPROUDMOORE: return JainaProudmoore; - case DATA_THRALL: return Thrall; - case DATA_TYRANDEWHISPERWIND: return TyrandeWhisperwind; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_RAGEWINTERCHILLEVENT: m_auiEncounter[0] = data; break; - case DATA_ANETHERONEVENT: - m_auiEncounter[1] = data; - break; - case DATA_KAZROGALEVENT: m_auiEncounter[2] = data; break; - case DATA_AZGALOREVENT: - { - m_auiEncounter[3] = data; - if (data == DONE) - { - if (ArchiYell)break; - ArchiYell = true; - - Creature* pCreature = instance->GetCreature(Azgalor); - if (pCreature) - { - Creature* pUnit = pCreature->SummonCreature(21987,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,10000); - - Map* pMap = pCreature->GetMap(); - if (pMap->IsDungeon() && pUnit) - { - pUnit->SetVisibility(VISIBILITY_OFF); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()) - { - WorldPacket data(SMSG_MESSAGECHAT, 200); - pUnit->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,YELL_EFFORTS,0,YELL_EFFORTS_NAME,i->getSource()->GetGUID()); - i->getSource()->GetSession()->SendPacket(&data); - - WorldPacket data2(SMSG_PLAY_SOUND, 4); - data2 << 10986; - i->getSource()->GetSession()->SendPacket(&data2); - } - } - } - } - } - } - break; - case DATA_ARCHIMONDEEVENT: m_auiEncounter[4] = data; break; - case DATA_RESET_TRASH_COUNT: Trash = 0; break; - - case DATA_TRASH: - if (data) Trash = data; - else Trash--; - DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash); - break; - case TYPE_RETREAT: - if (data == SPECIAL) - { - if (!m_uiAncientGemGUID.empty()) - { - for (std::list::const_iterator itr = m_uiAncientGemGUID.begin(); itr != m_uiAncientGemGUID.end(); ++itr) - { - //don't know how long it expected - DoRespawnGameObject(*itr,DAY); - } - } - } - break; - case DATA_ALLIANCE_RETREAT: - allianceRetreat = data; - HandleGameObject(HordeGate, true); - SaveToDB(); - break; - case DATA_HORDE_RETREAT: - hordeRetreat = data; - HandleGameObject(ElfGate, true); - SaveToDB(); - break; - case DATA_RAIDDAMAGE: - RaidDamage += data; - if (RaidDamage >= MINRAIDDAMAGE) - RaidDamage = MINRAIDDAMAGE; - break; - case DATA_RESET_RAIDDAMAGE: - RaidDamage = 0; - break; - } - - debug_log("TSCR: Instance Hyjal: Instance data updated for event %u (Data=%u)",type,data); - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] - << " " << allianceRetreat << " " << hordeRetreat - << " " << RaidDamage; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_RAGEWINTERCHILLEVENT: return m_auiEncounter[0]; - case DATA_ANETHERONEVENT: return m_auiEncounter[1]; - case DATA_KAZROGALEVENT: return m_auiEncounter[2]; - case DATA_AZGALOREVENT: return m_auiEncounter[3]; - case DATA_ARCHIMONDEEVENT: return m_auiEncounter[4]; - case DATA_TRASH: return Trash; - case DATA_ALLIANCE_RETREAT: return allianceRetreat; - case DATA_HORDE_RETREAT: return hordeRetreat; - case DATA_RAIDDAMAGE: return RaidDamage; - } - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4] >> allianceRetreat >> hordeRetreat >> RaidDamage; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_mount_hyjal(Map* pMap) -{ - return new instance_mount_hyjal(pMap); -} - -void AddSC_instance_mount_hyjal() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_hyjal"; - newscript->GetInstanceData = &GetInstanceData_instance_mount_hyjal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp deleted file mode 100644 index 91c9e274b83..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Captain_Skarloc -SD%Complete: 75 -SDComment: Missing adds, missing waypoints to move up to Thrall once spawned + speech before enter combat. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define SAY_ENTER -1560000 -#define SAY_TAUNT1 -1560001 -#define SAY_TAUNT2 -1560002 -#define SAY_SLAY1 -1560003 -#define SAY_SLAY2 -1560004 -#define SAY_DEATH -1560005 - -#define SPELL_HOLY_LIGHT 29427 -#define SPELL_CLEANSE 29380 -#define SPELL_HAMMER_OF_JUSTICE 13005 -#define SPELL_HOLY_SHIELD 31904 -#define SPELL_DEVOTION_AURA 8258 -#define SPELL_CONSECRATION 38385 - -struct boss_captain_skarlocAI : public ScriptedAI -{ - boss_captain_skarlocAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Holy_Light_Timer; - uint32 Cleanse_Timer; - uint32 HammerOfJustice_Timer; - uint32 HolyShield_Timer; - uint32 DevotionAura_Timer; - uint32 Consecration_Timer; - - void Reset() - { - Holy_Light_Timer = 20000 + rand()%10000; - Cleanse_Timer = 10000; - HammerOfJustice_Timer = 20000 + rand()%15000; - HolyShield_Timer = 240000; - DevotionAura_Timer = 3000; - Consecration_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - //This is not correct. Should taunt Thrall before engage in combat - DoScriptText(SAY_TAUNT1, me); - DoScriptText(SAY_TAUNT2, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - pInstance->SetData(TYPE_THRALL_PART1, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Holy_Light - if (Holy_Light_Timer <= diff) - { - DoCast(me, SPELL_HOLY_LIGHT); - Holy_Light_Timer = 30000; - } else Holy_Light_Timer -= diff; - - //Cleanse - if (Cleanse_Timer <= diff) - { - DoCast(me, SPELL_CLEANSE); - Cleanse_Timer = 10000; - } else Cleanse_Timer -= diff; - - //Hammer of Justice - if (HammerOfJustice_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); - HammerOfJustice_Timer = 60000; - } else HammerOfJustice_Timer -= diff; - - //Holy Shield - if (HolyShield_Timer <= diff) - { - DoCast(me, SPELL_HOLY_SHIELD); - HolyShield_Timer = 240000; - } else HolyShield_Timer -= diff; - - //Devotion_Aura - if (DevotionAura_Timer <= diff) - { - DoCast(me, SPELL_DEVOTION_AURA); - DevotionAura_Timer = 45000 + rand()%10000; - } else DevotionAura_Timer -= diff; - - //Consecration - if (Consecration_Timer <= diff) - { - //DoCast(me->getVictim(), SPELL_CONSECRATION); - Consecration_Timer = 5000 + rand()%5000; - } else Consecration_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_captain_skarloc(Creature* pCreature) -{ - return new boss_captain_skarlocAI (pCreature); -} - -void AddSC_boss_captain_skarloc() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_captain_skarloc"; - newscript->GetAI = &GetAI_boss_captain_skarloc; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp deleted file mode 100644 index 2c2ad96ddb7..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Epoch_Hunter -SD%Complete: 60 -SDComment: Missing spawns pre-event, missing speech to be coordinated with rest of escort event. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define SAY_ENTER1 -1560013 -#define SAY_ENTER2 -1560014 -#define SAY_ENTER3 -1560015 -#define SAY_AGGRO1 -1560016 -#define SAY_AGGRO2 -1560017 -#define SAY_SLAY1 -1560018 -#define SAY_SLAY2 -1560019 -#define SAY_BREATH1 -1560020 -#define SAY_BREATH2 -1560021 -#define SAY_DEATH -1560022 - -#define SPELL_SAND_BREATH 31914 -#define SPELL_IMPENDING_DEATH 31916 -#define SPELL_MAGIC_DISRUPTION_AURA 33834 -#define SPELL_WING_BUFFET 31475 - -struct boss_epoch_hunterAI : public ScriptedAI -{ - boss_epoch_hunterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SandBreath_Timer; - uint32 ImpendingDeath_Timer; - uint32 WingBuffet_Timer; - uint32 Mda_Timer; - - void Reset() - { - SandBreath_Timer = 8000 + rand()%8000; - ImpendingDeath_Timer = 25000 + rand()%5000; - WingBuffet_Timer = 35000; - Mda_Timer = 40000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2), me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - pInstance->SetData(TYPE_THRALL_PART4, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sand Breath - if (SandBreath_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me->getVictim(), SPELL_SAND_BREATH); - - DoScriptText(RAND(SAY_BREATH1,SAY_BREATH2), me); - - SandBreath_Timer = 10000 + rand()%10000; - } else SandBreath_Timer -= diff; - - if (ImpendingDeath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_IMPENDING_DEATH); - ImpendingDeath_Timer = 25000+rand()%5000; - } else ImpendingDeath_Timer -= diff; - - if (WingBuffet_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_WING_BUFFET); - WingBuffet_Timer = 25000+rand()%10000; - } else WingBuffet_Timer -= diff; - - if (Mda_Timer <= diff) - { - DoCast(me, SPELL_MAGIC_DISRUPTION_AURA); - Mda_Timer = 15000; - } else Mda_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_epoch_hunter(Creature* pCreature) -{ - return new boss_epoch_hunterAI (pCreature); -} - -void AddSC_boss_epoch_hunter() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_epoch_hunter"; - newscript->GetAI = &GetAI_boss_epoch_hunter; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp deleted file mode 100644 index dae0f5390b1..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Luetenant_Drake -SD%Complete: 70 -SDComment: Missing proper code for patrolling area after being spawned. Script for GO (barrels) quest 10283 -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" -#include "ScriptedEscortAI.h" - -/*###### -## go_barrel_old_hillsbrad -######*/ - -bool GOHello_go_barrel_old_hillsbrad(Player* /*pPlayer*/, GameObject* pGO) -{ - if (ScriptedInstance* pInstance = pGO->GetInstanceData()) - { - if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE) - return false; - - pInstance->SetData(TYPE_BARREL_DIVERSION, IN_PROGRESS); - } - - return false; -} - -/*###### -## boss_lieutenant_drake -######*/ - -#define SAY_ENTER -1560006 -#define SAY_AGGRO -1560007 -#define SAY_SLAY1 -1560008 -#define SAY_SLAY2 -1560009 -#define SAY_MORTAL -1560010 -#define SAY_SHOUT -1560011 -#define SAY_DEATH -1560012 - -#define SPELL_WHIRLWIND 31909 -#define SPELL_HAMSTRING 9080 -#define SPELL_MORTAL_STRIKE 31911 -#define SPELL_FRIGHTENING_SHOUT 33789 - -struct Location -{ - uint32 wpId; - float x; - float y; - float z; -}; - -static Location DrakeWP[]= -{ - {0, 2125.84, 88.2535, 54.8830}, - {1, 2111.01, 93.8022, 52.6356}, - {2, 2106.70, 114.753, 53.1965}, - {3, 2107.76, 138.746, 52.5109}, - {4, 2114.83, 160.142, 52.4738}, - {5, 2125.24, 178.909, 52.7283}, - {6, 2151.02, 208.901, 53.1551}, - {7, 2177.00, 233.069, 52.4409}, - {8, 2190.71, 227.831, 53.2742}, - {9, 2178.14, 214.219, 53.0779}, - {10, 2154.99, 202.795, 52.6446}, - {11, 2132.00, 191.834, 52.5709}, - {12, 2117.59, 166.708, 52.7686}, - {13, 2093.61, 139.441, 52.7616}, - {14, 2086.29, 104.950, 52.9246}, - {15, 2094.23, 81.2788, 52.6946}, - {16, 2108.70, 85.3075, 53.3294}, - {17, 2125.50, 88.9481, 54.7953}, - {18, 2128.20, 70.9763, 64.4221} -}; - -struct boss_lieutenant_drakeAI : public ScriptedAI -{ - boss_lieutenant_drakeAI(Creature *c) : ScriptedAI(c) {} - - bool CanPatrol; - uint32 wpId; - - uint32 Whirlwind_Timer; - uint32 Fear_Timer; - uint32 MortalStrike_Timer; - uint32 ExplodingShout_Timer; - - void Reset() - { - CanPatrol = true; - wpId = 0; - - Whirlwind_Timer = 20000; - Fear_Timer = 30000; - MortalStrike_Timer = 45000; - ExplodingShout_Timer = 25000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - //TODO: make this work - if (CanPatrol && wpId == 0) - { - me->GetMotionMaster()->MovePoint(DrakeWP[0].wpId, DrakeWP[0].x, DrakeWP[0].y, DrakeWP[0].z); - ++wpId; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Whirlwind - if (Whirlwind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - Whirlwind_Timer = 20000+rand()%5000; - } else Whirlwind_Timer -= diff; - - //Fear - if (Fear_Timer <= diff) - { - DoScriptText(SAY_SHOUT, me); - DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); - Fear_Timer = 25000+rand()%10000; - } else Fear_Timer -= diff; - - //Mortal Strike - if (MortalStrike_Timer <= diff) - { - DoScriptText(SAY_MORTAL, me); - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - MortalStrike_Timer = 20000+rand()%10000; - } else MortalStrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_lieutenant_drake(Creature* pCreature) -{ - return new boss_lieutenant_drakeAI (pCreature); -} - -void AddSC_boss_lieutenant_drake() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_barrel_old_hillsbrad"; - newscript->pGOHello = &GOHello_go_barrel_old_hillsbrad; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lieutenant_drake"; - newscript->GetAI = &GetAI_boss_lieutenant_drake; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp deleted file mode 100644 index fa0b7c14595..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Old_Hillsbrad -SD%Complete: 75 -SDComment: If thrall escort fail, all parts will reset. In future, save sub-parts and continue from last known. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define MAX_ENCOUNTER 6 - -#define THRALL_ENTRY 17876 -#define TARETHA_ENTRY 18887 -#define EPOCH_ENTRY 18096 - -#define DRAKE_ENTRY 17848 - -#define QUEST_ENTRY_DIVERSION 10283 -#define LODGE_QUEST_TRIGGER 20155 - -struct instance_old_hillsbrad : public ScriptedInstance -{ - instance_old_hillsbrad(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 mBarrelCount; - uint32 mThrallEventCount; - - uint64 ThrallGUID; - uint64 TarethaGUID; - uint64 EpochGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - mBarrelCount = 0; - mThrallEventCount = 0; - ThrallGUID = 0; - TarethaGUID = 0; - EpochGUID = 0; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - - debug_log("TSCR: Instance Old Hillsbrad: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void UpdateQuestCredit() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->KilledMonsterCredit(LODGE_QUEST_TRIGGER,0); - } - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case THRALL_ENTRY: - ThrallGUID = pCreature->GetGUID(); - break; - case TARETHA_ENTRY: - TarethaGUID = pCreature->GetGUID(); - break; - case EPOCH_ENTRY: - EpochGUID = pCreature->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - Player* pPlayer = GetPlayerInMap(); - - if (!pPlayer) - { - debug_log("TSCR: Instance Old Hillsbrad: SetData (Type: %u Data %u) cannot find any player.", type, data); - return; - } - - switch(type) - { - case TYPE_BARREL_DIVERSION: - { - if (data == IN_PROGRESS) - { - if (mBarrelCount >= 5) - return; - - ++mBarrelCount; - DoUpdateWorldState(WORLD_STATE_OH, mBarrelCount); - - debug_log("TSCR: Instance Old Hillsbrad: go_barrel_old_hillsbrad count %u",mBarrelCount); - - m_auiEncounter[0] = IN_PROGRESS; - - if (mBarrelCount == 5) - { - UpdateQuestCredit(); - pPlayer->SummonCreature(DRAKE_ENTRY, 2128.43, 71.01, 64.42, 1.74, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000); - m_auiEncounter[0] = DONE; - } - } - break; - } - case TYPE_THRALL_EVENT: - { - if (data == FAIL) - { - if (mThrallEventCount <= 20) - { - ++mThrallEventCount; - m_auiEncounter[1] = NOT_STARTED; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); - m_auiEncounter[2] = NOT_STARTED; - m_auiEncounter[3] = NOT_STARTED; - m_auiEncounter[4] = NOT_STARTED; - m_auiEncounter[5] = NOT_STARTED; - } - else if (mThrallEventCount > 20) - { - m_auiEncounter[1] = data; - m_auiEncounter[2] = data; - m_auiEncounter[3] = data; - m_auiEncounter[4] = data; - m_auiEncounter[5] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); - } - } - else - m_auiEncounter[1] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall escort event adjusted to data %u.",data); - break; - } - case TYPE_THRALL_PART1: - m_auiEncounter[2] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part I adjusted to data %u.",data); - break; - case TYPE_THRALL_PART2: - m_auiEncounter[3] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part II adjusted to data %u.",data); - break; - case TYPE_THRALL_PART3: - m_auiEncounter[4] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part III adjusted to data %u.",data); - break; - case TYPE_THRALL_PART4: - m_auiEncounter[5] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part IV adjusted to data %u.",data); - break; - } - } - - uint32 GetData(uint32 data) - { - switch(data) - { - case TYPE_BARREL_DIVERSION: - return m_auiEncounter[0]; - case TYPE_THRALL_EVENT: - return m_auiEncounter[1]; - case TYPE_THRALL_PART1: - return m_auiEncounter[2]; - case TYPE_THRALL_PART2: - return m_auiEncounter[3]; - case TYPE_THRALL_PART3: - return m_auiEncounter[4]; - case TYPE_THRALL_PART4: - return m_auiEncounter[5]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THRALL: - return ThrallGUID; - case DATA_TARETHA: - return TarethaGUID; - case DATA_EPOCH: - return EpochGUID; - } - return 0; - } -}; -InstanceData* GetInstanceData_instance_old_hillsbrad(Map* pMap) -{ - return new instance_old_hillsbrad(pMap); -} - -void AddSC_instance_old_hillsbrad() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_old_hillsbrad"; - newscript->GetInstanceData = &GetInstanceData_instance_old_hillsbrad; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp deleted file mode 100644 index 08c63954db5..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp +++ /dev/null @@ -1,658 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Old_Hillsbrad -SD%Complete: 40 -SDComment: Quest support: 10283, 10284. All friendly NPC's. Thrall waypoints fairly complete, missing many details, but possible to complete escort. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -/* ContentData -npc_erozion -npc_thrall_old_hillsbrad -npc_taretha -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "old_hillsbrad.h" - -#define QUEST_ENTRY_HILLSBRAD 10282 -#define QUEST_ENTRY_DIVERSION 10283 -#define QUEST_ENTRY_ESCAPE 10284 -#define QUEST_ENTRY_RETURN 10285 -#define ITEM_ENTRY_BOMBS 25853 - -#define GOSSIP_HELLO_EROZION1 "I need a pack of Incendiary Bombs." -#define GOSSIP_HELLO_EROZION2 "[PH] Teleport please, i'm tired." - -/*###### -## npc_erozion -######*/ - -bool GossipHello_npc_erozion(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance && pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE && !pPlayer->HasItemCount(ITEM_ENTRY_BOMBS,1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - if (!pPlayer->GetQuestRewardStatus(QUEST_ENTRY_RETURN) && pPlayer->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(9778, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_erozion(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_ENTRY_BOMBS, 1); - if (msg == EQUIP_ERR_OK) - { - pPlayer->StoreNewItem(dest, ITEM_ENTRY_BOMBS, true); - } - pPlayer->SEND_GOSSIP_MENU(9515, pCreature->GetGUID()); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - } - return true; -} - -/*###### -## npc_thrall_old_hillsbrad -######*/ - -//Thrall texts -#define SAY_TH_START_EVENT_PART1 -1560023 -#define SAY_TH_ARMORY -1560024 -#define SAY_TH_SKARLOC_MEET -1560025 -#define SAY_TH_SKARLOC_TAUNT -1560026 -#define SAY_TH_START_EVENT_PART2 -1560027 -#define SAY_TH_MOUNTS_UP -1560028 -#define SAY_TH_CHURCH_END -1560029 -#define SAY_TH_MEET_TARETHA -1560030 -#define SAY_TH_EPOCH_WONDER -1560031 -#define SAY_TH_EPOCH_KILL_TARETHA -1560032 -#define SAY_TH_EVENT_COMPLETE -1560033 - -#define SAY_TH_RANDOM_LOW_HP1 -1560034 -#define SAY_TH_RANDOM_LOW_HP2 -1560035 - -#define SAY_TH_RANDOM_DIE1 -1560036 -#define SAY_TH_RANDOM_DIE2 -1560037 - -#define SAY_TH_RANDOM_AGGRO1 -1560038 -#define SAY_TH_RANDOM_AGGRO2 -1560039 -#define SAY_TH_RANDOM_AGGRO3 -1560040 -#define SAY_TH_RANDOM_AGGRO4 -1560041 - -#define SAY_TH_RANDOM_KILL1 -1560042 -#define SAY_TH_RANDOM_KILL2 -1560043 -#define SAY_TH_RANDOM_KILL3 -1560044 - -#define SAY_TH_LEAVE_COMBAT1 -1560045 -#define SAY_TH_LEAVE_COMBAT2 -1560046 -#define SAY_TH_LEAVE_COMBAT3 -1560047 - -//Taretha texts -#define SAY_TA_FREE -1560048 -#define SAY_TA_ESCAPED -1560049 - -//Misc for Thrall -#define SPELL_STRIKE 14516 -#define SPELL_SHIELD_BLOCK 12169 -#define SPELL_SUMMON_EROZION_IMAGE 33954 //if thrall dies during escort? - -#define SPEED_WALK (0.5f) -#define SPEED_RUN (1.0f) -#define SPEED_MOUNT (1.6f) - -#define THRALL_WEAPON_MODEL 22106 -#define THRALL_WEAPON_INFO 218169346 -#define THRALL_SHIELD_MODEL 18662 -#define THRALL_SHIELD_INFO 234948100 -#define THRALL_MODEL_UNEQUIPPED 17292 -#define THRALL_MODEL_EQUIPPED 18165 - -//Misc Creature entries -#define ENTRY_ARMORER 18764 -#define ENTRY_SCARLOC 17862 - -#define MOB_ENTRY_RIFLE 17820 -#define MOB_ENTRY_WARDEN 17833 -#define MOB_ENTRY_VETERAN 17860 -#define MOB_ENTRY_WATCHMAN 17814 -#define MOB_ENTRY_SENTRY 17815 - -#define MOB_ENTRY_BARN_GUARDSMAN 18092 -#define MOB_ENTRY_BARN_PROTECTOR 18093 -#define MOB_ENTRY_BARN_LOOKOUT 18094 - -#define MOB_ENTRY_CHURCH_GUARDSMAN 23175 -#define MOB_ENTRY_CHURCH_PROTECTOR 23179 -#define MOB_ENTRY_CHURCH_LOOKOUT 23177 - -#define MOB_ENTRY_INN_GUARDSMAN 23176 -#define MOB_ENTRY_INN_PROTECTOR 23180 -#define MOB_ENTRY_INN_LOOKOUT 23178 - -#define SKARLOC_MOUNT 18798 -#define SKARLOC_MOUNT_MODEL 18223 -#define EROZION_ENTRY 18723 -#define ENTRY_EPOCH 18096 - -//gossip items -#define GOSSIP_ID_START 9568 -#define GOSSIP_ID_SKARLOC1 9614 //I'm glad Taretha is alive. We now must find a way to free her... -#define GOSSIP_ITEM_SKARLOC1 "Taretha cannot see you, Thrall." -#define GOSSIP_ID_SKARLOC2 9579 //What do you mean by this? Is Taretha in danger? -#define GOSSIP_ITEM_SKARLOC2 "The situation is rather complicated, Thrall. It would be best for you to head into the mountains now, before more of Blackmoore's men show up. We'll make sure Taretha is safe." -#define GOSSIP_ID_SKARLOC3 9580 - -#define GOSSIP_ID_TARREN 9597 //tarren mill is beyond these trees -#define GOSSIP_ITEM_TARREN "We're ready, Thrall." - -#define GOSSIP_ID_COMPLETE 9578 //Thank you friends, I owe my freedom to you. Where is Taretha? I hoped to see her - -#define GOSSIP_ITEM_WALKING "[PH] Start walking." - -struct npc_thrall_old_hillsbradAI : public npc_escortAI -{ - npc_thrall_old_hillsbradAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - HadMount = false; - me->setActive(true); - } - - ScriptedInstance *pInstance; - - uint64 TarethaGUID; - - bool LowHp; - bool HadMount; - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch(i) - { - case 8: - SetRun(false); - me->SummonCreature(18764,2181.87,112.46,89.45,0.26,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 9: - DoScriptText(SAY_TH_ARMORY, me); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_MODEL); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_MODEL); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); - break; - case 10: - me->SetDisplayId(THRALL_MODEL_EQUIPPED); - break; - case 11: - SetRun(); - break; - case 15: - me->SummonCreature(MOB_ENTRY_RIFLE,2200.28,137.37,87.93,5.07,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2197.44,131.83,87.93,0.78,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2203.62,135.40,87.93,3.70,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2200.75,130.13,87.93,1.48,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 21: - me->SummonCreature(MOB_ENTRY_RIFLE,2135.80,154.01,67.45,4.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2144.36,151.87,67.74,4.46,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2142.12,154.41,67.12,4.56,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2138.08,155.38,67.24,4.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 25: - me->SummonCreature(MOB_ENTRY_RIFLE,2102.98,192.17,65.24,6.02,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2108.48,198.75,65.18,5.15,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2106.11,197.29,65.18,5.63,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2104.18,194.82,65.18,5.75,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 29: - DoScriptText(SAY_TH_SKARLOC_MEET, me); - me->SummonCreature(ENTRY_SCARLOC,2036.48,271.22,63.43,5.27,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - //temporary,skarloc should rather be triggered to walk up to thrall - break; - case 30: - SetEscortPaused(true); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetRun(false); - break; - case 31: - DoScriptText(SAY_TH_MOUNTS_UP, me); - DoMount(); - SetRun(); - break; - case 37: - //possibly regular patrollers? If so, remove this and let database handle them - me->SummonCreature(MOB_ENTRY_WATCHMAN,2124.26,522.16,56.87,3.99,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WATCHMAN,2121.69,525.37,57.11,4.01,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_SENTRY,2124.65,524.55,56.63,3.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 59: - me->SummonCreature(SKARLOC_MOUNT,2488.64,625.77,58.26,4.71,TEMPSUMMON_TIMED_DESPAWN,10000); - DoUnmount(); - HadMount = false; - SetRun(false); - break; - case 60: - me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); - //make horsie run off - SetEscortPaused(true); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pInstance->SetData(TYPE_THRALL_PART2, DONE); - SetRun(); - break; - case 64: - SetRun(false); - break; - case 68: - me->SummonCreature(MOB_ENTRY_BARN_PROTECTOR,2500.22,692.60,55.50,2.84,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_LOOKOUT,2500.13,696.55,55.51,3.38,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.55,693.64,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.94,695.81,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 71: - SetRun(); - break; - case 81: - SetRun(false); - break; - case 83: - me->SummonCreature(MOB_ENTRY_CHURCH_PROTECTOR,2627.33,646.82,56.03,4.28,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_LOOKOUT,2624.14,648.03,56.03,4.50,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2625.32,649.60,56.03,4.38,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2627.22,649.00,56.03,4.34,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - break; - case 84: - DoScriptText(SAY_TH_CHURCH_END, me); - SetRun(); - break; - case 91: - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - SetRun(false); - break; - case 93: - me->SummonCreature(MOB_ENTRY_INN_PROTECTOR,2652.71,660.31,61.93,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_LOOKOUT,2648.96,662.59,61.93,0.79,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2657.36,662.34,61.93,2.68,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2656.39,659.77,61.93,2.61,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 94: - if (uint64 TarethaGUID = pInstance->GetData64(DATA_TARETHA)) - { - if (Unit* Taretha = Unit::GetUnit((*me), TarethaGUID)) - DoScriptText(SAY_TA_ESCAPED, Taretha, me); - } - break; - case 95: - DoScriptText(SAY_TH_MEET_TARETHA, me); - pInstance->SetData(TYPE_THRALL_PART3,DONE); - SetEscortPaused(true); - break; - case 96: - DoScriptText(SAY_TH_EPOCH_WONDER, me); - break; - case 97: - DoScriptText(SAY_TH_EPOCH_KILL_TARETHA, me); - SetRun(); - break; - case 98: - //trigger epoch Yell("Thrall! Come outside and face your fate! ....") - //from here, thrall should not never be allowed to move to point 106 which he currently does. - break; - - case 106: - { - //trigger taretha to run down outside - if (Creature* Taretha = pInstance->instance->GetCreature(pInstance->GetData64(DATA_TARETHA))) - { - if (Player* pPlayer = GetPlayerForEscort()) - CAST_AI(npc_escortAI, (Taretha->AI()))->Start(false, true, pPlayer->GetGUID()); - } - - //kill credit Creature for quest - Map* pMap = me->GetMap(); - Map::PlayerList const& players = pMap->GetPlayers(); - if (!players.isEmpty() && pMap->IsDungeon()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->KilledMonsterCredit(20156,me->GetGUID()); - } - } - - //alot will happen here, thrall and taretha talk, erozion appear at spot to explain - me->SummonCreature(EROZION_ENTRY,2646.47,680.416,55.38,4.16,TEMPSUMMON_TIMED_DESPAWN,120000); - } - break; - case 108: - //last waypoint, just set Thrall invisible, respawn is turned off - me->SetVisibility(VISIBILITY_OFF); - break; - } - } - - void Reset() - { - LowHp = false; - - if (HadMount) - DoMount(); - - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - DoUnmount(); - HadMount = false; - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - me->SetDisplayId(THRALL_MODEL_UNEQUIPPED); - } - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - DoScriptText(RAND(SAY_TH_LEAVE_COMBAT1,SAY_TH_LEAVE_COMBAT2,SAY_TH_LEAVE_COMBAT3), me); - } - } - void StartWP() - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetEscortPaused(false); - } - void DoMount() - { - me->Mount(SKARLOC_MOUNT_MODEL); - me->SetSpeed(MOVE_RUN,SPEED_MOUNT); - } - void DoUnmount() - { - me->Unmount(); - me->SetSpeed(MOVE_RUN,SPEED_RUN); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(RAND(SAY_TH_RANDOM_AGGRO1,SAY_TH_RANDOM_AGGRO2,SAY_TH_RANDOM_AGGRO3,SAY_TH_RANDOM_AGGRO4), me); - if (me->IsMounted()) - { - DoUnmount(); - HadMount = true; - } - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - //TODO: make Scarloc start into event instead, and not start attack directly - case MOB_ENTRY_BARN_GUARDSMAN: - case MOB_ENTRY_BARN_PROTECTOR: - case MOB_ENTRY_BARN_LOOKOUT: - case SKARLOC_MOUNT: - case EROZION_ENTRY: - break; - default: - summoned->AI()->AttackStart(me); - break; - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_TH_RANDOM_KILL1,SAY_TH_RANDOM_KILL2,SAY_TH_RANDOM_KILL3), me); - } - void JustDied(Unit *slayer) - { - if (pInstance) - pInstance->SetData(TYPE_THRALL_EVENT,FAIL); - - // Don't do a yell if he kills self (if player goes too far or at the end). - if (slayer == me) - return; - - DoScriptText(RAND(SAY_TH_RANDOM_DIE1,SAY_TH_RANDOM_DIE2), me); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - //TODO: add his abilities'n-crap here - if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) - { - DoScriptText(RAND(SAY_TH_RANDOM_LOW_HP1,SAY_TH_RANDOM_LOW_HP2), me); - LowHp = true; - } - } -}; - -CreatureAI* GetAI_npc_thrall_old_hillsbrad(Creature* pCreature) -{ - return new npc_thrall_old_hillsbradAI(pCreature); -} - -bool GossipHello_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - { - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - pPlayer->SendPreparedQuest(pCreature->GetGUID()); - } - - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance) - { - if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE && !pInstance->GetData(TYPE_THRALL_EVENT)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WALKING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START, pCreature->GetGUID()); - } - - if (pInstance->GetData(TYPE_THRALL_PART1) == DONE && !pInstance->GetData(TYPE_THRALL_PART2)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC1, pCreature->GetGUID()); - } - - if (pInstance->GetData(TYPE_THRALL_PART2) == DONE && !pInstance->GetData(TYPE_THRALL_PART3)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TARREN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_TARREN, pCreature->GetGUID()); - } - } - return true; -} - -bool GossipSelect_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pInstance) - { - pInstance->SetData(TYPE_THRALL_EVENT,IN_PROGRESS); - pInstance->SetData(TYPE_THRALL_PART1,IN_PROGRESS); - } - - DoScriptText(SAY_TH_START_EVENT_PART1, pCreature); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())) - pEscortAI->Start(true, true, pPlayer->GetGUID()); - - CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(100.0f);//not really needed, because it will not despawn if player is too far - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); - break; - - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC2, pCreature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+20: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC3, pCreature->GetGUID()); - pCreature->SummonCreature(SKARLOC_MOUNT,2038.81,270.26,63.20,5.41,TEMPSUMMON_TIMED_DESPAWN,12000); - if (pInstance) - pInstance->SetData(TYPE_THRALL_PART2,IN_PROGRESS); - - DoScriptText(SAY_TH_START_EVENT_PART2, pCreature); - - CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); - break; - - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pInstance) - pInstance->SetData(TYPE_THRALL_PART3,IN_PROGRESS); - CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); - break; - } - return true; -} - -/*###### -## npc_taretha -######*/ - -#define GOSSIP_ID_EPOCH1 9610 //Thank you for helping Thrall escape, friends. Now I only hope -#define GOSSIP_ITEM_EPOCH1 "Strange wizard?" -#define GOSSIP_ID_EPOCH2 9613 //Yes, friends. This man was no wizard of -#define GOSSIP_ITEM_EPOCH2 "We'll get you out. Taretha. Don't worry. I doubt the wizard would wander too far away." - -struct npc_tarethaAI : public npc_escortAI -{ - npc_tarethaAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void WaypointReached(uint32 i) - { - switch(i) - { - case 6: - DoScriptText(SAY_TA_FREE, me); - break; - case 7: - me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); - break; - } - } - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_taretha(Creature* pCreature) -{ - return new npc_tarethaAI(pCreature); -} - -bool GossipHello_npc_taretha(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance && pInstance->GetData(TYPE_THRALL_PART3) == DONE && pInstance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH1, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_taretha(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH2, pCreature->GetGUID()); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - { - pInstance->SetData(TYPE_THRALL_PART4,IN_PROGRESS); - if (pInstance->GetData64(DATA_EPOCH) == 0) - pCreature->SummonCreature(ENTRY_EPOCH,2639.13,698.55,65.43,4.59,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); - - if (uint64 ThrallGUID = pInstance->GetData64(DATA_THRALL)) - { - Creature* Thrall = (Unit::GetCreature((*pCreature), ThrallGUID)); - if (Thrall) - CAST_AI(npc_thrall_old_hillsbradAI, Thrall->AI())->StartWP(); - } - } - } - return true; -} - -/*###### -## AddSC -######*/ - -void AddSC_old_hillsbrad() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_erozion"; - newscript->pGossipHello = &GossipHello_npc_erozion; - newscript->pGossipSelect = &GossipSelect_npc_erozion; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thrall_old_hillsbrad"; - newscript->pGossipHello = &GossipHello_npc_thrall_old_hillsbrad; - newscript->pGossipSelect = &GossipSelect_npc_thrall_old_hillsbrad; - newscript->GetAI = &GetAI_npc_thrall_old_hillsbrad; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_taretha"; - newscript->pGossipHello = &GossipHello_npc_taretha; - newscript->pGossipSelect = &GossipSelect_npc_taretha; - newscript->GetAI = &GetAI_npc_taretha; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h b/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h deleted file mode 100644 index 5c398cc2647..00000000000 --- a/src/server/scripts/Kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_OLD_HILLSBRAD_H -#define DEF_OLD_HILLSBRAD_H - -#define TYPE_BARREL_DIVERSION 1 -#define TYPE_THRALL_EVENT 2 -#define TYPE_THRALL_PART1 3 -#define TYPE_THRALL_PART2 4 -#define TYPE_THRALL_PART3 5 -#define TYPE_THRALL_PART4 6 -#define DATA_THRALL 7 -#define DATA_TARETHA 8 -#define DATA_EPOCH 9 -#define WORLD_STATE_OH 2436 -#endif - diff --git a/src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp b/src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp deleted file mode 100644 index 6f6b9d1baa9..00000000000 --- a/src/server/scripts/Kalimdor/maraudon/boss_celebras_the_cursed.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Celebras_the_Cursed -SD%Complete: 100 -SDComment: -SDCategory: Maraudon -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_WRATH 21807 -#define SPELL_ENTANGLINGROOTS 12747 -#define SPELL_CORRUPT_FORCES 21968 - -struct celebras_the_cursedAI : public ScriptedAI -{ - celebras_the_cursedAI(Creature *c) : ScriptedAI(c) {} - - uint32 Wrath_Timer; - uint32 EntanglingRoots_Timer; - uint32 CorruptForces_Timer; - - void Reset() - { - Wrath_Timer = 8000; - EntanglingRoots_Timer = 2000; - CorruptForces_Timer = 30000; - } - - void EnterCombat(Unit * /*who*/) { } - - void JustDied(Unit* /*Killer*/) - { - me->SummonCreature(13716, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Wrath - if (Wrath_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - DoCast(pTarget, SPELL_WRATH); - Wrath_Timer = 8000; - } else Wrath_Timer -= diff; - - //EntanglingRoots - if (EntanglingRoots_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ENTANGLINGROOTS); - EntanglingRoots_Timer = 20000; - } else EntanglingRoots_Timer -= diff; - - //CorruptForces - if (CorruptForces_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_CORRUPT_FORCES); - CorruptForces_Timer = 20000; - } else CorruptForces_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_celebras_the_cursed(Creature* pCreature) -{ - return new celebras_the_cursedAI (pCreature); -} - -void AddSC_boss_celebras_the_cursed() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "celebras_the_cursed"; - newscript->GetAI = &GetAI_celebras_the_cursed; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp b/src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp deleted file mode 100644 index d5b03ff218f..00000000000 --- a/src/server/scripts/Kalimdor/maraudon/boss_landslide.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Landslide -SD%Complete: 100 -SDComment: -SDCategory: Maraudon -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_KNOCKAWAY 18670 -#define SPELL_TRAMPLE 5568 -#define SPELL_LANDSLIDE 21808 - -struct boss_landslideAI : public ScriptedAI -{ - boss_landslideAI(Creature *c) : ScriptedAI(c) {} - - uint32 KnockAway_Timer; - uint32 Trample_Timer; - uint32 Landslide_Timer; - - void Reset() - { - KnockAway_Timer = 8000; - Trample_Timer = 2000; - Landslide_Timer = 0; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //KnockAway_Timer - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - KnockAway_Timer = 15000; - } else KnockAway_Timer -= diff; - - //Trample_Timer - if (Trample_Timer <= diff) - { - DoCast(me, SPELL_TRAMPLE); - Trample_Timer = 8000; - } else Trample_Timer -= diff; - - //Landslide - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - if (Landslide_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_LANDSLIDE); - Landslide_Timer = 60000; - } else Landslide_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_landslide(Creature* pCreature) -{ - return new boss_landslideAI (pCreature); -} - -void AddSC_boss_landslide() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_landslide"; - newscript->GetAI = &GetAI_boss_landslide; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp b/src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp deleted file mode 100644 index b49b1a5d71f..00000000000 --- a/src/server/scripts/Kalimdor/maraudon/boss_noxxion.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Noxxion -SD%Complete: 100 -SDComment: -SDCategory: Maraudon -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_TOXICVOLLEY 21687 -#define SPELL_UPPERCUT 22916 - -struct boss_noxxionAI : public ScriptedAI -{ - boss_noxxionAI(Creature *c) : ScriptedAI(c) {} - - uint32 ToxicVolley_Timer; - uint32 Uppercut_Timer; - uint32 Adds_Timer; - uint32 Invisible_Timer; - bool Invisible; - - void Reset() - { - ToxicVolley_Timer = 7000; - Uppercut_Timer = 16000; - Adds_Timer = 19000; - Invisible_Timer = 15000; //Too much too low? - Invisible = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void SummonAdds(Unit* pVictim) - { - if (Creature *Add = DoSpawnCreature(13456, irand(-7,7), irand(-7,7), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 90000)) - Add->AI()->AttackStart(pVictim); - } - - void UpdateAI(const uint32 diff) - { - if (Invisible && Invisible_Timer <= diff) - { - //Become visible again - me->setFaction(14); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //Noxxion model - me->SetDisplayId(11172); - Invisible = false; - //me->m_canMove = true; - } else if (Invisible) - { - Invisible_Timer -= diff; - //Do nothing while invisible - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //ToxicVolley_Timer - if (ToxicVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TOXICVOLLEY); - ToxicVolley_Timer = 9000; - } else ToxicVolley_Timer -= diff; - - //Uppercut_Timer - if (Uppercut_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_UPPERCUT); - Uppercut_Timer = 12000; - } else Uppercut_Timer -= diff; - - //Adds_Timer - if (!Invisible && Adds_Timer <= diff) - { - //Inturrupt any spell casting - //me->m_canMove = true; - me->InterruptNonMeleeSpells(false); - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // Invisible Model - me->SetDisplayId(11686); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - SummonAdds(me->getVictim()); - Invisible = true; - Invisible_Timer = 15000; - - Adds_Timer = 40000; - } else Adds_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_noxxion(Creature* pCreature) -{ - return new boss_noxxionAI (pCreature); -} - -void AddSC_boss_noxxion() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_noxxion"; - newscript->GetAI = &GetAI_boss_noxxion; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp b/src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp deleted file mode 100644 index 963863e89c8..00000000000 --- a/src/server/scripts/Kalimdor/maraudon/boss_princess_theradras.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Princess_Theradras -SD%Complete: 100 -SDComment: -SDCategory: Maraudon -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_DUSTFIELD 21909 -#define SPELL_BOULDER 21832 -#define SPELL_THRASH 3391 -#define SPELL_REPULSIVEGAZE 21869 - -struct boss_ptheradrasAI : public ScriptedAI -{ - boss_ptheradrasAI(Creature *c) : ScriptedAI(c) {} - - uint32 Dustfield_Timer; - uint32 Boulder_Timer; - uint32 Thrash_Timer; - uint32 RepulsiveGaze_Timer; - - void Reset() - { - Dustfield_Timer = 8000; - Boulder_Timer = 2000; - Thrash_Timer = 5000; - RepulsiveGaze_Timer = 23000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*killer*/) - { - me->SummonCreature(12238,28.067,61.875,-123.405,4.67,TEMPSUMMON_TIMED_DESPAWN,600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Dustfield_Timer - if (Dustfield_Timer <= diff) - { - DoCast(me, SPELL_DUSTFIELD); - Dustfield_Timer = 14000; - } else Dustfield_Timer -= diff; - - //Boulder_Timer - if (Boulder_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - DoCast(pTarget, SPELL_BOULDER); - Boulder_Timer = 10000; - } else Boulder_Timer -= diff; - - //RepulsiveGaze_Timer - if (RepulsiveGaze_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REPULSIVEGAZE); - RepulsiveGaze_Timer = 20000; - } else RepulsiveGaze_Timer -= diff; - - //Thrash_Timer - if (Thrash_Timer <= diff) - { - DoCast(me, SPELL_THRASH); - Thrash_Timer = 18000; - } else Thrash_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ptheradras(Creature* pCreature) -{ - return new boss_ptheradrasAI (pCreature); -} - -void AddSC_boss_ptheradras() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_princess_theradras"; - newscript->GetAI = &GetAI_boss_ptheradras; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp deleted file mode 100644 index 2d351d6c6a2..00000000000 --- a/src/server/scripts/Kalimdor/onyxias_lair/boss_onyxia.cpp +++ /dev/null @@ -1,500 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Onyxia -SD%Complete: 95 -SDComment: - Ground visual for Deep Breath effect; - Wing Buffet not ignoring armor; - Not summoning whelps on phase 3 (lacks info) - -SDCategory: Onyxia's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "onyxias_lair.h" - -enum eYells -{ - SAY_AGGRO = -1249000, - SAY_KILL = -1249001, - SAY_PHASE_2_TRANS = -1249002, - SAY_PHASE_3_TRANS = -1249003, - EMOTE_BREATH = -1249004, -}; - -enum eSpells -{ - // Phase 1 spells - SPELL_WING_BUFFET = 18500, - SPELL_FLAME_BREATH = 18435, - SPELL_CLEAVE = 68868, - SPELL_TAIL_SWEEP = 68867, - - // Phase 2 spells - SPELL_DEEP_BREATH = 23461, - SPELL_FIREBALL = 18392, - - //Not much choise about these. We have to make own defintion on the direction/start-end point - SPELL_BREATH_NORTH_TO_SOUTH = 17086, // 20x in "array" - SPELL_BREATH_SOUTH_TO_NORTH = 18351, // 11x in "array" - - SPELL_BREATH_EAST_TO_WEST = 18576, // 7x in "array" - SPELL_BREATH_WEST_TO_EAST = 18609, // 7x in "array" - - SPELL_BREATH_SE_TO_NW = 18564, // 12x in "array" - SPELL_BREATH_NW_TO_SE = 18584, // 12x in "array" - SPELL_BREATH_SW_TO_NE = 18596, // 12x in "array" - SPELL_BREATH_NE_TO_SW = 18617, // 12x in "array" - - //SPELL_BREATH = 21131, // 8x in "array", different initial cast than the other arrays - - // Phase 3 spells - SPELL_BELLOWING_ROAR = 18431, -}; - -struct sOnyxMove -{ - uint32 uiLocId; - uint32 uiLocIdEnd; - uint32 uiSpellId; - float fX, fY, fZ; -}; - -static sOnyxMove aMoveData[]= -{ - {0, 1, SPELL_BREATH_WEST_TO_EAST, -33.5561f, -182.682f, -56.9457f},//west - {1, 0, SPELL_BREATH_EAST_TO_WEST, -31.4963f, -250.123f, -55.1278f},//east - {2, 4, SPELL_BREATH_NW_TO_SE, 6.8951f, -180.246f, -55.896f},//north-west - {3, 5, SPELL_BREATH_NE_TO_SW, 10.2191f, -247.912f, -55.896f},//north-east - {4, 2, SPELL_BREATH_SE_TO_NW, -63.5156f, -240.096f, -55.477f},//south-east - {5, 3, SPELL_BREATH_SW_TO_NE, -58.2509f, -189.020f, -55.790f},//south-west - {6, 7, SPELL_BREATH_SOUTH_TO_NORTH, -65.8444f, -213.809f, -55.2985f},//south - {7, 6, SPELL_BREATH_NORTH_TO_SOUTH, 22.8763f, -217.152f, -55.0548f},//north -}; - -const Position MiddleRoomLocation = {-23.6155, -215.357, -55.7344}; - -static Position aSpawnLocations[3]= -{ - //Whelps - {-30.127, -254.463, -89.440}, - {-30.817, -177.106, -89.258}, - //Lair Guard - {-145.950, -212.831, -68.659} -}; - -struct boss_onyxiaAI : public ScriptedAI -{ - boss_onyxiaAI(Creature* pCreature) : ScriptedAI(pCreature), Summons(me) - { - m_pInstance = pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* m_pInstance; - SummonList Summons; - - uint32 m_uiPhase; - - uint32 m_uiFlameBreathTimer; - uint32 m_uiCleaveTimer; - uint32 m_uiTailSweepTimer; - uint32 m_uiWingBuffetTimer; - - uint32 m_uiMovePoint; - uint32 m_uiMovementTimer; - sOnyxMove* m_pPointData; - - uint32 m_uiFireballTimer; - uint32 m_uiWhelpTimer; - uint32 m_uiLairGuardTimer; - uint32 m_uiDeepBreathTimer; - - uint32 m_uiBellowingRoarTimer; - - uint8 m_uiSummonWhelpCount; - uint8 m_uiSummonLairGuardCount; - bool m_bIsMoving; - - void Reset() - { - if (!IsCombatMovement()) - SetCombatMovement(true); - - m_uiPhase = PHASE_START; - - m_uiFlameBreathTimer = urand(10000, 20000); - m_uiTailSweepTimer = urand(15000, 20000); - m_uiCleaveTimer = urand(2000, 5000); - m_uiWingBuffetTimer = urand(10000, 20000); - - m_uiMovePoint = urand(0, 5); - m_uiMovementTimer = 20000; - m_pPointData = GetMoveData(); - - m_uiFireballTimer = 15000; - m_uiWhelpTimer = 1000; - m_uiLairGuardTimer = 15000; - m_uiDeepBreathTimer = 85000; - - m_uiBellowingRoarTimer = 30000; - - Summons.DespawnAll(); - m_uiSummonWhelpCount = 0; - m_uiSummonLairGuardCount = 0; - m_bIsMoving = false; - - if (m_pInstance) - { - m_pInstance->SetData(DATA_ONYXIA, NOT_STARTED); - m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void EnterCombat(Unit* pWho) - { - DoScriptText(SAY_AGGRO, me); - me->SetInCombatWithZone(); - - if (m_pInstance) - { - m_pInstance->SetData(DATA_ONYXIA, IN_PROGRESS); - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - sLog.outBasic("[Onyxia] DoStartTimedAchievement(%u,%u)",ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void JustDied(Unit* killer) - { - if (m_pInstance) - m_pInstance->SetData(DATA_ONYXIA, DONE); - - Summons.DespawnAll(); - } - - void JustSummoned(Creature *pSummoned) - { - pSummoned->SetInCombatWithZone(); - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - pSummoned->AI()->AttackStart(pTarget); - - switch (pSummoned->GetEntry()) - { - case NPC_WHELP: - ++m_uiSummonWhelpCount; - break; - case NPC_LAIRGUARD: - pSummoned->setActive(true); - ++m_uiSummonLairGuardCount; - break; - } - Summons.Summon(pSummoned); - } - - void SummonedCreatureDespawn(Creature *summon) - { - Summons.Despawn(summon); - } - - void KilledUnit(Unit* pVictim) - { - DoScriptText(SAY_KILL, me); - } - - void SpellHit(Unit *pCaster, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_BREATH_EAST_TO_WEST || - pSpell->Id == SPELL_BREATH_WEST_TO_EAST || - pSpell->Id == SPELL_BREATH_SE_TO_NW || - pSpell->Id == SPELL_BREATH_NW_TO_SE || - pSpell->Id == SPELL_BREATH_SW_TO_NE || - pSpell->Id == SPELL_BREATH_NE_TO_SW) - { - m_pPointData = GetMoveData(); - m_uiMovePoint = m_pPointData->uiLocIdEnd; - - me->SetSpeed(MOVE_FLIGHT, 1.5f); - me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation); - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type == POINT_MOTION_TYPE) - { - switch (id) - { - case 8: - m_pPointData = GetMoveData(); - if (m_pPointData) - { - me->SetSpeed(MOVE_FLIGHT, 1.0f); - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); - } - break; - case 9: - me->GetMotionMaster()->MoveChase(me->getVictim()); - m_uiBellowingRoarTimer = 1000; - break; - default: - m_bIsMoving = false; - break; - } - } - } - - void SpellHitTarget(Unit* target, const SpellEntry* pSpell) - { - //Workaround - Couldn't find a way to group this spells (All Eruption) - if (((pSpell->Id >= 17086 && pSpell->Id <= 17095) || - (pSpell->Id == 17097) || - (pSpell->Id >= 18351 && pSpell->Id <= 18361) || - (pSpell->Id >= 18564 && pSpell->Id <= 18576) || - (pSpell->Id >= 18578 && pSpell->Id <= 18607) || - (pSpell->Id == 18609) || - (pSpell->Id >= 18611 && pSpell->Id <= 18628) || - (pSpell->Id >= 21132 && pSpell->Id <= 21133) || - (pSpell->Id >= 21135 && pSpell->Id <= 21139) || - (pSpell->Id >= 22191 && pSpell->Id <= 22202) || - (pSpell->Id >= 22267 && pSpell->Id <= 22268)) && - (target->GetTypeId() == TYPEID_PLAYER)) - { - if (m_pInstance) - { - m_pInstance->SetData(DATA_SHE_DEEP_BREATH_MORE, FAIL); - } - } - } - - sOnyxMove* GetMoveData() - { - uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); - - for (uint32 i = 0; i < uiMaxCount; ++i) - { - if (aMoveData[i].uiLocId == m_uiMovePoint) - return &aMoveData[i]; - } - - return NULL; - } - - void SetNextRandomPoint() - { - uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); - - int iTemp = rand()%(uiMaxCount-1); - - if (iTemp >= m_uiMovePoint) - ++iTemp; - - m_uiMovePoint = iTemp; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //Common to PHASE_START && PHASE_END - if (m_uiPhase == PHASE_START || m_uiPhase == PHASE_END) - { - //Specific to PHASE_START || PHASE_END - if (m_uiPhase == PHASE_START) - { - if (me->GetHealth()*100 / me->GetMaxHealth() < 60) - { - m_uiPhase = PHASE_BREATH; - - if (m_pInstance) - m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); - - SetCombatMovement(false); - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - me->SetFlying(true); - - DoScriptText(SAY_PHASE_2_TRANS, me); - - if (m_pPointData) - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); - - m_uiWhelpTimer = 1000; - return; - } - } - else - { - if (m_uiBellowingRoarTimer <= uiDiff) - { - DoCastVictim(SPELL_BELLOWING_ROAR); - // Eruption - GameObject* pFloor = NULL; - Trinity::GameObjectInRangeCheck check(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 15); - Trinity::GameObjectLastSearcher searcher(me, pFloor, check); - me->VisitNearbyGridObject(30, searcher); - if (m_pInstance && pFloor) - m_pInstance->SetData64(DATA_FLOOR_ERUPTION_GUID, pFloor->GetGUID()); - m_uiBellowingRoarTimer = 30000; - } - else - m_uiBellowingRoarTimer -= uiDiff; - } - - if (m_uiFlameBreathTimer <= uiDiff) - { - DoCastVictim(SPELL_FLAME_BREATH); - m_uiFlameBreathTimer = urand(10000, 20000); - } - else - m_uiFlameBreathTimer -= uiDiff; - - if (m_uiTailSweepTimer <= uiDiff) - { - DoCastAOE(SPELL_TAIL_SWEEP); - m_uiTailSweepTimer = urand(15000, 20000); - } - else - m_uiTailSweepTimer -= uiDiff; - - if (m_uiCleaveTimer <= uiDiff) - { - DoCastVictim(SPELL_CLEAVE); - m_uiCleaveTimer = urand(2000, 5000); - } - else - m_uiCleaveTimer -= uiDiff; - - if (m_uiWingBuffetTimer <= uiDiff) - { - DoCastVictim(SPELL_WING_BUFFET); - m_uiWingBuffetTimer = urand(15000, 30000); - } - else - m_uiWingBuffetTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - else - { - if (me->GetHealth()*100 / me->GetMaxHealth() < 40) - { - m_uiPhase = PHASE_END; - if (m_pInstance) - m_pInstance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); - DoScriptText(SAY_PHASE_3_TRANS, me); - - SetCombatMovement(true); - me->SetFlying(false); - m_bIsMoving = false; - me->GetMotionMaster()->MovePoint(9,me->GetHomePosition()); - return; - } - - if (m_uiDeepBreathTimer <= uiDiff) - { - if (!m_bIsMoving) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoScriptText(EMOTE_BREATH, me); - DoCast(me, m_pPointData->uiSpellId); - m_uiDeepBreathTimer = 70000; - } - } - else - m_uiDeepBreathTimer -= uiDiff; - - if (m_uiMovementTimer <= uiDiff) - { - if (!m_bIsMoving) - { - SetNextRandomPoint(); - m_pPointData = GetMoveData(); - - if (!m_pPointData) - return; - - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); - m_bIsMoving = true; - m_uiMovementTimer = 25000; - } - } - else - m_uiMovementTimer -= uiDiff; - - if (m_uiFireballTimer <= uiDiff) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FIREBALL); - - m_uiFireballTimer = 8000; - } - } - else - m_uiFireballTimer -= uiDiff; - - if (m_uiLairGuardTimer <= uiDiff) - { - me->SummonCreature(NPC_LAIRGUARD, aSpawnLocations[2].GetPositionX(), aSpawnLocations[2].GetPositionY(), aSpawnLocations[2].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - if (m_uiSummonLairGuardCount >= RAID_MODE(1,2)) - { - m_uiSummonLairGuardCount = 0; - m_uiLairGuardTimer = 30000; - } - else - m_uiLairGuardTimer = 2000; - } - else - m_uiLairGuardTimer -= uiDiff; - - if (m_uiWhelpTimer <= uiDiff) - { - me->SummonCreature(NPC_WHELP, aSpawnLocations[0].GetPositionX(), aSpawnLocations[0].GetPositionY(), aSpawnLocations[0].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - me->SummonCreature(NPC_WHELP, aSpawnLocations[1].GetPositionX(), aSpawnLocations[1].GetPositionY(), aSpawnLocations[1].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - if (m_uiSummonWhelpCount >= RAID_MODE(20,40)) - { - m_uiSummonWhelpCount = 0; - m_uiWhelpTimer = 90000; - } - else - m_uiWhelpTimer = 500; - } - else - m_uiWhelpTimer -= uiDiff; - } - } -}; - -CreatureAI* GetAI_boss_onyxiaAI(Creature* pCreature) -{ - return new boss_onyxiaAI (pCreature); -} - -void AddSC_boss_onyxia() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_onyxia"; - newscript->GetAI = &GetAI_boss_onyxiaAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp b/src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp deleted file mode 100644 index cfd66bf80f4..00000000000 --- a/src/server/scripts/Kalimdor/onyxias_lair/instance_onyxias_lair.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Onyxias_Lair -SD%Complete: 100 -SDComment: -SDCategory: Onyxia's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "onyxias_lair.h" - -struct instance_onyxias_lair : public ScriptedInstance -{ - instance_onyxias_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - //Eruption is a BFS graph problem - //One map to remember all floor, one map to keep floor that still need to erupt and one queue to know what needs to be removed - std::map FloorEruptionGUID[2]; - std::queue FloorEruptionGUIDQueue; - - uint64 m_uiOnyxiasGUID; - uint32 m_uiOnyxiaLiftoffTimer; - uint32 m_uiManyWhelpsCounter; - uint32 m_uiEruptTimer; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - - bool m_bAchievManyWhelpsHandleIt; - bool m_bAchievSheDeepBreathMore; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiOnyxiasGUID = 0; - m_uiOnyxiaLiftoffTimer = 0; - m_uiManyWhelpsCounter = 0; - m_bAchievManyWhelpsHandleIt = false; - m_bAchievSheDeepBreathMore = true; - - m_uiEruptTimer = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - switch (pCreature->GetEntry()) - { - case NPC_ONYXIA: - m_uiOnyxiasGUID = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if ((pGo->GetGOInfo()->displayId == 4392 || pGo->GetGOInfo()->displayId == 4472) && pGo->GetGOInfo()->trap.spellId == 17731) - { - if (add) - FloorEruptionGUID[0].insert(std::make_pair(pGo->GetGUID(),0)); - else - FloorEruptionGUID[0].erase(pGo->GetGUID()); - return; - } - - switch(pGo->GetEntry()) - { - case GO_WHELP_SPAWNER: - Position pGoPos; - pGo->GetPosition(&pGoPos); - if (Creature* pTemp = pGo->SummonCreature(NPC_WHELP,pGoPos,TEMPSUMMON_CORPSE_DESPAWN)) - { - pTemp->SetInCombatWithZone(); - ++m_uiManyWhelpsCounter; - } - break; - } - } - - void FloorEruption(uint64 floorEruptedGUID) - { - if (GameObject *pFloorEruption = instance->GetGameObject(floorEruptedGUID)) - { - //THIS GOB IS A TRAP - What shall i do? =( - //Cast it spell? Copyed Heigan method - pFloorEruption->SendCustomAnim(); - pFloorEruption->CastSpell(NULL, Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL ? 17731 : 69294); //pFloorEruption->GetGOInfo()->trap.spellId - - //Get all immediatly nearby floors - std::list nearFloorList; - Trinity::GameObjectInRangeCheck check(pFloorEruption->GetPositionX(), pFloorEruption->GetPositionY(), pFloorEruption->GetPositionZ(), 15); - Trinity::GameObjectListSearcher searcher(pFloorEruption, nearFloorList, check); - pFloorEruption->VisitNearbyGridObject(999, searcher); - //remove all that are not present on FloorEruptionGUID[1] and update treeLen on each GUID - for (std::list::const_iterator itr = nearFloorList.begin(); itr != nearFloorList.end(); ++itr) - { - if (((*itr)->GetGOInfo()->displayId == 4392 || (*itr)->GetGOInfo()->displayId == 4472) && (*itr)->GetGOInfo()->trap.spellId == 17731) - { - uint64 nearFloorGUID = (*itr)->GetGUID(); - if (FloorEruptionGUID[1].find(nearFloorGUID) != FloorEruptionGUID[1].end() && (*FloorEruptionGUID[1].find(nearFloorGUID)).second == 0) - { - (*FloorEruptionGUID[1].find(nearFloorGUID)).second = (*FloorEruptionGUID[1].find(floorEruptedGUID)).second+1; - FloorEruptionGUIDQueue.push(nearFloorGUID); - } - } - } - } - FloorEruptionGUID[1].erase(floorEruptedGUID); - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case DATA_ONYXIA: - m_auiEncounter[0] = uiData; - if (uiData == IN_PROGRESS) - SetData(DATA_SHE_DEEP_BREATH_MORE, IN_PROGRESS); - break; - case DATA_ONYXIA_PHASE: - if (uiData == PHASE_BREATH) //Used to mark the liftoff phase - { - m_bAchievManyWhelpsHandleIt = false; - m_uiManyWhelpsCounter = 0; - m_uiOnyxiaLiftoffTimer = 10*IN_MILISECONDS; - } - break; - case DATA_SHE_DEEP_BREATH_MORE: - if (uiData == IN_PROGRESS) - { - m_bAchievSheDeepBreathMore = true; - } - else if (uiData == FAIL) - { - m_bAchievSheDeepBreathMore = false; - } - break; - } - - if (uiType < MAX_ENCOUNTER && uiData == DONE) - SaveToDB(); - } - - void SetData64(uint32 uiType, uint64 uiData) - { - switch(uiType) - { - case DATA_FLOOR_ERUPTION_GUID: - FloorEruptionGUID[1] = FloorEruptionGUID[0]; - FloorEruptionGUIDQueue.push(uiData); - m_uiEruptTimer = 2500; - break; - } - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case DATA_ONYXIA: - return m_auiEncounter[0]; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_ONYXIA_GUID: - return m_uiOnyxiasGUID; - } - - return 0; - } - - void Update(uint32 uiDiff) - { - if (GetData(DATA_ONYXIA) == IN_PROGRESS) - { - if (m_uiOnyxiaLiftoffTimer && m_uiOnyxiaLiftoffTimer <= uiDiff) - { - m_uiOnyxiaLiftoffTimer = 0; - if (m_uiManyWhelpsCounter >= 50) - m_bAchievManyWhelpsHandleIt = true; - } else m_uiOnyxiaLiftoffTimer -= uiDiff; - } - - if (!FloorEruptionGUIDQueue.empty()) - { - if (m_uiEruptTimer <= uiDiff) - { - uint32 treeHeight = 0; - do - { - treeHeight = (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second; - FloorEruption(FloorEruptionGUIDQueue.front()); - FloorEruptionGUIDQueue.pop(); - } while (!FloorEruptionGUIDQueue.empty() && (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second == treeHeight); - m_uiEruptTimer = 1000; - } - else - m_uiEruptTimer -= uiDiff; - } - } - - bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* target = NULL, uint32 miscvalue1 = 0) - { - switch(criteria_id) - { - case ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER: // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s - case ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER: // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s - return m_bAchievManyWhelpsHandleIt; - case ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER: // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath - case ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER: // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath - return m_bAchievSheDeepBreathMore; - } - return false; - } -}; - -InstanceData* GetInstanceData_instance_onyxias_lair(Map* pMap) -{ - return new instance_onyxias_lair(pMap); -} - -void AddSC_instance_onyxias_lair() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_onyxias_lair"; - newscript->GetInstanceData = &GetInstanceData_instance_onyxias_lair; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h b/src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h deleted file mode 100644 index cadd5b5a2d5..00000000000 --- a/src/server/scripts/Kalimdor/onyxias_lair/onyxias_lair.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_ONYXIAS_LAIR_H -#define DEF_ONYXIAS_LAIR_H - -enum eData64 -{ - DATA_ONYXIA_GUID, - DATA_FLOOR_ERUPTION_GUID -}; - -enum eInstanceData -{ - DATA_ONYXIA, - MAX_ENCOUNTER, - - DATA_ONYXIA_PHASE, - DATA_SHE_DEEP_BREATH_MORE, - DATA_MANY_WHELPS_COUNT -}; - -enum eCreatures -{ - NPC_WHELP = 11262, - NPC_LAIRGUARD = 36561, - - NPC_ONYXIA = 10184 -}; - -enum eOnyxiaPhases -{ - PHASE_START = 1, - PHASE_BREATH = 2, - PHASE_END = 3 -}; - -enum eGameObjects -{ - GO_WHELP_SPAWNER = 176510, - GO_WHELP_EGG = 176511 -}; - -enum eAchievementData -{ - ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER = 12565, // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s - ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER = 12568, // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s - ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER = 12566, // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath - ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER = 12569, // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath - ACHIEV_TIMED_START_EVENT = 6601, // Timed event for achievement 4402, 4005: More Dots! (10,25 player) 5 min kill -}; -#endif diff --git a/src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp b/src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp deleted file mode 100644 index 711c4f0b2c1..00000000000 --- a/src/server/scripts/Kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Amnennar_the_coldbringer -SD%Complete: 100 -SDComment: -SDCategory: Razorfen Downs -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1129000 -#define SAY_SUMMON60 -1129001 -#define SAY_SUMMON30 -1129002 -#define SAY_HP -1129003 -#define SAY_KILL -1129004 - -#define SPELL_AMNENNARSWRATH 13009 -#define SPELL_FROSTBOLT 15530 -#define SPELL_FROST_NOVA 15531 -#define SPELL_FROST_SPECTRES 12642 - -struct boss_amnennar_the_coldbringerAI : public ScriptedAI -{ - boss_amnennar_the_coldbringerAI(Creature *c) : ScriptedAI(c) {} - - uint32 AmnenarsWrath_Timer; - uint32 FrostBolt_Timer; - uint32 FrostNova_Timer; - bool Spectrals60; - bool Spectrals30; - bool Hp; - - void Reset() - { - AmnenarsWrath_Timer = 8000; - FrostBolt_Timer = 1000; - FrostNova_Timer = 10000 + rand()%5000; - Spectrals30 = false; - Spectrals60 = false; - Hp = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit() - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //AmnenarsWrath_Timer - if (AmnenarsWrath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_AMNENNARSWRATH); - AmnenarsWrath_Timer = 12000; - } else AmnenarsWrath_Timer -= diff; - - //FrostBolt_Timer - if (FrostBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - FrostBolt_Timer = 8000; - } else FrostBolt_Timer -= diff; - - if (FrostNova_Timer <= diff) - { - DoCast(me, SPELL_FROST_NOVA); - FrostNova_Timer = 15000; - } else FrostNova_Timer -= diff; - - if (!Spectrals60 && me->GetHealth()*100 / me->GetMaxHealth() < 60) - { - DoScriptText(SAY_SUMMON60, me); - DoCast(me->getVictim(), SPELL_FROST_SPECTRES); - Spectrals60 = true; - } - - if (!Hp && me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - DoScriptText(SAY_HP, me); - Hp = true; - } - - if (!Spectrals30 && me->GetHealth()*100 / me->GetMaxHealth() < 30) - { - DoScriptText(SAY_SUMMON30, me); - DoCast(me->getVictim(), SPELL_FROST_SPECTRES); - Spectrals30 = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_amnennar_the_coldbringer(Creature* pCreature) -{ - return new boss_amnennar_the_coldbringerAI (pCreature); -} - -void AddSC_boss_amnennar_the_coldbringer() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_amnennar_the_coldbringer"; - newscript->GetAI = &GetAI_boss_amnennar_the_coldbringer; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp b/src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp deleted file mode 100644 index 04904f08a57..00000000000 --- a/src/server/scripts/Kalimdor/razorfen_downs/instance_razorfen_downs.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "razorfen_downs.h" - -#define MAX_ENCOUNTER 1 - -struct instance_razorfen_downs : public ScriptedInstance -{ - instance_razorfen_downs(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - }; - - uint64 uiGongGUID; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint8 uiGongWaves; - - std::string str_data; - - void Initialize() - { - uiGongGUID = 0; - - uiGongWaves = 0; - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - saveStream << "T C " << m_auiEncounter[0] - << " " << uiGongWaves; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; - - if (dataHead1 == 'T' && dataHead2 == 'C') - { - m_auiEncounter[0] = data0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiGongWaves = data1; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*bAdd*/) - { - switch(pGo->GetEntry()) - { - case GO_GONG: - uiGongGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - break; - default: - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - if (uiType == DATA_GONG_WAVES) - { - uiGongWaves = uiData; - - switch(uiGongWaves) - { - case 9: - case 14: - if (GameObject* pGo = instance->GetGameObject(uiGongGUID)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - break; - case 1: - case 10: - case 16: - { - GameObject* pGo = instance->GetGameObject(uiGongGUID); - - if (!pGo) - return; - - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - - uint32 uiCreature = 0; - uint8 uiSummonTimes = 0; - - switch(uiGongWaves) - { - case 1: - uiCreature = CREATURE_TOMB_FIEND; - uiSummonTimes = 7; - break; - case 10: - uiCreature = CREATURE_TOMB_REAVER; - uiSummonTimes = 3; - break; - case 16: - uiCreature = CREATURE_TUTEN_KASH; - break; - default: - break; - } - - - if (Creature* pCreature = pGo->SummonCreature(uiCreature,2502.635,844.140,46.896,0.633)) - { - if (uiGongWaves == 10 || uiGongWaves == 1) - { - for (uint8 i = 0; i < uiSummonTimes; ++i) - { - if (Creature* pSummon = pGo->SummonCreature(uiCreature,2502.635 + float(irand(-5,5)),844.140 + float(irand(-5,5)),46.896,0.633)) - pSummon->GetMotionMaster()->MovePoint(0,2533.479 + float(irand(-5,5)),870.020 + float(irand(-5,5)),47.678); - } - } - pCreature->GetMotionMaster()->MovePoint(0,2533.479 + float(irand(-5,5)),870.020 + float(irand(-5,5)),47.678); - } - break; - } - default: - break; - } - } - - if (uiType == BOSS_TUTEN_KASH) - { - m_auiEncounter[0] = uiData; - - if (uiData == DONE) - SaveToDB(); - } - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case DATA_GONG_WAVES: - return uiGongWaves; - } - - return 0; - } - - uint64 GetData64(uint32 uiType) - { - switch(uiType) - { - case DATA_GONG: return uiGongGUID; - } - - return 0; - } -}; - -InstanceData* GetInstanceData_instance_razorfen_downs(Map* pMap) -{ - return new instance_razorfen_downs(pMap); -} - -void AddSC_instance_razorfen_downs() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "instance_razorfen_downs"; - newscript->GetInstanceData = &GetInstanceData_instance_razorfen_downs; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp b/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp deleted file mode 100644 index 3e8f4049a37..00000000000 --- a/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Razorfen_Downs -SD%Complete: 100 -SDComment: Support for Henry Stern(2 recipes) -SDCategory: Razorfen Downs -EndScriptData */ - -/* ContentData -npc_henry_stern -EndContentData */ - -#include "ScriptedPch.h" -#include "razorfen_downs.h" - -/*### -# npc_henry_stern -####*/ - -enum eEnums -{ - SPELL_GOLDTHORN_TEA = 13028, - SPELL_TEACHING_GOLDTHORN_TEA = 13029, - SPELL_MIGHT_TROLLS_BLOOD_POTION = 3451, - SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION = 13030, - GOSSIP_TEXT_TEA_ANSWER = 2114, - GOSSIP_TEXT_POTION_ANSWER = 2115, -}; - -#define GOSSIP_ITEM_TEA "Teach me the cooking recipe" -#define GOSSIP_ITEM_POTION "Teach me the alchemy recipe" - -bool GossipHello_npc_henry_stern (Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetBaseSkillValue(SKILL_COOKING) >= 175 && !pPlayer->HasSpell(SPELL_GOLDTHORN_TEA)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (pPlayer->GetBaseSkillValue(SKILL_ALCHEMY) >= 180 && !pPlayer->HasSpell(SPELL_MIGHT_TROLLS_BLOOD_POTION)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_POTION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_henry_stern (Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CastSpell(pPlayer, SPELL_TEACHING_GOLDTHORN_TEA, true); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_TEA_ANSWER, pCreature->GetGUID()); - } - - if (uiAction == GOSSIP_ACTION_INFO_DEF + 2) - { - pPlayer->CastSpell(pPlayer, SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION, true); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_POTION_ANSWER, pCreature->GetGUID()); - } - - return true; -} - -/*###### -## go_gong -######*/ - -bool GOHello_go_gong(Player* /*pPlayer*/, GameObject* pGO) -{ - //basic support, not blizzlike data is missing... - ScriptedInstance* pInstance = pGO->GetInstanceData(); - - if (pInstance) - { - pInstance->SetData(DATA_GONG_WAVES,pInstance->GetData(DATA_GONG_WAVES)+1); - return true; - } - - return false; -} - -enum eTombCreature -{ - SPELL_WEB = 745 -}; - -struct npc_tomb_creatureAI : public ScriptedAI -{ - npc_tomb_creatureAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiWebTimer; - - void Reset() - { - uiWebTimer = urand(5000,8000); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - //from acid - if (me->GetEntry() == CREATURE_TOMB_REAVER) - { - if (uiWebTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_WEB); - uiWebTimer = urand(7000,16000); - } else uiWebTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(DATA_GONG_WAVES,pInstance->GetData(DATA_GONG_WAVES)+1); - } -}; - -CreatureAI* GetAI_npc_tomb_creature(Creature* pCreature) -{ - return new npc_tomb_creatureAI (pCreature); -} - -void AddSC_razorfen_downs() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "npc_henry_stern"; - newscript->pGossipHello = &GossipHello_npc_henry_stern; - newscript->pGossipSelect = &GossipSelect_npc_henry_stern; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_gong"; - newscript->pGOHello = &GOHello_go_gong; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tomb_creature"; - newscript->GetAI = &GetAI_npc_tomb_creature; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h b/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h deleted file mode 100644 index a67b4223c4a..00000000000 --- a/src/server/scripts/Kalimdor/razorfen_downs/razorfen_downs.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_RAZORFEN_DOWNS_H -#define DEF_RAZORFEN_DOWNS_H - -enum eData -{ - BOSS_TUTEN_KASH, - DATA_GONG_WAVES -}; - -enum eData64 -{ - DATA_GONG -}; - -enum eGameObject -{ - GO_GONG = 148917 -}; - -enum eCreature -{ - CREATURE_TOMB_FIEND = 7349, - CREATURE_TOMB_REAVER = 7351, - CREATURE_TUTEN_KASH = 7355 -}; - -#endif diff --git a/src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp b/src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp deleted file mode 100644 index 8a92d3d4d89..00000000000 --- a/src/server/scripts/Kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Razorfen_Kraul -SD%Complete: -SDComment: -SDCategory: Razorfen Kraul -EndScriptData */ - -#include "ScriptedPch.h" -#include "razorfen_kraul.h" - -#define WARD_KEEPERS_NR 2 - -struct instance_razorfen_kraul : public ScriptedInstance -{ - instance_razorfen_kraul(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 DoorWardGUID; - uint32 WardCheck_Timer; - int WardKeeperAlive; - - void Initialize() - { - WardKeeperAlive = 1; - WardCheck_Timer = 4000; - DoorWardGUID = 0; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - debug_log("TSCR: Instance Razorfen Kraul: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*apply*/) - { - switch(pGo->GetEntry()) - { - case 21099: DoorWardGUID = pGo->GetGUID(); break; - } - } - - void Update(uint32 diff) - { - if (WardCheck_Timer <= diff) - { - HandleGameObject(DoorWardGUID, WardKeeperAlive); - WardKeeperAlive = 0; - WardCheck_Timer = 4000; - }else - WardCheck_Timer -= diff; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_WARD_KEEPERS: - if (data == NOT_STARTED) - WardKeeperAlive = 1; - break; - } - } - -}; - -InstanceData* GetInstanceData_instance_razorfen_kraul(Map* pMap) -{ - return new instance_razorfen_kraul(pMap); -} - -void AddSC_instance_razorfen_kraul() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_razorfen_kraul"; - newscript->GetInstanceData = &GetInstanceData_instance_razorfen_kraul; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp b/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp deleted file mode 100644 index 8470fa6c7ac..00000000000 --- a/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Razorfen Kraul -SD%Complete: 100 -SDComment: Quest support: 1144 -SDCategory: Razorfen Kraul -EndScriptData */ - -/* ContentData -npc_willix -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "razorfen_kraul.h" - -#define SAY_READY -1047000 -#define SAY_POINT -1047001 -#define SAY_AGGRO1 -1047002 -#define SAY_BLUELEAF -1047003 -#define SAY_DANGER -1047004 -#define SAY_BAD -1047005 -#define SAY_THINK -1047006 -#define SAY_SOON -1047007 -#define SAY_FINALY -1047008 -#define SAY_WIN -1047009 -#define SAY_END -1047010 - -#define QUEST_WILLIX_THE_IMPORTER 1144 -#define ENTRY_BOAR 4514 -#define SPELL_QUILLBOAR_CHANNELING 7083 - -struct npc_willixAI : public npc_escortAI -{ - npc_willixAI(Creature *c) : npc_escortAI(c) {} - - void WaypointReached(uint32 i) - { - Player* pPlayer = GetPlayerForEscort(); - - if (!pPlayer) - return; - - switch (i) - { - case 3: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - DoScriptText(SAY_POINT, me, pPlayer); - break; - case 4: - me->SummonCreature(ENTRY_BOAR, 2137.66, 1843.98, 48.08, 1.54, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 8: - DoScriptText(SAY_BLUELEAF, me, pPlayer); - break; - case 9: - DoScriptText(SAY_DANGER, me, pPlayer); - break; - case 13: - DoScriptText(SAY_BAD, me, pPlayer); - break; - case 14: - me->SummonCreature(ENTRY_BOAR, 2078.91, 1704.54, 56.77, 1.54, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 25: - DoScriptText(SAY_THINK, me, pPlayer); - break; - case 31: - DoScriptText(SAY_SOON, me, pPlayer); - break; - case 42: - DoScriptText(SAY_FINALY, me, pPlayer); - break; - case 43: - me->SummonCreature(ENTRY_BOAR, 1956.43, 1596.97, 81.75, 1.54,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - break; - case 45: - DoScriptText(SAY_WIN, me, pPlayer); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) - CAST_PLR(pPlayer)->GroupEventHappens(QUEST_WILLIX_THE_IMPORTER,me); - break; - case 46: - DoScriptText(SAY_END, me, pPlayer); - break; - } - } - - void Reset() {} - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO1, me, NULL); - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void JustDied(Unit* /*killer*/) - { - if (Player* pPlayer = GetPlayerForEscort()) - CAST_PLR(pPlayer)->FailQuest(QUEST_WILLIX_THE_IMPORTER); - } -}; - -bool QuestAccept_npc_willix(Player* pPlayer, Creature* pCreature, Quest const* quest) -{ - if (quest->GetQuestId() == QUEST_WILLIX_THE_IMPORTER) - { - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(true, false, pPlayer->GetGUID()); - DoScriptText(SAY_READY, pCreature, pPlayer); - pCreature->setFaction(113); - } - - return true; -} - -struct npc_deaths_head_ward_keeperAI : public ScriptedAI -{ - npc_deaths_head_ward_keeperAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 QuillboarChanneling_Timer; - - void Reset() - { - QuillboarChanneling_Timer = 1500; - } - - void UpdateAI(const uint32 diff) - { - if (!me->isAlive()) - return; - - if (pInstance) - pInstance->SetData(TYPE_WARD_KEEPERS, NOT_STARTED); - - if (QuillboarChanneling_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_QUILLBOAR_CHANNELING); - QuillboarChanneling_Timer = 1100; - } else QuillboarChanneling_Timer -= diff; - - } -}; - -CreatureAI* GetAI_npc_deaths_head_ward_keeper(Creature* pCreature) -{ - return new npc_deaths_head_ward_keeperAI(pCreature); -} - -CreatureAI* GetAI_npc_willix(Creature* pCreature) -{ - return new npc_willixAI(pCreature); -} - -void AddSC_razorfen_kraul() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_willix"; - newscript->GetAI = &GetAI_npc_willix; - newscript->pQuestAccept = &QuestAccept_npc_willix; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_deaths_head_ward_keeper"; - newscript->GetAI = &GetAI_npc_deaths_head_ward_keeper; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h b/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h deleted file mode 100644 index e2219986f63..00000000000 --- a/src/server/scripts/Kalimdor/razorfen_kraul/razorfen_kraul.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_RAZORFEN_KRAUL_H -#define DEF_RAZORFEN_KRAUL_H - -#define TYPE_WARD_KEEPERS 1 -#endif diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp deleted file mode 100644 index f6dc75558c8..00000000000 --- a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ayamiss -SD%Complete: 50 -SDComment: VERIFY SCRIPT -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -/* -To do: -make him fly from 70-100% -*/ - -enum Spells -{ - SPELL_STINGERSPRAY = 25749, - SPELL_POISONSTINGER = 25748, //only used in phase1 - SPELL_SUMMONSWARMER = 25844, //might be 25708 - SPELL_PARALYZE = 23414 //doesnt work correct (core) -}; - -struct boss_ayamissAI : public ScriptedAI -{ - boss_ayamissAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 STINGERSPRAY_Timer; - uint32 POISONSTINGER_Timer; - uint32 SUMMONSWARMER_Timer; - uint32 phase; - - ScriptedInstance *pInstance; - - void Reset() - { - STINGERSPRAY_Timer = 30000; - POISONSTINGER_Timer = 30000; - SUMMONSWARMER_Timer = 60000; - phase=1; - - if (pInstance) - pInstance->SetData(DATA_AYAMISS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_AYAMISS_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_AYAMISS_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If he is 70% start phase 2 - if (phase == 1 && me->GetHealth()*100 / me->GetMaxHealth() <= 70 && !me->IsNonMeleeSpellCasted(false)) - { - phase=2; - } - - //STINGERSPRAY_Timer (only in phase2) - if (phase == 2 && STINGERSPRAY_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STINGERSPRAY); - STINGERSPRAY_Timer = 30000; - } else STINGERSPRAY_Timer -= diff; - - //POISONSTINGER_Timer (only in phase1) - if (phase == 1 && POISONSTINGER_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISONSTINGER); - POISONSTINGER_Timer = 30000; - } else POISONSTINGER_Timer -= diff; - - //SUMMONSWARMER_Timer (only in phase1) - if (SUMMONSWARMER_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUMMONSWARMER); - SUMMONSWARMER_Timer = 60000; - } else SUMMONSWARMER_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_ayamiss(Creature* pCreature) -{ - return new boss_ayamissAI (pCreature); -} - -void AddSC_boss_ayamiss() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ayamiss"; - newscript->GetAI = &GetAI_boss_ayamiss; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp deleted file mode 100644 index 86a2c559543..00000000000 --- a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_buru.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Buru -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Yells -{ - EMOTE_TARGET = -1509002 -}; - -struct boss_buruAI : public ScriptedAI -{ - boss_buruAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_BURU_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_BURU_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_BURU_EVENT, DONE); - } -}; -CreatureAI* GetAI_boss_buru(Creature* pCreature) -{ - return new boss_buruAI (pCreature); -} - -void AddSC_boss_buru() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_buru"; - newscript->GetAI = &GetAI_boss_buru; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp deleted file mode 100644 index 44f11bf4b60..00000000000 --- a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kurinnaxx -SD%Complete: 100 -SDComment: VERIFY SCRIPT AND SQL -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Spells -{ - SPELL_MORTALWOUND = 25646, - SPELL_SANDTRAP = 25656, - SPELL_ENRAGE = 28798, - SPELL_SUMMON_PLAYER = 26446, - SPELL_TRASH = 3391, - SPELL_WIDE_SLASH = 25814 -}; - -struct boss_kurinnaxxAI : public ScriptedAI -{ - boss_kurinnaxxAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiMortalWoundTimer; - uint32 uiSandtrapTimer; - uint32 uiWideSlashTimer; - uint32 uiSummonPlayerTimer; - uint32 uiTrashTimer; - bool bIsEnraged; - - ScriptedInstance* pInstance; - - void Reset() - { - bIsEnraged = false; - uiMortalWoundTimer = urand(2000,7000); - uiSandtrapTimer = urand(20000,30000); - uiWideSlashTimer = urand(10000,15000); - uiTrashTimer = urand(20000,25000); - uiSummonPlayerTimer = urand(30000,40000); - - if (pInstance) - pInstance->SetData(DATA_KURINNAXX_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_KURINNAXX_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_KURINNAXX_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //If we are <30% cast enrage - if (!bIsEnraged && me->GetHealth()*100 / me->GetMaxHealth() <= 30 && !me->IsNonMeleeSpellCasted(false)) - { - bIsEnraged = true; - DoCast(me, SPELL_ENRAGE); - } - - //Mortal Wound spell - if (uiMortalWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTALWOUND); - uiMortalWoundTimer = urand(2000,7000); - } else uiMortalWoundTimer -= diff; - - //Santrap spell - if (uiSandtrapTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SANDTRAP); - uiSandtrapTimer = 30000; - } else uiSandtrapTimer -= diff; - - //Wide Slash spell - if (uiWideSlashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WIDE_SLASH); - uiWideSlashTimer = urand(10000,15000); - } else uiWideSlashTimer -= diff; - - //Trash spell - if (uiTrashTimer <= diff) - { - DoCast(me, SPELL_TRASH); - uiTrashTimer = urand(20000,25000); - } else uiTrashTimer -= diff; - - //Summon Player spell - if (uiSummonPlayerTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SUMMON_PLAYER); - uiSummonPlayerTimer = urand(30000,40000); - } else uiSummonPlayerTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_kurinnaxx(Creature* pCreature) -{ - return new boss_kurinnaxxAI (pCreature); -} - -void AddSC_boss_kurinnaxx() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kurinnaxx"; - newscript->GetAI = &GetAI_boss_kurinnaxx; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp deleted file mode 100644 index 1882adc8fbb..00000000000 --- a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_moam.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Moam -SD%Complete: 90 -SDComment: TODO: Adjust timer, correct Stone phase buff -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Emotes -{ - EMOTE_AGGRO = -1509000, - EMOTE_MANA_FULL = -1509001 -}; - -enum Spells -{ - SPELL_TRAMPLE = 15550, - SPELL_DRAINMANA = 27256, //Doesn't exist ? - SPELL_ARCANEERUPTION = 25672, - SPELL_SUMMONMANA = 25681, //Summon Mana fiend. It only summons one so exec it three times - SPELL_GRDRSLEEP = 24360 //Greater Dreamless Sleep -}; - -enum Creatures -{ - CREATURE_MANA_FIEND = 15527 -}; - -enum CombatPhase -{ - NORMAL, - STONE -}; - -struct boss_moamAI : public ScriptedAI -{ - boss_moamAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiTrampleTimer; - uint32 uiDrainManaTimer; - uint32 uiPhaseTimer; - CombatPhase Phase; - - ScriptedInstance *pInstance; - - void Reset() - { - uiTrampleTimer = urand(3000,7000); - uiDrainManaTimer = urand(3000,7000); - uiPhaseTimer = 90000; - Phase = NORMAL; - me->SetPower(POWER_MANA,0); - - if (pInstance) - pInstance->SetData(DATA_MOAM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(EMOTE_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MOAM_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_MOAM_EVENT, DONE); - } - - void DrainMana() - { - for (uint8 i=0;i<6;++i) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - pTarget->ModifyPower(POWER_MANA, -500); - me->ModifyPower(POWER_MANA, 1000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Phase == NORMAL) - { - if (!UpdateVictim()) - return; - - //If we are 100%MANA cast Arcane Erruption - if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA)) - { - DoCast(me->getVictim(), SPELL_ARCANEERUPTION); - DoScriptText(EMOTE_MANA_FULL, me); - me->SetPower(POWER_MANA,0); - } - - //Trample Spell - if (uiTrampleTimer <= diff) - { - DoCast(me->getVictim(), SPELL_TRAMPLE); - uiTrampleTimer = urand(3000,7000); - } else uiTrampleTimer -= diff; - - //Drain Mana - if (uiDrainManaTimer <= diff) - { - DrainMana(); - uiDrainManaTimer = urand(3000,7000); - } else uiDrainManaTimer -= diff; - - DoMeleeAttackIfReady(); - - //After 90secs change phase - if (uiPhaseTimer <= diff) - { - Phase = STONE; - DoCast(me, SPELL_SUMMONMANA); - DoCast(me, SPELL_SUMMONMANA); - DoCast(me, SPELL_SUMMONMANA); - DoCast(me, SPELL_GRDRSLEEP); - } else uiPhaseTimer -= diff; - } - } -}; - -CreatureAI* GetAI_boss_moam(Creature* pCreature) -{ - return new boss_moamAI (pCreature); -} - -void AddSC_boss_moam() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_moam"; - newscript->GetAI = &GetAI_boss_moam; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp deleted file mode 100644 index 57ba8d9da7f..00000000000 --- a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ossirian -SD%Complete: 0 -SDComment: Place holder -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Yells -{ - SAY_SURPREME2 = -1509019, - SAY_SURPREME3 = -1509020, - SAY_RAND_INTRO1 = -1509021, - SAY_RAND_INTRO2 = -1509022, - SAY_RAND_INTRO3 = -1509023, - SAY_RAND_INTRO4 = -1509024, //possibly old? - SAY_AGGRO = -1509025, - SAY_SLAY = -1509026, - SAY_DEATH = -1509027 -}; - -struct boss_ossirianAI : public ScriptedAI -{ - boss_ossirianAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_OSSIRIAN_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_OSSIRIAN_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_OSSIRIAN_EVENT, DONE); - } -}; -CreatureAI* GetAI_boss_ossirian(Creature* pCreature) -{ - return new boss_ossirianAI (pCreature); -} - -void AddSC_boss_ossirian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ossirian"; - newscript->GetAI = &GetAI_boss_ossirian; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp deleted file mode 100644 index 5be60dc0ca0..00000000000 --- a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Rajaxx -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -enum Yells -{ - SAY_ANDOROV_INTRO = -1509003, - SAY_ANDOROV_ATTACK = -1509004, - SAY_WAVE3 = -1509005, - SAY_WAVE4 = -1509006, - SAY_WAVE5 = -1509007, - SAY_WAVE6 = -1509008, - SAY_WAVE7 = -1509009, - SAY_INTRO = -1509010, - SAY_UNK1 = -1509011, - SAY_UNK2 = -1509012, - SAY_UNK3 = -1509013, - SAY_UNK4 = -1509014, - SAY_DEAGGRO = -1509015, - SAY_KILLS_ANDOROV = -1509016, - SAY_COMPLETE_QUEST = -1509017 //Yell when realm complete quest 8743 for world event -}; - -struct boss_rajaxxAI : public ScriptedAI -{ - boss_rajaxxAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_RAJAXX_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_RAJAXX_EVENT, IN_PROGRESS); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_RAJAXX_EVENT, DONE); - } -}; -CreatureAI* GetAI_boss_rajaxx(Creature* pCreature) -{ - return new boss_rajaxxAI (pCreature); -} - -void AddSC_boss_rajaxx() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_rajaxx"; - newscript->GetAI = &GetAI_boss_rajaxx; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp deleted file mode 100644 index ba7471bdbd2..00000000000 --- a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Ruins_of_Ahnqiraj -SD%Complete: 0 -SDComment: Place holder -SDCategory: Ruins of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "ruins_of_ahnqiraj.h" - -#define MAX_ENCOUNTER 6 - -/* Ruins of Ahn'Qiraj encounters: -0 - Kurinnaxx -1 - General Rajaxx -2 - Moam -3 - Buru the Gorger -4 - Ayamiss the Hunter -5 - Ossirian the Unscarred */ - -struct instance_ruins_of_ahn_qiraj : public ScriptedInstance -{ - instance_ruins_of_ahn_qiraj(Map* pMap) : ScriptedInstance(pMap) { Initialize(); } - - uint64 uiKurinaxx; - uint64 uiRajaxx; - uint64 uiMoam; - uint64 uiBuru; - uint64 uiAyamiss; - uint64 uiOssirian; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - uiKurinaxx = 0; - uiRajaxx = 0; - uiMoam = 0; - uiBuru = 0; - uiAyamiss = 0; - uiOssirian = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case CREATURE_KURINAXX: - uiKurinaxx = pCreature->GetGUID(); - break; - case CREATURE_RAJAXX: - uiRajaxx = pCreature->GetGUID(); - break; - case CREATURE_MOAM: - uiMoam = pCreature->GetGUID(); - break; - case CREATURE_BURU: - uiBuru = pCreature->GetGUID(); - break; - case CREATURE_AYAMISS: - uiAyamiss = pCreature->GetGUID(); - break; - case CREATURE_OSSIRIAN: - uiOssirian = pCreature->GetGUID(); - break; - } - } - - uint32 GetData(uint32 identifier) - { - switch(identifier) - { - case DATA_KURINNAXX_EVENT: return m_auiEncounter[0]; - case DATA_RAJAXX_EVENT: return m_auiEncounter[1]; - case DATA_MOAM_EVENT: return m_auiEncounter[2]; - case DATA_BURU_EVENT: return m_auiEncounter[3]; - case DATA_AYAMISS_EVENT: return m_auiEncounter[4]; - case DATA_OSSIRIAN_EVENT: return m_auiEncounter[5]; - } - - return 0; - } - - void SetData(uint32 identifier, uint32 data) - { - switch(identifier) - { - case DATA_KURINNAXX_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_RAJAXX_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_MOAM_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_BURU_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_AYAMISS_EVENT: - m_auiEncounter[4] = data; - break; - case DATA_OSSIRIAN_EVENT: - m_auiEncounter[5] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint64 GetData64(uint32 uiIdentifier) - { - switch(uiIdentifier) - { - case DATA_KURINNAXX: return uiKurinaxx; - case DATA_RAJAXX: return uiRajaxx; - case DATA_MOAM: return uiMoam; - case DATA_BURU: return uiBuru; - case DATA_AYAMISS: return uiAyamiss; - case DATA_OSSIRIAN: return uiOssirian; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "R A " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; - - if (dataHead1 == 'R' && dataHead2 == 'A') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - m_auiEncounter[5] = data5; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - } -}; - -InstanceData* GetInstanceData_instance_ruins_of_ahn_qiraj(Map* pMap) -{ - return new instance_ruins_of_ahn_qiraj(pMap); -} - -void AddSC_instance_ruins_of_ahnqiraj() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_ruins_of_ahnqiraj"; - newscript->GetInstanceData = &GetInstanceData_instance_ruins_of_ahn_qiraj; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h b/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h deleted file mode 100644 index 33fd75d557a..00000000000 --- a/src/server/scripts/Kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DEF_RUINS_OF_AHNQIRAJ_H -#define DEF_RUINS_OF_AHNQIRAJ_H - -enum Data -{ - DATA_KURINNAXX_EVENT, - DATA_RAJAXX_EVENT, - DATA_MOAM_EVENT, - DATA_BURU_EVENT, - DATA_AYAMISS_EVENT, - DATA_OSSIRIAN_EVENT -}; - -enum Data64 -{ - DATA_KURINNAXX, - DATA_RAJAXX, - DATA_MOAM, - DATA_BURU, - DATA_AYAMISS, - DATA_OSSIRIAN -}; - -enum Bosses -{ - CREATURE_KURINAXX = 15348, - CREATURE_RAJAXX = 15341, - CREATURE_MOAM = 15340, - CREATURE_BURU = 15370, - CREATURE_AYAMISS = 15369, - CREATURE_OSSIRIAN = 15339 -}; - -#endif diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp deleted file mode 100644 index f6e3b0c741b..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: boss_kri, boss_yauj, boss_vem : The Bug Trio -SD%Complete: 100 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" - -#define SPELL_CLEAVE 26350 -#define SPELL_TOXIC_VOLLEY 25812 -#define SPELL_POISON_CLOUD 38718 //Only Spell with right dmg. -#define SPELL_ENRAGE 34624 //Changed cause 25790 is casted on gamers too. Same prob with old explosion of twin emperors. - -#define SPELL_CHARGE 26561 -#define SPELL_KNOCKBACK 26027 - -#define SPELL_HEAL 25807 -#define SPELL_FEAR 19408 - -struct boss_kriAI : public ScriptedAI -{ - boss_kriAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Cleave_Timer; - uint32 ToxicVolley_Timer; - uint32 Check_Timer; - - bool VemDead; - bool Death; - - void Reset() - { - Cleave_Timer = 4000 + rand()%4000; - ToxicVolley_Timer = 6000 + rand()%6000; - Check_Timer = 2000; - - VemDead = false; - Death = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) - // Unlootable if death - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - - pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); - } - } - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Cleave_Timer - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 5000 + rand()%7000; - } else Cleave_Timer -= diff; - - //ToxicVolley_Timer - if (ToxicVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TOXIC_VOLLEY); - ToxicVolley_Timer = 10000 + rand()%5000; - } else ToxicVolley_Timer -= diff; - - if (me->GetHealth() <= me->GetMaxHealth() * 0.05 && !Death) - { - DoCast(me->getVictim(), SPELL_POISON_CLOUD); - Death = true; - } - - if (!VemDead) - { - //Checking if Vem is dead. If yes we will enrage. - if (Check_Timer <= diff) - { - if (pInstance && pInstance->GetData(DATA_VEMISDEAD)) - { - DoCast(me, SPELL_ENRAGE); - VemDead = true; - } - Check_Timer = 2000; - } else Check_Timer -=diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_vemAI : public ScriptedAI -{ - boss_vemAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Charge_Timer; - uint32 KnockBack_Timer; - uint32 Enrage_Timer; - - bool Enraged; - - void Reset() - { - Charge_Timer = 15000 + rand()%12000; - KnockBack_Timer = 8000 + rand()%12000; - Enrage_Timer = 120000; - - Enraged = false; - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_VEM_DEATH, 0); - if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) - // Unlootable if death - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Charge_Timer - if (Charge_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget) - { - DoCast(pTarget, SPELL_CHARGE); - //me->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, true,1); - AttackStart(pTarget); - } - - Charge_Timer = 8000 + rand()%8000; - } else Charge_Timer -= diff; - - //KnockBack_Timer - if (KnockBack_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKBACK); - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-80); - KnockBack_Timer = 15000 + rand()%10000; - } else KnockBack_Timer -= diff; - - //Enrage_Timer - if (!Enraged && Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else Charge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_yaujAI : public ScriptedAI -{ - boss_yaujAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Heal_Timer; - uint32 Fear_Timer; - uint32 Check_Timer; - - bool VemDead; - - void Reset() - { - Heal_Timer = 25000 + rand()%15000; - Fear_Timer = 12000 + rand()%12000; - Check_Timer = 2000; - - VemDead = false; - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - if (pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2) - // Unlootable if death - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - pInstance->SetData(DATA_BUG_TRIO_DEATH, 1); - } - - for (uint8 i = 0; i < 10; ++i) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - Creature* Summoned = me->SummonCreature(15621,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,90000); - if (Summoned && pTarget) - Summoned->AI()->AttackStart(pTarget); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - DoResetThreat(); - Fear_Timer = 20000; - } else Fear_Timer -= diff; - - //Casting Heal to other twins or herself. - if (Heal_Timer <= diff) - { - if (pInstance) - { - Unit *pKri = Unit::GetUnit((*me), pInstance->GetData64(DATA_KRI)); - Unit *pVem = Unit::GetUnit((*me), pInstance->GetData64(DATA_VEM)); - - switch (urand(0,2)) - { - case 0: - if (pKri) - DoCast(pKri, SPELL_HEAL); - break; - case 1: - if (pVem) - DoCast(pVem, SPELL_HEAL); - break; - case 2: - DoCast(me, SPELL_HEAL); - break; - } - } - - Heal_Timer = 15000+rand()%15000; - } else Heal_Timer -= diff; - - //Checking if Vem is dead. If yes we will enrage. - if (Check_Timer <= diff) - { - if (!VemDead) - { - if (pInstance) - { - if (pInstance->GetData(DATA_VEMISDEAD)) - { - DoCast(me, SPELL_ENRAGE); - VemDead = true; - } - } - } - Check_Timer = 2000; - } else Check_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_yauj(Creature* pCreature) -{ - return new boss_yaujAI (pCreature); -} - -CreatureAI* GetAI_boss_vem(Creature* pCreature) -{ - return new boss_vemAI (pCreature); -} - -CreatureAI* GetAI_boss_kri(Creature* pCreature) -{ - return new boss_kriAI (pCreature); -} - -void AddSC_bug_trio() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kri"; - newscript->GetAI = &GetAI_boss_kri; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_vem"; - newscript->GetAI = &GetAI_boss_vem; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_yauj"; - newscript->GetAI = &GetAI_boss_yauj; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp deleted file mode 100644 index 3e42d16be3a..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_cthun.cpp +++ /dev/null @@ -1,1307 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Cthun -SD%Complete: 95 -SDComment: Darkglare tracking issue -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" - -/* - * This is a 2 phases events. Here follows an explanation of the main events and transition between phases and sub-phases. - * - * The first phase is the EYE phase: the Eye of C'Thun is active and C'thun is not active. - * During this phase, the "Eye of C'Thun" alternates between 2 sub-phases: - * - PHASE_EYE_GREEN_BEAM: - * 50 sec phase during which the Eye mainly casts its Green Beam every 3 sec. - * - PHASE_EYE_RED_BEAM: - * 35 sec phase during which the Eye casts its red beam every sec. - * This EYE phase ends when the "Eye of C'Thun" is killed. Then starts the CTHUN phase. - * - * The second phase is the CTHUN phase. The Eye of C'Thun is not active and C'Thun is active. - * This phase starts with the transformation of the Eye into C'Thun (PHASE_CTHUN_TRANSITION). - * After the transformation, C'Thun alternates between 2 sub-phases: - * - PHASE_CTHUN_STOMACH: - * - C'Thun is almost insensible to all damage (99% damage reduction). - * - It spawns 2 tentacles in its stomach. - * - C'Thun swallows players. - * - This sub-phase ends when the 2 tentacles are killed. Swallowed players are regurgitate. - * - * - PHASE_CTHUN_WEAK: - * - weakened C'Thun takes normal damage. - * - This sub-phase ends after 45 secs. - * - * This CTHUN phase ends when C'Thun is killed - * - * Note: - * - the current phase is stored in the instance data to be easily shared between the eye and cthun. - */ - -#define PI 3.14 - -enum Phases -{ - PHASE_NOT_STARTED = 0, - - // Main Phase 1 - EYE - PHASE_EYE_GREEN_BEAM = 1, - PHASE_EYE_RED_BEAM = 2, - - // Main Phase 2 - CTHUN - PHASE_CTHUN_TRANSITION = 3, - PHASE_CTHUN_STOMACH = 4, - PHASE_CTHUN_WEAK = 5, - - PHASE_CTHUN_DONE = 6, -}; - -enum Creatures -{ - MOB_CTHUN_PORTAL = 15896, - - //***** Main Phase 1 ******** - BOSS_EYE_OF_CTHUN = 15589, - MOB_CLAW_TENTACLE = 15725, - MOB_EYE_TENTACLE = 15726, - MOB_SMALL_PORTAL = 15904, - - //***** Main Phase 2 ******** - MOB_BODY_OF_CTHUN = 15809, - MOB_GIANT_CLAW_TENTACLE = 15728, - MOB_GIANT_EYE_TENTACLE = 15334, - MOB_FLESH_TENTACLE = 15802, - MOB_GIANT_PORTAL = 15910, -}; - -enum Spells -{ - //***** Main Phase 1 ******** - //Eye Spells - SPELL_FREEZE_ANIM = 16245, - SPELL_GREEN_BEAM = 26134, - SPELL_DARK_GLARE = 26029, - SPELL_RED_COLORATION = 22518, //Probably not the right spell but looks similar - - //Eye Tentacles Spells - SPELL_MIND_FLAY = 26143, - - //Claw Tentacles Spells - SPELL_GROUND_RUPTURE = 26139, - SPELL_HAMSTRING = 26141, - - //***** Main Phase 2 ****** - //Body spells - //#define SPELL_CARAPACE_CTHUN 26156 //Was removed from client dbcs - SPELL_TRANSFORM = 26232, - SPELL_PURPLE_COLORATION = 22581, //Probably not the right spell but looks similar - - //Eye Tentacles Spells - //SAME AS PHASE1 - - //Giant Claw Tentacles - SPELL_MASSIVE_GROUND_RUPTURE = 26100, - - //Also casts Hamstring - SPELL_THRASH = 3391, - - //Giant Eye Tentacles - //CHAIN CASTS "SPELL_GREEN_BEAM" - - //Stomach Spells - SPELL_MOUTH_TENTACLE = 26332, - SPELL_EXIT_STOMACH_KNOCKBACK = 25383, - SPELL_DIGESTIVE_ACID = 26476, -}; - -enum Actions -{ - ACTION_FLESH_TENTACLE_KILLED = 1, -}; - -enum Yells -{ - //Text emote - EMOTE_WEAKENED = -1531011, - - //****** Out of Combat ****** - // Random Wispers - No txt only sound - // The random sound is chosen by the client. - RANDOM_SOUND_WHISPER = 8663, -}; - -//Stomach Teleport positions -#define STOMACH_X -8562.0f -#define STOMACH_Y 2037.0f -#define STOMACH_Z -70.0f -#define STOMACH_O 5.05f - -//Flesh tentacle positions -const Position FleshTentaclePos[2] = -{ - { -8571.0f, 1990.0f, -98.0f, 1.22f}, - { -8525.0f, 1994.0f, -98.0f, 2.12f}, -}; - -//Kick out position -const Position KickPos = { -8545.0f, 1984.0f, -96.0f}; - -struct eye_of_cthunAI : public Scripted_NoMovementAI -{ - eye_of_cthunAI(Creature *c) : Scripted_NoMovementAI(c) - { - pInst = c->GetInstanceData(); - if (!pInst) - error_log("TSCR: No Instance eye_of_cthunAI"); - } - - ScriptedInstance* pInst; - - //Global variables - uint32 PhaseTimer; - - //Eye beam phase - uint32 BeamTimer; - uint32 EyeTentacleTimer; - uint32 ClawTentacleTimer; - - //Dark Glare phase - uint32 DarkGlareTick; - uint32 DarkGlareTickTimer; - float DarkGlareAngle; - bool ClockWise; - - void Reset() - { - //Phase information - PhaseTimer = 50000; //First dark glare in 50 seconds - - //Eye beam phase 50 seconds - BeamTimer = 3000; - EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam - ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam) - - //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks) - DarkGlareTick = 0; - DarkGlareTickTimer = 1000; - DarkGlareAngle = 0; - ClockWise = false; - - //Reset flags - me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_ON); - - //Reset Phase - if (pInst) - pInst->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); - - //to avoid having a following void zone - Creature* pPortal= me->FindNearestCreature(MOB_CTHUN_PORTAL, 10); - if (pPortal) - pPortal->SetReactState(REACT_PASSIVE); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - if (pInst) - pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); - } - - void SpawnEyeTentacle(float x, float y) - { - if (Creature* Spawned = DoSpawnCreature(MOB_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500)) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - if (Spawned->AI()) - Spawned->AI()->AttackStart(pTarget); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //No instance - if (!pInst) - return; - - uint32 currentPhase = pInst->GetData(DATA_CTHUN_PHASE); - if (currentPhase == PHASE_EYE_GREEN_BEAM || currentPhase == PHASE_EYE_RED_BEAM) - { - // EyeTentacleTimer - if (EyeTentacleTimer <= diff) - { - //Spawn the 8 Eye Tentacles in the corret spots - SpawnEyeTentacle(0, 20); //south - SpawnEyeTentacle(10, 10); //south west - SpawnEyeTentacle(20, 0); //west - SpawnEyeTentacle(10, -10); //north west - - SpawnEyeTentacle(0, -20); //north - SpawnEyeTentacle(-10, -10); //north east - SpawnEyeTentacle(-20, 0); // east - SpawnEyeTentacle(-10, 10); // south east - - EyeTentacleTimer = 45000; - } else EyeTentacleTimer -= diff; - } - - switch (currentPhase) - { - case PHASE_EYE_GREEN_BEAM: - //BeamTimer - if (BeamTimer <= diff) - { - //SPELL_GREEN_BEAM - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - me->InterruptNonMeleeSpells(false); - DoCast(pTarget, SPELL_GREEN_BEAM); - - //Correctly update our target - me->SetUInt64Value(UNIT_FIELD_TARGET, pTarget->GetGUID()); - } - - //Beam every 3 seconds - BeamTimer = 3000; - } else BeamTimer -= diff; - - //ClawTentacleTimer - if (ClawTentacleTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - Creature* Spawned = NULL; - - //Spawn claw tentacle on the random target - Spawned = me->SummonCreature(MOB_CLAW_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500); - - if (Spawned && Spawned->AI()) - Spawned->AI()->AttackStart(pTarget); - } - - //One claw tentacle every 12.5 seconds - ClawTentacleTimer = 12500; - } else ClawTentacleTimer -= diff; - - //PhaseTimer - if (PhaseTimer <= diff) - { - //Switch to Dark Beam - pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_RED_BEAM); - - me->InterruptNonMeleeSpells(false); - me->SetReactState(REACT_PASSIVE); - - //Remove any target - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - //Select random target for dark beam to start on - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - //Face our target - DarkGlareAngle = me->GetAngle(pTarget); - DarkGlareTickTimer = 1000; - DarkGlareTick = 0; - ClockWise = RAND(true, false); - } - - //Add red coloration to C'thun - DoCast(me, SPELL_RED_COLORATION, true); - - //Freeze animation - DoCast(me, SPELL_FREEZE_ANIM); - me->SetOrientation(DarkGlareAngle); - me->StopMoving(); - - //Darkbeam for 35 seconds - PhaseTimer = 35000; - } else PhaseTimer -= diff; - - break; - - case PHASE_EYE_RED_BEAM: - if (DarkGlareTick < 35) - if (DarkGlareTickTimer <= diff) - { - //Set angle and cast - if (ClockWise) - me->SetOrientation(DarkGlareAngle + ((float)DarkGlareTick*PI/35)); - else - me->SetOrientation(DarkGlareAngle - ((float)DarkGlareTick*PI/35)); - - me->StopMoving(); - - //Actual dark glare cast, maybe something missing here? - DoCast(me, SPELL_DARK_GLARE, false); - - //Increase tick - ++DarkGlareTick; - - //1 second per tick - DarkGlareTickTimer = 1000; - } else DarkGlareTickTimer -= diff; - - //PhaseTimer - if (PhaseTimer <= diff) - { - //Switch to Eye Beam - pInst->SetData(DATA_CTHUN_PHASE, PHASE_EYE_GREEN_BEAM); - - BeamTimer = 3000; - ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn during Dark beam) - - me->InterruptNonMeleeSpells(false); - - //Remove Red coloration from c'thun - me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); - - //set it back to aggressive - me->SetReactState(REACT_AGGRESSIVE); - - //Eye Beam for 50 seconds - PhaseTimer = 50000; - } else PhaseTimer -= diff; - - break; - - //Transition phase - case PHASE_CTHUN_TRANSITION: - //Remove any target - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - me->SetHealth(0); - me->SetVisibility(VISIBILITY_OFF); - break; - - //Dead phase - case PHASE_CTHUN_DONE: - Creature* pPortal= me->FindNearestCreature(MOB_CTHUN_PORTAL, 10); - if (pPortal) - pPortal->ForcedDespawn(); - - me->ForcedDespawn(); - break; - } - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - //No instance - if (!pInst) - return; - - switch (pInst->GetData(DATA_CTHUN_PHASE)) - { - case PHASE_EYE_GREEN_BEAM: - case PHASE_EYE_RED_BEAM: - //Only if it will kill - if (damage < me->GetHealth()) - return; - - //Fake death in phase 0 or 1 (green beam or dark glare phase) - me->InterruptNonMeleeSpells(false); - - //Remove Red coloration from c'thun - me->RemoveAurasDueToSpell(SPELL_RED_COLORATION); - - //Reset to normal emote state and prevent select and attack - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - //Remove Target field - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - //Death animation/respawning; - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_TRANSITION); - - me->SetHealth(0); - damage = 0; - - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - break; - - case PHASE_CTHUN_DONE: - //Allow death here - return; - - default: - //Prevent death in these phases - damage = 0; - return; - } - } -}; - -struct cthunAI : public Scripted_NoMovementAI -{ - cthunAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - - pInst = c->GetInstanceData(); - if (!pInst) - error_log("TSCR: No Instance eye_of_cthunAI"); - } - - ScriptedInstance* pInst; - - //Out of combat whisper timer - uint32 WisperTimer; - - //Global variables - uint32 PhaseTimer; - - //------------------- - - //Phase transition - uint64 HoldPlayer; - - //Body Phase - uint32 EyeTentacleTimer; - uint8 FleshTentaclesKilled; - uint32 GiantClawTentacleTimer; - uint32 GiantEyeTentacleTimer; - uint32 StomachAcidTimer; - uint32 StomachEnterTimer; - uint32 StomachEnterVisTimer; - uint64 StomachEnterTarget; - - //Stomach map, bool = true then in stomach - UNORDERED_MAP Stomach_Map; - - void Reset() - { - //One random wisper every 90 - 300 seconds - WisperTimer = 90000; - - //Phase information - PhaseTimer = 10000; //Emerge in 10 seconds - - //No hold player for transition - HoldPlayer = 0; - - //Body Phase - EyeTentacleTimer = 30000; - FleshTentaclesKilled = 0; - GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat) - GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat) - StomachAcidTimer = 4000; //Every 4 seconds - StomachEnterTimer = 10000; //Every 10 seconds - StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer - StomachEnterTarget = 0; //Target to be teleported to stomach - - //Clear players in stomach and outside - Stomach_Map.clear(); - - //Reset flags - me->RemoveAurasDueToSpell(SPELL_TRANSFORM); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_OFF); - - if (pInst) - pInst->SetData(DATA_CTHUN_PHASE, PHASE_NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void SpawnEyeTentacle(float x, float y) - { - Creature* Spawned; - Spawned = DoSpawnCreature(MOB_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500); - if (Spawned && Spawned->AI()) - if (Unit *pTarget = SelectRandomNotStomach()) - Spawned->AI()->AttackStart(pTarget); - } - - Unit* SelectRandomNotStomach() - { - if (Stomach_Map.empty()) - return NULL; - - UNORDERED_MAP::const_iterator i = Stomach_Map.begin(); - - std::list temp; - std::list::const_iterator j; - - //Get all players in map - while (i != Stomach_Map.end()) - { - //Check for valid player - Unit* pUnit = Unit::GetUnit(*me, i->first); - - //Only units out of stomach - if (pUnit && i->second == false) - temp.push_back(pUnit); - - ++i; - } - - if (temp.empty()) - return NULL; - - j = temp.begin(); - - //Get random but only if we have more than one unit on threat list - if (temp.size() > 1) - advance (j , rand() % (temp.size() - 1)); - - return (*j); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - { - //No target so we'll use this section to do our random wispers instance wide - //WisperTimer - if (WisperTimer <= diff) - { - Map* pMap = me->GetMap(); - if (!pMap->IsDungeon()) return; - - //Play random sound to the zone - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) - { - if (Player* pPlr = itr->getSource()) - pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER,pPlr); - } - } - - //One random wisper every 90 - 300 seconds - WisperTimer = urand(90000,300000); - } else WisperTimer -= diff; - - return; - } - - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - //No instance - if (!pInst) - return; - - uint32 currentPhase = pInst->GetData(DATA_CTHUN_PHASE); - if (currentPhase == PHASE_CTHUN_STOMACH || currentPhase == PHASE_CTHUN_WEAK) - { - // EyeTentacleTimer - if (EyeTentacleTimer <= diff) - { - //Spawn the 8 Eye Tentacles in the corret spots - SpawnEyeTentacle(0, 20); //south - SpawnEyeTentacle(10, 10); //south west - SpawnEyeTentacle(20, 0); //west - SpawnEyeTentacle(10, -10); //north west - - SpawnEyeTentacle(0, -20); //north - SpawnEyeTentacle(-10, -10); //north east - SpawnEyeTentacle(-20, 0); // east - SpawnEyeTentacle(-10, 10); // south east - - EyeTentacleTimer = 30000; // every 30sec in phase 2 - } else EyeTentacleTimer -= diff; - } - - switch (currentPhase) - { - //Transition phase - case PHASE_CTHUN_TRANSITION: - //PhaseTimer - if (PhaseTimer <= diff) - { - //Switch - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); - - //Switch to c'thun model - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_TRANSFORM, false); - me->SetHealth(me->GetMaxHealth()); - - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - //Emerging phase - //AttackStart(Unit::GetUnit(*me, HoldpPlayer)); - DoZoneInCombat(); - - //Place all units in threat list on outside of stomach - Stomach_Map.clear(); - - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - //Outside stomach - Stomach_Map[(*i)->getUnitGuid()] = false; - } - - //Spawn 2 flesh tentacles - FleshTentaclesKilled = 0; - - //Spawn flesh tentacle - for (uint8 i = 0; i < 2; i++) - { - Creature* spawned = me->SummonCreature(MOB_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); - if (!spawned) - ++FleshTentaclesKilled; - } - - PhaseTimer = 0; - } else PhaseTimer -= diff; - - break; - - //Body Phase - case PHASE_CTHUN_STOMACH: - //Remove Target field - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - //Weaken - if (FleshTentaclesKilled > 1) - { - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_WEAK); - - DoScriptText(EMOTE_WEAKENED, me); - PhaseTimer = 45000; - - DoCast(me, SPELL_PURPLE_COLORATION, true); - - UNORDERED_MAP::iterator i = Stomach_Map.begin(); - - //Kick all players out of stomach - while (i != Stomach_Map.end()) - { - //Check for valid player - Unit* pUnit = Unit::GetUnit(*me, i->first); - - //Only move units in stomach - if (pUnit && i->second == true) - { - //Teleport each player out - DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+10, rand()%6); - - //Cast knockback on them - DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); - - //Remove the acid debuff - pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); - - i->second = false; - } - ++i; - } - - return; - } - - //Stomach acid - if (StomachAcidTimer <= diff) - { - //Apply aura to all players in stomach - UNORDERED_MAP::iterator i = Stomach_Map.begin(); - - while (i != Stomach_Map.end()) - { - //Check for valid player - Unit* pUnit = Unit::GetUnit(*me, i->first); - - //Only apply to units in stomach - if (pUnit && i->second == true) - { - //Cast digestive acid on them - DoCast(pUnit, SPELL_DIGESTIVE_ACID, true); - - //Check if player should be kicked from stomach - if (pUnit->IsWithinDist3d(&KickPos, 15.0f)) - { - //Teleport each player out - DoTeleportPlayer(pUnit, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+10, rand()%6); - - //Cast knockback on them - DoCast(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, true); - - //Remove the acid debuff - pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID); - - i->second = false; - } - } - ++i; - } - - StomachAcidTimer = 4000; - } else StomachAcidTimer -= diff; - - //Stomach Enter Timer - if (StomachEnterTimer <= diff) - { - if (Unit *pTarget = SelectRandomNotStomach()) - { - //Set target in stomach - Stomach_Map[pTarget->GetGUID()] = true; - pTarget->InterruptNonMeleeSpells(false); - pTarget->CastSpell(pTarget, SPELL_MOUTH_TENTACLE, true, NULL, NULL, me->GetGUID()); - StomachEnterTarget = pTarget->GetGUID(); - StomachEnterVisTimer = 3800; - } - - StomachEnterTimer = 13800; - } else StomachEnterTimer -= diff; - - if (StomachEnterVisTimer && StomachEnterTarget) - if (StomachEnterVisTimer <= diff) - { - //Check for valid player - Unit* pUnit = Unit::GetUnit(*me, StomachEnterTarget); - - if (pUnit) - { - DoTeleportPlayer(pUnit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O); - } - - StomachEnterTarget = 0; - StomachEnterVisTimer = 0; - } else StomachEnterVisTimer -= diff; - - //GientClawTentacleTimer - if (GiantClawTentacleTimer <= diff) - { - if (Unit *pTarget = SelectRandomNotStomach()) - { - //Spawn claw tentacle on the random target - if (Creature* spawned = me->SummonCreature(MOB_GIANT_CLAW_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500)) - if (spawned->AI()) - spawned->AI()->AttackStart(pTarget); - } - - //One giant claw tentacle every minute - GiantClawTentacleTimer = 60000; - } else GiantClawTentacleTimer -= diff; - - //GiantEyeTentacleTimer - if (GiantEyeTentacleTimer <= diff) - { - if (Unit *pTarget = SelectRandomNotStomach()) - { - //Spawn claw tentacle on the random target - if (Creature* spawned = me->SummonCreature(MOB_GIANT_EYE_TENTACLE, *pTarget, TEMPSUMMON_CORPSE_DESPAWN, 500)) - if (spawned->AI()) - spawned->AI()->AttackStart(pTarget); - } - - //One giant eye tentacle every minute - GiantEyeTentacleTimer = 60000; - } else GiantEyeTentacleTimer -= diff; - - break; - - //Weakened state - case PHASE_CTHUN_WEAK: - //PhaseTimer - if (PhaseTimer <= diff) - { - //Switch - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_STOMACH); - - //Remove purple coloration - me->RemoveAurasDueToSpell(SPELL_PURPLE_COLORATION); - - //Spawn 2 flesh tentacles - FleshTentaclesKilled = 0; - - //Spawn flesh tentacle - for (uint8 i = 0; i < 2; i++) - { - Creature* spawned = me->SummonCreature(MOB_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN); - if (!spawned) - ++FleshTentaclesKilled; - } - - PhaseTimer = 0; - } else PhaseTimer -= diff; - - break; - } - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInst) - pInst->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - //No instance - if (!pInst) - return; - - switch (pInst->GetData(DATA_CTHUN_PHASE)) - { - case PHASE_CTHUN_STOMACH: - //Not weakened so reduce damage by 99% - damage /= 100; - if (damage == 0) - damage = 1; - - //Prevent death in non-weakened state - if (damage >= me->GetHealth()) - damage = 0; - - return; - - case PHASE_CTHUN_WEAK: - //Weakened - takes normal damage - return; - - default: - damage = 0; - break; - } - } - - void DoAction(const int32 param) - { - switch(param) - { - case ACTION_FLESH_TENTACLE_KILLED: - ++FleshTentaclesKilled; - break; - } - } -}; - -struct eye_tentacleAI : public Scripted_NoMovementAI -{ - eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - } - - uint32 MindflayTimer; - uint32 KillSelfTimer; - uint64 Portal; - - void JustDied(Unit* /*who*/) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - } - - void Reset() - { - //Mind flay half a second after we spawn - MindflayTimer = 500; - - //This prevents eyes from overlapping - KillSelfTimer = 35000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //KillSelfTimer - if (KillSelfTimer <= diff) - { - me->Kill(me); - return; - } else KillSelfTimer -= diff; - - //MindflayTimer - if (MindflayTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && !pTarget->HasAura(SPELL_DIGESTIVE_ACID)) - DoCast(pTarget, SPELL_MIND_FLAY); - - //Mindflay every 10 seconds - MindflayTimer = 10000; - } else MindflayTimer -= diff; - } -}; - -struct claw_tentacleAI : public Scripted_NoMovementAI -{ - claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - - if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - } - - uint32 GroundRuptureTimer; - uint32 HamstringTimer; - uint32 EvadeTimer; - uint64 Portal; - - void JustDied(Unit* /*who*/) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - } - - void Reset() - { - //First rupture should happen half a second after we spawn - GroundRuptureTimer = 500; - HamstringTimer = 2000; - EvadeTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //EvadeTimer - if (!me->IsWithinMeleeRange(me->getVictim())) - if (EvadeTimer <= diff) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - - //Dissapear and reappear at new position - me->SetVisibility(VISIBILITY_OFF); - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget) - { - me->Kill(me); - return; - } - - if (!pTarget->HasAura(SPELL_DIGESTIVE_ACID)) - { - me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); - if (Creature* pPortal = me->SummonCreature(MOB_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - - GroundRuptureTimer = 500; - HamstringTimer = 2000; - EvadeTimer = 5000; - AttackStart(pTarget); - } - - me->SetVisibility(VISIBILITY_ON); - } else EvadeTimer -= diff; - - //GroundRuptureTimer - if (GroundRuptureTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); - GroundRuptureTimer = 30000; - } else GroundRuptureTimer -= diff; - - //HamstringTimer - if (HamstringTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - HamstringTimer = 5000; - } else HamstringTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct giant_claw_tentacleAI : public Scripted_NoMovementAI -{ - giant_claw_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - - if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - } - - uint32 GroundRuptureTimer; - uint32 ThrashTimer; - uint32 HamstringTimer; - uint32 EvadeTimer; - uint64 Portal; - - void JustDied(Unit* /*who*/) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - } - - void Reset() - { - //First rupture should happen half a second after we spawn - GroundRuptureTimer = 500; - HamstringTimer = 2000; - ThrashTimer = 5000; - EvadeTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //EvadeTimer - if (!me->IsWithinMeleeRange(me->getVictim())) - if (EvadeTimer <= diff) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - - //Dissapear and reappear at new position - me->SetVisibility(VISIBILITY_OFF); - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (!pTarget) - { - me->Kill(me); - return; - } - - if (!pTarget->HasAura(SPELL_DIGESTIVE_ACID)) - { - me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0); - if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - - GroundRuptureTimer = 500; - HamstringTimer = 2000; - ThrashTimer = 5000; - EvadeTimer = 5000; - AttackStart(pTarget); - } - - me->SetVisibility(VISIBILITY_ON); - - } else EvadeTimer -= diff; - - //GroundRuptureTimer - if (GroundRuptureTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); - GroundRuptureTimer = 30000; - } else GroundRuptureTimer -= diff; - - //ThrashTimer - if (ThrashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_THRASH); - ThrashTimer = 10000; - } else ThrashTimer -= diff; - - //HamstringTimer - if (HamstringTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMSTRING); - HamstringTimer = 10000; - } else HamstringTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct giant_eye_tentacleAI : public Scripted_NoMovementAI -{ - giant_eye_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - - if (Creature* pPortal = me->SummonCreature(MOB_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN)) - { - pPortal->SetReactState(REACT_PASSIVE); - Portal = pPortal->GetGUID(); - } - } - - uint32 BeamTimer; - uint64 Portal; - - void JustDied(Unit* /*who*/) - { - if (Unit* p = Unit::GetUnit(*me, Portal)) - p->Kill(p); - } - - void Reset() - { - //Green Beam half a second after we spawn - BeamTimer = 500; - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - - //BeamTimer - if (BeamTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && !pTarget->HasAura(SPELL_DIGESTIVE_ACID)) - DoCast(pTarget, SPELL_GREEN_BEAM); - - //Beam every 2 seconds - BeamTimer = 2100; - } else BeamTimer -= diff; - } -}; - -struct flesh_tentacleAI : public Scripted_NoMovementAI -{ - flesh_tentacleAI(Creature *c) : Scripted_NoMovementAI(c) - { - SetCombatMovement(false); - } - - void JustDied(Unit* /*killer*/) - { - if (CAST_SUM(me)) - if (Creature* pSummoner = CAST_CRE(CAST_SUM(me)->GetSummoner())) - if (pSummoner->AI()) - pSummoner->AI()->DoAction(ACTION_FLESH_TENTACLE_KILLED); - } -}; - -//GetAIs -CreatureAI* GetAI_eye_of_cthun(Creature* pCreature) -{ - return new eye_of_cthunAI (pCreature); -} - -CreatureAI* GetAI_cthun(Creature* pCreature) -{ - return new cthunAI (pCreature); -} - -CreatureAI* GetAI_eye_tentacle(Creature* pCreature) -{ - return new eye_tentacleAI (pCreature); -} - -CreatureAI* GetAI_claw_tentacle(Creature* pCreature) -{ - return new claw_tentacleAI (pCreature); -} - -CreatureAI* GetAI_giant_claw_tentacle(Creature* pCreature) -{ - return new giant_claw_tentacleAI (pCreature); -} - -CreatureAI* GetAI_giant_eye_tentacle(Creature* pCreature) -{ - return new giant_eye_tentacleAI (pCreature); -} - -CreatureAI* GetAI_flesh_tentacle(Creature* pCreature) -{ - return new flesh_tentacleAI (pCreature); -} - -void AddSC_boss_cthun() -{ - Script *newscript; - - //Eye - newscript = new Script; - newscript->Name = "boss_eye_of_cthun"; - newscript->GetAI = &GetAI_eye_of_cthun; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_cthun"; - newscript->GetAI = &GetAI_cthun; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_eye_tentacle"; - newscript->GetAI = &GetAI_eye_tentacle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_claw_tentacle"; - newscript->GetAI = &GetAI_claw_tentacle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_giant_claw_tentacle"; - newscript->GetAI = &GetAI_giant_claw_tentacle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_giant_eye_tentacle"; - newscript->GetAI = &GetAI_giant_eye_tentacle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_giant_flesh_tentacle"; - newscript->GetAI = &GetAI_flesh_tentacle; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp deleted file mode 100644 index 32d5ec1c3df..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Fankriss -SD%Complete: 100 -SDComment: sound not implemented -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" - -#define SOUND_SENTENCE_YOU 8588 -#define SOUND_SERVE_TO 8589 -#define SOUND_LAWS 8590 -#define SOUND_TRESPASS 8591 -#define SOUND_WILL_BE 8592 - -#define SPELL_MORTAL_WOUND 28467 -#define SPELL_ROOT 28858 - -// Enrage for his spawns -#define SPELL_ENRAGE 28798 - -struct boss_fankrissAI : public ScriptedAI -{ - boss_fankrissAI(Creature *c) : ScriptedAI(c) {} - - uint32 MortalWound_Timer; - uint32 SpawnHatchlings_Timer; - uint32 SpawnSpawns_Timer; - int Rand; - int RandX; - int RandY; - - Creature* Hatchling; - Creature* Spawn; - - void Reset() - { - MortalWound_Timer = 10000 + rand()%5000; - SpawnHatchlings_Timer = 6000 + rand()%6000; - SpawnSpawns_Timer = 15000 + rand()%30000; - } - - void SummonSpawn(Unit* victim) - { - if (!victim) - return; - - Rand = 10 + (rand()%10); - switch (rand()%2) - { - case 0: RandX = 0 - Rand; break; - case 1: RandX = 0 + Rand; break; - } - Rand = 0; - Rand = 10 + (rand()%10); - switch (rand()%2) - { - case 0: RandY = 0 - Rand; break; - case 1: RandY = 0 + Rand; break; - } - Rand = 0; - Spawn = DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); - if (Spawn) - Spawn->AI()->AttackStart(victim); - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //MortalWound_Timer - if (MortalWound_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - MortalWound_Timer = 10000 + rand()%10000; - } else MortalWound_Timer -= diff; - - //Summon 1-3 Spawns of Fankriss at random time. - if (SpawnSpawns_Timer <= diff) - { - switch (urand(0,2)) - { - case 0: - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - break; - case 1: - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - break; - case 2: - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - SummonSpawn(SelectUnit(SELECT_TARGET_RANDOM,0)); - break; - } - SpawnSpawns_Timer = 30000 + rand()%30000; - } else SpawnSpawns_Timer -= diff; - - // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer. - //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot. - if (me->GetHealth()*100 / me->GetMaxHealth() > 3) - { - if (SpawnHatchlings_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, SPELL_ROOT); - - if (DoGetThreat(pTarget)) - DoModifyThreatPercent(pTarget, -100); - - switch(urand(0,2)) - { - case 0: - DoTeleportPlayer(pTarget, -8106.0142,1289.2900,-74.419533,5.112); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - break; - case 1: - DoTeleportPlayer(pTarget, -7990.135354,1155.1907,-78.849319,2.608); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - break; - case 2: - DoTeleportPlayer(pTarget,-8159.7753,1127.9064,-76.868660,0.675); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()-3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-3, pTarget->GetPositionY()+3, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()-5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - Hatchling = me->SummonCreature(15962, pTarget->GetPositionX()-5, pTarget->GetPositionY()+5, pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - if (Hatchling) - Hatchling->AI()->AttackStart(pTarget); - break; - } - } - SpawnHatchlings_Timer = 45000 + rand()%15000; - } else SpawnHatchlings_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_fankriss(Creature* pCreature) -{ - return new boss_fankrissAI (pCreature); -} - -void AddSC_boss_fankriss() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_fankriss"; - newscript->GetAI = &GetAI_boss_fankriss; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp deleted file mode 100644 index f0e3a425edd..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Huhuran -SD%Complete: 100 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_GENERIC_FRENZY_KILL -1000001 -#define EMOTE_GENERIC_BERSERK -1000004 - -#define SPELL_FRENZY 26051 -#define SPELL_BERSERK 26068 -#define SPELL_POISONBOLT 26052 -#define SPELL_NOXIOUSPOISON 26053 -#define SPELL_WYVERNSTING 26180 -#define SPELL_ACIDSPIT 26050 - -struct boss_huhuranAI : public ScriptedAI -{ - boss_huhuranAI(Creature *c) : ScriptedAI(c) {} - - uint32 Frenzy_Timer; - uint32 Wyvern_Timer; - uint32 Spit_Timer; - uint32 PoisonBolt_Timer; - uint32 NoxiousPoison_Timer; - uint32 FrenzyBack_Timer; - - bool Frenzy; - bool Berserk; - - void Reset() - { - Frenzy_Timer = 25000 + rand()%10000; - Wyvern_Timer = 18000 + rand()%10000; - Spit_Timer = 8000; - PoisonBolt_Timer = 4000; - NoxiousPoison_Timer = 10000 + rand()%10000; - FrenzyBack_Timer = 15000; - - Frenzy = false; - Berserk = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frenzy_Timer - if (!Frenzy && Frenzy_Timer <= diff) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(EMOTE_GENERIC_FRENZY_KILL, me); - Frenzy = true; - PoisonBolt_Timer = 3000; - Frenzy_Timer = 25000 + rand()%10000; - } else Frenzy_Timer -= diff; - - // Wyvern Timer - if (Wyvern_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_WYVERNSTING); - Wyvern_Timer = 15000 + rand()%17000; - } else Wyvern_Timer -= diff; - - //Spit Timer - if (Spit_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ACIDSPIT); - Spit_Timer = 5000 + rand()%5000; - } else Spit_Timer -= diff; - - //NoxiousPoison_Timer - if (NoxiousPoison_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_NOXIOUSPOISON); - NoxiousPoison_Timer = 12000 + rand()%12000; - } else NoxiousPoison_Timer -= diff; - - //PoisonBolt only if frenzy or berserk - if (Frenzy || Berserk) - { - if (PoisonBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISONBOLT); - PoisonBolt_Timer = 3000; - } else PoisonBolt_Timer -= diff; - } - - //FrenzyBack_Timer - if (Frenzy && FrenzyBack_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - Frenzy = false; - FrenzyBack_Timer = 15000; - } else FrenzyBack_Timer -= diff; - - if (!Berserk && me->GetHealth()*100 / me->GetMaxHealth() < 31) - { - me->InterruptNonMeleeSpells(false); - DoScriptText(EMOTE_GENERIC_BERSERK, me); - DoCast(me, SPELL_BERSERK); - Berserk = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_huhuran(Creature* pCreature) -{ - return new boss_huhuranAI (pCreature); -} - -void AddSC_boss_huhuran() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_huhuran"; - newscript->GetAI = &GetAI_boss_huhuran; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp deleted file mode 100644 index 1dd642c38f4..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_ouro.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ouro -SD%Complete: 85 -SDComment: No model for submerging. Currently just invisible. -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" - -#define SPELL_SWEEP 26103 -#define SPELL_SANDBLAST 26102 -#define SPELL_GROUND_RUPTURE 26100 -#define SPELL_BIRTH 26262 //The Birth Animation - -#define SPELL_DIRTMOUND_PASSIVE 26092 - -struct boss_ouroAI : public ScriptedAI -{ - boss_ouroAI(Creature *c) : ScriptedAI(c) {} - - uint32 Sweep_Timer; - uint32 SandBlast_Timer; - uint32 Submerge_Timer; - uint32 Back_Timer; - uint32 ChangeTarget_Timer; - uint32 Spawn_Timer; - - bool Enrage; - bool Submerged; - - void Reset() - { - Sweep_Timer = 5000 + rand()%5000; - SandBlast_Timer = 20000 + rand()%15000; - Submerge_Timer = 90000 + rand()%60000; - Back_Timer = 30000 + rand()%15000; - ChangeTarget_Timer = 5000 + rand()%3000; - Spawn_Timer = 10000 + rand()%10000; - - Enrage = false; - Submerged = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoCast(me->getVictim(), SPELL_BIRTH); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sweep_Timer - if (!Submerged && Sweep_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SWEEP); - Sweep_Timer = 15000 + rand()%15000; - } else Sweep_Timer -= diff; - - //SandBlast_Timer - if (!Submerged && SandBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SANDBLAST); - SandBlast_Timer = 20000 + rand()%15000; - } else SandBlast_Timer -= diff; - - //Submerge_Timer - if (!Submerged && Submerge_Timer <= diff) - { - //Cast - me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(35); - DoCast(me, SPELL_DIRTMOUND_PASSIVE); - - Submerged = true; - Back_Timer = 30000 + rand()%15000; - } else Submerge_Timer -= diff; - - //ChangeTarget_Timer - if (Submerged && ChangeTarget_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (pTarget) - DoTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()); - - ChangeTarget_Timer = 10000 + rand()%10000; - } else ChangeTarget_Timer -= diff; - - //Back_Timer - if (Submerged && Back_Timer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - - DoCast(me->getVictim(), SPELL_GROUND_RUPTURE); - - Submerged = false; - Submerge_Timer = 60000 + rand()%60000; - } else Back_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ouro(Creature* pCreature) -{ - return new boss_ouroAI (pCreature); -} - -void AddSC_boss_ouro() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ouro"; - newscript->GetAI = &GetAI_boss_ouro; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp deleted file mode 100644 index 282a25b7215..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_sartura.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Sartura -SD%Complete: 95 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1531008 -#define SAY_SLAY -1531009 -#define SAY_DEATH -1531010 - -#define SPELL_WHIRLWIND 26083 -#define SPELL_ENRAGE 28747 //Not sure if right ID. -#define SPELL_ENRAGEHARD 28798 - -//Guard Spell -#define SPELL_WHIRLWINDADD 26038 -#define SPELL_KNOCKBACK 26027 - -struct boss_sarturaAI : public ScriptedAI -{ - boss_sarturaAI(Creature *c) : ScriptedAI(c) {} - - uint32 WhirlWind_Timer; - uint32 WhirlWindRandom_Timer; - uint32 WhirlWindEnd_Timer; - uint32 AggroReset_Timer; - uint32 AggroResetEnd_Timer; - uint32 EnrageHard_Timer; - - bool Enraged; - bool EnragedHard; - bool WhirlWind; - bool AggroReset; - - void Reset() - { - WhirlWind_Timer = 30000; - WhirlWindRandom_Timer = 3000 + rand()%4000; - WhirlWindEnd_Timer = 15000; - AggroReset_Timer = 45000 + rand()%10000; - AggroResetEnd_Timer = 5000; - EnrageHard_Timer = 10*60000; - - WhirlWind = false; - AggroReset = false; - Enraged = false; - EnragedHard = false; - - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_SLAY, me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (WhirlWind) - { - if (WhirlWindRandom_Timer <= diff) - { - //Attack random Gamers - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget) - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - - WhirlWindRandom_Timer = 3000 + rand()%4000; - } else WhirlWindRandom_Timer -= diff; - - if (WhirlWindEnd_Timer <= diff) - { - WhirlWind = false; - WhirlWind_Timer = 25000 + rand()%15000; - } else WhirlWindEnd_Timer -= diff; - } - - if (!WhirlWind) - { - if (WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - WhirlWind = true; - WhirlWindEnd_Timer = 15000; - } else WhirlWind_Timer -= diff; - - if (AggroReset_Timer <= diff) - { - //Attack random Gamers - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget) - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - - AggroReset = true; - AggroReset_Timer = 2000 + rand()%3000; - } else AggroReset_Timer -= diff; - - if (AggroReset) - { - if (AggroResetEnd_Timer <= diff) - { - AggroReset = false; - AggroResetEnd_Timer = 5000; - AggroReset_Timer = 35000 + rand()%10000; - } else AggroResetEnd_Timer -= diff; - } - - //If she is 20% enrage - if (!Enraged) - { - if (me->GetHealth()*100 / me->GetMaxHealth() <= 20 && !me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } - } - - //After 10 minutes hard enrage - if (!EnragedHard) - { - if (EnrageHard_Timer <= diff) - { - DoCast(me, SPELL_ENRAGEHARD); - EnragedHard = true; - } else EnrageHard_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - } -}; - -struct mob_sartura_royal_guardAI : public ScriptedAI -{ - mob_sartura_royal_guardAI(Creature *c) : ScriptedAI(c) {} - - uint32 WhirlWind_Timer; - uint32 WhirlWindRandom_Timer; - uint32 WhirlWindEnd_Timer; - uint32 AggroReset_Timer; - uint32 AggroResetEnd_Timer; - uint32 KnockBack_Timer; - - bool WhirlWind; - bool AggroReset; - - void Reset() - { - WhirlWind_Timer = 30000; - WhirlWindRandom_Timer = 3000 + rand()%4000; - WhirlWindEnd_Timer = 15000; - AggroReset_Timer = 45000 + rand()%10000; - AggroResetEnd_Timer = 5000; - KnockBack_Timer = 10000; - - WhirlWind = false; - AggroReset = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!WhirlWind && WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWINDADD); - WhirlWind = true; - WhirlWind_Timer = 25000 + rand()%15000; - WhirlWindEnd_Timer = 15000; - } else WhirlWind_Timer -= diff; - - if (WhirlWind) - { - if (WhirlWindRandom_Timer <= diff) - { - //Attack random Gamers - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget) - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - - WhirlWindRandom_Timer = 3000 + rand()%4000; - } else WhirlWindRandom_Timer -= diff; - - if (WhirlWindEnd_Timer <= diff) - { - WhirlWind = false; - } else WhirlWindEnd_Timer -= diff; - } - - if (!WhirlWind) - { - if (AggroReset_Timer <= diff) - { - //Attack random Gamers - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget) - me->AddThreat(pTarget, 1.0f); - me->TauntApply(pTarget); - AttackStart(pTarget); - - AggroReset = true; - AggroReset_Timer = 2000 + rand()%3000; - } else AggroReset_Timer -= diff; - - if (KnockBack_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWINDADD); - KnockBack_Timer = 10000 + rand()%10000; - } else KnockBack_Timer -= diff; - } - - if (AggroReset) - { - if (AggroResetEnd_Timer <= diff) - { - AggroReset = false; - AggroResetEnd_Timer = 5000; - AggroReset_Timer = 30000 + rand()%10000; - } else AggroResetEnd_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_sartura(Creature* pCreature) -{ - return new boss_sarturaAI (pCreature); -} - -CreatureAI* GetAI_mob_sartura_royal_guard(Creature* pCreature) -{ - return new mob_sartura_royal_guardAI (pCreature); -} - -void AddSC_boss_sartura() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_sartura"; - newscript->GetAI = &GetAI_boss_sartura; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_sartura_royal_guard"; - newscript->GetAI = &GetAI_mob_sartura_royal_guard; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp deleted file mode 100644 index 7e52bed750c..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_skeram.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Skeram -SD%Complete: 75 -SDComment: Mind Control buggy. -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" -#include "Group.h" - -#define SAY_AGGRO1 -1531000 -#define SAY_AGGRO2 -1531001 -#define SAY_AGGRO3 -1531002 -#define SAY_SLAY1 -1531003 -#define SAY_SLAY2 -1531004 -#define SAY_SLAY3 -1531005 -#define SAY_SPLIT -1531006 -#define SAY_DEATH -1531007 - -#define SPELL_ARCANE_EXPLOSION 25679 -#define SPELL_EARTH_SHOCK 26194 -#define SPELL_TRUE_FULFILLMENT4 26526 -#define SPELL_BLINK 28391 - -class ov_mycoordinates -{ - public: - float x,y,z,r; - ov_mycoordinates(float cx, float cy, float cz, float cr) - { - x = cx; y = cy; z = cz; r = cr; - } -}; - -struct boss_skeramAI : public ScriptedAI -{ - boss_skeramAI(Creature *c) : ScriptedAI(c) - { - IsImage = false; - } - - uint32 ArcaneExplosion_Timer; - uint32 EarthShock_Timer; - uint32 FullFillment_Timer; - uint32 Blink_Timer; - uint32 Invisible_Timer; - - bool Images75; - bool Images50; - bool Images25; - bool IsImage; - bool Invisible; - - void Reset() - { - ArcaneExplosion_Timer = 6000 + rand()%6000; - EarthShock_Timer = 2000; - FullFillment_Timer = 15000; - Blink_Timer = 8000 + rand()%12000; - Invisible_Timer = 500; - - Images75 = false; - Images50 = false; - Images25 = false; - Invisible = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - if (IsImage) - me->setDeathState(JUST_DIED); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit* /*Killer*/) - { - if (!IsImage) - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - if (IsImage || Images75) - return; - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); - ArcaneExplosion_Timer = 8000 + rand()%10000; - } else ArcaneExplosion_Timer -= diff; - - //If we are within range melee the target - if (me->IsWithinMeleeRange(me->getVictim())) - { - //Make sure our attack is ready and we arn't currently casting - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - }else - { - //EarthShock_Timer - if (EarthShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_EARTH_SHOCK); - EarthShock_Timer = 1000; - } else EarthShock_Timer -= diff; - } - - //Blink_Timer - if (Blink_Timer <= diff) - { - //DoCast(me, SPELL_BLINK); - switch (urand(0,2)) - { - case 0: - me->GetMap()->CreatureRelocation(me, -8340.782227,2083.814453,125.648788,0.0f); - DoResetThreat(); - break; - case 1: - me->GetMap()->CreatureRelocation(me, -8341.546875,2118.504639,133.058151,0.0f); - DoResetThreat(); - break; - case 2: - me->GetMap()->CreatureRelocation(me, -8318.822266,2058.231201,133.058151,0.0f); - DoResetThreat(); - break; - } - DoStopAttack(); - - Blink_Timer= 20000 + rand()%20000; - } else Blink_Timer -= diff; - - int procent = (int) (me->GetHealth()*100 / me->GetMaxHealth() +0.5); - - //Summoning 2 Images and teleporting to a random position on 75% health - if ((!Images75 && !IsImage) && (procent <= 75 && procent > 70)) - DoSplit(75); - - //Summoning 2 Images and teleporting to a random position on 50% health - if ((!Images50 && !IsImage) && - (procent <= 50 && procent > 45)) - DoSplit(50); - - //Summoning 2 Images and teleporting to a random position on 25% health - if ((!Images25 && !IsImage) && (procent <= 25 && procent > 20)) - DoSplit(25); - - //Invisible_Timer - if (Invisible) - { - if (Invisible_Timer <= diff) - { - //Making Skeram visible after telporting - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - Invisible_Timer = 2500; - Invisible = false; - } else Invisible_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void DoSplit(int atPercent /* 75 50 25 */) - { - DoScriptText(SAY_SPLIT, me); - - ov_mycoordinates *place1 = new ov_mycoordinates(-8340.782227,2083.814453,125.648788,0); - ov_mycoordinates *place2 = new ov_mycoordinates(-8341.546875,2118.504639,133.058151,0); - ov_mycoordinates *place3 = new ov_mycoordinates(-8318.822266,2058.231201,133.058151,0); - - ov_mycoordinates *bossc=place1, *i1=place2, *i2=place3; - - switch (urand(0,2)) - { - case 0: - bossc=place1; - i1=place2; - i2=place3; - break; - case 1: - bossc=place2; - i1=place1; - i2=place3; - break; - case 2: - bossc=place3; - i1=place1; - i2=place2; - break; - } - - for (uint16 i = 0; i < 41; ++i) - { - if (Player *pTarget = CAST_PLR(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))) - { - if (Group *pGrp = pTarget->GetGroup()) - for (uint8 ico = 0; ico < TARGETICONCOUNT; ++ico) - { - //if (grp->m_targetIcons[ico] == me->GetGUID()) -- private member :( - pGrp->SetTargetIcon(ico, 0, 0); - } - - break; - } - } - - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_OFF); - me->GetMap()->CreatureRelocation(me, bossc->x, bossc->y, bossc->z, bossc->r); - Invisible = true; - delete place1; - delete place2; - delete place3; - DoResetThreat(); - DoStopAttack(); - - switch (atPercent) - { - case 75: Images75 = true; break; - case 50: Images50 = true; break; - case 25: Images25 = true; break; - } - - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - Creature *Image1 = me->SummonCreature(15263, i1->x, i1->y, i1->z, i1->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); - if (Image1) - { - Image1->SetMaxHealth(me->GetMaxHealth() / 5); - Image1->SetHealth(me->GetHealth() / 5); - if (pTarget) - Image1->AI()->AttackStart(pTarget); - CAST_AI(boss_skeramAI, Image1->AI())->IsImage = true; - } - - Creature *Image2 = me->SummonCreature(15263,i2->x, i2->y, i2->z, i2->r, TEMPSUMMON_CORPSE_DESPAWN, 30000); - if (Image2) - { - Image2->SetMaxHealth(me->GetMaxHealth() / 5); - Image2->SetHealth(me->GetHealth() / 5); - if (pTarget) - Image2->AI()->AttackStart(pTarget); - CAST_AI(boss_skeramAI, Image2->AI())->IsImage = true; - } - Invisible = true; - } - -}; - -CreatureAI* GetAI_boss_skeram(Creature* pCreature) -{ - return new boss_skeramAI (pCreature); -} - -void AddSC_boss_skeram() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_skeram"; - newscript->GetAI = &GetAI_boss_skeram; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp deleted file mode 100644 index 73f17485f7f..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp +++ /dev/null @@ -1,596 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Twinemperors -SD%Complete: 95 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" -#include "WorldPacket.h" - -#include "Item.h" -#include "Spell.h" - -#define SPELL_HEAL_BROTHER 7393 -#define SPELL_TWIN_TELEPORT 800 // CTRA watches for this spell to start its teleport timer -#define SPELL_TWIN_TELEPORT_VISUAL 26638 // visual - -#define SPELL_EXPLODEBUG 804 -#define SPELL_MUTATE_BUG 802 - -#define SOUND_VN_DEATH 8660 //8660 - Death - Feel -#define SOUND_VN_AGGRO 8661 //8661 - Aggro - Let none -#define SOUND_VN_KILL 8662 //8661 - Kill - your fate - -#define SOUND_VL_AGGRO 8657 //8657 - Aggro - To Late -#define SOUND_VL_KILL 8658 //8658 - Kill - You will not -#define SOUND_VL_DEATH 8659 //8659 - Death - -#define PULL_RANGE 50 -#define ABUSE_BUG_RANGE 20 -#define SPELL_BERSERK 26662 -#define TELEPORTTIME 30000 - -#define SPELL_UPPERCUT 26007 -#define SPELL_UNBALANCING_STRIKE 26613 - -#define VEKLOR_DIST 20 // VL will not come to melee when attacking - -#define SPELL_SHADOWBOLT 26006 -#define SPELL_BLIZZARD 26607 -#define SPELL_ARCANEBURST 568 - -struct boss_twinemperorsAI : public ScriptedAI -{ - boss_twinemperorsAI(Creature *c): ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Heal_Timer; - uint32 Teleport_Timer; - bool AfterTeleport; - uint32 AfterTeleportTimer; - bool DontYellWhenDead; - uint32 Abuse_Bug_Timer, BugsTimer; - bool tspellcasted; - uint32 EnrageTimer; - - virtual bool IAmVeklor() = 0; - virtual void Reset() = 0; - virtual void CastSpellOnBug(Creature *pTarget) = 0; - - void TwinReset() - { - Heal_Timer = 0; // first heal immediately when they get close together - Teleport_Timer = TELEPORTTIME; - AfterTeleport = false; - tspellcasted = false; - AfterTeleportTimer = 0; - Abuse_Bug_Timer = 10000 + rand()%7000; - BugsTimer = 2000; - me->clearUnitState(UNIT_STAT_STUNNED); - DontYellWhenDead = false; - EnrageTimer = 15*60000; - } - - Creature *GetOtherBoss() - { - if (pInstance) - return Unit::GetCreature(*me, pInstance->GetData64(IAmVeklor() ? DATA_VEKNILASH : DATA_VEKLOR)); - else - return NULL; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - Unit *pOtherBoss = GetOtherBoss(); - if (pOtherBoss) - { - float dPercent = ((float)damage) / ((float)me->GetMaxHealth()); - int odmg = (int)(dPercent * ((float)pOtherBoss->GetMaxHealth())); - int ohealth = pOtherBoss->GetHealth()-odmg; - pOtherBoss->SetHealth(ohealth > 0 ? ohealth : 0); - if (ohealth <= 0) - { - pOtherBoss->setDeathState(JUST_DIED); - pOtherBoss->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - } - } - - void JustDied(Unit* /*Killer*/) - { - Creature *pOtherBoss = GetOtherBoss(); - if (pOtherBoss) - { - pOtherBoss->SetHealth(0); - pOtherBoss->setDeathState(JUST_DIED); - pOtherBoss->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - CAST_AI(boss_twinemperorsAI, pOtherBoss->AI())->DontYellWhenDead = true; - } - if (!DontYellWhenDead) // I hope AI is not threaded - DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_DEATH : SOUND_VN_DEATH); - } - - void KilledUnit(Unit* /*victim*/) - { - DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_KILL : SOUND_VN_KILL); - } - - void EnterCombat(Unit * who) - { - DoZoneInCombat(); - Creature *pOtherBoss = GetOtherBoss(); - if (pOtherBoss) - { - // TODO: we should activate the other boss location so he can start attackning even if nobody - // is near I dont know how to do that - ScriptedAI *otherAI = CAST_AI(ScriptedAI, pOtherBoss->AI()); - if (!pOtherBoss->isInCombat()) - { - DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_AGGRO : SOUND_VN_AGGRO); - otherAI->AttackStart(who); - otherAI->DoZoneInCombat(); - } - } - } - - void SpellHit(Unit *caster, const SpellEntry *entry) - { - if (caster == me) - return; - - Creature *pOtherBoss = GetOtherBoss(); - if (entry->Id != SPELL_HEAL_BROTHER || !pOtherBoss) - return; - - // add health so we keep same percentage for both brothers - uint32 mytotal = me->GetMaxHealth(), histotal = pOtherBoss->GetMaxHealth(); - float mult = ((float)mytotal) / ((float)histotal); - if (mult < 1) - mult = 1.0f/mult; - #define HEAL_BROTHER_AMOUNT 30000.0f - uint32 largerAmount = (uint32)((HEAL_BROTHER_AMOUNT * mult) - HEAL_BROTHER_AMOUNT); - - if (mytotal > histotal) - { - uint32 h = me->GetHealth()+largerAmount; - me->SetHealth(std::min(mytotal, h)); - } - else - { - uint32 h = pOtherBoss->GetHealth()+largerAmount; - pOtherBoss->SetHealth(std::min(histotal, h)); - } - } - - void TryHealBrother(uint32 diff) - { - if (IAmVeklor()) // this spell heals caster and the other brother so let VN cast it - return; - - if (Heal_Timer <= diff) - { - Unit *pOtherBoss = GetOtherBoss(); - if (pOtherBoss && pOtherBoss->IsWithinDist(me,60)) - { - DoCast(pOtherBoss, SPELL_HEAL_BROTHER); - Heal_Timer = 1000; - } - } else Heal_Timer -= diff; - } - - void TeleportToMyBrother() - { - if (!pInstance) - return; - - Teleport_Timer = TELEPORTTIME; - - if (IAmVeklor()) - return; // mechanics handled by veknilash so they teleport exactly at the same time and to correct coordinates - - Creature *pOtherBoss = GetOtherBoss(); - if (pOtherBoss) - { - //me->MonsterYell("Teleporting ...", LANG_UNIVERSAL, 0); - float other_x = pOtherBoss->GetPositionX(); - float other_y = pOtherBoss->GetPositionY(); - float other_z = pOtherBoss->GetPositionZ(); - float other_o = pOtherBoss->GetOrientation(); - - Map *thismap = me->GetMap(); - thismap->CreatureRelocation(pOtherBoss, me->GetPositionX(), - me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); - thismap->CreatureRelocation(me, other_x, other_y, other_z, other_o); - - SetAfterTeleport(); - CAST_AI(boss_twinemperorsAI, pOtherBoss->AI())->SetAfterTeleport(); - } - } - - void SetAfterTeleport() - { - me->InterruptNonMeleeSpells(false); - DoStopAttack(); - DoResetThreat(); - DoCast(me, SPELL_TWIN_TELEPORT_VISUAL); - me->addUnitState(UNIT_STAT_STUNNED); - AfterTeleport = true; - AfterTeleportTimer = 2000; - tspellcasted = false; - } - - bool TryActivateAfterTTelep(uint32 diff) - { - if (AfterTeleport) - { - if (!tspellcasted) - { - me->clearUnitState(UNIT_STAT_STUNNED); - DoCast(me, SPELL_TWIN_TELEPORT); - me->addUnitState(UNIT_STAT_STUNNED); - } - - tspellcasted = true; - - if (AfterTeleportTimer <= diff) - { - AfterTeleport = false; - me->clearUnitState(UNIT_STAT_STUNNED); - if (Unit *nearu = me->SelectNearestTarget(100)) - { - //DoYell(nearu->GetName(), LANG_UNIVERSAL, 0); - AttackStart(nearu); - me->AddThreat(nearu, 10000); - } - return true; - } - else - { - AfterTeleportTimer -= diff; - // update important timers which would otherwise get skipped - if (EnrageTimer > diff) - EnrageTimer -= diff; - else - EnrageTimer = 0; - if (Teleport_Timer > diff) - Teleport_Timer -= diff; - else - Teleport_Timer = 0; - return false; - } - } - else - { - return true; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - float attackRadius = me->GetAttackDistance(who); - if (attackRadius < PULL_RANGE) - attackRadius = PULL_RANGE; - if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= /*CREATURE_Z_ATTACK_RANGE*/7 /*there are stairs*/) - { - //if (who->HasStealthAura()) - // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - } - } - - Creature *RespawnNearbyBugsAndGetOne() - { - std::list lUnitList; - me->GetCreatureListWithEntryInGrid(lUnitList,15316,150.0f); - me->GetCreatureListWithEntryInGrid(lUnitList,15317,150.0f); - - if (lUnitList.empty()) - return NULL; - - Creature *nearb = NULL; - - for (std::list::const_iterator iter = lUnitList.begin(); iter != lUnitList.end(); ++iter) - { - Creature *c = *iter; - if (c) - { - if (c->isDead()) - { - c->Respawn(); - c->setFaction(7); - c->RemoveAllAuras(); - } - if (c->IsWithinDistInMap(me, ABUSE_BUG_RANGE)) - { - if (!nearb || (rand()%4) == 0) - nearb = c; - } - } - } - return nearb; - } - - void HandleBugs(uint32 diff) - { - if (BugsTimer < diff || Abuse_Bug_Timer <= diff) - { - Creature *c = RespawnNearbyBugsAndGetOne(); - if (Abuse_Bug_Timer <= diff) - { - if (c) - { - CastSpellOnBug(c); - Abuse_Bug_Timer = 10000 + rand()%7000; - } - else - { - Abuse_Bug_Timer = 1000; - } - } - else - { - Abuse_Bug_Timer -= diff; - } - BugsTimer = 2000; - } - else - { - BugsTimer -= diff; - Abuse_Bug_Timer -= diff; - } - } - - void CheckEnrage(uint32 diff) - { - if (EnrageTimer <= diff) - { - if (!me->IsNonMeleeSpellCasted(true)) - { - DoCast(me, SPELL_BERSERK); - EnrageTimer = 60*60000; - } else EnrageTimer = 0; - } else EnrageTimer-=diff; - } -}; - -struct boss_veknilashAI : public boss_twinemperorsAI -{ - bool IAmVeklor() {return false;} - boss_veknilashAI(Creature *c) : boss_twinemperorsAI(c) {} - - uint32 UpperCut_Timer; - uint32 UnbalancingStrike_Timer; - uint32 Scarabs_Timer; - int Rand; - int RandX; - int RandY; - - Creature* Summoned; - - void Reset() - { - TwinReset(); - UpperCut_Timer = 14000 + rand()%15000; - UnbalancingStrike_Timer = 8000 + rand()%10000; - Scarabs_Timer = 7000 + rand()%7000; - - //Added. Can be removed if its included in DB. - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - } - - void CastSpellOnBug(Creature *pTarget) - { - pTarget->setFaction(14); - pTarget->AI()->AttackStart(me->getThreatManager().getHostilTarget()); - pTarget->AddAura(SPELL_MUTATE_BUG, pTarget); - pTarget->SetHealth(pTarget->GetMaxHealth()); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!TryActivateAfterTTelep(diff)) - return; - - //UnbalancingStrike_Timer - if (UnbalancingStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE); - UnbalancingStrike_Timer = 8000+rand()%12000; - } else UnbalancingStrike_Timer -= diff; - - if (UpperCut_Timer <= diff) - { - Unit* randomMelee = SelectTarget(SELECT_TARGET_RANDOM, 0, NOMINAL_MELEE_RANGE, true); - if (randomMelee) - DoCast(randomMelee, SPELL_UPPERCUT); - UpperCut_Timer = 15000+rand()%15000; - } else UpperCut_Timer -= diff; - - HandleBugs(diff); - - //Heal brother when 60yrds close - TryHealBrother(diff); - - //Teleporting to brother - if (Teleport_Timer <= diff) - { - TeleportToMyBrother(); - } else Teleport_Timer -= diff; - - CheckEnrage(diff); - - DoMeleeAttackIfReady(); - } -}; - -struct boss_veklorAI : public boss_twinemperorsAI -{ - bool IAmVeklor() {return true;} - boss_veklorAI(Creature *c) : boss_twinemperorsAI(c) {} - - uint32 ShadowBolt_Timer; - uint32 Blizzard_Timer; - uint32 ArcaneBurst_Timer; - uint32 Scorpions_Timer; - int Rand; - int RandX; - int RandY; - - Creature* Summoned; - - void Reset() - { - TwinReset(); - ShadowBolt_Timer = 0; - Blizzard_Timer = 15000 + rand()%5000; - ArcaneBurst_Timer = 1000; - Scorpions_Timer = 7000 + rand()%7000; - - //Added. Can be removed if its included in DB. - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0); - me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0); - } - - void CastSpellOnBug(Creature *pTarget) - { - pTarget->setFaction(14); - pTarget->AddAura(SPELL_EXPLODEBUG, pTarget); - pTarget->SetHealth(pTarget->GetMaxHealth()); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // reset arcane burst after teleport - we need to do this because - // when VL jumps to VN's location there will be a warrior who will get only 2s to run away - // which is almost impossible - if (AfterTeleport) - ArcaneBurst_Timer = 5000; - if (!TryActivateAfterTTelep(diff)) - return; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - if (!me->IsWithinDist(me->getVictim(), 45.0f)) - me->GetMotionMaster()->MoveChase(me->getVictim(), VEKLOR_DIST, 0); - else - DoCast(me->getVictim(), SPELL_SHADOWBOLT); - ShadowBolt_Timer = 2000; - } else ShadowBolt_Timer -= diff; - - //Blizzard_Timer - if (Blizzard_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45, true); - if (pTarget) - DoCast(pTarget, SPELL_BLIZZARD); - Blizzard_Timer = 15000+rand()%15000; - } else Blizzard_Timer -= diff; - - if (ArcaneBurst_Timer <= diff) - { - Unit *mvic; - if ((mvic=SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) != NULL) - { - DoCast(mvic, SPELL_ARCANEBURST); - ArcaneBurst_Timer = 5000; - } - } else ArcaneBurst_Timer -= diff; - - HandleBugs(diff); - - //Heal brother when 60yrds close - TryHealBrother(diff); - - //Teleporting to brother - if (Teleport_Timer <= diff) - { - TeleportToMyBrother(); - } else Teleport_Timer -= diff; - - CheckEnrage(diff); - - //VL doesn't melee - //DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (who->isTargetableForAttack()) - { - // VL doesn't melee - if (me->Attack(who, false)) - { - me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); - me->AddThreat(who, 0.0f); - } - } - } -}; - -CreatureAI* GetAI_boss_veknilash(Creature* pCreature) -{ - return new boss_veknilashAI (pCreature); -} - -CreatureAI* GetAI_boss_veklor(Creature* pCreature) -{ - return new boss_veklorAI (pCreature); -} - -void AddSC_boss_twinemperors() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_veknilash"; - newscript->GetAI = &GetAI_boss_veknilash; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_veklor"; - newscript->GetAI = &GetAI_boss_veklor; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp deleted file mode 100644 index f5e71a35bae..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Viscidus -SD%Complete: 0 -SDComment: place holder -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_POISON_SHOCK 25993 -#define SPELL_POISONBOLT_VOLLEY 25991 - -#define SPELL_TOXIN_CLOUD 25989 - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp deleted file mode 100644 index 1125a0c8623..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Temple_of_Ahnqiraj -SD%Complete: 80 -SDComment: -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "temple_of_ahnqiraj.h" - -struct instance_temple_of_ahnqiraj : public ScriptedInstance -{ - instance_temple_of_ahnqiraj(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - //If Vem is dead... - bool IsBossDied[3]; - - //Storing Skeram, Vem and Kri. - uint64 SkeramGUID; - uint64 VemGUID; - uint64 KriGUID; - uint64 VeklorGUID; - uint64 VeknilashGUID; - - uint32 BugTrioDeathCount; - - uint32 CthunPhase; - - void Initialize() - { - IsBossDied[0] = false; - IsBossDied[1] = false; - IsBossDied[2] = false; - - SkeramGUID = 0; - VemGUID = 0; - KriGUID = 0; - VeklorGUID = 0; - VeknilashGUID = 0; - - BugTrioDeathCount = 0; - - CthunPhase = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch (pCreature->GetEntry()) - { - case 15263: SkeramGUID = pCreature->GetGUID(); break; - case 15544: VemGUID = pCreature->GetGUID(); break; - case 15511: KriGUID = pCreature->GetGUID(); break; - case 15276: VeklorGUID = pCreature->GetGUID(); break; - case 15275: VeknilashGUID = pCreature->GetGUID(); break; - } - } - - bool IsEncounterInProgress() const - { - //not active in AQ40 - return false; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_VEMISDEAD: - if (IsBossDied[0]) - return 1; - break; - - case DATA_VEKLORISDEAD: - if (IsBossDied[1]) - return 1; - break; - - case DATA_VEKNILASHISDEAD: - if (IsBossDied[2]) - return 1; - break; - - case DATA_BUG_TRIO_DEATH: - return BugTrioDeathCount; - - case DATA_CTHUN_PHASE: - return CthunPhase; - } - return 0; - } - - uint64 GetData64 (uint32 identifier) - { - switch(identifier) - { - case DATA_SKERAM: - return SkeramGUID; - case DATA_VEM: - return VemGUID; - case DATA_KRI: - return KriGUID; - case DATA_VEKLOR: - return VeklorGUID; - case DATA_VEKNILASH: - return VeknilashGUID; - } - return 0; - } // end GetData64 - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_VEM_DEATH: - IsBossDied[0] = true; - break; - - case DATA_BUG_TRIO_DEATH: - ++BugTrioDeathCount; - break; - - case DATA_VEKLOR_DEATH: - IsBossDied[1] = true; - break; - - case DATA_VEKNILASH_DEATH: - IsBossDied[2] = true; - break; - - case DATA_CTHUN_PHASE: - CthunPhase = data; - break; - } - } -}; - -InstanceData* GetInstanceData_instance_temple_of_ahnqiraj(Map* pMap) -{ - return new instance_temple_of_ahnqiraj(pMap); -} - -void AddSC_instance_temple_of_ahnqiraj() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_temple_of_ahnqiraj"; - newscript->GetInstanceData = &GetInstanceData_instance_temple_of_ahnqiraj; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp deleted file mode 100644 index 074f9ed68ae..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: mob_anubisath_sentinel -SD%Complete: 95 -SDComment: Shadow storm is not properly implemented in core it should only pTarget ppl outside of melee range. -SDCategory: Temple of Ahn'Qiraj -EndScriptData */ - -#include "ScriptedPch.h" -#include "WorldPacket.h" - -#include "Item.h" -#include "Player.h" -#include "Spell.h" - -#include "Cell.h" -#include "CellImpl.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" - -#define SPELL_MENDING_BUFF 2147 - -#define SPELL_KNOCK_BUFF 21737 -#define SPELL_KNOCK 25778 -#define SPELL_MANAB_BUFF 812 -#define SPELL_MANAB 25779 - -#define SPELL_REFLECTAF_BUFF 13022 -#define SPELL_REFLECTSFr_BUFF 19595 -#define SPELL_THORNS_BUFF 25777 - -#define SPELL_THUNDER_BUFF 2834 -#define SPELL_THUNDER 8732 - -#define SPELL_MSTRIKE_BUFF 9347 -#define SPELL_MSTRIKE 24573 - -#define SPELL_STORM_BUFF 2148 -#define SPELL_STORM 26546 - -struct aqsentinelAI : public ScriptedAI -{ - uint32 ability; - int abselected; - - void selectAbility(int asel) - { - switch (asel) - { - case 0: ability = SPELL_MENDING_BUFF;break; - case 1: ability = SPELL_KNOCK_BUFF;break; - case 2: ability = SPELL_MANAB_BUFF;break; - case 3: ability = SPELL_REFLECTAF_BUFF;break; - case 4: ability = SPELL_REFLECTSFr_BUFF;break; - case 5: ability = SPELL_THORNS_BUFF;break; - case 6: ability = SPELL_THUNDER_BUFF;break; - case 7: ability = SPELL_MSTRIKE_BUFF;break; - case 8: ability = SPELL_STORM_BUFF;break; - } - } - - aqsentinelAI(Creature *c) : ScriptedAI(c) - { - ClearBuddyList(); - abselected = 0; // just initialization of variable - } - - uint64 NearbyGUID[3]; - - void ClearBuddyList() - { - NearbyGUID[0] = NearbyGUID[1] = NearbyGUID[2] = 0; - } - - void AddBuddyToList(uint64 CreatureGUID) - { - if (CreatureGUID == me->GetGUID()) - return; - - for (int i=0; i<3; ++i) - { - if (NearbyGUID[i] == CreatureGUID) - return; - if (!NearbyGUID[i]) - { - NearbyGUID[i] = CreatureGUID; - return; - } - } - } - - void GiveBuddyMyList(Creature *c) - { - aqsentinelAI *cai = CAST_AI(aqsentinelAI, (c)->AI()); - for (int i=0; i<3; ++i) - if (NearbyGUID[i] && NearbyGUID[i] != c->GetGUID()) - cai->AddBuddyToList(NearbyGUID[i]); - cai->AddBuddyToList(me->GetGUID()); - } - - void SendMyListToBuddies() - { - for (int i=0; i<3; ++i) - if (Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[i])) - GiveBuddyMyList(pNearby); - } - - void CallBuddiesToAttack(Unit *who) - { - for (int i=0; i<3; ++i) - { - Creature *c = Unit::GetCreature(*me, NearbyGUID[i]); - if (c) - { - if (!c->isInCombat()) - { - c->SetNoCallAssistance(true); - if (c->AI()) - c->AI()->AttackStart(who); - } - } - } - } - - void AddSentinelsNear(Unit * /*nears*/) - { - std::list assistList; - me->GetCreatureListWithEntryInGrid(assistList,15264,70.0f); - - if (assistList.empty()) - return; - - for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) - AddBuddyToList((*iter)->GetGUID()); - } - - int pickAbilityRandom(bool *chosenAbilities) - { - for (int t = 0; t < 2; ++t) - { - for (int i = !t ? (rand()%9) : 0; i < 9; ++i) - { - if (!chosenAbilities[i]) - { - chosenAbilities[i] = true; - return i; - } - } - } - return 0; // should never happen - } - - void GetOtherSentinels(Unit *who) - { - bool *chosenAbilities = new bool[9]; - memset(chosenAbilities, 0, 9*sizeof(bool)); - selectAbility(pickAbilityRandom(chosenAbilities)); - - ClearBuddyList(); - AddSentinelsNear(me); - int bli; - for (bli = 0; bli < 3; ++bli) - { - if (!NearbyGUID[bli]) - break; - - Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[bli]); - if (!pNearby) - break; - - AddSentinelsNear(pNearby); - CAST_AI(aqsentinelAI, pNearby->AI())->gatherOthersWhenAggro = false; - CAST_AI(aqsentinelAI, pNearby->AI())->selectAbility(pickAbilityRandom(chosenAbilities)); - } - /*if (bli < 3) - DoYell("I dont have enough buddies.", LANG_NEUTRAL, 0);*/ - SendMyListToBuddies(); - CallBuddiesToAttack(who); - - delete[] chosenAbilities; - } - - bool gatherOthersWhenAggro; - - void Reset() - { - if (!me->isDead()) - { - for (int i=0; i<3; ++i) - { - if (!NearbyGUID[i]) - continue; - if (Creature *pNearby = Unit::GetCreature(*me, NearbyGUID[i])) - { - if (pNearby->isDead()) - pNearby->Respawn(); - } - } - } - ClearBuddyList(); - gatherOthersWhenAggro = true; - } - - void GainSentinelAbility(uint32 id) - { - me->AddAura(id, me); - } - - void EnterCombat(Unit * who) - { - if (gatherOthersWhenAggro) - GetOtherSentinels(who); - - GainSentinelAbility(ability); - DoZoneInCombat(); - } - - void JustDied(Unit* /*who*/) - { - for (int ni=0; ni<3; ++ni) - { - Creature *sent = Unit::GetCreature(*me, NearbyGUID[ni]); - if (!sent) - continue; - if (sent->isDead()) - continue; - int h = sent->GetHealth() + (sent->GetMaxHealth() / 2); - if (h > sent->GetMaxHealth()) - h = sent->GetMaxHealth(); - sent->SetHealth(h); - CAST_AI(aqsentinelAI, sent->AI())->GainSentinelAbility(ability); - } - } - - Unit *GetHatedManaUser() const - { - std::list::const_iterator i; - for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit->getPowerType() == POWER_MANA) - return pUnit; - } - return NULL; - } - - Unit* GetAuraEffectTriggerTarget(uint32 spellId, uint8 /*effIndex*/) const - { - switch (spellId) - { - case SPELL_KNOCK_BUFF: - case SPELL_THUNDER_BUFF: - case SPELL_MSTRIKE_BUFF: - case SPELL_STORM_BUFF: - return me->getVictim(); - - case SPELL_MANAB_BUFF: - return GetHatedManaUser(); - - case SPELL_MENDING_BUFF: - case SPELL_REFLECTAF_BUFF: - case SPELL_REFLECTSFr_BUFF: - case SPELL_THORNS_BUFF: - default: - return me; - } - } -}; -CreatureAI* GetAI_mob_anubisath_sentinelAI(Creature* pCreature) -{ - return new aqsentinelAI (pCreature); -} - -void AddSC_mob_anubisath_sentinel() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_anubisath_sentinel"; - newscript->GetAI = &GetAI_mob_anubisath_sentinelAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h b/src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h deleted file mode 100644 index 5d545ed7c74..00000000000 --- a/src/server/scripts/Kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_TEMPLE_OF_AHNQIRAJ_H -#define DEF_TEMPLE_OF_AHNQIRAJ_H - -#define DATA_SKERAM 1 -#define DATA_KRI 2 -#define DATA_VEM 3 -#define DATA_VEMISDEAD 4 -#define DATA_VEM_DEATH 5 -#define DATA_VEKLOR 6 -#define DATA_VEKLORISDEAD 7 -#define DATA_VEKLOR_DEATH 8 -#define DATA_VEKNILASH 9 -#define DATA_VEKNILASHISDEAD 10 -#define DATA_VEKNILASH_DEATH 11 -#define DATA_BUG_TRIO_DEATH 14 - -#define DATA_CTHUN_PHASE 20 -#endif - diff --git a/src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp b/src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp deleted file mode 100644 index 287b5db6d57..00000000000 --- a/src/server/scripts/Kalimdor/wailing_caverns/instance_wailing_caverns.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Wailing_Caverns -SD%Complete: 99 -SDComment: Everything seems to work, still need some checking -SDCategory: Wailing Caverns -EndScriptData */ - -#include "ScriptedPch.h" -#include "wailing_caverns.h" - -#define MAX_ENCOUNTER 9 - -struct instance_wailing_caverns : public ScriptedInstance -{ - instance_wailing_caverns(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - bool yelled; - uint64 NaralexGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - yelled = false; - NaralexGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == DATA_NARALEX) - NaralexGUID = pCreature->GetGUID(); - } - - void SetData(uint32 type, uint32 data) - { - switch (type) - { - case TYPE_LORD_COBRAHN: m_auiEncounter[0] = data;break; - case TYPE_LORD_PYTHAS: m_auiEncounter[1] = data;break; - case TYPE_LADY_ANACONDRA: m_auiEncounter[2] = data;break; - case TYPE_LORD_SERPENTIS: m_auiEncounter[3] = data;break; - case TYPE_NARALEX_EVENT: m_auiEncounter[4] = data;break; - case TYPE_NARALEX_PART1: m_auiEncounter[5] = data;break; - case TYPE_NARALEX_PART2: m_auiEncounter[6] = data;break; - case TYPE_NARALEX_PART3: m_auiEncounter[7] = data;break; - case TYPE_MUTANUS_THE_DEVOURER: m_auiEncounter[8] = data;break; - case TYPE_NARALEX_YELLED: yelled = true; break; - } - if (data == DONE)SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch (type) - { - case TYPE_LORD_COBRAHN: return m_auiEncounter[0]; - case TYPE_LORD_PYTHAS: return m_auiEncounter[1]; - case TYPE_LADY_ANACONDRA: return m_auiEncounter[2]; - case TYPE_LORD_SERPENTIS: return m_auiEncounter[3]; - case TYPE_NARALEX_EVENT: return m_auiEncounter[4]; - case TYPE_NARALEX_PART1: return m_auiEncounter[5]; - case TYPE_NARALEX_PART2: return m_auiEncounter[6]; - case TYPE_NARALEX_PART3: return m_auiEncounter[7]; - case TYPE_MUTANUS_THE_DEVOURER: return m_auiEncounter[8]; - case TYPE_NARALEX_YELLED: return yelled; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - if (data == DATA_NARALEX)return NaralexGUID; - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " - << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] >> m_auiEncounter[8]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] != DONE) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } - -}; - -InstanceData* GetInstanceData_instance_wailing_caverns(Map* pMap) -{ - return new instance_wailing_caverns(pMap); -} - -void AddSC_instance_wailing_caverns() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_wailing_caverns"; - newscript->GetInstanceData = &GetInstanceData_instance_wailing_caverns; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp b/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp deleted file mode 100644 index 544c119fc93..00000000000 --- a/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Wailing Caverns -SD%Complete: 95 -SDComment: Need to add skill usage for Disciple of Naralex -SDCategory: Wailing Caverns -EndScriptData */ - -/* ContentData -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "wailing_caverns.h" - -/*###### -## npc_disciple_of_naralex -######*/ - -enum eEnums -{ - //say - SAY_MAKE_PREPARATIONS = -1043001, - SAY_TEMPLE_OF_PROMISE = -1043002, - SAY_MUST_CONTINUE = -1043003, - SAY_BANISH_THE_SPIRITS = -1043004, - SAY_CAVERNS_PURIFIED = -1043005, - SAY_BEYOND_THIS_CORRIDOR = -1043006, - SAY_EMERALD_DREAM = -1043007, - SAY_MUTANUS_THE_DEVOURER = -1043012, - SAY_NARALEX_AWAKES = -1043014, - SAY_THANK_YOU = -1043015, - SAY_FAREWELL = -1043016, - SAY_ATTACKED = -1043017, - //yell - SAY_AT_LAST = -1043000, - SAY_I_AM_AWAKE = -1043013, - //emote - EMOTE_AWAKENING_RITUAL = -1043008, - EMOTE_TROUBLED_SLEEP = -1043009, - EMOTE_WRITHE_IN_AGONY = -1043010, - EMOTE_HORRENDOUS_VISION = -1043011, - //spell - SPELL_MARK_OF_THE_WILD_RANK_2 = 5232, - SPELL_SERPENTINE_CLEANSING = 6270, - SPELL_NARALEXS_AWAKENING = 6271, - SPELL_FLIGHT_FORM = 33943, - //npc entry - NPC_DEVIATE_RAVAGER = 3636, - NPC_DEVIATE_VIPER = 5755, - NPC_DEVIATE_MOCCASIN = 5762, - NPC_NIGHTMARE_ECTOPLASM = 5763, - NPC_MUTANUS_THE_DEVOURER = 3654, -}; - -#define GOSSIP_ID_START_1 698 //Naralex sleeps again! -#define GOSSIP_ID_START_2 699 //The fanglords are dead! -#define GOSSIP_ITEM_NARALEX "Let the event begin!" -#define ACHIEVEMENT_WAILING_CAVERNS 630 - -struct npc_disciple_of_naralexAI : public npc_escortAI -{ - npc_disciple_of_naralexAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - eventTimer = 0; - currentEvent = 0; - eventProgress = 0; - me->setActive(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - uint32 eventTimer; - uint32 currentEvent; - uint32 eventProgress; - ScriptedInstance *pInstance; - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch (i) - { - case 4: - eventProgress = 1; - currentEvent = TYPE_NARALEX_PART1; - pInstance->SetData(TYPE_NARALEX_PART1, IN_PROGRESS); - break; - case 5: - DoScriptText(SAY_MUST_CONTINUE, me); - pInstance->SetData(TYPE_NARALEX_PART1, DONE); - break; - case 11: - eventProgress = 1; - currentEvent = TYPE_NARALEX_PART2; - pInstance->SetData(TYPE_NARALEX_PART2, IN_PROGRESS); - break; - case 19: - DoScriptText(SAY_BEYOND_THIS_CORRIDOR, me); - break; - case 24: - eventProgress = 1; - currentEvent = TYPE_NARALEX_PART3; - pInstance->SetData(TYPE_NARALEX_PART3, IN_PROGRESS); - break; - } - } - - void Reset() - { - - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_ATTACKED, me, who); - } - - void JustDied(Unit * /*slayer*/) - { - if (pInstance) - { - pInstance->SetData(TYPE_NARALEX_EVENT, FAIL); - pInstance->SetData(TYPE_NARALEX_PART1, FAIL); - pInstance->SetData(TYPE_NARALEX_PART2, FAIL); - pInstance->SetData(TYPE_NARALEX_PART3, FAIL); - } - } - - void JustSummoned(Creature* summoned) - { - summoned->AI()->AttackStart(me); - } - - void UpdateAI(const uint32 diff) - { - if (currentEvent != TYPE_NARALEX_PART3) - npc_escortAI::UpdateAI(diff); - - if (!pInstance) - return; - if (eventTimer <= diff) - { - eventTimer = 0; - if (pInstance->GetData(currentEvent) == IN_PROGRESS) - { - switch (currentEvent) - { - case TYPE_NARALEX_PART1: - if (eventProgress == 1) - { - ++eventProgress; - DoScriptText(SAY_TEMPLE_OF_PROMISE, me); - me->SummonCreature(NPC_DEVIATE_RAVAGER, -82.1763, 227.874, -93.3233, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - me->SummonCreature(NPC_DEVIATE_RAVAGER, -72.9506, 216.645, -93.6756, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - } - break; - case TYPE_NARALEX_PART2: - if (eventProgress == 1) - { - ++eventProgress; - DoScriptText(SAY_BANISH_THE_SPIRITS, me); - DoCast(me, SPELL_SERPENTINE_CLEANSING); - //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(false); - eventTimer = 30000; - me->SummonCreature(NPC_DEVIATE_VIPER, -61.5261, 273.676, -92.8442, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - me->SummonCreature(NPC_DEVIATE_VIPER, -58.4658, 280.799, -92.8393, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - me->SummonCreature(NPC_DEVIATE_VIPER, -50.002, 278.578, -92.8442, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - } - else - if (eventProgress == 2) - { - //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(true); - DoScriptText(SAY_CAVERNS_PURIFIED, me); - pInstance->SetData(TYPE_NARALEX_PART2, DONE); - if (me->HasAura(SPELL_SERPENTINE_CLEANSING)) - me->RemoveAura(SPELL_SERPENTINE_CLEANSING); - } - break; - case TYPE_NARALEX_PART3: - if (eventProgress == 1) - { - ++eventProgress; - eventTimer = 4000; - me->SetStandState(UNIT_STAND_STATE_KNEEL); - DoScriptText(SAY_EMERALD_DREAM, me); - } - else - if (eventProgress == 2) - { - ++eventProgress; - eventTimer = 15000; - //CAST_AI(npc_escortAI, me->AI())->SetCanDefend(false); - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoCast(naralex, SPELL_NARALEXS_AWAKENING, true); - DoScriptText(EMOTE_AWAKENING_RITUAL, me); - } - else - if (eventProgress == 3) - { - ++eventProgress; - eventTimer = 15000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoScriptText(EMOTE_TROUBLED_SLEEP, naralex); - me->SummonCreature(NPC_DEVIATE_MOCCASIN, 135.943, 199.701, -103.529, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_DEVIATE_MOCCASIN, 151.08, 221.13, -103.609, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_DEVIATE_MOCCASIN, 128.007, 227.428, -97.421, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - } - else - if (eventProgress == 4) - { - ++eventProgress; - eventTimer = 30000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoScriptText(EMOTE_WRITHE_IN_AGONY, naralex); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 133.413, 207.188, -102.469, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 142.857, 218.645, -102.905, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 105.102, 227.211, -102.752, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 153.372, 235.149, -102.826, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 149.524, 251.113, -102.558, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 136.208, 266.466, -102.977, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - me->SummonCreature(NPC_NIGHTMARE_ECTOPLASM, 126.167, 274.759, -102.962, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - } - else - if (eventProgress == 5) - { - ++eventProgress; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoScriptText(EMOTE_HORRENDOUS_VISION, naralex); - me->SummonCreature(NPC_MUTANUS_THE_DEVOURER, 150.872, 262.905, -103.503, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000); - DoScriptText(SAY_MUTANUS_THE_DEVOURER, me); - pInstance->SetData(TYPE_MUTANUS_THE_DEVOURER, IN_PROGRESS); - } - else - if (eventProgress == 6 && pInstance->GetData(TYPE_MUTANUS_THE_DEVOURER) == DONE) - { - ++eventProgress; - eventTimer = 3000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - { - AchievementEntry const *AchievWC = GetAchievementStore()->LookupEntry(ACHIEVEMENT_WAILING_CAVERNS); - if (AchievWC) - { - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievWC); - } - } - if (me->HasAura(SPELL_NARALEXS_AWAKENING)) - me->RemoveAura(SPELL_NARALEXS_AWAKENING); - naralex->SetStandState(UNIT_STAND_STATE_STAND); - DoScriptText(SAY_I_AM_AWAKE, naralex); - } - DoScriptText(SAY_NARALEX_AWAKES, me); - } - else - if (eventProgress == 7) - { - ++eventProgress; - eventTimer = 6000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - DoScriptText(SAY_THANK_YOU, naralex); - } - else - if (eventProgress == 8) - { - ++eventProgress; - eventTimer = 8000; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - { - DoScriptText(SAY_FAREWELL, naralex); - naralex->AddAura(SPELL_FLIGHT_FORM, naralex); - } - SetRun(); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->AddAura(SPELL_FLIGHT_FORM, me); - } - else - if (eventProgress == 9) - { - ++eventProgress; - eventTimer = 1500; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - naralex->GetMotionMaster()->MovePoint(25, naralex->GetPositionX(), naralex->GetPositionY(), naralex->GetPositionZ()); - } - else - if (eventProgress == 10) - { - ++eventProgress; - eventTimer = 2500; - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - { - naralex->GetMotionMaster()->MovePoint(0, 117.095512, 247.107971, -96.167870); - naralex->GetMotionMaster()->MovePoint(1, 90.388809, 276.135406, -83.389801); - } - me->GetMotionMaster()->MovePoint(26, 117.095512, 247.107971, -96.167870); - me->GetMotionMaster()->MovePoint(27, 144.375443, 281.045837, -82.477135); - } - else - if (eventProgress == 11) - { - if (Creature* naralex = pInstance->instance->GetCreature(pInstance->GetData64(DATA_NARALEX))) - naralex->SetVisibility(VISIBILITY_OFF); - me->SetVisibility(VISIBILITY_OFF); - pInstance->SetData(TYPE_NARALEX_PART3, DONE); - } - break; - } - } - } else eventTimer -= diff; - } -}; - -CreatureAI* GetAI_npc_disciple_of_naralex(Creature* pCreature) -{ - return new npc_disciple_of_naralexAI(pCreature); -} - -bool GossipHello_npc_disciple_of_naralex(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance *pInstance = pCreature->GetInstanceData(); - - if (pInstance) - { - pCreature->CastSpell(pPlayer, SPELL_MARK_OF_THE_WILD_RANK_2, true); - if ((pInstance->GetData(TYPE_LORD_COBRAHN) == DONE) && (pInstance->GetData(TYPE_LORD_PYTHAS) == DONE) && - (pInstance->GetData(TYPE_LADY_ANACONDRA) == DONE) && (pInstance->GetData(TYPE_LORD_SERPENTIS) == DONE)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NARALEX, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START_2, pCreature->GetGUID()); - - if (!pInstance->GetData(TYPE_NARALEX_YELLED)) - { - DoScriptText(SAY_AT_LAST, pCreature); - pInstance->SetData(TYPE_NARALEX_YELLED, 1); - } - } - else - { - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START_1, pCreature->GetGUID()); - } - } - return true; -} - -bool GossipSelect_npc_disciple_of_naralex(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - ScriptedInstance *pInstance = pCreature->GetInstanceData(); - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - if (pInstance) - pInstance->SetData(TYPE_NARALEX_EVENT, IN_PROGRESS); - - DoScriptText(SAY_MAKE_PREPARATIONS, pCreature); - - pCreature->setFaction(250); - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - - CAST_AI(npc_escortAI, (pCreature->AI()))->Start(false, false, pPlayer->GetGUID()); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); - } - return true; -} - -void AddSC_wailing_caverns() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_disciple_of_naralex"; - newscript->pGossipHello = &GossipHello_npc_disciple_of_naralex; - newscript->pGossipSelect = &GossipSelect_npc_disciple_of_naralex; - newscript->GetAI = &GetAI_npc_disciple_of_naralex; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h b/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h deleted file mode 100644 index 6ef1a673c59..00000000000 --- a/src/server/scripts/Kalimdor/wailing_caverns/wailing_caverns.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_WAILING_CAVERNS_H -#define DEF_WAILING_CAVERNS_H - -enum eTypes -{ - TYPE_LORD_COBRAHN = 1, - TYPE_LORD_PYTHAS = 2, - TYPE_LADY_ANACONDRA = 3, - TYPE_LORD_SERPENTIS = 4, - TYPE_NARALEX_EVENT = 5, - TYPE_NARALEX_PART1 = 6, - TYPE_NARALEX_PART2 = 7, - TYPE_NARALEX_PART3 = 8, - TYPE_MUTANUS_THE_DEVOURER = 9, - TYPE_NARALEX_YELLED = 10, - - DATA_NARALEX = 3679, -}; - -#endif diff --git a/src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp b/src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp deleted file mode 100644 index 530ef30f44c..00000000000 --- a/src/server/scripts/Kalimdor/zulfarrak/instance_zulfarrak.cpp +++ /dev/null @@ -1,58 +0,0 @@ - /* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" - -#define NPC_GAHZRILLA 7273 - -struct instance_zulfarrak : public ScriptedInstance -{ - instance_zulfarrak(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 GahzRillaEncounter; - - void Initialize() - { - GahzRillaEncounter = NOT_STARTED; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == NPC_GAHZRILLA) - { - if (GahzRillaEncounter >= IN_PROGRESS) - pCreature->DisappearAndDie(); - else - GahzRillaEncounter = IN_PROGRESS; - } - } -}; - -InstanceData* GetInstanceData_instance_zulfarrak(Map* pMap) -{ - return new instance_zulfarrak(pMap); -} - -void AddSC_instance_zulfarrak() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_zulfarrak"; - newscript->GetInstanceData = &GetInstanceData_instance_zulfarrak; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp b/src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp deleted file mode 100644 index 2ca053c23b6..00000000000 --- a/src/server/scripts/Kalimdor/zulfarrak/zulfarrak.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Zulfarrak -SD%Complete: 50 -SDComment: Consider it temporary, no instance script made for this instance yet. -SDCategory: Zul'Farrak -EndScriptData */ - -/* ContentData -npc_sergeant_bly -npc_weegli_blastfuse -EndContentData */ - -#include "ScriptedPch.h" - -/*###### -## npc_sergeant_bly -######*/ - -#define FACTION_HOSTILE 14 -#define FACTION_FRIENDLY 35 - -#define SPELL_SHIELD_BASH 11972 -#define SPELL_REVENGE 12170 - -#define GOSSIP_BLY "[PH] In that case, I will take my reward!" - -struct npc_sergeant_blyAI : public ScriptedAI -{ - npc_sergeant_blyAI(Creature *c) : ScriptedAI(c) - { - //pInstance = c->GetInstanceData(); - } - - //ScriptedInstance* pInstance; - - uint32 ShieldBash_Timer; - uint32 Revenge_Timer; //this is wrong, spell should never be used unless me->getVictim() dodge, parry or block attack. Trinity support required. - - void Reset() - { - ShieldBash_Timer = 5000; - Revenge_Timer = 8000; - - me->setFaction(FACTION_FRIENDLY); - - /*if (pInstance) - pInstance->SetData(0, NOT_STARTED);*/ - } - - void EnterCombat(Unit * /*who*/) - { - /*if (pInstance) - pInstance->SetData(0, IN_PROGRESS);*/ - } - - void JustDied(Unit * /*victim*/) - { - /*if (pInstance) - pInstance->SetData(0, DONE);*/ - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShieldBash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHIELD_BASH); - ShieldBash_Timer = 15000; - } else ShieldBash_Timer -= diff; - - if (Revenge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_REVENGE); - Revenge_Timer = 10000; - } else Revenge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_sergeant_bly(Creature* pCreature) -{ - return new npc_sergeant_blyAI (pCreature); -} - -bool GossipHello_npc_sergeant_bly(Player* pPlayer, Creature* pCreature) -{ - /*if (pInstance->GetData(0) == DONE) - {*/ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(1517, pCreature->GetGUID()); - /*} - else if (pInstance->GetData(0) == IN_PROGRESS) - pPlayer->SEND_GOSSIP_MENU(1516, pCreature->GetGUID()); - else - pPlayer->SEND_GOSSIP_MENU(1515, pCreature->GetGUID());*/ - - return true; -} - -bool GossipSelect_npc_sergeant_bly(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->setFaction(FACTION_HOSTILE); - CAST_AI(npc_sergeant_blyAI, pCreature->AI())->AttackStart(pPlayer); - } - return true; -} - -/*###### -## npc_weegli_blastfuse -######*/ - -#define SPELL_BOMB 8858 -#define SPELL_GOBLIN_LAND_MINE 21688 -#define SPELL_SHOOT 6660 -#define SPELL_WEEGLIS_BARREL 10772 - -#define GOSSIP_WEEGLI "[PH] Please blow up the door." - -struct npc_weegli_blastfuseAI : public ScriptedAI -{ - npc_weegli_blastfuseAI(Creature *c) : ScriptedAI(c) - { - //pInstance = c->GetInstanceData(); - } - - //ScriptedInstance* pInstance; - - void Reset() - { - /*if (pInstance) - pInstance->SetData(0, NOT_STARTED);*/ - } - - void EnterCombat(Unit * /*who*/) - { - /*if (pInstance) - pInstance->SetData(0, IN_PROGRESS);*/ - } - - void JustDied(Unit * /*victim*/) - { - /*if (pInstance) - pInstance->SetData(0, DONE);*/ - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_npc_weegli_blastfuse(Creature* pCreature) -{ - return new npc_weegli_blastfuseAI (pCreature); -} - -bool GossipHello_npc_weegli_blastfuse(Player* pPlayer, Creature* pCreature) -{ - //event not implemented yet, this is only placeholder for future developement - /*if (pInstance->GetData(0) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEEGLI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(1514, pCreature->GetGUID());//if event can proceed to end - } - else if (pInstance->GetData(0) == IN_PROGRESS) - pPlayer->SEND_GOSSIP_MENU(1513, pCreature->GetGUID());//if event are in progress - else*/ - pPlayer->SEND_GOSSIP_MENU(1511, pCreature->GetGUID()); //if event not started - return true; -} - -bool GossipSelect_npc_weegli_blastfuse(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - //here we make him run to door, set the charge and run away off to nowhere - } - return true; -} - -/*###### -## go_shallow_grave -######*/ - -enum { - ZOMBIE = 7286, - DEAD_HERO = 7276, - ZOMBIE_CHANCE = 65, - DEAD_HERO_CHANCE = 10 -}; - -bool GOHello_go_shallow_grave(Player* /*pPlayer*/, GameObject* pGo) -{ - // randomly summon a zombie or dead hero the first time a grave is used - if (pGo->GetUseCount() == 0) - { - uint32 randomchance = urand(0,100); - if (randomchance < ZOMBIE_CHANCE) - pGo->SummonCreature(ZOMBIE, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - else if ((randomchance-ZOMBIE_CHANCE) < DEAD_HERO_CHANCE) - pGo->SummonCreature(DEAD_HERO, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - } - pGo->AddUse(); - return false; -} - -/*###### -## at_zumrah -######*/ - -enum { - ZUMRAH_ID = 7271, - ZUMRAH_HOSTILE_FACTION = 37 -}; - -bool AreaTrigger_at_zumrah(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - Creature* Zumrah = pPlayer->FindNearestCreature(ZUMRAH_ID, 30.0f); - - if (!Zumrah) - return false; - - Zumrah->setFaction(ZUMRAH_HOSTILE_FACTION); - Zumrah->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - return true; -} - -void AddSC_zulfarrak() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sergeant_bly"; - newscript->GetAI = &GetAI_npc_sergeant_bly; - newscript->pGossipHello = &GossipHello_npc_sergeant_bly; - newscript->pGossipSelect = &GossipSelect_npc_sergeant_bly; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_weegli_blastfuse"; - newscript->GetAI = &GetAI_npc_weegli_blastfuse; - newscript->pGossipHello = &GossipHello_npc_weegli_blastfuse; - newscript->pGossipSelect = &GossipSelect_npc_weegli_blastfuse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_shallow_grave"; - newscript->pGOHello = &GOHello_go_shallow_grave; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_zumrah"; - newscript->pAreaTrigger = &AreaTrigger_at_zumrah; - newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h new file mode 100644 index 00000000000..240ad77c74d --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/ahnkahet.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_AHNKAHET_H +#define DEF_AHNKAHET_H + +enum Data64 +{ + DATA_ELDER_NADOX, + DATA_PRINCE_TALDARAM, + DATA_JEDOGA_SHADOWSEEKER, + DATA_HERALD_VOLAZJ, + DATA_AMANITAR, + DATA_SPHERE1, + DATA_SPHERE2, + DATA_PRINCE_TALDARAM_PLATFORM, + DATA_PL_JEDOGA_TARGET, + DATA_ADD_JEDOGA_OPFER, + DATA_ADD_JEDOGA_INITIAND +}; + +enum Data +{ + DATA_ELDER_NADOX_EVENT, + DATA_PRINCE_TALDARAM_EVENT, + DATA_JEDOGA_SHADOWSEEKER_EVENT, + DATA_HERALD_VOLAZJ_EVENT, + DATA_AMANITAR_EVENT, + DATA_SPHERE1_EVENT, + DATA_SPHERE2_EVENT, + DATA_JEDOGA_TRIGGER_SWITCH, + DATA_JEDOGA_RESET_INITIANDS, + DATA_INITIAND_KILLED, + DATA_ALL_INITIAND_DEAD +}; + +#endif diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp new file mode 100644 index 00000000000..51c4bce0c2d --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_amanitar.cpp @@ -0,0 +1,226 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Comment: Find correct mushrooms spell to make them visible - buffs of the mushrooms not ever applied to the users... + */ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +enum Spells +{ + SPELL_BASH = 57094, // Victim + SPELL_ENTANGLING_ROOTS = 57095, // Random Victim 100Y + SPELL_MINI = 57055, // Self + SPELL_VENOM_BOLT_VOLLEY = 57088, // Random Victim 100Y + SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS = 56648, // Killer 3Y + SPELL_POISONOUS_MUSHROOM_POISON_CLOUD = 57061, // Self - Duration 8 Sec + SPELL_POISONOUS_MUSHROOM_VISUAL_AREA = 61566, // Self + SPELL_POISONOUS_MUSHROOM_VISUAL_AURA = 56741, // Self + SPELL_PUTRID_MUSHROOM = 31690, // To make the mushrooms visible +}; + +enum Creatures +{ + NPC_HEALTHY_MUSHROOM = 30391, + NPC_POISONOUS_MUSHROOM = 30435 +}; + +struct boss_amanitarAI : public ScriptedAI +{ + boss_amanitarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + bFirstTime = true; + } + + ScriptedInstance* pInstance; + + uint32 uiRootTimer; + uint32 uiBashTimer; + uint32 uiBoltTimer; + uint32 uiSpawnTimer; + + bool bFirstTime; + + void Reset() + { + uiRootTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); + uiBashTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); + uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + uiSpawnTimer = 0; + + me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + + if (pInstance) + { + pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); + if (!bFirstTime) + pInstance->SetData(DATA_AMANITAR_EVENT, FAIL); + else + bFirstTime = false; + } + } + + void JustDied(Unit * /*Killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_AMANITAR_EVENT, DONE); + pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_AMANITAR_EVENT, IN_PROGRESS); + + DoCast(me, SPELL_MINI, false); + } + + void SpawnAdds() + { + for (uint8 i = 0; i < 30; ++i) + { + Unit* victim = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (victim) + { + Position pos; + victim->GetPosition(&pos); + me->GetRandomNearPosition(pos, float(urand(5,80))); + me->SummonCreature(NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILISECONDS); + me->GetRandomNearPosition(pos, float(urand(5,80))); + me->SummonCreature(NPC_HEALTHY_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILISECONDS); + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiSpawnTimer <= diff) + { + SpawnAdds(); + uiSpawnTimer = urand(35*IN_MILISECONDS,40*IN_MILISECONDS); + } else uiSpawnTimer -= diff; + + if (uiRootTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ENTANGLING_ROOTS); + uiRootTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiRootTimer -= diff; + + if (uiBashTimer <= diff) + { + DoCastVictim(SPELL_BASH); + uiBashTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiBashTimer -= diff; + + if (uiBoltTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_VENOM_BOLT_VOLLEY); + uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_amanitar_mushroomsAI : public Scripted_NoMovementAI +{ + mob_amanitar_mushroomsAI(Creature* c) : Scripted_NoMovementAI(c) {} + + uint32 uiAuraTimer; + uint32 uiDeathTimer; + + void Reset() + { + DoCast(me, SPELL_PUTRID_MUSHROOM, true); // Hack, to make the mushrooms visible, can't find orig. spell... + + if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) + DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true); + + uiAuraTimer = 0; + uiDeathTimer = 30*IN_MILISECONDS; + } + + void JustDied(Unit *killer) + { + if (!killer) + return; + + if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && killer->GetTypeId() == TYPEID_PLAYER) + { + me->InterruptNonMeleeSpells(false); + DoCast(killer, SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, false); + } + } + + void EnterCombat(Unit * /*who*/) {} + void AttackStart(Unit * /*victim*/) {} + + void UpdateAI(const uint32 diff) + { + if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) + { + if (uiAuraTimer <= diff) + { + DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AREA, true); + DoCast(me, SPELL_POISONOUS_MUSHROOM_POISON_CLOUD, false); + uiAuraTimer = 7*IN_MILISECONDS; + } else uiAuraTimer -= diff; + } + if (uiDeathTimer <= diff) + me->DisappearAndDie(); + else uiDeathTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_amanitar(Creature* pCreature) +{ + return new boss_amanitarAI (pCreature); +} + +CreatureAI* GetAI_mob_amanitar_mushrooms(Creature *pCreature) +{ + return new mob_amanitar_mushroomsAI (pCreature); +} + +void AddSC_boss_amanitar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_amanitar"; + newscript->GetAI = &GetAI_boss_amanitar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_amanitar_mushrooms"; + newscript->GetAI = &GetAI_mob_amanitar_mushrooms; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp new file mode 100644 index 00000000000..2215d91c749 --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_elder_nadox.cpp @@ -0,0 +1,283 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +bool DeadAhnkaharGuardian; // needed for achievement: Respect Your Elders(2038) + +enum Achievements +{ + ACHIEV_RESPECT_YOUR_ELDERS = 2038 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1619014, + SAY_SLAY_1 = -1619015, + SAY_SLAY_2 = -1619016, + SAY_SLAY_3 = -1619017, + SAY_DEATH = -1619018, + SAY_EGG_SAC_1 = -1619019, + SAY_EGG_SAC_2 = -1619020 +}; + +enum Spells +{ + SPELL_BROOD_PLAGUE = 56130, + H_SPELL_BROOD_PLAGUE = 59467, + H_SPELL_BROOD_RAGE = 59465, + SPELL_ENRAGE = 26662, // Enraged if too far away from home + SPELL_SUMMON_SWARMERS = 56119, //2x 30178 -- 2x every 10secs + SPELL_SUMMON_SWARM_GUARD = 56120, //1x 30176 -- every 25secs +}; + +enum Creatures +{ + MOB_AHNKAHAR_SWARMER = 30178, + MOB_AHNKAHAR_GUARDIAN_ENTRY = 30176 +}; + +#define EMOTE_HATCHES "An Ahn'kahar Guardian hatches!" + +struct boss_elder_nadoxAI : public ScriptedAI +{ + boss_elder_nadoxAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiPlagueTimer; + uint32 uiRagueTimer; + + uint32 uiSwarmerSpawnTimer; + uint32 uiGuardSpawnTimer; + uint32 uiEnragueTimer; + + bool bGuardSpawned; + + ScriptedInstance *pInstance; + + void Reset() + { + uiPlagueTimer = 13*IN_MILISECONDS; + uiRagueTimer = 20*IN_MILISECONDS; + + uiSwarmerSpawnTimer = 10*IN_MILISECONDS; + uiGuardSpawnTimer = 25*IN_MILISECONDS; + + uiEnragueTimer = 5*IN_MILISECONDS; + + DeadAhnkaharGuardian = false; + bGuardSpawned = false; + + if (pInstance) + pInstance->SetData(DATA_ELDER_NADOX_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_DEATH,me); + + if (pInstance) + pInstance->SetData(DATA_ELDER_NADOX_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_SLAY_3,me); //SAY_SLAY_3 on death? + + if (pInstance) + { + pInstance->SetData(DATA_ELDER_NADOX_EVENT, DONE); + if (IsHeroic() && !DeadAhnkaharGuardian) + pInstance->DoCompleteAchievement(ACHIEV_RESPECT_YOUR_ELDERS); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiPlagueTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BROOD_PLAGUE); + uiPlagueTimer = 15*IN_MILISECONDS; + } else uiPlagueTimer -= diff; + + if (IsHeroic()) + if (uiRagueTimer <= diff) + { + if (Creature *pSwarmer = me->FindNearestCreature(MOB_AHNKAHAR_SWARMER, 35)) + { + DoCast(pSwarmer, H_SPELL_BROOD_RAGE, true); + uiRagueTimer = 15*IN_MILISECONDS; + } + } else uiRagueTimer -= diff; + + if (uiSwarmerSpawnTimer <= diff) + { + DoCast(me, SPELL_SUMMON_SWARMERS, true); + DoCast(me, SPELL_SUMMON_SWARMERS); + if (urand(1,3) == 3) // 33% chance of dialog + DoScriptText(RAND(SAY_EGG_SAC_1,SAY_EGG_SAC_2), me); + + uiSwarmerSpawnTimer = 10*IN_MILISECONDS; + } else uiSwarmerSpawnTimer -= diff; + + if (!bGuardSpawned && uiGuardSpawnTimer <= diff) + { + me->MonsterTextEmote(EMOTE_HATCHES,me->GetGUID(),true); + DoCast(me, SPELL_SUMMON_SWARM_GUARD); + bGuardSpawned = true; + } else uiGuardSpawnTimer -= diff; + + if (uiEnragueTimer <= diff) + { + if (me->HasAura(SPELL_ENRAGE,0)) + return; + + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + if (z < 24) + if (!me->IsNonMeleeSpellCasted(false)) + DoCast(me, SPELL_ENRAGE, true); + + uiEnragueTimer = 5*IN_MILISECONDS; + } else uiEnragueTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_elder_nadox(Creature* pCreature) +{ + return new boss_elder_nadoxAI(pCreature); +} + +enum AddSpells +{ + SPELL_SPRINT = 56354, + SPELL_GUARDIAN_AURA = 56151 +}; + +struct mob_ahnkahar_nerubianAI : public ScriptedAI +{ + mob_ahnkahar_nerubianAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 uiSprintTimer; + + void Reset() + { + if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) //magic numbers are bad! + DoCast(me, SPELL_GUARDIAN_AURA, true); + uiSprintTimer = 10*IN_MILISECONDS; + } + + void JustDied(Unit * /*killer*/) + { + if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) + DeadAhnkaharGuardian = true; + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) + me->RemoveAurasDueToSpell(SPELL_GUARDIAN_AURA); + + if (pInstance) + { + if (pInstance->GetData(DATA_ELDER_NADOX_EVENT) != IN_PROGRESS) + { + me->DisappearAndDie(); + } + } + + if (!UpdateVictim()) + return; + + if (uiSprintTimer <= diff) + { + DoCast(me, SPELL_SPRINT); + uiSprintTimer = 25*IN_MILISECONDS; + } else uiSprintTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//HACK: No, AI. Replace with proper db content? +struct mob_nadox_eggsAI : public Scripted_NoMovementAI +{ + mob_nadox_eggsAI(Creature* c) : Scripted_NoMovementAI(c) + { + c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + c->UpdateAllStats(); + } + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*victim*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_mob_ahnkahar_nerubian(Creature* pCreature) +{ + return new mob_ahnkahar_nerubianAI(pCreature); +} + +CreatureAI* GetAI_mob_nadox_eggs(Creature* _Creature) +{ + return new mob_nadox_eggsAI(_Creature); +} + +void AddSC_boss_elder_nadox() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_elder_nadox"; + newscript->GetAI = &GetAI_boss_elder_nadox; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ahnkahar_nerubian"; + newscript->GetAI = &GetAI_mob_ahnkahar_nerubian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nadox_eggs"; + newscript->GetAI = &GetAI_mob_nadox_eggs; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_herald_volazj.cpp new file mode 100644 index 00000000000..16c291d6484 --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_herald_volazj.cpp @@ -0,0 +1,328 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Comment: Missing AI for Twisted Visages + */ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +enum Spells +{ + SPELL_INSANITY = 57496, //Dummy + INSANITY_VISUAL = 57561, + SPELL_INSANITY_TARGET = 57508, + SPELL_MIND_FLAY = 57941, + SPELL_SHADOW_BOLT_VOLLEY = 57942, + SPELL_SHIVER = 57949, + SPELL_CLONE_PLAYER = 57507, //casted on player during insanity + SPELL_INSANITY_PHASING_1 = 57508, + SPELL_INSANITY_PHASING_2 = 57509, + SPELL_INSANITY_PHASING_3 = 57510, + SPELL_INSANITY_PHASING_4 = 57511, + SPELL_INSANITY_PHASING_5 = 57512 +}; + +enum Creatures +{ + MOB_TWISTED_VISAGE = 30625 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1619030, + SAY_SLAY_1 = -1619031, + SAY_SLAY_2 = -1619032, + SAY_SLAY_3 = -1619033, + SAY_DEATH_1 = -1619034, + SAY_DEATH_2 = -1619035, + SAY_PHASE = -1619036 +}; + +enum Achievements +{ + ACHIEV_QUICK_DEMISE_START_EVENT = 20382, +}; + +struct boss_volazjAI : public ScriptedAI +{ + boss_volazjAI(Creature* pCreature) : ScriptedAI(pCreature),Summons(me) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 uiMindFlayTimer; + uint32 uiShadowBoltVolleyTimer; + uint32 uiShiverTimer; + uint32 insanityHandled; + SummonList Summons; + + // returns the percentage of health after taking the given damage. + uint32 GetHealthPct(uint32 damage) + { + if (damage > me->GetHealth()) + return 0; + return 100*(me->GetHealth()-damage)/me->GetMaxHealth(); + } + + void DamageTaken(Unit * /*pAttacker*/, uint32 &damage) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + damage = 0; + + if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)|| + (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33)) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_INSANITY, false); + } + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (spell->Id == SPELL_INSANITY) + { + // Not good target or too many players + if (pTarget->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4) + return; + // First target - start channel visual and set self as unnattackable + if (!insanityHandled) + { + // Channel visual + DoCast(me, INSANITY_VISUAL, true); + // Unattackable + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(true, UNIT_STAT_STUNNED); + } + // phase mask + pTarget->CastSpell(pTarget, SPELL_INSANITY_TARGET+insanityHandled, true); + // summon twisted party members for this target + Map::PlayerList const &players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player *plr = i->getSource(); + if (!plr || !plr->isAlive()) + continue; + // Summon clone + if (Unit *summon = me->SummonCreature(MOB_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,0)) + { + // required for correct visual + // Fixme: allow mirror image query to send other guid to get rid of minion status + summon->SetUInt64Value(UNIT_FIELD_CREATEDBY, plr->GetGUID()); + // clone + plr->CastSpell(summon, SPELL_CLONE_PLAYER, true); + // set phase + summon->SetPhaseMask((1<<(4+insanityHandled)),true); + } + } + ++insanityHandled; + } + } + + void ResetPlayersPhaseMask() + { + Map::PlayerList const &players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player* pPlayer = i->getSource(); + pPlayer->RemoveAurasDueToSpell(GetSpellForPhaseMask(pPlayer->GetPhaseMask())); + } + } + + void Reset() + { + uiMindFlayTimer = 8*IN_MILISECONDS; + uiShadowBoltVolleyTimer = 5*IN_MILISECONDS; + uiShiverTimer = 15*IN_MILISECONDS; + + if (pInstance) + { + pInstance->SetData(DATA_HERALD_VOLAZJ, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); + } + + // Visible for all players in insanity + me->SetPhaseMask((1|16|32|64|128|256),true); + // Used for Insanity handling + insanityHandled = 0; + + ResetPlayersPhaseMask(); + + // Cleanup + Summons.DespawnAll(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + { + pInstance->SetData(DATA_HERALD_VOLAZJ, IN_PROGRESS); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); + } + } + + void JustSummoned(Creature *summon) + { + Summons.Summon(summon); + } + + uint32 GetSpellForPhaseMask(uint32 phase) + { + uint32 spell = 0; + switch (phase) + { + case 16: + spell = SPELL_INSANITY_PHASING_1; + break; + case 32: + spell = SPELL_INSANITY_PHASING_2; + break; + case 64: + spell = SPELL_INSANITY_PHASING_3; + break; + case 128: + spell = SPELL_INSANITY_PHASING_4; + break; + case 256: + spell = SPELL_INSANITY_PHASING_5; + break; + } + return spell; + } + + void SummonedCreatureDespawn(Creature *summon) + { + uint32 phase= summon->GetPhaseMask(); + uint32 nextPhase = 0; + Summons.Despawn(summon); + + // Check if all summons in this phase killed + for (SummonList::const_iterator iter = Summons.begin(); iter != Summons.end(); ++iter) + { + if (Creature *visage = Unit::GetCreature(*me, *iter)) + { + // Not all are dead + if (phase == visage->GetPhaseMask()) + return; + else + nextPhase = visage->GetPhaseMask(); + } + } + + // Roll Insanity + uint32 spell = GetSpellForPhaseMask(phase); + uint32 spell2 = GetSpellForPhaseMask(nextPhase); + Map* pMap = me->GetMap(); + if (!pMap) + return; + + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->HasAura(spell)) + { + pPlayer->RemoveAurasDueToSpell(spell); + if (spell2) // if there is still some different mask cast spell for it + pPlayer->CastSpell(pPlayer, spell2, true); + } + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (insanityHandled) + { + if (!Summons.empty()) + return; + + insanityHandled = 0; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetControlled(false, UNIT_STAT_STUNNED); + me->RemoveAurasDueToSpell(INSANITY_VISUAL); + } + + if (uiMindFlayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MIND_FLAY); + uiMindFlayTimer = 20*IN_MILISECONDS; + } else uiMindFlayTimer -= diff; + + if (uiShadowBoltVolleyTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); + uiShadowBoltVolleyTimer = 5*IN_MILISECONDS; + } else uiShadowBoltVolleyTimer -= diff; + + if (uiShiverTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHIVER); + uiShiverTimer = 15*IN_MILISECONDS; + } else uiShiverTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH_1, me); + + if (pInstance) + pInstance->SetData(DATA_HERALD_VOLAZJ, DONE); + + Summons.DespawnAll(); + ResetPlayersPhaseMask(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_volazj(Creature* pCreature) +{ + return new boss_volazjAI (pCreature); +} + +void AddSC_boss_volazj() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_volazj"; + newscript->GetAI = &GetAI_boss_volazj; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp new file mode 100644 index 00000000000..eb8046f63cd --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_jedoga_shadowseeker.cpp @@ -0,0 +1,588 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Comment: Complete - BUT THE TRIGGER NEEDS DATA WHETHER THE PRISON OF TALDARAM IS OFFLINE ! + */ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +enum Yells +{ + TEXT_AGGRO = -1619000, + TEXT_SACRIFICE_1_1 = -1619001, + TEXT_SACRIFICE_1_2 = -1619002, + TEXT_SACRIFICE_2_1 = -1619003, + TEXT_SACRIFICE_2_2 = -1619004, + TEXT_SLAY_1 = -1619005, + TEXT_SLAY_2 = -1619006, + TEXT_SLAY_3 = -1619007, + TEXT_DEATH = -1619008, + TEXT_PREACHING_1 = -1619009, + TEXT_PREACHING_2 = -1619010, + TEXT_PREACHING_3 = -1619011, + TEXT_PREACHING_4 = -1619012, + TEXT_PREACHING_5 = -1619013 +}; + +enum Spells +{ + SPELL_SPHERE_VISUAL = 56075, + SPELL_GIFT_OF_THE_HERALD = 56219, + SPELL_CYCLONE_STRIKE = 56855, // Self + SPELL_CYCLONE_STRIKE_H = 60030, + SPELL_LIGHTNING_BOLT = 56891, // 40Y + SPELL_LIGHTNING_BOLT_H = 60032, // 40Y + SPELL_THUNDERSHOCK = 56926, // 30Y + SPELL_THUNDERSHOCK_H = 60029 // 30Y +}; + +enum Creatures +{ + NPC_JEDOGA_CONTROLLER = 30181 +}; + +const Position JedogaPosition[2] = +{ + {372.330994f, -705.278015f, -0.624178f, 5.427970f}, + {372.330994f, -705.278015f, -16.179716f, 5.427970f} +}; + +struct boss_jedoga_shadowseekerAI : public ScriptedAI +{ + boss_jedoga_shadowseekerAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + bFirstTime = true; + bPreDone = false; + } + + ScriptedInstance* pInstance; + + uint32 uiOpFerTimer; + uint32 uiCycloneTimer; + uint32 uiBoltTimer; + uint32 uiThunderTimer; + + bool bPreDone; + bool bOpFerok; + bool bOnGround; + bool bOpFerokFail; + bool bCanDown; + + bool bFirstTime; + + void Reset() + { + uiOpFerTimer = urand(15*IN_MILISECONDS,20*IN_MILISECONDS); + + uiCycloneTimer = 3*IN_MILISECONDS; + uiBoltTimer = 7*IN_MILISECONDS; + uiThunderTimer = 12*IN_MILISECONDS; + + bOpFerok = false; + bOpFerokFail = false; + bOnGround = false; + bCanDown = false; + + if (pInstance) + { + if (!bFirstTime) + pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, FAIL); + + pInstance->SetData64(DATA_PL_JEDOGA_TARGET, 0); + pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); + pInstance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); + } + MoveUp(); + + bFirstTime = false; + } + + void EnterCombat(Unit* who) + { + if (!pInstance || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) + return; + + DoScriptText(TEXT_AGGRO, me); + me->SetInCombatWithZone(); + pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit* who) + { + if (!who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) + return; + + ScriptedAI::AttackStart(who); + } + + void KilledUnit(Unit* Victim) + { + if (!Victim || Victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(RAND(TEXT_SLAY_1, TEXT_SLAY_2, TEXT_SLAY_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(TEXT_DEATH, me); + if (pInstance) + pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, DONE); + } + + void MoveInLineOfSight(Unit* who) + { + if (!pInstance || !who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) + return; + + if (!bPreDone && who->GetTypeId() == TYPEID_PLAYER && me->GetDistance(who) < 100.0f) + { + DoScriptText(RAND(TEXT_PREACHING_1, TEXT_PREACHING_2, TEXT_PREACHING_3, TEXT_PREACHING_4, TEXT_PREACHING_5), me); + bPreDone = true; + } + + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS || !bOnGround) + return; + + if (!me->getVictim() && who->isTargetableForAttack() && me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + if (!me->getVictim()) + { + who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (me->GetMap()->IsDungeon()) + { + who->SetInCombatWith(me); + me->AddThreat(who, 0.0f); + } + } + } + } + + void MoveDown() + { + if (!pInstance) + return; + + bOpFerokFail = false; + + pInstance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 0); + me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); +/* me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); + me->SendMonsterMove(JedogaPosition[1], MOVEFLAG_JUMP, 0); + me->Relocate(JedogaPosition[1][0], JedogaPosition[1][1], JedogaPosition[1][2], JedogaPosition[1][3]); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); +*/ + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + + bOnGround = true; + + if (UpdateVictim()) + { + AttackStart(me->getVictim()); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + else + { + if (Unit* pTarget = Unit::GetUnit(*me, pInstance->GetData64(DATA_PL_JEDOGA_TARGET))) + { + AttackStart(pTarget); + pInstance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) + EnterCombat(pTarget); + } + else if (!me->isInCombat()) + EnterEvadeMode(); + } + } + + void MoveUp() + { + if (!pInstance) + return; + + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + + me->AttackStop(); + me->RemoveAllAuras(); + me->LoadCreaturesAddon(); + me->GetMotionMaster()->MovePoint(0, JedogaPosition[0]); +/* me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); + me->SendMonsterMove(JedogaPosition[0][0], JedogaPosition[0][1], JedogaPosition[0][2], 0, MOVEFLAG_JUMP, 0); + me->Relocate(JedogaPosition[0][0], JedogaPosition[0][1], JedogaPosition[0][2], JedogaPosition[0][3]); + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); +*/ + + pInstance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 1); + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) OpferRufen(); + + bOnGround = false; + uiOpFerTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } + + void OpferRufen() + { + if (!pInstance) + return; + + uint64 opfer = pInstance->GetData64(DATA_ADD_JEDOGA_INITIAND); + + if (opfer) + { + DoScriptText(RAND(TEXT_SACRIFICE_1_1, TEXT_SACRIFICE_1_2), me); + pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, opfer); + } else + bCanDown = true; + } + + void Opfern() + { + DoScriptText(RAND(TEXT_SACRIFICE_2_1, TEXT_SACRIFICE_2_2), me); + + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_GIFT_OF_THE_HERALD, false); + + bOpFerok = false; + bCanDown = true; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && pInstance->GetData(DATA_ALL_INITIAND_DEAD)) + MoveDown(); + + if (bOpFerok && !bOnGround && !bCanDown) Opfern(); + + if (bOpFerokFail && !bOnGround && !bCanDown) + bCanDown = true; + + if (bCanDown) + { + MoveDown(); + bCanDown = false; + } + + if (bOnGround) + { + if (!UpdateVictim()) + return; + + if (uiCycloneTimer <= diff) + { + DoCast(me, SPELL_CYCLONE_STRIKE, false); + uiCycloneTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiCycloneTimer -= diff; + + if (uiBoltTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + me->CastSpell(pTarget, DUNGEON_MODE(SPELL_LIGHTNING_BOLT, SPELL_LIGHTNING_BOLT_H), false); + + uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiBoltTimer -= diff; + + if (uiThunderTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + me->CastSpell(pTarget, DUNGEON_MODE(SPELL_THUNDERSHOCK, SPELL_THUNDERSHOCK_H), false); + + uiThunderTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiThunderTimer -= diff; + + if (uiOpFerTimer <= diff) + MoveUp(); + else + uiOpFerTimer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +struct mob_jedoga_initiandAI : public ScriptedAI +{ + mob_jedoga_initiandAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 bCheckTimer; + + bool bWalking; + + void Reset() + { + if (!pInstance) + return; + + bWalking = false; + bCheckTimer = 2*IN_MILISECONDS; + + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) + { + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + } + else + { + DoCast(me, SPELL_SPHERE_VISUAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + } + } + + void JustDied(Unit* Killer) + { + if (!Killer || !pInstance) return; + + if (bWalking) + { + Creature* boss = me->GetMap()->GetCreature(pInstance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); + if (boss && !CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok) CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = true; + + if (Killer->GetTypeId() == TYPEID_PLAYER) pInstance->SetData(DATA_INITIAND_KILLED, 1); + pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); + + bWalking = false; + } + if (Killer->GetTypeId() == TYPEID_PLAYER) pInstance->SetData64(DATA_PL_JEDOGA_TARGET, Killer->GetGUID()); + } + + void EnterCombat(Unit* who) + { + if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) return; + } + + void AttackStart(Unit* victim) + { + if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !victim) return; + + ScriptedAI::AttackStart(victim); + } + + void MoveInLineOfSight(Unit* who) + { + if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE || !pInstance) return; + + switch(uiPointId) + { + case 1: + { + Creature* boss = me->GetMap()->GetCreature(pInstance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); + if (boss) + { + CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok = true; + CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = false; + me->Kill(me); + } + } + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance && bCheckTimer <= diff) + { + if (me->GetGUID() == pInstance->GetData64(DATA_ADD_JEDOGA_OPFER) && !bWalking) + { + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + + float distance = me->GetDistance(JedogaPosition[1]); + + if (distance < 9.0f) + me->SetSpeed(MOVE_WALK, 0.5f, true); + else if (distance < 15.0f) + me->SetSpeed(MOVE_WALK, 0.75f, true); + else if (distance < 20.0f) + me->SetSpeed(MOVE_WALK, 1.0f, true); + + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); + bWalking = true; + } + if (!bWalking) + { + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && me->HasAura(SPELL_SPHERE_VISUAL)) + { + me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + } + if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS && !me->HasAura(SPELL_SPHERE_VISUAL)) + { + DoCast(me, SPELL_SPHERE_VISUAL, false); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); + } + } + bCheckTimer = 2*IN_MILISECONDS; + } else bCheckTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +// ------------------------------------------------------------------------------------------------------------ +// Jedogas Aufseher - Entry: 30181 +// ------------------------------------------------------------------------------------------------------------ +enum AufseherSpell +{ + SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1 = 60342, + SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2 = 56312 +}; + +struct npc_jedogas_aufseher_triggerAI : public Scripted_NoMovementAI +{ + npc_jedogas_aufseher_triggerAI(Creature* c) : Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); +// c->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); +// c->setFaction(35); + bRemoved = false; + bRemoved2 = false; + bCasted = false; + bCasted2 = false; + } + + ScriptedInstance* pInstance; + + bool bRemoved; + bool bRemoved2; + bool bCasted; + bool bCasted2; + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*victim*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 /*diff*/) + { + if (!pInstance) + return; + + if (!bRemoved && me->GetPositionX() > 440.0f) + { + if (pInstance->GetData(DATA_PRINCE_TALDARAM_EVENT) == DONE) + { + me->InterruptNonMeleeSpells(true); + bRemoved = true; + return; + } + if (!bCasted) + { + DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1, false); + bCasted = true; + } + } + if (!bRemoved2 && me->GetPositionX() < 440.0f) + { + if (!bCasted2 && pInstance->GetData(DATA_JEDOGA_TRIGGER_SWITCH)) + { + DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2, false); + bCasted2 = true; + } + if (bCasted2 && !pInstance->GetData(DATA_JEDOGA_TRIGGER_SWITCH)) + { + me->InterruptNonMeleeSpells(true); + bCasted2 = false; + } + if (!bRemoved2 && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == DONE) + { + me->InterruptNonMeleeSpells(true); + bRemoved2 = true; + } + } + } +}; + +CreatureAI* GetAI_boss_jedoga_shadowseeker(Creature* pCreature) +{ + return new boss_jedoga_shadowseekerAI (pCreature); +} + +CreatureAI* GetAI_mob_jedoga_initiand(Creature* pCreature) +{ + return new mob_jedoga_initiandAI (pCreature); +} + +CreatureAI* GetAI_npc_jedogas_aufseher_trigger(Creature* pCreature) +{ + return new npc_jedogas_aufseher_triggerAI (pCreature); +} + +void AddSC_boss_jedoga_shadowseeker() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_jedoga_shadowseeker"; + newscript->GetAI = &GetAI_boss_jedoga_shadowseeker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_jedoga_initiand"; + newscript->GetAI = &GetAI_mob_jedoga_initiand; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jedogas_aufseher_trigger"; + newscript->GetAI = &GetAI_npc_jedogas_aufseher_trigger; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp new file mode 100644 index 00000000000..93a66ccfbca --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/boss_prince_taldaram.cpp @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +enum Spells +{ + SPELL_BLOODTHIRST = 55968, //Trigger Spell + add aura + SPELL_CONJURE_FLAME_SPHERE = 55931, + SPELL_FLAME_SPHERE_SUMMON_1 = 55895,// 1x 30106 + H_SPELL_FLAME_SPHERE_SUMMON_1 = 59511,// 1x 31686 + H_SPELL_FLAME_SPHERE_SUMMON_2 = 59512,// 1x 31687 + SPELL_FLAME_SPHERE_SPAWN_EFFECT = 55891, + SPELL_FLAME_SPHERE_VISUAL = 55928, + SPELL_FLAME_SPHERE_PERIODIC = 55926, + H_SPELL_FLAME_SPHERE_PERIODIC = 59508, + SPELL_FLAME_SPHERE_DEATH_EFFECT = 55947, + SPELL_BEAM_VISUAL = 60342, + SPELL_EMBRACE_OF_THE_VAMPYR = 55959, + H_SPELL_EMBRACE_OF_THE_VAMPYR = 59513, + SPELL_VANISH = 55964, + CREATURE_FLAME_SPHERE = 30106, + H_CREATURE_FLAME_SPHERE_1 = 31686, + H_CREATURE_FLAME_SPHERE_2 = 31687 +}; +enum Misc +{ + DATA_EMBRACE_DMG = 20000, + H_DATA_EMBRACE_DMG = 40000, + DATA_SPHERE_DISTANCE = 15 +}; +#define DATA_SPHERE_ANGLE_OFFSET 0.7 +#define DATA_GROUND_POSITION_Z 11.4 + +enum Yells +{ + SAY_AGGRO = -1619021, + SAY_SLAY_1 = -1619022, + SAY_SLAY_2 = -1619023, + SAY_DEATH = -1619024, + SAY_FEED_1 = -1619025, + SAY_FEED_2 = -1619026, + SAY_VANISH_1 = -1619027, + SAY_VANISH_2 = -1619028 +}; +enum CombatPhase +{ + NORMAL, + CASTING_FLAME_SPHERES, + JUST_VANISHED, + VANISHED, + FEEDING +}; +enum GameObjects +{ + GO_SPHERE1 = 193093, + GO_SPHERE2 = 193094 +}; + +struct boss_taldaramAI : public ScriptedAI +{ + boss_taldaramAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + uint32 uiBloodthirstTimer; + uint32 uiVanishTimer; + uint32 uiWaitTimer; + uint32 uiEmbraceTimer; + uint32 uiEmbraceTakenDamage; + uint32 uiFlamesphereTimer; + uint32 uiPhaseTimer; + + uint64 uiEmbraceTarget; + + CombatPhase Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + uiBloodthirstTimer = 10*IN_MILISECONDS; + uiVanishTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); + uiEmbraceTimer = 20*IN_MILISECONDS; + uiFlamesphereTimer = 5*IN_MILISECONDS; + uiEmbraceTakenDamage = 0; + Phase = NORMAL; + uiPhaseTimer = 0; + uiEmbraceTarget = 0; + if (pInstance) + pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, IN_PROGRESS); + DoScriptText(SAY_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + if (uiPhaseTimer <= diff) + { + switch (Phase) + { + case CASTING_FLAME_SPHERES: + { + Creature* pSpheres[3]; + + //DoCast(me, SPELL_FLAME_SPHERE_SUMMON_1); + pSpheres[0] = DoSpawnCreature(CREATURE_FLAME_SPHERE, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); + Unit *pSphereTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pSphereTarget && pSpheres[0]) + { + float angle,x,y; + angle = pSpheres[0]->GetAngle(pSphereTarget); + x = pSpheres[0]->GetPositionX() + DATA_SPHERE_DISTANCE * cos(angle); + y = pSpheres[0]->GetPositionY() + DATA_SPHERE_DISTANCE * sin(angle); + pSpheres[0]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[0]->GetPositionZ()); + } + if (IsHeroic()) + { + //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_1); + pSpheres[1] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_1, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); + //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_2); + pSpheres[2] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_2, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); + if (pSphereTarget && pSpheres[1] && pSpheres[2]) + { + float angle,x,y; + angle = pSpheres[1]->GetAngle(pSphereTarget) + DATA_SPHERE_ANGLE_OFFSET; + x = pSpheres[1]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * cos(angle); + y = pSpheres[1]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * sin(angle); + pSpheres[1]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[1]->GetPositionZ()); + angle = pSpheres[2]->GetAngle(pSphereTarget) - DATA_SPHERE_ANGLE_OFFSET; + x = pSpheres[2]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * cos(angle); + y = pSpheres[2]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * sin(angle); + pSpheres[2]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[2]->GetPositionZ()); + } + } + + Phase = NORMAL; + uiPhaseTimer = 0; + break; + } + case JUST_VANISHED: + if (Unit *pEmbraceTarget = GetEmbraceTarget()) + { + me->GetMotionMaster()->Clear(); + me->SetSpeed(MOVE_WALK, 2.0f, true); + me->GetMotionMaster()->MoveChase(pEmbraceTarget); + } + Phase = VANISHED; + uiPhaseTimer = 1300; + break; + case VANISHED: + if (Unit *pEmbraceTarget = GetEmbraceTarget()) + DoCast(pEmbraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR); + me->GetMotionMaster()->Clear(); + me->SetSpeed(MOVE_WALK, 1.0f, true); + me->GetMotionMaster()->MoveChase(me->getVictim()); + Phase = FEEDING; + uiPhaseTimer = 20*IN_MILISECONDS; + break; + case FEEDING: + Phase = NORMAL; + uiPhaseTimer = 0; + uiEmbraceTarget = 0; + break; + case NORMAL: + if (uiBloodthirstTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BLOODTHIRST); + uiBloodthirstTimer = 10*IN_MILISECONDS; + } else uiBloodthirstTimer -= diff; + + if (uiFlamesphereTimer <= diff) + { + DoCast(me, SPELL_CONJURE_FLAME_SPHERE); + Phase = CASTING_FLAME_SPHERES; + uiPhaseTimer = 3*IN_MILISECONDS + diff; + uiFlamesphereTimer = 15*IN_MILISECONDS; + } else uiFlamesphereTimer -= diff; + + if (uiVanishTimer <= diff) + { + //Count alive players + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + // exclude pets & totems + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + target_list.push_back(pTarget); + pTarget = NULL; + } + //He only vanishes if there are 3 or more alive players + if (target_list.size() > 2) + { + DoScriptText(RAND(SAY_VANISH_1,SAY_VANISH_2), me); + DoCast(me, SPELL_VANISH); + Phase = JUST_VANISHED; + uiPhaseTimer = 500; + if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + uiEmbraceTarget = pEmbraceTarget->GetGUID(); + + } + uiVanishTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); + } else uiVanishTimer -= diff; + + DoMeleeAttackIfReady(); + break; + } + } else uiPhaseTimer -= diff; + } + + void DamageTaken(Unit* /*done_by*/, uint32 &damage) + { + Unit* pEmbraceTarget = GetEmbraceTarget(); + + if (Phase == FEEDING && pEmbraceTarget && pEmbraceTarget->isAlive()) + { + uiEmbraceTakenDamage += damage; + if (uiEmbraceTakenDamage > DUNGEON_MODE(DATA_EMBRACE_DMG, H_DATA_EMBRACE_DMG)) + { + Phase = NORMAL; + uiPhaseTimer = 0; + uiEmbraceTarget = 0; + me->CastStop(); + } + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + Unit* pEmbraceTarget = GetEmbraceTarget(); + if (Phase == FEEDING && pEmbraceTarget && victim == pEmbraceTarget) + { + Phase = NORMAL; + uiPhaseTimer = 0; + uiEmbraceTarget = 0; + } + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + bool CheckSpheres() + { + if (!pInstance) + return false; + + uint64 uiSphereGuids[2]; + uiSphereGuids[0] = pInstance->GetData64(DATA_SPHERE1); + uiSphereGuids[1] = pInstance->GetData64(DATA_SPHERE2); + + for (uint8 i=0; i < 2; ++i) + { + GameObject *pSpheres = pInstance->instance->GetGameObject(uiSphereGuids[i]); + if (!pSpheres) + return false; + if (pSpheres->GetGoState() != GO_STATE_ACTIVE) + return false; + } + RemovePrison(); + return true; + } + + Unit* GetEmbraceTarget() + { + if (!uiEmbraceTarget) + return NULL; + + return Unit::GetUnit(*me, uiEmbraceTarget); + } + + void RemovePrison() + { + if (!pInstance) + return; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAurasDueToSpell(SPELL_BEAM_VISUAL); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation()); + uint64 prison_GUID = pInstance->GetData64(DATA_PRINCE_TALDARAM_PLATFORM); + pInstance->HandleGameObject(prison_GUID,true); + } +}; + +struct mob_taldaram_flamesphereAI : public ScriptedAI +{ + mob_taldaram_flamesphereAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiDespawnTimer; + ScriptedInstance* pInstance; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->setFaction(16); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + DoCast(me, SPELL_FLAME_SPHERE_VISUAL); + DoCast(me, SPELL_FLAME_SPHERE_SPAWN_EFFECT); + DoCast(me, SPELL_FLAME_SPHERE_PERIODIC); + uiDespawnTimer = 10*IN_MILISECONDS; + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void JustDied(Unit* /*who*/) + { + DoCast(me, SPELL_FLAME_SPHERE_DEATH_EFFECT); + } + + void UpdateAI(const uint32 diff) + { + if (uiDespawnTimer <= diff) + me->DisappearAndDie(); + else + uiDespawnTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_taldaram(Creature* pCreature) +{ + return new boss_taldaramAI (pCreature); +} + +CreatureAI* GetAI_mob_taldaram_flamesphere(Creature* pCreature) +{ + return new mob_taldaram_flamesphereAI (pCreature); +} + +bool GOHello_prince_taldaram_sphere(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + + Creature *pPrinceTaldaram = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_PRINCE_TALDARAM) : 0); + if (pPrinceTaldaram && pPrinceTaldaram->isAlive()) + { + // maybe these are hacks :( + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + switch(pGO->GetEntry()) + { + case GO_SPHERE1: pInstance->SetData(DATA_SPHERE1_EVENT,IN_PROGRESS); break; + case GO_SPHERE2: pInstance->SetData(DATA_SPHERE2_EVENT,IN_PROGRESS); break; + } + + CAST_AI(boss_taldaramAI, pPrinceTaldaram->AI())->CheckSpheres(); + } + return true; +} + +void AddSC_boss_taldaram() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_taldaram"; + newscript->GetAI = &GetAI_boss_taldaram; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_taldaram_flamesphere"; + newscript->GetAI = &GetAI_mob_taldaram_flamesphere; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "prince_taldaram_sphere"; + newscript->pGOHello = &GOHello_prince_taldaram_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp new file mode 100644 index 00000000000..4e6e3ec8c9f --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/ahnkahet/instance_ahnkahet.cpp @@ -0,0 +1,313 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "ahnkahet.h" + +/* Ahn'kahet encounters: +0 - Elder Nadox +1 - Prince Taldaram +2 - Jedoga Shadowseeker +3 - Herald Volazj +4 - Amanitar (Heroic only) +*/ + +#define MAX_ENCOUNTER 5 + +enum Achievements +{ + ACHIEV_VOLUNTEER_WORK = 2056 +}; + +struct instance_ahnkahet : public ScriptedInstance +{ + instance_ahnkahet(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 Elder_Nadox; + uint64 Prince_Taldaram; + uint64 Jedoga_Shadowseeker; + uint64 Herald_Volazj; + uint64 Amanitar; + + uint64 Prince_TaldaramSpheres[2]; + uint64 Prince_TaldaramPlatform; + uint64 Prince_TaldaramGate; + + std::set InitiandGUIDs; + uint64 JedogaSacrifices; + uint64 JedogaTarget; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 spheres[2]; + + uint8 InitiandCnt, + switchtrigger, + initiandkilled; + + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + InitiandGUIDs.clear(); + + Elder_Nadox =0; + Prince_Taldaram =0; + Jedoga_Shadowseeker =0; + Herald_Volazj =0; + Amanitar =0; + + spheres[0] = NOT_STARTED; + spheres[1] = NOT_STARTED; + + InitiandCnt = 0; + switchtrigger = 0; + initiandkilled = 0; + JedogaSacrifices = 0; + JedogaTarget = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 29309: Elder_Nadox = pCreature->GetGUID(); break; + case 29308: Prince_Taldaram = pCreature->GetGUID(); break; + case 29310: Jedoga_Shadowseeker = pCreature->GetGUID(); break; + case 29311: Herald_Volazj = pCreature->GetGUID(); break; + case 30258: Amanitar = pCreature->GetGUID(); break; + case 30114: InitiandGUIDs.insert(pCreature->GetGUID()); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 193564: Prince_TaldaramPlatform = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) HandleGameObject(NULL,true,pGo); break; + case 193093: Prince_TaldaramSpheres[0] = pGo->GetGUID(); + if (spheres[0] == IN_PROGRESS) + { + pGo->SetGoState(GO_STATE_ACTIVE); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + else pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case 193094: Prince_TaldaramSpheres[1] = pGo->GetGUID(); + if (spheres[1] == IN_PROGRESS) + { + pGo->SetGoState(GO_STATE_ACTIVE); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + else pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + case 192236: Prince_TaldaramGate = pGo->GetGUID(); // Web gate past Prince Taldaram + if (m_auiEncounter[1] == DONE)HandleGameObject(NULL,true,pGo);break; + } + } + + void SetData64(uint32 idx, uint64 guid) + { + switch(idx) + { + case DATA_ADD_JEDOGA_OPFER: JedogaSacrifices = guid; break; + case DATA_PL_JEDOGA_TARGET: JedogaTarget = guid; break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_ELDER_NADOX: return Elder_Nadox; + case DATA_PRINCE_TALDARAM: return Prince_Taldaram; + case DATA_JEDOGA_SHADOWSEEKER: return Jedoga_Shadowseeker; + case DATA_HERALD_VOLAZJ: return Herald_Volazj; + case DATA_AMANITAR: return Amanitar; + case DATA_SPHERE1: return Prince_TaldaramSpheres[0]; + case DATA_SPHERE2: return Prince_TaldaramSpheres[1]; + case DATA_PRINCE_TALDARAM_PLATFORM: return Prince_TaldaramPlatform; + case DATA_ADD_JEDOGA_INITIAND: + { + std::vector vInitiands; + vInitiands.clear(); + for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (cr && cr->isAlive()) + vInitiands.push_back(*itr); + } + if (vInitiands.empty()) + return 0; + uint8 j = urand(0,vInitiands.size() -1); + return vInitiands[j]; + } + case DATA_ADD_JEDOGA_OPFER: return JedogaSacrifices; + case DATA_PL_JEDOGA_TARGET: return JedogaTarget; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_ELDER_NADOX_EVENT: m_auiEncounter[0] = data; break; + case DATA_PRINCE_TALDARAM_EVENT: + if (data == DONE) + HandleGameObject(Prince_TaldaramGate,true); + m_auiEncounter[1] = data; + break; + case DATA_JEDOGA_SHADOWSEEKER_EVENT: + m_auiEncounter[2] = data; + if (data == DONE) + { + for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (cr && cr->isAlive()) + { + cr->SetVisibility(VISIBILITY_OFF); + cr->setDeathState(JUST_DIED); + cr->RemoveCorpse(); + } + } + if (!initiandkilled && instance->IsHeroic()) + DoCompleteAchievement(ACHIEV_VOLUNTEER_WORK); + } + break; + case DATA_HERALD_VOLAZJ_EVENT: m_auiEncounter[3] = data; break; + case DATA_AMANITAR_EVENT: m_auiEncounter[4] = data; break; + case DATA_SPHERE1_EVENT: spheres[0] = data; break; + case DATA_SPHERE2_EVENT: spheres[1] = data; break; + case DATA_JEDOGA_TRIGGER_SWITCH: switchtrigger = data; break; + case DATA_INITIAND_KILLED: initiandkilled = data; break; + case DATA_JEDOGA_RESET_INITIANDS: + for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (cr) + { + cr->Respawn(); + if (!cr->IsInEvadeMode()) cr->AI()->EnterEvadeMode(); + } + } + break; + } + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_ELDER_NADOX_EVENT: return m_auiEncounter[0]; + case DATA_PRINCE_TALDARAM_EVENT: return m_auiEncounter[1]; + case DATA_JEDOGA_SHADOWSEEKER_EVENT: return m_auiEncounter[2]; + case DATA_HERALD_VOLAZJ: return m_auiEncounter[3]; + case DATA_AMANITAR_EVENT: return m_auiEncounter[4]; + case DATA_SPHERE1_EVENT: return spheres[0]; + case DATA_SPHERE2_EVENT: return spheres[1]; + case DATA_ALL_INITIAND_DEAD: + for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (!cr || (cr && cr->isAlive())) return 0; + } + return 1; + case DATA_JEDOGA_TRIGGER_SWITCH: return switchtrigger; + case DATA_INITIAND_KILLED: return initiandkilled; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "A K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " + << spheres[0] << " " << spheres[1]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5, data6; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6; + + if (dataHead1 == 'A' && dataHead2 == 'K') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + spheres[0] = data5; + spheres[1] = data6; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_ahnkahet(Map* pMap) +{ + return new instance_ahnkahet(pMap); +} + +void AddSC_instance_ahnkahet() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_ahnkahet"; + newscript->GetInstanceData = &GetInstanceData_instance_ahnkahet; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h new file mode 100644 index 00000000000..4113885b6f4 --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_AZJOL_NERUB_H +#define DEF_AZJOL_NERUB_H + +enum Data64 +{ + DATA_KRIKTHIR_THE_GATEWATCHER, + DATA_HADRONOX, + DATA_ANUBARAK, + DATA_WATCHER_GASHRA, + DATA_WATCHER_SILTHIK, + DATA_WATCHER_NARJIL +}; +enum Data +{ + DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, + DATA_HADRONOX_EVENT, + DATA_ANUBARAK_EVENT +}; + +#endif diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp new file mode 100644 index 00000000000..6de6578f7bb --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp @@ -0,0 +1,360 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +//SQL: UPDATE creature_template SET mechanic_immune_mask = 1073741823 WHERE name like "anub'arak%"; + +enum Spells +{ + SPELL_CARRION_BEETLES = 53520, + SPELL_SUMMON_CARRION_BEETLES = 53521, + SPELL_LEECHING_SWARM = 53467, + SPELL_POUND = 53472, + SPELL_POUND_H = 59433, + SPELL_SUBMERGE = 53421, + SPELL_IMPALE_DMG = 53454, + SPELL_IMPALE_DMG_H = 59446, + SPELL_IMPALE_SHAKEGROUND = 53455, + SPELL_IMPALE_SPIKE = 53539, //this is not the correct visual effect + //SPELL_IMPALE_TARGET = 53458, +}; + +enum Creatures +{ + CREATURE_GUARDIAN = 29216, + CREATURE_VENOMANCER = 29217, + CREATURE_DATTER = 29213, + CREATURE_IMPALE_TARGET = 89, + DISPLAY_INVISIBLE = 11686 +}; + +// not in db +enum Yells +{ + SAY_INTRO = -1601010, + SAY_AGGRO = -1601000, + SAY_SLAY_1 = -1601001, + SAY_SLAY_2 = -1601002, + SAY_SLAY_3 = -1601003, + SAY_LOCUST_1 = -1601005, + SAY_LOCUST_2 = -1601006, + SAY_LOCUST_3 = -1601007, + SAY_SUBMERGE_1 = -1601008, + SAY_SUBMERGE_2 = -1601009, + SAY_DEATH = -1601004 +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 20381, +}; + +enum Phases +{ + PHASE_MELEE = 0, + PHASE_UNDERGROUND = 1, + IMPALE_PHASE_TARGET = 0, + IMPALE_PHASE_ATTACK = 1, + IMPALE_PHASE_DMG = 2 +}; + +const Position SpawnPoint[2] = +{ + { 550.7, 282.8, 224.3 }, + { 551.1, 229.4, 224.3 }, +}; + +const Position SpawnPointGuardian[2] = +{ + { 550.348633, 316.006805, 234.2947 }, + { 550.188660, 324.264557, 237.7412 }, +}; + +struct boss_anub_arakAI : public ScriptedAI +{ + boss_anub_arakAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + bool bChanneling; + bool bGuardianSummoned; + bool bVenomancerSummoned; + bool bDatterSummoned; + uint8 uiPhase; + uint32 uiUndergroundPhase; + uint32 uiCarrionBeetlesTimer; + uint32 uiLeechingSwarmTimer; + uint32 uiPoundTimer; + uint32 uiSubmergeTimer; + uint32 uiUndergroundTimer; + uint32 uiVenomancerTimer; + uint32 uiDatterTimer; + + uint32 uiImpaleTimer; + uint32 uiImpalePhase; + uint64 uiImpaleTarget; + + SummonList lSummons; + + void Reset() + { + uiCarrionBeetlesTimer = 8*IN_MILISECONDS; + uiLeechingSwarmTimer = 20*IN_MILISECONDS; + uiImpaleTimer = 9*IN_MILISECONDS; + uiPoundTimer = 15*IN_MILISECONDS; + + uiPhase = PHASE_MELEE; + uiUndergroundPhase = 0; + bChanneling = false; + uiImpalePhase = IMPALE_PHASE_TARGET; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAura(SPELL_SUBMERGE); + + lSummons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_ANUBARAK_EVENT, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + Creature* DoSummonImpaleTarget(Unit *pTarget) + { + Position targetPos; + pTarget->GetPosition(&targetPos); + + if (TempSummon* pImpaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILISECONDS)) + { + uiImpaleTarget = pImpaleTarget->GetGUID(); + pImpaleTarget->SetReactState(REACT_PASSIVE); + pImpaleTarget->SetDisplayId(DISPLAY_INVISIBLE); + pImpaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + return pImpaleTarget; + } + + return NULL; + } + + void EnterCombat(Unit * /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + pInstance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + switch (uiPhase) + { + case PHASE_UNDERGROUND: + if (uiImpaleTimer <= diff) + { + switch(uiImpalePhase) + { + case IMPALE_PHASE_TARGET: + if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) + pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SHAKEGROUND, true); + uiImpaleTimer = 3*IN_MILISECONDS; + uiImpalePhase = IMPALE_PHASE_ATTACK; + } + break; + case IMPALE_PHASE_ATTACK: + if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) + { + pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SPIKE, false); + pImpaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND); + } + uiImpalePhase = IMPALE_PHASE_DMG; + uiImpaleTimer = 1*IN_MILISECONDS; + break; + case IMPALE_PHASE_DMG: + if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) + me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_IMPALE_DMG, SPELL_IMPALE_DMG_H), true); + uiImpalePhase = IMPALE_PHASE_TARGET; + uiImpaleTimer = 9*IN_MILISECONDS; + break; + } + } else uiImpaleTimer -= diff; + + if (!bGuardianSummoned) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Guardian = me->SummonCreature(CREATURE_GUARDIAN,SpawnPointGuardian[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Guardian->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Guardian); + } + } + bGuardianSummoned = true; + } + + if (!bVenomancerSummoned) + { + if (uiVenomancerTimer <= diff) + { + if (uiUndergroundPhase > 1) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Venomancer = me->SummonCreature(CREATURE_VENOMANCER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Venomancer->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Venomancer); + } + } + bVenomancerSummoned = true; + } + } else uiVenomancerTimer -= diff; + } + + if (!bDatterSummoned) + { + if (uiDatterTimer <= diff) + { + if (uiUndergroundPhase > 2) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Datter = me->SummonCreature(CREATURE_DATTER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Datter->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Datter); + } + } + bDatterSummoned = true; + } + } else uiDatterTimer -= diff; + } + + if (uiUndergroundTimer <= diff) + { + me->RemoveAura(SPELL_SUBMERGE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + uiPhase = PHASE_MELEE; + } else uiUndergroundTimer -= diff; + break; + + case PHASE_MELEE: + if (((uiUndergroundPhase == 0 && HealthBelowPct(75)) + || (uiUndergroundPhase == 1 && HealthBelowPct(50)) + || (uiUndergroundPhase == 2 && HealthBelowPct(25))) + && !me->hasUnitState(UNIT_STAT_CASTING)) + { + bGuardianSummoned = false; + bVenomancerSummoned = false; + bDatterSummoned = false; + + uiUndergroundTimer = 40*IN_MILISECONDS; + uiVenomancerTimer = 25*IN_MILISECONDS; + uiDatterTimer = 32*IN_MILISECONDS; + + uiImpalePhase = 0; + uiImpaleTimer = 9*IN_MILISECONDS; + + DoCast(me, SPELL_SUBMERGE, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + + uiPhase = PHASE_UNDERGROUND; + ++uiUndergroundPhase; + } + + if (bChanneling == true) + { + for (uint8 i = 0; i < 8; ++i) + DoCast(me->getVictim(), SPELL_SUMMON_CARRION_BEETLES, true); + bChanneling = false; + } + else if (uiCarrionBeetlesTimer <= diff) + { + bChanneling = true; + DoCastVictim(SPELL_CARRION_BEETLES); + uiCarrionBeetlesTimer = 25*IN_MILISECONDS; + } else uiCarrionBeetlesTimer -= diff; + + if (uiLeechingSwarmTimer <= diff) + { + DoCast(me, SPELL_LEECHING_SWARM, true); + uiLeechingSwarmTimer = 19*IN_MILISECONDS; + } else uiLeechingSwarmTimer -= diff; + + if (uiPoundTimer <= diff) + { + if (Unit *target = me->getVictim()) + { + if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) + me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_POUND, SPELL_POUND_H), false); + } + uiPoundTimer = 16.5*IN_MILISECONDS; + } else uiPoundTimer -= diff; + + DoMeleeAttackIfReady(); + break; + } + } + + void JustDied(Unit * /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + lSummons.DespawnAll(); + if (pInstance) + pInstance->SetData(DATA_ANUBARAK_EVENT, DONE); + } + + void KilledUnit(Unit *pVictim) + { + if (pVictim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustSummoned(Creature* summon) + { + lSummons.Summon(summon); + } +}; + +CreatureAI* GetAI_boss_anub_arak(Creature *pCreature) +{ + return new boss_anub_arakAI (pCreature); +} + +void AddSC_boss_anub_arak() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_anub_arak"; + newscript->GetAI = &GetAI_boss_anub_arak; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp new file mode 100644 index 00000000000..0fc4e87d7c5 --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* +* Comment: No Waves atm and the doors spells are crazy... +* +* When your group enters the main room (the one after the bridge), you will notice a group of 3 Nerubians. +* When you engage them, 2 more groups like this one spawn behind the first one - it is important to pull the first group back, +* so you don't aggro all 3. Hadronox will be under you, fighting Nerubians. +* +* This is the timed gauntlet - waves of non-elite spiders +* will spawn from the 3 doors located a little above the main room, and will then head down to fight Hadronox. After clearing the +* main room, it is recommended to just stay in it, kill the occasional non-elites that will attack you instead of the boss, and wait for +* Hadronox to make his way to you. When Hadronox enters the main room, she will web the doors, and no more non-elites will spawn. +*/ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +enum Spells +{ + SPELL_ACID_CLOUD = 53400, // Victim + SPELL_LEECH_POISON = 53030, // Victim + SPELL_PIERCE_ARMOR = 53418, // Victim + SPELL_WEB_GRAB = 57731, // Victim + SPELL_WEB_FRONT_DOORS = 53177, // Self + SPELL_WEB_SIDE_DOORS = 53185, // Self + H_SPELL_ACID_CLOUD = 59419, + H_SPELL_LEECH_POISON = 59417, + H_SPELL_WEB_GRAB = 59421 +}; + +struct boss_hadronoxAI : public ScriptedAI +{ + boss_hadronoxAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + fMaxDistance = 50.0f; + bFirstTime = true; + } + + ScriptedInstance* pInstance; + + uint32 uiAcidTimer; + uint32 uiLeechTimer; + uint32 uiPierceTimer; + uint32 uiGrabTimer; + uint32 uiDoorsTimer; + uint32 uiCheckDistanceTimer; + + bool bFirstTime; + + float fMaxDistance; + + void Reset() + { + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 9.0f); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 9.0f); + + uiAcidTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); + uiLeechTimer = urand(3*IN_MILISECONDS,9*IN_MILISECONDS); + uiPierceTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); + uiGrabTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); + uiDoorsTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + uiCheckDistanceTimer = 2*IN_MILISECONDS; + + if (pInstance && (pInstance->GetData(DATA_HADRONOX_EVENT) != DONE && !bFirstTime)) + pInstance->SetData(DATA_HADRONOX_EVENT, FAIL); + + bFirstTime = false; + } + + //when Hadronox kills any enemy (that includes a party member) she will regain 10% of her HP if the target had Leech Poison on + void KilledUnit(Unit* Victim) + { + // not sure if this aura check is correct, I think it is though + if (!Victim || !Victim->HasAura(DUNGEON_MODE(SPELL_LEECH_POISON, H_SPELL_LEECH_POISON)) || !me->isAlive()) + return; + + uint32 health = me->GetMaxHealth()/10; + + if ((me->GetHealth()+health) >= me->GetMaxHealth()) + me->SetHealth(me->GetMaxHealth()); + else + me->SetHealth(me->GetHealth()+health); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_HADRONOX_EVENT, DONE); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HADRONOX_EVENT, IN_PROGRESS); + me->SetInCombatWithZone(); + } + + void CheckDistance(float dist, const uint32 uiDiff) + { + if (!me->isInCombat()) + return; + + float x=0.0f, y=0.0f, z=0.0f; + me->GetRespawnCoord(x,y,z); + + if (uiCheckDistanceTimer <= uiDiff) + uiCheckDistanceTimer = 5*IN_MILISECONDS; + else + { + uiCheckDistanceTimer -= uiDiff; + return; + } + if (me->IsInEvadeMode() || !me->getVictim()) + return; + if (me->GetDistance(x,y,z) > dist) + EnterEvadeMode(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) return; + + // Without he comes up through the air to players on the bridge after krikthir if players crossing this bridge! + CheckDistance(fMaxDistance, diff); + + if (me->HasAura(SPELL_WEB_FRONT_DOORS) || me->HasAura(SPELL_WEB_SIDE_DOORS)) + { + if (IsCombatMovement()) + SetCombatMovement(false); + } + else if (!IsCombatMovement()) + SetCombatMovement(true); + + if (uiPierceTimer <= diff) + { + DoCast(me->getVictim(), SPELL_PIERCE_ARMOR); + uiPierceTimer = 8*IN_MILISECONDS; + } else uiPierceTimer -= diff; + + if (uiAcidTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ACID_CLOUD); + + uiAcidTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiAcidTimer -= diff; + + if (uiLeechTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_LEECH_POISON); + + uiLeechTimer = urand(11*IN_MILISECONDS,14*IN_MILISECONDS); + } else uiLeechTimer -= diff; + + if (uiGrabTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) // Draws all players (and attacking Mobs) to itself. + DoCast(pTarget, SPELL_WEB_GRAB); + + uiGrabTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiGrabTimer -= diff; + + if (uiDoorsTimer <= diff) + { + //DoCast(me, RAND(SPELL_WEB_FRONT_DOORS, SPELL_WEB_SIDE_DOORS)); + uiDoorsTimer = urand(30*IN_MILISECONDS,60*IN_MILISECONDS); + } else uiDoorsTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_hadronox(Creature* pCreature) +{ + return new boss_hadronoxAI (pCreature); +} + +void AddSC_boss_hadronox() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_hadronox"; + newscript->GetAI = &GetAI_boss_hadronox; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp new file mode 100644 index 00000000000..4863bdcb032 --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp @@ -0,0 +1,553 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: Find in the future best timers and the event is not implemented. + */ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +enum Spells +{ + SPELL_MIND_FLAY = 52586, + H_SPELL_MIND_FLAY = 59367, + SPELL_CURSE_OF_FATIGUE = 52592, + H_SPELL_CURSE_OF_FATIGUE = 59368, + SPELL_FRENZY = 28747, //maybe 53361 + SPELL_SUMMON_SKITTERING_SWARMER = 52438, //AOE Effect 140, maybe 52439 + SPELL_SUMMON_SKITTERING_SWARMER_1 = 52439, //Summon 3x 28735 + H_SPELL_ACID_SPLASH = 59363, + SPELL_ACID_SPLASH = 52446, + SPELL_CHARGE = 16979,//maybe is another spell + SPELL_BACKSTAB = 52540, + SPELL_SHADOW_BOLT = 52534, + H_SPELL_SHADOW_BOLT = 59357, + SPELL_SHADOW_NOVA = 52535, + H_SPELL_SHADOW_NOVA = 59358, + SPELL_STRIKE = 52532, + SPELL_CLEAVE = 49806, + SPELL_ENRAGE = 52470, + SPELL_INFECTED_BITE = 52469, + H_SPELL_INFECTED_BITE = 59364, + SPELL_WEB_WRAP = 52086,//the spell is not working properly + SPELL_BLINDING_WEBS = 52524, + H_SPELL_BLINDING_WEBS = 59365, + SPELL_POSION_SPRAY = 52493, + H_SPELL_POSION_SPRAY = 59366 +}; + +enum Mobs +{ + MOB_SKITTERING_SWARMER = 28735, + MOB_SKITTERING_SWARMER_CONTROLLER = 32593, + MOB_SKITTERING_INFECTIOR = 28736 +}; + +enum Yells +{ + SAY_AGGRO = -1601011, + SAY_SLAY_1 = -1601012, + SAY_SLAY_2 = -1601013, + SAY_DEATH = -1601014, + //Not in db + SAY_SEND_GROUP_1 = -1601020, + SAY_SEND_GROUP_2 = -1601021, + SAY_SEND_GROUP_3 = -1601022, + SAY_SWARM_1 = -1601015, + SAY_SWARM_2 = -1601016, + SAY_PREFIGHT_1 = -1601017, + SAY_PREFIGHT_2 = -1601018, + SAY_PREFIGHT_3 = -1601019 +}; + +enum Misc +{ + ACHIEV_WATH_HIM_DIE = 1296 +}; + +const Position SpawnPoint[] = +{ + { 566.164, 682.087, 769.079, 2.21657 }, + { 529.042, 706.941, 777.298, 1.0821 }, + { 489.975, 671.239, 772.131, 0.261799 }, + { 488.556, 692.95, 771.764, 4.88692 }, + { 553.34, 640.387, 777.419, 1.20428 }, + { 517.486, 706.398, 777.335, 5.35816 }, + { 504.01, 637.693, 777.479, 0.506145 }, + { 552.625, 706.408, 777.177, 3.4383 } +}; +struct boss_krik_thirAI : public ScriptedAI +{ + boss_krik_thirAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiMindFlayTimer; + uint32 uiCurseFatigueTimer; + uint32 uiSummonTimer; + + void Reset() + { + uiMindFlayTimer = 15*IN_MILISECONDS; + uiCurseFatigueTimer = 12*IN_MILISECONDS; + + if (pInstance) + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + Summon(); + uiSummonTimer = 15*IN_MILISECONDS; + + if (pInstance) + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, IN_PROGRESS); + } + + void Summon() + { + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiSummonTimer <= diff) + { + Summon(); + uiSummonTimer = 15*IN_MILISECONDS; + } else uiSummonTimer -= diff; + + if (uiMindFlayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MIND_FLAY); + uiMindFlayTimer = 15*IN_MILISECONDS; + } else uiMindFlayTimer -= diff; + + if (uiCurseFatigueTimer <= diff) + { + //WowWiki say "Curse of Fatigue-Kirk'thir will cast Curse of Fatigue on 2-3 targets periodically." + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + Unit *pTarget_1 = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + + DoCast(pTarget, SPELL_CURSE_OF_FATIGUE); + DoCast(pTarget_1, SPELL_CURSE_OF_FATIGUE); + + uiCurseFatigueTimer = 10*IN_MILISECONDS; + } else uiCurseFatigueTimer -= diff; + + if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10)) + DoCast(me, SPELL_FRENZY, true); + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DONE); + //Achievement: Watch him die + Creature *pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_GASHRA)); + if (!pAdd || !pAdd->isAlive()) + return; + + pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_SILTHIK)); + if (!pAdd || !pAdd->isAlive()) + return; + + pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_NARJIL)); + if (!pAdd || !pAdd->isAlive()) + return; + + pInstance->DoCompleteAchievement(ACHIEV_WATH_HIM_DIE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustSummoned(Creature* summoned) + { + summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); + } +}; + +struct npc_skittering_infectorAI : public ScriptedAI +{ + npc_skittering_infectorAI(Creature *c) : ScriptedAI(c) {} + + void JustDied(Unit* /*killer*/) + { + //The spell is not working propperly + DoCast(me->getVictim(),SPELL_ACID_SPLASH, true); + } + +}; + +struct npc_anub_ar_skirmisherAI : public ScriptedAI +{ + npc_anub_ar_skirmisherAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiChargeTimer; + uint32 uiBackstabTimer; + + void Reset() + { + uiChargeTimer = 11*IN_MILISECONDS; + uiBackstabTimer = 7*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiChargeTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoResetThreat(); + me->AddThreat(pTarget,1.0f); + DoCast(pTarget, SPELL_CHARGE, true); + } + uiChargeTimer = 15*IN_MILISECONDS; + } else uiChargeTimer -= diff; + + if (uiBackstabTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BACKSTAB); + uiBackstabTimer = 12*IN_MILISECONDS; + } else uiBackstabTimer -= diff; + + DoMeleeAttackIfReady(); + + } +}; + +struct npc_anub_ar_shadowcasterAI : public ScriptedAI +{ + npc_anub_ar_shadowcasterAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiShadowBoltTimer; + uint32 uiShadowNovaTimer; + + void Reset() + { + uiShadowBoltTimer = 6*IN_MILISECONDS; + uiShadowNovaTimer = 15*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiShadowBoltTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SHADOW_BOLT, true); + uiShadowBoltTimer = 15*IN_MILISECONDS; + } else uiShadowBoltTimer -= diff; + + if (uiShadowNovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_NOVA, true); + uiShadowNovaTimer = 17*IN_MILISECONDS; + } else uiShadowNovaTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_anub_ar_warriorAI : public ScriptedAI +{ + npc_anub_ar_warriorAI(Creature *c) : ScriptedAI(c){} + + uint32 uiCleaveTimer; + uint32 uiStrikeTimer; + + void Reset() + { + uiCleaveTimer = 11*IN_MILISECONDS; + uiStrikeTimer = 6*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STRIKE, true); + uiStrikeTimer = 15*IN_MILISECONDS; + } else uiStrikeTimer -= diff; + + if (uiCleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE, true); + uiCleaveTimer = 17*IN_MILISECONDS; + } else uiCleaveTimer -= diff; + + DoMeleeAttackIfReady(); + + } + +}; + +struct npc_watcher_gashraAI : public ScriptedAI +{ + npc_watcher_gashraAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_ENRAGE, true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + uiWebWrapTimer = 17*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 15*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_watcher_narjilAI : public ScriptedAI +{ + npc_watcher_narjilAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + uint32 uiBindingWebsTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + uiBindingWebsTimer = 17*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + uiWebWrapTimer = 15*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 11*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + if (uiBindingWebsTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BLINDING_WEBS, true); + uiBindingWebsTimer = 17*IN_MILISECONDS; + } else uiBindingWebsTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_watcher_silthikAI : public ScriptedAI +{ + npc_watcher_silthikAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + uint32 uiPoisonSprayTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + uiPoisonSprayTimer = 15*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + + uiWebWrapTimer = 15*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 15*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + if (uiPoisonSprayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POSION_SPRAY, true); + uiPoisonSprayTimer = 17*IN_MILISECONDS; + } else uiPoisonSprayTimer -= diff; + + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_boss_krik_thir(Creature* pCreature) +{ + return new boss_krik_thirAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_skirmisher (Creature* pCreature) +{ + return new npc_anub_ar_skirmisherAI (pCreature); +} + +CreatureAI* GetAI_npc_skittering_infector (Creature* pCreature) +{ + return new npc_skittering_infectorAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_shadowcaster (Creature* pCreature) +{ + return new npc_anub_ar_shadowcasterAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_warrior (Creature* pCreature) +{ + return new npc_anub_ar_warriorAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_gashra (Creature* pCreature) +{ + return new npc_watcher_gashraAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_narjil (Creature* pCreature) +{ + return new npc_watcher_narjilAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_silthik (Creature* pCreature) +{ + return new npc_watcher_silthikAI (pCreature); +} + +void AddSC_boss_krik_thir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_krik_thir"; + newscript->GetAI = &GetAI_boss_krik_thir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_skittering_infector"; + newscript->GetAI = &GetAI_npc_skittering_infector; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_skirmisher"; + newscript->GetAI = &GetAI_npc_anub_ar_skirmisher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_shadowcaster"; + newscript->GetAI = &GetAI_npc_anub_ar_shadowcaster; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_gashra"; + newscript->GetAI = &GetAI_npc_watcher_gashra; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_warrior"; + newscript->GetAI = &GetAI_npc_anub_ar_warrior; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_silthik"; + newscript->GetAI = &GetAI_npc_watcher_silthik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_narjil"; + newscript->GetAI = &GetAI_npc_watcher_narjil; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp new file mode 100644 index 00000000000..d12dbd604ba --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +#define MAX_ENCOUNTER 3 + +/* Azjol Nerub encounters: +0 - Krik'thir the Gatewatcher +1 - Hadronox +2 - Anub'arak +*/ + +struct instance_azjol_nerub : public ScriptedInstance +{ + instance_azjol_nerub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiKrikthir; + uint64 uiHadronox; + uint64 uiAnubarak; + uint64 uiWatcherGashra; + uint64 uiWatcherSilthik; + uint64 uiWatcherNarjil; + uint64 uiAnubarakDoor[3]; + + uint64 uiKrikthirDoor; + + uint32 auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&auiEncounter, 0, sizeof(auiEncounter)); + memset(&uiAnubarakDoor, 0, sizeof(uiAnubarakDoor)); + + uiKrikthir = 0; + uiHadronox = 0; + uiAnubarak = 0; + uiWatcherGashra = 0; + uiWatcherSilthik = 0; + uiWatcherNarjil = 0; + uiKrikthirDoor = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 28684: uiKrikthir = pCreature->GetGUID(); break; + case 28921: uiHadronox = pCreature->GetGUID(); break; + case 29120: uiAnubarak = pCreature->GetGUID(); break; + case 28730: uiWatcherGashra = pCreature->GetGUID(); break; + case 28731: uiWatcherSilthik = pCreature->GetGUID(); break; + case 28729: uiWatcherNarjil = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch (pGo->GetEntry()) + { + case 192395: + uiKrikthirDoor = pGo->GetGUID(); + if (auiEncounter[0] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 192396: + uiAnubarakDoor[0] = pGo->GetGUID(); + break; + case 192397: + uiAnubarakDoor[1] = pGo->GetGUID(); + break; + case 192398: + uiAnubarakDoor[2] = pGo->GetGUID(); + break; + } + } + + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_KRIKTHIR_THE_GATEWATCHER: return uiKrikthir; + case DATA_HADRONOX: return uiHadronox; + case DATA_ANUBARAK: return uiAnubarak; + case DATA_WATCHER_GASHRA: return uiWatcherGashra; + case DATA_WATCHER_SILTHIK: return uiWatcherSilthik; + case DATA_WATCHER_NARJIL: return uiWatcherNarjil; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: + auiEncounter[0] = data; + if (data == DONE) + HandleGameObject(uiKrikthirDoor,true); + break; + case DATA_HADRONOX_EVENT: + auiEncounter[1] = data; + break; + case DATA_ANUBARAK_EVENT: + auiEncounter[2] = data; + if (data == IN_PROGRESS) + for (uint8 i = 0; i < 3; ++i) + HandleGameObject(uiAnubarakDoor[i], false); + else if (data == NOT_STARTED || data == DONE) + for (uint8 i = 0; i < 3; ++i) + HandleGameObject(uiAnubarakDoor[i], true); + break; + } + + if (data == DONE) + { + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: return auiEncounter[0]; + case DATA_HADRONOX_EVENT: return auiEncounter[1]; + case DATA_ANUBARAK_EVENT: return auiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "A N " << auiEncounter[0] << " " << auiEncounter[1] << " " + << auiEncounter[2]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0,data1,data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; + + if (dataHead1 == 'A' && dataHead2 == 'N') + { + auiEncounter[0] = data0; + auiEncounter[1] = data1; + auiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (auiEncounter[i] == IN_PROGRESS) + auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_azjol_nerub(Map* pMap) +{ + return new instance_azjol_nerub(pMap); +} + +void AddSC_instance_azjol_nerub() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_azjol_nerub"; + newscript->GetInstanceData = &GetInstanceData_instance_azjol_nerub; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp new file mode 100644 index 00000000000..c33ea69fa2d --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Argent Challenge Encounter. +SD%Complete: 50 % +SDComment: AI for Argent Soldiers are not implemented. AI from bosses need more improvements. +SDCategory: Trial of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" +#include "ScriptedEscortAI.h" + +enum eSpells +{ + //Eadric + SPELL_EADRIC_ACHIEVEMENT = 68197, + SPELL_HAMMER_JUSTICE = 66863, + SPELL_HAMMER_RIGHTEOUS = 66867, + SPELL_RADIANCE = 66935, + SPELL_VENGEANCE = 66865, + + //Paletress + SPELL_SMITE = 66536, + SPELL_SMITE_H = 67674, + SPELL_HOLY_FIRE = 66538, + SPELL_HOLY_FIRE_H = 67676, + SPELL_RENEW = 66537, + SPELL_RENEW_H = 67675, + SPELL_HOLY_NOVA = 66546, + SPELL_SHIELD = 66515, + SPELL_CONFESS = 66680, + SPELL_SUMMON_MEMORY = 66545, + + //Memory + SPELL_OLD_WOUNDS = 66620, + SPELL_OLD_WOUNDS_H = 67679, + SPELL_SHADOWS_PAST = 66619, + SPELL_SHADOWS_PAST_H = 67678, + SPELL_WAKING_NIGHTMARE = 66552, + SPELL_WAKING_NIGHTMARE_H = 67677 +}; + +struct boss_eadricAI : public ScriptedAI +{ + boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + pCreature->SetReactState(REACT_PASSIVE); + pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint32 uiVenganceTimer; + uint32 uiRadianceTimer; + uint32 uiHammerJusticeTimer; + uint32 uiResetTimer; + + bool bDone; + + void Reset() + { + uiVenganceTimer = 10000; + uiRadianceTimer = 16000; + uiHammerJusticeTimer = 25000; + uiResetTimer = 5000; + + bDone = false; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + damage = 0; + EnterEvadeMode(); + me->setFaction(35); + bDone = true; + } + } + + void MovementInform(uint32 MovementType, uint32 /*Data*/) + { + if (MovementType != POINT_MOTION_TYPE) + return; + + if (pInstance) + pInstance->SetData(BOSS_ARGENT_CHALLENGE_E, DONE); + + me->DisappearAndDie(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (bDone && uiResetTimer <= uiDiff) + { + me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); + bDone = false; + } else uiResetTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + if (uiHammerJusticeTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + { + DoCast(pTarget, SPELL_HAMMER_JUSTICE); + DoCast(pTarget, SPELL_HAMMER_RIGHTEOUS); + } + } + uiHammerJusticeTimer = 25000; + } else uiHammerJusticeTimer -= uiDiff; + + if (uiVenganceTimer <= uiDiff) + { + DoCast(me,SPELL_VENGEANCE); + + uiVenganceTimer = 10000; + } else uiVenganceTimer -= uiDiff; + + if (uiRadianceTimer <= uiDiff) + { + DoCastAOE(SPELL_RADIANCE); + + uiRadianceTimer = 16000; + } else uiRadianceTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_eadric(Creature* pCreature) +{ + return new boss_eadricAI(pCreature); +} + +struct boss_paletressAI : public ScriptedAI +{ + boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + MemoryGUID = 0; + pCreature->SetReactState(REACT_PASSIVE); + pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pCreature->RestoreFaction(); + } + + ScriptedInstance* pInstance; + + Creature* pMemory; + uint64 MemoryGUID; + + bool bHealth; + bool bDone; + + uint32 uiHolyFireTimer; + uint32 uiHolySmiteTimer; + uint32 uiRenewTimer; + uint32 uiResetTimer; + + void Reset() + { + me->RemoveAllAuras(); + + uiHolyFireTimer = urand(9000,12000); + uiHolySmiteTimer = urand(5000,7000); + uiRenewTimer = urand(2000,5000); + + uiResetTimer = 7000; + + bHealth = false; + bDone = false; + + if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) + if (pMemory->isAlive()) + pMemory->RemoveFromWorld(); + } + + void SetData(uint32 uiId, uint32 /*uiValue*/) + { + if (uiId == 1) + me->RemoveAura(SPELL_SHIELD); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + damage = 0; + EnterEvadeMode(); + me->setFaction(35); + bDone = true; + } + } + + void MovementInform(uint32 MovementType, uint32 Point) + { + if (MovementType != POINT_MOTION_TYPE || Point != 0) + return; + + if (pInstance) + pInstance->SetData(BOSS_ARGENT_CHALLENGE_P, DONE); + + me->DisappearAndDie(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (bDone && uiResetTimer <= uiDiff) + { + me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); + bDone = false; + } else uiResetTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + if (uiHolyFireTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_HOLY_FIRE); + } + if (me->HasAura(SPELL_SHIELD)) + uiHolyFireTimer = 13000; + else + uiHolyFireTimer = urand(9000,12000); + } else uiHolyFireTimer -= uiDiff; + + if (uiHolySmiteTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_SMITE); + } + if (me->HasAura(SPELL_SHIELD)) + uiHolySmiteTimer = 9000; + else + uiHolySmiteTimer = urand(5000,7000); + } else uiHolySmiteTimer -= uiDiff; + + if (me->HasAura(SPELL_SHIELD)) + if (uiRenewTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + uint8 uiTarget = urand(0,1); + switch(uiTarget) + { + case 0: + DoCast(me,SPELL_RENEW); + break; + case 1: + if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) + if (pMemory->isAlive()) + DoCast(pMemory, SPELL_RENEW); + break; + } + uiRenewTimer = urand(15000,17000); + } else uiRenewTimer -= uiDiff; + + + if (!bHealth && me->GetHealth()*100 / me->GetMaxHealth() <= 25) + { + me->InterruptNonMeleeSpells(true); + DoCastAOE(SPELL_HOLY_NOVA,false); + DoCast(me, SPELL_SHIELD); + DoCastAOE(SPELL_SUMMON_MEMORY,false); + DoCastAOE(SPELL_CONFESS,false); + + bHealth = true; + } + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* pSummon) + { + MemoryGUID = pSummon->GetGUID(); + } +}; + +CreatureAI* GetAI_boss_paletress(Creature* pCreature) +{ + return new boss_paletressAI(pCreature); +} + +struct npc_memoryAI : public ScriptedAI +{ + npc_memoryAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiOldWoundsTimer; + uint32 uiShadowPastTimer; + uint32 uiWakingNightmare; + + void Reset() + { + uiOldWoundsTimer = 12000; + uiShadowPastTimer = 5000; + uiWakingNightmare = 7000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiOldWoundsTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, SPELL_OLD_WOUNDS); + } + uiOldWoundsTimer = 12000; + }else uiOldWoundsTimer -= uiDiff; + + if (uiWakingNightmare <= uiDiff) + { + DoCast(me, SPELL_WAKING_NIGHTMARE); + uiWakingNightmare = 7000; + }else uiWakingNightmare -= uiDiff; + + if (uiShadowPastTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_SHADOWS_PAST); + } + uiShadowPastTimer = 5000; + }else uiShadowPastTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (me->isSummon()) + { + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + { + if (pSummoner && pSummoner->isAlive()) + CAST_CRE(pSummoner)->AI()->SetData(1,0); + } + } + } +}; + +CreatureAI* GetAI_npc_memory(Creature* pCreature) +{ + return new npc_memoryAI(pCreature); +} + +// THIS AI NEEDS MORE IMPROVEMENTS +struct npc_argent_soldierAI : public npc_escortAI +{ + npc_argent_soldierAI(Creature* pCreature) : npc_escortAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + me->SetReactState(REACT_DEFENSIVE); + SetDespawnAtEnd(false); + uiWaypoint = 0; + } + + ScriptedInstance* pInstance; + + uint8 uiWaypoint; + + void WaypointReached(uint32 uiPoint) + { + if (uiPoint == 0) + { + switch(uiWaypoint) + { + case 0: + me->SetOrientation(5.81); + break; + case 1: + me->SetOrientation(4.60); + break; + case 2: + me->SetOrientation(2.79); + break; + } + + me->SendMovementFlagUpdate(); + } + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch(me->GetEntry()) + { + case NPC_ARGENT_LIGHWIELDER: + switch(uiType) + { + case 0: + AddWaypoint(0,712.14,628.42,411.88); + break; + case 1: + AddWaypoint(0,742.44,650.29,411.79); + break; + case 2: + AddWaypoint(0,783.33,615.29,411.84); + break; + } + break; + case NPC_ARGENT_MONK: + switch(uiType) + { + case 0: + AddWaypoint(0,713.12,632.97,411.90); + break; + case 1: + AddWaypoint(0,746.73,650.24,411.56); + break; + case 2: + AddWaypoint(0,781.32,610.54,411.82); + break; + } + break; + case NPC_PRIESTESS: + switch(uiType) + { + case 0: + AddWaypoint(0,715.06,637.07,411.91); + break; + case 1: + AddWaypoint(0,750.72,650.20,411.77); + break; + case 2: + AddWaypoint(0,779.77,607.03,411.81); + break; + } + break; + } + + Start(false,true,0); + uiWaypoint = uiType; + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(DATA_ARGENT_SOLDIER_DEFEATED,pInstance->GetData(DATA_ARGENT_SOLDIER_DEFEATED) + 1); + } +}; + +CreatureAI* GetAI_npc_argent_soldier(Creature* pCreature) +{ + return new npc_argent_soldierAI(pCreature); +} + +void AddSC_boss_argent_challenge() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_eadric"; + NewScript->GetAI = &GetAI_boss_eadric; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_paletress"; + NewScript->GetAI = &GetAI_boss_paletress; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_memory"; + NewScript->GetAI = &GetAI_npc_memory; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_argent_soldier"; + NewScript->GetAI = &GetAI_npc_argent_soldier; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp new file mode 100644 index 00000000000..e1f4586ca6c --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Black Knight +SD%Complete: 80% +SDComment: missing yells. not sure about timers. +SDCategory: Trial of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "trial_of_the_champion.h" + +enum eSpells +{ + //phase 1 + SPELL_PLAGUE_STRIKE = 67884, + SPELL_PLAGUE_STRIKE_2 = 67724, + SPELL_ICY_TOUCH_H = 67881, + SPELL_ICY_TOUCH = 67718, + SPELL_DEATH_RESPITE = 67745, + SPELL_DEATH_RESPITE_2 = 68306, + SPELL_DEATH_RESPITE_3 = 66798, + SPELL_OBLITERATE_H = 67883, + SPELL_OBLITERATE = 67725, + //in this phase should rise herald (the spell is missing) + + //phase 2 - During this phase, the Black Knight will use the same abilities as in phase 1, except for Death's Respite + SPELL_ARMY_DEAD = 67761, + SPELL_DESECRATION = 67778, + SPELL_DESECRATION_2 = 67778, + SPELL_GHOUL_EXPLODE = 67751, + + //phase 3 + SPELL_DEATH_BITE_H = 67875, + SPELL_DEATH_BITE = 67808, + SPELL_MARKED_DEATH = 67882, + SPELL_MARKED_DEATH_2 = 67823, + + SPELL_BLACK_KNIGHT_RES = 67693, + + SPELL_LEAP = 67749, + SPELL_LEAP_H = 67880 +}; + +enum eModels +{ + MODEL_SKELETON = 29846, + MODEL_GHOST = 21300 +}; + +enum ePhases +{ + PHASE_UNDEAD = 1, + PHASE_SKELETON = 2, + PHASE_GHOST = 3 +}; + +struct boss_black_knightAI : public ScriptedAI +{ + boss_black_knightAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + std::list SummonList; + + bool bEventInProgress; + bool bEvent; + bool bSummonArmy; + bool bDeathArmyDone; + + uint8 uiPhase; + + uint32 uiPlagueStrikeTimer; + uint32 uiIcyTouchTimer; + uint32 uiDeathRespiteTimer; + uint32 uiObliterateTimer; + uint32 uiDesecration; + uint32 uiResurrectTimer; + uint32 uiDeathArmyCheckTimer; + uint32 uiGhoulExplodeTimer; + uint32 uiDeathBiteTimer; + uint32 uiMarkedDeathTimer; + + void Reset() + { + RemoveSummons(); + me->SetDisplayId(me->GetNativeDisplayId()); + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + + bEventInProgress = false; + bEvent = false; + bSummonArmy = false; + bDeathArmyDone = false; + + uiPhase = PHASE_UNDEAD; + + uiIcyTouchTimer = urand(5000,9000); + uiPlagueStrikeTimer = urand(10000,13000); + uiDeathRespiteTimer = urand(15000,16000); + uiObliterateTimer = urand(17000,19000); + uiDesecration = urand(15000,16000); + uiDeathArmyCheckTimer = 7000; + uiResurrectTimer = 4000; + uiGhoulExplodeTimer = 8000; + uiDeathBiteTimer = urand (2000,4000); + uiMarkedDeathTimer = urand (5000,7000); + } + + void RemoveSummons() + { + if (SummonList.empty()) + return; + + for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + if (pTemp) + pTemp->DisappearAndDie(); + } + SummonList.clear(); + } + + void JustSummoned(Creature* pSummon) + { + SummonList.push_back(pSummon->GetGUID()); + pSummon->AI()->AttackStart(me->getVictim()); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (bEventInProgress) + if (uiResurrectTimer <= uiDiff) + { + me->SetHealth(me->GetMaxHealth()); + DoCast(me,SPELL_BLACK_KNIGHT_RES,true); + uiPhase++; + uiResurrectTimer = 4000; + bEventInProgress = false; + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + } else uiResurrectTimer -= uiDiff; + + switch(uiPhase) + { + case PHASE_UNDEAD: + case PHASE_SKELETON: + { + if (uiIcyTouchTimer <= uiDiff) + { + DoCastVictim(SPELL_ICY_TOUCH); + uiIcyTouchTimer = urand(5000,7000); + } else uiIcyTouchTimer -= uiDiff; + if (uiPlagueStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_ICY_TOUCH); + uiPlagueStrikeTimer = urand(12000,15000); + } else uiPlagueStrikeTimer -= uiDiff; + if (uiObliterateTimer <= uiDiff) + { + DoCastVictim(SPELL_OBLITERATE); + uiObliterateTimer = urand(17000,19000); + } else uiObliterateTimer -= uiDiff; + switch(uiPhase) + { + case PHASE_UNDEAD: + { + if (uiDeathRespiteTimer <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_DEATH_RESPITE); + } + uiDeathRespiteTimer = urand(15000,16000); + } else uiDeathRespiteTimer -= uiDiff; + break; + } + case PHASE_SKELETON: + { + if (!bSummonArmy) + { + bSummonArmy = true; + me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + DoCast(me, SPELL_ARMY_DEAD); + } + if (!bDeathArmyDone) + if (uiDeathArmyCheckTimer <= uiDiff) + { + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + uiDeathArmyCheckTimer = 0; + bDeathArmyDone = true; + } else uiDeathArmyCheckTimer -= uiDiff; + if (uiDesecration <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_DESECRATION); + } + uiDesecration = urand(15000,16000); + } else uiDesecration -= uiDiff; + if (uiGhoulExplodeTimer <= uiDiff) + { + DoCast(me, SPELL_GHOUL_EXPLODE); + uiGhoulExplodeTimer = 8000; + } else uiGhoulExplodeTimer -= uiDiff; + break; + } + break; + } + break; + } + case PHASE_GHOST: + { + if (uiDeathBiteTimer <= uiDiff) + { + DoCastAOE(SPELL_DEATH_BITE); + uiDeathBiteTimer = urand (2000, 4000); + } else uiDeathBiteTimer -= uiDiff; + if (uiMarkedDeathTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_MARKED_DEATH); + } + uiMarkedDeathTimer = urand (5000, 7000); + } else uiMarkedDeathTimer -= uiDiff; + break; + } + } + + if (!me->hasUnitState(UNIT_STAT_ROOT) && !me->GetHealth()*100 / me->GetMaxHealth() <= 0) + DoMeleeAttackIfReady(); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) + { + if (uiDamage > me->GetHealth() && uiPhase <= PHASE_SKELETON) + { + uiDamage = 0; + me->SetHealth(0); + me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + RemoveSummons(); + switch(uiPhase) + { + case PHASE_UNDEAD: + me->SetDisplayId(MODEL_SKELETON); + break; + case PHASE_SKELETON: + me->SetDisplayId(MODEL_GHOST); + break; + } + bEventInProgress = true; + } + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_BLACK_KNIGHT,DONE); + } +}; + +CreatureAI* GetAI_boss_black_knight(Creature *pCreature) +{ + return new boss_black_knightAI (pCreature); +} + +struct npc_risen_ghoulAI : public ScriptedAI +{ + npc_risen_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiAttackTimer; + + void Reset() + { + uiAttackTimer = 3500; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiAttackTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, (SPELL_LEAP)); + } + uiAttackTimer = 3500; + } else uiAttackTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_risen_ghoul(Creature* pCreature) +{ + return new npc_risen_ghoulAI(pCreature); +} + +struct npc_black_knight_skeletal_gryphonAI : public npc_escortAI +{ + npc_black_knight_skeletal_gryphonAI(Creature* pCreature) : npc_escortAI(pCreature) + { + Start(false,true,0,NULL); + } + + void WaypointReached(uint32 /*i*/) + { + + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + } + +}; + +CreatureAI* GetAI_npc_black_knight_skeletal_gryphon(Creature* pCreature) +{ + return new npc_black_knight_skeletal_gryphonAI(pCreature); +} + +void AddSC_boss_black_knight() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_black_knight"; + NewScript->GetAI = &GetAI_boss_black_knight; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_risen_ghoul"; + NewScript->GetAI = &GetAI_npc_risen_ghoul; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_black_knight_skeletal_gryphon"; + NewScript->GetAI = &GetAI_npc_black_knight_skeletal_gryphon; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp new file mode 100644 index 00000000000..4bf8143a210 --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp @@ -0,0 +1,993 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_grand_champions +SD%Complete: 50 % +SDComment: Is missing the ai to make the npcs look for a new mount and use it. +SDCategory: Trial Of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "Vehicle.h" +#include "trial_of_the_champion.h" + +enum eSpells +{ + //Vehicle + SPELL_CHARGE = 63010, + SPELL_SHIELD_BREAKER = 68504, + SPELL_SHIELD = 66482, + + // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior + SPELL_MORTAL_STRIKE = 68783, + SPELL_MORTAL_STRIKE_H = 68784, + SPELL_BLADESTORM = 63784, + SPELL_INTERCEPT = 67540, + SPELL_ROLLING_THROW = 47115, //not implemented in the AI yet... + + // Ambrose Boltspark && Eressea Dawnsinger || Mage + SPELL_FIREBALL = 66042, + SPELL_FIREBALL_H = 68310, + SPELL_BLAST_WAVE = 66044, + SPELL_BLAST_WAVE_H = 68312, + SPELL_HASTE = 66045, + SPELL_POLYMORPH = 66043, + SPELL_POLYMORPH_H = 68311, + + // Colosos && Runok Wildmane || Shaman + SPELL_CHAIN_LIGHTNING = 67529, + SPELL_CHAIN_LIGHTNING_H = 68319, + SPELL_EARTH_SHIELD = 67530, + SPELL_HEALING_WAVE = 67528, + SPELL_HEALING_WAVE_H = 68318, + SPELL_HEX_OF_MENDING = 67534, + + // Jaelyne Evensong && Zul'tore || Hunter + SPELL_DISENGAGE = 68340, //not implemented in the AI yet... + SPELL_LIGHTNING_ARROWS = 66083, + SPELL_MULTI_SHOT = 66081, + SPELL_SHOOT = 65868, + SPELL_SHOOT_H = 67988, + + // Lana Stouthammer Evensong && Deathstalker Visceri || Rouge + SPELL_EVISCERATE = 67709, + SPELL_EVISCERATE_H = 68317, + SPELL_FAN_OF_KNIVES = 67706, + SPELL_POISON_BOTTLE = 67701 +}; + +enum eSeat +{ + SEAT_ID_0 = 0 +}; + +struct Point +{ + float x,y,z; +}; + +const Point MovementPoint[] = +{ + {746.84,623.15,411.41}, + {747.96,620.29,411.09}, + {750.23,618.35,411.09} +}; + +void AggroAllPlayers(Creature* pTemp) +{ + Map::PlayerList const &PlList = pTemp->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(pTemp); + pTemp->AddThreat(pPlayer, 0.0f); + } + } + } +} + +bool GrandChampionsOutVehicle(Creature* me) +{ + ScriptedInstance* pInstance = me->GetInstanceData(); + + if (!pInstance) + return false; + + Creature* pGrandChampion1 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_1)); + Creature* pGrandChampion2 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_2)); + Creature* pGrandChampion3 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_3)); + + if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) + { + if (!pGrandChampion1->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && + !pGrandChampion2->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && + !pGrandChampion3->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return true; + } + + return false; +} + +/* +* Generic AI for vehicles used by npcs in ToC, it needs more improvements. * +* Script Complete: 25%. * +*/ + +struct generic_vehicleAI_toc5AI : public npc_escortAI +{ + generic_vehicleAI_toc5AI(Creature* pCreature) : npc_escortAI(pCreature) + { + SetDespawnAtEnd(false); + uiWaypointPath = 0; + + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiChargeTimer; + uint32 uiShieldBreakerTimer; + uint32 uiBuffTimer; + + uint32 uiWaypointPath; + + void Reset() + { + uiChargeTimer = 5000; + uiShieldBreakerTimer = 8000; + uiBuffTimer = urand(30000,60000); + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch(uiType) + { + case 1: + AddWaypoint(0,747.36,634.07,411.572); + AddWaypoint(1,780.43,607.15,411.82); + AddWaypoint(2,785.99,599.41,411.92); + AddWaypoint(3,778.44,601.64,411.79); + uiWaypointPath = 1; + break; + case 2: + AddWaypoint(0,747.35,634.07,411.57); + AddWaypoint(1,768.72,581.01,411.92); + AddWaypoint(2,763.55,590.52,411.71); + uiWaypointPath = 2; + break; + case 3: + AddWaypoint(0,747.35,634.07,411.57); + AddWaypoint(1,784.02,645.33,412.39); + AddWaypoint(2,775.67,641.91,411.91); + uiWaypointPath = 3; + break; + } + + if (uiType <= 3) + Start(false,true,0,NULL); + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 2: + if (pInstance && uiWaypointPath == 3 || uiWaypointPath == 2) + pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); + break; + case 3: + if (pInstance) + pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); + break; + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoCastSpellShield(); + } + + void DoCastSpellShield() + { + for (uint8 i = 0; i < 3; ++i) + DoCast(me,SPELL_SHIELD,true); + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + if (uiBuffTimer <= uiDiff) + { + if (!me->HasAura(SPELL_SHIELD)) + DoCastSpellShield(); + + uiBuffTimer = urand(30000,45000); + }else uiBuffTimer -= uiDiff; + + if (uiChargeTimer <= uiDiff) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) + { + DoResetThreat(); + me->AddThreat(pPlayer,1.0f); + DoCast(pPlayer, SPELL_CHARGE); + break; + } + } + } + uiChargeTimer = 5000; + }else uiChargeTimer -= uiDiff; + + //dosen't work at all + if (uiShieldBreakerTimer <= uiDiff) + { + Vehicle *pVehicle = me->GetVehicleKit(); + if (!pVehicle) + return; + + if (Unit* pPassenger = pVehicle->GetPassenger(SEAT_ID_0)) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,10.0f,30.0f,false)) + { + pPassenger->CastSpell(pPlayer,SPELL_SHIELD_BREAKER,true); + break; + } + } + } + } + uiShieldBreakerTimer = 7000; + }else uiShieldBreakerTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_generic_vehicleAI_toc5(Creature* pCreature) +{ + return new generic_vehicleAI_toc5AI(pCreature); +} + +// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior +struct boss_warrior_toc5AI : public ScriptedAI +{ + boss_warrior_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiBladeStormTimer; + uint32 uiInterceptTimer; + uint32 uiMortalStrikeTimer; + uint32 uiAttackTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiBladeStormTimer = urand(15000,20000); + uiInterceptTimer = 7000; + uiMortalStrikeTimer = urand(8000,12000); + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiInterceptTimer <= uiDiff) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) + { + DoResetThreat(); + me->AddThreat(pPlayer,5.0f); + DoCast(pPlayer,SPELL_INTERCEPT); + break; + } + } + } + uiInterceptTimer = 7000; + } else uiInterceptTimer -= uiDiff; + + if (uiBladeStormTimer <= uiDiff) + { + DoCastVictim(SPELL_BLADESTORM); + uiBladeStormTimer = urand(15000,20000); + } else uiBladeStormTimer -= uiDiff; + + if (uiMortalStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_MORTAL_STRIKE); + uiMortalStrikeTimer = urand(8000,12000); + } else uiMortalStrikeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_warrior_toc5(Creature* pCreature) +{ + return new boss_warrior_toc5AI(pCreature); +} + +// Ambrose Boltspark && Eressea Dawnsinger || Mage +struct boss_mage_toc5AI : public ScriptedAI +{ + boss_mage_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiFireBallTimer; + uint32 uiBlastWaveTimer; + uint32 uiHasteTimer; + uint32 uiPolymorphTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiFireBallTimer = 5000; + uiPolymorphTimer = 8000; + uiBlastWaveTimer = 12000; + uiHasteTimer = 22000; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (uiFireBallTimer <= uiDiff) + { + if (me->getVictim()) + DoCastVictim(SPELL_FIREBALL); + uiFireBallTimer = 5000; + } else uiFireBallTimer -= uiDiff; + + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiFireBallTimer <= uiDiff) + { + DoCastVictim(SPELL_FIREBALL); + uiFireBallTimer = 5000; + } else uiFireBallTimer -= uiDiff; + + if (uiPolymorphTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_POLYMORPH); + uiPolymorphTimer = 8000; + } else uiPolymorphTimer -= uiDiff; + + if (uiBlastWaveTimer <= uiDiff) + { + DoCastAOE(SPELL_BLAST_WAVE,false); + uiBlastWaveTimer = 13000; + } else uiBlastWaveTimer -= uiDiff; + + if (uiHasteTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + + DoCast(me,SPELL_HASTE); + uiHasteTimer = 22000; + } else uiHasteTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_mage_toc5(Creature* pCreature) +{ + return new boss_mage_toc5AI(pCreature); +} + +// Colosos && Runok Wildmane || Shaman +struct boss_shaman_toc5AI : public ScriptedAI +{ + boss_shaman_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiChainLightningTimer; + uint32 uiEartShieldTimer; + uint32 uiHealingWaveTimer; + uint32 uiHexMendingTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiChainLightningTimer = 16000; + uiHealingWaveTimer = 12000; + uiEartShieldTimer = urand(30000,35000); + uiHexMendingTimer = urand(20000,25000); + } + + void EnterCombat(Unit* pWho) + { + DoCast(me,SPELL_EARTH_SHIELD); + DoCast(pWho,SPELL_HEX_OF_MENDING); + }; + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiChainLightningTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_CHAIN_LIGHTNING); + + uiChainLightningTimer = 16000; + } else uiChainLightningTimer -= uiDiff; + + if (uiHealingWaveTimer <= uiDiff) + { + bool bChance = urand(0,1); + + if (!bChance) + { + if (Unit* pFriend = DoSelectLowestHpFriendly(40)) + DoCast(pFriend,SPELL_HEALING_WAVE); + } else + DoCast(me,SPELL_HEALING_WAVE); + + uiHealingWaveTimer = 12000; + } else uiHealingWaveTimer -= uiDiff; + + if (uiEartShieldTimer <= uiDiff) + { + DoCast(me,SPELL_EARTH_SHIELD); + + uiEartShieldTimer = urand(30000,35000); + } else uiEartShieldTimer -= uiDiff; + + if (uiHexMendingTimer <= uiDiff) + { + DoCastVictim(SPELL_HEX_OF_MENDING,true); + + uiHexMendingTimer = urand(20000,25000); + } else uiHexMendingTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_shaman_toc5(Creature* pCreature) +{ + return new boss_shaman_toc5AI(pCreature); +} + +// Jaelyne Evensong && Zul'tore || Hunter +struct boss_hunter_toc5AI : public ScriptedAI +{ + boss_hunter_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiShootTimer; + uint32 uiMultiShotTimer; + uint32 uiLightningArrowsTimer; + + uint64 uiTargetGUID; + + bool bShoot; + bool bDone; + bool bHome; + + void Reset() + { + uiShootTimer = 12000; + uiMultiShotTimer = 0; + uiLightningArrowsTimer = 7000; + + uiTargetGUID = 0; + + bShoot = false; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiLightningArrowsTimer <= uiDiff) + { + DoCastAOE(SPELL_LIGHTNING_ARROWS,false); + uiLightningArrowsTimer = 7000; + } else uiLightningArrowsTimer -= uiDiff; + + if (uiShootTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_FARTHEST,0,30.0f)) + { + uiTargetGUID = pTarget->GetGUID(); + DoCast(pTarget, SPELL_SHOOT); + } + uiShootTimer = 12000; + uiMultiShotTimer = 3000; + bShoot = true; + } else uiShootTimer -= uiDiff; + + if (bShoot && uiMultiShotTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + Unit* pTarget = Unit::GetUnit(*me, uiTargetGUID); + + if (pTarget && me->IsInRange(pTarget,5.0f,30.0f,false)) + { + DoCast(pTarget,SPELL_MULTI_SHOT); + } else + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,5.0f,30.0f,false)) + { + DoCast(pTarget,SPELL_MULTI_SHOT); + break; + } + } + } + } + bShoot = false; + } else uiMultiShotTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_hunter_toc5(Creature* pCreature) +{ + return new boss_hunter_toc5AI(pCreature); +} + +// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge +struct boss_rouge_toc5AI : public ScriptedAI +{ + boss_rouge_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + uint32 uiEviscerateTimer; + uint32 uiFanKivesTimer; + uint32 uiPosionBottleTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiEviscerateTimer = 8000; + uiFanKivesTimer = 14000; + uiPosionBottleTimer = 19000; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + } else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiEviscerateTimer <= uiDiff) + { + DoCast(me->getVictim(),SPELL_EVISCERATE); + uiEviscerateTimer = 8000; + } else uiEviscerateTimer -= uiDiff; + + if (uiFanKivesTimer <= uiDiff) + { + DoCastAOE(SPELL_FAN_OF_KNIVES,false); + uiFanKivesTimer = 14000; + } else uiFanKivesTimer -= uiDiff; + + if (uiPosionBottleTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_POISON_BOTTLE); + uiPosionBottleTimer = 19000; + } else uiPosionBottleTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_rouge_toc5(Creature* pCreature) +{ + return new boss_rouge_toc5AI(pCreature); +} + +void AddSC_boss_grand_champions() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "generic_vehicleAI_toc5"; + NewScript->GetAI = &GetAI_generic_vehicleAI_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_warrior_toc5"; + NewScript->GetAI = &GetAI_boss_warrior_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_mage_toc5"; + NewScript->GetAI = &GetAI_boss_mage_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_shaman_toc5"; + NewScript->GetAI = &GetAI_boss_shaman_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_hunter_toc5"; + NewScript->GetAI = &GetAI_boss_hunter_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_rouge_toc5"; + NewScript->GetAI = &GetAI_boss_rouge_toc5; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp new file mode 100644 index 00000000000..04b671ec11c --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* ScriptData +SDName: Instance Trial of the Champion +SDComment: +SDCategory: Trial Of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" + +#define MAX_ENCOUNTER 4 + +struct instance_trial_of_the_champion : public ScriptedInstance +{ + instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint8 uiMovementDone; + uint8 uiGrandChampionsDeaths; + uint8 uiArgentSoldierDeaths; + + uint64 uiAnnouncerGUID; + uint64 uiMainGateGUID; + uint64 uiGrandChampionVehicle1GUID; + uint64 uiGrandChampionVehicle2GUID; + uint64 uiGrandChampionVehicle3GUID; + uint64 uiGrandChampion1GUID; + uint64 uiGrandChampion2GUID; + uint64 uiGrandChampion3GUID; + uint64 uiChampionLootGUID; + uint64 uiArgentChampionGUID; + + std::list VehicleList; + + std::string str_data; + + bool bDone; + + void Initialize() + { + uiMovementDone = 0; + uiGrandChampionsDeaths = 0; + uiArgentSoldierDeaths = 0; + + uiAnnouncerGUID = 0; + uiMainGateGUID = 0; + uiGrandChampionVehicle1GUID = 0; + uiGrandChampionVehicle2GUID = 0; + uiGrandChampionVehicle3GUID = 0; + uiGrandChampion1GUID = 0; + uiGrandChampion2GUID = 0; + uiGrandChampion3GUID = 0; + uiChampionLootGUID = 0; + uiArgentChampionGUID = 0; + + bDone = false; + + VehicleList.clear(); + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + } + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + uint32 TeamInInstance = 0; + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + TeamInInstance = pPlayer->GetTeam(); + } + + switch(pCreature->GetEntry()) + { + // Champions + case VEHICLE_MOKRA_SKILLCRUSHER_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT, ALLIANCE); + break; + case VEHICLE_ERESSEA_DAWNSINGER_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_AMBROSE_BOLTSPARK_MOUNT, ALLIANCE); + break; + case VEHICLE_RUNOK_WILDMANE_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_COLOSOS_MOUNT, ALLIANCE); + break; + case VEHICLE_ZUL_TORE_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_EVENSONG_MOUNT, ALLIANCE); + break; + case VEHICLE_DEATHSTALKER_VESCERI_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_LANA_STOUTHAMMER_MOUNT, ALLIANCE); + break; + // Coliseum Announcer || Just NPC_JAEREN must be spawned. + case NPC_JAEREN: + uiAnnouncerGUID = pCreature->GetGUID(); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_ARELAS,ALLIANCE); + break; + case VEHICLE_ARGENT_WARHORSE: + case VEHICLE_ARGENT_BATTLEWORG: + VehicleList.push_back(pCreature->GetGUID()); + break; + case NPC_EADRIC: + case NPC_PALETRESS: + uiArgentChampionGUID = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGO, bool /*bAdd*/) + { + switch(pGO->GetEntry()) + { + case GO_MAIN_GATE: + uiMainGateGUID = pGO->GetGUID(); + break; + case GO_CHAMPIONS_LOOT: + case GO_CHAMPIONS_LOOT_H: + uiChampionLootGUID = pGO->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case DATA_MOVEMENT_DONE: + uiMovementDone = uiData; + if (uiMovementDone == 3) + { + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + pAnnouncer->AI()->SetData(DATA_IN_POSITION,0); + } + break; + case BOSS_GRAND_CHAMPIONS: + m_auiEncounter[0] = uiData; + if (uiData == IN_PROGRESS) + { + for (std::list::const_iterator itr = VehicleList.begin(); itr != VehicleList.end(); ++itr) + if (Creature* pSummon = instance->GetCreature(*itr)) + pSummon->RemoveFromWorld(); + }else if (uiData == DONE) + { + ++uiGrandChampionsDeaths; + if (uiGrandChampionsDeaths == 3) + { + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + } + } + break; + case DATA_ARGENT_SOLDIER_DEFEATED: + uiArgentSoldierDeaths = uiData; + if (uiArgentSoldierDeaths == 9) + { + if (Creature* pBoss = instance->GetCreature(uiArgentChampionGUID)) + { + pBoss->GetMotionMaster()->MovePoint(0,746.88,618.74,411.06); + pBoss->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pBoss->SetReactState(REACT_AGGRESSIVE); + } + } + break; + case BOSS_ARGENT_CHALLENGE_E: + m_auiEncounter[1] = uiData; + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + break; + case BOSS_ARGENT_CHALLENGE_P: + m_auiEncounter[2] = uiData; + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + break; + } + + if (uiData == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 uiData) + { + switch(uiData) + { + case BOSS_GRAND_CHAMPIONS: return m_auiEncounter[0]; + case BOSS_ARGENT_CHALLENGE_E: return m_auiEncounter[1]; + case BOSS_ARGENT_CHALLENGE_P: return m_auiEncounter[2]; + case BOSS_BLACK_KNIGHT: return m_auiEncounter[3]; + + case DATA_MOVEMENT_DONE: return uiMovementDone; + case DATA_ARGENT_SOLDIER_DEFEATED: return uiArgentSoldierDeaths; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_ANNOUNCER: return uiAnnouncerGUID; + case DATA_MAIN_GATE: return uiMainGateGUID; + + case DATA_GRAND_CHAMPION_1: return uiGrandChampion1GUID; + case DATA_GRAND_CHAMPION_2: return uiGrandChampion2GUID; + case DATA_GRAND_CHAMPION_3: return uiGrandChampion3GUID; + } + + return 0; + } + + void SetData64(uint32 uiType, uint64 uiData) + { + switch(uiType) + { + case DATA_GRAND_CHAMPION_1: + uiGrandChampion1GUID = uiData; + break; + case DATA_GRAND_CHAMPION_2: + uiGrandChampion2GUID = uiData; + break; + case DATA_GRAND_CHAMPION_3: + uiGrandChampion3GUID = uiData; + break; + } + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + saveStream << "T C " << m_auiEncounter[0] + << " " << m_auiEncounter[1] + << " " << m_auiEncounter[2] + << " " << m_auiEncounter[3] + << " " << uiGrandChampionsDeaths + << " " << uiMovementDone; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + + if (dataHead1 == 'T' && dataHead2 == 'C') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + uiGrandChampionsDeaths = data4; + uiMovementDone = data5; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_trial_of_the_champion(Map* pMap) +{ + return new instance_trial_of_the_champion(pMap); +} + +void AddSC_instance_trial_of_the_champion() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_trial_of_the_champion"; + newscript->GetInstanceData = &GetInstanceData_instance_trial_of_the_champion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp new file mode 100644 index 00000000000..090b64b96cc --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Trial Of the Champion +SD%Complete: +SDComment: +SDCategory: trial_of_the_champion +EndScriptData */ + +/* ContentData +npc_announcer_toc5 +EndContentData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" +#include "Vehicle.h" + +#define GOSSIP_START_EVENT1 "I'm ready to start challenge." +#define GOSSIP_START_EVENT2 "I'm ready for the next challenge." + +#define ORIENTATION 4.714 + +/*###### +## npc_announcer_toc5 +######*/ + +const Position SpawnPosition = {746.261,657.401,411.681,4.65}; + +struct npc_announcer_toc5AI : public ScriptedAI +{ + npc_announcer_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + uiSummonTimes = 0; + uiPosition = 0; + uiLesserChampions = 0; + + uiFirstBoss = 0; + uiSecondBoss = 0; + uiThirdBoss = 0; + + uiArgentChampion = 0; + + uiPhase = 0; + uiTimer = 0; + + uiVehicle1GUID = 0; + uiVehicle2GUID = 0; + uiVehicle3GUID = 0; + + Champion1List.clear(); + Champion2List.clear(); + Champion3List.clear(); + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + SetGrandChampionsForEncounter(); + SetArgentChampion(); + } + + ScriptedInstance* pInstance; + + uint8 uiSummonTimes; + uint8 uiPosition; + uint8 uiLesserChampions; + + uint32 uiArgentChampion; + + uint32 uiFirstBoss; + uint32 uiSecondBoss; + uint32 uiThirdBoss; + + uint32 uiPhase; + uint32 uiTimer; + + uint64 uiVehicle1GUID; + uint64 uiVehicle2GUID; + uint64 uiVehicle3GUID; + + uint64 uiGrandChampionBoss1; + + std::list Champion1List; + std::list Champion2List; + std::list Champion3List; + + void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) + { + uiTimer = uiTimerStep; + if (bNextStep) + ++uiPhase; + else + uiPhase = uiPhaseStep; + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch (uiType) + { + case DATA_START: + DoSummonGrandChampion(uiFirstBoss); + NextStep(10000,false,1); + break; + case DATA_IN_POSITION: //movement done. + me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); + if (GameObject* pGO = GameObject::GetGameObject(*me, pInstance->GetData64(DATA_MAIN_GATE))) + pInstance->HandleGameObject(pGO->GetGUID(),false); + NextStep(10000,false,3); + break; + case DATA_LESSER_CHAMPIONS_DEFEATED: + { + ++uiLesserChampions; + std::list TempList; + if (uiLesserChampions == 3 || uiLesserChampions == 6) + { + switch(uiLesserChampions) + { + case 3: + TempList = Champion2List; + break; + case 6: + TempList = Champion3List; + break; + } + + for (std::list::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr) + if (Creature* pSummon = Unit::GetCreature(*me, *itr)) + AggroAllPlayers(pSummon); + }else if (uiLesserChampions == 9) + StartGrandChampionsAttack(); + + break; + } + } + } + + void StartGrandChampionsAttack() + { + Creature* pGrandChampion1 = Unit::GetCreature(*me, uiVehicle1GUID); + Creature* pGrandChampion2 = Unit::GetCreature(*me, uiVehicle2GUID); + Creature* pGrandChampion3 = Unit::GetCreature(*me, uiVehicle3GUID); + + if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) + { + AggroAllPlayers(pGrandChampion1); + AggroAllPlayers(pGrandChampion2); + AggroAllPlayers(pGrandChampion3); + } + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (uiPointId == 1) + { + me->SetOrientation(ORIENTATION); + me->SendMovementFlagUpdate(); + } + } + + void DoSummonGrandChampion(uint32 uiBoss) + { + ++uiSummonTimes; + uint32 VEHICLE_TO_SUMMON1 = 0; + uint32 VEHICLE_TO_SUMMON2 = 0; + switch(uiBoss) + { + case 0: + VEHICLE_TO_SUMMON1 = VEHICLE_MOKRA_SKILLCRUSHER_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_ORGRIMMAR_WOLF; + break; + case 1: + VEHICLE_TO_SUMMON1 = VEHICLE_ERESSEA_DAWNSINGER_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_SILVERMOON_HAWKSTRIDER; + break; + case 2: + VEHICLE_TO_SUMMON1 = VEHICLE_RUNOK_WILDMANE_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_THUNDER_BLUFF_KODO; + break; + case 3: + VEHICLE_TO_SUMMON1 = VEHICLE_ZUL_TORE_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_DARKSPEAR_RAPTOR; + break; + case 4: + VEHICLE_TO_SUMMON1 = VEHICLE_DEATHSTALKER_VESCERI_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_FORSAKE_WARHORSE; + break; + default: + return; + } + + if (Creature* pBoss = me->SummonCreature(VEHICLE_TO_SUMMON1,SpawnPosition)) + { + switch(uiSummonTimes) + { + case 1: + { + uiVehicle1GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss1 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle1GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss1 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_1,uiVehicle1GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_1,uiGrandChampionBoss1); + } + pBoss->AI()->SetData(1,0); + break; + } + case 2: + { + uiVehicle2GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss2 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle2GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss2 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_2,uiVehicle2GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_2,uiGrandChampionBoss2); + } + pBoss->AI()->SetData(2,0); + break; + } + case 3: + { + uiVehicle3GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss3 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle3GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss3 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_3,uiVehicle3GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_3,uiGrandChampionBoss3); + } + pBoss->AI()->SetData(3,0); + break; + } + default: + return; + } + + for (uint8 i = 0; i < 3; ++i) + { + if (Creature* pAdd = me->SummonCreature(VEHICLE_TO_SUMMON2,SpawnPosition,TEMPSUMMON_CORPSE_DESPAWN)) + { + switch(uiSummonTimes) + { + case 1: + Champion1List.push_back(pAdd->GetGUID()); + break; + case 2: + Champion2List.push_back(pAdd->GetGUID()); + break; + case 3: + Champion3List.push_back(pAdd->GetGUID()); + break; + } + + switch(i) + { + case 0: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI); + break; + case 1: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2); + break; + case 2: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2 + M_PI); + break; + } + } + + } + } + } + + void DoStartArgentChampionEncounter() + { + me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); + + if (Creature* pBoss = me->SummonCreature(uiArgentChampion,SpawnPosition)) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_LIGHWIELDER,SpawnPosition)) + pTrash->AI()->SetData(i,0); + if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_MONK,SpawnPosition)) + pTrash->AI()->SetData(i,0); + if (Creature* pTrash = me->SummonCreature(NPC_PRIESTESS,SpawnPosition)) + pTrash->AI()->SetData(i,0); + } + } + } + + void SetGrandChampionsForEncounter() + { + uiFirstBoss = urand(0,4); + + while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss) + { + uiSecondBoss = urand(0,4); + uiThirdBoss = urand(0,4); + } + } + + void SetArgentChampion() + { + uint8 uiTempBoss = urand(0,1); + + switch(uiTempBoss) + { + case 0: + uiArgentChampion = NPC_EADRIC; + break; + case 1: + uiArgentChampion = NPC_PALETRESS; + break; + } + } + + void StartEncounter() + { + if (!pInstance) + return; + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + if (pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) + { + if (pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED) + { + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) + me->AI()->SetData(DATA_START,0); + + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE) + DoStartArgentChampionEncounter(); + } + + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) + me->SummonCreature(VEHICLE_BLACK_KNIGHT,769.834,651.915,447.035,0); + } + } + + void AggroAllPlayers(Creature* pTemp) + { + Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + pTemp->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(pTemp); + pTemp->AddThreat(pPlayer, 0.0f); + } + } + } + } + + + void UpdateAI(const uint32 uiDiff) + { + ScriptedAI::UpdateAI(uiDiff); + + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + DoSummonGrandChampion(uiSecondBoss); + NextStep(10000,true); + break; + case 2: + DoSummonGrandChampion(uiThirdBoss); + NextStep(0,false); + break; + case 3: + if (!Champion1List.empty()) + { + for (std::list::const_iterator itr = Champion1List.begin(); itr != Champion1List.end(); ++itr) + if (Creature* pSummon = Unit::GetCreature(*me, *itr)) + AggroAllPlayers(pSummon); + NextStep(0,false); + } + break; + } + } else uiTimer -= uiDiff; + + if (!UpdateVictim()) + return; + } + + void JustSummoned(Creature* pSummon) + { + if (pInstance && pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) + { + pSummon->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pSummon->SetReactState(REACT_PASSIVE); + } + } + + void SummonedCreatureDespawn(Creature* pSummon) + { + switch(pSummon->GetEntry()) + { + case VEHICLE_DARNASSIA_NIGHTSABER: + case VEHICLE_EXODAR_ELEKK: + case VEHICLE_STORMWIND_STEED: + case VEHICLE_GNOMEREGAN_MECHANOSTRIDER: + case VEHICLE_IRONFORGE_RAM: + case VEHICLE_FORSAKE_WARHORSE: + case VEHICLE_THUNDER_BLUFF_KODO: + case VEHICLE_ORGRIMMAR_WOLF: + case VEHICLE_SILVERMOON_HAWKSTRIDER: + case VEHICLE_DARKSPEAR_RAPTOR: + me->AI()->SetData(DATA_LESSER_CHAMPIONS_DEFEATED,0); + break; + } + } +}; + +CreatureAI* GetAI_npc_announcer_toc5(Creature* pCreature) +{ + return new npc_announcer_toc5AI(pCreature); +} + +bool GossipHello_npc_announcer_toc5(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && + pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && + pInstance->GetData(BOSS_BLACK_KNIGHT) == DONE && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) + return false; + + if (pInstance && + pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED && + pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + else if (pInstance) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_announcer_toc5(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_announcer_toc5AI, pCreature->AI())->StartEncounter(); + } + + return true; +} + +void AddSC_trial_of_the_champion() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "npc_announcer_toc5"; + NewScript->GetAI = &GetAI_npc_announcer_toc5; + NewScript->pGossipHello = &GossipHello_npc_announcer_toc5; + NewScript->pGossipSelect = &GossipSelect_npc_announcer_toc5; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h new file mode 100644 index 00000000000..221c7c0412f --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_TOC_H +#define DEF_TOC_H + + +enum eData +{ + BOSS_GRAND_CHAMPIONS, + BOSS_ARGENT_CHALLENGE_E, + BOSS_ARGENT_CHALLENGE_P, + BOSS_BLACK_KNIGHT, + DATA_MOVEMENT_DONE, + DATA_LESSER_CHAMPIONS_DEFEATED, + DATA_START, + DATA_IN_POSITION, + DATA_ARGENT_SOLDIER_DEFEATED +}; + +enum Data64 +{ + DATA_ANNOUNCER, + DATA_MAIN_GATE, + + DATA_GRAND_CHAMPION_VEHICLE_1, + DATA_GRAND_CHAMPION_VEHICLE_2, + DATA_GRAND_CHAMPION_VEHICLE_3, + + DATA_GRAND_CHAMPION_1, + DATA_GRAND_CHAMPION_2, + DATA_GRAND_CHAMPION_3 +}; + +enum eNpcs +{ + // Horde Champions + NPC_MOKRA = 35572, + NPC_ERESSEA = 35569, + NPC_RUNOK = 35571, + NPC_ZULTORE = 35570, + NPC_VISCERI = 35617, + + // Alliance Champions + NPC_JACOB = 34705, + NPC_AMBROSE = 34702, + NPC_COLOSOS = 34701, + NPC_JAELYNE = 34657, + NPC_LANA = 34703, + + NPC_EADRIC = 35119, + NPC_PALETRESS = 34928, + + NPC_ARGENT_LIGHWIELDER = 35309, + NPC_ARGENT_MONK = 35305, + NPC_PRIESTESS = 35307, + + NPC_BLACK_KNIGHT = 35451, + + NPC_RISEN_JAEREN = 35545, + NPC_RISEN_ARELAS = 35564, + + NPC_JAEREN = 35004, + NPC_ARELAS = 35005 +}; + +enum eGameObjects +{ + GO_MAIN_GATE = 195647, + + GO_CHAMPIONS_LOOT = 195709, + GO_CHAMPIONS_LOOT_H = 195710, + + GO_EADRIC_LOOT = 195374, + GO_EADRIC_LOOT_H = 195375, + + GO_PALETRESS_LOOT = 195323, + GO_PALETRESS_LOOT_H = 195324 +}; + +enum eVehicles +{ + //Grand Champions Alliance Vehicles + VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT = 35637, + VEHICLE_AMBROSE_BOLTSPARK_MOUNT = 35633, + VEHICLE_COLOSOS_MOUNT = 35768, + VEHICLE_EVENSONG_MOUNT = 34658, + VEHICLE_LANA_STOUTHAMMER_MOUNT = 35636, + //Faction Champions (ALLIANCE) + VEHICLE_DARNASSIA_NIGHTSABER = 33298, + VEHICLE_EXODAR_ELEKK = 33416, + VEHICLE_STORMWIND_STEED = 33297, + VEHICLE_GNOMEREGAN_MECHANOSTRIDER = 33301, + VEHICLE_IRONFORGE_RAM = 33408, + //Grand Champions Horde Vehicles + VEHICLE_MOKRA_SKILLCRUSHER_MOUNT = 35638, + VEHICLE_ERESSEA_DAWNSINGER_MOUNT = 35635, + VEHICLE_RUNOK_WILDMANE_MOUNT = 35640, + VEHICLE_ZUL_TORE_MOUNT = 35641, + VEHICLE_DEATHSTALKER_VESCERI_MOUNT = 35634, + //Faction Champions (HORDE) + VEHICLE_FORSAKE_WARHORSE = 33414, + VEHICLE_THUNDER_BLUFF_KODO = 33300, + VEHICLE_ORGRIMMAR_WOLF = 33409, + VEHICLE_SILVERMOON_HAWKSTRIDER = 33418, + VEHICLE_DARKSPEAR_RAPTOR = 33299, + + VEHICLE_ARGENT_WARHORSE = 35644, + VEHICLE_ARGENT_BATTLEWORG = 36558, + + VEHICLE_BLACK_KNIGHT = 35491 +}; + +#endif diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp new file mode 100644 index 00000000000..ba64a4748dd --- /dev/null +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_dred.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2008 - 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: MAYBE need more improve the "Raptor Call". + */ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +enum eSpells +{ + SPELL_BELLOWING_ROAR = 22686, // fears the group, can be resisted/dispelled + SPELL_GRIEVOUS_BITE = 48920, + SPELL_MANGLING_SLASH = 48873, //casted on the current tank, adds debuf + SPELL_FEARSOME_ROAR = 48849, + H_SPELL_FEARSOME_ROAR = 59422, //Not stacking, debuff + SPELL_PIERCING_SLASH = 48878, //debuff -->Armor reduced by 75% + SPELL_RAPTOR_CALL = 59416, //dummy + SPELL_GUT_RIP = 49710, + SPELL_REND = 13738 +}; + +enum eArchivements +{ + ACHIEV_BETTER_OFF_DRED = 2039 +}; + +enum Creatures +{ + NPC_RAPTOR_1 = 26641, + NPC_RAPTOR_2 = 26628 +}; + +struct boss_dredAI : public ScriptedAI +{ + boss_dredAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBellowingRoarTimer; + uint32 uiGrievousBiteTimer; + uint32 uiManglingSlashTimer; + uint32 uiFearsomeRoarTimer; + uint32 uiPiercingSlashTimer; + uint32 uiRaptorCallTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + { + pInstance->SetData(DATA_DRED_EVENT,NOT_STARTED); + pInstance->SetData(DATA_KING_DRED_ACHIEV, 0); + } + + uiBellowingRoarTimer = 33*IN_MILISECONDS; + uiGrievousBiteTimer = 20*IN_MILISECONDS; + uiManglingSlashTimer = 18.5*IN_MILISECONDS; + uiFearsomeRoarTimer = urand(10*IN_MILISECONDS,20*IN_MILISECONDS); + uiPiercingSlashTimer = 17*IN_MILISECONDS; + uiRaptorCallTimer = urand(20*IN_MILISECONDS,25*IN_MILISECONDS); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_DRED_EVENT,IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBellowingRoarTimer < diff) + { + DoCastAOE(SPELL_BELLOWING_ROAR, false); + uiBellowingRoarTimer = 40*IN_MILISECONDS; + } else uiBellowingRoarTimer -=diff; + + if (uiGrievousBiteTimer < diff) + { + DoCastVictim(SPELL_GRIEVOUS_BITE ,false); + uiGrievousBiteTimer = 20*IN_MILISECONDS; + } else uiGrievousBiteTimer -=diff; + + if (uiManglingSlashTimer < diff) + { + DoCastVictim(SPELL_MANGLING_SLASH,false); + uiManglingSlashTimer = 20*IN_MILISECONDS; + } else uiManglingSlashTimer -=diff; + + if (uiFearsomeRoarTimer < diff) + { + DoCastAOE(SPELL_FEARSOME_ROAR,false); + uiFearsomeRoarTimer = urand(16*IN_MILISECONDS,18*IN_MILISECONDS); + } else uiFearsomeRoarTimer -=diff; + + if (uiPiercingSlashTimer < diff) + { + DoCastVictim(SPELL_PIERCING_SLASH,false); + uiPiercingSlashTimer = 20*IN_MILISECONDS; + } else uiPiercingSlashTimer -=diff; + + if (uiRaptorCallTimer < diff) + { + DoCastVictim(SPELL_RAPTOR_CALL,false); + + float x,y,z; + + me->GetClosePoint(x,y,z,me->GetObjectSize()/3,10.0f); + me->SummonCreature(RAND(NPC_RAPTOR_1,NPC_RAPTOR_2),x,y,z,0,TEMPSUMMON_DEAD_DESPAWN,1*IN_MILISECONDS); + + uiRaptorCallTimer = urand(20*IN_MILISECONDS,25*IN_MILISECONDS); + } else uiRaptorCallTimer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_DRED_EVENT,DONE); + + if (IsHeroic() && pInstance->GetData(DATA_KING_DRED_ACHIEV) == 6) + pInstance->DoCompleteAchievement(ACHIEV_BETTER_OFF_DRED); + } + } +}; + +CreatureAI* GetAI_boss_dred(Creature* pCreature) +{ + return new boss_dredAI (pCreature); +} + +struct npc_drakkari_gutripperAI : public ScriptedAI +{ + npc_drakkari_gutripperAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 GutRipTimer; + + void Reset() + { + GutRipTimer = urand(10000,15000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (GutRipTimer < diff) + { + DoCastVictim(SPELL_GUT_RIP,false); + GutRipTimer = urand(10000,15000); + }else GutRipTimer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (IsHeroic() && pInstance->GetData(DATA_DRED_EVENT) == IN_PROGRESS && pInstance->GetData(DATA_KING_DRED_ACHIEV) < 6) + { + pInstance->SetData(DATA_KING_DRED_ACHIEV, pInstance->GetData(DATA_KING_DRED_ACHIEV) + 1); + } + } + } +}; + +CreatureAI* GetAI_npc_drakkari_gutripper(Creature* pCreature) +{ + return new npc_drakkari_gutripperAI (pCreature); +} + +struct npc_drakkari_scytheclawAI : public ScriptedAI +{ + npc_drakkari_scytheclawAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiRendTimer; + + void Reset() + { + uiRendTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiRendTimer < diff) + { + DoCastVictim(SPELL_REND,false); + uiRendTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + }else uiRendTimer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (IsHeroic() && pInstance->GetData(DATA_DRED_EVENT) == IN_PROGRESS && pInstance->GetData(DATA_KING_DRED_ACHIEV) < 6) + { + pInstance->SetData(DATA_KING_DRED_ACHIEV, pInstance->GetData(DATA_KING_DRED_ACHIEV) + 1); + } + } + } +}; + +CreatureAI* GetAI_npc_drakkari_scytheclaw(Creature* pCreature) +{ + return new npc_drakkari_scytheclawAI (pCreature); +} + +void AddSC_boss_dred() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_drakkari_gutripper"; + newscript->GetAI = &GetAI_npc_drakkari_gutripper; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_drakkari_scytheclaw"; + newscript->GetAI = &GetAI_npc_drakkari_scytheclaw; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_dred"; + newscript->GetAI = &GetAI_boss_dred; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp new file mode 100644 index 00000000000..5e8792c352d --- /dev/null +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp @@ -0,0 +1,328 @@ +/* +* Copyright (C) 2008 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +enum Spells +{ + SPELL_ARCANE_BLAST = 49198, + H_SPELL_ARCANE_BLAST = 59909, + SPELL_ARCANE_FIELD = 47346, + SPELL_BLIZZARD = 49034, + H_SPELL_BLIZZARD = 59854, + SPELL_FROSTBOLT = 49037, + H_SPELL_FROSTBOLT = 59855, + SPELL_WRATH_OF_MISERY = 50089, + H_SPELL_WRATH_OF_MISERY = 59856, + SPELL_SUMMON_MINIONS = 59910 //Summons an army of Fetid Troll Corpses to assist the caster. +}; +//not in db +enum Yells +{ + SAY_AGGRO = -1600000, + SAY_KILL = -1600001, + SAY_DEATH = -1600002, + SAY_NECRO_ADD = -1600003, + SAY_REUBBLE_1 = -1600004, + SAY_REUBBLE_2 = -1600005 +}; +enum Creatures +{ + CREATURE_RISEN_SHADOWCASTER = 27600, + CREATURE_FETID_TROLL_CORPSE = 27598, + CREATURE_HULKING_CORPSE = 27597, + CREATURE_CRYSTAL_HANDLER = 26627 +}; +enum CombatPhase +{ + IDLE, + PHASE_1, + PHASE_2 +}; +enum Achievements +{ + ACHIEV_OH_NOVOS = 2057 +}; + +static Position AddSpawnPoint = { -379.20, -816.76, 59.70 }; +static Position CrystalHandlerSpawnPoint = { -326.626343, -709.956604, 27.813314 }; +static Position AddDestinyPoint = { -379.314545, -772.577637, 28.58837 }; + +struct boss_novosAI : public Scripted_NoMovementAI +{ + boss_novosAI(Creature *c) : Scripted_NoMovementAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiTimer; + uint32 uiCrystalHandlerTimer; + + bool bAchiev; + + SummonList lSummons; + + std::list luiCrystals; + + CombatPhase Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + Phase = IDLE; + luiCrystals.clear(); + bAchiev = true; + me->CastStop(); + lSummons.DespawnAll(); + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (pInstance) + { + pInstance->SetData(DATA_NOVOS_EVENT, NOT_STARTED); + luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_1)); + luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_2)); + luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_3)); + luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_4)); + for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) + { + if (GameObject* pTemp = pInstance->instance->GetGameObject(*itr)) + pTemp->SetGoState(GO_STATE_READY); + } + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + Phase = PHASE_1; + uiCrystalHandlerTimer = 30*IN_MILISECONDS; + uiTimer = 1*IN_MILISECONDS; + DoCast(SPELL_ARCANE_FIELD); + if (pInstance) + { + for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) + { + if (GameObject *pTemp = pInstance->instance->GetGameObject(*itr)) + pTemp->SetGoState(GO_STATE_ACTIVE); + } + pInstance->SetData(DATA_NOVOS_EVENT, IN_PROGRESS); + } + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void UpdateAI(const uint32 diff) + { + switch (Phase) + { + case PHASE_1: + if (uiTimer <= diff) + { + Creature *pSummon = me->SummonCreature(RAND(CREATURE_FETID_TROLL_CORPSE,CREATURE_HULKING_CORPSE,CREATURE_RISEN_SHADOWCASTER), AddSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); + pSummon->GetMotionMaster()->MovePoint(0, AddDestinyPoint); + //If spell is casted stops casting arcane field so no spell casting + //DoCast(me, SPELL_SUMMON_MINIONS); + uiTimer = 3*IN_MILISECONDS; + } else uiTimer -= diff; + if (uiCrystalHandlerTimer <= diff) + { + DoScriptText(SAY_NECRO_ADD, me); + Creature *pCrystalHandler = me->SummonCreature(CREATURE_CRYSTAL_HANDLER, CrystalHandlerSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); + pCrystalHandler->GetMotionMaster()->MovePoint(0, AddDestinyPoint); + uiCrystalHandlerTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiCrystalHandlerTimer -= diff; + break; + case PHASE_2: + if (uiTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, DUNGEON_MODE(RAND(SPELL_ARCANE_BLAST,SPELL_BLIZZARD,SPELL_FROSTBOLT,SPELL_WRATH_OF_MISERY), + RAND(H_SPELL_ARCANE_BLAST,H_SPELL_BLIZZARD,H_SPELL_FROSTBOLT,H_SPELL_WRATH_OF_MISERY))); + uiTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); + } else uiTimer -= diff; + break; + } + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + { + pInstance->SetData(DATA_NOVOS_EVENT, DONE); + + if (IsHeroic() && bAchiev) + pInstance->DoCompleteAchievement(ACHIEV_OH_NOVOS); + } + lSummons.DespawnAll(); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(SAY_KILL, me); + } + + void JustSummoned(Creature *summon) + { + lSummons.Summon(summon); + } + + void RemoveCrystal() + { + if (!luiCrystals.empty()) + { + if (pInstance) + if (GameObject *pTemp = pInstance->instance->GetGameObject(luiCrystals.back())) + pTemp->SetGoState(GO_STATE_READY); + luiCrystals.pop_back(); + } + if (luiCrystals.empty()) + { + me->CastStop(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Phase = PHASE_2; + uiTimer = 1*IN_MILISECONDS; + } + } + + Unit* GetRandomTarget() + { + return SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + } +}; + +enum CrystalHandlerSpells +{ + SPELL_FLASH_OF_DARKNESS = 49668, + H_SPELL_FLASH_OF_DARKNESS = 59004 +}; + +struct mob_crystal_handlerAI : public ScriptedAI +{ + mob_crystal_handlerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiFlashOfDarknessTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiFlashOfDarknessTimer = 5*IN_MILISECONDS; + } + + void JustDied(Unit* /*killer*/) + { + if (Creature* pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) + CAST_AI(boss_novosAI,pNovos->AI())->RemoveCrystal(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiFlashOfDarknessTimer <= diff) + { + DoCast(me->getVictim(), DUNGEON_MODE(SPELL_FLASH_OF_DARKNESS,H_SPELL_FLASH_OF_DARKNESS)); + uiFlashOfDarknessTimer = 5*IN_MILISECONDS; + } else uiFlashOfDarknessTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || id != 0) + return; + if (Creature *pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) + if (Unit *pTarget = CAST_AI(boss_novosAI, pNovos->AI())->GetRandomTarget()) + AttackStart(pTarget); + } +}; + +struct mob_novos_minionAI : public ScriptedAI +{ + mob_novos_minionAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || id !=0) + return; + if (Creature* pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) + { + CAST_AI(boss_novosAI, pNovos->AI())->bAchiev = false; + if (Unit *pTarget = CAST_AI(boss_novosAI, pNovos->AI())->GetRandomTarget()) + AttackStart(pTarget); + } + } +}; + +CreatureAI* GetAI_boss_novos(Creature* pCreature) +{ + return new boss_novosAI (pCreature); +} + +CreatureAI* GetAI_mob_crystal_handler(Creature* pCreature) +{ + return new mob_crystal_handlerAI (pCreature); +} + +CreatureAI* GetAI_mob_novos_minion(Creature* pCreature) +{ + return new mob_novos_minionAI (pCreature); +} + +void AddSC_boss_novos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_novos"; + newscript->GetAI = &GetAI_boss_novos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crystal_handler"; + newscript->GetAI = &GetAI_mob_crystal_handler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_novos_minion"; + newscript->GetAI = &GetAI_mob_novos_minion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp new file mode 100644 index 00000000000..1e60dfc6135 --- /dev/null +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_tharon_ja.cpp @@ -0,0 +1,260 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +enum Spells +{ + //skeletal spells (phase 1) + SPELL_CURSE_OF_LIFE = 49527, + H_SPELL_CURSE_OF_LIFE = 59972, + SPELL_RAIN_OF_FIRE = 49518, + H_SPELL_RAIN_OF_FIRE = 59971, + SPELL_SHADOW_VOLLEY = 49528, + H_SPELL_SHADOW_VOLLEY = 59973, + SPELL_DECAY_FLESH = 49356, //casted at end of phase 1, starts phase 2 + //flesh spells (phase 2) + SPELL_GIFT_OF_THARON_JA = 52509, + SPELL_EYE_BEAM = 49544, + H_SPELL_EYE_BEAM = 59965, + SPELL_LIGHTNING_BREATH = 49537, + H_SPELL_LIGHTNING_BREATH = 59963, + SPELL_POISON_CLOUD = 49548, + H_SPELL_POISON_CLOUD = 59969, + SPELL_RETURN_FLESH = 53463, //Channeled spell ending phase two and returning to phase 1. This ability will stun the party for 6 seconds. + SPELL_ACHIEVEMENT_CHECK = 61863, +}; + +enum Yells +{ + SAY_AGGRO = -1600011, + SAY_KILL_1 = -1600012, + SAY_KILL_2 = -1600013, + SAY_FLESH_1 = -1600014, + SAY_FLESH_2 = -1600015, + SAY_SKELETON_1 = -1600016, + SAY_SKELETON_2 = -1600017, + SAY_DEATH = -1600018 +}; +enum Models +{ + MODEL_FLESH = 27073, + MODEL_SKELETON = 27511 +}; +enum CombatPhase +{ + SKELETAL, + GOING_FLESH, + FLESH, + GOING_SKELETAL +}; + +struct boss_tharon_jaAI : public ScriptedAI +{ + boss_tharon_jaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiPhaseTimer; + uint32 uiCurseOfLifeTimer; + uint32 uiRainOfFireTimer; + uint32 uiShadowVolleyTimer; + uint32 uiEyeBeamTimer; + uint32 uiLightningBreathTimer; + uint32 uiPoisonCloudTimer; + + CombatPhase Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + uiPhaseTimer = 20*IN_MILISECONDS; + uiCurseOfLifeTimer = 1*IN_MILISECONDS; + uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); + uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); + Phase = SKELETAL; + me->SetDisplayId(me->GetNativeDisplayId()); + if (pInstance) + pInstance->SetData(DATA_THARON_JA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_THARON_JA_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + switch (Phase) + { + case SKELETAL: + if (uiCurseOfLifeTimer < diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CURSE_OF_LIFE); + uiCurseOfLifeTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiCurseOfLifeTimer -= diff; + + if (uiShadowVolleyTimer < diff) + { + DoCastVictim(SPELL_SHADOW_VOLLEY); + uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); + } else uiShadowVolleyTimer -= diff; + + if (uiRainOfFireTimer < diff) + { + DoCastAOE(SPELL_RAIN_OF_FIRE); + uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); + } else uiRainOfFireTimer -= diff; + + if (uiPhaseTimer < diff) + { + DoCast(SPELL_DECAY_FLESH); + Phase = GOING_FLESH; + uiPhaseTimer = 6*IN_MILISECONDS; + } else uiPhaseTimer -= diff; + + DoMeleeAttackIfReady(); + break; + case GOING_FLESH: + if (uiPhaseTimer < diff) + { + DoScriptText(RAND(SAY_FLESH_1,SAY_FLESH_2),me); + me->SetDisplayId(MODEL_FLESH); + std::list& threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + Unit *pTemp = Unit::GetUnit((*me),(*itr)->getUnitGuid()); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) + { + me->AddAura(SPELL_GIFT_OF_THARON_JA,pTemp); + pTemp->SetDisplayId(MODEL_SKELETON); + } + } + uiPhaseTimer = 20*IN_MILISECONDS; + uiLightningBreathTimer = urand(3*IN_MILISECONDS,4*IN_MILISECONDS); + uiEyeBeamTimer = urand(4*IN_MILISECONDS,8*IN_MILISECONDS); + uiPoisonCloudTimer = urand(6*IN_MILISECONDS,7*IN_MILISECONDS); + Phase = FLESH; + } else uiPhaseTimer -= diff; + break; + case FLESH: + if (uiLightningBreathTimer < diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_LIGHTNING_BREATH); + uiLightningBreathTimer = urand(6*IN_MILISECONDS,7*IN_MILISECONDS); + } else uiLightningBreathTimer -= diff; + + if (uiEyeBeamTimer < diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_EYE_BEAM); + uiEyeBeamTimer = urand(4*IN_MILISECONDS,6*IN_MILISECONDS); + } else uiEyeBeamTimer -= diff; + + if (uiPoisonCloudTimer < diff) + { + DoCastAOE(SPELL_POISON_CLOUD); + uiPoisonCloudTimer = urand(10*IN_MILISECONDS,12*IN_MILISECONDS); + } else uiPoisonCloudTimer -= diff; + + if (uiPhaseTimer < diff) + { + DoCast(SPELL_RETURN_FLESH); + Phase = GOING_SKELETAL; + uiPhaseTimer = 6*IN_MILISECONDS; + } else uiPhaseTimer -= diff; + DoMeleeAttackIfReady(); + break; + case GOING_SKELETAL: + if (uiPhaseTimer < diff) + { + DoScriptText(RAND(SAY_SKELETON_1,SAY_SKELETON_2), me); + me->DeMorph(); + Phase = SKELETAL; + uiPhaseTimer = 20*IN_MILISECONDS; + uiCurseOfLifeTimer = 1*IN_MILISECONDS; + uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); + uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); + std::list& threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) + { + Unit *pTemp = Unit::GetUnit((*me),(*itr)->getUnitGuid()); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) + { + if (pTemp->HasAura(SPELL_GIFT_OF_THARON_JA)) + pTemp->RemoveAura(SPELL_GIFT_OF_THARON_JA); + pTemp->DeMorph(); + } + } + } else uiPhaseTimer -= diff; + break; + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2),me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH,me); + + if (pInstance) + { + // clean morph on players + Map::PlayerList const &PlayerList = pInstance->instance->GetPlayers(); + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player *pPlayer = i->getSource()) + pPlayer->DeMorph(); + // cast is not rewarding the achievement. + // DoCast(SPELL_ACHIEVEMENT_CHECK); + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, SPELL_ACHIEVEMENT_CHECK); + + pInstance->SetData(DATA_THARON_JA_EVENT, DONE); + } + } +}; + +CreatureAI* GetAI_boss_tharon_ja(Creature* pCreature) +{ + return new boss_tharon_jaAI (pCreature); +} + +void AddSC_boss_tharon_ja() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_tharon_ja"; + newscript->GetAI = &GetAI_boss_tharon_ja; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp new file mode 100644 index 00000000000..03eac73385d --- /dev/null +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: TODO: spawn troll waves + */ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +enum Spells +{ + SPELL_INFECTED_WOUND = 49637, + SPELL_CRUSH = 49639, + SPELL_CORPSE_EXPLODE = 49555, + SPELL_CONSUME = 49380, + SPELL_CONSUME_AURA = 49381, + //Heroic spells + H_SPELL_CORPSE_EXPLODE = 59807, + H_SPELL_CONSUME = 59803, + H_SPELL_CONSUME_AURA = 59805, +}; +enum Yells +{ + SAY_AGGRO = -1600006, + SAY_KILL = -1600007, + SAY_CONSUME = -1600008, + SAY_EXPLODE = -1600009, + SAY_DEATH = -1600010 +}; +enum Achievements +{ + ACHIEV_CONSUMPTION_JUNCTION = 2151 +}; +enum Creatures +{ + NPC_DRAKKARI_INVADER_1 = 27753, + NPC_DRAKKARI_INVADER_2 = 27709 +}; + +Position AddSpawnPoint = { -260.493011, -622.968018, 26.605301, 3.036870 }; + +struct boss_trollgoreAI : public ScriptedAI +{ + boss_trollgoreAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiConsumeTimer; + uint32 uiAuraCountTimer; + uint32 uiCrushTimer; + uint32 uiInfectedWoundTimer; + uint32 uiExplodeCorpseTimer; + uint32 uiSpawnTimer; + + bool bAchiev; + + SummonList lSummons; + + ScriptedInstance* pInstance; + + void Reset() + { + uiConsumeTimer = 15*IN_MILISECONDS; + uiAuraCountTimer = 15.5*IN_MILISECONDS; + uiCrushTimer = urand(1*IN_MILISECONDS,5*IN_MILISECONDS); + uiInfectedWoundTimer = urand(60*IN_MILISECONDS,10*IN_MILISECONDS); + uiExplodeCorpseTimer = 3*IN_MILISECONDS; + uiSpawnTimer = urand(30*IN_MILISECONDS,40*IN_MILISECONDS); + + bAchiev = IsHeroic(); + + lSummons.DespawnAll(); + + me->RemoveAura(DUNGEON_MODE(SPELL_CONSUME_AURA,H_SPELL_CONSUME_AURA)); + + if (pInstance) + pInstance->SetData(DATA_TROLLGORE_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_TROLLGORE_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiSpawnTimer <= diff) + { + uint32 spawnNumber = urand(2,DUNGEON_MODE(3,5)); + for (uint8 i = 0; i < spawnNumber; ++i) + DoSummon(RAND(NPC_DRAKKARI_INVADER_1,NPC_DRAKKARI_INVADER_2), AddSpawnPoint, 0, TEMPSUMMON_DEAD_DESPAWN); + uiSpawnTimer = urand(30*IN_MILISECONDS,40*IN_MILISECONDS); + } else uiSpawnTimer -= diff; + + if (uiConsumeTimer <= diff) + { + DoScriptText(SAY_CONSUME, me); + DoCast(SPELL_CONSUME); + uiConsumeTimer = 15*IN_MILISECONDS; + } else uiConsumeTimer -= diff; + + if (bAchiev) + { + Aura *pConsumeAura = me->GetAura(DUNGEON_MODE(SPELL_CONSUME_AURA,H_SPELL_CONSUME_AURA)); + if (pConsumeAura && pConsumeAura->GetStackAmount() > 9) + bAchiev = false; + } + + if (uiCrushTimer <= diff) + { + DoCastVictim(SPELL_CRUSH); + uiCrushTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); + } else uiCrushTimer -= diff; + + if (uiInfectedWoundTimer <= diff) + { + DoCastVictim(SPELL_INFECTED_WOUND); + uiInfectedWoundTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); + } else uiInfectedWoundTimer -= diff; + + if (uiExplodeCorpseTimer <= diff) + { + DoCast(SPELL_CORPSE_EXPLODE); + DoScriptText(SAY_EXPLODE, me); + uiExplodeCorpseTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); + } else uiExplodeCorpseTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + lSummons.DespawnAll(); + + if (pInstance) + { + if (bAchiev) + pInstance->DoCompleteAchievement(ACHIEV_CONSUMPTION_JUNCTION); + pInstance->SetData(DATA_TROLLGORE_EVENT, DONE); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(SAY_KILL, me); + } + + void JustSummoned(Creature* summon) + { + lSummons.push_back(summon->GetGUID()); + if (summon->AI()) + summon->AI()->AttackStart(me); + } +}; + +CreatureAI* GetAI_boss_trollgore(Creature* pCreature) +{ + return new boss_trollgoreAI (pCreature); +} + +void AddSC_boss_trollgore() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_trollgore"; + newscript->GetAI = &GetAI_boss_trollgore; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h b/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h new file mode 100644 index 00000000000..597971d17dd --- /dev/null +++ b/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h @@ -0,0 +1,40 @@ +/* +* Copyright (C) 2008 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DEF_DRAK_THARON_H +#define DEF_DRAK_THARON_H +enum Data +{ + DATA_TROLLGORE_EVENT, + DATA_NOVOS_EVENT, + DATA_DRED_EVENT, + DATA_THARON_JA_EVENT, + DATA_KING_DRED_ACHIEV +}; +enum Data64 +{ + DATA_TROLLGORE, + DATA_NOVOS, + DATA_DRED, + DATA_THARON_JA, + DATA_NOVOS_CRYSTAL_1, + DATA_NOVOS_CRYSTAL_2, + DATA_NOVOS_CRYSTAL_3, + DATA_NOVOS_CRYSTAL_4 +}; +#endif diff --git a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp new file mode 100644 index 00000000000..9f4d2ee52a2 --- /dev/null +++ b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "drak_tharon_keep.h" + +#define MAX_ENCOUNTER 4 + +/* Drak'Tharon Keep encounters: +0 - Trollgore +1 - Novos +2 - King Dred +3 - Tharon Ja +*/ + +enum Creatures +{ + NPC_TROLLGORE = 26630, + NPC_NOVOS = 26631, + NPC_KING_DRED = 27483, + NPC_THARON_JA = 26632 +}; +enum GameObjects +{ + GO_NOVOS_CRYSTAL_1 = 189299, + GO_NOVOS_CRYSTAL_2 = 189300, + GO_NOVOS_CRYSTAL_3 = 189301, + GO_NOVOS_CRYSTAL_4 = 189302 +}; + +struct instance_drak_tharon : public ScriptedInstance +{ + instance_drak_tharon(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint8 uiDredAchievCounter; + + uint64 uiTrollgore; + uint64 uiNovos; + uint64 uiDred; + uint64 uiTharonJa; + + uint64 uiNovosCrystal1; + uint64 uiNovosCrystal2; + uint64 uiNovosCrystal3; + uint64 uiNovosCrystal4; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + + std::string str_data; + + void Initialize() + { + uiTrollgore = 0; + uiNovos = 0; + uiDred = 0; + uiTharonJa = 0; + uiNovosCrystal1 = 0; + uiNovosCrystal2 = 0; + uiNovosCrystal3 = 0; + uiNovosCrystal4 = 0; + uiDredAchievCounter = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_NOVOS_CRYSTAL_1: + uiNovosCrystal1 = pGo->GetGUID(); + break; + case GO_NOVOS_CRYSTAL_2: + uiNovosCrystal2 = pGo->GetGUID(); + break; + case GO_NOVOS_CRYSTAL_3: + uiNovosCrystal3 = pGo->GetGUID(); + break; + case GO_NOVOS_CRYSTAL_4: + uiNovosCrystal4 = pGo->GetGUID(); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_TROLLGORE: + uiTrollgore = pCreature->GetGUID(); + break; + case NPC_NOVOS: + uiNovos = pCreature->GetGUID(); + break; + case NPC_KING_DRED: + uiDred = pCreature->GetGUID(); + break; + case NPC_THARON_JA: + uiTharonJa = pCreature->GetGUID(); + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_TROLLGORE: return uiTrollgore; + case DATA_NOVOS: return uiNovos; + case DATA_DRED: return uiDred; + case DATA_THARON_JA: return uiTharonJa; + case DATA_NOVOS_CRYSTAL_1: return uiNovosCrystal1; + case DATA_NOVOS_CRYSTAL_2: return uiNovosCrystal2; + case DATA_NOVOS_CRYSTAL_3: return uiNovosCrystal3; + case DATA_NOVOS_CRYSTAL_4: return uiNovosCrystal4; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_TROLLGORE_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_NOVOS_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_DRED_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_THARON_JA_EVENT: + m_auiEncounter[3] = data; + break; + + case DATA_KING_DRED_ACHIEV: + uiDredAchievCounter = data; + break; + } + + if (data == DONE) + { + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch (type) + { + case DATA_TROLLGORE_EVENT: return m_auiEncounter[0]; + case DATA_NOVOS_EVENT: return m_auiEncounter[1]; + case DATA_DRED_EVENT: return m_auiEncounter[2]; + case DATA_THARON_JA_EVENT: return m_auiEncounter[3]; + case DATA_KING_DRED_ACHIEV: return uiDredAchievCounter; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::string str_data; + + std::ostringstream saveStream; + saveStream << "D K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0,data1,data2,data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'D' && dataHead2 == 'K') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_drak_tharon(Map* pMap) +{ + return new instance_drak_tharon(pMap); +} + +void AddSC_instance_drak_tharon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_drak_tharon"; + newscript->GetInstanceData = &GetInstanceData_instance_drak_tharon; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp new file mode 100644 index 00000000000..59db2842735 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp @@ -0,0 +1,263 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +/* + * TODO: + * - Fix Soul Storm spell and remove work around. + */ + +enum Yells +{ + SAY_AGGRO = -1632001, + SAY_SLAY_1 = -1632002, + SAY_SLAY_2 = -1632003, + SAY_DEATH = -1632004, + SAY_SOUL_STORM = -1632005, + SAY_CORRUPT_SOUL = -1632006, +}; + +enum Spells +{ + SPELL_MAGIC_S_BANE = 68793, + SPELL_CORRUPT_SOUL = 68839, + SPELL_CONSUME_SOUL = 68858, + SPELL_TELEPORT = 68988, + SPELL_FEAR = 68950, + SPELL_SOULSTORM = 68872, + SPELL_SOULSTORM_AURA = 68921, + SPELL_SHADOW_BOLT = 70043, +}; + +enum Events +{ + EVENT_NONE, + EVENT_SHADOW_BOLT, + EVENT_MAGIC_BANE, + EVENT_CORRUPT_SOUL, + EVENT_SOUL_STORM, + EVENT_SOUL_STORM_AURA, + EVENT_FEAR, +}; + +enum CombatPhases +{ + PHASE_1, + PHASE_2 +}; + +struct boss_bronjahmAI : public ScriptedAI +{ + boss_bronjahmAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + CombatPhases phase; + + void Reset() + { + phase = PHASE_1; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + events.Reset(); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); + events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); + events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + // Cast aura spell on all players farther than 10y + void ApplySoulStorm() + { + std::list targetList; + + SelectTargetList(targetList, 100, SELECT_TARGET_TOPAGGRO, -10.0f); + if (targetList.empty()) + return; + + for (std::list::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr) + { + Unit* pUnit = (*itr); + if (pUnit && pUnit->isAlive()) + me->CastSpell(pUnit, SPELL_SOULSTORM_AURA, true); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (phase == PHASE_1 && HealthBelowPct(30)) + { + phase = PHASE_2; + DoCast(me,SPELL_TELEPORT); + me->GetMotionMaster()->Clear(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + events.CancelEvent(EVENT_CORRUPT_SOUL); + events.ScheduleEvent(EVENT_SOUL_STORM, 1000); + events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); + return; + } + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CORRUPT_SOUL: + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + DoScriptText(SAY_CORRUPT_SOUL, me); + DoCast(pTarget,SPELL_CORRUPT_SOUL); + } + events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); + break; + case EVENT_SOUL_STORM: + DoScriptText(SAY_SOUL_STORM, me); + // DoCast(me, SPELL_SOULSTORM); bug: put the aura without the limit of 10 yards. + events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); + break; + case EVENT_SOUL_STORM_AURA: + ApplySoulStorm(); + events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); + break; + case EVENT_FEAR: + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget,SPELL_FEAR); + events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); + break; + case EVENT_SHADOW_BOLT: + DoCastVictim(SPELL_SHADOW_BOLT); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); + break; + case EVENT_MAGIC_BANE: + DoCastVictim(SPELL_MAGIC_S_BANE); + events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bronjahm(Creature* pCreature) +{ + return new boss_bronjahmAI(pCreature); +} + +struct mob_corrupted_soul_fragmentAI : public ScriptedAI +{ + mob_corrupted_soul_fragmentAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCheckTimer; + + void Reset() + { + uiCheckTimer = 0; // first check is immediate + } + + void UpdateAI(const uint32 diff) + { + if (uiCheckTimer <= diff) + { + if (pInstance) + { + Creature* pBronjham = Unit::GetCreature(*me, pInstance->GetData64(DATA_BRONJAHM)); + if (pBronjham && pBronjham->isAlive()) + { + if (me->IsWithinMeleeRange(pBronjham)) + { + pBronjham->CastSpell(pBronjham, SPELL_CONSUME_SOUL, true); + me->ForcedDespawn(); + } + else + { + Position pos; + pBronjham->GetPosition(&pos); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, pos); + } + } + else + me->ForcedDespawn(); + } + uiCheckTimer = 500; + } + else + uiCheckTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_corrupted_soul_fragment(Creature* pCreature) +{ + return new mob_corrupted_soul_fragmentAI(pCreature); +} + +void AddSC_boss_bronjahm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_bronjahm"; + newscript->GetAI = &GetAI_boss_bronjahm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_corrupted_soul_fragment"; + newscript->GetAI = &GetAI_mob_corrupted_soul_fragment; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp new file mode 100644 index 00000000000..6811ba953e2 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp @@ -0,0 +1,349 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +/* + * TODO: + * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing). + * - Fix outro npc movement + */ + +#define PI 3.1415f + +enum Yells +{ + SAY_FACE_ANGER_AGGRO = -1632010, + SAY_FACE_DESIRE_AGGRO = -1632011, + SAY_FACE_ANGER_SLAY_1 = -1632012, + SAY_FACE_SORROW_SLAY_1 = -1632013, + SAY_FACE_DESIRE_SLAY_1 = -1632014, + SAY_FACE_ANGER_SLAY_2 = -1632015, + SAY_FACE_SORROW_SLAY_2 = -1632016, + SAY_FACE_DESIRE_SLAY_2 = -1632017, + SAY_FACE_SORROW_DEATH = -1632019, + SAY_FACE_DESIRE_DEATH = -1632020, + EMOTE_MIRRORED_SOUL = -1632021, + EMOTE_UNLEASH_SOUL = -1632022, + SAY_FACE_ANGER_UNLEASH_SOUL = -1632023, + SAY_FACE_SORROW_UNLEASH_SOUL = -1632024, + SAY_FACE_DESIRE_UNLEASH_SOUL = -1632025, + EMOTE_WAILING_SOUL = -1632026, + SAY_FACE_ANGER_WAILING_SOUL = -1632027, + SAY_FACE_DESIRE_WAILING_SOUL = -1632028, + + SAY_JAINA_OUTRO = -1632029, + SAY_SYLVANAS_OUTRO = -1632030, +}; + +enum Spells +{ + SPELL_PHANTOM_BLAST = 68982, + H_SPELL_PHANTOM_BLAST = 70322, + SPELL_MIRRORED_SOUL = 69051, + SPELL_WELL_OF_SOULS = 68820, + SPELL_WELL_OF_SOULS_VIS = 68854, + SPELL_UNLEASHED_SOULS = 68939, + SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase + SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual + SPELL_WAILING_SOULS = 68873, // the actual spell + H_SPELL_WAILING_SOULS = 70324, +// 68871,68873,68875,68876,68899,68912,70324, +// 68899 trigger 68871 +}; + +enum Events +{ + EVENT_NONE, + EVENT_PHANTOM_BLAST, + EVENT_MIRRORED_SOUL, + EVENT_WELL_OF_SOULS, + EVENT_UNLEASHED_SOULS, + EVENT_WAILING_SOULS, + EVENT_WAILING_SOULS_TICK, + EVENT_FACE_ANGER, +}; + +enum eEnum +{ + ACHIEV_THREE_FACED = 4523, + DISPLAY_ANGER = 30148, + DISPLAY_SORROW = 30149, + DISPLAY_DESIRE = 30150, +}; + +struct +{ + uint32 entry[2]; + Position movePosition; +} outroPositions[] = +{ + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5590.47, 2427.79, 705.935, 0.802851 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5593.59, 2428.34, 705.935, 0.977384 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2429.31, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2421.12, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.43, 2426.53, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.55, 2418.36, 705.935, 1.15192 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5598, 2429.14, 705.935, 1.0472 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5594.04, 2424.87, 705.935, 1.15192 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5597.89, 2421.54, 705.935, 0.610865 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5598.57, 2434.62, 705.935, 1.13446 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5585.46, 2417.99, 705.935, 1.06465 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5605.81, 2428.42, 705.935, 0.820305 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5591.61, 2412.66, 705.935, 0.925025 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5593.9, 2410.64, 705.935, 0.872665 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5586.76, 2416.73, 705.935, 0.942478 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5592.23, 2419.14, 705.935, 0.855211 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5594.61, 2416.87, 705.935, 0.907571 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5589.77, 2421.03, 705.935, 0.855211 } }, + + { NPC_KORELN, NPC_LORALEN, { 5602.58, 2435.95, 705.935, 0.959931 } }, + { NPC_ELANDRA, NPC_KALIRA, { 5606.13, 2433.16, 705.935, 0.785398 } }, + { NPC_JAINA_PART2, NPC_SYLVANAS_PART2, { 5606.12, 2436.6, 705.935, 0.890118 } }, + + { 0, 0, { 0, 0, 0, 0 } } +}; + +struct boss_devourer_of_soulsAI : public ScriptedAI +{ + boss_devourer_of_soulsAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + bool bThreeFaceAchievement; + + ScriptedInstance* pInstance; + EventMap events; + + // wailing soul event + float beamAngle; + float beamAngleDiff; + int8 wailingSoulTick; + + uint64 uiMirroredSoulTarget; + + void Reset() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetDisplayId(DISPLAY_ANGER); + me->SetReactState(REACT_AGGRESSIVE); + + events.Reset(); + + bThreeFaceAchievement = true; + uiMirroredSoulTarget = 0; + + if (pInstance) + pInstance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS); + + DoScriptText(RAND(SAY_FACE_ANGER_AGGRO,SAY_FACE_DESIRE_AGGRO), me); + + events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); + events.ScheduleEvent(EVENT_MIRRORED_SOUL, 8000); + events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000); + events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000); + events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + if (uiMirroredSoulTarget && me->HasAura(SPELL_MIRRORED_SOUL)) + { + if (Player *pPlayer = Unit::GetPlayer(uiMirroredSoulTarget)) + { + if (Aura *pAura = pPlayer->GetAura(SPELL_MIRRORED_SOUL)) + { + int32 mirrorDamage = (uiDamage * 45)/100; + me->CastCustomSpell(pPlayer, 69034, &mirrorDamage, 0, 0, true); +// me->DealDamage(pPlayer, (uiDamage * 45)/100, 0, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); + } + else + uiMirroredSoulTarget = 0; + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_FACE_ANGER_SLAY_1,SAY_FACE_SORROW_SLAY_1,SAY_FACE_DESIRE_SLAY_1, + SAY_FACE_ANGER_SLAY_2,SAY_FACE_SORROW_SLAY_2,SAY_FACE_DESIRE_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + Position spawnPoint = { 5618.139, 2451.873, 705.854 }; + + DoScriptText(RAND(SAY_FACE_SORROW_DEATH,SAY_FACE_DESIRE_DEATH), me); + + if (pInstance) + { + pInstance->SetData(DATA_DEVOURER_EVENT, DONE); + + if (bThreeFaceAchievement && IsHeroic()) + pInstance->DoCompleteAchievement(ACHIEV_THREE_FACED); + + int32 entryIndex; + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + entryIndex = 0; + else + entryIndex = 1; + + for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i) + { + if (Creature *pSummon = me->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint, TEMPSUMMON_DEAD_DESPAWN)) + { + pSummon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition); + + if (pSummon->GetEntry() == NPC_JAINA_PART2) + DoScriptText(SAY_JAINA_OUTRO, pSummon); + else if (pSummon->GetEntry() == NPC_SYLVANAS_PART2) + DoScriptText(SAY_SYLVANAS_OUTRO, pSummon); + } + } + } + } + + void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry *pSpell) + { + if (pSpell->Id == H_SPELL_PHANTOM_BLAST) + bThreeFaceAchievement = false; + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_PHANTOM_BLAST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, SPELL_PHANTOM_BLAST); + events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); + break; + case EVENT_MIRRORED_SOUL: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) + { + uiMirroredSoulTarget = pTarget->GetGUID(); + DoCast(pTarget, SPELL_MIRRORED_SOUL); + DoScriptText(EMOTE_MIRRORED_SOUL, me); + } + events.ScheduleEvent(EVENT_MIRRORED_SOUL, urand(15000,30000)); + break; + case EVENT_WELL_OF_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_WELL_OF_SOULS); + events.ScheduleEvent(EVENT_WELL_OF_SOULS, 20000); + break; + case EVENT_UNLEASHED_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_UNLEASHED_SOULS); + me->SetDisplayId(DISPLAY_SORROW); + DoScriptText(RAND(SAY_FACE_ANGER_UNLEASH_SOUL,SAY_FACE_SORROW_UNLEASH_SOUL,SAY_FACE_DESIRE_UNLEASH_SOUL), me); + DoScriptText(EMOTE_UNLEASH_SOUL, me); + events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 30000); + events.ScheduleEvent(EVENT_FACE_ANGER, 5000); + break; + case EVENT_FACE_ANGER: + me->SetDisplayId(DISPLAY_ANGER); + break; + + case EVENT_WAILING_SOULS: + me->SetDisplayId(DISPLAY_DESIRE); + DoScriptText(RAND(SAY_FACE_ANGER_WAILING_SOUL,SAY_FACE_DESIRE_WAILING_SOUL), me); + DoScriptText(EMOTE_WAILING_SOUL, me); + DoCast(me, SPELL_WAILING_SOULS_STARTING); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->SetOrientation(me->GetAngle(pTarget)); + DoCast(me, SPELL_WAILING_SOULS_BEAM); + } + + beamAngle = me->GetOrientation(); + + beamAngleDiff = PI/30.0f; // PI/2 in 15 sec = PI/30 per tick + if (RAND(true,false)) + beamAngleDiff = -beamAngleDiff; + + me->InterruptNonMeleeSpells(false); + me->SetReactState(REACT_PASSIVE); + + //Remove any target + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + me->GetMotionMaster()->Clear(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + wailingSoulTick = 15; + events.DelayEvents(18000); // no other events during wailing souls + events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3000); // first one after 3 secs. + break; + + case EVENT_WAILING_SOULS_TICK: + beamAngle += beamAngleDiff; + me->SetOrientation(beamAngle); + me->StopMoving(); + + DoCast(me, SPELL_WAILING_SOULS); + + if (--wailingSoulTick) + events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 1000); + else + { + me->SetReactState(REACT_AGGRESSIVE); + me->SetDisplayId(DISPLAY_ANGER); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->GetMotionMaster()->MoveChase(me->getVictim()); + events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); + } + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_devourer_of_souls(Creature* pCreature) +{ + return new boss_devourer_of_soulsAI(pCreature); +} + +void AddSC_boss_devourer_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_devourer_of_souls"; + newscript->GetAI = &GetAI_boss_devourer_of_souls; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp new file mode 100644 index 00000000000..5c85da69898 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp @@ -0,0 +1,899 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +enum Spells +{ + //Spiteful Apparition + SPELL_SPITE = 68895, + H_SPELL_SPITE = 70212, + + //Spectral Warden + SPELL_VEIL_OF_SHADOWS = 69633, + SPELL_WAIL_OF_SOULS = 69148, + H_SPELL_WAIL_OF_SOULS = 70210, + + //Soulguard Watchman + SPELL_SHROUD_OF_RUNES = 69056, + SPELL_UNHOLY_RAGE = 69053, + + //Soulguard Reaper + SPELL_FROST_NOVA = 69060, + H_SPELL_FROST_NOVA = 70209, + SPELL_SHADOW_LANCE = 69058, + + //Soulguard Bonecaster + SPELL_BONE_VOLLEY = 69080, + H_SPELL_BONE_VOLLEY = 70206, + SPELL_RAISE_DEAD = 69562, + SPELL_SHIELD_OF_BONES = 69069, + H_SPELL_SHIELD_OF_BONES = 70207, + + //Soulguard Animator + // Raise dead 69562 + SPELL_SHADOW_BOLT = 69068, + H_SPELL_SHADOW_BOLT = 70208, + SPELL_SOUL_SICKNESS = 69131, + SPELL_SOUL_SIPHON = 69128, + + //Soulguard Adept + //Raise dead 69562 + //Shadow Bolt 69068/70208 + SPELL_DRAIN_LIFE = 69066, + H_SPELL_DRAIN_LIFE = 70213, + SPELL_SHADOW_MEND = 69564, + H_SPELL_SHADOW_MEND = 70205, + + //Soul Horror + SPELL_SOUL_STRIKE = 69088, + H_SPELL_SOUL_STRIKE = 70211, +}; + +enum Events +{ + EVENT_NONE, + + // Jaina/Sylvanas Intro + EVENT_INTRO_1, + EVENT_INTRO_2, + EVENT_INTRO_3, + EVENT_INTRO_4, + EVENT_INTRO_5, + EVENT_INTRO_6, + EVENT_INTRO_7, + EVENT_INTRO_8, + + //Spiteful Apparition + EVENT_SPITE, + + //Spectral Warden + EVENT_VEIL_OF_SHADOWS, + EVENT_WAIL_OF_SOULS, + + //Soulguard Watchman + EVENT_SHROUD_OF_RUNES, + EVENT_UNHOLY_RAGE, + + //Soulguard Reaper + EVENT_FROST_NOVA, + EVENT_SHADOW_LANCE, + + //Soulguard Bonecaster + EVENT_BONE_VOLLEY, + EVENT_RAISE_DEAD, + EVENT_SHIELD_OF_BONES, + + //Soulguard Animator + EVENT_SHADOW_BOLT, + EVENT_SOUL_SICKNESS, + EVENT_SOUL_SIPHON, + + //Soulguard Adept + EVENT_DRAIN_LIFE, + EVENT_SHADOW_MEND, + + //Soul Horror + EVENT_SOUL_STRIKE, +}; + +/****************************************SYLVANAS************************************/ +#define GOSSIP_SYLVANAS_ITEM "What would you have of me, Banshee Queen?" +#define GOSSIP_JAINA_ITEM "What would you have of me, my lady?" + +enum Yells +{ + SAY_JAINA_INTRO_1 = -1632040, + SAY_JAINA_INTRO_2 = -1632041, + SAY_JAINA_INTRO_3 = -1632042, + SAY_JAINA_INTRO_4 = -1632043, + SAY_JAINA_INTRO_5 = -1632044, + SAY_JAINA_INTRO_6 = -1632045, + SAY_JAINA_INTRO_7 = -1632046, + SAY_JAINA_INTRO_8 = -1632047, + + SAY_SYLVANAS_INTRO_1 = -1632050, + SAY_SYLVANAS_INTRO_2 = -1632051, + SAY_SYLVANAS_INTRO_3 = -1632052, + SAY_SYLVANAS_INTRO_4 = -1632053, + SAY_SYLVANAS_INTRO_5 = -1632054, + SAY_SYLVANAS_INTRO_6 = -1632055, +}; + +enum eSylvanas +{ + GOSSIP_SPEECHINTRO = 13525, + ACTION_INTRO, +}; + +enum Phase +{ + PHASE_NORMAL, + PHASE_INTRO, +}; + +struct npc_sylvanas_fosAI: public ScriptedAI +{ + npc_sylvanas_fosAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + ScriptedInstance* pInstance; + + EventMap events; + Phase phase; + + void Reset() + { + events.Reset(); + phase = PHASE_NORMAL; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_INTRO: + { + phase = PHASE_INTRO; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.Reset(); + events.ScheduleEvent(EVENT_INTRO_1, 1000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_INTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_INTRO_1: + DoScriptText(SAY_SYLVANAS_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_2, 11500); + break; + + case EVENT_INTRO_2: + DoScriptText(SAY_SYLVANAS_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_3, 10500); + break; + + case EVENT_INTRO_3: + DoScriptText(SAY_SYLVANAS_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_4, 9500); + break; + + case EVENT_INTRO_4: + DoScriptText(SAY_SYLVANAS_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_5, 10500); + break; + + case EVENT_INTRO_5: + DoScriptText(SAY_SYLVANAS_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_6, 9500); + break; + + case EVENT_INTRO_6: + DoScriptText(SAY_SYLVANAS_INTRO_6, me); + // End of Intro + phase = PHASE_NORMAL; + break; + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + //if (me->hasUnitState(UNIT_STAT_CASTING)) + // return; + + //while (uint32 eventId = events.ExecuteEvent()) + //{ + // switch(eventId) + // { + // } + //} + + DoMeleeAttackIfReady(); + } +}; + +struct npc_jaina_fosAI: public ScriptedAI +{ + npc_jaina_fosAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + ScriptedInstance* pInstance; + + EventMap events; + Phase phase; + + void Reset() + { + events.Reset(); + phase = PHASE_NORMAL; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_INTRO: + { + phase = PHASE_INTRO; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.Reset(); + events.ScheduleEvent(EVENT_INTRO_1, 1000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_INTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_INTRO_1: + DoScriptText(SAY_JAINA_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_2, 8000); + break; + + case EVENT_INTRO_2: + DoScriptText(SAY_JAINA_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_3, 8500); + break; + + case EVENT_INTRO_3: + DoScriptText(SAY_JAINA_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_4, 8000); + break; + + case EVENT_INTRO_4: + DoScriptText(SAY_JAINA_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_5, 10000); + break; + + case EVENT_INTRO_5: + DoScriptText(SAY_JAINA_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_6, 8000); + break; + + case EVENT_INTRO_6: + DoScriptText(SAY_JAINA_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_7, 12000); + break; + + case EVENT_INTRO_7: + DoScriptText(SAY_JAINA_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_8, 8000); + break; + + case EVENT_INTRO_8: + DoScriptText(SAY_JAINA_INTRO_8, me); + // End of Intro + phase = PHASE_NORMAL; + break; + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + //if (me->hasUnitState(UNIT_STAT_CASTING)) + // return; + + //while (uint32 eventId = events.ExecuteEvent()) + //{ + // switch(eventId) + // { + // } + //} + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->GetEntry() == NPC_JAINA_PART1) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_JAINA_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + else + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SYLVANAS_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_INTRO); + break; + } + + return true; +} + +struct mob_spiteful_apparitionAI: public ScriptedAI +{ + mob_spiteful_apparitionAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SPITE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SPITE: + DoCast(me->getVictim(), SPELL_SPITE); + events.RescheduleEvent(EVENT_SPITE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_spectral_wardenAI: public ScriptedAI +{ + mob_spectral_wardenAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_VEIL_OF_SHADOWS, 5000); + events.ScheduleEvent(EVENT_WAIL_OF_SOULS, 10000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_VEIL_OF_SHADOWS: + DoCast(me->getVictim(), SPELL_VEIL_OF_SHADOWS); + events.RescheduleEvent(EVENT_VEIL_OF_SHADOWS, 10000); + return; + case EVENT_WAIL_OF_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_WAIL_OF_SOULS); + events.RescheduleEvent(EVENT_WAIL_OF_SOULS, 5000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_watchmanAI: public ScriptedAI +{ + mob_soulguard_watchmanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHROUD_OF_RUNES, 1000); + events.ScheduleEvent(EVENT_UNHOLY_RAGE, 1000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHROUD_OF_RUNES: + DoCast(me, SPELL_SHROUD_OF_RUNES); + events.RescheduleEvent(EVENT_SHROUD_OF_RUNES, 5000); + return; + case EVENT_UNHOLY_RAGE: + DoCast(me, SPELL_UNHOLY_RAGE); + events.RescheduleEvent(EVENT_UNHOLY_RAGE, 99999); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_reaperAI: public ScriptedAI +{ + mob_soulguard_reaperAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROST_NOVA, 8000); + events.ScheduleEvent(EVENT_SHADOW_LANCE, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROST_NOVA: + DoCast(me, SPELL_FROST_NOVA); + events.RescheduleEvent(EVENT_FROST_NOVA, 9600); + return; + case EVENT_SHADOW_LANCE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_LANCE); + events.RescheduleEvent(EVENT_SHADOW_LANCE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_bonecasterAI: public ScriptedAI +{ + mob_soulguard_bonecasterAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BONE_VOLLEY, 6000); + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHIELD_OF_BONES, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BONE_VOLLEY: + DoCastAOE(SPELL_BONE_VOLLEY); + events.RescheduleEvent(EVENT_BONE_VOLLEY, 7000); + return; + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHIELD_OF_BONES: + DoCast(me, SPELL_SHIELD_OF_BONES); + events.RescheduleEvent(EVENT_SHIELD_OF_BONES, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_animatorAI: public ScriptedAI +{ + mob_soulguard_animatorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 5000); + events.ScheduleEvent(EVENT_SOUL_SICKNESS, 8000); + events.ScheduleEvent(EVENT_SOUL_SIPHON, 10000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); + return; + case EVENT_SOUL_SICKNESS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SOUL_SICKNESS); + events.RescheduleEvent(EVENT_SOUL_SICKNESS, 10000); + return; + case EVENT_SOUL_SIPHON: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SOUL_SIPHON); + events.RescheduleEvent(EVENT_SOUL_SIPHON, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_adeptAI: public ScriptedAI +{ + mob_soulguard_adeptAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 8000); + events.ScheduleEvent(EVENT_DRAIN_LIFE, 7000); + events.ScheduleEvent(EVENT_SHADOW_MEND, 35000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 4000); + return; + case EVENT_DRAIN_LIFE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DRAIN_LIFE); + events.RescheduleEvent(EVENT_DRAIN_LIFE, 9000); + return; + case EVENT_SHADOW_MEND: + DoCast(me, SPELL_SHADOW_MEND); + events.RescheduleEvent(EVENT_SHADOW_MEND, 20000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soul_horrorAI: public ScriptedAI +{ + mob_soul_horrorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SOUL_STRIKE, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SOUL_STRIKE: + DoCast(me->getVictim(), SPELL_SOUL_STRIKE); + events.RescheduleEvent(EVENT_SOUL_STRIKE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_jaina_fosAI(Creature* pCreature) +{ + return new npc_jaina_fosAI(pCreature); +}; + +CreatureAI* GetAI_npc_sylvanas_fosAI(Creature* pCreature) +{ + return new npc_sylvanas_fosAI(pCreature); +}; + +CreatureAI* GetAI_mob_spiteful_apparitionAI(Creature* pCreature) +{ + return new mob_spiteful_apparitionAI(pCreature); +} + +CreatureAI* GetAI_mob_spectral_wardenAI(Creature* pCreature) +{ + return new mob_spectral_wardenAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_watchmanAI(Creature* pCreature) +{ + return new mob_soulguard_watchmanAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_reaperAI(Creature* pCreature) +{ + return new mob_soulguard_reaperAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_bonecasterAI(Creature* pCreature) +{ + return new mob_soulguard_bonecasterAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_animatorAI(Creature* pCreature) +{ + return new mob_soulguard_animatorAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_adeptAI(Creature* pCreature) +{ + return new mob_soulguard_adeptAI(pCreature); +} + +CreatureAI* GetAI_mob_soul_horrorAI(Creature* pCreature) +{ + return new mob_soul_horrorAI(pCreature); +} + +void AddSC_forge_of_souls() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sylvanas_fos"; + newscript->GetAI = &GetAI_npc_sylvanas_fosAI; + newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_fos"; + newscript->GetAI = &GetAI_npc_jaina_fosAI; + newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_spiteful_apparition"; + newscript->GetAI = &GetAI_mob_spiteful_apparitionAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_spectral_warden"; + newscript->GetAI = &GetAI_mob_spectral_wardenAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_watchman"; + newscript->GetAI = &GetAI_mob_soulguard_watchmanAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_reaper"; + newscript->GetAI = &GetAI_mob_soulguard_reaperAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_bonecaster"; + newscript->GetAI = &GetAI_mob_soulguard_bonecasterAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_animator"; + newscript->GetAI = &GetAI_mob_soulguard_animatorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_adept"; + newscript->GetAI = &GetAI_mob_soulguard_adeptAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soul_horror"; + newscript->GetAI = &GetAI_mob_soul_horrorAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h new file mode 100644 index 00000000000..e0479eb4d2b --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_FORGE_OF_SOULS_H +#define DEF_FORGE_OF_SOULS_H + +enum Data +{ + DATA_BRONJAHM_EVENT, + DATA_DEVOURER_EVENT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_BRONJAHM, + DATA_DEVOURER, +}; + +enum Creatures +{ + CREATURE_BRONJAHM = 36497, + CREATURE_DEVOURER = 36502, + + NPC_SYLVANAS_PART1 = 37596, + NPC_SYLVANAS_PART2 = 38161, + NPC_JAINA_PART1 = 37597, + NPC_JAINA_PART2 = 38160, + NPC_KALIRA = 37583, + NPC_ELANDRA = 37774, + NPC_LORALEN = 37779, + NPC_KORELN = 37582, + NPC_CHAMPION_1_HORDE = 37584, + NPC_CHAMPION_2_HORDE = 37587, + NPC_CHAMPION_3_HORDE = 37588, + NPC_CHAMPION_1_ALLIANCE = 37496, + NPC_CHAMPION_2_ALLIANCE = 37497, +}; +#endif diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp new file mode 100644 index 00000000000..67a6cdb4579 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp @@ -0,0 +1,168 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +#define MAX_ENCOUNTER 2 + +/* Forge of Souls encounters: +0- Bronjahm, The Godfather of Souls +1- The Devourer of Souls +*/ + +struct instance_forge_of_souls : public ScriptedInstance +{ + instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiBronjahm; + uint64 uiDevourer; + + uint32 uiEncounter[MAX_ENCOUNTER]; + uint32 uiTeamInInstance; + + void Initialize() + { + uiBronjahm = 0; + uiDevourer = 0; + + uiTeamInInstance = 0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + + if (!players.isEmpty()) + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + + switch(pCreature->GetEntry()) + { + case CREATURE_BRONJAHM: + uiBronjahm = pCreature->GetGUID(); + break; + case CREATURE_DEVOURER: + uiDevourer = pCreature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_BRONJAHM_EVENT: + uiEncounter[0] = data; + break; + case DATA_DEVOURER_EVENT: + uiEncounter[1] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_BRONJAHM_EVENT: return uiEncounter[0]; + case DATA_DEVOURER_EVENT: return uiEncounter[1]; + case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_BRONJAHM: return uiBronjahm; + case DATA_DEVOURER: return uiBronjahm; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "F S " << uiEncounter[0] << " " << uiEncounter[1]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; + + if (dataHead1 == 'F' && dataHead2 == 'S') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap) +{ + return new instance_forge_of_souls(pMap); +} + +void AddSC_instance_forge_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_forge_of_souls"; + newscript->GetInstanceData = &GetInstanceData_instance_forge_of_souls; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp new file mode 100644 index 00000000000..c9978faca6e --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_AGGRO = -1668050, + SAY_SLAY_1 = -1668051, + SAY_SLAY_2 = -1668052, + SAY_DEATH = -1668053, + SAY_IMPENDING_DESPAIR = -1668054, + SAY_DEFILING_HORROR = -1668055, +}; + +enum Spells +{ + SPELL_QUIVERING_STRIKE = 72422, + SPELL_IMPENDING_DESPAIR = 72426, + SPELL_DEFILING_HORROR = 72435, + SPELL_HOPELESSNESS = 72395, + H_SPELL_HOPELESSNESS = 72390, // TODO: not in dbc. Add in DB. +}; + +enum Events +{ + EVENT_NONE, + EVENT_QUIVERING_STRIKE, + EVENT_IMPENDING_DESPAIR, + EVENT_DEFILING_HORROR, +}; + +struct boss_falricAI : public boss_horAI +{ + boss_falricAI(Creature *pCreature) : boss_horAI(pCreature) {} + + uint8 uiHopelessnessCount; + + void Reset() + { + boss_horAI::Reset(); + + uiHopelessnessCount = 0; + + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000); + events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000); + events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_QUIVERING_STRIKE: + DoCast(SPELL_QUIVERING_STRIKE); + events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000); + break; + case EVENT_IMPENDING_DESPAIR: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + { + DoScriptText(SAY_IMPENDING_DESPAIR, me); + DoCast(pTarget, SPELL_IMPENDING_DESPAIR); + } + events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000); + break; + case EVENT_DEFILING_HORROR: + DoCast(SPELL_DEFILING_HORROR); + events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. + break; + } + + if ((uiHopelessnessCount < 1 && HealthBelowPct(66)) + || (uiHopelessnessCount < 2 && HealthBelowPct(33)) + || (uiHopelessnessCount < 3 && HealthBelowPct(10))) + { + uiHopelessnessCount++; + DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS,H_SPELL_HOPELESSNESS)); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_falric(Creature* pCreature) +{ + return new boss_falricAI(pCreature); +} + +void AddSC_boss_falric() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_falric"; + newscript->GetAI = &GetAI_boss_falric; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp new file mode 100644 index 00000000000..95fb2737ce9 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp @@ -0,0 +1,133 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_AGGRO = -1668060, + SAY_SLAY_1 = -1668061, + SAY_SLAY_2 = -1668062, + SAY_DEATH = -1668063, + SAY_CORRUPTED_FLESH_1 = -1668064, + SAY_CORRUPTED_FLESH_2 = -1668065, +}; + +enum Spells +{ + SPELL_OBLITERATE = 72360, + SPELL_WELL_OF_CORRUPTION = 72362, + SPELL_CORRUPTED_FLESH = 72363, + SPELL_SHARED_SUFFERING = 72368, +}; + +enum Events +{ + EVENT_NONE, + EVENT_OBLITERATE, + EVENT_WELL_OF_CORRUPTION, + EVENT_CORRUPTED_FLESH, + EVENT_SHARED_SUFFERING, +}; + +struct boss_marwynAI : public boss_horAI +{ + boss_marwynAI(Creature *pCreature) : boss_horAI(pCreature) {} + + void Reset() + { + boss_horAI::Reset(); + + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_OBLITERATE, 30000); // TODO Check timer + events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); + events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); + events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); // TODO Check timer + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_OBLITERATE: + DoCast(SPELL_OBLITERATE); + events.ScheduleEvent(EVENT_OBLITERATE, 30000); + break; + case EVENT_WELL_OF_CORRUPTION: + DoCast(SPELL_WELL_OF_CORRUPTION); + events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); + break; + case EVENT_CORRUPTED_FLESH: + DoScriptText(RAND(SAY_CORRUPTED_FLESH_1,SAY_CORRUPTED_FLESH_2), me); + DoCast(SPELL_CORRUPTED_FLESH); + events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); + break; + case EVENT_SHARED_SUFFERING: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHARED_SUFFERING); + events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_marwyn(Creature* pCreature) +{ + return new boss_marwynAI(pCreature); +} + +void AddSC_boss_marwyn() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_marwyn"; + newscript->GetAI = &GetAI_boss_marwyn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp new file mode 100644 index 00000000000..fb3d3d5d752 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp @@ -0,0 +1,1022 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_JAINA_INTRO_1 = -1668001, + SAY_JAINA_INTRO_2 = -1668002, + SAY_JAINA_INTRO_3 = -1668003, + SAY_JAINA_INTRO_4 = -1668004, + SAY_UTHER_INTRO_A2_1 = -1668005, + SAY_JAINA_INTRO_5 = -1668006, + SAY_UTHER_INTRO_A2_2 = -1668007, + SAY_JAINA_INTRO_6 = -1668008, + SAY_UTHER_INTRO_A2_3 = -1668009, + SAY_JAINA_INTRO_7 = -1668010, + SAY_UTHER_INTRO_A2_4 = -1668011, + SAY_JAINA_INTRO_8 = -1668012, + SAY_UTHER_INTRO_A2_5 = -1668013, + SAY_JAINA_INTRO_9 = -1668014, + SAY_UTHER_INTRO_A2_6 = -1668015, + SAY_UTHER_INTRO_A2_7 = -1668016, + SAY_JAINA_INTRO_10 = -1668017, + SAY_UTHER_INTRO_A2_8 = -1668018, + SAY_JAINA_INTRO_11 = -1668019, + SAY_UTHER_INTRO_A2_9 = -1668020, + + SAY_SYLVANAS_INTRO_1 = -1668021, + SAY_SYLVANAS_INTRO_2 = -1668022, + SAY_SYLVANAS_INTRO_3 = -1668023, + SAY_UTHER_INTRO_H2_1 = -1668024, + SAY_SYLVANAS_INTRO_4 = -1668025, + SAY_UTHER_INTRO_H2_2 = -1668026, + SAY_SYLVANAS_INTRO_5 = -1668027, + SAY_UTHER_INTRO_H2_3 = -1668028, + SAY_SYLVANAS_INTRO_6 = -1668029, + SAY_UTHER_INTRO_H2_4 = -1668030, + SAY_SYLVANAS_INTRO_7 = -1668031, + SAY_UTHER_INTRO_H2_5 = -1668032, + SAY_UTHER_INTRO_H2_6 = -1668033, + SAY_SYLVANAS_INTRO_8 = -1668034, + SAY_UTHER_INTRO_H2_7 = -1668035, + + SAY_LK_INTRO_1 = -1668036, + SAY_LK_INTRO_2 = -1668037, + SAY_LK_INTRO_3 = -1668038, + SAY_FALRIC_INTRO_1 = -1668039, + SAY_MARWYN_INTRO_1 = -1668040, + SAY_FALRIC_INTRO_2 = -1668041, + + SAY_JAINA_INTRO_END = -1668042, + SAY_SYLVANAS_INTRO_END = -1668043, +}; + +enum Events +{ + EVENT_NONE, + + EVENT_START_INTRO, + EVENT_SKIP_INTRO, + + EVENT_INTRO_A2_1, + EVENT_INTRO_A2_2, + EVENT_INTRO_A2_3, + EVENT_INTRO_A2_4, + EVENT_INTRO_A2_5, + EVENT_INTRO_A2_6, + EVENT_INTRO_A2_7, + EVENT_INTRO_A2_8, + EVENT_INTRO_A2_9, + EVENT_INTRO_A2_10, + EVENT_INTRO_A2_11, + EVENT_INTRO_A2_12, + EVENT_INTRO_A2_13, + EVENT_INTRO_A2_14, + EVENT_INTRO_A2_15, + EVENT_INTRO_A2_16, + EVENT_INTRO_A2_17, + EVENT_INTRO_A2_18, + EVENT_INTRO_A2_19, + + EVENT_INTRO_H2_1, + EVENT_INTRO_H2_2, + EVENT_INTRO_H2_3, + EVENT_INTRO_H2_4, + EVENT_INTRO_H2_5, + EVENT_INTRO_H2_6, + EVENT_INTRO_H2_7, + EVENT_INTRO_H2_8, + EVENT_INTRO_H2_9, + EVENT_INTRO_H2_10, + EVENT_INTRO_H2_11, + EVENT_INTRO_H2_12, + EVENT_INTRO_H2_13, + EVENT_INTRO_H2_14, + EVENT_INTRO_H2_15, + + EVENT_INTRO_LK_1, + EVENT_INTRO_LK_2, + EVENT_INTRO_LK_3, + EVENT_INTRO_LK_4, + EVENT_INTRO_LK_5, + EVENT_INTRO_LK_6, + EVENT_INTRO_LK_7, + EVENT_INTRO_LK_8, + EVENT_INTRO_LK_9, + + EVENT_INTRO_END, +}; + +enum eEnum +{ + ACTION_START_INTRO, + ACTION_SKIP_INTRO, + + QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710, + QUEST_DELIVRANCE_FROM_THE_PIT_H2 = 24712, + QUEST_WRATH_OF_THE_LICH_KING_A2 = 24500, + QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802, +}; + +static Position HallsofReflectionLocs[]= +{ + {5283.234863, 1990.946777, 707.695679, 0.929097}, // 2 Loralen Follows + {5408.031250, 2102.918213, 707.695251, 0.792756}, // 9 Sylvanas Follows + {5401.866699, 2110.837402, 707.695251, 0.800610}, // 10 Loralen follows +}; + +static Position SpawnPos = {5262.540527, 1949.693726, 707.695007, 0.808736}; // Jaina/Sylvanas Beginning Position +static Position MoveThronePos = {5306.952148, 1998.499023, 709.341431, 1.277278}; // Jaina/Sylvanas walks to throne +static Position UtherSpawnPos = {5308.310059, 2003.857178, 709.341431, 4.650315}; +static Position LichKingSpawnPos = {5362.917480, 2062.307129, 707.695374, 3.945812}; +static Position LichKingMoveThronePos = {5312.080566, 2009.172119, 709.341431, 3.973301}; // Lich King walks to throne +static Position LichKingMoveAwayPos = {5400.069824, 2102.7131689, 707.69525, 0.843803}; // Lich King walks away + +// AI of Part1: handle the intro till start of gauntlet event. +struct npc_jaina_or_sylvanas_horAI : public ScriptedAI +{ + npc_jaina_or_sylvanas_horAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint64 uiUther; + uint64 uiLichKing; + + EventMap events; + + void Reset() + { + events.Reset(); + + uiUther = 0; + uiLichKing = 0; + + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetVisibility(VISIBILITY_ON); + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_START_INTRO: + events.ScheduleEvent(EVENT_START_INTRO, 0); + break; + case ACTION_SKIP_INTRO: + events.ScheduleEvent(EVENT_SKIP_INTRO, 0); + break; + } + } + + void UpdateAI(const uint32 diff) + { + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_START_INTRO: + me->GetMotionMaster()->MovePoint(0, MoveThronePos); + // Begining of intro is differents between factions as the speech sequence and timers are differents. + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + events.ScheduleEvent(EVENT_INTRO_A2_1, 0); + else + events.ScheduleEvent(EVENT_INTRO_H2_1, 0); + break; + + // A2 Intro Events + case EVENT_INTRO_A2_1: + DoScriptText(SAY_JAINA_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_A2_2, 5000); + break; + case EVENT_INTRO_A2_2: + DoScriptText(SAY_JAINA_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_A2_3, 10000); + break; + case EVENT_INTRO_A2_3: + // TODO: she's doing some kind of spell casting emote + pInstance->HandleGameObject(pInstance->GetData64(DATA_FROSTMOURNE), true); + events.ScheduleEvent(EVENT_INTRO_A2_4, 10000); + break; + case EVENT_INTRO_A2_4: + // spawn UTHER during speach 2 + if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pUther->GetMotionMaster()->MoveIdle(); + pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas + uiUther = pUther->GetGUID(); + } + events.ScheduleEvent(EVENT_INTRO_A2_5, 2000); + break; + case EVENT_INTRO_A2_5: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_1, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_6, 3000); + break; + case EVENT_INTRO_A2_6: + DoScriptText(SAY_JAINA_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_A2_7, 6000); + break; + case EVENT_INTRO_A2_7: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_2, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_8, 6500); + break; + case EVENT_INTRO_A2_8: + DoScriptText(SAY_JAINA_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_A2_9, 2000); + break; + case EVENT_INTRO_A2_9: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_3, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_10, 9000); + break; + case EVENT_INTRO_A2_10: + DoScriptText(SAY_JAINA_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_A2_11, 5000); + break; + case EVENT_INTRO_A2_11: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_4, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_12, 11000); + break; + case EVENT_INTRO_A2_12: + DoScriptText(SAY_JAINA_INTRO_8, me); + events.ScheduleEvent(EVENT_INTRO_A2_13, 4000); + break; + case EVENT_INTRO_A2_13: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_5, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_14, 12500); + break; + case EVENT_INTRO_A2_14: + DoScriptText(SAY_JAINA_INTRO_9, me); + events.ScheduleEvent(EVENT_INTRO_A2_15, 10000); + break; + case EVENT_INTRO_A2_15: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_6, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_16, 22000); + break; + case EVENT_INTRO_A2_16: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_7, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_17, 4000); + break; + case EVENT_INTRO_A2_17: + DoScriptText(SAY_JAINA_INTRO_10, me); + events.ScheduleEvent(EVENT_INTRO_A2_18, 2000); + break; + case EVENT_INTRO_A2_18: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); + DoScriptText(SAY_UTHER_INTRO_A2_8, pUther); + } + events.ScheduleEvent(EVENT_INTRO_A2_19, 11000); + break; + case EVENT_INTRO_A2_19: + DoScriptText(SAY_JAINA_INTRO_11, me); + events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + break; + + // H2 Intro Events + case EVENT_INTRO_H2_1: + DoScriptText(SAY_SYLVANAS_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_H2_2, 8000); + break; + case EVENT_INTRO_H2_2: + DoScriptText(SAY_SYLVANAS_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_H2_3, 6000); + break; + case EVENT_INTRO_H2_3: + DoScriptText(SAY_SYLVANAS_INTRO_3, me); + // TODO: she's doing some kind of spell casting emote + events.ScheduleEvent(EVENT_INTRO_H2_4, 6000); + break; + case EVENT_INTRO_H2_4: + // spawn UTHER during speach 2 + if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pUther->GetMotionMaster()->MoveIdle(); + pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas + uiUther = pUther->GetGUID(); + } + events.ScheduleEvent(EVENT_INTRO_H2_5, 2000); + break; + case EVENT_INTRO_H2_5: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_1, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_6, 11000); + break; + case EVENT_INTRO_H2_6: + DoScriptText(SAY_SYLVANAS_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_H2_7, 3000); + break; + case EVENT_INTRO_H2_7: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_2, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_8, 6000); + break; + case EVENT_INTRO_H2_8: + DoScriptText(SAY_SYLVANAS_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_H2_9, 5000); + break; + case EVENT_INTRO_H2_9: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_3, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_10, 19000); + break; + case EVENT_INTRO_H2_10: + DoScriptText(SAY_SYLVANAS_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_H2_11, 1500); + break; + case EVENT_INTRO_H2_11: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_4, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_12, 19500); + break; + case EVENT_INTRO_H2_12: + DoScriptText(SAY_SYLVANAS_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_H2_13, 2000); + break; + case EVENT_INTRO_H2_13: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); + DoScriptText(SAY_UTHER_INTRO_H2_5, pUther); + } + events.ScheduleEvent(EVENT_INTRO_H2_14, 12000); + break; + case EVENT_INTRO_H2_14: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_6, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_15, 8000); + break; + case EVENT_INTRO_H2_15: + DoScriptText(SAY_SYLVANAS_INTRO_8, me); + events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + break; + + // Remaining Intro Events common for both faction + case EVENT_INTRO_LK_1: + // Spawn LK in front of door, and make him move to the sword. + if (Creature* pLichKing = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pLichKing->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); + pLichKing->SetReactState(REACT_PASSIVE); + uiLichKing = pLichKing->GetGUID(); + } + + if (Creature* pUther = me->GetCreature(*me, uiUther)) + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + DoScriptText(SAY_UTHER_INTRO_A2_9, pUther); + else + DoScriptText(SAY_UTHER_INTRO_H2_7, pUther); + + events.ScheduleEvent(EVENT_INTRO_LK_2, 11000); + break; + + case EVENT_INTRO_LK_2: + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + DoScriptText(SAY_LK_INTRO_1, pLichKing); + events.ScheduleEvent(EVENT_INTRO_LK_3, 2000); + break; + + case EVENT_INTRO_LK_3: + // The Lich King banishes Uther to the abyss. + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->DisappearAndDie(); + uiUther = 0; + } + + // He steps forward and removes the runeblade from the heap of skulls. + + events.ScheduleEvent(EVENT_INTRO_LK_4, 4000); + break; + + case EVENT_INTRO_LK_4: + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + DoScriptText(SAY_LK_INTRO_2, pLichKing); + events.ScheduleEvent(EVENT_INTRO_LK_5, 10000); + break; + + case EVENT_INTRO_LK_5: + // summon Falric and Marwyn. then go back to the door + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + pFalric->SetVisibility(VISIBILITY_ON); + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + pMarwyn->SetVisibility(VISIBILITY_ON); + + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + { + pLichKing->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + DoScriptText(SAY_LK_INTRO_3, pLichKing); + } + + events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); + break; + + case EVENT_INTRO_LK_6: + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + DoScriptText(SAY_FALRIC_INTRO_1, pFalric); + + events.ScheduleEvent(EVENT_INTRO_LK_7, 2000); + break; + + case EVENT_INTRO_LK_7: + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + DoScriptText(SAY_MARWYN_INTRO_1, pMarwyn); + + events.ScheduleEvent(EVENT_INTRO_LK_8, 2000); + break; + + case EVENT_INTRO_LK_8: + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + DoScriptText(SAY_FALRIC_INTRO_2, pFalric); + + events.ScheduleEvent(EVENT_INTRO_LK_9, 5000); + break; + + case EVENT_INTRO_LK_9: + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + DoScriptText(SAY_JAINA_INTRO_END, me); + else + DoScriptText(SAY_SYLVANAS_INTRO_END, me); + + me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + // TODO: Loralen/Koreln shall run also + events.ScheduleEvent(EVENT_INTRO_END, 10000); + break; + + case EVENT_INTRO_END: + if (pInstance) + pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave + + // Loralen or Koreln disappearAndDie() + me->DisappearAndDie(); + break; + + case EVENT_SKIP_INTRO: + // TODO: implement + + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + pFalric->SetVisibility(VISIBILITY_ON); + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + pMarwyn->SetVisibility(VISIBILITY_ON); + + me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + // TODO: Loralen/Koreln shall run also + + events.ScheduleEvent(EVENT_INTRO_END, 15000); + break; + } + } +}; + +bool GossipHello_npc_sylvanas_hor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_H2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + // once last quest is completed, she offers this shortcut of the starting event + if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_H2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Dark Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + + return true; +} + +bool GossipHello_npc_jaina_hor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_A2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + // once last quest of the series is completed, she offers this shortcut of the starting event + if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_A2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "My Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_or_sylvanas_hor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_START_INTRO); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_SKIP_INTRO); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + } + + return true; +} + +enum TrashSpells +{ + // Ghostly Priest + SPELL_SHADOW_WORD_PAIN = 72318, + SPELL_CIRCLE_OF_DESTRUCTION = 72320, + SPELL_COWER_IN_FEAR = 72321, + SPELL_DARK_MENDING = 72322, + + // Phantom Mage + SPELL_FIREBALL = 72163, + SPELL_FLAMESTRIKE = 72169, + SPELL_FROSTBOLT = 72166, + SPELL_CHAINS_OF_ICE = 72121, + SPELL_HALLUCINATION = 72342, + + // Phantom Hallucination (same as phantom mage + HALLUCINATION_2 when dies) + SPELL_HALLUCINATION_2 = 72344, + + // Shadowy Mercenary + SPELL_SHADOW_STEP = 72326, + SPELL_DEADLY_POISON = 72329, + SPELL_ENVENOMED_DAGGER_THROW = 72333, + SPELL_KIDNEY_SHOT = 72335, + + // Spectral Footman + SPELL_SPECTRAL_STRIKE = 72198, + SPELL_SHIELD_BASH = 72194, + SPELL_TORTURED_ENRAGE = 72203, + + // Tortured Rifleman + SPELL_SHOOT = 72208, + SPELL_CURSED_ARROW = 72222, + SPELL_FROST_TRAP = 72215, + SPELL_ICE_SHOT = 72268, +}; + +enum TrashEvents +{ + EVENT_TRASH_NONE, + + // Ghostly Priest + EVENT_SHADOW_WORD_PAIN, + EVENT_CIRCLE_OF_DESTRUCTION, + EVENT_COWER_IN_FEAR, + EVENT_DARK_MENDING, + + // Phantom Mage + EVENT_FIREBALL, + EVENT_FLAMESTRIKE, + EVENT_FROSTBOLT, + EVENT_CHAINS_OF_ICE, + EVENT_HALLUCINATION, + + // Shadowy Mercenary + EVENT_SHADOW_STEP, + EVENT_DEADLY_POISON, + EVENT_ENVENOMED_DAGGER_THROW, + EVENT_KIDNEY_SHOT, + + // Spectral Footman + EVENT_SPECTRAL_STRIKE, + EVENT_SHIELD_BASH, + EVENT_TORTURED_ENRAGE, + + // Tortured Rifleman + EVENT_SHOOT, + EVENT_CURSED_ARROW, + EVENT_FROST_TRAP, + EVENT_ICE_SHOT, +}; + +struct npc_ghostly_priestAI: public ScriptedAI +{ + npc_ghostly_priestAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); // TODO: adjust timers + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_WORD_PAIN: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); + return; + case EVENT_CIRCLE_OF_DESTRUCTION: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CIRCLE_OF_DESTRUCTION); + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + return; + case EVENT_COWER_IN_FEAR: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_COWER_IN_FEAR); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + return; + case EVENT_DARK_MENDING: + // find an ally with missing HP + if (Unit *pTarget = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000,50000))) + { + DoCast(pTarget, SPELL_DARK_MENDING); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + else + { + // no friendly unit with missing hp. re-check in just 5 sec. + events.ScheduleEvent(EVENT_DARK_MENDING, 5000); + } + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_phantom_mageAI: public ScriptedAI +{ + npc_phantom_mageAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FIREBALL, 3000); // TODO: adjust timers + events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000); + events.ScheduleEvent(EVENT_FROSTBOLT, 9000); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000); + events.ScheduleEvent(EVENT_HALLUCINATION, 40000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FIREBALL: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 15000); + return; + case EVENT_FLAMESTRIKE: + DoCast(SPELL_FLAMESTRIKE); + events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); + return; + case EVENT_FROSTBOLT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_FROSTBOLT); + events.ScheduleEvent(EVENT_FROSTBOLT, 15000); + return; + case EVENT_CHAINS_OF_ICE: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CHAINS_OF_ICE); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); + return; + case EVENT_HALLUCINATION: + DoCast(SPELL_HALLUCINATION); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_phantom_hallucinationAI: public npc_phantom_mageAI +{ + npc_phantom_hallucinationAI(Creature *c) : npc_phantom_mageAI(c) + { + } + + void JustDied(Unit * /*pWho*/) + { + DoCast(SPELL_HALLUCINATION_2); + } +}; + +struct npc_shadowy_mercenaryAI: public ScriptedAI +{ + npc_shadowy_mercenaryAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); // TODO: adjust timers + events.ScheduleEvent(EVENT_DEADLY_POISON, 5000); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_STEP: + DoCast(SPELL_SHADOW_STEP); + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); + return; + case EVENT_DEADLY_POISON: + DoCast(me->getVictim(), SPELL_DEADLY_POISON); + events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); + return; + case EVENT_ENVENOMED_DAGGER_THROW: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_ENVENOMED_DAGGER_THROW); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + return; + case EVENT_KIDNEY_SHOT: + DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_spectral_footmanAI: public ScriptedAI +{ + npc_spectral_footmanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); // TODO: adjust timers + events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SPECTRAL_STRIKE: + DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); + return; + case EVENT_SHIELD_BASH: + DoCast(me->getVictim(), SPELL_SHIELD_BASH); + events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); + return; + case EVENT_TORTURED_ENRAGE: + DoCast(SPELL_TORTURED_ENRAGE); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_tortured_riflemanAI : public ScriptedAI +{ + npc_tortured_riflemanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHOOT, 2000); // TODO: adjust timers + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + events.ScheduleEvent(EVENT_FROST_TRAP, 1000); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHOOT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHOOT); + events.ScheduleEvent(EVENT_SHOOT, 2000); + return; + case EVENT_CURSED_ARROW: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CURSED_ARROW); + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + return; + case EVENT_FROST_TRAP: + DoCast(SPELL_FROST_TRAP); + events.ScheduleEvent(EVENT_FROST_TRAP, 30000); + return; + case EVENT_ICE_SHOT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_ICE_SHOT); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_jaina_or_sylvanas_horAI(Creature* pCreature) +{ + return new npc_jaina_or_sylvanas_horAI(pCreature); +} + +CreatureAI* GetAI_npc_ghostly_priestAI(Creature* pCreature) +{ + return new npc_ghostly_priestAI(pCreature); +} + +CreatureAI* GetAI_npc_phantom_mageAI(Creature* pCreature) +{ + return new npc_phantom_mageAI(pCreature); +} + +CreatureAI* GetAI_npc_phantom_hallucinationAI(Creature* pCreature) +{ + return new npc_phantom_hallucinationAI(pCreature); +} + +CreatureAI* GetAI_npc_shadowy_mercenaryAI(Creature* pCreature) +{ + return new npc_shadowy_mercenaryAI(pCreature); +} + +CreatureAI* GetAI_npc_spectral_footmanAI(Creature* pCreature) +{ + return new npc_spectral_footmanAI(pCreature); +} + +CreatureAI* GetAI_npc_tortured_riflemanAI(Creature* pCreature) +{ + return new npc_tortured_riflemanAI(pCreature); +} + +void AddSC_halls_of_reflection() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sylvanas_hor_part1"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; + newscript->pGossipHello = &GossipHello_npc_sylvanas_hor; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_hor_part1"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; + newscript->pGossipHello = &GossipHello_npc_jaina_hor; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ghostly_priest"; + newscript->GetAI = &GetAI_npc_ghostly_priestAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_phantom_mage"; + newscript->GetAI = &GetAI_npc_phantom_mageAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_phantom_hallucination"; + newscript->GetAI = &GetAI_npc_phantom_hallucinationAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_shadowy_mercenary"; + newscript->GetAI = &GetAI_npc_shadowy_mercenaryAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_spectral_footman"; + newscript->GetAI = &GetAI_npc_spectral_footmanAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tortured_rifleman"; + newscript->GetAI = &GetAI_npc_tortured_riflemanAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h new file mode 100644 index 00000000000..46ae0cb283c --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h @@ -0,0 +1,156 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_HALLS_OF_REFLECTION_H +#define DEF_HALLS_OF_REFLECTION_H + +enum Data +{ + DATA_FALRIC_EVENT, + DATA_MARWYN_EVENT, + DATA_LICHKING_EVENT, + DATA_WAVE_COUNT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_FALRIC, + DATA_MARWYN, + DATA_LICHKING, + DATA_FROSTMOURNE, +}; + +enum Creatures +{ + NPC_FALRIC = 38112, + NPC_MARWYN = 38113, + NPC_LICH_KING_EVENT = 37226, + NPC_LICH_KING_BOSS = 36954, + + NPC_UTHER = 37225, + NPC_JAINA_PART1 = 37221, + NPC_JAINA_PART2 = 36955, + NPC_SYLVANAS_PART1 = 37223, + NPC_SYLVANAS_PART2 = 37554, + + NPC_WAVE_MERCENARY = 38177, + NPC_WAVE_FOOTMAN = 38173, + NPC_WAVE_RIFLEMAN = 38176, + NPC_WAVE_PRIEST = 38175, + NPC_WAVE_MAGE = 38172, +}; + +enum GameObjects +{ + GO_FROSTMOURNE = 202302, + GO_FROSTMOURNE_ALTAR = 202236, + GO_FRONT_DOOR = 201976, + GO_ARTHAS_DOOR = 197341, +}; + +enum HorWorldStates +{ + WORLD_STATE_HOR = 4884, + WORLD_STATE_HOR_WAVE_COUNT = 4882, +}; + +// Common actions from Instance Script to Boss Script +enum Actions +{ + ACTION_ENTER_COMBAT, +}; + +// Base class for FALRIC and MARWYN +// handled the summonList and the notification events to/from the InstanceData +struct boss_horAI : ScriptedAI +{ + boss_horAI(Creature *pCreature) : ScriptedAI(pCreature), summons(pCreature) + { + pInstance = me->GetInstanceData(); + } + + InstanceData* pInstance; + EventMap events; + SummonList summons; + + void Reset() + { + events.Reset(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + } + + void DamageTaken(Unit *pWho, uint32 &uiDamage) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + uiDamage = 0; + } + + void DoAction(const int32 actionID) + { + switch(actionID) + { + case ACTION_ENTER_COMBAT: // called by InstanceData when boss shall enter in combat. + // Just in case. Should have been done by InstanceData + me->SetVisibility(VISIBILITY_ON); + + // Reset flags + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + + if (Unit *pUnit = me->SelectNearestTarget()) + AttackStart(pUnit); + + DoZoneInCombat(); + break; + } + } + + void JustSummoned(Creature *pSummoned) + { + summons.Summon(pSummoned); + + if (Unit *pUnit = pSummoned->SelectNearestTarget()) + { + if (pSummoned->AI()) + pSummoned->AI()->AttackStart(pUnit); + else + { + pSummoned->GetMotionMaster()->MoveChase(pUnit); + pSummoned->Attack(pUnit, true); + } + } + + if (pSummoned->AI()) + pSummoned->AI()->DoZoneInCombat(); + } + + void SummonedCreatureDespawn(Creature *pSummoned) + { + summons.Despawn(pSummoned); + if (summons.empty()) + { + if (pSummoned->isAlive()) + pInstance->SetData(DATA_WAVE_COUNT, NOT_STARTED); + else + pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); + } + } +}; + +#endif diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp new file mode 100644 index 00000000000..7a5d2479b7c --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp @@ -0,0 +1,431 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +#define MAX_ENCOUNTER 3 + +/* Halls of Reflection encounters: +0- Falric +1- Marwyn +2- The Lich King +*/ + +enum eEnum +{ + ENCOUNTER_WAVE_MERCENARY = 6, + ENCOUNTER_WAVE_FOOTMAN = 10, + ENCOUNTER_WAVE_RIFLEMAN = 6, + ENCOUNTER_WAVE_PRIEST = 6, + ENCOUNTER_WAVE_MAGE = 6, +}; + +enum Events +{ + EVENT_NONE, + EVENT_NEXT_WAVE, + EVENT_START_LICH_KING, +}; + +static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] = +{ + {5277.74,2016.88,707.778,5.96903}, + {5295.88,2040.34,707.778,5.07891}, + {5320.37,1980.13,707.778,2.00713}, + {5280.51,1997.84,707.778,0.296706}, + {5302.45,2042.22,707.778,4.90438}, + {5306.57,1977.47,707.778,1.50098}, +}; + +static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] = +{ + {5312.75,2037.12,707.778,4.59022}, + {5309.58,2042.67,707.778,4.69494}, + {5275.08,2008.72,707.778,6.21337}, + {5279.65,2004.66,707.778,0.069813}, + {5275.48,2001.14,707.778,0.174533}, + {5316.7,2041.55,707.778,4.50295}, +}; + +static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] = +{ + {5302.25,1972.41,707.778,1.37881}, + {5311.03,1972.23,707.778,1.64061}, + {5277.36,1993.23,707.778,0.401426}, + {5318.7,2036.11,707.778,4.2237}, + {5335.72,1996.86,707.778,2.74017}, + {5299.43,1979.01,707.778,1.23918}, +}; + +static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] = +{ + {5306.06,2037,707.778,4.81711}, + {5344.15,2007.17,707.778,3.15905}, + {5337.83,2010.06,707.778,3.22886}, + {5343.29,1999.38,707.778,2.9147}, + {5340.84,1992.46,707.778,2.75762}, + {5325.07,1977.6,707.778,2.07694}, + {5336.6,2017.28,707.778,3.47321}, + {5313.82,1978.15,707.778,1.74533}, + {5280.63,2012.16,707.778,6.05629}, + {5322.96,2040.29,707.778,4.34587}, +}; + +static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] = +{ + {5343.47,2015.95,707.778,3.49066}, + {5337.86,2003.4,707.778,2.98451}, + {5319.16,1974,707.778,1.91986}, + {5299.25,2036,707.778,5.02655}, + {5295.64,1973.76,707.778,1.18682}, + {5282.9,2019.6,707.778,5.88176}, +}; + +struct instance_halls_of_reflection : public ScriptedInstance +{ + instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiFalric; + uint64 uiMarwyn; + uint64 uiLichKingEvent; + uint64 uiJainaPart1; + uint64 uiSylvanasPart1; + + uint64 uiFrostmourne; + uint64 uiFrostmourneAltar; + uint64 uiArthasDoor; + uint64 uiFrontDoor; + + uint32 uiEncounter[MAX_ENCOUNTER]; + uint32 uiTeamInInstance; + uint32 uiWaveCount; + bool bIntroDone; + + EventMap events; + + void Initialize() + { + events.Reset(); + + uiFalric = 0; + uiMarwyn = 0; + uiLichKingEvent = 0; + uiJainaPart1 = 0; + uiSylvanasPart1 = 0; + + uiFrostmourne = 0; + uiFrostmourneAltar = 0; + uiArthasDoor = 0; + uiFrontDoor = 0; + uiTeamInInstance = 0; + uiWaveCount = 0; + bIntroDone = false; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + if (!add) + return; + + Map::PlayerList const &players = instance->GetPlayers(); + if (!players.isEmpty()) + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + + switch(pCreature->GetEntry()) + { + case NPC_FALRIC: + uiFalric = pCreature->GetGUID(); + break; + case NPC_MARWYN: + uiMarwyn = pCreature->GetGUID(); + break; + case NPC_LICH_KING_EVENT: + uiLichKingEvent = pCreature->GetGUID(); + break; + case NPC_JAINA_PART1: + uiJainaPart1 = pCreature->GetGUID(); + break; + case NPC_SYLVANAS_PART1: + uiSylvanasPart1 = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (!add) + return; + + // TODO: init state depending on encounters + switch(pGo->GetEntry()) + { + case GO_FROSTMOURNE: + uiFrostmourne = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, false, pGo); + break; + case GO_FROSTMOURNE_ALTAR: + uiFrostmourneAltar = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, true, pGo); + break; + case GO_FRONT_DOOR: + uiFrontDoor = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, true, pGo); + break; + case GO_ARTHAS_DOOR: + uiArthasDoor = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + + if (uiEncounter[1] == DONE) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + if (type == DATA_WAVE_COUNT && data == SPECIAL) + { + bIntroDone = true; + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + return; + } + + + if (uiWaveCount && data == NOT_STARTED) + DoWipe(); + + switch(type) + { + case DATA_FALRIC_EVENT: + uiEncounter[0] = data; + if (data == DONE) + events.ScheduleEvent(EVENT_NEXT_WAVE, 60000); + break; + case DATA_MARWYN_EVENT: + uiEncounter[1] = data; + if (data == DONE) + HandleGameObject(uiArthasDoor, true); + break; + case DATA_LICHKING_EVENT: + uiEncounter[2] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_FALRIC_EVENT: return uiEncounter[0]; + case DATA_MARWYN_EVENT: return uiEncounter[1]; + case DATA_LICHKING_EVENT: return uiEncounter[2]; + case DATA_WAVE_COUNT: return uiWaveCount; + case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_FALRIC: return uiFalric; + case DATA_MARWYN: return uiMarwyn; + case DATA_LICHKING: return uiLichKingEvent; + case DATA_FROSTMOURNE: return uiFrostmourne; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H R 1 " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 version; + uint16 data0, data1, data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2; + + if (dataHead1 == 'H' && dataHead2 == 'R') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + uiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + if (uiEncounter[0] == DONE || uiEncounter[1] == DONE) + bIntroDone = true; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void AddWave() + { + DoUpdateWorldState(WORLD_STATE_HOR, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); + + switch(uiWaveCount) + { + case 1: + case 2: + case 3: + case 4: + if (Creature *pFalric = instance->GetCreature(uiFalric)) + SpawnWave(pFalric); + break; + case 5: + if (GetData(DATA_FALRIC_EVENT) == DONE) + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + else if (Creature *pFalric = instance->GetCreature(uiFalric)) + if (pFalric->AI()) + pFalric->AI()->DoAction(ACTION_ENTER_COMBAT); + break; + case 6: + case 7: + case 8: + case 9: + if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) + SpawnWave(pMarwyn); + break; + case 10: + if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit! + if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) + if (pMarwyn->AI()) + pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT); + break; + } + } + + // Wipe has been detected. Perform cleanup and reset. + void DoWipe() + { + uiWaveCount = 0; + events.Reset(); + DoUpdateWorldState(WORLD_STATE_HOR, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); + HandleGameObject(uiFrontDoor, true); + + // TODO + // in case of wipe, the event is normally restarted by jumping into the center of the room. + // As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted. + if (Creature* pJaina = instance->GetCreature(uiJainaPart1)) + pJaina->Respawn(); + if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1)) + pSylvanas->Respawn(); + + if (Creature* pFalric = instance->GetCreature(uiFalric)) + pFalric->SetVisibility(VISIBILITY_OFF); + if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) + pMarwyn->SetVisibility(VISIBILITY_OFF); + } + + // spawn a wave on behalf of the summoner. + void SpawnWave(Creature *pSummoner) + { + uint32 index; + + pSummoner->SetVisibility(VISIBILITY_ON); + + // TODO: do composition at random. # of spawn also depends on uiWaveCount + // As of now, it is just one of each. + index = urand(0,ENCOUNTER_WAVE_MERCENARY-1); + pSummoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_FOOTMAN-1); + pSummoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_RIFLEMAN-1); + pSummoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_PRIEST-1); + pSummoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_MAGE-1); + pSummoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + } + + void Update(uint32 diff) + { + if (!instance->HavePlayers()) + return; + + events.Update(diff); + + switch(uint32 eventId = events.ExecuteEvent()) + { + case EVENT_NEXT_WAVE: + uiWaveCount++; + AddWave(); + break; + case EVENT_START_LICH_KING: + // TODO + break; + } + } +}; + +InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap) +{ + return new instance_halls_of_reflection(pMap); +} + +void AddSC_instance_halls_of_reflection() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_reflection"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_reflection; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp new file mode 100644 index 00000000000..25c78c4a0d3 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp @@ -0,0 +1,209 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +enum Yells +{ + SAY_AGGRO = -1658001, + SAY_SLAY_1 = -1658002, + SAY_SLAY_2 = -1658003, + SAY_DEATH = -1658004, + SAY_PHASE2 = -1658005, + SAY_PHASE3 = -1658006, + + SAY_TYRANNUS_DEATH = -1659007, +}; + +enum eEvents +{ + EVENT_NONE, + EVENT_PERMAFROST, + EVENT_THROW_SARONITE, + EVENT_CHILLINGWAVE, + EVENT_DEEPFREEZE, +}; + +enum Spells +{ + SPELL_PERMAFROST = 70326, + SPELL_PERMAFROST_TRIGGER = 68786, // triggered by PERMAFROST. Used to check aura + SPELL_THROW_SARONITE = 68788, + SPELL_THUNDERING_STOMP = 68771, + SPELL_CHILLING_WAVE = 68778, + H_SPELL_CHILLING_WAVE = 70333, + SPELL_DEEP_FREEZE = 70381, + H_SPELL_DEEP_FREEZE = 72930, + SPELL_FORGE_MACE = 68785, + H_SPELL_FORGE_MACE = 70335, + SPELL_FORGE_BLADE = 68774, + H_SPELL_FORGE_BLADE = 70334, +}; + +enum eEnums +{ + EQUIP_ID_SWORD = 49345, + EQUIP_ID_MACE = 49344, + ACHIEV_DOESNT_GO_TO_ELEVEN = 4524, +}; + +struct boss_garfrostAI : public ScriptedAI +{ + boss_garfrostAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + bool phase2; + bool phase3; + bool bAchievement; + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + phase2 = false; + phase3 = false; + bAchievement = true; + + if (pInstance) + pInstance->SetData(DATA_GARFROST_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_PERMAFROST); + + if (pInstance) + pInstance->SetData(DATA_GARFROST_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_THROW_SARONITE, 45000); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& /*uiDamage*/) + { + if (HealthBelowPct(66) && !phase2) + { + phase2 = true; + DoCast(me, SPELL_THUNDERING_STOMP); + // TODO: should go to a forge + DoCast(me, SPELL_FORGE_BLADE); + // TODO: should equip when spell completes + SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + events.ScheduleEvent(EVENT_CHILLINGWAVE, 10000); + } + + if (HealthBelowPct(33) && !phase3) + { + phase3 = true; + DoCast(me, SPELL_THUNDERING_STOMP); + // TODO: should go to a forge + DoCast(me, SPELL_FORGE_MACE); + // TODO: should equip when spell completes + SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + events.CancelEvent(EVENT_CHILLINGWAVE); // cast only in phase 2. + events.ScheduleEvent(EVENT_DEEPFREEZE, 10000); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + { + if (Creature *pTyrannus = me->GetCreature(*me, pInstance->GetData64(DATA_TYRANNUS))) + DoScriptText(SAY_TYRANNUS_DEATH, pTyrannus); + + pInstance->SetData(DATA_GARFROST_EVENT, DONE); + if (IsHeroic() && bAchievement) + pInstance->DoCompleteAchievement(ACHIEV_DOESNT_GO_TO_ELEVEN); + } + } + + void SpellHitTarget(Unit* pTarget, const SpellEntry *spell) + { + if (spell->Id == SPELL_PERMAFROST_TRIGGER && bAchievement) + { + if (Aura *pAura = pTarget->GetAura(SPELL_PERMAFROST_TRIGGER)) + if (pAura->GetStackAmount() > 10) + bAchievement = false; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_THROW_SARONITE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_THROW_SARONITE); + events.RescheduleEvent(EVENT_THROW_SARONITE, 35000); + return; + case EVENT_DEEPFREEZE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DEEP_FREEZE); + events.RescheduleEvent(EVENT_DEEPFREEZE, 35000); + return; + case EVENT_CHILLINGWAVE: + DoCastAOE(SPELL_CHILLING_WAVE); + events.RescheduleEvent(EVENT_CHILLINGWAVE, 40000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_garfrost(Creature* pCreature) +{ + return new boss_garfrostAI (pCreature); +} + +void AddSC_boss_garfrost() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_garfrost"; + newscript->GetAI = &GetAI_boss_garfrost; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp new file mode 100644 index 00000000000..8b8b03a3d4e --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp @@ -0,0 +1,482 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/* + * SDComment: Spell Explosive barrage is not working. + */ + +enum Spells +{ + SPELL_PURSUED = 68987, + SPELL_CONFUSION = 69029, + SPELL_EXPLOSIVE_BARRAGE = 69263, + SPELL_MIGHTY_KICK = 69021, + SPELL_POISON_NOVA = 68989, + H_SPELL_POISON_NOVA = 70434, + SPELL_SHADOW_BOLT = 69028, + SPELL_TOXIC_WASTE = 69024, + H_SPELL_TOXIC_WASTE = 70436, +}; + +enum Yells +{ + // Krick + SAY_KRICK_AGGRO = -1658010, + SAY_KRICK_SLAY_1 = -1658011, + SAY_KRICK_SLAY_2 = -1658012, + SAY_KRICK_BARRAGE_1 = -1658013, + SAY_KRICK_BARRAGE_2 = -1658014, + SAY_KRICK_POISON_NOVA = -1658015, + SAY_KRICK_CHASE_1 = -1658016, + SAY_KRICK_CHASE_2 = -1658017, + SAY_KRICK_CHASE_3 = -1658018, + + // Ick + SAY_ICK_POISON_NOVA = -1658020, + SAY_ICK_CHASE_1 = -1658021, + + // OUTRO + SAY_KRICK_OUTRO_1 = -1658030, + SAY_JAYNA_OUTRO_2 = -1658031, + SAY_SYLVANAS_OUTRO_2 = -1658032, + SAY_KRICK_OUTRO_3 = -1658033, + SAY_JAYNA_OUTRO_4 = -1658034, + SAY_SYLVANAS_OUTRO_4 = -1658035, + SAY_KRICK_OUTRO_5 = -1658036, + SAY_TYRANNUS_OUTRO_7 = -1658037, + SAY_KRICK_OUTRO_8 = -1658038, + SAY_TYRANNUS_OUTRO_9 = -1658039, + SAY_JAYNA_OUTRO_10 = -1658040, + SAY_SYLVANAS_OUTRO_10 = -1658041, +}; + +enum Events +{ + EVENT_NONE, + EVENT_PURSUE, + EVENT_MIGHTY_KICK, + EVENT_POISON_NOVA, + EVENT_EXPLOSIVE_BARRAGE, + EVENT_END_EXPLOSIVE_BARRAGE, + + // Krick + EVENT_SHADOW_BOLT, + EVENT_TOXIC_WASTE, + + // Krick OUTRO + EVENT_OUTRO_1, + EVENT_OUTRO_2, + EVENT_OUTRO_3, + EVENT_OUTRO_4, + EVENT_OUTRO_5, + EVENT_OUTRO_6, + EVENT_OUTRO_7, + EVENT_OUTRO_8, + EVENT_OUTRO_9, + EVENT_OUTRO_10, + EVENT_OUTRO_11, + EVENT_OUTRO_12, + EVENT_OUTRO_END, +}; + +enum KrickPhase +{ + PHASE_COMBAT, + PHASE_OUTRO, +}; + +enum Actions +{ + ACTION_OUTRO, +}; + +enum Misc +{ + SEAT_KRICK = 0, + + // events GCD. Shall not be 0. + GCD_1 = 1, +}; + +// Krick is the Gnome. +// Ick is the Mount +// Common Events are handled/triggered by Ick that "drive" Krick through DoAction. + +struct boss_ickAI : public ScriptedAI +{ + boss_ickAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, NOT_STARTED); + } + + Creature* GetKrick() + { + return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_KRICK) : 0); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, IN_PROGRESS); + + Creature* pKrick = GetKrick(); + if (!pKrick) + pKrick = me->SummonCreature(CREATURE_KRICK, *me, TEMPSUMMON_MANUAL_DESPAWN); + + if (pKrick) + DoScriptText(SAY_KRICK_AGGRO, pKrick); + + events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000, GCD_1); + events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); + events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); + events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 35000); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + } + + void EnterEvadeMode() + { + me->GetMotionMaster()->Clear(); + ScriptedAI::EnterEvadeMode(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (Creature* pKrick = GetKrick()) + { + if (pKrick->AI()) + pKrick->AI()->DoAction(ACTION_OUTRO); + } + + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + return; + + if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch(events.ExecuteEvent()) + { + case EVENT_PURSUE: + if (Creature* pKrick = GetKrick()) + DoScriptText(RAND(SAY_KRICK_CHASE_1,SAY_KRICK_CHASE_2,SAY_KRICK_CHASE_3), pKrick); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->Attack(pTarget,false); + DoScriptText(SAY_ICK_CHASE_1, me, pTarget); + DoCast(pTarget, SPELL_PURSUED); + } + + DoCast(SPELL_CONFUSION); + events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); + return; + + case EVENT_MIGHTY_KICK: + DoCast(me->getVictim(), SPELL_MIGHTY_KICK); + events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000, GCD_1); + return; + + case EVENT_POISON_NOVA: + if (Creature* pKrick = GetKrick()) + DoScriptText(SAY_KRICK_POISON_NOVA, pKrick); + + DoScriptText(SAY_ICK_POISON_NOVA, me); + DoCastAOE(SPELL_POISON_NOVA); + events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); + return; + + case EVENT_TOXIC_WASTE: + DoCast(me->getVictim(), SPELL_TOXIC_WASTE); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + return; + + case EVENT_SHADOW_BOLT: + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + return; + + case EVENT_EXPLOSIVE_BARRAGE: + if (Creature *pKrick = GetKrick()) + { + DoScriptText(SAY_KRICK_BARRAGE_1, pKrick); + DoScriptText(SAY_KRICK_BARRAGE_2, pKrick); + } + + DoCastAOE(SPELL_EXPLOSIVE_BARRAGE); + me->GetMotionMaster()->MoveIdle(); + events.DelayEvents(20000, GCD_1); // 2 sec cast + 18 sec + events.ScheduleEvent(EVENT_END_EXPLOSIVE_BARRAGE, 20000); + return; + + case EVENT_END_EXPLOSIVE_BARRAGE: + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 25000); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_krickAI : public ScriptedAI +{ + boss_krickAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + KrickPhase phase; + uint64 uiNpcOutroDialog; + uint64 uiTyrannus; + + void Reset() + { + uiNpcOutroDialog = 0; + uiTyrannus = 0; + phase = PHASE_COMBAT; + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_OFF); + } + + Creature* GetIck() + { + return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ICK) : 0); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_KRICK_SLAY_1,SAY_KRICK_SLAY_2), me); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + // if killed whatever the reason, it breaks the outro + uiDamage = 0; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_OUTRO: + { + Position pos; + if (Creature* pIck = GetIck()) + { + // TODO: tele on Ick then run some distance. + pIck->GetNearPosition(pos, 5.0f, 3.14); + me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0.0f); + } + me->SetVisibility(VISIBILITY_ON); + + Creature* pJainaOrSylvanas = me->GetCreature(*me, pInstance->GetData64(DATA_JAINA_SYLVANAS_1)); + if (pJainaOrSylvanas) { + Position pos; + me->GetNearPosition(pos, 5.0f, 0); + pJainaOrSylvanas->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), + pos.GetAngle(me->GetPositionX(), me->GetPositionY())); + } + else { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + pJainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); + else + pJainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); + } + + if (pJainaOrSylvanas) + { + pJainaOrSylvanas->SetOrientation(pJainaOrSylvanas->GetAngle(me->GetPositionX(), me->GetPositionY())); + me->SetOrientation(me->GetAngle(pJainaOrSylvanas->GetPositionX(), pJainaOrSylvanas->GetPositionY())); + uiNpcOutroDialog = pJainaOrSylvanas->GetGUID(); + } + + phase = PHASE_OUTRO; + events.Reset(); + events.ScheduleEvent(EVENT_OUTRO_1, 1000); + break; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_OUTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_OUTRO_1: + { + DoScriptText(SAY_KRICK_OUTRO_1, me); + events.ScheduleEvent(EVENT_OUTRO_2, 14000); + break; + } + case EVENT_OUTRO_2: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_2, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_2, pNpcDialog); + } + events.ScheduleEvent(EVENT_OUTRO_3, 8500); + break; + } + case EVENT_OUTRO_3: + DoScriptText(SAY_KRICK_OUTRO_3, me); + events.ScheduleEvent(EVENT_OUTRO_4, 12000); + break; + case EVENT_OUTRO_4: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_4, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_4, pNpcDialog); + } + events.ScheduleEvent(EVENT_OUTRO_5, 8000); + break; + } + case EVENT_OUTRO_5: + DoScriptText(SAY_KRICK_OUTRO_5, me); + events.ScheduleEvent(EVENT_OUTRO_6, 4000); + break; + case EVENT_OUTRO_6: + // TODO spawn Tyrannus at some distance and MovePoint near-by (flying on rimefang) + // store uiTyrannus + // Adjust timer so tyrannus has time to come + uiTyrannus = (pInstance ? pInstance->GetData64(DATA_TYRANNUS) : 0); + events.ScheduleEvent(EVENT_OUTRO_7, 1); + break; + case EVENT_OUTRO_7: + if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) + DoScriptText(SAY_TYRANNUS_OUTRO_7, pTyrannus); + events.ScheduleEvent(EVENT_OUTRO_8, 7000); + break; + case EVENT_OUTRO_8: + DoScriptText(SAY_KRICK_OUTRO_8, me); + // TODO: Tyrannus starts killing Krick. + // there shall be some visual spell effect + events.ScheduleEvent(EVENT_OUTRO_9, 6000); + break; + case EVENT_OUTRO_9: + // tyrannus kills krick + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetHealth(0); + + if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) + DoScriptText(SAY_TYRANNUS_OUTRO_9, pTyrannus); + + events.ScheduleEvent(EVENT_OUTRO_10, 12000); + break; + case EVENT_OUTRO_10: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_10, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_10, pNpcDialog); + } + + // End of OUTRO. for now... + events.ScheduleEvent(EVENT_OUTRO_END, 8000); + break; + } + case EVENT_OUTRO_END: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + pNpcDialog->DisappearAndDie(); + + me->DisappearAndDie(); + break; + } + } + return; + } + } +}; + +CreatureAI* GetAI_boss_ick(Creature* pCreature) +{ + return new boss_ickAI(pCreature); +} + +CreatureAI* GetAI_boss_krick(Creature* pCreature) +{ + return new boss_krickAI(pCreature); +} + +void AddSC_boss_ick() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ick"; + newscript->GetAI = &GetAI_boss_ick; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_krick"; + newscript->GetAI = &GetAI_boss_krick; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp new file mode 100644 index 00000000000..55ffa0b4e4b --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp @@ -0,0 +1,273 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/* + * SDComment: TODO: + * - implement aura for spell Overlord Brand. + * - Intro/Outro + * - improve script of Rimefang + */ + +enum Yells +{ + SAY_AMBUSH_1 = -1658050, + SAY_AMBUSH_2 = -1658051, + SAY_GAUNTLET_START = -1658052, + SAY_INTRO_1 = -1658053, + SAY_INTRO_2 = -1658054, + + SAY_AGGRO = -1658055, + SAY_SLAY_1 = -1658056, + SAY_SLAY_2 = -1658057, + SAY_DEATH = -1658058, + SAY_MARK_RIMEFANG_1 = -1658059, + SAY_MARK_RIMEFANG_2 = -1658060, + SAY_DARK_MIGHT_1 = -1658061, + SAY_DARK_MIGHT_2 = -1658062, + + SAY_GORKUN_OUTRO_1 = -1658063, + SAY_GORKUN_OUTRO_2 = -1658064, + SAY_JAYNA_OUTRO_3 = -1658065, + SAY_SYLVANAS_OUTRO_3 = -1658066, + SAY_JAYNA_OUTRO_4 = -1658067, + SAY_SYLVANAS_OUTRO_4 = -1658068, + SAY_JAYNA_OUTRO_5 = -1658069, +}; + +enum Spells +{ + SPELL_FORCEFUL_SMASH = 69155, + H_SPELL_FORCEFUL_SMASH = 69627, + SPELL_OVERLORDS_BRAND = 69172, + SPELL_DARK_MIGHT = 69167, + H_SPELL_DARK_MIGHT = 69629, + SPELL_HOARFROST = 69246, + SPELL_MARK_OF_RIMEFANG = 69275, + SPELL_ICY_BLAST = 69233, + H_SPELL_ICY_BLAST = 69646, + SPELL_ICY_BLAST_2 = 69238, + H_SPELL_ICY_BLAST_2 = 69628, +}; + +enum Events +{ + EVENT_NONE, + EVENT_FORCEFUL_SMASH, + EVENT_OVERLORDS_BRAND, + EVENT_DARK_MIGHT, + + // Rimefang + EVENT_MARK_OF_RIMEFANG, + EVENT_HOARFROST, + EVENT_ICY_BLAST, + EVENT_ICY_BLAST_2, +}; + +enum Misc +{ + SEAT_TYRANNUS = 0 +}; + +struct boss_tyrannusAI : public ScriptedAI +{ + boss_tyrannusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_TYRANNUS_EVENT, NOT_STARTED); + } + + Creature* GetRimefang() + { + return me->GetCreature(*me, pInstance->GetData64(DATA_RIMEFANG)); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + me->ExitVehicle(); + + // restore health if any damage done during intro + me->SetHealth(me->GetMaxHealth()); + + if (pInstance) + pInstance->SetData(DATA_TYRANNUS_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); + events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 35000); + events.ScheduleEvent(EVENT_DARK_MIGHT, 40000); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_TYRANNUS_EVENT, DONE); + if (Creature* pRimefang = GetRimefang()) + pRimefang->ForcedDespawn(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FORCEFUL_SMASH: + DoCast(me->getVictim(), SPELL_FORCEFUL_SMASH); + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); + return; + case EVENT_OVERLORDS_BRAND: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_OVERLORDS_BRAND); + events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 45000); + return; + case EVENT_DARK_MIGHT: + DoScriptText(SAY_DARK_MIGHT_1, me); + DoScriptText(SAY_DARK_MIGHT_2, me); + DoCast(me, SPELL_DARK_MIGHT); + events.ScheduleEvent(EVENT_DARK_MIGHT, 60000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_rimefangAI : public ScriptedAI +{ + boss_rimefangAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 25000); + events.ScheduleEvent(EVENT_ICY_BLAST, 35000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_MARK_OF_RIMEFANG: + DoScriptText(SAY_MARK_RIMEFANG_1, me); + DoScriptText(SAY_MARK_RIMEFANG_2, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MARK_OF_RIMEFANG); + events.ScheduleEvent(EVENT_HOARFROST, 5000); + return; + case EVENT_HOARFROST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_HOARFROST); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 20000); + return; + case EVENT_ICY_BLAST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ICY_BLAST); + events.ScheduleEvent(EVENT_ICY_BLAST_2, 5000); + return; + case EVENT_ICY_BLAST_2: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget->getVictim(), SPELL_ICY_BLAST_2); + events.ScheduleEvent(EVENT_ICY_BLAST, 30000); + return; + } + } + } +}; + +CreatureAI* GetAI_boss_tyrannus(Creature* pCreature) +{ + return new boss_tyrannusAI(pCreature); +} + +CreatureAI* GetAI_boss_rimefang(Creature* pCreature) +{ + return new boss_rimefangAI(pCreature); +} + +void AddSC_boss_tyrannus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_tyrannus"; + newscript->GetAI = &GetAI_boss_tyrannus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="boss_rimefang"; + newscript->GetAI = &GetAI_boss_rimefang; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp new file mode 100644 index 00000000000..8512eca24c1 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp @@ -0,0 +1,236 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +#define MAX_ENCOUNTER 3 + +/* Pit of Saron encounters: +0- Forgemaster Garfrost +1- Krick and Ick +2- Scourgelord Tyrannus +*/ + +struct instance_pit_of_saron : public ScriptedInstance +{ + instance_pit_of_saron(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiKrick; + uint64 uiIck; + uint64 uiGarfrost; + uint64 uiTyrannus; + uint64 uiRimefang; + + uint64 uiJainaOrSylvanas1; + uint64 uiJainaOrSylvanas2; + + uint32 uiTeamInInstance; + uint32 uiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + + uiGarfrost = 0; + uiKrick = 0; + uiIck = 0; + uiTyrannus = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + } + + switch(pCreature->GetEntry()) + { + case CREATURE_KRICK: + uiKrick = pCreature->GetGUID(); + break; + + case CREATURE_ICK: + uiIck = pCreature->GetGUID(); + break; + + case CREATURE_GARFROST: + uiGarfrost = pCreature->GetGUID(); + break; + + case CREATURE_TYRANNUS: + uiTyrannus = pCreature->GetGUID(); + break; + + case CREATURE_RIMEFANG: + uiRimefang = pCreature->GetGUID(); + break; + + case NPC_SYLVANAS_PART1: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); + uiJainaOrSylvanas1 = pCreature->GetGUID(); + break; + case NPC_SYLVANAS_PART2: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); + uiJainaOrSylvanas2 = pCreature->GetGUID(); + break; + case NPC_KILARA: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_ELANDRA, ALLIANCE); + break; + case NPC_KORALEN: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_KORLAEN, ALLIANCE); + break; + case NPC_CHAMPION_1_HORDE: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_2_HORDE: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_GARFROST: return uiGarfrost; + case DATA_KRICK: return uiKrick; + case DATA_ICK: return uiIck; + case DATA_TYRANNUS: return uiTyrannus; + case DATA_RIMEFANG: return uiRimefang; + + case DATA_JAINA_SYLVANAS_1: return uiJainaOrSylvanas1; + case DATA_JAINA_SYLVANAS_2: return uiJainaOrSylvanas2; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_GARFROST_EVENT: + uiEncounter[0] = data; + break; + case DATA_TYRANNUS_EVENT: + uiEncounter[1] = data; + break; + case DATA_KRICKANDICK_EVENT: + uiEncounter[2] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_GARFROST_EVENT: return uiEncounter[0]; + case DATA_TYRANNUS_EVENT: return uiEncounter[1]; + case DATA_KRICKANDICK_EVENT: return uiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::string str_data; + + std::ostringstream saveStream; + saveStream << "P S " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; + + if (dataHead1 == 'P' && dataHead2 == 'S') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + uiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_pit_of_saron(Map* pMap) +{ + return new instance_pit_of_saron(pMap); +} + +void AddSC_instance_pit_of_saron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_pit_of_saron"; + newscript->GetInstanceData = &GetInstanceData_instance_pit_of_saron; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp new file mode 100644 index 00000000000..bc53efc7033 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp @@ -0,0 +1,1101 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/***************************************SPELLS*************************************/ +// Ymirjar Wrathbringer +#define SPELL_BLIGHT DUNGEON_MODE(69603,70285) + +//Ymirjar Skycaller +#define SPELL_FROSTBLADE 70291 +#define SPELL_GLACIAL_STRIKE 70292 + +//Ymirjar Flamebearer +#define SPELL_FIREBALL DUNGEON_MODE(69583,70282) +#define SPELL_HELLFIRE DUNGEON_MODE(69586,70283) +#define SPELL_TACTICAL_BLINK 69584 + +//Ymirjar Deathbringer +#define SPELL_EMPOWERED_SHADOW_BOLT DUNGEON_MODE(69528,70281) +#define SPELL_SUMMON_UNDEAD 69516 + +//Wrathbone Laborer +#define SPELL_BLINDING_DIRT 70302 +#define SPELL_PUNCTURE_WOUND DUNGEON_MODE(70278,70279) +#define SPELL_SHOVELLED DUNGEON_MODE(69572,70280) + +//Wrathbone Coldwraith +#define SPELL_FREEZING_CIRCLE DUNGEON_MODE(69574,70276) +#define SPELL_FROSTBOLT DUNGEON_MODE(69573,70277) + +//Stonespine Gargoyle +#define SPELL_GARGOYLE_STRIKE DUNGEON_MODE(69520,70275) +#define SPELL_STONEFORM 69575 + +// Plagueborn Horror +#define SPELL_BLIGHT_BOMB 69582 +#define SPELL_PUSTULANT_FLESH DUNGEON_MODE(69581,70273) +#define SPELL_TOXIC_WASTE 70274 + +//Iceborn Proto-Drake +#define SPELL_FROST_BREATH DUNGEON_MODE(69527,70272) + +//Hungering Ghoul +#define SPELL_DEVOUR_FLESH 70393 + +//Fallen Warrior +#define SPELL_ARCING_SLICE 69579 +#define SPELL_DEMORALIZING_SHOUT 61044 +#define SPELL_SHIELD_BLOCK 69580 + +//Deathwhisper Torturer +#define SPELL_BLACK_BRAND 70392 +#define SPELL_CURSE_OF_AGONY 70391 + +//Deathwhisper Shadowcaster +#define SPELL_SHADOW_BOLT DUNGEON_MODE(70386,70387) + +//Deathwhisper Necrolyte +#define SPELL_CONVERSION_BEAM DUNGEON_MODE(69578,70269) +#define SPELL_SHADOW_BOLT_2 DUNGEON_MODE(69577,70270) + +//Wrathbone Sorcerer +#define SPELL_SHADOW_BOLT_3 DUNGEON_MODE(70386,70387) + +//Geist Ambusher +#define SPELL_LEAPING_FACE_MAUL DUNGEON_MODE(69504,70271) + +/****************************************EVENTS************************************/ +enum eEvents +{ + EVENT_NONE, + + // Ymirjar Wrathbringer + EVENT_BLIGHT, + + // Ymirjar Skycaller + EVENT_FROSTBLADE, + EVENT_GLACIAL_STRIKE, + + // Ymirjar Flamebearer + EVENT_FIREBALL, + EVENT_HELLFIRE, + EVENT_TACTICAL_BLINK, + + //Ymirjar Deathbringer + EVENT_EMPOWERED_SHADOW_BOLT, + EVENT_SUMMON_UNDEAD, + + //Wrathbone Laborer + EVENT_BLINDING_DIRT, + EVENT_PUNCTURE_WOUND, + EVENT_SHOVELLED, + + //Wrathbone Coldwraith + EVENT_FREEZING_CIRCLE, + EVENT_FROSTBOLT, + + //Stonespine Gargoyle + EVENT_GARGOYLE_STRIKE, + EVENT_STONEFORM, + + //Plagueborn Horror + EVENT_BLIGHT_BOMB, + EVENT_PUSTULANT_FLESH, + EVENT_TOXIC_WASTE, + + //Iceborn Proto-Drake + EVENT_FROST_BREATH, + + //Hungering Ghoul + EVENT_DEVOUR_FLESH, + + //Fallen Warrior + EVENT_ARCING_SLICE, + EVENT_DEMORALIZING_SHOUT, + EVENT_SHIELD_BLOCK, + + //Deathwhisper Torturer + EVENT_BLACK_BRAND, + EVENT_CURSE_OF_AGONY, + + //Deathwhisper Shadowcaster + EVENT_SHADOW_BOLT, + + //Deathwhisper Necrolyte + EVENT_CONVERSION_BEAM, + EVENT_SHADOW_BOLT_2, + + EVENT_SHADOW_BOLT_3, + + //Geist Ambusher + EVENT_LEAPING_FACE_MAUL, +}; + +/****************************************AI****************************************/ +struct mob_ymirjar_wrathbringerAI : public ScriptedAI +{ + mob_ymirjar_wrathbringerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLIGHT, 7000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLIGHT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLIGHT); + events.RescheduleEvent(EVENT_BLIGHT, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_skyCallerAI: public ScriptedAI +{ + mob_ymirjar_skyCallerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROSTBLADE, 1); + events.ScheduleEvent(EVENT_GLACIAL_STRIKE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_GLACIAL_STRIKE: + DoCast(me->getVictim(), SPELL_GLACIAL_STRIKE); + events.RescheduleEvent(EVENT_GLACIAL_STRIKE, 8000); + return; + case EVENT_FROSTBLADE: + DoCast(me, SPELL_FROSTBLADE); + events.CancelEvent(EVENT_FROSTBLADE); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_flamebearerAI: public ScriptedAI +{ + mob_ymirjar_flamebearerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FIREBALL, 4000); + events.ScheduleEvent(EVENT_HELLFIRE, 8000); + events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FIREBALL: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FIREBALL); + events.RescheduleEvent(EVENT_FIREBALL, 5000); + return; + case EVENT_HELLFIRE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_HELLFIRE); + events.RescheduleEvent(EVENT_HELLFIRE, 10000); + return; + case EVENT_TACTICAL_BLINK: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_TACTICAL_BLINK); + events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_deathbringerAI: public ScriptedAI +{ + mob_ymirjar_deathbringerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_EMPOWERED_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_EMPOWERED_SHADOW_BOLT); + events.RescheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_laborerAI: public ScriptedAI +{ + mob_wrathbone_laborerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); + events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + events.ScheduleEvent(EVENT_SHOVELLED, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLINDING_DIRT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLINDING_DIRT); + events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); + return; + case EVENT_PUNCTURE_WOUND: + DoCast(me->getVictim(), SPELL_PUNCTURE_WOUND); + events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + return; + case EVENT_SHOVELLED: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHOVELLED); + events.RescheduleEvent(EVENT_SHOVELLED, 7000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_coldwraithAI: public ScriptedAI +{ + mob_wrathbone_coldwraithAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FREEZING_CIRCLE, 9000); + events.ScheduleEvent(EVENT_FROSTBOLT, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FREEZING_CIRCLE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FREEZING_CIRCLE); + events.RescheduleEvent(EVENT_FREEZING_CIRCLE, 9000); + return; + case EVENT_FROSTBOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FROSTBOLT); + events.RescheduleEvent(EVENT_FROSTBOLT, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_stonespine_gargoyleAI: public ScriptedAI +{ + mob_stonespine_gargoyleAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_GARGOYLE_STRIKE, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_GARGOYLE_STRIKE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_GARGOYLE_STRIKE); + events.RescheduleEvent(EVENT_GARGOYLE_STRIKE, 6000); + return; + case EVENT_STONEFORM: + if (HealthBelowPct(10)) + DoCast(me, SPELL_STONEFORM); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_plagueborn_horrorAI: public ScriptedAI +{ + mob_plagueborn_horrorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLIGHT_BOMB, 999999); + events.ScheduleEvent(EVENT_PUSTULANT_FLESH, 5000); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLIGHT_BOMB: + if (HealthBelowPct(15)) + DoCast(me, SPELL_BLIGHT_BOMB); + return; + case EVENT_PUSTULANT_FLESH: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_PUSTULANT_FLESH); + events.RescheduleEvent(EVENT_PUSTULANT_FLESH, 10000); + return; + case EVENT_TOXIC_WASTE: + DoCast(me, SPELL_TOXIC_WASTE); + events.RescheduleEvent(EVENT_TOXIC_WASTE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_iceborn_protodrakeAI: public ScriptedAI +{ + mob_iceborn_protodrakeAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROST_BREATH, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROST_BREATH: + DoCast(me->getVictim(), SPELL_FROST_BREATH); + events.RescheduleEvent(EVENT_FROST_BREATH, 10000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_hungering_ghoulAI: public ScriptedAI +{ + mob_hungering_ghoulAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_DEVOUR_FLESH, 4000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_DEVOUR_FLESH: + DoCast(me->getVictim(), SPELL_DEVOUR_FLESH); + events.RescheduleEvent(EVENT_DEVOUR_FLESH, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_fallen_warriorAI: public ScriptedAI +{ + mob_fallen_warriorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_ARCING_SLICE, 8000); + events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); + events.ScheduleEvent(EVENT_SHIELD_BLOCK, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ARCING_SLICE: + DoCast(me->getVictim(), SPELL_ARCING_SLICE); + events.RescheduleEvent(EVENT_ARCING_SLICE, 10000); + return; + case EVENT_DEMORALIZING_SHOUT: + DoCast(me, SPELL_DEMORALIZING_SHOUT); + events.RescheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); + return; + case EVENT_SHIELD_BLOCK: + DoCast(me->getVictim(), SPELL_SHIELD_BLOCK); + events.RescheduleEvent(EVENT_SHIELD_BLOCK, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_torturerAI: public ScriptedAI +{ + mob_deathwhisper_torturerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLACK_BRAND, 10000); + events.ScheduleEvent(EVENT_CURSE_OF_AGONY, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLACK_BRAND: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLACK_BRAND); + events.RescheduleEvent(EVENT_BLACK_BRAND, 10000); + return; + case EVENT_CURSE_OF_AGONY: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CURSE_OF_AGONY); + events.RescheduleEvent(EVENT_CURSE_OF_AGONY, 13000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_shadowcasterAI: public ScriptedAI +{ + mob_deathwhisper_shadowcasterAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_BOLT, 3000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_necrolyteAI: public ScriptedAI +{ + mob_deathwhisper_necrolyteAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_CONVERSION_BEAM, 12000); + events.ScheduleEvent(EVENT_SHADOW_BOLT_2, 4000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CONVERSION_BEAM: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CONVERSION_BEAM); + events.RescheduleEvent(EVENT_CONVERSION_BEAM, 12000); + return; + case EVENT_SHADOW_BOLT_2: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT_2); + events.RescheduleEvent(EVENT_SHADOW_BOLT_2, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_sorcererAI: public ScriptedAI +{ + mob_wrathbone_sorcererAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_BOLT_3, 3000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_BOLT_3: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT_3); + events.RescheduleEvent(EVENT_SHADOW_BOLT_3, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_geist_ambusherAI: public ScriptedAI +{ + mob_geist_ambusherAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + //Only here so when I figure out how to make it cast on an NPC i can do that. + events.ScheduleEvent(EVENT_LEAPING_FACE_MAUL, 99999); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + //Should only be used on NPCs + case EVENT_LEAPING_FACE_MAUL: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_LEAPING_FACE_MAUL); + events.CancelEvent(EVENT_LEAPING_FACE_MAUL); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_ymirjar_wrathbringerAI(Creature* pCreature) +{ + return new mob_ymirjar_wrathbringerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_skyCallerAI(Creature* pCreature) +{ + return new mob_ymirjar_skyCallerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_flamebearerAI(Creature* pCreature) +{ + return new mob_ymirjar_flamebearerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_deathbringerAI(Creature* pCreature) +{ + return new mob_ymirjar_deathbringerAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_laborerAI(Creature* pCreature) +{ + return new mob_wrathbone_laborerAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_coldwraithAI(Creature* pCreature) +{ + return new mob_wrathbone_coldwraithAI(pCreature); +} + +CreatureAI* GetAI_mob_stonespine_gargoyleAI(Creature* pCreature) +{ + return new mob_stonespine_gargoyleAI(pCreature); +} + +CreatureAI* GetAI_mob_plagueborn_horrorAI(Creature* pCreature) +{ + return new mob_plagueborn_horrorAI(pCreature); +} + +CreatureAI* GetAI_mob_iceborn_protodrakeAI(Creature* pCreature) +{ + return new mob_iceborn_protodrakeAI(pCreature); +} + +CreatureAI* GetAI_mob_hungering_ghoulAI(Creature* pCreature) +{ + return new mob_hungering_ghoulAI(pCreature); +} + +CreatureAI* GetAI_mob_fallen_warriorAI(Creature* pCreature) +{ + return new mob_fallen_warriorAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_torturerAI(Creature* pCreature) +{ + return new mob_deathwhisper_torturerAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_shadowcasterAI(Creature* pCreature) +{ + return new mob_deathwhisper_shadowcasterAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_necrolyteAI(Creature* pCreature) +{ + return new mob_deathwhisper_necrolyteAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_sorcererAI(Creature* pCreature) +{ + return new mob_wrathbone_sorcererAI(pCreature); +} + +CreatureAI* GetAI_mob_geist_ambusherAI(Creature* pCreature) +{ + return new mob_geist_ambusherAI(pCreature); +} + +void AddSC_pit_of_saron() +{ + Script *newscript; + newscript = new Script; + newscript->Name="mob_ymirjar_wrathbringer"; + newscript->GetAI = &GetAI_mob_ymirjar_wrathbringerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_skycaller"; + newscript->GetAI = &GetAI_mob_ymirjar_skyCallerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_flamebearer"; + newscript->GetAI = &GetAI_mob_ymirjar_flamebearerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_deathbringer"; + newscript->GetAI = &GetAI_mob_ymirjar_deathbringerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_laborer"; + newscript->GetAI = &GetAI_mob_wrathbone_laborerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_coldwraith"; + newscript->GetAI = &GetAI_mob_wrathbone_coldwraithAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_stonespine_gargoyle"; + newscript->GetAI = &GetAI_mob_stonespine_gargoyleAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_plagueborn_horror"; + newscript->GetAI = &GetAI_mob_plagueborn_horrorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_iceborn_protodrake"; + newscript->GetAI = &GetAI_mob_iceborn_protodrakeAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_hungering_ghoul"; + newscript->GetAI = &GetAI_mob_hungering_ghoulAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_fallen_warrior"; + newscript->GetAI = &GetAI_mob_fallen_warriorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_torturer"; + newscript->GetAI = &GetAI_mob_deathwhisper_torturerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_shadowcaster"; + newscript->GetAI = &GetAI_mob_deathwhisper_shadowcasterAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_necrolyte"; + newscript->GetAI = &GetAI_mob_deathwhisper_necrolyteAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_sorcerer"; + newscript->GetAI = &GetAI_mob_wrathbone_sorcererAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_geist_ambusher"; + newscript->GetAI = &GetAI_mob_geist_ambusherAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h new file mode 100644 index 00000000000..4a221d17518 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_PIT_OF_SARON_H +#define DEF_PIT_OF_SARON_H + +enum Data +{ + DATA_GARFROST_EVENT, + DATA_KRICKANDICK_EVENT, + DATA_TYRANNUS_EVENT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_GARFROST, + DATA_KRICK, + DATA_ICK, + DATA_TYRANNUS, + DATA_RIMEFANG, + + DATA_JAINA_SYLVANAS_1, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. + DATA_JAINA_SYLVANAS_2, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. +}; + +enum Creatures +{ + CREATURE_GARFROST = 36494, + CREATURE_KRICK = 36477, + CREATURE_ICK = 36476, + CREATURE_TYRANNUS = 36658, + CREATURE_RIMEFANG = 36661, + + NPC_SYLVANAS_PART1 = 36990, + NPC_SYLVANAS_PART2 = 38189, + NPC_JAINA_PART1 = 36993, + NPC_JAINA_PART2 = 38188, + NPC_KILARA = 37583, + NPC_ELANDRA = 37774, + NPC_KORALEN = 37779, + NPC_KORLAEN = 37582, + NPC_CHAMPION_1_HORDE = 37584, + NPC_CHAMPION_2_HORDE = 37587, + NPC_CHAMPION_3_HORDE = 37588, + NPC_CHAMPION_1_ALLIANCE = 37496, + NPC_CHAMPION_2_ALLIANCE = 37497, +}; + +#endif diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp new file mode 100644 index 00000000000..04603c68813 --- /dev/null +++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: The event with the Living Mojos is not implemented, just is done that when one of the mojos around the boss take damage will make the boss enter in combat! + */ + +#include "ScriptedPch.h" +#include "gundrak.h" + +enum Spells +{ + SPELL_EMERGE = 54850, + SPELL_MIGHTY_BLOW = 54719, + SPELL_MERGE = 54878, + SPELL_SURGE = 54801, + SPELL_FREEZE_ANIM = 16245, + SPELL_MOJO_PUDDLE = 55627, + H_SPELL_MOJO_PUDDLE = 58994, + SPELL_MOJO_WAVE = 55626, + H_SPELL_MOJO_WAVE = 58993 +}; + +struct boss_drakkari_colossusAI : public ScriptedAI +{ + boss_drakkari_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bHealth; + bool bHealth1; + + uint32 MightyBlowTimer; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, NOT_STARTED); + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->clearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); + me->SetReactState(REACT_PASSIVE); + MightyBlowTimer = 10*IN_MILISECONDS; + bHealth = false; + bHealth1 = false; + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, IN_PROGRESS); + } + + void CreatureState(Creature* pWho, bool bRestore = false) + { + if (!pWho) + return; + + if (bRestore) + { + pWho->clearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); + pWho->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pWho == me) + me->RemoveAura(SPELL_FREEZE_ANIM); + }else + { + pWho->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pWho->addUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); + if (pWho == me) + DoCast(me,SPELL_FREEZE_ANIM); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bHealth && HealthBelowPct(50) && !HealthBelowPct(5)) + { + CreatureState(me, false); + DoCast(me,SPELL_FREEZE_ANIM); + DoCast(me,SPELL_EMERGE); + bHealth = true; + } + + if (!bHealth1 && HealthBelowPct(5)) + { + DoCast(me,SPELL_EMERGE); + CreatureState(me, false); + bHealth1 = true; + me->RemoveAllAuras(); + } + + if (MightyBlowTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, true); + MightyBlowTimer = 10*IN_MILISECONDS; + } else MightyBlowTimer -= diff; + + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, DONE); + } + + void JustSummoned(Creature* pSummon) + { + if (HealthBelowPct(5)) + pSummon->DealDamage(pSummon, pSummon->GetHealth() * 0.5 , NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + pSummon->AI()->AttackStart(me->getVictim()); + } +}; + +struct boss_drakkari_elementalAI : public ScriptedAI +{ + boss_drakkari_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiSurgeTimer; + + bool bGoToColossus; + + void Reset() + { + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->CreatureState(me, true); + uiSurgeTimer = 7*IN_MILISECONDS; + bGoToColossus = false; + } + + void EnterEvadeMode() + { + me->RemoveFromWorld(); + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + { + CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->CreatureState(pColossus, true); + CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->bHealth1 = false; + } + me->RemoveFromWorld(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bGoToColossus && HealthBelowPct(50)) + { + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + { + if (!CAST_AI(boss_drakkari_colossusAI,pColossus->AI())->HealthBelowPct(6)) + { + me->InterruptNonMeleeSpells(true); + DoCast(pColossus, SPELL_MERGE); + bGoToColossus = true; + } + } + } + + if (uiSurgeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SURGE); + uiSurgeTimer = 7*IN_MILISECONDS; + } else uiSurgeTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + pColossus->Kill(pColossus); + } +}; + +struct npc_living_mojoAI : public ScriptedAI +{ + npc_living_mojoAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiMojoWaveTimer; + uint32 uiMojoPuddleTimer; + + void Reset() + { + uiMojoWaveTimer = 2*IN_MILISECONDS; + uiMojoPuddleTimer = 7*IN_MILISECONDS; + } + + void EnterCombat(Unit* /*who*/) + { + + //Check if the npc is near of Drakkari Colossus. + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + { + if (pColossus->isAlive() && me->IsInRange3d(pColossus->GetHomePosition().GetPositionX(),pColossus->GetHomePosition().GetPositionY(),pColossus->GetHomePosition().GetPositionZ(),0.0f,17.0f)) + me->SetReactState(REACT_PASSIVE); + else + me->SetReactState(REACT_AGGRESSIVE); + } + } + + void DamageTaken(Unit* pDone_by, uint32& /*uiDamage*/) + { + if (me->HasReactState(REACT_PASSIVE)) + { + if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) + { + if (pColossus->isAlive() && !pColossus->isInCombat()) + { + pColossus->RemoveAura(SPELL_FREEZE_ANIM); + pColossus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pColossus->SetReactState(REACT_AGGRESSIVE); + if (pDone_by && pDone_by->isAlive()) + pColossus->AI()->AttackStart(pDone_by); + EnterEvadeMode(); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiMojoWaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MOJO_WAVE); + uiMojoWaveTimer = 15*IN_MILISECONDS; + } else uiMojoWaveTimer -= diff; + + if (uiMojoPuddleTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MOJO_PUDDLE); + uiMojoPuddleTimer = 18*IN_MILISECONDS; + } else uiMojoPuddleTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_drakkari_colossus(Creature* pCreature) +{ + return new boss_drakkari_colossusAI (pCreature); +} + +CreatureAI* GetAI_boss_drakkari_elemental(Creature* pCreature) +{ + return new boss_drakkari_elementalAI (pCreature); +} + +CreatureAI* GetAI_npc_living_mojo(Creature* pCreature) +{ + return new npc_living_mojoAI (pCreature); +} + +void AddSC_boss_drakkari_colossus() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_drakkari_colossus"; + newscript->GetAI = &GetAI_boss_drakkari_colossus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_drakkari_elemental"; + newscript->GetAI = &GetAI_boss_drakkari_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_living_mojo"; + newscript->GetAI = &GetAI_npc_living_mojo; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Gundrak/boss_eck.cpp b/src/server/scripts/Northrend/Gundrak/boss_eck.cpp new file mode 100644 index 00000000000..3bf1a33da5a --- /dev/null +++ b/src/server/scripts/Northrend/Gundrak/boss_eck.cpp @@ -0,0 +1,168 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +enum Spells +{ + SPELL_ECK_BERSERK = 55816, //Eck goes berserk, increasing his attack speed by 150% and all damage he deals by 500%. + SPELL_ECK_BITE = 55813, //Eck bites down hard, inflicting 150% of his normal damage to an enemy. + SPELL_ECK_SPIT = 55814, //Eck spits toxic bile at enemies in a cone in front of him, inflicting 2970 Nature damage and draining 220 mana every 1 sec for 3 sec. + SPELL_ECK_SPRING_1 = 55815, //Eck leaps at a distant target. --> Drops aggro and charges a random player. Tank can simply taunt him back. + SPELL_ECK_SPRING_2 = 55837 //Eck leaps at a distant target. +}; + +static Position EckSpawnPoint = { 1643.877930, 936.278015, 107.204948, 0.668432 }; + +struct boss_eckAI : public ScriptedAI +{ + boss_eckAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBerserkTimer; + uint32 uiBiteTimer; + uint32 uiSpitTimer; + uint32 uiSpringTimer; + + bool bBerserk; + + ScriptedInstance* pInstance; + + void Reset() + { + uiBerserkTimer = urand(60*IN_MILISECONDS,90*IN_MILISECONDS); //60-90 secs according to wowwiki + uiBiteTimer = 5*IN_MILISECONDS; + uiSpitTimer = 10*IN_MILISECONDS; + uiSpringTimer = 8*IN_MILISECONDS; + + bBerserk = false; + + if (pInstance) + pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ECK_BITE); + uiBiteTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); + } else uiBiteTimer -= diff; + + if (uiSpitTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ECK_SPIT); + uiSpitTimer = urand(6*IN_MILISECONDS,14*IN_MILISECONDS); + } else uiSpitTimer -= diff; + + if (uiSpringTimer <= diff) + { + Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, RAND(SPELL_ECK_SPRING_1, SPELL_ECK_SPRING_2)); + uiSpringTimer = urand(5*IN_MILISECONDS,10*IN_MILISECONDS); + } + } else uiSpringTimer -= diff; + + //Berserk on timer or 20% of health + if (!bBerserk) + { + if (uiBerserkTimer <= diff) + { + DoCast(me, SPELL_ECK_BERSERK); + bBerserk = true; + } + else + { + uiBerserkTimer -= diff; + if (HealthBelowPct(20)) + { + DoCast(me, SPELL_ECK_BERSERK); + bBerserk = true; + } + } + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, DONE); + } +}; + +CreatureAI* GetAI_boss_eck(Creature* pCreature) +{ + return new boss_eckAI (pCreature); +} + +struct npc_ruins_dwellerAI : public ScriptedAI +{ + npc_ruins_dwellerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void JustDied(Unit * /*who*/) + { + if (pInstance) + { + pInstance->SetData64(DATA_RUIN_DWELLER_DIED,me->GetGUID()); + if (pInstance->GetData(DATA_ALIVE_RUIN_DWELLERS) == 0) + me->SummonCreature(CREATURE_ECK, EckSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300*IN_MILISECONDS); + } + } +}; + +CreatureAI* GetAI_npc_ruins_dweller(Creature* pCreature) +{ + return new npc_ruins_dwellerAI (pCreature); +} + +void AddSC_boss_eck() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_eck"; + newscript->GetAI = &GetAI_boss_eck; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ruins_dweller"; + newscript->GetAI = &GetAI_npc_ruins_dweller; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp b/src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp new file mode 100644 index 00000000000..c87a6600783 --- /dev/null +++ b/src/server/scripts/Northrend/Gundrak/boss_gal_darah.cpp @@ -0,0 +1,288 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +//Spells +enum Spells +{ + SPELL_ENRAGE = 55285, + H_SPELL_ENRAGE = 59828, + SPELL_IMPALING_CHARGE = 54956, + H_SPELL_IMPALING_CHARGE = 59827, + SPELL_STOMP = 55292, + H_SPELL_STOMP = 59829, + SPELL_PUNCTURE = 55276, + H_SPELL_PUNCTURE = 59826, + SPELL_STAMPEDE = 55218, + SPELL_WHIRLING_SLASH = 55250, + H_SPELL_WHIRLING_SLASH = 59824, + SPELL_ECK_RESIDUE = 55817 +}; + +//Yells +enum Yells +{ + SAY_AGGRO = -1604000, + SAY_SLAY_1 = -1604001, + SAY_SLAY_2 = -1604002, + SAY_SLAY_3 = -1604003, + SAY_DEATH = -1604004, + SAY_SUMMON_RHINO_1 = -1604005, + SAY_SUMMON_RHINO_2 = -1604006, + SAY_SUMMON_RHINO_3 = -1604007, + SAY_TRANSFORM_1 = -1604008, //Phase change + SAY_TRANSFORM_2 = -1604009 +}; + +enum Achievements +{ + ACHIEV_WHAT_THE_ECK = 1864, + ACHIEV_SHARE_THE_LOVE = 2152 +}; + +enum Displays +{ + DISPLAY_RHINO = 26265, + DISPLAY_TROLL = 27061 +}; + +enum CombatPhase +{ + TROLL, + RHINO +}; + +struct boss_gal_darahAI : public ScriptedAI +{ + boss_gal_darahAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiStampedeTimer; + uint32 uiWhirlingSlashTimer; + uint32 uiPunctureTimer; + uint32 uiEnrageTimer; + uint32 uiImpalingChargeTimer; + uint32 uiStompTimer; + uint32 uiTransformationTimer; + std::set lImpaledPlayers; + + CombatPhase Phase; + + uint8 uiPhaseCounter; + + bool bStartOfTransformation; + + ScriptedInstance* pInstance; + + void Reset() + { + uiStampedeTimer = 10*IN_MILISECONDS; + uiWhirlingSlashTimer = 21*IN_MILISECONDS; + uiPunctureTimer = 10*IN_MILISECONDS; + uiEnrageTimer = 15*IN_MILISECONDS; + uiImpalingChargeTimer = 21*IN_MILISECONDS; + uiStompTimer = 25*IN_MILISECONDS; + uiTransformationTimer = 9*IN_MILISECONDS; + uiPhaseCounter = 0; + + lImpaledPlayers.clear(); + + bStartOfTransformation = true; + + Phase = TROLL; + + me->SetDisplayId(DISPLAY_TROLL); + + if (pInstance) + pInstance->SetData(DATA_GAL_DARAH_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_GAL_DARAH_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + switch (Phase) + { + case TROLL: + if (uiPhaseCounter == 2) + { + if (uiTransformationTimer <= diff) + { + me->SetDisplayId(DISPLAY_RHINO); + Phase = RHINO; + uiPhaseCounter = 0; + DoScriptText(SAY_TRANSFORM_1, me); + uiTransformationTimer = 5*IN_MILISECONDS; + bStartOfTransformation = true; + me->clearUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); + me->SetReactState(REACT_AGGRESSIVE); + } + else + { + uiTransformationTimer -= diff; + + if (bStartOfTransformation) + { + bStartOfTransformation = false; + me->addUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); + me->SetReactState(REACT_PASSIVE); + } + } + } + else + { + if (uiStampedeTimer <= diff) + { + DoCast(me, SPELL_STAMPEDE); + DoScriptText(RAND(SAY_SUMMON_RHINO_1,SAY_SUMMON_RHINO_2,SAY_SUMMON_RHINO_3),me); + uiStampedeTimer = 15*IN_MILISECONDS; + } else uiStampedeTimer -= diff; + + if (uiWhirlingSlashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLING_SLASH); + uiWhirlingSlashTimer = 21*IN_MILISECONDS; + ++uiPhaseCounter; + } else uiWhirlingSlashTimer -= diff; + } + break; + case RHINO: + if (uiPhaseCounter == 2) + { + if (uiTransformationTimer <= diff) + { + me->SetDisplayId(DISPLAY_TROLL); + Phase = TROLL; + uiPhaseCounter = 0; + DoScriptText(SAY_TRANSFORM_2, me); + uiTransformationTimer = 9*IN_MILISECONDS; + bStartOfTransformation = true; + me->clearUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); + me->SetReactState(REACT_AGGRESSIVE); + } + else + { + uiTransformationTimer -= diff; + + if (bStartOfTransformation) + { + bStartOfTransformation = false; + me->addUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); + me->SetReactState(REACT_PASSIVE); + } + } + } + else + { + if (uiPunctureTimer <= diff) + { + DoCast(me->getVictim(), SPELL_PUNCTURE); + uiPunctureTimer = 8*IN_MILISECONDS; + } else uiPunctureTimer -= diff; + + if (uiEnrageTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ENRAGE); + uiEnrageTimer = 20*IN_MILISECONDS; + } else uiEnrageTimer -= diff; + + if (uiStompTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STOMP); + uiStompTimer = 20*IN_MILISECONDS; + } else uiStompTimer -= diff; + + if (uiImpalingChargeTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_IMPALING_CHARGE); + lImpaledPlayers.insert(pTarget->GetGUID()); + } + uiImpalingChargeTimer = 31*IN_MILISECONDS; + ++uiPhaseCounter; + } else uiImpalingChargeTimer -= diff; + } + break; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic()) + { + if (lImpaledPlayers.size() == 5) + pInstance->DoCompleteAchievement(ACHIEV_SHARE_THE_LOVE); + + AchievementEntry const *achievWhatTheEck = GetAchievementStore()->LookupEntry(ACHIEV_WHAT_THE_ECK); + if (achievWhatTheEck) + { + Map::PlayerList const &players = pInstance->instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (itr->getSource()->HasAura(SPELL_ECK_RESIDUE)) + itr->getSource()->CompletedAchievement(achievWhatTheEck); + } + } + + pInstance->SetData(DATA_GAL_DARAH_EVENT, DONE); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_gal_darah(Creature* pCreature) +{ + return new boss_gal_darahAI (pCreature); +} + +void AddSC_boss_gal_darah() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_gal_darah"; + newscript->GetAI = &GetAI_boss_gal_darah; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp b/src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp new file mode 100644 index 00000000000..84a7d8bc654 --- /dev/null +++ b/src/server/scripts/Northrend/Gundrak/boss_moorabi.cpp @@ -0,0 +1,175 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +enum eSpells +{ + SPELL_DETERMINED_STAB = 55104, + SPELL_GROUND_TREMOR = 55142, + SPELL_NUMBING_SHOUT = 55106, + SPELL_DETERMINED_GORE = 55102, + H_SPELL_DETERMINED_GORE = 59444, + SPELL_QUAKE = 55101, + SPELL_NUMBING_ROAR = 55100, + SPELL_MOJO_FRENZY = 55163, + SPELL_TRANSFORMATION = 55098, //Periodic, The caster transforms into a powerful mammoth, increasing Physical damage done by 25% and granting immunity to Stun effects. +}; + +enum eArchivements +{ + ACHIEV_LESS_RABI = 2040 +}; + +enum eSays +{ + SAY_AGGRO = -1604010, + //SAY_SLAY_1 = -1604011, // not in db + SAY_SLAY_2 = -1604012, + SAY_SLAY_3 = -1604013, + SAY_DEATH = -1604014, + SAY_TRANSFORM = -1604015, + SAY_QUAKE = -1604016, + EMOTE_TRANSFORM = -1604017 +}; + +struct boss_moorabiAI : public ScriptedAI +{ + boss_moorabiAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bPhase; + + uint32 uiNumblingShoutTimer; + uint32 uiGroundTremorTimer; + uint32 uiDeterminedStabTimer; + uint32 uiTransformationTImer; + + void Reset() + { + uiGroundTremorTimer = 18*IN_MILISECONDS; + uiNumblingShoutTimer = 10*IN_MILISECONDS; + uiDeterminedStabTimer = 20*IN_MILISECONDS; + uiTransformationTImer = 12*IN_MILISECONDS; + bPhase = false; + + if (pInstance) + pInstance->SetData(DATA_MOORABI_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_MOJO_FRENZY, true); + + if (pInstance) + pInstance->SetData(DATA_MOORABI_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bPhase && me->HasAura(SPELL_TRANSFORMATION)) + { + bPhase = true; + me->RemoveAura(SPELL_MOJO_FRENZY); + } + + if (uiGroundTremorTimer <= uiDiff) + { + DoScriptText(SAY_QUAKE, me); + if (bPhase) + DoCast(me->getVictim(), SPELL_QUAKE, true); + else + DoCast(me->getVictim(), SPELL_GROUND_TREMOR, true); + uiGroundTremorTimer = 10*IN_MILISECONDS; + } else uiGroundTremorTimer -= uiDiff; + + if (uiNumblingShoutTimer <= uiDiff) + { + if (bPhase) + DoCast(me->getVictim(), SPELL_NUMBING_ROAR, true); + else + DoCast(me->getVictim(), SPELL_NUMBING_SHOUT, true); + uiNumblingShoutTimer = 10*IN_MILISECONDS; + } else uiNumblingShoutTimer -=uiDiff; + + if (uiDeterminedStabTimer <= uiDiff) + { + if (bPhase) + DoCast(me->getVictim(), SPELL_DETERMINED_GORE); + else + DoCast(me->getVictim(), SPELL_DETERMINED_STAB, true); + uiDeterminedStabTimer = 8*IN_MILISECONDS; + } else uiDeterminedStabTimer -=uiDiff; + + if (!bPhase && uiTransformationTImer <= uiDiff) + { + DoScriptText(EMOTE_TRANSFORM, me); + DoScriptText(SAY_TRANSFORM, me); + DoCast(me, SPELL_TRANSFORMATION, false); + uiTransformationTImer = 10*IN_MILISECONDS; + } else uiTransformationTImer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_MOORABI_EVENT, DONE); + + if (IsHeroic() && !bPhase) + pInstance->DoCompleteAchievement(ACHIEV_LESS_RABI); + } + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim == me) + return; + + DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_moorabi(Creature *pCreature) +{ + return new boss_moorabiAI(pCreature); +} + +void AddSC_boss_moorabi() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_moorabi"; + newscript->GetAI = &GetAI_boss_moorabi; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp new file mode 100644 index 00000000000..1014beaeddd --- /dev/null +++ b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp @@ -0,0 +1,266 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +//Spells +enum Spells +{ + SPELL_POISON_NOVA = 55081, + H_SPELL_POISON_NOVA = 59842, + SPELL_POWERFULL_BITE = 48287, + H_SPELL_POWERFULL_BITE = 59840, + SPELL_VENOM_BOLT = 54970, + H_SPELL_VENOM_BOLT = 59839 +}; + +//Yell +enum Yells +{ + SAY_AGGRO = -1604017, + SAY_SLAY_1 = -1604018, + SAY_SLAY_2 = -1604019, + SAY_SLAY_3 = -1604020, + SAY_DEATH = -1604021, + SAY_SUMMON_SNAKES = -1604022, + SAY_SUMMON_CONSTRICTORS = -1604023 +}; + +//Creatures +enum Creatures +{ + CREATURE_SNAKE = 29680, + CREATURE_CONSTRICTORS = 29713 +}; + +//Creatures' spells +enum ConstrictorSpells +{ + SPELL_GRIP_OF_SLAD_RAN = 55093, + SPELL_VENOMOUS_BITE = 54987, + H_SPELL_VENOMOUS_BITE = 58996 +}; + +static Position SpawnLoc[]= +{ + {1783.81, 646.637, 133.948, 3.71755}, + {1775.03, 606.586, 134.165, 1.43117}, + {1717.39, 630.041, 129.282, 5.96903}, + {1765.66, 646.542, 134.02, 5.11381}, + {1716.76, 635.159, 129.282, 0.191986} +}; + +struct boss_slad_ranAI : public ScriptedAI +{ + boss_slad_ranAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiPoisonNovaTimer; + uint32 uiPowerfullBiteTimer; + uint32 uiVenomBoltTimer; + uint32 uiSpawnTimer; + + uint8 uiPhase; + + SummonList lSummons; + + ScriptedInstance* pInstance; + + void Reset() + { + uiPoisonNovaTimer = 10*IN_MILISECONDS; + uiPowerfullBiteTimer = 3*IN_MILISECONDS; + uiVenomBoltTimer = 15*IN_MILISECONDS; + uiSpawnTimer = 5*IN_MILISECONDS; + uiPhase = 0; + + lSummons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_SLAD_RAN_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_SLAD_RAN_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiPoisonNovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_NOVA); + uiPoisonNovaTimer = 15*IN_MILISECONDS; + } else uiPoisonNovaTimer -= diff; + + if (uiPowerfullBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POWERFULL_BITE); + uiPowerfullBiteTimer = 10*IN_MILISECONDS; + } else uiPowerfullBiteTimer -= diff; + + if (uiVenomBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_VENOM_BOLT); + uiVenomBoltTimer = 10*IN_MILISECONDS; + } else uiVenomBoltTimer -= diff; + + if (uiPhase) + { + if (uiSpawnTimer <= diff) + { + if (uiPhase == 1) + for (uint8 i = 0; i < DUNGEON_MODE(3, 5); ++i) + me->SummonCreature(CREATURE_SNAKE, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); + if (uiPhase == 2) + for (uint8 i = 0; i < DUNGEON_MODE(3, 5); ++i) + me->SummonCreature(CREATURE_CONSTRICTORS, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); + uiSpawnTimer = 5*IN_MILISECONDS; + } else uiSpawnTimer -= diff; + } + + if (uiPhase == 0 && HealthBelowPct(30)) + { + DoScriptText(SAY_SUMMON_SNAKES,me); + uiPhase = 1; + } + + if (uiPhase == 1 && HealthBelowPct(25)) + { + DoScriptText(SAY_SUMMON_CONSTRICTORS,me); + uiPhase = 2; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_SLAD_RAN_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustSummoned(Creature* summoned) + { + summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); + lSummons.Summon(summoned); + } +}; + +struct mob_slad_ran_constrictorAI : public ScriptedAI +{ + mob_slad_ran_constrictorAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiGripOfSladRanTimer; + + void Reset() + { + uiGripOfSladRanTimer = 1*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + if (uiGripOfSladRanTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GRIP_OF_SLAD_RAN); + uiGripOfSladRanTimer = 5*IN_MILISECONDS; + } else uiGripOfSladRanTimer -= diff; + } + + ScriptedInstance* pInstance; +}; + +struct mob_slad_ran_viperAI : public ScriptedAI +{ + mob_slad_ran_viperAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiVenomousBiteTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiVenomousBiteTimer = 2*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiVenomousBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_VENOMOUS_BITE); + uiVenomousBiteTimer = 10*IN_MILISECONDS; + } else uiVenomousBiteTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_slad_ran(Creature* pCreature) +{ + return new boss_slad_ranAI (pCreature); +} + +CreatureAI* GetAI_mob_slad_ran_constrictor(Creature* pCreature) +{ + return new mob_slad_ran_constrictorAI (pCreature); +} + +CreatureAI* GetAI_mob_slad_ran_viper(Creature* pCreature) +{ + return new mob_slad_ran_viperAI (pCreature); +} + +void AddSC_boss_slad_ran() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_slad_ran"; + newscript->GetAI = &GetAI_boss_slad_ran; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_slad_ran_constrictor"; + newscript->GetAI = &GetAI_mob_slad_ran_constrictor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_slad_ran_viper"; + newscript->GetAI = &GetAI_mob_slad_ran_viper; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Gundrak/gundrak.h b/src/server/scripts/Northrend/Gundrak/gundrak.h new file mode 100644 index 00000000000..a443aa4e698 --- /dev/null +++ b/src/server/scripts/Northrend/Gundrak/gundrak.h @@ -0,0 +1,54 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DEF_GUNDRAK_H +#define DEF_GUNDRAK_H + +enum Data +{ + DATA_SLAD_RAN_EVENT, + DATA_MOORABI_EVENT, + DATA_DRAKKARI_COLOSSUS_EVENT, + DATA_GAL_DARAH_EVENT, + DATA_ECK_THE_FEROCIOUS_EVENT, + DATA_ALIVE_RUIN_DWELLERS +}; + +enum Data64 +{ + DATA_SLAD_RAN_ALTAR, + DATA_MOORABI_ALTAR, + DATA_DRAKKARI_COLOSSUS_ALTAR, + DATA_SLAD_RAN_STATUE, + DATA_MOORABI_STATUE, + DATA_DRAKKARI_COLOSSUS_STATUE, + DATA_DRAKKARI_COLOSSUS, + DATA_RUIN_DWELLER_DIED +}; + +enum mainCreatures +{ + CREATURE_RUIN_DWELLER = 29920, + CREATURE_SLAD_RAN = 29304, + CREATURE_MOORABI = 29305, + CREATURE_GALDARAH = 29306, + CREATURE_DRAKKARICOLOSSUS = 29307, + CREATURE_ECK = 29932 +}; + +#endif diff --git a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp new file mode 100644 index 00000000000..4dd896f74f2 --- /dev/null +++ b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp @@ -0,0 +1,536 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "gundrak.h" + +#define MAX_ENCOUNTER 5 + +/* GunDrak encounters: +0 - Slad'Ran +1 - Moorabi +2 - Drakkari Colossus +3 - Gal'Darah +4 - Eck the Ferocious +*/ + +struct instance_gundrak : public ScriptedInstance +{ + instance_gundrak(Map* pMap) : ScriptedInstance(pMap) + { + bHeroicMode = pMap->IsHeroic(); + Initialize(); + }; + + bool bHeroicMode; + bool spawnSupport; + + uint32 timer; + uint32 phase; + uint64 toActivate; + + uint64 uiSladRan; + uint64 uiMoorabi; + uint64 uiDrakkariColossus; + uint64 uiGalDarah; + uint64 uiEckTheFerocious; + + uint64 uiSladRanAltar; + uint64 uiMoorabiAltar; + uint64 uiDrakkariColossusAltar; + uint64 uiSladRanStatue; + uint64 uiMoorabiStatue; + uint64 uiDrakkariColossusStatue; + uint64 uiGalDarahStatue; + uint64 uiEckTheFerociousDoor; + uint64 uiEckTheFerociousDoorBehind; + uint64 uiGalDarahDoor1; + uint64 uiGalDarahDoor2; + uint64 uiBridge; + uint64 uiCollision; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + GOState uiSladRanStatueState; + GOState uiMoorabiStatueState; + GOState uiDrakkariColossusStatueState; + GOState uiGalDarahStatueState; + GOState uiBridgeState; + GOState uiCollisionState; + + std::set DwellerGUIDs; + + std::string str_data; + + void Initialize() + { + spawnSupport = false; + + timer = 0; + phase = 0; + toActivate = 0; + + uiSladRan = 0; + uiMoorabi = 0; + uiDrakkariColossus = 0; + uiGalDarah = 0; + uiEckTheFerocious = 0; + + uiSladRanAltar = 0; + uiMoorabiAltar = 0; + uiDrakkariColossusAltar = 0; + + uiSladRanStatue = 0; + uiMoorabiStatue = 0; + uiDrakkariColossusStatue = 0; + uiGalDarahStatue = 0; + + uiEckTheFerociousDoor = 0; + uiEckTheFerociousDoorBehind = 0; + uiGalDarahDoor1 = 0; + uiGalDarahDoor2 = 0; + + uiBridge = 0; + uiCollision = 0; + + uiSladRanStatueState = GO_STATE_ACTIVE; + uiMoorabiStatueState = GO_STATE_ACTIVE; + uiDrakkariColossusStatueState = GO_STATE_ACTIVE; + uiGalDarahStatueState = GO_STATE_READY; + uiBridgeState = GO_STATE_ACTIVE; + uiCollisionState = GO_STATE_READY; + + DwellerGUIDs.clear(); + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case CREATURE_SLAD_RAN: uiSladRan = pCreature->GetGUID(); break; + case CREATURE_MOORABI: uiMoorabi = pCreature->GetGUID(); break; + case CREATURE_GALDARAH: uiGalDarah = pCreature->GetGUID(); break; + case CREATURE_DRAKKARICOLOSSUS: uiDrakkariColossus = pCreature->GetGUID(); break; + case CREATURE_ECK: uiEckTheFerocious = pCreature->GetGUID(); break; + case CREATURE_RUIN_DWELLER: + if (pCreature->isAlive()) + DwellerGUIDs.insert(pCreature->GetGUID()); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 192518: + uiSladRanAltar = pGo->GetGUID(); + // Make sure that they start out as unusuable + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + if (m_auiEncounter[0] == DONE) + { + if (uiSladRanStatueState == GO_STATE_ACTIVE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + else + { + ++phase; + pGo->SetGoState(GO_STATE_ACTIVE); + } + } + break; + case 192519: + uiMoorabiAltar = pGo->GetGUID(); + // Make sure that they start out as unusuable + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + if (m_auiEncounter[0] == DONE) + { + if (uiMoorabiStatueState == GO_STATE_ACTIVE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + else + { + ++phase; + pGo->SetGoState(GO_STATE_ACTIVE); + } + } + break; + case 192520: + uiDrakkariColossusAltar = pGo->GetGUID(); + // Make sure that they start out as unusuable + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + if (m_auiEncounter[0] == DONE) + { + if (uiDrakkariColossusStatueState == GO_STATE_ACTIVE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + else + { + ++phase; + pGo->SetGoState(GO_STATE_ACTIVE); + } + } + break; + case 192564: + uiSladRanStatue = pGo->GetGUID(); + pGo->SetGoState(uiSladRanStatueState); + break; + case 192565: + uiMoorabiStatue = pGo->GetGUID(); + pGo->SetGoState(uiMoorabiStatueState); + break; + case 192566: + uiGalDarahStatue = pGo->GetGUID(); + pGo->SetGoState(uiGalDarahStatueState); + break; + case 192567: + uiDrakkariColossusStatue = pGo->GetGUID(); + pGo->SetGoState(uiDrakkariColossusStatueState); + break; + case 192632: + uiEckTheFerociousDoor = pGo->GetGUID(); + if (bHeroicMode && m_auiEncounter[1] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 192569: + uiEckTheFerociousDoorBehind = pGo->GetGUID(); + if (bHeroicMode && m_auiEncounter[4] == DONE) + HandleGameObject(NULL,true,pGo); + case 193208: + uiGalDarahDoor1 = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 193209: + uiGalDarahDoor2 = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 193188: + uiBridge = pGo->GetGUID(); + pGo->SetGoState(uiBridgeState); + break; + case 192633: + uiCollision = pGo->GetGUID(); + pGo->SetGoState(uiCollisionState); + + // Can't spawn here with SpawnGameObject because pGo isn't added to world yet... + if (uiCollisionState == GO_STATE_ACTIVE_ALTERNATIVE) + spawnSupport = true; + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_SLAD_RAN_EVENT: + m_auiEncounter[0] = data; + if (data == DONE) + { + GameObject* pGo = instance->GetGameObject(uiSladRanAltar); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + } + break; + case DATA_MOORABI_EVENT: + m_auiEncounter[1] = data; + if (data == DONE) + { + GameObject* pGo = instance->GetGameObject(uiMoorabiAltar); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + if (bHeroicMode) + HandleGameObject(uiEckTheFerociousDoor,true); + } + break; + case DATA_DRAKKARI_COLOSSUS_EVENT: + m_auiEncounter[2] = data; + if (data == DONE) + { + GameObject* pGo = instance->GetGameObject(uiDrakkariColossusAltar); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); + } + break; + case DATA_GAL_DARAH_EVENT: + m_auiEncounter[3] = data; + if (data == DONE) + { + HandleGameObject(uiGalDarahDoor1,true); + HandleGameObject(uiGalDarahDoor2,true); + } + break; + case DATA_ECK_THE_FEROCIOUS_EVENT: + m_auiEncounter[4] = data; + if (bHeroicMode && data == DONE) + HandleGameObject(uiEckTheFerociousDoorBehind,true); + break; + } + + if (data == DONE) + SaveToDB(); + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_RUIN_DWELLER_DIED) + DwellerGUIDs.erase(data); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_SLAD_RAN_EVENT: return m_auiEncounter[0]; + case DATA_MOORABI_EVENT: return m_auiEncounter[1]; + case DATA_GAL_DARAH_EVENT: return m_auiEncounter[2]; + case DATA_DRAKKARI_COLOSSUS_EVENT: return m_auiEncounter[3]; + case DATA_ECK_THE_FEROCIOUS_EVENT: return m_auiEncounter[4]; + case DATA_ALIVE_RUIN_DWELLERS: return DwellerGUIDs.size(); + } + + return 0; + } + + uint64 GetData64(uint32 type) + { + switch(type) + { + case DATA_SLAD_RAN_ALTAR: return uiSladRanAltar; + case DATA_MOORABI_ALTAR: return uiMoorabiAltar; + case DATA_DRAKKARI_COLOSSUS_ALTAR: return uiDrakkariColossusAltar; + case DATA_SLAD_RAN_STATUE: return uiSladRanStatue; + case DATA_MOORABI_STATUE: return uiMoorabiStatue; + case DATA_DRAKKARI_COLOSSUS_STATUE: return uiDrakkariColossusStatue; + case DATA_DRAKKARI_COLOSSUS: return uiDrakkariColossus; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "G D " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " + << (uiSladRanStatue ? GetObjState(uiSladRanStatue) : GO_STATE_ACTIVE) << " " << (uiMoorabiStatue ? GetObjState(uiMoorabiStatue) : GO_STATE_ACTIVE) << " " + << (uiDrakkariColossusStatue ? GetObjState(uiDrakkariColossusStatue) : GO_STATE_ACTIVE) << " " << (uiGalDarahStatue ? GetObjState(uiGalDarahStatue) : GO_STATE_READY) << " " + << (uiBridge ? GetObjState(uiBridge) : GO_STATE_ACTIVE) << " " << (uiCollision ? GetObjState(uiCollision) : GO_STATE_READY); + + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 + >> data4 >> data5 >> data6 >> data7 >> data8 >> data9 >> data10; + + if (dataHead1 == 'G' && dataHead2 == 'D') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + uiSladRanStatueState = GOState(data5); + uiMoorabiStatueState = GOState(data6); + uiDrakkariColossusStatueState = GOState(data7); + uiGalDarahStatueState = GOState(data8); + uiBridgeState = GOState(data9); + uiCollisionState = GOState(data10); + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + bool QueueActivation(uint64 guid, uint32 time) + { + if (timer) + return false; + + toActivate = guid; + timer = time; + phase++; + return true; + } + + void Update(uint32 diff) + { + // Spawn the support for the bridge if necessary + if (spawnSupport) + { + if (GameObject* pCollision = instance->GetGameObject(uiCollision)) + pCollision->SummonGameObject(192743, pCollision->GetPositionX(), pCollision->GetPositionY(), pCollision->GetPositionZ(), pCollision->GetOrientation(), 0, 0, 0, 0, 0); + spawnSupport = false; + } + + // If there is nothing to activate, then return + if (!toActivate) + return; + + if (timer < diff) + { + timer = 0; + if (toActivate == uiBridge) + { + toActivate = 0; + GameObject* pBridge = instance->GetGameObject(uiBridge); + GameObject* pCollision = instance->GetGameObject(uiCollision); + GameObject* pSladRanStatue = instance->GetGameObject(uiSladRanStatue); + GameObject* pMoorabiStatue = instance->GetGameObject(uiMoorabiStatue); + GameObject* pDrakkariColossusStatue = instance->GetGameObject(uiDrakkariColossusStatue); + GameObject* pGalDarahStatue = instance->GetGameObject(uiGalDarahStatue); + + if (pBridge && pCollision && pSladRanStatue && pMoorabiStatue && pDrakkariColossusStatue && pGalDarahStatue) + { + pBridge->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pCollision->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pSladRanStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pMoorabiStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pDrakkariColossusStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + pGalDarahStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + + // Add the GO that solidifies the bridge so you can walk on it + spawnSupport = true; + SaveToDB(); + } + } + else + { + uint32 spell = 0; + GameObject* pAltar = NULL; + if (toActivate == uiSladRanStatue) + { + spell = 57071; + pAltar = instance->GetGameObject(uiSladRanAltar); + } else if (toActivate == uiMoorabiStatue) + { + spell = 57068; + pAltar = instance->GetGameObject(uiMoorabiAltar); + } else if (toActivate == uiDrakkariColossusStatue) + { + spell = 57072; + pAltar = instance->GetGameObject(uiDrakkariColossusAltar); + } + + // This is a workaround to make the beam cast properly. The caster should be ID 30298 but since the spells + // all are with scripted target for that same ID, it will hit itself. + if (pAltar) + if (Creature* trigger = pAltar->SummonCreature(18721, pAltar->GetPositionX(), pAltar->GetPositionY(), pAltar->GetPositionZ() + 3, pAltar->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 5000)) + { + // Set the trigger model to invisible + trigger->SetDisplayId(11686); + trigger->CastSpell(trigger, spell, false); + } + + if (GameObject* statueGO = instance->GetGameObject(toActivate)) + statueGO->SetGoState(GO_STATE_READY); + + toActivate = 0; + + if (phase == 3) + QueueActivation(uiBridge, 3000); + else + SaveToDB(); // Don't save in between last statue and bridge turning in case of crash leading to stuck instance + } + } else timer -= diff; + } + + GOState GetObjState(uint64 guid) + { + if (GameObject* go = instance->GetGameObject(guid)) + return go->GetGoState(); + return GO_STATE_ACTIVE; + } +}; + +bool GOHello_altar(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + uint64 uiStatue = 0; + + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + if (pInstance) + { + switch(pGO->GetEntry()) + { + case 192518: uiStatue = pInstance->GetData64(DATA_SLAD_RAN_STATUE); break; + case 192519: uiStatue = pInstance->GetData64(DATA_MOORABI_STATUE); break; + case 192520: uiStatue = pInstance->GetData64(DATA_DRAKKARI_COLOSSUS_STATUE); break; + } + if (((instance_gundrak*)pInstance)->QueueActivation(uiStatue, 3500)) + { + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + } + return true; + } + return false; +} + +InstanceData* GetInstanceData_instance_gundrak(Map* pMap) +{ + return new instance_gundrak(pMap); +} + +void AddSC_instance_gundrak() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_gundrak"; + newscript->GetInstanceData = &GetInstanceData_instance_gundrak; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_gundrak_altar"; + newscript->pGOHello = &GOHello_altar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp new file mode 100644 index 00000000000..896eb068eb6 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -0,0 +1,185 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SAY_GREET RAND(-1533000,-1533004,-1533005,-1533006,-1533007) +#define SAY_AGGRO RAND(-1533001,-1533002,-1533003) +#define SAY_SLAY -1533008 + +#define MOB_CRYPT_GUARD 16573 + +const Position GuardSummonPos = {3333.72, -3476.30, 287.1, 6.2801}; + +enum Events +{ + EVENT_NONE, + EVENT_IMPALE, + EVENT_LOCUST, + EVENT_SPAWN_GUARDIAN_NORMAL, + EVENT_BERSERK, +}; + +enum Spells +{ + SPELL_IMPALE_10 = 28783, + SPELL_IMPALE_25 = 56090, + SPELL_LOCUST_SWARM_10 = 28785, + SPELL_LOCUST_SWARM_25 = 54021, + SPELL_SUMMON_CORPSE_SCARABS_PLR = 29105, // This spawns 5 corpse scarabs on top of player + SPELL_SUMMON_CORPSE_SCARABS_MOB = 28864, // This spawns 10 corpse scarabs on top of dead guards + SPELL_BERSERK = 27680, +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 9891, +}; + +struct boss_anubrekhanAI : public BossAI +{ + boss_anubrekhanAI(Creature *c) : BossAI(c, BOSS_ANUBREKHAN) {} + + bool hasTaunted; + + void Reset() + { + _Reset(); + + hasTaunted = false; + + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + { + Position pos; + + // respawn guard using home position, + // otherwise, after a wipe, they respawn where boss was at wipe moment. + pos = me->GetHomePosition(); + pos.m_positionY -= 10.0f; + me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); + + pos = me->GetHomePosition(); + pos.m_positionY += 10.0f; + me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); + } + } + + void KilledUnit(Unit* victim) + { + //Force the player to spawn corpse scarabs via spell, TODO: Check percent chance for scarabs, 20% at the moment + if (!(rand()%5)) + if (victim->GetTypeId() == TYPEID_PLAYER) + victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, NULL, NULL, me->GetGUID()); + + DoScriptText(SAY_SLAY, me); + } + + void JustDied(Unit *) + { + _JustDied(); + + // start achievement timer (kill Maexna within 20 min) + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO, me); + events.ScheduleEvent(EVENT_IMPALE, 10000 + rand()%10000); + events.ScheduleEvent(EVENT_LOCUST, 90000); + events.ScheduleEvent(EVENT_BERSERK, 600000); + + if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000,20000)); + } + + void MoveInLineOfSight(Unit *who) + { + if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(SAY_GREET, me); + hasTaunted = true; + } + ScriptedAI::MoveInLineOfSight(who); + } + + void SummonedCreatureDespawn(Creature *summon) + { + BossAI::SummonedCreatureDespawn(summon); + + // check if it is an actual killed guard + if (!me->isAlive() || summon->isAlive() || summon->GetEntry() != MOB_CRYPT_GUARD) + return; + + summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, NULL, NULL, me->GetGUID()); + } + + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || !CheckInRoom()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_IMPALE: + //Cast Impale on a random target + //Do NOT cast it when we are afflicted by locust swarm + if (!me->HasAura(RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25))) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_IMPALE_10,SPELL_IMPALE_25)); + events.ScheduleEvent(EVENT_IMPALE, urand(10000,20000)); + break; + case EVENT_LOCUST: + // TODO : Add Text + DoCast(me, RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25)); + DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); + events.ScheduleEvent(EVENT_LOCUST, 90000); + break; + case EVENT_SPAWN_GUARDIAN_NORMAL: + // TODO : Add Text + DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); + break; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK, true); + events.ScheduleEvent(EVENT_BERSERK, 600000); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_anubrekhan(Creature* pCreature) +{ + return new boss_anubrekhanAI (pCreature); +} + +void AddSC_boss_anubrekhan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_anubrekhan"; + newscript->GetAI = &GetAI_boss_anubrekhan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp new file mode 100644 index 00000000000..aa5a940eb8f --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Yells +{ + SAY_GREET = -1533009, + SAY_AGGRO_1 = -1533010, + SAY_AGGRO_2 = -1533011, + SAY_AGGRO_3 = -1533012, + SAY_AGGRO_4 = -1533013, + SAY_SLAY_1 = -1533014, + SAY_SLAY_2 = -1533015, + SAY_DEATH = -1533016 +}; +//#define SOUND_RANDOM_AGGRO 8955 //soundId containing the 4 aggro sounds, we not using this + +enum Spells +{ + SPELL_POISON_BOLT_VOLLEY = 28796, + H_SPELL_POISON_BOLT_VOLLEY = 54098, + SPELL_RAIN_OF_FIRE = 28794, + H_SPELL_RAIN_OF_FIRE = 54099, + SPELL_FRENZY = 28798, + H_SPELL_FRENZY = 54100, + SPELL_WIDOWS_EMBRACE = 28732, + H_SPELL_WIDOWS_EMBRACE = 54097 +}; + +enum Events +{ + EVENT_NONE, + EVENT_POISON, + EVENT_FIRE, + EVENT_FRENZY +}; + +enum Achievements +{ + ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10 = 1997, + ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25 = 2140 +}; + +struct boss_faerlinaAI : public BossAI +{ + boss_faerlinaAI(Creature *c) : BossAI(c, BOSS_FAERLINA), greet(false) {} + + bool greet; + bool doDelayFrenzy; + bool bAchievement; + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4), me); + events.ScheduleEvent(EVENT_POISON, urand(10000,15000)); + events.ScheduleEvent(EVENT_FIRE, urand(6000,18000)); + events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000)); + } + + void Reset() + { + doDelayFrenzy = false; + bAchievement = true; + _Reset(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!greet && who->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(SAY_GREET, me); + greet = true; + } + BossAI::MoveInLineOfSight(who); + } + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%3)) + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + + if (instance && bAchievement) + instance->DoCompleteAchievement(RAID_MODE(ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10,ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25)); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (doDelayFrenzy && !me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE, H_SPELL_WIDOWS_EMBRACE))) + { + doDelayFrenzy = false; + DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY), true); + } + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_POISON: + if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE))) + DoCastAOE(RAID_MODE(SPELL_POISON_BOLT_VOLLEY,H_SPELL_POISON_BOLT_VOLLEY)); + events.ScheduleEvent(EVENT_POISON, urand(8000,15000)); + break; + case EVENT_FIRE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_RAIN_OF_FIRE, H_SPELL_RAIN_OF_FIRE)); + events.ScheduleEvent(EVENT_FIRE, urand(6000,18000)); + break; + case EVENT_FRENZY: + // TODO : Add Text + if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE))) + DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY)); + else + doDelayFrenzy = true; + + events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000)); + break; + } + } + + DoMeleeAttackIfReady(); + } + + void SpellHit(Unit* caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_WIDOWS_EMBRACE || spell->Id == H_SPELL_WIDOWS_EMBRACE) + { + // TODO : Add Text + bAchievement = false; + doDelayFrenzy = true; + me->Kill(caster); + } + } +}; + +CreatureAI* GetAI_boss_faerlina(Creature* pCreature) +{ + return new boss_faerlinaAI (pCreature); +} + +struct mob_faerlina_addAI : public ScriptedAI +{ + mob_faerlina_addAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) { + me->ApplySpellImmune(0, IMMUNITY_MECHANIC, SPELL_EFFECT_BIND, true); + me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true); + } + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance && getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + { + if (Creature *pFaerlina = pInstance->instance->GetCreature(pInstance->GetData64(DATA_FAERLINA))) + DoCast(pFaerlina, SPELL_WIDOWS_EMBRACE); + } + } +}; + +CreatureAI* GetAI_mob_faerlina_add(Creature* pCreature) +{ + return new mob_faerlina_addAI (pCreature); +} + +void AddSC_boss_faerlina() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_faerlina"; + newscript->GetAI = &GetAI_boss_faerlina; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_faerlina_add"; + newscript->GetAI = &GetAI_mob_faerlina_add; + newscript->RegisterSelf(); +} + + diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp new file mode 100644 index 00000000000..f04b39040db --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -0,0 +1,397 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Horsemen +{ + HORSEMEN_THANE, + HORSEMEN_LADY, + HORSEMEN_BARON, + HORSEMEN_SIR, +}; + +enum Events +{ + EVENT_NONE, + EVENT_MARK, + EVENT_CAST, + EVENT_BERSERK, +}; + +const Position WaypointPositions[12] = +{ + // Thane waypoints + {2542.3, -2984.1, 241.49, 5.362}, + {2547.6, -2999.4, 241.34, 5.049}, + {2542.9, -3015.0, 241.35, 4.654}, + // Lady waypoints + {2498.3, -2961.8, 241.28, 3.267}, + {2487.7, -2959.2, 241.28, 2.890}, + {2469.4, -2947.6, 241.28, 2.576}, + // Baron waypoints + {2553.8, -2968.4, 241.33, 5.757}, + {2564.3, -2972.5, 241.33, 5.890}, + {2583.9, -2971.67, 241.35, 0.008}, + // Sir waypoints + {2534.5, -2921.7, 241.53, 1.363}, + {2523.5, -2902.8, 241.28, 2.095}, + {2517.8, -2896.6, 241.28, 2.315}, +}; + +const uint32 MOB_HORSEMEN[] = {16064, 16065, 30549, 16063}; +const uint32 SPELL_MARK[] = {28832, 28833, 28834, 28835}; +#define SPELL_PRIMARY(i) RAID_MODE(SPELL_PRIMARY_N[i],SPELL_PRIMARY_H[i]) +const uint32 SPELL_PRIMARY_N[] = {28884, 28863, 28882, 28883}; +const uint32 SPELL_PRIMARY_H[] = {57467, 57463, 57369, 57466}; +#define SPELL_SECONDARY(i) RAID_MODE(SPELL_SECONDARY_N[i],SPELL_SECONDARY_H[i]) +const uint32 SPELL_SECONDARY_N[]= {0, 57374, 0, 57376}; +const uint32 SPELL_SECONDARY_H[]= {0, 57464, 0, 57465}; +const uint32 SPELL_PUNISH[] = {0, 57381, 0, 57377}; +#define SPELL_BERSERK 26662 + +// used by 16063,16064,16065,30549, but signed for 16063 +const int32 SAY_AGGRO[] = {-1533051, -1533044, -1533065, -1533058}; +const int32 SAY_TAUNT[3][4] ={ {-1533052, -1533045, -1533071, -1533059}, + {-1533053, -1533046, -1533072, -1533060}, + {-1533054, -1533047, -1533073, -1533061},}; +const int32 SAY_SPECIAL[] = {-1533055, -1533048, -1533070, -1533062}; +const int32 SAY_SLAY[] = {-1533056, -1533049, -1533068, -1533063}; +const int32 SAY_DEATH[] = {-1533057, -1533050, -1533074, -1533064}; + +#define SAY_BARON_AGGRO RAND(-1533065,-1533066,-1533067) +#define SAY_BARON_SLAY RAND(-1533068,-1533069) + +struct boss_four_horsemenAI : public BossAI +{ + boss_four_horsemenAI(Creature *c) : BossAI(c, BOSS_HORSEMEN) + { + id = Horsemen(0); + for (uint8 i = 0; i < 4; ++i) + if (me->GetEntry() == MOB_HORSEMEN[i]) + id = Horsemen(i); + caster = (id == HORSEMEN_LADY || id == HORSEMEN_SIR); + } + + Horsemen id; + uint64 uiEventStarterGUID; + uint8 nextWP; + uint32 punishTimer; + bool caster; + bool nextMovementStarted; + bool movementCompleted; + bool movementStarted; + bool encounterActionAttack; + bool encounterActionReset; + bool doDelayPunish; + + void Reset() + { + if (!encounterActionReset) + DoEncounterAction(NULL, false, true, false); + + if (instance) + instance->SetData(DATA_HORSEMEN0 + id, NOT_STARTED); + + me->SetReactState(REACT_AGGRESSIVE); + uiEventStarterGUID = 0; + nextWP = 0; + punishTimer = 2000; + nextMovementStarted = false; + movementCompleted = false; + movementStarted = false; + encounterActionAttack = false; + encounterActionReset = false; + doDelayPunish = false; + _Reset(); + } + + bool DoEncounterAction(Unit *who, bool attack, bool reset, bool checkAllDead) + { + if (!instance) + return false; + + Creature *Thane = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_THANE))); + Creature *Lady = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_LADY))); + Creature *Baron = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_BARON))); + Creature *Sir = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_SIR))); + + if (Thane && Lady && Baron && Sir) + { + if (attack && who) + { + CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionAttack = true; + CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionAttack = true; + CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionAttack = true; + CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionAttack = true; + + CAST_AI(boss_four_horsemenAI, Thane->AI())->AttackStart(who); + CAST_AI(boss_four_horsemenAI, Lady->AI())->AttackStart(who); + CAST_AI(boss_four_horsemenAI, Baron->AI())->AttackStart(who); + CAST_AI(boss_four_horsemenAI, Sir->AI())->AttackStart(who); + } + + if (reset) + { + if (instance->GetBossState(BOSS_HORSEMEN) != NOT_STARTED) + { + if (!Thane->isAlive()) + Thane->Respawn(); + + if (!Lady->isAlive()) + Lady->Respawn(); + + if (!Baron->isAlive()) + Baron->Respawn(); + + if (!Sir->isAlive()) + Sir->Respawn(); + + CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionReset = true; + CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionReset = true; + CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionReset = true; + CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionReset = true; + + CAST_AI(boss_four_horsemenAI, Thane->AI())->EnterEvadeMode(); + CAST_AI(boss_four_horsemenAI, Lady->AI())->EnterEvadeMode(); + CAST_AI(boss_four_horsemenAI, Baron->AI())->EnterEvadeMode(); + CAST_AI(boss_four_horsemenAI, Sir->AI())->EnterEvadeMode(); + } + } + + if (checkAllDead) + return !Thane->isAlive() && !Lady->isAlive() && !Baron->isAlive() && !Sir->isAlive(); + } + return false; + } + + void BeginFourHorsemenMovement() + { + movementStarted = true; + me->SetReactState(REACT_PASSIVE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true); + + switch(id) + { + case HORSEMEN_THANE: + me->GetMotionMaster()->MovePoint(0, WaypointPositions[0]); + break; + case HORSEMEN_LADY: + me->GetMotionMaster()->MovePoint(3, WaypointPositions[3]); + break; + case HORSEMEN_BARON: + me->GetMotionMaster()->MovePoint(6, WaypointPositions[6]); + break; + case HORSEMEN_SIR: + me->GetMotionMaster()->MovePoint(9, WaypointPositions[9]); + break; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 2 || id == 5 || id == 8 || id == 11) + { + movementCompleted = true; + me->SetReactState(REACT_AGGRESSIVE); + + Unit *eventStarter = Unit::GetUnit(*me, uiEventStarterGUID); + + if (eventStarter && me->canAttack(eventStarter)) + AttackStart(eventStarter); + else if (!UpdateVictim()) + { + EnterEvadeMode(); + return; + } + + if (caster) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + } + + return; + } + + nextMovementStarted = false; + nextWP = id + 1; + } + + // switch to "who" if nearer than current target. + void SelectNearestTarget(Unit *who) + { + if (me->getVictim() && me->GetDistanceOrder(who, me->getVictim()) && me->canAttack(who)) + { + me->getThreatManager().modifyThreatPercent(me->getVictim(), -100); + me->AddThreat(who, 1000000.0f); + } + } + + void MoveInLineOfSight(Unit *who) + { + BossAI::MoveInLineOfSight(who); + if (caster) + SelectNearestTarget(who); + } + + void AttackStart(Unit *who) + { + if (!movementCompleted && !movementStarted) + { + uiEventStarterGUID = who->GetGUID(); + BeginFourHorsemenMovement(); + + if (!encounterActionAttack) + DoEncounterAction(who, true, false, false); + } + else if (movementCompleted && movementStarted) + { + if (caster) + me->Attack(who, false); + else + BossAI::AttackStart(who); + } + } + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%5)) + { + if (id == HORSEMEN_BARON) + DoScriptText(SAY_BARON_SLAY, me); + else + DoScriptText(SAY_SLAY[id], me); + } + } + + void JustDied(Unit* /*killer*/) + { + events.Reset(); + summons.DespawnAll(); + + if (instance) + instance->SetData(DATA_HORSEMEN0 + id, DONE); + + if (instance && DoEncounterAction(NULL, false, false, true)) + { + instance->SetBossState(BOSS_HORSEMEN, DONE); + instance->SaveToDB(); + + // Achievements related to the 4-horsemen are given through spell 59450 which does not exist. + // There is thus no way it can be given by casting the spell on the players. + instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59450); + } + + DoScriptText(SAY_DEATH[id], me); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + + if (id == HORSEMEN_BARON) + DoScriptText(SAY_BARON_AGGRO, me); + else + DoScriptText(SAY_AGGRO[id], me); + + events.ScheduleEvent(EVENT_MARK, 15000); + events.ScheduleEvent(EVENT_CAST, 20000+rand()%5000); + events.ScheduleEvent(EVENT_BERSERK, 15*100*1000); + } + + void UpdateAI(const uint32 diff) + { + if (nextWP && movementStarted && !movementCompleted && !nextMovementStarted) + { + nextMovementStarted = true; + me->GetMotionMaster()->MovePoint(nextWP, WaypointPositions[nextWP]); + } + + if (!UpdateVictim() || !CheckInRoom() || !movementCompleted) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_MARK: + if (!(rand()%5)) + DoScriptText(SAY_SPECIAL[id], me); + DoCastAOE(SPELL_MARK[id]); + events.ScheduleEvent(EVENT_MARK, 15000); + break; + case EVENT_CAST: + if (!(rand()%5)) + DoScriptText(SAY_TAUNT[rand()%3][id], me); + + if (caster) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) + DoCast(pTarget, SPELL_PRIMARY(id)); + } + else + DoCast(me->getVictim(), SPELL_PRIMARY(id)); + + events.ScheduleEvent(EVENT_CAST, 15000); + break; + case EVENT_BERSERK: + DoScriptText(SAY_SPECIAL[id], me); + DoCast(me, EVENT_BERSERK); + break; + } + } + + if (punishTimer <= diff) + { + if (doDelayPunish) + { + DoCastAOE(SPELL_PUNISH[id], true); + doDelayPunish = false; + } + punishTimer = 2000; + } else punishTimer -= diff; + + if (!caster) + DoMeleeAttackIfReady(); + else if ((!DoSpellAttackIfReady(SPELL_SECONDARY(id)) || !me->IsWithinLOSInMap(me->getVictim())) && movementCompleted && !doDelayPunish) + doDelayPunish = true; + } +}; + +CreatureAI* GetAI_four_horsemen(Creature* pCreature) +{ + return new boss_four_horsemenAI (pCreature); +} + +void AddSC_boss_four_horsemen() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_four_horsemen"; + newscript->GetAI = &GetAI_four_horsemen; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp new file mode 100644 index 00000000000..ab6fa6c46d3 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -0,0 +1,147 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SPELL_MORTAL_WOUND 25646 +#define SPELL_ENRAGE RAID_MODE(28371,54427) +#define SPELL_DECIMATE RAID_MODE(28374,54426) +#define SPELL_BERSERK 26662 +#define SPELL_INFECTED_WOUND 29306 + +#define MOB_ZOMBIE 16360 + +const Position PosSummon[3] = +{ + {3267.9, -3172.1, 297.42, 0.94}, + {3253.2, -3132.3, 297.42, 0}, + {3308.3, -3185.8, 297.42, 1.58}, +}; + +enum Events +{ + EVENT_NONE, + EVENT_WOUND, + EVENT_ENRAGE, + EVENT_DECIMATE, + EVENT_BERSERK, + EVENT_SUMMON, +}; + +#define EMOTE_NEARBY " spots a nearby zombie to devour!" + +struct boss_gluthAI : public BossAI +{ + boss_gluthAI(Creature *c) : BossAI(c, BOSS_GLUTH) + { + // Do not let Gluth be affected by zombies' debuff + me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true); + } + + void MoveInLineOfSight(Unit *who) + { + if (who->GetEntry() == MOB_ZOMBIE && me->IsWithinDistInMap(who, 7)) + { + SetGazeOn(who); + // TODO: use a script text + me->MonsterTextEmote(EMOTE_NEARBY, 0, true); + } + else + BossAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + events.ScheduleEvent(EVENT_WOUND, 10000); + events.ScheduleEvent(EVENT_ENRAGE, 15000); + events.ScheduleEvent(EVENT_DECIMATE, 105000); + events.ScheduleEvent(EVENT_BERSERK, 8*60000); + events.ScheduleEvent(EVENT_SUMMON, 15000); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == MOB_ZOMBIE) + summon->AI()->AttackStart(me); + summons.Summon(summon); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictimWithGaze() || !CheckInRoom()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_WOUND: + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + events.ScheduleEvent(EVENT_WOUND, 10000); + break; + case EVENT_ENRAGE: + // TODO : Add missing text + DoCast(me, SPELL_ENRAGE); + events.ScheduleEvent(EVENT_ENRAGE, 15000); + break; + case EVENT_DECIMATE: + // TODO : Add missing text + DoCastAOE(SPELL_DECIMATE); + events.ScheduleEvent(EVENT_DECIMATE, 105000); + break; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + events.ScheduleEvent(EVENT_BERSERK, 5*60000); + break; + case EVENT_SUMMON: + for (uint32 i = 0; i < RAID_MODE(1,2); ++i) + DoSummon(MOB_ZOMBIE, PosSummon[rand()%3]); + events.ScheduleEvent(EVENT_SUMMON, 10000); + break; + } + } + + if (me->getVictim() && me->getVictim()->GetEntry() == MOB_ZOMBIE) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->Kill(me->getVictim()); + me->ModifyHealth(me->GetMaxHealth() * 0.05f); + } + } + else + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_gluth(Creature* pCreature) +{ + return new boss_gluthAI (pCreature); +} + +void AddSC_boss_gluth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gluth"; + newscript->GetAI = &GetAI_boss_gluth; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp new file mode 100644 index 00000000000..d958ff24951 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -0,0 +1,582 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Yells +{ + SAY_SPEECH = -1533040, + SAY_KILL = -1533041, + SAY_DEATH = -1533042, + SAY_TELEPORT = -1533043 +}; +//Gothik +enum Spells +{ + SPELL_HARVEST_SOUL = 28679, + SPELL_SHADOW_BOLT = 29317, + H_SPELL_SHADOW_BOLT = 56405, + SPELL_INFORM_LIVE_TRAINEE = 27892, + SPELL_INFORM_LIVE_KNIGHT = 27928, + SPELL_INFORM_LIVE_RIDER = 27935, + SPELL_INFORM_DEAD_TRAINEE = 27915, + SPELL_INFORM_DEAD_KNIGHT = 27931, + SPELL_INFORM_DEAD_RIDER = 27937 +}; +enum Creatures +{ + MOB_LIVE_TRAINEE = 16124, + MOB_LIVE_KNIGHT = 16125, + MOB_LIVE_RIDER = 16126, + MOB_DEAD_TRAINEE = 16127, + MOB_DEAD_KNIGHT = 16148, + MOB_DEAD_RIDER = 16150, + MOB_DEAD_HORSE = 16149 +}; + +struct Waves { uint32 entry, time, mode; }; +// wave setups are not the same in heroic and normal difficulty, +// mode is 0 only normal, 1 both and 2 only heroic +// but this is handled in DoGothikSummon function +const Waves waves[] = +{ + {MOB_LIVE_TRAINEE, 20000, 1}, + {MOB_LIVE_TRAINEE, 20000, 1}, + {MOB_LIVE_TRAINEE, 10000, 1}, + {MOB_LIVE_KNIGHT, 10000, 1}, + {MOB_LIVE_TRAINEE, 15000, 1}, + {MOB_LIVE_KNIGHT, 5000, 1}, + {MOB_LIVE_TRAINEE, 20000, 1}, + {MOB_LIVE_TRAINEE, 0, 1}, + {MOB_LIVE_KNIGHT, 10000, 1}, + {MOB_LIVE_TRAINEE, 10000, 2}, + {MOB_LIVE_RIDER, 10000, 0}, + {MOB_LIVE_RIDER, 5000, 2}, + {MOB_LIVE_TRAINEE, 5000, 0}, + {MOB_LIVE_TRAINEE, 15000, 2}, + {MOB_LIVE_KNIGHT, 15000, 0}, + {MOB_LIVE_TRAINEE, 0, 0}, + {MOB_LIVE_RIDER, 10000, 1}, + {MOB_LIVE_KNIGHT, 10000, 1}, + {MOB_LIVE_TRAINEE, 10000, 0}, + {MOB_LIVE_RIDER, 10000, 2}, + {MOB_LIVE_TRAINEE, 0, 2}, + {MOB_LIVE_RIDER, 5000, 1}, + {MOB_LIVE_TRAINEE, 0, 2}, + {MOB_LIVE_KNIGHT, 5000, 1}, + {MOB_LIVE_RIDER, 0, 2}, + {MOB_LIVE_TRAINEE, 20000, 1}, + {MOB_LIVE_RIDER, 0, 1}, + {MOB_LIVE_KNIGHT, 0, 1}, + {MOB_LIVE_TRAINEE, 25000, 2}, + {MOB_LIVE_TRAINEE, 15000, 0}, + {MOB_LIVE_TRAINEE, 25000, 0}, + {0, 0, 1}, +}; + +#define POS_Y_GATE -3360.78f +#define POS_Y_WEST -3285.0f +#define POS_Y_EAST -3434.0f +#define POS_X_NORTH 2750.49f +#define POS_X_SOUTH 2633.84f + +#define IN_LIVE_SIDE(who) (who->GetPositionY() < POS_Y_GATE) + +enum Events +{ + EVENT_NONE, + EVENT_SUMMON, + EVENT_HARVEST, + EVENT_BOLT, + EVENT_TELEPORT +}; +enum Pos +{ + POS_LIVE = 6, + POS_DEAD = 5 +}; + +const Position PosSummonLive[POS_LIVE] = +{ + {2669.7, -3428.76, 268.56, 1.6}, + {2692.1, -3428.76, 268.56, 1.6}, + {2714.4, -3428.76, 268.56, 1.6}, + {2669.7, -3431.67, 268.56, 1.6}, + {2692.1, -3431.67, 268.56, 1.6}, + {2714.4, -3431.67, 268.56, 1.6}, +}; + +const Position PosSummonDead[POS_DEAD] = +{ + {2725.1, -3310.0, 268.85, 3.4}, + {2699.3, -3322.8, 268.60, 3.3}, + {2733.1, -3348.5, 268.84, 3.1}, + {2682.8, -3304.2, 268.85, 3.9}, + {2664.8, -3340.7, 268.23, 3.7}, +}; + +const float PosGroundLiveSide[4] = {2691.2, -3387.0, 267.68, 1.52}; +const float PosGroundDeadSide[4] = {2693.5, -3334.6, 267.68, 4.67}; +const float PosPlatform[4] = {2640.5, -3360.6, 285.26, 0}; + +// Predicate function to check that the r efzr unit is NOT on the same side as the source. +struct NotOnSameSide : public std::unary_function { + bool m_inLiveSide; + NotOnSameSide(Unit *pSource) : m_inLiveSide(IN_LIVE_SIDE(pSource)) {} + bool operator() (const Unit *pTarget) { + return (m_inLiveSide != IN_LIVE_SIDE(pTarget)); + } +}; + +struct boss_gothikAI : public BossAI +{ + boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK) {} + + uint32 waveCount; + typedef std::vector TriggerVct; + TriggerVct liveTrigger, deadTrigger; + bool mergedSides; + bool phaseTwo; + bool thirtyPercentReached; + + std::vector LiveTriggerGUID; + std::vector DeadTriggerGUID; + + void Reset() + { + LiveTriggerGUID.clear(); + DeadTriggerGUID.clear(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); + me->SetReactState(REACT_PASSIVE); + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); + _Reset(); + mergedSides = false; + phaseTwo = false; + thirtyPercentReached = false; + } + + void EnterCombat(Unit * /*who*/) + { + for (uint32 i = 0; i < POS_LIVE; ++i) + if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonLive[i])) + LiveTriggerGUID.push_back(trigger->GetGUID()); + for (uint32 i = 0; i < POS_DEAD; ++i) + if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonDead[i])) + DeadTriggerGUID.push_back(trigger->GetGUID()); + + if (LiveTriggerGUID.size() < POS_LIVE || DeadTriggerGUID.size() < POS_DEAD) + { + error_log("Script Gothik: cannot summon triggers!"); + EnterEvadeMode(); + return; + } + + _EnterCombat(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); + waveCount = 0; + events.ScheduleEvent(EVENT_SUMMON, 30000); + DoTeleportTo(PosPlatform); + DoScriptText(SAY_SPEECH, me); + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_READY); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == WORLD_TRIGGER) + summon->setActive(true); + else if (!mergedSides) + { + summon->AI()->DoAction(me->HasReactState(REACT_PASSIVE) ? 1 : 0); + summon->AI()->EnterEvadeMode(); + } + else + { + summon->AI()->DoAction(0); + summon->AI()->DoZoneInCombat(); + } + summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature *summon) + { + summons.Despawn(summon); + } + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*Killer*/) + { + LiveTriggerGUID.clear(); + DeadTriggerGUID.clear(); + _JustDied(); + DoScriptText(SAY_DEATH, me); + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); + } + + void DoGothikSummon(uint32 entry) + { + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + { + switch(entry) + { + case MOB_LIVE_TRAINEE: + { + if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[0])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1); + if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[1])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1); + if (Creature *LiveTrigger2 = Unit::GetCreature(*me, LiveTriggerGUID[2])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger2, 1); + break; + } + case MOB_LIVE_KNIGHT: + { + if (Creature *LiveTrigger3 = Unit::GetCreature(*me, LiveTriggerGUID[3])) + DoSummon(MOB_LIVE_KNIGHT, LiveTrigger3, 1); + if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[5])) + DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1); + break; + } + case MOB_LIVE_RIDER: + { + if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1); + break; + } + } + } + else + { + switch(entry) + { + case MOB_LIVE_TRAINEE: + { + if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1); + if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1); + break; + } + case MOB_LIVE_KNIGHT: + { + if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1); + break; + } + case MOB_LIVE_RIDER: + { + if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4])) + DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1); + break; + } + } + } + } + + bool CheckGroupSplitted() + { + bool checklife = false; + bool checkdead = false; + + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->isAlive() && + i->getSource()->GetPositionX() <= POS_X_NORTH && + i->getSource()->GetPositionX() >= POS_X_SOUTH && + i->getSource()->GetPositionY() <= POS_Y_GATE && + i->getSource()->GetPositionY() >= POS_Y_EAST) + { + checklife = true; + } + else if (i->getSource() && i->getSource()->isAlive() && + i->getSource()->GetPositionX() <= POS_X_NORTH && + i->getSource()->GetPositionX() >= POS_X_SOUTH && + i->getSource()->GetPositionY() >= POS_Y_GATE && + i->getSource()->GetPositionY() <= POS_Y_WEST) + { + checkdead = true; + } + + if (checklife && checkdead) + return true; + } + } + } + + return false; + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + uint32 spellId = 0; + switch(spell->Id) + { + case SPELL_INFORM_LIVE_TRAINEE: spellId = SPELL_INFORM_DEAD_TRAINEE; break; + case SPELL_INFORM_LIVE_KNIGHT: spellId = SPELL_INFORM_DEAD_KNIGHT; break; + case SPELL_INFORM_LIVE_RIDER: spellId = SPELL_INFORM_DEAD_RIDER; break; + } + if (spellId && me->isInCombat()) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST); + if (Creature *pRandomDeadTrigger = Unit::GetCreature(*me, DeadTriggerGUID[rand() % POS_DEAD])) + me->CastSpell(pRandomDeadTrigger, spellId, true); + } + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (!me->isInCombat()) + return; + + switch(spell->Id) + { + case SPELL_INFORM_DEAD_TRAINEE: + DoSummon(MOB_DEAD_TRAINEE, pTarget, 0); + break; + case SPELL_INFORM_DEAD_KNIGHT: + DoSummon(MOB_DEAD_KNIGHT, pTarget, 0); + break; + case SPELL_INFORM_DEAD_RIDER: + DoSummon(MOB_DEAD_RIDER, pTarget, 1.0f); + DoSummon(MOB_DEAD_HORSE, pTarget, 1.0f); + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateCombatState() || !CheckInRoom()) + return; + + events.Update(diff); + + if (!thirtyPercentReached && HealthBelowPct(30) && phaseTwo) + { + thirtyPercentReached = true; + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); + } + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SUMMON: + if (waves[waveCount].entry) + { + if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) + DoGothikSummon(waves[waveCount].entry); + else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) + DoGothikSummon(waves[waveCount].entry); + else if (waves[waveCount].mode == 1) + DoGothikSummon(waves[waveCount].entry); + + // if group is not splitted, open gate and merge both sides at ~ 2 minutes (wave 11) + if (waveCount == 11) + { + if (!CheckGroupSplitted()) + { + if (instance) + instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); + summons.DoAction(0, 0); + summons.DoZoneInCombat(); + mergedSides = true; + } + } + + if (waves[waveCount].mode == 1) + events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); + else if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) + events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); + else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) + events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); + else + events.ScheduleEvent(EVENT_SUMMON, 0); + + ++waveCount; + } + else + { + phaseTwo = true; + DoScriptText(SAY_TELEPORT, me); + DoTeleportTo(PosGroundLiveSide); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + summons.DoAction(0, 0); + summons.DoZoneInCombat(); + events.ScheduleEvent(EVENT_BOLT, 1000); + events.ScheduleEvent(EVENT_HARVEST, urand(3000,15000)); + events.ScheduleEvent(EVENT_TELEPORT, 20000); + } + break; + case EVENT_BOLT: + DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BOLT, H_SPELL_SHADOW_BOLT)); + events.ScheduleEvent(EVENT_BOLT, 1000); + break; + case EVENT_HARVEST: + DoCast(me->getVictim(), SPELL_HARVEST_SOUL, true); + events.ScheduleEvent(EVENT_HARVEST, urand(20000,25000)); + break; + case EVENT_TELEPORT: + if (!thirtyPercentReached) + { + me->AttackStop(); + if (IN_LIVE_SIDE(me)) + { + DoTeleportTo(PosGroundDeadSide); + } + else + { + DoTeleportTo(PosGroundLiveSide); + } + + me->getThreatManager().resetAggro(NotOnSameSide(me)); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0)) + { + me->getThreatManager().addThreat(pTarget, 100.0f); + AttackStart(pTarget); + } + + events.ScheduleEvent(EVENT_TELEPORT, 20000); + } + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_gothik_minionAI : public CombatAI +{ + mob_gothik_minionAI(Creature *c) : CombatAI(c) + { + liveSide = IN_LIVE_SIDE(me); + } + + bool liveSide; + bool gateClose; + + bool isOnSameSide(const Unit *pWho) + { + return (liveSide == IN_LIVE_SIDE(pWho)); + } + + void DoAction(const int32 param) + { + gateClose = param; + } + + void DamageTaken(Unit *attacker, uint32 &damage) + { + if (gateClose && !isOnSameSide(attacker)) + damage = 0; + } + + void JustDied(Unit * /*killer*/) + { + if (me->isSummon()) + { + if (Unit *owner = CAST_SUM(me)->GetSummoner()) + CombatAI::JustDied(owner); + } + } + + void EnterEvadeMode() + { + if (!gateClose) + { + CombatAI::EnterEvadeMode(); + return; + } + + if (!_EnterEvadeMode()) + return; + + Map* pMap = me->GetMap(); + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->isAlive() && isOnSameSide(i->getSource())) + { + AttackStart(i->getSource()); + return; + } + } + } + } + + me->GetMotionMaster()->MoveIdle(); + Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (gateClose && (!isOnSameSide(me) || me->getVictim() && !isOnSameSide(me->getVictim()))) + { + EnterEvadeMode(); + return; + } + + CombatAI::UpdateAI(diff); + } +}; + +CreatureAI* GetAI_boss_gothik(Creature* pCreature) +{ + return new boss_gothikAI (pCreature); +} + +CreatureAI* GetAI_mob_gothik_minion(Creature* pCreature) +{ + return new mob_gothik_minionAI (pCreature); +} + +void AddSC_boss_gothik() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gothik"; + newscript->GetAI = &GetAI_boss_gothik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_gothik_minion"; + newscript->GetAI = &GetAI_mob_gothik_minion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp new file mode 100644 index 00000000000..7df01e18483 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SPELL_BOMBARD_SLIME 28280 + +#define SPELL_POISON_CLOUD 28240 +#define SPELL_MUTATING_INJECTION 28169 +#define SPELL_SLIME_SPRAY RAID_MODE(28157,54364) +#define SPELL_BERSERK 26662 +#define SPELL_POISON_CLOUD_ADD 59116 + +#define EVENT_BERSERK 1 +#define EVENT_CLOUD 2 +#define EVENT_INJECT 3 +#define EVENT_SPRAY 4 + +#define MOB_FALLOUT_SLIME 16290 + +struct boss_grobbulusAI : public BossAI +{ + boss_grobbulusAI(Creature *c) : BossAI(c, BOSS_GROBBULUS) + { + me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_POISON_CLOUD_ADD, true); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + events.ScheduleEvent(EVENT_CLOUD, 15000); + events.ScheduleEvent(EVENT_INJECT, 20000); + events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure + events.ScheduleEvent(EVENT_BERSERK, 12*60000); + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (spell->Id == uint32(SPELL_SLIME_SPRAY)) + { + if (TempSummon *slime = me->SummonCreature(MOB_FALLOUT_SLIME, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) + DoZoneInCombat(slime); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CLOUD: + DoCastAOE(SPELL_POISON_CLOUD); + events.ScheduleEvent(EVENT_CLOUD, 15000); + return; + case EVENT_BERSERK: + DoCastAOE(SPELL_BERSERK); + return; + case EVENT_SPRAY: + DoCastAOE(SPELL_SLIME_SPRAY); + events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); + return; + case EVENT_INJECT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + if (!pTarget->HasAura(SPELL_MUTATING_INJECTION)) + DoCast(pTarget, SPELL_MUTATING_INJECTION); + events.ScheduleEvent(EVENT_INJECT, 8000 + 12000 * ((float)me->GetHealth() / me->GetMaxHealth())); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_grobbulus_poison_cloudAI : public Scripted_NoMovementAI +{ + npc_grobbulus_poison_cloudAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + Reset(); + } + + uint32 Cloud_Timer; + + void Reset() + { + Cloud_Timer = 1000; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void UpdateAI(const uint32 diff) + { + if (Cloud_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLOUD_ADD); + Cloud_Timer = 10000; + } else Cloud_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_grobbulus(Creature* pCreature) +{ + return new boss_grobbulusAI (pCreature); +} + +CreatureAI* GetAI_npc_grobbulus_poison_cloud(Creature* pCreature) +{ + return new npc_grobbulus_poison_cloudAI(pCreature); +} + +void AddSC_boss_grobbulus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grobbulus"; + newscript->GetAI = &GetAI_boss_grobbulus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_grobbulus_poison_cloud"; + newscript->GetAI = &GetAI_npc_grobbulus_poison_cloud; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp new file mode 100644 index 00000000000..1de9c0e00c8 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp @@ -0,0 +1,149 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SAY_AGGRO RAND(-1533109,-1533110,-1533111) +#define SAY_SLAY -1533112 +#define SAY_TAUNT RAND(-1533113,-1533114,-1533115,-1533116,-1533117) +#define SAY_DEATH -1533118 + +#define SPELL_SPELL_DISRUPTION 29310 +#define SPELL_DECREPIT_FEVER RAID_MODE(29998,55011) +#define SPELL_PLAGUE_CLOUD 29350 + +enum Events +{ + EVENT_NONE, + EVENT_DISRUPT, + EVENT_FEVER, + EVENT_ERUPT, + EVENT_PHASE, +}; + +enum Phases +{ + PHASE_FIGHT = 1, + PHASE_DANCE, +}; + +struct boss_heiganAI : public BossAI +{ + boss_heiganAI(Creature *c) : BossAI(c, BOSS_HEIGAN) {} + + uint32 eruptSection; + bool eruptDirection; + Phases phase; + + void KilledUnit(Unit* /*Victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_SLAY, me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO, me); + EnterPhase(PHASE_FIGHT); + } + + void EnterPhase(Phases newPhase) + { + phase = newPhase; + events.Reset(); + eruptSection = 3; + if (phase == PHASE_FIGHT) + { + events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000)); + events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000)); + events.ScheduleEvent(EVENT_PHASE, 90000); + events.ScheduleEvent(EVENT_ERUPT, 15000); + } + else + { + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + me->NearTeleportTo(x, y, z, o); + DoCastAOE(SPELL_PLAGUE_CLOUD); + events.ScheduleEvent(EVENT_PHASE, 45000); + events.ScheduleEvent(EVENT_ERUPT, 8000); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || !CheckInRoom()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_DISRUPT: + DoCastAOE(SPELL_SPELL_DISRUPTION); + events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000)); + break; + case EVENT_FEVER: + DoCastAOE(SPELL_DECREPIT_FEVER); + events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000)); + break; + case EVENT_PHASE: + // TODO : Add missing texts for both phase switches + EnterPhase(phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT); + break; + case EVENT_ERUPT: + instance->SetData(DATA_HEIGAN_ERUPT, eruptSection); + TeleportCheaters(); + + if (eruptSection == 0) + eruptDirection = true; + else if (eruptSection == 3) + eruptDirection = false; + + eruptDirection ? ++eruptSection : --eruptSection; + + events.ScheduleEvent(EVENT_ERUPT, phase == PHASE_FIGHT ? 10000 : 3000); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_heigan(Creature* pCreature) +{ + return new boss_heiganAI (pCreature); +} + +void AddSC_boss_heigan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_heigan"; + newscript->GetAI = &GetAI_boss_heigan; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_highlord_mograine.cpp b/src/server/scripts/Northrend/Naxxramas/boss_highlord_mograine.cpp new file mode 100644 index 00000000000..4eb72a3780e --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_highlord_mograine.cpp @@ -0,0 +1,179 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Highlord_Mograine +SD%Complete: 100 +SDComment: SCRIPT OBSOLETE +SDCategory: Naxxramas +EndScriptData */ + +#include "precompiled.h" + +//All horsemen +#define SPELL_SHIELDWALL 29061 +#define SPELL_BESERK 26662 + +// highlord mograine +#define SPELL_MARK_OF_MOGRAINE 28834 +#define SPELL_RIGHTEOUS_FIRE 28882 // Applied as a 25% chance on melee hit to proc. me->GetVictim() + +#define SAY_TAUNT1 "Enough prattling. Let them come! We shall grind their bones to dust." +#define SAY_TAUNT2 "Conserve your anger! Harness your rage! You will all have outlets for your frustration soon enough." +#define SAY_TAUNT3 "Life is meaningless. It is in death that we are truly tested." +#define SAY_AGGRO1 "You seek death?" +#define SAY_AGGRO2 "None shall pass!" +#define SAY_AGGRO3 "Be still!" +#define SAY_SLAY1 "You will find no peace in death." +#define SAY_SLAY2 "The master's will is done." +#define SAY_SPECIAL "Bow to the might of the Highlord!" +#define SAY_DEATH "I... am... released! Perhaps it's not too late to - noo! I need... more time..." + +#define SOUND_TAUNT1 8842 +#define SOUND_TAUNT2 8843 +#define SOUND_TAUNT3 8844 +#define SOUND_AGGRO1 8835 +#define SOUND_AGGRO2 8836 +#define SOUND_AGGRO3 8837 +#define SOUND_SLAY1 8839 +#define SOUND_SLAY2 8840 +#define SOUND_SPECIAL 8841 +#define SOUND_DEATH 8838 + +#define SPIRIT_OF_MOGRAINE 16775 + +struct TRINITY_DLL_DECL boss_highlord_mograineAI : public ScriptedAI +{ + boss_highlord_mograineAI(Creature *c) : ScriptedAI(c) {} + + uint32 Mark_Timer; + uint32 RighteousFire_Timer; + bool ShieldWall1; + bool ShieldWall2; + + void Reset() + { + Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. + RighteousFire_Timer = 2000; // applied approx 1 out of 4 attacks + ShieldWall1 = true; + ShieldWall2 = true; + } + + void InitialYell() + { + if (!me->isInCombat()) + { + switch(rand()%3) + { + case 0: + DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_AGGRO1); + break; + case 1: + DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_AGGRO2); + break; + case 2: + DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_AGGRO3); + break; + } + } + } + + void KilledUnit() + { + switch(rand()%2) + { + case 0: + DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_SLAY1); + break; + case 1: + DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me,SOUND_SLAY2); + break; + } + } + + void JustDied(Unit* Killer) + { + DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); + DoPlaySoundToSet(me, SOUND_DEATH); + } + + void Aggro(Unit *who) + { + InitialYell(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Mark of Mograine + if (Mark_Timer < diff) + { + DoCast(me->getVictim(),SPELL_MARK_OF_MOGRAINE); + Mark_Timer = 12000; + }else Mark_Timer -= diff; + + // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds + if (ShieldWall1 && (me->GetHealth()*100 / me->GetMaxHealth()) < 50) + { + if (ShieldWall1) + { + DoCast(me,SPELL_SHIELDWALL); + ShieldWall1 = false; + } + } + if (ShieldWall2 && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) + { + if (ShieldWall2) + { + DoCast(me,SPELL_SHIELDWALL); + ShieldWall2 = false; + } + } + + // Righteous Fire + if (RighteousFire_Timer < diff) + { + if (rand()%4 == 1) // 1/4 + { + DoCast(me->getVictim(),SPELL_RIGHTEOUS_FIRE); + } + RighteousFire_Timer = 2000; + }else RighteousFire_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_highlord_mograine(Creature* pCreature) +{ + return new boss_highlord_mograineAI (pCreature); +} + +void AddSC_boss_highlord_mograine() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_highlord_mograine"; + newscript->GetAI = &GetAI_boss_highlord_mograine; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp new file mode 100644 index 00000000000..bfcd0636298 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -0,0 +1,706 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_KelThuzad +SD%Complete: 80% +SDComment: VERIFY SCRIPT +SDCategory: Naxxramas +EndScriptData */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Yells +{ + //when shappiron dies. dialog between kel and lich king (in this order) + SAY_SAPP_DIALOG1 = -1533084, //not used + SAY_SAPP_DIALOG2_LICH = -1533085, //not used + SAY_SAPP_DIALOG3 = -1533086, //not used + SAY_SAPP_DIALOG4_LICH = -1533087, //not used + SAY_SAPP_DIALOG5 = -1533088, //not used + SAY_CAT_DIED = -1533089, //when cat dies, not used + //when each of the 4 wing bosses dies + SAY_TAUNT1 = -1533090, //not used + SAY_TAUNT2 = -1533091, //not used + SAY_TAUNT3 = -1533092, //not used + SAY_TAUNT4 = -1533093, //not used + SAY_SUMMON_MINIONS = -1533105, //start of phase 1 + SAY_AGGRO_1 = -1533094, //start of phase 2 + SAY_AGGRO_2 = -1533095, + SAY_AGGRO_3 = -1533096, + SAY_SLAY_1 = -1533097, + SAY_SLAY_2 = -1533098, + SAY_DEATH = -1533099, + SAY_CHAIN_1 = -1533100, + SAY_CHAIN_2 = -1533101, + SAY_FROST_BLAST = -1533102, + SAY_SPECIAL_1 = -1533106, + SAY_SPECIAL_2 = -1533107, + SAY_SPECIAL_3 = -1533108, + SAY_REQUEST_AID = -1533103, //start of phase 3 + SAY_ANSWER_REQUEST = -1533104 //lich king answer +}; +enum Event +{ + EVENT_NONE, + EVENT_BOLT, + EVENT_NOVA, + EVENT_CHAIN, + EVENT_CHAINED_SPELL, + EVENT_DETONATE, + EVENT_FISSURE, + EVENT_BLAST, + + EVENT_WASTE, + EVENT_ABOMIN, + EVENT_WEAVER, + EVENT_ICECROWN, + EVENT_TRIGGER, + + EVENT_PHASE, +}; + +enum Spells +{ + SPELL_FROST_BOLT = 28478, + H_SPELL_FROST_BOLT = 55802, + SPELL_FROST_BOLT_AOE = 28479, + H_SPELL_FROST_BOLT_AOE = 55807, + SPELL_SHADOW_FISURE = 27810, + SPELL_VOID_BLAST = 27812, + SPELL_MANA_DETONATION = 27819, + SPELL_FROST_BLAST = 27808, + SPELL_CHAINS_OF_KELTHUZAD = 28410, //28408 script effect + SPELL_KELTHUZAD_CHANNEL = 29423, + SPELL_BERSERK = 28498, + + //spells for chained + //warlock + SPELL_CURSE_OF_AGONY = 47864, + SPELL_SHADOW_BOLT = 47809, + //shaman + SPELL_EARTH_SHOCK = 49231, + SPELL_HEALING_WAVE = 49273, + //mage + SPELL_FROST_FIREBOLT = 47610, + SPELL_ARCANE_MISSILES = 42846, + //rogue + SPELL_HEMORRHAGE = 48660, + SPELL_MUTILATE = 48666, + //paladin + SPELL_HOLY_SHOCK = 48825, + SPELL_HAMMER_OF_JUSTICE = 10308, + //priest + SPELL_VAMPIRIC_TOUCH = 48160, + SPELL_RENEW = 48068, + //hunter + SPELL_MULTI_SHOT = 49048, + SPELL_VOLLEY = 58434, + //warrior + SPELL_BLADESTORM = 46924, + SPELL_CLEAVE = 47520, + //druid + SPELL_MOONFIRE = 48463, + SPELL_LIFEBLOOM = 48451, + //death knight + SPELL_PLAGUE_STRIKE = 49921, + SPELL_HOWLING_BLAST = 51411, +}; + +enum Creatures +{ + NPC_WASTE = 16427, // Soldiers of the Frozen Wastes + NPC_ABOMINATION = 16428, // Unstoppable Abominations + NPC_WEAVER = 16429, // Soul Weavers + NPC_ICECROWN = 16441 // Guardians of Icecrown +}; + +const Position Pos[12] = +{ + {3783.272705, -5062.697266, 143.711203, 3.617599}, //LEFT_FAR + {3730.291260, -5027.239258, 143.956909, 4.461900}, //LEFT_MIDDLE + {3757.6, -5172.0, 143.7, 1.97}, //WINDOW_PORTAL05 + {3759.355225, -5174.128418, 143.802383, 2.170104}, //RIGHT_FAR + {3700.724365, -5185.123047, 143.928024, 1.309310}, //RIGHT_MIDDLE + {3700.86, -5181.29, 143.928024, 1.42}, //WINDOW_PORTAL04 + {3754.431396, -5080.727734, 142.036316, 3.736189}, //LEFT_FAR + {3724.396484, -5061.330566, 142.032700, 4.564785}, //LEFT_MIDDLE + {3732.02, -5028.53, 143.92, 4.49}, //WINDOW_PORTAL02 + {3687.571777, -5126.831055, 142.017807, 0.604023}, //RIGHT_FAR + {3707.990733, -5151.450195, 142.032562, 1.376855}, //RIGHT_MIDDLE + {3782.76, -5062.97, 143.79, 3.82}, //WINDOW_PORTAL03 +}; + +//creatures in corners +//Unstoppable Abominations +#define MAX_ABOMINATIONS 21 +const Position PosAbominations[MAX_ABOMINATIONS] = +{ + {3755.52, -5155.22, 143.480, 2.0}, + {3744.35, -5164.03, 143.590, 2.00}, + {3749.28, -5159.04, 143.190, 2.0}, + {3774.47, -5076.28, 143.528, 2.15912}, + {3765.94, -5074.15, 143.186, 3.77233}, + {3763.15, -5063.36, 143.694, 3.77233}, + {3737.81, -5045.69, 143.709, 4.9033}, + {3728.13, -5045.01, 143.355, 1.45069}, + {3721.56, -5048.35, 143.542, 1.45069}, + {3689.55, -5049.66, 143.637, 5.2104}, + {3681.71, -5053.03, 143.242, 2.47957}, + {3677.64, -5061.44, 143.358, 2.47957}, + {3654.2, -5090.87, 143.469, 1.0313}, + {3650.39, -5097.45, 143.496, 2.5047}, + {3658.7, -5103.59, 143.607, 3.3278}, + {3659.02, -5133.97, 143.624, 3.84538}, + {3666.33, -5139.34, 143.183, 3.84538}, + {3669.74, -5149.63, 143.678, 0.528643}, + {3695.53, -5169.53, 143.671, 2.11908}, + {3701.98, -5166.51, 143.395, 1.24257}, + {3709.62, -5169.15, 143.576, 5.97695}, +}; + +//Soldiers of the Frozen Wastes +#define MAX_WASTES 49 +const Position PosWastes[MAX_WASTES] = +{ + {3754.41, -5147.24, 143.204, 2.0}, + {3754.68, -5156.17, 143.418, 2.0}, + {3757.91, -5160.12, 143.503, 2.0}, + {3752.67, -5164.6, 143.395, 2.0}, + {3745.42, -5164.47, 143.565, 2.74587}, + {3741.2, -5155.92, 143.17, 5.29134}, + {3746.57, -5148.82, 143.176, 5.07772}, + {3778.14, -5070.1, 143.568, 3.16208}, + {3775.09, -5078.97, 143.65, 2.81022}, + {3773.54, -5083.47, 143.758, 3.21549}, + {3765, -5078.29, 143.176, 4.36688}, + {3766.94, -5072.63, 143.184, 5.27951}, + {3762.68, -5064.94, 143.635, 3.95297}, + {3769.9, -5059.94, 143.74, 3.36549}, + {3736.33, -5042.18, 143.643, 5.9471}, + {3727.51, -5040.58, 143.502, 0.871859}, + {3719.89, -5049.64, 143.58, 4.75172}, + {3720.69, -5044.43, 143.662, 1.87245}, + {3725.69, -5048.99, 143.363, 2.48271}, + {3732.33, -5054.01, 143.44, 3.59405}, + {3738.09, -5051.06, 143.718, 4.70931}, + {3682.76, -5063.5, 143.175, 0.636238}, + {3686.7, -5060.58, 143.18, 0.636238}, + {3682.45, -5057.21, 143.184, 5.61252}, + {3677.57, -5053.34, 143.369, 1.52531}, + {3677.3, -5062.26, 143.369, 2.73482}, + {3691.21, -5053.02, 143.421, 5.93218}, + {3685.22, -5053.34, 143.314, 4.70303}, + {3652.11, -5088.47, 143.555, 0.793317}, + {3648.23, -5093.21, 143.311, 1.18837}, + {3648.14, -5100.11, 143.632, 2.12221}, + {3653.88, -5099.7, 143.558, 3.04348}, + {3661.23, -5100.33, 143.42, 4.08335}, + {3663.49, -5092.77, 143.346, 4.47134}, + {3661.85, -5087.99, 143.571, 1.0148}, + {3664.56, -5149.01, 143.532, 0.0762528}, + {3665.01, -5142.04, 143.201, 1.72009}, + {3671.15, -5142.92, 143.174, 4.81535}, + {3670.18, -5134.38, 143.177, 5.37534}, + {3664.33, -5131.69, 143.262, 5.39576}, + {3658.21, -5133.63, 143.662, 1.3863}, + {3659.7, -5144.49, 143.363, 2.32328}, + {3705.71, -5179.63, 143.746, 1.06743}, + {3696.77, -5177.45, 143.759, 5.36748}, + {3700.97, -5173.13, 143.52, 3.26575}, + {3708.53, -5172.19, 143.573, 3.26575}, + {3712.49, -5167.62, 143.657, 5.63295}, + {3704.89, -5161.84, 143.239, 5.63295}, + {3695.66, -5164.63, 143.674, 1.54416}, +}; + +//Soul Weavers +#define MAX_WEAVERS 7 +const Position PosWeavers[MAX_WEAVERS] = +{ + {3752.45, -5168.35, 143.562, 1.6094}, + {3772.2, -5070.04, 143.329, 1.93686}, + {3732.28, -5032.88, 143.771, 3.08355}, + {3689.05, -5055.7, 143.172, 6.09554}, + {3649.45, -5093.17, 143.299, 2.51805}, + {3659.7, -5144.49, 143.363, 4.08806}, + {3704.71, -5175.96, 143.597, 3.36549}, +}; + +// predicate function to select not charmed target +struct NotCharmedTargetSelector : public std::unary_function { + NotCharmedTargetSelector() {} + + bool operator() (const Unit *pTarget) { + return (!pTarget->isCharmed()); + } +}; + +struct boss_kelthuzadAI : public BossAI +{ + boss_kelthuzadAI(Creature* c) : BossAI(c, BOSS_KELTHUZAD), spawns(c) + { + uiFaction = me->getFaction(); + } + + uint32 Phase; + uint32 uiGuardiansOfIcecrownTimer; + uint32 uiFaction; + + uint8 nGuardiansOfIcecrownCount; + uint8 nAbomination; + uint8 nWeaver; + + std::map chained; + + uint64 PortalsGUID[4]; + uint64 KTTriggerGUID; + + SummonList spawns; // adds spawn by the trigger. kept in separated list (i.e. not in summons) + + void Reset() + { + _Reset(); + + PortalsGUID[0] = PortalsGUID[1] = PortalsGUID[2] = PortalsGUID[3] = 0; + KTTriggerGUID = 0; + + me->setFaction(35); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + std::map::const_iterator itr; + for (itr = chained.begin(); itr != chained.end(); ++itr) + { + if (Player* charmed = Unit::GetPlayer((*itr).first)) + charmed->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + } + + chained.clear(); + spawns.DespawnAll(); + + FindGameObjects(); + + if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID)) + { + pKTTrigger->ResetDoorOrButton(); + pKTTrigger->SetPhaseMask(1, true); + } + + for (uint8 i = 0; i <= 3; ++i) + { + if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) + { + if (!((pPortal->getLootState() == GO_READY) || (pPortal->getLootState() == GO_NOT_READY))) + pPortal->ResetDoorOrButton(); + } + } + + nGuardiansOfIcecrownCount = 0; + uiGuardiansOfIcecrownTimer = 5000; //5 seconds for summoning each Guardian of Icecrown in phase 3 + + Phase = 0; + nAbomination = 0; + nWeaver = 0; + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + + std::map::const_iterator itr; + for (itr = chained.begin(); itr != chained.end(); ++itr) + { + if (Player* pPlayer = Unit::GetPlayer((*itr).first)) + pPlayer->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + } + chained.clear(); + } + + void EnterCombat(Unit* /*who*/) + { + me->setFaction(uiFaction); + + _EnterCombat(); + FindGameObjects(); + for (uint8 i = 0; i <= 3; ++i) + { + if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) + pPortal->ResetDoorOrButton(); + } + DoCast(me, SPELL_KELTHUZAD_CHANNEL, false); + DoScriptText(SAY_SUMMON_MINIONS, me); + Phase = 1; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4); + events.ScheduleEvent(EVENT_TRIGGER, 5000); + events.ScheduleEvent(EVENT_WASTE, 15000); + events.ScheduleEvent(EVENT_ABOMIN, 30000); + events.ScheduleEvent(EVENT_WEAVER, 50000); + events.ScheduleEvent(EVENT_PHASE, 228000); + } + + void FindGameObjects() + { + PortalsGUID[0] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL01) : 0; + PortalsGUID[1] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL02) : 0; + PortalsGUID[2] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL03) : 0; + PortalsGUID[3] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL04) : 0; + KTTriggerGUID = instance ? instance->GetData64(DATA_KELTHUZAD_TRIGGER) : 0; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateCombatState()) + return; + + events.Update(diff); + + if (Phase == 1) + { + while (uint32 eventId = events.GetEvent()) + { + switch(eventId) + { + case EVENT_WASTE: + DoSummon(NPC_WASTE, Pos[RAND(0,3,6,9)]); + events.RepeatEvent(urand(2000,5000)); + break; + case EVENT_ABOMIN: + if (nAbomination < 8) + { + DoSummon(NPC_ABOMINATION, Pos[RAND(1,4,7,10)]); + nAbomination++; + events.RepeatEvent(20000); + } + else + events.PopEvent(); + break; + case EVENT_WEAVER: + if (nWeaver < 8) + { + DoSummon(NPC_WEAVER, Pos[RAND(0,3,6,9)]); + nWeaver++; + events.RepeatEvent(25000); + } + else + events.PopEvent(); + break; + case EVENT_TRIGGER: + if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID)) + pKTTrigger->SetPhaseMask(2, true); + events.PopEvent(); + break; + case EVENT_PHASE: + events.Reset(); + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + spawns.DespawnAll(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->CastStop(); + + DoStartMovement(me->getVictim()); + events.ScheduleEvent(EVENT_BOLT, urand(5000,10000)); + events.ScheduleEvent(EVENT_NOVA, 15000); + events.ScheduleEvent(EVENT_DETONATE, urand(30000,40000)); + events.ScheduleEvent(EVENT_FISSURE, urand(10000,30000)); + events.ScheduleEvent(EVENT_BLAST, urand(60000,120000)); + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + events.ScheduleEvent(EVENT_CHAIN, urand(30000,60000)); + Phase = 2; + break; + default: + events.PopEvent(); + break; + } + } + } + else + { + //start phase 3 when we are 45% health + if (Phase != 3) + { + if (HealthBelowPct(45)) + { + Phase = 3 ; + DoScriptText(SAY_REQUEST_AID, me); + //here Lich King should respond to KelThuzad but I don't know which Creature to make talk + //so for now just make Kelthuzad says it. + DoScriptText(SAY_ANSWER_REQUEST, me); + + for (uint8 i = 0; i <= 3; ++i) + { + if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) + { + if (pPortal->getLootState() == GO_READY) + pPortal->UseDoorOrButton(); + } + } + } + } + else if (nGuardiansOfIcecrownCount < RAID_MODE(2,4)) + { + if (uiGuardiansOfIcecrownTimer <= diff) + { + // TODO : Add missing text + if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2,5,8,11)])) + pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2); + ++nGuardiansOfIcecrownCount; + uiGuardiansOfIcecrownTimer = 5000; + } + else uiGuardiansOfIcecrownTimer -= diff; + } + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (uint32 eventId = events.GetEvent()) + { + switch(eventId) + { + case EVENT_BOLT: + DoCastVictim(RAID_MODE(SPELL_FROST_BOLT,H_SPELL_FROST_BOLT)); + events.RepeatEvent(urand(5000,10000)); + break; + case EVENT_NOVA: + DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE,H_SPELL_FROST_BOLT_AOE)); + events.RepeatEvent(urand(15000,30000)); + break; + case EVENT_CHAIN: + { + uint32 count = urand(1,3); + for (uint8 i = 1; i <= count; i++) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true); + if (pTarget && !pTarget->isCharmed() && (chained.find(pTarget->GetGUID()) == chained.end())) + { + DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD); + float scale = pTarget->GetFloatValue(OBJECT_FIELD_SCALE_X); + chained.insert(std::make_pair(pTarget->GetGUID(), scale)); + pTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2); + events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm + } + } + if (!chained.empty()) + DoScriptText(RAND(SAY_CHAIN_1,SAY_CHAIN_2), me); + events.RepeatEvent(urand(100000,180000)); + break; + } + case EVENT_CHAINED_SPELL: + { + std::map::iterator itr; + for (itr = chained.begin(); itr != chained.end();) + { + if (Unit* player = Unit::GetPlayer((*itr).first)) + { + if (!player->isCharmed()) + { + player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + std::map::iterator next = itr; + ++next; + chained.erase(itr); + itr = next; + continue; + } + + if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector())) + { + switch(player->getClass()) + { + case CLASS_DRUID: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_MOONFIRE, false); + else + player->CastSpell(me, SPELL_LIFEBLOOM, false); + break; + case CLASS_HUNTER: + player->CastSpell(pTarget, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false); + break; + case CLASS_MAGE: + player->CastSpell(pTarget, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false); + break; + case CLASS_WARLOCK: + player->CastSpell(pTarget, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true); + break; + case CLASS_WARRIOR: + player->CastSpell(pTarget, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false); + break; + case CLASS_PALADIN: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_HAMMER_OF_JUSTICE, false); + else + player->CastSpell(me, SPELL_HOLY_SHOCK, false); + break; + case CLASS_PRIEST: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_VAMPIRIC_TOUCH, false); + else + player->CastSpell(me, SPELL_RENEW, false); + break; + case CLASS_SHAMAN: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_EARTH_SHOCK, false); + else + player->CastSpell(me, SPELL_HEALING_WAVE, false); + break; + case CLASS_ROGUE: + player->CastSpell(pTarget, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false); + break; + case CLASS_DEATH_KNIGHT: + if (urand(0,1)) + player->CastSpell(pTarget, SPELL_PLAGUE_STRIKE, true); + else + player->CastSpell(pTarget, SPELL_HOWLING_BLAST, true); + break; + } + } + } + ++itr; + } + + if (chained.empty()) + events.PopEvent(); + else + events.RepeatEvent(5000); + + break; + } + case EVENT_DETONATE: + { + std::vector unitList; + std::list *threatList = &me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr) + { + if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER + && (*itr)->getTarget()->getPowerType() == POWER_MANA + && (*itr)->getTarget()->GetPower(POWER_MANA)) + unitList.push_back((*itr)->getTarget()); + } + + if (!unitList.empty()) + { + std::vector::const_iterator itr = unitList.begin(); + advance(itr, rand()%unitList.size()); + DoCast(*itr, SPELL_MANA_DETONATION); + DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2,SAY_SPECIAL_3), me); + } + + events.RepeatEvent(urand(20000,50000)); + break; + } + case EVENT_FISSURE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_FISURE); + events.RepeatEvent(urand(10000,45000)); + break; + case EVENT_BLAST: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1,0), 0, true)) + DoCast(pTarget, SPELL_FROST_BLAST); + if (rand()%2) + DoScriptText(SAY_FROST_BLAST, me); + events.RepeatEvent(urand(30000,90000)); + break; + default: + events.PopEvent(); + break; + } + } + + DoMeleeAttackIfReady(); + } + } +}; + +CreatureAI* GetAI_boss_kelthuzadAI(Creature* pCreature) +{ + return new boss_kelthuzadAI (pCreature); +} + +bool AreaTrigger_at_kelthuzad_center(Player* pPlayer, const AreaTriggerEntry * /*at*/) +{ + if (pPlayer->isGameMaster()) + return false; + + ScriptedInstance* pInstance = pPlayer->GetInstanceData(); + if (!pInstance || pInstance->IsEncounterInProgress() || pInstance->GetBossState(BOSS_KELTHUZAD) == DONE) + return false; + + Creature* pKelthuzad = CAST_CRE(Unit::GetUnit(*pPlayer, pInstance->GetData64(DATA_KELTHUZAD))); + if (!pKelthuzad) + return false; + + boss_kelthuzadAI* pKelthuzadAI = CAST_AI(boss_kelthuzadAI, pKelthuzad->AI()); + if (!pKelthuzadAI) + return false; + + pKelthuzadAI->AttackStart(pPlayer); + if (GameObject* trigger = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_TRIGGER))) + { + if (trigger->getLootState() == GO_READY) + trigger->UseDoorOrButton(); + + // Note: summon must be done by trigger and not by KT. + // Otherwise, they attack immediately as KT is in combat. + for (uint8 i = 0; i <= MAX_ABOMINATIONS; ++i) + { + if (Creature* sum = trigger->SummonCreature(NPC_ABOMINATION, PosAbominations[i])) + { + pKelthuzadAI->spawns.Summon(sum); + sum->GetMotionMaster()->MoveRandom(9.0f); + sum->SetReactState(REACT_DEFENSIVE); + } + } + for (uint8 i = 0; i <= MAX_WASTES; ++i) + { + if (Creature* sum = trigger->SummonCreature(NPC_WASTE, PosWastes[i])) + { + pKelthuzadAI->spawns.Summon(sum); + sum->GetMotionMaster()->MoveRandom(5.0f); + sum->SetReactState(REACT_DEFENSIVE); + } + } + for (uint8 i = 0; i <= MAX_WEAVERS; ++i) + { + if (Creature* sum = trigger->SummonCreature(NPC_WEAVER, PosWeavers[i])) + { + pKelthuzadAI->spawns.Summon(sum); + sum->GetMotionMaster()->MoveRandom(9.0f); + sum->SetReactState(REACT_DEFENSIVE); + } + } + } + + return true; +} + +void AddSC_boss_kelthuzad() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kelthuzad"; + newscript->GetAI = &GetAI_boss_kelthuzadAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_kelthuzad_center"; + newscript->pAreaTrigger = &AreaTrigger_at_kelthuzad_center; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp new file mode 100644 index 00000000000..0b0c8f5e4c5 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Spells +{ + SPELL_NECROTIC_AURA = 55593, + SPELL_SUMMON_SPORE = 29234, + SPELL_DEATHBLOOM = 29865, + H_SPELL_DEATHBLOOM = 55053, + SPELL_INEVITABLE_DOOM = 29204, + H_SPELL_INEVITABLE_DOOM = 55052 +}; + +enum Events +{ + EVENT_NONE, + EVENT_AURA, + EVENT_BLOOM, + EVENT_DOOM, +}; + +struct boss_loathebAI : public BossAI +{ + boss_loathebAI(Creature *c) : BossAI(c, BOSS_LOATHEB) {} + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + events.ScheduleEvent(EVENT_AURA, 10000); + events.ScheduleEvent(EVENT_BLOOM, 5000); + events.ScheduleEvent(EVENT_DOOM, 120000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_AURA: + DoCastAOE(SPELL_NECROTIC_AURA); + events.ScheduleEvent(EVENT_AURA, 20000); + break; + case EVENT_BLOOM: + // TODO : Add missing text + DoCastAOE(SPELL_SUMMON_SPORE, true); + DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM,H_SPELL_DEATHBLOOM)); + events.ScheduleEvent(EVENT_BLOOM, 30000); + break; + case EVENT_DOOM: + DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM,H_SPELL_INEVITABLE_DOOM)); + events.ScheduleEvent(EVENT_DOOM, events.GetTimer() < 5*60000 ? 30000 : 15000); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_loatheb(Creature* pCreature) +{ + return new boss_loathebAI (pCreature); +} + +enum SporeSpells +{ + SPELL_FUNGAL_CREEP = 29232 +}; + +struct mob_loatheb_sporeAI : public ScriptedAI +{ + mob_loatheb_sporeAI(Creature *c) : ScriptedAI(c) {} + + void JustDied(Unit* killer) + { + DoCast(killer, SPELL_FUNGAL_CREEP); + } +}; + +CreatureAI* GetAI_mob_loatheb_spore(Creature* pCreature) +{ + return new mob_loatheb_sporeAI (pCreature); +} + +void AddSC_boss_loatheb() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_loatheb"; + newscript->GetAI = &GetAI_boss_loatheb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_loatheb_spore"; + newscript->GetAI = &GetAI_mob_loatheb_spore; + newscript->RegisterSelf(); + + // Fungal Creep + //GetAISpellInfo(29232)->condition = AICOND_DIE; +} + diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp new file mode 100644 index 00000000000..71d9cb86102 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Spells +{ + SPELL_WEB_WRAP = 28622, + SPELL_WEB_SPRAY_10 = 29484, + SPELL_WEB_SPRAY_25 = 54125, + SPELL_POISON_SHOCK_10 = 28741, + SPELL_POISON_SHOCK_25 = 54122, + SPELL_NECROTIC_POISON_10 = 28776, + SPELL_NECROTIC_POISON_25 = 54121, + SPELL_FRENZY_10 = 54123, + SPELL_FRENZY_25 = 54124, +}; + +enum Creatures +{ + MOB_WEB_WRAP = 16486, + MOB_SPIDERLING = 17055, +}; + +#define MAX_POS_WRAP 3 +const Position PosWrap[MAX_POS_WRAP] = +{ + {3546.796, -3869.082, 296.450, 0.0}, + {3531.271, -3847.424, 299.450, 0.0}, + {3497.067, -3843.384, 302.384, 0.0}, +}; + +enum Events +{ + EVENT_NONE, + EVENT_SPRAY, + EVENT_SHOCK, + EVENT_POISON, + EVENT_WRAP, + EVENT_SUMMON, + EVENT_FRENZY, +}; + +struct boss_maexxnaAI : public BossAI +{ + boss_maexxnaAI(Creature *c) : BossAI(c, BOSS_MAEXXNA) {} + + bool enraged; + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + enraged = false; + events.ScheduleEvent(EVENT_WRAP, 20000); + events.ScheduleEvent(EVENT_SPRAY, 40000); + events.ScheduleEvent(EVENT_SHOCK, urand(5000,10000)); + events.ScheduleEvent(EVENT_POISON, urand(10000,15000)); + events.ScheduleEvent(EVENT_SUMMON, 30000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() || !CheckInRoom()) + return; + + if (!enraged && HealthBelowPct(30)) + { + enraged = true; + events.ScheduleEvent(EVENT_FRENZY, 0); // will be cast immediately + } + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_WRAP: + // TODO : Add missing text + for (uint8 i = 0; i < RAID_MODE(1,2); ++i) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP)) + { + pTarget->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25)); + uint8 pos = rand()%MAX_POS_WRAP; + pTarget->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20); + if (Creature *wrap = DoSummon(MOB_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN)) + wrap->AI()->SetGUID(pTarget->GetGUID()); + } + } + events.ScheduleEvent(EVENT_WRAP, 40000); + break; + case EVENT_SPRAY: + DoCastAOE(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25)); + events.ScheduleEvent(EVENT_SPRAY, 40000); + break; + case EVENT_SHOCK: + DoCastAOE(RAID_MODE(SPELL_POISON_SHOCK_10,SPELL_POISON_SHOCK_25)); + events.ScheduleEvent(EVENT_SHOCK, urand(10000,20000)); + break; + case EVENT_POISON: + DoCast(me->getVictim(), RAID_MODE(SPELL_NECROTIC_POISON_10,SPELL_NECROTIC_POISON_25)); + events.ScheduleEvent(EVENT_POISON, urand(10000, 20000)); + break; + case EVENT_FRENZY: + DoCast(me, RAID_MODE(SPELL_FRENZY_10,SPELL_FRENZY_25), true); + events.ScheduleEvent(EVENT_FRENZY, 600000); + break; + case EVENT_SUMMON: + // TODO : Add missing text + uint8 amount = urand(8,10); + for (uint8 i = 0; i < amount; ++i) + DoSummon(MOB_SPIDERLING, me, 0, TEMPSUMMON_CORPSE_DESPAWN); + events.ScheduleEvent(EVENT_SUMMON, 40000); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_webwrapAI : public NullCreatureAI +{ + mob_webwrapAI(Creature *c) : NullCreatureAI(c), victimGUID(0) {} + + uint64 victimGUID; + + void SetGUID(const uint64 &guid, int32 /*param*/) + { + victimGUID = guid; + if (me->m_spells[0] && victimGUID) + if (Unit *victim = Unit::GetUnit(*me, victimGUID)) + victim->CastSpell(victim, me->m_spells[0], true, NULL, NULL, me->GetGUID()); + } + + void JustDied(Unit * /*killer*/) + { + if (me->m_spells[0] && victimGUID) + if (Unit *victim = Unit::GetUnit(*me, victimGUID)) + victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID()); + } +}; + +CreatureAI* GetAI_boss_maexxna(Creature* pCreature) +{ + return new boss_maexxnaAI (pCreature); +} + +CreatureAI* GetAI_mob_webwrap(Creature* pCreature) +{ + return new mob_webwrapAI (pCreature); +} + +void AddSC_boss_maexxna() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_maexxna"; + newscript->GetAI = &GetAI_boss_maexxna; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_webwrap"; + newscript->GetAI = &GetAI_mob_webwrap; + newscript->RegisterSelf(); + +} + diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp new file mode 100644 index 00000000000..b0cd4018955 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -0,0 +1,212 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define SAY_AGGRO RAND(-1533075,-1533076,-1533077) +#define SAY_SUMMON -1533078 +#define SAY_SLAY RAND(-1533079,-1533080) +#define SAY_DEATH -1533081 + +#define SOUND_DEATH 8848 + +#define SPELL_CURSE_PLAGUEBRINGER RAID_MODE(29213,54835) +#define SPELL_BLINK RAND(29208,29209,29210,29211) +#define SPELL_CRIPPLE RAID_MODE(29212,54814) +#define SPELL_TELEPORT 29216 + +#define MOB_WARRIOR 16984 +#define MOB_CHAMPION 16983 +#define MOB_GUARDIAN 16981 + +// Teleport position of Noth on his balcony +#define TELE_X 2631.370 +#define TELE_Y -3529.680 +#define TELE_Z 274.040 +#define TELE_O 6.277 + +#define MAX_SUMMON_POS 5 + +const float SummonPos[MAX_SUMMON_POS][4] = +{ + {2728.12, -3544.43, 261.91, 6.04}, + {2729.05, -3544.47, 261.91, 5.58}, + {2728.24, -3465.08, 264.20, 3.56}, + {2704.11, -3456.81, 265.53, 4.51}, + {2663.56, -3464.43, 262.66, 5.20}, +}; + +enum Events +{ + EVENT_NONE, + EVENT_BERSERK, + EVENT_CURSE, + EVENT_BLINK, + EVENT_WARRIOR, + EVENT_BALCONY, + EVENT_WAVE, + EVENT_GROUND, +}; + +struct boss_nothAI : public BossAI +{ + boss_nothAI(Creature *c) : BossAI(c, BOSS_NOTH) {} + + uint32 waveCount, balconyCount; + + void Reset() + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + _Reset(); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO, me); + balconyCount = 0; + EnterPhaseGround(); + } + + void EnterPhaseGround() + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoZoneInCombat(); + if (me->getThreatManager().isThreatListEmpty()) + EnterEvadeMode(); + else + { + events.ScheduleEvent(EVENT_BALCONY, 110000); + events.ScheduleEvent(EVENT_CURSE, 10000+rand()%15000); + events.ScheduleEvent(EVENT_WARRIOR, 30000); + if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + events.ScheduleEvent(EVENT_BLINK, 20000 + rand()%20000); + } + } + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_SLAY, me); + } + + void JustSummoned(Creature *summon) + { + summons.Summon(summon); + summon->setActive(true); + summon->AI()->DoZoneInCombat(); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + } + + void SummonUndead(uint32 entry, uint32 num) + { + for (uint32 i = 0; i < num; ++i) + { + uint32 pos = rand()%MAX_SUMMON_POS; + me->SummonCreature(entry, SummonPos[pos][0], SummonPos[pos][1], SummonPos[pos][2], + SummonPos[pos][3], TEMPSUMMON_CORPSE_DESPAWN, 60000); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateCombatState() || !CheckInRoom()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CURSE: + DoCastAOE(SPELL_CURSE_PLAGUEBRINGER); + events.ScheduleEvent(EVENT_CURSE, 50000 + rand()%10000); + return; + case EVENT_WARRIOR: + DoScriptText(SAY_SUMMON, me); + SummonUndead(MOB_WARRIOR, RAID_MODE(2,3)); + events.ScheduleEvent(EVENT_WARRIOR, 30000); + return; + case EVENT_BLINK: + DoCastAOE(SPELL_CRIPPLE, true); + DoCastAOE(SPELL_BLINK); + DoResetThreat(); + events.ScheduleEvent(EVENT_BLINK, 40000); + return; + case EVENT_BALCONY: + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->AttackStop(); + me->RemoveAllAuras(); + me->NearTeleportTo(TELE_X, TELE_Y, TELE_Z, TELE_O); + events.Reset(); + events.ScheduleEvent(EVENT_WAVE, 2000 + rand()%3000); + waveCount = 0; + return; + case EVENT_WAVE: + DoScriptText(SAY_SUMMON, me); + switch(balconyCount) + { + case 0: SummonUndead(MOB_CHAMPION, RAID_MODE(2,4)); break; + case 1: SummonUndead(MOB_CHAMPION, RAID_MODE(1,2)); + SummonUndead(MOB_GUARDIAN, RAID_MODE(1,2)); break; + case 2: SummonUndead(MOB_GUARDIAN, RAID_MODE(2,4)); break; + default:SummonUndead(MOB_CHAMPION, RAID_MODE(5,10)); + SummonUndead(MOB_GUARDIAN, RAID_MODE(5,10));break; + } + ++waveCount; + events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, 30000 + rand()%15000); + return; + case EVENT_GROUND: + { + ++balconyCount; + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + me->NearTeleportTo(x, y, z, o); + events.ScheduleEvent(EVENT_BALCONY, 110000); + EnterPhaseGround(); + return; + } + } + } + + if (me->HasReactState(REACT_AGGRESSIVE)) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_noth(Creature* pCreature) +{ + return new boss_nothAI (pCreature); +} + +void AddSC_boss_noth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_noth"; + newscript->GetAI = &GetAI_boss_noth; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp new file mode 100644 index 00000000000..e4472b299ce --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp @@ -0,0 +1,159 @@ +/* Copyright (C) 2008 - 2009 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +enum Spells +{ + SPELL_HATEFUL_STRIKE = 41926, + H_SPELL_HATEFUL_STRIKE = 59192, + SPELL_FRENZY = 28131, + SPELL_BERSERK = 26662, + SPELL_SLIME_BOLT = 32309, +}; + +enum Yells +{ + SAY_AGGRO_1 = -1533017, + SAY_AGGRO_2 = -1533018, + SAY_SLAY = -1533019, + SAY_DEATH = -1533020, + EMOTE_BERSERK = -1533021, + EMOTE_ENRAGE = -1533022, +}; + +enum Events +{ + EVENT_NONE, + EVENT_BERSERK, + EVENT_HATEFUL, + EVENT_SLIME +}; + +enum +{ + ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT = 10286, +}; + +struct boss_patchwerkAI : public BossAI +{ + boss_patchwerkAI(Creature *c) : BossAI(c, BOSS_PATCHWERK) {} + + bool Enraged; + + void Reset() + { + _Reset(); + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); + } + + void KilledUnit(Unit* /*Victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_SLAY, me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + Enraged = false; + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me); + events.ScheduleEvent(EVENT_HATEFUL, 1200); + events.ScheduleEvent(EVENT_BERSERK, 360000); + + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_HATEFUL: + { + //Cast Hateful strike on the player with the highest + //amount of HP within melee distance + uint32 MostHP = 0; + Unit* pMostHPTarget = NULL; + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit *pTarget = (*i)->getTarget(); + if (pTarget->isAlive() && pTarget->GetHealth() > MostHP && me->IsWithinMeleeRange(pTarget)) + { + MostHP = pTarget->GetHealth(); + pMostHPTarget = pTarget; + } + } + + if (pMostHPTarget) + DoCast(pMostHPTarget, RAID_MODE(SPELL_HATEFUL_STRIKE,H_SPELL_HATEFUL_STRIKE), true); + + events.ScheduleEvent(EVENT_HATEFUL, 1200); + break; + } + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK, true); + DoScriptText(EMOTE_BERSERK, me); + events.ScheduleEvent(EVENT_SLIME, 2000); + break; + case EVENT_SLIME: + DoCast(me->getVictim(), SPELL_SLIME_BOLT); + events.ScheduleEvent(EVENT_SLIME, 2000); + break; + } + } + + if (!Enraged && HealthBelowPct(5)) + { + DoCast(me, SPELL_FRENZY, true); + DoScriptText(EMOTE_ENRAGE, me); + Enraged = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_patchwerk(Creature* pCreature) +{ + return new boss_patchwerkAI (pCreature); +} + +void AddSC_boss_patchwerk() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_patchwerk"; + newscript->GetAI = &GetAI_boss_patchwerk; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp new file mode 100644 index 00000000000..d507df86e83 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +//Razuvious - NO TEXT sound only +//8852 aggro01 - Hah hah, I'm just getting warmed up! +//8853 aggro02 Stand and fight! +//8854 aggro03 Show me what you've got! +//8861 slay1 - You should've stayed home! +//8863 slay2- +//8858 cmmnd3 - You disappoint me, students! +//8855 cmmnd1 - Do as I taught you! +//8856 cmmnd2 - Show them no mercy! +//8859 cmmnd4 - The time for practice is over! Show me what you've learned! +//8861 Sweep the leg! Do you have a problem with that? +//8860 death - An honorable... death... +//8947 - Aggro Mixed? - ? + +#define SOUND_AGGRO RAND(8852,8853,8854) +#define SOUND_SLAY RAND(8861,8863) +#define SOUND_COMMND RAND(8855,8856,8858,8859,8861) +#define SOUND_DEATH 8860 +#define SOUND_AGGROMIX 8847 + +#define SPELL_UNBALANCING_STRIKE 26613 +#define SPELL_DISRUPTING_SHOUT RAID_MODE(29107,55543) +#define SPELL_JAGGED_KNIFE 55550 +#define SPELL_HOPELESS 29125 + +enum Events +{ + EVENT_NONE, + EVENT_STRIKE, + EVENT_SHOUT, + EVENT_KNIFE, + EVENT_COMMAND, +}; + +struct boss_razuviousAI : public BossAI +{ + boss_razuviousAI(Creature *c) : BossAI(c, BOSS_RAZUVIOUS) {} + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%3)) + DoPlaySoundToSet(me, SOUND_SLAY); + } + + void DamageTaken(Unit* pDone_by, uint32& uiDamage) + { + // Damage done by the controlled Death Knight understudies should also count toward damage done by players + if (pDone_by->GetTypeId() == TYPEID_UNIT && (pDone_by->GetEntry() == 16803 || pDone_by->GetEntry() == 29941)) + { + me->LowerPlayerDamageReq(uiDamage); + } + } + + void JustDied(Unit* /*killer*/) + { + _JustDied(); + DoPlaySoundToSet(me, SOUND_DEATH); + me->CastSpell(me, SPELL_HOPELESS, true); // TODO: this may affect other creatures + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoPlaySoundToSet(me, SOUND_AGGRO); + events.ScheduleEvent(EVENT_STRIKE, 30000); + events.ScheduleEvent(EVENT_SHOUT, 25000); + events.ScheduleEvent(EVENT_COMMAND, 40000); + events.ScheduleEvent(EVENT_KNIFE, 10000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_STRIKE: + DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE); + events.ScheduleEvent(EVENT_STRIKE, 30000); + return; + case EVENT_SHOUT: + DoCastAOE(SPELL_DISRUPTING_SHOUT); + events.ScheduleEvent(EVENT_SHOUT, 25000); + return; + case EVENT_KNIFE: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) + DoCast(pTarget, SPELL_JAGGED_KNIFE); + events.ScheduleEvent(EVENT_KNIFE, 10000); + return; + case EVENT_COMMAND: + DoPlaySoundToSet(me, SOUND_COMMND); + events.ScheduleEvent(EVENT_COMMAND, 40000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_razuvious(Creature* pCreature) +{ + return new boss_razuviousAI (pCreature); +} + +void AddSC_boss_razuvious() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_razuvious"; + newscript->GetAI = &GetAI_boss_razuvious; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp new file mode 100644 index 00000000000..d75b3ab78b0 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +#define EMOTE_BREATH -1533082 +#define EMOTE_ENRAGE -1533083 + +#define SPELL_FROST_AURA RAID_MODE(28531,55799) +#define SPELL_CLEAVE 19983 +#define SPELL_TAIL_SWEEP RAID_MODE(55697,55696) +#define SPELL_SUMMON_BLIZZARD 28560 +#define SPELL_LIFE_DRAIN RAID_MODE(28542,55665) +#define SPELL_ICEBOLT 28522 +#define SPELL_FROST_BREATH 29318 +#define SPELL_FROST_EXPLOSION 28524 +#define SPELL_FROST_MISSILE 30101 +#define SPELL_BERSERK 26662 +#define SPELL_DIES 29357 + +#define SPELL_CHILL RAID_MODE(28547,55699) + +#define MOB_BLIZZARD 16474 +#define GO_ICEBLOCK 181247 + +#define ACHIEVEMENT_THE_HUNDRED_CLUB RAID_MODE(2146, 2147) +#define MAX_FROST_RESISTANCE 100 + +enum Phases +{ + PHASE_NULL = 0, + PHASE_BIRTH, + PHASE_GROUND, + PHASE_FLIGHT, +}; + +enum Events +{ + EVENT_NONE, + EVENT_BERSERK, + EVENT_CLEAVE, + EVENT_TAIL, + EVENT_DRAIN, + EVENT_BLIZZARD, + EVENT_FLIGHT, + EVENT_LIFTOFF, + EVENT_ICEBOLT, + EVENT_BREATH, + EVENT_EXPLOSION, + EVENT_LAND, + EVENT_GROUND, + EVENT_BIRTH, +}; + +typedef std::map IceBlockMap; + +struct boss_sapphironAI : public BossAI +{ + boss_sapphironAI(Creature* c) : BossAI(c, BOSS_SAPPHIRON) + , phase(PHASE_NULL) + { + pMap = me->GetMap(); + } + + Phases phase; + uint32 iceboltCount; + IceBlockMap iceblocks; + + bool CanTheHundredClub; // needed for achievement: The Hundred Club(2146, 2147) + uint32 CheckFrostResistTimer; + Map* pMap; + + void InitializeAI() + { + float x, y, z; + me->GetPosition(x, y, z); + me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + + ScriptedAI::InitializeAI(); + } + + void Reset() + { + _Reset(); + + if (phase == PHASE_FLIGHT) + ClearIceBlock(); + + phase = PHASE_NULL; + + CanTheHundredClub = true; + CheckFrostResistTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + + me->CastSpell(me, SPELL_FROST_AURA, true); + + events.ScheduleEvent(EVENT_BERSERK, 15*60000); + EnterPhaseGround(); + + CheckPlayersFrostResist(); + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (spell->Id == SPELL_ICEBOLT) + { + IceBlockMap::iterator itr = iceblocks.find(pTarget->GetGUID()); + if (itr != iceblocks.end() && !itr->second) + { + if (GameObject *iceblock = me->SummonGameObject(GO_ICEBLOCK, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, 0, 0, 0, 0, 25000)) + itr->second = iceblock->GetGUID(); + } + } + } + + void JustDied(Unit* /*who*/) + { + _JustDied(); + me->CastSpell(me, SPELL_DIES, true); + + CheckPlayersFrostResist(); + if (CanTheHundredClub) + { + AchievementEntry const *AchievTheHundredClub = GetAchievementStore()->LookupEntry(ACHIEVEMENT_THE_HUNDRED_CLUB); + if (AchievTheHundredClub) + { + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievTheHundredClub); + } + } + } + } + + void MovementInform(uint32, uint32 id) + { + if (id == 1) + events.ScheduleEvent(EVENT_LIFTOFF, 0); + } + + void DoAction(const int32 param) + { + if (param == DATA_SAPPHIRON_BIRTH) + { + phase = PHASE_BIRTH; + events.ScheduleEvent(EVENT_BIRTH, 23000); + } + } + + void CheckPlayersFrostResist() + { + if (CanTheHundredClub && pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (itr->getSource()->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE) + { + CanTheHundredClub = false; + break; + } + } + } + } + + void EnterPhaseGround() + { + phase = PHASE_GROUND; + me->SetReactState(REACT_AGGRESSIVE); + events.SetPhase(PHASE_GROUND); + events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_BLIZZARD, 5000+rand()%5000, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_FLIGHT, 45000); + } + + void ClearIceBlock() + { + for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr) + { + if (Player* pPlayer = Unit::GetPlayer(itr->first)) + pPlayer->RemoveAura(SPELL_ICEBOLT); + if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second)) + pGo->Delete(); + } + iceblocks.clear(); + } + + void UpdateAI(const uint32 diff) + { + if (!phase) + return; + + events.Update(diff); + + if (phase != PHASE_BIRTH && !UpdateCombatState() || !CheckInRoom()) + return; + + if (CanTheHundredClub) + { + if (CheckFrostResistTimer <= diff) + { + CheckPlayersFrostResist(); + CheckFrostResistTimer = (rand() % 5 + 5) * 1000; + } else CheckFrostResistTimer -= diff; + } + + if (phase == PHASE_GROUND) + { + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BERSERK: + DoScriptText(EMOTE_ENRAGE, me); + DoCast(me, SPELL_BERSERK); + return; + case EVENT_CLEAVE: + DoCast(me->getVictim(), SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); + return; + case EVENT_TAIL: + DoCastAOE(SPELL_TAIL_SWEEP); + events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); + return; + case EVENT_DRAIN: + DoCastAOE(SPELL_LIFE_DRAIN); + events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); + return; + case EVENT_BLIZZARD: + { + //DoCastAOE(SPELL_SUMMON_BLIZZARD); + if (Creature *pSummon = DoSummon(MOB_BLIZZARD, me, 0.0f, urand(25000,30000), TEMPSUMMON_TIMED_DESPAWN)) + pSummon->GetMotionMaster()->MoveRandom(40); + events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20000,7000), 0, PHASE_GROUND); + break; + } + case EVENT_FLIGHT: + phase = PHASE_FLIGHT; + events.SetPhase(PHASE_FLIGHT); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + float x, y, z, o; + me->GetHomePosition(x, y, z, o); + me->GetMotionMaster()->MovePoint(1, x, y, z); + return; + } + } + + DoMeleeAttackIfReady(); + } + else + { + if (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_LIFTOFF: + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMovementFlagUpdate(); + events.ScheduleEvent(EVENT_ICEBOLT, 1500); + iceboltCount = RAID_MODE(2,3); + return; + case EVENT_ICEBOLT: + { + std::vector targets; + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT)) + targets.push_back((*i)->getTarget()); + + if (targets.empty()) + iceboltCount = 0; + else + { + std::vector::const_iterator itr = targets.begin(); + advance(itr, rand()%targets.size()); + iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0)); + DoCast(*itr, SPELL_ICEBOLT); + --iceboltCount; + } + + if (iceboltCount) + events.ScheduleEvent(EVENT_ICEBOLT, 1000); + else + events.ScheduleEvent(EVENT_BREATH, 1000); + return; + } + case EVENT_BREATH: + { + DoScriptText(EMOTE_BREATH, me); + DoCastAOE(SPELL_FROST_MISSILE); + events.ScheduleEvent(EVENT_EXPLOSION, 8000); + return; + } + case EVENT_EXPLOSION: + CastExplosion(); + ClearIceBlock(); + events.ScheduleEvent(EVENT_LAND, 3000); + return; + case EVENT_LAND: + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->SendMovementFlagUpdate(); + events.ScheduleEvent(EVENT_GROUND, 1500); + return; + case EVENT_GROUND: + EnterPhaseGround(); + return; + case EVENT_BIRTH: + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + return; + } + }//if (uint32 eventId = events.ExecuteEvent()) + }//if (phase == PHASE_GROUND) + } + + void CastExplosion() + { + DoZoneInCombat(); // make sure everyone is in threatlist + std::vector targets; + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit *pTarget = (*i)->getTarget(); + if (pTarget->GetTypeId() != TYPEID_PLAYER) + continue; + + if (pTarget->HasAura(SPELL_ICEBOLT)) + { + pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); + targets.push_back(pTarget); + continue; + } + + for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr) + { + if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second)) + { + if (pGo->IsInBetween(me, pTarget, 2.0f) + && me->GetExactDist2d(pTarget->GetPositionX(), pTarget->GetPositionY()) - me->GetExactDist2d(pGo->GetPositionX(), pGo->GetPositionY()) < 5.0f) + { + pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); + targets.push_back(pTarget); + break; + } + } + } + } + + me->CastSpell(me, SPELL_FROST_EXPLOSION, true); + + for (std::vector::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + (*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false); + } +}; + +CreatureAI* GetAI_boss_sapphiron(Creature* pCreature) +{ + return new boss_sapphironAI (pCreature); +} + +void AddSC_boss_sapphiron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_sapphiron"; + newscript->GetAI = &GetAI_boss_sapphiron; + newscript->RegisterSelf(); + + // Chill + GetAISpellInfo(28547)->cooldown = 1000; + GetAISpellInfo(55699)->cooldown = 1000; +} diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp new file mode 100644 index 00000000000..350cd450510 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2008 - 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +//Stalagg +enum StalaggYells +{ + SAY_STAL_AGGRO = -1533023, //not used + SAY_STAL_SLAY = -1533024, //not used + SAY_STAL_DEATH = -1533025 //not used +}; + +enum StalagSpells +{ + SPELL_POWERSURGE = 28134, + H_SPELL_POWERSURGE = 54529, + SPELL_MAGNETIC_PULL = 28338, + SPELL_STALAGG_TESLA = 28097 +}; + +//Feugen +enum FeugenYells +{ + SAY_FEUG_AGGRO = -1533026, //not used + SAY_FEUG_SLAY = -1533027, //not used + SAY_FEUG_DEATH = -1533028 //not used +}; + +enum FeugenSpells +{ + SPELL_STATICFIELD = 28135, + H_SPELL_STATICFIELD = 54528, + SPELL_FEUGEN_TESLA = 28109 +}; + +// Thaddius DoAction +enum ThaddiusActions +{ + ACTION_FEUGEN_RESET, + ACTION_FEUGEN_DIED, + ACTION_STALAGG_RESET, + ACTION_STALAGG_DIED +}; + +//generic +#define C_TESLA_COIL 16218 //the coils (emotes "Tesla Coil overloads!") + +//Thaddius +enum ThaddiusYells +{ + SAY_GREET = -1533029, //not used + SAY_AGGRO_1 = -1533030, + SAY_AGGRO_2 = -1533031, + SAY_AGGRO_3 = -1533032, + SAY_SLAY = -1533033, + SAY_ELECT = -1533034, //not used + SAY_DEATH = -1533035, + SAY_SCREAM1 = -1533036, //not used + SAY_SCREAM2 = -1533037, //not used + SAY_SCREAM3 = -1533038, //not used + SAY_SCREAM4 = -1533039 //not used +}; + +enum ThaddiusSpells +{ + SPELL_POLARITY_SHIFT = 28089, + SPELL_BALL_LIGHTNING = 28299, + SPELL_CHAIN_LIGHTNING = 28167, + H_SPELL_CHAIN_LIGHTNING = 54531, + SPELL_BERSERK = 27680 +}; + +enum Events +{ + EVENT_NONE, + EVENT_SHIFT, + EVENT_CHAIN, + EVENT_BERSERK, +}; + +struct boss_thaddiusAI : public BossAI +{ + boss_thaddiusAI(Creature *c) : BossAI(c, BOSS_THADDIUS) + { + // init is a bit tricky because thaddius shall track the life of both adds, but not if there was a wipe + // and, in particular, if there was a crash after both adds were killed (should not respawn) + + // Moreover, the adds may not yet be spawn. So just track down the status if mob is spawn + // and each mob will send its status at reset (meaning that it is alive) + checkFeugenAlive = false; + if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN))) + checkFeugenAlive = pFeugen->isAlive(); + + checkStalaggAlive = false; + if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG))) + checkStalaggAlive = pStalagg->isAlive(); + + if (!checkFeugenAlive && !checkStalaggAlive) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + me->SetReactState(REACT_AGGRESSIVE); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + me->SetReactState(REACT_PASSIVE); + } + } + + bool checkStalaggAlive; + bool checkFeugenAlive; + uint32 uiAddsTimer; + + void KilledUnit(Unit* /*victim*/) + { + if (!(rand()%5)) + DoScriptText(SAY_SLAY, me); + } + + void JustDied(Unit* /*Killer*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + } + + void DoAction(const int32 action) + { + switch(action) + { + case ACTION_FEUGEN_RESET: + checkFeugenAlive = true; + break; + case ACTION_FEUGEN_DIED: + checkFeugenAlive = false; + break; + case ACTION_STALAGG_RESET: + checkStalaggAlive = true; + break; + case ACTION_STALAGG_DIED: + checkStalaggAlive = false; + break; + } + + if (!checkFeugenAlive && !checkStalaggAlive) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + // REACT_AGGRESSIVE only reset when he takes damage. + DoZoneInCombat(); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + me->SetReactState(REACT_PASSIVE); + } + } + + void EnterCombat(Unit * /*who*/) + { + _EnterCombat(); + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + events.ScheduleEvent(EVENT_SHIFT, 30000); + events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000)); + events.ScheduleEvent(EVENT_BERSERK, 360000); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 & /*uiDamage*/) + { + me->SetReactState(REACT_AGGRESSIVE); + } + + void UpdateAI(const uint32 diff) + { + if (checkFeugenAlive && checkStalaggAlive) + uiAddsTimer = 0; + + if (checkStalaggAlive != checkFeugenAlive) + { + uiAddsTimer += diff; + if (uiAddsTimer > 5000) + { + if (!checkStalaggAlive) + { + if (instance) + if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG))) + pStalagg->Respawn(); + } + else + { + if (instance) + if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN))) + pFeugen->Respawn(); + } + } + } + + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHIFT: + DoCastAOE(SPELL_POLARITY_SHIFT); + events.ScheduleEvent(EVENT_SHIFT, 30000); + return; + case EVENT_CHAIN: + DoCast(me->getVictim(), RAID_MODE(SPELL_CHAIN_LIGHTNING, H_SPELL_CHAIN_LIGHTNING)); + events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000)); + return; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + return; + } + } + + if (events.GetTimer() > 15000 && !me->IsWithinMeleeRange(me->getVictim())) + DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); + else + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thaddius(Creature* pCreature) +{ + return new boss_thaddiusAI (pCreature); +} + +struct mob_stalaggAI : public ScriptedAI +{ + mob_stalaggAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 powerSurgeTimer; + uint32 magneticPullTimer; + + void Reset() + { + if (pInstance) + if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) + if (pThaddius->AI()) + pThaddius->AI()->DoAction(ACTION_STALAGG_RESET); + powerSurgeTimer = urand(20000,25000); + magneticPullTimer = 20000; + } + + void EnterCombat(Unit * /*pWho*/) + { + DoCast(SPELL_STALAGG_TESLA); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) + if (pThaddius->AI()) + pThaddius->AI()->DoAction(ACTION_STALAGG_DIED); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (magneticPullTimer <= uiDiff) + { + if (Creature *pFeugen = me->GetCreature(*me, pInstance->GetData64(DATA_FEUGEN))) + { + Unit* pStalaggVictim = me->getVictim(); + Unit* pFeugenVictim = pFeugen->getVictim(); + + if (pFeugenVictim && pStalaggVictim) + { + // magnetic pull is not working. So just jump. + + // reset aggro to be sure that feugen will not follow the jump + pFeugen->getThreatManager().modifyThreatPercent(pFeugenVictim, -100); + pFeugenVictim->JumpTo(me, 0.3f); + + me->getThreatManager().modifyThreatPercent(pStalaggVictim, -100); + pStalaggVictim->JumpTo(pFeugen, 0.3f); + } + } + + magneticPullTimer = 20000; + } + else magneticPullTimer -= uiDiff; + + if (powerSurgeTimer <= uiDiff) + { + DoCast(me, RAID_MODE(SPELL_POWERSURGE, H_SPELL_POWERSURGE)); + powerSurgeTimer = urand(15000,20000); + } else powerSurgeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_stalagg(Creature* pCreature) +{ + return new mob_stalaggAI(pCreature); +} + +struct mob_feugenAI : public ScriptedAI +{ + mob_feugenAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 staticFieldTimer; + + void Reset() + { + if (pInstance) + if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) + if (pThaddius->AI()) + pThaddius->AI()->DoAction(ACTION_FEUGEN_RESET); + staticFieldTimer = 5000; + } + + void EnterCombat(Unit * /*pWho*/) + { + DoCast(SPELL_FEUGEN_TESLA); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) + if (pThaddius->AI()) + pThaddius->AI()->DoAction(ACTION_FEUGEN_DIED); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (staticFieldTimer <= uiDiff) + { + DoCast(me, RAID_MODE(SPELL_STATICFIELD, H_SPELL_STATICFIELD)); + staticFieldTimer = 5000; + } else staticFieldTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_feugen(Creature* pCreature) +{ + return new mob_feugenAI(pCreature); +} + +void AddSC_boss_thaddius() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_thaddius"; + newscript->GetAI = &GetAI_boss_thaddius; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stalagg"; + newscript->GetAI = &GetAI_mob_stalagg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_feugen"; + newscript->GetAI = &GetAI_mob_feugen; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp new file mode 100644 index 00000000000..706789a73f1 --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -0,0 +1,324 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "naxxramas.h" + +const DoorData doorData[] = +{ + {181126, BOSS_ANUBREKHAN,DOOR_TYPE_ROOM, BOUNDARY_S}, + {181195, BOSS_ANUBREKHAN,DOOR_TYPE_PASSAGE, 0}, + {194022, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0}, + {181209, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0}, + {181209, BOSS_MAEXXNA, DOOR_TYPE_ROOM, BOUNDARY_SW}, + {181200, BOSS_NOTH, DOOR_TYPE_ROOM, BOUNDARY_N}, + {181201, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_E}, + {181202, BOSS_NOTH, DOOR_TYPE_PASSAGE, 0}, + {181202, BOSS_HEIGAN, DOOR_TYPE_ROOM, BOUNDARY_N}, + {181203, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_E}, + {181241, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, 0}, + {181241, BOSS_LOATHEB, DOOR_TYPE_ROOM, BOUNDARY_W}, + {181123, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE, 0}, + {181123, BOSS_GROBBULUS, DOOR_TYPE_ROOM, 0}, + {181120, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NW}, + {181121, BOSS_GLUTH, DOOR_TYPE_PASSAGE, 0}, + {181121, BOSS_THADDIUS, DOOR_TYPE_ROOM, 0}, + {181124, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE, 0}, + {181124, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_N}, + {181125, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_S}, + {181119, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, 0}, + {181119, BOSS_HORSEMEN, DOOR_TYPE_ROOM, BOUNDARY_NE}, + {181225, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE, BOUNDARY_W}, + {181228, BOSS_KELTHUZAD, DOOR_TYPE_ROOM, BOUNDARY_S}, + {0, 0, DOOR_TYPE_ROOM, 0}, // EOF +}; + +const MinionData minionData[] = +{ + //{16573, BOSS_ANUBREKHAN}, there is no spawn point in db, so we do not add them here + {16506, BOSS_FAERLINA}, + {16803, BOSS_RAZUVIOUS}, + {16063, BOSS_HORSEMEN}, + {16064, BOSS_HORSEMEN}, + {16065, BOSS_HORSEMEN}, + {30549, BOSS_HORSEMEN}, + {0, 0,} +}; + +enum eEnums +{ + GO_HORSEMEN_CHEST_HERO = 193426, + GO_HORSEMEN_CHEST = 181366, //four horsemen event, DoRespawnGameObject() when event == DONE + GO_GOTHIK_GATE = 181170, + GO_KELTHUZAD_PORTAL01 = 181402, + GO_KELTHUZAD_PORTAL02 = 181403, + GO_KELTHUZAD_PORTAL03 = 181404, + GO_KELTHUZAD_PORTAL04 = 181405, + GO_KELTHUZAD_TRIGGER = 181444, + + SPELL_ERUPTION = 29371 +}; + +const float HeiganPos[2] = {2796, -3707}; +const float HeiganEruptionSlope[3] = +{ + (-3685 - HeiganPos[1]) /(2724 - HeiganPos[0]), + (-3647 - HeiganPos[1]) /(2749 - HeiganPos[0]), + (-3637 - HeiganPos[1]) /(2771 - HeiganPos[0]), +}; + +// 0 H x +// 1 ^ +// 2 | +// 3 y<--o +inline uint32 GetEruptionSection(float x, float y) +{ + y -= HeiganPos[1]; + if (y < 1.0f) + return 0; + + x -= HeiganPos[0]; + if (x > -1.0f) + return 3; + + float slope = y/x; + for (uint32 i = 0; i < 3; ++i) + if (slope > HeiganEruptionSlope[i]) + return i; + return 3; +} + +struct instance_naxxramas : public InstanceData +{ + instance_naxxramas(Map* pMap) : InstanceData(pMap) + { + SetBossNumber(MAX_BOSS_NUMBER); + LoadDoorData(doorData); + LoadMinionData(minionData); + } + + std::set HeiganEruptionGUID[4]; + uint64 GothikGateGUID; + uint64 HorsemenChestGUID; + uint64 SapphironGUID; + uint64 uiFaerlina; + uint64 uiThane; + uint64 uiLady; + uint64 uiBaron; + uint64 uiSir; + + uint64 uiThaddius; + uint64 uiFeugen; + uint64 uiStalagg; + + uint64 uiKelthuzad; + uint64 uiKelthuzadTrigger; + uint64 uiPortals[4]; + + time_t minHorsemenDiedTime; + time_t maxHorsemenDiedTime; + + void OnCreatureCreate(Creature* pCreature, bool add) + { + switch(pCreature->GetEntry()) + { + case 15989: SapphironGUID = add ? pCreature->GetGUID() : 0; return; + case 15953: uiFaerlina = pCreature->GetGUID(); return; + case 16064: uiThane = pCreature->GetGUID(); return; + case 16065: uiLady = pCreature->GetGUID(); return; + case 30549: uiBaron = pCreature->GetGUID(); return; + case 16063: uiSir = pCreature->GetGUID(); return; + case 15928: uiThaddius = pCreature->GetGUID(); return; + case 15930: uiFeugen = pCreature->GetGUID(); return; + case 15929: uiStalagg = pCreature->GetGUID(); return; + case 15990: uiKelthuzad = pCreature->GetGUID(); return; + } + + AddMinion(pCreature, add); + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (pGo->GetGOInfo()->displayId == 6785 || pGo->GetGOInfo()->displayId == 1287) + { + uint32 section = GetEruptionSection(pGo->GetPositionX(), pGo->GetPositionY()); + if (add) + HeiganEruptionGUID[section].insert(pGo->GetGUID()); + else + HeiganEruptionGUID[section].erase(pGo->GetGUID()); + return; + } + + switch(pGo->GetEntry()) + { + case GO_BIRTH: + if (!add && SapphironGUID) + { + if (Creature *pSapphiron = instance->GetCreature(SapphironGUID)) + pSapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH); + return; + } + case GO_GOTHIK_GATE: GothikGateGUID = add ? pGo->GetGUID() : 0; break; + case GO_HORSEMEN_CHEST: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break; + case GO_HORSEMEN_CHEST_HERO: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break; + case GO_KELTHUZAD_PORTAL01: uiPortals[0] = pGo->GetGUID(); break; + case GO_KELTHUZAD_PORTAL02: uiPortals[1] = pGo->GetGUID(); break; + case GO_KELTHUZAD_PORTAL03: uiPortals[2] = pGo->GetGUID(); break; + case GO_KELTHUZAD_PORTAL04: uiPortals[3] = pGo->GetGUID(); break; + case GO_KELTHUZAD_TRIGGER: uiKelthuzadTrigger = pGo->GetGUID(); break; + } + + AddDoor(pGo, add); + } + + void SetData(uint32 id, uint32 value) + { + switch(id) + { + case DATA_HEIGAN_ERUPT: + HeiganErupt(value); + break; + case DATA_GOTHIK_GATE: + if (GameObject *pGothikGate = instance->GetGameObject(GothikGateGUID)) + pGothikGate->SetGoState(GOState(value)); + break; + + case DATA_HORSEMEN0: + case DATA_HORSEMEN1: + case DATA_HORSEMEN2: + case DATA_HORSEMEN3: + if (value == NOT_STARTED) + { + minHorsemenDiedTime = 0; + maxHorsemenDiedTime = 0; + } + else if (value == DONE) + { + time_t now = time(NULL); + + if (minHorsemenDiedTime == 0) + minHorsemenDiedTime = now; + + maxHorsemenDiedTime = now; + } + break; + } + } + + uint64 GetData64(uint32 id) + { + switch(id) + { + case DATA_FAERLINA: + return uiFaerlina; + case DATA_THANE: + return uiThane; + case DATA_LADY: + return uiLady; + case DATA_BARON: + return uiBaron; + case DATA_SIR: + return uiSir; + case DATA_THADDIUS: + return uiThaddius; + case DATA_FEUGEN: + return uiFeugen; + case DATA_STALAGG: + return uiStalagg; + case DATA_KELTHUZAD: + return uiKelthuzad; + case DATA_KELTHUZAD_PORTAL01: + return uiPortals[0]; + case DATA_KELTHUZAD_PORTAL02: + return uiPortals[1]; + case DATA_KELTHUZAD_PORTAL03: + return uiPortals[2]; + case DATA_KELTHUZAD_PORTAL04: + return uiPortals[3]; + case DATA_KELTHUZAD_TRIGGER: + return uiKelthuzadTrigger; + } + return 0; + } + + bool SetBossState(uint32 id, EncounterState state) + { + if (!InstanceData::SetBossState(id, state)) + return false; + + if (id == BOSS_HORSEMEN && state == DONE) + { + if (GameObject *pHorsemenChest = instance->GetGameObject(HorsemenChestGUID)) + pHorsemenChest->SetRespawnTime(pHorsemenChest->GetRespawnDelay()); + } + + return true; + } + + void HeiganErupt(uint32 section) + { + for (uint32 i = 0; i < 4; ++i) + { + if (i == section) + continue; + + for (std::set::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr) + { + if (GameObject *pHeiganEruption = instance->GetGameObject(*itr)) + { + pHeiganEruption->SendCustomAnim(); + pHeiganEruption->CastSpell(NULL, SPELL_ERUPTION); + } + } + } + } + + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/) + { + switch(criteria_id) + { + case 7600: // Criteria for achievement 2176: And They Would All Go Down Together 15sec of each other 10-man + if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) + return true; + return false; + case 7601: // Criteria for achievement 2177: And They Would All Go Down Together 15sec of each other 25-man + if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) + return true; + return false; + case 13233: // Criteria for achievement 2186: The Immortal (25-man) + // TODO. + break; + case 13237: // Criteria for achievement 2187: The Undying (10-man) + // TODO. + break; + } + return false; + } +}; + +InstanceData* GetInstanceData_instance_naxxramas(Map* pMap) +{ + return new instance_naxxramas(pMap); +} + +void AddSC_instance_naxxramas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_naxxramas"; + newscript->GetInstanceData = &GetInstanceData_instance_naxxramas; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h new file mode 100644 index 00000000000..9b1fac2ff5b --- /dev/null +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008 - 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_NAXXRAMAS_H +#define DEF_NAXXRAMAS_H + +enum Encounter +{ + BOSS_ANUBREKHAN, + BOSS_FAERLINA, + BOSS_MAEXXNA, + BOSS_NOTH, + BOSS_HEIGAN, + BOSS_LOATHEB, + BOSS_PATCHWERK, + BOSS_GROBBULUS, + BOSS_GLUTH, + BOSS_THADDIUS, + BOSS_RAZUVIOUS, + BOSS_GOTHIK, + BOSS_HORSEMEN, + BOSS_SAPPHIRON, + BOSS_KELTHUZAD, + MAX_BOSS_NUMBER +}; + +enum Data +{ + DATA_HEIGAN_ERUPT, + DATA_GOTHIK_GATE, + DATA_SAPPHIRON_BIRTH, + + DATA_HORSEMEN0, + DATA_HORSEMEN1, + DATA_HORSEMEN2, + DATA_HORSEMEN3, +}; + +enum Data64 +{ + DATA_FAERLINA, + DATA_THANE, + DATA_LADY, + DATA_BARON, + DATA_SIR, + DATA_THADDIUS, + DATA_FEUGEN, + DATA_STALAGG, + DATA_KELTHUZAD, + DATA_KELTHUZAD_PORTAL01, + DATA_KELTHUZAD_PORTAL02, + DATA_KELTHUZAD_PORTAL03, + DATA_KELTHUZAD_PORTAL04, + DATA_KELTHUZAD_TRIGGER, +}; + +#define GO_BIRTH 181356 + +#endif + diff --git a/src/server/scripts/Northrend/ObsidianSanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/ObsidianSanctum/boss_sartharion.cpp new file mode 100644 index 00000000000..3e24aaeb6c0 --- /dev/null +++ b/src/server/scripts/Northrend/ObsidianSanctum/boss_sartharion.cpp @@ -0,0 +1,1421 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "obsidian_sanctum.h" + +enum eEnums +{ + //Sartharion Yell + SAY_SARTHARION_AGGRO = -1615018, + SAY_SARTHARION_BERSERK = -1615019, + SAY_SARTHARION_BREATH = -1615020, + SAY_SARTHARION_CALL_SHADRON = -1615021, + SAY_SARTHARION_CALL_TENEBRON = -1615022, + SAY_SARTHARION_CALL_VESPERON = -1615023, + SAY_SARTHARION_DEATH = -1615024, + SAY_SARTHARION_SPECIAL_1 = -1615025, + SAY_SARTHARION_SPECIAL_2 = -1615026, + SAY_SARTHARION_SPECIAL_3 = -1615027, + SAY_SARTHARION_SPECIAL_4 = -1615028, + SAY_SARTHARION_SLAY_1 = -1615029, + SAY_SARTHARION_SLAY_2 = -1615030, + SAY_SARTHARION_SLAY_3 = -1615031, + + WHISPER_LAVA_CHURN = -1615032, + + WHISPER_SHADRON_DICIPLE = -1615008, + WHISPER_VESPERON_DICIPLE = -1615041, + WHISPER_HATCH_EGGS = -1615017, + WHISPER_OPEN_PORTAL = -1615042, // whisper, shared by two dragons + + //Sartharion Spells + SPELL_BERSERK = 61632, // Increases the caster's attack speed by 150% and all damage it deals by 500% for 5 min. + SPELL_CLEAVE = 56909, // Inflicts 35% weapon damage to an enemy and its nearest allies, affecting up to 10 targets. + SPELL_FLAME_BREATH = 56908, // Inflicts 8750 to 11250 Fire damage to enemies in a cone in front of the caster. + SPELL_FLAME_BREATH_H = 58956, // Inflicts 10938 to 14062 Fire damage to enemies in a cone in front of the caster. + SPELL_TAIL_LASH = 56910, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec. + SPELL_TAIL_LASH_H = 58957, // A sweeping tail strike hits all enemies behind the caster, inflicting 4375 to 5625 damage and stunning them for 2 sec. + SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%. + SPELL_LAVA_STRIKE = 57571, // (Real spell casted should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572) + SPELL_TWILIGHT_REVENGE = 60639, + + SPELL_PYROBUFFET = 56916, // currently used for hard enrage after 15 minutes + SPELL_PYROBUFFET_RANGE = 58907, // possibly used when player get too far away from dummy creatures (2x Creature entry 30494) + + SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO + SPELL_TWILIGHT_SHIFT = 57874, // Twilight Shift Aura + SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase + SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave) + + //Mini bosses common spells + SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase + + //Miniboses (Vesperon, Shadron, Tenebron) + SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster. + SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster. + + SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec. + SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec. + + //Vesperon + //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times + NPC_ACOLYTE_OF_VESPERON = 31219, // Acolyte of Vesperon + SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%. + SPELL_TWILIGHT_TORMENT_VESP = 57948, // (Shadow only) trigger 57935 then 57988 + SPELL_TWILIGHT_TORMENT_VESP_ACO = 58853, // (Fire and Shadow) trigger 58835 then 57988 + + //Shadron + //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times + NPC_ACOLYTE_OF_SHADRON = 31218, // Acolyte of Shadron + SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%. + SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron + SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion + SPELL_VOID_BLAST = 57581, // Twilight Fissure + SPELL_VOID_BLAST_H = 59128, + + //Tenebron + //in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708 + SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%. + //Tenebron, dummy spell + SPELL_SUMMON_TWILIGHT_WHELP = 58035, // doesn't work, will spawn NPC_TWILIGHT_WHELP + SPELL_SUMMON_SARTHARION_TWILIGHT_WHELP = 58826, // doesn't work, will spawn NPC_SHARTHARION_TWILIGHT_WHELP + + SPELL_HATCH_EGGS_H = 59189, + SPELL_HATCH_EGGS = 58542, + SPELL_HATCH_EGGS_EFFECT_H = 59190, + SPELL_HATCH_EGGS_EFFECT = 58685, + NPC_TWILIHT_WHELP = 31214, + NPC_TWILIGHT_EGG = 30882, + + //Whelps + NPC_TWILIGHT_WHELP = 30890, + NPC_SHARTHARION_TWILIGHT_WHELP = 31214, + SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s + + //flame tsunami + SPELL_FLAME_TSUNAMI = 57494, // the visual dummy + SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction + SPELL_FLAME_TSUNAMI_DMG_AURA = 57492, // periodic damage, npc has this aura + + NPC_FLAME_TSUNAMI = 30616, // for the flame waves + NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike + + //using these custom points for dragons start and end + POINT_ID_INIT = 100, + POINT_ID_LAND = 200, + + //Achievements + ACHIEV_TWILIGHT_ASSIST = 2049, + H_ACHIEV_TWILIGHT_ASSIST = 2052, + ACHIEV_TWILIGHT_DUO = 2050, + H_ACHIEV_TWILIGHT_DUO = 2053, + ACHIEV_TWILIGHT_ZONE = 2051, + H_ACHIEV_TWILIGHT_ZONE = 2054 +}; + +struct Waypoint +{ + float m_fX, m_fY, m_fZ; +}; +struct Location +{ + float x,y,z; +}; +struct Locations +{ + float x,y,z; +}; + +//each dragons special points. First where fly to before connect to connon, second where land point is. +Waypoint m_aTene[]= +{ + {3212.854, 575.597, 109.856}, //init + {3246.425, 565.367, 61.249} //end +}; + +Waypoint m_aShad[]= +{ + {3293.238, 472.223, 106.968}, + {3271.669, 526.907, 61.931} +}; + +Waypoint m_aVesp[]= +{ + {3193.310, 472.861, 102.697}, + {3227.268, 533.238, 59.995} +}; + +#define MAX_WAYPOINT 6 +//points around raid "isle", counter clockwise. should probably be adjusted to be more alike +Waypoint m_aDragonCommon[MAX_WAYPOINT]= +{ + {3214.012, 468.932, 98.652}, + {3244.950, 468.427, 98.652}, + {3283.520, 496.869, 98.652}, + {3287.316, 555.875, 98.652}, + {3250.479, 585.827, 98.652}, + {3209.969, 566.523, 98.652} +}; +static Location FlameRight1Spawn = { 3197.59, 495.336, 57.8462 }; +static Location FlameRight1Direction = { 3289.28, 521.569, 55.1526 }; +static Location FlameRight2Spawn = { 3201.94, 543.324, 56.7209 }; +static Location FlameRight2Direction = { 3288.98, 549.291, 55.1232 }; +static Location FlameLeft1Spawn = { 3290.24, 521.725, 55.1238 }; +static Location FlameLeft1Direction = { 3199.94, 516.891, 57.5112 }; +static Location FlameLeft2Spawn = { 3290.33, 586.51, 55.063 }; +static Location FlameLeft2Direction = { 3195.03, 479.135, 55.6331 }; + +static Location AcolyteofShadron = { 3363.92, 534.703, 97.2683 }; +static Location AcolyteofShadron2 = { 3246.57, 551.263, 58.6164 }; +static Location AcolyteofVesperon = { 3145.68, 520.71, 89.7 }; +static Location AcolyteofVesperon2 = { 3246.57, 551.263, 58.6164 }; + +Locations TwilightEggs[] = +{ + {3219.28, 669.121 , 88.5549}, + {3221.55, 682.852 , 90.5361}, + {3239.77, 685.94 , 90.3168}, + {3250.33, 669.749 , 88.7637}, + {3246.6, 642.365 , 84.8752}, + {3233.68, 653.117 , 85.7051} +}; +Locations TwilightEggsSarth[] = +{ + {3261.75, 539.14 , 58.6082}, + {3257.41, 512.939 , 58.5432}, + {3231.04, 498.281 , 58.6439} +}; + +/*###### +## Boss Sartharion +######*/ + +struct boss_sartharionAI : public ScriptedAI +{ + boss_sartharionAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool m_bIsBerserk; + bool m_bIsSoftEnraged; + + uint32 m_uiEnrageTimer; + bool m_bIsHardEnraged; + + uint32 m_uiTenebronTimer; + uint32 m_uiShadronTimer; + uint32 m_uiVesperonTimer; + + uint32 m_uiFlameTsunamiTimer; + uint32 m_uiFlameBreathTimer; + uint32 m_uiTailSweepTimer; + uint32 m_uiCleaveTimer; + uint32 m_uiLavaStrikeTimer; + + bool m_bHasCalledTenebron; + bool m_bHasCalledShadron; + bool m_bHasCalledVesperon; + + uint32 achievProgress; + + void Reset() + { + m_bIsBerserk = false; + m_bIsSoftEnraged = false; + + m_uiEnrageTimer = 15*MINUTE*IN_MILISECONDS; + m_bIsHardEnraged = false; + + m_uiTenebronTimer = 30000; + m_uiShadronTimer = 75000; + m_uiVesperonTimer = 120000; + + m_uiFlameTsunamiTimer = 30000; + m_uiFlameBreathTimer = 20000; + m_uiTailSweepTimer = 20000; + m_uiCleaveTimer = 7000; + m_uiLavaStrikeTimer = 5000; + + m_bHasCalledTenebron = false; + m_bHasCalledShadron = false; + m_bHasCalledVesperon = false; + + if (me->HasAura(SPELL_TWILIGHT_REVENGE)) + me->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE); + + me->ResetLootMode(); + + achievProgress = 0; + } + + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(TYPE_SARTHARION_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_SARTHARION_AGGRO,me); + DoZoneInCombat(); + + if (pInstance) + { + pInstance->SetData(TYPE_SARTHARION_EVENT, IN_PROGRESS); + FetchDragons(); + } + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_SARTHARION_DEATH,me); + + if (pInstance) + { + if (achievProgress >= 1) + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_ASSIST,H_ACHIEV_TWILIGHT_ASSIST)); + else if (achievProgress >= 2) + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_DUO,H_ACHIEV_TWILIGHT_DUO)); + else if (achievProgress == 3) + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_ZONE,H_ACHIEV_TWILIGHT_ZONE)); + + pInstance->SetData(TYPE_SARTHARION_EVENT, DONE); + } + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SARTHARION_SLAY_1,SAY_SARTHARION_SLAY_2,SAY_SARTHARION_SLAY_3), me); + } + + // me->ResetLootMode() is called from Reset() + // AddDrakeLootMode() should only ever be called from FetchDragons(), which is called from Aggro() + void AddDrakeLootMode() + { + if (me->HasLootMode(LOOT_MODE_HARD_MODE_2)) // Has two Drake loot modes + me->AddLootMode(LOOT_MODE_HARD_MODE_3); // Add 3rd Drake loot mode + else if (me->HasLootMode(LOOT_MODE_HARD_MODE_1)) // Has one Drake loot mode + me->AddLootMode(LOOT_MODE_HARD_MODE_2); // Add 2nd Drake loot mode + else // Has no Drake loot modes + me->AddLootMode(LOOT_MODE_HARD_MODE_1); // Add 1st Drake loot mode + } + + void FetchDragons() + { + if (!pInstance) + return; + Creature* pFetchTene = Unit::GetCreature(*me, pInstance->GetData64(DATA_TENEBRON)); + Creature* pFetchShad = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON)); + Creature* pFetchVesp = Unit::GetCreature(*me, pInstance->GetData64(DATA_VESPERON)); + + //if at least one of the dragons are alive and are being called + bool bCanUseWill = false; + + if (pFetchTene && pFetchTene->isAlive() && !pFetchTene->getVictim()) + { + bCanUseWill = true; + pFetchTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ); + + if (!pFetchTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pFetchTene->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + if (pFetchShad && pFetchShad->isAlive() && !pFetchShad->getVictim()) + { + bCanUseWill = true; + pFetchShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ); + + if (!pFetchShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pFetchShad->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + if (pFetchVesp && pFetchVesp->isAlive() && !pFetchVesp->getVictim()) + { + bCanUseWill = true; + pFetchVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ); + + if (!pFetchVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pFetchVesp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + if (bCanUseWill) + DoCast(me, SPELL_WILL_OF_SARTHARION); + } + + void CallDragon(uint32 uiDataId) + { + if (pInstance) + { + if (Creature *pTemp = Unit::GetCreature(*me,pInstance->GetData64(uiDataId))) + { + if (pTemp->isAlive() && !pTemp->getVictim()) + { + if (pTemp->HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE)) + pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + if (pTemp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + int32 iTextId = 0; + AddDrakeLootMode(); + + achievProgress++; + + switch(pTemp->GetEntry()) + { + case NPC_TENEBRON: + iTextId = SAY_SARTHARION_CALL_TENEBRON; + pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aTene[1].m_fX, m_aTene[1].m_fY, m_aTene[1].m_fZ); + break; + case NPC_SHADRON: + iTextId = SAY_SARTHARION_CALL_SHADRON; + pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aShad[1].m_fX, m_aShad[1].m_fY, m_aShad[1].m_fZ); + break; + case NPC_VESPERON: + iTextId = SAY_SARTHARION_CALL_VESPERON; + pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aVesp[1].m_fX, m_aVesp[1].m_fY, m_aVesp[1].m_fZ); + break; + } + + DoScriptText(iTextId, me); + } + } + } + } + + void SendFlameTsunami() + { + if (Map* pMap = me->GetMap()) + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource() && i->getSource()->isAlive()) + DoScriptText(WHISPER_LAVA_CHURN, me, i->getSource()); + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + Unit* pTene = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_TENEBRON) : 0); + Unit* pShad = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SHADRON) : 0); + Unit* pVesp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_VESPERON) : 0); + + //spell will target dragons, if they are still alive at 35% + if (!m_bIsBerserk && (me->GetHealth()*100 / me->GetMaxHealth()) <= 35 + && ((pTene && pTene->isAlive()) || (pShad && pShad->isAlive()) || (pVesp && pVesp->isAlive()))) + { + DoScriptText(SAY_SARTHARION_BERSERK, me); + DoCast(me, SPELL_BERSERK); + m_bIsBerserk = true; + } + + //soft enrage + if (!m_bIsSoftEnraged && (me->GetHealth()*100 / me->GetMaxHealth()) <= 10) + { + // TODO + m_bIsSoftEnraged = true; + } + + // hard enrage + if (!m_bIsHardEnraged) + { + if (m_uiEnrageTimer <= uiDiff) + { + DoCast(me, SPELL_PYROBUFFET, true); + m_bIsHardEnraged = true; + } + else + m_uiEnrageTimer -= uiDiff; + } + + // flame tsunami + if (m_uiFlameTsunamiTimer <= uiDiff) + { + SendFlameTsunami(); + switch(urand(0,1)) + { + case 0: + { + if (Creature *Right1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight1Spawn.x, FlameRight1Spawn.y , FlameRight1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) + Right1->GetMotionMaster()->MovePoint(0, FlameRight1Direction.x, FlameRight1Direction.y, FlameRight1Direction.z); + if (Creature *Right2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight2Spawn.x, FlameRight2Spawn.y , FlameRight2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) + Right2->GetMotionMaster()->MovePoint(0, FlameRight2Direction.x, FlameRight2Direction.y, FlameRight2Direction.z); + break; + } + case 1: + { + if (Creature *Left1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft1Spawn.x, FlameLeft1Spawn.y , FlameLeft1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) + Left1->GetMotionMaster()->MovePoint(0, FlameLeft1Direction.x, FlameLeft1Direction.y, FlameLeft1Direction.z); + if (Creature *Left2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft2Spawn.x, FlameLeft2Spawn.y , FlameLeft2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) + Left2->GetMotionMaster()->MovePoint(0, FlameLeft2Direction.x, FlameLeft2Direction.y, FlameLeft2Direction.z); + break; + } + } + + m_uiFlameTsunamiTimer = 30000; + } + else + m_uiFlameTsunamiTimer -= uiDiff; + + // flame breath + if (m_uiFlameBreathTimer <= uiDiff) + { + DoScriptText(SAY_SARTHARION_BREATH, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_FLAME_BREATH, SPELL_FLAME_BREATH_H)); + m_uiFlameBreathTimer = urand(25000,35000); + } + else + m_uiFlameBreathTimer -= uiDiff; + + // Tail Sweep + if (m_uiTailSweepTimer <= uiDiff) + { + DoCast(me->getVictim(), RAID_MODE(SPELL_TAIL_LASH, SPELL_TAIL_LASH_H)); + m_uiTailSweepTimer = urand(15000,20000); + } + else + m_uiTailSweepTimer -= uiDiff; + + // Cleave + if (m_uiCleaveTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + m_uiCleaveTimer = urand(7000,10000); + } + else + m_uiCleaveTimer -= uiDiff; + + // Lavas Strike + if (m_uiLavaStrikeTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_LAVA_STRIKE); + + if (urand(0,4) == 4) + DoScriptText(RAND(SAY_SARTHARION_SPECIAL_1,SAY_SARTHARION_SPECIAL_2,SAY_SARTHARION_SPECIAL_3), me); + } + m_uiLavaStrikeTimer = urand(5000,20000); + } + else + m_uiLavaStrikeTimer -= uiDiff; + + // call tenebron + if (!m_bHasCalledTenebron && m_uiTenebronTimer <= uiDiff) + { + CallDragon(DATA_TENEBRON); + m_bHasCalledTenebron = true; + } + else + m_uiTenebronTimer -= uiDiff; + + // call shadron + if (!m_bHasCalledShadron && m_uiShadronTimer <= uiDiff) + { + CallDragon(DATA_SHADRON); + m_bHasCalledShadron = true; + } + else + m_uiShadronTimer -= uiDiff; + + // call vesperon + if (!m_bHasCalledVesperon && m_uiVesperonTimer <= uiDiff) + { + CallDragon(DATA_VESPERON); + m_bHasCalledVesperon = true; + } + else + m_uiVesperonTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(uiDiff); + } +}; + +CreatureAI* GetAI_boss_sartharion(Creature* pCreature) +{ + return new boss_sartharionAI(pCreature); +} + +enum TeneText +{ + SAY_TENEBRON_AGGRO = -1615009, + SAY_TENEBRON_SLAY_1 = -1615010, + SAY_TENEBRON_SLAY_2 = -1615011, + SAY_TENEBRON_DEATH = -1615012, + SAY_TENEBRON_BREATH = -1615013, + SAY_TENEBRON_RESPOND = -1615014, + SAY_TENEBRON_SPECIAL_1 = -1615015, + SAY_TENEBRON_SPECIAL_2 = -1615016 +}; + +enum ShadText +{ + SAY_SHADRON_AGGRO = -1615000, + SAY_SHADRON_SLAY_1 = -1615001, + SAY_SHADRON_SLAY_2 = -1615002, + SAY_SHADRON_DEATH = -1615003, + SAY_SHADRON_BREATH = -1615004, + SAY_SHADRON_RESPOND = -1615005, + SAY_SHADRON_SPECIAL_1 = -1615006, + SAY_SHADRON_SPECIAL_2 = -1615007 +}; + +enum VespText +{ + SAY_VESPERON_AGGRO = -1615033, + SAY_VESPERON_SLAY_1 = -1615034, + SAY_VESPERON_SLAY_2 = -1615035, + SAY_VESPERON_DEATH = -1615036, + SAY_VESPERON_BREATH = -1615037, + SAY_VESPERON_RESPOND = -1615038, + SAY_VESPERON_SPECIAL_1 = -1615039, + SAY_VESPERON_SPECIAL_2 = -1615040 +}; + +//to control each dragons common abilities +struct dummy_dragonAI : public ScriptedAI +{ + dummy_dragonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 m_uiWaypointId; + uint32 m_uiMoveNextTimer; + int32 m_iPortalRespawnTime; + bool m_bCanMoveFree; + + void Reset() + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (GameObject* TwilightPortal = GameObject::GetGameObject((*me), pInstance->GetData64(GO_TWILIGHT_PORTAL))) + TwilightPortal->SetGoState(GO_STATE_READY); + + m_uiWaypointId = 0; + m_uiMoveNextTimer = 500; + m_iPortalRespawnTime = 30000; + m_bCanMoveFree = false; + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (!pInstance || uiType != POINT_MOTION_TYPE) + return; + + debug_log("dummy_dragonAI: %s reached point %u", me->GetName(), uiPointId); + + //if healers messed up the raid and we was already initialized + if (pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + { + EnterEvadeMode(); + return; + } + + //this is end, if we reach this, don't do much + if (uiPointId == POINT_ID_LAND) + { + me->GetMotionMaster()->Clear(); + m_bCanMoveFree = false; + return; + } + + //get amount of common points + uint32 uiCommonWPCount = sizeof(m_aDragonCommon)/sizeof(Waypoint); + + //increase + m_uiWaypointId = uiPointId+1; + + //if we have reached a point bigger or equal to count, it mean we must reset to point 0 + if (m_uiWaypointId >= uiCommonWPCount) + { + if (!m_bCanMoveFree) + m_bCanMoveFree = true; + + m_uiWaypointId = 0; + } + + m_uiMoveNextTimer = 500; + } + + //used when open portal and spawn mobs in phase + void DoRaidWhisper(int32 iTextId) + { + Map* pMap = me->GetMap(); + + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + DoScriptText(iTextId, me, i->getSource()); + } + } + } + + //"opens" the portal and does the "opening" whisper + void OpenPortal() + { + int32 iTextId = 0; + + //there are 4 portal spawn locations, each are expected to be spawned with negative spawntimesecs in database + + //using a grid search here seem to be more efficient than caching all four guids + //in instance script and calculate range to each. + GameObject* pPortal = me->FindNearestGameObject(GO_TWILIGHT_PORTAL,50.0f); + if (GameObject* TwilightPortal = GameObject::GetGameObject((*me), pInstance->GetData64(GO_TWILIGHT_PORTAL))) + TwilightPortal->SetGoState(GO_STATE_ACTIVE); + + switch(me->GetEntry()) + { + case NPC_TENEBRON: + { + iTextId = WHISPER_HATCH_EGGS; + if (pInstance && pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[0].x, TwilightEggs[0].y, TwilightEggs[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + else + me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggsSarth[0].x, TwilightEggsSarth[0].y, TwilightEggsSarth[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + break; + } + case NPC_SHADRON: + { + iTextId = WHISPER_OPEN_PORTAL; + if (pInstance && !pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron.x, AcolyteofShadron.y , AcolyteofShadron.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + else + me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2.x, AcolyteofShadron2.y , AcolyteofShadron2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + + break; + } + case NPC_VESPERON: + { + if (pInstance && !pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon.x, AcolyteofVesperon.y , AcolyteofVesperon.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + else + me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon2.x, AcolyteofVesperon2.y , AcolyteofVesperon2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); + + iTextId = WHISPER_OPEN_PORTAL; + break; + } + } + + DoRaidWhisper(iTextId); + + //By using SetRespawnTime() we will actually "spawn" the object with our defined time. + //Once time is up, portal will disappear again. + if (pPortal && !pPortal->isSpawned()) + pPortal->SetRespawnTime(m_iPortalRespawnTime); + + //Unclear what are expected to happen if one drake has a portal open already + //Refresh respawnTime so time again are set to 30secs? + } + + void JustDied(Unit* /*pKiller*/) + { + int32 iTextId = 0; + uint32 uiSpellId = 0; + + switch(me->GetEntry()) + { + case NPC_TENEBRON: + iTextId = SAY_TENEBRON_DEATH; + uiSpellId = SPELL_POWER_OF_TENEBRON; + break; + case NPC_SHADRON: + iTextId = SAY_SHADRON_DEATH; + uiSpellId = SPELL_POWER_OF_SHADRON; + break; + case NPC_VESPERON: + iTextId = SAY_VESPERON_DEATH; + uiSpellId = SPELL_POWER_OF_VESPERON; + break; + } + + DoScriptText(iTextId, me); + + me->RemoveOwnedAura(uiSpellId); + + if (pInstance) + { + // not if solo mini-boss fight + if (pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + return; + + // Twilight Revenge to main boss + if (Unit* pSartharion = Unit::GetUnit((*me), pInstance->GetData64(DATA_SARTHARION))) + if (pSartharion->isAlive()) + DoCast(pSartharion, SPELL_TWILIGHT_REVENGE, true); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_bCanMoveFree && m_uiMoveNextTimer) + { + if (m_uiMoveNextTimer <= uiDiff) + { + if (m_uiWaypointId < MAX_WAYPOINT) + me->GetMotionMaster()->MovePoint(m_uiWaypointId, + m_aDragonCommon[m_uiWaypointId].m_fX, m_aDragonCommon[m_uiWaypointId].m_fY, m_aDragonCommon[m_uiWaypointId].m_fZ); + + debug_log("dummy_dragonAI: %s moving to point %u", me->GetName(), m_uiWaypointId); + m_uiMoveNextTimer = 0; + } + else + m_uiMoveNextTimer -= uiDiff; + } + } +}; + +/*###### +## Mob Tenebron +######*/ + +struct mob_tenebronAI : public dummy_dragonAI +{ + mob_tenebronAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} + + uint32 m_uiShadowBreathTimer; + uint32 m_uiShadowFissureTimer; + uint32 m_uiHatchEggTimer; + + void Reset() + { + m_uiShadowBreathTimer = 20000; + m_uiShadowFissureTimer = 5000; + m_uiHatchEggTimer = 30000; + } + + void Aggro(Unit* /*pWho*/) + { + DoScriptText(SAY_TENEBRON_AGGRO, me); + DoZoneInCombat(); + DoCast(me, SPELL_POWER_OF_TENEBRON); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_TENEBRON_SLAY_1,SAY_TENEBRON_SLAY_2), me); + /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + achievProgress = 1;*/ + } + + void UpdateAI(const uint32 uiDiff) + { + //if no target, update dummy and return + if (!UpdateVictim()) + { + dummy_dragonAI::UpdateAI(uiDiff); + return; + } + + // shadow fissure + if (m_uiShadowFissureTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE)); + + m_uiShadowFissureTimer = urand(15000,20000); + } + else + m_uiShadowFissureTimer -= uiDiff; + + // Hach Egg + if (m_uiHatchEggTimer <= uiDiff) + { + OpenPortal(); + m_uiHatchEggTimer = 30000; + } + else + m_uiHatchEggTimer -= uiDiff; + + // shadow breath + if (m_uiShadowBreathTimer <= uiDiff) + { + DoScriptText(SAY_TENEBRON_BREATH, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); + m_uiShadowBreathTimer = urand(20000,25000); + } + else + m_uiShadowBreathTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_tenebron(Creature* pCreature) +{ + return new mob_tenebronAI(pCreature); +} + +/*###### +## Mob Shadron +######*/ + +struct mob_shadronAI : public dummy_dragonAI +{ + mob_shadronAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} + + uint32 m_uiShadowBreathTimer; + uint32 m_uiShadowFissureTimer; + uint32 m_uiAcolyteShadronTimer; + + void Reset() + { + m_uiShadowBreathTimer = 20000; + m_uiShadowFissureTimer = 5000; + m_uiAcolyteShadronTimer = 60000; + + if (me->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) + me->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); + + if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) + me->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); + } + + void Aggro(Unit* /*pWho*/) + { + DoScriptText(SAY_SHADRON_AGGRO,me); + DoZoneInCombat(); + DoCast(me, SPELL_POWER_OF_SHADRON); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SHADRON_SLAY_1,SAY_SHADRON_SLAY_2), me); + /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + achievProgress = 2;*/ + } + + void UpdateAI(const uint32 uiDiff) + { + //if no target, update dummy and return + if (!UpdateVictim()) + { + dummy_dragonAI::UpdateAI(uiDiff); + return; + } + + // shadow fissure + if (m_uiShadowFissureTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H)); + + m_uiShadowFissureTimer = urand(15000,20000); + } + else + m_uiShadowFissureTimer -= uiDiff; + + // Portal Event + if (m_uiAcolyteShadronTimer <= uiDiff) + { + if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) + return; + + OpenPortal(); + m_uiAcolyteShadronTimer = urand(60000,65000); + } + else + m_uiAcolyteShadronTimer -= uiDiff; + + // shadow breath + if (m_uiShadowBreathTimer <= uiDiff) + { + DoScriptText(SAY_SHADRON_BREATH, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); + m_uiShadowBreathTimer = urand(20000,25000); + } + else + m_uiShadowBreathTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_shadron(Creature* pCreature) +{ + return new mob_shadronAI(pCreature); +} + +/*###### +## Mob Vesperon +######*/ + +struct mob_vesperonAI : public dummy_dragonAI +{ + mob_vesperonAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} + + uint32 m_uiShadowBreathTimer; + uint32 m_uiShadowFissureTimer; + uint32 m_uiAcolyteVesperonTimer; + + void Reset() + { + m_uiShadowBreathTimer = 20000; + m_uiShadowFissureTimer = 5000; + m_uiAcolyteVesperonTimer = 60000; + } + + void Aggro(Unit* /*pWho*/) + { + DoScriptText(SAY_VESPERON_AGGRO,me); + DoZoneInCombat(); + DoCast(me, SPELL_POWER_OF_VESPERON); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_VESPERON_SLAY_1,SAY_VESPERON_SLAY_2), me); + /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + achievProgress = 3;*/ + } + + void UpdateAI(const uint32 uiDiff) + { + //if no target, update dummy and return + if (!UpdateVictim()) + { + dummy_dragonAI::UpdateAI(uiDiff); + return; + } + + // shadow fissure + if (m_uiShadowFissureTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H)); + + m_uiShadowFissureTimer = urand(15000,20000); + } + else + m_uiShadowFissureTimer -= uiDiff; + + // Portal Event + if (m_uiAcolyteVesperonTimer <= uiDiff) + { + OpenPortal(); + DoCast(me->getVictim(), SPELL_TWILIGHT_TORMENT_VESP); + m_uiAcolyteVesperonTimer = urand(60000,70000); + } + else + m_uiAcolyteVesperonTimer -= uiDiff; + + // shadow breath + if (m_uiShadowBreathTimer <= uiDiff) + { + DoScriptText(SAY_VESPERON_BREATH, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); + m_uiShadowBreathTimer = urand(20000,25000); + } + else + m_uiShadowBreathTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_vesperon(Creature* pCreature) +{ + return new mob_vesperonAI(pCreature); +} + +/*###### +## Mob Acolyte of Shadron +######*/ + +struct mob_acolyte_of_shadronAI : public ScriptedAI +{ + mob_acolyte_of_shadronAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 uiShiftEffectTimer; + + void Reset() + { + uiShiftEffectTimer = 1000; + if (pInstance) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true); + + Creature* pSartharion = Unit::GetCreature(*me, pInstance->GetData64(DATA_SARTHARION)); + if (Creature* pShadron = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON))) + //if not solo figth, buff main boss, else place debuff on mini-boss. both spells TARGET_SCRIPT + if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + pSartharion->CastSpell(me, SPELL_GIFT_OF_TWILIGTH_SAR, true); + else + { + pShadron->CastSpell(me, SPELL_GIFT_OF_TWILIGTH_SHA,true); + pShadron->AddThreat(pTarget, 100.0f); + AttackStart(pShadron->getVictim()); + } + } + me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER,me); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + //Creature* pDebuffTarget = NULL; + Map *map = me->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT,0) && !i->getSource()->getVictim()) + { + i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_SHIFT_REMOVAL_ALL,true); + i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_RESIDUE,true); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); + } + } + } + + if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + { + //not solo fight, so main boss has deduff + Creature* pDebuffTarget = Unit::GetCreature(*me, pInstance->GetData64(DATA_SARTHARION)); + if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SAR)) + pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SAR); + } + else + { + //event not in progress, then solo fight and must remove debuff mini-boss + Creature* pDebuffTarget = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON)); + if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) + pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); + } + } + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_acolyte_of_shadron(Creature* pCreature) +{ + return new mob_acolyte_of_shadronAI(pCreature); +} + +/*###### +## Mob Acolyte of Vesperon +######*/ + +struct mob_acolyte_of_vesperonAI : public ScriptedAI +{ + mob_acolyte_of_vesperonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + { + me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER,me); + } + DoCast(me, SPELL_TWILIGHT_TORMENT_VESP_ACO); + } + + void JustDied(Unit* /*pKiller*/) + { + // remove twilight torment on Vesperon + if (pInstance) + { + Creature* pVesperon = Unit::GetCreature(*me, pInstance->GetData64(DATA_VESPERON)); + + if (pVesperon && pVesperon->isAlive() && pVesperon->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) + pVesperon->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); + + Map *map = me->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT,0) && !i->getSource()->getVictim()) + { + i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_SHIFT_REMOVAL_ALL,true); + i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_RESIDUE,true); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); + } + if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_TORMENT_VESP,0) && !i->getSource()->getVictim()) + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); + } + } + + } + } + + void UpdateAI(const uint32 /*uiDiff*/) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_acolyte_of_vesperon(Creature* pCreature) +{ + return new mob_acolyte_of_vesperonAI(pCreature); +} + +/*###### +## Mob Twilight Eggs +######*/ + +struct mob_twilight_eggsAI : public Scripted_NoMovementAI +{ + mob_twilight_eggsAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + uint32 m_uiFadeArmorTimer; + uint32 m_uiHatchEggTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + m_uiHatchEggTimer = 20000; + m_uiFadeArmorTimer = 1000; + } + void SpawnWhelps() + { + if (!pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + else + me->SummonCreature(NPC_SHARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); + me->DealDamage(me, me->GetHealth()); + } + void UpdateAI(const uint32 uiDiff) + { + if (m_uiHatchEggTimer <= uiDiff) + { + SpawnWhelps(); + } + else + m_uiHatchEggTimer -= uiDiff; + } + void AttackStart(Unit* /*pWho*/) {} + void MoveInLineOfSight(Unit* /*pWho*/) {} +}; + +CreatureAI* GetAI_mob_twilight_eggs(Creature* pCreature) +{ + return new mob_twilight_eggsAI(pCreature); +} + +/*###### +## Flame Tzunami +######*/ +struct npc_flame_tsunamiAI : public ScriptedAI +{ + npc_flame_tsunamiAI(Creature* pCreature) : ScriptedAI(pCreature) + { + me->HasAura(SPELL_FLAME_TSUNAMI_DMG_AURA); + DoCast(me, SPELL_FLAME_TSUNAMI); + } + + uint32 Tsunami_Timer; + + void Reset() + { + Tsunami_Timer = 100; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void UpdateAI(const uint32 diff) + { + if (Tsunami_Timer <= diff) + { + DoCast(me, SPELL_FLAME_TSUNAMI_DMG_AURA); + Tsunami_Timer = 1000; + } else Tsunami_Timer -= diff; + } +}; +// Twilight Fissure +struct npc_twilight_fissureAI : public Scripted_NoMovementAI +{ + npc_twilight_fissureAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + Reset(); + } + + uint32 VoidBlast_Timer; + + void Reset() + { + VoidBlast_Timer = 5000; + } + + void UpdateAI(const uint32 diff) + { + if (VoidBlast_Timer <= diff) + { + DoCast(me->getVictim(), RAID_MODE(SPELL_VOID_BLAST, SPELL_VOID_BLAST_H)); + VoidBlast_Timer = 9000; + me->Kill(me); + } else VoidBlast_Timer -= diff; + } +}; + + +CreatureAI* GetAI_npc_flame_tsunami(Creature* pCreature) +{ + return new npc_flame_tsunamiAI(pCreature); +} + +CreatureAI* GetAI_npc_twilight_fissure(Creature* pCreature) +{ + return new npc_twilight_fissureAI(pCreature); +} + +/*###### +## Mob Twilight Whelps +######*/ + +struct mob_twilight_whelpAI : public ScriptedAI +{ + mob_twilight_whelpAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 m_uiFadeArmorTimer; + + void Reset() + { + m_uiFadeArmorTimer = 1000; + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // twilight torment + if (m_uiFadeArmorTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_FADE_ARMOR); + m_uiFadeArmorTimer = urand(5000,10000); + } + else + m_uiFadeArmorTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_twilight_whelp(Creature* pCreature) +{ + return new mob_twilight_whelpAI(pCreature); +} + +void AddSC_boss_sartharion() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sartharion"; + newscript->GetAI = &GetAI_boss_sartharion; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vesperon"; + newscript->GetAI = &GetAI_mob_vesperon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadron"; + newscript->GetAI = &GetAI_mob_shadron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tenebron"; + newscript->GetAI = &GetAI_mob_tenebron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_acolyte_of_shadron"; + newscript->GetAI = &GetAI_mob_acolyte_of_shadron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_acolyte_of_vesperon"; + newscript->GetAI = &GetAI_mob_acolyte_of_vesperon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_twilight_eggs"; + newscript->GetAI = &GetAI_mob_twilight_eggs; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_flame_tsunami"; + newscript->GetAI = &GetAI_npc_flame_tsunami; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_twilight_fissure"; + newscript->GetAI = &GetAI_npc_twilight_fissure; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_twilight_whelp"; + newscript->GetAI = &GetAI_mob_twilight_whelp; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ObsidianSanctum/instance_obsidian_sanctum.cpp b/src/server/scripts/Northrend/ObsidianSanctum/instance_obsidian_sanctum.cpp new file mode 100644 index 00000000000..7ef8e03c779 --- /dev/null +++ b/src/server/scripts/Northrend/ObsidianSanctum/instance_obsidian_sanctum.cpp @@ -0,0 +1,97 @@ +#include "ScriptedPch.h" +#include "obsidian_sanctum.h" + +#define MAX_ENCOUNTER 1 + +/* Obsidian Sanctum encounters: +0 - Sartharion +*/ + +struct instance_obsidian_sanctum : public ScriptedInstance +{ + instance_obsidian_sanctum(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 m_uiSartharionGUID; + uint64 m_uiTenebronGUID; + uint64 m_uiShadronGUID; + uint64 m_uiVesperonGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiSartharionGUID = 0; + m_uiTenebronGUID = 0; + m_uiShadronGUID = 0; + m_uiVesperonGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_SARTHARION: + m_uiSartharionGUID = pCreature->GetGUID(); + break; + //three dragons below set to active state once created. + //we must expect bigger raid to encounter main boss, and then three dragons must be active due to grid differences + case NPC_TENEBRON: + m_uiTenebronGUID = pCreature->GetGUID(); + pCreature->setActive(true); + break; + case NPC_SHADRON: + m_uiShadronGUID = pCreature->GetGUID(); + pCreature->setActive(true); + break; + case NPC_VESPERON: + m_uiVesperonGUID = pCreature->GetGUID(); + pCreature->setActive(true); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + if (uiType == TYPE_SARTHARION_EVENT) + m_auiEncounter[0] = uiData; + } + + uint32 GetData(uint32 uiType) + { + if (uiType == TYPE_SARTHARION_EVENT) + return m_auiEncounter[0]; + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_SARTHARION: + return m_uiSartharionGUID; + case DATA_TENEBRON: + return m_uiTenebronGUID; + case DATA_SHADRON: + return m_uiShadronGUID; + case DATA_VESPERON: + return m_uiVesperonGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_obsidian_sanctum(Map* pMap) +{ + return new instance_obsidian_sanctum(pMap); +} + +void AddSC_instance_obsidian_sanctum() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_obsidian_sanctum"; + newscript->GetInstanceData = &GetInstanceData_instance_obsidian_sanctum; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/ObsidianSanctum/obsidian_sanctum.h b/src/server/scripts/Northrend/ObsidianSanctum/obsidian_sanctum.h new file mode 100644 index 00000000000..59013174795 --- /dev/null +++ b/src/server/scripts/Northrend/ObsidianSanctum/obsidian_sanctum.h @@ -0,0 +1,20 @@ +#ifndef DEF_OBSIDIAN_SANCTUM_H +#define DEF_OBSIDIAN_SANCTUM_H + +enum eTypes +{ + TYPE_SARTHARION_EVENT = 1, + + DATA_SARTHARION = 10, + DATA_TENEBRON = 11, + DATA_SHADRON = 12, + DATA_VESPERON = 13, + + NPC_SARTHARION = 28860, + NPC_TENEBRON = 30452, + NPC_SHADRON = 30451, + NPC_VESPERON = 30449, + GO_TWILIGHT_PORTAL = 193988 +}; + +#endif diff --git a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp new file mode 100644 index 00000000000..bbb1df2731d --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp @@ -0,0 +1,175 @@ +/* Script Data Start +SDName: Boss malygos +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +//Spells +#define SPELL_ARCANE_BREATH_N 56272 +#define SPELL_ARCANE_BREATH_H 60072 +#define SPELL_ARCANE_PULSE 57432 +#define SPELL_ARCANE_STORM_1 57459 +#define SPELL_ARCANE_STORM_2 61693 +#define SPELL_ARCANE_STORM_3 61694 +#define SPELL_STATIC_FIELD 57430 +#define SPELL_SURGE_OF_POWER_1 56505 +#define SPELL_SURGE_OF_POWER_2 57407 +#define SPELL_SURGE_OF_POWER_3 60936 +#define SPELL_VORTEX 56105 + +//Dragon "mounts" spells in Phase3 +//they use Rugelike energy +#define SPELL_DMOUNT_FLAME_SPIKE 56091 //maybe not accurate +#define SPELL_DMOUNT_ENGULF_IN_FLAMES 61621 +#define SPELL_DMOUNT_REVIVIFY 57090 +#define SPELL_DMOUNT_LIFE_BURST 57143 +#define SPELL_DMOUNT_FLAME_SHIELD 57108 +//#define SPELL_DMOUNT_UNKNOWN XYZ //Increases your drake's flight speed by 500%. + +//not in db +//Yell +//-->Other +#define SAY_ANTI_MAGIC_SHELL -1616000 +#define SAY_BREATH_ATTACK -1616001 +#define SAY_HIGH_DAMAGE_MODE -1616002 +#define SAY_MAGIC_BLAST -1616003 +//--> Generic Spells +#define SAY_GENERIC_SPELL_1 -1616004 +#define SAY_GENERIC_SPELL_2 -1616005 +#define SAY_GENERIC_SPELL_3 -1616006 +#define SAY_DEATH -1616007 +//--> Prefight +#define SAY_PREFIGHT_1 -1616008 +#define SAY_PREFIGHT_2 -1616009 +#define SAY_PREFIGHT_3 -1616010 +#define SAY_PREFIGHT_4 -1616011 +#define SAY_PREFIGHT_5 -1616012 +//--> Phase1 +#define SAY_PHASE1_AGGRO -1616013 +#define SAY_PHASE1_END -1616014 +#define SAY_PHASE1_SLAY_1 -1616015 +#define SAY_PHASE1_SLAY_2 -1616016 +#define SAY_PHASE1_SLAY_3 -1616017 + +//--> Phase2 at 50% HP, + +/*Malygos himself is not targetable during this phase, it will end when the adds he spawns are all killed. However, he does continue to play a part in the encounter. +During this phase he drops anti-magic zones onto the ground the raid MUST stand inside of, it reduces magical damage taken by 50%. They shrink over time, so it's important that your raid moves to each new one he drops. +Throughout the phase, he will deep breath doing ~4k damage per second, unless you are standing inside of the anti-magic zone. +The way the fight works during this phase is there are NPCs riding around on disks in the room. There are two types of mobs, Lords and Scions. +The Lords will move down onto the group, and need to be tanked (They will one-shot a non-tank). After they die, they drop a disk that a raid member can mount onto, which allows them to fly, to attack the Scions that do not come down to the ground. +It is recommended to let melee take the first disks, then ranged. As those mobs die, they also drop disks, which allows the rest of your dps to get onto them. +The Scions will continually cast Arcane Blast on random targets on the floor, which is mitigated by the anti-magic zones. While mounted on a disk, you will not take damage. +After all of the NPCs riding on the disks die, the players on the disks need to dismount as Phase 3 is about to begin.*/ + +//not in db +#define SAY_PHASE2_AGGRO -1616018 +#define SAY_PHASE2_END -1616019 +#define SAY_PHASE2_SLAY_1 -1616020 +#define SAY_PHASE2_SLAY_2 -1616021 +#define SAY_PHASE2_SLAY_3 -1616022 +//--> Phase3 Malygos destroys the floor, encounter continues on dragon "mounts" +#define SAY_PHASE3_INTRO -1616023 +#define SAY_PHASE3_AGGRO -1616024 +#define SAY_PHASE3_SLAY_1 -1616025 +#define SAY_PHASE3_SLAY_2 -1616026 +#define SAY_PHASE3_SLAY_3 -1616027 +#define SAY_PHASE3_BIG_ATTACK -1616028 + +enum +{ + ACHIEV_TIMED_START_EVENT = 20387, +}; + +struct boss_malygosAI : public ScriptedAI +{ + boss_malygosAI(Creature *c) : ScriptedAI(c) + { + instance = me->GetInstanceData(); + } + + InstanceData *instance; + + uint32 phase; + uint32 enrage; + + void Reset() + { + phase = 1; + enrage = 615000; //Source Deadly Boss Mod + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void EnterCombat(Unit* /*who*/) + { + if (phase == 1) + { + DoScriptText(SAY_PHASE1_AGGRO, me); + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + if (phase == 2) + DoScriptText(SAY_PHASE1_AGGRO, me); + if (phase == 3) + DoScriptText(SAY_PHASE1_AGGRO, me); + } + + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (phase == 1 && HealthBelowPct(50)) { + phase = 2; + //spawn adds + //set malygos unatackable untill all adds spawned dead + //start phase3 + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + if (phase == 1) + DoScriptText(RAND(SAY_PHASE1_SLAY_1,SAY_PHASE1_SLAY_2,SAY_PHASE1_SLAY_3), me); + if (phase == 2) + DoScriptText(RAND(SAY_PHASE2_SLAY_1,SAY_PHASE2_SLAY_2,SAY_PHASE2_SLAY_3), me); + if (phase == 3) + DoScriptText(RAND(SAY_PHASE3_SLAY_1,SAY_PHASE3_SLAY_2,SAY_PHASE3_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_malygos(Creature* pCreature) +{ + return new boss_malygosAI (pCreature); +} + +void AddSC_boss_malygos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_malygos"; + newscript->GetAI = &GetAI_boss_malygos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h new file mode 100644 index 00000000000..caa82a92e95 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h @@ -0,0 +1,4 @@ +#ifndef DEF_EYE_OF_ETERNITY_H +#define DEF_EYE_OF_ETERNITY_H + +#endif diff --git a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp new file mode 100644 index 00000000000..d93ec415b42 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp @@ -0,0 +1,21 @@ +#include "ScriptedPch.h" +#include "eye_of_eternity.h" + +struct instance_eye_of_eternity : public ScriptedInstance +{ + instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; +}; + +InstanceData* GetInstanceData_instance_eye_of_eternity(Map* pMap) +{ + return new instance_eye_of_eternity(pMap); +} + +void AddSC_instance_eye_of_eternity() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_eye_of_eternity"; + newscript->GetInstanceData = &GetInstanceData_instance_eye_of_eternity; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp b/src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp new file mode 100644 index 00000000000..02c39dc1232 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp @@ -0,0 +1,253 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + //Spells + SPELL_SPARK = 47751, + H_SPELL_SPARK = 57062, + SPELL_RIFT_SHIELD = 47748, + SPELL_CHARGE_RIFT = 47747, //Works wrong (affect players, not rifts) + SPELL_CREATE_RIFT = 47743, //Don't work, using WA + SPELL_ARCANE_ATTRACTION = 57063, //No idea, when it's used +}; + +enum Adds +{ + MOB_CRAZED_MANA_WRAITH = 26746, + MOB_CHAOTIC_RIFT = 26918 +}; +enum Yells +{ + //Yell + SAY_AGGRO = -1576010, + SAY_DEATH = -1576011, + SAY_RIFT = -1576012, + SAY_SHIELD = -1576013 +}; + +enum Achievs +{ + ACHIEV_CHAOS_THEORY = 2037 +}; + +const Position RiftLocation[6] = +{ + {652.64, -273.70, -8.75}, + {634.45, -265.94, -8.44}, + {620.73, -281.17, -9.02}, + {626.10, -304.67, -9.44}, + {639.87, -314.11, -9.49}, + {651.72, -297.44, -9.37} +}; + +struct boss_anomalusAI : public ScriptedAI +{ + boss_anomalusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint8 Phase; + uint32 uiSparkTimer; + uint32 uiCreateRiftTimer; + uint64 uiChaoticRiftGUID; + + bool bDeadChaoticRift; // needed for achievement: Chaos Theory(2037) + + void Reset() + { + Phase = 0; + uiSparkTimer = 5*IN_MILISECONDS; + uiChaoticRiftGUID = 0; + + bDeadChaoticRift = false; + + if (pInstance) + pInstance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && !bDeadChaoticRift) + pInstance->DoCompleteAchievement(ACHIEV_CHAOS_THEORY); + pInstance->SetData(DATA_ANOMALUS_EVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetDistance(me->GetHomePosition()) > 60.0f) + { + //Not blizzlike, hack to avoid an exploit + EnterEvadeMode(); + return; + } + + if (me->HasAura(SPELL_RIFT_SHIELD)) + { + if (uiChaoticRiftGUID) + { + Unit* Rift = Unit::GetUnit((*me), uiChaoticRiftGUID); + if (Rift && Rift->isDead()) + { + me->RemoveAurasDueToSpell(SPELL_RIFT_SHIELD); + uiChaoticRiftGUID = 0; + } + return; + } + } else + uiChaoticRiftGUID = 0; + + if ((Phase == 0) && HealthBelowPct(50)) + { + Phase = 1; + DoScriptText(SAY_SHIELD, me); + DoCast(me, SPELL_RIFT_SHIELD); + Creature* Rift = me->SummonCreature(MOB_CHAOTIC_RIFT, RiftLocation[urand(0,5)], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); + if (Rift) + { + //DoCast(Rift, SPELL_CHARGE_RIFT); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Rift->AI()->AttackStart(pTarget); + uiChaoticRiftGUID = Rift->GetGUID(); + DoScriptText(SAY_RIFT , me); + } + } + + + if (uiSparkTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SPARK); + uiSparkTimer = 5*IN_MILISECONDS; + } else uiSparkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_anomalus(Creature* pCreature) +{ + return new boss_anomalusAI (pCreature); +} + +enum RiftSpells +{ + SPELL_CHAOTIC_ENERGY_BURST = 47688, + SPELL_CHARGED_CHAOTIC_ENERGY_BURST = 47737, + SPELL_ARCANEFORM = 48019 //Chaotic Rift visual +}; + +struct mob_chaotic_riftAI : public Scripted_NoMovementAI +{ + mob_chaotic_riftAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiChaoticEnergyBurstTimer; + uint32 uiSummonCrazedManaWraithTimer; + + void Reset() + { + uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; + uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; + //me->SetDisplayId(25206); //For some reason in DB models for ally and horde are different. + //Model for ally (1126) does not show auras. Horde model works perfect. + //Set model to horde number + DoCast(me, SPELL_ARCANEFORM, false); + } + + void JustDied(Unit * /*killer*/) + { + if (Creature* pAnomalus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0)) + CAST_AI(boss_anomalusAI,pAnomalus->AI())->bDeadChaoticRift = true; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiChaoticEnergyBurstTimer <= diff) + { + Unit* pAnomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + if (pAnomalus && pAnomalus->HasAura(SPELL_RIFT_SHIELD)) + DoCast(pTarget, SPELL_CHARGED_CHAOTIC_ENERGY_BURST); + else + DoCast(pTarget, SPELL_CHAOTIC_ENERGY_BURST); + uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; + } else uiChaoticEnergyBurstTimer -= diff; + + if (uiSummonCrazedManaWraithTimer <= diff) + { + Creature* Wraith = me->SummonCreature(MOB_CRAZED_MANA_WRAITH, me->GetPositionX()+1, me->GetPositionY()+1, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); + if (Wraith) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Wraith->AI()->AttackStart(pTarget); + Unit* Anomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); + if (Anomalus && Anomalus->HasAura(SPELL_RIFT_SHIELD)) + uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; + else + uiSummonCrazedManaWraithTimer = 10*IN_MILISECONDS; + } else uiSummonCrazedManaWraithTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_chaotic_rift(Creature* pCreature) +{ + return new mob_chaotic_riftAI (pCreature); +} + +void AddSC_boss_anomalus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_anomalus"; + newscript->GetAI = &GetAI_boss_anomalus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_chaotic_rift"; + newscript->GetAI = &GetAI_mob_chaotic_rift; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp new file mode 100644 index 00000000000..ff633c55eac --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp @@ -0,0 +1,247 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + //Spells + SPELL_FROZEN_PRISON = 47854, + SPELL_TAIL_SWEEP = 50155, + SPELL_CRYSTAL_CHAINS = 50997, + SPELL_ENRAGE = 8599, + SPELL_CRYSTALFIRE_BREATH = 48096, + H_SPELL_CRYSTALFIRE_BREATH = 57091, + SPELL_CRYSTALIZE = 48179, + SPELL_INTENSE_COLD = 48094, + SPELL_INTENSE_COLD_TRIGGERED = 48095 +}; +enum Yells +{ + //Yell + SAY_AGGRO = -1576040, + SAY_SLAY = -1576041, + SAY_ENRAGE = -1576042, + SAY_DEATH = -1576043, + SAY_CRYSTAL_NOVA = -1576044 +}; +enum Achievements +{ + ACHIEV_INTENSE_COLD = 2036 +}; +enum Misc +{ + DATA_CONTAINMENT_SPHERES = 3 +}; + +struct boss_keristraszaAI : public ScriptedAI +{ + boss_keristraszaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCrystalfireBreathTimer; + uint32 uiCrystalChainsCrystalizeTimer; + uint32 uiTailSweepTimer; + bool bEnrage; + + uint64 auiContainmentSphereGUIDs[DATA_CONTAINMENT_SPHERES]; + + uint32 uiCheckIntenseColdTimer; + bool bMoreThanTwoIntenseCold; // needed for achievement: Intense Cold(2036) + + void Reset() + { + uiCrystalfireBreathTimer = 14*IN_MILISECONDS; + uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); + uiTailSweepTimer = 5*IN_MILISECONDS; + bEnrage = false; + + uiCheckIntenseColdTimer = 2*IN_MILISECONDS; + bMoreThanTwoIntenseCold = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + + RemovePrison(CheckContainmentSpheres()); + + if (pInstance) + pInstance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCastAOE(SPELL_INTENSE_COLD); + + if (pInstance) + pInstance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && !bMoreThanTwoIntenseCold) + pInstance->DoCompleteAchievement(ACHIEV_INTENSE_COLD); + pInstance->SetData(DATA_KERISTRASZA_EVENT, DONE); + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_SLAY, me); + } + + bool CheckContainmentSpheres(bool remove_prison = false) + { + if (!pInstance) + return false; + + auiContainmentSphereGUIDs[0] = pInstance->GetData64(ANOMALUS_CONTAINMET_SPHERE); + auiContainmentSphereGUIDs[1] = pInstance->GetData64(ORMOROKS_CONTAINMET_SPHERE); + auiContainmentSphereGUIDs[2] = pInstance->GetData64(TELESTRAS_CONTAINMET_SPHERE); + + GameObject *ContainmentSpheres[DATA_CONTAINMENT_SPHERES]; + + for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i) + { + ContainmentSpheres[i] = pInstance->instance->GetGameObject(auiContainmentSphereGUIDs[i]); + if (!ContainmentSpheres[i]) + return false; + if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE) + return false; + } + if (remove_prison) + RemovePrison(true); + return true; + } + + void RemovePrison(bool remove) + { + if (remove) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (me->HasAura(SPELL_FROZEN_PRISON)) + me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(me, SPELL_FROZEN_PRISON, false); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiCheckIntenseColdTimer < diff && !bMoreThanTwoIntenseCold) + { + std::list ThreatList = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER) + continue; + + Aura *AuraIntenseCold = pTarget->GetAura(SPELL_INTENSE_COLD_TRIGGERED); + if (AuraIntenseCold && AuraIntenseCold->GetStackAmount() > 2) + { + bMoreThanTwoIntenseCold = true; + break; + } + } + uiCheckIntenseColdTimer = 2*IN_MILISECONDS; + } else uiCheckIntenseColdTimer -= diff; + + if (!bEnrage && HealthBelowPct(25)) + { + DoScriptText(SAY_ENRAGE, me); + DoCast(me, SPELL_ENRAGE); + bEnrage = true; + } + + if (uiCrystalfireBreathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CRYSTALFIRE_BREATH); + uiCrystalfireBreathTimer = 14*IN_MILISECONDS; + } else uiCrystalfireBreathTimer -= diff; + + if (uiTailSweepTimer <= diff) + { + DoCast(me, SPELL_TAIL_SWEEP); + uiTailSweepTimer = 5*IN_MILISECONDS; + } else uiTailSweepTimer -= diff; + + if (uiCrystalChainsCrystalizeTimer <= diff) + { + DoScriptText(SAY_CRYSTAL_NOVA, me); + if (IsHeroic()) + DoCast(me, SPELL_CRYSTALIZE); + else if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CRYSTAL_CHAINS); + uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); + } else uiCrystalChainsCrystalizeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_keristrasza(Creature* pCreature) +{ + return new boss_keristraszaAI (pCreature); +} + +bool GOHello_containment_sphere(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + + Creature *pKeristrasza = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_KERISTRASZA) : 0); + if (pKeristrasza && pKeristrasza->isAlive()) + { + // maybe these are hacks :( + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + CAST_AI(boss_keristraszaAI, pKeristrasza->AI())->CheckContainmentSpheres(true); + } + return true; +} + +void AddSC_boss_keristrasza() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_keristrasza"; + newscript->GetAI = &GetAI_boss_keristrasza; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "containment_sphere"; + newscript->pGOHello = &GOHello_containment_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp b/src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp new file mode 100644 index 00000000000..0bf9fb07bb7 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp @@ -0,0 +1,327 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + SPELL_ICE_NOVA = 47772, + H_SPELL_ICE_NOVA = 56935, + SPELL_FIREBOMB = 47773, + H_SPELL_FIREBOMB = 56934, + SPELL_GRAVITY_WELL = 47756, + SPELL_TELESTRA_BACK = 47714, + + SPELL_FIRE_MAGUS_VISUAL = 47705, + SPELL_FROST_MAGUS_VISUAL = 47706, + SPELL_ARCANE_MAGUS_VISUAL = 47704 +}; +enum Creatures +{ + MOB_FIRE_MAGUS = 26928, + MOB_FROST_MAGUS = 26930, + MOB_ARCANE_MAGUS = 26929 +}; +enum Yells +{ + SAY_AGGRO = -1576000, + SAY_KILL = -1576001, + SAY_DEATH = -1576002, + SAY_MERGE = -1576003, + SAY_SPLIT_1 = -1576004, + SAY_SPLIT_2 = -1576005, +}; +enum Achievements +{ + ACHIEV_SPLIT_PERSONALITY = 2150, + ACHIEV_TIMER = 5*IN_MILISECONDS +}; + +const Position CenterOfRoom = {504.80, 89.07, -16.12, 6.27}; + +struct boss_magus_telestraAI : public ScriptedAI +{ + boss_magus_telestraAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 uiFireMagusGUID; + uint64 uiFrostMagusGUID; + uint64 uiArcaneMagusGUID; + + bool bFireMagusDead; + bool bFrostMagusDead; + bool bArcaneMagusDead; + bool bIsWaitingToAppear; + bool bIsAchievementTimerRunning; + + uint32 uiIsWaitingToAppearTimer; + uint32 uiIceNovaTimer; + uint32 uiFireBombTimer; + uint32 uiGravityWellTimer; + uint32 uiCooldown; + uint32 uiAchievementTimer; + + uint8 Phase; + uint8 uiAchievementProgress; + + void Reset() + { + Phase = 0; + //These times are probably wrong + uiIceNovaTimer = 7*IN_MILISECONDS; + uiFireBombTimer = 0; + uiGravityWellTimer = 15*IN_MILISECONDS; + uiCooldown = 0; + + uiFireMagusGUID = 0; + uiFrostMagusGUID = 0; + uiArcaneMagusGUID = 0; + + uiAchievementProgress = 0; + uiAchievementTimer = 0; + + bIsAchievementTimerRunning = false; + bIsWaitingToAppear = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + if (pInstance) + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && uiAchievementProgress == 2) + pInstance->DoCompleteAchievement(ACHIEV_SPLIT_PERSONALITY); + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE); + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + uint64 SplitPersonality(uint32 entry) + { + if (Creature* Summoned = me->SummonCreature(entry, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS)) + { + switch (entry) + { + case MOB_FIRE_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_FIRE_MAGUS_VISUAL, false); + break; + } + case MOB_FROST_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_FROST_MAGUS_VISUAL, false); + break; + } + case MOB_ARCANE_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_ARCANE_MAGUS_VISUAL, false); + break; + } + } + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Summoned->AI()->AttackStart(pTarget); + return Summoned->GetGUID(); + } + return 0; + } + + void SummonedCreatureDespawn(Creature *summon) + { + if (summon->isAlive()) + return; + + if (summon->GetGUID() == uiFireMagusGUID) + { + bFireMagusDead = true; + bIsAchievementTimerRunning = true; + } + else if (summon->GetGUID() == uiFrostMagusGUID) + { + bFrostMagusDead = true; + bIsAchievementTimerRunning = true; + } + else if (summon->GetGUID() == uiArcaneMagusGUID) + { + bArcaneMagusDead = true; + bIsAchievementTimerRunning = true; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (bIsWaitingToAppear) + { + me->StopMoving(); + me->AttackStop(); + if (uiIsWaitingToAppearTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + bIsWaitingToAppear = false; + } else uiIsWaitingToAppearTimer -= diff; + return; + } + + if ((Phase == 1) ||(Phase == 3)) + { + if (bIsAchievementTimerRunning) + uiAchievementTimer += diff; + if (bFireMagusDead && bFrostMagusDead && bArcaneMagusDead) + { + if (uiAchievementTimer <= ACHIEV_TIMER) + uiAchievementProgress +=1; + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, CenterOfRoom.GetPositionX(), CenterOfRoom.GetPositionY(), CenterOfRoom.GetPositionZ(), CenterOfRoom.GetOrientation()); + DoCast(me, SPELL_TELESTRA_BACK); + me->SetVisibility(VISIBILITY_ON); + if (Phase == 1) + Phase = 2; + if (Phase == 3) + Phase = 4; + uiFireMagusGUID = 0; + uiFrostMagusGUID = 0; + uiArcaneMagusGUID = 0; + bIsWaitingToAppear = true; + uiIsWaitingToAppearTimer = 4*IN_MILISECONDS; + DoScriptText(SAY_MERGE, me); + bIsAchievementTimerRunning = false; + uiAchievementTimer = 0; + } + else + return; + } + + if ((Phase == 0) && HealthBelowPct(50)) + { + Phase = 1; + me->CastStop(); + me->RemoveAllAuras(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); + uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); + uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); + bFireMagusDead = false; + bFrostMagusDead = false; + bArcaneMagusDead = false; + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + return; + } + + if (IsHeroic() && (Phase == 2) && HealthBelowPct(10)) + { + Phase = 3; + me->CastStop(); + me->RemoveAllAuras(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); + uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); + uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); + bFireMagusDead = false; + bFrostMagusDead = false; + bArcaneMagusDead = false; + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + return; + } + + if (uiCooldown) + { + if (uiCooldown <= diff) + uiCooldown = 0; + else + { + uiCooldown -= diff; + return; + } + } + + if (uiIceNovaTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_ICE_NOVA, false); + uiCooldown = 1.5*IN_MILISECONDS; + } + uiIceNovaTimer = 15*IN_MILISECONDS; + } else uiIceNovaTimer -= diff; + + if (uiGravityWellTimer <= diff) + { + if (Unit *pTarget = me->getVictim()) + { + DoCast(pTarget, SPELL_GRAVITY_WELL); + uiCooldown = 6*IN_MILISECONDS; + } + uiGravityWellTimer = 15*IN_MILISECONDS; + } else uiGravityWellTimer -= diff; + + if (uiFireBombTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_FIREBOMB, false); + uiCooldown = 2*IN_MILISECONDS; + } + uiFireBombTimer = 2*IN_MILISECONDS; + } else uiFireBombTimer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_magus_telestra(Creature* pCreature) +{ + return new boss_magus_telestraAI (pCreature); +} + +void AddSC_boss_magus_telestra() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_magus_telestra"; + newscript->GetAI = &GetAI_boss_magus_telestra; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp new file mode 100644 index 00000000000..1304f95c7ac --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp @@ -0,0 +1,298 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + SPELL_CRYSTAL_SPIKES = 47958, //Don't work, using walkaround + H_SPELL_CRYSTAL_SPIKES = 57082, //Don't work, using walkaround + SPELL_CRYSTALL_SPIKE_DAMAGE = 47944, + H_SPELL_CRYSTALL_SPIKE_DAMAGE = 57067, + SPELL_CRYSTAL_SPIKE_PREVISUAL = 50442, + MOB_CRYSTAL_SPIKE = 27099, + SPELL_SPELL_REFLECTION = 47981, + SPELL_TRAMPLE = 48016, + H_SPELL_TRAMPLE = 57066, + SPELL_FRENZY = 48017, + SPELL_SUMMON_CRYSTALLINE_TANGLER = 61564, //summons npc 32665 + SPELL_ROOTS = 28858 //proper spell id is unknown +}; +enum Yells +{ + SAY_AGGRO = -1576020, + SAY_DEATH = -1576021, + SAY_REFLECT = -1576022, + SAY_CRYSTAL_SPIKES = -1576023, + SAY_KILL = -1576024 +}; +enum Creatures +{ + MOB_CRYSTALLINE_TANGLER = 32665 +}; + +#define SPIKE_DISTANCE 5.0f + +struct boss_ormorokAI : public ScriptedAI +{ + boss_ormorokAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bFrenzy; + bool bCrystalSpikes; + uint8 uiCrystalSpikesCount; + float fBaseX; + float fBaseY; + float fBaseZ; + float fBaseO; + float fSpikeXY[4][2]; + + uint32 uiCrystalSpikesTimer; + uint32 uiCrystalSpikesTimer2; + uint32 uiTrampleTimer; + uint32 uiFrenzyTimer; + uint32 uiSpellReflectionTimer; + uint32 uiSummonCrystallineTanglerTimer; + + void Reset() + { + uiCrystalSpikesTimer = 12*IN_MILISECONDS; + uiTrampleTimer = 10*IN_MILISECONDS; + uiSpellReflectionTimer = 30*IN_MILISECONDS; + uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; + bFrenzy = false; + bCrystalSpikes = false; + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + return; + } + if (bCrystalSpikes) + if (uiCrystalSpikesTimer2 <= diff) + { + fSpikeXY[0][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); + fSpikeXY[0][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); + fSpikeXY[1][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); + fSpikeXY[1][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); + fSpikeXY[2][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); + fSpikeXY[2][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); + fSpikeXY[3][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); + fSpikeXY[3][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); + for (uint8 i = 0; i < 4; ++i) + me->SummonCreature(MOB_CRYSTAL_SPIKE, fSpikeXY[i][0], fSpikeXY[i][1], fBaseZ, 0, TEMPSUMMON_TIMED_DESPAWN, 7*IN_MILISECONDS); + if (++uiCrystalSpikesCount >= 13) + bCrystalSpikes = false; + uiCrystalSpikesTimer2 = 200; + } else uiCrystalSpikesTimer2 -= diff; + + if (!bFrenzy && (me->GetHealth() < me->GetMaxHealth() * 0.25)) + { + DoCast(me, SPELL_FRENZY); + bFrenzy = true; + } + + if (uiTrampleTimer <= diff) + { + DoCast(me, SPELL_TRAMPLE); + uiTrampleTimer = 10*IN_MILISECONDS; + } else uiTrampleTimer -= diff; + + if (uiSpellReflectionTimer <= diff) + { + DoScriptText(SAY_REFLECT, me); + DoCast(me, SPELL_SPELL_REFLECTION); + uiSpellReflectionTimer = 30*IN_MILISECONDS; + } else uiSpellReflectionTimer -= diff; + + if (uiCrystalSpikesTimer <= diff) + { + DoScriptText(SAY_CRYSTAL_SPIKES, me); + bCrystalSpikes = true; + uiCrystalSpikesCount = 1; + uiCrystalSpikesTimer2 = 0; + fBaseX = me->GetPositionX(); + fBaseY = me->GetPositionY(); + fBaseZ = me->GetPositionZ(); + fBaseO = me->GetOrientation(); + uiCrystalSpikesTimer = 20*IN_MILISECONDS; + } else uiCrystalSpikesTimer -= diff; + + if (IsHeroic() && (uiSummonCrystallineTanglerTimer <= diff)) + { + Creature* Crystalline_Tangler = me->SummonCreature(MOB_CRYSTALLINE_TANGLER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + if (Crystalline_Tangler) + { + Unit *pTarget = NULL; + uint8 Healer = 0; + for (uint8 j = 1; j <= 4; j++) + { + switch (j) + { + case 1: Healer = CLASS_PRIEST; break; + case 2: Healer = CLASS_PALADIN; break; + case 3: Healer = CLASS_DRUID; break; + case 4: Healer = CLASS_SHAMAN; break; + } + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pTemp = Unit::GetUnit((*me),(*i)->getUnitGuid()); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && pTemp->getClass() == Healer) + { + pTarget = pTemp; + break; + } + } + if (pTarget) + break; + } + if (!pTarget) + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Crystalline_Tangler->AI()->AttackStart(pTarget); + Crystalline_Tangler->getThreatManager().addThreat(pTarget, 1000000000.0f); + } + } + uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; + } else uiSummonCrystallineTanglerTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_crystal_spikeAI : public Scripted_NoMovementAI +{ + mob_crystal_spikeAI(Creature *c) : Scripted_NoMovementAI(c) + { + } + + uint32 SpellCrystalSpikeDamageTimer; + uint32 SpellCrystalSpikePrevisualTimer; + + void Reset() + { + SpellCrystalSpikeDamageTimer = 3.7*IN_MILISECONDS; + SpellCrystalSpikePrevisualTimer = 1*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (SpellCrystalSpikePrevisualTimer <= diff) + { + DoCast(me, SPELL_CRYSTAL_SPIKE_PREVISUAL); + SpellCrystalSpikePrevisualTimer = 10*IN_MILISECONDS; + } else SpellCrystalSpikePrevisualTimer -= diff; + + if (SpellCrystalSpikeDamageTimer <= diff) + { + DoCast(me, SPELL_CRYSTALL_SPIKE_DAMAGE); + SpellCrystalSpikeDamageTimer = 10*IN_MILISECONDS; + } else SpellCrystalSpikeDamageTimer -= diff; + } +}; + +struct mob_crystalline_tanglerAI : public ScriptedAI +{ + mob_crystalline_tanglerAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiRootsTimer; + + void Reset() + { + uiRootsTimer = 1*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (uiRootsTimer <= diff) + { + if (me->IsWithinDist(me->getVictim(), 5.0f, false)) + { + DoCast(me->getVictim(), SPELL_ROOTS); + uiRootsTimer = 15*IN_MILISECONDS; + } + } else uiRootsTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_crystal_spike(Creature* pCreature) +{ + return new mob_crystal_spikeAI (pCreature); +} + +CreatureAI* GetAI_mob_crystalline_tangler(Creature* pCreature) +{ + return new mob_crystalline_tanglerAI (pCreature); +} + +CreatureAI* GetAI_boss_ormorok(Creature* pCreature) +{ + return new boss_ormorokAI (pCreature); +} + +void AddSC_boss_ormorok() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ormorok"; + newscript->GetAI = &GetAI_boss_ormorok; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crystal_spike"; + newscript->GetAI = &GetAI_mob_crystal_spike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crystalline_tangler"; + newscript->GetAI = &GetAI_mob_crystalline_tangler; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp b/src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp new file mode 100644 index 00000000000..4bd9f55a013 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp @@ -0,0 +1,58 @@ +/* Script Data Start +SDName: Boss Commander Kolurg +SDAuthor: LordVanMartin +SD%Complete: +SDComment: Only Alliance Heroic +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_commander_kolurg' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +#define SPELL_BATTLE_SHOUT 31403 +#define SPELL_CHARGE 60067 +#define SPELL_FRIGHTENING_SHOUT 19134 +#define SPELL_WHIRLWIND_1 38619 +#define SPELL_WHIRLWIND_2 38618 + +//not used +//Yell +#define SAY_AGGRO -1576024 +#define SAY_KILL -1576025 +#define SAY_DEATH -1576026 + +struct boss_commander_kolurgAI : public ScriptedAI +{ + boss_commander_kolurgAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) {} +}; + +CreatureAI* GetAI_boss_commander_kolurg(Creature* pCreature) +{ + return new boss_commander_kolurgAI (pCreature); +} + +void AddSC_boss_commander_kolurg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_commander_kolurg"; + newscript->GetAI = &GetAI_boss_commander_kolurg; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp b/src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp new file mode 100644 index 00000000000..ef02baa38e6 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp @@ -0,0 +1,64 @@ +/* Script Data Start +SDName: Boss Commander Stoutbeard +SDAuthor: LordVanMartin +SD%Complete: +SDComment: Only Horde Heroic +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_commander_stoutbeard' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +#define SPELL_BATTLE_SHOUT 31403 +#define SPELL_CHARGE 60067 +#define SPELL_FRIGHTENING_SHOUT 19134 +#define SPELL_WHIRLWIND_1 38619 +#define SPELL_WHIRLWIND_2 38618 + +//not used +//Yell +#define SAY_AGGRO -1576021 +#define SAY_KILL -1576022 +#define SAY_DEATH -1576023 + +struct boss_commander_stoutbeardAI : public ScriptedAI +{ + boss_commander_stoutbeardAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + } +}; + +CreatureAI* GetAI_boss_commander_stoutbeard(Creature* pCreature) +{ + return new boss_commander_stoutbeardAI (pCreature); +} + +void AddSC_boss_commander_stoutbeard() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_commander_stoutbeard"; + newscript->GetAI = &GetAI_boss_commander_stoutbeard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp b/src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp new file mode 100644 index 00000000000..db70245e3a4 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp @@ -0,0 +1,259 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +#define NUMBER_OF_ENCOUNTERS 4 + +enum Factions +{ + FACTION_HOSTILE_FOR_ALL = 16 +}; + +struct instance_nexus : public ScriptedInstance +{ + instance_nexus(Map *pMap) : ScriptedInstance(pMap) { Initialize(); } + + uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS]; + + uint64 Anomalus; + uint64 Keristrasza; + + uint64 AnomalusContainmentSphere; + uint64 OrmoroksContainmentSphere; + uint64 TelestrasContainmentSphere; + + std::string strInstData; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Anomalus = 0; + Keristrasza = 0; + } + + void OnCreatureCreate(Creature *pCreature, bool /*bAdd*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + uint32 TeamInInstance = 0; + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + TeamInInstance = pPlayer->GetTeam(); + } + switch (pCreature->GetEntry()) + { + case 26763: + Anomalus = pCreature->GetGUID(); + break; + case 26723: + Keristrasza = pCreature->GetGUID(); + break; + // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. + case 26800: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26799, HORDE); + break; + } + case 26802: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26801, HORDE); + break; + } + case 26805: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26803, HORDE); + break; + } + case 27949: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(27947, HORDE); + break; + } + case 26796: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26798, HORDE); + break; + } + } + } + + void OnGameObjectCreate(GameObject *pGo, bool /*bAdd*/) + { + switch (pGo->GetEntry()) + { + case 188527: + { + AnomalusContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + case 188528: + { + OrmoroksContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + case 188526: + { + TelestrasContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + } + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0]; + case DATA_ANOMALUS_EVENT: return m_auiEncounter[1]; + case DATA_ORMOROK_EVENT: return m_auiEncounter[2]; + case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3]; + } + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch (identifier) + { + case DATA_MAGUS_TELESTRA_EVENT: + { + if (data == DONE) + { + GameObject *Sphere = instance->GetGameObject(TelestrasContainmentSphere); + if (Sphere) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[0] = data; + break; + } + case DATA_ANOMALUS_EVENT: + { + if (data == DONE) + { + if (GameObject *Sphere = instance->GetGameObject(AnomalusContainmentSphere)) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[1] = data; + break; + } + case DATA_ORMOROK_EVENT: + { + if (data == DONE) + { + if (GameObject *Sphere = instance->GetGameObject(OrmoroksContainmentSphere)) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[2] = data; + break; + } + case DATA_KERISTRASZA_EVENT: + m_auiEncounter[3] = data; + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3]; + + strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint64 GetData64(uint32 uiIdentifier) + { + switch(uiIdentifier) + { + case DATA_ANOMALUS: return Anomalus; + case DATA_KERISTRASZA: return Keristrasza; + case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere; + case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere; + case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere; + } + return 0; + } + + std::string GetSaveData() + { + return strInstData; + } + + void Load(const char *chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + + for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData *GetInstanceData_instance_nexus(Map *pMap) +{ + return new instance_nexus(pMap); +} + +void AddSC_instance_nexus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_nexus"; + newscript->GetInstanceData = &GetInstanceData_instance_nexus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/nexus.h b/src/server/scripts/Northrend/TheNexus/nexus/nexus.h new file mode 100644 index 00000000000..66902bece30 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/nexus/nexus.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_NEXUS_H +#define DEF_NEXUS_H + +enum eTypes +{ + DATA_MAGUS_TELESTRA_EVENT, + DATA_ANOMALUS_EVENT, + DATA_ORMOROK_EVENT, + DATA_KERISTRASZA_EVENT, + + DATA_ANOMALUS, + DATA_KERISTRASZA, + + ANOMALUS_CONTAINMET_SPHERE, + ORMOROKS_CONTAINMET_SPHERE, + TELESTRAS_CONTAINMET_SPHERE +}; + +#endif diff --git a/src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp b/src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp new file mode 100644 index 00000000000..7d276206339 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp @@ -0,0 +1,218 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + SPELL_MAGIC_PULL = 51336, + SPELL_MAGIC_PULL_EFFECT = 50770, + SPELL_THUNDERING_STOMP = 50774, + SPELL_THUNDERING_STOMP_H = 59370, + SPELL_UNSTABLE_SPHERE_PASSIVE = 50756, + SPELL_UNSTABLE_SPHERE_PULSE = 50757, + SPELL_UNSTABLE_SPHERE_TIMER = 50758, + NPC_UNSTABLE_SPHERE = 28166, +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1578000, + SAY_KILL_1 = -1578001, + SAY_KILL_2 = -1578002, + SAY_KILL_3 = -1578003, + SAY_DEATH = -1578004, + SAY_PULL_1 = -1578005, + SAY_PULL_2 = -1578006, + SAY_PULL_3 = -1578007, + SAY_PULL_4 = -1578008, + SAY_STOMP_1 = -1578009, + SAY_STOMP_2 = -1578010, + SAY_STOMP_3 = -1578011 +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 18153, +}; + +struct boss_drakosAI : public ScriptedAI +{ + boss_drakosAI(Creature* pCreature) : ScriptedAI(pCreature), lSummons(me) + { + pInstance = pCreature->GetInstanceData(); + } + + uint32 uiMagicPullTimer; + uint32 uiStompTimer; + uint32 uiBombSummonTimer; + + bool bPostPull; + + ScriptedInstance* pInstance; + SummonList lSummons; + + void Reset() + { + lSummons.DespawnAll(); + uiMagicPullTimer = 15000; + uiStompTimer = 17000; + uiBombSummonTimer = 2000; + + bPostPull = false; + + if (pInstance) + pInstance->SetData(DATA_DRAKOS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_DRAKOS_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature* pSummon) + { + lSummons.Summon(pSummon); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBombSummonTimer <= uiDiff) + { + Position pPosition; + me->GetPosition(&pPosition); + + if (bPostPull) + { + for (uint8 uiI = 0; uiI >= 3; uiI++) + { + me->GetRandomNearPosition(pPosition, float(urand(0,10))); + me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); + } + } + else + { + me->GetRandomNearPosition(pPosition, float(urand(0,10))); + me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); + } + + uiBombSummonTimer = 2000; + } else uiBombSummonTimer -= uiDiff; + + if (uiMagicPullTimer <= uiDiff) + { + DoCast(SPELL_MAGIC_PULL); + + bPostPull = true; + + uiMagicPullTimer = 15000; + } else uiMagicPullTimer -= uiDiff; + + if (uiStompTimer <= uiDiff) + { + DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2,SAY_STOMP_3), me); + DoCast(SPELL_THUNDERING_STOMP); + uiStompTimer = 17000; + } else uiStompTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_DRAKOS_EVENT, DONE); + // start achievement timer (kill Eregos within 20 min) + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + lSummons.DespawnAll(); + } + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); + } +}; + +CreatureAI* GetAI_boss_drakos(Creature* pCreature) +{ + return new boss_drakosAI (pCreature); +} + +struct npc_unstable_sphereAI : public ScriptedAI +{ + npc_unstable_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiPulseTimer; + uint32 uiDeathTimer; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MoveRandom(40.0f); + + me->AddAura(SPELL_UNSTABLE_SPHERE_PASSIVE, me); + me->AddAura(SPELL_UNSTABLE_SPHERE_TIMER, me); + + uiPulseTimer = 3000; + uiDeathTimer = 19000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiPulseTimer <= uiDiff) + { + DoCast(SPELL_UNSTABLE_SPHERE_PULSE); + uiPulseTimer = 3*IN_MILISECONDS; + } else uiPulseTimer -= uiDiff; + + if (uiDeathTimer <= uiDiff) + me->DisappearAndDie(); + else uiDeathTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_unstable_sphere(Creature* pCreature) +{ + return new npc_unstable_sphereAI (pCreature); +} + +void AddSC_boss_drakos() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_drakos"; + newscript->GetAI = &GetAI_boss_drakos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_unstable_sphere"; + newscript->GetAI = &GetAI_npc_unstable_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp b/src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp new file mode 100644 index 00000000000..94fb90ab206 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp @@ -0,0 +1,129 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +//Types of drake mounts: Ruby(Tank), Amber(DPS), Emerald(Healer) +//Two Repeating phases + +enum Spells +{ + SPELL_ARCANE_BARRAGE = 50804, + H_SPELL_ARCANE_BARRAGE = 59381, + SPELL_ARCANE_VOLLEY = 51153, + H_SPELL_ARCANE_VOLLEY = 59382, + SPELL_ENRAGED_ASSAULT = 51170, + SPELL_PLANAR_ANOMALIES = 57959, + SPELL_PLANAR_SHIFT = 51162, +}; +/*Ruby Drake , +(npc 27756) (item 37860) +(summoned by spell Ruby Essence = 37860 ---> Call Amber Drake == 49462 ---> Summon 27756) +*/ +enum RubyDrake +{ + NPC_RUBY_DRAKE_VEHICLE = 27756, + SPELL_RIDE_RUBY_DRAKE_QUE = 49463, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49464 + SPELL_RUBY_DRAKE_SADDLE = 49464, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_RUBY_SEARING_WRATH = 50232, //(60 yds) - Instant - Breathes a stream of fire at an enemy dragon, dealing 6800 to 9200 Fire damage and then jumping to additional dragons within 30 yards. Each jump increases the damage by 50%. Affects up to 5 total targets + SPELL_RUBY_EVASIVE_AURA = 50248, //Instant - Allows the Ruby Drake to generate Evasive Charges when hit by hostile attacks and spells. + SPELL_RUBY_EVASIVE_MANEUVERS = 50240, //Instant - 5 sec. cooldown - Allows your drake to dodge all incoming attacks and spells. Requires Evasive Charges to use. Each attack or spell dodged while this ability is active burns one Evasive Charge. Lasts 30 sec. or until all charges are exhausted. + //you do not have acces to until you kill Mage-Lord Urom + SPELL_RUBY_MARTYR = 50253 //Instant - 10 sec. cooldown - Redirect all harmful spells cast at friendly drakes to yourself for 10 sec. +}; +/*Amber Drake, +(npc 27755) (item 37859) +(summoned by spell Amber Essence = 37859 ---> Call Amber Drake == 49461 ---> Summon 27755) +*/ +enum AmberDrake +{ + NPC_AMBER_DRAKE_VEHICLE = 27755, + SPELL_RIDE_AMBER_DRAKE_QUE = 49459, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49460 + SPELL_AMBER_DRAKE_SADDLE = 49460, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_AMBER_SHOCK_LANCE = 49840, //(60 yds) - Instant - Deals 4822 to 5602 Arcane damage and detonates all Shock Charges on an enemy dragon. Damage is increased by 6525 for each detonated. +// SPELL_AMBER_STOP_TIME //Instant - 1 min cooldown - Halts the passage of time, freezing all enemy dragons in place for 10 sec. This attack applies 5 Shock Charges to each affected target. + //you do not have access to until you kill the Mage-Lord Urom. + SPELL_AMBER_TEMPORAL_RIFT = 49592 //(60 yds) - Channeled - Channels a temporal rift on an enemy dragon for 10 sec. While trapped in the rift, all damage done to the target is increased by 100%. In addition, for every 15,000 damage done to a target affected by Temporal Rift, 1 Shock Charge is generated. +}; +/*Emerald Drake, +(npc 27692) (item 37815), + (summoned by spell Emerald Essence = 37815 ---> Call Emerald Drake == 49345 ---> Summon 27692) +*/ +enum EmeraldDrake +{ + NPC_EMERALD_DRAKE_VEHICLE = 27692, + SPELL_RIDE_EMERALD_DRAKE_QUE = 49427, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49346 + SPELL_EMERALD_DRAKE_SADDLE = 49346, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_EMERALD_LEECHING_POISON = 50328, //(60 yds) - Instant - Poisons the enemy dragon, leeching 1300 to the caster every 2 sec. for 12 sec. Stacks up to 3 times. + SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, //(60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25,000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec. + // you do not have access to until you kill the Mage-Lord Urom + SPELL_EMERALD_DREAM_FUNNEL = 50344 //(60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels. +}; + +struct boss_eregosAI : public ScriptedAI +{ + boss_eregosAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, DONE); + } +}; + +CreatureAI* GetAI_boss_eregos(Creature* pCreature) +{ + return new boss_eregosAI (pCreature); +} + +void AddSC_boss_eregos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_eregos"; + newscript->GetAI = &GetAI_boss_eregos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp b/src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp new file mode 100644 index 00000000000..29435441d00 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp @@ -0,0 +1,356 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Urom +SD%Complete: 80 +SDComment: Is not working SPELL_ARCANE_SHIELD. SPELL_FROSTBOMB has some issues, the damage aura should not stack. +SDCategory: Instance Script +EndScriptData */ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + + SPELL_ARCANE_SHIELD = 53813, //Dummy --> Channeled, shields the caster from damage. + SPELL_EMPOWERED_ARCANE_EXPLOSION = 51110, + SPELL_EMPOWERED_ARCANE_EXPLOSION_2 = 59377, + SPELL_FROSTBOMB = 51103, //Urom throws a bomb, hitting its target with the highest aggro which inflict directly 650 frost damage and drops a frost zone on the ground. This zone deals 650 frost damage per second and reduce the movement speed by 35%. Lasts 1 minute. + SPELL_SUMMON_MENAGERIE = 50476, //Summons an assortment of creatures and teleports the caster to safety. + SPELL_SUMMON_MENAGERIE_2 = 50495, + SPELL_SUMMON_MENAGERIE_3 = 50496, + SPELL_TELEPORT = 51112, //Teleports to the center of Oculus + SPELL_TIME_BOMB = 51121, //Deals arcane damage to a random player, and after 6 seconds, deals zone damage to nearby equal to the health missing of the target afflicted by the debuff. + SPELL_TIME_BOMB_2 = 59376 +}; + +enum Yells +{ + SAY_AGGRO_1 = -1578000, + SAY_AGGRO_2 = -1578001, + SAY_AGGRO_3 = -1578002, + SAY_AGGRO_4 = -1578003, + SAY_TELEPORT = -1578004, +}; + +enum eCreature +{ + NPC_PHANTASMAL_CLOUDSCRAPER = 27645, + NPC_PHANTASMAL_MAMMOTH = 27642, + NPC_PHANTASMAL_WOLF = 27644, + + NPC_PHANTASMAL_AIR = 27650, + NPC_PHANTASMAL_FIRE = 27651, + NPC_PHANTASMAL_WATER = 27653, + + NPC_PHANTASMAL_MURLOC = 27649, + NPC_PHANTASMAL_NAGAL = 27648, + NPC_PHANTASMAL_OGRE = 27647 +}; + +struct Summons +{ + uint32 uiEntry[4]; +}; + +static Summons Group[]= +{ + {NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_MAMMOTH,NPC_PHANTASMAL_WOLF}, + {NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_WATER,NPC_PHANTASMAL_FIRE}, + {NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_NAGAL,NPC_PHANTASMAL_MURLOC} +}; + +static uint32 TeleportSpells[]= +{ + SPELL_SUMMON_MENAGERIE,SPELL_SUMMON_MENAGERIE_2,SPELL_SUMMON_MENAGERIE_3 +}; + +static int32 SayAggro[]= +{ + SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4 +}; + +struct boss_uromAI : public ScriptedAI +{ + boss_uromAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + float x,y; + + bool bCanCast; + bool bCanGoBack; + + uint8 uiGroup[3]; + + uint32 uiTeleportTimer; + uint32 uiArcaneExplosionTimer; + uint32 uiCastArcaneExplosionTimer; + uint32 uiFrostBombTimer; + uint32 uiTimeBombTimer; + + void Reset() + { + if (pInstance && pInstance->GetData(DATA_VAROS_EVENT) != DONE) + DoCast(SPELL_ARCANE_SHIELD); + + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, NOT_STARTED); + + if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) == 0) + { + uiGroup[0] = 0; + uiGroup[1] = 0; + uiGroup[2] = 0; + } + + x,y = 0.0f; + bCanCast = false; + bCanGoBack = false; + + me->GetMotionMaster()->MoveIdle(); + + uiTeleportTimer = urand(30000,35000); + uiArcaneExplosionTimer = 9000; + uiCastArcaneExplosionTimer = 2000; + uiFrostBombTimer = urand(5000,8000); + uiTimeBombTimer = urand(20000,25000); + } + + void EnterCombat(Unit* pWho) + { + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, IN_PROGRESS); + + SetGroups(); + SummonGroups(); + CastTeleport(); + + if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) != 3) + pInstance->SetData(DATA_UROM_PLATAFORM,pInstance->GetData(DATA_UROM_PLATAFORM)+1); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (me->GetPositionZ() > 518.63) + DoStartNoMovement(pWho); + + if (me->GetPositionZ() < 518.63) + { + if (me->Attack(pWho, true)) + { + DoScriptText(SayAggro[3],me); + + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(pWho, 0,0); + } + } + } + + void SetGroups() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) != 0) + return; + + while (uiGroup[0] == uiGroup[1] || uiGroup[0] == uiGroup[2] || uiGroup[1] == uiGroup[2]) + { + uiGroup[0] = urand(0,2); + uiGroup[1] = urand(0,2); + uiGroup[2] = urand(0,2); + } + } + + void SetPosition(uint8 uiI) + { + switch(uiI) + { + case 0: + x = me->GetPositionX() + 4; + y = me->GetPositionY() - 4; + break; + case 1: + x = me->GetPositionX() + 4; + y = me->GetPositionY() + 4; + break; + case 2: + x = me->GetPositionX() - 4; + y = me->GetPositionY() + 4; + break; + case 3: + x = me->GetPositionX() - 4; + y = me->GetPositionY() - 4; + break; + default: + break; + } + } + + void SummonGroups() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) + return; + + for (uint8 uiI = 0; uiI < 4 ; uiI++) + { + SetPosition(uiI); + me->SummonCreature(Group[uiGroup[pInstance->GetData(DATA_UROM_PLATAFORM)]].uiEntry[uiI],x,y,me->GetPositionZ(),me->GetOrientation()); + } + } + + void CastTeleport() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) + return; + + DoScriptText(SayAggro[pInstance->GetData(DATA_UROM_PLATAFORM)],me); + DoCast(TeleportSpells[pInstance->GetData(DATA_UROM_PLATAFORM)]); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) < 2) + return; + + if (uiTeleportTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(false); + DoScriptText(SAY_TELEPORT,me); + me->GetMotionMaster()->MoveIdle(); + DoCast(SPELL_TELEPORT); + uiTeleportTimer = urand(30000,35000); + + } else uiTeleportTimer -= uiDiff; + + if (bCanCast && !me->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION)) + { + if (uiCastArcaneExplosionTimer <= uiDiff) + { + bCanCast = false; + bCanGoBack = true; + DoCastAOE(SPELL_EMPOWERED_ARCANE_EXPLOSION); + uiCastArcaneExplosionTimer = 2000; + }else uiCastArcaneExplosionTimer -= uiDiff; + } + + if (bCanGoBack) + { + if (uiArcaneExplosionTimer <= uiDiff) + { + Position pPos; + me->getVictim()->GetPosition(&pPos); + + me->NearTeleportTo(pPos.GetPositionX(),pPos.GetPositionY(),pPos.GetPositionZ(),pPos.GetOrientation()); + me->GetMotionMaster()->MoveChase(me->getVictim(),0,0); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + + bCanCast = false; + bCanGoBack = false; + uiArcaneExplosionTimer = 9000; + } else uiArcaneExplosionTimer -= uiDiff; + } + + if (!me->IsNonMeleeSpellCasted(false, true, true)) + { + if (uiFrostBombTimer <= uiDiff) + { + DoCastVictim(SPELL_FROSTBOMB); + uiFrostBombTimer = urand(5000,8000); + } else uiFrostBombTimer -= uiDiff; + + if (uiTimeBombTimer <= uiDiff) + { + if (Unit* pUnit = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pUnit,SPELL_TIME_BOMB); + + uiTimeBombTimer = urand(20000,25000); + } else uiTimeBombTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, DONE); + } + + void JustSummoned(Creature* pSummon) + { + pSummon->SetInCombatWithZone(); + } + + void LeaveCombat() + { + me->RemoveAllAuras(); + me->CombatStop(false); + me->DeleteThreatList(); + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + switch(pSpell->Id) + { + case SPELL_SUMMON_MENAGERIE: + me->SetHomePosition(968.66,1042.53,527.32,0.077); + LeaveCombat(); + break; + case SPELL_SUMMON_MENAGERIE_2: + me->SetHomePosition(1164.02,1170.85,527.321,3.66); + LeaveCombat(); + break; + case SPELL_SUMMON_MENAGERIE_3: + me->SetHomePosition(1118.31,1080.377,508.361,4.25); + LeaveCombat(); + break; + case SPELL_TELEPORT: + me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE); // with out it the npc will fall down while is casting + bCanCast = true; + break; + default: + break; + } + } +}; + +CreatureAI* GetAI_boss_urom(Creature* pCreature) +{ + return new boss_uromAI (pCreature); +} + +void AddSC_boss_urom() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_urom"; + newscript->GetAI = &GetAI_boss_urom; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp b/src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp new file mode 100644 index 00000000000..79034250a43 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + SPELL_ENERGIZE_CORES = 50785, //Damage 5938 to 6562, effec2 Triggers 54069, effect3 Triggers 56251 + SPELL_ENERGIZE_CORES_TRIGGER_1 = 54069, + SPELL_ENERGIZE_CORES_TRIGGER_2 = 56251, + SPELL_ENERGIZE_CORES_2 = 59372, //Damage 9025 to 9975, effect2 Triggers 54069, effect 56251 + SPELL_CALL_AZURE_RING_CAPTAIN = 51002, //Effect Send Event (12229) + SPELL_CALL_AZURE_RING_CAPTAIN_2 = 51006, //Effect Send Event (10665) + SPELL_CALL_AZURE_RING_CAPTAIN_3 = 51007, //Effect Send Event (18454) + SPELL_CALL_AZURE_RING_CAPTAIN_4 = 51008, //Effect Send Event (18455) + SPELL_CALL_AMPLIFY_MAGIC = 51054, + SPELL_CALL_AMPLIFY_MAGIC_2 = 59371 +}; +//not in db +enum Yells +{ + SAY_AGGRO = -1578022, + SAY_KILL_1 = -1578023, + SAY_KILL_2 = -1578024, + SAY_DEATH = -1578025, + SAY_STRIKE_1 = -1578026, + SAY_STRIKE_2 = -1578027, + SAY_STRIKE_3 = -1578028, + SAY_SPAWN = -1578029 +}; + +struct boss_varosAI : public ScriptedAI +{ + boss_varosAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, NOT_STARTED); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, IN_PROGRESS); + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, DONE); + } + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } +}; + +CreatureAI* GetAI_boss_varos(Creature* pCreature) +{ + return new boss_varosAI (pCreature); +} + +void AddSC_boss_varos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_varos"; + newscript->GetAI = &GetAI_boss_varos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp b/src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp new file mode 100644 index 00000000000..49be2385a3c --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +#define MAX_ENCOUNTER 4 + +/* The Occulus encounters: +0 - Drakos the Interrogator +1 - Varos Cloudstrider +2 - Mage-Lord Urom +3 - Ley-Guardian Eregos */ + +struct instance_oculus : public ScriptedInstance +{ + instance_oculus(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiDrakos; + uint64 uiVaros; + uint64 uiUrom; + uint64 uiEregos; + + uint8 uiPlataformUrom; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + std::list GameObjectList; + + void Initialize() + { + uiPlataformUrom = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case CREATURE_DRAKOS: + uiDrakos = pCreature->GetGUID(); + break; + case CREATURE_VAROS: + uiVaros = pCreature->GetGUID(); + break; + case CREATURE_UROM: + uiUrom = pCreature->GetGUID(); + break; + case CREATURE_EREGOS: + uiEregos = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGO, bool bAdd) + { + if (pGO->GetEntry() == GO_DRAGON_CAGE_DOOR) + { + if (DATA_DRAKOS_EVENT == DONE) + pGO->SetGoState(GO_STATE_ACTIVE); + else + pGO->SetGoState(GO_STATE_READY); + + GameObjectList.push_back(pGO->GetGUID()); + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_DRAKOS_EVENT: + m_auiEncounter[0] = data; + if (data == DONE) + OpenCageDoors(); + break; + case DATA_VAROS_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_UROM_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_EREGOS_EVENT: + m_auiEncounter[3] = data; + break; + case DATA_UROM_PLATAFORM: + uiPlataformUrom = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_DRAKOS_EVENT: return m_auiEncounter[0]; + case DATA_VAROS_EVENT: return m_auiEncounter[1]; + case DATA_UROM_EVENT: return m_auiEncounter[2]; + case DATA_EREGOS_EVENT: return m_auiEncounter[3]; + case DATA_UROM_PLATAFORM: return uiPlataformUrom; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_DRAKOS: return uiDrakos; + case DATA_VAROS: return uiVaros; + case DATA_UROM: return uiUrom; + case DATA_EREGOS: return uiEregos; + } + + return 0; + } + + void OpenCageDoors() + { + if (GameObjectList.empty()) + return; + + for (std::list::const_iterator itr = GameObjectList.begin(); itr != GameObjectList.end(); ++itr) + { + if (GameObject* pGO = instance->GetGameObject(*itr)) + pGO->SetGoState(GO_STATE_ACTIVE); + } + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "T O " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'T' && dataHead2 == 'O') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_oculus(Map* pMap) +{ + return new instance_oculus(pMap); +} + +void AddSC_instance_oculus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_oculus"; + newscript->GetInstanceData = &GetInstanceData_instance_oculus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp b/src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp new file mode 100644 index 00000000000..685583532d5 --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2006 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +#define GOSSIP_ITEM_DRAKES "So where do we go from here?" +#define GOSSIP_ITEM_BELGARISTRASZ1 "I want to fly on the wings of the Red Flight" +#define GOSSIP_ITEM_BELGARISTRASZ2 "What abilities do Ruby Drakes have?" +#define GOSSIP_ITEM_VERDISA1 "I want to fly on the wings of the Green Flight" +#define GOSSIP_ITEM_VERDISA2 "What abilities do Emerald Drakes have?" +#define GOSSIP_ITEM_ETERNOS1 "I want to fly on the wings of the Bronze Flight" +#define GOSSIP_ITEM_ETERNOS2 "What abilities do Amber Drakes have?" + +#define HAS_ESSENCE(a) ((a)->HasItemCount(ITEM_EMERALD_ESSENCE,1) || (a)->HasItemCount(ITEM_AMBER_ESSENCE,1) || (a)->HasItemCount(ITEM_RUBY_ESSENCE,1)) + +enum Drakes +{ + GOSSIP_TEXTID_DRAKES = 13267, + GOSSIP_TEXTID_BELGARISTRASZ1 = 12916, + GOSSIP_TEXTID_BELGARISTRASZ2 = 13466, + GOSSIP_TEXTID_BELGARISTRASZ3 = 13254, + GOSSIP_TEXTID_VERDISA1 = 1, + GOSSIP_TEXTID_VERDISA2 = 1, + GOSSIP_TEXTID_VERDISA3 = 1, + GOSSIP_TEXTID_ETERNOS1 = 1, + GOSSIP_TEXTID_ETERNOS2 = 1, + GOSSIP_TEXTID_ETERNOS3 = 13256, + + ITEM_EMERALD_ESSENCE = 37815, + ITEM_AMBER_ESSENCE = 37859, + ITEM_RUBY_ESSENCE = 37860, + + NPC_VERDISA = 27657, + NPC_BELGARISTRASZ = 27658, + NPC_ETERNOS = 27659 +}; + +bool GossipHello_npc_oculus_drake(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->GetInstanceData()->GetData(DATA_DRAKOS_EVENT) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DRAKES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DRAKES, pCreature->GetGUID()); + } + + return true; +} + +bool GossipSelect_npc_oculus_drake(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(pCreature->GetEntry()) + { + case NPC_VERDISA: //Verdisa + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_EMERALD_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_EMERALD_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA3, pCreature->GetGUID()); + break; + } + break; + case NPC_BELGARISTRASZ: //Belgaristrasz + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_RUBY_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_RUBY_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ3, pCreature->GetGUID()); + break; + } + break; + case NPC_ETERNOS: //Eternos + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_AMBER_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_AMBER_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS3, pCreature->GetGUID()); + break; + } + break; + } + + return true; +} + +void AddSC_oculus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_oculus_drake"; + newscript->pGossipHello = &GossipHello_npc_oculus_drake; + newscript->pGossipSelect = &GossipSelect_npc_oculus_drake; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/oculus.h b/src/server/scripts/Northrend/TheNexus/oculus/oculus.h new file mode 100644 index 00000000000..b212c9b8b6a --- /dev/null +++ b/src/server/scripts/Northrend/TheNexus/oculus/oculus.h @@ -0,0 +1,34 @@ +#ifndef DEF_OCULUS_H +#define DEF_OCULUS_H + +enum Data +{ + DATA_DRAKOS_EVENT, + DATA_VAROS_EVENT, + DATA_UROM_EVENT, + DATA_EREGOS_EVENT, + DATA_UROM_PLATAFORM +}; + +enum Data64 +{ + DATA_DRAKOS, + DATA_VAROS, + DATA_UROM, + DATA_EREGOS +}; + +enum Bosses +{ + CREATURE_DRAKOS = 27654, + CREATURE_VAROS = 27447, + CREATURE_UROM = 27655, + CREATURE_EREGOS = 27656 +}; + +enum GameObjects +{ + GO_DRAGON_CAGE_DOOR = 193995 +}; + +#endif diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp new file mode 100644 index 00000000000..c2da2a24e71 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp @@ -0,0 +1,432 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss General Bjarngrim +SD%Complete: 70% +SDComment: Waypoint needed, we expect boss to always have 2x Stormforged Lieutenant following +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + //Yell + SAY_AGGRO = -1602000, + SAY_SLAY_1 = -1602001, + SAY_SLAY_2 = -1602002, + SAY_SLAY_3 = -1602003, + SAY_DEATH = -1602004, + SAY_BATTLE_STANCE = -1602005, + EMOTE_BATTLE_STANCE = -1602006, + SAY_BERSEKER_STANCE = -1602007, + EMOTE_BERSEKER_STANCE = -1602008, + SAY_DEFENSIVE_STANCE = -1602009, + EMOTE_DEFENSIVE_STANCE = -1602010, + + SPELL_DEFENSIVE_STANCE = 53790, + //SPELL_DEFENSIVE_AURA = 41105, + SPELL_SPELL_REFLECTION = 36096, + SPELL_PUMMEL = 12555, + SPELL_KNOCK_AWAY = 52029, + SPELL_IRONFORM = 52022, + + SPELL_BERSEKER_STANCE = 53791, + //SPELL_BERSEKER_AURA = 41107, + SPELL_INTERCEPT = 58769, + SPELL_WHIRLWIND = 52027, + SPELL_CLEAVE = 15284, + + SPELL_BATTLE_STANCE = 53792, + //SPELL_BATTLE_AURA = 41106, + SPELL_MORTAL_STRIKE = 16856, + SPELL_SLAM = 52026, + + //OTHER SPELLS + //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other + //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above + + NPC_STORMFORGED_LIEUTENANT = 29240, + SPELL_ARC_WELD = 59085, + SPELL_RENEW_STEEL_N = 52774, + SPELL_RENEW_STEEL_H = 59160, + + EQUIP_SWORD = 37871, + EQUIP_SHIELD = 35642, + EQUIP_MACE = 43623, + + STANCE_DEFENSIVE = 0, + STANCE_BERSERKER = 1, + STANCE_BATTLE = 2 +}; + +/*###### +## boss_bjarngrim +######*/ + +struct boss_bjarngrimAI : public ScriptedAI +{ + boss_bjarngrimAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + m_uiStance = STANCE_DEFENSIVE; + memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID)); + } + + ScriptedInstance* m_pInstance; + + bool m_bIsChangingStance; + + uint8 m_uiChargingStatus; + uint8 m_uiStance; + + uint32 m_uiCharge_Timer; + uint32 m_uiChangeStance_Timer; + + uint32 m_uiReflection_Timer; + uint32 m_uiKnockAway_Timer; + uint32 m_uiPummel_Timer; + uint32 m_uiIronform_Timer; + + uint32 m_uiIntercept_Timer; + uint32 m_uiWhirlwind_Timer; + uint32 m_uiCleave_Timer; + + uint32 m_uiMortalStrike_Timer; + uint32 m_uiSlam_Timer; + + uint64 m_auiStormforgedLieutenantGUID[2]; + + void Reset() + { + m_bIsChangingStance = false; + + m_uiChargingStatus = 0; + m_uiCharge_Timer = 1000; + + m_uiChangeStance_Timer = 20000 + rand()%5000; + + m_uiReflection_Timer = 8000; + m_uiKnockAway_Timer = 20000; + m_uiPummel_Timer = 10000; + m_uiIronform_Timer = 25000; + + m_uiIntercept_Timer = 5000; + m_uiWhirlwind_Timer = 10000; + m_uiCleave_Timer = 8000; + + m_uiMortalStrike_Timer = 8000; + m_uiSlam_Timer = 10000; + + for (uint8 i = 0; i < 2; ++i) + { + if (Creature* pStormforgedLieutenant = (Unit::GetCreature((*me), m_auiStormforgedLieutenantGUID[i]))) + { + if (!pStormforgedLieutenant->isAlive()) + pStormforgedLieutenant->Respawn(); + } + } + + if (m_uiStance != STANCE_DEFENSIVE) + { + DoRemoveStanceAura(m_uiStance); + DoCast(me, SPELL_DEFENSIVE_STANCE); + m_uiStance = STANCE_DEFENSIVE; + } + + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + //must get both lieutenants here and make sure they are with him + me->CallForHelp(30.0f); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, DONE); + } + + //TODO: remove when removal is done by the core + void DoRemoveStanceAura(uint8 uiStance) + { + switch(uiStance) + { + case STANCE_DEFENSIVE: + me->RemoveAurasDueToSpell(SPELL_DEFENSIVE_STANCE); + break; + case STANCE_BERSERKER: + me->RemoveAurasDueToSpell(SPELL_BERSEKER_STANCE); + break; + case STANCE_BATTLE: + me->RemoveAurasDueToSpell(SPELL_BATTLE_STANCE); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // Change stance + if (m_uiChangeStance_Timer <= uiDiff) + { + //wait for current spell to finish before change stance + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoRemoveStanceAura(m_uiStance); + + int uiTempStance = rand()%(3-1); + + if (uiTempStance >= m_uiStance) + ++uiTempStance; + + m_uiStance = uiTempStance; + + switch(m_uiStance) + { + case STANCE_DEFENSIVE: + DoScriptText(SAY_DEFENSIVE_STANCE, me); + DoScriptText(EMOTE_DEFENSIVE_STANCE, me); + DoCast(me, SPELL_DEFENSIVE_STANCE); + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); + break; + case STANCE_BERSERKER: + DoScriptText(SAY_BERSEKER_STANCE, me); + DoScriptText(EMOTE_BERSEKER_STANCE, me); + DoCast(me, SPELL_BERSEKER_STANCE); + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); + break; + case STANCE_BATTLE: + DoScriptText(SAY_BATTLE_STANCE, me); + DoScriptText(EMOTE_BATTLE_STANCE, me); + DoCast(me, SPELL_BATTLE_STANCE); + SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + break; + } + + m_uiChangeStance_Timer = 20000 + rand()%5000; + return; + } + else + m_uiChangeStance_Timer -= uiDiff; + + switch(m_uiStance) + { + case STANCE_DEFENSIVE: + { + if (m_uiReflection_Timer <= uiDiff) + { + DoCast(me, SPELL_SPELL_REFLECTION); + m_uiReflection_Timer = 8000 + rand()%1000; + } + else + m_uiReflection_Timer -= uiDiff; + + if (m_uiKnockAway_Timer <= uiDiff) + { + DoCast(me, SPELL_KNOCK_AWAY); + m_uiKnockAway_Timer = 20000 + rand()%1000; + } + else + m_uiKnockAway_Timer -= uiDiff; + + if (m_uiPummel_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_PUMMEL); + m_uiPummel_Timer = 10000 + rand()%1000; + } + else + m_uiPummel_Timer -= uiDiff; + + if (m_uiIronform_Timer <= uiDiff) + { + DoCast(me, SPELL_IRONFORM); + m_uiIronform_Timer = 25000 + rand()%1000; + } + else + m_uiIronform_Timer -= uiDiff; + + break; + } + case STANCE_BERSERKER: + { + if (m_uiIntercept_Timer <= uiDiff) + { + //not much point is this, better random target and more often? + DoCast(me->getVictim(), SPELL_INTERCEPT); + m_uiIntercept_Timer = 45000 + rand()%1000; + } + else + m_uiIntercept_Timer -= uiDiff; + + if (m_uiWhirlwind_Timer <= uiDiff) + { + DoCast(me, SPELL_WHIRLWIND); + m_uiWhirlwind_Timer = 10000 + rand()%1000; + } + else + m_uiWhirlwind_Timer -= uiDiff; + + if (m_uiCleave_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + m_uiCleave_Timer = 8000 + rand()%1000; + } + else + m_uiCleave_Timer -= uiDiff; + + break; + } + case STANCE_BATTLE: + { + if (m_uiMortalStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + m_uiMortalStrike_Timer = 20000 + rand()%1000; + } + else + m_uiMortalStrike_Timer -= uiDiff; + + if (m_uiSlam_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SLAM); + m_uiSlam_Timer = 15000 + rand()%1000; + } + else + m_uiSlam_Timer -= uiDiff; + + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## mob_stormforged_lieutenant +######*/ + +struct mob_stormforged_lieutenantAI : public ScriptedAI +{ + mob_stormforged_lieutenantAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiArcWeld_Timer; + uint32 m_uiRenewSteel_Timer; + + void Reset() + { + m_uiArcWeld_Timer = 20000 + rand()%1000; + m_uiRenewSteel_Timer = 10000 + rand()%1000; + } + + void EnterCombat(Unit* pWho) + { + if (m_pInstance) + { + if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) + { + if (pBjarngrim->isAlive() && !pBjarngrim->getVictim()) + pBjarngrim->AI()->AttackStart(pWho); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_uiArcWeld_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_ARC_WELD); + m_uiArcWeld_Timer = 20000 + rand()%1000; + } + else + m_uiArcWeld_Timer -= uiDiff; + + if (m_uiRenewSteel_Timer <= uiDiff) + { + if (m_pInstance) + { + if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) + { + if (pBjarngrim->isAlive()) + DoCast(pBjarngrim, SPELL_RENEW_STEEL_N); + } + } + m_uiRenewSteel_Timer = 10000 + rand()%4000; + } + else + m_uiRenewSteel_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bjarngrim(Creature* pCreature) +{ + return new boss_bjarngrimAI(pCreature); +} + +CreatureAI* GetAI_mob_stormforged_lieutenant(Creature* pCreature) +{ + return new mob_stormforged_lieutenantAI(pCreature); +} + +void AddSC_boss_bjarngrim() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_bjarngrim"; + newscript->GetAI = &GetAI_boss_bjarngrim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stormforged_lieutenant"; + newscript->GetAI = &GetAI_mob_stormforged_lieutenant; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp new file mode 100644 index 00000000000..ecf61188b3e --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp @@ -0,0 +1,388 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: Timer check pending + */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum Spells +{ + SPELL_BALL_LIGHTNING = 52780, + H_SPELL_BALL_LIGHTNING = 59800, + SPELL_STATIC_OVERLOAD = 52658, + H_SPELL_STATIC_OVERLOAD = 59795, + + SPELL_DISPERSE = 52770, + SPELL_SUMMON_SPARK = 52746, + SPELL_SPARK_DESPAWN = 52776, + + //Spark of Ionar + SPELL_SPARK_VISUAL_TRIGGER = 52667, + H_SPELL_SPARK_VISUAL_TRIGGER = 59833 +}; + +enum Yells +{ + SAY_AGGRO = -1602011, + SAY_SLAY_1 = -1602012, + SAY_SLAY_2 = -1602013, + SAY_SLAY_3 = -1602014, + SAY_DEATH = -1602015, + SAY_SPLIT_1 = -1602016, + SAY_SPLIT_2 = -1602017 +}; + +enum Creatures +{ + NPC_SPARK_OF_IONAR = 28926 +}; + +enum Misc +{ + DATA_MAX_SPARKS = 5, + DATA_MAX_SPARK_DISTANCE = 90, // Distance to boss - prevent runs through the whole instance + DATA_POINT_CALLBACK = 0 +}; + +/*###### +## Boss Ionar +######*/ + +struct boss_ionarAI : public ScriptedAI +{ + boss_ionarAI(Creature *pCreature) : ScriptedAI(pCreature), lSparkList(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + SummonList lSparkList; + + bool bIsSplitPhase; + bool bHasDispersed; + + uint32 uiSplitTimer; + + uint32 uiStaticOverloadTimer; + uint32 uiBallLightningTimer; + + uint32 uiDisperseHealth; + + void Reset() + { + lSparkList.DespawnAll(); + + bIsSplitPhase = true; + bHasDispersed = false; + + uiSplitTimer = 25*IN_MILISECONDS; + + uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); + uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); + + uiDisperseHealth = 45 + urand(0,10); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + if (me->GetVisibility() == VISIBILITY_OFF) + me->SetVisibility(VISIBILITY_ON); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + lSparkList.DespawnAll(); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + //make sparks come back + void CallBackSparks() + { + //should never be empty here, but check + if (lSparkList.empty()) + return; + + Position pos; + me->GetPosition(&pos); + + for (std::list::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) + { + if (Creature* pSpark = Unit::GetCreature(*me, *itr)) + { + if (pSpark->isAlive()) + { + pSpark->SetSpeed(MOVE_RUN, 2.0f); + pSpark->GetMotionMaster()->Clear(); + pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); + } + else + pSpark->ForcedDespawn(); + } + } + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + if (me->GetVisibility() == VISIBILITY_OFF) + uiDamage = 0; + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) + { + lSparkList.Summon(pSummoned); + + pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER,H_SPELL_SPARK_VISUAL_TRIGGER), true); + + Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + pSummoned->SetInCombatWith(pTarget); + pSummoned->GetMotionMaster()->Clear(); + pSummoned->GetMotionMaster()->MoveFollow(pTarget, 0.0f, 0.0f); + } + } + } + + void SummonedCreatureDespawn(Creature *pSummoned) + { + if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) + lSparkList.Despawn(pSummoned); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // Splitted + if (me->GetVisibility() == VISIBILITY_OFF) + { + if (uiSplitTimer <= uiDiff) + { + uiSplitTimer = 2.5*IN_MILISECONDS; + + // Return sparks to where Ionar splitted + if (bIsSplitPhase) + { + CallBackSparks(); + bIsSplitPhase = false; + } + // Lightning effect and restore Ionar + else if (lSparkList.empty()) + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + DoCast(me, SPELL_SPARK_DESPAWN, false); + + uiSplitTimer = 25*IN_MILISECONDS; + bIsSplitPhase = true; + + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + } + else + uiSplitTimer -= uiDiff; + + return; + } + + if (uiStaticOverloadTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_STATIC_OVERLOAD); + + uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); + } + else + uiStaticOverloadTimer -= uiDiff; + + if (uiBallLightningTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); + uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); + } + else + uiBallLightningTimer -= uiDiff; + + // Health check + if (!bHasDispersed && HealthBelowPct(uiDisperseHealth)) + { + bHasDispersed = true; + + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me, SPELL_DISPERSE, true); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ionar(Creature* pCreature) +{ + return new boss_ionarAI(pCreature); +} + +bool EffectDummyCreature_boss_ionar(Unit* /*pCaster*/, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_DISPERSE && uiEffIndex == 0) + { + if (pCreatureTarget->GetEntry() != NPC_IONAR) + return true; + + for (uint8 i = 0; i < DATA_MAX_SPARKS; ++i) + pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true); + + pCreatureTarget->AttackStop(); + pCreatureTarget->SetVisibility(VISIBILITY_OFF); + pCreatureTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + pCreatureTarget->GetMotionMaster()->Clear(); + pCreatureTarget->GetMotionMaster()->MoveIdle(); + + //always return true when we are handling this spell and effect + return true; + } + return false; +} + +/*###### +## mob_spark_of_ionar +######*/ + +struct mob_spark_of_ionarAI : public ScriptedAI +{ + mob_spark_of_ionarAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCheckTimer; + + void Reset() + { + uiCheckTimer = 2*IN_MILISECONDS; + me->SetReactState(REACT_PASSIVE); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE || !pInstance) + return; + + if (uiPointId == DATA_POINT_CALLBACK) + me->ForcedDespawn(); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + uiDamage = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + // Despawn if the encounter is not running + if (pInstance && pInstance->GetData(TYPE_IONAR) != IN_PROGRESS) + { + me->ForcedDespawn(); + return; + } + + // Prevent them to follow players through the whole instance + if (uiCheckTimer <= uiDiff) + { + if (pInstance) + { + Creature* pIonar = pInstance->instance->GetCreature(pInstance->GetData64(DATA_IONAR)); + if (pIonar && pIonar->isAlive()) + { + if (me->GetDistance(pIonar) > DATA_MAX_SPARK_DISTANCE) + { + Position pos; + pIonar->GetPosition(&pos); + + me->SetSpeed(MOVE_RUN, 2.0f); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); + } + } + else + me->ForcedDespawn(); + } + uiCheckTimer = 2*IN_MILISECONDS; + } + else + uiCheckTimer -= uiDiff; + + // No melee attack at all! + } +}; + +CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature) +{ + return new mob_spark_of_ionarAI(pCreature); +} + +void AddSC_boss_ionar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ionar"; + newscript->GetAI = &GetAI_boss_ionar; + newscript->pEffectDummyCreature = &EffectDummyCreature_boss_ionar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_spark_of_ionar"; + newscript->GetAI = &GetAI_mob_spark_of_ionar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp new file mode 100644 index 00000000000..f08c19efca2 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp @@ -0,0 +1,222 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Loken +SD%Complete: 60% +SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414) +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + ACHIEV_TIMELY_DEATH_START_EVENT = 20384, + + SAY_AGGRO = -1602018, + SAY_INTRO_1 = -1602019, + SAY_INTRO_2 = -1602020, + SAY_SLAY_1 = -1602021, + SAY_SLAY_2 = -1602022, + SAY_SLAY_3 = -1602023, + SAY_DEATH = -1602024, + SAY_NOVA_1 = -1602025, + SAY_NOVA_2 = -1602026, + SAY_NOVA_3 = -1602027, + SAY_75HEALTH = -1602028, + SAY_50HEALTH = -1602029, + SAY_25HEALTH = -1602030, + EMOTE_NOVA = -1602031, + + SPELL_ARC_LIGHTNING = 52921, + SPELL_LIGHTNING_NOVA_N = 52960, + SPELL_LIGHTNING_NOVA_H = 59835, + + SPELL_PULSING_SHOCKWAVE_N = 52961, + SPELL_PULSING_SHOCKWAVE_H = 59836, + SPELL_PULSING_SHOCKWAVE_AURA = 59414 +}; + +/*###### +## Boss Loken +######*/ + +struct boss_lokenAI : public ScriptedAI +{ + boss_lokenAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + bool m_bIsAura; + + uint32 m_uiArcLightning_Timer; + uint32 m_uiLightningNova_Timer; + uint32 m_uiPulsingShockwave_Timer; + uint32 m_uiResumePulsingShockwave_Timer; + + uint32 m_uiHealthAmountModifier; + + void Reset() + { + m_bIsAura = false; + + m_uiArcLightning_Timer = 15000; + m_uiLightningNova_Timer = 20000; + m_uiPulsingShockwave_Timer = 2000; + m_uiResumePulsingShockwave_Timer = 15000; + + m_uiHealthAmountModifier = 1; + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS); + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); + } + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_LOKEN, DONE); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_bIsAura) + { + // workaround for PULSING_SHOCKWAVE + if (m_uiPulsingShockwave_Timer <= uiDiff) + { + Map* pMap = me->GetMap(); + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack()) + { + int32 dmg; + float m_fDist = me->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()); + + dmg = DUNGEON_MODE(100, 150); // need to correct damage + if (m_fDist > 1.0f) // Further from 1 yard + dmg *= m_fDist; + + me->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false); + } + } + m_uiPulsingShockwave_Timer = 2000; + } else m_uiPulsingShockwave_Timer -= uiDiff; + } + else + { + if (m_uiResumePulsingShockwave_Timer <= uiDiff) + { + //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement? + DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); + + DoCast(me, SPELL_PULSING_SHOCKWAVE_N); // need core support + m_bIsAura = true; + m_uiResumePulsingShockwave_Timer = 0; + } + else + m_uiResumePulsingShockwave_Timer -= uiDiff; + } + + if (m_uiArcLightning_Timer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ARC_LIGHTNING); + + m_uiArcLightning_Timer = 15000 + rand()%1000; + } + else + m_uiArcLightning_Timer -= uiDiff; + + if (m_uiLightningNova_Timer <= uiDiff) + { + DoScriptText(RAND(SAY_NOVA_1,SAY_NOVA_2,SAY_NOVA_3), me); + DoScriptText(EMOTE_NOVA, me); + DoCast(me, SPELL_LIGHTNING_NOVA_N); + + m_bIsAura = false; + m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura + m_uiLightningNova_Timer = 20000 + rand()%1000; + } + else + m_uiLightningNova_Timer -= uiDiff; + + // Health check + if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(25*m_uiHealthAmountModifier))) + { + switch(m_uiHealthAmountModifier) + { + case 1: DoScriptText(SAY_75HEALTH, me); break; + case 2: DoScriptText(SAY_50HEALTH, me); break; + case 3: DoScriptText(SAY_25HEALTH, me); break; + } + + ++m_uiHealthAmountModifier; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_loken(Creature* pCreature) +{ + return new boss_lokenAI(pCreature); +} + +void AddSC_boss_loken() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_loken"; + newscript->GetAI = &GetAI_boss_loken; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp new file mode 100644 index 00000000000..184050e3103 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp @@ -0,0 +1,478 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Volkhan +SD%Complete: 60% +SDComment: Not considered complete. Some events may fail and need further development +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + SAY_AGGRO = -1602032, + SAY_SLAY_1 = -1602033, + SAY_SLAY_2 = -1602034, + SAY_SLAY_3 = -1602035, + SAY_DEATH = -1602036, + SAY_STOMP_1 = -1602037, + SAY_STOMP_2 = -1602038, + SAY_FORGE_1 = -1602039, + SAY_FORGE_2 = -1602040, + EMOTE_TO_ANVIL = -1602041, + EMOTE_SHATTER = -1602042, + + SPELL_HEAT_N = 52387, + SPELL_HEAT_H = 59528, + SPELL_SHATTERING_STOMP_N = 52237, + SPELL_SHATTERING_STOMP_H = 59529, + + //unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on: + SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil + SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss + + //SPELL_TEMPER_VISUAL = 52661, //summons GO + + SPELL_SUMMON_MOLTEN_GOLEM = 52405, + + //Molten Golem + SPELL_BLAST_WAVE = 23113, + SPELL_IMMOLATION_STRIKE_N = 52433, + SPELL_IMMOLATION_STRIKE_H = 59530, + SPELL_SHATTER_N = 52429, + SPELL_SHATTER_H = 59527, + + NPC_VOLKHAN_ANVIL = 28823, + NPC_MOLTEN_GOLEM = 28695, + NPC_BRITTLE_GOLEM = 28681, + + POINT_ID_ANVIL = 0, + MAX_GOLEM = 2, + + ACHIEVEMENT_SHATTER_RESISTANT = 2042 +}; + +/*###### +## Boss Volkhan +######*/ + +struct boss_volkhanAI : public ScriptedAI +{ + boss_volkhanAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + std::list m_lGolemGUIDList; + + bool m_bHasTemper; + bool m_bIsStriking; + bool m_bCanShatterGolem; + + uint8 GolemsShattered; + uint32 m_uiPause_Timer; + uint32 m_uiShatteringStomp_Timer; + uint32 m_uiShatter_Timer; + + uint32 m_uiHealthAmountModifier; + + void Reset() + { + m_bIsStriking = false; + m_bHasTemper = false; + m_bCanShatterGolem = false; + + m_uiPause_Timer = 3500; + m_uiShatteringStomp_Timer = 0; + m_uiShatter_Timer = 5000; + GolemsShattered = 0; + + m_uiHealthAmountModifier = 1; + + DespawnGolem(); + m_lGolemGUIDList.clear(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); + } + + void AttackStart(Unit* pWho) + { + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + if (!m_bHasTemper) + me->GetMotionMaster()->MoveChase(pWho); + } + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + DespawnGolem(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, DONE); + + if (IsHeroic() && GolemsShattered < 5) + { + AchievementEntry const *AchievShatterResistant = GetAchievementStore()->LookupEntry(ACHIEVEMENT_SHATTER_RESISTANT); + if (AchievShatterResistant) + { + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievShatterResistant); + } + } + } + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void DespawnGolem() + { + if (m_lGolemGUIDList.empty()) + return; + + for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + } + + m_lGolemGUIDList.clear(); + } + + void ShatterGolem() + { + if (m_lGolemGUIDList.empty()) + return; + + for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + // only shatter brittle golems + if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM) + { + pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false); + GolemsShattered += 1; + } + } + } + } + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_TEMPER_DUMMY) + m_bIsStriking = true; + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_MOLTEN_GOLEM) + { + m_lGolemGUIDList.push_back(pSummoned->GetGUID()); + + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + + //why healing when just summoned? + pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, me->GetGUID()); + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_bIsStriking) + { + if (m_uiPause_Timer <= uiDiff) + { + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + { + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + + m_bHasTemper = false; + m_bIsStriking = false; + m_uiPause_Timer = 3500; + } + else + m_uiPause_Timer -= uiDiff; + + return; + } + + // When to start shatter? After 60, 40 or 20% hp? + if (!m_bHasTemper && m_uiHealthAmountModifier >= 3) + { + if (m_uiShatteringStomp_Timer <= uiDiff) + { + //should he stomp even if he has no brittle golem to shatter? + + DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2), me); + + DoCast(me, SPELL_SHATTERING_STOMP_N); + + DoScriptText(EMOTE_SHATTER, me); + + m_uiShatteringStomp_Timer = 30000; + m_bCanShatterGolem = true; + } + else + m_uiShatteringStomp_Timer -= uiDiff; + } + + // Shatter Golems 3 seconds after Shattering Stomp + if (m_bCanShatterGolem) + { + if (m_uiShatter_Timer <= uiDiff) + { + ShatterGolem(); + m_uiShatter_Timer = 3000; + m_bCanShatterGolem = false; + } + else + m_uiShatter_Timer -= uiDiff; + } + + // Health check + if (!m_bCanShatterGolem && (me->GetHealth()*100 / me->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier))) + { + ++m_uiHealthAmountModifier; + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoScriptText(RAND(SAY_FORGE_1,SAY_FORGE_2), me); + + m_bHasTemper = true; + + DoCast(me, SPELL_TEMPER, false); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_volkhan(Creature* pCreature) +{ + return new boss_volkhanAI(pCreature); +} + +bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_TEMPER_DUMMY && uiEffIndex == 0) + { + if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN) + return true; + + for (uint8 i = 0; i < MAX_GOLEM; ++i) + { + pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true); + } + + //always return true when we are handling this spell and effect + return true; + } + + return false; +} + +/*###### +## npc_volkhan_anvil +######*/ + +bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_TEMPER && uiEffIndex == 0) + { + if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL) + return true; + + Creature *cre = CAST_CRE(pCaster); + + DoScriptText(EMOTE_TO_ANVIL, pCaster); + + float fX, fY, fZ; + pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE); + + pCaster->AttackStop(); + + if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + pCaster->GetMotionMaster()->MovementExpired(); + + cre->GetMap()->CreatureRelocation(cre, fX, fY, fZ, pCreatureTarget->GetOrientation()); + cre->SendMonsterMove(fX, fY, fZ, 0, cre->GetUnitMovementFlags(), 1); + + pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); + + //always return true when we are handling this spell and effect + return true; + } + + return false; +} + +/*###### +## mob_molten_golem +######*/ + +struct mob_molten_golemAI : public ScriptedAI +{ + mob_molten_golemAI(Creature *pCreature) : ScriptedAI(pCreature) + { + } + + bool m_bIsFrozen; + + uint32 m_uiBlast_Timer; + uint32 m_uiDeathDelay_Timer; + uint32 m_uiImmolation_Timer; + + void Reset() + { + m_bIsFrozen = false; + + m_uiBlast_Timer = 20000; + m_uiDeathDelay_Timer = 0; + m_uiImmolation_Timer = 5000; + } + + void AttackStart(Unit* pWho) + { + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + if (!m_bIsFrozen) + me->GetMotionMaster()->MoveChase(pWho); + } + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) + { + if (uiDamage > me->GetHealth()) + { + me->UpdateEntry(NPC_BRITTLE_GOLEM); + me->SetHealth(1); + uiDamage = 0; + me->RemoveAllAuras(); + me->AttackStop(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + m_bIsFrozen = true; + } + } + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + //this is the dummy effect of the spells + if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H) + { + if (me->GetEntry() == NPC_BRITTLE_GOLEM) + me->ForcedDespawn(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target or if we are frozen + if (!UpdateVictim() || m_bIsFrozen) + return; + + if (m_uiBlast_Timer <= uiDiff) + { + DoCast(me, SPELL_BLAST_WAVE); + m_uiBlast_Timer = 20000; + } + else + m_uiBlast_Timer -= uiDiff; + + if (m_uiImmolation_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_IMMOLATION_STRIKE_N); + m_uiImmolation_Timer = 5000; + } + else + m_uiImmolation_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_molten_golem(Creature* pCreature) +{ + return new mob_molten_golemAI(pCreature); +} + +void AddSC_boss_volkhan() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_volkhan"; + newscript->GetAI = &GetAI_boss_volkhan; + newscript->pEffectDummyCreature = &EffectDummyCreature_boss_volkhan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_volkhan_anvil"; + newscript->pEffectDummyCreature = &EffectDummyCreature_npc_volkhan_anvil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_molten_golem"; + newscript->GetAI = &GetAI_mob_molten_golem; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h new file mode 100644 index 00000000000..d9739fdf888 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_HALLS_OF_LIGHTNING_H +#define DEF_HALLS_OF_LIGHTNING_H + +enum eTypes +{ + MAX_ENCOUNTER = 4, + + DATA_BJARNGRIM = 1, + DATA_IONAR = 2, + DATA_LOKEN = 3, + DATA_VOLKHAN = 4, + + TYPE_BJARNGRIM = 10, + TYPE_IONAR = 11, + TYPE_LOKEN = 12, + TYPE_VOLKHAN = 13, + + NPC_BJARNGRIM = 28586, + NPC_VOLKHAN = 28587, + NPC_IONAR = 28546, + NPC_LOKEN = 28923, + + GO_BJARNGRIM_DOOR = 191416, //_doors10 + GO_VOLKHAN_DOOR = 191325, //_doors07 + GO_IONAR_DOOR = 191326, //_doors05 + GO_LOKEN_DOOR = 191324, //_doors02 + GO_LOKEN_THRONE = 192654 +}; + +#endif diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp new file mode 100644 index 00000000000..46cd5c9cccc --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp @@ -0,0 +1,248 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Halls_of_Lightning +SD%Complete: 90% +SDComment: All ready. +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +/* Halls of Lightning encounters: +0 - General Bjarngrim +1 - Volkhan +2 - Ionar +3 - Loken +*/ + +struct instance_halls_of_lightning : public ScriptedInstance +{ + instance_halls_of_lightning(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 m_uiGeneralBjarngrimGUID; + uint64 m_uiIonarGUID; + uint64 m_uiLokenGUID; + uint64 m_uiVolkhanGUID; + + uint64 m_uiBjarngrimDoorGUID; + uint64 m_uiVolkhanDoorGUID; + uint64 m_uiIonarDoorGUID; + uint64 m_uiLokenDoorGUID; + uint64 m_uiLokenGlobeGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiGeneralBjarngrimGUID = 0; + m_uiVolkhanGUID = 0; + m_uiIonarGUID = 0; + m_uiLokenGUID = 0; + + m_uiBjarngrimDoorGUID = 0; + m_uiVolkhanDoorGUID = 0; + m_uiIonarDoorGUID = 0; + m_uiLokenDoorGUID = 0; + m_uiLokenGlobeGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_BJARNGRIM: + m_uiGeneralBjarngrimGUID = pCreature->GetGUID(); + break; + case NPC_VOLKHAN: + m_uiVolkhanGUID = pCreature->GetGUID(); + break; + case NPC_IONAR: + m_uiIonarGUID = pCreature->GetGUID(); + break; + case NPC_LOKEN: + m_uiLokenGUID = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_BJARNGRIM_DOOR: + m_uiBjarngrimDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_VOLKHAN_DOOR: + m_uiVolkhanDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_IONAR_DOOR: + m_uiIonarDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_LOKEN_DOOR: + m_uiLokenDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_LOKEN_THRONE: + m_uiLokenGlobeGUID = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_BJARNGRIM: + if (uiData == DONE) + DoUseDoorOrButton(m_uiBjarngrimDoorGUID); + m_auiEncounter[0] = uiData; + break; + case TYPE_VOLKHAN: + if (uiData == DONE) + DoUseDoorOrButton(m_uiVolkhanDoorGUID); + m_auiEncounter[1] = uiData; + break; + case TYPE_IONAR: + if (uiData == DONE) + DoUseDoorOrButton(m_uiIonarDoorGUID); + m_auiEncounter[2] = uiData; + break; + case TYPE_LOKEN: + if (uiData == DONE) + { + DoUseDoorOrButton(m_uiLokenDoorGUID); + + //Appears to be type 5 GO with animation. Need to figure out how this work, code below only placeholder + if (GameObject* pGlobe = instance->GetGameObject(m_uiLokenGlobeGUID)) + pGlobe->SetGoState(GO_STATE_ACTIVE); + } + m_auiEncounter[3] = uiData; + break; + } + + if (uiData == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_BJARNGRIM: + return m_auiEncounter[0]; + case TYPE_VOLKHAN: + return m_auiEncounter[1]; + case TYPE_IONAR: + return m_auiEncounter[2]; + case TYPE_LOKEN: + return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_BJARNGRIM: + return m_uiGeneralBjarngrimGUID; + case DATA_VOLKHAN: + return m_uiVolkhanGUID; + case DATA_IONAR: + return m_uiIonarGUID; + case DATA_LOKEN: + return m_uiLokenGUID; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H L " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'H' && dataHead2 == 'L') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_halls_of_lightning(Map* pMap) +{ + return new instance_halls_of_lightning(pMap); +} + +void AddSC_instance_halls_of_lightning() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_lightning"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_lightning; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp new file mode 100644 index 00000000000..0674b7c79eb --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp @@ -0,0 +1,148 @@ +/* Script Data Start +SDName: Boss krystallus +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_krystallus' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_BOULDER_TOSS = 50843, + H_SPELL_BOULDER_TOSS = 59742, + SPELL_GROUND_SPIKE = 59750, + SPELL_GROUND_SLAM = 50827, + SPELL_SHATTER = 50810, + H_SPELL_SHATTER = 61546, + SPELL_STOMP = 48131, + H_SPELL_STOMP = 59744 +}; + +enum Yells +{ + SAY_AGGRO = -1599007, + SAY_KILL = -1599008, + SAY_DEATH = -1599009, + SAY_SHATTER = -1599010 +}; + +struct boss_krystallusAI : public ScriptedAI +{ + boss_krystallusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBoulderTossTimer; + uint32 uiGroundSpikeTimer; + uint32 uiGroundSlamTimer; + uint32 uiShatterTimer; + uint32 uiStompTimer; + + bool bIsSlam; + + ScriptedInstance* pInstance; + + void Reset() + { + bIsSlam = false; + + uiBoulderTossTimer = 3000 + rand()%6000; + uiGroundSpikeTimer = 9000 + rand()%5000; + uiGroundSlamTimer = 15000 + rand()%3000; + uiStompTimer = 20000 + rand()%9000; + uiShatterTimer = 0; + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, NOT_STARTED); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBoulderTossTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BOULDER_TOSS); + uiBoulderTossTimer = 9000 + rand()%6000; + } else uiBoulderTossTimer -= diff; + + if (uiGroundSpikeTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_GROUND_SPIKE); + uiGroundSpikeTimer = 12000 + rand()%5000; + } else uiGroundSpikeTimer -= diff; + + if (uiStompTimer <= diff) + { + DoCast(me, SPELL_STOMP); + uiStompTimer = 20000 + rand()%9000; + } else uiStompTimer -= diff; + + if (uiGroundSlamTimer <= diff) + { + DoCast(me, SPELL_GROUND_SLAM); + bIsSlam = true; + uiShatterTimer = 10000; + uiGroundSlamTimer = 15000 + rand()%3000; + } else uiGroundSlamTimer -= diff; + + if (bIsSlam) + { + if (uiShatterTimer <= diff) + { + DoCast(me, SPELL_SHATTER); + bIsSlam = false; + } else uiShatterTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(SAY_KILL, me); + } +}; + +CreatureAI* GetAI_boss_krystallus(Creature* pCreature) +{ + return new boss_krystallusAI (pCreature); +} + +void AddSC_boss_krystallus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_krystallus"; + newscript->GetAI = &GetAI_boss_krystallus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp new file mode 100644 index 00000000000..b3c3c675347 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp @@ -0,0 +1,166 @@ +/* Script Data Start +SDName: Boss maiden_of_grief +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_maiden_of_grief' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_PARTING_SORROW = 59723, + SPELL_STORM_OF_GRIEF_N = 50752, + SPELL_STORM_OF_GRIEF_H = 59772, + SPELL_SHOCK_OF_SORROW_N = 50760, + SPELL_SHOCK_OF_SORROW_H = 59726, + SPELL_PILLAR_OF_WOE_N = 50761, + SPELL_PILLAR_OF_WOE_H = 59727 +}; + +enum Yells +{ + SAY_AGGRO = -1599000, + SAY_SLAY_1 = -1599001, + SAY_SLAY_2 = -1599002, + SAY_SLAY_3 = -1599003, + SAY_SLAY_4 = -1599004, + SAY_DEATH = -1599005, + SAY_STUN = -1599006 +}; + +enum Achievements +{ + ACHIEV_GOOD_GRIEF_START_EVENT = 20383, +}; + +struct boss_maiden_of_griefAI : public ScriptedAI +{ + boss_maiden_of_griefAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 PartingSorrowTimer; + uint32 StormOfGriefTimer; + uint32 ShockOfSorrowTimer; + uint32 PillarOfWoeTimer; + + void Reset() + { + PartingSorrowTimer = 25000 + rand()%5000; + StormOfGriefTimer = 10000; + ShockOfSorrowTimer = 20000+rand()%5000; + PillarOfWoeTimer = 5000 + rand()%10000; + + if (pInstance) + { + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAIDEN_DOOR))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, IN_PROGRESS); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (IsHeroic()) + { + if (PartingSorrowTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget) + DoCast(pTarget, SPELL_PARTING_SORROW); + + PartingSorrowTimer = 30000 + rand()%10000; + } else PartingSorrowTimer -= diff; + } + + if (StormOfGriefTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STORM_OF_GRIEF_N, true); + StormOfGriefTimer = 15000 + rand()%5000; + } else StormOfGriefTimer -= diff; + + if (ShockOfSorrowTimer <= diff) + { + DoResetThreat(); + DoScriptText(SAY_STUN, me); + DoCast(me, SPELL_SHOCK_OF_SORROW_N); + ShockOfSorrowTimer = 20000 + rand()%10000; + } else ShockOfSorrowTimer -= diff; + + if (PillarOfWoeTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if (pTarget) + DoCast(pTarget, SPELL_PILLAR_OF_WOE_N); + else + DoCast(me->getVictim(), SPELL_PILLAR_OF_WOE_N); + + PillarOfWoeTimer = 5000 + rand()%20000; + } else PillarOfWoeTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } +}; + +CreatureAI* GetAI_boss_maiden_of_grief(Creature* pCreature) +{ + return new boss_maiden_of_griefAI (pCreature); +} + +void AddSC_boss_maiden_of_grief() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_maiden_of_grief"; + newscript->GetAI = &GetAI_boss_maiden_of_grief; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp new file mode 100644 index 00000000000..68c3e34e6bf --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp @@ -0,0 +1,300 @@ +/* Script Data Start +SDName: Boss sjonnir +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_sjonnir' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_LIGHTING_RING = 51849, //Periodic Trigger (interval 2s) spell = 50841 + H_SPELL_LIGHTING_RING = 59861, //Periodic Trigger (interval 2s) spell = 59849 + SPELL_LIGHTING_RING_1 = 50840, //Periodic Trigger (interval 2s) spell = 50841 + H_SPELL_LIGHTING_RING_1 = 59848, //Periodic Trigger (interval 2s) spell = 59849 + SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835 + H_SPELL_STATIC_CHARGE = 59846, //Periodic Trigger 2s interval, spell =50847 + SPELL_CHAIN_LIGHTING = 50830, + H_SPELL_CHAIN_LIGHTING = 59844, + SPELL_LIGHTING_SHIELD = 50831, + H_SPELL_LIGHTING_SHIELD = 59845, + SPELL_FRENZY = 28747 +}; + +enum Yells +{ + SAY_AGGRO = -1599011, + SAY_SLAY_1 = -1599012, + SAY_SLAY_2 = -1599013, + SAY_SLAY_3 = -1599014, + SAY_DEATH = -1599015 +}; + +#define EMOTE_GENERIC_FRENZY -1000002 + +enum SjonnirCreatures +{ + CREATURE_FORGED_IRON_TROGG = 27979, + CREATURE_MALFORMED_OOZE = 27981, + CREATURE_FORGED_IRON_DWARF = 27982, + CREATURE_IRON_SLUDGE = 28165 +}; + +enum Misc +{ + DATA_TIME_BEFORE_OOZE = 150000, //2min 30 secs + ACHIEV_ABUSE_THE_OOZE = 2155 +}; + +struct Locations +{ + float x, y, z; +}; + +static Locations PipeLocations[] = +{ + {1295.44, 734.07, 200.3}, //left + {1297.7, 595.6, 199.9} //right +}; + +static Locations CenterPoint = {1295.21, 667.157, 189.691}; + +struct boss_sjonnirAI : public ScriptedAI +{ + boss_sjonnirAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + bool bIsFrenzy; + + uint32 uiChainLightningTimer; + uint32 uiLightningShieldTimer; + uint32 uiStaticChargeTimer; + uint32 uiLightningRingTimer; + uint32 uiSummonTimer; + uint32 uiFrenzyTimer; + uint32 uiEncounterTimer; + uint32 uiKilledIronSludges; + + SummonList lSummons; + + ScriptedInstance* pInstance; + + void Reset() + { + bIsFrenzy = false; + + uiEncounterTimer = 0; + uiChainLightningTimer = 3000 + rand()%5000; + uiLightningShieldTimer = 20000 + rand()%5000; + uiStaticChargeTimer = 20000 + rand()%5000; + uiLightningRingTimer = 30000 + rand()%5000; + uiSummonTimer = 5000; + uiFrenzyTimer = 300000; //5 minutes + uiKilledIronSludges = 0; + + lSummons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_SJONNIR_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + uiEncounterTimer = 0; + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SJONNIR_DOOR))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + pInstance->SetData(DATA_SJONNIR_EVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiChainLightningTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CHAIN_LIGHTING); + uiChainLightningTimer = 10000 + rand()%5000; + } else uiChainLightningTimer -= diff; + + if (uiLightningShieldTimer <= diff) + { + DoCast(me, SPELL_LIGHTING_SHIELD); + uiLightningShieldTimer -= diff; + } + + if (uiStaticChargeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STATIC_CHARGE); + uiStaticChargeTimer = 20000 + rand()%5000; + } uiStaticChargeTimer -= diff; + + if (uiLightningRingTimer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_LIGHTING_RING); + uiLightningRingTimer = 30000 + rand()%5000; + } else uiLightningRingTimer -= diff; + + if (uiSummonTimer <= diff) + { + uint32 uiSummonPipe = rand()%2; + me->SummonCreature(uiEncounterTimer > DATA_TIME_BEFORE_OOZE ? CREATURE_MALFORMED_OOZE : + RAND(CREATURE_FORGED_IRON_DWARF,CREATURE_FORGED_IRON_TROGG), + PipeLocations[uiSummonPipe].x, PipeLocations[uiSummonPipe].y, PipeLocations[uiSummonPipe].z, 0.0f, + TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + uiSummonTimer = 20000; + } else uiSummonTimer -= diff; + + if (!bIsFrenzy) + { + if (uiFrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + bIsFrenzy = true; + } + else uiFrenzyTimer -= diff; + } + + uiEncounterTimer +=diff; + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* summon) + { + summon->GetMotionMaster()->MovePoint(0, CenterPoint.x, CenterPoint.y, CenterPoint.z); + /*if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + summon->AI()->AttackStart(pTarget);*/ + lSummons.Summon(summon); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + lSummons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_SJONNIR_EVENT, DONE); + if (IsHeroic() && uiKilledIronSludges > 4) + pInstance->DoCompleteAchievement(ACHIEV_ABUSE_THE_OOZE); + } + } + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void KilledIronSludge() + { + ++uiKilledIronSludges; + } +}; + +CreatureAI* GetAI_boss_sjonnir(Creature* pCreature) +{ + return new boss_sjonnirAI (pCreature); +} + +struct mob_malformed_oozeAI : public ScriptedAI +{ + mob_malformed_oozeAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiMergeTimer; + + void Reset() + { + uiMergeTimer = 10000; + } + + void UpdateAI(const uint32 diff) + { + if (uiMergeTimer <= diff) + { + if (Creature* pTemp = me->FindNearestCreature(CREATURE_MALFORMED_OOZE, 3.0f, true)) + { + DoSpawnCreature(CREATURE_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + pTemp->DisappearAndDie(); + me->DisappearAndDie(); + } + uiMergeTimer = 3000; + } else uiMergeTimer -= diff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_malformed_ooze(Creature* pCreature) +{ + return new mob_malformed_oozeAI(pCreature); +} + +struct mob_iron_sludgeAI : public ScriptedAI +{ + mob_iron_sludgeAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + if (Creature* pSjonnir = Unit::GetCreature(*me, pInstance->GetData64(DATA_SJONNIR))) + CAST_AI(boss_sjonnirAI, pSjonnir->AI())->KilledIronSludge(); + } +}; + +CreatureAI* GetAI_mob_iron_sludge(Creature* pCreature) +{ + return new mob_iron_sludgeAI(pCreature); +} + +void AddSC_boss_sjonnir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sjonnir"; + newscript->GetAI = &GetAI_boss_sjonnir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_malformed_ooze"; + newscript->GetAI = &GetAI_mob_malformed_ooze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_iron_sludge"; + newscript->GetAI = &GetAI_mob_iron_sludge; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp new file mode 100644 index 00000000000..8febdaab879 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp @@ -0,0 +1,724 @@ +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "halls_of_stone.h" + +enum Texts +{ + SAY_KILL_1 = -1599016, + SAY_KILL_2 = -1599017, + SAY_KILL_3 = -1599018, + SAY_LOW_HEALTH = -1599019, + SAY_DEATH = -1599020, + SAY_PLAYER_DEATH_1 = -1599021, + SAY_PLAYER_DEATH_2 = -1599022, + SAY_PLAYER_DEATH_3 = -1599023, + SAY_ESCORT_START = -1599024, + + SAY_SPAWN_DWARF = -1599025, + SAY_SPAWN_TROGG = -1599026, + SAY_SPAWN_OOZE = -1599027, + SAY_SPAWN_EARTHEN = -1599028, + + SAY_EVENT_INTRO_1 = -1599029, + SAY_EVENT_INTRO_2 = -1599030, + SAY_EVENT_INTRO_3_ABED = -1599031, + + SAY_EVENT_A_1 = -1599032, + SAY_EVENT_A_2_KADD = -1599033, + SAY_EVENT_A_3 = -1599034, + + SAY_EVENT_B_1 = -1599035, + SAY_EVENT_B_2_MARN = -1599036, + SAY_EVENT_B_3 = -1599037, + + SAY_EVENT_C_1 = -1599038, + SAY_EVENT_C_2_ABED = -1599039, + SAY_EVENT_C_3 = -1599040, + + SAY_EVENT_D_1 = -1599041, + SAY_EVENT_D_2_ABED = -1599042, + SAY_EVENT_D_3 = -1599043, + SAY_EVENT_D_4_ABED = -1599044, + + SAY_EVENT_END_01 = -1599045, + SAY_EVENT_END_02 = -1599046, + SAY_EVENT_END_03_ABED = -1599047, + SAY_EVENT_END_04 = -1599048, + SAY_EVENT_END_05_ABED = -1599049, + SAY_EVENT_END_06 = -1599050, + SAY_EVENT_END_07_ABED = -1599051, + SAY_EVENT_END_08 = -1599052, + SAY_EVENT_END_09_KADD = -1599053, + SAY_EVENT_END_10 = -1599054, + SAY_EVENT_END_11_KADD = -1599055, + SAY_EVENT_END_12 = -1599056, + SAY_EVENT_END_13_KADD = -1599057, + SAY_EVENT_END_14 = -1599058, + SAY_EVENT_END_15_MARN = -1599059, + SAY_EVENT_END_16 = -1599060, + SAY_EVENT_END_17_MARN = -1599061, + SAY_EVENT_END_18 = -1599062, + SAY_EVENT_END_19_MARN = -1599063, + SAY_EVENT_END_20 = -1599064, + SAY_EVENT_END_21_ABED = -1599065, + + SAY_VICTORY_SJONNIR_1 = -1599066, + SAY_VICTORY_SJONNIR_2 = -1599067, + + SAY_ENTRANCE_MEET = -1599068, + + TEXT_ID_START = 13100, + TEXT_ID_PROGRESS = 13101 +}; + +enum BrannCreatures +{ + CREATURE_TRIBUNAL_OF_THE_AGES = 28234, + CREATURE_BRANN_BRONZEBEARD = 28070, + CREATURE_DARK_MATTER_TARGET = 28237, + CREATURE_SEARING_GAZE_TARGET = 28265, + CREATURE_DARK_RUNE_PROTECTOR = 27983, + CREATURE_DARK_RUNE_STORMCALLER = 27984, + CREATURE_IRON_GOLEM_CUSTODIAN = 27985, +}; + +enum Spells +{ + SPELL_STEALTH = 58506, + //Kadrak + SPELL_GLARE_OF_THE_TRIBUNAL = 50988, + H_SPELL_GLARE_OF_THE_TRIBUNAL = 59868, + //Marnak + SPELL_DARK_MATTER = 51012, + H_SPELL_DARK_MATTER = 59868, + //Abedneum + SPELL_SEARING_GAZE = 51136, + H_SPELL_SEARING_GAZE = 59867 +}; + +enum Quests +{ + QUEST_HALLS_OF_STONE = 13207 +}; + +enum Achievements +{ + ACHIEV_BRANN_SPANKIN_NEW = 2154 +}; + +#define GOSSIP_ITEM_START "Brann, it would be our honor!" +#define GOSSIP_ITEM_PROGRESS "Let's move Brann, enough of the history lessons!" + +static Position SpawnLocations[]= +{ + {946.992, 397.016, 208.374}, + {960.748, 382.944, 208.374}, +}; + +struct mob_tribuna_controllerAI : public ScriptedAI +{ + mob_tribuna_controllerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + SetCombatMovement(false); + } + + ScriptedInstance* pInstance; + + uint32 uiKaddrakEncounterTimer; + uint32 uiMarnakEncounterTimer; + uint32 uiAbedneumEncounterTimer; + + bool bKaddrakActivated; + bool bMarnakActivated; + bool bAbedneumActivated; + + std::list KaddrakGUIDList; + + void Reset() + { + uiKaddrakEncounterTimer = 1500; + uiMarnakEncounterTimer = 10000; + uiAbedneumEncounterTimer = 10000; + + bKaddrakActivated = false; + bMarnakActivated = false; + bAbedneumActivated = false; + + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); + } + + KaddrakGUIDList.clear(); + } + + void UpdateFacesList() + { + /*GetCreatureListWithEntryInGrid(lKaddrakGUIDList, me, CREATURE_KADDRAK, 50.0f); + if (!lKaddrakGUIDList.empty()) + { + uint32 uiPositionCounter = 0; + for (std::list::const_iterator itr = lKaddrakGUIDList.begin(); itr != lKaddrakGUIDList.end(); ++itr) + { + if ((*itr)->isAlive()) + { + if (uiPositionCounter == 0) + { + (*itr)->GetMap()->CreatureRelocation((*itr), 927.265, 333.200, 218.780, (*itr)->GetOrientation()); + (*itr)->SendMonsterMove(927.265, 333.200, 218.780, 0, (*itr)->GetMovementFlags(), 1); + } + else + { + (*itr)->GetMap()->CreatureRelocation((*itr), 921.745, 328.076, 218.780, (*itr)->GetOrientation()); + (*itr)->SendMonsterMove(921.745, 328.076, 218.780, 0, (*itr)->GetMovementFlags(), 1); + } + } + ++uiPositionCounter; + } + }*/ + } + + void UpdateAI(const uint32 diff) + { + if (bKaddrakActivated) + { + if (uiKaddrakEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (!KaddrakGUIDList.empty()) + for (std::list::const_iterator itr = KaddrakGUIDList.begin(); itr != KaddrakGUIDList.end(); ++itr) + { + if (Creature *pKaddrak = Unit::GetCreature(*me, *itr)) + { + if (pKaddrak->isAlive()) + pKaddrak->CastSpell(pTarget, DUNGEON_MODE(SPELL_GLARE_OF_THE_TRIBUNAL, H_SPELL_GLARE_OF_THE_TRIBUNAL), true); + } + } + uiKaddrakEncounterTimer = 1500; + } else uiKaddrakEncounterTimer -= diff; + } + if (bMarnakActivated) + { + if (uiMarnakEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature* pSummon = me->SummonCreature(CREATURE_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) + { + pSummon->SetDisplayId(11686); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_DARK_MATTER, H_SPELL_DARK_MATTER), true); + } + } + uiMarnakEncounterTimer = 30000 + rand()%1000; + } else uiMarnakEncounterTimer -= diff; + } + if (bAbedneumActivated) + { + if (uiAbedneumEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature* pSummon = me->SummonCreature(CREATURE_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) + { + pSummon->SetDisplayId(11686); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_SEARING_GAZE, H_SPELL_SEARING_GAZE), true); + } + } + uiAbedneumEncounterTimer = 30000 + rand()%1000; + } else uiAbedneumEncounterTimer -= diff; + } + } +}; + +struct npc_brann_hosAI : public npc_escortAI +{ + npc_brann_hosAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiStep; + uint32 uiPhaseTimer; + + uint64 uiControllerGUID; + std::list lDwarfGUIDList; + + ScriptedInstance* pInstance; + + bool bIsBattle; + bool bIsLowHP; + bool bHasBeenDamaged; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + bIsLowHP = false; + bIsBattle = false; + bHasBeenDamaged = false; + uiStep = 0; + uiPhaseTimer = 0; + uiControllerGUID = 0; + + DespawnDwarf(); + + if (pInstance) + pInstance->SetData(DATA_BRANN_EVENT, NOT_STARTED); + } + } + + void DespawnDwarf() + { + if (lDwarfGUIDList.empty()) + return; + for (std::list::const_iterator itr = lDwarfGUIDList.begin(); itr != lDwarfGUIDList.end(); ++itr) + { + Creature* pTemp = Unit::GetCreature(*me, pInstance ? (*itr) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + lDwarfGUIDList.clear(); + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 7: + if (Creature* pCreature = GetClosestCreatureWithEntry(me, CREATURE_TRIBUNAL_OF_THE_AGES, 100.0f)) + { + if (!pCreature->isAlive()) + pCreature->Respawn(); + CAST_AI(mob_tribuna_controllerAI, pCreature->AI())->UpdateFacesList(); + uiControllerGUID = pCreature->GetGUID(); + } + break; + case 13: + DoScriptText(SAY_EVENT_INTRO_1, me); + SetEscortPaused(true); + JumpToNextStep(20000); + break; + case 17: + DoScriptText(SAY_EVENT_INTRO_2, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_TRIBUNAL_CONSOLE),true); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + SetEscortPaused(true); + JumpToNextStep(8500); + break; + case 18: + SetEscortPaused(true); + break; + } + } + + void SpawnDwarf(uint32 uiType) + { + switch(uiType) + { + case 1: + { + uint32 uiSpawnNumber = DUNGEON_MODE(2,3); + for (uint8 i = 0; i < uiSpawnNumber; ++i) + me->SummonCreature(CREATURE_DARK_RUNE_PROTECTOR, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + } + case 2: + for (uint8 i = 0; i < 2; ++i) + me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + case 3: + me->SummonCreature(CREATURE_IRON_GOLEM_CUSTODIAN, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + lDwarfGUIDList.push_back(pSummoned->GetGUID()); + pSummoned->AddThreat(me, 0.0f); + pSummoned->AI()->AttackStart(me); + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhaseTimer = uiTimer; + ++uiStep; + } + + void StartWP() + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetEscortPaused(false); + uiStep = 1; + Start(); + } + + void DamageTaken(Unit* /*done_by*/, uint32 & /*damage*/) + { + if (!bHasBeenDamaged) + bHasBeenDamaged = true; + } + + void UpdateEscortAI(const uint32 uiDiff) + { + if (uiPhaseTimer <= uiDiff) + { + switch(uiStep) + { + case 1: + if (pInstance) + { + if (pInstance->GetData(DATA_BRANN_EVENT) != NOT_STARTED) + return; + pInstance->SetData(DATA_BRANN_EVENT, IN_PROGRESS); + } + bIsBattle = false; + DoScriptText(SAY_ESCORT_START, me); + SetRun(true); + JumpToNextStep(0); + break; + case 3: + SetEscortPaused(false); + JumpToNextStep(0); + break; + case 5: + if (pInstance) + if (Creature* pTemp = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM)))) + DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp); + JumpToNextStep(8500); + break; + case 6: + DoScriptText(SAY_EVENT_A_1, me); + JumpToNextStep(6500); + break; + case 7: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_A_2_KADD, pTemp); + JumpToNextStep(12500); + break; + case 8: + DoScriptText(SAY_EVENT_A_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bKaddrakActivated = true; + JumpToNextStep(5000); + break; + case 9: + me->SetReactState(REACT_PASSIVE); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 10: + DoScriptText(SAY_EVENT_B_1, me); + JumpToNextStep(6000); + break; + case 11: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_B_2_MARN, pTemp); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 12: + DoScriptText(SAY_EVENT_B_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bMarnakActivated = true; + JumpToNextStep(10000); + break; + case 13: + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 14: + SpawnDwarf(2); + JumpToNextStep(20000); + break; + case 15: + DoScriptText(SAY_EVENT_C_1, me); + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 16: + SpawnDwarf(2); + JumpToNextStep(20000); + break; + case 17: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_C_2_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 18: + DoScriptText(SAY_EVENT_C_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bAbedneumActivated = true; + JumpToNextStep(5000); + break; + case 19: + SpawnDwarf(2); + JumpToNextStep(10000); + break; + case 20: + SpawnDwarf(1); + JumpToNextStep(15000); + break; + case 21: + DoScriptText(SAY_EVENT_D_1, me); + SpawnDwarf(3); + JumpToNextStep(20000); + break; + case 22: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_D_2_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(5000); + break; + case 23: + SpawnDwarf(2); + JumpToNextStep(15000); + break; + case 24: + DoScriptText(SAY_EVENT_D_3, me); + SpawnDwarf(3); + JumpToNextStep(5000); + break; + case 25: + SpawnDwarf(1); + JumpToNextStep(5000); + break; + case 26: + SpawnDwarf(2); + JumpToNextStep(10000); + break; + case 27: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_D_4_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 28: + me->SetReactState(REACT_DEFENSIVE); + DoScriptText(SAY_EVENT_END_01, me); + me->SetStandState(UNIT_STAND_STATE_STAND); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + bIsBattle = true; + SetEscortPaused(false); + JumpToNextStep(6500); + break; + case 29: + DoScriptText(SAY_EVENT_END_02, me); + if (pInstance) + { + pInstance->SetData(DATA_BRANN_EVENT, DONE); + + // Achievement criteria is with spell 59046 which does not exist. + // There is thus no way it can be given by casting the spell on the players. + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59046); + + if (!bHasBeenDamaged) + pInstance->DoCompleteAchievement(ACHIEV_BRANN_SPANKIN_NEW); + } + + JumpToNextStep(5500); + break; + case 30: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_03_ABED, pTemp); + JumpToNextStep(8500); + break; + case 31: + DoScriptText(SAY_EVENT_END_04, me); + JumpToNextStep(11500); + break; + case 32: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_05_ABED, pTemp); + JumpToNextStep(11500); + break; + case 33: + DoScriptText(SAY_EVENT_END_06, me); + JumpToNextStep(4500); + break; + case 34: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_07_ABED, pTemp); + JumpToNextStep(22500); + break; + case 35: + DoScriptText(SAY_EVENT_END_08, me); + JumpToNextStep(7500); + break; + case 36: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_09_KADD, pTemp); + JumpToNextStep(18500); + break; + case 37: + DoScriptText(SAY_EVENT_END_10, me); + JumpToNextStep(5500); + break; + case 38: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_11_KADD, pTemp); + JumpToNextStep(20500); + break; + case 39: + DoScriptText(SAY_EVENT_END_12, me); + JumpToNextStep(2500); + break; + case 40: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_13_KADD, pTemp); + JumpToNextStep(19500); + break; + case 41: + DoScriptText(SAY_EVENT_END_14, me); + JumpToNextStep(10500); + break; + case 42: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_15_MARN, pTemp); + JumpToNextStep(6500); + break; + case 43: + DoScriptText(SAY_EVENT_END_16, me); + JumpToNextStep(6500); + break; + case 44: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_17_MARN, pTemp); + JumpToNextStep(25500); + break; + case 45: + DoScriptText(SAY_EVENT_END_18, me); + JumpToNextStep(23500); + break; + case 46: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_19_MARN, pTemp); + JumpToNextStep(3500); + break; + case 47: + DoScriptText(SAY_EVENT_END_20, me); + JumpToNextStep(8500); + break; + case 48: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_21_ABED, pTemp); + JumpToNextStep(5500); + break; + case 49: + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); + } + Player* pPlayer = GetPlayerForEscort(); + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, me); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + JumpToNextStep(180000); + break; + } + case 50: + SetEscortPaused(false); + break; + } + } else uiPhaseTimer -= uiDiff; + + if (!bIsLowHP && HealthBelowPct(30)) + { + DoScriptText(SAY_LOW_HEALTH, me); + bIsLowHP = true; + } + else if (bIsLowHP && !HealthBelowPct(30)) + bIsLowHP = false; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_brann_hos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1 || uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_brann_hosAI, pCreature->AI())->StartWP(); + } + + return true; +} + +CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature) +{ + return new mob_tribuna_controllerAI(pCreature); +} + +CreatureAI* GetAI_npc_brann_hos(Creature* pCreature) +{ + return new npc_brann_hosAI(pCreature); +} + +void AddSC_halls_of_stone() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_brann_hos"; + newscript->GetAI = &GetAI_npc_brann_hos; + newscript->pGossipHello = &GossipHello_npc_brann_hos; + newscript->pGossipSelect = &GossipSelect_npc_brann_hos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tribuna_controller"; + newscript->GetAI = &GetAI_mob_tribuna_controller; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h b/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h new file mode 100644 index 00000000000..b61e7057ddc --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h @@ -0,0 +1,48 @@ +#ifndef DEF_HALLS_OF_STONE_H +#define DEF_HALLS_OF_STONE_H +enum Data +{ + DATA_KRYSTALLUS_EVENT, + DATA_MAIDEN_OF_GRIEF_EVENT, + DATA_SJONNIR_EVENT, + DATA_BRANN_EVENT +}; +enum Data64 +{ + DATA_KRYSTALLUS, + DATA_MAIDEN_OF_GRIEF, + DATA_SJONNIR, + DATA_KADDRAK, + DATA_MARNAK, + DATA_ABEDNEUM, + DATA_GO_TRIBUNAL_CONSOLE, + DATA_GO_KADDRAK, + DATA_GO_MARNAK, + DATA_GO_ABEDNEUM, + DATA_GO_SKY_FLOOR, + DATA_SJONNIR_DOOR, + DATA_MAIDEN_DOOR +}; +enum Creatures +{ + CREATURE_MAIDEN = 27975, + CREATURE_KRYSTALLUS = 27977, + CREATURE_SJONNIR = 27978, + CREATURE_MARNAK = 30897, + CREATURE_KADDRAK = 30898, + CREATURE_ABEDNEUM = 30899, + CREATURE_BRANN = 28070 +}; +enum GameObjects +{ + GO_ABEDNEUM = 191669, + GO_MARNAK = 192170, + GO_KADDRAK = 192171, + GO_MAIDEN_DOOR = 191292, + GO_BRANN_DOOR = 191295, + GO_SJONNIR_DOOR = 191296, + GO_TRIBUNAL_CONSOLE = 193907, + GO_TRIBUNAL_CHEST = 190586, + GO_TRIBUNAL_CHEST_HERO = 193996 +}; +#endif diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp new file mode 100644 index 00000000000..69bb3779e70 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp @@ -0,0 +1,254 @@ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +#define MAX_ENCOUNTER 4 + +/* Halls of Stone encounters: +0- Krystallus +1- Maiden of Grief +2- Escort Event +3- Sjonnir The Ironshaper +*/ + +struct instance_halls_of_stone : public ScriptedInstance +{ + instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiMaidenOfGrief; + uint64 uiKrystallus; + uint64 uiSjonnir; + + uint64 uiKaddrak; + uint64 uiAbedneum; + uint64 uiMarnak; + uint64 uiBrann; + + uint64 uiMaidenOfGriefDoor; + uint64 uiSjonnirDoor; + uint64 uiBrannDoor; + uint64 uiTribunalConsole; + uint64 uiTribunalChest; + uint64 uiTribunalSkyFloor; + uint64 uiKaddrakGo; + uint64 uiAbedneumGo; + uint64 uiMarnakGo; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + std::string str_data; + + void Initialize() + { + uiMaidenOfGrief = 0; + uiKrystallus = 0; + uiSjonnir = 0; + + uiKaddrak = 0; + uiMarnak = 0; + uiAbedneum = 0; + uiBrann = 0; + + uiMaidenOfGriefDoor = 0; + uiSjonnirDoor = 0; + uiBrannDoor = 0; + uiKaddrakGo = 0; + uiMarnakGo = 0; + uiAbedneumGo = 0; + uiTribunalConsole = 0; + uiTribunalChest = 0; + uiTribunalSkyFloor = 0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + m_auiEncounter[i] = NOT_STARTED; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case CREATURE_MAIDEN: uiMaidenOfGrief = pCreature->GetGUID(); break; + case CREATURE_KRYSTALLUS: uiKrystallus = pCreature->GetGUID(); break; + case CREATURE_SJONNIR: uiSjonnir = pCreature->GetGUID(); break; + case CREATURE_MARNAK: uiMarnak = pCreature->GetGUID(); break; + case CREATURE_KADDRAK: uiKaddrak = pCreature->GetGUID(); break; + case CREATURE_ABEDNEUM: uiAbedneum = pCreature->GetGUID(); break; + case CREATURE_BRANN: uiBrann = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_ABEDNEUM: + uiAbedneumGo = pGo->GetGUID(); + break; + case GO_MARNAK: + uiMarnakGo = pGo->GetGUID(); + break; + case GO_KADDRAK: + uiKaddrakGo = pGo->GetGUID(); + break; + case GO_MAIDEN_DOOR: + uiMaidenOfGriefDoor = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_BRANN_DOOR: + uiBrannDoor = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_SJONNIR_DOOR: + uiSjonnirDoor = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_TRIBUNAL_CONSOLE: + uiTribunalConsole = pGo->GetGUID(); + break; + case GO_TRIBUNAL_CHEST: + case GO_TRIBUNAL_CHEST_HERO: + uiTribunalChest = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + case 191527: + uiTribunalSkyFloor = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAIDEN_OF_GRIEF_EVENT: + m_auiEncounter[1] = data; + if (m_auiEncounter[1] == DONE) + HandleGameObject(uiBrannDoor,true); + break; + case DATA_KRYSTALLUS_EVENT: + m_auiEncounter[0] = data; + if (m_auiEncounter[0] == DONE) + HandleGameObject(uiMaidenOfGriefDoor,true); + break; + case DATA_SJONNIR_EVENT: + m_auiEncounter[3] = data; + break; + case DATA_BRANN_EVENT: + m_auiEncounter[2] = data; + if (m_auiEncounter[2] == DONE) + { + HandleGameObject(uiSjonnirDoor,true); + GameObject *pGo = instance->GetGameObject(uiTribunalChest); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + } + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_KRYSTALLUS_EVENT: return m_auiEncounter[0]; + case DATA_MAIDEN_OF_GRIEF_EVENT: return m_auiEncounter[1]; + case DATA_SJONNIR_EVENT: return m_auiEncounter[2]; + case DATA_BRANN_EVENT: return m_auiEncounter[3]; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MAIDEN_OF_GRIEF: return uiMaidenOfGrief; + case DATA_KRYSTALLUS: return uiKrystallus; + case DATA_SJONNIR: return uiSjonnir; + case DATA_KADDRAK: return uiKaddrak; + case DATA_MARNAK: return uiMarnak; + case DATA_ABEDNEUM: return uiAbedneum; + case DATA_GO_TRIBUNAL_CONSOLE: return uiTribunalConsole; + case DATA_GO_KADDRAK: return uiKaddrakGo; + case DATA_GO_ABEDNEUM: return uiAbedneumGo; + case DATA_GO_MARNAK: return uiMarnakGo; + case DATA_GO_SKY_FLOOR: return uiTribunalSkyFloor; + case DATA_SJONNIR_DOOR: return uiSjonnirDoor; + case DATA_MAIDEN_DOOR: return uiMaidenOfGriefDoor; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'H' && dataHead2 == 'S') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_halls_of_stone(Map* pMap) +{ + return new instance_halls_of_stone(pMap); +} + +void AddSC_instance_halls_of_stone() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_stone"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_stone; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_algalon.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_algalon.cpp new file mode 100644 index 00000000000..e944543fb9e --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_algalon.cpp @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2008 - 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +#define GAMEOBJECT_GIVE_OF_THE_OBSERVER 194821 + +enum Spells +{ + SPELL_ASCEND = 64487, + SPELL_BERSERK = 47008, + SPELL_BIG_BANG = 64443, + H_SPELL_BIG_BANG = 64584, + SPELL_COSMIC_SMASH = 62301, + H_SPELL_COSMIC_SMASH = 64598, + SPELL_PHASE_PUNCH = 64412, + SPELL_QUANTUM_STRIKE = 64395, + H_SPELL_QUANTUM_STRIKE = 64592, + SPELL_BLACK_HOLE_EXPLOSION = 64122, + SPELL_ARCANE_BARAGE = 64599, + H_SPELL_ARCANE_BARAGE = 64607 +}; + +enum Creatures +{ + CREATURE_COLLAPSING_STAR = 32955, + CREATURE_BLACK_HOLE = 32953, + CREATURE_LIVING_CONSTELLATION = 33052, + CREATURE_DARK_MATTER = 33089 +}; + +#define NORDRASSIL_X 1614.288574 +#define NORDRASSIL_Y -320.713287 +#define NORDRASSIL_Z 417.321167 +#define NORDRASSIL_X 1614.276245 +#define NORDRASSIL_Y -287.016632 +#define NORDRASSIL_Z 417.321106 +#define NORDRASSIL_X 1650.428467 +#define NORDRASSIL_Y -292.331390 +#define NORDRASSIL_Z 417.321167 +#define NORDRASSIL_X 1649.501831 +#define NORDRASSIL_Y -324.609222 +#define NORDRASSIL_Z 417.322174 + +enum Yells +{ + SAY_AGGRO = -1603000, + SAY_SLAY_1 = -1603001, + SAY_SLAY_2 = -1603002, + SAY_ENGADED_FOR_FIRTS_TIME = -1603003, + SAY_PHASE_2 = -1603004, + SAY_SUMMON_COLLAPSING_STAR = -1603005, + SAY_DEATH_1 = -1603006, + SAY_DEATH_2 = -1603007, + SAY_DEATH_3 = -1603008, + SAY_DEATH_4 = -1603009, + SAY_DEATH_5 = -1603010, + SAY_BERSERK = -1603011, + SAY_BIG_BANG_1 = -1603012, + SAY_BIG_BANG_2 = -1603013, + SAY_TIMER_1 = -1603014, + SAY_TIMER_2 = -1603015, + SAY_TIMER_3 = -1603016, + SAY_SUMMON_1 = -1603017, + SAY_SUMMON_2 = -1603018, + SAY_SUMMON_3 = -1603019, +}; + +struct boss_algalonAI : public ScriptedAI +{ + boss_algalonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Summon = false; // not in reset. intro speech done only once. + } + + ScriptedInstance* pInstance; + + std::list m_lCollapsingStarGUIDList; + + uint32 Phase; + uint32 Ascend_Timer; + uint32 Berserk_Timer; + uint32 BigBang_Timer; + uint32 CosmicSmash_Timer; + uint32 PhasePunch_Timer; + uint32 QuantumStrike_Timer; + uint32 CollapsingStar_Timer; + uint32 uiPhase_timer; + uint32 uiStep; + + uint64 BlackHoleGUID; + + bool Enrage; + bool Summon; + + void EnterCombat(Unit* who) + { + if (Summon) + { + DoScriptText(SAY_AGGRO, me); + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + DoZoneInCombat(who->ToCreature()); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + uiStep = 1; + } + + if (pInstance) + pInstance->SetData(TYPE_ALGALON, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void Reset() + { + Phase = 1; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pInstance) + pInstance->SetData(TYPE_ALGALON, NOT_STARTED); + + BlackHoleGUID = 0; + + uiPhase_timer = 0; + Ascend_Timer = 480000; //8 minutes + QuantumStrike_Timer = 4000 + rand()%10000; + Berserk_Timer = 360000; //6 minutes + CollapsingStar_Timer = urand(15000, 20000); //Spawns between 15 to 20 seconds + BigBang_Timer = 90000; + PhasePunch_Timer = 8000; + CosmicSmash_Timer = urand(30000, 60000); + Enrage = false; + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhase_timer = uiTimer; + ++uiStep; + } + + void DespawnCollapsingStar() + { + if (m_lCollapsingStarGUIDList.empty()) + return; + + for (std::list::const_iterator itr = m_lCollapsingStarGUIDList.begin(); itr != m_lCollapsingStarGUIDList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + } + m_lCollapsingStarGUIDList.clear(); + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == CREATURE_COLLAPSING_STAR) + { + Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (me->getVictim()) + pSummoned->AI()->AttackStart(pTarget ? pTarget : me->getVictim()); + m_lCollapsingStarGUIDList.push_back(pSummoned->GetGUID()); + } + } + + void SummonCollapsingStar(Unit* target) + { + DoScriptText(SAY_SUMMON_COLLAPSING_STAR, me); + me->SummonCreature(CREATURE_COLLAPSING_STAR,target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN, 100000); + me->SummonCreature(CREATURE_BLACK_HOLE,target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN, 27000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Phase == 1 && HealthBelowPct(20)) + { + Phase = 2; + DoScriptText(SAY_PHASE_2, me); + } + + if (HealthBelowPct(2)) + { + me->SummonGameObject(GAMEOBJECT_GIVE_OF_THE_OBSERVER, 1634.258667, -295.101166,417.321381,0,0,0,0,0,0); + + // All of them. or random? + DoScriptText(SAY_DEATH_1, me); + DoScriptText(SAY_DEATH_2, me); + DoScriptText(SAY_DEATH_3, me); + DoScriptText(SAY_DEATH_4, me); + DoScriptText(SAY_DEATH_5, me); + + me->DisappearAndDie(); + + if (pInstance) + pInstance->SetData(TYPE_ALGALON, DONE); + + return; + } + + if (Phase == 1) + { + if (!Summon) + { + if (uiPhase_timer <= diff) + { + switch(uiStep) + { + case 1: + DoScriptText(SAY_SUMMON_1, me); + JumpToNextStep(3000); + break; + case 2: + DoScriptText(SAY_SUMMON_2, me); + JumpToNextStep(3000); + break; + case 3: + DoScriptText(SAY_SUMMON_3, me); + JumpToNextStep(3000); + break; + case 4: + DoScriptText(SAY_ENGADED_FOR_FIRTS_TIME, me); + JumpToNextStep(3000); + break; + case 5: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + Summon = true; + break; + } + } else uiPhase_timer -= diff; + + return; + } + + if (QuantumStrike_Timer <= diff) + { + DoCast(me->getVictim(), RAID_MODE(SPELL_QUANTUM_STRIKE,H_SPELL_QUANTUM_STRIKE), true); + + QuantumStrike_Timer = urand(4000, 14000); + } else QuantumStrike_Timer -= diff; + + if (BigBang_Timer <= diff) + { + DoScriptText(RAND(SAY_BIG_BANG_1,SAY_BIG_BANG_2), me); + DoCast(me->getVictim(), RAID_MODE(SPELL_BIG_BANG,H_SPELL_BIG_BANG), true); + + BigBang_Timer = 90000; + } else BigBang_Timer -= diff; + + if (Ascend_Timer <= diff) + { + DoCast(me->getVictim(),SPELL_ASCEND, true); + + Ascend_Timer = 480000; + } else Ascend_Timer -= diff; + + if (PhasePunch_Timer <= diff) + { + DoCast(me->getVictim(),SPELL_PHASE_PUNCH, true); + + PhasePunch_Timer = 8000; + } else PhasePunch_Timer -= diff; + + if (CosmicSmash_Timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), RAID_MODE(SPELL_COSMIC_SMASH,H_SPELL_COSMIC_SMASH), true); + + CosmicSmash_Timer = urand(30000, 60000); + } else CosmicSmash_Timer -= diff; + + if (Berserk_Timer <= diff) + { + DoScriptText(SAY_BERSERK, me); + DoCast(me->getVictim(),SPELL_BERSERK, true); + + Berserk_Timer = 360000; + } else Berserk_Timer -= diff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } + + if (Phase == 2) + { + if (Enrage) + { + if (Ascend_Timer <= diff) + { + DoCast(me, SPELL_ASCEND); + DoScriptText(SAY_BERSERK, me); + Ascend_Timer = urand(360000,365000); + Enrage = false; + } else Ascend_Timer -= diff; + } + } + + DoMeleeAttackIfReady(); + } +}; + +//Collapsing Star +struct mob_collapsing_starAI : public ScriptedAI +{ + mob_collapsing_starAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 BlackHoleExplosion_Timer; + + void Reset() + { + BlackHoleExplosion_Timer = 0; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BlackHoleExplosion_Timer <= diff) + { + me->CastSpell(me, SPELL_BLACK_HOLE_EXPLOSION, false); + BlackHoleExplosion_Timer = 0; + } else BlackHoleExplosion_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_algalon(Creature* pCreature) +{ + return new boss_algalonAI(pCreature); +} + +CreatureAI* GetAI_mob_collapsing_star(Creature* pCreature) +{ + return new mob_collapsing_starAI(pCreature); +} + +void AddSC_boss_Algalon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_algalon"; + newscript->GetAI = &GetAI_boss_algalon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_collapsing_star"; + newscript->GetAI = &GetAI_mob_collapsing_star; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp new file mode 100644 index 00000000000..8d3ae4d3431 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_assembly_of_iron.cpp @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Assembly of Iron encounter +SD%Complete: 60% +SDComment: Runes need DB support, chain lightning won't cast, supercharge won't cast (pTarget error?) - it worked before during debugging. +SDCategory: Ulduar - Ulduar +EndScriptData */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +// Any boss +#define SPELL_SUPERCHARGE 61920 +#define SPELL_BERSERK 47008 // Hard enrage, don't know the correct ID. + +// Steelbreaker +#define SPELL_HIGH_VOLTAGE 61890 +#define SPELL_HIGH_VOLTAGE_H 63498 +#define SPELL_FUSION_PUNCH 61903 +#define SPELL_FUSION_PUNCH_H 63493 +#define SPELL_STATIC_DISRUPTION 44008 +#define SPELL_STATIC_DISRUPTION_H 63494 +#define SPELL_OVERWHELMING_POWER_H 61888 +#define SPELL_OVERWHELMING_POWER 64637 +#define SPELL_ELECTRICAL_CHARGE 61902 + +// Runemaster Molgeim +#define SPELL_SHIELD_OF_RUNES 62274 +#define SPELL_SHIELD_OF_RUNES_H 63489 +#define SPELL_RUNE_OF_POWER 64320 +#define SPELL_RUNE_OF_DEATH 62269 +#define SPELL_RUNE_OF_SUMMONING 62273 +#define SPELL_LIGHTNING_BLAST 62054 +#define SPELL_LIGHTNING_BLAST_H 63491 +#define CREATURE_RUNE_OF_SUMMONING 33051 + +// Stormcaller Brundir +#define SPELL_CHAIN_LIGHTNING_N 61879 +#define SPELL_CHAIN_LIGHTNING_H 63479 +#define SPELL_OVERLOAD 61869 +#define SPELL_OVERLOAD_H 63481 +#define SPELL_LIGHTNING_WHIRL 61915 +#define SPELL_LIGHTNING_WHIRL_H 63483 +#define SPELL_LIGHTNING_TENDRILS 61887 +#define SPELL_LIGHTNING_TENDRILS_H 63486 +#define SPELL_STORMSHIELD 64187 + +enum Events +{ + EVENT_NONE, + EVENT_ENRAGE, + // Steelbreaker + EVENT_FUSION_PUNCH, + EVENT_STATIC_DISRUPTION, + EVENT_OVERWHELMING_POWER, + // Molgeim + EVENT_RUNE_OF_POWER, + EVENT_SHIELD_OF_RUNES, + EVENT_RUNE_OF_DEATH, + EVENT_RUNE_OF_SUMMONING, + EVENT_LIGHTNING_BLAST, + // Brundir + EVENT_CHAIN_LIGHTNING, + EVENT_OVERLOAD, + EVENT_LIGHTNING_WHIRL, + EVENT_LIGHTNING_TENDRILS, + EVENT_STORMSHIELD, +}; + +enum Yells +{ + SAY_STEELBREAKER_AGGRO = -1603020, + SAY_STEELBREAKER_SLAY_1 = -1603021, + SAY_STEELBREAKER_SLAY_2 = -1603022, + SAY_STEELBREAKER_POWER = -1603023, + SAY_STEELBREAKER_DEATH_1 = -1603024, + SAY_STEELBREAKER_DEATH_2 = -1603025, + SAY_STEELBREAKER_BERSERK = -1603026, + + SAY_MOLGEIM_AGGRO = -1603030, + SAY_MOLGEIM_SLAY_1 = -1603031, + SAY_MOLGEIM_SLAY_2 = -1603032, + SAY_MOLGEIM_RUNE_DEATH = -1603033, + SAY_MOLGEIM_SUMMON = -1603034, + SAY_MOLGEIM_DEATH_1 = -1603035, + SAY_MOLGEIM_DEATH_2 = -1603036, + SAY_MOLGEIM_BERSERK = -1603037, + + SAY_BRUNDIR_AGGRO = -1603040, + SAY_BRUNDIR_SLAY_1 = -1603041, + SAY_BRUNDIR_SLAY_2 = -1603042, + SAY_BRUNDIR_SPECIAL = -1603043, + SAY_BRUNDIR_FLIGHT = -1603044, + SAY_BRUNDIR_DEATH_1 = -1603045, + SAY_BRUNDIR_DEATH_2 = -1603046, + SAY_BRUNDIR_BERSERK = -1603047, +}; + +bool IsEncounterComplete(ScriptedInstance* pInstance, Creature* me) +{ + if (!pInstance || !me) + return false; + + for (uint8 i = 0; i < 3; ++i) + { + uint64 guid = pInstance->GetData64(DATA_STEELBREAKER+i); + if (!guid) + return false; + + if (Creature *boss = Unit::GetCreature(*me, guid)) + { + if (boss->isAlive()) + return false; + } + else + return false; + } + return true; +} + +struct boss_steelbreakerAI : public ScriptedAI +{ + boss_steelbreakerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() + { + events.Reset(); + phase = 0; + me->RemoveAllAuras(); + if (pInstance) + pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); + } + + EventMap events; + ScriptedInstance* pInstance; + uint32 phase; + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_STEELBREAKER_AGGRO, me); + DoZoneInCombat(); + DoCast(me, RAID_MODE(SPELL_HIGH_VOLTAGE, SPELL_HIGH_VOLTAGE_H)); + events.ScheduleEvent(EVENT_ENRAGE, 900000); + UpdatePhase(); + } + + void UpdatePhase() + { + ++phase; + events.SetPhase(phase); + events.RescheduleEvent(EVENT_FUSION_PUNCH, 15000); + if (phase >= 2) + events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 30000); + if (phase >= 3) + events.RescheduleEvent(EVENT_OVERWHELMING_POWER, rand()%5000); + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + if (Creature* Brundir = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0)) + if (Brundir->isAlive()) + Brundir->SetHealth(Brundir->GetMaxHealth()); + + if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0)) + if (Molgeim->isAlive()) + Molgeim->SetHealth(Molgeim->GetMaxHealth()); + + DoCast(SPELL_SUPERCHARGE); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(RAND(SAY_STEELBREAKER_DEATH_1,SAY_STEELBREAKER_DEATH_2), me); + if (IsEncounterComplete(pInstance, me) && pInstance) + pInstance->SetData(TYPE_ASSEMBLY, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_STEELBREAKER_SLAY_1,SAY_STEELBREAKER_SLAY_2), me); + + if (phase == 3) + DoCast(me, SPELL_ELECTRICAL_CHARGE); + } + + void SpellHit(Unit * /*from*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_SUPERCHARGE) + UpdatePhase(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ENRAGE: + DoScriptText(SAY_STEELBREAKER_BERSERK, me); + DoCast(SPELL_BERSERK); + break; + case EVENT_FUSION_PUNCH: + DoCast(me->getVictim(), RAID_MODE(SPELL_FUSION_PUNCH, SPELL_FUSION_PUNCH_H)); + events.ScheduleEvent(EVENT_FUSION_PUNCH, urand(13000, 22000)); + break; + case EVENT_STATIC_DISRUPTION: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, RAID_MODE(SPELL_STATIC_DISRUPTION, SPELL_STATIC_DISRUPTION_H)); + events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(20000, 40000)); + break; + case EVENT_OVERWHELMING_POWER: + DoScriptText(SAY_STEELBREAKER_POWER, me); + DoCast(me->getVictim(), RAID_MODE(SPELL_OVERWHELMING_POWER, SPELL_OVERWHELMING_POWER_H)); + events.ScheduleEvent(EVENT_OVERWHELMING_POWER, RAID_MODE(60000, 35000)); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_runemaster_molgeimAI : public ScriptedAI +{ + boss_runemaster_molgeimAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() + { + if (pInstance) + pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); + events.Reset(); + me->RemoveAllAuras(); + phase = 0; + } + + ScriptedInstance* pInstance; + EventMap events; + uint32 phase; + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_MOLGEIM_AGGRO, me); + DoZoneInCombat(); + events.ScheduleEvent(EVENT_ENRAGE, 900000); + UpdatePhase(); + } + + void UpdatePhase() + { + ++phase; + events.SetPhase(phase); + events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27000); + events.RescheduleEvent(EVENT_RUNE_OF_POWER, 60000); + if (phase >= 2) + events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 30000); + if (phase >= 3) + events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0)) + if (Steelbreaker->isAlive()) + Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth()); + + if (Creature* Brundir = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0)) + if (Brundir->isAlive()) + Brundir->SetHealth(Brundir->GetMaxHealth()); + + DoCast(me, SPELL_SUPERCHARGE); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(RAND(SAY_MOLGEIM_DEATH_1,SAY_MOLGEIM_DEATH_2), me); + if (IsEncounterComplete(pInstance, me) && pInstance) + pInstance->SetData(TYPE_ASSEMBLY, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_MOLGEIM_SLAY_1,SAY_MOLGEIM_SLAY_2), me); + } + + void SpellHit(Unit * /*from*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_SUPERCHARGE) + UpdatePhase(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ENRAGE: + DoScriptText(SAY_MOLGEIM_BERSERK, me); + DoCast(SPELL_BERSERK); + break; + case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly + { + Unit *pTarget = DoSelectLowestHpFriendly(60); + if (!pTarget || (pTarget && !pTarget->isAlive())) + pTarget = me; + DoCast(pTarget, SPELL_RUNE_OF_POWER); + events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000); + break; + } + case EVENT_SHIELD_OF_RUNES: + DoCast(me, RAID_MODE(SPELL_SHIELD_OF_RUNES, SPELL_SHIELD_OF_RUNES_H)); + events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, urand(27000,34000)); + break; + case EVENT_RUNE_OF_DEATH: + DoScriptText(SAY_MOLGEIM_RUNE_DEATH, me); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_RUNE_OF_DEATH); + events.ScheduleEvent(EVENT_RUNE_OF_DEATH, urand(30000,40000)); + break; + case EVENT_RUNE_OF_SUMMONING: + DoScriptText(SAY_MOLGEIM_SUMMON, me); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_RUNE_OF_SUMMONING); + events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_lightning_elementalAI : public ScriptedAI +{ + mob_lightning_elementalAI(Creature *c) : ScriptedAI(c) + { + Charge(); + } + + void Charge() + { + Unit* pTarget = me->SelectNearestTarget(); + me->AddThreat(pTarget, 5000000.0f); + AttackStart(pTarget); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!me->isInCombat()) + return; + + if (!UpdateVictim()) + return; + + if (me->IsWithinMeleeRange(me->getVictim())) + { + DoCast(me->getVictim(), RAID_MODE(SPELL_LIGHTNING_BLAST, SPELL_LIGHTNING_BLAST_H)); + me->Kill(me); // hack until spell works + } + + me->GetMotionMaster()->MoveChase(me->getVictim()); // needed at every update? + } +}; + +struct mob_rune_of_summoningAI : public ScriptedAI +{ + mob_rune_of_summoningAI(Creature *c) : ScriptedAI(c) + { + SummonLightningElemental(); + } + + void SummonLightningElemental() + { + me->SummonCreature(CREATURE_RUNE_OF_SUMMONING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN); + me->DealDamage(me, me->GetHealth()); + } +}; + +struct boss_stormcaller_brundirAI : public ScriptedAI +{ + boss_stormcaller_brundirAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + void Reset() + { + if (pInstance) + pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); + me->RemoveAllAuras(); + events.Reset(); + phase = 0; + } + + EventMap events; + ScriptedInstance* pInstance; + uint32 phase; + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_BRUNDIR_AGGRO, me); + DoZoneInCombat(); + events.ScheduleEvent(EVENT_ENRAGE, 900000); + UpdatePhase(); + } + + void UpdatePhase() + { + ++phase; + events.SetPhase(phase); + events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000,17000)); + events.RescheduleEvent(EVENT_OVERLOAD, urand(60000,125000)); + if (phase >= 2) + events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000,40000)); + if (phase >= 3) + { + DoCast(me, SPELL_STORMSHIELD); + events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, urand(40000,80000)); + } + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0)) + if (Steelbreaker->isAlive()) + Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth()); + + if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0)) + if (Molgeim->isAlive()) + Molgeim->SetHealth(Molgeim->GetMaxHealth()); + + DoCast(SPELL_SUPERCHARGE); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(RAND(SAY_BRUNDIR_DEATH_1,SAY_BRUNDIR_DEATH_2), me); + if (IsEncounterComplete(pInstance, me) && pInstance) + pInstance->SetData(TYPE_ASSEMBLY, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_BRUNDIR_SLAY_1,SAY_BRUNDIR_SLAY_2), me); + } + + void SpellHit(Unit * /*from*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_SUPERCHARGE) + UpdatePhase(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ENRAGE: + DoScriptText(SAY_BRUNDIR_BERSERK, me); + DoCast(SPELL_BERSERK); + break; + case EVENT_CHAIN_LIGHTNING: + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, RAID_MODE(SPELL_CHAIN_LIGHTNING_N , SPELL_CHAIN_LIGHTNING_H)); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000,17000)); + break; + case EVENT_OVERLOAD: + DoCast(RAID_MODE(SPELL_OVERLOAD , SPELL_OVERLOAD_H)); + events.ScheduleEvent(EVENT_OVERLOAD, urand(60000,125000)); + break; + case EVENT_LIGHTNING_WHIRL: + DoCast(RAID_MODE(SPELL_LIGHTNING_WHIRL , SPELL_LIGHTNING_WHIRL_H)); + events.ScheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000,40000)); + break; + case EVENT_LIGHTNING_TENDRILS: + DoCast(RAID_MODE(SPELL_LIGHTNING_TENDRILS, SPELL_LIGHTNING_TENDRILS_H)); + events.DelayEvents(15000, 5000); + DoResetThreat(); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_steelbreaker(Creature* pCreature) +{ + return new boss_steelbreakerAI (pCreature); +} + +CreatureAI* GetAI_boss_runemaster_molgeim(Creature* pCreature) +{ + return new boss_runemaster_molgeimAI (pCreature); +} + +CreatureAI* GetAI_boss_stormcaller_brundir(Creature* pCreature) +{ + return new boss_stormcaller_brundirAI (pCreature); +} + +CreatureAI* GetAI_mob_lightning_elemental(Creature* pCreature) +{ + return new mob_lightning_elementalAI (pCreature); +} + +CreatureAI* GetAI_mob_rune_of_summoning(Creature* pCreature) +{ + return new mob_rune_of_summoningAI (pCreature); +} + +void AddSC_boss_assembly_of_iron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_steelbreaker"; + newscript->GetAI = &GetAI_boss_steelbreaker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_runemaster_molgeim"; + newscript->GetAI = &GetAI_boss_runemaster_molgeim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_stormcaller_brundir"; + newscript->GetAI = &GetAI_boss_stormcaller_brundir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lightning_elemental"; + newscript->GetAI = &GetAI_mob_lightning_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_rune_of_summoning"; + newscript->GetAI = &GetAI_mob_rune_of_summoning; + newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_auriaya.cpp new file mode 100644 index 00000000000..41c0f317f4e --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_auriaya.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +//boss_auriaya +#define SPELL_TERRIFYING_SCREECH 64386 +#define SPELL_SETINEL_BLAST 64679 +#define SPELL_SONIC_SCREECH 64422 +#define SPELL_SUMMON_SWARMING_GUARDIAN 64397 + +enum Yells +{ + SAY_AGGRO = -1603050, + SAY_SLAY_1 = -1603051, + SAY_SLAY_2 = -1603052, + SAY_DEATH = -1603053, + SAY_BERSERK = -1603054, +}; + +struct boss_auriaya_AI : public BossAI +{ + boss_auriaya_AI(Creature *pCreature) : BossAI(pCreature, TYPE_AURIAYA) + { + } + + uint32 TERRIFYING_SCREECH_Timer; + uint32 SONIC_SCREECH_Timer; + + void Reset() + { + _Reset(); + TERRIFYING_SCREECH_Timer = 180000; + SONIC_SCREECH_Timer = 30000; + } + + void EnterCombat(Unit* /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO,me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (TERRIFYING_SCREECH_Timer <= diff) + { + DoCast(SPELL_TERRIFYING_SCREECH); + TERRIFYING_SCREECH_Timer = 180000; + } else TERRIFYING_SCREECH_Timer -= diff; + + if (SONIC_SCREECH_Timer <= diff) + { + DoCastVictim(SPELL_SONIC_SCREECH); + SONIC_SCREECH_Timer = 30000; + } else SONIC_SCREECH_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_auriaya(Creature* pCreature) +{ + return new boss_auriaya_AI (pCreature); +} + +void AddSC_boss_auriaya() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_auriaya"; + newscript->GetAI = &GetAI_boss_auriaya; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp new file mode 100644 index 00000000000..b50f12805a4 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_flame_leviathan.cpp @@ -0,0 +1,574 @@ +/* + * Copyright (C) 2008 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: Tower Event support is not finished, there is missing code on triggers and + * Lore Keeper and Brann Bronzebeard are not scripted yet. Lore Keeper's script + * should activate the hard mode so is not possible to play hard-mode yet. Add a call to + * Leviathan's DoAction(0) from Lore Keeper's script to activate hard-mode + */ + +#include "ScriptedPch.h" +#include "ulduar.h" +#include "Vehicle.h" + +enum Spells +{ + SPELL_PURSUED = 62374, + SPELL_GATHERING_SPEED = 62375, + SPELL_BATTERING_RAM = 62376, + SPELL_FLAME_VENTS = 62396, + SPELL_MISSILE_BARRAGE = 62400, + SPELL_SYSTEMS_SHUTDOWN = 62475, + + SPELL_FLAME_CANNON = 62395, +// SPELL_FLAME_CANNON = 64692, trigger the same spell + + SPELL_OVERLOAD_CIRCUIT = 62399, + SPELL_SEARING_FLAME = 62402, + SPELL_BLAZE = 62292, + SPELL_SMOKE_TRAIL = 63575, + SPELL_ELECTROSHOCK = 62522, + //TOWER BUFF SPELLS + SPELL_THORIM_S_HAMMER = 62912, // Tower of Storms + SPELL_MIMIRON_S_INFERNO = 62910, // Tower of Flames + SPELL_HODIR_S_FURY = 62297, // Tower of Frost + SPELL_FREYA_S_WARD = 62906 // Tower of Nature +}; + +enum Creatures +{ + MOB_MECHANOLIFT = 33214, + MOB_LIQUID = 33189, + MOB_CONTAINER = 33218, +}; + +enum Events +{ + EVENT_NONE, + EVENT_PURSUE, + EVENT_MISSILE, + EVENT_VENT, + EVENT_SPEED, + EVENT_SUMMON, + EVENT_THORIM_S_HAMMER, // Tower of Storms + EVENT_MIMIRON_S_INFERNO, // Tower of Flames + EVENT_HODIR_S_FURY, // Tower of Frost + EVENT_FREYA_S_WARD // Tower of Nature +}; + +enum Seats +{ + SEAT_PLAYER = 0, + SEAT_TURRET = 1, + SEAT_DEVICE = 2, +}; + +enum Yells +{ + SAY_AGGRO = -1603060, + SAY_SLAY = -1603061, + SAY_DEATH = -1603062, + SAY_TARGET_1 = -1603063, + SAY_TARGET_2 = -1603064, + SAY_TARGET_3 = -1603065, + SAY_HARDMODE = -1603066, + SAY_TOWER_NONE = -1603067, + SAY_TOWER_FROST = -1603068, + SAY_TOWER_FLAME = -1603069, + SAY_TOWER_NATURE = -1603070, + SAY_TOWER_STORM = -1603071, + SAY_PLAYER_RIDING = -1603072, + SAY_OVERLOAD_1 = -1603073, + SAY_OVERLOAD_2 = -1603074, + SAY_OVERLOAD_3 = -1603075, +}; + +enum eAchievementData +{ + //ACHIEV_CHAMPION_OF_ULDUAR = 10042, + //ACHIEV_CONQUEROR_OF_ULDUAR = 10352, + ACHIEV_10_NUKED_FROM_ORBIT = 10058, + ACHIEV_25_NUKED_FROM_ORBIT = 10060, + ACHIEV_10_ORBITAL_BOMBARDMENT = 10056, + ACHIEV_25_ORBITAL_BOMBARDMENT = 10061, + ACHIEV_10_ORBITAL_DEVASTATION = 10057, + ACHIEV_25_ORBITAL_DEVASTATION = 10059, + ACHIEV_10_ORBIT_UARY = 10218, + ACHIEV_25_ORBIT_UARY = 10219, + ACHIEV_10_SHUTOUT = 10054, + ACHIEV_25_SHUTOUT = 10055, + ACHIEV_10_SIEGE_OF_ULDUAR = 9999, + ACHIEV_25_SIEGE_OF_ULDUAR = 10003, + //ACHIEV_10_THREE_CAR_GARAGE = 10046, 10047, 10048, + //ACHIEV_25_THREE_CAR_GARAGE = 10049, 10050, 10051, + ACHIEV_10_UNBROKEN = 10044, + ACHIEV_25_UNBROKEN = 10045, +}; + +static Position Center[]= +{ + {354.8771, -12.90240, 409.803650}, +}; + +struct boss_flame_leviathanAI : public BossAI +{ + boss_flame_leviathanAI(Creature* pCreature) : BossAI(pCreature, TYPE_LEVIATHAN), vehicle(pCreature->GetVehicleKit()) + { + assert(vehicle); + + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + Vehicle* vehicle; + uint8 uiActiveTowers; + + void Reset() + { + _Reset(); + assert(vehicle); + uiActiveTowers = 0; + me->SetReactState(REACT_AGGRESSIVE); + } + + void EnterCombat(Unit* /*who*/) + { + _EnterCombat(); + DoScriptText(SAY_AGGRO, me); + me->SetReactState(REACT_DEFENSIVE); + events.ScheduleEvent(EVENT_PURSUE, 0); + events.ScheduleEvent(EVENT_MISSILE, 1500); + events.ScheduleEvent(EVENT_VENT, 20000); + events.ScheduleEvent(EVENT_SPEED, 15000); + events.ScheduleEvent(EVENT_SUMMON, 0); + + if (Creature *turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET))) + turret->AI()->DoZoneInCombat(); + } + + // TODO: effect 0 and effect 1 may be on different target + void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_PURSUED) + AttackStart(pTarget); + } + + void JustDied(Unit* /*victim*/) + { + _JustDied(); + DoScriptText(SAY_DEATH, me); + if (pInstance) + { + if (uiActiveTowers) + { + switch (uiActiveTowers) + { + case 4: + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBIT_UARY, ACHIEV_25_ORBIT_UARY)); + break; + case 3: + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_NUKED_FROM_ORBIT, ACHIEV_25_NUKED_FROM_ORBIT)); + break; + case 2: + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBITAL_DEVASTATION, ACHIEV_25_ORBITAL_DEVASTATION)); + break; + case 1: + pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBITAL_BOMBARDMENT, ACHIEV_25_ORBITAL_BOMBARDMENT)); + break; + } + } + } + } + + void SpellHit(Unit* /*caster*/, const SpellEntry* pSpell) + { + if (pSpell->Id == 62472) + vehicle->InstallAllAccessories(); + else if (pSpell->Id == SPELL_ELECTROSHOCK) + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + return; + + if (me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + uint32 eventId = events.GetEvent(); + if (!me->getVictim()) + eventId = EVENT_PURSUE; + + switch(eventId) + { + case 0: break; // this is a must + case EVENT_PURSUE: + DoCastAOE(SPELL_PURSUED, true); + //events.RepeatEvent(35000); // this should not be used because eventId may be overriden + events.RescheduleEvent(EVENT_PURSUE, 35000); + if (!me->getVictim()) // all siege engines and demolishers are dead + UpdateVictim(); // begin to kill other things + return; + case EVENT_MISSILE: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_MISSILE_BARRAGE); + events.RepeatEvent(1500); + return; + case EVENT_VENT: + DoCastAOE(SPELL_FLAME_VENTS); + events.RepeatEvent(20000); + return; + case EVENT_SPEED: + DoCastAOE(SPELL_GATHERING_SPEED); + events.RepeatEvent(15000); + return; + case EVENT_SUMMON: + if (summons.size() < 15) // 4seat+1turret+10lift + if (Creature* pLift = DoSummonFlyer(MOB_MECHANOLIFT, me, urand(20,40), 50, 0)) + pLift->GetMotionMaster()->MoveRandom(100); + events.RepeatEvent(2000); + return; + case EVENT_THORIM_S_HAMMER: // Tower of Storms + DoCast(me, SPELL_THORIM_S_HAMMER); + events.RepeatEvent(urand(60000, 120000)); + return; + case EVENT_MIMIRON_S_INFERNO: // Tower of Flames + DoCast(me->getVictim(), SPELL_MIMIRON_S_INFERNO); + events.RepeatEvent(urand(60000, 120000)); + return; + case EVENT_HODIR_S_FURY: // Tower of Frost + DoCast(me->getVictim(), SPELL_HODIR_S_FURY); + events.RepeatEvent(urand(60000, 120000)); + return; + case EVENT_FREYA_S_WARD: // Tower of Nature + DoCast(me, SPELL_FREYA_S_WARD); + events.RepeatEvent(urand(60000, 120000)); + return; + default: + events.PopEvent(); + break; + } + DoSpellAttackIfReady(SPELL_BATTERING_RAM); + } + + void DoAction(const int32 uiAction) + { + // Start encounter + if (uiAction == 10) + { + me->GetMotionMaster()->MovePoint(0, Center[0]); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + return; + } + /* + Tower event triggers + General TODO: + Yells + + Actions: + DoAction(0): Activate hard-mode. Buff up leviathan's AP & health, schedule all the tower spells. + Should be triggered on Lore Keeper's script + DoAction(1-4): A tower have been destroyed, debuff leviathan's AP & health + DoAction(1); Tower of Storms has been destroyed, deschedule spell Thorim's Hammer + DoAction(2): Tower of Flames has been destroyed, deschedule spell Mimiron's Inferno + DoAction(3): Tower of Frost has been destroyed, deschedule spell Hodir's Fury + DoAction(4): Tower of Nature has been destroyed, deschedule spell Freya's Ward + */ + + if (uiAction) // Tower destruction, debuff leviathan AP & health + { + --uiActiveTowers; + } + + switch (uiAction) + { + case 0: // Activate hard-mode + events.ScheduleEvent(EVENT_THORIM_S_HAMMER, urand(30000,60000)); + events.ScheduleEvent(EVENT_MIMIRON_S_INFERNO, urand(30000,60000)); + events.ScheduleEvent(EVENT_HODIR_S_FURY, urand(30000,60000)); + events.ScheduleEvent(EVENT_FREYA_S_WARD, urand(30000,60000)); + uiActiveTowers=4; + break; + case 1: // Tower of Storms destroyed + events.CancelEvent(EVENT_THORIM_S_HAMMER); + break; + case 2: // Tower of Flames destroyed + events.CancelEvent(EVENT_MIMIRON_S_INFERNO); + break; + case 3: // Tower of Frost destroyed + events.CancelEvent(EVENT_HODIR_S_FURY); + break; + case 4: // Tower of Nature destroyed + events.CancelEvent(EVENT_FREYA_S_WARD); + break; + } + } +}; + +//#define BOSS_DEBUG + +struct boss_flame_leviathan_seatAI : public PassiveAI +{ + boss_flame_leviathan_seatAI(Creature *c) : PassiveAI(c), vehicle(c->GetVehicleKit()) + { + assert(vehicle); +#ifdef BOSS_DEBUG + me->SetReactState(REACT_AGGRESSIVE); +#endif + } + + Vehicle* vehicle; + +#ifdef BOSS_DEBUG + void MoveInLineOfSight(Unit *who) + { + if (who->GetTypeId() == TYPEID_PLAYER && CAST_PLR(who)->isGameMaster() + && !who->GetVehicle() && vehicle->GetPassenger(SEAT_TURRET)) + who->EnterVehicle(vehicle, SEAT_PLAYER); + } +#endif + + void PassengerBoarded(Unit* who, int8 seatId, bool apply) + { + if (!me->GetVehicle()) + return; + + if (seatId == SEAT_PLAYER) + { + if (!apply) + return; + + if (Creature* turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET))) + { + turret->setFaction(me->GetVehicleBase()->getFaction()); + turret->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable + turret->AI()->AttackStart(who); + } + if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) + { + device->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + device->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + else if (seatId == SEAT_TURRET) + { + if (apply) + return; + + if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) + { + device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + device->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable + } + } + } +}; + +struct boss_flame_leviathan_defense_turretAI : public TurretAI +{ + boss_flame_leviathan_defense_turretAI(Creature *c) : TurretAI(c) {} + + void DamageTaken(Unit* who, uint32 &damage) + { + if (!CanAIAttack(who)) + damage = 0; + } + + bool CanAIAttack(const Unit *who) const + { + if (who->GetTypeId() != TYPEID_PLAYER || !who->GetVehicle() || who->GetVehicleBase()->GetEntry() != 33114) + return false; + return true; + } +}; + +struct boss_flame_leviathan_overload_deviceAI : public PassiveAI +{ + boss_flame_leviathan_overload_deviceAI(Creature* pCreature) : PassiveAI(pCreature) {} + + void DoAction(const int32 param) + { + if (param == EVENT_SPELLCLICK) + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (me->GetVehicle()) + { + if (Unit* pPlayer = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) + { + pPlayer->ExitVehicle(); + me->GetVehicleBase()->CastSpell(pPlayer, SPELL_SMOKE_TRAIL, true); + if (Unit* leviathan = me->GetVehicleBase()->GetVehicleBase()) + pPlayer->GetMotionMaster()->MoveKnockbackFrom(leviathan->GetPositionX(), leviathan->GetPositionY(), 30, 30); + } + } + } + } +}; + +struct boss_flame_leviathan_safety_containerAI : public PassiveAI +{ + boss_flame_leviathan_safety_containerAI(Creature *c) : PassiveAI(c) {} + + void MovementInform(uint32 /*type*/, uint32 id) + { + if (id == me->GetEntry()) + { + if (Creature* pLiquid = DoSummon(MOB_LIQUID, me, 0)) + pLiquid->CastSpell(pLiquid, 62494, true); + me->DisappearAndDie(); // this will relocate creature to sky + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!me->GetVehicle() && me->isSummon() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) + me->GetMotionMaster()->MoveFall(409.8f, me->GetEntry()); + } +}; + +struct spell_pool_of_tarAI : public TriggerAI +{ + spell_pool_of_tarAI(Creature *c) : TriggerAI(c) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void DamageTaken(Unit * /*who*/, uint32 &damage) + { + damage = 0; + } + + void SpellHit(Unit* /*caster*/, const SpellEntry *spell) + { + if (spell->SchoolMask & SPELL_SCHOOL_MASK_FIRE && !me->HasAura(SPELL_BLAZE)) + me->CastSpell(me, SPELL_BLAZE, true); + } +}; + +struct npc_colossusAI : public ScriptedAI +{ + npc_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance *pInstance; + Position pPos; + + void JustDied(Unit* /*Who*/) + { + if (me->GetHomePosition().IsInDist(Center,50.f)) + { + if (pInstance) + pInstance->SetData(TYPE_COLOSSUS,pInstance->GetData(TYPE_COLOSSUS)+1); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + } +}; + +CreatureAI* GetAI_boss_flame_leviathan(Creature* pCreature) +{ + return new boss_flame_leviathanAI (pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan_seat(Creature* pCreature) +{ + return new boss_flame_leviathan_seatAI (pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan_defense_turret(Creature* pCreature) +{ + return new boss_flame_leviathan_defense_turretAI (pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan_overload_device(Creature* pCreature) +{ + return new boss_flame_leviathan_overload_deviceAI (pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan_safety_containerAI(Creature* pCreature) +{ + return new boss_flame_leviathan_safety_containerAI(pCreature); +} + +CreatureAI* GetAI_spell_pool_of_tar(Creature* pCreature) +{ + return new spell_pool_of_tarAI (pCreature); +} + +CreatureAI* GetAI_npc_colossus(Creature* pCreature) +{ + return new npc_colossusAI(pCreature); +} + +void AddSC_boss_flame_leviathan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_flame_leviathan"; + newscript->GetAI = &GetAI_boss_flame_leviathan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_flame_leviathan_seat"; + newscript->GetAI = &GetAI_boss_flame_leviathan_seat; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_flame_leviathan_defense_turret"; + newscript->GetAI = &GetAI_boss_flame_leviathan_defense_turret; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_flame_leviathan_overload_device"; + newscript->GetAI = &GetAI_boss_flame_leviathan_overload_device; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_flame_leviathan_safety_container"; + newscript->GetAI = &GetAI_boss_flame_leviathan_safety_containerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "spell_pool_of_tar"; + newscript->GetAI = &GetAI_spell_pool_of_tar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_colossus"; + newscript->GetAI = &GetAI_npc_colossus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_freya.cpp new file mode 100644 index 00000000000..ee995878a0e --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_freya.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO = -1603180, + SAY_AGGRO_WITH_ELDER = -1603181, + SAY_SLAY_1 = -1603182, + SAY_SLAY_2 = -1603183, + SAY_DEATH = -1603184, + SAY_BERSERK = -1603185, + SAY_SUMMON_CONSERVATOR = -1603186, + SAY_SUMMON_TRIO = -1603187, + SAY_SUMMON_LASHERS = -1603188, + SAY_YS_HELP = -1603189, + + // Elder Brightleaf + SAY_BRIGHTLEAF_AGGRO = -1603190, + SAY_BRIGHTLEAF_SLAY_1 = -1603191, + SAY_BRIGHTLEAF_SLAY_2 = -1603192, + SAY_BRIGHTLEAF_DEATH = -1603193, + + // Elder Ironbranch + SAY_IRONBRANCH_AGGRO = -1603194, + SAY_IRONBRANCH_SLAY_1 = -1603195, + SAY_IRONBRANCH_SLAY_2 = -1603196, + SAY_IRONBRANCH_DEATH = -1603197, + + // Elder Stonebark + SAY_STONEBARK_AGGRO = -1603198, + SAY_STONEBARK_SLAY_1 = -1603199, + SAY_STONEBARK_SLAY_2 = -1603200, + SAY_STONEBARK_DEATH = -1603201, +}; + +enum +{ + // Con-speed-atory timed achievement. + // TODO Should be started when 1st trash is killed. + ACHIEV_CON_SPEED_ATORY_START_EVENT = 21597, + SPELL_ACHIEVEMENT_CHECK = 65074, + + // Lumberjacked timed achievement. + // TODO should be started when 1st elder is killed. + // Spell should be casted when 3rd elder is killed. + ACHIEV_LUMBERJACKED = 21686, + SPELL_LUMBERJACKED_ACHIEVEMENT_CHECK = 65296, +}; + +struct boss_freyaAI : public BossAI +{ + boss_freyaAI(Creature* pCreature) : BossAI(pCreature, TYPE_FREYA) + { + } + + void Reset() + { + _Reset(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + + // cast is not rewarding the achievement. + // DoCast(SPELL_ACHIEVEMENT_CHECK); + instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_ACHIEVEMENT_CHECK); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + _EnterCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; +//SPELLS TODO: + +// + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_freya(Creature* pCreature) +{ + return new boss_freyaAI(pCreature); +} + +void AddSC_boss_freya() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_freya"; + newscript->GetAI = &GetAI_boss_freya; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_general_vezax.cpp new file mode 100644 index 00000000000..f84c638d3e3 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_general_vezax.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO = -1603290, + SAY_SLAY_1 = -1603291, + SAY_SLAY_2 = -1603292, + SAY_KITE = -1603293, + SAY_DEATH = -1603294, + SAY_BERSERK = -1603295, + SAY_HARDMODE_ON = -1603296, +}; diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_hodir.cpp new file mode 100644 index 00000000000..6facd8ac639 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_hodir.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO = -1603210, + SAY_SLAY_1 = -1603211, + SAY_SLAY_2 = -1603212, + SAY_FLASH_FREEZE = -1603213, + SAY_STALACTITE = -1603214, + SAY_DEATH = -1603215, + SAY_BERSERK = -1603216, + SAY_YS_HELP = -1603217, + SAY_HARD_MODE_MISSED = -1603218, +}; + +struct boss_hodirAI : public BossAI +{ + boss_hodirAI(Creature *pCreature) : BossAI(pCreature, TYPE_HODIR) + { + } + + void Reset() + { + _Reset(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + _EnterCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; +//SPELLS TODO: + +// + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_hodir(Creature* pCreature) +{ + return new boss_hodirAI(pCreature); +} + +void AddSC_boss_hodir() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hodir"; + newscript->GetAI = &GetAI_boss_hodir; + newscript->RegisterSelf(); + +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp new file mode 100644 index 00000000000..05f9ecd3c66 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_ignis.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +#define SPELL_FLAME_JETS 62680 +#define SPELL_SCORCH 62546 +#define SPELL_SLAG_POT 62717 + +enum Yells +{ + SAY_AGGRO = -1603220, + SAY_SLAY_1 = -1603221, + SAY_SLAY_2 = -1603222, + SAY_DEATH = -1603223, + SAY_SUMMON = -1603224, + SAY_SLAG_POT = -1603225, + SAY_SCORCH_1 = -1603226, + SAY_SCORCH_2 = -1603227, + SAY_BERSERK = -1603228, +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 20951, +}; + +struct boss_ignis_AI : public BossAI +{ + boss_ignis_AI(Creature *pCreature) : BossAI(pCreature, TYPE_IGNIS) {} + + uint32 uiFlameJetsTimer; + uint32 uiScorchTimer; + uint32 uiSlagPotTimer; + + void Reset() + { + _Reset(); + uiFlameJetsTimer = 32000; + uiScorchTimer = 100; + uiSlagPotTimer = 100; + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO,me); + _EnterCombat(); + + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetPositionY() < 150 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(false); + me->GetMotionMaster()->MoveTargetedHome(); + } + + if (uiFlameJetsTimer <= diff) + { + DoCast(SPELL_FLAME_JETS); + uiFlameJetsTimer = 25000; + } else uiFlameJetsTimer -= diff; + + if (uiScorchTimer <= diff) + { + DoScriptText(RAND(SAY_SCORCH_1,SAY_SCORCH_2), me); + DoCast(SPELL_SCORCH); + uiScorchTimer = 20000; + } else uiScorchTimer -= diff; + + if (uiSlagPotTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(SAY_SLAG_POT, me); + DoCast(pTarget, SPELL_SLAG_POT); + } + uiSlagPotTimer = 30000; + } else uiSlagPotTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ignis(Creature* pCreature) +{ + return new boss_ignis_AI (pCreature); +} +void AddSC_boss_ignis() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ignis"; + newscript->GetAI = &GetAI_boss_ignis; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp new file mode 100644 index 00000000000..2080b458a1b --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" +#include "Vehicle.h" + +#define SPELL_ARM_DEAD_DAMAGE RAID_MODE(63629,63979) +#define SPELL_TWO_ARM_SMASH RAID_MODE(63356,64003) +#define SPELL_ONE_ARM_SMASH RAID_MODE(63573,64006) +#define SPELL_STONE_SHOUT RAID_MODE(63716,64005) +#define SPELL_PETRIFY_BREATH RAID_MODE(62030,63980) + +#define SPELL_STONE_GRIP RAID_MODE(62166,63981) +#define SPELL_ARM_SWEEP RAID_MODE(63766,63983) + +enum Events +{ + EVENT_NONE = 0, + EVENT_SMASH, + EVENT_GRIP, + EVENT_SWEEP, +}; + +enum Yells +{ + SAY_AGGRO = -1603230, + SAY_SLAY_1 = -1603231, + SAY_SLAY_2 = -1603232, + SAY_LEFT_ARM_GONE = -1603233, + SAY_RIGHT_ARM_GONE = -1603234, + SAY_SHOCKWAVE = -1603235, + SAY_GRAB_PLAYER = -1603236, + SAY_DEATH = -1603237, + SAY_BERSERK = -1603238, +}; + +enum +{ + ACHIEV_DISARMED_START_EVENT = 21687, +}; + +struct boss_kologarnAI : public BossAI +{ + boss_kologarnAI(Creature *pCreature) : BossAI(pCreature, TYPE_KOLOGARN), vehicle(pCreature->GetVehicleKit()), + left(false), right(false) + { + assert(vehicle); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); // i think this is a hack, but there is no other way to disable his rotation + } + + Vehicle *vehicle; + bool left, right; + + void AttackStart(Unit *who) + { + me->Attack(who, true); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void KilledUnit(Unit* /*who*/) + { + DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_2), me); + } + + void PassengerBoarded(Unit *who, int8 /*seatId*/, bool apply) + { + if (who->GetTypeId() == TYPEID_UNIT) + { + if (who->GetEntry() == 32933) + left = apply; + else if (who->GetEntry() == 32934) + right = apply; + + if (!apply && instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT); + + who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + CAST_CRE(who)->SetReactState(REACT_PASSIVE); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + _EnterCombat(); + events.ScheduleEvent(EVENT_SMASH, 5000); + events.ScheduleEvent(EVENT_SWEEP, 10000); + events.ScheduleEvent(EVENT_GRIP, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + // TODO: because we are using hack, he is stunned and cannot cast, so we use triggered for every spell + switch(events.GetEvent()) + { + case EVENT_NONE: + break; + case EVENT_SMASH: + if (left && right) + DoCastVictim(SPELL_TWO_ARM_SMASH, true); + else if (left || right) + DoCastVictim(SPELL_ONE_ARM_SMASH, true); + events.RepeatEvent(15000); + break; + case EVENT_SWEEP: + if (left) + DoCastAOE(SPELL_ARM_SWEEP, true); + events.RepeatEvent(15000); + break; + case EVENT_GRIP: + if (right) + DoCastAOE(SPELL_STONE_GRIP, true); + events.RepeatEvent(15000); + break; + default: + events.PopEvent(); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kologarn(Creature* pCreature) +{ + return new boss_kologarnAI (pCreature); +} + +void AddSC_boss_kologarn() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kologarn"; + newscript->GetAI = &GetAI_boss_kologarn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_mimiron.cpp new file mode 100644 index 00000000000..2b9994d5d9b --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_mimiron.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO = -1603240, + SAY_HARDMODE_ON = -1603241, + SAY_MKII_ACTIVATE = -1603242, + SAY_MKII_SLAY_1 = -1603243, + SAY_MKII_SLAY_2 = -1603244, + SAY_MKII_DEATH = -1603245, + SAY_VX001_ACTIVATE = -1603246, + SAY_VX001_SLAY_1 = -1603247, + SAY_VX001_SLAY_2 = -1603248, + SAY_VX001_DEATH = -1603249, + SAY_AERIAL_ACTIVATE = -1603250, + SAY_AERIAL_SLAY_1 = -1603251, + SAY_AERIAL_SLAY_2 = -1603252, + SAY_AERIAL_DEATH = -1603253, + SAY_V07TRON_ACTIVATE = -1603254, + SAY_V07TRON_SLAY_1 = -1603255, + SAY_V07TRON_SLAY_2 = -1603256, + SAY_V07TRON_DEATH = -1603257, + SAY_BERSERK = -1603258, + SAY_YS_HELP = -1603259, +}; diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp new file mode 100644 index 00000000000..c61f1046474 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_razorscale.cpp @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: razorscale +SDAuthor: MaXiMiUS +SD%Complete: 65 +EndScriptData */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +//not in db +#define SAY_AGGRO -2000000 +#define SAY_KILL -2000001 +#define SAY_PHASE_2_TRANS -2000002 +#define SAY_PHASE_3_TRANS -2000003 +#define EMOTE_BREATH -2000004 + +enum Spells +{ + SPELL_FLAMEBUFFET = 64016, + SPELL_FIREBALL = 62796, + + SPELL_WINGBUFFET = 62666, + SPELL_FLAMEBREATH = 63317, + SPELL_FUSEARMOR = 64771, + SPELL_DEVOURINGFLAME = 63014 +}; + +enum Mobs +{ + NPC_DARK_RUNE_SENTINEL = 33846 +}; + +struct boss_razorscaleAI : public BossAI +{ + boss_razorscaleAI(Creature *pCreature) : BossAI(pCreature, TYPE_RAZORSCALE) {} + + uint8 Phase; + + uint32 FlameBreathTimer; + uint32 FuseArmorTimer; + uint32 DevouringFlameTimer; + uint32 FlameBuffetTimer; + uint32 SummonAddsTimer; + uint32 WingBuffetTimer; + uint32 FireballTimer; + //uint32 StunTimer; + //uint32 CastSpellsTimer; + + bool InitialSpawn; + bool IsFlying; + + void Reset() + { + Phase = 1; + + FlyPhase(Phase, 0); + + FlameBreathTimer = 20000; + DevouringFlameTimer = 2000; + FuseArmorTimer = 15000; + FlameBuffetTimer = 3000; + SummonAddsTimer = 45000; + WingBuffetTimer = 17000; + FireballTimer = 18000; + //StunTimer = 30000; + //CastSpellsTimer = 0; + + InitialSpawn = true; + IsFlying = true; + + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + } + + void JustDied(Unit* /*Killer*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetPositionY() > -60 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(false); + me->GetMotionMaster()->MoveTargetedHome(); + } + + // Victim is not controlled by a player (should never happen) + if (me->getVictim() && !me->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) + me->Kill(me->getVictim()); + + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 99 && Phase == 1) // TODO: Only land (exit Phase 1) if brought down with harpoon guns! This is important! + { + Phase = 2; + DoScriptText(SAY_PHASE_2_TRANS, me); // Audio: "Move quickly! She won't remain grounded for long!" + } + + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 33 && Phase == 2) // Health under 33%, Razorscale can't fly anymore. + { + Phase = 3; + DoScriptText(SAY_PHASE_3_TRANS, me); // "Razorscale lands permanently!" + // TODO: Cast Devouring Flame on all harpoon guns simultaneously, briefly after Phase 3 starts (lasts until the harpoon guns are destroyed) + } + + /* + if (Phase == 2 && CastSpellsTimer > 0) // 5 seconds of spell casting, after stun breaks, during Phase 2 + { + if (CastSpellsTimer <= diff) // 5 seconds are up + Phase = 1; // Return to phase 1 + else + CastSpellsTimer -= diff; + }*/ + + FlyPhase(Phase, diff); + + if (Phase >= 2) // Ground Phase (Phase 3 = permanent ground phase) + { + if (FuseArmorTimer <= diff) + { + DoCastVictim(SPELL_FUSEARMOR); + FuseArmorTimer = 10000; + } else FuseArmorTimer -= diff; + + if (WingBuffetTimer <= diff) + { + DoCast(SPELL_WINGBUFFET); + WingBuffetTimer = urand(7000,14000); + } else WingBuffetTimer -= diff; + + if (FireballTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) + { + me->SetInFront(pTarget); + DoCast(pTarget, SPELL_FIREBALL); + } + + FireballTimer = 18000; + } else FireballTimer -= diff; + + if (FlameBreathTimer <= diff) + { + DoScriptText(EMOTE_BREATH, me); // TODO: "Razorscale takes a deep breath..." + DoCastVictim(SPELL_FLAMEBREATH); + FlameBreathTimer = 15000; + WingBuffetTimer = 0; + } else FlameBreathTimer -= diff; + + if (Phase == 3) + { + if (FlameBuffetTimer <= diff) + { + DoScriptText(EMOTE_BREATH, me); + std::list pTargets; + SelectTargetList(pTargets, RAID_MODE(3,9), SELECT_TARGET_RANDOM, 100, true); + uint8 i = 0; + for (std::list::const_iterator itr = pTargets.begin(); itr != pTargets.end();) + { + if (me->HasInArc(M_PI, *itr)) + { + DoCast(*itr, SPELL_FLAMEBUFFET, true); + ++i; + } + if (++itr == pTargets.end() || i == RAID_MODE(3,9)) + { + AttackStart(*--itr); // seems to attack targets randomly during perma-ground phase.. + break; + } + } + FlameBuffetTimer = 25000; + } else FlameBuffetTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + else if (Phase == 1) //Flying Phase + { + if (InitialSpawn) + SummonAdds(); + + InitialSpawn = false; + + if (FireballTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) + { + me->SetInFront(pTarget); + DoCast(pTarget, SPELL_FIREBALL); + } + + FireballTimer = 18000; + } else FireballTimer -= diff; + + if (DevouringFlameTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) + { + me->SetInFront(pTarget); + DoCast(pTarget, SPELL_DEVOURINGFLAME); + } + + DevouringFlameTimer = 10000; + } else DevouringFlameTimer -= diff; + + if (SummonAddsTimer <= diff) + SummonAdds(); + else SummonAddsTimer -= diff; + } + } + + void SummonAdds() + { + // TODO: Adds will come in waves from mole machines. One mole can spawn a Dark Rune Watcher + // with 1-2 Guardians, or a lone Sentinel. Up to 4 mole machines can spawn adds at any given time. + uint8 random = urand(1,4); + for (uint8 i = 0; i < random; ++i) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) + { + float x = std::max(500.0f, std::min(650.0f, pTarget->GetPositionX() + irand(-20,20))); // Safe range is between 500 and 650 + float y = std::max(-235.0f, std::min(-145.0f, pTarget->GetPositionY() + irand(-20,20))); // Safe range is between -235 and -145 + float z = me->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); // Ground level + // TODO: Spawn drillers, then spawn adds 5 seconds later + if (Creature *pAdd = me->SummonCreature(NPC_DARK_RUNE_SENTINEL, x, y, z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)) + pAdd->AI()->AttackStart(pTarget); + } + } + SummonAddsTimer = 45000; + } + + void FlyPhase(uint8 Phase, const uint32 /*diff*/) + { + const float x = 587.54; + const float y = -174.92; + const float GroundLevel = me->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); + const float FlightHeight = GroundLevel + 4.0f; // TODO: Fly out of range of attacks (442 is sufficient height for this), minus ~(10*number of harpoon gun chains attached to Razorscale) + + if (Phase == 1) // Always flying during Phase 1 + IsFlying = true; + + me->SetFlying(IsFlying); + me->SendMovementFlagUpdate(); + me->SetSpeed(MOVE_WALK, IsFlying ? 7.0f : 2.5f, IsFlying); + + if (Phase == 1) // Flying Phase + { + if (me->GetPositionZ() > FlightHeight) // Correct height, stop moving + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + else // Incorrect height + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->GetMotionMaster()->MovePoint(0, x, y, FlightHeight + 0.5f); // Fly to slightly above (x, y, FlightHeight) + } + } + else // Ground Phases + { + const float CurrentGroundLevel = me->GetBaseMap()->GetHeight(me->GetPositionX(), me->GetPositionY(), MAX_HEIGHT); + //if (StunTimer == 30000) // Only fly around if not stunned. + //{ + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + if (IsFlying && me->GetPositionZ() > CurrentGroundLevel) // Fly towards the ground + me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), CurrentGroundLevel); + // TODO: Swoop up just before landing + else + IsFlying = false; // Landed, no longer flying + //} + + //if (!IsFlying &&Phase == 2 && CastSpellsTimer == 0 && StunTimer >= diff) // No longer flying, non-permanent ground phase, and not casting spells + //{ + // TODO: Add stun here. 30 second stun after Razorscale is grounded by harpoon guns + //StunTimer -= diff; + //} + //else if (StunTimer != 30000 && (StunTimer < 0 || Phase == 3)) // Stun is active, and needs to end. Note: Stun breaks instantly if Phase 3 starts + //{ + // TODO: Remove stun here. + //DoCast(SPELL_WINGBUFFET); // "Used in the beginning of the phase." + //WingBuffetTimer = urand(7000,14000); + //StunTimer = 30000; // Reinitialize the stun timer + //if (Phase == 2) // Non-permanent ground phase + // CastSpellsTimer = 5000; // Five seconds of casting before returning to Phase 1 + //} + } + } +}; + +CreatureAI* GetAI_boss_razorscale(Creature* pCreature) +{ + return new boss_razorscaleAI (pCreature); +} + +void AddSC_boss_razorscale() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_razorscale"; + newscript->GetAI = &GetAI_boss_razorscale; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_thorim.cpp new file mode 100644 index 00000000000..bbab077e10e --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_thorim.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Yells +{ + SAY_AGGRO_1 = -1603270, + SAY_AGGRO_2 = -1603271, + SAY_SPECIAL_1 = -1603272, + SAY_SPECIAL_2 = -1603273, + SAY_SPECIAL_3 = -1603274, + SAY_JUMPDOWN = -1603275, + SAY_SLAY_1 = -1603276, + SAY_SLAY_2 = -1603277, + SAY_BERSERK = -1603278, + SAY_WIPE = -1603279, + SAY_DEATH = -1603280, + SAY_END_NORMAL_1 = -1603281, + SAY_END_NORMAL_2 = -1603282, + SAY_END_NORMAL_3 = -1603283, + SAY_END_HARD_1 = -1603284, + SAY_END_HARD_2 = -1603285, + SAY_END_HARD_3 = -1603286, + SAY_YS_HELP = -1603287, +}; + +struct boss_thorimAI : public BossAI +{ + boss_thorimAI(Creature* pCreature) : BossAI(pCreature, TYPE_THORIM) + { + } + + void Reset() + { + _Reset(); + } + + void EnterEvadeMode() + { + DoScriptText(SAY_WIPE, me); + _EnterEvadeMode(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me); + _EnterCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; +//SPELLS TODO: + +// + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_thorim(Creature* pCreature) +{ + return new boss_thorimAI(pCreature); +} + +void AddSC_boss_thorim() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_thorim"; + newscript->GetAI = &GetAI_boss_thorim; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_xt002.cpp new file mode 100644 index 00000000000..58123951d2f --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_xt002.cpp @@ -0,0 +1,850 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + TODO: + Add achievments + Boombot explosion only hurt allies to the npc at the moment + Boombot explosion visual + Test the enrage timer + Fix gravity bomb - tractor beam. + Fix void zone spell + If the boss is to close to a scrap pile -> no summon + make the life sparks visible... +*/ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Spells +{ + SPELL_TYMPANIC_TANTRUM = 62776, + SPELL_SEARING_LIGHT_10 = 63018, + SPELL_SEARING_LIGHT_25 = 65121, + + SPELL_GRAVITY_BOMB_10 = 63024, + SPELL_GRAVITY_BOMB_25 = 63234, + SPELL_GRAVITY_BOMB_AURA_10 = 63025, + SPELL_GRAVITY_BOMB_AURA_25 = 63233, + + SPELL_HEARTBREAK_10 = 65737, + SPELL_HEARTBREAK_25 = 64193, + + SPELL_ENRAGE = 26662, + + //------------------VOID ZONE-------------------- + SPELL_VOID_ZONE_10 = 64203, + SPELL_VOID_ZONE_25 = 64235, + + // Life Spark + SPELL_STATIC_CHARGED_10 = 64227, + SPELL_STATIC_CHARGED_25 = 64236, + SPELL_SHOCK = 64230, + + //----------------XT-002 HEART------------------- + SPELL_EXPOSED_HEART = 63849, + + //---------------XM-024 PUMMELLER---------------- + SPELL_ARCING_SMASH = 8374, + SPELL_TRAMPLE = 5568, + SPELL_UPPERCUT = 10966, + + //------------------BOOMBOT----------------------- + SPELL_BOOM = 62834, +}; + +enum Timers +{ + TIMER_TYMPANIC_TANTRUM_MIN = 32000, + TIMER_TYMPANIC_TANTRUM_MAX = 36000, + TIMER_SEARING_LIGHT = 20000, + TIMER_SPAWN_LIFE_SPARK = 9000, + TIMER_GRAVITY_BOMB = 20000, + TIMER_HEART_PHASE = 30000, + TIMER_ENRAGE = 600000, + TIMER_GRAVITY_BOMB_AURA = 8900, + + TIMER_VOID_ZONE = 3000, + + // Life Spark + TIMER_SHOCK = 12000, + + // Pummeller + // Timers may be off + TIMER_ARCING_SMASH = 27000, + TIMER_TRAMPLE = 22000, + TIMER_UPPERCUT = 17000, + + TIMER_SPAWN_ADD = 12000, +}; + +enum Creatures +{ + NPC_VOID_ZONE = 34001, + NPC_LIFE_SPARK = 34004, + NPC_XT002_HEART = 33329, + NPC_XS013_SCRAPBOT = 33343, + NPC_XM024_PUMMELLER = 33344, + NPC_XE321_BOOMBOT = 33346, +}; + +enum Actions +{ + ACTION_ENTER_HARD_MODE = 0, +}; + +enum XT002Data +{ + DATA_TRANSFERED_HEALTH = 0, +}; + +enum Yells +{ + SAY_AGGRO = -1603300, + SAY_HEART_OPENED = -1603301, + SAY_HEART_CLOSED = -1603302, + SAY_TYMPANIC_TANTRUM = -1603303, + SAY_SLAY_1 = -1603304, + SAY_SLAY_2 = -1603305, + SAY_BERSERK = -1603306, + SAY_DEATH = -1603307, + SAY_SUMMON = -1603308, +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 21027, +}; + +//#define GRAVITY_BOMB_DMG_MIN_10 11700 +//#define GRAVITY_BOMB_DMG_MAX_10 12300 +//#define GRAVITY_BOMB_DMG_MIN_25 14625 +//#define GRAVITY_BOMB_DMG_MAX_25 15375 +//#define GRAVITY_BOMB_RADIUS 12 + +//#define VOID_ZONE_DMG_10 5000 +//#define VOID_ZONE_DMG_25 7500 +//#define VOID_ZONE_RADIUS + + +/************************************************ +-----------------SPAWN LOCATIONS----------------- +************************************************/ +//Shared Z-level +#define SPAWN_Z 412 +//Lower right +#define LR_X 796 +#define LR_Y -94 +//Lower left +#define LL_X 796 +#define LL_Y 57 +//Upper right +#define UR_X 890 +#define UR_Y -82 +//Upper left +#define UL_X 894 +#define UL_Y 62 + +/*------------------------------------------------------- + * + * XT-002 DECONSTRUCTOR + * + *///---------------------------------------------------- +struct boss_xt002_AI : public BossAI +{ + boss_xt002_AI(Creature *pCreature) : BossAI(pCreature, TYPE_XT002) + { + } + + uint32 uiSearingLightTimer; + uint32 uiSpawnLifeSparkTimer; + uint32 uiGravityBombTimer; + uint32 uiGravityBombAuraTimer; + uint32 uiTympanicTantrumTimer; + uint32 uiHeartPhaseTimer; + uint32 uiSpawnAddTimer; + uint32 uiEnrageTimer; + + bool searing_light_active; + uint64 uiSearingLightTarget; + + bool gravity_bomb_active; + uint64 uiGravityBombTarget; + + uint8 phase; + uint8 heart_exposed; + bool enraged; + + uint32 transferHealth; + bool enterHardMode; + bool hardMode; + + void Reset() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + + //Makes XT-002 to cast a light bomb 10 seconds after aggro. + uiSearingLightTimer = TIMER_SEARING_LIGHT/2; + uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; + uiGravityBombTimer = TIMER_GRAVITY_BOMB; + uiGravityBombAuraTimer = TIMER_GRAVITY_BOMB_AURA; + uiHeartPhaseTimer = TIMER_HEART_PHASE; + uiSpawnAddTimer = TIMER_SPAWN_ADD; + uiEnrageTimer = TIMER_ENRAGE; + + //Tantrum is casted a bit slower the first time. + uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX) * 2; + + searing_light_active = false; + gravity_bomb_active = false; + enraged = false; + hardMode = false; + enterHardMode = false; + + phase = 1; + heart_exposed = 0; + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + _EnterCombat(); + + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void DoAction(const int32 action) + { + switch (action) + { + case ACTION_ENTER_HARD_MODE: + if (!hardMode) + { + hardMode = true; + + // Enter hard mode + enterHardMode = true; + + // set max health + me->SetHealth(me->GetMaxHealth()); + + // Get his heartbreak buff + me->CastSpell(me, RAID_MODE(SPELL_HEARTBREAK_10, SPELL_HEARTBREAK_25), true); + } + break; + } + } + + void SetData(uint32 id, uint32 value) + { + switch(id) + { + case DATA_TRANSFERED_HEALTH: + transferHealth = value; + break; + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + _JustDied(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (enterHardMode) + { + SetPhaseOne(); + enterHardMode = false; + } + + // Handles spell casting. These spells only occur during phase 1 and hard mode + if (phase == 1 || hardMode) + { + if (uiSearingLightTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, RAID_MODE(SPELL_SEARING_LIGHT_10, SPELL_SEARING_LIGHT_25)); + uiSearingLightTarget = pTarget->GetGUID(); + } + uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; + if (hardMode) + searing_light_active = true; + uiSearingLightTimer = TIMER_SEARING_LIGHT; + } else uiSearingLightTimer -= diff; + + if (uiGravityBombTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, RAID_MODE(SPELL_GRAVITY_BOMB_10,SPELL_GRAVITY_BOMB_25)); + uiGravityBombTarget = pTarget->GetGUID(); + } + uiGravityBombTimer = TIMER_GRAVITY_BOMB; + gravity_bomb_active = true; + } else uiGravityBombTimer -= diff; + + if (uiTympanicTantrumTimer <= 0) + { + DoScriptText(SAY_TYMPANIC_TANTRUM, me); + DoCast(SPELL_TYMPANIC_TANTRUM); + uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX); + } else uiTympanicTantrumTimer -= diff; + } + + if (!hardMode) + { + if (phase == 1) + { + if (HealthBelowPct(75) && heart_exposed == 0) + { + exposeHeart(); + } + else if (HealthBelowPct(50) && heart_exposed == 1) + { + exposeHeart(); + } + else if (HealthBelowPct(25) && heart_exposed == 2) + { + exposeHeart(); + } + + DoMeleeAttackIfReady(); + } + else + { + //Stop moving + me->StopMoving(); + + //Start summoning adds + if (uiSpawnAddTimer <= diff) + { + DoScriptText(SAY_SUMMON, me); + + // Spawn Pummeller + switch (rand() % 4) + { + case 0: me->SummonCreature(NPC_XM024_PUMMELLER, LR_X, LR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 1: me->SummonCreature(NPC_XM024_PUMMELLER, LL_X, LL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 2: me->SummonCreature(NPC_XM024_PUMMELLER, UR_X, UR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 3: me->SummonCreature(NPC_XM024_PUMMELLER, UL_X, UL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + } + + // Spawn 5 Bombs + for (int8 n = 0; n < 5; n++) + { + //Some randomes are added so they wont spawn in a pile + switch(rand() % 4) + { + case 0: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(LR_X - 3, LR_X + 3), irand(LR_Y - 3, LR_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 1: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(LL_X - 3, LL_X + 3), irand(LL_Y - 3, LL_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 2: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(UR_X - 3, UR_X + 3), irand(UR_Y - 3, UR_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 3: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(UL_X - 3, UL_X + 3), irand(UL_Y - 3, UL_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + } + } + + //Spawn 5 Scrapbots + switch (rand() % 4) + { + case 0: me->SummonCreature(NPC_XE321_BOOMBOT, LR_X, LR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 1: me->SummonCreature(NPC_XE321_BOOMBOT, LL_X, LL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 2: me->SummonCreature(NPC_XE321_BOOMBOT, UR_X, UR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + case 3: me->SummonCreature(NPC_XE321_BOOMBOT, UL_X, UL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; + } + + uiSpawnAddTimer = TIMER_SPAWN_ADD; + } else uiSpawnAddTimer -= diff; + + // Is the phase over? + if (uiHeartPhaseTimer <= diff) + { + DoScriptText(SAY_HEART_CLOSED, me); + SetPhaseOne(); + } + else + uiHeartPhaseTimer -= diff; + } + } + else + { + // Adding life sparks when searing light debuff runs out if hard mode + if (searing_light_active) + { + if (uiSpawnLifeSparkTimer <= diff) + { + if (Unit *pSearingLightTarget = me->GetUnit(*me, uiSearingLightTarget)) + pSearingLightTarget->SummonCreature(NPC_LIFE_SPARK, pSearingLightTarget->GetPositionX(), pSearingLightTarget->GetPositionY(), pSearingLightTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); + uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; + searing_light_active = false; + } else uiSpawnLifeSparkTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + if (gravity_bomb_active) + { + if (uiGravityBombAuraTimer <= diff) + { + if (Unit *pGravityBombTarget = me->GetUnit(*me, uiGravityBombTarget)) + { + pGravityBombTarget->RemoveAurasDueToSpell(RAID_MODE(SPELL_GRAVITY_BOMB_10,SPELL_GRAVITY_BOMB_25)); + if (hardMode) + { + //Remains spawned for 3 minutes + pGravityBombTarget->SummonCreature(NPC_VOID_ZONE, pGravityBombTarget->GetPositionX(), pGravityBombTarget->GetPositionY(), pGravityBombTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); + } + } + + gravity_bomb_active = false; + uiGravityBombAuraTimer = TIMER_GRAVITY_BOMB_AURA; + //gravityBomb(); + } else uiGravityBombAuraTimer -= diff; + } + + //Enrage stuff + if (!enraged) + if (uiEnrageTimer <= diff) + { + DoScriptText(SAY_BERSERK, me); + DoCast(me, SPELL_ENRAGE); + enraged = true; + } else uiEnrageTimer -= diff; + } + + void exposeHeart() + { + //Make untargetable + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + + //Summon the heart npc + me->SummonCreature(NPC_XT002_HEART, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 7, 0, TEMPSUMMON_TIMED_DESPAWN, TIMER_HEART_PHASE); + + // Start "end of phase 2 timer" + uiHeartPhaseTimer = TIMER_HEART_PHASE; + + //Phase 2 has offically started + phase = 2; + heart_exposed++; + + //Reset the add spawning timer + uiSpawnAddTimer = TIMER_SPAWN_ADD; + + DoScriptText(SAY_HEART_OPENED, me); + } + + void SetPhaseOne() + { + uiSearingLightTimer = TIMER_SEARING_LIGHT / 2; + uiGravityBombTimer = TIMER_GRAVITY_BOMB; + uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX); + uiSpawnAddTimer = TIMER_SPAWN_ADD; + + if (!hardMode) + me->ModifyHealth(-((int32)transferHealth)); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + phase = 1; + } + + // TODO: put in comment and kept for reference. The spell should be fixed properly in spell system, if necessary. + ////Have to do this the custom way since the original spell messes up player movement + //void gravityBomb() + //{ + // uint32 maxDamage = RAID_MODE(GRAVITY_BOMB_DMG_MAX_10, GRAVITY_BOMB_DMG_MAX_25); + // uint32 minDamage = RAID_MODE(GRAVITY_BOMB_DMG_MIN_10, GRAVITY_BOMB_DMG_MIN_25); + // uint16 range = GRAVITY_BOMB_RADIUS; + // Map* pMap = me->GetMap(); + // if (pMap && pMap->IsDungeon()) + // { + // Map::PlayerList const &PlayerList = pMap->GetPlayers(); + // for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + // { + // //If a player is within the range of the spell + // if (i->getSource() && i->getSource()->GetDistance2d(pGravityBombTarget) <= range) + // { + // //Deal damage to the victim + // int32 damage = urand(minDamage, maxDamage); + // i->getSource()->ModifyHealth(-damage); + // me->SendSpellNonMeleeDamageLog(i->getSource(), SPELL_GRAVITY_BOMB_AURA_10, damage, SPELL_SCHOOL_MASK_SHADOW, 0, 0, false, 0); + + // //Replacing the tractor beam effect + // i->getSource()->JumpTo(pGravityBombTarget, 5); + // } + // } + // } + //} +}; + +CreatureAI* GetAI_boss_xt002(Creature* pCreature) +{ + return new boss_xt002_AI(pCreature); +} + +/*------------------------------------------------------- + * + * XT-002 HEART + * + *///---------------------------------------------------- +struct mob_xt002_heartAI : public ScriptedAI +{ + mob_xt002_heartAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_EXPOSED_HEART); + } + + ScriptedInstance* m_pInstance; + + void JustDied(Unit * /*victim*/) + { + if (m_pInstance) + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + if (pXT002->AI()) + pXT002->AI()->DoAction(ACTION_ENTER_HARD_MODE); + + //removes the aura + me->RemoveAurasDueToSpell(SPELL_EXPOSED_HEART); + } + + void DamageTaken(Unit * /*pDone*/, uint32 &damage) + { + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + if (pXT002->AI()) + { + uint32 health = me->GetHealth(); + health -= damage; + if (health < 0) + health = 0; + + pXT002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetMaxHealth() - health); + } + } +}; + +CreatureAI* GetAI_mob_xt002_heart(Creature* pCreature) +{ + return new mob_xt002_heartAI(pCreature); +} + +/*------------------------------------------------------- + * + * XS-013 SCRAPBOT + * + *///---------------------------------------------------- +struct mob_scrapbotAI : public ScriptedAI +{ + mob_scrapbotAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = me->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + me->GetMotionMaster()->MoveChase(pXT002); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + { + if (me->GetDistance2d(pXT002) <= 0.5) + { + // TODO Send raid message + + // Increase health with 1 percent + pXT002->ModifyHealth(pXT002->GetMaxHealth() * 0.01); + + // Despawns the scrapbot + me->ForcedDespawn(); + } + } + } +}; + +CreatureAI* GetAI_mob_scrapbot(Creature* pCreature) +{ + return new mob_scrapbotAI(pCreature); +} + +/*------------------------------------------------------- + * + * XM-024 PUMMELLER + * + *///---------------------------------------------------- +struct mob_pummellerAI : public ScriptedAI +{ + mob_pummellerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + int32 uiArcingSmashTimer; + int32 uiTrampleTimer; + int32 uiUppercutTimer; + + void Reset() + { + uiArcingSmashTimer = TIMER_ARCING_SMASH; + uiTrampleTimer = TIMER_TRAMPLE; + uiUppercutTimer = TIMER_UPPERCUT; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->IsWithinMeleeRange(me->getVictim())) + { + if (uiArcingSmashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCING_SMASH); + uiArcingSmashTimer = TIMER_ARCING_SMASH; + } else uiArcingSmashTimer -= diff; + + if (uiTrampleTimer <= diff) + { + DoCast(me->getVictim(), SPELL_TRAMPLE); + uiTrampleTimer = TIMER_TRAMPLE; + } else uiTrampleTimer -= diff; + + if (uiUppercutTimer <= diff) + { + DoCast(me->getVictim(), SPELL_UPPERCUT); + uiUppercutTimer = TIMER_UPPERCUT; + } else uiUppercutTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_pummeller(Creature* pCreature) +{ + return new mob_pummellerAI(pCreature); +} + +/*------------------------------------------------------- + * + * XE-321 BOOMBOT + * + *///---------------------------------------------------- +struct mob_boombotAI : public ScriptedAI +{ + mob_boombotAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + me->GetMotionMaster()->MoveChase(pXT002); + } + + void JustDied(Unit * /*killer*/) + { + DoCast(SPELL_BOOM); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) + { + if (me->GetDistance2d(pXT002) <= 0.5) + { + //Explosion + DoCast(me, SPELL_BOOM); + + //Despawns the boombot + me->ForcedDespawn(); + } + } + } +}; + +CreatureAI* GetAI_mob_boombot(Creature* pCreature) +{ + return new mob_boombotAI(pCreature); +} + +/*------------------------------------------------------- + * + * VOID ZONE + * + *///---------------------------------------------------- +struct mob_void_zoneAI : public ScriptedAI +{ + mob_void_zoneAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + + ScriptedInstance* m_pInstance; + uint32 uiVoidZoneTimer; + + void Reset() + { + uiVoidZoneTimer = TIMER_VOID_ZONE; + } + + void UpdateAI(const uint32 diff) + { + if (uiVoidZoneTimer <= diff) + { + //voidZone(); + uiVoidZoneTimer = TIMER_VOID_ZONE; + } else uiVoidZoneTimer -= diff; + } + + // TODO: put in comment and kept for reference. The spell should be fixed properly in spell system, if necessary. + //void voidZone() + //{ + // Map* pMap = me->GetMap(); + // if (pMap && pMap->IsDungeon()) + // { + // Map::PlayerList const &PlayerList = pMap->GetPlayers(); + // for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + // { + // // If a player is within the range of the spell + // if (i->getSource() && i->getSource()->GetDistance2d(me) <= 16) + // { + // // Deal damage to the victim + // int32 damage = RAID_MODE(VOID_ZONE_DMG_10, VOID_ZONE_DMG_25); + // me->DealDamage(i->getSource(), damage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); + // } + // } + // } + //} +}; + +CreatureAI* GetAI_mob_void_zone(Creature* pCreature) +{ + return new mob_void_zoneAI(pCreature); +} + +/*------------------------------------------------------- + * + * LIFE SPARK + * + *///---------------------------------------------------- +struct mob_life_sparkAI : public ScriptedAI +{ + mob_life_sparkAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + uint32 uiShockTimer; + + void Reset() + { + DoCast(me, RAID_MODE(SPELL_STATIC_CHARGED_10, SPELL_STATIC_CHARGED_25)); + uiShockTimer = 0; // first one is immediate. + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiShockTimer <= diff) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + DoCast(me->getVictim(), SPELL_SHOCK); + uiShockTimer = TIMER_SHOCK; + } + } + else uiShockTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_life_spark(Creature* pCreature) +{ + return new mob_life_sparkAI(pCreature); +} + +void AddSC_boss_xt002() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_xt002"; + newscript->GetAI = &GetAI_boss_xt002; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_xt002_heart"; + newscript->GetAI = &GetAI_mob_xt002_heart; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_scrapbot"; + newscript->GetAI = &GetAI_mob_scrapbot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_pummeller"; + newscript->GetAI = &GetAI_mob_pummeller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_boombot"; + newscript->GetAI = &GetAI_mob_boombot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_void_zone"; + newscript->GetAI = &GetAI_mob_void_zone; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_life_spark"; + newscript->GetAI = &GetAI_mob_life_spark; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_yoggsaron.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_yoggsaron.cpp new file mode 100644 index 00000000000..8f42f289204 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_yoggsaron.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum Sara_Yells +{ + SAY_SARA_PREFIGHT_1 = -1603310, + SAY_SARA_PREFIGHT_2 = -1603311, + SAY_SARA_AGGRO_1 = -1603312, + SAY_SARA_AGGRO_2 = -1603313, + SAY_SARA_AGGRO_3 = -1603314, + SAY_SARA_SLAY_1 = -1603315, + SAY_SARA_SLAY_2 = -1603316, + WHISP_SARA_INSANITY = -1603317, + SAY_SARA_PHASE2_1 = -1603318, + SAY_SARA_PHASE2_2 = -1603319, +}; + +enum YoggSaron_Yells +{ + SAY_PHASE2_1 = -1603330, + SAY_PHASE2_2 = -1603331, + SAY_PHASE2_3 = -1603332, + SAY_PHASE2_4 = -1603333, + SAY_PHASE2_5 = -1603334, + SAY_PHASE3 = -1603335, + SAY_VISION = -1603336, + SAY_SLAY_1 = -1603337, + SAY_SLAY_2 = -1603338, + WHISP_INSANITY_1 = -1603339, + WHISP_INSANITY_2 = -1603340, + SAY_DEATH = -1603341, +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 21001, +}; diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp new file mode 100644 index 00000000000..692dbf72473 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/instance_ulduar.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "ulduar.h" + +enum eGameObjects +{ + GO_KOLOGARN_CHEST_HERO = 195047, + GO_KOLOGARN_CHEST = 195046, + GO_THORIM_CHEST_HERO = 194315, + GO_THORIM_CHEST = 194314, + GO_HODIR_CHEST_HERO = 194308, + GO_HODIR_CHEST = 194307, + GO_FREYA_CHEST_HERO = 194325, + GO_FREYA_CHEST = 194324, + GO_LEVIATHAN_DOOR = 194905, + GO_LEVIATHAN_GATE = 194630 +}; + +struct instance_ulduar : public ScriptedInstance +{ + instance_ulduar(Map* pMap) : ScriptedInstance(pMap) { Initialize(); }; + + uint32 uiEncounter[MAX_ENCOUNTER]; + std::string m_strInstData; + uint8 flag; + + uint64 uiLeviathanGUID; + uint64 uiIgnisGUID; + uint64 uiRazorscaleGUID; + uint64 uiXT002GUID; + uint64 uiAssemblyGUIDs[3]; + uint64 uiKologarnGUID; + uint64 uiAuriayaGUID; + uint64 uiMimironGUID; + uint64 uiHodirGUID; + uint64 uiThorimGUID; + uint64 uiFreyaGUID; + uint64 uiVezaxGUID; + uint64 uiYoggSaronGUID; + uint64 uiAlgalonGUID; + uint64 uiLeviathanDoor[7]; + uint64 uiLeviathanGateGUID; + + uint64 uiKologarnChestGUID; + uint64 uiThorimChestGUID; + uint64 uiHodirChestGUID; + uint64 uiFreyaChestGUID; + + void Initialize() + { + uiLeviathanGUID = 0; + uiIgnisGUID = 0; + uiRazorscaleGUID = 0; + uiXT002GUID = 0; + uiKologarnGUID = 0; + uiAuriayaGUID = 0; + uiMimironGUID = 0; + uiHodirGUID = 0; + uiThorimGUID = 0; + uiFreyaGUID = 0; + uiVezaxGUID = 0; + uiYoggSaronGUID = 0; + uiAlgalonGUID = 0; + uiKologarnChestGUID = 0; + uiKologarnChestGUID = 0; + uiHodirChestGUID = 0; + uiFreyaChestGUID = 0; + uiLeviathanGateGUID = 0; + flag = 0; + + memset(&uiEncounter, 0, sizeof(uiEncounter)); + memset(&uiAssemblyGUIDs, 0, sizeof(uiAssemblyGUIDs)); + memset(&uiLeviathanDoor, 0, sizeof(uiLeviathanDoor)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (uiEncounter[i] == IN_PROGRESS) + return true; + } + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_LEVIATHAN: + uiLeviathanGUID = pCreature->GetGUID(); + break; + case NPC_IGNIS: + uiIgnisGUID = pCreature->GetGUID(); + break; + case NPC_RAZORSCALE: + uiRazorscaleGUID = pCreature->GetGUID(); + break; + case NPC_XT002: + uiXT002GUID = pCreature->GetGUID(); + break; + + // Assembly of Iron + case NPC_STEELBREAKER: + uiAssemblyGUIDs[0] = pCreature->GetGUID(); + break; + case NPC_MOLGEIM: + uiAssemblyGUIDs[1] = pCreature->GetGUID(); + break; + case NPC_BRUNDIR: + uiAssemblyGUIDs[2] = pCreature->GetGUID(); + break; + + case NPC_KOLOGARN: + uiKologarnGUID = pCreature->GetGUID(); + break; + case NPC_AURIAYA: + uiAuriayaGUID = pCreature->GetGUID(); + break; + case NPC_MIMIRON: + uiMimironGUID = pCreature->GetGUID(); + break; + case NPC_HODIR: + uiHodirGUID = pCreature->GetGUID(); + break; + case NPC_THORIM: + uiThorimGUID = pCreature->GetGUID(); + break; + case NPC_FREYA: + uiFreyaGUID = pCreature->GetGUID(); + break; + case NPC_VEZAX: + uiVezaxGUID = pCreature->GetGUID(); + break; + case NPC_YOGGSARON: + uiYoggSaronGUID = pCreature->GetGUID(); + break; + case NPC_ALGALON: + uiAlgalonGUID = pCreature->GetGUID(); + break; + } + + } + + void OnGameObjectCreate(GameObject* pGO, bool add) + { + switch(pGO->GetEntry()) + { + case GO_KOLOGARN_CHEST_HERO: + case GO_KOLOGARN_CHEST: + uiKologarnChestGUID = add ? pGO->GetGUID() : NULL; + break; + case GO_THORIM_CHEST_HERO: + case GO_THORIM_CHEST: + uiThorimChestGUID = add ? pGO->GetGUID() : NULL; + break; + case GO_HODIR_CHEST_HERO: + case GO_HODIR_CHEST: + uiHodirChestGUID = add ? pGO->GetGUID() : NULL; + break; + case GO_FREYA_CHEST_HERO: + case GO_FREYA_CHEST: + uiFreyaChestGUID = add ? pGO->GetGUID() : NULL; + break; + case GO_LEVIATHAN_DOOR: + uiLeviathanDoor[flag] = pGO->GetGUID(); + HandleGameObject(NULL, true, pGO); + flag++; + if (flag == 7) + flag =0; + break; + case GO_LEVIATHAN_GATE: + uiLeviathanGateGUID = pGO->GetGUID(); + HandleGameObject(NULL, false, pGO); + break; + } + } + + void ProcessEvent(GameObject* pGO, uint32 uiEventId) + { + // Flame Leviathan's Tower Event triggers + Creature* pFlameLeviathan = instance->GetCreature(NPC_LEVIATHAN); + if (pFlameLeviathan && pFlameLeviathan->isAlive()) //No leviathan, no event triggering ;) + switch(uiEventId) + { + case EVENT_TOWER_OF_STORM_DESTROYED: + pFlameLeviathan->AI()->DoAction(1); + break; + case EVENT_TOWER_OF_FROST_DESTROYED: + pFlameLeviathan->AI()->DoAction(2); + break; + case EVENT_TOWER_OF_FLAMES_DESTROYED: + pFlameLeviathan->AI()->DoAction(3); + break; + case EVENT_TOWER_OF_NATURE_DESTROYED: + pFlameLeviathan->AI()->DoAction(4); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + if (type != TYPE_COLOSSUS) + uiEncounter[type] = data; + + switch(type) + { + /*case TYPE_IGNIS: + case TYPE_RAZORSCALE: + case TYPE_XT002: + case TYPE_ASSEMBLY: + case TYPE_AURIAYA: + case TYPE_MIMIRON: + case TYPE_VEZAX: + case TYPE_YOGGSARON: + break;*/ + case TYPE_LEVIATHAN: + if (data == IN_PROGRESS) + { + for (uint8 uiI = 0; uiI < 7; uiI++) + HandleGameObject(uiLeviathanDoor[uiI],false); + } + else + { + for (uint8 uiI = 0; uiI < 7; uiI++) + HandleGameObject(uiLeviathanDoor[uiI],true); + } + break; + case TYPE_KOLOGARN: + if (data == DONE) + if (GameObject* pGO = instance->GetGameObject(uiKologarnChestGUID)) + pGO->SetRespawnTime(pGO->GetRespawnDelay()); + break; + case TYPE_HODIR: + if (data == DONE) + if (GameObject* pGO = instance->GetGameObject(uiHodirChestGUID)) + pGO->SetRespawnTime(pGO->GetRespawnDelay()); + break; + case TYPE_THORIM: + if (data == DONE) + if (GameObject* pGO = instance->GetGameObject(uiThorimChestGUID)) + pGO->SetRespawnTime(pGO->GetRespawnDelay()); + break; + case TYPE_FREYA: + if (data == DONE) + if (GameObject* pGO = instance->GetGameObject(uiFreyaChestGUID)) + pGO->SetRespawnTime(pGO->GetRespawnDelay()); + break; + case TYPE_COLOSSUS: + if (data == 2) + { + if (Creature* pBoss = instance->GetCreature(uiLeviathanGUID)) + pBoss->AI()->DoAction(10); + if (GameObject* pGate = instance->GetGameObject(uiLeviathanGateGUID)) + pGate->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + } + break; + default: + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + saveStream << uiEncounter[i] << " "; + + m_strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case TYPE_LEVIATHAN: return uiLeviathanGUID; + case TYPE_IGNIS: return uiIgnisGUID; + case TYPE_RAZORSCALE: return uiRazorscaleGUID; + case TYPE_XT002: return uiXT002GUID; + case TYPE_KOLOGARN: return uiKologarnGUID; + case TYPE_AURIAYA: return uiAuriayaGUID; + case TYPE_MIMIRON: return uiMimironGUID; + case TYPE_HODIR: return uiMimironGUID; + case TYPE_THORIM: return uiThorimGUID; + case TYPE_FREYA: return uiFreyaGUID; + case TYPE_VEZAX: return uiVezaxGUID; + case TYPE_YOGGSARON: return uiYoggSaronGUID; + case TYPE_ALGALON: return uiAlgalonGUID; + + // Assembly of Iron + case DATA_STEELBREAKER: return uiAssemblyGUIDs[0]; + case DATA_MOLGEIM: return uiAssemblyGUIDs[1]; + case DATA_BRUNDIR: return uiAssemblyGUIDs[2]; + } + + return 0; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_LEVIATHAN: + case TYPE_IGNIS: + case TYPE_RAZORSCALE: + case TYPE_XT002: + case TYPE_ASSEMBLY: + case TYPE_KOLOGARN: + case TYPE_AURIAYA: + case TYPE_MIMIRON: + case TYPE_HODIR: + case TYPE_THORIM: + case TYPE_FREYA: + case TYPE_VEZAX: + case TYPE_YOGGSARON: + case TYPE_ALGALON: + case TYPE_COLOSSUS: + return uiEncounter[type]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "U U " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2] << " " << uiEncounter[3] + << uiEncounter[4] << " " << uiEncounter[5] << " " << uiEncounter[6] << " " << uiEncounter[7] + << uiEncounter[8] << " " << uiEncounter[9] << " " << uiEncounter[10] << " " << uiEncounter[11] + << uiEncounter[12] << " " << uiEncounter[13] << " " << uiEncounter[14]; + + m_strInstData = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return m_strInstData; + } + + void Load(const char* strIn) + { + if (!strIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(strIn); + + char dataHead1, dataHead2; + uint32 data0, data1, data2, data3, data4, data5, data6, + data7, data8, data9, data10, data11, data12, data13, data14; + + std::istringstream loadStream(strIn); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6 + >> data7 >> data8 >> data9 >> data10 >> data11 >> data12 >> data13 >> data14; + + if (dataHead1 == 'U' && dataHead2 == 'U') + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + loadStream >> uiEncounter[i]; + + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + } + } + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_ulduar(Map* pMap) +{ + return new instance_ulduar(pMap); +} + +void AddSC_instance_ulduar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_ulduar"; + newscript->GetInstanceData = &GetInstanceData_instance_ulduar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h new file mode 100644 index 00000000000..cb11bcb579c --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008 - 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_ULDUAR_H +#define DEF_ULDUAR_H + +enum eTypes +{ + MAX_ENCOUNTER = 15, + + TYPE_LEVIATHAN = 0, + TYPE_IGNIS = 1, + TYPE_RAZORSCALE = 2, + TYPE_XT002 = 3, + TYPE_ASSEMBLY = 4, + TYPE_KOLOGARN = 5, + TYPE_AURIAYA = 6, + TYPE_MIMIRON = 7, + TYPE_HODIR = 8, + TYPE_THORIM = 9, + TYPE_FREYA = 10, + TYPE_VEZAX = 11, + TYPE_YOGGSARON = 12, + TYPE_ALGALON = 13, + TYPE_COLOSSUS = 14, + + DATA_STEELBREAKER = 20, + DATA_MOLGEIM = 21, + DATA_BRUNDIR = 22, + DATA_RUNEMASTER_MOLGEIM = 23, + DATA_STORMCALLER_BRUNDIR = 24, + + NPC_LEVIATHAN = 33113, + NPC_IGNIS = 33118, + NPC_RAZORSCALE = 33186, + NPC_XT002 = 33293, + NPC_STEELBREAKER = 32867, + NPC_MOLGEIM = 32927, + NPC_BRUNDIR = 32857, + NPC_KOLOGARN = 32930, + NPC_AURIAYA = 33515, + NPC_MIMIRON = 33350, + NPC_HODIR = 32845, + NPC_THORIM = 32865, + NPC_FREYA = 32906, + NPC_VEZAX = 33271, + NPC_YOGGSARON = 33288, + NPC_ALGALON = 32871, + + EVENT_TOWER_OF_STORM_DESTROYED = 21031, + EVENT_TOWER_OF_FROST_DESTROYED = 21032, + EVENT_TOWER_OF_FLAMES_DESTROYED = 21033, + EVENT_TOWER_OF_NATURE_DESTROYED = 21030 +}; + +#endif diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar_teleporter.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar_teleporter.cpp new file mode 100644 index 00000000000..44f9e86b69c --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar_teleporter.cpp @@ -0,0 +1,92 @@ +#include "ScriptedPch.h" +#include "ulduar.h" + +/* +The teleporter appears to be active and stable. + +- Expedition Base Camp +- Formation Grounds +- Colossal Forge +- Scrapyard +- Antechamber of Ulduar +- Shattered Walkway +- Conservatory of Life +*/ + +#define BASE_CAMP 200 +#define GROUNDS 201 +#define FORGE 202 +#define SCRAPYARD 203 +#define ANTECHAMBER 204 +#define WALKWAY 205 +#define CONSERVATORY 206 + +bool GoHello_ulduar_teleporter(Player *pPlayer, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + if (!pInstance) return true; + + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Expedition Base Camp", GOSSIP_SENDER_MAIN, BASE_CAMP); + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Formation Grounds", GOSSIP_SENDER_MAIN, GROUNDS); + if (pInstance->GetData(TYPE_LEVIATHAN) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Colossal Forge", GOSSIP_SENDER_MAIN, FORGE); + if (pInstance->GetData(TYPE_XT002) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Scrapyard", GOSSIP_SENDER_MAIN, SCRAPYARD); + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Antechamber of Ulduar", GOSSIP_SENDER_MAIN, ANTECHAMBER); + if (pInstance->GetData(TYPE_KOLOGARN) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Shattered Walkway", GOSSIP_SENDER_MAIN, WALKWAY); + if (pInstance->GetData(TYPE_AURIAYA) == DONE) + pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Conservatory of Life", GOSSIP_SENDER_MAIN, CONSERVATORY); + } + } + } + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pGO->GetGUID()); + + return true; +} + +bool GOSelect_ulduar_teleporter(Player *pPlayer, GameObject * /*pGO*/, uint32 sender, uint32 action) +{ + if (sender != GOSSIP_SENDER_MAIN) return true; + if (!pPlayer->getAttackers().empty()) return true; + + switch(action) + { + case BASE_CAMP: + pPlayer->TeleportTo(603, -706.122, -92.6024, 429.876, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case GROUNDS: + pPlayer->TeleportTo(603, 131.248, -35.3802, 409.804, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case FORGE: + pPlayer->TeleportTo(603, 553.233, -12.3247, 409.679, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case SCRAPYARD: + pPlayer->TeleportTo(603, 926.292, -11.4635, 418.595, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case ANTECHAMBER: + pPlayer->TeleportTo(603, 1498.09, -24.246, 420.967, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case WALKWAY: + pPlayer->TeleportTo(603, 1859.45, -24.1, 448.9, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + case CONSERVATORY: + pPlayer->TeleportTo(603, 2086.27, -24.3134, 421.239, 0); + pPlayer->CLOSE_GOSSIP_MENU(); break; + } + + return true; +} + +void AddSC_ulduar_teleporter() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "ulduar_teleporter"; + newscript->pGOHello = &GoHello_ulduar_teleporter; + newscript->pGOSelect = &GOSelect_ulduar_teleporter; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp new file mode 100644 index 00000000000..77f824c48d5 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ingvar_The_Plunderer +SD%Complete: 95 +SDComment: Some Problems with Annhylde Movement, Blizzlike Timers +SDCategory: Udgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum Yells +{ + //Yells Ingvar + YELL_AGGRO_1 = -1574005, + YELL_AGGRO_2 = -1574006, + + YELL_DEAD_1 = -1574007, + YELL_DEAD_2 = -1574008, + + YELL_KILL_1 = -1574009, + YELL_KILL_2 = -1574010, +}; + +enum Creatures +{ + MOB_INGVAR_HUMAN = 23954, + MOB_ANNHYLDE_THE_CALLER = 24068, + MOB_INGVAR_UNDEAD = 23980, +}; + +enum Spells +{ + //Ingvar Spells human form + SPELL_CLEAVE = 42724, + SPELL_SMASH = 42669, + H_SPELL_SMASH = 59706, + SPELL_STAGGERING_ROAR = 42708, + H_SPELL_STAGGERING_ROAR = 59708, + SPELL_ENRAGE = 42705, + H_SPELL_ENRAGE = 59707, + + SPELL_INGVAR_FEIGN_DEATH = 42795, + SPELL_SUMMON_BANSHEE = 42912, + SPELL_SCOURG_RESURRECTION = 42863, // Spawn resurrect effect around Ingvar + + //Ingvar Spells undead form + SPELL_DARK_SMASH = 42723, + SPELL_DREADFUL_ROAR = 42729, + H_SPELL_DREADFUL_ROAR = 59734, + SPELL_WOE_STRIKE = 42730, + H_SPELL_WOE_STRIKE = 59735, + + ENTRY_THROW_TARGET = 23996, + SPELL_SHADOW_AXE_SUMMON = 42749 +}; + +struct boss_ingvar_the_plundererAI : public ScriptedAI +{ + boss_ingvar_the_plundererAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bIsUndead; + bool bEventInProgress; + + uint32 uiCleaveTimer; + uint32 uiSmashTimer; + uint32 uiEnrageTimer; + uint32 uiRoarTimer; + uint32 uiSpawnResTimer; + + void Reset() + { + if (bIsUndead) + me->UpdateEntry(MOB_INGVAR_HUMAN); + + bIsUndead = false; + bEventInProgress = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + + uiCleaveTimer = 2000; + uiSmashTimer = 5000; + uiEnrageTimer = 10000; + uiRoarTimer = 15000; + + uiSpawnResTimer = 3000; + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, NOT_STARTED); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth() && !bIsUndead) + { + //DoCast(me, SPELL_INGVAR_FEIGN_DEATH, true); // Dont work ??? + // visuel hack + me->SetHealth(0); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + // visuel hack end + + bEventInProgress = true; + bIsUndead = true; + + DoScriptText(YELL_DEAD_1,me); + } + + if (bEventInProgress) + { + damage = 0; + } + } + + void StartZombiePhase() + { + bIsUndead = true; + bEventInProgress = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->UpdateEntry(MOB_INGVAR_UNDEAD); + me->SetInCombatWith(me->getVictim()); + me->GetMotionMaster()->MoveChase(me->getVictim()); + + DoScriptText(YELL_AGGRO_2,me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO_1,me); + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(YELL_DEAD_2,me); + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + if (bIsUndead) + DoScriptText(YELL_KILL_1,me); + else + DoScriptText(YELL_KILL_2,me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (bEventInProgress) + { + if (uiSpawnResTimer) + if (uiSpawnResTimer <= diff) + { + DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position + // DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ? + uiSpawnResTimer = 0; + } else uiSpawnResTimer -= diff; + + return; + } + + if (uiCleaveTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me->getVictim(), SPELL_WOE_STRIKE); + else + DoCast(me->getVictim(), SPELL_CLEAVE); + uiCleaveTimer = rand()%5000 + 2000; + } + } else uiCleaveTimer -= diff; + + if (uiSmashTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me->getVictim(), SPELL_DARK_SMASH); + else + DoCast(me->getVictim(), SPELL_SMASH); + uiSmashTimer = 10000; + } + } else uiSmashTimer -= diff; + + if (!bIsUndead) + { + if (uiEnrageTimer <= diff) + { + DoCast(me, SPELL_ENRAGE); + uiEnrageTimer = 10000; + } else uiEnrageTimer -= diff; + } else // In Undead form used to summon weapon + { + if (uiEnrageTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + // Spawn target for Axe + Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + if (pTarget) + { + me->SummonCreature(ENTRY_THROW_TARGET,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,2000); + + DoCast(me, SPELL_SHADOW_AXE_SUMMON); + } + uiEnrageTimer = 30000; + } + } else uiEnrageTimer -= diff; + } + + if (uiRoarTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me, SPELL_DREADFUL_ROAR); + else + DoCast(me, SPELL_STAGGERING_ROAR); + uiRoarTimer = 10000; + } + } else uiRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ingvar_the_plunderer(Creature* pCreature) +{ + return new boss_ingvar_the_plundererAI(pCreature); +} + +enum eSpells +{ +//we don't have that text in db so comment it until we get this text +// YELL_RESSURECT = -1574025, + +//Spells for Annhylde + SPELL_SCOURG_RESURRECTION_HEAL = 42704, //Heal Max + DummyAura + SPELL_SCOURG_RESURRECTION_BEAM = 42857, //Channeling Beam of Annhylde + SPELL_SCOURG_RESURRECTION_DUMMY = 42862, //Some Emote Dummy? + SPELL_INGVAR_TRANSFORM = 42796 +}; + +struct mob_annhylde_the_callerAI : public ScriptedAI +{ + mob_annhylde_the_callerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + float x,y,z; + ScriptedInstance* pInstance; + uint32 uiResurectTimer; + uint32 uiResurectPhase; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_HOVER); + me->SetSpeed(MOVE_SWIM , 1.0f); + me->SetSpeed(MOVE_RUN , 1.0f); + me->SetSpeed(MOVE_WALK , 1.0f); + //me->SetSpeed(MOVE_FLIGHT , 1.0f); + + me->GetPosition(x,y,z); + DoTeleportTo(x+1,y,z+30); + + Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + me->GetMotionMaster()->MovePoint(1,x,y,z+15); + +// DoScriptText(YELL_RESSURECT,me); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + Unit* ingvar = Unit::GetUnit((*me), pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + switch (id) + { + case 1: + ingvar->RemoveAura(SPELL_SUMMON_BANSHEE); + ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_DUMMY,true); + DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); + uiResurectTimer = 8000; + uiResurectPhase = 1; + break; + case 2: + me->SetVisibility(VISIBILITY_OFF); + me->DealDamage(me,me->GetHealth()); + me->RemoveCorpse(); + break; + } + } + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit * /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (uiResurectTimer) + if (uiResurectTimer <= diff) + { + if (uiResurectPhase == 1) + { + Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + ingvar->SetStandState(UNIT_STAND_STATE_STAND); + ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_HEAL,false); + } + uiResurectTimer = 3000; + uiResurectPhase = 2; + } + else if (uiResurectPhase == 2) + { + if (Creature* ingvar = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0)) + { + ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); + + if (boss_ingvar_the_plundererAI* pAI = CAST_AI(boss_ingvar_the_plundererAI, ingvar->AI())) + pAI->StartZombiePhase(); + + me->GetMotionMaster()->MovePoint(2,x+1,y,z+30); + ++uiResurectPhase; + uiResurectTimer = 0; + } + } + + } else uiResurectTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_annhylde_the_caller(Creature* pCreature) +{ + return new mob_annhylde_the_callerAI (pCreature); +} + +enum eShadowAxe +{ + SPELL_SHADOW_AXE_DAMAGE = 42750, + H_SPELL_SHADOW_AXE_DAMAGE = 59719 +}; + +struct mob_ingvar_throw_dummyAI : public ScriptedAI +{ + mob_ingvar_throw_dummyAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 uiDespawnTimer; + + void Reset() + { + Unit *pTarget = me->FindNearestCreature(ENTRY_THROW_TARGET,50); + if (pTarget) + { + DoCast(me, SPELL_SHADOW_AXE_DAMAGE); + float x,y,z; + pTarget->GetPosition(x,y,z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + } + uiDespawnTimer = 7000; + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit * /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (uiDespawnTimer <= diff) + { + me->DealDamage(me,me->GetHealth()); + me->RemoveCorpse(); + uiDespawnTimer = 0; + } else uiDespawnTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_ingvar_throw_dummy(Creature* pCreature) +{ + return new mob_ingvar_throw_dummyAI (pCreature); +} + +void AddSC_boss_ingvar_the_plunderer() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ingvar_the_plunderer"; + newscript->GetAI = &GetAI_boss_ingvar_the_plunderer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_annhylde_the_caller"; + newscript->GetAI = &GetAI_mob_annhylde_the_caller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ingvar_throw_dummy"; + newscript->GetAI = &GetAI_mob_ingvar_throw_dummy; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp new file mode 100644 index 00000000000..d69f0eee846 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Prince_Keleseth +SD%Complete: 90 +SDComment: Needs Prince Movements, Needs adjustments to blizzlike timers, Needs Shadowbolt castbar, Needs right Ressurect Visual, Needs Some Heroic Spells +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum eEnums +{ + ACHIEVEMENT_ON_THE_ROCKS = 1919, + + SPELL_SHADOWBOLT = 43667, + SPELL_SHADOWBOLT_HEROIC = 59389, + SPELL_FROST_TOMB = 48400, + SPELL_FROST_TOMB_SUMMON = 42714, + SPELL_DECREPIFY = 42702, + SPELL_SCOURGE_RESSURRECTION = 42704, + CREATURE_FROSTTOMB = 23965, + CREATURE_SKELETON = 23970, + + SAY_AGGRO = -1574000, + SAY_FROST_TOMB = -1574001, + SAY_SKELETONS = -1574002, + SAY_KILL = -1574003, + SAY_DEATH = -1574004 +}; + +#define SKELETONSPAWN_Z 42.8668 + +float SkeletonSpawnPoint[5][5]= +{ + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, +}; + +float AttackLoc[3]={197.636, 194.046, 40.8164}; + +bool ShatterFrostTomb; // needed for achievement: On The Rocks(1919) + +struct mob_frost_tombAI : public ScriptedAI +{ + mob_frost_tombAI(Creature *c) : ScriptedAI(c) + { + FrostTombGUID = 0; + } + + uint64 FrostTombGUID; + + void SetPrisoner(Unit* uPrisoner) + { + FrostTombGUID = uPrisoner->GetGUID(); + } + + void Reset(){ FrostTombGUID = 0; } + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void JustDied(Unit *killer) + { + if (killer->GetGUID() != me->GetGUID()) + ShatterFrostTomb = true; + + if (FrostTombGUID) + { + Unit* FrostTomb = Unit::GetUnit((*me),FrostTombGUID); + if (FrostTomb) + FrostTomb->RemoveAurasDueToSpell(SPELL_FROST_TOMB); + } + } + + void UpdateAI(const uint32 /*diff*/) + { + Unit* temp = Unit::GetUnit((*me),FrostTombGUID); + if ((temp && temp->isAlive() && !temp->HasAura(SPELL_FROST_TOMB)) || !temp) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } +}; + +struct boss_kelesethAI : public ScriptedAI +{ + boss_kelesethAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 FrostTombTimer; + uint32 SummonSkeletonsTimer; + uint32 RespawnSkeletonsTimer; + uint32 ShadowboltTimer; + uint64 SkeletonGUID[5]; + bool Skeletons; + bool RespawnSkeletons; + + void Reset() + { + ShadowboltTimer = 0; + Skeletons = false; + + ShatterFrostTomb = false; + + ResetTimer(); + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (IsHeroic() && !ShatterFrostTomb) + { + AchievementEntry const *AchievOnTheRocks = GetAchievementStore()->LookupEntry(ACHIEVEMENT_ON_THE_ROCKS); + if (AchievOnTheRocks) + { + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievOnTheRocks); + } + } + } + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); + } + + void ResetTimer(uint32 inc = 0) + { + SummonSkeletonsTimer = 5000 + inc; + FrostTombTimer = 28000 + inc; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowboltTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + me->CastSpell(pTarget, DUNGEON_MODE(SPELL_SHADOWBOLT, SPELL_SHADOWBOLT_HEROIC), true); + ShadowboltTimer = 10000; + } else ShadowboltTimer -= diff; + + if (!Skeletons) + if ((SummonSkeletonsTimer <= diff)) + { + Creature* Skeleton; + DoScriptText(SAY_SKELETONS, me); + for (uint8 i = 0; i < 5; ++i) + { + Skeleton = me->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1] , SKELETONSPAWN_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); + if (Skeleton) + { + Skeleton->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Skeleton->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY() , me->GetPositionZ()); + Skeleton->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Skeleton); + } + } + Skeletons = true; + } else SummonSkeletonsTimer -= diff; + + if (FrostTombTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (pTarget->isAlive()) + { + //DoCast(pTarget, SPELL_FROST_TOMB_SUMMON, true); + if (Creature *pChains = me->SummonCreature(CREATURE_FROSTTOMB, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) + { + CAST_AI(mob_frost_tombAI, pChains->AI())->SetPrisoner(pTarget); + pChains->CastSpell(pTarget, SPELL_FROST_TOMB, true); + + DoScriptText(SAY_FROST_TOMB, me); + } + } + FrostTombTimer = 15000; + } else FrostTombTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_vrykul_skeletonAI : public ScriptedAI +{ + mob_vrykul_skeletonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 Respawn_Time; + uint64 Target_Guid; + uint32 Decrepify_Timer; + + bool isDead; + + void Reset() + { + Respawn_Time = 12000; + Decrepify_Timer = urand(10000,20000); + isDead = false; + } + + void EnterCombat(Unit * /*who*/){} + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() == me->GetGUID()) + return; + + if (damage >= me->GetHealth()) + { + PretendToDie(); + damage = 0; + } + } + + void PretendToDie() + { + isDead = true; + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + }; + + void Resurrect() + { + isDead = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_SCOURGE_RESSURRECTION, true); + + if (me->getVictim()) + { + me->GetMotionMaster()->MoveChase(me->getVictim()); + me->AI()->AttackStart(me->getVictim()); + } + else + me->GetMotionMaster()->Initialize(); + }; + + void UpdateAI(const uint32 diff) + { + if (pInstance && pInstance->GetData(DATA_PRINCEKELESETH_EVENT) == IN_PROGRESS) + { + if (isDead) + { + if (Respawn_Time <= diff) + { + Resurrect(); + Respawn_Time = 12000; + } else Respawn_Time -= diff; + } + else + { + if (!UpdateVictim()) + return; + + if (Decrepify_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DECREPIFY); + Decrepify_Timer = 30000; + } else Decrepify_Timer -= diff; + + DoMeleeAttackIfReady(); + } + }else + { + if (me->isAlive()) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + } +}; + +CreatureAI* GetAI_mob_frost_tomb(Creature* pCreature) +{ + return new mob_frost_tombAI(pCreature); +} + +CreatureAI* GetAI_boss_keleseth(Creature* pCreature) +{ + return new boss_kelesethAI (pCreature); +} + +CreatureAI* GetAI_mob_vrykul_skeleton(Creature* pCreature) +{ + return new mob_vrykul_skeletonAI (pCreature); +} + +void AddSC_boss_keleseth() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_keleseth"; + newscript->GetAI = &GetAI_boss_keleseth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_tomb"; + newscript->GetAI = &GetAI_mob_frost_tomb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vrykul_skeleton"; + newscript->GetAI = &GetAI_mob_vrykul_skeleton; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp new file mode 100644 index 00000000000..2146d37635b --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Skarvald_Dalronn +SD%Complete: 95 +SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum eEnums +{ + //signed for 24200, but used by 24200,27390 + YELL_SKARVALD_AGGRO = -1574011, + YELL_SKARVALD_DAL_DIED = -1574012, + YELL_SKARVALD_SKA_DIEDFIRST = -1574013, + YELL_SKARVALD_KILL = -1574014, + YELL_SKARVALD_DAL_DIEDFIRST = -1574015, + + //signed for 24201, but used by 24201,27389 + YELL_DALRONN_AGGRO = -1574016, + YELL_DALRONN_SKA_DIED = -1574017, + YELL_DALRONN_DAL_DIEDFIRST = -1574018, + YELL_DALRONN_KILL = -1574019, + YELL_DALRONN_SKA_DIEDFIRST = -1574020, + +//Spells of Skarvald and his Ghost + MOB_SKARVALD_THE_CONSTRUCTOR = 24200, + SPELL_CHARGE = 43651, + SPELL_STONE_STRIKE = 48583, + SPELL_SUMMON_SKARVALD_GHOST = 48613, + MOB_SKARVALD_GHOST = 27390, +//Spells of Dalronn and his Ghost + MOB_DALRONN_THE_CONTROLLER = 24201, + SPELL_SHADOW_BOLT = 43649, + H_SPELL_SHADOW_BOLT = 59575, + H_SPELL_SUMMON_SKELETONS = 52611, + SPELL_DEBILITATE = 43650, + SPELL_SUMMON_DALRONN_GHOST = 48612, + MOB_DALRONN_GHOST = 27389 +}; + +struct boss_skarvald_the_constructorAI : public ScriptedAI +{ + boss_skarvald_the_constructorAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool ghost; + uint32 Charge_Timer; + uint32 StoneStrike_Timer; + uint32 Response_Timer; + uint32 Check_Timer; + bool Dalronn_isDead; + + void Reset() + { + Charge_Timer = 5000; + StoneStrike_Timer = 10000; + Dalronn_isDead = false; + Check_Timer = 5000; + + ghost = (me->GetEntry() == MOB_SKARVALD_GHOST); + if (!ghost && pInstance) + { + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn && dalronn->isDead()) + CAST_CRE(dalronn)->Respawn(); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit * who) + { + if (!ghost && pInstance) + { + DoScriptText(YELL_SKARVALD_AGGRO,me); + + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn && dalronn->isAlive() && !dalronn->getVictim()) + dalronn->getThreatManager().addThreat(who,0.0f); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* Killer) + { + if (!ghost && pInstance) + { + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn) + { + if (dalronn->isDead()) + { + DoScriptText(YELL_SKARVALD_DAL_DIED,me); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); + } + else + { + DoScriptText(YELL_SKARVALD_SKA_DIEDFIRST,me); + + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true); + Creature* temp = me->SummonCreature(MOB_SKARVALD_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); + if (temp) + { + temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(Killer); + } + } + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + if (!ghost) + { + DoScriptText(YELL_SKARVALD_KILL,me); + } + } + + void UpdateAI(const uint32 diff) + { + if (ghost) + { + if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (!UpdateVictim()) + return; + + if (!ghost) + { + if (Check_Timer) + if (Check_Timer <= diff) + { + Check_Timer = 5000; + Unit* dalronn = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_DALRONN) : 0); + if (dalronn && dalronn->isDead()) + { + Dalronn_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } + } else Check_Timer -= diff; + + if (Response_Timer) + if (Dalronn_isDead) + if (Response_Timer <= diff) + { + DoScriptText(YELL_SKARVALD_DAL_DIEDFIRST,me); + + Response_Timer = 0; + } else Response_Timer -= diff; + } + + if (Charge_Timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE); + Charge_Timer = 5000+rand()%5000; + } else Charge_Timer -= diff; + + if (StoneStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STONE_STRIKE); + StoneStrike_Timer = 5000+rand()%5000; + } else StoneStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_skarvald_the_constructor(Creature* pCreature) +{ + return new boss_skarvald_the_constructorAI (pCreature); +} + +struct boss_dalronn_the_controllerAI : public ScriptedAI +{ + boss_dalronn_the_controllerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool ghost; + uint32 ShadowBolt_Timer; + uint32 Debilitate_Timer; + uint32 Summon_Timer; + + uint32 Response_Timer; + uint32 Check_Timer; + uint32 AggroYell_Timer; + bool Skarvald_isDead; + + void Reset() + { + ShadowBolt_Timer = 1000; + Debilitate_Timer = 5000; + Summon_Timer = 10000; + Check_Timer = 5000; + Skarvald_isDead = false; + AggroYell_Timer = 0; + + ghost = me->GetEntry() == MOB_DALRONN_GHOST; + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald && skarvald->isDead()) + CAST_CRE(skarvald)->Respawn(); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit * who) + { + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald && skarvald->isAlive() && !skarvald->getVictim()) + skarvald->getThreatManager().addThreat(who,0.0f); + + AggroYell_Timer = 5000; + + if (pInstance) + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* Killer) + { + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald) + if (skarvald->isDead()) + { + DoScriptText(YELL_DALRONN_SKA_DIED,me); + + if (pInstance) + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); + } + else + { + DoScriptText(YELL_DALRONN_DAL_DIEDFIRST,me); + + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true); + Creature* temp = me->SummonCreature(MOB_DALRONN_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); + if (temp) + { + temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(Killer); + } + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + if (!ghost) + { + DoScriptText(YELL_DALRONN_KILL,me); + } + } + + void UpdateAI(const uint32 diff) + { + if (ghost) + { + if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (!UpdateVictim()) + return; + + if (AggroYell_Timer) + if (AggroYell_Timer <= diff) + { + DoScriptText(YELL_DALRONN_AGGRO,me); + + AggroYell_Timer = 0; + } else AggroYell_Timer -= diff; + + if (!ghost) + { + if (Check_Timer) + if (Check_Timer <= diff) + { + Check_Timer = 5000; + Unit* skarvald = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SKARVALD) : 0); + if (skarvald && skarvald->isDead()) + { + Skarvald_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } + } else Check_Timer -= diff; + + if (Response_Timer) + if (Skarvald_isDead) + if (Response_Timer <= diff) + { + DoScriptText(YELL_DALRONN_SKA_DIEDFIRST,me); + + Response_Timer = 0; + } else Response_Timer -= diff; + } + + if (ShadowBolt_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells + } + } else ShadowBolt_Timer -= diff; + + if (Debilitate_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DEBILITATE); + Debilitate_Timer = 5000+rand()%5000; + } + } else Debilitate_Timer -= diff; + + if (IsHeroic()) + if (Summon_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, H_SPELL_SUMMON_SKELETONS); + Summon_Timer = (rand()%10000) + 20000; + } + } else Summon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_dalronn_the_controller(Creature* pCreature) +{ + return new boss_dalronn_the_controllerAI (pCreature); +} + +void AddSC_boss_skarvald_dalronn() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_skarvald_the_constructor"; + newscript->GetAI = &GetAI_boss_skarvald_the_constructor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_dalronn_the_controller"; + newscript->GetAI = &GetAI_boss_dalronn_the_controller; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp new file mode 100644 index 00000000000..03f97b1d27e --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Utgarde_Keep +SD%Complete: 90 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Utgarde Keep Scripts +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +#define MAX_ENCOUNTER 3 + +#define ENTRY_BELLOW_1 186688 +#define ENTRY_BELLOW_2 186689 +#define ENTRY_BELLOW_3 186690 + +#define ENTRY_FORGEFIRE_1 186692 +#define ENTRY_FORGEFIRE_2 186693 +#define ENTRY_FORGEFIRE_3 186691 + +#define ENTRY_GLOWING_ANVIL_1 186609 +#define ENTRY_GLOWING_ANVIL_2 186610 +#define ENTRY_GLOWING_ANVIL_3 186611 + +#define ENTRY_GIANT_PORTCULLIS_1 186756 +#define ENTRY_GIANT_PORTCULLIS_2 186694 + +/* Utgarde Keep encounters: +0 - Prince Keleseth +1 - Skarvald Dalronn +2 - Ingvar the Plunderer +*/ + +struct instance_utgarde_keep : public ScriptedInstance +{ + instance_utgarde_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 Keleseth; + uint64 Skarvald; + uint64 Dalronn; + uint64 Ingvar; + + uint64 forge_bellow[3]; + uint64 forge_fire[3]; + uint64 forge_anvil[3]; + uint64 portcullis[2]; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 forge_event[3]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Keleseth = 0; + Skarvald = 0; + Dalronn = 0; + Ingvar = 0; + + for (uint8 i = 0; i < 3; ++i) + { + forge_bellow[i] = 0; + forge_fire[i] = 0; + forge_anvil[i] = 0; + forge_event[i] = NOT_STARTED; + } + + portcullis[0] = 0; + portcullis[1] = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 23953: Keleseth = pCreature->GetGUID(); break; + case 24201: Dalronn = pCreature->GetGUID(); break; + case 24200: Skarvald = pCreature->GetGUID(); break; + case 23954: Ingvar = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + //door and object id + case ENTRY_BELLOW_1: forge_bellow[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_BELLOW_2: forge_bellow[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_BELLOW_3: forge_bellow[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_1: forge_fire[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_2: forge_fire[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_3: forge_fire[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_1: forge_anvil[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_2: forge_anvil[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_3: forge_anvil[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GIANT_PORTCULLIS_1: portcullis[0] = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GIANT_PORTCULLIS_2: portcullis[1] = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_PRINCEKELESETH: return Keleseth; + case DATA_DALRONN: return Dalronn; + case DATA_SKARVALD: return Skarvald; + case DATA_INGVAR: return Ingvar; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_PRINCEKELESETH_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_SKARVALD_DALRONN_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_INGVAR_EVENT: + if (data == DONE) + { + HandleGameObject(portcullis[0], true); + HandleGameObject(portcullis[1], true); + } + m_auiEncounter[2] = data; + break; + case EVENT_FORGE_1: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[0],false); + HandleGameObject(forge_fire[0],false); + HandleGameObject(forge_anvil[0],false); + }else + { + HandleGameObject(forge_bellow[0],true); + HandleGameObject(forge_fire[0],true); + HandleGameObject(forge_anvil[0],true); + } + forge_event[0] = data; + break; + case EVENT_FORGE_2: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[1],false); + HandleGameObject(forge_fire[1],false); + HandleGameObject(forge_anvil[1],false); + }else + { + HandleGameObject(forge_bellow[1],true); + HandleGameObject(forge_fire[1],true); + HandleGameObject(forge_anvil[1],true); + } + forge_event[1] = data; + break; + case EVENT_FORGE_3: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[2],false); + HandleGameObject(forge_fire[2],false); + HandleGameObject(forge_anvil[2],false); + }else + { + HandleGameObject(forge_bellow[2],true); + HandleGameObject(forge_fire[2],true); + HandleGameObject(forge_anvil[2],true); + } + forge_event[2] = data; + break; + } + + if (data == DONE) + { + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_PRINCEKELESETH_EVENT: return m_auiEncounter[0]; + case DATA_SKARVALD_DALRONN_EVENT: return m_auiEncounter[1]; + case DATA_INGVAR_EVENT: return m_auiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "U K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << forge_event[0] << " " << forge_event[1] << " " << forge_event[2]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + + if (dataHead1 == 'U' && dataHead2 == 'K') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + forge_event[0] = data3; + forge_event[1] = data4; + forge_event[2] = data5; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_utgarde_keep(Map* pMap) +{ + return new instance_utgarde_keep(pMap); +} + +void AddSC_instance_utgarde_keep() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_utgarde_keep"; + newscript->GetInstanceData = &GetInstanceData_instance_utgarde_keep; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp new file mode 100644 index 00000000000..95825aa49b6 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +uint32 entry_search[3] = +{ + 186609, + 186610, + 186611 +}; + +struct npc_dragonflayer_forge_masterAI : public ScriptedAI +{ + npc_dragonflayer_forge_masterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + fm_Type = 0; + } + + ScriptedInstance* pInstance; + uint8 fm_Type; + + void Reset() + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + CheckForge(); + } + + void CheckForge() + { + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,me->isAlive() ? NOT_STARTED : DONE); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,me->isAlive() ? NOT_STARTED : DONE); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,me->isAlive() ? NOT_STARTED : DONE); + break; + } + } + } + + void JustDied(Unit * /*killer*/) + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,DONE); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,DONE); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,DONE); + break; + } + } + } + + void EnterCombat(Unit * /*who*/) + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,IN_PROGRESS); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,IN_PROGRESS); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,IN_PROGRESS); + break; + } + } + me->SetUInt32Value(UNIT_NPC_EMOTESTATE ,EMOTE_ONESHOT_NONE); + } + + uint8 GetForgeMasterType() + { + float diff = 30.0f; + int near_f = 0; + + for (uint8 i = 0; i < 3 ; ++i) + { + GameObject* temp; + temp = me->FindNearestGameObject(entry_search[i],30); + if (temp) + { + if (me->IsWithinDist(temp,diff,false)) + { + near_f = i + 1; + diff = me->GetDistance2d(temp); + + } + } + } + + switch (near_f) + { + case 1: return 1; + case 2: return 2; + case 3: return 3; + default: return 0; + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (fm_Type == 0) + fm_Type = GetForgeMasterType(); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_dragonflayer_forge_master(Creature* pCreature) +{ + return new npc_dragonflayer_forge_masterAI(pCreature); +} + +void AddSC_utgarde_keep() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_dragonflayer_forge_master"; + newscript->GetAI = &GetAI_npc_dragonflayer_forge_master; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h new file mode 100644 index 00000000000..b630e156564 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_UTGARDE_KEEP_H +#define DEF_UTGARDE_KEEP_H + +#define DATA_PRINCEKELESETH 1 +#define DATA_SKARVALD 3 +#define DATA_DALRONN 4 +#define DATA_INGVAR 6 + +#define DATA_PRINCEKELESETH_EVENT 2 +#define DATA_SKARVALD_DALRONN_EVENT 5 +#define DATA_INGVAR_EVENT 7 + +#define EVENT_FORGE_1 8 +#define EVENT_FORGE_2 9 +#define EVENT_FORGE_3 10 + +#endif diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp new file mode 100644 index 00000000000..297fe37b7d8 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp @@ -0,0 +1,830 @@ +/* Script Data Start +SDName: Boss palehoof +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_palehoof' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_ARCING_SMASH = 48260, + SPELL_IMPALE = 48261, + H_SPELL_IMPALE = 59268, + SPELL_WITHERING_ROAR = 48256, + H_SPELL_WITHERING_ROAR = 59267, + SPELL_FREEZE = 16245 +}; + +//Orb spells +enum OrbSpells +{ + SPELL_ORB_VISUAL = 48044, + SPELL_ORB_CHANNEL = 48048 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1575000, + SAY_SLAY_1 = -1575001, + SAY_SLAY_2 = -1575002, + SAY_DEATH = -1575003 +}; + +enum Creatures +{ + MOB_STASIS_CONTROLLER = 26688 +}; + +struct Locations +{ + float x, y, z; +}; + +struct Locations moveLocs[]= +{ + {261.6,-449.3,109.5}, + {263.3,-454.0,109.5}, + {291.5,-450.4,109.5}, + {291.5,-454.0,109.5}, + {310.0,-453.4,109.5}, + {238.6,-460.7,109.5} +}; + +enum Phase +{ + PHASE_FRENZIED_WORGEN, + PHASE_RAVENOUS_FURLBORG, + PHASE_MASSIVE_JORMUNGAR, + PHASE_FEROCIOUS_RHINO, + PHASE_GORTOK_PALEHOOF, + PHASE_NONE +}; + +struct boss_palehoofAI : public ScriptedAI +{ + boss_palehoofAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiArcingSmashTimer; + uint32 uiImpaleTimer; + uint32 uiWhiteringRoarTimer; + uint32 uiWaitingTimer; + Phase currentPhase; + uint8 AddCount; + bool DoneAdds[4]; + + ScriptedInstance *pInstance; + + void Reset() + { + uiArcingSmashTimer = 15000; + uiImpaleTimer = 12000; + uiWhiteringRoarTimer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + for (uint32 i=0;i<4;i++) + DoneAdds[i]=false; + AddCount=0; + + currentPhase=PHASE_NONE; + + if (pInstance) + { + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, NOT_STARTED); + + Creature* pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GORTOK_PALEHOOF_SPHERE)); + if (pGo) + { + pGo->SetGoState(GO_STATE_READY); + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void UpdateAI(const uint32 diff) + { + if (currentPhase != PHASE_GORTOK_PALEHOOF) + return; + //Return since we have no target + if (!UpdateVictim()) + return; + + Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->DisappearAndDie(); + + if (uiArcingSmashTimer <= diff) + { + DoCast(me, SPELL_ARCING_SMASH); + uiArcingSmashTimer = urand(13000,17000); + } else uiArcingSmashTimer -= diff; + + if (uiImpaleTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_IMPALE); + uiImpaleTimer = urand(8000,12000); + } else uiImpaleTimer -= diff; + + if (uiWhiteringRoarTimer <= diff) + { + DoCast(me, SPELL_WITHERING_ROAR); + uiWhiteringRoarTimer = urand(8000,12000); + } else uiWhiteringRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, DONE); + Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->DisappearAndDie(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void NextPhase() + { + if (currentPhase == PHASE_NONE) + { + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); + me->SummonCreature(MOB_STASIS_CONTROLLER,moveLocs[5].x,moveLocs[5].y,moveLocs[5].z,0,TEMPSUMMON_CORPSE_DESPAWN); + } + Phase move = PHASE_NONE; + if (AddCount >= DUNGEON_MODE(2,4)) + move = PHASE_GORTOK_PALEHOOF; + else + { + //select random not yet defeated add + uint8 next = urand(0,3); + for (uint8 i=0; i < 16; i++) + { + if (!DoneAdds[i%4] && next == 0) + { + move = (Phase)(i%4); + break; + } else if (!DoneAdds[i%4] && next > 0) + --next; + } + ++AddCount; + DoneAdds[move] = true; + move = (Phase)(move%4); + } + //send orb to summon spot + Creature *pOrb = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pOrb && pOrb->isAlive()) + { + if (currentPhase == PHASE_NONE) + pOrb->CastSpell(me,SPELL_ORB_VISUAL,true); + pOrb->GetMotionMaster()->MovePoint(move,moveLocs[move].x,moveLocs[move].y,moveLocs[move].z); + } + currentPhase = move; + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_boss_palehoof(Creature* pCreature) +{ + return new boss_palehoofAI (pCreature); +} + +//ravenous furbolg's spells +enum RavenousSpells +{ + SPELL_CHAIN_LIGHTING = 48140, + H_SPELL_CHAIN_LIGHTING = 59273, + SPELL_CRAZED = 48139, + SPELL_TERRIFYING_ROAR = 48144 +}; + +struct mob_ravenous_furbolgAI : public ScriptedAI +{ + mob_ravenous_furbolgAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiChainLightingTimer; + uint32 uiCrazedTimer; + uint32 uiTerrifyingRoarTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiChainLightingTimer = 5000; + uiCrazedTimer = 10000; + uiTerrifyingRoarTimer = 15000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiChainLightingTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTING); + uiChainLightingTimer = 5000 + rand()%5000; + } else uiChainLightingTimer -= diff; + + if (uiCrazedTimer <= diff) + { + DoCast(me, SPELL_CRAZED); + uiCrazedTimer = 8000 + rand()%4000; + } else uiCrazedTimer -= diff; + + if (uiTerrifyingRoarTimer <= diff) + { + DoCast(me, SPELL_TERRIFYING_ROAR); + uiTerrifyingRoarTimer = 10000 + rand()%10000; + } else uiTerrifyingRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_ravenous_furbolg(Creature* pCreature) +{ + return new mob_ravenous_furbolgAI (pCreature); +} + +//frenzied worgen's spells +enum FrenziedSpells +{ + SPELL_MORTAL_WOUND = 48137, + H_SPELL_MORTAL_WOUND = 59265, + SPELL_ENRAGE_1 = 48138, + SPELL_ENRAGE_2 = 48142 +}; + +struct mob_frenzied_worgenAI : public ScriptedAI +{ + mob_frenzied_worgenAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiMortalWoundTimer; + uint32 uiEnrage1Timer; + uint32 uiEnrage2Timer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiMortalWoundTimer = 5000; + uiEnrage1Timer = 15000; + uiEnrage2Timer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiMortalWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + uiMortalWoundTimer = 3000 + rand()%4000; + } else uiMortalWoundTimer -= diff; + + if (uiEnrage1Timer <= diff) + { + DoCast(me, SPELL_ENRAGE_1); + uiEnrage1Timer = 15000; + } else uiEnrage1Timer -= diff; + + if (uiEnrage2Timer <= diff) + { + DoCast(me, SPELL_ENRAGE_2); + uiEnrage2Timer = 10000; + } else uiEnrage2Timer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + if (pInstance) + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance->GetData64(DATA_GORTOK_PALEHOOF)); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_frenzied_worgen(Creature* pCreature) +{ + return new mob_frenzied_worgenAI (pCreature); +} + +//ferocious rhino's spells +enum FerociousSpells +{ + SPELL_GORE = 48130, + H_SPELL_GORE = 59264, + SPELL_GRIEVOUS_WOUND = 48105, + H_SPELL_GRIEVOUS_WOUND = 59263, + SPELL_STOMP = 48131 +}; + +struct mob_ferocious_rhinoAI : public ScriptedAI +{ + mob_ferocious_rhinoAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiStompTimer; + uint32 uiGoreTimer; + uint32 uiGrievousWoundTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiStompTimer = 10000; + uiGoreTimer = 15000; + uiGrievousWoundTimer = 20000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiStompTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STOMP); + uiStompTimer = 8000 + rand()%4000; + } else uiStompTimer -= diff; + + if (uiGoreTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GORE); + uiGoreTimer = 13000 + rand()%4000; + } else uiGoreTimer -= diff; + + if (uiGrievousWoundTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_GRIEVOUS_WOUND); + uiGrievousWoundTimer = 18000 + rand()%4000; + } else uiGrievousWoundTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_ferocious_rhino(Creature* pCreature) +{ + return new mob_ferocious_rhinoAI (pCreature); +} + +//massive jormungar's spells +enum MassiveSpells +{ + SPELL_ACID_SPIT = 48132, + SPELL_ACID_SPLATTER = 48136, + H_SPELL_ACID_SPLATTER = 59272, + SPELL_POISON_BREATH = 48133, + H_SPELL_POISON_BREATH = 59271 +}; + +enum MassiveAdds +{ + CREATURE_JORMUNGAR_WORM = 27228 +}; + +struct mob_massive_jormungarAI : public ScriptedAI +{ + mob_massive_jormungarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiAcidSpitTimer; + uint32 uiAcidSplatterTimer; + uint32 uiPoisonBreathTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiAcidSpitTimer = 3000; + uiAcidSplatterTimer = 12000; + uiPoisonBreathTimer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiAcidSpitTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ACID_SPIT); + uiAcidSpitTimer = 2000 + rand()%2000; + } else uiAcidSpitTimer -= diff; + + if (uiAcidSplatterTimer <= diff) + { + DoCast(me, SPELL_POISON_BREATH); + uiAcidSplatterTimer = 10000 + rand()%4000; + } else uiAcidSplatterTimer -= diff; + + if (uiPoisonBreathTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_POISON_BREATH); + uiPoisonBreathTimer = 8000 + rand()%4000; + } else uiPoisonBreathTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI,pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_massive_jormungar(Creature* pCreature) +{ + return new mob_massive_jormungarAI (pCreature); +} + + +struct mob_palehoof_orbAI : public ScriptedAI +{ + mob_palehoof_orbAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 SummonTimer; + Phase currentPhase; + + void Reset() + { + currentPhase=PHASE_NONE; + SummonTimer=5000; + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL); + me->SetSpeed(MOVE_FLIGHT , 0.5f); + } + + void UpdateAI(const uint32 diff) + { + if (currentPhase == PHASE_NONE) + return; + + if (SummonTimer <= diff) + { + if (currentPhase<5&¤tPhase >= 0) + { + Creature *pNext = NULL; + switch(currentPhase) + { + case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; + case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; + case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; + case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; + case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; + } + + if (pNext) + { + pNext->RemoveAurasDueToSpell(SPELL_FREEZE); + pNext->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + pNext->SetStandState(UNIT_STAND_STATE_STAND); + pNext->SetInCombatWithZone(); + pNext->Attack(pNext->SelectNearestTarget(100),true); + + } + currentPhase=PHASE_NONE; + } + } else SummonTimer-=diff; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + if (id<0 || id>4) + return; + Creature *pNext = NULL; + switch(id) + { + case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; + case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; + case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; + case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; + case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; + } + if (pNext) + DoCast(pNext, SPELL_ORB_CHANNEL, false); + currentPhase=(Phase)id; + SummonTimer=5000; + } +}; + +CreatureAI* GetAI_mob_palehoof_orb(Creature* pCreature) +{ + return new mob_palehoof_orbAI (pCreature); +} + + + +bool GOHello_palehoof_sphere(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + + Creature *pPalehoof = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + { + // maybe these are hacks :( + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + return true; +} + + + +void AddSC_boss_palehoof() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_palehoof"; + newscript->GetAI = &GetAI_boss_palehoof; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ravenous_furbolg"; + newscript->GetAI = &GetAI_mob_ravenous_furbolg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frenzied_worgen"; + newscript->GetAI = &GetAI_mob_frenzied_worgen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ferocious_rhino"; + newscript->GetAI = &GetAI_mob_ferocious_rhino; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_massive_jormungar"; + newscript->GetAI = &GetAI_mob_massive_jormungar; + newscript->RegisterSelf(); + + + newscript = new Script; + newscript->Name = "mob_palehoof_orb"; + newscript->GetAI = &GetAI_mob_palehoof_orb; + newscript->RegisterSelf(); + + + newscript = new Script; + newscript->Name = "go_palehoof_sphere"; + newscript->pGOHello=&GOHello_palehoof_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp new file mode 100644 index 00000000000..a75eb3465be --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp @@ -0,0 +1,477 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Boss_Skadi +SDAuthor: LordVanMartin, JohnHoliver +SD%Complete: 90% +SDComment: + After Unmount() he appears to still be flying even with SetFlying(false) + +SDCategory: Utgarde Pinnacle +Script Data End */ + +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +//Yell +enum eYells +{ + SAY_AGGRO = -1575004, + SAY_KILL_1 = -1575005, + SAY_KILL_2 = -1575006, + EMOTE_RANGE = -1575007, //Skadi + SAY_DEATH = -1575008, + SAY_DRAKE_DEATH = -1575009, + EMOTE_BREATH = -1575010, //Grauf + SAY_DRAKE_BREATH_1 = -1575011, + SAY_DRAKE_BREATH_2 = -1575012, + SAY_DRAKE_BREATH_3 = -1575013, +}; + +static Position SpawnLoc = {468.931, -513.555, 104.723}; +static Position Location[]= +{ + // Boss + {341.740997, -516.955017, 104.66900}, // 0 + {293.299, -505.95, 142.03}, // 1 + {301.664, -535.164, 146.097}, // 2 + {521.031006, -544.667847, 128.80064}, // 3 + {477.311981, -509.296814, 104.72308}, // 4 + {341.740997, -516.955017, 104.66900}, // 5 + {341.740997, -516.955017, 104.66900}, // 6 + {341.740997, -516.955017, 104.66900}, // 7 + // Triggers Left + {469.661, -484.546, 104.712}, // 8 + {483.315, -485.028, 104.718}, // 9 + {476.87, -487.994, 104.735}, //10 + {477.512, -497.772, 104.728}, //11 + {486.287, -500.759, 104.722}, //12 + {480.1, -503.895, 104.722}, //13 + {472.391, -505.103, 104.723}, //14 + {478.885, -510.803, 104.723}, //15 + {489.529, -508.615, 104.723}, //16 + {484.272, -508.589, 104.723}, //17 + {465.328, -506.495, 104.427}, //18 + {456.885, -508.104, 104.447}, //19 + {450.177, -507.989, 105.247}, //20 + {442.273, -508.029, 104.813}, //21 + {434.225, -508.19, 104.787}, //22 + {423.902, -508.525, 104.274}, //23 + {414.551, -508.645, 105.136}, //24 + {405.787, -508.755, 104.988}, //25 + {398.812, -507.224, 104.82}, //26 + {389.702, -506.846, 104.729}, //27 + {381.856, -506.76, 104.756}, //28 + {372.881, -507.254, 104.779}, //29 + {364.978, -508.182, 104.673}, //30 + {357.633, -508.075, 104.647}, //31 + {350.008, -506.826, 104.588}, //32 + {341.69, -506.77, 104.499}, //33 + {335.31, -505.745, 105.18}, //34 + {471.178, -510.74, 104.723}, //35 + {461.759, -510.365, 104.199}, //36 + {424.07287, -510.082916, 104.711082}, //37 + // Triggers Right + {489.46, -513.297, 105.413}, //38 + {485.706, -517.175, 104.724}, //39 + {480.98, -519.313, 104.724}, //40 + {475.05, -520.52, 104.724}, //41 + {482.97, -512.099, 104.724}, //42 + {477.082, -514.172, 104.724}, //43 + {468.991, -516.691, 104.724}, //44 + {461.722, -517.063, 104.627}, //45 + {455.88, -517.681, 104.707}, //46 + {450.499, -519.099, 104.701}, //47 + {444.889, -518.963, 104.82}, //48 + {440.181, -518.893, 104.861}, //49 + {434.393, -518.758, 104.891}, //50 + {429.328, -518.583, 104.904}, //51 + {423.844, -518.394, 105.004}, //52 + {418.707, -518.266, 105.135}, //53 + {413.377, -518.085, 105.153}, //54 + {407.277, -517.844, 104.893}, //55 + {401.082, -517.443, 104.723}, //56 + {394.933, -514.64, 104.724}, //57 + {388.917, -514.688, 104.734}, //58 + {383.814, -515.834, 104.73}, //59 + {377.887, -518.653, 104.777}, //60 + {371.376, -518.289, 104.781}, //61 + {365.669, -517.822, 104.758}, //62 + {359.572, -517.314, 104.706}, //63 + {353.632, -517.146, 104.647}, //64 + {347.998, -517.038, 104.538}, //65 + {341.803, -516.98, 104.584}, //66 + {335.879, -516.674, 104.628}, //67 + {329.871, -515.92, 104.711}, //68 + // Breach Zone + {485.4577, -511.2515, 115.3011}, //69 + {435.1892, -514.5232, 118.6719}, //70 + {413.9327, -540.9407, 138.2614}, //71 +}; + +enum eCombatPhase +{ + FLYING, + SKADI +}; + +enum eSpells +{ + //Skadi Spells + SPELL_CRUSH = 50234, + SPELL_POISONED_SPEAR = 50225, //isn't being casted =/ + SPELL_WHIRLWIND = 50228, //random target, but not the tank approx. every 20s + SPELL_RAPID_FIRE = 56570, + SPELL_HARPOON_DAMAGE = 56578, + SPELL_FREEZING_CLOUD = 47579, +}; + +enum eCreature +{ + CREATURE_YMIRJAR_WARRIOR = 26690, + CREATURE_YMIRJAR_WITCH_DOCTOR = 26691, + CREATURE_YMIRJAR_HARPOONER = 26692, + CREATURE_GRAUF = 26893, + CREATURE_TRIGGER = 28351, + DATA_MOUNT = 27043, +}; + +enum eAchievments +{ + ACHIEV_TIMED_START_EVENT = 17726, +}; + +struct boss_skadiAI : public ScriptedAI +{ + boss_skadiAI(Creature *c) : ScriptedAI(c), Summons(me) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + SummonList Summons; + uint64 m_uiGraufGUID; + std::vector triggersGUID; + + uint32 m_uiCrushTimer; + uint32 m_uiPoisonedSpearTimer; + uint32 m_uiWhirlwindTimer; + uint32 m_uiWaypointId; + uint32 m_uiMovementTimer; + uint32 m_uiMountTimer; + uint32 m_uiSummonTimer; + uint8 m_uiSpellHitCount; + bool m_bSaidEmote; + + eCombatPhase Phase; + + void Reset() + { + triggersGUID.clear(); + + m_uiCrushTimer = 8000; + m_uiPoisonedSpearTimer = 10000; + m_uiWhirlwindTimer = 20000; + m_uiMountTimer = 3000; + m_uiWaypointId = 0; + m_bSaidEmote = false; + m_uiSpellHitCount = 0; + + Phase = SKADI; + + Summons.DespawnAll(); + me->SetSpeed(MOVE_FLIGHT, 3.0f); + if ((Unit::GetCreature((*me), m_uiGraufGUID) == NULL) && !me->IsMounted()) + me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); + if (m_pInstance) + { + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, NOT_STARTED); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void JustReachedHome() + { + me->SetFlying(false); + me->Unmount(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + if (Unit::GetCreature((*me), m_uiGraufGUID) == NULL) + me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + Phase = FLYING; + + m_uiMovementTimer = 1000; + m_uiSummonTimer = 10000; + me->SetInCombatWithZone(); + if (m_pInstance) + { + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, IN_PROGRESS); + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + me->GetMotionMaster()->MoveJump(Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 5.0f, 10.0f); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + m_uiMountTimer = 1000; + Summons.DespawnEntry(CREATURE_GRAUF); + } + } + + void JustSummoned(Creature* pSummoned) + { + switch (pSummoned->GetEntry()) + { + case CREATURE_GRAUF: + m_uiGraufGUID = pSummoned->GetGUID(); + break; + case CREATURE_YMIRJAR_WARRIOR: + case CREATURE_YMIRJAR_WITCH_DOCTOR: + case CREATURE_YMIRJAR_HARPOONER: + pSummoned->setActive(true); + pSummoned->SetInCombatWithZone(); + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + break; + case CREATURE_TRIGGER: + pSummoned->CastSpell((Unit*)NULL, SPELL_FREEZING_CLOUD, true); + pSummoned->ForcedDespawn(10*IN_MILISECONDS); + break; + } + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature* pSummoned) + { + if (pSummoned->GetEntry() == CREATURE_GRAUF) + m_uiGraufGUID = 0; + Summons.Despawn(pSummoned); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_HARPOON_DAMAGE) + { + m_uiSpellHitCount++; + if (m_uiSpellHitCount >= 5) + { + Phase = SKADI; + me->SetFlying(false); + me->Unmount(); + if(Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILISECONDS)) + { + pGrauf->GetMotionMaster()->MoveFall(0); + pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); + } + sLog.outBasic("[Skadi] Fly off"); + me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + DoScriptText(SAY_DRAKE_DEATH, me); + m_uiCrushTimer = 8000; + m_uiPoisonedSpearTimer = 10000; + m_uiWhirlwindTimer = 20000; + me->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); + } + } + } + + + void UpdateAI(const uint32 diff) + { + switch(Phase) + { + case FLYING: + if (!UpdateVictim()) + return; + + if (me->GetPositionX() >= 519) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + if (!m_bSaidEmote) + { + DoScriptText(EMOTE_RANGE, me); + m_bSaidEmote = true; + } + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + m_bSaidEmote = false; + } + + if (m_uiMountTimer && m_uiMountTimer <= diff) + { + me->Mount(DATA_MOUNT); + me->SetFlying(true); + m_uiMountTimer = 0; + } else m_uiMountTimer -= diff; + + if (m_uiSummonTimer <= diff) + { + SpawnMobs(); + m_uiSummonTimer = 25000; + } else m_uiSummonTimer -= diff; + + if (m_uiMovementTimer <= diff) + { + switch(m_uiWaypointId) + { + case 0: + me->GetMotionMaster()->MovePoint(0, Location[1].GetPositionX(), Location[1].GetPositionY(), Location[1].GetPositionZ()); + m_uiMovementTimer = 5000; + break; + case 1: + me->GetMotionMaster()->MovePoint(0, Location[2].GetPositionX(), Location[2].GetPositionY(), Location[2].GetPositionZ()); + m_uiMovementTimer = 2000; + break; + case 2: + me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); + m_uiMovementTimer = 15000; + break; + case 3: + me->GetMotionMaster()->MovePoint(0, Location[69].GetPositionX(), Location[69].GetPositionY(), Location[69].GetPositionZ()); + DoScriptText(RAND(SAY_DRAKE_BREATH_1,SAY_DRAKE_BREATH_2), me); + DoScriptText(EMOTE_BREATH, me); + m_uiMovementTimer = 2500; + break; + case 4: + me->GetMotionMaster()->MovePoint(0, Location[70].GetPositionX(), Location[70].GetPositionY(), Location[70].GetPositionZ()); + m_uiMovementTimer = 2000; + SpawnTrigger(); + break; + case 5: + me->GetMotionMaster()->MovePoint(0, Location[71].GetPositionX(), Location[71].GetPositionY(), Location[71].GetPositionZ()); + m_uiMovementTimer = 3000; + break; + case 6: + me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); + m_uiWaypointId = 2; + m_uiMovementTimer = 15000; + break; + } + m_uiWaypointId++; + } else m_uiMovementTimer -= diff; + break; + case SKADI: + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_uiCrushTimer <= diff) + { + DoCastVictim(SPELL_CRUSH); + m_uiCrushTimer = 8000; + } else m_uiCrushTimer -= diff; + + if (m_uiPoisonedSpearTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_POISONED_SPEAR); + m_uiPoisonedSpearTimer = 10000; + } else m_uiPoisonedSpearTimer -= diff; + + if (m_uiWhirlwindTimer <= diff) + { + DoCastAOE(SPELL_WHIRLWIND); + m_uiWhirlwindTimer = 20000; + } else m_uiWhirlwindTimer -= diff; + + DoMeleeAttackIfReady(); + break; + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + Summons.DespawnAll(); + if (m_pInstance) + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void SpawnMobs() + { + for (uint8 i = 0; i < DUNGEON_MODE(5,6); ++i) + { + switch (urand(0,2)) + { + case 0: me->SummonCreature(CREATURE_YMIRJAR_WARRIOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + case 1: me->SummonCreature(CREATURE_YMIRJAR_WITCH_DOCTOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + case 2: me->SummonCreature(CREATURE_YMIRJAR_HARPOONER, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + } + } + } + + void SpawnTrigger() + { + uint8 iStart,iEnd; + switch (urand(0,1)) + { + case 0: + iStart = 8; + iEnd = 37; + break; + case 1: + iStart = 38; + iEnd = 68; + break; + } + for(uint32 i = iStart; i < iEnd; ++i) + me->SummonCreature(CREATURE_TRIGGER,Location[i]); + } +}; + +bool GOHello_go_harpoon_launcher(Player *pPlayer, GameObject *pGO) +{ + ScriptedInstance* m_pInstance; + m_pInstance = (ScriptedInstance*)pGO->GetInstanceData(); + if (!m_pInstance) return false; + + if (Creature* pSkadi = Unit::GetCreature((*pGO),m_pInstance->GetData64(DATA_SKADI_THE_RUTHLESS))) + { + pPlayer->CastSpell(pSkadi,SPELL_RAPID_FIRE, true); + } + return false; +} + +CreatureAI* GetAI_boss_skadi(Creature* pCreature) +{ + return new boss_skadiAI (pCreature); +} + +void AddSC_boss_skadi() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_skadi"; + newscript->GetAI = &GetAI_boss_skadi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_harpoon_launcher"; + newscript->pGOHello = &GOHello_go_harpoon_launcher; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp new file mode 100644 index 00000000000..aae1015ddab --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp @@ -0,0 +1,408 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_CALL_FLAMES = 48258, + SPELL_RITUAL_OF_THE_SWORD = 48276, //Effect #1 Teleport, Effect #2 Dummy + SPELL_SINSTER_STRIKE = 15667, + H_SPELL_SINSTER_STRIKE = 59409, + SPELL_SVALA_TRANSFORMING1 = 54140, + SPELL_SVALA_TRANSFORMING2 = 54205 +}; +//not in db +enum Yells +{ + SAY_DIALOG_WITH_ARTHAS_1 = -1575015, + SAY_DIALOG_WITH_ARTHAS_2 = -1575016, + SAY_DIALOG_WITH_ARTHAS_3 = -1575017, + SAY_AGGRO = -1575018, + SAY_SLAY_1 = -1575019, + SAY_SLAY_2 = -1575020, + SAY_SLAY_3 = -1575021, + SAY_DEATH = -1575022, + SAY_SACRIFICE_PLAYER_1 = -1575023, + SAY_SACRIFICE_PLAYER_2 = -1575024, + SAY_SACRIFICE_PLAYER_3 = -1575025, + SAY_SACRIFICE_PLAYER_4 = -1575026, + SAY_SACRIFICE_PLAYER_5 = -1575027, + SAY_DIALOG_OF_ARTHAS_1 = -1575028, + SAY_DIALOG_OF_ARTHAS_2 = -1575029 +}; +enum Creatures +{ + CREATURE_ARTHAS = 24266, // Image of Arthas + CREATURE_SVALA_SORROWGRAVE = 26668, // Svala after transformation + CREATURE_SVALA = 29281, // Svala before transformation + CREATURE_RITUAL_CHANNELER = 27281 +}; +enum ChannelerSpells +{ + //ritual channeler's spells + SPELL_PARALYZE = 48278, + SPELL_SHADOWS_IN_THE_DARK = 59407 +}; +enum Misc +{ + DATA_SVALA_DISPLAY_ID = 25944 +}; +enum IntroPhase +{ + IDLE, + INTRO, + FINISHED +}; +enum CombatPhase +{ + NORMAL, + SACRIFICING +}; + +static Position RitualChannelerPos[]= +{ + {296.42, -355.01, 90.94}, + {302.36, -352.01, 90.54}, + {291.39, -350.89, 90.54} +}; +static Position ArthasPos = { 295.81, -366.16, 92.57, 1.58 }; +static Position SvalaPos = { 296.632, -346.075, 90.6307, 1.58 }; + +struct boss_svalaAI : public ScriptedAI +{ + boss_svalaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiIntroTimer; + + uint8 uiIntroPhase; + + IntroPhase Phase; + + TempSummon* pArthas; + uint64 uiArthasGUID; + + ScriptedInstance* pInstance; + + void Reset() + { + Phase = IDLE; + uiIntroTimer = 1*IN_MILISECONDS; + uiIntroPhase = 0; + uiArthasGUID = 0; + + if (pInstance) + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (Phase == IDLE && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && me->IsWithinDistInMap(pWho, 40)) + { + Phase = INTRO; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Creature *pArthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pArthas->SetFloatValue(OBJECT_FIELD_SCALE_X, 5); + uiArthasGUID = pArthas->GetGUID(); + } + } + } + + void AttackStart(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (Phase != INTRO) + return; + + if (uiIntroTimer <= diff) + { + Creature *pArthas = Unit::GetCreature(*me, uiArthasGUID); + if (!pArthas) + return; + + switch (uiIntroPhase) + { + case 0: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_1, me); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 1: + DoScriptText(SAY_DIALOG_OF_ARTHAS_1, pArthas); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 2: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_2, me); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 3: + DoScriptText(SAY_DIALOG_OF_ARTHAS_2, pArthas); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 4: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_3, me); + DoCast(me, SPELL_SVALA_TRANSFORMING1); + ++uiIntroPhase; + uiIntroTimer = 2.8*IN_MILISECONDS; + break; + case 5: + DoCast(me, SPELL_SVALA_TRANSFORMING2); + ++uiIntroPhase; + uiIntroTimer = 200; + break; + case 6: + if (Creature* pSvalaSorrowgrave = me->SummonCreature(CREATURE_SVALA_SORROWGRAVE, SvalaPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60*IN_MILISECONDS)) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(DATA_SVALA_DISPLAY_ID); + pArthas->ToTempSummon()->UnSummon(); + uiArthasGUID = 0; + Phase = FINISHED; + } + else + Reset(); + break; + } + } else uiIntroTimer -= diff; + } +}; + +struct mob_ritual_channelerAI : public Scripted_NoMovementAI +{ + mob_ritual_channelerAI(Creature *c) :Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + DoCast(me, SPELL_SHADOWS_IN_THE_DARK); + } + + // called by svala sorrowgrave to set guid of victim + void DoAction(uint32 /*action*/) + { + if (pInstance) + if (Unit *pVictim = me->GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER))) + DoCast(pVictim, SPELL_PARALYZE); + } + + void EnterCombat(Unit* /*who*/) + { + } +}; + +struct boss_svala_sorrowgraveAI : public ScriptedAI +{ + boss_svala_sorrowgraveAI(Creature *c) : ScriptedAI(c), summons(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiSinsterStrikeTimer; + uint32 uiCallFlamesTimer; + uint32 uiRitualOfSwordTimer; + uint32 uiSacrificeTimer; + + CombatPhase Phase; + + SummonList summons; + + bool bSacrificed; + + ScriptedInstance* pInstance; + + void Reset() + { + uiSinsterStrikeTimer = 7*IN_MILISECONDS; + uiCallFlamesTimer = 10*IN_MILISECONDS; + uiRitualOfSwordTimer = 20*IN_MILISECONDS; + uiSacrificeTimer = 8*IN_MILISECONDS; + + bSacrificed = false; + + Phase = NORMAL; + + DoTeleportTo(296.632, -346.075, 90.6307); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + + summons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); + pInstance->SetData64(DATA_SACRIFICED_PLAYER,0); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature *summon) + { + summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature *summon) + { + summons.Despawn(summon); + } + + void UpdateAI(const uint32 diff) + { + if (Phase == NORMAL) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiSinsterStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); + uiSinsterStrikeTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); + } else uiSinsterStrikeTimer -= diff; + + if (uiCallFlamesTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_CALL_FLAMES); + uiCallFlamesTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); + } + } else uiCallFlamesTimer -= diff; + + if (!bSacrificed) + if (uiRitualOfSwordTimer <= diff) + { + if (Unit* pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(RAND(SAY_SACRIFICE_PLAYER_1,SAY_SACRIFICE_PLAYER_2,SAY_SACRIFICE_PLAYER_3,SAY_SACRIFICE_PLAYER_4,SAY_SACRIFICE_PLAYER_5),me); + DoCast(pSacrificeTarget, SPELL_RITUAL_OF_THE_SWORD); + //Spell doesn't teleport + DoTeleportPlayer(pSacrificeTarget, 296.632, -346.075, 90.63, 4.6); + me->SetUnitMovementFlags(MOVEMENTFLAG_FLY_MODE); + DoTeleportTo(296.632, -346.075, 120.85); + Phase = SACRIFICING; + if (pInstance) + { + pInstance->SetData64(DATA_SACRIFICED_PLAYER,pSacrificeTarget->GetGUID()); + + for (uint8 i = 0; i < 3; ++i) + if (Creature* pSummon = me->SummonCreature(CREATURE_RITUAL_CHANNELER, RitualChannelerPos[i], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) + pSummon->AI()->DoAction(0); + } + + bSacrificed = true; + } + } else uiRitualOfSwordTimer -= diff; + + DoMeleeAttackIfReady(); + } + else //SACRIFICING + { + if (uiSacrificeTimer <= diff) + { + Unit* pSacrificeTarget = pInstance ? Unit::GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER)) : NULL; + if (pInstance && !summons.empty() && pSacrificeTarget && pSacrificeTarget->isAlive()) + me->Kill(pSacrificeTarget, false); // durability damage? + + //go down + Phase = NORMAL; + pSacrificeTarget = NULL; + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + me->GetMotionMaster()->MoveChase(pTarget); + + uiSacrificeTimer = 8*IN_MILISECONDS; + } + else uiSacrificeTimer -= diff; + } + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* pKiller) + { + if (pInstance) + { + Creature* pSvala = Unit::GetCreature((*me), pInstance->GetData64(DATA_SVALA)); + if (pSvala && pSvala->isAlive()) + pKiller->Kill(pSvala); + + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); + } + DoScriptText(SAY_DEATH, me); + } +}; + +CreatureAI* GetAI_boss_svala(Creature* pCreature) +{ + return new boss_svalaAI (pCreature); +} + +CreatureAI* GetAI_mob_ritual_channeler(Creature* pCreature) +{ + return new mob_ritual_channelerAI(pCreature); +} + +CreatureAI* GetAI_boss_svala_sorrowgrave(Creature* pCreature) +{ + return new boss_svala_sorrowgraveAI(pCreature); +} + +void AddSC_boss_svala() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_svala"; + newscript->GetAI = &GetAI_boss_svala; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ritual_channeler"; + newscript->GetAI = &GetAI_mob_ritual_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_svala_sorrowgrave"; + newscript->GetAI = &GetAI_boss_svala_sorrowgrave; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp new file mode 100644 index 00000000000..1a650f94101 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp @@ -0,0 +1,367 @@ +/* Script Data Start +SDName: Boss ymiron +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_ymiron' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_BANE = 48294, + H_SPELL_BANE = 59301, + SPELL_DARK_SLASH = 48292, + SPELL_FETID_ROT = 48291, + H_SPELL_FETID_ROT = 59300, + SPELL_SCREAMS_OF_THE_DEAD = 51750, + SPELL_SPIRIT_BURST = 48529, + H_SPELL_SPIRIT_BURST = 59305, + SPELL_SPIRIT_STRIKE = 48423, + H_SPELL_SPIRIT_STRIKE = 59304, + SPELL_ANCESTORS_VENGEANCE = 16939, + + SPELL_SUMMON_AVENGING_SPIRIT = 48592, + SPELL_SUMMON_SPIRIT_FOUNT = 48386, + + SPELL_CHANNEL_SPIRIT_TO_YMIRON = 48316, + SPELL_CHANNEL_YMIRON_TO_SPIRIT = 48307, + + SPELL_SPIRIT_FOUNT = 48380, + H_SPELL_SPIRIT_FOUNT = 59320 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1575028, + SAY_SLAY_1 = -1575029, + SAY_SLAY_2 = -1575030, + SAY_SLAY_3 = -1575031, + SAY_SLAY_4 = -1575032, + SAY_DEATH = -1575033, + SAY_SUMMON_BJORN = -1575034, + SAY_SUMMON_HALDOR = -1575035, + SAY_SUMMON_RANULF = -1575036, + SAY_SUMMON_TORGYN = -1575037 +}; + +enum Creatures +{ + CREATURE_BJORN = 27303, + CREATURE_BJORN_VISUAL = 27304, + CREATURE_HALDOR = 27307, + CREATURE_HALDOR_VISUAL = 27310, + CREATURE_RANULF = 27308, + CREATURE_RANULF_VISUAL = 27311, + CREATURE_TORGYN = 27309, + CREATURE_TORGYN_VISUAL = 27312, + CREATURE_SPIRIT_FOUNT = 27339, + CREATURE_AVENGING_SPIRIT = 27386 +}; + +struct ActiveBoatStruct +{ + uint32 npc; + int32 say; + float MoveX,MoveY,MoveZ,SpawnX,SpawnY,SpawnZ,SpawnO; +}; + +static ActiveBoatStruct ActiveBot[4] = +{ + {CREATURE_BJORN_VISUAL, SAY_SUMMON_BJORN, 404.379, -335.335, 104.756, 413.594, -335.408, 107.995, 3.157}, + {CREATURE_HALDOR_VISUAL, SAY_SUMMON_HALDOR, 380.813, -335.069, 104.756, 369.994, -334.771, 107.995, 6.232}, + {CREATURE_RANULF_VISUAL, SAY_SUMMON_RANULF, 381.546, -314.362, 104.756, 370.841, -314.426, 107.995, 6.232}, + {CREATURE_TORGYN_VISUAL, SAY_SUMMON_TORGYN, 404.310, -314.761, 104.756, 413.992, -314.703, 107.995, 3.157} +}; + +struct boss_ymironAI : public ScriptedAI +{ + boss_ymironAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + srand(time(NULL)); + for (int i = 0; i < 4; ++i) + m_uiActiveOrder[i] = i; + for (int i = 0; i < 3; ++i) + { + int r = i + (rand()%(4-i)); + int temp = m_uiActiveOrder[i]; + m_uiActiveOrder[i] = m_uiActiveOrder[r]; + m_uiActiveOrder[r] = temp; + } + } + + bool m_bIsWalking; + bool m_bIsPause; + bool m_bIsActiveWithBJORN; + bool m_bIsActiveWithHALDOR; + bool m_bIsActiveWithRANULF; + bool m_bIsActiveWithTORGYN; + + uint8 m_uiActiveOrder[4]; + uint8 m_uiActivedNumber; + + uint32 m_uiFetidRot_Timer; + uint32 m_uiBane_Timer; + uint32 m_uiDarkSlash_Timer; + uint32 m_uiAncestors_Vengeance_Timer; + + uint32 m_uiAbility_BJORN_Timer; + uint32 m_uiAbility_HALDOR_Timer; + uint32 m_uiAbility_RANULF_Timer; + uint32 m_uiAbility_TORGYN_Timer; + + uint32 m_uiPause_Timer; + uint32 m_uiHealthAmountModifier; + uint32 m_uiHealthAmountMultipler; + + uint64 m_uiActivedCreatureGUID; + uint64 m_uiOrbGUID; + + ScriptedInstance *pInstance; + + void Reset() + { + m_bIsPause = false; + m_bIsActiveWithBJORN = false; + m_bIsActiveWithHALDOR = false; + m_bIsActiveWithRANULF = false; + m_bIsActiveWithTORGYN = false; + + m_uiFetidRot_Timer = urand(8000,13000); + m_uiBane_Timer = urand(18000,23000); + m_uiDarkSlash_Timer = urand(28000,33000); + m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(60000,45000); + m_uiPause_Timer = 0; + + m_uiAbility_BJORN_Timer = 0; + m_uiAbility_HALDOR_Timer = 0; + m_uiAbility_RANULF_Timer = 0; + m_uiAbility_TORGYN_Timer = 0; + + m_uiActivedNumber = 0; + m_uiHealthAmountModifier = 1; + m_uiHealthAmountMultipler = DUNGEON_MODE(20,25); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (m_bIsWalking) + { + if (m_uiPause_Timer <= diff) + { + DoScriptText(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].say, me); + DoCast(me, SPELL_CHANNEL_YMIRON_TO_SPIRIT); // should be on spirit + if (Creature* pTemp = me->SummonCreature(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].npc, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnX, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnY, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnZ, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnO, TEMPSUMMON_CORPSE_DESPAWN, 0)) + { + m_uiActivedCreatureGUID = pTemp->GetGUID(); + pTemp->CastSpell(me, SPELL_CHANNEL_SPIRIT_TO_YMIRON, true); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + switch(m_uiActiveOrder[m_uiActivedNumber]) + { + case 0: m_bIsActiveWithBJORN = true; break; + case 1: m_bIsActiveWithHALDOR = true; break; + case 2: m_bIsActiveWithRANULF = true; break; + case 3: m_bIsActiveWithTORGYN = true; break; + } + } + + m_bIsPause = true; + m_bIsWalking = false; + m_uiPause_Timer = 3000; + } else m_uiPause_Timer -= diff; + return; + } + else if (m_bIsPause) + { + if (m_uiPause_Timer <= diff) + { + m_uiAbility_BJORN_Timer = 5000; + m_uiAbility_HALDOR_Timer = 5000; + m_uiAbility_RANULF_Timer = 5000; + m_uiAbility_TORGYN_Timer = 5000; + + m_bIsPause = false; + m_uiPause_Timer = 0; + } else m_uiPause_Timer -= diff; + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!m_bIsPause) + { + // Normal spells ------------------------------------------------------------------------ + if (m_uiBane_Timer <= diff) + { + DoCast(me, SPELL_BANE); + m_uiBane_Timer = urand(20000,25000); + } else m_uiBane_Timer -= diff; + + if (m_uiFetidRot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FETID_ROT); + m_uiFetidRot_Timer = urand(10000,15000); + } else m_uiFetidRot_Timer -= diff; + + if (m_uiDarkSlash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DARK_SLASH); + m_uiDarkSlash_Timer = urand(30000,35000); + } else m_uiDarkSlash_Timer -= diff; + + if (m_uiAncestors_Vengeance_Timer <= diff) + { + DoCast(me, SPELL_ANCESTORS_VENGEANCE); + m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(urand(60000,65000),urand(45000,50000)); + } else m_uiAncestors_Vengeance_Timer -= diff; + + // Abilities ------------------------------------------------------------------------------ + if (m_bIsActiveWithBJORN && m_uiAbility_BJORN_Timer <= diff) + { + //DoCast(me, SPELL_SUMMON_SPIRIT_FOUNT); // works fine, but using summon has better control + if (Creature* pTemp = me->SummonCreature(CREATURE_SPIRIT_FOUNT, 385+rand()%10, -330+rand()%10, 104.756, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) + { + pTemp->SetSpeed(MOVE_RUN, 0.4f); + pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SPIRIT_FOUNT, H_SPELL_SPIRIT_FOUNT), true); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetDisplayId(11686); + //pTemp->GetMotionMaster()->MoveChase(me->getVictim()); + m_uiOrbGUID = pTemp->GetGUID(); + } + m_bIsActiveWithBJORN = false; // only one orb + } else m_uiAbility_BJORN_Timer -= diff; + + if (m_bIsActiveWithHALDOR && m_uiAbility_HALDOR_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SPIRIT_STRIKE); + m_uiAbility_HALDOR_Timer = 5000; // overtime + } else m_uiAbility_HALDOR_Timer -= diff; + + if (m_bIsActiveWithRANULF && m_uiAbility_RANULF_Timer <= diff) + { + DoCast(me, SPELL_SPIRIT_BURST); + m_uiAbility_RANULF_Timer = 10000; // overtime + } else m_uiAbility_RANULF_Timer -= diff; + + if (m_bIsActiveWithTORGYN && m_uiAbility_TORGYN_Timer <= diff) + { + float x,y,z; + x = me->GetPositionX()-5; + y = me->GetPositionY()-5; + z = me->GetPositionZ(); + for (uint8 i = 0; i < 4; ++i) + { + //DoCast(me, SPELL_SUMMON_AVENGING_SPIRIT); // works fine, but using summon has better control + if (Creature* pTemp = me->SummonCreature(CREATURE_AVENGING_SPIRIT, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + pTemp->AddThreat(pTarget, 0.0f); + pTemp->AI()->AttackStart(pTarget); + } + } + } + m_uiAbility_TORGYN_Timer = 15000; // overtime + } else m_uiAbility_TORGYN_Timer -= diff; + + // Health check ----------------------------------------------------------------------------- + if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(m_uiHealthAmountMultipler * m_uiHealthAmountModifier))) + { + uint8 m_uiOrder = m_uiHealthAmountModifier - 1; + ++m_uiHealthAmountModifier; + + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_SCREAMS_OF_THE_DEAD); + me->GetMotionMaster()->Clear(); + me->StopMoving(); + me->AttackStop(); + me->GetMotionMaster()->MovePoint(0, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveX, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveY, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveZ); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + m_bIsActiveWithBJORN = false; + m_bIsActiveWithHALDOR = false; + m_bIsActiveWithRANULF = false; + m_bIsActiveWithTORGYN = false; + + m_uiBane_Timer += 8000; + m_uiFetidRot_Timer += 8000; + m_uiDarkSlash_Timer += 8000; + m_uiAncestors_Vengeance_Timer += 8000; + + m_uiActivedNumber = m_uiOrder; + m_bIsWalking = true; + m_uiPause_Timer = 2000; + return; + } + DoMeleeAttackIfReady(); + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } + + void DespawnBoatGhosts(uint64& m_uiCreatureGUID) + { + if (m_uiCreatureGUID) + if (Creature* pTemp = Unit::GetCreature(*me, m_uiCreatureGUID)) + pTemp->DisappearAndDie(); + + m_uiCreatureGUID = 0; + } +}; + +CreatureAI* GetAI_boss_ymiron(Creature* pCreature) +{ + return new boss_ymironAI(pCreature); +} + +void AddSC_boss_ymiron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ymiron"; + newscript->GetAI = &GetAI_boss_ymiron; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp new file mode 100644 index 00000000000..cf042867707 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp @@ -0,0 +1,241 @@ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +#define MAX_ENCOUNTER 4 + +/* Utgarde Pinnacle encounters: +0 - Svala Sorrowgrave +1 - Gortok Palehoof +2 - Skadi the Ruthless +3 - King Ymiron +*/ + +enum GameObjects +{ + ENTRY_SKADI_THE_RUTHLESS_DOOR = 192173, + ENTRY_KING_YMIRON_DOOR = 192174, + ENTRY_GORK_PALEHOOF_SPHERE = 188593 +}; + +struct instance_pinnacle : public ScriptedInstance +{ + instance_pinnacle(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiSvalaSorrowgrave; + uint64 uiGortokPalehoof; + uint64 uiSkadiTheRuthless; + uint64 uiKingYmiron; + + uint64 uiSkadiTheRuthlessDoor; + uint64 uiKingYmironDoor; + uint64 uiGortokPalehoofSphere; + + uint64 uiFrenziedWorgen; + uint64 uiRavenousFurbolg; + uint64 uiFerociousRhino; + uint64 uiMassiveJormungar; + uint64 uiPalehoofOrb; + + uint64 uiSvala; + uint64 uiSacrificedPlayer; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + std::string str_data; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + m_auiEncounter[i] = NOT_STARTED; + + uiSvalaSorrowgrave = 0; + uiGortokPalehoof = 0; + uiSkadiTheRuthless = 0; + uiKingYmiron = 0; + + uiSkadiTheRuthlessDoor = 0; + uiKingYmironDoor = 0; + uiGortokPalehoofSphere = 0; + + uiFrenziedWorgen = 0; + uiRavenousFurbolg = 0; + uiFerociousRhino = 0; + uiMassiveJormungar = 0; + uiPalehoofOrb = 0; + + uiSvala = 0; + uiSacrificedPlayer = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case BOSS_SVALA_SORROWGRAVE: uiSvalaSorrowgrave = pCreature->GetGUID(); break; + case BOSS_GORTOK_PALEHOOF: uiGortokPalehoof = pCreature->GetGUID(); break; + case BOSS_SKADI_RUTHLESS: uiSkadiTheRuthless = pCreature->GetGUID(); break; + case BOSS_KING_YMIRON: uiKingYmiron = pCreature->GetGUID(); break; + case MOB_FRENZIED_WORGEN: uiFrenziedWorgen = pCreature->GetGUID(); break; + case MOB_RAVENOUS_FURBOLG: uiRavenousFurbolg = pCreature->GetGUID(); break; + case MOB_MASSIVE_JORMUNGAR: uiMassiveJormungar = pCreature->GetGUID(); break; + case MOB_FEROCIOUS_RHINO: uiFerociousRhino = pCreature->GetGUID(); break; + case MOB_SVALA: uiSvala = pCreature->GetGUID(); break; + case MOB_PALEHOOF_ORB: uiPalehoofOrb = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case ENTRY_SKADI_THE_RUTHLESS_DOOR: + uiSkadiTheRuthlessDoor = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) HandleGameObject(NULL,true,pGo); + break; + case ENTRY_KING_YMIRON_DOOR: + uiKingYmironDoor = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) HandleGameObject(NULL,true,pGo); + break; + case ENTRY_GORK_PALEHOOF_SPHERE: + uiGortokPalehoofSphere = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + { + HandleGameObject(NULL,true,pGo); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_SVALA_SORROWGRAVE_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_GORTOK_PALEHOOF_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_SKADI_THE_RUTHLESS_EVENT: + if (data == DONE) + HandleGameObject(uiSkadiTheRuthlessDoor,true); + m_auiEncounter[2] = data; + break; + case DATA_KING_YMIRON_EVENT: + if (data == DONE) + HandleGameObject(uiKingYmironDoor,true); + m_auiEncounter[3] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_SACRIFICED_PLAYER) + uiSacrificedPlayer = data; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_SVALA_SORROWGRAVE_EVENT: return m_auiEncounter[0]; + case DATA_GORTOK_PALEHOOF_EVENT: return m_auiEncounter[1]; + case DATA_SKADI_THE_RUTHLESS_EVENT: return m_auiEncounter[2]; + case DATA_KING_YMIRON_EVENT: return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_SVALA_SORROWGRAVE: return uiSvalaSorrowgrave; + case DATA_GORTOK_PALEHOOF: return uiGortokPalehoof; + case DATA_SKADI_THE_RUTHLESS: return uiSkadiTheRuthless; + case DATA_KING_YMIRON: return uiKingYmiron; + case DATA_MOB_FRENZIED_WORGEN: return uiFrenziedWorgen; + case DATA_MOB_RAVENOUS_FURBOLG: return uiRavenousFurbolg; + case DATA_MOB_MASSIVE_JORMUNGAR: return uiMassiveJormungar; + case DATA_MOB_FEROCIOUS_RHINO: return uiFerociousRhino; + case DATA_MOB_ORB: return uiPalehoofOrb; + case DATA_SVALA: return uiSvala; + case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "U P " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'U' && dataHead2 == 'P') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_utgarde_pinnacle(Map* pMap) +{ + return new instance_pinnacle(pMap); +} + +void AddSC_instance_utgarde_pinnacle() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_utgarde_pinnacle"; + newscript->GetInstanceData = &GetInstanceData_instance_utgarde_pinnacle; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h new file mode 100644 index 00000000000..a51d7aceda0 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h @@ -0,0 +1,42 @@ +#ifndef DEF_PINNACLE_H +#define DEF_PINNACLE_H + +enum Data +{ + DATA_SVALA_SORROWGRAVE_EVENT, + DATA_GORTOK_PALEHOOF_EVENT, + DATA_SKADI_THE_RUTHLESS_EVENT, + DATA_KING_YMIRON_EVENT +}; +enum Data64 +{ + DATA_SVALA, + DATA_SVALA_SORROWGRAVE, + DATA_GORTOK_PALEHOOF, + DATA_SKADI_THE_RUTHLESS, + DATA_MOB_GRAUF, + DATA_KING_YMIRON, + DATA_MOB_FRENZIED_WORGEN, + DATA_MOB_RAVENOUS_FURBOLG, + DATA_MOB_MASSIVE_JORMUNGAR, + DATA_MOB_FEROCIOUS_RHINO, + DATA_MOB_ORB, + DATA_GORTOK_PALEHOOF_SPHERE, + DATA_SACRIFICED_PLAYER +}; + +enum eCreatures +{ + BOSS_SVALA_SORROWGRAVE = 26668, + BOSS_GORTOK_PALEHOOF = 26687, + BOSS_SKADI_RUTHLESS = 26693, + BOSS_KING_YMIRON = 26861, + MOB_FRENZIED_WORGEN = 26683, + MOB_RAVENOUS_FURBOLG = 26684, + MOB_MASSIVE_JORMUNGAR = 26685, + MOB_FEROCIOUS_RHINO = 26686, + MOB_SVALA = 29281, + MOB_PALEHOOF_ORB = 26688, +}; + +#endif diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp new file mode 100644 index 00000000000..11d432e94c6 --- /dev/null +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2009-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*** SQL START *** +UPDATE `creature_template` SET `ScriptName`='boss_archavon' WHERE `entry`='31125'; +UPDATE `creature_template` SET `ScriptName`='mob_archavon_warder' WHERE `entry`='32353'; +*** SQL END ***/ + +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +#define EMOTE_BERSERK -1590002 + +//Spells Archavon +#define SPELL_ROCK_SHARDS 58678 +#define SPELL_CRUSHING_LEAP RAID_MODE(58960,60894)//Instant (10-80yr range) -- Leaps at an enemy, inflicting 8000 Physical damage, knocking all nearby enemies away, and creating a cloud of choking debris. +#define SPELL_STOMP RAID_MODE(58663,60880) +#define SPELL_IMPALE RAID_MODE(58666,60882) //Lifts an enemy off the ground with a spiked fist, inflicting 47125 to 52875 Physical damage and 9425 to 10575 additional damage each second for 8 sec. +#define SPELL_BERSERK 47008 +//Spells Archavon Warders +#define SPELL_ROCK_SHOWER RAID_MODE(60919,60923) +#define SPELL_SHIELD_CRUSH RAID_MODE(60897,60899) +#define SPELL_WHIRL RAID_MODE(60902,60916) + +//4 Warders spawned +#define ARCHAVON_WARDER 32353 //npc 32353 + +//Yell +#define SAY_LEAP "Archavon the Stone Watcher lunges for $N!" //$N should be the target + +#define EVENT_ROCK_SHARDS 1 //15s cd +#define EVENT_CHOKING_CLOUD 2 //30s cd +#define EVENT_STOMP 3 //45s cd +#define EVENT_IMPALE 4 +#define EVENT_BERSERK 5 //300s cd + +//mob +#define EVENT_ROCK_SHOWER 5 //set = 20s cd,unkown cd +#define EVENT_SHIELD_CRUSH 6 //set = 30s cd +#define EVENT_WHIRL 8 //set= 10s cd + +struct boss_archavonAI : public ScriptedAI +{ + boss_archavonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit* /*Victim*/) {} + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); + events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); + events.ScheduleEvent(EVENT_STOMP, 45000); + events.ScheduleEvent(EVENT_BERSERK, 300000); + + if (pInstance) + pInstance->SetData(DATA_ARCHAVON_EVENT, IN_PROGRESS); + } + + // Below UpdateAI may need review/debug. + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ROCK_SHARDS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ROCK_SHARDS); + events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); + return; + case EVENT_CHOKING_CLOUD: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CRUSHING_LEAP, true); //10y~80y, ignore range + events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); + return; + case EVENT_STOMP: + DoCast(me->getVictim(), SPELL_STOMP); + events.ScheduleEvent(EVENT_IMPALE, 3000); + events.ScheduleEvent(EVENT_STOMP, 45000); + return; + case EVENT_IMPALE: + DoCast(me->getVictim(), SPELL_IMPALE); + return; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + DoScriptText(EMOTE_BERSERK, me); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Mob Archavon Warder +######*/ +struct mob_archavon_warderAI : public ScriptedAI //npc 32353 +{ + mob_archavon_warderAI(Creature *c) : ScriptedAI(c) {} + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + events.ScheduleEvent(EVENT_ROCK_SHOWER, 2000); + events.ScheduleEvent(EVENT_SHIELD_CRUSH, 20000); + events.ScheduleEvent(EVENT_WHIRL, 7500); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ROCK_SHOWER: + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ROCK_SHOWER); + events.ScheduleEvent(EVENT_ROCK_SHARDS, 6000); + return; + } + case EVENT_SHIELD_CRUSH: + DoCast(me->getVictim(), SPELL_SHIELD_CRUSH); + events.ScheduleEvent(EVENT_SHIELD_CRUSH, 20000); + return; + case EVENT_WHIRL: + DoCast(me->getVictim(), SPELL_WHIRL); + events.ScheduleEvent(EVENT_WHIRL, 8000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_archavon_warder(Creature* pCreature) +{ + return new mob_archavon_warderAI(pCreature); +} + +CreatureAI* GetAI_boss_archavon(Creature* pCreature) +{ + return new boss_archavonAI (pCreature); +} + +void AddSC_boss_archavon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_archavon"; + newscript->GetAI = &GetAI_boss_archavon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_archavon_warder"; + newscript->GetAI = &GetAI_mob_archavon_warder; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp new file mode 100644 index 00000000000..92a0331708e --- /dev/null +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_emalon.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2009-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +//Emalon spells +#define SPELL_CHAIN_LIGHTNING RAID_MODE(64213, 64215) +#define SPELL_LIGHTNING_NOVA RAID_MODE(64216, 65279) +#define SPELL_OVERCHARGE 64218 //Casted every 45 sec on a random Tempest Minion +#define SPELL_BERSERK 26662 + +//Tempest Minion spells +#define SPELL_SHOCK 64363 +#define SPELL_OVERCHARGED 64217 +#define SPELL_OVERCHARGED_BLAST 64219 //Casted when Overcharged reaches 10 stacks. Mob dies after that + +//Emotes +#define EMOTE_OVERCHARGE -1590000 +#define EMOTE_MINION_RESPAWN -1590001 +#define EMOTE_BERSERK -1590002 + +//Events +#define EVENT_CHAIN_LIGHTNING 1 +#define EVENT_LIGHTNING_NOVA 2 +#define EVENT_OVERCHARGE 3 +#define EVENT_BERSERK 4 +#define EVENT_SHOCK 5 + +//Creatures +#define MOB_TEMPEST_MINION 33998 + +#define MAX_TEMPEST_MINIONS 4 + +struct Position TempestMinions[MAX_TEMPEST_MINIONS] = +{ + {-203.980103, -281.287720, 91.650223, 1.598807}, + {-233.489410, -281.139282, 91.652412, 1.598807}, + {-233.267578, -297.104645, 91.681915, 1.598807}, + {-203.842529, -297.097015, 91.745163, 1.598807} +}; + +/*###### +## Emalon the Storm Watcher +######*/ +struct boss_emalonAI : public BossAI +{ + boss_emalonAI(Creature *c) : BossAI(c, DATA_EMALON_EVENT) + { + } + + void Reset() + { + _Reset(); + + for (uint8 i = 0; i < MAX_TEMPEST_MINIONS; ++i) + me->SummonCreature(MOB_TEMPEST_MINION, TempestMinions[i], TEMPSUMMON_CORPSE_DESPAWN, 0); + } + + void JustSummoned(Creature *summoned) + { + BossAI::JustSummoned(summoned); + + if (me->getVictim() && summoned->AI()) + summoned->AI()->AttackStart(me->getVictim()); + } + + void EnterCombat(Unit * who) + { + if (!summons.empty()) + { + for (std::list::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) + { + Creature *minion = Unit::GetCreature(*me, *itr); + if (minion && minion->isAlive() && !minion->getVictim() && minion->AI()) + minion->AI()->AttackStart(who); + } + } + + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 5000); + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 40000); + events.ScheduleEvent(EVENT_BERSERK, 360000); + events.ScheduleEvent(EVENT_OVERCHARGE, 45000); + + _EnterCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CHAIN_LIGHTNING: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 25000); + break; + case EVENT_LIGHTNING_NOVA: + DoCastAOE(SPELL_LIGHTNING_NOVA, false); + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 40000); + break; + case EVENT_OVERCHARGE: + if (!summons.empty()) + { + std::list::const_iterator itr = summons.begin(); + std::advance(itr, urand(0, summons.size()-1)); + Creature *minion = Unit::GetCreature(*me, *itr); + if (minion && minion->isAlive()) + { + minion->CastSpell(me, SPELL_OVERCHARGED, true); + minion->SetHealth(minion->GetMaxHealth()); + DoScriptText(EMOTE_OVERCHARGE, me); + events.ScheduleEvent(EVENT_OVERCHARGE, 45000); + } + } + break; + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK); + DoScriptText(EMOTE_BERSERK, me); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Tempest Minion +######*/ +struct mob_tempest_minionAI : public ScriptedAI +{ + mob_tempest_minionAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + EventMap events; + + uint32 uiOverchargedTimer; + + void Reset() + { + events.Reset(); + + uiOverchargedTimer = 0; + } + + void JustDied(Unit* /*Killer*/) + { + if (Creature *pEmalon = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EMALON) : 0)) + { + if (pEmalon->isAlive()) + { + pEmalon->SummonCreature(MOB_TEMPEST_MINION, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoScriptText(EMOTE_MINION_RESPAWN, me); + } + } + } + + void EnterCombat(Unit * who) + { + DoZoneInCombat(); + events.ScheduleEvent(EVENT_SHOCK, 20000); + + if (Creature *pEmalon = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EMALON) : 0)) + { + if (!pEmalon->getVictim() && pEmalon->AI()) + pEmalon->AI()->AttackStart(who); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (Aura *overchargedAura = me->GetAura(SPELL_OVERCHARGED)) + { + if (overchargedAura->GetStackAmount() < 10) + { + if (uiOverchargedTimer <= diff) + { + DoCast(me, SPELL_OVERCHARGED); + uiOverchargedTimer = 2000; + } else uiOverchargedTimer -=diff; + } + else + { + if (overchargedAura->GetStackAmount() == 10) + { + DoCast(me, SPELL_OVERCHARGED_BLAST); + me->ForcedDespawn(); + DoScriptText(EMOTE_MINION_RESPAWN, me); + } + } + } + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHOCK: + DoCast(me->getVictim(), SPELL_SHOCK); + events.ScheduleEvent(EVENT_SHOCK, 20000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_tempest_minion(Creature *_Creature) +{ + return new mob_tempest_minionAI (_Creature); +} + +CreatureAI* GetAI_boss_emalon(Creature *_Creature) +{ + return new boss_emalonAI (_Creature); +} + +void AddSC_boss_emalon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_emalon"; + newscript->GetAI = &GetAI_boss_emalon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tempest_minion"; + newscript->GetAI = &GetAI_mob_tempest_minion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp new file mode 100644 index 00000000000..61843647136 --- /dev/null +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_koralon.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2009-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*** SQL START *** +UPDATE `creature_template` SET `ScriptName`='boss_koralon' WHERE `entry`='35013'; +UPDATE `creature_template` SET `ScriptName`='mob_flame_warder' WHERE `entry`='35143'; +*** SQL END ***/ + +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +enum Events +{ + EVENT_NONE, + + // Koralon + EVENT_BURNING_BREATH, + EVENT_BURNING_FURY, + EVENT_FLAME_CINDER_A, + EVENT_METEOR_FISTS_A, + EVENT_METEOR_FISTS_B, + + // Flame Warder + EVENT_FW_LAVA_BIRST, + EVENT_FW_METEOR_FISTS_A, + EVENT_FW_METEOR_FISTS_B, +}; + +enum Spells +{ + // Spells Koralon + SPELL_BURNING_BREATH = 66665, + SPELL_BURNING_BREATH_H = 67328, + SPELL_BURNING_FURY = 66721, + SPELL_FLAME_CINDER_A = 66684, + SPELL_FLAME_CINDER_A_H = 67332, + SPELL_FLAME_CINDER_B = 66681, // don't know the real relation to SPELL_FLAME_CINDER_A atm. + SPELL_METEOR_FISTS_A = 66725, + SPELL_METEOR_FISTS_A_H = 66765, + SPELL_METEOR_FISTS_B = 67333, + SPELL_METEOR_FISTS_B_H = 68161, + + // Spells Flame Warder + SPELL_FW_LAVA_BIRST = 66813, + SPELL_FW_LAVA_BIRST_H = 67330, + SPELL_FW_METEOR_FISTS_A = 66808, + SPELL_FW_METEOR_FISTS_A_H = 66809, + SPELL_FW_METEOR_FISTS_B = 67331, + SPELL_FW_METEOR_FISTS_B_H = 68160, +}; + +struct boss_koralonAI : public ScriptedAI +{ + boss_koralonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_KORALON_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit* /*Victim*/) {} + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_KORALON_EVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + + DoCast(me, SPELL_BURNING_FURY); + + events.ScheduleEvent(EVENT_BURNING_FURY, 20000); // TODO check timer + events.ScheduleEvent(EVENT_BURNING_BREATH, 15000); // 1st after 15sec, then every 45sec + events.ScheduleEvent(EVENT_METEOR_FISTS_A, 75000); // 1st after 75sec, then every 45sec + events.ScheduleEvent(EVENT_FLAME_CINDER_A, 30000); // TODO check timer + + if (pInstance) + pInstance->SetData(DATA_KORALON_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BURNING_FURY: + DoCast(me, SPELL_BURNING_FURY); + events.ScheduleEvent(EVENT_BURNING_FURY, 20000); + return; + case EVENT_BURNING_BREATH: + DoCast(me, RAID_MODE(SPELL_BURNING_BREATH,SPELL_BURNING_BREATH_H)); + events.ScheduleEvent(EVENT_BURNING_BREATH, 45000); + return; + case EVENT_METEOR_FISTS_A: + DoCast(me, RAID_MODE(SPELL_METEOR_FISTS_A,SPELL_METEOR_FISTS_A_H)); + events.ScheduleEvent(EVENT_METEOR_FISTS_B, 1500); + return; + case EVENT_METEOR_FISTS_B: + DoCast(me, RAID_MODE(SPELL_METEOR_FISTS_B,SPELL_METEOR_FISTS_B_H)); + events.ScheduleEvent(EVENT_METEOR_FISTS_A, 45000); + return; + case EVENT_FLAME_CINDER_A: + DoCast(me, RAID_MODE(SPELL_FLAME_CINDER_A,SPELL_FLAME_CINDER_A_H)); + events.ScheduleEvent(EVENT_FLAME_CINDER_A, 30000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Mob Flame Warder +######*/ +struct mob_flame_warderAI : public ScriptedAI +{ + mob_flame_warderAI(Creature *c) : ScriptedAI(c) {} + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + + events.ScheduleEvent(EVENT_FW_LAVA_BIRST, 5000); + events.ScheduleEvent(EVENT_FW_METEOR_FISTS_A, 10000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FW_LAVA_BIRST: + DoCast(me->getVictim(), RAID_MODE(SPELL_FW_LAVA_BIRST,SPELL_FW_LAVA_BIRST_H)); + events.ScheduleEvent(EVENT_FW_LAVA_BIRST, 15000); + return; + case EVENT_FW_METEOR_FISTS_A: + DoCast(me, RAID_MODE(SPELL_FW_METEOR_FISTS_A,SPELL_FW_METEOR_FISTS_A_H)); + events.ScheduleEvent(EVENT_FW_METEOR_FISTS_B, 1500); + return; + case EVENT_FW_METEOR_FISTS_B: + DoCast(me, RAID_MODE(SPELL_FW_METEOR_FISTS_B,SPELL_FW_METEOR_FISTS_B_H)); + events.ScheduleEvent(EVENT_FW_METEOR_FISTS_A, 20000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_koralon(Creature* pCreature) +{ + return new boss_koralonAI (pCreature); +} + +CreatureAI* GetAI_mob_flame_warder(Creature* pCreature) +{ + return new mob_flame_warderAI (pCreature); +} + +void AddSC_boss_koralon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_koralon"; + newscript->GetAI = &GetAI_boss_koralon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flame_warder"; + newscript->GetAI = &GetAI_mob_flame_warder; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp new file mode 100644 index 00000000000..2e16f9211d2 --- /dev/null +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2009-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*** SQL START *** +UPDATE `creature_template` SET `ScriptName`='boss_toravon' WHERE `entry`='38433'; +UPDATE `creature_template` SET `ScriptName`='mob_frost_warder' WHERE `entry`='38482'; +UPDATE `creature_template` SET `ScriptName`='mob_frozen_orb_stalker' WHERE `entry`='38461'; +UPDATE `creature_template` SET `ScriptName`='mob_frozen_orb' WHERE `entry`='38456'; +*** SQL END ***/ + +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +// Spells Toravon +#define SPELL_FREEZING_GROUND RAID_MODE(72090,72104) // don't know cd... using 20 secs. +#define SPELL_FROZEN_ORB RAID_MODE(72091,72095) +#define SPELL_WHITEOUT RAID_MODE(72034,72096) // Every 38 sec. cast. (after SPELL_FROZEN_ORB) +#define SPELL_FROZEN_MALLET 71993 + +// Spells Frost Warder +#define SPELL_FROST_BLAST RAID_MODE(72123,72124) // don't know cd... using 20 secs. +#define SPELL_FROZEN_MALLET 72122 + +// Spell Frozen Orb +#define SPELL_FROZEN_ORB_DMG 72081 // priodic dmg aura +#define SPELL_FROZEN_ORB_AURA 72067 // make visible + +// Spell Frozen Orb Stalker +#define SPELL_FROZEN_ORB_SUMMON 72093 // summon orb + +// Events boss +#define EVENT_FREEZING_GROUND 1 +#define EVENT_FROZEN_ORB 2 +#define EVENT_WHITEOUT 3 + +// Events mob +#define EVENT_FROST_BLAST 4 + +// Mob Frozen Orb +#define MOB_FROZEN_ORB 38456 // 1 in 10 mode and 3 in 25 mode + +struct boss_toravonAI : public ScriptedAI +{ + boss_toravonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_TORAVON_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit* /*Victim*/) {} + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_TORAVON_EVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + + DoCast(me, SPELL_FROZEN_MALLET); + + events.ScheduleEvent(EVENT_FROZEN_ORB, 11000); + events.ScheduleEvent(EVENT_WHITEOUT, 13000); + events.ScheduleEvent(EVENT_FREEZING_GROUND, 15000); + + if (pInstance) + pInstance->SetData(DATA_TORAVON_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROZEN_ORB: + DoCast(me, SPELL_FROZEN_ORB); + events.ScheduleEvent(EVENT_FROZEN_ORB, 38000); + return; + case EVENT_WHITEOUT: + DoCast(me, SPELL_WHITEOUT); + events.ScheduleEvent(EVENT_WHITEOUT, 38000); + return; + case EVENT_FREEZING_GROUND: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FREEZING_GROUND); + events.ScheduleEvent(EVENT_FREEZING_GROUND, 20000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +/*###### +## Mob Frost Warder +######*/ +struct mob_frost_warderAI : public ScriptedAI +{ + mob_frost_warderAI(Creature *c) : ScriptedAI(c) {} + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + + DoCast(me, SPELL_FROZEN_MALLET); + + events.ScheduleEvent(EVENT_FROST_BLAST, 5000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROST_BLAST: + DoCast(me->getVictim(), SPELL_FROST_BLAST); + events.ScheduleEvent(EVENT_FROST_BLAST, 20000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + + +/*###### +## Mob Frozen Orb +######*/ +struct mob_frozen_orbAI : public ScriptedAI +{ + mob_frozen_orbAI(Creature *c) : ScriptedAI(c) {} + + bool done; + uint32 killtimer; + + void Reset() + { + done = false; + killtimer = 60000; // if after this time there is no victim -> destroy! + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + if (!done) + { + DoCast(me, SPELL_FROZEN_ORB_AURA, true); + DoCast(me, SPELL_FROZEN_ORB_DMG, true); + done = true; + } + + if (killtimer <= diff) + { + if (!UpdateVictim()) + me->ForcedDespawn(); + killtimer = 10000; + } + else + killtimer -= diff; + } +}; + +/*###### +## Mob Frozen Orb Stalker +######*/ +struct mob_frozen_orb_stalkerAI : public Scripted_NoMovementAI +{ + mob_frozen_orb_stalkerAI(Creature* c) : Scripted_NoMovementAI(c) + { + c->SetVisibility(VISIBILITY_OFF); + c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); + c->SetReactState(REACT_PASSIVE); + + pInstance = c->GetInstanceData(); + spawned = false; + } + + ScriptedInstance *pInstance; + bool spawned; + + void UpdateAI(const uint32 /*diff*/) + { + if (spawned) + return; + + spawned = true; + if (!pInstance) + return; + + Unit* pToravon = me->GetCreature(*me, pInstance->GetData64(DATA_TORAVON)); + if (!pToravon) + return; + + uint8 num_orbs = RAID_MODE(1, 3); + for (uint8 i=0; iGetNearPoint(pToravon, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 10.0f, 0.0f); + me->SetPosition(pos, true); + DoCast(me, SPELL_FROZEN_ORB_SUMMON); + } + } +}; + +CreatureAI* GetAI_boss_toravon(Creature* pCreature) +{ + return new boss_toravonAI (pCreature); +} + +CreatureAI* GetAI_mob_frost_warder(Creature* pCreature) +{ + return new mob_frost_warderAI (pCreature); +} + +CreatureAI* GetAI_mob_frozen_orb(Creature* pCreature) +{ + return new mob_frozen_orbAI (pCreature); +} + +CreatureAI* GetAI_mob_frozen_orb_stalker(Creature* pCreature) +{ + return new mob_frozen_orb_stalkerAI (pCreature); +} + +void AddSC_boss_toravon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_toravon"; + newscript->GetAI = &GetAI_boss_toravon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_warder"; + newscript->GetAI = &GetAI_mob_frost_warder; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frozen_orb"; + newscript->GetAI = &GetAI_mob_frozen_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frozen_orb_stalker"; + newscript->GetAI = &GetAI_mob_frozen_orb_stalker; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp new file mode 100644 index 00000000000..a7183921cce --- /dev/null +++ b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp @@ -0,0 +1,143 @@ +#include "ScriptedPch.h" +#include "vault_of_archavon.h" + +#define ENCOUNTERS 4 + +/* Vault of Archavon encounters: +1 - Archavon the Stone Watcher event +2 - Emalon the Storm Watcher event +3 - Koralon the Flame Watcher event +4 - Toravon the Ice Watcher event +*/ + +struct instance_archavon : public ScriptedInstance +{ + instance_archavon(Map *Map) : ScriptedInstance(Map) {}; + + uint32 uiEncounters[ENCOUNTERS]; + + uint64 uiArchavon; + uint64 uiEmalon; + uint64 uiKoralon; + uint64 uiToravon; + + void Initialize() + { + uiArchavon = 0; + uiEmalon = 0; + uiKoralon = 0; + uiToravon = 0; + + for (uint8 i = 0; i < ENCOUNTERS; i++) + uiEncounters[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < ENCOUNTERS; i++) + if (uiEncounters[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature *creature, bool /*add*/) + { + switch(creature->GetEntry()) + { + case CREATURE_ARCHAVON: uiArchavon = creature->GetGUID(); break; + case CREATURE_EMALON: uiEmalon = creature->GetGUID(); break; + case CREATURE_KORALON: uiKoralon = creature->GetGUID(); break; + case CREATURE_TORAVON: uiToravon = creature->GetGUID(); break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_ARCHAVON_EVENT: return uiEncounters[0]; + case DATA_EMALON_EVENT: return uiEncounters[1]; + case DATA_KORALON_EVENT: return uiEncounters[2]; + case DATA_TORAVON_EVENT: return uiEncounters[3]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_ARCHAVON: return uiArchavon; + case DATA_EMALON: return uiEmalon; + case DATA_KORALON: return uiKoralon; + case DATA_TORAVON: return uiToravon; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_ARCHAVON_EVENT: uiEncounters[0] = data; break; + case DATA_EMALON_EVENT: uiEncounters[1] = data; break; + case DATA_KORALON_EVENT: uiEncounters[2] = data; break; + case DATA_TORAVON_EVENT: uiEncounters[3] = data; break; + } + + if (data == DONE) + SaveToDB(); + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << uiEncounters[0] << " " << uiEncounters[1] << " " << uiEncounters[2] << " " << uiEncounters[3]; + + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream stream(in); + stream >> uiEncounters[0] >> uiEncounters[1] >> uiEncounters[2] >> uiEncounters[3]; + + for (uint8 i = 0; i < ENCOUNTERS; ++i) + if (uiEncounters[i] == IN_PROGRESS) + uiEncounters[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_archavon(Map* map) +{ + return new instance_archavon(map); +} + +void AddSC_instance_archavon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_archavon"; + newscript->GetInstanceData = &GetInstanceData_instance_archavon; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h b/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h new file mode 100644 index 00000000000..6aa642ff701 --- /dev/null +++ b/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h @@ -0,0 +1,28 @@ +#ifndef DEF_ARCHAVON_H +#define DEF_ARCHAVON_H + +enum Creatures +{ + CREATURE_ARCHAVON = 31125, + CREATURE_EMALON = 33993, + CREATURE_KORALON = 35013, + CREATURE_TORAVON = 38433, +}; + +enum Data +{ + DATA_ARCHAVON_EVENT, + DATA_EMALON_EVENT, + DATA_KORALON_EVENT, + DATA_TORAVON_EVENT, +}; + +enum Data64 +{ + DATA_ARCHAVON, + DATA_EMALON, + DATA_KORALON, + DATA_TORAVON, +}; + +#endif diff --git a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp new file mode 100644 index 00000000000..589e69a6f18 --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp @@ -0,0 +1,156 @@ +/* Script Data Start +SDName: Boss cyanigosa +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_ARCANE_VACUUM = 58694, + SPELL_BLIZZARD = 58693, + H_SPELL_BLIZZARD = 59369, + SPELL_MANA_DESTRUCTION = 59374, + SPELL_TAIL_SWEEP = 58690, + H_SPELL_TAIL_SWEEP = 59283, + SPELL_UNCONTROLLABLE_ENERGY = 58688, + H_SPELL_UNCONTROLLABLE_ENERGY = 59281, + SPELL_TRANSFORM = 58668 +}; + +enum Yells +{ + SAY_AGGRO = -1608000, + SAY_SLAY_1 = -1608001, + SAY_SLAY_2 = -1608002, + SAY_SLAY_3 = -1608003, + SAY_DEATH = -1608004, + SAY_SPAWN = -1608005, + SAY_DISRUPTION = -1608006, + SAY_BREATH_ATTACK = -1608007, + SAY_SPECIAL_ATTACK_1 = -1608008, + SAY_SPECIAL_ATTACK_2 = -1608009 +}; + +struct boss_cyanigosaAI : public ScriptedAI +{ + boss_cyanigosaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiArcaneVacuumTimer; + uint32 uiBlizzardTimer; + uint32 uiManaDestructionTimer; + uint32 uiTailSweepTimer; + uint32 uiUncontrollableEnergyTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiArcaneVacuumTimer = 10000; + uiBlizzardTimer = 15000; + uiManaDestructionTimer = 30000; + uiTailSweepTimer = 20000; + uiUncontrollableEnergyTimer = 25000; + if (pInstance) + pInstance->SetData(DATA_CYANIGOSA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_TRANSFORM); + + if (pInstance) + pInstance->SetData(DATA_CYANIGOSA_EVENT, IN_PROGRESS); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (pInstance && pInstance->GetData(DATA_REMOVE_NPC) == 1) + { + me->ForcedDespawn(); + pInstance->SetData(DATA_REMOVE_NPC, 0); + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiArcaneVacuumTimer <= diff) + { + DoCast(SPELL_ARCANE_VACUUM); + uiArcaneVacuumTimer = 10000; + } else uiArcaneVacuumTimer -= diff; + + if (uiBlizzardTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BLIZZARD); + uiBlizzardTimer = 15000; + } else uiBlizzardTimer -= diff; + + if (uiTailSweepTimer <= diff) + { + DoCast(SPELL_TAIL_SWEEP); + uiTailSweepTimer = 20000; + } else uiTailSweepTimer -= diff; + + if (uiUncontrollableEnergyTimer <= diff) + { + DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY); + uiUncontrollableEnergyTimer = 25000; + } else uiUncontrollableEnergyTimer -= diff; + + if (IsHeroic()) + if (uiManaDestructionTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_MANA_DESTRUCTION); + uiManaDestructionTimer = 30000; + } else uiManaDestructionTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_CYANIGOSA_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_cyanigosa(Creature* pCreature) +{ + return new boss_cyanigosaAI (pCreature); +} + +void AddSC_boss_cyanigosa() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_cyanigosa"; + newscript->GetAI = &GetAI_boss_cyanigosa; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp new file mode 100644 index 00000000000..a9cc7393af4 --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp @@ -0,0 +1,329 @@ +/* Script Data Start +SDName: Boss erekem +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_BLOODLUST = 54516, + SPELL_BREAK_BONDS = 59463, + SPELL_CHAIN_HEAL = 54481, + H_SPELL_CHAIN_HEAL = 59473, + SPELL_EARTH_SHIELD = 54479, + H_SPELL_EARTH_SHIELD = 59471, + SPELL_EARTH_SHOCK = 54511, + SPELL_LIGHTNING_BOLT = 53044, + SPELL_STORMSTRIKE = 51876 +}; + +enum Yells +{ + SAY_AGGRO = -1608010, + SAY_SLAY_1 = -1608011, + SAY_SLAY_2 = -1608012, + SAY_SLAY_3 = -1608013, + SAY_DEATH = -1608014, + SAY_SPAWN = -1608015, + SAY_ADD_KILLED = -1608016, + SAY_BOTH_ADDS_KILLED = -1608017 +}; + +struct boss_erekemAI : public ScriptedAI +{ + boss_erekemAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBloodlustTimer; + uint32 uiChainHealTimer; + uint32 uiEarthShockTimer; + uint32 uiLightningBoltTimer; + uint32 uiEarthShieldTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiBloodlustTimer = 15000; + uiChainHealTimer = 0; + uiEarthShockTimer = urand(2000,8000); + uiLightningBoltTimer = urand(5000,10000); + uiEarthShieldTimer = 20000; + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + + if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + { + if (!pGuard1->isAlive()) + pGuard1->Respawn(); + } + if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + { + if (!pGuard2->isAlive()) + pGuard2->Respawn(); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + + if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + { + pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + if (!pGuard1->getVictim() && pGuard1->AI()) + pGuard1->AI()->AttackStart(pWho); + } + if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + { + pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + if (!pGuard2->getVictim() && pGuard2->AI()) + pGuard2->AI()->AttackStart(pWho); + } + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_EARTH_SHIELD); + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_EREKEM_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //spam stormstrike in hc mode if spawns are dead + if (IsHeroic()) + { + if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) + { + if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) + { + if (!pGuard1->isAlive() && !pGuard2->isAlive()) + DoCast(me->getVictim(), SPELL_STORMSTRIKE); + } + } + } + + if (uiEarthShieldTimer <= diff) + { + DoCast(me, SPELL_EARTH_SHIELD); + uiEarthShieldTimer = 20000; + } else uiEarthShieldTimer -= diff; + + if (uiChainHealTimer <= diff) + { + if (uint64 TargetGUID = GetChainHealTargetGUID()) + { + if (Creature *pTarget = Unit::GetCreature(*me, TargetGUID)) + DoCast(pTarget, SPELL_CHAIN_HEAL); + + //If one of the adds is dead spawn heals faster + Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0); + Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0); + uiChainHealTimer = ((pGuard1 && !pGuard1->isAlive()) || (pGuard2 && !pGuard2->isAlive()) ? 3000 : 8000) + rand()%3000; + } + } else uiChainHealTimer -= diff; + + if (uiBloodlustTimer <= diff) + { + DoCast(me, SPELL_BLOODLUST); + uiBloodlustTimer = urand(35000,45000); + } else uiBloodlustTimer -= diff; + + if (uiEarthShockTimer <= diff) + { + DoCast(me->getVictim(), SPELL_EARTH_SHOCK); + uiEarthShockTimer = urand(8000,13000); + } else uiEarthShockTimer -= diff; + + if (uiLightningBoltTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_LIGHTNING_BOLT); + uiLightningBoltTimer = urand(18000,24000); + } else uiLightningBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + uint64 GetChainHealTargetGUID() + { + if (HealthBelowPct(85)) + return me->GetGUID(); + + Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0); + if (pGuard1 && pGuard1->isAlive() && (pGuard1->GetHealth()*100 <= pGuard1->GetMaxHealth() * 75)) + return pGuard1->GetGUID(); + + Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0); + if (pGuard2 && pGuard2->isAlive() && (pGuard2->GetHealth()*100 <= pGuard2->GetMaxHealth() * 75)) + return pGuard2->GetGUID(); + + return 0; + } +}; + +CreatureAI* GetAI_boss_erekem(Creature* pCreature) +{ + return new boss_erekemAI (pCreature); +} + +enum GuardSpells +{ + SPELL_GUSHING_WOUND = 39215, + SPELL_HOWLING_SCREECH = 54462, + SPELL_STRIKE = 14516 +}; + +struct mob_erekem_guardAI : public ScriptedAI +{ + mob_erekem_guardAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiGushingWoundTimer; + uint32 uiHowlingScreechTimer; + uint32 uiStrikeTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiStrikeTimer = urand(4000,8000); + uiHowlingScreechTimer = urand(8000,13000); + uiGushingWoundTimer = urand(1000,3000); + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + + if (uiStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STRIKE); + uiStrikeTimer = urand(4000,8000); + } else uiStrikeTimer -= diff; + + if (uiHowlingScreechTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HOWLING_SCREECH); + uiHowlingScreechTimer = urand(8000,13000); + } else uiHowlingScreechTimer -= diff; + + if (uiGushingWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GUSHING_WOUND); + uiGushingWoundTimer = urand(7000,12000); + } else uiGushingWoundTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_erekem_guard(Creature* pCreature) +{ + return new mob_erekem_guardAI (pCreature); +} + +void AddSC_boss_erekem() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_erekem"; + newscript->GetAI = &GetAI_boss_erekem; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_erekem_guard"; + newscript->GetAI = &GetAI_mob_erekem_guard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp new file mode 100644 index 00000000000..a28bfdffb7c --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp @@ -0,0 +1,394 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Boss ichoron +SDAuthor: ckegg +SD%Complete: 80% +SDComment: TODO: better spawn location for adds +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_DRAINED = 59820, + SPELL_FRENZY = 54312, + SPELL_FRENZY_H = 59522, + SPELL_PROTECTIVE_BUBBLE = 54306, + SPELL_WATER_BLAST = 54237, + SPELL_WATER_BLAST_H = 59520, + SPELL_WATER_BOLT_VOLLEY = 54241, + SPELL_WATER_BOLT_VOLLEY_H = 59521, + SPELL_SPLASH = 59516, +}; + +enum IchoronCreatures +{ + NPC_ICHOR_GLOBULE = 29321, +}; + +enum Yells +{ + SAY_AGGRO = -1608018, + SAY_SLAY_1 = -1608019, + SAY_SLAY_2 = -1608020, + SAY_SLAY_3 = -1608021, + SAY_DEATH = -1608022, + SAY_SPAWN = -1608023, + SAY_ENRAGE = -1608024, + SAY_SHATTER = -1608025, + SAY_BUBBLE = -1608026 +}; + +enum Achievements +{ + ACHIEVEMENT_DEHYDRATION = 2041, +}; + +enum Actions +{ + ACTION_WATER_ELEMENT_HIT = 1, + ACTION_WATER_ELEMENT_KILLED = 2, +}; + +// TODO get those positions from spawn of creature 29326 +#define MAX_SPAWN_LOC 5 +static Position SpawnLoc[MAX_SPAWN_LOC]= +{ + {1840.64, 795.407, 44.079, 1.676}, + {1886.24, 757.733, 47.750, 5.201}, + {1877.91, 845.915, 43.417, 3.560}, + {1918.97, 850.645, 47.225, 4.136}, + {1935.50, 796.224, 52.492, 4.224}, +}; + +struct boss_ichoronAI : public ScriptedAI +{ + boss_ichoronAI(Creature* pCreature) : ScriptedAI(pCreature), m_waterElements(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + bool bIsExploded; + bool bIsFrenzy; + bool bAchievement; + + uint32 uiBubbleCheckerTimer; + uint32 uiWaterBoltVolleyTimer; + + ScriptedInstance* pInstance; + + SummonList m_waterElements; + + void Reset() + { + bIsExploded = false; + bIsFrenzy = false; + bAchievement = true; + uiBubbleCheckerTimer = 1000; + uiWaterBoltVolleyTimer = urand(10000, 15000); + + me->SetVisibility(VISIBILITY_ON); + DespawnWaterElements(); + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + DoCast(me, SPELL_PROTECTIVE_BUBBLE); + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ICHORON_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void DoAction(const int32 param) + { + if (!me->isAlive()) + return; + + switch(param) + { + case ACTION_WATER_ELEMENT_HIT: + me->SetHealth(me->GetHealth() + me->GetMaxHealth() * 0.01); + + if (bIsExploded) + DoExplodeCompleted(); + + bAchievement = false; + break; + case ACTION_WATER_ELEMENT_KILLED: + uint32 damage = (me->GetMaxHealth()*3)/100; + me->SetHealth(me->GetHealth() - damage); + me->LowerPlayerDamageReq(damage); + break; + } + } + + void DespawnWaterElements() + { + m_waterElements.DespawnAll(); + } + + // call when explode shall stop. + // either when "hit" by a bubble, or when there is no bubble left. + void DoExplodeCompleted() + { + bIsExploded = false; + + if (!HealthBelowPct(25)) + { + DoScriptText(SAY_BUBBLE, me); + DoCast(me, SPELL_PROTECTIVE_BUBBLE, true); + } + + me->SetVisibility(VISIBILITY_ON); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + + void MoveInLineOfSight(Unit* /*pWho*/) {} + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded) + { + DoScriptText(SAY_ENRAGE, me); + DoCast(me, SPELL_FRENZY, true); + bIsFrenzy = true; + } + + if (!bIsFrenzy) + { + if (uiBubbleCheckerTimer <= uiDiff) + { + if (!bIsExploded) + { + if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE, 0)) + { + DoScriptText(SAY_SHATTER, me); + DoCast(me, SPELL_WATER_BLAST); + DoCast(me, SPELL_DRAINED); + bIsExploded = true; + me->AttackStop(); + me->SetVisibility(VISIBILITY_OFF); + for (uint8 i = 0; i < 10; i++) + { + int tmp = urand(0, MAX_SPAWN_LOC-1); + me->SummonCreature(NPC_ICHOR_GLOBULE, SpawnLoc[tmp], TEMPSUMMON_CORPSE_DESPAWN); + } + } + } + else + { + bool bIsWaterElementsAlive = false; + if (!m_waterElements.empty()) + { + for (std::list::const_iterator itr = m_waterElements.begin(); itr != m_waterElements.end(); ++itr) + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + if (pTemp->isAlive()) + { + bIsWaterElementsAlive = true; + break; + } + } + + if (!bIsWaterElementsAlive) + DoExplodeCompleted(); + } + uiBubbleCheckerTimer = 1000; + } + else uiBubbleCheckerTimer -= uiDiff; + } + + if (!bIsExploded) + { + if (uiWaterBoltVolleyTimer <= uiDiff) + { + DoCast(me, SPELL_WATER_BOLT_VOLLEY); + uiWaterBoltVolleyTimer = urand(10000, 15000); + } + else uiWaterBoltVolleyTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (bIsExploded) + { + bIsExploded = false; + me->SetVisibility(VISIBILITY_ON); + } + + DespawnWaterElements(); + + if (pInstance) + { + if (IsHeroic() && bAchievement) + pInstance->DoCompleteAchievement(ACHIEVEMENT_DEHYDRATION); + + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->SetSpeed(MOVE_RUN, 0.3f); + pSummoned->GetMotionMaster()->MoveFollow(me, 0, 0); + m_waterElements.push_back(pSummoned->GetGUID()); + } + + + void SummonedCreatureDespawn(Creature *pSummoned) + { + m_waterElements.remove(pSummoned->GetGUID()); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_ichoron(Creature* pCreature) +{ + return new boss_ichoronAI (pCreature); +} + +struct mob_ichor_globuleAI : public ScriptedAI +{ + mob_ichor_globuleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiRangeCheck_Timer; + + void Reset() + { + uiRangeCheck_Timer = 1000; + } + + void AttackStart(Unit* /*pWho*/) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiRangeCheck_Timer < uiDiff) + { + if (pInstance) + { + if (Creature* pIchoron = Unit::GetCreature(*me, pInstance->GetData64(DATA_ICHORON))) + { + if (me->IsWithinDist(pIchoron, 2.0f , false)) + { + if (pIchoron->AI()) + pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT); + me->ForcedDespawn(); + } + } + } + uiRangeCheck_Timer = 1000; + } + else uiRangeCheck_Timer -= uiDiff; + } + + void JustDied(Unit* /*pKiller*/) + { + DoCast(me, SPELL_SPLASH); + if (Creature* pIchoron = Unit::GetCreature(*me, pInstance->GetData64(DATA_ICHORON))) + if (pIchoron->AI()) + pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED); + } +}; + +CreatureAI* GetAI_mob_ichor_globule(Creature* pCreature) +{ + return new mob_ichor_globuleAI (pCreature); +} + +void AddSC_boss_ichoron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ichoron"; + newscript->GetAI = &GetAI_boss_ichoron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ichor_globule"; + newscript->GetAI = &GetAI_mob_ichor_globule; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp new file mode 100644 index 00000000000..d8cd3a4962f --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp @@ -0,0 +1,155 @@ +/* Script Data Start +SDName: Boss lavanthor +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_CAUTERIZING_FLAMES = 59466, //Only in heroic + SPELL_FIREBOLT = 54235, + H_SPELL_FIREBOLT = 59468, + SPELL_FLAME_BREATH = 54282, + H_SPELL_FLAME_BREATH = 59469, + SPELL_LAVA_BURN = 54249, + H_SPELL_LAVA_BURN = 59594 +}; + +struct boss_lavanthorAI : public ScriptedAI +{ + boss_lavanthorAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiFireboltTimer; + uint32 uiFlameBreathTimer; + uint32 uiLavaBurnTimer; + uint32 uiCauterizingFlamesTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiFireboltTimer = 1000; + uiFlameBreathTimer = 5000; + uiLavaBurnTimer = 10000; + uiCauterizingFlamesTimer = 3000; + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_LAVANTHOR_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiFireboltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBOLT); + uiFireboltTimer = urand(5000,13000); + } else uiFireboltTimer -= diff; + + if (uiFlameBreathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAME_BREATH); + uiFlameBreathTimer = urand(10000,15000); + } else uiFlameBreathTimer -= diff; + + if (uiLavaBurnTimer <= diff) + { + DoCast(me->getVictim(), SPELL_LAVA_BURN); + uiLavaBurnTimer = urand(15000,23000); + } + + if (IsHeroic()) + { + if (uiCauterizingFlamesTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CAUTERIZING_FLAMES); + uiCauterizingFlamesTimer = urand(10000,16000); + } else uiCauterizingFlamesTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } +}; + +CreatureAI* GetAI_boss_lavanthor(Creature* pCreature) +{ + return new boss_lavanthorAI (pCreature); +} + +void AddSC_boss_lavanthor() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_lavanthor"; + newscript->GetAI = &GetAI_boss_lavanthor; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp new file mode 100644 index 00000000000..6d283c7bfb4 --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp @@ -0,0 +1,133 @@ +/* Script Data Start +SDName: Boss moragg +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "violet_hold.h" + +//Spells +enum Spells +{ + SPELL_CORROSIVE_SALIVA = 54527, + SPELL_OPTIC_LINK = 54396 +}; + +struct boss_moraggAI : public ScriptedAI +{ + boss_moraggAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiOpticLinkTimer; + uint32 uiCorrosiveSalivaTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiOpticLinkTimer = 10000; + uiCorrosiveSalivaTimer = 5000; + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MORAGG_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiOpticLinkTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_OPTIC_LINK); + uiOpticLinkTimer = 15000; + } else uiOpticLinkTimer -= diff; + + if (uiCorrosiveSalivaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVE_SALIVA); + uiCorrosiveSalivaTimer = 10000; + } else uiCorrosiveSalivaTimer -= diff; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT,13); + } + } + } +}; + +CreatureAI* GetAI_boss_moragg(Creature* pCreature) +{ + return new boss_moraggAI (pCreature); +} + +void AddSC_boss_moragg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_moragg"; + newscript->GetAI = &GetAI_boss_moragg; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp new file mode 100644 index 00000000000..2633705c1b7 --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp @@ -0,0 +1,307 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Boss xevozz +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_ARCANE_BARRAGE_VOLLEY = 54202, + SPELL_ARCANE_BARRAGE_VOLLEY_H = 59483, + SPELL_ARCANE_BUFFET = 54226, + SPELL_ARCANE_BUFFET_H = 59485, + SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102, + SPELL_SUMMON_ETHEREAL_SPHERE_2 = 54137, + SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138, +}; + +enum NPCs +{ + NPC_ETHEREAL_SPHERE = 29271, + //NPC_ETHEREAL_SPHERE2 = 32582, // heroic only? +}; + +enum CreatureSpells +{ + SPELL_ARCANE_POWER = 54160, + H_SPELL_ARCANE_POWER = 59474, + SPELL_SUMMON_PLAYERS = 54164, + SPELL_POWER_BALL_VISUAL = 54141, +}; + +enum Yells +{ + SAY_AGGRO = -1608027, + SAY_SLAY_1 = -1608028, + SAY_SLAY_2 = -1608029, + SAY_SLAY_3 = -1608030, + SAY_DEATH = -1608031, + SAY_SPAWN = -1608032, + SAY_CHARGED = -1608033, + SAY_REPEAT_SUMMON_1 = -1608034, + SAY_REPEAT_SUMMON_2 = -1608035, + SAY_SUMMON_ENERGY = -1608036 +}; + +struct boss_xevozzAI : public ScriptedAI +{ + boss_xevozzAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiSummonEtherealSphere_Timer; + uint32 uiArcaneBarrageVolley_Timer; + uint32 uiArcaneBuffet_Timer; + + void Reset() + { + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + + uiSummonEtherealSphere_Timer = urand(10000, 12000); + uiArcaneBarrageVolley_Timer = urand(20000, 22000); + uiArcaneBuffet_Timer = uiSummonEtherealSphere_Timer + urand(5000, 6000); + DespawnSphere(); + } + + void DespawnSphere() + { + std::list assistList; + GetCreatureListWithEntryInGrid(assistList,me, NPC_ETHEREAL_SPHERE ,150.0f); + + if (assistList.empty()) + return; + + for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + { + if (Creature* pSphere = *iter) + pSphere->Kill(pSphere, false); + } + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->SetSpeed(MOVE_RUN, 0.5f); + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + pSummoned->AddThreat(pTarget, 0.00f); + pSummoned->AI()->AttackStart(pTarget); + } + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_XEVOZZ_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void MoveInLineOfSight(Unit* /*pWho*/) {} + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiArcaneBarrageVolley_Timer < uiDiff) + { + DoCast(me, SPELL_ARCANE_BARRAGE_VOLLEY); + uiArcaneBarrageVolley_Timer = urand(20000, 22000); + } + else uiArcaneBarrageVolley_Timer -= uiDiff; + + if (uiArcaneBuffet_Timer) + if (uiArcaneBuffet_Timer < uiDiff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BUFFET); + uiArcaneBuffet_Timer = 0; + } + else uiArcaneBuffet_Timer -= uiDiff; + + if (uiSummonEtherealSphere_Timer < uiDiff) + { + DoScriptText(SAY_SPAWN, me); + DoCast(me, SPELL_SUMMON_ETHEREAL_SPHERE_1); + if (IsHeroic()) // extra one for heroic + me->SummonCreature(NPC_ETHEREAL_SPHERE, me->GetPositionX()-5+rand()%10, me->GetPositionY()-5+rand()%10, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 40000); + + uiSummonEtherealSphere_Timer = urand(45000, 47000); + uiArcaneBuffet_Timer = urand(5000, 6000); + } + else uiSummonEtherealSphere_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + DespawnSphere(); + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } + void KilledUnit(Unit* pVictim) + { + if (pVictim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_xevozz(Creature* pCreature) +{ + return new boss_xevozzAI (pCreature); +} + +struct mob_ethereal_sphereAI : public ScriptedAI +{ + mob_ethereal_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiSummonPlayers_Timer; + uint32 uiRangeCheck_Timer; + + void Reset() + { + uiSummonPlayers_Timer = urand(33000, 35000); + uiRangeCheck_Timer = 1000; + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!me->HasAura(SPELL_POWER_BALL_VISUAL)) + DoCast(me, SPELL_POWER_BALL_VISUAL); + + if (uiRangeCheck_Timer < uiDiff) + { + if (pInstance) + { + if (Creature* pXevozz = Unit::GetCreature(*me, pInstance->GetData64(DATA_XEVOZZ))) + { + float fDistance = me->GetDistance2d(pXevozz); + if (fDistance <= 3) + DoCast(pXevozz, SPELL_ARCANE_POWER); + else + DoCast(me, 35845); //Is it blizzlike? + } + } + uiRangeCheck_Timer = 1000; + } + else uiRangeCheck_Timer -= uiDiff; + + if (uiSummonPlayers_Timer < uiDiff) + { + DoCast(me, SPELL_SUMMON_PLAYERS); // not working right + + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->isAlive()) + DoTeleportPlayer(i->getSource(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), i->getSource()->GetOrientation()); + } + + uiSummonPlayers_Timer = urand(33000, 35000); + } + else uiSummonPlayers_Timer -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_ethereal_sphere(Creature* pCreature) +{ + return new mob_ethereal_sphereAI (pCreature); +} + +void AddSC_boss_xevozz() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_xevozz"; + newscript->GetAI = &GetAI_boss_xevozz; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ethereal_sphere"; + newscript->GetAI = &GetAI_mob_ethereal_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp new file mode 100644 index 00000000000..da75ed94fc2 --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp @@ -0,0 +1,178 @@ +/* Script Data Start +SDName: Boss zuramat +SD%Complete: +SDComment: The phasemask for the voids dosen't work. +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "violet_hold.h" + +enum Spells +{ + SPELL_SHROUD_OF_DARKNESS = 54524, + H_SPELL_SHROUD_OF_DARKNESS = 59745, + SPELL_SUMMON_VOID_SENTRY = 54369, + SPELL_VOID_SHIFT = 54361, + H_SPELL_VOID_SHIFT = 59743, + + SPELL_ZURAMAT_ADD_2 = 54342, + H_SPELL_ZURAMAT_ADD_2 = 59747 +}; + +enum ZuramatCreatures +{ + CREATURE_VOID_SENTRY = 29364 +}; + +enum Yells +{ + SAY_AGGRO = -1608037, + SAY_SLAY_1 = -1608038, + SAY_SLAY_2 = -1608039, + SAY_SLAY_3 = -1608040, + SAY_DEATH = -1608041, + SAY_SPAWN = -1608042, + SAY_SHIELD = -1608043, + SAY_WHISPER = -1608044 +}; + +struct boss_zuramatAI : public ScriptedAI +{ + boss_zuramatAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 SpellVoidShiftTimer; + uint32 SpellSummonVoidTimer; + uint32 SpellShroudOfDarknessTimer; + + void Reset() + { + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + } + + SpellShroudOfDarknessTimer = 22000; + SpellVoidShiftTimer = 15000; + SpellSummonVoidTimer = 12000; + } + + void AttackStart(Unit* pWho) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + DoStartMovement(pWho); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ZURAMAT_CELL))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + } + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (SpellSummonVoidTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SUMMON_VOID_SENTRY, false); + SpellSummonVoidTimer = 20000; + } else SpellSummonVoidTimer -=diff; + + if (SpellVoidShiftTimer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_VOID_SHIFT); + SpellVoidShiftTimer = 20000; + } else SpellVoidShiftTimer -=diff; + + if (SpellShroudOfDarknessTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHROUD_OF_DARKNESS); + SpellShroudOfDarknessTimer = 20000; + } else SpellShroudOfDarknessTimer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (pInstance->GetData(DATA_WAVE_COUNT) == 6) + { + pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 7); + } + else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) + { + pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); + pInstance->SetData(DATA_WAVE_COUNT, 13); + } + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustSummoned(Creature* summon) + { + summon->AI()->AttackStart(me->getVictim()); + summon->AI()->DoCastAOE(SPELL_ZURAMAT_ADD_2); + summon->SetPhaseMask(17,true); + } +}; + +CreatureAI* GetAI_boss_zuramat(Creature* pCreature) +{ + return new boss_zuramatAI (pCreature); +} + +void AddSC_boss_zuramat() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_zuramat"; + newscript->GetAI = &GetAI_boss_zuramat; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp new file mode 100644 index 00000000000..781511f940b --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp @@ -0,0 +1,528 @@ +#include "ScriptedPch.h" +#include "violet_hold.h" + +#define MAX_ENCOUNTER 3 + +/* Violet Hold encounters: +0 - First boss +1 - Second boss +2 - Cyanigosa*/ + +/* Violet hold bosses: +1 - Moragg +2 - Erekem +3 - Ichoron +4 - Lavanthor +5 - Xevozz +6 - Zuramat +7 - Cyanigosa */ + +enum GameObjects +{ + GO_MAIN_DOOR = 191723, + GO_XEVOZZ_DOOR = 191556, + GO_LAVANTHOR_DOOR = 191566, + GO_ICHORON_DOOR = 191722, + GO_ZURAMAT_DOOR = 191565, + GO_EREKEM_DOOR = 191564, + GO_EREKEM_GUARD_1_DOOR = 191563, + GO_EREKEM_GUARD_2_DOOR = 191562, + GO_MORAGG_DOOR = 191606, + GO_INTRO_ACTIVATION_CRYSTAL = 193615, + GO_ACTIVATION_CRYSTAL = 193611 +}; + +const Position PortalLocation[] = +{ + {1936.07, 803.198, 53.3749, 3.12414}, + {1877.51, 850.104, 44.6599, 4.7822 }, + {1890.64, 753.471, 48.7224, 1.71042}, + {1908.31, 809.657, 38.7037, 3.08701}, + {1918.37, 853.437, 47.1624, 4.12294}, + {1927.61, 758.436, 51.4533, 2.20891} +}; + +struct instance_violet_hold : public ScriptedInstance +{ + instance_violet_hold(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiMoragg; + uint64 uiErekem; + uint64 uiErekemGuard[2]; + uint64 uiIchoron; + uint64 uiLavanthor; + uint64 uiXevozz; + uint64 uiZuramat; + uint64 uiCyanigosa; + uint64 uiSinclari; + + uint64 uiMoraggCell; + uint64 uiErekemCell; + uint64 uiErekemLeftGuardCell; + uint64 uiErekemRightGuardCell; + uint64 uiIchoronCell; + uint64 uiLavanthorCell; + uint64 uiXevozzCell; + uint64 uiZuramatCell; + uint64 uiMainDoor; + + uint64 uiActivationCrystal[3]; + + uint32 uiActivationTimer; + + uint8 uiWaveCount; + uint8 uiLocation; + uint8 uiFirstBoss; + uint8 uiSecondBoss; + uint8 uiRemoveNpc; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + uint8 uiCountErekemGuards; + uint8 uiCountActivationCrystals; + + bool bActive; + bool bWiped; + + std::string str_data; + + void Initialize() + { + uiMoragg = 0; + uiErekem = 0; + uiIchoron = 0; + uiLavanthor = 0; + uiXevozz = 0; + uiZuramat = 0; + uiCyanigosa = 0; + uiSinclari = 0; + + uiMoraggCell = 0; + uiErekemCell = 0; + uiErekemGuard[0] = 0; + uiErekemGuard[1] = 0; + uiIchoronCell = 0; + uiLavanthorCell = 0; + uiXevozzCell = 0; + uiZuramatCell = 0; + uiMainDoor = 0; + uiRemoveNpc = 0; + + uiWaveCount = 0; + uiLocation = urand(0,5); + uiFirstBoss = 0; + uiSecondBoss = 0; + uiCountErekemGuards = 0; + uiCountActivationCrystals = 0; + + uiActivationTimer = 5000; + + bActive = false; + bWiped = false; + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + switch(pCreature->GetEntry()) + { + case CREATURE_XEVOZZ: + uiXevozz = pCreature->GetGUID(); + break; + case CREATURE_LAVANTHOR: + uiLavanthor = pCreature->GetGUID(); + break; + case CREATURE_ICHORON: + uiIchoron = pCreature->GetGUID(); + break; + case CREATURE_ZURAMAT: + uiZuramat = pCreature->GetGUID(); + break; + case CREATURE_EREKEM: + uiErekem = pCreature->GetGUID(); + break; + case CREATURE_EREKEM_GUARD: + if (uiCountErekemGuards < 2) + { + uiErekemGuard[uiCountErekemGuards++] = pCreature->GetGUID(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + } + break; + case CREATURE_MORAGG: + uiMoragg = pCreature->GetGUID(); + break; + case CREATURE_CYANIGOSA: + uiCyanigosa = pCreature->GetGUID(); + break; + case CREATURE_SINCLARI: + uiSinclari = pCreature->GetGUID(); + break; + } + + if (add && (pCreature->GetGUID() == uiFirstBoss || pCreature->GetGUID() == uiSecondBoss)) + { + pCreature->AllLootRemovedFromCorpse(); + pCreature->RemoveLootMode(1); + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_EREKEM_GUARD_1_DOOR: + uiErekemLeftGuardCell = pGo->GetGUID(); + break; + case GO_EREKEM_GUARD_2_DOOR: + uiErekemRightGuardCell = pGo->GetGUID(); + break; + case GO_EREKEM_DOOR: + uiErekemCell = pGo->GetGUID(); + break; + case GO_ZURAMAT_DOOR: + uiZuramatCell = pGo->GetGUID(); + break; + case GO_LAVANTHOR_DOOR: + uiLavanthorCell = pGo->GetGUID(); + break; + case GO_MORAGG_DOOR: + uiMoraggCell = pGo->GetGUID(); + break; + case GO_ICHORON_DOOR: + uiIchoronCell = pGo->GetGUID(); + break; + case GO_XEVOZZ_DOOR: + uiXevozzCell = pGo->GetGUID(); + break; + case GO_MAIN_DOOR: + uiMainDoor = pGo->GetGUID(); + break; + case GO_ACTIVATION_CRYSTAL: + if (uiCountActivationCrystals < 3) + uiActivationCrystal[uiCountActivationCrystals++] = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_1ST_BOSS_EVENT: + m_auiEncounter[0] = data; + if (data == DONE) + SaveToDB(); + break; + case DATA_2ND_BOSS_EVENT: + m_auiEncounter[1] = data; + if (data == DONE) + SaveToDB(); + break; + case DATA_CYANIGOSA_EVENT: + m_auiEncounter[2] = data; + if (data == DONE) + { + SaveToDB(); + if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) + pMainDoor->SetGoState(GO_STATE_ACTIVE); + } + break; + case DATA_WAVE_COUNT: + uiWaveCount = data; + bActive = true; + break; + case DATA_REMOVE_NPC: + uiRemoveNpc = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_1ST_BOSS_EVENT: return m_auiEncounter[0]; + case DATA_2ND_BOSS_EVENT: return m_auiEncounter[1]; + case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2]; + case DATA_WAVE_COUNT: return uiWaveCount; + case DATA_REMOVE_NPC: return uiRemoveNpc; + } + + return 0; + } + + void SpawnPortal() + { + if (Creature *pSinclari = instance->GetCreature(uiSinclari)) + if (Creature *pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL,PortalLocation[uiLocation],TEMPSUMMON_CORPSE_DESPAWN)) + uiLocation = (uiLocation+urand(1,5))%6; + } + + void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true) + { + Creature* pBoss = NULL; + + switch(uiBoss) + { + case BOSS_MORAGG: + HandleGameObject(uiMoraggCell,bForceRespawn); + pBoss = instance->GetCreature(uiMoragg); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + case BOSS_EREKEM: + HandleGameObject(uiErekemCell, bForceRespawn); + HandleGameObject(uiErekemRightGuardCell, bForceRespawn); + HandleGameObject(uiErekemLeftGuardCell, bForceRespawn); + + pBoss = instance->GetCreature(uiErekem); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + + if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0])) + { + if (bForceRespawn) + pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + else + pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + } + + if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1])) + { + if (bForceRespawn) + pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + else + pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + } + break; + case BOSS_ICHORON: + HandleGameObject(uiIchoronCell,bForceRespawn); + pBoss = instance->GetCreature(uiIchoron); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + case BOSS_LAVANTHOR: + HandleGameObject(uiLavanthorCell,bForceRespawn); + pBoss = instance->GetCreature(uiLavanthor); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + case BOSS_XEVOZZ: + HandleGameObject(uiXevozzCell,bForceRespawn); + pBoss = instance->GetCreature(uiXevozz); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + case BOSS_ZURAMAT: + HandleGameObject(uiZuramatCell,bForceRespawn); + pBoss = instance->GetCreature(uiZuramat); + if (pBoss) + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + break; + } + + if (!bForceRespawn && pBoss) + { + if (pBoss->isDead()) + { + // respawn but avoid to be looted again + pBoss->Respawn(); + pBoss->RemoveLootMode(1); + } + pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); + SetData(DATA_WAVE_COUNT,0); + uiWaveCount = 0; + } + } + + void AddWave() + { + DoUpdateWorldState(WORLD_STATE_VH, 1); + DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, uiWaveCount); + DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); // TODO + + switch(uiWaveCount) + { + case 6: + if (uiFirstBoss == 0) + uiFirstBoss = urand(1,6); + StartBossEncounter(uiFirstBoss); + break; + case 12: + if (uiSecondBoss == 0) + do + { + uiSecondBoss = urand(1,6); + } while (uiSecondBoss == uiFirstBoss); + StartBossEncounter(uiSecondBoss); + break; + case 18: + { + Creature *pSinclari = instance->GetCreature(uiSinclari); + if (pSinclari) + pSinclari->SummonCreature(CREATURE_CYANIGOSA,PortalLocation[0],TEMPSUMMON_DEAD_DESPAWN); + break; + } + case 1: + { + if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) + pMainDoor->SetGoState(GO_STATE_READY); + } + default: + if (!bWiped) + SpawnPortal(); + bWiped = false; + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MORAGG: return uiMoragg; + case DATA_EREKEM: return uiErekem; + case DATA_EREKEM_GUARD_1: return uiErekemGuard[0]; + case DATA_EREKEM_GUARD_2: return uiErekemGuard[1]; + case DATA_ICHORON: return uiIchoron; + case DATA_LAVANTHOR: return uiLavanthor; + case DATA_XEVOZZ: return uiXevozz; + case DATA_ZURAMAT: return uiZuramat; + case DATA_CYANIGOSA: return uiCyanigosa; + case DATA_MORAGG_CELL: return uiMoraggCell; + case DATA_EREKEM_CELL: return uiErekemCell; + case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell; + case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell; + case DATA_ICHORON_CELL: return uiIchoronCell; + case DATA_LAVANTHOR_CELL: return uiLavanthorCell; + case DATA_XEVOZZ_CELL: return uiXevozzCell; + case DATA_ZURAMAT_CELL: return uiZuramatCell; + case DATA_MAIN_DOOR: return uiMainDoor; + case DATA_SINCLARI: return uiSinclari; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "V H " << (uint16)m_auiEncounter[0] + << " " << (uint16)m_auiEncounter[1] + << " " << (uint16)m_auiEncounter[2] + << " " << (uint16)uiFirstBoss + << " " << (uint16)uiSecondBoss; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; + + if (dataHead1 == 'V' && dataHead2 == 'H') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + uiFirstBoss = data3; + uiSecondBoss = data4; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + bool CheckWipe() + { + Map::PlayerList const &players = instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + return false; + } + + return true; + } + + void Update(uint32 diff) + { + if (!instance->HavePlayers()) + return; + + if (bActive) + { + if (uiActivationTimer < diff) + { + AddWave(); + bActive = false; + uiActivationTimer = 5000; + } else uiActivationTimer -= diff; + } + + if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) + if (pMainDoor->GetGoState() != GO_STATE_ACTIVE && CheckWipe()) + { + SetData(DATA_REMOVE_NPC, 1); + StartBossEncounter(uiFirstBoss, false); + StartBossEncounter(uiSecondBoss, false); + bWiped = true; + if (Creature* pSinclari = instance->GetCreature(uiSinclari)) + { + pSinclari->DisappearAndDie(); + pSinclari->Respawn(true); + } + + if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) + pMainDoor->SetGoState(GO_STATE_ACTIVE); + SetData(DATA_WAVE_COUNT, 0); + } + } +}; + +InstanceData* GetInstanceData_instance_violet_hold(Map* pMap) +{ + return new instance_violet_hold(pMap); +} + +void AddSC_instance_violet_hold() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_violet_hold"; + newscript->GetInstanceData = &GetInstanceData_instance_violet_hold; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp new file mode 100644 index 00000000000..49883b5dbf3 --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -0,0 +1,274 @@ +#include "ScriptedPch.h" +#include "violet_hold.h" + +#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay." +#define GOSSIP_ITEM_1 "Activate the crystals when we get in trouble, right" +#define SPAWN_TIME 20000 + +enum PortalCreatures +{ + CREATURE_AZURE_INVADER = 30661, + CREATURE_AZURE_SPELLBREAKER = 30662, + CREATURE_AZURE_BINDER = 30663, + CREATURE_AZURE_MAGE_SLAYER = 30664, + CREATURE_AZURE_CAPTAIN = 30666, + CREATURE_AZURE_SORCEROR = 30667, + CREATURE_AZURE_RAIDER = 30668, + CREATURE_AZURE_STALKER = 32191 +}; + +enum Spells +{ + SPELL_PORTAL_CHANNEL = 58012 +}; + +enum eSinclari +{ + NPC_VIOLET_HOLD_GUARD = 30659, + + SAY_SINCLARI_1 = -1608045, +}; + +const Position DoorPosition = { 1828.300049, 797.309021, 46.135502, 1.48353}; +const Position MovePosition = { 1806.955566, 803.851807, 44.363323}; + +struct npc_sinclariAI : public ScriptedAI +{ + npc_sinclariAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiTimer; + + void Reset() + { + uiPhase = 0; + uiTimer = 0; + + me->SetVisibility(VISIBILITY_ON); + me->SetReactState(REACT_AGGRESSIVE); + + std::list GuardList; + me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); + if (!GuardList.empty()) + { + for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + { + if (Creature* pGuard = *itr) + { + pGuard->DisappearAndDie(); + pGuard->Respawn(); + pGuard->SetVisibility(VISIBILITY_ON); + pGuard->SetReactState(REACT_AGGRESSIVE); + } + } + } + } + + void MovementInform(uint32 uiType, uint32 /*uiId*/) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (pInstance) + { + pInstance->SetData(DATA_WAVE_COUNT,1); + pInstance->SetData(DATA_REMOVE_NPC,0); // might not have been reset after a wipe on a boss. + } + + //She should not be despawned, she will be used by the instance to summon some npcs + me->SetVisibility(VISIBILITY_OFF); + me->SetReactState(REACT_PASSIVE); + } + + void UpdateAI(const uint32 uiDiff) + { + ScriptedAI::UpdateAI(uiDiff); + + if (uiPhase) + { + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + DoScriptText(SAY_SINCLARI_1, me); + uiTimer = 4000; + uiPhase = 2; + break; + case 2: + { + std::list GuardList; + me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); + if (!GuardList.empty()) + for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + { + if (Creature* pGuard = *itr) + { + pGuard->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pGuard->GetMotionMaster()->MovePoint(0, MovePosition); + } + } + uiTimer = 6000; + uiPhase = 3; + break; + } + case 3: + { + std::list GuardList; + me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); + if (!GuardList.empty()) + for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + { + if (Creature* pGuard = *itr) + { + pGuard->SetVisibility(VISIBILITY_OFF); + pGuard->SetReactState(REACT_PASSIVE); + } + } + uiTimer = 2000; + uiPhase = 4; + break; + } + case 4: + me->GetMotionMaster()->MovePoint(0, MovePosition); + uiTimer = 0; + uiPhase = 0; + break; + } + } + else uiTimer -= uiDiff; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_sinclari(Creature* pCreature) +{ + return new npc_sinclariAI(pCreature); +} + +bool GossipHello_npc_sinclari(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance && pInstance->GetData(DATA_CYANIGOSA_EVENT) != DONE && pInstance->GetData(DATA_WAVE_COUNT) == 0 && pPlayer) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_1,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_START_EVENT,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(13853, pCreature->GetGUID()); + }else + pPlayer->SEND_GOSSIP_MENU(13910, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_sinclari(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + if (pPlayer) + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_sinclariAI, (pCreature->AI()))->uiPhase = 1; + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->SEND_GOSSIP_MENU(13854, pCreature->GetGUID()); + break; + } + return true; +} + +struct npc_teleportation_portalAI : public ScriptedAI +{ + npc_teleportation_portalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiSpawnTimer; + bool bPortalGuardianOrKeeperSpawn; + + ScriptedInstance *pInstance; + + void Reset() + { + uiSpawnTimer = 10000; + bPortalGuardianOrKeeperSpawn = false; + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (pInstance && pInstance->GetData(DATA_REMOVE_NPC) == 1) + { + me->ForcedDespawn(); + pInstance->SetData(DATA_REMOVE_NPC, 0); + } + + if (uiSpawnTimer <= diff) + { + if (bPortalGuardianOrKeeperSpawn) + { + uint8 k = pInstance->GetData(DATA_WAVE_COUNT) < 12 ? 2 : 3; + for (uint8 i = 0; i < k; ++i) + { + uint32 entry = RAND(CREATURE_AZURE_CAPTAIN,CREATURE_AZURE_RAIDER,CREATURE_AZURE_STALKER,CREATURE_AZURE_SORCEROR); + if (Creature* pSummon = DoSummon(entry, me, 2.0f, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) + pSummon->GetMotionMaster()->MovePoint(0, DoorPosition); + } + } + else + { + bPortalGuardianOrKeeperSpawn = true; + uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER); + if (Creature *pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) + me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false); + } + uiSpawnTimer = SPAWN_TIME; + } else uiSpawnTimer -= diff; + + if (bPortalGuardianOrKeeperSpawn && !me->IsNonMeleeSpellCasted(false)) + { + me->Kill(me, false); + me->RemoveCorpse(); + return; + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_WAVE_COUNT,pInstance->GetData(DATA_WAVE_COUNT)+1); + } +}; + +CreatureAI* GetAI_npc_teleportation_portal(Creature *pCreature) +{ + return new npc_teleportation_portalAI(pCreature); +} + +void AddSC_violet_hold() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sinclari_vh"; + newscript->GetAI = &GetAI_npc_sinclari; + newscript->pGossipHello = &GossipHello_npc_sinclari; + newscript->pGossipSelect = &GossipSelect_npc_sinclari; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_teleportation_portal_vh"; + newscript->GetAI = &GetAI_npc_teleportation_portal; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.h b/src/server/scripts/Northrend/VioletHold/violet_hold.h new file mode 100644 index 00000000000..4476d5e823a --- /dev/null +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.h @@ -0,0 +1,71 @@ +#ifndef DEF_VIOLET_HOLD_H +#define DEF_VIOLET_HOLD_H + +enum Creatures +{ + CREATURE_TELEPORTATION_PORTAL = 31011, + CREATURE_PORTAL_GUARDIAN = 30660, + CREATURE_PORTAL_KEEPER = 30695, + CREATURE_XEVOZZ = 29266, + CREATURE_LAVANTHOR = 29312, + CREATURE_ICHORON = 29313, + CREATURE_ZURAMAT = 29314, + CREATURE_EREKEM = 29315, + CREATURE_EREKEM_GUARD = 29395, + CREATURE_MORAGG = 29316, + CREATURE_CYANIGOSA = 31134, + CREATURE_SINCLARI = 30658 +}; + +enum Data +{ + DATA_1ST_BOSS_EVENT, + DATA_2ND_BOSS_EVENT, + DATA_CYANIGOSA_EVENT, + DATA_WAVE_COUNT, + DATA_REMOVE_NPC +}; + +enum Data64 +{ + DATA_MORAGG, + DATA_EREKEM, + DATA_EREKEM_GUARD_1, + DATA_EREKEM_GUARD_2, + DATA_ICHORON, + DATA_LAVANTHOR, + DATA_XEVOZZ, + DATA_ZURAMAT, + DATA_CYANIGOSA, + DATA_MORAGG_CELL, + DATA_EREKEM_CELL, + DATA_EREKEM_LEFT_GUARD_CELL, + DATA_EREKEM_RIGHT_GUARD_CELL, + DATA_ICHORON_CELL, + DATA_LAVANTHOR_CELL, + DATA_XEVOZZ_CELL, + DATA_ZURAMAT_CELL, + DATA_MAIN_DOOR, + DATA_SINCLARI +}; + +enum Bosses +{ + BOSS_NONE, // 0 used as marker for not yet randomized + BOSS_MORAGG, + BOSS_EREKEM, + BOSS_ICHORON, + BOSS_LAVANTHOR, + BOSS_XEVOZZ, + BOSS_ZURAMAT, + BOSS_CYANIGOSA +}; + +enum VHWorldStates +{ + WORLD_STATE_VH = 3816, + WORLD_STATE_VH_PRISON_STATE = 3815, + WORLD_STATE_VH_WAVE_COUNT = 3810, +}; + +#endif diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h deleted file mode 100644 index 240ad77c74d..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/ahnkahet.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_AHNKAHET_H -#define DEF_AHNKAHET_H - -enum Data64 -{ - DATA_ELDER_NADOX, - DATA_PRINCE_TALDARAM, - DATA_JEDOGA_SHADOWSEEKER, - DATA_HERALD_VOLAZJ, - DATA_AMANITAR, - DATA_SPHERE1, - DATA_SPHERE2, - DATA_PRINCE_TALDARAM_PLATFORM, - DATA_PL_JEDOGA_TARGET, - DATA_ADD_JEDOGA_OPFER, - DATA_ADD_JEDOGA_INITIAND -}; - -enum Data -{ - DATA_ELDER_NADOX_EVENT, - DATA_PRINCE_TALDARAM_EVENT, - DATA_JEDOGA_SHADOWSEEKER_EVENT, - DATA_HERALD_VOLAZJ_EVENT, - DATA_AMANITAR_EVENT, - DATA_SPHERE1_EVENT, - DATA_SPHERE2_EVENT, - DATA_JEDOGA_TRIGGER_SWITCH, - DATA_JEDOGA_RESET_INITIANDS, - DATA_INITIAND_KILLED, - DATA_ALL_INITIAND_DEAD -}; - -#endif diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp deleted file mode 100644 index 51c4bce0c2d..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Comment: Find correct mushrooms spell to make them visible - buffs of the mushrooms not ever applied to the users... - */ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -enum Spells -{ - SPELL_BASH = 57094, // Victim - SPELL_ENTANGLING_ROOTS = 57095, // Random Victim 100Y - SPELL_MINI = 57055, // Self - SPELL_VENOM_BOLT_VOLLEY = 57088, // Random Victim 100Y - SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS = 56648, // Killer 3Y - SPELL_POISONOUS_MUSHROOM_POISON_CLOUD = 57061, // Self - Duration 8 Sec - SPELL_POISONOUS_MUSHROOM_VISUAL_AREA = 61566, // Self - SPELL_POISONOUS_MUSHROOM_VISUAL_AURA = 56741, // Self - SPELL_PUTRID_MUSHROOM = 31690, // To make the mushrooms visible -}; - -enum Creatures -{ - NPC_HEALTHY_MUSHROOM = 30391, - NPC_POISONOUS_MUSHROOM = 30435 -}; - -struct boss_amanitarAI : public ScriptedAI -{ - boss_amanitarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - bFirstTime = true; - } - - ScriptedInstance* pInstance; - - uint32 uiRootTimer; - uint32 uiBashTimer; - uint32 uiBoltTimer; - uint32 uiSpawnTimer; - - bool bFirstTime; - - void Reset() - { - uiRootTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); - uiBashTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); - uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - uiSpawnTimer = 0; - - me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - - if (pInstance) - { - pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); - if (!bFirstTime) - pInstance->SetData(DATA_AMANITAR_EVENT, FAIL); - else - bFirstTime = false; - } - } - - void JustDied(Unit * /*Killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_AMANITAR_EVENT, DONE); - pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_AMANITAR_EVENT, IN_PROGRESS); - - DoCast(me, SPELL_MINI, false); - } - - void SpawnAdds() - { - for (uint8 i = 0; i < 30; ++i) - { - Unit* victim = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (victim) - { - Position pos; - victim->GetPosition(&pos); - me->GetRandomNearPosition(pos, float(urand(5,80))); - me->SummonCreature(NPC_POISONOUS_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILISECONDS); - me->GetRandomNearPosition(pos, float(urand(5,80))); - me->SummonCreature(NPC_HEALTHY_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30*IN_MILISECONDS); - } - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiSpawnTimer <= diff) - { - SpawnAdds(); - uiSpawnTimer = urand(35*IN_MILISECONDS,40*IN_MILISECONDS); - } else uiSpawnTimer -= diff; - - if (uiRootTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ENTANGLING_ROOTS); - uiRootTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiRootTimer -= diff; - - if (uiBashTimer <= diff) - { - DoCastVictim(SPELL_BASH); - uiBashTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiBashTimer -= diff; - - if (uiBoltTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_VENOM_BOLT_VOLLEY); - uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_amanitar_mushroomsAI : public Scripted_NoMovementAI -{ - mob_amanitar_mushroomsAI(Creature* c) : Scripted_NoMovementAI(c) {} - - uint32 uiAuraTimer; - uint32 uiDeathTimer; - - void Reset() - { - DoCast(me, SPELL_PUTRID_MUSHROOM, true); // Hack, to make the mushrooms visible, can't find orig. spell... - - if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) - DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AURA, true); - - uiAuraTimer = 0; - uiDeathTimer = 30*IN_MILISECONDS; - } - - void JustDied(Unit *killer) - { - if (!killer) - return; - - if (me->GetEntry() == NPC_HEALTHY_MUSHROOM && killer->GetTypeId() == TYPEID_PLAYER) - { - me->InterruptNonMeleeSpells(false); - DoCast(killer, SPELL_HEALTHY_MUSHROOM_POTENT_FUNGUS, false); - } - } - - void EnterCombat(Unit * /*who*/) {} - void AttackStart(Unit * /*victim*/) {} - - void UpdateAI(const uint32 diff) - { - if (me->GetEntry() == NPC_POISONOUS_MUSHROOM) - { - if (uiAuraTimer <= diff) - { - DoCast(me, SPELL_POISONOUS_MUSHROOM_VISUAL_AREA, true); - DoCast(me, SPELL_POISONOUS_MUSHROOM_POISON_CLOUD, false); - uiAuraTimer = 7*IN_MILISECONDS; - } else uiAuraTimer -= diff; - } - if (uiDeathTimer <= diff) - me->DisappearAndDie(); - else uiDeathTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_amanitar(Creature* pCreature) -{ - return new boss_amanitarAI (pCreature); -} - -CreatureAI* GetAI_mob_amanitar_mushrooms(Creature *pCreature) -{ - return new mob_amanitar_mushroomsAI (pCreature); -} - -void AddSC_boss_amanitar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_amanitar"; - newscript->GetAI = &GetAI_boss_amanitar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_amanitar_mushrooms"; - newscript->GetAI = &GetAI_mob_amanitar_mushrooms; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp deleted file mode 100644 index 2215d91c749..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -bool DeadAhnkaharGuardian; // needed for achievement: Respect Your Elders(2038) - -enum Achievements -{ - ACHIEV_RESPECT_YOUR_ELDERS = 2038 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1619014, - SAY_SLAY_1 = -1619015, - SAY_SLAY_2 = -1619016, - SAY_SLAY_3 = -1619017, - SAY_DEATH = -1619018, - SAY_EGG_SAC_1 = -1619019, - SAY_EGG_SAC_2 = -1619020 -}; - -enum Spells -{ - SPELL_BROOD_PLAGUE = 56130, - H_SPELL_BROOD_PLAGUE = 59467, - H_SPELL_BROOD_RAGE = 59465, - SPELL_ENRAGE = 26662, // Enraged if too far away from home - SPELL_SUMMON_SWARMERS = 56119, //2x 30178 -- 2x every 10secs - SPELL_SUMMON_SWARM_GUARD = 56120, //1x 30176 -- every 25secs -}; - -enum Creatures -{ - MOB_AHNKAHAR_SWARMER = 30178, - MOB_AHNKAHAR_GUARDIAN_ENTRY = 30176 -}; - -#define EMOTE_HATCHES "An Ahn'kahar Guardian hatches!" - -struct boss_elder_nadoxAI : public ScriptedAI -{ - boss_elder_nadoxAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiPlagueTimer; - uint32 uiRagueTimer; - - uint32 uiSwarmerSpawnTimer; - uint32 uiGuardSpawnTimer; - uint32 uiEnragueTimer; - - bool bGuardSpawned; - - ScriptedInstance *pInstance; - - void Reset() - { - uiPlagueTimer = 13*IN_MILISECONDS; - uiRagueTimer = 20*IN_MILISECONDS; - - uiSwarmerSpawnTimer = 10*IN_MILISECONDS; - uiGuardSpawnTimer = 25*IN_MILISECONDS; - - uiEnragueTimer = 5*IN_MILISECONDS; - - DeadAhnkaharGuardian = false; - bGuardSpawned = false; - - if (pInstance) - pInstance->SetData(DATA_ELDER_NADOX_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_DEATH,me); - - if (pInstance) - pInstance->SetData(DATA_ELDER_NADOX_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_SLAY_3,me); //SAY_SLAY_3 on death? - - if (pInstance) - { - pInstance->SetData(DATA_ELDER_NADOX_EVENT, DONE); - if (IsHeroic() && !DeadAhnkaharGuardian) - pInstance->DoCompleteAchievement(ACHIEV_RESPECT_YOUR_ELDERS); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiPlagueTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BROOD_PLAGUE); - uiPlagueTimer = 15*IN_MILISECONDS; - } else uiPlagueTimer -= diff; - - if (IsHeroic()) - if (uiRagueTimer <= diff) - { - if (Creature *pSwarmer = me->FindNearestCreature(MOB_AHNKAHAR_SWARMER, 35)) - { - DoCast(pSwarmer, H_SPELL_BROOD_RAGE, true); - uiRagueTimer = 15*IN_MILISECONDS; - } - } else uiRagueTimer -= diff; - - if (uiSwarmerSpawnTimer <= diff) - { - DoCast(me, SPELL_SUMMON_SWARMERS, true); - DoCast(me, SPELL_SUMMON_SWARMERS); - if (urand(1,3) == 3) // 33% chance of dialog - DoScriptText(RAND(SAY_EGG_SAC_1,SAY_EGG_SAC_2), me); - - uiSwarmerSpawnTimer = 10*IN_MILISECONDS; - } else uiSwarmerSpawnTimer -= diff; - - if (!bGuardSpawned && uiGuardSpawnTimer <= diff) - { - me->MonsterTextEmote(EMOTE_HATCHES,me->GetGUID(),true); - DoCast(me, SPELL_SUMMON_SWARM_GUARD); - bGuardSpawned = true; - } else uiGuardSpawnTimer -= diff; - - if (uiEnragueTimer <= diff) - { - if (me->HasAura(SPELL_ENRAGE,0)) - return; - - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - if (z < 24) - if (!me->IsNonMeleeSpellCasted(false)) - DoCast(me, SPELL_ENRAGE, true); - - uiEnragueTimer = 5*IN_MILISECONDS; - } else uiEnragueTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_elder_nadox(Creature* pCreature) -{ - return new boss_elder_nadoxAI(pCreature); -} - -enum AddSpells -{ - SPELL_SPRINT = 56354, - SPELL_GUARDIAN_AURA = 56151 -}; - -struct mob_ahnkahar_nerubianAI : public ScriptedAI -{ - mob_ahnkahar_nerubianAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 uiSprintTimer; - - void Reset() - { - if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) //magic numbers are bad! - DoCast(me, SPELL_GUARDIAN_AURA, true); - uiSprintTimer = 10*IN_MILISECONDS; - } - - void JustDied(Unit * /*killer*/) - { - if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) - DeadAhnkaharGuardian = true; - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetEntry() == MOB_AHNKAHAR_GUARDIAN_ENTRY) - me->RemoveAurasDueToSpell(SPELL_GUARDIAN_AURA); - - if (pInstance) - { - if (pInstance->GetData(DATA_ELDER_NADOX_EVENT) != IN_PROGRESS) - { - me->DisappearAndDie(); - } - } - - if (!UpdateVictim()) - return; - - if (uiSprintTimer <= diff) - { - DoCast(me, SPELL_SPRINT); - uiSprintTimer = 25*IN_MILISECONDS; - } else uiSprintTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//HACK: No, AI. Replace with proper db content? -struct mob_nadox_eggsAI : public Scripted_NoMovementAI -{ - mob_nadox_eggsAI(Creature* c) : Scripted_NoMovementAI(c) - { - c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - c->UpdateAllStats(); - } - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*victim*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_mob_ahnkahar_nerubian(Creature* pCreature) -{ - return new mob_ahnkahar_nerubianAI(pCreature); -} - -CreatureAI* GetAI_mob_nadox_eggs(Creature* _Creature) -{ - return new mob_nadox_eggsAI(_Creature); -} - -void AddSC_boss_elder_nadox() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_elder_nadox"; - newscript->GetAI = &GetAI_boss_elder_nadox; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ahnkahar_nerubian"; - newscript->GetAI = &GetAI_mob_ahnkahar_nerubian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_nadox_eggs"; - newscript->GetAI = &GetAI_mob_nadox_eggs; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp deleted file mode 100644 index 16c291d6484..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Comment: Missing AI for Twisted Visages - */ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -enum Spells -{ - SPELL_INSANITY = 57496, //Dummy - INSANITY_VISUAL = 57561, - SPELL_INSANITY_TARGET = 57508, - SPELL_MIND_FLAY = 57941, - SPELL_SHADOW_BOLT_VOLLEY = 57942, - SPELL_SHIVER = 57949, - SPELL_CLONE_PLAYER = 57507, //casted on player during insanity - SPELL_INSANITY_PHASING_1 = 57508, - SPELL_INSANITY_PHASING_2 = 57509, - SPELL_INSANITY_PHASING_3 = 57510, - SPELL_INSANITY_PHASING_4 = 57511, - SPELL_INSANITY_PHASING_5 = 57512 -}; - -enum Creatures -{ - MOB_TWISTED_VISAGE = 30625 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1619030, - SAY_SLAY_1 = -1619031, - SAY_SLAY_2 = -1619032, - SAY_SLAY_3 = -1619033, - SAY_DEATH_1 = -1619034, - SAY_DEATH_2 = -1619035, - SAY_PHASE = -1619036 -}; - -enum Achievements -{ - ACHIEV_QUICK_DEMISE_START_EVENT = 20382, -}; - -struct boss_volazjAI : public ScriptedAI -{ - boss_volazjAI(Creature* pCreature) : ScriptedAI(pCreature),Summons(me) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 uiMindFlayTimer; - uint32 uiShadowBoltVolleyTimer; - uint32 uiShiverTimer; - uint32 insanityHandled; - SummonList Summons; - - // returns the percentage of health after taking the given damage. - uint32 GetHealthPct(uint32 damage) - { - if (damage > me->GetHealth()) - return 0; - return 100*(me->GetHealth()-damage)/me->GetMaxHealth(); - } - - void DamageTaken(Unit * /*pAttacker*/, uint32 &damage) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - damage = 0; - - if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)|| - (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33)) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_INSANITY, false); - } - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (spell->Id == SPELL_INSANITY) - { - // Not good target or too many players - if (pTarget->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4) - return; - // First target - start channel visual and set self as unnattackable - if (!insanityHandled) - { - // Channel visual - DoCast(me, INSANITY_VISUAL, true); - // Unattackable - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(true, UNIT_STAT_STUNNED); - } - // phase mask - pTarget->CastSpell(pTarget, SPELL_INSANITY_TARGET+insanityHandled, true); - // summon twisted party members for this target - Map::PlayerList const &players = me->GetMap()->GetPlayers(); - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player *plr = i->getSource(); - if (!plr || !plr->isAlive()) - continue; - // Summon clone - if (Unit *summon = me->SummonCreature(MOB_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,0)) - { - // required for correct visual - // Fixme: allow mirror image query to send other guid to get rid of minion status - summon->SetUInt64Value(UNIT_FIELD_CREATEDBY, plr->GetGUID()); - // clone - plr->CastSpell(summon, SPELL_CLONE_PLAYER, true); - // set phase - summon->SetPhaseMask((1<<(4+insanityHandled)),true); - } - } - ++insanityHandled; - } - } - - void ResetPlayersPhaseMask() - { - Map::PlayerList const &players = me->GetMap()->GetPlayers(); - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player* pPlayer = i->getSource(); - pPlayer->RemoveAurasDueToSpell(GetSpellForPhaseMask(pPlayer->GetPhaseMask())); - } - } - - void Reset() - { - uiMindFlayTimer = 8*IN_MILISECONDS; - uiShadowBoltVolleyTimer = 5*IN_MILISECONDS; - uiShiverTimer = 15*IN_MILISECONDS; - - if (pInstance) - { - pInstance->SetData(DATA_HERALD_VOLAZJ, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - } - - // Visible for all players in insanity - me->SetPhaseMask((1|16|32|64|128|256),true); - // Used for Insanity handling - insanityHandled = 0; - - ResetPlayersPhaseMask(); - - // Cleanup - Summons.DespawnAll(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - { - pInstance->SetData(DATA_HERALD_VOLAZJ, IN_PROGRESS); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); - } - } - - void JustSummoned(Creature *summon) - { - Summons.Summon(summon); - } - - uint32 GetSpellForPhaseMask(uint32 phase) - { - uint32 spell = 0; - switch (phase) - { - case 16: - spell = SPELL_INSANITY_PHASING_1; - break; - case 32: - spell = SPELL_INSANITY_PHASING_2; - break; - case 64: - spell = SPELL_INSANITY_PHASING_3; - break; - case 128: - spell = SPELL_INSANITY_PHASING_4; - break; - case 256: - spell = SPELL_INSANITY_PHASING_5; - break; - } - return spell; - } - - void SummonedCreatureDespawn(Creature *summon) - { - uint32 phase= summon->GetPhaseMask(); - uint32 nextPhase = 0; - Summons.Despawn(summon); - - // Check if all summons in this phase killed - for (SummonList::const_iterator iter = Summons.begin(); iter != Summons.end(); ++iter) - { - if (Creature *visage = Unit::GetCreature(*me, *iter)) - { - // Not all are dead - if (phase == visage->GetPhaseMask()) - return; - else - nextPhase = visage->GetPhaseMask(); - } - } - - // Roll Insanity - uint32 spell = GetSpellForPhaseMask(phase); - uint32 spell2 = GetSpellForPhaseMask(nextPhase); - Map* pMap = me->GetMap(); - if (!pMap) - return; - - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->HasAura(spell)) - { - pPlayer->RemoveAurasDueToSpell(spell); - if (spell2) // if there is still some different mask cast spell for it - pPlayer->CastSpell(pPlayer, spell2, true); - } - } - } - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (insanityHandled) - { - if (!Summons.empty()) - return; - - insanityHandled = 0; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetControlled(false, UNIT_STAT_STUNNED); - me->RemoveAurasDueToSpell(INSANITY_VISUAL); - } - - if (uiMindFlayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MIND_FLAY); - uiMindFlayTimer = 20*IN_MILISECONDS; - } else uiMindFlayTimer -= diff; - - if (uiShadowBoltVolleyTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT_VOLLEY); - uiShadowBoltVolleyTimer = 5*IN_MILISECONDS; - } else uiShadowBoltVolleyTimer -= diff; - - if (uiShiverTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHIVER); - uiShiverTimer = 15*IN_MILISECONDS; - } else uiShiverTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH_1, me); - - if (pInstance) - pInstance->SetData(DATA_HERALD_VOLAZJ, DONE); - - Summons.DespawnAll(); - ResetPlayersPhaseMask(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_volazj(Creature* pCreature) -{ - return new boss_volazjAI (pCreature); -} - -void AddSC_boss_volazj() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_volazj"; - newscript->GetAI = &GetAI_boss_volazj; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp deleted file mode 100644 index eb8046f63cd..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * Comment: Complete - BUT THE TRIGGER NEEDS DATA WHETHER THE PRISON OF TALDARAM IS OFFLINE ! - */ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -enum Yells -{ - TEXT_AGGRO = -1619000, - TEXT_SACRIFICE_1_1 = -1619001, - TEXT_SACRIFICE_1_2 = -1619002, - TEXT_SACRIFICE_2_1 = -1619003, - TEXT_SACRIFICE_2_2 = -1619004, - TEXT_SLAY_1 = -1619005, - TEXT_SLAY_2 = -1619006, - TEXT_SLAY_3 = -1619007, - TEXT_DEATH = -1619008, - TEXT_PREACHING_1 = -1619009, - TEXT_PREACHING_2 = -1619010, - TEXT_PREACHING_3 = -1619011, - TEXT_PREACHING_4 = -1619012, - TEXT_PREACHING_5 = -1619013 -}; - -enum Spells -{ - SPELL_SPHERE_VISUAL = 56075, - SPELL_GIFT_OF_THE_HERALD = 56219, - SPELL_CYCLONE_STRIKE = 56855, // Self - SPELL_CYCLONE_STRIKE_H = 60030, - SPELL_LIGHTNING_BOLT = 56891, // 40Y - SPELL_LIGHTNING_BOLT_H = 60032, // 40Y - SPELL_THUNDERSHOCK = 56926, // 30Y - SPELL_THUNDERSHOCK_H = 60029 // 30Y -}; - -enum Creatures -{ - NPC_JEDOGA_CONTROLLER = 30181 -}; - -const Position JedogaPosition[2] = -{ - {372.330994f, -705.278015f, -0.624178f, 5.427970f}, - {372.330994f, -705.278015f, -16.179716f, 5.427970f} -}; - -struct boss_jedoga_shadowseekerAI : public ScriptedAI -{ - boss_jedoga_shadowseekerAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - bFirstTime = true; - bPreDone = false; - } - - ScriptedInstance* pInstance; - - uint32 uiOpFerTimer; - uint32 uiCycloneTimer; - uint32 uiBoltTimer; - uint32 uiThunderTimer; - - bool bPreDone; - bool bOpFerok; - bool bOnGround; - bool bOpFerokFail; - bool bCanDown; - - bool bFirstTime; - - void Reset() - { - uiOpFerTimer = urand(15*IN_MILISECONDS,20*IN_MILISECONDS); - - uiCycloneTimer = 3*IN_MILISECONDS; - uiBoltTimer = 7*IN_MILISECONDS; - uiThunderTimer = 12*IN_MILISECONDS; - - bOpFerok = false; - bOpFerokFail = false; - bOnGround = false; - bCanDown = false; - - if (pInstance) - { - if (!bFirstTime) - pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, FAIL); - - pInstance->SetData64(DATA_PL_JEDOGA_TARGET, 0); - pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); - pInstance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); - } - MoveUp(); - - bFirstTime = false; - } - - void EnterCombat(Unit* who) - { - if (!pInstance || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) - return; - - DoScriptText(TEXT_AGGRO, me); - me->SetInCombatWithZone(); - pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* who) - { - if (!who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) - return; - - ScriptedAI::AttackStart(who); - } - - void KilledUnit(Unit* Victim) - { - if (!Victim || Victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(RAND(TEXT_SLAY_1, TEXT_SLAY_2, TEXT_SLAY_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(TEXT_DEATH, me); - if (pInstance) - pInstance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, DONE); - } - - void MoveInLineOfSight(Unit* who) - { - if (!pInstance || !who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) - return; - - if (!bPreDone && who->GetTypeId() == TYPEID_PLAYER && me->GetDistance(who) < 100.0f) - { - DoScriptText(RAND(TEXT_PREACHING_1, TEXT_PREACHING_2, TEXT_PREACHING_3, TEXT_PREACHING_4, TEXT_PREACHING_5), me); - bPreDone = true; - } - - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS || !bOnGround) - return; - - if (!me->getVictim() && who->isTargetableForAttack() && me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - if (!me->getVictim()) - { - who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (me->GetMap()->IsDungeon()) - { - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } - } - } - } - - void MoveDown() - { - if (!pInstance) - return; - - bOpFerokFail = false; - - pInstance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 0); - me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); -/* me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); - me->SendMonsterMove(JedogaPosition[1], MOVEFLAG_JUMP, 0); - me->Relocate(JedogaPosition[1][0], JedogaPosition[1][1], JedogaPosition[1][2], JedogaPosition[1][3]); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); -*/ - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - - bOnGround = true; - - if (UpdateVictim()) - { - AttackStart(me->getVictim()); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - else - { - if (Unit* pTarget = Unit::GetUnit(*me, pInstance->GetData64(DATA_PL_JEDOGA_TARGET))) - { - AttackStart(pTarget); - pInstance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) - EnterCombat(pTarget); - } - else if (!me->isInCombat()) - EnterEvadeMode(); - } - } - - void MoveUp() - { - if (!pInstance) - return; - - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - - me->AttackStop(); - me->RemoveAllAuras(); - me->LoadCreaturesAddon(); - me->GetMotionMaster()->MovePoint(0, JedogaPosition[0]); -/* me->SetUnitMovementFlags(MOVEMENTFLAG_JUMPING); - me->SendMonsterMove(JedogaPosition[0][0], JedogaPosition[0][1], JedogaPosition[0][2], 0, MOVEFLAG_JUMP, 0); - me->Relocate(JedogaPosition[0][0], JedogaPosition[0][1], JedogaPosition[0][2], JedogaPosition[0][3]); - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); -*/ - - pInstance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 1); - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) OpferRufen(); - - bOnGround = false; - uiOpFerTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } - - void OpferRufen() - { - if (!pInstance) - return; - - uint64 opfer = pInstance->GetData64(DATA_ADD_JEDOGA_INITIAND); - - if (opfer) - { - DoScriptText(RAND(TEXT_SACRIFICE_1_1, TEXT_SACRIFICE_1_2), me); - pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, opfer); - } else - bCanDown = true; - } - - void Opfern() - { - DoScriptText(RAND(TEXT_SACRIFICE_2_1, TEXT_SACRIFICE_2_2), me); - - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_GIFT_OF_THE_HERALD, false); - - bOpFerok = false; - bCanDown = true; - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && pInstance->GetData(DATA_ALL_INITIAND_DEAD)) - MoveDown(); - - if (bOpFerok && !bOnGround && !bCanDown) Opfern(); - - if (bOpFerokFail && !bOnGround && !bCanDown) - bCanDown = true; - - if (bCanDown) - { - MoveDown(); - bCanDown = false; - } - - if (bOnGround) - { - if (!UpdateVictim()) - return; - - if (uiCycloneTimer <= diff) - { - DoCast(me, SPELL_CYCLONE_STRIKE, false); - uiCycloneTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiCycloneTimer -= diff; - - if (uiBoltTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->CastSpell(pTarget, DUNGEON_MODE(SPELL_LIGHTNING_BOLT, SPELL_LIGHTNING_BOLT_H), false); - - uiBoltTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiBoltTimer -= diff; - - if (uiThunderTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->CastSpell(pTarget, DUNGEON_MODE(SPELL_THUNDERSHOCK, SPELL_THUNDERSHOCK_H), false); - - uiThunderTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiThunderTimer -= diff; - - if (uiOpFerTimer <= diff) - MoveUp(); - else - uiOpFerTimer -= diff; - - DoMeleeAttackIfReady(); - } - } -}; - -struct mob_jedoga_initiandAI : public ScriptedAI -{ - mob_jedoga_initiandAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 bCheckTimer; - - bool bWalking; - - void Reset() - { - if (!pInstance) - return; - - bWalking = false; - bCheckTimer = 2*IN_MILISECONDS; - - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) - { - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - } - else - { - DoCast(me, SPELL_SPHERE_VISUAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - } - } - - void JustDied(Unit* Killer) - { - if (!Killer || !pInstance) return; - - if (bWalking) - { - Creature* boss = me->GetMap()->GetCreature(pInstance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); - if (boss && !CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok) CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = true; - - if (Killer->GetTypeId() == TYPEID_PLAYER) pInstance->SetData(DATA_INITIAND_KILLED, 1); - pInstance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); - - bWalking = false; - } - if (Killer->GetTypeId() == TYPEID_PLAYER) pInstance->SetData64(DATA_PL_JEDOGA_TARGET, Killer->GetGUID()); - } - - void EnterCombat(Unit* who) - { - if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) return; - } - - void AttackStart(Unit* victim) - { - if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !victim) return; - - ScriptedAI::AttackStart(victim); - } - - void MoveInLineOfSight(Unit* who) - { - if ((pInstance && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE || !pInstance) return; - - switch(uiPointId) - { - case 1: - { - Creature* boss = me->GetMap()->GetCreature(pInstance->GetData64(DATA_JEDOGA_SHADOWSEEKER)); - if (boss) - { - CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok = true; - CAST_AI(boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = false; - me->Kill(me); - } - } - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance && bCheckTimer <= diff) - { - if (me->GetGUID() == pInstance->GetData64(DATA_ADD_JEDOGA_OPFER) && !bWalking) - { - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - - float distance = me->GetDistance(JedogaPosition[1]); - - if (distance < 9.0f) - me->SetSpeed(MOVE_WALK, 0.5f, true); - else if (distance < 15.0f) - me->SetSpeed(MOVE_WALK, 0.75f, true); - else if (distance < 20.0f) - me->SetSpeed(MOVE_WALK, 1.0f, true); - - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); - bWalking = true; - } - if (!bWalking) - { - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && me->HasAura(SPELL_SPHERE_VISUAL)) - { - me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - } - if (pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS && !me->HasAura(SPELL_SPHERE_VISUAL)) - { - DoCast(me, SPELL_SPHERE_VISUAL, false); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); - } - } - bCheckTimer = 2*IN_MILISECONDS; - } else bCheckTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -// ------------------------------------------------------------------------------------------------------------ -// Jedogas Aufseher - Entry: 30181 -// ------------------------------------------------------------------------------------------------------------ -enum AufseherSpell -{ - SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1 = 60342, - SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2 = 56312 -}; - -struct npc_jedogas_aufseher_triggerAI : public Scripted_NoMovementAI -{ - npc_jedogas_aufseher_triggerAI(Creature* c) : Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); -// c->SetUInt32Value(UNIT_FIELD_DISPLAYID, 11686); -// c->setFaction(35); - bRemoved = false; - bRemoved2 = false; - bCasted = false; - bCasted2 = false; - } - - ScriptedInstance* pInstance; - - bool bRemoved; - bool bRemoved2; - bool bCasted; - bool bCasted2; - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*victim*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 /*diff*/) - { - if (!pInstance) - return; - - if (!bRemoved && me->GetPositionX() > 440.0f) - { - if (pInstance->GetData(DATA_PRINCE_TALDARAM_EVENT) == DONE) - { - me->InterruptNonMeleeSpells(true); - bRemoved = true; - return; - } - if (!bCasted) - { - DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_1, false); - bCasted = true; - } - } - if (!bRemoved2 && me->GetPositionX() < 440.0f) - { - if (!bCasted2 && pInstance->GetData(DATA_JEDOGA_TRIGGER_SWITCH)) - { - DoCast(me, SPELL_BEAM_VISUAL_JEDOGAS_AUFSEHER_2, false); - bCasted2 = true; - } - if (bCasted2 && !pInstance->GetData(DATA_JEDOGA_TRIGGER_SWITCH)) - { - me->InterruptNonMeleeSpells(true); - bCasted2 = false; - } - if (!bRemoved2 && pInstance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == DONE) - { - me->InterruptNonMeleeSpells(true); - bRemoved2 = true; - } - } - } -}; - -CreatureAI* GetAI_boss_jedoga_shadowseeker(Creature* pCreature) -{ - return new boss_jedoga_shadowseekerAI (pCreature); -} - -CreatureAI* GetAI_mob_jedoga_initiand(Creature* pCreature) -{ - return new mob_jedoga_initiandAI (pCreature); -} - -CreatureAI* GetAI_npc_jedogas_aufseher_trigger(Creature* pCreature) -{ - return new npc_jedogas_aufseher_triggerAI (pCreature); -} - -void AddSC_boss_jedoga_shadowseeker() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_jedoga_shadowseeker"; - newscript->GetAI = &GetAI_boss_jedoga_shadowseeker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_jedoga_initiand"; - newscript->GetAI = &GetAI_mob_jedoga_initiand; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jedogas_aufseher_trigger"; - newscript->GetAI = &GetAI_npc_jedogas_aufseher_trigger; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp deleted file mode 100644 index 93a66ccfbca..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -enum Spells -{ - SPELL_BLOODTHIRST = 55968, //Trigger Spell + add aura - SPELL_CONJURE_FLAME_SPHERE = 55931, - SPELL_FLAME_SPHERE_SUMMON_1 = 55895,// 1x 30106 - H_SPELL_FLAME_SPHERE_SUMMON_1 = 59511,// 1x 31686 - H_SPELL_FLAME_SPHERE_SUMMON_2 = 59512,// 1x 31687 - SPELL_FLAME_SPHERE_SPAWN_EFFECT = 55891, - SPELL_FLAME_SPHERE_VISUAL = 55928, - SPELL_FLAME_SPHERE_PERIODIC = 55926, - H_SPELL_FLAME_SPHERE_PERIODIC = 59508, - SPELL_FLAME_SPHERE_DEATH_EFFECT = 55947, - SPELL_BEAM_VISUAL = 60342, - SPELL_EMBRACE_OF_THE_VAMPYR = 55959, - H_SPELL_EMBRACE_OF_THE_VAMPYR = 59513, - SPELL_VANISH = 55964, - CREATURE_FLAME_SPHERE = 30106, - H_CREATURE_FLAME_SPHERE_1 = 31686, - H_CREATURE_FLAME_SPHERE_2 = 31687 -}; -enum Misc -{ - DATA_EMBRACE_DMG = 20000, - H_DATA_EMBRACE_DMG = 40000, - DATA_SPHERE_DISTANCE = 15 -}; -#define DATA_SPHERE_ANGLE_OFFSET 0.7 -#define DATA_GROUND_POSITION_Z 11.4 - -enum Yells -{ - SAY_AGGRO = -1619021, - SAY_SLAY_1 = -1619022, - SAY_SLAY_2 = -1619023, - SAY_DEATH = -1619024, - SAY_FEED_1 = -1619025, - SAY_FEED_2 = -1619026, - SAY_VANISH_1 = -1619027, - SAY_VANISH_2 = -1619028 -}; -enum CombatPhase -{ - NORMAL, - CASTING_FLAME_SPHERES, - JUST_VANISHED, - VANISHED, - FEEDING -}; -enum GameObjects -{ - GO_SPHERE1 = 193093, - GO_SPHERE2 = 193094 -}; - -struct boss_taldaramAI : public ScriptedAI -{ - boss_taldaramAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - uint32 uiBloodthirstTimer; - uint32 uiVanishTimer; - uint32 uiWaitTimer; - uint32 uiEmbraceTimer; - uint32 uiEmbraceTakenDamage; - uint32 uiFlamesphereTimer; - uint32 uiPhaseTimer; - - uint64 uiEmbraceTarget; - - CombatPhase Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - uiBloodthirstTimer = 10*IN_MILISECONDS; - uiVanishTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); - uiEmbraceTimer = 20*IN_MILISECONDS; - uiFlamesphereTimer = 5*IN_MILISECONDS; - uiEmbraceTakenDamage = 0; - Phase = NORMAL; - uiPhaseTimer = 0; - uiEmbraceTarget = 0; - if (pInstance) - pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, IN_PROGRESS); - DoScriptText(SAY_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - if (uiPhaseTimer <= diff) - { - switch (Phase) - { - case CASTING_FLAME_SPHERES: - { - Creature* pSpheres[3]; - - //DoCast(me, SPELL_FLAME_SPHERE_SUMMON_1); - pSpheres[0] = DoSpawnCreature(CREATURE_FLAME_SPHERE, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); - Unit *pSphereTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pSphereTarget && pSpheres[0]) - { - float angle,x,y; - angle = pSpheres[0]->GetAngle(pSphereTarget); - x = pSpheres[0]->GetPositionX() + DATA_SPHERE_DISTANCE * cos(angle); - y = pSpheres[0]->GetPositionY() + DATA_SPHERE_DISTANCE * sin(angle); - pSpheres[0]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[0]->GetPositionZ()); - } - if (IsHeroic()) - { - //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_1); - pSpheres[1] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_1, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); - //DoCast(me, H_SPELL_FLAME_SPHERE_SUMMON_2); - pSpheres[2] = DoSpawnCreature(H_CREATURE_FLAME_SPHERE_2, 0, 0, 5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10*IN_MILISECONDS); - if (pSphereTarget && pSpheres[1] && pSpheres[2]) - { - float angle,x,y; - angle = pSpheres[1]->GetAngle(pSphereTarget) + DATA_SPHERE_ANGLE_OFFSET; - x = pSpheres[1]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * cos(angle); - y = pSpheres[1]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * sin(angle); - pSpheres[1]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[1]->GetPositionZ()); - angle = pSpheres[2]->GetAngle(pSphereTarget) - DATA_SPHERE_ANGLE_OFFSET; - x = pSpheres[2]->GetPositionX() + DATA_SPHERE_DISTANCE/2 * cos(angle); - y = pSpheres[2]->GetPositionY() + DATA_SPHERE_DISTANCE/2 * sin(angle); - pSpheres[2]->GetMotionMaster()->MovePoint(0, x, y, pSpheres[2]->GetPositionZ()); - } - } - - Phase = NORMAL; - uiPhaseTimer = 0; - break; - } - case JUST_VANISHED: - if (Unit *pEmbraceTarget = GetEmbraceTarget()) - { - me->GetMotionMaster()->Clear(); - me->SetSpeed(MOVE_WALK, 2.0f, true); - me->GetMotionMaster()->MoveChase(pEmbraceTarget); - } - Phase = VANISHED; - uiPhaseTimer = 1300; - break; - case VANISHED: - if (Unit *pEmbraceTarget = GetEmbraceTarget()) - DoCast(pEmbraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR); - me->GetMotionMaster()->Clear(); - me->SetSpeed(MOVE_WALK, 1.0f, true); - me->GetMotionMaster()->MoveChase(me->getVictim()); - Phase = FEEDING; - uiPhaseTimer = 20*IN_MILISECONDS; - break; - case FEEDING: - Phase = NORMAL; - uiPhaseTimer = 0; - uiEmbraceTarget = 0; - break; - case NORMAL: - if (uiBloodthirstTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BLOODTHIRST); - uiBloodthirstTimer = 10*IN_MILISECONDS; - } else uiBloodthirstTimer -= diff; - - if (uiFlamesphereTimer <= diff) - { - DoCast(me, SPELL_CONJURE_FLAME_SPHERE); - Phase = CASTING_FLAME_SPHERES; - uiPhaseTimer = 3*IN_MILISECONDS + diff; - uiFlamesphereTimer = 15*IN_MILISECONDS; - } else uiFlamesphereTimer -= diff; - - if (uiVanishTimer <= diff) - { - //Count alive players - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - // exclude pets & totems - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) - target_list.push_back(pTarget); - pTarget = NULL; - } - //He only vanishes if there are 3 or more alive players - if (target_list.size() > 2) - { - DoScriptText(RAND(SAY_VANISH_1,SAY_VANISH_2), me); - DoCast(me, SPELL_VANISH); - Phase = JUST_VANISHED; - uiPhaseTimer = 500; - if (Unit* pEmbraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - uiEmbraceTarget = pEmbraceTarget->GetGUID(); - - } - uiVanishTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); - } else uiVanishTimer -= diff; - - DoMeleeAttackIfReady(); - break; - } - } else uiPhaseTimer -= diff; - } - - void DamageTaken(Unit* /*done_by*/, uint32 &damage) - { - Unit* pEmbraceTarget = GetEmbraceTarget(); - - if (Phase == FEEDING && pEmbraceTarget && pEmbraceTarget->isAlive()) - { - uiEmbraceTakenDamage += damage; - if (uiEmbraceTakenDamage > DUNGEON_MODE(DATA_EMBRACE_DMG, H_DATA_EMBRACE_DMG)) - { - Phase = NORMAL; - uiPhaseTimer = 0; - uiEmbraceTarget = 0; - me->CastStop(); - } - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_PRINCE_TALDARAM_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - Unit* pEmbraceTarget = GetEmbraceTarget(); - if (Phase == FEEDING && pEmbraceTarget && victim == pEmbraceTarget) - { - Phase = NORMAL; - uiPhaseTimer = 0; - uiEmbraceTarget = 0; - } - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - bool CheckSpheres() - { - if (!pInstance) - return false; - - uint64 uiSphereGuids[2]; - uiSphereGuids[0] = pInstance->GetData64(DATA_SPHERE1); - uiSphereGuids[1] = pInstance->GetData64(DATA_SPHERE2); - - for (uint8 i=0; i < 2; ++i) - { - GameObject *pSpheres = pInstance->instance->GetGameObject(uiSphereGuids[i]); - if (!pSpheres) - return false; - if (pSpheres->GetGoState() != GO_STATE_ACTIVE) - return false; - } - RemovePrison(); - return true; - } - - Unit* GetEmbraceTarget() - { - if (!uiEmbraceTarget) - return NULL; - - return Unit::GetUnit(*me, uiEmbraceTarget); - } - - void RemovePrison() - { - if (!pInstance) - return; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAurasDueToSpell(SPELL_BEAM_VISUAL); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), DATA_GROUND_POSITION_Z, me->GetOrientation()); - uint64 prison_GUID = pInstance->GetData64(DATA_PRINCE_TALDARAM_PLATFORM); - pInstance->HandleGameObject(prison_GUID,true); - } -}; - -struct mob_taldaram_flamesphereAI : public ScriptedAI -{ - mob_taldaram_flamesphereAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiDespawnTimer; - ScriptedInstance* pInstance; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); - me->setFaction(16); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); - DoCast(me, SPELL_FLAME_SPHERE_VISUAL); - DoCast(me, SPELL_FLAME_SPHERE_SPAWN_EFFECT); - DoCast(me, SPELL_FLAME_SPHERE_PERIODIC); - uiDespawnTimer = 10*IN_MILISECONDS; - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void JustDied(Unit* /*who*/) - { - DoCast(me, SPELL_FLAME_SPHERE_DEATH_EFFECT); - } - - void UpdateAI(const uint32 diff) - { - if (uiDespawnTimer <= diff) - me->DisappearAndDie(); - else - uiDespawnTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_taldaram(Creature* pCreature) -{ - return new boss_taldaramAI (pCreature); -} - -CreatureAI* GetAI_mob_taldaram_flamesphere(Creature* pCreature) -{ - return new mob_taldaram_flamesphereAI (pCreature); -} - -bool GOHello_prince_taldaram_sphere(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - - Creature *pPrinceTaldaram = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_PRINCE_TALDARAM) : 0); - if (pPrinceTaldaram && pPrinceTaldaram->isAlive()) - { - // maybe these are hacks :( - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - switch(pGO->GetEntry()) - { - case GO_SPHERE1: pInstance->SetData(DATA_SPHERE1_EVENT,IN_PROGRESS); break; - case GO_SPHERE2: pInstance->SetData(DATA_SPHERE2_EVENT,IN_PROGRESS); break; - } - - CAST_AI(boss_taldaramAI, pPrinceTaldaram->AI())->CheckSpheres(); - } - return true; -} - -void AddSC_boss_taldaram() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_taldaram"; - newscript->GetAI = &GetAI_boss_taldaram; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_taldaram_flamesphere"; - newscript->GetAI = &GetAI_mob_taldaram_flamesphere; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "prince_taldaram_sphere"; - newscript->pGOHello = &GOHello_prince_taldaram_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp deleted file mode 100644 index 4e6e3ec8c9f..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "ahnkahet.h" - -/* Ahn'kahet encounters: -0 - Elder Nadox -1 - Prince Taldaram -2 - Jedoga Shadowseeker -3 - Herald Volazj -4 - Amanitar (Heroic only) -*/ - -#define MAX_ENCOUNTER 5 - -enum Achievements -{ - ACHIEV_VOLUNTEER_WORK = 2056 -}; - -struct instance_ahnkahet : public ScriptedInstance -{ - instance_ahnkahet(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 Elder_Nadox; - uint64 Prince_Taldaram; - uint64 Jedoga_Shadowseeker; - uint64 Herald_Volazj; - uint64 Amanitar; - - uint64 Prince_TaldaramSpheres[2]; - uint64 Prince_TaldaramPlatform; - uint64 Prince_TaldaramGate; - - std::set InitiandGUIDs; - uint64 JedogaSacrifices; - uint64 JedogaTarget; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 spheres[2]; - - uint8 InitiandCnt, - switchtrigger, - initiandkilled; - - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - InitiandGUIDs.clear(); - - Elder_Nadox =0; - Prince_Taldaram =0; - Jedoga_Shadowseeker =0; - Herald_Volazj =0; - Amanitar =0; - - spheres[0] = NOT_STARTED; - spheres[1] = NOT_STARTED; - - InitiandCnt = 0; - switchtrigger = 0; - initiandkilled = 0; - JedogaSacrifices = 0; - JedogaTarget = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 29309: Elder_Nadox = pCreature->GetGUID(); break; - case 29308: Prince_Taldaram = pCreature->GetGUID(); break; - case 29310: Jedoga_Shadowseeker = pCreature->GetGUID(); break; - case 29311: Herald_Volazj = pCreature->GetGUID(); break; - case 30258: Amanitar = pCreature->GetGUID(); break; - case 30114: InitiandGUIDs.insert(pCreature->GetGUID()); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 193564: Prince_TaldaramPlatform = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) HandleGameObject(NULL,true,pGo); break; - case 193093: Prince_TaldaramSpheres[0] = pGo->GetGUID(); - if (spheres[0] == IN_PROGRESS) - { - pGo->SetGoState(GO_STATE_ACTIVE); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - else pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case 193094: Prince_TaldaramSpheres[1] = pGo->GetGUID(); - if (spheres[1] == IN_PROGRESS) - { - pGo->SetGoState(GO_STATE_ACTIVE); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - else pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - case 192236: Prince_TaldaramGate = pGo->GetGUID(); // Web gate past Prince Taldaram - if (m_auiEncounter[1] == DONE)HandleGameObject(NULL,true,pGo);break; - } - } - - void SetData64(uint32 idx, uint64 guid) - { - switch(idx) - { - case DATA_ADD_JEDOGA_OPFER: JedogaSacrifices = guid; break; - case DATA_PL_JEDOGA_TARGET: JedogaTarget = guid; break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_ELDER_NADOX: return Elder_Nadox; - case DATA_PRINCE_TALDARAM: return Prince_Taldaram; - case DATA_JEDOGA_SHADOWSEEKER: return Jedoga_Shadowseeker; - case DATA_HERALD_VOLAZJ: return Herald_Volazj; - case DATA_AMANITAR: return Amanitar; - case DATA_SPHERE1: return Prince_TaldaramSpheres[0]; - case DATA_SPHERE2: return Prince_TaldaramSpheres[1]; - case DATA_PRINCE_TALDARAM_PLATFORM: return Prince_TaldaramPlatform; - case DATA_ADD_JEDOGA_INITIAND: - { - std::vector vInitiands; - vInitiands.clear(); - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (cr && cr->isAlive()) - vInitiands.push_back(*itr); - } - if (vInitiands.empty()) - return 0; - uint8 j = urand(0,vInitiands.size() -1); - return vInitiands[j]; - } - case DATA_ADD_JEDOGA_OPFER: return JedogaSacrifices; - case DATA_PL_JEDOGA_TARGET: return JedogaTarget; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_ELDER_NADOX_EVENT: m_auiEncounter[0] = data; break; - case DATA_PRINCE_TALDARAM_EVENT: - if (data == DONE) - HandleGameObject(Prince_TaldaramGate,true); - m_auiEncounter[1] = data; - break; - case DATA_JEDOGA_SHADOWSEEKER_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) - { - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (cr && cr->isAlive()) - { - cr->SetVisibility(VISIBILITY_OFF); - cr->setDeathState(JUST_DIED); - cr->RemoveCorpse(); - } - } - if (!initiandkilled && instance->IsHeroic()) - DoCompleteAchievement(ACHIEV_VOLUNTEER_WORK); - } - break; - case DATA_HERALD_VOLAZJ_EVENT: m_auiEncounter[3] = data; break; - case DATA_AMANITAR_EVENT: m_auiEncounter[4] = data; break; - case DATA_SPHERE1_EVENT: spheres[0] = data; break; - case DATA_SPHERE2_EVENT: spheres[1] = data; break; - case DATA_JEDOGA_TRIGGER_SWITCH: switchtrigger = data; break; - case DATA_INITIAND_KILLED: initiandkilled = data; break; - case DATA_JEDOGA_RESET_INITIANDS: - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (cr) - { - cr->Respawn(); - if (!cr->IsInEvadeMode()) cr->AI()->EnterEvadeMode(); - } - } - break; - } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_ELDER_NADOX_EVENT: return m_auiEncounter[0]; - case DATA_PRINCE_TALDARAM_EVENT: return m_auiEncounter[1]; - case DATA_JEDOGA_SHADOWSEEKER_EVENT: return m_auiEncounter[2]; - case DATA_HERALD_VOLAZJ: return m_auiEncounter[3]; - case DATA_AMANITAR_EVENT: return m_auiEncounter[4]; - case DATA_SPHERE1_EVENT: return spheres[0]; - case DATA_SPHERE2_EVENT: return spheres[1]; - case DATA_ALL_INITIAND_DEAD: - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (!cr || (cr && cr->isAlive())) return 0; - } - return 1; - case DATA_JEDOGA_TRIGGER_SWITCH: return switchtrigger; - case DATA_INITIAND_KILLED: return initiandkilled; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "A K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " - << spheres[0] << " " << spheres[1]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5, data6; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6; - - if (dataHead1 == 'A' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - spheres[0] = data5; - spheres[1] = data6; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_ahnkahet(Map* pMap) -{ - return new instance_ahnkahet(pMap); -} - -void AddSC_instance_ahnkahet() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_ahnkahet"; - newscript->GetInstanceData = &GetInstanceData_instance_ahnkahet; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h deleted file mode 100644 index 4113885b6f4..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/azjol_nerub.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_AZJOL_NERUB_H -#define DEF_AZJOL_NERUB_H - -enum Data64 -{ - DATA_KRIKTHIR_THE_GATEWATCHER, - DATA_HADRONOX, - DATA_ANUBARAK, - DATA_WATCHER_GASHRA, - DATA_WATCHER_SILTHIK, - DATA_WATCHER_NARJIL -}; -enum Data -{ - DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, - DATA_HADRONOX_EVENT, - DATA_ANUBARAK_EVENT -}; - -#endif diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp deleted file mode 100644 index 6de6578f7bb..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -//SQL: UPDATE creature_template SET mechanic_immune_mask = 1073741823 WHERE name like "anub'arak%"; - -enum Spells -{ - SPELL_CARRION_BEETLES = 53520, - SPELL_SUMMON_CARRION_BEETLES = 53521, - SPELL_LEECHING_SWARM = 53467, - SPELL_POUND = 53472, - SPELL_POUND_H = 59433, - SPELL_SUBMERGE = 53421, - SPELL_IMPALE_DMG = 53454, - SPELL_IMPALE_DMG_H = 59446, - SPELL_IMPALE_SHAKEGROUND = 53455, - SPELL_IMPALE_SPIKE = 53539, //this is not the correct visual effect - //SPELL_IMPALE_TARGET = 53458, -}; - -enum Creatures -{ - CREATURE_GUARDIAN = 29216, - CREATURE_VENOMANCER = 29217, - CREATURE_DATTER = 29213, - CREATURE_IMPALE_TARGET = 89, - DISPLAY_INVISIBLE = 11686 -}; - -// not in db -enum Yells -{ - SAY_INTRO = -1601010, - SAY_AGGRO = -1601000, - SAY_SLAY_1 = -1601001, - SAY_SLAY_2 = -1601002, - SAY_SLAY_3 = -1601003, - SAY_LOCUST_1 = -1601005, - SAY_LOCUST_2 = -1601006, - SAY_LOCUST_3 = -1601007, - SAY_SUBMERGE_1 = -1601008, - SAY_SUBMERGE_2 = -1601009, - SAY_DEATH = -1601004 -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 20381, -}; - -enum Phases -{ - PHASE_MELEE = 0, - PHASE_UNDERGROUND = 1, - IMPALE_PHASE_TARGET = 0, - IMPALE_PHASE_ATTACK = 1, - IMPALE_PHASE_DMG = 2 -}; - -const Position SpawnPoint[2] = -{ - { 550.7, 282.8, 224.3 }, - { 551.1, 229.4, 224.3 }, -}; - -const Position SpawnPointGuardian[2] = -{ - { 550.348633, 316.006805, 234.2947 }, - { 550.188660, 324.264557, 237.7412 }, -}; - -struct boss_anub_arakAI : public ScriptedAI -{ - boss_anub_arakAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - bool bChanneling; - bool bGuardianSummoned; - bool bVenomancerSummoned; - bool bDatterSummoned; - uint8 uiPhase; - uint32 uiUndergroundPhase; - uint32 uiCarrionBeetlesTimer; - uint32 uiLeechingSwarmTimer; - uint32 uiPoundTimer; - uint32 uiSubmergeTimer; - uint32 uiUndergroundTimer; - uint32 uiVenomancerTimer; - uint32 uiDatterTimer; - - uint32 uiImpaleTimer; - uint32 uiImpalePhase; - uint64 uiImpaleTarget; - - SummonList lSummons; - - void Reset() - { - uiCarrionBeetlesTimer = 8*IN_MILISECONDS; - uiLeechingSwarmTimer = 20*IN_MILISECONDS; - uiImpaleTimer = 9*IN_MILISECONDS; - uiPoundTimer = 15*IN_MILISECONDS; - - uiPhase = PHASE_MELEE; - uiUndergroundPhase = 0; - bChanneling = false; - uiImpalePhase = IMPALE_PHASE_TARGET; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->RemoveAura(SPELL_SUBMERGE); - - lSummons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_ANUBARAK_EVENT, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - Creature* DoSummonImpaleTarget(Unit *pTarget) - { - Position targetPos; - pTarget->GetPosition(&targetPos); - - if (TempSummon* pImpaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILISECONDS)) - { - uiImpaleTarget = pImpaleTarget->GetGUID(); - pImpaleTarget->SetReactState(REACT_PASSIVE); - pImpaleTarget->SetDisplayId(DISPLAY_INVISIBLE); - pImpaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - return pImpaleTarget; - } - - return NULL; - } - - void EnterCombat(Unit * /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - pInstance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - switch (uiPhase) - { - case PHASE_UNDERGROUND: - if (uiImpaleTimer <= diff) - { - switch(uiImpalePhase) - { - case IMPALE_PHASE_TARGET: - if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) - pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SHAKEGROUND, true); - uiImpaleTimer = 3*IN_MILISECONDS; - uiImpalePhase = IMPALE_PHASE_ATTACK; - } - break; - case IMPALE_PHASE_ATTACK: - if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) - { - pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SPIKE, false); - pImpaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND); - } - uiImpalePhase = IMPALE_PHASE_DMG; - uiImpaleTimer = 1*IN_MILISECONDS; - break; - case IMPALE_PHASE_DMG: - if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) - me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_IMPALE_DMG, SPELL_IMPALE_DMG_H), true); - uiImpalePhase = IMPALE_PHASE_TARGET; - uiImpaleTimer = 9*IN_MILISECONDS; - break; - } - } else uiImpaleTimer -= diff; - - if (!bGuardianSummoned) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Guardian = me->SummonCreature(CREATURE_GUARDIAN,SpawnPointGuardian[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Guardian->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Guardian); - } - } - bGuardianSummoned = true; - } - - if (!bVenomancerSummoned) - { - if (uiVenomancerTimer <= diff) - { - if (uiUndergroundPhase > 1) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Venomancer = me->SummonCreature(CREATURE_VENOMANCER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Venomancer->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Venomancer); - } - } - bVenomancerSummoned = true; - } - } else uiVenomancerTimer -= diff; - } - - if (!bDatterSummoned) - { - if (uiDatterTimer <= diff) - { - if (uiUndergroundPhase > 2) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Datter = me->SummonCreature(CREATURE_DATTER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Datter->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Datter); - } - } - bDatterSummoned = true; - } - } else uiDatterTimer -= diff; - } - - if (uiUndergroundTimer <= diff) - { - me->RemoveAura(SPELL_SUBMERGE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - uiPhase = PHASE_MELEE; - } else uiUndergroundTimer -= diff; - break; - - case PHASE_MELEE: - if (((uiUndergroundPhase == 0 && HealthBelowPct(75)) - || (uiUndergroundPhase == 1 && HealthBelowPct(50)) - || (uiUndergroundPhase == 2 && HealthBelowPct(25))) - && !me->hasUnitState(UNIT_STAT_CASTING)) - { - bGuardianSummoned = false; - bVenomancerSummoned = false; - bDatterSummoned = false; - - uiUndergroundTimer = 40*IN_MILISECONDS; - uiVenomancerTimer = 25*IN_MILISECONDS; - uiDatterTimer = 32*IN_MILISECONDS; - - uiImpalePhase = 0; - uiImpaleTimer = 9*IN_MILISECONDS; - - DoCast(me, SPELL_SUBMERGE, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - - uiPhase = PHASE_UNDERGROUND; - ++uiUndergroundPhase; - } - - if (bChanneling == true) - { - for (uint8 i = 0; i < 8; ++i) - DoCast(me->getVictim(), SPELL_SUMMON_CARRION_BEETLES, true); - bChanneling = false; - } - else if (uiCarrionBeetlesTimer <= diff) - { - bChanneling = true; - DoCastVictim(SPELL_CARRION_BEETLES); - uiCarrionBeetlesTimer = 25*IN_MILISECONDS; - } else uiCarrionBeetlesTimer -= diff; - - if (uiLeechingSwarmTimer <= diff) - { - DoCast(me, SPELL_LEECHING_SWARM, true); - uiLeechingSwarmTimer = 19*IN_MILISECONDS; - } else uiLeechingSwarmTimer -= diff; - - if (uiPoundTimer <= diff) - { - if (Unit *target = me->getVictim()) - { - if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) - me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_POUND, SPELL_POUND_H), false); - } - uiPoundTimer = 16.5*IN_MILISECONDS; - } else uiPoundTimer -= diff; - - DoMeleeAttackIfReady(); - break; - } - } - - void JustDied(Unit * /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - lSummons.DespawnAll(); - if (pInstance) - pInstance->SetData(DATA_ANUBARAK_EVENT, DONE); - } - - void KilledUnit(Unit *pVictim) - { - if (pVictim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustSummoned(Creature* summon) - { - lSummons.Summon(summon); - } -}; - -CreatureAI* GetAI_boss_anub_arak(Creature *pCreature) -{ - return new boss_anub_arakAI (pCreature); -} - -void AddSC_boss_anub_arak() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_anub_arak"; - newscript->GetAI = &GetAI_boss_anub_arak; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp deleted file mode 100644 index 0fc4e87d7c5..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* -* Comment: No Waves atm and the doors spells are crazy... -* -* When your group enters the main room (the one after the bridge), you will notice a group of 3 Nerubians. -* When you engage them, 2 more groups like this one spawn behind the first one - it is important to pull the first group back, -* so you don't aggro all 3. Hadronox will be under you, fighting Nerubians. -* -* This is the timed gauntlet - waves of non-elite spiders -* will spawn from the 3 doors located a little above the main room, and will then head down to fight Hadronox. After clearing the -* main room, it is recommended to just stay in it, kill the occasional non-elites that will attack you instead of the boss, and wait for -* Hadronox to make his way to you. When Hadronox enters the main room, she will web the doors, and no more non-elites will spawn. -*/ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -enum Spells -{ - SPELL_ACID_CLOUD = 53400, // Victim - SPELL_LEECH_POISON = 53030, // Victim - SPELL_PIERCE_ARMOR = 53418, // Victim - SPELL_WEB_GRAB = 57731, // Victim - SPELL_WEB_FRONT_DOORS = 53177, // Self - SPELL_WEB_SIDE_DOORS = 53185, // Self - H_SPELL_ACID_CLOUD = 59419, - H_SPELL_LEECH_POISON = 59417, - H_SPELL_WEB_GRAB = 59421 -}; - -struct boss_hadronoxAI : public ScriptedAI -{ - boss_hadronoxAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - fMaxDistance = 50.0f; - bFirstTime = true; - } - - ScriptedInstance* pInstance; - - uint32 uiAcidTimer; - uint32 uiLeechTimer; - uint32 uiPierceTimer; - uint32 uiGrabTimer; - uint32 uiDoorsTimer; - uint32 uiCheckDistanceTimer; - - bool bFirstTime; - - float fMaxDistance; - - void Reset() - { - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 9.0f); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 9.0f); - - uiAcidTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); - uiLeechTimer = urand(3*IN_MILISECONDS,9*IN_MILISECONDS); - uiPierceTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); - uiGrabTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); - uiDoorsTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - uiCheckDistanceTimer = 2*IN_MILISECONDS; - - if (pInstance && (pInstance->GetData(DATA_HADRONOX_EVENT) != DONE && !bFirstTime)) - pInstance->SetData(DATA_HADRONOX_EVENT, FAIL); - - bFirstTime = false; - } - - //when Hadronox kills any enemy (that includes a party member) she will regain 10% of her HP if the target had Leech Poison on - void KilledUnit(Unit* Victim) - { - // not sure if this aura check is correct, I think it is though - if (!Victim || !Victim->HasAura(DUNGEON_MODE(SPELL_LEECH_POISON, H_SPELL_LEECH_POISON)) || !me->isAlive()) - return; - - uint32 health = me->GetMaxHealth()/10; - - if ((me->GetHealth()+health) >= me->GetMaxHealth()) - me->SetHealth(me->GetMaxHealth()); - else - me->SetHealth(me->GetHealth()+health); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_HADRONOX_EVENT, DONE); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HADRONOX_EVENT, IN_PROGRESS); - me->SetInCombatWithZone(); - } - - void CheckDistance(float dist, const uint32 uiDiff) - { - if (!me->isInCombat()) - return; - - float x=0.0f, y=0.0f, z=0.0f; - me->GetRespawnCoord(x,y,z); - - if (uiCheckDistanceTimer <= uiDiff) - uiCheckDistanceTimer = 5*IN_MILISECONDS; - else - { - uiCheckDistanceTimer -= uiDiff; - return; - } - if (me->IsInEvadeMode() || !me->getVictim()) - return; - if (me->GetDistance(x,y,z) > dist) - EnterEvadeMode(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) return; - - // Without he comes up through the air to players on the bridge after krikthir if players crossing this bridge! - CheckDistance(fMaxDistance, diff); - - if (me->HasAura(SPELL_WEB_FRONT_DOORS) || me->HasAura(SPELL_WEB_SIDE_DOORS)) - { - if (IsCombatMovement()) - SetCombatMovement(false); - } - else if (!IsCombatMovement()) - SetCombatMovement(true); - - if (uiPierceTimer <= diff) - { - DoCast(me->getVictim(), SPELL_PIERCE_ARMOR); - uiPierceTimer = 8*IN_MILISECONDS; - } else uiPierceTimer -= diff; - - if (uiAcidTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ACID_CLOUD); - - uiAcidTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiAcidTimer -= diff; - - if (uiLeechTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_LEECH_POISON); - - uiLeechTimer = urand(11*IN_MILISECONDS,14*IN_MILISECONDS); - } else uiLeechTimer -= diff; - - if (uiGrabTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) // Draws all players (and attacking Mobs) to itself. - DoCast(pTarget, SPELL_WEB_GRAB); - - uiGrabTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiGrabTimer -= diff; - - if (uiDoorsTimer <= diff) - { - //DoCast(me, RAND(SPELL_WEB_FRONT_DOORS, SPELL_WEB_SIDE_DOORS)); - uiDoorsTimer = urand(30*IN_MILISECONDS,60*IN_MILISECONDS); - } else uiDoorsTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_hadronox(Creature* pCreature) -{ - return new boss_hadronoxAI (pCreature); -} - -void AddSC_boss_hadronox() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_hadronox"; - newscript->GetAI = &GetAI_boss_hadronox; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp deleted file mode 100644 index 4863bdcb032..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: Find in the future best timers and the event is not implemented. - */ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -enum Spells -{ - SPELL_MIND_FLAY = 52586, - H_SPELL_MIND_FLAY = 59367, - SPELL_CURSE_OF_FATIGUE = 52592, - H_SPELL_CURSE_OF_FATIGUE = 59368, - SPELL_FRENZY = 28747, //maybe 53361 - SPELL_SUMMON_SKITTERING_SWARMER = 52438, //AOE Effect 140, maybe 52439 - SPELL_SUMMON_SKITTERING_SWARMER_1 = 52439, //Summon 3x 28735 - H_SPELL_ACID_SPLASH = 59363, - SPELL_ACID_SPLASH = 52446, - SPELL_CHARGE = 16979,//maybe is another spell - SPELL_BACKSTAB = 52540, - SPELL_SHADOW_BOLT = 52534, - H_SPELL_SHADOW_BOLT = 59357, - SPELL_SHADOW_NOVA = 52535, - H_SPELL_SHADOW_NOVA = 59358, - SPELL_STRIKE = 52532, - SPELL_CLEAVE = 49806, - SPELL_ENRAGE = 52470, - SPELL_INFECTED_BITE = 52469, - H_SPELL_INFECTED_BITE = 59364, - SPELL_WEB_WRAP = 52086,//the spell is not working properly - SPELL_BLINDING_WEBS = 52524, - H_SPELL_BLINDING_WEBS = 59365, - SPELL_POSION_SPRAY = 52493, - H_SPELL_POSION_SPRAY = 59366 -}; - -enum Mobs -{ - MOB_SKITTERING_SWARMER = 28735, - MOB_SKITTERING_SWARMER_CONTROLLER = 32593, - MOB_SKITTERING_INFECTIOR = 28736 -}; - -enum Yells -{ - SAY_AGGRO = -1601011, - SAY_SLAY_1 = -1601012, - SAY_SLAY_2 = -1601013, - SAY_DEATH = -1601014, - //Not in db - SAY_SEND_GROUP_1 = -1601020, - SAY_SEND_GROUP_2 = -1601021, - SAY_SEND_GROUP_3 = -1601022, - SAY_SWARM_1 = -1601015, - SAY_SWARM_2 = -1601016, - SAY_PREFIGHT_1 = -1601017, - SAY_PREFIGHT_2 = -1601018, - SAY_PREFIGHT_3 = -1601019 -}; - -enum Misc -{ - ACHIEV_WATH_HIM_DIE = 1296 -}; - -const Position SpawnPoint[] = -{ - { 566.164, 682.087, 769.079, 2.21657 }, - { 529.042, 706.941, 777.298, 1.0821 }, - { 489.975, 671.239, 772.131, 0.261799 }, - { 488.556, 692.95, 771.764, 4.88692 }, - { 553.34, 640.387, 777.419, 1.20428 }, - { 517.486, 706.398, 777.335, 5.35816 }, - { 504.01, 637.693, 777.479, 0.506145 }, - { 552.625, 706.408, 777.177, 3.4383 } -}; -struct boss_krik_thirAI : public ScriptedAI -{ - boss_krik_thirAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiMindFlayTimer; - uint32 uiCurseFatigueTimer; - uint32 uiSummonTimer; - - void Reset() - { - uiMindFlayTimer = 15*IN_MILISECONDS; - uiCurseFatigueTimer = 12*IN_MILISECONDS; - - if (pInstance) - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - Summon(); - uiSummonTimer = 15*IN_MILISECONDS; - - if (pInstance) - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, IN_PROGRESS); - } - - void Summon() - { - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiSummonTimer <= diff) - { - Summon(); - uiSummonTimer = 15*IN_MILISECONDS; - } else uiSummonTimer -= diff; - - if (uiMindFlayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MIND_FLAY); - uiMindFlayTimer = 15*IN_MILISECONDS; - } else uiMindFlayTimer -= diff; - - if (uiCurseFatigueTimer <= diff) - { - //WowWiki say "Curse of Fatigue-Kirk'thir will cast Curse of Fatigue on 2-3 targets periodically." - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - Unit *pTarget_1 = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - - DoCast(pTarget, SPELL_CURSE_OF_FATIGUE); - DoCast(pTarget_1, SPELL_CURSE_OF_FATIGUE); - - uiCurseFatigueTimer = 10*IN_MILISECONDS; - } else uiCurseFatigueTimer -= diff; - - if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10)) - DoCast(me, SPELL_FRENZY, true); - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DONE); - //Achievement: Watch him die - Creature *pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_GASHRA)); - if (!pAdd || !pAdd->isAlive()) - return; - - pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_SILTHIK)); - if (!pAdd || !pAdd->isAlive()) - return; - - pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_NARJIL)); - if (!pAdd || !pAdd->isAlive()) - return; - - pInstance->DoCompleteAchievement(ACHIEV_WATH_HIM_DIE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustSummoned(Creature* summoned) - { - summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); - } -}; - -struct npc_skittering_infectorAI : public ScriptedAI -{ - npc_skittering_infectorAI(Creature *c) : ScriptedAI(c) {} - - void JustDied(Unit* /*killer*/) - { - //The spell is not working propperly - DoCast(me->getVictim(),SPELL_ACID_SPLASH, true); - } - -}; - -struct npc_anub_ar_skirmisherAI : public ScriptedAI -{ - npc_anub_ar_skirmisherAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiChargeTimer; - uint32 uiBackstabTimer; - - void Reset() - { - uiChargeTimer = 11*IN_MILISECONDS; - uiBackstabTimer = 7*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiChargeTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoResetThreat(); - me->AddThreat(pTarget,1.0f); - DoCast(pTarget, SPELL_CHARGE, true); - } - uiChargeTimer = 15*IN_MILISECONDS; - } else uiChargeTimer -= diff; - - if (uiBackstabTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BACKSTAB); - uiBackstabTimer = 12*IN_MILISECONDS; - } else uiBackstabTimer -= diff; - - DoMeleeAttackIfReady(); - - } -}; - -struct npc_anub_ar_shadowcasterAI : public ScriptedAI -{ - npc_anub_ar_shadowcasterAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiShadowBoltTimer; - uint32 uiShadowNovaTimer; - - void Reset() - { - uiShadowBoltTimer = 6*IN_MILISECONDS; - uiShadowNovaTimer = 15*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiShadowBoltTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SHADOW_BOLT, true); - uiShadowBoltTimer = 15*IN_MILISECONDS; - } else uiShadowBoltTimer -= diff; - - if (uiShadowNovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_NOVA, true); - uiShadowNovaTimer = 17*IN_MILISECONDS; - } else uiShadowNovaTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_anub_ar_warriorAI : public ScriptedAI -{ - npc_anub_ar_warriorAI(Creature *c) : ScriptedAI(c){} - - uint32 uiCleaveTimer; - uint32 uiStrikeTimer; - - void Reset() - { - uiCleaveTimer = 11*IN_MILISECONDS; - uiStrikeTimer = 6*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STRIKE, true); - uiStrikeTimer = 15*IN_MILISECONDS; - } else uiStrikeTimer -= diff; - - if (uiCleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE, true); - uiCleaveTimer = 17*IN_MILISECONDS; - } else uiCleaveTimer -= diff; - - DoMeleeAttackIfReady(); - - } - -}; - -struct npc_watcher_gashraAI : public ScriptedAI -{ - npc_watcher_gashraAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - } - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_ENRAGE, true); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - uiWebWrapTimer = 17*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 15*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_watcher_narjilAI : public ScriptedAI -{ - npc_watcher_narjilAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - uint32 uiBindingWebsTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - uiBindingWebsTimer = 17*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - uiWebWrapTimer = 15*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 11*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - if (uiBindingWebsTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BLINDING_WEBS, true); - uiBindingWebsTimer = 17*IN_MILISECONDS; - } else uiBindingWebsTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_watcher_silthikAI : public ScriptedAI -{ - npc_watcher_silthikAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - uint32 uiPoisonSprayTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - uiPoisonSprayTimer = 15*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - - uiWebWrapTimer = 15*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 15*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - if (uiPoisonSprayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POSION_SPRAY, true); - uiPoisonSprayTimer = 17*IN_MILISECONDS; - } else uiPoisonSprayTimer -= diff; - - DoMeleeAttackIfReady(); - - } -}; - -CreatureAI* GetAI_boss_krik_thir(Creature* pCreature) -{ - return new boss_krik_thirAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_skirmisher (Creature* pCreature) -{ - return new npc_anub_ar_skirmisherAI (pCreature); -} - -CreatureAI* GetAI_npc_skittering_infector (Creature* pCreature) -{ - return new npc_skittering_infectorAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_shadowcaster (Creature* pCreature) -{ - return new npc_anub_ar_shadowcasterAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_warrior (Creature* pCreature) -{ - return new npc_anub_ar_warriorAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_gashra (Creature* pCreature) -{ - return new npc_watcher_gashraAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_narjil (Creature* pCreature) -{ - return new npc_watcher_narjilAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_silthik (Creature* pCreature) -{ - return new npc_watcher_silthikAI (pCreature); -} - -void AddSC_boss_krik_thir() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_krik_thir"; - newscript->GetAI = &GetAI_boss_krik_thir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_skittering_infector"; - newscript->GetAI = &GetAI_npc_skittering_infector; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_skirmisher"; - newscript->GetAI = &GetAI_npc_anub_ar_skirmisher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_shadowcaster"; - newscript->GetAI = &GetAI_npc_anub_ar_shadowcaster; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_gashra"; - newscript->GetAI = &GetAI_npc_watcher_gashra; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_warrior"; - newscript->GetAI = &GetAI_npc_anub_ar_warrior; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_silthik"; - newscript->GetAI = &GetAI_npc_watcher_silthik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_narjil"; - newscript->GetAI = &GetAI_npc_watcher_narjil; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp deleted file mode 100644 index d12dbd604ba..00000000000 --- a/src/server/scripts/Northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -#define MAX_ENCOUNTER 3 - -/* Azjol Nerub encounters: -0 - Krik'thir the Gatewatcher -1 - Hadronox -2 - Anub'arak -*/ - -struct instance_azjol_nerub : public ScriptedInstance -{ - instance_azjol_nerub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiKrikthir; - uint64 uiHadronox; - uint64 uiAnubarak; - uint64 uiWatcherGashra; - uint64 uiWatcherSilthik; - uint64 uiWatcherNarjil; - uint64 uiAnubarakDoor[3]; - - uint64 uiKrikthirDoor; - - uint32 auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&auiEncounter, 0, sizeof(auiEncounter)); - memset(&uiAnubarakDoor, 0, sizeof(uiAnubarakDoor)); - - uiKrikthir = 0; - uiHadronox = 0; - uiAnubarak = 0; - uiWatcherGashra = 0; - uiWatcherSilthik = 0; - uiWatcherNarjil = 0; - uiKrikthirDoor = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 28684: uiKrikthir = pCreature->GetGUID(); break; - case 28921: uiHadronox = pCreature->GetGUID(); break; - case 29120: uiAnubarak = pCreature->GetGUID(); break; - case 28730: uiWatcherGashra = pCreature->GetGUID(); break; - case 28731: uiWatcherSilthik = pCreature->GetGUID(); break; - case 28729: uiWatcherNarjil = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch (pGo->GetEntry()) - { - case 192395: - uiKrikthirDoor = pGo->GetGUID(); - if (auiEncounter[0] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 192396: - uiAnubarakDoor[0] = pGo->GetGUID(); - break; - case 192397: - uiAnubarakDoor[1] = pGo->GetGUID(); - break; - case 192398: - uiAnubarakDoor[2] = pGo->GetGUID(); - break; - } - } - - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_KRIKTHIR_THE_GATEWATCHER: return uiKrikthir; - case DATA_HADRONOX: return uiHadronox; - case DATA_ANUBARAK: return uiAnubarak; - case DATA_WATCHER_GASHRA: return uiWatcherGashra; - case DATA_WATCHER_SILTHIK: return uiWatcherSilthik; - case DATA_WATCHER_NARJIL: return uiWatcherNarjil; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: - auiEncounter[0] = data; - if (data == DONE) - HandleGameObject(uiKrikthirDoor,true); - break; - case DATA_HADRONOX_EVENT: - auiEncounter[1] = data; - break; - case DATA_ANUBARAK_EVENT: - auiEncounter[2] = data; - if (data == IN_PROGRESS) - for (uint8 i = 0; i < 3; ++i) - HandleGameObject(uiAnubarakDoor[i], false); - else if (data == NOT_STARTED || data == DONE) - for (uint8 i = 0; i < 3; ++i) - HandleGameObject(uiAnubarakDoor[i], true); - break; - } - - if (data == DONE) - { - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: return auiEncounter[0]; - case DATA_HADRONOX_EVENT: return auiEncounter[1]; - case DATA_ANUBARAK_EVENT: return auiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "A N " << auiEncounter[0] << " " << auiEncounter[1] << " " - << auiEncounter[2]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0,data1,data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'A' && dataHead2 == 'N') - { - auiEncounter[0] = data0; - auiEncounter[1] = data1; - auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (auiEncounter[i] == IN_PROGRESS) - auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_azjol_nerub(Map* pMap) -{ - return new instance_azjol_nerub(pMap); -} - -void AddSC_instance_azjol_nerub() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_azjol_nerub"; - newscript->GetInstanceData = &GetInstanceData_instance_azjol_nerub; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp deleted file mode 100644 index c33ea69fa2d..00000000000 --- a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Argent Challenge Encounter. -SD%Complete: 50 % -SDComment: AI for Argent Soldiers are not implemented. AI from bosses need more improvements. -SDCategory: Trial of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" -#include "ScriptedEscortAI.h" - -enum eSpells -{ - //Eadric - SPELL_EADRIC_ACHIEVEMENT = 68197, - SPELL_HAMMER_JUSTICE = 66863, - SPELL_HAMMER_RIGHTEOUS = 66867, - SPELL_RADIANCE = 66935, - SPELL_VENGEANCE = 66865, - - //Paletress - SPELL_SMITE = 66536, - SPELL_SMITE_H = 67674, - SPELL_HOLY_FIRE = 66538, - SPELL_HOLY_FIRE_H = 67676, - SPELL_RENEW = 66537, - SPELL_RENEW_H = 67675, - SPELL_HOLY_NOVA = 66546, - SPELL_SHIELD = 66515, - SPELL_CONFESS = 66680, - SPELL_SUMMON_MEMORY = 66545, - - //Memory - SPELL_OLD_WOUNDS = 66620, - SPELL_OLD_WOUNDS_H = 67679, - SPELL_SHADOWS_PAST = 66619, - SPELL_SHADOWS_PAST_H = 67678, - SPELL_WAKING_NIGHTMARE = 66552, - SPELL_WAKING_NIGHTMARE_H = 67677 -}; - -struct boss_eadricAI : public ScriptedAI -{ - boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - pCreature->SetReactState(REACT_PASSIVE); - pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint32 uiVenganceTimer; - uint32 uiRadianceTimer; - uint32 uiHammerJusticeTimer; - uint32 uiResetTimer; - - bool bDone; - - void Reset() - { - uiVenganceTimer = 10000; - uiRadianceTimer = 16000; - uiHammerJusticeTimer = 25000; - uiResetTimer = 5000; - - bDone = false; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - damage = 0; - EnterEvadeMode(); - me->setFaction(35); - bDone = true; - } - } - - void MovementInform(uint32 MovementType, uint32 /*Data*/) - { - if (MovementType != POINT_MOTION_TYPE) - return; - - if (pInstance) - pInstance->SetData(BOSS_ARGENT_CHALLENGE_E, DONE); - - me->DisappearAndDie(); - } - - void UpdateAI(const uint32 uiDiff) - { - if (bDone && uiResetTimer <= uiDiff) - { - me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); - bDone = false; - } else uiResetTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - if (uiHammerJusticeTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - { - DoCast(pTarget, SPELL_HAMMER_JUSTICE); - DoCast(pTarget, SPELL_HAMMER_RIGHTEOUS); - } - } - uiHammerJusticeTimer = 25000; - } else uiHammerJusticeTimer -= uiDiff; - - if (uiVenganceTimer <= uiDiff) - { - DoCast(me,SPELL_VENGEANCE); - - uiVenganceTimer = 10000; - } else uiVenganceTimer -= uiDiff; - - if (uiRadianceTimer <= uiDiff) - { - DoCastAOE(SPELL_RADIANCE); - - uiRadianceTimer = 16000; - } else uiRadianceTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_eadric(Creature* pCreature) -{ - return new boss_eadricAI(pCreature); -} - -struct boss_paletressAI : public ScriptedAI -{ - boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - MemoryGUID = 0; - pCreature->SetReactState(REACT_PASSIVE); - pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pCreature->RestoreFaction(); - } - - ScriptedInstance* pInstance; - - Creature* pMemory; - uint64 MemoryGUID; - - bool bHealth; - bool bDone; - - uint32 uiHolyFireTimer; - uint32 uiHolySmiteTimer; - uint32 uiRenewTimer; - uint32 uiResetTimer; - - void Reset() - { - me->RemoveAllAuras(); - - uiHolyFireTimer = urand(9000,12000); - uiHolySmiteTimer = urand(5000,7000); - uiRenewTimer = urand(2000,5000); - - uiResetTimer = 7000; - - bHealth = false; - bDone = false; - - if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) - if (pMemory->isAlive()) - pMemory->RemoveFromWorld(); - } - - void SetData(uint32 uiId, uint32 /*uiValue*/) - { - if (uiId == 1) - me->RemoveAura(SPELL_SHIELD); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - damage = 0; - EnterEvadeMode(); - me->setFaction(35); - bDone = true; - } - } - - void MovementInform(uint32 MovementType, uint32 Point) - { - if (MovementType != POINT_MOTION_TYPE || Point != 0) - return; - - if (pInstance) - pInstance->SetData(BOSS_ARGENT_CHALLENGE_P, DONE); - - me->DisappearAndDie(); - } - - void UpdateAI(const uint32 uiDiff) - { - if (bDone && uiResetTimer <= uiDiff) - { - me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); - bDone = false; - } else uiResetTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - if (uiHolyFireTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_HOLY_FIRE); - } - if (me->HasAura(SPELL_SHIELD)) - uiHolyFireTimer = 13000; - else - uiHolyFireTimer = urand(9000,12000); - } else uiHolyFireTimer -= uiDiff; - - if (uiHolySmiteTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_SMITE); - } - if (me->HasAura(SPELL_SHIELD)) - uiHolySmiteTimer = 9000; - else - uiHolySmiteTimer = urand(5000,7000); - } else uiHolySmiteTimer -= uiDiff; - - if (me->HasAura(SPELL_SHIELD)) - if (uiRenewTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - uint8 uiTarget = urand(0,1); - switch(uiTarget) - { - case 0: - DoCast(me,SPELL_RENEW); - break; - case 1: - if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) - if (pMemory->isAlive()) - DoCast(pMemory, SPELL_RENEW); - break; - } - uiRenewTimer = urand(15000,17000); - } else uiRenewTimer -= uiDiff; - - - if (!bHealth && me->GetHealth()*100 / me->GetMaxHealth() <= 25) - { - me->InterruptNonMeleeSpells(true); - DoCastAOE(SPELL_HOLY_NOVA,false); - DoCast(me, SPELL_SHIELD); - DoCastAOE(SPELL_SUMMON_MEMORY,false); - DoCastAOE(SPELL_CONFESS,false); - - bHealth = true; - } - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* pSummon) - { - MemoryGUID = pSummon->GetGUID(); - } -}; - -CreatureAI* GetAI_boss_paletress(Creature* pCreature) -{ - return new boss_paletressAI(pCreature); -} - -struct npc_memoryAI : public ScriptedAI -{ - npc_memoryAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiOldWoundsTimer; - uint32 uiShadowPastTimer; - uint32 uiWakingNightmare; - - void Reset() - { - uiOldWoundsTimer = 12000; - uiShadowPastTimer = 5000; - uiWakingNightmare = 7000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiOldWoundsTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, SPELL_OLD_WOUNDS); - } - uiOldWoundsTimer = 12000; - }else uiOldWoundsTimer -= uiDiff; - - if (uiWakingNightmare <= uiDiff) - { - DoCast(me, SPELL_WAKING_NIGHTMARE); - uiWakingNightmare = 7000; - }else uiWakingNightmare -= uiDiff; - - if (uiShadowPastTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_SHADOWS_PAST); - } - uiShadowPastTimer = 5000; - }else uiShadowPastTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (me->isSummon()) - { - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - { - if (pSummoner && pSummoner->isAlive()) - CAST_CRE(pSummoner)->AI()->SetData(1,0); - } - } - } -}; - -CreatureAI* GetAI_npc_memory(Creature* pCreature) -{ - return new npc_memoryAI(pCreature); -} - -// THIS AI NEEDS MORE IMPROVEMENTS -struct npc_argent_soldierAI : public npc_escortAI -{ - npc_argent_soldierAI(Creature* pCreature) : npc_escortAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - me->SetReactState(REACT_DEFENSIVE); - SetDespawnAtEnd(false); - uiWaypoint = 0; - } - - ScriptedInstance* pInstance; - - uint8 uiWaypoint; - - void WaypointReached(uint32 uiPoint) - { - if (uiPoint == 0) - { - switch(uiWaypoint) - { - case 0: - me->SetOrientation(5.81); - break; - case 1: - me->SetOrientation(4.60); - break; - case 2: - me->SetOrientation(2.79); - break; - } - - me->SendMovementFlagUpdate(); - } - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch(me->GetEntry()) - { - case NPC_ARGENT_LIGHWIELDER: - switch(uiType) - { - case 0: - AddWaypoint(0,712.14,628.42,411.88); - break; - case 1: - AddWaypoint(0,742.44,650.29,411.79); - break; - case 2: - AddWaypoint(0,783.33,615.29,411.84); - break; - } - break; - case NPC_ARGENT_MONK: - switch(uiType) - { - case 0: - AddWaypoint(0,713.12,632.97,411.90); - break; - case 1: - AddWaypoint(0,746.73,650.24,411.56); - break; - case 2: - AddWaypoint(0,781.32,610.54,411.82); - break; - } - break; - case NPC_PRIESTESS: - switch(uiType) - { - case 0: - AddWaypoint(0,715.06,637.07,411.91); - break; - case 1: - AddWaypoint(0,750.72,650.20,411.77); - break; - case 2: - AddWaypoint(0,779.77,607.03,411.81); - break; - } - break; - } - - Start(false,true,0); - uiWaypoint = uiType; - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(DATA_ARGENT_SOLDIER_DEFEATED,pInstance->GetData(DATA_ARGENT_SOLDIER_DEFEATED) + 1); - } -}; - -CreatureAI* GetAI_npc_argent_soldier(Creature* pCreature) -{ - return new npc_argent_soldierAI(pCreature); -} - -void AddSC_boss_argent_challenge() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "boss_eadric"; - NewScript->GetAI = &GetAI_boss_eadric; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_paletress"; - NewScript->GetAI = &GetAI_boss_paletress; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_memory"; - NewScript->GetAI = &GetAI_npc_memory; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_argent_soldier"; - NewScript->GetAI = &GetAI_npc_argent_soldier; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp deleted file mode 100644 index e1f4586ca6c..00000000000 --- a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Black Knight -SD%Complete: 80% -SDComment: missing yells. not sure about timers. -SDCategory: Trial of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "trial_of_the_champion.h" - -enum eSpells -{ - //phase 1 - SPELL_PLAGUE_STRIKE = 67884, - SPELL_PLAGUE_STRIKE_2 = 67724, - SPELL_ICY_TOUCH_H = 67881, - SPELL_ICY_TOUCH = 67718, - SPELL_DEATH_RESPITE = 67745, - SPELL_DEATH_RESPITE_2 = 68306, - SPELL_DEATH_RESPITE_3 = 66798, - SPELL_OBLITERATE_H = 67883, - SPELL_OBLITERATE = 67725, - //in this phase should rise herald (the spell is missing) - - //phase 2 - During this phase, the Black Knight will use the same abilities as in phase 1, except for Death's Respite - SPELL_ARMY_DEAD = 67761, - SPELL_DESECRATION = 67778, - SPELL_DESECRATION_2 = 67778, - SPELL_GHOUL_EXPLODE = 67751, - - //phase 3 - SPELL_DEATH_BITE_H = 67875, - SPELL_DEATH_BITE = 67808, - SPELL_MARKED_DEATH = 67882, - SPELL_MARKED_DEATH_2 = 67823, - - SPELL_BLACK_KNIGHT_RES = 67693, - - SPELL_LEAP = 67749, - SPELL_LEAP_H = 67880 -}; - -enum eModels -{ - MODEL_SKELETON = 29846, - MODEL_GHOST = 21300 -}; - -enum ePhases -{ - PHASE_UNDEAD = 1, - PHASE_SKELETON = 2, - PHASE_GHOST = 3 -}; - -struct boss_black_knightAI : public ScriptedAI -{ - boss_black_knightAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - std::list SummonList; - - bool bEventInProgress; - bool bEvent; - bool bSummonArmy; - bool bDeathArmyDone; - - uint8 uiPhase; - - uint32 uiPlagueStrikeTimer; - uint32 uiIcyTouchTimer; - uint32 uiDeathRespiteTimer; - uint32 uiObliterateTimer; - uint32 uiDesecration; - uint32 uiResurrectTimer; - uint32 uiDeathArmyCheckTimer; - uint32 uiGhoulExplodeTimer; - uint32 uiDeathBiteTimer; - uint32 uiMarkedDeathTimer; - - void Reset() - { - RemoveSummons(); - me->SetDisplayId(me->GetNativeDisplayId()); - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - - bEventInProgress = false; - bEvent = false; - bSummonArmy = false; - bDeathArmyDone = false; - - uiPhase = PHASE_UNDEAD; - - uiIcyTouchTimer = urand(5000,9000); - uiPlagueStrikeTimer = urand(10000,13000); - uiDeathRespiteTimer = urand(15000,16000); - uiObliterateTimer = urand(17000,19000); - uiDesecration = urand(15000,16000); - uiDeathArmyCheckTimer = 7000; - uiResurrectTimer = 4000; - uiGhoulExplodeTimer = 8000; - uiDeathBiteTimer = urand (2000,4000); - uiMarkedDeathTimer = urand (5000,7000); - } - - void RemoveSummons() - { - if (SummonList.empty()) - return; - - for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - if (pTemp) - pTemp->DisappearAndDie(); - } - SummonList.clear(); - } - - void JustSummoned(Creature* pSummon) - { - SummonList.push_back(pSummon->GetGUID()); - pSummon->AI()->AttackStart(me->getVictim()); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (bEventInProgress) - if (uiResurrectTimer <= uiDiff) - { - me->SetHealth(me->GetMaxHealth()); - DoCast(me,SPELL_BLACK_KNIGHT_RES,true); - uiPhase++; - uiResurrectTimer = 4000; - bEventInProgress = false; - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - } else uiResurrectTimer -= uiDiff; - - switch(uiPhase) - { - case PHASE_UNDEAD: - case PHASE_SKELETON: - { - if (uiIcyTouchTimer <= uiDiff) - { - DoCastVictim(SPELL_ICY_TOUCH); - uiIcyTouchTimer = urand(5000,7000); - } else uiIcyTouchTimer -= uiDiff; - if (uiPlagueStrikeTimer <= uiDiff) - { - DoCastVictim(SPELL_ICY_TOUCH); - uiPlagueStrikeTimer = urand(12000,15000); - } else uiPlagueStrikeTimer -= uiDiff; - if (uiObliterateTimer <= uiDiff) - { - DoCastVictim(SPELL_OBLITERATE); - uiObliterateTimer = urand(17000,19000); - } else uiObliterateTimer -= uiDiff; - switch(uiPhase) - { - case PHASE_UNDEAD: - { - if (uiDeathRespiteTimer <= uiDiff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_DEATH_RESPITE); - } - uiDeathRespiteTimer = urand(15000,16000); - } else uiDeathRespiteTimer -= uiDiff; - break; - } - case PHASE_SKELETON: - { - if (!bSummonArmy) - { - bSummonArmy = true; - me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - DoCast(me, SPELL_ARMY_DEAD); - } - if (!bDeathArmyDone) - if (uiDeathArmyCheckTimer <= uiDiff) - { - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - uiDeathArmyCheckTimer = 0; - bDeathArmyDone = true; - } else uiDeathArmyCheckTimer -= uiDiff; - if (uiDesecration <= uiDiff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_DESECRATION); - } - uiDesecration = urand(15000,16000); - } else uiDesecration -= uiDiff; - if (uiGhoulExplodeTimer <= uiDiff) - { - DoCast(me, SPELL_GHOUL_EXPLODE); - uiGhoulExplodeTimer = 8000; - } else uiGhoulExplodeTimer -= uiDiff; - break; - } - break; - } - break; - } - case PHASE_GHOST: - { - if (uiDeathBiteTimer <= uiDiff) - { - DoCastAOE(SPELL_DEATH_BITE); - uiDeathBiteTimer = urand (2000, 4000); - } else uiDeathBiteTimer -= uiDiff; - if (uiMarkedDeathTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_MARKED_DEATH); - } - uiMarkedDeathTimer = urand (5000, 7000); - } else uiMarkedDeathTimer -= uiDiff; - break; - } - } - - if (!me->hasUnitState(UNIT_STAT_ROOT) && !me->GetHealth()*100 / me->GetMaxHealth() <= 0) - DoMeleeAttackIfReady(); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) - { - if (uiDamage > me->GetHealth() && uiPhase <= PHASE_SKELETON) - { - uiDamage = 0; - me->SetHealth(0); - me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - RemoveSummons(); - switch(uiPhase) - { - case PHASE_UNDEAD: - me->SetDisplayId(MODEL_SKELETON); - break; - case PHASE_SKELETON: - me->SetDisplayId(MODEL_GHOST); - break; - } - bEventInProgress = true; - } - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_BLACK_KNIGHT,DONE); - } -}; - -CreatureAI* GetAI_boss_black_knight(Creature *pCreature) -{ - return new boss_black_knightAI (pCreature); -} - -struct npc_risen_ghoulAI : public ScriptedAI -{ - npc_risen_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiAttackTimer; - - void Reset() - { - uiAttackTimer = 3500; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiAttackTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, (SPELL_LEAP)); - } - uiAttackTimer = 3500; - } else uiAttackTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_risen_ghoul(Creature* pCreature) -{ - return new npc_risen_ghoulAI(pCreature); -} - -struct npc_black_knight_skeletal_gryphonAI : public npc_escortAI -{ - npc_black_knight_skeletal_gryphonAI(Creature* pCreature) : npc_escortAI(pCreature) - { - Start(false,true,0,NULL); - } - - void WaypointReached(uint32 /*i*/) - { - - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - } - -}; - -CreatureAI* GetAI_npc_black_knight_skeletal_gryphon(Creature* pCreature) -{ - return new npc_black_knight_skeletal_gryphonAI(pCreature); -} - -void AddSC_boss_black_knight() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "boss_black_knight"; - NewScript->GetAI = &GetAI_boss_black_knight; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_risen_ghoul"; - NewScript->GetAI = &GetAI_npc_risen_ghoul; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_black_knight_skeletal_gryphon"; - NewScript->GetAI = &GetAI_npc_black_knight_skeletal_gryphon; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp deleted file mode 100644 index 4bf8143a210..00000000000 --- a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp +++ /dev/null @@ -1,993 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: boss_grand_champions -SD%Complete: 50 % -SDComment: Is missing the ai to make the npcs look for a new mount and use it. -SDCategory: Trial Of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "Vehicle.h" -#include "trial_of_the_champion.h" - -enum eSpells -{ - //Vehicle - SPELL_CHARGE = 63010, - SPELL_SHIELD_BREAKER = 68504, - SPELL_SHIELD = 66482, - - // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior - SPELL_MORTAL_STRIKE = 68783, - SPELL_MORTAL_STRIKE_H = 68784, - SPELL_BLADESTORM = 63784, - SPELL_INTERCEPT = 67540, - SPELL_ROLLING_THROW = 47115, //not implemented in the AI yet... - - // Ambrose Boltspark && Eressea Dawnsinger || Mage - SPELL_FIREBALL = 66042, - SPELL_FIREBALL_H = 68310, - SPELL_BLAST_WAVE = 66044, - SPELL_BLAST_WAVE_H = 68312, - SPELL_HASTE = 66045, - SPELL_POLYMORPH = 66043, - SPELL_POLYMORPH_H = 68311, - - // Colosos && Runok Wildmane || Shaman - SPELL_CHAIN_LIGHTNING = 67529, - SPELL_CHAIN_LIGHTNING_H = 68319, - SPELL_EARTH_SHIELD = 67530, - SPELL_HEALING_WAVE = 67528, - SPELL_HEALING_WAVE_H = 68318, - SPELL_HEX_OF_MENDING = 67534, - - // Jaelyne Evensong && Zul'tore || Hunter - SPELL_DISENGAGE = 68340, //not implemented in the AI yet... - SPELL_LIGHTNING_ARROWS = 66083, - SPELL_MULTI_SHOT = 66081, - SPELL_SHOOT = 65868, - SPELL_SHOOT_H = 67988, - - // Lana Stouthammer Evensong && Deathstalker Visceri || Rouge - SPELL_EVISCERATE = 67709, - SPELL_EVISCERATE_H = 68317, - SPELL_FAN_OF_KNIVES = 67706, - SPELL_POISON_BOTTLE = 67701 -}; - -enum eSeat -{ - SEAT_ID_0 = 0 -}; - -struct Point -{ - float x,y,z; -}; - -const Point MovementPoint[] = -{ - {746.84,623.15,411.41}, - {747.96,620.29,411.09}, - {750.23,618.35,411.09} -}; - -void AggroAllPlayers(Creature* pTemp) -{ - Map::PlayerList const &PlList = pTemp->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - pTemp->SetReactState(REACT_AGGRESSIVE); - pTemp->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(pTemp); - pTemp->AddThreat(pPlayer, 0.0f); - } - } - } -} - -bool GrandChampionsOutVehicle(Creature* me) -{ - ScriptedInstance* pInstance = me->GetInstanceData(); - - if (!pInstance) - return false; - - Creature* pGrandChampion1 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_1)); - Creature* pGrandChampion2 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_2)); - Creature* pGrandChampion3 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_3)); - - if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) - { - if (!pGrandChampion1->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && - !pGrandChampion2->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && - !pGrandChampion3->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return true; - } - - return false; -} - -/* -* Generic AI for vehicles used by npcs in ToC, it needs more improvements. * -* Script Complete: 25%. * -*/ - -struct generic_vehicleAI_toc5AI : public npc_escortAI -{ - generic_vehicleAI_toc5AI(Creature* pCreature) : npc_escortAI(pCreature) - { - SetDespawnAtEnd(false); - uiWaypointPath = 0; - - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiChargeTimer; - uint32 uiShieldBreakerTimer; - uint32 uiBuffTimer; - - uint32 uiWaypointPath; - - void Reset() - { - uiChargeTimer = 5000; - uiShieldBreakerTimer = 8000; - uiBuffTimer = urand(30000,60000); - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch(uiType) - { - case 1: - AddWaypoint(0,747.36,634.07,411.572); - AddWaypoint(1,780.43,607.15,411.82); - AddWaypoint(2,785.99,599.41,411.92); - AddWaypoint(3,778.44,601.64,411.79); - uiWaypointPath = 1; - break; - case 2: - AddWaypoint(0,747.35,634.07,411.57); - AddWaypoint(1,768.72,581.01,411.92); - AddWaypoint(2,763.55,590.52,411.71); - uiWaypointPath = 2; - break; - case 3: - AddWaypoint(0,747.35,634.07,411.57); - AddWaypoint(1,784.02,645.33,412.39); - AddWaypoint(2,775.67,641.91,411.91); - uiWaypointPath = 3; - break; - } - - if (uiType <= 3) - Start(false,true,0,NULL); - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 2: - if (pInstance && uiWaypointPath == 3 || uiWaypointPath == 2) - pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); - break; - case 3: - if (pInstance) - pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); - break; - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoCastSpellShield(); - } - - void DoCastSpellShield() - { - for (uint8 i = 0; i < 3; ++i) - DoCast(me,SPELL_SHIELD,true); - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - if (uiBuffTimer <= uiDiff) - { - if (!me->HasAura(SPELL_SHIELD)) - DoCastSpellShield(); - - uiBuffTimer = urand(30000,45000); - }else uiBuffTimer -= uiDiff; - - if (uiChargeTimer <= uiDiff) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) - { - DoResetThreat(); - me->AddThreat(pPlayer,1.0f); - DoCast(pPlayer, SPELL_CHARGE); - break; - } - } - } - uiChargeTimer = 5000; - }else uiChargeTimer -= uiDiff; - - //dosen't work at all - if (uiShieldBreakerTimer <= uiDiff) - { - Vehicle *pVehicle = me->GetVehicleKit(); - if (!pVehicle) - return; - - if (Unit* pPassenger = pVehicle->GetPassenger(SEAT_ID_0)) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,10.0f,30.0f,false)) - { - pPassenger->CastSpell(pPlayer,SPELL_SHIELD_BREAKER,true); - break; - } - } - } - } - uiShieldBreakerTimer = 7000; - }else uiShieldBreakerTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_generic_vehicleAI_toc5(Creature* pCreature) -{ - return new generic_vehicleAI_toc5AI(pCreature); -} - -// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior -struct boss_warrior_toc5AI : public ScriptedAI -{ - boss_warrior_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiBladeStormTimer; - uint32 uiInterceptTimer; - uint32 uiMortalStrikeTimer; - uint32 uiAttackTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiBladeStormTimer = urand(15000,20000); - uiInterceptTimer = 7000; - uiMortalStrikeTimer = urand(8000,12000); - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiInterceptTimer <= uiDiff) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) - { - DoResetThreat(); - me->AddThreat(pPlayer,5.0f); - DoCast(pPlayer,SPELL_INTERCEPT); - break; - } - } - } - uiInterceptTimer = 7000; - } else uiInterceptTimer -= uiDiff; - - if (uiBladeStormTimer <= uiDiff) - { - DoCastVictim(SPELL_BLADESTORM); - uiBladeStormTimer = urand(15000,20000); - } else uiBladeStormTimer -= uiDiff; - - if (uiMortalStrikeTimer <= uiDiff) - { - DoCastVictim(SPELL_MORTAL_STRIKE); - uiMortalStrikeTimer = urand(8000,12000); - } else uiMortalStrikeTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_warrior_toc5(Creature* pCreature) -{ - return new boss_warrior_toc5AI(pCreature); -} - -// Ambrose Boltspark && Eressea Dawnsinger || Mage -struct boss_mage_toc5AI : public ScriptedAI -{ - boss_mage_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiFireBallTimer; - uint32 uiBlastWaveTimer; - uint32 uiHasteTimer; - uint32 uiPolymorphTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiFireBallTimer = 5000; - uiPolymorphTimer = 8000; - uiBlastWaveTimer = 12000; - uiHasteTimer = 22000; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (uiFireBallTimer <= uiDiff) - { - if (me->getVictim()) - DoCastVictim(SPELL_FIREBALL); - uiFireBallTimer = 5000; - } else uiFireBallTimer -= uiDiff; - - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiFireBallTimer <= uiDiff) - { - DoCastVictim(SPELL_FIREBALL); - uiFireBallTimer = 5000; - } else uiFireBallTimer -= uiDiff; - - if (uiPolymorphTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_POLYMORPH); - uiPolymorphTimer = 8000; - } else uiPolymorphTimer -= uiDiff; - - if (uiBlastWaveTimer <= uiDiff) - { - DoCastAOE(SPELL_BLAST_WAVE,false); - uiBlastWaveTimer = 13000; - } else uiBlastWaveTimer -= uiDiff; - - if (uiHasteTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - - DoCast(me,SPELL_HASTE); - uiHasteTimer = 22000; - } else uiHasteTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_mage_toc5(Creature* pCreature) -{ - return new boss_mage_toc5AI(pCreature); -} - -// Colosos && Runok Wildmane || Shaman -struct boss_shaman_toc5AI : public ScriptedAI -{ - boss_shaman_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiChainLightningTimer; - uint32 uiEartShieldTimer; - uint32 uiHealingWaveTimer; - uint32 uiHexMendingTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiChainLightningTimer = 16000; - uiHealingWaveTimer = 12000; - uiEartShieldTimer = urand(30000,35000); - uiHexMendingTimer = urand(20000,25000); - } - - void EnterCombat(Unit* pWho) - { - DoCast(me,SPELL_EARTH_SHIELD); - DoCast(pWho,SPELL_HEX_OF_MENDING); - }; - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiChainLightningTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget,SPELL_CHAIN_LIGHTNING); - - uiChainLightningTimer = 16000; - } else uiChainLightningTimer -= uiDiff; - - if (uiHealingWaveTimer <= uiDiff) - { - bool bChance = urand(0,1); - - if (!bChance) - { - if (Unit* pFriend = DoSelectLowestHpFriendly(40)) - DoCast(pFriend,SPELL_HEALING_WAVE); - } else - DoCast(me,SPELL_HEALING_WAVE); - - uiHealingWaveTimer = 12000; - } else uiHealingWaveTimer -= uiDiff; - - if (uiEartShieldTimer <= uiDiff) - { - DoCast(me,SPELL_EARTH_SHIELD); - - uiEartShieldTimer = urand(30000,35000); - } else uiEartShieldTimer -= uiDiff; - - if (uiHexMendingTimer <= uiDiff) - { - DoCastVictim(SPELL_HEX_OF_MENDING,true); - - uiHexMendingTimer = urand(20000,25000); - } else uiHexMendingTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_shaman_toc5(Creature* pCreature) -{ - return new boss_shaman_toc5AI(pCreature); -} - -// Jaelyne Evensong && Zul'tore || Hunter -struct boss_hunter_toc5AI : public ScriptedAI -{ - boss_hunter_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiShootTimer; - uint32 uiMultiShotTimer; - uint32 uiLightningArrowsTimer; - - uint64 uiTargetGUID; - - bool bShoot; - bool bDone; - bool bHome; - - void Reset() - { - uiShootTimer = 12000; - uiMultiShotTimer = 0; - uiLightningArrowsTimer = 7000; - - uiTargetGUID = 0; - - bShoot = false; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiLightningArrowsTimer <= uiDiff) - { - DoCastAOE(SPELL_LIGHTNING_ARROWS,false); - uiLightningArrowsTimer = 7000; - } else uiLightningArrowsTimer -= uiDiff; - - if (uiShootTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_FARTHEST,0,30.0f)) - { - uiTargetGUID = pTarget->GetGUID(); - DoCast(pTarget, SPELL_SHOOT); - } - uiShootTimer = 12000; - uiMultiShotTimer = 3000; - bShoot = true; - } else uiShootTimer -= uiDiff; - - if (bShoot && uiMultiShotTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - Unit* pTarget = Unit::GetUnit(*me, uiTargetGUID); - - if (pTarget && me->IsInRange(pTarget,5.0f,30.0f,false)) - { - DoCast(pTarget,SPELL_MULTI_SHOT); - } else - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,5.0f,30.0f,false)) - { - DoCast(pTarget,SPELL_MULTI_SHOT); - break; - } - } - } - } - bShoot = false; - } else uiMultiShotTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_hunter_toc5(Creature* pCreature) -{ - return new boss_hunter_toc5AI(pCreature); -} - -// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge -struct boss_rouge_toc5AI : public ScriptedAI -{ - boss_rouge_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - uint32 uiEviscerateTimer; - uint32 uiFanKivesTimer; - uint32 uiPosionBottleTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiEviscerateTimer = 8000; - uiFanKivesTimer = 14000; - uiPosionBottleTimer = 19000; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - } else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiEviscerateTimer <= uiDiff) - { - DoCast(me->getVictim(),SPELL_EVISCERATE); - uiEviscerateTimer = 8000; - } else uiEviscerateTimer -= uiDiff; - - if (uiFanKivesTimer <= uiDiff) - { - DoCastAOE(SPELL_FAN_OF_KNIVES,false); - uiFanKivesTimer = 14000; - } else uiFanKivesTimer -= uiDiff; - - if (uiPosionBottleTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget,SPELL_POISON_BOTTLE); - uiPosionBottleTimer = 19000; - } else uiPosionBottleTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_rouge_toc5(Creature* pCreature) -{ - return new boss_rouge_toc5AI(pCreature); -} - -void AddSC_boss_grand_champions() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "generic_vehicleAI_toc5"; - NewScript->GetAI = &GetAI_generic_vehicleAI_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_warrior_toc5"; - NewScript->GetAI = &GetAI_boss_warrior_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_mage_toc5"; - NewScript->GetAI = &GetAI_boss_mage_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_shaman_toc5"; - NewScript->GetAI = &GetAI_boss_shaman_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_hunter_toc5"; - NewScript->GetAI = &GetAI_boss_hunter_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_rouge_toc5"; - NewScript->GetAI = &GetAI_boss_rouge_toc5; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp deleted file mode 100644 index 04b671ec11c..00000000000 --- a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* ScriptData -SDName: Instance Trial of the Champion -SDComment: -SDCategory: Trial Of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" - -#define MAX_ENCOUNTER 4 - -struct instance_trial_of_the_champion : public ScriptedInstance -{ - instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint8 uiMovementDone; - uint8 uiGrandChampionsDeaths; - uint8 uiArgentSoldierDeaths; - - uint64 uiAnnouncerGUID; - uint64 uiMainGateGUID; - uint64 uiGrandChampionVehicle1GUID; - uint64 uiGrandChampionVehicle2GUID; - uint64 uiGrandChampionVehicle3GUID; - uint64 uiGrandChampion1GUID; - uint64 uiGrandChampion2GUID; - uint64 uiGrandChampion3GUID; - uint64 uiChampionLootGUID; - uint64 uiArgentChampionGUID; - - std::list VehicleList; - - std::string str_data; - - bool bDone; - - void Initialize() - { - uiMovementDone = 0; - uiGrandChampionsDeaths = 0; - uiArgentSoldierDeaths = 0; - - uiAnnouncerGUID = 0; - uiMainGateGUID = 0; - uiGrandChampionVehicle1GUID = 0; - uiGrandChampionVehicle2GUID = 0; - uiGrandChampionVehicle3GUID = 0; - uiGrandChampion1GUID = 0; - uiGrandChampion2GUID = 0; - uiGrandChampion3GUID = 0; - uiChampionLootGUID = 0; - uiArgentChampionGUID = 0; - - bDone = false; - - VehicleList.clear(); - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - } - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - uint32 TeamInInstance = 0; - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - TeamInInstance = pPlayer->GetTeam(); - } - - switch(pCreature->GetEntry()) - { - // Champions - case VEHICLE_MOKRA_SKILLCRUSHER_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT, ALLIANCE); - break; - case VEHICLE_ERESSEA_DAWNSINGER_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_AMBROSE_BOLTSPARK_MOUNT, ALLIANCE); - break; - case VEHICLE_RUNOK_WILDMANE_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_COLOSOS_MOUNT, ALLIANCE); - break; - case VEHICLE_ZUL_TORE_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_EVENSONG_MOUNT, ALLIANCE); - break; - case VEHICLE_DEATHSTALKER_VESCERI_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_LANA_STOUTHAMMER_MOUNT, ALLIANCE); - break; - // Coliseum Announcer || Just NPC_JAEREN must be spawned. - case NPC_JAEREN: - uiAnnouncerGUID = pCreature->GetGUID(); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_ARELAS,ALLIANCE); - break; - case VEHICLE_ARGENT_WARHORSE: - case VEHICLE_ARGENT_BATTLEWORG: - VehicleList.push_back(pCreature->GetGUID()); - break; - case NPC_EADRIC: - case NPC_PALETRESS: - uiArgentChampionGUID = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGO, bool /*bAdd*/) - { - switch(pGO->GetEntry()) - { - case GO_MAIN_GATE: - uiMainGateGUID = pGO->GetGUID(); - break; - case GO_CHAMPIONS_LOOT: - case GO_CHAMPIONS_LOOT_H: - uiChampionLootGUID = pGO->GetGUID(); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case DATA_MOVEMENT_DONE: - uiMovementDone = uiData; - if (uiMovementDone == 3) - { - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - pAnnouncer->AI()->SetData(DATA_IN_POSITION,0); - } - break; - case BOSS_GRAND_CHAMPIONS: - m_auiEncounter[0] = uiData; - if (uiData == IN_PROGRESS) - { - for (std::list::const_iterator itr = VehicleList.begin(); itr != VehicleList.end(); ++itr) - if (Creature* pSummon = instance->GetCreature(*itr)) - pSummon->RemoveFromWorld(); - }else if (uiData == DONE) - { - ++uiGrandChampionsDeaths; - if (uiGrandChampionsDeaths == 3) - { - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - } - } - break; - case DATA_ARGENT_SOLDIER_DEFEATED: - uiArgentSoldierDeaths = uiData; - if (uiArgentSoldierDeaths == 9) - { - if (Creature* pBoss = instance->GetCreature(uiArgentChampionGUID)) - { - pBoss->GetMotionMaster()->MovePoint(0,746.88,618.74,411.06); - pBoss->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pBoss->SetReactState(REACT_AGGRESSIVE); - } - } - break; - case BOSS_ARGENT_CHALLENGE_E: - m_auiEncounter[1] = uiData; - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - break; - case BOSS_ARGENT_CHALLENGE_P: - m_auiEncounter[2] = uiData; - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - break; - } - - if (uiData == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 uiData) - { - switch(uiData) - { - case BOSS_GRAND_CHAMPIONS: return m_auiEncounter[0]; - case BOSS_ARGENT_CHALLENGE_E: return m_auiEncounter[1]; - case BOSS_ARGENT_CHALLENGE_P: return m_auiEncounter[2]; - case BOSS_BLACK_KNIGHT: return m_auiEncounter[3]; - - case DATA_MOVEMENT_DONE: return uiMovementDone; - case DATA_ARGENT_SOLDIER_DEFEATED: return uiArgentSoldierDeaths; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_ANNOUNCER: return uiAnnouncerGUID; - case DATA_MAIN_GATE: return uiMainGateGUID; - - case DATA_GRAND_CHAMPION_1: return uiGrandChampion1GUID; - case DATA_GRAND_CHAMPION_2: return uiGrandChampion2GUID; - case DATA_GRAND_CHAMPION_3: return uiGrandChampion3GUID; - } - - return 0; - } - - void SetData64(uint32 uiType, uint64 uiData) - { - switch(uiType) - { - case DATA_GRAND_CHAMPION_1: - uiGrandChampion1GUID = uiData; - break; - case DATA_GRAND_CHAMPION_2: - uiGrandChampion2GUID = uiData; - break; - case DATA_GRAND_CHAMPION_3: - uiGrandChampion3GUID = uiData; - break; - } - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - saveStream << "T C " << m_auiEncounter[0] - << " " << m_auiEncounter[1] - << " " << m_auiEncounter[2] - << " " << m_auiEncounter[3] - << " " << uiGrandChampionsDeaths - << " " << uiMovementDone; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; - - if (dataHead1 == 'T' && dataHead2 == 'C') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiGrandChampionsDeaths = data4; - uiMovementDone = data5; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_trial_of_the_champion(Map* pMap) -{ - return new instance_trial_of_the_champion(pMap); -} - -void AddSC_instance_trial_of_the_champion() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_trial_of_the_champion"; - newscript->GetInstanceData = &GetInstanceData_instance_trial_of_the_champion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp deleted file mode 100644 index 090b64b96cc..00000000000 --- a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Trial Of the Champion -SD%Complete: -SDComment: -SDCategory: trial_of_the_champion -EndScriptData */ - -/* ContentData -npc_announcer_toc5 -EndContentData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" -#include "Vehicle.h" - -#define GOSSIP_START_EVENT1 "I'm ready to start challenge." -#define GOSSIP_START_EVENT2 "I'm ready for the next challenge." - -#define ORIENTATION 4.714 - -/*###### -## npc_announcer_toc5 -######*/ - -const Position SpawnPosition = {746.261,657.401,411.681,4.65}; - -struct npc_announcer_toc5AI : public ScriptedAI -{ - npc_announcer_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - uiSummonTimes = 0; - uiPosition = 0; - uiLesserChampions = 0; - - uiFirstBoss = 0; - uiSecondBoss = 0; - uiThirdBoss = 0; - - uiArgentChampion = 0; - - uiPhase = 0; - uiTimer = 0; - - uiVehicle1GUID = 0; - uiVehicle2GUID = 0; - uiVehicle3GUID = 0; - - Champion1List.clear(); - Champion2List.clear(); - Champion3List.clear(); - - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - SetGrandChampionsForEncounter(); - SetArgentChampion(); - } - - ScriptedInstance* pInstance; - - uint8 uiSummonTimes; - uint8 uiPosition; - uint8 uiLesserChampions; - - uint32 uiArgentChampion; - - uint32 uiFirstBoss; - uint32 uiSecondBoss; - uint32 uiThirdBoss; - - uint32 uiPhase; - uint32 uiTimer; - - uint64 uiVehicle1GUID; - uint64 uiVehicle2GUID; - uint64 uiVehicle3GUID; - - uint64 uiGrandChampionBoss1; - - std::list Champion1List; - std::list Champion2List; - std::list Champion3List; - - void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) - { - uiTimer = uiTimerStep; - if (bNextStep) - ++uiPhase; - else - uiPhase = uiPhaseStep; - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch (uiType) - { - case DATA_START: - DoSummonGrandChampion(uiFirstBoss); - NextStep(10000,false,1); - break; - case DATA_IN_POSITION: //movement done. - me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); - if (GameObject* pGO = GameObject::GetGameObject(*me, pInstance->GetData64(DATA_MAIN_GATE))) - pInstance->HandleGameObject(pGO->GetGUID(),false); - NextStep(10000,false,3); - break; - case DATA_LESSER_CHAMPIONS_DEFEATED: - { - ++uiLesserChampions; - std::list TempList; - if (uiLesserChampions == 3 || uiLesserChampions == 6) - { - switch(uiLesserChampions) - { - case 3: - TempList = Champion2List; - break; - case 6: - TempList = Champion3List; - break; - } - - for (std::list::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr) - if (Creature* pSummon = Unit::GetCreature(*me, *itr)) - AggroAllPlayers(pSummon); - }else if (uiLesserChampions == 9) - StartGrandChampionsAttack(); - - break; - } - } - } - - void StartGrandChampionsAttack() - { - Creature* pGrandChampion1 = Unit::GetCreature(*me, uiVehicle1GUID); - Creature* pGrandChampion2 = Unit::GetCreature(*me, uiVehicle2GUID); - Creature* pGrandChampion3 = Unit::GetCreature(*me, uiVehicle3GUID); - - if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) - { - AggroAllPlayers(pGrandChampion1); - AggroAllPlayers(pGrandChampion2); - AggroAllPlayers(pGrandChampion3); - } - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (uiPointId == 1) - { - me->SetOrientation(ORIENTATION); - me->SendMovementFlagUpdate(); - } - } - - void DoSummonGrandChampion(uint32 uiBoss) - { - ++uiSummonTimes; - uint32 VEHICLE_TO_SUMMON1 = 0; - uint32 VEHICLE_TO_SUMMON2 = 0; - switch(uiBoss) - { - case 0: - VEHICLE_TO_SUMMON1 = VEHICLE_MOKRA_SKILLCRUSHER_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_ORGRIMMAR_WOLF; - break; - case 1: - VEHICLE_TO_SUMMON1 = VEHICLE_ERESSEA_DAWNSINGER_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_SILVERMOON_HAWKSTRIDER; - break; - case 2: - VEHICLE_TO_SUMMON1 = VEHICLE_RUNOK_WILDMANE_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_THUNDER_BLUFF_KODO; - break; - case 3: - VEHICLE_TO_SUMMON1 = VEHICLE_ZUL_TORE_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_DARKSPEAR_RAPTOR; - break; - case 4: - VEHICLE_TO_SUMMON1 = VEHICLE_DEATHSTALKER_VESCERI_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_FORSAKE_WARHORSE; - break; - default: - return; - } - - if (Creature* pBoss = me->SummonCreature(VEHICLE_TO_SUMMON1,SpawnPosition)) - { - switch(uiSummonTimes) - { - case 1: - { - uiVehicle1GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss1 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle1GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss1 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_1,uiVehicle1GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_1,uiGrandChampionBoss1); - } - pBoss->AI()->SetData(1,0); - break; - } - case 2: - { - uiVehicle2GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss2 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle2GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss2 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_2,uiVehicle2GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_2,uiGrandChampionBoss2); - } - pBoss->AI()->SetData(2,0); - break; - } - case 3: - { - uiVehicle3GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss3 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle3GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss3 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_3,uiVehicle3GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_3,uiGrandChampionBoss3); - } - pBoss->AI()->SetData(3,0); - break; - } - default: - return; - } - - for (uint8 i = 0; i < 3; ++i) - { - if (Creature* pAdd = me->SummonCreature(VEHICLE_TO_SUMMON2,SpawnPosition,TEMPSUMMON_CORPSE_DESPAWN)) - { - switch(uiSummonTimes) - { - case 1: - Champion1List.push_back(pAdd->GetGUID()); - break; - case 2: - Champion2List.push_back(pAdd->GetGUID()); - break; - case 3: - Champion3List.push_back(pAdd->GetGUID()); - break; - } - - switch(i) - { - case 0: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI); - break; - case 1: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2); - break; - case 2: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2 + M_PI); - break; - } - } - - } - } - } - - void DoStartArgentChampionEncounter() - { - me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); - - if (Creature* pBoss = me->SummonCreature(uiArgentChampion,SpawnPosition)) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_LIGHWIELDER,SpawnPosition)) - pTrash->AI()->SetData(i,0); - if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_MONK,SpawnPosition)) - pTrash->AI()->SetData(i,0); - if (Creature* pTrash = me->SummonCreature(NPC_PRIESTESS,SpawnPosition)) - pTrash->AI()->SetData(i,0); - } - } - } - - void SetGrandChampionsForEncounter() - { - uiFirstBoss = urand(0,4); - - while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss) - { - uiSecondBoss = urand(0,4); - uiThirdBoss = urand(0,4); - } - } - - void SetArgentChampion() - { - uint8 uiTempBoss = urand(0,1); - - switch(uiTempBoss) - { - case 0: - uiArgentChampion = NPC_EADRIC; - break; - case 1: - uiArgentChampion = NPC_PALETRESS; - break; - } - } - - void StartEncounter() - { - if (!pInstance) - return; - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - if (pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) - { - if (pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED) - { - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) - me->AI()->SetData(DATA_START,0); - - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE) - DoStartArgentChampionEncounter(); - } - - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) - me->SummonCreature(VEHICLE_BLACK_KNIGHT,769.834,651.915,447.035,0); - } - } - - void AggroAllPlayers(Creature* pTemp) - { - Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - pTemp->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetReactState(REACT_AGGRESSIVE); - pTemp->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(pTemp); - pTemp->AddThreat(pPlayer, 0.0f); - } - } - } - } - - - void UpdateAI(const uint32 uiDiff) - { - ScriptedAI::UpdateAI(uiDiff); - - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - DoSummonGrandChampion(uiSecondBoss); - NextStep(10000,true); - break; - case 2: - DoSummonGrandChampion(uiThirdBoss); - NextStep(0,false); - break; - case 3: - if (!Champion1List.empty()) - { - for (std::list::const_iterator itr = Champion1List.begin(); itr != Champion1List.end(); ++itr) - if (Creature* pSummon = Unit::GetCreature(*me, *itr)) - AggroAllPlayers(pSummon); - NextStep(0,false); - } - break; - } - } else uiTimer -= uiDiff; - - if (!UpdateVictim()) - return; - } - - void JustSummoned(Creature* pSummon) - { - if (pInstance && pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) - { - pSummon->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pSummon->SetReactState(REACT_PASSIVE); - } - } - - void SummonedCreatureDespawn(Creature* pSummon) - { - switch(pSummon->GetEntry()) - { - case VEHICLE_DARNASSIA_NIGHTSABER: - case VEHICLE_EXODAR_ELEKK: - case VEHICLE_STORMWIND_STEED: - case VEHICLE_GNOMEREGAN_MECHANOSTRIDER: - case VEHICLE_IRONFORGE_RAM: - case VEHICLE_FORSAKE_WARHORSE: - case VEHICLE_THUNDER_BLUFF_KODO: - case VEHICLE_ORGRIMMAR_WOLF: - case VEHICLE_SILVERMOON_HAWKSTRIDER: - case VEHICLE_DARKSPEAR_RAPTOR: - me->AI()->SetData(DATA_LESSER_CHAMPIONS_DEFEATED,0); - break; - } - } -}; - -CreatureAI* GetAI_npc_announcer_toc5(Creature* pCreature) -{ - return new npc_announcer_toc5AI(pCreature); -} - -bool GossipHello_npc_announcer_toc5(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && - pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && - pInstance->GetData(BOSS_BLACK_KNIGHT) == DONE && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) - return false; - - if (pInstance && - pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED && - pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - else if (pInstance) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_announcer_toc5(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_announcer_toc5AI, pCreature->AI())->StartEncounter(); - } - - return true; -} - -void AddSC_trial_of_the_champion() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "npc_announcer_toc5"; - NewScript->GetAI = &GetAI_npc_announcer_toc5; - NewScript->pGossipHello = &GossipHello_npc_announcer_toc5; - NewScript->pGossipSelect = &GossipSelect_npc_announcer_toc5; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h b/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h deleted file mode 100644 index 221c7c0412f..00000000000 --- a/src/server/scripts/Northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_TOC_H -#define DEF_TOC_H - - -enum eData -{ - BOSS_GRAND_CHAMPIONS, - BOSS_ARGENT_CHALLENGE_E, - BOSS_ARGENT_CHALLENGE_P, - BOSS_BLACK_KNIGHT, - DATA_MOVEMENT_DONE, - DATA_LESSER_CHAMPIONS_DEFEATED, - DATA_START, - DATA_IN_POSITION, - DATA_ARGENT_SOLDIER_DEFEATED -}; - -enum Data64 -{ - DATA_ANNOUNCER, - DATA_MAIN_GATE, - - DATA_GRAND_CHAMPION_VEHICLE_1, - DATA_GRAND_CHAMPION_VEHICLE_2, - DATA_GRAND_CHAMPION_VEHICLE_3, - - DATA_GRAND_CHAMPION_1, - DATA_GRAND_CHAMPION_2, - DATA_GRAND_CHAMPION_3 -}; - -enum eNpcs -{ - // Horde Champions - NPC_MOKRA = 35572, - NPC_ERESSEA = 35569, - NPC_RUNOK = 35571, - NPC_ZULTORE = 35570, - NPC_VISCERI = 35617, - - // Alliance Champions - NPC_JACOB = 34705, - NPC_AMBROSE = 34702, - NPC_COLOSOS = 34701, - NPC_JAELYNE = 34657, - NPC_LANA = 34703, - - NPC_EADRIC = 35119, - NPC_PALETRESS = 34928, - - NPC_ARGENT_LIGHWIELDER = 35309, - NPC_ARGENT_MONK = 35305, - NPC_PRIESTESS = 35307, - - NPC_BLACK_KNIGHT = 35451, - - NPC_RISEN_JAEREN = 35545, - NPC_RISEN_ARELAS = 35564, - - NPC_JAEREN = 35004, - NPC_ARELAS = 35005 -}; - -enum eGameObjects -{ - GO_MAIN_GATE = 195647, - - GO_CHAMPIONS_LOOT = 195709, - GO_CHAMPIONS_LOOT_H = 195710, - - GO_EADRIC_LOOT = 195374, - GO_EADRIC_LOOT_H = 195375, - - GO_PALETRESS_LOOT = 195323, - GO_PALETRESS_LOOT_H = 195324 -}; - -enum eVehicles -{ - //Grand Champions Alliance Vehicles - VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT = 35637, - VEHICLE_AMBROSE_BOLTSPARK_MOUNT = 35633, - VEHICLE_COLOSOS_MOUNT = 35768, - VEHICLE_EVENSONG_MOUNT = 34658, - VEHICLE_LANA_STOUTHAMMER_MOUNT = 35636, - //Faction Champions (ALLIANCE) - VEHICLE_DARNASSIA_NIGHTSABER = 33298, - VEHICLE_EXODAR_ELEKK = 33416, - VEHICLE_STORMWIND_STEED = 33297, - VEHICLE_GNOMEREGAN_MECHANOSTRIDER = 33301, - VEHICLE_IRONFORGE_RAM = 33408, - //Grand Champions Horde Vehicles - VEHICLE_MOKRA_SKILLCRUSHER_MOUNT = 35638, - VEHICLE_ERESSEA_DAWNSINGER_MOUNT = 35635, - VEHICLE_RUNOK_WILDMANE_MOUNT = 35640, - VEHICLE_ZUL_TORE_MOUNT = 35641, - VEHICLE_DEATHSTALKER_VESCERI_MOUNT = 35634, - //Faction Champions (HORDE) - VEHICLE_FORSAKE_WARHORSE = 33414, - VEHICLE_THUNDER_BLUFF_KODO = 33300, - VEHICLE_ORGRIMMAR_WOLF = 33409, - VEHICLE_SILVERMOON_HAWKSTRIDER = 33418, - VEHICLE_DARKSPEAR_RAPTOR = 33299, - - VEHICLE_ARGENT_WARHORSE = 35644, - VEHICLE_ARGENT_BATTLEWORG = 36558, - - VEHICLE_BLACK_KNIGHT = 35491 -}; - -#endif diff --git a/src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp b/src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp deleted file mode 100644 index ba64a4748dd..00000000000 --- a/src/server/scripts/Northrend/draktharon_keep/boss_dred.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: MAYBE need more improve the "Raptor Call". - */ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -enum eSpells -{ - SPELL_BELLOWING_ROAR = 22686, // fears the group, can be resisted/dispelled - SPELL_GRIEVOUS_BITE = 48920, - SPELL_MANGLING_SLASH = 48873, //casted on the current tank, adds debuf - SPELL_FEARSOME_ROAR = 48849, - H_SPELL_FEARSOME_ROAR = 59422, //Not stacking, debuff - SPELL_PIERCING_SLASH = 48878, //debuff -->Armor reduced by 75% - SPELL_RAPTOR_CALL = 59416, //dummy - SPELL_GUT_RIP = 49710, - SPELL_REND = 13738 -}; - -enum eArchivements -{ - ACHIEV_BETTER_OFF_DRED = 2039 -}; - -enum Creatures -{ - NPC_RAPTOR_1 = 26641, - NPC_RAPTOR_2 = 26628 -}; - -struct boss_dredAI : public ScriptedAI -{ - boss_dredAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBellowingRoarTimer; - uint32 uiGrievousBiteTimer; - uint32 uiManglingSlashTimer; - uint32 uiFearsomeRoarTimer; - uint32 uiPiercingSlashTimer; - uint32 uiRaptorCallTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - { - pInstance->SetData(DATA_DRED_EVENT,NOT_STARTED); - pInstance->SetData(DATA_KING_DRED_ACHIEV, 0); - } - - uiBellowingRoarTimer = 33*IN_MILISECONDS; - uiGrievousBiteTimer = 20*IN_MILISECONDS; - uiManglingSlashTimer = 18.5*IN_MILISECONDS; - uiFearsomeRoarTimer = urand(10*IN_MILISECONDS,20*IN_MILISECONDS); - uiPiercingSlashTimer = 17*IN_MILISECONDS; - uiRaptorCallTimer = urand(20*IN_MILISECONDS,25*IN_MILISECONDS); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_DRED_EVENT,IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBellowingRoarTimer < diff) - { - DoCastAOE(SPELL_BELLOWING_ROAR, false); - uiBellowingRoarTimer = 40*IN_MILISECONDS; - } else uiBellowingRoarTimer -=diff; - - if (uiGrievousBiteTimer < diff) - { - DoCastVictim(SPELL_GRIEVOUS_BITE ,false); - uiGrievousBiteTimer = 20*IN_MILISECONDS; - } else uiGrievousBiteTimer -=diff; - - if (uiManglingSlashTimer < diff) - { - DoCastVictim(SPELL_MANGLING_SLASH,false); - uiManglingSlashTimer = 20*IN_MILISECONDS; - } else uiManglingSlashTimer -=diff; - - if (uiFearsomeRoarTimer < diff) - { - DoCastAOE(SPELL_FEARSOME_ROAR,false); - uiFearsomeRoarTimer = urand(16*IN_MILISECONDS,18*IN_MILISECONDS); - } else uiFearsomeRoarTimer -=diff; - - if (uiPiercingSlashTimer < diff) - { - DoCastVictim(SPELL_PIERCING_SLASH,false); - uiPiercingSlashTimer = 20*IN_MILISECONDS; - } else uiPiercingSlashTimer -=diff; - - if (uiRaptorCallTimer < diff) - { - DoCastVictim(SPELL_RAPTOR_CALL,false); - - float x,y,z; - - me->GetClosePoint(x,y,z,me->GetObjectSize()/3,10.0f); - me->SummonCreature(RAND(NPC_RAPTOR_1,NPC_RAPTOR_2),x,y,z,0,TEMPSUMMON_DEAD_DESPAWN,1*IN_MILISECONDS); - - uiRaptorCallTimer = urand(20*IN_MILISECONDS,25*IN_MILISECONDS); - } else uiRaptorCallTimer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_DRED_EVENT,DONE); - - if (IsHeroic() && pInstance->GetData(DATA_KING_DRED_ACHIEV) == 6) - pInstance->DoCompleteAchievement(ACHIEV_BETTER_OFF_DRED); - } - } -}; - -CreatureAI* GetAI_boss_dred(Creature* pCreature) -{ - return new boss_dredAI (pCreature); -} - -struct npc_drakkari_gutripperAI : public ScriptedAI -{ - npc_drakkari_gutripperAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 GutRipTimer; - - void Reset() - { - GutRipTimer = urand(10000,15000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (GutRipTimer < diff) - { - DoCastVictim(SPELL_GUT_RIP,false); - GutRipTimer = urand(10000,15000); - }else GutRipTimer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (IsHeroic() && pInstance->GetData(DATA_DRED_EVENT) == IN_PROGRESS && pInstance->GetData(DATA_KING_DRED_ACHIEV) < 6) - { - pInstance->SetData(DATA_KING_DRED_ACHIEV, pInstance->GetData(DATA_KING_DRED_ACHIEV) + 1); - } - } - } -}; - -CreatureAI* GetAI_npc_drakkari_gutripper(Creature* pCreature) -{ - return new npc_drakkari_gutripperAI (pCreature); -} - -struct npc_drakkari_scytheclawAI : public ScriptedAI -{ - npc_drakkari_scytheclawAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiRendTimer; - - void Reset() - { - uiRendTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiRendTimer < diff) - { - DoCastVictim(SPELL_REND,false); - uiRendTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - }else uiRendTimer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (IsHeroic() && pInstance->GetData(DATA_DRED_EVENT) == IN_PROGRESS && pInstance->GetData(DATA_KING_DRED_ACHIEV) < 6) - { - pInstance->SetData(DATA_KING_DRED_ACHIEV, pInstance->GetData(DATA_KING_DRED_ACHIEV) + 1); - } - } - } -}; - -CreatureAI* GetAI_npc_drakkari_scytheclaw(Creature* pCreature) -{ - return new npc_drakkari_scytheclawAI (pCreature); -} - -void AddSC_boss_dred() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_drakkari_gutripper"; - newscript->GetAI = &GetAI_npc_drakkari_gutripper; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_drakkari_scytheclaw"; - newscript->GetAI = &GetAI_npc_drakkari_scytheclaw; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_dred"; - newscript->GetAI = &GetAI_boss_dred; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp b/src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp deleted file mode 100644 index 5e8792c352d..00000000000 --- a/src/server/scripts/Northrend/draktharon_keep/boss_novos.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* -* Copyright (C) 2008 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -enum Spells -{ - SPELL_ARCANE_BLAST = 49198, - H_SPELL_ARCANE_BLAST = 59909, - SPELL_ARCANE_FIELD = 47346, - SPELL_BLIZZARD = 49034, - H_SPELL_BLIZZARD = 59854, - SPELL_FROSTBOLT = 49037, - H_SPELL_FROSTBOLT = 59855, - SPELL_WRATH_OF_MISERY = 50089, - H_SPELL_WRATH_OF_MISERY = 59856, - SPELL_SUMMON_MINIONS = 59910 //Summons an army of Fetid Troll Corpses to assist the caster. -}; -//not in db -enum Yells -{ - SAY_AGGRO = -1600000, - SAY_KILL = -1600001, - SAY_DEATH = -1600002, - SAY_NECRO_ADD = -1600003, - SAY_REUBBLE_1 = -1600004, - SAY_REUBBLE_2 = -1600005 -}; -enum Creatures -{ - CREATURE_RISEN_SHADOWCASTER = 27600, - CREATURE_FETID_TROLL_CORPSE = 27598, - CREATURE_HULKING_CORPSE = 27597, - CREATURE_CRYSTAL_HANDLER = 26627 -}; -enum CombatPhase -{ - IDLE, - PHASE_1, - PHASE_2 -}; -enum Achievements -{ - ACHIEV_OH_NOVOS = 2057 -}; - -static Position AddSpawnPoint = { -379.20, -816.76, 59.70 }; -static Position CrystalHandlerSpawnPoint = { -326.626343, -709.956604, 27.813314 }; -static Position AddDestinyPoint = { -379.314545, -772.577637, 28.58837 }; - -struct boss_novosAI : public Scripted_NoMovementAI -{ - boss_novosAI(Creature *c) : Scripted_NoMovementAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiTimer; - uint32 uiCrystalHandlerTimer; - - bool bAchiev; - - SummonList lSummons; - - std::list luiCrystals; - - CombatPhase Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - Phase = IDLE; - luiCrystals.clear(); - bAchiev = true; - me->CastStop(); - lSummons.DespawnAll(); - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (pInstance) - { - pInstance->SetData(DATA_NOVOS_EVENT, NOT_STARTED); - luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_1)); - luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_2)); - luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_3)); - luiCrystals.push_back(pInstance->GetData64(DATA_NOVOS_CRYSTAL_4)); - for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) - { - if (GameObject* pTemp = pInstance->instance->GetGameObject(*itr)) - pTemp->SetGoState(GO_STATE_READY); - } - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - Phase = PHASE_1; - uiCrystalHandlerTimer = 30*IN_MILISECONDS; - uiTimer = 1*IN_MILISECONDS; - DoCast(SPELL_ARCANE_FIELD); - if (pInstance) - { - for (std::list::const_iterator itr = luiCrystals.begin(); itr != luiCrystals.end(); ++itr) - { - if (GameObject *pTemp = pInstance->instance->GetGameObject(*itr)) - pTemp->SetGoState(GO_STATE_ACTIVE); - } - pInstance->SetData(DATA_NOVOS_EVENT, IN_PROGRESS); - } - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void UpdateAI(const uint32 diff) - { - switch (Phase) - { - case PHASE_1: - if (uiTimer <= diff) - { - Creature *pSummon = me->SummonCreature(RAND(CREATURE_FETID_TROLL_CORPSE,CREATURE_HULKING_CORPSE,CREATURE_RISEN_SHADOWCASTER), AddSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); - pSummon->GetMotionMaster()->MovePoint(0, AddDestinyPoint); - //If spell is casted stops casting arcane field so no spell casting - //DoCast(me, SPELL_SUMMON_MINIONS); - uiTimer = 3*IN_MILISECONDS; - } else uiTimer -= diff; - if (uiCrystalHandlerTimer <= diff) - { - DoScriptText(SAY_NECRO_ADD, me); - Creature *pCrystalHandler = me->SummonCreature(CREATURE_CRYSTAL_HANDLER, CrystalHandlerSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); - pCrystalHandler->GetMotionMaster()->MovePoint(0, AddDestinyPoint); - uiCrystalHandlerTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiCrystalHandlerTimer -= diff; - break; - case PHASE_2: - if (uiTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, DUNGEON_MODE(RAND(SPELL_ARCANE_BLAST,SPELL_BLIZZARD,SPELL_FROSTBOLT,SPELL_WRATH_OF_MISERY), - RAND(H_SPELL_ARCANE_BLAST,H_SPELL_BLIZZARD,H_SPELL_FROSTBOLT,H_SPELL_WRATH_OF_MISERY))); - uiTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); - } else uiTimer -= diff; - break; - } - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - { - pInstance->SetData(DATA_NOVOS_EVENT, DONE); - - if (IsHeroic() && bAchiev) - pInstance->DoCompleteAchievement(ACHIEV_OH_NOVOS); - } - lSummons.DespawnAll(); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(SAY_KILL, me); - } - - void JustSummoned(Creature *summon) - { - lSummons.Summon(summon); - } - - void RemoveCrystal() - { - if (!luiCrystals.empty()) - { - if (pInstance) - if (GameObject *pTemp = pInstance->instance->GetGameObject(luiCrystals.back())) - pTemp->SetGoState(GO_STATE_READY); - luiCrystals.pop_back(); - } - if (luiCrystals.empty()) - { - me->CastStop(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Phase = PHASE_2; - uiTimer = 1*IN_MILISECONDS; - } - } - - Unit* GetRandomTarget() - { - return SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - } -}; - -enum CrystalHandlerSpells -{ - SPELL_FLASH_OF_DARKNESS = 49668, - H_SPELL_FLASH_OF_DARKNESS = 59004 -}; - -struct mob_crystal_handlerAI : public ScriptedAI -{ - mob_crystal_handlerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiFlashOfDarknessTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiFlashOfDarknessTimer = 5*IN_MILISECONDS; - } - - void JustDied(Unit* /*killer*/) - { - if (Creature* pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) - CAST_AI(boss_novosAI,pNovos->AI())->RemoveCrystal(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiFlashOfDarknessTimer <= diff) - { - DoCast(me->getVictim(), DUNGEON_MODE(SPELL_FLASH_OF_DARKNESS,H_SPELL_FLASH_OF_DARKNESS)); - uiFlashOfDarknessTimer = 5*IN_MILISECONDS; - } else uiFlashOfDarknessTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE || id != 0) - return; - if (Creature *pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) - if (Unit *pTarget = CAST_AI(boss_novosAI, pNovos->AI())->GetRandomTarget()) - AttackStart(pTarget); - } -}; - -struct mob_novos_minionAI : public ScriptedAI -{ - mob_novos_minionAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE || id !=0) - return; - if (Creature* pNovos = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_NOVOS) : 0)) - { - CAST_AI(boss_novosAI, pNovos->AI())->bAchiev = false; - if (Unit *pTarget = CAST_AI(boss_novosAI, pNovos->AI())->GetRandomTarget()) - AttackStart(pTarget); - } - } -}; - -CreatureAI* GetAI_boss_novos(Creature* pCreature) -{ - return new boss_novosAI (pCreature); -} - -CreatureAI* GetAI_mob_crystal_handler(Creature* pCreature) -{ - return new mob_crystal_handlerAI (pCreature); -} - -CreatureAI* GetAI_mob_novos_minion(Creature* pCreature) -{ - return new mob_novos_minionAI (pCreature); -} - -void AddSC_boss_novos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_novos"; - newscript->GetAI = &GetAI_boss_novos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crystal_handler"; - newscript->GetAI = &GetAI_mob_crystal_handler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_novos_minion"; - newscript->GetAI = &GetAI_mob_novos_minion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp b/src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp deleted file mode 100644 index 1e60dfc6135..00000000000 --- a/src/server/scripts/Northrend/draktharon_keep/boss_tharon_ja.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -enum Spells -{ - //skeletal spells (phase 1) - SPELL_CURSE_OF_LIFE = 49527, - H_SPELL_CURSE_OF_LIFE = 59972, - SPELL_RAIN_OF_FIRE = 49518, - H_SPELL_RAIN_OF_FIRE = 59971, - SPELL_SHADOW_VOLLEY = 49528, - H_SPELL_SHADOW_VOLLEY = 59973, - SPELL_DECAY_FLESH = 49356, //casted at end of phase 1, starts phase 2 - //flesh spells (phase 2) - SPELL_GIFT_OF_THARON_JA = 52509, - SPELL_EYE_BEAM = 49544, - H_SPELL_EYE_BEAM = 59965, - SPELL_LIGHTNING_BREATH = 49537, - H_SPELL_LIGHTNING_BREATH = 59963, - SPELL_POISON_CLOUD = 49548, - H_SPELL_POISON_CLOUD = 59969, - SPELL_RETURN_FLESH = 53463, //Channeled spell ending phase two and returning to phase 1. This ability will stun the party for 6 seconds. - SPELL_ACHIEVEMENT_CHECK = 61863, -}; - -enum Yells -{ - SAY_AGGRO = -1600011, - SAY_KILL_1 = -1600012, - SAY_KILL_2 = -1600013, - SAY_FLESH_1 = -1600014, - SAY_FLESH_2 = -1600015, - SAY_SKELETON_1 = -1600016, - SAY_SKELETON_2 = -1600017, - SAY_DEATH = -1600018 -}; -enum Models -{ - MODEL_FLESH = 27073, - MODEL_SKELETON = 27511 -}; -enum CombatPhase -{ - SKELETAL, - GOING_FLESH, - FLESH, - GOING_SKELETAL -}; - -struct boss_tharon_jaAI : public ScriptedAI -{ - boss_tharon_jaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiPhaseTimer; - uint32 uiCurseOfLifeTimer; - uint32 uiRainOfFireTimer; - uint32 uiShadowVolleyTimer; - uint32 uiEyeBeamTimer; - uint32 uiLightningBreathTimer; - uint32 uiPoisonCloudTimer; - - CombatPhase Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - uiPhaseTimer = 20*IN_MILISECONDS; - uiCurseOfLifeTimer = 1*IN_MILISECONDS; - uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); - uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); - Phase = SKELETAL; - me->SetDisplayId(me->GetNativeDisplayId()); - if (pInstance) - pInstance->SetData(DATA_THARON_JA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_THARON_JA_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - switch (Phase) - { - case SKELETAL: - if (uiCurseOfLifeTimer < diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CURSE_OF_LIFE); - uiCurseOfLifeTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiCurseOfLifeTimer -= diff; - - if (uiShadowVolleyTimer < diff) - { - DoCastVictim(SPELL_SHADOW_VOLLEY); - uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); - } else uiShadowVolleyTimer -= diff; - - if (uiRainOfFireTimer < diff) - { - DoCastAOE(SPELL_RAIN_OF_FIRE); - uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); - } else uiRainOfFireTimer -= diff; - - if (uiPhaseTimer < diff) - { - DoCast(SPELL_DECAY_FLESH); - Phase = GOING_FLESH; - uiPhaseTimer = 6*IN_MILISECONDS; - } else uiPhaseTimer -= diff; - - DoMeleeAttackIfReady(); - break; - case GOING_FLESH: - if (uiPhaseTimer < diff) - { - DoScriptText(RAND(SAY_FLESH_1,SAY_FLESH_2),me); - me->SetDisplayId(MODEL_FLESH); - std::list& threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - Unit *pTemp = Unit::GetUnit((*me),(*itr)->getUnitGuid()); - if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) - { - me->AddAura(SPELL_GIFT_OF_THARON_JA,pTemp); - pTemp->SetDisplayId(MODEL_SKELETON); - } - } - uiPhaseTimer = 20*IN_MILISECONDS; - uiLightningBreathTimer = urand(3*IN_MILISECONDS,4*IN_MILISECONDS); - uiEyeBeamTimer = urand(4*IN_MILISECONDS,8*IN_MILISECONDS); - uiPoisonCloudTimer = urand(6*IN_MILISECONDS,7*IN_MILISECONDS); - Phase = FLESH; - } else uiPhaseTimer -= diff; - break; - case FLESH: - if (uiLightningBreathTimer < diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_LIGHTNING_BREATH); - uiLightningBreathTimer = urand(6*IN_MILISECONDS,7*IN_MILISECONDS); - } else uiLightningBreathTimer -= diff; - - if (uiEyeBeamTimer < diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_EYE_BEAM); - uiEyeBeamTimer = urand(4*IN_MILISECONDS,6*IN_MILISECONDS); - } else uiEyeBeamTimer -= diff; - - if (uiPoisonCloudTimer < diff) - { - DoCastAOE(SPELL_POISON_CLOUD); - uiPoisonCloudTimer = urand(10*IN_MILISECONDS,12*IN_MILISECONDS); - } else uiPoisonCloudTimer -= diff; - - if (uiPhaseTimer < diff) - { - DoCast(SPELL_RETURN_FLESH); - Phase = GOING_SKELETAL; - uiPhaseTimer = 6*IN_MILISECONDS; - } else uiPhaseTimer -= diff; - DoMeleeAttackIfReady(); - break; - case GOING_SKELETAL: - if (uiPhaseTimer < diff) - { - DoScriptText(RAND(SAY_SKELETON_1,SAY_SKELETON_2), me); - me->DeMorph(); - Phase = SKELETAL; - uiPhaseTimer = 20*IN_MILISECONDS; - uiCurseOfLifeTimer = 1*IN_MILISECONDS; - uiRainOfFireTimer = urand(14*IN_MILISECONDS,18*IN_MILISECONDS); - uiShadowVolleyTimer = urand(8*IN_MILISECONDS,10*IN_MILISECONDS); - std::list& threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - Unit *pTemp = Unit::GetUnit((*me),(*itr)->getUnitGuid()); - if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER) - { - if (pTemp->HasAura(SPELL_GIFT_OF_THARON_JA)) - pTemp->RemoveAura(SPELL_GIFT_OF_THARON_JA); - pTemp->DeMorph(); - } - } - } else uiPhaseTimer -= diff; - break; - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2),me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH,me); - - if (pInstance) - { - // clean morph on players - Map::PlayerList const &PlayerList = pInstance->instance->GetPlayers(); - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player *pPlayer = i->getSource()) - pPlayer->DeMorph(); - // cast is not rewarding the achievement. - // DoCast(SPELL_ACHIEVEMENT_CHECK); - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, SPELL_ACHIEVEMENT_CHECK); - - pInstance->SetData(DATA_THARON_JA_EVENT, DONE); - } - } -}; - -CreatureAI* GetAI_boss_tharon_ja(Creature* pCreature) -{ - return new boss_tharon_jaAI (pCreature); -} - -void AddSC_boss_tharon_ja() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_tharon_ja"; - newscript->GetAI = &GetAI_boss_tharon_ja; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp b/src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp deleted file mode 100644 index 03eac73385d..00000000000 --- a/src/server/scripts/Northrend/draktharon_keep/boss_trollgore.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: TODO: spawn troll waves - */ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -enum Spells -{ - SPELL_INFECTED_WOUND = 49637, - SPELL_CRUSH = 49639, - SPELL_CORPSE_EXPLODE = 49555, - SPELL_CONSUME = 49380, - SPELL_CONSUME_AURA = 49381, - //Heroic spells - H_SPELL_CORPSE_EXPLODE = 59807, - H_SPELL_CONSUME = 59803, - H_SPELL_CONSUME_AURA = 59805, -}; -enum Yells -{ - SAY_AGGRO = -1600006, - SAY_KILL = -1600007, - SAY_CONSUME = -1600008, - SAY_EXPLODE = -1600009, - SAY_DEATH = -1600010 -}; -enum Achievements -{ - ACHIEV_CONSUMPTION_JUNCTION = 2151 -}; -enum Creatures -{ - NPC_DRAKKARI_INVADER_1 = 27753, - NPC_DRAKKARI_INVADER_2 = 27709 -}; - -Position AddSpawnPoint = { -260.493011, -622.968018, 26.605301, 3.036870 }; - -struct boss_trollgoreAI : public ScriptedAI -{ - boss_trollgoreAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiConsumeTimer; - uint32 uiAuraCountTimer; - uint32 uiCrushTimer; - uint32 uiInfectedWoundTimer; - uint32 uiExplodeCorpseTimer; - uint32 uiSpawnTimer; - - bool bAchiev; - - SummonList lSummons; - - ScriptedInstance* pInstance; - - void Reset() - { - uiConsumeTimer = 15*IN_MILISECONDS; - uiAuraCountTimer = 15.5*IN_MILISECONDS; - uiCrushTimer = urand(1*IN_MILISECONDS,5*IN_MILISECONDS); - uiInfectedWoundTimer = urand(60*IN_MILISECONDS,10*IN_MILISECONDS); - uiExplodeCorpseTimer = 3*IN_MILISECONDS; - uiSpawnTimer = urand(30*IN_MILISECONDS,40*IN_MILISECONDS); - - bAchiev = IsHeroic(); - - lSummons.DespawnAll(); - - me->RemoveAura(DUNGEON_MODE(SPELL_CONSUME_AURA,H_SPELL_CONSUME_AURA)); - - if (pInstance) - pInstance->SetData(DATA_TROLLGORE_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_TROLLGORE_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiSpawnTimer <= diff) - { - uint32 spawnNumber = urand(2,DUNGEON_MODE(3,5)); - for (uint8 i = 0; i < spawnNumber; ++i) - DoSummon(RAND(NPC_DRAKKARI_INVADER_1,NPC_DRAKKARI_INVADER_2), AddSpawnPoint, 0, TEMPSUMMON_DEAD_DESPAWN); - uiSpawnTimer = urand(30*IN_MILISECONDS,40*IN_MILISECONDS); - } else uiSpawnTimer -= diff; - - if (uiConsumeTimer <= diff) - { - DoScriptText(SAY_CONSUME, me); - DoCast(SPELL_CONSUME); - uiConsumeTimer = 15*IN_MILISECONDS; - } else uiConsumeTimer -= diff; - - if (bAchiev) - { - Aura *pConsumeAura = me->GetAura(DUNGEON_MODE(SPELL_CONSUME_AURA,H_SPELL_CONSUME_AURA)); - if (pConsumeAura && pConsumeAura->GetStackAmount() > 9) - bAchiev = false; - } - - if (uiCrushTimer <= diff) - { - DoCastVictim(SPELL_CRUSH); - uiCrushTimer = urand(10*IN_MILISECONDS,15*IN_MILISECONDS); - } else uiCrushTimer -= diff; - - if (uiInfectedWoundTimer <= diff) - { - DoCastVictim(SPELL_INFECTED_WOUND); - uiInfectedWoundTimer = urand(25*IN_MILISECONDS,35*IN_MILISECONDS); - } else uiInfectedWoundTimer -= diff; - - if (uiExplodeCorpseTimer <= diff) - { - DoCast(SPELL_CORPSE_EXPLODE); - DoScriptText(SAY_EXPLODE, me); - uiExplodeCorpseTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); - } else uiExplodeCorpseTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - lSummons.DespawnAll(); - - if (pInstance) - { - if (bAchiev) - pInstance->DoCompleteAchievement(ACHIEV_CONSUMPTION_JUNCTION); - pInstance->SetData(DATA_TROLLGORE_EVENT, DONE); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(SAY_KILL, me); - } - - void JustSummoned(Creature* summon) - { - lSummons.push_back(summon->GetGUID()); - if (summon->AI()) - summon->AI()->AttackStart(me); - } -}; - -CreatureAI* GetAI_boss_trollgore(Creature* pCreature) -{ - return new boss_trollgoreAI (pCreature); -} - -void AddSC_boss_trollgore() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_trollgore"; - newscript->GetAI = &GetAI_boss_trollgore; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h b/src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h deleted file mode 100644 index 597971d17dd..00000000000 --- a/src/server/scripts/Northrend/draktharon_keep/drak_tharon_keep.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright (C) 2008 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef DEF_DRAK_THARON_H -#define DEF_DRAK_THARON_H -enum Data -{ - DATA_TROLLGORE_EVENT, - DATA_NOVOS_EVENT, - DATA_DRED_EVENT, - DATA_THARON_JA_EVENT, - DATA_KING_DRED_ACHIEV -}; -enum Data64 -{ - DATA_TROLLGORE, - DATA_NOVOS, - DATA_DRED, - DATA_THARON_JA, - DATA_NOVOS_CRYSTAL_1, - DATA_NOVOS_CRYSTAL_2, - DATA_NOVOS_CRYSTAL_3, - DATA_NOVOS_CRYSTAL_4 -}; -#endif diff --git a/src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp b/src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp deleted file mode 100644 index 9f4d2ee52a2..00000000000 --- a/src/server/scripts/Northrend/draktharon_keep/instance_drak_tharon_keep.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "drak_tharon_keep.h" - -#define MAX_ENCOUNTER 4 - -/* Drak'Tharon Keep encounters: -0 - Trollgore -1 - Novos -2 - King Dred -3 - Tharon Ja -*/ - -enum Creatures -{ - NPC_TROLLGORE = 26630, - NPC_NOVOS = 26631, - NPC_KING_DRED = 27483, - NPC_THARON_JA = 26632 -}; -enum GameObjects -{ - GO_NOVOS_CRYSTAL_1 = 189299, - GO_NOVOS_CRYSTAL_2 = 189300, - GO_NOVOS_CRYSTAL_3 = 189301, - GO_NOVOS_CRYSTAL_4 = 189302 -}; - -struct instance_drak_tharon : public ScriptedInstance -{ - instance_drak_tharon(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint8 uiDredAchievCounter; - - uint64 uiTrollgore; - uint64 uiNovos; - uint64 uiDred; - uint64 uiTharonJa; - - uint64 uiNovosCrystal1; - uint64 uiNovosCrystal2; - uint64 uiNovosCrystal3; - uint64 uiNovosCrystal4; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() - { - uiTrollgore = 0; - uiNovos = 0; - uiDred = 0; - uiTharonJa = 0; - uiNovosCrystal1 = 0; - uiNovosCrystal2 = 0; - uiNovosCrystal3 = 0; - uiNovosCrystal4 = 0; - uiDredAchievCounter = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_NOVOS_CRYSTAL_1: - uiNovosCrystal1 = pGo->GetGUID(); - break; - case GO_NOVOS_CRYSTAL_2: - uiNovosCrystal2 = pGo->GetGUID(); - break; - case GO_NOVOS_CRYSTAL_3: - uiNovosCrystal3 = pGo->GetGUID(); - break; - case GO_NOVOS_CRYSTAL_4: - uiNovosCrystal4 = pGo->GetGUID(); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_TROLLGORE: - uiTrollgore = pCreature->GetGUID(); - break; - case NPC_NOVOS: - uiNovos = pCreature->GetGUID(); - break; - case NPC_KING_DRED: - uiDred = pCreature->GetGUID(); - break; - case NPC_THARON_JA: - uiTharonJa = pCreature->GetGUID(); - break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_TROLLGORE: return uiTrollgore; - case DATA_NOVOS: return uiNovos; - case DATA_DRED: return uiDred; - case DATA_THARON_JA: return uiTharonJa; - case DATA_NOVOS_CRYSTAL_1: return uiNovosCrystal1; - case DATA_NOVOS_CRYSTAL_2: return uiNovosCrystal2; - case DATA_NOVOS_CRYSTAL_3: return uiNovosCrystal3; - case DATA_NOVOS_CRYSTAL_4: return uiNovosCrystal4; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_TROLLGORE_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_NOVOS_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_DRED_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_THARON_JA_EVENT: - m_auiEncounter[3] = data; - break; - - case DATA_KING_DRED_ACHIEV: - uiDredAchievCounter = data; - break; - } - - if (data == DONE) - { - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch (type) - { - case DATA_TROLLGORE_EVENT: return m_auiEncounter[0]; - case DATA_NOVOS_EVENT: return m_auiEncounter[1]; - case DATA_DRED_EVENT: return m_auiEncounter[2]; - case DATA_THARON_JA_EVENT: return m_auiEncounter[3]; - case DATA_KING_DRED_ACHIEV: return uiDredAchievCounter; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::string str_data; - - std::ostringstream saveStream; - saveStream << "D K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0,data1,data2,data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'D' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_drak_tharon(Map* pMap) -{ - return new instance_drak_tharon(pMap); -} - -void AddSC_instance_drak_tharon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_drak_tharon"; - newscript->GetInstanceData = &GetInstanceData_instance_drak_tharon; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp deleted file mode 100644 index 59db2842735..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -/* - * TODO: - * - Fix Soul Storm spell and remove work around. - */ - -enum Yells -{ - SAY_AGGRO = -1632001, - SAY_SLAY_1 = -1632002, - SAY_SLAY_2 = -1632003, - SAY_DEATH = -1632004, - SAY_SOUL_STORM = -1632005, - SAY_CORRUPT_SOUL = -1632006, -}; - -enum Spells -{ - SPELL_MAGIC_S_BANE = 68793, - SPELL_CORRUPT_SOUL = 68839, - SPELL_CONSUME_SOUL = 68858, - SPELL_TELEPORT = 68988, - SPELL_FEAR = 68950, - SPELL_SOULSTORM = 68872, - SPELL_SOULSTORM_AURA = 68921, - SPELL_SHADOW_BOLT = 70043, -}; - -enum Events -{ - EVENT_NONE, - EVENT_SHADOW_BOLT, - EVENT_MAGIC_BANE, - EVENT_CORRUPT_SOUL, - EVENT_SOUL_STORM, - EVENT_SOUL_STORM_AURA, - EVENT_FEAR, -}; - -enum CombatPhases -{ - PHASE_1, - PHASE_2 -}; - -struct boss_bronjahmAI : public ScriptedAI -{ - boss_bronjahmAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - CombatPhases phase; - - void Reset() - { - phase = PHASE_1; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - - events.Reset(); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); - events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); - events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - // Cast aura spell on all players farther than 10y - void ApplySoulStorm() - { - std::list targetList; - - SelectTargetList(targetList, 100, SELECT_TARGET_TOPAGGRO, -10.0f); - if (targetList.empty()) - return; - - for (std::list::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr) - { - Unit* pUnit = (*itr); - if (pUnit && pUnit->isAlive()) - me->CastSpell(pUnit, SPELL_SOULSTORM_AURA, true); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (phase == PHASE_1 && HealthBelowPct(30)) - { - phase = PHASE_2; - DoCast(me,SPELL_TELEPORT); - me->GetMotionMaster()->Clear(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - events.CancelEvent(EVENT_CORRUPT_SOUL); - events.ScheduleEvent(EVENT_SOUL_STORM, 1000); - events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); - return; - } - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CORRUPT_SOUL: - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - DoScriptText(SAY_CORRUPT_SOUL, me); - DoCast(pTarget,SPELL_CORRUPT_SOUL); - } - events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); - break; - case EVENT_SOUL_STORM: - DoScriptText(SAY_SOUL_STORM, me); - // DoCast(me, SPELL_SOULSTORM); bug: put the aura without the limit of 10 yards. - events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); - break; - case EVENT_SOUL_STORM_AURA: - ApplySoulStorm(); - events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); - break; - case EVENT_FEAR: - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget,SPELL_FEAR); - events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); - break; - case EVENT_SHADOW_BOLT: - DoCastVictim(SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); - break; - case EVENT_MAGIC_BANE: - DoCastVictim(SPELL_MAGIC_S_BANE); - events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_bronjahm(Creature* pCreature) -{ - return new boss_bronjahmAI(pCreature); -} - -struct mob_corrupted_soul_fragmentAI : public ScriptedAI -{ - mob_corrupted_soul_fragmentAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCheckTimer; - - void Reset() - { - uiCheckTimer = 0; // first check is immediate - } - - void UpdateAI(const uint32 diff) - { - if (uiCheckTimer <= diff) - { - if (pInstance) - { - Creature* pBronjham = Unit::GetCreature(*me, pInstance->GetData64(DATA_BRONJAHM)); - if (pBronjham && pBronjham->isAlive()) - { - if (me->IsWithinMeleeRange(pBronjham)) - { - pBronjham->CastSpell(pBronjham, SPELL_CONSUME_SOUL, true); - me->ForcedDespawn(); - } - else - { - Position pos; - pBronjham->GetPosition(&pos); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, pos); - } - } - else - me->ForcedDespawn(); - } - uiCheckTimer = 500; - } - else - uiCheckTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_corrupted_soul_fragment(Creature* pCreature) -{ - return new mob_corrupted_soul_fragmentAI(pCreature); -} - -void AddSC_boss_bronjahm() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_bronjahm"; - newscript->GetAI = &GetAI_boss_bronjahm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_corrupted_soul_fragment"; - newscript->GetAI = &GetAI_mob_corrupted_soul_fragment; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp deleted file mode 100644 index 6811ba953e2..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -/* - * TODO: - * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing). - * - Fix outro npc movement - */ - -#define PI 3.1415f - -enum Yells -{ - SAY_FACE_ANGER_AGGRO = -1632010, - SAY_FACE_DESIRE_AGGRO = -1632011, - SAY_FACE_ANGER_SLAY_1 = -1632012, - SAY_FACE_SORROW_SLAY_1 = -1632013, - SAY_FACE_DESIRE_SLAY_1 = -1632014, - SAY_FACE_ANGER_SLAY_2 = -1632015, - SAY_FACE_SORROW_SLAY_2 = -1632016, - SAY_FACE_DESIRE_SLAY_2 = -1632017, - SAY_FACE_SORROW_DEATH = -1632019, - SAY_FACE_DESIRE_DEATH = -1632020, - EMOTE_MIRRORED_SOUL = -1632021, - EMOTE_UNLEASH_SOUL = -1632022, - SAY_FACE_ANGER_UNLEASH_SOUL = -1632023, - SAY_FACE_SORROW_UNLEASH_SOUL = -1632024, - SAY_FACE_DESIRE_UNLEASH_SOUL = -1632025, - EMOTE_WAILING_SOUL = -1632026, - SAY_FACE_ANGER_WAILING_SOUL = -1632027, - SAY_FACE_DESIRE_WAILING_SOUL = -1632028, - - SAY_JAINA_OUTRO = -1632029, - SAY_SYLVANAS_OUTRO = -1632030, -}; - -enum Spells -{ - SPELL_PHANTOM_BLAST = 68982, - H_SPELL_PHANTOM_BLAST = 70322, - SPELL_MIRRORED_SOUL = 69051, - SPELL_WELL_OF_SOULS = 68820, - SPELL_WELL_OF_SOULS_VIS = 68854, - SPELL_UNLEASHED_SOULS = 68939, - SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase - SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual - SPELL_WAILING_SOULS = 68873, // the actual spell - H_SPELL_WAILING_SOULS = 70324, -// 68871,68873,68875,68876,68899,68912,70324, -// 68899 trigger 68871 -}; - -enum Events -{ - EVENT_NONE, - EVENT_PHANTOM_BLAST, - EVENT_MIRRORED_SOUL, - EVENT_WELL_OF_SOULS, - EVENT_UNLEASHED_SOULS, - EVENT_WAILING_SOULS, - EVENT_WAILING_SOULS_TICK, - EVENT_FACE_ANGER, -}; - -enum eEnum -{ - ACHIEV_THREE_FACED = 4523, - DISPLAY_ANGER = 30148, - DISPLAY_SORROW = 30149, - DISPLAY_DESIRE = 30150, -}; - -struct -{ - uint32 entry[2]; - Position movePosition; -} outroPositions[] = -{ - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5590.47, 2427.79, 705.935, 0.802851 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5593.59, 2428.34, 705.935, 0.977384 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2429.31, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2421.12, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.43, 2426.53, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.55, 2418.36, 705.935, 1.15192 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5598, 2429.14, 705.935, 1.0472 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5594.04, 2424.87, 705.935, 1.15192 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5597.89, 2421.54, 705.935, 0.610865 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5598.57, 2434.62, 705.935, 1.13446 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5585.46, 2417.99, 705.935, 1.06465 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5605.81, 2428.42, 705.935, 0.820305 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5591.61, 2412.66, 705.935, 0.925025 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5593.9, 2410.64, 705.935, 0.872665 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5586.76, 2416.73, 705.935, 0.942478 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5592.23, 2419.14, 705.935, 0.855211 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5594.61, 2416.87, 705.935, 0.907571 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5589.77, 2421.03, 705.935, 0.855211 } }, - - { NPC_KORELN, NPC_LORALEN, { 5602.58, 2435.95, 705.935, 0.959931 } }, - { NPC_ELANDRA, NPC_KALIRA, { 5606.13, 2433.16, 705.935, 0.785398 } }, - { NPC_JAINA_PART2, NPC_SYLVANAS_PART2, { 5606.12, 2436.6, 705.935, 0.890118 } }, - - { 0, 0, { 0, 0, 0, 0 } } -}; - -struct boss_devourer_of_soulsAI : public ScriptedAI -{ - boss_devourer_of_soulsAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - bool bThreeFaceAchievement; - - ScriptedInstance* pInstance; - EventMap events; - - // wailing soul event - float beamAngle; - float beamAngleDiff; - int8 wailingSoulTick; - - uint64 uiMirroredSoulTarget; - - void Reset() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->SetDisplayId(DISPLAY_ANGER); - me->SetReactState(REACT_AGGRESSIVE); - - events.Reset(); - - bThreeFaceAchievement = true; - uiMirroredSoulTarget = 0; - - if (pInstance) - pInstance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS); - - DoScriptText(RAND(SAY_FACE_ANGER_AGGRO,SAY_FACE_DESIRE_AGGRO), me); - - events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); - events.ScheduleEvent(EVENT_MIRRORED_SOUL, 8000); - events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000); - events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000); - events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - if (uiMirroredSoulTarget && me->HasAura(SPELL_MIRRORED_SOUL)) - { - if (Player *pPlayer = Unit::GetPlayer(uiMirroredSoulTarget)) - { - if (Aura *pAura = pPlayer->GetAura(SPELL_MIRRORED_SOUL)) - { - int32 mirrorDamage = (uiDamage * 45)/100; - me->CastCustomSpell(pPlayer, 69034, &mirrorDamage, 0, 0, true); -// me->DealDamage(pPlayer, (uiDamage * 45)/100, 0, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); - } - else - uiMirroredSoulTarget = 0; - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_FACE_ANGER_SLAY_1,SAY_FACE_SORROW_SLAY_1,SAY_FACE_DESIRE_SLAY_1, - SAY_FACE_ANGER_SLAY_2,SAY_FACE_SORROW_SLAY_2,SAY_FACE_DESIRE_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - Position spawnPoint = { 5618.139, 2451.873, 705.854 }; - - DoScriptText(RAND(SAY_FACE_SORROW_DEATH,SAY_FACE_DESIRE_DEATH), me); - - if (pInstance) - { - pInstance->SetData(DATA_DEVOURER_EVENT, DONE); - - if (bThreeFaceAchievement && IsHeroic()) - pInstance->DoCompleteAchievement(ACHIEV_THREE_FACED); - - int32 entryIndex; - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - entryIndex = 0; - else - entryIndex = 1; - - for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i) - { - if (Creature *pSummon = me->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint, TEMPSUMMON_DEAD_DESPAWN)) - { - pSummon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition); - - if (pSummon->GetEntry() == NPC_JAINA_PART2) - DoScriptText(SAY_JAINA_OUTRO, pSummon); - else if (pSummon->GetEntry() == NPC_SYLVANAS_PART2) - DoScriptText(SAY_SYLVANAS_OUTRO, pSummon); - } - } - } - } - - void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry *pSpell) - { - if (pSpell->Id == H_SPELL_PHANTOM_BLAST) - bThreeFaceAchievement = false; - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_PHANTOM_BLAST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0)) - DoCast(pTarget, SPELL_PHANTOM_BLAST); - events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); - break; - case EVENT_MIRRORED_SOUL: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) - { - uiMirroredSoulTarget = pTarget->GetGUID(); - DoCast(pTarget, SPELL_MIRRORED_SOUL); - DoScriptText(EMOTE_MIRRORED_SOUL, me); - } - events.ScheduleEvent(EVENT_MIRRORED_SOUL, urand(15000,30000)); - break; - case EVENT_WELL_OF_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_WELL_OF_SOULS); - events.ScheduleEvent(EVENT_WELL_OF_SOULS, 20000); - break; - case EVENT_UNLEASHED_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_UNLEASHED_SOULS); - me->SetDisplayId(DISPLAY_SORROW); - DoScriptText(RAND(SAY_FACE_ANGER_UNLEASH_SOUL,SAY_FACE_SORROW_UNLEASH_SOUL,SAY_FACE_DESIRE_UNLEASH_SOUL), me); - DoScriptText(EMOTE_UNLEASH_SOUL, me); - events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 30000); - events.ScheduleEvent(EVENT_FACE_ANGER, 5000); - break; - case EVENT_FACE_ANGER: - me->SetDisplayId(DISPLAY_ANGER); - break; - - case EVENT_WAILING_SOULS: - me->SetDisplayId(DISPLAY_DESIRE); - DoScriptText(RAND(SAY_FACE_ANGER_WAILING_SOUL,SAY_FACE_DESIRE_WAILING_SOUL), me); - DoScriptText(EMOTE_WAILING_SOUL, me); - DoCast(me, SPELL_WAILING_SOULS_STARTING); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->SetOrientation(me->GetAngle(pTarget)); - DoCast(me, SPELL_WAILING_SOULS_BEAM); - } - - beamAngle = me->GetOrientation(); - - beamAngleDiff = PI/30.0f; // PI/2 in 15 sec = PI/30 per tick - if (RAND(true,false)) - beamAngleDiff = -beamAngleDiff; - - me->InterruptNonMeleeSpells(false); - me->SetReactState(REACT_PASSIVE); - - //Remove any target - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - me->GetMotionMaster()->Clear(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - - wailingSoulTick = 15; - events.DelayEvents(18000); // no other events during wailing souls - events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3000); // first one after 3 secs. - break; - - case EVENT_WAILING_SOULS_TICK: - beamAngle += beamAngleDiff; - me->SetOrientation(beamAngle); - me->StopMoving(); - - DoCast(me, SPELL_WAILING_SOULS); - - if (--wailingSoulTick) - events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 1000); - else - { - me->SetReactState(REACT_AGGRESSIVE); - me->SetDisplayId(DISPLAY_ANGER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->GetMotionMaster()->MoveChase(me->getVictim()); - events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); - } - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_devourer_of_souls(Creature* pCreature) -{ - return new boss_devourer_of_soulsAI(pCreature); -} - -void AddSC_boss_devourer_of_souls() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_devourer_of_souls"; - newscript->GetAI = &GetAI_boss_devourer_of_souls; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp deleted file mode 100644 index 5c85da69898..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp +++ /dev/null @@ -1,899 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -enum Spells -{ - //Spiteful Apparition - SPELL_SPITE = 68895, - H_SPELL_SPITE = 70212, - - //Spectral Warden - SPELL_VEIL_OF_SHADOWS = 69633, - SPELL_WAIL_OF_SOULS = 69148, - H_SPELL_WAIL_OF_SOULS = 70210, - - //Soulguard Watchman - SPELL_SHROUD_OF_RUNES = 69056, - SPELL_UNHOLY_RAGE = 69053, - - //Soulguard Reaper - SPELL_FROST_NOVA = 69060, - H_SPELL_FROST_NOVA = 70209, - SPELL_SHADOW_LANCE = 69058, - - //Soulguard Bonecaster - SPELL_BONE_VOLLEY = 69080, - H_SPELL_BONE_VOLLEY = 70206, - SPELL_RAISE_DEAD = 69562, - SPELL_SHIELD_OF_BONES = 69069, - H_SPELL_SHIELD_OF_BONES = 70207, - - //Soulguard Animator - // Raise dead 69562 - SPELL_SHADOW_BOLT = 69068, - H_SPELL_SHADOW_BOLT = 70208, - SPELL_SOUL_SICKNESS = 69131, - SPELL_SOUL_SIPHON = 69128, - - //Soulguard Adept - //Raise dead 69562 - //Shadow Bolt 69068/70208 - SPELL_DRAIN_LIFE = 69066, - H_SPELL_DRAIN_LIFE = 70213, - SPELL_SHADOW_MEND = 69564, - H_SPELL_SHADOW_MEND = 70205, - - //Soul Horror - SPELL_SOUL_STRIKE = 69088, - H_SPELL_SOUL_STRIKE = 70211, -}; - -enum Events -{ - EVENT_NONE, - - // Jaina/Sylvanas Intro - EVENT_INTRO_1, - EVENT_INTRO_2, - EVENT_INTRO_3, - EVENT_INTRO_4, - EVENT_INTRO_5, - EVENT_INTRO_6, - EVENT_INTRO_7, - EVENT_INTRO_8, - - //Spiteful Apparition - EVENT_SPITE, - - //Spectral Warden - EVENT_VEIL_OF_SHADOWS, - EVENT_WAIL_OF_SOULS, - - //Soulguard Watchman - EVENT_SHROUD_OF_RUNES, - EVENT_UNHOLY_RAGE, - - //Soulguard Reaper - EVENT_FROST_NOVA, - EVENT_SHADOW_LANCE, - - //Soulguard Bonecaster - EVENT_BONE_VOLLEY, - EVENT_RAISE_DEAD, - EVENT_SHIELD_OF_BONES, - - //Soulguard Animator - EVENT_SHADOW_BOLT, - EVENT_SOUL_SICKNESS, - EVENT_SOUL_SIPHON, - - //Soulguard Adept - EVENT_DRAIN_LIFE, - EVENT_SHADOW_MEND, - - //Soul Horror - EVENT_SOUL_STRIKE, -}; - -/****************************************SYLVANAS************************************/ -#define GOSSIP_SYLVANAS_ITEM "What would you have of me, Banshee Queen?" -#define GOSSIP_JAINA_ITEM "What would you have of me, my lady?" - -enum Yells -{ - SAY_JAINA_INTRO_1 = -1632040, - SAY_JAINA_INTRO_2 = -1632041, - SAY_JAINA_INTRO_3 = -1632042, - SAY_JAINA_INTRO_4 = -1632043, - SAY_JAINA_INTRO_5 = -1632044, - SAY_JAINA_INTRO_6 = -1632045, - SAY_JAINA_INTRO_7 = -1632046, - SAY_JAINA_INTRO_8 = -1632047, - - SAY_SYLVANAS_INTRO_1 = -1632050, - SAY_SYLVANAS_INTRO_2 = -1632051, - SAY_SYLVANAS_INTRO_3 = -1632052, - SAY_SYLVANAS_INTRO_4 = -1632053, - SAY_SYLVANAS_INTRO_5 = -1632054, - SAY_SYLVANAS_INTRO_6 = -1632055, -}; - -enum eSylvanas -{ - GOSSIP_SPEECHINTRO = 13525, - ACTION_INTRO, -}; - -enum Phase -{ - PHASE_NORMAL, - PHASE_INTRO, -}; - -struct npc_sylvanas_fosAI: public ScriptedAI -{ - npc_sylvanas_fosAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - ScriptedInstance* pInstance; - - EventMap events; - Phase phase; - - void Reset() - { - events.Reset(); - phase = PHASE_NORMAL; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_INTRO: - { - phase = PHASE_INTRO; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - events.Reset(); - events.ScheduleEvent(EVENT_INTRO_1, 1000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_INTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_INTRO_1: - DoScriptText(SAY_SYLVANAS_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_2, 11500); - break; - - case EVENT_INTRO_2: - DoScriptText(SAY_SYLVANAS_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_3, 10500); - break; - - case EVENT_INTRO_3: - DoScriptText(SAY_SYLVANAS_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_4, 9500); - break; - - case EVENT_INTRO_4: - DoScriptText(SAY_SYLVANAS_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_5, 10500); - break; - - case EVENT_INTRO_5: - DoScriptText(SAY_SYLVANAS_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_6, 9500); - break; - - case EVENT_INTRO_6: - DoScriptText(SAY_SYLVANAS_INTRO_6, me); - // End of Intro - phase = PHASE_NORMAL; - break; - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - //if (me->hasUnitState(UNIT_STAT_CASTING)) - // return; - - //while (uint32 eventId = events.ExecuteEvent()) - //{ - // switch(eventId) - // { - // } - //} - - DoMeleeAttackIfReady(); - } -}; - -struct npc_jaina_fosAI: public ScriptedAI -{ - npc_jaina_fosAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - ScriptedInstance* pInstance; - - EventMap events; - Phase phase; - - void Reset() - { - events.Reset(); - phase = PHASE_NORMAL; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_INTRO: - { - phase = PHASE_INTRO; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - events.Reset(); - events.ScheduleEvent(EVENT_INTRO_1, 1000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_INTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_INTRO_1: - DoScriptText(SAY_JAINA_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_2, 8000); - break; - - case EVENT_INTRO_2: - DoScriptText(SAY_JAINA_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_3, 8500); - break; - - case EVENT_INTRO_3: - DoScriptText(SAY_JAINA_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_4, 8000); - break; - - case EVENT_INTRO_4: - DoScriptText(SAY_JAINA_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_5, 10000); - break; - - case EVENT_INTRO_5: - DoScriptText(SAY_JAINA_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_6, 8000); - break; - - case EVENT_INTRO_6: - DoScriptText(SAY_JAINA_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_7, 12000); - break; - - case EVENT_INTRO_7: - DoScriptText(SAY_JAINA_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_8, 8000); - break; - - case EVENT_INTRO_8: - DoScriptText(SAY_JAINA_INTRO_8, me); - // End of Intro - phase = PHASE_NORMAL; - break; - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - //if (me->hasUnitState(UNIT_STAT_CASTING)) - // return; - - //while (uint32 eventId = events.ExecuteEvent()) - //{ - // switch(eventId) - // { - // } - //} - - DoMeleeAttackIfReady(); - } -}; - -bool GossipHello_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->GetEntry() == NPC_JAINA_PART1) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_JAINA_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - else - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SYLVANAS_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_INTRO); - break; - } - - return true; -} - -struct mob_spiteful_apparitionAI: public ScriptedAI -{ - mob_spiteful_apparitionAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SPITE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SPITE: - DoCast(me->getVictim(), SPELL_SPITE); - events.RescheduleEvent(EVENT_SPITE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_spectral_wardenAI: public ScriptedAI -{ - mob_spectral_wardenAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_VEIL_OF_SHADOWS, 5000); - events.ScheduleEvent(EVENT_WAIL_OF_SOULS, 10000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_VEIL_OF_SHADOWS: - DoCast(me->getVictim(), SPELL_VEIL_OF_SHADOWS); - events.RescheduleEvent(EVENT_VEIL_OF_SHADOWS, 10000); - return; - case EVENT_WAIL_OF_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_WAIL_OF_SOULS); - events.RescheduleEvent(EVENT_WAIL_OF_SOULS, 5000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_watchmanAI: public ScriptedAI -{ - mob_soulguard_watchmanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHROUD_OF_RUNES, 1000); - events.ScheduleEvent(EVENT_UNHOLY_RAGE, 1000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHROUD_OF_RUNES: - DoCast(me, SPELL_SHROUD_OF_RUNES); - events.RescheduleEvent(EVENT_SHROUD_OF_RUNES, 5000); - return; - case EVENT_UNHOLY_RAGE: - DoCast(me, SPELL_UNHOLY_RAGE); - events.RescheduleEvent(EVENT_UNHOLY_RAGE, 99999); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_reaperAI: public ScriptedAI -{ - mob_soulguard_reaperAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_NOVA, 8000); - events.ScheduleEvent(EVENT_SHADOW_LANCE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROST_NOVA: - DoCast(me, SPELL_FROST_NOVA); - events.RescheduleEvent(EVENT_FROST_NOVA, 9600); - return; - case EVENT_SHADOW_LANCE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_LANCE); - events.RescheduleEvent(EVENT_SHADOW_LANCE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_bonecasterAI: public ScriptedAI -{ - mob_soulguard_bonecasterAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BONE_VOLLEY, 6000); - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHIELD_OF_BONES, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BONE_VOLLEY: - DoCastAOE(SPELL_BONE_VOLLEY); - events.RescheduleEvent(EVENT_BONE_VOLLEY, 7000); - return; - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHIELD_OF_BONES: - DoCast(me, SPELL_SHIELD_OF_BONES); - events.RescheduleEvent(EVENT_SHIELD_OF_BONES, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_animatorAI: public ScriptedAI -{ - mob_soulguard_animatorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 5000); - events.ScheduleEvent(EVENT_SOUL_SICKNESS, 8000); - events.ScheduleEvent(EVENT_SOUL_SIPHON, 10000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; - case EVENT_SOUL_SICKNESS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SOUL_SICKNESS); - events.RescheduleEvent(EVENT_SOUL_SICKNESS, 10000); - return; - case EVENT_SOUL_SIPHON: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SOUL_SIPHON); - events.RescheduleEvent(EVENT_SOUL_SIPHON, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_adeptAI: public ScriptedAI -{ - mob_soulguard_adeptAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 8000); - events.ScheduleEvent(EVENT_DRAIN_LIFE, 7000); - events.ScheduleEvent(EVENT_SHADOW_MEND, 35000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 4000); - return; - case EVENT_DRAIN_LIFE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DRAIN_LIFE); - events.RescheduleEvent(EVENT_DRAIN_LIFE, 9000); - return; - case EVENT_SHADOW_MEND: - DoCast(me, SPELL_SHADOW_MEND); - events.RescheduleEvent(EVENT_SHADOW_MEND, 20000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soul_horrorAI: public ScriptedAI -{ - mob_soul_horrorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SOUL_STRIKE, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SOUL_STRIKE: - DoCast(me->getVictim(), SPELL_SOUL_STRIKE); - events.RescheduleEvent(EVENT_SOUL_STRIKE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_jaina_fosAI(Creature* pCreature) -{ - return new npc_jaina_fosAI(pCreature); -}; - -CreatureAI* GetAI_npc_sylvanas_fosAI(Creature* pCreature) -{ - return new npc_sylvanas_fosAI(pCreature); -}; - -CreatureAI* GetAI_mob_spiteful_apparitionAI(Creature* pCreature) -{ - return new mob_spiteful_apparitionAI(pCreature); -} - -CreatureAI* GetAI_mob_spectral_wardenAI(Creature* pCreature) -{ - return new mob_spectral_wardenAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_watchmanAI(Creature* pCreature) -{ - return new mob_soulguard_watchmanAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_reaperAI(Creature* pCreature) -{ - return new mob_soulguard_reaperAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_bonecasterAI(Creature* pCreature) -{ - return new mob_soulguard_bonecasterAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_animatorAI(Creature* pCreature) -{ - return new mob_soulguard_animatorAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_adeptAI(Creature* pCreature) -{ - return new mob_soulguard_adeptAI(pCreature); -} - -CreatureAI* GetAI_mob_soul_horrorAI(Creature* pCreature) -{ - return new mob_soul_horrorAI(pCreature); -} - -void AddSC_forge_of_souls() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sylvanas_fos"; - newscript->GetAI = &GetAI_npc_sylvanas_fosAI; - newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jaina_fos"; - newscript->GetAI = &GetAI_npc_jaina_fosAI; - newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_spiteful_apparition"; - newscript->GetAI = &GetAI_mob_spiteful_apparitionAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_spectral_warden"; - newscript->GetAI = &GetAI_mob_spectral_wardenAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_watchman"; - newscript->GetAI = &GetAI_mob_soulguard_watchmanAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_reaper"; - newscript->GetAI = &GetAI_mob_soulguard_reaperAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_bonecaster"; - newscript->GetAI = &GetAI_mob_soulguard_bonecasterAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_animator"; - newscript->GetAI = &GetAI_mob_soulguard_animatorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_adept"; - newscript->GetAI = &GetAI_mob_soulguard_adeptAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soul_horror"; - newscript->GetAI = &GetAI_mob_soul_horrorAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h deleted file mode 100644 index e0479eb4d2b..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/forge_of_souls.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_FORGE_OF_SOULS_H -#define DEF_FORGE_OF_SOULS_H - -enum Data -{ - DATA_BRONJAHM_EVENT, - DATA_DEVOURER_EVENT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_BRONJAHM, - DATA_DEVOURER, -}; - -enum Creatures -{ - CREATURE_BRONJAHM = 36497, - CREATURE_DEVOURER = 36502, - - NPC_SYLVANAS_PART1 = 37596, - NPC_SYLVANAS_PART2 = 38161, - NPC_JAINA_PART1 = 37597, - NPC_JAINA_PART2 = 38160, - NPC_KALIRA = 37583, - NPC_ELANDRA = 37774, - NPC_LORALEN = 37779, - NPC_KORELN = 37582, - NPC_CHAMPION_1_HORDE = 37584, - NPC_CHAMPION_2_HORDE = 37587, - NPC_CHAMPION_3_HORDE = 37588, - NPC_CHAMPION_1_ALLIANCE = 37496, - NPC_CHAMPION_2_ALLIANCE = 37497, -}; -#endif diff --git a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp b/src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp deleted file mode 100644 index 67a6cdb4579..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -#define MAX_ENCOUNTER 2 - -/* Forge of Souls encounters: -0- Bronjahm, The Godfather of Souls -1- The Devourer of Souls -*/ - -struct instance_forge_of_souls : public ScriptedInstance -{ - instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiBronjahm; - uint64 uiDevourer; - - uint32 uiEncounter[MAX_ENCOUNTER]; - uint32 uiTeamInInstance; - - void Initialize() - { - uiBronjahm = 0; - uiDevourer = 0; - - uiTeamInInstance = 0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - - if (!players.isEmpty()) - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - - switch(pCreature->GetEntry()) - { - case CREATURE_BRONJAHM: - uiBronjahm = pCreature->GetGUID(); - break; - case CREATURE_DEVOURER: - uiDevourer = pCreature->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_BRONJAHM_EVENT: - uiEncounter[0] = data; - break; - case DATA_DEVOURER_EVENT: - uiEncounter[1] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_BRONJAHM_EVENT: return uiEncounter[0]; - case DATA_DEVOURER_EVENT: return uiEncounter[1]; - case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_BRONJAHM: return uiBronjahm; - case DATA_DEVOURER: return uiBronjahm; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "F S " << uiEncounter[0] << " " << uiEncounter[1]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; - - if (dataHead1 == 'F' && dataHead2 == 'S') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap) -{ - return new instance_forge_of_souls(pMap); -} - -void AddSC_instance_forge_of_souls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_forge_of_souls"; - newscript->GetInstanceData = &GetInstanceData_instance_forge_of_souls; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp deleted file mode 100644 index c9978faca6e..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_falric.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_AGGRO = -1668050, - SAY_SLAY_1 = -1668051, - SAY_SLAY_2 = -1668052, - SAY_DEATH = -1668053, - SAY_IMPENDING_DESPAIR = -1668054, - SAY_DEFILING_HORROR = -1668055, -}; - -enum Spells -{ - SPELL_QUIVERING_STRIKE = 72422, - SPELL_IMPENDING_DESPAIR = 72426, - SPELL_DEFILING_HORROR = 72435, - SPELL_HOPELESSNESS = 72395, - H_SPELL_HOPELESSNESS = 72390, // TODO: not in dbc. Add in DB. -}; - -enum Events -{ - EVENT_NONE, - EVENT_QUIVERING_STRIKE, - EVENT_IMPENDING_DESPAIR, - EVENT_DEFILING_HORROR, -}; - -struct boss_falricAI : public boss_horAI -{ - boss_falricAI(Creature *pCreature) : boss_horAI(pCreature) {} - - uint8 uiHopelessnessCount; - - void Reset() - { - boss_horAI::Reset(); - - uiHopelessnessCount = 0; - - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000); - events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000); - events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, DONE); - } - - void KilledUnit(Unit *victim) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_QUIVERING_STRIKE: - DoCast(SPELL_QUIVERING_STRIKE); - events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000); - break; - case EVENT_IMPENDING_DESPAIR: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - { - DoScriptText(SAY_IMPENDING_DESPAIR, me); - DoCast(pTarget, SPELL_IMPENDING_DESPAIR); - } - events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000); - break; - case EVENT_DEFILING_HORROR: - DoCast(SPELL_DEFILING_HORROR); - events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. - break; - } - - if ((uiHopelessnessCount < 1 && HealthBelowPct(66)) - || (uiHopelessnessCount < 2 && HealthBelowPct(33)) - || (uiHopelessnessCount < 3 && HealthBelowPct(10))) - { - uiHopelessnessCount++; - DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS,H_SPELL_HOPELESSNESS)); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_falric(Creature* pCreature) -{ - return new boss_falricAI(pCreature); -} - -void AddSC_boss_falric() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_falric"; - newscript->GetAI = &GetAI_boss_falric; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp deleted file mode 100644 index 95fb2737ce9..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_AGGRO = -1668060, - SAY_SLAY_1 = -1668061, - SAY_SLAY_2 = -1668062, - SAY_DEATH = -1668063, - SAY_CORRUPTED_FLESH_1 = -1668064, - SAY_CORRUPTED_FLESH_2 = -1668065, -}; - -enum Spells -{ - SPELL_OBLITERATE = 72360, - SPELL_WELL_OF_CORRUPTION = 72362, - SPELL_CORRUPTED_FLESH = 72363, - SPELL_SHARED_SUFFERING = 72368, -}; - -enum Events -{ - EVENT_NONE, - EVENT_OBLITERATE, - EVENT_WELL_OF_CORRUPTION, - EVENT_CORRUPTED_FLESH, - EVENT_SHARED_SUFFERING, -}; - -struct boss_marwynAI : public boss_horAI -{ - boss_marwynAI(Creature *pCreature) : boss_horAI(pCreature) {} - - void Reset() - { - boss_horAI::Reset(); - - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_OBLITERATE, 30000); // TODO Check timer - events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); - events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); - events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); // TODO Check timer - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, DONE); - } - - void KilledUnit(Unit *victim) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_OBLITERATE: - DoCast(SPELL_OBLITERATE); - events.ScheduleEvent(EVENT_OBLITERATE, 30000); - break; - case EVENT_WELL_OF_CORRUPTION: - DoCast(SPELL_WELL_OF_CORRUPTION); - events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); - break; - case EVENT_CORRUPTED_FLESH: - DoScriptText(RAND(SAY_CORRUPTED_FLESH_1,SAY_CORRUPTED_FLESH_2), me); - DoCast(SPELL_CORRUPTED_FLESH); - events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); - break; - case EVENT_SHARED_SUFFERING: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHARED_SUFFERING); - events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); - break; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_marwyn(Creature* pCreature) -{ - return new boss_marwynAI(pCreature); -} - -void AddSC_boss_marwyn() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_marwyn"; - newscript->GetAI = &GetAI_boss_marwyn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp deleted file mode 100644 index fb3d3d5d752..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_JAINA_INTRO_1 = -1668001, - SAY_JAINA_INTRO_2 = -1668002, - SAY_JAINA_INTRO_3 = -1668003, - SAY_JAINA_INTRO_4 = -1668004, - SAY_UTHER_INTRO_A2_1 = -1668005, - SAY_JAINA_INTRO_5 = -1668006, - SAY_UTHER_INTRO_A2_2 = -1668007, - SAY_JAINA_INTRO_6 = -1668008, - SAY_UTHER_INTRO_A2_3 = -1668009, - SAY_JAINA_INTRO_7 = -1668010, - SAY_UTHER_INTRO_A2_4 = -1668011, - SAY_JAINA_INTRO_8 = -1668012, - SAY_UTHER_INTRO_A2_5 = -1668013, - SAY_JAINA_INTRO_9 = -1668014, - SAY_UTHER_INTRO_A2_6 = -1668015, - SAY_UTHER_INTRO_A2_7 = -1668016, - SAY_JAINA_INTRO_10 = -1668017, - SAY_UTHER_INTRO_A2_8 = -1668018, - SAY_JAINA_INTRO_11 = -1668019, - SAY_UTHER_INTRO_A2_9 = -1668020, - - SAY_SYLVANAS_INTRO_1 = -1668021, - SAY_SYLVANAS_INTRO_2 = -1668022, - SAY_SYLVANAS_INTRO_3 = -1668023, - SAY_UTHER_INTRO_H2_1 = -1668024, - SAY_SYLVANAS_INTRO_4 = -1668025, - SAY_UTHER_INTRO_H2_2 = -1668026, - SAY_SYLVANAS_INTRO_5 = -1668027, - SAY_UTHER_INTRO_H2_3 = -1668028, - SAY_SYLVANAS_INTRO_6 = -1668029, - SAY_UTHER_INTRO_H2_4 = -1668030, - SAY_SYLVANAS_INTRO_7 = -1668031, - SAY_UTHER_INTRO_H2_5 = -1668032, - SAY_UTHER_INTRO_H2_6 = -1668033, - SAY_SYLVANAS_INTRO_8 = -1668034, - SAY_UTHER_INTRO_H2_7 = -1668035, - - SAY_LK_INTRO_1 = -1668036, - SAY_LK_INTRO_2 = -1668037, - SAY_LK_INTRO_3 = -1668038, - SAY_FALRIC_INTRO_1 = -1668039, - SAY_MARWYN_INTRO_1 = -1668040, - SAY_FALRIC_INTRO_2 = -1668041, - - SAY_JAINA_INTRO_END = -1668042, - SAY_SYLVANAS_INTRO_END = -1668043, -}; - -enum Events -{ - EVENT_NONE, - - EVENT_START_INTRO, - EVENT_SKIP_INTRO, - - EVENT_INTRO_A2_1, - EVENT_INTRO_A2_2, - EVENT_INTRO_A2_3, - EVENT_INTRO_A2_4, - EVENT_INTRO_A2_5, - EVENT_INTRO_A2_6, - EVENT_INTRO_A2_7, - EVENT_INTRO_A2_8, - EVENT_INTRO_A2_9, - EVENT_INTRO_A2_10, - EVENT_INTRO_A2_11, - EVENT_INTRO_A2_12, - EVENT_INTRO_A2_13, - EVENT_INTRO_A2_14, - EVENT_INTRO_A2_15, - EVENT_INTRO_A2_16, - EVENT_INTRO_A2_17, - EVENT_INTRO_A2_18, - EVENT_INTRO_A2_19, - - EVENT_INTRO_H2_1, - EVENT_INTRO_H2_2, - EVENT_INTRO_H2_3, - EVENT_INTRO_H2_4, - EVENT_INTRO_H2_5, - EVENT_INTRO_H2_6, - EVENT_INTRO_H2_7, - EVENT_INTRO_H2_8, - EVENT_INTRO_H2_9, - EVENT_INTRO_H2_10, - EVENT_INTRO_H2_11, - EVENT_INTRO_H2_12, - EVENT_INTRO_H2_13, - EVENT_INTRO_H2_14, - EVENT_INTRO_H2_15, - - EVENT_INTRO_LK_1, - EVENT_INTRO_LK_2, - EVENT_INTRO_LK_3, - EVENT_INTRO_LK_4, - EVENT_INTRO_LK_5, - EVENT_INTRO_LK_6, - EVENT_INTRO_LK_7, - EVENT_INTRO_LK_8, - EVENT_INTRO_LK_9, - - EVENT_INTRO_END, -}; - -enum eEnum -{ - ACTION_START_INTRO, - ACTION_SKIP_INTRO, - - QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710, - QUEST_DELIVRANCE_FROM_THE_PIT_H2 = 24712, - QUEST_WRATH_OF_THE_LICH_KING_A2 = 24500, - QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802, -}; - -static Position HallsofReflectionLocs[]= -{ - {5283.234863, 1990.946777, 707.695679, 0.929097}, // 2 Loralen Follows - {5408.031250, 2102.918213, 707.695251, 0.792756}, // 9 Sylvanas Follows - {5401.866699, 2110.837402, 707.695251, 0.800610}, // 10 Loralen follows -}; - -static Position SpawnPos = {5262.540527, 1949.693726, 707.695007, 0.808736}; // Jaina/Sylvanas Beginning Position -static Position MoveThronePos = {5306.952148, 1998.499023, 709.341431, 1.277278}; // Jaina/Sylvanas walks to throne -static Position UtherSpawnPos = {5308.310059, 2003.857178, 709.341431, 4.650315}; -static Position LichKingSpawnPos = {5362.917480, 2062.307129, 707.695374, 3.945812}; -static Position LichKingMoveThronePos = {5312.080566, 2009.172119, 709.341431, 3.973301}; // Lich King walks to throne -static Position LichKingMoveAwayPos = {5400.069824, 2102.7131689, 707.69525, 0.843803}; // Lich King walks away - -// AI of Part1: handle the intro till start of gauntlet event. -struct npc_jaina_or_sylvanas_horAI : public ScriptedAI -{ - npc_jaina_or_sylvanas_horAI(Creature *pCreature) : ScriptedAI(pCreature) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint64 uiUther; - uint64 uiLichKing; - - EventMap events; - - void Reset() - { - events.Reset(); - - uiUther = 0; - uiLichKing = 0; - - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetVisibility(VISIBILITY_ON); - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_START_INTRO: - events.ScheduleEvent(EVENT_START_INTRO, 0); - break; - case ACTION_SKIP_INTRO: - events.ScheduleEvent(EVENT_SKIP_INTRO, 0); - break; - } - } - - void UpdateAI(const uint32 diff) - { - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_START_INTRO: - me->GetMotionMaster()->MovePoint(0, MoveThronePos); - // Begining of intro is differents between factions as the speech sequence and timers are differents. - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - events.ScheduleEvent(EVENT_INTRO_A2_1, 0); - else - events.ScheduleEvent(EVENT_INTRO_H2_1, 0); - break; - - // A2 Intro Events - case EVENT_INTRO_A2_1: - DoScriptText(SAY_JAINA_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_A2_2, 5000); - break; - case EVENT_INTRO_A2_2: - DoScriptText(SAY_JAINA_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_A2_3, 10000); - break; - case EVENT_INTRO_A2_3: - // TODO: she's doing some kind of spell casting emote - pInstance->HandleGameObject(pInstance->GetData64(DATA_FROSTMOURNE), true); - events.ScheduleEvent(EVENT_INTRO_A2_4, 10000); - break; - case EVENT_INTRO_A2_4: - // spawn UTHER during speach 2 - if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pUther->GetMotionMaster()->MoveIdle(); - pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas - uiUther = pUther->GetGUID(); - } - events.ScheduleEvent(EVENT_INTRO_A2_5, 2000); - break; - case EVENT_INTRO_A2_5: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_1, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_6, 3000); - break; - case EVENT_INTRO_A2_6: - DoScriptText(SAY_JAINA_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_A2_7, 6000); - break; - case EVENT_INTRO_A2_7: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_2, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_8, 6500); - break; - case EVENT_INTRO_A2_8: - DoScriptText(SAY_JAINA_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_A2_9, 2000); - break; - case EVENT_INTRO_A2_9: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_3, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_10, 9000); - break; - case EVENT_INTRO_A2_10: - DoScriptText(SAY_JAINA_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_A2_11, 5000); - break; - case EVENT_INTRO_A2_11: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_4, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_12, 11000); - break; - case EVENT_INTRO_A2_12: - DoScriptText(SAY_JAINA_INTRO_8, me); - events.ScheduleEvent(EVENT_INTRO_A2_13, 4000); - break; - case EVENT_INTRO_A2_13: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_5, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_14, 12500); - break; - case EVENT_INTRO_A2_14: - DoScriptText(SAY_JAINA_INTRO_9, me); - events.ScheduleEvent(EVENT_INTRO_A2_15, 10000); - break; - case EVENT_INTRO_A2_15: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_6, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_16, 22000); - break; - case EVENT_INTRO_A2_16: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_7, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_17, 4000); - break; - case EVENT_INTRO_A2_17: - DoScriptText(SAY_JAINA_INTRO_10, me); - events.ScheduleEvent(EVENT_INTRO_A2_18, 2000); - break; - case EVENT_INTRO_A2_18: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); - DoScriptText(SAY_UTHER_INTRO_A2_8, pUther); - } - events.ScheduleEvent(EVENT_INTRO_A2_19, 11000); - break; - case EVENT_INTRO_A2_19: - DoScriptText(SAY_JAINA_INTRO_11, me); - events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); - break; - - // H2 Intro Events - case EVENT_INTRO_H2_1: - DoScriptText(SAY_SYLVANAS_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_H2_2, 8000); - break; - case EVENT_INTRO_H2_2: - DoScriptText(SAY_SYLVANAS_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_H2_3, 6000); - break; - case EVENT_INTRO_H2_3: - DoScriptText(SAY_SYLVANAS_INTRO_3, me); - // TODO: she's doing some kind of spell casting emote - events.ScheduleEvent(EVENT_INTRO_H2_4, 6000); - break; - case EVENT_INTRO_H2_4: - // spawn UTHER during speach 2 - if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pUther->GetMotionMaster()->MoveIdle(); - pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas - uiUther = pUther->GetGUID(); - } - events.ScheduleEvent(EVENT_INTRO_H2_5, 2000); - break; - case EVENT_INTRO_H2_5: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_1, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_6, 11000); - break; - case EVENT_INTRO_H2_6: - DoScriptText(SAY_SYLVANAS_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_H2_7, 3000); - break; - case EVENT_INTRO_H2_7: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_2, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_8, 6000); - break; - case EVENT_INTRO_H2_8: - DoScriptText(SAY_SYLVANAS_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_H2_9, 5000); - break; - case EVENT_INTRO_H2_9: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_3, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_10, 19000); - break; - case EVENT_INTRO_H2_10: - DoScriptText(SAY_SYLVANAS_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_H2_11, 1500); - break; - case EVENT_INTRO_H2_11: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_4, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_12, 19500); - break; - case EVENT_INTRO_H2_12: - DoScriptText(SAY_SYLVANAS_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_H2_13, 2000); - break; - case EVENT_INTRO_H2_13: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); - DoScriptText(SAY_UTHER_INTRO_H2_5, pUther); - } - events.ScheduleEvent(EVENT_INTRO_H2_14, 12000); - break; - case EVENT_INTRO_H2_14: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_6, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_15, 8000); - break; - case EVENT_INTRO_H2_15: - DoScriptText(SAY_SYLVANAS_INTRO_8, me); - events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); - break; - - // Remaining Intro Events common for both faction - case EVENT_INTRO_LK_1: - // Spawn LK in front of door, and make him move to the sword. - if (Creature* pLichKing = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pLichKing->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); - pLichKing->SetReactState(REACT_PASSIVE); - uiLichKing = pLichKing->GetGUID(); - } - - if (Creature* pUther = me->GetCreature(*me, uiUther)) - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - DoScriptText(SAY_UTHER_INTRO_A2_9, pUther); - else - DoScriptText(SAY_UTHER_INTRO_H2_7, pUther); - - events.ScheduleEvent(EVENT_INTRO_LK_2, 11000); - break; - - case EVENT_INTRO_LK_2: - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - DoScriptText(SAY_LK_INTRO_1, pLichKing); - events.ScheduleEvent(EVENT_INTRO_LK_3, 2000); - break; - - case EVENT_INTRO_LK_3: - // The Lich King banishes Uther to the abyss. - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->DisappearAndDie(); - uiUther = 0; - } - - // He steps forward and removes the runeblade from the heap of skulls. - - events.ScheduleEvent(EVENT_INTRO_LK_4, 4000); - break; - - case EVENT_INTRO_LK_4: - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - DoScriptText(SAY_LK_INTRO_2, pLichKing); - events.ScheduleEvent(EVENT_INTRO_LK_5, 10000); - break; - - case EVENT_INTRO_LK_5: - // summon Falric and Marwyn. then go back to the door - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - pFalric->SetVisibility(VISIBILITY_ON); - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - pMarwyn->SetVisibility(VISIBILITY_ON); - - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - { - pLichKing->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - DoScriptText(SAY_LK_INTRO_3, pLichKing); - } - - events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); - break; - - case EVENT_INTRO_LK_6: - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - DoScriptText(SAY_FALRIC_INTRO_1, pFalric); - - events.ScheduleEvent(EVENT_INTRO_LK_7, 2000); - break; - - case EVENT_INTRO_LK_7: - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - DoScriptText(SAY_MARWYN_INTRO_1, pMarwyn); - - events.ScheduleEvent(EVENT_INTRO_LK_8, 2000); - break; - - case EVENT_INTRO_LK_8: - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - DoScriptText(SAY_FALRIC_INTRO_2, pFalric); - - events.ScheduleEvent(EVENT_INTRO_LK_9, 5000); - break; - - case EVENT_INTRO_LK_9: - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - DoScriptText(SAY_JAINA_INTRO_END, me); - else - DoScriptText(SAY_SYLVANAS_INTRO_END, me); - - me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - // TODO: Loralen/Koreln shall run also - events.ScheduleEvent(EVENT_INTRO_END, 10000); - break; - - case EVENT_INTRO_END: - if (pInstance) - pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave - - // Loralen or Koreln disappearAndDie() - me->DisappearAndDie(); - break; - - case EVENT_SKIP_INTRO: - // TODO: implement - - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - pFalric->SetVisibility(VISIBILITY_ON); - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - pMarwyn->SetVisibility(VISIBILITY_ON); - - me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - // TODO: Loralen/Koreln shall run also - - events.ScheduleEvent(EVENT_INTRO_END, 15000); - break; - } - } -}; - -bool GossipHello_npc_sylvanas_hor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_H2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - // once last quest is completed, she offers this shortcut of the starting event - if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_H2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Dark Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - - return true; -} - -bool GossipHello_npc_jaina_hor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_A2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - // once last quest of the series is completed, she offers this shortcut of the starting event - if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_A2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "My Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_or_sylvanas_hor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_START_INTRO); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_SKIP_INTRO); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - } - - return true; -} - -enum TrashSpells -{ - // Ghostly Priest - SPELL_SHADOW_WORD_PAIN = 72318, - SPELL_CIRCLE_OF_DESTRUCTION = 72320, - SPELL_COWER_IN_FEAR = 72321, - SPELL_DARK_MENDING = 72322, - - // Phantom Mage - SPELL_FIREBALL = 72163, - SPELL_FLAMESTRIKE = 72169, - SPELL_FROSTBOLT = 72166, - SPELL_CHAINS_OF_ICE = 72121, - SPELL_HALLUCINATION = 72342, - - // Phantom Hallucination (same as phantom mage + HALLUCINATION_2 when dies) - SPELL_HALLUCINATION_2 = 72344, - - // Shadowy Mercenary - SPELL_SHADOW_STEP = 72326, - SPELL_DEADLY_POISON = 72329, - SPELL_ENVENOMED_DAGGER_THROW = 72333, - SPELL_KIDNEY_SHOT = 72335, - - // Spectral Footman - SPELL_SPECTRAL_STRIKE = 72198, - SPELL_SHIELD_BASH = 72194, - SPELL_TORTURED_ENRAGE = 72203, - - // Tortured Rifleman - SPELL_SHOOT = 72208, - SPELL_CURSED_ARROW = 72222, - SPELL_FROST_TRAP = 72215, - SPELL_ICE_SHOT = 72268, -}; - -enum TrashEvents -{ - EVENT_TRASH_NONE, - - // Ghostly Priest - EVENT_SHADOW_WORD_PAIN, - EVENT_CIRCLE_OF_DESTRUCTION, - EVENT_COWER_IN_FEAR, - EVENT_DARK_MENDING, - - // Phantom Mage - EVENT_FIREBALL, - EVENT_FLAMESTRIKE, - EVENT_FROSTBOLT, - EVENT_CHAINS_OF_ICE, - EVENT_HALLUCINATION, - - // Shadowy Mercenary - EVENT_SHADOW_STEP, - EVENT_DEADLY_POISON, - EVENT_ENVENOMED_DAGGER_THROW, - EVENT_KIDNEY_SHOT, - - // Spectral Footman - EVENT_SPECTRAL_STRIKE, - EVENT_SHIELD_BASH, - EVENT_TORTURED_ENRAGE, - - // Tortured Rifleman - EVENT_SHOOT, - EVENT_CURSED_ARROW, - EVENT_FROST_TRAP, - EVENT_ICE_SHOT, -}; - -struct npc_ghostly_priestAI: public ScriptedAI -{ - npc_ghostly_priestAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); // TODO: adjust timers - events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); - events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); - events.ScheduleEvent(EVENT_DARK_MENDING, 20000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_WORD_PAIN: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); - return; - case EVENT_CIRCLE_OF_DESTRUCTION: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CIRCLE_OF_DESTRUCTION); - events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); - return; - case EVENT_COWER_IN_FEAR: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_COWER_IN_FEAR); - events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); - return; - case EVENT_DARK_MENDING: - // find an ally with missing HP - if (Unit *pTarget = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000,50000))) - { - DoCast(pTarget, SPELL_DARK_MENDING); - events.ScheduleEvent(EVENT_DARK_MENDING, 20000); - } - else - { - // no friendly unit with missing hp. re-check in just 5 sec. - events.ScheduleEvent(EVENT_DARK_MENDING, 5000); - } - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_phantom_mageAI: public ScriptedAI -{ - npc_phantom_mageAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FIREBALL, 3000); // TODO: adjust timers - events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000); - events.ScheduleEvent(EVENT_FROSTBOLT, 9000); - events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000); - events.ScheduleEvent(EVENT_HALLUCINATION, 40000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FIREBALL: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_FIREBALL); - events.ScheduleEvent(EVENT_FIREBALL, 15000); - return; - case EVENT_FLAMESTRIKE: - DoCast(SPELL_FLAMESTRIKE); - events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); - return; - case EVENT_FROSTBOLT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_FROSTBOLT); - events.ScheduleEvent(EVENT_FROSTBOLT, 15000); - return; - case EVENT_CHAINS_OF_ICE: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CHAINS_OF_ICE); - events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); - return; - case EVENT_HALLUCINATION: - DoCast(SPELL_HALLUCINATION); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_phantom_hallucinationAI: public npc_phantom_mageAI -{ - npc_phantom_hallucinationAI(Creature *c) : npc_phantom_mageAI(c) - { - } - - void JustDied(Unit * /*pWho*/) - { - DoCast(SPELL_HALLUCINATION_2); - } -}; - -struct npc_shadowy_mercenaryAI: public ScriptedAI -{ - npc_shadowy_mercenaryAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); // TODO: adjust timers - events.ScheduleEvent(EVENT_DEADLY_POISON, 5000); - events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); - events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_STEP: - DoCast(SPELL_SHADOW_STEP); - events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); - return; - case EVENT_DEADLY_POISON: - DoCast(me->getVictim(), SPELL_DEADLY_POISON); - events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); - return; - case EVENT_ENVENOMED_DAGGER_THROW: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_ENVENOMED_DAGGER_THROW); - events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); - return; - case EVENT_KIDNEY_SHOT: - DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); - events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_spectral_footmanAI: public ScriptedAI -{ - npc_spectral_footmanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); // TODO: adjust timers - events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); - events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SPECTRAL_STRIKE: - DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); - events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); - return; - case EVENT_SHIELD_BASH: - DoCast(me->getVictim(), SPELL_SHIELD_BASH); - events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); - return; - case EVENT_TORTURED_ENRAGE: - DoCast(SPELL_TORTURED_ENRAGE); - events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_tortured_riflemanAI : public ScriptedAI -{ - npc_tortured_riflemanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHOOT, 2000); // TODO: adjust timers - events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); - events.ScheduleEvent(EVENT_FROST_TRAP, 1000); - events.ScheduleEvent(EVENT_ICE_SHOT, 15000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHOOT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHOOT); - events.ScheduleEvent(EVENT_SHOOT, 2000); - return; - case EVENT_CURSED_ARROW: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CURSED_ARROW); - events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); - return; - case EVENT_FROST_TRAP: - DoCast(SPELL_FROST_TRAP); - events.ScheduleEvent(EVENT_FROST_TRAP, 30000); - return; - case EVENT_ICE_SHOT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_ICE_SHOT); - events.ScheduleEvent(EVENT_ICE_SHOT, 15000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_jaina_or_sylvanas_horAI(Creature* pCreature) -{ - return new npc_jaina_or_sylvanas_horAI(pCreature); -} - -CreatureAI* GetAI_npc_ghostly_priestAI(Creature* pCreature) -{ - return new npc_ghostly_priestAI(pCreature); -} - -CreatureAI* GetAI_npc_phantom_mageAI(Creature* pCreature) -{ - return new npc_phantom_mageAI(pCreature); -} - -CreatureAI* GetAI_npc_phantom_hallucinationAI(Creature* pCreature) -{ - return new npc_phantom_hallucinationAI(pCreature); -} - -CreatureAI* GetAI_npc_shadowy_mercenaryAI(Creature* pCreature) -{ - return new npc_shadowy_mercenaryAI(pCreature); -} - -CreatureAI* GetAI_npc_spectral_footmanAI(Creature* pCreature) -{ - return new npc_spectral_footmanAI(pCreature); -} - -CreatureAI* GetAI_npc_tortured_riflemanAI(Creature* pCreature) -{ - return new npc_tortured_riflemanAI(pCreature); -} - -void AddSC_halls_of_reflection() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sylvanas_hor_part1"; - newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; - newscript->pGossipHello = &GossipHello_npc_sylvanas_hor; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jaina_hor_part1"; - newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; - newscript->pGossipHello = &GossipHello_npc_jaina_hor; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ghostly_priest"; - newscript->GetAI = &GetAI_npc_ghostly_priestAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_phantom_mage"; - newscript->GetAI = &GetAI_npc_phantom_mageAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_phantom_hallucination"; - newscript->GetAI = &GetAI_npc_phantom_hallucinationAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_shadowy_mercenary"; - newscript->GetAI = &GetAI_npc_shadowy_mercenaryAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_spectral_footman"; - newscript->GetAI = &GetAI_npc_spectral_footmanAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tortured_rifleman"; - newscript->GetAI = &GetAI_npc_tortured_riflemanAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h deleted file mode 100644 index 46ae0cb283c..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_HALLS_OF_REFLECTION_H -#define DEF_HALLS_OF_REFLECTION_H - -enum Data -{ - DATA_FALRIC_EVENT, - DATA_MARWYN_EVENT, - DATA_LICHKING_EVENT, - DATA_WAVE_COUNT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_FALRIC, - DATA_MARWYN, - DATA_LICHKING, - DATA_FROSTMOURNE, -}; - -enum Creatures -{ - NPC_FALRIC = 38112, - NPC_MARWYN = 38113, - NPC_LICH_KING_EVENT = 37226, - NPC_LICH_KING_BOSS = 36954, - - NPC_UTHER = 37225, - NPC_JAINA_PART1 = 37221, - NPC_JAINA_PART2 = 36955, - NPC_SYLVANAS_PART1 = 37223, - NPC_SYLVANAS_PART2 = 37554, - - NPC_WAVE_MERCENARY = 38177, - NPC_WAVE_FOOTMAN = 38173, - NPC_WAVE_RIFLEMAN = 38176, - NPC_WAVE_PRIEST = 38175, - NPC_WAVE_MAGE = 38172, -}; - -enum GameObjects -{ - GO_FROSTMOURNE = 202302, - GO_FROSTMOURNE_ALTAR = 202236, - GO_FRONT_DOOR = 201976, - GO_ARTHAS_DOOR = 197341, -}; - -enum HorWorldStates -{ - WORLD_STATE_HOR = 4884, - WORLD_STATE_HOR_WAVE_COUNT = 4882, -}; - -// Common actions from Instance Script to Boss Script -enum Actions -{ - ACTION_ENTER_COMBAT, -}; - -// Base class for FALRIC and MARWYN -// handled the summonList and the notification events to/from the InstanceData -struct boss_horAI : ScriptedAI -{ - boss_horAI(Creature *pCreature) : ScriptedAI(pCreature), summons(pCreature) - { - pInstance = me->GetInstanceData(); - } - - InstanceData* pInstance; - EventMap events; - SummonList summons; - - void Reset() - { - events.Reset(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); - } - - void DamageTaken(Unit *pWho, uint32 &uiDamage) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - uiDamage = 0; - } - - void DoAction(const int32 actionID) - { - switch(actionID) - { - case ACTION_ENTER_COMBAT: // called by InstanceData when boss shall enter in combat. - // Just in case. Should have been done by InstanceData - me->SetVisibility(VISIBILITY_ON); - - // Reset flags - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - - if (Unit *pUnit = me->SelectNearestTarget()) - AttackStart(pUnit); - - DoZoneInCombat(); - break; - } - } - - void JustSummoned(Creature *pSummoned) - { - summons.Summon(pSummoned); - - if (Unit *pUnit = pSummoned->SelectNearestTarget()) - { - if (pSummoned->AI()) - pSummoned->AI()->AttackStart(pUnit); - else - { - pSummoned->GetMotionMaster()->MoveChase(pUnit); - pSummoned->Attack(pUnit, true); - } - } - - if (pSummoned->AI()) - pSummoned->AI()->DoZoneInCombat(); - } - - void SummonedCreatureDespawn(Creature *pSummoned) - { - summons.Despawn(pSummoned); - if (summons.empty()) - { - if (pSummoned->isAlive()) - pInstance->SetData(DATA_WAVE_COUNT, NOT_STARTED); - else - pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); - } - } -}; - -#endif diff --git a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp deleted file mode 100644 index 7a5d2479b7c..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -#define MAX_ENCOUNTER 3 - -/* Halls of Reflection encounters: -0- Falric -1- Marwyn -2- The Lich King -*/ - -enum eEnum -{ - ENCOUNTER_WAVE_MERCENARY = 6, - ENCOUNTER_WAVE_FOOTMAN = 10, - ENCOUNTER_WAVE_RIFLEMAN = 6, - ENCOUNTER_WAVE_PRIEST = 6, - ENCOUNTER_WAVE_MAGE = 6, -}; - -enum Events -{ - EVENT_NONE, - EVENT_NEXT_WAVE, - EVENT_START_LICH_KING, -}; - -static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] = -{ - {5277.74,2016.88,707.778,5.96903}, - {5295.88,2040.34,707.778,5.07891}, - {5320.37,1980.13,707.778,2.00713}, - {5280.51,1997.84,707.778,0.296706}, - {5302.45,2042.22,707.778,4.90438}, - {5306.57,1977.47,707.778,1.50098}, -}; - -static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] = -{ - {5312.75,2037.12,707.778,4.59022}, - {5309.58,2042.67,707.778,4.69494}, - {5275.08,2008.72,707.778,6.21337}, - {5279.65,2004.66,707.778,0.069813}, - {5275.48,2001.14,707.778,0.174533}, - {5316.7,2041.55,707.778,4.50295}, -}; - -static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] = -{ - {5302.25,1972.41,707.778,1.37881}, - {5311.03,1972.23,707.778,1.64061}, - {5277.36,1993.23,707.778,0.401426}, - {5318.7,2036.11,707.778,4.2237}, - {5335.72,1996.86,707.778,2.74017}, - {5299.43,1979.01,707.778,1.23918}, -}; - -static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] = -{ - {5306.06,2037,707.778,4.81711}, - {5344.15,2007.17,707.778,3.15905}, - {5337.83,2010.06,707.778,3.22886}, - {5343.29,1999.38,707.778,2.9147}, - {5340.84,1992.46,707.778,2.75762}, - {5325.07,1977.6,707.778,2.07694}, - {5336.6,2017.28,707.778,3.47321}, - {5313.82,1978.15,707.778,1.74533}, - {5280.63,2012.16,707.778,6.05629}, - {5322.96,2040.29,707.778,4.34587}, -}; - -static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] = -{ - {5343.47,2015.95,707.778,3.49066}, - {5337.86,2003.4,707.778,2.98451}, - {5319.16,1974,707.778,1.91986}, - {5299.25,2036,707.778,5.02655}, - {5295.64,1973.76,707.778,1.18682}, - {5282.9,2019.6,707.778,5.88176}, -}; - -struct instance_halls_of_reflection : public ScriptedInstance -{ - instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiFalric; - uint64 uiMarwyn; - uint64 uiLichKingEvent; - uint64 uiJainaPart1; - uint64 uiSylvanasPart1; - - uint64 uiFrostmourne; - uint64 uiFrostmourneAltar; - uint64 uiArthasDoor; - uint64 uiFrontDoor; - - uint32 uiEncounter[MAX_ENCOUNTER]; - uint32 uiTeamInInstance; - uint32 uiWaveCount; - bool bIntroDone; - - EventMap events; - - void Initialize() - { - events.Reset(); - - uiFalric = 0; - uiMarwyn = 0; - uiLichKingEvent = 0; - uiJainaPart1 = 0; - uiSylvanasPart1 = 0; - - uiFrostmourne = 0; - uiFrostmourneAltar = 0; - uiArthasDoor = 0; - uiFrontDoor = 0; - uiTeamInInstance = 0; - uiWaveCount = 0; - bIntroDone = false; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - if (!add) - return; - - Map::PlayerList const &players = instance->GetPlayers(); - if (!players.isEmpty()) - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - - switch(pCreature->GetEntry()) - { - case NPC_FALRIC: - uiFalric = pCreature->GetGUID(); - break; - case NPC_MARWYN: - uiMarwyn = pCreature->GetGUID(); - break; - case NPC_LICH_KING_EVENT: - uiLichKingEvent = pCreature->GetGUID(); - break; - case NPC_JAINA_PART1: - uiJainaPart1 = pCreature->GetGUID(); - break; - case NPC_SYLVANAS_PART1: - uiSylvanasPart1 = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if (!add) - return; - - // TODO: init state depending on encounters - switch(pGo->GetEntry()) - { - case GO_FROSTMOURNE: - uiFrostmourne = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, false, pGo); - break; - case GO_FROSTMOURNE_ALTAR: - uiFrostmourneAltar = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, true, pGo); - break; - case GO_FRONT_DOOR: - uiFrontDoor = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, true, pGo); - break; - case GO_ARTHAS_DOOR: - uiArthasDoor = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - - if (uiEncounter[1] == DONE) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - if (type == DATA_WAVE_COUNT && data == SPECIAL) - { - bIntroDone = true; - events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); - return; - } - - - if (uiWaveCount && data == NOT_STARTED) - DoWipe(); - - switch(type) - { - case DATA_FALRIC_EVENT: - uiEncounter[0] = data; - if (data == DONE) - events.ScheduleEvent(EVENT_NEXT_WAVE, 60000); - break; - case DATA_MARWYN_EVENT: - uiEncounter[1] = data; - if (data == DONE) - HandleGameObject(uiArthasDoor, true); - break; - case DATA_LICHKING_EVENT: - uiEncounter[2] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_FALRIC_EVENT: return uiEncounter[0]; - case DATA_MARWYN_EVENT: return uiEncounter[1]; - case DATA_LICHKING_EVENT: return uiEncounter[2]; - case DATA_WAVE_COUNT: return uiWaveCount; - case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_FALRIC: return uiFalric; - case DATA_MARWYN: return uiMarwyn; - case DATA_LICHKING: return uiLichKingEvent; - case DATA_FROSTMOURNE: return uiFrostmourne; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H R 1 " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 version; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2; - - if (dataHead1 == 'H' && dataHead2 == 'R') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - if (uiEncounter[0] == DONE || uiEncounter[1] == DONE) - bIntroDone = true; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void AddWave() - { - DoUpdateWorldState(WORLD_STATE_HOR, 1); - DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); - - switch(uiWaveCount) - { - case 1: - case 2: - case 3: - case 4: - if (Creature *pFalric = instance->GetCreature(uiFalric)) - SpawnWave(pFalric); - break; - case 5: - if (GetData(DATA_FALRIC_EVENT) == DONE) - events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); - else if (Creature *pFalric = instance->GetCreature(uiFalric)) - if (pFalric->AI()) - pFalric->AI()->DoAction(ACTION_ENTER_COMBAT); - break; - case 6: - case 7: - case 8: - case 9: - if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) - SpawnWave(pMarwyn); - break; - case 10: - if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit! - if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) - if (pMarwyn->AI()) - pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT); - break; - } - } - - // Wipe has been detected. Perform cleanup and reset. - void DoWipe() - { - uiWaveCount = 0; - events.Reset(); - DoUpdateWorldState(WORLD_STATE_HOR, 1); - DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); - HandleGameObject(uiFrontDoor, true); - - // TODO - // in case of wipe, the event is normally restarted by jumping into the center of the room. - // As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted. - if (Creature* pJaina = instance->GetCreature(uiJainaPart1)) - pJaina->Respawn(); - if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1)) - pSylvanas->Respawn(); - - if (Creature* pFalric = instance->GetCreature(uiFalric)) - pFalric->SetVisibility(VISIBILITY_OFF); - if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) - pMarwyn->SetVisibility(VISIBILITY_OFF); - } - - // spawn a wave on behalf of the summoner. - void SpawnWave(Creature *pSummoner) - { - uint32 index; - - pSummoner->SetVisibility(VISIBILITY_ON); - - // TODO: do composition at random. # of spawn also depends on uiWaveCount - // As of now, it is just one of each. - index = urand(0,ENCOUNTER_WAVE_MERCENARY-1); - pSummoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_FOOTMAN-1); - pSummoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_RIFLEMAN-1); - pSummoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_PRIEST-1); - pSummoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_MAGE-1); - pSummoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - } - - void Update(uint32 diff) - { - if (!instance->HavePlayers()) - return; - - events.Update(diff); - - switch(uint32 eventId = events.ExecuteEvent()) - { - case EVENT_NEXT_WAVE: - uiWaveCount++; - AddWave(); - break; - case EVENT_START_LICH_KING: - // TODO - break; - } - } -}; - -InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap) -{ - return new instance_halls_of_reflection(pMap); -} - -void AddSC_instance_halls_of_reflection() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_reflection"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_reflection; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp deleted file mode 100644 index 25c78c4a0d3..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -enum Yells -{ - SAY_AGGRO = -1658001, - SAY_SLAY_1 = -1658002, - SAY_SLAY_2 = -1658003, - SAY_DEATH = -1658004, - SAY_PHASE2 = -1658005, - SAY_PHASE3 = -1658006, - - SAY_TYRANNUS_DEATH = -1659007, -}; - -enum eEvents -{ - EVENT_NONE, - EVENT_PERMAFROST, - EVENT_THROW_SARONITE, - EVENT_CHILLINGWAVE, - EVENT_DEEPFREEZE, -}; - -enum Spells -{ - SPELL_PERMAFROST = 70326, - SPELL_PERMAFROST_TRIGGER = 68786, // triggered by PERMAFROST. Used to check aura - SPELL_THROW_SARONITE = 68788, - SPELL_THUNDERING_STOMP = 68771, - SPELL_CHILLING_WAVE = 68778, - H_SPELL_CHILLING_WAVE = 70333, - SPELL_DEEP_FREEZE = 70381, - H_SPELL_DEEP_FREEZE = 72930, - SPELL_FORGE_MACE = 68785, - H_SPELL_FORGE_MACE = 70335, - SPELL_FORGE_BLADE = 68774, - H_SPELL_FORGE_BLADE = 70334, -}; - -enum eEnums -{ - EQUIP_ID_SWORD = 49345, - EQUIP_ID_MACE = 49344, - ACHIEV_DOESNT_GO_TO_ELEVEN = 4524, -}; - -struct boss_garfrostAI : public ScriptedAI -{ - boss_garfrostAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - bool phase2; - bool phase3; - bool bAchievement; - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - phase2 = false; - phase3 = false; - bAchievement = true; - - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_PERMAFROST); - - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_THROW_SARONITE, 45000); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& /*uiDamage*/) - { - if (HealthBelowPct(66) && !phase2) - { - phase2 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_BLADE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.ScheduleEvent(EVENT_CHILLINGWAVE, 10000); - } - - if (HealthBelowPct(33) && !phase3) - { - phase3 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_MACE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.CancelEvent(EVENT_CHILLINGWAVE); // cast only in phase 2. - events.ScheduleEvent(EVENT_DEEPFREEZE, 10000); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - { - if (Creature *pTyrannus = me->GetCreature(*me, pInstance->GetData64(DATA_TYRANNUS))) - DoScriptText(SAY_TYRANNUS_DEATH, pTyrannus); - - pInstance->SetData(DATA_GARFROST_EVENT, DONE); - if (IsHeroic() && bAchievement) - pInstance->DoCompleteAchievement(ACHIEV_DOESNT_GO_TO_ELEVEN); - } - } - - void SpellHitTarget(Unit* pTarget, const SpellEntry *spell) - { - if (spell->Id == SPELL_PERMAFROST_TRIGGER && bAchievement) - { - if (Aura *pAura = pTarget->GetAura(SPELL_PERMAFROST_TRIGGER)) - if (pAura->GetStackAmount() > 10) - bAchievement = false; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_THROW_SARONITE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_THROW_SARONITE); - events.RescheduleEvent(EVENT_THROW_SARONITE, 35000); - return; - case EVENT_DEEPFREEZE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DEEP_FREEZE); - events.RescheduleEvent(EVENT_DEEPFREEZE, 35000); - return; - case EVENT_CHILLINGWAVE: - DoCastAOE(SPELL_CHILLING_WAVE); - events.RescheduleEvent(EVENT_CHILLINGWAVE, 40000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_garfrost(Creature* pCreature) -{ - return new boss_garfrostAI (pCreature); -} - -void AddSC_boss_garfrost() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_garfrost"; - newscript->GetAI = &GetAI_boss_garfrost; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp deleted file mode 100644 index 8b8b03a3d4e..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/* - * SDComment: Spell Explosive barrage is not working. - */ - -enum Spells -{ - SPELL_PURSUED = 68987, - SPELL_CONFUSION = 69029, - SPELL_EXPLOSIVE_BARRAGE = 69263, - SPELL_MIGHTY_KICK = 69021, - SPELL_POISON_NOVA = 68989, - H_SPELL_POISON_NOVA = 70434, - SPELL_SHADOW_BOLT = 69028, - SPELL_TOXIC_WASTE = 69024, - H_SPELL_TOXIC_WASTE = 70436, -}; - -enum Yells -{ - // Krick - SAY_KRICK_AGGRO = -1658010, - SAY_KRICK_SLAY_1 = -1658011, - SAY_KRICK_SLAY_2 = -1658012, - SAY_KRICK_BARRAGE_1 = -1658013, - SAY_KRICK_BARRAGE_2 = -1658014, - SAY_KRICK_POISON_NOVA = -1658015, - SAY_KRICK_CHASE_1 = -1658016, - SAY_KRICK_CHASE_2 = -1658017, - SAY_KRICK_CHASE_3 = -1658018, - - // Ick - SAY_ICK_POISON_NOVA = -1658020, - SAY_ICK_CHASE_1 = -1658021, - - // OUTRO - SAY_KRICK_OUTRO_1 = -1658030, - SAY_JAYNA_OUTRO_2 = -1658031, - SAY_SYLVANAS_OUTRO_2 = -1658032, - SAY_KRICK_OUTRO_3 = -1658033, - SAY_JAYNA_OUTRO_4 = -1658034, - SAY_SYLVANAS_OUTRO_4 = -1658035, - SAY_KRICK_OUTRO_5 = -1658036, - SAY_TYRANNUS_OUTRO_7 = -1658037, - SAY_KRICK_OUTRO_8 = -1658038, - SAY_TYRANNUS_OUTRO_9 = -1658039, - SAY_JAYNA_OUTRO_10 = -1658040, - SAY_SYLVANAS_OUTRO_10 = -1658041, -}; - -enum Events -{ - EVENT_NONE, - EVENT_PURSUE, - EVENT_MIGHTY_KICK, - EVENT_POISON_NOVA, - EVENT_EXPLOSIVE_BARRAGE, - EVENT_END_EXPLOSIVE_BARRAGE, - - // Krick - EVENT_SHADOW_BOLT, - EVENT_TOXIC_WASTE, - - // Krick OUTRO - EVENT_OUTRO_1, - EVENT_OUTRO_2, - EVENT_OUTRO_3, - EVENT_OUTRO_4, - EVENT_OUTRO_5, - EVENT_OUTRO_6, - EVENT_OUTRO_7, - EVENT_OUTRO_8, - EVENT_OUTRO_9, - EVENT_OUTRO_10, - EVENT_OUTRO_11, - EVENT_OUTRO_12, - EVENT_OUTRO_END, -}; - -enum KrickPhase -{ - PHASE_COMBAT, - PHASE_OUTRO, -}; - -enum Actions -{ - ACTION_OUTRO, -}; - -enum Misc -{ - SEAT_KRICK = 0, - - // events GCD. Shall not be 0. - GCD_1 = 1, -}; - -// Krick is the Gnome. -// Ick is the Mount -// Common Events are handled/triggered by Ick that "drive" Krick through DoAction. - -struct boss_ickAI : public ScriptedAI -{ - boss_ickAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, NOT_STARTED); - } - - Creature* GetKrick() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_KRICK) : 0); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, IN_PROGRESS); - - Creature* pKrick = GetKrick(); - if (!pKrick) - pKrick = me->SummonCreature(CREATURE_KRICK, *me, TEMPSUMMON_MANUAL_DESPAWN); - - if (pKrick) - DoScriptText(SAY_KRICK_AGGRO, pKrick); - - events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000, GCD_1); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 35000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - } - - void EnterEvadeMode() - { - me->GetMotionMaster()->Clear(); - ScriptedAI::EnterEvadeMode(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (Creature* pKrick = GetKrick()) - { - if (pKrick->AI()) - pKrick->AI()->DoAction(ACTION_OUTRO); - } - - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; - - if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) - { - EnterEvadeMode(); - return; - } - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch(events.ExecuteEvent()) - { - case EVENT_PURSUE: - if (Creature* pKrick = GetKrick()) - DoScriptText(RAND(SAY_KRICK_CHASE_1,SAY_KRICK_CHASE_2,SAY_KRICK_CHASE_3), pKrick); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->Attack(pTarget,false); - DoScriptText(SAY_ICK_CHASE_1, me, pTarget); - DoCast(pTarget, SPELL_PURSUED); - } - - DoCast(SPELL_CONFUSION); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - return; - - case EVENT_MIGHTY_KICK: - DoCast(me->getVictim(), SPELL_MIGHTY_KICK); - events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000, GCD_1); - return; - - case EVENT_POISON_NOVA: - if (Creature* pKrick = GetKrick()) - DoScriptText(SAY_KRICK_POISON_NOVA, pKrick); - - DoScriptText(SAY_ICK_POISON_NOVA, me); - DoCastAOE(SPELL_POISON_NOVA); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - return; - - case EVENT_TOXIC_WASTE: - DoCast(me->getVictim(), SPELL_TOXIC_WASTE); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - return; - - case EVENT_SHADOW_BOLT: - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - return; - - case EVENT_EXPLOSIVE_BARRAGE: - if (Creature *pKrick = GetKrick()) - { - DoScriptText(SAY_KRICK_BARRAGE_1, pKrick); - DoScriptText(SAY_KRICK_BARRAGE_2, pKrick); - } - - DoCastAOE(SPELL_EXPLOSIVE_BARRAGE); - me->GetMotionMaster()->MoveIdle(); - events.DelayEvents(20000, GCD_1); // 2 sec cast + 18 sec - events.ScheduleEvent(EVENT_END_EXPLOSIVE_BARRAGE, 20000); - return; - - case EVENT_END_EXPLOSIVE_BARRAGE: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 25000); - break; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_krickAI : public ScriptedAI -{ - boss_krickAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - KrickPhase phase; - uint64 uiNpcOutroDialog; - uint64 uiTyrannus; - - void Reset() - { - uiNpcOutroDialog = 0; - uiTyrannus = 0; - phase = PHASE_COMBAT; - - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_OFF); - } - - Creature* GetIck() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ICK) : 0); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_KRICK_SLAY_1,SAY_KRICK_SLAY_2), me); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - // if killed whatever the reason, it breaks the outro - uiDamage = 0; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_OUTRO: - { - Position pos; - if (Creature* pIck = GetIck()) - { - // TODO: tele on Ick then run some distance. - pIck->GetNearPosition(pos, 5.0f, 3.14); - me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0.0f); - } - me->SetVisibility(VISIBILITY_ON); - - Creature* pJainaOrSylvanas = me->GetCreature(*me, pInstance->GetData64(DATA_JAINA_SYLVANAS_1)); - if (pJainaOrSylvanas) { - Position pos; - me->GetNearPosition(pos, 5.0f, 0); - pJainaOrSylvanas->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), - pos.GetAngle(me->GetPositionX(), me->GetPositionY())); - } - else { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - pJainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - else - pJainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - } - - if (pJainaOrSylvanas) - { - pJainaOrSylvanas->SetOrientation(pJainaOrSylvanas->GetAngle(me->GetPositionX(), me->GetPositionY())); - me->SetOrientation(me->GetAngle(pJainaOrSylvanas->GetPositionX(), pJainaOrSylvanas->GetPositionY())); - uiNpcOutroDialog = pJainaOrSylvanas->GetGUID(); - } - - phase = PHASE_OUTRO; - events.Reset(); - events.ScheduleEvent(EVENT_OUTRO_1, 1000); - break; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_OUTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_OUTRO_1: - { - DoScriptText(SAY_KRICK_OUTRO_1, me); - events.ScheduleEvent(EVENT_OUTRO_2, 14000); - break; - } - case EVENT_OUTRO_2: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_2, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_2, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_3, 8500); - break; - } - case EVENT_OUTRO_3: - DoScriptText(SAY_KRICK_OUTRO_3, me); - events.ScheduleEvent(EVENT_OUTRO_4, 12000); - break; - case EVENT_OUTRO_4: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_4, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_4, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_5, 8000); - break; - } - case EVENT_OUTRO_5: - DoScriptText(SAY_KRICK_OUTRO_5, me); - events.ScheduleEvent(EVENT_OUTRO_6, 4000); - break; - case EVENT_OUTRO_6: - // TODO spawn Tyrannus at some distance and MovePoint near-by (flying on rimefang) - // store uiTyrannus - // Adjust timer so tyrannus has time to come - uiTyrannus = (pInstance ? pInstance->GetData64(DATA_TYRANNUS) : 0); - events.ScheduleEvent(EVENT_OUTRO_7, 1); - break; - case EVENT_OUTRO_7: - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_7, pTyrannus); - events.ScheduleEvent(EVENT_OUTRO_8, 7000); - break; - case EVENT_OUTRO_8: - DoScriptText(SAY_KRICK_OUTRO_8, me); - // TODO: Tyrannus starts killing Krick. - // there shall be some visual spell effect - events.ScheduleEvent(EVENT_OUTRO_9, 6000); - break; - case EVENT_OUTRO_9: - // tyrannus kills krick - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetHealth(0); - - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_9, pTyrannus); - - events.ScheduleEvent(EVENT_OUTRO_10, 12000); - break; - case EVENT_OUTRO_10: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_10, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_10, pNpcDialog); - } - - // End of OUTRO. for now... - events.ScheduleEvent(EVENT_OUTRO_END, 8000); - break; - } - case EVENT_OUTRO_END: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - pNpcDialog->DisappearAndDie(); - - me->DisappearAndDie(); - break; - } - } - return; - } - } -}; - -CreatureAI* GetAI_boss_ick(Creature* pCreature) -{ - return new boss_ickAI(pCreature); -} - -CreatureAI* GetAI_boss_krick(Creature* pCreature) -{ - return new boss_krickAI(pCreature); -} - -void AddSC_boss_ick() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ick"; - newscript->GetAI = &GetAI_boss_ick; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_krick"; - newscript->GetAI = &GetAI_boss_krick; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp deleted file mode 100644 index 55ffa0b4e4b..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/* - * SDComment: TODO: - * - implement aura for spell Overlord Brand. - * - Intro/Outro - * - improve script of Rimefang - */ - -enum Yells -{ - SAY_AMBUSH_1 = -1658050, - SAY_AMBUSH_2 = -1658051, - SAY_GAUNTLET_START = -1658052, - SAY_INTRO_1 = -1658053, - SAY_INTRO_2 = -1658054, - - SAY_AGGRO = -1658055, - SAY_SLAY_1 = -1658056, - SAY_SLAY_2 = -1658057, - SAY_DEATH = -1658058, - SAY_MARK_RIMEFANG_1 = -1658059, - SAY_MARK_RIMEFANG_2 = -1658060, - SAY_DARK_MIGHT_1 = -1658061, - SAY_DARK_MIGHT_2 = -1658062, - - SAY_GORKUN_OUTRO_1 = -1658063, - SAY_GORKUN_OUTRO_2 = -1658064, - SAY_JAYNA_OUTRO_3 = -1658065, - SAY_SYLVANAS_OUTRO_3 = -1658066, - SAY_JAYNA_OUTRO_4 = -1658067, - SAY_SYLVANAS_OUTRO_4 = -1658068, - SAY_JAYNA_OUTRO_5 = -1658069, -}; - -enum Spells -{ - SPELL_FORCEFUL_SMASH = 69155, - H_SPELL_FORCEFUL_SMASH = 69627, - SPELL_OVERLORDS_BRAND = 69172, - SPELL_DARK_MIGHT = 69167, - H_SPELL_DARK_MIGHT = 69629, - SPELL_HOARFROST = 69246, - SPELL_MARK_OF_RIMEFANG = 69275, - SPELL_ICY_BLAST = 69233, - H_SPELL_ICY_BLAST = 69646, - SPELL_ICY_BLAST_2 = 69238, - H_SPELL_ICY_BLAST_2 = 69628, -}; - -enum Events -{ - EVENT_NONE, - EVENT_FORCEFUL_SMASH, - EVENT_OVERLORDS_BRAND, - EVENT_DARK_MIGHT, - - // Rimefang - EVENT_MARK_OF_RIMEFANG, - EVENT_HOARFROST, - EVENT_ICY_BLAST, - EVENT_ICY_BLAST_2, -}; - -enum Misc -{ - SEAT_TYRANNUS = 0 -}; - -struct boss_tyrannusAI : public ScriptedAI -{ - boss_tyrannusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, NOT_STARTED); - } - - Creature* GetRimefang() - { - return me->GetCreature(*me, pInstance->GetData64(DATA_RIMEFANG)); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - me->ExitVehicle(); - - // restore health if any damage done during intro - me->SetHealth(me->GetMaxHealth()); - - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 35000); - events.ScheduleEvent(EVENT_DARK_MIGHT, 40000); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_TYRANNUS_EVENT, DONE); - if (Creature* pRimefang = GetRimefang()) - pRimefang->ForcedDespawn(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FORCEFUL_SMASH: - DoCast(me->getVictim(), SPELL_FORCEFUL_SMASH); - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - return; - case EVENT_OVERLORDS_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_OVERLORDS_BRAND); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 45000); - return; - case EVENT_DARK_MIGHT: - DoScriptText(SAY_DARK_MIGHT_1, me); - DoScriptText(SAY_DARK_MIGHT_2, me); - DoCast(me, SPELL_DARK_MIGHT); - events.ScheduleEvent(EVENT_DARK_MIGHT, 60000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_rimefangAI : public ScriptedAI -{ - boss_rimefangAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 25000); - events.ScheduleEvent(EVENT_ICY_BLAST, 35000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_MARK_OF_RIMEFANG: - DoScriptText(SAY_MARK_RIMEFANG_1, me); - DoScriptText(SAY_MARK_RIMEFANG_2, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_MARK_OF_RIMEFANG); - events.ScheduleEvent(EVENT_HOARFROST, 5000); - return; - case EVENT_HOARFROST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HOARFROST); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 20000); - return; - case EVENT_ICY_BLAST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ICY_BLAST); - events.ScheduleEvent(EVENT_ICY_BLAST_2, 5000); - return; - case EVENT_ICY_BLAST_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget->getVictim(), SPELL_ICY_BLAST_2); - events.ScheduleEvent(EVENT_ICY_BLAST, 30000); - return; - } - } - } -}; - -CreatureAI* GetAI_boss_tyrannus(Creature* pCreature) -{ - return new boss_tyrannusAI(pCreature); -} - -CreatureAI* GetAI_boss_rimefang(Creature* pCreature) -{ - return new boss_rimefangAI(pCreature); -} - -void AddSC_boss_tyrannus() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_tyrannus"; - newscript->GetAI = &GetAI_boss_tyrannus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="boss_rimefang"; - newscript->GetAI = &GetAI_boss_rimefang; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp deleted file mode 100644 index 8512eca24c1..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -#define MAX_ENCOUNTER 3 - -/* Pit of Saron encounters: -0- Forgemaster Garfrost -1- Krick and Ick -2- Scourgelord Tyrannus -*/ - -struct instance_pit_of_saron : public ScriptedInstance -{ - instance_pit_of_saron(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiKrick; - uint64 uiIck; - uint64 uiGarfrost; - uint64 uiTyrannus; - uint64 uiRimefang; - - uint64 uiJainaOrSylvanas1; - uint64 uiJainaOrSylvanas2; - - uint32 uiTeamInInstance; - uint32 uiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - - uiGarfrost = 0; - uiKrick = 0; - uiIck = 0; - uiTyrannus = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - } - - switch(pCreature->GetEntry()) - { - case CREATURE_KRICK: - uiKrick = pCreature->GetGUID(); - break; - - case CREATURE_ICK: - uiIck = pCreature->GetGUID(); - break; - - case CREATURE_GARFROST: - uiGarfrost = pCreature->GetGUID(); - break; - - case CREATURE_TYRANNUS: - uiTyrannus = pCreature->GetGUID(); - break; - - case CREATURE_RIMEFANG: - uiRimefang = pCreature->GetGUID(); - break; - - case NPC_SYLVANAS_PART1: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); - uiJainaOrSylvanas1 = pCreature->GetGUID(); - break; - case NPC_SYLVANAS_PART2: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); - uiJainaOrSylvanas2 = pCreature->GetGUID(); - break; - case NPC_KILARA: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_ELANDRA, ALLIANCE); - break; - case NPC_KORALEN: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_KORLAEN, ALLIANCE); - break; - case NPC_CHAMPION_1_HORDE: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_2_HORDE: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_GARFROST: return uiGarfrost; - case DATA_KRICK: return uiKrick; - case DATA_ICK: return uiIck; - case DATA_TYRANNUS: return uiTyrannus; - case DATA_RIMEFANG: return uiRimefang; - - case DATA_JAINA_SYLVANAS_1: return uiJainaOrSylvanas1; - case DATA_JAINA_SYLVANAS_2: return uiJainaOrSylvanas2; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_GARFROST_EVENT: - uiEncounter[0] = data; - break; - case DATA_TYRANNUS_EVENT: - uiEncounter[1] = data; - break; - case DATA_KRICKANDICK_EVENT: - uiEncounter[2] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_GARFROST_EVENT: return uiEncounter[0]; - case DATA_TYRANNUS_EVENT: return uiEncounter[1]; - case DATA_KRICKANDICK_EVENT: return uiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::string str_data; - - std::ostringstream saveStream; - saveStream << "P S " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'P' && dataHead2 == 'S') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_pit_of_saron(Map* pMap) -{ - return new instance_pit_of_saron(pMap); -} - -void AddSC_instance_pit_of_saron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_pit_of_saron"; - newscript->GetInstanceData = &GetInstanceData_instance_pit_of_saron; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp deleted file mode 100644 index bc53efc7033..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp +++ /dev/null @@ -1,1101 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/***************************************SPELLS*************************************/ -// Ymirjar Wrathbringer -#define SPELL_BLIGHT DUNGEON_MODE(69603,70285) - -//Ymirjar Skycaller -#define SPELL_FROSTBLADE 70291 -#define SPELL_GLACIAL_STRIKE 70292 - -//Ymirjar Flamebearer -#define SPELL_FIREBALL DUNGEON_MODE(69583,70282) -#define SPELL_HELLFIRE DUNGEON_MODE(69586,70283) -#define SPELL_TACTICAL_BLINK 69584 - -//Ymirjar Deathbringer -#define SPELL_EMPOWERED_SHADOW_BOLT DUNGEON_MODE(69528,70281) -#define SPELL_SUMMON_UNDEAD 69516 - -//Wrathbone Laborer -#define SPELL_BLINDING_DIRT 70302 -#define SPELL_PUNCTURE_WOUND DUNGEON_MODE(70278,70279) -#define SPELL_SHOVELLED DUNGEON_MODE(69572,70280) - -//Wrathbone Coldwraith -#define SPELL_FREEZING_CIRCLE DUNGEON_MODE(69574,70276) -#define SPELL_FROSTBOLT DUNGEON_MODE(69573,70277) - -//Stonespine Gargoyle -#define SPELL_GARGOYLE_STRIKE DUNGEON_MODE(69520,70275) -#define SPELL_STONEFORM 69575 - -// Plagueborn Horror -#define SPELL_BLIGHT_BOMB 69582 -#define SPELL_PUSTULANT_FLESH DUNGEON_MODE(69581,70273) -#define SPELL_TOXIC_WASTE 70274 - -//Iceborn Proto-Drake -#define SPELL_FROST_BREATH DUNGEON_MODE(69527,70272) - -//Hungering Ghoul -#define SPELL_DEVOUR_FLESH 70393 - -//Fallen Warrior -#define SPELL_ARCING_SLICE 69579 -#define SPELL_DEMORALIZING_SHOUT 61044 -#define SPELL_SHIELD_BLOCK 69580 - -//Deathwhisper Torturer -#define SPELL_BLACK_BRAND 70392 -#define SPELL_CURSE_OF_AGONY 70391 - -//Deathwhisper Shadowcaster -#define SPELL_SHADOW_BOLT DUNGEON_MODE(70386,70387) - -//Deathwhisper Necrolyte -#define SPELL_CONVERSION_BEAM DUNGEON_MODE(69578,70269) -#define SPELL_SHADOW_BOLT_2 DUNGEON_MODE(69577,70270) - -//Wrathbone Sorcerer -#define SPELL_SHADOW_BOLT_3 DUNGEON_MODE(70386,70387) - -//Geist Ambusher -#define SPELL_LEAPING_FACE_MAUL DUNGEON_MODE(69504,70271) - -/****************************************EVENTS************************************/ -enum eEvents -{ - EVENT_NONE, - - // Ymirjar Wrathbringer - EVENT_BLIGHT, - - // Ymirjar Skycaller - EVENT_FROSTBLADE, - EVENT_GLACIAL_STRIKE, - - // Ymirjar Flamebearer - EVENT_FIREBALL, - EVENT_HELLFIRE, - EVENT_TACTICAL_BLINK, - - //Ymirjar Deathbringer - EVENT_EMPOWERED_SHADOW_BOLT, - EVENT_SUMMON_UNDEAD, - - //Wrathbone Laborer - EVENT_BLINDING_DIRT, - EVENT_PUNCTURE_WOUND, - EVENT_SHOVELLED, - - //Wrathbone Coldwraith - EVENT_FREEZING_CIRCLE, - EVENT_FROSTBOLT, - - //Stonespine Gargoyle - EVENT_GARGOYLE_STRIKE, - EVENT_STONEFORM, - - //Plagueborn Horror - EVENT_BLIGHT_BOMB, - EVENT_PUSTULANT_FLESH, - EVENT_TOXIC_WASTE, - - //Iceborn Proto-Drake - EVENT_FROST_BREATH, - - //Hungering Ghoul - EVENT_DEVOUR_FLESH, - - //Fallen Warrior - EVENT_ARCING_SLICE, - EVENT_DEMORALIZING_SHOUT, - EVENT_SHIELD_BLOCK, - - //Deathwhisper Torturer - EVENT_BLACK_BRAND, - EVENT_CURSE_OF_AGONY, - - //Deathwhisper Shadowcaster - EVENT_SHADOW_BOLT, - - //Deathwhisper Necrolyte - EVENT_CONVERSION_BEAM, - EVENT_SHADOW_BOLT_2, - - EVENT_SHADOW_BOLT_3, - - //Geist Ambusher - EVENT_LEAPING_FACE_MAUL, -}; - -/****************************************AI****************************************/ -struct mob_ymirjar_wrathbringerAI : public ScriptedAI -{ - mob_ymirjar_wrathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT, 7000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLIGHT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLIGHT); - events.RescheduleEvent(EVENT_BLIGHT, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_skyCallerAI: public ScriptedAI -{ - mob_ymirjar_skyCallerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROSTBLADE, 1); - events.ScheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_GLACIAL_STRIKE: - DoCast(me->getVictim(), SPELL_GLACIAL_STRIKE); - events.RescheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - return; - case EVENT_FROSTBLADE: - DoCast(me, SPELL_FROSTBLADE); - events.CancelEvent(EVENT_FROSTBLADE); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_flamebearerAI: public ScriptedAI -{ - mob_ymirjar_flamebearerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FIREBALL, 4000); - events.ScheduleEvent(EVENT_HELLFIRE, 8000); - events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FIREBALL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FIREBALL); - events.RescheduleEvent(EVENT_FIREBALL, 5000); - return; - case EVENT_HELLFIRE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HELLFIRE); - events.RescheduleEvent(EVENT_HELLFIRE, 10000); - return; - case EVENT_TACTICAL_BLINK: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_TACTICAL_BLINK); - events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_deathbringerAI: public ScriptedAI -{ - mob_ymirjar_deathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_EMPOWERED_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_EMPOWERED_SHADOW_BOLT); - events.RescheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_laborerAI: public ScriptedAI -{ - mob_wrathbone_laborerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); - events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - events.ScheduleEvent(EVENT_SHOVELLED, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLINDING_DIRT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLINDING_DIRT); - events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); - return; - case EVENT_PUNCTURE_WOUND: - DoCast(me->getVictim(), SPELL_PUNCTURE_WOUND); - events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - return; - case EVENT_SHOVELLED: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHOVELLED); - events.RescheduleEvent(EVENT_SHOVELLED, 7000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_coldwraithAI: public ScriptedAI -{ - mob_wrathbone_coldwraithAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - events.ScheduleEvent(EVENT_FROSTBOLT, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FREEZING_CIRCLE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FREEZING_CIRCLE); - events.RescheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - return; - case EVENT_FROSTBOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FROSTBOLT); - events.RescheduleEvent(EVENT_FROSTBOLT, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_stonespine_gargoyleAI: public ScriptedAI -{ - mob_stonespine_gargoyleAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_GARGOYLE_STRIKE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_GARGOYLE_STRIKE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_GARGOYLE_STRIKE); - events.RescheduleEvent(EVENT_GARGOYLE_STRIKE, 6000); - return; - case EVENT_STONEFORM: - if (HealthBelowPct(10)) - DoCast(me, SPELL_STONEFORM); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_plagueborn_horrorAI: public ScriptedAI -{ - mob_plagueborn_horrorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT_BOMB, 999999); - events.ScheduleEvent(EVENT_PUSTULANT_FLESH, 5000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLIGHT_BOMB: - if (HealthBelowPct(15)) - DoCast(me, SPELL_BLIGHT_BOMB); - return; - case EVENT_PUSTULANT_FLESH: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_PUSTULANT_FLESH); - events.RescheduleEvent(EVENT_PUSTULANT_FLESH, 10000); - return; - case EVENT_TOXIC_WASTE: - DoCast(me, SPELL_TOXIC_WASTE); - events.RescheduleEvent(EVENT_TOXIC_WASTE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_iceborn_protodrakeAI: public ScriptedAI -{ - mob_iceborn_protodrakeAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_BREATH, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROST_BREATH: - DoCast(me->getVictim(), SPELL_FROST_BREATH); - events.RescheduleEvent(EVENT_FROST_BREATH, 10000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_hungering_ghoulAI: public ScriptedAI -{ - mob_hungering_ghoulAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_DEVOUR_FLESH, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_DEVOUR_FLESH: - DoCast(me->getVictim(), SPELL_DEVOUR_FLESH); - events.RescheduleEvent(EVENT_DEVOUR_FLESH, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_fallen_warriorAI: public ScriptedAI -{ - mob_fallen_warriorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_ARCING_SLICE, 8000); - events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - events.ScheduleEvent(EVENT_SHIELD_BLOCK, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ARCING_SLICE: - DoCast(me->getVictim(), SPELL_ARCING_SLICE); - events.RescheduleEvent(EVENT_ARCING_SLICE, 10000); - return; - case EVENT_DEMORALIZING_SHOUT: - DoCast(me, SPELL_DEMORALIZING_SHOUT); - events.RescheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - return; - case EVENT_SHIELD_BLOCK: - DoCast(me->getVictim(), SPELL_SHIELD_BLOCK); - events.RescheduleEvent(EVENT_SHIELD_BLOCK, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_torturerAI: public ScriptedAI -{ - mob_deathwhisper_torturerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLACK_BRAND, 10000); - events.ScheduleEvent(EVENT_CURSE_OF_AGONY, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLACK_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLACK_BRAND); - events.RescheduleEvent(EVENT_BLACK_BRAND, 10000); - return; - case EVENT_CURSE_OF_AGONY: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CURSE_OF_AGONY); - events.RescheduleEvent(EVENT_CURSE_OF_AGONY, 13000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_shadowcasterAI: public ScriptedAI -{ - mob_deathwhisper_shadowcasterAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_necrolyteAI: public ScriptedAI -{ - mob_deathwhisper_necrolyteAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_CONVERSION_BEAM, 12000); - events.ScheduleEvent(EVENT_SHADOW_BOLT_2, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CONVERSION_BEAM: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CONVERSION_BEAM); - events.RescheduleEvent(EVENT_CONVERSION_BEAM, 12000); - return; - case EVENT_SHADOW_BOLT_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_2); - events.RescheduleEvent(EVENT_SHADOW_BOLT_2, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_sorcererAI: public ScriptedAI -{ - mob_wrathbone_sorcererAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT_3, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_BOLT_3: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_3); - events.RescheduleEvent(EVENT_SHADOW_BOLT_3, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_geist_ambusherAI: public ScriptedAI -{ - mob_geist_ambusherAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - //Only here so when I figure out how to make it cast on an NPC i can do that. - events.ScheduleEvent(EVENT_LEAPING_FACE_MAUL, 99999); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - //Should only be used on NPCs - case EVENT_LEAPING_FACE_MAUL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_LEAPING_FACE_MAUL); - events.CancelEvent(EVENT_LEAPING_FACE_MAUL); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_ymirjar_wrathbringerAI(Creature* pCreature) -{ - return new mob_ymirjar_wrathbringerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_skyCallerAI(Creature* pCreature) -{ - return new mob_ymirjar_skyCallerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_flamebearerAI(Creature* pCreature) -{ - return new mob_ymirjar_flamebearerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_deathbringerAI(Creature* pCreature) -{ - return new mob_ymirjar_deathbringerAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_laborerAI(Creature* pCreature) -{ - return new mob_wrathbone_laborerAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_coldwraithAI(Creature* pCreature) -{ - return new mob_wrathbone_coldwraithAI(pCreature); -} - -CreatureAI* GetAI_mob_stonespine_gargoyleAI(Creature* pCreature) -{ - return new mob_stonespine_gargoyleAI(pCreature); -} - -CreatureAI* GetAI_mob_plagueborn_horrorAI(Creature* pCreature) -{ - return new mob_plagueborn_horrorAI(pCreature); -} - -CreatureAI* GetAI_mob_iceborn_protodrakeAI(Creature* pCreature) -{ - return new mob_iceborn_protodrakeAI(pCreature); -} - -CreatureAI* GetAI_mob_hungering_ghoulAI(Creature* pCreature) -{ - return new mob_hungering_ghoulAI(pCreature); -} - -CreatureAI* GetAI_mob_fallen_warriorAI(Creature* pCreature) -{ - return new mob_fallen_warriorAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_torturerAI(Creature* pCreature) -{ - return new mob_deathwhisper_torturerAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_shadowcasterAI(Creature* pCreature) -{ - return new mob_deathwhisper_shadowcasterAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_necrolyteAI(Creature* pCreature) -{ - return new mob_deathwhisper_necrolyteAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_sorcererAI(Creature* pCreature) -{ - return new mob_wrathbone_sorcererAI(pCreature); -} - -CreatureAI* GetAI_mob_geist_ambusherAI(Creature* pCreature) -{ - return new mob_geist_ambusherAI(pCreature); -} - -void AddSC_pit_of_saron() -{ - Script *newscript; - newscript = new Script; - newscript->Name="mob_ymirjar_wrathbringer"; - newscript->GetAI = &GetAI_mob_ymirjar_wrathbringerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_skycaller"; - newscript->GetAI = &GetAI_mob_ymirjar_skyCallerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_flamebearer"; - newscript->GetAI = &GetAI_mob_ymirjar_flamebearerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_deathbringer"; - newscript->GetAI = &GetAI_mob_ymirjar_deathbringerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_laborer"; - newscript->GetAI = &GetAI_mob_wrathbone_laborerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_coldwraith"; - newscript->GetAI = &GetAI_mob_wrathbone_coldwraithAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_stonespine_gargoyle"; - newscript->GetAI = &GetAI_mob_stonespine_gargoyleAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_plagueborn_horror"; - newscript->GetAI = &GetAI_mob_plagueborn_horrorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_iceborn_protodrake"; - newscript->GetAI = &GetAI_mob_iceborn_protodrakeAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_hungering_ghoul"; - newscript->GetAI = &GetAI_mob_hungering_ghoulAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_fallen_warrior"; - newscript->GetAI = &GetAI_mob_fallen_warriorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_torturer"; - newscript->GetAI = &GetAI_mob_deathwhisper_torturerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_shadowcaster"; - newscript->GetAI = &GetAI_mob_deathwhisper_shadowcasterAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_necrolyte"; - newscript->GetAI = &GetAI_mob_deathwhisper_necrolyteAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_sorcerer"; - newscript->GetAI = &GetAI_mob_wrathbone_sorcererAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_geist_ambusher"; - newscript->GetAI = &GetAI_mob_geist_ambusherAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h b/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h deleted file mode 100644 index 4a221d17518..00000000000 --- a/src/server/scripts/Northrend/frozen_halls/pit_of_saron/pit_of_saron.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_PIT_OF_SARON_H -#define DEF_PIT_OF_SARON_H - -enum Data -{ - DATA_GARFROST_EVENT, - DATA_KRICKANDICK_EVENT, - DATA_TYRANNUS_EVENT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_GARFROST, - DATA_KRICK, - DATA_ICK, - DATA_TYRANNUS, - DATA_RIMEFANG, - - DATA_JAINA_SYLVANAS_1, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. - DATA_JAINA_SYLVANAS_2, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. -}; - -enum Creatures -{ - CREATURE_GARFROST = 36494, - CREATURE_KRICK = 36477, - CREATURE_ICK = 36476, - CREATURE_TYRANNUS = 36658, - CREATURE_RIMEFANG = 36661, - - NPC_SYLVANAS_PART1 = 36990, - NPC_SYLVANAS_PART2 = 38189, - NPC_JAINA_PART1 = 36993, - NPC_JAINA_PART2 = 38188, - NPC_KILARA = 37583, - NPC_ELANDRA = 37774, - NPC_KORALEN = 37779, - NPC_KORLAEN = 37582, - NPC_CHAMPION_1_HORDE = 37584, - NPC_CHAMPION_2_HORDE = 37587, - NPC_CHAMPION_3_HORDE = 37588, - NPC_CHAMPION_1_ALLIANCE = 37496, - NPC_CHAMPION_2_ALLIANCE = 37497, -}; - -#endif diff --git a/src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp deleted file mode 100644 index 04603c68813..00000000000 --- a/src/server/scripts/Northrend/gundrak/boss_drakkari_colossus.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: The event with the Living Mojos is not implemented, just is done that when one of the mojos around the boss take damage will make the boss enter in combat! - */ - -#include "ScriptedPch.h" -#include "gundrak.h" - -enum Spells -{ - SPELL_EMERGE = 54850, - SPELL_MIGHTY_BLOW = 54719, - SPELL_MERGE = 54878, - SPELL_SURGE = 54801, - SPELL_FREEZE_ANIM = 16245, - SPELL_MOJO_PUDDLE = 55627, - H_SPELL_MOJO_PUDDLE = 58994, - SPELL_MOJO_WAVE = 55626, - H_SPELL_MOJO_WAVE = 58993 -}; - -struct boss_drakkari_colossusAI : public ScriptedAI -{ - boss_drakkari_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bHealth; - bool bHealth1; - - uint32 MightyBlowTimer; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, NOT_STARTED); - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->clearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); - me->SetReactState(REACT_PASSIVE); - MightyBlowTimer = 10*IN_MILISECONDS; - bHealth = false; - bHealth1 = false; - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, IN_PROGRESS); - } - - void CreatureState(Creature* pWho, bool bRestore = false) - { - if (!pWho) - return; - - if (bRestore) - { - pWho->clearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); - pWho->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pWho == me) - me->RemoveAura(SPELL_FREEZE_ANIM); - }else - { - pWho->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pWho->addUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); - if (pWho == me) - DoCast(me,SPELL_FREEZE_ANIM); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bHealth && HealthBelowPct(50) && !HealthBelowPct(5)) - { - CreatureState(me, false); - DoCast(me,SPELL_FREEZE_ANIM); - DoCast(me,SPELL_EMERGE); - bHealth = true; - } - - if (!bHealth1 && HealthBelowPct(5)) - { - DoCast(me,SPELL_EMERGE); - CreatureState(me, false); - bHealth1 = true; - me->RemoveAllAuras(); - } - - if (MightyBlowTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, true); - MightyBlowTimer = 10*IN_MILISECONDS; - } else MightyBlowTimer -= diff; - - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, DONE); - } - - void JustSummoned(Creature* pSummon) - { - if (HealthBelowPct(5)) - pSummon->DealDamage(pSummon, pSummon->GetHealth() * 0.5 , NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - pSummon->AI()->AttackStart(me->getVictim()); - } -}; - -struct boss_drakkari_elementalAI : public ScriptedAI -{ - boss_drakkari_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiSurgeTimer; - - bool bGoToColossus; - - void Reset() - { - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->CreatureState(me, true); - uiSurgeTimer = 7*IN_MILISECONDS; - bGoToColossus = false; - } - - void EnterEvadeMode() - { - me->RemoveFromWorld(); - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - { - CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->CreatureState(pColossus, true); - CAST_AI(boss_drakkari_colossusAI, pColossus->AI())->bHealth1 = false; - } - me->RemoveFromWorld(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bGoToColossus && HealthBelowPct(50)) - { - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - { - if (!CAST_AI(boss_drakkari_colossusAI,pColossus->AI())->HealthBelowPct(6)) - { - me->InterruptNonMeleeSpells(true); - DoCast(pColossus, SPELL_MERGE); - bGoToColossus = true; - } - } - } - - if (uiSurgeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SURGE); - uiSurgeTimer = 7*IN_MILISECONDS; - } else uiSurgeTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - pColossus->Kill(pColossus); - } -}; - -struct npc_living_mojoAI : public ScriptedAI -{ - npc_living_mojoAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiMojoWaveTimer; - uint32 uiMojoPuddleTimer; - - void Reset() - { - uiMojoWaveTimer = 2*IN_MILISECONDS; - uiMojoPuddleTimer = 7*IN_MILISECONDS; - } - - void EnterCombat(Unit* /*who*/) - { - - //Check if the npc is near of Drakkari Colossus. - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - { - if (pColossus->isAlive() && me->IsInRange3d(pColossus->GetHomePosition().GetPositionX(),pColossus->GetHomePosition().GetPositionY(),pColossus->GetHomePosition().GetPositionZ(),0.0f,17.0f)) - me->SetReactState(REACT_PASSIVE); - else - me->SetReactState(REACT_AGGRESSIVE); - } - } - - void DamageTaken(Unit* pDone_by, uint32& /*uiDamage*/) - { - if (me->HasReactState(REACT_PASSIVE)) - { - if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) - { - if (pColossus->isAlive() && !pColossus->isInCombat()) - { - pColossus->RemoveAura(SPELL_FREEZE_ANIM); - pColossus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - pColossus->SetReactState(REACT_AGGRESSIVE); - if (pDone_by && pDone_by->isAlive()) - pColossus->AI()->AttackStart(pDone_by); - EnterEvadeMode(); - } - } - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiMojoWaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MOJO_WAVE); - uiMojoWaveTimer = 15*IN_MILISECONDS; - } else uiMojoWaveTimer -= diff; - - if (uiMojoPuddleTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MOJO_PUDDLE); - uiMojoPuddleTimer = 18*IN_MILISECONDS; - } else uiMojoPuddleTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_drakkari_colossus(Creature* pCreature) -{ - return new boss_drakkari_colossusAI (pCreature); -} - -CreatureAI* GetAI_boss_drakkari_elemental(Creature* pCreature) -{ - return new boss_drakkari_elementalAI (pCreature); -} - -CreatureAI* GetAI_npc_living_mojo(Creature* pCreature) -{ - return new npc_living_mojoAI (pCreature); -} - -void AddSC_boss_drakkari_colossus() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_drakkari_colossus"; - newscript->GetAI = &GetAI_boss_drakkari_colossus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_drakkari_elemental"; - newscript->GetAI = &GetAI_boss_drakkari_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_living_mojo"; - newscript->GetAI = &GetAI_npc_living_mojo; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/gundrak/boss_eck.cpp b/src/server/scripts/Northrend/gundrak/boss_eck.cpp deleted file mode 100644 index 3bf1a33da5a..00000000000 --- a/src/server/scripts/Northrend/gundrak/boss_eck.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -enum Spells -{ - SPELL_ECK_BERSERK = 55816, //Eck goes berserk, increasing his attack speed by 150% and all damage he deals by 500%. - SPELL_ECK_BITE = 55813, //Eck bites down hard, inflicting 150% of his normal damage to an enemy. - SPELL_ECK_SPIT = 55814, //Eck spits toxic bile at enemies in a cone in front of him, inflicting 2970 Nature damage and draining 220 mana every 1 sec for 3 sec. - SPELL_ECK_SPRING_1 = 55815, //Eck leaps at a distant target. --> Drops aggro and charges a random player. Tank can simply taunt him back. - SPELL_ECK_SPRING_2 = 55837 //Eck leaps at a distant target. -}; - -static Position EckSpawnPoint = { 1643.877930, 936.278015, 107.204948, 0.668432 }; - -struct boss_eckAI : public ScriptedAI -{ - boss_eckAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBerserkTimer; - uint32 uiBiteTimer; - uint32 uiSpitTimer; - uint32 uiSpringTimer; - - bool bBerserk; - - ScriptedInstance* pInstance; - - void Reset() - { - uiBerserkTimer = urand(60*IN_MILISECONDS,90*IN_MILISECONDS); //60-90 secs according to wowwiki - uiBiteTimer = 5*IN_MILISECONDS; - uiSpitTimer = 10*IN_MILISECONDS; - uiSpringTimer = 8*IN_MILISECONDS; - - bBerserk = false; - - if (pInstance) - pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ECK_BITE); - uiBiteTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); - } else uiBiteTimer -= diff; - - if (uiSpitTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ECK_SPIT); - uiSpitTimer = urand(6*IN_MILISECONDS,14*IN_MILISECONDS); - } else uiSpitTimer -= diff; - - if (uiSpringTimer <= diff) - { - Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, RAND(SPELL_ECK_SPRING_1, SPELL_ECK_SPRING_2)); - uiSpringTimer = urand(5*IN_MILISECONDS,10*IN_MILISECONDS); - } - } else uiSpringTimer -= diff; - - //Berserk on timer or 20% of health - if (!bBerserk) - { - if (uiBerserkTimer <= diff) - { - DoCast(me, SPELL_ECK_BERSERK); - bBerserk = true; - } - else - { - uiBerserkTimer -= diff; - if (HealthBelowPct(20)) - { - DoCast(me, SPELL_ECK_BERSERK); - bBerserk = true; - } - } - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ECK_THE_FEROCIOUS_EVENT, DONE); - } -}; - -CreatureAI* GetAI_boss_eck(Creature* pCreature) -{ - return new boss_eckAI (pCreature); -} - -struct npc_ruins_dwellerAI : public ScriptedAI -{ - npc_ruins_dwellerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void JustDied(Unit * /*who*/) - { - if (pInstance) - { - pInstance->SetData64(DATA_RUIN_DWELLER_DIED,me->GetGUID()); - if (pInstance->GetData(DATA_ALIVE_RUIN_DWELLERS) == 0) - me->SummonCreature(CREATURE_ECK, EckSpawnPoint, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300*IN_MILISECONDS); - } - } -}; - -CreatureAI* GetAI_npc_ruins_dweller(Creature* pCreature) -{ - return new npc_ruins_dwellerAI (pCreature); -} - -void AddSC_boss_eck() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_eck"; - newscript->GetAI = &GetAI_boss_eck; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ruins_dweller"; - newscript->GetAI = &GetAI_npc_ruins_dweller; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp b/src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp deleted file mode 100644 index c87a6600783..00000000000 --- a/src/server/scripts/Northrend/gundrak/boss_gal_darah.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -//Spells -enum Spells -{ - SPELL_ENRAGE = 55285, - H_SPELL_ENRAGE = 59828, - SPELL_IMPALING_CHARGE = 54956, - H_SPELL_IMPALING_CHARGE = 59827, - SPELL_STOMP = 55292, - H_SPELL_STOMP = 59829, - SPELL_PUNCTURE = 55276, - H_SPELL_PUNCTURE = 59826, - SPELL_STAMPEDE = 55218, - SPELL_WHIRLING_SLASH = 55250, - H_SPELL_WHIRLING_SLASH = 59824, - SPELL_ECK_RESIDUE = 55817 -}; - -//Yells -enum Yells -{ - SAY_AGGRO = -1604000, - SAY_SLAY_1 = -1604001, - SAY_SLAY_2 = -1604002, - SAY_SLAY_3 = -1604003, - SAY_DEATH = -1604004, - SAY_SUMMON_RHINO_1 = -1604005, - SAY_SUMMON_RHINO_2 = -1604006, - SAY_SUMMON_RHINO_3 = -1604007, - SAY_TRANSFORM_1 = -1604008, //Phase change - SAY_TRANSFORM_2 = -1604009 -}; - -enum Achievements -{ - ACHIEV_WHAT_THE_ECK = 1864, - ACHIEV_SHARE_THE_LOVE = 2152 -}; - -enum Displays -{ - DISPLAY_RHINO = 26265, - DISPLAY_TROLL = 27061 -}; - -enum CombatPhase -{ - TROLL, - RHINO -}; - -struct boss_gal_darahAI : public ScriptedAI -{ - boss_gal_darahAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiStampedeTimer; - uint32 uiWhirlingSlashTimer; - uint32 uiPunctureTimer; - uint32 uiEnrageTimer; - uint32 uiImpalingChargeTimer; - uint32 uiStompTimer; - uint32 uiTransformationTimer; - std::set lImpaledPlayers; - - CombatPhase Phase; - - uint8 uiPhaseCounter; - - bool bStartOfTransformation; - - ScriptedInstance* pInstance; - - void Reset() - { - uiStampedeTimer = 10*IN_MILISECONDS; - uiWhirlingSlashTimer = 21*IN_MILISECONDS; - uiPunctureTimer = 10*IN_MILISECONDS; - uiEnrageTimer = 15*IN_MILISECONDS; - uiImpalingChargeTimer = 21*IN_MILISECONDS; - uiStompTimer = 25*IN_MILISECONDS; - uiTransformationTimer = 9*IN_MILISECONDS; - uiPhaseCounter = 0; - - lImpaledPlayers.clear(); - - bStartOfTransformation = true; - - Phase = TROLL; - - me->SetDisplayId(DISPLAY_TROLL); - - if (pInstance) - pInstance->SetData(DATA_GAL_DARAH_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_GAL_DARAH_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - switch (Phase) - { - case TROLL: - if (uiPhaseCounter == 2) - { - if (uiTransformationTimer <= diff) - { - me->SetDisplayId(DISPLAY_RHINO); - Phase = RHINO; - uiPhaseCounter = 0; - DoScriptText(SAY_TRANSFORM_1, me); - uiTransformationTimer = 5*IN_MILISECONDS; - bStartOfTransformation = true; - me->clearUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); - me->SetReactState(REACT_AGGRESSIVE); - } - else - { - uiTransformationTimer -= diff; - - if (bStartOfTransformation) - { - bStartOfTransformation = false; - me->addUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); - me->SetReactState(REACT_PASSIVE); - } - } - } - else - { - if (uiStampedeTimer <= diff) - { - DoCast(me, SPELL_STAMPEDE); - DoScriptText(RAND(SAY_SUMMON_RHINO_1,SAY_SUMMON_RHINO_2,SAY_SUMMON_RHINO_3),me); - uiStampedeTimer = 15*IN_MILISECONDS; - } else uiStampedeTimer -= diff; - - if (uiWhirlingSlashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLING_SLASH); - uiWhirlingSlashTimer = 21*IN_MILISECONDS; - ++uiPhaseCounter; - } else uiWhirlingSlashTimer -= diff; - } - break; - case RHINO: - if (uiPhaseCounter == 2) - { - if (uiTransformationTimer <= diff) - { - me->SetDisplayId(DISPLAY_TROLL); - Phase = TROLL; - uiPhaseCounter = 0; - DoScriptText(SAY_TRANSFORM_2, me); - uiTransformationTimer = 9*IN_MILISECONDS; - bStartOfTransformation = true; - me->clearUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); - me->SetReactState(REACT_AGGRESSIVE); - } - else - { - uiTransformationTimer -= diff; - - if (bStartOfTransformation) - { - bStartOfTransformation = false; - me->addUnitState(UNIT_STAT_STUNNED|UNIT_STAT_ROOT); - me->SetReactState(REACT_PASSIVE); - } - } - } - else - { - if (uiPunctureTimer <= diff) - { - DoCast(me->getVictim(), SPELL_PUNCTURE); - uiPunctureTimer = 8*IN_MILISECONDS; - } else uiPunctureTimer -= diff; - - if (uiEnrageTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ENRAGE); - uiEnrageTimer = 20*IN_MILISECONDS; - } else uiEnrageTimer -= diff; - - if (uiStompTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STOMP); - uiStompTimer = 20*IN_MILISECONDS; - } else uiStompTimer -= diff; - - if (uiImpalingChargeTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, SPELL_IMPALING_CHARGE); - lImpaledPlayers.insert(pTarget->GetGUID()); - } - uiImpalingChargeTimer = 31*IN_MILISECONDS; - ++uiPhaseCounter; - } else uiImpalingChargeTimer -= diff; - } - break; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic()) - { - if (lImpaledPlayers.size() == 5) - pInstance->DoCompleteAchievement(ACHIEV_SHARE_THE_LOVE); - - AchievementEntry const *achievWhatTheEck = GetAchievementStore()->LookupEntry(ACHIEV_WHAT_THE_ECK); - if (achievWhatTheEck) - { - Map::PlayerList const &players = pInstance->instance->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - if (itr->getSource()->HasAura(SPELL_ECK_RESIDUE)) - itr->getSource()->CompletedAchievement(achievWhatTheEck); - } - } - - pInstance->SetData(DATA_GAL_DARAH_EVENT, DONE); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_gal_darah(Creature* pCreature) -{ - return new boss_gal_darahAI (pCreature); -} - -void AddSC_boss_gal_darah() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_gal_darah"; - newscript->GetAI = &GetAI_boss_gal_darah; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/gundrak/boss_moorabi.cpp b/src/server/scripts/Northrend/gundrak/boss_moorabi.cpp deleted file mode 100644 index 84a7d8bc654..00000000000 --- a/src/server/scripts/Northrend/gundrak/boss_moorabi.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -enum eSpells -{ - SPELL_DETERMINED_STAB = 55104, - SPELL_GROUND_TREMOR = 55142, - SPELL_NUMBING_SHOUT = 55106, - SPELL_DETERMINED_GORE = 55102, - H_SPELL_DETERMINED_GORE = 59444, - SPELL_QUAKE = 55101, - SPELL_NUMBING_ROAR = 55100, - SPELL_MOJO_FRENZY = 55163, - SPELL_TRANSFORMATION = 55098, //Periodic, The caster transforms into a powerful mammoth, increasing Physical damage done by 25% and granting immunity to Stun effects. -}; - -enum eArchivements -{ - ACHIEV_LESS_RABI = 2040 -}; - -enum eSays -{ - SAY_AGGRO = -1604010, - //SAY_SLAY_1 = -1604011, // not in db - SAY_SLAY_2 = -1604012, - SAY_SLAY_3 = -1604013, - SAY_DEATH = -1604014, - SAY_TRANSFORM = -1604015, - SAY_QUAKE = -1604016, - EMOTE_TRANSFORM = -1604017 -}; - -struct boss_moorabiAI : public ScriptedAI -{ - boss_moorabiAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bPhase; - - uint32 uiNumblingShoutTimer; - uint32 uiGroundTremorTimer; - uint32 uiDeterminedStabTimer; - uint32 uiTransformationTImer; - - void Reset() - { - uiGroundTremorTimer = 18*IN_MILISECONDS; - uiNumblingShoutTimer = 10*IN_MILISECONDS; - uiDeterminedStabTimer = 20*IN_MILISECONDS; - uiTransformationTImer = 12*IN_MILISECONDS; - bPhase = false; - - if (pInstance) - pInstance->SetData(DATA_MOORABI_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_MOJO_FRENZY, true); - - if (pInstance) - pInstance->SetData(DATA_MOORABI_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bPhase && me->HasAura(SPELL_TRANSFORMATION)) - { - bPhase = true; - me->RemoveAura(SPELL_MOJO_FRENZY); - } - - if (uiGroundTremorTimer <= uiDiff) - { - DoScriptText(SAY_QUAKE, me); - if (bPhase) - DoCast(me->getVictim(), SPELL_QUAKE, true); - else - DoCast(me->getVictim(), SPELL_GROUND_TREMOR, true); - uiGroundTremorTimer = 10*IN_MILISECONDS; - } else uiGroundTremorTimer -= uiDiff; - - if (uiNumblingShoutTimer <= uiDiff) - { - if (bPhase) - DoCast(me->getVictim(), SPELL_NUMBING_ROAR, true); - else - DoCast(me->getVictim(), SPELL_NUMBING_SHOUT, true); - uiNumblingShoutTimer = 10*IN_MILISECONDS; - } else uiNumblingShoutTimer -=uiDiff; - - if (uiDeterminedStabTimer <= uiDiff) - { - if (bPhase) - DoCast(me->getVictim(), SPELL_DETERMINED_GORE); - else - DoCast(me->getVictim(), SPELL_DETERMINED_STAB, true); - uiDeterminedStabTimer = 8*IN_MILISECONDS; - } else uiDeterminedStabTimer -=uiDiff; - - if (!bPhase && uiTransformationTImer <= uiDiff) - { - DoScriptText(EMOTE_TRANSFORM, me); - DoScriptText(SAY_TRANSFORM, me); - DoCast(me, SPELL_TRANSFORMATION, false); - uiTransformationTImer = 10*IN_MILISECONDS; - } else uiTransformationTImer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_MOORABI_EVENT, DONE); - - if (IsHeroic() && !bPhase) - pInstance->DoCompleteAchievement(ACHIEV_LESS_RABI); - } - } - - void KilledUnit(Unit* pVictim) - { - if (pVictim == me) - return; - - DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_moorabi(Creature *pCreature) -{ - return new boss_moorabiAI(pCreature); -} - -void AddSC_boss_moorabi() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_moorabi"; - newscript->GetAI = &GetAI_boss_moorabi; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp b/src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp deleted file mode 100644 index 1014beaeddd..00000000000 --- a/src/server/scripts/Northrend/gundrak/boss_slad_ran.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -//Spells -enum Spells -{ - SPELL_POISON_NOVA = 55081, - H_SPELL_POISON_NOVA = 59842, - SPELL_POWERFULL_BITE = 48287, - H_SPELL_POWERFULL_BITE = 59840, - SPELL_VENOM_BOLT = 54970, - H_SPELL_VENOM_BOLT = 59839 -}; - -//Yell -enum Yells -{ - SAY_AGGRO = -1604017, - SAY_SLAY_1 = -1604018, - SAY_SLAY_2 = -1604019, - SAY_SLAY_3 = -1604020, - SAY_DEATH = -1604021, - SAY_SUMMON_SNAKES = -1604022, - SAY_SUMMON_CONSTRICTORS = -1604023 -}; - -//Creatures -enum Creatures -{ - CREATURE_SNAKE = 29680, - CREATURE_CONSTRICTORS = 29713 -}; - -//Creatures' spells -enum ConstrictorSpells -{ - SPELL_GRIP_OF_SLAD_RAN = 55093, - SPELL_VENOMOUS_BITE = 54987, - H_SPELL_VENOMOUS_BITE = 58996 -}; - -static Position SpawnLoc[]= -{ - {1783.81, 646.637, 133.948, 3.71755}, - {1775.03, 606.586, 134.165, 1.43117}, - {1717.39, 630.041, 129.282, 5.96903}, - {1765.66, 646.542, 134.02, 5.11381}, - {1716.76, 635.159, 129.282, 0.191986} -}; - -struct boss_slad_ranAI : public ScriptedAI -{ - boss_slad_ranAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiPoisonNovaTimer; - uint32 uiPowerfullBiteTimer; - uint32 uiVenomBoltTimer; - uint32 uiSpawnTimer; - - uint8 uiPhase; - - SummonList lSummons; - - ScriptedInstance* pInstance; - - void Reset() - { - uiPoisonNovaTimer = 10*IN_MILISECONDS; - uiPowerfullBiteTimer = 3*IN_MILISECONDS; - uiVenomBoltTimer = 15*IN_MILISECONDS; - uiSpawnTimer = 5*IN_MILISECONDS; - uiPhase = 0; - - lSummons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_SLAD_RAN_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_SLAD_RAN_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiPoisonNovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_NOVA); - uiPoisonNovaTimer = 15*IN_MILISECONDS; - } else uiPoisonNovaTimer -= diff; - - if (uiPowerfullBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POWERFULL_BITE); - uiPowerfullBiteTimer = 10*IN_MILISECONDS; - } else uiPowerfullBiteTimer -= diff; - - if (uiVenomBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_VENOM_BOLT); - uiVenomBoltTimer = 10*IN_MILISECONDS; - } else uiVenomBoltTimer -= diff; - - if (uiPhase) - { - if (uiSpawnTimer <= diff) - { - if (uiPhase == 1) - for (uint8 i = 0; i < DUNGEON_MODE(3, 5); ++i) - me->SummonCreature(CREATURE_SNAKE, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); - if (uiPhase == 2) - for (uint8 i = 0; i < DUNGEON_MODE(3, 5); ++i) - me->SummonCreature(CREATURE_CONSTRICTORS, SpawnLoc[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN,20*IN_MILISECONDS); - uiSpawnTimer = 5*IN_MILISECONDS; - } else uiSpawnTimer -= diff; - } - - if (uiPhase == 0 && HealthBelowPct(30)) - { - DoScriptText(SAY_SUMMON_SNAKES,me); - uiPhase = 1; - } - - if (uiPhase == 1 && HealthBelowPct(25)) - { - DoScriptText(SAY_SUMMON_CONSTRICTORS,me); - uiPhase = 2; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_SLAD_RAN_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustSummoned(Creature* summoned) - { - summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); - lSummons.Summon(summoned); - } -}; - -struct mob_slad_ran_constrictorAI : public ScriptedAI -{ - mob_slad_ran_constrictorAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiGripOfSladRanTimer; - - void Reset() - { - uiGripOfSladRanTimer = 1*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - if (uiGripOfSladRanTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GRIP_OF_SLAD_RAN); - uiGripOfSladRanTimer = 5*IN_MILISECONDS; - } else uiGripOfSladRanTimer -= diff; - } - - ScriptedInstance* pInstance; -}; - -struct mob_slad_ran_viperAI : public ScriptedAI -{ - mob_slad_ran_viperAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiVenomousBiteTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiVenomousBiteTimer = 2*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiVenomousBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_VENOMOUS_BITE); - uiVenomousBiteTimer = 10*IN_MILISECONDS; - } else uiVenomousBiteTimer -= diff; - } -}; - -CreatureAI* GetAI_boss_slad_ran(Creature* pCreature) -{ - return new boss_slad_ranAI (pCreature); -} - -CreatureAI* GetAI_mob_slad_ran_constrictor(Creature* pCreature) -{ - return new mob_slad_ran_constrictorAI (pCreature); -} - -CreatureAI* GetAI_mob_slad_ran_viper(Creature* pCreature) -{ - return new mob_slad_ran_viperAI (pCreature); -} - -void AddSC_boss_slad_ran() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_slad_ran"; - newscript->GetAI = &GetAI_boss_slad_ran; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_slad_ran_constrictor"; - newscript->GetAI = &GetAI_mob_slad_ran_constrictor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_slad_ran_viper"; - newscript->GetAI = &GetAI_mob_slad_ran_viper; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/gundrak/gundrak.h b/src/server/scripts/Northrend/gundrak/gundrak.h deleted file mode 100644 index a443aa4e698..00000000000 --- a/src/server/scripts/Northrend/gundrak/gundrak.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef DEF_GUNDRAK_H -#define DEF_GUNDRAK_H - -enum Data -{ - DATA_SLAD_RAN_EVENT, - DATA_MOORABI_EVENT, - DATA_DRAKKARI_COLOSSUS_EVENT, - DATA_GAL_DARAH_EVENT, - DATA_ECK_THE_FEROCIOUS_EVENT, - DATA_ALIVE_RUIN_DWELLERS -}; - -enum Data64 -{ - DATA_SLAD_RAN_ALTAR, - DATA_MOORABI_ALTAR, - DATA_DRAKKARI_COLOSSUS_ALTAR, - DATA_SLAD_RAN_STATUE, - DATA_MOORABI_STATUE, - DATA_DRAKKARI_COLOSSUS_STATUE, - DATA_DRAKKARI_COLOSSUS, - DATA_RUIN_DWELLER_DIED -}; - -enum mainCreatures -{ - CREATURE_RUIN_DWELLER = 29920, - CREATURE_SLAD_RAN = 29304, - CREATURE_MOORABI = 29305, - CREATURE_GALDARAH = 29306, - CREATURE_DRAKKARICOLOSSUS = 29307, - CREATURE_ECK = 29932 -}; - -#endif diff --git a/src/server/scripts/Northrend/gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/gundrak/instance_gundrak.cpp deleted file mode 100644 index 4dd896f74f2..00000000000 --- a/src/server/scripts/Northrend/gundrak/instance_gundrak.cpp +++ /dev/null @@ -1,536 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "gundrak.h" - -#define MAX_ENCOUNTER 5 - -/* GunDrak encounters: -0 - Slad'Ran -1 - Moorabi -2 - Drakkari Colossus -3 - Gal'Darah -4 - Eck the Ferocious -*/ - -struct instance_gundrak : public ScriptedInstance -{ - instance_gundrak(Map* pMap) : ScriptedInstance(pMap) - { - bHeroicMode = pMap->IsHeroic(); - Initialize(); - }; - - bool bHeroicMode; - bool spawnSupport; - - uint32 timer; - uint32 phase; - uint64 toActivate; - - uint64 uiSladRan; - uint64 uiMoorabi; - uint64 uiDrakkariColossus; - uint64 uiGalDarah; - uint64 uiEckTheFerocious; - - uint64 uiSladRanAltar; - uint64 uiMoorabiAltar; - uint64 uiDrakkariColossusAltar; - uint64 uiSladRanStatue; - uint64 uiMoorabiStatue; - uint64 uiDrakkariColossusStatue; - uint64 uiGalDarahStatue; - uint64 uiEckTheFerociousDoor; - uint64 uiEckTheFerociousDoorBehind; - uint64 uiGalDarahDoor1; - uint64 uiGalDarahDoor2; - uint64 uiBridge; - uint64 uiCollision; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - GOState uiSladRanStatueState; - GOState uiMoorabiStatueState; - GOState uiDrakkariColossusStatueState; - GOState uiGalDarahStatueState; - GOState uiBridgeState; - GOState uiCollisionState; - - std::set DwellerGUIDs; - - std::string str_data; - - void Initialize() - { - spawnSupport = false; - - timer = 0; - phase = 0; - toActivate = 0; - - uiSladRan = 0; - uiMoorabi = 0; - uiDrakkariColossus = 0; - uiGalDarah = 0; - uiEckTheFerocious = 0; - - uiSladRanAltar = 0; - uiMoorabiAltar = 0; - uiDrakkariColossusAltar = 0; - - uiSladRanStatue = 0; - uiMoorabiStatue = 0; - uiDrakkariColossusStatue = 0; - uiGalDarahStatue = 0; - - uiEckTheFerociousDoor = 0; - uiEckTheFerociousDoorBehind = 0; - uiGalDarahDoor1 = 0; - uiGalDarahDoor2 = 0; - - uiBridge = 0; - uiCollision = 0; - - uiSladRanStatueState = GO_STATE_ACTIVE; - uiMoorabiStatueState = GO_STATE_ACTIVE; - uiDrakkariColossusStatueState = GO_STATE_ACTIVE; - uiGalDarahStatueState = GO_STATE_READY; - uiBridgeState = GO_STATE_ACTIVE; - uiCollisionState = GO_STATE_READY; - - DwellerGUIDs.clear(); - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case CREATURE_SLAD_RAN: uiSladRan = pCreature->GetGUID(); break; - case CREATURE_MOORABI: uiMoorabi = pCreature->GetGUID(); break; - case CREATURE_GALDARAH: uiGalDarah = pCreature->GetGUID(); break; - case CREATURE_DRAKKARICOLOSSUS: uiDrakkariColossus = pCreature->GetGUID(); break; - case CREATURE_ECK: uiEckTheFerocious = pCreature->GetGUID(); break; - case CREATURE_RUIN_DWELLER: - if (pCreature->isAlive()) - DwellerGUIDs.insert(pCreature->GetGUID()); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 192518: - uiSladRanAltar = pGo->GetGUID(); - // Make sure that they start out as unusuable - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - if (m_auiEncounter[0] == DONE) - { - if (uiSladRanStatueState == GO_STATE_ACTIVE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - else - { - ++phase; - pGo->SetGoState(GO_STATE_ACTIVE); - } - } - break; - case 192519: - uiMoorabiAltar = pGo->GetGUID(); - // Make sure that they start out as unusuable - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - if (m_auiEncounter[0] == DONE) - { - if (uiMoorabiStatueState == GO_STATE_ACTIVE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - else - { - ++phase; - pGo->SetGoState(GO_STATE_ACTIVE); - } - } - break; - case 192520: - uiDrakkariColossusAltar = pGo->GetGUID(); - // Make sure that they start out as unusuable - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - if (m_auiEncounter[0] == DONE) - { - if (uiDrakkariColossusStatueState == GO_STATE_ACTIVE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - else - { - ++phase; - pGo->SetGoState(GO_STATE_ACTIVE); - } - } - break; - case 192564: - uiSladRanStatue = pGo->GetGUID(); - pGo->SetGoState(uiSladRanStatueState); - break; - case 192565: - uiMoorabiStatue = pGo->GetGUID(); - pGo->SetGoState(uiMoorabiStatueState); - break; - case 192566: - uiGalDarahStatue = pGo->GetGUID(); - pGo->SetGoState(uiGalDarahStatueState); - break; - case 192567: - uiDrakkariColossusStatue = pGo->GetGUID(); - pGo->SetGoState(uiDrakkariColossusStatueState); - break; - case 192632: - uiEckTheFerociousDoor = pGo->GetGUID(); - if (bHeroicMode && m_auiEncounter[1] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 192569: - uiEckTheFerociousDoorBehind = pGo->GetGUID(); - if (bHeroicMode && m_auiEncounter[4] == DONE) - HandleGameObject(NULL,true,pGo); - case 193208: - uiGalDarahDoor1 = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 193209: - uiGalDarahDoor2 = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 193188: - uiBridge = pGo->GetGUID(); - pGo->SetGoState(uiBridgeState); - break; - case 192633: - uiCollision = pGo->GetGUID(); - pGo->SetGoState(uiCollisionState); - - // Can't spawn here with SpawnGameObject because pGo isn't added to world yet... - if (uiCollisionState == GO_STATE_ACTIVE_ALTERNATIVE) - spawnSupport = true; - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_SLAD_RAN_EVENT: - m_auiEncounter[0] = data; - if (data == DONE) - { - GameObject* pGo = instance->GetGameObject(uiSladRanAltar); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - } - break; - case DATA_MOORABI_EVENT: - m_auiEncounter[1] = data; - if (data == DONE) - { - GameObject* pGo = instance->GetGameObject(uiMoorabiAltar); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - if (bHeroicMode) - HandleGameObject(uiEckTheFerociousDoor,true); - } - break; - case DATA_DRAKKARI_COLOSSUS_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) - { - GameObject* pGo = instance->GetGameObject(uiDrakkariColossusAltar); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_UNK1); - } - break; - case DATA_GAL_DARAH_EVENT: - m_auiEncounter[3] = data; - if (data == DONE) - { - HandleGameObject(uiGalDarahDoor1,true); - HandleGameObject(uiGalDarahDoor2,true); - } - break; - case DATA_ECK_THE_FEROCIOUS_EVENT: - m_auiEncounter[4] = data; - if (bHeroicMode && data == DONE) - HandleGameObject(uiEckTheFerociousDoorBehind,true); - break; - } - - if (data == DONE) - SaveToDB(); - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_RUIN_DWELLER_DIED) - DwellerGUIDs.erase(data); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_SLAD_RAN_EVENT: return m_auiEncounter[0]; - case DATA_MOORABI_EVENT: return m_auiEncounter[1]; - case DATA_GAL_DARAH_EVENT: return m_auiEncounter[2]; - case DATA_DRAKKARI_COLOSSUS_EVENT: return m_auiEncounter[3]; - case DATA_ECK_THE_FEROCIOUS_EVENT: return m_auiEncounter[4]; - case DATA_ALIVE_RUIN_DWELLERS: return DwellerGUIDs.size(); - } - - return 0; - } - - uint64 GetData64(uint32 type) - { - switch(type) - { - case DATA_SLAD_RAN_ALTAR: return uiSladRanAltar; - case DATA_MOORABI_ALTAR: return uiMoorabiAltar; - case DATA_DRAKKARI_COLOSSUS_ALTAR: return uiDrakkariColossusAltar; - case DATA_SLAD_RAN_STATUE: return uiSladRanStatue; - case DATA_MOORABI_STATUE: return uiMoorabiStatue; - case DATA_DRAKKARI_COLOSSUS_STATUE: return uiDrakkariColossusStatue; - case DATA_DRAKKARI_COLOSSUS: return uiDrakkariColossus; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "G D " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " - << (uiSladRanStatue ? GetObjState(uiSladRanStatue) : GO_STATE_ACTIVE) << " " << (uiMoorabiStatue ? GetObjState(uiMoorabiStatue) : GO_STATE_ACTIVE) << " " - << (uiDrakkariColossusStatue ? GetObjState(uiDrakkariColossusStatue) : GO_STATE_ACTIVE) << " " << (uiGalDarahStatue ? GetObjState(uiGalDarahStatue) : GO_STATE_READY) << " " - << (uiBridge ? GetObjState(uiBridge) : GO_STATE_ACTIVE) << " " << (uiCollision ? GetObjState(uiCollision) : GO_STATE_READY); - - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 - >> data4 >> data5 >> data6 >> data7 >> data8 >> data9 >> data10; - - if (dataHead1 == 'G' && dataHead2 == 'D') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - uiSladRanStatueState = GOState(data5); - uiMoorabiStatueState = GOState(data6); - uiDrakkariColossusStatueState = GOState(data7); - uiGalDarahStatueState = GOState(data8); - uiBridgeState = GOState(data9); - uiCollisionState = GOState(data10); - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - bool QueueActivation(uint64 guid, uint32 time) - { - if (timer) - return false; - - toActivate = guid; - timer = time; - phase++; - return true; - } - - void Update(uint32 diff) - { - // Spawn the support for the bridge if necessary - if (spawnSupport) - { - if (GameObject* pCollision = instance->GetGameObject(uiCollision)) - pCollision->SummonGameObject(192743, pCollision->GetPositionX(), pCollision->GetPositionY(), pCollision->GetPositionZ(), pCollision->GetOrientation(), 0, 0, 0, 0, 0); - spawnSupport = false; - } - - // If there is nothing to activate, then return - if (!toActivate) - return; - - if (timer < diff) - { - timer = 0; - if (toActivate == uiBridge) - { - toActivate = 0; - GameObject* pBridge = instance->GetGameObject(uiBridge); - GameObject* pCollision = instance->GetGameObject(uiCollision); - GameObject* pSladRanStatue = instance->GetGameObject(uiSladRanStatue); - GameObject* pMoorabiStatue = instance->GetGameObject(uiMoorabiStatue); - GameObject* pDrakkariColossusStatue = instance->GetGameObject(uiDrakkariColossusStatue); - GameObject* pGalDarahStatue = instance->GetGameObject(uiGalDarahStatue); - - if (pBridge && pCollision && pSladRanStatue && pMoorabiStatue && pDrakkariColossusStatue && pGalDarahStatue) - { - pBridge->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pCollision->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pSladRanStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pMoorabiStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pDrakkariColossusStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pGalDarahStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - - // Add the GO that solidifies the bridge so you can walk on it - spawnSupport = true; - SaveToDB(); - } - } - else - { - uint32 spell = 0; - GameObject* pAltar = NULL; - if (toActivate == uiSladRanStatue) - { - spell = 57071; - pAltar = instance->GetGameObject(uiSladRanAltar); - } else if (toActivate == uiMoorabiStatue) - { - spell = 57068; - pAltar = instance->GetGameObject(uiMoorabiAltar); - } else if (toActivate == uiDrakkariColossusStatue) - { - spell = 57072; - pAltar = instance->GetGameObject(uiDrakkariColossusAltar); - } - - // This is a workaround to make the beam cast properly. The caster should be ID 30298 but since the spells - // all are with scripted target for that same ID, it will hit itself. - if (pAltar) - if (Creature* trigger = pAltar->SummonCreature(18721, pAltar->GetPositionX(), pAltar->GetPositionY(), pAltar->GetPositionZ() + 3, pAltar->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 5000)) - { - // Set the trigger model to invisible - trigger->SetDisplayId(11686); - trigger->CastSpell(trigger, spell, false); - } - - if (GameObject* statueGO = instance->GetGameObject(toActivate)) - statueGO->SetGoState(GO_STATE_READY); - - toActivate = 0; - - if (phase == 3) - QueueActivation(uiBridge, 3000); - else - SaveToDB(); // Don't save in between last statue and bridge turning in case of crash leading to stuck instance - } - } else timer -= diff; - } - - GOState GetObjState(uint64 guid) - { - if (GameObject* go = instance->GetGameObject(guid)) - return go->GetGoState(); - return GO_STATE_ACTIVE; - } -}; - -bool GOHello_altar(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - uint64 uiStatue = 0; - - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - if (pInstance) - { - switch(pGO->GetEntry()) - { - case 192518: uiStatue = pInstance->GetData64(DATA_SLAD_RAN_STATUE); break; - case 192519: uiStatue = pInstance->GetData64(DATA_MOORABI_STATUE); break; - case 192520: uiStatue = pInstance->GetData64(DATA_DRAKKARI_COLOSSUS_STATUE); break; - } - if (((instance_gundrak*)pInstance)->QueueActivation(uiStatue, 3500)) - { - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - } - return true; - } - return false; -} - -InstanceData* GetInstanceData_instance_gundrak(Map* pMap) -{ - return new instance_gundrak(pMap); -} - -void AddSC_instance_gundrak() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_gundrak"; - newscript->GetInstanceData = &GetInstanceData_instance_gundrak; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_gundrak_altar"; - newscript->pGOHello = &GOHello_altar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp deleted file mode 100644 index 896eb068eb6..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_anubrekhan.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SAY_GREET RAND(-1533000,-1533004,-1533005,-1533006,-1533007) -#define SAY_AGGRO RAND(-1533001,-1533002,-1533003) -#define SAY_SLAY -1533008 - -#define MOB_CRYPT_GUARD 16573 - -const Position GuardSummonPos = {3333.72, -3476.30, 287.1, 6.2801}; - -enum Events -{ - EVENT_NONE, - EVENT_IMPALE, - EVENT_LOCUST, - EVENT_SPAWN_GUARDIAN_NORMAL, - EVENT_BERSERK, -}; - -enum Spells -{ - SPELL_IMPALE_10 = 28783, - SPELL_IMPALE_25 = 56090, - SPELL_LOCUST_SWARM_10 = 28785, - SPELL_LOCUST_SWARM_25 = 54021, - SPELL_SUMMON_CORPSE_SCARABS_PLR = 29105, // This spawns 5 corpse scarabs on top of player - SPELL_SUMMON_CORPSE_SCARABS_MOB = 28864, // This spawns 10 corpse scarabs on top of dead guards - SPELL_BERSERK = 27680, -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 9891, -}; - -struct boss_anubrekhanAI : public BossAI -{ - boss_anubrekhanAI(Creature *c) : BossAI(c, BOSS_ANUBREKHAN) {} - - bool hasTaunted; - - void Reset() - { - _Reset(); - - hasTaunted = false; - - if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - { - Position pos; - - // respawn guard using home position, - // otherwise, after a wipe, they respawn where boss was at wipe moment. - pos = me->GetHomePosition(); - pos.m_positionY -= 10.0f; - me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); - - pos = me->GetHomePosition(); - pos.m_positionY += 10.0f; - me->SummonCreature(MOB_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); - } - } - - void KilledUnit(Unit* victim) - { - //Force the player to spawn corpse scarabs via spell, TODO: Check percent chance for scarabs, 20% at the moment - if (!(rand()%5)) - if (victim->GetTypeId() == TYPEID_PLAYER) - victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, NULL, NULL, me->GetGUID()); - - DoScriptText(SAY_SLAY, me); - } - - void JustDied(Unit *) - { - _JustDied(); - - // start achievement timer (kill Maexna within 20 min) - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO, me); - events.ScheduleEvent(EVENT_IMPALE, 10000 + rand()%10000); - events.ScheduleEvent(EVENT_LOCUST, 90000); - events.ScheduleEvent(EVENT_BERSERK, 600000); - - if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000,20000)); - } - - void MoveInLineOfSight(Unit *who) - { - if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER) - { - DoScriptText(SAY_GREET, me); - hasTaunted = true; - } - ScriptedAI::MoveInLineOfSight(who); - } - - void SummonedCreatureDespawn(Creature *summon) - { - BossAI::SummonedCreatureDespawn(summon); - - // check if it is an actual killed guard - if (!me->isAlive() || summon->isAlive() || summon->GetEntry() != MOB_CRYPT_GUARD) - return; - - summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, NULL, NULL, me->GetGUID()); - } - - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim() || !CheckInRoom()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_IMPALE: - //Cast Impale on a random target - //Do NOT cast it when we are afflicted by locust swarm - if (!me->HasAura(RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25))) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_IMPALE_10,SPELL_IMPALE_25)); - events.ScheduleEvent(EVENT_IMPALE, urand(10000,20000)); - break; - case EVENT_LOCUST: - // TODO : Add Text - DoCast(me, RAID_MODE(SPELL_LOCUST_SWARM_10,SPELL_LOCUST_SWARM_25)); - DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); - events.ScheduleEvent(EVENT_LOCUST, 90000); - break; - case EVENT_SPAWN_GUARDIAN_NORMAL: - // TODO : Add Text - DoSummon(MOB_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); - break; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK, true); - events.ScheduleEvent(EVENT_BERSERK, 600000); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_anubrekhan(Creature* pCreature) -{ - return new boss_anubrekhanAI (pCreature); -} - -void AddSC_boss_anubrekhan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_anubrekhan"; - newscript->GetAI = &GetAI_boss_anubrekhan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp deleted file mode 100644 index aa5a940eb8f..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_faerlina.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Yells -{ - SAY_GREET = -1533009, - SAY_AGGRO_1 = -1533010, - SAY_AGGRO_2 = -1533011, - SAY_AGGRO_3 = -1533012, - SAY_AGGRO_4 = -1533013, - SAY_SLAY_1 = -1533014, - SAY_SLAY_2 = -1533015, - SAY_DEATH = -1533016 -}; -//#define SOUND_RANDOM_AGGRO 8955 //soundId containing the 4 aggro sounds, we not using this - -enum Spells -{ - SPELL_POISON_BOLT_VOLLEY = 28796, - H_SPELL_POISON_BOLT_VOLLEY = 54098, - SPELL_RAIN_OF_FIRE = 28794, - H_SPELL_RAIN_OF_FIRE = 54099, - SPELL_FRENZY = 28798, - H_SPELL_FRENZY = 54100, - SPELL_WIDOWS_EMBRACE = 28732, - H_SPELL_WIDOWS_EMBRACE = 54097 -}; - -enum Events -{ - EVENT_NONE, - EVENT_POISON, - EVENT_FIRE, - EVENT_FRENZY -}; - -enum Achievements -{ - ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10 = 1997, - ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25 = 2140 -}; - -struct boss_faerlinaAI : public BossAI -{ - boss_faerlinaAI(Creature *c) : BossAI(c, BOSS_FAERLINA), greet(false) {} - - bool greet; - bool doDelayFrenzy; - bool bAchievement; - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4), me); - events.ScheduleEvent(EVENT_POISON, urand(10000,15000)); - events.ScheduleEvent(EVENT_FIRE, urand(6000,18000)); - events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000)); - } - - void Reset() - { - doDelayFrenzy = false; - bAchievement = true; - _Reset(); - } - - void MoveInLineOfSight(Unit *who) - { - if (!greet && who->GetTypeId() == TYPEID_PLAYER) - { - DoScriptText(SAY_GREET, me); - greet = true; - } - BossAI::MoveInLineOfSight(who); - } - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%3)) - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - - if (instance && bAchievement) - instance->DoCompleteAchievement(RAID_MODE(ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_10,ACHIEVEMENT_MOMMA_SAID_KNOCK_YOU_OUT_25)); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (doDelayFrenzy && !me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE, H_SPELL_WIDOWS_EMBRACE))) - { - doDelayFrenzy = false; - DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY), true); - } - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_POISON: - if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE))) - DoCastAOE(RAID_MODE(SPELL_POISON_BOLT_VOLLEY,H_SPELL_POISON_BOLT_VOLLEY)); - events.ScheduleEvent(EVENT_POISON, urand(8000,15000)); - break; - case EVENT_FIRE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_RAIN_OF_FIRE, H_SPELL_RAIN_OF_FIRE)); - events.ScheduleEvent(EVENT_FIRE, urand(6000,18000)); - break; - case EVENT_FRENZY: - // TODO : Add Text - if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE,H_SPELL_WIDOWS_EMBRACE))) - DoCast(me, RAID_MODE(SPELL_FRENZY, H_SPELL_FRENZY)); - else - doDelayFrenzy = true; - - events.ScheduleEvent(EVENT_FRENZY, urand(60000,80000)); - break; - } - } - - DoMeleeAttackIfReady(); - } - - void SpellHit(Unit* caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_WIDOWS_EMBRACE || spell->Id == H_SPELL_WIDOWS_EMBRACE) - { - // TODO : Add Text - bAchievement = false; - doDelayFrenzy = true; - me->Kill(caster); - } - } -}; - -CreatureAI* GetAI_boss_faerlina(Creature* pCreature) -{ - return new boss_faerlinaAI (pCreature); -} - -struct mob_faerlina_addAI : public ScriptedAI -{ - mob_faerlina_addAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - if (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) { - me->ApplySpellImmune(0, IMMUNITY_MECHANIC, SPELL_EFFECT_BIND, true); - me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true); - } - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance && getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - { - if (Creature *pFaerlina = pInstance->instance->GetCreature(pInstance->GetData64(DATA_FAERLINA))) - DoCast(pFaerlina, SPELL_WIDOWS_EMBRACE); - } - } -}; - -CreatureAI* GetAI_mob_faerlina_add(Creature* pCreature) -{ - return new mob_faerlina_addAI (pCreature); -} - -void AddSC_boss_faerlina() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_faerlina"; - newscript->GetAI = &GetAI_boss_faerlina; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_faerlina_add"; - newscript->GetAI = &GetAI_mob_faerlina_add; - newscript->RegisterSelf(); -} - - diff --git a/src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp deleted file mode 100644 index f04b39040db..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_four_horsemen.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Horsemen -{ - HORSEMEN_THANE, - HORSEMEN_LADY, - HORSEMEN_BARON, - HORSEMEN_SIR, -}; - -enum Events -{ - EVENT_NONE, - EVENT_MARK, - EVENT_CAST, - EVENT_BERSERK, -}; - -const Position WaypointPositions[12] = -{ - // Thane waypoints - {2542.3, -2984.1, 241.49, 5.362}, - {2547.6, -2999.4, 241.34, 5.049}, - {2542.9, -3015.0, 241.35, 4.654}, - // Lady waypoints - {2498.3, -2961.8, 241.28, 3.267}, - {2487.7, -2959.2, 241.28, 2.890}, - {2469.4, -2947.6, 241.28, 2.576}, - // Baron waypoints - {2553.8, -2968.4, 241.33, 5.757}, - {2564.3, -2972.5, 241.33, 5.890}, - {2583.9, -2971.67, 241.35, 0.008}, - // Sir waypoints - {2534.5, -2921.7, 241.53, 1.363}, - {2523.5, -2902.8, 241.28, 2.095}, - {2517.8, -2896.6, 241.28, 2.315}, -}; - -const uint32 MOB_HORSEMEN[] = {16064, 16065, 30549, 16063}; -const uint32 SPELL_MARK[] = {28832, 28833, 28834, 28835}; -#define SPELL_PRIMARY(i) RAID_MODE(SPELL_PRIMARY_N[i],SPELL_PRIMARY_H[i]) -const uint32 SPELL_PRIMARY_N[] = {28884, 28863, 28882, 28883}; -const uint32 SPELL_PRIMARY_H[] = {57467, 57463, 57369, 57466}; -#define SPELL_SECONDARY(i) RAID_MODE(SPELL_SECONDARY_N[i],SPELL_SECONDARY_H[i]) -const uint32 SPELL_SECONDARY_N[]= {0, 57374, 0, 57376}; -const uint32 SPELL_SECONDARY_H[]= {0, 57464, 0, 57465}; -const uint32 SPELL_PUNISH[] = {0, 57381, 0, 57377}; -#define SPELL_BERSERK 26662 - -// used by 16063,16064,16065,30549, but signed for 16063 -const int32 SAY_AGGRO[] = {-1533051, -1533044, -1533065, -1533058}; -const int32 SAY_TAUNT[3][4] ={ {-1533052, -1533045, -1533071, -1533059}, - {-1533053, -1533046, -1533072, -1533060}, - {-1533054, -1533047, -1533073, -1533061},}; -const int32 SAY_SPECIAL[] = {-1533055, -1533048, -1533070, -1533062}; -const int32 SAY_SLAY[] = {-1533056, -1533049, -1533068, -1533063}; -const int32 SAY_DEATH[] = {-1533057, -1533050, -1533074, -1533064}; - -#define SAY_BARON_AGGRO RAND(-1533065,-1533066,-1533067) -#define SAY_BARON_SLAY RAND(-1533068,-1533069) - -struct boss_four_horsemenAI : public BossAI -{ - boss_four_horsemenAI(Creature *c) : BossAI(c, BOSS_HORSEMEN) - { - id = Horsemen(0); - for (uint8 i = 0; i < 4; ++i) - if (me->GetEntry() == MOB_HORSEMEN[i]) - id = Horsemen(i); - caster = (id == HORSEMEN_LADY || id == HORSEMEN_SIR); - } - - Horsemen id; - uint64 uiEventStarterGUID; - uint8 nextWP; - uint32 punishTimer; - bool caster; - bool nextMovementStarted; - bool movementCompleted; - bool movementStarted; - bool encounterActionAttack; - bool encounterActionReset; - bool doDelayPunish; - - void Reset() - { - if (!encounterActionReset) - DoEncounterAction(NULL, false, true, false); - - if (instance) - instance->SetData(DATA_HORSEMEN0 + id, NOT_STARTED); - - me->SetReactState(REACT_AGGRESSIVE); - uiEventStarterGUID = 0; - nextWP = 0; - punishTimer = 2000; - nextMovementStarted = false; - movementCompleted = false; - movementStarted = false; - encounterActionAttack = false; - encounterActionReset = false; - doDelayPunish = false; - _Reset(); - } - - bool DoEncounterAction(Unit *who, bool attack, bool reset, bool checkAllDead) - { - if (!instance) - return false; - - Creature *Thane = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_THANE))); - Creature *Lady = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_LADY))); - Creature *Baron = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_BARON))); - Creature *Sir = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_SIR))); - - if (Thane && Lady && Baron && Sir) - { - if (attack && who) - { - CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionAttack = true; - CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionAttack = true; - CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionAttack = true; - CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionAttack = true; - - CAST_AI(boss_four_horsemenAI, Thane->AI())->AttackStart(who); - CAST_AI(boss_four_horsemenAI, Lady->AI())->AttackStart(who); - CAST_AI(boss_four_horsemenAI, Baron->AI())->AttackStart(who); - CAST_AI(boss_four_horsemenAI, Sir->AI())->AttackStart(who); - } - - if (reset) - { - if (instance->GetBossState(BOSS_HORSEMEN) != NOT_STARTED) - { - if (!Thane->isAlive()) - Thane->Respawn(); - - if (!Lady->isAlive()) - Lady->Respawn(); - - if (!Baron->isAlive()) - Baron->Respawn(); - - if (!Sir->isAlive()) - Sir->Respawn(); - - CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionReset = true; - CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionReset = true; - CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionReset = true; - CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionReset = true; - - CAST_AI(boss_four_horsemenAI, Thane->AI())->EnterEvadeMode(); - CAST_AI(boss_four_horsemenAI, Lady->AI())->EnterEvadeMode(); - CAST_AI(boss_four_horsemenAI, Baron->AI())->EnterEvadeMode(); - CAST_AI(boss_four_horsemenAI, Sir->AI())->EnterEvadeMode(); - } - } - - if (checkAllDead) - return !Thane->isAlive() && !Lady->isAlive() && !Baron->isAlive() && !Sir->isAlive(); - } - return false; - } - - void BeginFourHorsemenMovement() - { - movementStarted = true; - me->SetReactState(REACT_PASSIVE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true); - - switch(id) - { - case HORSEMEN_THANE: - me->GetMotionMaster()->MovePoint(0, WaypointPositions[0]); - break; - case HORSEMEN_LADY: - me->GetMotionMaster()->MovePoint(3, WaypointPositions[3]); - break; - case HORSEMEN_BARON: - me->GetMotionMaster()->MovePoint(6, WaypointPositions[6]); - break; - case HORSEMEN_SIR: - me->GetMotionMaster()->MovePoint(9, WaypointPositions[9]); - break; - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 2 || id == 5 || id == 8 || id == 11) - { - movementCompleted = true; - me->SetReactState(REACT_AGGRESSIVE); - - Unit *eventStarter = Unit::GetUnit(*me, uiEventStarterGUID); - - if (eventStarter && me->canAttack(eventStarter)) - AttackStart(eventStarter); - else if (!UpdateVictim()) - { - EnterEvadeMode(); - return; - } - - if (caster) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - } - - return; - } - - nextMovementStarted = false; - nextWP = id + 1; - } - - // switch to "who" if nearer than current target. - void SelectNearestTarget(Unit *who) - { - if (me->getVictim() && me->GetDistanceOrder(who, me->getVictim()) && me->canAttack(who)) - { - me->getThreatManager().modifyThreatPercent(me->getVictim(), -100); - me->AddThreat(who, 1000000.0f); - } - } - - void MoveInLineOfSight(Unit *who) - { - BossAI::MoveInLineOfSight(who); - if (caster) - SelectNearestTarget(who); - } - - void AttackStart(Unit *who) - { - if (!movementCompleted && !movementStarted) - { - uiEventStarterGUID = who->GetGUID(); - BeginFourHorsemenMovement(); - - if (!encounterActionAttack) - DoEncounterAction(who, true, false, false); - } - else if (movementCompleted && movementStarted) - { - if (caster) - me->Attack(who, false); - else - BossAI::AttackStart(who); - } - } - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%5)) - { - if (id == HORSEMEN_BARON) - DoScriptText(SAY_BARON_SLAY, me); - else - DoScriptText(SAY_SLAY[id], me); - } - } - - void JustDied(Unit* /*killer*/) - { - events.Reset(); - summons.DespawnAll(); - - if (instance) - instance->SetData(DATA_HORSEMEN0 + id, DONE); - - if (instance && DoEncounterAction(NULL, false, false, true)) - { - instance->SetBossState(BOSS_HORSEMEN, DONE); - instance->SaveToDB(); - - // Achievements related to the 4-horsemen are given through spell 59450 which does not exist. - // There is thus no way it can be given by casting the spell on the players. - instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59450); - } - - DoScriptText(SAY_DEATH[id], me); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - - if (id == HORSEMEN_BARON) - DoScriptText(SAY_BARON_AGGRO, me); - else - DoScriptText(SAY_AGGRO[id], me); - - events.ScheduleEvent(EVENT_MARK, 15000); - events.ScheduleEvent(EVENT_CAST, 20000+rand()%5000); - events.ScheduleEvent(EVENT_BERSERK, 15*100*1000); - } - - void UpdateAI(const uint32 diff) - { - if (nextWP && movementStarted && !movementCompleted && !nextMovementStarted) - { - nextMovementStarted = true; - me->GetMotionMaster()->MovePoint(nextWP, WaypointPositions[nextWP]); - } - - if (!UpdateVictim() || !CheckInRoom() || !movementCompleted) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_MARK: - if (!(rand()%5)) - DoScriptText(SAY_SPECIAL[id], me); - DoCastAOE(SPELL_MARK[id]); - events.ScheduleEvent(EVENT_MARK, 15000); - break; - case EVENT_CAST: - if (!(rand()%5)) - DoScriptText(SAY_TAUNT[rand()%3][id], me); - - if (caster) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) - DoCast(pTarget, SPELL_PRIMARY(id)); - } - else - DoCast(me->getVictim(), SPELL_PRIMARY(id)); - - events.ScheduleEvent(EVENT_CAST, 15000); - break; - case EVENT_BERSERK: - DoScriptText(SAY_SPECIAL[id], me); - DoCast(me, EVENT_BERSERK); - break; - } - } - - if (punishTimer <= diff) - { - if (doDelayPunish) - { - DoCastAOE(SPELL_PUNISH[id], true); - doDelayPunish = false; - } - punishTimer = 2000; - } else punishTimer -= diff; - - if (!caster) - DoMeleeAttackIfReady(); - else if ((!DoSpellAttackIfReady(SPELL_SECONDARY(id)) || !me->IsWithinLOSInMap(me->getVictim())) && movementCompleted && !doDelayPunish) - doDelayPunish = true; - } -}; - -CreatureAI* GetAI_four_horsemen(Creature* pCreature) -{ - return new boss_four_horsemenAI (pCreature); -} - -void AddSC_boss_four_horsemen() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_four_horsemen"; - newscript->GetAI = &GetAI_four_horsemen; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/naxxramas/boss_gluth.cpp deleted file mode 100644 index ab6fa6c46d3..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_gluth.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SPELL_MORTAL_WOUND 25646 -#define SPELL_ENRAGE RAID_MODE(28371,54427) -#define SPELL_DECIMATE RAID_MODE(28374,54426) -#define SPELL_BERSERK 26662 -#define SPELL_INFECTED_WOUND 29306 - -#define MOB_ZOMBIE 16360 - -const Position PosSummon[3] = -{ - {3267.9, -3172.1, 297.42, 0.94}, - {3253.2, -3132.3, 297.42, 0}, - {3308.3, -3185.8, 297.42, 1.58}, -}; - -enum Events -{ - EVENT_NONE, - EVENT_WOUND, - EVENT_ENRAGE, - EVENT_DECIMATE, - EVENT_BERSERK, - EVENT_SUMMON, -}; - -#define EMOTE_NEARBY " spots a nearby zombie to devour!" - -struct boss_gluthAI : public BossAI -{ - boss_gluthAI(Creature *c) : BossAI(c, BOSS_GLUTH) - { - // Do not let Gluth be affected by zombies' debuff - me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true); - } - - void MoveInLineOfSight(Unit *who) - { - if (who->GetEntry() == MOB_ZOMBIE && me->IsWithinDistInMap(who, 7)) - { - SetGazeOn(who); - // TODO: use a script text - me->MonsterTextEmote(EMOTE_NEARBY, 0, true); - } - else - BossAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - events.ScheduleEvent(EVENT_WOUND, 10000); - events.ScheduleEvent(EVENT_ENRAGE, 15000); - events.ScheduleEvent(EVENT_DECIMATE, 105000); - events.ScheduleEvent(EVENT_BERSERK, 8*60000); - events.ScheduleEvent(EVENT_SUMMON, 15000); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == MOB_ZOMBIE) - summon->AI()->AttackStart(me); - summons.Summon(summon); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictimWithGaze() || !CheckInRoom()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_WOUND: - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - events.ScheduleEvent(EVENT_WOUND, 10000); - break; - case EVENT_ENRAGE: - // TODO : Add missing text - DoCast(me, SPELL_ENRAGE); - events.ScheduleEvent(EVENT_ENRAGE, 15000); - break; - case EVENT_DECIMATE: - // TODO : Add missing text - DoCastAOE(SPELL_DECIMATE); - events.ScheduleEvent(EVENT_DECIMATE, 105000); - break; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - events.ScheduleEvent(EVENT_BERSERK, 5*60000); - break; - case EVENT_SUMMON: - for (uint32 i = 0; i < RAID_MODE(1,2); ++i) - DoSummon(MOB_ZOMBIE, PosSummon[rand()%3]); - events.ScheduleEvent(EVENT_SUMMON, 10000); - break; - } - } - - if (me->getVictim() && me->getVictim()->GetEntry() == MOB_ZOMBIE) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->Kill(me->getVictim()); - me->ModifyHealth(me->GetMaxHealth() * 0.05f); - } - } - else - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_gluth(Creature* pCreature) -{ - return new boss_gluthAI (pCreature); -} - -void AddSC_boss_gluth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gluth"; - newscript->GetAI = &GetAI_boss_gluth; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Northrend/naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/naxxramas/boss_gothik.cpp deleted file mode 100644 index d958ff24951..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_gothik.cpp +++ /dev/null @@ -1,582 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Yells -{ - SAY_SPEECH = -1533040, - SAY_KILL = -1533041, - SAY_DEATH = -1533042, - SAY_TELEPORT = -1533043 -}; -//Gothik -enum Spells -{ - SPELL_HARVEST_SOUL = 28679, - SPELL_SHADOW_BOLT = 29317, - H_SPELL_SHADOW_BOLT = 56405, - SPELL_INFORM_LIVE_TRAINEE = 27892, - SPELL_INFORM_LIVE_KNIGHT = 27928, - SPELL_INFORM_LIVE_RIDER = 27935, - SPELL_INFORM_DEAD_TRAINEE = 27915, - SPELL_INFORM_DEAD_KNIGHT = 27931, - SPELL_INFORM_DEAD_RIDER = 27937 -}; -enum Creatures -{ - MOB_LIVE_TRAINEE = 16124, - MOB_LIVE_KNIGHT = 16125, - MOB_LIVE_RIDER = 16126, - MOB_DEAD_TRAINEE = 16127, - MOB_DEAD_KNIGHT = 16148, - MOB_DEAD_RIDER = 16150, - MOB_DEAD_HORSE = 16149 -}; - -struct Waves { uint32 entry, time, mode; }; -// wave setups are not the same in heroic and normal difficulty, -// mode is 0 only normal, 1 both and 2 only heroic -// but this is handled in DoGothikSummon function -const Waves waves[] = -{ - {MOB_LIVE_TRAINEE, 20000, 1}, - {MOB_LIVE_TRAINEE, 20000, 1}, - {MOB_LIVE_TRAINEE, 10000, 1}, - {MOB_LIVE_KNIGHT, 10000, 1}, - {MOB_LIVE_TRAINEE, 15000, 1}, - {MOB_LIVE_KNIGHT, 5000, 1}, - {MOB_LIVE_TRAINEE, 20000, 1}, - {MOB_LIVE_TRAINEE, 0, 1}, - {MOB_LIVE_KNIGHT, 10000, 1}, - {MOB_LIVE_TRAINEE, 10000, 2}, - {MOB_LIVE_RIDER, 10000, 0}, - {MOB_LIVE_RIDER, 5000, 2}, - {MOB_LIVE_TRAINEE, 5000, 0}, - {MOB_LIVE_TRAINEE, 15000, 2}, - {MOB_LIVE_KNIGHT, 15000, 0}, - {MOB_LIVE_TRAINEE, 0, 0}, - {MOB_LIVE_RIDER, 10000, 1}, - {MOB_LIVE_KNIGHT, 10000, 1}, - {MOB_LIVE_TRAINEE, 10000, 0}, - {MOB_LIVE_RIDER, 10000, 2}, - {MOB_LIVE_TRAINEE, 0, 2}, - {MOB_LIVE_RIDER, 5000, 1}, - {MOB_LIVE_TRAINEE, 0, 2}, - {MOB_LIVE_KNIGHT, 5000, 1}, - {MOB_LIVE_RIDER, 0, 2}, - {MOB_LIVE_TRAINEE, 20000, 1}, - {MOB_LIVE_RIDER, 0, 1}, - {MOB_LIVE_KNIGHT, 0, 1}, - {MOB_LIVE_TRAINEE, 25000, 2}, - {MOB_LIVE_TRAINEE, 15000, 0}, - {MOB_LIVE_TRAINEE, 25000, 0}, - {0, 0, 1}, -}; - -#define POS_Y_GATE -3360.78f -#define POS_Y_WEST -3285.0f -#define POS_Y_EAST -3434.0f -#define POS_X_NORTH 2750.49f -#define POS_X_SOUTH 2633.84f - -#define IN_LIVE_SIDE(who) (who->GetPositionY() < POS_Y_GATE) - -enum Events -{ - EVENT_NONE, - EVENT_SUMMON, - EVENT_HARVEST, - EVENT_BOLT, - EVENT_TELEPORT -}; -enum Pos -{ - POS_LIVE = 6, - POS_DEAD = 5 -}; - -const Position PosSummonLive[POS_LIVE] = -{ - {2669.7, -3428.76, 268.56, 1.6}, - {2692.1, -3428.76, 268.56, 1.6}, - {2714.4, -3428.76, 268.56, 1.6}, - {2669.7, -3431.67, 268.56, 1.6}, - {2692.1, -3431.67, 268.56, 1.6}, - {2714.4, -3431.67, 268.56, 1.6}, -}; - -const Position PosSummonDead[POS_DEAD] = -{ - {2725.1, -3310.0, 268.85, 3.4}, - {2699.3, -3322.8, 268.60, 3.3}, - {2733.1, -3348.5, 268.84, 3.1}, - {2682.8, -3304.2, 268.85, 3.9}, - {2664.8, -3340.7, 268.23, 3.7}, -}; - -const float PosGroundLiveSide[4] = {2691.2, -3387.0, 267.68, 1.52}; -const float PosGroundDeadSide[4] = {2693.5, -3334.6, 267.68, 4.67}; -const float PosPlatform[4] = {2640.5, -3360.6, 285.26, 0}; - -// Predicate function to check that the r efzr unit is NOT on the same side as the source. -struct NotOnSameSide : public std::unary_function { - bool m_inLiveSide; - NotOnSameSide(Unit *pSource) : m_inLiveSide(IN_LIVE_SIDE(pSource)) {} - bool operator() (const Unit *pTarget) { - return (m_inLiveSide != IN_LIVE_SIDE(pTarget)); - } -}; - -struct boss_gothikAI : public BossAI -{ - boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK) {} - - uint32 waveCount; - typedef std::vector TriggerVct; - TriggerVct liveTrigger, deadTrigger; - bool mergedSides; - bool phaseTwo; - bool thirtyPercentReached; - - std::vector LiveTriggerGUID; - std::vector DeadTriggerGUID; - - void Reset() - { - LiveTriggerGUID.clear(); - DeadTriggerGUID.clear(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); - me->SetReactState(REACT_PASSIVE); - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); - _Reset(); - mergedSides = false; - phaseTwo = false; - thirtyPercentReached = false; - } - - void EnterCombat(Unit * /*who*/) - { - for (uint32 i = 0; i < POS_LIVE; ++i) - if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonLive[i])) - LiveTriggerGUID.push_back(trigger->GetGUID()); - for (uint32 i = 0; i < POS_DEAD; ++i) - if (Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonDead[i])) - DeadTriggerGUID.push_back(trigger->GetGUID()); - - if (LiveTriggerGUID.size() < POS_LIVE || DeadTriggerGUID.size() < POS_DEAD) - { - error_log("Script Gothik: cannot summon triggers!"); - EnterEvadeMode(); - return; - } - - _EnterCombat(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); - waveCount = 0; - events.ScheduleEvent(EVENT_SUMMON, 30000); - DoTeleportTo(PosPlatform); - DoScriptText(SAY_SPEECH, me); - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_READY); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == WORLD_TRIGGER) - summon->setActive(true); - else if (!mergedSides) - { - summon->AI()->DoAction(me->HasReactState(REACT_PASSIVE) ? 1 : 0); - summon->AI()->EnterEvadeMode(); - } - else - { - summon->AI()->DoAction(0); - summon->AI()->DoZoneInCombat(); - } - summons.Summon(summon); - } - - void SummonedCreatureDespawn(Creature *summon) - { - summons.Despawn(summon); - } - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*Killer*/) - { - LiveTriggerGUID.clear(); - DeadTriggerGUID.clear(); - _JustDied(); - DoScriptText(SAY_DEATH, me); - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); - } - - void DoGothikSummon(uint32 entry) - { - if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - { - switch(entry) - { - case MOB_LIVE_TRAINEE: - { - if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[0])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1); - if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[1])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1); - if (Creature *LiveTrigger2 = Unit::GetCreature(*me, LiveTriggerGUID[2])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger2, 1); - break; - } - case MOB_LIVE_KNIGHT: - { - if (Creature *LiveTrigger3 = Unit::GetCreature(*me, LiveTriggerGUID[3])) - DoSummon(MOB_LIVE_KNIGHT, LiveTrigger3, 1); - if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[5])) - DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1); - break; - } - case MOB_LIVE_RIDER: - { - if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1); - break; - } - } - } - else - { - switch(entry) - { - case MOB_LIVE_TRAINEE: - { - if (Creature *LiveTrigger0 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger0, 1); - if (Creature *LiveTrigger1 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_TRAINEE, LiveTrigger1, 1); - break; - } - case MOB_LIVE_KNIGHT: - { - if (Creature *LiveTrigger5 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_KNIGHT, LiveTrigger5, 1); - break; - } - case MOB_LIVE_RIDER: - { - if (Creature *LiveTrigger4 = Unit::GetCreature(*me, LiveTriggerGUID[4])) - DoSummon(MOB_LIVE_RIDER, LiveTrigger4, 1); - break; - } - } - } - } - - bool CheckGroupSplitted() - { - bool checklife = false; - bool checkdead = false; - - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->isAlive() && - i->getSource()->GetPositionX() <= POS_X_NORTH && - i->getSource()->GetPositionX() >= POS_X_SOUTH && - i->getSource()->GetPositionY() <= POS_Y_GATE && - i->getSource()->GetPositionY() >= POS_Y_EAST) - { - checklife = true; - } - else if (i->getSource() && i->getSource()->isAlive() && - i->getSource()->GetPositionX() <= POS_X_NORTH && - i->getSource()->GetPositionX() >= POS_X_SOUTH && - i->getSource()->GetPositionY() >= POS_Y_GATE && - i->getSource()->GetPositionY() <= POS_Y_WEST) - { - checkdead = true; - } - - if (checklife && checkdead) - return true; - } - } - } - - return false; - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - uint32 spellId = 0; - switch(spell->Id) - { - case SPELL_INFORM_LIVE_TRAINEE: spellId = SPELL_INFORM_DEAD_TRAINEE; break; - case SPELL_INFORM_LIVE_KNIGHT: spellId = SPELL_INFORM_DEAD_KNIGHT; break; - case SPELL_INFORM_LIVE_RIDER: spellId = SPELL_INFORM_DEAD_RIDER; break; - } - if (spellId && me->isInCombat()) - { - me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST); - if (Creature *pRandomDeadTrigger = Unit::GetCreature(*me, DeadTriggerGUID[rand() % POS_DEAD])) - me->CastSpell(pRandomDeadTrigger, spellId, true); - } - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (!me->isInCombat()) - return; - - switch(spell->Id) - { - case SPELL_INFORM_DEAD_TRAINEE: - DoSummon(MOB_DEAD_TRAINEE, pTarget, 0); - break; - case SPELL_INFORM_DEAD_KNIGHT: - DoSummon(MOB_DEAD_KNIGHT, pTarget, 0); - break; - case SPELL_INFORM_DEAD_RIDER: - DoSummon(MOB_DEAD_RIDER, pTarget, 1.0f); - DoSummon(MOB_DEAD_HORSE, pTarget, 1.0f); - break; - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateCombatState() || !CheckInRoom()) - return; - - events.Update(diff); - - if (!thirtyPercentReached && HealthBelowPct(30) && phaseTwo) - { - thirtyPercentReached = true; - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); - } - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SUMMON: - if (waves[waveCount].entry) - { - if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) - DoGothikSummon(waves[waveCount].entry); - else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) - DoGothikSummon(waves[waveCount].entry); - else if (waves[waveCount].mode == 1) - DoGothikSummon(waves[waveCount].entry); - - // if group is not splitted, open gate and merge both sides at ~ 2 minutes (wave 11) - if (waveCount == 11) - { - if (!CheckGroupSplitted()) - { - if (instance) - instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); - summons.DoAction(0, 0); - summons.DoZoneInCombat(); - mergedSides = true; - } - } - - if (waves[waveCount].mode == 1) - events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); - else if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) - events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); - else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) - events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); - else - events.ScheduleEvent(EVENT_SUMMON, 0); - - ++waveCount; - } - else - { - phaseTwo = true; - DoScriptText(SAY_TELEPORT, me); - DoTeleportTo(PosGroundLiveSide); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - summons.DoAction(0, 0); - summons.DoZoneInCombat(); - events.ScheduleEvent(EVENT_BOLT, 1000); - events.ScheduleEvent(EVENT_HARVEST, urand(3000,15000)); - events.ScheduleEvent(EVENT_TELEPORT, 20000); - } - break; - case EVENT_BOLT: - DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BOLT, H_SPELL_SHADOW_BOLT)); - events.ScheduleEvent(EVENT_BOLT, 1000); - break; - case EVENT_HARVEST: - DoCast(me->getVictim(), SPELL_HARVEST_SOUL, true); - events.ScheduleEvent(EVENT_HARVEST, urand(20000,25000)); - break; - case EVENT_TELEPORT: - if (!thirtyPercentReached) - { - me->AttackStop(); - if (IN_LIVE_SIDE(me)) - { - DoTeleportTo(PosGroundDeadSide); - } - else - { - DoTeleportTo(PosGroundLiveSide); - } - - me->getThreatManager().resetAggro(NotOnSameSide(me)); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0)) - { - me->getThreatManager().addThreat(pTarget, 100.0f); - AttackStart(pTarget); - } - - events.ScheduleEvent(EVENT_TELEPORT, 20000); - } - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_gothik_minionAI : public CombatAI -{ - mob_gothik_minionAI(Creature *c) : CombatAI(c) - { - liveSide = IN_LIVE_SIDE(me); - } - - bool liveSide; - bool gateClose; - - bool isOnSameSide(const Unit *pWho) - { - return (liveSide == IN_LIVE_SIDE(pWho)); - } - - void DoAction(const int32 param) - { - gateClose = param; - } - - void DamageTaken(Unit *attacker, uint32 &damage) - { - if (gateClose && !isOnSameSide(attacker)) - damage = 0; - } - - void JustDied(Unit * /*killer*/) - { - if (me->isSummon()) - { - if (Unit *owner = CAST_SUM(me)->GetSummoner()) - CombatAI::JustDied(owner); - } - } - - void EnterEvadeMode() - { - if (!gateClose) - { - CombatAI::EnterEvadeMode(); - return; - } - - if (!_EnterEvadeMode()) - return; - - Map* pMap = me->GetMap(); - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->isAlive() && isOnSameSide(i->getSource())) - { - AttackStart(i->getSource()); - return; - } - } - } - } - - me->GetMotionMaster()->MoveIdle(); - Reset(); - } - - void UpdateAI(const uint32 diff) - { - if (gateClose && (!isOnSameSide(me) || me->getVictim() && !isOnSameSide(me->getVictim()))) - { - EnterEvadeMode(); - return; - } - - CombatAI::UpdateAI(diff); - } -}; - -CreatureAI* GetAI_boss_gothik(Creature* pCreature) -{ - return new boss_gothikAI (pCreature); -} - -CreatureAI* GetAI_mob_gothik_minion(Creature* pCreature) -{ - return new mob_gothik_minionAI (pCreature); -} - -void AddSC_boss_gothik() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gothik"; - newscript->GetAI = &GetAI_boss_gothik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_gothik_minion"; - newscript->GetAI = &GetAI_mob_gothik_minion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp deleted file mode 100644 index 7df01e18483..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_grobbulus.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SPELL_BOMBARD_SLIME 28280 - -#define SPELL_POISON_CLOUD 28240 -#define SPELL_MUTATING_INJECTION 28169 -#define SPELL_SLIME_SPRAY RAID_MODE(28157,54364) -#define SPELL_BERSERK 26662 -#define SPELL_POISON_CLOUD_ADD 59116 - -#define EVENT_BERSERK 1 -#define EVENT_CLOUD 2 -#define EVENT_INJECT 3 -#define EVENT_SPRAY 4 - -#define MOB_FALLOUT_SLIME 16290 - -struct boss_grobbulusAI : public BossAI -{ - boss_grobbulusAI(Creature *c) : BossAI(c, BOSS_GROBBULUS) - { - me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_POISON_CLOUD_ADD, true); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - events.ScheduleEvent(EVENT_CLOUD, 15000); - events.ScheduleEvent(EVENT_INJECT, 20000); - events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure - events.ScheduleEvent(EVENT_BERSERK, 12*60000); - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (spell->Id == uint32(SPELL_SLIME_SPRAY)) - { - if (TempSummon *slime = me->SummonCreature(MOB_FALLOUT_SLIME, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0)) - DoZoneInCombat(slime); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CLOUD: - DoCastAOE(SPELL_POISON_CLOUD); - events.ScheduleEvent(EVENT_CLOUD, 15000); - return; - case EVENT_BERSERK: - DoCastAOE(SPELL_BERSERK); - return; - case EVENT_SPRAY: - DoCastAOE(SPELL_SLIME_SPRAY); - events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); - return; - case EVENT_INJECT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - if (!pTarget->HasAura(SPELL_MUTATING_INJECTION)) - DoCast(pTarget, SPELL_MUTATING_INJECTION); - events.ScheduleEvent(EVENT_INJECT, 8000 + 12000 * ((float)me->GetHealth() / me->GetMaxHealth())); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_grobbulus_poison_cloudAI : public Scripted_NoMovementAI -{ - npc_grobbulus_poison_cloudAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - Reset(); - } - - uint32 Cloud_Timer; - - void Reset() - { - Cloud_Timer = 1000; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void UpdateAI(const uint32 diff) - { - if (Cloud_Timer <= diff) - { - DoCast(me, SPELL_POISON_CLOUD_ADD); - Cloud_Timer = 10000; - } else Cloud_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_grobbulus(Creature* pCreature) -{ - return new boss_grobbulusAI (pCreature); -} - -CreatureAI* GetAI_npc_grobbulus_poison_cloud(Creature* pCreature) -{ - return new npc_grobbulus_poison_cloudAI(pCreature); -} - -void AddSC_boss_grobbulus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grobbulus"; - newscript->GetAI = &GetAI_boss_grobbulus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_grobbulus_poison_cloud"; - newscript->GetAI = &GetAI_npc_grobbulus_poison_cloud; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/naxxramas/boss_heigan.cpp deleted file mode 100644 index 1de9c0e00c8..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_heigan.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SAY_AGGRO RAND(-1533109,-1533110,-1533111) -#define SAY_SLAY -1533112 -#define SAY_TAUNT RAND(-1533113,-1533114,-1533115,-1533116,-1533117) -#define SAY_DEATH -1533118 - -#define SPELL_SPELL_DISRUPTION 29310 -#define SPELL_DECREPIT_FEVER RAID_MODE(29998,55011) -#define SPELL_PLAGUE_CLOUD 29350 - -enum Events -{ - EVENT_NONE, - EVENT_DISRUPT, - EVENT_FEVER, - EVENT_ERUPT, - EVENT_PHASE, -}; - -enum Phases -{ - PHASE_FIGHT = 1, - PHASE_DANCE, -}; - -struct boss_heiganAI : public BossAI -{ - boss_heiganAI(Creature *c) : BossAI(c, BOSS_HEIGAN) {} - - uint32 eruptSection; - bool eruptDirection; - Phases phase; - - void KilledUnit(Unit* /*Victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_SLAY, me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO, me); - EnterPhase(PHASE_FIGHT); - } - - void EnterPhase(Phases newPhase) - { - phase = newPhase; - events.Reset(); - eruptSection = 3; - if (phase == PHASE_FIGHT) - { - events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000)); - events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000)); - events.ScheduleEvent(EVENT_PHASE, 90000); - events.ScheduleEvent(EVENT_ERUPT, 15000); - } - else - { - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o); - DoCastAOE(SPELL_PLAGUE_CLOUD); - events.ScheduleEvent(EVENT_PHASE, 45000); - events.ScheduleEvent(EVENT_ERUPT, 8000); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim() || !CheckInRoom()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_DISRUPT: - DoCastAOE(SPELL_SPELL_DISRUPTION); - events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000)); - break; - case EVENT_FEVER: - DoCastAOE(SPELL_DECREPIT_FEVER); - events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000)); - break; - case EVENT_PHASE: - // TODO : Add missing texts for both phase switches - EnterPhase(phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT); - break; - case EVENT_ERUPT: - instance->SetData(DATA_HEIGAN_ERUPT, eruptSection); - TeleportCheaters(); - - if (eruptSection == 0) - eruptDirection = true; - else if (eruptSection == 3) - eruptDirection = false; - - eruptDirection ? ++eruptSection : --eruptSection; - - events.ScheduleEvent(EVENT_ERUPT, phase == PHASE_FIGHT ? 10000 : 3000); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_heigan(Creature* pCreature) -{ - return new boss_heiganAI (pCreature); -} - -void AddSC_boss_heigan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_heigan"; - newscript->GetAI = &GetAI_boss_heigan; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp b/src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp deleted file mode 100644 index 4eb72a3780e..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_highlord_mograine.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Highlord_Mograine -SD%Complete: 100 -SDComment: SCRIPT OBSOLETE -SDCategory: Naxxramas -EndScriptData */ - -#include "precompiled.h" - -//All horsemen -#define SPELL_SHIELDWALL 29061 -#define SPELL_BESERK 26662 - -// highlord mograine -#define SPELL_MARK_OF_MOGRAINE 28834 -#define SPELL_RIGHTEOUS_FIRE 28882 // Applied as a 25% chance on melee hit to proc. me->GetVictim() - -#define SAY_TAUNT1 "Enough prattling. Let them come! We shall grind their bones to dust." -#define SAY_TAUNT2 "Conserve your anger! Harness your rage! You will all have outlets for your frustration soon enough." -#define SAY_TAUNT3 "Life is meaningless. It is in death that we are truly tested." -#define SAY_AGGRO1 "You seek death?" -#define SAY_AGGRO2 "None shall pass!" -#define SAY_AGGRO3 "Be still!" -#define SAY_SLAY1 "You will find no peace in death." -#define SAY_SLAY2 "The master's will is done." -#define SAY_SPECIAL "Bow to the might of the Highlord!" -#define SAY_DEATH "I... am... released! Perhaps it's not too late to - noo! I need... more time..." - -#define SOUND_TAUNT1 8842 -#define SOUND_TAUNT2 8843 -#define SOUND_TAUNT3 8844 -#define SOUND_AGGRO1 8835 -#define SOUND_AGGRO2 8836 -#define SOUND_AGGRO3 8837 -#define SOUND_SLAY1 8839 -#define SOUND_SLAY2 8840 -#define SOUND_SPECIAL 8841 -#define SOUND_DEATH 8838 - -#define SPIRIT_OF_MOGRAINE 16775 - -struct TRINITY_DLL_DECL boss_highlord_mograineAI : public ScriptedAI -{ - boss_highlord_mograineAI(Creature *c) : ScriptedAI(c) {} - - uint32 Mark_Timer; - uint32 RighteousFire_Timer; - bool ShieldWall1; - bool ShieldWall2; - - void Reset() - { - Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. - RighteousFire_Timer = 2000; // applied approx 1 out of 4 attacks - ShieldWall1 = true; - ShieldWall2 = true; - } - - void InitialYell() - { - if (!me->isInCombat()) - { - switch(rand()%3) - { - case 0: - DoYell(SAY_AGGRO1,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_AGGRO1); - break; - case 1: - DoYell(SAY_AGGRO2,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_AGGRO2); - break; - case 2: - DoYell(SAY_AGGRO3,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_AGGRO3); - break; - } - } - } - - void KilledUnit() - { - switch(rand()%2) - { - case 0: - DoYell(SAY_SLAY1,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_SLAY1); - break; - case 1: - DoYell(SAY_SLAY2,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me,SOUND_SLAY2); - break; - } - } - - void JustDied(Unit* Killer) - { - DoYell(SAY_DEATH,LANG_UNIVERSAL,NULL); - DoPlaySoundToSet(me, SOUND_DEATH); - } - - void Aggro(Unit *who) - { - InitialYell(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Mark of Mograine - if (Mark_Timer < diff) - { - DoCast(me->getVictim(),SPELL_MARK_OF_MOGRAINE); - Mark_Timer = 12000; - }else Mark_Timer -= diff; - - // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds - if (ShieldWall1 && (me->GetHealth()*100 / me->GetMaxHealth()) < 50) - { - if (ShieldWall1) - { - DoCast(me,SPELL_SHIELDWALL); - ShieldWall1 = false; - } - } - if (ShieldWall2 && (me->GetHealth()*100 / me->GetMaxHealth()) < 20) - { - if (ShieldWall2) - { - DoCast(me,SPELL_SHIELDWALL); - ShieldWall2 = false; - } - } - - // Righteous Fire - if (RighteousFire_Timer < diff) - { - if (rand()%4 == 1) // 1/4 - { - DoCast(me->getVictim(),SPELL_RIGHTEOUS_FIRE); - } - RighteousFire_Timer = 2000; - }else RighteousFire_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_highlord_mograine(Creature* pCreature) -{ - return new boss_highlord_mograineAI (pCreature); -} - -void AddSC_boss_highlord_mograine() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_highlord_mograine"; - newscript->GetAI = &GetAI_boss_highlord_mograine; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp deleted file mode 100644 index bfcd0636298..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_kelthuzad.cpp +++ /dev/null @@ -1,706 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_KelThuzad -SD%Complete: 80% -SDComment: VERIFY SCRIPT -SDCategory: Naxxramas -EndScriptData */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Yells -{ - //when shappiron dies. dialog between kel and lich king (in this order) - SAY_SAPP_DIALOG1 = -1533084, //not used - SAY_SAPP_DIALOG2_LICH = -1533085, //not used - SAY_SAPP_DIALOG3 = -1533086, //not used - SAY_SAPP_DIALOG4_LICH = -1533087, //not used - SAY_SAPP_DIALOG5 = -1533088, //not used - SAY_CAT_DIED = -1533089, //when cat dies, not used - //when each of the 4 wing bosses dies - SAY_TAUNT1 = -1533090, //not used - SAY_TAUNT2 = -1533091, //not used - SAY_TAUNT3 = -1533092, //not used - SAY_TAUNT4 = -1533093, //not used - SAY_SUMMON_MINIONS = -1533105, //start of phase 1 - SAY_AGGRO_1 = -1533094, //start of phase 2 - SAY_AGGRO_2 = -1533095, - SAY_AGGRO_3 = -1533096, - SAY_SLAY_1 = -1533097, - SAY_SLAY_2 = -1533098, - SAY_DEATH = -1533099, - SAY_CHAIN_1 = -1533100, - SAY_CHAIN_2 = -1533101, - SAY_FROST_BLAST = -1533102, - SAY_SPECIAL_1 = -1533106, - SAY_SPECIAL_2 = -1533107, - SAY_SPECIAL_3 = -1533108, - SAY_REQUEST_AID = -1533103, //start of phase 3 - SAY_ANSWER_REQUEST = -1533104 //lich king answer -}; -enum Event -{ - EVENT_NONE, - EVENT_BOLT, - EVENT_NOVA, - EVENT_CHAIN, - EVENT_CHAINED_SPELL, - EVENT_DETONATE, - EVENT_FISSURE, - EVENT_BLAST, - - EVENT_WASTE, - EVENT_ABOMIN, - EVENT_WEAVER, - EVENT_ICECROWN, - EVENT_TRIGGER, - - EVENT_PHASE, -}; - -enum Spells -{ - SPELL_FROST_BOLT = 28478, - H_SPELL_FROST_BOLT = 55802, - SPELL_FROST_BOLT_AOE = 28479, - H_SPELL_FROST_BOLT_AOE = 55807, - SPELL_SHADOW_FISURE = 27810, - SPELL_VOID_BLAST = 27812, - SPELL_MANA_DETONATION = 27819, - SPELL_FROST_BLAST = 27808, - SPELL_CHAINS_OF_KELTHUZAD = 28410, //28408 script effect - SPELL_KELTHUZAD_CHANNEL = 29423, - SPELL_BERSERK = 28498, - - //spells for chained - //warlock - SPELL_CURSE_OF_AGONY = 47864, - SPELL_SHADOW_BOLT = 47809, - //shaman - SPELL_EARTH_SHOCK = 49231, - SPELL_HEALING_WAVE = 49273, - //mage - SPELL_FROST_FIREBOLT = 47610, - SPELL_ARCANE_MISSILES = 42846, - //rogue - SPELL_HEMORRHAGE = 48660, - SPELL_MUTILATE = 48666, - //paladin - SPELL_HOLY_SHOCK = 48825, - SPELL_HAMMER_OF_JUSTICE = 10308, - //priest - SPELL_VAMPIRIC_TOUCH = 48160, - SPELL_RENEW = 48068, - //hunter - SPELL_MULTI_SHOT = 49048, - SPELL_VOLLEY = 58434, - //warrior - SPELL_BLADESTORM = 46924, - SPELL_CLEAVE = 47520, - //druid - SPELL_MOONFIRE = 48463, - SPELL_LIFEBLOOM = 48451, - //death knight - SPELL_PLAGUE_STRIKE = 49921, - SPELL_HOWLING_BLAST = 51411, -}; - -enum Creatures -{ - NPC_WASTE = 16427, // Soldiers of the Frozen Wastes - NPC_ABOMINATION = 16428, // Unstoppable Abominations - NPC_WEAVER = 16429, // Soul Weavers - NPC_ICECROWN = 16441 // Guardians of Icecrown -}; - -const Position Pos[12] = -{ - {3783.272705, -5062.697266, 143.711203, 3.617599}, //LEFT_FAR - {3730.291260, -5027.239258, 143.956909, 4.461900}, //LEFT_MIDDLE - {3757.6, -5172.0, 143.7, 1.97}, //WINDOW_PORTAL05 - {3759.355225, -5174.128418, 143.802383, 2.170104}, //RIGHT_FAR - {3700.724365, -5185.123047, 143.928024, 1.309310}, //RIGHT_MIDDLE - {3700.86, -5181.29, 143.928024, 1.42}, //WINDOW_PORTAL04 - {3754.431396, -5080.727734, 142.036316, 3.736189}, //LEFT_FAR - {3724.396484, -5061.330566, 142.032700, 4.564785}, //LEFT_MIDDLE - {3732.02, -5028.53, 143.92, 4.49}, //WINDOW_PORTAL02 - {3687.571777, -5126.831055, 142.017807, 0.604023}, //RIGHT_FAR - {3707.990733, -5151.450195, 142.032562, 1.376855}, //RIGHT_MIDDLE - {3782.76, -5062.97, 143.79, 3.82}, //WINDOW_PORTAL03 -}; - -//creatures in corners -//Unstoppable Abominations -#define MAX_ABOMINATIONS 21 -const Position PosAbominations[MAX_ABOMINATIONS] = -{ - {3755.52, -5155.22, 143.480, 2.0}, - {3744.35, -5164.03, 143.590, 2.00}, - {3749.28, -5159.04, 143.190, 2.0}, - {3774.47, -5076.28, 143.528, 2.15912}, - {3765.94, -5074.15, 143.186, 3.77233}, - {3763.15, -5063.36, 143.694, 3.77233}, - {3737.81, -5045.69, 143.709, 4.9033}, - {3728.13, -5045.01, 143.355, 1.45069}, - {3721.56, -5048.35, 143.542, 1.45069}, - {3689.55, -5049.66, 143.637, 5.2104}, - {3681.71, -5053.03, 143.242, 2.47957}, - {3677.64, -5061.44, 143.358, 2.47957}, - {3654.2, -5090.87, 143.469, 1.0313}, - {3650.39, -5097.45, 143.496, 2.5047}, - {3658.7, -5103.59, 143.607, 3.3278}, - {3659.02, -5133.97, 143.624, 3.84538}, - {3666.33, -5139.34, 143.183, 3.84538}, - {3669.74, -5149.63, 143.678, 0.528643}, - {3695.53, -5169.53, 143.671, 2.11908}, - {3701.98, -5166.51, 143.395, 1.24257}, - {3709.62, -5169.15, 143.576, 5.97695}, -}; - -//Soldiers of the Frozen Wastes -#define MAX_WASTES 49 -const Position PosWastes[MAX_WASTES] = -{ - {3754.41, -5147.24, 143.204, 2.0}, - {3754.68, -5156.17, 143.418, 2.0}, - {3757.91, -5160.12, 143.503, 2.0}, - {3752.67, -5164.6, 143.395, 2.0}, - {3745.42, -5164.47, 143.565, 2.74587}, - {3741.2, -5155.92, 143.17, 5.29134}, - {3746.57, -5148.82, 143.176, 5.07772}, - {3778.14, -5070.1, 143.568, 3.16208}, - {3775.09, -5078.97, 143.65, 2.81022}, - {3773.54, -5083.47, 143.758, 3.21549}, - {3765, -5078.29, 143.176, 4.36688}, - {3766.94, -5072.63, 143.184, 5.27951}, - {3762.68, -5064.94, 143.635, 3.95297}, - {3769.9, -5059.94, 143.74, 3.36549}, - {3736.33, -5042.18, 143.643, 5.9471}, - {3727.51, -5040.58, 143.502, 0.871859}, - {3719.89, -5049.64, 143.58, 4.75172}, - {3720.69, -5044.43, 143.662, 1.87245}, - {3725.69, -5048.99, 143.363, 2.48271}, - {3732.33, -5054.01, 143.44, 3.59405}, - {3738.09, -5051.06, 143.718, 4.70931}, - {3682.76, -5063.5, 143.175, 0.636238}, - {3686.7, -5060.58, 143.18, 0.636238}, - {3682.45, -5057.21, 143.184, 5.61252}, - {3677.57, -5053.34, 143.369, 1.52531}, - {3677.3, -5062.26, 143.369, 2.73482}, - {3691.21, -5053.02, 143.421, 5.93218}, - {3685.22, -5053.34, 143.314, 4.70303}, - {3652.11, -5088.47, 143.555, 0.793317}, - {3648.23, -5093.21, 143.311, 1.18837}, - {3648.14, -5100.11, 143.632, 2.12221}, - {3653.88, -5099.7, 143.558, 3.04348}, - {3661.23, -5100.33, 143.42, 4.08335}, - {3663.49, -5092.77, 143.346, 4.47134}, - {3661.85, -5087.99, 143.571, 1.0148}, - {3664.56, -5149.01, 143.532, 0.0762528}, - {3665.01, -5142.04, 143.201, 1.72009}, - {3671.15, -5142.92, 143.174, 4.81535}, - {3670.18, -5134.38, 143.177, 5.37534}, - {3664.33, -5131.69, 143.262, 5.39576}, - {3658.21, -5133.63, 143.662, 1.3863}, - {3659.7, -5144.49, 143.363, 2.32328}, - {3705.71, -5179.63, 143.746, 1.06743}, - {3696.77, -5177.45, 143.759, 5.36748}, - {3700.97, -5173.13, 143.52, 3.26575}, - {3708.53, -5172.19, 143.573, 3.26575}, - {3712.49, -5167.62, 143.657, 5.63295}, - {3704.89, -5161.84, 143.239, 5.63295}, - {3695.66, -5164.63, 143.674, 1.54416}, -}; - -//Soul Weavers -#define MAX_WEAVERS 7 -const Position PosWeavers[MAX_WEAVERS] = -{ - {3752.45, -5168.35, 143.562, 1.6094}, - {3772.2, -5070.04, 143.329, 1.93686}, - {3732.28, -5032.88, 143.771, 3.08355}, - {3689.05, -5055.7, 143.172, 6.09554}, - {3649.45, -5093.17, 143.299, 2.51805}, - {3659.7, -5144.49, 143.363, 4.08806}, - {3704.71, -5175.96, 143.597, 3.36549}, -}; - -// predicate function to select not charmed target -struct NotCharmedTargetSelector : public std::unary_function { - NotCharmedTargetSelector() {} - - bool operator() (const Unit *pTarget) { - return (!pTarget->isCharmed()); - } -}; - -struct boss_kelthuzadAI : public BossAI -{ - boss_kelthuzadAI(Creature* c) : BossAI(c, BOSS_KELTHUZAD), spawns(c) - { - uiFaction = me->getFaction(); - } - - uint32 Phase; - uint32 uiGuardiansOfIcecrownTimer; - uint32 uiFaction; - - uint8 nGuardiansOfIcecrownCount; - uint8 nAbomination; - uint8 nWeaver; - - std::map chained; - - uint64 PortalsGUID[4]; - uint64 KTTriggerGUID; - - SummonList spawns; // adds spawn by the trigger. kept in separated list (i.e. not in summons) - - void Reset() - { - _Reset(); - - PortalsGUID[0] = PortalsGUID[1] = PortalsGUID[2] = PortalsGUID[3] = 0; - KTTriggerGUID = 0; - - me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - std::map::const_iterator itr; - for (itr = chained.begin(); itr != chained.end(); ++itr) - { - if (Player* charmed = Unit::GetPlayer((*itr).first)) - charmed->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); - } - - chained.clear(); - spawns.DespawnAll(); - - FindGameObjects(); - - if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID)) - { - pKTTrigger->ResetDoorOrButton(); - pKTTrigger->SetPhaseMask(1, true); - } - - for (uint8 i = 0; i <= 3; ++i) - { - if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) - { - if (!((pPortal->getLootState() == GO_READY) || (pPortal->getLootState() == GO_NOT_READY))) - pPortal->ResetDoorOrButton(); - } - } - - nGuardiansOfIcecrownCount = 0; - uiGuardiansOfIcecrownTimer = 5000; //5 seconds for summoning each Guardian of Icecrown in phase 3 - - Phase = 0; - nAbomination = 0; - nWeaver = 0; - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - - std::map::const_iterator itr; - for (itr = chained.begin(); itr != chained.end(); ++itr) - { - if (Player* pPlayer = Unit::GetPlayer((*itr).first)) - pPlayer->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); - } - chained.clear(); - } - - void EnterCombat(Unit* /*who*/) - { - me->setFaction(uiFaction); - - _EnterCombat(); - FindGameObjects(); - for (uint8 i = 0; i <= 3; ++i) - { - if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) - pPortal->ResetDoorOrButton(); - } - DoCast(me, SPELL_KELTHUZAD_CHANNEL, false); - DoScriptText(SAY_SUMMON_MINIONS, me); - Phase = 1; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4); - events.ScheduleEvent(EVENT_TRIGGER, 5000); - events.ScheduleEvent(EVENT_WASTE, 15000); - events.ScheduleEvent(EVENT_ABOMIN, 30000); - events.ScheduleEvent(EVENT_WEAVER, 50000); - events.ScheduleEvent(EVENT_PHASE, 228000); - } - - void FindGameObjects() - { - PortalsGUID[0] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL01) : 0; - PortalsGUID[1] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL02) : 0; - PortalsGUID[2] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL03) : 0; - PortalsGUID[3] = instance ? instance->GetData64(DATA_KELTHUZAD_PORTAL04) : 0; - KTTriggerGUID = instance ? instance->GetData64(DATA_KELTHUZAD_TRIGGER) : 0; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateCombatState()) - return; - - events.Update(diff); - - if (Phase == 1) - { - while (uint32 eventId = events.GetEvent()) - { - switch(eventId) - { - case EVENT_WASTE: - DoSummon(NPC_WASTE, Pos[RAND(0,3,6,9)]); - events.RepeatEvent(urand(2000,5000)); - break; - case EVENT_ABOMIN: - if (nAbomination < 8) - { - DoSummon(NPC_ABOMINATION, Pos[RAND(1,4,7,10)]); - nAbomination++; - events.RepeatEvent(20000); - } - else - events.PopEvent(); - break; - case EVENT_WEAVER: - if (nWeaver < 8) - { - DoSummon(NPC_WEAVER, Pos[RAND(0,3,6,9)]); - nWeaver++; - events.RepeatEvent(25000); - } - else - events.PopEvent(); - break; - case EVENT_TRIGGER: - if (GameObject *pKTTrigger = me->GetMap()->GetGameObject(KTTriggerGUID)) - pKTTrigger->SetPhaseMask(2, true); - events.PopEvent(); - break; - case EVENT_PHASE: - events.Reset(); - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - spawns.DespawnAll(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - me->CastStop(); - - DoStartMovement(me->getVictim()); - events.ScheduleEvent(EVENT_BOLT, urand(5000,10000)); - events.ScheduleEvent(EVENT_NOVA, 15000); - events.ScheduleEvent(EVENT_DETONATE, urand(30000,40000)); - events.ScheduleEvent(EVENT_FISSURE, urand(10000,30000)); - events.ScheduleEvent(EVENT_BLAST, urand(60000,120000)); - if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - events.ScheduleEvent(EVENT_CHAIN, urand(30000,60000)); - Phase = 2; - break; - default: - events.PopEvent(); - break; - } - } - } - else - { - //start phase 3 when we are 45% health - if (Phase != 3) - { - if (HealthBelowPct(45)) - { - Phase = 3 ; - DoScriptText(SAY_REQUEST_AID, me); - //here Lich King should respond to KelThuzad but I don't know which Creature to make talk - //so for now just make Kelthuzad says it. - DoScriptText(SAY_ANSWER_REQUEST, me); - - for (uint8 i = 0; i <= 3; ++i) - { - if (GameObject *pPortal = me->GetMap()->GetGameObject(PortalsGUID[i])) - { - if (pPortal->getLootState() == GO_READY) - pPortal->UseDoorOrButton(); - } - } - } - } - else if (nGuardiansOfIcecrownCount < RAID_MODE(2,4)) - { - if (uiGuardiansOfIcecrownTimer <= diff) - { - // TODO : Add missing text - if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2,5,8,11)])) - pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2); - ++nGuardiansOfIcecrownCount; - uiGuardiansOfIcecrownTimer = 5000; - } - else uiGuardiansOfIcecrownTimer -= diff; - } - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (uint32 eventId = events.GetEvent()) - { - switch(eventId) - { - case EVENT_BOLT: - DoCastVictim(RAID_MODE(SPELL_FROST_BOLT,H_SPELL_FROST_BOLT)); - events.RepeatEvent(urand(5000,10000)); - break; - case EVENT_NOVA: - DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE,H_SPELL_FROST_BOLT_AOE)); - events.RepeatEvent(urand(15000,30000)); - break; - case EVENT_CHAIN: - { - uint32 count = urand(1,3); - for (uint8 i = 1; i <= count; i++) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true); - if (pTarget && !pTarget->isCharmed() && (chained.find(pTarget->GetGUID()) == chained.end())) - { - DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD); - float scale = pTarget->GetFloatValue(OBJECT_FIELD_SCALE_X); - chained.insert(std::make_pair(pTarget->GetGUID(), scale)); - pTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2); - events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm - } - } - if (!chained.empty()) - DoScriptText(RAND(SAY_CHAIN_1,SAY_CHAIN_2), me); - events.RepeatEvent(urand(100000,180000)); - break; - } - case EVENT_CHAINED_SPELL: - { - std::map::iterator itr; - for (itr = chained.begin(); itr != chained.end();) - { - if (Unit* player = Unit::GetPlayer((*itr).first)) - { - if (!player->isCharmed()) - { - player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); - std::map::iterator next = itr; - ++next; - chained.erase(itr); - itr = next; - continue; - } - - if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector())) - { - switch(player->getClass()) - { - case CLASS_DRUID: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_MOONFIRE, false); - else - player->CastSpell(me, SPELL_LIFEBLOOM, false); - break; - case CLASS_HUNTER: - player->CastSpell(pTarget, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false); - break; - case CLASS_MAGE: - player->CastSpell(pTarget, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false); - break; - case CLASS_WARLOCK: - player->CastSpell(pTarget, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true); - break; - case CLASS_WARRIOR: - player->CastSpell(pTarget, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false); - break; - case CLASS_PALADIN: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_HAMMER_OF_JUSTICE, false); - else - player->CastSpell(me, SPELL_HOLY_SHOCK, false); - break; - case CLASS_PRIEST: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_VAMPIRIC_TOUCH, false); - else - player->CastSpell(me, SPELL_RENEW, false); - break; - case CLASS_SHAMAN: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_EARTH_SHOCK, false); - else - player->CastSpell(me, SPELL_HEALING_WAVE, false); - break; - case CLASS_ROGUE: - player->CastSpell(pTarget, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false); - break; - case CLASS_DEATH_KNIGHT: - if (urand(0,1)) - player->CastSpell(pTarget, SPELL_PLAGUE_STRIKE, true); - else - player->CastSpell(pTarget, SPELL_HOWLING_BLAST, true); - break; - } - } - } - ++itr; - } - - if (chained.empty()) - events.PopEvent(); - else - events.RepeatEvent(5000); - - break; - } - case EVENT_DETONATE: - { - std::vector unitList; - std::list *threatList = &me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr) - { - if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER - && (*itr)->getTarget()->getPowerType() == POWER_MANA - && (*itr)->getTarget()->GetPower(POWER_MANA)) - unitList.push_back((*itr)->getTarget()); - } - - if (!unitList.empty()) - { - std::vector::const_iterator itr = unitList.begin(); - advance(itr, rand()%unitList.size()); - DoCast(*itr, SPELL_MANA_DETONATION); - DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2,SAY_SPECIAL_3), me); - } - - events.RepeatEvent(urand(20000,50000)); - break; - } - case EVENT_FISSURE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_FISURE); - events.RepeatEvent(urand(10000,45000)); - break; - case EVENT_BLAST: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1,0), 0, true)) - DoCast(pTarget, SPELL_FROST_BLAST); - if (rand()%2) - DoScriptText(SAY_FROST_BLAST, me); - events.RepeatEvent(urand(30000,90000)); - break; - default: - events.PopEvent(); - break; - } - } - - DoMeleeAttackIfReady(); - } - } -}; - -CreatureAI* GetAI_boss_kelthuzadAI(Creature* pCreature) -{ - return new boss_kelthuzadAI (pCreature); -} - -bool AreaTrigger_at_kelthuzad_center(Player* pPlayer, const AreaTriggerEntry * /*at*/) -{ - if (pPlayer->isGameMaster()) - return false; - - ScriptedInstance* pInstance = pPlayer->GetInstanceData(); - if (!pInstance || pInstance->IsEncounterInProgress() || pInstance->GetBossState(BOSS_KELTHUZAD) == DONE) - return false; - - Creature* pKelthuzad = CAST_CRE(Unit::GetUnit(*pPlayer, pInstance->GetData64(DATA_KELTHUZAD))); - if (!pKelthuzad) - return false; - - boss_kelthuzadAI* pKelthuzadAI = CAST_AI(boss_kelthuzadAI, pKelthuzad->AI()); - if (!pKelthuzadAI) - return false; - - pKelthuzadAI->AttackStart(pPlayer); - if (GameObject* trigger = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_TRIGGER))) - { - if (trigger->getLootState() == GO_READY) - trigger->UseDoorOrButton(); - - // Note: summon must be done by trigger and not by KT. - // Otherwise, they attack immediately as KT is in combat. - for (uint8 i = 0; i <= MAX_ABOMINATIONS; ++i) - { - if (Creature* sum = trigger->SummonCreature(NPC_ABOMINATION, PosAbominations[i])) - { - pKelthuzadAI->spawns.Summon(sum); - sum->GetMotionMaster()->MoveRandom(9.0f); - sum->SetReactState(REACT_DEFENSIVE); - } - } - for (uint8 i = 0; i <= MAX_WASTES; ++i) - { - if (Creature* sum = trigger->SummonCreature(NPC_WASTE, PosWastes[i])) - { - pKelthuzadAI->spawns.Summon(sum); - sum->GetMotionMaster()->MoveRandom(5.0f); - sum->SetReactState(REACT_DEFENSIVE); - } - } - for (uint8 i = 0; i <= MAX_WEAVERS; ++i) - { - if (Creature* sum = trigger->SummonCreature(NPC_WEAVER, PosWeavers[i])) - { - pKelthuzadAI->spawns.Summon(sum); - sum->GetMotionMaster()->MoveRandom(9.0f); - sum->SetReactState(REACT_DEFENSIVE); - } - } - } - - return true; -} - -void AddSC_boss_kelthuzad() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kelthuzad"; - newscript->GetAI = &GetAI_boss_kelthuzadAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "at_kelthuzad_center"; - newscript->pAreaTrigger = &AreaTrigger_at_kelthuzad_center; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp deleted file mode 100644 index 0b0c8f5e4c5..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_loatheb.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Spells -{ - SPELL_NECROTIC_AURA = 55593, - SPELL_SUMMON_SPORE = 29234, - SPELL_DEATHBLOOM = 29865, - H_SPELL_DEATHBLOOM = 55053, - SPELL_INEVITABLE_DOOM = 29204, - H_SPELL_INEVITABLE_DOOM = 55052 -}; - -enum Events -{ - EVENT_NONE, - EVENT_AURA, - EVENT_BLOOM, - EVENT_DOOM, -}; - -struct boss_loathebAI : public BossAI -{ - boss_loathebAI(Creature *c) : BossAI(c, BOSS_LOATHEB) {} - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - events.ScheduleEvent(EVENT_AURA, 10000); - events.ScheduleEvent(EVENT_BLOOM, 5000); - events.ScheduleEvent(EVENT_DOOM, 120000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_AURA: - DoCastAOE(SPELL_NECROTIC_AURA); - events.ScheduleEvent(EVENT_AURA, 20000); - break; - case EVENT_BLOOM: - // TODO : Add missing text - DoCastAOE(SPELL_SUMMON_SPORE, true); - DoCastAOE(RAID_MODE(SPELL_DEATHBLOOM,H_SPELL_DEATHBLOOM)); - events.ScheduleEvent(EVENT_BLOOM, 30000); - break; - case EVENT_DOOM: - DoCastAOE(RAID_MODE(SPELL_INEVITABLE_DOOM,H_SPELL_INEVITABLE_DOOM)); - events.ScheduleEvent(EVENT_DOOM, events.GetTimer() < 5*60000 ? 30000 : 15000); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_loatheb(Creature* pCreature) -{ - return new boss_loathebAI (pCreature); -} - -enum SporeSpells -{ - SPELL_FUNGAL_CREEP = 29232 -}; - -struct mob_loatheb_sporeAI : public ScriptedAI -{ - mob_loatheb_sporeAI(Creature *c) : ScriptedAI(c) {} - - void JustDied(Unit* killer) - { - DoCast(killer, SPELL_FUNGAL_CREEP); - } -}; - -CreatureAI* GetAI_mob_loatheb_spore(Creature* pCreature) -{ - return new mob_loatheb_sporeAI (pCreature); -} - -void AddSC_boss_loatheb() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_loatheb"; - newscript->GetAI = &GetAI_boss_loatheb; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_loatheb_spore"; - newscript->GetAI = &GetAI_mob_loatheb_spore; - newscript->RegisterSelf(); - - // Fungal Creep - //GetAISpellInfo(29232)->condition = AICOND_DIE; -} - diff --git a/src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp deleted file mode 100644 index 71d9cb86102..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_maexxna.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Spells -{ - SPELL_WEB_WRAP = 28622, - SPELL_WEB_SPRAY_10 = 29484, - SPELL_WEB_SPRAY_25 = 54125, - SPELL_POISON_SHOCK_10 = 28741, - SPELL_POISON_SHOCK_25 = 54122, - SPELL_NECROTIC_POISON_10 = 28776, - SPELL_NECROTIC_POISON_25 = 54121, - SPELL_FRENZY_10 = 54123, - SPELL_FRENZY_25 = 54124, -}; - -enum Creatures -{ - MOB_WEB_WRAP = 16486, - MOB_SPIDERLING = 17055, -}; - -#define MAX_POS_WRAP 3 -const Position PosWrap[MAX_POS_WRAP] = -{ - {3546.796, -3869.082, 296.450, 0.0}, - {3531.271, -3847.424, 299.450, 0.0}, - {3497.067, -3843.384, 302.384, 0.0}, -}; - -enum Events -{ - EVENT_NONE, - EVENT_SPRAY, - EVENT_SHOCK, - EVENT_POISON, - EVENT_WRAP, - EVENT_SUMMON, - EVENT_FRENZY, -}; - -struct boss_maexxnaAI : public BossAI -{ - boss_maexxnaAI(Creature *c) : BossAI(c, BOSS_MAEXXNA) {} - - bool enraged; - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - enraged = false; - events.ScheduleEvent(EVENT_WRAP, 20000); - events.ScheduleEvent(EVENT_SPRAY, 40000); - events.ScheduleEvent(EVENT_SHOCK, urand(5000,10000)); - events.ScheduleEvent(EVENT_POISON, urand(10000,15000)); - events.ScheduleEvent(EVENT_SUMMON, 30000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim() || !CheckInRoom()) - return; - - if (!enraged && HealthBelowPct(30)) - { - enraged = true; - events.ScheduleEvent(EVENT_FRENZY, 0); // will be cast immediately - } - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_WRAP: - // TODO : Add missing text - for (uint8 i = 0; i < RAID_MODE(1,2); ++i) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP)) - { - pTarget->RemoveAura(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25)); - uint8 pos = rand()%MAX_POS_WRAP; - pTarget->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20); - if (Creature *wrap = DoSummon(MOB_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN)) - wrap->AI()->SetGUID(pTarget->GetGUID()); - } - } - events.ScheduleEvent(EVENT_WRAP, 40000); - break; - case EVENT_SPRAY: - DoCastAOE(RAID_MODE(SPELL_WEB_SPRAY_10,SPELL_WEB_SPRAY_25)); - events.ScheduleEvent(EVENT_SPRAY, 40000); - break; - case EVENT_SHOCK: - DoCastAOE(RAID_MODE(SPELL_POISON_SHOCK_10,SPELL_POISON_SHOCK_25)); - events.ScheduleEvent(EVENT_SHOCK, urand(10000,20000)); - break; - case EVENT_POISON: - DoCast(me->getVictim(), RAID_MODE(SPELL_NECROTIC_POISON_10,SPELL_NECROTIC_POISON_25)); - events.ScheduleEvent(EVENT_POISON, urand(10000, 20000)); - break; - case EVENT_FRENZY: - DoCast(me, RAID_MODE(SPELL_FRENZY_10,SPELL_FRENZY_25), true); - events.ScheduleEvent(EVENT_FRENZY, 600000); - break; - case EVENT_SUMMON: - // TODO : Add missing text - uint8 amount = urand(8,10); - for (uint8 i = 0; i < amount; ++i) - DoSummon(MOB_SPIDERLING, me, 0, TEMPSUMMON_CORPSE_DESPAWN); - events.ScheduleEvent(EVENT_SUMMON, 40000); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_webwrapAI : public NullCreatureAI -{ - mob_webwrapAI(Creature *c) : NullCreatureAI(c), victimGUID(0) {} - - uint64 victimGUID; - - void SetGUID(const uint64 &guid, int32 /*param*/) - { - victimGUID = guid; - if (me->m_spells[0] && victimGUID) - if (Unit *victim = Unit::GetUnit(*me, victimGUID)) - victim->CastSpell(victim, me->m_spells[0], true, NULL, NULL, me->GetGUID()); - } - - void JustDied(Unit * /*killer*/) - { - if (me->m_spells[0] && victimGUID) - if (Unit *victim = Unit::GetUnit(*me, victimGUID)) - victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID()); - } -}; - -CreatureAI* GetAI_boss_maexxna(Creature* pCreature) -{ - return new boss_maexxnaAI (pCreature); -} - -CreatureAI* GetAI_mob_webwrap(Creature* pCreature) -{ - return new mob_webwrapAI (pCreature); -} - -void AddSC_boss_maexxna() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_maexxna"; - newscript->GetAI = &GetAI_boss_maexxna; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_webwrap"; - newscript->GetAI = &GetAI_mob_webwrap; - newscript->RegisterSelf(); - -} - diff --git a/src/server/scripts/Northrend/naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/naxxramas/boss_noth.cpp deleted file mode 100644 index b0cd4018955..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_noth.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define SAY_AGGRO RAND(-1533075,-1533076,-1533077) -#define SAY_SUMMON -1533078 -#define SAY_SLAY RAND(-1533079,-1533080) -#define SAY_DEATH -1533081 - -#define SOUND_DEATH 8848 - -#define SPELL_CURSE_PLAGUEBRINGER RAID_MODE(29213,54835) -#define SPELL_BLINK RAND(29208,29209,29210,29211) -#define SPELL_CRIPPLE RAID_MODE(29212,54814) -#define SPELL_TELEPORT 29216 - -#define MOB_WARRIOR 16984 -#define MOB_CHAMPION 16983 -#define MOB_GUARDIAN 16981 - -// Teleport position of Noth on his balcony -#define TELE_X 2631.370 -#define TELE_Y -3529.680 -#define TELE_Z 274.040 -#define TELE_O 6.277 - -#define MAX_SUMMON_POS 5 - -const float SummonPos[MAX_SUMMON_POS][4] = -{ - {2728.12, -3544.43, 261.91, 6.04}, - {2729.05, -3544.47, 261.91, 5.58}, - {2728.24, -3465.08, 264.20, 3.56}, - {2704.11, -3456.81, 265.53, 4.51}, - {2663.56, -3464.43, 262.66, 5.20}, -}; - -enum Events -{ - EVENT_NONE, - EVENT_BERSERK, - EVENT_CURSE, - EVENT_BLINK, - EVENT_WARRIOR, - EVENT_BALCONY, - EVENT_WAVE, - EVENT_GROUND, -}; - -struct boss_nothAI : public BossAI -{ - boss_nothAI(Creature *c) : BossAI(c, BOSS_NOTH) {} - - uint32 waveCount, balconyCount; - - void Reset() - { - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - _Reset(); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO, me); - balconyCount = 0; - EnterPhaseGround(); - } - - void EnterPhaseGround() - { - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoZoneInCombat(); - if (me->getThreatManager().isThreatListEmpty()) - EnterEvadeMode(); - else - { - events.ScheduleEvent(EVENT_BALCONY, 110000); - events.ScheduleEvent(EVENT_CURSE, 10000+rand()%15000); - events.ScheduleEvent(EVENT_WARRIOR, 30000); - if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - events.ScheduleEvent(EVENT_BLINK, 20000 + rand()%20000); - } - } - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_SLAY, me); - } - - void JustSummoned(Creature *summon) - { - summons.Summon(summon); - summon->setActive(true); - summon->AI()->DoZoneInCombat(); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - } - - void SummonUndead(uint32 entry, uint32 num) - { - for (uint32 i = 0; i < num; ++i) - { - uint32 pos = rand()%MAX_SUMMON_POS; - me->SummonCreature(entry, SummonPos[pos][0], SummonPos[pos][1], SummonPos[pos][2], - SummonPos[pos][3], TEMPSUMMON_CORPSE_DESPAWN, 60000); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateCombatState() || !CheckInRoom()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CURSE: - DoCastAOE(SPELL_CURSE_PLAGUEBRINGER); - events.ScheduleEvent(EVENT_CURSE, 50000 + rand()%10000); - return; - case EVENT_WARRIOR: - DoScriptText(SAY_SUMMON, me); - SummonUndead(MOB_WARRIOR, RAID_MODE(2,3)); - events.ScheduleEvent(EVENT_WARRIOR, 30000); - return; - case EVENT_BLINK: - DoCastAOE(SPELL_CRIPPLE, true); - DoCastAOE(SPELL_BLINK); - DoResetThreat(); - events.ScheduleEvent(EVENT_BLINK, 40000); - return; - case EVENT_BALCONY: - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->AttackStop(); - me->RemoveAllAuras(); - me->NearTeleportTo(TELE_X, TELE_Y, TELE_Z, TELE_O); - events.Reset(); - events.ScheduleEvent(EVENT_WAVE, 2000 + rand()%3000); - waveCount = 0; - return; - case EVENT_WAVE: - DoScriptText(SAY_SUMMON, me); - switch(balconyCount) - { - case 0: SummonUndead(MOB_CHAMPION, RAID_MODE(2,4)); break; - case 1: SummonUndead(MOB_CHAMPION, RAID_MODE(1,2)); - SummonUndead(MOB_GUARDIAN, RAID_MODE(1,2)); break; - case 2: SummonUndead(MOB_GUARDIAN, RAID_MODE(2,4)); break; - default:SummonUndead(MOB_CHAMPION, RAID_MODE(5,10)); - SummonUndead(MOB_GUARDIAN, RAID_MODE(5,10));break; - } - ++waveCount; - events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, 30000 + rand()%15000); - return; - case EVENT_GROUND: - { - ++balconyCount; - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o); - events.ScheduleEvent(EVENT_BALCONY, 110000); - EnterPhaseGround(); - return; - } - } - } - - if (me->HasReactState(REACT_AGGRESSIVE)) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_noth(Creature* pCreature) -{ - return new boss_nothAI (pCreature); -} - -void AddSC_boss_noth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_noth"; - newscript->GetAI = &GetAI_boss_noth; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp deleted file mode 100644 index e4472b299ce..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_patchwerk.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright (C) 2008 - 2009 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -enum Spells -{ - SPELL_HATEFUL_STRIKE = 41926, - H_SPELL_HATEFUL_STRIKE = 59192, - SPELL_FRENZY = 28131, - SPELL_BERSERK = 26662, - SPELL_SLIME_BOLT = 32309, -}; - -enum Yells -{ - SAY_AGGRO_1 = -1533017, - SAY_AGGRO_2 = -1533018, - SAY_SLAY = -1533019, - SAY_DEATH = -1533020, - EMOTE_BERSERK = -1533021, - EMOTE_ENRAGE = -1533022, -}; - -enum Events -{ - EVENT_NONE, - EVENT_BERSERK, - EVENT_HATEFUL, - EVENT_SLIME -}; - -enum -{ - ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT = 10286, -}; - -struct boss_patchwerkAI : public BossAI -{ - boss_patchwerkAI(Creature *c) : BossAI(c, BOSS_PATCHWERK) {} - - bool Enraged; - - void Reset() - { - _Reset(); - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); - } - - void KilledUnit(Unit* /*Victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_SLAY, me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - Enraged = false; - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me); - events.ScheduleEvent(EVENT_HATEFUL, 1200); - events.ScheduleEvent(EVENT_BERSERK, 360000); - - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_HATEFUL: - { - //Cast Hateful strike on the player with the highest - //amount of HP within melee distance - uint32 MostHP = 0; - Unit* pMostHPTarget = NULL; - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit *pTarget = (*i)->getTarget(); - if (pTarget->isAlive() && pTarget->GetHealth() > MostHP && me->IsWithinMeleeRange(pTarget)) - { - MostHP = pTarget->GetHealth(); - pMostHPTarget = pTarget; - } - } - - if (pMostHPTarget) - DoCast(pMostHPTarget, RAID_MODE(SPELL_HATEFUL_STRIKE,H_SPELL_HATEFUL_STRIKE), true); - - events.ScheduleEvent(EVENT_HATEFUL, 1200); - break; - } - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK, true); - DoScriptText(EMOTE_BERSERK, me); - events.ScheduleEvent(EVENT_SLIME, 2000); - break; - case EVENT_SLIME: - DoCast(me->getVictim(), SPELL_SLIME_BOLT); - events.ScheduleEvent(EVENT_SLIME, 2000); - break; - } - } - - if (!Enraged && HealthBelowPct(5)) - { - DoCast(me, SPELL_FRENZY, true); - DoScriptText(EMOTE_ENRAGE, me); - Enraged = true; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_patchwerk(Creature* pCreature) -{ - return new boss_patchwerkAI (pCreature); -} - -void AddSC_boss_patchwerk() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_patchwerk"; - newscript->GetAI = &GetAI_boss_patchwerk; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp deleted file mode 100644 index d507df86e83..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_razuvious.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -//Razuvious - NO TEXT sound only -//8852 aggro01 - Hah hah, I'm just getting warmed up! -//8853 aggro02 Stand and fight! -//8854 aggro03 Show me what you've got! -//8861 slay1 - You should've stayed home! -//8863 slay2- -//8858 cmmnd3 - You disappoint me, students! -//8855 cmmnd1 - Do as I taught you! -//8856 cmmnd2 - Show them no mercy! -//8859 cmmnd4 - The time for practice is over! Show me what you've learned! -//8861 Sweep the leg! Do you have a problem with that? -//8860 death - An honorable... death... -//8947 - Aggro Mixed? - ? - -#define SOUND_AGGRO RAND(8852,8853,8854) -#define SOUND_SLAY RAND(8861,8863) -#define SOUND_COMMND RAND(8855,8856,8858,8859,8861) -#define SOUND_DEATH 8860 -#define SOUND_AGGROMIX 8847 - -#define SPELL_UNBALANCING_STRIKE 26613 -#define SPELL_DISRUPTING_SHOUT RAID_MODE(29107,55543) -#define SPELL_JAGGED_KNIFE 55550 -#define SPELL_HOPELESS 29125 - -enum Events -{ - EVENT_NONE, - EVENT_STRIKE, - EVENT_SHOUT, - EVENT_KNIFE, - EVENT_COMMAND, -}; - -struct boss_razuviousAI : public BossAI -{ - boss_razuviousAI(Creature *c) : BossAI(c, BOSS_RAZUVIOUS) {} - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%3)) - DoPlaySoundToSet(me, SOUND_SLAY); - } - - void DamageTaken(Unit* pDone_by, uint32& uiDamage) - { - // Damage done by the controlled Death Knight understudies should also count toward damage done by players - if (pDone_by->GetTypeId() == TYPEID_UNIT && (pDone_by->GetEntry() == 16803 || pDone_by->GetEntry() == 29941)) - { - me->LowerPlayerDamageReq(uiDamage); - } - } - - void JustDied(Unit* /*killer*/) - { - _JustDied(); - DoPlaySoundToSet(me, SOUND_DEATH); - me->CastSpell(me, SPELL_HOPELESS, true); // TODO: this may affect other creatures - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoPlaySoundToSet(me, SOUND_AGGRO); - events.ScheduleEvent(EVENT_STRIKE, 30000); - events.ScheduleEvent(EVENT_SHOUT, 25000); - events.ScheduleEvent(EVENT_COMMAND, 40000); - events.ScheduleEvent(EVENT_KNIFE, 10000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_STRIKE: - DoCast(me->getVictim(), SPELL_UNBALANCING_STRIKE); - events.ScheduleEvent(EVENT_STRIKE, 30000); - return; - case EVENT_SHOUT: - DoCastAOE(SPELL_DISRUPTING_SHOUT); - events.ScheduleEvent(EVENT_SHOUT, 25000); - return; - case EVENT_KNIFE: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) - DoCast(pTarget, SPELL_JAGGED_KNIFE); - events.ScheduleEvent(EVENT_KNIFE, 10000); - return; - case EVENT_COMMAND: - DoPlaySoundToSet(me, SOUND_COMMND); - events.ScheduleEvent(EVENT_COMMAND, 40000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_razuvious(Creature* pCreature) -{ - return new boss_razuviousAI (pCreature); -} - -void AddSC_boss_razuvious() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_razuvious"; - newscript->GetAI = &GetAI_boss_razuvious; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp deleted file mode 100644 index d75b3ab78b0..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_sapphiron.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -#define EMOTE_BREATH -1533082 -#define EMOTE_ENRAGE -1533083 - -#define SPELL_FROST_AURA RAID_MODE(28531,55799) -#define SPELL_CLEAVE 19983 -#define SPELL_TAIL_SWEEP RAID_MODE(55697,55696) -#define SPELL_SUMMON_BLIZZARD 28560 -#define SPELL_LIFE_DRAIN RAID_MODE(28542,55665) -#define SPELL_ICEBOLT 28522 -#define SPELL_FROST_BREATH 29318 -#define SPELL_FROST_EXPLOSION 28524 -#define SPELL_FROST_MISSILE 30101 -#define SPELL_BERSERK 26662 -#define SPELL_DIES 29357 - -#define SPELL_CHILL RAID_MODE(28547,55699) - -#define MOB_BLIZZARD 16474 -#define GO_ICEBLOCK 181247 - -#define ACHIEVEMENT_THE_HUNDRED_CLUB RAID_MODE(2146, 2147) -#define MAX_FROST_RESISTANCE 100 - -enum Phases -{ - PHASE_NULL = 0, - PHASE_BIRTH, - PHASE_GROUND, - PHASE_FLIGHT, -}; - -enum Events -{ - EVENT_NONE, - EVENT_BERSERK, - EVENT_CLEAVE, - EVENT_TAIL, - EVENT_DRAIN, - EVENT_BLIZZARD, - EVENT_FLIGHT, - EVENT_LIFTOFF, - EVENT_ICEBOLT, - EVENT_BREATH, - EVENT_EXPLOSION, - EVENT_LAND, - EVENT_GROUND, - EVENT_BIRTH, -}; - -typedef std::map IceBlockMap; - -struct boss_sapphironAI : public BossAI -{ - boss_sapphironAI(Creature* c) : BossAI(c, BOSS_SAPPHIRON) - , phase(PHASE_NULL) - { - pMap = me->GetMap(); - } - - Phases phase; - uint32 iceboltCount; - IceBlockMap iceblocks; - - bool CanTheHundredClub; // needed for achievement: The Hundred Club(2146, 2147) - uint32 CheckFrostResistTimer; - Map* pMap; - - void InitializeAI() - { - float x, y, z; - me->GetPosition(x, y, z); - me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - - ScriptedAI::InitializeAI(); - } - - void Reset() - { - _Reset(); - - if (phase == PHASE_FLIGHT) - ClearIceBlock(); - - phase = PHASE_NULL; - - CanTheHundredClub = true; - CheckFrostResistTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - - me->CastSpell(me, SPELL_FROST_AURA, true); - - events.ScheduleEvent(EVENT_BERSERK, 15*60000); - EnterPhaseGround(); - - CheckPlayersFrostResist(); - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (spell->Id == SPELL_ICEBOLT) - { - IceBlockMap::iterator itr = iceblocks.find(pTarget->GetGUID()); - if (itr != iceblocks.end() && !itr->second) - { - if (GameObject *iceblock = me->SummonGameObject(GO_ICEBLOCK, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, 0, 0, 0, 0, 25000)) - itr->second = iceblock->GetGUID(); - } - } - } - - void JustDied(Unit* /*who*/) - { - _JustDied(); - me->CastSpell(me, SPELL_DIES, true); - - CheckPlayersFrostResist(); - if (CanTheHundredClub) - { - AchievementEntry const *AchievTheHundredClub = GetAchievementStore()->LookupEntry(ACHIEVEMENT_THE_HUNDRED_CLUB); - if (AchievTheHundredClub) - { - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievTheHundredClub); - } - } - } - } - - void MovementInform(uint32, uint32 id) - { - if (id == 1) - events.ScheduleEvent(EVENT_LIFTOFF, 0); - } - - void DoAction(const int32 param) - { - if (param == DATA_SAPPHIRON_BIRTH) - { - phase = PHASE_BIRTH; - events.ScheduleEvent(EVENT_BIRTH, 23000); - } - } - - void CheckPlayersFrostResist() - { - if (CanTheHundredClub && pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (itr->getSource()->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE) - { - CanTheHundredClub = false; - break; - } - } - } - } - - void EnterPhaseGround() - { - phase = PHASE_GROUND; - me->SetReactState(REACT_AGGRESSIVE); - events.SetPhase(PHASE_GROUND); - events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_BLIZZARD, 5000+rand()%5000, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_FLIGHT, 45000); - } - - void ClearIceBlock() - { - for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr) - { - if (Player* pPlayer = Unit::GetPlayer(itr->first)) - pPlayer->RemoveAura(SPELL_ICEBOLT); - if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second)) - pGo->Delete(); - } - iceblocks.clear(); - } - - void UpdateAI(const uint32 diff) - { - if (!phase) - return; - - events.Update(diff); - - if (phase != PHASE_BIRTH && !UpdateCombatState() || !CheckInRoom()) - return; - - if (CanTheHundredClub) - { - if (CheckFrostResistTimer <= diff) - { - CheckPlayersFrostResist(); - CheckFrostResistTimer = (rand() % 5 + 5) * 1000; - } else CheckFrostResistTimer -= diff; - } - - if (phase == PHASE_GROUND) - { - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BERSERK: - DoScriptText(EMOTE_ENRAGE, me); - DoCast(me, SPELL_BERSERK); - return; - case EVENT_CLEAVE: - DoCast(me->getVictim(), SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); - return; - case EVENT_TAIL: - DoCastAOE(SPELL_TAIL_SWEEP); - events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); - return; - case EVENT_DRAIN: - DoCastAOE(SPELL_LIFE_DRAIN); - events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); - return; - case EVENT_BLIZZARD: - { - //DoCastAOE(SPELL_SUMMON_BLIZZARD); - if (Creature *pSummon = DoSummon(MOB_BLIZZARD, me, 0.0f, urand(25000,30000), TEMPSUMMON_TIMED_DESPAWN)) - pSummon->GetMotionMaster()->MoveRandom(40); - events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20000,7000), 0, PHASE_GROUND); - break; - } - case EVENT_FLIGHT: - phase = PHASE_FLIGHT; - events.SetPhase(PHASE_FLIGHT); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->GetMotionMaster()->MovePoint(1, x, y, z); - return; - } - } - - DoMeleeAttackIfReady(); - } - else - { - if (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_LIFTOFF: - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SendMovementFlagUpdate(); - events.ScheduleEvent(EVENT_ICEBOLT, 1500); - iceboltCount = RAID_MODE(2,3); - return; - case EVENT_ICEBOLT: - { - std::vector targets; - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT)) - targets.push_back((*i)->getTarget()); - - if (targets.empty()) - iceboltCount = 0; - else - { - std::vector::const_iterator itr = targets.begin(); - advance(itr, rand()%targets.size()); - iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0)); - DoCast(*itr, SPELL_ICEBOLT); - --iceboltCount; - } - - if (iceboltCount) - events.ScheduleEvent(EVENT_ICEBOLT, 1000); - else - events.ScheduleEvent(EVENT_BREATH, 1000); - return; - } - case EVENT_BREATH: - { - DoScriptText(EMOTE_BREATH, me); - DoCastAOE(SPELL_FROST_MISSILE); - events.ScheduleEvent(EVENT_EXPLOSION, 8000); - return; - } - case EVENT_EXPLOSION: - CastExplosion(); - ClearIceBlock(); - events.ScheduleEvent(EVENT_LAND, 3000); - return; - case EVENT_LAND: - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->SendMovementFlagUpdate(); - events.ScheduleEvent(EVENT_GROUND, 1500); - return; - case EVENT_GROUND: - EnterPhaseGround(); - return; - case EVENT_BIRTH: - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - return; - } - }//if (uint32 eventId = events.ExecuteEvent()) - }//if (phase == PHASE_GROUND) - } - - void CastExplosion() - { - DoZoneInCombat(); // make sure everyone is in threatlist - std::vector targets; - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit *pTarget = (*i)->getTarget(); - if (pTarget->GetTypeId() != TYPEID_PLAYER) - continue; - - if (pTarget->HasAura(SPELL_ICEBOLT)) - { - pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); - targets.push_back(pTarget); - continue; - } - - for (IceBlockMap::const_iterator itr = iceblocks.begin(); itr != iceblocks.end(); ++itr) - { - if (GameObject* pGo = GameObject::GetGameObject(*me, itr->second)) - { - if (pGo->IsInBetween(me, pTarget, 2.0f) - && me->GetExactDist2d(pTarget->GetPositionX(), pTarget->GetPositionY()) - me->GetExactDist2d(pGo->GetPositionX(), pGo->GetPositionY()) < 5.0f) - { - pTarget->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); - targets.push_back(pTarget); - break; - } - } - } - } - - me->CastSpell(me, SPELL_FROST_EXPLOSION, true); - - for (std::vector::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - (*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false); - } -}; - -CreatureAI* GetAI_boss_sapphiron(Creature* pCreature) -{ - return new boss_sapphironAI (pCreature); -} - -void AddSC_boss_sapphiron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_sapphiron"; - newscript->GetAI = &GetAI_boss_sapphiron; - newscript->RegisterSelf(); - - // Chill - GetAISpellInfo(28547)->cooldown = 1000; - GetAISpellInfo(55699)->cooldown = 1000; -} diff --git a/src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp deleted file mode 100644 index 350cd450510..00000000000 --- a/src/server/scripts/Northrend/naxxramas/boss_thaddius.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -//Stalagg -enum StalaggYells -{ - SAY_STAL_AGGRO = -1533023, //not used - SAY_STAL_SLAY = -1533024, //not used - SAY_STAL_DEATH = -1533025 //not used -}; - -enum StalagSpells -{ - SPELL_POWERSURGE = 28134, - H_SPELL_POWERSURGE = 54529, - SPELL_MAGNETIC_PULL = 28338, - SPELL_STALAGG_TESLA = 28097 -}; - -//Feugen -enum FeugenYells -{ - SAY_FEUG_AGGRO = -1533026, //not used - SAY_FEUG_SLAY = -1533027, //not used - SAY_FEUG_DEATH = -1533028 //not used -}; - -enum FeugenSpells -{ - SPELL_STATICFIELD = 28135, - H_SPELL_STATICFIELD = 54528, - SPELL_FEUGEN_TESLA = 28109 -}; - -// Thaddius DoAction -enum ThaddiusActions -{ - ACTION_FEUGEN_RESET, - ACTION_FEUGEN_DIED, - ACTION_STALAGG_RESET, - ACTION_STALAGG_DIED -}; - -//generic -#define C_TESLA_COIL 16218 //the coils (emotes "Tesla Coil overloads!") - -//Thaddius -enum ThaddiusYells -{ - SAY_GREET = -1533029, //not used - SAY_AGGRO_1 = -1533030, - SAY_AGGRO_2 = -1533031, - SAY_AGGRO_3 = -1533032, - SAY_SLAY = -1533033, - SAY_ELECT = -1533034, //not used - SAY_DEATH = -1533035, - SAY_SCREAM1 = -1533036, //not used - SAY_SCREAM2 = -1533037, //not used - SAY_SCREAM3 = -1533038, //not used - SAY_SCREAM4 = -1533039 //not used -}; - -enum ThaddiusSpells -{ - SPELL_POLARITY_SHIFT = 28089, - SPELL_BALL_LIGHTNING = 28299, - SPELL_CHAIN_LIGHTNING = 28167, - H_SPELL_CHAIN_LIGHTNING = 54531, - SPELL_BERSERK = 27680 -}; - -enum Events -{ - EVENT_NONE, - EVENT_SHIFT, - EVENT_CHAIN, - EVENT_BERSERK, -}; - -struct boss_thaddiusAI : public BossAI -{ - boss_thaddiusAI(Creature *c) : BossAI(c, BOSS_THADDIUS) - { - // init is a bit tricky because thaddius shall track the life of both adds, but not if there was a wipe - // and, in particular, if there was a crash after both adds were killed (should not respawn) - - // Moreover, the adds may not yet be spawn. So just track down the status if mob is spawn - // and each mob will send its status at reset (meaning that it is alive) - checkFeugenAlive = false; - if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN))) - checkFeugenAlive = pFeugen->isAlive(); - - checkStalaggAlive = false; - if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG))) - checkStalaggAlive = pStalagg->isAlive(); - - if (!checkFeugenAlive && !checkStalaggAlive) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_AGGRESSIVE); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_PASSIVE); - } - } - - bool checkStalaggAlive; - bool checkFeugenAlive; - uint32 uiAddsTimer; - - void KilledUnit(Unit* /*victim*/) - { - if (!(rand()%5)) - DoScriptText(SAY_SLAY, me); - } - - void JustDied(Unit* /*Killer*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - } - - void DoAction(const int32 action) - { - switch(action) - { - case ACTION_FEUGEN_RESET: - checkFeugenAlive = true; - break; - case ACTION_FEUGEN_DIED: - checkFeugenAlive = false; - break; - case ACTION_STALAGG_RESET: - checkStalaggAlive = true; - break; - case ACTION_STALAGG_DIED: - checkStalaggAlive = false; - break; - } - - if (!checkFeugenAlive && !checkStalaggAlive) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - // REACT_AGGRESSIVE only reset when he takes damage. - DoZoneInCombat(); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_PASSIVE); - } - } - - void EnterCombat(Unit * /*who*/) - { - _EnterCombat(); - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - events.ScheduleEvent(EVENT_SHIFT, 30000); - events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000)); - events.ScheduleEvent(EVENT_BERSERK, 360000); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 & /*uiDamage*/) - { - me->SetReactState(REACT_AGGRESSIVE); - } - - void UpdateAI(const uint32 diff) - { - if (checkFeugenAlive && checkStalaggAlive) - uiAddsTimer = 0; - - if (checkStalaggAlive != checkFeugenAlive) - { - uiAddsTimer += diff; - if (uiAddsTimer > 5000) - { - if (!checkStalaggAlive) - { - if (instance) - if (Creature *pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG))) - pStalagg->Respawn(); - } - else - { - if (instance) - if (Creature *pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN))) - pFeugen->Respawn(); - } - } - } - - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHIFT: - DoCastAOE(SPELL_POLARITY_SHIFT); - events.ScheduleEvent(EVENT_SHIFT, 30000); - return; - case EVENT_CHAIN: - DoCast(me->getVictim(), RAID_MODE(SPELL_CHAIN_LIGHTNING, H_SPELL_CHAIN_LIGHTNING)); - events.ScheduleEvent(EVENT_CHAIN, urand(10000,20000)); - return; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - return; - } - } - - if (events.GetTimer() > 15000 && !me->IsWithinMeleeRange(me->getVictim())) - DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); - else - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_thaddius(Creature* pCreature) -{ - return new boss_thaddiusAI (pCreature); -} - -struct mob_stalaggAI : public ScriptedAI -{ - mob_stalaggAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 powerSurgeTimer; - uint32 magneticPullTimer; - - void Reset() - { - if (pInstance) - if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_STALAGG_RESET); - powerSurgeTimer = urand(20000,25000); - magneticPullTimer = 20000; - } - - void EnterCombat(Unit * /*pWho*/) - { - DoCast(SPELL_STALAGG_TESLA); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_STALAGG_DIED); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (magneticPullTimer <= uiDiff) - { - if (Creature *pFeugen = me->GetCreature(*me, pInstance->GetData64(DATA_FEUGEN))) - { - Unit* pStalaggVictim = me->getVictim(); - Unit* pFeugenVictim = pFeugen->getVictim(); - - if (pFeugenVictim && pStalaggVictim) - { - // magnetic pull is not working. So just jump. - - // reset aggro to be sure that feugen will not follow the jump - pFeugen->getThreatManager().modifyThreatPercent(pFeugenVictim, -100); - pFeugenVictim->JumpTo(me, 0.3f); - - me->getThreatManager().modifyThreatPercent(pStalaggVictim, -100); - pStalaggVictim->JumpTo(pFeugen, 0.3f); - } - } - - magneticPullTimer = 20000; - } - else magneticPullTimer -= uiDiff; - - if (powerSurgeTimer <= uiDiff) - { - DoCast(me, RAID_MODE(SPELL_POWERSURGE, H_SPELL_POWERSURGE)); - powerSurgeTimer = urand(15000,20000); - } else powerSurgeTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_stalagg(Creature* pCreature) -{ - return new mob_stalaggAI(pCreature); -} - -struct mob_feugenAI : public ScriptedAI -{ - mob_feugenAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 staticFieldTimer; - - void Reset() - { - if (pInstance) - if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_FEUGEN_RESET); - staticFieldTimer = 5000; - } - - void EnterCombat(Unit * /*pWho*/) - { - DoCast(SPELL_FEUGEN_TESLA); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - if (Creature *pThaddius = me->GetCreature(*me, pInstance->GetData64(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_FEUGEN_DIED); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (staticFieldTimer <= uiDiff) - { - DoCast(me, RAID_MODE(SPELL_STATICFIELD, H_SPELL_STATICFIELD)); - staticFieldTimer = 5000; - } else staticFieldTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_feugen(Creature* pCreature) -{ - return new mob_feugenAI(pCreature); -} - -void AddSC_boss_thaddius() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_thaddius"; - newscript->GetAI = &GetAI_boss_thaddius; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stalagg"; - newscript->GetAI = &GetAI_mob_stalagg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_feugen"; - newscript->GetAI = &GetAI_mob_feugen; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp deleted file mode 100644 index 706789a73f1..00000000000 --- a/src/server/scripts/Northrend/naxxramas/instance_naxxramas.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "naxxramas.h" - -const DoorData doorData[] = -{ - {181126, BOSS_ANUBREKHAN,DOOR_TYPE_ROOM, BOUNDARY_S}, - {181195, BOSS_ANUBREKHAN,DOOR_TYPE_PASSAGE, 0}, - {194022, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0}, - {181209, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0}, - {181209, BOSS_MAEXXNA, DOOR_TYPE_ROOM, BOUNDARY_SW}, - {181200, BOSS_NOTH, DOOR_TYPE_ROOM, BOUNDARY_N}, - {181201, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_E}, - {181202, BOSS_NOTH, DOOR_TYPE_PASSAGE, 0}, - {181202, BOSS_HEIGAN, DOOR_TYPE_ROOM, BOUNDARY_N}, - {181203, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_E}, - {181241, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, 0}, - {181241, BOSS_LOATHEB, DOOR_TYPE_ROOM, BOUNDARY_W}, - {181123, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE, 0}, - {181123, BOSS_GROBBULUS, DOOR_TYPE_ROOM, 0}, - {181120, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NW}, - {181121, BOSS_GLUTH, DOOR_TYPE_PASSAGE, 0}, - {181121, BOSS_THADDIUS, DOOR_TYPE_ROOM, 0}, - {181124, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE, 0}, - {181124, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_N}, - {181125, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_S}, - {181119, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, 0}, - {181119, BOSS_HORSEMEN, DOOR_TYPE_ROOM, BOUNDARY_NE}, - {181225, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE, BOUNDARY_W}, - {181228, BOSS_KELTHUZAD, DOOR_TYPE_ROOM, BOUNDARY_S}, - {0, 0, DOOR_TYPE_ROOM, 0}, // EOF -}; - -const MinionData minionData[] = -{ - //{16573, BOSS_ANUBREKHAN}, there is no spawn point in db, so we do not add them here - {16506, BOSS_FAERLINA}, - {16803, BOSS_RAZUVIOUS}, - {16063, BOSS_HORSEMEN}, - {16064, BOSS_HORSEMEN}, - {16065, BOSS_HORSEMEN}, - {30549, BOSS_HORSEMEN}, - {0, 0,} -}; - -enum eEnums -{ - GO_HORSEMEN_CHEST_HERO = 193426, - GO_HORSEMEN_CHEST = 181366, //four horsemen event, DoRespawnGameObject() when event == DONE - GO_GOTHIK_GATE = 181170, - GO_KELTHUZAD_PORTAL01 = 181402, - GO_KELTHUZAD_PORTAL02 = 181403, - GO_KELTHUZAD_PORTAL03 = 181404, - GO_KELTHUZAD_PORTAL04 = 181405, - GO_KELTHUZAD_TRIGGER = 181444, - - SPELL_ERUPTION = 29371 -}; - -const float HeiganPos[2] = {2796, -3707}; -const float HeiganEruptionSlope[3] = -{ - (-3685 - HeiganPos[1]) /(2724 - HeiganPos[0]), - (-3647 - HeiganPos[1]) /(2749 - HeiganPos[0]), - (-3637 - HeiganPos[1]) /(2771 - HeiganPos[0]), -}; - -// 0 H x -// 1 ^ -// 2 | -// 3 y<--o -inline uint32 GetEruptionSection(float x, float y) -{ - y -= HeiganPos[1]; - if (y < 1.0f) - return 0; - - x -= HeiganPos[0]; - if (x > -1.0f) - return 3; - - float slope = y/x; - for (uint32 i = 0; i < 3; ++i) - if (slope > HeiganEruptionSlope[i]) - return i; - return 3; -} - -struct instance_naxxramas : public InstanceData -{ - instance_naxxramas(Map* pMap) : InstanceData(pMap) - { - SetBossNumber(MAX_BOSS_NUMBER); - LoadDoorData(doorData); - LoadMinionData(minionData); - } - - std::set HeiganEruptionGUID[4]; - uint64 GothikGateGUID; - uint64 HorsemenChestGUID; - uint64 SapphironGUID; - uint64 uiFaerlina; - uint64 uiThane; - uint64 uiLady; - uint64 uiBaron; - uint64 uiSir; - - uint64 uiThaddius; - uint64 uiFeugen; - uint64 uiStalagg; - - uint64 uiKelthuzad; - uint64 uiKelthuzadTrigger; - uint64 uiPortals[4]; - - time_t minHorsemenDiedTime; - time_t maxHorsemenDiedTime; - - void OnCreatureCreate(Creature* pCreature, bool add) - { - switch(pCreature->GetEntry()) - { - case 15989: SapphironGUID = add ? pCreature->GetGUID() : 0; return; - case 15953: uiFaerlina = pCreature->GetGUID(); return; - case 16064: uiThane = pCreature->GetGUID(); return; - case 16065: uiLady = pCreature->GetGUID(); return; - case 30549: uiBaron = pCreature->GetGUID(); return; - case 16063: uiSir = pCreature->GetGUID(); return; - case 15928: uiThaddius = pCreature->GetGUID(); return; - case 15930: uiFeugen = pCreature->GetGUID(); return; - case 15929: uiStalagg = pCreature->GetGUID(); return; - case 15990: uiKelthuzad = pCreature->GetGUID(); return; - } - - AddMinion(pCreature, add); - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if (pGo->GetGOInfo()->displayId == 6785 || pGo->GetGOInfo()->displayId == 1287) - { - uint32 section = GetEruptionSection(pGo->GetPositionX(), pGo->GetPositionY()); - if (add) - HeiganEruptionGUID[section].insert(pGo->GetGUID()); - else - HeiganEruptionGUID[section].erase(pGo->GetGUID()); - return; - } - - switch(pGo->GetEntry()) - { - case GO_BIRTH: - if (!add && SapphironGUID) - { - if (Creature *pSapphiron = instance->GetCreature(SapphironGUID)) - pSapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH); - return; - } - case GO_GOTHIK_GATE: GothikGateGUID = add ? pGo->GetGUID() : 0; break; - case GO_HORSEMEN_CHEST: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break; - case GO_HORSEMEN_CHEST_HERO: HorsemenChestGUID = add ? pGo->GetGUID() : 0; break; - case GO_KELTHUZAD_PORTAL01: uiPortals[0] = pGo->GetGUID(); break; - case GO_KELTHUZAD_PORTAL02: uiPortals[1] = pGo->GetGUID(); break; - case GO_KELTHUZAD_PORTAL03: uiPortals[2] = pGo->GetGUID(); break; - case GO_KELTHUZAD_PORTAL04: uiPortals[3] = pGo->GetGUID(); break; - case GO_KELTHUZAD_TRIGGER: uiKelthuzadTrigger = pGo->GetGUID(); break; - } - - AddDoor(pGo, add); - } - - void SetData(uint32 id, uint32 value) - { - switch(id) - { - case DATA_HEIGAN_ERUPT: - HeiganErupt(value); - break; - case DATA_GOTHIK_GATE: - if (GameObject *pGothikGate = instance->GetGameObject(GothikGateGUID)) - pGothikGate->SetGoState(GOState(value)); - break; - - case DATA_HORSEMEN0: - case DATA_HORSEMEN1: - case DATA_HORSEMEN2: - case DATA_HORSEMEN3: - if (value == NOT_STARTED) - { - minHorsemenDiedTime = 0; - maxHorsemenDiedTime = 0; - } - else if (value == DONE) - { - time_t now = time(NULL); - - if (minHorsemenDiedTime == 0) - minHorsemenDiedTime = now; - - maxHorsemenDiedTime = now; - } - break; - } - } - - uint64 GetData64(uint32 id) - { - switch(id) - { - case DATA_FAERLINA: - return uiFaerlina; - case DATA_THANE: - return uiThane; - case DATA_LADY: - return uiLady; - case DATA_BARON: - return uiBaron; - case DATA_SIR: - return uiSir; - case DATA_THADDIUS: - return uiThaddius; - case DATA_FEUGEN: - return uiFeugen; - case DATA_STALAGG: - return uiStalagg; - case DATA_KELTHUZAD: - return uiKelthuzad; - case DATA_KELTHUZAD_PORTAL01: - return uiPortals[0]; - case DATA_KELTHUZAD_PORTAL02: - return uiPortals[1]; - case DATA_KELTHUZAD_PORTAL03: - return uiPortals[2]; - case DATA_KELTHUZAD_PORTAL04: - return uiPortals[3]; - case DATA_KELTHUZAD_TRIGGER: - return uiKelthuzadTrigger; - } - return 0; - } - - bool SetBossState(uint32 id, EncounterState state) - { - if (!InstanceData::SetBossState(id, state)) - return false; - - if (id == BOSS_HORSEMEN && state == DONE) - { - if (GameObject *pHorsemenChest = instance->GetGameObject(HorsemenChestGUID)) - pHorsemenChest->SetRespawnTime(pHorsemenChest->GetRespawnDelay()); - } - - return true; - } - - void HeiganErupt(uint32 section) - { - for (uint32 i = 0; i < 4; ++i) - { - if (i == section) - continue; - - for (std::set::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr) - { - if (GameObject *pHeiganEruption = instance->GetGameObject(*itr)) - { - pHeiganEruption->SendCustomAnim(); - pHeiganEruption->CastSpell(NULL, SPELL_ERUPTION); - } - } - } - } - - bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/) - { - switch(criteria_id) - { - case 7600: // Criteria for achievement 2176: And They Would All Go Down Together 15sec of each other 10-man - if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) - return true; - return false; - case 7601: // Criteria for achievement 2177: And They Would All Go Down Together 15sec of each other 25-man - if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) - return true; - return false; - case 13233: // Criteria for achievement 2186: The Immortal (25-man) - // TODO. - break; - case 13237: // Criteria for achievement 2187: The Undying (10-man) - // TODO. - break; - } - return false; - } -}; - -InstanceData* GetInstanceData_instance_naxxramas(Map* pMap) -{ - return new instance_naxxramas(pMap); -} - -void AddSC_instance_naxxramas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_naxxramas"; - newscript->GetInstanceData = &GetInstanceData_instance_naxxramas; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/naxxramas/naxxramas.h b/src/server/scripts/Northrend/naxxramas/naxxramas.h deleted file mode 100644 index 9b1fac2ff5b..00000000000 --- a/src/server/scripts/Northrend/naxxramas/naxxramas.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_NAXXRAMAS_H -#define DEF_NAXXRAMAS_H - -enum Encounter -{ - BOSS_ANUBREKHAN, - BOSS_FAERLINA, - BOSS_MAEXXNA, - BOSS_NOTH, - BOSS_HEIGAN, - BOSS_LOATHEB, - BOSS_PATCHWERK, - BOSS_GROBBULUS, - BOSS_GLUTH, - BOSS_THADDIUS, - BOSS_RAZUVIOUS, - BOSS_GOTHIK, - BOSS_HORSEMEN, - BOSS_SAPPHIRON, - BOSS_KELTHUZAD, - MAX_BOSS_NUMBER -}; - -enum Data -{ - DATA_HEIGAN_ERUPT, - DATA_GOTHIK_GATE, - DATA_SAPPHIRON_BIRTH, - - DATA_HORSEMEN0, - DATA_HORSEMEN1, - DATA_HORSEMEN2, - DATA_HORSEMEN3, -}; - -enum Data64 -{ - DATA_FAERLINA, - DATA_THANE, - DATA_LADY, - DATA_BARON, - DATA_SIR, - DATA_THADDIUS, - DATA_FEUGEN, - DATA_STALAGG, - DATA_KELTHUZAD, - DATA_KELTHUZAD_PORTAL01, - DATA_KELTHUZAD_PORTAL02, - DATA_KELTHUZAD_PORTAL03, - DATA_KELTHUZAD_PORTAL04, - DATA_KELTHUZAD_TRIGGER, -}; - -#define GO_BIRTH 181356 - -#endif - diff --git a/src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp b/src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp deleted file mode 100644 index bbb1df2731d..00000000000 --- a/src/server/scripts/Northrend/nexus/eye_of_eternity/boss_malygos.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* Script Data Start -SDName: Boss malygos -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -//Spells -#define SPELL_ARCANE_BREATH_N 56272 -#define SPELL_ARCANE_BREATH_H 60072 -#define SPELL_ARCANE_PULSE 57432 -#define SPELL_ARCANE_STORM_1 57459 -#define SPELL_ARCANE_STORM_2 61693 -#define SPELL_ARCANE_STORM_3 61694 -#define SPELL_STATIC_FIELD 57430 -#define SPELL_SURGE_OF_POWER_1 56505 -#define SPELL_SURGE_OF_POWER_2 57407 -#define SPELL_SURGE_OF_POWER_3 60936 -#define SPELL_VORTEX 56105 - -//Dragon "mounts" spells in Phase3 -//they use Rugelike energy -#define SPELL_DMOUNT_FLAME_SPIKE 56091 //maybe not accurate -#define SPELL_DMOUNT_ENGULF_IN_FLAMES 61621 -#define SPELL_DMOUNT_REVIVIFY 57090 -#define SPELL_DMOUNT_LIFE_BURST 57143 -#define SPELL_DMOUNT_FLAME_SHIELD 57108 -//#define SPELL_DMOUNT_UNKNOWN XYZ //Increases your drake's flight speed by 500%. - -//not in db -//Yell -//-->Other -#define SAY_ANTI_MAGIC_SHELL -1616000 -#define SAY_BREATH_ATTACK -1616001 -#define SAY_HIGH_DAMAGE_MODE -1616002 -#define SAY_MAGIC_BLAST -1616003 -//--> Generic Spells -#define SAY_GENERIC_SPELL_1 -1616004 -#define SAY_GENERIC_SPELL_2 -1616005 -#define SAY_GENERIC_SPELL_3 -1616006 -#define SAY_DEATH -1616007 -//--> Prefight -#define SAY_PREFIGHT_1 -1616008 -#define SAY_PREFIGHT_2 -1616009 -#define SAY_PREFIGHT_3 -1616010 -#define SAY_PREFIGHT_4 -1616011 -#define SAY_PREFIGHT_5 -1616012 -//--> Phase1 -#define SAY_PHASE1_AGGRO -1616013 -#define SAY_PHASE1_END -1616014 -#define SAY_PHASE1_SLAY_1 -1616015 -#define SAY_PHASE1_SLAY_2 -1616016 -#define SAY_PHASE1_SLAY_3 -1616017 - -//--> Phase2 at 50% HP, - -/*Malygos himself is not targetable during this phase, it will end when the adds he spawns are all killed. However, he does continue to play a part in the encounter. -During this phase he drops anti-magic zones onto the ground the raid MUST stand inside of, it reduces magical damage taken by 50%. They shrink over time, so it's important that your raid moves to each new one he drops. -Throughout the phase, he will deep breath doing ~4k damage per second, unless you are standing inside of the anti-magic zone. -The way the fight works during this phase is there are NPCs riding around on disks in the room. There are two types of mobs, Lords and Scions. -The Lords will move down onto the group, and need to be tanked (They will one-shot a non-tank). After they die, they drop a disk that a raid member can mount onto, which allows them to fly, to attack the Scions that do not come down to the ground. -It is recommended to let melee take the first disks, then ranged. As those mobs die, they also drop disks, which allows the rest of your dps to get onto them. -The Scions will continually cast Arcane Blast on random targets on the floor, which is mitigated by the anti-magic zones. While mounted on a disk, you will not take damage. -After all of the NPCs riding on the disks die, the players on the disks need to dismount as Phase 3 is about to begin.*/ - -//not in db -#define SAY_PHASE2_AGGRO -1616018 -#define SAY_PHASE2_END -1616019 -#define SAY_PHASE2_SLAY_1 -1616020 -#define SAY_PHASE2_SLAY_2 -1616021 -#define SAY_PHASE2_SLAY_3 -1616022 -//--> Phase3 Malygos destroys the floor, encounter continues on dragon "mounts" -#define SAY_PHASE3_INTRO -1616023 -#define SAY_PHASE3_AGGRO -1616024 -#define SAY_PHASE3_SLAY_1 -1616025 -#define SAY_PHASE3_SLAY_2 -1616026 -#define SAY_PHASE3_SLAY_3 -1616027 -#define SAY_PHASE3_BIG_ATTACK -1616028 - -enum -{ - ACHIEV_TIMED_START_EVENT = 20387, -}; - -struct boss_malygosAI : public ScriptedAI -{ - boss_malygosAI(Creature *c) : ScriptedAI(c) - { - instance = me->GetInstanceData(); - } - - InstanceData *instance; - - uint32 phase; - uint32 enrage; - - void Reset() - { - phase = 1; - enrage = 615000; //Source Deadly Boss Mod - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) - { - if (phase == 1) - { - DoScriptText(SAY_PHASE1_AGGRO, me); - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - if (phase == 2) - DoScriptText(SAY_PHASE1_AGGRO, me); - if (phase == 3) - DoScriptText(SAY_PHASE1_AGGRO, me); - } - - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (phase == 1 && HealthBelowPct(50)) { - phase = 2; - //spawn adds - //set malygos unatackable untill all adds spawned dead - //start phase3 - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - if (phase == 1) - DoScriptText(RAND(SAY_PHASE1_SLAY_1,SAY_PHASE1_SLAY_2,SAY_PHASE1_SLAY_3), me); - if (phase == 2) - DoScriptText(RAND(SAY_PHASE2_SLAY_1,SAY_PHASE2_SLAY_2,SAY_PHASE2_SLAY_3), me); - if (phase == 3) - DoScriptText(RAND(SAY_PHASE3_SLAY_1,SAY_PHASE3_SLAY_2,SAY_PHASE3_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_malygos(Creature* pCreature) -{ - return new boss_malygosAI (pCreature); -} - -void AddSC_boss_malygos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_malygos"; - newscript->GetAI = &GetAI_boss_malygos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h b/src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h deleted file mode 100644 index caa82a92e95..00000000000 --- a/src/server/scripts/Northrend/nexus/eye_of_eternity/eye_of_eternity.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef DEF_EYE_OF_ETERNITY_H -#define DEF_EYE_OF_ETERNITY_H - -#endif diff --git a/src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp deleted file mode 100644 index d93ec415b42..00000000000 --- a/src/server/scripts/Northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "ScriptedPch.h" -#include "eye_of_eternity.h" - -struct instance_eye_of_eternity : public ScriptedInstance -{ - instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; -}; - -InstanceData* GetInstanceData_instance_eye_of_eternity(Map* pMap) -{ - return new instance_eye_of_eternity(pMap); -} - -void AddSC_instance_eye_of_eternity() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_eye_of_eternity"; - newscript->GetInstanceData = &GetInstanceData_instance_eye_of_eternity; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp b/src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp deleted file mode 100644 index 02c39dc1232..00000000000 --- a/src/server/scripts/Northrend/nexus/nexus/boss_anomalus.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - //Spells - SPELL_SPARK = 47751, - H_SPELL_SPARK = 57062, - SPELL_RIFT_SHIELD = 47748, - SPELL_CHARGE_RIFT = 47747, //Works wrong (affect players, not rifts) - SPELL_CREATE_RIFT = 47743, //Don't work, using WA - SPELL_ARCANE_ATTRACTION = 57063, //No idea, when it's used -}; - -enum Adds -{ - MOB_CRAZED_MANA_WRAITH = 26746, - MOB_CHAOTIC_RIFT = 26918 -}; -enum Yells -{ - //Yell - SAY_AGGRO = -1576010, - SAY_DEATH = -1576011, - SAY_RIFT = -1576012, - SAY_SHIELD = -1576013 -}; - -enum Achievs -{ - ACHIEV_CHAOS_THEORY = 2037 -}; - -const Position RiftLocation[6] = -{ - {652.64, -273.70, -8.75}, - {634.45, -265.94, -8.44}, - {620.73, -281.17, -9.02}, - {626.10, -304.67, -9.44}, - {639.87, -314.11, -9.49}, - {651.72, -297.44, -9.37} -}; - -struct boss_anomalusAI : public ScriptedAI -{ - boss_anomalusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint8 Phase; - uint32 uiSparkTimer; - uint32 uiCreateRiftTimer; - uint64 uiChaoticRiftGUID; - - bool bDeadChaoticRift; // needed for achievement: Chaos Theory(2037) - - void Reset() - { - Phase = 0; - uiSparkTimer = 5*IN_MILISECONDS; - uiChaoticRiftGUID = 0; - - bDeadChaoticRift = false; - - if (pInstance) - pInstance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && !bDeadChaoticRift) - pInstance->DoCompleteAchievement(ACHIEV_CHAOS_THEORY); - pInstance->SetData(DATA_ANOMALUS_EVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetDistance(me->GetHomePosition()) > 60.0f) - { - //Not blizzlike, hack to avoid an exploit - EnterEvadeMode(); - return; - } - - if (me->HasAura(SPELL_RIFT_SHIELD)) - { - if (uiChaoticRiftGUID) - { - Unit* Rift = Unit::GetUnit((*me), uiChaoticRiftGUID); - if (Rift && Rift->isDead()) - { - me->RemoveAurasDueToSpell(SPELL_RIFT_SHIELD); - uiChaoticRiftGUID = 0; - } - return; - } - } else - uiChaoticRiftGUID = 0; - - if ((Phase == 0) && HealthBelowPct(50)) - { - Phase = 1; - DoScriptText(SAY_SHIELD, me); - DoCast(me, SPELL_RIFT_SHIELD); - Creature* Rift = me->SummonCreature(MOB_CHAOTIC_RIFT, RiftLocation[urand(0,5)], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); - if (Rift) - { - //DoCast(Rift, SPELL_CHARGE_RIFT); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Rift->AI()->AttackStart(pTarget); - uiChaoticRiftGUID = Rift->GetGUID(); - DoScriptText(SAY_RIFT , me); - } - } - - - if (uiSparkTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SPARK); - uiSparkTimer = 5*IN_MILISECONDS; - } else uiSparkTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_anomalus(Creature* pCreature) -{ - return new boss_anomalusAI (pCreature); -} - -enum RiftSpells -{ - SPELL_CHAOTIC_ENERGY_BURST = 47688, - SPELL_CHARGED_CHAOTIC_ENERGY_BURST = 47737, - SPELL_ARCANEFORM = 48019 //Chaotic Rift visual -}; - -struct mob_chaotic_riftAI : public Scripted_NoMovementAI -{ - mob_chaotic_riftAI(Creature *c) : Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiChaoticEnergyBurstTimer; - uint32 uiSummonCrazedManaWraithTimer; - - void Reset() - { - uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; - uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; - //me->SetDisplayId(25206); //For some reason in DB models for ally and horde are different. - //Model for ally (1126) does not show auras. Horde model works perfect. - //Set model to horde number - DoCast(me, SPELL_ARCANEFORM, false); - } - - void JustDied(Unit * /*killer*/) - { - if (Creature* pAnomalus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0)) - CAST_AI(boss_anomalusAI,pAnomalus->AI())->bDeadChaoticRift = true; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiChaoticEnergyBurstTimer <= diff) - { - Unit* pAnomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - if (pAnomalus && pAnomalus->HasAura(SPELL_RIFT_SHIELD)) - DoCast(pTarget, SPELL_CHARGED_CHAOTIC_ENERGY_BURST); - else - DoCast(pTarget, SPELL_CHAOTIC_ENERGY_BURST); - uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; - } else uiChaoticEnergyBurstTimer -= diff; - - if (uiSummonCrazedManaWraithTimer <= diff) - { - Creature* Wraith = me->SummonCreature(MOB_CRAZED_MANA_WRAITH, me->GetPositionX()+1, me->GetPositionY()+1, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); - if (Wraith) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Wraith->AI()->AttackStart(pTarget); - Unit* Anomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); - if (Anomalus && Anomalus->HasAura(SPELL_RIFT_SHIELD)) - uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; - else - uiSummonCrazedManaWraithTimer = 10*IN_MILISECONDS; - } else uiSummonCrazedManaWraithTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_chaotic_rift(Creature* pCreature) -{ - return new mob_chaotic_riftAI (pCreature); -} - -void AddSC_boss_anomalus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_anomalus"; - newscript->GetAI = &GetAI_boss_anomalus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_chaotic_rift"; - newscript->GetAI = &GetAI_mob_chaotic_rift; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp deleted file mode 100644 index ff633c55eac..00000000000 --- a/src/server/scripts/Northrend/nexus/nexus/boss_keristrasza.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - //Spells - SPELL_FROZEN_PRISON = 47854, - SPELL_TAIL_SWEEP = 50155, - SPELL_CRYSTAL_CHAINS = 50997, - SPELL_ENRAGE = 8599, - SPELL_CRYSTALFIRE_BREATH = 48096, - H_SPELL_CRYSTALFIRE_BREATH = 57091, - SPELL_CRYSTALIZE = 48179, - SPELL_INTENSE_COLD = 48094, - SPELL_INTENSE_COLD_TRIGGERED = 48095 -}; -enum Yells -{ - //Yell - SAY_AGGRO = -1576040, - SAY_SLAY = -1576041, - SAY_ENRAGE = -1576042, - SAY_DEATH = -1576043, - SAY_CRYSTAL_NOVA = -1576044 -}; -enum Achievements -{ - ACHIEV_INTENSE_COLD = 2036 -}; -enum Misc -{ - DATA_CONTAINMENT_SPHERES = 3 -}; - -struct boss_keristraszaAI : public ScriptedAI -{ - boss_keristraszaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCrystalfireBreathTimer; - uint32 uiCrystalChainsCrystalizeTimer; - uint32 uiTailSweepTimer; - bool bEnrage; - - uint64 auiContainmentSphereGUIDs[DATA_CONTAINMENT_SPHERES]; - - uint32 uiCheckIntenseColdTimer; - bool bMoreThanTwoIntenseCold; // needed for achievement: Intense Cold(2036) - - void Reset() - { - uiCrystalfireBreathTimer = 14*IN_MILISECONDS; - uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); - uiTailSweepTimer = 5*IN_MILISECONDS; - bEnrage = false; - - uiCheckIntenseColdTimer = 2*IN_MILISECONDS; - bMoreThanTwoIntenseCold = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - - RemovePrison(CheckContainmentSpheres()); - - if (pInstance) - pInstance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCastAOE(SPELL_INTENSE_COLD); - - if (pInstance) - pInstance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && !bMoreThanTwoIntenseCold) - pInstance->DoCompleteAchievement(ACHIEV_INTENSE_COLD); - pInstance->SetData(DATA_KERISTRASZA_EVENT, DONE); - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_SLAY, me); - } - - bool CheckContainmentSpheres(bool remove_prison = false) - { - if (!pInstance) - return false; - - auiContainmentSphereGUIDs[0] = pInstance->GetData64(ANOMALUS_CONTAINMET_SPHERE); - auiContainmentSphereGUIDs[1] = pInstance->GetData64(ORMOROKS_CONTAINMET_SPHERE); - auiContainmentSphereGUIDs[2] = pInstance->GetData64(TELESTRAS_CONTAINMET_SPHERE); - - GameObject *ContainmentSpheres[DATA_CONTAINMENT_SPHERES]; - - for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i) - { - ContainmentSpheres[i] = pInstance->instance->GetGameObject(auiContainmentSphereGUIDs[i]); - if (!ContainmentSpheres[i]) - return false; - if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE) - return false; - } - if (remove_prison) - RemovePrison(true); - return true; - } - - void RemovePrison(bool remove) - { - if (remove) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (me->HasAura(SPELL_FROZEN_PRISON)) - me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoCast(me, SPELL_FROZEN_PRISON, false); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiCheckIntenseColdTimer < diff && !bMoreThanTwoIntenseCold) - { - std::list ThreatList = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER) - continue; - - Aura *AuraIntenseCold = pTarget->GetAura(SPELL_INTENSE_COLD_TRIGGERED); - if (AuraIntenseCold && AuraIntenseCold->GetStackAmount() > 2) - { - bMoreThanTwoIntenseCold = true; - break; - } - } - uiCheckIntenseColdTimer = 2*IN_MILISECONDS; - } else uiCheckIntenseColdTimer -= diff; - - if (!bEnrage && HealthBelowPct(25)) - { - DoScriptText(SAY_ENRAGE, me); - DoCast(me, SPELL_ENRAGE); - bEnrage = true; - } - - if (uiCrystalfireBreathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CRYSTALFIRE_BREATH); - uiCrystalfireBreathTimer = 14*IN_MILISECONDS; - } else uiCrystalfireBreathTimer -= diff; - - if (uiTailSweepTimer <= diff) - { - DoCast(me, SPELL_TAIL_SWEEP); - uiTailSweepTimer = 5*IN_MILISECONDS; - } else uiTailSweepTimer -= diff; - - if (uiCrystalChainsCrystalizeTimer <= diff) - { - DoScriptText(SAY_CRYSTAL_NOVA, me); - if (IsHeroic()) - DoCast(me, SPELL_CRYSTALIZE); - else if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CRYSTAL_CHAINS); - uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); - } else uiCrystalChainsCrystalizeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_keristrasza(Creature* pCreature) -{ - return new boss_keristraszaAI (pCreature); -} - -bool GOHello_containment_sphere(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - - Creature *pKeristrasza = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_KERISTRASZA) : 0); - if (pKeristrasza && pKeristrasza->isAlive()) - { - // maybe these are hacks :( - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - CAST_AI(boss_keristraszaAI, pKeristrasza->AI())->CheckContainmentSpheres(true); - } - return true; -} - -void AddSC_boss_keristrasza() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_keristrasza"; - newscript->GetAI = &GetAI_boss_keristrasza; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "containment_sphere"; - newscript->pGOHello = &GOHello_containment_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp b/src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp deleted file mode 100644 index 0bf9fb07bb7..00000000000 --- a/src/server/scripts/Northrend/nexus/nexus/boss_magus_telestra.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - SPELL_ICE_NOVA = 47772, - H_SPELL_ICE_NOVA = 56935, - SPELL_FIREBOMB = 47773, - H_SPELL_FIREBOMB = 56934, - SPELL_GRAVITY_WELL = 47756, - SPELL_TELESTRA_BACK = 47714, - - SPELL_FIRE_MAGUS_VISUAL = 47705, - SPELL_FROST_MAGUS_VISUAL = 47706, - SPELL_ARCANE_MAGUS_VISUAL = 47704 -}; -enum Creatures -{ - MOB_FIRE_MAGUS = 26928, - MOB_FROST_MAGUS = 26930, - MOB_ARCANE_MAGUS = 26929 -}; -enum Yells -{ - SAY_AGGRO = -1576000, - SAY_KILL = -1576001, - SAY_DEATH = -1576002, - SAY_MERGE = -1576003, - SAY_SPLIT_1 = -1576004, - SAY_SPLIT_2 = -1576005, -}; -enum Achievements -{ - ACHIEV_SPLIT_PERSONALITY = 2150, - ACHIEV_TIMER = 5*IN_MILISECONDS -}; - -const Position CenterOfRoom = {504.80, 89.07, -16.12, 6.27}; - -struct boss_magus_telestraAI : public ScriptedAI -{ - boss_magus_telestraAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 uiFireMagusGUID; - uint64 uiFrostMagusGUID; - uint64 uiArcaneMagusGUID; - - bool bFireMagusDead; - bool bFrostMagusDead; - bool bArcaneMagusDead; - bool bIsWaitingToAppear; - bool bIsAchievementTimerRunning; - - uint32 uiIsWaitingToAppearTimer; - uint32 uiIceNovaTimer; - uint32 uiFireBombTimer; - uint32 uiGravityWellTimer; - uint32 uiCooldown; - uint32 uiAchievementTimer; - - uint8 Phase; - uint8 uiAchievementProgress; - - void Reset() - { - Phase = 0; - //These times are probably wrong - uiIceNovaTimer = 7*IN_MILISECONDS; - uiFireBombTimer = 0; - uiGravityWellTimer = 15*IN_MILISECONDS; - uiCooldown = 0; - - uiFireMagusGUID = 0; - uiFrostMagusGUID = 0; - uiArcaneMagusGUID = 0; - - uiAchievementProgress = 0; - uiAchievementTimer = 0; - - bIsAchievementTimerRunning = false; - bIsWaitingToAppear = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - if (pInstance) - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && uiAchievementProgress == 2) - pInstance->DoCompleteAchievement(ACHIEV_SPLIT_PERSONALITY); - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE); - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - uint64 SplitPersonality(uint32 entry) - { - if (Creature* Summoned = me->SummonCreature(entry, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS)) - { - switch (entry) - { - case MOB_FIRE_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_FIRE_MAGUS_VISUAL, false); - break; - } - case MOB_FROST_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_FROST_MAGUS_VISUAL, false); - break; - } - case MOB_ARCANE_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_ARCANE_MAGUS_VISUAL, false); - break; - } - } - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Summoned->AI()->AttackStart(pTarget); - return Summoned->GetGUID(); - } - return 0; - } - - void SummonedCreatureDespawn(Creature *summon) - { - if (summon->isAlive()) - return; - - if (summon->GetGUID() == uiFireMagusGUID) - { - bFireMagusDead = true; - bIsAchievementTimerRunning = true; - } - else if (summon->GetGUID() == uiFrostMagusGUID) - { - bFrostMagusDead = true; - bIsAchievementTimerRunning = true; - } - else if (summon->GetGUID() == uiArcaneMagusGUID) - { - bArcaneMagusDead = true; - bIsAchievementTimerRunning = true; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (bIsWaitingToAppear) - { - me->StopMoving(); - me->AttackStop(); - if (uiIsWaitingToAppearTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - bIsWaitingToAppear = false; - } else uiIsWaitingToAppearTimer -= diff; - return; - } - - if ((Phase == 1) ||(Phase == 3)) - { - if (bIsAchievementTimerRunning) - uiAchievementTimer += diff; - if (bFireMagusDead && bFrostMagusDead && bArcaneMagusDead) - { - if (uiAchievementTimer <= ACHIEV_TIMER) - uiAchievementProgress +=1; - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, CenterOfRoom.GetPositionX(), CenterOfRoom.GetPositionY(), CenterOfRoom.GetPositionZ(), CenterOfRoom.GetOrientation()); - DoCast(me, SPELL_TELESTRA_BACK); - me->SetVisibility(VISIBILITY_ON); - if (Phase == 1) - Phase = 2; - if (Phase == 3) - Phase = 4; - uiFireMagusGUID = 0; - uiFrostMagusGUID = 0; - uiArcaneMagusGUID = 0; - bIsWaitingToAppear = true; - uiIsWaitingToAppearTimer = 4*IN_MILISECONDS; - DoScriptText(SAY_MERGE, me); - bIsAchievementTimerRunning = false; - uiAchievementTimer = 0; - } - else - return; - } - - if ((Phase == 0) && HealthBelowPct(50)) - { - Phase = 1; - me->CastStop(); - me->RemoveAllAuras(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); - uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); - uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); - bFireMagusDead = false; - bFrostMagusDead = false; - bArcaneMagusDead = false; - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - return; - } - - if (IsHeroic() && (Phase == 2) && HealthBelowPct(10)) - { - Phase = 3; - me->CastStop(); - me->RemoveAllAuras(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); - uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); - uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); - bFireMagusDead = false; - bFrostMagusDead = false; - bArcaneMagusDead = false; - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - return; - } - - if (uiCooldown) - { - if (uiCooldown <= diff) - uiCooldown = 0; - else - { - uiCooldown -= diff; - return; - } - } - - if (uiIceNovaTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_ICE_NOVA, false); - uiCooldown = 1.5*IN_MILISECONDS; - } - uiIceNovaTimer = 15*IN_MILISECONDS; - } else uiIceNovaTimer -= diff; - - if (uiGravityWellTimer <= diff) - { - if (Unit *pTarget = me->getVictim()) - { - DoCast(pTarget, SPELL_GRAVITY_WELL); - uiCooldown = 6*IN_MILISECONDS; - } - uiGravityWellTimer = 15*IN_MILISECONDS; - } else uiGravityWellTimer -= diff; - - if (uiFireBombTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_FIREBOMB, false); - uiCooldown = 2*IN_MILISECONDS; - } - uiFireBombTimer = 2*IN_MILISECONDS; - } else uiFireBombTimer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_magus_telestra(Creature* pCreature) -{ - return new boss_magus_telestraAI (pCreature); -} - -void AddSC_boss_magus_telestra() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_magus_telestra"; - newscript->GetAI = &GetAI_boss_magus_telestra; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp deleted file mode 100644 index 1304f95c7ac..00000000000 --- a/src/server/scripts/Northrend/nexus/nexus/boss_ormorok.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - SPELL_CRYSTAL_SPIKES = 47958, //Don't work, using walkaround - H_SPELL_CRYSTAL_SPIKES = 57082, //Don't work, using walkaround - SPELL_CRYSTALL_SPIKE_DAMAGE = 47944, - H_SPELL_CRYSTALL_SPIKE_DAMAGE = 57067, - SPELL_CRYSTAL_SPIKE_PREVISUAL = 50442, - MOB_CRYSTAL_SPIKE = 27099, - SPELL_SPELL_REFLECTION = 47981, - SPELL_TRAMPLE = 48016, - H_SPELL_TRAMPLE = 57066, - SPELL_FRENZY = 48017, - SPELL_SUMMON_CRYSTALLINE_TANGLER = 61564, //summons npc 32665 - SPELL_ROOTS = 28858 //proper spell id is unknown -}; -enum Yells -{ - SAY_AGGRO = -1576020, - SAY_DEATH = -1576021, - SAY_REFLECT = -1576022, - SAY_CRYSTAL_SPIKES = -1576023, - SAY_KILL = -1576024 -}; -enum Creatures -{ - MOB_CRYSTALLINE_TANGLER = 32665 -}; - -#define SPIKE_DISTANCE 5.0f - -struct boss_ormorokAI : public ScriptedAI -{ - boss_ormorokAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bFrenzy; - bool bCrystalSpikes; - uint8 uiCrystalSpikesCount; - float fBaseX; - float fBaseY; - float fBaseZ; - float fBaseO; - float fSpikeXY[4][2]; - - uint32 uiCrystalSpikesTimer; - uint32 uiCrystalSpikesTimer2; - uint32 uiTrampleTimer; - uint32 uiFrenzyTimer; - uint32 uiSpellReflectionTimer; - uint32 uiSummonCrystallineTanglerTimer; - - void Reset() - { - uiCrystalSpikesTimer = 12*IN_MILISECONDS; - uiTrampleTimer = 10*IN_MILISECONDS; - uiSpellReflectionTimer = 30*IN_MILISECONDS; - uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; - bFrenzy = false; - bCrystalSpikes = false; - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - return; - } - if (bCrystalSpikes) - if (uiCrystalSpikesTimer2 <= diff) - { - fSpikeXY[0][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); - fSpikeXY[0][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); - fSpikeXY[1][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); - fSpikeXY[1][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); - fSpikeXY[2][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); - fSpikeXY[2][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); - fSpikeXY[3][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); - fSpikeXY[3][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); - for (uint8 i = 0; i < 4; ++i) - me->SummonCreature(MOB_CRYSTAL_SPIKE, fSpikeXY[i][0], fSpikeXY[i][1], fBaseZ, 0, TEMPSUMMON_TIMED_DESPAWN, 7*IN_MILISECONDS); - if (++uiCrystalSpikesCount >= 13) - bCrystalSpikes = false; - uiCrystalSpikesTimer2 = 200; - } else uiCrystalSpikesTimer2 -= diff; - - if (!bFrenzy && (me->GetHealth() < me->GetMaxHealth() * 0.25)) - { - DoCast(me, SPELL_FRENZY); - bFrenzy = true; - } - - if (uiTrampleTimer <= diff) - { - DoCast(me, SPELL_TRAMPLE); - uiTrampleTimer = 10*IN_MILISECONDS; - } else uiTrampleTimer -= diff; - - if (uiSpellReflectionTimer <= diff) - { - DoScriptText(SAY_REFLECT, me); - DoCast(me, SPELL_SPELL_REFLECTION); - uiSpellReflectionTimer = 30*IN_MILISECONDS; - } else uiSpellReflectionTimer -= diff; - - if (uiCrystalSpikesTimer <= diff) - { - DoScriptText(SAY_CRYSTAL_SPIKES, me); - bCrystalSpikes = true; - uiCrystalSpikesCount = 1; - uiCrystalSpikesTimer2 = 0; - fBaseX = me->GetPositionX(); - fBaseY = me->GetPositionY(); - fBaseZ = me->GetPositionZ(); - fBaseO = me->GetOrientation(); - uiCrystalSpikesTimer = 20*IN_MILISECONDS; - } else uiCrystalSpikesTimer -= diff; - - if (IsHeroic() && (uiSummonCrystallineTanglerTimer <= diff)) - { - Creature* Crystalline_Tangler = me->SummonCreature(MOB_CRYSTALLINE_TANGLER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); - if (Crystalline_Tangler) - { - Unit *pTarget = NULL; - uint8 Healer = 0; - for (uint8 j = 1; j <= 4; j++) - { - switch (j) - { - case 1: Healer = CLASS_PRIEST; break; - case 2: Healer = CLASS_PALADIN; break; - case 3: Healer = CLASS_DRUID; break; - case 4: Healer = CLASS_SHAMAN; break; - } - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pTemp = Unit::GetUnit((*me),(*i)->getUnitGuid()); - if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && pTemp->getClass() == Healer) - { - pTarget = pTemp; - break; - } - } - if (pTarget) - break; - } - if (!pTarget) - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Crystalline_Tangler->AI()->AttackStart(pTarget); - Crystalline_Tangler->getThreatManager().addThreat(pTarget, 1000000000.0f); - } - } - uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; - } else uiSummonCrystallineTanglerTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_crystal_spikeAI : public Scripted_NoMovementAI -{ - mob_crystal_spikeAI(Creature *c) : Scripted_NoMovementAI(c) - { - } - - uint32 SpellCrystalSpikeDamageTimer; - uint32 SpellCrystalSpikePrevisualTimer; - - void Reset() - { - SpellCrystalSpikeDamageTimer = 3.7*IN_MILISECONDS; - SpellCrystalSpikePrevisualTimer = 1*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (SpellCrystalSpikePrevisualTimer <= diff) - { - DoCast(me, SPELL_CRYSTAL_SPIKE_PREVISUAL); - SpellCrystalSpikePrevisualTimer = 10*IN_MILISECONDS; - } else SpellCrystalSpikePrevisualTimer -= diff; - - if (SpellCrystalSpikeDamageTimer <= diff) - { - DoCast(me, SPELL_CRYSTALL_SPIKE_DAMAGE); - SpellCrystalSpikeDamageTimer = 10*IN_MILISECONDS; - } else SpellCrystalSpikeDamageTimer -= diff; - } -}; - -struct mob_crystalline_tanglerAI : public ScriptedAI -{ - mob_crystalline_tanglerAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiRootsTimer; - - void Reset() - { - uiRootsTimer = 1*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (uiRootsTimer <= diff) - { - if (me->IsWithinDist(me->getVictim(), 5.0f, false)) - { - DoCast(me->getVictim(), SPELL_ROOTS); - uiRootsTimer = 15*IN_MILISECONDS; - } - } else uiRootsTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_crystal_spike(Creature* pCreature) -{ - return new mob_crystal_spikeAI (pCreature); -} - -CreatureAI* GetAI_mob_crystalline_tangler(Creature* pCreature) -{ - return new mob_crystalline_tanglerAI (pCreature); -} - -CreatureAI* GetAI_boss_ormorok(Creature* pCreature) -{ - return new boss_ormorokAI (pCreature); -} - -void AddSC_boss_ormorok() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ormorok"; - newscript->GetAI = &GetAI_boss_ormorok; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crystal_spike"; - newscript->GetAI = &GetAI_mob_crystal_spike; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crystalline_tangler"; - newscript->GetAI = &GetAI_mob_crystalline_tangler; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp b/src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp deleted file mode 100644 index 4bd9f55a013..00000000000 --- a/src/server/scripts/Northrend/nexus/nexus/commander_kolurg.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Script Data Start -SDName: Boss Commander Kolurg -SDAuthor: LordVanMartin -SD%Complete: -SDComment: Only Alliance Heroic -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_commander_kolurg' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -#define SPELL_BATTLE_SHOUT 31403 -#define SPELL_CHARGE 60067 -#define SPELL_FRIGHTENING_SHOUT 19134 -#define SPELL_WHIRLWIND_1 38619 -#define SPELL_WHIRLWIND_2 38618 - -//not used -//Yell -#define SAY_AGGRO -1576024 -#define SAY_KILL -1576025 -#define SAY_DEATH -1576026 - -struct boss_commander_kolurgAI : public ScriptedAI -{ - boss_commander_kolurgAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) {} -}; - -CreatureAI* GetAI_boss_commander_kolurg(Creature* pCreature) -{ - return new boss_commander_kolurgAI (pCreature); -} - -void AddSC_boss_commander_kolurg() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_commander_kolurg"; - newscript->GetAI = &GetAI_boss_commander_kolurg; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp b/src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp deleted file mode 100644 index ef02baa38e6..00000000000 --- a/src/server/scripts/Northrend/nexus/nexus/commander_stoutbeard.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* Script Data Start -SDName: Boss Commander Stoutbeard -SDAuthor: LordVanMartin -SD%Complete: -SDComment: Only Horde Heroic -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_commander_stoutbeard' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -#define SPELL_BATTLE_SHOUT 31403 -#define SPELL_CHARGE 60067 -#define SPELL_FRIGHTENING_SHOUT 19134 -#define SPELL_WHIRLWIND_1 38619 -#define SPELL_WHIRLWIND_2 38618 - -//not used -//Yell -#define SAY_AGGRO -1576021 -#define SAY_KILL -1576022 -#define SAY_DEATH -1576023 - -struct boss_commander_stoutbeardAI : public ScriptedAI -{ - boss_commander_stoutbeardAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - } -}; - -CreatureAI* GetAI_boss_commander_stoutbeard(Creature* pCreature) -{ - return new boss_commander_stoutbeardAI (pCreature); -} - -void AddSC_boss_commander_stoutbeard() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_commander_stoutbeard"; - newscript->GetAI = &GetAI_boss_commander_stoutbeard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp b/src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp deleted file mode 100644 index db70245e3a4..00000000000 --- a/src/server/scripts/Northrend/nexus/nexus/instance_nexus.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -#define NUMBER_OF_ENCOUNTERS 4 - -enum Factions -{ - FACTION_HOSTILE_FOR_ALL = 16 -}; - -struct instance_nexus : public ScriptedInstance -{ - instance_nexus(Map *pMap) : ScriptedInstance(pMap) { Initialize(); } - - uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS]; - - uint64 Anomalus; - uint64 Keristrasza; - - uint64 AnomalusContainmentSphere; - uint64 OrmoroksContainmentSphere; - uint64 TelestrasContainmentSphere; - - std::string strInstData; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Anomalus = 0; - Keristrasza = 0; - } - - void OnCreatureCreate(Creature *pCreature, bool /*bAdd*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - uint32 TeamInInstance = 0; - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - TeamInInstance = pPlayer->GetTeam(); - } - switch (pCreature->GetEntry()) - { - case 26763: - Anomalus = pCreature->GetGUID(); - break; - case 26723: - Keristrasza = pCreature->GetGUID(); - break; - // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. - case 26800: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26799, HORDE); - break; - } - case 26802: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26801, HORDE); - break; - } - case 26805: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26803, HORDE); - break; - } - case 27949: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(27947, HORDE); - break; - } - case 26796: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26798, HORDE); - break; - } - } - } - - void OnGameObjectCreate(GameObject *pGo, bool /*bAdd*/) - { - switch (pGo->GetEntry()) - { - case 188527: - { - AnomalusContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - case 188528: - { - OrmoroksContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - case 188526: - { - TelestrasContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - } - } - - uint32 GetData(uint32 identifier) - { - switch(identifier) - { - case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0]; - case DATA_ANOMALUS_EVENT: return m_auiEncounter[1]; - case DATA_ORMOROK_EVENT: return m_auiEncounter[2]; - case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3]; - } - return 0; - } - - void SetData(uint32 identifier, uint32 data) - { - switch (identifier) - { - case DATA_MAGUS_TELESTRA_EVENT: - { - if (data == DONE) - { - GameObject *Sphere = instance->GetGameObject(TelestrasContainmentSphere); - if (Sphere) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[0] = data; - break; - } - case DATA_ANOMALUS_EVENT: - { - if (data == DONE) - { - if (GameObject *Sphere = instance->GetGameObject(AnomalusContainmentSphere)) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[1] = data; - break; - } - case DATA_ORMOROK_EVENT: - { - if (data == DONE) - { - if (GameObject *Sphere = instance->GetGameObject(OrmoroksContainmentSphere)) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[2] = data; - break; - } - case DATA_KERISTRASZA_EVENT: - m_auiEncounter[3] = data; - break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3]; - - strInstData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint64 GetData64(uint32 uiIdentifier) - { - switch(uiIdentifier) - { - case DATA_ANOMALUS: return Anomalus; - case DATA_KERISTRASZA: return Keristrasza; - case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere; - case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere; - case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere; - } - return 0; - } - - std::string GetSaveData() - { - return strInstData; - } - - void Load(const char *chrIn) - { - if (!chrIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(chrIn); - - std::istringstream loadStream(chrIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - - for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData *GetInstanceData_instance_nexus(Map *pMap) -{ - return new instance_nexus(pMap); -} - -void AddSC_instance_nexus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_nexus"; - newscript->GetInstanceData = &GetInstanceData_instance_nexus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/nexus/nexus.h b/src/server/scripts/Northrend/nexus/nexus/nexus.h deleted file mode 100644 index 66902bece30..00000000000 --- a/src/server/scripts/Northrend/nexus/nexus/nexus.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_NEXUS_H -#define DEF_NEXUS_H - -enum eTypes -{ - DATA_MAGUS_TELESTRA_EVENT, - DATA_ANOMALUS_EVENT, - DATA_ORMOROK_EVENT, - DATA_KERISTRASZA_EVENT, - - DATA_ANOMALUS, - DATA_KERISTRASZA, - - ANOMALUS_CONTAINMET_SPHERE, - ORMOROKS_CONTAINMET_SPHERE, - TELESTRAS_CONTAINMET_SPHERE -}; - -#endif diff --git a/src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp b/src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp deleted file mode 100644 index 7d276206339..00000000000 --- a/src/server/scripts/Northrend/nexus/oculus/boss_drakos.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - SPELL_MAGIC_PULL = 51336, - SPELL_MAGIC_PULL_EFFECT = 50770, - SPELL_THUNDERING_STOMP = 50774, - SPELL_THUNDERING_STOMP_H = 59370, - SPELL_UNSTABLE_SPHERE_PASSIVE = 50756, - SPELL_UNSTABLE_SPHERE_PULSE = 50757, - SPELL_UNSTABLE_SPHERE_TIMER = 50758, - NPC_UNSTABLE_SPHERE = 28166, -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1578000, - SAY_KILL_1 = -1578001, - SAY_KILL_2 = -1578002, - SAY_KILL_3 = -1578003, - SAY_DEATH = -1578004, - SAY_PULL_1 = -1578005, - SAY_PULL_2 = -1578006, - SAY_PULL_3 = -1578007, - SAY_PULL_4 = -1578008, - SAY_STOMP_1 = -1578009, - SAY_STOMP_2 = -1578010, - SAY_STOMP_3 = -1578011 -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 18153, -}; - -struct boss_drakosAI : public ScriptedAI -{ - boss_drakosAI(Creature* pCreature) : ScriptedAI(pCreature), lSummons(me) - { - pInstance = pCreature->GetInstanceData(); - } - - uint32 uiMagicPullTimer; - uint32 uiStompTimer; - uint32 uiBombSummonTimer; - - bool bPostPull; - - ScriptedInstance* pInstance; - SummonList lSummons; - - void Reset() - { - lSummons.DespawnAll(); - uiMagicPullTimer = 15000; - uiStompTimer = 17000; - uiBombSummonTimer = 2000; - - bPostPull = false; - - if (pInstance) - pInstance->SetData(DATA_DRAKOS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_DRAKOS_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature* pSummon) - { - lSummons.Summon(pSummon); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBombSummonTimer <= uiDiff) - { - Position pPosition; - me->GetPosition(&pPosition); - - if (bPostPull) - { - for (uint8 uiI = 0; uiI >= 3; uiI++) - { - me->GetRandomNearPosition(pPosition, float(urand(0,10))); - me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); - } - } - else - { - me->GetRandomNearPosition(pPosition, float(urand(0,10))); - me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); - } - - uiBombSummonTimer = 2000; - } else uiBombSummonTimer -= uiDiff; - - if (uiMagicPullTimer <= uiDiff) - { - DoCast(SPELL_MAGIC_PULL); - - bPostPull = true; - - uiMagicPullTimer = 15000; - } else uiMagicPullTimer -= uiDiff; - - if (uiStompTimer <= uiDiff) - { - DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2,SAY_STOMP_3), me); - DoCast(SPELL_THUNDERING_STOMP); - uiStompTimer = 17000; - } else uiStompTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_DRAKOS_EVENT, DONE); - // start achievement timer (kill Eregos within 20 min) - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - lSummons.DespawnAll(); - } - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); - } -}; - -CreatureAI* GetAI_boss_drakos(Creature* pCreature) -{ - return new boss_drakosAI (pCreature); -} - -struct npc_unstable_sphereAI : public ScriptedAI -{ - npc_unstable_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiPulseTimer; - uint32 uiDeathTimer; - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveRandom(40.0f); - - me->AddAura(SPELL_UNSTABLE_SPHERE_PASSIVE, me); - me->AddAura(SPELL_UNSTABLE_SPHERE_TIMER, me); - - uiPulseTimer = 3000; - uiDeathTimer = 19000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (uiPulseTimer <= uiDiff) - { - DoCast(SPELL_UNSTABLE_SPHERE_PULSE); - uiPulseTimer = 3*IN_MILISECONDS; - } else uiPulseTimer -= uiDiff; - - if (uiDeathTimer <= uiDiff) - me->DisappearAndDie(); - else uiDeathTimer -= uiDiff; - } -}; - -CreatureAI* GetAI_npc_unstable_sphere(Creature* pCreature) -{ - return new npc_unstable_sphereAI (pCreature); -} - -void AddSC_boss_drakos() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_drakos"; - newscript->GetAI = &GetAI_boss_drakos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_unstable_sphere"; - newscript->GetAI = &GetAI_npc_unstable_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp b/src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp deleted file mode 100644 index 94fb90ab206..00000000000 --- a/src/server/scripts/Northrend/nexus/oculus/boss_eregos.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -//Types of drake mounts: Ruby(Tank), Amber(DPS), Emerald(Healer) -//Two Repeating phases - -enum Spells -{ - SPELL_ARCANE_BARRAGE = 50804, - H_SPELL_ARCANE_BARRAGE = 59381, - SPELL_ARCANE_VOLLEY = 51153, - H_SPELL_ARCANE_VOLLEY = 59382, - SPELL_ENRAGED_ASSAULT = 51170, - SPELL_PLANAR_ANOMALIES = 57959, - SPELL_PLANAR_SHIFT = 51162, -}; -/*Ruby Drake , -(npc 27756) (item 37860) -(summoned by spell Ruby Essence = 37860 ---> Call Amber Drake == 49462 ---> Summon 27756) -*/ -enum RubyDrake -{ - NPC_RUBY_DRAKE_VEHICLE = 27756, - SPELL_RIDE_RUBY_DRAKE_QUE = 49463, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49464 - SPELL_RUBY_DRAKE_SADDLE = 49464, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_RUBY_SEARING_WRATH = 50232, //(60 yds) - Instant - Breathes a stream of fire at an enemy dragon, dealing 6800 to 9200 Fire damage and then jumping to additional dragons within 30 yards. Each jump increases the damage by 50%. Affects up to 5 total targets - SPELL_RUBY_EVASIVE_AURA = 50248, //Instant - Allows the Ruby Drake to generate Evasive Charges when hit by hostile attacks and spells. - SPELL_RUBY_EVASIVE_MANEUVERS = 50240, //Instant - 5 sec. cooldown - Allows your drake to dodge all incoming attacks and spells. Requires Evasive Charges to use. Each attack or spell dodged while this ability is active burns one Evasive Charge. Lasts 30 sec. or until all charges are exhausted. - //you do not have acces to until you kill Mage-Lord Urom - SPELL_RUBY_MARTYR = 50253 //Instant - 10 sec. cooldown - Redirect all harmful spells cast at friendly drakes to yourself for 10 sec. -}; -/*Amber Drake, -(npc 27755) (item 37859) -(summoned by spell Amber Essence = 37859 ---> Call Amber Drake == 49461 ---> Summon 27755) -*/ -enum AmberDrake -{ - NPC_AMBER_DRAKE_VEHICLE = 27755, - SPELL_RIDE_AMBER_DRAKE_QUE = 49459, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49460 - SPELL_AMBER_DRAKE_SADDLE = 49460, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_AMBER_SHOCK_LANCE = 49840, //(60 yds) - Instant - Deals 4822 to 5602 Arcane damage and detonates all Shock Charges on an enemy dragon. Damage is increased by 6525 for each detonated. -// SPELL_AMBER_STOP_TIME //Instant - 1 min cooldown - Halts the passage of time, freezing all enemy dragons in place for 10 sec. This attack applies 5 Shock Charges to each affected target. - //you do not have access to until you kill the Mage-Lord Urom. - SPELL_AMBER_TEMPORAL_RIFT = 49592 //(60 yds) - Channeled - Channels a temporal rift on an enemy dragon for 10 sec. While trapped in the rift, all damage done to the target is increased by 100%. In addition, for every 15,000 damage done to a target affected by Temporal Rift, 1 Shock Charge is generated. -}; -/*Emerald Drake, -(npc 27692) (item 37815), - (summoned by spell Emerald Essence = 37815 ---> Call Emerald Drake == 49345 ---> Summon 27692) -*/ -enum EmeraldDrake -{ - NPC_EMERALD_DRAKE_VEHICLE = 27692, - SPELL_RIDE_EMERALD_DRAKE_QUE = 49427, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49346 - SPELL_EMERALD_DRAKE_SADDLE = 49346, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_EMERALD_LEECHING_POISON = 50328, //(60 yds) - Instant - Poisons the enemy dragon, leeching 1300 to the caster every 2 sec. for 12 sec. Stacks up to 3 times. - SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, //(60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25,000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec. - // you do not have access to until you kill the Mage-Lord Urom - SPELL_EMERALD_DREAM_FUNNEL = 50344 //(60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels. -}; - -struct boss_eregosAI : public ScriptedAI -{ - boss_eregosAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, DONE); - } -}; - -CreatureAI* GetAI_boss_eregos(Creature* pCreature) -{ - return new boss_eregosAI (pCreature); -} - -void AddSC_boss_eregos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_eregos"; - newscript->GetAI = &GetAI_boss_eregos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp b/src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp deleted file mode 100644 index 29435441d00..00000000000 --- a/src/server/scripts/Northrend/nexus/oculus/boss_urom.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Urom -SD%Complete: 80 -SDComment: Is not working SPELL_ARCANE_SHIELD. SPELL_FROSTBOMB has some issues, the damage aura should not stack. -SDCategory: Instance Script -EndScriptData */ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - - SPELL_ARCANE_SHIELD = 53813, //Dummy --> Channeled, shields the caster from damage. - SPELL_EMPOWERED_ARCANE_EXPLOSION = 51110, - SPELL_EMPOWERED_ARCANE_EXPLOSION_2 = 59377, - SPELL_FROSTBOMB = 51103, //Urom throws a bomb, hitting its target with the highest aggro which inflict directly 650 frost damage and drops a frost zone on the ground. This zone deals 650 frost damage per second and reduce the movement speed by 35%. Lasts 1 minute. - SPELL_SUMMON_MENAGERIE = 50476, //Summons an assortment of creatures and teleports the caster to safety. - SPELL_SUMMON_MENAGERIE_2 = 50495, - SPELL_SUMMON_MENAGERIE_3 = 50496, - SPELL_TELEPORT = 51112, //Teleports to the center of Oculus - SPELL_TIME_BOMB = 51121, //Deals arcane damage to a random player, and after 6 seconds, deals zone damage to nearby equal to the health missing of the target afflicted by the debuff. - SPELL_TIME_BOMB_2 = 59376 -}; - -enum Yells -{ - SAY_AGGRO_1 = -1578000, - SAY_AGGRO_2 = -1578001, - SAY_AGGRO_3 = -1578002, - SAY_AGGRO_4 = -1578003, - SAY_TELEPORT = -1578004, -}; - -enum eCreature -{ - NPC_PHANTASMAL_CLOUDSCRAPER = 27645, - NPC_PHANTASMAL_MAMMOTH = 27642, - NPC_PHANTASMAL_WOLF = 27644, - - NPC_PHANTASMAL_AIR = 27650, - NPC_PHANTASMAL_FIRE = 27651, - NPC_PHANTASMAL_WATER = 27653, - - NPC_PHANTASMAL_MURLOC = 27649, - NPC_PHANTASMAL_NAGAL = 27648, - NPC_PHANTASMAL_OGRE = 27647 -}; - -struct Summons -{ - uint32 uiEntry[4]; -}; - -static Summons Group[]= -{ - {NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_MAMMOTH,NPC_PHANTASMAL_WOLF}, - {NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_WATER,NPC_PHANTASMAL_FIRE}, - {NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_NAGAL,NPC_PHANTASMAL_MURLOC} -}; - -static uint32 TeleportSpells[]= -{ - SPELL_SUMMON_MENAGERIE,SPELL_SUMMON_MENAGERIE_2,SPELL_SUMMON_MENAGERIE_3 -}; - -static int32 SayAggro[]= -{ - SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4 -}; - -struct boss_uromAI : public ScriptedAI -{ - boss_uromAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - float x,y; - - bool bCanCast; - bool bCanGoBack; - - uint8 uiGroup[3]; - - uint32 uiTeleportTimer; - uint32 uiArcaneExplosionTimer; - uint32 uiCastArcaneExplosionTimer; - uint32 uiFrostBombTimer; - uint32 uiTimeBombTimer; - - void Reset() - { - if (pInstance && pInstance->GetData(DATA_VAROS_EVENT) != DONE) - DoCast(SPELL_ARCANE_SHIELD); - - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, NOT_STARTED); - - if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) == 0) - { - uiGroup[0] = 0; - uiGroup[1] = 0; - uiGroup[2] = 0; - } - - x,y = 0.0f; - bCanCast = false; - bCanGoBack = false; - - me->GetMotionMaster()->MoveIdle(); - - uiTeleportTimer = urand(30000,35000); - uiArcaneExplosionTimer = 9000; - uiCastArcaneExplosionTimer = 2000; - uiFrostBombTimer = urand(5000,8000); - uiTimeBombTimer = urand(20000,25000); - } - - void EnterCombat(Unit* pWho) - { - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, IN_PROGRESS); - - SetGroups(); - SummonGroups(); - CastTeleport(); - - if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) != 3) - pInstance->SetData(DATA_UROM_PLATAFORM,pInstance->GetData(DATA_UROM_PLATAFORM)+1); - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - if (me->GetPositionZ() > 518.63) - DoStartNoMovement(pWho); - - if (me->GetPositionZ() < 518.63) - { - if (me->Attack(pWho, true)) - { - DoScriptText(SayAggro[3],me); - - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(pWho, 0,0); - } - } - } - - void SetGroups() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) != 0) - return; - - while (uiGroup[0] == uiGroup[1] || uiGroup[0] == uiGroup[2] || uiGroup[1] == uiGroup[2]) - { - uiGroup[0] = urand(0,2); - uiGroup[1] = urand(0,2); - uiGroup[2] = urand(0,2); - } - } - - void SetPosition(uint8 uiI) - { - switch(uiI) - { - case 0: - x = me->GetPositionX() + 4; - y = me->GetPositionY() - 4; - break; - case 1: - x = me->GetPositionX() + 4; - y = me->GetPositionY() + 4; - break; - case 2: - x = me->GetPositionX() - 4; - y = me->GetPositionY() + 4; - break; - case 3: - x = me->GetPositionX() - 4; - y = me->GetPositionY() - 4; - break; - default: - break; - } - } - - void SummonGroups() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) - return; - - for (uint8 uiI = 0; uiI < 4 ; uiI++) - { - SetPosition(uiI); - me->SummonCreature(Group[uiGroup[pInstance->GetData(DATA_UROM_PLATAFORM)]].uiEntry[uiI],x,y,me->GetPositionZ(),me->GetOrientation()); - } - } - - void CastTeleport() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) - return; - - DoScriptText(SayAggro[pInstance->GetData(DATA_UROM_PLATAFORM)],me); - DoCast(TeleportSpells[pInstance->GetData(DATA_UROM_PLATAFORM)]); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) < 2) - return; - - if (uiTeleportTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(false); - DoScriptText(SAY_TELEPORT,me); - me->GetMotionMaster()->MoveIdle(); - DoCast(SPELL_TELEPORT); - uiTeleportTimer = urand(30000,35000); - - } else uiTeleportTimer -= uiDiff; - - if (bCanCast && !me->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION)) - { - if (uiCastArcaneExplosionTimer <= uiDiff) - { - bCanCast = false; - bCanGoBack = true; - DoCastAOE(SPELL_EMPOWERED_ARCANE_EXPLOSION); - uiCastArcaneExplosionTimer = 2000; - }else uiCastArcaneExplosionTimer -= uiDiff; - } - - if (bCanGoBack) - { - if (uiArcaneExplosionTimer <= uiDiff) - { - Position pPos; - me->getVictim()->GetPosition(&pPos); - - me->NearTeleportTo(pPos.GetPositionX(),pPos.GetPositionY(),pPos.GetPositionZ(),pPos.GetOrientation()); - me->GetMotionMaster()->MoveChase(me->getVictim(),0,0); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - - bCanCast = false; - bCanGoBack = false; - uiArcaneExplosionTimer = 9000; - } else uiArcaneExplosionTimer -= uiDiff; - } - - if (!me->IsNonMeleeSpellCasted(false, true, true)) - { - if (uiFrostBombTimer <= uiDiff) - { - DoCastVictim(SPELL_FROSTBOMB); - uiFrostBombTimer = urand(5000,8000); - } else uiFrostBombTimer -= uiDiff; - - if (uiTimeBombTimer <= uiDiff) - { - if (Unit* pUnit = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pUnit,SPELL_TIME_BOMB); - - uiTimeBombTimer = urand(20000,25000); - } else uiTimeBombTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, DONE); - } - - void JustSummoned(Creature* pSummon) - { - pSummon->SetInCombatWithZone(); - } - - void LeaveCombat() - { - me->RemoveAllAuras(); - me->CombatStop(false); - me->DeleteThreatList(); - } - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - switch(pSpell->Id) - { - case SPELL_SUMMON_MENAGERIE: - me->SetHomePosition(968.66,1042.53,527.32,0.077); - LeaveCombat(); - break; - case SPELL_SUMMON_MENAGERIE_2: - me->SetHomePosition(1164.02,1170.85,527.321,3.66); - LeaveCombat(); - break; - case SPELL_SUMMON_MENAGERIE_3: - me->SetHomePosition(1118.31,1080.377,508.361,4.25); - LeaveCombat(); - break; - case SPELL_TELEPORT: - me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE); // with out it the npc will fall down while is casting - bCanCast = true; - break; - default: - break; - } - } -}; - -CreatureAI* GetAI_boss_urom(Creature* pCreature) -{ - return new boss_uromAI (pCreature); -} - -void AddSC_boss_urom() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_urom"; - newscript->GetAI = &GetAI_boss_urom; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp b/src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp deleted file mode 100644 index 79034250a43..00000000000 --- a/src/server/scripts/Northrend/nexus/oculus/boss_varos.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - SPELL_ENERGIZE_CORES = 50785, //Damage 5938 to 6562, effec2 Triggers 54069, effect3 Triggers 56251 - SPELL_ENERGIZE_CORES_TRIGGER_1 = 54069, - SPELL_ENERGIZE_CORES_TRIGGER_2 = 56251, - SPELL_ENERGIZE_CORES_2 = 59372, //Damage 9025 to 9975, effect2 Triggers 54069, effect 56251 - SPELL_CALL_AZURE_RING_CAPTAIN = 51002, //Effect Send Event (12229) - SPELL_CALL_AZURE_RING_CAPTAIN_2 = 51006, //Effect Send Event (10665) - SPELL_CALL_AZURE_RING_CAPTAIN_3 = 51007, //Effect Send Event (18454) - SPELL_CALL_AZURE_RING_CAPTAIN_4 = 51008, //Effect Send Event (18455) - SPELL_CALL_AMPLIFY_MAGIC = 51054, - SPELL_CALL_AMPLIFY_MAGIC_2 = 59371 -}; -//not in db -enum Yells -{ - SAY_AGGRO = -1578022, - SAY_KILL_1 = -1578023, - SAY_KILL_2 = -1578024, - SAY_DEATH = -1578025, - SAY_STRIKE_1 = -1578026, - SAY_STRIKE_2 = -1578027, - SAY_STRIKE_3 = -1578028, - SAY_SPAWN = -1578029 -}; - -struct boss_varosAI : public ScriptedAI -{ - boss_varosAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, NOT_STARTED); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, IN_PROGRESS); - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, DONE); - } - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } -}; - -CreatureAI* GetAI_boss_varos(Creature* pCreature) -{ - return new boss_varosAI (pCreature); -} - -void AddSC_boss_varos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_varos"; - newscript->GetAI = &GetAI_boss_varos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp b/src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp deleted file mode 100644 index 49be2385a3c..00000000000 --- a/src/server/scripts/Northrend/nexus/oculus/instance_oculus.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -#define MAX_ENCOUNTER 4 - -/* The Occulus encounters: -0 - Drakos the Interrogator -1 - Varos Cloudstrider -2 - Mage-Lord Urom -3 - Ley-Guardian Eregos */ - -struct instance_oculus : public ScriptedInstance -{ - instance_oculus(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiDrakos; - uint64 uiVaros; - uint64 uiUrom; - uint64 uiEregos; - - uint8 uiPlataformUrom; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - std::list GameObjectList; - - void Initialize() - { - uiPlataformUrom = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case CREATURE_DRAKOS: - uiDrakos = pCreature->GetGUID(); - break; - case CREATURE_VAROS: - uiVaros = pCreature->GetGUID(); - break; - case CREATURE_UROM: - uiUrom = pCreature->GetGUID(); - break; - case CREATURE_EREGOS: - uiEregos = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGO, bool bAdd) - { - if (pGO->GetEntry() == GO_DRAGON_CAGE_DOOR) - { - if (DATA_DRAKOS_EVENT == DONE) - pGO->SetGoState(GO_STATE_ACTIVE); - else - pGO->SetGoState(GO_STATE_READY); - - GameObjectList.push_back(pGO->GetGUID()); - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_DRAKOS_EVENT: - m_auiEncounter[0] = data; - if (data == DONE) - OpenCageDoors(); - break; - case DATA_VAROS_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_UROM_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_EREGOS_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_UROM_PLATAFORM: - uiPlataformUrom = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_DRAKOS_EVENT: return m_auiEncounter[0]; - case DATA_VAROS_EVENT: return m_auiEncounter[1]; - case DATA_UROM_EVENT: return m_auiEncounter[2]; - case DATA_EREGOS_EVENT: return m_auiEncounter[3]; - case DATA_UROM_PLATAFORM: return uiPlataformUrom; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_DRAKOS: return uiDrakos; - case DATA_VAROS: return uiVaros; - case DATA_UROM: return uiUrom; - case DATA_EREGOS: return uiEregos; - } - - return 0; - } - - void OpenCageDoors() - { - if (GameObjectList.empty()) - return; - - for (std::list::const_iterator itr = GameObjectList.begin(); itr != GameObjectList.end(); ++itr) - { - if (GameObject* pGO = instance->GetGameObject(*itr)) - pGO->SetGoState(GO_STATE_ACTIVE); - } - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "T O " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'T' && dataHead2 == 'O') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_oculus(Map* pMap) -{ - return new instance_oculus(pMap); -} - -void AddSC_instance_oculus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_oculus"; - newscript->GetInstanceData = &GetInstanceData_instance_oculus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/oculus/oculus.cpp b/src/server/scripts/Northrend/nexus/oculus/oculus.cpp deleted file mode 100644 index 685583532d5..00000000000 --- a/src/server/scripts/Northrend/nexus/oculus/oculus.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -#define GOSSIP_ITEM_DRAKES "So where do we go from here?" -#define GOSSIP_ITEM_BELGARISTRASZ1 "I want to fly on the wings of the Red Flight" -#define GOSSIP_ITEM_BELGARISTRASZ2 "What abilities do Ruby Drakes have?" -#define GOSSIP_ITEM_VERDISA1 "I want to fly on the wings of the Green Flight" -#define GOSSIP_ITEM_VERDISA2 "What abilities do Emerald Drakes have?" -#define GOSSIP_ITEM_ETERNOS1 "I want to fly on the wings of the Bronze Flight" -#define GOSSIP_ITEM_ETERNOS2 "What abilities do Amber Drakes have?" - -#define HAS_ESSENCE(a) ((a)->HasItemCount(ITEM_EMERALD_ESSENCE,1) || (a)->HasItemCount(ITEM_AMBER_ESSENCE,1) || (a)->HasItemCount(ITEM_RUBY_ESSENCE,1)) - -enum Drakes -{ - GOSSIP_TEXTID_DRAKES = 13267, - GOSSIP_TEXTID_BELGARISTRASZ1 = 12916, - GOSSIP_TEXTID_BELGARISTRASZ2 = 13466, - GOSSIP_TEXTID_BELGARISTRASZ3 = 13254, - GOSSIP_TEXTID_VERDISA1 = 1, - GOSSIP_TEXTID_VERDISA2 = 1, - GOSSIP_TEXTID_VERDISA3 = 1, - GOSSIP_TEXTID_ETERNOS1 = 1, - GOSSIP_TEXTID_ETERNOS2 = 1, - GOSSIP_TEXTID_ETERNOS3 = 13256, - - ITEM_EMERALD_ESSENCE = 37815, - ITEM_AMBER_ESSENCE = 37859, - ITEM_RUBY_ESSENCE = 37860, - - NPC_VERDISA = 27657, - NPC_BELGARISTRASZ = 27658, - NPC_ETERNOS = 27659 -}; - -bool GossipHello_npc_oculus_drake(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->GetInstanceData()->GetData(DATA_DRAKOS_EVENT) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DRAKES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DRAKES, pCreature->GetGUID()); - } - - return true; -} - -bool GossipSelect_npc_oculus_drake(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(pCreature->GetEntry()) - { - case NPC_VERDISA: //Verdisa - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_EMERALD_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_EMERALD_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA3, pCreature->GetGUID()); - break; - } - break; - case NPC_BELGARISTRASZ: //Belgaristrasz - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_RUBY_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_RUBY_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ3, pCreature->GetGUID()); - break; - } - break; - case NPC_ETERNOS: //Eternos - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_AMBER_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_AMBER_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS3, pCreature->GetGUID()); - break; - } - break; - } - - return true; -} - -void AddSC_oculus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_oculus_drake"; - newscript->pGossipHello = &GossipHello_npc_oculus_drake; - newscript->pGossipSelect = &GossipSelect_npc_oculus_drake; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/nexus/oculus/oculus.h b/src/server/scripts/Northrend/nexus/oculus/oculus.h deleted file mode 100644 index b212c9b8b6a..00000000000 --- a/src/server/scripts/Northrend/nexus/oculus/oculus.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DEF_OCULUS_H -#define DEF_OCULUS_H - -enum Data -{ - DATA_DRAKOS_EVENT, - DATA_VAROS_EVENT, - DATA_UROM_EVENT, - DATA_EREGOS_EVENT, - DATA_UROM_PLATAFORM -}; - -enum Data64 -{ - DATA_DRAKOS, - DATA_VAROS, - DATA_UROM, - DATA_EREGOS -}; - -enum Bosses -{ - CREATURE_DRAKOS = 27654, - CREATURE_VAROS = 27447, - CREATURE_UROM = 27655, - CREATURE_EREGOS = 27656 -}; - -enum GameObjects -{ - GO_DRAGON_CAGE_DOOR = 193995 -}; - -#endif diff --git a/src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp deleted file mode 100644 index 3e24aaeb6c0..00000000000 --- a/src/server/scripts/Northrend/obsidian_sanctum/boss_sartharion.cpp +++ /dev/null @@ -1,1421 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "obsidian_sanctum.h" - -enum eEnums -{ - //Sartharion Yell - SAY_SARTHARION_AGGRO = -1615018, - SAY_SARTHARION_BERSERK = -1615019, - SAY_SARTHARION_BREATH = -1615020, - SAY_SARTHARION_CALL_SHADRON = -1615021, - SAY_SARTHARION_CALL_TENEBRON = -1615022, - SAY_SARTHARION_CALL_VESPERON = -1615023, - SAY_SARTHARION_DEATH = -1615024, - SAY_SARTHARION_SPECIAL_1 = -1615025, - SAY_SARTHARION_SPECIAL_2 = -1615026, - SAY_SARTHARION_SPECIAL_3 = -1615027, - SAY_SARTHARION_SPECIAL_4 = -1615028, - SAY_SARTHARION_SLAY_1 = -1615029, - SAY_SARTHARION_SLAY_2 = -1615030, - SAY_SARTHARION_SLAY_3 = -1615031, - - WHISPER_LAVA_CHURN = -1615032, - - WHISPER_SHADRON_DICIPLE = -1615008, - WHISPER_VESPERON_DICIPLE = -1615041, - WHISPER_HATCH_EGGS = -1615017, - WHISPER_OPEN_PORTAL = -1615042, // whisper, shared by two dragons - - //Sartharion Spells - SPELL_BERSERK = 61632, // Increases the caster's attack speed by 150% and all damage it deals by 500% for 5 min. - SPELL_CLEAVE = 56909, // Inflicts 35% weapon damage to an enemy and its nearest allies, affecting up to 10 targets. - SPELL_FLAME_BREATH = 56908, // Inflicts 8750 to 11250 Fire damage to enemies in a cone in front of the caster. - SPELL_FLAME_BREATH_H = 58956, // Inflicts 10938 to 14062 Fire damage to enemies in a cone in front of the caster. - SPELL_TAIL_LASH = 56910, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec. - SPELL_TAIL_LASH_H = 58957, // A sweeping tail strike hits all enemies behind the caster, inflicting 4375 to 5625 damage and stunning them for 2 sec. - SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%. - SPELL_LAVA_STRIKE = 57571, // (Real spell casted should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572) - SPELL_TWILIGHT_REVENGE = 60639, - - SPELL_PYROBUFFET = 56916, // currently used for hard enrage after 15 minutes - SPELL_PYROBUFFET_RANGE = 58907, // possibly used when player get too far away from dummy creatures (2x Creature entry 30494) - - SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO - SPELL_TWILIGHT_SHIFT = 57874, // Twilight Shift Aura - SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase - SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave) - - //Mini bosses common spells - SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase - - //Miniboses (Vesperon, Shadron, Tenebron) - SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster. - SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster. - - SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec. - SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec. - - //Vesperon - //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times - NPC_ACOLYTE_OF_VESPERON = 31219, // Acolyte of Vesperon - SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%. - SPELL_TWILIGHT_TORMENT_VESP = 57948, // (Shadow only) trigger 57935 then 57988 - SPELL_TWILIGHT_TORMENT_VESP_ACO = 58853, // (Fire and Shadow) trigger 58835 then 57988 - - //Shadron - //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times - NPC_ACOLYTE_OF_SHADRON = 31218, // Acolyte of Shadron - SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%. - SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron - SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion - SPELL_VOID_BLAST = 57581, // Twilight Fissure - SPELL_VOID_BLAST_H = 59128, - - //Tenebron - //in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708 - SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%. - //Tenebron, dummy spell - SPELL_SUMMON_TWILIGHT_WHELP = 58035, // doesn't work, will spawn NPC_TWILIGHT_WHELP - SPELL_SUMMON_SARTHARION_TWILIGHT_WHELP = 58826, // doesn't work, will spawn NPC_SHARTHARION_TWILIGHT_WHELP - - SPELL_HATCH_EGGS_H = 59189, - SPELL_HATCH_EGGS = 58542, - SPELL_HATCH_EGGS_EFFECT_H = 59190, - SPELL_HATCH_EGGS_EFFECT = 58685, - NPC_TWILIHT_WHELP = 31214, - NPC_TWILIGHT_EGG = 30882, - - //Whelps - NPC_TWILIGHT_WHELP = 30890, - NPC_SHARTHARION_TWILIGHT_WHELP = 31214, - SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s - - //flame tsunami - SPELL_FLAME_TSUNAMI = 57494, // the visual dummy - SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction - SPELL_FLAME_TSUNAMI_DMG_AURA = 57492, // periodic damage, npc has this aura - - NPC_FLAME_TSUNAMI = 30616, // for the flame waves - NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike - - //using these custom points for dragons start and end - POINT_ID_INIT = 100, - POINT_ID_LAND = 200, - - //Achievements - ACHIEV_TWILIGHT_ASSIST = 2049, - H_ACHIEV_TWILIGHT_ASSIST = 2052, - ACHIEV_TWILIGHT_DUO = 2050, - H_ACHIEV_TWILIGHT_DUO = 2053, - ACHIEV_TWILIGHT_ZONE = 2051, - H_ACHIEV_TWILIGHT_ZONE = 2054 -}; - -struct Waypoint -{ - float m_fX, m_fY, m_fZ; -}; -struct Location -{ - float x,y,z; -}; -struct Locations -{ - float x,y,z; -}; - -//each dragons special points. First where fly to before connect to connon, second where land point is. -Waypoint m_aTene[]= -{ - {3212.854, 575.597, 109.856}, //init - {3246.425, 565.367, 61.249} //end -}; - -Waypoint m_aShad[]= -{ - {3293.238, 472.223, 106.968}, - {3271.669, 526.907, 61.931} -}; - -Waypoint m_aVesp[]= -{ - {3193.310, 472.861, 102.697}, - {3227.268, 533.238, 59.995} -}; - -#define MAX_WAYPOINT 6 -//points around raid "isle", counter clockwise. should probably be adjusted to be more alike -Waypoint m_aDragonCommon[MAX_WAYPOINT]= -{ - {3214.012, 468.932, 98.652}, - {3244.950, 468.427, 98.652}, - {3283.520, 496.869, 98.652}, - {3287.316, 555.875, 98.652}, - {3250.479, 585.827, 98.652}, - {3209.969, 566.523, 98.652} -}; -static Location FlameRight1Spawn = { 3197.59, 495.336, 57.8462 }; -static Location FlameRight1Direction = { 3289.28, 521.569, 55.1526 }; -static Location FlameRight2Spawn = { 3201.94, 543.324, 56.7209 }; -static Location FlameRight2Direction = { 3288.98, 549.291, 55.1232 }; -static Location FlameLeft1Spawn = { 3290.24, 521.725, 55.1238 }; -static Location FlameLeft1Direction = { 3199.94, 516.891, 57.5112 }; -static Location FlameLeft2Spawn = { 3290.33, 586.51, 55.063 }; -static Location FlameLeft2Direction = { 3195.03, 479.135, 55.6331 }; - -static Location AcolyteofShadron = { 3363.92, 534.703, 97.2683 }; -static Location AcolyteofShadron2 = { 3246.57, 551.263, 58.6164 }; -static Location AcolyteofVesperon = { 3145.68, 520.71, 89.7 }; -static Location AcolyteofVesperon2 = { 3246.57, 551.263, 58.6164 }; - -Locations TwilightEggs[] = -{ - {3219.28, 669.121 , 88.5549}, - {3221.55, 682.852 , 90.5361}, - {3239.77, 685.94 , 90.3168}, - {3250.33, 669.749 , 88.7637}, - {3246.6, 642.365 , 84.8752}, - {3233.68, 653.117 , 85.7051} -}; -Locations TwilightEggsSarth[] = -{ - {3261.75, 539.14 , 58.6082}, - {3257.41, 512.939 , 58.5432}, - {3231.04, 498.281 , 58.6439} -}; - -/*###### -## Boss Sartharion -######*/ - -struct boss_sartharionAI : public ScriptedAI -{ - boss_sartharionAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool m_bIsBerserk; - bool m_bIsSoftEnraged; - - uint32 m_uiEnrageTimer; - bool m_bIsHardEnraged; - - uint32 m_uiTenebronTimer; - uint32 m_uiShadronTimer; - uint32 m_uiVesperonTimer; - - uint32 m_uiFlameTsunamiTimer; - uint32 m_uiFlameBreathTimer; - uint32 m_uiTailSweepTimer; - uint32 m_uiCleaveTimer; - uint32 m_uiLavaStrikeTimer; - - bool m_bHasCalledTenebron; - bool m_bHasCalledShadron; - bool m_bHasCalledVesperon; - - uint32 achievProgress; - - void Reset() - { - m_bIsBerserk = false; - m_bIsSoftEnraged = false; - - m_uiEnrageTimer = 15*MINUTE*IN_MILISECONDS; - m_bIsHardEnraged = false; - - m_uiTenebronTimer = 30000; - m_uiShadronTimer = 75000; - m_uiVesperonTimer = 120000; - - m_uiFlameTsunamiTimer = 30000; - m_uiFlameBreathTimer = 20000; - m_uiTailSweepTimer = 20000; - m_uiCleaveTimer = 7000; - m_uiLavaStrikeTimer = 5000; - - m_bHasCalledTenebron = false; - m_bHasCalledShadron = false; - m_bHasCalledVesperon = false; - - if (me->HasAura(SPELL_TWILIGHT_REVENGE)) - me->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE); - - me->ResetLootMode(); - - achievProgress = 0; - } - - void JustReachedHome() - { - if (pInstance) - pInstance->SetData(TYPE_SARTHARION_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_SARTHARION_AGGRO,me); - DoZoneInCombat(); - - if (pInstance) - { - pInstance->SetData(TYPE_SARTHARION_EVENT, IN_PROGRESS); - FetchDragons(); - } - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_SARTHARION_DEATH,me); - - if (pInstance) - { - if (achievProgress >= 1) - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_ASSIST,H_ACHIEV_TWILIGHT_ASSIST)); - else if (achievProgress >= 2) - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_DUO,H_ACHIEV_TWILIGHT_DUO)); - else if (achievProgress == 3) - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_TWILIGHT_ZONE,H_ACHIEV_TWILIGHT_ZONE)); - - pInstance->SetData(TYPE_SARTHARION_EVENT, DONE); - } - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SARTHARION_SLAY_1,SAY_SARTHARION_SLAY_2,SAY_SARTHARION_SLAY_3), me); - } - - // me->ResetLootMode() is called from Reset() - // AddDrakeLootMode() should only ever be called from FetchDragons(), which is called from Aggro() - void AddDrakeLootMode() - { - if (me->HasLootMode(LOOT_MODE_HARD_MODE_2)) // Has two Drake loot modes - me->AddLootMode(LOOT_MODE_HARD_MODE_3); // Add 3rd Drake loot mode - else if (me->HasLootMode(LOOT_MODE_HARD_MODE_1)) // Has one Drake loot mode - me->AddLootMode(LOOT_MODE_HARD_MODE_2); // Add 2nd Drake loot mode - else // Has no Drake loot modes - me->AddLootMode(LOOT_MODE_HARD_MODE_1); // Add 1st Drake loot mode - } - - void FetchDragons() - { - if (!pInstance) - return; - Creature* pFetchTene = Unit::GetCreature(*me, pInstance->GetData64(DATA_TENEBRON)); - Creature* pFetchShad = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON)); - Creature* pFetchVesp = Unit::GetCreature(*me, pInstance->GetData64(DATA_VESPERON)); - - //if at least one of the dragons are alive and are being called - bool bCanUseWill = false; - - if (pFetchTene && pFetchTene->isAlive() && !pFetchTene->getVictim()) - { - bCanUseWill = true; - pFetchTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ); - - if (!pFetchTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pFetchTene->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (pFetchShad && pFetchShad->isAlive() && !pFetchShad->getVictim()) - { - bCanUseWill = true; - pFetchShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ); - - if (!pFetchShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pFetchShad->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (pFetchVesp && pFetchVesp->isAlive() && !pFetchVesp->getVictim()) - { - bCanUseWill = true; - pFetchVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ); - - if (!pFetchVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pFetchVesp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - if (bCanUseWill) - DoCast(me, SPELL_WILL_OF_SARTHARION); - } - - void CallDragon(uint32 uiDataId) - { - if (pInstance) - { - if (Creature *pTemp = Unit::GetCreature(*me,pInstance->GetData64(uiDataId))) - { - if (pTemp->isAlive() && !pTemp->getVictim()) - { - if (pTemp->HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE)) - pTemp->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - if (pTemp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - int32 iTextId = 0; - AddDrakeLootMode(); - - achievProgress++; - - switch(pTemp->GetEntry()) - { - case NPC_TENEBRON: - iTextId = SAY_SARTHARION_CALL_TENEBRON; - pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aTene[1].m_fX, m_aTene[1].m_fY, m_aTene[1].m_fZ); - break; - case NPC_SHADRON: - iTextId = SAY_SARTHARION_CALL_SHADRON; - pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aShad[1].m_fX, m_aShad[1].m_fY, m_aShad[1].m_fZ); - break; - case NPC_VESPERON: - iTextId = SAY_SARTHARION_CALL_VESPERON; - pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aVesp[1].m_fX, m_aVesp[1].m_fY, m_aVesp[1].m_fZ); - break; - } - - DoScriptText(iTextId, me); - } - } - } - } - - void SendFlameTsunami() - { - if (Map* pMap = me->GetMap()) - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (!PlayerList.isEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource() && i->getSource()->isAlive()) - DoScriptText(WHISPER_LAVA_CHURN, me, i->getSource()); - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - Unit* pTene = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_TENEBRON) : 0); - Unit* pShad = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SHADRON) : 0); - Unit* pVesp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_VESPERON) : 0); - - //spell will target dragons, if they are still alive at 35% - if (!m_bIsBerserk && (me->GetHealth()*100 / me->GetMaxHealth()) <= 35 - && ((pTene && pTene->isAlive()) || (pShad && pShad->isAlive()) || (pVesp && pVesp->isAlive()))) - { - DoScriptText(SAY_SARTHARION_BERSERK, me); - DoCast(me, SPELL_BERSERK); - m_bIsBerserk = true; - } - - //soft enrage - if (!m_bIsSoftEnraged && (me->GetHealth()*100 / me->GetMaxHealth()) <= 10) - { - // TODO - m_bIsSoftEnraged = true; - } - - // hard enrage - if (!m_bIsHardEnraged) - { - if (m_uiEnrageTimer <= uiDiff) - { - DoCast(me, SPELL_PYROBUFFET, true); - m_bIsHardEnraged = true; - } - else - m_uiEnrageTimer -= uiDiff; - } - - // flame tsunami - if (m_uiFlameTsunamiTimer <= uiDiff) - { - SendFlameTsunami(); - switch(urand(0,1)) - { - case 0: - { - if (Creature *Right1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight1Spawn.x, FlameRight1Spawn.y , FlameRight1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) - Right1->GetMotionMaster()->MovePoint(0, FlameRight1Direction.x, FlameRight1Direction.y, FlameRight1Direction.z); - if (Creature *Right2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameRight2Spawn.x, FlameRight2Spawn.y , FlameRight2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) - Right2->GetMotionMaster()->MovePoint(0, FlameRight2Direction.x, FlameRight2Direction.y, FlameRight2Direction.z); - break; - } - case 1: - { - if (Creature *Left1 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft1Spawn.x, FlameLeft1Spawn.y , FlameLeft1Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) - Left1->GetMotionMaster()->MovePoint(0, FlameLeft1Direction.x, FlameLeft1Direction.y, FlameLeft1Direction.z); - if (Creature *Left2 = me->SummonCreature(NPC_FLAME_TSUNAMI, FlameLeft2Spawn.x, FlameLeft2Spawn.y , FlameLeft2Spawn.z, 0, TEMPSUMMON_TIMED_DESPAWN,12000)) - Left2->GetMotionMaster()->MovePoint(0, FlameLeft2Direction.x, FlameLeft2Direction.y, FlameLeft2Direction.z); - break; - } - } - - m_uiFlameTsunamiTimer = 30000; - } - else - m_uiFlameTsunamiTimer -= uiDiff; - - // flame breath - if (m_uiFlameBreathTimer <= uiDiff) - { - DoScriptText(SAY_SARTHARION_BREATH, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_FLAME_BREATH, SPELL_FLAME_BREATH_H)); - m_uiFlameBreathTimer = urand(25000,35000); - } - else - m_uiFlameBreathTimer -= uiDiff; - - // Tail Sweep - if (m_uiTailSweepTimer <= uiDiff) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_TAIL_LASH, SPELL_TAIL_LASH_H)); - m_uiTailSweepTimer = urand(15000,20000); - } - else - m_uiTailSweepTimer -= uiDiff; - - // Cleave - if (m_uiCleaveTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - m_uiCleaveTimer = urand(7000,10000); - } - else - m_uiCleaveTimer -= uiDiff; - - // Lavas Strike - if (m_uiLavaStrikeTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_LAVA_STRIKE); - - if (urand(0,4) == 4) - DoScriptText(RAND(SAY_SARTHARION_SPECIAL_1,SAY_SARTHARION_SPECIAL_2,SAY_SARTHARION_SPECIAL_3), me); - } - m_uiLavaStrikeTimer = urand(5000,20000); - } - else - m_uiLavaStrikeTimer -= uiDiff; - - // call tenebron - if (!m_bHasCalledTenebron && m_uiTenebronTimer <= uiDiff) - { - CallDragon(DATA_TENEBRON); - m_bHasCalledTenebron = true; - } - else - m_uiTenebronTimer -= uiDiff; - - // call shadron - if (!m_bHasCalledShadron && m_uiShadronTimer <= uiDiff) - { - CallDragon(DATA_SHADRON); - m_bHasCalledShadron = true; - } - else - m_uiShadronTimer -= uiDiff; - - // call vesperon - if (!m_bHasCalledVesperon && m_uiVesperonTimer <= uiDiff) - { - CallDragon(DATA_VESPERON); - m_bHasCalledVesperon = true; - } - else - m_uiVesperonTimer -= uiDiff; - - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(uiDiff); - } -}; - -CreatureAI* GetAI_boss_sartharion(Creature* pCreature) -{ - return new boss_sartharionAI(pCreature); -} - -enum TeneText -{ - SAY_TENEBRON_AGGRO = -1615009, - SAY_TENEBRON_SLAY_1 = -1615010, - SAY_TENEBRON_SLAY_2 = -1615011, - SAY_TENEBRON_DEATH = -1615012, - SAY_TENEBRON_BREATH = -1615013, - SAY_TENEBRON_RESPOND = -1615014, - SAY_TENEBRON_SPECIAL_1 = -1615015, - SAY_TENEBRON_SPECIAL_2 = -1615016 -}; - -enum ShadText -{ - SAY_SHADRON_AGGRO = -1615000, - SAY_SHADRON_SLAY_1 = -1615001, - SAY_SHADRON_SLAY_2 = -1615002, - SAY_SHADRON_DEATH = -1615003, - SAY_SHADRON_BREATH = -1615004, - SAY_SHADRON_RESPOND = -1615005, - SAY_SHADRON_SPECIAL_1 = -1615006, - SAY_SHADRON_SPECIAL_2 = -1615007 -}; - -enum VespText -{ - SAY_VESPERON_AGGRO = -1615033, - SAY_VESPERON_SLAY_1 = -1615034, - SAY_VESPERON_SLAY_2 = -1615035, - SAY_VESPERON_DEATH = -1615036, - SAY_VESPERON_BREATH = -1615037, - SAY_VESPERON_RESPOND = -1615038, - SAY_VESPERON_SPECIAL_1 = -1615039, - SAY_VESPERON_SPECIAL_2 = -1615040 -}; - -//to control each dragons common abilities -struct dummy_dragonAI : public ScriptedAI -{ - dummy_dragonAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 m_uiWaypointId; - uint32 m_uiMoveNextTimer; - int32 m_iPortalRespawnTime; - bool m_bCanMoveFree; - - void Reset() - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (GameObject* TwilightPortal = GameObject::GetGameObject((*me), pInstance->GetData64(GO_TWILIGHT_PORTAL))) - TwilightPortal->SetGoState(GO_STATE_READY); - - m_uiWaypointId = 0; - m_uiMoveNextTimer = 500; - m_iPortalRespawnTime = 30000; - m_bCanMoveFree = false; - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (!pInstance || uiType != POINT_MOTION_TYPE) - return; - - debug_log("dummy_dragonAI: %s reached point %u", me->GetName(), uiPointId); - - //if healers messed up the raid and we was already initialized - if (pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) - { - EnterEvadeMode(); - return; - } - - //this is end, if we reach this, don't do much - if (uiPointId == POINT_ID_LAND) - { - me->GetMotionMaster()->Clear(); - m_bCanMoveFree = false; - return; - } - - //get amount of common points - uint32 uiCommonWPCount = sizeof(m_aDragonCommon)/sizeof(Waypoint); - - //increase - m_uiWaypointId = uiPointId+1; - - //if we have reached a point bigger or equal to count, it mean we must reset to point 0 - if (m_uiWaypointId >= uiCommonWPCount) - { - if (!m_bCanMoveFree) - m_bCanMoveFree = true; - - m_uiWaypointId = 0; - } - - m_uiMoveNextTimer = 500; - } - - //used when open portal and spawn mobs in phase - void DoRaidWhisper(int32 iTextId) - { - Map* pMap = me->GetMap(); - - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - DoScriptText(iTextId, me, i->getSource()); - } - } - } - - //"opens" the portal and does the "opening" whisper - void OpenPortal() - { - int32 iTextId = 0; - - //there are 4 portal spawn locations, each are expected to be spawned with negative spawntimesecs in database - - //using a grid search here seem to be more efficient than caching all four guids - //in instance script and calculate range to each. - GameObject* pPortal = me->FindNearestGameObject(GO_TWILIGHT_PORTAL,50.0f); - if (GameObject* TwilightPortal = GameObject::GetGameObject((*me), pInstance->GetData64(GO_TWILIGHT_PORTAL))) - TwilightPortal->SetGoState(GO_STATE_ACTIVE); - - switch(me->GetEntry()) - { - case NPC_TENEBRON: - { - iTextId = WHISPER_HATCH_EGGS; - if (pInstance && pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggs[0].x, TwilightEggs[0].y, TwilightEggs[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - else - me->SummonCreature(NPC_TWILIGHT_EGG, TwilightEggsSarth[0].x, TwilightEggsSarth[0].y, TwilightEggsSarth[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - break; - } - case NPC_SHADRON: - { - iTextId = WHISPER_OPEN_PORTAL; - if (pInstance && !pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron.x, AcolyteofShadron.y , AcolyteofShadron.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - else - me->SummonCreature(NPC_ACOLYTE_OF_SHADRON, AcolyteofShadron2.x, AcolyteofShadron2.y , AcolyteofShadron2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - - break; - } - case NPC_VESPERON: - { - if (pInstance && !pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon.x, AcolyteofVesperon.y , AcolyteofVesperon.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - else - me->SummonCreature(NPC_ACOLYTE_OF_VESPERON, AcolyteofVesperon2.x, AcolyteofVesperon2.y , AcolyteofVesperon2.z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN,20000); - - iTextId = WHISPER_OPEN_PORTAL; - break; - } - } - - DoRaidWhisper(iTextId); - - //By using SetRespawnTime() we will actually "spawn" the object with our defined time. - //Once time is up, portal will disappear again. - if (pPortal && !pPortal->isSpawned()) - pPortal->SetRespawnTime(m_iPortalRespawnTime); - - //Unclear what are expected to happen if one drake has a portal open already - //Refresh respawnTime so time again are set to 30secs? - } - - void JustDied(Unit* /*pKiller*/) - { - int32 iTextId = 0; - uint32 uiSpellId = 0; - - switch(me->GetEntry()) - { - case NPC_TENEBRON: - iTextId = SAY_TENEBRON_DEATH; - uiSpellId = SPELL_POWER_OF_TENEBRON; - break; - case NPC_SHADRON: - iTextId = SAY_SHADRON_DEATH; - uiSpellId = SPELL_POWER_OF_SHADRON; - break; - case NPC_VESPERON: - iTextId = SAY_VESPERON_DEATH; - uiSpellId = SPELL_POWER_OF_VESPERON; - break; - } - - DoScriptText(iTextId, me); - - me->RemoveOwnedAura(uiSpellId); - - if (pInstance) - { - // not if solo mini-boss fight - if (pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) - return; - - // Twilight Revenge to main boss - if (Unit* pSartharion = Unit::GetUnit((*me), pInstance->GetData64(DATA_SARTHARION))) - if (pSartharion->isAlive()) - DoCast(pSartharion, SPELL_TWILIGHT_REVENGE, true); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_bCanMoveFree && m_uiMoveNextTimer) - { - if (m_uiMoveNextTimer <= uiDiff) - { - if (m_uiWaypointId < MAX_WAYPOINT) - me->GetMotionMaster()->MovePoint(m_uiWaypointId, - m_aDragonCommon[m_uiWaypointId].m_fX, m_aDragonCommon[m_uiWaypointId].m_fY, m_aDragonCommon[m_uiWaypointId].m_fZ); - - debug_log("dummy_dragonAI: %s moving to point %u", me->GetName(), m_uiWaypointId); - m_uiMoveNextTimer = 0; - } - else - m_uiMoveNextTimer -= uiDiff; - } - } -}; - -/*###### -## Mob Tenebron -######*/ - -struct mob_tenebronAI : public dummy_dragonAI -{ - mob_tenebronAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} - - uint32 m_uiShadowBreathTimer; - uint32 m_uiShadowFissureTimer; - uint32 m_uiHatchEggTimer; - - void Reset() - { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiHatchEggTimer = 30000; - } - - void Aggro(Unit* /*pWho*/) - { - DoScriptText(SAY_TENEBRON_AGGRO, me); - DoZoneInCombat(); - DoCast(me, SPELL_POWER_OF_TENEBRON); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_TENEBRON_SLAY_1,SAY_TENEBRON_SLAY_2), me); - /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - achievProgress = 1;*/ - } - - void UpdateAI(const uint32 uiDiff) - { - //if no target, update dummy and return - if (!UpdateVictim()) - { - dummy_dragonAI::UpdateAI(uiDiff); - return; - } - - // shadow fissure - if (m_uiShadowFissureTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE)); - - m_uiShadowFissureTimer = urand(15000,20000); - } - else - m_uiShadowFissureTimer -= uiDiff; - - // Hach Egg - if (m_uiHatchEggTimer <= uiDiff) - { - OpenPortal(); - m_uiHatchEggTimer = 30000; - } - else - m_uiHatchEggTimer -= uiDiff; - - // shadow breath - if (m_uiShadowBreathTimer <= uiDiff) - { - DoScriptText(SAY_TENEBRON_BREATH, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); - m_uiShadowBreathTimer = urand(20000,25000); - } - else - m_uiShadowBreathTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_tenebron(Creature* pCreature) -{ - return new mob_tenebronAI(pCreature); -} - -/*###### -## Mob Shadron -######*/ - -struct mob_shadronAI : public dummy_dragonAI -{ - mob_shadronAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} - - uint32 m_uiShadowBreathTimer; - uint32 m_uiShadowFissureTimer; - uint32 m_uiAcolyteShadronTimer; - - void Reset() - { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiAcolyteShadronTimer = 60000; - - if (me->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) - me->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); - - if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) - me->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); - } - - void Aggro(Unit* /*pWho*/) - { - DoScriptText(SAY_SHADRON_AGGRO,me); - DoZoneInCombat(); - DoCast(me, SPELL_POWER_OF_SHADRON); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SHADRON_SLAY_1,SAY_SHADRON_SLAY_2), me); - /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - achievProgress = 2;*/ - } - - void UpdateAI(const uint32 uiDiff) - { - //if no target, update dummy and return - if (!UpdateVictim()) - { - dummy_dragonAI::UpdateAI(uiDiff); - return; - } - - // shadow fissure - if (m_uiShadowFissureTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H)); - - m_uiShadowFissureTimer = urand(15000,20000); - } - else - m_uiShadowFissureTimer -= uiDiff; - - // Portal Event - if (m_uiAcolyteShadronTimer <= uiDiff) - { - if (me->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) - return; - - OpenPortal(); - m_uiAcolyteShadronTimer = urand(60000,65000); - } - else - m_uiAcolyteShadronTimer -= uiDiff; - - // shadow breath - if (m_uiShadowBreathTimer <= uiDiff) - { - DoScriptText(SAY_SHADRON_BREATH, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); - m_uiShadowBreathTimer = urand(20000,25000); - } - else - m_uiShadowBreathTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_shadron(Creature* pCreature) -{ - return new mob_shadronAI(pCreature); -} - -/*###### -## Mob Vesperon -######*/ - -struct mob_vesperonAI : public dummy_dragonAI -{ - mob_vesperonAI(Creature* pCreature) : dummy_dragonAI(pCreature) {} - - uint32 m_uiShadowBreathTimer; - uint32 m_uiShadowFissureTimer; - uint32 m_uiAcolyteVesperonTimer; - - void Reset() - { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiAcolyteVesperonTimer = 60000; - } - - void Aggro(Unit* /*pWho*/) - { - DoScriptText(SAY_VESPERON_AGGRO,me); - DoZoneInCombat(); - DoCast(me, SPELL_POWER_OF_VESPERON); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_VESPERON_SLAY_1,SAY_VESPERON_SLAY_2), me); - /*if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - achievProgress = 3;*/ - } - - void UpdateAI(const uint32 uiDiff) - { - //if no target, update dummy and return - if (!UpdateVictim()) - { - dummy_dragonAI::UpdateAI(uiDiff); - return; - } - - // shadow fissure - if (m_uiShadowFissureTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, RAID_MODE(SPELL_SHADOW_FISSURE, SPELL_SHADOW_FISSURE_H)); - - m_uiShadowFissureTimer = urand(15000,20000); - } - else - m_uiShadowFissureTimer -= uiDiff; - - // Portal Event - if (m_uiAcolyteVesperonTimer <= uiDiff) - { - OpenPortal(); - DoCast(me->getVictim(), SPELL_TWILIGHT_TORMENT_VESP); - m_uiAcolyteVesperonTimer = urand(60000,70000); - } - else - m_uiAcolyteVesperonTimer -= uiDiff; - - // shadow breath - if (m_uiShadowBreathTimer <= uiDiff) - { - DoScriptText(SAY_VESPERON_BREATH, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BREATH, SPELL_SHADOW_BREATH_H)); - m_uiShadowBreathTimer = urand(20000,25000); - } - else - m_uiShadowBreathTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_vesperon(Creature* pCreature) -{ - return new mob_vesperonAI(pCreature); -} - -/*###### -## Mob Acolyte of Shadron -######*/ - -struct mob_acolyte_of_shadronAI : public ScriptedAI -{ - mob_acolyte_of_shadronAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 uiShiftEffectTimer; - - void Reset() - { - uiShiftEffectTimer = 1000; - if (pInstance) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true); - - Creature* pSartharion = Unit::GetCreature(*me, pInstance->GetData64(DATA_SARTHARION)); - if (Creature* pShadron = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON))) - //if not solo figth, buff main boss, else place debuff on mini-boss. both spells TARGET_SCRIPT - if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - pSartharion->CastSpell(me, SPELL_GIFT_OF_TWILIGTH_SAR, true); - else - { - pShadron->CastSpell(me, SPELL_GIFT_OF_TWILIGTH_SHA,true); - pShadron->AddThreat(pTarget, 100.0f); - AttackStart(pShadron->getVictim()); - } - } - me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER,me); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - //Creature* pDebuffTarget = NULL; - Map *map = me->GetMap(); - if (map->IsDungeon()) - { - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT,0) && !i->getSource()->getVictim()) - { - i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_SHIFT_REMOVAL_ALL,true); - i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_RESIDUE,true); - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); - } - } - } - - if (pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - { - //not solo fight, so main boss has deduff - Creature* pDebuffTarget = Unit::GetCreature(*me, pInstance->GetData64(DATA_SARTHARION)); - if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SAR)) - pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SAR); - } - else - { - //event not in progress, then solo fight and must remove debuff mini-boss - Creature* pDebuffTarget = Unit::GetCreature(*me, pInstance->GetData64(DATA_SHADRON)); - if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) - pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); - } - } - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_acolyte_of_shadron(Creature* pCreature) -{ - return new mob_acolyte_of_shadronAI(pCreature); -} - -/*###### -## Mob Acolyte of Vesperon -######*/ - -struct mob_acolyte_of_vesperonAI : public ScriptedAI -{ - mob_acolyte_of_vesperonAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - { - me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER,me); - } - DoCast(me, SPELL_TWILIGHT_TORMENT_VESP_ACO); - } - - void JustDied(Unit* /*pKiller*/) - { - // remove twilight torment on Vesperon - if (pInstance) - { - Creature* pVesperon = Unit::GetCreature(*me, pInstance->GetData64(DATA_VESPERON)); - - if (pVesperon && pVesperon->isAlive() && pVesperon->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) - pVesperon->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); - - Map *map = me->GetMap(); - if (map->IsDungeon()) - { - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT,0) && !i->getSource()->getVictim()) - { - i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_SHIFT_REMOVAL_ALL,true); - i->getSource()->CastSpell(i->getSource(),SPELL_TWILIGHT_RESIDUE,true); - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); - } - if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_TORMENT_VESP,0) && !i->getSource()->getVictim()) - i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); - } - } - - } - } - - void UpdateAI(const uint32 /*uiDiff*/) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_acolyte_of_vesperon(Creature* pCreature) -{ - return new mob_acolyte_of_vesperonAI(pCreature); -} - -/*###### -## Mob Twilight Eggs -######*/ - -struct mob_twilight_eggsAI : public Scripted_NoMovementAI -{ - mob_twilight_eggsAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - uint32 m_uiFadeArmorTimer; - uint32 m_uiHatchEggTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - m_uiHatchEggTimer = 20000; - m_uiFadeArmorTimer = 1000; - } - void SpawnWhelps() - { - if (!pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - me->SummonCreature(NPC_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - else - me->SummonCreature(NPC_SHARTHARION_TWILIGHT_WHELP, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - me->DealDamage(me, me->GetHealth()); - } - void UpdateAI(const uint32 uiDiff) - { - if (m_uiHatchEggTimer <= uiDiff) - { - SpawnWhelps(); - } - else - m_uiHatchEggTimer -= uiDiff; - } - void AttackStart(Unit* /*pWho*/) {} - void MoveInLineOfSight(Unit* /*pWho*/) {} -}; - -CreatureAI* GetAI_mob_twilight_eggs(Creature* pCreature) -{ - return new mob_twilight_eggsAI(pCreature); -} - -/*###### -## Flame Tzunami -######*/ -struct npc_flame_tsunamiAI : public ScriptedAI -{ - npc_flame_tsunamiAI(Creature* pCreature) : ScriptedAI(pCreature) - { - me->HasAura(SPELL_FLAME_TSUNAMI_DMG_AURA); - DoCast(me, SPELL_FLAME_TSUNAMI); - } - - uint32 Tsunami_Timer; - - void Reset() - { - Tsunami_Timer = 100; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void UpdateAI(const uint32 diff) - { - if (Tsunami_Timer <= diff) - { - DoCast(me, SPELL_FLAME_TSUNAMI_DMG_AURA); - Tsunami_Timer = 1000; - } else Tsunami_Timer -= diff; - } -}; -// Twilight Fissure -struct npc_twilight_fissureAI : public Scripted_NoMovementAI -{ - npc_twilight_fissureAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - Reset(); - } - - uint32 VoidBlast_Timer; - - void Reset() - { - VoidBlast_Timer = 5000; - } - - void UpdateAI(const uint32 diff) - { - if (VoidBlast_Timer <= diff) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_VOID_BLAST, SPELL_VOID_BLAST_H)); - VoidBlast_Timer = 9000; - me->Kill(me); - } else VoidBlast_Timer -= diff; - } -}; - - -CreatureAI* GetAI_npc_flame_tsunami(Creature* pCreature) -{ - return new npc_flame_tsunamiAI(pCreature); -} - -CreatureAI* GetAI_npc_twilight_fissure(Creature* pCreature) -{ - return new npc_twilight_fissureAI(pCreature); -} - -/*###### -## Mob Twilight Whelps -######*/ - -struct mob_twilight_whelpAI : public ScriptedAI -{ - mob_twilight_whelpAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 m_uiFadeArmorTimer; - - void Reset() - { - m_uiFadeArmorTimer = 1000; - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // twilight torment - if (m_uiFadeArmorTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_FADE_ARMOR); - m_uiFadeArmorTimer = urand(5000,10000); - } - else - m_uiFadeArmorTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_twilight_whelp(Creature* pCreature) -{ - return new mob_twilight_whelpAI(pCreature); -} - -void AddSC_boss_sartharion() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sartharion"; - newscript->GetAI = &GetAI_boss_sartharion; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_vesperon"; - newscript->GetAI = &GetAI_mob_vesperon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadron"; - newscript->GetAI = &GetAI_mob_shadron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tenebron"; - newscript->GetAI = &GetAI_mob_tenebron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_acolyte_of_shadron"; - newscript->GetAI = &GetAI_mob_acolyte_of_shadron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_acolyte_of_vesperon"; - newscript->GetAI = &GetAI_mob_acolyte_of_vesperon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_twilight_eggs"; - newscript->GetAI = &GetAI_mob_twilight_eggs; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_flame_tsunami"; - newscript->GetAI = &GetAI_npc_flame_tsunami; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_twilight_fissure"; - newscript->GetAI = &GetAI_npc_twilight_fissure; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_twilight_whelp"; - newscript->GetAI = &GetAI_mob_twilight_whelp; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp b/src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp deleted file mode 100644 index 7ef8e03c779..00000000000 --- a/src/server/scripts/Northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "ScriptedPch.h" -#include "obsidian_sanctum.h" - -#define MAX_ENCOUNTER 1 - -/* Obsidian Sanctum encounters: -0 - Sartharion -*/ - -struct instance_obsidian_sanctum : public ScriptedInstance -{ - instance_obsidian_sanctum(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint64 m_uiSartharionGUID; - uint64 m_uiTenebronGUID; - uint64 m_uiShadronGUID; - uint64 m_uiVesperonGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiSartharionGUID = 0; - m_uiTenebronGUID = 0; - m_uiShadronGUID = 0; - m_uiVesperonGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_SARTHARION: - m_uiSartharionGUID = pCreature->GetGUID(); - break; - //three dragons below set to active state once created. - //we must expect bigger raid to encounter main boss, and then three dragons must be active due to grid differences - case NPC_TENEBRON: - m_uiTenebronGUID = pCreature->GetGUID(); - pCreature->setActive(true); - break; - case NPC_SHADRON: - m_uiShadronGUID = pCreature->GetGUID(); - pCreature->setActive(true); - break; - case NPC_VESPERON: - m_uiVesperonGUID = pCreature->GetGUID(); - pCreature->setActive(true); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - if (uiType == TYPE_SARTHARION_EVENT) - m_auiEncounter[0] = uiData; - } - - uint32 GetData(uint32 uiType) - { - if (uiType == TYPE_SARTHARION_EVENT) - return m_auiEncounter[0]; - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_SARTHARION: - return m_uiSartharionGUID; - case DATA_TENEBRON: - return m_uiTenebronGUID; - case DATA_SHADRON: - return m_uiShadronGUID; - case DATA_VESPERON: - return m_uiVesperonGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_obsidian_sanctum(Map* pMap) -{ - return new instance_obsidian_sanctum(pMap); -} - -void AddSC_instance_obsidian_sanctum() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_obsidian_sanctum"; - newscript->GetInstanceData = &GetInstanceData_instance_obsidian_sanctum; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h b/src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h deleted file mode 100644 index 59013174795..00000000000 --- a/src/server/scripts/Northrend/obsidian_sanctum/obsidian_sanctum.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef DEF_OBSIDIAN_SANCTUM_H -#define DEF_OBSIDIAN_SANCTUM_H - -enum eTypes -{ - TYPE_SARTHARION_EVENT = 1, - - DATA_SARTHARION = 10, - DATA_TENEBRON = 11, - DATA_SHADRON = 12, - DATA_VESPERON = 13, - - NPC_SARTHARION = 28860, - NPC_TENEBRON = 30452, - NPC_SHADRON = 30451, - NPC_VESPERON = 30449, - GO_TWILIGHT_PORTAL = 193988 -}; - -#endif diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp deleted file mode 100644 index c2da2a24e71..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss General Bjarngrim -SD%Complete: 70% -SDComment: Waypoint needed, we expect boss to always have 2x Stormforged Lieutenant following -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - //Yell - SAY_AGGRO = -1602000, - SAY_SLAY_1 = -1602001, - SAY_SLAY_2 = -1602002, - SAY_SLAY_3 = -1602003, - SAY_DEATH = -1602004, - SAY_BATTLE_STANCE = -1602005, - EMOTE_BATTLE_STANCE = -1602006, - SAY_BERSEKER_STANCE = -1602007, - EMOTE_BERSEKER_STANCE = -1602008, - SAY_DEFENSIVE_STANCE = -1602009, - EMOTE_DEFENSIVE_STANCE = -1602010, - - SPELL_DEFENSIVE_STANCE = 53790, - //SPELL_DEFENSIVE_AURA = 41105, - SPELL_SPELL_REFLECTION = 36096, - SPELL_PUMMEL = 12555, - SPELL_KNOCK_AWAY = 52029, - SPELL_IRONFORM = 52022, - - SPELL_BERSEKER_STANCE = 53791, - //SPELL_BERSEKER_AURA = 41107, - SPELL_INTERCEPT = 58769, - SPELL_WHIRLWIND = 52027, - SPELL_CLEAVE = 15284, - - SPELL_BATTLE_STANCE = 53792, - //SPELL_BATTLE_AURA = 41106, - SPELL_MORTAL_STRIKE = 16856, - SPELL_SLAM = 52026, - - //OTHER SPELLS - //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other - //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above - - NPC_STORMFORGED_LIEUTENANT = 29240, - SPELL_ARC_WELD = 59085, - SPELL_RENEW_STEEL_N = 52774, - SPELL_RENEW_STEEL_H = 59160, - - EQUIP_SWORD = 37871, - EQUIP_SHIELD = 35642, - EQUIP_MACE = 43623, - - STANCE_DEFENSIVE = 0, - STANCE_BERSERKER = 1, - STANCE_BATTLE = 2 -}; - -/*###### -## boss_bjarngrim -######*/ - -struct boss_bjarngrimAI : public ScriptedAI -{ - boss_bjarngrimAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - m_uiStance = STANCE_DEFENSIVE; - memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID)); - } - - ScriptedInstance* m_pInstance; - - bool m_bIsChangingStance; - - uint8 m_uiChargingStatus; - uint8 m_uiStance; - - uint32 m_uiCharge_Timer; - uint32 m_uiChangeStance_Timer; - - uint32 m_uiReflection_Timer; - uint32 m_uiKnockAway_Timer; - uint32 m_uiPummel_Timer; - uint32 m_uiIronform_Timer; - - uint32 m_uiIntercept_Timer; - uint32 m_uiWhirlwind_Timer; - uint32 m_uiCleave_Timer; - - uint32 m_uiMortalStrike_Timer; - uint32 m_uiSlam_Timer; - - uint64 m_auiStormforgedLieutenantGUID[2]; - - void Reset() - { - m_bIsChangingStance = false; - - m_uiChargingStatus = 0; - m_uiCharge_Timer = 1000; - - m_uiChangeStance_Timer = 20000 + rand()%5000; - - m_uiReflection_Timer = 8000; - m_uiKnockAway_Timer = 20000; - m_uiPummel_Timer = 10000; - m_uiIronform_Timer = 25000; - - m_uiIntercept_Timer = 5000; - m_uiWhirlwind_Timer = 10000; - m_uiCleave_Timer = 8000; - - m_uiMortalStrike_Timer = 8000; - m_uiSlam_Timer = 10000; - - for (uint8 i = 0; i < 2; ++i) - { - if (Creature* pStormforgedLieutenant = (Unit::GetCreature((*me), m_auiStormforgedLieutenantGUID[i]))) - { - if (!pStormforgedLieutenant->isAlive()) - pStormforgedLieutenant->Respawn(); - } - } - - if (m_uiStance != STANCE_DEFENSIVE) - { - DoRemoveStanceAura(m_uiStance); - DoCast(me, SPELL_DEFENSIVE_STANCE); - m_uiStance = STANCE_DEFENSIVE; - } - - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - //must get both lieutenants here and make sure they are with him - me->CallForHelp(30.0f); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, DONE); - } - - //TODO: remove when removal is done by the core - void DoRemoveStanceAura(uint8 uiStance) - { - switch(uiStance) - { - case STANCE_DEFENSIVE: - me->RemoveAurasDueToSpell(SPELL_DEFENSIVE_STANCE); - break; - case STANCE_BERSERKER: - me->RemoveAurasDueToSpell(SPELL_BERSEKER_STANCE); - break; - case STANCE_BATTLE: - me->RemoveAurasDueToSpell(SPELL_BATTLE_STANCE); - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // Change stance - if (m_uiChangeStance_Timer <= uiDiff) - { - //wait for current spell to finish before change stance - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoRemoveStanceAura(m_uiStance); - - int uiTempStance = rand()%(3-1); - - if (uiTempStance >= m_uiStance) - ++uiTempStance; - - m_uiStance = uiTempStance; - - switch(m_uiStance) - { - case STANCE_DEFENSIVE: - DoScriptText(SAY_DEFENSIVE_STANCE, me); - DoScriptText(EMOTE_DEFENSIVE_STANCE, me); - DoCast(me, SPELL_DEFENSIVE_STANCE); - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); - break; - case STANCE_BERSERKER: - DoScriptText(SAY_BERSEKER_STANCE, me); - DoScriptText(EMOTE_BERSEKER_STANCE, me); - DoCast(me, SPELL_BERSEKER_STANCE); - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); - break; - case STANCE_BATTLE: - DoScriptText(SAY_BATTLE_STANCE, me); - DoScriptText(EMOTE_BATTLE_STANCE, me); - DoCast(me, SPELL_BATTLE_STANCE); - SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - break; - } - - m_uiChangeStance_Timer = 20000 + rand()%5000; - return; - } - else - m_uiChangeStance_Timer -= uiDiff; - - switch(m_uiStance) - { - case STANCE_DEFENSIVE: - { - if (m_uiReflection_Timer <= uiDiff) - { - DoCast(me, SPELL_SPELL_REFLECTION); - m_uiReflection_Timer = 8000 + rand()%1000; - } - else - m_uiReflection_Timer -= uiDiff; - - if (m_uiKnockAway_Timer <= uiDiff) - { - DoCast(me, SPELL_KNOCK_AWAY); - m_uiKnockAway_Timer = 20000 + rand()%1000; - } - else - m_uiKnockAway_Timer -= uiDiff; - - if (m_uiPummel_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_PUMMEL); - m_uiPummel_Timer = 10000 + rand()%1000; - } - else - m_uiPummel_Timer -= uiDiff; - - if (m_uiIronform_Timer <= uiDiff) - { - DoCast(me, SPELL_IRONFORM); - m_uiIronform_Timer = 25000 + rand()%1000; - } - else - m_uiIronform_Timer -= uiDiff; - - break; - } - case STANCE_BERSERKER: - { - if (m_uiIntercept_Timer <= uiDiff) - { - //not much point is this, better random target and more often? - DoCast(me->getVictim(), SPELL_INTERCEPT); - m_uiIntercept_Timer = 45000 + rand()%1000; - } - else - m_uiIntercept_Timer -= uiDiff; - - if (m_uiWhirlwind_Timer <= uiDiff) - { - DoCast(me, SPELL_WHIRLWIND); - m_uiWhirlwind_Timer = 10000 + rand()%1000; - } - else - m_uiWhirlwind_Timer -= uiDiff; - - if (m_uiCleave_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - m_uiCleave_Timer = 8000 + rand()%1000; - } - else - m_uiCleave_Timer -= uiDiff; - - break; - } - case STANCE_BATTLE: - { - if (m_uiMortalStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - m_uiMortalStrike_Timer = 20000 + rand()%1000; - } - else - m_uiMortalStrike_Timer -= uiDiff; - - if (m_uiSlam_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SLAM); - m_uiSlam_Timer = 15000 + rand()%1000; - } - else - m_uiSlam_Timer -= uiDiff; - - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -/*###### -## mob_stormforged_lieutenant -######*/ - -struct mob_stormforged_lieutenantAI : public ScriptedAI -{ - mob_stormforged_lieutenantAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiArcWeld_Timer; - uint32 m_uiRenewSteel_Timer; - - void Reset() - { - m_uiArcWeld_Timer = 20000 + rand()%1000; - m_uiRenewSteel_Timer = 10000 + rand()%1000; - } - - void EnterCombat(Unit* pWho) - { - if (m_pInstance) - { - if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) - { - if (pBjarngrim->isAlive() && !pBjarngrim->getVictim()) - pBjarngrim->AI()->AttackStart(pWho); - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_uiArcWeld_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_ARC_WELD); - m_uiArcWeld_Timer = 20000 + rand()%1000; - } - else - m_uiArcWeld_Timer -= uiDiff; - - if (m_uiRenewSteel_Timer <= uiDiff) - { - if (m_pInstance) - { - if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) - { - if (pBjarngrim->isAlive()) - DoCast(pBjarngrim, SPELL_RENEW_STEEL_N); - } - } - m_uiRenewSteel_Timer = 10000 + rand()%4000; - } - else - m_uiRenewSteel_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_bjarngrim(Creature* pCreature) -{ - return new boss_bjarngrimAI(pCreature); -} - -CreatureAI* GetAI_mob_stormforged_lieutenant(Creature* pCreature) -{ - return new mob_stormforged_lieutenantAI(pCreature); -} - -void AddSC_boss_bjarngrim() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_bjarngrim"; - newscript->GetAI = &GetAI_boss_bjarngrim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stormforged_lieutenant"; - newscript->GetAI = &GetAI_mob_stormforged_lieutenant; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp deleted file mode 100644 index ecf61188b3e..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_ionar.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: Timer check pending - */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum Spells -{ - SPELL_BALL_LIGHTNING = 52780, - H_SPELL_BALL_LIGHTNING = 59800, - SPELL_STATIC_OVERLOAD = 52658, - H_SPELL_STATIC_OVERLOAD = 59795, - - SPELL_DISPERSE = 52770, - SPELL_SUMMON_SPARK = 52746, - SPELL_SPARK_DESPAWN = 52776, - - //Spark of Ionar - SPELL_SPARK_VISUAL_TRIGGER = 52667, - H_SPELL_SPARK_VISUAL_TRIGGER = 59833 -}; - -enum Yells -{ - SAY_AGGRO = -1602011, - SAY_SLAY_1 = -1602012, - SAY_SLAY_2 = -1602013, - SAY_SLAY_3 = -1602014, - SAY_DEATH = -1602015, - SAY_SPLIT_1 = -1602016, - SAY_SPLIT_2 = -1602017 -}; - -enum Creatures -{ - NPC_SPARK_OF_IONAR = 28926 -}; - -enum Misc -{ - DATA_MAX_SPARKS = 5, - DATA_MAX_SPARK_DISTANCE = 90, // Distance to boss - prevent runs through the whole instance - DATA_POINT_CALLBACK = 0 -}; - -/*###### -## Boss Ionar -######*/ - -struct boss_ionarAI : public ScriptedAI -{ - boss_ionarAI(Creature *pCreature) : ScriptedAI(pCreature), lSparkList(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - SummonList lSparkList; - - bool bIsSplitPhase; - bool bHasDispersed; - - uint32 uiSplitTimer; - - uint32 uiStaticOverloadTimer; - uint32 uiBallLightningTimer; - - uint32 uiDisperseHealth; - - void Reset() - { - lSparkList.DespawnAll(); - - bIsSplitPhase = true; - bHasDispersed = false; - - uiSplitTimer = 25*IN_MILISECONDS; - - uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); - uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); - - uiDisperseHealth = 45 + urand(0,10); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - if (me->GetVisibility() == VISIBILITY_OFF) - me->SetVisibility(VISIBILITY_ON); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - lSparkList.DespawnAll(); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - //make sparks come back - void CallBackSparks() - { - //should never be empty here, but check - if (lSparkList.empty()) - return; - - Position pos; - me->GetPosition(&pos); - - for (std::list::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) - { - if (Creature* pSpark = Unit::GetCreature(*me, *itr)) - { - if (pSpark->isAlive()) - { - pSpark->SetSpeed(MOVE_RUN, 2.0f); - pSpark->GetMotionMaster()->Clear(); - pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); - } - else - pSpark->ForcedDespawn(); - } - } - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - if (me->GetVisibility() == VISIBILITY_OFF) - uiDamage = 0; - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) - { - lSparkList.Summon(pSummoned); - - pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER,H_SPELL_SPARK_VISUAL_TRIGGER), true); - - Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - pSummoned->SetInCombatWith(pTarget); - pSummoned->GetMotionMaster()->Clear(); - pSummoned->GetMotionMaster()->MoveFollow(pTarget, 0.0f, 0.0f); - } - } - } - - void SummonedCreatureDespawn(Creature *pSummoned) - { - if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) - lSparkList.Despawn(pSummoned); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // Splitted - if (me->GetVisibility() == VISIBILITY_OFF) - { - if (uiSplitTimer <= uiDiff) - { - uiSplitTimer = 2.5*IN_MILISECONDS; - - // Return sparks to where Ionar splitted - if (bIsSplitPhase) - { - CallBackSparks(); - bIsSplitPhase = false; - } - // Lightning effect and restore Ionar - else if (lSparkList.empty()) - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - DoCast(me, SPELL_SPARK_DESPAWN, false); - - uiSplitTimer = 25*IN_MILISECONDS; - bIsSplitPhase = true; - - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - } - else - uiSplitTimer -= uiDiff; - - return; - } - - if (uiStaticOverloadTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_STATIC_OVERLOAD); - - uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); - } - else - uiStaticOverloadTimer -= uiDiff; - - if (uiBallLightningTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); - uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); - } - else - uiBallLightningTimer -= uiDiff; - - // Health check - if (!bHasDispersed && HealthBelowPct(uiDisperseHealth)) - { - bHasDispersed = true; - - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me, SPELL_DISPERSE, true); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ionar(Creature* pCreature) -{ - return new boss_ionarAI(pCreature); -} - -bool EffectDummyCreature_boss_ionar(Unit* /*pCaster*/, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_DISPERSE && uiEffIndex == 0) - { - if (pCreatureTarget->GetEntry() != NPC_IONAR) - return true; - - for (uint8 i = 0; i < DATA_MAX_SPARKS; ++i) - pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true); - - pCreatureTarget->AttackStop(); - pCreatureTarget->SetVisibility(VISIBILITY_OFF); - pCreatureTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - pCreatureTarget->GetMotionMaster()->Clear(); - pCreatureTarget->GetMotionMaster()->MoveIdle(); - - //always return true when we are handling this spell and effect - return true; - } - return false; -} - -/*###### -## mob_spark_of_ionar -######*/ - -struct mob_spark_of_ionarAI : public ScriptedAI -{ - mob_spark_of_ionarAI(Creature *pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCheckTimer; - - void Reset() - { - uiCheckTimer = 2*IN_MILISECONDS; - me->SetReactState(REACT_PASSIVE); - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE || !pInstance) - return; - - if (uiPointId == DATA_POINT_CALLBACK) - me->ForcedDespawn(); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - uiDamage = 0; - } - - void UpdateAI(const uint32 uiDiff) - { - // Despawn if the encounter is not running - if (pInstance && pInstance->GetData(TYPE_IONAR) != IN_PROGRESS) - { - me->ForcedDespawn(); - return; - } - - // Prevent them to follow players through the whole instance - if (uiCheckTimer <= uiDiff) - { - if (pInstance) - { - Creature* pIonar = pInstance->instance->GetCreature(pInstance->GetData64(DATA_IONAR)); - if (pIonar && pIonar->isAlive()) - { - if (me->GetDistance(pIonar) > DATA_MAX_SPARK_DISTANCE) - { - Position pos; - pIonar->GetPosition(&pos); - - me->SetSpeed(MOVE_RUN, 2.0f); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); - } - } - else - me->ForcedDespawn(); - } - uiCheckTimer = 2*IN_MILISECONDS; - } - else - uiCheckTimer -= uiDiff; - - // No melee attack at all! - } -}; - -CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature) -{ - return new mob_spark_of_ionarAI(pCreature); -} - -void AddSC_boss_ionar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ionar"; - newscript->GetAI = &GetAI_boss_ionar; - newscript->pEffectDummyCreature = &EffectDummyCreature_boss_ionar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_spark_of_ionar"; - newscript->GetAI = &GetAI_mob_spark_of_ionar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp deleted file mode 100644 index f08c19efca2..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_loken.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Loken -SD%Complete: 60% -SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414) -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - ACHIEV_TIMELY_DEATH_START_EVENT = 20384, - - SAY_AGGRO = -1602018, - SAY_INTRO_1 = -1602019, - SAY_INTRO_2 = -1602020, - SAY_SLAY_1 = -1602021, - SAY_SLAY_2 = -1602022, - SAY_SLAY_3 = -1602023, - SAY_DEATH = -1602024, - SAY_NOVA_1 = -1602025, - SAY_NOVA_2 = -1602026, - SAY_NOVA_3 = -1602027, - SAY_75HEALTH = -1602028, - SAY_50HEALTH = -1602029, - SAY_25HEALTH = -1602030, - EMOTE_NOVA = -1602031, - - SPELL_ARC_LIGHTNING = 52921, - SPELL_LIGHTNING_NOVA_N = 52960, - SPELL_LIGHTNING_NOVA_H = 59835, - - SPELL_PULSING_SHOCKWAVE_N = 52961, - SPELL_PULSING_SHOCKWAVE_H = 59836, - SPELL_PULSING_SHOCKWAVE_AURA = 59414 -}; - -/*###### -## Boss Loken -######*/ - -struct boss_lokenAI : public ScriptedAI -{ - boss_lokenAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - bool m_bIsAura; - - uint32 m_uiArcLightning_Timer; - uint32 m_uiLightningNova_Timer; - uint32 m_uiPulsingShockwave_Timer; - uint32 m_uiResumePulsingShockwave_Timer; - - uint32 m_uiHealthAmountModifier; - - void Reset() - { - m_bIsAura = false; - - m_uiArcLightning_Timer = 15000; - m_uiLightningNova_Timer = 20000; - m_uiPulsingShockwave_Timer = 2000; - m_uiResumePulsingShockwave_Timer = 15000; - - m_uiHealthAmountModifier = 1; - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED); - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS); - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); - } - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_LOKEN, DONE); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_bIsAura) - { - // workaround for PULSING_SHOCKWAVE - if (m_uiPulsingShockwave_Timer <= uiDiff) - { - Map* pMap = me->GetMap(); - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack()) - { - int32 dmg; - float m_fDist = me->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()); - - dmg = DUNGEON_MODE(100, 150); // need to correct damage - if (m_fDist > 1.0f) // Further from 1 yard - dmg *= m_fDist; - - me->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false); - } - } - m_uiPulsingShockwave_Timer = 2000; - } else m_uiPulsingShockwave_Timer -= uiDiff; - } - else - { - if (m_uiResumePulsingShockwave_Timer <= uiDiff) - { - //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement? - DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); - - DoCast(me, SPELL_PULSING_SHOCKWAVE_N); // need core support - m_bIsAura = true; - m_uiResumePulsingShockwave_Timer = 0; - } - else - m_uiResumePulsingShockwave_Timer -= uiDiff; - } - - if (m_uiArcLightning_Timer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ARC_LIGHTNING); - - m_uiArcLightning_Timer = 15000 + rand()%1000; - } - else - m_uiArcLightning_Timer -= uiDiff; - - if (m_uiLightningNova_Timer <= uiDiff) - { - DoScriptText(RAND(SAY_NOVA_1,SAY_NOVA_2,SAY_NOVA_3), me); - DoScriptText(EMOTE_NOVA, me); - DoCast(me, SPELL_LIGHTNING_NOVA_N); - - m_bIsAura = false; - m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura - m_uiLightningNova_Timer = 20000 + rand()%1000; - } - else - m_uiLightningNova_Timer -= uiDiff; - - // Health check - if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(25*m_uiHealthAmountModifier))) - { - switch(m_uiHealthAmountModifier) - { - case 1: DoScriptText(SAY_75HEALTH, me); break; - case 2: DoScriptText(SAY_50HEALTH, me); break; - case 3: DoScriptText(SAY_25HEALTH, me); break; - } - - ++m_uiHealthAmountModifier; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_loken(Creature* pCreature) -{ - return new boss_lokenAI(pCreature); -} - -void AddSC_boss_loken() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_loken"; - newscript->GetAI = &GetAI_boss_loken; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp deleted file mode 100644 index 184050e3103..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_lightning/boss_volkhan.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Volkhan -SD%Complete: 60% -SDComment: Not considered complete. Some events may fail and need further development -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - SAY_AGGRO = -1602032, - SAY_SLAY_1 = -1602033, - SAY_SLAY_2 = -1602034, - SAY_SLAY_3 = -1602035, - SAY_DEATH = -1602036, - SAY_STOMP_1 = -1602037, - SAY_STOMP_2 = -1602038, - SAY_FORGE_1 = -1602039, - SAY_FORGE_2 = -1602040, - EMOTE_TO_ANVIL = -1602041, - EMOTE_SHATTER = -1602042, - - SPELL_HEAT_N = 52387, - SPELL_HEAT_H = 59528, - SPELL_SHATTERING_STOMP_N = 52237, - SPELL_SHATTERING_STOMP_H = 59529, - - //unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on: - SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil - SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss - - //SPELL_TEMPER_VISUAL = 52661, //summons GO - - SPELL_SUMMON_MOLTEN_GOLEM = 52405, - - //Molten Golem - SPELL_BLAST_WAVE = 23113, - SPELL_IMMOLATION_STRIKE_N = 52433, - SPELL_IMMOLATION_STRIKE_H = 59530, - SPELL_SHATTER_N = 52429, - SPELL_SHATTER_H = 59527, - - NPC_VOLKHAN_ANVIL = 28823, - NPC_MOLTEN_GOLEM = 28695, - NPC_BRITTLE_GOLEM = 28681, - - POINT_ID_ANVIL = 0, - MAX_GOLEM = 2, - - ACHIEVEMENT_SHATTER_RESISTANT = 2042 -}; - -/*###### -## Boss Volkhan -######*/ - -struct boss_volkhanAI : public ScriptedAI -{ - boss_volkhanAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - std::list m_lGolemGUIDList; - - bool m_bHasTemper; - bool m_bIsStriking; - bool m_bCanShatterGolem; - - uint8 GolemsShattered; - uint32 m_uiPause_Timer; - uint32 m_uiShatteringStomp_Timer; - uint32 m_uiShatter_Timer; - - uint32 m_uiHealthAmountModifier; - - void Reset() - { - m_bIsStriking = false; - m_bHasTemper = false; - m_bCanShatterGolem = false; - - m_uiPause_Timer = 3500; - m_uiShatteringStomp_Timer = 0; - m_uiShatter_Timer = 5000; - GolemsShattered = 0; - - m_uiHealthAmountModifier = 1; - - DespawnGolem(); - m_lGolemGUIDList.clear(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); - } - - void AttackStart(Unit* pWho) - { - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - if (!m_bHasTemper) - me->GetMotionMaster()->MoveChase(pWho); - } - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - DespawnGolem(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, DONE); - - if (IsHeroic() && GolemsShattered < 5) - { - AchievementEntry const *AchievShatterResistant = GetAchievementStore()->LookupEntry(ACHIEVEMENT_SHATTER_RESISTANT); - if (AchievShatterResistant) - { - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievShatterResistant); - } - } - } - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void DespawnGolem() - { - if (m_lGolemGUIDList.empty()) - return; - - for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - if (pTemp->isAlive()) - pTemp->ForcedDespawn(); - } - } - - m_lGolemGUIDList.clear(); - } - - void ShatterGolem() - { - if (m_lGolemGUIDList.empty()) - return; - - for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - // only shatter brittle golems - if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM) - { - pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false); - GolemsShattered += 1; - } - } - } - } - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_TEMPER_DUMMY) - m_bIsStriking = true; - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_MOLTEN_GOLEM) - { - m_lGolemGUIDList.push_back(pSummoned->GetGUID()); - - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - - //why healing when just summoned? - pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, me->GetGUID()); - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_bIsStriking) - { - if (m_uiPause_Timer <= uiDiff) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) - { - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - - m_bHasTemper = false; - m_bIsStriking = false; - m_uiPause_Timer = 3500; - } - else - m_uiPause_Timer -= uiDiff; - - return; - } - - // When to start shatter? After 60, 40 or 20% hp? - if (!m_bHasTemper && m_uiHealthAmountModifier >= 3) - { - if (m_uiShatteringStomp_Timer <= uiDiff) - { - //should he stomp even if he has no brittle golem to shatter? - - DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2), me); - - DoCast(me, SPELL_SHATTERING_STOMP_N); - - DoScriptText(EMOTE_SHATTER, me); - - m_uiShatteringStomp_Timer = 30000; - m_bCanShatterGolem = true; - } - else - m_uiShatteringStomp_Timer -= uiDiff; - } - - // Shatter Golems 3 seconds after Shattering Stomp - if (m_bCanShatterGolem) - { - if (m_uiShatter_Timer <= uiDiff) - { - ShatterGolem(); - m_uiShatter_Timer = 3000; - m_bCanShatterGolem = false; - } - else - m_uiShatter_Timer -= uiDiff; - } - - // Health check - if (!m_bCanShatterGolem && (me->GetHealth()*100 / me->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier))) - { - ++m_uiHealthAmountModifier; - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoScriptText(RAND(SAY_FORGE_1,SAY_FORGE_2), me); - - m_bHasTemper = true; - - DoCast(me, SPELL_TEMPER, false); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_volkhan(Creature* pCreature) -{ - return new boss_volkhanAI(pCreature); -} - -bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_TEMPER_DUMMY && uiEffIndex == 0) - { - if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN) - return true; - - for (uint8 i = 0; i < MAX_GOLEM; ++i) - { - pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true); - } - - //always return true when we are handling this spell and effect - return true; - } - - return false; -} - -/*###### -## npc_volkhan_anvil -######*/ - -bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_TEMPER && uiEffIndex == 0) - { - if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL) - return true; - - Creature *cre = CAST_CRE(pCaster); - - DoScriptText(EMOTE_TO_ANVIL, pCaster); - - float fX, fY, fZ; - pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE); - - pCaster->AttackStop(); - - if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - pCaster->GetMotionMaster()->MovementExpired(); - - cre->GetMap()->CreatureRelocation(cre, fX, fY, fZ, pCreatureTarget->GetOrientation()); - cre->SendMonsterMove(fX, fY, fZ, 0, cre->GetUnitMovementFlags(), 1); - - pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); - - //always return true when we are handling this spell and effect - return true; - } - - return false; -} - -/*###### -## mob_molten_golem -######*/ - -struct mob_molten_golemAI : public ScriptedAI -{ - mob_molten_golemAI(Creature *pCreature) : ScriptedAI(pCreature) - { - } - - bool m_bIsFrozen; - - uint32 m_uiBlast_Timer; - uint32 m_uiDeathDelay_Timer; - uint32 m_uiImmolation_Timer; - - void Reset() - { - m_bIsFrozen = false; - - m_uiBlast_Timer = 20000; - m_uiDeathDelay_Timer = 0; - m_uiImmolation_Timer = 5000; - } - - void AttackStart(Unit* pWho) - { - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - if (!m_bIsFrozen) - me->GetMotionMaster()->MoveChase(pWho); - } - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) - { - if (uiDamage > me->GetHealth()) - { - me->UpdateEntry(NPC_BRITTLE_GOLEM); - me->SetHealth(1); - uiDamage = 0; - me->RemoveAllAuras(); - me->AttackStop(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - m_bIsFrozen = true; - } - } - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - //this is the dummy effect of the spells - if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H) - { - if (me->GetEntry() == NPC_BRITTLE_GOLEM) - me->ForcedDespawn(); - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target or if we are frozen - if (!UpdateVictim() || m_bIsFrozen) - return; - - if (m_uiBlast_Timer <= uiDiff) - { - DoCast(me, SPELL_BLAST_WAVE); - m_uiBlast_Timer = 20000; - } - else - m_uiBlast_Timer -= uiDiff; - - if (m_uiImmolation_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_IMMOLATION_STRIKE_N); - m_uiImmolation_Timer = 5000; - } - else - m_uiImmolation_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_molten_golem(Creature* pCreature) -{ - return new mob_molten_golemAI(pCreature); -} - -void AddSC_boss_volkhan() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_volkhan"; - newscript->GetAI = &GetAI_boss_volkhan; - newscript->pEffectDummyCreature = &EffectDummyCreature_boss_volkhan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_volkhan_anvil"; - newscript->pEffectDummyCreature = &EffectDummyCreature_npc_volkhan_anvil; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_molten_golem"; - newscript->GetAI = &GetAI_mob_molten_golem; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h b/src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h deleted file mode 100644 index d9739fdf888..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_lightning/halls_of_lightning.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_HALLS_OF_LIGHTNING_H -#define DEF_HALLS_OF_LIGHTNING_H - -enum eTypes -{ - MAX_ENCOUNTER = 4, - - DATA_BJARNGRIM = 1, - DATA_IONAR = 2, - DATA_LOKEN = 3, - DATA_VOLKHAN = 4, - - TYPE_BJARNGRIM = 10, - TYPE_IONAR = 11, - TYPE_LOKEN = 12, - TYPE_VOLKHAN = 13, - - NPC_BJARNGRIM = 28586, - NPC_VOLKHAN = 28587, - NPC_IONAR = 28546, - NPC_LOKEN = 28923, - - GO_BJARNGRIM_DOOR = 191416, //_doors10 - GO_VOLKHAN_DOOR = 191325, //_doors07 - GO_IONAR_DOOR = 191326, //_doors05 - GO_LOKEN_DOOR = 191324, //_doors02 - GO_LOKEN_THRONE = 192654 -}; - -#endif diff --git a/src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp deleted file mode 100644 index 46cd5c9cccc..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Halls_of_Lightning -SD%Complete: 90% -SDComment: All ready. -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -/* Halls of Lightning encounters: -0 - General Bjarngrim -1 - Volkhan -2 - Ionar -3 - Loken -*/ - -struct instance_halls_of_lightning : public ScriptedInstance -{ - instance_halls_of_lightning(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 m_uiGeneralBjarngrimGUID; - uint64 m_uiIonarGUID; - uint64 m_uiLokenGUID; - uint64 m_uiVolkhanGUID; - - uint64 m_uiBjarngrimDoorGUID; - uint64 m_uiVolkhanDoorGUID; - uint64 m_uiIonarDoorGUID; - uint64 m_uiLokenDoorGUID; - uint64 m_uiLokenGlobeGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiGeneralBjarngrimGUID = 0; - m_uiVolkhanGUID = 0; - m_uiIonarGUID = 0; - m_uiLokenGUID = 0; - - m_uiBjarngrimDoorGUID = 0; - m_uiVolkhanDoorGUID = 0; - m_uiIonarDoorGUID = 0; - m_uiLokenDoorGUID = 0; - m_uiLokenGlobeGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_BJARNGRIM: - m_uiGeneralBjarngrimGUID = pCreature->GetGUID(); - break; - case NPC_VOLKHAN: - m_uiVolkhanGUID = pCreature->GetGUID(); - break; - case NPC_IONAR: - m_uiIonarGUID = pCreature->GetGUID(); - break; - case NPC_LOKEN: - m_uiLokenGUID = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_BJARNGRIM_DOOR: - m_uiBjarngrimDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_VOLKHAN_DOOR: - m_uiVolkhanDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_IONAR_DOOR: - m_uiIonarDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_LOKEN_DOOR: - m_uiLokenDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_LOKEN_THRONE: - m_uiLokenGlobeGUID = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_BJARNGRIM: - if (uiData == DONE) - DoUseDoorOrButton(m_uiBjarngrimDoorGUID); - m_auiEncounter[0] = uiData; - break; - case TYPE_VOLKHAN: - if (uiData == DONE) - DoUseDoorOrButton(m_uiVolkhanDoorGUID); - m_auiEncounter[1] = uiData; - break; - case TYPE_IONAR: - if (uiData == DONE) - DoUseDoorOrButton(m_uiIonarDoorGUID); - m_auiEncounter[2] = uiData; - break; - case TYPE_LOKEN: - if (uiData == DONE) - { - DoUseDoorOrButton(m_uiLokenDoorGUID); - - //Appears to be type 5 GO with animation. Need to figure out how this work, code below only placeholder - if (GameObject* pGlobe = instance->GetGameObject(m_uiLokenGlobeGUID)) - pGlobe->SetGoState(GO_STATE_ACTIVE); - } - m_auiEncounter[3] = uiData; - break; - } - - if (uiData == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case TYPE_BJARNGRIM: - return m_auiEncounter[0]; - case TYPE_VOLKHAN: - return m_auiEncounter[1]; - case TYPE_IONAR: - return m_auiEncounter[2]; - case TYPE_LOKEN: - return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_BJARNGRIM: - return m_uiGeneralBjarngrimGUID; - case DATA_VOLKHAN: - return m_uiVolkhanGUID; - case DATA_IONAR: - return m_uiIonarGUID; - case DATA_LOKEN: - return m_uiLokenGUID; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H L " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'H' && dataHead2 == 'L') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_halls_of_lightning(Map* pMap) -{ - return new instance_halls_of_lightning(pMap); -} - -void AddSC_instance_halls_of_lightning() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_lightning"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_lightning; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp deleted file mode 100644 index 0674b7c79eb..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_krystallus.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* Script Data Start -SDName: Boss krystallus -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_krystallus' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_BOULDER_TOSS = 50843, - H_SPELL_BOULDER_TOSS = 59742, - SPELL_GROUND_SPIKE = 59750, - SPELL_GROUND_SLAM = 50827, - SPELL_SHATTER = 50810, - H_SPELL_SHATTER = 61546, - SPELL_STOMP = 48131, - H_SPELL_STOMP = 59744 -}; - -enum Yells -{ - SAY_AGGRO = -1599007, - SAY_KILL = -1599008, - SAY_DEATH = -1599009, - SAY_SHATTER = -1599010 -}; - -struct boss_krystallusAI : public ScriptedAI -{ - boss_krystallusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBoulderTossTimer; - uint32 uiGroundSpikeTimer; - uint32 uiGroundSlamTimer; - uint32 uiShatterTimer; - uint32 uiStompTimer; - - bool bIsSlam; - - ScriptedInstance* pInstance; - - void Reset() - { - bIsSlam = false; - - uiBoulderTossTimer = 3000 + rand()%6000; - uiGroundSpikeTimer = 9000 + rand()%5000; - uiGroundSlamTimer = 15000 + rand()%3000; - uiStompTimer = 20000 + rand()%9000; - uiShatterTimer = 0; - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, NOT_STARTED); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBoulderTossTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BOULDER_TOSS); - uiBoulderTossTimer = 9000 + rand()%6000; - } else uiBoulderTossTimer -= diff; - - if (uiGroundSpikeTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_GROUND_SPIKE); - uiGroundSpikeTimer = 12000 + rand()%5000; - } else uiGroundSpikeTimer -= diff; - - if (uiStompTimer <= diff) - { - DoCast(me, SPELL_STOMP); - uiStompTimer = 20000 + rand()%9000; - } else uiStompTimer -= diff; - - if (uiGroundSlamTimer <= diff) - { - DoCast(me, SPELL_GROUND_SLAM); - bIsSlam = true; - uiShatterTimer = 10000; - uiGroundSlamTimer = 15000 + rand()%3000; - } else uiGroundSlamTimer -= diff; - - if (bIsSlam) - { - if (uiShatterTimer <= diff) - { - DoCast(me, SPELL_SHATTER); - bIsSlam = false; - } else uiShatterTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(SAY_KILL, me); - } -}; - -CreatureAI* GetAI_boss_krystallus(Creature* pCreature) -{ - return new boss_krystallusAI (pCreature); -} - -void AddSC_boss_krystallus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_krystallus"; - newscript->GetAI = &GetAI_boss_krystallus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp deleted file mode 100644 index b3c3c675347..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* Script Data Start -SDName: Boss maiden_of_grief -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_maiden_of_grief' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_PARTING_SORROW = 59723, - SPELL_STORM_OF_GRIEF_N = 50752, - SPELL_STORM_OF_GRIEF_H = 59772, - SPELL_SHOCK_OF_SORROW_N = 50760, - SPELL_SHOCK_OF_SORROW_H = 59726, - SPELL_PILLAR_OF_WOE_N = 50761, - SPELL_PILLAR_OF_WOE_H = 59727 -}; - -enum Yells -{ - SAY_AGGRO = -1599000, - SAY_SLAY_1 = -1599001, - SAY_SLAY_2 = -1599002, - SAY_SLAY_3 = -1599003, - SAY_SLAY_4 = -1599004, - SAY_DEATH = -1599005, - SAY_STUN = -1599006 -}; - -enum Achievements -{ - ACHIEV_GOOD_GRIEF_START_EVENT = 20383, -}; - -struct boss_maiden_of_griefAI : public ScriptedAI -{ - boss_maiden_of_griefAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 PartingSorrowTimer; - uint32 StormOfGriefTimer; - uint32 ShockOfSorrowTimer; - uint32 PillarOfWoeTimer; - - void Reset() - { - PartingSorrowTimer = 25000 + rand()%5000; - StormOfGriefTimer = 10000; - ShockOfSorrowTimer = 20000+rand()%5000; - PillarOfWoeTimer = 5000 + rand()%10000; - - if (pInstance) - { - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAIDEN_DOOR))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, IN_PROGRESS); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (IsHeroic()) - { - if (PartingSorrowTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget) - DoCast(pTarget, SPELL_PARTING_SORROW); - - PartingSorrowTimer = 30000 + rand()%10000; - } else PartingSorrowTimer -= diff; - } - - if (StormOfGriefTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STORM_OF_GRIEF_N, true); - StormOfGriefTimer = 15000 + rand()%5000; - } else StormOfGriefTimer -= diff; - - if (ShockOfSorrowTimer <= diff) - { - DoResetThreat(); - DoScriptText(SAY_STUN, me); - DoCast(me, SPELL_SHOCK_OF_SORROW_N); - ShockOfSorrowTimer = 20000 + rand()%10000; - } else ShockOfSorrowTimer -= diff; - - if (PillarOfWoeTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - - if (pTarget) - DoCast(pTarget, SPELL_PILLAR_OF_WOE_N); - else - DoCast(me->getVictim(), SPELL_PILLAR_OF_WOE_N); - - PillarOfWoeTimer = 5000 + rand()%20000; - } else PillarOfWoeTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } -}; - -CreatureAI* GetAI_boss_maiden_of_grief(Creature* pCreature) -{ - return new boss_maiden_of_griefAI (pCreature); -} - -void AddSC_boss_maiden_of_grief() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_maiden_of_grief"; - newscript->GetAI = &GetAI_boss_maiden_of_grief; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp deleted file mode 100644 index 68c3e34e6bf..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_stone/boss_sjonnir.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* Script Data Start -SDName: Boss sjonnir -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_sjonnir' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_LIGHTING_RING = 51849, //Periodic Trigger (interval 2s) spell = 50841 - H_SPELL_LIGHTING_RING = 59861, //Periodic Trigger (interval 2s) spell = 59849 - SPELL_LIGHTING_RING_1 = 50840, //Periodic Trigger (interval 2s) spell = 50841 - H_SPELL_LIGHTING_RING_1 = 59848, //Periodic Trigger (interval 2s) spell = 59849 - SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835 - H_SPELL_STATIC_CHARGE = 59846, //Periodic Trigger 2s interval, spell =50847 - SPELL_CHAIN_LIGHTING = 50830, - H_SPELL_CHAIN_LIGHTING = 59844, - SPELL_LIGHTING_SHIELD = 50831, - H_SPELL_LIGHTING_SHIELD = 59845, - SPELL_FRENZY = 28747 -}; - -enum Yells -{ - SAY_AGGRO = -1599011, - SAY_SLAY_1 = -1599012, - SAY_SLAY_2 = -1599013, - SAY_SLAY_3 = -1599014, - SAY_DEATH = -1599015 -}; - -#define EMOTE_GENERIC_FRENZY -1000002 - -enum SjonnirCreatures -{ - CREATURE_FORGED_IRON_TROGG = 27979, - CREATURE_MALFORMED_OOZE = 27981, - CREATURE_FORGED_IRON_DWARF = 27982, - CREATURE_IRON_SLUDGE = 28165 -}; - -enum Misc -{ - DATA_TIME_BEFORE_OOZE = 150000, //2min 30 secs - ACHIEV_ABUSE_THE_OOZE = 2155 -}; - -struct Locations -{ - float x, y, z; -}; - -static Locations PipeLocations[] = -{ - {1295.44, 734.07, 200.3}, //left - {1297.7, 595.6, 199.9} //right -}; - -static Locations CenterPoint = {1295.21, 667.157, 189.691}; - -struct boss_sjonnirAI : public ScriptedAI -{ - boss_sjonnirAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - bool bIsFrenzy; - - uint32 uiChainLightningTimer; - uint32 uiLightningShieldTimer; - uint32 uiStaticChargeTimer; - uint32 uiLightningRingTimer; - uint32 uiSummonTimer; - uint32 uiFrenzyTimer; - uint32 uiEncounterTimer; - uint32 uiKilledIronSludges; - - SummonList lSummons; - - ScriptedInstance* pInstance; - - void Reset() - { - bIsFrenzy = false; - - uiEncounterTimer = 0; - uiChainLightningTimer = 3000 + rand()%5000; - uiLightningShieldTimer = 20000 + rand()%5000; - uiStaticChargeTimer = 20000 + rand()%5000; - uiLightningRingTimer = 30000 + rand()%5000; - uiSummonTimer = 5000; - uiFrenzyTimer = 300000; //5 minutes - uiKilledIronSludges = 0; - - lSummons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_SJONNIR_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - uiEncounterTimer = 0; - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SJONNIR_DOOR))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - pInstance->SetData(DATA_SJONNIR_EVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiChainLightningTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CHAIN_LIGHTING); - uiChainLightningTimer = 10000 + rand()%5000; - } else uiChainLightningTimer -= diff; - - if (uiLightningShieldTimer <= diff) - { - DoCast(me, SPELL_LIGHTING_SHIELD); - uiLightningShieldTimer -= diff; - } - - if (uiStaticChargeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STATIC_CHARGE); - uiStaticChargeTimer = 20000 + rand()%5000; - } uiStaticChargeTimer -= diff; - - if (uiLightningRingTimer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_LIGHTING_RING); - uiLightningRingTimer = 30000 + rand()%5000; - } else uiLightningRingTimer -= diff; - - if (uiSummonTimer <= diff) - { - uint32 uiSummonPipe = rand()%2; - me->SummonCreature(uiEncounterTimer > DATA_TIME_BEFORE_OOZE ? CREATURE_MALFORMED_OOZE : - RAND(CREATURE_FORGED_IRON_DWARF,CREATURE_FORGED_IRON_TROGG), - PipeLocations[uiSummonPipe].x, PipeLocations[uiSummonPipe].y, PipeLocations[uiSummonPipe].z, 0.0f, - TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - uiSummonTimer = 20000; - } else uiSummonTimer -= diff; - - if (!bIsFrenzy) - { - if (uiFrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - bIsFrenzy = true; - } - else uiFrenzyTimer -= diff; - } - - uiEncounterTimer +=diff; - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* summon) - { - summon->GetMotionMaster()->MovePoint(0, CenterPoint.x, CenterPoint.y, CenterPoint.z); - /*if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - summon->AI()->AttackStart(pTarget);*/ - lSummons.Summon(summon); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - lSummons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_SJONNIR_EVENT, DONE); - if (IsHeroic() && uiKilledIronSludges > 4) - pInstance->DoCompleteAchievement(ACHIEV_ABUSE_THE_OOZE); - } - } - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void KilledIronSludge() - { - ++uiKilledIronSludges; - } -}; - -CreatureAI* GetAI_boss_sjonnir(Creature* pCreature) -{ - return new boss_sjonnirAI (pCreature); -} - -struct mob_malformed_oozeAI : public ScriptedAI -{ - mob_malformed_oozeAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiMergeTimer; - - void Reset() - { - uiMergeTimer = 10000; - } - - void UpdateAI(const uint32 diff) - { - if (uiMergeTimer <= diff) - { - if (Creature* pTemp = me->FindNearestCreature(CREATURE_MALFORMED_OOZE, 3.0f, true)) - { - DoSpawnCreature(CREATURE_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); - pTemp->DisappearAndDie(); - me->DisappearAndDie(); - } - uiMergeTimer = 3000; - } else uiMergeTimer -= diff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_malformed_ooze(Creature* pCreature) -{ - return new mob_malformed_oozeAI(pCreature); -} - -struct mob_iron_sludgeAI : public ScriptedAI -{ - mob_iron_sludgeAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - if (Creature* pSjonnir = Unit::GetCreature(*me, pInstance->GetData64(DATA_SJONNIR))) - CAST_AI(boss_sjonnirAI, pSjonnir->AI())->KilledIronSludge(); - } -}; - -CreatureAI* GetAI_mob_iron_sludge(Creature* pCreature) -{ - return new mob_iron_sludgeAI(pCreature); -} - -void AddSC_boss_sjonnir() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sjonnir"; - newscript->GetAI = &GetAI_boss_sjonnir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_malformed_ooze"; - newscript->GetAI = &GetAI_mob_malformed_ooze; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_iron_sludge"; - newscript->GetAI = &GetAI_mob_iron_sludge; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp deleted file mode 100644 index 8febdaab879..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.cpp +++ /dev/null @@ -1,724 +0,0 @@ -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "halls_of_stone.h" - -enum Texts -{ - SAY_KILL_1 = -1599016, - SAY_KILL_2 = -1599017, - SAY_KILL_3 = -1599018, - SAY_LOW_HEALTH = -1599019, - SAY_DEATH = -1599020, - SAY_PLAYER_DEATH_1 = -1599021, - SAY_PLAYER_DEATH_2 = -1599022, - SAY_PLAYER_DEATH_3 = -1599023, - SAY_ESCORT_START = -1599024, - - SAY_SPAWN_DWARF = -1599025, - SAY_SPAWN_TROGG = -1599026, - SAY_SPAWN_OOZE = -1599027, - SAY_SPAWN_EARTHEN = -1599028, - - SAY_EVENT_INTRO_1 = -1599029, - SAY_EVENT_INTRO_2 = -1599030, - SAY_EVENT_INTRO_3_ABED = -1599031, - - SAY_EVENT_A_1 = -1599032, - SAY_EVENT_A_2_KADD = -1599033, - SAY_EVENT_A_3 = -1599034, - - SAY_EVENT_B_1 = -1599035, - SAY_EVENT_B_2_MARN = -1599036, - SAY_EVENT_B_3 = -1599037, - - SAY_EVENT_C_1 = -1599038, - SAY_EVENT_C_2_ABED = -1599039, - SAY_EVENT_C_3 = -1599040, - - SAY_EVENT_D_1 = -1599041, - SAY_EVENT_D_2_ABED = -1599042, - SAY_EVENT_D_3 = -1599043, - SAY_EVENT_D_4_ABED = -1599044, - - SAY_EVENT_END_01 = -1599045, - SAY_EVENT_END_02 = -1599046, - SAY_EVENT_END_03_ABED = -1599047, - SAY_EVENT_END_04 = -1599048, - SAY_EVENT_END_05_ABED = -1599049, - SAY_EVENT_END_06 = -1599050, - SAY_EVENT_END_07_ABED = -1599051, - SAY_EVENT_END_08 = -1599052, - SAY_EVENT_END_09_KADD = -1599053, - SAY_EVENT_END_10 = -1599054, - SAY_EVENT_END_11_KADD = -1599055, - SAY_EVENT_END_12 = -1599056, - SAY_EVENT_END_13_KADD = -1599057, - SAY_EVENT_END_14 = -1599058, - SAY_EVENT_END_15_MARN = -1599059, - SAY_EVENT_END_16 = -1599060, - SAY_EVENT_END_17_MARN = -1599061, - SAY_EVENT_END_18 = -1599062, - SAY_EVENT_END_19_MARN = -1599063, - SAY_EVENT_END_20 = -1599064, - SAY_EVENT_END_21_ABED = -1599065, - - SAY_VICTORY_SJONNIR_1 = -1599066, - SAY_VICTORY_SJONNIR_2 = -1599067, - - SAY_ENTRANCE_MEET = -1599068, - - TEXT_ID_START = 13100, - TEXT_ID_PROGRESS = 13101 -}; - -enum BrannCreatures -{ - CREATURE_TRIBUNAL_OF_THE_AGES = 28234, - CREATURE_BRANN_BRONZEBEARD = 28070, - CREATURE_DARK_MATTER_TARGET = 28237, - CREATURE_SEARING_GAZE_TARGET = 28265, - CREATURE_DARK_RUNE_PROTECTOR = 27983, - CREATURE_DARK_RUNE_STORMCALLER = 27984, - CREATURE_IRON_GOLEM_CUSTODIAN = 27985, -}; - -enum Spells -{ - SPELL_STEALTH = 58506, - //Kadrak - SPELL_GLARE_OF_THE_TRIBUNAL = 50988, - H_SPELL_GLARE_OF_THE_TRIBUNAL = 59868, - //Marnak - SPELL_DARK_MATTER = 51012, - H_SPELL_DARK_MATTER = 59868, - //Abedneum - SPELL_SEARING_GAZE = 51136, - H_SPELL_SEARING_GAZE = 59867 -}; - -enum Quests -{ - QUEST_HALLS_OF_STONE = 13207 -}; - -enum Achievements -{ - ACHIEV_BRANN_SPANKIN_NEW = 2154 -}; - -#define GOSSIP_ITEM_START "Brann, it would be our honor!" -#define GOSSIP_ITEM_PROGRESS "Let's move Brann, enough of the history lessons!" - -static Position SpawnLocations[]= -{ - {946.992, 397.016, 208.374}, - {960.748, 382.944, 208.374}, -}; - -struct mob_tribuna_controllerAI : public ScriptedAI -{ - mob_tribuna_controllerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - SetCombatMovement(false); - } - - ScriptedInstance* pInstance; - - uint32 uiKaddrakEncounterTimer; - uint32 uiMarnakEncounterTimer; - uint32 uiAbedneumEncounterTimer; - - bool bKaddrakActivated; - bool bMarnakActivated; - bool bAbedneumActivated; - - std::list KaddrakGUIDList; - - void Reset() - { - uiKaddrakEncounterTimer = 1500; - uiMarnakEncounterTimer = 10000; - uiAbedneumEncounterTimer = 10000; - - bKaddrakActivated = false; - bMarnakActivated = false; - bAbedneumActivated = false; - - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); - } - - KaddrakGUIDList.clear(); - } - - void UpdateFacesList() - { - /*GetCreatureListWithEntryInGrid(lKaddrakGUIDList, me, CREATURE_KADDRAK, 50.0f); - if (!lKaddrakGUIDList.empty()) - { - uint32 uiPositionCounter = 0; - for (std::list::const_iterator itr = lKaddrakGUIDList.begin(); itr != lKaddrakGUIDList.end(); ++itr) - { - if ((*itr)->isAlive()) - { - if (uiPositionCounter == 0) - { - (*itr)->GetMap()->CreatureRelocation((*itr), 927.265, 333.200, 218.780, (*itr)->GetOrientation()); - (*itr)->SendMonsterMove(927.265, 333.200, 218.780, 0, (*itr)->GetMovementFlags(), 1); - } - else - { - (*itr)->GetMap()->CreatureRelocation((*itr), 921.745, 328.076, 218.780, (*itr)->GetOrientation()); - (*itr)->SendMonsterMove(921.745, 328.076, 218.780, 0, (*itr)->GetMovementFlags(), 1); - } - } - ++uiPositionCounter; - } - }*/ - } - - void UpdateAI(const uint32 diff) - { - if (bKaddrakActivated) - { - if (uiKaddrakEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (!KaddrakGUIDList.empty()) - for (std::list::const_iterator itr = KaddrakGUIDList.begin(); itr != KaddrakGUIDList.end(); ++itr) - { - if (Creature *pKaddrak = Unit::GetCreature(*me, *itr)) - { - if (pKaddrak->isAlive()) - pKaddrak->CastSpell(pTarget, DUNGEON_MODE(SPELL_GLARE_OF_THE_TRIBUNAL, H_SPELL_GLARE_OF_THE_TRIBUNAL), true); - } - } - uiKaddrakEncounterTimer = 1500; - } else uiKaddrakEncounterTimer -= diff; - } - if (bMarnakActivated) - { - if (uiMarnakEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature* pSummon = me->SummonCreature(CREATURE_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) - { - pSummon->SetDisplayId(11686); - pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_DARK_MATTER, H_SPELL_DARK_MATTER), true); - } - } - uiMarnakEncounterTimer = 30000 + rand()%1000; - } else uiMarnakEncounterTimer -= diff; - } - if (bAbedneumActivated) - { - if (uiAbedneumEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature* pSummon = me->SummonCreature(CREATURE_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) - { - pSummon->SetDisplayId(11686); - pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_SEARING_GAZE, H_SPELL_SEARING_GAZE), true); - } - } - uiAbedneumEncounterTimer = 30000 + rand()%1000; - } else uiAbedneumEncounterTimer -= diff; - } - } -}; - -struct npc_brann_hosAI : public npc_escortAI -{ - npc_brann_hosAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiStep; - uint32 uiPhaseTimer; - - uint64 uiControllerGUID; - std::list lDwarfGUIDList; - - ScriptedInstance* pInstance; - - bool bIsBattle; - bool bIsLowHP; - bool bHasBeenDamaged; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - bIsLowHP = false; - bIsBattle = false; - bHasBeenDamaged = false; - uiStep = 0; - uiPhaseTimer = 0; - uiControllerGUID = 0; - - DespawnDwarf(); - - if (pInstance) - pInstance->SetData(DATA_BRANN_EVENT, NOT_STARTED); - } - } - - void DespawnDwarf() - { - if (lDwarfGUIDList.empty()) - return; - for (std::list::const_iterator itr = lDwarfGUIDList.begin(); itr != lDwarfGUIDList.end(); ++itr) - { - Creature* pTemp = Unit::GetCreature(*me, pInstance ? (*itr) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->ForcedDespawn(); - } - lDwarfGUIDList.clear(); - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 7: - if (Creature* pCreature = GetClosestCreatureWithEntry(me, CREATURE_TRIBUNAL_OF_THE_AGES, 100.0f)) - { - if (!pCreature->isAlive()) - pCreature->Respawn(); - CAST_AI(mob_tribuna_controllerAI, pCreature->AI())->UpdateFacesList(); - uiControllerGUID = pCreature->GetGUID(); - } - break; - case 13: - DoScriptText(SAY_EVENT_INTRO_1, me); - SetEscortPaused(true); - JumpToNextStep(20000); - break; - case 17: - DoScriptText(SAY_EVENT_INTRO_2, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_TRIBUNAL_CONSOLE),true); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - SetEscortPaused(true); - JumpToNextStep(8500); - break; - case 18: - SetEscortPaused(true); - break; - } - } - - void SpawnDwarf(uint32 uiType) - { - switch(uiType) - { - case 1: - { - uint32 uiSpawnNumber = DUNGEON_MODE(2,3); - for (uint8 i = 0; i < uiSpawnNumber; ++i) - me->SummonCreature(CREATURE_DARK_RUNE_PROTECTOR, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - } - case 2: - for (uint8 i = 0; i < 2; ++i) - me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - case 3: - me->SummonCreature(CREATURE_IRON_GOLEM_CUSTODIAN, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - lDwarfGUIDList.push_back(pSummoned->GetGUID()); - pSummoned->AddThreat(me, 0.0f); - pSummoned->AI()->AttackStart(me); - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhaseTimer = uiTimer; - ++uiStep; - } - - void StartWP() - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetEscortPaused(false); - uiStep = 1; - Start(); - } - - void DamageTaken(Unit* /*done_by*/, uint32 & /*damage*/) - { - if (!bHasBeenDamaged) - bHasBeenDamaged = true; - } - - void UpdateEscortAI(const uint32 uiDiff) - { - if (uiPhaseTimer <= uiDiff) - { - switch(uiStep) - { - case 1: - if (pInstance) - { - if (pInstance->GetData(DATA_BRANN_EVENT) != NOT_STARTED) - return; - pInstance->SetData(DATA_BRANN_EVENT, IN_PROGRESS); - } - bIsBattle = false; - DoScriptText(SAY_ESCORT_START, me); - SetRun(true); - JumpToNextStep(0); - break; - case 3: - SetEscortPaused(false); - JumpToNextStep(0); - break; - case 5: - if (pInstance) - if (Creature* pTemp = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM)))) - DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp); - JumpToNextStep(8500); - break; - case 6: - DoScriptText(SAY_EVENT_A_1, me); - JumpToNextStep(6500); - break; - case 7: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_A_2_KADD, pTemp); - JumpToNextStep(12500); - break; - case 8: - DoScriptText(SAY_EVENT_A_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bKaddrakActivated = true; - JumpToNextStep(5000); - break; - case 9: - me->SetReactState(REACT_PASSIVE); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 10: - DoScriptText(SAY_EVENT_B_1, me); - JumpToNextStep(6000); - break; - case 11: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_B_2_MARN, pTemp); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 12: - DoScriptText(SAY_EVENT_B_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bMarnakActivated = true; - JumpToNextStep(10000); - break; - case 13: - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 14: - SpawnDwarf(2); - JumpToNextStep(20000); - break; - case 15: - DoScriptText(SAY_EVENT_C_1, me); - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 16: - SpawnDwarf(2); - JumpToNextStep(20000); - break; - case 17: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_C_2_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 18: - DoScriptText(SAY_EVENT_C_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bAbedneumActivated = true; - JumpToNextStep(5000); - break; - case 19: - SpawnDwarf(2); - JumpToNextStep(10000); - break; - case 20: - SpawnDwarf(1); - JumpToNextStep(15000); - break; - case 21: - DoScriptText(SAY_EVENT_D_1, me); - SpawnDwarf(3); - JumpToNextStep(20000); - break; - case 22: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_D_2_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(5000); - break; - case 23: - SpawnDwarf(2); - JumpToNextStep(15000); - break; - case 24: - DoScriptText(SAY_EVENT_D_3, me); - SpawnDwarf(3); - JumpToNextStep(5000); - break; - case 25: - SpawnDwarf(1); - JumpToNextStep(5000); - break; - case 26: - SpawnDwarf(2); - JumpToNextStep(10000); - break; - case 27: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_D_4_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 28: - me->SetReactState(REACT_DEFENSIVE); - DoScriptText(SAY_EVENT_END_01, me); - me->SetStandState(UNIT_STAND_STATE_STAND); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - bIsBattle = true; - SetEscortPaused(false); - JumpToNextStep(6500); - break; - case 29: - DoScriptText(SAY_EVENT_END_02, me); - if (pInstance) - { - pInstance->SetData(DATA_BRANN_EVENT, DONE); - - // Achievement criteria is with spell 59046 which does not exist. - // There is thus no way it can be given by casting the spell on the players. - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59046); - - if (!bHasBeenDamaged) - pInstance->DoCompleteAchievement(ACHIEV_BRANN_SPANKIN_NEW); - } - - JumpToNextStep(5500); - break; - case 30: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_03_ABED, pTemp); - JumpToNextStep(8500); - break; - case 31: - DoScriptText(SAY_EVENT_END_04, me); - JumpToNextStep(11500); - break; - case 32: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_05_ABED, pTemp); - JumpToNextStep(11500); - break; - case 33: - DoScriptText(SAY_EVENT_END_06, me); - JumpToNextStep(4500); - break; - case 34: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_07_ABED, pTemp); - JumpToNextStep(22500); - break; - case 35: - DoScriptText(SAY_EVENT_END_08, me); - JumpToNextStep(7500); - break; - case 36: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_09_KADD, pTemp); - JumpToNextStep(18500); - break; - case 37: - DoScriptText(SAY_EVENT_END_10, me); - JumpToNextStep(5500); - break; - case 38: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_11_KADD, pTemp); - JumpToNextStep(20500); - break; - case 39: - DoScriptText(SAY_EVENT_END_12, me); - JumpToNextStep(2500); - break; - case 40: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_13_KADD, pTemp); - JumpToNextStep(19500); - break; - case 41: - DoScriptText(SAY_EVENT_END_14, me); - JumpToNextStep(10500); - break; - case 42: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_15_MARN, pTemp); - JumpToNextStep(6500); - break; - case 43: - DoScriptText(SAY_EVENT_END_16, me); - JumpToNextStep(6500); - break; - case 44: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_17_MARN, pTemp); - JumpToNextStep(25500); - break; - case 45: - DoScriptText(SAY_EVENT_END_18, me); - JumpToNextStep(23500); - break; - case 46: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_19_MARN, pTemp); - JumpToNextStep(3500); - break; - case 47: - DoScriptText(SAY_EVENT_END_20, me); - JumpToNextStep(8500); - break; - case 48: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_21_ABED, pTemp); - JumpToNextStep(5500); - break; - case 49: - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); - } - Player* pPlayer = GetPlayerForEscort(); - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, me); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - JumpToNextStep(180000); - break; - } - case 50: - SetEscortPaused(false); - break; - } - } else uiPhaseTimer -= uiDiff; - - if (!bIsLowHP && HealthBelowPct(30)) - { - DoScriptText(SAY_LOW_HEALTH, me); - bIsLowHP = true; - } - else if (bIsLowHP && !HealthBelowPct(30)) - bIsLowHP = false; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_brann_hos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1 || uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_brann_hosAI, pCreature->AI())->StartWP(); - } - - return true; -} - -CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature) -{ - return new mob_tribuna_controllerAI(pCreature); -} - -CreatureAI* GetAI_npc_brann_hos(Creature* pCreature) -{ - return new npc_brann_hosAI(pCreature); -} - -void AddSC_halls_of_stone() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_brann_hos"; - newscript->GetAI = &GetAI_npc_brann_hos; - newscript->pGossipHello = &GossipHello_npc_brann_hos; - newscript->pGossipSelect = &GossipSelect_npc_brann_hos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tribuna_controller"; - newscript->GetAI = &GetAI_mob_tribuna_controller; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h b/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h deleted file mode 100644 index b61e7057ddc..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_stone/halls_of_stone.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef DEF_HALLS_OF_STONE_H -#define DEF_HALLS_OF_STONE_H -enum Data -{ - DATA_KRYSTALLUS_EVENT, - DATA_MAIDEN_OF_GRIEF_EVENT, - DATA_SJONNIR_EVENT, - DATA_BRANN_EVENT -}; -enum Data64 -{ - DATA_KRYSTALLUS, - DATA_MAIDEN_OF_GRIEF, - DATA_SJONNIR, - DATA_KADDRAK, - DATA_MARNAK, - DATA_ABEDNEUM, - DATA_GO_TRIBUNAL_CONSOLE, - DATA_GO_KADDRAK, - DATA_GO_MARNAK, - DATA_GO_ABEDNEUM, - DATA_GO_SKY_FLOOR, - DATA_SJONNIR_DOOR, - DATA_MAIDEN_DOOR -}; -enum Creatures -{ - CREATURE_MAIDEN = 27975, - CREATURE_KRYSTALLUS = 27977, - CREATURE_SJONNIR = 27978, - CREATURE_MARNAK = 30897, - CREATURE_KADDRAK = 30898, - CREATURE_ABEDNEUM = 30899, - CREATURE_BRANN = 28070 -}; -enum GameObjects -{ - GO_ABEDNEUM = 191669, - GO_MARNAK = 192170, - GO_KADDRAK = 192171, - GO_MAIDEN_DOOR = 191292, - GO_BRANN_DOOR = 191295, - GO_SJONNIR_DOOR = 191296, - GO_TRIBUNAL_CONSOLE = 193907, - GO_TRIBUNAL_CHEST = 190586, - GO_TRIBUNAL_CHEST_HERO = 193996 -}; -#endif diff --git a/src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp deleted file mode 100644 index 69bb3779e70..00000000000 --- a/src/server/scripts/Northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -#define MAX_ENCOUNTER 4 - -/* Halls of Stone encounters: -0- Krystallus -1- Maiden of Grief -2- Escort Event -3- Sjonnir The Ironshaper -*/ - -struct instance_halls_of_stone : public ScriptedInstance -{ - instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiMaidenOfGrief; - uint64 uiKrystallus; - uint64 uiSjonnir; - - uint64 uiKaddrak; - uint64 uiAbedneum; - uint64 uiMarnak; - uint64 uiBrann; - - uint64 uiMaidenOfGriefDoor; - uint64 uiSjonnirDoor; - uint64 uiBrannDoor; - uint64 uiTribunalConsole; - uint64 uiTribunalChest; - uint64 uiTribunalSkyFloor; - uint64 uiKaddrakGo; - uint64 uiAbedneumGo; - uint64 uiMarnakGo; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() - { - uiMaidenOfGrief = 0; - uiKrystallus = 0; - uiSjonnir = 0; - - uiKaddrak = 0; - uiMarnak = 0; - uiAbedneum = 0; - uiBrann = 0; - - uiMaidenOfGriefDoor = 0; - uiSjonnirDoor = 0; - uiBrannDoor = 0; - uiKaddrakGo = 0; - uiMarnakGo = 0; - uiAbedneumGo = 0; - uiTribunalConsole = 0; - uiTribunalChest = 0; - uiTribunalSkyFloor = 0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i] = NOT_STARTED; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case CREATURE_MAIDEN: uiMaidenOfGrief = pCreature->GetGUID(); break; - case CREATURE_KRYSTALLUS: uiKrystallus = pCreature->GetGUID(); break; - case CREATURE_SJONNIR: uiSjonnir = pCreature->GetGUID(); break; - case CREATURE_MARNAK: uiMarnak = pCreature->GetGUID(); break; - case CREATURE_KADDRAK: uiKaddrak = pCreature->GetGUID(); break; - case CREATURE_ABEDNEUM: uiAbedneum = pCreature->GetGUID(); break; - case CREATURE_BRANN: uiBrann = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_ABEDNEUM: - uiAbedneumGo = pGo->GetGUID(); - break; - case GO_MARNAK: - uiMarnakGo = pGo->GetGUID(); - break; - case GO_KADDRAK: - uiKaddrakGo = pGo->GetGUID(); - break; - case GO_MAIDEN_DOOR: - uiMaidenOfGriefDoor = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_BRANN_DOOR: - uiBrannDoor = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_SJONNIR_DOOR: - uiSjonnirDoor = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_TRIBUNAL_CONSOLE: - uiTribunalConsole = pGo->GetGUID(); - break; - case GO_TRIBUNAL_CHEST: - case GO_TRIBUNAL_CHEST_HERO: - uiTribunalChest = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - case 191527: - uiTribunalSkyFloor = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MAIDEN_OF_GRIEF_EVENT: - m_auiEncounter[1] = data; - if (m_auiEncounter[1] == DONE) - HandleGameObject(uiBrannDoor,true); - break; - case DATA_KRYSTALLUS_EVENT: - m_auiEncounter[0] = data; - if (m_auiEncounter[0] == DONE) - HandleGameObject(uiMaidenOfGriefDoor,true); - break; - case DATA_SJONNIR_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_BRANN_EVENT: - m_auiEncounter[2] = data; - if (m_auiEncounter[2] == DONE) - { - HandleGameObject(uiSjonnirDoor,true); - GameObject *pGo = instance->GetGameObject(uiTribunalChest); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - } - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_KRYSTALLUS_EVENT: return m_auiEncounter[0]; - case DATA_MAIDEN_OF_GRIEF_EVENT: return m_auiEncounter[1]; - case DATA_SJONNIR_EVENT: return m_auiEncounter[2]; - case DATA_BRANN_EVENT: return m_auiEncounter[3]; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_MAIDEN_OF_GRIEF: return uiMaidenOfGrief; - case DATA_KRYSTALLUS: return uiKrystallus; - case DATA_SJONNIR: return uiSjonnir; - case DATA_KADDRAK: return uiKaddrak; - case DATA_MARNAK: return uiMarnak; - case DATA_ABEDNEUM: return uiAbedneum; - case DATA_GO_TRIBUNAL_CONSOLE: return uiTribunalConsole; - case DATA_GO_KADDRAK: return uiKaddrakGo; - case DATA_GO_ABEDNEUM: return uiAbedneumGo; - case DATA_GO_MARNAK: return uiMarnakGo; - case DATA_GO_SKY_FLOOR: return uiTribunalSkyFloor; - case DATA_SJONNIR_DOOR: return uiSjonnirDoor; - case DATA_MAIDEN_DOOR: return uiMaidenOfGriefDoor; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'H' && dataHead2 == 'S') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_halls_of_stone(Map* pMap) -{ - return new instance_halls_of_stone(pMap); -} - -void AddSC_instance_halls_of_stone() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_stone"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_stone; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp deleted file mode 100644 index e944543fb9e..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_algalon.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -#define GAMEOBJECT_GIVE_OF_THE_OBSERVER 194821 - -enum Spells -{ - SPELL_ASCEND = 64487, - SPELL_BERSERK = 47008, - SPELL_BIG_BANG = 64443, - H_SPELL_BIG_BANG = 64584, - SPELL_COSMIC_SMASH = 62301, - H_SPELL_COSMIC_SMASH = 64598, - SPELL_PHASE_PUNCH = 64412, - SPELL_QUANTUM_STRIKE = 64395, - H_SPELL_QUANTUM_STRIKE = 64592, - SPELL_BLACK_HOLE_EXPLOSION = 64122, - SPELL_ARCANE_BARAGE = 64599, - H_SPELL_ARCANE_BARAGE = 64607 -}; - -enum Creatures -{ - CREATURE_COLLAPSING_STAR = 32955, - CREATURE_BLACK_HOLE = 32953, - CREATURE_LIVING_CONSTELLATION = 33052, - CREATURE_DARK_MATTER = 33089 -}; - -#define NORDRASSIL_X 1614.288574 -#define NORDRASSIL_Y -320.713287 -#define NORDRASSIL_Z 417.321167 -#define NORDRASSIL_X 1614.276245 -#define NORDRASSIL_Y -287.016632 -#define NORDRASSIL_Z 417.321106 -#define NORDRASSIL_X 1650.428467 -#define NORDRASSIL_Y -292.331390 -#define NORDRASSIL_Z 417.321167 -#define NORDRASSIL_X 1649.501831 -#define NORDRASSIL_Y -324.609222 -#define NORDRASSIL_Z 417.322174 - -enum Yells -{ - SAY_AGGRO = -1603000, - SAY_SLAY_1 = -1603001, - SAY_SLAY_2 = -1603002, - SAY_ENGADED_FOR_FIRTS_TIME = -1603003, - SAY_PHASE_2 = -1603004, - SAY_SUMMON_COLLAPSING_STAR = -1603005, - SAY_DEATH_1 = -1603006, - SAY_DEATH_2 = -1603007, - SAY_DEATH_3 = -1603008, - SAY_DEATH_4 = -1603009, - SAY_DEATH_5 = -1603010, - SAY_BERSERK = -1603011, - SAY_BIG_BANG_1 = -1603012, - SAY_BIG_BANG_2 = -1603013, - SAY_TIMER_1 = -1603014, - SAY_TIMER_2 = -1603015, - SAY_TIMER_3 = -1603016, - SAY_SUMMON_1 = -1603017, - SAY_SUMMON_2 = -1603018, - SAY_SUMMON_3 = -1603019, -}; - -struct boss_algalonAI : public ScriptedAI -{ - boss_algalonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Summon = false; // not in reset. intro speech done only once. - } - - ScriptedInstance* pInstance; - - std::list m_lCollapsingStarGUIDList; - - uint32 Phase; - uint32 Ascend_Timer; - uint32 Berserk_Timer; - uint32 BigBang_Timer; - uint32 CosmicSmash_Timer; - uint32 PhasePunch_Timer; - uint32 QuantumStrike_Timer; - uint32 CollapsingStar_Timer; - uint32 uiPhase_timer; - uint32 uiStep; - - uint64 BlackHoleGUID; - - bool Enrage; - bool Summon; - - void EnterCombat(Unit* who) - { - if (Summon) - { - DoScriptText(SAY_AGGRO, me); - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - DoZoneInCombat(who->ToCreature()); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - uiStep = 1; - } - - if (pInstance) - pInstance->SetData(TYPE_ALGALON, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void Reset() - { - Phase = 1; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pInstance) - pInstance->SetData(TYPE_ALGALON, NOT_STARTED); - - BlackHoleGUID = 0; - - uiPhase_timer = 0; - Ascend_Timer = 480000; //8 minutes - QuantumStrike_Timer = 4000 + rand()%10000; - Berserk_Timer = 360000; //6 minutes - CollapsingStar_Timer = urand(15000, 20000); //Spawns between 15 to 20 seconds - BigBang_Timer = 90000; - PhasePunch_Timer = 8000; - CosmicSmash_Timer = urand(30000, 60000); - Enrage = false; - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhase_timer = uiTimer; - ++uiStep; - } - - void DespawnCollapsingStar() - { - if (m_lCollapsingStarGUIDList.empty()) - return; - - for (std::list::const_iterator itr = m_lCollapsingStarGUIDList.begin(); itr != m_lCollapsingStarGUIDList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - if (pTemp->isAlive()) - pTemp->ForcedDespawn(); - } - } - m_lCollapsingStarGUIDList.clear(); - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == CREATURE_COLLAPSING_STAR) - { - Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (me->getVictim()) - pSummoned->AI()->AttackStart(pTarget ? pTarget : me->getVictim()); - m_lCollapsingStarGUIDList.push_back(pSummoned->GetGUID()); - } - } - - void SummonCollapsingStar(Unit* target) - { - DoScriptText(SAY_SUMMON_COLLAPSING_STAR, me); - me->SummonCreature(CREATURE_COLLAPSING_STAR,target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN, 100000); - me->SummonCreature(CREATURE_BLACK_HOLE,target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN, 27000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Phase == 1 && HealthBelowPct(20)) - { - Phase = 2; - DoScriptText(SAY_PHASE_2, me); - } - - if (HealthBelowPct(2)) - { - me->SummonGameObject(GAMEOBJECT_GIVE_OF_THE_OBSERVER, 1634.258667, -295.101166,417.321381,0,0,0,0,0,0); - - // All of them. or random? - DoScriptText(SAY_DEATH_1, me); - DoScriptText(SAY_DEATH_2, me); - DoScriptText(SAY_DEATH_3, me); - DoScriptText(SAY_DEATH_4, me); - DoScriptText(SAY_DEATH_5, me); - - me->DisappearAndDie(); - - if (pInstance) - pInstance->SetData(TYPE_ALGALON, DONE); - - return; - } - - if (Phase == 1) - { - if (!Summon) - { - if (uiPhase_timer <= diff) - { - switch(uiStep) - { - case 1: - DoScriptText(SAY_SUMMON_1, me); - JumpToNextStep(3000); - break; - case 2: - DoScriptText(SAY_SUMMON_2, me); - JumpToNextStep(3000); - break; - case 3: - DoScriptText(SAY_SUMMON_3, me); - JumpToNextStep(3000); - break; - case 4: - DoScriptText(SAY_ENGADED_FOR_FIRTS_TIME, me); - JumpToNextStep(3000); - break; - case 5: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - Summon = true; - break; - } - } else uiPhase_timer -= diff; - - return; - } - - if (QuantumStrike_Timer <= diff) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_QUANTUM_STRIKE,H_SPELL_QUANTUM_STRIKE), true); - - QuantumStrike_Timer = urand(4000, 14000); - } else QuantumStrike_Timer -= diff; - - if (BigBang_Timer <= diff) - { - DoScriptText(RAND(SAY_BIG_BANG_1,SAY_BIG_BANG_2), me); - DoCast(me->getVictim(), RAID_MODE(SPELL_BIG_BANG,H_SPELL_BIG_BANG), true); - - BigBang_Timer = 90000; - } else BigBang_Timer -= diff; - - if (Ascend_Timer <= diff) - { - DoCast(me->getVictim(),SPELL_ASCEND, true); - - Ascend_Timer = 480000; - } else Ascend_Timer -= diff; - - if (PhasePunch_Timer <= diff) - { - DoCast(me->getVictim(),SPELL_PHASE_PUNCH, true); - - PhasePunch_Timer = 8000; - } else PhasePunch_Timer -= diff; - - if (CosmicSmash_Timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), RAID_MODE(SPELL_COSMIC_SMASH,H_SPELL_COSMIC_SMASH), true); - - CosmicSmash_Timer = urand(30000, 60000); - } else CosmicSmash_Timer -= diff; - - if (Berserk_Timer <= diff) - { - DoScriptText(SAY_BERSERK, me); - DoCast(me->getVictim(),SPELL_BERSERK, true); - - Berserk_Timer = 360000; - } else Berserk_Timer -= diff; - - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } - - if (Phase == 2) - { - if (Enrage) - { - if (Ascend_Timer <= diff) - { - DoCast(me, SPELL_ASCEND); - DoScriptText(SAY_BERSERK, me); - Ascend_Timer = urand(360000,365000); - Enrage = false; - } else Ascend_Timer -= diff; - } - } - - DoMeleeAttackIfReady(); - } -}; - -//Collapsing Star -struct mob_collapsing_starAI : public ScriptedAI -{ - mob_collapsing_starAI(Creature *pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 BlackHoleExplosion_Timer; - - void Reset() - { - BlackHoleExplosion_Timer = 0; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BlackHoleExplosion_Timer <= diff) - { - me->CastSpell(me, SPELL_BLACK_HOLE_EXPLOSION, false); - BlackHoleExplosion_Timer = 0; - } else BlackHoleExplosion_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_algalon(Creature* pCreature) -{ - return new boss_algalonAI(pCreature); -} - -CreatureAI* GetAI_mob_collapsing_star(Creature* pCreature) -{ - return new mob_collapsing_starAI(pCreature); -} - -void AddSC_boss_Algalon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_algalon"; - newscript->GetAI = &GetAI_boss_algalon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_collapsing_star"; - newscript->GetAI = &GetAI_mob_collapsing_star; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp deleted file mode 100644 index 8d3ae4d3431..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_assembly_of_iron.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Assembly of Iron encounter -SD%Complete: 60% -SDComment: Runes need DB support, chain lightning won't cast, supercharge won't cast (pTarget error?) - it worked before during debugging. -SDCategory: Ulduar - Ulduar -EndScriptData */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -// Any boss -#define SPELL_SUPERCHARGE 61920 -#define SPELL_BERSERK 47008 // Hard enrage, don't know the correct ID. - -// Steelbreaker -#define SPELL_HIGH_VOLTAGE 61890 -#define SPELL_HIGH_VOLTAGE_H 63498 -#define SPELL_FUSION_PUNCH 61903 -#define SPELL_FUSION_PUNCH_H 63493 -#define SPELL_STATIC_DISRUPTION 44008 -#define SPELL_STATIC_DISRUPTION_H 63494 -#define SPELL_OVERWHELMING_POWER_H 61888 -#define SPELL_OVERWHELMING_POWER 64637 -#define SPELL_ELECTRICAL_CHARGE 61902 - -// Runemaster Molgeim -#define SPELL_SHIELD_OF_RUNES 62274 -#define SPELL_SHIELD_OF_RUNES_H 63489 -#define SPELL_RUNE_OF_POWER 64320 -#define SPELL_RUNE_OF_DEATH 62269 -#define SPELL_RUNE_OF_SUMMONING 62273 -#define SPELL_LIGHTNING_BLAST 62054 -#define SPELL_LIGHTNING_BLAST_H 63491 -#define CREATURE_RUNE_OF_SUMMONING 33051 - -// Stormcaller Brundir -#define SPELL_CHAIN_LIGHTNING_N 61879 -#define SPELL_CHAIN_LIGHTNING_H 63479 -#define SPELL_OVERLOAD 61869 -#define SPELL_OVERLOAD_H 63481 -#define SPELL_LIGHTNING_WHIRL 61915 -#define SPELL_LIGHTNING_WHIRL_H 63483 -#define SPELL_LIGHTNING_TENDRILS 61887 -#define SPELL_LIGHTNING_TENDRILS_H 63486 -#define SPELL_STORMSHIELD 64187 - -enum Events -{ - EVENT_NONE, - EVENT_ENRAGE, - // Steelbreaker - EVENT_FUSION_PUNCH, - EVENT_STATIC_DISRUPTION, - EVENT_OVERWHELMING_POWER, - // Molgeim - EVENT_RUNE_OF_POWER, - EVENT_SHIELD_OF_RUNES, - EVENT_RUNE_OF_DEATH, - EVENT_RUNE_OF_SUMMONING, - EVENT_LIGHTNING_BLAST, - // Brundir - EVENT_CHAIN_LIGHTNING, - EVENT_OVERLOAD, - EVENT_LIGHTNING_WHIRL, - EVENT_LIGHTNING_TENDRILS, - EVENT_STORMSHIELD, -}; - -enum Yells -{ - SAY_STEELBREAKER_AGGRO = -1603020, - SAY_STEELBREAKER_SLAY_1 = -1603021, - SAY_STEELBREAKER_SLAY_2 = -1603022, - SAY_STEELBREAKER_POWER = -1603023, - SAY_STEELBREAKER_DEATH_1 = -1603024, - SAY_STEELBREAKER_DEATH_2 = -1603025, - SAY_STEELBREAKER_BERSERK = -1603026, - - SAY_MOLGEIM_AGGRO = -1603030, - SAY_MOLGEIM_SLAY_1 = -1603031, - SAY_MOLGEIM_SLAY_2 = -1603032, - SAY_MOLGEIM_RUNE_DEATH = -1603033, - SAY_MOLGEIM_SUMMON = -1603034, - SAY_MOLGEIM_DEATH_1 = -1603035, - SAY_MOLGEIM_DEATH_2 = -1603036, - SAY_MOLGEIM_BERSERK = -1603037, - - SAY_BRUNDIR_AGGRO = -1603040, - SAY_BRUNDIR_SLAY_1 = -1603041, - SAY_BRUNDIR_SLAY_2 = -1603042, - SAY_BRUNDIR_SPECIAL = -1603043, - SAY_BRUNDIR_FLIGHT = -1603044, - SAY_BRUNDIR_DEATH_1 = -1603045, - SAY_BRUNDIR_DEATH_2 = -1603046, - SAY_BRUNDIR_BERSERK = -1603047, -}; - -bool IsEncounterComplete(ScriptedInstance* pInstance, Creature* me) -{ - if (!pInstance || !me) - return false; - - for (uint8 i = 0; i < 3; ++i) - { - uint64 guid = pInstance->GetData64(DATA_STEELBREAKER+i); - if (!guid) - return false; - - if (Creature *boss = Unit::GetCreature(*me, guid)) - { - if (boss->isAlive()) - return false; - } - else - return false; - } - return true; -} - -struct boss_steelbreakerAI : public ScriptedAI -{ - boss_steelbreakerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() - { - events.Reset(); - phase = 0; - me->RemoveAllAuras(); - if (pInstance) - pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); - } - - EventMap events; - ScriptedInstance* pInstance; - uint32 phase; - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_STEELBREAKER_AGGRO, me); - DoZoneInCombat(); - DoCast(me, RAID_MODE(SPELL_HIGH_VOLTAGE, SPELL_HIGH_VOLTAGE_H)); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - UpdatePhase(); - } - - void UpdatePhase() - { - ++phase; - events.SetPhase(phase); - events.RescheduleEvent(EVENT_FUSION_PUNCH, 15000); - if (phase >= 2) - events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 30000); - if (phase >= 3) - events.RescheduleEvent(EVENT_OVERWHELMING_POWER, rand()%5000); - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - if (Creature* Brundir = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0)) - if (Brundir->isAlive()) - Brundir->SetHealth(Brundir->GetMaxHealth()); - - if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0)) - if (Molgeim->isAlive()) - Molgeim->SetHealth(Molgeim->GetMaxHealth()); - - DoCast(SPELL_SUPERCHARGE); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_STEELBREAKER_DEATH_1,SAY_STEELBREAKER_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(TYPE_ASSEMBLY, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_STEELBREAKER_SLAY_1,SAY_STEELBREAKER_SLAY_2), me); - - if (phase == 3) - DoCast(me, SPELL_ELECTRICAL_CHARGE); - } - - void SpellHit(Unit * /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - UpdatePhase(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ENRAGE: - DoScriptText(SAY_STEELBREAKER_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_FUSION_PUNCH: - DoCast(me->getVictim(), RAID_MODE(SPELL_FUSION_PUNCH, SPELL_FUSION_PUNCH_H)); - events.ScheduleEvent(EVENT_FUSION_PUNCH, urand(13000, 22000)); - break; - case EVENT_STATIC_DISRUPTION: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, RAID_MODE(SPELL_STATIC_DISRUPTION, SPELL_STATIC_DISRUPTION_H)); - events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(20000, 40000)); - break; - case EVENT_OVERWHELMING_POWER: - DoScriptText(SAY_STEELBREAKER_POWER, me); - DoCast(me->getVictim(), RAID_MODE(SPELL_OVERWHELMING_POWER, SPELL_OVERWHELMING_POWER_H)); - events.ScheduleEvent(EVENT_OVERWHELMING_POWER, RAID_MODE(60000, 35000)); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_runemaster_molgeimAI : public ScriptedAI -{ - boss_runemaster_molgeimAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() - { - if (pInstance) - pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); - events.Reset(); - me->RemoveAllAuras(); - phase = 0; - } - - ScriptedInstance* pInstance; - EventMap events; - uint32 phase; - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_MOLGEIM_AGGRO, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - UpdatePhase(); - } - - void UpdatePhase() - { - ++phase; - events.SetPhase(phase); - events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27000); - events.RescheduleEvent(EVENT_RUNE_OF_POWER, 60000); - if (phase >= 2) - events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 30000); - if (phase >= 3) - events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0)) - if (Steelbreaker->isAlive()) - Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth()); - - if (Creature* Brundir = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_STORMCALLER_BRUNDIR) : 0)) - if (Brundir->isAlive()) - Brundir->SetHealth(Brundir->GetMaxHealth()); - - DoCast(me, SPELL_SUPERCHARGE); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_MOLGEIM_DEATH_1,SAY_MOLGEIM_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(TYPE_ASSEMBLY, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_MOLGEIM_SLAY_1,SAY_MOLGEIM_SLAY_2), me); - } - - void SpellHit(Unit * /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - UpdatePhase(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ENRAGE: - DoScriptText(SAY_MOLGEIM_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_RUNE_OF_POWER: // Improve target selection; random alive friendly - { - Unit *pTarget = DoSelectLowestHpFriendly(60); - if (!pTarget || (pTarget && !pTarget->isAlive())) - pTarget = me; - DoCast(pTarget, SPELL_RUNE_OF_POWER); - events.ScheduleEvent(EVENT_RUNE_OF_POWER, 60000); - break; - } - case EVENT_SHIELD_OF_RUNES: - DoCast(me, RAID_MODE(SPELL_SHIELD_OF_RUNES, SPELL_SHIELD_OF_RUNES_H)); - events.ScheduleEvent(EVENT_SHIELD_OF_RUNES, urand(27000,34000)); - break; - case EVENT_RUNE_OF_DEATH: - DoScriptText(SAY_MOLGEIM_RUNE_DEATH, me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_RUNE_OF_DEATH); - events.ScheduleEvent(EVENT_RUNE_OF_DEATH, urand(30000,40000)); - break; - case EVENT_RUNE_OF_SUMMONING: - DoScriptText(SAY_MOLGEIM_SUMMON, me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_RUNE_OF_SUMMONING); - events.ScheduleEvent(EVENT_RUNE_OF_SUMMONING, urand(20000,30000)); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_lightning_elementalAI : public ScriptedAI -{ - mob_lightning_elementalAI(Creature *c) : ScriptedAI(c) - { - Charge(); - } - - void Charge() - { - Unit* pTarget = me->SelectNearestTarget(); - me->AddThreat(pTarget, 5000000.0f); - AttackStart(pTarget); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!me->isInCombat()) - return; - - if (!UpdateVictim()) - return; - - if (me->IsWithinMeleeRange(me->getVictim())) - { - DoCast(me->getVictim(), RAID_MODE(SPELL_LIGHTNING_BLAST, SPELL_LIGHTNING_BLAST_H)); - me->Kill(me); // hack until spell works - } - - me->GetMotionMaster()->MoveChase(me->getVictim()); // needed at every update? - } -}; - -struct mob_rune_of_summoningAI : public ScriptedAI -{ - mob_rune_of_summoningAI(Creature *c) : ScriptedAI(c) - { - SummonLightningElemental(); - } - - void SummonLightningElemental() - { - me->SummonCreature(CREATURE_RUNE_OF_SUMMONING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN); - me->DealDamage(me, me->GetHealth()); - } -}; - -struct boss_stormcaller_brundirAI : public ScriptedAI -{ - boss_stormcaller_brundirAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - void Reset() - { - if (pInstance) - pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED); - me->RemoveAllAuras(); - events.Reset(); - phase = 0; - } - - EventMap events; - ScriptedInstance* pInstance; - uint32 phase; - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_BRUNDIR_AGGRO, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ENRAGE, 900000); - UpdatePhase(); - } - - void UpdatePhase() - { - ++phase; - events.SetPhase(phase); - events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000,17000)); - events.RescheduleEvent(EVENT_OVERLOAD, urand(60000,125000)); - if (phase >= 2) - events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000,40000)); - if (phase >= 3) - { - DoCast(me, SPELL_STORMSHIELD); - events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, urand(40000,80000)); - } - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - if (Creature* Steelbreaker = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_STEELBREAKER) : 0)) - if (Steelbreaker->isAlive()) - Steelbreaker->SetHealth(Steelbreaker->GetMaxHealth()); - - if (Creature* Molgeim = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RUNEMASTER_MOLGEIM) : 0)) - if (Molgeim->isAlive()) - Molgeim->SetHealth(Molgeim->GetMaxHealth()); - - DoCast(SPELL_SUPERCHARGE); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(RAND(SAY_BRUNDIR_DEATH_1,SAY_BRUNDIR_DEATH_2), me); - if (IsEncounterComplete(pInstance, me) && pInstance) - pInstance->SetData(TYPE_ASSEMBLY, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_BRUNDIR_SLAY_1,SAY_BRUNDIR_SLAY_2), me); - } - - void SpellHit(Unit * /*from*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_SUPERCHARGE) - UpdatePhase(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ENRAGE: - DoScriptText(SAY_BRUNDIR_BERSERK, me); - DoCast(SPELL_BERSERK); - break; - case EVENT_CHAIN_LIGHTNING: - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, RAID_MODE(SPELL_CHAIN_LIGHTNING_N , SPELL_CHAIN_LIGHTNING_H)); - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(9000,17000)); - break; - case EVENT_OVERLOAD: - DoCast(RAID_MODE(SPELL_OVERLOAD , SPELL_OVERLOAD_H)); - events.ScheduleEvent(EVENT_OVERLOAD, urand(60000,125000)); - break; - case EVENT_LIGHTNING_WHIRL: - DoCast(RAID_MODE(SPELL_LIGHTNING_WHIRL , SPELL_LIGHTNING_WHIRL_H)); - events.ScheduleEvent(EVENT_LIGHTNING_WHIRL, urand(20000,40000)); - break; - case EVENT_LIGHTNING_TENDRILS: - DoCast(RAID_MODE(SPELL_LIGHTNING_TENDRILS, SPELL_LIGHTNING_TENDRILS_H)); - events.DelayEvents(15000, 5000); - DoResetThreat(); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_steelbreaker(Creature* pCreature) -{ - return new boss_steelbreakerAI (pCreature); -} - -CreatureAI* GetAI_boss_runemaster_molgeim(Creature* pCreature) -{ - return new boss_runemaster_molgeimAI (pCreature); -} - -CreatureAI* GetAI_boss_stormcaller_brundir(Creature* pCreature) -{ - return new boss_stormcaller_brundirAI (pCreature); -} - -CreatureAI* GetAI_mob_lightning_elemental(Creature* pCreature) -{ - return new mob_lightning_elementalAI (pCreature); -} - -CreatureAI* GetAI_mob_rune_of_summoning(Creature* pCreature) -{ - return new mob_rune_of_summoningAI (pCreature); -} - -void AddSC_boss_assembly_of_iron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_steelbreaker"; - newscript->GetAI = &GetAI_boss_steelbreaker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_runemaster_molgeim"; - newscript->GetAI = &GetAI_boss_runemaster_molgeim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_stormcaller_brundir"; - newscript->GetAI = &GetAI_boss_stormcaller_brundir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lightning_elemental"; - newscript->GetAI = &GetAI_mob_lightning_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_rune_of_summoning"; - newscript->GetAI = &GetAI_mob_rune_of_summoning; - newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp deleted file mode 100644 index 41c0f317f4e..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_auriaya.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -//boss_auriaya -#define SPELL_TERRIFYING_SCREECH 64386 -#define SPELL_SETINEL_BLAST 64679 -#define SPELL_SONIC_SCREECH 64422 -#define SPELL_SUMMON_SWARMING_GUARDIAN 64397 - -enum Yells -{ - SAY_AGGRO = -1603050, - SAY_SLAY_1 = -1603051, - SAY_SLAY_2 = -1603052, - SAY_DEATH = -1603053, - SAY_BERSERK = -1603054, -}; - -struct boss_auriaya_AI : public BossAI -{ - boss_auriaya_AI(Creature *pCreature) : BossAI(pCreature, TYPE_AURIAYA) - { - } - - uint32 TERRIFYING_SCREECH_Timer; - uint32 SONIC_SCREECH_Timer; - - void Reset() - { - _Reset(); - TERRIFYING_SCREECH_Timer = 180000; - SONIC_SCREECH_Timer = 30000; - } - - void EnterCombat(Unit* /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO,me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (TERRIFYING_SCREECH_Timer <= diff) - { - DoCast(SPELL_TERRIFYING_SCREECH); - TERRIFYING_SCREECH_Timer = 180000; - } else TERRIFYING_SCREECH_Timer -= diff; - - if (SONIC_SCREECH_Timer <= diff) - { - DoCastVictim(SPELL_SONIC_SCREECH); - SONIC_SCREECH_Timer = 30000; - } else SONIC_SCREECH_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_auriaya(Creature* pCreature) -{ - return new boss_auriaya_AI (pCreature); -} - -void AddSC_boss_auriaya() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_auriaya"; - newscript->GetAI = &GetAI_boss_auriaya; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp deleted file mode 100644 index b50f12805a4..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_flame_leviathan.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2008 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: Tower Event support is not finished, there is missing code on triggers and - * Lore Keeper and Brann Bronzebeard are not scripted yet. Lore Keeper's script - * should activate the hard mode so is not possible to play hard-mode yet. Add a call to - * Leviathan's DoAction(0) from Lore Keeper's script to activate hard-mode - */ - -#include "ScriptedPch.h" -#include "ulduar.h" -#include "Vehicle.h" - -enum Spells -{ - SPELL_PURSUED = 62374, - SPELL_GATHERING_SPEED = 62375, - SPELL_BATTERING_RAM = 62376, - SPELL_FLAME_VENTS = 62396, - SPELL_MISSILE_BARRAGE = 62400, - SPELL_SYSTEMS_SHUTDOWN = 62475, - - SPELL_FLAME_CANNON = 62395, -// SPELL_FLAME_CANNON = 64692, trigger the same spell - - SPELL_OVERLOAD_CIRCUIT = 62399, - SPELL_SEARING_FLAME = 62402, - SPELL_BLAZE = 62292, - SPELL_SMOKE_TRAIL = 63575, - SPELL_ELECTROSHOCK = 62522, - //TOWER BUFF SPELLS - SPELL_THORIM_S_HAMMER = 62912, // Tower of Storms - SPELL_MIMIRON_S_INFERNO = 62910, // Tower of Flames - SPELL_HODIR_S_FURY = 62297, // Tower of Frost - SPELL_FREYA_S_WARD = 62906 // Tower of Nature -}; - -enum Creatures -{ - MOB_MECHANOLIFT = 33214, - MOB_LIQUID = 33189, - MOB_CONTAINER = 33218, -}; - -enum Events -{ - EVENT_NONE, - EVENT_PURSUE, - EVENT_MISSILE, - EVENT_VENT, - EVENT_SPEED, - EVENT_SUMMON, - EVENT_THORIM_S_HAMMER, // Tower of Storms - EVENT_MIMIRON_S_INFERNO, // Tower of Flames - EVENT_HODIR_S_FURY, // Tower of Frost - EVENT_FREYA_S_WARD // Tower of Nature -}; - -enum Seats -{ - SEAT_PLAYER = 0, - SEAT_TURRET = 1, - SEAT_DEVICE = 2, -}; - -enum Yells -{ - SAY_AGGRO = -1603060, - SAY_SLAY = -1603061, - SAY_DEATH = -1603062, - SAY_TARGET_1 = -1603063, - SAY_TARGET_2 = -1603064, - SAY_TARGET_3 = -1603065, - SAY_HARDMODE = -1603066, - SAY_TOWER_NONE = -1603067, - SAY_TOWER_FROST = -1603068, - SAY_TOWER_FLAME = -1603069, - SAY_TOWER_NATURE = -1603070, - SAY_TOWER_STORM = -1603071, - SAY_PLAYER_RIDING = -1603072, - SAY_OVERLOAD_1 = -1603073, - SAY_OVERLOAD_2 = -1603074, - SAY_OVERLOAD_3 = -1603075, -}; - -enum eAchievementData -{ - //ACHIEV_CHAMPION_OF_ULDUAR = 10042, - //ACHIEV_CONQUEROR_OF_ULDUAR = 10352, - ACHIEV_10_NUKED_FROM_ORBIT = 10058, - ACHIEV_25_NUKED_FROM_ORBIT = 10060, - ACHIEV_10_ORBITAL_BOMBARDMENT = 10056, - ACHIEV_25_ORBITAL_BOMBARDMENT = 10061, - ACHIEV_10_ORBITAL_DEVASTATION = 10057, - ACHIEV_25_ORBITAL_DEVASTATION = 10059, - ACHIEV_10_ORBIT_UARY = 10218, - ACHIEV_25_ORBIT_UARY = 10219, - ACHIEV_10_SHUTOUT = 10054, - ACHIEV_25_SHUTOUT = 10055, - ACHIEV_10_SIEGE_OF_ULDUAR = 9999, - ACHIEV_25_SIEGE_OF_ULDUAR = 10003, - //ACHIEV_10_THREE_CAR_GARAGE = 10046, 10047, 10048, - //ACHIEV_25_THREE_CAR_GARAGE = 10049, 10050, 10051, - ACHIEV_10_UNBROKEN = 10044, - ACHIEV_25_UNBROKEN = 10045, -}; - -static Position Center[]= -{ - {354.8771, -12.90240, 409.803650}, -}; - -struct boss_flame_leviathanAI : public BossAI -{ - boss_flame_leviathanAI(Creature* pCreature) : BossAI(pCreature, TYPE_LEVIATHAN), vehicle(pCreature->GetVehicleKit()) - { - assert(vehicle); - - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - Vehicle* vehicle; - uint8 uiActiveTowers; - - void Reset() - { - _Reset(); - assert(vehicle); - uiActiveTowers = 0; - me->SetReactState(REACT_AGGRESSIVE); - } - - void EnterCombat(Unit* /*who*/) - { - _EnterCombat(); - DoScriptText(SAY_AGGRO, me); - me->SetReactState(REACT_DEFENSIVE); - events.ScheduleEvent(EVENT_PURSUE, 0); - events.ScheduleEvent(EVENT_MISSILE, 1500); - events.ScheduleEvent(EVENT_VENT, 20000); - events.ScheduleEvent(EVENT_SPEED, 15000); - events.ScheduleEvent(EVENT_SUMMON, 0); - - if (Creature *turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET))) - turret->AI()->DoZoneInCombat(); - } - - // TODO: effect 0 and effect 1 may be on different target - void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_PURSUED) - AttackStart(pTarget); - } - - void JustDied(Unit* /*victim*/) - { - _JustDied(); - DoScriptText(SAY_DEATH, me); - if (pInstance) - { - if (uiActiveTowers) - { - switch (uiActiveTowers) - { - case 4: - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBIT_UARY, ACHIEV_25_ORBIT_UARY)); - break; - case 3: - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_NUKED_FROM_ORBIT, ACHIEV_25_NUKED_FROM_ORBIT)); - break; - case 2: - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBITAL_DEVASTATION, ACHIEV_25_ORBITAL_DEVASTATION)); - break; - case 1: - pInstance->DoCompleteAchievement(RAID_MODE(ACHIEV_10_ORBITAL_BOMBARDMENT, ACHIEV_25_ORBITAL_BOMBARDMENT)); - break; - } - } - } - } - - void SpellHit(Unit* /*caster*/, const SpellEntry* pSpell) - { - if (pSpell->Id == 62472) - vehicle->InstallAllAccessories(); - else if (pSpell->Id == SPELL_ELECTROSHOCK) - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; - - if (me->getThreatManager().isThreatListEmpty()) - { - EnterEvadeMode(); - return; - } - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - uint32 eventId = events.GetEvent(); - if (!me->getVictim()) - eventId = EVENT_PURSUE; - - switch(eventId) - { - case 0: break; // this is a must - case EVENT_PURSUE: - DoCastAOE(SPELL_PURSUED, true); - //events.RepeatEvent(35000); // this should not be used because eventId may be overriden - events.RescheduleEvent(EVENT_PURSUE, 35000); - if (!me->getVictim()) // all siege engines and demolishers are dead - UpdateVictim(); // begin to kill other things - return; - case EVENT_MISSILE: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_MISSILE_BARRAGE); - events.RepeatEvent(1500); - return; - case EVENT_VENT: - DoCastAOE(SPELL_FLAME_VENTS); - events.RepeatEvent(20000); - return; - case EVENT_SPEED: - DoCastAOE(SPELL_GATHERING_SPEED); - events.RepeatEvent(15000); - return; - case EVENT_SUMMON: - if (summons.size() < 15) // 4seat+1turret+10lift - if (Creature* pLift = DoSummonFlyer(MOB_MECHANOLIFT, me, urand(20,40), 50, 0)) - pLift->GetMotionMaster()->MoveRandom(100); - events.RepeatEvent(2000); - return; - case EVENT_THORIM_S_HAMMER: // Tower of Storms - DoCast(me, SPELL_THORIM_S_HAMMER); - events.RepeatEvent(urand(60000, 120000)); - return; - case EVENT_MIMIRON_S_INFERNO: // Tower of Flames - DoCast(me->getVictim(), SPELL_MIMIRON_S_INFERNO); - events.RepeatEvent(urand(60000, 120000)); - return; - case EVENT_HODIR_S_FURY: // Tower of Frost - DoCast(me->getVictim(), SPELL_HODIR_S_FURY); - events.RepeatEvent(urand(60000, 120000)); - return; - case EVENT_FREYA_S_WARD: // Tower of Nature - DoCast(me, SPELL_FREYA_S_WARD); - events.RepeatEvent(urand(60000, 120000)); - return; - default: - events.PopEvent(); - break; - } - DoSpellAttackIfReady(SPELL_BATTERING_RAM); - } - - void DoAction(const int32 uiAction) - { - // Start encounter - if (uiAction == 10) - { - me->GetMotionMaster()->MovePoint(0, Center[0]); - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - return; - } - /* - Tower event triggers - General TODO: - Yells - - Actions: - DoAction(0): Activate hard-mode. Buff up leviathan's AP & health, schedule all the tower spells. - Should be triggered on Lore Keeper's script - DoAction(1-4): A tower have been destroyed, debuff leviathan's AP & health - DoAction(1); Tower of Storms has been destroyed, deschedule spell Thorim's Hammer - DoAction(2): Tower of Flames has been destroyed, deschedule spell Mimiron's Inferno - DoAction(3): Tower of Frost has been destroyed, deschedule spell Hodir's Fury - DoAction(4): Tower of Nature has been destroyed, deschedule spell Freya's Ward - */ - - if (uiAction) // Tower destruction, debuff leviathan AP & health - { - --uiActiveTowers; - } - - switch (uiAction) - { - case 0: // Activate hard-mode - events.ScheduleEvent(EVENT_THORIM_S_HAMMER, urand(30000,60000)); - events.ScheduleEvent(EVENT_MIMIRON_S_INFERNO, urand(30000,60000)); - events.ScheduleEvent(EVENT_HODIR_S_FURY, urand(30000,60000)); - events.ScheduleEvent(EVENT_FREYA_S_WARD, urand(30000,60000)); - uiActiveTowers=4; - break; - case 1: // Tower of Storms destroyed - events.CancelEvent(EVENT_THORIM_S_HAMMER); - break; - case 2: // Tower of Flames destroyed - events.CancelEvent(EVENT_MIMIRON_S_INFERNO); - break; - case 3: // Tower of Frost destroyed - events.CancelEvent(EVENT_HODIR_S_FURY); - break; - case 4: // Tower of Nature destroyed - events.CancelEvent(EVENT_FREYA_S_WARD); - break; - } - } -}; - -//#define BOSS_DEBUG - -struct boss_flame_leviathan_seatAI : public PassiveAI -{ - boss_flame_leviathan_seatAI(Creature *c) : PassiveAI(c), vehicle(c->GetVehicleKit()) - { - assert(vehicle); -#ifdef BOSS_DEBUG - me->SetReactState(REACT_AGGRESSIVE); -#endif - } - - Vehicle* vehicle; - -#ifdef BOSS_DEBUG - void MoveInLineOfSight(Unit *who) - { - if (who->GetTypeId() == TYPEID_PLAYER && CAST_PLR(who)->isGameMaster() - && !who->GetVehicle() && vehicle->GetPassenger(SEAT_TURRET)) - who->EnterVehicle(vehicle, SEAT_PLAYER); - } -#endif - - void PassengerBoarded(Unit* who, int8 seatId, bool apply) - { - if (!me->GetVehicle()) - return; - - if (seatId == SEAT_PLAYER) - { - if (!apply) - return; - - if (Creature* turret = CAST_CRE(vehicle->GetPassenger(SEAT_TURRET))) - { - turret->setFaction(me->GetVehicleBase()->getFaction()); - turret->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable - turret->AI()->AttackStart(who); - } - if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) - { - device->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - device->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - } - else if (seatId == SEAT_TURRET) - { - if (apply) - return; - - if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) - { - device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - device->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable - } - } - } -}; - -struct boss_flame_leviathan_defense_turretAI : public TurretAI -{ - boss_flame_leviathan_defense_turretAI(Creature *c) : TurretAI(c) {} - - void DamageTaken(Unit* who, uint32 &damage) - { - if (!CanAIAttack(who)) - damage = 0; - } - - bool CanAIAttack(const Unit *who) const - { - if (who->GetTypeId() != TYPEID_PLAYER || !who->GetVehicle() || who->GetVehicleBase()->GetEntry() != 33114) - return false; - return true; - } -}; - -struct boss_flame_leviathan_overload_deviceAI : public PassiveAI -{ - boss_flame_leviathan_overload_deviceAI(Creature* pCreature) : PassiveAI(pCreature) {} - - void DoAction(const int32 param) - { - if (param == EVENT_SPELLCLICK) - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (me->GetVehicle()) - { - if (Unit* pPlayer = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) - { - pPlayer->ExitVehicle(); - me->GetVehicleBase()->CastSpell(pPlayer, SPELL_SMOKE_TRAIL, true); - if (Unit* leviathan = me->GetVehicleBase()->GetVehicleBase()) - pPlayer->GetMotionMaster()->MoveKnockbackFrom(leviathan->GetPositionX(), leviathan->GetPositionY(), 30, 30); - } - } - } - } -}; - -struct boss_flame_leviathan_safety_containerAI : public PassiveAI -{ - boss_flame_leviathan_safety_containerAI(Creature *c) : PassiveAI(c) {} - - void MovementInform(uint32 /*type*/, uint32 id) - { - if (id == me->GetEntry()) - { - if (Creature* pLiquid = DoSummon(MOB_LIQUID, me, 0)) - pLiquid->CastSpell(pLiquid, 62494, true); - me->DisappearAndDie(); // this will relocate creature to sky - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!me->GetVehicle() && me->isSummon() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) - me->GetMotionMaster()->MoveFall(409.8f, me->GetEntry()); - } -}; - -struct spell_pool_of_tarAI : public TriggerAI -{ - spell_pool_of_tarAI(Creature *c) : TriggerAI(c) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void DamageTaken(Unit * /*who*/, uint32 &damage) - { - damage = 0; - } - - void SpellHit(Unit* /*caster*/, const SpellEntry *spell) - { - if (spell->SchoolMask & SPELL_SCHOOL_MASK_FIRE && !me->HasAura(SPELL_BLAZE)) - me->CastSpell(me, SPELL_BLAZE, true); - } -}; - -struct npc_colossusAI : public ScriptedAI -{ - npc_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance *pInstance; - Position pPos; - - void JustDied(Unit* /*Who*/) - { - if (me->GetHomePosition().IsInDist(Center,50.f)) - { - if (pInstance) - pInstance->SetData(TYPE_COLOSSUS,pInstance->GetData(TYPE_COLOSSUS)+1); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - } -}; - -CreatureAI* GetAI_boss_flame_leviathan(Creature* pCreature) -{ - return new boss_flame_leviathanAI (pCreature); -} - -CreatureAI* GetAI_boss_flame_leviathan_seat(Creature* pCreature) -{ - return new boss_flame_leviathan_seatAI (pCreature); -} - -CreatureAI* GetAI_boss_flame_leviathan_defense_turret(Creature* pCreature) -{ - return new boss_flame_leviathan_defense_turretAI (pCreature); -} - -CreatureAI* GetAI_boss_flame_leviathan_overload_device(Creature* pCreature) -{ - return new boss_flame_leviathan_overload_deviceAI (pCreature); -} - -CreatureAI* GetAI_boss_flame_leviathan_safety_containerAI(Creature* pCreature) -{ - return new boss_flame_leviathan_safety_containerAI(pCreature); -} - -CreatureAI* GetAI_spell_pool_of_tar(Creature* pCreature) -{ - return new spell_pool_of_tarAI (pCreature); -} - -CreatureAI* GetAI_npc_colossus(Creature* pCreature) -{ - return new npc_colossusAI(pCreature); -} - -void AddSC_boss_flame_leviathan() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_flame_leviathan"; - newscript->GetAI = &GetAI_boss_flame_leviathan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_flame_leviathan_seat"; - newscript->GetAI = &GetAI_boss_flame_leviathan_seat; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_flame_leviathan_defense_turret"; - newscript->GetAI = &GetAI_boss_flame_leviathan_defense_turret; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_flame_leviathan_overload_device"; - newscript->GetAI = &GetAI_boss_flame_leviathan_overload_device; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_flame_leviathan_safety_container"; - newscript->GetAI = &GetAI_boss_flame_leviathan_safety_containerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "spell_pool_of_tar"; - newscript->GetAI = &GetAI_spell_pool_of_tar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_colossus"; - newscript->GetAI = &GetAI_npc_colossus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp deleted file mode 100644 index ee995878a0e..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_freya.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO = -1603180, - SAY_AGGRO_WITH_ELDER = -1603181, - SAY_SLAY_1 = -1603182, - SAY_SLAY_2 = -1603183, - SAY_DEATH = -1603184, - SAY_BERSERK = -1603185, - SAY_SUMMON_CONSERVATOR = -1603186, - SAY_SUMMON_TRIO = -1603187, - SAY_SUMMON_LASHERS = -1603188, - SAY_YS_HELP = -1603189, - - // Elder Brightleaf - SAY_BRIGHTLEAF_AGGRO = -1603190, - SAY_BRIGHTLEAF_SLAY_1 = -1603191, - SAY_BRIGHTLEAF_SLAY_2 = -1603192, - SAY_BRIGHTLEAF_DEATH = -1603193, - - // Elder Ironbranch - SAY_IRONBRANCH_AGGRO = -1603194, - SAY_IRONBRANCH_SLAY_1 = -1603195, - SAY_IRONBRANCH_SLAY_2 = -1603196, - SAY_IRONBRANCH_DEATH = -1603197, - - // Elder Stonebark - SAY_STONEBARK_AGGRO = -1603198, - SAY_STONEBARK_SLAY_1 = -1603199, - SAY_STONEBARK_SLAY_2 = -1603200, - SAY_STONEBARK_DEATH = -1603201, -}; - -enum -{ - // Con-speed-atory timed achievement. - // TODO Should be started when 1st trash is killed. - ACHIEV_CON_SPEED_ATORY_START_EVENT = 21597, - SPELL_ACHIEVEMENT_CHECK = 65074, - - // Lumberjacked timed achievement. - // TODO should be started when 1st elder is killed. - // Spell should be casted when 3rd elder is killed. - ACHIEV_LUMBERJACKED = 21686, - SPELL_LUMBERJACKED_ACHIEVEMENT_CHECK = 65296, -}; - -struct boss_freyaAI : public BossAI -{ - boss_freyaAI(Creature* pCreature) : BossAI(pCreature, TYPE_FREYA) - { - } - - void Reset() - { - _Reset(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - - // cast is not rewarding the achievement. - // DoCast(SPELL_ACHIEVEMENT_CHECK); - instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_ACHIEVEMENT_CHECK); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - _EnterCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; -//SPELLS TODO: - -// - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_freya(Creature* pCreature) -{ - return new boss_freyaAI(pCreature); -} - -void AddSC_boss_freya() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_freya"; - newscript->GetAI = &GetAI_boss_freya; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp deleted file mode 100644 index f84c638d3e3..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_general_vezax.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO = -1603290, - SAY_SLAY_1 = -1603291, - SAY_SLAY_2 = -1603292, - SAY_KITE = -1603293, - SAY_DEATH = -1603294, - SAY_BERSERK = -1603295, - SAY_HARDMODE_ON = -1603296, -}; diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp deleted file mode 100644 index 6facd8ac639..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_hodir.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO = -1603210, - SAY_SLAY_1 = -1603211, - SAY_SLAY_2 = -1603212, - SAY_FLASH_FREEZE = -1603213, - SAY_STALACTITE = -1603214, - SAY_DEATH = -1603215, - SAY_BERSERK = -1603216, - SAY_YS_HELP = -1603217, - SAY_HARD_MODE_MISSED = -1603218, -}; - -struct boss_hodirAI : public BossAI -{ - boss_hodirAI(Creature *pCreature) : BossAI(pCreature, TYPE_HODIR) - { - } - - void Reset() - { - _Reset(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - _EnterCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; -//SPELLS TODO: - -// - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_hodir(Creature* pCreature) -{ - return new boss_hodirAI(pCreature); -} - -void AddSC_boss_hodir() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hodir"; - newscript->GetAI = &GetAI_boss_hodir; - newscript->RegisterSelf(); - -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp deleted file mode 100644 index 05f9ecd3c66..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_ignis.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -#define SPELL_FLAME_JETS 62680 -#define SPELL_SCORCH 62546 -#define SPELL_SLAG_POT 62717 - -enum Yells -{ - SAY_AGGRO = -1603220, - SAY_SLAY_1 = -1603221, - SAY_SLAY_2 = -1603222, - SAY_DEATH = -1603223, - SAY_SUMMON = -1603224, - SAY_SLAG_POT = -1603225, - SAY_SCORCH_1 = -1603226, - SAY_SCORCH_2 = -1603227, - SAY_BERSERK = -1603228, -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 20951, -}; - -struct boss_ignis_AI : public BossAI -{ - boss_ignis_AI(Creature *pCreature) : BossAI(pCreature, TYPE_IGNIS) {} - - uint32 uiFlameJetsTimer; - uint32 uiScorchTimer; - uint32 uiSlagPotTimer; - - void Reset() - { - _Reset(); - uiFlameJetsTimer = 32000; - uiScorchTimer = 100; - uiSlagPotTimer = 100; - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO,me); - _EnterCombat(); - - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetPositionY() < 150 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(false); - me->GetMotionMaster()->MoveTargetedHome(); - } - - if (uiFlameJetsTimer <= diff) - { - DoCast(SPELL_FLAME_JETS); - uiFlameJetsTimer = 25000; - } else uiFlameJetsTimer -= diff; - - if (uiScorchTimer <= diff) - { - DoScriptText(RAND(SAY_SCORCH_1,SAY_SCORCH_2), me); - DoCast(SPELL_SCORCH); - uiScorchTimer = 20000; - } else uiScorchTimer -= diff; - - if (uiSlagPotTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(SAY_SLAG_POT, me); - DoCast(pTarget, SPELL_SLAG_POT); - } - uiSlagPotTimer = 30000; - } else uiSlagPotTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ignis(Creature* pCreature) -{ - return new boss_ignis_AI (pCreature); -} -void AddSC_boss_ignis() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ignis"; - newscript->GetAI = &GetAI_boss_ignis; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp deleted file mode 100644 index 2080b458a1b..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_kologarn.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" -#include "Vehicle.h" - -#define SPELL_ARM_DEAD_DAMAGE RAID_MODE(63629,63979) -#define SPELL_TWO_ARM_SMASH RAID_MODE(63356,64003) -#define SPELL_ONE_ARM_SMASH RAID_MODE(63573,64006) -#define SPELL_STONE_SHOUT RAID_MODE(63716,64005) -#define SPELL_PETRIFY_BREATH RAID_MODE(62030,63980) - -#define SPELL_STONE_GRIP RAID_MODE(62166,63981) -#define SPELL_ARM_SWEEP RAID_MODE(63766,63983) - -enum Events -{ - EVENT_NONE = 0, - EVENT_SMASH, - EVENT_GRIP, - EVENT_SWEEP, -}; - -enum Yells -{ - SAY_AGGRO = -1603230, - SAY_SLAY_1 = -1603231, - SAY_SLAY_2 = -1603232, - SAY_LEFT_ARM_GONE = -1603233, - SAY_RIGHT_ARM_GONE = -1603234, - SAY_SHOCKWAVE = -1603235, - SAY_GRAB_PLAYER = -1603236, - SAY_DEATH = -1603237, - SAY_BERSERK = -1603238, -}; - -enum -{ - ACHIEV_DISARMED_START_EVENT = 21687, -}; - -struct boss_kologarnAI : public BossAI -{ - boss_kologarnAI(Creature *pCreature) : BossAI(pCreature, TYPE_KOLOGARN), vehicle(pCreature->GetVehicleKit()), - left(false), right(false) - { - assert(vehicle); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); // i think this is a hack, but there is no other way to disable his rotation - } - - Vehicle *vehicle; - bool left, right; - - void AttackStart(Unit *who) - { - me->Attack(who, true); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void KilledUnit(Unit* /*who*/) - { - DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_2), me); - } - - void PassengerBoarded(Unit *who, int8 /*seatId*/, bool apply) - { - if (who->GetTypeId() == TYPEID_UNIT) - { - if (who->GetEntry() == 32933) - left = apply; - else if (who->GetEntry() == 32934) - right = apply; - - if (!apply && instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT); - - who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - CAST_CRE(who)->SetReactState(REACT_PASSIVE); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - _EnterCombat(); - events.ScheduleEvent(EVENT_SMASH, 5000); - events.ScheduleEvent(EVENT_SWEEP, 10000); - events.ScheduleEvent(EVENT_GRIP, 15000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - // TODO: because we are using hack, he is stunned and cannot cast, so we use triggered for every spell - switch(events.GetEvent()) - { - case EVENT_NONE: - break; - case EVENT_SMASH: - if (left && right) - DoCastVictim(SPELL_TWO_ARM_SMASH, true); - else if (left || right) - DoCastVictim(SPELL_ONE_ARM_SMASH, true); - events.RepeatEvent(15000); - break; - case EVENT_SWEEP: - if (left) - DoCastAOE(SPELL_ARM_SWEEP, true); - events.RepeatEvent(15000); - break; - case EVENT_GRIP: - if (right) - DoCastAOE(SPELL_STONE_GRIP, true); - events.RepeatEvent(15000); - break; - default: - events.PopEvent(); - break; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kologarn(Creature* pCreature) -{ - return new boss_kologarnAI (pCreature); -} - -void AddSC_boss_kologarn() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kologarn"; - newscript->GetAI = &GetAI_boss_kologarn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp deleted file mode 100644 index 2b9994d5d9b..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_mimiron.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO = -1603240, - SAY_HARDMODE_ON = -1603241, - SAY_MKII_ACTIVATE = -1603242, - SAY_MKII_SLAY_1 = -1603243, - SAY_MKII_SLAY_2 = -1603244, - SAY_MKII_DEATH = -1603245, - SAY_VX001_ACTIVATE = -1603246, - SAY_VX001_SLAY_1 = -1603247, - SAY_VX001_SLAY_2 = -1603248, - SAY_VX001_DEATH = -1603249, - SAY_AERIAL_ACTIVATE = -1603250, - SAY_AERIAL_SLAY_1 = -1603251, - SAY_AERIAL_SLAY_2 = -1603252, - SAY_AERIAL_DEATH = -1603253, - SAY_V07TRON_ACTIVATE = -1603254, - SAY_V07TRON_SLAY_1 = -1603255, - SAY_V07TRON_SLAY_2 = -1603256, - SAY_V07TRON_DEATH = -1603257, - SAY_BERSERK = -1603258, - SAY_YS_HELP = -1603259, -}; diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp deleted file mode 100644 index c61f1046474..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_razorscale.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: razorscale -SDAuthor: MaXiMiUS -SD%Complete: 65 -EndScriptData */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -//not in db -#define SAY_AGGRO -2000000 -#define SAY_KILL -2000001 -#define SAY_PHASE_2_TRANS -2000002 -#define SAY_PHASE_3_TRANS -2000003 -#define EMOTE_BREATH -2000004 - -enum Spells -{ - SPELL_FLAMEBUFFET = 64016, - SPELL_FIREBALL = 62796, - - SPELL_WINGBUFFET = 62666, - SPELL_FLAMEBREATH = 63317, - SPELL_FUSEARMOR = 64771, - SPELL_DEVOURINGFLAME = 63014 -}; - -enum Mobs -{ - NPC_DARK_RUNE_SENTINEL = 33846 -}; - -struct boss_razorscaleAI : public BossAI -{ - boss_razorscaleAI(Creature *pCreature) : BossAI(pCreature, TYPE_RAZORSCALE) {} - - uint8 Phase; - - uint32 FlameBreathTimer; - uint32 FuseArmorTimer; - uint32 DevouringFlameTimer; - uint32 FlameBuffetTimer; - uint32 SummonAddsTimer; - uint32 WingBuffetTimer; - uint32 FireballTimer; - //uint32 StunTimer; - //uint32 CastSpellsTimer; - - bool InitialSpawn; - bool IsFlying; - - void Reset() - { - Phase = 1; - - FlyPhase(Phase, 0); - - FlameBreathTimer = 20000; - DevouringFlameTimer = 2000; - FuseArmorTimer = 15000; - FlameBuffetTimer = 3000; - SummonAddsTimer = 45000; - WingBuffetTimer = 17000; - FireballTimer = 18000; - //StunTimer = 30000; - //CastSpellsTimer = 0; - - InitialSpawn = true; - IsFlying = true; - - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - } - - void JustDied(Unit* /*Killer*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetPositionY() > -60 || me->GetPositionX() < 450) // Not Blizzlike, anti-exploit to prevent players from pulling bosses to vehicles. - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(false); - me->GetMotionMaster()->MoveTargetedHome(); - } - - // Victim is not controlled by a player (should never happen) - if (me->getVictim() && !me->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) - me->Kill(me->getVictim()); - - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 99 && Phase == 1) // TODO: Only land (exit Phase 1) if brought down with harpoon guns! This is important! - { - Phase = 2; - DoScriptText(SAY_PHASE_2_TRANS, me); // Audio: "Move quickly! She won't remain grounded for long!" - } - - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 33 && Phase == 2) // Health under 33%, Razorscale can't fly anymore. - { - Phase = 3; - DoScriptText(SAY_PHASE_3_TRANS, me); // "Razorscale lands permanently!" - // TODO: Cast Devouring Flame on all harpoon guns simultaneously, briefly after Phase 3 starts (lasts until the harpoon guns are destroyed) - } - - /* - if (Phase == 2 && CastSpellsTimer > 0) // 5 seconds of spell casting, after stun breaks, during Phase 2 - { - if (CastSpellsTimer <= diff) // 5 seconds are up - Phase = 1; // Return to phase 1 - else - CastSpellsTimer -= diff; - }*/ - - FlyPhase(Phase, diff); - - if (Phase >= 2) // Ground Phase (Phase 3 = permanent ground phase) - { - if (FuseArmorTimer <= diff) - { - DoCastVictim(SPELL_FUSEARMOR); - FuseArmorTimer = 10000; - } else FuseArmorTimer -= diff; - - if (WingBuffetTimer <= diff) - { - DoCast(SPELL_WINGBUFFET); - WingBuffetTimer = urand(7000,14000); - } else WingBuffetTimer -= diff; - - if (FireballTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - { - me->SetInFront(pTarget); - DoCast(pTarget, SPELL_FIREBALL); - } - - FireballTimer = 18000; - } else FireballTimer -= diff; - - if (FlameBreathTimer <= diff) - { - DoScriptText(EMOTE_BREATH, me); // TODO: "Razorscale takes a deep breath..." - DoCastVictim(SPELL_FLAMEBREATH); - FlameBreathTimer = 15000; - WingBuffetTimer = 0; - } else FlameBreathTimer -= diff; - - if (Phase == 3) - { - if (FlameBuffetTimer <= diff) - { - DoScriptText(EMOTE_BREATH, me); - std::list pTargets; - SelectTargetList(pTargets, RAID_MODE(3,9), SELECT_TARGET_RANDOM, 100, true); - uint8 i = 0; - for (std::list::const_iterator itr = pTargets.begin(); itr != pTargets.end();) - { - if (me->HasInArc(M_PI, *itr)) - { - DoCast(*itr, SPELL_FLAMEBUFFET, true); - ++i; - } - if (++itr == pTargets.end() || i == RAID_MODE(3,9)) - { - AttackStart(*--itr); // seems to attack targets randomly during perma-ground phase.. - break; - } - } - FlameBuffetTimer = 25000; - } else FlameBuffetTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - else if (Phase == 1) //Flying Phase - { - if (InitialSpawn) - SummonAdds(); - - InitialSpawn = false; - - if (FireballTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - { - me->SetInFront(pTarget); - DoCast(pTarget, SPELL_FIREBALL); - } - - FireballTimer = 18000; - } else FireballTimer -= diff; - - if (DevouringFlameTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - { - me->SetInFront(pTarget); - DoCast(pTarget, SPELL_DEVOURINGFLAME); - } - - DevouringFlameTimer = 10000; - } else DevouringFlameTimer -= diff; - - if (SummonAddsTimer <= diff) - SummonAdds(); - else SummonAddsTimer -= diff; - } - } - - void SummonAdds() - { - // TODO: Adds will come in waves from mole machines. One mole can spawn a Dark Rune Watcher - // with 1-2 Guardians, or a lone Sentinel. Up to 4 mole machines can spawn adds at any given time. - uint8 random = urand(1,4); - for (uint8 i = 0; i < random; ++i) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true)) - { - float x = std::max(500.0f, std::min(650.0f, pTarget->GetPositionX() + irand(-20,20))); // Safe range is between 500 and 650 - float y = std::max(-235.0f, std::min(-145.0f, pTarget->GetPositionY() + irand(-20,20))); // Safe range is between -235 and -145 - float z = me->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); // Ground level - // TODO: Spawn drillers, then spawn adds 5 seconds later - if (Creature *pAdd = me->SummonCreature(NPC_DARK_RUNE_SENTINEL, x, y, z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)) - pAdd->AI()->AttackStart(pTarget); - } - } - SummonAddsTimer = 45000; - } - - void FlyPhase(uint8 Phase, const uint32 /*diff*/) - { - const float x = 587.54; - const float y = -174.92; - const float GroundLevel = me->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); - const float FlightHeight = GroundLevel + 4.0f; // TODO: Fly out of range of attacks (442 is sufficient height for this), minus ~(10*number of harpoon gun chains attached to Razorscale) - - if (Phase == 1) // Always flying during Phase 1 - IsFlying = true; - - me->SetFlying(IsFlying); - me->SendMovementFlagUpdate(); - me->SetSpeed(MOVE_WALK, IsFlying ? 7.0f : 2.5f, IsFlying); - - if (Phase == 1) // Flying Phase - { - if (me->GetPositionZ() > FlightHeight) // Correct height, stop moving - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - else // Incorrect height - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->GetMotionMaster()->MovePoint(0, x, y, FlightHeight + 0.5f); // Fly to slightly above (x, y, FlightHeight) - } - } - else // Ground Phases - { - const float CurrentGroundLevel = me->GetBaseMap()->GetHeight(me->GetPositionX(), me->GetPositionY(), MAX_HEIGHT); - //if (StunTimer == 30000) // Only fly around if not stunned. - //{ - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - if (IsFlying && me->GetPositionZ() > CurrentGroundLevel) // Fly towards the ground - me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), CurrentGroundLevel); - // TODO: Swoop up just before landing - else - IsFlying = false; // Landed, no longer flying - //} - - //if (!IsFlying &&Phase == 2 && CastSpellsTimer == 0 && StunTimer >= diff) // No longer flying, non-permanent ground phase, and not casting spells - //{ - // TODO: Add stun here. 30 second stun after Razorscale is grounded by harpoon guns - //StunTimer -= diff; - //} - //else if (StunTimer != 30000 && (StunTimer < 0 || Phase == 3)) // Stun is active, and needs to end. Note: Stun breaks instantly if Phase 3 starts - //{ - // TODO: Remove stun here. - //DoCast(SPELL_WINGBUFFET); // "Used in the beginning of the phase." - //WingBuffetTimer = urand(7000,14000); - //StunTimer = 30000; // Reinitialize the stun timer - //if (Phase == 2) // Non-permanent ground phase - // CastSpellsTimer = 5000; // Five seconds of casting before returning to Phase 1 - //} - } - } -}; - -CreatureAI* GetAI_boss_razorscale(Creature* pCreature) -{ - return new boss_razorscaleAI (pCreature); -} - -void AddSC_boss_razorscale() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_razorscale"; - newscript->GetAI = &GetAI_boss_razorscale; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp deleted file mode 100644 index bbab077e10e..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_thorim.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Yells -{ - SAY_AGGRO_1 = -1603270, - SAY_AGGRO_2 = -1603271, - SAY_SPECIAL_1 = -1603272, - SAY_SPECIAL_2 = -1603273, - SAY_SPECIAL_3 = -1603274, - SAY_JUMPDOWN = -1603275, - SAY_SLAY_1 = -1603276, - SAY_SLAY_2 = -1603277, - SAY_BERSERK = -1603278, - SAY_WIPE = -1603279, - SAY_DEATH = -1603280, - SAY_END_NORMAL_1 = -1603281, - SAY_END_NORMAL_2 = -1603282, - SAY_END_NORMAL_3 = -1603283, - SAY_END_HARD_1 = -1603284, - SAY_END_HARD_2 = -1603285, - SAY_END_HARD_3 = -1603286, - SAY_YS_HELP = -1603287, -}; - -struct boss_thorimAI : public BossAI -{ - boss_thorimAI(Creature* pCreature) : BossAI(pCreature, TYPE_THORIM) - { - } - - void Reset() - { - _Reset(); - } - - void EnterEvadeMode() - { - DoScriptText(SAY_WIPE, me); - _EnterEvadeMode(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2), me); - _EnterCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; -//SPELLS TODO: - -// - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_thorim(Creature* pCreature) -{ - return new boss_thorimAI(pCreature); -} - -void AddSC_boss_thorim() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_thorim"; - newscript->GetAI = &GetAI_boss_thorim; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp deleted file mode 100644 index 58123951d2f..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_xt002.cpp +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - TODO: - Add achievments - Boombot explosion only hurt allies to the npc at the moment - Boombot explosion visual - Test the enrage timer - Fix gravity bomb - tractor beam. - Fix void zone spell - If the boss is to close to a scrap pile -> no summon - make the life sparks visible... -*/ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Spells -{ - SPELL_TYMPANIC_TANTRUM = 62776, - SPELL_SEARING_LIGHT_10 = 63018, - SPELL_SEARING_LIGHT_25 = 65121, - - SPELL_GRAVITY_BOMB_10 = 63024, - SPELL_GRAVITY_BOMB_25 = 63234, - SPELL_GRAVITY_BOMB_AURA_10 = 63025, - SPELL_GRAVITY_BOMB_AURA_25 = 63233, - - SPELL_HEARTBREAK_10 = 65737, - SPELL_HEARTBREAK_25 = 64193, - - SPELL_ENRAGE = 26662, - - //------------------VOID ZONE-------------------- - SPELL_VOID_ZONE_10 = 64203, - SPELL_VOID_ZONE_25 = 64235, - - // Life Spark - SPELL_STATIC_CHARGED_10 = 64227, - SPELL_STATIC_CHARGED_25 = 64236, - SPELL_SHOCK = 64230, - - //----------------XT-002 HEART------------------- - SPELL_EXPOSED_HEART = 63849, - - //---------------XM-024 PUMMELLER---------------- - SPELL_ARCING_SMASH = 8374, - SPELL_TRAMPLE = 5568, - SPELL_UPPERCUT = 10966, - - //------------------BOOMBOT----------------------- - SPELL_BOOM = 62834, -}; - -enum Timers -{ - TIMER_TYMPANIC_TANTRUM_MIN = 32000, - TIMER_TYMPANIC_TANTRUM_MAX = 36000, - TIMER_SEARING_LIGHT = 20000, - TIMER_SPAWN_LIFE_SPARK = 9000, - TIMER_GRAVITY_BOMB = 20000, - TIMER_HEART_PHASE = 30000, - TIMER_ENRAGE = 600000, - TIMER_GRAVITY_BOMB_AURA = 8900, - - TIMER_VOID_ZONE = 3000, - - // Life Spark - TIMER_SHOCK = 12000, - - // Pummeller - // Timers may be off - TIMER_ARCING_SMASH = 27000, - TIMER_TRAMPLE = 22000, - TIMER_UPPERCUT = 17000, - - TIMER_SPAWN_ADD = 12000, -}; - -enum Creatures -{ - NPC_VOID_ZONE = 34001, - NPC_LIFE_SPARK = 34004, - NPC_XT002_HEART = 33329, - NPC_XS013_SCRAPBOT = 33343, - NPC_XM024_PUMMELLER = 33344, - NPC_XE321_BOOMBOT = 33346, -}; - -enum Actions -{ - ACTION_ENTER_HARD_MODE = 0, -}; - -enum XT002Data -{ - DATA_TRANSFERED_HEALTH = 0, -}; - -enum Yells -{ - SAY_AGGRO = -1603300, - SAY_HEART_OPENED = -1603301, - SAY_HEART_CLOSED = -1603302, - SAY_TYMPANIC_TANTRUM = -1603303, - SAY_SLAY_1 = -1603304, - SAY_SLAY_2 = -1603305, - SAY_BERSERK = -1603306, - SAY_DEATH = -1603307, - SAY_SUMMON = -1603308, -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 21027, -}; - -//#define GRAVITY_BOMB_DMG_MIN_10 11700 -//#define GRAVITY_BOMB_DMG_MAX_10 12300 -//#define GRAVITY_BOMB_DMG_MIN_25 14625 -//#define GRAVITY_BOMB_DMG_MAX_25 15375 -//#define GRAVITY_BOMB_RADIUS 12 - -//#define VOID_ZONE_DMG_10 5000 -//#define VOID_ZONE_DMG_25 7500 -//#define VOID_ZONE_RADIUS - - -/************************************************ ------------------SPAWN LOCATIONS----------------- -************************************************/ -//Shared Z-level -#define SPAWN_Z 412 -//Lower right -#define LR_X 796 -#define LR_Y -94 -//Lower left -#define LL_X 796 -#define LL_Y 57 -//Upper right -#define UR_X 890 -#define UR_Y -82 -//Upper left -#define UL_X 894 -#define UL_Y 62 - -/*------------------------------------------------------- - * - * XT-002 DECONSTRUCTOR - * - *///---------------------------------------------------- -struct boss_xt002_AI : public BossAI -{ - boss_xt002_AI(Creature *pCreature) : BossAI(pCreature, TYPE_XT002) - { - } - - uint32 uiSearingLightTimer; - uint32 uiSpawnLifeSparkTimer; - uint32 uiGravityBombTimer; - uint32 uiGravityBombAuraTimer; - uint32 uiTympanicTantrumTimer; - uint32 uiHeartPhaseTimer; - uint32 uiSpawnAddTimer; - uint32 uiEnrageTimer; - - bool searing_light_active; - uint64 uiSearingLightTarget; - - bool gravity_bomb_active; - uint64 uiGravityBombTarget; - - uint8 phase; - uint8 heart_exposed; - bool enraged; - - uint32 transferHealth; - bool enterHardMode; - bool hardMode; - - void Reset() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - - //Makes XT-002 to cast a light bomb 10 seconds after aggro. - uiSearingLightTimer = TIMER_SEARING_LIGHT/2; - uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; - uiGravityBombTimer = TIMER_GRAVITY_BOMB; - uiGravityBombAuraTimer = TIMER_GRAVITY_BOMB_AURA; - uiHeartPhaseTimer = TIMER_HEART_PHASE; - uiSpawnAddTimer = TIMER_SPAWN_ADD; - uiEnrageTimer = TIMER_ENRAGE; - - //Tantrum is casted a bit slower the first time. - uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX) * 2; - - searing_light_active = false; - gravity_bomb_active = false; - enraged = false; - hardMode = false; - enterHardMode = false; - - phase = 1; - heart_exposed = 0; - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - _EnterCombat(); - - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void DoAction(const int32 action) - { - switch (action) - { - case ACTION_ENTER_HARD_MODE: - if (!hardMode) - { - hardMode = true; - - // Enter hard mode - enterHardMode = true; - - // set max health - me->SetHealth(me->GetMaxHealth()); - - // Get his heartbreak buff - me->CastSpell(me, RAID_MODE(SPELL_HEARTBREAK_10, SPELL_HEARTBREAK_25), true); - } - break; - } - } - - void SetData(uint32 id, uint32 value) - { - switch(id) - { - case DATA_TRANSFERED_HEALTH: - transferHealth = value; - break; - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - _JustDied(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (enterHardMode) - { - SetPhaseOne(); - enterHardMode = false; - } - - // Handles spell casting. These spells only occur during phase 1 and hard mode - if (phase == 1 || hardMode) - { - if (uiSearingLightTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, RAID_MODE(SPELL_SEARING_LIGHT_10, SPELL_SEARING_LIGHT_25)); - uiSearingLightTarget = pTarget->GetGUID(); - } - uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; - if (hardMode) - searing_light_active = true; - uiSearingLightTimer = TIMER_SEARING_LIGHT; - } else uiSearingLightTimer -= diff; - - if (uiGravityBombTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, RAID_MODE(SPELL_GRAVITY_BOMB_10,SPELL_GRAVITY_BOMB_25)); - uiGravityBombTarget = pTarget->GetGUID(); - } - uiGravityBombTimer = TIMER_GRAVITY_BOMB; - gravity_bomb_active = true; - } else uiGravityBombTimer -= diff; - - if (uiTympanicTantrumTimer <= 0) - { - DoScriptText(SAY_TYMPANIC_TANTRUM, me); - DoCast(SPELL_TYMPANIC_TANTRUM); - uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX); - } else uiTympanicTantrumTimer -= diff; - } - - if (!hardMode) - { - if (phase == 1) - { - if (HealthBelowPct(75) && heart_exposed == 0) - { - exposeHeart(); - } - else if (HealthBelowPct(50) && heart_exposed == 1) - { - exposeHeart(); - } - else if (HealthBelowPct(25) && heart_exposed == 2) - { - exposeHeart(); - } - - DoMeleeAttackIfReady(); - } - else - { - //Stop moving - me->StopMoving(); - - //Start summoning adds - if (uiSpawnAddTimer <= diff) - { - DoScriptText(SAY_SUMMON, me); - - // Spawn Pummeller - switch (rand() % 4) - { - case 0: me->SummonCreature(NPC_XM024_PUMMELLER, LR_X, LR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 1: me->SummonCreature(NPC_XM024_PUMMELLER, LL_X, LL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 2: me->SummonCreature(NPC_XM024_PUMMELLER, UR_X, UR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 3: me->SummonCreature(NPC_XM024_PUMMELLER, UL_X, UL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - } - - // Spawn 5 Bombs - for (int8 n = 0; n < 5; n++) - { - //Some randomes are added so they wont spawn in a pile - switch(rand() % 4) - { - case 0: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(LR_X - 3, LR_X + 3), irand(LR_Y - 3, LR_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 1: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(LL_X - 3, LL_X + 3), irand(LL_Y - 3, LL_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 2: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(UR_X - 3, UR_X + 3), irand(UR_Y - 3, UR_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 3: me->SummonCreature(NPC_XS013_SCRAPBOT, irand(UL_X - 3, UL_X + 3), irand(UL_Y - 3, UL_Y + 3), SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - } - } - - //Spawn 5 Scrapbots - switch (rand() % 4) - { - case 0: me->SummonCreature(NPC_XE321_BOOMBOT, LR_X, LR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 1: me->SummonCreature(NPC_XE321_BOOMBOT, LL_X, LL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 2: me->SummonCreature(NPC_XE321_BOOMBOT, UR_X, UR_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - case 3: me->SummonCreature(NPC_XE321_BOOMBOT, UL_X, UL_Y, SPAWN_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); break; - } - - uiSpawnAddTimer = TIMER_SPAWN_ADD; - } else uiSpawnAddTimer -= diff; - - // Is the phase over? - if (uiHeartPhaseTimer <= diff) - { - DoScriptText(SAY_HEART_CLOSED, me); - SetPhaseOne(); - } - else - uiHeartPhaseTimer -= diff; - } - } - else - { - // Adding life sparks when searing light debuff runs out if hard mode - if (searing_light_active) - { - if (uiSpawnLifeSparkTimer <= diff) - { - if (Unit *pSearingLightTarget = me->GetUnit(*me, uiSearingLightTarget)) - pSearingLightTarget->SummonCreature(NPC_LIFE_SPARK, pSearingLightTarget->GetPositionX(), pSearingLightTarget->GetPositionY(), pSearingLightTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - uiSpawnLifeSparkTimer = TIMER_SPAWN_LIFE_SPARK; - searing_light_active = false; - } else uiSpawnLifeSparkTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - if (gravity_bomb_active) - { - if (uiGravityBombAuraTimer <= diff) - { - if (Unit *pGravityBombTarget = me->GetUnit(*me, uiGravityBombTarget)) - { - pGravityBombTarget->RemoveAurasDueToSpell(RAID_MODE(SPELL_GRAVITY_BOMB_10,SPELL_GRAVITY_BOMB_25)); - if (hardMode) - { - //Remains spawned for 3 minutes - pGravityBombTarget->SummonCreature(NPC_VOID_ZONE, pGravityBombTarget->GetPositionX(), pGravityBombTarget->GetPositionY(), pGravityBombTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); - } - } - - gravity_bomb_active = false; - uiGravityBombAuraTimer = TIMER_GRAVITY_BOMB_AURA; - //gravityBomb(); - } else uiGravityBombAuraTimer -= diff; - } - - //Enrage stuff - if (!enraged) - if (uiEnrageTimer <= diff) - { - DoScriptText(SAY_BERSERK, me); - DoCast(me, SPELL_ENRAGE); - enraged = true; - } else uiEnrageTimer -= diff; - } - - void exposeHeart() - { - //Make untargetable - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - - //Summon the heart npc - me->SummonCreature(NPC_XT002_HEART, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 7, 0, TEMPSUMMON_TIMED_DESPAWN, TIMER_HEART_PHASE); - - // Start "end of phase 2 timer" - uiHeartPhaseTimer = TIMER_HEART_PHASE; - - //Phase 2 has offically started - phase = 2; - heart_exposed++; - - //Reset the add spawning timer - uiSpawnAddTimer = TIMER_SPAWN_ADD; - - DoScriptText(SAY_HEART_OPENED, me); - } - - void SetPhaseOne() - { - uiSearingLightTimer = TIMER_SEARING_LIGHT / 2; - uiGravityBombTimer = TIMER_GRAVITY_BOMB; - uiTympanicTantrumTimer = urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX); - uiSpawnAddTimer = TIMER_SPAWN_ADD; - - if (!hardMode) - me->ModifyHealth(-((int32)transferHealth)); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - phase = 1; - } - - // TODO: put in comment and kept for reference. The spell should be fixed properly in spell system, if necessary. - ////Have to do this the custom way since the original spell messes up player movement - //void gravityBomb() - //{ - // uint32 maxDamage = RAID_MODE(GRAVITY_BOMB_DMG_MAX_10, GRAVITY_BOMB_DMG_MAX_25); - // uint32 minDamage = RAID_MODE(GRAVITY_BOMB_DMG_MIN_10, GRAVITY_BOMB_DMG_MIN_25); - // uint16 range = GRAVITY_BOMB_RADIUS; - // Map* pMap = me->GetMap(); - // if (pMap && pMap->IsDungeon()) - // { - // Map::PlayerList const &PlayerList = pMap->GetPlayers(); - // for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - // { - // //If a player is within the range of the spell - // if (i->getSource() && i->getSource()->GetDistance2d(pGravityBombTarget) <= range) - // { - // //Deal damage to the victim - // int32 damage = urand(minDamage, maxDamage); - // i->getSource()->ModifyHealth(-damage); - // me->SendSpellNonMeleeDamageLog(i->getSource(), SPELL_GRAVITY_BOMB_AURA_10, damage, SPELL_SCHOOL_MASK_SHADOW, 0, 0, false, 0); - - // //Replacing the tractor beam effect - // i->getSource()->JumpTo(pGravityBombTarget, 5); - // } - // } - // } - //} -}; - -CreatureAI* GetAI_boss_xt002(Creature* pCreature) -{ - return new boss_xt002_AI(pCreature); -} - -/*------------------------------------------------------- - * - * XT-002 HEART - * - *///---------------------------------------------------- -struct mob_xt002_heartAI : public ScriptedAI -{ - mob_xt002_heartAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_EXPOSED_HEART); - } - - ScriptedInstance* m_pInstance; - - void JustDied(Unit * /*victim*/) - { - if (m_pInstance) - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - if (pXT002->AI()) - pXT002->AI()->DoAction(ACTION_ENTER_HARD_MODE); - - //removes the aura - me->RemoveAurasDueToSpell(SPELL_EXPOSED_HEART); - } - - void DamageTaken(Unit * /*pDone*/, uint32 &damage) - { - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - if (pXT002->AI()) - { - uint32 health = me->GetHealth(); - health -= damage; - if (health < 0) - health = 0; - - pXT002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetMaxHealth() - health); - } - } -}; - -CreatureAI* GetAI_mob_xt002_heart(Creature* pCreature) -{ - return new mob_xt002_heartAI(pCreature); -} - -/*------------------------------------------------------- - * - * XS-013 SCRAPBOT - * - *///---------------------------------------------------- -struct mob_scrapbotAI : public ScriptedAI -{ - mob_scrapbotAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = me->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - me->GetMotionMaster()->MoveChase(pXT002); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - { - if (me->GetDistance2d(pXT002) <= 0.5) - { - // TODO Send raid message - - // Increase health with 1 percent - pXT002->ModifyHealth(pXT002->GetMaxHealth() * 0.01); - - // Despawns the scrapbot - me->ForcedDespawn(); - } - } - } -}; - -CreatureAI* GetAI_mob_scrapbot(Creature* pCreature) -{ - return new mob_scrapbotAI(pCreature); -} - -/*------------------------------------------------------- - * - * XM-024 PUMMELLER - * - *///---------------------------------------------------- -struct mob_pummellerAI : public ScriptedAI -{ - mob_pummellerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - int32 uiArcingSmashTimer; - int32 uiTrampleTimer; - int32 uiUppercutTimer; - - void Reset() - { - uiArcingSmashTimer = TIMER_ARCING_SMASH; - uiTrampleTimer = TIMER_TRAMPLE; - uiUppercutTimer = TIMER_UPPERCUT; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->IsWithinMeleeRange(me->getVictim())) - { - if (uiArcingSmashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCING_SMASH); - uiArcingSmashTimer = TIMER_ARCING_SMASH; - } else uiArcingSmashTimer -= diff; - - if (uiTrampleTimer <= diff) - { - DoCast(me->getVictim(), SPELL_TRAMPLE); - uiTrampleTimer = TIMER_TRAMPLE; - } else uiTrampleTimer -= diff; - - if (uiUppercutTimer <= diff) - { - DoCast(me->getVictim(), SPELL_UPPERCUT); - uiUppercutTimer = TIMER_UPPERCUT; - } else uiUppercutTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_pummeller(Creature* pCreature) -{ - return new mob_pummellerAI(pCreature); -} - -/*------------------------------------------------------- - * - * XE-321 BOOMBOT - * - *///---------------------------------------------------- -struct mob_boombotAI : public ScriptedAI -{ - mob_boombotAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - me->GetMotionMaster()->MoveChase(pXT002); - } - - void JustDied(Unit * /*killer*/) - { - DoCast(SPELL_BOOM); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (Creature* pXT002 = me->GetCreature(*me, m_pInstance->GetData64(TYPE_XT002))) - { - if (me->GetDistance2d(pXT002) <= 0.5) - { - //Explosion - DoCast(me, SPELL_BOOM); - - //Despawns the boombot - me->ForcedDespawn(); - } - } - } -}; - -CreatureAI* GetAI_mob_boombot(Creature* pCreature) -{ - return new mob_boombotAI(pCreature); -} - -/*------------------------------------------------------- - * - * VOID ZONE - * - *///---------------------------------------------------- -struct mob_void_zoneAI : public ScriptedAI -{ - mob_void_zoneAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - } - - ScriptedInstance* m_pInstance; - uint32 uiVoidZoneTimer; - - void Reset() - { - uiVoidZoneTimer = TIMER_VOID_ZONE; - } - - void UpdateAI(const uint32 diff) - { - if (uiVoidZoneTimer <= diff) - { - //voidZone(); - uiVoidZoneTimer = TIMER_VOID_ZONE; - } else uiVoidZoneTimer -= diff; - } - - // TODO: put in comment and kept for reference. The spell should be fixed properly in spell system, if necessary. - //void voidZone() - //{ - // Map* pMap = me->GetMap(); - // if (pMap && pMap->IsDungeon()) - // { - // Map::PlayerList const &PlayerList = pMap->GetPlayers(); - // for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - // { - // // If a player is within the range of the spell - // if (i->getSource() && i->getSource()->GetDistance2d(me) <= 16) - // { - // // Deal damage to the victim - // int32 damage = RAID_MODE(VOID_ZONE_DMG_10, VOID_ZONE_DMG_25); - // me->DealDamage(i->getSource(), damage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); - // } - // } - // } - //} -}; - -CreatureAI* GetAI_mob_void_zone(Creature* pCreature) -{ - return new mob_void_zoneAI(pCreature); -} - -/*------------------------------------------------------- - * - * LIFE SPARK - * - *///---------------------------------------------------- -struct mob_life_sparkAI : public ScriptedAI -{ - mob_life_sparkAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - uint32 uiShockTimer; - - void Reset() - { - DoCast(me, RAID_MODE(SPELL_STATIC_CHARGED_10, SPELL_STATIC_CHARGED_25)); - uiShockTimer = 0; // first one is immediate. - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiShockTimer <= diff) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - DoCast(me->getVictim(), SPELL_SHOCK); - uiShockTimer = TIMER_SHOCK; - } - } - else uiShockTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_life_spark(Creature* pCreature) -{ - return new mob_life_sparkAI(pCreature); -} - -void AddSC_boss_xt002() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_xt002"; - newscript->GetAI = &GetAI_boss_xt002; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_xt002_heart"; - newscript->GetAI = &GetAI_mob_xt002_heart; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_scrapbot"; - newscript->GetAI = &GetAI_mob_scrapbot; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_pummeller"; - newscript->GetAI = &GetAI_mob_pummeller; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_boombot"; - newscript->GetAI = &GetAI_mob_boombot; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_void_zone"; - newscript->GetAI = &GetAI_mob_void_zone; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_life_spark"; - newscript->GetAI = &GetAI_mob_life_spark; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp b/src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp deleted file mode 100644 index 8f42f289204..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/boss_yoggsaron.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum Sara_Yells -{ - SAY_SARA_PREFIGHT_1 = -1603310, - SAY_SARA_PREFIGHT_2 = -1603311, - SAY_SARA_AGGRO_1 = -1603312, - SAY_SARA_AGGRO_2 = -1603313, - SAY_SARA_AGGRO_3 = -1603314, - SAY_SARA_SLAY_1 = -1603315, - SAY_SARA_SLAY_2 = -1603316, - WHISP_SARA_INSANITY = -1603317, - SAY_SARA_PHASE2_1 = -1603318, - SAY_SARA_PHASE2_2 = -1603319, -}; - -enum YoggSaron_Yells -{ - SAY_PHASE2_1 = -1603330, - SAY_PHASE2_2 = -1603331, - SAY_PHASE2_3 = -1603332, - SAY_PHASE2_4 = -1603333, - SAY_PHASE2_5 = -1603334, - SAY_PHASE3 = -1603335, - SAY_VISION = -1603336, - SAY_SLAY_1 = -1603337, - SAY_SLAY_2 = -1603338, - WHISP_INSANITY_1 = -1603339, - WHISP_INSANITY_2 = -1603340, - SAY_DEATH = -1603341, -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 21001, -}; diff --git a/src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp deleted file mode 100644 index 692dbf72473..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/instance_ulduar.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "ulduar.h" - -enum eGameObjects -{ - GO_KOLOGARN_CHEST_HERO = 195047, - GO_KOLOGARN_CHEST = 195046, - GO_THORIM_CHEST_HERO = 194315, - GO_THORIM_CHEST = 194314, - GO_HODIR_CHEST_HERO = 194308, - GO_HODIR_CHEST = 194307, - GO_FREYA_CHEST_HERO = 194325, - GO_FREYA_CHEST = 194324, - GO_LEVIATHAN_DOOR = 194905, - GO_LEVIATHAN_GATE = 194630 -}; - -struct instance_ulduar : public ScriptedInstance -{ - instance_ulduar(Map* pMap) : ScriptedInstance(pMap) { Initialize(); }; - - uint32 uiEncounter[MAX_ENCOUNTER]; - std::string m_strInstData; - uint8 flag; - - uint64 uiLeviathanGUID; - uint64 uiIgnisGUID; - uint64 uiRazorscaleGUID; - uint64 uiXT002GUID; - uint64 uiAssemblyGUIDs[3]; - uint64 uiKologarnGUID; - uint64 uiAuriayaGUID; - uint64 uiMimironGUID; - uint64 uiHodirGUID; - uint64 uiThorimGUID; - uint64 uiFreyaGUID; - uint64 uiVezaxGUID; - uint64 uiYoggSaronGUID; - uint64 uiAlgalonGUID; - uint64 uiLeviathanDoor[7]; - uint64 uiLeviathanGateGUID; - - uint64 uiKologarnChestGUID; - uint64 uiThorimChestGUID; - uint64 uiHodirChestGUID; - uint64 uiFreyaChestGUID; - - void Initialize() - { - uiLeviathanGUID = 0; - uiIgnisGUID = 0; - uiRazorscaleGUID = 0; - uiXT002GUID = 0; - uiKologarnGUID = 0; - uiAuriayaGUID = 0; - uiMimironGUID = 0; - uiHodirGUID = 0; - uiThorimGUID = 0; - uiFreyaGUID = 0; - uiVezaxGUID = 0; - uiYoggSaronGUID = 0; - uiAlgalonGUID = 0; - uiKologarnChestGUID = 0; - uiKologarnChestGUID = 0; - uiHodirChestGUID = 0; - uiFreyaChestGUID = 0; - uiLeviathanGateGUID = 0; - flag = 0; - - memset(&uiEncounter, 0, sizeof(uiEncounter)); - memset(&uiAssemblyGUIDs, 0, sizeof(uiAssemblyGUIDs)); - memset(&uiLeviathanDoor, 0, sizeof(uiLeviathanDoor)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (uiEncounter[i] == IN_PROGRESS) - return true; - } - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_LEVIATHAN: - uiLeviathanGUID = pCreature->GetGUID(); - break; - case NPC_IGNIS: - uiIgnisGUID = pCreature->GetGUID(); - break; - case NPC_RAZORSCALE: - uiRazorscaleGUID = pCreature->GetGUID(); - break; - case NPC_XT002: - uiXT002GUID = pCreature->GetGUID(); - break; - - // Assembly of Iron - case NPC_STEELBREAKER: - uiAssemblyGUIDs[0] = pCreature->GetGUID(); - break; - case NPC_MOLGEIM: - uiAssemblyGUIDs[1] = pCreature->GetGUID(); - break; - case NPC_BRUNDIR: - uiAssemblyGUIDs[2] = pCreature->GetGUID(); - break; - - case NPC_KOLOGARN: - uiKologarnGUID = pCreature->GetGUID(); - break; - case NPC_AURIAYA: - uiAuriayaGUID = pCreature->GetGUID(); - break; - case NPC_MIMIRON: - uiMimironGUID = pCreature->GetGUID(); - break; - case NPC_HODIR: - uiHodirGUID = pCreature->GetGUID(); - break; - case NPC_THORIM: - uiThorimGUID = pCreature->GetGUID(); - break; - case NPC_FREYA: - uiFreyaGUID = pCreature->GetGUID(); - break; - case NPC_VEZAX: - uiVezaxGUID = pCreature->GetGUID(); - break; - case NPC_YOGGSARON: - uiYoggSaronGUID = pCreature->GetGUID(); - break; - case NPC_ALGALON: - uiAlgalonGUID = pCreature->GetGUID(); - break; - } - - } - - void OnGameObjectCreate(GameObject* pGO, bool add) - { - switch(pGO->GetEntry()) - { - case GO_KOLOGARN_CHEST_HERO: - case GO_KOLOGARN_CHEST: - uiKologarnChestGUID = add ? pGO->GetGUID() : NULL; - break; - case GO_THORIM_CHEST_HERO: - case GO_THORIM_CHEST: - uiThorimChestGUID = add ? pGO->GetGUID() : NULL; - break; - case GO_HODIR_CHEST_HERO: - case GO_HODIR_CHEST: - uiHodirChestGUID = add ? pGO->GetGUID() : NULL; - break; - case GO_FREYA_CHEST_HERO: - case GO_FREYA_CHEST: - uiFreyaChestGUID = add ? pGO->GetGUID() : NULL; - break; - case GO_LEVIATHAN_DOOR: - uiLeviathanDoor[flag] = pGO->GetGUID(); - HandleGameObject(NULL, true, pGO); - flag++; - if (flag == 7) - flag =0; - break; - case GO_LEVIATHAN_GATE: - uiLeviathanGateGUID = pGO->GetGUID(); - HandleGameObject(NULL, false, pGO); - break; - } - } - - void ProcessEvent(GameObject* pGO, uint32 uiEventId) - { - // Flame Leviathan's Tower Event triggers - Creature* pFlameLeviathan = instance->GetCreature(NPC_LEVIATHAN); - if (pFlameLeviathan && pFlameLeviathan->isAlive()) //No leviathan, no event triggering ;) - switch(uiEventId) - { - case EVENT_TOWER_OF_STORM_DESTROYED: - pFlameLeviathan->AI()->DoAction(1); - break; - case EVENT_TOWER_OF_FROST_DESTROYED: - pFlameLeviathan->AI()->DoAction(2); - break; - case EVENT_TOWER_OF_FLAMES_DESTROYED: - pFlameLeviathan->AI()->DoAction(3); - break; - case EVENT_TOWER_OF_NATURE_DESTROYED: - pFlameLeviathan->AI()->DoAction(4); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - if (type != TYPE_COLOSSUS) - uiEncounter[type] = data; - - switch(type) - { - /*case TYPE_IGNIS: - case TYPE_RAZORSCALE: - case TYPE_XT002: - case TYPE_ASSEMBLY: - case TYPE_AURIAYA: - case TYPE_MIMIRON: - case TYPE_VEZAX: - case TYPE_YOGGSARON: - break;*/ - case TYPE_LEVIATHAN: - if (data == IN_PROGRESS) - { - for (uint8 uiI = 0; uiI < 7; uiI++) - HandleGameObject(uiLeviathanDoor[uiI],false); - } - else - { - for (uint8 uiI = 0; uiI < 7; uiI++) - HandleGameObject(uiLeviathanDoor[uiI],true); - } - break; - case TYPE_KOLOGARN: - if (data == DONE) - if (GameObject* pGO = instance->GetGameObject(uiKologarnChestGUID)) - pGO->SetRespawnTime(pGO->GetRespawnDelay()); - break; - case TYPE_HODIR: - if (data == DONE) - if (GameObject* pGO = instance->GetGameObject(uiHodirChestGUID)) - pGO->SetRespawnTime(pGO->GetRespawnDelay()); - break; - case TYPE_THORIM: - if (data == DONE) - if (GameObject* pGO = instance->GetGameObject(uiThorimChestGUID)) - pGO->SetRespawnTime(pGO->GetRespawnDelay()); - break; - case TYPE_FREYA: - if (data == DONE) - if (GameObject* pGO = instance->GetGameObject(uiFreyaChestGUID)) - pGO->SetRespawnTime(pGO->GetRespawnDelay()); - break; - case TYPE_COLOSSUS: - if (data == 2) - { - if (Creature* pBoss = instance->GetCreature(uiLeviathanGUID)) - pBoss->AI()->DoAction(10); - if (GameObject* pGate = instance->GetGameObject(uiLeviathanGateGUID)) - pGate->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - } - break; - default: - break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - saveStream << uiEncounter[i] << " "; - - m_strInstData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case TYPE_LEVIATHAN: return uiLeviathanGUID; - case TYPE_IGNIS: return uiIgnisGUID; - case TYPE_RAZORSCALE: return uiRazorscaleGUID; - case TYPE_XT002: return uiXT002GUID; - case TYPE_KOLOGARN: return uiKologarnGUID; - case TYPE_AURIAYA: return uiAuriayaGUID; - case TYPE_MIMIRON: return uiMimironGUID; - case TYPE_HODIR: return uiMimironGUID; - case TYPE_THORIM: return uiThorimGUID; - case TYPE_FREYA: return uiFreyaGUID; - case TYPE_VEZAX: return uiVezaxGUID; - case TYPE_YOGGSARON: return uiYoggSaronGUID; - case TYPE_ALGALON: return uiAlgalonGUID; - - // Assembly of Iron - case DATA_STEELBREAKER: return uiAssemblyGUIDs[0]; - case DATA_MOLGEIM: return uiAssemblyGUIDs[1]; - case DATA_BRUNDIR: return uiAssemblyGUIDs[2]; - } - - return 0; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_LEVIATHAN: - case TYPE_IGNIS: - case TYPE_RAZORSCALE: - case TYPE_XT002: - case TYPE_ASSEMBLY: - case TYPE_KOLOGARN: - case TYPE_AURIAYA: - case TYPE_MIMIRON: - case TYPE_HODIR: - case TYPE_THORIM: - case TYPE_FREYA: - case TYPE_VEZAX: - case TYPE_YOGGSARON: - case TYPE_ALGALON: - case TYPE_COLOSSUS: - return uiEncounter[type]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "U U " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2] << " " << uiEncounter[3] - << uiEncounter[4] << " " << uiEncounter[5] << " " << uiEncounter[6] << " " << uiEncounter[7] - << uiEncounter[8] << " " << uiEncounter[9] << " " << uiEncounter[10] << " " << uiEncounter[11] - << uiEncounter[12] << " " << uiEncounter[13] << " " << uiEncounter[14]; - - m_strInstData = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return m_strInstData; - } - - void Load(const char* strIn) - { - if (!strIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(strIn); - - char dataHead1, dataHead2; - uint32 data0, data1, data2, data3, data4, data5, data6, - data7, data8, data9, data10, data11, data12, data13, data14; - - std::istringstream loadStream(strIn); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6 - >> data7 >> data8 >> data9 >> data10 >> data11 >> data12 >> data13 >> data14; - - if (dataHead1 == 'U' && dataHead2 == 'U') - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - loadStream >> uiEncounter[i]; - - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - } - } - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_ulduar(Map* pMap) -{ - return new instance_ulduar(pMap); -} - -void AddSC_instance_ulduar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_ulduar"; - newscript->GetInstanceData = &GetInstanceData_instance_ulduar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/ulduar/ulduar/ulduar.h b/src/server/scripts/Northrend/ulduar/ulduar/ulduar.h deleted file mode 100644 index cb11bcb579c..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/ulduar.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008 - 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_ULDUAR_H -#define DEF_ULDUAR_H - -enum eTypes -{ - MAX_ENCOUNTER = 15, - - TYPE_LEVIATHAN = 0, - TYPE_IGNIS = 1, - TYPE_RAZORSCALE = 2, - TYPE_XT002 = 3, - TYPE_ASSEMBLY = 4, - TYPE_KOLOGARN = 5, - TYPE_AURIAYA = 6, - TYPE_MIMIRON = 7, - TYPE_HODIR = 8, - TYPE_THORIM = 9, - TYPE_FREYA = 10, - TYPE_VEZAX = 11, - TYPE_YOGGSARON = 12, - TYPE_ALGALON = 13, - TYPE_COLOSSUS = 14, - - DATA_STEELBREAKER = 20, - DATA_MOLGEIM = 21, - DATA_BRUNDIR = 22, - DATA_RUNEMASTER_MOLGEIM = 23, - DATA_STORMCALLER_BRUNDIR = 24, - - NPC_LEVIATHAN = 33113, - NPC_IGNIS = 33118, - NPC_RAZORSCALE = 33186, - NPC_XT002 = 33293, - NPC_STEELBREAKER = 32867, - NPC_MOLGEIM = 32927, - NPC_BRUNDIR = 32857, - NPC_KOLOGARN = 32930, - NPC_AURIAYA = 33515, - NPC_MIMIRON = 33350, - NPC_HODIR = 32845, - NPC_THORIM = 32865, - NPC_FREYA = 32906, - NPC_VEZAX = 33271, - NPC_YOGGSARON = 33288, - NPC_ALGALON = 32871, - - EVENT_TOWER_OF_STORM_DESTROYED = 21031, - EVENT_TOWER_OF_FROST_DESTROYED = 21032, - EVENT_TOWER_OF_FLAMES_DESTROYED = 21033, - EVENT_TOWER_OF_NATURE_DESTROYED = 21030 -}; - -#endif diff --git a/src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp b/src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp deleted file mode 100644 index 44f9e86b69c..00000000000 --- a/src/server/scripts/Northrend/ulduar/ulduar/ulduar_teleporter.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "ScriptedPch.h" -#include "ulduar.h" - -/* -The teleporter appears to be active and stable. - -- Expedition Base Camp -- Formation Grounds -- Colossal Forge -- Scrapyard -- Antechamber of Ulduar -- Shattered Walkway -- Conservatory of Life -*/ - -#define BASE_CAMP 200 -#define GROUNDS 201 -#define FORGE 202 -#define SCRAPYARD 203 -#define ANTECHAMBER 204 -#define WALKWAY 205 -#define CONSERVATORY 206 - -bool GoHello_ulduar_teleporter(Player *pPlayer, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - if (!pInstance) return true; - - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Expedition Base Camp", GOSSIP_SENDER_MAIN, BASE_CAMP); - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Formation Grounds", GOSSIP_SENDER_MAIN, GROUNDS); - if (pInstance->GetData(TYPE_LEVIATHAN) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Colossal Forge", GOSSIP_SENDER_MAIN, FORGE); - if (pInstance->GetData(TYPE_XT002) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Scrapyard", GOSSIP_SENDER_MAIN, SCRAPYARD); - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Antechamber of Ulduar", GOSSIP_SENDER_MAIN, ANTECHAMBER); - if (pInstance->GetData(TYPE_KOLOGARN) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Shattered Walkway", GOSSIP_SENDER_MAIN, WALKWAY); - if (pInstance->GetData(TYPE_AURIAYA) == DONE) - pPlayer->ADD_GOSSIP_ITEM(0, "Teleport to the Conservatory of Life", GOSSIP_SENDER_MAIN, CONSERVATORY); - } - } - } - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pGO->GetGUID()); - - return true; -} - -bool GOSelect_ulduar_teleporter(Player *pPlayer, GameObject * /*pGO*/, uint32 sender, uint32 action) -{ - if (sender != GOSSIP_SENDER_MAIN) return true; - if (!pPlayer->getAttackers().empty()) return true; - - switch(action) - { - case BASE_CAMP: - pPlayer->TeleportTo(603, -706.122, -92.6024, 429.876, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case GROUNDS: - pPlayer->TeleportTo(603, 131.248, -35.3802, 409.804, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case FORGE: - pPlayer->TeleportTo(603, 553.233, -12.3247, 409.679, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case SCRAPYARD: - pPlayer->TeleportTo(603, 926.292, -11.4635, 418.595, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case ANTECHAMBER: - pPlayer->TeleportTo(603, 1498.09, -24.246, 420.967, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case WALKWAY: - pPlayer->TeleportTo(603, 1859.45, -24.1, 448.9, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - case CONSERVATORY: - pPlayer->TeleportTo(603, 2086.27, -24.3134, 421.239, 0); - pPlayer->CLOSE_GOSSIP_MENU(); break; - } - - return true; -} - -void AddSC_ulduar_teleporter() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "ulduar_teleporter"; - newscript->pGOHello = &GoHello_ulduar_teleporter; - newscript->pGOSelect = &GOSelect_ulduar_teleporter; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp deleted file mode 100644 index 77f824c48d5..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ingvar_The_Plunderer -SD%Complete: 95 -SDComment: Some Problems with Annhylde Movement, Blizzlike Timers -SDCategory: Udgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum Yells -{ - //Yells Ingvar - YELL_AGGRO_1 = -1574005, - YELL_AGGRO_2 = -1574006, - - YELL_DEAD_1 = -1574007, - YELL_DEAD_2 = -1574008, - - YELL_KILL_1 = -1574009, - YELL_KILL_2 = -1574010, -}; - -enum Creatures -{ - MOB_INGVAR_HUMAN = 23954, - MOB_ANNHYLDE_THE_CALLER = 24068, - MOB_INGVAR_UNDEAD = 23980, -}; - -enum Spells -{ - //Ingvar Spells human form - SPELL_CLEAVE = 42724, - SPELL_SMASH = 42669, - H_SPELL_SMASH = 59706, - SPELL_STAGGERING_ROAR = 42708, - H_SPELL_STAGGERING_ROAR = 59708, - SPELL_ENRAGE = 42705, - H_SPELL_ENRAGE = 59707, - - SPELL_INGVAR_FEIGN_DEATH = 42795, - SPELL_SUMMON_BANSHEE = 42912, - SPELL_SCOURG_RESURRECTION = 42863, // Spawn resurrect effect around Ingvar - - //Ingvar Spells undead form - SPELL_DARK_SMASH = 42723, - SPELL_DREADFUL_ROAR = 42729, - H_SPELL_DREADFUL_ROAR = 59734, - SPELL_WOE_STRIKE = 42730, - H_SPELL_WOE_STRIKE = 59735, - - ENTRY_THROW_TARGET = 23996, - SPELL_SHADOW_AXE_SUMMON = 42749 -}; - -struct boss_ingvar_the_plundererAI : public ScriptedAI -{ - boss_ingvar_the_plundererAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bIsUndead; - bool bEventInProgress; - - uint32 uiCleaveTimer; - uint32 uiSmashTimer; - uint32 uiEnrageTimer; - uint32 uiRoarTimer; - uint32 uiSpawnResTimer; - - void Reset() - { - if (bIsUndead) - me->UpdateEntry(MOB_INGVAR_HUMAN); - - bIsUndead = false; - bEventInProgress = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - - uiCleaveTimer = 2000; - uiSmashTimer = 5000; - uiEnrageTimer = 10000; - uiRoarTimer = 15000; - - uiSpawnResTimer = 3000; - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, NOT_STARTED); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth() && !bIsUndead) - { - //DoCast(me, SPELL_INGVAR_FEIGN_DEATH, true); // Dont work ??? - // visuel hack - me->SetHealth(0); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - // visuel hack end - - bEventInProgress = true; - bIsUndead = true; - - DoScriptText(YELL_DEAD_1,me); - } - - if (bEventInProgress) - { - damage = 0; - } - } - - void StartZombiePhase() - { - bIsUndead = true; - bEventInProgress = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->UpdateEntry(MOB_INGVAR_UNDEAD); - me->SetInCombatWith(me->getVictim()); - me->GetMotionMaster()->MoveChase(me->getVictim()); - - DoScriptText(YELL_AGGRO_2,me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO_1,me); - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(YELL_DEAD_2,me); - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - if (bIsUndead) - DoScriptText(YELL_KILL_1,me); - else - DoScriptText(YELL_KILL_2,me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (bEventInProgress) - { - if (uiSpawnResTimer) - if (uiSpawnResTimer <= diff) - { - DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position - // DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ? - uiSpawnResTimer = 0; - } else uiSpawnResTimer -= diff; - - return; - } - - if (uiCleaveTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me->getVictim(), SPELL_WOE_STRIKE); - else - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = rand()%5000 + 2000; - } - } else uiCleaveTimer -= diff; - - if (uiSmashTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me->getVictim(), SPELL_DARK_SMASH); - else - DoCast(me->getVictim(), SPELL_SMASH); - uiSmashTimer = 10000; - } - } else uiSmashTimer -= diff; - - if (!bIsUndead) - { - if (uiEnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - uiEnrageTimer = 10000; - } else uiEnrageTimer -= diff; - } else // In Undead form used to summon weapon - { - if (uiEnrageTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - // Spawn target for Axe - Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); - if (pTarget) - { - me->SummonCreature(ENTRY_THROW_TARGET,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,2000); - - DoCast(me, SPELL_SHADOW_AXE_SUMMON); - } - uiEnrageTimer = 30000; - } - } else uiEnrageTimer -= diff; - } - - if (uiRoarTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me, SPELL_DREADFUL_ROAR); - else - DoCast(me, SPELL_STAGGERING_ROAR); - uiRoarTimer = 10000; - } - } else uiRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ingvar_the_plunderer(Creature* pCreature) -{ - return new boss_ingvar_the_plundererAI(pCreature); -} - -enum eSpells -{ -//we don't have that text in db so comment it until we get this text -// YELL_RESSURECT = -1574025, - -//Spells for Annhylde - SPELL_SCOURG_RESURRECTION_HEAL = 42704, //Heal Max + DummyAura - SPELL_SCOURG_RESURRECTION_BEAM = 42857, //Channeling Beam of Annhylde - SPELL_SCOURG_RESURRECTION_DUMMY = 42862, //Some Emote Dummy? - SPELL_INGVAR_TRANSFORM = 42796 -}; - -struct mob_annhylde_the_callerAI : public ScriptedAI -{ - mob_annhylde_the_callerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - float x,y,z; - ScriptedInstance* pInstance; - uint32 uiResurectTimer; - uint32 uiResurectPhase; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_HOVER); - me->SetSpeed(MOVE_SWIM , 1.0f); - me->SetSpeed(MOVE_RUN , 1.0f); - me->SetSpeed(MOVE_WALK , 1.0f); - //me->SetSpeed(MOVE_FLIGHT , 1.0f); - - me->GetPosition(x,y,z); - DoTeleportTo(x+1,y,z+30); - - Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - me->GetMotionMaster()->MovePoint(1,x,y,z+15); - -// DoScriptText(YELL_RESSURECT,me); - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - Unit* ingvar = Unit::GetUnit((*me), pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - switch (id) - { - case 1: - ingvar->RemoveAura(SPELL_SUMMON_BANSHEE); - ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_DUMMY,true); - DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); - uiResurectTimer = 8000; - uiResurectPhase = 1; - break; - case 2: - me->SetVisibility(VISIBILITY_OFF); - me->DealDamage(me,me->GetHealth()); - me->RemoveCorpse(); - break; - } - } - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit * /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (uiResurectTimer) - if (uiResurectTimer <= diff) - { - if (uiResurectPhase == 1) - { - Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - ingvar->SetStandState(UNIT_STAND_STATE_STAND); - ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_HEAL,false); - } - uiResurectTimer = 3000; - uiResurectPhase = 2; - } - else if (uiResurectPhase == 2) - { - if (Creature* ingvar = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0)) - { - ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); - - if (boss_ingvar_the_plundererAI* pAI = CAST_AI(boss_ingvar_the_plundererAI, ingvar->AI())) - pAI->StartZombiePhase(); - - me->GetMotionMaster()->MovePoint(2,x+1,y,z+30); - ++uiResurectPhase; - uiResurectTimer = 0; - } - } - - } else uiResurectTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_annhylde_the_caller(Creature* pCreature) -{ - return new mob_annhylde_the_callerAI (pCreature); -} - -enum eShadowAxe -{ - SPELL_SHADOW_AXE_DAMAGE = 42750, - H_SPELL_SHADOW_AXE_DAMAGE = 59719 -}; - -struct mob_ingvar_throw_dummyAI : public ScriptedAI -{ - mob_ingvar_throw_dummyAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 uiDespawnTimer; - - void Reset() - { - Unit *pTarget = me->FindNearestCreature(ENTRY_THROW_TARGET,50); - if (pTarget) - { - DoCast(me, SPELL_SHADOW_AXE_DAMAGE); - float x,y,z; - pTarget->GetPosition(x,y,z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - } - uiDespawnTimer = 7000; - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit * /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (uiDespawnTimer <= diff) - { - me->DealDamage(me,me->GetHealth()); - me->RemoveCorpse(); - uiDespawnTimer = 0; - } else uiDespawnTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_ingvar_throw_dummy(Creature* pCreature) -{ - return new mob_ingvar_throw_dummyAI (pCreature); -} - -void AddSC_boss_ingvar_the_plunderer() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ingvar_the_plunderer"; - newscript->GetAI = &GetAI_boss_ingvar_the_plunderer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_annhylde_the_caller"; - newscript->GetAI = &GetAI_mob_annhylde_the_caller; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ingvar_throw_dummy"; - newscript->GetAI = &GetAI_mob_ingvar_throw_dummy; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp deleted file mode 100644 index d69f0eee846..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Prince_Keleseth -SD%Complete: 90 -SDComment: Needs Prince Movements, Needs adjustments to blizzlike timers, Needs Shadowbolt castbar, Needs right Ressurect Visual, Needs Some Heroic Spells -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum eEnums -{ - ACHIEVEMENT_ON_THE_ROCKS = 1919, - - SPELL_SHADOWBOLT = 43667, - SPELL_SHADOWBOLT_HEROIC = 59389, - SPELL_FROST_TOMB = 48400, - SPELL_FROST_TOMB_SUMMON = 42714, - SPELL_DECREPIFY = 42702, - SPELL_SCOURGE_RESSURRECTION = 42704, - CREATURE_FROSTTOMB = 23965, - CREATURE_SKELETON = 23970, - - SAY_AGGRO = -1574000, - SAY_FROST_TOMB = -1574001, - SAY_SKELETONS = -1574002, - SAY_KILL = -1574003, - SAY_DEATH = -1574004 -}; - -#define SKELETONSPAWN_Z 42.8668 - -float SkeletonSpawnPoint[5][5]= -{ - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, -}; - -float AttackLoc[3]={197.636, 194.046, 40.8164}; - -bool ShatterFrostTomb; // needed for achievement: On The Rocks(1919) - -struct mob_frost_tombAI : public ScriptedAI -{ - mob_frost_tombAI(Creature *c) : ScriptedAI(c) - { - FrostTombGUID = 0; - } - - uint64 FrostTombGUID; - - void SetPrisoner(Unit* uPrisoner) - { - FrostTombGUID = uPrisoner->GetGUID(); - } - - void Reset(){ FrostTombGUID = 0; } - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void JustDied(Unit *killer) - { - if (killer->GetGUID() != me->GetGUID()) - ShatterFrostTomb = true; - - if (FrostTombGUID) - { - Unit* FrostTomb = Unit::GetUnit((*me),FrostTombGUID); - if (FrostTomb) - FrostTomb->RemoveAurasDueToSpell(SPELL_FROST_TOMB); - } - } - - void UpdateAI(const uint32 /*diff*/) - { - Unit* temp = Unit::GetUnit((*me),FrostTombGUID); - if ((temp && temp->isAlive() && !temp->HasAura(SPELL_FROST_TOMB)) || !temp) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } -}; - -struct boss_kelesethAI : public ScriptedAI -{ - boss_kelesethAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 FrostTombTimer; - uint32 SummonSkeletonsTimer; - uint32 RespawnSkeletonsTimer; - uint32 ShadowboltTimer; - uint64 SkeletonGUID[5]; - bool Skeletons; - bool RespawnSkeletons; - - void Reset() - { - ShadowboltTimer = 0; - Skeletons = false; - - ShatterFrostTomb = false; - - ResetTimer(); - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (IsHeroic() && !ShatterFrostTomb) - { - AchievementEntry const *AchievOnTheRocks = GetAchievementStore()->LookupEntry(ACHIEVEMENT_ON_THE_ROCKS); - if (AchievOnTheRocks) - { - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievOnTheRocks); - } - } - } - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); - } - - void ResetTimer(uint32 inc = 0) - { - SummonSkeletonsTimer = 5000 + inc; - FrostTombTimer = 28000 + inc; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowboltTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - me->CastSpell(pTarget, DUNGEON_MODE(SPELL_SHADOWBOLT, SPELL_SHADOWBOLT_HEROIC), true); - ShadowboltTimer = 10000; - } else ShadowboltTimer -= diff; - - if (!Skeletons) - if ((SummonSkeletonsTimer <= diff)) - { - Creature* Skeleton; - DoScriptText(SAY_SKELETONS, me); - for (uint8 i = 0; i < 5; ++i) - { - Skeleton = me->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1] , SKELETONSPAWN_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); - if (Skeleton) - { - Skeleton->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Skeleton->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY() , me->GetPositionZ()); - Skeleton->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Skeleton); - } - } - Skeletons = true; - } else SummonSkeletonsTimer -= diff; - - if (FrostTombTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (pTarget->isAlive()) - { - //DoCast(pTarget, SPELL_FROST_TOMB_SUMMON, true); - if (Creature *pChains = me->SummonCreature(CREATURE_FROSTTOMB, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) - { - CAST_AI(mob_frost_tombAI, pChains->AI())->SetPrisoner(pTarget); - pChains->CastSpell(pTarget, SPELL_FROST_TOMB, true); - - DoScriptText(SAY_FROST_TOMB, me); - } - } - FrostTombTimer = 15000; - } else FrostTombTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_vrykul_skeletonAI : public ScriptedAI -{ - mob_vrykul_skeletonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 Respawn_Time; - uint64 Target_Guid; - uint32 Decrepify_Timer; - - bool isDead; - - void Reset() - { - Respawn_Time = 12000; - Decrepify_Timer = urand(10000,20000); - isDead = false; - } - - void EnterCombat(Unit * /*who*/){} - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() == me->GetGUID()) - return; - - if (damage >= me->GetHealth()) - { - PretendToDie(); - damage = 0; - } - } - - void PretendToDie() - { - isDead = true; - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - }; - - void Resurrect() - { - isDead = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_SCOURGE_RESSURRECTION, true); - - if (me->getVictim()) - { - me->GetMotionMaster()->MoveChase(me->getVictim()); - me->AI()->AttackStart(me->getVictim()); - } - else - me->GetMotionMaster()->Initialize(); - }; - - void UpdateAI(const uint32 diff) - { - if (pInstance && pInstance->GetData(DATA_PRINCEKELESETH_EVENT) == IN_PROGRESS) - { - if (isDead) - { - if (Respawn_Time <= diff) - { - Resurrect(); - Respawn_Time = 12000; - } else Respawn_Time -= diff; - } - else - { - if (!UpdateVictim()) - return; - - if (Decrepify_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DECREPIFY); - Decrepify_Timer = 30000; - } else Decrepify_Timer -= diff; - - DoMeleeAttackIfReady(); - } - }else - { - if (me->isAlive()) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - } -}; - -CreatureAI* GetAI_mob_frost_tomb(Creature* pCreature) -{ - return new mob_frost_tombAI(pCreature); -} - -CreatureAI* GetAI_boss_keleseth(Creature* pCreature) -{ - return new boss_kelesethAI (pCreature); -} - -CreatureAI* GetAI_mob_vrykul_skeleton(Creature* pCreature) -{ - return new mob_vrykul_skeletonAI (pCreature); -} - -void AddSC_boss_keleseth() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_keleseth"; - newscript->GetAI = &GetAI_boss_keleseth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frost_tomb"; - newscript->GetAI = &GetAI_mob_frost_tomb; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_vrykul_skeleton"; - newscript->GetAI = &GetAI_mob_vrykul_skeleton; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp deleted file mode 100644 index 2146d37635b..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Skarvald_Dalronn -SD%Complete: 95 -SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum eEnums -{ - //signed for 24200, but used by 24200,27390 - YELL_SKARVALD_AGGRO = -1574011, - YELL_SKARVALD_DAL_DIED = -1574012, - YELL_SKARVALD_SKA_DIEDFIRST = -1574013, - YELL_SKARVALD_KILL = -1574014, - YELL_SKARVALD_DAL_DIEDFIRST = -1574015, - - //signed for 24201, but used by 24201,27389 - YELL_DALRONN_AGGRO = -1574016, - YELL_DALRONN_SKA_DIED = -1574017, - YELL_DALRONN_DAL_DIEDFIRST = -1574018, - YELL_DALRONN_KILL = -1574019, - YELL_DALRONN_SKA_DIEDFIRST = -1574020, - -//Spells of Skarvald and his Ghost - MOB_SKARVALD_THE_CONSTRUCTOR = 24200, - SPELL_CHARGE = 43651, - SPELL_STONE_STRIKE = 48583, - SPELL_SUMMON_SKARVALD_GHOST = 48613, - MOB_SKARVALD_GHOST = 27390, -//Spells of Dalronn and his Ghost - MOB_DALRONN_THE_CONTROLLER = 24201, - SPELL_SHADOW_BOLT = 43649, - H_SPELL_SHADOW_BOLT = 59575, - H_SPELL_SUMMON_SKELETONS = 52611, - SPELL_DEBILITATE = 43650, - SPELL_SUMMON_DALRONN_GHOST = 48612, - MOB_DALRONN_GHOST = 27389 -}; - -struct boss_skarvald_the_constructorAI : public ScriptedAI -{ - boss_skarvald_the_constructorAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool ghost; - uint32 Charge_Timer; - uint32 StoneStrike_Timer; - uint32 Response_Timer; - uint32 Check_Timer; - bool Dalronn_isDead; - - void Reset() - { - Charge_Timer = 5000; - StoneStrike_Timer = 10000; - Dalronn_isDead = false; - Check_Timer = 5000; - - ghost = (me->GetEntry() == MOB_SKARVALD_GHOST); - if (!ghost && pInstance) - { - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn && dalronn->isDead()) - CAST_CRE(dalronn)->Respawn(); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit * who) - { - if (!ghost && pInstance) - { - DoScriptText(YELL_SKARVALD_AGGRO,me); - - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn && dalronn->isAlive() && !dalronn->getVictim()) - dalronn->getThreatManager().addThreat(who,0.0f); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* Killer) - { - if (!ghost && pInstance) - { - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn) - { - if (dalronn->isDead()) - { - DoScriptText(YELL_SKARVALD_DAL_DIED,me); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); - } - else - { - DoScriptText(YELL_SKARVALD_SKA_DIEDFIRST,me); - - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true); - Creature* temp = me->SummonCreature(MOB_SKARVALD_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); - if (temp) - { - temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - temp->AI()->AttackStart(Killer); - } - } - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - if (!ghost) - { - DoScriptText(YELL_SKARVALD_KILL,me); - } - } - - void UpdateAI(const uint32 diff) - { - if (ghost) - { - if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (!UpdateVictim()) - return; - - if (!ghost) - { - if (Check_Timer) - if (Check_Timer <= diff) - { - Check_Timer = 5000; - Unit* dalronn = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_DALRONN) : 0); - if (dalronn && dalronn->isDead()) - { - Dalronn_isDead = true; - Response_Timer = 2000; - Check_Timer = 0; - } - } else Check_Timer -= diff; - - if (Response_Timer) - if (Dalronn_isDead) - if (Response_Timer <= diff) - { - DoScriptText(YELL_SKARVALD_DAL_DIEDFIRST,me); - - Response_Timer = 0; - } else Response_Timer -= diff; - } - - if (Charge_Timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE); - Charge_Timer = 5000+rand()%5000; - } else Charge_Timer -= diff; - - if (StoneStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STONE_STRIKE); - StoneStrike_Timer = 5000+rand()%5000; - } else StoneStrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_skarvald_the_constructor(Creature* pCreature) -{ - return new boss_skarvald_the_constructorAI (pCreature); -} - -struct boss_dalronn_the_controllerAI : public ScriptedAI -{ - boss_dalronn_the_controllerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool ghost; - uint32 ShadowBolt_Timer; - uint32 Debilitate_Timer; - uint32 Summon_Timer; - - uint32 Response_Timer; - uint32 Check_Timer; - uint32 AggroYell_Timer; - bool Skarvald_isDead; - - void Reset() - { - ShadowBolt_Timer = 1000; - Debilitate_Timer = 5000; - Summon_Timer = 10000; - Check_Timer = 5000; - Skarvald_isDead = false; - AggroYell_Timer = 0; - - ghost = me->GetEntry() == MOB_DALRONN_GHOST; - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald && skarvald->isDead()) - CAST_CRE(skarvald)->Respawn(); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit * who) - { - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald && skarvald->isAlive() && !skarvald->getVictim()) - skarvald->getThreatManager().addThreat(who,0.0f); - - AggroYell_Timer = 5000; - - if (pInstance) - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* Killer) - { - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald) - if (skarvald->isDead()) - { - DoScriptText(YELL_DALRONN_SKA_DIED,me); - - if (pInstance) - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); - } - else - { - DoScriptText(YELL_DALRONN_DAL_DIEDFIRST,me); - - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true); - Creature* temp = me->SummonCreature(MOB_DALRONN_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); - if (temp) - { - temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - temp->AI()->AttackStart(Killer); - } - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - if (!ghost) - { - DoScriptText(YELL_DALRONN_KILL,me); - } - } - - void UpdateAI(const uint32 diff) - { - if (ghost) - { - if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (!UpdateVictim()) - return; - - if (AggroYell_Timer) - if (AggroYell_Timer <= diff) - { - DoScriptText(YELL_DALRONN_AGGRO,me); - - AggroYell_Timer = 0; - } else AggroYell_Timer -= diff; - - if (!ghost) - { - if (Check_Timer) - if (Check_Timer <= diff) - { - Check_Timer = 5000; - Unit* skarvald = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SKARVALD) : 0); - if (skarvald && skarvald->isDead()) - { - Skarvald_isDead = true; - Response_Timer = 2000; - Check_Timer = 0; - } - } else Check_Timer -= diff; - - if (Response_Timer) - if (Skarvald_isDead) - if (Response_Timer <= diff) - { - DoScriptText(YELL_DALRONN_SKA_DIEDFIRST,me); - - Response_Timer = 0; - } else Response_Timer -= diff; - } - - if (ShadowBolt_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOW_BOLT); - ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells - } - } else ShadowBolt_Timer -= diff; - - if (Debilitate_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DEBILITATE); - Debilitate_Timer = 5000+rand()%5000; - } - } else Debilitate_Timer -= diff; - - if (IsHeroic()) - if (Summon_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, H_SPELL_SUMMON_SKELETONS); - Summon_Timer = (rand()%10000) + 20000; - } - } else Summon_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_dalronn_the_controller(Creature* pCreature) -{ - return new boss_dalronn_the_controllerAI (pCreature); -} - -void AddSC_boss_skarvald_dalronn() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_skarvald_the_constructor"; - newscript->GetAI = &GetAI_boss_skarvald_the_constructor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_dalronn_the_controller"; - newscript->GetAI = &GetAI_boss_dalronn_the_controller; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp deleted file mode 100644 index 03f97b1d27e..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Utgarde_Keep -SD%Complete: 90 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Utgarde Keep Scripts -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -#define MAX_ENCOUNTER 3 - -#define ENTRY_BELLOW_1 186688 -#define ENTRY_BELLOW_2 186689 -#define ENTRY_BELLOW_3 186690 - -#define ENTRY_FORGEFIRE_1 186692 -#define ENTRY_FORGEFIRE_2 186693 -#define ENTRY_FORGEFIRE_3 186691 - -#define ENTRY_GLOWING_ANVIL_1 186609 -#define ENTRY_GLOWING_ANVIL_2 186610 -#define ENTRY_GLOWING_ANVIL_3 186611 - -#define ENTRY_GIANT_PORTCULLIS_1 186756 -#define ENTRY_GIANT_PORTCULLIS_2 186694 - -/* Utgarde Keep encounters: -0 - Prince Keleseth -1 - Skarvald Dalronn -2 - Ingvar the Plunderer -*/ - -struct instance_utgarde_keep : public ScriptedInstance -{ - instance_utgarde_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 Keleseth; - uint64 Skarvald; - uint64 Dalronn; - uint64 Ingvar; - - uint64 forge_bellow[3]; - uint64 forge_fire[3]; - uint64 forge_anvil[3]; - uint64 portcullis[2]; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 forge_event[3]; - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Keleseth = 0; - Skarvald = 0; - Dalronn = 0; - Ingvar = 0; - - for (uint8 i = 0; i < 3; ++i) - { - forge_bellow[i] = 0; - forge_fire[i] = 0; - forge_anvil[i] = 0; - forge_event[i] = NOT_STARTED; - } - - portcullis[0] = 0; - portcullis[1] = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - - debug_log("TSCR: Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 23953: Keleseth = pCreature->GetGUID(); break; - case 24201: Dalronn = pCreature->GetGUID(); break; - case 24200: Skarvald = pCreature->GetGUID(); break; - case 23954: Ingvar = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - //door and object id - case ENTRY_BELLOW_1: forge_bellow[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_BELLOW_2: forge_bellow[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_BELLOW_3: forge_bellow[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_1: forge_fire[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_2: forge_fire[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_3: forge_fire[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_1: forge_anvil[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_2: forge_anvil[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_3: forge_anvil[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GIANT_PORTCULLIS_1: portcullis[0] = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GIANT_PORTCULLIS_2: portcullis[1] = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_PRINCEKELESETH: return Keleseth; - case DATA_DALRONN: return Dalronn; - case DATA_SKARVALD: return Skarvald; - case DATA_INGVAR: return Ingvar; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_PRINCEKELESETH_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_SKARVALD_DALRONN_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_INGVAR_EVENT: - if (data == DONE) - { - HandleGameObject(portcullis[0], true); - HandleGameObject(portcullis[1], true); - } - m_auiEncounter[2] = data; - break; - case EVENT_FORGE_1: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[0],false); - HandleGameObject(forge_fire[0],false); - HandleGameObject(forge_anvil[0],false); - }else - { - HandleGameObject(forge_bellow[0],true); - HandleGameObject(forge_fire[0],true); - HandleGameObject(forge_anvil[0],true); - } - forge_event[0] = data; - break; - case EVENT_FORGE_2: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[1],false); - HandleGameObject(forge_fire[1],false); - HandleGameObject(forge_anvil[1],false); - }else - { - HandleGameObject(forge_bellow[1],true); - HandleGameObject(forge_fire[1],true); - HandleGameObject(forge_anvil[1],true); - } - forge_event[1] = data; - break; - case EVENT_FORGE_3: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[2],false); - HandleGameObject(forge_fire[2],false); - HandleGameObject(forge_anvil[2],false); - }else - { - HandleGameObject(forge_bellow[2],true); - HandleGameObject(forge_fire[2],true); - HandleGameObject(forge_anvil[2],true); - } - forge_event[2] = data; - break; - } - - if (data == DONE) - { - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_PRINCEKELESETH_EVENT: return m_auiEncounter[0]; - case DATA_SKARVALD_DALRONN_EVENT: return m_auiEncounter[1]; - case DATA_INGVAR_EVENT: return m_auiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "U K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << forge_event[0] << " " << forge_event[1] << " " << forge_event[2]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; - - if (dataHead1 == 'U' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - forge_event[0] = data3; - forge_event[1] = data4; - forge_event[2] = data5; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_utgarde_keep(Map* pMap) -{ - return new instance_utgarde_keep(pMap); -} - -void AddSC_instance_utgarde_keep() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_utgarde_keep"; - newscript->GetInstanceData = &GetInstanceData_instance_utgarde_keep; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp deleted file mode 100644 index 95825aa49b6..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -uint32 entry_search[3] = -{ - 186609, - 186610, - 186611 -}; - -struct npc_dragonflayer_forge_masterAI : public ScriptedAI -{ - npc_dragonflayer_forge_masterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - fm_Type = 0; - } - - ScriptedInstance* pInstance; - uint8 fm_Type; - - void Reset() - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - CheckForge(); - } - - void CheckForge() - { - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,me->isAlive() ? NOT_STARTED : DONE); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,me->isAlive() ? NOT_STARTED : DONE); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,me->isAlive() ? NOT_STARTED : DONE); - break; - } - } - } - - void JustDied(Unit * /*killer*/) - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,DONE); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,DONE); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,DONE); - break; - } - } - } - - void EnterCombat(Unit * /*who*/) - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,IN_PROGRESS); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,IN_PROGRESS); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,IN_PROGRESS); - break; - } - } - me->SetUInt32Value(UNIT_NPC_EMOTESTATE ,EMOTE_ONESHOT_NONE); - } - - uint8 GetForgeMasterType() - { - float diff = 30.0f; - int near_f = 0; - - for (uint8 i = 0; i < 3 ; ++i) - { - GameObject* temp; - temp = me->FindNearestGameObject(entry_search[i],30); - if (temp) - { - if (me->IsWithinDist(temp,diff,false)) - { - near_f = i + 1; - diff = me->GetDistance2d(temp); - - } - } - } - - switch (near_f) - { - case 1: return 1; - case 2: return 2; - case 3: return 3; - default: return 0; - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (fm_Type == 0) - fm_Type = GetForgeMasterType(); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_dragonflayer_forge_master(Creature* pCreature) -{ - return new npc_dragonflayer_forge_masterAI(pCreature); -} - -void AddSC_utgarde_keep() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_dragonflayer_forge_master"; - newscript->GetAI = &GetAI_npc_dragonflayer_forge_master; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h b/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h deleted file mode 100644 index b630e156564..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_keep/utgarde_keep.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_UTGARDE_KEEP_H -#define DEF_UTGARDE_KEEP_H - -#define DATA_PRINCEKELESETH 1 -#define DATA_SKARVALD 3 -#define DATA_DALRONN 4 -#define DATA_INGVAR 6 - -#define DATA_PRINCEKELESETH_EVENT 2 -#define DATA_SKARVALD_DALRONN_EVENT 5 -#define DATA_INGVAR_EVENT 7 - -#define EVENT_FORGE_1 8 -#define EVENT_FORGE_2 9 -#define EVENT_FORGE_3 10 - -#endif diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp deleted file mode 100644 index 297fe37b7d8..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp +++ /dev/null @@ -1,830 +0,0 @@ -/* Script Data Start -SDName: Boss palehoof -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_palehoof' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_ARCING_SMASH = 48260, - SPELL_IMPALE = 48261, - H_SPELL_IMPALE = 59268, - SPELL_WITHERING_ROAR = 48256, - H_SPELL_WITHERING_ROAR = 59267, - SPELL_FREEZE = 16245 -}; - -//Orb spells -enum OrbSpells -{ - SPELL_ORB_VISUAL = 48044, - SPELL_ORB_CHANNEL = 48048 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1575000, - SAY_SLAY_1 = -1575001, - SAY_SLAY_2 = -1575002, - SAY_DEATH = -1575003 -}; - -enum Creatures -{ - MOB_STASIS_CONTROLLER = 26688 -}; - -struct Locations -{ - float x, y, z; -}; - -struct Locations moveLocs[]= -{ - {261.6,-449.3,109.5}, - {263.3,-454.0,109.5}, - {291.5,-450.4,109.5}, - {291.5,-454.0,109.5}, - {310.0,-453.4,109.5}, - {238.6,-460.7,109.5} -}; - -enum Phase -{ - PHASE_FRENZIED_WORGEN, - PHASE_RAVENOUS_FURLBORG, - PHASE_MASSIVE_JORMUNGAR, - PHASE_FEROCIOUS_RHINO, - PHASE_GORTOK_PALEHOOF, - PHASE_NONE -}; - -struct boss_palehoofAI : public ScriptedAI -{ - boss_palehoofAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiArcingSmashTimer; - uint32 uiImpaleTimer; - uint32 uiWhiteringRoarTimer; - uint32 uiWaitingTimer; - Phase currentPhase; - uint8 AddCount; - bool DoneAdds[4]; - - ScriptedInstance *pInstance; - - void Reset() - { - uiArcingSmashTimer = 15000; - uiImpaleTimer = 12000; - uiWhiteringRoarTimer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - for (uint32 i=0;i<4;i++) - DoneAdds[i]=false; - AddCount=0; - - currentPhase=PHASE_NONE; - - if (pInstance) - { - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, NOT_STARTED); - - Creature* pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GORTOK_PALEHOOF_SPHERE)); - if (pGo) - { - pGo->SetGoState(GO_STATE_READY); - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void UpdateAI(const uint32 diff) - { - if (currentPhase != PHASE_GORTOK_PALEHOOF) - return; - //Return since we have no target - if (!UpdateVictim()) - return; - - Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->DisappearAndDie(); - - if (uiArcingSmashTimer <= diff) - { - DoCast(me, SPELL_ARCING_SMASH); - uiArcingSmashTimer = urand(13000,17000); - } else uiArcingSmashTimer -= diff; - - if (uiImpaleTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_IMPALE); - uiImpaleTimer = urand(8000,12000); - } else uiImpaleTimer -= diff; - - if (uiWhiteringRoarTimer <= diff) - { - DoCast(me, SPELL_WITHERING_ROAR); - uiWhiteringRoarTimer = urand(8000,12000); - } else uiWhiteringRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, DONE); - Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->DisappearAndDie(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void NextPhase() - { - if (currentPhase == PHASE_NONE) - { - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); - me->SummonCreature(MOB_STASIS_CONTROLLER,moveLocs[5].x,moveLocs[5].y,moveLocs[5].z,0,TEMPSUMMON_CORPSE_DESPAWN); - } - Phase move = PHASE_NONE; - if (AddCount >= DUNGEON_MODE(2,4)) - move = PHASE_GORTOK_PALEHOOF; - else - { - //select random not yet defeated add - uint8 next = urand(0,3); - for (uint8 i=0; i < 16; i++) - { - if (!DoneAdds[i%4] && next == 0) - { - move = (Phase)(i%4); - break; - } else if (!DoneAdds[i%4] && next > 0) - --next; - } - ++AddCount; - DoneAdds[move] = true; - move = (Phase)(move%4); - } - //send orb to summon spot - Creature *pOrb = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pOrb && pOrb->isAlive()) - { - if (currentPhase == PHASE_NONE) - pOrb->CastSpell(me,SPELL_ORB_VISUAL,true); - pOrb->GetMotionMaster()->MovePoint(move,moveLocs[move].x,moveLocs[move].y,moveLocs[move].z); - } - currentPhase = move; - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_boss_palehoof(Creature* pCreature) -{ - return new boss_palehoofAI (pCreature); -} - -//ravenous furbolg's spells -enum RavenousSpells -{ - SPELL_CHAIN_LIGHTING = 48140, - H_SPELL_CHAIN_LIGHTING = 59273, - SPELL_CRAZED = 48139, - SPELL_TERRIFYING_ROAR = 48144 -}; - -struct mob_ravenous_furbolgAI : public ScriptedAI -{ - mob_ravenous_furbolgAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiChainLightingTimer; - uint32 uiCrazedTimer; - uint32 uiTerrifyingRoarTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiChainLightingTimer = 5000; - uiCrazedTimer = 10000; - uiTerrifyingRoarTimer = 15000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiChainLightingTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTING); - uiChainLightingTimer = 5000 + rand()%5000; - } else uiChainLightingTimer -= diff; - - if (uiCrazedTimer <= diff) - { - DoCast(me, SPELL_CRAZED); - uiCrazedTimer = 8000 + rand()%4000; - } else uiCrazedTimer -= diff; - - if (uiTerrifyingRoarTimer <= diff) - { - DoCast(me, SPELL_TERRIFYING_ROAR); - uiTerrifyingRoarTimer = 10000 + rand()%10000; - } else uiTerrifyingRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_ravenous_furbolg(Creature* pCreature) -{ - return new mob_ravenous_furbolgAI (pCreature); -} - -//frenzied worgen's spells -enum FrenziedSpells -{ - SPELL_MORTAL_WOUND = 48137, - H_SPELL_MORTAL_WOUND = 59265, - SPELL_ENRAGE_1 = 48138, - SPELL_ENRAGE_2 = 48142 -}; - -struct mob_frenzied_worgenAI : public ScriptedAI -{ - mob_frenzied_worgenAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiMortalWoundTimer; - uint32 uiEnrage1Timer; - uint32 uiEnrage2Timer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiMortalWoundTimer = 5000; - uiEnrage1Timer = 15000; - uiEnrage2Timer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiMortalWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - uiMortalWoundTimer = 3000 + rand()%4000; - } else uiMortalWoundTimer -= diff; - - if (uiEnrage1Timer <= diff) - { - DoCast(me, SPELL_ENRAGE_1); - uiEnrage1Timer = 15000; - } else uiEnrage1Timer -= diff; - - if (uiEnrage2Timer <= diff) - { - DoCast(me, SPELL_ENRAGE_2); - uiEnrage2Timer = 10000; - } else uiEnrage2Timer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - if (pInstance) - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance->GetData64(DATA_GORTOK_PALEHOOF)); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_frenzied_worgen(Creature* pCreature) -{ - return new mob_frenzied_worgenAI (pCreature); -} - -//ferocious rhino's spells -enum FerociousSpells -{ - SPELL_GORE = 48130, - H_SPELL_GORE = 59264, - SPELL_GRIEVOUS_WOUND = 48105, - H_SPELL_GRIEVOUS_WOUND = 59263, - SPELL_STOMP = 48131 -}; - -struct mob_ferocious_rhinoAI : public ScriptedAI -{ - mob_ferocious_rhinoAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiStompTimer; - uint32 uiGoreTimer; - uint32 uiGrievousWoundTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiStompTimer = 10000; - uiGoreTimer = 15000; - uiGrievousWoundTimer = 20000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiStompTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STOMP); - uiStompTimer = 8000 + rand()%4000; - } else uiStompTimer -= diff; - - if (uiGoreTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GORE); - uiGoreTimer = 13000 + rand()%4000; - } else uiGoreTimer -= diff; - - if (uiGrievousWoundTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_GRIEVOUS_WOUND); - uiGrievousWoundTimer = 18000 + rand()%4000; - } else uiGrievousWoundTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_ferocious_rhino(Creature* pCreature) -{ - return new mob_ferocious_rhinoAI (pCreature); -} - -//massive jormungar's spells -enum MassiveSpells -{ - SPELL_ACID_SPIT = 48132, - SPELL_ACID_SPLATTER = 48136, - H_SPELL_ACID_SPLATTER = 59272, - SPELL_POISON_BREATH = 48133, - H_SPELL_POISON_BREATH = 59271 -}; - -enum MassiveAdds -{ - CREATURE_JORMUNGAR_WORM = 27228 -}; - -struct mob_massive_jormungarAI : public ScriptedAI -{ - mob_massive_jormungarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiAcidSpitTimer; - uint32 uiAcidSplatterTimer; - uint32 uiPoisonBreathTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiAcidSpitTimer = 3000; - uiAcidSplatterTimer = 12000; - uiPoisonBreathTimer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiAcidSpitTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ACID_SPIT); - uiAcidSpitTimer = 2000 + rand()%2000; - } else uiAcidSpitTimer -= diff; - - if (uiAcidSplatterTimer <= diff) - { - DoCast(me, SPELL_POISON_BREATH); - uiAcidSplatterTimer = 10000 + rand()%4000; - } else uiAcidSplatterTimer -= diff; - - if (uiPoisonBreathTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_POISON_BREATH); - uiPoisonBreathTimer = 8000 + rand()%4000; - } else uiPoisonBreathTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI,pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_massive_jormungar(Creature* pCreature) -{ - return new mob_massive_jormungarAI (pCreature); -} - - -struct mob_palehoof_orbAI : public ScriptedAI -{ - mob_palehoof_orbAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 SummonTimer; - Phase currentPhase; - - void Reset() - { - currentPhase=PHASE_NONE; - SummonTimer=5000; - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); - me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL); - me->SetSpeed(MOVE_FLIGHT , 0.5f); - } - - void UpdateAI(const uint32 diff) - { - if (currentPhase == PHASE_NONE) - return; - - if (SummonTimer <= diff) - { - if (currentPhase<5&¤tPhase >= 0) - { - Creature *pNext = NULL; - switch(currentPhase) - { - case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; - case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; - case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; - case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; - case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; - } - - if (pNext) - { - pNext->RemoveAurasDueToSpell(SPELL_FREEZE); - pNext->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - pNext->SetStandState(UNIT_STAND_STATE_STAND); - pNext->SetInCombatWithZone(); - pNext->Attack(pNext->SelectNearestTarget(100),true); - - } - currentPhase=PHASE_NONE; - } - } else SummonTimer-=diff; - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - if (id<0 || id>4) - return; - Creature *pNext = NULL; - switch(id) - { - case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; - case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; - case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; - case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; - case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; - } - if (pNext) - DoCast(pNext, SPELL_ORB_CHANNEL, false); - currentPhase=(Phase)id; - SummonTimer=5000; - } -}; - -CreatureAI* GetAI_mob_palehoof_orb(Creature* pCreature) -{ - return new mob_palehoof_orbAI (pCreature); -} - - - -bool GOHello_palehoof_sphere(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - - Creature *pPalehoof = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - { - // maybe these are hacks :( - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - return true; -} - - - -void AddSC_boss_palehoof() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_palehoof"; - newscript->GetAI = &GetAI_boss_palehoof; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ravenous_furbolg"; - newscript->GetAI = &GetAI_mob_ravenous_furbolg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frenzied_worgen"; - newscript->GetAI = &GetAI_mob_frenzied_worgen; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ferocious_rhino"; - newscript->GetAI = &GetAI_mob_ferocious_rhino; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_massive_jormungar"; - newscript->GetAI = &GetAI_mob_massive_jormungar; - newscript->RegisterSelf(); - - - newscript = new Script; - newscript->Name = "mob_palehoof_orb"; - newscript->GetAI = &GetAI_mob_palehoof_orb; - newscript->RegisterSelf(); - - - newscript = new Script; - newscript->Name = "go_palehoof_sphere"; - newscript->pGOHello=&GOHello_palehoof_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp deleted file mode 100644 index a75eb3465be..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Boss_Skadi -SDAuthor: LordVanMartin, JohnHoliver -SD%Complete: 90% -SDComment: - After Unmount() he appears to still be flying even with SetFlying(false) - -SDCategory: Utgarde Pinnacle -Script Data End */ - -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -//Yell -enum eYells -{ - SAY_AGGRO = -1575004, - SAY_KILL_1 = -1575005, - SAY_KILL_2 = -1575006, - EMOTE_RANGE = -1575007, //Skadi - SAY_DEATH = -1575008, - SAY_DRAKE_DEATH = -1575009, - EMOTE_BREATH = -1575010, //Grauf - SAY_DRAKE_BREATH_1 = -1575011, - SAY_DRAKE_BREATH_2 = -1575012, - SAY_DRAKE_BREATH_3 = -1575013, -}; - -static Position SpawnLoc = {468.931, -513.555, 104.723}; -static Position Location[]= -{ - // Boss - {341.740997, -516.955017, 104.66900}, // 0 - {293.299, -505.95, 142.03}, // 1 - {301.664, -535.164, 146.097}, // 2 - {521.031006, -544.667847, 128.80064}, // 3 - {477.311981, -509.296814, 104.72308}, // 4 - {341.740997, -516.955017, 104.66900}, // 5 - {341.740997, -516.955017, 104.66900}, // 6 - {341.740997, -516.955017, 104.66900}, // 7 - // Triggers Left - {469.661, -484.546, 104.712}, // 8 - {483.315, -485.028, 104.718}, // 9 - {476.87, -487.994, 104.735}, //10 - {477.512, -497.772, 104.728}, //11 - {486.287, -500.759, 104.722}, //12 - {480.1, -503.895, 104.722}, //13 - {472.391, -505.103, 104.723}, //14 - {478.885, -510.803, 104.723}, //15 - {489.529, -508.615, 104.723}, //16 - {484.272, -508.589, 104.723}, //17 - {465.328, -506.495, 104.427}, //18 - {456.885, -508.104, 104.447}, //19 - {450.177, -507.989, 105.247}, //20 - {442.273, -508.029, 104.813}, //21 - {434.225, -508.19, 104.787}, //22 - {423.902, -508.525, 104.274}, //23 - {414.551, -508.645, 105.136}, //24 - {405.787, -508.755, 104.988}, //25 - {398.812, -507.224, 104.82}, //26 - {389.702, -506.846, 104.729}, //27 - {381.856, -506.76, 104.756}, //28 - {372.881, -507.254, 104.779}, //29 - {364.978, -508.182, 104.673}, //30 - {357.633, -508.075, 104.647}, //31 - {350.008, -506.826, 104.588}, //32 - {341.69, -506.77, 104.499}, //33 - {335.31, -505.745, 105.18}, //34 - {471.178, -510.74, 104.723}, //35 - {461.759, -510.365, 104.199}, //36 - {424.07287, -510.082916, 104.711082}, //37 - // Triggers Right - {489.46, -513.297, 105.413}, //38 - {485.706, -517.175, 104.724}, //39 - {480.98, -519.313, 104.724}, //40 - {475.05, -520.52, 104.724}, //41 - {482.97, -512.099, 104.724}, //42 - {477.082, -514.172, 104.724}, //43 - {468.991, -516.691, 104.724}, //44 - {461.722, -517.063, 104.627}, //45 - {455.88, -517.681, 104.707}, //46 - {450.499, -519.099, 104.701}, //47 - {444.889, -518.963, 104.82}, //48 - {440.181, -518.893, 104.861}, //49 - {434.393, -518.758, 104.891}, //50 - {429.328, -518.583, 104.904}, //51 - {423.844, -518.394, 105.004}, //52 - {418.707, -518.266, 105.135}, //53 - {413.377, -518.085, 105.153}, //54 - {407.277, -517.844, 104.893}, //55 - {401.082, -517.443, 104.723}, //56 - {394.933, -514.64, 104.724}, //57 - {388.917, -514.688, 104.734}, //58 - {383.814, -515.834, 104.73}, //59 - {377.887, -518.653, 104.777}, //60 - {371.376, -518.289, 104.781}, //61 - {365.669, -517.822, 104.758}, //62 - {359.572, -517.314, 104.706}, //63 - {353.632, -517.146, 104.647}, //64 - {347.998, -517.038, 104.538}, //65 - {341.803, -516.98, 104.584}, //66 - {335.879, -516.674, 104.628}, //67 - {329.871, -515.92, 104.711}, //68 - // Breach Zone - {485.4577, -511.2515, 115.3011}, //69 - {435.1892, -514.5232, 118.6719}, //70 - {413.9327, -540.9407, 138.2614}, //71 -}; - -enum eCombatPhase -{ - FLYING, - SKADI -}; - -enum eSpells -{ - //Skadi Spells - SPELL_CRUSH = 50234, - SPELL_POISONED_SPEAR = 50225, //isn't being casted =/ - SPELL_WHIRLWIND = 50228, //random target, but not the tank approx. every 20s - SPELL_RAPID_FIRE = 56570, - SPELL_HARPOON_DAMAGE = 56578, - SPELL_FREEZING_CLOUD = 47579, -}; - -enum eCreature -{ - CREATURE_YMIRJAR_WARRIOR = 26690, - CREATURE_YMIRJAR_WITCH_DOCTOR = 26691, - CREATURE_YMIRJAR_HARPOONER = 26692, - CREATURE_GRAUF = 26893, - CREATURE_TRIGGER = 28351, - DATA_MOUNT = 27043, -}; - -enum eAchievments -{ - ACHIEV_TIMED_START_EVENT = 17726, -}; - -struct boss_skadiAI : public ScriptedAI -{ - boss_skadiAI(Creature *c) : ScriptedAI(c), Summons(me) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - SummonList Summons; - uint64 m_uiGraufGUID; - std::vector triggersGUID; - - uint32 m_uiCrushTimer; - uint32 m_uiPoisonedSpearTimer; - uint32 m_uiWhirlwindTimer; - uint32 m_uiWaypointId; - uint32 m_uiMovementTimer; - uint32 m_uiMountTimer; - uint32 m_uiSummonTimer; - uint8 m_uiSpellHitCount; - bool m_bSaidEmote; - - eCombatPhase Phase; - - void Reset() - { - triggersGUID.clear(); - - m_uiCrushTimer = 8000; - m_uiPoisonedSpearTimer = 10000; - m_uiWhirlwindTimer = 20000; - m_uiMountTimer = 3000; - m_uiWaypointId = 0; - m_bSaidEmote = false; - m_uiSpellHitCount = 0; - - Phase = SKADI; - - Summons.DespawnAll(); - me->SetSpeed(MOVE_FLIGHT, 3.0f); - if ((Unit::GetCreature((*me), m_uiGraufGUID) == NULL) && !me->IsMounted()) - me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); - if (m_pInstance) - { - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, NOT_STARTED); - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void JustReachedHome() - { - me->SetFlying(false); - me->Unmount(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - if (Unit::GetCreature((*me), m_uiGraufGUID) == NULL) - me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - Phase = FLYING; - - m_uiMovementTimer = 1000; - m_uiSummonTimer = 10000; - me->SetInCombatWithZone(); - if (m_pInstance) - { - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, IN_PROGRESS); - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - me->GetMotionMaster()->MoveJump(Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 5.0f, 10.0f); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - m_uiMountTimer = 1000; - Summons.DespawnEntry(CREATURE_GRAUF); - } - } - - void JustSummoned(Creature* pSummoned) - { - switch (pSummoned->GetEntry()) - { - case CREATURE_GRAUF: - m_uiGraufGUID = pSummoned->GetGUID(); - break; - case CREATURE_YMIRJAR_WARRIOR: - case CREATURE_YMIRJAR_WITCH_DOCTOR: - case CREATURE_YMIRJAR_HARPOONER: - pSummoned->setActive(true); - pSummoned->SetInCombatWithZone(); - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - break; - case CREATURE_TRIGGER: - pSummoned->CastSpell((Unit*)NULL, SPELL_FREEZING_CLOUD, true); - pSummoned->ForcedDespawn(10*IN_MILISECONDS); - break; - } - Summons.Summon(pSummoned); - } - - void SummonedCreatureDespawn(Creature* pSummoned) - { - if (pSummoned->GetEntry() == CREATURE_GRAUF) - m_uiGraufGUID = 0; - Summons.Despawn(pSummoned); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_HARPOON_DAMAGE) - { - m_uiSpellHitCount++; - if (m_uiSpellHitCount >= 5) - { - Phase = SKADI; - me->SetFlying(false); - me->Unmount(); - if(Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILISECONDS)) - { - pGrauf->GetMotionMaster()->MoveFall(0); - pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); - } - sLog.outBasic("[Skadi] Fly off"); - me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - DoScriptText(SAY_DRAKE_DEATH, me); - m_uiCrushTimer = 8000; - m_uiPoisonedSpearTimer = 10000; - m_uiWhirlwindTimer = 20000; - me->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); - } - } - } - - - void UpdateAI(const uint32 diff) - { - switch(Phase) - { - case FLYING: - if (!UpdateVictim()) - return; - - if (me->GetPositionX() >= 519) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - if (!m_bSaidEmote) - { - DoScriptText(EMOTE_RANGE, me); - m_bSaidEmote = true; - } - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - m_bSaidEmote = false; - } - - if (m_uiMountTimer && m_uiMountTimer <= diff) - { - me->Mount(DATA_MOUNT); - me->SetFlying(true); - m_uiMountTimer = 0; - } else m_uiMountTimer -= diff; - - if (m_uiSummonTimer <= diff) - { - SpawnMobs(); - m_uiSummonTimer = 25000; - } else m_uiSummonTimer -= diff; - - if (m_uiMovementTimer <= diff) - { - switch(m_uiWaypointId) - { - case 0: - me->GetMotionMaster()->MovePoint(0, Location[1].GetPositionX(), Location[1].GetPositionY(), Location[1].GetPositionZ()); - m_uiMovementTimer = 5000; - break; - case 1: - me->GetMotionMaster()->MovePoint(0, Location[2].GetPositionX(), Location[2].GetPositionY(), Location[2].GetPositionZ()); - m_uiMovementTimer = 2000; - break; - case 2: - me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); - m_uiMovementTimer = 15000; - break; - case 3: - me->GetMotionMaster()->MovePoint(0, Location[69].GetPositionX(), Location[69].GetPositionY(), Location[69].GetPositionZ()); - DoScriptText(RAND(SAY_DRAKE_BREATH_1,SAY_DRAKE_BREATH_2), me); - DoScriptText(EMOTE_BREATH, me); - m_uiMovementTimer = 2500; - break; - case 4: - me->GetMotionMaster()->MovePoint(0, Location[70].GetPositionX(), Location[70].GetPositionY(), Location[70].GetPositionZ()); - m_uiMovementTimer = 2000; - SpawnTrigger(); - break; - case 5: - me->GetMotionMaster()->MovePoint(0, Location[71].GetPositionX(), Location[71].GetPositionY(), Location[71].GetPositionZ()); - m_uiMovementTimer = 3000; - break; - case 6: - me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); - m_uiWaypointId = 2; - m_uiMovementTimer = 15000; - break; - } - m_uiWaypointId++; - } else m_uiMovementTimer -= diff; - break; - case SKADI: - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_uiCrushTimer <= diff) - { - DoCastVictim(SPELL_CRUSH); - m_uiCrushTimer = 8000; - } else m_uiCrushTimer -= diff; - - if (m_uiPoisonedSpearTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_POISONED_SPEAR); - m_uiPoisonedSpearTimer = 10000; - } else m_uiPoisonedSpearTimer -= diff; - - if (m_uiWhirlwindTimer <= diff) - { - DoCastAOE(SPELL_WHIRLWIND); - m_uiWhirlwindTimer = 20000; - } else m_uiWhirlwindTimer -= diff; - - DoMeleeAttackIfReady(); - break; - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - Summons.DespawnAll(); - if (m_pInstance) - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void SpawnMobs() - { - for (uint8 i = 0; i < DUNGEON_MODE(5,6); ++i) - { - switch (urand(0,2)) - { - case 0: me->SummonCreature(CREATURE_YMIRJAR_WARRIOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - case 1: me->SummonCreature(CREATURE_YMIRJAR_WITCH_DOCTOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - case 2: me->SummonCreature(CREATURE_YMIRJAR_HARPOONER, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - } - } - } - - void SpawnTrigger() - { - uint8 iStart,iEnd; - switch (urand(0,1)) - { - case 0: - iStart = 8; - iEnd = 37; - break; - case 1: - iStart = 38; - iEnd = 68; - break; - } - for(uint32 i = iStart; i < iEnd; ++i) - me->SummonCreature(CREATURE_TRIGGER,Location[i]); - } -}; - -bool GOHello_go_harpoon_launcher(Player *pPlayer, GameObject *pGO) -{ - ScriptedInstance* m_pInstance; - m_pInstance = (ScriptedInstance*)pGO->GetInstanceData(); - if (!m_pInstance) return false; - - if (Creature* pSkadi = Unit::GetCreature((*pGO),m_pInstance->GetData64(DATA_SKADI_THE_RUTHLESS))) - { - pPlayer->CastSpell(pSkadi,SPELL_RAPID_FIRE, true); - } - return false; -} - -CreatureAI* GetAI_boss_skadi(Creature* pCreature) -{ - return new boss_skadiAI (pCreature); -} - -void AddSC_boss_skadi() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_skadi"; - newscript->GetAI = &GetAI_boss_skadi; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_harpoon_launcher"; - newscript->pGOHello = &GOHello_go_harpoon_launcher; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp deleted file mode 100644 index aae1015ddab..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_CALL_FLAMES = 48258, - SPELL_RITUAL_OF_THE_SWORD = 48276, //Effect #1 Teleport, Effect #2 Dummy - SPELL_SINSTER_STRIKE = 15667, - H_SPELL_SINSTER_STRIKE = 59409, - SPELL_SVALA_TRANSFORMING1 = 54140, - SPELL_SVALA_TRANSFORMING2 = 54205 -}; -//not in db -enum Yells -{ - SAY_DIALOG_WITH_ARTHAS_1 = -1575015, - SAY_DIALOG_WITH_ARTHAS_2 = -1575016, - SAY_DIALOG_WITH_ARTHAS_3 = -1575017, - SAY_AGGRO = -1575018, - SAY_SLAY_1 = -1575019, - SAY_SLAY_2 = -1575020, - SAY_SLAY_3 = -1575021, - SAY_DEATH = -1575022, - SAY_SACRIFICE_PLAYER_1 = -1575023, - SAY_SACRIFICE_PLAYER_2 = -1575024, - SAY_SACRIFICE_PLAYER_3 = -1575025, - SAY_SACRIFICE_PLAYER_4 = -1575026, - SAY_SACRIFICE_PLAYER_5 = -1575027, - SAY_DIALOG_OF_ARTHAS_1 = -1575028, - SAY_DIALOG_OF_ARTHAS_2 = -1575029 -}; -enum Creatures -{ - CREATURE_ARTHAS = 24266, // Image of Arthas - CREATURE_SVALA_SORROWGRAVE = 26668, // Svala after transformation - CREATURE_SVALA = 29281, // Svala before transformation - CREATURE_RITUAL_CHANNELER = 27281 -}; -enum ChannelerSpells -{ - //ritual channeler's spells - SPELL_PARALYZE = 48278, - SPELL_SHADOWS_IN_THE_DARK = 59407 -}; -enum Misc -{ - DATA_SVALA_DISPLAY_ID = 25944 -}; -enum IntroPhase -{ - IDLE, - INTRO, - FINISHED -}; -enum CombatPhase -{ - NORMAL, - SACRIFICING -}; - -static Position RitualChannelerPos[]= -{ - {296.42, -355.01, 90.94}, - {302.36, -352.01, 90.54}, - {291.39, -350.89, 90.54} -}; -static Position ArthasPos = { 295.81, -366.16, 92.57, 1.58 }; -static Position SvalaPos = { 296.632, -346.075, 90.6307, 1.58 }; - -struct boss_svalaAI : public ScriptedAI -{ - boss_svalaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiIntroTimer; - - uint8 uiIntroPhase; - - IntroPhase Phase; - - TempSummon* pArthas; - uint64 uiArthasGUID; - - ScriptedInstance* pInstance; - - void Reset() - { - Phase = IDLE; - uiIntroTimer = 1*IN_MILISECONDS; - uiIntroPhase = 0; - uiArthasGUID = 0; - - if (pInstance) - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); - } - - void MoveInLineOfSight(Unit* pWho) - { - if (!pWho) - return; - - if (Phase == IDLE && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && me->IsWithinDistInMap(pWho, 40)) - { - Phase = INTRO; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Creature *pArthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - pArthas->SetFloatValue(OBJECT_FIELD_SCALE_X, 5); - uiArthasGUID = pArthas->GetGUID(); - } - } - } - - void AttackStart(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (Phase != INTRO) - return; - - if (uiIntroTimer <= diff) - { - Creature *pArthas = Unit::GetCreature(*me, uiArthasGUID); - if (!pArthas) - return; - - switch (uiIntroPhase) - { - case 0: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_1, me); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 1: - DoScriptText(SAY_DIALOG_OF_ARTHAS_1, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 2: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_2, me); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 3: - DoScriptText(SAY_DIALOG_OF_ARTHAS_2, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 4: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_3, me); - DoCast(me, SPELL_SVALA_TRANSFORMING1); - ++uiIntroPhase; - uiIntroTimer = 2.8*IN_MILISECONDS; - break; - case 5: - DoCast(me, SPELL_SVALA_TRANSFORMING2); - ++uiIntroPhase; - uiIntroTimer = 200; - break; - case 6: - if (Creature* pSvalaSorrowgrave = me->SummonCreature(CREATURE_SVALA_SORROWGRAVE, SvalaPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60*IN_MILISECONDS)) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(DATA_SVALA_DISPLAY_ID); - pArthas->ToTempSummon()->UnSummon(); - uiArthasGUID = 0; - Phase = FINISHED; - } - else - Reset(); - break; - } - } else uiIntroTimer -= diff; - } -}; - -struct mob_ritual_channelerAI : public Scripted_NoMovementAI -{ - mob_ritual_channelerAI(Creature *c) :Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - DoCast(me, SPELL_SHADOWS_IN_THE_DARK); - } - - // called by svala sorrowgrave to set guid of victim - void DoAction(uint32 /*action*/) - { - if (pInstance) - if (Unit *pVictim = me->GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER))) - DoCast(pVictim, SPELL_PARALYZE); - } - - void EnterCombat(Unit* /*who*/) - { - } -}; - -struct boss_svala_sorrowgraveAI : public ScriptedAI -{ - boss_svala_sorrowgraveAI(Creature *c) : ScriptedAI(c), summons(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiSinsterStrikeTimer; - uint32 uiCallFlamesTimer; - uint32 uiRitualOfSwordTimer; - uint32 uiSacrificeTimer; - - CombatPhase Phase; - - SummonList summons; - - bool bSacrificed; - - ScriptedInstance* pInstance; - - void Reset() - { - uiSinsterStrikeTimer = 7*IN_MILISECONDS; - uiCallFlamesTimer = 10*IN_MILISECONDS; - uiRitualOfSwordTimer = 20*IN_MILISECONDS; - uiSacrificeTimer = 8*IN_MILISECONDS; - - bSacrificed = false; - - Phase = NORMAL; - - DoTeleportTo(296.632, -346.075, 90.6307); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - - summons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); - pInstance->SetData64(DATA_SACRIFICED_PLAYER,0); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature *summon) - { - summons.Summon(summon); - } - - void SummonedCreatureDespawn(Creature *summon) - { - summons.Despawn(summon); - } - - void UpdateAI(const uint32 diff) - { - if (Phase == NORMAL) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiSinsterStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); - uiSinsterStrikeTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); - } else uiSinsterStrikeTimer -= diff; - - if (uiCallFlamesTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, SPELL_CALL_FLAMES); - uiCallFlamesTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); - } - } else uiCallFlamesTimer -= diff; - - if (!bSacrificed) - if (uiRitualOfSwordTimer <= diff) - { - if (Unit* pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(RAND(SAY_SACRIFICE_PLAYER_1,SAY_SACRIFICE_PLAYER_2,SAY_SACRIFICE_PLAYER_3,SAY_SACRIFICE_PLAYER_4,SAY_SACRIFICE_PLAYER_5),me); - DoCast(pSacrificeTarget, SPELL_RITUAL_OF_THE_SWORD); - //Spell doesn't teleport - DoTeleportPlayer(pSacrificeTarget, 296.632, -346.075, 90.63, 4.6); - me->SetUnitMovementFlags(MOVEMENTFLAG_FLY_MODE); - DoTeleportTo(296.632, -346.075, 120.85); - Phase = SACRIFICING; - if (pInstance) - { - pInstance->SetData64(DATA_SACRIFICED_PLAYER,pSacrificeTarget->GetGUID()); - - for (uint8 i = 0; i < 3; ++i) - if (Creature* pSummon = me->SummonCreature(CREATURE_RITUAL_CHANNELER, RitualChannelerPos[i], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) - pSummon->AI()->DoAction(0); - } - - bSacrificed = true; - } - } else uiRitualOfSwordTimer -= diff; - - DoMeleeAttackIfReady(); - } - else //SACRIFICING - { - if (uiSacrificeTimer <= diff) - { - Unit* pSacrificeTarget = pInstance ? Unit::GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER)) : NULL; - if (pInstance && !summons.empty() && pSacrificeTarget && pSacrificeTarget->isAlive()) - me->Kill(pSacrificeTarget, false); // durability damage? - - //go down - Phase = NORMAL; - pSacrificeTarget = NULL; - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->GetMotionMaster()->MoveChase(pTarget); - - uiSacrificeTimer = 8*IN_MILISECONDS; - } - else uiSacrificeTimer -= diff; - } - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* pKiller) - { - if (pInstance) - { - Creature* pSvala = Unit::GetCreature((*me), pInstance->GetData64(DATA_SVALA)); - if (pSvala && pSvala->isAlive()) - pKiller->Kill(pSvala); - - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); - } - DoScriptText(SAY_DEATH, me); - } -}; - -CreatureAI* GetAI_boss_svala(Creature* pCreature) -{ - return new boss_svalaAI (pCreature); -} - -CreatureAI* GetAI_mob_ritual_channeler(Creature* pCreature) -{ - return new mob_ritual_channelerAI(pCreature); -} - -CreatureAI* GetAI_boss_svala_sorrowgrave(Creature* pCreature) -{ - return new boss_svala_sorrowgraveAI(pCreature); -} - -void AddSC_boss_svala() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_svala"; - newscript->GetAI = &GetAI_boss_svala; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ritual_channeler"; - newscript->GetAI = &GetAI_mob_ritual_channeler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_svala_sorrowgrave"; - newscript->GetAI = &GetAI_boss_svala_sorrowgrave; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp deleted file mode 100644 index 1a650f94101..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* Script Data Start -SDName: Boss ymiron -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_ymiron' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_BANE = 48294, - H_SPELL_BANE = 59301, - SPELL_DARK_SLASH = 48292, - SPELL_FETID_ROT = 48291, - H_SPELL_FETID_ROT = 59300, - SPELL_SCREAMS_OF_THE_DEAD = 51750, - SPELL_SPIRIT_BURST = 48529, - H_SPELL_SPIRIT_BURST = 59305, - SPELL_SPIRIT_STRIKE = 48423, - H_SPELL_SPIRIT_STRIKE = 59304, - SPELL_ANCESTORS_VENGEANCE = 16939, - - SPELL_SUMMON_AVENGING_SPIRIT = 48592, - SPELL_SUMMON_SPIRIT_FOUNT = 48386, - - SPELL_CHANNEL_SPIRIT_TO_YMIRON = 48316, - SPELL_CHANNEL_YMIRON_TO_SPIRIT = 48307, - - SPELL_SPIRIT_FOUNT = 48380, - H_SPELL_SPIRIT_FOUNT = 59320 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1575028, - SAY_SLAY_1 = -1575029, - SAY_SLAY_2 = -1575030, - SAY_SLAY_3 = -1575031, - SAY_SLAY_4 = -1575032, - SAY_DEATH = -1575033, - SAY_SUMMON_BJORN = -1575034, - SAY_SUMMON_HALDOR = -1575035, - SAY_SUMMON_RANULF = -1575036, - SAY_SUMMON_TORGYN = -1575037 -}; - -enum Creatures -{ - CREATURE_BJORN = 27303, - CREATURE_BJORN_VISUAL = 27304, - CREATURE_HALDOR = 27307, - CREATURE_HALDOR_VISUAL = 27310, - CREATURE_RANULF = 27308, - CREATURE_RANULF_VISUAL = 27311, - CREATURE_TORGYN = 27309, - CREATURE_TORGYN_VISUAL = 27312, - CREATURE_SPIRIT_FOUNT = 27339, - CREATURE_AVENGING_SPIRIT = 27386 -}; - -struct ActiveBoatStruct -{ - uint32 npc; - int32 say; - float MoveX,MoveY,MoveZ,SpawnX,SpawnY,SpawnZ,SpawnO; -}; - -static ActiveBoatStruct ActiveBot[4] = -{ - {CREATURE_BJORN_VISUAL, SAY_SUMMON_BJORN, 404.379, -335.335, 104.756, 413.594, -335.408, 107.995, 3.157}, - {CREATURE_HALDOR_VISUAL, SAY_SUMMON_HALDOR, 380.813, -335.069, 104.756, 369.994, -334.771, 107.995, 6.232}, - {CREATURE_RANULF_VISUAL, SAY_SUMMON_RANULF, 381.546, -314.362, 104.756, 370.841, -314.426, 107.995, 6.232}, - {CREATURE_TORGYN_VISUAL, SAY_SUMMON_TORGYN, 404.310, -314.761, 104.756, 413.992, -314.703, 107.995, 3.157} -}; - -struct boss_ymironAI : public ScriptedAI -{ - boss_ymironAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - srand(time(NULL)); - for (int i = 0; i < 4; ++i) - m_uiActiveOrder[i] = i; - for (int i = 0; i < 3; ++i) - { - int r = i + (rand()%(4-i)); - int temp = m_uiActiveOrder[i]; - m_uiActiveOrder[i] = m_uiActiveOrder[r]; - m_uiActiveOrder[r] = temp; - } - } - - bool m_bIsWalking; - bool m_bIsPause; - bool m_bIsActiveWithBJORN; - bool m_bIsActiveWithHALDOR; - bool m_bIsActiveWithRANULF; - bool m_bIsActiveWithTORGYN; - - uint8 m_uiActiveOrder[4]; - uint8 m_uiActivedNumber; - - uint32 m_uiFetidRot_Timer; - uint32 m_uiBane_Timer; - uint32 m_uiDarkSlash_Timer; - uint32 m_uiAncestors_Vengeance_Timer; - - uint32 m_uiAbility_BJORN_Timer; - uint32 m_uiAbility_HALDOR_Timer; - uint32 m_uiAbility_RANULF_Timer; - uint32 m_uiAbility_TORGYN_Timer; - - uint32 m_uiPause_Timer; - uint32 m_uiHealthAmountModifier; - uint32 m_uiHealthAmountMultipler; - - uint64 m_uiActivedCreatureGUID; - uint64 m_uiOrbGUID; - - ScriptedInstance *pInstance; - - void Reset() - { - m_bIsPause = false; - m_bIsActiveWithBJORN = false; - m_bIsActiveWithHALDOR = false; - m_bIsActiveWithRANULF = false; - m_bIsActiveWithTORGYN = false; - - m_uiFetidRot_Timer = urand(8000,13000); - m_uiBane_Timer = urand(18000,23000); - m_uiDarkSlash_Timer = urand(28000,33000); - m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(60000,45000); - m_uiPause_Timer = 0; - - m_uiAbility_BJORN_Timer = 0; - m_uiAbility_HALDOR_Timer = 0; - m_uiAbility_RANULF_Timer = 0; - m_uiAbility_TORGYN_Timer = 0; - - m_uiActivedNumber = 0; - m_uiHealthAmountModifier = 1; - m_uiHealthAmountMultipler = DUNGEON_MODE(20,25); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (m_bIsWalking) - { - if (m_uiPause_Timer <= diff) - { - DoScriptText(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].say, me); - DoCast(me, SPELL_CHANNEL_YMIRON_TO_SPIRIT); // should be on spirit - if (Creature* pTemp = me->SummonCreature(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].npc, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnX, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnY, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnZ, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnO, TEMPSUMMON_CORPSE_DESPAWN, 0)) - { - m_uiActivedCreatureGUID = pTemp->GetGUID(); - pTemp->CastSpell(me, SPELL_CHANNEL_SPIRIT_TO_YMIRON, true); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - switch(m_uiActiveOrder[m_uiActivedNumber]) - { - case 0: m_bIsActiveWithBJORN = true; break; - case 1: m_bIsActiveWithHALDOR = true; break; - case 2: m_bIsActiveWithRANULF = true; break; - case 3: m_bIsActiveWithTORGYN = true; break; - } - } - - m_bIsPause = true; - m_bIsWalking = false; - m_uiPause_Timer = 3000; - } else m_uiPause_Timer -= diff; - return; - } - else if (m_bIsPause) - { - if (m_uiPause_Timer <= diff) - { - m_uiAbility_BJORN_Timer = 5000; - m_uiAbility_HALDOR_Timer = 5000; - m_uiAbility_RANULF_Timer = 5000; - m_uiAbility_TORGYN_Timer = 5000; - - m_bIsPause = false; - m_uiPause_Timer = 0; - } else m_uiPause_Timer -= diff; - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!m_bIsPause) - { - // Normal spells ------------------------------------------------------------------------ - if (m_uiBane_Timer <= diff) - { - DoCast(me, SPELL_BANE); - m_uiBane_Timer = urand(20000,25000); - } else m_uiBane_Timer -= diff; - - if (m_uiFetidRot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FETID_ROT); - m_uiFetidRot_Timer = urand(10000,15000); - } else m_uiFetidRot_Timer -= diff; - - if (m_uiDarkSlash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DARK_SLASH); - m_uiDarkSlash_Timer = urand(30000,35000); - } else m_uiDarkSlash_Timer -= diff; - - if (m_uiAncestors_Vengeance_Timer <= diff) - { - DoCast(me, SPELL_ANCESTORS_VENGEANCE); - m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(urand(60000,65000),urand(45000,50000)); - } else m_uiAncestors_Vengeance_Timer -= diff; - - // Abilities ------------------------------------------------------------------------------ - if (m_bIsActiveWithBJORN && m_uiAbility_BJORN_Timer <= diff) - { - //DoCast(me, SPELL_SUMMON_SPIRIT_FOUNT); // works fine, but using summon has better control - if (Creature* pTemp = me->SummonCreature(CREATURE_SPIRIT_FOUNT, 385+rand()%10, -330+rand()%10, 104.756, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) - { - pTemp->SetSpeed(MOVE_RUN, 0.4f); - pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SPIRIT_FOUNT, H_SPELL_SPIRIT_FOUNT), true); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->SetDisplayId(11686); - //pTemp->GetMotionMaster()->MoveChase(me->getVictim()); - m_uiOrbGUID = pTemp->GetGUID(); - } - m_bIsActiveWithBJORN = false; // only one orb - } else m_uiAbility_BJORN_Timer -= diff; - - if (m_bIsActiveWithHALDOR && m_uiAbility_HALDOR_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SPIRIT_STRIKE); - m_uiAbility_HALDOR_Timer = 5000; // overtime - } else m_uiAbility_HALDOR_Timer -= diff; - - if (m_bIsActiveWithRANULF && m_uiAbility_RANULF_Timer <= diff) - { - DoCast(me, SPELL_SPIRIT_BURST); - m_uiAbility_RANULF_Timer = 10000; // overtime - } else m_uiAbility_RANULF_Timer -= diff; - - if (m_bIsActiveWithTORGYN && m_uiAbility_TORGYN_Timer <= diff) - { - float x,y,z; - x = me->GetPositionX()-5; - y = me->GetPositionY()-5; - z = me->GetPositionZ(); - for (uint8 i = 0; i < 4; ++i) - { - //DoCast(me, SPELL_SUMMON_AVENGING_SPIRIT); // works fine, but using summon has better control - if (Creature* pTemp = me->SummonCreature(CREATURE_AVENGING_SPIRIT, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - pTemp->AddThreat(pTarget, 0.0f); - pTemp->AI()->AttackStart(pTarget); - } - } - } - m_uiAbility_TORGYN_Timer = 15000; // overtime - } else m_uiAbility_TORGYN_Timer -= diff; - - // Health check ----------------------------------------------------------------------------- - if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(m_uiHealthAmountMultipler * m_uiHealthAmountModifier))) - { - uint8 m_uiOrder = m_uiHealthAmountModifier - 1; - ++m_uiHealthAmountModifier; - - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_SCREAMS_OF_THE_DEAD); - me->GetMotionMaster()->Clear(); - me->StopMoving(); - me->AttackStop(); - me->GetMotionMaster()->MovePoint(0, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveX, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveY, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveZ); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - m_bIsActiveWithBJORN = false; - m_bIsActiveWithHALDOR = false; - m_bIsActiveWithRANULF = false; - m_bIsActiveWithTORGYN = false; - - m_uiBane_Timer += 8000; - m_uiFetidRot_Timer += 8000; - m_uiDarkSlash_Timer += 8000; - m_uiAncestors_Vengeance_Timer += 8000; - - m_uiActivedNumber = m_uiOrder; - m_bIsWalking = true; - m_uiPause_Timer = 2000; - return; - } - DoMeleeAttackIfReady(); - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } - - void DespawnBoatGhosts(uint64& m_uiCreatureGUID) - { - if (m_uiCreatureGUID) - if (Creature* pTemp = Unit::GetCreature(*me, m_uiCreatureGUID)) - pTemp->DisappearAndDie(); - - m_uiCreatureGUID = 0; - } -}; - -CreatureAI* GetAI_boss_ymiron(Creature* pCreature) -{ - return new boss_ymironAI(pCreature); -} - -void AddSC_boss_ymiron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ymiron"; - newscript->GetAI = &GetAI_boss_ymiron; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp deleted file mode 100644 index cf042867707..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -#define MAX_ENCOUNTER 4 - -/* Utgarde Pinnacle encounters: -0 - Svala Sorrowgrave -1 - Gortok Palehoof -2 - Skadi the Ruthless -3 - King Ymiron -*/ - -enum GameObjects -{ - ENTRY_SKADI_THE_RUTHLESS_DOOR = 192173, - ENTRY_KING_YMIRON_DOOR = 192174, - ENTRY_GORK_PALEHOOF_SPHERE = 188593 -}; - -struct instance_pinnacle : public ScriptedInstance -{ - instance_pinnacle(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiSvalaSorrowgrave; - uint64 uiGortokPalehoof; - uint64 uiSkadiTheRuthless; - uint64 uiKingYmiron; - - uint64 uiSkadiTheRuthlessDoor; - uint64 uiKingYmironDoor; - uint64 uiGortokPalehoofSphere; - - uint64 uiFrenziedWorgen; - uint64 uiRavenousFurbolg; - uint64 uiFerociousRhino; - uint64 uiMassiveJormungar; - uint64 uiPalehoofOrb; - - uint64 uiSvala; - uint64 uiSacrificedPlayer; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i] = NOT_STARTED; - - uiSvalaSorrowgrave = 0; - uiGortokPalehoof = 0; - uiSkadiTheRuthless = 0; - uiKingYmiron = 0; - - uiSkadiTheRuthlessDoor = 0; - uiKingYmironDoor = 0; - uiGortokPalehoofSphere = 0; - - uiFrenziedWorgen = 0; - uiRavenousFurbolg = 0; - uiFerociousRhino = 0; - uiMassiveJormungar = 0; - uiPalehoofOrb = 0; - - uiSvala = 0; - uiSacrificedPlayer = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case BOSS_SVALA_SORROWGRAVE: uiSvalaSorrowgrave = pCreature->GetGUID(); break; - case BOSS_GORTOK_PALEHOOF: uiGortokPalehoof = pCreature->GetGUID(); break; - case BOSS_SKADI_RUTHLESS: uiSkadiTheRuthless = pCreature->GetGUID(); break; - case BOSS_KING_YMIRON: uiKingYmiron = pCreature->GetGUID(); break; - case MOB_FRENZIED_WORGEN: uiFrenziedWorgen = pCreature->GetGUID(); break; - case MOB_RAVENOUS_FURBOLG: uiRavenousFurbolg = pCreature->GetGUID(); break; - case MOB_MASSIVE_JORMUNGAR: uiMassiveJormungar = pCreature->GetGUID(); break; - case MOB_FEROCIOUS_RHINO: uiFerociousRhino = pCreature->GetGUID(); break; - case MOB_SVALA: uiSvala = pCreature->GetGUID(); break; - case MOB_PALEHOOF_ORB: uiPalehoofOrb = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case ENTRY_SKADI_THE_RUTHLESS_DOOR: - uiSkadiTheRuthlessDoor = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) HandleGameObject(NULL,true,pGo); - break; - case ENTRY_KING_YMIRON_DOOR: - uiKingYmironDoor = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) HandleGameObject(NULL,true,pGo); - break; - case ENTRY_GORK_PALEHOOF_SPHERE: - uiGortokPalehoofSphere = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - { - HandleGameObject(NULL,true,pGo); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_SVALA_SORROWGRAVE_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_GORTOK_PALEHOOF_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_SKADI_THE_RUTHLESS_EVENT: - if (data == DONE) - HandleGameObject(uiSkadiTheRuthlessDoor,true); - m_auiEncounter[2] = data; - break; - case DATA_KING_YMIRON_EVENT: - if (data == DONE) - HandleGameObject(uiKingYmironDoor,true); - m_auiEncounter[3] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_SACRIFICED_PLAYER) - uiSacrificedPlayer = data; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_SVALA_SORROWGRAVE_EVENT: return m_auiEncounter[0]; - case DATA_GORTOK_PALEHOOF_EVENT: return m_auiEncounter[1]; - case DATA_SKADI_THE_RUTHLESS_EVENT: return m_auiEncounter[2]; - case DATA_KING_YMIRON_EVENT: return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_SVALA_SORROWGRAVE: return uiSvalaSorrowgrave; - case DATA_GORTOK_PALEHOOF: return uiGortokPalehoof; - case DATA_SKADI_THE_RUTHLESS: return uiSkadiTheRuthless; - case DATA_KING_YMIRON: return uiKingYmiron; - case DATA_MOB_FRENZIED_WORGEN: return uiFrenziedWorgen; - case DATA_MOB_RAVENOUS_FURBOLG: return uiRavenousFurbolg; - case DATA_MOB_MASSIVE_JORMUNGAR: return uiMassiveJormungar; - case DATA_MOB_FEROCIOUS_RHINO: return uiFerociousRhino; - case DATA_MOB_ORB: return uiPalehoofOrb; - case DATA_SVALA: return uiSvala; - case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "U P " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'U' && dataHead2 == 'P') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_utgarde_pinnacle(Map* pMap) -{ - return new instance_pinnacle(pMap); -} - -void AddSC_instance_utgarde_pinnacle() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_utgarde_pinnacle"; - newscript->GetInstanceData = &GetInstanceData_instance_utgarde_pinnacle; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h deleted file mode 100644 index a51d7aceda0..00000000000 --- a/src/server/scripts/Northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef DEF_PINNACLE_H -#define DEF_PINNACLE_H - -enum Data -{ - DATA_SVALA_SORROWGRAVE_EVENT, - DATA_GORTOK_PALEHOOF_EVENT, - DATA_SKADI_THE_RUTHLESS_EVENT, - DATA_KING_YMIRON_EVENT -}; -enum Data64 -{ - DATA_SVALA, - DATA_SVALA_SORROWGRAVE, - DATA_GORTOK_PALEHOOF, - DATA_SKADI_THE_RUTHLESS, - DATA_MOB_GRAUF, - DATA_KING_YMIRON, - DATA_MOB_FRENZIED_WORGEN, - DATA_MOB_RAVENOUS_FURBOLG, - DATA_MOB_MASSIVE_JORMUNGAR, - DATA_MOB_FEROCIOUS_RHINO, - DATA_MOB_ORB, - DATA_GORTOK_PALEHOOF_SPHERE, - DATA_SACRIFICED_PLAYER -}; - -enum eCreatures -{ - BOSS_SVALA_SORROWGRAVE = 26668, - BOSS_GORTOK_PALEHOOF = 26687, - BOSS_SKADI_RUTHLESS = 26693, - BOSS_KING_YMIRON = 26861, - MOB_FRENZIED_WORGEN = 26683, - MOB_RAVENOUS_FURBOLG = 26684, - MOB_MASSIVE_JORMUNGAR = 26685, - MOB_FEROCIOUS_RHINO = 26686, - MOB_SVALA = 29281, - MOB_PALEHOOF_ORB = 26688, -}; - -#endif diff --git a/src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp b/src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp deleted file mode 100644 index 11d432e94c6..00000000000 --- a/src/server/scripts/Northrend/vault_of_archavon/boss_archavon.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2009-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*** SQL START *** -UPDATE `creature_template` SET `ScriptName`='boss_archavon' WHERE `entry`='31125'; -UPDATE `creature_template` SET `ScriptName`='mob_archavon_warder' WHERE `entry`='32353'; -*** SQL END ***/ - -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -#define EMOTE_BERSERK -1590002 - -//Spells Archavon -#define SPELL_ROCK_SHARDS 58678 -#define SPELL_CRUSHING_LEAP RAID_MODE(58960,60894)//Instant (10-80yr range) -- Leaps at an enemy, inflicting 8000 Physical damage, knocking all nearby enemies away, and creating a cloud of choking debris. -#define SPELL_STOMP RAID_MODE(58663,60880) -#define SPELL_IMPALE RAID_MODE(58666,60882) //Lifts an enemy off the ground with a spiked fist, inflicting 47125 to 52875 Physical damage and 9425 to 10575 additional damage each second for 8 sec. -#define SPELL_BERSERK 47008 -//Spells Archavon Warders -#define SPELL_ROCK_SHOWER RAID_MODE(60919,60923) -#define SPELL_SHIELD_CRUSH RAID_MODE(60897,60899) -#define SPELL_WHIRL RAID_MODE(60902,60916) - -//4 Warders spawned -#define ARCHAVON_WARDER 32353 //npc 32353 - -//Yell -#define SAY_LEAP "Archavon the Stone Watcher lunges for $N!" //$N should be the target - -#define EVENT_ROCK_SHARDS 1 //15s cd -#define EVENT_CHOKING_CLOUD 2 //30s cd -#define EVENT_STOMP 3 //45s cd -#define EVENT_IMPALE 4 -#define EVENT_BERSERK 5 //300s cd - -//mob -#define EVENT_ROCK_SHOWER 5 //set = 20s cd,unkown cd -#define EVENT_SHIELD_CRUSH 6 //set = 30s cd -#define EVENT_WHIRL 8 //set= 10s cd - -struct boss_archavonAI : public ScriptedAI -{ - boss_archavonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_ARCHAVON_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit* /*Victim*/) {} - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ARCHAVON_EVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); - events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); - events.ScheduleEvent(EVENT_STOMP, 45000); - events.ScheduleEvent(EVENT_BERSERK, 300000); - - if (pInstance) - pInstance->SetData(DATA_ARCHAVON_EVENT, IN_PROGRESS); - } - - // Below UpdateAI may need review/debug. - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ROCK_SHARDS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ROCK_SHARDS); - events.ScheduleEvent(EVENT_ROCK_SHARDS, 15000); - return; - case EVENT_CHOKING_CLOUD: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CRUSHING_LEAP, true); //10y~80y, ignore range - events.ScheduleEvent(EVENT_CHOKING_CLOUD, 30000); - return; - case EVENT_STOMP: - DoCast(me->getVictim(), SPELL_STOMP); - events.ScheduleEvent(EVENT_IMPALE, 3000); - events.ScheduleEvent(EVENT_STOMP, 45000); - return; - case EVENT_IMPALE: - DoCast(me->getVictim(), SPELL_IMPALE); - return; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - DoScriptText(EMOTE_BERSERK, me); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -/*###### -## Mob Archavon Warder -######*/ -struct mob_archavon_warderAI : public ScriptedAI //npc 32353 -{ - mob_archavon_warderAI(Creature *c) : ScriptedAI(c) {} - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - events.ScheduleEvent(EVENT_ROCK_SHOWER, 2000); - events.ScheduleEvent(EVENT_SHIELD_CRUSH, 20000); - events.ScheduleEvent(EVENT_WHIRL, 7500); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ROCK_SHOWER: - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ROCK_SHOWER); - events.ScheduleEvent(EVENT_ROCK_SHARDS, 6000); - return; - } - case EVENT_SHIELD_CRUSH: - DoCast(me->getVictim(), SPELL_SHIELD_CRUSH); - events.ScheduleEvent(EVENT_SHIELD_CRUSH, 20000); - return; - case EVENT_WHIRL: - DoCast(me->getVictim(), SPELL_WHIRL); - events.ScheduleEvent(EVENT_WHIRL, 8000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_archavon_warder(Creature* pCreature) -{ - return new mob_archavon_warderAI(pCreature); -} - -CreatureAI* GetAI_boss_archavon(Creature* pCreature) -{ - return new boss_archavonAI (pCreature); -} - -void AddSC_boss_archavon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_archavon"; - newscript->GetAI = &GetAI_boss_archavon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_archavon_warder"; - newscript->GetAI = &GetAI_mob_archavon_warder; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp b/src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp deleted file mode 100644 index 92a0331708e..00000000000 --- a/src/server/scripts/Northrend/vault_of_archavon/boss_emalon.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2009-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -//Emalon spells -#define SPELL_CHAIN_LIGHTNING RAID_MODE(64213, 64215) -#define SPELL_LIGHTNING_NOVA RAID_MODE(64216, 65279) -#define SPELL_OVERCHARGE 64218 //Casted every 45 sec on a random Tempest Minion -#define SPELL_BERSERK 26662 - -//Tempest Minion spells -#define SPELL_SHOCK 64363 -#define SPELL_OVERCHARGED 64217 -#define SPELL_OVERCHARGED_BLAST 64219 //Casted when Overcharged reaches 10 stacks. Mob dies after that - -//Emotes -#define EMOTE_OVERCHARGE -1590000 -#define EMOTE_MINION_RESPAWN -1590001 -#define EMOTE_BERSERK -1590002 - -//Events -#define EVENT_CHAIN_LIGHTNING 1 -#define EVENT_LIGHTNING_NOVA 2 -#define EVENT_OVERCHARGE 3 -#define EVENT_BERSERK 4 -#define EVENT_SHOCK 5 - -//Creatures -#define MOB_TEMPEST_MINION 33998 - -#define MAX_TEMPEST_MINIONS 4 - -struct Position TempestMinions[MAX_TEMPEST_MINIONS] = -{ - {-203.980103, -281.287720, 91.650223, 1.598807}, - {-233.489410, -281.139282, 91.652412, 1.598807}, - {-233.267578, -297.104645, 91.681915, 1.598807}, - {-203.842529, -297.097015, 91.745163, 1.598807} -}; - -/*###### -## Emalon the Storm Watcher -######*/ -struct boss_emalonAI : public BossAI -{ - boss_emalonAI(Creature *c) : BossAI(c, DATA_EMALON_EVENT) - { - } - - void Reset() - { - _Reset(); - - for (uint8 i = 0; i < MAX_TEMPEST_MINIONS; ++i) - me->SummonCreature(MOB_TEMPEST_MINION, TempestMinions[i], TEMPSUMMON_CORPSE_DESPAWN, 0); - } - - void JustSummoned(Creature *summoned) - { - BossAI::JustSummoned(summoned); - - if (me->getVictim() && summoned->AI()) - summoned->AI()->AttackStart(me->getVictim()); - } - - void EnterCombat(Unit * who) - { - if (!summons.empty()) - { - for (std::list::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) - { - Creature *minion = Unit::GetCreature(*me, *itr); - if (minion && minion->isAlive() && !minion->getVictim() && minion->AI()) - minion->AI()->AttackStart(who); - } - } - - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 5000); - events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 40000); - events.ScheduleEvent(EVENT_BERSERK, 360000); - events.ScheduleEvent(EVENT_OVERCHARGE, 45000); - - _EnterCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CHAIN_LIGHTNING: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 25000); - break; - case EVENT_LIGHTNING_NOVA: - DoCastAOE(SPELL_LIGHTNING_NOVA, false); - events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 40000); - break; - case EVENT_OVERCHARGE: - if (!summons.empty()) - { - std::list::const_iterator itr = summons.begin(); - std::advance(itr, urand(0, summons.size()-1)); - Creature *minion = Unit::GetCreature(*me, *itr); - if (minion && minion->isAlive()) - { - minion->CastSpell(me, SPELL_OVERCHARGED, true); - minion->SetHealth(minion->GetMaxHealth()); - DoScriptText(EMOTE_OVERCHARGE, me); - events.ScheduleEvent(EVENT_OVERCHARGE, 45000); - } - } - break; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - DoScriptText(EMOTE_BERSERK, me); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -/*###### -## Tempest Minion -######*/ -struct mob_tempest_minionAI : public ScriptedAI -{ - mob_tempest_minionAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - EventMap events; - - uint32 uiOverchargedTimer; - - void Reset() - { - events.Reset(); - - uiOverchargedTimer = 0; - } - - void JustDied(Unit* /*Killer*/) - { - if (Creature *pEmalon = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EMALON) : 0)) - { - if (pEmalon->isAlive()) - { - pEmalon->SummonCreature(MOB_TEMPEST_MINION, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoScriptText(EMOTE_MINION_RESPAWN, me); - } - } - } - - void EnterCombat(Unit * who) - { - DoZoneInCombat(); - events.ScheduleEvent(EVENT_SHOCK, 20000); - - if (Creature *pEmalon = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EMALON) : 0)) - { - if (!pEmalon->getVictim() && pEmalon->AI()) - pEmalon->AI()->AttackStart(who); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (Aura *overchargedAura = me->GetAura(SPELL_OVERCHARGED)) - { - if (overchargedAura->GetStackAmount() < 10) - { - if (uiOverchargedTimer <= diff) - { - DoCast(me, SPELL_OVERCHARGED); - uiOverchargedTimer = 2000; - } else uiOverchargedTimer -=diff; - } - else - { - if (overchargedAura->GetStackAmount() == 10) - { - DoCast(me, SPELL_OVERCHARGED_BLAST); - me->ForcedDespawn(); - DoScriptText(EMOTE_MINION_RESPAWN, me); - } - } - } - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHOCK: - DoCast(me->getVictim(), SPELL_SHOCK); - events.ScheduleEvent(EVENT_SHOCK, 20000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_tempest_minion(Creature *_Creature) -{ - return new mob_tempest_minionAI (_Creature); -} - -CreatureAI* GetAI_boss_emalon(Creature *_Creature) -{ - return new boss_emalonAI (_Creature); -} - -void AddSC_boss_emalon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_emalon"; - newscript->GetAI = &GetAI_boss_emalon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tempest_minion"; - newscript->GetAI = &GetAI_mob_tempest_minion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp b/src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp deleted file mode 100644 index 61843647136..00000000000 --- a/src/server/scripts/Northrend/vault_of_archavon/boss_koralon.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2009-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*** SQL START *** -UPDATE `creature_template` SET `ScriptName`='boss_koralon' WHERE `entry`='35013'; -UPDATE `creature_template` SET `ScriptName`='mob_flame_warder' WHERE `entry`='35143'; -*** SQL END ***/ - -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -enum Events -{ - EVENT_NONE, - - // Koralon - EVENT_BURNING_BREATH, - EVENT_BURNING_FURY, - EVENT_FLAME_CINDER_A, - EVENT_METEOR_FISTS_A, - EVENT_METEOR_FISTS_B, - - // Flame Warder - EVENT_FW_LAVA_BIRST, - EVENT_FW_METEOR_FISTS_A, - EVENT_FW_METEOR_FISTS_B, -}; - -enum Spells -{ - // Spells Koralon - SPELL_BURNING_BREATH = 66665, - SPELL_BURNING_BREATH_H = 67328, - SPELL_BURNING_FURY = 66721, - SPELL_FLAME_CINDER_A = 66684, - SPELL_FLAME_CINDER_A_H = 67332, - SPELL_FLAME_CINDER_B = 66681, // don't know the real relation to SPELL_FLAME_CINDER_A atm. - SPELL_METEOR_FISTS_A = 66725, - SPELL_METEOR_FISTS_A_H = 66765, - SPELL_METEOR_FISTS_B = 67333, - SPELL_METEOR_FISTS_B_H = 68161, - - // Spells Flame Warder - SPELL_FW_LAVA_BIRST = 66813, - SPELL_FW_LAVA_BIRST_H = 67330, - SPELL_FW_METEOR_FISTS_A = 66808, - SPELL_FW_METEOR_FISTS_A_H = 66809, - SPELL_FW_METEOR_FISTS_B = 67331, - SPELL_FW_METEOR_FISTS_B_H = 68160, -}; - -struct boss_koralonAI : public ScriptedAI -{ - boss_koralonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_KORALON_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit* /*Victim*/) {} - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_KORALON_EVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - - DoCast(me, SPELL_BURNING_FURY); - - events.ScheduleEvent(EVENT_BURNING_FURY, 20000); // TODO check timer - events.ScheduleEvent(EVENT_BURNING_BREATH, 15000); // 1st after 15sec, then every 45sec - events.ScheduleEvent(EVENT_METEOR_FISTS_A, 75000); // 1st after 75sec, then every 45sec - events.ScheduleEvent(EVENT_FLAME_CINDER_A, 30000); // TODO check timer - - if (pInstance) - pInstance->SetData(DATA_KORALON_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BURNING_FURY: - DoCast(me, SPELL_BURNING_FURY); - events.ScheduleEvent(EVENT_BURNING_FURY, 20000); - return; - case EVENT_BURNING_BREATH: - DoCast(me, RAID_MODE(SPELL_BURNING_BREATH,SPELL_BURNING_BREATH_H)); - events.ScheduleEvent(EVENT_BURNING_BREATH, 45000); - return; - case EVENT_METEOR_FISTS_A: - DoCast(me, RAID_MODE(SPELL_METEOR_FISTS_A,SPELL_METEOR_FISTS_A_H)); - events.ScheduleEvent(EVENT_METEOR_FISTS_B, 1500); - return; - case EVENT_METEOR_FISTS_B: - DoCast(me, RAID_MODE(SPELL_METEOR_FISTS_B,SPELL_METEOR_FISTS_B_H)); - events.ScheduleEvent(EVENT_METEOR_FISTS_A, 45000); - return; - case EVENT_FLAME_CINDER_A: - DoCast(me, RAID_MODE(SPELL_FLAME_CINDER_A,SPELL_FLAME_CINDER_A_H)); - events.ScheduleEvent(EVENT_FLAME_CINDER_A, 30000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -/*###### -## Mob Flame Warder -######*/ -struct mob_flame_warderAI : public ScriptedAI -{ - mob_flame_warderAI(Creature *c) : ScriptedAI(c) {} - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - - events.ScheduleEvent(EVENT_FW_LAVA_BIRST, 5000); - events.ScheduleEvent(EVENT_FW_METEOR_FISTS_A, 10000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FW_LAVA_BIRST: - DoCast(me->getVictim(), RAID_MODE(SPELL_FW_LAVA_BIRST,SPELL_FW_LAVA_BIRST_H)); - events.ScheduleEvent(EVENT_FW_LAVA_BIRST, 15000); - return; - case EVENT_FW_METEOR_FISTS_A: - DoCast(me, RAID_MODE(SPELL_FW_METEOR_FISTS_A,SPELL_FW_METEOR_FISTS_A_H)); - events.ScheduleEvent(EVENT_FW_METEOR_FISTS_B, 1500); - return; - case EVENT_FW_METEOR_FISTS_B: - DoCast(me, RAID_MODE(SPELL_FW_METEOR_FISTS_B,SPELL_FW_METEOR_FISTS_B_H)); - events.ScheduleEvent(EVENT_FW_METEOR_FISTS_A, 20000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_koralon(Creature* pCreature) -{ - return new boss_koralonAI (pCreature); -} - -CreatureAI* GetAI_mob_flame_warder(Creature* pCreature) -{ - return new mob_flame_warderAI (pCreature); -} - -void AddSC_boss_koralon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_koralon"; - newscript->GetAI = &GetAI_boss_koralon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flame_warder"; - newscript->GetAI = &GetAI_mob_flame_warder; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp b/src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp deleted file mode 100644 index 2e16f9211d2..00000000000 --- a/src/server/scripts/Northrend/vault_of_archavon/boss_toravon.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (C) 2009-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*** SQL START *** -UPDATE `creature_template` SET `ScriptName`='boss_toravon' WHERE `entry`='38433'; -UPDATE `creature_template` SET `ScriptName`='mob_frost_warder' WHERE `entry`='38482'; -UPDATE `creature_template` SET `ScriptName`='mob_frozen_orb_stalker' WHERE `entry`='38461'; -UPDATE `creature_template` SET `ScriptName`='mob_frozen_orb' WHERE `entry`='38456'; -*** SQL END ***/ - -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -// Spells Toravon -#define SPELL_FREEZING_GROUND RAID_MODE(72090,72104) // don't know cd... using 20 secs. -#define SPELL_FROZEN_ORB RAID_MODE(72091,72095) -#define SPELL_WHITEOUT RAID_MODE(72034,72096) // Every 38 sec. cast. (after SPELL_FROZEN_ORB) -#define SPELL_FROZEN_MALLET 71993 - -// Spells Frost Warder -#define SPELL_FROST_BLAST RAID_MODE(72123,72124) // don't know cd... using 20 secs. -#define SPELL_FROZEN_MALLET 72122 - -// Spell Frozen Orb -#define SPELL_FROZEN_ORB_DMG 72081 // priodic dmg aura -#define SPELL_FROZEN_ORB_AURA 72067 // make visible - -// Spell Frozen Orb Stalker -#define SPELL_FROZEN_ORB_SUMMON 72093 // summon orb - -// Events boss -#define EVENT_FREEZING_GROUND 1 -#define EVENT_FROZEN_ORB 2 -#define EVENT_WHITEOUT 3 - -// Events mob -#define EVENT_FROST_BLAST 4 - -// Mob Frozen Orb -#define MOB_FROZEN_ORB 38456 // 1 in 10 mode and 3 in 25 mode - -struct boss_toravonAI : public ScriptedAI -{ - boss_toravonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_TORAVON_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit* /*Victim*/) {} - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_TORAVON_EVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - - DoCast(me, SPELL_FROZEN_MALLET); - - events.ScheduleEvent(EVENT_FROZEN_ORB, 11000); - events.ScheduleEvent(EVENT_WHITEOUT, 13000); - events.ScheduleEvent(EVENT_FREEZING_GROUND, 15000); - - if (pInstance) - pInstance->SetData(DATA_TORAVON_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROZEN_ORB: - DoCast(me, SPELL_FROZEN_ORB); - events.ScheduleEvent(EVENT_FROZEN_ORB, 38000); - return; - case EVENT_WHITEOUT: - DoCast(me, SPELL_WHITEOUT); - events.ScheduleEvent(EVENT_WHITEOUT, 38000); - return; - case EVENT_FREEZING_GROUND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FREEZING_GROUND); - events.ScheduleEvent(EVENT_FREEZING_GROUND, 20000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -/*###### -## Mob Frost Warder -######*/ -struct mob_frost_warderAI : public ScriptedAI -{ - mob_frost_warderAI(Creature *c) : ScriptedAI(c) {} - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - - DoCast(me, SPELL_FROZEN_MALLET); - - events.ScheduleEvent(EVENT_FROST_BLAST, 5000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROST_BLAST: - DoCast(me->getVictim(), SPELL_FROST_BLAST); - events.ScheduleEvent(EVENT_FROST_BLAST, 20000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - - -/*###### -## Mob Frozen Orb -######*/ -struct mob_frozen_orbAI : public ScriptedAI -{ - mob_frozen_orbAI(Creature *c) : ScriptedAI(c) {} - - bool done; - uint32 killtimer; - - void Reset() - { - done = false; - killtimer = 60000; // if after this time there is no victim -> destroy! - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - if (!done) - { - DoCast(me, SPELL_FROZEN_ORB_AURA, true); - DoCast(me, SPELL_FROZEN_ORB_DMG, true); - done = true; - } - - if (killtimer <= diff) - { - if (!UpdateVictim()) - me->ForcedDespawn(); - killtimer = 10000; - } - else - killtimer -= diff; - } -}; - -/*###### -## Mob Frozen Orb Stalker -######*/ -struct mob_frozen_orb_stalkerAI : public Scripted_NoMovementAI -{ - mob_frozen_orb_stalkerAI(Creature* c) : Scripted_NoMovementAI(c) - { - c->SetVisibility(VISIBILITY_OFF); - c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); - c->SetReactState(REACT_PASSIVE); - - pInstance = c->GetInstanceData(); - spawned = false; - } - - ScriptedInstance *pInstance; - bool spawned; - - void UpdateAI(const uint32 /*diff*/) - { - if (spawned) - return; - - spawned = true; - if (!pInstance) - return; - - Unit* pToravon = me->GetCreature(*me, pInstance->GetData64(DATA_TORAVON)); - if (!pToravon) - return; - - uint8 num_orbs = RAID_MODE(1, 3); - for (uint8 i=0; iGetNearPoint(pToravon, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 10.0f, 0.0f); - me->SetPosition(pos, true); - DoCast(me, SPELL_FROZEN_ORB_SUMMON); - } - } -}; - -CreatureAI* GetAI_boss_toravon(Creature* pCreature) -{ - return new boss_toravonAI (pCreature); -} - -CreatureAI* GetAI_mob_frost_warder(Creature* pCreature) -{ - return new mob_frost_warderAI (pCreature); -} - -CreatureAI* GetAI_mob_frozen_orb(Creature* pCreature) -{ - return new mob_frozen_orbAI (pCreature); -} - -CreatureAI* GetAI_mob_frozen_orb_stalker(Creature* pCreature) -{ - return new mob_frozen_orb_stalkerAI (pCreature); -} - -void AddSC_boss_toravon() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_toravon"; - newscript->GetAI = &GetAI_boss_toravon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frost_warder"; - newscript->GetAI = &GetAI_mob_frost_warder; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frozen_orb"; - newscript->GetAI = &GetAI_mob_frozen_orb; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frozen_orb_stalker"; - newscript->GetAI = &GetAI_mob_frozen_orb_stalker; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp b/src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp deleted file mode 100644 index a7183921cce..00000000000 --- a/src/server/scripts/Northrend/vault_of_archavon/instance_vault_of_archavon.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "ScriptedPch.h" -#include "vault_of_archavon.h" - -#define ENCOUNTERS 4 - -/* Vault of Archavon encounters: -1 - Archavon the Stone Watcher event -2 - Emalon the Storm Watcher event -3 - Koralon the Flame Watcher event -4 - Toravon the Ice Watcher event -*/ - -struct instance_archavon : public ScriptedInstance -{ - instance_archavon(Map *Map) : ScriptedInstance(Map) {}; - - uint32 uiEncounters[ENCOUNTERS]; - - uint64 uiArchavon; - uint64 uiEmalon; - uint64 uiKoralon; - uint64 uiToravon; - - void Initialize() - { - uiArchavon = 0; - uiEmalon = 0; - uiKoralon = 0; - uiToravon = 0; - - for (uint8 i = 0; i < ENCOUNTERS; i++) - uiEncounters[i] = NOT_STARTED; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < ENCOUNTERS; i++) - if (uiEncounters[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature *creature, bool /*add*/) - { - switch(creature->GetEntry()) - { - case CREATURE_ARCHAVON: uiArchavon = creature->GetGUID(); break; - case CREATURE_EMALON: uiEmalon = creature->GetGUID(); break; - case CREATURE_KORALON: uiKoralon = creature->GetGUID(); break; - case CREATURE_TORAVON: uiToravon = creature->GetGUID(); break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_ARCHAVON_EVENT: return uiEncounters[0]; - case DATA_EMALON_EVENT: return uiEncounters[1]; - case DATA_KORALON_EVENT: return uiEncounters[2]; - case DATA_TORAVON_EVENT: return uiEncounters[3]; - } - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_ARCHAVON: return uiArchavon; - case DATA_EMALON: return uiEmalon; - case DATA_KORALON: return uiKoralon; - case DATA_TORAVON: return uiToravon; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_ARCHAVON_EVENT: uiEncounters[0] = data; break; - case DATA_EMALON_EVENT: uiEncounters[1] = data; break; - case DATA_KORALON_EVENT: uiEncounters[2] = data; break; - case DATA_TORAVON_EVENT: uiEncounters[3] = data; break; - } - - if (data == DONE) - SaveToDB(); - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << uiEncounters[0] << " " << uiEncounters[1] << " " << uiEncounters[2] << " " << uiEncounters[3]; - - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream stream(in); - stream >> uiEncounters[0] >> uiEncounters[1] >> uiEncounters[2] >> uiEncounters[3]; - - for (uint8 i = 0; i < ENCOUNTERS; ++i) - if (uiEncounters[i] == IN_PROGRESS) - uiEncounters[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_archavon(Map* map) -{ - return new instance_archavon(map); -} - -void AddSC_instance_archavon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_archavon"; - newscript->GetInstanceData = &GetInstanceData_instance_archavon; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h b/src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h deleted file mode 100644 index 6aa642ff701..00000000000 --- a/src/server/scripts/Northrend/vault_of_archavon/vault_of_archavon.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef DEF_ARCHAVON_H -#define DEF_ARCHAVON_H - -enum Creatures -{ - CREATURE_ARCHAVON = 31125, - CREATURE_EMALON = 33993, - CREATURE_KORALON = 35013, - CREATURE_TORAVON = 38433, -}; - -enum Data -{ - DATA_ARCHAVON_EVENT, - DATA_EMALON_EVENT, - DATA_KORALON_EVENT, - DATA_TORAVON_EVENT, -}; - -enum Data64 -{ - DATA_ARCHAVON, - DATA_EMALON, - DATA_KORALON, - DATA_TORAVON, -}; - -#endif diff --git a/src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp deleted file mode 100644 index 589e69a6f18..00000000000 --- a/src/server/scripts/Northrend/violet_hold/boss_cyanigosa.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* Script Data Start -SDName: Boss cyanigosa -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_ARCANE_VACUUM = 58694, - SPELL_BLIZZARD = 58693, - H_SPELL_BLIZZARD = 59369, - SPELL_MANA_DESTRUCTION = 59374, - SPELL_TAIL_SWEEP = 58690, - H_SPELL_TAIL_SWEEP = 59283, - SPELL_UNCONTROLLABLE_ENERGY = 58688, - H_SPELL_UNCONTROLLABLE_ENERGY = 59281, - SPELL_TRANSFORM = 58668 -}; - -enum Yells -{ - SAY_AGGRO = -1608000, - SAY_SLAY_1 = -1608001, - SAY_SLAY_2 = -1608002, - SAY_SLAY_3 = -1608003, - SAY_DEATH = -1608004, - SAY_SPAWN = -1608005, - SAY_DISRUPTION = -1608006, - SAY_BREATH_ATTACK = -1608007, - SAY_SPECIAL_ATTACK_1 = -1608008, - SAY_SPECIAL_ATTACK_2 = -1608009 -}; - -struct boss_cyanigosaAI : public ScriptedAI -{ - boss_cyanigosaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiArcaneVacuumTimer; - uint32 uiBlizzardTimer; - uint32 uiManaDestructionTimer; - uint32 uiTailSweepTimer; - uint32 uiUncontrollableEnergyTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiArcaneVacuumTimer = 10000; - uiBlizzardTimer = 15000; - uiManaDestructionTimer = 30000; - uiTailSweepTimer = 20000; - uiUncontrollableEnergyTimer = 25000; - if (pInstance) - pInstance->SetData(DATA_CYANIGOSA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_TRANSFORM); - - if (pInstance) - pInstance->SetData(DATA_CYANIGOSA_EVENT, IN_PROGRESS); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (pInstance && pInstance->GetData(DATA_REMOVE_NPC) == 1) - { - me->ForcedDespawn(); - pInstance->SetData(DATA_REMOVE_NPC, 0); - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiArcaneVacuumTimer <= diff) - { - DoCast(SPELL_ARCANE_VACUUM); - uiArcaneVacuumTimer = 10000; - } else uiArcaneVacuumTimer -= diff; - - if (uiBlizzardTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BLIZZARD); - uiBlizzardTimer = 15000; - } else uiBlizzardTimer -= diff; - - if (uiTailSweepTimer <= diff) - { - DoCast(SPELL_TAIL_SWEEP); - uiTailSweepTimer = 20000; - } else uiTailSweepTimer -= diff; - - if (uiUncontrollableEnergyTimer <= diff) - { - DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY); - uiUncontrollableEnergyTimer = 25000; - } else uiUncontrollableEnergyTimer -= diff; - - if (IsHeroic()) - if (uiManaDestructionTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_MANA_DESTRUCTION); - uiManaDestructionTimer = 30000; - } else uiManaDestructionTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_CYANIGOSA_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_cyanigosa(Creature* pCreature) -{ - return new boss_cyanigosaAI (pCreature); -} - -void AddSC_boss_cyanigosa() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_cyanigosa"; - newscript->GetAI = &GetAI_boss_cyanigosa; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/boss_erekem.cpp b/src/server/scripts/Northrend/violet_hold/boss_erekem.cpp deleted file mode 100644 index a9cc7393af4..00000000000 --- a/src/server/scripts/Northrend/violet_hold/boss_erekem.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* Script Data Start -SDName: Boss erekem -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_BLOODLUST = 54516, - SPELL_BREAK_BONDS = 59463, - SPELL_CHAIN_HEAL = 54481, - H_SPELL_CHAIN_HEAL = 59473, - SPELL_EARTH_SHIELD = 54479, - H_SPELL_EARTH_SHIELD = 59471, - SPELL_EARTH_SHOCK = 54511, - SPELL_LIGHTNING_BOLT = 53044, - SPELL_STORMSTRIKE = 51876 -}; - -enum Yells -{ - SAY_AGGRO = -1608010, - SAY_SLAY_1 = -1608011, - SAY_SLAY_2 = -1608012, - SAY_SLAY_3 = -1608013, - SAY_DEATH = -1608014, - SAY_SPAWN = -1608015, - SAY_ADD_KILLED = -1608016, - SAY_BOTH_ADDS_KILLED = -1608017 -}; - -struct boss_erekemAI : public ScriptedAI -{ - boss_erekemAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBloodlustTimer; - uint32 uiChainHealTimer; - uint32 uiEarthShockTimer; - uint32 uiLightningBoltTimer; - uint32 uiEarthShieldTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiBloodlustTimer = 15000; - uiChainHealTimer = 0; - uiEarthShockTimer = urand(2000,8000); - uiLightningBoltTimer = urand(5000,10000); - uiEarthShieldTimer = 20000; - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - - if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) - { - if (!pGuard1->isAlive()) - pGuard1->Respawn(); - } - if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) - { - if (!pGuard2->isAlive()) - pGuard2->Respawn(); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - - if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) - { - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - if (!pGuard1->getVictim() && pGuard1->AI()) - pGuard1->AI()->AttackStart(pWho); - } - if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) - { - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - if (!pGuard2->getVictim() && pGuard2->AI()) - pGuard2->AI()->AttackStart(pWho); - } - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_EARTH_SHIELD); - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_EREKEM_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //spam stormstrike in hc mode if spawns are dead - if (IsHeroic()) - { - if (Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0)) - { - if (Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0)) - { - if (!pGuard1->isAlive() && !pGuard2->isAlive()) - DoCast(me->getVictim(), SPELL_STORMSTRIKE); - } - } - } - - if (uiEarthShieldTimer <= diff) - { - DoCast(me, SPELL_EARTH_SHIELD); - uiEarthShieldTimer = 20000; - } else uiEarthShieldTimer -= diff; - - if (uiChainHealTimer <= diff) - { - if (uint64 TargetGUID = GetChainHealTargetGUID()) - { - if (Creature *pTarget = Unit::GetCreature(*me, TargetGUID)) - DoCast(pTarget, SPELL_CHAIN_HEAL); - - //If one of the adds is dead spawn heals faster - Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0); - Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0); - uiChainHealTimer = ((pGuard1 && !pGuard1->isAlive()) || (pGuard2 && !pGuard2->isAlive()) ? 3000 : 8000) + rand()%3000; - } - } else uiChainHealTimer -= diff; - - if (uiBloodlustTimer <= diff) - { - DoCast(me, SPELL_BLOODLUST); - uiBloodlustTimer = urand(35000,45000); - } else uiBloodlustTimer -= diff; - - if (uiEarthShockTimer <= diff) - { - DoCast(me->getVictim(), SPELL_EARTH_SHOCK); - uiEarthShockTimer = urand(8000,13000); - } else uiEarthShockTimer -= diff; - - if (uiLightningBoltTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_LIGHTNING_BOLT); - uiLightningBoltTimer = urand(18000,24000); - } else uiLightningBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - uint64 GetChainHealTargetGUID() - { - if (HealthBelowPct(85)) - return me->GetGUID(); - - Creature *pGuard1 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_1) : 0); - if (pGuard1 && pGuard1->isAlive() && (pGuard1->GetHealth()*100 <= pGuard1->GetMaxHealth() * 75)) - return pGuard1->GetGUID(); - - Creature *pGuard2 = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_EREKEM_GUARD_2) : 0); - if (pGuard2 && pGuard2->isAlive() && (pGuard2->GetHealth()*100 <= pGuard2->GetMaxHealth() * 75)) - return pGuard2->GetGUID(); - - return 0; - } -}; - -CreatureAI* GetAI_boss_erekem(Creature* pCreature) -{ - return new boss_erekemAI (pCreature); -} - -enum GuardSpells -{ - SPELL_GUSHING_WOUND = 39215, - SPELL_HOWLING_SCREECH = 54462, - SPELL_STRIKE = 14516 -}; - -struct mob_erekem_guardAI : public ScriptedAI -{ - mob_erekem_guardAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiGushingWoundTimer; - uint32 uiHowlingScreechTimer; - uint32 uiStrikeTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiStrikeTimer = urand(4000,8000); - uiHowlingScreechTimer = urand(8000,13000); - uiGushingWoundTimer = urand(1000,3000); - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - - if (uiStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STRIKE); - uiStrikeTimer = urand(4000,8000); - } else uiStrikeTimer -= diff; - - if (uiHowlingScreechTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HOWLING_SCREECH); - uiHowlingScreechTimer = urand(8000,13000); - } else uiHowlingScreechTimer -= diff; - - if (uiGushingWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GUSHING_WOUND); - uiGushingWoundTimer = urand(7000,12000); - } else uiGushingWoundTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_erekem_guard(Creature* pCreature) -{ - return new mob_erekem_guardAI (pCreature); -} - -void AddSC_boss_erekem() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_erekem"; - newscript->GetAI = &GetAI_boss_erekem; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_erekem_guard"; - newscript->GetAI = &GetAI_mob_erekem_guard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp b/src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp deleted file mode 100644 index a28bfdffb7c..00000000000 --- a/src/server/scripts/Northrend/violet_hold/boss_ichoron.cpp +++ /dev/null @@ -1,394 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Boss ichoron -SDAuthor: ckegg -SD%Complete: 80% -SDComment: TODO: better spawn location for adds -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_DRAINED = 59820, - SPELL_FRENZY = 54312, - SPELL_FRENZY_H = 59522, - SPELL_PROTECTIVE_BUBBLE = 54306, - SPELL_WATER_BLAST = 54237, - SPELL_WATER_BLAST_H = 59520, - SPELL_WATER_BOLT_VOLLEY = 54241, - SPELL_WATER_BOLT_VOLLEY_H = 59521, - SPELL_SPLASH = 59516, -}; - -enum IchoronCreatures -{ - NPC_ICHOR_GLOBULE = 29321, -}; - -enum Yells -{ - SAY_AGGRO = -1608018, - SAY_SLAY_1 = -1608019, - SAY_SLAY_2 = -1608020, - SAY_SLAY_3 = -1608021, - SAY_DEATH = -1608022, - SAY_SPAWN = -1608023, - SAY_ENRAGE = -1608024, - SAY_SHATTER = -1608025, - SAY_BUBBLE = -1608026 -}; - -enum Achievements -{ - ACHIEVEMENT_DEHYDRATION = 2041, -}; - -enum Actions -{ - ACTION_WATER_ELEMENT_HIT = 1, - ACTION_WATER_ELEMENT_KILLED = 2, -}; - -// TODO get those positions from spawn of creature 29326 -#define MAX_SPAWN_LOC 5 -static Position SpawnLoc[MAX_SPAWN_LOC]= -{ - {1840.64, 795.407, 44.079, 1.676}, - {1886.24, 757.733, 47.750, 5.201}, - {1877.91, 845.915, 43.417, 3.560}, - {1918.97, 850.645, 47.225, 4.136}, - {1935.50, 796.224, 52.492, 4.224}, -}; - -struct boss_ichoronAI : public ScriptedAI -{ - boss_ichoronAI(Creature* pCreature) : ScriptedAI(pCreature), m_waterElements(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - bool bIsExploded; - bool bIsFrenzy; - bool bAchievement; - - uint32 uiBubbleCheckerTimer; - uint32 uiWaterBoltVolleyTimer; - - ScriptedInstance* pInstance; - - SummonList m_waterElements; - - void Reset() - { - bIsExploded = false; - bIsFrenzy = false; - bAchievement = true; - uiBubbleCheckerTimer = 1000; - uiWaterBoltVolleyTimer = urand(10000, 15000); - - me->SetVisibility(VISIBILITY_ON); - DespawnWaterElements(); - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - DoCast(me, SPELL_PROTECTIVE_BUBBLE); - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ICHORON_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void DoAction(const int32 param) - { - if (!me->isAlive()) - return; - - switch(param) - { - case ACTION_WATER_ELEMENT_HIT: - me->SetHealth(me->GetHealth() + me->GetMaxHealth() * 0.01); - - if (bIsExploded) - DoExplodeCompleted(); - - bAchievement = false; - break; - case ACTION_WATER_ELEMENT_KILLED: - uint32 damage = (me->GetMaxHealth()*3)/100; - me->SetHealth(me->GetHealth() - damage); - me->LowerPlayerDamageReq(damage); - break; - } - } - - void DespawnWaterElements() - { - m_waterElements.DespawnAll(); - } - - // call when explode shall stop. - // either when "hit" by a bubble, or when there is no bubble left. - void DoExplodeCompleted() - { - bIsExploded = false; - - if (!HealthBelowPct(25)) - { - DoScriptText(SAY_BUBBLE, me); - DoCast(me, SPELL_PROTECTIVE_BUBBLE, true); - } - - me->SetVisibility(VISIBILITY_ON); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - - void MoveInLineOfSight(Unit* /*pWho*/) {} - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded) - { - DoScriptText(SAY_ENRAGE, me); - DoCast(me, SPELL_FRENZY, true); - bIsFrenzy = true; - } - - if (!bIsFrenzy) - { - if (uiBubbleCheckerTimer <= uiDiff) - { - if (!bIsExploded) - { - if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE, 0)) - { - DoScriptText(SAY_SHATTER, me); - DoCast(me, SPELL_WATER_BLAST); - DoCast(me, SPELL_DRAINED); - bIsExploded = true; - me->AttackStop(); - me->SetVisibility(VISIBILITY_OFF); - for (uint8 i = 0; i < 10; i++) - { - int tmp = urand(0, MAX_SPAWN_LOC-1); - me->SummonCreature(NPC_ICHOR_GLOBULE, SpawnLoc[tmp], TEMPSUMMON_CORPSE_DESPAWN); - } - } - } - else - { - bool bIsWaterElementsAlive = false; - if (!m_waterElements.empty()) - { - for (std::list::const_iterator itr = m_waterElements.begin(); itr != m_waterElements.end(); ++itr) - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - if (pTemp->isAlive()) - { - bIsWaterElementsAlive = true; - break; - } - } - - if (!bIsWaterElementsAlive) - DoExplodeCompleted(); - } - uiBubbleCheckerTimer = 1000; - } - else uiBubbleCheckerTimer -= uiDiff; - } - - if (!bIsExploded) - { - if (uiWaterBoltVolleyTimer <= uiDiff) - { - DoCast(me, SPELL_WATER_BOLT_VOLLEY); - uiWaterBoltVolleyTimer = urand(10000, 15000); - } - else uiWaterBoltVolleyTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (bIsExploded) - { - bIsExploded = false; - me->SetVisibility(VISIBILITY_ON); - } - - DespawnWaterElements(); - - if (pInstance) - { - if (IsHeroic() && bAchievement) - pInstance->DoCompleteAchievement(ACHIEVEMENT_DEHYDRATION); - - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->SetSpeed(MOVE_RUN, 0.3f); - pSummoned->GetMotionMaster()->MoveFollow(me, 0, 0); - m_waterElements.push_back(pSummoned->GetGUID()); - } - - - void SummonedCreatureDespawn(Creature *pSummoned) - { - m_waterElements.remove(pSummoned->GetGUID()); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_ichoron(Creature* pCreature) -{ - return new boss_ichoronAI (pCreature); -} - -struct mob_ichor_globuleAI : public ScriptedAI -{ - mob_ichor_globuleAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiRangeCheck_Timer; - - void Reset() - { - uiRangeCheck_Timer = 1000; - } - - void AttackStart(Unit* /*pWho*/) - { - return; - } - - void UpdateAI(const uint32 uiDiff) - { - if (uiRangeCheck_Timer < uiDiff) - { - if (pInstance) - { - if (Creature* pIchoron = Unit::GetCreature(*me, pInstance->GetData64(DATA_ICHORON))) - { - if (me->IsWithinDist(pIchoron, 2.0f , false)) - { - if (pIchoron->AI()) - pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT); - me->ForcedDespawn(); - } - } - } - uiRangeCheck_Timer = 1000; - } - else uiRangeCheck_Timer -= uiDiff; - } - - void JustDied(Unit* /*pKiller*/) - { - DoCast(me, SPELL_SPLASH); - if (Creature* pIchoron = Unit::GetCreature(*me, pInstance->GetData64(DATA_ICHORON))) - if (pIchoron->AI()) - pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED); - } -}; - -CreatureAI* GetAI_mob_ichor_globule(Creature* pCreature) -{ - return new mob_ichor_globuleAI (pCreature); -} - -void AddSC_boss_ichoron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ichoron"; - newscript->GetAI = &GetAI_boss_ichoron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ichor_globule"; - newscript->GetAI = &GetAI_mob_ichor_globule; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp b/src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp deleted file mode 100644 index d8cd3a4962f..00000000000 --- a/src/server/scripts/Northrend/violet_hold/boss_lavanthor.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* Script Data Start -SDName: Boss lavanthor -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_CAUTERIZING_FLAMES = 59466, //Only in heroic - SPELL_FIREBOLT = 54235, - H_SPELL_FIREBOLT = 59468, - SPELL_FLAME_BREATH = 54282, - H_SPELL_FLAME_BREATH = 59469, - SPELL_LAVA_BURN = 54249, - H_SPELL_LAVA_BURN = 59594 -}; - -struct boss_lavanthorAI : public ScriptedAI -{ - boss_lavanthorAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiFireboltTimer; - uint32 uiFlameBreathTimer; - uint32 uiLavaBurnTimer; - uint32 uiCauterizingFlamesTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiFireboltTimer = 1000; - uiFlameBreathTimer = 5000; - uiLavaBurnTimer = 10000; - uiCauterizingFlamesTimer = 3000; - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_LAVANTHOR_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiFireboltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBOLT); - uiFireboltTimer = urand(5000,13000); - } else uiFireboltTimer -= diff; - - if (uiFlameBreathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAME_BREATH); - uiFlameBreathTimer = urand(10000,15000); - } else uiFlameBreathTimer -= diff; - - if (uiLavaBurnTimer <= diff) - { - DoCast(me->getVictim(), SPELL_LAVA_BURN); - uiLavaBurnTimer = urand(15000,23000); - } - - if (IsHeroic()) - { - if (uiCauterizingFlamesTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CAUTERIZING_FLAMES); - uiCauterizingFlamesTimer = urand(10000,16000); - } else uiCauterizingFlamesTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } -}; - -CreatureAI* GetAI_boss_lavanthor(Creature* pCreature) -{ - return new boss_lavanthorAI (pCreature); -} - -void AddSC_boss_lavanthor() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_lavanthor"; - newscript->GetAI = &GetAI_boss_lavanthor; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/boss_moragg.cpp b/src/server/scripts/Northrend/violet_hold/boss_moragg.cpp deleted file mode 100644 index 6d283c7bfb4..00000000000 --- a/src/server/scripts/Northrend/violet_hold/boss_moragg.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Script Data Start -SDName: Boss moragg -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "violet_hold.h" - -//Spells -enum Spells -{ - SPELL_CORROSIVE_SALIVA = 54527, - SPELL_OPTIC_LINK = 54396 -}; - -struct boss_moraggAI : public ScriptedAI -{ - boss_moraggAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiOpticLinkTimer; - uint32 uiCorrosiveSalivaTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiOpticLinkTimer = 10000; - uiCorrosiveSalivaTimer = 5000; - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MORAGG_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiOpticLinkTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_OPTIC_LINK); - uiOpticLinkTimer = 15000; - } else uiOpticLinkTimer -= diff; - - if (uiCorrosiveSalivaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVE_SALIVA); - uiCorrosiveSalivaTimer = 10000; - } else uiCorrosiveSalivaTimer -= diff; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT,13); - } - } - } -}; - -CreatureAI* GetAI_boss_moragg(Creature* pCreature) -{ - return new boss_moraggAI (pCreature); -} - -void AddSC_boss_moragg() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_moragg"; - newscript->GetAI = &GetAI_boss_moragg; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp b/src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp deleted file mode 100644 index 2633705c1b7..00000000000 --- a/src/server/scripts/Northrend/violet_hold/boss_xevozz.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Boss xevozz -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_ARCANE_BARRAGE_VOLLEY = 54202, - SPELL_ARCANE_BARRAGE_VOLLEY_H = 59483, - SPELL_ARCANE_BUFFET = 54226, - SPELL_ARCANE_BUFFET_H = 59485, - SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102, - SPELL_SUMMON_ETHEREAL_SPHERE_2 = 54137, - SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138, -}; - -enum NPCs -{ - NPC_ETHEREAL_SPHERE = 29271, - //NPC_ETHEREAL_SPHERE2 = 32582, // heroic only? -}; - -enum CreatureSpells -{ - SPELL_ARCANE_POWER = 54160, - H_SPELL_ARCANE_POWER = 59474, - SPELL_SUMMON_PLAYERS = 54164, - SPELL_POWER_BALL_VISUAL = 54141, -}; - -enum Yells -{ - SAY_AGGRO = -1608027, - SAY_SLAY_1 = -1608028, - SAY_SLAY_2 = -1608029, - SAY_SLAY_3 = -1608030, - SAY_DEATH = -1608031, - SAY_SPAWN = -1608032, - SAY_CHARGED = -1608033, - SAY_REPEAT_SUMMON_1 = -1608034, - SAY_REPEAT_SUMMON_2 = -1608035, - SAY_SUMMON_ENERGY = -1608036 -}; - -struct boss_xevozzAI : public ScriptedAI -{ - boss_xevozzAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiSummonEtherealSphere_Timer; - uint32 uiArcaneBarrageVolley_Timer; - uint32 uiArcaneBuffet_Timer; - - void Reset() - { - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - - uiSummonEtherealSphere_Timer = urand(10000, 12000); - uiArcaneBarrageVolley_Timer = urand(20000, 22000); - uiArcaneBuffet_Timer = uiSummonEtherealSphere_Timer + urand(5000, 6000); - DespawnSphere(); - } - - void DespawnSphere() - { - std::list assistList; - GetCreatureListWithEntryInGrid(assistList,me, NPC_ETHEREAL_SPHERE ,150.0f); - - if (assistList.empty()) - return; - - for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) - { - if (Creature* pSphere = *iter) - pSphere->Kill(pSphere, false); - } - } - - void JustSummoned(Creature* pSummoned) - { - pSummoned->SetSpeed(MOVE_RUN, 0.5f); - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - pSummoned->AddThreat(pTarget, 0.00f); - pSummoned->AI()->AttackStart(pTarget); - } - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_XEVOZZ_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void MoveInLineOfSight(Unit* /*pWho*/) {} - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiArcaneBarrageVolley_Timer < uiDiff) - { - DoCast(me, SPELL_ARCANE_BARRAGE_VOLLEY); - uiArcaneBarrageVolley_Timer = urand(20000, 22000); - } - else uiArcaneBarrageVolley_Timer -= uiDiff; - - if (uiArcaneBuffet_Timer) - if (uiArcaneBuffet_Timer < uiDiff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BUFFET); - uiArcaneBuffet_Timer = 0; - } - else uiArcaneBuffet_Timer -= uiDiff; - - if (uiSummonEtherealSphere_Timer < uiDiff) - { - DoScriptText(SAY_SPAWN, me); - DoCast(me, SPELL_SUMMON_ETHEREAL_SPHERE_1); - if (IsHeroic()) // extra one for heroic - me->SummonCreature(NPC_ETHEREAL_SPHERE, me->GetPositionX()-5+rand()%10, me->GetPositionY()-5+rand()%10, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 40000); - - uiSummonEtherealSphere_Timer = urand(45000, 47000); - uiArcaneBuffet_Timer = urand(5000, 6000); - } - else uiSummonEtherealSphere_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - DespawnSphere(); - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } - void KilledUnit(Unit* pVictim) - { - if (pVictim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_xevozz(Creature* pCreature) -{ - return new boss_xevozzAI (pCreature); -} - -struct mob_ethereal_sphereAI : public ScriptedAI -{ - mob_ethereal_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiSummonPlayers_Timer; - uint32 uiRangeCheck_Timer; - - void Reset() - { - uiSummonPlayers_Timer = urand(33000, 35000); - uiRangeCheck_Timer = 1000; - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!me->HasAura(SPELL_POWER_BALL_VISUAL)) - DoCast(me, SPELL_POWER_BALL_VISUAL); - - if (uiRangeCheck_Timer < uiDiff) - { - if (pInstance) - { - if (Creature* pXevozz = Unit::GetCreature(*me, pInstance->GetData64(DATA_XEVOZZ))) - { - float fDistance = me->GetDistance2d(pXevozz); - if (fDistance <= 3) - DoCast(pXevozz, SPELL_ARCANE_POWER); - else - DoCast(me, 35845); //Is it blizzlike? - } - } - uiRangeCheck_Timer = 1000; - } - else uiRangeCheck_Timer -= uiDiff; - - if (uiSummonPlayers_Timer < uiDiff) - { - DoCast(me, SPELL_SUMMON_PLAYERS); // not working right - - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (!PlayerList.isEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource()->isAlive()) - DoTeleportPlayer(i->getSource(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), i->getSource()->GetOrientation()); - } - - uiSummonPlayers_Timer = urand(33000, 35000); - } - else uiSummonPlayers_Timer -= uiDiff; - } -}; - -CreatureAI* GetAI_mob_ethereal_sphere(Creature* pCreature) -{ - return new mob_ethereal_sphereAI (pCreature); -} - -void AddSC_boss_xevozz() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_xevozz"; - newscript->GetAI = &GetAI_boss_xevozz; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ethereal_sphere"; - newscript->GetAI = &GetAI_mob_ethereal_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp b/src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp deleted file mode 100644 index da75ed94fc2..00000000000 --- a/src/server/scripts/Northrend/violet_hold/boss_zuramat.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* Script Data Start -SDName: Boss zuramat -SD%Complete: -SDComment: The phasemask for the voids dosen't work. -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "violet_hold.h" - -enum Spells -{ - SPELL_SHROUD_OF_DARKNESS = 54524, - H_SPELL_SHROUD_OF_DARKNESS = 59745, - SPELL_SUMMON_VOID_SENTRY = 54369, - SPELL_VOID_SHIFT = 54361, - H_SPELL_VOID_SHIFT = 59743, - - SPELL_ZURAMAT_ADD_2 = 54342, - H_SPELL_ZURAMAT_ADD_2 = 59747 -}; - -enum ZuramatCreatures -{ - CREATURE_VOID_SENTRY = 29364 -}; - -enum Yells -{ - SAY_AGGRO = -1608037, - SAY_SLAY_1 = -1608038, - SAY_SLAY_2 = -1608039, - SAY_SLAY_3 = -1608040, - SAY_DEATH = -1608041, - SAY_SPAWN = -1608042, - SAY_SHIELD = -1608043, - SAY_WHISPER = -1608044 -}; - -struct boss_zuramatAI : public ScriptedAI -{ - boss_zuramatAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 SpellVoidShiftTimer; - uint32 SpellSummonVoidTimer; - uint32 SpellShroudOfDarknessTimer; - - void Reset() - { - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - - SpellShroudOfDarknessTimer = 22000; - SpellVoidShiftTimer = 15000; - SpellSummonVoidTimer = 12000; - } - - void AttackStart(Unit* pWho) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - DoStartMovement(pWho); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_ZURAMAT_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - pInstance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - pInstance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (SpellSummonVoidTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SUMMON_VOID_SENTRY, false); - SpellSummonVoidTimer = 20000; - } else SpellSummonVoidTimer -=diff; - - if (SpellVoidShiftTimer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_VOID_SHIFT); - SpellVoidShiftTimer = 20000; - } else SpellVoidShiftTimer -=diff; - - if (SpellShroudOfDarknessTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHROUD_OF_DARKNESS); - SpellShroudOfDarknessTimer = 20000; - } else SpellShroudOfDarknessTimer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (pInstance->GetData(DATA_WAVE_COUNT) == 6) - { - pInstance->SetData(DATA_1ST_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 7); - } - else if (pInstance->GetData(DATA_WAVE_COUNT) == 12) - { - pInstance->SetData(DATA_2ND_BOSS_EVENT, DONE); - pInstance->SetData(DATA_WAVE_COUNT, 13); - } - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustSummoned(Creature* summon) - { - summon->AI()->AttackStart(me->getVictim()); - summon->AI()->DoCastAOE(SPELL_ZURAMAT_ADD_2); - summon->SetPhaseMask(17,true); - } -}; - -CreatureAI* GetAI_boss_zuramat(Creature* pCreature) -{ - return new boss_zuramatAI (pCreature); -} - -void AddSC_boss_zuramat() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_zuramat"; - newscript->GetAI = &GetAI_boss_zuramat; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp b/src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp deleted file mode 100644 index 781511f940b..00000000000 --- a/src/server/scripts/Northrend/violet_hold/instance_violet_hold.cpp +++ /dev/null @@ -1,528 +0,0 @@ -#include "ScriptedPch.h" -#include "violet_hold.h" - -#define MAX_ENCOUNTER 3 - -/* Violet Hold encounters: -0 - First boss -1 - Second boss -2 - Cyanigosa*/ - -/* Violet hold bosses: -1 - Moragg -2 - Erekem -3 - Ichoron -4 - Lavanthor -5 - Xevozz -6 - Zuramat -7 - Cyanigosa */ - -enum GameObjects -{ - GO_MAIN_DOOR = 191723, - GO_XEVOZZ_DOOR = 191556, - GO_LAVANTHOR_DOOR = 191566, - GO_ICHORON_DOOR = 191722, - GO_ZURAMAT_DOOR = 191565, - GO_EREKEM_DOOR = 191564, - GO_EREKEM_GUARD_1_DOOR = 191563, - GO_EREKEM_GUARD_2_DOOR = 191562, - GO_MORAGG_DOOR = 191606, - GO_INTRO_ACTIVATION_CRYSTAL = 193615, - GO_ACTIVATION_CRYSTAL = 193611 -}; - -const Position PortalLocation[] = -{ - {1936.07, 803.198, 53.3749, 3.12414}, - {1877.51, 850.104, 44.6599, 4.7822 }, - {1890.64, 753.471, 48.7224, 1.71042}, - {1908.31, 809.657, 38.7037, 3.08701}, - {1918.37, 853.437, 47.1624, 4.12294}, - {1927.61, 758.436, 51.4533, 2.20891} -}; - -struct instance_violet_hold : public ScriptedInstance -{ - instance_violet_hold(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiMoragg; - uint64 uiErekem; - uint64 uiErekemGuard[2]; - uint64 uiIchoron; - uint64 uiLavanthor; - uint64 uiXevozz; - uint64 uiZuramat; - uint64 uiCyanigosa; - uint64 uiSinclari; - - uint64 uiMoraggCell; - uint64 uiErekemCell; - uint64 uiErekemLeftGuardCell; - uint64 uiErekemRightGuardCell; - uint64 uiIchoronCell; - uint64 uiLavanthorCell; - uint64 uiXevozzCell; - uint64 uiZuramatCell; - uint64 uiMainDoor; - - uint64 uiActivationCrystal[3]; - - uint32 uiActivationTimer; - - uint8 uiWaveCount; - uint8 uiLocation; - uint8 uiFirstBoss; - uint8 uiSecondBoss; - uint8 uiRemoveNpc; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - uint8 uiCountErekemGuards; - uint8 uiCountActivationCrystals; - - bool bActive; - bool bWiped; - - std::string str_data; - - void Initialize() - { - uiMoragg = 0; - uiErekem = 0; - uiIchoron = 0; - uiLavanthor = 0; - uiXevozz = 0; - uiZuramat = 0; - uiCyanigosa = 0; - uiSinclari = 0; - - uiMoraggCell = 0; - uiErekemCell = 0; - uiErekemGuard[0] = 0; - uiErekemGuard[1] = 0; - uiIchoronCell = 0; - uiLavanthorCell = 0; - uiXevozzCell = 0; - uiZuramatCell = 0; - uiMainDoor = 0; - uiRemoveNpc = 0; - - uiWaveCount = 0; - uiLocation = urand(0,5); - uiFirstBoss = 0; - uiSecondBoss = 0; - uiCountErekemGuards = 0; - uiCountActivationCrystals = 0; - - uiActivationTimer = 5000; - - bActive = false; - bWiped = false; - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - switch(pCreature->GetEntry()) - { - case CREATURE_XEVOZZ: - uiXevozz = pCreature->GetGUID(); - break; - case CREATURE_LAVANTHOR: - uiLavanthor = pCreature->GetGUID(); - break; - case CREATURE_ICHORON: - uiIchoron = pCreature->GetGUID(); - break; - case CREATURE_ZURAMAT: - uiZuramat = pCreature->GetGUID(); - break; - case CREATURE_EREKEM: - uiErekem = pCreature->GetGUID(); - break; - case CREATURE_EREKEM_GUARD: - if (uiCountErekemGuards < 2) - { - uiErekemGuard[uiCountErekemGuards++] = pCreature->GetGUID(); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - } - break; - case CREATURE_MORAGG: - uiMoragg = pCreature->GetGUID(); - break; - case CREATURE_CYANIGOSA: - uiCyanigosa = pCreature->GetGUID(); - break; - case CREATURE_SINCLARI: - uiSinclari = pCreature->GetGUID(); - break; - } - - if (add && (pCreature->GetGUID() == uiFirstBoss || pCreature->GetGUID() == uiSecondBoss)) - { - pCreature->AllLootRemovedFromCorpse(); - pCreature->RemoveLootMode(1); - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_EREKEM_GUARD_1_DOOR: - uiErekemLeftGuardCell = pGo->GetGUID(); - break; - case GO_EREKEM_GUARD_2_DOOR: - uiErekemRightGuardCell = pGo->GetGUID(); - break; - case GO_EREKEM_DOOR: - uiErekemCell = pGo->GetGUID(); - break; - case GO_ZURAMAT_DOOR: - uiZuramatCell = pGo->GetGUID(); - break; - case GO_LAVANTHOR_DOOR: - uiLavanthorCell = pGo->GetGUID(); - break; - case GO_MORAGG_DOOR: - uiMoraggCell = pGo->GetGUID(); - break; - case GO_ICHORON_DOOR: - uiIchoronCell = pGo->GetGUID(); - break; - case GO_XEVOZZ_DOOR: - uiXevozzCell = pGo->GetGUID(); - break; - case GO_MAIN_DOOR: - uiMainDoor = pGo->GetGUID(); - break; - case GO_ACTIVATION_CRYSTAL: - if (uiCountActivationCrystals < 3) - uiActivationCrystal[uiCountActivationCrystals++] = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_1ST_BOSS_EVENT: - m_auiEncounter[0] = data; - if (data == DONE) - SaveToDB(); - break; - case DATA_2ND_BOSS_EVENT: - m_auiEncounter[1] = data; - if (data == DONE) - SaveToDB(); - break; - case DATA_CYANIGOSA_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) - { - SaveToDB(); - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_ACTIVE); - } - break; - case DATA_WAVE_COUNT: - uiWaveCount = data; - bActive = true; - break; - case DATA_REMOVE_NPC: - uiRemoveNpc = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_1ST_BOSS_EVENT: return m_auiEncounter[0]; - case DATA_2ND_BOSS_EVENT: return m_auiEncounter[1]; - case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2]; - case DATA_WAVE_COUNT: return uiWaveCount; - case DATA_REMOVE_NPC: return uiRemoveNpc; - } - - return 0; - } - - void SpawnPortal() - { - if (Creature *pSinclari = instance->GetCreature(uiSinclari)) - if (Creature *pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL,PortalLocation[uiLocation],TEMPSUMMON_CORPSE_DESPAWN)) - uiLocation = (uiLocation+urand(1,5))%6; - } - - void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true) - { - Creature* pBoss = NULL; - - switch(uiBoss) - { - case BOSS_MORAGG: - HandleGameObject(uiMoraggCell,bForceRespawn); - pBoss = instance->GetCreature(uiMoragg); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - case BOSS_EREKEM: - HandleGameObject(uiErekemCell, bForceRespawn); - HandleGameObject(uiErekemRightGuardCell, bForceRespawn); - HandleGameObject(uiErekemLeftGuardCell, bForceRespawn); - - pBoss = instance->GetCreature(uiErekem); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - - if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0])) - { - if (bForceRespawn) - pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - else - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - } - - if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1])) - { - if (bForceRespawn) - pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - else - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - } - break; - case BOSS_ICHORON: - HandleGameObject(uiIchoronCell,bForceRespawn); - pBoss = instance->GetCreature(uiIchoron); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - case BOSS_LAVANTHOR: - HandleGameObject(uiLavanthorCell,bForceRespawn); - pBoss = instance->GetCreature(uiLavanthor); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - case BOSS_XEVOZZ: - HandleGameObject(uiXevozzCell,bForceRespawn); - pBoss = instance->GetCreature(uiXevozz); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - case BOSS_ZURAMAT: - HandleGameObject(uiZuramatCell,bForceRespawn); - pBoss = instance->GetCreature(uiZuramat); - if (pBoss) - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - break; - } - - if (!bForceRespawn && pBoss) - { - if (pBoss->isDead()) - { - // respawn but avoid to be looted again - pBoss->Respawn(); - pBoss->RemoveLootMode(1); - } - pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE|UNIT_FLAG_NON_ATTACKABLE); - SetData(DATA_WAVE_COUNT,0); - uiWaveCount = 0; - } - } - - void AddWave() - { - DoUpdateWorldState(WORLD_STATE_VH, 1); - DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, uiWaveCount); - DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); // TODO - - switch(uiWaveCount) - { - case 6: - if (uiFirstBoss == 0) - uiFirstBoss = urand(1,6); - StartBossEncounter(uiFirstBoss); - break; - case 12: - if (uiSecondBoss == 0) - do - { - uiSecondBoss = urand(1,6); - } while (uiSecondBoss == uiFirstBoss); - StartBossEncounter(uiSecondBoss); - break; - case 18: - { - Creature *pSinclari = instance->GetCreature(uiSinclari); - if (pSinclari) - pSinclari->SummonCreature(CREATURE_CYANIGOSA,PortalLocation[0],TEMPSUMMON_DEAD_DESPAWN); - break; - } - case 1: - { - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_READY); - } - default: - if (!bWiped) - SpawnPortal(); - bWiped = false; - break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_MORAGG: return uiMoragg; - case DATA_EREKEM: return uiErekem; - case DATA_EREKEM_GUARD_1: return uiErekemGuard[0]; - case DATA_EREKEM_GUARD_2: return uiErekemGuard[1]; - case DATA_ICHORON: return uiIchoron; - case DATA_LAVANTHOR: return uiLavanthor; - case DATA_XEVOZZ: return uiXevozz; - case DATA_ZURAMAT: return uiZuramat; - case DATA_CYANIGOSA: return uiCyanigosa; - case DATA_MORAGG_CELL: return uiMoraggCell; - case DATA_EREKEM_CELL: return uiErekemCell; - case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell; - case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell; - case DATA_ICHORON_CELL: return uiIchoronCell; - case DATA_LAVANTHOR_CELL: return uiLavanthorCell; - case DATA_XEVOZZ_CELL: return uiXevozzCell; - case DATA_ZURAMAT_CELL: return uiZuramatCell; - case DATA_MAIN_DOOR: return uiMainDoor; - case DATA_SINCLARI: return uiSinclari; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "V H " << (uint16)m_auiEncounter[0] - << " " << (uint16)m_auiEncounter[1] - << " " << (uint16)m_auiEncounter[2] - << " " << (uint16)uiFirstBoss - << " " << (uint16)uiSecondBoss; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; - - if (dataHead1 == 'V' && dataHead2 == 'H') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiFirstBoss = data3; - uiSecondBoss = data4; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - bool CheckWipe() - { - Map::PlayerList const &players = instance->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - return false; - } - - return true; - } - - void Update(uint32 diff) - { - if (!instance->HavePlayers()) - return; - - if (bActive) - { - if (uiActivationTimer < diff) - { - AddWave(); - bActive = false; - uiActivationTimer = 5000; - } else uiActivationTimer -= diff; - } - - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - if (pMainDoor->GetGoState() != GO_STATE_ACTIVE && CheckWipe()) - { - SetData(DATA_REMOVE_NPC, 1); - StartBossEncounter(uiFirstBoss, false); - StartBossEncounter(uiSecondBoss, false); - bWiped = true; - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) - { - pSinclari->DisappearAndDie(); - pSinclari->Respawn(true); - } - - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_ACTIVE); - SetData(DATA_WAVE_COUNT, 0); - } - } -}; - -InstanceData* GetInstanceData_instance_violet_hold(Map* pMap) -{ - return new instance_violet_hold(pMap); -} - -void AddSC_instance_violet_hold() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_violet_hold"; - newscript->GetInstanceData = &GetInstanceData_instance_violet_hold; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/violet_hold.cpp b/src/server/scripts/Northrend/violet_hold/violet_hold.cpp deleted file mode 100644 index 49883b5dbf3..00000000000 --- a/src/server/scripts/Northrend/violet_hold/violet_hold.cpp +++ /dev/null @@ -1,274 +0,0 @@ -#include "ScriptedPch.h" -#include "violet_hold.h" - -#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay." -#define GOSSIP_ITEM_1 "Activate the crystals when we get in trouble, right" -#define SPAWN_TIME 20000 - -enum PortalCreatures -{ - CREATURE_AZURE_INVADER = 30661, - CREATURE_AZURE_SPELLBREAKER = 30662, - CREATURE_AZURE_BINDER = 30663, - CREATURE_AZURE_MAGE_SLAYER = 30664, - CREATURE_AZURE_CAPTAIN = 30666, - CREATURE_AZURE_SORCEROR = 30667, - CREATURE_AZURE_RAIDER = 30668, - CREATURE_AZURE_STALKER = 32191 -}; - -enum Spells -{ - SPELL_PORTAL_CHANNEL = 58012 -}; - -enum eSinclari -{ - NPC_VIOLET_HOLD_GUARD = 30659, - - SAY_SINCLARI_1 = -1608045, -}; - -const Position DoorPosition = { 1828.300049, 797.309021, 46.135502, 1.48353}; -const Position MovePosition = { 1806.955566, 803.851807, 44.363323}; - -struct npc_sinclariAI : public ScriptedAI -{ - npc_sinclariAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiTimer; - - void Reset() - { - uiPhase = 0; - uiTimer = 0; - - me->SetVisibility(VISIBILITY_ON); - me->SetReactState(REACT_AGGRESSIVE); - - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - { - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - { - pGuard->DisappearAndDie(); - pGuard->Respawn(); - pGuard->SetVisibility(VISIBILITY_ON); - pGuard->SetReactState(REACT_AGGRESSIVE); - } - } - } - } - - void MovementInform(uint32 uiType, uint32 /*uiId*/) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (pInstance) - { - pInstance->SetData(DATA_WAVE_COUNT,1); - pInstance->SetData(DATA_REMOVE_NPC,0); // might not have been reset after a wipe on a boss. - } - - //She should not be despawned, she will be used by the instance to summon some npcs - me->SetVisibility(VISIBILITY_OFF); - me->SetReactState(REACT_PASSIVE); - } - - void UpdateAI(const uint32 uiDiff) - { - ScriptedAI::UpdateAI(uiDiff); - - if (uiPhase) - { - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - DoScriptText(SAY_SINCLARI_1, me); - uiTimer = 4000; - uiPhase = 2; - break; - case 2: - { - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - { - pGuard->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pGuard->GetMotionMaster()->MovePoint(0, MovePosition); - } - } - uiTimer = 6000; - uiPhase = 3; - break; - } - case 3: - { - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - { - pGuard->SetVisibility(VISIBILITY_OFF); - pGuard->SetReactState(REACT_PASSIVE); - } - } - uiTimer = 2000; - uiPhase = 4; - break; - } - case 4: - me->GetMotionMaster()->MovePoint(0, MovePosition); - uiTimer = 0; - uiPhase = 0; - break; - } - } - else uiTimer -= uiDiff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_sinclari(Creature* pCreature) -{ - return new npc_sinclariAI(pCreature); -} - -bool GossipHello_npc_sinclari(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance && pInstance->GetData(DATA_CYANIGOSA_EVENT) != DONE && pInstance->GetData(DATA_WAVE_COUNT) == 0 && pPlayer) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_1,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_START_EVENT,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(13853, pCreature->GetGUID()); - }else - pPlayer->SEND_GOSSIP_MENU(13910, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_sinclari(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - if (pPlayer) - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_sinclariAI, (pCreature->AI()))->uiPhase = 1; - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->SEND_GOSSIP_MENU(13854, pCreature->GetGUID()); - break; - } - return true; -} - -struct npc_teleportation_portalAI : public ScriptedAI -{ - npc_teleportation_portalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiSpawnTimer; - bool bPortalGuardianOrKeeperSpawn; - - ScriptedInstance *pInstance; - - void Reset() - { - uiSpawnTimer = 10000; - bPortalGuardianOrKeeperSpawn = false; - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (pInstance && pInstance->GetData(DATA_REMOVE_NPC) == 1) - { - me->ForcedDespawn(); - pInstance->SetData(DATA_REMOVE_NPC, 0); - } - - if (uiSpawnTimer <= diff) - { - if (bPortalGuardianOrKeeperSpawn) - { - uint8 k = pInstance->GetData(DATA_WAVE_COUNT) < 12 ? 2 : 3; - for (uint8 i = 0; i < k; ++i) - { - uint32 entry = RAND(CREATURE_AZURE_CAPTAIN,CREATURE_AZURE_RAIDER,CREATURE_AZURE_STALKER,CREATURE_AZURE_SORCEROR); - if (Creature* pSummon = DoSummon(entry, me, 2.0f, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) - pSummon->GetMotionMaster()->MovePoint(0, DoorPosition); - } - } - else - { - bPortalGuardianOrKeeperSpawn = true; - uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER); - if (Creature *pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) - me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false); - } - uiSpawnTimer = SPAWN_TIME; - } else uiSpawnTimer -= diff; - - if (bPortalGuardianOrKeeperSpawn && !me->IsNonMeleeSpellCasted(false)) - { - me->Kill(me, false); - me->RemoveCorpse(); - return; - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_WAVE_COUNT,pInstance->GetData(DATA_WAVE_COUNT)+1); - } -}; - -CreatureAI* GetAI_npc_teleportation_portal(Creature *pCreature) -{ - return new npc_teleportation_portalAI(pCreature); -} - -void AddSC_violet_hold() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sinclari_vh"; - newscript->GetAI = &GetAI_npc_sinclari; - newscript->pGossipHello = &GossipHello_npc_sinclari; - newscript->pGossipSelect = &GossipSelect_npc_sinclari; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_teleportation_portal_vh"; - newscript->GetAI = &GetAI_npc_teleportation_portal; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/violet_hold/violet_hold.h b/src/server/scripts/Northrend/violet_hold/violet_hold.h deleted file mode 100644 index 4476d5e823a..00000000000 --- a/src/server/scripts/Northrend/violet_hold/violet_hold.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef DEF_VIOLET_HOLD_H -#define DEF_VIOLET_HOLD_H - -enum Creatures -{ - CREATURE_TELEPORTATION_PORTAL = 31011, - CREATURE_PORTAL_GUARDIAN = 30660, - CREATURE_PORTAL_KEEPER = 30695, - CREATURE_XEVOZZ = 29266, - CREATURE_LAVANTHOR = 29312, - CREATURE_ICHORON = 29313, - CREATURE_ZURAMAT = 29314, - CREATURE_EREKEM = 29315, - CREATURE_EREKEM_GUARD = 29395, - CREATURE_MORAGG = 29316, - CREATURE_CYANIGOSA = 31134, - CREATURE_SINCLARI = 30658 -}; - -enum Data -{ - DATA_1ST_BOSS_EVENT, - DATA_2ND_BOSS_EVENT, - DATA_CYANIGOSA_EVENT, - DATA_WAVE_COUNT, - DATA_REMOVE_NPC -}; - -enum Data64 -{ - DATA_MORAGG, - DATA_EREKEM, - DATA_EREKEM_GUARD_1, - DATA_EREKEM_GUARD_2, - DATA_ICHORON, - DATA_LAVANTHOR, - DATA_XEVOZZ, - DATA_ZURAMAT, - DATA_CYANIGOSA, - DATA_MORAGG_CELL, - DATA_EREKEM_CELL, - DATA_EREKEM_LEFT_GUARD_CELL, - DATA_EREKEM_RIGHT_GUARD_CELL, - DATA_ICHORON_CELL, - DATA_LAVANTHOR_CELL, - DATA_XEVOZZ_CELL, - DATA_ZURAMAT_CELL, - DATA_MAIN_DOOR, - DATA_SINCLARI -}; - -enum Bosses -{ - BOSS_NONE, // 0 used as marker for not yet randomized - BOSS_MORAGG, - BOSS_EREKEM, - BOSS_ICHORON, - BOSS_LAVANTHOR, - BOSS_XEVOZZ, - BOSS_ZURAMAT, - BOSS_CYANIGOSA -}; - -enum VHWorldStates -{ - WORLD_STATE_VH = 3816, - WORLD_STATE_VH_PRISON_STATE = 3815, - WORLD_STATE_VH_WAVE_COUNT = 3810, -}; - -#endif diff --git a/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp b/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp new file mode 100644 index 00000000000..bfde95ffcb0 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp @@ -0,0 +1,348 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Exarch_Maladaar +SD%Complete: 95 +SDComment: Most of event implemented, some adjustments to timers remain and possibly make some better code for switching his dark side in to better "images" of player. +SDCategory: Auchindoun, Auchenai Crypts +EndScriptData */ + +/* ContentData +mob_stolen_soul +boss_exarch_maladaar +mob_avatar_of_martyred +EndContentData */ + +#include "ScriptedPch.h" + +#define SPELL_MOONFIRE 37328 +#define SPELL_FIREBALL 37329 +#define SPELL_MIND_FLAY 37330 +#define SPELL_HEMORRHAGE 37331 +#define SPELL_FROSTSHOCK 37332 +#define SPELL_CURSE_OF_AGONY 37334 +#define SPELL_MORTAL_STRIKE 37335 +#define SPELL_FREEZING_TRAP 37368 +#define SPELL_HAMMER_OF_JUSTICE 37369 + +struct mob_stolen_soulAI : public ScriptedAI +{ + mob_stolen_soulAI(Creature *c) : ScriptedAI(c) {} + + uint8 myClass; + uint32 Class_Timer; + + void Reset() + { + Class_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { } + + void SetMyClass(uint8 myclass) + { + myClass = myclass; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Class_Timer <= diff) + { + switch (myClass) + { + case CLASS_WARRIOR: + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + Class_Timer = 6000; + break; + case CLASS_PALADIN: + DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); + Class_Timer = 6000; + break; + case CLASS_HUNTER: + DoCast(me->getVictim(), SPELL_FREEZING_TRAP); + Class_Timer = 20000; + break; + case CLASS_ROGUE: + DoCast(me->getVictim(), SPELL_HEMORRHAGE); + Class_Timer = 10000; + break; + case CLASS_PRIEST: + DoCast(me->getVictim(), SPELL_MIND_FLAY); + Class_Timer = 5000; + break; + case CLASS_SHAMAN: + DoCast(me->getVictim(), SPELL_FROSTSHOCK); + Class_Timer = 8000; + break; + case CLASS_MAGE: + DoCast(me->getVictim(), SPELL_FIREBALL); + Class_Timer = 5000; + break; + case CLASS_WARLOCK: + DoCast(me->getVictim(), SPELL_CURSE_OF_AGONY); + Class_Timer = 20000; + break; + case CLASS_DRUID: + DoCast(me->getVictim(), SPELL_MOONFIRE); + Class_Timer = 10000; + break; + } + } else Class_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_stolen_soul(Creature* pCreature) +{ + return new mob_stolen_soulAI (pCreature); +} + +#define SAY_INTRO -1558000 +#define SAY_SUMMON -1558001 + +#define SAY_AGGRO_1 -1558002 +#define SAY_AGGRO_2 -1558003 +#define SAY_AGGRO_3 -1558004 + +#define SAY_ROAR -1558005 +#define SAY_SOUL_CLEAVE -1558006 + +#define SAY_SLAY_1 -1558007 +#define SAY_SLAY_2 -1558008 + +#define SAY_DEATH -1558009 + +#define SPELL_RIBBON_OF_SOULS 32422 +#define SPELL_SOUL_SCREAM 32421 + +#define SPELL_STOLEN_SOUL 32346 +#define SPELL_STOLEN_SOUL_VISUAL 32395 + +#define SPELL_SUMMON_AVATAR 32424 + +#define ENTRY_STOLEN_SOUL 18441 + +struct boss_exarch_maladaarAI : public ScriptedAI +{ + boss_exarch_maladaarAI(Creature *c) : ScriptedAI(c) + { + HasTaunted = false; + } + + uint32 soulmodel; + uint64 soulholder; + uint8 soulclass; + + uint32 Fear_timer; + uint32 Ribbon_of_Souls_timer; + uint32 StolenSoul_Timer; + + bool HasTaunted; + bool Avatar_summoned; + + void Reset() + { + soulmodel = 0; + soulholder = 0; + soulclass = 0; + + Fear_timer = 15000 + rand()% 5000; + Ribbon_of_Souls_timer = 5000; + StolenSoul_Timer = 25000 + rand()% 10000; + + Avatar_summoned = false; + } + + void MoveInLineOfSight(Unit *who) + { + if (!HasTaunted && me->IsWithinDistInMap(who, 150.0)) + { + DoScriptText(SAY_INTRO, me); + HasTaunted = true; + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == ENTRY_STOLEN_SOUL) + { + //SPELL_STOLEN_SOUL_VISUAL has shapeshift effect, but not implemented feature in Trinity for this spell. + summoned->CastSpell(summoned,SPELL_STOLEN_SOUL_VISUAL,false); + summoned->SetDisplayId(soulmodel); + summoned->setFaction(me->getFaction()); + + if (Unit *pTarget = Unit::GetUnit(*me,soulholder)) + { + + CAST_AI(mob_stolen_soulAI, summoned->AI())->SetMyClass(soulclass); + summoned->AI()->AttackStart(pTarget); + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + //When Exarch Maladar is defeated D'ore appear. + me->SummonCreature(19412, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!Avatar_summoned && ((me->GetHealth()*100) / me->GetMaxHealth() < 25)) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(SAY_SUMMON, me); + + DoCast(me, SPELL_SUMMON_AVATAR); + Avatar_summoned = true; + StolenSoul_Timer = 15000 + rand()% 15000; + } + + if (StolenSoul_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + uint32 i = urand(1,2); + if (i == 1) + DoScriptText(SAY_ROAR, me); + else + DoScriptText(SAY_SOUL_CLEAVE, me); + + soulmodel = pTarget->GetDisplayId(); + soulholder = pTarget->GetGUID(); + soulclass = pTarget->getClass(); + + DoCast(pTarget, SPELL_STOLEN_SOUL); + me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); + + StolenSoul_Timer = 20000 + rand()% 10000; + } else StolenSoul_Timer = 1000; + } + } else StolenSoul_Timer -= diff; + + if (Ribbon_of_Souls_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_RIBBON_OF_SOULS); + + Ribbon_of_Souls_timer = 5000 + (rand()%20 * 1000); + } else Ribbon_of_Souls_timer -= diff; + + if (Fear_timer <= diff) + { + DoCast(me, SPELL_SOUL_SCREAM); + Fear_timer = 15000 + rand()% 15000; + } else Fear_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_exarch_maladaar(Creature* pCreature) +{ + return new boss_exarch_maladaarAI (pCreature); +} + +#define SPELL_AV_MORTAL_STRIKE 16856 +#define SPELL_AV_SUNDER_ARMOR 16145 + +struct mob_avatar_of_martyredAI : public ScriptedAI +{ + mob_avatar_of_martyredAI(Creature *c) : ScriptedAI(c) {} + + uint32 Mortal_Strike_timer; + + void Reset() + { + Mortal_Strike_timer = 10000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Mortal_Strike_timer <= diff) + { + DoCast(me->getVictim(), SPELL_AV_MORTAL_STRIKE); + Mortal_Strike_timer = 10000 + rand()%20 * 1000; + } else Mortal_Strike_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_avatar_of_martyred(Creature* pCreature) +{ + return new mob_avatar_of_martyredAI (pCreature); +} + +void AddSC_boss_exarch_maladaar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_exarch_maladaar"; + newscript->GetAI = &GetAI_boss_exarch_maladaar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_avatar_of_martyred"; + newscript->GetAI = &GetAI_mob_avatar_of_martyred; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stolen_soul"; + newscript->GetAI = &GetAI_mob_stolen_soul; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp new file mode 100644 index 00000000000..c13e2905171 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp @@ -0,0 +1,211 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +Name: Boss_Shirrak_the_dead_watcher +%Complete: 80 +Comment: InhibitMagic should stack slower far from the boss, proper Visual for Focus Fire, heroic implemented +Category: Auchindoun, Auchenai Crypts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_INHIBITMAGIC 32264 +#define SPELL_ATTRACTMAGIC 32265 +#define N_SPELL_CARNIVOROUSBITE 36383 +#define H_SPELL_CARNIVOROUSBITE 39382 +#define SPELL_CARNIVOROUSBITE DUNGEON_MODE(N_SPELL_CARNIVOROUSBITE, H_SPELL_CARNIVOROUSBITE) + +#define ENTRY_FOCUS_FIRE 18374 + +#define N_SPELL_FIERY_BLAST 32302 +#define H_SPELL_FIERY_BLAST 38382 +#define SPELL_FIERY_BLAST DUNGEON_MODE(N_SPELL_FIERY_BLAST, H_SPELL_FIERY_BLAST) +#define SPELL_FOCUS_FIRE_VISUAL 42075 //need to find better visual + +#define EMOTE_FOCUSES_ON "focuses on " + +struct boss_shirrak_the_dead_watcherAI : public ScriptedAI +{ + boss_shirrak_the_dead_watcherAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Inhibitmagic_Timer; + uint32 Attractmagic_Timer; + uint32 Carnivorousbite_Timer; + uint32 FocusFire_Timer; + + uint64 FocusedTargetGUID; + + void Reset() + { + Inhibitmagic_Timer = 0; + Attractmagic_Timer = 28000; + Carnivorousbite_Timer = 10000; + FocusFire_Timer = 17000; + FocusedTargetGUID = 0; + } + + void EnterCombat(Unit * /*who*/) + { } + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == ENTRY_FOCUS_FIRE) + { + summoned->CastSpell(summoned,SPELL_FOCUS_FIRE_VISUAL,false); + summoned->setFaction(me->getFaction()); + summoned->SetLevel(me->getLevel()); + summoned->addUnitState(UNIT_STAT_ROOT); + + if (Unit *pFocusedTarget = Unit::GetUnit(*me, FocusedTargetGUID)) + summoned->AI()->AttackStart(pFocusedTarget); + } + } + + void UpdateAI(const uint32 diff) + { + //Inhibitmagic_Timer + if (Inhibitmagic_Timer <= diff) + { + float dist; + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* i_pl = i->getSource()) + if (i_pl->isAlive() && (dist = i_pl->IsWithinDist(me, 45))) + { + i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC); + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 35) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 25) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 15) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + } + Inhibitmagic_Timer = 3000+(rand()%1000); + } else Inhibitmagic_Timer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Attractmagic_Timer + if (Attractmagic_Timer <= diff) + { + DoCast(me, SPELL_ATTRACTMAGIC); + Attractmagic_Timer = 30000; + Carnivorousbite_Timer = 1500; + } else Attractmagic_Timer -= diff; + + //Carnivorousbite_Timer + if (Carnivorousbite_Timer <= diff) + { + DoCast(me, SPELL_CARNIVOROUSBITE); + Carnivorousbite_Timer = 10000; + } else Carnivorousbite_Timer -= diff; + + //FocusFire_Timer + if (FocusFire_Timer <= diff) + { + // Summon Focus Fire & Emote + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + { + FocusedTargetGUID = pTarget->GetGUID(); + me->SummonCreature(ENTRY_FOCUS_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,5500); + + // TODO: Find better way to handle emote + // Emote + std::string *emote = new std::string(EMOTE_FOCUSES_ON); + emote->append(pTarget->GetName()); + emote->append("!"); + const char* text = emote->c_str(); + me->MonsterTextEmote(text, 0, true); + delete emote; + } + FocusFire_Timer = 15000+(rand()%5000); + } else FocusFire_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shirrak_the_dead_watcher(Creature* pCreature) +{ + return new boss_shirrak_the_dead_watcherAI (pCreature); +} + +struct mob_focus_fireAI : public ScriptedAI +{ + mob_focus_fireAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 FieryBlast_Timer; + bool fiery1, fiery2; + + void Reset() + { + FieryBlast_Timer = 3000+(rand()%1000); + fiery1 = fiery2 = true; + } + + void EnterCombat(Unit * /*who*/) + { } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FieryBlast_Timer + if (fiery2 && FieryBlast_Timer <= diff) + { + DoCast(me, SPELL_FIERY_BLAST); + + if (fiery1) fiery1 = false; + else if (fiery2) fiery2 = false; + + FieryBlast_Timer = 1000; + } else FieryBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_focus_fire(Creature* pCreature) +{ + return new mob_focus_fireAI (pCreature); +} + +void AddSC_boss_shirrak_the_dead_watcher() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shirrak_the_dead_watcher"; + newscript->GetAI = &GetAI_boss_shirrak_the_dead_watcher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_focus_fire"; + newscript->GetAI = &GetAI_mob_focus_fire; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp b/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp new file mode 100644 index 00000000000..5b15178c33e --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp @@ -0,0 +1,358 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_NexusPrince_Shaffar +SD%Complete: 80 +SDComment: Need more tuning of spell timers, it should not be as linear fight as current. Also should possibly find a better way to deal with his three initial beacons to make sure all aggro. +SDCategory: Auchindoun, Mana Tombs +EndScriptData */ + +/* ContentData +boss_nexusprince_shaffar +mob_ethereal_beacon +EndContentData */ + +#include "ScriptedPch.h" + +enum ePrince +{ + SAY_INTRO = -1557000, + SAY_AGGRO_1 = -1557001, + SAY_AGGRO_2 = -1557002, + SAY_AGGRO_3 = -1557003, + SAY_SLAY_1 = -1557004, + SAY_SLAY_2 = -1557005, + SAY_SUMMON = -1557006, + SAY_DEAD = -1557007, + + SPELL_BLINK = 34605, + SPELL_FROSTBOLT = 32364, + SPELL_FIREBALL = 32363, + SPELL_FROSTNOVA = 32365, + + SPELL_ETHEREAL_BEACON = 32371, // Summons NPC_BEACON + SPELL_ETHEREAL_BEACON_VISUAL = 32368, + + NPC_BEACON = 18431, + NPC_SHAFFAR = 18344, + + NR_INITIAL_BEACONS = 3 +}; + +struct boss_nexusprince_shaffarAI : public ScriptedAI +{ + boss_nexusprince_shaffarAI(Creature *c) : ScriptedAI(c), summons(me) { HasTaunted = false; } + + uint32 Blink_Timer; + uint32 Beacon_Timer; + uint32 FireBall_Timer; + uint32 Frostbolt_Timer; + uint32 FrostNova_Timer; + + SummonList summons; + + bool HasTaunted; + bool CanBlink; + + void Reset() + { + Blink_Timer = 1500; + Beacon_Timer = 10000; + FireBall_Timer = 8000; + Frostbolt_Timer = 4000; + FrostNova_Timer = 15000; + + CanBlink = false; + + float dist = 8.0f; + float posX, posY, posZ, angle; + me->GetHomePosition(posX, posY, posZ, angle); + + me->SummonCreature(NPC_BEACON, posX - dist, posY - dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + me->SummonCreature(NPC_BEACON, posX - dist, posY + dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + me->SummonCreature(NPC_BEACON, posX + dist, posY, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + } + + void EnterEvadeMode() + { + summons.DespawnAll(); + ScriptedAI::EnterEvadeMode(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!HasTaunted && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 100.0f)) + { + DoScriptText(SAY_INTRO, me); + HasTaunted = true; + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + DoZoneInCombat(); + summons.DoZoneInCombat(); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == NPC_BEACON) + { + summoned->CastSpell(summoned,SPELL_ETHEREAL_BEACON_VISUAL,false); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(pTarget); + } + + summons.Summon(summoned); + } + + void SummonedCreatureDespawn(Creature *summon) + { + summons.Despawn(summon); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEAD, me); + summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (FrostNova_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoCast(me, SPELL_FROSTNOVA); + FrostNova_Timer = 17500 + rand()%7500; + CanBlink = true; + } else FrostNova_Timer -= diff; + + if (Frostbolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 4500 + rand()%1500; + } else Frostbolt_Timer -= diff; + + if (FireBall_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL); + FireBall_Timer = 4500 + rand()%1500; + } else FireBall_Timer -= diff; + + if (CanBlink) + { + if (Blink_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + //expire movement, will prevent from running right back to victim after cast + //(but should MoveChase be used again at a certain time or should he not move?) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + + DoCast(me, SPELL_BLINK); + Blink_Timer = 1000 + rand()%1500; + CanBlink = false; + } else Blink_Timer -= diff; + } + + if (Beacon_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + if (!urand(0,3)) + DoScriptText(SAY_SUMMON, me); + + DoCast(me, SPELL_ETHEREAL_BEACON, true); + + Beacon_Timer = 10000; + } else Beacon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nexusprince_shaffar(Creature* pCreature) +{ + return new boss_nexusprince_shaffarAI (pCreature); +} + +enum eEnums +{ + SPELL_ARCANE_BOLT = 15254, + SPELL_ETHEREAL_APPRENTICE = 32372 // Summon 18430 +}; + +struct mob_ethereal_beaconAI : public ScriptedAI +{ + mob_ethereal_beaconAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Apprentice_Timer; + uint32 ArcaneBolt_Timer; + uint32 Check_Timer; + + void KillSelf() + { + me->Kill(me); + } + + void Reset() + { + Apprentice_Timer = DUNGEON_MODE(20000, 10000); + ArcaneBolt_Timer = 1000; + Check_Timer = 1000; + } + + void EnterCombat(Unit * who) + { + // Send Shaffar to fight + Creature* Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); + if (!Shaffar || Shaffar->isDead()) + { + KillSelf(); + return; + } + if (!Shaffar->isInCombat()) + Shaffar->AI()->AttackStart(who); + } + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(me->getVictim()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Check_Timer <= diff) + { + Creature *Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); + if (!Shaffar || Shaffar->isDead() || !Shaffar->isInCombat()) + { + KillSelf(); + return; + } + Check_Timer = 1000; + } else Check_Timer -= diff; + + if (ArcaneBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BOLT); + ArcaneBolt_Timer = 2000 + rand()%2500; + } else ArcaneBolt_Timer -= diff; + + if (Apprentice_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoCast(me, SPELL_ETHEREAL_APPRENTICE, true); + me->ForcedDespawn(); + return; + } else Apprentice_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_ethereal_beacon(Creature* pCreature) +{ + return new mob_ethereal_beaconAI (pCreature); +} + +enum eEthereal +{ + SPELL_ETHEREAL_APPRENTICE_FIREBOLT = 32369, + SPELL_ETHEREAL_APPRENTICE_FROSTBOLT = 32370 +}; + +struct mob_ethereal_apprenticeAI : public ScriptedAI +{ + mob_ethereal_apprenticeAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cast_Timer; + + bool isFireboltTurn; + + void Reset() + { + Cast_Timer = 3000; + isFireboltTurn = true; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Cast_Timer <= diff) + { + if (isFireboltTurn) + { + DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FIREBOLT, true); + isFireboltTurn = false; + }else{ + DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FROSTBOLT, true); + isFireboltTurn = true; + } + Cast_Timer = 3000; + } else Cast_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_ethereal_apprentice(Creature* pCreature) +{ + return new mob_ethereal_apprenticeAI (pCreature); +} + +void AddSC_boss_nexusprince_shaffar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_nexusprince_shaffar"; + newscript->GetAI = &GetAI_boss_nexusprince_shaffar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ethereal_beacon"; + newscript->GetAI = &GetAI_mob_ethereal_beacon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ethereal_apprentice"; + newscript->GetAI = &GetAI_mob_ethereal_apprentice; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp b/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp new file mode 100644 index 00000000000..51ec2e83b46 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp @@ -0,0 +1,126 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Pandemonius +SD%Complete: 75 +SDComment: Not known how void blast is done (amount of rapid cast seems to be related to players in party). All mobs remaining in surrounding area should aggro when engaged. +SDCategory: Auchindoun, Mana Tombs +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1557008 +#define SAY_AGGRO_2 -1557009 +#define SAY_AGGRO_3 -1557010 + +#define SAY_KILL_1 -1557011 +#define SAY_KILL_2 -1557012 + +#define SAY_DEATH -1557013 + +#define EMOTE_DARK_SHELL -1557014 + +#define SPELL_VOID_BLAST 32325 +#define H_SPELL_VOID_BLAST 38760 +#define SPELL_DARK_SHELL 32358 +#define H_SPELL_DARK_SHELL 38759 + +struct boss_pandemoniusAI : public ScriptedAI +{ + boss_pandemoniusAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 VoidBlast_Timer; + uint32 DarkShell_Timer; + uint32 VoidBlast_Counter; + + void Reset() + { + VoidBlast_Timer = 8000+rand()%15000; + DarkShell_Timer = 20000; + VoidBlast_Counter = 0; + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (VoidBlast_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_VOID_BLAST); + VoidBlast_Timer = 500; + ++VoidBlast_Counter; + } + + if (VoidBlast_Counter == 5) + { + VoidBlast_Timer = 15000+rand()%10000; + VoidBlast_Counter = 0; + } + } else VoidBlast_Timer -= diff; + + if (!VoidBlast_Counter) + { + if (DarkShell_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(EMOTE_DARK_SHELL, me); + + DoCast(me, SPELL_DARK_SHELL); + DarkShell_Timer = 20000; + } else DarkShell_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_pandemonius(Creature* pCreature) +{ + return new boss_pandemoniusAI (pCreature); +} + +void AddSC_boss_pandemonius() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_pandemonius"; + newscript->GetAI = &GetAI_boss_pandemonius; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp b/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp new file mode 100644 index 00000000000..9628fa1a98f --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp @@ -0,0 +1,414 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Darkweaver_Syth +SD%Complete: 85 +SDComment: Shock spells/times need more work. Heroic partly implemented. +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_SUMMON -1556000 + +#define SAY_AGGRO_1 -1556001 +#define SAY_AGGRO_2 -1556002 +#define SAY_AGGRO_3 -1556003 + +#define SAY_SLAY_1 -1556004 +#define SAY_SLAY_2 -1556005 + +#define SAY_DEATH -1556006 + +#define SPELL_FROST_SHOCK 21401 //37865 +#define SPELL_FLAME_SHOCK 34354 +#define SPELL_SHADOW_SHOCK 30138 +#define SPELL_ARCANE_SHOCK 37132 + +#define SPELL_CHAIN_LIGHTNING 15659 //15305 + +#define SPELL_SUMMON_SYTH_FIRE 33537 // Spawns 19203 +#define SPELL_SUMMON_SYTH_ARCANE 33538 // Spawns 19205 +#define SPELL_SUMMON_SYTH_FROST 33539 // Spawns 19204 +#define SPELL_SUMMON_SYTH_SHADOW 33540 // Spawns 19206 + +#define SPELL_FLAME_BUFFET DUNGEON_MODE(33526, 38141) +#define SPELL_ARCANE_BUFFET DUNGEON_MODE(33527, 38138) +#define SPELL_FROST_BUFFET DUNGEON_MODE(33528, 38142) +#define SPELL_SHADOW_BUFFET DUNGEON_MODE(33529, 38143) + +struct boss_darkweaver_sythAI : public ScriptedAI +{ + boss_darkweaver_sythAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 flameshock_timer; + uint32 arcaneshock_timer; + uint32 frostshock_timer; + uint32 shadowshock_timer; + uint32 chainlightning_timer; + + bool summon90; + bool summon50; + bool summon10; + + void Reset() + { + flameshock_timer = 2000; + arcaneshock_timer = 4000; + frostshock_timer = 6000; + shadowshock_timer = 8000; + chainlightning_timer = 15000; + + summon90 = false; + summon50 = false; + summon10 = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustSummoned(Creature *summoned) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(pTarget); + } + + void SythSummoning() + { + DoScriptText(SAY_SUMMON, me); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me, SPELL_SUMMON_SYTH_ARCANE, true); //front + DoCast(me, SPELL_SUMMON_SYTH_FIRE, true); //back + DoCast(me, SPELL_SUMMON_SYTH_FROST, true); //left + DoCast(me, SPELL_SUMMON_SYTH_SHADOW, true); //right + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 90) && !summon90) + { + SythSummoning(); + summon90 = true; + } + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 50) && !summon50) + { + SythSummoning(); + summon50 = true; + } + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 10) && !summon10) + { + SythSummoning(); + summon10 = true; + } + + if (flameshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_SHOCK); + + flameshock_timer = 10000 + rand()%5000; + } else flameshock_timer -= diff; + + if (arcaneshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_SHOCK); + + arcaneshock_timer = 10000 + rand()%5000; + } else arcaneshock_timer -= diff; + + if (frostshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_SHOCK); + + frostshock_timer = 10000 + rand()%5000; + } else frostshock_timer -= diff; + + if (shadowshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_SHOCK); + + shadowshock_timer = 10000 + rand()%5000; + } else shadowshock_timer -= diff; + + if (chainlightning_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + + chainlightning_timer = 25000; + } else chainlightning_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_darkweaver_syth(Creature* pCreature) +{ + return new boss_darkweaver_sythAI (pCreature); +} + +/* ELEMENTALS */ + +struct mob_syth_fireAI : public ScriptedAI +{ + mob_syth_fireAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 flameshock_timer; + uint32 flamebuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + flameshock_timer = 2500; + flamebuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (flameshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_SHOCK); + + flameshock_timer = 5000; + } else flameshock_timer -= diff; + + if (flamebuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_BUFFET); + + flamebuffet_timer = 5000; + } else flamebuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_fire(Creature* pCreature) +{ + return new mob_syth_fireAI (pCreature); +} + +struct mob_syth_arcaneAI : public ScriptedAI +{ + mob_syth_arcaneAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 arcaneshock_timer; + uint32 arcanebuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); + arcaneshock_timer = 2500; + arcanebuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (arcaneshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_SHOCK); + + arcaneshock_timer = 5000; + } else arcaneshock_timer -= diff; + + if (arcanebuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_BUFFET); + + arcanebuffet_timer = 5000; + } else arcanebuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_arcane(Creature* pCreature) +{ + return new mob_syth_arcaneAI (pCreature); +} + +struct mob_syth_frostAI : public ScriptedAI +{ + mob_syth_frostAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 frostshock_timer; + uint32 frostbuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + frostshock_timer = 2500; + frostbuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (frostshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_SHOCK); + + frostshock_timer = 5000; + } else frostshock_timer -= diff; + + if (frostbuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_BUFFET); + + frostbuffet_timer = 5000; + } else frostbuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_frost(Creature* pCreature) +{ + return new mob_syth_frostAI (pCreature); +} + +struct mob_syth_shadowAI : public ScriptedAI +{ + mob_syth_shadowAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 shadowshock_timer; + uint32 shadowbuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + shadowshock_timer = 2500; + shadowbuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (shadowshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_SHOCK); + + shadowshock_timer = 5000; + } else shadowshock_timer -= diff; + + if (shadowbuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_BUFFET); + + shadowbuffet_timer = 5000; + } else shadowbuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_shadow(Creature* pCreature) +{ + return new mob_syth_shadowAI (pCreature); +} + +void AddSC_boss_darkweaver_syth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_darkweaver_syth"; + newscript->GetAI = &GetAI_boss_darkweaver_syth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_fire"; + newscript->GetAI = &GetAI_mob_syth_arcane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_arcane"; + newscript->GetAI = &GetAI_mob_syth_arcane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_frost"; + newscript->GetAI = &GetAI_mob_syth_frost; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_shadow"; + newscript->GetAI = &GetAI_mob_syth_shadow; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp new file mode 100644 index 00000000000..32b97293ca3 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp @@ -0,0 +1,213 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Talon_King_Ikiss +SD%Complete: 80 +SDComment: Heroic supported. Some details missing, but most are spell related. +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "sethekk_halls.h" + +#define SAY_INTRO -1556007 + +#define SAY_AGGRO_1 -1556008 +#define SAY_AGGRO_2 -1556009 +#define SAY_AGGRO_3 -1556010 + +#define SAY_SLAY_1 -1556011 +#define SAY_SLAY_2 -1556012 +#define SAY_DEATH -1556013 +#define EMOTE_ARCANE_EXP -1556015 + +#define SPELL_BLINK 38194 +#define SPELL_BLINK_TELEPORT 38203 +#define SPELL_MANA_SHIELD 38151 +#define SPELL_ARCANE_BUBBLE 9438 +#define H_SPELL_SLOW 35032 + +#define SPELL_POLYMORPH 38245 +#define H_SPELL_POLYMORPH 43309 + +#define SPELL_ARCANE_VOLLEY 35059 +#define H_SPELL_ARCANE_VOLLEY 40424 + +#define SPELL_ARCANE_EXPLOSION 38197 +#define H_SPELL_ARCANE_EXPLOSION 40425 + +struct boss_talon_king_ikissAI : public ScriptedAI +{ + boss_talon_king_ikissAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ArcaneVolley_Timer; + uint32 Sheep_Timer; + uint32 Blink_Timer; + uint32 Slow_Timer; + + bool ManaShield; + bool Blink; + bool Intro; + + void Reset() + { + ArcaneVolley_Timer = 5000; + Sheep_Timer = 8000; + Blink_Timer = 35000; + Slow_Timer = 15000+rand()%15000; + Blink = false; + Intro = false; + ManaShield = false; + } + + void MoveInLineOfSight(Unit *who) + { + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!Intro && me->IsWithinDistInMap(who, 100)) + { + Intro = true; + DoScriptText(SAY_INTRO, me); + } + + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_IKISSDOOREVENT, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Blink) + { + DoCast(me, SPELL_ARCANE_EXPLOSION); + DoCast(me, SPELL_ARCANE_BUBBLE, true); + Blink = false; + } + + if (ArcaneVolley_Timer <= diff) + { + DoCast(me, SPELL_ARCANE_VOLLEY); + ArcaneVolley_Timer = 7000+rand()%5000; + } else ArcaneVolley_Timer -= diff; + + if (Sheep_Timer <= diff) + { + Unit *pTarget; + + //second top aggro target in normal, random target in heroic correct? + if (IsHeroic()) + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + else + pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + + if (pTarget) + DoCast(pTarget, SPELL_POLYMORPH); + Sheep_Timer = 15000+rand()%2500; + } else Sheep_Timer -= diff; + + //may not be correct time to cast + if (!ManaShield && ((me->GetHealth()*100) / me->GetMaxHealth() < 20)) + { + DoCast(me, SPELL_MANA_SHIELD); + ManaShield = true; + } + + if (IsHeroic()) + { + if (Slow_Timer <= diff) + { + DoCast(me, H_SPELL_SLOW); + Slow_Timer = 15000+rand()%25000; + } else Slow_Timer -= diff; + } + + if (Blink_Timer <= diff) + { + DoScriptText(EMOTE_ARCANE_EXP, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + //Spell doesn't work, but we use for visual effect at least + DoCast(pTarget, SPELL_BLINK); + + float X = pTarget->GetPositionX(); + float Y = pTarget->GetPositionY(); + float Z = pTarget->GetPositionZ(); + + DoTeleportTo(X,Y,Z); + + DoCast(pTarget, SPELL_BLINK_TELEPORT); + Blink = true; + } + Blink_Timer = 35000+rand()%5000; + } else Blink_Timer -= diff; + + if (!Blink) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_talon_king_ikiss(Creature* pCreature) +{ + return new boss_talon_king_ikissAI (pCreature); +} + +void AddSC_boss_talon_king_ikiss() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_talon_king_ikiss"; + newscript->GetAI = &GetAI_boss_talon_king_ikiss; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp b/src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp new file mode 100644 index 00000000000..ee27da3cff5 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance - Sethekk Halls +SD%Complete: 50 +SDComment: Instance Data for Sethekk Halls instance +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "sethekk_halls.h" + +enum eEnums +{ + NPC_ANZU = 23035, + IKISS_DOOR = 177203, +}; + +struct instance_sethekk_halls : public ScriptedInstance +{ + instance_sethekk_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 AnzuEncounter; + uint64 m_uiIkissDoorGUID; + + void Initialize() + { + AnzuEncounter = NOT_STARTED; + m_uiIkissDoorGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == NPC_ANZU) + { + if (AnzuEncounter >= IN_PROGRESS) + pCreature->DisappearAndDie(); + else + AnzuEncounter = IN_PROGRESS; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + if (pGo->GetEntry() == IKISS_DOOR) + m_uiIkissDoorGUID = pGo->GetGUID(); + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_IKISSDOOREVENT: + if (data == DONE) + DoUseDoorOrButton(m_uiIkissDoorGUID,DAY*IN_MILISECONDS); + break; + case TYPE_ANZU_ENCOUNTER: + AnzuEncounter = data; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_sethekk_halls(Map* pMap) +{ + return new instance_sethekk_halls(pMap); +} + +void AddSC_instance_sethekk_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_sethekk_halls"; + newscript->GetInstanceData = &GetInstanceData_instance_sethekk_halls; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h b/src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h new file mode 100644 index 00000000000..79a6cd4952d --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SETHEKK_HALLS_H +#define DEF_SETHEKK_HALLS_H + +enum eTypes +{ + DATA_IKISSDOOREVENT = 1, + TYPE_ANZU_ENCOUNTER = 2, +}; +#endif + diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp new file mode 100644 index 00000000000..2bb6a717a5a --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ambassador_Hellmaw +SD%Complete: 80 +SDComment: Enrage spell missing/not known +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "shadow_labyrinth.h" + +enum eEnums +{ + SAY_INTRO = -1555000, + SAY_AGGRO1 = -1555001, + SAY_AGGRO2 = -1555002, + SAY_AGGRO3 = -1555003, + SAY_HELP = -1555004, + SAY_SLAY1 = -1555005, + SAY_SLAY2 = -1555006, + SAY_DEATH = -1555007, + + SPELL_BANISH = 30231, + SPELL_CORROSIVE_ACID = 33551, + SPELL_FEAR = 33547, + SPELL_ENRAGE = 34970 +}; + +struct boss_ambassador_hellmawAI : public npc_escortAI +{ + boss_ambassador_hellmawAI(Creature* pCreature) : npc_escortAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 EventCheck_Timer; + uint32 CorrosiveAcid_Timer; + uint32 Fear_Timer; + uint32 Enrage_Timer; + bool Intro; + bool IsBanished; + bool Enraged; + + void Reset() + { + EventCheck_Timer = 5000; + CorrosiveAcid_Timer = 5000 + rand()%5000; + Fear_Timer = 25000 + rand()%5000; + Enrage_Timer = 180000; + Intro = false; + IsBanished = true; + Enraged = false; + + if (m_pInstance && me->isAlive()) + { + if (m_pInstance->GetData(TYPE_OVERSEER) != DONE) + DoCast(me, SPELL_BANISH, true); + } + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_HELLMAW, FAIL); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (me->HasAura(SPELL_BANISH)) + return; + + npc_escortAI::MoveInLineOfSight(pWho); + } + + void WaypointReached(uint32 /*i*/) + { + } + + void DoIntro() + { + if (me->HasAura(SPELL_BANISH)) + me->RemoveAurasDueToSpell(SPELL_BANISH); + + IsBanished = false; + Intro = true; + + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_HELLMAW) != FAIL) + { + DoScriptText(SAY_INTRO, me); + Start(true, false, 0, NULL, false, true); + } + + m_pInstance->SetData(TYPE_HELLMAW, IN_PROGRESS); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_HELLMAW, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!Intro && !HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (EventCheck_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_OVERSEER) == DONE) + { + DoIntro(); + return; + } + } + EventCheck_Timer = 5000; + return; + } + else + { + EventCheck_Timer -= diff; + return; + } + } + + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + if (me->HasAura(SPELL_BANISH, 0)) + { + EnterEvadeMode(); + return; + } + + if (CorrosiveAcid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVE_ACID); + CorrosiveAcid_Timer = 15000 + rand()%10000; + } else CorrosiveAcid_Timer -= diff; + + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 20000 + rand()%15000; + } else Fear_Timer -= diff; + + if (IsHeroic()) + { + if (!Enraged && Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else Enrage_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_ambassador_hellmaw(Creature* pCreature) +{ + return new boss_ambassador_hellmawAI(pCreature); +} + +void AddSC_boss_ambassador_hellmaw() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ambassador_hellmaw"; + newscript->GetAI = &GetAI_boss_ambassador_hellmaw; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp new file mode 100644 index 00000000000..52c60ae0d0e --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp @@ -0,0 +1,169 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Blackheart_the_Inciter +SD%Complete: 75 +SDComment: Incite Chaos not functional since core lacks Mind Control support +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define SPELL_INCITE_CHAOS 33676 +#define SPELL_INCITE_CHAOS_B 33684 //debuff applied to each member of party +#define SPELL_CHARGE 33709 +#define SPELL_WAR_STOMP 33707 + +#define SAY_INTRO1 -1555008 //not used +#define SAY_INTRO2 -1555009 //not used +#define SAY_INTRO3 -1555010 //not used +#define SAY_AGGRO1 -1555011 +#define SAY_AGGRO2 -1555012 +#define SAY_AGGRO3 -1555013 +#define SAY_SLAY1 -1555014 +#define SAY_SLAY2 -1555015 +#define SAY_HELP -1555016 //not used +#define SAY_DEATH -1555017 + +//below, not used +#define SAY2_INTRO1 -1555018 +#define SAY2_INTRO2 -1555019 +#define SAY2_INTRO3 -1555020 +#define SAY2_AGGRO1 -1555021 +#define SAY2_AGGRO2 -1555022 +#define SAY2_AGGRO3 -1555023 +#define SAY2_SLAY1 -1555024 +#define SAY2_SLAY2 -1555025 +#define SAY2_HELP -1555026 +#define SAY2_DEATH -1555027 + +struct boss_blackheart_the_inciterAI : public ScriptedAI +{ + boss_blackheart_the_inciterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + bool InciteChaos; + uint32 InciteChaos_Timer; + uint32 InciteChaosWait_Timer; + uint32 Charge_Timer; + uint32 Knockback_Timer; + + void Reset() + { + InciteChaos = false; + InciteChaos_Timer = 20000; + InciteChaosWait_Timer = 15000; + Charge_Timer = 5000; + Knockback_Timer = 15000; + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (InciteChaos) + { + if (InciteChaosWait_Timer <= diff) + { + InciteChaos = false; + InciteChaosWait_Timer = 15000; + } else InciteChaosWait_Timer -= diff; + + return; + } + + if (InciteChaos_Timer <= diff) + { + DoCast(me, SPELL_INCITE_CHAOS); + + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + pTarget->CastSpell(pTarget,SPELL_INCITE_CHAOS_B,true); + } + + DoResetThreat(); + InciteChaos = true; + InciteChaos_Timer = 40000; + return; + } else InciteChaos_Timer -= diff; + + //Charge_Timer + if (Charge_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CHARGE); + Charge_Timer = 15000 + rand()%10000; + } else Charge_Timer -= diff; + + //Knockback_Timer + if (Knockback_Timer <= diff) + { + DoCast(me, SPELL_WAR_STOMP); + Knockback_Timer = 18000 + rand()%6000; + } else Knockback_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_blackheart_the_inciter(Creature* pCreature) +{ + return new boss_blackheart_the_inciterAI (pCreature); +} + +void AddSC_boss_blackheart_the_inciter() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_blackheart_the_inciter"; + newscript->GetAI = &GetAI_boss_blackheart_the_inciter; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp new file mode 100644 index 00000000000..8b63b765b47 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp @@ -0,0 +1,313 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grandmaster_Vorpil +SD%Complete: 100 +SDComment: +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define SAY_INTRO -1555028 +#define SAY_AGGRO1 -1555029 +#define SAY_AGGRO2 -1555030 +#define SAY_AGGRO3 -1555031 +#define SAY_HELP -1555032 +#define SAY_SLAY1 -1555033 +#define SAY_SLAY2 -1555034 +#define SAY_DEATH -1555035 + +#define SPELL_RAIN_OF_FIRE 33617 +#define H_SPELL_RAIN_OF_FIRE 39363 + +#define SPELL_DRAW_SHADOWS 33563 +#define SPELL_SHADOWBOLT_VOLLEY 33841 +#define SPELL_BANISH 38791 + +#define MOB_VOID_TRAVELER 19226 +#define SPELL_SACRIFICE 33587 +#define SPELL_SHADOW_NOVA 33846 +#define SPELL_EMPOWERING_SHADOWS 33783 +#define H_SPELL_EMPOWERING_SHADOWS 39364 + +#define MOB_VOID_PORTAL 19224 +#define SPELL_VOID_PORTAL_VISUAL 33569 + +float VorpilPosition[3] = {-252.8820,-264.3030,17.1}; + +float VoidPortalCoords[5][3] = +{ + {-283.5894, -239.5718, 12.7}, + {-306.5853, -258.4539, 12.7}, + {-295.8789, -269.0899, 12.7}, + {-209.3401, -262.7564, 17.1}, + {-261.4533, -297.3298, 17.1} +}; + +struct mob_voidtravelerAI : public ScriptedAI +{ + mob_voidtravelerAI(Creature *c) : ScriptedAI(c) + { + } + + uint64 VorpilGUID; + uint32 move; + bool sacrificed; + + void Reset() + { + VorpilGUID = 0; + move = 0; + sacrificed = false; + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (!VorpilGUID) + { + me->Kill(me); + return; + } + if (move <= diff) + { + Creature *Vorpil = Unit::GetCreature(*me, VorpilGUID); + if (!Vorpil) + { + VorpilGUID = 0; + return; + } + + if (sacrificed) + { + me->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), Vorpil); + Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth()/25); + DoCast(me, SPELL_SHADOW_NOVA, true); + me->Kill(me); + return; + } + me->GetMotionMaster()->MoveFollow(Vorpil,0,0); + if (me->IsWithinDist(Vorpil, 3)) + { + DoCast(me, SPELL_SACRIFICE, false); + sacrificed = true; + move = 500; + return; + } + if (!Vorpil->isInCombat() || Vorpil->isDead()) + { + me->Kill(me); + return; + } + move = 1000; + } else move -= diff; + } +}; +CreatureAI* GetAI_mob_voidtraveler(Creature* pCreature) +{ + return new mob_voidtravelerAI (pCreature); +} + +struct boss_grandmaster_vorpilAI : public ScriptedAI +{ + boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = false; + } + + ScriptedInstance *pInstance; + bool Intro, HelpYell; + bool sumportals; + + uint32 ShadowBoltVolley_Timer; + uint32 DrawShadows_Timer; + uint32 summonTraveler_Timer; + uint32 banish_Timer; + uint64 PortalsGuid[5]; + + void Reset() + { + ShadowBoltVolley_Timer = 7000 + rand()%7000; + DrawShadows_Timer = 45000; + summonTraveler_Timer = 90000; + banish_Timer = 17000; + HelpYell = false; + destroyPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED); + } + + void summonPortals() + { + if (!sumportals) + { + for (uint8 i = 0; i < 5; ++i) + { + Creature *Portal = NULL; + Portal = me->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000); + if (Portal) + { + PortalsGuid[i] = Portal->GetGUID(); + Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false); + } + } + sumportals = true; + summonTraveler_Timer = 5000; + } + } + + void destroyPortals() + { + if (sumportals) + { + for (uint8 i = 0; i < 5; ++i) + { + Unit *Portal = Unit::GetUnit((*me), PortalsGuid[i]); + if (Portal && Portal->isAlive()) + Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + PortalsGuid[i] = 0; + } + sumportals = false; + } + } + + void spawnVoidTraveler() + { + int pos = urand(0,4); + me->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,5000); + if (!HelpYell) + { + DoScriptText(SAY_HELP, me); + HelpYell = true; + } + } + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == MOB_VOID_TRAVELER) + CAST_AI(mob_voidtravelerAI, summoned->AI())->VorpilGUID = me->GetGUID(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + destroyPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + summonPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS); + } + + void MoveInLineOfSight(Unit *who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (!Intro && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 100) && me->IsHostileTo(who)) + { + DoScriptText(SAY_INTRO, me); + Intro = true; + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOWBOLT_VOLLEY); + ShadowBoltVolley_Timer = 15000 + rand()%15000; + } else ShadowBoltVolley_Timer -= diff; + + if (IsHeroic() && banish_Timer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,false); + if (pTarget) + { + DoCast(pTarget, SPELL_BANISH); + banish_Timer = 16000; + } + } else banish_Timer -= diff; + + if (DrawShadows_Timer <= diff) + { + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* i_pl = i->getSource()) + if (i_pl->isAlive() && !i_pl->HasAura(SPELL_BANISH)) + i_pl->TeleportTo(me->GetMapId(), VorpilPosition[0],VorpilPosition[1],VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT); + + me->GetMap()->CreatureRelocation(me, VorpilPosition[0],VorpilPosition[1],VorpilPosition[2],0.0f); + DoCast(me, SPELL_DRAW_SHADOWS, true); + + DoCast(me, SPELL_RAIN_OF_FIRE); + + ShadowBoltVolley_Timer = 6000; + DrawShadows_Timer = 30000; + } else DrawShadows_Timer -= diff; + + if (summonTraveler_Timer <= diff) + { + spawnVoidTraveler(); + summonTraveler_Timer = 10000; + //enrage at 20% + if ((me->GetHealth()*5) < me->GetMaxHealth()) + summonTraveler_Timer = 5000; + } else summonTraveler_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grandmaster_vorpil(Creature* pCreature) +{ + return new boss_grandmaster_vorpilAI (pCreature); +} + +void AddSC_boss_grandmaster_vorpil() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grandmaster_vorpil"; + newscript->GetAI = &GetAI_boss_grandmaster_vorpil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_voidtraveler"; + newscript->GetAI = &GetAI_mob_voidtraveler; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp new file mode 100644 index 00000000000..14bf249c3b5 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Murmur +SD%Complete: 90 +SDComment: Timers may be incorrect +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define EMOTE_SONIC_BOOM -1555036 + +#define SPELL_SONIC_BOOM_CAST DUNGEON_MODE(33923, 38796) +#define SPELL_SONIC_BOOM_EFFECT DUNGEON_MODE(33666, 38795) +#define SPELL_RESONANCE 33657 +#define SPELL_MURMURS_TOUCH DUNGEON_MODE(33711, 38794) +#define SPELL_MAGNETIC_PULL 33689 +#define SPELL_SONIC_SHOCK 38797 +#define SPELL_THUNDERING_STORM 39365 + +struct boss_murmurAI : public ScriptedAI +{ + boss_murmurAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 SonicBoom_Timer; + uint32 MurmursTouch_Timer; + uint32 Resonance_Timer; + uint32 MagneticPull_Timer; + uint32 SonicShock_Timer; + uint32 ThunderingStorm_Timer; + bool SonicBoom; + + void Reset() + { + SonicBoom_Timer = 30000; + MurmursTouch_Timer = 8000 + rand()%12000; + Resonance_Timer = 5000; + MagneticPull_Timer = 15000 + rand()%15000; + ThunderingStorm_Timer = 15000; + SonicShock_Timer = 10000; + SonicBoom = false; + + //database should have `RegenHealth`=0 to prevent regen + uint32 hp = (me->GetMaxHealth()*40)/100; + if (hp) me->SetHealth(hp); + me->ResetPlayerDamageReq(); + } + + void SonicBoomEffect() + { + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + //Not do anything without aura, spell can be resisted! + if (pTarget->HasAura(SPELL_SONIC_BOOM_CAST) && me->IsWithinDistInMap(pTarget, 34.0f)) + { + //This will be wrong calculation. Also, comments suggest it must deal damage + pTarget->SetHealth(uint32(pTarget->GetMaxHealth() - pTarget->GetMaxHealth() * 0.8)); + } + } + } + } + + void EnterCombat(Unit * /*who*/) { } + + // Sonic Boom instant damage (needs core fix instead of this) + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (pTarget && pTarget->isAlive() && spell && spell->Id == uint32(SPELL_SONIC_BOOM_EFFECT)) + me->DealDamage(pTarget,(pTarget->GetHealth()*90)/100,NULL,SPELL_DIRECT_DAMAGE,SPELL_SCHOOL_MASK_NATURE,spell); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target or casting + if (!UpdateVictim() || me->IsNonMeleeSpellCasted(false)) + return; + + // Sonic Boom + if (SonicBoom) + { + DoCast(me, SPELL_SONIC_BOOM_EFFECT, true); + SonicBoomEffect(); + + SonicBoom = false; + Resonance_Timer = 1500; + } + if (SonicBoom_Timer <= diff) + { + DoScriptText(EMOTE_SONIC_BOOM, me); + DoCast(me, SPELL_SONIC_BOOM_CAST); + SonicBoom_Timer = 30000; + SonicBoom = true; + return; + } else SonicBoom_Timer -= diff; + + // Murmur's Touch + if (MurmursTouch_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,80,true)) + DoCast(pTarget, SPELL_MURMURS_TOUCH); + MurmursTouch_Timer = 25000 + rand()%10000; + } else MurmursTouch_Timer -= diff; + + // Resonance + if (!SonicBoom && !(me->IsWithinMeleeRange(me->getVictim()))) + { + if (Resonance_Timer <= diff) + { + DoCast(me, SPELL_RESONANCE); + Resonance_Timer = 5000; + } else Resonance_Timer -= diff; + } + + // Magnetic Pull + if (MagneticPull_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + if (pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + { + DoCast(pTarget, SPELL_MAGNETIC_PULL); + MagneticPull_Timer = 15000+rand()%15000; + return; + } + MagneticPull_Timer = 500; + } else MagneticPull_Timer -= diff; + + if (IsHeroic()) + { + // Thundering Storm + if (ThunderingStorm_Timer <= diff) + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) + if (pTarget->isAlive() && !me->IsWithinDist(pTarget, 35, false)) + DoCast(pTarget, SPELL_THUNDERING_STORM, true); + ThunderingStorm_Timer = 15000; + } else ThunderingStorm_Timer -= diff; + + // Sonic Shock + if (SonicShock_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,20,false)) + if (pTarget->isAlive()) + DoCast(pTarget, SPELL_SONIC_SHOCK); + SonicShock_Timer = 10000+rand()%10000; + } else SonicShock_Timer -= diff; + } + + // Select nearest most aggro target if top aggro too far + if (!me->isAttackReady()) + return; + if (!me->IsWithinMeleeRange(me->getVictim())) + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) + if (pTarget->isAlive() && me->IsWithinMeleeRange(pTarget)) + { + me->TauntApply(pTarget); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_murmur(Creature* pCreature) +{ + return new boss_murmurAI (pCreature); +} + +void AddSC_boss_murmur() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_murmur"; + newscript->GetAI = &GetAI_boss_murmur; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp new file mode 100644 index 00000000000..78340e5e132 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp @@ -0,0 +1,227 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shadow_Labyrinth +SD%Complete: 85 +SDComment: Some cleanup left along with save +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define MAX_ENCOUNTER 5 + +#define REFECTORY_DOOR 183296 //door opened when blackheart the inciter dies +#define SCREAMING_HALL_DOOR 183295 //door opened when grandmaster vorpil dies + +/* Shadow Labyrinth encounters: +1 - Ambassador Hellmaw event +2 - Blackheart the Inciter event +3 - Grandmaster Vorpil event +4 - Murmur event +*/ + +struct instance_shadow_labyrinth : public ScriptedInstance +{ + instance_shadow_labyrinth(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 m_uiRefectoryDoorGUID; + uint64 m_uiScreamingHallDoorGUID; + + uint64 m_uiGrandmasterVorpil; + uint32 m_uiFelOverseerCount; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiRefectoryDoorGUID = 0; + m_uiScreamingHallDoorGUID = 0; + + m_uiGrandmasterVorpil = 0; + m_uiFelOverseerCount = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case REFECTORY_DOOR: + m_uiRefectoryDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case SCREAMING_HALL_DOOR: + m_uiScreamingHallDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 18732: + m_uiGrandmasterVorpil = pCreature->GetGUID(); + break; + case 18796: + if (pCreature->isAlive()) + { + ++m_uiFelOverseerCount; + debug_log("TSCR: Shadow Labyrinth: counting %u Fel Overseers.",m_uiFelOverseerCount); + } + break; + } + } + + void SetData(uint32 type, uint32 uiData) + { + switch(type) + { + case TYPE_HELLMAW: + m_auiEncounter[0] = uiData; + break; + + case TYPE_OVERSEER: + if (uiData != DONE) + { + error_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER did not expect other data than DONE"); + return; + } + if (m_uiFelOverseerCount) + { + --m_uiFelOverseerCount; + + if (m_uiFelOverseerCount) + debug_log("TSCR: Shadow Labyrinth: %u Fel Overseers left to kill.",m_uiFelOverseerCount); + else + { + m_auiEncounter[1] = DONE; + debug_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER == DONE"); + } + } + break; + + case DATA_BLACKHEARTTHEINCITEREVENT: + if (uiData == DONE) + DoUseDoorOrButton(m_uiRefectoryDoorGUID); + m_auiEncounter[2] = uiData; + break; + + case DATA_GRANDMASTERVORPILEVENT: + if (uiData == DONE) + DoUseDoorOrButton(m_uiScreamingHallDoorGUID); + m_auiEncounter[3] = uiData; + break; + + case DATA_MURMUREVENT: + m_auiEncounter[4] = uiData; + break; + } + + if (uiData == DONE) + { + if (type == TYPE_OVERSEER && m_uiFelOverseerCount != 0) + return; + + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HELLMAW: return m_auiEncounter[0]; + case TYPE_OVERSEER: return m_auiEncounter[1]; + case DATA_GRANDMASTERVORPILEVENT: return m_auiEncounter[3]; + case DATA_MURMUREVENT: return m_auiEncounter[4]; + } + return false; + } + + uint64 GetData64(uint32 identifier) + { + if (identifier == DATA_GRANDMASTERVORPIL) + return m_uiGrandmasterVorpil; + + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_shadow_labyrinth(Map* pMap) +{ + return new instance_shadow_labyrinth(pMap); +} + +void AddSC_instance_shadow_labyrinth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shadow_labyrinth"; + newscript->GetInstanceData = &GetInstanceData_instance_shadow_labyrinth; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h new file mode 100644 index 00000000000..a78955368bf --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHADOW_LABYRINTH_H +#define DEF_SHADOW_LABYRINTH_H + +#define TYPE_HELLMAW 1 +#define TYPE_OVERSEER 2 +#define DATA_BLACKHEARTTHEINCITEREVENT 3 +#define DATA_GRANDMASTERVORPILEVENT 4 +#define DATA_MURMUREVENT 5 +#define DATA_GRANDMASTERVORPIL 6 +#endif + diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.cpp b/src/server/scripts/Outland/BlackTemple/black_temple.cpp new file mode 100644 index 00000000000..c1e7f19fbb1 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/black_temple.cpp @@ -0,0 +1,69 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Black_Temple +SD%Complete: 95 +SDComment: Spirit of Olum: Player Teleporter to Seer Kanai Teleport after defeating Naj'entus and Supremus. TODO: Find proper gossip. +SDCategory: Black Temple +EndScriptData */ + +/* ContentData +npc_spirit_of_olum +EndContentData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +/*### +# npc_spirit_of_olum +####*/ + +#define SPELL_TELEPORT 41566 // s41566 - Teleport to Ashtongue NPC's +#define GOSSIP_OLUM1 "Teleport me to the other Ashtongue Deathsworn" + +bool GossipHello_npc_spirit_of_olum(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && (pInstance->GetData(DATA_SUPREMUSEVENT) >= DONE) && (pInstance->GetData(DATA_HIGHWARLORDNAJENTUSEVENT) >= DONE)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_OLUM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_spirit_of_olum(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) + pPlayer->CLOSE_GOSSIP_MENU(); + + pPlayer->InterruptNonMeleeSpells(false); + pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, false); + return true; +} + +void AddSC_black_temple() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_spirit_of_olum"; + newscript->pGossipHello = &GossipHello_npc_spirit_of_olum; + newscript->pGossipSelect = &GossipSelect_npc_spirit_of_olum; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.h b/src/server/scripts/Outland/BlackTemple/black_temple.h new file mode 100644 index 00000000000..b7432cd5b20 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/black_temple.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BLACK_TEMPLE_H +#define DEF_BLACK_TEMPLE_H + +enum eTypes +{ + DATA_AKAMA = 1, + DATA_AKAMA_SHADE = 2, + DATA_GURTOGGBLOODBOILEVENT = 3, + DATA_HIGHWARLORDNAJENTUS = 4, + DATA_HIGHWARLORDNAJENTUSEVENT = 5, + DATA_ILLIDANSTORMRAGE = 6, + DATA_ILLIDANSTORMRAGEEVENT = 7, + DATA_ILLIDARICOUNCILEVENT = 8, + DATA_ILLIDARICOUNCIL = 9, + DATA_LADYMALANDE = 10, + DATA_HIGHNETHERMANCERZEREVOR = 11, + DATA_GATHIOSTHESHATTERER = 12, + DATA_VERASDARKSHADOW = 13, + DATA_MOTHERSHAHRAZEVENT = 14, + DATA_RELIQUARYOFSOULSEVENT = 15, + DATA_SHADEOFAKAMA = 16, + DATA_SHADEOFAKAMAEVENT = 17, + DATA_SUPREMUS = 18, + DATA_SUPREMUSEVENT = 19, + DATA_TERONGOREFIENDEVENT = 20, + DATA_GAMEOBJECT_NAJENTUS_GATE = 21, + DATA_GAMEOBJECT_ILLIDAN_GATE = 22, + DATA_GAMEOBJECT_ILLIDAN_DOOR_R = 23, + DATA_GAMEOBJECT_ILLIDAN_DOOR_L = 24, + DATA_GAMEOBJECT_SUPREMUS_DOORS = 25, + DATA_BLOOD_ELF_COUNCIL_VOICE = 26 +}; + +#endif + diff --git a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp new file mode 100644 index 00000000000..1093ce06cb8 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp @@ -0,0 +1,332 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Bloodboil +SD%Complete: 80 +SDComment: Bloodboil not working correctly, missing enrage +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +//Speech'n'Sound +#define SAY_AGGRO -1564029 +#define SAY_SLAY1 -1564030 +#define SAY_SLAY2 -1564031 +#define SAY_SPECIAL1 -1564032 +#define SAY_SPECIAL2 -1564033 +#define SAY_ENRAGE1 -1564034 +#define SAY_ENRAGE2 -1564035 +#define SAY_DEATH -1564036 + +//Spells +#define SPELL_ACID_GEYSER 40630 +#define SPELL_ACIDIC_WOUND 40481 +#define SPELL_ARCING_SMASH 40599 +#define SPELL_BLOODBOIL 42005 // This spell is AoE whereas it shouldn't be +#define SPELL_FEL_ACID 40508 +#define SPELL_FEL_RAGE_SELF 40594 +#define SPELL_FEL_RAGE_TARGET 40604 +#define SPELL_FEL_RAGE_2 40616 +#define SPELL_FEL_RAGE_3 41625 +#define SPELL_BEWILDERING_STRIKE 40491 +#define SPELL_EJECT1 40486 // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) +#define SPELL_EJECT2 40597 // 1000 Physical damage + Stun (used in phase 2?) +#define SPELL_TAUNT_GURTOGG 40603 +#define SPELL_INSIGNIFIGANCE 40618 +#define SPELL_BERSERK 45078 + +//This is used to sort the players by distance in preparation for the Bloodboil cast. + +struct boss_gurtogg_bloodboilAI : public ScriptedAI +{ + boss_gurtogg_bloodboilAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 TargetGUID; + + float TargetThreat; + + uint32 BloodboilTimer; + uint32 BloodboilCount; + uint32 AcidGeyserTimer; + uint32 AcidicWoundTimer; + uint32 ArcingSmashTimer; + uint32 EnrageTimer; + uint32 FelAcidTimer; + uint32 EjectTimer; + uint32 BewilderingStrikeTimer; + uint32 PhaseChangeTimer; + + bool Phase1; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, NOT_STARTED); + + TargetGUID = 0; + + TargetThreat = 0; + + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidGeyserTimer = 1000; + AcidicWoundTimer = 6000; + ArcingSmashTimer = 19000; + EnrageTimer = 600000; + FelAcidTimer = 25000; + EjectTimer = 10000; + BewilderingStrikeTimer = 15000; + PhaseChangeTimer = 60000; + + Phase1 = true; + + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); + } + + void EnterCombat(Unit * /*who*/) + { + DoZoneInCombat(); + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited. + void CastBloodboil() + { + // Get the Threat List + std::list m_threatlist = me->getThreatManager().getThreatList(); + + if (!m_threatlist.size()) // He doesn't have anyone in his threatlist, useless to continue + return; + + std::list targets; + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //only on alive players + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + targets.push_back(pTarget); + } + + //Sort the list of players + targets.sort(Trinity::ObjectDistanceOrderPred(me, false)); + //Resize so we only get top 5 + targets.resize(5); + + //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp + /*SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(SPELL_BLOODBOIL); + if (spellInfo) + { + for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + { + Unit *pTarget = *itr; + if (!pTarget) return; + for (uint32 i = 0; i<3; ++i) + { + uint8 eff = spellInfo->Effect[i]; + if (eff >= TOTAL_SPELL_EFFECTS) + continue; + + Aura *Aur = new Aura(spellInfo, i, pTarget, pTarget, pTarget); + pTarget->AddAura(Aur); + } + } + }*/ + } + + void RevertThreatOnTarget(uint64 guid) + { + Unit* pUnit = NULL; + pUnit = Unit::GetUnit((*me), guid); + if (pUnit) + { + if (DoGetThreat(pUnit)) + DoModifyThreatPercent(pUnit, -100); + if (TargetThreat) + me->AddThreat(pUnit, TargetThreat); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ArcingSmashTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCING_SMASH); + ArcingSmashTimer = 10000; + } else ArcingSmashTimer -= diff; + + if (FelAcidTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FEL_ACID); + FelAcidTimer = 25000; + } else FelAcidTimer -= diff; + + if (!me->HasAura(SPELL_BERSERK)) + { + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + DoScriptText(RAND(SAY_ENRAGE1,SAY_ENRAGE2), me); + } else EnrageTimer -= diff; + } + + if (Phase1) + { + if (BewilderingStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BEWILDERING_STRIKE); + float mt_threat = DoGetThreat(me->getVictim()); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1)) + me->AddThreat(pTarget, mt_threat); + BewilderingStrikeTimer = 20000; + } else BewilderingStrikeTimer -= diff; + + if (EjectTimer <= diff) + { + DoCast(me->getVictim(), SPELL_EJECT1); + DoModifyThreatPercent(me->getVictim(), -40); + EjectTimer = 15000; + } else EjectTimer -= diff; + + if (AcidicWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ACIDIC_WOUND); + AcidicWoundTimer = 10000; + } else AcidicWoundTimer -= diff; + + if (BloodboilTimer <= diff) + { + if (BloodboilCount < 5) // Only cast it five times. + { + //CastBloodboil(); // Causes issues on windows, so is commented out. + DoCast(me->getVictim(), SPELL_BLOODBOIL); + ++BloodboilCount; + BloodboilTimer = 10000*BloodboilCount; + } + } else BloodboilTimer -= diff; + } + + if (!Phase1) + { + if (AcidGeyserTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ACID_GEYSER); + AcidGeyserTimer = 30000; + } else AcidGeyserTimer -= diff; + + if (EjectTimer <= diff) + { + DoCast(me->getVictim(), SPELL_EJECT2); + EjectTimer = 15000; + } else EjectTimer -= diff; + } + + if (PhaseChangeTimer <= diff) + { + if (Phase1) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget && pTarget->isAlive()) + { + Phase1 = false; + + TargetThreat = DoGetThreat(pTarget); + TargetGUID = pTarget->GetGUID(); + pTarget->CastSpell(me, SPELL_TAUNT_GURTOGG, true); + if (DoGetThreat(pTarget)) + DoModifyThreatPercent(pTarget, -100); + me->AddThreat(pTarget, 50000000.0f); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + // If VMaps are disabled, this spell can call the whole instance + DoCast(me, SPELL_INSIGNIFIGANCE, true); + DoCast(pTarget, SPELL_FEL_RAGE_TARGET, true); + DoCast(pTarget, SPELL_FEL_RAGE_2, true); + /* These spells do not work, comment them out for now. + DoCast(pTarget, SPELL_FEL_RAGE_2, true); + DoCast(pTarget, SPELL_FEL_RAGE_3, true);*/ + + //Cast this without triggered so that it appears in combat logs and shows visual. + DoCast(me, SPELL_FEL_RAGE_SELF); + + DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); + + AcidGeyserTimer = 1000; + PhaseChangeTimer = 30000; + } + } else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage + { + if (TargetGUID) + RevertThreatOnTarget(TargetGUID); + TargetGUID = 0; + Phase1 = true; + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidicWoundTimer += 2000; + ArcingSmashTimer += 2000; + FelAcidTimer += 2000; + EjectTimer += 2000; + PhaseChangeTimer = 60000; + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); + } + } else PhaseChangeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_gurtogg_bloodboil(Creature* pCreature) +{ + return new boss_gurtogg_bloodboilAI (pCreature); +} + +void AddSC_boss_gurtogg_bloodboil() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gurtogg_bloodboil"; + newscript->GetAI = &GetAI_boss_gurtogg_bloodboil; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp new file mode 100644 index 00000000000..b8e09c0e08e --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -0,0 +1,2248 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_illidan_stormrage +SD%Complete: 90 +SDComment: Somewhat of a workaround for Parasitic Shadowfiend, unable to summon GOs for Cage Trap. +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +#define GETGO(obj, guid) GameObject* obj = pInstance->instance->GetGameObject(guid) +#define GETUNIT(unit, guid) Unit* unit = Unit::GetUnit(*me, guid) +#define GETCRE(cre, guid) Creature* cre = Unit::GetCreature(*me, guid) +#define HPPCT(unit) unit->GetHealth()*100 / unit->GetMaxHealth() + +/************* Quotes and Sounds ***********************/ +// Gossip for when a player clicks Akama +#define GOSSIP_ITEM "We are ready to face Illidan" + +// Yells for/by Akama +#define SAY_AKAMA_BEWARE "Be wary friends, The Betrayer meditates in the court just beyond." +#define SOUND_AKAMA_BEWARE 11388 +#define SAY_AKAMA_MINION "Come, my minions. Deal with this traitor as he deserves!" +#define SOUND_AKAMA_MINION 11465 +#define SAY_AKAMA_LEAVE "I'll deal with these mongrels. Strike now, friends! Strike at the betrayer!" +#define SOUND_AKAMA_LEAVE 11390 + +// Self explanatory +const char* SAY_KILL1 = "Who shall be next to taste my blades?!"; +#define SOUND_KILL1 11473 +const char* SAY_KILL2 = "This is too easy!"; +#define SOUND_KILL2 11472 + +// I think I'll fly now and let my subordinates take you on +#define SAY_TAKEOFF "I will not be touched by rabble such as you!" +#define SOUND_TAKEOFF 11479 +#define SAY_SUMMONFLAMES "Behold the flames of Azzinoth!" +#define SOUND_SUMMONFLAMES 11480 + +// When casting Eye Blast. Demon Fire will be appear on places that he casts this +#define SAY_EYE_BLAST "Stare into the eyes of the Betrayer!" +#define SOUND_EYE_BLAST 11481 + +// kk, I go big, dark and demon on you. +#define SAY_MORPH "Behold the power... of the demon within!" +#define SOUND_MORPH 11475 + +// I KILL! +#define SAY_ENRAGE "You've wasted too much time mortals, now you shall fall!" +#define SOUND_ENRAGE 11474 + +/************** Spells *************/ +// Normal Form +#define SPELL_SHEAR 37335 // 41032 is bugged, cannot be block/dodge/parry// Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5 second cast +#define SPELL_FLAME_CRASH 40832 // Summons an invis/unselect passive mob that has an aura of flame in a circle around him. +#define SPELL_DRAW_SOUL 40904 // 5k Shadow Damage in front of him. Heals Illidan for 100k health (script effect) +#define SPELL_PARASITIC_SHADOWFIEND 41917 // DoT of 3k Shadow every 2 seconds. Lasts 10 seconds. (Script effect: Summon 2 parasites once the debuff has ticked off) +#define SPELL_PARASITIC_SHADOWFIEND2 41914 // Used by Parasitic +#define SPELL_SUMMON_PARASITICS 41915 // Summons 2 Parasitic Shadowfiends on the target. It's supposed to be cast as soon as the Parasitic Shadowfiend debuff is gone, but the spells aren't linked :( +#define SPELL_AGONIZING_FLAMES 40932 // 4k fire damage initial to target and anyone w/i 5 yards. PHASE 3 ONLY +#define SPELL_ENRAGE 40683 // Increases damage by 50% and attack speed by 30%. 20 seconds, PHASE 5 ONLY +// Flying (Phase 2) +#define SPELL_THROW_GLAIVE 39635 // Throws a glaive on the ground +#define SPELL_THROW_GLAIVE2 39849 // Animation for the above spell +#define SPELL_GLAIVE_RETURNS 39873 // Glaive flies back to Illidan +#define SPELL_FIREBALL 40598 // 2.5k-3.5k damage in 10 yard radius. 2 second cast time. +#define SPELL_DARK_BARRAGE 40585 // 10 second channeled spell, 3k shadow damage per second. +// Demon Form +#define SPELL_DEMON_TRANSFORM_1 40511 // First phase of animations for transforming into Dark Illidan (fall to ground) +#define SPELL_DEMON_TRANSFORM_2 40398 // Second phase of animations (kneel) +#define SPELL_DEMON_TRANSFORM_3 40510 // Final phase of animations (stand up and roar) +#define SPELL_DEMON_FORM 40506 // Transforms into Demon Illidan. Has an Aura of Dread on him. +#define SPELL_SHADOW_BLAST 41078 // 8k - 11k Shadow Damage. Targets highest threat. Has a splash effect, damaging anyone in 20 yards of the target. +#define SPELL_FLAME_BURST 41126 // Hurls fire at entire raid for ~3.5k damage every 10 seconds. Resistable. (Does not work: Script effect) +#define SPELL_FLAME_BURST_EFFECT 41131 // The actual damage. Have each player cast it on itself (workaround) +// Other Illidan spells +#define SPELL_KNEEL 39656 // Before beginning encounter, this is how he appears (talking to skully). +#define SPELL_SHADOW_PRISON 40647 // Illidan casts this spell to immobilize entire raid when he summons Maiev. +#define SPELL_DEATH 41220 // This spell doesn't do anything except stun Illidan and set him on his knees. +#define SPELL_BERSERK 45078 // Damage increased by 500%, attack speed by 150% +#define SPELL_DUAL_WIELD 42459 +//Phase Normal spells +#define SPELL_FLAME_CRASH_EFFECT 40836 // Firey blue ring of circle that the other flame crash summons +#define SPELL_SUMMON_SHADOWDEMON 41117 // Summon four shadowfiends +#define SPELL_SHADOWFIEND_PASSIVE 41913 // Passive aura for shadowfiends +#define SPELL_SHADOW_DEMON_PASSIVE 41079 // Adds the "shadowform" aura to Shadow Demons. +#define SPELL_CONSUME_SOUL 41080 // Once the Shadow Demons reach their target, they use this to kill them +#define SPELL_PARALYZE 41083 // Shadow Demons cast this on their target +#define SPELL_PURPLE_BEAM 39123 // Purple Beam connecting Shadow Demon to their target +//Phase Flight spells +#define SPELL_AZZINOTH_CHANNEL 39857 // Glaives cast it on Flames. Not sure if this is the right spell. +#define SPELL_EYE_BLAST_TRIGGER 40017 // This summons Demon Form every few seconds and deals ~20k damage in its radius +#define SPELL_EYE_BLAST 39908 // This does the blue flamey animation. +#define SPELL_BLAZE_EFFECT 40610 // Green flame on the ground, triggers damage (5k) every few seconds +#define SPELL_BLAZE_SUMMON 40637 // Summons the Blaze creature +#define SPELL_DEMON_FIRE 40029 // Blue fire trail left by Eye Blast. Deals 2k per second if players stand on it. +#define SPELL_FLAME_BLAST 40631 // Flames of Azzinoth use this. Frontal cone AoE 7k-9k damage. +#define SPELL_CHARGE 41581 //40602 // Flames of Azzinoth charges whoever is too far from them. They enrage after this. For simplicity, we'll use the same enrage as Illidan. +#define SPELL_FLAME_ENRAGE 45078 +//Akama spells +#define SPELL_AKAMA_DOOR_CHANNEL 41268 // Akama's channel spell on the door before the Temple Summit +#define SPELL_DEATHSWORN_DOOR_CHANNEL 41269 // Olum and Udalo's channel spell on the door before the Temple Summit +#define SPELL_AKAMA_DOOR_FAIL 41271 // Not sure where this is really used... +#define SPELL_HEALING_POTION 40535 // Akama uses this to heal himself to full. +#define SPELL_CHAIN_LIGHTNING 40536 // 6938 to 8062 for 5 targets +//Maiev spells +#define SPELL_CAGE_TRAP_DUMMY 40761 // Put this in DB for cage trap GO. +#define SPELL_CAGED 40695 // Caged Trap triggers will cast this on Illidan if he is within 3 yards +#define SPELL_CAGE_TRAP_SUMMON 40694 // Summons a Cage Trap GO (bugged) on the ground along with a Cage Trap Disturb Trigger mob (working) +#define SPELL_CAGE_TRAP_BEAM 40713 // 8 Triggers on the ground in an octagon cast spells like this on Illidan 'caging him' +#define SPELL_TELEPORT_VISUAL 41232 // Teleport visual for Maiev +#define SPELL_SHADOW_STRIKE 40685 // 4375 to 5625 every 3 seconds for 12 seconds +#define SPELL_THROW_DAGGER 41152 // 5400 to 6600 damage, need dagger +#define SPELL_FAN_BLADES 39954 // bugged visual + +// Other defines +#define CENTER_X 676.740 +#define CENTER_Y 305.297 +#define CENTER_Z 353.192 + +#define FLAME_ENRAGE_DISTANCE 30 +#define FLAME_CHARGE_DISTANCE 50 + +#define EQUIP_ID_MAIN_HAND 32837 +#define EQUIP_ID_OFF_HAND 32838 + +/**** Creature Summon and Recognition IDs ****/ +enum CreatureEntry +{ + EMPTY = 0, + AKAMA = 22990, + ILLIDAN_STORMRAGE = 22917, + BLADE_OF_AZZINOTH = 22996, + FLAME_OF_AZZINOTH = 22997, + MAIEV_SHADOWSONG = 23197, + SHADOW_DEMON = 23375, + DEMON_FIRE = 23069, + FLAME_CRASH = 23336, + ILLIDAN_DOOR_TRIGGER = 23412, + SPIRIT_OF_OLUM = 23411, + SPIRIT_OF_UDALO = 23410, + ILLIDARI_ELITE = 23226, + PARASITIC_SHADOWFIEND = 23498, + CAGE_TRAP_TRIGGER = 23292, +}; + +/*** Phase Names ***/ +enum PhaseIllidan +{ + PHASE_ILLIDAN_NULL = 0, + PHASE_NORMAL = 1, + PHASE_FLIGHT = 2, + PHASE_NORMAL_2 = 3, + PHASE_DEMON = 4, + PHASE_NORMAL_MAIEV = 5, + PHASE_TALK_SEQUENCE = 6, + PHASE_FLIGHT_SEQUENCE = 7, + PHASE_TRANSFORM_SEQUENCE = 8, + PHASE_ILLIDAN_MAX = 9, +};//Maiev uses the same phase + +enum PhaseAkama +{ + PHASE_AKAMA_NULL = 0, + PHASE_CHANNEL = 1, + PHASE_WALK = 2, + PHASE_TALK = 3, + PHASE_FIGHT_ILLIDAN = 4, + PHASE_FIGHT_MINIONS = 5, + PHASE_RETURN = 6, +}; + +enum EventIllidan +{ + EVENT_NULL = 0, + EVENT_BERSERK = 1, + //normal phase + EVENT_TAUNT = 2, + EVENT_SHEAR = 3, + EVENT_FLAME_CRASH = 4, + EVENT_PARASITIC_SHADOWFIEND = 5, + EVENT_PARASITE_CHECK = 6, + EVENT_DRAW_SOUL = 7, + EVENT_AGONIZING_FLAMES = 8, + EVENT_TRANSFORM_NORMAL = 9, + EVENT_ENRAGE = 10, + //flight phase + EVENT_FIREBALL = 2, + EVENT_DARK_BARRAGE = 3, + EVENT_EYE_BLAST = 4, + EVENT_MOVE_POINT = 5, + //demon phase + EVENT_SHADOW_BLAST = 2, + EVENT_FLAME_BURST = 3, + EVENT_SHADOWDEMON = 4, + EVENT_TRANSFORM_DEMON = 5, + //sequence phase + EVENT_TALK_SEQUENCE = 2, + EVENT_FLIGHT_SEQUENCE = 2, + EVENT_TRANSFORM_SEQUENCE = 2, +}; + +enum EventMaiev +{ + EVENT_MAIEV_NULL = 0, + EVENT_MAIEV_STEALTH = 1, + EVENT_MAIEV_TAUNT = 2, + EVENT_MAIEV_SHADOW_STRIKE = 3, + EVENT_MAIEV_THROW_DAGGER = 4, + EVENT_MAIEV_TRAP = 4, +}; + +static EventIllidan MaxTimer[]= +{ + EVENT_NULL, + EVENT_DRAW_SOUL, + EVENT_MOVE_POINT, + EVENT_TRANSFORM_NORMAL, + EVENT_TRANSFORM_DEMON, + EVENT_ENRAGE, + EVENT_TALK_SEQUENCE, + EVENT_FLIGHT_SEQUENCE, + EVENT_TRANSFORM_SEQUENCE +}; + +struct Yells +{ + uint32 sound; + char* text; + uint32 pCreature, timer, emote; + bool Talk; +}; + +static Yells Conversation[]= +{ + {11463, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.", ILLIDAN_STORMRAGE, 8000, 0, true}, + {0, NULL, ILLIDAN_STORMRAGE, 5000, 396, true}, + {11389, "We've come to end your reign, Illidan. My people and all of Outland shall be free!", AKAMA, 7000, 25, true}, + {0, NULL, AKAMA, 5000, 66, true}, + {11464, "Boldly said. But I remain unconvinced.", ILLIDAN_STORMRAGE, 8000, 396, true}, + {11380, "The time has come! The moment is at hand!", AKAMA, 3000, 22, true}, + {0, NULL, AKAMA, 2000, 15, true}, + {11466, "You are not prepared!", ILLIDAN_STORMRAGE, 3000, 406, true}, + {0, NULL, EMPTY, 1000, 0, true}, + {0, NULL, EMPTY, 0, 0, false},//9 + {11476, "Is this it, mortals? Is this all the fury you can muster?", ILLIDAN_STORMRAGE, 8000, 0, true}, + {11491, "Their fury pales before mine, Illidan. We have some unsettled business between us.", MAIEV_SHADOWSONG, 8000, 5, true}, + {11477, "Maiev... How is this even possible?", ILLIDAN_STORMRAGE, 5000, 1, true}, + {11492, "Ah... my long hunt is finally over. Today, Justice will be done!", MAIEV_SHADOWSONG, 8000, 15, true}, + {11470, "Feel the hatred of ten thousand years!", ILLIDAN_STORMRAGE, 1000, 0, false},//14 + {11496, "Ahh... It is finished. You are beaten.", MAIEV_SHADOWSONG, 6000, 0, true},//15 + {11478, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..", ILLIDAN_STORMRAGE, 30000, 65, true}, // Emote dead for now. Kill him later + {11497, "He is right. I feel nothing... I am nothing... Farewell, champions.", MAIEV_SHADOWSONG, 9000, 0, true}, + {11498, NULL, MAIEV_SHADOWSONG, 5000, 0, true}, + {11498, NULL, EMPTY, 1000, 0, true},//19 Maiev disappear + {11387, "The Light will fill these dismal halls once again. I swear it.", AKAMA, 8000, 0, true}, + {0, NULL, EMPTY, 1000, 0, false}//21 +}; + +static Yells RandomTaunts[]= +{ + {11467, "I can feel your hatred.", ILLIDAN_STORMRAGE, 0, 0, false}, + {11468, "Give in to your fear!", ILLIDAN_STORMRAGE, 0, 0, false}, + {11469, "You know nothing of power!", ILLIDAN_STORMRAGE, 0, 0, false}, + {11471, "Such... arrogance!", ILLIDAN_STORMRAGE, 0, 0, false} +}; + +static Yells MaievTaunts[]= +{ + {11493, "That is for Naisha!", MAIEV_SHADOWSONG, 0, false}, + {11494, "Bleed as I have bled!", MAIEV_SHADOWSONG, 0, 0, false}, + {11495, "There shall be no prison for you this time!", MAIEV_SHADOWSONG, 0, 0, false}, + {11500, "Meet your end, demon!", MAIEV_SHADOWSONG, 0, 0, false} +}; + +struct Locations +{ + float x, y, z; +}; + +static Locations HoverPosition[]= +{ + {657, 340, 355}, + {657, 275, 355}, + {705, 275, 355}, + {705, 340, 355} +}; + +static Locations GlaivePosition[]= +{ + {695.105, 305.303, 354.256}, + {659.338, 305.303, 354.256},//the distance between two glaives is 36 + {700.105, 305.303, 354.256}, + {664.338, 305.303, 354.256} +}; + +static Locations EyeBlast[]= +{ + {677, 350, 354},//start point, pass through glaive point + {677, 260, 354} +}; + +static Locations AkamaWP[]= +{ + {770.01, 304.50, 312.29}, // Bottom of the first stairs, at the doors + {780.66, 304.50, 319.74}, // Top of the first stairs + {790.13, 319.68, 319.76}, // Bottom of the second stairs (left from the entrance) + {787.17, 347.38, 341.42}, // Top of the second stairs + {781.34, 350.31, 341.44}, // Bottom of the third stairs + {762.60, 361.06, 353.60}, // Top of the third stairs + {756.35, 360.52, 353.27}, // Before the door-thingy + {743.82, 342.21, 353.00}, // Somewhere further + {732.69, 305.13, 353.00}, // In front of Illidan - (8) + {738.11, 365.44, 353.00}, // in front of the door-thingy (the other one!) + {792.18, 366.62, 341.42}, // Down the first flight of stairs + {796.84, 304.89, 319.76}, // Down the second flight of stairs + {782.01, 304.55, 319.76} // Final location - back at the initial gates. This is where he will fight the minions! (12) +}; +// 755.762, 304.0747, 312.1769 -- This is where Akama should be spawned +static Locations SpiritSpawns[]= +{ + {755.5426, 309.9156, 312.2129}, + {755.5426, 298.7923, 312.0834} +}; + +struct Animation // For the demon transformation +{ + uint32 aura, unaura, timer, size, displayid, phase; + bool equip; +}; + +static Animation DemonTransformation[]= +{ + {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, true}, + {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, true}, + {0, 0, 3000, 1073741824, 21322, 6, false},//stunned, cannot cast demon form + {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, false}, + {SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 4, false}, + {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, false}, + {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, false}, + {0, SPELL_DEMON_FORM, 3000, 1069547520, 21135, 6, false}, + {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, true}, + {0, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 8, true} +}; + +#define EMOTE_SETS_GAZE_ON "sets its gaze on $N!" +#define EMOTE_UNABLE_TO_SUMMON "is unable to summon Maiev Shadowsong and enter Phase 4. Resetting Encounter." + +/************************************** Illidan's AI ***************************************/ +struct boss_illidan_stormrageAI : public ScriptedAI +{ + boss_illidan_stormrageAI(Creature* c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + DoCast(me, SPELL_DUAL_WIELD, true); + + SpellEntry *TempSpell = GET_SPELL(SPELL_SHADOWFIEND_PASSIVE); + if (TempSpell) + TempSpell->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends + } + + ScriptedInstance* pInstance; + + PhaseIllidan Phase; + EventIllidan Event; + uint32 Timer[EVENT_ENRAGE + 1]; + + uint32 TalkCount; + uint32 TransformCount; + uint32 FlightCount; + + uint32 HoverPoint; + + uint64 AkamaGUID; + uint64 MaievGUID; + uint64 FlameGUID[2]; + uint64 GlaiveGUID[2]; + + SummonList Summons; + + void Reset(); + + void JustSummoned(Creature* summon); + + void SummonedCreatureDespawn(Creature* summon) + { + if (summon->GetCreatureInfo()->Entry == FLAME_OF_AZZINOTH) + { + for (uint8 i = 0; i < 2; ++i) + if (summon->GetGUID() == FlameGUID[i]) + FlameGUID[i] = 0; + + if (!FlameGUID[0] && !FlameGUID[1] && Phase != PHASE_ILLIDAN_NULL) + { + me->InterruptNonMeleeSpells(true); + EnterPhase(PHASE_FLIGHT_SEQUENCE); + } + } + Summons.Despawn(summon); + } + + void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) + { + if (FlightCount == 7) //change hover point + { + if (me->getVictim()) + { + me->SetInFront(me->getVictim()); + me->StopMoving(); + } + EnterPhase(PHASE_FLIGHT); + } + else // handle flight sequence + Timer[EVENT_FLIGHT_SEQUENCE] = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + me->setActive(true); + DoZoneInCombat(); + } + + void AttackStart(Unit *who) + { + if (!who || Phase >= PHASE_TALK_SEQUENCE) + return; + + if (Phase == PHASE_FLIGHT || Phase == PHASE_DEMON) + AttackStartNoMove(who); + else + ScriptedAI::AttackStart(who); + } + + void MoveInLineOfSight(Unit *) {} + + void JustDied(Unit * /*killer*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (!pInstance) + return; + + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, DONE); // Completed + + for (uint8 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L + 1; ++i) + pInstance->HandleGameObject(pInstance->GetData64(i), true); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) return; + // TODO: Find better way to handle emote + switch (urand(0,1)) + { + case 0: + me->MonsterYell(SAY_KILL1, LANG_UNIVERSAL, victim->GetGUID()); + DoPlaySoundToSet(me, SOUND_KILL1); + break; + case 1: + me->MonsterYell(SAY_KILL2, LANG_UNIVERSAL, victim->GetGUID()); + DoPlaySoundToSet(me, SOUND_KILL2); + break; + } + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = 0; + if (done_by->GetGUID() == MaievGUID) + done_by->AddThreat(me, -(3*(float)damage)/4); // do not let maiev tank him + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades! + { + if (!me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) + SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + else + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + } + } + + void DeleteFromThreatList(uint64 TargetGUID) + { + for (std::list::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) + { + if ((*itr)->getUnitGuid() == TargetGUID) + { + (*itr)->removeReference(); + break; + } + } + } + + void Talk(uint32 count) + { + Timer[EVENT_TALK_SEQUENCE] = Conversation[count].timer; + + Creature* pCreature = NULL; + if (Conversation[count].pCreature == ILLIDAN_STORMRAGE) + pCreature = me; + else if (Conversation[count].pCreature == AKAMA) + pCreature = (Unit::GetCreature((*me), AkamaGUID)); + else if (Conversation[count].pCreature == MAIEV_SHADOWSONG) + pCreature = (Unit::GetCreature((*me), MaievGUID)); + + if (pCreature) + { + if (Conversation[count].emote) + pCreature->HandleEmoteCommand(Conversation[count].emote); // Make the Creature do some animation! + if (Conversation[count].text) + pCreature->MonsterYell(Conversation[count].text, LANG_UNIVERSAL, 0); // Have the Creature yell out some text + if (Conversation[count].sound) + DoPlaySoundToSet(pCreature, Conversation[count].sound); // Play some sound on the creature + } + } + + void EnterPhase(PhaseIllidan NextPhase); + void CastEyeBlast(); + void SummonFlamesOfAzzinoth(); + void SummonMaiev(); + void HandleTalkSequence(); + void HandleFlightSequence() + { + switch(FlightCount) + { + case 1://lift off + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + me->StopMoving(); + me->MonsterYell(SAY_TAKEOFF, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_TAKEOFF); + Timer[EVENT_FLIGHT_SEQUENCE] = 3000; + break; + case 2://move to center + me->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); //+5, for SPELL_THROW_GLAIVE bug + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 3://throw one glaive + { + uint8 i=1; + Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Glaive) + { + GlaiveGUID[i] = Glaive->GetGUID(); + Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Glaive->SetDisplayId(11686); + Glaive->setFaction(me->getFaction()); + DoCast(Glaive, SPELL_THROW_GLAIVE2); + } + } + Timer[EVENT_FLIGHT_SEQUENCE] = 700; + break; + case 4://throw another + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + { + uint8 i=0; + Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Glaive) + { + GlaiveGUID[i] = Glaive->GetGUID(); + Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Glaive->SetDisplayId(11686); + Glaive->setFaction(me->getFaction()); + DoCast(Glaive, SPELL_THROW_GLAIVE, true); + } + } + Timer[EVENT_FLIGHT_SEQUENCE] = 5000; + break; + case 5://summon flames + SummonFlamesOfAzzinoth(); + Timer[EVENT_FLIGHT_SEQUENCE] = 3000; + break; + case 6://fly to hover point + me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 7://return to center + me->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 8://glaive return + for (uint8 i = 0; i < 2; ++i) + { + if (GlaiveGUID[i]) + { + Unit* Glaive = Unit::GetUnit((*me), GlaiveGUID[i]); + if (Glaive) + { + Glaive->CastSpell(me, SPELL_GLAIVE_RETURNS, false); // Make it look like the Glaive flies back up to us + Glaive->SetDisplayId(11686); // disappear but not die for now + } + } + } + Timer[EVENT_FLIGHT_SEQUENCE] = 2000; + break; + case 9://land + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->StopMoving(); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + for (uint8 i = 0; i < 2; ++i) + { + if (GlaiveGUID[i]) + { + if (GETUNIT(Glaive, GlaiveGUID[i])) + { + Glaive->SetVisibility(VISIBILITY_OFF); + Glaive->setDeathState(JUST_DIED); // Despawn the Glaive + } + GlaiveGUID[i] = 0; + } + } + Timer[EVENT_FLIGHT_SEQUENCE] = 2000; + break; + case 10://attack + DoResetThreat(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + EnterPhase(PHASE_NORMAL_2); + break; + default: + break; + } + ++FlightCount; + } + + void HandleTransformSequence() + { + if (DemonTransformation[TransformCount].unaura) + me->RemoveAurasDueToSpell(DemonTransformation[TransformCount].unaura); + + if (DemonTransformation[TransformCount].aura) + DoCast(me, DemonTransformation[TransformCount].aura, true); + + if (DemonTransformation[TransformCount].displayid) + me->SetDisplayId(DemonTransformation[TransformCount].displayid); // It's morphin time! + + if (DemonTransformation[TransformCount].equip) + { + // Requip warglaives if needed + SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + } + else + { + // Unequip warglaives if needed + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + } + + switch(TransformCount) + { + case 2: + DoResetThreat(); + break; + case 4: + EnterPhase(PHASE_DEMON); + break; + case 7: + DoResetThreat(); + break; + case 9: + if (MaievGUID) + EnterPhase(PHASE_NORMAL_MAIEV); // Depending on whether we summoned Maiev, we switch to either phase 5 or 3 + else + EnterPhase(PHASE_NORMAL_2); + break; + default: + break; + } + if (Phase == PHASE_TRANSFORM_SEQUENCE) + Timer[EVENT_TRANSFORM_SEQUENCE] = DemonTransformation[TransformCount].timer; + ++TransformCount; + } + + void UpdateAI(const uint32 diff) + { + if ((!UpdateVictim()) && Phase < PHASE_TALK_SEQUENCE) + return; + + Event = EVENT_NULL; + for (uint32 i = 1; i <= MaxTimer[Phase]; ++i) + { + if (Timer[i]) // Event is enabled + if (Timer[i] <= diff) + { + if (!Event) // No event with higher priority + Event = (EventIllidan)i; + } + else Timer[i] -= diff; + } + + switch(Phase) + { + case PHASE_NORMAL: + if (HPPCT(me) < 65) + EnterPhase(PHASE_FLIGHT_SEQUENCE); + break; + + case PHASE_NORMAL_2: + if (HPPCT(me) < 30) + EnterPhase(PHASE_TALK_SEQUENCE); + break; + + case PHASE_NORMAL_MAIEV: + if (HPPCT(me) < 1) + EnterPhase(PHASE_TALK_SEQUENCE); + break; + + case PHASE_TALK_SEQUENCE: + if (Event == EVENT_TALK_SEQUENCE) + HandleTalkSequence(); + break; + + case PHASE_FLIGHT_SEQUENCE: + if (Event == EVENT_FLIGHT_SEQUENCE) + HandleFlightSequence(); + break; + + case PHASE_TRANSFORM_SEQUENCE: + if (Event == EVENT_TRANSFORM_SEQUENCE) + HandleTransformSequence(); + break; + } + + if (me->IsNonMeleeSpellCasted(false)) + return; + + if (Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV && !me->HasAura(SPELL_CAGED)) + { + switch(Event) + { + //PHASE_NORMAL + case EVENT_BERSERK: + me->MonsterYell(SAY_ENRAGE, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_ENRAGE); + DoCast(me, SPELL_BERSERK, true); + Timer[EVENT_BERSERK] = 5000;//The buff actually lasts forever. + break; + + case EVENT_TAUNT: + { + uint32 random = rand()%4; + char* yell = RandomTaunts[random].text; + uint32 soundid = RandomTaunts[random].sound; + if (yell) + me->MonsterYell(yell, LANG_UNIVERSAL, 0); + if (soundid) + DoPlaySoundToSet(me, soundid); + } + Timer[EVENT_TAUNT] = 25000 + rand()%10000; + break; + + case EVENT_SHEAR: + // no longer exists in 3.0.2 + //DoCast(me->getVictim(), SPELL_SHEAR); + Timer[EVENT_SHEAR] = 25000 + (rand()%16 * 1000); + break; + + case EVENT_FLAME_CRASH: + DoCast(me->getVictim(), SPELL_FLAME_CRASH); + Timer[EVENT_FLAME_CRASH] = 30000 + rand()%10000; + break; + + case EVENT_PARASITIC_SHADOWFIEND: + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true)) + DoCast(pTarget, SPELL_PARASITIC_SHADOWFIEND, true); + Timer[EVENT_PARASITIC_SHADOWFIEND] = 35000 + rand()%10000; + } + break; + + case EVENT_PARASITE_CHECK: + Timer[EVENT_PARASITE_CHECK] = 0; + break; + + case EVENT_DRAW_SOUL: + DoCast(me->getVictim(), SPELL_DRAW_SOUL); + Timer[EVENT_DRAW_SOUL] = 50000 + rand()%10000; + break; + + //PHASE_NORMAL_2 + case EVENT_AGONIZING_FLAMES: + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES); + Timer[EVENT_AGONIZING_FLAMES] = 0; + break; + + case EVENT_TRANSFORM_NORMAL: + EnterPhase(PHASE_TRANSFORM_SEQUENCE); + break; + + //PHASE_NORMAL_MAIEV + case EVENT_ENRAGE: + DoCast(me, SPELL_ENRAGE); + Timer[EVENT_ENRAGE] = 0; + break; + + default: + break; + } + DoMeleeAttackIfReady(); + } + + if (Phase == PHASE_FLIGHT) + { + switch(Event) + { + case EVENT_FIREBALL: + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL); + Timer[EVENT_FIREBALL] = 3000; + break; + + case EVENT_DARK_BARRAGE: + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE); + Timer[EVENT_DARK_BARRAGE] = 0; + break; + + case EVENT_EYE_BLAST: + CastEyeBlast(); + Timer[EVENT_EYE_BLAST] = 0; + break; + + case EVENT_MOVE_POINT: + Phase = PHASE_FLIGHT_SEQUENCE; + Timer[EVENT_FLIGHT_SEQUENCE] = 0;//do not start Event when changing hover point + HoverPoint += (rand()%3 + 1); + if (HoverPoint > 3) + HoverPoint -= 4; + me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); + break; + + default: + break; + } + } + + if (Phase == PHASE_DEMON) + { + switch(Event) + { + case EVENT_SHADOW_BLAST: + me->GetMotionMaster()->Clear(false); + if (!me->IsWithinDistInMap(me->getVictim(), 50)||!me->IsWithinLOSInMap(me->getVictim())) + me->GetMotionMaster()->MoveChase(me->getVictim(), 30); + else + me->GetMotionMaster()->MoveIdle(); + DoCast(me->getVictim(), SPELL_SHADOW_BLAST); + Timer[EVENT_SHADOW_BLAST] = 4000; + break; + case EVENT_SHADOWDEMON: + DoCast(me, SPELL_SUMMON_SHADOWDEMON); + Timer[EVENT_SHADOWDEMON] = 0; + Timer[EVENT_FLAME_BURST] += 10000; + break; + case EVENT_FLAME_BURST: + DoCast(me, SPELL_FLAME_BURST); + Timer[EVENT_FLAME_BURST] = 15000; + break; + case EVENT_TRANSFORM_DEMON: + EnterPhase(PHASE_TRANSFORM_SEQUENCE); + break; + default: + break; + } + } + } +}; + +/********************************** End of Illidan AI ******************************************/ + +struct flame_of_azzinothAI : public ScriptedAI +{ + flame_of_azzinothAI(Creature *c) : ScriptedAI(c) {} + + uint32 FlameBlastTimer; + uint32 CheckTimer; + uint64 GlaiveGUID; + + void Reset() + { + FlameBlastTimer = 15000; + CheckTimer = 5000; + GlaiveGUID = 0; + } + + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + + void ChargeCheck() + { + Unit *pTarget = SelectTarget(SELECT_TARGET_FARTHEST, 0, 200, false); + if (pTarget && (!me->IsWithinCombatRange(pTarget, FLAME_CHARGE_DISTANCE))) + { + me->AddThreat(pTarget, 5000000.0f); + AttackStart(pTarget); + DoCast(pTarget, SPELL_CHARGE); + me->MonsterTextEmote(EMOTE_SETS_GAZE_ON, pTarget->GetGUID()); + } + } + + void EnrageCheck() + { + if (GETUNIT(Glaive, GlaiveGUID)) + { + if (!me->IsWithinDistInMap(Glaive, FLAME_ENRAGE_DISTANCE)) + { + Glaive->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_FLAME_ENRAGE, true); + DoResetThreat(); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget && pTarget->isAlive()) + { + me->AddThreat(me->getVictim(), 5000000.0f); + AttackStart(me->getVictim()); + } + } + else if (!me->HasAura(SPELL_AZZINOTH_CHANNEL)) + { + Glaive->CastSpell(me, SPELL_AZZINOTH_CHANNEL, false); + me->RemoveAurasDueToSpell(SPELL_FLAME_ENRAGE); + } + } + } + + void SetGlaiveGUID(uint64 guid){ GlaiveGUID = guid; } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (FlameBlastTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BLAZE_SUMMON, true); //appear at victim + DoCast(me->getVictim(), SPELL_FLAME_BLAST); + FlameBlastTimer = 15000; //10000 is official-like? + DoZoneInCombat(); //in case someone is revived + } else FlameBlastTimer -= diff; + + if (CheckTimer <= diff) + { + ChargeCheck(); + EnrageCheck(); + CheckTimer = 1000; + } else CheckTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +/******* Functions and vars for Akama's AI ******/ +struct npc_akama_illidanAI : public ScriptedAI +{ + npc_akama_illidanAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + JustCreated = true; + } + bool JustCreated; + ScriptedInstance* pInstance; + + PhaseAkama Phase; + bool Event; + uint32 Timer; + + uint64 IllidanGUID; + uint64 ChannelGUID; + uint64 SpiritGUID[2]; + uint64 GateGUID; + uint64 DoorGUID[2]; + + uint32 ChannelCount; + uint32 WalkCount; + uint32 TalkCount; + uint32 Check_Timer; + + void Reset() + { + WalkCount = 0; + if (pInstance) + { + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); + + IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); + GateGUID = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_GATE); + DoorGUID[0] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_R); + DoorGUID[1] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_L); + + if (JustCreated)//close all doors at create + { + pInstance->HandleGameObject(GateGUID, false); + + for (uint8 i = 0; i < 2; ++i) + pInstance->HandleGameObject(DoorGUID[i], false); + //JustCreated = false; + }else + {//open all doors, raid wiped + pInstance->HandleGameObject(GateGUID, true); + WalkCount = 1;//skip first wp + for (uint8 i = 0; i < 2; ++i) + pInstance->HandleGameObject(DoorGUID[i], true); + } + } + else + { + IllidanGUID = 0; + GateGUID = 0; + DoorGUID[0] = 0; + DoorGUID[1] = 0; + } + + ChannelGUID = 0; + SpiritGUID[0] = 0; + SpiritGUID[1] = 0; + + Phase = PHASE_AKAMA_NULL; + Timer = 0; + + ChannelCount = 0; + TalkCount = 0; + Check_Timer = 5000; + + KillAllElites(); + + me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values.. + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->setActive(false); + me->SetVisibility(VISIBILITY_OFF); + } + + // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit + void EnterEvadeMode() + { + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void MovementInform(uint32 MovementType, uint32 /*Data*/) + { + if (MovementType == POINT_MOTION_TYPE) + Timer = 1; + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage > me->GetHealth() || done_by->GetGUID() != IllidanGUID) + damage = 0; + } + + void KillAllElites() + { + std::list& threatList = me->getThreatManager().getThreatList(); + std::vector eliteList; + for (std::list::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->GetEntry() == ILLIDARI_ELITE) + eliteList.push_back(pUnit); + } + for (std::vector::const_iterator itr = eliteList.begin(); itr != eliteList.end(); ++itr) + (*itr)->setDeathState(JUST_DIED); + EnterEvadeMode(); + } + + void BeginTalk() + { + if (!pInstance) + return; + + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, IN_PROGRESS); + for (uint8 i = 0; i < 2; ++i) + pInstance->HandleGameObject(DoorGUID[i], false); + if (GETCRE(Illidan, IllidanGUID)) + { + Illidan->RemoveAurasDueToSpell(SPELL_KNEEL); + me->SetInFront(Illidan); + Illidan->SetInFront(me); + me->GetMotionMaster()->MoveIdle(); + Illidan->GetMotionMaster()->MoveIdle(); + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->AkamaGUID = me->GetGUID(); + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->EnterPhase(PHASE_TALK_SEQUENCE); + } + } + + void BeginChannel() + { + me->setActive(true); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + if (!JustCreated) + return; + float x, y, z; + if (GETGO(Gate, GateGUID)) + Gate->GetPosition(x, y, z); + else + return;//if door not spawned, don't crash server + + if (Creature* Channel = me->SummonCreature(ILLIDAN_DOOR_TRIGGER, x, y, z+5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) + { + ChannelGUID = Channel->GetGUID(); + Channel->SetDisplayId(11686); // Invisible but spell visuals can still be seen. + DoCast(Channel, SPELL_AKAMA_DOOR_FAIL); + } + + for (uint8 i = 0; i < 2; ++i) + if (Creature* Spirit = me->SummonCreature(i ? SPIRIT_OF_OLUM : SPIRIT_OF_UDALO, SpiritSpawns[i].x, SpiritSpawns[i].y, SpiritSpawns[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) + { + Spirit->SetVisibility(VISIBILITY_OFF); + SpiritGUID[i] = Spirit->GetGUID(); + } + } + + void BeginWalk() + { + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->SetSpeed(MOVE_RUN, 1.0f); + me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); + } + + void EnterPhase(PhaseAkama NextPhase) + { + if (!pInstance) + return; + switch(NextPhase) + { + case PHASE_CHANNEL: + BeginChannel(); + Timer = 5000; + ChannelCount = 0; + break; + case PHASE_WALK: + if (Phase == PHASE_CHANNEL) + WalkCount = 0; + else if (Phase == PHASE_TALK) + { + if (GETCRE(Illidan, IllidanGUID)) + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); + EnterEvadeMode(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + ++WalkCount; + } + JustCreated = false; + BeginWalk(); + Timer = 0; + break; + case PHASE_TALK: + if (Phase == PHASE_WALK) + { + BeginTalk(); + Timer = 0; + } + else if (Phase == PHASE_FIGHT_ILLIDAN) + { + Timer = 1; + TalkCount = 0; + } + break; + case PHASE_FIGHT_ILLIDAN: + if (GETUNIT(Illidan, IllidanGUID)) + { + me->AddThreat(Illidan, 10000000.0f); + me->GetMotionMaster()->MoveChase(Illidan); + } + Timer = 30000; //chain lightning + break; + case PHASE_FIGHT_MINIONS: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Timer = 10000 + rand()%6000;//summon minion + break; + case PHASE_RETURN: + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + KillAllElites(); + WalkCount = 0; + BeginWalk(); + Timer = 1; + break; + default: + break; + } + Phase = NextPhase; + Event = false; + } + + void HandleTalkSequence() + { + switch(TalkCount) + { + case 0: + if (GETCRE(Illidan, IllidanGUID)) + { + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->Timer[EVENT_TAUNT] += 30000; + Illidan->MonsterYell(SAY_AKAMA_MINION, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(Illidan, SOUND_AKAMA_MINION); + } + Timer = 8000; + break; + case 1: + me->MonsterYell(SAY_AKAMA_LEAVE, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_AKAMA_LEAVE); + Timer = 3000; + break; + case 2: + EnterPhase(PHASE_WALK); + break; + } + ++TalkCount; + } + + void HandleChannelSequence() + { + Unit* Channel = NULL, *Spirit[2]; + if (ChannelCount <= 5) + { + Channel = Unit::GetUnit((*me), ChannelGUID); + Spirit[0] = Unit::GetUnit((*me), SpiritGUID[0]); + Spirit[1] = Unit::GetUnit((*me), SpiritGUID[1]); + if (!Channel || !Spirit[0] || !Spirit[1]) + return; + } + + switch(ChannelCount) + { + case 0: // channel failed + me->InterruptNonMeleeSpells(true); + Timer = 2000; + break; + case 1: // spirit appear + Spirit[0]->SetVisibility(VISIBILITY_ON); + Spirit[1]->SetVisibility(VISIBILITY_ON); + Timer = 2000; + break; + case 2: // spirit help + DoCast(Channel, SPELL_AKAMA_DOOR_CHANNEL); + Spirit[0]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); + Spirit[1]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); + Timer = 5000; + break; + case 3: //open the gate + me->InterruptNonMeleeSpells(true); + Spirit[0]->InterruptNonMeleeSpells(true); + Spirit[1]->InterruptNonMeleeSpells(true); + if (pInstance) + pInstance->HandleGameObject(GateGUID, true); + Timer = 2000; + break; + case 4: + me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + Timer = 2000; + break; + case 5: + me->MonsterYell(SAY_AKAMA_BEWARE, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_AKAMA_BEWARE); + Channel->setDeathState(JUST_DIED); + Spirit[0]->SetVisibility(VISIBILITY_OFF); + Spirit[1]->SetVisibility(VISIBILITY_OFF); + Timer = 3000; + break; + case 6: + EnterPhase(PHASE_WALK); + break; + default: + break; + } + ++ChannelCount; + } + + void HandleWalkSequence() + { + switch(WalkCount) + { + case 6: + for (uint8 i = 0; i < 2; ++i) + if (pInstance) + pInstance->HandleGameObject(DoorGUID[i], true); + break; + case 8: + if (Phase == PHASE_WALK) + EnterPhase(PHASE_TALK); + else + EnterPhase(PHASE_FIGHT_ILLIDAN); + break; + case 12: + EnterPhase(PHASE_FIGHT_MINIONS); + break; + } + + if (Phase == PHASE_WALK) + { + Timer = 0; + ++WalkCount; + me->GetMotionMaster()->MovePoint(WalkCount, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); + } + } + + void UpdateAI(const uint32 diff) + { + if (me->GetVisibility() == VISIBILITY_OFF) + { + if (Check_Timer <= diff) + { + if (pInstance && pInstance->GetData(DATA_ILLIDARICOUNCILEVENT) == DONE) + me->SetVisibility(VISIBILITY_ON); + + Check_Timer = 5000; + } else Check_Timer -= diff; + } + Event = false; + if (Timer) + { + if (Timer <= diff) + Event = true; + else Timer -= diff; + } + + if (Event) + { + switch(Phase) + { + case PHASE_CHANNEL: + if (JustCreated) + HandleChannelSequence(); + else{ + EnterPhase(PHASE_WALK); + } + break; + case PHASE_TALK: + HandleTalkSequence(); + break; + case PHASE_WALK: + case PHASE_RETURN: + HandleWalkSequence(); + break; + case PHASE_FIGHT_ILLIDAN: + { + GETUNIT(Illidan, IllidanGUID); + if (Illidan && HPPCT(Illidan) < 90) + EnterPhase(PHASE_TALK); + else + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); + Timer = 30000; + } + } + break; + case PHASE_FIGHT_MINIONS: + { + float x, y, z; + me->GetPosition(x, y, z); + Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); + //Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); + if (Elite) + { + Elite->AI()->AttackStart(me); + Elite->AddThreat(me, 1000000.0f); + AttackStart(Elite); + me->AddThreat(Elite, 1000000.0f); + } + Timer = 10000 + rand()%6000; + GETUNIT(Illidan, IllidanGUID); + if (Illidan && HPPCT(Illidan) < 10) + EnterPhase(PHASE_RETURN); + } + break; + default: + break; + } + } + + if (!UpdateVictim()) + return; + + if (me->GetHealth()*100 / me->GetMaxHealth() < 20) + DoCast(me, SPELL_HEALING_POTION); + + DoMeleeAttackIfReady(); + } +}; + +struct boss_maievAI : public ScriptedAI +{ + boss_maievAI(Creature *c) : ScriptedAI(c) {}; + + uint64 IllidanGUID; + + PhaseIllidan Phase; + EventMaiev Event; + uint32 Timer[5]; + uint32 MaxTimer; + + void Reset() + { + MaxTimer = 0; + Phase = PHASE_NORMAL_MAIEV; + IllidanGUID = 0; + Timer[EVENT_MAIEV_STEALTH] = 0; + Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; + Timer[EVENT_MAIEV_SHADOW_STRIKE] = 30000; + SetEquipmentSlots(false, 44850, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, 45738); + } + + void EnterCombat(Unit * /*who*/) {} + void MoveInLineOfSight(Unit * /*who*/) {} + void EnterEvadeMode() {} + void GetIllidanGUID(uint64 guid) { IllidanGUID = guid; } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != IllidanGUID) + damage = 0; + else + { + GETUNIT(Illidan, IllidanGUID); + if (Illidan && Illidan->getVictim() == me) + damage = me->GetMaxHealth()/10; + if (damage >= me->GetHealth()) + damage = 0; + } + } + + void AttackStart(Unit *who) + { + if (!who || Timer[EVENT_MAIEV_STEALTH]) + return; + + if (Phase == PHASE_TALK_SEQUENCE) + AttackStartNoMove(who); + else if (Phase == PHASE_DEMON || Phase == PHASE_TRANSFORM_SEQUENCE) + { + GETUNIT(Illidan, IllidanGUID); + if (Illidan && me->IsWithinDistInMap(Illidan, 25)) + BlinkToPlayer();//Do not let dread aura hurt her. + AttackStartNoMove(who); + } + else + ScriptedAI::AttackStart(who); + } + + void DoAction(const int32 param) + { + if (param > PHASE_ILLIDAN_NULL && param < PHASE_ILLIDAN_MAX) + EnterPhase(PhaseIllidan(param)); + } + + void EnterPhase(PhaseIllidan NextPhase)//This is in fact Illidan's phase. + { + switch(NextPhase) + { + case PHASE_TALK_SEQUENCE: + if (Timer[EVENT_MAIEV_STEALTH]) + { + me->SetHealth(me->GetMaxHealth()); + me->SetVisibility(VISIBILITY_ON); + Timer[EVENT_MAIEV_STEALTH] = 0; + } + me->InterruptNonMeleeSpells(false); + me->GetMotionMaster()->Clear(false); + me->AttackStop(); + me->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); + MaxTimer = 0; + break; + case PHASE_TRANSFORM_SEQUENCE: + MaxTimer = 4; + Timer[EVENT_MAIEV_TAUNT] += 10000; + Timer[EVENT_MAIEV_THROW_DAGGER] = 2000; + break; + case PHASE_DEMON: + break; + case PHASE_NORMAL_MAIEV: + MaxTimer = 4; + Timer[EVENT_MAIEV_TAUNT] += 10000; + Timer[EVENT_MAIEV_TRAP] = 22000; + break; + default: + break; + } + if (Timer[EVENT_MAIEV_STEALTH]) + MaxTimer = 1; + Phase = NextPhase; + } + + void BlinkTo(float x, float y, float z) + { + me->AttackStop(); + me->InterruptNonMeleeSpells(false); + me->GetMotionMaster()->Clear(false); + DoTeleportTo(x, y, z); + DoCast(me, SPELL_TELEPORT_VISUAL, true); + } + + void BlinkToPlayer() + { + if (GETCRE(Illidan, IllidanGUID)) + { + Unit *pTarget = CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (!pTarget || !me->IsWithinDistInMap(pTarget, 80) || Illidan->IsWithinDistInMap(pTarget, 20)) + { + uint8 pos = rand()%4; + BlinkTo(HoverPosition[pos].x, HoverPosition[pos].y, HoverPosition[pos].z); + } + else + { + float x, y, z; + pTarget->GetPosition(x, y, z); + BlinkTo(x, y, z); + } + } + } + + void UpdateAI(const uint32 diff) + { + if ((!UpdateVictim()) + && !Timer[EVENT_MAIEV_STEALTH]) + return; + + Event = EVENT_MAIEV_NULL; + for (uint8 i = 1; i <= MaxTimer; ++i) + if (Timer[i]) + { + if (Timer[i] <= diff) + Event = (EventMaiev)i; + else Timer[i] -= diff; + } + + switch(Event) + { + case EVENT_MAIEV_STEALTH: + { + me->SetHealth(me->GetMaxHealth()); + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Timer[EVENT_MAIEV_STEALTH] = 0; + BlinkToPlayer(); + EnterPhase(Phase); + } + break; + case EVENT_MAIEV_TAUNT: + { + uint32 random = rand()%4; + char* text = MaievTaunts[random].text; + uint32 sound = MaievTaunts[random].sound; + me->MonsterYell(text, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, sound); + Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; + } + break; + case EVENT_MAIEV_SHADOW_STRIKE: + DoCast(me->getVictim(), SPELL_SHADOW_STRIKE); + Timer[EVENT_MAIEV_SHADOW_STRIKE] = 60000; + break; + case EVENT_MAIEV_TRAP: + if (Phase == PHASE_NORMAL_MAIEV) + { + BlinkToPlayer(); + DoCast(me, SPELL_CAGE_TRAP_SUMMON); + Timer[EVENT_MAIEV_TRAP] = 22000; + } + else + { + if (!me->IsWithinDistInMap(me->getVictim(), 40)) + me->GetMotionMaster()->MoveChase(me->getVictim(), 30); + DoCast(me->getVictim(), SPELL_THROW_DAGGER); + Timer[EVENT_MAIEV_THROW_DAGGER] = 2000; + } + break; + default: + break; + } + + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (GETCRE(Illidan, IllidanGUID)) + CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); + me->AttackStop(); + Timer[EVENT_MAIEV_STEALTH] = 60000; //reappear after 1 minute + MaxTimer = 1; + } + + if (Phase == PHASE_NORMAL_MAIEV) + DoMeleeAttackIfReady(); + } +}; + +bool GossipSelect_npc_akama_at_illidan(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) // Time to begin the Event + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_akama_illidanAI, pCreature->AI())->EnterPhase(PHASE_CHANNEL); + } + return true; +} + +bool GossipHello_npc_akama_at_illidan(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(10465, pCreature->GetGUID()); + + return true; +} + +struct cage_trap_triggerAI : public ScriptedAI +{ + cage_trap_triggerAI(Creature *c) : ScriptedAI(c) {} + + uint64 IllidanGUID; + uint32 DespawnTimer; + + bool Active; + bool SummonedBeams; + + void Reset() + { + IllidanGUID = 0; + + Active = false; + SummonedBeams = false; + + DespawnTimer = 0; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/){} + + void MoveInLineOfSight(Unit *who) + { + if (!Active) + return; + + if (who && (who->GetTypeId() != TYPEID_PLAYER)) + { + if (who->GetEntry() == ILLIDAN_STORMRAGE) // Check if who is Illidan + { + if (!IllidanGUID && me->IsWithinDistInMap(who, 3) && (!who->HasAura(SPELL_CAGED))) + { + IllidanGUID = who->GetGUID(); + who->CastSpell(who, SPELL_CAGED, true); + DespawnTimer = 5000; + if (who->HasAura(SPELL_ENRAGE)) + who->RemoveAurasDueToSpell(SPELL_ENRAGE); // Dispel his enrage + //if (GameObject* CageTrap = pInstance->instance->GetGameObject(pInstance->GetData64(CageTrapGUID))) + // CageTrap->SetLootState(GO_JUST_DEACTIVATED); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (DespawnTimer) + if (DespawnTimer <= diff) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else DespawnTimer -= diff; + + //if (IllidanGUID && !SummonedBeams) + //{ + // if (Unit* Illidan = Unit::GetUnit(*me, IllidanGUID) + // { + // //TODO: Find proper spells and properly apply 'caged' Illidan effect + // } + //} + } +}; + +bool GOHello_cage_trap(Player* pPlayer, GameObject* pGo) +{ + float x, y, z; + pPlayer->GetPosition(x, y, z); + + // Grid search for nearest live Creature of entry 23304 within 10 yards + if (Creature* pTrigger = pGo->FindNearestCreature(23304, 10.0f)) + CAST_AI(cage_trap_triggerAI, pTrigger->AI())->Active = true; + pGo->SetGoState(GO_STATE_ACTIVE); + return true; +} + +struct shadow_demonAI : public ScriptedAI +{ + shadow_demonAI(Creature *c) : ScriptedAI(c) {} + + uint64 TargetGUID; + + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + + void Reset() + { + TargetGUID = 0; + DoCast(me, SPELL_SHADOW_DEMON_PASSIVE, true); + } + + void JustDied(Unit * /*killer*/) + { + if (Unit *pTarget = Unit::GetUnit((*me), TargetGUID)) + pTarget->RemoveAurasDueToSpell(SPELL_PARALYZE); + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) return; + + if (me->getVictim()->GetTypeId() != TYPEID_PLAYER) return; // Only cast the below on players. + + if (!me->getVictim()->HasAura(SPELL_PARALYZE)) + { + TargetGUID = me->getVictim()->GetGUID(); + me->AddThreat(me->getVictim(), 10000000.0f); + DoCast(me->getVictim(), SPELL_PURPLE_BEAM, true); + DoCast(me->getVictim(), SPELL_PARALYZE, true); + } + // Kill our target if we're very close. + if (me->IsWithinDistInMap(me->getVictim(), 3)) + DoCast(me->getVictim(), SPELL_CONSUME_SOUL); + } +}; + +// Shadowfiends interact with Illidan, setting more targets in Illidan's hashmap +struct mob_parasitic_shadowfiendAI : public ScriptedAI +{ + mob_parasitic_shadowfiendAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint64 IllidanGUID; + uint32 CheckTimer; + + void Reset() + { + if (pInstance) + IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); + else + IllidanGUID = 0; + + CheckTimer = 5000; + DoCast(me, SPELL_SHADOWFIEND_PASSIVE, true); + } + + void EnterCombat(Unit* /*who*/) { DoZoneInCombat(); } + + void DoMeleeAttackIfReady() + { + if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim())) + { + if (!me->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND) + && !me->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) + { + if (Creature* illidan = Unit::GetCreature((*me),IllidanGUID))//summon only in 1. phase + if (CAST_AI(boss_illidan_stormrageAI, illidan->AI())->Phase == PHASE_NORMAL) + me->CastSpell(me->getVictim(), SPELL_PARASITIC_SHADOWFIEND2, true, 0, 0, IllidanGUID); //do not stack + } + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->getVictim()) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) + AttackStart(pTarget); + else + { + me->SetVisibility(VISIBILITY_OFF); + me->setDeathState(JUST_DIED); + return; + } + } + + if (CheckTimer <= diff) + { + GETUNIT(Illidan, IllidanGUID); + if (!Illidan || CAST_CRE(Illidan)->IsInEvadeMode()) + { + me->SetVisibility(VISIBILITY_OFF); + me->setDeathState(JUST_DIED); + return; + } else CheckTimer = 5000; + } else CheckTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct blade_of_azzinothAI : public NullCreatureAI +{ + blade_of_azzinothAI(Creature* c) : NullCreatureAI(c) {} + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_THROW_GLAIVE2 || spell->Id == SPELL_THROW_GLAIVE) + me->SetDisplayId(21431);//appear when hit by Illidan's glaive + } +}; + +void boss_illidan_stormrageAI::Reset() +{ + if (pInstance) + pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); + + if (AkamaGUID) + { + if (GETCRE(Akama, AkamaGUID)) + { + if (!Akama->isAlive()) + Akama->Respawn(); + else + { + CAST_AI(npc_akama_illidanAI, Akama->AI())->EnterEvadeMode(); + Akama->GetMotionMaster()->MoveTargetedHome(); + CAST_AI(npc_akama_illidanAI, Akama->AI())->Reset(); + } + } + AkamaGUID = 0; + } + + MaievGUID = 0; + for (uint8 i = 0; i < 2; ++i) + { + FlameGUID[i] = 0; + GlaiveGUID[i] = 0; + } + + Phase = PHASE_ILLIDAN_NULL; + Event = EVENT_NULL; + Timer[EVENT_BERSERK] = 1500000; + + HoverPoint = 0; + TalkCount = 0; + FlightCount = 0; + TransformCount = 0; + + me->SetDisplayId(21135); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->setActive(false); + Summons.DespawnAll(); +} + +void boss_illidan_stormrageAI::JustSummoned(Creature* summon) +{ + Summons.Summon(summon); + switch(summon->GetEntry()) + { + case PARASITIC_SHADOWFIEND: + { + if (Phase == PHASE_TALK_SEQUENCE) + { + summon->SetVisibility(VISIBILITY_OFF); + summon->setDeathState(JUST_DIED); + return; + } + Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true); + if (!pTarget || pTarget->HasAura(SPELL_PARASITIC_SHADOWFIEND) + || pTarget->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true); + if (pTarget) + summon->AI()->AttackStart(pTarget); + } + break; + case SHADOW_DEMON: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) // only on players. + { + summon->AddThreat(pTarget, 5000000.0f); + summon->AI()->AttackStart(pTarget); + } + break; + case MAIEV_SHADOWSONG: + { + summon->SetVisibility(VISIBILITY_OFF); // Leave her invisible until she has to talk + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + MaievGUID = summon->GetGUID(); + CAST_AI(boss_maievAI, summon->AI())->GetIllidanGUID(me->GetGUID()); + summon->AI()->DoAction(PHASE_TALK_SEQUENCE); + } + break; + case FLAME_OF_AZZINOTH: + { + summon->AI()->AttackStart(summon->SelectNearestTarget(999)); + } + break; + default: + break; + } +} + +void boss_illidan_stormrageAI::HandleTalkSequence() +{ + switch(TalkCount) + { + case 0: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + break; + case 8: + // Equip our warglaives! + SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + break; + case 9: + if (GETCRE(Akama, AkamaGUID)) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->AddThreat(Akama, 100.0f); + CAST_AI(npc_akama_illidanAI, Akama->AI())->EnterPhase(PHASE_FIGHT_ILLIDAN); + EnterPhase(PHASE_NORMAL); + } + break; + case 10: + SummonMaiev(); + break; + case 11: + if (GETUNIT(Maiev, MaievGUID)) + { + Maiev->SetVisibility(VISIBILITY_ON); // Maiev is now visible + Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); // onoz she looks like she teleported! + Maiev->SetInFront(me); // Have her face us + me->SetInFront(Maiev); // Face her, so it's not rude =P + Maiev->GetMotionMaster()->MoveIdle(); + me->GetMotionMaster()->MoveIdle(); + } + break; + case 14: + if (GETCRE(Maiev, MaievGUID)) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + Maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + Maiev->AddThreat(me, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE + Maiev->AI()->AttackStart(me); // Force Maiev to attack us. + EnterPhase(PHASE_NORMAL_MAIEV); + } + break; + case 15: + DoCast(me, SPELL_DEATH); // Animate his kneeling + stun him + Summons.DespawnAll(); + break; + case 17: + if (GETUNIT(Akama, AkamaGUID)) + { + if (!me->IsWithinDistInMap(Akama, 15)) + { + float x, y, z; + me->GetPosition(x, y, z); + x += 10; y += 10; + Akama->GetMotionMaster()->Clear(false); + //Akama->GetMotionMaster()->MoveIdle(); + Akama->GetMap()->CreatureRelocation(me, x, y, z, 0.0f); + Akama->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_NONE, 0);//Illidan must not die until Akama arrives. + Akama->GetMotionMaster()->MoveChase(me); + } + } + break; + case 19: // Make Maiev leave + if (GETUNIT(Maiev, MaievGUID)) + { + Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); + Maiev->setDeathState(JUST_DIED); + me->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); + } + break; + case 21: // Kill ourself. + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + break; + default: + break; + } + if (Phase == PHASE_TALK_SEQUENCE) + Talk(TalkCount); // This function does most of the talking + ++TalkCount; +} + +void boss_illidan_stormrageAI::CastEyeBlast() +{ + me->InterruptNonMeleeSpells(false); + + me->MonsterYell(SAY_EYE_BLAST, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_EYE_BLAST); + + float distx, disty, dist[2]; + for (uint8 i = 0; i < 2; ++i) + { + distx = EyeBlast[i].x - HoverPosition[HoverPoint].x; + disty = EyeBlast[i].y - HoverPosition[HoverPoint].y; + dist[i] = distx * distx + disty * disty; + } + Locations initial = EyeBlast[dist[0] < dist[1] ? 0 : 1]; + for (uint8 i = 0; i < 2; ++i) + { + distx = GlaivePosition[i].x - HoverPosition[HoverPoint].x; + disty = GlaivePosition[i].y - HoverPosition[HoverPoint].y; + dist[i] = distx * distx + disty * disty; + } + Locations final = GlaivePosition[dist[0] < dist[1] ? 0 : 1]; + + final.x = 2 * final.x - initial.x; + final.y = 2 * final.y - initial.y; + + Creature* Trigger = me->SummonCreature(23069, initial.x, initial.y, initial.z, 0, TEMPSUMMON_TIMED_DESPAWN, 13000); + if (!Trigger) return; + + Trigger->SetSpeed(MOVE_WALK, 3); + Trigger->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z); + + //Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetUInt64Value(UNIT_FIELD_TARGET, Trigger->GetGUID()); + DoCast(Trigger, SPELL_EYE_BLAST); +} + +void boss_illidan_stormrageAI::SummonFlamesOfAzzinoth() +{ + me->MonsterYell(SAY_SUMMONFLAMES, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_SUMMONFLAMES); + + for (uint8 i = 0; i < 2; ++i) + { + if (GETUNIT(Glaive, GlaiveGUID[i])) + { + Creature* Flame = me->SummonCreature(FLAME_OF_AZZINOTH, GlaivePosition[i+2].x, GlaivePosition[i+2].y, GlaivePosition[i+2].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + if (Flame) + { + Flame->setFaction(me->getFaction()); // Just in case the database has it as a different faction + Flame->SetMeleeDamageSchool(SPELL_SCHOOL_FIRE); + FlameGUID[i] = Flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase + CAST_AI(flame_of_azzinothAI, Flame->AI())->SetGlaiveGUID(GlaiveGUID[i]); + Glaive->CastSpell(Flame, SPELL_AZZINOTH_CHANNEL, false); // Glaives do some random Beam type channel on it. + } + } + } +} + +void boss_illidan_stormrageAI::SummonMaiev() +{ + DoCast(me, SPELL_SHADOW_PRISON, true); + DoCast(me, 40403, true); + if (!MaievGUID) // If Maiev cannot be summoned, reset the encounter and post some errors to the console. + { + EnterEvadeMode(); + me->MonsterTextEmote(EMOTE_UNABLE_TO_SUMMON, 0); + error_log("SD2 ERROR: Unable to summon Maiev Shadowsong (entry: 23197). Check your database to see if you have the proper SQL for Maiev Shadowsong (entry: 23197)"); + } +} + +void boss_illidan_stormrageAI::EnterPhase(PhaseIllidan NextPhase) +{ + DoZoneInCombat(); + switch(NextPhase) + { + case PHASE_NORMAL: + case PHASE_NORMAL_2: + case PHASE_NORMAL_MAIEV: + AttackStart(me->getVictim()); + Timer[EVENT_TAUNT] = 32000; + Timer[EVENT_SHEAR] = 10000 + rand()%15 * 1000; + Timer[EVENT_FLAME_CRASH] = 20000; + Timer[EVENT_PARASITIC_SHADOWFIEND] = 25000; + Timer[EVENT_PARASITE_CHECK] = 0; + Timer[EVENT_DRAW_SOUL] = 30000; + if (NextPhase == PHASE_NORMAL) + break; + Timer[EVENT_AGONIZING_FLAMES] = 35000; + Timer[EVENT_TRANSFORM_NORMAL] = 60000; + if (NextPhase == PHASE_NORMAL_2) + break; + Timer[EVENT_ENRAGE] = 30000 + rand()%10 * 1000; + break; + case PHASE_FLIGHT: + Timer[EVENT_FIREBALL] = 1000; + if (!(rand()%4)) + Timer[EVENT_DARK_BARRAGE] = 10000; + Timer[EVENT_EYE_BLAST] = 10000 + rand()%15 * 1000; + Timer[EVENT_MOVE_POINT] = 20000 + rand()%20 * 1000; + break; + case PHASE_DEMON: + Timer[EVENT_SHADOW_BLAST] = 1000; + Timer[EVENT_FLAME_BURST] = 10000; + Timer[EVENT_SHADOWDEMON] = 30000; + Timer[EVENT_TRANSFORM_DEMON] = 60000; + AttackStart(me->getVictim()); + break; + case PHASE_TALK_SEQUENCE: + Timer[EVENT_TALK_SEQUENCE] = 100; + me->RemoveAllAuras(); + me->InterruptNonMeleeSpells(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->Clear(false); + me->AttackStop(); + break; + case PHASE_FLIGHT_SEQUENCE: + if (Phase == PHASE_NORMAL) //lift off + { + FlightCount = 1; + Timer[EVENT_FLIGHT_SEQUENCE] = 1; + me->RemoveAllAuras(); + me->InterruptNonMeleeSpells(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->Clear(false); + me->AttackStop(); + } + else //land + Timer[EVENT_FLIGHT_SEQUENCE] = 2000; + break; + case PHASE_TRANSFORM_SEQUENCE: + if (Phase == PHASE_DEMON) + Timer[EVENT_TRANSFORM_SEQUENCE] = 500; + else + { + TransformCount = 0; + Timer[EVENT_TRANSFORM_SEQUENCE] = 500; + me->MonsterYell(SAY_MORPH, LANG_UNIVERSAL, 0); + DoPlaySoundToSet(me, SOUND_MORPH); + } + me->GetMotionMaster()->Clear(); + me->AttackStop(); + break; + default: + break; + } + if (MaievGUID) + { + GETCRE(Maiev, MaievGUID); + if (Maiev && Maiev->isAlive()) + Maiev->AI()->DoAction(NextPhase); + } + Phase = NextPhase; + Event = EVENT_NULL; +} + +CreatureAI* GetAI_boss_illidan_stormrage(Creature* pCreature) +{ + return new boss_illidan_stormrageAI (pCreature); +} + +CreatureAI* GetAI_npc_akama_at_illidan(Creature* pCreature) +{ + return new npc_akama_illidanAI(pCreature); +} + +CreatureAI* GetAI_boss_maiev(Creature* pCreature) +{ + return new boss_maievAI (pCreature); +} + +CreatureAI* GetAI_mob_flame_of_azzinoth(Creature* pCreature) +{ + return new flame_of_azzinothAI (pCreature); +} + +CreatureAI* GetAI_cage_trap_trigger(Creature* pCreature) +{ + return new cage_trap_triggerAI (pCreature); +} + +CreatureAI* GetAI_shadow_demon(Creature* pCreature) +{ + return new shadow_demonAI (pCreature); +} + +CreatureAI* GetAI_blade_of_azzinoth(Creature* pCreature) +{ + return new blade_of_azzinothAI (pCreature); +} + +CreatureAI* GetAI_parasitic_shadowfiend(Creature* pCreature) +{ + return new mob_parasitic_shadowfiendAI (pCreature); +} + +void AddSC_boss_illidan() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_illidan_stormrage"; + newscript->GetAI = &GetAI_boss_illidan_stormrage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_akama_illidan"; + newscript->GetAI = &GetAI_npc_akama_at_illidan; + newscript->pGossipHello = &GossipHello_npc_akama_at_illidan; + newscript->pGossipSelect = &GossipSelect_npc_akama_at_illidan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_maiev_shadowsong"; + newscript->GetAI = &GetAI_boss_maiev; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flame_of_azzinoth"; + newscript->GetAI = &GetAI_mob_flame_of_azzinoth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_blade_of_azzinoth"; + newscript->GetAI = &GetAI_blade_of_azzinoth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "gameobject_cage_trap"; + newscript->pGOHello = &GOHello_cage_trap; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_cage_trap_trigger"; + newscript->GetAI = &GetAI_cage_trap_trigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadow_demon"; + newscript->GetAI = &GetAI_shadow_demon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_parasitic_shadowfiend"; + newscript->GetAI = &GetAI_parasitic_shadowfiend; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp new file mode 100644 index 00000000000..5949fc46511 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp @@ -0,0 +1,302 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mother_Shahraz +SD%Complete: 80 +SDComment: Saber Lash missing, Fatal Attraction slightly incorrect; need to damage only if affected players are within range of each other +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +//Speech'n'Sounds +#define SAY_TAUNT1 -1564018 +#define SAY_TAUNT2 -1564019 +#define SAY_TAUNT3 -1564020 +#define SAY_AGGRO -1564021 +#define SAY_SPELL1 -1564022 +#define SAY_SPELL2 -1564023 +#define SAY_SPELL3 -1564024 +#define SAY_SLAY1 -1564025 +#define SAY_SLAY2 -1564026 +#define SAY_ENRAGE -1564027 +#define SAY_DEATH -1564028 + +//Spells +#define SPELL_BEAM_SINISTER 40859 +#define SPELL_BEAM_VILE 40860 +#define SPELL_BEAM_WICKED 40861 +#define SPELL_BEAM_SINFUL 40827 +#define SPELL_ATTRACTION 40871 +#define SPELL_SILENCING_SHRIEK 40823 +#define SPELL_ENRAGE 23537 +#define SPELL_SABER_LASH 40810//43267 +#define SPELL_SABER_LASH_IMM 43690 +#define SPELL_TELEPORT_VISUAL 40869 +#define SPELL_BERSERK 45078 + +uint32 PrismaticAuras[]= +{ + 40880, // Shadow + 40882, // Fire + 40883, // Nature + 40891, // Arcane + 40896, // Frost + 40897, // Holy +}; + +struct Locations +{ + float x,y,z; +}; + +static Locations TeleportPoint[]= +{ + {959.996, 212.576, 193.843}, + {932.537, 231.813, 193.838}, + {958.675, 254.767, 193.822}, + {946.955, 201.316, 192.535}, + {944.294, 149.676, 197.551}, + {930.548, 284.888, 193.367}, + {965.997, 278.398, 195.777} +}; + +struct boss_shahrazAI : public ScriptedAI +{ + boss_shahrazAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 TargetGUID[3]; + uint32 BeamTimer; + uint32 BeamCount; + uint32 CurrentBeam; + uint32 PrismaticShieldTimer; + uint32 FatalAttractionTimer; + uint32 FatalAttractionExplodeTimer; + uint32 ShriekTimer; + uint32 SaberTimer; + uint32 RandomYellTimer; + uint32 EnrageTimer; + uint32 ExplosionCount; + + bool Enraged; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, NOT_STARTED); + + for (uint8 i = 0; i<3; ++i) + TargetGUID[i] = 0; + + BeamTimer = 20000; // Timers may be incorrect + BeamCount = 0; + CurrentBeam = 0; // 0 - Sinister, 1 - Vile, 2 - Wicked, 3 - Sinful + PrismaticShieldTimer = 0; + FatalAttractionTimer = 60000; + FatalAttractionExplodeTimer = 70000; + ShriekTimer = 30000; + SaberTimer = 35000; + RandomYellTimer = 70000 + rand()%41 * 1000; + EnrageTimer = 600000; + ExplosionCount = 0; + + Enraged = false; + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, IN_PROGRESS); + + DoZoneInCombat(); + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + void TeleportPlayers() + { + uint32 random = rand()%7; + float X = TeleportPoint[random].x; + float Y = TeleportPoint[random].y; + float Z = TeleportPoint[random].z; + for (uint8 i = 0; i < 3; ++i) + { + Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + TargetGUID[i] = pUnit->GetGUID(); + pUnit->CastSpell(pUnit, SPELL_TELEPORT_VISUAL, true); + DoTeleportPlayer(pUnit, X, Y, Z, pUnit->GetOrientation()); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !Enraged) + { + Enraged = true; + DoCast(me, SPELL_ENRAGE, true); + DoScriptText(SAY_ENRAGE, me); + } + + //Randomly cast one beam. + if (BeamTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (!pTarget || !pTarget->isAlive()) + return; + + BeamTimer = 9000; + + switch(CurrentBeam) + { + case 0: + DoCast(pTarget, SPELL_BEAM_SINISTER); + break; + case 1: + DoCast(pTarget, SPELL_BEAM_VILE); + break; + case 2: + DoCast(pTarget, SPELL_BEAM_WICKED); + break; + case 3: + DoCast(pTarget, SPELL_BEAM_SINFUL); + break; + } + ++BeamCount; + uint32 Beam = CurrentBeam; + if (BeamCount > 3) + while (CurrentBeam == Beam) + CurrentBeam = rand()%3; + + } else BeamTimer -= diff; + + // Random Prismatic Shield every 15 seconds. + if (PrismaticShieldTimer <= diff) + { + uint32 random = rand()%6; + if (PrismaticAuras[random]) + DoCast(me, PrismaticAuras[random]); + PrismaticShieldTimer = 15000; + } else PrismaticShieldTimer -= diff; + + // Select 3 random targets (can select same target more than once), teleport to a random location then make them cast explosions until they get away from each other. + if (FatalAttractionTimer <= diff) + { + ExplosionCount = 0; + + TeleportPlayers(); + + DoScriptText(RAND(SAY_SPELL2,SAY_SPELL3), me); + FatalAttractionExplodeTimer = 2000; + FatalAttractionTimer = 40000 + rand()%31 * 1000; + } else FatalAttractionTimer -= diff; + + if (FatalAttractionExplodeTimer <= diff) + { + // Just make them explode three times... they're supposed to keep exploding while they are in range, but it'll take too much code. I'll try to think of an efficient way for it later. + if (ExplosionCount < 3) + { + for (uint8 i = 0; i < 3; ++i) + { + Unit* pUnit = NULL; + if (TargetGUID[i]) + { + pUnit = Unit::GetUnit((*me), TargetGUID[i]); + if (pUnit) + pUnit->CastSpell(pUnit, SPELL_ATTRACTION, true); + TargetGUID[i] = 0; + } + } + + ++ExplosionCount; + FatalAttractionExplodeTimer = 1000; + } + else + { + FatalAttractionExplodeTimer = FatalAttractionTimer + 2000; + ExplosionCount = 0; + } + } else FatalAttractionExplodeTimer -= diff; + + if (ShriekTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCING_SHRIEK); + ShriekTimer = 25000+rand()%10 * 1000; + } else ShriekTimer -= diff; + + if (SaberTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SABER_LASH); + SaberTimer = 25000+rand()%10 * 1000; + } else SaberTimer -= diff; + + //Enrage + if (!me->HasAura(SPELL_BERSERK)) + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + DoScriptText(SAY_ENRAGE, me); + } else EnrageTimer -= diff; + + //Random taunts + if (RandomYellTimer <= diff) + { + DoScriptText(RAND(SAY_TAUNT1,SAY_TAUNT2,SAY_TAUNT3), me); + RandomYellTimer = 60000 + rand()%91 * 1000; + } else RandomYellTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shahraz(Creature* pCreature) +{ + return new boss_shahrazAI (pCreature); +} + +void AddSC_boss_mother_shahraz() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_mother_shahraz"; + newscript->GetAI = &GetAI_boss_shahraz; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp new file mode 100644 index 00000000000..3e019a8dc35 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -0,0 +1,690 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Reliquary_of_Souls +SD%Complete: 90 +SDComment: +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" +#include "Spell.h" + +//Sound'n'speech +//Suffering +#define SUFF_SAY_FREED -1564047 +#define SUFF_SAY_AGGRO -1564048 +#define SUFF_SAY_SLAY1 -1564049 +#define SUFF_SAY_SLAY2 -1564050 +#define SUFF_SAY_SLAY3 -1564051 +#define SUFF_SAY_RECAP -1564052 +#define SUFF_SAY_AFTER -1564053 +#define SUFF_EMOTE_ENRAGE -1564054 + +//Desire +#define DESI_SAY_FREED -1564055 +#define DESI_SAY_SLAY1 -1564056 +#define DESI_SAY_SLAY2 -1564057 +#define DESI_SAY_SLAY3 -1564058 +#define DESI_SAY_SPEC -1564059 +#define DESI_SAY_RECAP -1564060 +#define DESI_SAY_AFTER -1564061 + +//Anger +#define ANGER_SAY_FREED -1564062 +#define ANGER_SAY_FREED2 -1564063 +#define ANGER_SAY_SLAY1 -1564064 +#define ANGER_SAY_SLAY2 -1564065 +#define ANGER_SAY_SPEC -1564066 +#define ANGER_SAY_BEFORE -1564067 +#define ANGER_SAY_DEATH -1564068 + +//Spells +#define AURA_OF_SUFFERING 41292 +#define AURA_OF_SUFFERING_ARMOR 42017 // linked aura, need core support +#define ESSENCE_OF_SUFFERING_PASSIVE 41296 // periodic trigger 41294 +#define ESSENCE_OF_SUFFERING_PASSIVE2 41623 +#define SPELL_FIXATE_TARGET 41294 // dummy, select target +#define SPELL_FIXATE_TAUNT 41295 // force taunt +#define SPELL_ENRAGE 41305 +#define SPELL_SOUL_DRAIN 41303 + +#define AURA_OF_DESIRE 41350 +#define AURA_OF_DESIRE_DAMAGE 41352 +#define SPELL_RUNE_SHIELD 41431 +#define SPELL_DEADEN 41410 +#define SPELL_SOUL_SHOCK 41426 + +#define AURA_OF_ANGER 41337 +#define SPELL_SELF_SEETHE 41364 // force cast 41520 +#define SPELL_ENEMY_SEETHE 41520 +#define SPELL_SOUL_SCREAM 41545 +#define SPELL_SPITE_TARGET 41376 // cast 41377 after 6 sec +#define SPELL_SPITE_DAMAGE 41377 + +#define ENSLAVED_SOUL_PASSIVE 41535 +#define SPELL_SOUL_RELEASE 41542 +#define SPELL_SUBMERGE 37550 //dropout 'head' + +#define CREATURE_ENSLAVED_SOUL 23469 +#define NUMBER_ENSLAVED_SOUL 8 + +struct Position2d +{ + float x,y; +}; + +static Position2d Coords[]= +{ + {450.4, 212.3}, + {542.1, 212.3}, + {542.1, 168.3}, + {542.1, 137.4}, + {450.4, 137.4}, + {450.4, 168.3} +}; + +struct npc_enslaved_soulAI : public ScriptedAI +{ + npc_enslaved_soulAI(Creature *c) : ScriptedAI(c) {} + + uint64 ReliquaryGUID; + + void Reset() {ReliquaryGUID = 0;} + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, ENSLAVED_SOUL_PASSIVE, true); + DoZoneInCombat(); + } + + void JustDied(Unit *killer); +}; + +struct boss_reliquary_of_soulsAI : public ScriptedAI +{ + boss_reliquary_of_soulsAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EssenceGUID = 0; + } + + ScriptedInstance* pInstance; + + uint64 EssenceGUID; + + uint32 Phase; + uint32 Counter; + uint32 Timer; + + uint32 SoulCount; + uint32 SoulDeathCount; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, NOT_STARTED); + + if (EssenceGUID) + { + if (Creature* Essence = Unit::GetCreature(*me, EssenceGUID)) + { + Essence->ForcedDespawn(); + } + EssenceGUID = 0; + } + + Phase = 0; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + me->RemoveAurasDueToSpell(SPELL_SUBMERGE); + } + + void EnterCombat(Unit* who) + { + me->AddThreat(who, 10000.0f); + DoZoneInCombat(); + if (pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, IN_PROGRESS); + + Phase = 1; + Counter = 0; + Timer = 0; + } + + bool SummonSoul() + { + uint32 random = rand()%6; + float x = Coords[random].x; + float y = Coords[random].y; + Creature* Soul = me->SummonCreature(CREATURE_ENSLAVED_SOUL, x, y, me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0); + if (!Soul) return false; + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + CAST_AI(npc_enslaved_soulAI, Soul->AI())->ReliquaryGUID = me->GetGUID(); + Soul->AI()->AttackStart(pTarget); + } else EnterEvadeMode(); + return true; + } + + void MergeThreatList(Creature *pTarget) + { + if (!pTarget) + return; + + std::list& m_threatlist = pTarget->getThreatManager().getThreatList(); + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit) + { + DoModifyThreatPercent(pUnit, -100); + float threat = pTarget->getThreatManager().getThreat(pUnit); + me->AddThreat(pUnit, threat); // This makes it so that the unit has the same amount of threat in Reliquary's threatlist as in the target creature's (One of the Essences). + } + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!Phase) + return; + + if (me->getThreatManager().getThreatList().empty()) // Reset if event is begun and we don't have a threatlist + { + EnterEvadeMode(); + return; + } + + Creature* Essence = NULL; + if (EssenceGUID) + { + Essence = Unit::GetCreature(*me, EssenceGUID); + if (!Essence) + { + EnterEvadeMode(); + return; + } + } + + if (Timer <= diff) + { + switch(Counter) + { + case 0: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); // I R ANNNGRRRY! + DoStartNoMovement(me); + Timer = 3000; + break; + case 1: + Timer = 2800; + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_SUBMERGE); // Release the cube + DoCast(me, SPELL_SUBMERGE); + DoStartNoMovement(me); + break; + case 2: + Timer = 5000; + if (Creature* Summon = DoSpawnCreature(23417+Phase, 0, 0, 0, 0, TEMPSUMMON_DEAD_DESPAWN, 0)) + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED); // Ribs: open + Summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_TOPAGGRO, 0)); + EssenceGUID = Summon->GetGUID(); + DoStartNoMovement(me); + } else EnterEvadeMode(); + break; + case 3: + Timer = 1000; + if (Phase == 3) + { + if (!Essence->isAlive()) + DoCast(me, 7, true); + else return; + } + else + { + if (Essence->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + { + MergeThreatList(Essence); + Essence->RemoveAllAuras(); + Essence->DeleteThreatList(); + Essence->GetMotionMaster()->MoveFollow(me,0.0f,0.0f); + } else return; + } + break; + case 4: + Timer = 1500; + if (Essence->IsWithinDistInMap(me, 10)) + { + Essence->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); //rotate and disappear + Timer = 2000; + me->RemoveAurasDueToSpell(SPELL_SUBMERGE); + } + else + { + MergeThreatList(Essence); + Essence->RemoveAllAuras(); + Essence->DeleteThreatList(); + Essence->GetMotionMaster()->MoveFollow(me, 0, 0); + return; + } + break; + case 5: + if (Phase == 1) + { + DoScriptText(SUFF_SAY_AFTER, Essence); + } + else + { + DoScriptText(DESI_SAY_AFTER, Essence); + } + Essence->ForcedDespawn(); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE,0); + EssenceGUID = 0; + SoulCount = 0; + SoulDeathCount = 0; + Timer = 3000; + break; + case 6: + if (SoulCount < NUMBER_ENSLAVED_SOUL) + { + if (SummonSoul()) + ++SoulCount; + Timer = 500; + return; + } + break; + case 7: + if (SoulDeathCount >= SoulCount) + { + Counter = 1; + ++Phase; + Timer = 5000; + } + return; + default: + break; + } + ++Counter; + } else Timer -= diff; + } +}; + +struct boss_essence_of_sufferingAI : public ScriptedAI +{ + boss_essence_of_sufferingAI(Creature *c) : ScriptedAI(c) {} + + uint64 StatAuraGUID; + + uint32 AggroYellTimer; + uint32 FixateTimer; + uint32 EnrageTimer; + uint32 SoulDrainTimer; + uint32 AuraTimer; + + void Reset() + { + StatAuraGUID = 0; + + AggroYellTimer = 5000; + FixateTimer = 8000; + EnrageTimer = 30000; + SoulDrainTimer = 45000; + AuraTimer = 5000; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + damage = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->Yell(SUFF_SAY_RECAP,LANG_UNIVERSAL,0); + DoScriptText(SUFF_SAY_RECAP, me); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + { + DoScriptText(SUFF_SAY_FREED, me); + DoZoneInCombat(); + DoCast(me, AURA_OF_SUFFERING, true); // linked aura need core support + DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE, true); + DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE2, true); + } + else return; + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SUFF_SAY_SLAY1,SUFF_SAY_SLAY2,SUFF_SAY_SLAY3), me); + } + + void CastFixate() + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + if (m_threatlist.empty()) + return; // No point continuing if empty threatlist. + std::list targets; + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) // Only alive players + targets.push_back(pUnit); + } + if (targets.empty()) + return; // No targets added for some reason. No point continuing. + targets.sort(Trinity::ObjectDistanceOrderPred(me)); // Sort players by distance. + targets.resize(1); // Only need closest target. + Unit *pTarget = targets.front(); // Get the first target. + if (pTarget) + pTarget->CastSpell(me, SPELL_FIXATE_TAUNT, true); + DoResetThreat(); + me->AddThreat(pTarget,1000000); + } + + void UpdateAI(const uint32 diff) + { + if (me->isInCombat()) + { + //Supposed to be cast on nearest target + if (FixateTimer <= diff) + { + CastFixate(); + FixateTimer = 5000; + if (!(rand()%16)) + { + DoScriptText(SUFF_SAY_AGGRO, me); + } + } else FixateTimer -= diff; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_ENRAGE); + EnrageTimer = 60000; + DoScriptText(SUFF_EMOTE_ENRAGE, me); + } else EnrageTimer -= diff; + + if (SoulDrainTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SOUL_DRAIN); + SoulDrainTimer = 60000; + } else SoulDrainTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_essence_of_desireAI : public ScriptedAI +{ + boss_essence_of_desireAI(Creature *c) : ScriptedAI(c) {} + + uint32 RuneShieldTimer; + uint32 DeadenTimer; + uint32 SoulShockTimer; + + void Reset() + { + RuneShieldTimer = 60000; + DeadenTimer = 30000; + SoulShockTimer = 5000; + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_CONFUSE, true); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by == me) + return; + + if (damage >= me->GetHealth()) + { + damage = 0; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoScriptText(SUFF_SAY_RECAP, me); + } + else + { + int32 bp0 = damage / 2; + me->CastCustomSpell(done_by, AURA_OF_DESIRE_DAMAGE, &bp0, NULL, NULL, true); + } + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)) + for (uint8 i = 0; i < 3; ++i) + if (spell->Effect[i] == SPELL_EFFECT_INTERRUPT_CAST) + if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_SOUL_SHOCK + || me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_DEADEN) + me->InterruptSpell(CURRENT_GENERIC_SPELL, false); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(DESI_SAY_FREED, me); + DoZoneInCombat(); + DoCast(me, AURA_OF_DESIRE, true); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(DESI_SAY_SLAY1,DESI_SAY_SLAY2,DESI_SAY_SLAY3), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (RuneShieldTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_RUNE_SHIELD, true); + SoulShockTimer += 2000; + DeadenTimer += 2000; + RuneShieldTimer = 60000; + } else RuneShieldTimer -= diff; + + if (SoulShockTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOUL_SHOCK); + SoulShockTimer = 5000; + } else SoulShockTimer -= diff; + + if (DeadenTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me->getVictim(), SPELL_DEADEN); + DeadenTimer = 25000 + rand()%10000; + if (!(rand()%2)) + { + DoScriptText(DESI_SAY_SPEC, me); + } + } else DeadenTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_essence_of_angerAI : public ScriptedAI +{ + boss_essence_of_angerAI(Creature *c) : ScriptedAI(c) {} + + uint64 AggroTargetGUID; + + uint32 CheckTankTimer; + uint32 SoulScreamTimer; + uint32 SpiteTimer; + + std::list SpiteTargetGUID; + + bool CheckedAggro; + + void Reset() + { + AggroTargetGUID = 0; + + CheckTankTimer = 5000; + SoulScreamTimer = 10000; + SpiteTimer = 30000; + + SpiteTargetGUID.clear(); + + CheckedAggro = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(ANGER_SAY_FREED,ANGER_SAY_FREED2), me); + + DoZoneInCombat(); + DoCast(me, AURA_OF_ANGER, true); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(ANGER_SAY_DEATH, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(ANGER_SAY_SLAY1,ANGER_SAY_SLAY2), me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!CheckedAggro) + { + AggroTargetGUID = me->getVictim()->GetGUID(); + CheckedAggro = true; + } + + if (CheckTankTimer <= diff) + { + if (me->getVictim()->GetGUID() != AggroTargetGUID) + { + DoScriptText(ANGER_SAY_BEFORE, me); + DoCast(me, SPELL_SELF_SEETHE, true); + AggroTargetGUID = me->getVictim()->GetGUID(); + } + CheckTankTimer = 2000; + } else CheckTankTimer -= diff; + + if (SoulScreamTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOUL_SCREAM); + SoulScreamTimer = 9000 + rand()%2000; + if (!(rand()%3)) + { + DoScriptText(ANGER_SAY_SPEC, me); + } + } else SoulScreamTimer -= diff; + + if (SpiteTimer <= diff) + { + DoCast(me, SPELL_SPITE_TARGET); + SpiteTimer = 30000; + DoScriptText(ANGER_SAY_SPEC, me); + } else SpiteTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +void npc_enslaved_soulAI::JustDied(Unit * /*killer*/) +{ + if (ReliquaryGUID) + if (Creature *Reliquary = (Unit::GetCreature((*me), ReliquaryGUID))) + ++(CAST_AI(boss_reliquary_of_soulsAI, Reliquary->AI())->SoulDeathCount); + + DoCast(me, SPELL_SOUL_RELEASE, true); +} + +CreatureAI* GetAI_boss_reliquary_of_souls(Creature* pCreature) +{ + return new boss_reliquary_of_soulsAI (pCreature); +} + +CreatureAI* GetAI_boss_essence_of_suffering(Creature* pCreature) +{ + return new boss_essence_of_sufferingAI (pCreature); +} + +CreatureAI* GetAI_boss_essence_of_desire(Creature* pCreature) +{ + return new boss_essence_of_desireAI (pCreature); +} + +CreatureAI* GetAI_boss_essence_of_anger(Creature* pCreature) +{ + return new boss_essence_of_angerAI (pCreature); +} + +CreatureAI* GetAI_npc_enslaved_soul(Creature* pCreature) +{ + return new npc_enslaved_soulAI (pCreature); +} + +void AddSC_boss_reliquary_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_reliquary_of_souls"; + newscript->GetAI = &GetAI_boss_reliquary_of_souls; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_essence_of_suffering"; + newscript->GetAI = &GetAI_boss_essence_of_suffering; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_essence_of_desire"; + newscript->GetAI = &GetAI_boss_essence_of_desire; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_essence_of_anger"; + newscript->GetAI = &GetAI_boss_essence_of_anger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_enslaved_soul"; + newscript->GetAI = &GetAI_npc_enslaved_soul; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp new file mode 100644 index 00000000000..94f88d5715c --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -0,0 +1,871 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Shade_of_Akama +SD%Complete: 90 +SDComment: Seems to be complete. +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +#define SAY_DEATH -1564013 +#define SAY_LOW_HEALTH -1564014 +// Ending cinematic text +#define SAY_FREE -1564015 +#define SAY_BROKEN_FREE_01 -1564016 +#define SAY_BROKEN_FREE_02 -1564017 + +#define GOSSIP_ITEM "We are ready to fight alongside you, Akama" + +struct Location +{ + float x, y, o, z; +}; + +static Location ChannelerLocations[]= +{ + {463.161285, 401.219757, 3.141592}, + {457.377625, 391.227661, 2.106461}, + {446.012421, 391.227661, 1.071904}, + {439.533783, 401.219757, 0.000000}, + {446.012421, 411.211853, 5.210546}, + {457.377625, 411.211853, 4.177494} +}; + +static Location SpawnLocations[]= +{ + {498.652740, 461.728119, 0}, + {498.505003, 339.619324, 0} +}; + +static Location AkamaWP[]= +{ + {482.352448, 401.162720, 0, 112.783928}, + {469.597443, 402.264404, 0, 118.537910} +}; + +static Location BrokenCoords[]= +{ + {541.375916, 401.439575, M_PI, 112.783997}, // The place where Akama channels + {534.130005, 352.394531, 2.164150, 112.783737}, // Behind a 'pillar' which is behind the east alcove + {499.621185, 341.534729, 1.652856, 112.783730}, // East Alcove + {499.151093, 461.036438, 4.770888, 112.78370}, // West Alcove +}; + +static Location BrokenWP[]= +{ + {492.491638, 400.744690, 3.122336, 112.783737}, + {494.335724, 382.221771, 2.676230, 112.783737}, + {489.555939, 373.507202, 2.416263, 112.783737}, + {491.136353, 427.868774, 3.519748, 112.783737}, +}; + +// Locations +#define Z1 118.543144 +#define Z2 120.783768 +#define Z_SPAWN 113.537949 +#define AGGRO_X 482.793182 +#define AGGRO_Y 401.270172 +#define AGGRO_Z 112.783928 +#define AKAMA_X 514.583984 +#define AKAMA_Y 400.601013 +#define AKAMA_Z 112.783997 + +// Spells +#define SPELL_VERTEX_SHADE_BLACK 39833 +#define SPELL_SHADE_SOUL_CHANNEL 40401 +#define SPELL_DESTRUCTIVE_POISON 40874 +#define SPELL_LIGHTNING_BOLT 42024 +#define SPELL_AKAMA_SOUL_CHANNEL 40447 +#define SPELL_AKAMA_SOUL_RETRIEVE 40902 +#define AKAMA_SOUL_EXPEL 40855 +#define SPELL_SHADE_SOUL_CHANNEL_2 40520 + +// Channeler entry +#define CREATURE_CHANNELER 23421 +#define CREATURE_SORCERER 23215 +#define CREATURE_DEFENDER 23216 +#define CREATURE_BROKEN 23319 + +const uint32 spawnEntries[4]= { 23523, 23318, 23524 }; + +struct mob_ashtongue_channelerAI : public ScriptedAI +{ + mob_ashtongue_channelerAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;} + + uint64 ShadeGUID; + + void Reset() {} + void JustDied(Unit* /*killer*/); + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +struct mob_ashtongue_sorcererAI : public ScriptedAI +{ + mob_ashtongue_sorcererAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;} + + uint64 ShadeGUID; + uint32 CheckTimer; + bool StartBanishing; + + void Reset() + { + StartBanishing = false; + CheckTimer = 5000; + } + + void JustDied(Unit* /*killer*/); + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (StartBanishing) + return; + + if (CheckTimer <= diff) + { + Creature* Shade = Unit::GetCreature((*me), ShadeGUID); + if (Shade && Shade->isAlive() && me->isAlive()) + { + if (me->IsWithinDist(Shade, 20,false)) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL, true); + DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL_2, true); + + StartBanishing = true; + } + } + CheckTimer = 2000; + } else CheckTimer -= diff; + } +}; + +struct boss_shade_of_akamaAI : public ScriptedAI +{ + boss_shade_of_akamaAI(Creature* c) : ScriptedAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + AkamaGUID = pInstance ? pInstance->GetData64(DATA_AKAMA_SHADE) : 0; + me->setActive(true);//if view distance is too low + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + + ScriptedInstance* pInstance; + + std::list Channelers; + std::list Sorcerers; + uint64 AkamaGUID; + + uint32 SorcererCount; + uint32 DeathCount; + + uint32 ReduceHealthTimer; + uint32 SummonTimer; + uint32 ResetTimer; + uint32 DefenderTimer; // They are on a flat 15 second timer, independant of the other summon Creature timer. + + bool IsBanished; + bool HasKilledAkama; + bool reseting; + bool GridSearcherSucceeded; + bool HasKilledAkamaAndReseting; + SummonList summons; + + void Reset() + { + reseting = true; + HasKilledAkamaAndReseting = false; + + GridSearcherSucceeded = false; + + Sorcerers.clear(); + summons.DespawnAll();//despawn all adds + + if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) + { + Akama->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//turn gossip on so players can restart the event + if (Akama->isDead()) + { + Akama->Respawn();//respawn akama if dead + Akama->AI()->EnterEvadeMode(); + } + } + SorcererCount = 0; + DeathCount = 0; + + SummonTimer = 10000; + ReduceHealthTimer = 0; + ResetTimer = 60000; + DefenderTimer = 15000; + + IsBanished = true; + HasKilledAkama = false; + + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //me->GetMotionMaster()->Clear(); + //me->GetMotionMaster()->MoveIdle(); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); + + if (pInstance) + pInstance->SetData(DATA_SHADEOFAKAMAEVENT, NOT_STARTED); + + reseting = false; + } + void JustDied(Unit* /*killer*/) + { + summons.DespawnAll(); + } + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524) + summons.Summon(summon); + } + void SummonedCreatureDespawn(Creature *summon) + { + if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524) + summons.Despawn(summon); + } + + void MoveInLineOfSight(Unit * /*who*/) + { + if (!GridSearcherSucceeded) + { + FindChannelers(); + + if (!Channelers.empty()) + { + for (std::list::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) + { + Creature* Channeler = (Unit::GetCreature(*me, *itr)); + if (Channeler) + { + if (Channeler->isDead()) + { + Channeler->RemoveCorpse(); + Channeler->Respawn(); + } + + Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true); + Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL_2, true); + Channeler->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + GridSearcherSucceeded = true; + } + } + } else error_log("SD2 ERROR: No Channelers are stored in the list. This encounter will not work properly"); + } + } + + void AttackStart(Unit* who) + { + if (!who || IsBanished) return; + + if (who->isTargetableForAttack() && who != me) + DoStartMovement(who); + } + + void IncrementDeathCount(uint64 guid = 0) // If guid is set, will remove it from list of sorcerer + { + if (reseting) + return; + + debug_log("TSCR: Increasing Death Count for Shade of Akama encounter"); + ++DeathCount; + me->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2); + if (guid) + { + if (Sorcerers.empty()) + error_log("SD2 ERROR: Shade of Akama - attempt to remove guid %u from Sorcerers list but list is already empty", guid); + else Sorcerers.remove(guid); + } + } + + void SummonCreature() + { + uint32 random = rand()%2; + float X = SpawnLocations[random].x; + float Y = SpawnLocations[random].y; + // max of 6 sorcerers can be summoned + if ((rand()%3 == 0) && (DeathCount > 0) && (SorcererCount < 7)) + { + Creature* Sorcerer = me->SummonCreature(CREATURE_SORCERER, X, Y, Z_SPAWN, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + if (Sorcerer) + { + CAST_AI(mob_ashtongue_sorcererAI, Sorcerer->AI())->ShadeGUID = me->GetGUID(); + Sorcerer->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Sorcerer->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + Sorcerer->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + Sorcerers.push_back(Sorcerer->GetGUID()); + --DeathCount; + ++SorcererCount; + } + } + else + { + for (uint8 i = 0; i < 3; ++i) + { + Creature* Spawn = me->SummonCreature(spawnEntries[i], X, Y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); + if (Spawn) + { + Spawn->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Spawn->GetMotionMaster()->MovePoint(0, AGGRO_X, AGGRO_Y, AGGRO_Z); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + Spawn->AI()->AttackStart(pTarget); + } + } + } + } + + void FindChannelers() + { + std::list ChannelerList; + me->GetCreatureListWithEntryInGrid(ChannelerList,CREATURE_CHANNELER,50.0f); + + if (!ChannelerList.empty()) + { + for (std::list::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr) + { + CAST_AI(mob_ashtongue_channelerAI, (*itr)->AI())->ShadeGUID = me->GetGUID(); + Channelers.push_back((*itr)->GetGUID()); + debug_log("TSCR: Shade of Akama Grid Search found channeler %u. Adding to list", (*itr)->GetGUID()); + } + } + else error_log("SD2 ERROR: Grid Search was unable to find any channelers. Shade of Akama encounter will be buggy"); + } + + void SetSelectableChannelers() + { + if (Channelers.empty()) + { + error_log("SD2 ERROR: Channeler List is empty, Shade of Akama encounter will be buggy"); + return; + } + + for (std::list::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) + if (Creature* Channeler = (Unit::GetCreature(*me, *itr))) + Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void SetAkamaGUID(uint64 guid) { AkamaGUID = guid; } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + return; + + if (IsBanished) + { + // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check + if (me->getThreatManager().getThreatList().size() < 2) + { + EnterEvadeMode(); + return; + } + + if (DefenderTimer <= diff) + { + uint32 ran = rand()%2; + Creature* Defender = me->SummonCreature(CREATURE_DEFENDER, SpawnLocations[ran].x, SpawnLocations[ran].y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); + if (Defender) + { + Defender->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + bool move = true; + if (AkamaGUID) + { + if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) + { + float x, y, z; + Akama->GetPosition(x,y,z); + // They move towards AKama + Defender->GetMotionMaster()->MovePoint(0, x, y, z); + Defender->AI()->AttackStart(Akama); + } else move = false; + } else move = false; + if (!move) + Defender->GetMotionMaster()->MovePoint(0, AKAMA_X, AKAMA_Y, AKAMA_Z); + } + DefenderTimer = 15000; + } else DefenderTimer -= diff; + + if (SummonTimer <= diff) + { + SummonCreature(); + SummonTimer = 35000; + } else SummonTimer -= diff; + + if (DeathCount >= 6) + { + if (AkamaGUID) + { + Creature* Akama = Unit::GetCreature((*me), AkamaGUID); + if (Akama && Akama->isAlive()) + { + IsBanished = false; + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveChase(Akama); + Akama->GetMotionMaster()->Clear(); + // Shade should move to Akama, not the other way around + Akama->GetMotionMaster()->MoveIdle(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Crazy amount of threat + me->AddThreat(Akama, 10000000.0f); + Akama->AddThreat(me, 10000000.0f); + me->Attack(Akama, true); + Akama->Attack(me, true); + } + } + } + } + else // No longer banished, let's fight Akama now + { + if (ReduceHealthTimer <= diff) + { + if (AkamaGUID) + { + Creature* Akama = Unit::GetCreature((*me), AkamaGUID); + if (Akama && Akama->isAlive()) + { + //10 % less health every few seconds. + me->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + ReduceHealthTimer = 12000; + } + } + } else ReduceHealthTimer -= diff; + + if (HasKilledAkama) + { + if (!HasKilledAkamaAndReseting)//do not let players kill Shade if Akama is dead and Shade is waiting for ResetTimer!! event would bug + { + HasKilledAkamaAndReseting = true; + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(); + //me->SetHealth(me->GetMaxHealth()); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->MoveTargetedHome(); + } + if (ResetTimer <= diff) + { + EnterEvadeMode();// Reset a little while after killing Akama, evade and respawn Akama + return; + } else ResetTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + } +}; + +void mob_ashtongue_channelerAI::JustDied(Unit* /*killer*/) +{ + Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); + if (Shade && Shade->isAlive()) + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(); + else error_log("SD2 ERROR: Channeler dead but unable to increment DeathCount for Shade of Akama."); +} + +void mob_ashtongue_sorcererAI::JustDied(Unit* /*killer*/) +{ + Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); + if (Shade && Shade->isAlive()) + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(me->GetGUID()); + else error_log("SD2 ERROR: Sorcerer dead but unable to increment DeathCount for Shade of Akama."); +} + +struct npc_akamaAI : public ScriptedAI +{ + npc_akamaAI(Creature* c) : ScriptedAI(c), summons(me) + { + ShadeHasDied = false; + StartCombat = false; + pInstance = c->GetInstanceData(); + ShadeGUID = pInstance ? pInstance->GetData64(DATA_SHADEOFAKAMA) : NOT_STARTED; + me->setActive(true); + EventBegun = false; + CastSoulRetrieveTimer = 0; + SoulRetrieveTimer = 0; + SummonBrokenTimer = 0; + EndingTalkCount = 0; + WayPointId = 0; + BrokenSummonIndex = 0; + BrokenList.clear(); + HasYelledOnce = false; + } + + ScriptedInstance* pInstance; + + uint64 ShadeGUID; + + uint32 DestructivePoisonTimer; + uint32 LightningBoltTimer; + uint32 CheckTimer; + uint32 CastSoulRetrieveTimer; + uint32 SoulRetrieveTimer; + uint32 SummonBrokenTimer; + uint32 EndingTalkCount; + uint32 WayPointId; + uint32 BrokenSummonIndex; + + std::list BrokenList; + + bool EventBegun; + bool ShadeHasDied; + bool StartCombat; + bool HasYelledOnce; + SummonList summons; + + void Reset() + { + DestructivePoisonTimer = 15000; + LightningBoltTimer = 10000; + CheckTimer = 2000; + + if (!EventBegun) + { + me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has very very strange values + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + summons.DespawnAll(); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == CREATURE_BROKEN) + summons.Summon(summon); + } + void SummonedCreatureDespawn(Creature *summon) + { + if (summon->GetEntry() == CREATURE_BROKEN) + summons.Despawn(summon); + } + + void EnterCombat(Unit* /*who*/) {} + + void BeginEvent(Player* pl) + { + if (!pInstance) + return; + + ShadeGUID = pInstance->GetData64(DATA_SHADEOFAKAMA); + if (!ShadeGUID) + return; + + Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); + if (Shade) + { + pInstance->SetData(DATA_SHADEOFAKAMAEVENT, IN_PROGRESS); + // Prevent players from trying to restart event + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->SetAkamaGUID(me->GetGUID()); + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->SetSelectableChannelers(); + Shade->AddThreat(me, 1000000.0f); + me->CombatStart(Shade); + Shade->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + Shade->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (pl) Shade->AddThreat(pl, 1.0f); + DoZoneInCombat(Shade); + EventBegun = true; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + switch(id) + { + case 0: ++WayPointId; break; + + case 1: + if (Creature* Shade = Unit::GetCreature(*me, ShadeGUID)) + { + me->SetUInt64Value(UNIT_FIELD_TARGET, ShadeGUID); + DoCast(Shade, SPELL_AKAMA_SOUL_RETRIEVE); + EndingTalkCount = 0; + SoulRetrieveTimer = 16000; + } + break; + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + EventBegun = false; + ShadeHasDied = false; + StartCombat = false; + CastSoulRetrieveTimer = 0; + SoulRetrieveTimer = 0; + SummonBrokenTimer = 0; + EndingTalkCount = 0; + WayPointId = 0; + BrokenSummonIndex = 0; + BrokenList.clear(); + HasYelledOnce = false; + Creature* Shade = Unit::GetCreature((*me), ShadeGUID); + if (Shade && Shade->isAlive()) + CAST_AI(boss_shade_of_akamaAI, Shade->AI())->HasKilledAkama = true; + summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!EventBegun) + return; + + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 15 && !HasYelledOnce) + { + DoScriptText(SAY_LOW_HEALTH, me); + HasYelledOnce = true; + } + + if (ShadeGUID && !StartCombat) + { + Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); + if (Shade && Shade->isAlive()) + { + if (CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IsBanished) + { + if (CastSoulRetrieveTimer <= diff) + { + DoCast(Shade, SPELL_AKAMA_SOUL_CHANNEL); + CastSoulRetrieveTimer = 500; + } else CastSoulRetrieveTimer -= diff; + } + else + { + me->InterruptNonMeleeSpells(false); + StartCombat = true; + } + } + } + + if (ShadeHasDied && (WayPointId == 1)) + { + if (pInstance) + pInstance->SetData(DATA_SHADEOFAKAMAEVENT, DONE); + me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[1].x, AkamaWP[1].y, AkamaWP[1].z); + ++WayPointId; + } + + if (!ShadeHasDied && StartCombat) + { + if (CheckTimer <= diff) + { + if (ShadeGUID) + { + Creature* Shade = Unit::GetCreature((*me), ShadeGUID); + if (Shade && !Shade->isAlive()) + { + ShadeHasDied = true; + WayPointId = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z); + } + if (Shade && Shade->isAlive()) + { + if (Shade->getThreatManager().getThreatList().size() < 2) + Shade->AI()->EnterEvadeMode(); + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + } + + if (SummonBrokenTimer && BrokenSummonIndex < 4) + { + if (SummonBrokenTimer <= diff) + { + for (uint8 i = 0; i < 4; ++i) + { + float x = BrokenCoords[BrokenSummonIndex].x + (i*5); + float y = BrokenCoords[BrokenSummonIndex].y + (1*5); + float z = BrokenCoords[BrokenSummonIndex].z; + float o = BrokenCoords[BrokenSummonIndex].o; + Creature* Broken = me->SummonCreature(CREATURE_BROKEN, x, y, z, o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000); + if (Broken) + { + float wx = BrokenWP[BrokenSummonIndex].x + (i*5); + float wy = BrokenWP[BrokenSummonIndex].y + (i*5); + float wz = BrokenWP[BrokenSummonIndex].z; + Broken->GetMotionMaster()->MovePoint(0, wx, wy, wz); + Broken->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + BrokenList.push_back(Broken->GetGUID()); + } + } + ++BrokenSummonIndex; + SummonBrokenTimer = 1000; + } else SummonBrokenTimer -= diff; + } + + if (SoulRetrieveTimer) + if (SoulRetrieveTimer <= diff) + { + switch(EndingTalkCount) + { + case 0: + me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + ++EndingTalkCount; + SoulRetrieveTimer = 2000; + SummonBrokenTimer = 1; + break; + case 1: + DoScriptText(SAY_FREE, me); + ++EndingTalkCount; + SoulRetrieveTimer = 25000; + break; + case 2: + if (!BrokenList.empty()) + { + bool Yelled = false; + for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if (Creature* pUnit = Unit::GetCreature(*me, *itr)) + { + if (!Yelled) + { + DoScriptText(SAY_BROKEN_FREE_01, pUnit); + Yelled = true; + } + pUnit->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + } + } + ++EndingTalkCount; + SoulRetrieveTimer = 1500; + break; + case 3: + if (!BrokenList.empty()) + { + for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if (Creature* pUnit = Unit::GetCreature(*me, *itr)) + // This is the incorrect spell, but can't seem to find the right one. + pUnit->CastSpell(pUnit, 39656, true); + } + ++EndingTalkCount; + SoulRetrieveTimer = 5000; + break; + case 4: + if (!BrokenList.empty()) + { + for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) + if (Creature* pUnit = Unit::GetCreature((*me), *itr)) + pUnit->MonsterYell(SAY_BROKEN_FREE_02, LANG_UNIVERSAL, 0); + } + SoulRetrieveTimer = 0; + break; + } + } else SoulRetrieveTimer -= diff; + + if (!UpdateVictim()) + return; + + if (DestructivePoisonTimer <= diff) + { + Creature* Shade = Unit::GetCreature((*me), ShadeGUID); + if (Shade && Shade->isAlive()) + DoCast(Shade, SPELL_DESTRUCTIVE_POISON); + DestructivePoisonTimer = 15000; + } else DestructivePoisonTimer -= diff; + + if (LightningBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); + LightningBoltTimer = 10000; + } else LightningBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shade_of_akama(Creature* pCreature) +{ + return new boss_shade_of_akamaAI (pCreature); +} + +CreatureAI* GetAI_mob_ashtongue_channeler(Creature* pCreature) +{ + return new mob_ashtongue_channelerAI (pCreature); +} + +CreatureAI* GetAI_mob_ashtongue_sorcerer(Creature* pCreature) +{ + return new mob_ashtongue_sorcererAI (pCreature); +} + +CreatureAI* GetAI_npc_akama_shade(Creature* pCreature) +{ + return new npc_akamaAI (pCreature); +} + +bool GossipSelect_npc_akama(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_akamaAI, pCreature->AI())->BeginEvent(pPlayer); + } + + return true; +} + +bool GossipHello_npc_akama(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->isAlive()) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + } + + return true; +} + +void AddSC_boss_shade_of_akama() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shade_of_akama"; + newscript->GetAI = &GetAI_boss_shade_of_akama; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ashtongue_channeler"; + newscript->GetAI = &GetAI_mob_ashtongue_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ashtongue_sorcerer"; + newscript->GetAI = &GetAI_mob_ashtongue_sorcerer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_akama_shade"; + newscript->GetAI = &GetAI_npc_akama_shade; + newscript->pGossipHello = &GossipHello_npc_akama; + newscript->pGossipSelect = &GossipSelect_npc_akama; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp new file mode 100644 index 00000000000..bc1ea3ec673 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp @@ -0,0 +1,296 @@ +/* Copyright (C) 2006 - 2008 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Supremus +SD%Complete: 95 +SDComment: Need to implement molten punch +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +#define EMOTE_NEW_TARGET -1564010 +#define EMOTE_PUNCH_GROUND -1564011 //DoScriptText(EMOTE_PUNCH_GROUND, me); +#define EMOTE_GROUND_CRACK -1564012 + +//Spells +#define SPELL_MOLTEN_PUNCH 40126 +#define SPELL_HATEFUL_STRIKE 41926 +#define SPELL_MOLTEN_FLAME 40980 +#define SPELL_VOLCANIC_ERUPTION 40117 +#define SPELL_VOLCANIC_SUMMON 40276 +#define SPELL_BERSERK 45078 + +#define CREATURE_VOLCANO 23085 +#define CREATURE_STALKER 23095 + +#define PHASE_STRIKE 1 +#define PHASE_CHASE 2 + +#define EVENT_BERSERK 1 +#define EVENT_SWITCH_PHASE 2 +#define EVENT_FLAME 3 +#define EVENT_VOLCANO 4 +#define EVENT_SWITCH_TARGET 5 +#define EVENT_HATEFUL_STRIKE 6 + +#define GCD_CAST 1 + +struct molten_flameAI : public NullCreatureAI +{ + molten_flameAI(Creature *c) : NullCreatureAI(c) {} + + void InitializeAI() + { + float x, y, z; + me->GetNearPoint(me, x, y, z, 1, 100, M_PI*2*rand_norm()); + me->GetMotionMaster()->MovePoint(0, x, y, z); + me->SetVisibility(VISIBILITY_OFF); + me->CastSpell(me,SPELL_MOLTEN_FLAME,true); + } +}; + +struct boss_supremusAI : public ScriptedAI +{ + boss_supremusAI(Creature *c) : ScriptedAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + SummonList summons; + uint32 phase; + + void Reset() + { + if (pInstance) + { + if (me->isAlive()) + { + pInstance->SetData(DATA_SUPREMUSEVENT, NOT_STARTED); + //ToggleDoors(true); + } + //else ToggleDoors(false); + } + + phase = 0; + + events.Reset(); + summons.DespawnAll(); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_SUPREMUSEVENT, IN_PROGRESS); + + ChangePhase(); + events.ScheduleEvent(EVENT_BERSERK, 900000, GCD_CAST); + events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST); + } + + void ChangePhase() + { + if (!phase || phase == PHASE_CHASE) + { + phase = PHASE_STRIKE; + summons.DoAction(EVENT_VOLCANO, 0); + events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); + me->SetSpeed(MOVE_RUN, 1.2f); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); + } + else + { + phase = PHASE_CHASE; + events.ScheduleEvent(EVENT_VOLCANO, 5000, GCD_CAST, PHASE_CHASE); + events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); + me->SetSpeed(MOVE_RUN, 0.9f); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + DoResetThreat(); + DoZoneInCombat(); + events.SetPhase(phase); + events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000, GCD_CAST); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_SUPREMUSEVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GAMEOBJECT_SUPREMUS_DOORS), true); + } + summons.DespawnAll(); + } + + void JustSummoned(Creature *summon) {summons.Summon(summon);} + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + + Unit* CalculateHatefulStrikeTarget() + { + uint32 health = 0; + Unit *pTarget = NULL; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + std::list::const_iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && me->IsWithinMeleeRange(pUnit)) + { + if (pUnit->GetHealth() > health) + { + health = pUnit->GetHealth(); + pTarget = pUnit; + } + } + } + + return pTarget; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BERSERK: + DoCast(me, SPELL_BERSERK, true); + break; + case EVENT_FLAME: + DoCast(me, SPELL_MOLTEN_PUNCH); + events.DelayEvents(1500, GCD_CAST); + events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST); + break; + case EVENT_HATEFUL_STRIKE: + if (Unit *pTarget = CalculateHatefulStrikeTarget()) + DoCast(pTarget, SPELL_HATEFUL_STRIKE); + events.DelayEvents(1000, GCD_CAST); + events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); + break; + case EVENT_SWITCH_TARGET: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + { + DoResetThreat(); + me->AddThreat(pTarget, 5000000.0f); + DoScriptText(EMOTE_NEW_TARGET, me); + } + events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); + break; + case EVENT_VOLCANO: + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true); + if (!pTarget) pTarget = me->getVictim(); + if (pTarget) + { + //DoCast(pTarget, SPELL_VOLCANIC_SUMMON);//movement bugged + me->SummonCreature(CREATURE_VOLCANO,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); + DoScriptText(EMOTE_GROUND_CRACK, me); + events.DelayEvents(1500, GCD_CAST); + } + events.ScheduleEvent(EVENT_VOLCANO, 10000, GCD_CAST, PHASE_CHASE); + return; + } + case EVENT_SWITCH_PHASE: + ChangePhase(); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_volcanoAI : public Scripted_NoMovementAI +{ + npc_volcanoAI(Creature *c) : Scripted_NoMovementAI(c) {} + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //DoCast(me, SPELL_VOLCANIC_ERUPTION); + me->SetReactState(REACT_PASSIVE); + wait = 3000; + } + uint32 wait; + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void DoAction(const uint32 /*info*/) + { + me->RemoveAura(SPELL_VOLCANIC_ERUPTION); + } + + void UpdateAI(const uint32 diff) + { + if (wait <= diff)//wait 3secs before casting + { + DoCast(me, SPELL_VOLCANIC_ERUPTION); + wait = 60000; + } + else wait -= diff; + } + +}; + +CreatureAI* GetAI_boss_supremus(Creature* pCreature) +{ + return new boss_supremusAI (pCreature); +} + +CreatureAI* GetAI_molten_flame(Creature* pCreature) +{ + return new molten_flameAI (pCreature); +} + +CreatureAI* GetAI_npc_volcano(Creature* pCreature) +{ + return new npc_volcanoAI (pCreature); +} + +void AddSC_boss_supremus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_supremus"; + newscript->GetAI = &GetAI_boss_supremus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "molten_flame"; + newscript->GetAI = &GetAI_molten_flame; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_volcano"; + newscript->GetAI = &GetAI_npc_volcano; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp new file mode 100644 index 00000000000..670edc4d869 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp @@ -0,0 +1,508 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Teron_Gorefiend +SD%Complete: 60 +SDComment: Requires Mind Control support for Ghosts. +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + + //Speech'n'sound +#define SAY_INTRO -1564037 +#define SAY_AGGRO -1564038 +#define SAY_SLAY1 -1564039 +#define SAY_SLAY2 -1564040 +#define SAY_SPELL1 -1564041 +#define SAY_SPELL2 -1564042 +#define SAY_SPECIAL1 -1564043 +#define SAY_SPECIAL2 -1564044 +#define SAY_ENRAGE -1564045 +#define SAY_DEATH -1564046 + +//Spells +#define SPELL_INCINERATE 40239 +#define SPELL_CRUSHING_SHADOWS 40243 +#define SPELL_SHADOWBOLT 40185 +#define SPELL_PASSIVE_SHADOWFORM 40326 +#define SPELL_SHADOW_OF_DEATH 40251 +#define SPELL_BERSERK 45078 + +#define SPELL_ATROPHY 40327 // Shadowy Constructs use this when they get within melee range of a player + +#define CREATURE_DOOM_BLOSSOM 23123 +#define CREATURE_SHADOWY_CONSTRUCT 23111 + +struct mob_doom_blossomAI : public ScriptedAI +{ + mob_doom_blossomAI(Creature *c) : ScriptedAI(c) {} + + uint32 CheckTeronTimer; + uint32 ShadowBoltTimer; + uint64 TeronGUID; + + void Reset() + { + CheckTeronTimer = 5000; + ShadowBoltTimer = 12000; + TeronGUID = 0; + } + + void EnterCombat(Unit * /*who*/) { } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void Despawn() + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + } + + void UpdateAI(const uint32 diff) + { + if (CheckTeronTimer <= diff) + { + if (TeronGUID) + { + DoZoneInCombat(); + + Creature* Teron = (Unit::GetCreature((*me), TeronGUID)); + if ((Teron) && (!Teron->isAlive() || Teron->IsInEvadeMode())) + Despawn(); + } + else + Despawn(); + + CheckTeronTimer = 5000; + } else CheckTeronTimer -= diff; + + if (ShadowBoltTimer < diff && me->isInCombat()) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOWBOLT); + ShadowBoltTimer = 10000; + } else ShadowBoltTimer -= diff; + return; + } + + void SetTeronGUID(uint64 guid){ TeronGUID = guid; } +}; + +struct mob_shadowy_constructAI : public ScriptedAI +{ + mob_shadowy_constructAI(Creature* c) : ScriptedAI(c) {} + + uint64 GhostGUID; + uint64 TeronGUID; + + uint32 CheckPlayerTimer; + uint32 CheckTeronTimer; + + void Reset() + { + GhostGUID = 0; + TeronGUID = 0; + + CheckPlayerTimer = 2000; + CheckTeronTimer = 5000; + } + + void EnterCombat(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (!who || (!who->isAlive()) || (who->GetGUID() == GhostGUID)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + +/* Comment it out for now. NOTE TO FUTURE DEV: UNCOMMENT THIS OUT ONLY AFTER MIND CONTROL IS IMPLEMENTED + void DamageTaken(Unit* done_by, uint32 &damage) + { + if (done_by->GetGUID() != GhostGUID) + damage = 0; // Only the ghost can deal damage. + } + */ + + void CheckPlayers() + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + if (m_threatlist.empty()) + return; // No threat list. Don't continue. + std::list::const_iterator itr = m_threatlist.begin(); + std::list targets; + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + targets.push_back(pUnit); + } + targets.sort(Trinity::ObjectDistanceOrderPred(me)); + Unit *pTarget = targets.front(); + if (pTarget && me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) + { + DoCast(pTarget, SPELL_ATROPHY); + me->AI()->AttackStart(pTarget); + } + } + + void UpdateAI(const uint32 diff) + { + if (CheckPlayerTimer <= diff) + { + CheckPlayers(); + CheckPlayerTimer = 3000; + } else CheckPlayerTimer -= diff; + + if (CheckTeronTimer <= diff) + { + Creature* Teron = (Unit::GetCreature((*me), TeronGUID)); + if (!Teron || !Teron->isAlive() || Teron->IsInEvadeMode()) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + CheckTeronTimer = 5000; + } else CheckTeronTimer -= diff; + } +}; + +struct boss_teron_gorefiendAI : public ScriptedAI +{ + boss_teron_gorefiendAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 IncinerateTimer; + uint32 SummonDoomBlossomTimer; + uint32 EnrageTimer; + uint32 CrushingShadowsTimer; + uint32 ShadowOfDeathTimer; + uint32 SummonShadowsTimer; + uint32 RandomYellTimer; + uint32 AggroTimer; + + uint64 AggroTargetGUID; + uint64 GhostGUID; // Player that gets killed by Shadow of Death and gets turned into a ghost + + bool Intro; + bool Done; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, NOT_STARTED); + + IncinerateTimer = 20000 + rand()%11000; + SummonDoomBlossomTimer = 12000; + EnrageTimer = 600000; + CrushingShadowsTimer = 22000; + SummonShadowsTimer = 60000; + RandomYellTimer = 50000; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // Start off unattackable so that the intro is done properly + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + AggroTimer = 20000; + AggroTargetGUID = 0; + Intro = false; + Done = false; + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit* pWho) + { + if (!Intro && pWho->GetTypeId() == TYPEID_PLAYER && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && pWho->isInAccessiblePlaceFor(me)) + { + if (me->IsWithinDistInMap(pWho, VISIBLE_RANGE) && me->IsWithinLOSInMap(pWho)) + { + if (pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, IN_PROGRESS); + + me->GetMotionMaster()->Clear(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoScriptText(SAY_INTRO, me); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + AggroTargetGUID = pWho->GetGUID(); + Intro = true; + } + } + if (Done) + ScriptedAI::MoveInLineOfSight(pWho); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_TERONGOREFIENDEVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + float CalculateRandomLocation(float Loc, uint32 radius) + { + float coord = Loc; + switch (urand(0,1)) + { + case 0: + coord += rand()%radius; + break; + case 1: + coord -= rand()%radius; + break; + } + return coord; + } + + void SetThreatList(Creature* Blossom) + { + if (!Blossom) return; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + std::list::const_iterator i = m_threatlist.begin(); + for (i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + { + float threat = DoGetThreat(pUnit); + Blossom->AddThreat(pUnit, threat); + } + } + } + + void MindControlGhost() + { + /************************************************************************/ + /** NOTE FOR FUTURE DEVELOPER: PROPERLY IMPLEMENT THE GHOST PORTION *****/ + /** ONLY AFTER TrinIty FULLY IMPLEMENTS MIND CONTROL ABILITIES *****/ + /** THE CURRENT CODE IN THIS FUNCTION IS ONLY THE BEGINNING OF *****/ + /** WHAT IS FULLY NECESSARY FOR GOREFIEND TO BE 100% COMPLETE *****/ + /************************************************************************/ + + Unit* Ghost = NULL; + if (GhostGUID) + Ghost = Unit::GetUnit((*me), GhostGUID); + if (Ghost && Ghost->isAlive() && Ghost->HasAura(SPELL_SHADOW_OF_DEATH)) + { + /*float x,y,z; + Ghost->GetPosition(x,y,z); + Creature* control = me->SummonCreature(CREATURE_GHOST, x, y, z, 0, TEMPSUMMON_TIMED_DESAWN, 30000); + if (control) + { + CAST_PLR(Ghost)->Possess(control); + Ghost->DealDamage(Ghost, Ghost->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, + false); + }*/ + for (uint8 i = 0; i < 4; ++i) + { + Creature* Construct = NULL; + float X = CalculateRandomLocation(Ghost->GetPositionX(), 10); + float Y = CalculateRandomLocation(Ghost->GetPositionY(), 10); + Construct = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, Y, Ghost->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); + if (Construct) + { + Construct->CastSpell(Construct, SPELL_PASSIVE_SHADOWFORM, true); + SetThreatList(Construct); // Use same function as Doom Blossom to set Threat List. + CAST_AI(mob_shadowy_constructAI, Construct->AI())->GhostGUID = GhostGUID; + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) // someone's trying to solo. + pTarget = me->getVictim(); + + if (pTarget) + Construct->GetMotionMaster()->MoveChase(pTarget); + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Intro && !Done) + { + if (AggroTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoScriptText(SAY_AGGRO, me); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + Done = true; + if (AggroTargetGUID) + { + Unit* pUnit = Unit::GetUnit((*me), AggroTargetGUID); + if (pUnit) + AttackStart(pUnit); + + DoZoneInCombat(); + } + else + { + EnterEvadeMode(); + return; + } + } else AggroTimer -= diff; + } + + if (!UpdateVictim() || !Done) + return; + + if (SummonShadowsTimer <= diff) + { + //MindControlGhost(); + + for (uint8 i = 0; i < 2; ++i) + { + Creature* Shadow = NULL; + float X = CalculateRandomLocation(me->GetPositionX(), 10); + Shadow = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 0); + if (Shadow) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget) + Shadow->AI()->AttackStart(pTarget); + } + } + SummonShadowsTimer = 60000; + } else SummonShadowsTimer -= diff; + + if (SummonDoomBlossomTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float X = CalculateRandomLocation(pTarget->GetPositionX(), 20); + float Y = CalculateRandomLocation(pTarget->GetPositionY(), 20); + float Z = pTarget->GetPositionZ(); + Z = me->GetMap()->GetHeight(X, Y, Z); + Creature* DoomBlossom = me->SummonCreature(CREATURE_DOOM_BLOSSOM, X, Y, Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + if (DoomBlossom) + { + DoomBlossom->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoomBlossom->setFaction(me->getFaction()); + DoomBlossom->AddThreat(pTarget, 1.0f); + CAST_AI(mob_doom_blossomAI, DoomBlossom->AI())->SetTeronGUID(me->GetGUID()); + pTarget->CombatStart(DoomBlossom); + SetThreatList(DoomBlossom); + SummonDoomBlossomTimer = 35000; + } + } + } else SummonDoomBlossomTimer -= diff; + + if (IncinerateTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget) + { + DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); + DoCast(pTarget, SPELL_INCINERATE); + IncinerateTimer = 20000 + rand()%31 * 1000; + } + } else IncinerateTimer -= diff; + + if (CrushingShadowsTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, SPELL_CRUSHING_SHADOWS); + CrushingShadowsTimer = 10000 + rand()%16 * 1000; + } else CrushingShadowsTimer -= diff; + + /*** NOTE FOR FUTURE DEV: UNCOMMENT BELOW ONLY IF MIND CONTROL IS FULLY IMPLEMENTED **/ + /*if (ShadowOfDeathTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SPELL_SHADOW_OF_DEATH); + GhostGUID = pTarget->GetGUID(); + ShadowOfDeathTimer = 30000; + SummonShadowsTimer = 53000; // Make it VERY close but slightly less so that we can check if the aura is still on the player + } + } else ShadowOfDeathTimer -= diff;*/ + + if (RandomYellTimer <= diff) + { + DoScriptText(RAND(SAY_SPELL1,SAY_SPELL2), me); + RandomYellTimer = 50000 + rand()%51 * 1000; + } else RandomYellTimer -= diff; + + if (!me->HasAura(SPELL_BERSERK)) + { + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + DoScriptText(SAY_ENRAGE, me); + } else EnrageTimer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_doom_blossom(Creature* pCreature) +{ + return new mob_doom_blossomAI(pCreature); +} + +CreatureAI* GetAI_mob_shadowy_construct(Creature* pCreature) +{ + return new mob_shadowy_constructAI(pCreature); +} + +CreatureAI* GetAI_boss_teron_gorefiend(Creature* pCreature) +{ + return new boss_teron_gorefiendAI (pCreature); +} + +void AddSC_boss_teron_gorefiend() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_doom_blossom"; + newscript->GetAI = &GetAI_mob_doom_blossom; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadowy_construct"; + newscript->GetAI = &GetAI_mob_shadowy_construct; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_teron_gorefiend"; + newscript->GetAI = &GetAI_boss_teron_gorefiend; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp new file mode 100644 index 00000000000..7d94b4b36a0 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp @@ -0,0 +1,226 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warlord_Najentus +SD%Complete: 95 +SDComment: +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +enum eEnums +{ + SAY_AGGRO = -1564000, + SAY_NEEDLE1 = -1564001, + SAY_NEEDLE2 = -1564002, + SAY_SLAY1 = -1564003, + SAY_SLAY2 = -1564004, + SAY_SPECIAL1 = -1564005, + SAY_SPECIAL2 = -1564006, + SAY_ENRAGE1 = -1564007, //is this text actually in use? + SAY_ENRAGE2 = -1564008, + SAY_DEATH = -1564009, + + //Spells + SPELL_NEEDLE_SPINE = 39992, + SPELL_TIDAL_BURST = 39878, + SPELL_TIDAL_SHIELD = 39872, + SPELL_IMPALING_SPINE = 39837, + SPELL_CREATE_NAJENTUS_SPINE = 39956, + SPELL_HURL_SPINE = 39948, + SPELL_BERSERK = 26662, + + GOBJECT_SPINE = 185584, + + EVENT_BERSERK = 1, + EVENT_YELL = 2, + EVENT_NEEDLE = 3, + EVENT_SPINE = 4, + EVENT_SHIELD = 5, + + GCD_CAST = 1, + GCD_YELL = 2 +}; + +struct boss_najentusAI : public ScriptedAI +{ + boss_najentusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + uint64 SpineTargetGUID; + + void Reset() + { + events.Reset(); + + SpineTargetGUID = 0; + + if (pInstance) + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(rand()%2 ? SAY_SLAY1 : SAY_SLAY2, me); + events.DelayEvents(5000, GCD_YELL); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + if (spell->Id == SPELL_HURL_SPINE && me->HasAura(SPELL_TIDAL_SHIELD)) + { + me->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD); + DoCast(me, SPELL_TIDAL_BURST, true); + ResetTimer(); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + events.ScheduleEvent(EVENT_BERSERK, 480000, GCD_CAST); + events.ScheduleEvent(EVENT_YELL, 45000 + (rand()%76)*1000, GCD_YELL); + ResetTimer(); + } + + bool RemoveImpalingSpine() + { + if (!SpineTargetGUID) return false; + Unit *pTarget = Unit::GetUnit(*me, SpineTargetGUID); + if (pTarget && pTarget->HasAura(SPELL_IMPALING_SPINE)) + pTarget->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE); + SpineTargetGUID=0; + return true; + } + + void ResetTimer(uint32 inc = 0) + { + events.RescheduleEvent(EVENT_NEEDLE, 10000 + inc, GCD_CAST); + events.RescheduleEvent(EVENT_SPINE, 20000 + inc, GCD_CAST); + events.RescheduleEvent(EVENT_SHIELD, 60000 + inc); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHIELD: + DoCast(me, SPELL_TIDAL_SHIELD, true); + ResetTimer(45000); + break; + case EVENT_BERSERK: + DoScriptText(SAY_ENRAGE2, me); + DoCast(me, SPELL_BERSERK, true); + events.DelayEvents(15000, GCD_YELL); + break; + case EVENT_SPINE: + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!pTarget) pTarget = me->getVictim(); + if (pTarget) + { + DoCast(pTarget, SPELL_IMPALING_SPINE, true); + SpineTargetGUID = pTarget->GetGUID(); + //must let target summon, otherwise you cannot click the spine + pTarget->SummonGameObject(GOBJECT_SPINE, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 30); + DoScriptText(rand()%2 ? SAY_NEEDLE1 : SAY_NEEDLE2, me); + events.DelayEvents(1500, GCD_CAST); + events.DelayEvents(15000, GCD_YELL); + } + events.ScheduleEvent(EVENT_SPINE, 21000, GCD_CAST); + return; + } + case EVENT_NEEDLE: + { + //DoCast(me, SPELL_NEEDLE_SPINE, true); + std::list pTargets; + SelectTargetList(pTargets, 3, SELECT_TARGET_RANDOM, 80, true); + for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) + DoCast(*i, 39835, true); + events.ScheduleEvent(EVENT_NEEDLE, urand(15000,25000), GCD_CAST); + events.DelayEvents(1500, GCD_CAST); + return; + } + case EVENT_YELL: + DoScriptText(RAND(SAY_SPECIAL1, SAY_SPECIAL2), me); + events.ScheduleEvent(EVENT_YELL, urand(25000,100000), GCD_YELL); + events.DelayEvents(15000, GCD_YELL); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +bool GOHello_go_najentus_spine(Player* pPlayer, GameObject* pGo) +{ + if (ScriptedInstance* pInstance = pGo->GetInstanceData()) + if (Creature* Najentus = Unit::GetCreature(*pGo, pInstance->GetData64(DATA_HIGHWARLORDNAJENTUS))) + if (CAST_AI(boss_najentusAI, Najentus->AI())->RemoveImpalingSpine()) + { + pPlayer->CastSpell(pPlayer, SPELL_CREATE_NAJENTUS_SPINE, true); + pGo->Delete(); + } + return true; +} + +CreatureAI* GetAI_boss_najentus(Creature* pCreature) +{ + return new boss_najentusAI (pCreature); +} + +void AddSC_boss_najentus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_najentus"; + newscript->GetAI = &GetAI_boss_najentus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_najentus_spine"; + newscript->pGOHello = &GOHello_go_najentus_spine; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp new file mode 100644 index 00000000000..82cc2876b5a --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp @@ -0,0 +1,874 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Illidari_Council +SD%Complete: 95 +SDComment: Circle of Healing not working properly. +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +//Speech'n'Sounds +#define SAY_GATH_SLAY -1564085 +#define SAY_GATH_SLAY_COMNT -1564089 +#define SAY_GATH_DEATH -1564093 +#define SAY_GATH_SPECIAL1 -1564077 +#define SAY_GATH_SPECIAL2 -1564081 + +#define SAY_VERA_SLAY -1564086 +#define SAY_VERA_COMNT -1564089 //signed for 22949 +#define SAY_VERA_DEATH -1564094 +#define SAY_VERA_SPECIAL1 -1564078 +#define SAY_VERA_SPECIAL2 -1564082 + +#define SAY_MALA_SLAY -1564087 +#define SAY_MALA_COMNT -1564090 +#define SAY_MALA_DEATH -1564095 +#define SAY_MALA_SPECIAL1 -1564079 +#define SAY_MALA_SPECIAL2 -1564083 + +#define SAY_ZERE_SLAY -1564088 +#define SAY_ZERE_COMNT -1564091 +#define SAY_ZERE_DEATH -1564096 +#define SAY_ZERE_SPECIAL1 -1564080 +#define SAY_ZERE_SPECIAL2 -1564084 + +#define ERROR_INST_DATA "SD2 ERROR: Instance Data for Black Temple not set properly; Illidari Council event will not function properly." + +#define AKAMAID 23089 + +struct CouncilYells +{ + int32 entry; + uint32 timer; +}; + +static CouncilYells CouncilAggro[]= +{ + {-1564069, 5000}, // Gathios + {-1564070, 5500}, // Veras + {-1564071, 5000}, // Malande + {-1564072, 0}, // Zerevor +}; + +// Need to get proper timers for this later +static CouncilYells CouncilEnrage[]= +{ + {-1564073, 2000}, // Gathios + {-1564074, 6000}, // Veras + {-1564075, 5000}, // Malande + {-1564076, 0}, // Zerevor +}; + +// High Nethermancer Zerevor's spells +#define SPELL_FLAMESTRIKE 41481 +#define SPELL_BLIZZARD 41482 +#define SPELL_ARCANE_BOLT 41483 +#define SPELL_ARCANE_EXPLOSION 41524 +#define SPELL_DAMPEN_MAGIC 41478 + +// Lady Malande's spells +#define SPELL_EMPOWERED_SMITE 41471 +#define SPELL_CIRCLE_OF_HEALING 41455 +#define SPELL_REFLECTIVE_SHIELD 41475 +#define SPELL_DIVINE_WRATH 41472 +#define SPELL_HEAL_VISUAL 24171 + +// Gathios the Shatterer's spells +#define SPELL_BLESS_PROTECTION 41450 +#define SPELL_BLESS_SPELLWARD 41451 +#define SPELL_CONSECRATION 41541 +#define SPELL_HAMMER_OF_JUSTICE 41468 +#define SPELL_SEAL_OF_COMMAND 41469 +#define SPELL_SEAL_OF_BLOOD 41459 +#define SPELL_CHROMATIC_AURA 41453 +#define SPELL_DEVOTION_AURA 41452 + +// Veras Darkshadow's spells +#define SPELL_DEADLY_POISON 41485 +#define SPELL_ENVENOM 41487 +#define SPELL_VANISH 41479 + +#define SPELL_BERSERK 45078 + +struct mob_blood_elf_council_voice_triggerAI : public ScriptedAI +{ + mob_blood_elf_council_voice_triggerAI(Creature* c) : ScriptedAI(c) + { + for (uint8 i = 0; i < 4; ++i) + Council[i] = 0; + } + + uint64 Council[4]; + + uint32 EnrageTimer; + uint32 AggroYellTimer; + + uint8 YellCounter; // Serves as the counter for both the aggro and enrage yells + + bool EventStarted; + + void Reset() + { + EnrageTimer = 900000; // 15 minutes + AggroYellTimer = 500; + + YellCounter = 0; + + EventStarted = false; + } + + // finds and stores the GUIDs for each Council member using instance data system. + void LoadCouncilGUIDs() + { + if (ScriptedInstance* pInstance = me->GetInstanceData()) + { + Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[1] = pInstance->GetData64(DATA_VERASDARKSHADOW); + Council[2] = pInstance->GetData64(DATA_LADYMALANDE); + Council[3] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + } else error_log(ERROR_INST_DATA); + } + + void EnterCombat(Unit* /*who*/) {} + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!EventStarted) + return; + + if (YellCounter > 3) + return; + + if (AggroYellTimer) + { + if (AggroYellTimer <= diff) + { + if (Unit* pMember = Unit::GetUnit(*me, Council[YellCounter])) + { + DoScriptText(CouncilAggro[YellCounter].entry, pMember); + AggroYellTimer = CouncilAggro[YellCounter].timer; + } + ++YellCounter; + if (YellCounter > 3) + YellCounter = 0; // Reuse for Enrage Yells + } else AggroYellTimer -= diff; + } + + if (EnrageTimer) + { + if (EnrageTimer <= diff) + { + if (Unit* pMember = Unit::GetUnit(*me, Council[YellCounter])) + { + pMember->CastSpell(pMember, SPELL_BERSERK, true); + DoScriptText(CouncilEnrage[YellCounter].entry, pMember); + EnrageTimer = CouncilEnrage[YellCounter].timer; + } + ++YellCounter; + } else EnrageTimer -= diff; + } + } +}; + +struct mob_illidari_councilAI : public ScriptedAI +{ + mob_illidari_councilAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i = 0; i < 4; ++i) + Council[i] = 0; + } + + ScriptedInstance* pInstance; + + uint64 Council[4]; + + uint32 CheckTimer; + uint32 EndEventTimer; + + uint8 DeathCount; + + bool EventBegun; + + void Reset() + { + CheckTimer = 2000; + EndEventTimer = 0; + + DeathCount = 0; + + Creature* pMember = NULL; + for (uint8 i = 0; i < 4; ++i) + { + pMember = Unit::GetCreature((*me), Council[i]); + if (!pMember) + continue; + + if (!pMember->isAlive()) + { + pMember->RemoveCorpse(); + pMember->Respawn(); + } + pMember->AI()->EnterEvadeMode(); + } + + if (pInstance) + { + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, NOT_STARTED); + if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + VoiceTrigger->AI()->EnterEvadeMode(); + } + + EventBegun = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(11686); + } + + void EnterCombat(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void StartEvent(Unit *pTarget) + { + if (!pInstance) + return; + + if (pTarget && pTarget->isAlive()) + { + Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + Council[2] = pInstance->GetData64(DATA_LADYMALANDE); + Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); + + // Start the event for the Voice Trigger + if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + { + CAST_AI(mob_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->LoadCouncilGUIDs(); + CAST_AI(mob_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->EventStarted = true; + } + + for (uint8 i = 0; i < 4; ++i) + { + Unit* Member = NULL; + if (Council[i]) + { + Member = Unit::GetUnit((*me), Council[i]); + if (Member && Member->isAlive()) + CAST_CRE(Member)->AI()->AttackStart(pTarget); + } + } + + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, IN_PROGRESS); + + EventBegun = true; + } + } + + void UpdateAI(const uint32 diff) + { + if (!EventBegun) return; + + if (EndEventTimer) + { + if (EndEventTimer <= diff) + { + if (DeathCount > 3) + { + if (pInstance) + { + if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, DONE); + //me->SummonCreature(AKAMAID,746.466980f,304.394989f,311.90208f,6.272870f,TEMPSUMMON_DEAD_DESPAWN,0); + } + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + + Creature* pMember = (Unit::GetCreature(*me, Council[DeathCount])); + if (pMember && pMember->isAlive()) + pMember->DealDamage(pMember, pMember->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + ++DeathCount; + EndEventTimer = 1500; + } else EndEventTimer -= diff; + } + + if (CheckTimer) + { + if (CheckTimer <= diff) + { + uint8 EvadeCheck = 0; + for (uint8 i = 0; i < 4; ++i) + { + if (Council[i]) + { + if (Creature* Member = (Unit::GetCreature((*me), Council[i]))) + { + // This is the evade/death check. + if (Member->isAlive() && !Member->getVictim()) + ++EvadeCheck; //If all members evade, we reset so that players can properly reset the event + else if (!Member->isAlive()) // If even one member dies, kill the rest, set instance data, and kill self. + { + EndEventTimer = 1000; + CheckTimer = 0; + return; + } + } + } + } + + if (EvadeCheck > 3) + Reset(); + + CheckTimer = 2000; + } else CheckTimer -= diff; + } + + } +}; + +struct boss_illidari_councilAI : public ScriptedAI +{ + boss_illidari_councilAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i = 0; i < 4; ++i) + Council[i] = 0; + LoadedGUIDs = false; + } + + uint64 Council[4]; + + ScriptedInstance* pInstance; + + bool LoadedGUIDs; + + void EnterCombat(Unit* who) + { + if (pInstance) + { + Creature* Controller = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ILLIDARICOUNCIL))); + if (Controller) + CAST_AI(mob_illidari_councilAI, Controller->AI())->StartEvent(who); + } + else + { + error_log(ERROR_INST_DATA); + EnterEvadeMode(); + return; + } + DoZoneInCombat(); + // Load GUIDs on first aggro because the Creature guids are only set as the creatures are created in world- + // this means that for each pCreature, it will attempt to LoadGUIDs even though some of the other creatures are + // not in world, and thus have no GUID set in the instance data system. Putting it in aggro ensures that all the creatures + // have been loaded and have their GUIDs set in the instance data system. + if (!LoadedGUIDs) + LoadGUIDs(); + } + + void EnterEvadeMode() + { + for (uint8 i = 0; i < 4; ++i) + { + if (Unit* pUnit = Unit::GetUnit(*me, Council[i])) + if (pUnit != me && pUnit->getVictim()) + { + AttackStart(pUnit->getVictim()); + return; + } + } + ScriptedAI::EnterEvadeMode(); + } + + void DamageTaken(Unit* done_by, uint32 &damage) + { + if (done_by == me) + return; + + damage /= 4; + for (uint8 i = 0; i < 4; ++i) + { + if (Creature* pUnit = Unit::GetCreature(*me, Council[i])) + if (pUnit != me && damage < pUnit->GetHealth()) + { + pUnit->SetHealth(pUnit->GetHealth() - damage); + pUnit->LowerPlayerDamageReq(damage); + } + } + } + + void LoadGUIDs() + { + if (!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + + Council[0] = pInstance->GetData64(DATA_LADYMALANDE); + Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + Council[2] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); + Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); + + LoadedGUIDs = true; + } +}; + +struct boss_gathios_the_shattererAI : public boss_illidari_councilAI +{ + boss_gathios_the_shattererAI(Creature *c) : boss_illidari_councilAI(c) {} + + uint32 ConsecrationTimer; + uint32 HammerOfJusticeTimer; + uint32 SealTimer; + uint32 AuraTimer; + uint32 BlessingTimer; + + void Reset() + { + ConsecrationTimer = 40000; + HammerOfJusticeTimer = 10000; + SealTimer = 40000; + AuraTimer = 90000; + BlessingTimer = 60000; + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_GATH_SLAY, me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_GATH_DEATH, me); + } + + Unit* SelectCouncilMember() + { + Unit* pUnit = me; + uint32 member = 0; // He chooses Lady Malande most often + + if (rand()%10 == 0) // But there is a chance he picks someone else. + member = urand(1, 3); + + if (member != 2) // No need to create another pointer to us using Unit::GetUnit + pUnit = Unit::GetUnit((*me), Council[member]); + return pUnit; + } + + void CastAuraOnCouncil() + { + uint32 spellid = 0; + switch (urand(0,1)) + { + case 0: spellid = SPELL_DEVOTION_AURA; break; + case 1: spellid = SPELL_CHROMATIC_AURA; break; + } + for (uint8 i = 0; i < 4; ++i) + { + Unit* pUnit = Unit::GetUnit((*me), Council[i]); + if (pUnit) + pUnit->CastSpell(pUnit, spellid, true, 0, 0, me->GetGUID()); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (BlessingTimer <= diff) + { + if (Unit* pUnit = SelectCouncilMember()) + { + switch (urand(0,1)) + { + case 0: DoCast(pUnit, SPELL_BLESS_SPELLWARD); break; + case 1: DoCast(pUnit, SPELL_BLESS_PROTECTION); break; + } + } + BlessingTimer = 60000; + } else BlessingTimer -= diff; + + if (ConsecrationTimer <= diff) + { + DoCast(me, SPELL_CONSECRATION); + ConsecrationTimer = 40000; + } else ConsecrationTimer -= diff; + + if (HammerOfJusticeTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + // is in ~10-40 yd range + if (me->IsInRange(pTarget, 10.0f, 40.0f, false)) + { + DoCast(pTarget, SPELL_HAMMER_OF_JUSTICE); + HammerOfJusticeTimer = 20000; + } + } + } else HammerOfJusticeTimer -= diff; + + if (SealTimer <= diff) + { + switch (urand(0,1)) + { + case 0: DoCast(me, SPELL_SEAL_OF_COMMAND); break; + case 1: DoCast(me, SPELL_SEAL_OF_BLOOD); break; + } + SealTimer = 40000; + } else SealTimer -= diff; + + if (AuraTimer <= diff) + { + CastAuraOnCouncil(); + AuraTimer = 90000; + } else AuraTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_high_nethermancer_zerevorAI : public boss_illidari_councilAI +{ + boss_high_nethermancer_zerevorAI(Creature *c) : boss_illidari_councilAI(c) {} + + uint32 BlizzardTimer; + uint32 FlamestrikeTimer; + uint32 ArcaneBoltTimer; + uint32 DampenMagicTimer; + uint32 Cooldown; + uint32 ArcaneExplosionTimer; + + void Reset() + { + BlizzardTimer = 30000 + rand()%61 * 1000; + FlamestrikeTimer = 30000 + rand()%61 * 1000; + ArcaneBoltTimer = 10000; + DampenMagicTimer = 2000; + ArcaneExplosionTimer = 14000; + Cooldown = 0; + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_ZERE_SLAY, me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_ZERE_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Cooldown) + { + if (Cooldown <= diff) Cooldown = 0; + else + { + Cooldown -= diff; + return; // Don't cast any other spells if global cooldown is still ticking + } + } + + if (DampenMagicTimer <= diff) + { + DoCast(me, SPELL_DAMPEN_MAGIC); + Cooldown = 1000; + DampenMagicTimer = 67200; // almost 1,12 minutes + ArcaneBoltTimer += 1000; // Give the Mage some time to spellsteal Dampen. + } else DampenMagicTimer -= diff; + + if (ArcaneExplosionTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); + Cooldown = 1000; + ArcaneExplosionTimer = 14000; + } else ArcaneExplosionTimer -= diff; + + if (ArcaneBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BOLT); + ArcaneBoltTimer = 3000; + Cooldown = 2000; + } else ArcaneBoltTimer -= diff; + + if (BlizzardTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_BLIZZARD); + BlizzardTimer = 45000 + rand()%46 * 1000; + FlamestrikeTimer += 10000; + Cooldown = 1000; + } + } else BlizzardTimer -= diff; + + if (FlamestrikeTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_FLAMESTRIKE); + FlamestrikeTimer = 55000 + rand()%46 * 1000; + BlizzardTimer += 10000; + Cooldown = 2000; + } + } else FlamestrikeTimer -= diff; + } +}; + +struct boss_lady_malandeAI : public boss_illidari_councilAI +{ + boss_lady_malandeAI(Creature *c) : boss_illidari_councilAI(c) {} + + uint32 EmpoweredSmiteTimer; + uint32 CircleOfHealingTimer; + uint32 DivineWrathTimer; + uint32 ReflectiveShieldTimer; + + void Reset() + { + EmpoweredSmiteTimer = 38000; + CircleOfHealingTimer = 20000; + DivineWrathTimer = 40000; + ReflectiveShieldTimer = 0; + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_MALA_SLAY, me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_MALA_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (EmpoweredSmiteTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_EMPOWERED_SMITE); + EmpoweredSmiteTimer = 38000; + } + } else EmpoweredSmiteTimer -= diff; + + if (CircleOfHealingTimer <= diff) + { + DoCast(me, SPELL_CIRCLE_OF_HEALING); + CircleOfHealingTimer = 60000; + } else CircleOfHealingTimer -= diff; + + if (DivineWrathTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_DIVINE_WRATH); + DivineWrathTimer = 40000 + rand()%41 * 1000; + } + } else DivineWrathTimer -= diff; + + if (ReflectiveShieldTimer <= diff) + { + DoCast(me, SPELL_REFLECTIVE_SHIELD); + ReflectiveShieldTimer = 65000; + } else ReflectiveShieldTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_veras_darkshadowAI : public boss_illidari_councilAI +{ + boss_veras_darkshadowAI(Creature *c) : boss_illidari_councilAI(c) {} + + uint64 EnvenomTargetGUID; + + uint32 DeadlyPoisonTimer; + uint32 VanishTimer; + uint32 AppearEnvenomTimer; + + bool HasVanished; + + void Reset() + { + EnvenomTargetGUID = 0; + + DeadlyPoisonTimer = 20000; + VanishTimer = 60000 + rand()%61 * 1000; + AppearEnvenomTimer = 150000; + + HasVanished = false; + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_VERA_SLAY, me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_VERA_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!HasVanished) + { + if (DeadlyPoisonTimer <= diff) + { + DoCast(me->getVictim(), SPELL_DEADLY_POISON); + DeadlyPoisonTimer = 15000 + rand()%31 * 1000; + } else DeadlyPoisonTimer -= diff; + + if (AppearEnvenomTimer <= diff) // Cast Envenom. This is cast 4 seconds after Vanish is over + { + DoCast(me->getVictim(), SPELL_ENVENOM); + AppearEnvenomTimer = 90000; + } else AppearEnvenomTimer -= diff; + + if (VanishTimer <= diff) // Disappear and stop attacking, but follow a random unit + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + VanishTimer = 30000; + AppearEnvenomTimer= 28000; + HasVanished = true; + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoResetThreat(); + // Chase a unit. Check before DoMeleeAttackIfReady prevents from attacking + me->AddThreat(pTarget, 500000.0f); + me->GetMotionMaster()->MoveChase(pTarget); + } + } else VanishTimer -= diff; + + DoMeleeAttackIfReady(); + } + else + { + if (VanishTimer <= diff) // Become attackable and poison current target + { + Unit *pTarget = me->getVictim(); + DoCast(pTarget, SPELL_DEADLY_POISON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoResetThreat(); + me->AddThreat(pTarget, 3000.0f); // Make Veras attack his target for a while, he will cast Envenom 4 seconds after. + DeadlyPoisonTimer += 6000; + VanishTimer = 90000; + AppearEnvenomTimer = 4000; + HasVanished = false; + } else VanishTimer -= diff; + + if (AppearEnvenomTimer <= diff) // Appear 2 seconds before becoming attackable (Shifting out of vanish) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + me->SetVisibility(VISIBILITY_ON); + AppearEnvenomTimer = 6000; + } else AppearEnvenomTimer -= diff; + } + } +}; + +CreatureAI* GetAI_mob_blood_elf_council_voice_trigger(Creature* c) +{ + return new mob_blood_elf_council_voice_triggerAI(c); +} + +CreatureAI* GetAI_mob_illidari_council(Creature* pCreature) +{ + return new mob_illidari_councilAI (pCreature); +} + +CreatureAI* GetAI_boss_gathios_the_shatterer(Creature* pCreature) +{ + return new boss_gathios_the_shattererAI (pCreature); +} + +CreatureAI* GetAI_boss_lady_malande(Creature* pCreature) +{ + return new boss_lady_malandeAI (pCreature); +} + +CreatureAI* GetAI_boss_veras_darkshadow(Creature* pCreature) +{ + return new boss_veras_darkshadowAI (pCreature); +} + +CreatureAI* GetAI_boss_high_nethermancer_zerevor(Creature* pCreature) +{ + return new boss_high_nethermancer_zerevorAI (pCreature); +} + +void AddSC_boss_illidari_council() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_illidari_council"; + newscript->GetAI = &GetAI_mob_illidari_council; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_blood_elf_council_voice_trigger"; + newscript->GetAI = &GetAI_mob_blood_elf_council_voice_trigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_gathios_the_shatterer"; + newscript->GetAI = &GetAI_boss_gathios_the_shatterer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lady_malande"; + newscript->GetAI = &GetAI_boss_lady_malande; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_veras_darkshadow"; + newscript->GetAI = &GetAI_boss_veras_darkshadow; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_high_nethermancer_zerevor"; + newscript->GetAI = &GetAI_boss_high_nethermancer_zerevor; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp new file mode 100644 index 00000000000..88e25026a13 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp @@ -0,0 +1,346 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Black_Temple +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Black Temple Scripts +SDCategory: Black Temple +EndScriptData */ + +#include "ScriptedPch.h" +#include "black_temple.h" + +#define MAX_ENCOUNTER 9 + +/* Black Temple encounters: +0 - High Warlord Naj'entus event +1 - Supremus Event +2 - Shade of Akama Event +3 - Teron Gorefiend Event +4 - Gurtogg Bloodboil Event +5 - Reliquary Of Souls Event +6 - Mother Shahraz Event +7 - Illidari Council Event +8 - Illidan Stormrage Event +*/ + +struct instance_black_temple : public ScriptedInstance +{ + instance_black_temple(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 Najentus; + uint64 Akama; // This is the Akama that starts the Illidan encounter. + uint64 Akama_Shade; // This is the Akama that starts the Shade of Akama encounter. + uint64 ShadeOfAkama; + uint64 Supremus; + uint64 LadyMalande; + uint64 GathiosTheShatterer; + uint64 HighNethermancerZerevor; + uint64 VerasDarkshadow; + uint64 IllidariCouncil; + uint64 BloodElfCouncilVoice; + uint64 IllidanStormrage; + + uint64 NajentusGate; + uint64 MainTempleDoors; + uint64 ShadeOfAkamaDoor; + uint64 CommonDoor;//Teron + uint64 TeronDoor; + uint64 GuurtogDoor; + uint64 MotherDoor; + uint64 TempleDoor;//Befor mother + uint64 CouncilDoor; + uint64 SimpleDoor;//council + uint64 IllidanGate; + uint64 IllidanDoor[2]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Najentus = 0; + Akama = 0; + Akama_Shade = 0; + ShadeOfAkama = 0; + Supremus = 0; + LadyMalande = 0; + GathiosTheShatterer = 0; + HighNethermancerZerevor = 0; + VerasDarkshadow = 0; + IllidariCouncil = 0; + BloodElfCouncilVoice = 0; + IllidanStormrage = 0; + + NajentusGate = 0; + MainTempleDoors = 0; + ShadeOfAkamaDoor= 0; + CommonDoor = 0;//teron + TeronDoor = 0; + GuurtogDoor = 0; + MotherDoor = 0; + TempleDoor = 0; + SimpleDoor = 0;//Bycouncil + CouncilDoor = 0; + IllidanGate = 0; + IllidanDoor[0] = 0; + IllidanDoor[1] = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Black Temple: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 22887: Najentus = pCreature->GetGUID(); break; + case 23089: Akama = pCreature->GetGUID(); break; + case 22990: Akama_Shade = pCreature->GetGUID(); break; + case 22841: ShadeOfAkama = pCreature->GetGUID(); break; + case 22898: Supremus = pCreature->GetGUID(); break; + case 22917: IllidanStormrage = pCreature->GetGUID(); break; + case 22949: GathiosTheShatterer = pCreature->GetGUID(); break; + case 22950: HighNethermancerZerevor = pCreature->GetGUID(); break; + case 22951: LadyMalande = pCreature->GetGUID(); break; + case 22952: VerasDarkshadow = pCreature->GetGUID(); break; + case 23426: IllidariCouncil = pCreature->GetGUID(); break; + case 23499: BloodElfCouncilVoice = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 185483: NajentusGate = pGo->GetGUID();// Gate past Naj'entus (at the entrance to Supermoose's courtyards) + if (m_auiEncounter[0] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185882: MainTempleDoors = pGo->GetGUID();// Main Temple Doors - right past Supermoose (Supremus) + if (m_auiEncounter[1] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185478: ShadeOfAkamaDoor = pGo->GetGUID();break; + case 185480: CommonDoor = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE)HandleGameObject(NULL,true,pGo);break; + case 186153: TeronDoor = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185892: GuurtogDoor = pGo->GetGUID(); + if (m_auiEncounter[4] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185479: TempleDoor = pGo->GetGUID(); + if (m_auiEncounter[5] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185482: MotherDoor = pGo->GetGUID(); + if (m_auiEncounter[6] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185481: CouncilDoor = pGo->GetGUID(); + if (m_auiEncounter[7] == DONE)HandleGameObject(NULL,true,pGo);break; + case 186152: SimpleDoor = pGo->GetGUID(); + if (m_auiEncounter[7] == DONE)HandleGameObject(NULL,true,pGo);break; + case 185905: IllidanGate = pGo->GetGUID(); break; // Gate leading to Temple Summit + case 186261: IllidanDoor[0] = pGo->GetGUID(); break; // Right door at Temple Summit + case 186262: IllidanDoor[1] = pGo->GetGUID(); break; // Left door at Temple Summit + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_HIGHWARLORDNAJENTUS: return Najentus; + case DATA_AKAMA: return Akama; + case DATA_AKAMA_SHADE: return Akama_Shade; + case DATA_SHADEOFAKAMA: return ShadeOfAkama; + case DATA_SUPREMUS: return Supremus; + case DATA_ILLIDANSTORMRAGE: return IllidanStormrage; + case DATA_GATHIOSTHESHATTERER: return GathiosTheShatterer; + case DATA_HIGHNETHERMANCERZEREVOR: return HighNethermancerZerevor; + case DATA_LADYMALANDE: return LadyMalande; + case DATA_VERASDARKSHADOW: return VerasDarkshadow; + case DATA_ILLIDARICOUNCIL: return IllidariCouncil; + case DATA_GAMEOBJECT_NAJENTUS_GATE: return NajentusGate; + case DATA_GAMEOBJECT_ILLIDAN_GATE: return IllidanGate; + case DATA_GAMEOBJECT_ILLIDAN_DOOR_R: return IllidanDoor[0]; + case DATA_GAMEOBJECT_ILLIDAN_DOOR_L: return IllidanDoor[1]; + case DATA_GAMEOBJECT_SUPREMUS_DOORS: return MainTempleDoors; + case DATA_BLOOD_ELF_COUNCIL_VOICE: return BloodElfCouncilVoice; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_HIGHWARLORDNAJENTUSEVENT: + if (data == DONE) + { + HandleGameObject(NajentusGate, true); + } + m_auiEncounter[0] = data;break; + case DATA_SUPREMUSEVENT: + if (data == DONE) + { + HandleGameObject(NajentusGate, true); + } + m_auiEncounter[1] = data; break; + case DATA_SHADEOFAKAMAEVENT: + if (data == IN_PROGRESS) + { + HandleGameObject(ShadeOfAkamaDoor, false); + } else HandleGameObject(ShadeOfAkamaDoor, true); + m_auiEncounter[2] = data; break; + case DATA_TERONGOREFIENDEVENT: + if (data == IN_PROGRESS) + { + HandleGameObject(TeronDoor, false); + HandleGameObject(CommonDoor, false); + }else + { + HandleGameObject(TeronDoor, true); + HandleGameObject(CommonDoor, true); + } + m_auiEncounter[3] = data; break; + case DATA_GURTOGGBLOODBOILEVENT: + if (data == DONE) + { + HandleGameObject(GuurtogDoor, true); + } + m_auiEncounter[4] = data; break; + case DATA_RELIQUARYOFSOULSEVENT: + if (data == DONE) + { + HandleGameObject(TempleDoor, true); + } + m_auiEncounter[5] = data; break; + case DATA_MOTHERSHAHRAZEVENT: + if (data == DONE) + { + HandleGameObject(MotherDoor, true); + } + m_auiEncounter[6] = data; break; + case DATA_ILLIDARICOUNCILEVENT: + if (data == IN_PROGRESS) + { + HandleGameObject(CouncilDoor, false); + HandleGameObject(SimpleDoor, false); + }else + { + HandleGameObject(CouncilDoor, true); + HandleGameObject(SimpleDoor, true); + } + m_auiEncounter[7] = data; break; + case DATA_ILLIDANSTORMRAGEEVENT: m_auiEncounter[8] = data; break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] + << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " << m_auiEncounter[7] + << " " << m_auiEncounter[8]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_HIGHWARLORDNAJENTUSEVENT: return m_auiEncounter[0]; + case DATA_SUPREMUSEVENT: return m_auiEncounter[1]; + case DATA_SHADEOFAKAMAEVENT: return m_auiEncounter[2]; + case DATA_TERONGOREFIENDEVENT: return m_auiEncounter[3]; + case DATA_GURTOGGBLOODBOILEVENT: return m_auiEncounter[4]; + case DATA_RELIQUARYOFSOULSEVENT: return m_auiEncounter[5]; + case DATA_MOTHERSHAHRAZEVENT: return m_auiEncounter[6]; + case DATA_ILLIDARICOUNCILEVENT: return m_auiEncounter[7]; + case DATA_ILLIDANSTORMRAGEEVENT: return m_auiEncounter[8]; + } + + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] + >> m_auiEncounter[3] >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] + >> m_auiEncounter[7] >> m_auiEncounter[8]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_black_temple(Map* pMap) +{ + return new instance_black_temple(pMap); +} + +void AddSC_instance_black_temple() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_black_temple"; + newscript->GetInstanceData = &GetInstanceData_instance_black_temple; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp new file mode 100644 index 00000000000..69a969adda0 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp @@ -0,0 +1,746 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Fathomlord_Karathress +SD%Complete: 70 +SDComment: Cyclone workaround +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedEscortAI.h" + +#define SAY_AGGRO -1548021 +#define SAY_GAIN_BLESSING -1548022 +#define SAY_GAIN_ABILITY1 -1548023 +#define SAY_GAIN_ABILITY2 -1548024 +#define SAY_GAIN_ABILITY3 -1548025 +#define SAY_SLAY1 -1548026 +#define SAY_SLAY2 -1548027 +#define SAY_SLAY3 -1548028 +#define SAY_DEATH -1548029 + +//Karathress spells +#define SPELL_CATACLYSMIC_BOLT 38441 +#define SPELL_POWER_OF_SHARKKIS 38455 +#define SPELL_POWER_OF_TIDALVESS 38452 +#define SPELL_POWER_OF_CARIBDIS 38451 +#define SPELL_ENRAGE 24318 +#define SPELL_SEAR_NOVA 38445 +#define SPELL_BLESSING_OF_THE_TIDES 38449 + +//Sharkkis spells +#define SPELL_LEECHING_THROW 29436 +#define SPELL_THE_BEAST_WITHIN 38373 +#define SPELL_MULTISHOT 38366 +#define SPELL_SUMMON_FATHOM_LURKER 38433 +#define SPELL_SUMMON_FATHOM_SPOREBAT 38431 +#define SPELL_PET_ENRAGE 19574 + +//Tidalvess spells +#define SPELL_FROST_SHOCK 38234 +#define SPELL_SPITFIRE_TOTEM 38236 +#define SPELL_POISON_CLEANSING_TOTEM 38306 +// Spell obsolete +// #define SPELL_POISON_CLEANSING_EFFECT 8167 +#define SPELL_EARTHBIND_TOTEM 38304 +#define SPELL_EARTHBIND_TOTEM_EFFECT 6474 +#define SPELL_WINDFURY_WEAPON 38184 + +//Caribdis Spells +#define SPELL_WATER_BOLT_VOLLEY 38335 +#define SPELL_TIDAL_SURGE 38358 +#define SPELL_TIDAL_SURGE_FREEZE 38357 +#define SPELL_HEAL 38330 +#define SPELL_SUMMON_CYCLONE 38337 +#define SPELL_CYCLONE_CYCLONE 29538 + +//Yells and Quotes +#define SAY_GAIN_BLESSING_OF_TIDES "Your overconfidence will be your undoing! Guards, lend me your strength!" +#define SOUND_GAIN_BLESSING_OF_TIDES 11278 +#define SAY_MISC "Alana be'lendor!" //don't know what use this +#define SOUND_MISC 11283 + +//Summoned Unit GUIDs +#define CREATURE_CYCLONE 22104 +#define CREATURE_FATHOM_SPOREBAT 22120 +#define CREATURE_FATHOM_LURKER 22119 +#define CREATURE_SPITFIRE_TOTEM 22091 +#define CREATURE_EARTHBIND_TOTEM 22486 +#define CREATURE_POISON_CLEANSING_TOTEM 22487 + +//entry and position for Seer Olum +#define SEER_OLUM 22820 +#define OLUM_X 446.78f +#define OLUM_Y -542.76f +#define OLUM_Z -7.54773f +#define OLUM_O 0.401581f + +//Fathom-Lord Karathress AI +struct boss_fathomlord_karathressAI : public ScriptedAI +{ + boss_fathomlord_karathressAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Advisors[0] = 0; + Advisors[1] = 0; + Advisors[2] = 0; + } + + ScriptedInstance* pInstance; + + uint32 CataclysmicBolt_Timer; + uint32 Enrage_Timer; + uint32 SearNova_Timer; + + bool BlessingOfTides; + + uint64 Advisors[3]; + + void Reset() + { + CataclysmicBolt_Timer = 10000; + Enrage_Timer = 600000; //10 minutes + SearNova_Timer = 20000+rand()%40000; // 20 - 60 seconds + + BlessingOfTides = false; + + if (pInstance) + { + uint64 RAdvisors[3]; + RAdvisors[0] = pInstance->GetData64(DATA_SHARKKIS); + RAdvisors[1] = pInstance->GetData64(DATA_TIDALVESS); + RAdvisors[2] = pInstance->GetData64(DATA_CARIBDIS); + //Respawn of the 3 Advisors + Creature* pAdvisor = NULL; + for (int i=0; i<3; ++i) + + if (RAdvisors[i]) + { + pAdvisor = (Unit::GetCreature((*me), RAdvisors[i])); + if (pAdvisor && !pAdvisor->isAlive()) + { + pAdvisor->Respawn(); + pAdvisor->AI()->EnterEvadeMode(); + pAdvisor->GetMotionMaster()->MoveTargetedHome(); + } + } + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + } + + void EventSharkkisDeath() + { + DoScriptText(SAY_GAIN_ABILITY1, me); + DoCast(me, SPELL_POWER_OF_SHARKKIS); + } + + void EventTidalvessDeath() + { + DoScriptText(SAY_GAIN_ABILITY2, me); + DoCast(me, SPELL_POWER_OF_TIDALVESS); + } + + void EventCaribdisDeath() + { + DoScriptText(SAY_GAIN_ABILITY3, me); + DoCast(me, SPELL_POWER_OF_CARIBDIS); + } + + void GetAdvisors() + { + if (!pInstance) + return; + + Advisors[0] = pInstance->GetData64(DATA_SHARKKIS); + Advisors[1] = pInstance->GetData64(DATA_TIDALVESS); + Advisors[2] = pInstance->GetData64(DATA_CARIBDIS); + } + + void StartEvent(Unit *who) + { + if (!pInstance) + return; + + GetAdvisors(); + + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); + + //support for quest 10944 + me->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 3600000); + } + + void EnterCombat(Unit * who) + { + StartEvent(who); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + GetAdvisors(); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //CataclysmicBolt_Timer + if (CataclysmicBolt_Timer <= diff) + { + //select a random unit other than the main tank + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + + //if there aren't other units, cast on the tank + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget) + DoCast(pTarget, SPELL_CATACLYSMIC_BOLT); + CataclysmicBolt_Timer = 10000; + } else CataclysmicBolt_Timer -= diff; + + //SearNova_Timer + if (SearNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SEAR_NOVA); + SearNova_Timer = 20000+rand()%40000; + } else SearNova_Timer -= diff; + + //Enrage_Timer + if (Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enrage_Timer = 90000; + } else Enrage_Timer -= diff; + + //Blessing of Tides Trigger + if ((me->GetHealth()*100 / me->GetMaxHealth()) <= 75 && !BlessingOfTides) + { + BlessingOfTides = true; + bool continueTriggering = false; + Creature* Advisor; + for (uint8 i = 0; i < 4; ++i) + if (Advisors[i]) + { + Advisor = (Unit::GetCreature(*me, Advisors[i])); + if (Advisor && Advisor->isAlive()) + { + continueTriggering = true; + break; + } + } + if (continueTriggering) + { + DoCast(me, SPELL_BLESSING_OF_THE_TIDES); + me->MonsterYell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_GAIN_BLESSING_OF_TIDES); + } + } + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Sharkkis AI +struct boss_fathomguard_sharkkisAI : public ScriptedAI +{ + boss_fathomguard_sharkkisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 LeechingThrow_Timer; + uint32 TheBeastWithin_Timer; + uint32 Multishot_Timer; + uint32 Pet_Timer; + + bool pet; + + uint64 SummonedPet; + + void Reset() + { + LeechingThrow_Timer = 20000; + TheBeastWithin_Timer = 30000; + Multishot_Timer = 15000; + Pet_Timer = 10000; + + pet = false; + + Creature *Pet = Unit::GetCreature(*me, SummonedPet); + if (Pet && Pet->isAlive()) + { + Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + SummonedPet = 0; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //LeechingThrow_Timer + if (LeechingThrow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LEECHING_THROW); + LeechingThrow_Timer = 20000; + } else LeechingThrow_Timer -= diff; + + //Multishot_Timer + if (Multishot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MULTISHOT); + Multishot_Timer = 20000; + } else Multishot_Timer -= diff; + + //TheBeastWithin_Timer + if (TheBeastWithin_Timer <= diff) + { + DoCast(me, SPELL_THE_BEAST_WITHIN); + Creature *Pet = Unit::GetCreature(*me, SummonedPet); + if (Pet && Pet->isAlive()) + { + Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); + } + TheBeastWithin_Timer = 30000; + } else TheBeastWithin_Timer -= diff; + + //Pet_Timer + if (Pet_Timer < diff && pet == false) + { + pet = true; + //uint32 spell_id; + uint32 pet_id; + if (!urand(0,1)) + { + //spell_id = SPELL_SUMMON_FATHOM_LURKER; + pet_id = CREATURE_FATHOM_LURKER; + } + else + { + //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; + pet_id = CREATURE_FATHOM_SPOREBAT; + } + //DoCast(me, spell_id, true); + Creature *Pet = DoSpawnCreature(pet_id,0,0,0,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (Pet && pTarget) + { + Pet->AI()->AttackStart(pTarget); + SummonedPet = Pet->GetGUID(); + } + } else Pet_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Tidalvess AI +struct boss_fathomguard_tidalvessAI : public ScriptedAI +{ + boss_fathomguard_tidalvessAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 FrostShock_Timer; + uint32 Spitfire_Timer; + uint32 PoisonCleansing_Timer; + uint32 Earthbind_Timer; + + void Reset() + { + FrostShock_Timer = 25000; + Spitfire_Timer = 60000; + PoisonCleansing_Timer = 30000; + Earthbind_Timer = 45000; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + if (!me->isAlive() && Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventTidalvessDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + DoCast(me, SPELL_WINDFURY_WEAPON); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + if (!me->HasAura(SPELL_WINDFURY_WEAPON)) + { + DoCast(me, SPELL_WINDFURY_WEAPON); + } + + //FrostShock_Timer + if (FrostShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_SHOCK); + FrostShock_Timer = 25000+rand()%5000; + } else FrostShock_Timer -= diff; + + //Spitfire_Timer + if (Spitfire_Timer <= diff) + { + DoCast(me, SPELL_SPITFIRE_TOTEM); + Unit *SpitfireTotem = Unit::GetUnit(*me, CREATURE_SPITFIRE_TOTEM); + if (SpitfireTotem) + { + CAST_CRE(SpitfireTotem)->AI()->AttackStart(me->getVictim()); + } + Spitfire_Timer = 60000; + } else Spitfire_Timer -= diff; + + //PoisonCleansing_Timer + if (PoisonCleansing_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLEANSING_TOTEM); + PoisonCleansing_Timer = 30000; + } else PoisonCleansing_Timer -= diff; + + //Earthbind_Timer + if (Earthbind_Timer <= diff) + { + DoCast(me, SPELL_EARTHBIND_TOTEM); + Earthbind_Timer = 45000; + } else Earthbind_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Caribdis AI +struct boss_fathomguard_caribdisAI : public ScriptedAI +{ + boss_fathomguard_caribdisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 WaterBoltVolley_Timer; + uint32 TidalSurge_Timer; + uint32 Heal_Timer; + uint32 Cyclone_Timer; + + void Reset() + { + WaterBoltVolley_Timer = 35000; + TidalSurge_Timer = 15000+rand()%5000; + Heal_Timer = 55000; + Cyclone_Timer = 30000+rand()%10000; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + if (!me->isAlive() && Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventCaribdisDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //WaterBoltVolley_Timer + if (WaterBoltVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WATER_BOLT_VOLLEY); + WaterBoltVolley_Timer = 30000; + } else WaterBoltVolley_Timer -= diff; + + //TidalSurge_Timer + if (TidalSurge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIDAL_SURGE); + // Hacky way to do it - won't trigger elseways + me->getVictim()->CastSpell(me->getVictim(), SPELL_TIDAL_SURGE_FREEZE, true); + TidalSurge_Timer = 15000+rand()%5000; + } else TidalSurge_Timer -= diff; + + //Cyclone_Timer + if (Cyclone_Timer <= diff) + { + //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work + Cyclone_Timer = 30000+rand()%10000; + Creature *Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000); + if (Cyclone) + { + CAST_CRE(Cyclone)->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); + Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Cyclone->setFaction(me->getFaction()); + Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Cyclone->AI()->AttackStart(pTarget); + } + } + } else Cyclone_Timer -= diff; + + //Heal_Timer + if (Heal_Timer <= diff) + { + // It can be cast on any of the mobs + Unit *pUnit = NULL; + + while (pUnit == NULL || !pUnit->isAlive()) + { + pUnit = selectAdvisorUnit(); + } + + if (pUnit && pUnit->isAlive()) + DoCast(pUnit, SPELL_HEAL); + Heal_Timer = 60000; + } else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + Unit* selectAdvisorUnit() + { + Unit* pUnit = NULL; + if (pInstance) + { + switch(rand()%4) + { + case 0: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESS)); + break; + case 1: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_SHARKKIS)); + break; + case 2: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_TIDALVESS)); + break; + case 3: + pUnit = me; + break; + } + } else pUnit = me; + + return pUnit; + } +}; + +CreatureAI* GetAI_boss_fathomlord_karathress(Creature* pCreature) +{ + return new boss_fathomlord_karathressAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_sharkkis(Creature* pCreature) +{ + return new boss_fathomguard_sharkkisAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_tidalvess(Creature* pCreature) +{ + return new boss_fathomguard_tidalvessAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_caribdis(Creature* pCreature) +{ + return new boss_fathomguard_caribdisAI (pCreature); +} + +void AddSC_boss_fathomlord_karathress() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_fathomlord_karathress"; + newscript->GetAI = &GetAI_boss_fathomlord_karathress; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_sharkkis"; + newscript->GetAI = &GetAI_boss_fathomguard_sharkkis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_tidalvess"; + newscript->GetAI = &GetAI_boss_fathomguard_tidalvess; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_caribdis"; + newscript->GetAI = &GetAI_boss_fathomguard_caribdis; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp new file mode 100644 index 00000000000..923fdf55f80 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp @@ -0,0 +1,379 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hydross_The_Unstable +SD%Complete: 90 +SDComment: Some details and adjustments left to do, probably nothing major. Spawns may be spawned in different way/location. +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define SAY_AGGRO -1548000 +#define SAY_SWITCH_TO_CLEAN -1548001 +#define SAY_CLEAN_SLAY1 -1548002 +#define SAY_CLEAN_SLAY2 -1548003 +#define SAY_CLEAN_DEATH -1548004 +#define SAY_SWITCH_TO_CORRUPT -1548005 +#define SAY_CORRUPT_SLAY1 -1548006 +#define SAY_CORRUPT_SLAY2 -1548007 +#define SAY_CORRUPT_DEATH -1548008 + +#define SWITCH_RADIUS 18 + +#define MODEL_CORRUPT 20609 +#define MODEL_CLEAN 20162 + +#define SPELL_WATER_TOMB 38235 +#define SPELL_MARK_OF_HYDROSS1 38215 +#define SPELL_MARK_OF_HYDROSS2 38216 +#define SPELL_MARK_OF_HYDROSS3 38217 +#define SPELL_MARK_OF_HYDROSS4 38218 +#define SPELL_MARK_OF_HYDROSS5 38231 +#define SPELL_MARK_OF_HYDROSS6 40584 +#define SPELL_MARK_OF_CORRUPTION1 38219 +#define SPELL_MARK_OF_CORRUPTION2 38220 +#define SPELL_MARK_OF_CORRUPTION3 38221 +#define SPELL_MARK_OF_CORRUPTION4 38222 +#define SPELL_MARK_OF_CORRUPTION5 38230 +#define SPELL_MARK_OF_CORRUPTION6 40583 +#define SPELL_VILE_SLUDGE 38246 +#define SPELL_ENRAGE 27680 //this spell need verification +#define SPELL_SUMMON_WATER_ELEMENT 36459 //not in use yet(in use ever?) +#define SPELL_ELEMENTAL_SPAWNIN 25035 +#define SPELL_BLUE_BEAM 40227 //channeled Hydross Beam Helper (not in use yet) + +#define ENTRY_PURE_SPAWN 22035 +#define ENTRY_TAINTED_SPAWN 22036 +#define ENTRY_BEAM_DUMMY 21934 + +#define HYDROSS_X -239.439 +#define HYDROSS_Y -363.481 + +#define SPAWN_X_DIFF1 6.934003 +#define SPAWN_Y_DIFF1 -11.255012 +#define SPAWN_X_DIFF2 -6.934003 +#define SPAWN_Y_DIFF2 11.255012 +#define SPAWN_X_DIFF3 -12.577011 +#define SPAWN_Y_DIFF3 -4.72702 +#define SPAWN_X_DIFF4 12.577011 +#define SPAWN_Y_DIFF4 4.72702 + +struct boss_hydross_the_unstableAI : public ScriptedAI +{ + boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 beams[2]; + uint32 PosCheck_Timer; + uint32 MarkOfHydross_Timer; + uint32 MarkOfCorruption_Timer; + uint32 WaterTomb_Timer; + uint32 VileSludge_Timer; + uint32 MarkOfHydross_Count; + uint32 MarkOfCorruption_Count; + uint32 EnrageTimer; + bool CorruptedForm; + bool beam; + SummonList Summons; + + void Reset() + { + DeSummonBeams(); + beams[0] = 0; + beams[1] = 0; + PosCheck_Timer = 2500; + MarkOfHydross_Timer = 15000; + MarkOfCorruption_Timer = 15000; + WaterTomb_Timer = 7000; + VileSludge_Timer = 7000; + MarkOfHydross_Count = 0; + MarkOfCorruption_Count = 0; + EnrageTimer = 600000; + + CorruptedForm = false; + me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + + me->SetDisplayId(MODEL_CLEAN); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); + beam = false; + Summons.DespawnAll(); + } + + void SummonBeams() + { + Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-258.333,-356.34,22.0499,5.90835,TEMPSUMMON_CORPSE_DESPAWN,0); + if (beamer) + { + beamer->CastSpell(me,SPELL_BLUE_BEAM,true); + beamer->SetDisplayId(11686); //invisible + beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + beams[0]=beamer->GetGUID(); + } + beamer = beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-219.918,-371.308,22.0042,2.73072,TEMPSUMMON_CORPSE_DESPAWN,0); + if (beamer) + { + beamer->CastSpell(me,SPELL_BLUE_BEAM,true); + beamer->SetDisplayId(11686); //invisible + beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + beams[1]=beamer->GetGUID(); + } + } + void DeSummonBeams() + { + for (uint8 i=0; i<2; ++i) + { + Creature* mob = Unit::GetCreature(*me,beams[i]); + if (mob) + { + mob->setDeathState(DEAD); + mob->RemoveCorpse(); + } + } + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + if (CorruptedForm) + { + DoScriptText(RAND(SAY_CORRUPT_SLAY1,SAY_CORRUPT_SLAY2), me); + } + else + { + DoScriptText(RAND(SAY_CLEAN_SLAY1,SAY_CLEAN_SLAY2), me); + } + } + + void JustSummoned(Creature* summoned) + { + if (summoned->GetEntry() == ENTRY_PURE_SPAWN) + { + summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); + Summons.Summon(summoned); + } + if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN) + { + summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); + Summons.Summon(summoned); + } + } + + void SummonedCreatureDespawn(Creature *summon) + { + Summons.Despawn(summon); + } + + void JustDied(Unit * /*victim*/) + { + if (CorruptedForm) + DoScriptText(SAY_CORRUPT_DEATH, me); + else + DoScriptText(SAY_CLEAN_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, DONE); + Summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!beam) + { + SummonBeams(); + beam=true; + } + //Return since we have no target + if (!UpdateVictim()) + return; + + // corrupted form + if (CorruptedForm) + { + //MarkOfCorruption_Timer + if (MarkOfCorruption_Timer <= diff) + { + if (MarkOfCorruption_Count <= 5) + { + uint32 mark_spell = 0; + + switch (MarkOfCorruption_Count) + { + case 0: mark_spell = SPELL_MARK_OF_CORRUPTION1; break; + case 1: mark_spell = SPELL_MARK_OF_CORRUPTION2; break; + case 2: mark_spell = SPELL_MARK_OF_CORRUPTION3; break; + case 3: mark_spell = SPELL_MARK_OF_CORRUPTION4; break; + case 4: mark_spell = SPELL_MARK_OF_CORRUPTION5; break; + case 5: mark_spell = SPELL_MARK_OF_CORRUPTION6; break; + } + + DoCast(me->getVictim(), mark_spell); + + if (MarkOfCorruption_Count < 5) + ++MarkOfCorruption_Count; + } + + MarkOfCorruption_Timer = 15000; + } else MarkOfCorruption_Timer -= diff; + + //VileSludge_Timer + if (VileSludge_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_VILE_SLUDGE); + + VileSludge_Timer = 15000; + } else VileSludge_Timer -= diff; + + //PosCheck_Timer + if (PosCheck_Timer <= diff) + { + if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) + { + // switch to clean form + me->SetDisplayId(MODEL_CLEAN); + CorruptedForm = false; + MarkOfHydross_Count = 0; + + DoScriptText(SAY_SWITCH_TO_CLEAN, me); + DoResetThreat(); + SummonBeams(); + + // spawn 4 adds + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + } + + PosCheck_Timer = 2500; + } else PosCheck_Timer -=diff; + } + // clean form + else + { + //MarkOfHydross_Timer + if (MarkOfHydross_Timer <= diff) + { + if (MarkOfHydross_Count <= 5) + { + uint32 mark_spell = NULL; + + switch(MarkOfHydross_Count) + { + case 0: mark_spell = SPELL_MARK_OF_HYDROSS1; break; + case 1: mark_spell = SPELL_MARK_OF_HYDROSS2; break; + case 2: mark_spell = SPELL_MARK_OF_HYDROSS3; break; + case 3: mark_spell = SPELL_MARK_OF_HYDROSS4; break; + case 4: mark_spell = SPELL_MARK_OF_HYDROSS5; break; + case 5: mark_spell = SPELL_MARK_OF_HYDROSS6; break; + } + + DoCast(me->getVictim(), mark_spell); + + if (MarkOfHydross_Count < 5) + ++MarkOfHydross_Count; + } + + MarkOfHydross_Timer = 15000; + } else MarkOfHydross_Timer -= diff; + + //WaterTomb_Timer + if (WaterTomb_Timer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget) + DoCast(pTarget, SPELL_WATER_TOMB); + + WaterTomb_Timer = 7000; + } else WaterTomb_Timer -= diff; + + //PosCheck_Timer + if (PosCheck_Timer <= diff) + { + if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) + { + // switch to corrupted form + me->SetDisplayId(MODEL_CORRUPT); + MarkOfCorruption_Count = 0; + CorruptedForm = true; + + DoScriptText(SAY_SWITCH_TO_CORRUPT, me); + DoResetThreat(); + DeSummonBeams(); + + // spawn 4 adds + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + } + + PosCheck_Timer = 2500; + } else PosCheck_Timer -=diff; + } + + //EnrageTimer + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_ENRAGE); + EnrageTimer = 60000; + } else EnrageTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hydross_the_unstable(Creature* pCreature) +{ + return new boss_hydross_the_unstableAI (pCreature); +} + +void AddSC_boss_hydross_the_unstable() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hydross_the_unstable"; + newscript->GetAI = &GetAI_boss_hydross_the_unstable; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp new file mode 100644 index 00000000000..2f0485d0e6c --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp @@ -0,0 +1,1039 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA + */ + +/* ScriptData +SDName: Boss_Lady_Vashj +SD%Complete: 99 +SDComment: Missing blizzlike Shield Generators coords +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedSimpleAI.h" +#include "Spell.h" + +#define SAY_INTRO -1548042 +#define SAY_AGGRO1 -1548043 +#define SAY_AGGRO2 -1548044 +#define SAY_AGGRO3 -1548045 +#define SAY_AGGRO4 -1548046 +#define SAY_PHASE1 -1548047 +#define SAY_PHASE2 -1548048 +#define SAY_PHASE3 -1548049 +#define SAY_BOWSHOT1 -1548050 +#define SAY_BOWSHOT2 -1548051 +#define SAY_SLAY1 -1548052 +#define SAY_SLAY2 -1548053 +#define SAY_SLAY3 -1548054 +#define SAY_DEATH -1548055 + +#define SPELL_SURGE 38044 +#define SPELL_MULTI_SHOT 38310 +#define SPELL_SHOCK_BLAST 38509 +#define SPELL_ENTANGLE 38316 +#define SPELL_STATIC_CHARGE_TRIGGER 38280 +#define SPELL_FORKED_LIGHTNING 40088 +#define SPELL_SHOOT 40873 +#define SPELL_POISON_BOLT 40095 +#define SPELL_TOXIC_SPORES 38575 +#define SPELL_MAGIC_BARRIER 38112 + +#define MIDDLE_X 30.134 +#define MIDDLE_Y -923.65 +#define MIDDLE_Z 42.9 + +#define SPOREBAT_X 30.977156 +#define SPOREBAT_Y -925.297761 +#define SPOREBAT_Z 77.176567 +#define SPOREBAT_O 5.223932 + +#define SHIED_GENERATOR_CHANNEL 19870 +#define ENCHANTED_ELEMENTAL 21958 +#define TAINTED_ELEMENTAL 22009 +#define COILFANG_STRIDER 22056 +#define COILFANG_ELITE 22055 +#define TOXIC_SPOREBAT 22140 +#define TOXIC_SPORES_TRIGGER 22207 + +#define TEXT_NOT_INITIALIZED "Instance script not initialized" +#define TEXT_ALREADY_DEACTIVATED "Already deactivated" + +float ElementPos[8][4] = +{ + {8.3, -835.3, 21.9, 5}, + {53.4, -835.3, 21.9, 4.5}, + {96, -861.9, 21.8, 4}, + {96, -986.4, 21.4, 2.5}, + {54.4, -1010.6, 22, 1.8}, + {9.8, -1012, 21.7, 1.4}, + {-35, -987.6, 21.5, 0.8}, + {-58.9, -901.6, 21.5, 6} +}; + +float ElementWPPos[8][3] = +{ + {71.700752, -883.905884, 41.097168}, + {45.039848, -868.022827, 41.097015}, + {14.585141, -867.894470, 41.097061}, + {-25.415508, -906.737732, 41.097061}, + {-11.801594, -963.405884, 41.097067}, + {14.556657, -979.051514, 41.097137}, + {43.466549, -979.406677, 41.097027}, + {69.945908, -964.663940, 41.097054} +}; + +float SporebatWPPos[8][3] = +{ + {31.6,-896.3,59.1}, + {9.1, -913.9, 56}, + {5.2, -934.4, 52.4}, + {20.7, -946.9, 49.7}, + {41, -941.9, 51}, + {47.7, -927.3, 55}, + {42.2, -912.4, 51.7}, + {27, -905.9, 50} +}; + +float CoilfangElitePos[3][4] = +{ + {28.84, -923.28, 42.9, 6}, + {31.183281, -953.502625, 41.523602, 1.640957}, + {58.895180, -923.124268, 41.545307, 3.152848} +}; + +float CoilfangStriderPos[3][4] = +{ + {66.427010, -948.778503, 41.262245, 2.584220}, + {7.513962, -959.538208, 41.300422, 1.034629}, + {-12.843201, -907.798401, 41.239620, 6.087094} +}; + +float ShieldGeneratorChannelPos[4][4] = +{ + {49.6262, -902.181, 43.0975, 3.95683}, + {10.988, -901.616, 42.5371, 5.4373}, + {10.3859, -944.036, 42.5446, 0.779888}, + {49.3126, -943.398, 42.5501, 2.40174} +}; + +//Lady Vashj AI +struct boss_lady_vashjAI : public ScriptedAI +{ + boss_lady_vashjAI (Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = false; + JustCreated = true; + c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //set it only once on Creature create (no need do intro if wiped) + } + + ScriptedInstance *pInstance; + + uint64 ShieldGeneratorChannel[4]; + + uint32 AggroTimer; + uint32 ShockBlast_Timer; + uint32 Entangle_Timer; + uint32 StaticCharge_Timer; + uint32 ForkedLightning_Timer; + uint32 Check_Timer; + uint32 EnchantedElemental_Timer; + uint32 TaintedElemental_Timer; + uint32 CoilfangElite_Timer; + uint32 CoilfangStrider_Timer; + uint32 SummonSporebat_Timer; + uint32 SummonSporebat_StaticTimer; + uint8 EnchantedElemental_Pos; + uint8 Phase; + + bool Entangle; + bool Intro; + bool CanAttack; + bool JustCreated; + + void Reset() + { + AggroTimer = 19000; + ShockBlast_Timer = 1+rand()%60000; + Entangle_Timer = 30000; + StaticCharge_Timer = 10000+rand()%15000; + ForkedLightning_Timer = 2000; + Check_Timer = 15000; + EnchantedElemental_Timer = 5000; + TaintedElemental_Timer = 50000; + CoilfangElite_Timer = 45000+rand()%5000; + CoilfangStrider_Timer = 60000+rand()%10000; + SummonSporebat_Timer = 10000; + SummonSporebat_StaticTimer = 30000; + EnchantedElemental_Pos = 0; + Phase = 0; + + Entangle = false; + if (JustCreated) + { + CanAttack = false; + JustCreated = false; + } else CanAttack = true; + + Unit *remo; + for (uint8 i = 0; i < 4; ++i) + { + remo = Unit::GetUnit(*me, ShieldGeneratorChannel[i]); + if (remo) + remo->setDeathState(JUST_DIED); + } + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED); + ShieldGeneratorChannel[0] = 0; + ShieldGeneratorChannel[1] = 0; + ShieldGeneratorChannel[2] = 0; + ShieldGeneratorChannel[3] = 0; + + me->SetCorpseDelay(1000*60*60); + } + + //Called when a tainted elemental dies + void EventTaintedElementalDeath() + { + //the next will spawn 50 seconds after the previous one's death + if (TaintedElemental_Timer > 50000) + TaintedElemental_Timer = 50000; + } + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, DONE); + } + + void StartEvent() + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3,SAY_AGGRO4), me); + + Phase = 1; + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + //remove old tainted cores to prevent cheating in phase 2 + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* i_pl = i->getSource()) + { + i_pl->DestroyItemCount(31088, 1, true); + } + } + } + StartEvent();//this is EnterCombat(), so were are 100% in combat, start the event + + if (Phase != 2) + AttackStart(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (!Intro) + { + Intro = true; + DoScriptText(SAY_INTRO, me); + } + if (!CanAttack) + return; + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) + { + //if (who->HasStealthAura()) + // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!me->isInCombat())//AttackStart() sets UNIT_FLAG_IN_COMBAT, so this msut be before attacking + StartEvent(); + + if (Phase != 2) + AttackStart(who); + } + } + } + + void CastShootOrMultishot() + { + switch (urand(0,1)) + { + case 0: + //Shoot + //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. + DoCast(me->getVictim(), SPELL_SHOOT); + break; + case 1: + //Multishot + //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. + DoCast(me->getVictim(), SPELL_MULTI_SHOT); + break; + } + if (rand()%3) + { + DoScriptText(RAND(SAY_BOWSHOT1,SAY_BOWSHOT2), me); + } + } + + void UpdateAI(const uint32 diff) + { + if (!CanAttack && Intro) + { + if (AggroTimer <= diff) + { + CanAttack = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer=19000; + }else + { + AggroTimer-=diff; + return; + } + } + //to prevent abuses during phase 2 + if (Phase == 2 && !me->getVictim() && me->isInCombat()) + { + EnterEvadeMode(); + return; + } + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Phase == 1 || Phase == 3) + { + //ShockBlast_Timer + if (ShockBlast_Timer <= diff) + { + //Shock Burst + //Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. + DoCast(me->getVictim(), SPELL_SHOCK_BLAST); + me->TauntApply(me->getVictim()); + + ShockBlast_Timer = 1000+rand()%14000; //random cooldown + } else ShockBlast_Timer -= diff; + + //StaticCharge_Timer + if (StaticCharge_Timer <= diff) + { + //Static Charge + //Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. + Unit *pTarget = NULL; + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true); + + if (pTarget && !pTarget->HasAura(SPELL_STATIC_CHARGE_TRIGGER)) + //cast Static Charge every 2 seconds for 20 seconds + DoCast(pTarget, SPELL_STATIC_CHARGE_TRIGGER); + + StaticCharge_Timer = 10000+rand()%20000; //blizzlike + } else StaticCharge_Timer -= diff; + + //Entangle_Timer + if (Entangle_Timer <= diff) + { + if (!Entangle) + { + //Entangle + //Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. + DoCast(me->getVictim(), SPELL_ENTANGLE); + Entangle = true; + Entangle_Timer = 10000; + } + else + { + CastShootOrMultishot(); + Entangle = false; + Entangle_Timer = 20000+rand()%5000; + } + } else Entangle_Timer -= diff; + + //Phase 1 + if (Phase == 1) + { + //Start phase 2 + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 70) + { + //Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. + Phase = 2; + + me->GetMotionMaster()->Clear(); + DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + + Creature *pCreature; + for (uint8 i = 0; i < 4; ++i) + { + pCreature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0], ShieldGeneratorChannelPos[i][1], ShieldGeneratorChannelPos[i][2], ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + if (pCreature) + ShieldGeneratorChannel[i] = pCreature->GetGUID(); + } + DoScriptText(SAY_PHASE2, me); + } + } + //Phase 3 + else + { + //SummonSporebat_Timer + if (SummonSporebat_Timer <= diff) + { + Creature *Sporebat = NULL; + Sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (Sporebat) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Sporebat->AI()->AttackStart(pTarget); + } + + //summon sporebats faster and faster + if (SummonSporebat_StaticTimer > 1000) + SummonSporebat_StaticTimer -= 1000; + + SummonSporebat_Timer = SummonSporebat_StaticTimer; + + if (SummonSporebat_Timer < 5000) + SummonSporebat_Timer = 5000; + + } else SummonSporebat_Timer -= diff; + } + + //Melee attack + DoMeleeAttackIfReady(); + + //Check_Timer - used to check if somebody is in melee range + if (Check_Timer <= diff) + { + bool InMeleeRange = false; + Unit *pTarget; + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //if in melee range + if (pTarget && pTarget->IsWithinDistInMap(me, 5)) + { + InMeleeRange = true; + break; + } + } + + //if nobody is in melee range + if (!InMeleeRange) + CastShootOrMultishot(); + + Check_Timer = 5000; + } else Check_Timer -= diff; + } + //Phase 2 + else + { + //ForkedLightning_Timer + if (ForkedLightning_Timer <= diff) + { + //Forked Lightning + //Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (!pTarget) + pTarget = me->getVictim(); + + DoCast(pTarget, SPELL_FORKED_LIGHTNING); + + ForkedLightning_Timer = 2000+rand()%6000; //blizzlike + } else ForkedLightning_Timer -= diff; + + //EnchantedElemental_Timer + if (EnchantedElemental_Timer <= diff) + { + Creature *Elemental; + Elemental = me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (EnchantedElemental_Pos == 7) + EnchantedElemental_Pos = 0; + else + ++EnchantedElemental_Pos; + + EnchantedElemental_Timer = 10000+rand()%5000; + } else EnchantedElemental_Timer -= diff; + + //TaintedElemental_Timer + if (TaintedElemental_Timer <= diff) + { + Creature *Tain_Elemental; + uint32 pos = rand()%8; + Tain_Elemental = me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN, 0); + + TaintedElemental_Timer = 120000; + } else TaintedElemental_Timer -= diff; + + //CoilfangElite_Timer + if (CoilfangElite_Timer <= diff) + { + uint32 pos = rand()%3; + Creature* CoilfangElite = NULL; + CoilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (CoilfangElite) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + CoilfangElite->AI()->AttackStart(pTarget); + else if (me->getVictim()) + CoilfangElite->AI()->AttackStart(me->getVictim()); + } + CoilfangElite_Timer = 45000+rand()%5000; + } else CoilfangElite_Timer -= diff; + + //CoilfangStrider_Timer + if (CoilfangStrider_Timer <= diff) + { + uint32 pos = rand()%3; + Creature* CoilfangStrider = NULL; + CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (CoilfangStrider) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + CoilfangStrider->AI()->AttackStart(pTarget); + else if (me->getVictim()) + CoilfangStrider->AI()->AttackStart(me->getVictim()); + } + CoilfangStrider_Timer = 60000+rand()%10000; + } else CoilfangStrider_Timer -= diff; + + //Check_Timer + if (Check_Timer <= diff) + { + //Start Phase 3 + if (pInstance && pInstance->GetData(DATA_CANSTARTPHASE3)) + { + //set life 50% + me->SetHealth(me->GetMaxHealth()/2); + + me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); + + DoScriptText(SAY_PHASE3, me); + + Phase = 3; + + //return to the tank + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + Check_Timer = 1000; + } else Check_Timer -= diff; + } + } +}; + +//Enchanted Elemental +//If one of them reaches Vashj he will increase her damage done by 5%. +struct mob_enchanted_elementalAI : public ScriptedAI +{ + mob_enchanted_elementalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 move; + uint32 phase; + float x, y, z; + + uint64 VashjGUID; + + void Reset() + { + me->SetSpeed(MOVE_WALK,0.6);//walk + me->SetSpeed(MOVE_RUN,0.6);//run + move = 0; + phase = 1; + + VashjGUID = 0; + + for (int i = 0; i<8; ++i)//search for nearest waypoint (up on stairs) + { + if (!x || !y || !z) + { + x = ElementWPPos[i][0]; + y = ElementWPPos[i][1]; + z = ElementWPPos[i][2]; + } + else + { + if (me->GetDistance(ElementWPPos[i][0],ElementWPPos[i][1],ElementWPPos[i][2]) < me->GetDistance(x,y,z)) + { + x = ElementWPPos[i][0]; + y = ElementWPPos[i][1]; + z = ElementWPPos[i][2]; + } + } + } + if (pInstance) + VashjGUID = pInstance->GetData64(DATA_LADYVASHJ); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (!VashjGUID) + return; + + if (move <= diff) + { + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + if (phase == 1) + me->GetMotionMaster()->MovePoint(0, x, y, z); + if (phase == 1 && me->IsWithinDist3d(x,y,z, 0.1)) + phase = 2; + if (phase == 2) + { + me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + phase = 3; + } + if (phase == 3) + { + me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + if (me->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) + DoCast(me, SPELL_SURGE); + } + if (Creature *Vashj = Unit::GetCreature(*me, VashjGUID)) + { + if (!Vashj->isInCombat() || CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase != 2 || Vashj->isDead()) + { + //call Unsummon() + me->Kill(me); + } + } + move = 1000; + } else move -= diff; + } +}; + +//Tainted Elemental +//This mob has 7,900 life, doesn't move, and shoots Poison Bolts at one person anywhere in the area, doing 3,000 nature damage and placing a posion doing 2,000 damage every 2 seconds. He will switch targets often, or sometimes just hang on a single player, but there is nothing you can do about it except heal the damage and kill the Tainted Elemental +struct mob_tainted_elementalAI : public ScriptedAI +{ + mob_tainted_elementalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 PoisonBolt_Timer; + uint32 Despawn_Timer; + + void Reset() + { + PoisonBolt_Timer = 5000+rand()%5000; + Despawn_Timer = 30000; + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + { + Creature *Vashj = NULL; + Vashj = (Unit::GetCreature((*me), pInstance->GetData64(DATA_LADYVASHJ))); + + if (Vashj) + CAST_AI(boss_lady_vashjAI, Vashj->AI())->EventTaintedElementalDeath(); + } + } + + void EnterCombat(Unit * who) + { + me->AddThreat(who, 0.1f); + } + + void UpdateAI(const uint32 diff) + { + //PoisonBolt_Timer + if (PoisonBolt_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget && pTarget->IsWithinDistInMap(me, 30)) + DoCast(pTarget, SPELL_POISON_BOLT); + + PoisonBolt_Timer = 5000+rand()%5000; + } else PoisonBolt_Timer -= diff; + + //Despawn_Timer + if (Despawn_Timer <= diff) + { + //call Unsummon() + me->setDeathState(DEAD); + + //to prevent crashes + Despawn_Timer = 1000; + } else Despawn_Timer -= diff; + } +}; + +//Toxic Sporebat +//Toxic Spores: Used in Phase 3 by the Spore Bats, it creates a contaminated green patch of ground, dealing about 2775-3225 nature damage every second to anyone who stands in it. +struct mob_toxic_sporebatAI : public ScriptedAI +{ + mob_toxic_sporebatAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EnterEvadeMode(); + } + + ScriptedInstance *pInstance; + + uint32 movement_timer; + uint32 ToxicSpore_Timer; + uint32 bolt_timer; + uint32 Check_Timer; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->setFaction(14); + movement_timer = 0; + ToxicSpore_Timer = 5000; + bolt_timer = 5500; + Check_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + + } + + void MoveInLineOfSight(Unit * /*who*/) + { + + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + movement_timer = 0; + } + + void UpdateAI (const uint32 diff) + { + //Random movement + if (movement_timer <= diff) + { + uint32 rndpos = rand()%8; + me->GetMotionMaster()->MovePoint(1,SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]); + movement_timer = 6000; + } else movement_timer -= diff; + + //toxic spores + if (bolt_timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); + if (trig) + { + trig->setFaction(14); + trig->CastSpell(trig, SPELL_TOXIC_SPORES,true); + } + } + bolt_timer = 10000+rand()%5000; + } + else bolt_timer -= diff; + + //Check_Timer + if (Check_Timer <= diff) + { + if (pInstance) + { + //check if vashj is death + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); + if (!Vashj || (Vashj && !Vashj->isAlive()) || (Vashj && CAST_AI(boss_lady_vashjAI, CAST_CRE(Vashj)->AI())->Phase != 3)) + { + //remove + me->setDeathState(DEAD); + me->RemoveCorpse(); + me->setFaction(35); + } + } + + Check_Timer = 1000; + } else Check_Timer -= diff; + } +}; + +//Coilfang Elite +//It's an elite Naga mob with 170,000 HP. It does about 5000 damage on plate, and has a nasty cleave hitting for about 7500 damage +CreatureAI* GetAI_mob_coilfang_elite(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 31345; //Cleave + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].CooldownRandomAddition = 5000; + ai->Spell[0].First_Cast = 5000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_RANDOM; + + ai->EnterEvadeMode(); + + return ai; +} + +//Coilfang Strider +//It hits plate for about 8000 damage, has a Mind Blast spell doing about 3000 shadow damage, and a Psychic Scream Aura, which fears everybody in a 8 yard range of it every 2-3 seconds , for 5 seconds and increasing their movement speed by 150% during the fear. +CreatureAI* GetAI_mob_coilfang_strider(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 41374; //Mind Blast + ai->Spell[0].Cooldown = 30000; + ai->Spell[0].CooldownRandomAddition = 10000; + ai->Spell[0].First_Cast = 8000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + //Scream aura not implemented + + ai->EnterEvadeMode(); + + return ai; +} + +struct mob_shield_generator_channelAI : public ScriptedAI +{ + mob_shield_generator_channelAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 Check_Timer; + bool Casted; + void Reset() + { + Check_Timer = 0; + Casted = false; + me->SetDisplayId(11686); //invisible + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI (const uint32 diff) + { + if (!pInstance) + return; + + if (Check_Timer <= diff) + { + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); + + if (Vashj && Vashj->isAlive()) + { + //start visual channel + if (!Casted || !Vashj->HasAura(SPELL_MAGIC_BARRIER)) + { + DoCast(Vashj, SPELL_MAGIC_BARRIER, true); + Casted = true; + } + } + Check_Timer = 1000; + } else Check_Timer -= diff; + } +}; + +bool ItemUse_item_tainted_core(Player* pPlayer, Item* /*_Item*/, SpellCastTargets const& targets) +{ + ScriptedInstance *pInstance = pPlayer->GetInstanceData(); + + if (!pInstance) + { + pPlayer->GetSession()->SendNotification(TEXT_NOT_INITIALIZED); + return true; + } + + Creature *Vashj = NULL; + Vashj = (Unit::GetCreature((*pPlayer), pInstance->GetData64(DATA_LADYVASHJ))); + if (Vashj && CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase == 2) + { + if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT) + { + uint32 identifier; + uint8 channel_identifier; + switch(targets.getGOTarget()->GetEntry()) + { + case 185052: + identifier = DATA_SHIELDGENERATOR1; + channel_identifier = 0; + break; + case 185053: + identifier = DATA_SHIELDGENERATOR2; + channel_identifier = 1; + break; + case 185051: + identifier = DATA_SHIELDGENERATOR3; + channel_identifier = 2; + break; + case 185054: + identifier = DATA_SHIELDGENERATOR4; + channel_identifier = 3; + break; + default: + return true; + } + + if (pInstance->GetData(identifier)) + { + pPlayer->GetSession()->SendNotification(TEXT_ALREADY_DEACTIVATED); + return true; + } + + //get and remove channel + Unit *Channel = NULL; + Channel = Unit::GetCreature(*Vashj, CAST_AI(boss_lady_vashjAI, Vashj->AI())->ShieldGeneratorChannel[channel_identifier]); + if (Channel) + { + //call Unsummon() + Channel->setDeathState(JUST_DIED); + } + + pInstance->SetData(identifier, 1); + + //remove this item + pPlayer->DestroyItemCount(31088, 1, true); + return true; + } + else if (targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT) + return false; + else if (targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) + { + pPlayer->DestroyItemCount(31088, 1, true); + pPlayer->CastSpell(targets.getUnitTarget(), 38134, true); + return true; + } + } + return true; +} + +CreatureAI* GetAI_boss_lady_vashj(Creature* pCreature) +{ + return new boss_lady_vashjAI (pCreature); +} + +CreatureAI* GetAI_mob_enchanted_elemental(Creature* pCreature) +{ + return new mob_enchanted_elementalAI (pCreature); +} + +CreatureAI* GetAI_mob_tainted_elemental(Creature* pCreature) +{ + return new mob_tainted_elementalAI (pCreature); +} + +CreatureAI* GetAI_mob_toxic_sporebat(Creature* pCreature) +{ + return new mob_toxic_sporebatAI (pCreature); +} + +CreatureAI* GetAI_mob_shield_generator_channel(Creature* pCreature) +{ + return new mob_shield_generator_channelAI (pCreature); +} + +void AddSC_boss_lady_vashj() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lady_vashj"; + newscript->GetAI = &GetAI_boss_lady_vashj; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_enchanted_elemental"; + newscript->GetAI = &GetAI_mob_enchanted_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tainted_elemental"; + newscript->GetAI = &GetAI_mob_tainted_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toxic_sporebat"; + newscript->GetAI = &GetAI_mob_toxic_sporebat; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_elite"; + newscript->GetAI = &GetAI_mob_coilfang_elite; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_strider"; + newscript->GetAI = &GetAI_mob_coilfang_strider; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shield_generator_channel"; + newscript->GetAI = &GetAI_mob_shield_generator_channel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_tainted_core"; + newscript->pItemUse = &ItemUse_item_tainted_core; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp new file mode 100644 index 00000000000..61c9ed9d527 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp @@ -0,0 +1,787 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Leotheras_The_Blind +SD%Complete: 80 +SDComment: Possesion Support +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +// --- Spells used by Leotheras The Blind +#define SPELL_WHIRLWIND 37640 +#define SPELL_CHAOS_BLAST 37674 +#define SPELL_BERSERK 26662 +#define SPELL_INSIDIOUS_WHISPER 37676 +#define SPELL_DUAL_WIELD 42459 + +// --- Spells used in banish phase --- +#define BANISH_BEAM 38909 +#define AURA_BANISH 37833 + +// --- Spells used by Greyheart Spellbinders +#define SPELL_EARTHSHOCK 39076 +#define SPELL_MINDBLAST 37531 + +// --- Spells used by Inner Demons and Creature ID +#define INNER_DEMON_ID 21857 +#define AURA_DEMONIC_ALIGNMENT 37713 +#define SPELL_SHADOWBOLT 39309 +#define SPELL_SOUL_LINK 38007 +#define SPELL_CONSUMING_MADNESS 37749 //not supported by core yet + +//Misc. +#define MODEL_DEMON 20125 +#define MODEL_NIGHTELF 20514 +#define DEMON_FORM 21875 +#define MOB_SPELLBINDER 21806 + +#define SAY_AGGRO -1548009 +#define SAY_SWITCH_TO_DEMON -1548010 +#define SAY_INNER_DEMONS -1548011 +#define SAY_DEMON_SLAY1 -1548012 +#define SAY_DEMON_SLAY2 -1548013 +#define SAY_DEMON_SLAY3 -1548014 +#define SAY_NIGHTELF_SLAY1 -1548015 +#define SAY_NIGHTELF_SLAY2 -1548016 +#define SAY_NIGHTELF_SLAY3 -1548017 +#define SAY_FINAL_FORM -1548018 +#define SAY_FREE -1548019 +#define SAY_DEATH -1548020 + +struct mob_inner_demonAI : public ScriptedAI +{ + mob_inner_demonAI(Creature *c) : ScriptedAI(c) + { + victimGUID = 0; + } + + uint32 ShadowBolt_Timer; + + uint32 Link_Timer; + uint64 victimGUID; + + void Reset() + { + ShadowBolt_Timer = 10000; + Link_Timer = 1000; + } + void JustDied(Unit * /*victim*/) + { + Unit* pUnit = Unit::GetUnit((*me),victimGUID); + if (pUnit && pUnit->HasAura(SPELL_INSIDIOUS_WHISPER)) + pUnit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID()) + { + damage = 0; + DoModifyThreatPercent(done_by, -100); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (!victimGUID) return; + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (me->getVictim()->GetGUID() != victimGUID) + { + DoModifyThreatPercent(me->getVictim(), -100); + Unit* owner = Unit::GetUnit((*me),victimGUID); + if (owner && owner->isAlive()) + { + me->AddThreat(owner,999999); + AttackStart(owner); + } else if (owner && owner->isDead()) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + } + + if (Link_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOUL_LINK, true); + Link_Timer = 1000; + } else Link_Timer -= diff; + + if (!me->HasAura(AURA_DEMONIC_ALIGNMENT)) + DoCast(me, AURA_DEMONIC_ALIGNMENT, true); + + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLT, false); + ShadowBolt_Timer = 10000; + } else ShadowBolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +//Original Leotheras the Blind AI +struct boss_leotheras_the_blindAI : public ScriptedAI +{ + boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c) + { + c->GetPosition(x,y,z); + pInstance = c->GetInstanceData(); + Demon = 0; + + for (uint8 i = 0; i < 3; ++i)//clear guids + SpellBinderGUID[i] = 0; + } + + ScriptedInstance *pInstance; + + uint32 Whirlwind_Timer; + uint32 ChaosBlast_Timer; + uint32 SwitchToDemon_Timer; + uint32 SwitchToHuman_Timer; + uint32 Berserk_Timer; + uint32 InnerDemons_Timer; + uint32 BanishTimer; + + bool DealDamage; + bool NeedThreatReset; + bool DemonForm; + bool IsFinalForm; + bool EnrageUsed; + float x,y,z; + + uint64 InnderDemon[5]; + uint32 InnerDemon_Count; + uint64 Demon; + uint64 SpellBinderGUID[3]; + + void Reset() + { + CheckChannelers(); + BanishTimer = 1000; + Whirlwind_Timer = 15000; + ChaosBlast_Timer = 1000; + SwitchToDemon_Timer = 45000; + SwitchToHuman_Timer = 60000; + Berserk_Timer = 600000; + InnerDemons_Timer = 30000; + me->SetCanDualWield(true); + DealDamage = true; + DemonForm = false; + IsFinalForm = false; + NeedThreatReset = false; + EnrageUsed = false; + InnerDemon_Count = 0; + me->SetSpeed(MOVE_RUN, 2.0f, true); + me->SetDisplayId(MODEL_NIGHTELF); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + DoCast(me, SPELL_DUAL_WIELD, true); + me->SetCorpseDelay(1000*60*60); + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED); + } + + void CheckChannelers(/*bool DoEvade = true*/) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Creature *add = Unit::GetCreature(*me,SpellBinderGUID[i])) + add->DisappearAndDie(); + + float nx = x; + float ny = y; + float o = 2.4f; + if (i == 0) {nx += 10; ny -= 5; o=2.5f;} + if (i == 1) {nx -= 8; ny -= 7; o=0.9f;} + if (i == 2) {nx -= 3; ny += 9; o=5.0f;} + Creature* binder = me->SummonCreature(MOB_SPELLBINDER,nx,ny,z,o,TEMPSUMMON_DEAD_DESPAWN,0); + if (binder) + SpellBinderGUID[i] = binder->GetGUID(); + + } + } + void MoveInLineOfSight(Unit *who) + { + if (me->HasAura(AURA_BANISH)) + return; + + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius)) + { + // Check first that object is in an angle in front of this one before LoS check + if (me->HasInArc(M_PI/2.0f, who) && me->IsWithinLOSInMap(who)) + { + AttackStart(who); + } + } + } + } + + void StartEvent() + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, IN_PROGRESS); + } + + void CheckBanish() + { + uint8 AliveChannelers = 0; + for (uint8 i = 0; i < 3; ++i) + { + Unit *add = Unit::GetUnit(*me,SpellBinderGUID[i]); + if (add && add->isAlive()) + ++AliveChannelers; + } + + // channelers == 0 remove banish aura + if (AliveChannelers == 0 && me->HasAura(AURA_BANISH)) + { + // removing banish aura + me->RemoveAurasDueToSpell(AURA_BANISH); + + // Leotheras is getting immune again + me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); + + // changing model to bloodelf + me->SetDisplayId(MODEL_NIGHTELF); + + // and reseting equipment + me->LoadEquipment(me->GetEquipmentId()); + + if (pInstance && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + Unit *victim = NULL; + victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); + if (victim) + me->getThreatManager().addThreat(victim, 1); + StartEvent(); + } + } + else if (AliveChannelers != 0 && !me->HasAura(AURA_BANISH)) + { + // channelers != 0 apply banish aura + // removing Leotheras banish immune to apply AURA_BANISH + me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); + DoCast(me, AURA_BANISH); + + // changing model + me->SetDisplayId(MODEL_DEMON); + + // and removing weapons + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + } + } + + //Despawn all Inner Demon summoned + void DespawnDemon() + { + for (uint8 i=0; i<5; ++i) + { + if (InnderDemon[i]) + { + //delete creature + Creature* pCreature = Unit::GetCreature((*me), InnderDemon[i]); + if (pCreature && pCreature->isAlive()) + { + pCreature->ForcedDespawn(); + } + InnderDemon[i] = 0; + } + } + + InnerDemon_Count = 0; + } + + void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core + { + for (uint8 i=0; i<5; ++i) + { + if (InnderDemon[i] > 0) + { + Creature* pUnit = Unit::GetCreature((*me), InnderDemon[i]); + if (pUnit && pUnit->isAlive()) + { + Unit* pUnit_pTarget = Unit::GetUnit(*pUnit, CAST_AI(mob_inner_demonAI, pUnit->AI())->victimGUID); + if (pUnit_pTarget && pUnit_pTarget->isAlive()) + { + pUnit->CastSpell(pUnit_pTarget, SPELL_CONSUMING_MADNESS, true); + DoModifyThreatPercent(pUnit_pTarget, -100); + } + } + } + } + } + + void KilledUnit(Unit * victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + if (DemonForm) + { + DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); + } + else + { + DoScriptText(RAND(SAY_NIGHTELF_SLAY1,SAY_NIGHTELF_SLAY2,SAY_NIGHTELF_SLAY3), me); + } + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + //despawn copy + if (Demon) + { + if (Creature* pDemon = Unit::GetCreature(*me, Demon)) + pDemon->ForcedDespawn(); + } + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + if (me->HasAura(AURA_BANISH)) + return; + + me->LoadEquipment(me->GetEquipmentId()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (me->HasAura(AURA_BANISH) || !UpdateVictim()) + { + if (BanishTimer <= diff) + { + CheckBanish();//no need to check every update tick + BanishTimer = 1000; + } else BanishTimer -= diff; + return; + } + if (me->HasAura(SPELL_WHIRLWIND)) + if (Whirlwind_Timer <= diff) + { + Unit *newTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (newTarget) + { + DoResetThreat(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,newTarget->GetPositionX(),newTarget->GetPositionY(),newTarget->GetPositionZ()); + } + Whirlwind_Timer = 2000; + } else Whirlwind_Timer -= diff; + + // reseting after changing forms and after ending whirlwind + if (NeedThreatReset && !me->HasAura(SPELL_WHIRLWIND)) + { + // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding) + if (DemonForm) + InnerDemons_Timer = 30000; + else + Whirlwind_Timer = 15000; + + NeedThreatReset = false; + DoResetThreat(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + + //Enrage_Timer (10 min) + if (Berserk_Timer < diff && !EnrageUsed) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_BERSERK); + EnrageUsed = true; + } else Berserk_Timer -= diff; + + if (!DemonForm) + { + //Whirldind Timer + if (!me->HasAura(SPELL_WHIRLWIND)) + { + if (Whirlwind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + // while whirlwinding this variable is used to countdown target's change + Whirlwind_Timer = 2000; + NeedThreatReset = true; + } else Whirlwind_Timer -= diff; + } + //Switch_Timer + + if (!IsFinalForm) + if (SwitchToDemon_Timer <= diff) + { + //switch to demon form + me->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0); + me->SetDisplayId(MODEL_DEMON); + DoScriptText(SAY_SWITCH_TO_DEMON, me); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + DemonForm = true; + NeedThreatReset = true; + SwitchToDemon_Timer = 45000; + } else SwitchToDemon_Timer -= diff; + DoMeleeAttackIfReady(); + } + else + { + //ChaosBlast_Timer + if (!me->getVictim()) + return; + if (me->IsWithinDist(me->getVictim(), 30)) + me->StopMoving(); + if (ChaosBlast_Timer <= diff) + { + // will cast only when in range of spell + if (me->IsWithinDist(me->getVictim(), 30)) + { + //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); + int damage = 100; + me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); + } + ChaosBlast_Timer = 3000; + } else ChaosBlast_Timer -= diff; + //Summon Inner Demon + if (InnerDemons_Timer <= diff) + { + std::list& ThreatList = me->getThreatManager().getThreatList(); + std::vector TargetList; + for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) + { + Unit *tempTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->getVictim()->GetGUID() && TargetList.size()<5) + TargetList.push_back(tempTarget); + } + //SpellEntry *spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); + for (std::vector::const_iterator itr = TargetList.begin(); itr != TargetList.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive()) + { + Creature * demon = me->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (demon) + { + demon->AI()->AttackStart((*itr)); + CAST_AI(mob_inner_demonAI, demon->AI())->victimGUID = (*itr)->GetGUID(); + + (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); + + if (InnerDemon_Count > 4) + InnerDemon_Count = 0; + + //Safe storing of creatures + InnderDemon[InnerDemon_Count] = demon->GetGUID(); + + //Update demon count + ++InnerDemon_Count; + } + } + } + DoScriptText(SAY_INNER_DEMONS, me); + + InnerDemons_Timer = 999999; + } else InnerDemons_Timer -= diff; + + //Switch_Timer + if (SwitchToHuman_Timer <= diff) + { + //switch to nightelf form + me->SetDisplayId(MODEL_NIGHTELF); + me->LoadEquipment(me->GetEquipmentId()); + + CastConsumingMadness(); + DespawnDemon(); + + DemonForm = false; + NeedThreatReset = true; + + SwitchToHuman_Timer = 60000; + } else SwitchToHuman_Timer -= diff; + } + + if (!IsFinalForm && (me->GetHealth()*100 / me->GetMaxHealth()) < 15) + { + //at this point he divides himself in two parts + CastConsumingMadness(); + DespawnDemon(); + Creature *Copy = NULL; + Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000); + if (Copy) + { + Demon = Copy->GetGUID(); + if (me->getVictim()) + Copy->AI()->AttackStart(me->getVictim()); + } + //set nightelf final form + IsFinalForm = true; + DemonForm = false; + + DoScriptText(SAY_FINAL_FORM, me); + me->SetDisplayId(MODEL_NIGHTELF); + me->LoadEquipment(me->GetEquipmentId()); + } + } +}; + +//Leotheras the Blind Demon Form AI +struct boss_leotheras_the_blind_demonformAI : public ScriptedAI +{ + boss_leotheras_the_blind_demonformAI(Creature *c) : ScriptedAI(c) {} + + uint32 ChaosBlast_Timer; + bool DealDamage; + + void Reset() + { + ChaosBlast_Timer = 1000; + DealDamage = true; + } + + void StartEvent() + { + DoScriptText(SAY_FREE, me); + } + + void KilledUnit(Unit * victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) + DoCast(me, 8149, true); + } + + void EnterCombat(Unit * /*who*/) + { + StartEvent(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + //ChaosBlast_Timer + if (me->IsWithinDist(me->getVictim(), 30)) + me->StopMoving(); + + if (ChaosBlast_Timer <= diff) + { + // will cast only when in range od spell + if (me->IsWithinDist(me->getVictim(), 30)) + { + //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); + int damage = 100; + me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); + ChaosBlast_Timer = 3000; + } + } else ChaosBlast_Timer -= diff; + + //Do NOT deal any melee damage to the target. + } +}; +struct mob_greyheart_spellbinderAI : public ScriptedAI +{ + mob_greyheart_spellbinderAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + leotherasGUID = 0; + AddedBanish = false; + } + + ScriptedInstance *pInstance; + + uint64 leotherasGUID; + + uint32 Mindblast_Timer; + uint32 Earthshock_Timer; + + bool AddedBanish; + + void Reset() + { + Mindblast_Timer = 3000 + rand()%5000; + Earthshock_Timer = 5000 + rand()%5000; + + if (pInstance) + { + pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, 0); + Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); + if (leotheras && leotheras->isAlive()) + CAST_AI(boss_leotheras_the_blindAI, leotheras->AI())->CheckChannelers(/*false*/); + } + } + + void EnterCombat(Unit * who) + { + me->InterruptNonMeleeSpells(false); + if (pInstance) + pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID()); + } + + void JustRespawned() + { + AddedBanish = false; + Reset(); + } + + void CastChanneling() + { + if (!me->isInCombat() && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + { + if (leotherasGUID) + { + Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); + if (leotheras && leotheras->isAlive()) + DoCast(leotheras, BANISH_BEAM); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance) + { + if (!leotherasGUID) + leotherasGUID = pInstance->GetData64(DATA_LEOTHERAS); + + if (!me->isInCombat() && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + Unit *victim = NULL; + victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); + if (victim) + AttackStart(victim); + } + } + + if (!UpdateVictim()) + { + CastChanneling(); + return; + } + + if (pInstance && !pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + EnterEvadeMode(); + return; + } + + if (Mindblast_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (pTarget)DoCast(pTarget, SPELL_MINDBLAST); + + Mindblast_Timer = 10000 + rand()%5000; + } else Mindblast_Timer -= diff; + + if (Earthshock_Timer <= diff) + { + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) + { + if (Player* i_pl = itr->getSource()) + { + bool isCasting = false; + for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) + if (i_pl->GetCurrentSpell(i)) + isCasting = true; + + if (isCasting) + { + DoCast(i_pl, SPELL_EARTHSHOCK); + break; + } + } + } + Earthshock_Timer = 8000 + rand()%7000; + } else Earthshock_Timer -= diff; + DoMeleeAttackIfReady(); + } + + void JustDied(Unit * /*killer*/) {} +}; +CreatureAI* GetAI_boss_leotheras_the_blind(Creature* pCreature) +{ + return new boss_leotheras_the_blindAI (pCreature); +} + +CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature* pCreature) +{ + return new boss_leotheras_the_blind_demonformAI (pCreature); +} + +CreatureAI* GetAI_mob_greyheart_spellbinder(Creature* pCreature) +{ + return new mob_greyheart_spellbinderAI (pCreature); +} + +CreatureAI* GetAI_mob_inner_demon(Creature* pCreature) +{ + return new mob_inner_demonAI (pCreature); +} +void AddSC_boss_leotheras_the_blind() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_leotheras_the_blind"; + newscript->GetAI = &GetAI_boss_leotheras_the_blind; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_leotheras_the_blind_demonform"; + newscript->GetAI = &GetAI_boss_leotheras_the_blind_demonform; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_greyheart_spellbinder"; + newscript->GetAI = &GetAI_mob_greyheart_spellbinder; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_inner_demon"; + newscript->GetAI = &GetAI_mob_inner_demon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp new file mode 100644 index 00000000000..b1c0c10bcce --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp @@ -0,0 +1,458 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_the_lurker_below +SD%Complete: 80 +SDComment: Coilfang Frenzy, find out how could we fishing in the strangepool +SDCategory: The Lurker Below +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedSimpleAI.h" +#include "Spell.h" + +#define SPELL_SPOUT 37433 +#define SPELL_SPOUT_ANIM 42835 +#define SPELL_SPOUT_BREATH 37431 +#define SPELL_KNOCKBACK 19813 +#define SPELL_GEYSER 37478 +#define SPELL_WHIRL 37660 +#define SPELL_WATERBOLT 37138 +#define SPELL_SUBMERGE 37550 +#define SPELL_EMERGE 20568 + +#define EMOTE_SPOUT "The Lurker Below takes a deep breath." + +#define SPOUT_DIST 100 + +#define MOB_COILFANG_GUARDIAN 21873 +#define MOB_COILFANG_AMBUSHER 21865 + +//Ambusher spells +#define SPELL_SPREAD_SHOT 37790 +#define SPELL_SHOOT 37770 + +//Guardian spells +#define SPELL_ARCINGSMASH 38761 // Wrong SpellId. Can't find the right one. +#define SPELL_HAMSTRING 26211 + +float AddPos[9][3] = +{ + {2.8553810, -459.823914, -19.182686}, //MOVE_AMBUSHER_1 X, Y, Z + {12.400000, -466.042267, -19.182686}, //MOVE_AMBUSHER_2 X, Y, Z + {51.366653, -460.836060, -19.182686}, //MOVE_AMBUSHER_3 X, Y, Z + {62.597980, -457.433044, -19.182686}, //MOVE_AMBUSHER_4 X, Y, Z + {77.607452, -384.302765, -19.182686}, //MOVE_AMBUSHER_5 X, Y, Z + {63.897900, -378.984924, -19.182686}, //MOVE_AMBUSHER_6 X, Y, Z + {34.447250, -387.333618, -19.182686}, //MOVE_GUARDIAN_1 X, Y, Z + {14.388216, -423.468018, -19.625271}, //MOVE_GUARDIAN_2 X, Y, Z + {42.471519, -445.115295, -19.769423} //MOVE_GUARDIAN_3 X, Y, Z +}; + +struct boss_the_lurker_belowAI : public Scripted_NoMovementAI +{ + boss_the_lurker_belowAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + SpellEntry *TempSpell = GET_SPELL(SPELL_SPOUT_ANIM); + if (TempSpell) + { + TempSpell->Effect[0] = 0;//remove all spell effect, only anim is needed + TempSpell->Effect[1] = 0; + TempSpell->Effect[2] = 0; + } + } + + ScriptedInstance* pInstance; + SummonList Summons; + + bool Spawned; + bool Submerged; + bool InRange; + bool CanStartEvent; + uint32 RotTimer; + uint32 SpoutAnimTimer; + uint32 WaterboltTimer; + uint32 SpoutTimer; + uint32 WhirlTimer; + uint32 PhaseTimer; + uint32 GeyserTimer; + uint32 CheckTimer; + uint32 WaitTimer; + uint32 WaitTimer2; + + bool CheckCanStart()//check if players fished + { + if (pInstance && pInstance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) + return false; + return true; + } + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); + SpoutAnimTimer = 1000; + RotTimer = 0; + WaterboltTimer = 15000;//give time to get in range when fight starts + SpoutTimer = 45000; + WhirlTimer = 18000;//after avery spout + PhaseTimer = 120000; + GeyserTimer = rand()%5000 + 15000; + CheckTimer = 15000;//give time to get in range when fight starts + WaitTimer = 60000;//never reached + WaitTimer2 = 60000;//never reached + + Submerged = true;//will be false at combat start + Spawned = false; + InRange = false; + CanStartEvent = false; + + Summons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_THELURKERBELOWEVENT, NOT_STARTED); + pInstance->SetData(DATA_STRANGE_POOL, NOT_STARTED); + } + DoCast(me, SPELL_SUBMERGE);//submerge anim + me->SetVisibility(VISIBILITY_OFF);//we start invis under water, submerged + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_THELURKERBELOWEVENT, DONE); + + Summons.DespawnAll(); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + pInstance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS); + Scripted_NoMovementAI::EnterCombat(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (!CanStartEvent)//boss is invisible, don't attack + return; + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius)) + { + AttackStart(who); + } + } + } + + void MovementInform(uint32 type, uint32 /*id*/) + { + if (type == ROTATE_MOTION_TYPE) + me->SetReactState(REACT_AGGRESSIVE); + } + + void UpdateAI(const uint32 diff) + { + if (!CanStartEvent)//boss is invisible, don't attack + { + if (CheckCanStart()) + { + if (Submerged) + { + me->SetVisibility(VISIBILITY_ON); + Submerged = false; + WaitTimer2 = 500; + } + if (!Submerged && WaitTimer2 <= diff)//wait 500ms before emerge anim + { + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); + DoCast(me, SPELL_EMERGE, false); + WaitTimer2 = 60000;//never reached + WaitTimer = 3000; + } else WaitTimer2 -= diff; + + if (WaitTimer <= diff)//wait 3secs for emerge anim, then attack + { + WaitTimer = 3000; + CanStartEvent=true;//fresh fished from pool + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } else WaitTimer -= diff; + } + return; + } + + if (me->getThreatManager().getThreatList().empty())//check if should evade + { + if (me->isInCombat()) + EnterEvadeMode(); + return; + } + if (!Submerged) + { + if (PhaseTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUBMERGE); + PhaseTimer = 60000;//60secs submerged + Submerged = true; + } else PhaseTimer-=diff; + + if (SpoutTimer <= diff) + { + me->MonsterTextEmote(EMOTE_SPOUT,0,true); + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MoveRotate(20000, rand()%2 ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); + SpoutTimer = 45000; + WhirlTimer = 20000;//whirl directly after spout + RotTimer = 20000; + return; + } else SpoutTimer -= diff; + + //Whirl directly after a Spout and at random times + if (WhirlTimer <= diff) + { + WhirlTimer = 18000; + DoCast(me, SPELL_WHIRL); + } else WhirlTimer -= diff; + + if (CheckTimer <= diff)//check if there are players in melee range + { + InRange = false; + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (me->IsWithinMeleeRange(i->getSource())) + InRange = true; + } + } + CheckTimer = 2000; + } else CheckTimer -= diff; + + if (RotTimer) + { + Map* pMap = me->GetMap(); + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->isAlive() && me->HasInArc((double)diff/20000*(double)M_PI*2,i->getSource()) && me->IsWithinDist(i->getSource(), SPOUT_DIST) && !i->getSource()->IsInWater()) + DoCast(i->getSource(), SPELL_SPOUT, true);//only knock back palyers in arc, in 100yards, not in water + } + } + + if (SpoutAnimTimer <= diff) + { + DoCast(me, SPELL_SPOUT_ANIM, true); + SpoutAnimTimer = 1000; + } else SpoutAnimTimer -= diff; + + if (RotTimer <= diff) + { + RotTimer = 0; + } else RotTimer -= diff; + return; + } + + if (GeyserTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (!pTarget && me->getVictim()) + pTarget = me->getVictim(); + if (pTarget) + DoCast(pTarget, SPELL_GEYSER, true); + GeyserTimer = rand()%5000 + 15000; + } else GeyserTimer -= diff; + + if (!InRange)//if on players in melee range cast Waterbolt + { + if (WaterboltTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget && me->getVictim()) + pTarget = me->getVictim(); + if (pTarget) + DoCast(pTarget, SPELL_WATERBOLT, true); + WaterboltTimer = 3000; + } else WaterboltTimer -= diff; + } + + if (!UpdateCombatState()) + return; + + DoMeleeAttackIfReady(); + + }else//submerged + { + if (PhaseTimer <= diff) + { + Submerged = false; + me->InterruptNonMeleeSpells(false);//shouldn't be any + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); + DoCast(me, SPELL_EMERGE, true); + Spawned = false; + SpoutTimer = 3000; // directly cast Spout after emerging! + PhaseTimer = 120000; + return; + } else PhaseTimer-=diff; + + if (me->getThreatManager().getThreatList().empty())//check if should evade + { + EnterEvadeMode(); + return; + } + if (!me->isInCombat()) + DoZoneInCombat(); + + if (!Spawned) + { + me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + //spawn adds + for (uint8 i = 0; i < 9; ++i) + { + Creature* Summoned; + if (i < 6) + Summoned = me->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + else Summoned = me->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (Summoned) + Summons.Summon(Summoned); + } + Spawned = true; + } + } + } + }; + +CreatureAI* GetAI_mob_coilfang_guardian(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_ARCINGSMASH; + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].First_Cast = 5000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->Spell[1].Enabled = true; + ai->Spell[1].Spell_Id = SPELL_HAMSTRING; + ai->Spell[1].Cooldown = 10000; + ai->Spell[1].First_Cast = 2000; + ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; + + return ai; +} + +struct mob_coilfang_ambusherAI : public Scripted_NoMovementAI +{ + mob_coilfang_ambusherAI(Creature *c) : Scripted_NoMovementAI(c) + { + SpellEntry *TempSpell = GET_SPELL(SPELL_SHOOT); + if (TempSpell) + TempSpell->Effect[0] = 2;//change spell effect from weapon % dmg to simple phisical dmg + } + + uint32 MultiShotTimer; + uint32 ShootBowTimer; + + void Reset() + { + MultiShotTimer = 10000; + ShootBowTimer = 4000; + + } + + void EnterCombat(Unit * /*who*/) + { + + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who) && me->IsWithinDistInMap(who, 45)) + { + AttackStart(who); + } + } + + void UpdateAI(const uint32 diff) + { + if (MultiShotTimer <= diff) + { + if (me->getVictim()) + DoCast(me->getVictim(), SPELL_SPREAD_SHOT, true); + + MultiShotTimer = 10000+rand()%10000; + ShootBowTimer += 1500;//add global cooldown + } else MultiShotTimer -= diff; + + if (ShootBowTimer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + int bp0 = 1100; + if (pTarget) + me->CastCustomSpell(pTarget,SPELL_SHOOT,&bp0,NULL,NULL,true); + ShootBowTimer = 4000+rand()%5000; + MultiShotTimer += 1500;//add global cooldown + } else ShootBowTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_coilfang_ambusher(Creature* pCreature) +{ + return new mob_coilfang_ambusherAI (pCreature); +} + +CreatureAI* GetAI_boss_the_lurker_below(Creature* pCreature) +{ + return new boss_the_lurker_belowAI (pCreature); +} + +void AddSC_boss_the_lurker_below() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_lurker_below"; + newscript->GetAI = &GetAI_boss_the_lurker_below; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_guardian"; + newscript->GetAI = &GetAI_mob_coilfang_guardian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_ambusher"; + newscript->GetAI = &GetAI_mob_coilfang_ambusher; + newscript->RegisterSelf(); +} + + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp new file mode 100644 index 00000000000..14c87aee141 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp @@ -0,0 +1,369 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Morogrim_Tidewalker +SD%Complete: 90 +SDComment: Water globules don't explode properly, remove hacks +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define SAY_AGGRO -1548030 +#define SAY_SUMMON1 -1548031 +#define SAY_SUMMON2 -1548032 +#define SAY_SUMMON_BUBL1 -1548033 +#define SAY_SUMMON_BUBL2 -1548034 +#define SAY_SLAY1 -1548035 +#define SAY_SLAY2 -1548036 +#define SAY_SLAY3 -1548037 +#define SAY_DEATH -1548038 +#define EMOTE_WATERY_GRAVE -1548039 +#define EMOTE_EARTHQUAKE -1548040 +#define EMOTE_WATERY_GLOBULES -1548041 + +#define SPELL_TIDAL_WAVE 37730 +#define SPELL_WATERY_GRAVE 38049 +#define SPELL_EARTHQUAKE 37764 +#define SPELL_WATERY_GRAVE_EXPLOSION 37852 + +#define WATERY_GRAVE_X1 334.64 +#define WATERY_GRAVE_Y1 -728.89 +#define WATERY_GRAVE_Z1 -14.42 +#define WATERY_GRAVE_X2 365.51 +#define WATERY_GRAVE_Y2 -737.14 +#define WATERY_GRAVE_Z2 -14.44 +#define WATERY_GRAVE_X3 366.19 +#define WATERY_GRAVE_Y3 -709.59 +#define WATERY_GRAVE_Z3 -14.36 +#define WATERY_GRAVE_X4 372.93 +#define WATERY_GRAVE_Y4 -690.96 +#define WATERY_GRAVE_Z4 -14.44 + +#define SPELL_WATERY_GRAVE_1 38023 +#define SPELL_WATERY_GRAVE_2 38024 +#define SPELL_WATERY_GRAVE_3 38025 +#define SPELL_WATERY_GRAVE_4 37850 + +#define SPELL_SUMMON_WATER_GLOBULE_1 37854 +#define SPELL_SUMMON_WATER_GLOBULE_2 37858 +#define SPELL_SUMMON_WATER_GLOBULE_3 37860 +#define SPELL_SUMMON_WATER_GLOBULE_4 37861 + +/*#define SPELL_SUMMON_MURLOC_A6 39813 +#define SPELL_SUMMON_MURLOC_A7 39814 +#define SPELL_SUMMON_MURLOC_A8 39815 +#define SPELL_SUMMON_MURLOC_A9 39816 +#define SPELL_SUMMON_MURLOC_A10 39817 + +#define SPELL_SUMMON_MURLOC_B6 39818 +#define SPELL_SUMMON_MURLOC_B7 39819 +#define SPELL_SUMMON_MURLOC_B8 39820 +#define SPELL_SUMMON_MURLOC_B9 39821 +#define SPELL_SUMMON_MURLOC_B10 39822*/ + +float MurlocCords[10][5] = +{ + {21920, 424.36, -715.4, -7.14, 0.124}, + {21920, 425.13, -719.3, -7.14, 0.124}, + {21920, 425.05, -724.23, -7.14, 0.124}, + {21920, 424.91, -728.68, -7.14, 0.124}, + {21920, 424.84, -732.18, -7.14, 0.124}, + {21920, 321.05, -734.2, -13.15, 0.124}, + {21920, 321.05, -729.4, -13.15, 0.124}, + {21920, 321.05, -724.03, -13.15, 0.124}, + {21920, 321.05, -718.73, -13.15, 0.124}, + {21920, 321.05, -714.24, -13.15, 0.124} +}; + +//Creatures +#define WATER_GLOBULE 21913 +#define TIDEWALKER_LURKER 21920 + +//Morogrim Tidewalker AI +struct boss_morogrim_tidewalkerAI : public ScriptedAI +{ + boss_morogrim_tidewalkerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + Map::PlayerList const *PlayerList; + + uint32 TidalWave_Timer; + uint32 WateryGrave_Timer; + uint32 Earthquake_Timer; + uint32 WateryGlobules_Timer; + uint32 globulespell[4]; + int8 Playercount; + int8 counter; + + bool Earthquake; + bool Phase2; + + void Reset() + { + TidalWave_Timer = 10000; + WateryGrave_Timer = 30000; + Earthquake_Timer = 40000; + WateryGlobules_Timer = 0; + globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1; + globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2; + globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3; + globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4; + + Earthquake = false; + Phase2 = false; + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); + } + + void StartEvent() + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + PlayerList = &me->GetMap()->GetPlayers(); + Playercount = PlayerList->getSize(); + StartEvent(); + } + + void ApplyWateryGrave(Unit* pPlayer, uint8 i) + { + switch(i) + { + case 0: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_1, true); break; + case 1: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_2, true); break; + case 2: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_3, true); break; + case 3: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_4, true); break; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Earthquake_Timer + if (Earthquake_Timer <= diff) + { + if (!Earthquake) + { + DoCast(me->getVictim(), SPELL_EARTHQUAKE); + Earthquake = true; + Earthquake_Timer = 10000; + } + else + { + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + + for (uint8 i = 0; i < 10; ++i) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + Creature* Murloc = me->SummonCreature(MurlocCords[i][0],MurlocCords[i][1],MurlocCords[i][2],MurlocCords[i][3],MurlocCords[i][4], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); + if (pTarget && Murloc) + Murloc->AI()->AttackStart(pTarget); + } + DoScriptText(EMOTE_EARTHQUAKE, me); + Earthquake = false; + Earthquake_Timer = 40000+rand()%5000; + } + } else Earthquake_Timer -= diff; + + //TidalWave_Timer + if (TidalWave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIDAL_WAVE); + TidalWave_Timer = 20000; + } else TidalWave_Timer -= diff; + + if (!Phase2) + { + //WateryGrave_Timer + if (WateryGrave_Timer <= diff) + { + //Teleport 4 players under the waterfalls + Unit *pTarget; + using std::set; + setlist; + set::const_iterator itr; + for (uint8 i = 0; i < 4; ++i) + { + counter = 0; + do + { + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only + if (counter < Playercount) + break; + if (pTarget) + itr = list.find(pTarget->GetGUID()); + ++counter; + } while (itr != list.end()); + + if (pTarget) + { + list.insert(pTarget->GetGUID()); + ApplyWateryGrave(pTarget, i); + } + } + + DoScriptText(RAND(SAY_SUMMON_BUBL1,SAY_SUMMON_BUBL2), me); + + DoScriptText(EMOTE_WATERY_GRAVE, me); + WateryGrave_Timer = 30000; + } else WateryGrave_Timer -= diff; + + //Start Phase2 + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) + Phase2 = true; + } + else + { + //WateryGlobules_Timer + if (WateryGlobules_Timer <= diff) + { + Unit* pGlobuleTarget; + using std::set; + setglobulelist; + set::const_iterator itr; + for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD + { + counter = 0; + do { + pGlobuleTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); + if (pGlobuleTarget) + itr = globulelist.find(pGlobuleTarget->GetGUID()); + if (counter > Playercount) + break; + ++counter; + } while (itr != globulelist.end()); + if (pGlobuleTarget) + globulelist.insert(pGlobuleTarget->GetGUID()); + pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true); + } + DoScriptText(EMOTE_WATERY_GLOBULES, me); + WateryGlobules_Timer = 25000; + } else WateryGlobules_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +//Water Globule AI +#define SPELL_GLOBULE_EXPLOSION 37871 + +struct mob_water_globuleAI : public ScriptedAI +{ + mob_water_globuleAI(Creature *c) : ScriptedAI(c) {} + + uint32 Check_Timer; + + void Reset() + { + Check_Timer = 1000; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + //no attack radius check - it attacks the first target that moves in his los + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Check_Timer <= diff) + { + if (me->IsWithinDistInMap(me->getVictim(), 5)) + { + DoCast(me->getVictim(), SPELL_GLOBULE_EXPLOSION); + + //despawn + me->ForcedDespawn(); + return; + } + Check_Timer = 500; + } else Check_Timer -= diff; + + //do NOT deal any melee damage to the target. + } +}; + +CreatureAI* GetAI_boss_morogrim_tidewalker(Creature* pCreature) +{ + return new boss_morogrim_tidewalkerAI (pCreature); +} +CreatureAI* GetAI_mob_water_globule(Creature* pCreature) +{ + return new mob_water_globuleAI (pCreature); +} + +void AddSC_boss_morogrim_tidewalker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_morogrim_tidewalker"; + newscript->GetAI = &GetAI_boss_morogrim_tidewalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_water_globule"; + newscript->GetAI = &GetAI_mob_water_globule; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp new file mode 100644 index 00000000000..c80afae15c7 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp @@ -0,0 +1,398 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Serpent_Shrine +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Serpent Shrine Scripts +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define MAX_ENCOUNTER 6 +#define SPELL_SCALDINGWATER 37284 +#define MOB_COILFANG_FRENZY 21508 +#define TRASHMOB_COILFANG_PRIESTESS 21220 //6*2 +#define TRASHMOB_COILFANG_SHATTERER 21301 //6*3 + +#define MIN_KILLS 30 + +//NOTE: there are 6 platforms +//there should be 3 shatterers and 2 priestess on all platforms, total of 30 elites, else it won't work! +//delete all other elites not on platforms! these mobs should only be on those platforms nowhere else. + +/* Serpentshrine cavern encounters: +0 - Hydross The Unstable event +1 - Leotheras The Blind Event +2 - The Lurker Below Event +3 - Fathom-Lord Karathress Event +4 - Morogrim Tidewalker Event +5 - Lady Vashj Event +*/ + +bool GOHello_go_bridge_console(Player* /*pPlayer*/, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + + if (!pInstance) + return false; + + if (pInstance) + pInstance->SetData(DATA_CONTROL_CONSOLE, DONE); + + return true; +} + +struct instance_serpentshrine_cavern : public ScriptedInstance +{ + instance_serpentshrine_cavern(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 LurkerBelow; + uint64 Sharkkis; + uint64 Tidalvess; + uint64 Caribdis; + uint64 LadyVashj; + uint64 Karathress; + uint64 KarathressEvent_Starter; + uint64 LeotherasTheBlind; + uint64 LeotherasEventStarter; + + uint64 ControlConsole; + uint64 BridgePart[3]; + uint32 StrangePool; + uint32 FishingTimer; + uint32 LurkerSubEvent; + uint32 WaterCheckTimer; + uint32 FrenzySpawnTimer; + uint32 Water; + uint32 TrashCount; + + bool ShieldGeneratorDeactivated[4]; + uint32 m_auiEncounter[MAX_ENCOUNTER]; + bool DoSpawnFrenzy; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + LurkerBelow = 0; + Sharkkis = 0; + Tidalvess = 0; + Caribdis = 0; + LadyVashj = 0; + Karathress = 0; + KarathressEvent_Starter = 0; + LeotherasTheBlind = 0; + LeotherasEventStarter = 0; + + ControlConsole = 0; + BridgePart[0] = 0; + BridgePart[1] = 0; + BridgePart[2] = 0; + StrangePool = 0; + Water = WATERSTATE_FRENZY; + + ShieldGeneratorDeactivated[0] = false; + ShieldGeneratorDeactivated[1] = false; + ShieldGeneratorDeactivated[2] = false; + ShieldGeneratorDeactivated[3] = false; + FishingTimer = 1000; + LurkerSubEvent = 0; + WaterCheckTimer = 500; + FrenzySpawnTimer = 2000; + DoSpawnFrenzy = false; + TrashCount = 0; + + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void Update (uint32 diff) + { + //Lurker Fishing event + if (LurkerSubEvent == LURKER_FISHING) + { + if (FishingTimer <= diff) + { + LurkerSubEvent = LURKER_HOOKED; + SetData(DATA_STRANGE_POOL, IN_PROGRESS);//just fished, signal Lurker script to emerge and start fight, we use IN_PROGRESS so it won't get saved and lurker will be alway invis at start if server restarted + } else FishingTimer -= diff; + } + //Water checks + if (WaterCheckTimer <= diff) + { + if (TrashCount >= MIN_KILLS) + Water = WATERSTATE_SCALDING; + else + Water = WATERSTATE_FRENZY; + + Map::PlayerList const &PlayerList = instance->GetPlayers(); + if (PlayerList.isEmpty()) + return; + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isAlive() && /*i->getSource()->GetPositionZ() <= -21.434931f*/pPlayer->IsInWater()) + { + if (Water == WATERSTATE_SCALDING) + { + + if (!pPlayer->HasAura(SPELL_SCALDINGWATER)) + { + pPlayer->CastSpell(pPlayer, SPELL_SCALDINGWATER,true); + } + } else if (Water == WATERSTATE_FRENZY) + { + //spawn frenzy + if (DoSpawnFrenzy) + { + if (Creature* frenzy = pPlayer->SummonCreature(MOB_COILFANG_FRENZY,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ(),pPlayer->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,2000)) + { + frenzy->Attack(pPlayer,false); + frenzy->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); + } + DoSpawnFrenzy = false; + } + } + } + if (!pPlayer->IsInWater()) + pPlayer->RemoveAurasDueToSpell(SPELL_SCALDINGWATER); + } + + } + WaterCheckTimer = 500;//remove stress from core + } else WaterCheckTimer -= diff; + if (FrenzySpawnTimer <= diff) + { + DoSpawnFrenzy = true; + FrenzySpawnTimer = 2000; + } else FrenzySpawnTimer -= diff; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 184568: + ControlConsole = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184203: + BridgePart[0] = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184204: + BridgePart[1] = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184205: + BridgePart[2] = pGo->GetGUID(); + pGo->setActive(true); + break; + case GAMEOBJECT_FISHINGNODE_ENTRY://no way checking if fish is hooked, so we create a timed event + if (LurkerSubEvent == LURKER_NOT_STARTED) + { + FishingTimer = 10000+rand()%30000;//random time before lurker emerges + LurkerSubEvent = LURKER_FISHING; + } + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 21212: LadyVashj = pCreature->GetGUID(); break; + case 21214: Karathress = pCreature->GetGUID(); break; + case 21966: Sharkkis = pCreature->GetGUID(); break; + case 21217: LurkerBelow = pCreature->GetGUID(); break; + case 21965: Tidalvess = pCreature->GetGUID(); break; + case 21964: Caribdis = pCreature->GetGUID(); break; + case 21215: LeotherasTheBlind = pCreature->GetGUID(); break; + /*case TRASHMOB_COILFANG_PRIESTESS: + case TRASHMOB_COILFANG_SHATTERER: + if (pCreature->isAlive()) + ++TrashCount; + break;*/ + } + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_KARATHRESSEVENT_STARTER) + KarathressEvent_Starter = data; + if (type == DATA_LEOTHERAS_EVENT_STARTER) + LeotherasEventStarter = data; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_THELURKERBELOW: return LurkerBelow; + case DATA_SHARKKIS: return Sharkkis; + case DATA_TIDALVESS: return Tidalvess; + case DATA_CARIBDIS: return Caribdis; + case DATA_LADYVASHJ: return LadyVashj; + case DATA_KARATHRESS: return Karathress; + case DATA_KARATHRESSEVENT_STARTER: return KarathressEvent_Starter; + case DATA_LEOTHERAS: return LeotherasTheBlind; + case DATA_LEOTHERAS_EVENT_STARTER: return LeotherasEventStarter; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_STRANGE_POOL: + { + StrangePool = data; + if (data == NOT_STARTED) + LurkerSubEvent = LURKER_NOT_STARTED; + } + break; + case DATA_CONTROL_CONSOLE: + if (data == DONE) + { + HandleGameObject(BridgePart[0], true); + HandleGameObject(BridgePart[0], true); + HandleGameObject(BridgePart[0], true); + } + ControlConsole = data;break; + case DATA_TRASH : + { + if (data == 1 && TrashCount < MIN_KILLS) + ++TrashCount;//+1 died + SaveToDB(); + break; + } + case DATA_WATER : Water = data;break; + case DATA_HYDROSSTHEUNSTABLEEVENT: m_auiEncounter[0] = data; break; + case DATA_LEOTHERASTHEBLINDEVENT: m_auiEncounter[1] = data; break; + case DATA_THELURKERBELOWEVENT: m_auiEncounter[2] = data; break; + case DATA_KARATHRESSEVENT: m_auiEncounter[3] = data; break; + case DATA_MOROGRIMTIDEWALKEREVENT: m_auiEncounter[4] = data; break; + //Lady Vashj + case DATA_LADYVASHJEVENT: + if (data == NOT_STARTED) + { + ShieldGeneratorDeactivated[0] = false; + ShieldGeneratorDeactivated[1] = false; + ShieldGeneratorDeactivated[2] = false; + ShieldGeneratorDeactivated[3] = false; + } + m_auiEncounter[5] = data; break; + case DATA_SHIELDGENERATOR1:ShieldGeneratorDeactivated[0] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR2:ShieldGeneratorDeactivated[1] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR3:ShieldGeneratorDeactivated[2] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR4:ShieldGeneratorDeactivated[3] = (data) ? true : false; break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_HYDROSSTHEUNSTABLEEVENT: return m_auiEncounter[0]; + case DATA_LEOTHERASTHEBLINDEVENT: return m_auiEncounter[1]; + case DATA_THELURKERBELOWEVENT: return m_auiEncounter[2]; + case DATA_KARATHRESSEVENT: return m_auiEncounter[3]; + case DATA_MOROGRIMTIDEWALKEREVENT: return m_auiEncounter[4]; + //Lady Vashj + case DATA_LADYVASHJEVENT: return m_auiEncounter[5]; + case DATA_SHIELDGENERATOR1: return ShieldGeneratorDeactivated[0]; + case DATA_SHIELDGENERATOR2: return ShieldGeneratorDeactivated[1]; + case DATA_SHIELDGENERATOR3: return ShieldGeneratorDeactivated[2]; + case DATA_SHIELDGENERATOR4: return ShieldGeneratorDeactivated[3]; + case DATA_CANSTARTPHASE3: + if (ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3])return 1;break; + case DATA_STRANGE_POOL: return StrangePool; + case DATA_WATER: return Water; + } + return 0; + } + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << TrashCount; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> TrashCount; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_serpentshrine_cavern(Map* pMap) +{ + return new instance_serpentshrine_cavern(pMap); +} + +void AddSC_instance_serpentshrine_cavern() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_serpent_shrine"; + newscript->GetInstanceData = &GetInstanceData_instance_serpentshrine_cavern; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_bridge_console"; + newscript->pGOHello = &GOHello_go_bridge_console; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h new file mode 100644 index 00000000000..adfa39dc7e0 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SERPENT_SHRINE_H +#define DEF_SERPENT_SHRINE_H +enum LurkerEventState +{ + LURKER_NOT_STARTED = 0, + LURKER_FISHING = 1, + LURKER_HOOKED = 2 +}; +enum WaterEventState +{ + WATERSTATE_NONE = 0, + WATERSTATE_FRENZY = 1, + WATERSTATE_SCALDING = 2 +}; +#define DATA_CANSTARTPHASE3 1 +#define DATA_CARIBDIS 2 +#define DATA_HYDROSSTHEUNSTABLEEVENT 3 +#define DATA_KARATHRESS 4 +#define DATA_KARATHRESSEVENT 5 +#define DATA_KARATHRESSEVENT_STARTER 6 +#define DATA_LADYVASHJ 7 +#define DATA_LADYVASHJEVENT 8 +#define DATA_LEOTHERASTHEBLINDEVENT 9 +#define DATA_MOROGRIMTIDEWALKEREVENT 10 +#define DATA_SHARKKIS 11 +#define DATA_SHIELDGENERATOR1 12 +#define DATA_SHIELDGENERATOR2 13 +#define DATA_SHIELDGENERATOR3 14 +#define DATA_SHIELDGENERATOR4 15 +#define DATA_THELURKERBELOW 16 +#define DATA_THELURKERBELOWEVENT 17 +#define DATA_TIDALVESS 18 +#define DATA_FATHOMLORDKARATHRESSEVENT 19 +#define DATA_LEOTHERAS 20 +#define DATA_LEOTHERAS_EVENT_STARTER 21 +#define DATA_CONTROL_CONSOLE 22 +#define DATA_STRANGE_POOL 23 +#define DATA_WATER 24 +#define DATA_TRASH 25 +#endif + diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp new file mode 100644 index 00000000000..8e1b438bdc5 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp @@ -0,0 +1,187 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hydromancer_Thespia +SD%Complete: 80 +SDComment: Needs additional adjustments (when instance script is adjusted) +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +/* ContentData +boss_hydromancer_thespia +mob_coilfang_waterelemental +EndContentData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_SUMMON -1545000 +#define SAY_AGGRO_1 -1545001 +#define SAY_AGGRO_2 -1545002 +#define SAY_AGGRO_3 -1545003 +#define SAY_SLAY_1 -1545004 +#define SAY_SLAY_2 -1545005 +#define SAY_DEAD -1545006 + +#define SPELL_LIGHTNING_CLOUD 25033 +#define SPELL_LUNG_BURST 31481 +#define SPELL_ENVELOPING_WINDS 31718 + +struct boss_thespiaAI : public ScriptedAI +{ + boss_thespiaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 LightningCloud_Timer; + uint32 LungBurst_Timer; + uint32 EnvelopingWinds_Timer; + + void Reset() + { + LightningCloud_Timer = 15000; + LungBurst_Timer = 7000; + EnvelopingWinds_Timer = 9000; + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, NOT_STARTED); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEAD, me); + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //LightningCloud_Timer + if (LightningCloud_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LIGHTNING_CLOUD); + + //cast twice in Heroic mode + if (IsHeroic()) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LIGHTNING_CLOUD); + + LightningCloud_Timer = 15000+rand()%10000; + } else LightningCloud_Timer -=diff; + + //LungBurst_Timer + if (LungBurst_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LUNG_BURST); + LungBurst_Timer = 7000+rand()%5000; + } else LungBurst_Timer -=diff; + + //EnvelopingWinds_Timer + if (EnvelopingWinds_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ENVELOPING_WINDS); + + //cast twice in Heroic mode + if (IsHeroic()) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ENVELOPING_WINDS); + EnvelopingWinds_Timer = 10000+rand()%5000; + } else EnvelopingWinds_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_WATER_BOLT_VOLLEY 34449 +#define H_SPELL_WATER_BOLT_VOLLEY 37924 + +struct mob_coilfang_waterelementalAI : public ScriptedAI +{ + mob_coilfang_waterelementalAI(Creature *c) : ScriptedAI(c) {} + + uint32 WaterBoltVolley_Timer; + + void Reset() + { + WaterBoltVolley_Timer = 3000+rand()%3000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (WaterBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_WATER_BOLT_VOLLEY); + WaterBoltVolley_Timer = 7000+rand()%5000; + } else WaterBoltVolley_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thespiaAI(Creature* pCreature) +{ + return new boss_thespiaAI (pCreature); +} + +CreatureAI* GetAI_mob_coilfang_waterelementalAI(Creature* pCreature) +{ + return new mob_coilfang_waterelementalAI (pCreature); +} + +void AddSC_boss_hydromancer_thespia() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_hydromancer_thespia"; + newscript->GetAI = &GetAI_boss_thespiaAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_waterelemental"; + newscript->GetAI = &GetAI_mob_coilfang_waterelementalAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp new file mode 100644 index 00000000000..f2da4058e44 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp @@ -0,0 +1,264 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mekgineer_Steamrigger +SD%Complete: 60 +SDComment: Mechanics' interrrupt heal doesn't work very well, also a proper movement needs to be implemented -> summon further away and move towards pTarget to repair. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +/* ContentData +boss_mekgineer_steamrigger +mob_steamrigger_mechanic +EndContentData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_MECHANICS -1545007 +#define SAY_AGGRO_1 -1545008 +#define SAY_AGGRO_2 -1545009 +#define SAY_AGGRO_3 -1545010 +#define SAY_AGGRO_4 -1545011 +#define SAY_SLAY_1 -1545012 +#define SAY_SLAY_2 -1545013 +#define SAY_SLAY_3 -1545014 +#define SAY_DEATH -1545015 + +#define SPELL_SUPER_SHRINK_RAY 31485 +#define SPELL_SAW_BLADE 31486 +#define SPELL_ELECTRIFIED_NET 35107 +#define H_SPELL_ENRAGE 1 //corrent enrage spell not known + +#define ENTRY_STREAMRIGGER_MECHANIC 17951 + +struct boss_mekgineer_steamriggerAI : public ScriptedAI +{ + boss_mekgineer_steamriggerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Shrink_Timer; + uint32 Saw_Blade_Timer; + uint32 Electrified_Net_Timer; + bool Summon75; + bool Summon50; + bool Summon25; + + void Reset() + { + Shrink_Timer = 20000; + Saw_Blade_Timer = 15000; + Electrified_Net_Timer = 10000; + + Summon75 = false; + Summon50 = false; + Summon25 = false; + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, NOT_STARTED); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, IN_PROGRESS); + } + + //no known summon spells exist + void SummonMechanichs() + { + DoScriptText(SAY_MECHANICS, me); + + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + + if (rand()%2) + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,-7,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + if (rand()%2) + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,7,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Shrink_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUPER_SHRINK_RAY); + Shrink_Timer = 20000; + } else Shrink_Timer -= diff; + + if (Saw_Blade_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_SAW_BLADE); + else + DoCast(me->getVictim(), SPELL_SAW_BLADE); + + Saw_Blade_Timer = 15000; + } else Saw_Blade_Timer -= diff; + + if (Electrified_Net_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ELECTRIFIED_NET); + Electrified_Net_Timer = 10000; + } + else Electrified_Net_Timer -= diff; + + if (!Summon75) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 75) + { + SummonMechanichs(); + Summon75 = true; + } + } + + if (!Summon50) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) + { + SummonMechanichs(); + Summon50 = true; + } + } + + if (!Summon25) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) + { + SummonMechanichs(); + Summon25 = true; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_mekgineer_steamrigger(Creature* pCreature) +{ + return new boss_mekgineer_steamriggerAI (pCreature); +} + +#define SPELL_DISPEL_MAGIC 17201 +#define SPELL_REPAIR 31532 +#define H_SPELL_REPAIR 37936 + +#define MAX_REPAIR_RANGE (13.0f) //we should be at least at this range for repair +#define MIN_REPAIR_RANGE (7.0f) //we can stop movement at this range to repair but not required + +struct mob_steamrigger_mechanicAI : public ScriptedAI +{ + mob_steamrigger_mechanicAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Repair_Timer; + + void Reset() + { + Repair_Timer = 2000; + } + + void MoveInLineOfSight(Unit* /*who*/) + { + //react only if attacked + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (Repair_Timer <= diff) + { + if (pInstance && pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER) && pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) + { + if (Unit* pMekgineer = Unit::GetUnit((*me), pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER))) + { + if (me->IsWithinDistInMap(pMekgineer, MAX_REPAIR_RANGE)) + { + //are we already channeling? Doesn't work very well, find better check? + if (!me->GetUInt32Value(UNIT_CHANNEL_SPELL)) + { + //me->GetMotionMaster()->MovementExpired(); + //me->GetMotionMaster()->MoveIdle(); + + DoCast(me, SPELL_REPAIR, true); + } + Repair_Timer = 5000; + } + else + { + //me->GetMotionMaster()->MovementExpired(); + //me->GetMotionMaster()->MoveFollow(pMekgineer,0,0); + } + } + } else Repair_Timer = 5000; + } else Repair_Timer -= diff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_steamrigger_mechanic(Creature* pCreature) +{ + return new mob_steamrigger_mechanicAI (pCreature); +} + +void AddSC_boss_mekgineer_steamrigger() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_mekgineer_steamrigger"; + newscript->GetAI = &GetAI_boss_mekgineer_steamrigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_steamrigger_mechanic"; + newscript->GetAI = &GetAI_mob_steamrigger_mechanic; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp new file mode 100644 index 00000000000..f46956dda81 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp @@ -0,0 +1,204 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warlord_Kalithres +SD%Complete: 65 +SDComment: Contains workarounds regarding warlord's rage spells not acting as expected. Both scripts here require review and fine tuning. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_INTRO -1545016 +#define SAY_REGEN -1545017 +#define SAY_AGGRO1 -1545018 +#define SAY_AGGRO2 -1545019 +#define SAY_AGGRO3 -1545020 +#define SAY_SLAY1 -1545021 +#define SAY_SLAY2 -1545022 +#define SAY_DEATH -1545023 + +#define SPELL_SPELL_REFLECTION 31534 +#define SPELL_IMPALE 39061 +#define SPELL_WARLORDS_RAGE 37081 +#define SPELL_WARLORDS_RAGE_NAGA 31543 + +#define SPELL_WARLORDS_RAGE_PROC 36453 + +struct mob_naga_distillerAI : public ScriptedAI +{ + mob_naga_distillerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + //hack, due to really weird spell behaviour :( + if (pInstance) + { + if (pInstance->GetData(TYPE_DISTILLER) == IN_PROGRESS) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + } + + void EnterCombat(Unit * /*who*/) { } + + void StartRageGen(Unit * /*caster*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + DoCast(me, SPELL_WARLORDS_RAGE_NAGA, true); + + if (pInstance) + pInstance->SetData(TYPE_DISTILLER,IN_PROGRESS); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (me->GetHealth() <= damage) + if (pInstance) + pInstance->SetData(TYPE_DISTILLER,DONE); + } +}; + +struct boss_warlord_kalithreshAI : public ScriptedAI +{ + boss_warlord_kalithreshAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Reflection_Timer; + uint32 Impale_Timer; + uint32 Rage_Timer; + bool CanRage; + + void Reset() + { + Reflection_Timer = 10000; + Impale_Timer = 7000+rand()%7000; + Rage_Timer = 45000; + CanRage = false; + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + //hack :( + if (spell->Id == SPELL_WARLORDS_RAGE_PROC) + if (pInstance) + if (pInstance->GetData(TYPE_DISTILLER) == DONE) + me->RemoveAurasDueToSpell(SPELL_WARLORDS_RAGE_PROC); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Rage_Timer <= diff) + { + if (Creature* distiller = me->FindNearestCreature(17954, 100.0f)) + { + DoScriptText(SAY_REGEN, me); + DoCast(me, SPELL_WARLORDS_RAGE); + CAST_AI(mob_naga_distillerAI, distiller->AI())->StartRageGen(me); + } + Rage_Timer = 3000+rand()%15000; + } else Rage_Timer -= diff; + + //Reflection_Timer + if (Reflection_Timer <= diff) + { + DoCast(me, SPELL_SPELL_REFLECTION); + Reflection_Timer = 15000+rand()%10000; + } else Reflection_Timer -= diff; + + //Impale_Timer + if (Impale_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_IMPALE); + + Impale_Timer = 7500+rand()%5000; + } else Impale_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_naga_distiller(Creature* pCreature) +{ + return new mob_naga_distillerAI (pCreature); +} + +CreatureAI* GetAI_boss_warlord_kalithresh(Creature* pCreature) +{ + return new boss_warlord_kalithreshAI (pCreature); +} + +void AddSC_boss_warlord_kalithresh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_naga_distiller"; + newscript->GetAI = &GetAI_mob_naga_distiller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_warlord_kalithresh"; + newscript->GetAI = &GetAI_boss_warlord_kalithresh; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp new file mode 100644 index 00000000000..188a23738f5 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp @@ -0,0 +1,231 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Steam_Vault +SD%Complete: 80 +SDComment: Instance script and access panel GO +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define MAX_ENCOUNTER 4 + +#define MAIN_CHAMBERS_DOOR 183049 +#define ACCESS_PANEL_HYDRO 184125 +#define ACCESS_PANEL_MEK 184126 + +/* Steam Vaults encounters: +1 - Hydromancer Thespia Event +2 - Mekgineer Steamrigger Event +3 - Warlord Kalithresh Event +*/ + +bool GOHello_go_main_chambers_access_panel(Player* /*pPlayer*/, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + + if (!pInstance) + return false; + + if (pGo->GetEntry() == ACCESS_PANEL_HYDRO && (pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == DONE || pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL)) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA,SPECIAL); + + if (pGo->GetEntry() == ACCESS_PANEL_MEK && (pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == DONE || pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL)) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER,SPECIAL); + + return true; +} + +struct instance_steam_vault : public ScriptedInstance +{ + instance_steam_vault(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 ThespiaGUID; + uint64 MekgineerGUID; + uint64 KalithreshGUID; + + uint64 MainChambersDoor; + uint64 AccessPanelHydro; + uint64 AccessPanelMek; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + ThespiaGUID = 0; + MekgineerGUID = 0; + KalithreshGUID = 0; + MainChambersDoor = 0; + AccessPanelHydro = 0; + AccessPanelMek = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17797: ThespiaGUID = pCreature->GetGUID(); break; + case 17796: MekgineerGUID = pCreature->GetGUID(); break; + case 17798: KalithreshGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case MAIN_CHAMBERS_DOOR: MainChambersDoor = pGo->GetGUID(); break; + case ACCESS_PANEL_HYDRO: AccessPanelHydro = pGo->GetGUID(); break; + case ACCESS_PANEL_MEK: AccessPanelMek = pGo->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_HYDROMANCER_THESPIA: + if (data == SPECIAL) + { + HandleGameObject(AccessPanelHydro, true); + + if (GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL) + HandleGameObject(MainChambersDoor, true); + + debug_log("TSCR: Instance Steamvault: Access panel used."); + } + m_auiEncounter[0] = data; + break; + case TYPE_MEKGINEER_STEAMRIGGER: + if (data == SPECIAL) + { + HandleGameObject(AccessPanelMek, true); + + if (GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL) + HandleGameObject(MainChambersDoor, true); + + debug_log("TSCR: Instance Steamvault: Access panel used."); + } + m_auiEncounter[1] = data; + break; + case TYPE_WARLORD_KALITHRESH: + m_auiEncounter[2] = data; + break; + case TYPE_DISTILLER: + m_auiEncounter[3] = data; + break; + } + + if (data == DONE || data == SPECIAL) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HYDROMANCER_THESPIA: + return m_auiEncounter[0]; + case TYPE_MEKGINEER_STEAMRIGGER: + return m_auiEncounter[1]; + case TYPE_WARLORD_KALITHRESH: + return m_auiEncounter[2]; + case TYPE_DISTILLER: + return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THESPIA: + return ThespiaGUID; + case DATA_MEKGINEERSTEAMRIGGER: + return MekgineerGUID; + case DATA_KALITRESH: + return KalithreshGUID; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_steam_vault(Map* pMap) +{ + return new instance_steam_vault(pMap); +} + +void AddSC_instance_steam_vault() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_main_chambers_access_panel"; + newscript->pGOHello = &GOHello_go_main_chambers_access_panel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "instance_steam_vault"; + newscript->GetInstanceData = &GetInstanceData_instance_steam_vault; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h new file mode 100644 index 00000000000..4b407ac4816 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_STEAM_VAULT_H +#define DEF_STEAM_VAULT_H + +#define TYPE_HYDROMANCER_THESPIA 1 +#define TYPE_MEKGINEER_STEAMRIGGER 2 +#define TYPE_WARLORD_KALITHRESH 3 +#define TYPE_DISTILLER 4 + +#define DATA_MEKGINEERSTEAMRIGGER 5 +#define DATA_KALITRESH 6 +#define DATA_THESPIA 7 +#endif + diff --git a/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp b/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp new file mode 100644 index 00000000000..fcfcc1b1a90 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp @@ -0,0 +1,154 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hungarfen +SD%Complete: 95 +SDComment: Need confirmation if spell data are same in both modes. Summons should have faster rate in heroic +SDCategory: Coilfang Resevoir, Underbog +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FOUL_SPORES 31673 +#define SPELL_ACID_GEYSER 38739 + +struct boss_hungarfenAI : public ScriptedAI +{ + boss_hungarfenAI(Creature *c) : ScriptedAI(c) + { + } + + bool Root; + uint32 Mushroom_Timer; + uint32 AcidGeyser_Timer; + + void Reset() + { + Root = false; + Mushroom_Timer = 5000; // 1 mushroom after 5s, then one per 10s. This should be different in heroic mode + AcidGeyser_Timer = 10000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) + { + if (!Root) + { + DoCast(me, SPELL_FOUL_SPORES); + Root = true; + } + } + + if (Mushroom_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + me->SummonCreature(17990, pTarget->GetPositionX()+(rand()%8), pTarget->GetPositionY()+(rand()%8), pTarget->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); + else + me->SummonCreature(17990, me->GetPositionX()+(rand()%8), me->GetPositionY()+(rand()%8), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); + + Mushroom_Timer = 10000; + } else Mushroom_Timer -= diff; + + if (AcidGeyser_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ACID_GEYSER); + AcidGeyser_Timer = 10000+rand()%7500; + } else AcidGeyser_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hungarfen(Creature* pCreature) +{ + return new boss_hungarfenAI (pCreature); +} + +#define SPELL_SPORE_CLOUD 34168 +#define SPELL_PUTRID_MUSHROOM 31690 +#define SPELL_GROW 31698 + +struct mob_underbog_mushroomAI : public ScriptedAI +{ + mob_underbog_mushroomAI(Creature *c) : ScriptedAI(c) {} + + bool Stop; + uint32 Grow_Timer; + uint32 Shrink_Timer; + + void Reset() + { + Stop = false; + Grow_Timer = 0; + Shrink_Timer = 20000; + + DoCast(me, SPELL_PUTRID_MUSHROOM, true); + DoCast(me, SPELL_SPORE_CLOUD, true); + } + + void MoveInLineOfSight(Unit * /*who*/) {} + + void AttackStart(Unit* /*who*/) {} + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (Stop) + return; + + if (Grow_Timer <= diff) + { + DoCast(me, SPELL_GROW); + Grow_Timer = 3000; + } else Grow_Timer -= diff; + + if (Shrink_Timer <= diff) + { + me->RemoveAurasDueToSpell(SPELL_GROW); + Stop = true; + } else Shrink_Timer -= diff; + } +}; +CreatureAI* GetAI_mob_underbog_mushroom(Creature* pCreature) +{ + return new mob_underbog_mushroomAI (pCreature); +} + +void AddSC_boss_hungarfen() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_hungarfen"; + newscript->GetAI = &GetAI_boss_hungarfen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_underbog_mushroom"; + newscript->GetAI = &GetAI_mob_underbog_mushroom; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp new file mode 100644 index 00000000000..3a78660389b --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp @@ -0,0 +1,185 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_the_black_stalker +SD%Complete: 95 +SDComment: Timers may be incorrect +SDCategory: Coilfang Resevoir, Underbog +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_LEVITATE 31704 +#define SPELL_SUSPENSION 31719 +#define SPELL_LEVITATION_PULSE 31701 +#define SPELL_MAGNETIC_PULL 31705 +#define SPELL_CHAIN_LIGHTNING 31717 +#define SPELL_STATIC_CHARGE 31715 +#define SPELL_SUMMON_SPORE_STRIDER 38755 + +#define ENTRY_SPORE_STRIDER 22299 + +struct boss_the_black_stalkerAI : public ScriptedAI +{ + boss_the_black_stalkerAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 SporeStriders_Timer; + uint32 Levitate_Timer; + uint32 ChainLightning_Timer; + uint32 StaticCharge_Timer; + uint64 LevitatedTarget; + uint32 LevitatedTarget_Timer; + bool InAir; + uint32 check_Timer; + std::list Striders; + + void Reset() + { + Levitate_Timer = 12000; + ChainLightning_Timer = 6000; + StaticCharge_Timer = 10000; + SporeStriders_Timer = 10000+rand()%5000; + check_Timer = 5000; + LevitatedTarget = 0; + LevitatedTarget_Timer = 0; + Striders.clear(); + } + + void EnterCombat(Unit * /*who*/) {} + + void JustSummoned(Creature *summon) + { + if (summon && summon->GetEntry() == ENTRY_SPORE_STRIDER) + { + Striders.push_back(summon->GetGUID()); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + summon->AI()->AttackStart(pTarget); + else + if (me->getVictim()) + summon->AI()->AttackStart(me->getVictim()); + } + } + + void JustDied(Unit * /*who*/) + { + for (std::list::const_iterator i = Striders.begin(); i != Striders.end(); ++i) + if (Creature *strider = Unit::GetCreature(*me, *i)) + strider->DisappearAndDie(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Evade if too far + if (check_Timer <= diff) + { + float x,y,z,o; + me->GetHomePosition(x,y,z,o); + if (!me->IsWithinDist3d(x,y,z, 60)) + { + EnterEvadeMode(); + return; + } + check_Timer = 1000; + } else check_Timer -= diff; + + // Spore Striders + if (IsHeroic() && SporeStriders_Timer <= diff) + { + DoCast(me, SPELL_SUMMON_SPORE_STRIDER); + SporeStriders_Timer = 10000+rand()%5000; + } else SporeStriders_Timer -= diff; + + // Levitate + if (LevitatedTarget) + { + if (LevitatedTarget_Timer <= diff) + { + if (Unit *pTarget = Unit::GetUnit(*me, LevitatedTarget)) + { + if (!pTarget->HasAura(SPELL_LEVITATE)) + { + LevitatedTarget = 0; + return; + } + if (InAir) + { + pTarget->AddAura(SPELL_SUSPENSION, pTarget); + LevitatedTarget = 0; + } + else + { + pTarget->CastSpell(pTarget, SPELL_MAGNETIC_PULL, true); + InAir = true; + LevitatedTarget_Timer = 1500; + } + } + else + LevitatedTarget = 0; + } else LevitatedTarget_Timer -= diff; + } + if (Levitate_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + DoCast(pTarget, SPELL_LEVITATE); + LevitatedTarget = pTarget->GetGUID(); + LevitatedTarget_Timer = 2000; + InAir = false; + } + Levitate_Timer = 12000+rand()%3000; + } else Levitate_Timer -= diff; + + // Chain Lightning + if (ChainLightning_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + ChainLightning_Timer = 7000; + } else ChainLightning_Timer -= diff; + + // Static Charge + if (StaticCharge_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true)) + DoCast(pTarget, SPELL_STATIC_CHARGE); + StaticCharge_Timer = 10000; + } else StaticCharge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_the_black_stalker(Creature* pCreature) +{ + return new boss_the_black_stalkerAI (pCreature); +} + +void AddSC_boss_the_black_stalker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_the_black_stalker"; + newscript->GetAI = &GetAI_boss_the_black_stalker; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp new file mode 100644 index 00000000000..a07ac910598 --- /dev/null +++ b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp @@ -0,0 +1,255 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gruul +SD%Complete: 60 +SDComment: Ground Slam need further development (knock back effect and shatter effect must be added to the core) +SDCategory: Gruul's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "gruuls_lair.h" + +enum eEnums +{ + SAY_AGGRO = -1565010, + SAY_SLAM1 = -1565011, + SAY_SLAM2 = -1565012, + SAY_SHATTER1 = -1565013, + SAY_SHATTER2 = -1565014, + SAY_SLAY1 = -1565015, + SAY_SLAY2 = -1565016, + SAY_SLAY3 = -1565017, + SAY_DEATH = -1565018, + + EMOTE_GROW = -1565019, + + SPELL_GROWTH = 36300, + SPELL_CAVE_IN = 36240, + SPELL_GROUND_SLAM = 33525, //AoE Ground Slam applying Ground Slam to everyone with a script effect (most likely the knock back, we can code it to a set knockback) + SPELL_REVERBERATION = 36297, + SPELL_SHATTER = 33654, + + SPELL_SHATTER_EFFECT = 33671, + SPELL_HURTFUL_STRIKE = 33813, + SPELL_STONED = 33652, //Spell is self cast by target + + SPELL_MAGNETIC_PULL = 28337, + SPELL_KNOCK_BACK = 24199, //Knockback spell until correct implementation is made +}; + +struct boss_gruulAI : public ScriptedAI +{ + boss_gruulAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 m_uiGrowth_Timer; + uint32 m_uiCaveIn_Timer; + uint32 m_uiCaveIn_StaticTimer; + uint32 m_uiGroundSlamTimer; + uint32 m_uiHurtfulStrike_Timer; + uint32 m_uiReverberation_Timer; + + bool m_bPerformingGroundSlam; + + void Reset() + { + m_uiGrowth_Timer= 30000; + m_uiCaveIn_Timer= 27000; + m_uiCaveIn_StaticTimer = 30000; + m_uiGroundSlamTimer= 35000; + m_bPerformingGroundSlam= false; + m_uiHurtfulStrike_Timer= 8000; + m_uiReverberation_Timer= 60000+45000; + + if (pInstance) + pInstance->SetData(DATA_GRUULEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_GRUULEVENT, IN_PROGRESS); + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_GRUULEVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GRUULDOOR), true); // Open the encounter door + } + } + + void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) + { + //This to emulate effect1 (77) of SPELL_GROUND_SLAM, knock back to any direction + //It's initially wrong, since this will cause fall damage, which is by comments, not intended. + if (pSpell->Id == SPELL_GROUND_SLAM) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + switch (urand(0,1)) + { + case 0: pTarget->CastSpell(pTarget, SPELL_MAGNETIC_PULL, true, NULL, NULL, me->GetGUID()); break; + case 1: pTarget->CastSpell(pTarget, SPELL_KNOCK_BACK, true, NULL, NULL, me->GetGUID()); break; + } + } + } + + //this part should be in the core + if (pSpell->Id == SPELL_SHATTER) + { + //this spell must have custom handling in the core, dealing damage based on distance + pTarget->CastSpell(pTarget, SPELL_SHATTER_EFFECT, true); + + if (pTarget->HasAura(SPELL_STONED)) + pTarget->RemoveAurasDueToSpell(SPELL_STONED); + + //clear this, if we are still performing + if (m_bPerformingGroundSlam) + { + m_bPerformingGroundSlam = false; + + //and correct movement, if not already + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + { + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // Growth + // Gruul can cast this spell up to 30 times + if (m_uiGrowth_Timer <= uiDiff) + { + DoScriptText(EMOTE_GROW, me); + DoCast(me, SPELL_GROWTH); + m_uiGrowth_Timer = 30000; + } + else + m_uiGrowth_Timer -= uiDiff; + + if (m_bPerformingGroundSlam) + { + if (m_uiGroundSlamTimer <= uiDiff) + { + m_uiGroundSlamTimer =120000; + m_uiHurtfulStrike_Timer= 8000; + + if (m_uiReverberation_Timer < 10000) //Give a little time to the players to undo the damage from shatter + m_uiReverberation_Timer += 10000; + + DoCast(me, SPELL_SHATTER); + } + else + m_uiGroundSlamTimer -= uiDiff; + } + else + { + // Hurtful Strike + if (m_uiHurtfulStrike_Timer <= uiDiff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + + if (pTarget && me->IsWithinMeleeRange(me->getVictim())) + DoCast(pTarget, SPELL_HURTFUL_STRIKE); + else + DoCast(me->getVictim(), SPELL_HURTFUL_STRIKE); + + m_uiHurtfulStrike_Timer= 8000; + } + else + m_uiHurtfulStrike_Timer -= uiDiff; + + // Reverberation + if (m_uiReverberation_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_REVERBERATION, true); + m_uiReverberation_Timer = 15000 + rand()%10000; + } + else + m_uiReverberation_Timer -= uiDiff; + + // Cave In + if (m_uiCaveIn_Timer <= uiDiff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CAVE_IN); + + if (m_uiCaveIn_StaticTimer >= 4000) + m_uiCaveIn_StaticTimer -= 2000; + + m_uiCaveIn_Timer = m_uiCaveIn_StaticTimer; + } + else + m_uiCaveIn_Timer -= uiDiff; + + // Ground Slam, Gronn Lord's Grasp, Stoned, Shatter + if (m_uiGroundSlamTimer <= uiDiff) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + + m_bPerformingGroundSlam= true; + m_uiGroundSlamTimer = 10000; + + DoCast(me, SPELL_GROUND_SLAM); + } + else + m_uiGroundSlamTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + } +}; + +CreatureAI* GetAI_boss_gruul(Creature* pCreature) +{ + return new boss_gruulAI (pCreature); +} + +void AddSC_boss_gruul() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gruul"; + newscript->GetAI = &GetAI_boss_gruul; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp new file mode 100644 index 00000000000..482af86225c --- /dev/null +++ b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp @@ -0,0 +1,783 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_King_Maulgar +SD%Complete: 90 +SDComment: Correct timers, after whirlwind melee attack bug, prayer of healing +SDCategory: Gruul's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "gruuls_lair.h" + +#define SAY_AGGRO -1565000 +#define SAY_ENRAGE -1565001 +#define SAY_OGRE_DEATH1 -1565002 +#define SAY_OGRE_DEATH2 -1565003 +#define SAY_OGRE_DEATH3 -1565004 +#define SAY_OGRE_DEATH4 -1565005 +#define SAY_SLAY1 -1565006 +#define SAY_SLAY2 -1565007 +#define SAY_SLAY3 -1565008 +#define SAY_DEATH -1565009 + +// High King Maulgar +#define SPELL_ARCING_SMASH 39144 +#define SPELL_MIGHTY_BLOW 33230 +#define SPELL_WHIRLWIND 33238 +#define SPELL_BERSERKER_C 26561 +#define SPELL_ROAR 16508 +#define SPELL_FLURRY 33232 +#define SPELL_DUAL_WIELD 29651 //used in phase + +// Olm the Summoner +#define SPELL_DARK_DECAY 33129 +#define SPELL_DEATH_COIL 33130 +#define SPELL_SUMMON_WFH 33131 + +//Kiggler the Craed +#define SPELL_GREATER_POLYMORPH 33173 +#define SPELL_LIGHTNING_BOLT 36152 +#define SPELL_ARCANE_SHOCK 33175 +#define SPELL_ARCANE_EXPLOSION 33237 + +//Blindeye the Seer +#define SPELL_GREATER_PW_SHIELD 33147 +#define SPELL_HEAL 33144 +#define SPELL_PRAYER_OH 33152 + +//Krosh Firehand +#define SPELL_GREATER_FIREBALL 33051 +#define SPELL_SPELLSHIELD 33054 +#define SPELL_BLAST_WAVE 33061 + +bool CheckAllBossDied(ScriptedInstance* pInstance, Creature* me) +{ + if (!pInstance || !me) + return false; + + uint64 MaulgarGUID = 0; + uint64 KigglerGUID = 0; + uint64 BlindeyeGUID = 0; + uint64 OlmGUID = 0; + uint64 KroshGUID = 0; + + Creature* Maulgar = NULL; + Creature* Kiggler = NULL; + Creature* Blindeye = NULL; + Creature* Olm = NULL; + Creature* Krosh = NULL; + + MaulgarGUID = pInstance->GetData64(DATA_MAULGAR); + KigglerGUID = pInstance->GetData64(DATA_KIGGLERTHECRAZED); + BlindeyeGUID = pInstance->GetData64(DATA_BLINDEYETHESEER); + OlmGUID = pInstance->GetData64(DATA_OLMTHESUMMONER); + KroshGUID = pInstance->GetData64(DATA_KROSHFIREHAND); + + Maulgar = (Unit::GetCreature((*me), MaulgarGUID)); + Kiggler = (Unit::GetCreature((*me), KigglerGUID)); + Blindeye = (Unit::GetCreature((*me), BlindeyeGUID)); + Olm = (Unit::GetCreature((*me), OlmGUID)); + Krosh = (Unit::GetCreature((*me), KroshGUID)); + + if (!Maulgar || !Kiggler || !Blindeye || !Olm || !Krosh) + return false; + + if (!Maulgar->isAlive() && !Kiggler->isAlive() && !Blindeye->isAlive() && !Olm->isAlive() && !Krosh->isAlive()) + return true; + + return false; +} + +//High King Maulgar AI +struct boss_high_king_maulgarAI : public ScriptedAI +{ + boss_high_king_maulgarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i = 0; i < 4; ++i) + Council[i] = 0; + } + + ScriptedInstance* pInstance; + + uint32 ArcingSmash_Timer; + uint32 MightyBlow_Timer; + uint32 Whirlwind_Timer; + uint32 Charging_Timer; + uint32 Roar_Timer; + + bool Phase2; + + uint64 Council[4]; + + void Reset() + { + ArcingSmash_Timer = 10000; + MightyBlow_Timer = 40000; + Whirlwind_Timer = 30000; + Charging_Timer = 0; + Roar_Timer = 0; + + DoCast(me, SPELL_DUAL_WIELD, false); + + Phase2 = false; + + Creature *pCreature = NULL; + for (uint8 i = 0; i < 4; ++i) + { + if (Council[i]) + { + pCreature = (Unit::GetCreature((*me), Council[i])); + if (pCreature && !pCreature->isAlive()) + { + pCreature->Respawn(); + pCreature->AI()->EnterEvadeMode(); + } + } + } + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + + void AddDeath() + { + DoScriptText(RAND(SAY_OGRE_DEATH1,SAY_OGRE_DEATH2,SAY_OGRE_DEATH3,SAY_OGRE_DEATH4), me); + } + + void EnterCombat(Unit *who) + { + StartEvent(who); + } + + void GetCouncil() + { + if (pInstance) + { + //get council member's guid to respawn them if needed + Council[0] = pInstance->GetData64(DATA_KIGGLERTHECRAZED); + Council[1] = pInstance->GetData64(DATA_BLINDEYETHESEER); + Council[2] = pInstance->GetData64(DATA_OLMTHESUMMONER); + Council[3] = pInstance->GetData64(DATA_KROSHFIREHAND); + } + } + + void StartEvent(Unit *who) + { + if (!pInstance) + return; + + GetCouncil(); + + DoScriptText(SAY_AGGRO, me); + + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + + DoZoneInCombat(); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + GetCouncil(); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //ArcingSmash_Timer + if (ArcingSmash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCING_SMASH); + ArcingSmash_Timer = 10000; + } else ArcingSmash_Timer -= diff; + + //Whirlwind_Timer + if (Whirlwind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + Whirlwind_Timer = 55000; + } else Whirlwind_Timer -= diff; + + //MightyBlow_Timer + if (MightyBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MIGHTY_BLOW); + MightyBlow_Timer = 30000+rand()%10000; + } else MightyBlow_Timer -= diff; + + //Entering Phase 2 + if (!Phase2 && (me->GetHealth()*100 / me->GetMaxHealth()) < 50) + { + Phase2 = true; + DoScriptText(SAY_ENRAGE, me); + + DoCast(me, SPELL_DUAL_WIELD, true); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + } + + if (Phase2) + { + //Charging_Timer + if (Charging_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + AttackStart(pTarget); + DoCast(pTarget, SPELL_BERSERKER_C); + } + Charging_Timer = 20000; + } else Charging_Timer -= diff; + + //Intimidating Roar + if (Roar_Timer <= diff) + { + DoCast(me, SPELL_ROAR); + Roar_Timer = 40000+(rand()%10000); + } else Roar_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +//Olm The Summoner AI +struct boss_olm_the_summonerAI : public ScriptedAI +{ + boss_olm_the_summonerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 DarkDecay_Timer; + uint32 Summon_Timer; + uint32 DeathCoil_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + DarkDecay_Timer = 10000; + Summon_Timer = 15000; + DeathCoil_Timer = 20000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(pWho, 30.0f); + } + } + + void EnterCombat(Unit *who) + { + if (pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + Creature *Maulgar = NULL; + Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); + + if (Maulgar) + CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //DarkDecay_Timer + if (DarkDecay_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DARK_DECAY); + DarkDecay_Timer = 20000; + } else DarkDecay_Timer -= diff; + + //Summon_Timer + if (Summon_Timer <= diff) + { + DoCast(me, SPELL_SUMMON_WFH); + Summon_Timer = 30000; + } else Summon_Timer -= diff; + + //DeathCoil Timer /need correct timer + if (DeathCoil_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_DEATH_COIL); + DeathCoil_Timer = 20000; + } else DeathCoil_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Kiggler The Crazed AI +struct boss_kiggler_the_crazedAI : public ScriptedAI +{ + boss_kiggler_the_crazedAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 GreaterPolymorph_Timer; + uint32 LightningBolt_Timer; + uint32 ArcaneShock_Timer; + uint32 ArcaneExplosion_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreaterPolymorph_Timer = 5000; + LightningBolt_Timer = 10000; + ArcaneShock_Timer = 20000; + ArcaneExplosion_Timer = 30000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + if (pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + Creature *Maulgar = NULL; + Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); + + if (Maulgar) + CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //GreaterPolymorph_Timer + if (GreaterPolymorph_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_GREATER_POLYMORPH); + + GreaterPolymorph_Timer = 15000 + rand()%5000; + } else GreaterPolymorph_Timer -= diff; + + //LightningBolt_Timer + if (LightningBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); + LightningBolt_Timer = 15000; + } else LightningBolt_Timer -= diff; + + //ArcaneShock_Timer + if (ArcaneShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_SHOCK); + ArcaneShock_Timer = 20000; + } else ArcaneShock_Timer -= diff; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 30000; + } else ArcaneExplosion_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Blindeye The Seer AI +struct boss_blindeye_the_seerAI : public ScriptedAI +{ + boss_blindeye_the_seerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 GreaterPowerWordShield_Timer; + uint32 Heal_Timer; + uint32 PrayerofHealing_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreaterPowerWordShield_Timer = 5000; + Heal_Timer = 25000 + rand()%15000; + PrayerofHealing_Timer = 45000 + rand()%10000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + Creature *Maulgar = NULL; + Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); + + if (Maulgar) + CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //GreaterPowerWordShield_Timer + if (GreaterPowerWordShield_Timer <= diff) + { + DoCast(me, SPELL_GREATER_PW_SHIELD); + GreaterPowerWordShield_Timer = 40000; + } else GreaterPowerWordShield_Timer -= diff; + + //Heal_Timer + if (Heal_Timer <= diff) + { + DoCast(me, SPELL_HEAL); + Heal_Timer = 15000 + rand()%25000; + } else Heal_Timer -= diff; + + //PrayerofHealing_Timer + if (PrayerofHealing_Timer <= diff) + { + DoCast(me, SPELL_PRAYER_OH); + PrayerofHealing_Timer = 35000 + rand()%15000; + } else PrayerofHealing_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Krosh Firehand AI +struct boss_krosh_firehandAI : public ScriptedAI +{ + boss_krosh_firehandAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 GreaterFireball_Timer; + uint32 SpellShield_Timer; + uint32 BlastWave_Timer; + + ScriptedInstance* pInstance; + + void Reset() + { + GreaterFireball_Timer = 1000; + SpellShield_Timer = 5000; + BlastWave_Timer = 20000; + + //reset encounter + if (pInstance) + pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); + pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + Creature *Maulgar = NULL; + Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); + + if (Maulgar) + CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + + if (CheckAllBossDied(pInstance, me)) + pInstance->SetData(DATA_MAULGAREVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) + { + EnterEvadeMode(); + return; + } + + //GreaterFireball_Timer + if (GreaterFireball_Timer < diff || me->IsWithinDist(me->getVictim(), 30)) + { + DoCast(me->getVictim(), SPELL_GREATER_FIREBALL); + GreaterFireball_Timer = 2000; + } else GreaterFireball_Timer -= diff; + + //SpellShield_Timer + if (SpellShield_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me->getVictim(), SPELL_SPELLSHIELD); + SpellShield_Timer = 30000; + } else SpellShield_Timer -= diff; + + //BlastWave_Timer + if (BlastWave_Timer <= diff) + { + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //15 yard radius minimum + if (pTarget && pTarget->IsWithinDist(me, 15,false)) + target_list.push_back(pTarget); + pTarget = NULL; + } + if (target_list.size()) + pTarget = *(target_list.begin()+rand()%target_list.size()); + + me->InterruptNonMeleeSpells(false); + DoCast(pTarget, SPELL_BLAST_WAVE); + BlastWave_Timer = 60000; + } else BlastWave_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_high_king_maulgar(Creature* pCreature) +{ + return new boss_high_king_maulgarAI (pCreature); +} + +CreatureAI* GetAI_boss_olm_the_summoner(Creature* pCreature) +{ + return new boss_olm_the_summonerAI (pCreature); +} + +CreatureAI *GetAI_boss_kiggler_the_crazed(Creature* pCreature) +{ + return new boss_kiggler_the_crazedAI (pCreature); +} + +CreatureAI *GetAI_boss_blindeye_the_seer(Creature* pCreature) +{ + return new boss_blindeye_the_seerAI (pCreature); +} + +CreatureAI *GetAI_boss_krosh_firehand(Creature* pCreature) +{ + return new boss_krosh_firehandAI (pCreature); +} + +void AddSC_boss_high_king_maulgar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_high_king_maulgar"; + newscript->GetAI = &GetAI_boss_high_king_maulgar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_kiggler_the_crazed"; + newscript->GetAI = &GetAI_boss_kiggler_the_crazed; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_blindeye_the_seer"; + newscript->GetAI = &GetAI_boss_blindeye_the_seer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_olm_the_summoner"; + newscript->GetAI = &GetAI_boss_olm_the_summoner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_krosh_firehand"; + newscript->GetAI = &GetAI_boss_krosh_firehand; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/GruulsLair/gruuls_lair.h b/src/server/scripts/Outland/GruulsLair/gruuls_lair.h new file mode 100644 index 00000000000..7003dcb1e26 --- /dev/null +++ b/src/server/scripts/Outland/GruulsLair/gruuls_lair.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_GRUULS_LAIR_H +#define DEF_GRUULS_LAIR_H + +#define DATA_BLINDEYETHESEER 1 +#define DATA_GRUULEVENT 2 +#define DATA_KIGGLERTHECRAZED 3 +#define DATA_KROSHFIREHAND 4 +#define DATA_MAULGAREVENT 5 +#define DATA_MAULGAREVENT_TANK 6 +#define DATA_OLMTHESUMMONER 7 +#define DATA_MAULGARDOOR 8 +#define DATA_GRUULDOOR 9 +#define DATA_MAULGAR 10 + +#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Gruul's Lair instance (map 565). Encounters will be buggy." +#endif + diff --git a/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp b/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp new file mode 100644 index 00000000000..bb790a5d4ea --- /dev/null +++ b/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp @@ -0,0 +1,193 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Gruuls_Lair +SD%Complete: 100 +SDComment: +SDCategory: Gruul's Lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "gruuls_lair.h" + +#define MAX_ENCOUNTER 2 + +/* Gruuls Lair encounters: +1 - High King Maulgar event +2 - Gruul event +*/ + +struct instance_gruuls_lair : public ScriptedInstance +{ + instance_gruuls_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 MaulgarEvent_Tank; + uint64 KigglerTheCrazed; + uint64 BlindeyeTheSeer; + uint64 OlmTheSummoner; + uint64 KroshFirehand; + uint64 Maulgar; + + uint64 MaulgarDoor; + uint64 GruulDoor; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + MaulgarEvent_Tank = 0; + KigglerTheCrazed = 0; + BlindeyeTheSeer = 0; + OlmTheSummoner = 0; + KroshFirehand = 0; + Maulgar = 0; + + MaulgarDoor = 0; + GruulDoor = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 18835: KigglerTheCrazed = pCreature->GetGUID(); break; + case 18836: BlindeyeTheSeer = pCreature->GetGUID(); break; + case 18834: OlmTheSummoner = pCreature->GetGUID(); break; + case 18832: KroshFirehand = pCreature->GetGUID(); break; + case 18831: Maulgar = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 184468: + MaulgarDoor = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) HandleGameObject(NULL, true, pGo); + break; + case 184662: GruulDoor = pGo->GetGUID(); break; + } + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_MAULGAREVENT_TANK) + MaulgarEvent_Tank = data; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MAULGAREVENT_TANK: return MaulgarEvent_Tank; + case DATA_KIGGLERTHECRAZED: return KigglerTheCrazed; + case DATA_BLINDEYETHESEER: return BlindeyeTheSeer; + case DATA_OLMTHESUMMONER: return OlmTheSummoner; + case DATA_KROSHFIREHAND: return KroshFirehand; + case DATA_MAULGARDOOR: return MaulgarDoor; + case DATA_GRUULDOOR: return GruulDoor; + case DATA_MAULGAR: return Maulgar; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAULGAREVENT: + if (data == DONE) HandleGameObject(MaulgarDoor, true); + m_auiEncounter[0] = data; break; + case DATA_GRUULEVENT: + if (data == IN_PROGRESS) HandleGameObject(GruulDoor, false); + else HandleGameObject(GruulDoor, true); + m_auiEncounter[1] = data; break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_MAULGAREVENT: return m_auiEncounter[0]; + case DATA_GRUULEVENT: return m_auiEncounter[1]; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_gruuls_lair(Map* pMap) +{ + return new instance_gruuls_lair(pMap); +} + +void AddSC_instance_gruuls_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_gruuls_lair"; + newscript->GetInstanceData = &GetInstanceData_instance_gruuls_lair; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h new file mode 100644 index 00000000000..b845c66823f --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BLOOD_FURNACE_H +#define DEF_BLOOD_FURNACE_H + +#define DATA_THE_MAKER 1 +#define DATA_BROGGOK 2 +#define DATA_KELIDAN_THE_MAKER 3 +#define TYPE_THE_MAKER_EVENT 4 +#define TYPE_BROGGOK_EVENT 5 +#define TYPE_KELIDAN_THE_BREAKER_EVENT 6 +#define DATA_DOOR1 7 +#define DATA_DOOR2 8 +#define DATA_DOOR3 9 +#define DATA_DOOR4 10 +#define DATA_DOOR5 11 +#define DATA_DOOR6 12 +#define DATA_PRISON_CELL1 13 +#define DATA_PRISON_CELL2 14 +#define DATA_PRISON_CELL3 15 +#define DATA_PRISON_CELL4 16 +#define DATA_PRISON_CELL5 17 +#define DATA_PRISON_CELL6 18 +#define DATA_PRISON_CELL7 19 +#define DATA_PRISON_CELL8 20 +#endif + diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp new file mode 100644 index 00000000000..d5fb9bdba49 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp @@ -0,0 +1,131 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Broggok +SD%Complete: 70 +SDComment: pre-event not made +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eEnums +{ + SAY_AGGRO = -1542008, + + SPELL_SLIME_SPRAY = 30913, + SPELL_POISON_CLOUD = 30916, + SPELL_POISON_BOLT = 30917, + + SPELL_POISON = 30914 +}; + +struct boss_broggokAI : public ScriptedAI +{ + boss_broggokAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AcidSpray_Timer; + uint32 PoisonSpawn_Timer; + uint32 PoisonBolt_Timer; + + void Reset() + { + AcidSpray_Timer = 10000; + PoisonSpawn_Timer = 5000; + PoisonBolt_Timer = 7000; + if (pInstance) + { + pInstance->SetData(TYPE_BROGGOK_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + pInstance->SetData(TYPE_BROGGOK_EVENT, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), false); + } + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(16); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->CastSpell(summoned,SPELL_POISON,false,0,0,me->GetGUID()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AcidSpray_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLIME_SPRAY); + AcidSpray_Timer = 4000+rand()%8000; + } else AcidSpray_Timer -=diff; + + if (PoisonBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_BOLT); + PoisonBolt_Timer = 4000+rand()%8000; + } else PoisonBolt_Timer -=diff; + + if (PoisonSpawn_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLOUD); + PoisonSpawn_Timer = 20000; + } else PoisonSpawn_Timer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*who*/) + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR5), true); + pInstance->SetData(TYPE_BROGGOK_EVENT, DONE); + } + } + +}; + +CreatureAI* GetAI_boss_broggok(Creature* pCreature) +{ + return new boss_broggokAI (pCreature); +} + +void AddSC_boss_broggok() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_broggok"; + newscript->GetAI = &GetAI_boss_broggok; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp new file mode 100644 index 00000000000..a44ad9cc3c8 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp @@ -0,0 +1,356 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kelidan_The_Breaker +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +/* ContentData +boss_kelidan_the_breaker +mob_shadowmoon_channeler +EndContentData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eKelidan +{ + SAY_WAKE = -1542000, + SAY_ADD_AGGRO_1 = -1542001, + SAY_ADD_AGGRO_2 = -1542002, + SAY_ADD_AGGRO_3 = -1542003, + SAY_KILL_1 = -1542004, + SAY_KILL_2 = -1542005, + SAY_NOVA = -1542006, + SAY_DIE = -1542007, + + SPELL_CORRUPTION = 30938, + SPELL_EVOCATION = 30935, + + SPELL_FIRE_NOVA = 33132, + H_SPELL_FIRE_NOVA = 37371, + + SPELL_SHADOW_BOLT_VOLLEY = 28599, + H_SPELL_SHADOW_BOLT_VOLLEY = 40070, + + SPELL_BURNING_NOVA = 30940, + SPELL_VORTEX = 37370, + + ENTRY_KELIDAN = 17377, + ENTRY_CHANNELER = 17653 +}; + +const float ShadowmoonChannelers[5][4]= +{ + {302,-87,-24.4,0.157}, + {321,-63.5,-24.6,4.887}, + {346,-74.5,-24.6,3.595}, + {344,-103.5,-24.5,2.356}, + {316,-109,-24.6,1.257} +}; + +struct boss_kelidan_the_breakerAI : public ScriptedAI +{ + boss_kelidan_the_breakerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i=0; i<5; ++i) + Channelers[i] = 0; + } + + ScriptedInstance* pInstance; + + uint32 ShadowVolley_Timer; + uint32 BurningNova_Timer; + uint32 Firenova_Timer; + uint32 Corruption_Timer; + uint32 check_Timer; + bool Firenova; + bool addYell; + uint64 Channelers[5]; + + void Reset() + { + ShadowVolley_Timer = 1000; + BurningNova_Timer = 15000; + Corruption_Timer = 5000; + check_Timer = 0; + Firenova = false; + addYell = false; + SummonChannelers(); + if (pInstance) + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_WAKE, me); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoStartMovement(who); + if (pInstance) + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void ChannelerEngaged(Unit* who) + { + if (who && !addYell) + { + addYell = true; + DoScriptText(RAND(SAY_ADD_AGGRO_1,SAY_ADD_AGGRO_2,SAY_ADD_AGGRO_3), me); + } + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (who && channeler && !channeler->isInCombat()) + channeler->AI()->AttackStart(who); + } + } + + void ChannelerDied(Unit* killer) + { + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (channeler && channeler->isAlive()) + return; + } + + if (killer) + me->AI()->AttackStart(killer); + } + + uint64 GetChanneled(Creature *channeler1) + { + SummonChannelers(); + if (!channeler1) return NULL; + uint8 i; + for (i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (channeler && channeler->GetGUID() == channeler1->GetGUID()) + break; + } + return Channelers[(i+2)%5]; + } + + void SummonChannelers() + { + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (!channeler || channeler->isDead()) + channeler = me->SummonCreature(ENTRY_CHANNELER,ShadowmoonChannelers[i][0],ShadowmoonChannelers[i][1],ShadowmoonChannelers[i][2],ShadowmoonChannelers[i][3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,300000); + if (channeler) + Channelers[i] = channeler->GetGUID(); + else + Channelers[i] = 0; + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR1), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR6), true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (check_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + DoCast(me, SPELL_EVOCATION); + check_Timer = 5000; + } else check_Timer -= diff; + return; + } + + if (Firenova) + { + if (Firenova_Timer <= diff) + { + DoCast(me, SPELL_FIRE_NOVA, true); + Firenova = false; + ShadowVolley_Timer = 2000; + } else Firenova_Timer -=diff; + + return; + } + + if (ShadowVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); + ShadowVolley_Timer = 5000+rand()%8000; + } else ShadowVolley_Timer -=diff; + + if (Corruption_Timer <= diff) + { + DoCast(me, SPELL_CORRUPTION); + Corruption_Timer = 30000+rand()%20000; + } else Corruption_Timer -=diff; + + if (BurningNova_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(SAY_NOVA, me); + + if (SpellEntry *nova = GET_SPELL(SPELL_BURNING_NOVA)) + { + if (Aura * aura = Aura::TryCreate(nova, me, me)) + aura->ApplyForTargets(); + } + + if (IsHeroic()) + DoTeleportAll(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + + BurningNova_Timer = 20000+rand()%8000; + Firenova_Timer= 5000; + Firenova = true; + } else BurningNova_Timer -=diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_kelidan_the_breaker(Creature* pCreature) +{ + return new boss_kelidan_the_breakerAI (pCreature); +} + +/*###### +## mob_shadowmoon_channeler +######*/ + +enum eShadowmoon +{ + SPELL_SHADOW_BOLT = 12739, + H_SPELL_SHADOW_BOLT = 15472, + + SPELL_MARK_OF_SHADOW = 30937, + SPELL_CHANNELING = 39123 +}; + +struct mob_shadowmoon_channelerAI : public ScriptedAI +{ + mob_shadowmoon_channelerAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 ShadowBolt_Timer; + uint32 MarkOfShadow_Timer; + uint32 check_Timer; + + void Reset() + { + ShadowBolt_Timer = 1000+rand()%1000; + MarkOfShadow_Timer = 5000+rand()%2000; + check_Timer = 0; + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + } + + void EnterCombat(Unit* who) + { + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerEngaged(who); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoStartMovement(who); + } + + void JustDied(Unit* Killer) + { + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerDied(Killer); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (check_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + { + uint64 channeler = CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->GetChanneled(me); + if (Unit *channeled = Unit::GetUnit(*me, channeler)) + DoCast(channeled, SPELL_CHANNELING); + } + check_Timer = 5000; + } else check_Timer -= diff; + return; + } + + if (MarkOfShadow_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MARK_OF_SHADOW); + MarkOfShadow_Timer = 15000+rand()%5000; + } else MarkOfShadow_Timer -=diff; + + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 5000+rand()%1000; + } else ShadowBolt_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_shadowmoon_channeler(Creature* pCreature) +{ + return new mob_shadowmoon_channelerAI (pCreature); +} + +void AddSC_boss_kelidan_the_breaker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_kelidan_the_breaker"; + newscript->GetAI = &GetAI_boss_kelidan_the_breaker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadowmoon_channeler"; + newscript->GetAI = &GetAI_mob_shadowmoon_channeler; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp new file mode 100644 index 00000000000..45219b6509b --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_The_Maker +SD%Complete: 80 +SDComment: Mind control no support +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eEnums +{ + SAY_AGGRO_1 = -1542009, + SAY_AGGRO_2 = -1542010, + SAY_AGGRO_3 = -1542011, + SAY_KILL_1 = -1542012, + SAY_KILL_2 = -1542013, + SAY_DIE = -1542014, + + SPELL_ACID_SPRAY = 38153, // heroic 38973 ??? 38153 + SPELL_EXPLODING_BREAKER = 30925, + SPELL_KNOCKDOWN = 20276, + SPELL_DOMINATION = 25772 // ??? +}; + +struct boss_the_makerAI : public ScriptedAI +{ + boss_the_makerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AcidSpray_Timer; + uint32 ExplodingBreaker_Timer; + uint32 Domination_Timer; + uint32 Knockdown_Timer; + + void Reset() + { + AcidSpray_Timer = 15000; + ExplodingBreaker_Timer = 6000; + Domination_Timer = 120000; + Knockdown_Timer = 10000; + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), false); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR3), true); + + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AcidSpray_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ACID_SPRAY); + AcidSpray_Timer = 15000+rand()%8000; + } else AcidSpray_Timer -=diff; + + if (ExplodingBreaker_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_EXPLODING_BREAKER); + ExplodingBreaker_Timer = 4000+rand()%8000; + } else ExplodingBreaker_Timer -=diff; + + /* // Disabled until Core Support for mind control + if (domination_timer_timer <= diff) + { + Unit *pTarget; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(pTarget, SPELL_DOMINATION); + + domination_timer = 120000; + } else domination_timer -=diff; + */ + + if (Knockdown_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + Knockdown_Timer = 4000+rand()%8000; + } else Knockdown_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_the_makerAI(Creature* pCreature) +{ + return new boss_the_makerAI (pCreature); +} + +void AddSC_boss_the_maker() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_maker"; + newscript->GetAI = &GetAI_boss_the_makerAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp new file mode 100644 index 00000000000..3a2eb8ba5ee --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp @@ -0,0 +1,232 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Blood_Furnace +SD%Complete: 85 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +#define ENTRY_SEWER1 181823 +#define ENTRY_SEWER2 181766 +#define MAX_ENCOUNTER 3 + +struct instance_blood_furnace : public ScriptedInstance +{ + instance_blood_furnace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 The_MakerGUID; + uint64 BroggokGUID; + uint64 Kelidan_The_BreakerGUID; + + uint64 Door1GUID; + uint64 Door2GUID; + uint64 Door3GUID; + uint64 Door4GUID; + uint64 Door5GUID; + uint64 Door6GUID; + + uint64 PrisonCell1GUID; + uint64 PrisonCell2GUID; + uint64 PrisonCell3GUID; + uint64 PrisonCell4GUID; + uint64 PrisonCell5GUID; + uint64 PrisonCell6GUID; + uint64 PrisonCell7GUID; + uint64 PrisonCell8GUID; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + The_MakerGUID = 0; + BroggokGUID = 0; + Kelidan_The_BreakerGUID = 0; + + Door1GUID = 0; + Door2GUID = 0; + Door3GUID = 0; + Door4GUID = 0; + Door5GUID = 0; + Door6GUID = 0; + + PrisonCell1GUID = 0; + PrisonCell2GUID = 0; + PrisonCell3GUID = 0; + PrisonCell4GUID = 0; + PrisonCell5GUID = 0; + PrisonCell6GUID = 0; + PrisonCell7GUID = 0; + PrisonCell8GUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + if (!add) + return; + + switch(pCreature->GetEntry()) + { + case 17381: The_MakerGUID = pCreature->GetGUID(); break; + case 17380: BroggokGUID = pCreature->GetGUID(); break; + case 17377: Kelidan_The_BreakerGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (!add) + return; + + if (pGo->GetEntry() == 181766) //Final exit door + Door1GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181811) //The Maker Front door + Door2GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181812) //The Maker Rear door + Door3GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181822) //Broggok Front door + Door4GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181819) //Broggok Rear door + Door5GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181823) //Kelidan exit door + Door6GUID = pGo->GetGUID(); + + if (pGo->GetEntry() == 181813) //The Maker prison cell front right + PrisonCell1GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181814) //The Maker prison cell back right + PrisonCell2GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181816) //The Maker prison cell front left + PrisonCell3GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181815) //The Maker prison cell back left + PrisonCell4GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181821) //Broggok prison cell front right + PrisonCell5GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181818) //Broggok prison cell back right + PrisonCell6GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181820) //Broggok prison cell front left + PrisonCell7GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181817) //Broggok prison cell back left + PrisonCell8GUID = pGo->GetGUID(); + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THE_MAKER: return The_MakerGUID; + case DATA_BROGGOK: return BroggokGUID; + case DATA_KELIDAN_THE_MAKER: return Kelidan_The_BreakerGUID; + case DATA_DOOR1: return Door1GUID; + case DATA_DOOR2: return Door2GUID; + case DATA_DOOR3: return Door3GUID; + case DATA_DOOR4: return Door4GUID; + case DATA_DOOR5: return Door5GUID; + case DATA_DOOR6: return Door6GUID; + case DATA_PRISON_CELL1: return PrisonCell1GUID; + case DATA_PRISON_CELL2: return PrisonCell2GUID; + case DATA_PRISON_CELL3: return PrisonCell3GUID; + case DATA_PRISON_CELL4: return PrisonCell4GUID; + case DATA_PRISON_CELL5: return PrisonCell5GUID; + case DATA_PRISON_CELL6: return PrisonCell6GUID; + case DATA_PRISON_CELL7: return PrisonCell7GUID; + case DATA_PRISON_CELL8: return PrisonCell8GUID; + } + + return 0; + } + + void SetData(uint32 /*type*/, uint32 data) + { + switch(data) + { + case TYPE_THE_MAKER_EVENT: m_auiEncounter[0] = data; break; + case TYPE_BROGGOK_EVENT: m_auiEncounter[1] = data; break; + case TYPE_KELIDAN_THE_BREAKER_EVENT: m_auiEncounter[2] = data; break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_THE_MAKER_EVENT: return m_auiEncounter[0]; + case TYPE_BROGGOK_EVENT: return m_auiEncounter[1]; + case TYPE_KELIDAN_THE_BREAKER_EVENT: return m_auiEncounter[2]; + } + + return 0; + } + + const char* Save() + { + return str_data.c_str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS || m_auiEncounter[i] == FAIL) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_blood_furnace(Map* pMap) +{ + return new instance_blood_furnace(pMap); +} + +void AddSC_instance_blood_furnace() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blood_furnace"; + newscript->GetInstanceData = &GetInstanceData_instance_blood_furnace; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp new file mode 100644 index 00000000000..d6c0b2fd401 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Omar_The_Unscarred +SD%Complete: 90 +SDComment: Temporary solution for orbital/shadow whip-ability. Needs more core support before making it more proper. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1543009 +#define SAY_AGGRO_2 -1543010 +#define SAY_AGGRO_3 -1543011 +#define SAY_SUMMON -1543012 +#define SAY_CURSE -1543013 +#define SAY_KILL_1 -1543014 +#define SAY_DIE -1543015 +#define SAY_WIPE -1543016 + +#define SPELL_ORBITAL_STRIKE 30637 +#define SPELL_SHADOW_WHIP 30638 +#define SPELL_TREACHEROUS_AURA 30695 +#define H_SPELL_BANE_OF_TREACHERY 37566 +#define SPELL_DEMONIC_SHIELD 31901 +#define SPELL_SHADOW_BOLT 30686 +#define H_SPELL_SHADOW_BOLT 39297 +#define SPELL_SUMMON_FIENDISH_HOUND 30707 + +struct boss_omor_the_unscarredAI : public ScriptedAI +{ + boss_omor_the_unscarredAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 OrbitalStrike_Timer; + uint32 ShadowWhip_Timer; + uint32 Aura_Timer; + uint32 DemonicShield_Timer; + uint32 Shadowbolt_Timer; + uint32 Summon_Timer; + uint32 SummonedCount; + uint64 PlayerGUID; + bool CanPullBack; + + void Reset() + { + DoScriptText(SAY_WIPE, me); + + OrbitalStrike_Timer = 25000; + ShadowWhip_Timer = 2000; + Aura_Timer = 10000; + DemonicShield_Timer = 1000; + Shadowbolt_Timer = 2000; + Summon_Timer = 10000; + SummonedCount = 0; + PlayerGUID = 0; + CanPullBack = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(SAY_KILL_1, me); + } + + void JustSummoned(Creature* summoned) + { + DoScriptText(SAY_SUMMON, me); + + if (Unit* random = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(random); + + ++SummonedCount; + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //only two may be wrong, perhaps increase timer and spawn periodically instead. + if (SummonedCount < 2) + { + if (Summon_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUMMON_FIENDISH_HOUND); + Summon_Timer = 15000+rand()%15000; + } else Summon_Timer -= diff; + } + + if (CanPullBack) + { + if (ShadowWhip_Timer <= diff) + { + if (Player* temp = Unit::GetPlayer(PlayerGUID)) + { + //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) + if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) + { + me->InterruptNonMeleeSpells(false); + DoCast(temp, SPELL_SHADOW_WHIP); + } + } + PlayerGUID = 0; + ShadowWhip_Timer = 2000; + CanPullBack = false; + } else ShadowWhip_Timer -= diff; + } + else if (OrbitalStrike_Timer <= diff) + { + Unit* temp = NULL; + if (me->IsWithinMeleeRange(me->getVictim())) + temp = me->getVictim(); + else temp = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (temp && temp->GetTypeId() == TYPEID_PLAYER) + { + DoCast(temp, SPELL_ORBITAL_STRIKE); + OrbitalStrike_Timer = 14000+rand()%2000; + PlayerGUID = temp->GetGUID(); + + if (PlayerGUID) + CanPullBack = true; + } + } else OrbitalStrike_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) + { + if (DemonicShield_Timer <= diff) + { + DoCast(me, SPELL_DEMONIC_SHIELD); + DemonicShield_Timer = 15000; + } else DemonicShield_Timer -= diff; + } + + if (Aura_Timer <= diff) + { + DoScriptText(SAY_CURSE, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_TREACHEROUS_AURA); + Aura_Timer = 8000+rand()%8000; + } + } else Aura_Timer -= diff; + + if (Shadowbolt_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget) + pTarget = me->getVictim(); + + DoCast(pTarget, SPELL_SHADOW_BOLT); + Shadowbolt_Timer = 4000+rand()%2500; + } + } else Shadowbolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_omor_the_unscarredAI(Creature* pCreature) +{ + return new boss_omor_the_unscarredAI (pCreature); +} + +void AddSC_boss_omor_the_unscarred() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_omor_the_unscarred"; + newscript->GetAI = &GetAI_boss_omor_the_unscarredAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp new file mode 100644 index 00000000000..181911f77a4 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp @@ -0,0 +1,467 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +Name: Boss_Vazruden_the_Herald +%Complete: 90 +Comment: +Category: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FIREBALL DUNGEON_MODE(34653, 36920) +#define SPELL_CONE_OF_FIRE DUNGEON_MODE(30926, 36921) +#define SPELL_SUMMON_LIQUID_FIRE DUNGEON_MODE(23971, 30928) +#define SPELL_BELLOWING_ROAR 39427 +#define SPELL_REVENGE DUNGEON_MODE(19130, 40392) +#define SPELL_KIDNEY_SHOT 30621 +#define SPELL_FIRE_NOVA_VISUAL 19823 + +#define ENTRY_HELLFIRE_SENTRY 17517 +#define ENTRY_VAZRUDEN_HERALD 17307 +#define ENTRY_VAZRUDEN 17537 +#define ENTRY_NAZAN 17536 +#define ENTRY_LIQUID_FIRE 22515 +#define ENTRY_REINFORCED_FEL_IRON_CHEST DUNGEON_MODE(185168, 185169) + +#define SAY_INTRO -1543017 +#define SAY_WIPE -1543018 +#define SAY_AGGRO_1 -1543019 +#define SAY_AGGRO_2 -1543020 +#define SAY_AGGRO_3 -1543021 +#define SAY_KILL_1 -1543022 +#define SAY_KILL_2 -1543023 +#define SAY_DIE -1543024 +#define EMOTE -1543025 + +#define PATH_ENTRY 2081 + +const float VazrudenMiddle[3] = {-1406.5, 1746.5, 81.2}; +const float VazrudenRing[2][3] = +{ + {-1430, 1705, 112}, + {-1377, 1760, 112} +}; + +struct boss_nazanAI : public ScriptedAI +{ + boss_nazanAI(Creature *c) : ScriptedAI(c) + { + VazrudenGUID = 0; + flight = true; + } + + uint32 Fireball_Timer; + uint32 ConeOfFire_Timer; + uint32 BellowingRoar_Timer; + uint32 Fly_Timer; + uint32 Turn_Timer; + uint32 UnsummonCheck; + bool flight; + uint64 VazrudenGUID; + SpellEntry *liquid_fire; + + void Reset() + { + Fireball_Timer = 4000; + Fly_Timer = 45000; + Turn_Timer = 0; + UnsummonCheck = 5000; + } + + void EnterCombat(Unit* /*who*/) {} + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == ENTRY_LIQUID_FIRE) + { + summoned->SetLevel(me->getLevel()); + summoned->setFaction(me->getFaction()); + summoned->CastSpell(summoned,SPELL_SUMMON_LIQUID_FIRE,true); + summoned->CastSpell(summoned,SPELL_FIRE_NOVA_VISUAL,true); + } + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry* entry) + { + if (pTarget && entry->Id == uint32(SPELL_FIREBALL)) + me->SummonCreature(ENTRY_LIQUID_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),pTarget->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,30000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (UnsummonCheck < diff && me->isAlive()) + me->DisappearAndDie(); + else + UnsummonCheck -= diff; + return; + } + + if (Fireball_Timer <= diff) + { + if (Unit *victim = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(victim, SPELL_FIREBALL, true); + Fireball_Timer = urand(4000,7000); + } else Fireball_Timer -= diff; + + if (flight) // phase 1 - the flight + { + Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); + if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) + { + flight = false; + BellowingRoar_Timer = 6000; + ConeOfFire_Timer = 12000; + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->Clear(); + if (Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) + me->AI()->AttackStart(victim); + DoStartMovement(me->getVictim()); + DoScriptText(EMOTE, me); + return; + } else Fly_Timer -= diff; + + if (Turn_Timer <= diff) + { + uint32 waypoint = (Fly_Timer/10000)%2; + if (me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) + me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); + Turn_Timer = 10000; + } else Turn_Timer -= diff; + } + else // phase 2 - land fight + { + if (ConeOfFire_Timer <= diff) + { + DoCast(me, SPELL_CONE_OF_FIRE); + ConeOfFire_Timer = 12000; + Fireball_Timer = 4000; + } else ConeOfFire_Timer -= diff; + + if (IsHeroic()) + if (BellowingRoar_Timer <= diff) + { + DoCast(me, SPELL_BELLOWING_ROAR); + BellowingRoar_Timer = 45000; + } else BellowingRoar_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +struct boss_vazrudenAI : public ScriptedAI +{ + boss_vazrudenAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Revenge_Timer; + bool WipeSaid; + uint32 UnsummonCheck; + + void Reset() + { + Revenge_Timer = 4000; + UnsummonCheck = 2000; + WipeSaid = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void KilledUnit(Unit* who) + { + if (who && who->GetEntry() != ENTRY_VAZRUDEN) + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* who) + { + if (who && who != me) + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (UnsummonCheck < diff && me->isAlive()) + { + if (!WipeSaid) + { + DoScriptText(SAY_WIPE, me); + WipeSaid = true; + } + me->DisappearAndDie(); + } else UnsummonCheck -= diff; + return; + } + + if (Revenge_Timer <= diff) + { + if (Unit *victim = me->getVictim()) + DoCast(victim, SPELL_REVENGE); + Revenge_Timer = 5000; + } else Revenge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_vazruden_the_heraldAI : public ScriptedAI +{ + boss_vazruden_the_heraldAI(Creature *c) : ScriptedAI(c) + { + summoned = false; + sentryDown = false; + NazanGUID = 0; + VazrudenGUID = 0; + } + + uint32 phase; + uint32 waypoint; + uint32 check; + bool sentryDown; + uint64 NazanGUID; + uint64 VazrudenGUID; + bool summoned; + + void Reset() + { + phase = 0; + waypoint = 0; + check = 0; + UnsummonAdds(); + me->GetMotionMaster()->MovePath(PATH_ENTRY, true); + } + + void UnsummonAdds() + { + if (summoned) + { + Creature *Nazan = Unit::GetCreature(*me, NazanGUID); + if (!Nazan) + Nazan = me->FindNearestCreature(ENTRY_NAZAN, 5000); + if (Nazan) + { + Nazan->DisappearAndDie(); + NazanGUID = 0; + } + + Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); + if (!Vazruden) + Vazruden = me->FindNearestCreature(ENTRY_VAZRUDEN, 5000); + if (Vazruden) + { + Vazruden->DisappearAndDie(); + VazrudenGUID = 0; + } + summoned = false; + me->clearUnitState(UNIT_STAT_ROOT); + me->SetVisibility(VISIBILITY_ON); + } + } + + void SummonAdds() + { + if (!summoned) + { + if (Creature* Vazruden = me->SummonCreature(ENTRY_VAZRUDEN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) + VazrudenGUID = Vazruden->GetGUID(); + if (Creature* Nazan = me->SummonCreature(ENTRY_NAZAN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) + NazanGUID = Nazan->GetGUID(); + summoned = true; + me->SetVisibility(VISIBILITY_OFF); + me->addUnitState(UNIT_STAT_ROOT); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (phase == 0) + { + phase = 1; + check = 0; + DoScriptText(SAY_INTRO, me); + } + } + + void JustSummoned(Creature *summoned) + { + if (!summoned) return; + Unit *victim = me->getVictim(); + if (summoned->GetEntry() == ENTRY_NAZAN) + { + CAST_AI(boss_nazanAI, summoned->AI())->VazrudenGUID = VazrudenGUID; + summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + summoned->SetSpeed(MOVE_FLIGHT, 2.5); + if (victim) + AttackStartNoMove(victim); + } + else if (victim) + summoned->AI()->AttackStart(victim); + } + + void SentryDownBy(Unit* killer) + { + if (sentryDown) + { + AttackStartNoMove(killer); + sentryDown = false; + } + else + sentryDown = true; + } + + void UpdateAI(const uint32 diff) + { + switch(phase) + { + case 0: // circle around the platform + return; + break; + case 1: // go to the middle and begin the fight + if (check <= diff) + { + if (!me->IsWithinDist3d(VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],5)) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2]); + check = 1000; + } + else + { + SummonAdds(); + phase = 2; + return; + } + } else check -= diff; + break; + default: // adds do the job now + if (check <= diff) + { + Creature *Nazan = Unit::GetCreature(*me, NazanGUID); + Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); + if (Nazan && Nazan->isAlive() || Vazruden && Vazruden->isAlive()) + { + if (Nazan && Nazan->getVictim() || Vazruden && Vazruden->getVictim()) + return; + else + { + UnsummonAdds(); + EnterEvadeMode(); + return; + } + } + else + { + me->SummonGameObject(ENTRY_REINFORCED_FEL_IRON_CHEST,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,0,0,0,0,0); + me->SetLootRecipient(NULL); // don't think this is necessary.. + me->Kill(me); + } + check = 2000; + } else check -= diff; + break; + } + } +}; + +struct mob_hellfire_sentryAI : public ScriptedAI +{ + mob_hellfire_sentryAI(Creature *c) : ScriptedAI(c) {} + + uint32 KidneyShot_Timer; + + void Reset() + { + KidneyShot_Timer = urand(3000,7000); + } + + void EnterCombat(Unit* /*who*/) {} + + void JustDied(Unit* who) + { + if (Creature *herald = me->FindNearestCreature(ENTRY_VAZRUDEN_HERALD,150)) + CAST_AI(boss_vazruden_the_heraldAI, herald->AI())->SentryDownBy(who); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (KidneyShot_Timer <= diff) + { + if (Unit *victim = me->getVictim()) + DoCast(victim, SPELL_KIDNEY_SHOT); + KidneyShot_Timer = 20000; + } else KidneyShot_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vazruden_the_herald(Creature* pCreature) +{ + return new boss_vazruden_the_heraldAI (pCreature); +} + +CreatureAI* GetAI_boss_vazruden(Creature* pCreature) +{ + return new boss_vazrudenAI (pCreature); +} + +CreatureAI* GetAI_boss_nazan(Creature* pCreature) +{ + return new boss_nazanAI (pCreature); +} + +CreatureAI* GetAI_mob_hellfire_sentry(Creature* pCreature) +{ + return new mob_hellfire_sentryAI (pCreature); +} + +void AddSC_boss_vazruden_the_herald() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vazruden_the_herald"; + newscript->GetAI = &GetAI_boss_vazruden_the_herald; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_vazruden"; + newscript->GetAI = &GetAI_boss_vazruden; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_nazan"; + newscript->GetAI = &GetAI_boss_nazan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_hellfire_sentry"; + newscript->GetAI = &GetAI_mob_hellfire_sentry; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp new file mode 100644 index 00000000000..f0e813d3890 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp @@ -0,0 +1,156 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Watchkeeper_Gargolmar +SD%Complete: 80 +SDComment: Missing adds to heal him. Surge should be used on pTarget furthest away, not random. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_TAUNT -1543000 +#define SAY_HEAL -1543001 +#define SAY_SURGE -1543002 +#define SAY_AGGRO_1 -1543003 +#define SAY_AGGRO_2 -1543004 +#define SAY_AGGRO_3 -1543005 +#define SAY_KILL_1 -1543006 +#define SAY_KILL_2 -1543007 +#define SAY_DIE -1543008 + +#define SPELL_MORTAL_WOUND 30641 +#define H_SPELL_MORTAL_WOUND 36814 +#define SPELL_SURGE 34645 +#define SPELL_RETALIATION 22857 + +struct boss_watchkeeper_gargolmarAI : public ScriptedAI +{ + boss_watchkeeper_gargolmarAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Surge_Timer; + uint32 MortalWound_Timer; + uint32 Retaliation_Timer; + + bool HasTaunted; + bool YelledForHeal; + + void Reset() + { + Surge_Timer = 5000; + MortalWound_Timer = 4000; + Retaliation_Timer = 0; + + HasTaunted = false; + YelledForHeal = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void MoveInLineOfSight(Unit* who) + { + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (!HasTaunted && me->IsWithinDistInMap(who, 60.0f)) + { + DoScriptText(SAY_TAUNT, me); + HasTaunted = true; + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (MortalWound_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + MortalWound_Timer = 5000+rand()%8000; + } else MortalWound_Timer -= diff; + + if (Surge_Timer <= diff) + { + DoScriptText(SAY_SURGE, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SURGE); + + Surge_Timer = 5000+rand()%8000; + } else Surge_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) + { + if (Retaliation_Timer <= diff) + { + DoCast(me, SPELL_RETALIATION); + Retaliation_Timer = 30000; + } else Retaliation_Timer -= diff; + } + + if (!YelledForHeal) + { + if ((me->GetHealth()*100) / me->GetMaxHealth() < 40) + { + DoScriptText(SAY_HEAL, me); + YelledForHeal = true; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_watchkeeper_gargolmarAI(Creature* pCreature) +{ + return new boss_watchkeeper_gargolmarAI (pCreature); +} + +void AddSC_boss_watchkeeper_gargolmar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_watchkeeper_gargolmar"; + newscript->GetAI = &GetAI_boss_watchkeeper_gargolmarAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h new file mode 100644 index 00000000000..599aa237774 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h @@ -0,0 +1,16 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_RAMPARTS_H +#define DEF_RAMPARTS_H + +#define MAX_ENCOUNTER 2 + +enum eTypes +{ + TYPE_VAZRUDEN = 1, + TYPE_NAZAN = 2 +}; + +#endif diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp new file mode 100644 index 00000000000..29c58675e9c --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp @@ -0,0 +1,84 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Hellfire_Ramparts +SD%Complete: 50 +SDComment: +SDCategory: Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" +#include "hellfire_ramparts.h" + +struct instance_ramparts : public ScriptedInstance +{ + instance_ramparts(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 m_uiChestNGUID; + uint64 m_uiChestHGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiChestNGUID = 0; + m_uiChestHGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 185168: m_uiChestNGUID = pGo->GetGUID(); break; + case 185169: m_uiChestHGUID = pGo->GetGUID(); break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + debug_log("TSCR: Instance Ramparts: SetData received for type %u with data %u",uiType,uiData); + + switch(uiType) + { + case TYPE_VAZRUDEN: + if (uiData == DONE && m_auiEncounter[1] == DONE) + DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); + m_auiEncounter[0] = uiData; + break; + case TYPE_NAZAN: + if (uiData == DONE && m_auiEncounter[0] == DONE) + DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); + m_auiEncounter[1] = uiData; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_ramparts(Map* pMap) +{ + return new instance_ramparts(pMap); +} + +void AddSC_instance_ramparts() +{ + Script* pNewScript; + pNewScript = new Script; + pNewScript->Name = "instance_ramparts"; + pNewScript->GetInstanceData = &GetInstanceData_instance_ramparts; + pNewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp new file mode 100644 index 00000000000..5fb381f4065 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp @@ -0,0 +1,570 @@ +/* Copyright(C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +*(at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Magtheridon +SD%Complete: 60 +SDComment: In Development +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "magtheridons_lair.h" + +struct Yell +{ + int32 id; +}; + +static Yell RandomTaunt[]= +{ + {-1544000}, + {-1544001}, + {-1544002}, + {-1544003}, + {-1544004}, + {-1544005}, +}; + +#define SAY_FREED -1544006 +#define SAY_AGGRO -1544007 +#define SAY_BANISH -1544008 +#define SAY_CHAMBER_DESTROY -1544009 +#define SAY_PLAYER_KILLED -1544010 +#define SAY_DEATH -1544011 + +#define EMOTE_BERSERK -1544012 +#define EMOTE_BLASTNOVA -1544013 +#define EMOTE_BEGIN -1544014 + +#define MOB_MAGTHERIDON 17257 +#define MOB_ROOM 17516 +#define MOB_CHANNELLER 17256 +#define MOB_ABYSSAL 17454 + +#define SPELL_BLASTNOVA 30616 +#define SPELL_CLEAVE 30619 +#define SPELL_QUAKE_TRIGGER 30657 // must be cast with 30561 as the proc spell +#define SPELL_QUAKE_KNOCKBACK 30571 +#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 +#define SPELL_BLAZE_TRAP 30542 +#define SPELL_DEBRIS_KNOCKDOWN 36449 +#define SPELL_DEBRIS_VISUAL 30632 +#define SPELL_DEBRIS_DAMAGE 30631 // core bug, does not support target 8 +#define SPELL_CAMERA_SHAKE 36455 +#define SPELL_BERSERK 27680 + +#define SPELL_SHADOW_CAGE 30168 +#define SPELL_SHADOW_GRASP 30410 +#define SPELL_SHADOW_GRASP_VISUAL 30166 +#define SPELL_MIND_EXHAUSTION 44032 //Casted by the cubes when channeling ends + +#define SPELL_SHADOW_CAGE_C 30205 +#define SPELL_SHADOW_GRASP_C 30207 + +#define SPELL_SHADOW_BOLT_VOLLEY 30510 +#define SPELL_DARK_MENDING 30528 +#define SPELL_FEAR 30530 //39176 +#define SPELL_BURNING_ABYSSAL 30511 +#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 + +#define SPELL_FIRE_BLAST 37110 + +// count of clickers needed to interrupt blast nova +#define CLICKERS_COUNT 5 + +typedef std::map CubeMap; + +struct mob_abyssalAI : public ScriptedAI +{ + mob_abyssalAI(Creature *c) : ScriptedAI(c) + { + trigger = 0; + Despawn_Timer = 60000; + } + + uint32 FireBlast_Timer; + uint32 Despawn_Timer; + uint32 trigger; + + void Reset() + { + FireBlast_Timer = 6000; + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (trigger == 2 && spell->Id == SPELL_BLAZE_TARGET) + { + DoCast(me, SPELL_BLAZE_TRAP, true); + me->SetVisibility(VISIBILITY_OFF); + Despawn_Timer = 130000; + } + } + + void SetTrigger(uint32 _trigger) + { + trigger = _trigger; + me->SetDisplayId(11686); + if (trigger == 1) //debris + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_DEBRIS_VISUAL, true); + FireBlast_Timer = 5000; + Despawn_Timer = 10000; + } + } + + void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} + void AttackStart(Unit *who) {if (!trigger) ScriptedAI::AttackStart(who);} + void MoveInLineOfSight(Unit *who) {if (!trigger) ScriptedAI::MoveInLineOfSight(who);} + + void UpdateAI(const uint32 diff) + { + if (trigger) + { + if (trigger == 1) + { + if (FireBlast_Timer <= diff) + { + DoCast(me, SPELL_DEBRIS_DAMAGE, true); + trigger = 3; + } else FireBlast_Timer -= diff; + } + return; + } + + if (Despawn_Timer <= diff) + { + me->ForcedDespawn(); + } else Despawn_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (FireBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRE_BLAST); + FireBlast_Timer = 5000+rand()%10000; + } else FireBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_magtheridonAI : public ScriptedAI +{ + boss_magtheridonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + + // target 7, random target with certain entry spell, need core fix + SpellEntry *TempSpell; + TempSpell = GET_SPELL(SPELL_BLAZE_TARGET); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 6) + { + TempSpell->EffectImplicitTargetA[0] = 6; + TempSpell->EffectImplicitTargetB[0] = 0; + } + TempSpell = GET_SPELL(SPELL_QUAKE_TRIGGER); + if (TempSpell && TempSpell->EffectTriggerSpell[0] != SPELL_QUAKE_KNOCKBACK) + { + TempSpell->EffectTriggerSpell[0] = SPELL_QUAKE_KNOCKBACK; + } + } + + CubeMap Cube; + + ScriptedInstance* pInstance; + + uint32 Berserk_Timer; + uint32 Quake_Timer; + uint32 Cleave_Timer; + uint32 BlastNova_Timer; + uint32 Blaze_Timer; + uint32 Debris_Timer; + uint32 RandChat_Timer; + + bool Phase3; + bool NeedCheckCube; + + void Reset() + { + Berserk_Timer = 1320000; + Quake_Timer = 40000; + Debris_Timer = 10000; + Blaze_Timer = 10000+rand()%20000; + BlastNova_Timer = 60000; + Cleave_Timer = 15000; + RandChat_Timer = 90000; + + Phase3 = false; + NeedCheckCube = false; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->addUnitState(UNIT_STAT_STUNNED); + DoCast(me, SPELL_SHADOW_CAGE_C, true); + } + + void JustReachedHome() + { + if (pInstance) + { + pInstance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED); + pInstance->SetData(DATA_COLLAPSE, false); + } + } + + void SetClicker(uint64 cubeGUID, uint64 clickerGUID) + { + // to avoid multiclicks from 1 cube + if (uint64 guid = Cube[cubeGUID]) + DebuffClicker(Unit::GetUnit(*me, guid)); + Cube[cubeGUID] = clickerGUID; + NeedCheckCube = true; + } + + //function to interrupt channeling and debuff clicker with mind exh(used if second person clicks with same cube or after dispeling/ending shadow grasp DoT) + void DebuffClicker(Unit *clicker) + { + if (!clicker || !clicker->isAlive()) + return; + + clicker->RemoveAurasDueToSpell(SPELL_SHADOW_GRASP); // cannot interrupt triggered spells + clicker->InterruptNonMeleeSpells(false); + clicker->CastSpell(clicker, SPELL_MIND_EXHAUSTION, true); + } + + void NeedCheckCubeStatus() + { + uint32 ClickerNum = 0; + // now checking if every clicker has debuff from manticron(it is dispelable atm rev 6110 : S) + // if not - apply mind exhaustion and delete from clicker's list + for (CubeMap::iterator i = Cube.begin(); i != Cube.end(); ++i) + { + Unit *clicker = Unit::GetUnit(*me, (*i).second); + if (!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP)) + { + DebuffClicker(clicker); + (*i).second = 0; + } else ++ClickerNum; + } + + // if 5 clickers from other cubes apply shadow cage + if (ClickerNum >= CLICKERS_COUNT && !me->HasAura(SPELL_SHADOW_CAGE)) + { + DoScriptText(SAY_BANISH, me); + DoCast(me, SPELL_SHADOW_CAGE, true); + } + else if (ClickerNum < CLICKERS_COUNT && me->HasAura(SPELL_SHADOW_CAGE)) + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); + + if (!ClickerNum) NeedCheckCube = false; + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_PLAYER_KILLED, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_MAGTHERIDON_EVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void AttackStart(Unit *who) + { + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS); + DoZoneInCombat(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); + + DoScriptText(SAY_FREED, me); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + { + if (RandChat_Timer <= diff) + { + DoScriptText(RandomTaunt[rand()%6].id, me); + RandChat_Timer = 90000; + } else RandChat_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + if (NeedCheckCube) NeedCheckCubeStatus(); + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + DoScriptText(EMOTE_BERSERK, me); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 10000; + } else Cleave_Timer -= diff; + + if (BlastNova_Timer <= diff) + { + // to avoid earthquake interruption + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + { + DoScriptText(EMOTE_BLASTNOVA, me); + DoCast(me, SPELL_BLASTNOVA); + BlastNova_Timer = 60000; + } + } else BlastNova_Timer -= diff; + + if (Quake_Timer <= diff) + { + // to avoid blastnova interruption + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_QUAKE_TRIGGER, true); + Quake_Timer = 50000; + } + } else Quake_Timer -= diff; + + if (Blaze_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (summon) + { + CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(2); + DoCast(summon, SPELL_BLAZE_TARGET, true); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + Blaze_Timer = 20000 + rand()%20000; + } else Blaze_Timer -= diff; + + if (!Phase3 && me->GetHealth()*10 < me->GetMaxHealth()*3 + && !me->IsNonMeleeSpellCasted(false) // blast nova + && !me->hasUnitState(UNIT_STAT_STUNNED)) // shadow cage and earthquake + { + Phase3 = true; + DoScriptText(SAY_CHAMBER_DESTROY, me); + DoCast(me, SPELL_CAMERA_SHAKE, true); + DoCast(me, SPELL_DEBRIS_KNOCKDOWN, true); + + if (pInstance) + pInstance->SetData(DATA_COLLAPSE, true); + } + + if (Phase3) + { + if (Debris_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (summon) CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(1); + } + Debris_Timer = 10000; + } else Debris_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_hellfire_channelerAI : public ScriptedAI +{ + mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c) + { + pInstance =me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ShadowBoltVolley_Timer; + uint32 DarkMending_Timer; + uint32 Fear_Timer; + uint32 Infernal_Timer; + + uint32 Check_Timer; + + void Reset() + { + ShadowBoltVolley_Timer = 8000 + rand()%2000; + DarkMending_Timer = 10000; + Fear_Timer = 15000 + rand()%5000; + Infernal_Timer = 10000 + rand()%40000; + + Check_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS); + + me->InterruptNonMeleeSpells(false); + DoZoneInCombat(); + } + + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED); + + DoCast(me, SPELL_SHADOW_GRASP_C, false); + } + + void JustSummoned(Creature *summon) + { + summon->AI()->AttackStart(me->getVictim()); + } + + void DamageTaken(Unit*, uint32 &damage) + { + if (damage >= me->GetHealth()) + DoCast(me, SPELL_SOUL_TRANSFER, true); + } + + void JustDied(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); + ShadowBoltVolley_Timer = 10000 + rand()%10000; + } else ShadowBoltVolley_Timer -= diff; + + if (DarkMending_Timer <= diff) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) + DoCast(me, SPELL_DARK_MENDING); + DarkMending_Timer = 10000 +(rand() % 10000); + } else DarkMending_Timer -= diff; + + if (Fear_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_FEAR); + Fear_Timer = 25000 + rand()%15000; + } else Fear_Timer -= diff; + + if (Infernal_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BURNING_ABYSSAL, true); + Infernal_Timer = 30000 + rand()%10000; + } else Infernal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Manticron Cube +bool GOHello_go_Manticron_Cube(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + if (!pInstance) + return true; + if (pInstance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) return true; + Creature *Magtheridon =Unit::GetCreature(*pGo, pInstance->GetData64(DATA_MAGTHERIDON)); + if (!Magtheridon || !Magtheridon->isAlive()) return true; + + // if exhausted or already channeling return + if (pPlayer->HasAura(SPELL_MIND_EXHAUSTION) || pPlayer->HasAura(SPELL_SHADOW_GRASP)) + return true; + + pPlayer->InterruptNonMeleeSpells(false); + pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP, true); + pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP_VISUAL, false); + CAST_AI(boss_magtheridonAI, Magtheridon->AI())->SetClicker(pGo->GetGUID(), pPlayer->GetGUID()); + return true; +} + +CreatureAI* GetAI_boss_magtheridon(Creature* pCreature) +{ + return new boss_magtheridonAI(pCreature); +} + +CreatureAI* GetAI_mob_hellfire_channeler(Creature* pCreature) +{ + return new mob_hellfire_channelerAI(pCreature); +} + +CreatureAI* GetAI_mob_abyssalAI(Creature* pCreature) +{ + return new mob_abyssalAI(pCreature); +} + +void AddSC_boss_magtheridon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magtheridon"; + newscript->GetAI = &GetAI_boss_magtheridon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_hellfire_channeler"; + newscript->GetAI = &GetAI_mob_hellfire_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_manticron_cube"; + newscript->pGOHello = &GOHello_go_Manticron_Cube; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_abyssal"; + newscript->GetAI = &GetAI_mob_abyssalAI; + newscript->RegisterSelf(); + +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp new file mode 100644 index 00000000000..d5b459a1fa1 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp @@ -0,0 +1,254 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Magtheridons_Lair +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "magtheridons_lair.h" + +#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 +#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 + +#define CHAMBER_CENTER_X -15.14 +#define CHAMBER_CENTER_Y 1.8 +#define CHAMBER_CENTER_Z -0.4 + +#define MAX_ENCOUNTER 2 + +#define EMOTE_BONDS_WEAKEN "'s bonds begin to weaken!" + +struct instance_magtheridons_lair : public ScriptedInstance +{ + instance_magtheridons_lair(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + } + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 MagtheridonGUID; + std::set ChannelerGUID; + uint64 DoorGUID; + std::set ColumnGUID; + + uint32 CageTimer; + uint32 RespawnTimer; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + MagtheridonGUID = 0; + ChannelerGUID.clear(); + DoorGUID = 0; + ColumnGUID.clear(); + + CageTimer = 0; + RespawnTimer = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17257: + MagtheridonGUID = pCreature->GetGUID(); + break; + case 17256: + ChannelerGUID.insert(pCreature->GetGUID()); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 181713: + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 0); + break; + case 183847: + DoorGUID = pGo->GetGUID(); + break; + case 184653: // hall + case 184634: // six columns + case 184635: + case 184636: + case 184637: + case 184638: + case 184639: + ColumnGUID.insert(pGo->GetGUID()); + break; + } + } + + uint64 GetData64(uint32 type) + { + switch(type) + { + case DATA_MAGTHERIDON: + return MagtheridonGUID; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAGTHERIDON_EVENT: + m_auiEncounter[0] = data; + if (data == NOT_STARTED) + RespawnTimer = 10000; + if (data != IN_PROGRESS) + HandleGameObject(DoorGUID, true); + break; + case DATA_CHANNELER_EVENT: + switch(data) + { + case NOT_STARTED: // Reset all channelers once one is reset. + if (m_auiEncounter[1] != NOT_STARTED) + { + m_auiEncounter[1] = NOT_STARTED; + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + if (Creature *Channeler = instance->GetCreature(*i)) + { + if (Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); + } + } + CageTimer = 0; + HandleGameObject(DoorGUID, true); + } + break; + case IN_PROGRESS: // Event start. + if (m_auiEncounter[1] != IN_PROGRESS) + { + m_auiEncounter[1] = IN_PROGRESS; + // Let all five channelers aggro. + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + Creature *Channeler = instance->GetCreature(*i); + if (Channeler && Channeler->isAlive()) + Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); + } + // Release Magtheridon after two minutes. + Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); + if (Magtheridon && Magtheridon->isAlive()) + { + Magtheridon->MonsterTextEmote(EMOTE_BONDS_WEAKEN, 0); + CageTimer = 120000; + } + HandleGameObject(DoorGUID, false); + } + break; + case DONE: // Add buff and check if all channelers are dead. + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + Creature *Channeler = instance->GetCreature(*i); + if (Channeler && Channeler->isAlive()) + { + //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); + data = IN_PROGRESS; + break; + } + } + break; + } + m_auiEncounter[1] = data; + break; + case DATA_COLLAPSE: + // true - collapse / false - reset + for (std::set::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) + DoUseDoorOrButton(*i); + break; + default: + break; + } + } + + uint32 GetData(uint32 type) + { + if (type == DATA_MAGTHERIDON_EVENT) + return m_auiEncounter[0]; + return 0; + } + + void Update(uint32 diff) + { + if (CageTimer) + { + if (CageTimer <= diff) + { + Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); + if (Magtheridon && Magtheridon->isAlive()) + { + Magtheridon->clearUnitState(UNIT_STAT_STUNNED); + Magtheridon->AI()->AttackStart(Magtheridon->SelectNearestTarget(999)); + } + CageTimer = 0; + } else CageTimer -= diff; + } + + if (RespawnTimer) + { + if (RespawnTimer <= diff) + { + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + if (Creature *Channeler = instance->GetCreature(*i)) + { + if (Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); + } + } + RespawnTimer = 0; + } else RespawnTimer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_magtheridons_lair(Map* pMap) +{ + return new instance_magtheridons_lair(pMap); +} + +void AddSC_instance_magtheridons_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_magtheridons_lair"; + newscript->GetInstanceData = &GetInstanceData_instance_magtheridons_lair; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h new file mode 100644 index 00000000000..1b3e525fc54 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MAGTHERIDONS_LAIR_H +#define DEF_MAGTHERIDONS_LAIR_H + +#define DATA_MAGTHERIDON_EVENT 1 +#define DATA_MAGTHERIDON 3 +#define DATA_CHANNELER_EVENT 2 +#define DATA_COLLAPSE 6 +#define DATA_CHANNELER 9 +#endif + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp new file mode 100644 index 00000000000..e3ded52edc9 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp @@ -0,0 +1,396 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grand_Warlock_Nethekurse +SD%Complete: 75 +SDComment: encounter not fully completed. missing part where boss kill minions. +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_grand_warlock_nethekurse +mob_fel_orc_convert +mob_lesser_shadow_fissure +EndContentData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +struct Say +{ + int32 id; +}; + +static Say PeonAttacked[]= +{ + {-1540001}, + {-1540002}, + {-1540003}, + {-1540004}, +}; +static Say PeonDies[]= +{ + {-1540005}, + {-1540006}, + {-1540007}, + {-1540008}, +}; + +#define SAY_INTRO -1540000 +#define SAY_TAUNT_1 -1540009 +#define SAY_TAUNT_2 -1540010 +#define SAY_TAUNT_3 -1540011 +#define SAY_AGGRO_1 -1540012 +#define SAY_AGGRO_2 -1540013 +#define SAY_AGGRO_3 -1540014 +#define SAY_SLAY_1 -1540015 +#define SAY_SLAY_2 -1540016 +#define SAY_DIE -1540017 + +#define SPELL_DEATH_COIL 30500 +#define SPELL_DARK_SPIN 30502 // core bug spell attack caster :D +#define SPELL_SHADOW_FISSURE 30496 // Summon the ShadowFissure NPC + +#define SPELL_SHADOW_CLEAVE 30495 +#define H_SPELL_SHADOW_SLAM 35953 + +#define SPELL_HEMORRHAGE 30478 + +#define SPELL_CONSUMPTION 30497 +#define SPELL_TEMPORARY_VISUAL 39312 // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should + +struct boss_grand_warlock_nethekurseAI : public ScriptedAI +{ + boss_grand_warlock_nethekurseAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool IntroOnce; + bool IsIntroEvent; + bool IsMainEvent; + bool SpinOnce; + //bool HasTaunted; + bool Phase; + + uint32 PeonEngagedCount; + uint32 PeonKilledCount; + + uint32 IntroEvent_Timer; + uint32 DeathCoil_Timer; + uint32 ShadowFissure_Timer; + uint32 Cleave_Timer; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + IsIntroEvent = false; + IntroOnce = false; + IsMainEvent = false; + //HasTaunted = false; + SpinOnce = false; + Phase = false; + + PeonEngagedCount = 0; + PeonKilledCount = 0; + + IntroEvent_Timer = 90000; //how long before getting bored and kills his minions? + DeathCoil_Timer = 20000; + ShadowFissure_Timer = 8000; + Cleave_Timer = 5000; + } + + void DoYellForPeonAggro() + { + if (PeonEngagedCount >= 4) + return; + + DoScriptText(PeonAttacked[PeonEngagedCount].id, me); + ++PeonEngagedCount; + } + + void DoYellForPeonDeath() + { + if (PeonKilledCount >= 4) + return; + + DoScriptText(PeonDies[PeonKilledCount].id, me); + ++PeonKilledCount; + + if (PeonKilledCount == 4) + { + IsIntroEvent = false; + IsMainEvent = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void DoTauntPeons() + { + DoScriptText(RAND(SAY_TAUNT_1,SAY_TAUNT_2,SAY_TAUNT_3), me); + + //TODO: kill the peons first + IsIntroEvent = false; + PeonEngagedCount = 4; + PeonKilledCount = 4; + IsMainEvent = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackStart(Unit* who) + { + if (IsIntroEvent || !IsMainEvent) + return; + + if (me->Attack(who, true)) + { + if (Phase) + DoStartNoMovement(who); + else + DoStartMovement(who); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!IntroOnce && me->IsWithinDistInMap(who, 50.0f)) + { + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(SAY_INTRO, me); + IntroOnce = true; + IsIntroEvent = true; + + if (pInstance) + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + + if (IsIntroEvent || !IsMainEvent) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(16); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //triggered spell of consumption does not properly show it's SpellVisual, wrong spellid? + summoned->CastSpell(summoned,SPELL_TEMPORARY_VISUAL,true); + summoned->CastSpell(summoned,SPELL_CONSUMPTION,false,0,0,me->GetGUID()); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_NETHEKURSE,DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_NETHEKURSE_DOOR), true); + } + + void UpdateAI(const uint32 diff) + { + if (IsIntroEvent) + { + if (!pInstance) + return; + + if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) + { + if (IntroEvent_Timer <= diff) + DoTauntPeons(); + else + IntroEvent_Timer -= diff; + } + } + + if (!UpdateVictim()) + return; + + if (!IsMainEvent) + return; + + if (Phase) + { + if (!SpinOnce) + { + DoCast(me->getVictim(), SPELL_DARK_SPIN); + SpinOnce = true; + } + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_CLEAVE); + Cleave_Timer = 6000+rand()%2500; + } else Cleave_Timer -= diff; + } + else + { + if (ShadowFissure_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_FISSURE); + ShadowFissure_Timer = urand(7500,15000); + } else ShadowFissure_Timer -= diff; + + if (DeathCoil_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_DEATH_COIL); + DeathCoil_Timer = urand(15000,20000); + } else DeathCoil_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) + Phase = true; + + DoMeleeAttackIfReady(); + } + } +}; + +struct mob_fel_orc_convertAI : public ScriptedAI +{ + mob_fel_orc_convertAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 Hemorrhage_Timer; + + void Reset() + { + me->SetNoCallAssistance(true); //we don't want any assistance (WE R HEROZ!) + Hemorrhage_Timer = 3000; + } + + void MoveInLineOfSight(Unit * /*who*/) + { + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + { + if (pInstance->GetData64(DATA_NETHEKURSE)) + { + Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE)); + if (pKurse && me->IsWithinDist(pKurse, 45.0f)) + { + CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonAggro(); + + if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) + return; + else + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + } + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + if (pInstance->GetData(TYPE_NETHEKURSE) != IN_PROGRESS) + return; + if (pInstance->GetData64(DATA_NETHEKURSE)) + if (Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE))) + CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonDeath(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Hemorrhage_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HEMORRHAGE); + Hemorrhage_Timer = 15000; + } else Hemorrhage_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//NOTE: this Creature are also summoned by other spells, for different creatures +struct mob_lesser_shadow_fissureAI : public ScriptedAI +{ + mob_lesser_shadow_fissureAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + void MoveInLineOfSight(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void EnterCombat(Unit* /*who*/) {} +}; + +CreatureAI* GetAI_boss_grand_warlock_nethekurse(Creature* pCreature) +{ + return new boss_grand_warlock_nethekurseAI (pCreature); +} + +CreatureAI* GetAI_mob_fel_orc_convert(Creature* pCreature) +{ + return new mob_fel_orc_convertAI (pCreature); +} + +CreatureAI* GetAI_mob_lesser_shadow_fissure(Creature* pCreature) +{ + return new mob_lesser_shadow_fissureAI (pCreature); +} + +void AddSC_boss_grand_warlock_nethekurse() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_grand_warlock_nethekurse"; + newscript->GetAI = &GetAI_boss_grand_warlock_nethekurse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_orc_convert"; + newscript->GetAI = &GetAI_mob_fel_orc_convert; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lesser_shadow_fissure"; + newscript->GetAI = &GetAI_mob_lesser_shadow_fissure; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp new file mode 100644 index 00000000000..6fa1c9efe33 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp @@ -0,0 +1,404 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warbringer_Omrogg +SD%Complete: 85 +SDComment: Heroic enabled. Spell timing may need additional tweaks +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +mob_omrogg_heads +boss_warbringer_omrogg +EndContentData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +enum eEnums +{ + YELL_DIE_L = -1540039, + YELL_DIE_R = -1540040, + EMOTE_ENRAGE = -1540041, + + SPELL_BLAST_WAVE = 30600, + SPELL_FEAR = 30584, + SPELL_THUNDERCLAP = 30633, + + SPELL_BURNING_MAUL = 30598, + H_SPELL_BURNING_MAUL = 36056, + + NPC_LEFT_HEAD = 19523, + NPC_RIGHT_HEAD = 19524 +}; + +struct Yell +{ + int32 id; + uint32 creature; +}; + +static Yell GoCombat[]= +{ + {-1540018, NPC_LEFT_HEAD}, + {-1540019, NPC_LEFT_HEAD}, + {-1540020, NPC_LEFT_HEAD}, +}; +static Yell GoCombatDelay[]= +{ + {-1540021, NPC_RIGHT_HEAD}, + {-1540022, NPC_RIGHT_HEAD}, + {-1540023, NPC_RIGHT_HEAD}, +}; + +static Yell Threat[]= +{ + {-1540024, NPC_LEFT_HEAD}, + {-1540025, NPC_RIGHT_HEAD}, + {-1540026, NPC_LEFT_HEAD}, + {-1540027, NPC_LEFT_HEAD}, +}; +static Yell ThreatDelay1[]= +{ + {-1540028, NPC_RIGHT_HEAD}, + {-1540029, NPC_LEFT_HEAD}, + {-1540030, NPC_RIGHT_HEAD}, + {-1540031, NPC_RIGHT_HEAD}, +}; +static Yell ThreatDelay2[]= +{ + {-1540032, NPC_LEFT_HEAD}, + {-1540033, NPC_RIGHT_HEAD}, + {-1540034, NPC_LEFT_HEAD}, + {-1540035, NPC_LEFT_HEAD}, +}; + +static Yell Killing[]= +{ + {-1540036, NPC_LEFT_HEAD}, + {-1540037, NPC_RIGHT_HEAD}, +}; +static Yell KillingDelay[]= +{ + {-1540038, NPC_RIGHT_HEAD}, + {-1000000, NPC_LEFT_HEAD}, +}; + +struct mob_omrogg_headsAI : public ScriptedAI +{ + mob_omrogg_headsAI(Creature *c) : ScriptedAI(c) {} + + bool DeathYell; + uint32 Death_Timer; + + void Reset() + { + Death_Timer = 4000; + DeathYell = false; + } + void EnterCombat(Unit* /*who*/) {} + + void DoDeathYell() + { + DeathYell = true; + } + + void UpdateAI(const uint32 diff) + { + if (!DeathYell) + return; + + if (Death_Timer <= diff) + { + DoScriptText(YELL_DIE_R, me); + Death_Timer = false; + me->setDeathState(JUST_DIED); + } else Death_Timer -= diff; + } +}; + +struct boss_warbringer_omroggAI : public ScriptedAI +{ + boss_warbringer_omroggAI(Creature *c) : ScriptedAI(c) + { + LeftHeadGUID = 0; + RightHeadGUID = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 LeftHeadGUID; + uint64 RightHeadGUID; + int iaggro; + int ithreat; + int ikilling; + + bool AggroYell; + bool ThreatYell; + bool ThreatYell2; + bool KillingYell; + + uint32 Delay_Timer; + uint32 BlastWave_Timer; + uint32 BlastCount; + uint32 Fear_Timer; + uint32 BurningMaul_Timer; + uint32 ThunderClap_Timer; + uint32 ResetThreat_Timer; + + void Reset() + { + if (Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) + { + pLeftHead->setDeathState(JUST_DIED); + LeftHeadGUID = 0; + } + + if (Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID)) + { + pRightHead->setDeathState(JUST_DIED); + RightHeadGUID = 0; + } + + AggroYell = false; + ThreatYell = false; + ThreatYell2 = false; + KillingYell = false; + + Delay_Timer = 4000; + BlastWave_Timer = 0; + BlastCount = 0; + Fear_Timer = 8000; + BurningMaul_Timer = 25000; + ThunderClap_Timer = 15000; + ResetThreat_Timer = 30000; + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, NOT_STARTED); //End boss can use this later. O'mrogg must be defeated(DONE) or he will come to aid. + } + + void DoYellForThreat() + { + Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit *pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + ithreat = rand()%4; + + Unit *source = (pLeftHead->GetEntry() == Threat[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(Threat[ithreat].id, source); + + Delay_Timer = 3500; + ThreatYell = true; + } + + void EnterCombat(Unit * /*who*/) + { + me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + + if (Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) + { + iaggro = rand()%3; + + DoScriptText(GoCombat[iaggro].id, pLeftHead); + + Delay_Timer = 3500; + AggroYell = true; + } + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, IN_PROGRESS); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == NPC_LEFT_HEAD) + LeftHeadGUID = summoned->GetGUID(); + + if (summoned->GetEntry() == NPC_RIGHT_HEAD) + RightHeadGUID = summoned->GetGUID(); + + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->SetVisibility(VISIBILITY_OFF); + } + + void KilledUnit(Unit* /*victim*/) + { + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + ikilling = rand()%2; + + Unit *source = (pLeftHead->GetEntry() == Killing[ikilling].creature ? pLeftHead : pRightHead); + + switch(ikilling) + { + case 0: + DoScriptText(Killing[ikilling].id, source); + Delay_Timer = 3500; + KillingYell = true; + break; + case 1: + DoScriptText(Killing[ikilling].id, source); + KillingYell = false; + break; + } + } + + void JustDied(Unit* /*Killer*/) + { + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + DoScriptText(YELL_DIE_L, pLeftHead); + + CAST_AI(mob_omrogg_headsAI, CAST_CRE(pRightHead)->AI())->DoDeathYell(); + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (Delay_Timer <= diff) + { + Delay_Timer = 3500; + + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + if (AggroYell) + { + DoScriptText(GoCombatDelay[iaggro].id, pRightHead); + AggroYell = false; + } + + if (ThreatYell2) + { + Unit *source = (pLeftHead->GetEntry() == ThreatDelay2[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(ThreatDelay2[ithreat].id, source); + ThreatYell2 = false; + } + + if (ThreatYell) + { + Unit *source = (pLeftHead->GetEntry() == ThreatDelay1[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(ThreatDelay1[ithreat].id, source); + ThreatYell = false; + ThreatYell2 = true; + } + + if (KillingYell) + { + Unit *source = (pLeftHead->GetEntry() == KillingDelay[ikilling].creature ? pLeftHead : pRightHead); + + DoScriptText(KillingDelay[ikilling].id, source); + KillingYell = false; + } + } else Delay_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (BlastCount && BlastWave_Timer <= diff) + { + DoCast(me, SPELL_BLAST_WAVE); + BlastWave_Timer = 5000; + ++BlastCount; + + if (BlastCount == 3) + BlastCount = 0; + } else BlastWave_Timer -= diff; + + if (BurningMaul_Timer <= diff) + { + DoScriptText(EMOTE_ENRAGE, me); + DoCast(me, SPELL_BURNING_MAUL); + BurningMaul_Timer = 40000; + BlastWave_Timer = 16000; + BlastCount = 1; + } else BurningMaul_Timer -= diff; + + if (ResetThreat_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoYellForThreat(); + DoResetThreat(); + me->AddThreat(pTarget, 0.0f); + } + ResetThreat_Timer = 25000+rand()%15000; + } else ResetThreat_Timer -= diff; + + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 15000+rand()%20000; + } else Fear_Timer -= diff; + + if (ThunderClap_Timer <= diff) + { + DoCast(me, SPELL_THUNDERCLAP); + ThunderClap_Timer = 15000+rand()%15000; + } else ThunderClap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_warbringer_omrogg(Creature* pCreature) +{ + return new boss_warbringer_omroggAI (pCreature); +} + +CreatureAI* GetAI_mob_omrogg_heads(Creature* pCreature) +{ + return new mob_omrogg_headsAI (pCreature); +} + +void AddSC_boss_warbringer_omrogg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_warbringer_omrogg"; + newscript->GetAI = &GetAI_boss_warbringer_omrogg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_omrogg_heads"; + newscript->GetAI = &GetAI_mob_omrogg_heads; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp new file mode 100644 index 00000000000..b108077518a --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp @@ -0,0 +1,288 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warchief_Kargath_Bladefist +SD%Complete: 90 +SDComment: +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_warchief_kargath_bladefist +EndContentData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO1 -1540042 +#define SAY_AGGRO2 -1540043 +#define SAY_AGGRO3 -1540044 +#define SAY_SLAY1 -1540045 +#define SAY_SLAY2 -1540046 +#define SAY_DEATH -1540047 + +#define SPELL_BLADE_DANCE 30739 +#define H_SPELL_CHARGE 25821 + +#define TARGET_NUM 5 + +#define MOB_SHATTERED_ASSASSIN 17695 +#define MOB_HEARTHEN_GUARD 17621 +#define MOB_SHARPSHOOTER_GUARD 17622 +#define MOB_REAVER_GUARD 17623 + +float AssassEntrance[3] = {275.136,-84.29,2.3}; // y -8 +float AssassExit[3] = {184.233,-84.29,2.3}; // y -8 +float AddsEntrance[3] = {306.036,-84.29,1.93}; + +struct boss_warchief_kargath_bladefistAI : public ScriptedAI +{ + boss_warchief_kargath_bladefistAI(Creature *c) : ScriptedAI(c) + { + } + + std::vector adds; + std::vector assassins; + + uint32 Charge_timer; + uint32 Blade_Dance_Timer; + uint32 Summon_Assistant_Timer; + uint32 resetcheck_timer; + uint32 Wait_Timer; + + uint32 Assassins_Timer; + + uint32 summoned; + bool InBlade; + + uint32 target_num; + + void Reset() + { + removeAdds(); + + me->SetSpeed(MOVE_RUN,2); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + summoned = 2; + InBlade = false; + Wait_Timer = 0; + + Charge_timer = 0; + Blade_Dance_Timer = 45000; + Summon_Assistant_Timer = 30000; + Assassins_Timer = 5000; + resetcheck_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void JustSummoned(Creature *summoned) + { + switch(summoned->GetEntry()) + { + case MOB_HEARTHEN_GUARD: + case MOB_SHARPSHOOTER_GUARD: + case MOB_REAVER_GUARD: + summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0)); + adds.push_back(summoned->GetGUID()); + break; + case MOB_SHATTERED_ASSASSIN: + assassins.push_back(summoned->GetGUID()); + break; + } + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + removeAdds(); + } + + void MovementInform(uint32 type, uint32 id) + { + if (InBlade) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id != 1) + return; + + if (target_num > 0) // to prevent loops + { + Wait_Timer = 1; + DoCast(me, SPELL_BLADE_DANCE, true); + target_num--; + } + } + } + + void removeAdds() + { + for (std::vector::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) + { + Unit* temp = Unit::GetUnit((*me),*itr); + if (temp && temp->isAlive()) + { + (*temp).GetMotionMaster()->Clear(true); + me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CAST_CRE(temp)->RemoveCorpse(); + } + } + adds.clear(); + + for (std::vector::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) + { + Unit* temp = Unit::GetUnit((*me),*itr); + if (temp && temp->isAlive()) + { + (*temp).GetMotionMaster()->Clear(true); + me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CAST_CRE(temp)->RemoveCorpse(); + } + } + assassins.clear(); + } + void SpawnAssassin() + { + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]+8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]-8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]+8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]-8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Assassins_Timer) + if (Assassins_Timer <= diff) + { + SpawnAssassin(); + Assassins_Timer = 0; + } else Assassins_Timer -= diff; + + if (InBlade) + { + if (Wait_Timer) + if (Wait_Timer <= diff) + { + if (target_num <= 0) + { + // stop bladedance + InBlade = false; + me->SetSpeed(MOVE_RUN,2); + me->GetMotionMaster()->MoveChase(me->getVictim()); + Blade_Dance_Timer = 30000; + Wait_Timer = 0; + if (IsHeroic()) + Charge_timer = 5000; + } + else + { + //move in bladedance + float x,y,randx,randy; + randx = (rand()%40); + randy = (rand()%40); + x = 210+ randx ; + y = -60- randy ; + me->GetMotionMaster()->MovePoint(1,x,y,me->GetPositionZ()); + Wait_Timer = 0; + } + } else Wait_Timer -= diff; + } + else + { + if (Blade_Dance_Timer) + if (Blade_Dance_Timer <= diff) + { + target_num = TARGET_NUM; + Wait_Timer = 1; + InBlade = true; + Blade_Dance_Timer = 0; + me->SetSpeed(MOVE_RUN,4); + return; + } else Blade_Dance_Timer -= diff; + + if (Charge_timer) + if (Charge_timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), H_SPELL_CHARGE); + Charge_timer = 0; + } else Charge_timer -= diff; + + if (Summon_Assistant_Timer <= diff) + { + for (uint8 i = 0; i < summoned; ++i) + { + switch (urand(0,2)) + { + case 0: me->SummonCreature(MOB_HEARTHEN_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + case 1: me->SummonCreature(MOB_SHARPSHOOTER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + case 2: me->SummonCreature(MOB_REAVER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + } + } + if (urand(0,9) < 2) + ++summoned; + Summon_Assistant_Timer = urand(25000,35000); + } else Summon_Assistant_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + if (resetcheck_timer <= diff) + { + uint32 tempx,tempy; + tempx = uint32(me->GetPositionX()); + tempy = uint32(me->GetPositionY()); + if (tempx > 255 || tempx < 205) + { + EnterEvadeMode(); + return; + } + resetcheck_timer = 5000; + } else resetcheck_timer -= diff; + } +}; + +CreatureAI* GetAI_boss_warchief_kargath_bladefist(Creature* pCreature) +{ + return new boss_warchief_kargath_bladefistAI (pCreature); +} + +void AddSC_boss_warchief_kargath_bladefist() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_warchief_kargath_bladefist"; + newscript->GetAI = &GetAI_boss_warchief_kargath_bladefist; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp new file mode 100644 index 00000000000..c29df4d6411 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shattered_Halls +SD%Complete: 50 +SDComment: currently missing info about door. instance not complete +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +#define MAX_ENCOUNTER 2 + +#define DOOR_NETHEKURSE 1 + +struct instance_shattered_halls : public ScriptedInstance +{ + instance_shattered_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 nethekurseGUID; + uint64 nethekurseDoorGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + nethekurseGUID = 0; + nethekurseDoorGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case DOOR_NETHEKURSE: nethekurseDoorGUID = pGo->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 16807: nethekurseGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_NETHEKURSE: + m_auiEncounter[0] = data; + break; + case TYPE_OMROGG: + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_NETHEKURSE: + return m_auiEncounter[0]; + case TYPE_OMROGG: + return m_auiEncounter[1]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_NETHEKURSE: + return nethekurseGUID; + case DATA_NETHEKURSE_DOOR: + return nethekurseDoorGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_shattered_halls(Map* pMap) +{ + return new instance_shattered_halls(pMap); +} + +void AddSC_instance_shattered_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shattered_halls"; + newscript->GetInstanceData = &GetInstanceData_instance_shattered_halls; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h new file mode 100644 index 00000000000..cbfa23ec4e0 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHATTERED_H +#define DEF_SHATTERED_H + +#define TYPE_NETHEKURSE 1 +#define DATA_NETHEKURSE 2 +#define DATA_NETHEKURSE_DOOR 3 + +#define TYPE_OMROGG 4 +#endif + diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp new file mode 100644 index 00000000000..69dbc877d89 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp @@ -0,0 +1,520 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Arcatraz +SD%Complete: 60 +SDComment: Warden Mellichar, event controller for Skyriss event. Millhouse Manastorm. TODO: make better combatAI for Millhouse. +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +/* ContentData +npc_millhouse_manastorm +npc_warden_mellichar +mob_zerekethvoidzone +EndContentData */ + +#include "ScriptedPch.h" +#include "arcatraz.h" + +/*##### +# npc_millhouse_manastorm +#####*/ + +#define SAY_INTRO_1 -1552010 +#define SAY_INTRO_2 -1552011 +#define SAY_WATER -1552012 +#define SAY_BUFFS -1552013 +#define SAY_DRINK -1552014 +#define SAY_READY -1552015 +#define SAY_KILL_1 -1552016 +#define SAY_KILL_2 -1552017 +#define SAY_PYRO -1552018 +#define SAY_ICEBLOCK -1552019 +#define SAY_LOWHP -1552020 +#define SAY_DEATH -1552021 +#define SAY_COMPLETE -1552022 + +#define SPELL_CONJURE_WATER 36879 +#define SPELL_ARCANE_INTELLECT 36880 +#define SPELL_ICE_ARMOR 36881 + +#define SPELL_ARCANE_MISSILES 33833 +#define SPELL_CONE_OF_COLD 12611 +#define SPELL_FIRE_BLAST 13341 +#define SPELL_FIREBALL 14034 +#define SPELL_FROSTBOLT 15497 +#define SPELL_PYROBLAST 33975 + +struct npc_millhouse_manastormAI : public ScriptedAI +{ + npc_millhouse_manastormAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 EventProgress_Timer; + uint32 Phase; + bool Init; + bool LowHp; + + uint32 Pyroblast_Timer; + uint32 Fireball_Timer; + + void Reset() + { + EventProgress_Timer = 2000; + LowHp = false; + Init = false; + Phase = 1; + + Pyroblast_Timer = 1000; + Fireball_Timer = 2500; + + if (pInstance) + { + if (pInstance->GetData(TYPE_WARDEN_2) == DONE) + Init = true; + + if (pInstance->GetData(TYPE_HARBINGERSKYRISS) == DONE) + { + DoScriptText(SAY_COMPLETE, me); + } + } + } + + void AttackStart(Unit* pWho) + { + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(pWho, 25.0f); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + /*for questId 10886 (heroic mode only) + if (pInstance && pInstance->GetData(TYPE_HARBINGERSKYRISS) != DONE) + ->FailQuest();*/ + } + + void UpdateAI(const uint32 diff) + { + if (!Init) + { + if (EventProgress_Timer <= diff) + { + if (Phase < 8) + { + switch(Phase) + { + case 1: + DoScriptText(SAY_INTRO_1, me); + EventProgress_Timer = 18000; + break; + case 2: + DoScriptText(SAY_INTRO_2, me); + EventProgress_Timer = 18000; + break; + case 3: + DoScriptText(SAY_WATER, me); + DoCast(me, SPELL_CONJURE_WATER); + EventProgress_Timer = 7000; + break; + case 4: + DoScriptText(SAY_BUFFS, me); + DoCast(me, SPELL_ICE_ARMOR); + EventProgress_Timer = 7000; + break; + case 5: + DoScriptText(SAY_DRINK, me); + DoCast(me, SPELL_ARCANE_INTELLECT); + EventProgress_Timer = 7000; + break; + case 6: + DoScriptText(SAY_READY, me); + EventProgress_Timer = 6000; + break; + case 7: + if (pInstance) + pInstance->SetData(TYPE_WARDEN_2,DONE); + Init = true; + break; + } + ++Phase; + } + } else EventProgress_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) + { + DoScriptText(SAY_LOWHP, me); + LowHp = true; + } + + if (Pyroblast_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoScriptText(SAY_PYRO, me); + + DoCast(me->getVictim(), SPELL_PYROBLAST); + Pyroblast_Timer = 40000; + } else Pyroblast_Timer -=diff; + + if (Fireball_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL); + Fireball_Timer = 4000; + } else Fireball_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_millhouse_manastorm(Creature* pCreature) +{ + return new npc_millhouse_manastormAI (pCreature); +} + +/*##### +# npc_warden_mellichar +#####*/ + +#define YELL_INTRO1 -1552023 +#define YELL_INTRO2 -1552024 +#define YELL_RELEASE1 -1552025 +#define YELL_RELEASE2A -1552026 +#define YELL_RELEASE2B -1552027 +#define YELL_RELEASE3 -1552028 +#define YELL_RELEASE4 -1552029 +#define YELL_WELCOME -1552030 + +//phase 2(acid mobs) +#define ENTRY_TRICKSTER 20905 +#define ENTRY_PH_HUNTER 20906 +//phase 3 +#define ENTRY_MILLHOUSE 20977 +//phase 4(acid mobs) +#define ENTRY_AKKIRIS 20908 +#define ENTRY_SULFURON 20909 +//phase 5(acid mobs) +#define ENTRY_TW_DRAK 20910 +#define ENTRY_BL_DRAK 20911 +//phase 6 +#define ENTRY_SKYRISS 20912 + +//TARGET_SCRIPT +#define SPELL_TARGET_ALPHA 36856 +#define SPELL_TARGET_BETA 36854 +#define SPELL_TARGET_DELTA 36857 +#define SPELL_TARGET_GAMMA 36858 +#define SPELL_TARGET_OMEGA 36852 +#define SPELL_BUBBLE_VISUAL 36849 + +struct npc_warden_mellicharAI : public ScriptedAI +{ + npc_warden_mellicharAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool IsRunning; + bool CanSpawn; + + uint32 EventProgress_Timer; + uint32 Phase; + + void Reset() + { + IsRunning = false; + CanSpawn = false; + + EventProgress_Timer = 22000; + Phase = 1; + + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + DoCast(me, SPELL_TARGET_OMEGA); + + if (pInstance) + pInstance->SetData(TYPE_HARBINGERSKYRISS,NOT_STARTED); + } + + void AttackStart(Unit* /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (IsRunning) + return; + + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + float attackRadius = me->GetAttackDistance(who)/10; + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + EnterCombat(who); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_INTRO1, me); + DoCast(me, SPELL_BUBBLE_VISUAL); + + if (pInstance) + { + pInstance->SetData(TYPE_HARBINGERSKYRISS,IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), false); + IsRunning = true; + } + } + + bool CanProgress() + { + if (pInstance) + { + if (Phase == 7 && pInstance->GetData(TYPE_WARDEN_4) == DONE) + return true; + if (Phase == 6 && pInstance->GetData(TYPE_WARDEN_3) == DONE) + return true; + if (Phase == 5 && pInstance->GetData(TYPE_WARDEN_2) == DONE) + return true; + if (Phase == 4) + return true; + if (Phase == 3 && pInstance->GetData(TYPE_WARDEN_1) == DONE) + return true; + if (Phase == 2 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS) + return true; + if (Phase == 1 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS) + return true; + return false; + } + return false; + } + + void DoPrepareForPhase() + { + if (pInstance) + { + me->InterruptNonMeleeSpells(true); + me->RemoveAurasByType(SPELL_AURA_DUMMY); + + switch(Phase) + { + case 2: + DoCast(me, SPELL_TARGET_ALPHA); + pInstance->SetData(TYPE_WARDEN_1,IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), false); + break; + case 3: + DoCast(me, SPELL_TARGET_BETA); + pInstance->SetData(TYPE_WARDEN_2,IN_PROGRESS); + break; + case 5: + DoCast(me, SPELL_TARGET_DELTA); + pInstance->SetData(TYPE_WARDEN_3,IN_PROGRESS); + break; + case 6: + DoCast(me, SPELL_TARGET_GAMMA); + pInstance->SetData(TYPE_WARDEN_4,IN_PROGRESS); + break; + case 7: + pInstance->SetData(TYPE_WARDEN_5,IN_PROGRESS); + break; + } + CanSpawn = true; + } + } + + void UpdateAI(const uint32 diff) + { + if (!IsRunning) + return; + + if (EventProgress_Timer <= diff) + { + if (pInstance) + { + if (pInstance->GetData(TYPE_HARBINGERSKYRISS) == FAIL) + { + Reset(); + return; + } + } + + if (CanSpawn) + { + //continue beam omega pod, unless we are about to summon skyriss + if (Phase != 7) + DoCast(me, SPELL_TARGET_OMEGA); + + switch(Phase) + { + case 2: + switch (urand(0,1)) + { + case 0: me->SummonCreature(ENTRY_TRICKSTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: me->SummonCreature(ENTRY_PH_HUNTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 3: + me->SummonCreature(ENTRY_MILLHOUSE,413.292,-148.378,42.56,6.27,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + break; + case 4: + DoScriptText(YELL_RELEASE2B, me); + break; + case 5: + switch (urand(0,1)) + { + case 0: me->SummonCreature(ENTRY_AKKIRIS,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: me->SummonCreature(ENTRY_SULFURON,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 6: + switch (urand(0,1)) + { + case 0: me->SummonCreature(ENTRY_TW_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + case 1: me->SummonCreature(ENTRY_BL_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; + } + break; + case 7: + me->SummonCreature(ENTRY_SKYRISS,445.763,-191.639,44.64,1.60,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); + DoScriptText(YELL_WELCOME, me); + break; + } + CanSpawn = false; + ++Phase; + } + if (CanProgress()) + { + switch(Phase) + { + case 1: + DoScriptText(YELL_INTRO2, me); + EventProgress_Timer = 10000; + ++Phase; + break; + case 2: + DoScriptText(YELL_RELEASE1, me); + DoPrepareForPhase(); + EventProgress_Timer = 7000; + break; + case 3: + DoScriptText(YELL_RELEASE2A, me); + DoPrepareForPhase(); + EventProgress_Timer = 10000; + break; + case 4: + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 5: + DoScriptText(YELL_RELEASE3, me); + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 6: + DoScriptText(YELL_RELEASE4, me); + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + case 7: + DoPrepareForPhase(); + EventProgress_Timer = 15000; + break; + } + } + } else EventProgress_Timer -= diff; + } +}; +CreatureAI* GetAI_npc_warden_mellichar(Creature* pCreature) +{ + return new npc_warden_mellicharAI (pCreature); +} + +/*##### +# mob_zerekethvoidzone (this script probably not needed in future -> `creature_template_addon`.`auras`='36120 0') +#####*/ + +#define SPELL_VOID_ZONE_DAMAGE 36120 + +struct mob_zerekethvoidzoneAI : public ScriptedAI +{ + mob_zerekethvoidzoneAI(Creature *c) : ScriptedAI(c) {} + + void Reset() + { + me->SetUInt32Value(UNIT_NPC_FLAGS,0); + me->setFaction(16); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + DoCast(me, SPELL_VOID_ZONE_DAMAGE); + } + + void EnterCombat(Unit* /*who*/) {} +}; +CreatureAI* GetAI_mob_zerekethvoidzoneAI(Creature* pCreature) +{ + return new mob_zerekethvoidzoneAI (pCreature); +} + +void AddSC_arcatraz() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_millhouse_manastorm"; + newscript->GetAI = &GetAI_npc_millhouse_manastorm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_warden_mellichar"; + newscript->GetAI = &GetAI_npc_warden_mellichar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_zerekethvoidzone"; + newscript->GetAI = &GetAI_mob_zerekethvoidzoneAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h new file mode 100644 index 00000000000..3f8dee8bbd0 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ARCATRAZ_H +#define DEF_ARCATRAZ_H + +#define TYPE_ZEREKETH 1 +#define TYPE_DALLIAH 2 +#define TYPE_SOCCOTHRATES 3 +#define TYPE_HARBINGERSKYRISS 4 +#define TYPE_WARDEN_1 5 +#define TYPE_WARDEN_2 6 +#define TYPE_WARDEN_3 7 +#define TYPE_WARDEN_4 8 +#define TYPE_WARDEN_5 9 +#define DATA_MELLICHAR 10 +#define TYPE_SHIELD_OPEN 11 +#define DATA_SPHERE_SHIELD 12 +#endif + diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp new file mode 100644 index 00000000000..6576974f3ff --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp @@ -0,0 +1,293 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Harbinger_Skyriss +SD%Complete: 45 +SDComment: CombatAI not fully implemented. Timers will need adjustments. Need more docs on how event fully work. Reset all event and force start over if fail at one point? +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +/* ContentData +boss_harbinger_skyriss +boss_harbinger_skyriss_illusion +EndContentData */ + +#include "ScriptedPch.h" +#include "arcatraz.h" + +#define SAY_INTRO -1552000 +#define SAY_AGGRO -1552001 +#define SAY_KILL_1 -1552002 +#define SAY_KILL_2 -1552003 +#define SAY_MIND_1 -1552004 +#define SAY_MIND_2 -1552005 +#define SAY_FEAR_1 -1552006 +#define SAY_FEAR_2 -1552007 +#define SAY_IMAGE -1552008 +#define SAY_DEATH -1552009 + +#define SPELL_FEAR 39415 + +#define SPELL_MIND_REND 36924 +#define H_SPELL_MIND_REND 39017 + +#define SPELL_DOMINATION 37162 +#define H_SPELL_DOMINATION 39019 + +#define H_SPELL_MANA_BURN 39020 + +#define SPELL_66_ILLUSION 36931 //entry 21466 +#define SPELL_33_ILLUSION 36932 //entry 21467 + +struct boss_harbinger_skyrissAI : public ScriptedAI +{ + boss_harbinger_skyrissAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = false; + } + + ScriptedInstance *pInstance; + + bool Intro; + bool IsImage33; + bool IsImage66; + + uint32 Intro_Phase; + uint32 Intro_Timer; + uint32 MindRend_Timer; + uint32 Fear_Timer; + uint32 Domination_Timer; + uint32 ManaBurn_Timer; + + void Reset() + { + if (!Intro) + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); + + IsImage33 = false; + IsImage66 = false; + + Intro_Phase = 1; + Intro_Timer = 5000; + MindRend_Timer = 3000; + Fear_Timer = 15000; + Domination_Timer = 30000; + ManaBurn_Timer = 25000; + } + + void MoveInLineOfSight(Unit *who) + { + if (!Intro) + { + return; + } + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) {} + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + pInstance->SetData(TYPE_HARBINGERSKYRISS,DONE); + } + + void JustSummoned(Creature *summon) + { + if (!summon) + return; + if (IsImage66) + summon->SetHealth((summon->GetMaxHealth()*33)/100); + else + summon->SetHealth((summon->GetMaxHealth()*66)/100); + if (me->getVictim()) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + summon->AI()->AttackStart(pTarget); + } + + void KilledUnit(Unit* victim) + { + //won't yell killing pet/other unit + if (victim->GetEntry() == 21436) + return; + + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void DoSplit(uint32 val) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoScriptText(SAY_IMAGE, me); + + if (val == 66) + DoCast(me, SPELL_66_ILLUSION); + else + DoCast(me, SPELL_33_ILLUSION); + } + + void UpdateAI(const uint32 diff) + { + if (!Intro) + { + if (!pInstance) + return; + + if (Intro_Timer <= diff) + { + switch(Intro_Phase) + { + case 1: + DoScriptText(SAY_INTRO, me); + pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), true); + ++Intro_Phase; + Intro_Timer = 25000; + break; + case 2: + DoScriptText(SAY_AGGRO, me); + if (Unit *mellic = Unit::GetUnit(*me,pInstance->GetData64(DATA_MELLICHAR))) + { + //should have a better way to do this. possibly spell exist. + mellic->setDeathState(JUST_DIED); + mellic->SetHealth(0); + pInstance->SetData(TYPE_SHIELD_OPEN,IN_PROGRESS); + } + ++Intro_Phase; + Intro_Timer = 3000; + break; + case 3: + me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); + Intro = true; + break; + } + } else Intro_Timer -=diff; + } + + if (!UpdateVictim()) + return; + + if (!IsImage66 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 66)) + { + DoSplit(66); + IsImage66 = true; + } + if (!IsImage33 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 33)) + { + DoSplit(33); + IsImage33 = true; + } + + if (MindRend_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_MIND_REND); + else + DoCast(me->getVictim(), SPELL_MIND_REND); + + MindRend_Timer = 8000; + } else MindRend_Timer -=diff; + + if (Fear_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoScriptText(RAND(SAY_FEAR_1,SAY_FEAR_2), me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_FEAR); + else + DoCast(me->getVictim(), SPELL_FEAR); + + Fear_Timer = 25000; + } else Fear_Timer -=diff; + + if (Domination_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoScriptText(RAND(SAY_MIND_1,SAY_MIND_2), me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_DOMINATION); + else + DoCast(me->getVictim(), SPELL_DOMINATION); + + Domination_Timer = 16000+rand()%16000; + } else Domination_Timer -=diff; + + if (IsHeroic()) + { + if (ManaBurn_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + return; + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, H_SPELL_MANA_BURN); + + ManaBurn_Timer = 16000+rand()%16000; + } else ManaBurn_Timer -=diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_harbinger_skyriss(Creature* pCreature) +{ + return new boss_harbinger_skyrissAI (pCreature); +} + +#define SPELL_MIND_REND_IMAGE 36929 +#define H_SPELL_MIND_REND_IMAGE 39021 + +struct boss_harbinger_skyriss_illusionAI : public ScriptedAI +{ + boss_harbinger_skyriss_illusionAI(Creature *c) : ScriptedAI(c) + { + } + + void Reset() { } + + void EnterCombat(Unit * /*who*/) { } +}; + +CreatureAI* GetAI_boss_harbinger_skyriss_illusion(Creature* pCreature) +{ + return new boss_harbinger_skyriss_illusionAI (pCreature); +} + +void AddSC_boss_harbinger_skyriss() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_harbinger_skyriss"; + newscript->GetAI = &GetAI_boss_harbinger_skyriss; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_harbinger_skyriss_illusion"; + newscript->GetAI = &GetAI_boss_harbinger_skyriss_illusion; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp new file mode 100644 index 00000000000..d16975e2af6 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp @@ -0,0 +1,240 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Arcatraz +SD%Complete: 80 +SDComment: Mainly Harbringer Skyriss event +SDCategory: Tempest Keep, The Arcatraz +EndScriptData */ + +#include "ScriptedPch.h" +#include "arcatraz.h" + +#define MAX_ENCOUNTER 9 + +#define CONTAINMENT_CORE_SECURITY_FIELD_ALPHA 184318 //door opened when Wrath-Scryer Soccothrates dies +#define CONTAINMENT_CORE_SECURITY_FIELD_BETA 184319 //door opened when Dalliah the Doomsayer dies +#define POD_ALPHA 183961 //pod first boss wave +#define POD_BETA 183963 //pod second boss wave +#define POD_DELTA 183964 //pod third boss wave +#define POD_GAMMA 183962 //pod fourth boss wave +#define POD_OMEGA 183965 //pod fifth boss wave +#define WARDENS_SHIELD 184802 // warden shield +#define SEAL_SPHERE 184802 //shield 'protecting' mellichar + +#define MELLICHAR 20904 //skyriss will kill this unit + +/* Arcatraz encounters: +1 - Zereketh the Unbound event +2 - Dalliah the Doomsayer event +3 - Wrath-Scryer Soccothrates event +4 - Harbinger Skyriss event, 5 sub-events +*/ + +struct instance_arcatraz : public ScriptedInstance +{ + instance_arcatraz(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 Containment_Core_Security_Field_AlphaGUID; + uint64 Containment_Core_Security_Field_BetaGUID; + uint64 Pod_AlphaGUID; + uint64 Pod_GammaGUID; + uint64 Pod_BetaGUID; + uint64 Pod_DeltaGUID; + uint64 Pod_OmegaGUID; + uint64 Wardens_ShieldGUID; + uint64 GoSphereGUID; + uint64 MellicharGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Containment_Core_Security_Field_AlphaGUID = 0; + Containment_Core_Security_Field_BetaGUID = 0; + Pod_AlphaGUID = 0; + Pod_GammaGUID = 0; + Pod_BetaGUID = 0; + Pod_DeltaGUID = 0; + Pod_OmegaGUID = 0; + Wardens_ShieldGUID = 0; + GoSphereGUID = 0; + MellicharGUID = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case CONTAINMENT_CORE_SECURITY_FIELD_ALPHA: Containment_Core_Security_Field_AlphaGUID = pGo->GetGUID(); break; + case CONTAINMENT_CORE_SECURITY_FIELD_BETA: Containment_Core_Security_Field_BetaGUID = pGo->GetGUID(); break; + case POD_ALPHA: Pod_AlphaGUID = pGo->GetGUID(); break; + case POD_GAMMA: Pod_GammaGUID = pGo->GetGUID(); break; + case POD_BETA: Pod_BetaGUID = pGo->GetGUID(); break; + case POD_DELTA: Pod_DeltaGUID = pGo->GetGUID(); break; + case POD_OMEGA: Pod_OmegaGUID = pGo->GetGUID(); break; + case SEAL_SPHERE: GoSphereGUID = pGo->GetGUID(); break; + //case WARDENS_SHIELD: Wardens_ShieldGUID = pGo->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == MELLICHAR) + MellicharGUID = pCreature->GetGUID(); + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_ZEREKETH: + m_auiEncounter[0] = data; + break; + + case TYPE_DALLIAH: + if (data == DONE) + { + if (GameObject *pGo = instance->GetGameObject(Containment_Core_Security_Field_BetaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[1] = data; + break; + + case TYPE_SOCCOTHRATES: + if (data == DONE) + { + if (GameObject *pGo = instance->GetGameObject(Containment_Core_Security_Field_AlphaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[2] = data; + break; + + case TYPE_HARBINGERSKYRISS: + if (data == NOT_STARTED || data == FAIL) + { + m_auiEncounter[4] = NOT_STARTED; + m_auiEncounter[5] = NOT_STARTED; + m_auiEncounter[6] = NOT_STARTED; + m_auiEncounter[7] = NOT_STARTED; + m_auiEncounter[8] = NOT_STARTED; + } + m_auiEncounter[3] = data; + break; + + case TYPE_WARDEN_1: + if (data == IN_PROGRESS) + if (GameObject *pGo = instance->GetGameObject(Pod_AlphaGUID)) + pGo->UseDoorOrButton(); + m_auiEncounter[4] = data; + break; + + case TYPE_WARDEN_2: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Pod_BetaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[5] = data; + break; + + case TYPE_WARDEN_3: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Pod_DeltaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[6] = data; + break; + + case TYPE_WARDEN_4: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Pod_GammaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[7] = data; + break; + + case TYPE_WARDEN_5: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Pod_OmegaGUID)) + pGo->UseDoorOrButton(); + } + m_auiEncounter[8] = data; + break; + + case TYPE_SHIELD_OPEN: + if (data == IN_PROGRESS) + { + if (GameObject *pGo = instance->GetGameObject(Wardens_ShieldGUID)) + pGo->UseDoorOrButton(); + } + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HARBINGERSKYRISS: return m_auiEncounter[3]; + case TYPE_WARDEN_1: return m_auiEncounter[4]; + case TYPE_WARDEN_2: return m_auiEncounter[5]; + case TYPE_WARDEN_3: return m_auiEncounter[6]; + case TYPE_WARDEN_4: return m_auiEncounter[7]; + case TYPE_WARDEN_5: return m_auiEncounter[8]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_MELLICHAR: return MellicharGUID; + case DATA_SPHERE_SHIELD: return GoSphereGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_arcatraz(Map* pMap) +{ + return new instance_arcatraz(pMap); +} + +void AddSC_instance_arcatraz() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_arcatraz"; + newscript->GetInstanceData = &GetInstanceData_instance_arcatraz; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp new file mode 100644 index 00000000000..1a077036298 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp @@ -0,0 +1,191 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_High_Botanist_Freywinn +SD%Complete: 90 +SDComment: some strange visual related to tree form(if aura lost before normal duration end). possible make summon&transform -process smoother(transform after delay) +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1553000 +#define SAY_KILL_1 -1553001 +#define SAY_KILL_2 -1553002 +#define SAY_TREE_1 -1553003 +#define SAY_TREE_2 -1553004 +#define SAY_DEATH -1553005 + +#define SPELL_TRANQUILITY 34550 +#define SPELL_TREE_FORM 34551 + +#define SPELL_SUMMON_FRAYER 34557 +#define ENTRY_FRAYER 19953 + +#define SPELL_PLANT_WHITE 34759 +#define SPELL_PLANT_GREEN 34761 +#define SPELL_PLANT_BLUE 34762 +#define SPELL_PLANT_RED 34763 + +struct boss_high_botanist_freywinnAI : public ScriptedAI +{ + boss_high_botanist_freywinnAI(Creature *c) : ScriptedAI(c) {} + + std::list Adds_List; + + uint32 SummonSeedling_Timer; + uint32 TreeForm_Timer; + uint32 MoveCheck_Timer; + uint32 DeadAddsCount; + bool MoveFree; + + void Reset() + { + Adds_List.clear(); + + SummonSeedling_Timer = 6000; + TreeForm_Timer = 30000; + MoveCheck_Timer = 1000; + DeadAddsCount = 0; + MoveFree = true; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == ENTRY_FRAYER) + Adds_List.push_back(summoned->GetGUID()); + } + + void DoSummonSeedling() + { + switch(rand()%4) + { + case 0: DoCast(me, SPELL_PLANT_WHITE); break; + case 1: DoCast(me, SPELL_PLANT_GREEN); break; + case 2: DoCast(me, SPELL_PLANT_BLUE); break; + case 3: DoCast(me, SPELL_PLANT_RED); break; + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (TreeForm_Timer <= diff) + { + DoScriptText(RAND(SAY_TREE_1,SAY_TREE_2), me); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + me->RemoveAllAuras(); + + DoCast(me, SPELL_SUMMON_FRAYER, true); + DoCast(me, SPELL_TRANQUILITY, true); + DoCast(me, SPELL_TREE_FORM, true); + + me->GetMotionMaster()->MoveIdle(); + MoveFree = false; + + TreeForm_Timer = 75000; + } else TreeForm_Timer -= diff; + + if (!MoveFree) + { + if (MoveCheck_Timer <= diff) + { + if (!Adds_List.empty()) + { + for (std::list::iterator itr = Adds_List.begin(); itr != Adds_List.end(); ++itr) + { + if (Unit *temp = Unit::GetUnit(*me,*itr)) + { + if (!temp->isAlive()) + { + Adds_List.erase(itr); + ++DeadAddsCount; + break; + } + } + } + } + + if (DeadAddsCount < 3 && TreeForm_Timer-30000 <= diff) + DeadAddsCount = 3; + + if (DeadAddsCount >= 3) + { + Adds_List.clear(); + DeadAddsCount = 0; + + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + MoveFree = true; + } + MoveCheck_Timer = 500; + } + else MoveCheck_Timer -= diff; + + return; + } + + /*if (me->HasAura(SPELL_TREE_FORM,0) || me->HasAura(SPELL_TRANQUILITY,0)) + return;*/ + + //one random seedling every 5 secs, but not in tree form + if (SummonSeedling_Timer <= diff) + { + DoSummonSeedling(); + SummonSeedling_Timer = 6000; + } else SummonSeedling_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_high_botanist_freywinn(Creature* pCreature) +{ + return new boss_high_botanist_freywinnAI (pCreature); +} + +void AddSC_boss_high_botanist_freywinn() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_high_botanist_freywinn"; + newscript->GetAI = &GetAI_boss_high_botanist_freywinn; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp new file mode 100644 index 00000000000..cbf21c2f992 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Laj +SD%Complete: 90 +SDComment: Immunities are wrong, must be adjusted to use resistance from creature_templates. Most spells require database support. +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "ScriptedPch.h" + +#define EMOTE_SUMMON -1553006 + +#define SPELL_ALLERGIC_REACTION 34697 +#define SPELL_TELEPORT_SELF 34673 + +#define SPELL_SUMMON_LASHER_1 34681 +#define SPELL_SUMMON_FLAYER_1 34682 +#define SPELL_SUMMON_LASHER_2 34684 +#define SPELL_SUMMON_FLAYER_2 34685 +#define SPELL_SUMMON_LASHER_3 34686 +#define SPELL_SUMMON_FLAYER_4 34687 +#define SPELL_SUMMON_LASHER_4 34688 +#define SPELL_SUMMON_FLAYER_3 34690 + +#define MODEL_DEFAULT 13109 +#define MODEL_ARCANE 14213 +#define MODEL_FIRE 13110 +#define MODEL_FROST 14112 +#define MODEL_NATURE 14214 + +struct boss_lajAI : public ScriptedAI +{ + boss_lajAI(Creature *c) : ScriptedAI(c) {} + + bool CanSummon; + uint32 Teleport_Timer; + uint32 Summon_Timer; + uint32 Transform_Timer; + uint32 Allergic_Timer; + + void Reset() + { + me->SetDisplayId(MODEL_DEFAULT); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + + CanSummon = false; + Teleport_Timer = 20000; + Summon_Timer = 2500; + Transform_Timer = 30000; + Allergic_Timer = 5000; + } + + void DoTransform() + { + switch(rand()%5) + { + case 0: + me->SetDisplayId(MODEL_DEFAULT); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 1: + me->SetDisplayId(MODEL_ARCANE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 2: + me->SetDisplayId(MODEL_FIRE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 3: + me->SetDisplayId(MODEL_FROST); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + break; + case 4: + me->SetDisplayId(MODEL_NATURE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + break; + } + } + + void DoSummons() + { + switch(rand()%4) + { + case 0: + DoCast(me, SPELL_SUMMON_LASHER_1, true); + DoCast(me, SPELL_SUMMON_FLAYER_1, true); + break; + case 1: + DoCast(me, SPELL_SUMMON_LASHER_2, true); + DoCast(me, SPELL_SUMMON_FLAYER_2, true); + break; + case 2: + DoCast(me, SPELL_SUMMON_LASHER_3, true); + DoCast(me, SPELL_SUMMON_FLAYER_3, true); + break; + case 3: + DoCast(me, SPELL_SUMMON_LASHER_4, true); + DoCast(me, SPELL_SUMMON_FLAYER_4, true); + break; + } + CanSummon = false; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void JustSummoned(Creature *summon) + { + if (summon && me->getVictim()) + summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (CanSummon) + { + if (Summon_Timer <= diff) + { + DoScriptText(EMOTE_SUMMON, me); + DoSummons(); + Summon_Timer = 2500; + } else Summon_Timer -= diff; + } + + if (Allergic_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ALLERGIC_REACTION); + Allergic_Timer = 25000+rand()%15000; + } else Allergic_Timer -= diff; + + if (Teleport_Timer <= diff) + { + DoCast(me, SPELL_TELEPORT_SELF); + Teleport_Timer = 30000+rand()%10000; + CanSummon = true; + } else Teleport_Timer -= diff; + + if (Transform_Timer <= diff) + { + DoTransform(); + Transform_Timer = 25000+rand()%15000; + } else Transform_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_laj(Creature* pCreature) +{ + return new boss_lajAI (pCreature); +} + +void AddSC_boss_laj() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_laj"; + newscript->GetAI = &GetAI_boss_laj; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp new file mode 100644 index 00000000000..48eb03c16d3 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp @@ -0,0 +1,216 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Warp_Splinter +SD%Complete: 80 +SDComment: Includes Sapling (need some better control with these). +SDCategory: Tempest Keep, The Botanica +EndScriptData */ + +#include "ScriptedPch.h" + +/*##### +# mob_treant (Sapling) +#####*/ + +#define SPELL_HEAL_FATHER 6262 + +struct mob_treantAI : public ScriptedAI +{ + mob_treantAI (Creature *c) : ScriptedAI(c) + { + WarpGuid = 0; + } + + uint64 WarpGuid; + uint32 check_Timer; + + void Reset() + { + check_Timer = 0; + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (WarpGuid && check_Timer <= diff) + { + if (Unit *Warp = Unit::GetUnit(*me, WarpGuid)) + { + if (me->IsWithinMeleeRange(Warp,2.5f)) + { + int32 CurrentHP_Treant = (int32)me->GetHealth(); + Warp->CastCustomSpell(Warp,SPELL_HEAL_FATHER,&CurrentHP_Treant, 0, 0, true,0 ,0, me->GetGUID()); + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + me->GetMotionMaster()->MoveFollow(Warp,0,0); + } + check_Timer = 1000; + } else check_Timer -= diff; + return; + } + + if (me->getVictim()->GetGUID() != WarpGuid) + DoMeleeAttackIfReady(); + } +}; + +/*##### +# boss_warp_splinter +#####*/ + +#define SAY_AGGRO -1553007 +#define SAY_SLAY_1 -1553008 +#define SAY_SLAY_2 -1553009 +#define SAY_SUMMON_1 -1553010 +#define SAY_SUMMON_2 -1553011 +#define SAY_DEATH -1553012 + +#define WAR_STOMP 34716 +#define SUMMON_TREANTS 34727 // DBC: 34727, 34731, 34733, 34734, 34736, 34739, 34741 (with Ancestral Life spell 34742) // won't work (guardian summon) +#define ARCANE_VOLLEY DUNGEON_MODE(36705, 39133) + +#define CREATURE_TREANT 19949 + +#define TREANT_SPAWN_DIST 50 //50 yards from Warp Splinter's spawn point + +float treant_pos[6][3] = +{ + {24.301233, 427.221100, -27.060635}, + {16.795492, 359.678802, -27.355425}, + {53.493484, 345.381470, -26.196192}, + {61.867096, 439.362732, -25.921030}, + {109.861877, 423.201630, -27.356019}, + {106.780159, 355.582581, -27.593357} +}; + +struct boss_warp_splinterAI : public ScriptedAI +{ + boss_warp_splinterAI(Creature *c) : ScriptedAI(c) + { + Treant_Spawn_Pos_X = c->GetPositionX(); + Treant_Spawn_Pos_Y = c->GetPositionY(); + } + + uint32 War_Stomp_Timer; + uint32 Summon_Treants_Timer; + uint32 Arcane_Volley_Timer; + + float Treant_Spawn_Pos_X; + float Treant_Spawn_Pos_Y; + + void Reset() + { + War_Stomp_Timer = 25000 + rand()%15000; + Summon_Treants_Timer = 45000; + Arcane_Volley_Timer = 8000 + rand()%12000; + + me->SetSpeed(MOVE_RUN, 0.7f, true); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void SummonTreants() + { + for (uint8 i = 0; i < 6; ++i) + { + float angle = (M_PI / 3) * i; + + float X = Treant_Spawn_Pos_X + TREANT_SPAWN_DIST * cos(angle); + float Y = Treant_Spawn_Pos_Y + TREANT_SPAWN_DIST * sin(angle); + float O = - me->GetAngle(X,Y); + + if (Creature *pTreant = me->SummonCreature(CREATURE_TREANT,treant_pos[i][0],treant_pos[i][1],treant_pos[i][2],O,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,25000)) + CAST_AI(mob_treantAI, pTreant->AI())->WarpGuid = me->GetGUID(); + } + DoScriptText(RAND(SAY_SUMMON_1,SAY_SUMMON_2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Check for War Stomp + if (War_Stomp_Timer <= diff) + { + DoCast(me->getVictim(), WAR_STOMP); + War_Stomp_Timer = 25000 + rand()%15000; + } else War_Stomp_Timer -= diff; + + //Check for Arcane Volley + if (Arcane_Volley_Timer <= diff) + { + DoCast(me->getVictim(), ARCANE_VOLLEY); + Arcane_Volley_Timer = 20000 + rand()%15000; + } else Arcane_Volley_Timer -= diff; + + //Check for Summon Treants + if (Summon_Treants_Timer <= diff) + { + SummonTreants(); + Summon_Treants_Timer = 45000; + } else Summon_Treants_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_warp_splinter(Creature* pCreature) +{ + return new boss_warp_splinterAI (pCreature); +} + +CreatureAI* GetAI_mob_treant(Creature* pCreature) +{ + return new mob_treantAI (pCreature); +} + +void AddSC_boss_warp_splinter() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_warp_splinter"; + newscript->GetAI = &GetAI_boss_warp_splinter; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_warp_splinter_treant"; + newscript->GetAI = &GetAI_mob_treant; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp new file mode 100644 index 00000000000..af5f1bd95c1 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp @@ -0,0 +1,523 @@ +/* Copyright(C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +*(at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_alar +SD%Complete: 95 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define SPELL_FLAME_BUFFET 34121 // Flame Buffet - every 1,5 secs in phase 1 if there is no victim in melee range and after Dive Bomb in phase 2 with same conditions +#define SPELL_FLAME_QUILLS 34229 // Randomly after changing position in phase after watching tonns of movies, set probability 20% +#define SPELL_REBIRTH 34342 // Rebirth - beginning of second phase(after loose all health in phase 1) +#define SPELL_REBIRTH_2 35369 // Rebirth(another, without healing to full HP) - after Dive Bomb in phase 2 +#define SPELL_MELT_ARMOR 35410 // Melt Armor - every 60 sec in phase 2 +#define SPELL_CHARGE 35412 // Charge - 30 sec cooldown +#define SPELL_DIVE_BOMB_VISUAL 35367 // Bosskillers says 30 sec cooldown, wowwiki says 30 sec colldown, DBM and BigWigs addons says ~47 sec +#define SPELL_DIVE_BOMB 35181 // after watching tonns of movies, set cooldown to 40+rand()%5. +#define SPELL_BERSERK 45078 // 10 minutes after phase 2 starts(id is wrong, but proper id is unknown) + +#define CREATURE_EMBER_OF_ALAR 19551 // Al'ar summons one Ember of Al'ar every position change in phase 1 and two after Dive Bomb. Also in phase 2 when Ember of Al'ar dies, boss loose 3% health. +#define SPELL_EMBER_BLAST 34133 // When Ember of Al'ar dies, it casts Ember Blast + +#define CREATURE_FLAME_PATCH_ALAR 20602 // Flame Patch - every 30 sec in phase 2 +#define SPELL_FLAME_PATCH 35380 // + +static float waypoint[6][3] = +{ + {340.15, 58.65, 17.71}, + {388.09, 31.54, 20.18}, + {388.18, -32.85, 20.18}, + {340.29, -60.19, 17.72}, + {332, 0.01, 39}, // better not use the same xy coord + {331, 0.01, -2.39} +}; + +enum WaitEventType +{ + WE_NONE = 0, + WE_DUMMY = 1, + WE_PLATFORM = 2, + WE_QUILL = 3, + WE_DIE = 4, + WE_REVIVE = 5, + WE_CHARGE = 6, + WE_METEOR = 7, + WE_DIVE = 8, + WE_LAND = 9, + WE_SUMMON = 10 +}; + +struct boss_alarAI : public ScriptedAI +{ + boss_alarAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + DefaultMoveSpeedRate = c->GetSpeedRate(MOVE_RUN); + } + + ScriptedInstance *pInstance; + + WaitEventType WaitEvent; + uint32 WaitTimer; + + bool AfterMoving; + + uint32 Platforms_Move_Timer; + uint32 DiveBomb_Timer; + uint32 MeltArmor_Timer; + uint32 Charge_Timer; + uint32 FlamePatch_Timer; + uint32 Berserk_Timer; + + float DefaultMoveSpeedRate; + + bool Phase1; + bool ForceMove; + uint32 ForceTimer; + + int8 cur_wp; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, NOT_STARTED); + + Berserk_Timer = 1200000; + Platforms_Move_Timer = 0; + + Phase1 = true; + WaitEvent = WE_NONE; + WaitTimer = 0; + AfterMoving = false; + ForceMove = false; + ForceTimer = 5000; + + cur_wp = 4; + + me->SetDisplayId(me->GetNativeDisplayId()); + me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + //me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + //me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->setActive(false); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, IN_PROGRESS); + + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); // after enterevademode will be set walk movement + DoZoneInCombat(); + me->setActive(true); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, DONE); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + summon->AI()->AttackStart(pTarget); + } + + void MoveInLineOfSight(Unit * /*who*/) {} + + void AttackStart(Unit* who) + { + if (Phase1) + AttackStartNoMove(who); + else + ScriptedAI::AttackStart(who); + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth() && Phase1) + { + damage = 0; + if (!WaitEvent) + { + WaitEvent = WE_DIE; + WaitTimer = 0; + me->SetHealth(0); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->AttackStop(); + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + me->SetSpeed(MOVE_RUN, 5.0f); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]); + } + } + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (spell->Id == SPELL_DIVE_BOMB_VISUAL) + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + me->SetDisplayId(11686); + //me->SendUpdateObjectToAllExcept(NULL); + } + } + + void MovementInform(uint32 type, uint32 /*id*/) + { + if (type == POINT_MOTION_TYPE) + { + WaitTimer = 1; + AfterMoving = true; + ForceMove = false; + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) // sometimes isincombat but !incombat, faction bug? + return; + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + if (ForceMove) + { + if (ForceTimer <= diff) + { + me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); + ForceTimer = 5000; + } else ForceTimer -= diff; + + } + if (WaitEvent) + { + if (WaitTimer) + { + if (WaitTimer <= diff) + { + if (AfterMoving) + { + me->GetMotionMaster()->MoveIdle(); + AfterMoving = false; + } + + switch(WaitEvent) + { + case WE_PLATFORM: + Platforms_Move_Timer = 30000+rand()%5000; + break; + case WE_QUILL: + DoCast(me, SPELL_FLAME_QUILLS, true); + Platforms_Move_Timer = 1; + WaitTimer = 10000; + WaitEvent = WE_DUMMY; + return; + case WE_DIE: + ForceMove = false; + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + WaitTimer = 5000; + WaitEvent = WE_REVIVE; + return; + case WE_REVIVE: + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); + me->SetHealth(me->GetMaxHealth()); + me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoZoneInCombat(); + DoCast(me, SPELL_REBIRTH, true); + MeltArmor_Timer = 60000; + Charge_Timer = 7000; + DiveBomb_Timer = 40000+rand()%5000; + FlamePatch_Timer = 30000; + Phase1 = false; + break; + case WE_METEOR: + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + DoCast(me, SPELL_DIVE_BOMB_VISUAL, false); + WaitEvent = WE_DIVE; + WaitTimer = 4000; + return; + case WE_DIVE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL); + DoCast(pTarget, SPELL_DIVE_BOMB, true); + float dist = 3.0f; + if (me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f)) + dist = 5.0f; + WaitTimer = 1000 + floor(dist / 80 * 1000.0f); + me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f); + me->StopMoving(); + WaitEvent = WE_LAND; + } + else + { + EnterEvadeMode(); + return; + } + case WE_LAND: + WaitEvent = WE_SUMMON; + WaitTimer = 2000; + return; + case WE_SUMMON: + for (uint8 i = 0; i < 2; ++i) + DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(me->GetNativeDisplayId()); + DoCast(me, SPELL_REBIRTH_2, true); + break; + case WE_DUMMY: + default: + break; + } + + WaitEvent = WE_NONE; + WaitTimer = 0; + } else WaitTimer -= diff; + } + return; + } + + if (Phase1) + { + if (me->getThreatManager().getThreatList().empty()) + { + EnterEvadeMode(); + return; + } + + if (Platforms_Move_Timer <= diff) + { + if (cur_wp == 4) + { + cur_wp = 0; + WaitEvent = WE_PLATFORM; + } + else + { + if (urand(0,4)) // next platform + { + DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (cur_wp == 3) + cur_wp = 0; + else + ++cur_wp; + WaitEvent = WE_PLATFORM; + } + else // flame quill + { + cur_wp = 4; + WaitEvent = WE_QUILL; + } + } + ForceMove = true; + ForceTimer = 5000; + me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); + WaitTimer = 0; + return; + } else Platforms_Move_Timer -= diff; + } + else + { + if (Charge_Timer <= diff) + { + Unit *pTarget= SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + if (pTarget) + DoCast(pTarget, SPELL_CHARGE); + Charge_Timer = 30000; + } else Charge_Timer -= diff; + + if (MeltArmor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MELT_ARMOR); + MeltArmor_Timer = 60000; + } else MeltArmor_Timer -= diff; + + if (DiveBomb_Timer <= diff) + { + me->AttackStop(); + me->GetMotionMaster()->MovePoint(6, waypoint[4][0], waypoint[4][1], waypoint[4][2]); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 50); + WaitEvent = WE_METEOR; + WaitTimer = 0; + DiveBomb_Timer = 40000+rand()%5000; + return; + } else DiveBomb_Timer -= diff; + + if (FlamePatch_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + Creature* Summoned = me->SummonCreature(CREATURE_FLAME_PATCH_ALAR, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000); + if (Summoned) + { + Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Summoned->SetFloatValue(OBJECT_FIELD_SCALE_X, Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); + Summoned->SetDisplayId(11686); + Summoned->setFaction(me->getFaction()); + Summoned->SetLevel(me->getLevel()); + Summoned->CastSpell(Summoned, SPELL_FLAME_PATCH, false); + } + } + FlamePatch_Timer = 30000; + } else FlamePatch_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void DoMeleeAttackIfReady() + { + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + else + { + Unit *pTarget = NULL; + pTarget = me->SelectNearestTargetInAttackDistance(5); + if (pTarget) + me->AI()->AttackStart(pTarget); + else + { + DoCast(me, SPELL_FLAME_BUFFET, true); + me->setAttackTimer(BASE_ATTACK, 1500); + } + } + } + } +}; + +CreatureAI* GetAI_boss_alar(Creature* pCreature) +{ + return new boss_alarAI(pCreature); +} + +struct mob_ember_of_alarAI : public ScriptedAI +{ + mob_ember_of_alarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + c->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + c->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + } + + ScriptedInstance *pInstance; + bool toDie; + + void Reset() {toDie = false;} + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + void EnterEvadeMode() {me->setDeathState(JUST_DIED);} + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage >= me->GetHealth() && pKiller != me && !toDie) + { + damage = 0; + DoCast(me, SPELL_EMBER_BLAST, true); + me->SetDisplayId(11686); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (pInstance && pInstance->GetData(DATA_ALAREVENT) == 2) + { + if (Unit* Alar = Unit::GetUnit((*me), pInstance->GetData64(DATA_ALAR))) + { + int AlarHealth = Alar->GetHealth() - Alar->GetMaxHealth()*0.03; + if (AlarHealth > 0) + Alar->SetHealth(AlarHealth); + else + Alar->SetHealth(1); + } + } + toDie = true; + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + if (toDie) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + //me->SetVisibility(VISIBILITY_OFF); + } + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_mob_ember_of_alar(Creature* pCreature) +{ + return new mob_ember_of_alarAI(pCreature); +} + +struct mob_flame_patch_alarAI : public ScriptedAI +{ + mob_flame_patch_alarAI(Creature *c) : ScriptedAI(c) {} + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_mob_flame_patch_alar(Creature* pCreature) +{ + return new mob_flame_patch_alarAI(pCreature); +} + +void AddSC_boss_alar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_alar"; + newscript->GetAI = &GetAI_boss_alar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ember_of_alar"; + newscript->GetAI = &GetAI_mob_ember_of_alar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flame_patch_alar"; + newscript->GetAI = &GetAI_mob_flame_patch_alar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp new file mode 100644 index 00000000000..e9e217a5c62 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp @@ -0,0 +1,466 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Astromancer +SD%Complete: 80 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +enum eEnums +{ + SAY_AGGRO = -1550007, + SAY_SUMMON1 = -1550008, + SAY_SUMMON2 = -1550009, + SAY_KILL1 = -1550010, + SAY_KILL2 = -1550011, + SAY_KILL3 = -1550012, + SAY_DEATH = -1550013, + SAY_VOIDA = -1550014, + SAY_VOIDB = -1550015, + + SPELL_ARCANE_MISSILES = 33031, + SPELL_WRATH_OF_THE_ASTROMANCER = 42783, + SPELL_BLINDING_LIGHT = 33009, + SPELL_FEAR = 34322, + SPELL_VOID_BOLT = 39329, + + SPELL_SPOTLIGHT = 25824, + NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT = 18928, + + NPC_SOLARIUM_AGENT = 18925, + NPC_SOLARIUM_PRIEST = 18806, + + MODEL_HUMAN = 18239, + MODEL_VOIDWALKER = 18988, + + SPELL_SOLARIUM_GREAT_HEAL = 33387, + SPELL_SOLARIUM_HOLY_SMITE = 25054, + SPELL_SOLARIUM_ARCANE_TORRENT = 33390, + + WV_ARMOR = 31000 +}; + +const float CENTER_X = 432.909f; +const float CENTER_Y = -373.424f; +const float CENTER_Z = 17.9608f; +const float CENTER_O = 1.06421f; +const float SMALL_PORTAL_RADIUS = 12.6f; +const float LARGE_PORTAL_RADIUS = 26.0f; +const float PORTAL_Z = 17.005f; + + // x, y, z, o +static float SolarianPos[4] = {432.909, -373.424, 17.9608, 1.06421}; + +struct boss_high_astromancer_solarianAI : public ScriptedAI +{ + boss_high_astromancer_solarianAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + + defaultarmor = c->GetArmor(); + defaultsize = c->GetFloatValue(OBJECT_FIELD_SCALE_X); + } + + ScriptedInstance *pInstance; + SummonList Summons; + + uint8 Phase; + + uint32 ArcaneMissiles_Timer; + uint32 m_uiWrathOfTheAstromancer_Timer; + uint32 BlindingLight_Timer; + uint32 Fear_Timer; + uint32 VoidBolt_Timer; + uint32 Phase1_Timer; + uint32 Phase2_Timer; + uint32 Phase3_Timer; + uint32 AppearDelay_Timer; + uint32 defaultarmor; + uint32 Wrath_Timer; + + float defaultsize; + float Portals[3][3]; + + bool AppearDelay; + bool BlindingLight; + + void Reset() + { + ArcaneMissiles_Timer = 2000; + m_uiWrathOfTheAstromancer_Timer = 15000; + BlindingLight_Timer = 41000; + Fear_Timer = 20000; + VoidBolt_Timer = 10000; + Phase1_Timer = 50000; + Phase2_Timer = 10000; + Phase3_Timer = 15000; + AppearDelay_Timer = 2000; + BlindingLight = false; + AppearDelay = false; + Wrath_Timer = 20000+rand()%5000;//twice in phase one + Phase = 1; + Wrath_Timer = 20000+rand()%5000;//twice in phase one + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); + + me->SetArmor(defaultarmor); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + me->SetDisplayId(MODEL_HUMAN); + + Summons.DespawnAll(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2,SAY_KILL3), me); + } + + void JustDied(Unit * /*victim*/) + { + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + me->SetDisplayId(MODEL_HUMAN); + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); + } + + void SummonMinion(uint32 entry, float x, float y, float z) + { + Creature* Summoned = me->SummonCreature(entry, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (Summoned) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Summoned->AI()->AttackStart(pTarget); + + Summons.Summon(Summoned); + } + } + + float Portal_X(float radius) + { + if (urand(0,1)) + radius = -radius; + + return radius * (float)(rand()%100)/100.0f + CENTER_X; + } + + float Portal_Y(float x, float radius) + { + float z = RAND(1, -1); + + return (z*sqrt(radius*radius - (x - CENTER_X)*(x - CENTER_X)) + CENTER_Y); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AppearDelay) + { + me->StopMoving(); + me->AttackStop(); + if (AppearDelay_Timer <= diff) + { + AppearDelay = false; + if (Phase == 2) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_OFF); + } + AppearDelay_Timer = 2000; + } else AppearDelay_Timer -= diff; + } + + if (Phase == 1) + { + if (BlindingLight_Timer <= diff) + { + BlindingLight = true; + BlindingLight_Timer = 45000; + } else BlindingLight_Timer -= diff; + + if (Wrath_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER, true); + Wrath_Timer = 20000+rand()%5000; + } else Wrath_Timer -= diff; + + if (ArcaneMissiles_Timer <= diff) + { + if (BlindingLight) + { + DoCast(me->getVictim(), SPELL_BLINDING_LIGHT); + BlindingLight = false; + }else{ + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (!me->HasInArc(2.5f, pTarget)) + pTarget = me->getVictim(); + + if (pTarget) + DoCast(pTarget, SPELL_ARCANE_MISSILES); + } + ArcaneMissiles_Timer = 3000; + } else ArcaneMissiles_Timer -= diff; + + if (m_uiWrathOfTheAstromancer_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + + //Target the tank ? + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER); + m_uiWrathOfTheAstromancer_Timer = 25000; + } + else + m_uiWrathOfTheAstromancer_Timer = 1000; + } else m_uiWrathOfTheAstromancer_Timer -= diff; + + //Phase1_Timer + if (Phase1_Timer <= diff) + { + Phase = 2; + Phase1_Timer = 50000; + //After these 50 seconds she portals to the middle of the room and disappears, leaving 3 light portals behind. + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, CENTER_X, CENTER_Y, CENTER_Z, CENTER_O); + for (uint8 i=0; i <= 2; ++i) + { + if (!i) + { + Portals[i][0] = Portal_X(SMALL_PORTAL_RADIUS); + Portals[i][1] = Portal_Y(Portals[i][0], SMALL_PORTAL_RADIUS); + Portals[i][2] = CENTER_Z; + } + else + { + Portals[i][0] = Portal_X(LARGE_PORTAL_RADIUS); + Portals[i][1] = Portal_Y(Portals[i][0], LARGE_PORTAL_RADIUS); + Portals[i][2] = PORTAL_Z; + } + } + if ((abs(Portals[2][0] - Portals[1][0]) < 7) && (abs(Portals[2][1] - Portals[1][1]) < 7)) + { + int i=1; + if (abs(CENTER_X + 26.0f - Portals[2][0]) < 7) + i = -1; + Portals[2][0] = Portals[2][0]+7*i; + Portals[2][1] = Portal_Y(Portals[2][0], LARGE_PORTAL_RADIUS); + } + for (int i=0; i <= 2; ++i) + { + if (Creature* Summoned = me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O, TEMPSUMMON_TIMED_DESPAWN, Phase2_Timer+Phase3_Timer+AppearDelay_Timer+1700)) + { + Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Summoned->CastSpell(Summoned, SPELL_SPOTLIGHT, false); + } + } + AppearDelay = true; + } else Phase1_Timer-=diff; + } + else if (Phase == 2) + { + //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. + me->AttackStop(); + me->StopMoving(); + if (Phase2_Timer <= diff) + { + Phase = 3; + for (int i=0; i <= 2; ++i) + for (int j=1; j <= 4; j++) + SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); + + DoScriptText(SAY_SUMMON1, me); + Phase2_Timer = 10000; + } else Phase2_Timer -= diff; + } + else if (Phase == 3) + { + me->AttackStop(); + me->StopMoving(); + + //Check Phase3_Timer + if (Phase3_Timer <= diff) + { + Phase = 1; + + //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. + int i = rand()%3; + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); + + for (int j=0; j <= 2; j++) + if (j != i) + SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + DoScriptText(SAY_SUMMON2, me); + AppearDelay = true; + Phase3_Timer = 15000; + } else Phase3_Timer -= diff; + } + else if (Phase == 4) + { + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 20000; + } else Fear_Timer -= diff; + + //VoidBolt_Timer + if (VoidBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VOID_BOLT); + VoidBolt_Timer = 10000; + } else VoidBolt_Timer -= diff; + } + + //When Solarian reaches 20% she will transform into a huge void walker. + if (Phase != 4 && ((me->GetHealth()*100 / me->GetMaxHealth())<20)) + { + Phase = 4; + + //To make sure she wont be invisible or not selecatble + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + DoScriptText(SAY_VOIDA, me); + DoScriptText(SAY_VOIDB, me); + me->SetArmor(WV_ARMOR); + me->SetDisplayId(MODEL_VOIDWALKER); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize*2.5f); + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_solarium_priestAI : public ScriptedAI +{ + mob_solarium_priestAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 healTimer; + uint32 holysmiteTimer; + uint32 aoesilenceTimer; + + void Reset() + { + healTimer = 9000; + holysmiteTimer = 1; + aoesilenceTimer = 15000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (healTimer <= diff) + { + Unit *pTarget = NULL; + + switch (urand(0,1)) + { + case 0: + if (pInstance) + pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_ASTROMANCER)); + break; + case 1: + pTarget = me; + break; + } + + if (pTarget) + { + DoCast(pTarget, SPELL_SOLARIUM_GREAT_HEAL); + healTimer = 9000; + } + } else healTimer -= diff; + + if (holysmiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARIUM_HOLY_SMITE); + holysmiteTimer = 4000; + } else holysmiteTimer -= diff; + + if (aoesilenceTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARIUM_ARCANE_TORRENT); + aoesilenceTimer = 13000; + } else aoesilenceTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_solarium_priest(Creature* pCreature) +{ + return new mob_solarium_priestAI (pCreature); +} + +CreatureAI* GetAI_boss_high_astromancer_solarian(Creature* pCreature) +{ + return new boss_high_astromancer_solarianAI (pCreature); +} + +void AddSC_boss_high_astromancer_solarian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_high_astromancer_solarian"; + newscript->GetAI = &GetAI_boss_high_astromancer_solarian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_solarium_priest"; + newscript->GetAI = &GetAI_mob_solarium_priest; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp new file mode 100644 index 00000000000..05681fb7539 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp @@ -0,0 +1,1498 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kaelthas +SD%Complete: 60 +SDComment: SQL, weapon scripts, mind control, need correct spells(interruptible/uninterruptible), phoenix spawn location & animation, phoenix behaviour & spawn during gravity lapse +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" +#include "WorldPacket.h" + +enum eEnums +{ + //kael'thas Speech + SAY_INTRO = -1550016, + SAY_INTRO_CAPERNIAN = -1550017, + SAY_INTRO_TELONICUS = -1550018, + SAY_INTRO_THALADRED = -1550019, + SAY_INTRO_SANGUINAR = -1550020, + SAY_PHASE2_WEAPON = -1550021, + SAY_PHASE3_ADVANCE = -1550022, + SAY_PHASE4_INTRO2 = -1550023, + SAY_PHASE5_NUTS = -1550024, + SAY_SLAY1 = -1550025, + SAY_SLAY2 = -1550026, + SAY_SLAY3 = -1550027, + SAY_MINDCONTROL1 = -1550028, + SAY_MINDCONTROL2 = -1550029, + SAY_GRAVITYLAPSE1 = -1550030, + SAY_GRAVITYLAPSE2 = -1550031, + SAY_SUMMON_PHOENIX1 = -1550032, + SAY_SUMMON_PHOENIX2 = -1550033, + SAY_DEATH = -1550034, + + //Thaladred the Darkener speech + SAY_THALADRED_AGGRO = -1550035, + SAY_THALADRED_DEATH = -1550036, + EMOTE_THALADRED_GAZE = -1550037, + + //Lord Sanguinar speech + SAY_SANGUINAR_AGGRO = -1550038, + SAY_SANGUINAR_DEATH = -1550039, + + //Grand Astromancer Capernian speech + SAY_CAPERNIAN_AGGRO = -1550040, + SAY_CAPERNIAN_DEATH = -1550041, + + //Master Engineer Telonicus speech + SAY_TELONICUS_AGGRO = -1550042, + SAY_TELONICUS_DEATH = -1550043, + + //Phase 2 spells + SPELL_SUMMON_WEAPONS = 36976, + SPELL_SUMMON_WEAPONA = 36958, + SPELL_SUMMON_WEAPONB = 36959, + SPELL_SUMMON_WEAPONC = 36960, + SPELL_SUMMON_WEAPOND = 36961, + SPELL_SUMMON_WEAPONE = 36962, + SPELL_SUMMON_WEAPONF = 36963, + SPELL_SUMMON_WEAPONG = 36964, + SPELL_RES_VISUAL = 24171, + + //Phase 4 spells + SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell + SPELL_PYROBLAST = 36819, + SPELL_FLAME_STRIKE = 36735, + SPELL_FLAME_STRIKE_VIS = 36730, + SPELL_FLAME_STRIKE_DMG = 36731, + SPELL_ARCANE_DISRUPTION = 36834, + SPELL_SHOCK_BARRIER = 36815, + SPELL_PHOENIX_ANIMATION = 36723, + SPELL_MIND_CONTROL = 32830, + + //Phase 5 spells + SPELL_EXPLODE = 36092, + SPELL_FULLPOWER = 36187, + SPELL_KNOCKBACK = 11027, + SPELL_GRAVITY_LAPSE = 34480, + SPELL_GRAVITY_LAPSE_AURA = 39432, + SPELL_NETHER_BEAM = 35873, + + //Thaladred the Darkener spells + SPELL_PSYCHIC_BLOW = 10689, + SPELL_SILENCE = 30225, + //Lord Sanguinar spells + SPELL_BELLOWING_ROAR = 40636, + //Grand Astromancer Capernian spells + + SPELL_CAPERNIAN_FIREBALL = 36971, + SPELL_CONFLAGRATION = 37018, + SPELL_ARCANE_EXPLOSION = 36970, + //Master Engineer Telonicus spells + SPELL_BOMB = 37036, + SPELL_REMOTE_TOY = 37027, + //Nether Vapor spell + SPELL_NETHER_VAPOR = 35859, + //Phoenix spell + SPELL_BURN = 36720, + SPELL_EMBER_BLAST = 34341, + SPELL_REBIRTH = 41587, + + //Creature IDs + NPC_PHOENIX = 21362, + NPC_PHOENIX_EGG = 21364, + + //Phoenix egg and phoenix model + MODEL_ID_PHOENIX = 19682, + MODEL_ID_PHOENIX_EGG = 20245, + + MAX_ADVISORS = 4 +}; + +uint32 m_auiSpellSummonWeapon[]= +{ + SPELL_SUMMON_WEAPONA, SPELL_SUMMON_WEAPONB, SPELL_SUMMON_WEAPONC, SPELL_SUMMON_WEAPOND, + SPELL_SUMMON_WEAPONE, SPELL_SUMMON_WEAPONF, SPELL_SUMMON_WEAPONG +}; + +const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target +const float KAEL_VISIBLE_RANGE = 50.0f; + +const float afGravityPos[3] = {795.0f, 0.0f, 70.0f}; + +#define TIME_PHASE_2_3 120000 +#define TIME_PHASE_3_4 180000 + +//Base AI for Advisors +struct advisorbase_ai : public ScriptedAI +{ + advisorbase_ai(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + m_bDoubled_Health = false; + } + + ScriptedInstance* m_pInstance; + bool FakeDeath; + bool m_bDoubled_Health; + uint32 DelayRes_Timer; + uint64 DelayRes_Target; + + void Reset() + { + if (m_bDoubled_Health) + { + me->SetMaxHealth(me->GetMaxHealth() / 2); + m_bDoubled_Health = false; + } + + FakeDeath = false; + DelayRes_Timer = 0; + DelayRes_Target = 0; + + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //reset encounter + if (m_pInstance && (m_pInstance->GetData(DATA_KAELTHASEVENT) == 1 || m_pInstance->GetData(DATA_KAELTHASEVENT) == 3)) + if (Creature *Kaelthas = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_KAELTHAS))) + Kaelthas->AI()->EnterEvadeMode(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void Revive(Unit* /*Target*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // double health for phase 3 + me->SetMaxHealth(me->GetMaxHealth() * 2); + m_bDoubled_Health = true; + me->SetHealth(me->GetMaxHealth()); + me->SetStandState(UNIT_STAND_STATE_STAND); + + DoCast(me, SPELL_RES_VISUAL, false); + DelayRes_Timer = 2000; + } + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage < me->GetHealth()) + return; + + //Prevent glitch if in fake death + if (FakeDeath && m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) + { + damage = 0; + return; + } + + //Don't really die in phase 1 & 3, only die after that + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) + { + //prevent death + damage = 0; + FakeDeath = true; + + me->InterruptNonMeleeSpells(false); + me->SetHealth(0); + me->StopMoving(); + me->ClearComboPointHolders(); + me->RemoveAllAurasOnDeath(); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->ClearAllReactives(); + me->SetUInt64Value(UNIT_FIELD_TARGET,0); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + JustDied(pKiller); + } + } + + void UpdateAI(const uint32 diff) + { + if (DelayRes_Timer) + { + if (DelayRes_Timer <= diff) + { + DelayRes_Timer = 0; + FakeDeath = false; + + Unit* Target = Unit::GetUnit((*me), DelayRes_Target); + if (!Target) + Target = me->getVictim(); + + DoResetThreat(); + AttackStart(Target); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(Target); + me->AddThreat(Target, 0.0f); + } else DelayRes_Timer -= diff; + } + } + +}; + +//Kael'thas AI +struct boss_kaelthasAI : public ScriptedAI +{ + boss_kaelthasAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me) + { + m_pInstance = pCreature->GetInstanceData(); + memset(&m_auiAdvisorGuid, 0, sizeof(m_auiAdvisorGuid)); + } + + ScriptedInstance* m_pInstance; + + uint32 Fireball_Timer; + uint32 ArcaneDisruption_Timer; + uint32 Phoenix_Timer; + uint32 ShockBarrier_Timer; + uint32 GravityLapse_Timer; + uint32 GravityLapse_Phase; + uint32 NetherBeam_Timer; + uint32 NetherVapor_Timer; + uint32 FlameStrike_Timer; + uint32 MindControl_Timer; + uint32 Phase; + uint32 PhaseSubphase; //generic + uint32 Phase_Timer; //generic timer + uint32 PyrosCasted; + + bool InGravityLapse; + bool IsCastingFireball; + bool ChainPyros; + + SummonList summons; + + uint64 m_auiAdvisorGuid[MAX_ADVISORS]; + + void Reset() + { + Fireball_Timer = 5000+rand()%10000; + ArcaneDisruption_Timer = 45000; + MindControl_Timer = 40000; + Phoenix_Timer = 50000; + ShockBarrier_Timer = 60000; + FlameStrike_Timer = 30000; + GravityLapse_Timer = 20000; + GravityLapse_Phase = 0; + NetherBeam_Timer = 8000; + NetherVapor_Timer = 10000; + PyrosCasted = 0; + Phase = 0; + InGravityLapse = false; + IsCastingFireball = false; + ChainPyros = false; + + if (me->isInCombat()) + PrepareAdvisors(); + + summons.DespawnAll(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 0); + } + + void PrepareAdvisors() + { + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + if (Creature *pCreature = Unit::GetCreature((*me), m_auiAdvisorGuid[i])) + { + pCreature->Respawn(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->setFaction(me->getFaction()); + pCreature->AI()->EnterEvadeMode(); + } + } + } + + void StartEvent() + { + if (!m_pInstance) + return; + + m_auiAdvisorGuid[0] = m_pInstance->GetData64(DATA_THALADREDTHEDARKENER); + m_auiAdvisorGuid[1] = m_pInstance->GetData64(DATA_LORDSANGUINAR); + m_auiAdvisorGuid[2] = m_pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN); + m_auiAdvisorGuid[3] = m_pInstance->GetData64(DATA_MASTERENGINEERTELONICUS); + + if (!m_auiAdvisorGuid[0] || !m_auiAdvisorGuid[1] || !m_auiAdvisorGuid[2] || !m_auiAdvisorGuid[3]) + { + error_log("TSCR: Kael'Thas One or more advisors missing, Skipping Phases 1-3"); + + DoScriptText(SAY_PHASE4_INTRO2, me); + + Phase = 4; + + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + AttackStart(pTarget); + + } + else + { + PrepareAdvisors(); + + DoScriptText(SAY_INTRO, me); + + m_pInstance->SetData(DATA_KAELTHASEVENT, 1); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + PhaseSubphase = 0; + Phase_Timer = 23000; + Phase = 1; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!me->hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() && + me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + if (!me->getVictim() && Phase >= 4) + { + who->RemoveAurasDueToSpell(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (me->GetMap()->IsDungeon()) + { + if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) + StartEvent(); + + who->SetInCombatWith(me); + me->AddThreat(who, 0.0f); + } + } + } + } + + void Aggro(Unit * /*who*/) + { + if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) + StartEvent(); + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustSummoned(Creature* pSummoned) + { + // if not phoenix, then it's one of the 7 weapons + if (pSummoned->GetEntry() != NPC_PHOENIX) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + + summons.Summon(pSummoned); + } + } + + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + + void JustDied(Unit* /*Killer*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + DoScriptText(SAY_DEATH, me); + + summons.DespawnAll(); + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 0); + + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + if (Unit* pAdvisor = Unit::GetUnit((*me), m_auiAdvisorGuid[i])) + pAdvisor->Kill(pAdvisor); + } + } + + void UpdateAI(const uint32 diff) + { + //Phase 1 + switch (Phase) + { + case 1: + { + Unit *pTarget = NULL; + Creature* Advisor = NULL; + + //Subphase switch + switch(PhaseSubphase) + { + //Subphase 1 - Start + case 0: + if (Phase_Timer <= diff) + { + DoScriptText(SAY_INTRO_THALADRED, me); + + //start advisor within 7 seconds + Phase_Timer = 7000; + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 1 - Unlock advisor + case 1: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 2 - Start + case 2: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_SANGUINAR, me); + + //start advisor within 12.5 seconds + Phase_Timer = 12500; + ++PhaseSubphase; + } + break; + + //Subphase 2 - Unlock advisor + case 3: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 3 - Start + case 4: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_CAPERNIAN, me); + + //start advisor within 7 seconds + Phase_Timer = 7000; + ++PhaseSubphase; + } + break; + + //Subphase 3 - Unlock advisor + case 5: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 4 - Start + case 6: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_TELONICUS, me); + + //start advisor within 8.4 seconds + Phase_Timer = 8400; + ++PhaseSubphase; + } + break; + + //Subphase 4 - Unlock advisor + case 7: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + Phase_Timer = 3000; + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //End of phase 1 + case 8: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + Phase = 2; + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 2); + + DoScriptText(SAY_PHASE2_WEAPON, me); + + PhaseSubphase = 0; + Phase_Timer = 3500; + DoCast(me, SPELL_SUMMON_WEAPONS); + } + break; + } + } + break; + + case 2: + { + if (PhaseSubphase == 0) + { + if (Phase_Timer <= diff) + { + PhaseSubphase = 1; + } else Phase_Timer -= diff; + } + + //Spawn weapons + if (PhaseSubphase == 1) + { + DoCast(me, SPELL_SUMMON_WEAPONS, false); + + uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32); + + for (uint32 i = 0; i < uiMaxWeapon; ++i) + DoCast(me, m_auiSpellSummonWeapon[i], true); + + PhaseSubphase = 2; + Phase_Timer = TIME_PHASE_2_3; + } + + if (PhaseSubphase == 2) + { + if (Phase_Timer <= diff) + { + DoScriptText(SAY_PHASE3_ADVANCE, me); + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 3); + Phase = 3; + PhaseSubphase = 0; + } else Phase_Timer -= diff; + } + } + break; + + case 3: + { + if (PhaseSubphase == 0) + { + //Respawn advisors + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + Creature *Advisor; + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + Advisor = Unit::GetCreature((*me), m_auiAdvisorGuid[i]); + + if (!Advisor) + error_log("SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); + else + CAST_AI(advisorbase_ai, Advisor->AI())->Revive(pTarget); + } + + PhaseSubphase = 1; + Phase_Timer = TIME_PHASE_3_4; + } + + if (Phase_Timer <= diff) + { + DoScriptText(SAY_PHASE4_INTRO2, me); + Phase = 4; + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + + // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. + DoResetThreat(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + AttackStart(pTarget); + + Phase_Timer = 30000; + } else Phase_Timer -= diff; + } + break; + + case 4: + case 5: + case 6: + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Fireball_Timer + if (!InGravityLapse && !ChainPyros && Phase != 5) + { + if (Fireball_Timer <= diff) + { + if (!IsCastingFireball) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + //interruptable + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); + int32 dmg = 20000+rand()%5000; + me->CastCustomSpell(me->getVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); + IsCastingFireball = true; + Fireball_Timer = 2500; + } + } + else + { + //apply resistance + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); + IsCastingFireball = false; + Fireball_Timer = 5000+rand()%10000; + } + } else Fireball_Timer -= diff; + + //ArcaneDisruption_Timer + if (ArcaneDisruption_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_DISRUPTION, true); + ArcaneDisruption_Timer = 60000; + } else ArcaneDisruption_Timer -= diff; + + if (FlameStrike_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_FLAME_STRIKE); + + FlameStrike_Timer = 30000; + } else FlameStrike_Timer -= diff; + + if (MindControl_Timer <= diff) + { + if (me->getThreatManager().getThreatList().size() >= 2) + for (uint32 i = 0; i < 3; ++i) + { + debug_log("SD2: Kael'Thas mind control not supported."); + //DoCast(pUnit, SPELL_MIND_CONTROL); + } + + MindControl_Timer = 60000; + } else MindControl_Timer -= diff; + } + + //Phoenix_Timer + if (Phoenix_Timer <= diff) + { + DoCast(me, SPELL_PHOENIX_ANIMATION); + DoScriptText(RAND(SAY_SUMMON_PHOENIX1,SAY_SUMMON_PHOENIX2), me); + + Phoenix_Timer = 60000; + } else Phoenix_Timer -= diff; + + //Phase 4 specific spells + if (Phase == 4) + { + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + Phase = 5; + Phase_Timer = 10000; + + DoScriptText(SAY_PHASE5_NUTS, me); + + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); + me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, 0, 0); + + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_FULLPOWER); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + //ShockBarrier_Timer + if (ShockBarrier_Timer <= diff) + { + DoCast(me, SPELL_SHOCK_BARRIER); + ChainPyros = true; + PyrosCasted = 0; + ShockBarrier_Timer = 60000; + } else ShockBarrier_Timer -= diff; + + //Chain Pyros (3 of them max) + if (ChainPyros && !me->IsNonMeleeSpellCasted(false)) + { + if (PyrosCasted < 3) + { + DoCast(me->getVictim(), SPELL_PYROBLAST); + ++PyrosCasted; + } + else + { + ChainPyros = false; + Fireball_Timer = 2500; + ArcaneDisruption_Timer = 60000; + } + } + } + + if (Phase == 5) + { + if (Phase_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + me->RemoveAurasDueToSpell(SPELL_FULLPOWER); + + DoCast(me, SPELL_EXPLODE); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Phase = 6; + AttackStart(me->getVictim()); + } else Phase_Timer -= diff; + } + + //Phase 5 + if (Phase == 6) + { + + //GravityLapse_Timer + if (GravityLapse_Timer <= diff) + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + switch (GravityLapse_Phase) + { + case 0: + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); + me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, MOVEMENTFLAG_NONE, 0); + + // 1) Kael'thas will portal the whole raid right into his body + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + //Use work around packet to prevent player from being dropped from combat + DoTeleportPlayer(pUnit, afGravityPos[0], afGravityPos[1], afGravityPos[2], pUnit->GetOrientation()); + } + } + + GravityLapse_Timer = 500; + ++GravityLapse_Phase; + InGravityLapse = true; + ShockBarrier_Timer = 1000; + NetherBeam_Timer = 5000; + break; + + case 1: + DoScriptText(RAND(SAY_GRAVITYLAPSE1,SAY_GRAVITYLAPSE2), me); + + // 2) At that point he will put a Gravity Lapse debuff on everyone + for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) + { + if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) + { + DoCast(pUnit, SPELL_KNOCKBACK, true); + //Gravity lapse - needs an exception in Spell system to work + + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); + + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + GravityLapse_Timer = 10000; + ++GravityLapse_Phase; + break; + + case 2: + //Cast nether vapor aura on self + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_NETHER_VAPOR); + + GravityLapse_Timer = 20000; + ++GravityLapse_Phase; + break; + + case 3: + //Remove flight + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) + { + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + + me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); + InGravityLapse = false; + GravityLapse_Timer = 60000; + GravityLapse_Phase = 0; + AttackStart(me->getVictim()); + break; + } + } else GravityLapse_Timer -= diff; + + if (InGravityLapse) + { + //ShockBarrier_Timer + if (ShockBarrier_Timer <= diff) + { + DoCast(me, SPELL_SHOCK_BARRIER); + ShockBarrier_Timer = 20000; + } else ShockBarrier_Timer -= diff; + + //NetherBeam_Timer + if (NetherBeam_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_NETHER_BEAM); + + NetherBeam_Timer = 4000; + } else NetherBeam_Timer -= diff; + } + } + + if (!InGravityLapse) + DoMeleeAttackIfReady(); + } + } + } +}; + +//Thaladred the Darkener AI +struct boss_thaladred_the_darkenerAI : public advisorbase_ai +{ + boss_thaladred_the_darkenerAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Gaze_Timer; + uint32 Silence_Timer; + uint32 PsychicBlow_Timer; + + void Reset() + { + Gaze_Timer = 100; + Silence_Timer = 20000; + PsychicBlow_Timer = 10000; + + advisorbase_ai::Reset(); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_THALADRED_AGGRO, me); + me->AddThreat(who, 5000000.0f); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_THALADRED_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Gaze_Timer + if (Gaze_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoResetThreat(); + me->AddThreat(pTarget, 5000000.0f); + DoScriptText(EMOTE_THALADRED_GAZE, me, pTarget); + Gaze_Timer = 8500; + } + } else Gaze_Timer -= diff; + + //Silence_Timer + if (Silence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + Silence_Timer = 20000; + } else Silence_Timer -= diff; + + //PsychicBlow_Timer + if (PsychicBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PSYCHIC_BLOW); + PsychicBlow_Timer = 20000+rand()%5000; + } else PsychicBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Lord Sanguinar AI +struct boss_lord_sanguinarAI : public advisorbase_ai +{ + boss_lord_sanguinarAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Fear_Timer; + + void Reset() + { + Fear_Timer = 20000; + advisorbase_ai::Reset(); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_SANGUINAR_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_SANGUINAR_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); + Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds + } else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Grand Astromancer Capernian AI +struct boss_grand_astromancer_capernianAI : public advisorbase_ai +{ + boss_grand_astromancer_capernianAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Fireball_Timer; + uint32 Conflagration_Timer; + uint32 ArcaneExplosion_Timer; + uint32 Yell_Timer; + bool Yell; + + void Reset() + { + Fireball_Timer = 2000; + Conflagration_Timer = 20000; + ArcaneExplosion_Timer = 5000; + Yell_Timer = 2000; + Yell = false; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_CAPERNIAN_DEATH, me); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(who, CAPERNIAN_DISTANCE); + } + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Yell_Timer + if (!Yell) + { + if (Yell_Timer <= diff) + { + DoScriptText(SAY_CAPERNIAN_AGGRO, me); + Yell = true; + } else Yell_Timer -= diff; + } + + //Fireball_Timer + if (Fireball_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CAPERNIAN_FIREBALL); + Fireball_Timer = 4000; + } else Fireball_Timer -= diff; + + //Conflagration_Timer + if (Conflagration_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget && me->IsWithinDistInMap(pTarget, 30)) + DoCast(pTarget, SPELL_CONFLAGRATION); + else + DoCast(me->getVictim(), SPELL_CONFLAGRATION); + + Conflagration_Timer = 10000+rand()%5000; + } else Conflagration_Timer -= diff; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + bool InMeleeRange = false; + Unit *pTarget = NULL; + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + //if in melee range + if (pUnit && pUnit->IsWithinDistInMap(me, 5)) + { + InMeleeRange = true; + pTarget = pUnit; + break; + } + } + + if (InMeleeRange) + DoCast(pTarget, SPELL_ARCANE_EXPLOSION); + + ArcaneExplosion_Timer = 4000+rand()%2000; + } else ArcaneExplosion_Timer -= diff; + + //Do NOT deal any melee damage. + } +}; + +//Master Engineer Telonicus AI +struct boss_master_engineer_telonicusAI : public advisorbase_ai +{ + boss_master_engineer_telonicusAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Bomb_Timer; + uint32 RemoteToy_Timer; + + void Reset() + { + Bomb_Timer = 10000; + RemoteToy_Timer = 5000; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_TELONICUS_DEATH, me); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_TELONICUS_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, do nothing + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Bomb_Timer + if (Bomb_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BOMB); + Bomb_Timer = 25000; + } else Bomb_Timer -= diff; + + //RemoteToy_Timer + if (RemoteToy_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_REMOTE_TOY); + + RemoteToy_Timer = 10000+rand()%5000; + } else RemoteToy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Flame Strike AI +struct mob_kael_flamestrikeAI : public Scripted_NoMovementAI +{ + mob_kael_flamestrikeAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) {} + + uint32 Timer; + bool Casting; + bool KillSelf; + + void Reset() + { + Timer = 5000; + Casting = false; + KillSelf = false; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + } + + void MoveInLineOfSight(Unit * /*who*/) {} + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!Casting) + { + DoCast(me, SPELL_FLAME_STRIKE_VIS); + Casting = true; + } + + //Timer + if (Timer <= diff) + { + if (!KillSelf) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_FLAME_STRIKE_DMG); + } else me->Kill(me); + + KillSelf = true; + Timer = 1000; + } else Timer -= diff; + } +}; + +//Phoenix AI +struct mob_phoenix_tkAI : public ScriptedAI +{ + mob_phoenix_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 Cycle_Timer; + + void Reset() + { + Cycle_Timer = 2000; + DoCast(me, SPELL_BURN, true); + } + + void JustDied(Unit* /*killer*/) + { + //is this spell in use anylonger? + //DoCast(me, SPELL_EMBER_BLAST, true); + me->SummonCreature(NPC_PHOENIX_EGG,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,16000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Cycle_Timer <= diff) + { + //spell Burn should possible do this, but it doesn't, so do this for now. + uint32 dmg = urand(4500,5500); + if (me->GetHealth() > dmg) + me->SetHealth(uint32(me->GetHealth()-dmg)); + Cycle_Timer = 2000; + } else Cycle_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Phoenix Egg AI +struct mob_phoenix_egg_tkAI : public ScriptedAI +{ + mob_phoenix_egg_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 Rebirth_Timer; + + void Reset() + { + Rebirth_Timer = 15000; + } + + //ignore any + void MoveInLineOfSight(Unit* /*who*/) {} + + void AttackStart(Unit* who) + { + if (me->Attack(who, false)) + { + me->SetInCombatWith(who); + who->SetInCombatWith(me); + + DoStartNoMovement(who); + } + } + + void JustSummoned(Creature* summoned) + { + summoned->AddThreat(me->getVictim(), 0.0f); + summoned->CastSpell(summoned,SPELL_REBIRTH,false); + } + + void UpdateAI(const uint32 diff) + { + if (!Rebirth_Timer) + return; + + if (Rebirth_Timer <= diff) + { + me->SummonCreature(NPC_PHOENIX,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,5000); + Rebirth_Timer = 0; + } else Rebirth_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_kaelthas(Creature* pCreature) +{ + return new boss_kaelthasAI(pCreature); +} + +CreatureAI* GetAI_boss_thaladred_the_darkener(Creature* pCreature) +{ + return new boss_thaladred_the_darkenerAI(pCreature); +} + +CreatureAI* GetAI_boss_lord_sanguinar(Creature* pCreature) +{ + return new boss_lord_sanguinarAI(pCreature); +} + +CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature* pCreature) +{ + return new boss_grand_astromancer_capernianAI(pCreature); +} + +CreatureAI* GetAI_boss_master_engineer_telonicus(Creature* pCreature) +{ + return new boss_master_engineer_telonicusAI(pCreature); +} + +CreatureAI* GetAI_mob_kael_flamestrike(Creature* pCreature) +{ + return new mob_kael_flamestrikeAI(pCreature); +} + +CreatureAI* GetAI_mob_phoenix_tk(Creature* pCreature) +{ + return new mob_phoenix_tkAI(pCreature); +} + +CreatureAI* GetAI_mob_phoenix_egg_tk(Creature* pCreature) +{ + return new mob_phoenix_egg_tkAI(pCreature); +} + +void AddSC_boss_kaelthas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kaelthas"; + newscript->GetAI = &GetAI_boss_kaelthas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_thaladred_the_darkener"; + newscript->GetAI = &GetAI_boss_thaladred_the_darkener; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_sanguinar"; + newscript->GetAI = &GetAI_boss_lord_sanguinar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_grand_astromancer_capernian"; + newscript->GetAI = &GetAI_boss_grand_astromancer_capernian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_master_engineer_telonicus"; + newscript->GetAI = &GetAI_boss_master_engineer_telonicus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_kael_flamestrike"; + newscript->GetAI = &GetAI_mob_kael_flamestrike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phoenix_tk"; + newscript->GetAI = &GetAI_mob_phoenix_tk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phoenix_egg_tk"; + newscript->GetAI = &GetAI_mob_phoenix_egg_tk; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp new file mode 100644 index 00000000000..e1b60b20948 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp @@ -0,0 +1,179 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Void_Reaver +SD%Complete: 90 +SDComment: Should reset if raid are out of room. +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +enum eEnums +{ + SAY_AGGRO = -1550000, + SAY_SLAY1 = -1550001, + SAY_SLAY2 = -1550002, + SAY_SLAY3 = -1550003, + SAY_DEATH = -1550004, + SAY_POUNDING1 = -1550005, + SAY_POUNDING2 = -1550006, + + SPELL_POUNDING = 34162, + SPELL_ARCANE_ORB = 34172, + SPELL_KNOCK_AWAY = 25778, + SPELL_BERSERK = 27680 +}; + +struct boss_void_reaverAI : public ScriptedAI +{ + boss_void_reaverAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Pounding_Timer; + uint32 ArcaneOrb_Timer; + uint32 KnockAway_Timer; + uint32 Berserk_Timer; + + bool Enraged; + + void Reset() + { + Pounding_Timer = 15000; + ArcaneOrb_Timer = 3000; + KnockAway_Timer = 30000; + Berserk_Timer = 600000; + + Enraged = false; + + if (pInstance && me->isAlive()) + pInstance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Pounding + if (Pounding_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POUNDING); + + DoScriptText(RAND(SAY_POUNDING1,SAY_POUNDING2), me); + Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000) + } else Pounding_Timer -= diff; + + // Arcane Orb + if (ArcaneOrb_Timer <= diff) + { + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (!pTarget) + continue; + + // exclude pets & totems + if (pTarget->GetTypeId() != TYPEID_PLAYER) + continue; + + //18 yard radius minimum + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive() && !pTarget->IsWithinDist(me, 18, false)) + target_list.push_back(pTarget); + pTarget = NULL; + } + + if (target_list.size()) + pTarget = *(target_list.begin()+rand()%target_list.size()); + else + pTarget = me->getVictim(); + + if (pTarget) + me->CastSpell(pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(), SPELL_ARCANE_ORB, false, NULL, NULL, NULL, pTarget); + + ArcaneOrb_Timer = 3000; + } else ArcaneOrb_Timer -= diff; + + // Single Target knock back, reduces aggro + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCK_AWAY); + + //Drop 25% aggro + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-25); + + KnockAway_Timer = 30000; + } else KnockAway_Timer -= diff; + + //Berserk + if (Berserk_Timer < diff && !Enraged) + { + DoCast(me, SPELL_BERSERK); + Enraged = true; + } else Berserk_Timer -= diff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_void_reaver(Creature* pCreature) +{ + return new boss_void_reaverAI (pCreature); +} + +void AddSC_boss_void_reaver() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_void_reaver"; + newscript->GetAI = &GetAI_boss_void_reaver; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp new file mode 100644 index 00000000000..59c72071238 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp @@ -0,0 +1,176 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_The_Eye +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define MAX_ENCOUNTER 5 + +/* The Eye encounters: +0 - Kael'thas event +1 - Al' ar event +2 - Solarian Event +3 - Void Reaver event +*/ + +struct instance_the_eye : public ScriptedInstance +{ + instance_the_eye(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 ThaladredTheDarkener; + uint64 LordSanguinar; + uint64 GrandAstromancerCapernian; + uint64 MasterEngineerTelonicus; + uint64 Kaelthas; + uint64 Astromancer; + uint64 Alar; + + uint8 KaelthasEventPhase; + uint8 AlarEventPhase; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + ThaladredTheDarkener = 0; + LordSanguinar = 0; + GrandAstromancerCapernian = 0; + MasterEngineerTelonicus = 0; + Kaelthas = 0; + Astromancer = 0; + Alar = 0; + + KaelthasEventPhase = 0; + AlarEventPhase = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 20064: ThaladredTheDarkener = pCreature->GetGUID(); break; + case 20063: MasterEngineerTelonicus = pCreature->GetGUID(); break; + case 20062: GrandAstromancerCapernian = pCreature->GetGUID(); break; + case 20060: LordSanguinar = pCreature->GetGUID(); break; + case 19622: Kaelthas = pCreature->GetGUID(); break; + case 18805: Astromancer = pCreature->GetGUID(); break; + case 19514: Alar = pCreature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_THALADREDTHEDARKENER: return ThaladredTheDarkener; + case DATA_LORDSANGUINAR: return LordSanguinar; + case DATA_GRANDASTROMANCERCAPERNIAN: return GrandAstromancerCapernian; + case DATA_MASTERENGINEERTELONICUS: return MasterEngineerTelonicus; + case DATA_KAELTHAS: return Kaelthas; + case DATA_ASTROMANCER: return Astromancer; + case DATA_ALAR: return Alar; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_ALAREVENT: AlarEventPhase = data; m_auiEncounter[0] = data; break; + case DATA_HIGHASTROMANCERSOLARIANEVENT: m_auiEncounter[1] = data; break; + case DATA_VOIDREAVEREVENT: m_auiEncounter[2] = data; break; + case DATA_KAELTHASEVENT: KaelthasEventPhase = data; m_auiEncounter[3] = data; break; + } + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_ALAREVENT: return AlarEventPhase; + case DATA_HIGHASTROMANCERSOLARIANEVENT: return m_auiEncounter[1]; + case DATA_VOIDREAVEREVENT: return m_auiEncounter[2]; + case DATA_KAELTHASEVENT: return KaelthasEventPhase; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_the_eye(Map* pMap) +{ + return new instance_the_eye(pMap); +} + +void AddSC_instance_the_eye() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_the_eye"; + newscript->GetInstanceData = &GetInstanceData_instance_the_eye; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp new file mode 100644 index 00000000000..97021fdc031 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: The_Eye +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +/* ContentData +mob_crystalcore_devastator +EndContentData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define SPELL_COUNTERCHARGE 35035 +#define SPELL_KNOCKAWAY 22893 + +struct mob_crystalcore_devastatorAI : public ScriptedAI +{ + mob_crystalcore_devastatorAI(Creature *c) : ScriptedAI(c) {} + + uint32 Knockaway_Timer; + uint32 Countercharge_Timer; + + void Reset() + { + Countercharge_Timer = 9000; + Knockaway_Timer = 25000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Check if we have a current target + //Knockaway_Timer + if (Knockaway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); + + // current aggro target is knocked away pick new target + Unit* pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!pTarget || pTarget == me->getVictim()) + pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + + if (pTarget) + me->TauntApply(pTarget); + + Knockaway_Timer = 23000; + } else Knockaway_Timer -= diff; + + //Countercharge_Timer + if (Countercharge_Timer <= diff) + { + DoCast(me, SPELL_COUNTERCHARGE); + Countercharge_Timer = 45000; + } else Countercharge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_crystalcore_devastator(Creature* pCreature) +{ + return new mob_crystalcore_devastatorAI (pCreature); +} + +void AddSC_the_eye() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_crystalcore_devastator"; + newscript->GetAI = &GetAI_mob_crystalcore_devastator; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h b/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h new file mode 100644 index 00000000000..d0d3ea09061 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h @@ -0,0 +1,20 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_THE_EYE_H +#define DEF_THE_EYE_H + +#define DATA_ALAREVENT 1 +#define DATA_ASTROMANCER 2 +#define DATA_GRANDASTROMANCERCAPERNIAN 3 +#define DATA_HIGHASTROMANCERSOLARIANEVENT 4 +#define DATA_KAELTHAS 5 +#define DATA_KAELTHASEVENT 6 +#define DATA_LORDSANGUINAR 7 +#define DATA_MASTERENGINEERTELONICUS 8 +#define DATA_THALADREDTHEDARKENER 10 +#define DATA_VOIDREAVEREVENT 11 +#define DATA_ALAR 12 +#endif + diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp new file mode 100644 index 00000000000..b9c365eda65 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp @@ -0,0 +1,39 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gatewatcher_Gyrokill +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +//not used +#define SAY_AGGRO -1554000 +#define SAY_SAW_ATTACK1 -1554001 +#define SAY_SAW_ATTACK2 -1554002 +#define SAY_SLAY1 -1554003 +#define SAY_SLAY2 -1554004 +#define SAY_DEATH -1554005 + +#define SPELL_STREAM_OF_MACHINE_FLUID 35311 +#define SPELL_SAW_BLADE 35318 +#define H_SPELL_SAW_BLADE 39192 +#define SPELL_SHADOW_POWER 35322 +#define H_SPELL_SHADOW_POWER 39193 + diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp new file mode 100644 index 00000000000..50c3a6171ce --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp @@ -0,0 +1,130 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Gatewatcher_Ironhand +SD%Complete: 75 +SDComment: +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1554006 +#define SAY_HAMMER_1 -1554007 +#define SAY_HAMMER_2 -1554008 +#define SAY_SLAY_1 -1554009 +#define SAY_SLAY_2 -1554010 +#define SAY_DEATH_1 -1554011 +#define EMOTE_HAMMER -1554012 + +// Spells to be casted +#define SPELL_SHADOW_POWER 35322 +#define H_SPELL_SHADOW_POWER 39193 +#define SPELL_HAMMER_PUNCH 35326 +#define SPELL_JACKHAMMER 35327 +#define H_SPELL_JACKHAMMER 39194 +#define SPELL_STREAM_OF_MACHINE_FLUID 35311 + +// Gatewatcher Iron-Hand AI +struct boss_gatewatcher_iron_handAI : public ScriptedAI +{ + boss_gatewatcher_iron_handAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Shadow_Power_Timer; + uint32 Jackhammer_Timer; + uint32 Stream_of_Machine_Fluid_Timer; + + void Reset() + { + Shadow_Power_Timer = 25000; + Jackhammer_Timer = 45000; + Stream_of_Machine_Fluid_Timer = 55000; + + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO_1, me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH_1, me); + //TODO: Add door check/open code + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Shadow Power + if (Shadow_Power_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_POWER); + Shadow_Power_Timer = 20000 + rand()%8000; + } else Shadow_Power_Timer -= diff; + + //Jack Hammer + if (Jackhammer_Timer <= diff) + { + //TODO: expect cast this about 5 times in a row (?), announce it by emote only once + DoScriptText(EMOTE_HAMMER, me); + DoCast(me->getVictim(), SPELL_JACKHAMMER); + + //chance to yell, but not same time as emote (after spell in fact casted) + if (rand()%2) + return; + + DoScriptText(RAND(SAY_HAMMER_1,SAY_HAMMER_2), me); + Jackhammer_Timer = 30000; + } else Jackhammer_Timer -= diff; + + //Stream of Machine Fluid + if (Stream_of_Machine_Fluid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STREAM_OF_MACHINE_FLUID); + Stream_of_Machine_Fluid_Timer = 35000 + rand()%15000; + } else Stream_of_Machine_Fluid_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gatewatcher_iron_hand(Creature* pCreature) +{ + return new boss_gatewatcher_iron_handAI (pCreature); +} + +void AddSC_boss_gatewatcher_iron_hand() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gatewatcher_iron_hand"; + newscript->GetAI = &GetAI_boss_gatewatcher_iron_hand; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp new file mode 100644 index 00000000000..ededec0196d --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp @@ -0,0 +1,245 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Nethermancer_Sepethrea +SD%Complete: 90 +SDComment: Need adjustments to initial summons +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" +#include "mechanar.h" + +#define SAY_AGGRO -1554013 +#define SAY_SUMMON -1554014 +#define SAY_DRAGONS_BREATH_1 -1554015 +#define SAY_DRAGONS_BREATH_2 -1554016 +#define SAY_SLAY1 -1554017 +#define SAY_SLAY2 -1554018 +#define SAY_DEATH -1554019 + +#define SPELL_SUMMON_RAGIN_FLAMES 35275 +#define H_SPELL_SUMMON_RAGIN_FLAMES 39084 + +#define SPELL_FROST_ATTACK 35263 +#define SPELL_ARCANE_BLAST 35314 +#define SPELL_DRAGONS_BREATH 35250 +#define SPELL_KNOCKBACK 37317 +#define SPELL_SOLARBURN 35267 + +struct boss_nethermancer_sepethreaAI : public ScriptedAI +{ + boss_nethermancer_sepethreaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 frost_attack_Timer; + uint32 arcane_blast_Timer; + uint32 dragons_breath_Timer; + uint32 knockback_Timer; + uint32 solarburn_Timer; + + void Reset() + { + frost_attack_Timer = 7000 + rand()%3000; + arcane_blast_Timer = 12000 + rand()%6000; + dragons_breath_Timer = 18000 + rand()%4000; + knockback_Timer = 22000 + rand()%6000; + solarburn_Timer = 30000; + + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, me); + DoCast(who, SPELL_SUMMON_RAGIN_FLAMES); + DoScriptText(SAY_SUMMON, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frost Attack + if (frost_attack_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_ATTACK); + frost_attack_Timer = 7000 + rand()%3000; + } else frost_attack_Timer -= diff; + + //Arcane Blast + if (arcane_blast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BLAST); + arcane_blast_Timer = 15000; + } else arcane_blast_Timer -= diff; + + //Dragons Breath + if (dragons_breath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DRAGONS_BREATH); + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_DRAGONS_BREATH_1,SAY_DRAGONS_BREATH_2), me); + } + dragons_breath_Timer = 12000 + rand()%10000; + } else dragons_breath_Timer -= diff; + + //Knockback + if (knockback_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKBACK); + knockback_Timer = 15000 + rand()%10000; + } else knockback_Timer -= diff; + + //Solarburn + if (solarburn_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARBURN); + solarburn_Timer = 30000; + } else solarburn_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nethermancer_sepethrea(Creature* pCreature) +{ + return new boss_nethermancer_sepethreaAI (pCreature); +} + +#define SPELL_INFERNO 35268 +#define H_SPELL_INFERNO 39346 +#define SPELL_FIRE_TAIL 35278 + +struct mob_ragin_flamesAI : public ScriptedAI +{ + mob_ragin_flamesAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 inferno_Timer; + uint32 flame_timer; + uint32 Check_Timer; + + bool onlyonce; + + void Reset() + { + inferno_Timer = 10000; + flame_timer = 500; + Check_Timer = 2000; + onlyonce = false; + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); + } + + void EnterCombat(Unit* /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Check_Timer + if (Check_Timer <= diff) + { + if (pInstance) + { + if (pInstance->GetData(DATA_NETHERMANCER_EVENT) != IN_PROGRESS) + { + //remove + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } + } + Check_Timer = 1000; + } else Check_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (!onlyonce) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + me->GetMotionMaster()->MoveChase(pTarget); + onlyonce = true; + } + + if (inferno_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_INFERNO); + me->TauntApply(me->getVictim()); + inferno_Timer = 10000; + } else inferno_Timer -= diff; + + if (flame_timer <= diff) + { + DoCast(me, SPELL_FIRE_TAIL); + flame_timer = 500; + } else flame_timer -=diff; + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_mob_ragin_flames(Creature* pCreature) +{ + return new mob_ragin_flamesAI (pCreature); +} +void AddSC_boss_nethermancer_sepethrea() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nethermancer_sepethrea"; + newscript->GetAI = &GetAI_boss_nethermancer_sepethrea; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ragin_flames"; + newscript->GetAI = &GetAI_mob_ragin_flames; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp new file mode 100644 index 00000000000..c0c06704db7 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp @@ -0,0 +1,246 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss Pathaleon the Calculator +SD%Complete: 50 +SDComment: Event missing. Script for himself 99% blizzlike. +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1554020 +#define SAY_DOMINATION_1 -1554021 +#define SAY_DOMINATION_2 -1554022 +#define SAY_SUMMON -1554023 +#define SAY_ENRAGE -1554024 +#define SAY_SLAY_1 -1554025 +#define SAY_SLAY_2 -1554026 +#define SAY_DEATH -1554027 + +// Spells to be casted +#define SPELL_MANA_TAP 36021 +#define SPELL_ARCANE_TORRENT 36022 +#define SPELL_DOMINATION 35280 +#define H_SPELL_ARCANE_EXPLOSION 15453 +#define SPELL_FRENZY 36992 + +#define SPELL_SUMMON_NETHER_WRAITH_1 35285 //Spells work, but not implemented +#define SPELL_SUMMON_NETHER_WRAITH_2 35286 +#define SPELL_SUMMON_NETHER_WRAITH_3 35287 +#define SPELL_SUMMON_NETHER_WRAITH_4 35288 + +// Add Spells +#define SPELL_DETONATION 35058 +#define SPELL_ARCANE_MISSILES 35034 + +struct boss_pathaleon_the_calculatorAI : public ScriptedAI +{ + boss_pathaleon_the_calculatorAI(Creature *c) : ScriptedAI(c), summons(me) + { + } + + uint32 Summon_Timer; + SummonList summons; + uint32 ManaTap_Timer; + uint32 ArcaneTorrent_Timer; + uint32 Domination_Timer; + uint32 ArcaneExplosion_Timer; + + bool Enraged; + + uint32 Counter; + + void Reset() + { + Summon_Timer = 30000; + ManaTap_Timer = 12000 + rand()%8000; + ArcaneTorrent_Timer = 16000 + rand()%9000; + Domination_Timer = 25000 + rand()%15000; + ArcaneExplosion_Timer = 8000 + rand()%5000; + + Enraged = false; + + Counter = 0; + summons.DespawnAll(); + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + summons.DespawnAll(); + } + + void JustSummoned(Creature *summon) {summons.Summon(summon);} + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Summon_Timer <= diff) + { + for (uint8 i = 0; i < 3; ++i) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + Creature* Wraith = me->SummonCreature(21062,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + if (pTarget && Wraith) + Wraith->AI()->AttackStart(pTarget); + } + DoScriptText(SAY_SUMMON, me); + Summon_Timer = 30000 + rand()%15000; + } else Summon_Timer -= diff; + + if (ManaTap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MANA_TAP); + ManaTap_Timer = 14000 + rand()%8000; + } else ManaTap_Timer -= diff; + + if (ArcaneTorrent_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_TORRENT); + ArcaneTorrent_Timer = 12000 + rand()%6000; + } else ArcaneTorrent_Timer -= diff; + + if (Domination_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + DoScriptText(RAND(SAY_DOMINATION_1,SAY_DOMINATION_2), me); + + DoCast(pTarget, SPELL_DOMINATION); + } + Domination_Timer = 25000 + rand()%5000; + } else Domination_Timer -= diff; + + //Only casting if Heroic Mode is used + if (IsHeroic()) + { + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), H_SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 10000 + rand()%4000; + } else ArcaneExplosion_Timer -= diff; + } + + if (!Enraged && me->GetHealth()*100 / me->GetMaxHealth() < 21) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(SAY_ENRAGE, me); + Enraged = true; + + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_pathaleon_the_calculator(Creature* pCreature) +{ + return new boss_pathaleon_the_calculatorAI (pCreature); +} + +struct mob_nether_wraithAI : public ScriptedAI +{ + mob_nether_wraithAI(Creature *c) : ScriptedAI(c) {} + + uint32 ArcaneMissiles_Timer; + uint32 Detonation_Timer; + uint32 Die_Timer; + bool Detonation; + + void Reset() + { + ArcaneMissiles_Timer = 1000 + rand()%3000; + Detonation_Timer = 20000; + Die_Timer = 2200; + Detonation = false; + + } + + void EnterCombat(Unit* /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ArcaneMissiles_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_ARCANE_MISSILES); + else + DoCast(me->getVictim(), SPELL_ARCANE_MISSILES); + + ArcaneMissiles_Timer = 5000 + rand()%5000; + } else ArcaneMissiles_Timer -=diff; + + if (!Detonation) + { + if (Detonation_Timer <= diff) + { + DoCast(me, SPELL_DETONATION); + Detonation = true; + } else Detonation_Timer -= diff; + } + + if (Detonation) + { + if (Die_Timer <= diff) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } else Die_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_mob_nether_wraith(Creature* pCreature) +{ + return new mob_nether_wraithAI (pCreature); +} + +void AddSC_boss_pathaleon_the_calculator() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_pathaleon_the_calculator"; + newscript->GetAI = &GetAI_boss_pathaleon_the_calculator; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nether_wraith"; + newscript->GetAI = &GetAI_mob_nether_wraith; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp new file mode 100644 index 00000000000..c70da24ea3f --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Mechanar +SD%Complete: 100 +SDComment: +SDCategory: Mechanar +EndScriptData */ + +#include "ScriptedPch.h" +#include "mechanar.h" + +#define MAX_ENCOUNTER 1 + +struct instance_mechanar : public ScriptedInstance +{ + instance_mechanar(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_NETHERMANCER_EVENT: return m_auiEncounter[0]; + } + + return false; + } + + uint64 GetData64 (uint32 /*identifier*/) + { + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_NETHERMANCER_EVENT: m_auiEncounter[0] = data; break; + } + } +}; + +InstanceData* GetInstanceData_instance_mechanar(Map* pMap) +{ + return new instance_mechanar(pMap); +} + +void AddSC_instance_mechanar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_mechanar"; + newscript->GetInstanceData = &GetInstanceData_instance_mechanar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h b/src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h new file mode 100644 index 00000000000..d1b53eebf53 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h @@ -0,0 +1,6 @@ +#ifndef DEF_MECHANAR_H +#define DEF_MECHANAR_H + +#define DATA_NETHERMANCER_EVENT 1 +#endif + diff --git a/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp b/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp deleted file mode 100644 index bfde95ffcb0..00000000000 --- a/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Exarch_Maladaar -SD%Complete: 95 -SDComment: Most of event implemented, some adjustments to timers remain and possibly make some better code for switching his dark side in to better "images" of player. -SDCategory: Auchindoun, Auchenai Crypts -EndScriptData */ - -/* ContentData -mob_stolen_soul -boss_exarch_maladaar -mob_avatar_of_martyred -EndContentData */ - -#include "ScriptedPch.h" - -#define SPELL_MOONFIRE 37328 -#define SPELL_FIREBALL 37329 -#define SPELL_MIND_FLAY 37330 -#define SPELL_HEMORRHAGE 37331 -#define SPELL_FROSTSHOCK 37332 -#define SPELL_CURSE_OF_AGONY 37334 -#define SPELL_MORTAL_STRIKE 37335 -#define SPELL_FREEZING_TRAP 37368 -#define SPELL_HAMMER_OF_JUSTICE 37369 - -struct mob_stolen_soulAI : public ScriptedAI -{ - mob_stolen_soulAI(Creature *c) : ScriptedAI(c) {} - - uint8 myClass; - uint32 Class_Timer; - - void Reset() - { - Class_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { } - - void SetMyClass(uint8 myclass) - { - myClass = myclass; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Class_Timer <= diff) - { - switch (myClass) - { - case CLASS_WARRIOR: - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - Class_Timer = 6000; - break; - case CLASS_PALADIN: - DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); - Class_Timer = 6000; - break; - case CLASS_HUNTER: - DoCast(me->getVictim(), SPELL_FREEZING_TRAP); - Class_Timer = 20000; - break; - case CLASS_ROGUE: - DoCast(me->getVictim(), SPELL_HEMORRHAGE); - Class_Timer = 10000; - break; - case CLASS_PRIEST: - DoCast(me->getVictim(), SPELL_MIND_FLAY); - Class_Timer = 5000; - break; - case CLASS_SHAMAN: - DoCast(me->getVictim(), SPELL_FROSTSHOCK); - Class_Timer = 8000; - break; - case CLASS_MAGE: - DoCast(me->getVictim(), SPELL_FIREBALL); - Class_Timer = 5000; - break; - case CLASS_WARLOCK: - DoCast(me->getVictim(), SPELL_CURSE_OF_AGONY); - Class_Timer = 20000; - break; - case CLASS_DRUID: - DoCast(me->getVictim(), SPELL_MOONFIRE); - Class_Timer = 10000; - break; - } - } else Class_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_stolen_soul(Creature* pCreature) -{ - return new mob_stolen_soulAI (pCreature); -} - -#define SAY_INTRO -1558000 -#define SAY_SUMMON -1558001 - -#define SAY_AGGRO_1 -1558002 -#define SAY_AGGRO_2 -1558003 -#define SAY_AGGRO_3 -1558004 - -#define SAY_ROAR -1558005 -#define SAY_SOUL_CLEAVE -1558006 - -#define SAY_SLAY_1 -1558007 -#define SAY_SLAY_2 -1558008 - -#define SAY_DEATH -1558009 - -#define SPELL_RIBBON_OF_SOULS 32422 -#define SPELL_SOUL_SCREAM 32421 - -#define SPELL_STOLEN_SOUL 32346 -#define SPELL_STOLEN_SOUL_VISUAL 32395 - -#define SPELL_SUMMON_AVATAR 32424 - -#define ENTRY_STOLEN_SOUL 18441 - -struct boss_exarch_maladaarAI : public ScriptedAI -{ - boss_exarch_maladaarAI(Creature *c) : ScriptedAI(c) - { - HasTaunted = false; - } - - uint32 soulmodel; - uint64 soulholder; - uint8 soulclass; - - uint32 Fear_timer; - uint32 Ribbon_of_Souls_timer; - uint32 StolenSoul_Timer; - - bool HasTaunted; - bool Avatar_summoned; - - void Reset() - { - soulmodel = 0; - soulholder = 0; - soulclass = 0; - - Fear_timer = 15000 + rand()% 5000; - Ribbon_of_Souls_timer = 5000; - StolenSoul_Timer = 25000 + rand()% 10000; - - Avatar_summoned = false; - } - - void MoveInLineOfSight(Unit *who) - { - if (!HasTaunted && me->IsWithinDistInMap(who, 150.0)) - { - DoScriptText(SAY_INTRO, me); - HasTaunted = true; - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == ENTRY_STOLEN_SOUL) - { - //SPELL_STOLEN_SOUL_VISUAL has shapeshift effect, but not implemented feature in Trinity for this spell. - summoned->CastSpell(summoned,SPELL_STOLEN_SOUL_VISUAL,false); - summoned->SetDisplayId(soulmodel); - summoned->setFaction(me->getFaction()); - - if (Unit *pTarget = Unit::GetUnit(*me,soulholder)) - { - - CAST_AI(mob_stolen_soulAI, summoned->AI())->SetMyClass(soulclass); - summoned->AI()->AttackStart(pTarget); - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - //When Exarch Maladar is defeated D'ore appear. - me->SummonCreature(19412, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!Avatar_summoned && ((me->GetHealth()*100) / me->GetMaxHealth() < 25)) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(SAY_SUMMON, me); - - DoCast(me, SPELL_SUMMON_AVATAR); - Avatar_summoned = true; - StolenSoul_Timer = 15000 + rand()% 15000; - } - - if (StolenSoul_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - uint32 i = urand(1,2); - if (i == 1) - DoScriptText(SAY_ROAR, me); - else - DoScriptText(SAY_SOUL_CLEAVE, me); - - soulmodel = pTarget->GetDisplayId(); - soulholder = pTarget->GetGUID(); - soulclass = pTarget->getClass(); - - DoCast(pTarget, SPELL_STOLEN_SOUL); - me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); - - StolenSoul_Timer = 20000 + rand()% 10000; - } else StolenSoul_Timer = 1000; - } - } else StolenSoul_Timer -= diff; - - if (Ribbon_of_Souls_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_RIBBON_OF_SOULS); - - Ribbon_of_Souls_timer = 5000 + (rand()%20 * 1000); - } else Ribbon_of_Souls_timer -= diff; - - if (Fear_timer <= diff) - { - DoCast(me, SPELL_SOUL_SCREAM); - Fear_timer = 15000 + rand()% 15000; - } else Fear_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_exarch_maladaar(Creature* pCreature) -{ - return new boss_exarch_maladaarAI (pCreature); -} - -#define SPELL_AV_MORTAL_STRIKE 16856 -#define SPELL_AV_SUNDER_ARMOR 16145 - -struct mob_avatar_of_martyredAI : public ScriptedAI -{ - mob_avatar_of_martyredAI(Creature *c) : ScriptedAI(c) {} - - uint32 Mortal_Strike_timer; - - void Reset() - { - Mortal_Strike_timer = 10000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Mortal_Strike_timer <= diff) - { - DoCast(me->getVictim(), SPELL_AV_MORTAL_STRIKE); - Mortal_Strike_timer = 10000 + rand()%20 * 1000; - } else Mortal_Strike_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_avatar_of_martyred(Creature* pCreature) -{ - return new mob_avatar_of_martyredAI (pCreature); -} - -void AddSC_boss_exarch_maladaar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_exarch_maladaar"; - newscript->GetAI = &GetAI_boss_exarch_maladaar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_avatar_of_martyred"; - newscript->GetAI = &GetAI_mob_avatar_of_martyred; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stolen_soul"; - newscript->GetAI = &GetAI_mob_stolen_soul; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp deleted file mode 100644 index c13e2905171..00000000000 --- a/src/server/scripts/Outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -Name: Boss_Shirrak_the_dead_watcher -%Complete: 80 -Comment: InhibitMagic should stack slower far from the boss, proper Visual for Focus Fire, heroic implemented -Category: Auchindoun, Auchenai Crypts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_INHIBITMAGIC 32264 -#define SPELL_ATTRACTMAGIC 32265 -#define N_SPELL_CARNIVOROUSBITE 36383 -#define H_SPELL_CARNIVOROUSBITE 39382 -#define SPELL_CARNIVOROUSBITE DUNGEON_MODE(N_SPELL_CARNIVOROUSBITE, H_SPELL_CARNIVOROUSBITE) - -#define ENTRY_FOCUS_FIRE 18374 - -#define N_SPELL_FIERY_BLAST 32302 -#define H_SPELL_FIERY_BLAST 38382 -#define SPELL_FIERY_BLAST DUNGEON_MODE(N_SPELL_FIERY_BLAST, H_SPELL_FIERY_BLAST) -#define SPELL_FOCUS_FIRE_VISUAL 42075 //need to find better visual - -#define EMOTE_FOCUSES_ON "focuses on " - -struct boss_shirrak_the_dead_watcherAI : public ScriptedAI -{ - boss_shirrak_the_dead_watcherAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Inhibitmagic_Timer; - uint32 Attractmagic_Timer; - uint32 Carnivorousbite_Timer; - uint32 FocusFire_Timer; - - uint64 FocusedTargetGUID; - - void Reset() - { - Inhibitmagic_Timer = 0; - Attractmagic_Timer = 28000; - Carnivorousbite_Timer = 10000; - FocusFire_Timer = 17000; - FocusedTargetGUID = 0; - } - - void EnterCombat(Unit * /*who*/) - { } - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == ENTRY_FOCUS_FIRE) - { - summoned->CastSpell(summoned,SPELL_FOCUS_FIRE_VISUAL,false); - summoned->setFaction(me->getFaction()); - summoned->SetLevel(me->getLevel()); - summoned->addUnitState(UNIT_STAT_ROOT); - - if (Unit *pFocusedTarget = Unit::GetUnit(*me, FocusedTargetGUID)) - summoned->AI()->AttackStart(pFocusedTarget); - } - } - - void UpdateAI(const uint32 diff) - { - //Inhibitmagic_Timer - if (Inhibitmagic_Timer <= diff) - { - float dist; - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* i_pl = i->getSource()) - if (i_pl->isAlive() && (dist = i_pl->IsWithinDist(me, 45))) - { - i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC); - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 35) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 25) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 15) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - } - Inhibitmagic_Timer = 3000+(rand()%1000); - } else Inhibitmagic_Timer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Attractmagic_Timer - if (Attractmagic_Timer <= diff) - { - DoCast(me, SPELL_ATTRACTMAGIC); - Attractmagic_Timer = 30000; - Carnivorousbite_Timer = 1500; - } else Attractmagic_Timer -= diff; - - //Carnivorousbite_Timer - if (Carnivorousbite_Timer <= diff) - { - DoCast(me, SPELL_CARNIVOROUSBITE); - Carnivorousbite_Timer = 10000; - } else Carnivorousbite_Timer -= diff; - - //FocusFire_Timer - if (FocusFire_Timer <= diff) - { - // Summon Focus Fire & Emote - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) - { - FocusedTargetGUID = pTarget->GetGUID(); - me->SummonCreature(ENTRY_FOCUS_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,5500); - - // TODO: Find better way to handle emote - // Emote - std::string *emote = new std::string(EMOTE_FOCUSES_ON); - emote->append(pTarget->GetName()); - emote->append("!"); - const char* text = emote->c_str(); - me->MonsterTextEmote(text, 0, true); - delete emote; - } - FocusFire_Timer = 15000+(rand()%5000); - } else FocusFire_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_shirrak_the_dead_watcher(Creature* pCreature) -{ - return new boss_shirrak_the_dead_watcherAI (pCreature); -} - -struct mob_focus_fireAI : public ScriptedAI -{ - mob_focus_fireAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 FieryBlast_Timer; - bool fiery1, fiery2; - - void Reset() - { - FieryBlast_Timer = 3000+(rand()%1000); - fiery1 = fiery2 = true; - } - - void EnterCombat(Unit * /*who*/) - { } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FieryBlast_Timer - if (fiery2 && FieryBlast_Timer <= diff) - { - DoCast(me, SPELL_FIERY_BLAST); - - if (fiery1) fiery1 = false; - else if (fiery2) fiery2 = false; - - FieryBlast_Timer = 1000; - } else FieryBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_focus_fire(Creature* pCreature) -{ - return new mob_focus_fireAI (pCreature); -} - -void AddSC_boss_shirrak_the_dead_watcher() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shirrak_the_dead_watcher"; - newscript->GetAI = &GetAI_boss_shirrak_the_dead_watcher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_focus_fire"; - newscript->GetAI = &GetAI_mob_focus_fire; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp b/src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp deleted file mode 100644 index 5b15178c33e..00000000000 --- a/src/server/scripts/Outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_NexusPrince_Shaffar -SD%Complete: 80 -SDComment: Need more tuning of spell timers, it should not be as linear fight as current. Also should possibly find a better way to deal with his three initial beacons to make sure all aggro. -SDCategory: Auchindoun, Mana Tombs -EndScriptData */ - -/* ContentData -boss_nexusprince_shaffar -mob_ethereal_beacon -EndContentData */ - -#include "ScriptedPch.h" - -enum ePrince -{ - SAY_INTRO = -1557000, - SAY_AGGRO_1 = -1557001, - SAY_AGGRO_2 = -1557002, - SAY_AGGRO_3 = -1557003, - SAY_SLAY_1 = -1557004, - SAY_SLAY_2 = -1557005, - SAY_SUMMON = -1557006, - SAY_DEAD = -1557007, - - SPELL_BLINK = 34605, - SPELL_FROSTBOLT = 32364, - SPELL_FIREBALL = 32363, - SPELL_FROSTNOVA = 32365, - - SPELL_ETHEREAL_BEACON = 32371, // Summons NPC_BEACON - SPELL_ETHEREAL_BEACON_VISUAL = 32368, - - NPC_BEACON = 18431, - NPC_SHAFFAR = 18344, - - NR_INITIAL_BEACONS = 3 -}; - -struct boss_nexusprince_shaffarAI : public ScriptedAI -{ - boss_nexusprince_shaffarAI(Creature *c) : ScriptedAI(c), summons(me) { HasTaunted = false; } - - uint32 Blink_Timer; - uint32 Beacon_Timer; - uint32 FireBall_Timer; - uint32 Frostbolt_Timer; - uint32 FrostNova_Timer; - - SummonList summons; - - bool HasTaunted; - bool CanBlink; - - void Reset() - { - Blink_Timer = 1500; - Beacon_Timer = 10000; - FireBall_Timer = 8000; - Frostbolt_Timer = 4000; - FrostNova_Timer = 15000; - - CanBlink = false; - - float dist = 8.0f; - float posX, posY, posZ, angle; - me->GetHomePosition(posX, posY, posZ, angle); - - me->SummonCreature(NPC_BEACON, posX - dist, posY - dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - me->SummonCreature(NPC_BEACON, posX - dist, posY + dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - me->SummonCreature(NPC_BEACON, posX + dist, posY, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - } - - void EnterEvadeMode() - { - summons.DespawnAll(); - ScriptedAI::EnterEvadeMode(); - } - - void MoveInLineOfSight(Unit *who) - { - if (!HasTaunted && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 100.0f)) - { - DoScriptText(SAY_INTRO, me); - HasTaunted = true; - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - DoZoneInCombat(); - summons.DoZoneInCombat(); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == NPC_BEACON) - { - summoned->CastSpell(summoned,SPELL_ETHEREAL_BEACON_VISUAL,false); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(pTarget); - } - - summons.Summon(summoned); - } - - void SummonedCreatureDespawn(Creature *summon) - { - summons.Despawn(summon); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEAD, me); - summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (FrostNova_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoCast(me, SPELL_FROSTNOVA); - FrostNova_Timer = 17500 + rand()%7500; - CanBlink = true; - } else FrostNova_Timer -= diff; - - if (Frostbolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - Frostbolt_Timer = 4500 + rand()%1500; - } else Frostbolt_Timer -= diff; - - if (FireBall_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL); - FireBall_Timer = 4500 + rand()%1500; - } else FireBall_Timer -= diff; - - if (CanBlink) - { - if (Blink_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - //expire movement, will prevent from running right back to victim after cast - //(but should MoveChase be used again at a certain time or should he not move?) - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - - DoCast(me, SPELL_BLINK); - Blink_Timer = 1000 + rand()%1500; - CanBlink = false; - } else Blink_Timer -= diff; - } - - if (Beacon_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - if (!urand(0,3)) - DoScriptText(SAY_SUMMON, me); - - DoCast(me, SPELL_ETHEREAL_BEACON, true); - - Beacon_Timer = 10000; - } else Beacon_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_nexusprince_shaffar(Creature* pCreature) -{ - return new boss_nexusprince_shaffarAI (pCreature); -} - -enum eEnums -{ - SPELL_ARCANE_BOLT = 15254, - SPELL_ETHEREAL_APPRENTICE = 32372 // Summon 18430 -}; - -struct mob_ethereal_beaconAI : public ScriptedAI -{ - mob_ethereal_beaconAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Apprentice_Timer; - uint32 ArcaneBolt_Timer; - uint32 Check_Timer; - - void KillSelf() - { - me->Kill(me); - } - - void Reset() - { - Apprentice_Timer = DUNGEON_MODE(20000, 10000); - ArcaneBolt_Timer = 1000; - Check_Timer = 1000; - } - - void EnterCombat(Unit * who) - { - // Send Shaffar to fight - Creature* Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); - if (!Shaffar || Shaffar->isDead()) - { - KillSelf(); - return; - } - if (!Shaffar->isInCombat()) - Shaffar->AI()->AttackStart(who); - } - - void JustSummoned(Creature *summoned) - { - summoned->AI()->AttackStart(me->getVictim()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Check_Timer <= diff) - { - Creature *Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); - if (!Shaffar || Shaffar->isDead() || !Shaffar->isInCombat()) - { - KillSelf(); - return; - } - Check_Timer = 1000; - } else Check_Timer -= diff; - - if (ArcaneBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BOLT); - ArcaneBolt_Timer = 2000 + rand()%2500; - } else ArcaneBolt_Timer -= diff; - - if (Apprentice_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoCast(me, SPELL_ETHEREAL_APPRENTICE, true); - me->ForcedDespawn(); - return; - } else Apprentice_Timer -= diff; - } -}; - -CreatureAI* GetAI_mob_ethereal_beacon(Creature* pCreature) -{ - return new mob_ethereal_beaconAI (pCreature); -} - -enum eEthereal -{ - SPELL_ETHEREAL_APPRENTICE_FIREBOLT = 32369, - SPELL_ETHEREAL_APPRENTICE_FROSTBOLT = 32370 -}; - -struct mob_ethereal_apprenticeAI : public ScriptedAI -{ - mob_ethereal_apprenticeAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cast_Timer; - - bool isFireboltTurn; - - void Reset() - { - Cast_Timer = 3000; - isFireboltTurn = true; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Cast_Timer <= diff) - { - if (isFireboltTurn) - { - DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FIREBOLT, true); - isFireboltTurn = false; - }else{ - DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FROSTBOLT, true); - isFireboltTurn = true; - } - Cast_Timer = 3000; - } else Cast_Timer -= diff; - } -}; - -CreatureAI* GetAI_mob_ethereal_apprentice(Creature* pCreature) -{ - return new mob_ethereal_apprenticeAI (pCreature); -} - -void AddSC_boss_nexusprince_shaffar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_nexusprince_shaffar"; - newscript->GetAI = &GetAI_boss_nexusprince_shaffar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ethereal_beacon"; - newscript->GetAI = &GetAI_mob_ethereal_beacon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ethereal_apprentice"; - newscript->GetAI = &GetAI_mob_ethereal_apprentice; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp b/src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp deleted file mode 100644 index 51ec2e83b46..00000000000 --- a/src/server/scripts/Outland/auchindoun/mana_tombs/boss_pandemonius.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Pandemonius -SD%Complete: 75 -SDComment: Not known how void blast is done (amount of rapid cast seems to be related to players in party). All mobs remaining in surrounding area should aggro when engaged. -SDCategory: Auchindoun, Mana Tombs -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1557008 -#define SAY_AGGRO_2 -1557009 -#define SAY_AGGRO_3 -1557010 - -#define SAY_KILL_1 -1557011 -#define SAY_KILL_2 -1557012 - -#define SAY_DEATH -1557013 - -#define EMOTE_DARK_SHELL -1557014 - -#define SPELL_VOID_BLAST 32325 -#define H_SPELL_VOID_BLAST 38760 -#define SPELL_DARK_SHELL 32358 -#define H_SPELL_DARK_SHELL 38759 - -struct boss_pandemoniusAI : public ScriptedAI -{ - boss_pandemoniusAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 VoidBlast_Timer; - uint32 DarkShell_Timer; - uint32 VoidBlast_Counter; - - void Reset() - { - VoidBlast_Timer = 8000+rand()%15000; - DarkShell_Timer = 20000; - VoidBlast_Counter = 0; - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (VoidBlast_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_VOID_BLAST); - VoidBlast_Timer = 500; - ++VoidBlast_Counter; - } - - if (VoidBlast_Counter == 5) - { - VoidBlast_Timer = 15000+rand()%10000; - VoidBlast_Counter = 0; - } - } else VoidBlast_Timer -= diff; - - if (!VoidBlast_Counter) - { - if (DarkShell_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(EMOTE_DARK_SHELL, me); - - DoCast(me, SPELL_DARK_SHELL); - DarkShell_Timer = 20000; - } else DarkShell_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_pandemonius(Creature* pCreature) -{ - return new boss_pandemoniusAI (pCreature); -} - -void AddSC_boss_pandemonius() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_pandemonius"; - newscript->GetAI = &GetAI_boss_pandemonius; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp b/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp deleted file mode 100644 index 9628fa1a98f..00000000000 --- a/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Darkweaver_Syth -SD%Complete: 85 -SDComment: Shock spells/times need more work. Heroic partly implemented. -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_SUMMON -1556000 - -#define SAY_AGGRO_1 -1556001 -#define SAY_AGGRO_2 -1556002 -#define SAY_AGGRO_3 -1556003 - -#define SAY_SLAY_1 -1556004 -#define SAY_SLAY_2 -1556005 - -#define SAY_DEATH -1556006 - -#define SPELL_FROST_SHOCK 21401 //37865 -#define SPELL_FLAME_SHOCK 34354 -#define SPELL_SHADOW_SHOCK 30138 -#define SPELL_ARCANE_SHOCK 37132 - -#define SPELL_CHAIN_LIGHTNING 15659 //15305 - -#define SPELL_SUMMON_SYTH_FIRE 33537 // Spawns 19203 -#define SPELL_SUMMON_SYTH_ARCANE 33538 // Spawns 19205 -#define SPELL_SUMMON_SYTH_FROST 33539 // Spawns 19204 -#define SPELL_SUMMON_SYTH_SHADOW 33540 // Spawns 19206 - -#define SPELL_FLAME_BUFFET DUNGEON_MODE(33526, 38141) -#define SPELL_ARCANE_BUFFET DUNGEON_MODE(33527, 38138) -#define SPELL_FROST_BUFFET DUNGEON_MODE(33528, 38142) -#define SPELL_SHADOW_BUFFET DUNGEON_MODE(33529, 38143) - -struct boss_darkweaver_sythAI : public ScriptedAI -{ - boss_darkweaver_sythAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 flameshock_timer; - uint32 arcaneshock_timer; - uint32 frostshock_timer; - uint32 shadowshock_timer; - uint32 chainlightning_timer; - - bool summon90; - bool summon50; - bool summon10; - - void Reset() - { - flameshock_timer = 2000; - arcaneshock_timer = 4000; - frostshock_timer = 6000; - shadowshock_timer = 8000; - chainlightning_timer = 15000; - - summon90 = false; - summon50 = false; - summon10 = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustSummoned(Creature *summoned) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(pTarget); - } - - void SythSummoning() - { - DoScriptText(SAY_SUMMON, me); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me, SPELL_SUMMON_SYTH_ARCANE, true); //front - DoCast(me, SPELL_SUMMON_SYTH_FIRE, true); //back - DoCast(me, SPELL_SUMMON_SYTH_FROST, true); //left - DoCast(me, SPELL_SUMMON_SYTH_SHADOW, true); //right - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 90) && !summon90) - { - SythSummoning(); - summon90 = true; - } - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 50) && !summon50) - { - SythSummoning(); - summon50 = true; - } - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 10) && !summon10) - { - SythSummoning(); - summon10 = true; - } - - if (flameshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_SHOCK); - - flameshock_timer = 10000 + rand()%5000; - } else flameshock_timer -= diff; - - if (arcaneshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_SHOCK); - - arcaneshock_timer = 10000 + rand()%5000; - } else arcaneshock_timer -= diff; - - if (frostshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_SHOCK); - - frostshock_timer = 10000 + rand()%5000; - } else frostshock_timer -= diff; - - if (shadowshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_SHOCK); - - shadowshock_timer = 10000 + rand()%5000; - } else shadowshock_timer -= diff; - - if (chainlightning_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - - chainlightning_timer = 25000; - } else chainlightning_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_darkweaver_syth(Creature* pCreature) -{ - return new boss_darkweaver_sythAI (pCreature); -} - -/* ELEMENTALS */ - -struct mob_syth_fireAI : public ScriptedAI -{ - mob_syth_fireAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 flameshock_timer; - uint32 flamebuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - flameshock_timer = 2500; - flamebuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (flameshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_SHOCK); - - flameshock_timer = 5000; - } else flameshock_timer -= diff; - - if (flamebuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_BUFFET); - - flamebuffet_timer = 5000; - } else flamebuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_fire(Creature* pCreature) -{ - return new mob_syth_fireAI (pCreature); -} - -struct mob_syth_arcaneAI : public ScriptedAI -{ - mob_syth_arcaneAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 arcaneshock_timer; - uint32 arcanebuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); - arcaneshock_timer = 2500; - arcanebuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (arcaneshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_SHOCK); - - arcaneshock_timer = 5000; - } else arcaneshock_timer -= diff; - - if (arcanebuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_BUFFET); - - arcanebuffet_timer = 5000; - } else arcanebuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_arcane(Creature* pCreature) -{ - return new mob_syth_arcaneAI (pCreature); -} - -struct mob_syth_frostAI : public ScriptedAI -{ - mob_syth_frostAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 frostshock_timer; - uint32 frostbuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - frostshock_timer = 2500; - frostbuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (frostshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_SHOCK); - - frostshock_timer = 5000; - } else frostshock_timer -= diff; - - if (frostbuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_BUFFET); - - frostbuffet_timer = 5000; - } else frostbuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_frost(Creature* pCreature) -{ - return new mob_syth_frostAI (pCreature); -} - -struct mob_syth_shadowAI : public ScriptedAI -{ - mob_syth_shadowAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 shadowshock_timer; - uint32 shadowbuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); - shadowshock_timer = 2500; - shadowbuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (shadowshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_SHOCK); - - shadowshock_timer = 5000; - } else shadowshock_timer -= diff; - - if (shadowbuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_BUFFET); - - shadowbuffet_timer = 5000; - } else shadowbuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_shadow(Creature* pCreature) -{ - return new mob_syth_shadowAI (pCreature); -} - -void AddSC_boss_darkweaver_syth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_darkweaver_syth"; - newscript->GetAI = &GetAI_boss_darkweaver_syth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_fire"; - newscript->GetAI = &GetAI_mob_syth_arcane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_arcane"; - newscript->GetAI = &GetAI_mob_syth_arcane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_frost"; - newscript->GetAI = &GetAI_mob_syth_frost; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_shadow"; - newscript->GetAI = &GetAI_mob_syth_shadow; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp deleted file mode 100644 index 32b97293ca3..00000000000 --- a/src/server/scripts/Outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Talon_King_Ikiss -SD%Complete: 80 -SDComment: Heroic supported. Some details missing, but most are spell related. -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "sethekk_halls.h" - -#define SAY_INTRO -1556007 - -#define SAY_AGGRO_1 -1556008 -#define SAY_AGGRO_2 -1556009 -#define SAY_AGGRO_3 -1556010 - -#define SAY_SLAY_1 -1556011 -#define SAY_SLAY_2 -1556012 -#define SAY_DEATH -1556013 -#define EMOTE_ARCANE_EXP -1556015 - -#define SPELL_BLINK 38194 -#define SPELL_BLINK_TELEPORT 38203 -#define SPELL_MANA_SHIELD 38151 -#define SPELL_ARCANE_BUBBLE 9438 -#define H_SPELL_SLOW 35032 - -#define SPELL_POLYMORPH 38245 -#define H_SPELL_POLYMORPH 43309 - -#define SPELL_ARCANE_VOLLEY 35059 -#define H_SPELL_ARCANE_VOLLEY 40424 - -#define SPELL_ARCANE_EXPLOSION 38197 -#define H_SPELL_ARCANE_EXPLOSION 40425 - -struct boss_talon_king_ikissAI : public ScriptedAI -{ - boss_talon_king_ikissAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ArcaneVolley_Timer; - uint32 Sheep_Timer; - uint32 Blink_Timer; - uint32 Slow_Timer; - - bool ManaShield; - bool Blink; - bool Intro; - - void Reset() - { - ArcaneVolley_Timer = 5000; - Sheep_Timer = 8000; - Blink_Timer = 35000; - Slow_Timer = 15000+rand()%15000; - Blink = false; - Intro = false; - ManaShield = false; - } - - void MoveInLineOfSight(Unit *who) - { - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (!Intro && me->IsWithinDistInMap(who, 100)) - { - Intro = true; - DoScriptText(SAY_INTRO, me); - } - - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_IKISSDOOREVENT, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Blink) - { - DoCast(me, SPELL_ARCANE_EXPLOSION); - DoCast(me, SPELL_ARCANE_BUBBLE, true); - Blink = false; - } - - if (ArcaneVolley_Timer <= diff) - { - DoCast(me, SPELL_ARCANE_VOLLEY); - ArcaneVolley_Timer = 7000+rand()%5000; - } else ArcaneVolley_Timer -= diff; - - if (Sheep_Timer <= diff) - { - Unit *pTarget; - - //second top aggro target in normal, random target in heroic correct? - if (IsHeroic()) - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - else - pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); - - if (pTarget) - DoCast(pTarget, SPELL_POLYMORPH); - Sheep_Timer = 15000+rand()%2500; - } else Sheep_Timer -= diff; - - //may not be correct time to cast - if (!ManaShield && ((me->GetHealth()*100) / me->GetMaxHealth() < 20)) - { - DoCast(me, SPELL_MANA_SHIELD); - ManaShield = true; - } - - if (IsHeroic()) - { - if (Slow_Timer <= diff) - { - DoCast(me, H_SPELL_SLOW); - Slow_Timer = 15000+rand()%25000; - } else Slow_Timer -= diff; - } - - if (Blink_Timer <= diff) - { - DoScriptText(EMOTE_ARCANE_EXP, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - //Spell doesn't work, but we use for visual effect at least - DoCast(pTarget, SPELL_BLINK); - - float X = pTarget->GetPositionX(); - float Y = pTarget->GetPositionY(); - float Z = pTarget->GetPositionZ(); - - DoTeleportTo(X,Y,Z); - - DoCast(pTarget, SPELL_BLINK_TELEPORT); - Blink = true; - } - Blink_Timer = 35000+rand()%5000; - } else Blink_Timer -= diff; - - if (!Blink) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_talon_king_ikiss(Creature* pCreature) -{ - return new boss_talon_king_ikissAI (pCreature); -} - -void AddSC_boss_talon_king_ikiss() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_talon_king_ikiss"; - newscript->GetAI = &GetAI_boss_talon_king_ikiss; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp b/src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp deleted file mode 100644 index ee27da3cff5..00000000000 --- a/src/server/scripts/Outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance - Sethekk Halls -SD%Complete: 50 -SDComment: Instance Data for Sethekk Halls instance -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "sethekk_halls.h" - -enum eEnums -{ - NPC_ANZU = 23035, - IKISS_DOOR = 177203, -}; - -struct instance_sethekk_halls : public ScriptedInstance -{ - instance_sethekk_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 AnzuEncounter; - uint64 m_uiIkissDoorGUID; - - void Initialize() - { - AnzuEncounter = NOT_STARTED; - m_uiIkissDoorGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == NPC_ANZU) - { - if (AnzuEncounter >= IN_PROGRESS) - pCreature->DisappearAndDie(); - else - AnzuEncounter = IN_PROGRESS; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - if (pGo->GetEntry() == IKISS_DOOR) - m_uiIkissDoorGUID = pGo->GetGUID(); - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_IKISSDOOREVENT: - if (data == DONE) - DoUseDoorOrButton(m_uiIkissDoorGUID,DAY*IN_MILISECONDS); - break; - case TYPE_ANZU_ENCOUNTER: - AnzuEncounter = data; - break; - } - } -}; - -InstanceData* GetInstanceData_instance_sethekk_halls(Map* pMap) -{ - return new instance_sethekk_halls(pMap); -} - -void AddSC_instance_sethekk_halls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_sethekk_halls"; - newscript->GetInstanceData = &GetInstanceData_instance_sethekk_halls; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h b/src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h deleted file mode 100644 index 79a6cd4952d..00000000000 --- a/src/server/scripts/Outland/auchindoun/sethekk_halls/sethekk_halls.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SETHEKK_HALLS_H -#define DEF_SETHEKK_HALLS_H - -enum eTypes -{ - DATA_IKISSDOOREVENT = 1, - TYPE_ANZU_ENCOUNTER = 2, -}; -#endif - diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp deleted file mode 100644 index 2bb6a717a5a..00000000000 --- a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ambassador_Hellmaw -SD%Complete: 80 -SDComment: Enrage spell missing/not known -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "shadow_labyrinth.h" - -enum eEnums -{ - SAY_INTRO = -1555000, - SAY_AGGRO1 = -1555001, - SAY_AGGRO2 = -1555002, - SAY_AGGRO3 = -1555003, - SAY_HELP = -1555004, - SAY_SLAY1 = -1555005, - SAY_SLAY2 = -1555006, - SAY_DEATH = -1555007, - - SPELL_BANISH = 30231, - SPELL_CORROSIVE_ACID = 33551, - SPELL_FEAR = 33547, - SPELL_ENRAGE = 34970 -}; - -struct boss_ambassador_hellmawAI : public npc_escortAI -{ - boss_ambassador_hellmawAI(Creature* pCreature) : npc_escortAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 EventCheck_Timer; - uint32 CorrosiveAcid_Timer; - uint32 Fear_Timer; - uint32 Enrage_Timer; - bool Intro; - bool IsBanished; - bool Enraged; - - void Reset() - { - EventCheck_Timer = 5000; - CorrosiveAcid_Timer = 5000 + rand()%5000; - Fear_Timer = 25000 + rand()%5000; - Enrage_Timer = 180000; - Intro = false; - IsBanished = true; - Enraged = false; - - if (m_pInstance && me->isAlive()) - { - if (m_pInstance->GetData(TYPE_OVERSEER) != DONE) - DoCast(me, SPELL_BANISH, true); - } - } - - void JustReachedHome() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_HELLMAW, FAIL); - } - - void MoveInLineOfSight(Unit* pWho) - { - if (me->HasAura(SPELL_BANISH)) - return; - - npc_escortAI::MoveInLineOfSight(pWho); - } - - void WaypointReached(uint32 /*i*/) - { - } - - void DoIntro() - { - if (me->HasAura(SPELL_BANISH)) - me->RemoveAurasDueToSpell(SPELL_BANISH); - - IsBanished = false; - Intro = true; - - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_HELLMAW) != FAIL) - { - DoScriptText(SAY_INTRO, me); - Start(true, false, 0, NULL, false, true); - } - - m_pInstance->SetData(TYPE_HELLMAW, IN_PROGRESS); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_HELLMAW, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!Intro && !HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (EventCheck_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_OVERSEER) == DONE) - { - DoIntro(); - return; - } - } - EventCheck_Timer = 5000; - return; - } - else - { - EventCheck_Timer -= diff; - return; - } - } - - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->HasAura(SPELL_BANISH, 0)) - { - EnterEvadeMode(); - return; - } - - if (CorrosiveAcid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVE_ACID); - CorrosiveAcid_Timer = 15000 + rand()%10000; - } else CorrosiveAcid_Timer -= diff; - - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 20000 + rand()%15000; - } else Fear_Timer -= diff; - - if (IsHeroic()) - { - if (!Enraged && Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else Enrage_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_boss_ambassador_hellmaw(Creature* pCreature) -{ - return new boss_ambassador_hellmawAI(pCreature); -} - -void AddSC_boss_ambassador_hellmaw() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ambassador_hellmaw"; - newscript->GetAI = &GetAI_boss_ambassador_hellmaw; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp deleted file mode 100644 index 52c60ae0d0e..00000000000 --- a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Blackheart_the_Inciter -SD%Complete: 75 -SDComment: Incite Chaos not functional since core lacks Mind Control support -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define SPELL_INCITE_CHAOS 33676 -#define SPELL_INCITE_CHAOS_B 33684 //debuff applied to each member of party -#define SPELL_CHARGE 33709 -#define SPELL_WAR_STOMP 33707 - -#define SAY_INTRO1 -1555008 //not used -#define SAY_INTRO2 -1555009 //not used -#define SAY_INTRO3 -1555010 //not used -#define SAY_AGGRO1 -1555011 -#define SAY_AGGRO2 -1555012 -#define SAY_AGGRO3 -1555013 -#define SAY_SLAY1 -1555014 -#define SAY_SLAY2 -1555015 -#define SAY_HELP -1555016 //not used -#define SAY_DEATH -1555017 - -//below, not used -#define SAY2_INTRO1 -1555018 -#define SAY2_INTRO2 -1555019 -#define SAY2_INTRO3 -1555020 -#define SAY2_AGGRO1 -1555021 -#define SAY2_AGGRO2 -1555022 -#define SAY2_AGGRO3 -1555023 -#define SAY2_SLAY1 -1555024 -#define SAY2_SLAY2 -1555025 -#define SAY2_HELP -1555026 -#define SAY2_DEATH -1555027 - -struct boss_blackheart_the_inciterAI : public ScriptedAI -{ - boss_blackheart_the_inciterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - bool InciteChaos; - uint32 InciteChaos_Timer; - uint32 InciteChaosWait_Timer; - uint32 Charge_Timer; - uint32 Knockback_Timer; - - void Reset() - { - InciteChaos = false; - InciteChaos_Timer = 20000; - InciteChaosWait_Timer = 15000; - Charge_Timer = 5000; - Knockback_Timer = 15000; - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (InciteChaos) - { - if (InciteChaosWait_Timer <= diff) - { - InciteChaos = false; - InciteChaosWait_Timer = 15000; - } else InciteChaosWait_Timer -= diff; - - return; - } - - if (InciteChaos_Timer <= diff) - { - DoCast(me, SPELL_INCITE_CHAOS); - - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - pTarget->CastSpell(pTarget,SPELL_INCITE_CHAOS_B,true); - } - - DoResetThreat(); - InciteChaos = true; - InciteChaos_Timer = 40000; - return; - } else InciteChaos_Timer -= diff; - - //Charge_Timer - if (Charge_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CHARGE); - Charge_Timer = 15000 + rand()%10000; - } else Charge_Timer -= diff; - - //Knockback_Timer - if (Knockback_Timer <= diff) - { - DoCast(me, SPELL_WAR_STOMP); - Knockback_Timer = 18000 + rand()%6000; - } else Knockback_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_blackheart_the_inciter(Creature* pCreature) -{ - return new boss_blackheart_the_inciterAI (pCreature); -} - -void AddSC_boss_blackheart_the_inciter() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_blackheart_the_inciter"; - newscript->GetAI = &GetAI_boss_blackheart_the_inciter; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp deleted file mode 100644 index 8b63b765b47..00000000000 --- a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grandmaster_Vorpil -SD%Complete: 100 -SDComment: -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define SAY_INTRO -1555028 -#define SAY_AGGRO1 -1555029 -#define SAY_AGGRO2 -1555030 -#define SAY_AGGRO3 -1555031 -#define SAY_HELP -1555032 -#define SAY_SLAY1 -1555033 -#define SAY_SLAY2 -1555034 -#define SAY_DEATH -1555035 - -#define SPELL_RAIN_OF_FIRE 33617 -#define H_SPELL_RAIN_OF_FIRE 39363 - -#define SPELL_DRAW_SHADOWS 33563 -#define SPELL_SHADOWBOLT_VOLLEY 33841 -#define SPELL_BANISH 38791 - -#define MOB_VOID_TRAVELER 19226 -#define SPELL_SACRIFICE 33587 -#define SPELL_SHADOW_NOVA 33846 -#define SPELL_EMPOWERING_SHADOWS 33783 -#define H_SPELL_EMPOWERING_SHADOWS 39364 - -#define MOB_VOID_PORTAL 19224 -#define SPELL_VOID_PORTAL_VISUAL 33569 - -float VorpilPosition[3] = {-252.8820,-264.3030,17.1}; - -float VoidPortalCoords[5][3] = -{ - {-283.5894, -239.5718, 12.7}, - {-306.5853, -258.4539, 12.7}, - {-295.8789, -269.0899, 12.7}, - {-209.3401, -262.7564, 17.1}, - {-261.4533, -297.3298, 17.1} -}; - -struct mob_voidtravelerAI : public ScriptedAI -{ - mob_voidtravelerAI(Creature *c) : ScriptedAI(c) - { - } - - uint64 VorpilGUID; - uint32 move; - bool sacrificed; - - void Reset() - { - VorpilGUID = 0; - move = 0; - sacrificed = false; - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (!VorpilGUID) - { - me->Kill(me); - return; - } - if (move <= diff) - { - Creature *Vorpil = Unit::GetCreature(*me, VorpilGUID); - if (!Vorpil) - { - VorpilGUID = 0; - return; - } - - if (sacrificed) - { - me->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), Vorpil); - Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth()/25); - DoCast(me, SPELL_SHADOW_NOVA, true); - me->Kill(me); - return; - } - me->GetMotionMaster()->MoveFollow(Vorpil,0,0); - if (me->IsWithinDist(Vorpil, 3)) - { - DoCast(me, SPELL_SACRIFICE, false); - sacrificed = true; - move = 500; - return; - } - if (!Vorpil->isInCombat() || Vorpil->isDead()) - { - me->Kill(me); - return; - } - move = 1000; - } else move -= diff; - } -}; -CreatureAI* GetAI_mob_voidtraveler(Creature* pCreature) -{ - return new mob_voidtravelerAI (pCreature); -} - -struct boss_grandmaster_vorpilAI : public ScriptedAI -{ - boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = false; - } - - ScriptedInstance *pInstance; - bool Intro, HelpYell; - bool sumportals; - - uint32 ShadowBoltVolley_Timer; - uint32 DrawShadows_Timer; - uint32 summonTraveler_Timer; - uint32 banish_Timer; - uint64 PortalsGuid[5]; - - void Reset() - { - ShadowBoltVolley_Timer = 7000 + rand()%7000; - DrawShadows_Timer = 45000; - summonTraveler_Timer = 90000; - banish_Timer = 17000; - HelpYell = false; - destroyPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED); - } - - void summonPortals() - { - if (!sumportals) - { - for (uint8 i = 0; i < 5; ++i) - { - Creature *Portal = NULL; - Portal = me->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000); - if (Portal) - { - PortalsGuid[i] = Portal->GetGUID(); - Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false); - } - } - sumportals = true; - summonTraveler_Timer = 5000; - } - } - - void destroyPortals() - { - if (sumportals) - { - for (uint8 i = 0; i < 5; ++i) - { - Unit *Portal = Unit::GetUnit((*me), PortalsGuid[i]); - if (Portal && Portal->isAlive()) - Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - PortalsGuid[i] = 0; - } - sumportals = false; - } - } - - void spawnVoidTraveler() - { - int pos = urand(0,4); - me->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,5000); - if (!HelpYell) - { - DoScriptText(SAY_HELP, me); - HelpYell = true; - } - } - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == MOB_VOID_TRAVELER) - CAST_AI(mob_voidtravelerAI, summoned->AI())->VorpilGUID = me->GetGUID(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - destroyPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - summonPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS); - } - - void MoveInLineOfSight(Unit *who) - { - ScriptedAI::MoveInLineOfSight(who); - - if (!Intro && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 100) && me->IsHostileTo(who)) - { - DoScriptText(SAY_INTRO, me); - Intro = true; - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOWBOLT_VOLLEY); - ShadowBoltVolley_Timer = 15000 + rand()%15000; - } else ShadowBoltVolley_Timer -= diff; - - if (IsHeroic() && banish_Timer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,false); - if (pTarget) - { - DoCast(pTarget, SPELL_BANISH); - banish_Timer = 16000; - } - } else banish_Timer -= diff; - - if (DrawShadows_Timer <= diff) - { - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* i_pl = i->getSource()) - if (i_pl->isAlive() && !i_pl->HasAura(SPELL_BANISH)) - i_pl->TeleportTo(me->GetMapId(), VorpilPosition[0],VorpilPosition[1],VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT); - - me->GetMap()->CreatureRelocation(me, VorpilPosition[0],VorpilPosition[1],VorpilPosition[2],0.0f); - DoCast(me, SPELL_DRAW_SHADOWS, true); - - DoCast(me, SPELL_RAIN_OF_FIRE); - - ShadowBoltVolley_Timer = 6000; - DrawShadows_Timer = 30000; - } else DrawShadows_Timer -= diff; - - if (summonTraveler_Timer <= diff) - { - spawnVoidTraveler(); - summonTraveler_Timer = 10000; - //enrage at 20% - if ((me->GetHealth()*5) < me->GetMaxHealth()) - summonTraveler_Timer = 5000; - } else summonTraveler_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_grandmaster_vorpil(Creature* pCreature) -{ - return new boss_grandmaster_vorpilAI (pCreature); -} - -void AddSC_boss_grandmaster_vorpil() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grandmaster_vorpil"; - newscript->GetAI = &GetAI_boss_grandmaster_vorpil; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_voidtraveler"; - newscript->GetAI = &GetAI_mob_voidtraveler; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp deleted file mode 100644 index 14bf249c3b5..00000000000 --- a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/boss_murmur.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Murmur -SD%Complete: 90 -SDComment: Timers may be incorrect -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define EMOTE_SONIC_BOOM -1555036 - -#define SPELL_SONIC_BOOM_CAST DUNGEON_MODE(33923, 38796) -#define SPELL_SONIC_BOOM_EFFECT DUNGEON_MODE(33666, 38795) -#define SPELL_RESONANCE 33657 -#define SPELL_MURMURS_TOUCH DUNGEON_MODE(33711, 38794) -#define SPELL_MAGNETIC_PULL 33689 -#define SPELL_SONIC_SHOCK 38797 -#define SPELL_THUNDERING_STORM 39365 - -struct boss_murmurAI : public ScriptedAI -{ - boss_murmurAI(Creature *c) : ScriptedAI(c) - { - SetCombatMovement(false); - } - - uint32 SonicBoom_Timer; - uint32 MurmursTouch_Timer; - uint32 Resonance_Timer; - uint32 MagneticPull_Timer; - uint32 SonicShock_Timer; - uint32 ThunderingStorm_Timer; - bool SonicBoom; - - void Reset() - { - SonicBoom_Timer = 30000; - MurmursTouch_Timer = 8000 + rand()%12000; - Resonance_Timer = 5000; - MagneticPull_Timer = 15000 + rand()%15000; - ThunderingStorm_Timer = 15000; - SonicShock_Timer = 10000; - SonicBoom = false; - - //database should have `RegenHealth`=0 to prevent regen - uint32 hp = (me->GetMaxHealth()*40)/100; - if (hp) me->SetHealth(hp); - me->ResetPlayerDamageReq(); - } - - void SonicBoomEffect() - { - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - //Not do anything without aura, spell can be resisted! - if (pTarget->HasAura(SPELL_SONIC_BOOM_CAST) && me->IsWithinDistInMap(pTarget, 34.0f)) - { - //This will be wrong calculation. Also, comments suggest it must deal damage - pTarget->SetHealth(uint32(pTarget->GetMaxHealth() - pTarget->GetMaxHealth() * 0.8)); - } - } - } - } - - void EnterCombat(Unit * /*who*/) { } - - // Sonic Boom instant damage (needs core fix instead of this) - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (pTarget && pTarget->isAlive() && spell && spell->Id == uint32(SPELL_SONIC_BOOM_EFFECT)) - me->DealDamage(pTarget,(pTarget->GetHealth()*90)/100,NULL,SPELL_DIRECT_DAMAGE,SPELL_SCHOOL_MASK_NATURE,spell); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target or casting - if (!UpdateVictim() || me->IsNonMeleeSpellCasted(false)) - return; - - // Sonic Boom - if (SonicBoom) - { - DoCast(me, SPELL_SONIC_BOOM_EFFECT, true); - SonicBoomEffect(); - - SonicBoom = false; - Resonance_Timer = 1500; - } - if (SonicBoom_Timer <= diff) - { - DoScriptText(EMOTE_SONIC_BOOM, me); - DoCast(me, SPELL_SONIC_BOOM_CAST); - SonicBoom_Timer = 30000; - SonicBoom = true; - return; - } else SonicBoom_Timer -= diff; - - // Murmur's Touch - if (MurmursTouch_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,80,true)) - DoCast(pTarget, SPELL_MURMURS_TOUCH); - MurmursTouch_Timer = 25000 + rand()%10000; - } else MurmursTouch_Timer -= diff; - - // Resonance - if (!SonicBoom && !(me->IsWithinMeleeRange(me->getVictim()))) - { - if (Resonance_Timer <= diff) - { - DoCast(me, SPELL_RESONANCE); - Resonance_Timer = 5000; - } else Resonance_Timer -= diff; - } - - // Magnetic Pull - if (MagneticPull_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - if (pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) - { - DoCast(pTarget, SPELL_MAGNETIC_PULL); - MagneticPull_Timer = 15000+rand()%15000; - return; - } - MagneticPull_Timer = 500; - } else MagneticPull_Timer -= diff; - - if (IsHeroic()) - { - // Thundering Storm - if (ThunderingStorm_Timer <= diff) - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) - if (pTarget->isAlive() && !me->IsWithinDist(pTarget, 35, false)) - DoCast(pTarget, SPELL_THUNDERING_STORM, true); - ThunderingStorm_Timer = 15000; - } else ThunderingStorm_Timer -= diff; - - // Sonic Shock - if (SonicShock_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,20,false)) - if (pTarget->isAlive()) - DoCast(pTarget, SPELL_SONIC_SHOCK); - SonicShock_Timer = 10000+rand()%10000; - } else SonicShock_Timer -= diff; - } - - // Select nearest most aggro target if top aggro too far - if (!me->isAttackReady()) - return; - if (!me->IsWithinMeleeRange(me->getVictim())) - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) - if (pTarget->isAlive() && me->IsWithinMeleeRange(pTarget)) - { - me->TauntApply(pTarget); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_murmur(Creature* pCreature) -{ - return new boss_murmurAI (pCreature); -} - -void AddSC_boss_murmur() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_murmur"; - newscript->GetAI = &GetAI_boss_murmur; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp deleted file mode 100644 index 78340e5e132..00000000000 --- a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Shadow_Labyrinth -SD%Complete: 85 -SDComment: Some cleanup left along with save -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define MAX_ENCOUNTER 5 - -#define REFECTORY_DOOR 183296 //door opened when blackheart the inciter dies -#define SCREAMING_HALL_DOOR 183295 //door opened when grandmaster vorpil dies - -/* Shadow Labyrinth encounters: -1 - Ambassador Hellmaw event -2 - Blackheart the Inciter event -3 - Grandmaster Vorpil event -4 - Murmur event -*/ - -struct instance_shadow_labyrinth : public ScriptedInstance -{ - instance_shadow_labyrinth(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 m_uiRefectoryDoorGUID; - uint64 m_uiScreamingHallDoorGUID; - - uint64 m_uiGrandmasterVorpil; - uint32 m_uiFelOverseerCount; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiRefectoryDoorGUID = 0; - m_uiScreamingHallDoorGUID = 0; - - m_uiGrandmasterVorpil = 0; - m_uiFelOverseerCount = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case REFECTORY_DOOR: - m_uiRefectoryDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case SCREAMING_HALL_DOOR: - m_uiScreamingHallDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 18732: - m_uiGrandmasterVorpil = pCreature->GetGUID(); - break; - case 18796: - if (pCreature->isAlive()) - { - ++m_uiFelOverseerCount; - debug_log("TSCR: Shadow Labyrinth: counting %u Fel Overseers.",m_uiFelOverseerCount); - } - break; - } - } - - void SetData(uint32 type, uint32 uiData) - { - switch(type) - { - case TYPE_HELLMAW: - m_auiEncounter[0] = uiData; - break; - - case TYPE_OVERSEER: - if (uiData != DONE) - { - error_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER did not expect other data than DONE"); - return; - } - if (m_uiFelOverseerCount) - { - --m_uiFelOverseerCount; - - if (m_uiFelOverseerCount) - debug_log("TSCR: Shadow Labyrinth: %u Fel Overseers left to kill.",m_uiFelOverseerCount); - else - { - m_auiEncounter[1] = DONE; - debug_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER == DONE"); - } - } - break; - - case DATA_BLACKHEARTTHEINCITEREVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiRefectoryDoorGUID); - m_auiEncounter[2] = uiData; - break; - - case DATA_GRANDMASTERVORPILEVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiScreamingHallDoorGUID); - m_auiEncounter[3] = uiData; - break; - - case DATA_MURMUREVENT: - m_auiEncounter[4] = uiData; - break; - } - - if (uiData == DONE) - { - if (type == TYPE_OVERSEER && m_uiFelOverseerCount != 0) - return; - - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_HELLMAW: return m_auiEncounter[0]; - case TYPE_OVERSEER: return m_auiEncounter[1]; - case DATA_GRANDMASTERVORPILEVENT: return m_auiEncounter[3]; - case DATA_MURMUREVENT: return m_auiEncounter[4]; - } - return false; - } - - uint64 GetData64(uint32 identifier) - { - if (identifier == DATA_GRANDMASTERVORPIL) - return m_uiGrandmasterVorpil; - - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_shadow_labyrinth(Map* pMap) -{ - return new instance_shadow_labyrinth(pMap); -} - -void AddSC_instance_shadow_labyrinth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_shadow_labyrinth"; - newscript->GetInstanceData = &GetInstanceData_instance_shadow_labyrinth; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h b/src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h deleted file mode 100644 index a78955368bf..00000000000 --- a/src/server/scripts/Outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SHADOW_LABYRINTH_H -#define DEF_SHADOW_LABYRINTH_H - -#define TYPE_HELLMAW 1 -#define TYPE_OVERSEER 2 -#define DATA_BLACKHEARTTHEINCITEREVENT 3 -#define DATA_GRANDMASTERVORPILEVENT 4 -#define DATA_MURMUREVENT 5 -#define DATA_GRANDMASTERVORPIL 6 -#endif - diff --git a/src/server/scripts/Outland/black_temple/black_temple.cpp b/src/server/scripts/Outland/black_temple/black_temple.cpp deleted file mode 100644 index c1e7f19fbb1..00000000000 --- a/src/server/scripts/Outland/black_temple/black_temple.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Black_Temple -SD%Complete: 95 -SDComment: Spirit of Olum: Player Teleporter to Seer Kanai Teleport after defeating Naj'entus and Supremus. TODO: Find proper gossip. -SDCategory: Black Temple -EndScriptData */ - -/* ContentData -npc_spirit_of_olum -EndContentData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -/*### -# npc_spirit_of_olum -####*/ - -#define SPELL_TELEPORT 41566 // s41566 - Teleport to Ashtongue NPC's -#define GOSSIP_OLUM1 "Teleport me to the other Ashtongue Deathsworn" - -bool GossipHello_npc_spirit_of_olum(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && (pInstance->GetData(DATA_SUPREMUSEVENT) >= DONE) && (pInstance->GetData(DATA_HIGHWARLORDNAJENTUSEVENT) >= DONE)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_OLUM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_spirit_of_olum(Player* pPlayer, Creature* /*pCreature*/, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - pPlayer->CLOSE_GOSSIP_MENU(); - - pPlayer->InterruptNonMeleeSpells(false); - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, false); - return true; -} - -void AddSC_black_temple() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_spirit_of_olum"; - newscript->pGossipHello = &GossipHello_npc_spirit_of_olum; - newscript->pGossipSelect = &GossipSelect_npc_spirit_of_olum; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/black_temple.h b/src/server/scripts/Outland/black_temple/black_temple.h deleted file mode 100644 index b7432cd5b20..00000000000 --- a/src/server/scripts/Outland/black_temple/black_temple.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BLACK_TEMPLE_H -#define DEF_BLACK_TEMPLE_H - -enum eTypes -{ - DATA_AKAMA = 1, - DATA_AKAMA_SHADE = 2, - DATA_GURTOGGBLOODBOILEVENT = 3, - DATA_HIGHWARLORDNAJENTUS = 4, - DATA_HIGHWARLORDNAJENTUSEVENT = 5, - DATA_ILLIDANSTORMRAGE = 6, - DATA_ILLIDANSTORMRAGEEVENT = 7, - DATA_ILLIDARICOUNCILEVENT = 8, - DATA_ILLIDARICOUNCIL = 9, - DATA_LADYMALANDE = 10, - DATA_HIGHNETHERMANCERZEREVOR = 11, - DATA_GATHIOSTHESHATTERER = 12, - DATA_VERASDARKSHADOW = 13, - DATA_MOTHERSHAHRAZEVENT = 14, - DATA_RELIQUARYOFSOULSEVENT = 15, - DATA_SHADEOFAKAMA = 16, - DATA_SHADEOFAKAMAEVENT = 17, - DATA_SUPREMUS = 18, - DATA_SUPREMUSEVENT = 19, - DATA_TERONGOREFIENDEVENT = 20, - DATA_GAMEOBJECT_NAJENTUS_GATE = 21, - DATA_GAMEOBJECT_ILLIDAN_GATE = 22, - DATA_GAMEOBJECT_ILLIDAN_DOOR_R = 23, - DATA_GAMEOBJECT_ILLIDAN_DOOR_L = 24, - DATA_GAMEOBJECT_SUPREMUS_DOORS = 25, - DATA_BLOOD_ELF_COUNCIL_VOICE = 26 -}; - -#endif - diff --git a/src/server/scripts/Outland/black_temple/boss_bloodboil.cpp b/src/server/scripts/Outland/black_temple/boss_bloodboil.cpp deleted file mode 100644 index 1093ce06cb8..00000000000 --- a/src/server/scripts/Outland/black_temple/boss_bloodboil.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Bloodboil -SD%Complete: 80 -SDComment: Bloodboil not working correctly, missing enrage -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -//Speech'n'Sound -#define SAY_AGGRO -1564029 -#define SAY_SLAY1 -1564030 -#define SAY_SLAY2 -1564031 -#define SAY_SPECIAL1 -1564032 -#define SAY_SPECIAL2 -1564033 -#define SAY_ENRAGE1 -1564034 -#define SAY_ENRAGE2 -1564035 -#define SAY_DEATH -1564036 - -//Spells -#define SPELL_ACID_GEYSER 40630 -#define SPELL_ACIDIC_WOUND 40481 -#define SPELL_ARCING_SMASH 40599 -#define SPELL_BLOODBOIL 42005 // This spell is AoE whereas it shouldn't be -#define SPELL_FEL_ACID 40508 -#define SPELL_FEL_RAGE_SELF 40594 -#define SPELL_FEL_RAGE_TARGET 40604 -#define SPELL_FEL_RAGE_2 40616 -#define SPELL_FEL_RAGE_3 41625 -#define SPELL_BEWILDERING_STRIKE 40491 -#define SPELL_EJECT1 40486 // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) -#define SPELL_EJECT2 40597 // 1000 Physical damage + Stun (used in phase 2?) -#define SPELL_TAUNT_GURTOGG 40603 -#define SPELL_INSIGNIFIGANCE 40618 -#define SPELL_BERSERK 45078 - -//This is used to sort the players by distance in preparation for the Bloodboil cast. - -struct boss_gurtogg_bloodboilAI : public ScriptedAI -{ - boss_gurtogg_bloodboilAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 TargetGUID; - - float TargetThreat; - - uint32 BloodboilTimer; - uint32 BloodboilCount; - uint32 AcidGeyserTimer; - uint32 AcidicWoundTimer; - uint32 ArcingSmashTimer; - uint32 EnrageTimer; - uint32 FelAcidTimer; - uint32 EjectTimer; - uint32 BewilderingStrikeTimer; - uint32 PhaseChangeTimer; - - bool Phase1; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, NOT_STARTED); - - TargetGUID = 0; - - TargetThreat = 0; - - BloodboilTimer = 10000; - BloodboilCount = 0; - AcidGeyserTimer = 1000; - AcidicWoundTimer = 6000; - ArcingSmashTimer = 19000; - EnrageTimer = 600000; - FelAcidTimer = 25000; - EjectTimer = 10000; - BewilderingStrikeTimer = 15000; - PhaseChangeTimer = 60000; - - Phase1 = true; - - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); - } - - void EnterCombat(Unit * /*who*/) - { - DoZoneInCombat(); - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_GURTOGGBLOODBOILEVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited. - void CastBloodboil() - { - // Get the Threat List - std::list m_threatlist = me->getThreatManager().getThreatList(); - - if (!m_threatlist.size()) // He doesn't have anyone in his threatlist, useless to continue - return; - - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //only on alive players - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - targets.push_back(pTarget); - } - - //Sort the list of players - targets.sort(Trinity::ObjectDistanceOrderPred(me, false)); - //Resize so we only get top 5 - targets.resize(5); - - //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp - /*SpellEntry const *spellInfo = GetSpellStore()->LookupEntry(SPELL_BLOODBOIL); - if (spellInfo) - { - for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - { - Unit *pTarget = *itr; - if (!pTarget) return; - for (uint32 i = 0; i<3; ++i) - { - uint8 eff = spellInfo->Effect[i]; - if (eff >= TOTAL_SPELL_EFFECTS) - continue; - - Aura *Aur = new Aura(spellInfo, i, pTarget, pTarget, pTarget); - pTarget->AddAura(Aur); - } - } - }*/ - } - - void RevertThreatOnTarget(uint64 guid) - { - Unit* pUnit = NULL; - pUnit = Unit::GetUnit((*me), guid); - if (pUnit) - { - if (DoGetThreat(pUnit)) - DoModifyThreatPercent(pUnit, -100); - if (TargetThreat) - me->AddThreat(pUnit, TargetThreat); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ArcingSmashTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCING_SMASH); - ArcingSmashTimer = 10000; - } else ArcingSmashTimer -= diff; - - if (FelAcidTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FEL_ACID); - FelAcidTimer = 25000; - } else FelAcidTimer -= diff; - - if (!me->HasAura(SPELL_BERSERK)) - { - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - DoScriptText(RAND(SAY_ENRAGE1,SAY_ENRAGE2), me); - } else EnrageTimer -= diff; - } - - if (Phase1) - { - if (BewilderingStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BEWILDERING_STRIKE); - float mt_threat = DoGetThreat(me->getVictim()); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1)) - me->AddThreat(pTarget, mt_threat); - BewilderingStrikeTimer = 20000; - } else BewilderingStrikeTimer -= diff; - - if (EjectTimer <= diff) - { - DoCast(me->getVictim(), SPELL_EJECT1); - DoModifyThreatPercent(me->getVictim(), -40); - EjectTimer = 15000; - } else EjectTimer -= diff; - - if (AcidicWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ACIDIC_WOUND); - AcidicWoundTimer = 10000; - } else AcidicWoundTimer -= diff; - - if (BloodboilTimer <= diff) - { - if (BloodboilCount < 5) // Only cast it five times. - { - //CastBloodboil(); // Causes issues on windows, so is commented out. - DoCast(me->getVictim(), SPELL_BLOODBOIL); - ++BloodboilCount; - BloodboilTimer = 10000*BloodboilCount; - } - } else BloodboilTimer -= diff; - } - - if (!Phase1) - { - if (AcidGeyserTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ACID_GEYSER); - AcidGeyserTimer = 30000; - } else AcidGeyserTimer -= diff; - - if (EjectTimer <= diff) - { - DoCast(me->getVictim(), SPELL_EJECT2); - EjectTimer = 15000; - } else EjectTimer -= diff; - } - - if (PhaseChangeTimer <= diff) - { - if (Phase1) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget && pTarget->isAlive()) - { - Phase1 = false; - - TargetThreat = DoGetThreat(pTarget); - TargetGUID = pTarget->GetGUID(); - pTarget->CastSpell(me, SPELL_TAUNT_GURTOGG, true); - if (DoGetThreat(pTarget)) - DoModifyThreatPercent(pTarget, -100); - me->AddThreat(pTarget, 50000000.0f); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); - // If VMaps are disabled, this spell can call the whole instance - DoCast(me, SPELL_INSIGNIFIGANCE, true); - DoCast(pTarget, SPELL_FEL_RAGE_TARGET, true); - DoCast(pTarget, SPELL_FEL_RAGE_2, true); - /* These spells do not work, comment them out for now. - DoCast(pTarget, SPELL_FEL_RAGE_2, true); - DoCast(pTarget, SPELL_FEL_RAGE_3, true);*/ - - //Cast this without triggered so that it appears in combat logs and shows visual. - DoCast(me, SPELL_FEL_RAGE_SELF); - - DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); - - AcidGeyserTimer = 1000; - PhaseChangeTimer = 30000; - } - } else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage - { - if (TargetGUID) - RevertThreatOnTarget(TargetGUID); - TargetGUID = 0; - Phase1 = true; - BloodboilTimer = 10000; - BloodboilCount = 0; - AcidicWoundTimer += 2000; - ArcingSmashTimer += 2000; - FelAcidTimer += 2000; - EjectTimer += 2000; - PhaseChangeTimer = 60000; - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); - } - } else PhaseChangeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_gurtogg_bloodboil(Creature* pCreature) -{ - return new boss_gurtogg_bloodboilAI (pCreature); -} - -void AddSC_boss_gurtogg_bloodboil() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gurtogg_bloodboil"; - newscript->GetAI = &GetAI_boss_gurtogg_bloodboil; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/boss_illidan.cpp b/src/server/scripts/Outland/black_temple/boss_illidan.cpp deleted file mode 100644 index b8e09c0e08e..00000000000 --- a/src/server/scripts/Outland/black_temple/boss_illidan.cpp +++ /dev/null @@ -1,2248 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_illidan_stormrage -SD%Complete: 90 -SDComment: Somewhat of a workaround for Parasitic Shadowfiend, unable to summon GOs for Cage Trap. -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -#define GETGO(obj, guid) GameObject* obj = pInstance->instance->GetGameObject(guid) -#define GETUNIT(unit, guid) Unit* unit = Unit::GetUnit(*me, guid) -#define GETCRE(cre, guid) Creature* cre = Unit::GetCreature(*me, guid) -#define HPPCT(unit) unit->GetHealth()*100 / unit->GetMaxHealth() - -/************* Quotes and Sounds ***********************/ -// Gossip for when a player clicks Akama -#define GOSSIP_ITEM "We are ready to face Illidan" - -// Yells for/by Akama -#define SAY_AKAMA_BEWARE "Be wary friends, The Betrayer meditates in the court just beyond." -#define SOUND_AKAMA_BEWARE 11388 -#define SAY_AKAMA_MINION "Come, my minions. Deal with this traitor as he deserves!" -#define SOUND_AKAMA_MINION 11465 -#define SAY_AKAMA_LEAVE "I'll deal with these mongrels. Strike now, friends! Strike at the betrayer!" -#define SOUND_AKAMA_LEAVE 11390 - -// Self explanatory -const char* SAY_KILL1 = "Who shall be next to taste my blades?!"; -#define SOUND_KILL1 11473 -const char* SAY_KILL2 = "This is too easy!"; -#define SOUND_KILL2 11472 - -// I think I'll fly now and let my subordinates take you on -#define SAY_TAKEOFF "I will not be touched by rabble such as you!" -#define SOUND_TAKEOFF 11479 -#define SAY_SUMMONFLAMES "Behold the flames of Azzinoth!" -#define SOUND_SUMMONFLAMES 11480 - -// When casting Eye Blast. Demon Fire will be appear on places that he casts this -#define SAY_EYE_BLAST "Stare into the eyes of the Betrayer!" -#define SOUND_EYE_BLAST 11481 - -// kk, I go big, dark and demon on you. -#define SAY_MORPH "Behold the power... of the demon within!" -#define SOUND_MORPH 11475 - -// I KILL! -#define SAY_ENRAGE "You've wasted too much time mortals, now you shall fall!" -#define SOUND_ENRAGE 11474 - -/************** Spells *************/ -// Normal Form -#define SPELL_SHEAR 37335 // 41032 is bugged, cannot be block/dodge/parry// Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5 second cast -#define SPELL_FLAME_CRASH 40832 // Summons an invis/unselect passive mob that has an aura of flame in a circle around him. -#define SPELL_DRAW_SOUL 40904 // 5k Shadow Damage in front of him. Heals Illidan for 100k health (script effect) -#define SPELL_PARASITIC_SHADOWFIEND 41917 // DoT of 3k Shadow every 2 seconds. Lasts 10 seconds. (Script effect: Summon 2 parasites once the debuff has ticked off) -#define SPELL_PARASITIC_SHADOWFIEND2 41914 // Used by Parasitic -#define SPELL_SUMMON_PARASITICS 41915 // Summons 2 Parasitic Shadowfiends on the target. It's supposed to be cast as soon as the Parasitic Shadowfiend debuff is gone, but the spells aren't linked :( -#define SPELL_AGONIZING_FLAMES 40932 // 4k fire damage initial to target and anyone w/i 5 yards. PHASE 3 ONLY -#define SPELL_ENRAGE 40683 // Increases damage by 50% and attack speed by 30%. 20 seconds, PHASE 5 ONLY -// Flying (Phase 2) -#define SPELL_THROW_GLAIVE 39635 // Throws a glaive on the ground -#define SPELL_THROW_GLAIVE2 39849 // Animation for the above spell -#define SPELL_GLAIVE_RETURNS 39873 // Glaive flies back to Illidan -#define SPELL_FIREBALL 40598 // 2.5k-3.5k damage in 10 yard radius. 2 second cast time. -#define SPELL_DARK_BARRAGE 40585 // 10 second channeled spell, 3k shadow damage per second. -// Demon Form -#define SPELL_DEMON_TRANSFORM_1 40511 // First phase of animations for transforming into Dark Illidan (fall to ground) -#define SPELL_DEMON_TRANSFORM_2 40398 // Second phase of animations (kneel) -#define SPELL_DEMON_TRANSFORM_3 40510 // Final phase of animations (stand up and roar) -#define SPELL_DEMON_FORM 40506 // Transforms into Demon Illidan. Has an Aura of Dread on him. -#define SPELL_SHADOW_BLAST 41078 // 8k - 11k Shadow Damage. Targets highest threat. Has a splash effect, damaging anyone in 20 yards of the target. -#define SPELL_FLAME_BURST 41126 // Hurls fire at entire raid for ~3.5k damage every 10 seconds. Resistable. (Does not work: Script effect) -#define SPELL_FLAME_BURST_EFFECT 41131 // The actual damage. Have each player cast it on itself (workaround) -// Other Illidan spells -#define SPELL_KNEEL 39656 // Before beginning encounter, this is how he appears (talking to skully). -#define SPELL_SHADOW_PRISON 40647 // Illidan casts this spell to immobilize entire raid when he summons Maiev. -#define SPELL_DEATH 41220 // This spell doesn't do anything except stun Illidan and set him on his knees. -#define SPELL_BERSERK 45078 // Damage increased by 500%, attack speed by 150% -#define SPELL_DUAL_WIELD 42459 -//Phase Normal spells -#define SPELL_FLAME_CRASH_EFFECT 40836 // Firey blue ring of circle that the other flame crash summons -#define SPELL_SUMMON_SHADOWDEMON 41117 // Summon four shadowfiends -#define SPELL_SHADOWFIEND_PASSIVE 41913 // Passive aura for shadowfiends -#define SPELL_SHADOW_DEMON_PASSIVE 41079 // Adds the "shadowform" aura to Shadow Demons. -#define SPELL_CONSUME_SOUL 41080 // Once the Shadow Demons reach their target, they use this to kill them -#define SPELL_PARALYZE 41083 // Shadow Demons cast this on their target -#define SPELL_PURPLE_BEAM 39123 // Purple Beam connecting Shadow Demon to their target -//Phase Flight spells -#define SPELL_AZZINOTH_CHANNEL 39857 // Glaives cast it on Flames. Not sure if this is the right spell. -#define SPELL_EYE_BLAST_TRIGGER 40017 // This summons Demon Form every few seconds and deals ~20k damage in its radius -#define SPELL_EYE_BLAST 39908 // This does the blue flamey animation. -#define SPELL_BLAZE_EFFECT 40610 // Green flame on the ground, triggers damage (5k) every few seconds -#define SPELL_BLAZE_SUMMON 40637 // Summons the Blaze creature -#define SPELL_DEMON_FIRE 40029 // Blue fire trail left by Eye Blast. Deals 2k per second if players stand on it. -#define SPELL_FLAME_BLAST 40631 // Flames of Azzinoth use this. Frontal cone AoE 7k-9k damage. -#define SPELL_CHARGE 41581 //40602 // Flames of Azzinoth charges whoever is too far from them. They enrage after this. For simplicity, we'll use the same enrage as Illidan. -#define SPELL_FLAME_ENRAGE 45078 -//Akama spells -#define SPELL_AKAMA_DOOR_CHANNEL 41268 // Akama's channel spell on the door before the Temple Summit -#define SPELL_DEATHSWORN_DOOR_CHANNEL 41269 // Olum and Udalo's channel spell on the door before the Temple Summit -#define SPELL_AKAMA_DOOR_FAIL 41271 // Not sure where this is really used... -#define SPELL_HEALING_POTION 40535 // Akama uses this to heal himself to full. -#define SPELL_CHAIN_LIGHTNING 40536 // 6938 to 8062 for 5 targets -//Maiev spells -#define SPELL_CAGE_TRAP_DUMMY 40761 // Put this in DB for cage trap GO. -#define SPELL_CAGED 40695 // Caged Trap triggers will cast this on Illidan if he is within 3 yards -#define SPELL_CAGE_TRAP_SUMMON 40694 // Summons a Cage Trap GO (bugged) on the ground along with a Cage Trap Disturb Trigger mob (working) -#define SPELL_CAGE_TRAP_BEAM 40713 // 8 Triggers on the ground in an octagon cast spells like this on Illidan 'caging him' -#define SPELL_TELEPORT_VISUAL 41232 // Teleport visual for Maiev -#define SPELL_SHADOW_STRIKE 40685 // 4375 to 5625 every 3 seconds for 12 seconds -#define SPELL_THROW_DAGGER 41152 // 5400 to 6600 damage, need dagger -#define SPELL_FAN_BLADES 39954 // bugged visual - -// Other defines -#define CENTER_X 676.740 -#define CENTER_Y 305.297 -#define CENTER_Z 353.192 - -#define FLAME_ENRAGE_DISTANCE 30 -#define FLAME_CHARGE_DISTANCE 50 - -#define EQUIP_ID_MAIN_HAND 32837 -#define EQUIP_ID_OFF_HAND 32838 - -/**** Creature Summon and Recognition IDs ****/ -enum CreatureEntry -{ - EMPTY = 0, - AKAMA = 22990, - ILLIDAN_STORMRAGE = 22917, - BLADE_OF_AZZINOTH = 22996, - FLAME_OF_AZZINOTH = 22997, - MAIEV_SHADOWSONG = 23197, - SHADOW_DEMON = 23375, - DEMON_FIRE = 23069, - FLAME_CRASH = 23336, - ILLIDAN_DOOR_TRIGGER = 23412, - SPIRIT_OF_OLUM = 23411, - SPIRIT_OF_UDALO = 23410, - ILLIDARI_ELITE = 23226, - PARASITIC_SHADOWFIEND = 23498, - CAGE_TRAP_TRIGGER = 23292, -}; - -/*** Phase Names ***/ -enum PhaseIllidan -{ - PHASE_ILLIDAN_NULL = 0, - PHASE_NORMAL = 1, - PHASE_FLIGHT = 2, - PHASE_NORMAL_2 = 3, - PHASE_DEMON = 4, - PHASE_NORMAL_MAIEV = 5, - PHASE_TALK_SEQUENCE = 6, - PHASE_FLIGHT_SEQUENCE = 7, - PHASE_TRANSFORM_SEQUENCE = 8, - PHASE_ILLIDAN_MAX = 9, -};//Maiev uses the same phase - -enum PhaseAkama -{ - PHASE_AKAMA_NULL = 0, - PHASE_CHANNEL = 1, - PHASE_WALK = 2, - PHASE_TALK = 3, - PHASE_FIGHT_ILLIDAN = 4, - PHASE_FIGHT_MINIONS = 5, - PHASE_RETURN = 6, -}; - -enum EventIllidan -{ - EVENT_NULL = 0, - EVENT_BERSERK = 1, - //normal phase - EVENT_TAUNT = 2, - EVENT_SHEAR = 3, - EVENT_FLAME_CRASH = 4, - EVENT_PARASITIC_SHADOWFIEND = 5, - EVENT_PARASITE_CHECK = 6, - EVENT_DRAW_SOUL = 7, - EVENT_AGONIZING_FLAMES = 8, - EVENT_TRANSFORM_NORMAL = 9, - EVENT_ENRAGE = 10, - //flight phase - EVENT_FIREBALL = 2, - EVENT_DARK_BARRAGE = 3, - EVENT_EYE_BLAST = 4, - EVENT_MOVE_POINT = 5, - //demon phase - EVENT_SHADOW_BLAST = 2, - EVENT_FLAME_BURST = 3, - EVENT_SHADOWDEMON = 4, - EVENT_TRANSFORM_DEMON = 5, - //sequence phase - EVENT_TALK_SEQUENCE = 2, - EVENT_FLIGHT_SEQUENCE = 2, - EVENT_TRANSFORM_SEQUENCE = 2, -}; - -enum EventMaiev -{ - EVENT_MAIEV_NULL = 0, - EVENT_MAIEV_STEALTH = 1, - EVENT_MAIEV_TAUNT = 2, - EVENT_MAIEV_SHADOW_STRIKE = 3, - EVENT_MAIEV_THROW_DAGGER = 4, - EVENT_MAIEV_TRAP = 4, -}; - -static EventIllidan MaxTimer[]= -{ - EVENT_NULL, - EVENT_DRAW_SOUL, - EVENT_MOVE_POINT, - EVENT_TRANSFORM_NORMAL, - EVENT_TRANSFORM_DEMON, - EVENT_ENRAGE, - EVENT_TALK_SEQUENCE, - EVENT_FLIGHT_SEQUENCE, - EVENT_TRANSFORM_SEQUENCE -}; - -struct Yells -{ - uint32 sound; - char* text; - uint32 pCreature, timer, emote; - bool Talk; -}; - -static Yells Conversation[]= -{ - {11463, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.", ILLIDAN_STORMRAGE, 8000, 0, true}, - {0, NULL, ILLIDAN_STORMRAGE, 5000, 396, true}, - {11389, "We've come to end your reign, Illidan. My people and all of Outland shall be free!", AKAMA, 7000, 25, true}, - {0, NULL, AKAMA, 5000, 66, true}, - {11464, "Boldly said. But I remain unconvinced.", ILLIDAN_STORMRAGE, 8000, 396, true}, - {11380, "The time has come! The moment is at hand!", AKAMA, 3000, 22, true}, - {0, NULL, AKAMA, 2000, 15, true}, - {11466, "You are not prepared!", ILLIDAN_STORMRAGE, 3000, 406, true}, - {0, NULL, EMPTY, 1000, 0, true}, - {0, NULL, EMPTY, 0, 0, false},//9 - {11476, "Is this it, mortals? Is this all the fury you can muster?", ILLIDAN_STORMRAGE, 8000, 0, true}, - {11491, "Their fury pales before mine, Illidan. We have some unsettled business between us.", MAIEV_SHADOWSONG, 8000, 5, true}, - {11477, "Maiev... How is this even possible?", ILLIDAN_STORMRAGE, 5000, 1, true}, - {11492, "Ah... my long hunt is finally over. Today, Justice will be done!", MAIEV_SHADOWSONG, 8000, 15, true}, - {11470, "Feel the hatred of ten thousand years!", ILLIDAN_STORMRAGE, 1000, 0, false},//14 - {11496, "Ahh... It is finished. You are beaten.", MAIEV_SHADOWSONG, 6000, 0, true},//15 - {11478, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..", ILLIDAN_STORMRAGE, 30000, 65, true}, // Emote dead for now. Kill him later - {11497, "He is right. I feel nothing... I am nothing... Farewell, champions.", MAIEV_SHADOWSONG, 9000, 0, true}, - {11498, NULL, MAIEV_SHADOWSONG, 5000, 0, true}, - {11498, NULL, EMPTY, 1000, 0, true},//19 Maiev disappear - {11387, "The Light will fill these dismal halls once again. I swear it.", AKAMA, 8000, 0, true}, - {0, NULL, EMPTY, 1000, 0, false}//21 -}; - -static Yells RandomTaunts[]= -{ - {11467, "I can feel your hatred.", ILLIDAN_STORMRAGE, 0, 0, false}, - {11468, "Give in to your fear!", ILLIDAN_STORMRAGE, 0, 0, false}, - {11469, "You know nothing of power!", ILLIDAN_STORMRAGE, 0, 0, false}, - {11471, "Such... arrogance!", ILLIDAN_STORMRAGE, 0, 0, false} -}; - -static Yells MaievTaunts[]= -{ - {11493, "That is for Naisha!", MAIEV_SHADOWSONG, 0, false}, - {11494, "Bleed as I have bled!", MAIEV_SHADOWSONG, 0, 0, false}, - {11495, "There shall be no prison for you this time!", MAIEV_SHADOWSONG, 0, 0, false}, - {11500, "Meet your end, demon!", MAIEV_SHADOWSONG, 0, 0, false} -}; - -struct Locations -{ - float x, y, z; -}; - -static Locations HoverPosition[]= -{ - {657, 340, 355}, - {657, 275, 355}, - {705, 275, 355}, - {705, 340, 355} -}; - -static Locations GlaivePosition[]= -{ - {695.105, 305.303, 354.256}, - {659.338, 305.303, 354.256},//the distance between two glaives is 36 - {700.105, 305.303, 354.256}, - {664.338, 305.303, 354.256} -}; - -static Locations EyeBlast[]= -{ - {677, 350, 354},//start point, pass through glaive point - {677, 260, 354} -}; - -static Locations AkamaWP[]= -{ - {770.01, 304.50, 312.29}, // Bottom of the first stairs, at the doors - {780.66, 304.50, 319.74}, // Top of the first stairs - {790.13, 319.68, 319.76}, // Bottom of the second stairs (left from the entrance) - {787.17, 347.38, 341.42}, // Top of the second stairs - {781.34, 350.31, 341.44}, // Bottom of the third stairs - {762.60, 361.06, 353.60}, // Top of the third stairs - {756.35, 360.52, 353.27}, // Before the door-thingy - {743.82, 342.21, 353.00}, // Somewhere further - {732.69, 305.13, 353.00}, // In front of Illidan - (8) - {738.11, 365.44, 353.00}, // in front of the door-thingy (the other one!) - {792.18, 366.62, 341.42}, // Down the first flight of stairs - {796.84, 304.89, 319.76}, // Down the second flight of stairs - {782.01, 304.55, 319.76} // Final location - back at the initial gates. This is where he will fight the minions! (12) -}; -// 755.762, 304.0747, 312.1769 -- This is where Akama should be spawned -static Locations SpiritSpawns[]= -{ - {755.5426, 309.9156, 312.2129}, - {755.5426, 298.7923, 312.0834} -}; - -struct Animation // For the demon transformation -{ - uint32 aura, unaura, timer, size, displayid, phase; - bool equip; -}; - -static Animation DemonTransformation[]= -{ - {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, true}, - {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, true}, - {0, 0, 3000, 1073741824, 21322, 6, false},//stunned, cannot cast demon form - {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, false}, - {SPELL_DEMON_FORM, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 4, false}, - {SPELL_DEMON_TRANSFORM_1, 0, 1000, 0, 0, 6, false}, - {SPELL_DEMON_TRANSFORM_2, SPELL_DEMON_TRANSFORM_1, 4000, 0, 0, 6, false}, - {0, SPELL_DEMON_FORM, 3000, 1069547520, 21135, 6, false}, - {SPELL_DEMON_TRANSFORM_3, SPELL_DEMON_TRANSFORM_2, 3500, 0, 0, 6, true}, - {0, SPELL_DEMON_TRANSFORM_3, 0, 0, 0, 8, true} -}; - -#define EMOTE_SETS_GAZE_ON "sets its gaze on $N!" -#define EMOTE_UNABLE_TO_SUMMON "is unable to summon Maiev Shadowsong and enter Phase 4. Resetting Encounter." - -/************************************** Illidan's AI ***************************************/ -struct boss_illidan_stormrageAI : public ScriptedAI -{ - boss_illidan_stormrageAI(Creature* c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - DoCast(me, SPELL_DUAL_WIELD, true); - - SpellEntry *TempSpell = GET_SPELL(SPELL_SHADOWFIEND_PASSIVE); - if (TempSpell) - TempSpell->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends - } - - ScriptedInstance* pInstance; - - PhaseIllidan Phase; - EventIllidan Event; - uint32 Timer[EVENT_ENRAGE + 1]; - - uint32 TalkCount; - uint32 TransformCount; - uint32 FlightCount; - - uint32 HoverPoint; - - uint64 AkamaGUID; - uint64 MaievGUID; - uint64 FlameGUID[2]; - uint64 GlaiveGUID[2]; - - SummonList Summons; - - void Reset(); - - void JustSummoned(Creature* summon); - - void SummonedCreatureDespawn(Creature* summon) - { - if (summon->GetCreatureInfo()->Entry == FLAME_OF_AZZINOTH) - { - for (uint8 i = 0; i < 2; ++i) - if (summon->GetGUID() == FlameGUID[i]) - FlameGUID[i] = 0; - - if (!FlameGUID[0] && !FlameGUID[1] && Phase != PHASE_ILLIDAN_NULL) - { - me->InterruptNonMeleeSpells(true); - EnterPhase(PHASE_FLIGHT_SEQUENCE); - } - } - Summons.Despawn(summon); - } - - void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) - { - if (FlightCount == 7) //change hover point - { - if (me->getVictim()) - { - me->SetInFront(me->getVictim()); - me->StopMoving(); - } - EnterPhase(PHASE_FLIGHT); - } - else // handle flight sequence - Timer[EVENT_FLIGHT_SEQUENCE] = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - me->setActive(true); - DoZoneInCombat(); - } - - void AttackStart(Unit *who) - { - if (!who || Phase >= PHASE_TALK_SEQUENCE) - return; - - if (Phase == PHASE_FLIGHT || Phase == PHASE_DEMON) - AttackStartNoMove(who); - else - ScriptedAI::AttackStart(who); - } - - void MoveInLineOfSight(Unit *) {} - - void JustDied(Unit * /*killer*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (!pInstance) - return; - - pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, DONE); // Completed - - for (uint8 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L + 1; ++i) - pInstance->HandleGameObject(pInstance->GetData64(i), true); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) return; - // TODO: Find better way to handle emote - switch (urand(0,1)) - { - case 0: - me->MonsterYell(SAY_KILL1, LANG_UNIVERSAL, victim->GetGUID()); - DoPlaySoundToSet(me, SOUND_KILL1); - break; - case 1: - me->MonsterYell(SAY_KILL2, LANG_UNIVERSAL, victim->GetGUID()); - DoPlaySoundToSet(me, SOUND_KILL2); - break; - } - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = 0; - if (done_by->GetGUID() == MaievGUID) - done_by->AddThreat(me, -(3*(float)damage)/4); // do not let maiev tank him - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades! - { - if (!me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) - SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - else - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - } - } - - void DeleteFromThreatList(uint64 TargetGUID) - { - for (std::list::const_iterator itr = me->getThreatManager().getThreatList().begin(); itr != me->getThreatManager().getThreatList().end(); ++itr) - { - if ((*itr)->getUnitGuid() == TargetGUID) - { - (*itr)->removeReference(); - break; - } - } - } - - void Talk(uint32 count) - { - Timer[EVENT_TALK_SEQUENCE] = Conversation[count].timer; - - Creature* pCreature = NULL; - if (Conversation[count].pCreature == ILLIDAN_STORMRAGE) - pCreature = me; - else if (Conversation[count].pCreature == AKAMA) - pCreature = (Unit::GetCreature((*me), AkamaGUID)); - else if (Conversation[count].pCreature == MAIEV_SHADOWSONG) - pCreature = (Unit::GetCreature((*me), MaievGUID)); - - if (pCreature) - { - if (Conversation[count].emote) - pCreature->HandleEmoteCommand(Conversation[count].emote); // Make the Creature do some animation! - if (Conversation[count].text) - pCreature->MonsterYell(Conversation[count].text, LANG_UNIVERSAL, 0); // Have the Creature yell out some text - if (Conversation[count].sound) - DoPlaySoundToSet(pCreature, Conversation[count].sound); // Play some sound on the creature - } - } - - void EnterPhase(PhaseIllidan NextPhase); - void CastEyeBlast(); - void SummonFlamesOfAzzinoth(); - void SummonMaiev(); - void HandleTalkSequence(); - void HandleFlightSequence() - { - switch(FlightCount) - { - case 1://lift off - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - me->StopMoving(); - me->MonsterYell(SAY_TAKEOFF, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_TAKEOFF); - Timer[EVENT_FLIGHT_SEQUENCE] = 3000; - break; - case 2://move to center - me->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); //+5, for SPELL_THROW_GLAIVE bug - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 3://throw one glaive - { - uint8 i=1; - Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Glaive) - { - GlaiveGUID[i] = Glaive->GetGUID(); - Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Glaive->SetDisplayId(11686); - Glaive->setFaction(me->getFaction()); - DoCast(Glaive, SPELL_THROW_GLAIVE2); - } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 700; - break; - case 4://throw another - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - { - uint8 i=0; - Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Glaive) - { - GlaiveGUID[i] = Glaive->GetGUID(); - Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Glaive->SetDisplayId(11686); - Glaive->setFaction(me->getFaction()); - DoCast(Glaive, SPELL_THROW_GLAIVE, true); - } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 5000; - break; - case 5://summon flames - SummonFlamesOfAzzinoth(); - Timer[EVENT_FLIGHT_SEQUENCE] = 3000; - break; - case 6://fly to hover point - me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 7://return to center - me->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 8://glaive return - for (uint8 i = 0; i < 2; ++i) - { - if (GlaiveGUID[i]) - { - Unit* Glaive = Unit::GetUnit((*me), GlaiveGUID[i]); - if (Glaive) - { - Glaive->CastSpell(me, SPELL_GLAIVE_RETURNS, false); // Make it look like the Glaive flies back up to us - Glaive->SetDisplayId(11686); // disappear but not die for now - } - } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 2000; - break; - case 9://land - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->StopMoving(); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - for (uint8 i = 0; i < 2; ++i) - { - if (GlaiveGUID[i]) - { - if (GETUNIT(Glaive, GlaiveGUID[i])) - { - Glaive->SetVisibility(VISIBILITY_OFF); - Glaive->setDeathState(JUST_DIED); // Despawn the Glaive - } - GlaiveGUID[i] = 0; - } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 2000; - break; - case 10://attack - DoResetThreat(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - EnterPhase(PHASE_NORMAL_2); - break; - default: - break; - } - ++FlightCount; - } - - void HandleTransformSequence() - { - if (DemonTransformation[TransformCount].unaura) - me->RemoveAurasDueToSpell(DemonTransformation[TransformCount].unaura); - - if (DemonTransformation[TransformCount].aura) - DoCast(me, DemonTransformation[TransformCount].aura, true); - - if (DemonTransformation[TransformCount].displayid) - me->SetDisplayId(DemonTransformation[TransformCount].displayid); // It's morphin time! - - if (DemonTransformation[TransformCount].equip) - { - // Requip warglaives if needed - SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - } - else - { - // Unequip warglaives if needed - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - } - - switch(TransformCount) - { - case 2: - DoResetThreat(); - break; - case 4: - EnterPhase(PHASE_DEMON); - break; - case 7: - DoResetThreat(); - break; - case 9: - if (MaievGUID) - EnterPhase(PHASE_NORMAL_MAIEV); // Depending on whether we summoned Maiev, we switch to either phase 5 or 3 - else - EnterPhase(PHASE_NORMAL_2); - break; - default: - break; - } - if (Phase == PHASE_TRANSFORM_SEQUENCE) - Timer[EVENT_TRANSFORM_SEQUENCE] = DemonTransformation[TransformCount].timer; - ++TransformCount; - } - - void UpdateAI(const uint32 diff) - { - if ((!UpdateVictim()) && Phase < PHASE_TALK_SEQUENCE) - return; - - Event = EVENT_NULL; - for (uint32 i = 1; i <= MaxTimer[Phase]; ++i) - { - if (Timer[i]) // Event is enabled - if (Timer[i] <= diff) - { - if (!Event) // No event with higher priority - Event = (EventIllidan)i; - } - else Timer[i] -= diff; - } - - switch(Phase) - { - case PHASE_NORMAL: - if (HPPCT(me) < 65) - EnterPhase(PHASE_FLIGHT_SEQUENCE); - break; - - case PHASE_NORMAL_2: - if (HPPCT(me) < 30) - EnterPhase(PHASE_TALK_SEQUENCE); - break; - - case PHASE_NORMAL_MAIEV: - if (HPPCT(me) < 1) - EnterPhase(PHASE_TALK_SEQUENCE); - break; - - case PHASE_TALK_SEQUENCE: - if (Event == EVENT_TALK_SEQUENCE) - HandleTalkSequence(); - break; - - case PHASE_FLIGHT_SEQUENCE: - if (Event == EVENT_FLIGHT_SEQUENCE) - HandleFlightSequence(); - break; - - case PHASE_TRANSFORM_SEQUENCE: - if (Event == EVENT_TRANSFORM_SEQUENCE) - HandleTransformSequence(); - break; - } - - if (me->IsNonMeleeSpellCasted(false)) - return; - - if (Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV && !me->HasAura(SPELL_CAGED)) - { - switch(Event) - { - //PHASE_NORMAL - case EVENT_BERSERK: - me->MonsterYell(SAY_ENRAGE, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_ENRAGE); - DoCast(me, SPELL_BERSERK, true); - Timer[EVENT_BERSERK] = 5000;//The buff actually lasts forever. - break; - - case EVENT_TAUNT: - { - uint32 random = rand()%4; - char* yell = RandomTaunts[random].text; - uint32 soundid = RandomTaunts[random].sound; - if (yell) - me->MonsterYell(yell, LANG_UNIVERSAL, 0); - if (soundid) - DoPlaySoundToSet(me, soundid); - } - Timer[EVENT_TAUNT] = 25000 + rand()%10000; - break; - - case EVENT_SHEAR: - // no longer exists in 3.0.2 - //DoCast(me->getVictim(), SPELL_SHEAR); - Timer[EVENT_SHEAR] = 25000 + (rand()%16 * 1000); - break; - - case EVENT_FLAME_CRASH: - DoCast(me->getVictim(), SPELL_FLAME_CRASH); - Timer[EVENT_FLAME_CRASH] = 30000 + rand()%10000; - break; - - case EVENT_PARASITIC_SHADOWFIEND: - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true)) - DoCast(pTarget, SPELL_PARASITIC_SHADOWFIEND, true); - Timer[EVENT_PARASITIC_SHADOWFIEND] = 35000 + rand()%10000; - } - break; - - case EVENT_PARASITE_CHECK: - Timer[EVENT_PARASITE_CHECK] = 0; - break; - - case EVENT_DRAW_SOUL: - DoCast(me->getVictim(), SPELL_DRAW_SOUL); - Timer[EVENT_DRAW_SOUL] = 50000 + rand()%10000; - break; - - //PHASE_NORMAL_2 - case EVENT_AGONIZING_FLAMES: - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES); - Timer[EVENT_AGONIZING_FLAMES] = 0; - break; - - case EVENT_TRANSFORM_NORMAL: - EnterPhase(PHASE_TRANSFORM_SEQUENCE); - break; - - //PHASE_NORMAL_MAIEV - case EVENT_ENRAGE: - DoCast(me, SPELL_ENRAGE); - Timer[EVENT_ENRAGE] = 0; - break; - - default: - break; - } - DoMeleeAttackIfReady(); - } - - if (Phase == PHASE_FLIGHT) - { - switch(Event) - { - case EVENT_FIREBALL: - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL); - Timer[EVENT_FIREBALL] = 3000; - break; - - case EVENT_DARK_BARRAGE: - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE); - Timer[EVENT_DARK_BARRAGE] = 0; - break; - - case EVENT_EYE_BLAST: - CastEyeBlast(); - Timer[EVENT_EYE_BLAST] = 0; - break; - - case EVENT_MOVE_POINT: - Phase = PHASE_FLIGHT_SEQUENCE; - Timer[EVENT_FLIGHT_SEQUENCE] = 0;//do not start Event when changing hover point - HoverPoint += (rand()%3 + 1); - if (HoverPoint > 3) - HoverPoint -= 4; - me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); - break; - - default: - break; - } - } - - if (Phase == PHASE_DEMON) - { - switch(Event) - { - case EVENT_SHADOW_BLAST: - me->GetMotionMaster()->Clear(false); - if (!me->IsWithinDistInMap(me->getVictim(), 50)||!me->IsWithinLOSInMap(me->getVictim())) - me->GetMotionMaster()->MoveChase(me->getVictim(), 30); - else - me->GetMotionMaster()->MoveIdle(); - DoCast(me->getVictim(), SPELL_SHADOW_BLAST); - Timer[EVENT_SHADOW_BLAST] = 4000; - break; - case EVENT_SHADOWDEMON: - DoCast(me, SPELL_SUMMON_SHADOWDEMON); - Timer[EVENT_SHADOWDEMON] = 0; - Timer[EVENT_FLAME_BURST] += 10000; - break; - case EVENT_FLAME_BURST: - DoCast(me, SPELL_FLAME_BURST); - Timer[EVENT_FLAME_BURST] = 15000; - break; - case EVENT_TRANSFORM_DEMON: - EnterPhase(PHASE_TRANSFORM_SEQUENCE); - break; - default: - break; - } - } - } -}; - -/********************************** End of Illidan AI ******************************************/ - -struct flame_of_azzinothAI : public ScriptedAI -{ - flame_of_azzinothAI(Creature *c) : ScriptedAI(c) {} - - uint32 FlameBlastTimer; - uint32 CheckTimer; - uint64 GlaiveGUID; - - void Reset() - { - FlameBlastTimer = 15000; - CheckTimer = 5000; - GlaiveGUID = 0; - } - - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - - void ChargeCheck() - { - Unit *pTarget = SelectTarget(SELECT_TARGET_FARTHEST, 0, 200, false); - if (pTarget && (!me->IsWithinCombatRange(pTarget, FLAME_CHARGE_DISTANCE))) - { - me->AddThreat(pTarget, 5000000.0f); - AttackStart(pTarget); - DoCast(pTarget, SPELL_CHARGE); - me->MonsterTextEmote(EMOTE_SETS_GAZE_ON, pTarget->GetGUID()); - } - } - - void EnrageCheck() - { - if (GETUNIT(Glaive, GlaiveGUID)) - { - if (!me->IsWithinDistInMap(Glaive, FLAME_ENRAGE_DISTANCE)) - { - Glaive->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_FLAME_ENRAGE, true); - DoResetThreat(); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget && pTarget->isAlive()) - { - me->AddThreat(me->getVictim(), 5000000.0f); - AttackStart(me->getVictim()); - } - } - else if (!me->HasAura(SPELL_AZZINOTH_CHANNEL)) - { - Glaive->CastSpell(me, SPELL_AZZINOTH_CHANNEL, false); - me->RemoveAurasDueToSpell(SPELL_FLAME_ENRAGE); - } - } - } - - void SetGlaiveGUID(uint64 guid){ GlaiveGUID = guid; } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (FlameBlastTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BLAZE_SUMMON, true); //appear at victim - DoCast(me->getVictim(), SPELL_FLAME_BLAST); - FlameBlastTimer = 15000; //10000 is official-like? - DoZoneInCombat(); //in case someone is revived - } else FlameBlastTimer -= diff; - - if (CheckTimer <= diff) - { - ChargeCheck(); - EnrageCheck(); - CheckTimer = 1000; - } else CheckTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -/******* Functions and vars for Akama's AI ******/ -struct npc_akama_illidanAI : public ScriptedAI -{ - npc_akama_illidanAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - JustCreated = true; - } - bool JustCreated; - ScriptedInstance* pInstance; - - PhaseAkama Phase; - bool Event; - uint32 Timer; - - uint64 IllidanGUID; - uint64 ChannelGUID; - uint64 SpiritGUID[2]; - uint64 GateGUID; - uint64 DoorGUID[2]; - - uint32 ChannelCount; - uint32 WalkCount; - uint32 TalkCount; - uint32 Check_Timer; - - void Reset() - { - WalkCount = 0; - if (pInstance) - { - pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); - - IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); - GateGUID = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_GATE); - DoorGUID[0] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_R); - DoorGUID[1] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_L); - - if (JustCreated)//close all doors at create - { - pInstance->HandleGameObject(GateGUID, false); - - for (uint8 i = 0; i < 2; ++i) - pInstance->HandleGameObject(DoorGUID[i], false); - //JustCreated = false; - }else - {//open all doors, raid wiped - pInstance->HandleGameObject(GateGUID, true); - WalkCount = 1;//skip first wp - for (uint8 i = 0; i < 2; ++i) - pInstance->HandleGameObject(DoorGUID[i], true); - } - } - else - { - IllidanGUID = 0; - GateGUID = 0; - DoorGUID[0] = 0; - DoorGUID[1] = 0; - } - - ChannelGUID = 0; - SpiritGUID[0] = 0; - SpiritGUID[1] = 0; - - Phase = PHASE_AKAMA_NULL; - Timer = 0; - - ChannelCount = 0; - TalkCount = 0; - Check_Timer = 5000; - - KillAllElites(); - - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values.. - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->setActive(false); - me->SetVisibility(VISIBILITY_OFF); - } - - // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit - void EnterEvadeMode() - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void MovementInform(uint32 MovementType, uint32 /*Data*/) - { - if (MovementType == POINT_MOTION_TYPE) - Timer = 1; - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage > me->GetHealth() || done_by->GetGUID() != IllidanGUID) - damage = 0; - } - - void KillAllElites() - { - std::list& threatList = me->getThreatManager().getThreatList(); - std::vector eliteList; - for (std::list::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->GetEntry() == ILLIDARI_ELITE) - eliteList.push_back(pUnit); - } - for (std::vector::const_iterator itr = eliteList.begin(); itr != eliteList.end(); ++itr) - (*itr)->setDeathState(JUST_DIED); - EnterEvadeMode(); - } - - void BeginTalk() - { - if (!pInstance) - return; - - pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, IN_PROGRESS); - for (uint8 i = 0; i < 2; ++i) - pInstance->HandleGameObject(DoorGUID[i], false); - if (GETCRE(Illidan, IllidanGUID)) - { - Illidan->RemoveAurasDueToSpell(SPELL_KNEEL); - me->SetInFront(Illidan); - Illidan->SetInFront(me); - me->GetMotionMaster()->MoveIdle(); - Illidan->GetMotionMaster()->MoveIdle(); - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->AkamaGUID = me->GetGUID(); - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->EnterPhase(PHASE_TALK_SEQUENCE); - } - } - - void BeginChannel() - { - me->setActive(true); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - if (!JustCreated) - return; - float x, y, z; - if (GETGO(Gate, GateGUID)) - Gate->GetPosition(x, y, z); - else - return;//if door not spawned, don't crash server - - if (Creature* Channel = me->SummonCreature(ILLIDAN_DOOR_TRIGGER, x, y, z+5, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) - { - ChannelGUID = Channel->GetGUID(); - Channel->SetDisplayId(11686); // Invisible but spell visuals can still be seen. - DoCast(Channel, SPELL_AKAMA_DOOR_FAIL); - } - - for (uint8 i = 0; i < 2; ++i) - if (Creature* Spirit = me->SummonCreature(i ? SPIRIT_OF_OLUM : SPIRIT_OF_UDALO, SpiritSpawns[i].x, SpiritSpawns[i].y, SpiritSpawns[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) - { - Spirit->SetVisibility(VISIBILITY_OFF); - SpiritGUID[i] = Spirit->GetGUID(); - } - } - - void BeginWalk() - { - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->SetSpeed(MOVE_RUN, 1.0f); - me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); - } - - void EnterPhase(PhaseAkama NextPhase) - { - if (!pInstance) - return; - switch(NextPhase) - { - case PHASE_CHANNEL: - BeginChannel(); - Timer = 5000; - ChannelCount = 0; - break; - case PHASE_WALK: - if (Phase == PHASE_CHANNEL) - WalkCount = 0; - else if (Phase == PHASE_TALK) - { - if (GETCRE(Illidan, IllidanGUID)) - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); - EnterEvadeMode(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - ++WalkCount; - } - JustCreated = false; - BeginWalk(); - Timer = 0; - break; - case PHASE_TALK: - if (Phase == PHASE_WALK) - { - BeginTalk(); - Timer = 0; - } - else if (Phase == PHASE_FIGHT_ILLIDAN) - { - Timer = 1; - TalkCount = 0; - } - break; - case PHASE_FIGHT_ILLIDAN: - if (GETUNIT(Illidan, IllidanGUID)) - { - me->AddThreat(Illidan, 10000000.0f); - me->GetMotionMaster()->MoveChase(Illidan); - } - Timer = 30000; //chain lightning - break; - case PHASE_FIGHT_MINIONS: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Timer = 10000 + rand()%6000;//summon minion - break; - case PHASE_RETURN: - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - KillAllElites(); - WalkCount = 0; - BeginWalk(); - Timer = 1; - break; - default: - break; - } - Phase = NextPhase; - Event = false; - } - - void HandleTalkSequence() - { - switch(TalkCount) - { - case 0: - if (GETCRE(Illidan, IllidanGUID)) - { - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->Timer[EVENT_TAUNT] += 30000; - Illidan->MonsterYell(SAY_AKAMA_MINION, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(Illidan, SOUND_AKAMA_MINION); - } - Timer = 8000; - break; - case 1: - me->MonsterYell(SAY_AKAMA_LEAVE, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_AKAMA_LEAVE); - Timer = 3000; - break; - case 2: - EnterPhase(PHASE_WALK); - break; - } - ++TalkCount; - } - - void HandleChannelSequence() - { - Unit* Channel = NULL, *Spirit[2]; - if (ChannelCount <= 5) - { - Channel = Unit::GetUnit((*me), ChannelGUID); - Spirit[0] = Unit::GetUnit((*me), SpiritGUID[0]); - Spirit[1] = Unit::GetUnit((*me), SpiritGUID[1]); - if (!Channel || !Spirit[0] || !Spirit[1]) - return; - } - - switch(ChannelCount) - { - case 0: // channel failed - me->InterruptNonMeleeSpells(true); - Timer = 2000; - break; - case 1: // spirit appear - Spirit[0]->SetVisibility(VISIBILITY_ON); - Spirit[1]->SetVisibility(VISIBILITY_ON); - Timer = 2000; - break; - case 2: // spirit help - DoCast(Channel, SPELL_AKAMA_DOOR_CHANNEL); - Spirit[0]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); - Spirit[1]->CastSpell(Channel, SPELL_DEATHSWORN_DOOR_CHANNEL,false); - Timer = 5000; - break; - case 3: //open the gate - me->InterruptNonMeleeSpells(true); - Spirit[0]->InterruptNonMeleeSpells(true); - Spirit[1]->InterruptNonMeleeSpells(true); - if (pInstance) - pInstance->HandleGameObject(GateGUID, true); - Timer = 2000; - break; - case 4: - me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); - Timer = 2000; - break; - case 5: - me->MonsterYell(SAY_AKAMA_BEWARE, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_AKAMA_BEWARE); - Channel->setDeathState(JUST_DIED); - Spirit[0]->SetVisibility(VISIBILITY_OFF); - Spirit[1]->SetVisibility(VISIBILITY_OFF); - Timer = 3000; - break; - case 6: - EnterPhase(PHASE_WALK); - break; - default: - break; - } - ++ChannelCount; - } - - void HandleWalkSequence() - { - switch(WalkCount) - { - case 6: - for (uint8 i = 0; i < 2; ++i) - if (pInstance) - pInstance->HandleGameObject(DoorGUID[i], true); - break; - case 8: - if (Phase == PHASE_WALK) - EnterPhase(PHASE_TALK); - else - EnterPhase(PHASE_FIGHT_ILLIDAN); - break; - case 12: - EnterPhase(PHASE_FIGHT_MINIONS); - break; - } - - if (Phase == PHASE_WALK) - { - Timer = 0; - ++WalkCount; - me->GetMotionMaster()->MovePoint(WalkCount, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); - } - } - - void UpdateAI(const uint32 diff) - { - if (me->GetVisibility() == VISIBILITY_OFF) - { - if (Check_Timer <= diff) - { - if (pInstance && pInstance->GetData(DATA_ILLIDARICOUNCILEVENT) == DONE) - me->SetVisibility(VISIBILITY_ON); - - Check_Timer = 5000; - } else Check_Timer -= diff; - } - Event = false; - if (Timer) - { - if (Timer <= diff) - Event = true; - else Timer -= diff; - } - - if (Event) - { - switch(Phase) - { - case PHASE_CHANNEL: - if (JustCreated) - HandleChannelSequence(); - else{ - EnterPhase(PHASE_WALK); - } - break; - case PHASE_TALK: - HandleTalkSequence(); - break; - case PHASE_WALK: - case PHASE_RETURN: - HandleWalkSequence(); - break; - case PHASE_FIGHT_ILLIDAN: - { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && HPPCT(Illidan) < 90) - EnterPhase(PHASE_TALK); - else - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTNING); - Timer = 30000; - } - } - break; - case PHASE_FIGHT_MINIONS: - { - float x, y, z; - me->GetPosition(x, y, z); - Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); - //Creature* Elite = me->SummonCreature(ILLIDARI_ELITE, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000); - if (Elite) - { - Elite->AI()->AttackStart(me); - Elite->AddThreat(me, 1000000.0f); - AttackStart(Elite); - me->AddThreat(Elite, 1000000.0f); - } - Timer = 10000 + rand()%6000; - GETUNIT(Illidan, IllidanGUID); - if (Illidan && HPPCT(Illidan) < 10) - EnterPhase(PHASE_RETURN); - } - break; - default: - break; - } - } - - if (!UpdateVictim()) - return; - - if (me->GetHealth()*100 / me->GetMaxHealth() < 20) - DoCast(me, SPELL_HEALING_POTION); - - DoMeleeAttackIfReady(); - } -}; - -struct boss_maievAI : public ScriptedAI -{ - boss_maievAI(Creature *c) : ScriptedAI(c) {}; - - uint64 IllidanGUID; - - PhaseIllidan Phase; - EventMaiev Event; - uint32 Timer[5]; - uint32 MaxTimer; - - void Reset() - { - MaxTimer = 0; - Phase = PHASE_NORMAL_MAIEV; - IllidanGUID = 0; - Timer[EVENT_MAIEV_STEALTH] = 0; - Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; - Timer[EVENT_MAIEV_SHADOW_STRIKE] = 30000; - SetEquipmentSlots(false, 44850, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, 45738); - } - - void EnterCombat(Unit * /*who*/) {} - void MoveInLineOfSight(Unit * /*who*/) {} - void EnterEvadeMode() {} - void GetIllidanGUID(uint64 guid) { IllidanGUID = guid; } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != IllidanGUID) - damage = 0; - else - { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && Illidan->getVictim() == me) - damage = me->GetMaxHealth()/10; - if (damage >= me->GetHealth()) - damage = 0; - } - } - - void AttackStart(Unit *who) - { - if (!who || Timer[EVENT_MAIEV_STEALTH]) - return; - - if (Phase == PHASE_TALK_SEQUENCE) - AttackStartNoMove(who); - else if (Phase == PHASE_DEMON || Phase == PHASE_TRANSFORM_SEQUENCE) - { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && me->IsWithinDistInMap(Illidan, 25)) - BlinkToPlayer();//Do not let dread aura hurt her. - AttackStartNoMove(who); - } - else - ScriptedAI::AttackStart(who); - } - - void DoAction(const int32 param) - { - if (param > PHASE_ILLIDAN_NULL && param < PHASE_ILLIDAN_MAX) - EnterPhase(PhaseIllidan(param)); - } - - void EnterPhase(PhaseIllidan NextPhase)//This is in fact Illidan's phase. - { - switch(NextPhase) - { - case PHASE_TALK_SEQUENCE: - if (Timer[EVENT_MAIEV_STEALTH]) - { - me->SetHealth(me->GetMaxHealth()); - me->SetVisibility(VISIBILITY_ON); - Timer[EVENT_MAIEV_STEALTH] = 0; - } - me->InterruptNonMeleeSpells(false); - me->GetMotionMaster()->Clear(false); - me->AttackStop(); - me->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); - MaxTimer = 0; - break; - case PHASE_TRANSFORM_SEQUENCE: - MaxTimer = 4; - Timer[EVENT_MAIEV_TAUNT] += 10000; - Timer[EVENT_MAIEV_THROW_DAGGER] = 2000; - break; - case PHASE_DEMON: - break; - case PHASE_NORMAL_MAIEV: - MaxTimer = 4; - Timer[EVENT_MAIEV_TAUNT] += 10000; - Timer[EVENT_MAIEV_TRAP] = 22000; - break; - default: - break; - } - if (Timer[EVENT_MAIEV_STEALTH]) - MaxTimer = 1; - Phase = NextPhase; - } - - void BlinkTo(float x, float y, float z) - { - me->AttackStop(); - me->InterruptNonMeleeSpells(false); - me->GetMotionMaster()->Clear(false); - DoTeleportTo(x, y, z); - DoCast(me, SPELL_TELEPORT_VISUAL, true); - } - - void BlinkToPlayer() - { - if (GETCRE(Illidan, IllidanGUID)) - { - Unit *pTarget = CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (!pTarget || !me->IsWithinDistInMap(pTarget, 80) || Illidan->IsWithinDistInMap(pTarget, 20)) - { - uint8 pos = rand()%4; - BlinkTo(HoverPosition[pos].x, HoverPosition[pos].y, HoverPosition[pos].z); - } - else - { - float x, y, z; - pTarget->GetPosition(x, y, z); - BlinkTo(x, y, z); - } - } - } - - void UpdateAI(const uint32 diff) - { - if ((!UpdateVictim()) - && !Timer[EVENT_MAIEV_STEALTH]) - return; - - Event = EVENT_MAIEV_NULL; - for (uint8 i = 1; i <= MaxTimer; ++i) - if (Timer[i]) - { - if (Timer[i] <= diff) - Event = (EventMaiev)i; - else Timer[i] -= diff; - } - - switch(Event) - { - case EVENT_MAIEV_STEALTH: - { - me->SetHealth(me->GetMaxHealth()); - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Timer[EVENT_MAIEV_STEALTH] = 0; - BlinkToPlayer(); - EnterPhase(Phase); - } - break; - case EVENT_MAIEV_TAUNT: - { - uint32 random = rand()%4; - char* text = MaievTaunts[random].text; - uint32 sound = MaievTaunts[random].sound; - me->MonsterYell(text, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, sound); - Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; - } - break; - case EVENT_MAIEV_SHADOW_STRIKE: - DoCast(me->getVictim(), SPELL_SHADOW_STRIKE); - Timer[EVENT_MAIEV_SHADOW_STRIKE] = 60000; - break; - case EVENT_MAIEV_TRAP: - if (Phase == PHASE_NORMAL_MAIEV) - { - BlinkToPlayer(); - DoCast(me, SPELL_CAGE_TRAP_SUMMON); - Timer[EVENT_MAIEV_TRAP] = 22000; - } - else - { - if (!me->IsWithinDistInMap(me->getVictim(), 40)) - me->GetMotionMaster()->MoveChase(me->getVictim(), 30); - DoCast(me->getVictim(), SPELL_THROW_DAGGER); - Timer[EVENT_MAIEV_THROW_DAGGER] = 2000; - } - break; - default: - break; - } - - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (GETCRE(Illidan, IllidanGUID)) - CAST_AI(boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); - me->AttackStop(); - Timer[EVENT_MAIEV_STEALTH] = 60000; //reappear after 1 minute - MaxTimer = 1; - } - - if (Phase == PHASE_NORMAL_MAIEV) - DoMeleeAttackIfReady(); - } -}; - -bool GossipSelect_npc_akama_at_illidan(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) // Time to begin the Event - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_akama_illidanAI, pCreature->AI())->EnterPhase(PHASE_CHANNEL); - } - return true; -} - -bool GossipHello_npc_akama_at_illidan(Player* pPlayer, Creature* pCreature) -{ - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(10465, pCreature->GetGUID()); - - return true; -} - -struct cage_trap_triggerAI : public ScriptedAI -{ - cage_trap_triggerAI(Creature *c) : ScriptedAI(c) {} - - uint64 IllidanGUID; - uint32 DespawnTimer; - - bool Active; - bool SummonedBeams; - - void Reset() - { - IllidanGUID = 0; - - Active = false; - SummonedBeams = false; - - DespawnTimer = 0; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/){} - - void MoveInLineOfSight(Unit *who) - { - if (!Active) - return; - - if (who && (who->GetTypeId() != TYPEID_PLAYER)) - { - if (who->GetEntry() == ILLIDAN_STORMRAGE) // Check if who is Illidan - { - if (!IllidanGUID && me->IsWithinDistInMap(who, 3) && (!who->HasAura(SPELL_CAGED))) - { - IllidanGUID = who->GetGUID(); - who->CastSpell(who, SPELL_CAGED, true); - DespawnTimer = 5000; - if (who->HasAura(SPELL_ENRAGE)) - who->RemoveAurasDueToSpell(SPELL_ENRAGE); // Dispel his enrage - //if (GameObject* CageTrap = pInstance->instance->GetGameObject(pInstance->GetData64(CageTrapGUID))) - // CageTrap->SetLootState(GO_JUST_DEACTIVATED); - } - } - } - } - - void UpdateAI(const uint32 diff) - { - if (DespawnTimer) - if (DespawnTimer <= diff) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - else DespawnTimer -= diff; - - //if (IllidanGUID && !SummonedBeams) - //{ - // if (Unit* Illidan = Unit::GetUnit(*me, IllidanGUID) - // { - // //TODO: Find proper spells and properly apply 'caged' Illidan effect - // } - //} - } -}; - -bool GOHello_cage_trap(Player* pPlayer, GameObject* pGo) -{ - float x, y, z; - pPlayer->GetPosition(x, y, z); - - // Grid search for nearest live Creature of entry 23304 within 10 yards - if (Creature* pTrigger = pGo->FindNearestCreature(23304, 10.0f)) - CAST_AI(cage_trap_triggerAI, pTrigger->AI())->Active = true; - pGo->SetGoState(GO_STATE_ACTIVE); - return true; -} - -struct shadow_demonAI : public ScriptedAI -{ - shadow_demonAI(Creature *c) : ScriptedAI(c) {} - - uint64 TargetGUID; - - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - - void Reset() - { - TargetGUID = 0; - DoCast(me, SPELL_SHADOW_DEMON_PASSIVE, true); - } - - void JustDied(Unit * /*killer*/) - { - if (Unit *pTarget = Unit::GetUnit((*me), TargetGUID)) - pTarget->RemoveAurasDueToSpell(SPELL_PARALYZE); - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) return; - - if (me->getVictim()->GetTypeId() != TYPEID_PLAYER) return; // Only cast the below on players. - - if (!me->getVictim()->HasAura(SPELL_PARALYZE)) - { - TargetGUID = me->getVictim()->GetGUID(); - me->AddThreat(me->getVictim(), 10000000.0f); - DoCast(me->getVictim(), SPELL_PURPLE_BEAM, true); - DoCast(me->getVictim(), SPELL_PARALYZE, true); - } - // Kill our target if we're very close. - if (me->IsWithinDistInMap(me->getVictim(), 3)) - DoCast(me->getVictim(), SPELL_CONSUME_SOUL); - } -}; - -// Shadowfiends interact with Illidan, setting more targets in Illidan's hashmap -struct mob_parasitic_shadowfiendAI : public ScriptedAI -{ - mob_parasitic_shadowfiendAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint64 IllidanGUID; - uint32 CheckTimer; - - void Reset() - { - if (pInstance) - IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE); - else - IllidanGUID = 0; - - CheckTimer = 5000; - DoCast(me, SPELL_SHADOWFIEND_PASSIVE, true); - } - - void EnterCombat(Unit* /*who*/) { DoZoneInCombat(); } - - void DoMeleeAttackIfReady() - { - if (me->isAttackReady() && me->IsWithinMeleeRange(me->getVictim())) - { - if (!me->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND) - && !me->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) - { - if (Creature* illidan = Unit::GetCreature((*me),IllidanGUID))//summon only in 1. phase - if (CAST_AI(boss_illidan_stormrageAI, illidan->AI())->Phase == PHASE_NORMAL) - me->CastSpell(me->getVictim(), SPELL_PARASITIC_SHADOWFIEND2, true, 0, 0, IllidanGUID); //do not stack - } - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->getVictim()) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) - AttackStart(pTarget); - else - { - me->SetVisibility(VISIBILITY_OFF); - me->setDeathState(JUST_DIED); - return; - } - } - - if (CheckTimer <= diff) - { - GETUNIT(Illidan, IllidanGUID); - if (!Illidan || CAST_CRE(Illidan)->IsInEvadeMode()) - { - me->SetVisibility(VISIBILITY_OFF); - me->setDeathState(JUST_DIED); - return; - } else CheckTimer = 5000; - } else CheckTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct blade_of_azzinothAI : public NullCreatureAI -{ - blade_of_azzinothAI(Creature* c) : NullCreatureAI(c) {} - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_THROW_GLAIVE2 || spell->Id == SPELL_THROW_GLAIVE) - me->SetDisplayId(21431);//appear when hit by Illidan's glaive - } -}; - -void boss_illidan_stormrageAI::Reset() -{ - if (pInstance) - pInstance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); - - if (AkamaGUID) - { - if (GETCRE(Akama, AkamaGUID)) - { - if (!Akama->isAlive()) - Akama->Respawn(); - else - { - CAST_AI(npc_akama_illidanAI, Akama->AI())->EnterEvadeMode(); - Akama->GetMotionMaster()->MoveTargetedHome(); - CAST_AI(npc_akama_illidanAI, Akama->AI())->Reset(); - } - } - AkamaGUID = 0; - } - - MaievGUID = 0; - for (uint8 i = 0; i < 2; ++i) - { - FlameGUID[i] = 0; - GlaiveGUID[i] = 0; - } - - Phase = PHASE_ILLIDAN_NULL; - Event = EVENT_NULL; - Timer[EVENT_BERSERK] = 1500000; - - HoverPoint = 0; - TalkCount = 0; - FlightCount = 0; - TransformCount = 0; - - me->SetDisplayId(21135); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->setActive(false); - Summons.DespawnAll(); -} - -void boss_illidan_stormrageAI::JustSummoned(Creature* summon) -{ - Summons.Summon(summon); - switch(summon->GetEntry()) - { - case PARASITIC_SHADOWFIEND: - { - if (Phase == PHASE_TALK_SEQUENCE) - { - summon->SetVisibility(VISIBILITY_OFF); - summon->setDeathState(JUST_DIED); - return; - } - Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 999, true); - if (!pTarget || pTarget->HasAura(SPELL_PARASITIC_SHADOWFIEND) - || pTarget->HasAura(SPELL_PARASITIC_SHADOWFIEND2)) - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true); - if (pTarget) - summon->AI()->AttackStart(pTarget); - } - break; - case SHADOW_DEMON: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true)) // only on players. - { - summon->AddThreat(pTarget, 5000000.0f); - summon->AI()->AttackStart(pTarget); - } - break; - case MAIEV_SHADOWSONG: - { - summon->SetVisibility(VISIBILITY_OFF); // Leave her invisible until she has to talk - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - MaievGUID = summon->GetGUID(); - CAST_AI(boss_maievAI, summon->AI())->GetIllidanGUID(me->GetGUID()); - summon->AI()->DoAction(PHASE_TALK_SEQUENCE); - } - break; - case FLAME_OF_AZZINOTH: - { - summon->AI()->AttackStart(summon->SelectNearestTarget(999)); - } - break; - default: - break; - } -} - -void boss_illidan_stormrageAI::HandleTalkSequence() -{ - switch(TalkCount) - { - case 0: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - break; - case 8: - // Equip our warglaives! - SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_ID_OFF_HAND, EQUIP_NO_CHANGE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - break; - case 9: - if (GETCRE(Akama, AkamaGUID)) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->AddThreat(Akama, 100.0f); - CAST_AI(npc_akama_illidanAI, Akama->AI())->EnterPhase(PHASE_FIGHT_ILLIDAN); - EnterPhase(PHASE_NORMAL); - } - break; - case 10: - SummonMaiev(); - break; - case 11: - if (GETUNIT(Maiev, MaievGUID)) - { - Maiev->SetVisibility(VISIBILITY_ON); // Maiev is now visible - Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); // onoz she looks like she teleported! - Maiev->SetInFront(me); // Have her face us - me->SetInFront(Maiev); // Face her, so it's not rude =P - Maiev->GetMotionMaster()->MoveIdle(); - me->GetMotionMaster()->MoveIdle(); - } - break; - case 14: - if (GETCRE(Maiev, MaievGUID)) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - Maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - Maiev->AddThreat(me, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE - Maiev->AI()->AttackStart(me); // Force Maiev to attack us. - EnterPhase(PHASE_NORMAL_MAIEV); - } - break; - case 15: - DoCast(me, SPELL_DEATH); // Animate his kneeling + stun him - Summons.DespawnAll(); - break; - case 17: - if (GETUNIT(Akama, AkamaGUID)) - { - if (!me->IsWithinDistInMap(Akama, 15)) - { - float x, y, z; - me->GetPosition(x, y, z); - x += 10; y += 10; - Akama->GetMotionMaster()->Clear(false); - //Akama->GetMotionMaster()->MoveIdle(); - Akama->GetMap()->CreatureRelocation(me, x, y, z, 0.0f); - Akama->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_NONE, 0);//Illidan must not die until Akama arrives. - Akama->GetMotionMaster()->MoveChase(me); - } - } - break; - case 19: // Make Maiev leave - if (GETUNIT(Maiev, MaievGUID)) - { - Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); - Maiev->setDeathState(JUST_DIED); - me->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); - } - break; - case 21: // Kill ourself. - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - break; - default: - break; - } - if (Phase == PHASE_TALK_SEQUENCE) - Talk(TalkCount); // This function does most of the talking - ++TalkCount; -} - -void boss_illidan_stormrageAI::CastEyeBlast() -{ - me->InterruptNonMeleeSpells(false); - - me->MonsterYell(SAY_EYE_BLAST, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_EYE_BLAST); - - float distx, disty, dist[2]; - for (uint8 i = 0; i < 2; ++i) - { - distx = EyeBlast[i].x - HoverPosition[HoverPoint].x; - disty = EyeBlast[i].y - HoverPosition[HoverPoint].y; - dist[i] = distx * distx + disty * disty; - } - Locations initial = EyeBlast[dist[0] < dist[1] ? 0 : 1]; - for (uint8 i = 0; i < 2; ++i) - { - distx = GlaivePosition[i].x - HoverPosition[HoverPoint].x; - disty = GlaivePosition[i].y - HoverPosition[HoverPoint].y; - dist[i] = distx * distx + disty * disty; - } - Locations final = GlaivePosition[dist[0] < dist[1] ? 0 : 1]; - - final.x = 2 * final.x - initial.x; - final.y = 2 * final.y - initial.y; - - Creature* Trigger = me->SummonCreature(23069, initial.x, initial.y, initial.z, 0, TEMPSUMMON_TIMED_DESPAWN, 13000); - if (!Trigger) return; - - Trigger->SetSpeed(MOVE_WALK, 3); - Trigger->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z); - - //Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetUInt64Value(UNIT_FIELD_TARGET, Trigger->GetGUID()); - DoCast(Trigger, SPELL_EYE_BLAST); -} - -void boss_illidan_stormrageAI::SummonFlamesOfAzzinoth() -{ - me->MonsterYell(SAY_SUMMONFLAMES, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_SUMMONFLAMES); - - for (uint8 i = 0; i < 2; ++i) - { - if (GETUNIT(Glaive, GlaiveGUID[i])) - { - Creature* Flame = me->SummonCreature(FLAME_OF_AZZINOTH, GlaivePosition[i+2].x, GlaivePosition[i+2].y, GlaivePosition[i+2].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - if (Flame) - { - Flame->setFaction(me->getFaction()); // Just in case the database has it as a different faction - Flame->SetMeleeDamageSchool(SPELL_SCHOOL_FIRE); - FlameGUID[i] = Flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase - CAST_AI(flame_of_azzinothAI, Flame->AI())->SetGlaiveGUID(GlaiveGUID[i]); - Glaive->CastSpell(Flame, SPELL_AZZINOTH_CHANNEL, false); // Glaives do some random Beam type channel on it. - } - } - } -} - -void boss_illidan_stormrageAI::SummonMaiev() -{ - DoCast(me, SPELL_SHADOW_PRISON, true); - DoCast(me, 40403, true); - if (!MaievGUID) // If Maiev cannot be summoned, reset the encounter and post some errors to the console. - { - EnterEvadeMode(); - me->MonsterTextEmote(EMOTE_UNABLE_TO_SUMMON, 0); - error_log("SD2 ERROR: Unable to summon Maiev Shadowsong (entry: 23197). Check your database to see if you have the proper SQL for Maiev Shadowsong (entry: 23197)"); - } -} - -void boss_illidan_stormrageAI::EnterPhase(PhaseIllidan NextPhase) -{ - DoZoneInCombat(); - switch(NextPhase) - { - case PHASE_NORMAL: - case PHASE_NORMAL_2: - case PHASE_NORMAL_MAIEV: - AttackStart(me->getVictim()); - Timer[EVENT_TAUNT] = 32000; - Timer[EVENT_SHEAR] = 10000 + rand()%15 * 1000; - Timer[EVENT_FLAME_CRASH] = 20000; - Timer[EVENT_PARASITIC_SHADOWFIEND] = 25000; - Timer[EVENT_PARASITE_CHECK] = 0; - Timer[EVENT_DRAW_SOUL] = 30000; - if (NextPhase == PHASE_NORMAL) - break; - Timer[EVENT_AGONIZING_FLAMES] = 35000; - Timer[EVENT_TRANSFORM_NORMAL] = 60000; - if (NextPhase == PHASE_NORMAL_2) - break; - Timer[EVENT_ENRAGE] = 30000 + rand()%10 * 1000; - break; - case PHASE_FLIGHT: - Timer[EVENT_FIREBALL] = 1000; - if (!(rand()%4)) - Timer[EVENT_DARK_BARRAGE] = 10000; - Timer[EVENT_EYE_BLAST] = 10000 + rand()%15 * 1000; - Timer[EVENT_MOVE_POINT] = 20000 + rand()%20 * 1000; - break; - case PHASE_DEMON: - Timer[EVENT_SHADOW_BLAST] = 1000; - Timer[EVENT_FLAME_BURST] = 10000; - Timer[EVENT_SHADOWDEMON] = 30000; - Timer[EVENT_TRANSFORM_DEMON] = 60000; - AttackStart(me->getVictim()); - break; - case PHASE_TALK_SEQUENCE: - Timer[EVENT_TALK_SEQUENCE] = 100; - me->RemoveAllAuras(); - me->InterruptNonMeleeSpells(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->GetMotionMaster()->Clear(false); - me->AttackStop(); - break; - case PHASE_FLIGHT_SEQUENCE: - if (Phase == PHASE_NORMAL) //lift off - { - FlightCount = 1; - Timer[EVENT_FLIGHT_SEQUENCE] = 1; - me->RemoveAllAuras(); - me->InterruptNonMeleeSpells(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->GetMotionMaster()->Clear(false); - me->AttackStop(); - } - else //land - Timer[EVENT_FLIGHT_SEQUENCE] = 2000; - break; - case PHASE_TRANSFORM_SEQUENCE: - if (Phase == PHASE_DEMON) - Timer[EVENT_TRANSFORM_SEQUENCE] = 500; - else - { - TransformCount = 0; - Timer[EVENT_TRANSFORM_SEQUENCE] = 500; - me->MonsterYell(SAY_MORPH, LANG_UNIVERSAL, 0); - DoPlaySoundToSet(me, SOUND_MORPH); - } - me->GetMotionMaster()->Clear(); - me->AttackStop(); - break; - default: - break; - } - if (MaievGUID) - { - GETCRE(Maiev, MaievGUID); - if (Maiev && Maiev->isAlive()) - Maiev->AI()->DoAction(NextPhase); - } - Phase = NextPhase; - Event = EVENT_NULL; -} - -CreatureAI* GetAI_boss_illidan_stormrage(Creature* pCreature) -{ - return new boss_illidan_stormrageAI (pCreature); -} - -CreatureAI* GetAI_npc_akama_at_illidan(Creature* pCreature) -{ - return new npc_akama_illidanAI(pCreature); -} - -CreatureAI* GetAI_boss_maiev(Creature* pCreature) -{ - return new boss_maievAI (pCreature); -} - -CreatureAI* GetAI_mob_flame_of_azzinoth(Creature* pCreature) -{ - return new flame_of_azzinothAI (pCreature); -} - -CreatureAI* GetAI_cage_trap_trigger(Creature* pCreature) -{ - return new cage_trap_triggerAI (pCreature); -} - -CreatureAI* GetAI_shadow_demon(Creature* pCreature) -{ - return new shadow_demonAI (pCreature); -} - -CreatureAI* GetAI_blade_of_azzinoth(Creature* pCreature) -{ - return new blade_of_azzinothAI (pCreature); -} - -CreatureAI* GetAI_parasitic_shadowfiend(Creature* pCreature) -{ - return new mob_parasitic_shadowfiendAI (pCreature); -} - -void AddSC_boss_illidan() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_illidan_stormrage"; - newscript->GetAI = &GetAI_boss_illidan_stormrage; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_akama_illidan"; - newscript->GetAI = &GetAI_npc_akama_at_illidan; - newscript->pGossipHello = &GossipHello_npc_akama_at_illidan; - newscript->pGossipSelect = &GossipSelect_npc_akama_at_illidan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_maiev_shadowsong"; - newscript->GetAI = &GetAI_boss_maiev; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flame_of_azzinoth"; - newscript->GetAI = &GetAI_mob_flame_of_azzinoth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_blade_of_azzinoth"; - newscript->GetAI = &GetAI_blade_of_azzinoth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "gameobject_cage_trap"; - newscript->pGOHello = &GOHello_cage_trap; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_cage_trap_trigger"; - newscript->GetAI = &GetAI_cage_trap_trigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadow_demon"; - newscript->GetAI = &GetAI_shadow_demon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_parasitic_shadowfiend"; - newscript->GetAI = &GetAI_parasitic_shadowfiend; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp deleted file mode 100644 index 5949fc46511..00000000000 --- a/src/server/scripts/Outland/black_temple/boss_mother_shahraz.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mother_Shahraz -SD%Complete: 80 -SDComment: Saber Lash missing, Fatal Attraction slightly incorrect; need to damage only if affected players are within range of each other -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -//Speech'n'Sounds -#define SAY_TAUNT1 -1564018 -#define SAY_TAUNT2 -1564019 -#define SAY_TAUNT3 -1564020 -#define SAY_AGGRO -1564021 -#define SAY_SPELL1 -1564022 -#define SAY_SPELL2 -1564023 -#define SAY_SPELL3 -1564024 -#define SAY_SLAY1 -1564025 -#define SAY_SLAY2 -1564026 -#define SAY_ENRAGE -1564027 -#define SAY_DEATH -1564028 - -//Spells -#define SPELL_BEAM_SINISTER 40859 -#define SPELL_BEAM_VILE 40860 -#define SPELL_BEAM_WICKED 40861 -#define SPELL_BEAM_SINFUL 40827 -#define SPELL_ATTRACTION 40871 -#define SPELL_SILENCING_SHRIEK 40823 -#define SPELL_ENRAGE 23537 -#define SPELL_SABER_LASH 40810//43267 -#define SPELL_SABER_LASH_IMM 43690 -#define SPELL_TELEPORT_VISUAL 40869 -#define SPELL_BERSERK 45078 - -uint32 PrismaticAuras[]= -{ - 40880, // Shadow - 40882, // Fire - 40883, // Nature - 40891, // Arcane - 40896, // Frost - 40897, // Holy -}; - -struct Locations -{ - float x,y,z; -}; - -static Locations TeleportPoint[]= -{ - {959.996, 212.576, 193.843}, - {932.537, 231.813, 193.838}, - {958.675, 254.767, 193.822}, - {946.955, 201.316, 192.535}, - {944.294, 149.676, 197.551}, - {930.548, 284.888, 193.367}, - {965.997, 278.398, 195.777} -}; - -struct boss_shahrazAI : public ScriptedAI -{ - boss_shahrazAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 TargetGUID[3]; - uint32 BeamTimer; - uint32 BeamCount; - uint32 CurrentBeam; - uint32 PrismaticShieldTimer; - uint32 FatalAttractionTimer; - uint32 FatalAttractionExplodeTimer; - uint32 ShriekTimer; - uint32 SaberTimer; - uint32 RandomYellTimer; - uint32 EnrageTimer; - uint32 ExplosionCount; - - bool Enraged; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, NOT_STARTED); - - for (uint8 i = 0; i<3; ++i) - TargetGUID[i] = 0; - - BeamTimer = 20000; // Timers may be incorrect - BeamCount = 0; - CurrentBeam = 0; // 0 - Sinister, 1 - Vile, 2 - Wicked, 3 - Sinful - PrismaticShieldTimer = 0; - FatalAttractionTimer = 60000; - FatalAttractionExplodeTimer = 70000; - ShriekTimer = 30000; - SaberTimer = 35000; - RandomYellTimer = 70000 + rand()%41 * 1000; - EnrageTimer = 600000; - ExplosionCount = 0; - - Enraged = false; - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, IN_PROGRESS); - - DoZoneInCombat(); - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_MOTHERSHAHRAZEVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - void TeleportPlayers() - { - uint32 random = rand()%7; - float X = TeleportPoint[random].x; - float Y = TeleportPoint[random].y; - float Z = TeleportPoint[random].z; - for (uint8 i = 0; i < 3; ++i) - { - Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - TargetGUID[i] = pUnit->GetGUID(); - pUnit->CastSpell(pUnit, SPELL_TELEPORT_VISUAL, true); - DoTeleportPlayer(pUnit, X, Y, Z, pUnit->GetOrientation()); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !Enraged) - { - Enraged = true; - DoCast(me, SPELL_ENRAGE, true); - DoScriptText(SAY_ENRAGE, me); - } - - //Randomly cast one beam. - if (BeamTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (!pTarget || !pTarget->isAlive()) - return; - - BeamTimer = 9000; - - switch(CurrentBeam) - { - case 0: - DoCast(pTarget, SPELL_BEAM_SINISTER); - break; - case 1: - DoCast(pTarget, SPELL_BEAM_VILE); - break; - case 2: - DoCast(pTarget, SPELL_BEAM_WICKED); - break; - case 3: - DoCast(pTarget, SPELL_BEAM_SINFUL); - break; - } - ++BeamCount; - uint32 Beam = CurrentBeam; - if (BeamCount > 3) - while (CurrentBeam == Beam) - CurrentBeam = rand()%3; - - } else BeamTimer -= diff; - - // Random Prismatic Shield every 15 seconds. - if (PrismaticShieldTimer <= diff) - { - uint32 random = rand()%6; - if (PrismaticAuras[random]) - DoCast(me, PrismaticAuras[random]); - PrismaticShieldTimer = 15000; - } else PrismaticShieldTimer -= diff; - - // Select 3 random targets (can select same target more than once), teleport to a random location then make them cast explosions until they get away from each other. - if (FatalAttractionTimer <= diff) - { - ExplosionCount = 0; - - TeleportPlayers(); - - DoScriptText(RAND(SAY_SPELL2,SAY_SPELL3), me); - FatalAttractionExplodeTimer = 2000; - FatalAttractionTimer = 40000 + rand()%31 * 1000; - } else FatalAttractionTimer -= diff; - - if (FatalAttractionExplodeTimer <= diff) - { - // Just make them explode three times... they're supposed to keep exploding while they are in range, but it'll take too much code. I'll try to think of an efficient way for it later. - if (ExplosionCount < 3) - { - for (uint8 i = 0; i < 3; ++i) - { - Unit* pUnit = NULL; - if (TargetGUID[i]) - { - pUnit = Unit::GetUnit((*me), TargetGUID[i]); - if (pUnit) - pUnit->CastSpell(pUnit, SPELL_ATTRACTION, true); - TargetGUID[i] = 0; - } - } - - ++ExplosionCount; - FatalAttractionExplodeTimer = 1000; - } - else - { - FatalAttractionExplodeTimer = FatalAttractionTimer + 2000; - ExplosionCount = 0; - } - } else FatalAttractionExplodeTimer -= diff; - - if (ShriekTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCING_SHRIEK); - ShriekTimer = 25000+rand()%10 * 1000; - } else ShriekTimer -= diff; - - if (SaberTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SABER_LASH); - SaberTimer = 25000+rand()%10 * 1000; - } else SaberTimer -= diff; - - //Enrage - if (!me->HasAura(SPELL_BERSERK)) - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - DoScriptText(SAY_ENRAGE, me); - } else EnrageTimer -= diff; - - //Random taunts - if (RandomYellTimer <= diff) - { - DoScriptText(RAND(SAY_TAUNT1,SAY_TAUNT2,SAY_TAUNT3), me); - RandomYellTimer = 60000 + rand()%91 * 1000; - } else RandomYellTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_shahraz(Creature* pCreature) -{ - return new boss_shahrazAI (pCreature); -} - -void AddSC_boss_mother_shahraz() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_mother_shahraz"; - newscript->GetAI = &GetAI_boss_shahraz; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp deleted file mode 100644 index 3e019a8dc35..00000000000 --- a/src/server/scripts/Outland/black_temple/boss_reliquary_of_souls.cpp +++ /dev/null @@ -1,690 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Reliquary_of_Souls -SD%Complete: 90 -SDComment: -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" -#include "Spell.h" - -//Sound'n'speech -//Suffering -#define SUFF_SAY_FREED -1564047 -#define SUFF_SAY_AGGRO -1564048 -#define SUFF_SAY_SLAY1 -1564049 -#define SUFF_SAY_SLAY2 -1564050 -#define SUFF_SAY_SLAY3 -1564051 -#define SUFF_SAY_RECAP -1564052 -#define SUFF_SAY_AFTER -1564053 -#define SUFF_EMOTE_ENRAGE -1564054 - -//Desire -#define DESI_SAY_FREED -1564055 -#define DESI_SAY_SLAY1 -1564056 -#define DESI_SAY_SLAY2 -1564057 -#define DESI_SAY_SLAY3 -1564058 -#define DESI_SAY_SPEC -1564059 -#define DESI_SAY_RECAP -1564060 -#define DESI_SAY_AFTER -1564061 - -//Anger -#define ANGER_SAY_FREED -1564062 -#define ANGER_SAY_FREED2 -1564063 -#define ANGER_SAY_SLAY1 -1564064 -#define ANGER_SAY_SLAY2 -1564065 -#define ANGER_SAY_SPEC -1564066 -#define ANGER_SAY_BEFORE -1564067 -#define ANGER_SAY_DEATH -1564068 - -//Spells -#define AURA_OF_SUFFERING 41292 -#define AURA_OF_SUFFERING_ARMOR 42017 // linked aura, need core support -#define ESSENCE_OF_SUFFERING_PASSIVE 41296 // periodic trigger 41294 -#define ESSENCE_OF_SUFFERING_PASSIVE2 41623 -#define SPELL_FIXATE_TARGET 41294 // dummy, select target -#define SPELL_FIXATE_TAUNT 41295 // force taunt -#define SPELL_ENRAGE 41305 -#define SPELL_SOUL_DRAIN 41303 - -#define AURA_OF_DESIRE 41350 -#define AURA_OF_DESIRE_DAMAGE 41352 -#define SPELL_RUNE_SHIELD 41431 -#define SPELL_DEADEN 41410 -#define SPELL_SOUL_SHOCK 41426 - -#define AURA_OF_ANGER 41337 -#define SPELL_SELF_SEETHE 41364 // force cast 41520 -#define SPELL_ENEMY_SEETHE 41520 -#define SPELL_SOUL_SCREAM 41545 -#define SPELL_SPITE_TARGET 41376 // cast 41377 after 6 sec -#define SPELL_SPITE_DAMAGE 41377 - -#define ENSLAVED_SOUL_PASSIVE 41535 -#define SPELL_SOUL_RELEASE 41542 -#define SPELL_SUBMERGE 37550 //dropout 'head' - -#define CREATURE_ENSLAVED_SOUL 23469 -#define NUMBER_ENSLAVED_SOUL 8 - -struct Position2d -{ - float x,y; -}; - -static Position2d Coords[]= -{ - {450.4, 212.3}, - {542.1, 212.3}, - {542.1, 168.3}, - {542.1, 137.4}, - {450.4, 137.4}, - {450.4, 168.3} -}; - -struct npc_enslaved_soulAI : public ScriptedAI -{ - npc_enslaved_soulAI(Creature *c) : ScriptedAI(c) {} - - uint64 ReliquaryGUID; - - void Reset() {ReliquaryGUID = 0;} - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, ENSLAVED_SOUL_PASSIVE, true); - DoZoneInCombat(); - } - - void JustDied(Unit *killer); -}; - -struct boss_reliquary_of_soulsAI : public ScriptedAI -{ - boss_reliquary_of_soulsAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EssenceGUID = 0; - } - - ScriptedInstance* pInstance; - - uint64 EssenceGUID; - - uint32 Phase; - uint32 Counter; - uint32 Timer; - - uint32 SoulCount; - uint32 SoulDeathCount; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, NOT_STARTED); - - if (EssenceGUID) - { - if (Creature* Essence = Unit::GetCreature(*me, EssenceGUID)) - { - Essence->ForcedDespawn(); - } - EssenceGUID = 0; - } - - Phase = 0; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - me->RemoveAurasDueToSpell(SPELL_SUBMERGE); - } - - void EnterCombat(Unit* who) - { - me->AddThreat(who, 10000.0f); - DoZoneInCombat(); - if (pInstance) - pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, IN_PROGRESS); - - Phase = 1; - Counter = 0; - Timer = 0; - } - - bool SummonSoul() - { - uint32 random = rand()%6; - float x = Coords[random].x; - float y = Coords[random].y; - Creature* Soul = me->SummonCreature(CREATURE_ENSLAVED_SOUL, x, y, me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0); - if (!Soul) return false; - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - CAST_AI(npc_enslaved_soulAI, Soul->AI())->ReliquaryGUID = me->GetGUID(); - Soul->AI()->AttackStart(pTarget); - } else EnterEvadeMode(); - return true; - } - - void MergeThreatList(Creature *pTarget) - { - if (!pTarget) - return; - - std::list& m_threatlist = pTarget->getThreatManager().getThreatList(); - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit) - { - DoModifyThreatPercent(pUnit, -100); - float threat = pTarget->getThreatManager().getThreat(pUnit); - me->AddThreat(pUnit, threat); // This makes it so that the unit has the same amount of threat in Reliquary's threatlist as in the target creature's (One of the Essences). - } - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_RELIQUARYOFSOULSEVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!Phase) - return; - - if (me->getThreatManager().getThreatList().empty()) // Reset if event is begun and we don't have a threatlist - { - EnterEvadeMode(); - return; - } - - Creature* Essence = NULL; - if (EssenceGUID) - { - Essence = Unit::GetCreature(*me, EssenceGUID); - if (!Essence) - { - EnterEvadeMode(); - return; - } - } - - if (Timer <= diff) - { - switch(Counter) - { - case 0: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); // I R ANNNGRRRY! - DoStartNoMovement(me); - Timer = 3000; - break; - case 1: - Timer = 2800; - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_SUBMERGE); // Release the cube - DoCast(me, SPELL_SUBMERGE); - DoStartNoMovement(me); - break; - case 2: - Timer = 5000; - if (Creature* Summon = DoSpawnCreature(23417+Phase, 0, 0, 0, 0, TEMPSUMMON_DEAD_DESPAWN, 0)) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED); // Ribs: open - Summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_TOPAGGRO, 0)); - EssenceGUID = Summon->GetGUID(); - DoStartNoMovement(me); - } else EnterEvadeMode(); - break; - case 3: - Timer = 1000; - if (Phase == 3) - { - if (!Essence->isAlive()) - DoCast(me, 7, true); - else return; - } - else - { - if (Essence->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - { - MergeThreatList(Essence); - Essence->RemoveAllAuras(); - Essence->DeleteThreatList(); - Essence->GetMotionMaster()->MoveFollow(me,0.0f,0.0f); - } else return; - } - break; - case 4: - Timer = 1500; - if (Essence->IsWithinDistInMap(me, 10)) - { - Essence->SetUInt32Value(UNIT_NPC_EMOTESTATE,374); //rotate and disappear - Timer = 2000; - me->RemoveAurasDueToSpell(SPELL_SUBMERGE); - } - else - { - MergeThreatList(Essence); - Essence->RemoveAllAuras(); - Essence->DeleteThreatList(); - Essence->GetMotionMaster()->MoveFollow(me, 0, 0); - return; - } - break; - case 5: - if (Phase == 1) - { - DoScriptText(SUFF_SAY_AFTER, Essence); - } - else - { - DoScriptText(DESI_SAY_AFTER, Essence); - } - Essence->ForcedDespawn(); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE,0); - EssenceGUID = 0; - SoulCount = 0; - SoulDeathCount = 0; - Timer = 3000; - break; - case 6: - if (SoulCount < NUMBER_ENSLAVED_SOUL) - { - if (SummonSoul()) - ++SoulCount; - Timer = 500; - return; - } - break; - case 7: - if (SoulDeathCount >= SoulCount) - { - Counter = 1; - ++Phase; - Timer = 5000; - } - return; - default: - break; - } - ++Counter; - } else Timer -= diff; - } -}; - -struct boss_essence_of_sufferingAI : public ScriptedAI -{ - boss_essence_of_sufferingAI(Creature *c) : ScriptedAI(c) {} - - uint64 StatAuraGUID; - - uint32 AggroYellTimer; - uint32 FixateTimer; - uint32 EnrageTimer; - uint32 SoulDrainTimer; - uint32 AuraTimer; - - void Reset() - { - StatAuraGUID = 0; - - AggroYellTimer = 5000; - FixateTimer = 8000; - EnrageTimer = 30000; - SoulDrainTimer = 45000; - AuraTimer = 5000; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - damage = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->Yell(SUFF_SAY_RECAP,LANG_UNIVERSAL,0); - DoScriptText(SUFF_SAY_RECAP, me); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - { - DoScriptText(SUFF_SAY_FREED, me); - DoZoneInCombat(); - DoCast(me, AURA_OF_SUFFERING, true); // linked aura need core support - DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE, true); - DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE2, true); - } - else return; - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SUFF_SAY_SLAY1,SUFF_SAY_SLAY2,SUFF_SAY_SLAY3), me); - } - - void CastFixate() - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - if (m_threatlist.empty()) - return; // No point continuing if empty threatlist. - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) // Only alive players - targets.push_back(pUnit); - } - if (targets.empty()) - return; // No targets added for some reason. No point continuing. - targets.sort(Trinity::ObjectDistanceOrderPred(me)); // Sort players by distance. - targets.resize(1); // Only need closest target. - Unit *pTarget = targets.front(); // Get the first target. - if (pTarget) - pTarget->CastSpell(me, SPELL_FIXATE_TAUNT, true); - DoResetThreat(); - me->AddThreat(pTarget,1000000); - } - - void UpdateAI(const uint32 diff) - { - if (me->isInCombat()) - { - //Supposed to be cast on nearest target - if (FixateTimer <= diff) - { - CastFixate(); - FixateTimer = 5000; - if (!(rand()%16)) - { - DoScriptText(SUFF_SAY_AGGRO, me); - } - } else FixateTimer -= diff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - EnrageTimer = 60000; - DoScriptText(SUFF_EMOTE_ENRAGE, me); - } else EnrageTimer -= diff; - - if (SoulDrainTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SOUL_DRAIN); - SoulDrainTimer = 60000; - } else SoulDrainTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_essence_of_desireAI : public ScriptedAI -{ - boss_essence_of_desireAI(Creature *c) : ScriptedAI(c) {} - - uint32 RuneShieldTimer; - uint32 DeadenTimer; - uint32 SoulShockTimer; - - void Reset() - { - RuneShieldTimer = 60000; - DeadenTimer = 30000; - SoulShockTimer = 5000; - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_CONFUSE, true); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by == me) - return; - - if (damage >= me->GetHealth()) - { - damage = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoScriptText(SUFF_SAY_RECAP, me); - } - else - { - int32 bp0 = damage / 2; - me->CastCustomSpell(done_by, AURA_OF_DESIRE_DAMAGE, &bp0, NULL, NULL, true); - } - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)) - for (uint8 i = 0; i < 3; ++i) - if (spell->Effect[i] == SPELL_EFFECT_INTERRUPT_CAST) - if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_SOUL_SHOCK - || me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_DEADEN) - me->InterruptSpell(CURRENT_GENERIC_SPELL, false); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(DESI_SAY_FREED, me); - DoZoneInCombat(); - DoCast(me, AURA_OF_DESIRE, true); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(DESI_SAY_SLAY1,DESI_SAY_SLAY2,DESI_SAY_SLAY3), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (RuneShieldTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_RUNE_SHIELD, true); - SoulShockTimer += 2000; - DeadenTimer += 2000; - RuneShieldTimer = 60000; - } else RuneShieldTimer -= diff; - - if (SoulShockTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOUL_SHOCK); - SoulShockTimer = 5000; - } else SoulShockTimer -= diff; - - if (DeadenTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me->getVictim(), SPELL_DEADEN); - DeadenTimer = 25000 + rand()%10000; - if (!(rand()%2)) - { - DoScriptText(DESI_SAY_SPEC, me); - } - } else DeadenTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_essence_of_angerAI : public ScriptedAI -{ - boss_essence_of_angerAI(Creature *c) : ScriptedAI(c) {} - - uint64 AggroTargetGUID; - - uint32 CheckTankTimer; - uint32 SoulScreamTimer; - uint32 SpiteTimer; - - std::list SpiteTargetGUID; - - bool CheckedAggro; - - void Reset() - { - AggroTargetGUID = 0; - - CheckTankTimer = 5000; - SoulScreamTimer = 10000; - SpiteTimer = 30000; - - SpiteTargetGUID.clear(); - - CheckedAggro = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(ANGER_SAY_FREED,ANGER_SAY_FREED2), me); - - DoZoneInCombat(); - DoCast(me, AURA_OF_ANGER, true); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(ANGER_SAY_DEATH, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(ANGER_SAY_SLAY1,ANGER_SAY_SLAY2), me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!CheckedAggro) - { - AggroTargetGUID = me->getVictim()->GetGUID(); - CheckedAggro = true; - } - - if (CheckTankTimer <= diff) - { - if (me->getVictim()->GetGUID() != AggroTargetGUID) - { - DoScriptText(ANGER_SAY_BEFORE, me); - DoCast(me, SPELL_SELF_SEETHE, true); - AggroTargetGUID = me->getVictim()->GetGUID(); - } - CheckTankTimer = 2000; - } else CheckTankTimer -= diff; - - if (SoulScreamTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOUL_SCREAM); - SoulScreamTimer = 9000 + rand()%2000; - if (!(rand()%3)) - { - DoScriptText(ANGER_SAY_SPEC, me); - } - } else SoulScreamTimer -= diff; - - if (SpiteTimer <= diff) - { - DoCast(me, SPELL_SPITE_TARGET); - SpiteTimer = 30000; - DoScriptText(ANGER_SAY_SPEC, me); - } else SpiteTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -void npc_enslaved_soulAI::JustDied(Unit * /*killer*/) -{ - if (ReliquaryGUID) - if (Creature *Reliquary = (Unit::GetCreature((*me), ReliquaryGUID))) - ++(CAST_AI(boss_reliquary_of_soulsAI, Reliquary->AI())->SoulDeathCount); - - DoCast(me, SPELL_SOUL_RELEASE, true); -} - -CreatureAI* GetAI_boss_reliquary_of_souls(Creature* pCreature) -{ - return new boss_reliquary_of_soulsAI (pCreature); -} - -CreatureAI* GetAI_boss_essence_of_suffering(Creature* pCreature) -{ - return new boss_essence_of_sufferingAI (pCreature); -} - -CreatureAI* GetAI_boss_essence_of_desire(Creature* pCreature) -{ - return new boss_essence_of_desireAI (pCreature); -} - -CreatureAI* GetAI_boss_essence_of_anger(Creature* pCreature) -{ - return new boss_essence_of_angerAI (pCreature); -} - -CreatureAI* GetAI_npc_enslaved_soul(Creature* pCreature) -{ - return new npc_enslaved_soulAI (pCreature); -} - -void AddSC_boss_reliquary_of_souls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_reliquary_of_souls"; - newscript->GetAI = &GetAI_boss_reliquary_of_souls; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_essence_of_suffering"; - newscript->GetAI = &GetAI_boss_essence_of_suffering; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_essence_of_desire"; - newscript->GetAI = &GetAI_boss_essence_of_desire; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_essence_of_anger"; - newscript->GetAI = &GetAI_boss_essence_of_anger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_enslaved_soul"; - newscript->GetAI = &GetAI_npc_enslaved_soul; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp deleted file mode 100644 index 94f88d5715c..00000000000 --- a/src/server/scripts/Outland/black_temple/boss_shade_of_akama.cpp +++ /dev/null @@ -1,871 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Shade_of_Akama -SD%Complete: 90 -SDComment: Seems to be complete. -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -#define SAY_DEATH -1564013 -#define SAY_LOW_HEALTH -1564014 -// Ending cinematic text -#define SAY_FREE -1564015 -#define SAY_BROKEN_FREE_01 -1564016 -#define SAY_BROKEN_FREE_02 -1564017 - -#define GOSSIP_ITEM "We are ready to fight alongside you, Akama" - -struct Location -{ - float x, y, o, z; -}; - -static Location ChannelerLocations[]= -{ - {463.161285, 401.219757, 3.141592}, - {457.377625, 391.227661, 2.106461}, - {446.012421, 391.227661, 1.071904}, - {439.533783, 401.219757, 0.000000}, - {446.012421, 411.211853, 5.210546}, - {457.377625, 411.211853, 4.177494} -}; - -static Location SpawnLocations[]= -{ - {498.652740, 461.728119, 0}, - {498.505003, 339.619324, 0} -}; - -static Location AkamaWP[]= -{ - {482.352448, 401.162720, 0, 112.783928}, - {469.597443, 402.264404, 0, 118.537910} -}; - -static Location BrokenCoords[]= -{ - {541.375916, 401.439575, M_PI, 112.783997}, // The place where Akama channels - {534.130005, 352.394531, 2.164150, 112.783737}, // Behind a 'pillar' which is behind the east alcove - {499.621185, 341.534729, 1.652856, 112.783730}, // East Alcove - {499.151093, 461.036438, 4.770888, 112.78370}, // West Alcove -}; - -static Location BrokenWP[]= -{ - {492.491638, 400.744690, 3.122336, 112.783737}, - {494.335724, 382.221771, 2.676230, 112.783737}, - {489.555939, 373.507202, 2.416263, 112.783737}, - {491.136353, 427.868774, 3.519748, 112.783737}, -}; - -// Locations -#define Z1 118.543144 -#define Z2 120.783768 -#define Z_SPAWN 113.537949 -#define AGGRO_X 482.793182 -#define AGGRO_Y 401.270172 -#define AGGRO_Z 112.783928 -#define AKAMA_X 514.583984 -#define AKAMA_Y 400.601013 -#define AKAMA_Z 112.783997 - -// Spells -#define SPELL_VERTEX_SHADE_BLACK 39833 -#define SPELL_SHADE_SOUL_CHANNEL 40401 -#define SPELL_DESTRUCTIVE_POISON 40874 -#define SPELL_LIGHTNING_BOLT 42024 -#define SPELL_AKAMA_SOUL_CHANNEL 40447 -#define SPELL_AKAMA_SOUL_RETRIEVE 40902 -#define AKAMA_SOUL_EXPEL 40855 -#define SPELL_SHADE_SOUL_CHANNEL_2 40520 - -// Channeler entry -#define CREATURE_CHANNELER 23421 -#define CREATURE_SORCERER 23215 -#define CREATURE_DEFENDER 23216 -#define CREATURE_BROKEN 23319 - -const uint32 spawnEntries[4]= { 23523, 23318, 23524 }; - -struct mob_ashtongue_channelerAI : public ScriptedAI -{ - mob_ashtongue_channelerAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;} - - uint64 ShadeGUID; - - void Reset() {} - void JustDied(Unit* /*killer*/); - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -struct mob_ashtongue_sorcererAI : public ScriptedAI -{ - mob_ashtongue_sorcererAI(Creature* c) : ScriptedAI(c) {ShadeGUID = 0;} - - uint64 ShadeGUID; - uint32 CheckTimer; - bool StartBanishing; - - void Reset() - { - StartBanishing = false; - CheckTimer = 5000; - } - - void JustDied(Unit* /*killer*/); - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (StartBanishing) - return; - - if (CheckTimer <= diff) - { - Creature* Shade = Unit::GetCreature((*me), ShadeGUID); - if (Shade && Shade->isAlive() && me->isAlive()) - { - if (me->IsWithinDist(Shade, 20,false)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL, true); - DoCast(Shade, SPELL_SHADE_SOUL_CHANNEL_2, true); - - StartBanishing = true; - } - } - CheckTimer = 2000; - } else CheckTimer -= diff; - } -}; - -struct boss_shade_of_akamaAI : public ScriptedAI -{ - boss_shade_of_akamaAI(Creature* c) : ScriptedAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - AkamaGUID = pInstance ? pInstance->GetData64(DATA_AKAMA_SHADE) : 0; - me->setActive(true);//if view distance is too low - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); - } - - ScriptedInstance* pInstance; - - std::list Channelers; - std::list Sorcerers; - uint64 AkamaGUID; - - uint32 SorcererCount; - uint32 DeathCount; - - uint32 ReduceHealthTimer; - uint32 SummonTimer; - uint32 ResetTimer; - uint32 DefenderTimer; // They are on a flat 15 second timer, independant of the other summon Creature timer. - - bool IsBanished; - bool HasKilledAkama; - bool reseting; - bool GridSearcherSucceeded; - bool HasKilledAkamaAndReseting; - SummonList summons; - - void Reset() - { - reseting = true; - HasKilledAkamaAndReseting = false; - - GridSearcherSucceeded = false; - - Sorcerers.clear(); - summons.DespawnAll();//despawn all adds - - if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) - { - Akama->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//turn gossip on so players can restart the event - if (Akama->isDead()) - { - Akama->Respawn();//respawn akama if dead - Akama->AI()->EnterEvadeMode(); - } - } - SorcererCount = 0; - DeathCount = 0; - - SummonTimer = 10000; - ReduceHealthTimer = 0; - ResetTimer = 60000; - DefenderTimer = 15000; - - IsBanished = true; - HasKilledAkama = false; - - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //me->GetMotionMaster()->Clear(); - //me->GetMotionMaster()->MoveIdle(); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); - - if (pInstance) - pInstance->SetData(DATA_SHADEOFAKAMAEVENT, NOT_STARTED); - - reseting = false; - } - void JustDied(Unit* /*killer*/) - { - summons.DespawnAll(); - } - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524) - summons.Summon(summon); - } - void SummonedCreatureDespawn(Creature *summon) - { - if (summon->GetEntry() == CREATURE_DEFENDER || summon->GetEntry() == 23523 || summon->GetEntry() == 23318 || summon->GetEntry() == 23524) - summons.Despawn(summon); - } - - void MoveInLineOfSight(Unit * /*who*/) - { - if (!GridSearcherSucceeded) - { - FindChannelers(); - - if (!Channelers.empty()) - { - for (std::list::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - { - Creature* Channeler = (Unit::GetCreature(*me, *itr)); - if (Channeler) - { - if (Channeler->isDead()) - { - Channeler->RemoveCorpse(); - Channeler->Respawn(); - } - - Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL, true); - Channeler->CastSpell(me, SPELL_SHADE_SOUL_CHANNEL_2, true); - Channeler->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - GridSearcherSucceeded = true; - } - } - } else error_log("SD2 ERROR: No Channelers are stored in the list. This encounter will not work properly"); - } - } - - void AttackStart(Unit* who) - { - if (!who || IsBanished) return; - - if (who->isTargetableForAttack() && who != me) - DoStartMovement(who); - } - - void IncrementDeathCount(uint64 guid = 0) // If guid is set, will remove it from list of sorcerer - { - if (reseting) - return; - - debug_log("TSCR: Increasing Death Count for Shade of Akama encounter"); - ++DeathCount; - me->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2); - if (guid) - { - if (Sorcerers.empty()) - error_log("SD2 ERROR: Shade of Akama - attempt to remove guid %u from Sorcerers list but list is already empty", guid); - else Sorcerers.remove(guid); - } - } - - void SummonCreature() - { - uint32 random = rand()%2; - float X = SpawnLocations[random].x; - float Y = SpawnLocations[random].y; - // max of 6 sorcerers can be summoned - if ((rand()%3 == 0) && (DeathCount > 0) && (SorcererCount < 7)) - { - Creature* Sorcerer = me->SummonCreature(CREATURE_SORCERER, X, Y, Z_SPAWN, 0, TEMPSUMMON_DEAD_DESPAWN, 0); - if (Sorcerer) - { - CAST_AI(mob_ashtongue_sorcererAI, Sorcerer->AI())->ShadeGUID = me->GetGUID(); - Sorcerer->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Sorcerer->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); - Sorcerer->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - Sorcerers.push_back(Sorcerer->GetGUID()); - --DeathCount; - ++SorcererCount; - } - } - else - { - for (uint8 i = 0; i < 3; ++i) - { - Creature* Spawn = me->SummonCreature(spawnEntries[i], X, Y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); - if (Spawn) - { - Spawn->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Spawn->GetMotionMaster()->MovePoint(0, AGGRO_X, AGGRO_Y, AGGRO_Z); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - Spawn->AI()->AttackStart(pTarget); - } - } - } - } - - void FindChannelers() - { - std::list ChannelerList; - me->GetCreatureListWithEntryInGrid(ChannelerList,CREATURE_CHANNELER,50.0f); - - if (!ChannelerList.empty()) - { - for (std::list::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr) - { - CAST_AI(mob_ashtongue_channelerAI, (*itr)->AI())->ShadeGUID = me->GetGUID(); - Channelers.push_back((*itr)->GetGUID()); - debug_log("TSCR: Shade of Akama Grid Search found channeler %u. Adding to list", (*itr)->GetGUID()); - } - } - else error_log("SD2 ERROR: Grid Search was unable to find any channelers. Shade of Akama encounter will be buggy"); - } - - void SetSelectableChannelers() - { - if (Channelers.empty()) - { - error_log("SD2 ERROR: Channeler List is empty, Shade of Akama encounter will be buggy"); - return; - } - - for (std::list::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - if (Creature* Channeler = (Unit::GetCreature(*me, *itr))) - Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void SetAkamaGUID(uint64 guid) { AkamaGUID = guid; } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; - - if (IsBanished) - { - // Akama is set in the threatlist so when we reset, we make sure that he is not included in our check - if (me->getThreatManager().getThreatList().size() < 2) - { - EnterEvadeMode(); - return; - } - - if (DefenderTimer <= diff) - { - uint32 ran = rand()%2; - Creature* Defender = me->SummonCreature(CREATURE_DEFENDER, SpawnLocations[ran].x, SpawnLocations[ran].y, Z_SPAWN, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 25000); - if (Defender) - { - Defender->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - bool move = true; - if (AkamaGUID) - { - if (Creature* Akama = Unit::GetCreature(*me, AkamaGUID)) - { - float x, y, z; - Akama->GetPosition(x,y,z); - // They move towards AKama - Defender->GetMotionMaster()->MovePoint(0, x, y, z); - Defender->AI()->AttackStart(Akama); - } else move = false; - } else move = false; - if (!move) - Defender->GetMotionMaster()->MovePoint(0, AKAMA_X, AKAMA_Y, AKAMA_Z); - } - DefenderTimer = 15000; - } else DefenderTimer -= diff; - - if (SummonTimer <= diff) - { - SummonCreature(); - SummonTimer = 35000; - } else SummonTimer -= diff; - - if (DeathCount >= 6) - { - if (AkamaGUID) - { - Creature* Akama = Unit::GetCreature((*me), AkamaGUID); - if (Akama && Akama->isAlive()) - { - IsBanished = false; - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveChase(Akama); - Akama->GetMotionMaster()->Clear(); - // Shade should move to Akama, not the other way around - Akama->GetMotionMaster()->MoveIdle(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // Crazy amount of threat - me->AddThreat(Akama, 10000000.0f); - Akama->AddThreat(me, 10000000.0f); - me->Attack(Akama, true); - Akama->Attack(me, true); - } - } - } - } - else // No longer banished, let's fight Akama now - { - if (ReduceHealthTimer <= diff) - { - if (AkamaGUID) - { - Creature* Akama = Unit::GetCreature((*me), AkamaGUID); - if (Akama && Akama->isAlive()) - { - //10 % less health every few seconds. - me->DealDamage(Akama, Akama->GetMaxHealth()/10, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - ReduceHealthTimer = 12000; - } - } - } else ReduceHealthTimer -= diff; - - if (HasKilledAkama) - { - if (!HasKilledAkamaAndReseting)//do not let players kill Shade if Akama is dead and Shade is waiting for ResetTimer!! event would bug - { - HasKilledAkamaAndReseting = true; - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(); - //me->SetHealth(me->GetMaxHealth()); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->GetMotionMaster()->MoveTargetedHome(); - } - if (ResetTimer <= diff) - { - EnterEvadeMode();// Reset a little while after killing Akama, evade and respawn Akama - return; - } else ResetTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - } -}; - -void mob_ashtongue_channelerAI::JustDied(Unit* /*killer*/) -{ - Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); - if (Shade && Shade->isAlive()) - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(); - else error_log("SD2 ERROR: Channeler dead but unable to increment DeathCount for Shade of Akama."); -} - -void mob_ashtongue_sorcererAI::JustDied(Unit* /*killer*/) -{ - Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); - if (Shade && Shade->isAlive()) - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IncrementDeathCount(me->GetGUID()); - else error_log("SD2 ERROR: Sorcerer dead but unable to increment DeathCount for Shade of Akama."); -} - -struct npc_akamaAI : public ScriptedAI -{ - npc_akamaAI(Creature* c) : ScriptedAI(c), summons(me) - { - ShadeHasDied = false; - StartCombat = false; - pInstance = c->GetInstanceData(); - ShadeGUID = pInstance ? pInstance->GetData64(DATA_SHADEOFAKAMA) : NOT_STARTED; - me->setActive(true); - EventBegun = false; - CastSoulRetrieveTimer = 0; - SoulRetrieveTimer = 0; - SummonBrokenTimer = 0; - EndingTalkCount = 0; - WayPointId = 0; - BrokenSummonIndex = 0; - BrokenList.clear(); - HasYelledOnce = false; - } - - ScriptedInstance* pInstance; - - uint64 ShadeGUID; - - uint32 DestructivePoisonTimer; - uint32 LightningBoltTimer; - uint32 CheckTimer; - uint32 CastSoulRetrieveTimer; - uint32 SoulRetrieveTimer; - uint32 SummonBrokenTimer; - uint32 EndingTalkCount; - uint32 WayPointId; - uint32 BrokenSummonIndex; - - std::list BrokenList; - - bool EventBegun; - bool ShadeHasDied; - bool StartCombat; - bool HasYelledOnce; - SummonList summons; - - void Reset() - { - DestructivePoisonTimer = 15000; - LightningBoltTimer = 10000; - CheckTimer = 2000; - - if (!EventBegun) - { - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has very very strange values - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - summons.DespawnAll(); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == CREATURE_BROKEN) - summons.Summon(summon); - } - void SummonedCreatureDespawn(Creature *summon) - { - if (summon->GetEntry() == CREATURE_BROKEN) - summons.Despawn(summon); - } - - void EnterCombat(Unit* /*who*/) {} - - void BeginEvent(Player* pl) - { - if (!pInstance) - return; - - ShadeGUID = pInstance->GetData64(DATA_SHADEOFAKAMA); - if (!ShadeGUID) - return; - - Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); - if (Shade) - { - pInstance->SetData(DATA_SHADEOFAKAMAEVENT, IN_PROGRESS); - // Prevent players from trying to restart event - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->SetAkamaGUID(me->GetGUID()); - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->SetSelectableChannelers(); - Shade->AddThreat(me, 1000000.0f); - me->CombatStart(Shade); - Shade->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - Shade->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (pl) Shade->AddThreat(pl, 1.0f); - DoZoneInCombat(Shade); - EventBegun = true; - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - switch(id) - { - case 0: ++WayPointId; break; - - case 1: - if (Creature* Shade = Unit::GetCreature(*me, ShadeGUID)) - { - me->SetUInt64Value(UNIT_FIELD_TARGET, ShadeGUID); - DoCast(Shade, SPELL_AKAMA_SOUL_RETRIEVE); - EndingTalkCount = 0; - SoulRetrieveTimer = 16000; - } - break; - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - EventBegun = false; - ShadeHasDied = false; - StartCombat = false; - CastSoulRetrieveTimer = 0; - SoulRetrieveTimer = 0; - SummonBrokenTimer = 0; - EndingTalkCount = 0; - WayPointId = 0; - BrokenSummonIndex = 0; - BrokenList.clear(); - HasYelledOnce = false; - Creature* Shade = Unit::GetCreature((*me), ShadeGUID); - if (Shade && Shade->isAlive()) - CAST_AI(boss_shade_of_akamaAI, Shade->AI())->HasKilledAkama = true; - summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!EventBegun) - return; - - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 15 && !HasYelledOnce) - { - DoScriptText(SAY_LOW_HEALTH, me); - HasYelledOnce = true; - } - - if (ShadeGUID && !StartCombat) - { - Creature* Shade = (Unit::GetCreature((*me), ShadeGUID)); - if (Shade && Shade->isAlive()) - { - if (CAST_AI(boss_shade_of_akamaAI, Shade->AI())->IsBanished) - { - if (CastSoulRetrieveTimer <= diff) - { - DoCast(Shade, SPELL_AKAMA_SOUL_CHANNEL); - CastSoulRetrieveTimer = 500; - } else CastSoulRetrieveTimer -= diff; - } - else - { - me->InterruptNonMeleeSpells(false); - StartCombat = true; - } - } - } - - if (ShadeHasDied && (WayPointId == 1)) - { - if (pInstance) - pInstance->SetData(DATA_SHADEOFAKAMAEVENT, DONE); - me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[1].x, AkamaWP[1].y, AkamaWP[1].z); - ++WayPointId; - } - - if (!ShadeHasDied && StartCombat) - { - if (CheckTimer <= diff) - { - if (ShadeGUID) - { - Creature* Shade = Unit::GetCreature((*me), ShadeGUID); - if (Shade && !Shade->isAlive()) - { - ShadeHasDied = true; - WayPointId = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->MovePoint(WayPointId, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z); - } - if (Shade && Shade->isAlive()) - { - if (Shade->getThreatManager().getThreatList().size() < 2) - Shade->AI()->EnterEvadeMode(); - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - } - - if (SummonBrokenTimer && BrokenSummonIndex < 4) - { - if (SummonBrokenTimer <= diff) - { - for (uint8 i = 0; i < 4; ++i) - { - float x = BrokenCoords[BrokenSummonIndex].x + (i*5); - float y = BrokenCoords[BrokenSummonIndex].y + (1*5); - float z = BrokenCoords[BrokenSummonIndex].z; - float o = BrokenCoords[BrokenSummonIndex].o; - Creature* Broken = me->SummonCreature(CREATURE_BROKEN, x, y, z, o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000); - if (Broken) - { - float wx = BrokenWP[BrokenSummonIndex].x + (i*5); - float wy = BrokenWP[BrokenSummonIndex].y + (i*5); - float wz = BrokenWP[BrokenSummonIndex].z; - Broken->GetMotionMaster()->MovePoint(0, wx, wy, wz); - Broken->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - BrokenList.push_back(Broken->GetGUID()); - } - } - ++BrokenSummonIndex; - SummonBrokenTimer = 1000; - } else SummonBrokenTimer -= diff; - } - - if (SoulRetrieveTimer) - if (SoulRetrieveTimer <= diff) - { - switch(EndingTalkCount) - { - case 0: - me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); - ++EndingTalkCount; - SoulRetrieveTimer = 2000; - SummonBrokenTimer = 1; - break; - case 1: - DoScriptText(SAY_FREE, me); - ++EndingTalkCount; - SoulRetrieveTimer = 25000; - break; - case 2: - if (!BrokenList.empty()) - { - bool Yelled = false; - for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if (Creature* pUnit = Unit::GetCreature(*me, *itr)) - { - if (!Yelled) - { - DoScriptText(SAY_BROKEN_FREE_01, pUnit); - Yelled = true; - } - pUnit->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); - } - } - ++EndingTalkCount; - SoulRetrieveTimer = 1500; - break; - case 3: - if (!BrokenList.empty()) - { - for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if (Creature* pUnit = Unit::GetCreature(*me, *itr)) - // This is the incorrect spell, but can't seem to find the right one. - pUnit->CastSpell(pUnit, 39656, true); - } - ++EndingTalkCount; - SoulRetrieveTimer = 5000; - break; - case 4: - if (!BrokenList.empty()) - { - for (std::list::const_iterator itr = BrokenList.begin(); itr != BrokenList.end(); ++itr) - if (Creature* pUnit = Unit::GetCreature((*me), *itr)) - pUnit->MonsterYell(SAY_BROKEN_FREE_02, LANG_UNIVERSAL, 0); - } - SoulRetrieveTimer = 0; - break; - } - } else SoulRetrieveTimer -= diff; - - if (!UpdateVictim()) - return; - - if (DestructivePoisonTimer <= diff) - { - Creature* Shade = Unit::GetCreature((*me), ShadeGUID); - if (Shade && Shade->isAlive()) - DoCast(Shade, SPELL_DESTRUCTIVE_POISON); - DestructivePoisonTimer = 15000; - } else DestructivePoisonTimer -= diff; - - if (LightningBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); - LightningBoltTimer = 10000; - } else LightningBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_shade_of_akama(Creature* pCreature) -{ - return new boss_shade_of_akamaAI (pCreature); -} - -CreatureAI* GetAI_mob_ashtongue_channeler(Creature* pCreature) -{ - return new mob_ashtongue_channelerAI (pCreature); -} - -CreatureAI* GetAI_mob_ashtongue_sorcerer(Creature* pCreature) -{ - return new mob_ashtongue_sorcererAI (pCreature); -} - -CreatureAI* GetAI_npc_akama_shade(Creature* pCreature) -{ - return new npc_akamaAI (pCreature); -} - -bool GossipSelect_npc_akama(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_akamaAI, pCreature->AI())->BeginEvent(pPlayer); - } - - return true; -} - -bool GossipHello_npc_akama(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->isAlive()) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - } - - return true; -} - -void AddSC_boss_shade_of_akama() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shade_of_akama"; - newscript->GetAI = &GetAI_boss_shade_of_akama; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ashtongue_channeler"; - newscript->GetAI = &GetAI_mob_ashtongue_channeler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ashtongue_sorcerer"; - newscript->GetAI = &GetAI_mob_ashtongue_sorcerer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_akama_shade"; - newscript->GetAI = &GetAI_npc_akama_shade; - newscript->pGossipHello = &GossipHello_npc_akama; - newscript->pGossipSelect = &GossipSelect_npc_akama; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/boss_supremus.cpp b/src/server/scripts/Outland/black_temple/boss_supremus.cpp deleted file mode 100644 index bc1ea3ec673..00000000000 --- a/src/server/scripts/Outland/black_temple/boss_supremus.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Supremus -SD%Complete: 95 -SDComment: Need to implement molten punch -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -#define EMOTE_NEW_TARGET -1564010 -#define EMOTE_PUNCH_GROUND -1564011 //DoScriptText(EMOTE_PUNCH_GROUND, me); -#define EMOTE_GROUND_CRACK -1564012 - -//Spells -#define SPELL_MOLTEN_PUNCH 40126 -#define SPELL_HATEFUL_STRIKE 41926 -#define SPELL_MOLTEN_FLAME 40980 -#define SPELL_VOLCANIC_ERUPTION 40117 -#define SPELL_VOLCANIC_SUMMON 40276 -#define SPELL_BERSERK 45078 - -#define CREATURE_VOLCANO 23085 -#define CREATURE_STALKER 23095 - -#define PHASE_STRIKE 1 -#define PHASE_CHASE 2 - -#define EVENT_BERSERK 1 -#define EVENT_SWITCH_PHASE 2 -#define EVENT_FLAME 3 -#define EVENT_VOLCANO 4 -#define EVENT_SWITCH_TARGET 5 -#define EVENT_HATEFUL_STRIKE 6 - -#define GCD_CAST 1 - -struct molten_flameAI : public NullCreatureAI -{ - molten_flameAI(Creature *c) : NullCreatureAI(c) {} - - void InitializeAI() - { - float x, y, z; - me->GetNearPoint(me, x, y, z, 1, 100, M_PI*2*rand_norm()); - me->GetMotionMaster()->MovePoint(0, x, y, z); - me->SetVisibility(VISIBILITY_OFF); - me->CastSpell(me,SPELL_MOLTEN_FLAME,true); - } -}; - -struct boss_supremusAI : public ScriptedAI -{ - boss_supremusAI(Creature *c) : ScriptedAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - SummonList summons; - uint32 phase; - - void Reset() - { - if (pInstance) - { - if (me->isAlive()) - { - pInstance->SetData(DATA_SUPREMUSEVENT, NOT_STARTED); - //ToggleDoors(true); - } - //else ToggleDoors(false); - } - - phase = 0; - - events.Reset(); - summons.DespawnAll(); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_SUPREMUSEVENT, IN_PROGRESS); - - ChangePhase(); - events.ScheduleEvent(EVENT_BERSERK, 900000, GCD_CAST); - events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST); - } - - void ChangePhase() - { - if (!phase || phase == PHASE_CHASE) - { - phase = PHASE_STRIKE; - summons.DoAction(EVENT_VOLCANO, 0); - events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); - me->SetSpeed(MOVE_RUN, 1.2f); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false); - } - else - { - phase = PHASE_CHASE; - events.ScheduleEvent(EVENT_VOLCANO, 5000, GCD_CAST, PHASE_CHASE); - events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); - me->SetSpeed(MOVE_RUN, 0.9f); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); - } - DoResetThreat(); - DoZoneInCombat(); - events.SetPhase(phase); - events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000, GCD_CAST); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_SUPREMUSEVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GAMEOBJECT_SUPREMUS_DOORS), true); - } - summons.DespawnAll(); - } - - void JustSummoned(Creature *summon) {summons.Summon(summon);} - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - - Unit* CalculateHatefulStrikeTarget() - { - uint32 health = 0; - Unit *pTarget = NULL; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - std::list::const_iterator i = m_threatlist.begin(); - for (i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && me->IsWithinMeleeRange(pUnit)) - { - if (pUnit->GetHealth() > health) - { - health = pUnit->GetHealth(); - pTarget = pUnit; - } - } - } - - return pTarget; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK, true); - break; - case EVENT_FLAME: - DoCast(me, SPELL_MOLTEN_PUNCH); - events.DelayEvents(1500, GCD_CAST); - events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST); - break; - case EVENT_HATEFUL_STRIKE: - if (Unit *pTarget = CalculateHatefulStrikeTarget()) - DoCast(pTarget, SPELL_HATEFUL_STRIKE); - events.DelayEvents(1000, GCD_CAST); - events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); - break; - case EVENT_SWITCH_TARGET: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - { - DoResetThreat(); - me->AddThreat(pTarget, 5000000.0f); - DoScriptText(EMOTE_NEW_TARGET, me); - } - events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); - break; - case EVENT_VOLCANO: - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 999, true); - if (!pTarget) pTarget = me->getVictim(); - if (pTarget) - { - //DoCast(pTarget, SPELL_VOLCANIC_SUMMON);//movement bugged - me->SummonCreature(CREATURE_VOLCANO,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); - DoScriptText(EMOTE_GROUND_CRACK, me); - events.DelayEvents(1500, GCD_CAST); - } - events.ScheduleEvent(EVENT_VOLCANO, 10000, GCD_CAST, PHASE_CHASE); - return; - } - case EVENT_SWITCH_PHASE: - ChangePhase(); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_volcanoAI : public Scripted_NoMovementAI -{ - npc_volcanoAI(Creature *c) : Scripted_NoMovementAI(c) {} - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //DoCast(me, SPELL_VOLCANIC_ERUPTION); - me->SetReactState(REACT_PASSIVE); - wait = 3000; - } - uint32 wait; - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void DoAction(const uint32 /*info*/) - { - me->RemoveAura(SPELL_VOLCANIC_ERUPTION); - } - - void UpdateAI(const uint32 diff) - { - if (wait <= diff)//wait 3secs before casting - { - DoCast(me, SPELL_VOLCANIC_ERUPTION); - wait = 60000; - } - else wait -= diff; - } - -}; - -CreatureAI* GetAI_boss_supremus(Creature* pCreature) -{ - return new boss_supremusAI (pCreature); -} - -CreatureAI* GetAI_molten_flame(Creature* pCreature) -{ - return new molten_flameAI (pCreature); -} - -CreatureAI* GetAI_npc_volcano(Creature* pCreature) -{ - return new npc_volcanoAI (pCreature); -} - -void AddSC_boss_supremus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_supremus"; - newscript->GetAI = &GetAI_boss_supremus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "molten_flame"; - newscript->GetAI = &GetAI_molten_flame; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_volcano"; - newscript->GetAI = &GetAI_npc_volcano; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp deleted file mode 100644 index 670edc4d869..00000000000 --- a/src/server/scripts/Outland/black_temple/boss_teron_gorefiend.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Teron_Gorefiend -SD%Complete: 60 -SDComment: Requires Mind Control support for Ghosts. -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - - //Speech'n'sound -#define SAY_INTRO -1564037 -#define SAY_AGGRO -1564038 -#define SAY_SLAY1 -1564039 -#define SAY_SLAY2 -1564040 -#define SAY_SPELL1 -1564041 -#define SAY_SPELL2 -1564042 -#define SAY_SPECIAL1 -1564043 -#define SAY_SPECIAL2 -1564044 -#define SAY_ENRAGE -1564045 -#define SAY_DEATH -1564046 - -//Spells -#define SPELL_INCINERATE 40239 -#define SPELL_CRUSHING_SHADOWS 40243 -#define SPELL_SHADOWBOLT 40185 -#define SPELL_PASSIVE_SHADOWFORM 40326 -#define SPELL_SHADOW_OF_DEATH 40251 -#define SPELL_BERSERK 45078 - -#define SPELL_ATROPHY 40327 // Shadowy Constructs use this when they get within melee range of a player - -#define CREATURE_DOOM_BLOSSOM 23123 -#define CREATURE_SHADOWY_CONSTRUCT 23111 - -struct mob_doom_blossomAI : public ScriptedAI -{ - mob_doom_blossomAI(Creature *c) : ScriptedAI(c) {} - - uint32 CheckTeronTimer; - uint32 ShadowBoltTimer; - uint64 TeronGUID; - - void Reset() - { - CheckTeronTimer = 5000; - ShadowBoltTimer = 12000; - TeronGUID = 0; - } - - void EnterCombat(Unit * /*who*/) { } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void Despawn() - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - } - - void UpdateAI(const uint32 diff) - { - if (CheckTeronTimer <= diff) - { - if (TeronGUID) - { - DoZoneInCombat(); - - Creature* Teron = (Unit::GetCreature((*me), TeronGUID)); - if ((Teron) && (!Teron->isAlive() || Teron->IsInEvadeMode())) - Despawn(); - } - else - Despawn(); - - CheckTeronTimer = 5000; - } else CheckTeronTimer -= diff; - - if (ShadowBoltTimer < diff && me->isInCombat()) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOWBOLT); - ShadowBoltTimer = 10000; - } else ShadowBoltTimer -= diff; - return; - } - - void SetTeronGUID(uint64 guid){ TeronGUID = guid; } -}; - -struct mob_shadowy_constructAI : public ScriptedAI -{ - mob_shadowy_constructAI(Creature* c) : ScriptedAI(c) {} - - uint64 GhostGUID; - uint64 TeronGUID; - - uint32 CheckPlayerTimer; - uint32 CheckTeronTimer; - - void Reset() - { - GhostGUID = 0; - TeronGUID = 0; - - CheckPlayerTimer = 2000; - CheckTeronTimer = 5000; - } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (!who || (!who->isAlive()) || (who->GetGUID() == GhostGUID)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - -/* Comment it out for now. NOTE TO FUTURE DEV: UNCOMMENT THIS OUT ONLY AFTER MIND CONTROL IS IMPLEMENTED - void DamageTaken(Unit* done_by, uint32 &damage) - { - if (done_by->GetGUID() != GhostGUID) - damage = 0; // Only the ghost can deal damage. - } - */ - - void CheckPlayers() - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - if (m_threatlist.empty()) - return; // No threat list. Don't continue. - std::list::const_iterator itr = m_threatlist.begin(); - std::list targets; - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - targets.push_back(pUnit); - } - targets.sort(Trinity::ObjectDistanceOrderPred(me)); - Unit *pTarget = targets.front(); - if (pTarget && me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) - { - DoCast(pTarget, SPELL_ATROPHY); - me->AI()->AttackStart(pTarget); - } - } - - void UpdateAI(const uint32 diff) - { - if (CheckPlayerTimer <= diff) - { - CheckPlayers(); - CheckPlayerTimer = 3000; - } else CheckPlayerTimer -= diff; - - if (CheckTeronTimer <= diff) - { - Creature* Teron = (Unit::GetCreature((*me), TeronGUID)); - if (!Teron || !Teron->isAlive() || Teron->IsInEvadeMode()) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - - CheckTeronTimer = 5000; - } else CheckTeronTimer -= diff; - } -}; - -struct boss_teron_gorefiendAI : public ScriptedAI -{ - boss_teron_gorefiendAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 IncinerateTimer; - uint32 SummonDoomBlossomTimer; - uint32 EnrageTimer; - uint32 CrushingShadowsTimer; - uint32 ShadowOfDeathTimer; - uint32 SummonShadowsTimer; - uint32 RandomYellTimer; - uint32 AggroTimer; - - uint64 AggroTargetGUID; - uint64 GhostGUID; // Player that gets killed by Shadow of Death and gets turned into a ghost - - bool Intro; - bool Done; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_TERONGOREFIENDEVENT, NOT_STARTED); - - IncinerateTimer = 20000 + rand()%11000; - SummonDoomBlossomTimer = 12000; - EnrageTimer = 600000; - CrushingShadowsTimer = 22000; - SummonShadowsTimer = 60000; - RandomYellTimer = 50000; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // Start off unattackable so that the intro is done properly - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - AggroTimer = 20000; - AggroTargetGUID = 0; - Intro = false; - Done = false; - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit* pWho) - { - if (!Intro && pWho->GetTypeId() == TYPEID_PLAYER && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && pWho->isInAccessiblePlaceFor(me)) - { - if (me->IsWithinDistInMap(pWho, VISIBLE_RANGE) && me->IsWithinLOSInMap(pWho)) - { - if (pInstance) - pInstance->SetData(DATA_TERONGOREFIENDEVENT, IN_PROGRESS); - - me->GetMotionMaster()->Clear(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoScriptText(SAY_INTRO, me); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); - AggroTargetGUID = pWho->GetGUID(); - Intro = true; - } - } - if (Done) - ScriptedAI::MoveInLineOfSight(pWho); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_TERONGOREFIENDEVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - float CalculateRandomLocation(float Loc, uint32 radius) - { - float coord = Loc; - switch (urand(0,1)) - { - case 0: - coord += rand()%radius; - break; - case 1: - coord -= rand()%radius; - break; - } - return coord; - } - - void SetThreatList(Creature* Blossom) - { - if (!Blossom) return; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - std::list::const_iterator i = m_threatlist.begin(); - for (i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - { - float threat = DoGetThreat(pUnit); - Blossom->AddThreat(pUnit, threat); - } - } - } - - void MindControlGhost() - { - /************************************************************************/ - /** NOTE FOR FUTURE DEVELOPER: PROPERLY IMPLEMENT THE GHOST PORTION *****/ - /** ONLY AFTER TrinIty FULLY IMPLEMENTS MIND CONTROL ABILITIES *****/ - /** THE CURRENT CODE IN THIS FUNCTION IS ONLY THE BEGINNING OF *****/ - /** WHAT IS FULLY NECESSARY FOR GOREFIEND TO BE 100% COMPLETE *****/ - /************************************************************************/ - - Unit* Ghost = NULL; - if (GhostGUID) - Ghost = Unit::GetUnit((*me), GhostGUID); - if (Ghost && Ghost->isAlive() && Ghost->HasAura(SPELL_SHADOW_OF_DEATH)) - { - /*float x,y,z; - Ghost->GetPosition(x,y,z); - Creature* control = me->SummonCreature(CREATURE_GHOST, x, y, z, 0, TEMPSUMMON_TIMED_DESAWN, 30000); - if (control) - { - CAST_PLR(Ghost)->Possess(control); - Ghost->DealDamage(Ghost, Ghost->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, - false); - }*/ - for (uint8 i = 0; i < 4; ++i) - { - Creature* Construct = NULL; - float X = CalculateRandomLocation(Ghost->GetPositionX(), 10); - float Y = CalculateRandomLocation(Ghost->GetPositionY(), 10); - Construct = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, Y, Ghost->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); - if (Construct) - { - Construct->CastSpell(Construct, SPELL_PASSIVE_SHADOWFORM, true); - SetThreatList(Construct); // Use same function as Doom Blossom to set Threat List. - CAST_AI(mob_shadowy_constructAI, Construct->AI())->GhostGUID = GhostGUID; - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) // someone's trying to solo. - pTarget = me->getVictim(); - - if (pTarget) - Construct->GetMotionMaster()->MoveChase(pTarget); - } - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Intro && !Done) - { - if (AggroTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoScriptText(SAY_AGGRO, me); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - Done = true; - if (AggroTargetGUID) - { - Unit* pUnit = Unit::GetUnit((*me), AggroTargetGUID); - if (pUnit) - AttackStart(pUnit); - - DoZoneInCombat(); - } - else - { - EnterEvadeMode(); - return; - } - } else AggroTimer -= diff; - } - - if (!UpdateVictim() || !Done) - return; - - if (SummonShadowsTimer <= diff) - { - //MindControlGhost(); - - for (uint8 i = 0; i < 2; ++i) - { - Creature* Shadow = NULL; - float X = CalculateRandomLocation(me->GetPositionX(), 10); - Shadow = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 0); - if (Shadow) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget) - Shadow->AI()->AttackStart(pTarget); - } - } - SummonShadowsTimer = 60000; - } else SummonShadowsTimer -= diff; - - if (SummonDoomBlossomTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float X = CalculateRandomLocation(pTarget->GetPositionX(), 20); - float Y = CalculateRandomLocation(pTarget->GetPositionY(), 20); - float Z = pTarget->GetPositionZ(); - Z = me->GetMap()->GetHeight(X, Y, Z); - Creature* DoomBlossom = me->SummonCreature(CREATURE_DOOM_BLOSSOM, X, Y, Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); - if (DoomBlossom) - { - DoomBlossom->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoomBlossom->setFaction(me->getFaction()); - DoomBlossom->AddThreat(pTarget, 1.0f); - CAST_AI(mob_doom_blossomAI, DoomBlossom->AI())->SetTeronGUID(me->GetGUID()); - pTarget->CombatStart(DoomBlossom); - SetThreatList(DoomBlossom); - SummonDoomBlossomTimer = 35000; - } - } - } else SummonDoomBlossomTimer -= diff; - - if (IncinerateTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget) - { - DoScriptText(RAND(SAY_SPECIAL1,SAY_SPECIAL2), me); - DoCast(pTarget, SPELL_INCINERATE); - IncinerateTimer = 20000 + rand()%31 * 1000; - } - } else IncinerateTimer -= diff; - - if (CrushingShadowsTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, SPELL_CRUSHING_SHADOWS); - CrushingShadowsTimer = 10000 + rand()%16 * 1000; - } else CrushingShadowsTimer -= diff; - - /*** NOTE FOR FUTURE DEV: UNCOMMENT BELOW ONLY IF MIND CONTROL IS FULLY IMPLEMENTED **/ - /*if (ShadowOfDeathTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, SPELL_SHADOW_OF_DEATH); - GhostGUID = pTarget->GetGUID(); - ShadowOfDeathTimer = 30000; - SummonShadowsTimer = 53000; // Make it VERY close but slightly less so that we can check if the aura is still on the player - } - } else ShadowOfDeathTimer -= diff;*/ - - if (RandomYellTimer <= diff) - { - DoScriptText(RAND(SAY_SPELL1,SAY_SPELL2), me); - RandomYellTimer = 50000 + rand()%51 * 1000; - } else RandomYellTimer -= diff; - - if (!me->HasAura(SPELL_BERSERK)) - { - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - DoScriptText(SAY_ENRAGE, me); - } else EnrageTimer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_doom_blossom(Creature* pCreature) -{ - return new mob_doom_blossomAI(pCreature); -} - -CreatureAI* GetAI_mob_shadowy_construct(Creature* pCreature) -{ - return new mob_shadowy_constructAI(pCreature); -} - -CreatureAI* GetAI_boss_teron_gorefiend(Creature* pCreature) -{ - return new boss_teron_gorefiendAI (pCreature); -} - -void AddSC_boss_teron_gorefiend() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_doom_blossom"; - newscript->GetAI = &GetAI_mob_doom_blossom; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadowy_construct"; - newscript->GetAI = &GetAI_mob_shadowy_construct; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_teron_gorefiend"; - newscript->GetAI = &GetAI_boss_teron_gorefiend; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp deleted file mode 100644 index 7d94b4b36a0..00000000000 --- a/src/server/scripts/Outland/black_temple/boss_warlord_najentus.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warlord_Najentus -SD%Complete: 95 -SDComment: -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -enum eEnums -{ - SAY_AGGRO = -1564000, - SAY_NEEDLE1 = -1564001, - SAY_NEEDLE2 = -1564002, - SAY_SLAY1 = -1564003, - SAY_SLAY2 = -1564004, - SAY_SPECIAL1 = -1564005, - SAY_SPECIAL2 = -1564006, - SAY_ENRAGE1 = -1564007, //is this text actually in use? - SAY_ENRAGE2 = -1564008, - SAY_DEATH = -1564009, - - //Spells - SPELL_NEEDLE_SPINE = 39992, - SPELL_TIDAL_BURST = 39878, - SPELL_TIDAL_SHIELD = 39872, - SPELL_IMPALING_SPINE = 39837, - SPELL_CREATE_NAJENTUS_SPINE = 39956, - SPELL_HURL_SPINE = 39948, - SPELL_BERSERK = 26662, - - GOBJECT_SPINE = 185584, - - EVENT_BERSERK = 1, - EVENT_YELL = 2, - EVENT_NEEDLE = 3, - EVENT_SPINE = 4, - EVENT_SHIELD = 5, - - GCD_CAST = 1, - GCD_YELL = 2 -}; - -struct boss_najentusAI : public ScriptedAI -{ - boss_najentusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - uint64 SpineTargetGUID; - - void Reset() - { - events.Reset(); - - SpineTargetGUID = 0; - - if (pInstance) - pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(rand()%2 ? SAY_SLAY1 : SAY_SLAY2, me); - events.DelayEvents(5000, GCD_YELL); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - if (spell->Id == SPELL_HURL_SPINE && me->HasAura(SPELL_TIDAL_SHIELD)) - { - me->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD); - DoCast(me, SPELL_TIDAL_BURST, true); - ResetTimer(); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, IN_PROGRESS); - - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - events.ScheduleEvent(EVENT_BERSERK, 480000, GCD_CAST); - events.ScheduleEvent(EVENT_YELL, 45000 + (rand()%76)*1000, GCD_YELL); - ResetTimer(); - } - - bool RemoveImpalingSpine() - { - if (!SpineTargetGUID) return false; - Unit *pTarget = Unit::GetUnit(*me, SpineTargetGUID); - if (pTarget && pTarget->HasAura(SPELL_IMPALING_SPINE)) - pTarget->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE); - SpineTargetGUID=0; - return true; - } - - void ResetTimer(uint32 inc = 0) - { - events.RescheduleEvent(EVENT_NEEDLE, 10000 + inc, GCD_CAST); - events.RescheduleEvent(EVENT_SPINE, 20000 + inc, GCD_CAST); - events.RescheduleEvent(EVENT_SHIELD, 60000 + inc); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHIELD: - DoCast(me, SPELL_TIDAL_SHIELD, true); - ResetTimer(45000); - break; - case EVENT_BERSERK: - DoScriptText(SAY_ENRAGE2, me); - DoCast(me, SPELL_BERSERK, true); - events.DelayEvents(15000, GCD_YELL); - break; - case EVENT_SPINE: - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!pTarget) pTarget = me->getVictim(); - if (pTarget) - { - DoCast(pTarget, SPELL_IMPALING_SPINE, true); - SpineTargetGUID = pTarget->GetGUID(); - //must let target summon, otherwise you cannot click the spine - pTarget->SummonGameObject(GOBJECT_SPINE, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 30); - DoScriptText(rand()%2 ? SAY_NEEDLE1 : SAY_NEEDLE2, me); - events.DelayEvents(1500, GCD_CAST); - events.DelayEvents(15000, GCD_YELL); - } - events.ScheduleEvent(EVENT_SPINE, 21000, GCD_CAST); - return; - } - case EVENT_NEEDLE: - { - //DoCast(me, SPELL_NEEDLE_SPINE, true); - std::list pTargets; - SelectTargetList(pTargets, 3, SELECT_TARGET_RANDOM, 80, true); - for (std::list::const_iterator i = pTargets.begin(); i != pTargets.end(); ++i) - DoCast(*i, 39835, true); - events.ScheduleEvent(EVENT_NEEDLE, urand(15000,25000), GCD_CAST); - events.DelayEvents(1500, GCD_CAST); - return; - } - case EVENT_YELL: - DoScriptText(RAND(SAY_SPECIAL1, SAY_SPECIAL2), me); - events.ScheduleEvent(EVENT_YELL, urand(25000,100000), GCD_YELL); - events.DelayEvents(15000, GCD_YELL); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -bool GOHello_go_najentus_spine(Player* pPlayer, GameObject* pGo) -{ - if (ScriptedInstance* pInstance = pGo->GetInstanceData()) - if (Creature* Najentus = Unit::GetCreature(*pGo, pInstance->GetData64(DATA_HIGHWARLORDNAJENTUS))) - if (CAST_AI(boss_najentusAI, Najentus->AI())->RemoveImpalingSpine()) - { - pPlayer->CastSpell(pPlayer, SPELL_CREATE_NAJENTUS_SPINE, true); - pGo->Delete(); - } - return true; -} - -CreatureAI* GetAI_boss_najentus(Creature* pCreature) -{ - return new boss_najentusAI (pCreature); -} - -void AddSC_boss_najentus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_najentus"; - newscript->GetAI = &GetAI_boss_najentus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_najentus_spine"; - newscript->pGOHello = &GOHello_go_najentus_spine; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/illidari_council.cpp b/src/server/scripts/Outland/black_temple/illidari_council.cpp deleted file mode 100644 index 82cc2876b5a..00000000000 --- a/src/server/scripts/Outland/black_temple/illidari_council.cpp +++ /dev/null @@ -1,874 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Illidari_Council -SD%Complete: 95 -SDComment: Circle of Healing not working properly. -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -//Speech'n'Sounds -#define SAY_GATH_SLAY -1564085 -#define SAY_GATH_SLAY_COMNT -1564089 -#define SAY_GATH_DEATH -1564093 -#define SAY_GATH_SPECIAL1 -1564077 -#define SAY_GATH_SPECIAL2 -1564081 - -#define SAY_VERA_SLAY -1564086 -#define SAY_VERA_COMNT -1564089 //signed for 22949 -#define SAY_VERA_DEATH -1564094 -#define SAY_VERA_SPECIAL1 -1564078 -#define SAY_VERA_SPECIAL2 -1564082 - -#define SAY_MALA_SLAY -1564087 -#define SAY_MALA_COMNT -1564090 -#define SAY_MALA_DEATH -1564095 -#define SAY_MALA_SPECIAL1 -1564079 -#define SAY_MALA_SPECIAL2 -1564083 - -#define SAY_ZERE_SLAY -1564088 -#define SAY_ZERE_COMNT -1564091 -#define SAY_ZERE_DEATH -1564096 -#define SAY_ZERE_SPECIAL1 -1564080 -#define SAY_ZERE_SPECIAL2 -1564084 - -#define ERROR_INST_DATA "SD2 ERROR: Instance Data for Black Temple not set properly; Illidari Council event will not function properly." - -#define AKAMAID 23089 - -struct CouncilYells -{ - int32 entry; - uint32 timer; -}; - -static CouncilYells CouncilAggro[]= -{ - {-1564069, 5000}, // Gathios - {-1564070, 5500}, // Veras - {-1564071, 5000}, // Malande - {-1564072, 0}, // Zerevor -}; - -// Need to get proper timers for this later -static CouncilYells CouncilEnrage[]= -{ - {-1564073, 2000}, // Gathios - {-1564074, 6000}, // Veras - {-1564075, 5000}, // Malande - {-1564076, 0}, // Zerevor -}; - -// High Nethermancer Zerevor's spells -#define SPELL_FLAMESTRIKE 41481 -#define SPELL_BLIZZARD 41482 -#define SPELL_ARCANE_BOLT 41483 -#define SPELL_ARCANE_EXPLOSION 41524 -#define SPELL_DAMPEN_MAGIC 41478 - -// Lady Malande's spells -#define SPELL_EMPOWERED_SMITE 41471 -#define SPELL_CIRCLE_OF_HEALING 41455 -#define SPELL_REFLECTIVE_SHIELD 41475 -#define SPELL_DIVINE_WRATH 41472 -#define SPELL_HEAL_VISUAL 24171 - -// Gathios the Shatterer's spells -#define SPELL_BLESS_PROTECTION 41450 -#define SPELL_BLESS_SPELLWARD 41451 -#define SPELL_CONSECRATION 41541 -#define SPELL_HAMMER_OF_JUSTICE 41468 -#define SPELL_SEAL_OF_COMMAND 41469 -#define SPELL_SEAL_OF_BLOOD 41459 -#define SPELL_CHROMATIC_AURA 41453 -#define SPELL_DEVOTION_AURA 41452 - -// Veras Darkshadow's spells -#define SPELL_DEADLY_POISON 41485 -#define SPELL_ENVENOM 41487 -#define SPELL_VANISH 41479 - -#define SPELL_BERSERK 45078 - -struct mob_blood_elf_council_voice_triggerAI : public ScriptedAI -{ - mob_blood_elf_council_voice_triggerAI(Creature* c) : ScriptedAI(c) - { - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; - } - - uint64 Council[4]; - - uint32 EnrageTimer; - uint32 AggroYellTimer; - - uint8 YellCounter; // Serves as the counter for both the aggro and enrage yells - - bool EventStarted; - - void Reset() - { - EnrageTimer = 900000; // 15 minutes - AggroYellTimer = 500; - - YellCounter = 0; - - EventStarted = false; - } - - // finds and stores the GUIDs for each Council member using instance data system. - void LoadCouncilGUIDs() - { - if (ScriptedInstance* pInstance = me->GetInstanceData()) - { - Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[1] = pInstance->GetData64(DATA_VERASDARKSHADOW); - Council[2] = pInstance->GetData64(DATA_LADYMALANDE); - Council[3] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); - } else error_log(ERROR_INST_DATA); - } - - void EnterCombat(Unit* /*who*/) {} - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!EventStarted) - return; - - if (YellCounter > 3) - return; - - if (AggroYellTimer) - { - if (AggroYellTimer <= diff) - { - if (Unit* pMember = Unit::GetUnit(*me, Council[YellCounter])) - { - DoScriptText(CouncilAggro[YellCounter].entry, pMember); - AggroYellTimer = CouncilAggro[YellCounter].timer; - } - ++YellCounter; - if (YellCounter > 3) - YellCounter = 0; // Reuse for Enrage Yells - } else AggroYellTimer -= diff; - } - - if (EnrageTimer) - { - if (EnrageTimer <= diff) - { - if (Unit* pMember = Unit::GetUnit(*me, Council[YellCounter])) - { - pMember->CastSpell(pMember, SPELL_BERSERK, true); - DoScriptText(CouncilEnrage[YellCounter].entry, pMember); - EnrageTimer = CouncilEnrage[YellCounter].timer; - } - ++YellCounter; - } else EnrageTimer -= diff; - } - } -}; - -struct mob_illidari_councilAI : public ScriptedAI -{ - mob_illidari_councilAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; - } - - ScriptedInstance* pInstance; - - uint64 Council[4]; - - uint32 CheckTimer; - uint32 EndEventTimer; - - uint8 DeathCount; - - bool EventBegun; - - void Reset() - { - CheckTimer = 2000; - EndEventTimer = 0; - - DeathCount = 0; - - Creature* pMember = NULL; - for (uint8 i = 0; i < 4; ++i) - { - pMember = Unit::GetCreature((*me), Council[i]); - if (!pMember) - continue; - - if (!pMember->isAlive()) - { - pMember->RemoveCorpse(); - pMember->Respawn(); - } - pMember->AI()->EnterEvadeMode(); - } - - if (pInstance) - { - pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, NOT_STARTED); - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) - VoiceTrigger->AI()->EnterEvadeMode(); - } - - EventBegun = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(11686); - } - - void EnterCombat(Unit * /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void StartEvent(Unit *pTarget) - { - if (!pInstance) - return; - - if (pTarget && pTarget->isAlive()) - { - Council[0] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); - Council[2] = pInstance->GetData64(DATA_LADYMALANDE); - Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); - - // Start the event for the Voice Trigger - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) - { - CAST_AI(mob_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->LoadCouncilGUIDs(); - CAST_AI(mob_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->EventStarted = true; - } - - for (uint8 i = 0; i < 4; ++i) - { - Unit* Member = NULL; - if (Council[i]) - { - Member = Unit::GetUnit((*me), Council[i]); - if (Member && Member->isAlive()) - CAST_CRE(Member)->AI()->AttackStart(pTarget); - } - } - - pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, IN_PROGRESS); - - EventBegun = true; - } - } - - void UpdateAI(const uint32 diff) - { - if (!EventBegun) return; - - if (EndEventTimer) - { - if (EndEventTimer <= diff) - { - if (DeathCount > 3) - { - if (pInstance) - { - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, pInstance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) - VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - pInstance->SetData(DATA_ILLIDARICOUNCILEVENT, DONE); - //me->SummonCreature(AKAMAID,746.466980f,304.394989f,311.90208f,6.272870f,TEMPSUMMON_DEAD_DESPAWN,0); - } - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - - Creature* pMember = (Unit::GetCreature(*me, Council[DeathCount])); - if (pMember && pMember->isAlive()) - pMember->DealDamage(pMember, pMember->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - ++DeathCount; - EndEventTimer = 1500; - } else EndEventTimer -= diff; - } - - if (CheckTimer) - { - if (CheckTimer <= diff) - { - uint8 EvadeCheck = 0; - for (uint8 i = 0; i < 4; ++i) - { - if (Council[i]) - { - if (Creature* Member = (Unit::GetCreature((*me), Council[i]))) - { - // This is the evade/death check. - if (Member->isAlive() && !Member->getVictim()) - ++EvadeCheck; //If all members evade, we reset so that players can properly reset the event - else if (!Member->isAlive()) // If even one member dies, kill the rest, set instance data, and kill self. - { - EndEventTimer = 1000; - CheckTimer = 0; - return; - } - } - } - } - - if (EvadeCheck > 3) - Reset(); - - CheckTimer = 2000; - } else CheckTimer -= diff; - } - - } -}; - -struct boss_illidari_councilAI : public ScriptedAI -{ - boss_illidari_councilAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; - LoadedGUIDs = false; - } - - uint64 Council[4]; - - ScriptedInstance* pInstance; - - bool LoadedGUIDs; - - void EnterCombat(Unit* who) - { - if (pInstance) - { - Creature* Controller = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ILLIDARICOUNCIL))); - if (Controller) - CAST_AI(mob_illidari_councilAI, Controller->AI())->StartEvent(who); - } - else - { - error_log(ERROR_INST_DATA); - EnterEvadeMode(); - return; - } - DoZoneInCombat(); - // Load GUIDs on first aggro because the Creature guids are only set as the creatures are created in world- - // this means that for each pCreature, it will attempt to LoadGUIDs even though some of the other creatures are - // not in world, and thus have no GUID set in the instance data system. Putting it in aggro ensures that all the creatures - // have been loaded and have their GUIDs set in the instance data system. - if (!LoadedGUIDs) - LoadGUIDs(); - } - - void EnterEvadeMode() - { - for (uint8 i = 0; i < 4; ++i) - { - if (Unit* pUnit = Unit::GetUnit(*me, Council[i])) - if (pUnit != me && pUnit->getVictim()) - { - AttackStart(pUnit->getVictim()); - return; - } - } - ScriptedAI::EnterEvadeMode(); - } - - void DamageTaken(Unit* done_by, uint32 &damage) - { - if (done_by == me) - return; - - damage /= 4; - for (uint8 i = 0; i < 4; ++i) - { - if (Creature* pUnit = Unit::GetCreature(*me, Council[i])) - if (pUnit != me && damage < pUnit->GetHealth()) - { - pUnit->SetHealth(pUnit->GetHealth() - damage); - pUnit->LowerPlayerDamageReq(damage); - } - } - } - - void LoadGUIDs() - { - if (!pInstance) - { - error_log(ERROR_INST_DATA); - return; - } - - Council[0] = pInstance->GetData64(DATA_LADYMALANDE); - Council[1] = pInstance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); - Council[2] = pInstance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[3] = pInstance->GetData64(DATA_VERASDARKSHADOW); - - LoadedGUIDs = true; - } -}; - -struct boss_gathios_the_shattererAI : public boss_illidari_councilAI -{ - boss_gathios_the_shattererAI(Creature *c) : boss_illidari_councilAI(c) {} - - uint32 ConsecrationTimer; - uint32 HammerOfJusticeTimer; - uint32 SealTimer; - uint32 AuraTimer; - uint32 BlessingTimer; - - void Reset() - { - ConsecrationTimer = 40000; - HammerOfJusticeTimer = 10000; - SealTimer = 40000; - AuraTimer = 90000; - BlessingTimer = 60000; - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_GATH_SLAY, me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_GATH_DEATH, me); - } - - Unit* SelectCouncilMember() - { - Unit* pUnit = me; - uint32 member = 0; // He chooses Lady Malande most often - - if (rand()%10 == 0) // But there is a chance he picks someone else. - member = urand(1, 3); - - if (member != 2) // No need to create another pointer to us using Unit::GetUnit - pUnit = Unit::GetUnit((*me), Council[member]); - return pUnit; - } - - void CastAuraOnCouncil() - { - uint32 spellid = 0; - switch (urand(0,1)) - { - case 0: spellid = SPELL_DEVOTION_AURA; break; - case 1: spellid = SPELL_CHROMATIC_AURA; break; - } - for (uint8 i = 0; i < 4; ++i) - { - Unit* pUnit = Unit::GetUnit((*me), Council[i]); - if (pUnit) - pUnit->CastSpell(pUnit, spellid, true, 0, 0, me->GetGUID()); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (BlessingTimer <= diff) - { - if (Unit* pUnit = SelectCouncilMember()) - { - switch (urand(0,1)) - { - case 0: DoCast(pUnit, SPELL_BLESS_SPELLWARD); break; - case 1: DoCast(pUnit, SPELL_BLESS_PROTECTION); break; - } - } - BlessingTimer = 60000; - } else BlessingTimer -= diff; - - if (ConsecrationTimer <= diff) - { - DoCast(me, SPELL_CONSECRATION); - ConsecrationTimer = 40000; - } else ConsecrationTimer -= diff; - - if (HammerOfJusticeTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - // is in ~10-40 yd range - if (me->IsInRange(pTarget, 10.0f, 40.0f, false)) - { - DoCast(pTarget, SPELL_HAMMER_OF_JUSTICE); - HammerOfJusticeTimer = 20000; - } - } - } else HammerOfJusticeTimer -= diff; - - if (SealTimer <= diff) - { - switch (urand(0,1)) - { - case 0: DoCast(me, SPELL_SEAL_OF_COMMAND); break; - case 1: DoCast(me, SPELL_SEAL_OF_BLOOD); break; - } - SealTimer = 40000; - } else SealTimer -= diff; - - if (AuraTimer <= diff) - { - CastAuraOnCouncil(); - AuraTimer = 90000; - } else AuraTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_high_nethermancer_zerevorAI : public boss_illidari_councilAI -{ - boss_high_nethermancer_zerevorAI(Creature *c) : boss_illidari_councilAI(c) {} - - uint32 BlizzardTimer; - uint32 FlamestrikeTimer; - uint32 ArcaneBoltTimer; - uint32 DampenMagicTimer; - uint32 Cooldown; - uint32 ArcaneExplosionTimer; - - void Reset() - { - BlizzardTimer = 30000 + rand()%61 * 1000; - FlamestrikeTimer = 30000 + rand()%61 * 1000; - ArcaneBoltTimer = 10000; - DampenMagicTimer = 2000; - ArcaneExplosionTimer = 14000; - Cooldown = 0; - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_ZERE_SLAY, me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_ZERE_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Cooldown) - { - if (Cooldown <= diff) Cooldown = 0; - else - { - Cooldown -= diff; - return; // Don't cast any other spells if global cooldown is still ticking - } - } - - if (DampenMagicTimer <= diff) - { - DoCast(me, SPELL_DAMPEN_MAGIC); - Cooldown = 1000; - DampenMagicTimer = 67200; // almost 1,12 minutes - ArcaneBoltTimer += 1000; // Give the Mage some time to spellsteal Dampen. - } else DampenMagicTimer -= diff; - - if (ArcaneExplosionTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); - Cooldown = 1000; - ArcaneExplosionTimer = 14000; - } else ArcaneExplosionTimer -= diff; - - if (ArcaneBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BOLT); - ArcaneBoltTimer = 3000; - Cooldown = 2000; - } else ArcaneBoltTimer -= diff; - - if (BlizzardTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_BLIZZARD); - BlizzardTimer = 45000 + rand()%46 * 1000; - FlamestrikeTimer += 10000; - Cooldown = 1000; - } - } else BlizzardTimer -= diff; - - if (FlamestrikeTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_FLAMESTRIKE); - FlamestrikeTimer = 55000 + rand()%46 * 1000; - BlizzardTimer += 10000; - Cooldown = 2000; - } - } else FlamestrikeTimer -= diff; - } -}; - -struct boss_lady_malandeAI : public boss_illidari_councilAI -{ - boss_lady_malandeAI(Creature *c) : boss_illidari_councilAI(c) {} - - uint32 EmpoweredSmiteTimer; - uint32 CircleOfHealingTimer; - uint32 DivineWrathTimer; - uint32 ReflectiveShieldTimer; - - void Reset() - { - EmpoweredSmiteTimer = 38000; - CircleOfHealingTimer = 20000; - DivineWrathTimer = 40000; - ReflectiveShieldTimer = 0; - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_MALA_SLAY, me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_MALA_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (EmpoweredSmiteTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_EMPOWERED_SMITE); - EmpoweredSmiteTimer = 38000; - } - } else EmpoweredSmiteTimer -= diff; - - if (CircleOfHealingTimer <= diff) - { - DoCast(me, SPELL_CIRCLE_OF_HEALING); - CircleOfHealingTimer = 60000; - } else CircleOfHealingTimer -= diff; - - if (DivineWrathTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_DIVINE_WRATH); - DivineWrathTimer = 40000 + rand()%41 * 1000; - } - } else DivineWrathTimer -= diff; - - if (ReflectiveShieldTimer <= diff) - { - DoCast(me, SPELL_REFLECTIVE_SHIELD); - ReflectiveShieldTimer = 65000; - } else ReflectiveShieldTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_veras_darkshadowAI : public boss_illidari_councilAI -{ - boss_veras_darkshadowAI(Creature *c) : boss_illidari_councilAI(c) {} - - uint64 EnvenomTargetGUID; - - uint32 DeadlyPoisonTimer; - uint32 VanishTimer; - uint32 AppearEnvenomTimer; - - bool HasVanished; - - void Reset() - { - EnvenomTargetGUID = 0; - - DeadlyPoisonTimer = 20000; - VanishTimer = 60000 + rand()%61 * 1000; - AppearEnvenomTimer = 150000; - - HasVanished = false; - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_VERA_SLAY, me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_VERA_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!HasVanished) - { - if (DeadlyPoisonTimer <= diff) - { - DoCast(me->getVictim(), SPELL_DEADLY_POISON); - DeadlyPoisonTimer = 15000 + rand()%31 * 1000; - } else DeadlyPoisonTimer -= diff; - - if (AppearEnvenomTimer <= diff) // Cast Envenom. This is cast 4 seconds after Vanish is over - { - DoCast(me->getVictim(), SPELL_ENVENOM); - AppearEnvenomTimer = 90000; - } else AppearEnvenomTimer -= diff; - - if (VanishTimer <= diff) // Disappear and stop attacking, but follow a random unit - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - VanishTimer = 30000; - AppearEnvenomTimer= 28000; - HasVanished = true; - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoResetThreat(); - // Chase a unit. Check before DoMeleeAttackIfReady prevents from attacking - me->AddThreat(pTarget, 500000.0f); - me->GetMotionMaster()->MoveChase(pTarget); - } - } else VanishTimer -= diff; - - DoMeleeAttackIfReady(); - } - else - { - if (VanishTimer <= diff) // Become attackable and poison current target - { - Unit *pTarget = me->getVictim(); - DoCast(pTarget, SPELL_DEADLY_POISON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoResetThreat(); - me->AddThreat(pTarget, 3000.0f); // Make Veras attack his target for a while, he will cast Envenom 4 seconds after. - DeadlyPoisonTimer += 6000; - VanishTimer = 90000; - AppearEnvenomTimer = 4000; - HasVanished = false; - } else VanishTimer -= diff; - - if (AppearEnvenomTimer <= diff) // Appear 2 seconds before becoming attackable (Shifting out of vanish) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - me->SetVisibility(VISIBILITY_ON); - AppearEnvenomTimer = 6000; - } else AppearEnvenomTimer -= diff; - } - } -}; - -CreatureAI* GetAI_mob_blood_elf_council_voice_trigger(Creature* c) -{ - return new mob_blood_elf_council_voice_triggerAI(c); -} - -CreatureAI* GetAI_mob_illidari_council(Creature* pCreature) -{ - return new mob_illidari_councilAI (pCreature); -} - -CreatureAI* GetAI_boss_gathios_the_shatterer(Creature* pCreature) -{ - return new boss_gathios_the_shattererAI (pCreature); -} - -CreatureAI* GetAI_boss_lady_malande(Creature* pCreature) -{ - return new boss_lady_malandeAI (pCreature); -} - -CreatureAI* GetAI_boss_veras_darkshadow(Creature* pCreature) -{ - return new boss_veras_darkshadowAI (pCreature); -} - -CreatureAI* GetAI_boss_high_nethermancer_zerevor(Creature* pCreature) -{ - return new boss_high_nethermancer_zerevorAI (pCreature); -} - -void AddSC_boss_illidari_council() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_illidari_council"; - newscript->GetAI = &GetAI_mob_illidari_council; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_blood_elf_council_voice_trigger"; - newscript->GetAI = &GetAI_mob_blood_elf_council_voice_trigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_gathios_the_shatterer"; - newscript->GetAI = &GetAI_boss_gathios_the_shatterer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lady_malande"; - newscript->GetAI = &GetAI_boss_lady_malande; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_veras_darkshadow"; - newscript->GetAI = &GetAI_boss_veras_darkshadow; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_high_nethermancer_zerevor"; - newscript->GetAI = &GetAI_boss_high_nethermancer_zerevor; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/black_temple/instance_black_temple.cpp b/src/server/scripts/Outland/black_temple/instance_black_temple.cpp deleted file mode 100644 index 88e25026a13..00000000000 --- a/src/server/scripts/Outland/black_temple/instance_black_temple.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Black_Temple -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Black Temple Scripts -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptedPch.h" -#include "black_temple.h" - -#define MAX_ENCOUNTER 9 - -/* Black Temple encounters: -0 - High Warlord Naj'entus event -1 - Supremus Event -2 - Shade of Akama Event -3 - Teron Gorefiend Event -4 - Gurtogg Bloodboil Event -5 - Reliquary Of Souls Event -6 - Mother Shahraz Event -7 - Illidari Council Event -8 - Illidan Stormrage Event -*/ - -struct instance_black_temple : public ScriptedInstance -{ - instance_black_temple(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 Najentus; - uint64 Akama; // This is the Akama that starts the Illidan encounter. - uint64 Akama_Shade; // This is the Akama that starts the Shade of Akama encounter. - uint64 ShadeOfAkama; - uint64 Supremus; - uint64 LadyMalande; - uint64 GathiosTheShatterer; - uint64 HighNethermancerZerevor; - uint64 VerasDarkshadow; - uint64 IllidariCouncil; - uint64 BloodElfCouncilVoice; - uint64 IllidanStormrage; - - uint64 NajentusGate; - uint64 MainTempleDoors; - uint64 ShadeOfAkamaDoor; - uint64 CommonDoor;//Teron - uint64 TeronDoor; - uint64 GuurtogDoor; - uint64 MotherDoor; - uint64 TempleDoor;//Befor mother - uint64 CouncilDoor; - uint64 SimpleDoor;//council - uint64 IllidanGate; - uint64 IllidanDoor[2]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Najentus = 0; - Akama = 0; - Akama_Shade = 0; - ShadeOfAkama = 0; - Supremus = 0; - LadyMalande = 0; - GathiosTheShatterer = 0; - HighNethermancerZerevor = 0; - VerasDarkshadow = 0; - IllidariCouncil = 0; - BloodElfCouncilVoice = 0; - IllidanStormrage = 0; - - NajentusGate = 0; - MainTempleDoors = 0; - ShadeOfAkamaDoor= 0; - CommonDoor = 0;//teron - TeronDoor = 0; - GuurtogDoor = 0; - MotherDoor = 0; - TempleDoor = 0; - SimpleDoor = 0;//Bycouncil - CouncilDoor = 0; - IllidanGate = 0; - IllidanDoor[0] = 0; - IllidanDoor[1] = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - - debug_log("TSCR: Instance Black Temple: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 22887: Najentus = pCreature->GetGUID(); break; - case 23089: Akama = pCreature->GetGUID(); break; - case 22990: Akama_Shade = pCreature->GetGUID(); break; - case 22841: ShadeOfAkama = pCreature->GetGUID(); break; - case 22898: Supremus = pCreature->GetGUID(); break; - case 22917: IllidanStormrage = pCreature->GetGUID(); break; - case 22949: GathiosTheShatterer = pCreature->GetGUID(); break; - case 22950: HighNethermancerZerevor = pCreature->GetGUID(); break; - case 22951: LadyMalande = pCreature->GetGUID(); break; - case 22952: VerasDarkshadow = pCreature->GetGUID(); break; - case 23426: IllidariCouncil = pCreature->GetGUID(); break; - case 23499: BloodElfCouncilVoice = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 185483: NajentusGate = pGo->GetGUID();// Gate past Naj'entus (at the entrance to Supermoose's courtyards) - if (m_auiEncounter[0] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185882: MainTempleDoors = pGo->GetGUID();// Main Temple Doors - right past Supermoose (Supremus) - if (m_auiEncounter[1] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185478: ShadeOfAkamaDoor = pGo->GetGUID();break; - case 185480: CommonDoor = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE)HandleGameObject(NULL,true,pGo);break; - case 186153: TeronDoor = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185892: GuurtogDoor = pGo->GetGUID(); - if (m_auiEncounter[4] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185479: TempleDoor = pGo->GetGUID(); - if (m_auiEncounter[5] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185482: MotherDoor = pGo->GetGUID(); - if (m_auiEncounter[6] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185481: CouncilDoor = pGo->GetGUID(); - if (m_auiEncounter[7] == DONE)HandleGameObject(NULL,true,pGo);break; - case 186152: SimpleDoor = pGo->GetGUID(); - if (m_auiEncounter[7] == DONE)HandleGameObject(NULL,true,pGo);break; - case 185905: IllidanGate = pGo->GetGUID(); break; // Gate leading to Temple Summit - case 186261: IllidanDoor[0] = pGo->GetGUID(); break; // Right door at Temple Summit - case 186262: IllidanDoor[1] = pGo->GetGUID(); break; // Left door at Temple Summit - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_HIGHWARLORDNAJENTUS: return Najentus; - case DATA_AKAMA: return Akama; - case DATA_AKAMA_SHADE: return Akama_Shade; - case DATA_SHADEOFAKAMA: return ShadeOfAkama; - case DATA_SUPREMUS: return Supremus; - case DATA_ILLIDANSTORMRAGE: return IllidanStormrage; - case DATA_GATHIOSTHESHATTERER: return GathiosTheShatterer; - case DATA_HIGHNETHERMANCERZEREVOR: return HighNethermancerZerevor; - case DATA_LADYMALANDE: return LadyMalande; - case DATA_VERASDARKSHADOW: return VerasDarkshadow; - case DATA_ILLIDARICOUNCIL: return IllidariCouncil; - case DATA_GAMEOBJECT_NAJENTUS_GATE: return NajentusGate; - case DATA_GAMEOBJECT_ILLIDAN_GATE: return IllidanGate; - case DATA_GAMEOBJECT_ILLIDAN_DOOR_R: return IllidanDoor[0]; - case DATA_GAMEOBJECT_ILLIDAN_DOOR_L: return IllidanDoor[1]; - case DATA_GAMEOBJECT_SUPREMUS_DOORS: return MainTempleDoors; - case DATA_BLOOD_ELF_COUNCIL_VOICE: return BloodElfCouncilVoice; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_HIGHWARLORDNAJENTUSEVENT: - if (data == DONE) - { - HandleGameObject(NajentusGate, true); - } - m_auiEncounter[0] = data;break; - case DATA_SUPREMUSEVENT: - if (data == DONE) - { - HandleGameObject(NajentusGate, true); - } - m_auiEncounter[1] = data; break; - case DATA_SHADEOFAKAMAEVENT: - if (data == IN_PROGRESS) - { - HandleGameObject(ShadeOfAkamaDoor, false); - } else HandleGameObject(ShadeOfAkamaDoor, true); - m_auiEncounter[2] = data; break; - case DATA_TERONGOREFIENDEVENT: - if (data == IN_PROGRESS) - { - HandleGameObject(TeronDoor, false); - HandleGameObject(CommonDoor, false); - }else - { - HandleGameObject(TeronDoor, true); - HandleGameObject(CommonDoor, true); - } - m_auiEncounter[3] = data; break; - case DATA_GURTOGGBLOODBOILEVENT: - if (data == DONE) - { - HandleGameObject(GuurtogDoor, true); - } - m_auiEncounter[4] = data; break; - case DATA_RELIQUARYOFSOULSEVENT: - if (data == DONE) - { - HandleGameObject(TempleDoor, true); - } - m_auiEncounter[5] = data; break; - case DATA_MOTHERSHAHRAZEVENT: - if (data == DONE) - { - HandleGameObject(MotherDoor, true); - } - m_auiEncounter[6] = data; break; - case DATA_ILLIDARICOUNCILEVENT: - if (data == IN_PROGRESS) - { - HandleGameObject(CouncilDoor, false); - HandleGameObject(SimpleDoor, false); - }else - { - HandleGameObject(CouncilDoor, true); - HandleGameObject(SimpleDoor, true); - } - m_auiEncounter[7] = data; break; - case DATA_ILLIDANSTORMRAGEEVENT: m_auiEncounter[8] = data; break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4] - << " " << m_auiEncounter[5] << " " << m_auiEncounter[6] << " " << m_auiEncounter[7] - << " " << m_auiEncounter[8]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_HIGHWARLORDNAJENTUSEVENT: return m_auiEncounter[0]; - case DATA_SUPREMUSEVENT: return m_auiEncounter[1]; - case DATA_SHADEOFAKAMAEVENT: return m_auiEncounter[2]; - case DATA_TERONGOREFIENDEVENT: return m_auiEncounter[3]; - case DATA_GURTOGGBLOODBOILEVENT: return m_auiEncounter[4]; - case DATA_RELIQUARYOFSOULSEVENT: return m_auiEncounter[5]; - case DATA_MOTHERSHAHRAZEVENT: return m_auiEncounter[6]; - case DATA_ILLIDARICOUNCILEVENT: return m_auiEncounter[7]; - case DATA_ILLIDANSTORMRAGEEVENT: return m_auiEncounter[8]; - } - - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] - >> m_auiEncounter[3] >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] - >> m_auiEncounter[7] >> m_auiEncounter[8]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_black_temple(Map* pMap) -{ - return new instance_black_temple(pMap); -} - -void AddSC_instance_black_temple() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_black_temple"; - newscript->GetInstanceData = &GetInstanceData_instance_black_temple; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp deleted file mode 100644 index 69a969adda0..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp +++ /dev/null @@ -1,746 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Fathomlord_Karathress -SD%Complete: 70 -SDComment: Cyclone workaround -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedEscortAI.h" - -#define SAY_AGGRO -1548021 -#define SAY_GAIN_BLESSING -1548022 -#define SAY_GAIN_ABILITY1 -1548023 -#define SAY_GAIN_ABILITY2 -1548024 -#define SAY_GAIN_ABILITY3 -1548025 -#define SAY_SLAY1 -1548026 -#define SAY_SLAY2 -1548027 -#define SAY_SLAY3 -1548028 -#define SAY_DEATH -1548029 - -//Karathress spells -#define SPELL_CATACLYSMIC_BOLT 38441 -#define SPELL_POWER_OF_SHARKKIS 38455 -#define SPELL_POWER_OF_TIDALVESS 38452 -#define SPELL_POWER_OF_CARIBDIS 38451 -#define SPELL_ENRAGE 24318 -#define SPELL_SEAR_NOVA 38445 -#define SPELL_BLESSING_OF_THE_TIDES 38449 - -//Sharkkis spells -#define SPELL_LEECHING_THROW 29436 -#define SPELL_THE_BEAST_WITHIN 38373 -#define SPELL_MULTISHOT 38366 -#define SPELL_SUMMON_FATHOM_LURKER 38433 -#define SPELL_SUMMON_FATHOM_SPOREBAT 38431 -#define SPELL_PET_ENRAGE 19574 - -//Tidalvess spells -#define SPELL_FROST_SHOCK 38234 -#define SPELL_SPITFIRE_TOTEM 38236 -#define SPELL_POISON_CLEANSING_TOTEM 38306 -// Spell obsolete -// #define SPELL_POISON_CLEANSING_EFFECT 8167 -#define SPELL_EARTHBIND_TOTEM 38304 -#define SPELL_EARTHBIND_TOTEM_EFFECT 6474 -#define SPELL_WINDFURY_WEAPON 38184 - -//Caribdis Spells -#define SPELL_WATER_BOLT_VOLLEY 38335 -#define SPELL_TIDAL_SURGE 38358 -#define SPELL_TIDAL_SURGE_FREEZE 38357 -#define SPELL_HEAL 38330 -#define SPELL_SUMMON_CYCLONE 38337 -#define SPELL_CYCLONE_CYCLONE 29538 - -//Yells and Quotes -#define SAY_GAIN_BLESSING_OF_TIDES "Your overconfidence will be your undoing! Guards, lend me your strength!" -#define SOUND_GAIN_BLESSING_OF_TIDES 11278 -#define SAY_MISC "Alana be'lendor!" //don't know what use this -#define SOUND_MISC 11283 - -//Summoned Unit GUIDs -#define CREATURE_CYCLONE 22104 -#define CREATURE_FATHOM_SPOREBAT 22120 -#define CREATURE_FATHOM_LURKER 22119 -#define CREATURE_SPITFIRE_TOTEM 22091 -#define CREATURE_EARTHBIND_TOTEM 22486 -#define CREATURE_POISON_CLEANSING_TOTEM 22487 - -//entry and position for Seer Olum -#define SEER_OLUM 22820 -#define OLUM_X 446.78f -#define OLUM_Y -542.76f -#define OLUM_Z -7.54773f -#define OLUM_O 0.401581f - -//Fathom-Lord Karathress AI -struct boss_fathomlord_karathressAI : public ScriptedAI -{ - boss_fathomlord_karathressAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Advisors[0] = 0; - Advisors[1] = 0; - Advisors[2] = 0; - } - - ScriptedInstance* pInstance; - - uint32 CataclysmicBolt_Timer; - uint32 Enrage_Timer; - uint32 SearNova_Timer; - - bool BlessingOfTides; - - uint64 Advisors[3]; - - void Reset() - { - CataclysmicBolt_Timer = 10000; - Enrage_Timer = 600000; //10 minutes - SearNova_Timer = 20000+rand()%40000; // 20 - 60 seconds - - BlessingOfTides = false; - - if (pInstance) - { - uint64 RAdvisors[3]; - RAdvisors[0] = pInstance->GetData64(DATA_SHARKKIS); - RAdvisors[1] = pInstance->GetData64(DATA_TIDALVESS); - RAdvisors[2] = pInstance->GetData64(DATA_CARIBDIS); - //Respawn of the 3 Advisors - Creature* pAdvisor = NULL; - for (int i=0; i<3; ++i) - - if (RAdvisors[i]) - { - pAdvisor = (Unit::GetCreature((*me), RAdvisors[i])); - if (pAdvisor && !pAdvisor->isAlive()) - { - pAdvisor->Respawn(); - pAdvisor->AI()->EnterEvadeMode(); - pAdvisor->GetMotionMaster()->MoveTargetedHome(); - } - } - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - } - - void EventSharkkisDeath() - { - DoScriptText(SAY_GAIN_ABILITY1, me); - DoCast(me, SPELL_POWER_OF_SHARKKIS); - } - - void EventTidalvessDeath() - { - DoScriptText(SAY_GAIN_ABILITY2, me); - DoCast(me, SPELL_POWER_OF_TIDALVESS); - } - - void EventCaribdisDeath() - { - DoScriptText(SAY_GAIN_ABILITY3, me); - DoCast(me, SPELL_POWER_OF_CARIBDIS); - } - - void GetAdvisors() - { - if (!pInstance) - return; - - Advisors[0] = pInstance->GetData64(DATA_SHARKKIS); - Advisors[1] = pInstance->GetData64(DATA_TIDALVESS); - Advisors[2] = pInstance->GetData64(DATA_CARIBDIS); - } - - void StartEvent(Unit *who) - { - if (!pInstance) - return; - - GetAdvisors(); - - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); - - //support for quest 10944 - me->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 3600000); - } - - void EnterCombat(Unit * who) - { - StartEvent(who); - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - GetAdvisors(); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //CataclysmicBolt_Timer - if (CataclysmicBolt_Timer <= diff) - { - //select a random unit other than the main tank - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - - //if there aren't other units, cast on the tank - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget) - DoCast(pTarget, SPELL_CATACLYSMIC_BOLT); - CataclysmicBolt_Timer = 10000; - } else CataclysmicBolt_Timer -= diff; - - //SearNova_Timer - if (SearNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SEAR_NOVA); - SearNova_Timer = 20000+rand()%40000; - } else SearNova_Timer -= diff; - - //Enrage_Timer - if (Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enrage_Timer = 90000; - } else Enrage_Timer -= diff; - - //Blessing of Tides Trigger - if ((me->GetHealth()*100 / me->GetMaxHealth()) <= 75 && !BlessingOfTides) - { - BlessingOfTides = true; - bool continueTriggering = false; - Creature* Advisor; - for (uint8 i = 0; i < 4; ++i) - if (Advisors[i]) - { - Advisor = (Unit::GetCreature(*me, Advisors[i])); - if (Advisor && Advisor->isAlive()) - { - continueTriggering = true; - break; - } - } - if (continueTriggering) - { - DoCast(me, SPELL_BLESSING_OF_THE_TIDES); - me->MonsterYell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_GAIN_BLESSING_OF_TIDES); - } - } - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Sharkkis AI -struct boss_fathomguard_sharkkisAI : public ScriptedAI -{ - boss_fathomguard_sharkkisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 LeechingThrow_Timer; - uint32 TheBeastWithin_Timer; - uint32 Multishot_Timer; - uint32 Pet_Timer; - - bool pet; - - uint64 SummonedPet; - - void Reset() - { - LeechingThrow_Timer = 20000; - TheBeastWithin_Timer = 30000; - Multishot_Timer = 15000; - Pet_Timer = 10000; - - pet = false; - - Creature *Pet = Unit::GetCreature(*me, SummonedPet); - if (Pet && Pet->isAlive()) - { - Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - SummonedPet = 0; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //LeechingThrow_Timer - if (LeechingThrow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LEECHING_THROW); - LeechingThrow_Timer = 20000; - } else LeechingThrow_Timer -= diff; - - //Multishot_Timer - if (Multishot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MULTISHOT); - Multishot_Timer = 20000; - } else Multishot_Timer -= diff; - - //TheBeastWithin_Timer - if (TheBeastWithin_Timer <= diff) - { - DoCast(me, SPELL_THE_BEAST_WITHIN); - Creature *Pet = Unit::GetCreature(*me, SummonedPet); - if (Pet && Pet->isAlive()) - { - Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); - } - TheBeastWithin_Timer = 30000; - } else TheBeastWithin_Timer -= diff; - - //Pet_Timer - if (Pet_Timer < diff && pet == false) - { - pet = true; - //uint32 spell_id; - uint32 pet_id; - if (!urand(0,1)) - { - //spell_id = SPELL_SUMMON_FATHOM_LURKER; - pet_id = CREATURE_FATHOM_LURKER; - } - else - { - //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; - pet_id = CREATURE_FATHOM_SPOREBAT; - } - //DoCast(me, spell_id, true); - Creature *Pet = DoSpawnCreature(pet_id,0,0,0,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (Pet && pTarget) - { - Pet->AI()->AttackStart(pTarget); - SummonedPet = Pet->GetGUID(); - } - } else Pet_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Tidalvess AI -struct boss_fathomguard_tidalvessAI : public ScriptedAI -{ - boss_fathomguard_tidalvessAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 FrostShock_Timer; - uint32 Spitfire_Timer; - uint32 PoisonCleansing_Timer; - uint32 Earthbind_Timer; - - void Reset() - { - FrostShock_Timer = 25000; - Spitfire_Timer = 60000; - PoisonCleansing_Timer = 30000; - Earthbind_Timer = 45000; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - if (!me->isAlive() && Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventTidalvessDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - DoCast(me, SPELL_WINDFURY_WEAPON); - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - if (!me->HasAura(SPELL_WINDFURY_WEAPON)) - { - DoCast(me, SPELL_WINDFURY_WEAPON); - } - - //FrostShock_Timer - if (FrostShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_SHOCK); - FrostShock_Timer = 25000+rand()%5000; - } else FrostShock_Timer -= diff; - - //Spitfire_Timer - if (Spitfire_Timer <= diff) - { - DoCast(me, SPELL_SPITFIRE_TOTEM); - Unit *SpitfireTotem = Unit::GetUnit(*me, CREATURE_SPITFIRE_TOTEM); - if (SpitfireTotem) - { - CAST_CRE(SpitfireTotem)->AI()->AttackStart(me->getVictim()); - } - Spitfire_Timer = 60000; - } else Spitfire_Timer -= diff; - - //PoisonCleansing_Timer - if (PoisonCleansing_Timer <= diff) - { - DoCast(me, SPELL_POISON_CLEANSING_TOTEM); - PoisonCleansing_Timer = 30000; - } else PoisonCleansing_Timer -= diff; - - //Earthbind_Timer - if (Earthbind_Timer <= diff) - { - DoCast(me, SPELL_EARTHBIND_TOTEM); - Earthbind_Timer = 45000; - } else Earthbind_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Caribdis AI -struct boss_fathomguard_caribdisAI : public ScriptedAI -{ - boss_fathomguard_caribdisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 WaterBoltVolley_Timer; - uint32 TidalSurge_Timer; - uint32 Heal_Timer; - uint32 Cyclone_Timer; - - void Reset() - { - WaterBoltVolley_Timer = 35000; - TidalSurge_Timer = 15000+rand()%5000; - Heal_Timer = 55000; - Cyclone_Timer = 30000+rand()%10000; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - if (!me->isAlive() && Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventCaribdisDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //WaterBoltVolley_Timer - if (WaterBoltVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WATER_BOLT_VOLLEY); - WaterBoltVolley_Timer = 30000; - } else WaterBoltVolley_Timer -= diff; - - //TidalSurge_Timer - if (TidalSurge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIDAL_SURGE); - // Hacky way to do it - won't trigger elseways - me->getVictim()->CastSpell(me->getVictim(), SPELL_TIDAL_SURGE_FREEZE, true); - TidalSurge_Timer = 15000+rand()%5000; - } else TidalSurge_Timer -= diff; - - //Cyclone_Timer - if (Cyclone_Timer <= diff) - { - //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work - Cyclone_Timer = 30000+rand()%10000; - Creature *Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000); - if (Cyclone) - { - CAST_CRE(Cyclone)->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); - Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Cyclone->setFaction(me->getFaction()); - Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Cyclone->AI()->AttackStart(pTarget); - } - } - } else Cyclone_Timer -= diff; - - //Heal_Timer - if (Heal_Timer <= diff) - { - // It can be cast on any of the mobs - Unit *pUnit = NULL; - - while (pUnit == NULL || !pUnit->isAlive()) - { - pUnit = selectAdvisorUnit(); - } - - if (pUnit && pUnit->isAlive()) - DoCast(pUnit, SPELL_HEAL); - Heal_Timer = 60000; - } else Heal_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - Unit* selectAdvisorUnit() - { - Unit* pUnit = NULL; - if (pInstance) - { - switch(rand()%4) - { - case 0: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESS)); - break; - case 1: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_SHARKKIS)); - break; - case 2: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_TIDALVESS)); - break; - case 3: - pUnit = me; - break; - } - } else pUnit = me; - - return pUnit; - } -}; - -CreatureAI* GetAI_boss_fathomlord_karathress(Creature* pCreature) -{ - return new boss_fathomlord_karathressAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_sharkkis(Creature* pCreature) -{ - return new boss_fathomguard_sharkkisAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_tidalvess(Creature* pCreature) -{ - return new boss_fathomguard_tidalvessAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_caribdis(Creature* pCreature) -{ - return new boss_fathomguard_caribdisAI (pCreature); -} - -void AddSC_boss_fathomlord_karathress() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_fathomlord_karathress"; - newscript->GetAI = &GetAI_boss_fathomlord_karathress; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_sharkkis"; - newscript->GetAI = &GetAI_boss_fathomguard_sharkkis; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_tidalvess"; - newscript->GetAI = &GetAI_boss_fathomguard_tidalvess; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_caribdis"; - newscript->GetAI = &GetAI_boss_fathomguard_caribdis; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp deleted file mode 100644 index 923fdf55f80..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hydross_The_Unstable -SD%Complete: 90 -SDComment: Some details and adjustments left to do, probably nothing major. Spawns may be spawned in different way/location. -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define SAY_AGGRO -1548000 -#define SAY_SWITCH_TO_CLEAN -1548001 -#define SAY_CLEAN_SLAY1 -1548002 -#define SAY_CLEAN_SLAY2 -1548003 -#define SAY_CLEAN_DEATH -1548004 -#define SAY_SWITCH_TO_CORRUPT -1548005 -#define SAY_CORRUPT_SLAY1 -1548006 -#define SAY_CORRUPT_SLAY2 -1548007 -#define SAY_CORRUPT_DEATH -1548008 - -#define SWITCH_RADIUS 18 - -#define MODEL_CORRUPT 20609 -#define MODEL_CLEAN 20162 - -#define SPELL_WATER_TOMB 38235 -#define SPELL_MARK_OF_HYDROSS1 38215 -#define SPELL_MARK_OF_HYDROSS2 38216 -#define SPELL_MARK_OF_HYDROSS3 38217 -#define SPELL_MARK_OF_HYDROSS4 38218 -#define SPELL_MARK_OF_HYDROSS5 38231 -#define SPELL_MARK_OF_HYDROSS6 40584 -#define SPELL_MARK_OF_CORRUPTION1 38219 -#define SPELL_MARK_OF_CORRUPTION2 38220 -#define SPELL_MARK_OF_CORRUPTION3 38221 -#define SPELL_MARK_OF_CORRUPTION4 38222 -#define SPELL_MARK_OF_CORRUPTION5 38230 -#define SPELL_MARK_OF_CORRUPTION6 40583 -#define SPELL_VILE_SLUDGE 38246 -#define SPELL_ENRAGE 27680 //this spell need verification -#define SPELL_SUMMON_WATER_ELEMENT 36459 //not in use yet(in use ever?) -#define SPELL_ELEMENTAL_SPAWNIN 25035 -#define SPELL_BLUE_BEAM 40227 //channeled Hydross Beam Helper (not in use yet) - -#define ENTRY_PURE_SPAWN 22035 -#define ENTRY_TAINTED_SPAWN 22036 -#define ENTRY_BEAM_DUMMY 21934 - -#define HYDROSS_X -239.439 -#define HYDROSS_Y -363.481 - -#define SPAWN_X_DIFF1 6.934003 -#define SPAWN_Y_DIFF1 -11.255012 -#define SPAWN_X_DIFF2 -6.934003 -#define SPAWN_Y_DIFF2 11.255012 -#define SPAWN_X_DIFF3 -12.577011 -#define SPAWN_Y_DIFF3 -4.72702 -#define SPAWN_X_DIFF4 12.577011 -#define SPAWN_Y_DIFF4 4.72702 - -struct boss_hydross_the_unstableAI : public ScriptedAI -{ - boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 beams[2]; - uint32 PosCheck_Timer; - uint32 MarkOfHydross_Timer; - uint32 MarkOfCorruption_Timer; - uint32 WaterTomb_Timer; - uint32 VileSludge_Timer; - uint32 MarkOfHydross_Count; - uint32 MarkOfCorruption_Count; - uint32 EnrageTimer; - bool CorruptedForm; - bool beam; - SummonList Summons; - - void Reset() - { - DeSummonBeams(); - beams[0] = 0; - beams[1] = 0; - PosCheck_Timer = 2500; - MarkOfHydross_Timer = 15000; - MarkOfCorruption_Timer = 15000; - WaterTomb_Timer = 7000; - VileSludge_Timer = 7000; - MarkOfHydross_Count = 0; - MarkOfCorruption_Count = 0; - EnrageTimer = 600000; - - CorruptedForm = false; - me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - - me->SetDisplayId(MODEL_CLEAN); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); - beam = false; - Summons.DespawnAll(); - } - - void SummonBeams() - { - Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-258.333,-356.34,22.0499,5.90835,TEMPSUMMON_CORPSE_DESPAWN,0); - if (beamer) - { - beamer->CastSpell(me,SPELL_BLUE_BEAM,true); - beamer->SetDisplayId(11686); //invisible - beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - beams[0]=beamer->GetGUID(); - } - beamer = beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-219.918,-371.308,22.0042,2.73072,TEMPSUMMON_CORPSE_DESPAWN,0); - if (beamer) - { - beamer->CastSpell(me,SPELL_BLUE_BEAM,true); - beamer->SetDisplayId(11686); //invisible - beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - beams[1]=beamer->GetGUID(); - } - } - void DeSummonBeams() - { - for (uint8 i=0; i<2; ++i) - { - Creature* mob = Unit::GetCreature(*me,beams[i]); - if (mob) - { - mob->setDeathState(DEAD); - mob->RemoveCorpse(); - } - } - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - if (CorruptedForm) - { - DoScriptText(RAND(SAY_CORRUPT_SLAY1,SAY_CORRUPT_SLAY2), me); - } - else - { - DoScriptText(RAND(SAY_CLEAN_SLAY1,SAY_CLEAN_SLAY2), me); - } - } - - void JustSummoned(Creature* summoned) - { - if (summoned->GetEntry() == ENTRY_PURE_SPAWN) - { - summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); - Summons.Summon(summoned); - } - if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN) - { - summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); - Summons.Summon(summoned); - } - } - - void SummonedCreatureDespawn(Creature *summon) - { - Summons.Despawn(summon); - } - - void JustDied(Unit * /*victim*/) - { - if (CorruptedForm) - DoScriptText(SAY_CORRUPT_DEATH, me); - else - DoScriptText(SAY_CLEAN_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, DONE); - Summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!beam) - { - SummonBeams(); - beam=true; - } - //Return since we have no target - if (!UpdateVictim()) - return; - - // corrupted form - if (CorruptedForm) - { - //MarkOfCorruption_Timer - if (MarkOfCorruption_Timer <= diff) - { - if (MarkOfCorruption_Count <= 5) - { - uint32 mark_spell = 0; - - switch (MarkOfCorruption_Count) - { - case 0: mark_spell = SPELL_MARK_OF_CORRUPTION1; break; - case 1: mark_spell = SPELL_MARK_OF_CORRUPTION2; break; - case 2: mark_spell = SPELL_MARK_OF_CORRUPTION3; break; - case 3: mark_spell = SPELL_MARK_OF_CORRUPTION4; break; - case 4: mark_spell = SPELL_MARK_OF_CORRUPTION5; break; - case 5: mark_spell = SPELL_MARK_OF_CORRUPTION6; break; - } - - DoCast(me->getVictim(), mark_spell); - - if (MarkOfCorruption_Count < 5) - ++MarkOfCorruption_Count; - } - - MarkOfCorruption_Timer = 15000; - } else MarkOfCorruption_Timer -= diff; - - //VileSludge_Timer - if (VileSludge_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_VILE_SLUDGE); - - VileSludge_Timer = 15000; - } else VileSludge_Timer -= diff; - - //PosCheck_Timer - if (PosCheck_Timer <= diff) - { - if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) - { - // switch to clean form - me->SetDisplayId(MODEL_CLEAN); - CorruptedForm = false; - MarkOfHydross_Count = 0; - - DoScriptText(SAY_SWITCH_TO_CLEAN, me); - DoResetThreat(); - SummonBeams(); - - // spawn 4 adds - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - } - - PosCheck_Timer = 2500; - } else PosCheck_Timer -=diff; - } - // clean form - else - { - //MarkOfHydross_Timer - if (MarkOfHydross_Timer <= diff) - { - if (MarkOfHydross_Count <= 5) - { - uint32 mark_spell = NULL; - - switch(MarkOfHydross_Count) - { - case 0: mark_spell = SPELL_MARK_OF_HYDROSS1; break; - case 1: mark_spell = SPELL_MARK_OF_HYDROSS2; break; - case 2: mark_spell = SPELL_MARK_OF_HYDROSS3; break; - case 3: mark_spell = SPELL_MARK_OF_HYDROSS4; break; - case 4: mark_spell = SPELL_MARK_OF_HYDROSS5; break; - case 5: mark_spell = SPELL_MARK_OF_HYDROSS6; break; - } - - DoCast(me->getVictim(), mark_spell); - - if (MarkOfHydross_Count < 5) - ++MarkOfHydross_Count; - } - - MarkOfHydross_Timer = 15000; - } else MarkOfHydross_Timer -= diff; - - //WaterTomb_Timer - if (WaterTomb_Timer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget) - DoCast(pTarget, SPELL_WATER_TOMB); - - WaterTomb_Timer = 7000; - } else WaterTomb_Timer -= diff; - - //PosCheck_Timer - if (PosCheck_Timer <= diff) - { - if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) - { - // switch to corrupted form - me->SetDisplayId(MODEL_CORRUPT); - MarkOfCorruption_Count = 0; - CorruptedForm = true; - - DoScriptText(SAY_SWITCH_TO_CORRUPT, me); - DoResetThreat(); - DeSummonBeams(); - - // spawn 4 adds - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - } - - PosCheck_Timer = 2500; - } else PosCheck_Timer -=diff; - } - - //EnrageTimer - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - EnrageTimer = 60000; - } else EnrageTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_hydross_the_unstable(Creature* pCreature) -{ - return new boss_hydross_the_unstableAI (pCreature); -} - -void AddSC_boss_hydross_the_unstable() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hydross_the_unstable"; - newscript->GetAI = &GetAI_boss_hydross_the_unstable; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp deleted file mode 100644 index 2f0485d0e6c..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp +++ /dev/null @@ -1,1039 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA - */ - -/* ScriptData -SDName: Boss_Lady_Vashj -SD%Complete: 99 -SDComment: Missing blizzlike Shield Generators coords -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedSimpleAI.h" -#include "Spell.h" - -#define SAY_INTRO -1548042 -#define SAY_AGGRO1 -1548043 -#define SAY_AGGRO2 -1548044 -#define SAY_AGGRO3 -1548045 -#define SAY_AGGRO4 -1548046 -#define SAY_PHASE1 -1548047 -#define SAY_PHASE2 -1548048 -#define SAY_PHASE3 -1548049 -#define SAY_BOWSHOT1 -1548050 -#define SAY_BOWSHOT2 -1548051 -#define SAY_SLAY1 -1548052 -#define SAY_SLAY2 -1548053 -#define SAY_SLAY3 -1548054 -#define SAY_DEATH -1548055 - -#define SPELL_SURGE 38044 -#define SPELL_MULTI_SHOT 38310 -#define SPELL_SHOCK_BLAST 38509 -#define SPELL_ENTANGLE 38316 -#define SPELL_STATIC_CHARGE_TRIGGER 38280 -#define SPELL_FORKED_LIGHTNING 40088 -#define SPELL_SHOOT 40873 -#define SPELL_POISON_BOLT 40095 -#define SPELL_TOXIC_SPORES 38575 -#define SPELL_MAGIC_BARRIER 38112 - -#define MIDDLE_X 30.134 -#define MIDDLE_Y -923.65 -#define MIDDLE_Z 42.9 - -#define SPOREBAT_X 30.977156 -#define SPOREBAT_Y -925.297761 -#define SPOREBAT_Z 77.176567 -#define SPOREBAT_O 5.223932 - -#define SHIED_GENERATOR_CHANNEL 19870 -#define ENCHANTED_ELEMENTAL 21958 -#define TAINTED_ELEMENTAL 22009 -#define COILFANG_STRIDER 22056 -#define COILFANG_ELITE 22055 -#define TOXIC_SPOREBAT 22140 -#define TOXIC_SPORES_TRIGGER 22207 - -#define TEXT_NOT_INITIALIZED "Instance script not initialized" -#define TEXT_ALREADY_DEACTIVATED "Already deactivated" - -float ElementPos[8][4] = -{ - {8.3, -835.3, 21.9, 5}, - {53.4, -835.3, 21.9, 4.5}, - {96, -861.9, 21.8, 4}, - {96, -986.4, 21.4, 2.5}, - {54.4, -1010.6, 22, 1.8}, - {9.8, -1012, 21.7, 1.4}, - {-35, -987.6, 21.5, 0.8}, - {-58.9, -901.6, 21.5, 6} -}; - -float ElementWPPos[8][3] = -{ - {71.700752, -883.905884, 41.097168}, - {45.039848, -868.022827, 41.097015}, - {14.585141, -867.894470, 41.097061}, - {-25.415508, -906.737732, 41.097061}, - {-11.801594, -963.405884, 41.097067}, - {14.556657, -979.051514, 41.097137}, - {43.466549, -979.406677, 41.097027}, - {69.945908, -964.663940, 41.097054} -}; - -float SporebatWPPos[8][3] = -{ - {31.6,-896.3,59.1}, - {9.1, -913.9, 56}, - {5.2, -934.4, 52.4}, - {20.7, -946.9, 49.7}, - {41, -941.9, 51}, - {47.7, -927.3, 55}, - {42.2, -912.4, 51.7}, - {27, -905.9, 50} -}; - -float CoilfangElitePos[3][4] = -{ - {28.84, -923.28, 42.9, 6}, - {31.183281, -953.502625, 41.523602, 1.640957}, - {58.895180, -923.124268, 41.545307, 3.152848} -}; - -float CoilfangStriderPos[3][4] = -{ - {66.427010, -948.778503, 41.262245, 2.584220}, - {7.513962, -959.538208, 41.300422, 1.034629}, - {-12.843201, -907.798401, 41.239620, 6.087094} -}; - -float ShieldGeneratorChannelPos[4][4] = -{ - {49.6262, -902.181, 43.0975, 3.95683}, - {10.988, -901.616, 42.5371, 5.4373}, - {10.3859, -944.036, 42.5446, 0.779888}, - {49.3126, -943.398, 42.5501, 2.40174} -}; - -//Lady Vashj AI -struct boss_lady_vashjAI : public ScriptedAI -{ - boss_lady_vashjAI (Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = false; - JustCreated = true; - c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //set it only once on Creature create (no need do intro if wiped) - } - - ScriptedInstance *pInstance; - - uint64 ShieldGeneratorChannel[4]; - - uint32 AggroTimer; - uint32 ShockBlast_Timer; - uint32 Entangle_Timer; - uint32 StaticCharge_Timer; - uint32 ForkedLightning_Timer; - uint32 Check_Timer; - uint32 EnchantedElemental_Timer; - uint32 TaintedElemental_Timer; - uint32 CoilfangElite_Timer; - uint32 CoilfangStrider_Timer; - uint32 SummonSporebat_Timer; - uint32 SummonSporebat_StaticTimer; - uint8 EnchantedElemental_Pos; - uint8 Phase; - - bool Entangle; - bool Intro; - bool CanAttack; - bool JustCreated; - - void Reset() - { - AggroTimer = 19000; - ShockBlast_Timer = 1+rand()%60000; - Entangle_Timer = 30000; - StaticCharge_Timer = 10000+rand()%15000; - ForkedLightning_Timer = 2000; - Check_Timer = 15000; - EnchantedElemental_Timer = 5000; - TaintedElemental_Timer = 50000; - CoilfangElite_Timer = 45000+rand()%5000; - CoilfangStrider_Timer = 60000+rand()%10000; - SummonSporebat_Timer = 10000; - SummonSporebat_StaticTimer = 30000; - EnchantedElemental_Pos = 0; - Phase = 0; - - Entangle = false; - if (JustCreated) - { - CanAttack = false; - JustCreated = false; - } else CanAttack = true; - - Unit *remo; - for (uint8 i = 0; i < 4; ++i) - { - remo = Unit::GetUnit(*me, ShieldGeneratorChannel[i]); - if (remo) - remo->setDeathState(JUST_DIED); - } - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED); - ShieldGeneratorChannel[0] = 0; - ShieldGeneratorChannel[1] = 0; - ShieldGeneratorChannel[2] = 0; - ShieldGeneratorChannel[3] = 0; - - me->SetCorpseDelay(1000*60*60); - } - - //Called when a tainted elemental dies - void EventTaintedElementalDeath() - { - //the next will spawn 50 seconds after the previous one's death - if (TaintedElemental_Timer > 50000) - TaintedElemental_Timer = 50000; - } - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, DONE); - } - - void StartEvent() - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3,SAY_AGGRO4), me); - - Phase = 1; - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - //remove old tainted cores to prevent cheating in phase 2 - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* i_pl = i->getSource()) - { - i_pl->DestroyItemCount(31088, 1, true); - } - } - } - StartEvent();//this is EnterCombat(), so were are 100% in combat, start the event - - if (Phase != 2) - AttackStart(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (!Intro) - { - Intro = true; - DoScriptText(SAY_INTRO, me); - } - if (!CanAttack) - return; - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) - { - //if (who->HasStealthAura()) - // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - - if (!me->isInCombat())//AttackStart() sets UNIT_FLAG_IN_COMBAT, so this msut be before attacking - StartEvent(); - - if (Phase != 2) - AttackStart(who); - } - } - } - - void CastShootOrMultishot() - { - switch (urand(0,1)) - { - case 0: - //Shoot - //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. - DoCast(me->getVictim(), SPELL_SHOOT); - break; - case 1: - //Multishot - //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. - DoCast(me->getVictim(), SPELL_MULTI_SHOT); - break; - } - if (rand()%3) - { - DoScriptText(RAND(SAY_BOWSHOT1,SAY_BOWSHOT2), me); - } - } - - void UpdateAI(const uint32 diff) - { - if (!CanAttack && Intro) - { - if (AggroTimer <= diff) - { - CanAttack = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer=19000; - }else - { - AggroTimer-=diff; - return; - } - } - //to prevent abuses during phase 2 - if (Phase == 2 && !me->getVictim() && me->isInCombat()) - { - EnterEvadeMode(); - return; - } - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Phase == 1 || Phase == 3) - { - //ShockBlast_Timer - if (ShockBlast_Timer <= diff) - { - //Shock Burst - //Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. - DoCast(me->getVictim(), SPELL_SHOCK_BLAST); - me->TauntApply(me->getVictim()); - - ShockBlast_Timer = 1000+rand()%14000; //random cooldown - } else ShockBlast_Timer -= diff; - - //StaticCharge_Timer - if (StaticCharge_Timer <= diff) - { - //Static Charge - //Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. - Unit *pTarget = NULL; - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true); - - if (pTarget && !pTarget->HasAura(SPELL_STATIC_CHARGE_TRIGGER)) - //cast Static Charge every 2 seconds for 20 seconds - DoCast(pTarget, SPELL_STATIC_CHARGE_TRIGGER); - - StaticCharge_Timer = 10000+rand()%20000; //blizzlike - } else StaticCharge_Timer -= diff; - - //Entangle_Timer - if (Entangle_Timer <= diff) - { - if (!Entangle) - { - //Entangle - //Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. - DoCast(me->getVictim(), SPELL_ENTANGLE); - Entangle = true; - Entangle_Timer = 10000; - } - else - { - CastShootOrMultishot(); - Entangle = false; - Entangle_Timer = 20000+rand()%5000; - } - } else Entangle_Timer -= diff; - - //Phase 1 - if (Phase == 1) - { - //Start phase 2 - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 70) - { - //Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. - Phase = 2; - - me->GetMotionMaster()->Clear(); - DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - - Creature *pCreature; - for (uint8 i = 0; i < 4; ++i) - { - pCreature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0], ShieldGeneratorChannelPos[i][1], ShieldGeneratorChannelPos[i][2], ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); - if (pCreature) - ShieldGeneratorChannel[i] = pCreature->GetGUID(); - } - DoScriptText(SAY_PHASE2, me); - } - } - //Phase 3 - else - { - //SummonSporebat_Timer - if (SummonSporebat_Timer <= diff) - { - Creature *Sporebat = NULL; - Sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (Sporebat) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Sporebat->AI()->AttackStart(pTarget); - } - - //summon sporebats faster and faster - if (SummonSporebat_StaticTimer > 1000) - SummonSporebat_StaticTimer -= 1000; - - SummonSporebat_Timer = SummonSporebat_StaticTimer; - - if (SummonSporebat_Timer < 5000) - SummonSporebat_Timer = 5000; - - } else SummonSporebat_Timer -= diff; - } - - //Melee attack - DoMeleeAttackIfReady(); - - //Check_Timer - used to check if somebody is in melee range - if (Check_Timer <= diff) - { - bool InMeleeRange = false; - Unit *pTarget; - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //if in melee range - if (pTarget && pTarget->IsWithinDistInMap(me, 5)) - { - InMeleeRange = true; - break; - } - } - - //if nobody is in melee range - if (!InMeleeRange) - CastShootOrMultishot(); - - Check_Timer = 5000; - } else Check_Timer -= diff; - } - //Phase 2 - else - { - //ForkedLightning_Timer - if (ForkedLightning_Timer <= diff) - { - //Forked Lightning - //Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (!pTarget) - pTarget = me->getVictim(); - - DoCast(pTarget, SPELL_FORKED_LIGHTNING); - - ForkedLightning_Timer = 2000+rand()%6000; //blizzlike - } else ForkedLightning_Timer -= diff; - - //EnchantedElemental_Timer - if (EnchantedElemental_Timer <= diff) - { - Creature *Elemental; - Elemental = me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (EnchantedElemental_Pos == 7) - EnchantedElemental_Pos = 0; - else - ++EnchantedElemental_Pos; - - EnchantedElemental_Timer = 10000+rand()%5000; - } else EnchantedElemental_Timer -= diff; - - //TaintedElemental_Timer - if (TaintedElemental_Timer <= diff) - { - Creature *Tain_Elemental; - uint32 pos = rand()%8; - Tain_Elemental = me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN, 0); - - TaintedElemental_Timer = 120000; - } else TaintedElemental_Timer -= diff; - - //CoilfangElite_Timer - if (CoilfangElite_Timer <= diff) - { - uint32 pos = rand()%3; - Creature* CoilfangElite = NULL; - CoilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (CoilfangElite) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - CoilfangElite->AI()->AttackStart(pTarget); - else if (me->getVictim()) - CoilfangElite->AI()->AttackStart(me->getVictim()); - } - CoilfangElite_Timer = 45000+rand()%5000; - } else CoilfangElite_Timer -= diff; - - //CoilfangStrider_Timer - if (CoilfangStrider_Timer <= diff) - { - uint32 pos = rand()%3; - Creature* CoilfangStrider = NULL; - CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (CoilfangStrider) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - CoilfangStrider->AI()->AttackStart(pTarget); - else if (me->getVictim()) - CoilfangStrider->AI()->AttackStart(me->getVictim()); - } - CoilfangStrider_Timer = 60000+rand()%10000; - } else CoilfangStrider_Timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - //Start Phase 3 - if (pInstance && pInstance->GetData(DATA_CANSTARTPHASE3)) - { - //set life 50% - me->SetHealth(me->GetMaxHealth()/2); - - me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); - - DoScriptText(SAY_PHASE3, me); - - Phase = 3; - - //return to the tank - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - Check_Timer = 1000; - } else Check_Timer -= diff; - } - } -}; - -//Enchanted Elemental -//If one of them reaches Vashj he will increase her damage done by 5%. -struct mob_enchanted_elementalAI : public ScriptedAI -{ - mob_enchanted_elementalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 move; - uint32 phase; - float x, y, z; - - uint64 VashjGUID; - - void Reset() - { - me->SetSpeed(MOVE_WALK,0.6);//walk - me->SetSpeed(MOVE_RUN,0.6);//run - move = 0; - phase = 1; - - VashjGUID = 0; - - for (int i = 0; i<8; ++i)//search for nearest waypoint (up on stairs) - { - if (!x || !y || !z) - { - x = ElementWPPos[i][0]; - y = ElementWPPos[i][1]; - z = ElementWPPos[i][2]; - } - else - { - if (me->GetDistance(ElementWPPos[i][0],ElementWPPos[i][1],ElementWPPos[i][2]) < me->GetDistance(x,y,z)) - { - x = ElementWPPos[i][0]; - y = ElementWPPos[i][1]; - z = ElementWPPos[i][2]; - } - } - } - if (pInstance) - VashjGUID = pInstance->GetData64(DATA_LADYVASHJ); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (!VashjGUID) - return; - - if (move <= diff) - { - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - if (phase == 1) - me->GetMotionMaster()->MovePoint(0, x, y, z); - if (phase == 1 && me->IsWithinDist3d(x,y,z, 0.1)) - phase = 2; - if (phase == 2) - { - me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - phase = 3; - } - if (phase == 3) - { - me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - if (me->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) - DoCast(me, SPELL_SURGE); - } - if (Creature *Vashj = Unit::GetCreature(*me, VashjGUID)) - { - if (!Vashj->isInCombat() || CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase != 2 || Vashj->isDead()) - { - //call Unsummon() - me->Kill(me); - } - } - move = 1000; - } else move -= diff; - } -}; - -//Tainted Elemental -//This mob has 7,900 life, doesn't move, and shoots Poison Bolts at one person anywhere in the area, doing 3,000 nature damage and placing a posion doing 2,000 damage every 2 seconds. He will switch targets often, or sometimes just hang on a single player, but there is nothing you can do about it except heal the damage and kill the Tainted Elemental -struct mob_tainted_elementalAI : public ScriptedAI -{ - mob_tainted_elementalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 PoisonBolt_Timer; - uint32 Despawn_Timer; - - void Reset() - { - PoisonBolt_Timer = 5000+rand()%5000; - Despawn_Timer = 30000; - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - { - Creature *Vashj = NULL; - Vashj = (Unit::GetCreature((*me), pInstance->GetData64(DATA_LADYVASHJ))); - - if (Vashj) - CAST_AI(boss_lady_vashjAI, Vashj->AI())->EventTaintedElementalDeath(); - } - } - - void EnterCombat(Unit * who) - { - me->AddThreat(who, 0.1f); - } - - void UpdateAI(const uint32 diff) - { - //PoisonBolt_Timer - if (PoisonBolt_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget && pTarget->IsWithinDistInMap(me, 30)) - DoCast(pTarget, SPELL_POISON_BOLT); - - PoisonBolt_Timer = 5000+rand()%5000; - } else PoisonBolt_Timer -= diff; - - //Despawn_Timer - if (Despawn_Timer <= diff) - { - //call Unsummon() - me->setDeathState(DEAD); - - //to prevent crashes - Despawn_Timer = 1000; - } else Despawn_Timer -= diff; - } -}; - -//Toxic Sporebat -//Toxic Spores: Used in Phase 3 by the Spore Bats, it creates a contaminated green patch of ground, dealing about 2775-3225 nature damage every second to anyone who stands in it. -struct mob_toxic_sporebatAI : public ScriptedAI -{ - mob_toxic_sporebatAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EnterEvadeMode(); - } - - ScriptedInstance *pInstance; - - uint32 movement_timer; - uint32 ToxicSpore_Timer; - uint32 bolt_timer; - uint32 Check_Timer; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->setFaction(14); - movement_timer = 0; - ToxicSpore_Timer = 5000; - bolt_timer = 5500; - Check_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - - } - - void MoveInLineOfSight(Unit * /*who*/) - { - - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - movement_timer = 0; - } - - void UpdateAI (const uint32 diff) - { - //Random movement - if (movement_timer <= diff) - { - uint32 rndpos = rand()%8; - me->GetMotionMaster()->MovePoint(1,SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]); - movement_timer = 6000; - } else movement_timer -= diff; - - //toxic spores - if (bolt_timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); - if (trig) - { - trig->setFaction(14); - trig->CastSpell(trig, SPELL_TOXIC_SPORES,true); - } - } - bolt_timer = 10000+rand()%5000; - } - else bolt_timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - if (pInstance) - { - //check if vashj is death - Unit *Vashj = NULL; - Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); - if (!Vashj || (Vashj && !Vashj->isAlive()) || (Vashj && CAST_AI(boss_lady_vashjAI, CAST_CRE(Vashj)->AI())->Phase != 3)) - { - //remove - me->setDeathState(DEAD); - me->RemoveCorpse(); - me->setFaction(35); - } - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - } -}; - -//Coilfang Elite -//It's an elite Naga mob with 170,000 HP. It does about 5000 damage on plate, and has a nasty cleave hitting for about 7500 damage -CreatureAI* GetAI_mob_coilfang_elite(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = 31345; //Cleave - ai->Spell[0].Cooldown = 15000; - ai->Spell[0].CooldownRandomAddition = 5000; - ai->Spell[0].First_Cast = 5000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_RANDOM; - - ai->EnterEvadeMode(); - - return ai; -} - -//Coilfang Strider -//It hits plate for about 8000 damage, has a Mind Blast spell doing about 3000 shadow damage, and a Psychic Scream Aura, which fears everybody in a 8 yard range of it every 2-3 seconds , for 5 seconds and increasing their movement speed by 150% during the fear. -CreatureAI* GetAI_mob_coilfang_strider(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = 41374; //Mind Blast - ai->Spell[0].Cooldown = 30000; - ai->Spell[0].CooldownRandomAddition = 10000; - ai->Spell[0].First_Cast = 8000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - //Scream aura not implemented - - ai->EnterEvadeMode(); - - return ai; -} - -struct mob_shield_generator_channelAI : public ScriptedAI -{ - mob_shield_generator_channelAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 Check_Timer; - bool Casted; - void Reset() - { - Check_Timer = 0; - Casted = false; - me->SetDisplayId(11686); //invisible - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI (const uint32 diff) - { - if (!pInstance) - return; - - if (Check_Timer <= diff) - { - Unit *Vashj = NULL; - Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); - - if (Vashj && Vashj->isAlive()) - { - //start visual channel - if (!Casted || !Vashj->HasAura(SPELL_MAGIC_BARRIER)) - { - DoCast(Vashj, SPELL_MAGIC_BARRIER, true); - Casted = true; - } - } - Check_Timer = 1000; - } else Check_Timer -= diff; - } -}; - -bool ItemUse_item_tainted_core(Player* pPlayer, Item* /*_Item*/, SpellCastTargets const& targets) -{ - ScriptedInstance *pInstance = pPlayer->GetInstanceData(); - - if (!pInstance) - { - pPlayer->GetSession()->SendNotification(TEXT_NOT_INITIALIZED); - return true; - } - - Creature *Vashj = NULL; - Vashj = (Unit::GetCreature((*pPlayer), pInstance->GetData64(DATA_LADYVASHJ))); - if (Vashj && CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase == 2) - { - if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT) - { - uint32 identifier; - uint8 channel_identifier; - switch(targets.getGOTarget()->GetEntry()) - { - case 185052: - identifier = DATA_SHIELDGENERATOR1; - channel_identifier = 0; - break; - case 185053: - identifier = DATA_SHIELDGENERATOR2; - channel_identifier = 1; - break; - case 185051: - identifier = DATA_SHIELDGENERATOR3; - channel_identifier = 2; - break; - case 185054: - identifier = DATA_SHIELDGENERATOR4; - channel_identifier = 3; - break; - default: - return true; - } - - if (pInstance->GetData(identifier)) - { - pPlayer->GetSession()->SendNotification(TEXT_ALREADY_DEACTIVATED); - return true; - } - - //get and remove channel - Unit *Channel = NULL; - Channel = Unit::GetCreature(*Vashj, CAST_AI(boss_lady_vashjAI, Vashj->AI())->ShieldGeneratorChannel[channel_identifier]); - if (Channel) - { - //call Unsummon() - Channel->setDeathState(JUST_DIED); - } - - pInstance->SetData(identifier, 1); - - //remove this item - pPlayer->DestroyItemCount(31088, 1, true); - return true; - } - else if (targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT) - return false; - else if (targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) - { - pPlayer->DestroyItemCount(31088, 1, true); - pPlayer->CastSpell(targets.getUnitTarget(), 38134, true); - return true; - } - } - return true; -} - -CreatureAI* GetAI_boss_lady_vashj(Creature* pCreature) -{ - return new boss_lady_vashjAI (pCreature); -} - -CreatureAI* GetAI_mob_enchanted_elemental(Creature* pCreature) -{ - return new mob_enchanted_elementalAI (pCreature); -} - -CreatureAI* GetAI_mob_tainted_elemental(Creature* pCreature) -{ - return new mob_tainted_elementalAI (pCreature); -} - -CreatureAI* GetAI_mob_toxic_sporebat(Creature* pCreature) -{ - return new mob_toxic_sporebatAI (pCreature); -} - -CreatureAI* GetAI_mob_shield_generator_channel(Creature* pCreature) -{ - return new mob_shield_generator_channelAI (pCreature); -} - -void AddSC_boss_lady_vashj() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lady_vashj"; - newscript->GetAI = &GetAI_boss_lady_vashj; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_enchanted_elemental"; - newscript->GetAI = &GetAI_mob_enchanted_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tainted_elemental"; - newscript->GetAI = &GetAI_mob_tainted_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_toxic_sporebat"; - newscript->GetAI = &GetAI_mob_toxic_sporebat; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_elite"; - newscript->GetAI = &GetAI_mob_coilfang_elite; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_strider"; - newscript->GetAI = &GetAI_mob_coilfang_strider; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shield_generator_channel"; - newscript->GetAI = &GetAI_mob_shield_generator_channel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_tainted_core"; - newscript->pItemUse = &ItemUse_item_tainted_core; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp deleted file mode 100644 index 61c9ed9d527..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Leotheras_The_Blind -SD%Complete: 80 -SDComment: Possesion Support -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -// --- Spells used by Leotheras The Blind -#define SPELL_WHIRLWIND 37640 -#define SPELL_CHAOS_BLAST 37674 -#define SPELL_BERSERK 26662 -#define SPELL_INSIDIOUS_WHISPER 37676 -#define SPELL_DUAL_WIELD 42459 - -// --- Spells used in banish phase --- -#define BANISH_BEAM 38909 -#define AURA_BANISH 37833 - -// --- Spells used by Greyheart Spellbinders -#define SPELL_EARTHSHOCK 39076 -#define SPELL_MINDBLAST 37531 - -// --- Spells used by Inner Demons and Creature ID -#define INNER_DEMON_ID 21857 -#define AURA_DEMONIC_ALIGNMENT 37713 -#define SPELL_SHADOWBOLT 39309 -#define SPELL_SOUL_LINK 38007 -#define SPELL_CONSUMING_MADNESS 37749 //not supported by core yet - -//Misc. -#define MODEL_DEMON 20125 -#define MODEL_NIGHTELF 20514 -#define DEMON_FORM 21875 -#define MOB_SPELLBINDER 21806 - -#define SAY_AGGRO -1548009 -#define SAY_SWITCH_TO_DEMON -1548010 -#define SAY_INNER_DEMONS -1548011 -#define SAY_DEMON_SLAY1 -1548012 -#define SAY_DEMON_SLAY2 -1548013 -#define SAY_DEMON_SLAY3 -1548014 -#define SAY_NIGHTELF_SLAY1 -1548015 -#define SAY_NIGHTELF_SLAY2 -1548016 -#define SAY_NIGHTELF_SLAY3 -1548017 -#define SAY_FINAL_FORM -1548018 -#define SAY_FREE -1548019 -#define SAY_DEATH -1548020 - -struct mob_inner_demonAI : public ScriptedAI -{ - mob_inner_demonAI(Creature *c) : ScriptedAI(c) - { - victimGUID = 0; - } - - uint32 ShadowBolt_Timer; - - uint32 Link_Timer; - uint64 victimGUID; - - void Reset() - { - ShadowBolt_Timer = 10000; - Link_Timer = 1000; - } - void JustDied(Unit * /*victim*/) - { - Unit* pUnit = Unit::GetUnit((*me),victimGUID); - if (pUnit && pUnit->HasAura(SPELL_INSIDIOUS_WHISPER)) - pUnit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID()) - { - damage = 0; - DoModifyThreatPercent(done_by, -100); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (!victimGUID) return; - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (me->getVictim()->GetGUID() != victimGUID) - { - DoModifyThreatPercent(me->getVictim(), -100); - Unit* owner = Unit::GetUnit((*me),victimGUID); - if (owner && owner->isAlive()) - { - me->AddThreat(owner,999999); - AttackStart(owner); - } else if (owner && owner->isDead()) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - } - - if (Link_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOUL_LINK, true); - Link_Timer = 1000; - } else Link_Timer -= diff; - - if (!me->HasAura(AURA_DEMONIC_ALIGNMENT)) - DoCast(me, AURA_DEMONIC_ALIGNMENT, true); - - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLT, false); - ShadowBolt_Timer = 10000; - } else ShadowBolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -//Original Leotheras the Blind AI -struct boss_leotheras_the_blindAI : public ScriptedAI -{ - boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c) - { - c->GetPosition(x,y,z); - pInstance = c->GetInstanceData(); - Demon = 0; - - for (uint8 i = 0; i < 3; ++i)//clear guids - SpellBinderGUID[i] = 0; - } - - ScriptedInstance *pInstance; - - uint32 Whirlwind_Timer; - uint32 ChaosBlast_Timer; - uint32 SwitchToDemon_Timer; - uint32 SwitchToHuman_Timer; - uint32 Berserk_Timer; - uint32 InnerDemons_Timer; - uint32 BanishTimer; - - bool DealDamage; - bool NeedThreatReset; - bool DemonForm; - bool IsFinalForm; - bool EnrageUsed; - float x,y,z; - - uint64 InnderDemon[5]; - uint32 InnerDemon_Count; - uint64 Demon; - uint64 SpellBinderGUID[3]; - - void Reset() - { - CheckChannelers(); - BanishTimer = 1000; - Whirlwind_Timer = 15000; - ChaosBlast_Timer = 1000; - SwitchToDemon_Timer = 45000; - SwitchToHuman_Timer = 60000; - Berserk_Timer = 600000; - InnerDemons_Timer = 30000; - me->SetCanDualWield(true); - DealDamage = true; - DemonForm = false; - IsFinalForm = false; - NeedThreatReset = false; - EnrageUsed = false; - InnerDemon_Count = 0; - me->SetSpeed(MOVE_RUN, 2.0f, true); - me->SetDisplayId(MODEL_NIGHTELF); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - DoCast(me, SPELL_DUAL_WIELD, true); - me->SetCorpseDelay(1000*60*60); - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED); - } - - void CheckChannelers(/*bool DoEvade = true*/) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Creature *add = Unit::GetCreature(*me,SpellBinderGUID[i])) - add->DisappearAndDie(); - - float nx = x; - float ny = y; - float o = 2.4f; - if (i == 0) {nx += 10; ny -= 5; o=2.5f;} - if (i == 1) {nx -= 8; ny -= 7; o=0.9f;} - if (i == 2) {nx -= 3; ny += 9; o=5.0f;} - Creature* binder = me->SummonCreature(MOB_SPELLBINDER,nx,ny,z,o,TEMPSUMMON_DEAD_DESPAWN,0); - if (binder) - SpellBinderGUID[i] = binder->GetGUID(); - - } - } - void MoveInLineOfSight(Unit *who) - { - if (me->HasAura(AURA_BANISH)) - return; - - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius)) - { - // Check first that object is in an angle in front of this one before LoS check - if (me->HasInArc(M_PI/2.0f, who) && me->IsWithinLOSInMap(who)) - { - AttackStart(who); - } - } - } - } - - void StartEvent() - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, IN_PROGRESS); - } - - void CheckBanish() - { - uint8 AliveChannelers = 0; - for (uint8 i = 0; i < 3; ++i) - { - Unit *add = Unit::GetUnit(*me,SpellBinderGUID[i]); - if (add && add->isAlive()) - ++AliveChannelers; - } - - // channelers == 0 remove banish aura - if (AliveChannelers == 0 && me->HasAura(AURA_BANISH)) - { - // removing banish aura - me->RemoveAurasDueToSpell(AURA_BANISH); - - // Leotheras is getting immune again - me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); - - // changing model to bloodelf - me->SetDisplayId(MODEL_NIGHTELF); - - // and reseting equipment - me->LoadEquipment(me->GetEquipmentId()); - - if (pInstance && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - Unit *victim = NULL; - victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); - if (victim) - me->getThreatManager().addThreat(victim, 1); - StartEvent(); - } - } - else if (AliveChannelers != 0 && !me->HasAura(AURA_BANISH)) - { - // channelers != 0 apply banish aura - // removing Leotheras banish immune to apply AURA_BANISH - me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); - DoCast(me, AURA_BANISH); - - // changing model - me->SetDisplayId(MODEL_DEMON); - - // and removing weapons - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - } - } - - //Despawn all Inner Demon summoned - void DespawnDemon() - { - for (uint8 i=0; i<5; ++i) - { - if (InnderDemon[i]) - { - //delete creature - Creature* pCreature = Unit::GetCreature((*me), InnderDemon[i]); - if (pCreature && pCreature->isAlive()) - { - pCreature->ForcedDespawn(); - } - InnderDemon[i] = 0; - } - } - - InnerDemon_Count = 0; - } - - void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core - { - for (uint8 i=0; i<5; ++i) - { - if (InnderDemon[i] > 0) - { - Creature* pUnit = Unit::GetCreature((*me), InnderDemon[i]); - if (pUnit && pUnit->isAlive()) - { - Unit* pUnit_pTarget = Unit::GetUnit(*pUnit, CAST_AI(mob_inner_demonAI, pUnit->AI())->victimGUID); - if (pUnit_pTarget && pUnit_pTarget->isAlive()) - { - pUnit->CastSpell(pUnit_pTarget, SPELL_CONSUMING_MADNESS, true); - DoModifyThreatPercent(pUnit_pTarget, -100); - } - } - } - } - } - - void KilledUnit(Unit * victim) - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - if (DemonForm) - { - DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); - } - else - { - DoScriptText(RAND(SAY_NIGHTELF_SLAY1,SAY_NIGHTELF_SLAY2,SAY_NIGHTELF_SLAY3), me); - } - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - //despawn copy - if (Demon) - { - if (Creature* pDemon = Unit::GetCreature(*me, Demon)) - pDemon->ForcedDespawn(); - } - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - if (me->HasAura(AURA_BANISH)) - return; - - me->LoadEquipment(me->GetEquipmentId()); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (me->HasAura(AURA_BANISH) || !UpdateVictim()) - { - if (BanishTimer <= diff) - { - CheckBanish();//no need to check every update tick - BanishTimer = 1000; - } else BanishTimer -= diff; - return; - } - if (me->HasAura(SPELL_WHIRLWIND)) - if (Whirlwind_Timer <= diff) - { - Unit *newTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (newTarget) - { - DoResetThreat(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0,newTarget->GetPositionX(),newTarget->GetPositionY(),newTarget->GetPositionZ()); - } - Whirlwind_Timer = 2000; - } else Whirlwind_Timer -= diff; - - // reseting after changing forms and after ending whirlwind - if (NeedThreatReset && !me->HasAura(SPELL_WHIRLWIND)) - { - // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding) - if (DemonForm) - InnerDemons_Timer = 30000; - else - Whirlwind_Timer = 15000; - - NeedThreatReset = false; - DoResetThreat(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - - //Enrage_Timer (10 min) - if (Berserk_Timer < diff && !EnrageUsed) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_BERSERK); - EnrageUsed = true; - } else Berserk_Timer -= diff; - - if (!DemonForm) - { - //Whirldind Timer - if (!me->HasAura(SPELL_WHIRLWIND)) - { - if (Whirlwind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - // while whirlwinding this variable is used to countdown target's change - Whirlwind_Timer = 2000; - NeedThreatReset = true; - } else Whirlwind_Timer -= diff; - } - //Switch_Timer - - if (!IsFinalForm) - if (SwitchToDemon_Timer <= diff) - { - //switch to demon form - me->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0); - me->SetDisplayId(MODEL_DEMON); - DoScriptText(SAY_SWITCH_TO_DEMON, me); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - DemonForm = true; - NeedThreatReset = true; - SwitchToDemon_Timer = 45000; - } else SwitchToDemon_Timer -= diff; - DoMeleeAttackIfReady(); - } - else - { - //ChaosBlast_Timer - if (!me->getVictim()) - return; - if (me->IsWithinDist(me->getVictim(), 30)) - me->StopMoving(); - if (ChaosBlast_Timer <= diff) - { - // will cast only when in range of spell - if (me->IsWithinDist(me->getVictim(), 30)) - { - //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); - int damage = 100; - me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); - } - ChaosBlast_Timer = 3000; - } else ChaosBlast_Timer -= diff; - //Summon Inner Demon - if (InnerDemons_Timer <= diff) - { - std::list& ThreatList = me->getThreatManager().getThreatList(); - std::vector TargetList; - for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) - { - Unit *tempTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->getVictim()->GetGUID() && TargetList.size()<5) - TargetList.push_back(tempTarget); - } - //SpellEntry *spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); - for (std::vector::const_iterator itr = TargetList.begin(); itr != TargetList.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive()) - { - Creature * demon = me->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (demon) - { - demon->AI()->AttackStart((*itr)); - CAST_AI(mob_inner_demonAI, demon->AI())->victimGUID = (*itr)->GetGUID(); - - (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); - - if (InnerDemon_Count > 4) - InnerDemon_Count = 0; - - //Safe storing of creatures - InnderDemon[InnerDemon_Count] = demon->GetGUID(); - - //Update demon count - ++InnerDemon_Count; - } - } - } - DoScriptText(SAY_INNER_DEMONS, me); - - InnerDemons_Timer = 999999; - } else InnerDemons_Timer -= diff; - - //Switch_Timer - if (SwitchToHuman_Timer <= diff) - { - //switch to nightelf form - me->SetDisplayId(MODEL_NIGHTELF); - me->LoadEquipment(me->GetEquipmentId()); - - CastConsumingMadness(); - DespawnDemon(); - - DemonForm = false; - NeedThreatReset = true; - - SwitchToHuman_Timer = 60000; - } else SwitchToHuman_Timer -= diff; - } - - if (!IsFinalForm && (me->GetHealth()*100 / me->GetMaxHealth()) < 15) - { - //at this point he divides himself in two parts - CastConsumingMadness(); - DespawnDemon(); - Creature *Copy = NULL; - Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000); - if (Copy) - { - Demon = Copy->GetGUID(); - if (me->getVictim()) - Copy->AI()->AttackStart(me->getVictim()); - } - //set nightelf final form - IsFinalForm = true; - DemonForm = false; - - DoScriptText(SAY_FINAL_FORM, me); - me->SetDisplayId(MODEL_NIGHTELF); - me->LoadEquipment(me->GetEquipmentId()); - } - } -}; - -//Leotheras the Blind Demon Form AI -struct boss_leotheras_the_blind_demonformAI : public ScriptedAI -{ - boss_leotheras_the_blind_demonformAI(Creature *c) : ScriptedAI(c) {} - - uint32 ChaosBlast_Timer; - bool DealDamage; - - void Reset() - { - ChaosBlast_Timer = 1000; - DealDamage = true; - } - - void StartEvent() - { - DoScriptText(SAY_FREE, me); - } - - void KilledUnit(Unit * victim) - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) - DoCast(me, 8149, true); - } - - void EnterCombat(Unit * /*who*/) - { - StartEvent(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - //ChaosBlast_Timer - if (me->IsWithinDist(me->getVictim(), 30)) - me->StopMoving(); - - if (ChaosBlast_Timer <= diff) - { - // will cast only when in range od spell - if (me->IsWithinDist(me->getVictim(), 30)) - { - //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); - int damage = 100; - me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); - ChaosBlast_Timer = 3000; - } - } else ChaosBlast_Timer -= diff; - - //Do NOT deal any melee damage to the target. - } -}; -struct mob_greyheart_spellbinderAI : public ScriptedAI -{ - mob_greyheart_spellbinderAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - leotherasGUID = 0; - AddedBanish = false; - } - - ScriptedInstance *pInstance; - - uint64 leotherasGUID; - - uint32 Mindblast_Timer; - uint32 Earthshock_Timer; - - bool AddedBanish; - - void Reset() - { - Mindblast_Timer = 3000 + rand()%5000; - Earthshock_Timer = 5000 + rand()%5000; - - if (pInstance) - { - pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, 0); - Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); - if (leotheras && leotheras->isAlive()) - CAST_AI(boss_leotheras_the_blindAI, leotheras->AI())->CheckChannelers(/*false*/); - } - } - - void EnterCombat(Unit * who) - { - me->InterruptNonMeleeSpells(false); - if (pInstance) - pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID()); - } - - void JustRespawned() - { - AddedBanish = false; - Reset(); - } - - void CastChanneling() - { - if (!me->isInCombat() && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - { - if (leotherasGUID) - { - Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); - if (leotheras && leotheras->isAlive()) - DoCast(leotheras, BANISH_BEAM); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance) - { - if (!leotherasGUID) - leotherasGUID = pInstance->GetData64(DATA_LEOTHERAS); - - if (!me->isInCombat() && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - Unit *victim = NULL; - victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); - if (victim) - AttackStart(victim); - } - } - - if (!UpdateVictim()) - { - CastChanneling(); - return; - } - - if (pInstance && !pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - EnterEvadeMode(); - return; - } - - if (Mindblast_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (pTarget)DoCast(pTarget, SPELL_MINDBLAST); - - Mindblast_Timer = 10000 + rand()%5000; - } else Mindblast_Timer -= diff; - - if (Earthshock_Timer <= diff) - { - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) - { - if (Player* i_pl = itr->getSource()) - { - bool isCasting = false; - for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) - if (i_pl->GetCurrentSpell(i)) - isCasting = true; - - if (isCasting) - { - DoCast(i_pl, SPELL_EARTHSHOCK); - break; - } - } - } - Earthshock_Timer = 8000 + rand()%7000; - } else Earthshock_Timer -= diff; - DoMeleeAttackIfReady(); - } - - void JustDied(Unit * /*killer*/) {} -}; -CreatureAI* GetAI_boss_leotheras_the_blind(Creature* pCreature) -{ - return new boss_leotheras_the_blindAI (pCreature); -} - -CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature* pCreature) -{ - return new boss_leotheras_the_blind_demonformAI (pCreature); -} - -CreatureAI* GetAI_mob_greyheart_spellbinder(Creature* pCreature) -{ - return new mob_greyheart_spellbinderAI (pCreature); -} - -CreatureAI* GetAI_mob_inner_demon(Creature* pCreature) -{ - return new mob_inner_demonAI (pCreature); -} -void AddSC_boss_leotheras_the_blind() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_leotheras_the_blind"; - newscript->GetAI = &GetAI_boss_leotheras_the_blind; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_leotheras_the_blind_demonform"; - newscript->GetAI = &GetAI_boss_leotheras_the_blind_demonform; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_greyheart_spellbinder"; - newscript->GetAI = &GetAI_mob_greyheart_spellbinder; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_inner_demon"; - newscript->GetAI = &GetAI_mob_inner_demon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp deleted file mode 100644 index b1c0c10bcce..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: boss_the_lurker_below -SD%Complete: 80 -SDComment: Coilfang Frenzy, find out how could we fishing in the strangepool -SDCategory: The Lurker Below -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedSimpleAI.h" -#include "Spell.h" - -#define SPELL_SPOUT 37433 -#define SPELL_SPOUT_ANIM 42835 -#define SPELL_SPOUT_BREATH 37431 -#define SPELL_KNOCKBACK 19813 -#define SPELL_GEYSER 37478 -#define SPELL_WHIRL 37660 -#define SPELL_WATERBOLT 37138 -#define SPELL_SUBMERGE 37550 -#define SPELL_EMERGE 20568 - -#define EMOTE_SPOUT "The Lurker Below takes a deep breath." - -#define SPOUT_DIST 100 - -#define MOB_COILFANG_GUARDIAN 21873 -#define MOB_COILFANG_AMBUSHER 21865 - -//Ambusher spells -#define SPELL_SPREAD_SHOT 37790 -#define SPELL_SHOOT 37770 - -//Guardian spells -#define SPELL_ARCINGSMASH 38761 // Wrong SpellId. Can't find the right one. -#define SPELL_HAMSTRING 26211 - -float AddPos[9][3] = -{ - {2.8553810, -459.823914, -19.182686}, //MOVE_AMBUSHER_1 X, Y, Z - {12.400000, -466.042267, -19.182686}, //MOVE_AMBUSHER_2 X, Y, Z - {51.366653, -460.836060, -19.182686}, //MOVE_AMBUSHER_3 X, Y, Z - {62.597980, -457.433044, -19.182686}, //MOVE_AMBUSHER_4 X, Y, Z - {77.607452, -384.302765, -19.182686}, //MOVE_AMBUSHER_5 X, Y, Z - {63.897900, -378.984924, -19.182686}, //MOVE_AMBUSHER_6 X, Y, Z - {34.447250, -387.333618, -19.182686}, //MOVE_GUARDIAN_1 X, Y, Z - {14.388216, -423.468018, -19.625271}, //MOVE_GUARDIAN_2 X, Y, Z - {42.471519, -445.115295, -19.769423} //MOVE_GUARDIAN_3 X, Y, Z -}; - -struct boss_the_lurker_belowAI : public Scripted_NoMovementAI -{ - boss_the_lurker_belowAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - SpellEntry *TempSpell = GET_SPELL(SPELL_SPOUT_ANIM); - if (TempSpell) - { - TempSpell->Effect[0] = 0;//remove all spell effect, only anim is needed - TempSpell->Effect[1] = 0; - TempSpell->Effect[2] = 0; - } - } - - ScriptedInstance* pInstance; - SummonList Summons; - - bool Spawned; - bool Submerged; - bool InRange; - bool CanStartEvent; - uint32 RotTimer; - uint32 SpoutAnimTimer; - uint32 WaterboltTimer; - uint32 SpoutTimer; - uint32 WhirlTimer; - uint32 PhaseTimer; - uint32 GeyserTimer; - uint32 CheckTimer; - uint32 WaitTimer; - uint32 WaitTimer2; - - bool CheckCanStart()//check if players fished - { - if (pInstance && pInstance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) - return false; - return true; - } - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); - SpoutAnimTimer = 1000; - RotTimer = 0; - WaterboltTimer = 15000;//give time to get in range when fight starts - SpoutTimer = 45000; - WhirlTimer = 18000;//after avery spout - PhaseTimer = 120000; - GeyserTimer = rand()%5000 + 15000; - CheckTimer = 15000;//give time to get in range when fight starts - WaitTimer = 60000;//never reached - WaitTimer2 = 60000;//never reached - - Submerged = true;//will be false at combat start - Spawned = false; - InRange = false; - CanStartEvent = false; - - Summons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_THELURKERBELOWEVENT, NOT_STARTED); - pInstance->SetData(DATA_STRANGE_POOL, NOT_STARTED); - } - DoCast(me, SPELL_SUBMERGE);//submerge anim - me->SetVisibility(VISIBILITY_OFF);//we start invis under water, submerged - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_THELURKERBELOWEVENT, DONE); - - Summons.DespawnAll(); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - pInstance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS); - Scripted_NoMovementAI::EnterCombat(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (!CanStartEvent)//boss is invisible, don't attack - return; - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius)) - { - AttackStart(who); - } - } - } - - void MovementInform(uint32 type, uint32 /*id*/) - { - if (type == ROTATE_MOTION_TYPE) - me->SetReactState(REACT_AGGRESSIVE); - } - - void UpdateAI(const uint32 diff) - { - if (!CanStartEvent)//boss is invisible, don't attack - { - if (CheckCanStart()) - { - if (Submerged) - { - me->SetVisibility(VISIBILITY_ON); - Submerged = false; - WaitTimer2 = 500; - } - if (!Submerged && WaitTimer2 <= diff)//wait 500ms before emerge anim - { - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); - DoCast(me, SPELL_EMERGE, false); - WaitTimer2 = 60000;//never reached - WaitTimer = 3000; - } else WaitTimer2 -= diff; - - if (WaitTimer <= diff)//wait 3secs for emerge anim, then attack - { - WaitTimer = 3000; - CanStartEvent=true;//fresh fished from pool - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } else WaitTimer -= diff; - } - return; - } - - if (me->getThreatManager().getThreatList().empty())//check if should evade - { - if (me->isInCombat()) - EnterEvadeMode(); - return; - } - if (!Submerged) - { - if (PhaseTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SUBMERGE); - PhaseTimer = 60000;//60secs submerged - Submerged = true; - } else PhaseTimer-=diff; - - if (SpoutTimer <= diff) - { - me->MonsterTextEmote(EMOTE_SPOUT,0,true); - me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveRotate(20000, rand()%2 ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); - SpoutTimer = 45000; - WhirlTimer = 20000;//whirl directly after spout - RotTimer = 20000; - return; - } else SpoutTimer -= diff; - - //Whirl directly after a Spout and at random times - if (WhirlTimer <= diff) - { - WhirlTimer = 18000; - DoCast(me, SPELL_WHIRL); - } else WhirlTimer -= diff; - - if (CheckTimer <= diff)//check if there are players in melee range - { - InRange = false; - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (me->IsWithinMeleeRange(i->getSource())) - InRange = true; - } - } - CheckTimer = 2000; - } else CheckTimer -= diff; - - if (RotTimer) - { - Map* pMap = me->GetMap(); - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->isAlive() && me->HasInArc((double)diff/20000*(double)M_PI*2,i->getSource()) && me->IsWithinDist(i->getSource(), SPOUT_DIST) && !i->getSource()->IsInWater()) - DoCast(i->getSource(), SPELL_SPOUT, true);//only knock back palyers in arc, in 100yards, not in water - } - } - - if (SpoutAnimTimer <= diff) - { - DoCast(me, SPELL_SPOUT_ANIM, true); - SpoutAnimTimer = 1000; - } else SpoutAnimTimer -= diff; - - if (RotTimer <= diff) - { - RotTimer = 0; - } else RotTimer -= diff; - return; - } - - if (GeyserTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (!pTarget && me->getVictim()) - pTarget = me->getVictim(); - if (pTarget) - DoCast(pTarget, SPELL_GEYSER, true); - GeyserTimer = rand()%5000 + 15000; - } else GeyserTimer -= diff; - - if (!InRange)//if on players in melee range cast Waterbolt - { - if (WaterboltTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget && me->getVictim()) - pTarget = me->getVictim(); - if (pTarget) - DoCast(pTarget, SPELL_WATERBOLT, true); - WaterboltTimer = 3000; - } else WaterboltTimer -= diff; - } - - if (!UpdateCombatState()) - return; - - DoMeleeAttackIfReady(); - - }else//submerged - { - if (PhaseTimer <= diff) - { - Submerged = false; - me->InterruptNonMeleeSpells(false);//shouldn't be any - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); - DoCast(me, SPELL_EMERGE, true); - Spawned = false; - SpoutTimer = 3000; // directly cast Spout after emerging! - PhaseTimer = 120000; - return; - } else PhaseTimer-=diff; - - if (me->getThreatManager().getThreatList().empty())//check if should evade - { - EnterEvadeMode(); - return; - } - if (!me->isInCombat()) - DoZoneInCombat(); - - if (!Spawned) - { - me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - //spawn adds - for (uint8 i = 0; i < 9; ++i) - { - Creature* Summoned; - if (i < 6) - Summoned = me->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - else Summoned = me->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (Summoned) - Summons.Summon(Summoned); - } - Spawned = true; - } - } - } - }; - -CreatureAI* GetAI_mob_coilfang_guardian(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = SPELL_ARCINGSMASH; - ai->Spell[0].Cooldown = 15000; - ai->Spell[0].First_Cast = 5000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->Spell[1].Enabled = true; - ai->Spell[1].Spell_Id = SPELL_HAMSTRING; - ai->Spell[1].Cooldown = 10000; - ai->Spell[1].First_Cast = 2000; - ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; - - return ai; -} - -struct mob_coilfang_ambusherAI : public Scripted_NoMovementAI -{ - mob_coilfang_ambusherAI(Creature *c) : Scripted_NoMovementAI(c) - { - SpellEntry *TempSpell = GET_SPELL(SPELL_SHOOT); - if (TempSpell) - TempSpell->Effect[0] = 2;//change spell effect from weapon % dmg to simple phisical dmg - } - - uint32 MultiShotTimer; - uint32 ShootBowTimer; - - void Reset() - { - MultiShotTimer = 10000; - ShootBowTimer = 4000; - - } - - void EnterCombat(Unit * /*who*/) - { - - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who) && me->IsWithinDistInMap(who, 45)) - { - AttackStart(who); - } - } - - void UpdateAI(const uint32 diff) - { - if (MultiShotTimer <= diff) - { - if (me->getVictim()) - DoCast(me->getVictim(), SPELL_SPREAD_SHOT, true); - - MultiShotTimer = 10000+rand()%10000; - ShootBowTimer += 1500;//add global cooldown - } else MultiShotTimer -= diff; - - if (ShootBowTimer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - int bp0 = 1100; - if (pTarget) - me->CastCustomSpell(pTarget,SPELL_SHOOT,&bp0,NULL,NULL,true); - ShootBowTimer = 4000+rand()%5000; - MultiShotTimer += 1500;//add global cooldown - } else ShootBowTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_coilfang_ambusher(Creature* pCreature) -{ - return new mob_coilfang_ambusherAI (pCreature); -} - -CreatureAI* GetAI_boss_the_lurker_below(Creature* pCreature) -{ - return new boss_the_lurker_belowAI (pCreature); -} - -void AddSC_boss_the_lurker_below() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_lurker_below"; - newscript->GetAI = &GetAI_boss_the_lurker_below; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_guardian"; - newscript->GetAI = &GetAI_mob_coilfang_guardian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_ambusher"; - newscript->GetAI = &GetAI_mob_coilfang_ambusher; - newscript->RegisterSelf(); -} - - diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp deleted file mode 100644 index 14c87aee141..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Morogrim_Tidewalker -SD%Complete: 90 -SDComment: Water globules don't explode properly, remove hacks -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define SAY_AGGRO -1548030 -#define SAY_SUMMON1 -1548031 -#define SAY_SUMMON2 -1548032 -#define SAY_SUMMON_BUBL1 -1548033 -#define SAY_SUMMON_BUBL2 -1548034 -#define SAY_SLAY1 -1548035 -#define SAY_SLAY2 -1548036 -#define SAY_SLAY3 -1548037 -#define SAY_DEATH -1548038 -#define EMOTE_WATERY_GRAVE -1548039 -#define EMOTE_EARTHQUAKE -1548040 -#define EMOTE_WATERY_GLOBULES -1548041 - -#define SPELL_TIDAL_WAVE 37730 -#define SPELL_WATERY_GRAVE 38049 -#define SPELL_EARTHQUAKE 37764 -#define SPELL_WATERY_GRAVE_EXPLOSION 37852 - -#define WATERY_GRAVE_X1 334.64 -#define WATERY_GRAVE_Y1 -728.89 -#define WATERY_GRAVE_Z1 -14.42 -#define WATERY_GRAVE_X2 365.51 -#define WATERY_GRAVE_Y2 -737.14 -#define WATERY_GRAVE_Z2 -14.44 -#define WATERY_GRAVE_X3 366.19 -#define WATERY_GRAVE_Y3 -709.59 -#define WATERY_GRAVE_Z3 -14.36 -#define WATERY_GRAVE_X4 372.93 -#define WATERY_GRAVE_Y4 -690.96 -#define WATERY_GRAVE_Z4 -14.44 - -#define SPELL_WATERY_GRAVE_1 38023 -#define SPELL_WATERY_GRAVE_2 38024 -#define SPELL_WATERY_GRAVE_3 38025 -#define SPELL_WATERY_GRAVE_4 37850 - -#define SPELL_SUMMON_WATER_GLOBULE_1 37854 -#define SPELL_SUMMON_WATER_GLOBULE_2 37858 -#define SPELL_SUMMON_WATER_GLOBULE_3 37860 -#define SPELL_SUMMON_WATER_GLOBULE_4 37861 - -/*#define SPELL_SUMMON_MURLOC_A6 39813 -#define SPELL_SUMMON_MURLOC_A7 39814 -#define SPELL_SUMMON_MURLOC_A8 39815 -#define SPELL_SUMMON_MURLOC_A9 39816 -#define SPELL_SUMMON_MURLOC_A10 39817 - -#define SPELL_SUMMON_MURLOC_B6 39818 -#define SPELL_SUMMON_MURLOC_B7 39819 -#define SPELL_SUMMON_MURLOC_B8 39820 -#define SPELL_SUMMON_MURLOC_B9 39821 -#define SPELL_SUMMON_MURLOC_B10 39822*/ - -float MurlocCords[10][5] = -{ - {21920, 424.36, -715.4, -7.14, 0.124}, - {21920, 425.13, -719.3, -7.14, 0.124}, - {21920, 425.05, -724.23, -7.14, 0.124}, - {21920, 424.91, -728.68, -7.14, 0.124}, - {21920, 424.84, -732.18, -7.14, 0.124}, - {21920, 321.05, -734.2, -13.15, 0.124}, - {21920, 321.05, -729.4, -13.15, 0.124}, - {21920, 321.05, -724.03, -13.15, 0.124}, - {21920, 321.05, -718.73, -13.15, 0.124}, - {21920, 321.05, -714.24, -13.15, 0.124} -}; - -//Creatures -#define WATER_GLOBULE 21913 -#define TIDEWALKER_LURKER 21920 - -//Morogrim Tidewalker AI -struct boss_morogrim_tidewalkerAI : public ScriptedAI -{ - boss_morogrim_tidewalkerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - Map::PlayerList const *PlayerList; - - uint32 TidalWave_Timer; - uint32 WateryGrave_Timer; - uint32 Earthquake_Timer; - uint32 WateryGlobules_Timer; - uint32 globulespell[4]; - int8 Playercount; - int8 counter; - - bool Earthquake; - bool Phase2; - - void Reset() - { - TidalWave_Timer = 10000; - WateryGrave_Timer = 30000; - Earthquake_Timer = 40000; - WateryGlobules_Timer = 0; - globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1; - globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2; - globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3; - globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4; - - Earthquake = false; - Phase2 = false; - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); - } - - void StartEvent() - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - PlayerList = &me->GetMap()->GetPlayers(); - Playercount = PlayerList->getSize(); - StartEvent(); - } - - void ApplyWateryGrave(Unit* pPlayer, uint8 i) - { - switch(i) - { - case 0: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_1, true); break; - case 1: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_2, true); break; - case 2: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_3, true); break; - case 3: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_4, true); break; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Earthquake_Timer - if (Earthquake_Timer <= diff) - { - if (!Earthquake) - { - DoCast(me->getVictim(), SPELL_EARTHQUAKE); - Earthquake = true; - Earthquake_Timer = 10000; - } - else - { - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - - for (uint8 i = 0; i < 10; ++i) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - Creature* Murloc = me->SummonCreature(MurlocCords[i][0],MurlocCords[i][1],MurlocCords[i][2],MurlocCords[i][3],MurlocCords[i][4], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); - if (pTarget && Murloc) - Murloc->AI()->AttackStart(pTarget); - } - DoScriptText(EMOTE_EARTHQUAKE, me); - Earthquake = false; - Earthquake_Timer = 40000+rand()%5000; - } - } else Earthquake_Timer -= diff; - - //TidalWave_Timer - if (TidalWave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIDAL_WAVE); - TidalWave_Timer = 20000; - } else TidalWave_Timer -= diff; - - if (!Phase2) - { - //WateryGrave_Timer - if (WateryGrave_Timer <= diff) - { - //Teleport 4 players under the waterfalls - Unit *pTarget; - using std::set; - setlist; - set::const_iterator itr; - for (uint8 i = 0; i < 4; ++i) - { - counter = 0; - do - { - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only - if (counter < Playercount) - break; - if (pTarget) - itr = list.find(pTarget->GetGUID()); - ++counter; - } while (itr != list.end()); - - if (pTarget) - { - list.insert(pTarget->GetGUID()); - ApplyWateryGrave(pTarget, i); - } - } - - DoScriptText(RAND(SAY_SUMMON_BUBL1,SAY_SUMMON_BUBL2), me); - - DoScriptText(EMOTE_WATERY_GRAVE, me); - WateryGrave_Timer = 30000; - } else WateryGrave_Timer -= diff; - - //Start Phase2 - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) - Phase2 = true; - } - else - { - //WateryGlobules_Timer - if (WateryGlobules_Timer <= diff) - { - Unit* pGlobuleTarget; - using std::set; - setglobulelist; - set::const_iterator itr; - for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD - { - counter = 0; - do { - pGlobuleTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); - if (pGlobuleTarget) - itr = globulelist.find(pGlobuleTarget->GetGUID()); - if (counter > Playercount) - break; - ++counter; - } while (itr != globulelist.end()); - if (pGlobuleTarget) - globulelist.insert(pGlobuleTarget->GetGUID()); - pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true); - } - DoScriptText(EMOTE_WATERY_GLOBULES, me); - WateryGlobules_Timer = 25000; - } else WateryGlobules_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -//Water Globule AI -#define SPELL_GLOBULE_EXPLOSION 37871 - -struct mob_water_globuleAI : public ScriptedAI -{ - mob_water_globuleAI(Creature *c) : ScriptedAI(c) {} - - uint32 Check_Timer; - - void Reset() - { - Check_Timer = 1000; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - //no attack radius check - it attacks the first target that moves in his los - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Check_Timer <= diff) - { - if (me->IsWithinDistInMap(me->getVictim(), 5)) - { - DoCast(me->getVictim(), SPELL_GLOBULE_EXPLOSION); - - //despawn - me->ForcedDespawn(); - return; - } - Check_Timer = 500; - } else Check_Timer -= diff; - - //do NOT deal any melee damage to the target. - } -}; - -CreatureAI* GetAI_boss_morogrim_tidewalker(Creature* pCreature) -{ - return new boss_morogrim_tidewalkerAI (pCreature); -} -CreatureAI* GetAI_mob_water_globule(Creature* pCreature) -{ - return new mob_water_globuleAI (pCreature); -} - -void AddSC_boss_morogrim_tidewalker() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_morogrim_tidewalker"; - newscript->GetAI = &GetAI_boss_morogrim_tidewalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_water_globule"; - newscript->GetAI = &GetAI_mob_water_globule; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp deleted file mode 100644 index c80afae15c7..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Serpent_Shrine -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Serpent Shrine Scripts -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define MAX_ENCOUNTER 6 -#define SPELL_SCALDINGWATER 37284 -#define MOB_COILFANG_FRENZY 21508 -#define TRASHMOB_COILFANG_PRIESTESS 21220 //6*2 -#define TRASHMOB_COILFANG_SHATTERER 21301 //6*3 - -#define MIN_KILLS 30 - -//NOTE: there are 6 platforms -//there should be 3 shatterers and 2 priestess on all platforms, total of 30 elites, else it won't work! -//delete all other elites not on platforms! these mobs should only be on those platforms nowhere else. - -/* Serpentshrine cavern encounters: -0 - Hydross The Unstable event -1 - Leotheras The Blind Event -2 - The Lurker Below Event -3 - Fathom-Lord Karathress Event -4 - Morogrim Tidewalker Event -5 - Lady Vashj Event -*/ - -bool GOHello_go_bridge_console(Player* /*pPlayer*/, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - - if (!pInstance) - return false; - - if (pInstance) - pInstance->SetData(DATA_CONTROL_CONSOLE, DONE); - - return true; -} - -struct instance_serpentshrine_cavern : public ScriptedInstance -{ - instance_serpentshrine_cavern(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 LurkerBelow; - uint64 Sharkkis; - uint64 Tidalvess; - uint64 Caribdis; - uint64 LadyVashj; - uint64 Karathress; - uint64 KarathressEvent_Starter; - uint64 LeotherasTheBlind; - uint64 LeotherasEventStarter; - - uint64 ControlConsole; - uint64 BridgePart[3]; - uint32 StrangePool; - uint32 FishingTimer; - uint32 LurkerSubEvent; - uint32 WaterCheckTimer; - uint32 FrenzySpawnTimer; - uint32 Water; - uint32 TrashCount; - - bool ShieldGeneratorDeactivated[4]; - uint32 m_auiEncounter[MAX_ENCOUNTER]; - bool DoSpawnFrenzy; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - LurkerBelow = 0; - Sharkkis = 0; - Tidalvess = 0; - Caribdis = 0; - LadyVashj = 0; - Karathress = 0; - KarathressEvent_Starter = 0; - LeotherasTheBlind = 0; - LeotherasEventStarter = 0; - - ControlConsole = 0; - BridgePart[0] = 0; - BridgePart[1] = 0; - BridgePart[2] = 0; - StrangePool = 0; - Water = WATERSTATE_FRENZY; - - ShieldGeneratorDeactivated[0] = false; - ShieldGeneratorDeactivated[1] = false; - ShieldGeneratorDeactivated[2] = false; - ShieldGeneratorDeactivated[3] = false; - FishingTimer = 1000; - LurkerSubEvent = 0; - WaterCheckTimer = 500; - FrenzySpawnTimer = 2000; - DoSpawnFrenzy = false; - TrashCount = 0; - - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void Update (uint32 diff) - { - //Lurker Fishing event - if (LurkerSubEvent == LURKER_FISHING) - { - if (FishingTimer <= diff) - { - LurkerSubEvent = LURKER_HOOKED; - SetData(DATA_STRANGE_POOL, IN_PROGRESS);//just fished, signal Lurker script to emerge and start fight, we use IN_PROGRESS so it won't get saved and lurker will be alway invis at start if server restarted - } else FishingTimer -= diff; - } - //Water checks - if (WaterCheckTimer <= diff) - { - if (TrashCount >= MIN_KILLS) - Water = WATERSTATE_SCALDING; - else - Water = WATERSTATE_FRENZY; - - Map::PlayerList const &PlayerList = instance->GetPlayers(); - if (PlayerList.isEmpty()) - return; - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isAlive() && /*i->getSource()->GetPositionZ() <= -21.434931f*/pPlayer->IsInWater()) - { - if (Water == WATERSTATE_SCALDING) - { - - if (!pPlayer->HasAura(SPELL_SCALDINGWATER)) - { - pPlayer->CastSpell(pPlayer, SPELL_SCALDINGWATER,true); - } - } else if (Water == WATERSTATE_FRENZY) - { - //spawn frenzy - if (DoSpawnFrenzy) - { - if (Creature* frenzy = pPlayer->SummonCreature(MOB_COILFANG_FRENZY,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ(),pPlayer->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,2000)) - { - frenzy->Attack(pPlayer,false); - frenzy->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); - } - DoSpawnFrenzy = false; - } - } - } - if (!pPlayer->IsInWater()) - pPlayer->RemoveAurasDueToSpell(SPELL_SCALDINGWATER); - } - - } - WaterCheckTimer = 500;//remove stress from core - } else WaterCheckTimer -= diff; - if (FrenzySpawnTimer <= diff) - { - DoSpawnFrenzy = true; - FrenzySpawnTimer = 2000; - } else FrenzySpawnTimer -= diff; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 184568: - ControlConsole = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184203: - BridgePart[0] = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184204: - BridgePart[1] = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184205: - BridgePart[2] = pGo->GetGUID(); - pGo->setActive(true); - break; - case GAMEOBJECT_FISHINGNODE_ENTRY://no way checking if fish is hooked, so we create a timed event - if (LurkerSubEvent == LURKER_NOT_STARTED) - { - FishingTimer = 10000+rand()%30000;//random time before lurker emerges - LurkerSubEvent = LURKER_FISHING; - } - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 21212: LadyVashj = pCreature->GetGUID(); break; - case 21214: Karathress = pCreature->GetGUID(); break; - case 21966: Sharkkis = pCreature->GetGUID(); break; - case 21217: LurkerBelow = pCreature->GetGUID(); break; - case 21965: Tidalvess = pCreature->GetGUID(); break; - case 21964: Caribdis = pCreature->GetGUID(); break; - case 21215: LeotherasTheBlind = pCreature->GetGUID(); break; - /*case TRASHMOB_COILFANG_PRIESTESS: - case TRASHMOB_COILFANG_SHATTERER: - if (pCreature->isAlive()) - ++TrashCount; - break;*/ - } - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_KARATHRESSEVENT_STARTER) - KarathressEvent_Starter = data; - if (type == DATA_LEOTHERAS_EVENT_STARTER) - LeotherasEventStarter = data; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_THELURKERBELOW: return LurkerBelow; - case DATA_SHARKKIS: return Sharkkis; - case DATA_TIDALVESS: return Tidalvess; - case DATA_CARIBDIS: return Caribdis; - case DATA_LADYVASHJ: return LadyVashj; - case DATA_KARATHRESS: return Karathress; - case DATA_KARATHRESSEVENT_STARTER: return KarathressEvent_Starter; - case DATA_LEOTHERAS: return LeotherasTheBlind; - case DATA_LEOTHERAS_EVENT_STARTER: return LeotherasEventStarter; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_STRANGE_POOL: - { - StrangePool = data; - if (data == NOT_STARTED) - LurkerSubEvent = LURKER_NOT_STARTED; - } - break; - case DATA_CONTROL_CONSOLE: - if (data == DONE) - { - HandleGameObject(BridgePart[0], true); - HandleGameObject(BridgePart[0], true); - HandleGameObject(BridgePart[0], true); - } - ControlConsole = data;break; - case DATA_TRASH : - { - if (data == 1 && TrashCount < MIN_KILLS) - ++TrashCount;//+1 died - SaveToDB(); - break; - } - case DATA_WATER : Water = data;break; - case DATA_HYDROSSTHEUNSTABLEEVENT: m_auiEncounter[0] = data; break; - case DATA_LEOTHERASTHEBLINDEVENT: m_auiEncounter[1] = data; break; - case DATA_THELURKERBELOWEVENT: m_auiEncounter[2] = data; break; - case DATA_KARATHRESSEVENT: m_auiEncounter[3] = data; break; - case DATA_MOROGRIMTIDEWALKEREVENT: m_auiEncounter[4] = data; break; - //Lady Vashj - case DATA_LADYVASHJEVENT: - if (data == NOT_STARTED) - { - ShieldGeneratorDeactivated[0] = false; - ShieldGeneratorDeactivated[1] = false; - ShieldGeneratorDeactivated[2] = false; - ShieldGeneratorDeactivated[3] = false; - } - m_auiEncounter[5] = data; break; - case DATA_SHIELDGENERATOR1:ShieldGeneratorDeactivated[0] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR2:ShieldGeneratorDeactivated[1] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR3:ShieldGeneratorDeactivated[2] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR4:ShieldGeneratorDeactivated[3] = (data) ? true : false; break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_HYDROSSTHEUNSTABLEEVENT: return m_auiEncounter[0]; - case DATA_LEOTHERASTHEBLINDEVENT: return m_auiEncounter[1]; - case DATA_THELURKERBELOWEVENT: return m_auiEncounter[2]; - case DATA_KARATHRESSEVENT: return m_auiEncounter[3]; - case DATA_MOROGRIMTIDEWALKEREVENT: return m_auiEncounter[4]; - //Lady Vashj - case DATA_LADYVASHJEVENT: return m_auiEncounter[5]; - case DATA_SHIELDGENERATOR1: return ShieldGeneratorDeactivated[0]; - case DATA_SHIELDGENERATOR2: return ShieldGeneratorDeactivated[1]; - case DATA_SHIELDGENERATOR3: return ShieldGeneratorDeactivated[2]; - case DATA_SHIELDGENERATOR4: return ShieldGeneratorDeactivated[3]; - case DATA_CANSTARTPHASE3: - if (ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3])return 1;break; - case DATA_STRANGE_POOL: return StrangePool; - case DATA_WATER: return Water; - } - return 0; - } - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << TrashCount; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> TrashCount; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_serpentshrine_cavern(Map* pMap) -{ - return new instance_serpentshrine_cavern(pMap); -} - -void AddSC_instance_serpentshrine_cavern() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_serpent_shrine"; - newscript->GetInstanceData = &GetInstanceData_instance_serpentshrine_cavern; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_bridge_console"; - newscript->pGOHello = &GOHello_go_bridge_console; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h b/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h deleted file mode 100644 index adfa39dc7e0..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SERPENT_SHRINE_H -#define DEF_SERPENT_SHRINE_H -enum LurkerEventState -{ - LURKER_NOT_STARTED = 0, - LURKER_FISHING = 1, - LURKER_HOOKED = 2 -}; -enum WaterEventState -{ - WATERSTATE_NONE = 0, - WATERSTATE_FRENZY = 1, - WATERSTATE_SCALDING = 2 -}; -#define DATA_CANSTARTPHASE3 1 -#define DATA_CARIBDIS 2 -#define DATA_HYDROSSTHEUNSTABLEEVENT 3 -#define DATA_KARATHRESS 4 -#define DATA_KARATHRESSEVENT 5 -#define DATA_KARATHRESSEVENT_STARTER 6 -#define DATA_LADYVASHJ 7 -#define DATA_LADYVASHJEVENT 8 -#define DATA_LEOTHERASTHEBLINDEVENT 9 -#define DATA_MOROGRIMTIDEWALKEREVENT 10 -#define DATA_SHARKKIS 11 -#define DATA_SHIELDGENERATOR1 12 -#define DATA_SHIELDGENERATOR2 13 -#define DATA_SHIELDGENERATOR3 14 -#define DATA_SHIELDGENERATOR4 15 -#define DATA_THELURKERBELOW 16 -#define DATA_THELURKERBELOWEVENT 17 -#define DATA_TIDALVESS 18 -#define DATA_FATHOMLORDKARATHRESSEVENT 19 -#define DATA_LEOTHERAS 20 -#define DATA_LEOTHERAS_EVENT_STARTER 21 -#define DATA_CONTROL_CONSOLE 22 -#define DATA_STRANGE_POOL 23 -#define DATA_WATER 24 -#define DATA_TRASH 25 -#endif - diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp deleted file mode 100644 index 8e1b438bdc5..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hydromancer_Thespia -SD%Complete: 80 -SDComment: Needs additional adjustments (when instance script is adjusted) -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -/* ContentData -boss_hydromancer_thespia -mob_coilfang_waterelemental -EndContentData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_SUMMON -1545000 -#define SAY_AGGRO_1 -1545001 -#define SAY_AGGRO_2 -1545002 -#define SAY_AGGRO_3 -1545003 -#define SAY_SLAY_1 -1545004 -#define SAY_SLAY_2 -1545005 -#define SAY_DEAD -1545006 - -#define SPELL_LIGHTNING_CLOUD 25033 -#define SPELL_LUNG_BURST 31481 -#define SPELL_ENVELOPING_WINDS 31718 - -struct boss_thespiaAI : public ScriptedAI -{ - boss_thespiaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 LightningCloud_Timer; - uint32 LungBurst_Timer; - uint32 EnvelopingWinds_Timer; - - void Reset() - { - LightningCloud_Timer = 15000; - LungBurst_Timer = 7000; - EnvelopingWinds_Timer = 9000; - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, NOT_STARTED); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEAD, me); - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //LightningCloud_Timer - if (LightningCloud_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LIGHTNING_CLOUD); - - //cast twice in Heroic mode - if (IsHeroic()) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LIGHTNING_CLOUD); - - LightningCloud_Timer = 15000+rand()%10000; - } else LightningCloud_Timer -=diff; - - //LungBurst_Timer - if (LungBurst_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LUNG_BURST); - LungBurst_Timer = 7000+rand()%5000; - } else LungBurst_Timer -=diff; - - //EnvelopingWinds_Timer - if (EnvelopingWinds_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ENVELOPING_WINDS); - - //cast twice in Heroic mode - if (IsHeroic()) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ENVELOPING_WINDS); - EnvelopingWinds_Timer = 10000+rand()%5000; - } else EnvelopingWinds_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -#define SPELL_WATER_BOLT_VOLLEY 34449 -#define H_SPELL_WATER_BOLT_VOLLEY 37924 - -struct mob_coilfang_waterelementalAI : public ScriptedAI -{ - mob_coilfang_waterelementalAI(Creature *c) : ScriptedAI(c) {} - - uint32 WaterBoltVolley_Timer; - - void Reset() - { - WaterBoltVolley_Timer = 3000+rand()%3000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (WaterBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_WATER_BOLT_VOLLEY); - WaterBoltVolley_Timer = 7000+rand()%5000; - } else WaterBoltVolley_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_thespiaAI(Creature* pCreature) -{ - return new boss_thespiaAI (pCreature); -} - -CreatureAI* GetAI_mob_coilfang_waterelementalAI(Creature* pCreature) -{ - return new mob_coilfang_waterelementalAI (pCreature); -} - -void AddSC_boss_hydromancer_thespia() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_hydromancer_thespia"; - newscript->GetAI = &GetAI_boss_thespiaAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_waterelemental"; - newscript->GetAI = &GetAI_mob_coilfang_waterelementalAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp deleted file mode 100644 index f2da4058e44..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mekgineer_Steamrigger -SD%Complete: 60 -SDComment: Mechanics' interrrupt heal doesn't work very well, also a proper movement needs to be implemented -> summon further away and move towards pTarget to repair. -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -/* ContentData -boss_mekgineer_steamrigger -mob_steamrigger_mechanic -EndContentData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_MECHANICS -1545007 -#define SAY_AGGRO_1 -1545008 -#define SAY_AGGRO_2 -1545009 -#define SAY_AGGRO_3 -1545010 -#define SAY_AGGRO_4 -1545011 -#define SAY_SLAY_1 -1545012 -#define SAY_SLAY_2 -1545013 -#define SAY_SLAY_3 -1545014 -#define SAY_DEATH -1545015 - -#define SPELL_SUPER_SHRINK_RAY 31485 -#define SPELL_SAW_BLADE 31486 -#define SPELL_ELECTRIFIED_NET 35107 -#define H_SPELL_ENRAGE 1 //corrent enrage spell not known - -#define ENTRY_STREAMRIGGER_MECHANIC 17951 - -struct boss_mekgineer_steamriggerAI : public ScriptedAI -{ - boss_mekgineer_steamriggerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Shrink_Timer; - uint32 Saw_Blade_Timer; - uint32 Electrified_Net_Timer; - bool Summon75; - bool Summon50; - bool Summon25; - - void Reset() - { - Shrink_Timer = 20000; - Saw_Blade_Timer = 15000; - Electrified_Net_Timer = 10000; - - Summon75 = false; - Summon50 = false; - Summon25 = false; - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, NOT_STARTED); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, IN_PROGRESS); - } - - //no known summon spells exist - void SummonMechanichs() - { - DoScriptText(SAY_MECHANICS, me); - - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - - if (rand()%2) - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,-7,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - if (rand()%2) - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,7,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Shrink_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUPER_SHRINK_RAY); - Shrink_Timer = 20000; - } else Shrink_Timer -= diff; - - if (Saw_Blade_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_SAW_BLADE); - else - DoCast(me->getVictim(), SPELL_SAW_BLADE); - - Saw_Blade_Timer = 15000; - } else Saw_Blade_Timer -= diff; - - if (Electrified_Net_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ELECTRIFIED_NET); - Electrified_Net_Timer = 10000; - } - else Electrified_Net_Timer -= diff; - - if (!Summon75) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 75) - { - SummonMechanichs(); - Summon75 = true; - } - } - - if (!Summon50) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) - { - SummonMechanichs(); - Summon50 = true; - } - } - - if (!Summon25) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) - { - SummonMechanichs(); - Summon25 = true; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_mekgineer_steamrigger(Creature* pCreature) -{ - return new boss_mekgineer_steamriggerAI (pCreature); -} - -#define SPELL_DISPEL_MAGIC 17201 -#define SPELL_REPAIR 31532 -#define H_SPELL_REPAIR 37936 - -#define MAX_REPAIR_RANGE (13.0f) //we should be at least at this range for repair -#define MIN_REPAIR_RANGE (7.0f) //we can stop movement at this range to repair but not required - -struct mob_steamrigger_mechanicAI : public ScriptedAI -{ - mob_steamrigger_mechanicAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Repair_Timer; - - void Reset() - { - Repair_Timer = 2000; - } - - void MoveInLineOfSight(Unit* /*who*/) - { - //react only if attacked - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (Repair_Timer <= diff) - { - if (pInstance && pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER) && pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) - { - if (Unit* pMekgineer = Unit::GetUnit((*me), pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER))) - { - if (me->IsWithinDistInMap(pMekgineer, MAX_REPAIR_RANGE)) - { - //are we already channeling? Doesn't work very well, find better check? - if (!me->GetUInt32Value(UNIT_CHANNEL_SPELL)) - { - //me->GetMotionMaster()->MovementExpired(); - //me->GetMotionMaster()->MoveIdle(); - - DoCast(me, SPELL_REPAIR, true); - } - Repair_Timer = 5000; - } - else - { - //me->GetMotionMaster()->MovementExpired(); - //me->GetMotionMaster()->MoveFollow(pMekgineer,0,0); - } - } - } else Repair_Timer = 5000; - } else Repair_Timer -= diff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_steamrigger_mechanic(Creature* pCreature) -{ - return new mob_steamrigger_mechanicAI (pCreature); -} - -void AddSC_boss_mekgineer_steamrigger() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_mekgineer_steamrigger"; - newscript->GetAI = &GetAI_boss_mekgineer_steamrigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_steamrigger_mechanic"; - newscript->GetAI = &GetAI_mob_steamrigger_mechanic; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp deleted file mode 100644 index f46956dda81..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warlord_Kalithres -SD%Complete: 65 -SDComment: Contains workarounds regarding warlord's rage spells not acting as expected. Both scripts here require review and fine tuning. -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_INTRO -1545016 -#define SAY_REGEN -1545017 -#define SAY_AGGRO1 -1545018 -#define SAY_AGGRO2 -1545019 -#define SAY_AGGRO3 -1545020 -#define SAY_SLAY1 -1545021 -#define SAY_SLAY2 -1545022 -#define SAY_DEATH -1545023 - -#define SPELL_SPELL_REFLECTION 31534 -#define SPELL_IMPALE 39061 -#define SPELL_WARLORDS_RAGE 37081 -#define SPELL_WARLORDS_RAGE_NAGA 31543 - -#define SPELL_WARLORDS_RAGE_PROC 36453 - -struct mob_naga_distillerAI : public ScriptedAI -{ - mob_naga_distillerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - //hack, due to really weird spell behaviour :( - if (pInstance) - { - if (pInstance->GetData(TYPE_DISTILLER) == IN_PROGRESS) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - } - - void EnterCombat(Unit * /*who*/) { } - - void StartRageGen(Unit * /*caster*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - DoCast(me, SPELL_WARLORDS_RAGE_NAGA, true); - - if (pInstance) - pInstance->SetData(TYPE_DISTILLER,IN_PROGRESS); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (me->GetHealth() <= damage) - if (pInstance) - pInstance->SetData(TYPE_DISTILLER,DONE); - } -}; - -struct boss_warlord_kalithreshAI : public ScriptedAI -{ - boss_warlord_kalithreshAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Reflection_Timer; - uint32 Impale_Timer; - uint32 Rage_Timer; - bool CanRage; - - void Reset() - { - Reflection_Timer = 10000; - Impale_Timer = 7000+rand()%7000; - Rage_Timer = 45000; - CanRage = false; - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - //hack :( - if (spell->Id == SPELL_WARLORDS_RAGE_PROC) - if (pInstance) - if (pInstance->GetData(TYPE_DISTILLER) == DONE) - me->RemoveAurasDueToSpell(SPELL_WARLORDS_RAGE_PROC); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Rage_Timer <= diff) - { - if (Creature* distiller = me->FindNearestCreature(17954, 100.0f)) - { - DoScriptText(SAY_REGEN, me); - DoCast(me, SPELL_WARLORDS_RAGE); - CAST_AI(mob_naga_distillerAI, distiller->AI())->StartRageGen(me); - } - Rage_Timer = 3000+rand()%15000; - } else Rage_Timer -= diff; - - //Reflection_Timer - if (Reflection_Timer <= diff) - { - DoCast(me, SPELL_SPELL_REFLECTION); - Reflection_Timer = 15000+rand()%10000; - } else Reflection_Timer -= diff; - - //Impale_Timer - if (Impale_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_IMPALE); - - Impale_Timer = 7500+rand()%5000; - } else Impale_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_naga_distiller(Creature* pCreature) -{ - return new mob_naga_distillerAI (pCreature); -} - -CreatureAI* GetAI_boss_warlord_kalithresh(Creature* pCreature) -{ - return new boss_warlord_kalithreshAI (pCreature); -} - -void AddSC_boss_warlord_kalithresh() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_naga_distiller"; - newscript->GetAI = &GetAI_mob_naga_distiller; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_warlord_kalithresh"; - newscript->GetAI = &GetAI_boss_warlord_kalithresh; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp deleted file mode 100644 index 188a23738f5..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Steam_Vault -SD%Complete: 80 -SDComment: Instance script and access panel GO -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define MAX_ENCOUNTER 4 - -#define MAIN_CHAMBERS_DOOR 183049 -#define ACCESS_PANEL_HYDRO 184125 -#define ACCESS_PANEL_MEK 184126 - -/* Steam Vaults encounters: -1 - Hydromancer Thespia Event -2 - Mekgineer Steamrigger Event -3 - Warlord Kalithresh Event -*/ - -bool GOHello_go_main_chambers_access_panel(Player* /*pPlayer*/, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - - if (!pInstance) - return false; - - if (pGo->GetEntry() == ACCESS_PANEL_HYDRO && (pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == DONE || pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL)) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA,SPECIAL); - - if (pGo->GetEntry() == ACCESS_PANEL_MEK && (pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == DONE || pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL)) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER,SPECIAL); - - return true; -} - -struct instance_steam_vault : public ScriptedInstance -{ - instance_steam_vault(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 ThespiaGUID; - uint64 MekgineerGUID; - uint64 KalithreshGUID; - - uint64 MainChambersDoor; - uint64 AccessPanelHydro; - uint64 AccessPanelMek; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - ThespiaGUID = 0; - MekgineerGUID = 0; - KalithreshGUID = 0; - MainChambersDoor = 0; - AccessPanelHydro = 0; - AccessPanelMek = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17797: ThespiaGUID = pCreature->GetGUID(); break; - case 17796: MekgineerGUID = pCreature->GetGUID(); break; - case 17798: KalithreshGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case MAIN_CHAMBERS_DOOR: MainChambersDoor = pGo->GetGUID(); break; - case ACCESS_PANEL_HYDRO: AccessPanelHydro = pGo->GetGUID(); break; - case ACCESS_PANEL_MEK: AccessPanelMek = pGo->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_HYDROMANCER_THESPIA: - if (data == SPECIAL) - { - HandleGameObject(AccessPanelHydro, true); - - if (GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL) - HandleGameObject(MainChambersDoor, true); - - debug_log("TSCR: Instance Steamvault: Access panel used."); - } - m_auiEncounter[0] = data; - break; - case TYPE_MEKGINEER_STEAMRIGGER: - if (data == SPECIAL) - { - HandleGameObject(AccessPanelMek, true); - - if (GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL) - HandleGameObject(MainChambersDoor, true); - - debug_log("TSCR: Instance Steamvault: Access panel used."); - } - m_auiEncounter[1] = data; - break; - case TYPE_WARLORD_KALITHRESH: - m_auiEncounter[2] = data; - break; - case TYPE_DISTILLER: - m_auiEncounter[3] = data; - break; - } - - if (data == DONE || data == SPECIAL) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_HYDROMANCER_THESPIA: - return m_auiEncounter[0]; - case TYPE_MEKGINEER_STEAMRIGGER: - return m_auiEncounter[1]; - case TYPE_WARLORD_KALITHRESH: - return m_auiEncounter[2]; - case TYPE_DISTILLER: - return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THESPIA: - return ThespiaGUID; - case DATA_MEKGINEERSTEAMRIGGER: - return MekgineerGUID; - case DATA_KALITRESH: - return KalithreshGUID; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_steam_vault(Map* pMap) -{ - return new instance_steam_vault(pMap); -} - -void AddSC_instance_steam_vault() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_main_chambers_access_panel"; - newscript->pGOHello = &GOHello_go_main_chambers_access_panel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "instance_steam_vault"; - newscript->GetInstanceData = &GetInstanceData_instance_steam_vault; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h b/src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h deleted file mode 100644 index 4b407ac4816..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/steam_vault/steam_vault.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_STEAM_VAULT_H -#define DEF_STEAM_VAULT_H - -#define TYPE_HYDROMANCER_THESPIA 1 -#define TYPE_MEKGINEER_STEAMRIGGER 2 -#define TYPE_WARLORD_KALITHRESH 3 -#define TYPE_DISTILLER 4 - -#define DATA_MEKGINEERSTEAMRIGGER 5 -#define DATA_KALITRESH 6 -#define DATA_THESPIA 7 -#endif - diff --git a/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp b/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp deleted file mode 100644 index fcfcc1b1a90..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_hungarfen.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hungarfen -SD%Complete: 95 -SDComment: Need confirmation if spell data are same in both modes. Summons should have faster rate in heroic -SDCategory: Coilfang Resevoir, Underbog -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FOUL_SPORES 31673 -#define SPELL_ACID_GEYSER 38739 - -struct boss_hungarfenAI : public ScriptedAI -{ - boss_hungarfenAI(Creature *c) : ScriptedAI(c) - { - } - - bool Root; - uint32 Mushroom_Timer; - uint32 AcidGeyser_Timer; - - void Reset() - { - Root = false; - Mushroom_Timer = 5000; // 1 mushroom after 5s, then one per 10s. This should be different in heroic mode - AcidGeyser_Timer = 10000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) - { - if (!Root) - { - DoCast(me, SPELL_FOUL_SPORES); - Root = true; - } - } - - if (Mushroom_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - me->SummonCreature(17990, pTarget->GetPositionX()+(rand()%8), pTarget->GetPositionY()+(rand()%8), pTarget->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); - else - me->SummonCreature(17990, me->GetPositionX()+(rand()%8), me->GetPositionY()+(rand()%8), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 22000); - - Mushroom_Timer = 10000; - } else Mushroom_Timer -= diff; - - if (AcidGeyser_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ACID_GEYSER); - AcidGeyser_Timer = 10000+rand()%7500; - } else AcidGeyser_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_hungarfen(Creature* pCreature) -{ - return new boss_hungarfenAI (pCreature); -} - -#define SPELL_SPORE_CLOUD 34168 -#define SPELL_PUTRID_MUSHROOM 31690 -#define SPELL_GROW 31698 - -struct mob_underbog_mushroomAI : public ScriptedAI -{ - mob_underbog_mushroomAI(Creature *c) : ScriptedAI(c) {} - - bool Stop; - uint32 Grow_Timer; - uint32 Shrink_Timer; - - void Reset() - { - Stop = false; - Grow_Timer = 0; - Shrink_Timer = 20000; - - DoCast(me, SPELL_PUTRID_MUSHROOM, true); - DoCast(me, SPELL_SPORE_CLOUD, true); - } - - void MoveInLineOfSight(Unit * /*who*/) {} - - void AttackStart(Unit* /*who*/) {} - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (Stop) - return; - - if (Grow_Timer <= diff) - { - DoCast(me, SPELL_GROW); - Grow_Timer = 3000; - } else Grow_Timer -= diff; - - if (Shrink_Timer <= diff) - { - me->RemoveAurasDueToSpell(SPELL_GROW); - Stop = true; - } else Shrink_Timer -= diff; - } -}; -CreatureAI* GetAI_mob_underbog_mushroom(Creature* pCreature) -{ - return new mob_underbog_mushroomAI (pCreature); -} - -void AddSC_boss_hungarfen() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_hungarfen"; - newscript->GetAI = &GetAI_boss_hungarfen; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_underbog_mushroom"; - newscript->GetAI = &GetAI_mob_underbog_mushroom; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp b/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp deleted file mode 100644 index 3a78660389b..00000000000 --- a/src/server/scripts/Outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_the_black_stalker -SD%Complete: 95 -SDComment: Timers may be incorrect -SDCategory: Coilfang Resevoir, Underbog -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_LEVITATE 31704 -#define SPELL_SUSPENSION 31719 -#define SPELL_LEVITATION_PULSE 31701 -#define SPELL_MAGNETIC_PULL 31705 -#define SPELL_CHAIN_LIGHTNING 31717 -#define SPELL_STATIC_CHARGE 31715 -#define SPELL_SUMMON_SPORE_STRIDER 38755 - -#define ENTRY_SPORE_STRIDER 22299 - -struct boss_the_black_stalkerAI : public ScriptedAI -{ - boss_the_black_stalkerAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 SporeStriders_Timer; - uint32 Levitate_Timer; - uint32 ChainLightning_Timer; - uint32 StaticCharge_Timer; - uint64 LevitatedTarget; - uint32 LevitatedTarget_Timer; - bool InAir; - uint32 check_Timer; - std::list Striders; - - void Reset() - { - Levitate_Timer = 12000; - ChainLightning_Timer = 6000; - StaticCharge_Timer = 10000; - SporeStriders_Timer = 10000+rand()%5000; - check_Timer = 5000; - LevitatedTarget = 0; - LevitatedTarget_Timer = 0; - Striders.clear(); - } - - void EnterCombat(Unit * /*who*/) {} - - void JustSummoned(Creature *summon) - { - if (summon && summon->GetEntry() == ENTRY_SPORE_STRIDER) - { - Striders.push_back(summon->GetGUID()); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - summon->AI()->AttackStart(pTarget); - else - if (me->getVictim()) - summon->AI()->AttackStart(me->getVictim()); - } - } - - void JustDied(Unit * /*who*/) - { - for (std::list::const_iterator i = Striders.begin(); i != Striders.end(); ++i) - if (Creature *strider = Unit::GetCreature(*me, *i)) - strider->DisappearAndDie(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Evade if too far - if (check_Timer <= diff) - { - float x,y,z,o; - me->GetHomePosition(x,y,z,o); - if (!me->IsWithinDist3d(x,y,z, 60)) - { - EnterEvadeMode(); - return; - } - check_Timer = 1000; - } else check_Timer -= diff; - - // Spore Striders - if (IsHeroic() && SporeStriders_Timer <= diff) - { - DoCast(me, SPELL_SUMMON_SPORE_STRIDER); - SporeStriders_Timer = 10000+rand()%5000; - } else SporeStriders_Timer -= diff; - - // Levitate - if (LevitatedTarget) - { - if (LevitatedTarget_Timer <= diff) - { - if (Unit *pTarget = Unit::GetUnit(*me, LevitatedTarget)) - { - if (!pTarget->HasAura(SPELL_LEVITATE)) - { - LevitatedTarget = 0; - return; - } - if (InAir) - { - pTarget->AddAura(SPELL_SUSPENSION, pTarget); - LevitatedTarget = 0; - } - else - { - pTarget->CastSpell(pTarget, SPELL_MAGNETIC_PULL, true); - InAir = true; - LevitatedTarget_Timer = 1500; - } - } - else - LevitatedTarget = 0; - } else LevitatedTarget_Timer -= diff; - } - if (Levitate_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - DoCast(pTarget, SPELL_LEVITATE); - LevitatedTarget = pTarget->GetGUID(); - LevitatedTarget_Timer = 2000; - InAir = false; - } - Levitate_Timer = 12000+rand()%3000; - } else Levitate_Timer -= diff; - - // Chain Lightning - if (ChainLightning_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - ChainLightning_Timer = 7000; - } else ChainLightning_Timer -= diff; - - // Static Charge - if (StaticCharge_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true)) - DoCast(pTarget, SPELL_STATIC_CHARGE); - StaticCharge_Timer = 10000; - } else StaticCharge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_the_black_stalker(Creature* pCreature) -{ - return new boss_the_black_stalkerAI (pCreature); -} - -void AddSC_boss_the_black_stalker() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_the_black_stalker"; - newscript->GetAI = &GetAI_boss_the_black_stalker; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp b/src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp deleted file mode 100644 index a07ac910598..00000000000 --- a/src/server/scripts/Outland/gruuls_lair/boss_gruul.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gruul -SD%Complete: 60 -SDComment: Ground Slam need further development (knock back effect and shatter effect must be added to the core) -SDCategory: Gruul's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "gruuls_lair.h" - -enum eEnums -{ - SAY_AGGRO = -1565010, - SAY_SLAM1 = -1565011, - SAY_SLAM2 = -1565012, - SAY_SHATTER1 = -1565013, - SAY_SHATTER2 = -1565014, - SAY_SLAY1 = -1565015, - SAY_SLAY2 = -1565016, - SAY_SLAY3 = -1565017, - SAY_DEATH = -1565018, - - EMOTE_GROW = -1565019, - - SPELL_GROWTH = 36300, - SPELL_CAVE_IN = 36240, - SPELL_GROUND_SLAM = 33525, //AoE Ground Slam applying Ground Slam to everyone with a script effect (most likely the knock back, we can code it to a set knockback) - SPELL_REVERBERATION = 36297, - SPELL_SHATTER = 33654, - - SPELL_SHATTER_EFFECT = 33671, - SPELL_HURTFUL_STRIKE = 33813, - SPELL_STONED = 33652, //Spell is self cast by target - - SPELL_MAGNETIC_PULL = 28337, - SPELL_KNOCK_BACK = 24199, //Knockback spell until correct implementation is made -}; - -struct boss_gruulAI : public ScriptedAI -{ - boss_gruulAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 m_uiGrowth_Timer; - uint32 m_uiCaveIn_Timer; - uint32 m_uiCaveIn_StaticTimer; - uint32 m_uiGroundSlamTimer; - uint32 m_uiHurtfulStrike_Timer; - uint32 m_uiReverberation_Timer; - - bool m_bPerformingGroundSlam; - - void Reset() - { - m_uiGrowth_Timer= 30000; - m_uiCaveIn_Timer= 27000; - m_uiCaveIn_StaticTimer = 30000; - m_uiGroundSlamTimer= 35000; - m_bPerformingGroundSlam= false; - m_uiHurtfulStrike_Timer= 8000; - m_uiReverberation_Timer= 60000+45000; - - if (pInstance) - pInstance->SetData(DATA_GRUULEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_GRUULEVENT, IN_PROGRESS); - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_GRUULEVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GRUULDOOR), true); // Open the encounter door - } - } - - void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) - { - //This to emulate effect1 (77) of SPELL_GROUND_SLAM, knock back to any direction - //It's initially wrong, since this will cause fall damage, which is by comments, not intended. - if (pSpell->Id == SPELL_GROUND_SLAM) - { - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - switch (urand(0,1)) - { - case 0: pTarget->CastSpell(pTarget, SPELL_MAGNETIC_PULL, true, NULL, NULL, me->GetGUID()); break; - case 1: pTarget->CastSpell(pTarget, SPELL_KNOCK_BACK, true, NULL, NULL, me->GetGUID()); break; - } - } - } - - //this part should be in the core - if (pSpell->Id == SPELL_SHATTER) - { - //this spell must have custom handling in the core, dealing damage based on distance - pTarget->CastSpell(pTarget, SPELL_SHATTER_EFFECT, true); - - if (pTarget->HasAura(SPELL_STONED)) - pTarget->RemoveAurasDueToSpell(SPELL_STONED); - - //clear this, if we are still performing - if (m_bPerformingGroundSlam) - { - m_bPerformingGroundSlam = false; - - //and correct movement, if not already - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) - { - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // Growth - // Gruul can cast this spell up to 30 times - if (m_uiGrowth_Timer <= uiDiff) - { - DoScriptText(EMOTE_GROW, me); - DoCast(me, SPELL_GROWTH); - m_uiGrowth_Timer = 30000; - } - else - m_uiGrowth_Timer -= uiDiff; - - if (m_bPerformingGroundSlam) - { - if (m_uiGroundSlamTimer <= uiDiff) - { - m_uiGroundSlamTimer =120000; - m_uiHurtfulStrike_Timer= 8000; - - if (m_uiReverberation_Timer < 10000) //Give a little time to the players to undo the damage from shatter - m_uiReverberation_Timer += 10000; - - DoCast(me, SPELL_SHATTER); - } - else - m_uiGroundSlamTimer -= uiDiff; - } - else - { - // Hurtful Strike - if (m_uiHurtfulStrike_Timer <= uiDiff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); - - if (pTarget && me->IsWithinMeleeRange(me->getVictim())) - DoCast(pTarget, SPELL_HURTFUL_STRIKE); - else - DoCast(me->getVictim(), SPELL_HURTFUL_STRIKE); - - m_uiHurtfulStrike_Timer= 8000; - } - else - m_uiHurtfulStrike_Timer -= uiDiff; - - // Reverberation - if (m_uiReverberation_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_REVERBERATION, true); - m_uiReverberation_Timer = 15000 + rand()%10000; - } - else - m_uiReverberation_Timer -= uiDiff; - - // Cave In - if (m_uiCaveIn_Timer <= uiDiff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CAVE_IN); - - if (m_uiCaveIn_StaticTimer >= 4000) - m_uiCaveIn_StaticTimer -= 2000; - - m_uiCaveIn_Timer = m_uiCaveIn_StaticTimer; - } - else - m_uiCaveIn_Timer -= uiDiff; - - // Ground Slam, Gronn Lord's Grasp, Stoned, Shatter - if (m_uiGroundSlamTimer <= uiDiff) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - - m_bPerformingGroundSlam= true; - m_uiGroundSlamTimer = 10000; - - DoCast(me, SPELL_GROUND_SLAM); - } - else - m_uiGroundSlamTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - } -}; - -CreatureAI* GetAI_boss_gruul(Creature* pCreature) -{ - return new boss_gruulAI (pCreature); -} - -void AddSC_boss_gruul() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gruul"; - newscript->GetAI = &GetAI_boss_gruul; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp b/src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp deleted file mode 100644 index 482af86225c..00000000000 --- a/src/server/scripts/Outland/gruuls_lair/boss_high_king_maulgar.cpp +++ /dev/null @@ -1,783 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_High_King_Maulgar -SD%Complete: 90 -SDComment: Correct timers, after whirlwind melee attack bug, prayer of healing -SDCategory: Gruul's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "gruuls_lair.h" - -#define SAY_AGGRO -1565000 -#define SAY_ENRAGE -1565001 -#define SAY_OGRE_DEATH1 -1565002 -#define SAY_OGRE_DEATH2 -1565003 -#define SAY_OGRE_DEATH3 -1565004 -#define SAY_OGRE_DEATH4 -1565005 -#define SAY_SLAY1 -1565006 -#define SAY_SLAY2 -1565007 -#define SAY_SLAY3 -1565008 -#define SAY_DEATH -1565009 - -// High King Maulgar -#define SPELL_ARCING_SMASH 39144 -#define SPELL_MIGHTY_BLOW 33230 -#define SPELL_WHIRLWIND 33238 -#define SPELL_BERSERKER_C 26561 -#define SPELL_ROAR 16508 -#define SPELL_FLURRY 33232 -#define SPELL_DUAL_WIELD 29651 //used in phase - -// Olm the Summoner -#define SPELL_DARK_DECAY 33129 -#define SPELL_DEATH_COIL 33130 -#define SPELL_SUMMON_WFH 33131 - -//Kiggler the Craed -#define SPELL_GREATER_POLYMORPH 33173 -#define SPELL_LIGHTNING_BOLT 36152 -#define SPELL_ARCANE_SHOCK 33175 -#define SPELL_ARCANE_EXPLOSION 33237 - -//Blindeye the Seer -#define SPELL_GREATER_PW_SHIELD 33147 -#define SPELL_HEAL 33144 -#define SPELL_PRAYER_OH 33152 - -//Krosh Firehand -#define SPELL_GREATER_FIREBALL 33051 -#define SPELL_SPELLSHIELD 33054 -#define SPELL_BLAST_WAVE 33061 - -bool CheckAllBossDied(ScriptedInstance* pInstance, Creature* me) -{ - if (!pInstance || !me) - return false; - - uint64 MaulgarGUID = 0; - uint64 KigglerGUID = 0; - uint64 BlindeyeGUID = 0; - uint64 OlmGUID = 0; - uint64 KroshGUID = 0; - - Creature* Maulgar = NULL; - Creature* Kiggler = NULL; - Creature* Blindeye = NULL; - Creature* Olm = NULL; - Creature* Krosh = NULL; - - MaulgarGUID = pInstance->GetData64(DATA_MAULGAR); - KigglerGUID = pInstance->GetData64(DATA_KIGGLERTHECRAZED); - BlindeyeGUID = pInstance->GetData64(DATA_BLINDEYETHESEER); - OlmGUID = pInstance->GetData64(DATA_OLMTHESUMMONER); - KroshGUID = pInstance->GetData64(DATA_KROSHFIREHAND); - - Maulgar = (Unit::GetCreature((*me), MaulgarGUID)); - Kiggler = (Unit::GetCreature((*me), KigglerGUID)); - Blindeye = (Unit::GetCreature((*me), BlindeyeGUID)); - Olm = (Unit::GetCreature((*me), OlmGUID)); - Krosh = (Unit::GetCreature((*me), KroshGUID)); - - if (!Maulgar || !Kiggler || !Blindeye || !Olm || !Krosh) - return false; - - if (!Maulgar->isAlive() && !Kiggler->isAlive() && !Blindeye->isAlive() && !Olm->isAlive() && !Krosh->isAlive()) - return true; - - return false; -} - -//High King Maulgar AI -struct boss_high_king_maulgarAI : public ScriptedAI -{ - boss_high_king_maulgarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; - } - - ScriptedInstance* pInstance; - - uint32 ArcingSmash_Timer; - uint32 MightyBlow_Timer; - uint32 Whirlwind_Timer; - uint32 Charging_Timer; - uint32 Roar_Timer; - - bool Phase2; - - uint64 Council[4]; - - void Reset() - { - ArcingSmash_Timer = 10000; - MightyBlow_Timer = 40000; - Whirlwind_Timer = 30000; - Charging_Timer = 0; - Roar_Timer = 0; - - DoCast(me, SPELL_DUAL_WIELD, false); - - Phase2 = false; - - Creature *pCreature = NULL; - for (uint8 i = 0; i < 4; ++i) - { - if (Council[i]) - { - pCreature = (Unit::GetCreature((*me), Council[i])); - if (pCreature && !pCreature->isAlive()) - { - pCreature->Respawn(); - pCreature->AI()->EnterEvadeMode(); - } - } - } - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - - void AddDeath() - { - DoScriptText(RAND(SAY_OGRE_DEATH1,SAY_OGRE_DEATH2,SAY_OGRE_DEATH3,SAY_OGRE_DEATH4), me); - } - - void EnterCombat(Unit *who) - { - StartEvent(who); - } - - void GetCouncil() - { - if (pInstance) - { - //get council member's guid to respawn them if needed - Council[0] = pInstance->GetData64(DATA_KIGGLERTHECRAZED); - Council[1] = pInstance->GetData64(DATA_BLINDEYETHESEER); - Council[2] = pInstance->GetData64(DATA_OLMTHESUMMONER); - Council[3] = pInstance->GetData64(DATA_KROSHFIREHAND); - } - } - - void StartEvent(Unit *who) - { - if (!pInstance) - return; - - GetCouncil(); - - DoScriptText(SAY_AGGRO, me); - - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - - DoZoneInCombat(); - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - GetCouncil(); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //ArcingSmash_Timer - if (ArcingSmash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCING_SMASH); - ArcingSmash_Timer = 10000; - } else ArcingSmash_Timer -= diff; - - //Whirlwind_Timer - if (Whirlwind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - Whirlwind_Timer = 55000; - } else Whirlwind_Timer -= diff; - - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MIGHTY_BLOW); - MightyBlow_Timer = 30000+rand()%10000; - } else MightyBlow_Timer -= diff; - - //Entering Phase 2 - if (!Phase2 && (me->GetHealth()*100 / me->GetMaxHealth()) < 50) - { - Phase2 = true; - DoScriptText(SAY_ENRAGE, me); - - DoCast(me, SPELL_DUAL_WIELD, true); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - } - - if (Phase2) - { - //Charging_Timer - if (Charging_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - AttackStart(pTarget); - DoCast(pTarget, SPELL_BERSERKER_C); - } - Charging_Timer = 20000; - } else Charging_Timer -= diff; - - //Intimidating Roar - if (Roar_Timer <= diff) - { - DoCast(me, SPELL_ROAR); - Roar_Timer = 40000+(rand()%10000); - } else Roar_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -//Olm The Summoner AI -struct boss_olm_the_summonerAI : public ScriptedAI -{ - boss_olm_the_summonerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 DarkDecay_Timer; - uint32 Summon_Timer; - uint32 DeathCoil_Timer; - - ScriptedInstance* pInstance; - - void Reset() - { - DarkDecay_Timer = 10000; - Summon_Timer = 15000; - DeathCoil_Timer = 20000; - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(pWho, 30.0f); - } - } - - void EnterCombat(Unit *who) - { - if (pInstance) - { - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - Creature *Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //DarkDecay_Timer - if (DarkDecay_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DARK_DECAY); - DarkDecay_Timer = 20000; - } else DarkDecay_Timer -= diff; - - //Summon_Timer - if (Summon_Timer <= diff) - { - DoCast(me, SPELL_SUMMON_WFH); - Summon_Timer = 30000; - } else Summon_Timer -= diff; - - //DeathCoil Timer /need correct timer - if (DeathCoil_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_DEATH_COIL); - DeathCoil_Timer = 20000; - } else DeathCoil_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Kiggler The Crazed AI -struct boss_kiggler_the_crazedAI : public ScriptedAI -{ - boss_kiggler_the_crazedAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 GreaterPolymorph_Timer; - uint32 LightningBolt_Timer; - uint32 ArcaneShock_Timer; - uint32 ArcaneExplosion_Timer; - - ScriptedInstance* pInstance; - - void Reset() - { - GreaterPolymorph_Timer = 5000; - LightningBolt_Timer = 10000; - ArcaneShock_Timer = 20000; - ArcaneExplosion_Timer = 30000; - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - if (pInstance) - { - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - Creature *Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //GreaterPolymorph_Timer - if (GreaterPolymorph_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_GREATER_POLYMORPH); - - GreaterPolymorph_Timer = 15000 + rand()%5000; - } else GreaterPolymorph_Timer -= diff; - - //LightningBolt_Timer - if (LightningBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LIGHTNING_BOLT); - LightningBolt_Timer = 15000; - } else LightningBolt_Timer -= diff; - - //ArcaneShock_Timer - if (ArcaneShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_SHOCK); - ArcaneShock_Timer = 20000; - } else ArcaneShock_Timer -= diff; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_EXPLOSION); - ArcaneExplosion_Timer = 30000; - } else ArcaneExplosion_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Blindeye The Seer AI -struct boss_blindeye_the_seerAI : public ScriptedAI -{ - boss_blindeye_the_seerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 GreaterPowerWordShield_Timer; - uint32 Heal_Timer; - uint32 PrayerofHealing_Timer; - - ScriptedInstance* pInstance; - - void Reset() - { - GreaterPowerWordShield_Timer = 5000; - Heal_Timer = 25000 + rand()%15000; - PrayerofHealing_Timer = 45000 + rand()%10000; - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - Creature *Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //GreaterPowerWordShield_Timer - if (GreaterPowerWordShield_Timer <= diff) - { - DoCast(me, SPELL_GREATER_PW_SHIELD); - GreaterPowerWordShield_Timer = 40000; - } else GreaterPowerWordShield_Timer -= diff; - - //Heal_Timer - if (Heal_Timer <= diff) - { - DoCast(me, SPELL_HEAL); - Heal_Timer = 15000 + rand()%25000; - } else Heal_Timer -= diff; - - //PrayerofHealing_Timer - if (PrayerofHealing_Timer <= diff) - { - DoCast(me, SPELL_PRAYER_OH); - PrayerofHealing_Timer = 35000 + rand()%15000; - } else PrayerofHealing_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Krosh Firehand AI -struct boss_krosh_firehandAI : public ScriptedAI -{ - boss_krosh_firehandAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 GreaterFireball_Timer; - uint32 SpellShield_Timer; - uint32 BlastWave_Timer; - - ScriptedInstance* pInstance; - - void Reset() - { - GreaterFireball_Timer = 1000; - SpellShield_Timer = 5000; - BlastWave_Timer = 20000; - - //reset encounter - if (pInstance) - pInstance->SetData(DATA_MAULGAREVENT, NOT_STARTED); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - pInstance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - Creature *Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), pInstance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(pInstance, me)) - pInstance->SetData(DATA_MAULGAREVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_MAULGAREVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - - //GreaterFireball_Timer - if (GreaterFireball_Timer < diff || me->IsWithinDist(me->getVictim(), 30)) - { - DoCast(me->getVictim(), SPELL_GREATER_FIREBALL); - GreaterFireball_Timer = 2000; - } else GreaterFireball_Timer -= diff; - - //SpellShield_Timer - if (SpellShield_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me->getVictim(), SPELL_SPELLSHIELD); - SpellShield_Timer = 30000; - } else SpellShield_Timer -= diff; - - //BlastWave_Timer - if (BlastWave_Timer <= diff) - { - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //15 yard radius minimum - if (pTarget && pTarget->IsWithinDist(me, 15,false)) - target_list.push_back(pTarget); - pTarget = NULL; - } - if (target_list.size()) - pTarget = *(target_list.begin()+rand()%target_list.size()); - - me->InterruptNonMeleeSpells(false); - DoCast(pTarget, SPELL_BLAST_WAVE); - BlastWave_Timer = 60000; - } else BlastWave_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_high_king_maulgar(Creature* pCreature) -{ - return new boss_high_king_maulgarAI (pCreature); -} - -CreatureAI* GetAI_boss_olm_the_summoner(Creature* pCreature) -{ - return new boss_olm_the_summonerAI (pCreature); -} - -CreatureAI *GetAI_boss_kiggler_the_crazed(Creature* pCreature) -{ - return new boss_kiggler_the_crazedAI (pCreature); -} - -CreatureAI *GetAI_boss_blindeye_the_seer(Creature* pCreature) -{ - return new boss_blindeye_the_seerAI (pCreature); -} - -CreatureAI *GetAI_boss_krosh_firehand(Creature* pCreature) -{ - return new boss_krosh_firehandAI (pCreature); -} - -void AddSC_boss_high_king_maulgar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_high_king_maulgar"; - newscript->GetAI = &GetAI_boss_high_king_maulgar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_kiggler_the_crazed"; - newscript->GetAI = &GetAI_boss_kiggler_the_crazed; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_blindeye_the_seer"; - newscript->GetAI = &GetAI_boss_blindeye_the_seer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_olm_the_summoner"; - newscript->GetAI = &GetAI_boss_olm_the_summoner; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_krosh_firehand"; - newscript->GetAI = &GetAI_boss_krosh_firehand; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/gruuls_lair/gruuls_lair.h b/src/server/scripts/Outland/gruuls_lair/gruuls_lair.h deleted file mode 100644 index 7003dcb1e26..00000000000 --- a/src/server/scripts/Outland/gruuls_lair/gruuls_lair.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_GRUULS_LAIR_H -#define DEF_GRUULS_LAIR_H - -#define DATA_BLINDEYETHESEER 1 -#define DATA_GRUULEVENT 2 -#define DATA_KIGGLERTHECRAZED 3 -#define DATA_KROSHFIREHAND 4 -#define DATA_MAULGAREVENT 5 -#define DATA_MAULGAREVENT_TANK 6 -#define DATA_OLMTHESUMMONER 7 -#define DATA_MAULGARDOOR 8 -#define DATA_GRUULDOOR 9 -#define DATA_MAULGAR 10 - -#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Gruul's Lair instance (map 565). Encounters will be buggy." -#endif - diff --git a/src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp b/src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp deleted file mode 100644 index bb790a5d4ea..00000000000 --- a/src/server/scripts/Outland/gruuls_lair/instance_gruuls_lair.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Gruuls_Lair -SD%Complete: 100 -SDComment: -SDCategory: Gruul's Lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "gruuls_lair.h" - -#define MAX_ENCOUNTER 2 - -/* Gruuls Lair encounters: -1 - High King Maulgar event -2 - Gruul event -*/ - -struct instance_gruuls_lair : public ScriptedInstance -{ - instance_gruuls_lair(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 MaulgarEvent_Tank; - uint64 KigglerTheCrazed; - uint64 BlindeyeTheSeer; - uint64 OlmTheSummoner; - uint64 KroshFirehand; - uint64 Maulgar; - - uint64 MaulgarDoor; - uint64 GruulDoor; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - MaulgarEvent_Tank = 0; - KigglerTheCrazed = 0; - BlindeyeTheSeer = 0; - OlmTheSummoner = 0; - KroshFirehand = 0; - Maulgar = 0; - - MaulgarDoor = 0; - GruulDoor = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 18835: KigglerTheCrazed = pCreature->GetGUID(); break; - case 18836: BlindeyeTheSeer = pCreature->GetGUID(); break; - case 18834: OlmTheSummoner = pCreature->GetGUID(); break; - case 18832: KroshFirehand = pCreature->GetGUID(); break; - case 18831: Maulgar = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 184468: - MaulgarDoor = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) HandleGameObject(NULL, true, pGo); - break; - case 184662: GruulDoor = pGo->GetGUID(); break; - } - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_MAULGAREVENT_TANK) - MaulgarEvent_Tank = data; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_MAULGAREVENT_TANK: return MaulgarEvent_Tank; - case DATA_KIGGLERTHECRAZED: return KigglerTheCrazed; - case DATA_BLINDEYETHESEER: return BlindeyeTheSeer; - case DATA_OLMTHESUMMONER: return OlmTheSummoner; - case DATA_KROSHFIREHAND: return KroshFirehand; - case DATA_MAULGARDOOR: return MaulgarDoor; - case DATA_GRUULDOOR: return GruulDoor; - case DATA_MAULGAR: return Maulgar; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MAULGAREVENT: - if (data == DONE) HandleGameObject(MaulgarDoor, true); - m_auiEncounter[0] = data; break; - case DATA_GRUULEVENT: - if (data == IN_PROGRESS) HandleGameObject(GruulDoor, false); - else HandleGameObject(GruulDoor, true); - m_auiEncounter[1] = data; break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_MAULGAREVENT: return m_auiEncounter[0]; - case DATA_GRUULEVENT: return m_auiEncounter[1]; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_gruuls_lair(Map* pMap) -{ - return new instance_gruuls_lair(pMap); -} - -void AddSC_instance_gruuls_lair() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_gruuls_lair"; - newscript->GetInstanceData = &GetInstanceData_instance_gruuls_lair; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h deleted file mode 100644 index b845c66823f..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/blood_furnace.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BLOOD_FURNACE_H -#define DEF_BLOOD_FURNACE_H - -#define DATA_THE_MAKER 1 -#define DATA_BROGGOK 2 -#define DATA_KELIDAN_THE_MAKER 3 -#define TYPE_THE_MAKER_EVENT 4 -#define TYPE_BROGGOK_EVENT 5 -#define TYPE_KELIDAN_THE_BREAKER_EVENT 6 -#define DATA_DOOR1 7 -#define DATA_DOOR2 8 -#define DATA_DOOR3 9 -#define DATA_DOOR4 10 -#define DATA_DOOR5 11 -#define DATA_DOOR6 12 -#define DATA_PRISON_CELL1 13 -#define DATA_PRISON_CELL2 14 -#define DATA_PRISON_CELL3 15 -#define DATA_PRISON_CELL4 16 -#define DATA_PRISON_CELL5 17 -#define DATA_PRISON_CELL6 18 -#define DATA_PRISON_CELL7 19 -#define DATA_PRISON_CELL8 20 -#endif - diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp deleted file mode 100644 index d5fb9bdba49..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_broggok.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Broggok -SD%Complete: 70 -SDComment: pre-event not made -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eEnums -{ - SAY_AGGRO = -1542008, - - SPELL_SLIME_SPRAY = 30913, - SPELL_POISON_CLOUD = 30916, - SPELL_POISON_BOLT = 30917, - - SPELL_POISON = 30914 -}; - -struct boss_broggokAI : public ScriptedAI -{ - boss_broggokAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AcidSpray_Timer; - uint32 PoisonSpawn_Timer; - uint32 PoisonBolt_Timer; - - void Reset() - { - AcidSpray_Timer = 10000; - PoisonSpawn_Timer = 5000; - PoisonBolt_Timer = 7000; - if (pInstance) - { - pInstance->SetData(TYPE_BROGGOK_EVENT, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - pInstance->SetData(TYPE_BROGGOK_EVENT, IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), false); - } - } - - void JustSummoned(Creature *summoned) - { - summoned->setFaction(16); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->CastSpell(summoned,SPELL_POISON,false,0,0,me->GetGUID()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AcidSpray_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLIME_SPRAY); - AcidSpray_Timer = 4000+rand()%8000; - } else AcidSpray_Timer -=diff; - - if (PoisonBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_BOLT); - PoisonBolt_Timer = 4000+rand()%8000; - } else PoisonBolt_Timer -=diff; - - if (PoisonSpawn_Timer <= diff) - { - DoCast(me, SPELL_POISON_CLOUD); - PoisonSpawn_Timer = 20000; - } else PoisonSpawn_Timer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*who*/) - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR5), true); - pInstance->SetData(TYPE_BROGGOK_EVENT, DONE); - } - } - -}; - -CreatureAI* GetAI_boss_broggok(Creature* pCreature) -{ - return new boss_broggokAI (pCreature); -} - -void AddSC_boss_broggok() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_broggok"; - newscript->GetAI = &GetAI_boss_broggok; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp deleted file mode 100644 index a44ad9cc3c8..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kelidan_The_Breaker -SD%Complete: 100 -SDComment: -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -/* ContentData -boss_kelidan_the_breaker -mob_shadowmoon_channeler -EndContentData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eKelidan -{ - SAY_WAKE = -1542000, - SAY_ADD_AGGRO_1 = -1542001, - SAY_ADD_AGGRO_2 = -1542002, - SAY_ADD_AGGRO_3 = -1542003, - SAY_KILL_1 = -1542004, - SAY_KILL_2 = -1542005, - SAY_NOVA = -1542006, - SAY_DIE = -1542007, - - SPELL_CORRUPTION = 30938, - SPELL_EVOCATION = 30935, - - SPELL_FIRE_NOVA = 33132, - H_SPELL_FIRE_NOVA = 37371, - - SPELL_SHADOW_BOLT_VOLLEY = 28599, - H_SPELL_SHADOW_BOLT_VOLLEY = 40070, - - SPELL_BURNING_NOVA = 30940, - SPELL_VORTEX = 37370, - - ENTRY_KELIDAN = 17377, - ENTRY_CHANNELER = 17653 -}; - -const float ShadowmoonChannelers[5][4]= -{ - {302,-87,-24.4,0.157}, - {321,-63.5,-24.6,4.887}, - {346,-74.5,-24.6,3.595}, - {344,-103.5,-24.5,2.356}, - {316,-109,-24.6,1.257} -}; - -struct boss_kelidan_the_breakerAI : public ScriptedAI -{ - boss_kelidan_the_breakerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i=0; i<5; ++i) - Channelers[i] = 0; - } - - ScriptedInstance* pInstance; - - uint32 ShadowVolley_Timer; - uint32 BurningNova_Timer; - uint32 Firenova_Timer; - uint32 Corruption_Timer; - uint32 check_Timer; - bool Firenova; - bool addYell; - uint64 Channelers[5]; - - void Reset() - { - ShadowVolley_Timer = 1000; - BurningNova_Timer = 15000; - Corruption_Timer = 5000; - check_Timer = 0; - Firenova = false; - addYell = false; - SummonChannelers(); - if (pInstance) - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_WAKE, me); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - DoStartMovement(who); - if (pInstance) - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void ChannelerEngaged(Unit* who) - { - if (who && !addYell) - { - addYell = true; - DoScriptText(RAND(SAY_ADD_AGGRO_1,SAY_ADD_AGGRO_2,SAY_ADD_AGGRO_3), me); - } - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (who && channeler && !channeler->isInCombat()) - channeler->AI()->AttackStart(who); - } - } - - void ChannelerDied(Unit* killer) - { - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (channeler && channeler->isAlive()) - return; - } - - if (killer) - me->AI()->AttackStart(killer); - } - - uint64 GetChanneled(Creature *channeler1) - { - SummonChannelers(); - if (!channeler1) return NULL; - uint8 i; - for (i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (channeler && channeler->GetGUID() == channeler1->GetGUID()) - break; - } - return Channelers[(i+2)%5]; - } - - void SummonChannelers() - { - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (!channeler || channeler->isDead()) - channeler = me->SummonCreature(ENTRY_CHANNELER,ShadowmoonChannelers[i][0],ShadowmoonChannelers[i][1],ShadowmoonChannelers[i][2],ShadowmoonChannelers[i][3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,300000); - if (channeler) - Channelers[i] = channeler->GetGUID(); - else - Channelers[i] = 0; - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR1), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR6), true); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (check_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - DoCast(me, SPELL_EVOCATION); - check_Timer = 5000; - } else check_Timer -= diff; - return; - } - - if (Firenova) - { - if (Firenova_Timer <= diff) - { - DoCast(me, SPELL_FIRE_NOVA, true); - Firenova = false; - ShadowVolley_Timer = 2000; - } else Firenova_Timer -=diff; - - return; - } - - if (ShadowVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); - ShadowVolley_Timer = 5000+rand()%8000; - } else ShadowVolley_Timer -=diff; - - if (Corruption_Timer <= diff) - { - DoCast(me, SPELL_CORRUPTION); - Corruption_Timer = 30000+rand()%20000; - } else Corruption_Timer -=diff; - - if (BurningNova_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(SAY_NOVA, me); - - if (SpellEntry *nova = GET_SPELL(SPELL_BURNING_NOVA)) - { - if (Aura * aura = Aura::TryCreate(nova, me, me)) - aura->ApplyForTargets(); - } - - if (IsHeroic()) - DoTeleportAll(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - - BurningNova_Timer = 20000+rand()%8000; - Firenova_Timer= 5000; - Firenova = true; - } else BurningNova_Timer -=diff; - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_boss_kelidan_the_breaker(Creature* pCreature) -{ - return new boss_kelidan_the_breakerAI (pCreature); -} - -/*###### -## mob_shadowmoon_channeler -######*/ - -enum eShadowmoon -{ - SPELL_SHADOW_BOLT = 12739, - H_SPELL_SHADOW_BOLT = 15472, - - SPELL_MARK_OF_SHADOW = 30937, - SPELL_CHANNELING = 39123 -}; - -struct mob_shadowmoon_channelerAI : public ScriptedAI -{ - mob_shadowmoon_channelerAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 ShadowBolt_Timer; - uint32 MarkOfShadow_Timer; - uint32 check_Timer; - - void Reset() - { - ShadowBolt_Timer = 1000+rand()%1000; - MarkOfShadow_Timer = 5000+rand()%2000; - check_Timer = 0; - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - } - - void EnterCombat(Unit* who) - { - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerEngaged(who); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - DoStartMovement(who); - } - - void JustDied(Unit* Killer) - { - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerDied(Killer); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (check_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - { - uint64 channeler = CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->GetChanneled(me); - if (Unit *channeled = Unit::GetUnit(*me, channeler)) - DoCast(channeled, SPELL_CHANNELING); - } - check_Timer = 5000; - } else check_Timer -= diff; - return; - } - - if (MarkOfShadow_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_MARK_OF_SHADOW); - MarkOfShadow_Timer = 15000+rand()%5000; - } else MarkOfShadow_Timer -=diff; - - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - ShadowBolt_Timer = 5000+rand()%1000; - } else ShadowBolt_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_shadowmoon_channeler(Creature* pCreature) -{ - return new mob_shadowmoon_channelerAI (pCreature); -} - -void AddSC_boss_kelidan_the_breaker() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_kelidan_the_breaker"; - newscript->GetAI = &GetAI_boss_kelidan_the_breaker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadowmoon_channeler"; - newscript->GetAI = &GetAI_mob_shadowmoon_channeler; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp deleted file mode 100644 index 45219b6509b..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_The_Maker -SD%Complete: 80 -SDComment: Mind control no support -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eEnums -{ - SAY_AGGRO_1 = -1542009, - SAY_AGGRO_2 = -1542010, - SAY_AGGRO_3 = -1542011, - SAY_KILL_1 = -1542012, - SAY_KILL_2 = -1542013, - SAY_DIE = -1542014, - - SPELL_ACID_SPRAY = 38153, // heroic 38973 ??? 38153 - SPELL_EXPLODING_BREAKER = 30925, - SPELL_KNOCKDOWN = 20276, - SPELL_DOMINATION = 25772 // ??? -}; - -struct boss_the_makerAI : public ScriptedAI -{ - boss_the_makerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AcidSpray_Timer; - uint32 ExplodingBreaker_Timer; - uint32 Domination_Timer; - uint32 Knockdown_Timer; - - void Reset() - { - AcidSpray_Timer = 15000; - ExplodingBreaker_Timer = 6000; - Domination_Timer = 120000; - Knockdown_Timer = 10000; - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), false); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR3), true); - - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AcidSpray_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ACID_SPRAY); - AcidSpray_Timer = 15000+rand()%8000; - } else AcidSpray_Timer -=diff; - - if (ExplodingBreaker_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_EXPLODING_BREAKER); - ExplodingBreaker_Timer = 4000+rand()%8000; - } else ExplodingBreaker_Timer -=diff; - - /* // Disabled until Core Support for mind control - if (domination_timer_timer <= diff) - { - Unit *pTarget; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - DoCast(pTarget, SPELL_DOMINATION); - - domination_timer = 120000; - } else domination_timer -=diff; - */ - - if (Knockdown_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - Knockdown_Timer = 4000+rand()%8000; - } else Knockdown_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_the_makerAI(Creature* pCreature) -{ - return new boss_the_makerAI (pCreature); -} - -void AddSC_boss_the_maker() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_maker"; - newscript->GetAI = &GetAI_boss_the_makerAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp deleted file mode 100644 index 3a2eb8ba5ee..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Blood_Furnace -SD%Complete: 85 -SDComment: -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -#define ENTRY_SEWER1 181823 -#define ENTRY_SEWER2 181766 -#define MAX_ENCOUNTER 3 - -struct instance_blood_furnace : public ScriptedInstance -{ - instance_blood_furnace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 The_MakerGUID; - uint64 BroggokGUID; - uint64 Kelidan_The_BreakerGUID; - - uint64 Door1GUID; - uint64 Door2GUID; - uint64 Door3GUID; - uint64 Door4GUID; - uint64 Door5GUID; - uint64 Door6GUID; - - uint64 PrisonCell1GUID; - uint64 PrisonCell2GUID; - uint64 PrisonCell3GUID; - uint64 PrisonCell4GUID; - uint64 PrisonCell5GUID; - uint64 PrisonCell6GUID; - uint64 PrisonCell7GUID; - uint64 PrisonCell8GUID; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - The_MakerGUID = 0; - BroggokGUID = 0; - Kelidan_The_BreakerGUID = 0; - - Door1GUID = 0; - Door2GUID = 0; - Door3GUID = 0; - Door4GUID = 0; - Door5GUID = 0; - Door6GUID = 0; - - PrisonCell1GUID = 0; - PrisonCell2GUID = 0; - PrisonCell3GUID = 0; - PrisonCell4GUID = 0; - PrisonCell5GUID = 0; - PrisonCell6GUID = 0; - PrisonCell7GUID = 0; - PrisonCell8GUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - if (!add) - return; - - switch(pCreature->GetEntry()) - { - case 17381: The_MakerGUID = pCreature->GetGUID(); break; - case 17380: BroggokGUID = pCreature->GetGUID(); break; - case 17377: Kelidan_The_BreakerGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if (!add) - return; - - if (pGo->GetEntry() == 181766) //Final exit door - Door1GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181811) //The Maker Front door - Door2GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181812) //The Maker Rear door - Door3GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181822) //Broggok Front door - Door4GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181819) //Broggok Rear door - Door5GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181823) //Kelidan exit door - Door6GUID = pGo->GetGUID(); - - if (pGo->GetEntry() == 181813) //The Maker prison cell front right - PrisonCell1GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181814) //The Maker prison cell back right - PrisonCell2GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181816) //The Maker prison cell front left - PrisonCell3GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181815) //The Maker prison cell back left - PrisonCell4GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181821) //Broggok prison cell front right - PrisonCell5GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181818) //Broggok prison cell back right - PrisonCell6GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181820) //Broggok prison cell front left - PrisonCell7GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181817) //Broggok prison cell back left - PrisonCell8GUID = pGo->GetGUID(); - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THE_MAKER: return The_MakerGUID; - case DATA_BROGGOK: return BroggokGUID; - case DATA_KELIDAN_THE_MAKER: return Kelidan_The_BreakerGUID; - case DATA_DOOR1: return Door1GUID; - case DATA_DOOR2: return Door2GUID; - case DATA_DOOR3: return Door3GUID; - case DATA_DOOR4: return Door4GUID; - case DATA_DOOR5: return Door5GUID; - case DATA_DOOR6: return Door6GUID; - case DATA_PRISON_CELL1: return PrisonCell1GUID; - case DATA_PRISON_CELL2: return PrisonCell2GUID; - case DATA_PRISON_CELL3: return PrisonCell3GUID; - case DATA_PRISON_CELL4: return PrisonCell4GUID; - case DATA_PRISON_CELL5: return PrisonCell5GUID; - case DATA_PRISON_CELL6: return PrisonCell6GUID; - case DATA_PRISON_CELL7: return PrisonCell7GUID; - case DATA_PRISON_CELL8: return PrisonCell8GUID; - } - - return 0; - } - - void SetData(uint32 /*type*/, uint32 data) - { - switch(data) - { - case TYPE_THE_MAKER_EVENT: m_auiEncounter[0] = data; break; - case TYPE_BROGGOK_EVENT: m_auiEncounter[1] = data; break; - case TYPE_KELIDAN_THE_BREAKER_EVENT: m_auiEncounter[2] = data; break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 data) - { - switch(data) - { - case TYPE_THE_MAKER_EVENT: return m_auiEncounter[0]; - case TYPE_BROGGOK_EVENT: return m_auiEncounter[1]; - case TYPE_KELIDAN_THE_BREAKER_EVENT: return m_auiEncounter[2]; - } - - return 0; - } - - const char* Save() - { - return str_data.c_str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS || m_auiEncounter[i] == FAIL) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_blood_furnace(Map* pMap) -{ - return new instance_blood_furnace(pMap); -} - -void AddSC_instance_blood_furnace() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blood_furnace"; - newscript->GetInstanceData = &GetInstanceData_instance_blood_furnace; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp deleted file mode 100644 index d6c0b2fd401..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Omar_The_Unscarred -SD%Complete: 90 -SDComment: Temporary solution for orbital/shadow whip-ability. Needs more core support before making it more proper. -SDCategory: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1543009 -#define SAY_AGGRO_2 -1543010 -#define SAY_AGGRO_3 -1543011 -#define SAY_SUMMON -1543012 -#define SAY_CURSE -1543013 -#define SAY_KILL_1 -1543014 -#define SAY_DIE -1543015 -#define SAY_WIPE -1543016 - -#define SPELL_ORBITAL_STRIKE 30637 -#define SPELL_SHADOW_WHIP 30638 -#define SPELL_TREACHEROUS_AURA 30695 -#define H_SPELL_BANE_OF_TREACHERY 37566 -#define SPELL_DEMONIC_SHIELD 31901 -#define SPELL_SHADOW_BOLT 30686 -#define H_SPELL_SHADOW_BOLT 39297 -#define SPELL_SUMMON_FIENDISH_HOUND 30707 - -struct boss_omor_the_unscarredAI : public ScriptedAI -{ - boss_omor_the_unscarredAI(Creature *c) : ScriptedAI(c) - { - SetCombatMovement(false); - } - - uint32 OrbitalStrike_Timer; - uint32 ShadowWhip_Timer; - uint32 Aura_Timer; - uint32 DemonicShield_Timer; - uint32 Shadowbolt_Timer; - uint32 Summon_Timer; - uint32 SummonedCount; - uint64 PlayerGUID; - bool CanPullBack; - - void Reset() - { - DoScriptText(SAY_WIPE, me); - - OrbitalStrike_Timer = 25000; - ShadowWhip_Timer = 2000; - Aura_Timer = 10000; - DemonicShield_Timer = 1000; - Shadowbolt_Timer = 2000; - Summon_Timer = 10000; - SummonedCount = 0; - PlayerGUID = 0; - CanPullBack = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(SAY_KILL_1, me); - } - - void JustSummoned(Creature* summoned) - { - DoScriptText(SAY_SUMMON, me); - - if (Unit* random = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(random); - - ++SummonedCount; - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //only two may be wrong, perhaps increase timer and spawn periodically instead. - if (SummonedCount < 2) - { - if (Summon_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SUMMON_FIENDISH_HOUND); - Summon_Timer = 15000+rand()%15000; - } else Summon_Timer -= diff; - } - - if (CanPullBack) - { - if (ShadowWhip_Timer <= diff) - { - if (Player* temp = Unit::GetPlayer(PlayerGUID)) - { - //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) - if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) - { - me->InterruptNonMeleeSpells(false); - DoCast(temp, SPELL_SHADOW_WHIP); - } - } - PlayerGUID = 0; - ShadowWhip_Timer = 2000; - CanPullBack = false; - } else ShadowWhip_Timer -= diff; - } - else if (OrbitalStrike_Timer <= diff) - { - Unit* temp = NULL; - if (me->IsWithinMeleeRange(me->getVictim())) - temp = me->getVictim(); - else temp = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (temp && temp->GetTypeId() == TYPEID_PLAYER) - { - DoCast(temp, SPELL_ORBITAL_STRIKE); - OrbitalStrike_Timer = 14000+rand()%2000; - PlayerGUID = temp->GetGUID(); - - if (PlayerGUID) - CanPullBack = true; - } - } else OrbitalStrike_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) - { - if (DemonicShield_Timer <= diff) - { - DoCast(me, SPELL_DEMONIC_SHIELD); - DemonicShield_Timer = 15000; - } else DemonicShield_Timer -= diff; - } - - if (Aura_Timer <= diff) - { - DoScriptText(SAY_CURSE, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_TREACHEROUS_AURA); - Aura_Timer = 8000+rand()%8000; - } - } else Aura_Timer -= diff; - - if (Shadowbolt_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget) - pTarget = me->getVictim(); - - DoCast(pTarget, SPELL_SHADOW_BOLT); - Shadowbolt_Timer = 4000+rand()%2500; - } - } else Shadowbolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_omor_the_unscarredAI(Creature* pCreature) -{ - return new boss_omor_the_unscarredAI (pCreature); -} - -void AddSC_boss_omor_the_unscarred() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_omor_the_unscarred"; - newscript->GetAI = &GetAI_boss_omor_the_unscarredAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp deleted file mode 100644 index 181911f77a4..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -Name: Boss_Vazruden_the_Herald -%Complete: 90 -Comment: -Category: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FIREBALL DUNGEON_MODE(34653, 36920) -#define SPELL_CONE_OF_FIRE DUNGEON_MODE(30926, 36921) -#define SPELL_SUMMON_LIQUID_FIRE DUNGEON_MODE(23971, 30928) -#define SPELL_BELLOWING_ROAR 39427 -#define SPELL_REVENGE DUNGEON_MODE(19130, 40392) -#define SPELL_KIDNEY_SHOT 30621 -#define SPELL_FIRE_NOVA_VISUAL 19823 - -#define ENTRY_HELLFIRE_SENTRY 17517 -#define ENTRY_VAZRUDEN_HERALD 17307 -#define ENTRY_VAZRUDEN 17537 -#define ENTRY_NAZAN 17536 -#define ENTRY_LIQUID_FIRE 22515 -#define ENTRY_REINFORCED_FEL_IRON_CHEST DUNGEON_MODE(185168, 185169) - -#define SAY_INTRO -1543017 -#define SAY_WIPE -1543018 -#define SAY_AGGRO_1 -1543019 -#define SAY_AGGRO_2 -1543020 -#define SAY_AGGRO_3 -1543021 -#define SAY_KILL_1 -1543022 -#define SAY_KILL_2 -1543023 -#define SAY_DIE -1543024 -#define EMOTE -1543025 - -#define PATH_ENTRY 2081 - -const float VazrudenMiddle[3] = {-1406.5, 1746.5, 81.2}; -const float VazrudenRing[2][3] = -{ - {-1430, 1705, 112}, - {-1377, 1760, 112} -}; - -struct boss_nazanAI : public ScriptedAI -{ - boss_nazanAI(Creature *c) : ScriptedAI(c) - { - VazrudenGUID = 0; - flight = true; - } - - uint32 Fireball_Timer; - uint32 ConeOfFire_Timer; - uint32 BellowingRoar_Timer; - uint32 Fly_Timer; - uint32 Turn_Timer; - uint32 UnsummonCheck; - bool flight; - uint64 VazrudenGUID; - SpellEntry *liquid_fire; - - void Reset() - { - Fireball_Timer = 4000; - Fly_Timer = 45000; - Turn_Timer = 0; - UnsummonCheck = 5000; - } - - void EnterCombat(Unit* /*who*/) {} - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == ENTRY_LIQUID_FIRE) - { - summoned->SetLevel(me->getLevel()); - summoned->setFaction(me->getFaction()); - summoned->CastSpell(summoned,SPELL_SUMMON_LIQUID_FIRE,true); - summoned->CastSpell(summoned,SPELL_FIRE_NOVA_VISUAL,true); - } - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry* entry) - { - if (pTarget && entry->Id == uint32(SPELL_FIREBALL)) - me->SummonCreature(ENTRY_LIQUID_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),pTarget->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,30000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (UnsummonCheck < diff && me->isAlive()) - me->DisappearAndDie(); - else - UnsummonCheck -= diff; - return; - } - - if (Fireball_Timer <= diff) - { - if (Unit *victim = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(victim, SPELL_FIREBALL, true); - Fireball_Timer = urand(4000,7000); - } else Fireball_Timer -= diff; - - if (flight) // phase 1 - the flight - { - Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); - if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) - { - flight = false; - BellowingRoar_Timer = 6000; - ConeOfFire_Timer = 12000; - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->Clear(); - if (Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) - me->AI()->AttackStart(victim); - DoStartMovement(me->getVictim()); - DoScriptText(EMOTE, me); - return; - } else Fly_Timer -= diff; - - if (Turn_Timer <= diff) - { - uint32 waypoint = (Fly_Timer/10000)%2; - if (me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) - me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); - Turn_Timer = 10000; - } else Turn_Timer -= diff; - } - else // phase 2 - land fight - { - if (ConeOfFire_Timer <= diff) - { - DoCast(me, SPELL_CONE_OF_FIRE); - ConeOfFire_Timer = 12000; - Fireball_Timer = 4000; - } else ConeOfFire_Timer -= diff; - - if (IsHeroic()) - if (BellowingRoar_Timer <= diff) - { - DoCast(me, SPELL_BELLOWING_ROAR); - BellowingRoar_Timer = 45000; - } else BellowingRoar_Timer -= diff; - - DoMeleeAttackIfReady(); - } - } -}; - -struct boss_vazrudenAI : public ScriptedAI -{ - boss_vazrudenAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Revenge_Timer; - bool WipeSaid; - uint32 UnsummonCheck; - - void Reset() - { - Revenge_Timer = 4000; - UnsummonCheck = 2000; - WipeSaid = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void KilledUnit(Unit* who) - { - if (who && who->GetEntry() != ENTRY_VAZRUDEN) - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* who) - { - if (who && who != me) - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (UnsummonCheck < diff && me->isAlive()) - { - if (!WipeSaid) - { - DoScriptText(SAY_WIPE, me); - WipeSaid = true; - } - me->DisappearAndDie(); - } else UnsummonCheck -= diff; - return; - } - - if (Revenge_Timer <= diff) - { - if (Unit *victim = me->getVictim()) - DoCast(victim, SPELL_REVENGE); - Revenge_Timer = 5000; - } else Revenge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_vazruden_the_heraldAI : public ScriptedAI -{ - boss_vazruden_the_heraldAI(Creature *c) : ScriptedAI(c) - { - summoned = false; - sentryDown = false; - NazanGUID = 0; - VazrudenGUID = 0; - } - - uint32 phase; - uint32 waypoint; - uint32 check; - bool sentryDown; - uint64 NazanGUID; - uint64 VazrudenGUID; - bool summoned; - - void Reset() - { - phase = 0; - waypoint = 0; - check = 0; - UnsummonAdds(); - me->GetMotionMaster()->MovePath(PATH_ENTRY, true); - } - - void UnsummonAdds() - { - if (summoned) - { - Creature *Nazan = Unit::GetCreature(*me, NazanGUID); - if (!Nazan) - Nazan = me->FindNearestCreature(ENTRY_NAZAN, 5000); - if (Nazan) - { - Nazan->DisappearAndDie(); - NazanGUID = 0; - } - - Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); - if (!Vazruden) - Vazruden = me->FindNearestCreature(ENTRY_VAZRUDEN, 5000); - if (Vazruden) - { - Vazruden->DisappearAndDie(); - VazrudenGUID = 0; - } - summoned = false; - me->clearUnitState(UNIT_STAT_ROOT); - me->SetVisibility(VISIBILITY_ON); - } - } - - void SummonAdds() - { - if (!summoned) - { - if (Creature* Vazruden = me->SummonCreature(ENTRY_VAZRUDEN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) - VazrudenGUID = Vazruden->GetGUID(); - if (Creature* Nazan = me->SummonCreature(ENTRY_NAZAN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) - NazanGUID = Nazan->GetGUID(); - summoned = true; - me->SetVisibility(VISIBILITY_OFF); - me->addUnitState(UNIT_STAT_ROOT); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (phase == 0) - { - phase = 1; - check = 0; - DoScriptText(SAY_INTRO, me); - } - } - - void JustSummoned(Creature *summoned) - { - if (!summoned) return; - Unit *victim = me->getVictim(); - if (summoned->GetEntry() == ENTRY_NAZAN) - { - CAST_AI(boss_nazanAI, summoned->AI())->VazrudenGUID = VazrudenGUID; - summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - summoned->SetSpeed(MOVE_FLIGHT, 2.5); - if (victim) - AttackStartNoMove(victim); - } - else if (victim) - summoned->AI()->AttackStart(victim); - } - - void SentryDownBy(Unit* killer) - { - if (sentryDown) - { - AttackStartNoMove(killer); - sentryDown = false; - } - else - sentryDown = true; - } - - void UpdateAI(const uint32 diff) - { - switch(phase) - { - case 0: // circle around the platform - return; - break; - case 1: // go to the middle and begin the fight - if (check <= diff) - { - if (!me->IsWithinDist3d(VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],5)) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2]); - check = 1000; - } - else - { - SummonAdds(); - phase = 2; - return; - } - } else check -= diff; - break; - default: // adds do the job now - if (check <= diff) - { - Creature *Nazan = Unit::GetCreature(*me, NazanGUID); - Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); - if (Nazan && Nazan->isAlive() || Vazruden && Vazruden->isAlive()) - { - if (Nazan && Nazan->getVictim() || Vazruden && Vazruden->getVictim()) - return; - else - { - UnsummonAdds(); - EnterEvadeMode(); - return; - } - } - else - { - me->SummonGameObject(ENTRY_REINFORCED_FEL_IRON_CHEST,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,0,0,0,0,0); - me->SetLootRecipient(NULL); // don't think this is necessary.. - me->Kill(me); - } - check = 2000; - } else check -= diff; - break; - } - } -}; - -struct mob_hellfire_sentryAI : public ScriptedAI -{ - mob_hellfire_sentryAI(Creature *c) : ScriptedAI(c) {} - - uint32 KidneyShot_Timer; - - void Reset() - { - KidneyShot_Timer = urand(3000,7000); - } - - void EnterCombat(Unit* /*who*/) {} - - void JustDied(Unit* who) - { - if (Creature *herald = me->FindNearestCreature(ENTRY_VAZRUDEN_HERALD,150)) - CAST_AI(boss_vazruden_the_heraldAI, herald->AI())->SentryDownBy(who); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (KidneyShot_Timer <= diff) - { - if (Unit *victim = me->getVictim()) - DoCast(victim, SPELL_KIDNEY_SHOT); - KidneyShot_Timer = 20000; - } else KidneyShot_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vazruden_the_herald(Creature* pCreature) -{ - return new boss_vazruden_the_heraldAI (pCreature); -} - -CreatureAI* GetAI_boss_vazruden(Creature* pCreature) -{ - return new boss_vazrudenAI (pCreature); -} - -CreatureAI* GetAI_boss_nazan(Creature* pCreature) -{ - return new boss_nazanAI (pCreature); -} - -CreatureAI* GetAI_mob_hellfire_sentry(Creature* pCreature) -{ - return new mob_hellfire_sentryAI (pCreature); -} - -void AddSC_boss_vazruden_the_herald() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vazruden_the_herald"; - newscript->GetAI = &GetAI_boss_vazruden_the_herald; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_vazruden"; - newscript->GetAI = &GetAI_boss_vazruden; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_nazan"; - newscript->GetAI = &GetAI_boss_nazan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_hellfire_sentry"; - newscript->GetAI = &GetAI_mob_hellfire_sentry; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp deleted file mode 100644 index f0e813d3890..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Watchkeeper_Gargolmar -SD%Complete: 80 -SDComment: Missing adds to heal him. Surge should be used on pTarget furthest away, not random. -SDCategory: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_TAUNT -1543000 -#define SAY_HEAL -1543001 -#define SAY_SURGE -1543002 -#define SAY_AGGRO_1 -1543003 -#define SAY_AGGRO_2 -1543004 -#define SAY_AGGRO_3 -1543005 -#define SAY_KILL_1 -1543006 -#define SAY_KILL_2 -1543007 -#define SAY_DIE -1543008 - -#define SPELL_MORTAL_WOUND 30641 -#define H_SPELL_MORTAL_WOUND 36814 -#define SPELL_SURGE 34645 -#define SPELL_RETALIATION 22857 - -struct boss_watchkeeper_gargolmarAI : public ScriptedAI -{ - boss_watchkeeper_gargolmarAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Surge_Timer; - uint32 MortalWound_Timer; - uint32 Retaliation_Timer; - - bool HasTaunted; - bool YelledForHeal; - - void Reset() - { - Surge_Timer = 5000; - MortalWound_Timer = 4000; - Retaliation_Timer = 0; - - HasTaunted = false; - YelledForHeal = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void MoveInLineOfSight(Unit* who) - { - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (!HasTaunted && me->IsWithinDistInMap(who, 60.0f)) - { - DoScriptText(SAY_TAUNT, me); - HasTaunted = true; - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (MortalWound_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - MortalWound_Timer = 5000+rand()%8000; - } else MortalWound_Timer -= diff; - - if (Surge_Timer <= diff) - { - DoScriptText(SAY_SURGE, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SURGE); - - Surge_Timer = 5000+rand()%8000; - } else Surge_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) - { - if (Retaliation_Timer <= diff) - { - DoCast(me, SPELL_RETALIATION); - Retaliation_Timer = 30000; - } else Retaliation_Timer -= diff; - } - - if (!YelledForHeal) - { - if ((me->GetHealth()*100) / me->GetMaxHealth() < 40) - { - DoScriptText(SAY_HEAL, me); - YelledForHeal = true; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_watchkeeper_gargolmarAI(Creature* pCreature) -{ - return new boss_watchkeeper_gargolmarAI (pCreature); -} - -void AddSC_boss_watchkeeper_gargolmar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_watchkeeper_gargolmar"; - newscript->GetAI = &GetAI_boss_watchkeeper_gargolmarAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h deleted file mode 100644 index 599aa237774..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_RAMPARTS_H -#define DEF_RAMPARTS_H - -#define MAX_ENCOUNTER 2 - -enum eTypes -{ - TYPE_VAZRUDEN = 1, - TYPE_NAZAN = 2 -}; - -#endif diff --git a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp b/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp deleted file mode 100644 index 29c58675e9c..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Hellfire_Ramparts -SD%Complete: 50 -SDComment: -SDCategory: Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" -#include "hellfire_ramparts.h" - -struct instance_ramparts : public ScriptedInstance -{ - instance_ramparts(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint64 m_uiChestNGUID; - uint64 m_uiChestHGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiChestNGUID = 0; - m_uiChestHGUID = 0; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 185168: m_uiChestNGUID = pGo->GetGUID(); break; - case 185169: m_uiChestHGUID = pGo->GetGUID(); break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - debug_log("TSCR: Instance Ramparts: SetData received for type %u with data %u",uiType,uiData); - - switch(uiType) - { - case TYPE_VAZRUDEN: - if (uiData == DONE && m_auiEncounter[1] == DONE) - DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); - m_auiEncounter[0] = uiData; - break; - case TYPE_NAZAN: - if (uiData == DONE && m_auiEncounter[0] == DONE) - DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); - m_auiEncounter[1] = uiData; - break; - } - } -}; - -InstanceData* GetInstanceData_instance_ramparts(Map* pMap) -{ - return new instance_ramparts(pMap); -} - -void AddSC_instance_ramparts() -{ - Script* pNewScript; - pNewScript = new Script; - pNewScript->Name = "instance_ramparts"; - pNewScript->GetInstanceData = &GetInstanceData_instance_ramparts; - pNewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp deleted file mode 100644 index 5fb381f4065..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/* Copyright(C) 2006 - 2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -*(at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Magtheridon -SD%Complete: 60 -SDComment: In Development -SDCategory: Hellfire Citadel, Magtheridon's lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "magtheridons_lair.h" - -struct Yell -{ - int32 id; -}; - -static Yell RandomTaunt[]= -{ - {-1544000}, - {-1544001}, - {-1544002}, - {-1544003}, - {-1544004}, - {-1544005}, -}; - -#define SAY_FREED -1544006 -#define SAY_AGGRO -1544007 -#define SAY_BANISH -1544008 -#define SAY_CHAMBER_DESTROY -1544009 -#define SAY_PLAYER_KILLED -1544010 -#define SAY_DEATH -1544011 - -#define EMOTE_BERSERK -1544012 -#define EMOTE_BLASTNOVA -1544013 -#define EMOTE_BEGIN -1544014 - -#define MOB_MAGTHERIDON 17257 -#define MOB_ROOM 17516 -#define MOB_CHANNELLER 17256 -#define MOB_ABYSSAL 17454 - -#define SPELL_BLASTNOVA 30616 -#define SPELL_CLEAVE 30619 -#define SPELL_QUAKE_TRIGGER 30657 // must be cast with 30561 as the proc spell -#define SPELL_QUAKE_KNOCKBACK 30571 -#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 -#define SPELL_BLAZE_TRAP 30542 -#define SPELL_DEBRIS_KNOCKDOWN 36449 -#define SPELL_DEBRIS_VISUAL 30632 -#define SPELL_DEBRIS_DAMAGE 30631 // core bug, does not support target 8 -#define SPELL_CAMERA_SHAKE 36455 -#define SPELL_BERSERK 27680 - -#define SPELL_SHADOW_CAGE 30168 -#define SPELL_SHADOW_GRASP 30410 -#define SPELL_SHADOW_GRASP_VISUAL 30166 -#define SPELL_MIND_EXHAUSTION 44032 //Casted by the cubes when channeling ends - -#define SPELL_SHADOW_CAGE_C 30205 -#define SPELL_SHADOW_GRASP_C 30207 - -#define SPELL_SHADOW_BOLT_VOLLEY 30510 -#define SPELL_DARK_MENDING 30528 -#define SPELL_FEAR 30530 //39176 -#define SPELL_BURNING_ABYSSAL 30511 -#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 - -#define SPELL_FIRE_BLAST 37110 - -// count of clickers needed to interrupt blast nova -#define CLICKERS_COUNT 5 - -typedef std::map CubeMap; - -struct mob_abyssalAI : public ScriptedAI -{ - mob_abyssalAI(Creature *c) : ScriptedAI(c) - { - trigger = 0; - Despawn_Timer = 60000; - } - - uint32 FireBlast_Timer; - uint32 Despawn_Timer; - uint32 trigger; - - void Reset() - { - FireBlast_Timer = 6000; - } - - void SpellHit(Unit*, const SpellEntry *spell) - { - if (trigger == 2 && spell->Id == SPELL_BLAZE_TARGET) - { - DoCast(me, SPELL_BLAZE_TRAP, true); - me->SetVisibility(VISIBILITY_OFF); - Despawn_Timer = 130000; - } - } - - void SetTrigger(uint32 _trigger) - { - trigger = _trigger; - me->SetDisplayId(11686); - if (trigger == 1) //debris - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_DEBRIS_VISUAL, true); - FireBlast_Timer = 5000; - Despawn_Timer = 10000; - } - } - - void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} - void AttackStart(Unit *who) {if (!trigger) ScriptedAI::AttackStart(who);} - void MoveInLineOfSight(Unit *who) {if (!trigger) ScriptedAI::MoveInLineOfSight(who);} - - void UpdateAI(const uint32 diff) - { - if (trigger) - { - if (trigger == 1) - { - if (FireBlast_Timer <= diff) - { - DoCast(me, SPELL_DEBRIS_DAMAGE, true); - trigger = 3; - } else FireBlast_Timer -= diff; - } - return; - } - - if (Despawn_Timer <= diff) - { - me->ForcedDespawn(); - } else Despawn_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (FireBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRE_BLAST); - FireBlast_Timer = 5000+rand()%10000; - } else FireBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_magtheridonAI : public ScriptedAI -{ - boss_magtheridonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - - // target 7, random target with certain entry spell, need core fix - SpellEntry *TempSpell; - TempSpell = GET_SPELL(SPELL_BLAZE_TARGET); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 6) - { - TempSpell->EffectImplicitTargetA[0] = 6; - TempSpell->EffectImplicitTargetB[0] = 0; - } - TempSpell = GET_SPELL(SPELL_QUAKE_TRIGGER); - if (TempSpell && TempSpell->EffectTriggerSpell[0] != SPELL_QUAKE_KNOCKBACK) - { - TempSpell->EffectTriggerSpell[0] = SPELL_QUAKE_KNOCKBACK; - } - } - - CubeMap Cube; - - ScriptedInstance* pInstance; - - uint32 Berserk_Timer; - uint32 Quake_Timer; - uint32 Cleave_Timer; - uint32 BlastNova_Timer; - uint32 Blaze_Timer; - uint32 Debris_Timer; - uint32 RandChat_Timer; - - bool Phase3; - bool NeedCheckCube; - - void Reset() - { - Berserk_Timer = 1320000; - Quake_Timer = 40000; - Debris_Timer = 10000; - Blaze_Timer = 10000+rand()%20000; - BlastNova_Timer = 60000; - Cleave_Timer = 15000; - RandChat_Timer = 90000; - - Phase3 = false; - NeedCheckCube = false; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->addUnitState(UNIT_STAT_STUNNED); - DoCast(me, SPELL_SHADOW_CAGE_C, true); - } - - void JustReachedHome() - { - if (pInstance) - { - pInstance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED); - pInstance->SetData(DATA_COLLAPSE, false); - } - } - - void SetClicker(uint64 cubeGUID, uint64 clickerGUID) - { - // to avoid multiclicks from 1 cube - if (uint64 guid = Cube[cubeGUID]) - DebuffClicker(Unit::GetUnit(*me, guid)); - Cube[cubeGUID] = clickerGUID; - NeedCheckCube = true; - } - - //function to interrupt channeling and debuff clicker with mind exh(used if second person clicks with same cube or after dispeling/ending shadow grasp DoT) - void DebuffClicker(Unit *clicker) - { - if (!clicker || !clicker->isAlive()) - return; - - clicker->RemoveAurasDueToSpell(SPELL_SHADOW_GRASP); // cannot interrupt triggered spells - clicker->InterruptNonMeleeSpells(false); - clicker->CastSpell(clicker, SPELL_MIND_EXHAUSTION, true); - } - - void NeedCheckCubeStatus() - { - uint32 ClickerNum = 0; - // now checking if every clicker has debuff from manticron(it is dispelable atm rev 6110 : S) - // if not - apply mind exhaustion and delete from clicker's list - for (CubeMap::iterator i = Cube.begin(); i != Cube.end(); ++i) - { - Unit *clicker = Unit::GetUnit(*me, (*i).second); - if (!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP)) - { - DebuffClicker(clicker); - (*i).second = 0; - } else ++ClickerNum; - } - - // if 5 clickers from other cubes apply shadow cage - if (ClickerNum >= CLICKERS_COUNT && !me->HasAura(SPELL_SHADOW_CAGE)) - { - DoScriptText(SAY_BANISH, me); - DoCast(me, SPELL_SHADOW_CAGE, true); - } - else if (ClickerNum < CLICKERS_COUNT && me->HasAura(SPELL_SHADOW_CAGE)) - me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); - - if (!ClickerNum) NeedCheckCube = false; - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_PLAYER_KILLED, me); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_MAGTHERIDON_EVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void AttackStart(Unit *who) - { - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS); - DoZoneInCombat(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); - - DoScriptText(SAY_FREED, me); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - { - if (RandChat_Timer <= diff) - { - DoScriptText(RandomTaunt[rand()%6].id, me); - RandChat_Timer = 90000; - } else RandChat_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - if (NeedCheckCube) NeedCheckCubeStatus(); - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - DoScriptText(EMOTE_BERSERK, me); - Berserk_Timer = 60000; - } else Berserk_Timer -= diff; - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 10000; - } else Cleave_Timer -= diff; - - if (BlastNova_Timer <= diff) - { - // to avoid earthquake interruption - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - { - DoScriptText(EMOTE_BLASTNOVA, me); - DoCast(me, SPELL_BLASTNOVA); - BlastNova_Timer = 60000; - } - } else BlastNova_Timer -= diff; - - if (Quake_Timer <= diff) - { - // to avoid blastnova interruption - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_QUAKE_TRIGGER, true); - Quake_Timer = 50000; - } - } else Quake_Timer -= diff; - - if (Blaze_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - pTarget->GetPosition(x, y, z); - Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (summon) - { - CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(2); - DoCast(summon, SPELL_BLAZE_TARGET, true); - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - } - Blaze_Timer = 20000 + rand()%20000; - } else Blaze_Timer -= diff; - - if (!Phase3 && me->GetHealth()*10 < me->GetMaxHealth()*3 - && !me->IsNonMeleeSpellCasted(false) // blast nova - && !me->hasUnitState(UNIT_STAT_STUNNED)) // shadow cage and earthquake - { - Phase3 = true; - DoScriptText(SAY_CHAMBER_DESTROY, me); - DoCast(me, SPELL_CAMERA_SHAKE, true); - DoCast(me, SPELL_DEBRIS_KNOCKDOWN, true); - - if (pInstance) - pInstance->SetData(DATA_COLLAPSE, true); - } - - if (Phase3) - { - if (Debris_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - pTarget->GetPosition(x, y, z); - Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (summon) CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(1); - } - Debris_Timer = 10000; - } else Debris_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_hellfire_channelerAI : public ScriptedAI -{ - mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c) - { - pInstance =me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ShadowBoltVolley_Timer; - uint32 DarkMending_Timer; - uint32 Fear_Timer; - uint32 Infernal_Timer; - - uint32 Check_Timer; - - void Reset() - { - ShadowBoltVolley_Timer = 8000 + rand()%2000; - DarkMending_Timer = 10000; - Fear_Timer = 15000 + rand()%5000; - Infernal_Timer = 10000 + rand()%40000; - - Check_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS); - - me->InterruptNonMeleeSpells(false); - DoZoneInCombat(); - } - - void JustReachedHome() - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED); - - DoCast(me, SPELL_SHADOW_GRASP_C, false); - } - - void JustSummoned(Creature *summon) - { - summon->AI()->AttackStart(me->getVictim()); - } - - void DamageTaken(Unit*, uint32 &damage) - { - if (damage >= me->GetHealth()) - DoCast(me, SPELL_SOUL_TRANSFER, true); - } - - void JustDied(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); - ShadowBoltVolley_Timer = 10000 + rand()%10000; - } else ShadowBoltVolley_Timer -= diff; - - if (DarkMending_Timer <= diff) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) - DoCast(me, SPELL_DARK_MENDING); - DarkMending_Timer = 10000 +(rand() % 10000); - } else DarkMending_Timer -= diff; - - if (Fear_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - DoCast(pTarget, SPELL_FEAR); - Fear_Timer = 25000 + rand()%15000; - } else Fear_Timer -= diff; - - if (Infernal_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BURNING_ABYSSAL, true); - Infernal_Timer = 30000 + rand()%10000; - } else Infernal_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Manticron Cube -bool GOHello_go_Manticron_Cube(Player* pPlayer, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - if (!pInstance) - return true; - if (pInstance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) return true; - Creature *Magtheridon =Unit::GetCreature(*pGo, pInstance->GetData64(DATA_MAGTHERIDON)); - if (!Magtheridon || !Magtheridon->isAlive()) return true; - - // if exhausted or already channeling return - if (pPlayer->HasAura(SPELL_MIND_EXHAUSTION) || pPlayer->HasAura(SPELL_SHADOW_GRASP)) - return true; - - pPlayer->InterruptNonMeleeSpells(false); - pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP, true); - pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP_VISUAL, false); - CAST_AI(boss_magtheridonAI, Magtheridon->AI())->SetClicker(pGo->GetGUID(), pPlayer->GetGUID()); - return true; -} - -CreatureAI* GetAI_boss_magtheridon(Creature* pCreature) -{ - return new boss_magtheridonAI(pCreature); -} - -CreatureAI* GetAI_mob_hellfire_channeler(Creature* pCreature) -{ - return new mob_hellfire_channelerAI(pCreature); -} - -CreatureAI* GetAI_mob_abyssalAI(Creature* pCreature) -{ - return new mob_abyssalAI(pCreature); -} - -void AddSC_boss_magtheridon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magtheridon"; - newscript->GetAI = &GetAI_boss_magtheridon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_hellfire_channeler"; - newscript->GetAI = &GetAI_mob_hellfire_channeler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_manticron_cube"; - newscript->pGOHello = &GOHello_go_Manticron_Cube; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_abyssal"; - newscript->GetAI = &GetAI_mob_abyssalAI; - newscript->RegisterSelf(); - -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp deleted file mode 100644 index d5b459a1fa1..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Magtheridons_Lair -SD%Complete: 100 -SDComment: -SDCategory: Hellfire Citadel, Magtheridon's lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "magtheridons_lair.h" - -#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 -#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 - -#define CHAMBER_CENTER_X -15.14 -#define CHAMBER_CENTER_Y 1.8 -#define CHAMBER_CENTER_Z -0.4 - -#define MAX_ENCOUNTER 2 - -#define EMOTE_BONDS_WEAKEN "'s bonds begin to weaken!" - -struct instance_magtheridons_lair : public ScriptedInstance -{ - instance_magtheridons_lair(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - } - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 MagtheridonGUID; - std::set ChannelerGUID; - uint64 DoorGUID; - std::set ColumnGUID; - - uint32 CageTimer; - uint32 RespawnTimer; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - MagtheridonGUID = 0; - ChannelerGUID.clear(); - DoorGUID = 0; - ColumnGUID.clear(); - - CageTimer = 0; - RespawnTimer = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17257: - MagtheridonGUID = pCreature->GetGUID(); - break; - case 17256: - ChannelerGUID.insert(pCreature->GetGUID()); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 181713: - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 0); - break; - case 183847: - DoorGUID = pGo->GetGUID(); - break; - case 184653: // hall - case 184634: // six columns - case 184635: - case 184636: - case 184637: - case 184638: - case 184639: - ColumnGUID.insert(pGo->GetGUID()); - break; - } - } - - uint64 GetData64(uint32 type) - { - switch(type) - { - case DATA_MAGTHERIDON: - return MagtheridonGUID; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MAGTHERIDON_EVENT: - m_auiEncounter[0] = data; - if (data == NOT_STARTED) - RespawnTimer = 10000; - if (data != IN_PROGRESS) - HandleGameObject(DoorGUID, true); - break; - case DATA_CHANNELER_EVENT: - switch(data) - { - case NOT_STARTED: // Reset all channelers once one is reset. - if (m_auiEncounter[1] != NOT_STARTED) - { - m_auiEncounter[1] = NOT_STARTED; - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - if (Creature *Channeler = instance->GetCreature(*i)) - { - if (Channeler->isAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } - } - CageTimer = 0; - HandleGameObject(DoorGUID, true); - } - break; - case IN_PROGRESS: // Event start. - if (m_auiEncounter[1] != IN_PROGRESS) - { - m_auiEncounter[1] = IN_PROGRESS; - // Let all five channelers aggro. - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - Creature *Channeler = instance->GetCreature(*i); - if (Channeler && Channeler->isAlive()) - Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); - } - // Release Magtheridon after two minutes. - Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); - if (Magtheridon && Magtheridon->isAlive()) - { - Magtheridon->MonsterTextEmote(EMOTE_BONDS_WEAKEN, 0); - CageTimer = 120000; - } - HandleGameObject(DoorGUID, false); - } - break; - case DONE: // Add buff and check if all channelers are dead. - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - Creature *Channeler = instance->GetCreature(*i); - if (Channeler && Channeler->isAlive()) - { - //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); - data = IN_PROGRESS; - break; - } - } - break; - } - m_auiEncounter[1] = data; - break; - case DATA_COLLAPSE: - // true - collapse / false - reset - for (std::set::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) - DoUseDoorOrButton(*i); - break; - default: - break; - } - } - - uint32 GetData(uint32 type) - { - if (type == DATA_MAGTHERIDON_EVENT) - return m_auiEncounter[0]; - return 0; - } - - void Update(uint32 diff) - { - if (CageTimer) - { - if (CageTimer <= diff) - { - Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); - if (Magtheridon && Magtheridon->isAlive()) - { - Magtheridon->clearUnitState(UNIT_STAT_STUNNED); - Magtheridon->AI()->AttackStart(Magtheridon->SelectNearestTarget(999)); - } - CageTimer = 0; - } else CageTimer -= diff; - } - - if (RespawnTimer) - { - if (RespawnTimer <= diff) - { - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - if (Creature *Channeler = instance->GetCreature(*i)) - { - if (Channeler->isAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } - } - RespawnTimer = 0; - } else RespawnTimer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_magtheridons_lair(Map* pMap) -{ - return new instance_magtheridons_lair(pMap); -} - -void AddSC_instance_magtheridons_lair() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_magtheridons_lair"; - newscript->GetInstanceData = &GetInstanceData_instance_magtheridons_lair; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h b/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h deleted file mode 100644 index 1b3e525fc54..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_MAGTHERIDONS_LAIR_H -#define DEF_MAGTHERIDONS_LAIR_H - -#define DATA_MAGTHERIDON_EVENT 1 -#define DATA_MAGTHERIDON 3 -#define DATA_CHANNELER_EVENT 2 -#define DATA_COLLAPSE 6 -#define DATA_CHANNELER 9 -#endif - diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp deleted file mode 100644 index e3ded52edc9..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grand_Warlock_Nethekurse -SD%Complete: 75 -SDComment: encounter not fully completed. missing part where boss kill minions. -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -boss_grand_warlock_nethekurse -mob_fel_orc_convert -mob_lesser_shadow_fissure -EndContentData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -struct Say -{ - int32 id; -}; - -static Say PeonAttacked[]= -{ - {-1540001}, - {-1540002}, - {-1540003}, - {-1540004}, -}; -static Say PeonDies[]= -{ - {-1540005}, - {-1540006}, - {-1540007}, - {-1540008}, -}; - -#define SAY_INTRO -1540000 -#define SAY_TAUNT_1 -1540009 -#define SAY_TAUNT_2 -1540010 -#define SAY_TAUNT_3 -1540011 -#define SAY_AGGRO_1 -1540012 -#define SAY_AGGRO_2 -1540013 -#define SAY_AGGRO_3 -1540014 -#define SAY_SLAY_1 -1540015 -#define SAY_SLAY_2 -1540016 -#define SAY_DIE -1540017 - -#define SPELL_DEATH_COIL 30500 -#define SPELL_DARK_SPIN 30502 // core bug spell attack caster :D -#define SPELL_SHADOW_FISSURE 30496 // Summon the ShadowFissure NPC - -#define SPELL_SHADOW_CLEAVE 30495 -#define H_SPELL_SHADOW_SLAM 35953 - -#define SPELL_HEMORRHAGE 30478 - -#define SPELL_CONSUMPTION 30497 -#define SPELL_TEMPORARY_VISUAL 39312 // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should - -struct boss_grand_warlock_nethekurseAI : public ScriptedAI -{ - boss_grand_warlock_nethekurseAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool IntroOnce; - bool IsIntroEvent; - bool IsMainEvent; - bool SpinOnce; - //bool HasTaunted; - bool Phase; - - uint32 PeonEngagedCount; - uint32 PeonKilledCount; - - uint32 IntroEvent_Timer; - uint32 DeathCoil_Timer; - uint32 ShadowFissure_Timer; - uint32 Cleave_Timer; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - IsIntroEvent = false; - IntroOnce = false; - IsMainEvent = false; - //HasTaunted = false; - SpinOnce = false; - Phase = false; - - PeonEngagedCount = 0; - PeonKilledCount = 0; - - IntroEvent_Timer = 90000; //how long before getting bored and kills his minions? - DeathCoil_Timer = 20000; - ShadowFissure_Timer = 8000; - Cleave_Timer = 5000; - } - - void DoYellForPeonAggro() - { - if (PeonEngagedCount >= 4) - return; - - DoScriptText(PeonAttacked[PeonEngagedCount].id, me); - ++PeonEngagedCount; - } - - void DoYellForPeonDeath() - { - if (PeonKilledCount >= 4) - return; - - DoScriptText(PeonDies[PeonKilledCount].id, me); - ++PeonKilledCount; - - if (PeonKilledCount == 4) - { - IsIntroEvent = false; - IsMainEvent = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - - void DoTauntPeons() - { - DoScriptText(RAND(SAY_TAUNT_1,SAY_TAUNT_2,SAY_TAUNT_3), me); - - //TODO: kill the peons first - IsIntroEvent = false; - PeonEngagedCount = 4; - PeonKilledCount = 4; - IsMainEvent = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void AttackStart(Unit* who) - { - if (IsIntroEvent || !IsMainEvent) - return; - - if (me->Attack(who, true)) - { - if (Phase) - DoStartNoMovement(who); - else - DoStartMovement(who); - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!IntroOnce && me->IsWithinDistInMap(who, 50.0f)) - { - if (who->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(SAY_INTRO, me); - IntroOnce = true; - IsIntroEvent = true; - - if (pInstance) - pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); - } - - if (IsIntroEvent || !IsMainEvent) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustSummoned(Creature *summoned) - { - summoned->setFaction(16); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - //triggered spell of consumption does not properly show it's SpellVisual, wrong spellid? - summoned->CastSpell(summoned,SPELL_TEMPORARY_VISUAL,true); - summoned->CastSpell(summoned,SPELL_CONSUMPTION,false,0,0,me->GetGUID()); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_NETHEKURSE,DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_NETHEKURSE_DOOR), true); - } - - void UpdateAI(const uint32 diff) - { - if (IsIntroEvent) - { - if (!pInstance) - return; - - if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) - { - if (IntroEvent_Timer <= diff) - DoTauntPeons(); - else - IntroEvent_Timer -= diff; - } - } - - if (!UpdateVictim()) - return; - - if (!IsMainEvent) - return; - - if (Phase) - { - if (!SpinOnce) - { - DoCast(me->getVictim(), SPELL_DARK_SPIN); - SpinOnce = true; - } - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_CLEAVE); - Cleave_Timer = 6000+rand()%2500; - } else Cleave_Timer -= diff; - } - else - { - if (ShadowFissure_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_FISSURE); - ShadowFissure_Timer = urand(7500,15000); - } else ShadowFissure_Timer -= diff; - - if (DeathCoil_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_DEATH_COIL); - DeathCoil_Timer = urand(15000,20000); - } else DeathCoil_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) - Phase = true; - - DoMeleeAttackIfReady(); - } - } -}; - -struct mob_fel_orc_convertAI : public ScriptedAI -{ - mob_fel_orc_convertAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 Hemorrhage_Timer; - - void Reset() - { - me->SetNoCallAssistance(true); //we don't want any assistance (WE R HEROZ!) - Hemorrhage_Timer = 3000; - } - - void MoveInLineOfSight(Unit * /*who*/) - { - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - { - if (pInstance->GetData64(DATA_NETHEKURSE)) - { - Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE)); - if (pKurse && me->IsWithinDist(pKurse, 45.0f)) - { - CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonAggro(); - - if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) - return; - else - pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); - } - } - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - if (pInstance->GetData(TYPE_NETHEKURSE) != IN_PROGRESS) - return; - if (pInstance->GetData64(DATA_NETHEKURSE)) - if (Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE))) - CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonDeath(); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Hemorrhage_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HEMORRHAGE); - Hemorrhage_Timer = 15000; - } else Hemorrhage_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//NOTE: this Creature are also summoned by other spells, for different creatures -struct mob_lesser_shadow_fissureAI : public ScriptedAI -{ - mob_lesser_shadow_fissureAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - void MoveInLineOfSight(Unit * /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void EnterCombat(Unit* /*who*/) {} -}; - -CreatureAI* GetAI_boss_grand_warlock_nethekurse(Creature* pCreature) -{ - return new boss_grand_warlock_nethekurseAI (pCreature); -} - -CreatureAI* GetAI_mob_fel_orc_convert(Creature* pCreature) -{ - return new mob_fel_orc_convertAI (pCreature); -} - -CreatureAI* GetAI_mob_lesser_shadow_fissure(Creature* pCreature) -{ - return new mob_lesser_shadow_fissureAI (pCreature); -} - -void AddSC_boss_grand_warlock_nethekurse() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_grand_warlock_nethekurse"; - newscript->GetAI = &GetAI_boss_grand_warlock_nethekurse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fel_orc_convert"; - newscript->GetAI = &GetAI_mob_fel_orc_convert; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lesser_shadow_fissure"; - newscript->GetAI = &GetAI_mob_lesser_shadow_fissure; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp deleted file mode 100644 index 6fa1c9efe33..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warbringer_Omrogg -SD%Complete: 85 -SDComment: Heroic enabled. Spell timing may need additional tweaks -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -mob_omrogg_heads -boss_warbringer_omrogg -EndContentData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -enum eEnums -{ - YELL_DIE_L = -1540039, - YELL_DIE_R = -1540040, - EMOTE_ENRAGE = -1540041, - - SPELL_BLAST_WAVE = 30600, - SPELL_FEAR = 30584, - SPELL_THUNDERCLAP = 30633, - - SPELL_BURNING_MAUL = 30598, - H_SPELL_BURNING_MAUL = 36056, - - NPC_LEFT_HEAD = 19523, - NPC_RIGHT_HEAD = 19524 -}; - -struct Yell -{ - int32 id; - uint32 creature; -}; - -static Yell GoCombat[]= -{ - {-1540018, NPC_LEFT_HEAD}, - {-1540019, NPC_LEFT_HEAD}, - {-1540020, NPC_LEFT_HEAD}, -}; -static Yell GoCombatDelay[]= -{ - {-1540021, NPC_RIGHT_HEAD}, - {-1540022, NPC_RIGHT_HEAD}, - {-1540023, NPC_RIGHT_HEAD}, -}; - -static Yell Threat[]= -{ - {-1540024, NPC_LEFT_HEAD}, - {-1540025, NPC_RIGHT_HEAD}, - {-1540026, NPC_LEFT_HEAD}, - {-1540027, NPC_LEFT_HEAD}, -}; -static Yell ThreatDelay1[]= -{ - {-1540028, NPC_RIGHT_HEAD}, - {-1540029, NPC_LEFT_HEAD}, - {-1540030, NPC_RIGHT_HEAD}, - {-1540031, NPC_RIGHT_HEAD}, -}; -static Yell ThreatDelay2[]= -{ - {-1540032, NPC_LEFT_HEAD}, - {-1540033, NPC_RIGHT_HEAD}, - {-1540034, NPC_LEFT_HEAD}, - {-1540035, NPC_LEFT_HEAD}, -}; - -static Yell Killing[]= -{ - {-1540036, NPC_LEFT_HEAD}, - {-1540037, NPC_RIGHT_HEAD}, -}; -static Yell KillingDelay[]= -{ - {-1540038, NPC_RIGHT_HEAD}, - {-1000000, NPC_LEFT_HEAD}, -}; - -struct mob_omrogg_headsAI : public ScriptedAI -{ - mob_omrogg_headsAI(Creature *c) : ScriptedAI(c) {} - - bool DeathYell; - uint32 Death_Timer; - - void Reset() - { - Death_Timer = 4000; - DeathYell = false; - } - void EnterCombat(Unit* /*who*/) {} - - void DoDeathYell() - { - DeathYell = true; - } - - void UpdateAI(const uint32 diff) - { - if (!DeathYell) - return; - - if (Death_Timer <= diff) - { - DoScriptText(YELL_DIE_R, me); - Death_Timer = false; - me->setDeathState(JUST_DIED); - } else Death_Timer -= diff; - } -}; - -struct boss_warbringer_omroggAI : public ScriptedAI -{ - boss_warbringer_omroggAI(Creature *c) : ScriptedAI(c) - { - LeftHeadGUID = 0; - RightHeadGUID = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 LeftHeadGUID; - uint64 RightHeadGUID; - int iaggro; - int ithreat; - int ikilling; - - bool AggroYell; - bool ThreatYell; - bool ThreatYell2; - bool KillingYell; - - uint32 Delay_Timer; - uint32 BlastWave_Timer; - uint32 BlastCount; - uint32 Fear_Timer; - uint32 BurningMaul_Timer; - uint32 ThunderClap_Timer; - uint32 ResetThreat_Timer; - - void Reset() - { - if (Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) - { - pLeftHead->setDeathState(JUST_DIED); - LeftHeadGUID = 0; - } - - if (Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID)) - { - pRightHead->setDeathState(JUST_DIED); - RightHeadGUID = 0; - } - - AggroYell = false; - ThreatYell = false; - ThreatYell2 = false; - KillingYell = false; - - Delay_Timer = 4000; - BlastWave_Timer = 0; - BlastCount = 0; - Fear_Timer = 8000; - BurningMaul_Timer = 25000; - ThunderClap_Timer = 15000; - ResetThreat_Timer = 30000; - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, NOT_STARTED); //End boss can use this later. O'mrogg must be defeated(DONE) or he will come to aid. - } - - void DoYellForThreat() - { - Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit *pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - ithreat = rand()%4; - - Unit *source = (pLeftHead->GetEntry() == Threat[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(Threat[ithreat].id, source); - - Delay_Timer = 3500; - ThreatYell = true; - } - - void EnterCombat(Unit * /*who*/) - { - me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); - me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); - - if (Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) - { - iaggro = rand()%3; - - DoScriptText(GoCombat[iaggro].id, pLeftHead); - - Delay_Timer = 3500; - AggroYell = true; - } - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, IN_PROGRESS); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == NPC_LEFT_HEAD) - LeftHeadGUID = summoned->GetGUID(); - - if (summoned->GetEntry() == NPC_RIGHT_HEAD) - RightHeadGUID = summoned->GetGUID(); - - //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->SetVisibility(VISIBILITY_OFF); - } - - void KilledUnit(Unit* /*victim*/) - { - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - ikilling = rand()%2; - - Unit *source = (pLeftHead->GetEntry() == Killing[ikilling].creature ? pLeftHead : pRightHead); - - switch(ikilling) - { - case 0: - DoScriptText(Killing[ikilling].id, source); - Delay_Timer = 3500; - KillingYell = true; - break; - case 1: - DoScriptText(Killing[ikilling].id, source); - KillingYell = false; - break; - } - } - - void JustDied(Unit* /*Killer*/) - { - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - DoScriptText(YELL_DIE_L, pLeftHead); - - CAST_AI(mob_omrogg_headsAI, CAST_CRE(pRightHead)->AI())->DoDeathYell(); - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (Delay_Timer <= diff) - { - Delay_Timer = 3500; - - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - if (AggroYell) - { - DoScriptText(GoCombatDelay[iaggro].id, pRightHead); - AggroYell = false; - } - - if (ThreatYell2) - { - Unit *source = (pLeftHead->GetEntry() == ThreatDelay2[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(ThreatDelay2[ithreat].id, source); - ThreatYell2 = false; - } - - if (ThreatYell) - { - Unit *source = (pLeftHead->GetEntry() == ThreatDelay1[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(ThreatDelay1[ithreat].id, source); - ThreatYell = false; - ThreatYell2 = true; - } - - if (KillingYell) - { - Unit *source = (pLeftHead->GetEntry() == KillingDelay[ikilling].creature ? pLeftHead : pRightHead); - - DoScriptText(KillingDelay[ikilling].id, source); - KillingYell = false; - } - } else Delay_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (BlastCount && BlastWave_Timer <= diff) - { - DoCast(me, SPELL_BLAST_WAVE); - BlastWave_Timer = 5000; - ++BlastCount; - - if (BlastCount == 3) - BlastCount = 0; - } else BlastWave_Timer -= diff; - - if (BurningMaul_Timer <= diff) - { - DoScriptText(EMOTE_ENRAGE, me); - DoCast(me, SPELL_BURNING_MAUL); - BurningMaul_Timer = 40000; - BlastWave_Timer = 16000; - BlastCount = 1; - } else BurningMaul_Timer -= diff; - - if (ResetThreat_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoYellForThreat(); - DoResetThreat(); - me->AddThreat(pTarget, 0.0f); - } - ResetThreat_Timer = 25000+rand()%15000; - } else ResetThreat_Timer -= diff; - - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 15000+rand()%20000; - } else Fear_Timer -= diff; - - if (ThunderClap_Timer <= diff) - { - DoCast(me, SPELL_THUNDERCLAP); - ThunderClap_Timer = 15000+rand()%15000; - } else ThunderClap_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_warbringer_omrogg(Creature* pCreature) -{ - return new boss_warbringer_omroggAI (pCreature); -} - -CreatureAI* GetAI_mob_omrogg_heads(Creature* pCreature) -{ - return new mob_omrogg_headsAI (pCreature); -} - -void AddSC_boss_warbringer_omrogg() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_warbringer_omrogg"; - newscript->GetAI = &GetAI_boss_warbringer_omrogg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_omrogg_heads"; - newscript->GetAI = &GetAI_mob_omrogg_heads; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp deleted file mode 100644 index b108077518a..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warchief_Kargath_Bladefist -SD%Complete: 90 -SDComment: -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -boss_warchief_kargath_bladefist -EndContentData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO1 -1540042 -#define SAY_AGGRO2 -1540043 -#define SAY_AGGRO3 -1540044 -#define SAY_SLAY1 -1540045 -#define SAY_SLAY2 -1540046 -#define SAY_DEATH -1540047 - -#define SPELL_BLADE_DANCE 30739 -#define H_SPELL_CHARGE 25821 - -#define TARGET_NUM 5 - -#define MOB_SHATTERED_ASSASSIN 17695 -#define MOB_HEARTHEN_GUARD 17621 -#define MOB_SHARPSHOOTER_GUARD 17622 -#define MOB_REAVER_GUARD 17623 - -float AssassEntrance[3] = {275.136,-84.29,2.3}; // y -8 -float AssassExit[3] = {184.233,-84.29,2.3}; // y -8 -float AddsEntrance[3] = {306.036,-84.29,1.93}; - -struct boss_warchief_kargath_bladefistAI : public ScriptedAI -{ - boss_warchief_kargath_bladefistAI(Creature *c) : ScriptedAI(c) - { - } - - std::vector adds; - std::vector assassins; - - uint32 Charge_timer; - uint32 Blade_Dance_Timer; - uint32 Summon_Assistant_Timer; - uint32 resetcheck_timer; - uint32 Wait_Timer; - - uint32 Assassins_Timer; - - uint32 summoned; - bool InBlade; - - uint32 target_num; - - void Reset() - { - removeAdds(); - - me->SetSpeed(MOVE_RUN,2); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - summoned = 2; - InBlade = false; - Wait_Timer = 0; - - Charge_timer = 0; - Blade_Dance_Timer = 45000; - Summon_Assistant_Timer = 30000; - Assassins_Timer = 5000; - resetcheck_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - } - - void JustSummoned(Creature *summoned) - { - switch(summoned->GetEntry()) - { - case MOB_HEARTHEN_GUARD: - case MOB_SHARPSHOOTER_GUARD: - case MOB_REAVER_GUARD: - summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0)); - adds.push_back(summoned->GetGUID()); - break; - case MOB_SHATTERED_ASSASSIN: - assassins.push_back(summoned->GetGUID()); - break; - } - } - - void KilledUnit(Unit* victim) - { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - removeAdds(); - } - - void MovementInform(uint32 type, uint32 id) - { - if (InBlade) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id != 1) - return; - - if (target_num > 0) // to prevent loops - { - Wait_Timer = 1; - DoCast(me, SPELL_BLADE_DANCE, true); - target_num--; - } - } - } - - void removeAdds() - { - for (std::vector::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) - { - Unit* temp = Unit::GetUnit((*me),*itr); - if (temp && temp->isAlive()) - { - (*temp).GetMotionMaster()->Clear(true); - me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - CAST_CRE(temp)->RemoveCorpse(); - } - } - adds.clear(); - - for (std::vector::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) - { - Unit* temp = Unit::GetUnit((*me),*itr); - if (temp && temp->isAlive()) - { - (*temp).GetMotionMaster()->Clear(true); - me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - CAST_CRE(temp)->RemoveCorpse(); - } - } - assassins.clear(); - } - void SpawnAssassin() - { - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]+8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]-8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]+8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]-8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Assassins_Timer) - if (Assassins_Timer <= diff) - { - SpawnAssassin(); - Assassins_Timer = 0; - } else Assassins_Timer -= diff; - - if (InBlade) - { - if (Wait_Timer) - if (Wait_Timer <= diff) - { - if (target_num <= 0) - { - // stop bladedance - InBlade = false; - me->SetSpeed(MOVE_RUN,2); - me->GetMotionMaster()->MoveChase(me->getVictim()); - Blade_Dance_Timer = 30000; - Wait_Timer = 0; - if (IsHeroic()) - Charge_timer = 5000; - } - else - { - //move in bladedance - float x,y,randx,randy; - randx = (rand()%40); - randy = (rand()%40); - x = 210+ randx ; - y = -60- randy ; - me->GetMotionMaster()->MovePoint(1,x,y,me->GetPositionZ()); - Wait_Timer = 0; - } - } else Wait_Timer -= diff; - } - else - { - if (Blade_Dance_Timer) - if (Blade_Dance_Timer <= diff) - { - target_num = TARGET_NUM; - Wait_Timer = 1; - InBlade = true; - Blade_Dance_Timer = 0; - me->SetSpeed(MOVE_RUN,4); - return; - } else Blade_Dance_Timer -= diff; - - if (Charge_timer) - if (Charge_timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), H_SPELL_CHARGE); - Charge_timer = 0; - } else Charge_timer -= diff; - - if (Summon_Assistant_Timer <= diff) - { - for (uint8 i = 0; i < summoned; ++i) - { - switch (urand(0,2)) - { - case 0: me->SummonCreature(MOB_HEARTHEN_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - case 1: me->SummonCreature(MOB_SHARPSHOOTER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - case 2: me->SummonCreature(MOB_REAVER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - } - } - if (urand(0,9) < 2) - ++summoned; - Summon_Assistant_Timer = urand(25000,35000); - } else Summon_Assistant_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - if (resetcheck_timer <= diff) - { - uint32 tempx,tempy; - tempx = uint32(me->GetPositionX()); - tempy = uint32(me->GetPositionY()); - if (tempx > 255 || tempx < 205) - { - EnterEvadeMode(); - return; - } - resetcheck_timer = 5000; - } else resetcheck_timer -= diff; - } -}; - -CreatureAI* GetAI_boss_warchief_kargath_bladefist(Creature* pCreature) -{ - return new boss_warchief_kargath_bladefistAI (pCreature); -} - -void AddSC_boss_warchief_kargath_bladefist() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_warchief_kargath_bladefist"; - newscript->GetAI = &GetAI_boss_warchief_kargath_bladefist; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp deleted file mode 100644 index c29df4d6411..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Shattered_Halls -SD%Complete: 50 -SDComment: currently missing info about door. instance not complete -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -#define MAX_ENCOUNTER 2 - -#define DOOR_NETHEKURSE 1 - -struct instance_shattered_halls : public ScriptedInstance -{ - instance_shattered_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint64 nethekurseGUID; - uint64 nethekurseDoorGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - nethekurseGUID = 0; - nethekurseDoorGUID = 0; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case DOOR_NETHEKURSE: nethekurseDoorGUID = pGo->GetGUID(); break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 16807: nethekurseGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_NETHEKURSE: - m_auiEncounter[0] = data; - break; - case TYPE_OMROGG: - m_auiEncounter[1] = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_NETHEKURSE: - return m_auiEncounter[0]; - case TYPE_OMROGG: - return m_auiEncounter[1]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_NETHEKURSE: - return nethekurseGUID; - case DATA_NETHEKURSE_DOOR: - return nethekurseDoorGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_shattered_halls(Map* pMap) -{ - return new instance_shattered_halls(pMap); -} - -void AddSC_instance_shattered_halls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_shattered_halls"; - newscript->GetInstanceData = &GetInstanceData_instance_shattered_halls; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h b/src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h deleted file mode 100644 index cbfa23ec4e0..00000000000 --- a/src/server/scripts/Outland/hellfire_citadel/shattered_halls/shattered_halls.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SHATTERED_H -#define DEF_SHATTERED_H - -#define TYPE_NETHEKURSE 1 -#define DATA_NETHEKURSE 2 -#define DATA_NETHEKURSE_DOOR 3 - -#define TYPE_OMROGG 4 -#endif - diff --git a/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp deleted file mode 100644 index 69dbc877d89..00000000000 --- a/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.cpp +++ /dev/null @@ -1,520 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Arcatraz -SD%Complete: 60 -SDComment: Warden Mellichar, event controller for Skyriss event. Millhouse Manastorm. TODO: make better combatAI for Millhouse. -SDCategory: Tempest Keep, The Arcatraz -EndScriptData */ - -/* ContentData -npc_millhouse_manastorm -npc_warden_mellichar -mob_zerekethvoidzone -EndContentData */ - -#include "ScriptedPch.h" -#include "arcatraz.h" - -/*##### -# npc_millhouse_manastorm -#####*/ - -#define SAY_INTRO_1 -1552010 -#define SAY_INTRO_2 -1552011 -#define SAY_WATER -1552012 -#define SAY_BUFFS -1552013 -#define SAY_DRINK -1552014 -#define SAY_READY -1552015 -#define SAY_KILL_1 -1552016 -#define SAY_KILL_2 -1552017 -#define SAY_PYRO -1552018 -#define SAY_ICEBLOCK -1552019 -#define SAY_LOWHP -1552020 -#define SAY_DEATH -1552021 -#define SAY_COMPLETE -1552022 - -#define SPELL_CONJURE_WATER 36879 -#define SPELL_ARCANE_INTELLECT 36880 -#define SPELL_ICE_ARMOR 36881 - -#define SPELL_ARCANE_MISSILES 33833 -#define SPELL_CONE_OF_COLD 12611 -#define SPELL_FIRE_BLAST 13341 -#define SPELL_FIREBALL 14034 -#define SPELL_FROSTBOLT 15497 -#define SPELL_PYROBLAST 33975 - -struct npc_millhouse_manastormAI : public ScriptedAI -{ - npc_millhouse_manastormAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 EventProgress_Timer; - uint32 Phase; - bool Init; - bool LowHp; - - uint32 Pyroblast_Timer; - uint32 Fireball_Timer; - - void Reset() - { - EventProgress_Timer = 2000; - LowHp = false; - Init = false; - Phase = 1; - - Pyroblast_Timer = 1000; - Fireball_Timer = 2500; - - if (pInstance) - { - if (pInstance->GetData(TYPE_WARDEN_2) == DONE) - Init = true; - - if (pInstance->GetData(TYPE_HARBINGERSKYRISS) == DONE) - { - DoScriptText(SAY_COMPLETE, me); - } - } - } - - void AttackStart(Unit* pWho) - { - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(pWho, 25.0f); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - /*for questId 10886 (heroic mode only) - if (pInstance && pInstance->GetData(TYPE_HARBINGERSKYRISS) != DONE) - ->FailQuest();*/ - } - - void UpdateAI(const uint32 diff) - { - if (!Init) - { - if (EventProgress_Timer <= diff) - { - if (Phase < 8) - { - switch(Phase) - { - case 1: - DoScriptText(SAY_INTRO_1, me); - EventProgress_Timer = 18000; - break; - case 2: - DoScriptText(SAY_INTRO_2, me); - EventProgress_Timer = 18000; - break; - case 3: - DoScriptText(SAY_WATER, me); - DoCast(me, SPELL_CONJURE_WATER); - EventProgress_Timer = 7000; - break; - case 4: - DoScriptText(SAY_BUFFS, me); - DoCast(me, SPELL_ICE_ARMOR); - EventProgress_Timer = 7000; - break; - case 5: - DoScriptText(SAY_DRINK, me); - DoCast(me, SPELL_ARCANE_INTELLECT); - EventProgress_Timer = 7000; - break; - case 6: - DoScriptText(SAY_READY, me); - EventProgress_Timer = 6000; - break; - case 7: - if (pInstance) - pInstance->SetData(TYPE_WARDEN_2,DONE); - Init = true; - break; - } - ++Phase; - } - } else EventProgress_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) - { - DoScriptText(SAY_LOWHP, me); - LowHp = true; - } - - if (Pyroblast_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoScriptText(SAY_PYRO, me); - - DoCast(me->getVictim(), SPELL_PYROBLAST); - Pyroblast_Timer = 40000; - } else Pyroblast_Timer -=diff; - - if (Fireball_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL); - Fireball_Timer = 4000; - } else Fireball_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_millhouse_manastorm(Creature* pCreature) -{ - return new npc_millhouse_manastormAI (pCreature); -} - -/*##### -# npc_warden_mellichar -#####*/ - -#define YELL_INTRO1 -1552023 -#define YELL_INTRO2 -1552024 -#define YELL_RELEASE1 -1552025 -#define YELL_RELEASE2A -1552026 -#define YELL_RELEASE2B -1552027 -#define YELL_RELEASE3 -1552028 -#define YELL_RELEASE4 -1552029 -#define YELL_WELCOME -1552030 - -//phase 2(acid mobs) -#define ENTRY_TRICKSTER 20905 -#define ENTRY_PH_HUNTER 20906 -//phase 3 -#define ENTRY_MILLHOUSE 20977 -//phase 4(acid mobs) -#define ENTRY_AKKIRIS 20908 -#define ENTRY_SULFURON 20909 -//phase 5(acid mobs) -#define ENTRY_TW_DRAK 20910 -#define ENTRY_BL_DRAK 20911 -//phase 6 -#define ENTRY_SKYRISS 20912 - -//TARGET_SCRIPT -#define SPELL_TARGET_ALPHA 36856 -#define SPELL_TARGET_BETA 36854 -#define SPELL_TARGET_DELTA 36857 -#define SPELL_TARGET_GAMMA 36858 -#define SPELL_TARGET_OMEGA 36852 -#define SPELL_BUBBLE_VISUAL 36849 - -struct npc_warden_mellicharAI : public ScriptedAI -{ - npc_warden_mellicharAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool IsRunning; - bool CanSpawn; - - uint32 EventProgress_Timer; - uint32 Phase; - - void Reset() - { - IsRunning = false; - CanSpawn = false; - - EventProgress_Timer = 22000; - Phase = 1; - - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - DoCast(me, SPELL_TARGET_OMEGA); - - if (pInstance) - pInstance->SetData(TYPE_HARBINGERSKYRISS,NOT_STARTED); - } - - void AttackStart(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (IsRunning) - return; - - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - if (who->GetTypeId() != TYPEID_PLAYER) - return; - - float attackRadius = me->GetAttackDistance(who)/10; - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - EnterCombat(who); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_INTRO1, me); - DoCast(me, SPELL_BUBBLE_VISUAL); - - if (pInstance) - { - pInstance->SetData(TYPE_HARBINGERSKYRISS,IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), false); - IsRunning = true; - } - } - - bool CanProgress() - { - if (pInstance) - { - if (Phase == 7 && pInstance->GetData(TYPE_WARDEN_4) == DONE) - return true; - if (Phase == 6 && pInstance->GetData(TYPE_WARDEN_3) == DONE) - return true; - if (Phase == 5 && pInstance->GetData(TYPE_WARDEN_2) == DONE) - return true; - if (Phase == 4) - return true; - if (Phase == 3 && pInstance->GetData(TYPE_WARDEN_1) == DONE) - return true; - if (Phase == 2 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS) - return true; - if (Phase == 1 && pInstance->GetData(TYPE_HARBINGERSKYRISS) == IN_PROGRESS) - return true; - return false; - } - return false; - } - - void DoPrepareForPhase() - { - if (pInstance) - { - me->InterruptNonMeleeSpells(true); - me->RemoveAurasByType(SPELL_AURA_DUMMY); - - switch(Phase) - { - case 2: - DoCast(me, SPELL_TARGET_ALPHA); - pInstance->SetData(TYPE_WARDEN_1,IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), false); - break; - case 3: - DoCast(me, SPELL_TARGET_BETA); - pInstance->SetData(TYPE_WARDEN_2,IN_PROGRESS); - break; - case 5: - DoCast(me, SPELL_TARGET_DELTA); - pInstance->SetData(TYPE_WARDEN_3,IN_PROGRESS); - break; - case 6: - DoCast(me, SPELL_TARGET_GAMMA); - pInstance->SetData(TYPE_WARDEN_4,IN_PROGRESS); - break; - case 7: - pInstance->SetData(TYPE_WARDEN_5,IN_PROGRESS); - break; - } - CanSpawn = true; - } - } - - void UpdateAI(const uint32 diff) - { - if (!IsRunning) - return; - - if (EventProgress_Timer <= diff) - { - if (pInstance) - { - if (pInstance->GetData(TYPE_HARBINGERSKYRISS) == FAIL) - { - Reset(); - return; - } - } - - if (CanSpawn) - { - //continue beam omega pod, unless we are about to summon skyriss - if (Phase != 7) - DoCast(me, SPELL_TARGET_OMEGA); - - switch(Phase) - { - case 2: - switch (urand(0,1)) - { - case 0: me->SummonCreature(ENTRY_TRICKSTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - case 1: me->SummonCreature(ENTRY_PH_HUNTER,478.326,-148.505,42.56,3.19,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - } - break; - case 3: - me->SummonCreature(ENTRY_MILLHOUSE,413.292,-148.378,42.56,6.27,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); - break; - case 4: - DoScriptText(YELL_RELEASE2B, me); - break; - case 5: - switch (urand(0,1)) - { - case 0: me->SummonCreature(ENTRY_AKKIRIS,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - case 1: me->SummonCreature(ENTRY_SULFURON,420.179,-174.396,42.58,0.02,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - } - break; - case 6: - switch (urand(0,1)) - { - case 0: me->SummonCreature(ENTRY_TW_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - case 1: me->SummonCreature(ENTRY_BL_DRAK,471.795,-174.58,42.58,3.06,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); break; - } - break; - case 7: - me->SummonCreature(ENTRY_SKYRISS,445.763,-191.639,44.64,1.60,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000); - DoScriptText(YELL_WELCOME, me); - break; - } - CanSpawn = false; - ++Phase; - } - if (CanProgress()) - { - switch(Phase) - { - case 1: - DoScriptText(YELL_INTRO2, me); - EventProgress_Timer = 10000; - ++Phase; - break; - case 2: - DoScriptText(YELL_RELEASE1, me); - DoPrepareForPhase(); - EventProgress_Timer = 7000; - break; - case 3: - DoScriptText(YELL_RELEASE2A, me); - DoPrepareForPhase(); - EventProgress_Timer = 10000; - break; - case 4: - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 5: - DoScriptText(YELL_RELEASE3, me); - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 6: - DoScriptText(YELL_RELEASE4, me); - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 7: - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - } - } - } else EventProgress_Timer -= diff; - } -}; -CreatureAI* GetAI_npc_warden_mellichar(Creature* pCreature) -{ - return new npc_warden_mellicharAI (pCreature); -} - -/*##### -# mob_zerekethvoidzone (this script probably not needed in future -> `creature_template_addon`.`auras`='36120 0') -#####*/ - -#define SPELL_VOID_ZONE_DAMAGE 36120 - -struct mob_zerekethvoidzoneAI : public ScriptedAI -{ - mob_zerekethvoidzoneAI(Creature *c) : ScriptedAI(c) {} - - void Reset() - { - me->SetUInt32Value(UNIT_NPC_FLAGS,0); - me->setFaction(16); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - DoCast(me, SPELL_VOID_ZONE_DAMAGE); - } - - void EnterCombat(Unit* /*who*/) {} -}; -CreatureAI* GetAI_mob_zerekethvoidzoneAI(Creature* pCreature) -{ - return new mob_zerekethvoidzoneAI (pCreature); -} - -void AddSC_arcatraz() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_millhouse_manastorm"; - newscript->GetAI = &GetAI_npc_millhouse_manastorm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_warden_mellichar"; - newscript->GetAI = &GetAI_npc_warden_mellichar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_zerekethvoidzone"; - newscript->GetAI = &GetAI_mob_zerekethvoidzoneAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h b/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h deleted file mode 100644 index 3f8dee8bbd0..00000000000 --- a/src/server/scripts/Outland/tempest_keep/arcatraz/arcatraz.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_ARCATRAZ_H -#define DEF_ARCATRAZ_H - -#define TYPE_ZEREKETH 1 -#define TYPE_DALLIAH 2 -#define TYPE_SOCCOTHRATES 3 -#define TYPE_HARBINGERSKYRISS 4 -#define TYPE_WARDEN_1 5 -#define TYPE_WARDEN_2 6 -#define TYPE_WARDEN_3 7 -#define TYPE_WARDEN_4 8 -#define TYPE_WARDEN_5 9 -#define DATA_MELLICHAR 10 -#define TYPE_SHIELD_OPEN 11 -#define DATA_SPHERE_SHIELD 12 -#endif - diff --git a/src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp b/src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp deleted file mode 100644 index 6576974f3ff..00000000000 --- a/src/server/scripts/Outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Harbinger_Skyriss -SD%Complete: 45 -SDComment: CombatAI not fully implemented. Timers will need adjustments. Need more docs on how event fully work. Reset all event and force start over if fail at one point? -SDCategory: Tempest Keep, The Arcatraz -EndScriptData */ - -/* ContentData -boss_harbinger_skyriss -boss_harbinger_skyriss_illusion -EndContentData */ - -#include "ScriptedPch.h" -#include "arcatraz.h" - -#define SAY_INTRO -1552000 -#define SAY_AGGRO -1552001 -#define SAY_KILL_1 -1552002 -#define SAY_KILL_2 -1552003 -#define SAY_MIND_1 -1552004 -#define SAY_MIND_2 -1552005 -#define SAY_FEAR_1 -1552006 -#define SAY_FEAR_2 -1552007 -#define SAY_IMAGE -1552008 -#define SAY_DEATH -1552009 - -#define SPELL_FEAR 39415 - -#define SPELL_MIND_REND 36924 -#define H_SPELL_MIND_REND 39017 - -#define SPELL_DOMINATION 37162 -#define H_SPELL_DOMINATION 39019 - -#define H_SPELL_MANA_BURN 39020 - -#define SPELL_66_ILLUSION 36931 //entry 21466 -#define SPELL_33_ILLUSION 36932 //entry 21467 - -struct boss_harbinger_skyrissAI : public ScriptedAI -{ - boss_harbinger_skyrissAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = false; - } - - ScriptedInstance *pInstance; - - bool Intro; - bool IsImage33; - bool IsImage66; - - uint32 Intro_Phase; - uint32 Intro_Timer; - uint32 MindRend_Timer; - uint32 Fear_Timer; - uint32 Domination_Timer; - uint32 ManaBurn_Timer; - - void Reset() - { - if (!Intro) - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); - - IsImage33 = false; - IsImage66 = false; - - Intro_Phase = 1; - Intro_Timer = 5000; - MindRend_Timer = 3000; - Fear_Timer = 15000; - Domination_Timer = 30000; - ManaBurn_Timer = 25000; - } - - void MoveInLineOfSight(Unit *who) - { - if (!Intro) - { - return; - } - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) {} - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - pInstance->SetData(TYPE_HARBINGERSKYRISS,DONE); - } - - void JustSummoned(Creature *summon) - { - if (!summon) - return; - if (IsImage66) - summon->SetHealth((summon->GetMaxHealth()*33)/100); - else - summon->SetHealth((summon->GetMaxHealth()*66)/100); - if (me->getVictim()) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - summon->AI()->AttackStart(pTarget); - } - - void KilledUnit(Unit* victim) - { - //won't yell killing pet/other unit - if (victim->GetEntry() == 21436) - return; - - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void DoSplit(uint32 val) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoScriptText(SAY_IMAGE, me); - - if (val == 66) - DoCast(me, SPELL_66_ILLUSION); - else - DoCast(me, SPELL_33_ILLUSION); - } - - void UpdateAI(const uint32 diff) - { - if (!Intro) - { - if (!pInstance) - return; - - if (Intro_Timer <= diff) - { - switch(Intro_Phase) - { - case 1: - DoScriptText(SAY_INTRO, me); - pInstance->HandleGameObject(pInstance->GetData64(DATA_SPHERE_SHIELD), true); - ++Intro_Phase; - Intro_Timer = 25000; - break; - case 2: - DoScriptText(SAY_AGGRO, me); - if (Unit *mellic = Unit::GetUnit(*me,pInstance->GetData64(DATA_MELLICHAR))) - { - //should have a better way to do this. possibly spell exist. - mellic->setDeathState(JUST_DIED); - mellic->SetHealth(0); - pInstance->SetData(TYPE_SHIELD_OPEN,IN_PROGRESS); - } - ++Intro_Phase; - Intro_Timer = 3000; - break; - case 3: - me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE); - Intro = true; - break; - } - } else Intro_Timer -=diff; - } - - if (!UpdateVictim()) - return; - - if (!IsImage66 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 66)) - { - DoSplit(66); - IsImage66 = true; - } - if (!IsImage33 && ((me->GetHealth()*100) / me->GetMaxHealth() <= 33)) - { - DoSplit(33); - IsImage33 = true; - } - - if (MindRend_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_MIND_REND); - else - DoCast(me->getVictim(), SPELL_MIND_REND); - - MindRend_Timer = 8000; - } else MindRend_Timer -=diff; - - if (Fear_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoScriptText(RAND(SAY_FEAR_1,SAY_FEAR_2), me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_FEAR); - else - DoCast(me->getVictim(), SPELL_FEAR); - - Fear_Timer = 25000; - } else Fear_Timer -=diff; - - if (Domination_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoScriptText(RAND(SAY_MIND_1,SAY_MIND_2), me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_DOMINATION); - else - DoCast(me->getVictim(), SPELL_DOMINATION); - - Domination_Timer = 16000+rand()%16000; - } else Domination_Timer -=diff; - - if (IsHeroic()) - { - if (ManaBurn_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - return; - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, H_SPELL_MANA_BURN); - - ManaBurn_Timer = 16000+rand()%16000; - } else ManaBurn_Timer -=diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_harbinger_skyriss(Creature* pCreature) -{ - return new boss_harbinger_skyrissAI (pCreature); -} - -#define SPELL_MIND_REND_IMAGE 36929 -#define H_SPELL_MIND_REND_IMAGE 39021 - -struct boss_harbinger_skyriss_illusionAI : public ScriptedAI -{ - boss_harbinger_skyriss_illusionAI(Creature *c) : ScriptedAI(c) - { - } - - void Reset() { } - - void EnterCombat(Unit * /*who*/) { } -}; - -CreatureAI* GetAI_boss_harbinger_skyriss_illusion(Creature* pCreature) -{ - return new boss_harbinger_skyriss_illusionAI (pCreature); -} - -void AddSC_boss_harbinger_skyriss() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_harbinger_skyriss"; - newscript->GetAI = &GetAI_boss_harbinger_skyriss; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_harbinger_skyriss_illusion"; - newscript->GetAI = &GetAI_boss_harbinger_skyriss_illusion; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp b/src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp deleted file mode 100644 index d16975e2af6..00000000000 --- a/src/server/scripts/Outland/tempest_keep/arcatraz/instance_arcatraz.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Arcatraz -SD%Complete: 80 -SDComment: Mainly Harbringer Skyriss event -SDCategory: Tempest Keep, The Arcatraz -EndScriptData */ - -#include "ScriptedPch.h" -#include "arcatraz.h" - -#define MAX_ENCOUNTER 9 - -#define CONTAINMENT_CORE_SECURITY_FIELD_ALPHA 184318 //door opened when Wrath-Scryer Soccothrates dies -#define CONTAINMENT_CORE_SECURITY_FIELD_BETA 184319 //door opened when Dalliah the Doomsayer dies -#define POD_ALPHA 183961 //pod first boss wave -#define POD_BETA 183963 //pod second boss wave -#define POD_DELTA 183964 //pod third boss wave -#define POD_GAMMA 183962 //pod fourth boss wave -#define POD_OMEGA 183965 //pod fifth boss wave -#define WARDENS_SHIELD 184802 // warden shield -#define SEAL_SPHERE 184802 //shield 'protecting' mellichar - -#define MELLICHAR 20904 //skyriss will kill this unit - -/* Arcatraz encounters: -1 - Zereketh the Unbound event -2 - Dalliah the Doomsayer event -3 - Wrath-Scryer Soccothrates event -4 - Harbinger Skyriss event, 5 sub-events -*/ - -struct instance_arcatraz : public ScriptedInstance -{ - instance_arcatraz(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 Containment_Core_Security_Field_AlphaGUID; - uint64 Containment_Core_Security_Field_BetaGUID; - uint64 Pod_AlphaGUID; - uint64 Pod_GammaGUID; - uint64 Pod_BetaGUID; - uint64 Pod_DeltaGUID; - uint64 Pod_OmegaGUID; - uint64 Wardens_ShieldGUID; - uint64 GoSphereGUID; - uint64 MellicharGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Containment_Core_Security_Field_AlphaGUID = 0; - Containment_Core_Security_Field_BetaGUID = 0; - Pod_AlphaGUID = 0; - Pod_GammaGUID = 0; - Pod_BetaGUID = 0; - Pod_DeltaGUID = 0; - Pod_OmegaGUID = 0; - Wardens_ShieldGUID = 0; - GoSphereGUID = 0; - MellicharGUID = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case CONTAINMENT_CORE_SECURITY_FIELD_ALPHA: Containment_Core_Security_Field_AlphaGUID = pGo->GetGUID(); break; - case CONTAINMENT_CORE_SECURITY_FIELD_BETA: Containment_Core_Security_Field_BetaGUID = pGo->GetGUID(); break; - case POD_ALPHA: Pod_AlphaGUID = pGo->GetGUID(); break; - case POD_GAMMA: Pod_GammaGUID = pGo->GetGUID(); break; - case POD_BETA: Pod_BetaGUID = pGo->GetGUID(); break; - case POD_DELTA: Pod_DeltaGUID = pGo->GetGUID(); break; - case POD_OMEGA: Pod_OmegaGUID = pGo->GetGUID(); break; - case SEAL_SPHERE: GoSphereGUID = pGo->GetGUID(); break; - //case WARDENS_SHIELD: Wardens_ShieldGUID = pGo->GetGUID(); break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == MELLICHAR) - MellicharGUID = pCreature->GetGUID(); - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_ZEREKETH: - m_auiEncounter[0] = data; - break; - - case TYPE_DALLIAH: - if (data == DONE) - { - if (GameObject *pGo = instance->GetGameObject(Containment_Core_Security_Field_BetaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[1] = data; - break; - - case TYPE_SOCCOTHRATES: - if (data == DONE) - { - if (GameObject *pGo = instance->GetGameObject(Containment_Core_Security_Field_AlphaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[2] = data; - break; - - case TYPE_HARBINGERSKYRISS: - if (data == NOT_STARTED || data == FAIL) - { - m_auiEncounter[4] = NOT_STARTED; - m_auiEncounter[5] = NOT_STARTED; - m_auiEncounter[6] = NOT_STARTED; - m_auiEncounter[7] = NOT_STARTED; - m_auiEncounter[8] = NOT_STARTED; - } - m_auiEncounter[3] = data; - break; - - case TYPE_WARDEN_1: - if (data == IN_PROGRESS) - if (GameObject *pGo = instance->GetGameObject(Pod_AlphaGUID)) - pGo->UseDoorOrButton(); - m_auiEncounter[4] = data; - break; - - case TYPE_WARDEN_2: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Pod_BetaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[5] = data; - break; - - case TYPE_WARDEN_3: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Pod_DeltaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[6] = data; - break; - - case TYPE_WARDEN_4: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Pod_GammaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[7] = data; - break; - - case TYPE_WARDEN_5: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Pod_OmegaGUID)) - pGo->UseDoorOrButton(); - } - m_auiEncounter[8] = data; - break; - - case TYPE_SHIELD_OPEN: - if (data == IN_PROGRESS) - { - if (GameObject *pGo = instance->GetGameObject(Wardens_ShieldGUID)) - pGo->UseDoorOrButton(); - } - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_HARBINGERSKYRISS: return m_auiEncounter[3]; - case TYPE_WARDEN_1: return m_auiEncounter[4]; - case TYPE_WARDEN_2: return m_auiEncounter[5]; - case TYPE_WARDEN_3: return m_auiEncounter[6]; - case TYPE_WARDEN_4: return m_auiEncounter[7]; - case TYPE_WARDEN_5: return m_auiEncounter[8]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_MELLICHAR: return MellicharGUID; - case DATA_SPHERE_SHIELD: return GoSphereGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_arcatraz(Map* pMap) -{ - return new instance_arcatraz(pMap); -} - -void AddSC_instance_arcatraz() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_arcatraz"; - newscript->GetInstanceData = &GetInstanceData_instance_arcatraz; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp b/src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp deleted file mode 100644 index 1a077036298..00000000000 --- a/src/server/scripts/Outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_High_Botanist_Freywinn -SD%Complete: 90 -SDComment: some strange visual related to tree form(if aura lost before normal duration end). possible make summon&transform -process smoother(transform after delay) -SDCategory: Tempest Keep, The Botanica -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1553000 -#define SAY_KILL_1 -1553001 -#define SAY_KILL_2 -1553002 -#define SAY_TREE_1 -1553003 -#define SAY_TREE_2 -1553004 -#define SAY_DEATH -1553005 - -#define SPELL_TRANQUILITY 34550 -#define SPELL_TREE_FORM 34551 - -#define SPELL_SUMMON_FRAYER 34557 -#define ENTRY_FRAYER 19953 - -#define SPELL_PLANT_WHITE 34759 -#define SPELL_PLANT_GREEN 34761 -#define SPELL_PLANT_BLUE 34762 -#define SPELL_PLANT_RED 34763 - -struct boss_high_botanist_freywinnAI : public ScriptedAI -{ - boss_high_botanist_freywinnAI(Creature *c) : ScriptedAI(c) {} - - std::list Adds_List; - - uint32 SummonSeedling_Timer; - uint32 TreeForm_Timer; - uint32 MoveCheck_Timer; - uint32 DeadAddsCount; - bool MoveFree; - - void Reset() - { - Adds_List.clear(); - - SummonSeedling_Timer = 6000; - TreeForm_Timer = 30000; - MoveCheck_Timer = 1000; - DeadAddsCount = 0; - MoveFree = true; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == ENTRY_FRAYER) - Adds_List.push_back(summoned->GetGUID()); - } - - void DoSummonSeedling() - { - switch(rand()%4) - { - case 0: DoCast(me, SPELL_PLANT_WHITE); break; - case 1: DoCast(me, SPELL_PLANT_GREEN); break; - case 2: DoCast(me, SPELL_PLANT_BLUE); break; - case 3: DoCast(me, SPELL_PLANT_RED); break; - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (TreeForm_Timer <= diff) - { - DoScriptText(RAND(SAY_TREE_1,SAY_TREE_2), me); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - me->RemoveAllAuras(); - - DoCast(me, SPELL_SUMMON_FRAYER, true); - DoCast(me, SPELL_TRANQUILITY, true); - DoCast(me, SPELL_TREE_FORM, true); - - me->GetMotionMaster()->MoveIdle(); - MoveFree = false; - - TreeForm_Timer = 75000; - } else TreeForm_Timer -= diff; - - if (!MoveFree) - { - if (MoveCheck_Timer <= diff) - { - if (!Adds_List.empty()) - { - for (std::list::iterator itr = Adds_List.begin(); itr != Adds_List.end(); ++itr) - { - if (Unit *temp = Unit::GetUnit(*me,*itr)) - { - if (!temp->isAlive()) - { - Adds_List.erase(itr); - ++DeadAddsCount; - break; - } - } - } - } - - if (DeadAddsCount < 3 && TreeForm_Timer-30000 <= diff) - DeadAddsCount = 3; - - if (DeadAddsCount >= 3) - { - Adds_List.clear(); - DeadAddsCount = 0; - - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - MoveFree = true; - } - MoveCheck_Timer = 500; - } - else MoveCheck_Timer -= diff; - - return; - } - - /*if (me->HasAura(SPELL_TREE_FORM,0) || me->HasAura(SPELL_TRANQUILITY,0)) - return;*/ - - //one random seedling every 5 secs, but not in tree form - if (SummonSeedling_Timer <= diff) - { - DoSummonSeedling(); - SummonSeedling_Timer = 6000; - } else SummonSeedling_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_high_botanist_freywinn(Creature* pCreature) -{ - return new boss_high_botanist_freywinnAI (pCreature); -} - -void AddSC_boss_high_botanist_freywinn() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_high_botanist_freywinn"; - newscript->GetAI = &GetAI_boss_high_botanist_freywinn; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp b/src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp deleted file mode 100644 index cbf21c2f992..00000000000 --- a/src/server/scripts/Outland/tempest_keep/botanica/boss_laj.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Laj -SD%Complete: 90 -SDComment: Immunities are wrong, must be adjusted to use resistance from creature_templates. Most spells require database support. -SDCategory: Tempest Keep, The Botanica -EndScriptData */ - -#include "ScriptedPch.h" - -#define EMOTE_SUMMON -1553006 - -#define SPELL_ALLERGIC_REACTION 34697 -#define SPELL_TELEPORT_SELF 34673 - -#define SPELL_SUMMON_LASHER_1 34681 -#define SPELL_SUMMON_FLAYER_1 34682 -#define SPELL_SUMMON_LASHER_2 34684 -#define SPELL_SUMMON_FLAYER_2 34685 -#define SPELL_SUMMON_LASHER_3 34686 -#define SPELL_SUMMON_FLAYER_4 34687 -#define SPELL_SUMMON_LASHER_4 34688 -#define SPELL_SUMMON_FLAYER_3 34690 - -#define MODEL_DEFAULT 13109 -#define MODEL_ARCANE 14213 -#define MODEL_FIRE 13110 -#define MODEL_FROST 14112 -#define MODEL_NATURE 14214 - -struct boss_lajAI : public ScriptedAI -{ - boss_lajAI(Creature *c) : ScriptedAI(c) {} - - bool CanSummon; - uint32 Teleport_Timer; - uint32 Summon_Timer; - uint32 Transform_Timer; - uint32 Allergic_Timer; - - void Reset() - { - me->SetDisplayId(MODEL_DEFAULT); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - - CanSummon = false; - Teleport_Timer = 20000; - Summon_Timer = 2500; - Transform_Timer = 30000; - Allergic_Timer = 5000; - } - - void DoTransform() - { - switch(rand()%5) - { - case 0: - me->SetDisplayId(MODEL_DEFAULT); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - break; - case 1: - me->SetDisplayId(MODEL_ARCANE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - break; - case 2: - me->SetDisplayId(MODEL_FIRE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - break; - case 3: - me->SetDisplayId(MODEL_FROST); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - break; - case 4: - me->SetDisplayId(MODEL_NATURE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - break; - } - } - - void DoSummons() - { - switch(rand()%4) - { - case 0: - DoCast(me, SPELL_SUMMON_LASHER_1, true); - DoCast(me, SPELL_SUMMON_FLAYER_1, true); - break; - case 1: - DoCast(me, SPELL_SUMMON_LASHER_2, true); - DoCast(me, SPELL_SUMMON_FLAYER_2, true); - break; - case 2: - DoCast(me, SPELL_SUMMON_LASHER_3, true); - DoCast(me, SPELL_SUMMON_FLAYER_3, true); - break; - case 3: - DoCast(me, SPELL_SUMMON_LASHER_4, true); - DoCast(me, SPELL_SUMMON_FLAYER_4, true); - break; - } - CanSummon = false; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void JustSummoned(Creature *summon) - { - if (summon && me->getVictim()) - summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (CanSummon) - { - if (Summon_Timer <= diff) - { - DoScriptText(EMOTE_SUMMON, me); - DoSummons(); - Summon_Timer = 2500; - } else Summon_Timer -= diff; - } - - if (Allergic_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ALLERGIC_REACTION); - Allergic_Timer = 25000+rand()%15000; - } else Allergic_Timer -= diff; - - if (Teleport_Timer <= diff) - { - DoCast(me, SPELL_TELEPORT_SELF); - Teleport_Timer = 30000+rand()%10000; - CanSummon = true; - } else Teleport_Timer -= diff; - - if (Transform_Timer <= diff) - { - DoTransform(); - Transform_Timer = 25000+rand()%15000; - } else Transform_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_laj(Creature* pCreature) -{ - return new boss_lajAI (pCreature); -} - -void AddSC_boss_laj() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_laj"; - newscript->GetAI = &GetAI_boss_laj; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp deleted file mode 100644 index 48eb03c16d3..00000000000 --- a/src/server/scripts/Outland/tempest_keep/botanica/boss_warp_splinter.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Warp_Splinter -SD%Complete: 80 -SDComment: Includes Sapling (need some better control with these). -SDCategory: Tempest Keep, The Botanica -EndScriptData */ - -#include "ScriptedPch.h" - -/*##### -# mob_treant (Sapling) -#####*/ - -#define SPELL_HEAL_FATHER 6262 - -struct mob_treantAI : public ScriptedAI -{ - mob_treantAI (Creature *c) : ScriptedAI(c) - { - WarpGuid = 0; - } - - uint64 WarpGuid; - uint32 check_Timer; - - void Reset() - { - check_Timer = 0; - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (WarpGuid && check_Timer <= diff) - { - if (Unit *Warp = Unit::GetUnit(*me, WarpGuid)) - { - if (me->IsWithinMeleeRange(Warp,2.5f)) - { - int32 CurrentHP_Treant = (int32)me->GetHealth(); - Warp->CastCustomSpell(Warp,SPELL_HEAL_FATHER,&CurrentHP_Treant, 0, 0, true,0 ,0, me->GetGUID()); - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - me->GetMotionMaster()->MoveFollow(Warp,0,0); - } - check_Timer = 1000; - } else check_Timer -= diff; - return; - } - - if (me->getVictim()->GetGUID() != WarpGuid) - DoMeleeAttackIfReady(); - } -}; - -/*##### -# boss_warp_splinter -#####*/ - -#define SAY_AGGRO -1553007 -#define SAY_SLAY_1 -1553008 -#define SAY_SLAY_2 -1553009 -#define SAY_SUMMON_1 -1553010 -#define SAY_SUMMON_2 -1553011 -#define SAY_DEATH -1553012 - -#define WAR_STOMP 34716 -#define SUMMON_TREANTS 34727 // DBC: 34727, 34731, 34733, 34734, 34736, 34739, 34741 (with Ancestral Life spell 34742) // won't work (guardian summon) -#define ARCANE_VOLLEY DUNGEON_MODE(36705, 39133) - -#define CREATURE_TREANT 19949 - -#define TREANT_SPAWN_DIST 50 //50 yards from Warp Splinter's spawn point - -float treant_pos[6][3] = -{ - {24.301233, 427.221100, -27.060635}, - {16.795492, 359.678802, -27.355425}, - {53.493484, 345.381470, -26.196192}, - {61.867096, 439.362732, -25.921030}, - {109.861877, 423.201630, -27.356019}, - {106.780159, 355.582581, -27.593357} -}; - -struct boss_warp_splinterAI : public ScriptedAI -{ - boss_warp_splinterAI(Creature *c) : ScriptedAI(c) - { - Treant_Spawn_Pos_X = c->GetPositionX(); - Treant_Spawn_Pos_Y = c->GetPositionY(); - } - - uint32 War_Stomp_Timer; - uint32 Summon_Treants_Timer; - uint32 Arcane_Volley_Timer; - - float Treant_Spawn_Pos_X; - float Treant_Spawn_Pos_Y; - - void Reset() - { - War_Stomp_Timer = 25000 + rand()%15000; - Summon_Treants_Timer = 45000; - Arcane_Volley_Timer = 8000 + rand()%12000; - - me->SetSpeed(MOVE_RUN, 0.7f, true); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void SummonTreants() - { - for (uint8 i = 0; i < 6; ++i) - { - float angle = (M_PI / 3) * i; - - float X = Treant_Spawn_Pos_X + TREANT_SPAWN_DIST * cos(angle); - float Y = Treant_Spawn_Pos_Y + TREANT_SPAWN_DIST * sin(angle); - float O = - me->GetAngle(X,Y); - - if (Creature *pTreant = me->SummonCreature(CREATURE_TREANT,treant_pos[i][0],treant_pos[i][1],treant_pos[i][2],O,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,25000)) - CAST_AI(mob_treantAI, pTreant->AI())->WarpGuid = me->GetGUID(); - } - DoScriptText(RAND(SAY_SUMMON_1,SAY_SUMMON_2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Check for War Stomp - if (War_Stomp_Timer <= diff) - { - DoCast(me->getVictim(), WAR_STOMP); - War_Stomp_Timer = 25000 + rand()%15000; - } else War_Stomp_Timer -= diff; - - //Check for Arcane Volley - if (Arcane_Volley_Timer <= diff) - { - DoCast(me->getVictim(), ARCANE_VOLLEY); - Arcane_Volley_Timer = 20000 + rand()%15000; - } else Arcane_Volley_Timer -= diff; - - //Check for Summon Treants - if (Summon_Treants_Timer <= diff) - { - SummonTreants(); - Summon_Treants_Timer = 45000; - } else Summon_Treants_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_warp_splinter(Creature* pCreature) -{ - return new boss_warp_splinterAI (pCreature); -} - -CreatureAI* GetAI_mob_treant(Creature* pCreature) -{ - return new mob_treantAI (pCreature); -} - -void AddSC_boss_warp_splinter() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_warp_splinter"; - newscript->GetAI = &GetAI_boss_warp_splinter; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_warp_splinter_treant"; - newscript->GetAI = &GetAI_mob_treant; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp deleted file mode 100644 index af5f1bd95c1..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_eye/boss_alar.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* Copyright(C) 2006 - 2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -*(at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_alar -SD%Complete: 95 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define SPELL_FLAME_BUFFET 34121 // Flame Buffet - every 1,5 secs in phase 1 if there is no victim in melee range and after Dive Bomb in phase 2 with same conditions -#define SPELL_FLAME_QUILLS 34229 // Randomly after changing position in phase after watching tonns of movies, set probability 20% -#define SPELL_REBIRTH 34342 // Rebirth - beginning of second phase(after loose all health in phase 1) -#define SPELL_REBIRTH_2 35369 // Rebirth(another, without healing to full HP) - after Dive Bomb in phase 2 -#define SPELL_MELT_ARMOR 35410 // Melt Armor - every 60 sec in phase 2 -#define SPELL_CHARGE 35412 // Charge - 30 sec cooldown -#define SPELL_DIVE_BOMB_VISUAL 35367 // Bosskillers says 30 sec cooldown, wowwiki says 30 sec colldown, DBM and BigWigs addons says ~47 sec -#define SPELL_DIVE_BOMB 35181 // after watching tonns of movies, set cooldown to 40+rand()%5. -#define SPELL_BERSERK 45078 // 10 minutes after phase 2 starts(id is wrong, but proper id is unknown) - -#define CREATURE_EMBER_OF_ALAR 19551 // Al'ar summons one Ember of Al'ar every position change in phase 1 and two after Dive Bomb. Also in phase 2 when Ember of Al'ar dies, boss loose 3% health. -#define SPELL_EMBER_BLAST 34133 // When Ember of Al'ar dies, it casts Ember Blast - -#define CREATURE_FLAME_PATCH_ALAR 20602 // Flame Patch - every 30 sec in phase 2 -#define SPELL_FLAME_PATCH 35380 // - -static float waypoint[6][3] = -{ - {340.15, 58.65, 17.71}, - {388.09, 31.54, 20.18}, - {388.18, -32.85, 20.18}, - {340.29, -60.19, 17.72}, - {332, 0.01, 39}, // better not use the same xy coord - {331, 0.01, -2.39} -}; - -enum WaitEventType -{ - WE_NONE = 0, - WE_DUMMY = 1, - WE_PLATFORM = 2, - WE_QUILL = 3, - WE_DIE = 4, - WE_REVIVE = 5, - WE_CHARGE = 6, - WE_METEOR = 7, - WE_DIVE = 8, - WE_LAND = 9, - WE_SUMMON = 10 -}; - -struct boss_alarAI : public ScriptedAI -{ - boss_alarAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - DefaultMoveSpeedRate = c->GetSpeedRate(MOVE_RUN); - } - - ScriptedInstance *pInstance; - - WaitEventType WaitEvent; - uint32 WaitTimer; - - bool AfterMoving; - - uint32 Platforms_Move_Timer; - uint32 DiveBomb_Timer; - uint32 MeltArmor_Timer; - uint32 Charge_Timer; - uint32 FlamePatch_Timer; - uint32 Berserk_Timer; - - float DefaultMoveSpeedRate; - - bool Phase1; - bool ForceMove; - uint32 ForceTimer; - - int8 cur_wp; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, NOT_STARTED); - - Berserk_Timer = 1200000; - Platforms_Move_Timer = 0; - - Phase1 = true; - WaitEvent = WE_NONE; - WaitTimer = 0; - AfterMoving = false; - ForceMove = false; - ForceTimer = 5000; - - cur_wp = 4; - - me->SetDisplayId(me->GetNativeDisplayId()); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); - //me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - //me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->setActive(false); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, IN_PROGRESS); - - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); // after enterevademode will be set walk movement - DoZoneInCombat(); - me->setActive(true); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, DONE); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - summon->AI()->AttackStart(pTarget); - } - - void MoveInLineOfSight(Unit * /*who*/) {} - - void AttackStart(Unit* who) - { - if (Phase1) - AttackStartNoMove(who); - else - ScriptedAI::AttackStart(who); - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth() && Phase1) - { - damage = 0; - if (!WaitEvent) - { - WaitEvent = WE_DIE; - WaitTimer = 0; - me->SetHealth(0); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->AttackStop(); - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - me->SetSpeed(MOVE_RUN, 5.0f); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]); - } - } - } - - void SpellHit(Unit*, const SpellEntry *spell) - { - if (spell->Id == SPELL_DIVE_BOMB_VISUAL) - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - me->SetDisplayId(11686); - //me->SendUpdateObjectToAllExcept(NULL); - } - } - - void MovementInform(uint32 type, uint32 /*id*/) - { - if (type == POINT_MOTION_TYPE) - { - WaitTimer = 1; - AfterMoving = true; - ForceMove = false; - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) // sometimes isincombat but !incombat, faction bug? - return; - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - Berserk_Timer = 60000; - } else Berserk_Timer -= diff; - - if (ForceMove) - { - if (ForceTimer <= diff) - { - me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); - ForceTimer = 5000; - } else ForceTimer -= diff; - - } - if (WaitEvent) - { - if (WaitTimer) - { - if (WaitTimer <= diff) - { - if (AfterMoving) - { - me->GetMotionMaster()->MoveIdle(); - AfterMoving = false; - } - - switch(WaitEvent) - { - case WE_PLATFORM: - Platforms_Move_Timer = 30000+rand()%5000; - break; - case WE_QUILL: - DoCast(me, SPELL_FLAME_QUILLS, true); - Platforms_Move_Timer = 1; - WaitTimer = 10000; - WaitEvent = WE_DUMMY; - return; - case WE_DIE: - ForceMove = false; - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); - WaitTimer = 5000; - WaitEvent = WE_REVIVE; - return; - case WE_REVIVE: - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); - me->SetHealth(me->GetMaxHealth()); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoZoneInCombat(); - DoCast(me, SPELL_REBIRTH, true); - MeltArmor_Timer = 60000; - Charge_Timer = 7000; - DiveBomb_Timer = 40000+rand()%5000; - FlamePatch_Timer = 30000; - Phase1 = false; - break; - case WE_METEOR: - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - DoCast(me, SPELL_DIVE_BOMB_VISUAL, false); - WaitEvent = WE_DIVE; - WaitTimer = 4000; - return; - case WE_DIVE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL); - DoCast(pTarget, SPELL_DIVE_BOMB, true); - float dist = 3.0f; - if (me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f)) - dist = 5.0f; - WaitTimer = 1000 + floor(dist / 80 * 1000.0f); - me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f); - me->StopMoving(); - WaitEvent = WE_LAND; - } - else - { - EnterEvadeMode(); - return; - } - case WE_LAND: - WaitEvent = WE_SUMMON; - WaitTimer = 2000; - return; - case WE_SUMMON: - for (uint8 i = 0; i < 2; ++i) - DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(me->GetNativeDisplayId()); - DoCast(me, SPELL_REBIRTH_2, true); - break; - case WE_DUMMY: - default: - break; - } - - WaitEvent = WE_NONE; - WaitTimer = 0; - } else WaitTimer -= diff; - } - return; - } - - if (Phase1) - { - if (me->getThreatManager().getThreatList().empty()) - { - EnterEvadeMode(); - return; - } - - if (Platforms_Move_Timer <= diff) - { - if (cur_wp == 4) - { - cur_wp = 0; - WaitEvent = WE_PLATFORM; - } - else - { - if (urand(0,4)) // next platform - { - DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (cur_wp == 3) - cur_wp = 0; - else - ++cur_wp; - WaitEvent = WE_PLATFORM; - } - else // flame quill - { - cur_wp = 4; - WaitEvent = WE_QUILL; - } - } - ForceMove = true; - ForceTimer = 5000; - me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); - WaitTimer = 0; - return; - } else Platforms_Move_Timer -= diff; - } - else - { - if (Charge_Timer <= diff) - { - Unit *pTarget= SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - if (pTarget) - DoCast(pTarget, SPELL_CHARGE); - Charge_Timer = 30000; - } else Charge_Timer -= diff; - - if (MeltArmor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MELT_ARMOR); - MeltArmor_Timer = 60000; - } else MeltArmor_Timer -= diff; - - if (DiveBomb_Timer <= diff) - { - me->AttackStop(); - me->GetMotionMaster()->MovePoint(6, waypoint[4][0], waypoint[4][1], waypoint[4][2]); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 50); - WaitEvent = WE_METEOR; - WaitTimer = 0; - DiveBomb_Timer = 40000+rand()%5000; - return; - } else DiveBomb_Timer -= diff; - - if (FlamePatch_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - Creature* Summoned = me->SummonCreature(CREATURE_FLAME_PATCH_ALAR, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000); - if (Summoned) - { - Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Summoned->SetFloatValue(OBJECT_FIELD_SCALE_X, Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); - Summoned->SetDisplayId(11686); - Summoned->setFaction(me->getFaction()); - Summoned->SetLevel(me->getLevel()); - Summoned->CastSpell(Summoned, SPELL_FLAME_PATCH, false); - } - } - FlamePatch_Timer = 30000; - } else FlamePatch_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void DoMeleeAttackIfReady() - { - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - else - { - Unit *pTarget = NULL; - pTarget = me->SelectNearestTargetInAttackDistance(5); - if (pTarget) - me->AI()->AttackStart(pTarget); - else - { - DoCast(me, SPELL_FLAME_BUFFET, true); - me->setAttackTimer(BASE_ATTACK, 1500); - } - } - } - } -}; - -CreatureAI* GetAI_boss_alar(Creature* pCreature) -{ - return new boss_alarAI(pCreature); -} - -struct mob_ember_of_alarAI : public ScriptedAI -{ - mob_ember_of_alarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - c->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - c->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - } - - ScriptedInstance *pInstance; - bool toDie; - - void Reset() {toDie = false;} - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - void EnterEvadeMode() {me->setDeathState(JUST_DIED);} - - void DamageTaken(Unit* pKiller, uint32 &damage) - { - if (damage >= me->GetHealth() && pKiller != me && !toDie) - { - damage = 0; - DoCast(me, SPELL_EMBER_BLAST, true); - me->SetDisplayId(11686); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (pInstance && pInstance->GetData(DATA_ALAREVENT) == 2) - { - if (Unit* Alar = Unit::GetUnit((*me), pInstance->GetData64(DATA_ALAR))) - { - int AlarHealth = Alar->GetHealth() - Alar->GetMaxHealth()*0.03; - if (AlarHealth > 0) - Alar->SetHealth(AlarHealth); - else - Alar->SetHealth(1); - } - } - toDie = true; - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - if (toDie) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - //me->SetVisibility(VISIBILITY_OFF); - } - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_mob_ember_of_alar(Creature* pCreature) -{ - return new mob_ember_of_alarAI(pCreature); -} - -struct mob_flame_patch_alarAI : public ScriptedAI -{ - mob_flame_patch_alarAI(Creature *c) : ScriptedAI(c) {} - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_mob_flame_patch_alar(Creature* pCreature) -{ - return new mob_flame_patch_alarAI(pCreature); -} - -void AddSC_boss_alar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_alar"; - newscript->GetAI = &GetAI_boss_alar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ember_of_alar"; - newscript->GetAI = &GetAI_mob_ember_of_alar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flame_patch_alar"; - newscript->GetAI = &GetAI_mob_flame_patch_alar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp deleted file mode 100644 index e9e217a5c62..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_eye/boss_astromancer.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Astromancer -SD%Complete: 80 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -enum eEnums -{ - SAY_AGGRO = -1550007, - SAY_SUMMON1 = -1550008, - SAY_SUMMON2 = -1550009, - SAY_KILL1 = -1550010, - SAY_KILL2 = -1550011, - SAY_KILL3 = -1550012, - SAY_DEATH = -1550013, - SAY_VOIDA = -1550014, - SAY_VOIDB = -1550015, - - SPELL_ARCANE_MISSILES = 33031, - SPELL_WRATH_OF_THE_ASTROMANCER = 42783, - SPELL_BLINDING_LIGHT = 33009, - SPELL_FEAR = 34322, - SPELL_VOID_BOLT = 39329, - - SPELL_SPOTLIGHT = 25824, - NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT = 18928, - - NPC_SOLARIUM_AGENT = 18925, - NPC_SOLARIUM_PRIEST = 18806, - - MODEL_HUMAN = 18239, - MODEL_VOIDWALKER = 18988, - - SPELL_SOLARIUM_GREAT_HEAL = 33387, - SPELL_SOLARIUM_HOLY_SMITE = 25054, - SPELL_SOLARIUM_ARCANE_TORRENT = 33390, - - WV_ARMOR = 31000 -}; - -const float CENTER_X = 432.909f; -const float CENTER_Y = -373.424f; -const float CENTER_Z = 17.9608f; -const float CENTER_O = 1.06421f; -const float SMALL_PORTAL_RADIUS = 12.6f; -const float LARGE_PORTAL_RADIUS = 26.0f; -const float PORTAL_Z = 17.005f; - - // x, y, z, o -static float SolarianPos[4] = {432.909, -373.424, 17.9608, 1.06421}; - -struct boss_high_astromancer_solarianAI : public ScriptedAI -{ - boss_high_astromancer_solarianAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - - defaultarmor = c->GetArmor(); - defaultsize = c->GetFloatValue(OBJECT_FIELD_SCALE_X); - } - - ScriptedInstance *pInstance; - SummonList Summons; - - uint8 Phase; - - uint32 ArcaneMissiles_Timer; - uint32 m_uiWrathOfTheAstromancer_Timer; - uint32 BlindingLight_Timer; - uint32 Fear_Timer; - uint32 VoidBolt_Timer; - uint32 Phase1_Timer; - uint32 Phase2_Timer; - uint32 Phase3_Timer; - uint32 AppearDelay_Timer; - uint32 defaultarmor; - uint32 Wrath_Timer; - - float defaultsize; - float Portals[3][3]; - - bool AppearDelay; - bool BlindingLight; - - void Reset() - { - ArcaneMissiles_Timer = 2000; - m_uiWrathOfTheAstromancer_Timer = 15000; - BlindingLight_Timer = 41000; - Fear_Timer = 20000; - VoidBolt_Timer = 10000; - Phase1_Timer = 50000; - Phase2_Timer = 10000; - Phase3_Timer = 15000; - AppearDelay_Timer = 2000; - BlindingLight = false; - AppearDelay = false; - Wrath_Timer = 20000+rand()%5000;//twice in phase one - Phase = 1; - Wrath_Timer = 20000+rand()%5000;//twice in phase one - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); - - me->SetArmor(defaultarmor); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); - me->SetDisplayId(MODEL_HUMAN); - - Summons.DespawnAll(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2,SAY_KILL3), me); - } - - void JustDied(Unit * /*victim*/) - { - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); - me->SetDisplayId(MODEL_HUMAN); - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); - } - - void SummonMinion(uint32 entry, float x, float y, float z) - { - Creature* Summoned = me->SummonCreature(entry, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (Summoned) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Summoned->AI()->AttackStart(pTarget); - - Summons.Summon(Summoned); - } - } - - float Portal_X(float radius) - { - if (urand(0,1)) - radius = -radius; - - return radius * (float)(rand()%100)/100.0f + CENTER_X; - } - - float Portal_Y(float x, float radius) - { - float z = RAND(1, -1); - - return (z*sqrt(radius*radius - (x - CENTER_X)*(x - CENTER_X)) + CENTER_Y); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AppearDelay) - { - me->StopMoving(); - me->AttackStop(); - if (AppearDelay_Timer <= diff) - { - AppearDelay = false; - if (Phase == 2) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_OFF); - } - AppearDelay_Timer = 2000; - } else AppearDelay_Timer -= diff; - } - - if (Phase == 1) - { - if (BlindingLight_Timer <= diff) - { - BlindingLight = true; - BlindingLight_Timer = 45000; - } else BlindingLight_Timer -= diff; - - if (Wrath_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER, true); - Wrath_Timer = 20000+rand()%5000; - } else Wrath_Timer -= diff; - - if (ArcaneMissiles_Timer <= diff) - { - if (BlindingLight) - { - DoCast(me->getVictim(), SPELL_BLINDING_LIGHT); - BlindingLight = false; - }else{ - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (!me->HasInArc(2.5f, pTarget)) - pTarget = me->getVictim(); - - if (pTarget) - DoCast(pTarget, SPELL_ARCANE_MISSILES); - } - ArcaneMissiles_Timer = 3000; - } else ArcaneMissiles_Timer -= diff; - - if (m_uiWrathOfTheAstromancer_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - - //Target the tank ? - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER); - m_uiWrathOfTheAstromancer_Timer = 25000; - } - else - m_uiWrathOfTheAstromancer_Timer = 1000; - } else m_uiWrathOfTheAstromancer_Timer -= diff; - - //Phase1_Timer - if (Phase1_Timer <= diff) - { - Phase = 2; - Phase1_Timer = 50000; - //After these 50 seconds she portals to the middle of the room and disappears, leaving 3 light portals behind. - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, CENTER_X, CENTER_Y, CENTER_Z, CENTER_O); - for (uint8 i=0; i <= 2; ++i) - { - if (!i) - { - Portals[i][0] = Portal_X(SMALL_PORTAL_RADIUS); - Portals[i][1] = Portal_Y(Portals[i][0], SMALL_PORTAL_RADIUS); - Portals[i][2] = CENTER_Z; - } - else - { - Portals[i][0] = Portal_X(LARGE_PORTAL_RADIUS); - Portals[i][1] = Portal_Y(Portals[i][0], LARGE_PORTAL_RADIUS); - Portals[i][2] = PORTAL_Z; - } - } - if ((abs(Portals[2][0] - Portals[1][0]) < 7) && (abs(Portals[2][1] - Portals[1][1]) < 7)) - { - int i=1; - if (abs(CENTER_X + 26.0f - Portals[2][0]) < 7) - i = -1; - Portals[2][0] = Portals[2][0]+7*i; - Portals[2][1] = Portal_Y(Portals[2][0], LARGE_PORTAL_RADIUS); - } - for (int i=0; i <= 2; ++i) - { - if (Creature* Summoned = me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O, TEMPSUMMON_TIMED_DESPAWN, Phase2_Timer+Phase3_Timer+AppearDelay_Timer+1700)) - { - Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Summoned->CastSpell(Summoned, SPELL_SPOTLIGHT, false); - } - } - AppearDelay = true; - } else Phase1_Timer-=diff; - } - else if (Phase == 2) - { - //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. - me->AttackStop(); - me->StopMoving(); - if (Phase2_Timer <= diff) - { - Phase = 3; - for (int i=0; i <= 2; ++i) - for (int j=1; j <= 4; j++) - SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); - - DoScriptText(SAY_SUMMON1, me); - Phase2_Timer = 10000; - } else Phase2_Timer -= diff; - } - else if (Phase == 3) - { - me->AttackStop(); - me->StopMoving(); - - //Check Phase3_Timer - if (Phase3_Timer <= diff) - { - Phase = 1; - - //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. - int i = rand()%3; - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); - - for (int j=0; j <= 2; j++) - if (j != i) - SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - DoScriptText(SAY_SUMMON2, me); - AppearDelay = true; - Phase3_Timer = 15000; - } else Phase3_Timer -= diff; - } - else if (Phase == 4) - { - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 20000; - } else Fear_Timer -= diff; - - //VoidBolt_Timer - if (VoidBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VOID_BOLT); - VoidBolt_Timer = 10000; - } else VoidBolt_Timer -= diff; - } - - //When Solarian reaches 20% she will transform into a huge void walker. - if (Phase != 4 && ((me->GetHealth()*100 / me->GetMaxHealth())<20)) - { - Phase = 4; - - //To make sure she wont be invisible or not selecatble - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - DoScriptText(SAY_VOIDA, me); - DoScriptText(SAY_VOIDB, me); - me->SetArmor(WV_ARMOR); - me->SetDisplayId(MODEL_VOIDWALKER); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize*2.5f); - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_solarium_priestAI : public ScriptedAI -{ - mob_solarium_priestAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 healTimer; - uint32 holysmiteTimer; - uint32 aoesilenceTimer; - - void Reset() - { - healTimer = 9000; - holysmiteTimer = 1; - aoesilenceTimer = 15000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (healTimer <= diff) - { - Unit *pTarget = NULL; - - switch (urand(0,1)) - { - case 0: - if (pInstance) - pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_ASTROMANCER)); - break; - case 1: - pTarget = me; - break; - } - - if (pTarget) - { - DoCast(pTarget, SPELL_SOLARIUM_GREAT_HEAL); - healTimer = 9000; - } - } else healTimer -= diff; - - if (holysmiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARIUM_HOLY_SMITE); - holysmiteTimer = 4000; - } else holysmiteTimer -= diff; - - if (aoesilenceTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARIUM_ARCANE_TORRENT); - aoesilenceTimer = 13000; - } else aoesilenceTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_solarium_priest(Creature* pCreature) -{ - return new mob_solarium_priestAI (pCreature); -} - -CreatureAI* GetAI_boss_high_astromancer_solarian(Creature* pCreature) -{ - return new boss_high_astromancer_solarianAI (pCreature); -} - -void AddSC_boss_high_astromancer_solarian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_high_astromancer_solarian"; - newscript->GetAI = &GetAI_boss_high_astromancer_solarian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_solarium_priest"; - newscript->GetAI = &GetAI_mob_solarium_priest; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp deleted file mode 100644 index 05681fb7539..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_eye/boss_kaelthas.cpp +++ /dev/null @@ -1,1498 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kaelthas -SD%Complete: 60 -SDComment: SQL, weapon scripts, mind control, need correct spells(interruptible/uninterruptible), phoenix spawn location & animation, phoenix behaviour & spawn during gravity lapse -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" -#include "WorldPacket.h" - -enum eEnums -{ - //kael'thas Speech - SAY_INTRO = -1550016, - SAY_INTRO_CAPERNIAN = -1550017, - SAY_INTRO_TELONICUS = -1550018, - SAY_INTRO_THALADRED = -1550019, - SAY_INTRO_SANGUINAR = -1550020, - SAY_PHASE2_WEAPON = -1550021, - SAY_PHASE3_ADVANCE = -1550022, - SAY_PHASE4_INTRO2 = -1550023, - SAY_PHASE5_NUTS = -1550024, - SAY_SLAY1 = -1550025, - SAY_SLAY2 = -1550026, - SAY_SLAY3 = -1550027, - SAY_MINDCONTROL1 = -1550028, - SAY_MINDCONTROL2 = -1550029, - SAY_GRAVITYLAPSE1 = -1550030, - SAY_GRAVITYLAPSE2 = -1550031, - SAY_SUMMON_PHOENIX1 = -1550032, - SAY_SUMMON_PHOENIX2 = -1550033, - SAY_DEATH = -1550034, - - //Thaladred the Darkener speech - SAY_THALADRED_AGGRO = -1550035, - SAY_THALADRED_DEATH = -1550036, - EMOTE_THALADRED_GAZE = -1550037, - - //Lord Sanguinar speech - SAY_SANGUINAR_AGGRO = -1550038, - SAY_SANGUINAR_DEATH = -1550039, - - //Grand Astromancer Capernian speech - SAY_CAPERNIAN_AGGRO = -1550040, - SAY_CAPERNIAN_DEATH = -1550041, - - //Master Engineer Telonicus speech - SAY_TELONICUS_AGGRO = -1550042, - SAY_TELONICUS_DEATH = -1550043, - - //Phase 2 spells - SPELL_SUMMON_WEAPONS = 36976, - SPELL_SUMMON_WEAPONA = 36958, - SPELL_SUMMON_WEAPONB = 36959, - SPELL_SUMMON_WEAPONC = 36960, - SPELL_SUMMON_WEAPOND = 36961, - SPELL_SUMMON_WEAPONE = 36962, - SPELL_SUMMON_WEAPONF = 36963, - SPELL_SUMMON_WEAPONG = 36964, - SPELL_RES_VISUAL = 24171, - - //Phase 4 spells - SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell - SPELL_PYROBLAST = 36819, - SPELL_FLAME_STRIKE = 36735, - SPELL_FLAME_STRIKE_VIS = 36730, - SPELL_FLAME_STRIKE_DMG = 36731, - SPELL_ARCANE_DISRUPTION = 36834, - SPELL_SHOCK_BARRIER = 36815, - SPELL_PHOENIX_ANIMATION = 36723, - SPELL_MIND_CONTROL = 32830, - - //Phase 5 spells - SPELL_EXPLODE = 36092, - SPELL_FULLPOWER = 36187, - SPELL_KNOCKBACK = 11027, - SPELL_GRAVITY_LAPSE = 34480, - SPELL_GRAVITY_LAPSE_AURA = 39432, - SPELL_NETHER_BEAM = 35873, - - //Thaladred the Darkener spells - SPELL_PSYCHIC_BLOW = 10689, - SPELL_SILENCE = 30225, - //Lord Sanguinar spells - SPELL_BELLOWING_ROAR = 40636, - //Grand Astromancer Capernian spells - - SPELL_CAPERNIAN_FIREBALL = 36971, - SPELL_CONFLAGRATION = 37018, - SPELL_ARCANE_EXPLOSION = 36970, - //Master Engineer Telonicus spells - SPELL_BOMB = 37036, - SPELL_REMOTE_TOY = 37027, - //Nether Vapor spell - SPELL_NETHER_VAPOR = 35859, - //Phoenix spell - SPELL_BURN = 36720, - SPELL_EMBER_BLAST = 34341, - SPELL_REBIRTH = 41587, - - //Creature IDs - NPC_PHOENIX = 21362, - NPC_PHOENIX_EGG = 21364, - - //Phoenix egg and phoenix model - MODEL_ID_PHOENIX = 19682, - MODEL_ID_PHOENIX_EGG = 20245, - - MAX_ADVISORS = 4 -}; - -uint32 m_auiSpellSummonWeapon[]= -{ - SPELL_SUMMON_WEAPONA, SPELL_SUMMON_WEAPONB, SPELL_SUMMON_WEAPONC, SPELL_SUMMON_WEAPOND, - SPELL_SUMMON_WEAPONE, SPELL_SUMMON_WEAPONF, SPELL_SUMMON_WEAPONG -}; - -const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target -const float KAEL_VISIBLE_RANGE = 50.0f; - -const float afGravityPos[3] = {795.0f, 0.0f, 70.0f}; - -#define TIME_PHASE_2_3 120000 -#define TIME_PHASE_3_4 180000 - -//Base AI for Advisors -struct advisorbase_ai : public ScriptedAI -{ - advisorbase_ai(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - m_bDoubled_Health = false; - } - - ScriptedInstance* m_pInstance; - bool FakeDeath; - bool m_bDoubled_Health; - uint32 DelayRes_Timer; - uint64 DelayRes_Target; - - void Reset() - { - if (m_bDoubled_Health) - { - me->SetMaxHealth(me->GetMaxHealth() / 2); - m_bDoubled_Health = false; - } - - FakeDeath = false; - DelayRes_Timer = 0; - DelayRes_Target = 0; - - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - //reset encounter - if (m_pInstance && (m_pInstance->GetData(DATA_KAELTHASEVENT) == 1 || m_pInstance->GetData(DATA_KAELTHASEVENT) == 3)) - if (Creature *Kaelthas = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_KAELTHAS))) - Kaelthas->AI()->EnterEvadeMode(); - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void AttackStart(Unit* who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void Revive(Unit* /*Target*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // double health for phase 3 - me->SetMaxHealth(me->GetMaxHealth() * 2); - m_bDoubled_Health = true; - me->SetHealth(me->GetMaxHealth()); - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoCast(me, SPELL_RES_VISUAL, false); - DelayRes_Timer = 2000; - } - - void DamageTaken(Unit* pKiller, uint32 &damage) - { - if (damage < me->GetHealth()) - return; - - //Prevent glitch if in fake death - if (FakeDeath && m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) - { - damage = 0; - return; - } - - //Don't really die in phase 1 & 3, only die after that - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) - { - //prevent death - damage = 0; - FakeDeath = true; - - me->InterruptNonMeleeSpells(false); - me->SetHealth(0); - me->StopMoving(); - me->ClearComboPointHolders(); - me->RemoveAllAurasOnDeath(); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->ClearAllReactives(); - me->SetUInt64Value(UNIT_FIELD_TARGET,0); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - JustDied(pKiller); - } - } - - void UpdateAI(const uint32 diff) - { - if (DelayRes_Timer) - { - if (DelayRes_Timer <= diff) - { - DelayRes_Timer = 0; - FakeDeath = false; - - Unit* Target = Unit::GetUnit((*me), DelayRes_Target); - if (!Target) - Target = me->getVictim(); - - DoResetThreat(); - AttackStart(Target); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(Target); - me->AddThreat(Target, 0.0f); - } else DelayRes_Timer -= diff; - } - } - -}; - -//Kael'thas AI -struct boss_kaelthasAI : public ScriptedAI -{ - boss_kaelthasAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me) - { - m_pInstance = pCreature->GetInstanceData(); - memset(&m_auiAdvisorGuid, 0, sizeof(m_auiAdvisorGuid)); - } - - ScriptedInstance* m_pInstance; - - uint32 Fireball_Timer; - uint32 ArcaneDisruption_Timer; - uint32 Phoenix_Timer; - uint32 ShockBarrier_Timer; - uint32 GravityLapse_Timer; - uint32 GravityLapse_Phase; - uint32 NetherBeam_Timer; - uint32 NetherVapor_Timer; - uint32 FlameStrike_Timer; - uint32 MindControl_Timer; - uint32 Phase; - uint32 PhaseSubphase; //generic - uint32 Phase_Timer; //generic timer - uint32 PyrosCasted; - - bool InGravityLapse; - bool IsCastingFireball; - bool ChainPyros; - - SummonList summons; - - uint64 m_auiAdvisorGuid[MAX_ADVISORS]; - - void Reset() - { - Fireball_Timer = 5000+rand()%10000; - ArcaneDisruption_Timer = 45000; - MindControl_Timer = 40000; - Phoenix_Timer = 50000; - ShockBarrier_Timer = 60000; - FlameStrike_Timer = 30000; - GravityLapse_Timer = 20000; - GravityLapse_Phase = 0; - NetherBeam_Timer = 8000; - NetherVapor_Timer = 10000; - PyrosCasted = 0; - Phase = 0; - InGravityLapse = false; - IsCastingFireball = false; - ChainPyros = false; - - if (me->isInCombat()) - PrepareAdvisors(); - - summons.DespawnAll(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 0); - } - - void PrepareAdvisors() - { - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Creature *pCreature = Unit::GetCreature((*me), m_auiAdvisorGuid[i])) - { - pCreature->Respawn(); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->setFaction(me->getFaction()); - pCreature->AI()->EnterEvadeMode(); - } - } - } - - void StartEvent() - { - if (!m_pInstance) - return; - - m_auiAdvisorGuid[0] = m_pInstance->GetData64(DATA_THALADREDTHEDARKENER); - m_auiAdvisorGuid[1] = m_pInstance->GetData64(DATA_LORDSANGUINAR); - m_auiAdvisorGuid[2] = m_pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN); - m_auiAdvisorGuid[3] = m_pInstance->GetData64(DATA_MASTERENGINEERTELONICUS); - - if (!m_auiAdvisorGuid[0] || !m_auiAdvisorGuid[1] || !m_auiAdvisorGuid[2] || !m_auiAdvisorGuid[3]) - { - error_log("TSCR: Kael'Thas One or more advisors missing, Skipping Phases 1-3"); - - DoScriptText(SAY_PHASE4_INTRO2, me); - - Phase = 4; - - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - AttackStart(pTarget); - - } - else - { - PrepareAdvisors(); - - DoScriptText(SAY_INTRO, me); - - m_pInstance->SetData(DATA_KAELTHASEVENT, 1); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - PhaseSubphase = 0; - Phase_Timer = 23000; - Phase = 1; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!me->hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() && - me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) - { - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - if (!me->getVictim() && Phase >= 4) - { - who->RemoveAurasDueToSpell(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (me->GetMap()->IsDungeon()) - { - if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); - - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } - } - } - } - - void Aggro(Unit * /*who*/) - { - if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustSummoned(Creature* pSummoned) - { - // if not phoenix, then it's one of the 7 weapons - if (pSummoned->GetEntry() != NPC_PHOENIX) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - - summons.Summon(pSummoned); - } - } - - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - - void JustDied(Unit* /*Killer*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - DoScriptText(SAY_DEATH, me); - - summons.DespawnAll(); - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 0); - - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Unit* pAdvisor = Unit::GetUnit((*me), m_auiAdvisorGuid[i])) - pAdvisor->Kill(pAdvisor); - } - } - - void UpdateAI(const uint32 diff) - { - //Phase 1 - switch (Phase) - { - case 1: - { - Unit *pTarget = NULL; - Creature* Advisor = NULL; - - //Subphase switch - switch(PhaseSubphase) - { - //Subphase 1 - Start - case 0: - if (Phase_Timer <= diff) - { - DoScriptText(SAY_INTRO_THALADRED, me); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 1 - Unlock advisor - case 1: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 2 - Start - case 2: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_SANGUINAR, me); - - //start advisor within 12.5 seconds - Phase_Timer = 12500; - ++PhaseSubphase; - } - break; - - //Subphase 2 - Unlock advisor - case 3: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 3 - Start - case 4: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_CAPERNIAN, me); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } - break; - - //Subphase 3 - Unlock advisor - case 5: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 4 - Start - case 6: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_TELONICUS, me); - - //start advisor within 8.4 seconds - Phase_Timer = 8400; - ++PhaseSubphase; - } - break; - - //Subphase 4 - Unlock advisor - case 7: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - Phase_Timer = 3000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //End of phase 1 - case 8: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Phase = 2; - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 2); - - DoScriptText(SAY_PHASE2_WEAPON, me); - - PhaseSubphase = 0; - Phase_Timer = 3500; - DoCast(me, SPELL_SUMMON_WEAPONS); - } - break; - } - } - break; - - case 2: - { - if (PhaseSubphase == 0) - { - if (Phase_Timer <= diff) - { - PhaseSubphase = 1; - } else Phase_Timer -= diff; - } - - //Spawn weapons - if (PhaseSubphase == 1) - { - DoCast(me, SPELL_SUMMON_WEAPONS, false); - - uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32); - - for (uint32 i = 0; i < uiMaxWeapon; ++i) - DoCast(me, m_auiSpellSummonWeapon[i], true); - - PhaseSubphase = 2; - Phase_Timer = TIME_PHASE_2_3; - } - - if (PhaseSubphase == 2) - { - if (Phase_Timer <= diff) - { - DoScriptText(SAY_PHASE3_ADVANCE, me); - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 3); - Phase = 3; - PhaseSubphase = 0; - } else Phase_Timer -= diff; - } - } - break; - - case 3: - { - if (PhaseSubphase == 0) - { - //Respawn advisors - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - Creature *Advisor; - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - Advisor = Unit::GetCreature((*me), m_auiAdvisorGuid[i]); - - if (!Advisor) - error_log("SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); - else - CAST_AI(advisorbase_ai, Advisor->AI())->Revive(pTarget); - } - - PhaseSubphase = 1; - Phase_Timer = TIME_PHASE_3_4; - } - - if (Phase_Timer <= diff) - { - DoScriptText(SAY_PHASE4_INTRO2, me); - Phase = 4; - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - - // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. - DoResetThreat(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - AttackStart(pTarget); - - Phase_Timer = 30000; - } else Phase_Timer -= diff; - } - break; - - case 4: - case 5: - case 6: - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fireball_Timer - if (!InGravityLapse && !ChainPyros && Phase != 5) - { - if (Fireball_Timer <= diff) - { - if (!IsCastingFireball) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - //interruptable - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); - int32 dmg = 20000+rand()%5000; - me->CastCustomSpell(me->getVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); - IsCastingFireball = true; - Fireball_Timer = 2500; - } - } - else - { - //apply resistance - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); - IsCastingFireball = false; - Fireball_Timer = 5000+rand()%10000; - } - } else Fireball_Timer -= diff; - - //ArcaneDisruption_Timer - if (ArcaneDisruption_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_DISRUPTION, true); - ArcaneDisruption_Timer = 60000; - } else ArcaneDisruption_Timer -= diff; - - if (FlameStrike_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_FLAME_STRIKE); - - FlameStrike_Timer = 30000; - } else FlameStrike_Timer -= diff; - - if (MindControl_Timer <= diff) - { - if (me->getThreatManager().getThreatList().size() >= 2) - for (uint32 i = 0; i < 3; ++i) - { - debug_log("SD2: Kael'Thas mind control not supported."); - //DoCast(pUnit, SPELL_MIND_CONTROL); - } - - MindControl_Timer = 60000; - } else MindControl_Timer -= diff; - } - - //Phoenix_Timer - if (Phoenix_Timer <= diff) - { - DoCast(me, SPELL_PHOENIX_ANIMATION); - DoScriptText(RAND(SAY_SUMMON_PHOENIX1,SAY_SUMMON_PHOENIX2), me); - - Phoenix_Timer = 60000; - } else Phoenix_Timer -= diff; - - //Phase 4 specific spells - if (Phase == 4) - { - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - Phase = 5; - Phase_Timer = 10000; - - DoScriptText(SAY_PHASE5_NUTS, me); - - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, 0, 0); - - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_FULLPOWER); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ChainPyros = true; - PyrosCasted = 0; - ShockBarrier_Timer = 60000; - } else ShockBarrier_Timer -= diff; - - //Chain Pyros (3 of them max) - if (ChainPyros && !me->IsNonMeleeSpellCasted(false)) - { - if (PyrosCasted < 3) - { - DoCast(me->getVictim(), SPELL_PYROBLAST); - ++PyrosCasted; - } - else - { - ChainPyros = false; - Fireball_Timer = 2500; - ArcaneDisruption_Timer = 60000; - } - } - } - - if (Phase == 5) - { - if (Phase_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - me->RemoveAurasDueToSpell(SPELL_FULLPOWER); - - DoCast(me, SPELL_EXPLODE); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Phase = 6; - AttackStart(me->getVictim()); - } else Phase_Timer -= diff; - } - - //Phase 5 - if (Phase == 6) - { - - //GravityLapse_Timer - if (GravityLapse_Timer <= diff) - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - switch (GravityLapse_Phase) - { - case 0: - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, MOVEMENTFLAG_NONE, 0); - - // 1) Kael'thas will portal the whole raid right into his body - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - //Use work around packet to prevent player from being dropped from combat - DoTeleportPlayer(pUnit, afGravityPos[0], afGravityPos[1], afGravityPos[2], pUnit->GetOrientation()); - } - } - - GravityLapse_Timer = 500; - ++GravityLapse_Phase; - InGravityLapse = true; - ShockBarrier_Timer = 1000; - NetherBeam_Timer = 5000; - break; - - case 1: - DoScriptText(RAND(SAY_GRAVITYLAPSE1,SAY_GRAVITYLAPSE2), me); - - // 2) At that point he will put a Gravity Lapse debuff on everyone - for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) - { - if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) - { - DoCast(pUnit, SPELL_KNOCKBACK, true); - //Gravity lapse - needs an exception in Spell system to work - - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); - - //Using packet workaround - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - GravityLapse_Timer = 10000; - ++GravityLapse_Phase; - break; - - case 2: - //Cast nether vapor aura on self - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_NETHER_VAPOR); - - GravityLapse_Timer = 20000; - ++GravityLapse_Phase; - break; - - case 3: - //Remove flight - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) - { - //Using packet workaround - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - - me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); - InGravityLapse = false; - GravityLapse_Timer = 60000; - GravityLapse_Phase = 0; - AttackStart(me->getVictim()); - break; - } - } else GravityLapse_Timer -= diff; - - if (InGravityLapse) - { - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ShockBarrier_Timer = 20000; - } else ShockBarrier_Timer -= diff; - - //NetherBeam_Timer - if (NetherBeam_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_NETHER_BEAM); - - NetherBeam_Timer = 4000; - } else NetherBeam_Timer -= diff; - } - } - - if (!InGravityLapse) - DoMeleeAttackIfReady(); - } - } - } -}; - -//Thaladred the Darkener AI -struct boss_thaladred_the_darkenerAI : public advisorbase_ai -{ - boss_thaladred_the_darkenerAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Gaze_Timer; - uint32 Silence_Timer; - uint32 PsychicBlow_Timer; - - void Reset() - { - Gaze_Timer = 100; - Silence_Timer = 20000; - PsychicBlow_Timer = 10000; - - advisorbase_ai::Reset(); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_THALADRED_AGGRO, me); - me->AddThreat(who, 5000000.0f); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_THALADRED_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Gaze_Timer - if (Gaze_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoResetThreat(); - me->AddThreat(pTarget, 5000000.0f); - DoScriptText(EMOTE_THALADRED_GAZE, me, pTarget); - Gaze_Timer = 8500; - } - } else Gaze_Timer -= diff; - - //Silence_Timer - if (Silence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - Silence_Timer = 20000; - } else Silence_Timer -= diff; - - //PsychicBlow_Timer - if (PsychicBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PSYCHIC_BLOW); - PsychicBlow_Timer = 20000+rand()%5000; - } else PsychicBlow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Lord Sanguinar AI -struct boss_lord_sanguinarAI : public advisorbase_ai -{ - boss_lord_sanguinarAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Fear_Timer; - - void Reset() - { - Fear_Timer = 20000; - advisorbase_ai::Reset(); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_SANGUINAR_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_SANGUINAR_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); - Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds - } else Fear_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Grand Astromancer Capernian AI -struct boss_grand_astromancer_capernianAI : public advisorbase_ai -{ - boss_grand_astromancer_capernianAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Fireball_Timer; - uint32 Conflagration_Timer; - uint32 ArcaneExplosion_Timer; - uint32 Yell_Timer; - bool Yell; - - void Reset() - { - Fireball_Timer = 2000; - Conflagration_Timer = 20000; - ArcaneExplosion_Timer = 5000; - Yell_Timer = 2000; - Yell = false; - - advisorbase_ai::Reset(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_CAPERNIAN_DEATH, me); - } - - void AttackStart(Unit* who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(who, CAPERNIAN_DISTANCE); - } - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking Death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Yell_Timer - if (!Yell) - { - if (Yell_Timer <= diff) - { - DoScriptText(SAY_CAPERNIAN_AGGRO, me); - Yell = true; - } else Yell_Timer -= diff; - } - - //Fireball_Timer - if (Fireball_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CAPERNIAN_FIREBALL); - Fireball_Timer = 4000; - } else Fireball_Timer -= diff; - - //Conflagration_Timer - if (Conflagration_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget && me->IsWithinDistInMap(pTarget, 30)) - DoCast(pTarget, SPELL_CONFLAGRATION); - else - DoCast(me->getVictim(), SPELL_CONFLAGRATION); - - Conflagration_Timer = 10000+rand()%5000; - } else Conflagration_Timer -= diff; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - bool InMeleeRange = false; - Unit *pTarget = NULL; - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - //if in melee range - if (pUnit && pUnit->IsWithinDistInMap(me, 5)) - { - InMeleeRange = true; - pTarget = pUnit; - break; - } - } - - if (InMeleeRange) - DoCast(pTarget, SPELL_ARCANE_EXPLOSION); - - ArcaneExplosion_Timer = 4000+rand()%2000; - } else ArcaneExplosion_Timer -= diff; - - //Do NOT deal any melee damage. - } -}; - -//Master Engineer Telonicus AI -struct boss_master_engineer_telonicusAI : public advisorbase_ai -{ - boss_master_engineer_telonicusAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Bomb_Timer; - uint32 RemoteToy_Timer; - - void Reset() - { - Bomb_Timer = 10000; - RemoteToy_Timer = 5000; - - advisorbase_ai::Reset(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_TELONICUS_DEATH, me); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_TELONICUS_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking Death, do nothing - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Bomb_Timer - if (Bomb_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BOMB); - Bomb_Timer = 25000; - } else Bomb_Timer -= diff; - - //RemoteToy_Timer - if (RemoteToy_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_REMOTE_TOY); - - RemoteToy_Timer = 10000+rand()%5000; - } else RemoteToy_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Flame Strike AI -struct mob_kael_flamestrikeAI : public Scripted_NoMovementAI -{ - mob_kael_flamestrikeAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) {} - - uint32 Timer; - bool Casting; - bool KillSelf; - - void Reset() - { - Timer = 5000; - Casting = false; - KillSelf = false; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - } - - void MoveInLineOfSight(Unit * /*who*/) {} - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!Casting) - { - DoCast(me, SPELL_FLAME_STRIKE_VIS); - Casting = true; - } - - //Timer - if (Timer <= diff) - { - if (!KillSelf) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_FLAME_STRIKE_DMG); - } else me->Kill(me); - - KillSelf = true; - Timer = 1000; - } else Timer -= diff; - } -}; - -//Phoenix AI -struct mob_phoenix_tkAI : public ScriptedAI -{ - mob_phoenix_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 Cycle_Timer; - - void Reset() - { - Cycle_Timer = 2000; - DoCast(me, SPELL_BURN, true); - } - - void JustDied(Unit* /*killer*/) - { - //is this spell in use anylonger? - //DoCast(me, SPELL_EMBER_BLAST, true); - me->SummonCreature(NPC_PHOENIX_EGG,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,16000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Cycle_Timer <= diff) - { - //spell Burn should possible do this, but it doesn't, so do this for now. - uint32 dmg = urand(4500,5500); - if (me->GetHealth() > dmg) - me->SetHealth(uint32(me->GetHealth()-dmg)); - Cycle_Timer = 2000; - } else Cycle_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Phoenix Egg AI -struct mob_phoenix_egg_tkAI : public ScriptedAI -{ - mob_phoenix_egg_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 Rebirth_Timer; - - void Reset() - { - Rebirth_Timer = 15000; - } - - //ignore any - void MoveInLineOfSight(Unit* /*who*/) {} - - void AttackStart(Unit* who) - { - if (me->Attack(who, false)) - { - me->SetInCombatWith(who); - who->SetInCombatWith(me); - - DoStartNoMovement(who); - } - } - - void JustSummoned(Creature* summoned) - { - summoned->AddThreat(me->getVictim(), 0.0f); - summoned->CastSpell(summoned,SPELL_REBIRTH,false); - } - - void UpdateAI(const uint32 diff) - { - if (!Rebirth_Timer) - return; - - if (Rebirth_Timer <= diff) - { - me->SummonCreature(NPC_PHOENIX,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,5000); - Rebirth_Timer = 0; - } else Rebirth_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_kaelthas(Creature* pCreature) -{ - return new boss_kaelthasAI(pCreature); -} - -CreatureAI* GetAI_boss_thaladred_the_darkener(Creature* pCreature) -{ - return new boss_thaladred_the_darkenerAI(pCreature); -} - -CreatureAI* GetAI_boss_lord_sanguinar(Creature* pCreature) -{ - return new boss_lord_sanguinarAI(pCreature); -} - -CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature* pCreature) -{ - return new boss_grand_astromancer_capernianAI(pCreature); -} - -CreatureAI* GetAI_boss_master_engineer_telonicus(Creature* pCreature) -{ - return new boss_master_engineer_telonicusAI(pCreature); -} - -CreatureAI* GetAI_mob_kael_flamestrike(Creature* pCreature) -{ - return new mob_kael_flamestrikeAI(pCreature); -} - -CreatureAI* GetAI_mob_phoenix_tk(Creature* pCreature) -{ - return new mob_phoenix_tkAI(pCreature); -} - -CreatureAI* GetAI_mob_phoenix_egg_tk(Creature* pCreature) -{ - return new mob_phoenix_egg_tkAI(pCreature); -} - -void AddSC_boss_kaelthas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kaelthas"; - newscript->GetAI = &GetAI_boss_kaelthas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_thaladred_the_darkener"; - newscript->GetAI = &GetAI_boss_thaladred_the_darkener; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_sanguinar"; - newscript->GetAI = &GetAI_boss_lord_sanguinar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_grand_astromancer_capernian"; - newscript->GetAI = &GetAI_boss_grand_astromancer_capernian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_master_engineer_telonicus"; - newscript->GetAI = &GetAI_boss_master_engineer_telonicus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_kael_flamestrike"; - newscript->GetAI = &GetAI_mob_kael_flamestrike; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phoenix_tk"; - newscript->GetAI = &GetAI_mob_phoenix_tk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phoenix_egg_tk"; - newscript->GetAI = &GetAI_mob_phoenix_egg_tk; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp deleted file mode 100644 index e1b60b20948..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_eye/boss_void_reaver.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Void_Reaver -SD%Complete: 90 -SDComment: Should reset if raid are out of room. -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -enum eEnums -{ - SAY_AGGRO = -1550000, - SAY_SLAY1 = -1550001, - SAY_SLAY2 = -1550002, - SAY_SLAY3 = -1550003, - SAY_DEATH = -1550004, - SAY_POUNDING1 = -1550005, - SAY_POUNDING2 = -1550006, - - SPELL_POUNDING = 34162, - SPELL_ARCANE_ORB = 34172, - SPELL_KNOCK_AWAY = 25778, - SPELL_BERSERK = 27680 -}; - -struct boss_void_reaverAI : public ScriptedAI -{ - boss_void_reaverAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Pounding_Timer; - uint32 ArcaneOrb_Timer; - uint32 KnockAway_Timer; - uint32 Berserk_Timer; - - bool Enraged; - - void Reset() - { - Pounding_Timer = 15000; - ArcaneOrb_Timer = 3000; - KnockAway_Timer = 30000; - Berserk_Timer = 600000; - - Enraged = false; - - if (pInstance && me->isAlive()) - pInstance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_VOIDREAVEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Pounding - if (Pounding_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POUNDING); - - DoScriptText(RAND(SAY_POUNDING1,SAY_POUNDING2), me); - Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000) - } else Pounding_Timer -= diff; - - // Arcane Orb - if (ArcaneOrb_Timer <= diff) - { - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (!pTarget) - continue; - - // exclude pets & totems - if (pTarget->GetTypeId() != TYPEID_PLAYER) - continue; - - //18 yard radius minimum - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive() && !pTarget->IsWithinDist(me, 18, false)) - target_list.push_back(pTarget); - pTarget = NULL; - } - - if (target_list.size()) - pTarget = *(target_list.begin()+rand()%target_list.size()); - else - pTarget = me->getVictim(); - - if (pTarget) - me->CastSpell(pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(), SPELL_ARCANE_ORB, false, NULL, NULL, NULL, pTarget); - - ArcaneOrb_Timer = 3000; - } else ArcaneOrb_Timer -= diff; - - // Single Target knock back, reduces aggro - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCK_AWAY); - - //Drop 25% aggro - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-25); - - KnockAway_Timer = 30000; - } else KnockAway_Timer -= diff; - - //Berserk - if (Berserk_Timer < diff && !Enraged) - { - DoCast(me, SPELL_BERSERK); - Enraged = true; - } else Berserk_Timer -= diff; - - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_void_reaver(Creature* pCreature) -{ - return new boss_void_reaverAI (pCreature); -} - -void AddSC_boss_void_reaver() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_void_reaver"; - newscript->GetAI = &GetAI_boss_void_reaver; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp deleted file mode 100644 index 59c72071238..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_eye/instance_the_eye.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_The_Eye -SD%Complete: 100 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define MAX_ENCOUNTER 5 - -/* The Eye encounters: -0 - Kael'thas event -1 - Al' ar event -2 - Solarian Event -3 - Void Reaver event -*/ - -struct instance_the_eye : public ScriptedInstance -{ - instance_the_eye(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 ThaladredTheDarkener; - uint64 LordSanguinar; - uint64 GrandAstromancerCapernian; - uint64 MasterEngineerTelonicus; - uint64 Kaelthas; - uint64 Astromancer; - uint64 Alar; - - uint8 KaelthasEventPhase; - uint8 AlarEventPhase; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - ThaladredTheDarkener = 0; - LordSanguinar = 0; - GrandAstromancerCapernian = 0; - MasterEngineerTelonicus = 0; - Kaelthas = 0; - Astromancer = 0; - Alar = 0; - - KaelthasEventPhase = 0; - AlarEventPhase = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 20064: ThaladredTheDarkener = pCreature->GetGUID(); break; - case 20063: MasterEngineerTelonicus = pCreature->GetGUID(); break; - case 20062: GrandAstromancerCapernian = pCreature->GetGUID(); break; - case 20060: LordSanguinar = pCreature->GetGUID(); break; - case 19622: Kaelthas = pCreature->GetGUID(); break; - case 18805: Astromancer = pCreature->GetGUID(); break; - case 19514: Alar = pCreature->GetGUID(); break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_THALADREDTHEDARKENER: return ThaladredTheDarkener; - case DATA_LORDSANGUINAR: return LordSanguinar; - case DATA_GRANDASTROMANCERCAPERNIAN: return GrandAstromancerCapernian; - case DATA_MASTERENGINEERTELONICUS: return MasterEngineerTelonicus; - case DATA_KAELTHAS: return Kaelthas; - case DATA_ASTROMANCER: return Astromancer; - case DATA_ALAR: return Alar; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_ALAREVENT: AlarEventPhase = data; m_auiEncounter[0] = data; break; - case DATA_HIGHASTROMANCERSOLARIANEVENT: m_auiEncounter[1] = data; break; - case DATA_VOIDREAVEREVENT: m_auiEncounter[2] = data; break; - case DATA_KAELTHASEVENT: KaelthasEventPhase = data; m_auiEncounter[3] = data; break; - } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_ALAREVENT: return AlarEventPhase; - case DATA_HIGHASTROMANCERSOLARIANEVENT: return m_auiEncounter[1]; - case DATA_VOIDREAVEREVENT: return m_auiEncounter[2]; - case DATA_KAELTHASEVENT: return KaelthasEventPhase; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_the_eye(Map* pMap) -{ - return new instance_the_eye(pMap); -} - -void AddSC_instance_the_eye() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_the_eye"; - newscript->GetInstanceData = &GetInstanceData_instance_the_eye; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp b/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp deleted file mode 100644 index 97021fdc031..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: The_Eye -SD%Complete: 100 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -/* ContentData -mob_crystalcore_devastator -EndContentData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define SPELL_COUNTERCHARGE 35035 -#define SPELL_KNOCKAWAY 22893 - -struct mob_crystalcore_devastatorAI : public ScriptedAI -{ - mob_crystalcore_devastatorAI(Creature *c) : ScriptedAI(c) {} - - uint32 Knockaway_Timer; - uint32 Countercharge_Timer; - - void Reset() - { - Countercharge_Timer = 9000; - Knockaway_Timer = 25000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Check if we have a current target - //Knockaway_Timer - if (Knockaway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); - - // current aggro target is knocked away pick new target - Unit* pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - - if (!pTarget || pTarget == me->getVictim()) - pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); - - if (pTarget) - me->TauntApply(pTarget); - - Knockaway_Timer = 23000; - } else Knockaway_Timer -= diff; - - //Countercharge_Timer - if (Countercharge_Timer <= diff) - { - DoCast(me, SPELL_COUNTERCHARGE); - Countercharge_Timer = 45000; - } else Countercharge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_crystalcore_devastator(Creature* pCreature) -{ - return new mob_crystalcore_devastatorAI (pCreature); -} - -void AddSC_the_eye() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_crystalcore_devastator"; - newscript->GetAI = &GetAI_mob_crystalcore_devastator; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h b/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h deleted file mode 100644 index d0d3ea09061..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_eye/the_eye.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_THE_EYE_H -#define DEF_THE_EYE_H - -#define DATA_ALAREVENT 1 -#define DATA_ASTROMANCER 2 -#define DATA_GRANDASTROMANCERCAPERNIAN 3 -#define DATA_HIGHASTROMANCERSOLARIANEVENT 4 -#define DATA_KAELTHAS 5 -#define DATA_KAELTHASEVENT 6 -#define DATA_LORDSANGUINAR 7 -#define DATA_MASTERENGINEERTELONICUS 8 -#define DATA_THALADREDTHEDARKENER 10 -#define DATA_VOIDREAVEREVENT 11 -#define DATA_ALAR 12 -#endif - diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp deleted file mode 100644 index b9c365eda65..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gatewatcher_Gyrokill -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -//not used -#define SAY_AGGRO -1554000 -#define SAY_SAW_ATTACK1 -1554001 -#define SAY_SAW_ATTACK2 -1554002 -#define SAY_SLAY1 -1554003 -#define SAY_SLAY2 -1554004 -#define SAY_DEATH -1554005 - -#define SPELL_STREAM_OF_MACHINE_FLUID 35311 -#define SPELL_SAW_BLADE 35318 -#define H_SPELL_SAW_BLADE 39192 -#define SPELL_SHADOW_POWER 35322 -#define H_SPELL_SHADOW_POWER 39193 - diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp deleted file mode 100644 index 50c3a6171ce..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Gatewatcher_Ironhand -SD%Complete: 75 -SDComment: -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1554006 -#define SAY_HAMMER_1 -1554007 -#define SAY_HAMMER_2 -1554008 -#define SAY_SLAY_1 -1554009 -#define SAY_SLAY_2 -1554010 -#define SAY_DEATH_1 -1554011 -#define EMOTE_HAMMER -1554012 - -// Spells to be casted -#define SPELL_SHADOW_POWER 35322 -#define H_SPELL_SHADOW_POWER 39193 -#define SPELL_HAMMER_PUNCH 35326 -#define SPELL_JACKHAMMER 35327 -#define H_SPELL_JACKHAMMER 39194 -#define SPELL_STREAM_OF_MACHINE_FLUID 35311 - -// Gatewatcher Iron-Hand AI -struct boss_gatewatcher_iron_handAI : public ScriptedAI -{ - boss_gatewatcher_iron_handAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Shadow_Power_Timer; - uint32 Jackhammer_Timer; - uint32 Stream_of_Machine_Fluid_Timer; - - void Reset() - { - Shadow_Power_Timer = 25000; - Jackhammer_Timer = 45000; - Stream_of_Machine_Fluid_Timer = 55000; - - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO_1, me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH_1, me); - //TODO: Add door check/open code - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Shadow Power - if (Shadow_Power_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_POWER); - Shadow_Power_Timer = 20000 + rand()%8000; - } else Shadow_Power_Timer -= diff; - - //Jack Hammer - if (Jackhammer_Timer <= diff) - { - //TODO: expect cast this about 5 times in a row (?), announce it by emote only once - DoScriptText(EMOTE_HAMMER, me); - DoCast(me->getVictim(), SPELL_JACKHAMMER); - - //chance to yell, but not same time as emote (after spell in fact casted) - if (rand()%2) - return; - - DoScriptText(RAND(SAY_HAMMER_1,SAY_HAMMER_2), me); - Jackhammer_Timer = 30000; - } else Jackhammer_Timer -= diff; - - //Stream of Machine Fluid - if (Stream_of_Machine_Fluid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STREAM_OF_MACHINE_FLUID); - Stream_of_Machine_Fluid_Timer = 35000 + rand()%15000; - } else Stream_of_Machine_Fluid_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gatewatcher_iron_hand(Creature* pCreature) -{ - return new boss_gatewatcher_iron_handAI (pCreature); -} - -void AddSC_boss_gatewatcher_iron_hand() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gatewatcher_iron_hand"; - newscript->GetAI = &GetAI_boss_gatewatcher_iron_hand; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp deleted file mode 100644 index ededec0196d..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Nethermancer_Sepethrea -SD%Complete: 90 -SDComment: Need adjustments to initial summons -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" -#include "mechanar.h" - -#define SAY_AGGRO -1554013 -#define SAY_SUMMON -1554014 -#define SAY_DRAGONS_BREATH_1 -1554015 -#define SAY_DRAGONS_BREATH_2 -1554016 -#define SAY_SLAY1 -1554017 -#define SAY_SLAY2 -1554018 -#define SAY_DEATH -1554019 - -#define SPELL_SUMMON_RAGIN_FLAMES 35275 -#define H_SPELL_SUMMON_RAGIN_FLAMES 39084 - -#define SPELL_FROST_ATTACK 35263 -#define SPELL_ARCANE_BLAST 35314 -#define SPELL_DRAGONS_BREATH 35250 -#define SPELL_KNOCKBACK 37317 -#define SPELL_SOLARBURN 35267 - -struct boss_nethermancer_sepethreaAI : public ScriptedAI -{ - boss_nethermancer_sepethreaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 frost_attack_Timer; - uint32 arcane_blast_Timer; - uint32 dragons_breath_Timer; - uint32 knockback_Timer; - uint32 solarburn_Timer; - - void Reset() - { - frost_attack_Timer = 7000 + rand()%3000; - arcane_blast_Timer = 12000 + rand()%6000; - dragons_breath_Timer = 18000 + rand()%4000; - knockback_Timer = 22000 + rand()%6000; - solarburn_Timer = 30000; - - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, IN_PROGRESS); - - DoScriptText(SAY_AGGRO, me); - DoCast(who, SPELL_SUMMON_RAGIN_FLAMES); - DoScriptText(SAY_SUMMON, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frost Attack - if (frost_attack_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_ATTACK); - frost_attack_Timer = 7000 + rand()%3000; - } else frost_attack_Timer -= diff; - - //Arcane Blast - if (arcane_blast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BLAST); - arcane_blast_Timer = 15000; - } else arcane_blast_Timer -= diff; - - //Dragons Breath - if (dragons_breath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DRAGONS_BREATH); - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_DRAGONS_BREATH_1,SAY_DRAGONS_BREATH_2), me); - } - dragons_breath_Timer = 12000 + rand()%10000; - } else dragons_breath_Timer -= diff; - - //Knockback - if (knockback_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKBACK); - knockback_Timer = 15000 + rand()%10000; - } else knockback_Timer -= diff; - - //Solarburn - if (solarburn_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARBURN); - solarburn_Timer = 30000; - } else solarburn_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_nethermancer_sepethrea(Creature* pCreature) -{ - return new boss_nethermancer_sepethreaAI (pCreature); -} - -#define SPELL_INFERNO 35268 -#define H_SPELL_INFERNO 39346 -#define SPELL_FIRE_TAIL 35278 - -struct mob_ragin_flamesAI : public ScriptedAI -{ - mob_ragin_flamesAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 inferno_Timer; - uint32 flame_timer; - uint32 Check_Timer; - - bool onlyonce; - - void Reset() - { - inferno_Timer = 10000; - flame_timer = 500; - Check_Timer = 2000; - onlyonce = false; - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); - } - - void EnterCombat(Unit* /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Check_Timer - if (Check_Timer <= diff) - { - if (pInstance) - { - if (pInstance->GetData(DATA_NETHERMANCER_EVENT) != IN_PROGRESS) - { - //remove - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } - } - Check_Timer = 1000; - } else Check_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (!onlyonce) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - me->GetMotionMaster()->MoveChase(pTarget); - onlyonce = true; - } - - if (inferno_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_INFERNO); - me->TauntApply(me->getVictim()); - inferno_Timer = 10000; - } else inferno_Timer -= diff; - - if (flame_timer <= diff) - { - DoCast(me, SPELL_FIRE_TAIL); - flame_timer = 500; - } else flame_timer -=diff; - - DoMeleeAttackIfReady(); - } - -}; -CreatureAI* GetAI_mob_ragin_flames(Creature* pCreature) -{ - return new mob_ragin_flamesAI (pCreature); -} -void AddSC_boss_nethermancer_sepethrea() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nethermancer_sepethrea"; - newscript->GetAI = &GetAI_boss_nethermancer_sepethrea; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ragin_flames"; - newscript->GetAI = &GetAI_mob_ragin_flames; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp deleted file mode 100644 index c0c06704db7..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss Pathaleon the Calculator -SD%Complete: 50 -SDComment: Event missing. Script for himself 99% blizzlike. -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1554020 -#define SAY_DOMINATION_1 -1554021 -#define SAY_DOMINATION_2 -1554022 -#define SAY_SUMMON -1554023 -#define SAY_ENRAGE -1554024 -#define SAY_SLAY_1 -1554025 -#define SAY_SLAY_2 -1554026 -#define SAY_DEATH -1554027 - -// Spells to be casted -#define SPELL_MANA_TAP 36021 -#define SPELL_ARCANE_TORRENT 36022 -#define SPELL_DOMINATION 35280 -#define H_SPELL_ARCANE_EXPLOSION 15453 -#define SPELL_FRENZY 36992 - -#define SPELL_SUMMON_NETHER_WRAITH_1 35285 //Spells work, but not implemented -#define SPELL_SUMMON_NETHER_WRAITH_2 35286 -#define SPELL_SUMMON_NETHER_WRAITH_3 35287 -#define SPELL_SUMMON_NETHER_WRAITH_4 35288 - -// Add Spells -#define SPELL_DETONATION 35058 -#define SPELL_ARCANE_MISSILES 35034 - -struct boss_pathaleon_the_calculatorAI : public ScriptedAI -{ - boss_pathaleon_the_calculatorAI(Creature *c) : ScriptedAI(c), summons(me) - { - } - - uint32 Summon_Timer; - SummonList summons; - uint32 ManaTap_Timer; - uint32 ArcaneTorrent_Timer; - uint32 Domination_Timer; - uint32 ArcaneExplosion_Timer; - - bool Enraged; - - uint32 Counter; - - void Reset() - { - Summon_Timer = 30000; - ManaTap_Timer = 12000 + rand()%8000; - ArcaneTorrent_Timer = 16000 + rand()%9000; - Domination_Timer = 25000 + rand()%15000; - ArcaneExplosion_Timer = 8000 + rand()%5000; - - Enraged = false; - - Counter = 0; - summons.DespawnAll(); - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - summons.DespawnAll(); - } - - void JustSummoned(Creature *summon) {summons.Summon(summon);} - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Summon_Timer <= diff) - { - for (uint8 i = 0; i < 3; ++i) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - Creature* Wraith = me->SummonCreature(21062,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - if (pTarget && Wraith) - Wraith->AI()->AttackStart(pTarget); - } - DoScriptText(SAY_SUMMON, me); - Summon_Timer = 30000 + rand()%15000; - } else Summon_Timer -= diff; - - if (ManaTap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MANA_TAP); - ManaTap_Timer = 14000 + rand()%8000; - } else ManaTap_Timer -= diff; - - if (ArcaneTorrent_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_TORRENT); - ArcaneTorrent_Timer = 12000 + rand()%6000; - } else ArcaneTorrent_Timer -= diff; - - if (Domination_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - DoScriptText(RAND(SAY_DOMINATION_1,SAY_DOMINATION_2), me); - - DoCast(pTarget, SPELL_DOMINATION); - } - Domination_Timer = 25000 + rand()%5000; - } else Domination_Timer -= diff; - - //Only casting if Heroic Mode is used - if (IsHeroic()) - { - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), H_SPELL_ARCANE_EXPLOSION); - ArcaneExplosion_Timer = 10000 + rand()%4000; - } else ArcaneExplosion_Timer -= diff; - } - - if (!Enraged && me->GetHealth()*100 / me->GetMaxHealth() < 21) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(SAY_ENRAGE, me); - Enraged = true; - - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_pathaleon_the_calculator(Creature* pCreature) -{ - return new boss_pathaleon_the_calculatorAI (pCreature); -} - -struct mob_nether_wraithAI : public ScriptedAI -{ - mob_nether_wraithAI(Creature *c) : ScriptedAI(c) {} - - uint32 ArcaneMissiles_Timer; - uint32 Detonation_Timer; - uint32 Die_Timer; - bool Detonation; - - void Reset() - { - ArcaneMissiles_Timer = 1000 + rand()%3000; - Detonation_Timer = 20000; - Die_Timer = 2200; - Detonation = false; - - } - - void EnterCombat(Unit* /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ArcaneMissiles_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_ARCANE_MISSILES); - else - DoCast(me->getVictim(), SPELL_ARCANE_MISSILES); - - ArcaneMissiles_Timer = 5000 + rand()%5000; - } else ArcaneMissiles_Timer -=diff; - - if (!Detonation) - { - if (Detonation_Timer <= diff) - { - DoCast(me, SPELL_DETONATION); - Detonation = true; - } else Detonation_Timer -= diff; - } - - if (Detonation) - { - if (Die_Timer <= diff) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } else Die_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - -}; -CreatureAI* GetAI_mob_nether_wraith(Creature* pCreature) -{ - return new mob_nether_wraithAI (pCreature); -} - -void AddSC_boss_pathaleon_the_calculator() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_pathaleon_the_calculator"; - newscript->GetAI = &GetAI_boss_pathaleon_the_calculator; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_nether_wraith"; - newscript->GetAI = &GetAI_mob_nether_wraith; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp b/src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp deleted file mode 100644 index c70da24ea3f..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_mechanar/instance_mechanar.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Mechanar -SD%Complete: 100 -SDComment: -SDCategory: Mechanar -EndScriptData */ - -#include "ScriptedPch.h" -#include "mechanar.h" - -#define MAX_ENCOUNTER 1 - -struct instance_mechanar : public ScriptedInstance -{ - instance_mechanar(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_NETHERMANCER_EVENT: return m_auiEncounter[0]; - } - - return false; - } - - uint64 GetData64 (uint32 /*identifier*/) - { - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_NETHERMANCER_EVENT: m_auiEncounter[0] = data; break; - } - } -}; - -InstanceData* GetInstanceData_instance_mechanar(Map* pMap) -{ - return new instance_mechanar(pMap); -} - -void AddSC_instance_mechanar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_mechanar"; - newscript->GetInstanceData = &GetInstanceData_instance_mechanar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h b/src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h deleted file mode 100644 index d1b53eebf53..00000000000 --- a/src/server/scripts/Outland/tempest_keep/the_mechanar/mechanar.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DEF_MECHANAR_H -#define DEF_MECHANAR_H - -#define DATA_NETHERMANCER_EVENT 1 -#endif - -- cgit v1.2.3